<?php

error_reporting(-1);

if (function_exists('ini_set')) {
    @ini_set('display_errors', 1);
    @ini_set('display_startup_errors', 1);
    @ini_set('opcache.enable_cli', '0');

    if (isset($_GET['opcache_reset']) && $_GET['opcache_reset'] === md5(__FILE__)) {
        $GLOBALS['opcacheEnabled'] = @ini_get('opcache.enable');
    } else {
        $GLOBALS['opcacheEnabled'] = @ini_set('opcache.enable', '0');
    }
}

if (PHP_VERSION_ID < 50509) {
    die('You are using PHP '.PHP_VERSION." but you need least PHP 5.5.9 to run the Contao Manager.\n");
}

if (!extension_loaded('Phar')) {
    echo 'PHP\'s phar extension is missing. Contao Manager requires it to run. Enable the extension or recompile php without --disable-phar then try again.' . PHP_EOL;
    exit(1);
}

if (('cli' === PHP_SAPI || !isset($_SERVER['REQUEST_URI'])) && isset($_SERVER['argv'][1]) && 'test' === $_SERVER['argv'][1]) {
    die(json_encode(['version' => PHP_VERSION, 'version_id' => PHP_VERSION_ID, 'sapi' => PHP_SAPI]));
}

if (PHP_VERSION_ID < 80100) {
    Phar::mapPhar('contao-manager.phar');
    @include 'phar://contao-manager.phar/downgrade.php';
    die('<script>setTimeout(function() { window.location.reload(true) }, 1000)</script>');
}

if (function_exists('date_default_timezone_set') && function_exists('date_default_timezone_get')) {
    date_default_timezone_set(@date_default_timezone_get());
}

if ('cli' === PHP_SAPI || !isset($_SERVER['REQUEST_URI'])) {
    Phar::mapPhar('contao-manager.phar');
    require 'phar://contao-manager.phar/api/console';
} else {
    function rewrites()
    {
        // The function argument is unreliable across servers, Nginx for example is always empty
        list(,$url) = explode(basename(__FILE__), $_SERVER['REQUEST_URI'], 2);

        if (strpos($url, '..')) {
            return false;
        }

        if ('' === $url) {
            header('Location: /'.basename(__FILE__).'/');
            exit;
        }

        if (0 === strpos($url, '/api/')) {
            return '/dist/api.php'.$url;
        }

        if (!empty($url) && is_file('phar://'.__FILE__.'/dist'.$url)) {
            return '/dist'.$url;
        }

        return '/dist/index.html';
    }

    Phar::webPhar(
        null,
        'index.html',
        null,
        array(
            'log' => 'text/plain',
            'txt' => 'text/plain',
            'php' => Phar::PHP, // parse as PHP
            'css' => 'text/css',
            'gif' => 'image/gif',
            'html' => 'text/html',
            'ico' => 'image/x-ico',
            'jpg' => 'image/jpeg',
            'jpeg' => 'image/jpeg',
            'js' => 'application/x-javascript',
            'png' => 'image/png',
            'svg' => 'image/svg+xml',
            'json' => 'application/json'
        ),
        'rewrites'
    );
}

__HALT_COMPILER(); ?>
~l q                 .box/bin/check-requirements.php  Qti  Ǔa         .box/.requirements.php  Qti           .box/vendor/autoload.php  Qti  es      ,   .box/vendor/composer/autoload_namespaces.php   Qti   /t         .box/vendor/composer/LICENSE.  Qti.         $   .box/vendor/composer/ClassLoader.php?  Qti?  2@u      &   .box/vendor/composer/autoload_psr4.php*  Qti*  'Ť      *   .box/vendor/composer/autoload_classmap.php
  Qti
  >(      (   .box/vendor/composer/autoload_static.phpu  Qtiu  *#      &   .box/vendor/composer/autoload_real.php   Qti   ֤      #   .box/vendor/composer/semver/LICENSE  Qti  Bh      4   .box/vendor/composer/semver/src/CompilingMatcher.php  Qti  ~X      ,   .box/vendor/composer/semver/src/Interval.php  Qti  3}Ѥ      .   .box/vendor/composer/semver/src/Comparator.php  Qti  41      -   .box/vendor/composer/semver/src/Intervals.php{9  Qti{9  B      *   .box/vendor/composer/semver/src/Semver.php  Qti        1   .box/vendor/composer/semver/src/VersionParser.php:  Qti:  nA      B   .box/vendor/composer/semver/src/Constraint/ConstraintInterface.php  Qti  )      >   .box/vendor/composer/semver/src/Constraint/MultiConstraint.phpS  QtiS  u0      9   .box/vendor/composer/semver/src/Constraint/Constraint.php&  Qti&  u^      A   .box/vendor/composer/semver/src/Constraint/MatchAllConstraint.php;  Qti;  ΖM      B   .box/vendor/composer/semver/src/Constraint/MatchNoneConstraint.phpY  QtiY  %      4   .box/vendor/composer/semver/src/Constraint/Bound.phpl  Qtil  \      *   .box/vendor/composer/InstalledVersions.php   Qti   J      "   .box/vendor/composer/installed.php,  Qti,  "kN         .box/src/Terminal.php  Qti  c         .box/src/IO.php  Qti  1      !   .box/src/IsExtensionFulfilled.php  Qti  I8u         .box/src/Checker.php  Qti  $      "   .box/src/IsPhpVersionFulfilled.php  Qti  TY      "   .box/src/RequirementCollection.php  Qti  }      )   .box/src/IsExtensionConflictFulfilled.php  Qti  vc         .box/src/Printer.php  Qti  ch         .box/src/IsFulfilled.php   Qti   %<'         .box/src/Requirement.php  Qti  XƤ         LICENSE  Qti  p         dist/index.htmlH'  QtiH'  I         dist/api.php--  Qti  L|R         dist/css/367.25211792.cssl  Qtil  A      #   dist/css/chunk-vendors.46f4dfde.cssv  Qtiv           dist/css/186.9aa9997d.css  Qti  %v         dist/css/756.71b41ac9.css  Qti  ?         dist/css/414.2589534e.css  Qti           dist/css/120.ce753a3c.css?  Qti?  Ld         dist/css/335.e18cb2b2.css  Qti  26&         dist/css/app.c74a3fc7.css  Qti  ?\4         dist/css/904.3a60e65a.css  Qti  i_Ӥ         dist/js/851.bccade28.js֫  Qti֫  Kͤ         dist/js/518.7d262c02.js  Qti  oR         dist/js/194.7e05c25f.js  Qti  Τ         dist/js/554.80f1af85.js  Qti  Ƭ         dist/js/904.469c423c.js0  Qti0  u         dist/js/523.7617c212.js  Qti           dist/js/180.42df9004.js=  Qti=  N::B         dist/js/710.24c4cd7c.jsu| Qtiu| 0      !   dist/js/chunk-vendors.921ece36.js Qti )!         dist/js/414.a23ef62c.jss  Qtis  ѷ         dist/js/557.69b9338e.js&  Qti&  Ru/         dist/js/219.8a6252ad.js  Qti  q伤         dist/js/721.a298060e.js1  Qti1  ڬ
j         dist/js/769.92e42b5f.js  Qti  ^         dist/js/606.2974c6f2.js7  Qti7  *d         dist/js/312.cc0c9fd5.jsBO  QtiBO  QI垤         dist/js/669.4d0edf1c.js  Qti           dist/js/139.31ca6808.jsU  QtiU  x0L6         dist/js/739.4c59edac.js  Qti  j#         dist/js/958.d35ccdeb.jsS  QtiS  CIsƤ         dist/js/859.dbf1a05f.js)  Qti)  Rx         dist/js/164.4e598192.jsE  QtiE  e         dist/js/748.766e08c8.js  Qti  	;         dist/js/874.f11456c0.jst  Qtit   O         dist/js/540.456d5d6d.jsz  Qtiz  ȭf         dist/js/551.01beb249.js  Qti  n^⊤         dist/js/186.836851cb.jsO  QtiO  "         dist/js/560.36aa04d8.jsU  QtiU  ĜP         dist/js/715.0c82c54e.js  Qti  >         dist/js/335.11020416.jsg  Qtig  G~         dist/js/542.70ad2246.jsN  QtiN  EJˤ         dist/js/120.0b468899.js  Qti  _=d         dist/js/44.5dc282ff.js  Qti  [F         dist/js/716.aac3cea9.js  Qti  1         dist/js/706.abaff9c8.js  Qti  8)         dist/js/28.44aaa9cb.jsw  Qtiw  Ig0         dist/js/477.fb77fe74.js  Qti           dist/js/553.48a1739b.js  Qti  ~d:         dist/js/643.372ea4d9.js  Qti  B         dist/js/52.cc5d0f06.js  Qti  |         dist/js/367.8d3af137.js]  Qti]  Qr         dist/js/140.6c8f8c32.js=  Qti=  3N         dist/js/486.d2c3c316.jsz  Qtiz  25         dist/js/581.5db3a790.js  Qti  6         dist/js/953.b6fc1039.js  Qti  '3         dist/js/app.78f6a337.js	 Qti	 2oY         dist/js/638.f63623a3.js  Qti  YY      !   dist/img/button-show.2336e1d9.svgS  QtiS  U         dist/img/warning.9a7cd776.svg   Qti   fh         dist/img/logo.d9707286.svg  Qti  ;w          dist/img/button-add.759df12e.svg   Qti   O
         dist/img/favers.056e2836.svgH  QtiH  y,ͤ      #   dist/img/server-config.1a2d0888.svgg  Qtig  RN      %   dist/img/button-database.5282fc7e.svg   Qti   P      "   dist/img/symfony-logo.5c162c73.svg
  Qti
  Os@      !   dist/img/button-link.dd42e161.svg   Qti   ֖>      (   dist/img/button-maintenance.93830369.svgE  QtiE  O      $   dist/img/create-project.b22522ee.svg   Qti   ʅ      )   dist/img/button-incompatible.3eb2b686.svg  Qti  /$      #   dist/img/document-root.0e6dd2e4.svg   Qti   D      '   dist/img/search-by-algolia.72f0ac9a.svg  Qti           dist/img/boot.92149bf5.svg   Qti   So      #   dist/img/button-search.44ce1d4b.svgL  QtiL  w         dist/img/oauth.1243e742.svg.  Qti.  @
         dist/img/private.a1c65662.svg  Qti  _50w      %   dist/img/button-download.e1ba6f25.svg1  Qti1  O#         dist/img/person.00d78897.svg   Qti   w*      )   dist/img/widget-checkbox--on.8b830157.svg   Qti   #;      !   dist/img/button-lock.98988f08.svgc  Qtic  5=6z      "   dist/img/button-check.7a3b5ada.svg   Qti   ]R         dist/img/user.129e863d.svg   Qti   cǤ         dist/img/offline.0c23d1ce.svg  Qti  У-      $   dist/img/button-passkey.3806f98a.svg=  Qti=  }      (   dist/img/symfony-logo--dark.ea265042.svg  Qti  溤      #   dist/img/private--dark.41b90022.svg  Qti  b      &   dist/img/button-cloud-off.dd8ba18e.svg  Qti  ܡ<      "   dist/img/button-power.298a8072.svg6  Qti6  Kb      %   dist/img/downloads--dark.034bf7a3.svg-  Qti-  	Ǥ      "   dist/img/button-trash.855f57fa.svgt  Qtit  2}          dist/img/link-blank.eb57b3fa.svg   Qti   f^      &   dist/img/button-clipboard.9ef63d39.svgJ  QtiJ  v,N      '   dist/img/widget-radio--off.4e93f443.svg  Qti           dist/img/task.e9e5333f.svg{  Qti{  Jl      #   dist/img/button-update.ad79c617.svg\  Qti\  Į         dist/img/hint.ba2ac97e.svg!  Qti!        !   dist/img/button-hide.d23f6533.svg  Qti  m3(         dist/img/database.7f0a8c49.svg  Qti  <	         dist/img/updated.3b47bebb.svgH  QtiH  ʦ      $   dist/img/language--dark.a24e849e.svgx  Qtix  G7?      !   dist/img/button-save.3b5224de.svg  Qti           dist/img/lock.3c42a55f.svgf  Qtif  gG      $   dist/img/button-details.8ce780e9.svg  Qti  `         dist/img/downloads.c1db2a9e.svg0  Qti0  ¤      "   dist/img/color_scheme.d527d153.svg   Qti   t         dist/img/recovery.70ee118a.svg   Qti   OTM`      #   dist/img/button-upload.ca8e9cfc.svg3  Qti3  0U      !   dist/img/button-edit.40a4be06.svg  Qti  !.      &   dist/img/link-blank--dark.07eeaee6.svg   Qti   B|         dist/img/funding.cf78a0a0.svgJ  QtiJ  `1_      #   dist/img/button-unlock.51b76e07.svgi  Qtii  
         dist/img/php-logo.7376e212.svg	  Qti	  k9q      #   dist/img/updated--dark.c21fdd5b.svgE  QtiE  Ey      "   dist/img/button-cloud.bc42f267.svg  Qti  I[      "   dist/img/favers--dark.4765f7d4.svgE  QtiE        !   dist/img/button-more.e3eb2622.svg  Qti  v         dist/img/language.582b2920.svg{  Qti{  tW      &   dist/img/widget-radio--on.181461b6.svg:  Qti:  jM      $   dist/img/button-console.05dcdfc4.svg   Qti   >y      (   dist/img/color_scheme--dark.ef0f0aed.svg:  Qti:  <      !   dist/img/button-gear.a2dc1f09.svg  Qti  0         dist/img/sad.c7de6e95.svg5  Qti5  h          dist/img/button-run.b6310c5a.svg  Qti           dist/img/close.8b27dbcb.svg   Qti   e      "   dist/img/link-funding.b25cd92d.svg  Qti  PԤ      *   dist/img/widget-checkbox--off.73856538.svg   Qti   ~      (   dist/icons/task-active/favicon-16x16.png3  Qti3  K       "   dist/icons/task-active/favicon.ico:  Qti:  8      (   dist/icons/task-active/favicon-32x32.pngF  QtiF  )fx      '   dist/icons/task-error/favicon-16x16.png;  Qti;        !   dist/icons/task-error/favicon.ico:  Qti:  u      '   dist/icons/task-error/favicon-32x32.pngB  QtiB        )   dist/icons/task-success/favicon-16x16.pngU  QtiU  {ؤ      #   dist/icons/task-success/favicon.ico:  Qti:  TIm      )   dist/icons/task-success/favicon-32x32.pngq  Qtiq  ?.         dist/api.php  Qti  C¾         dist/assets/favicon-16x16.png  Qti           dist/assets/mstile-310x310.png%  Qti%  xH      &   dist/assets/android-chrome-384x384.png%  Qti%  1|&      3   dist/assets/apple-touch-startup-image-1125x2436.png  Qti  5      2   dist/assets/apple-touch-startup-image-1792x828.png  Qti  8Q      2   dist/assets/apple-touch-startup-image-1334x750.png}y  Qti}y  Դ         dist/assets/mstile-144x144.png  Qti        3   dist/assets/apple-touch-startup-image-1290x2796.pngu  Qtiu  ^v         dist/assets/favicon.ico  Qti  }*~      (   dist/assets/apple-touch-icon-120x120.png
  Qti
        3   dist/assets/apple-touch-startup-image-2732x2048.png Qti .uE      &   dist/assets/android-chrome-192x192.png3  Qti3  '\          dist/assets/apple-touch-icon.png  Qti  :5      3   dist/assets/apple-touch-startup-image-1242x2688.png&  Qti&  :Pg      &   dist/assets/android-chrome-256x256.pngh  Qtih  j't      3   dist/assets/apple-touch-startup-image-2436x1125.png  Qti  5x         dist/assets/mstile-70x70.png  Qti  eݺ=      2   dist/assets/apple-touch-startup-image-640x1136.pngP  QtiP  n      3   dist/assets/apple-touch-startup-image-1170x2532.png@  Qti@  ˨      *   dist/assets/apple-touch-icon-1024x1024.pngr|  Qtir|  T      (   dist/assets/apple-touch-icon-152x152.png  Qti  o      3   dist/assets/apple-touch-startup-image-1620x2160.pngb  Qtib  RE      3   dist/assets/apple-touch-startup-image-1668x2388.png  Qti  I      2   dist/assets/apple-touch-startup-image-828x1792.pngv  Qtiv  >H      3   dist/assets/apple-touch-startup-image-2048x1536.pngn Qtin xEy      (   dist/assets/apple-touch-icon-180x180.png  Qti  :5      (   dist/assets/yandex-browser-manifest.json   Qti   p#Ȥ      3   dist/assets/apple-touch-startup-image-1640x2160.pngv  Qtiv  <o      3   dist/assets/apple-touch-startup-image-2224x1668.png+ Qti+       3   dist/assets/apple-touch-startup-image-1179x2556.pngZ  QtiZ           dist/assets/favicon-48x48.png  Qti  .i         dist/assets/mstile-310x150.png  Qti  ƒܤ      3   dist/assets/apple-touch-startup-image-1242x2208.pngٸ  Qtiٸ  &Nf      (   dist/assets/apple-touch-icon-114x114.pngR	  QtiR	  M      &   dist/assets/apple-touch-icon-76x76.png)  Qti)  b      &   dist/assets/android-chrome-512x512.pngL6  QtiL6  x9      3   dist/assets/apple-touch-startup-image-2556x1179.png  Qti  jW      2   dist/assets/apple-touch-startup-image-1136x640.pngd  Qtid  %¤      3   dist/assets/apple-touch-startup-image-2532x1170.png  Qti  Ҫ      3   dist/assets/apple-touch-startup-image-2208x1242.png  Qti  PQ      3   dist/assets/apple-touch-startup-image-1488x2266.pngb  Qtib  Wzۤ      &   dist/assets/apple-touch-icon-57x57.png  Qti  1@      2   dist/assets/apple-touch-startup-image-750x1334.pnga  Qtia  ΃      3   dist/assets/apple-touch-startup-image-2266x1488.pngP QtiP aФ      ,   dist/assets/apple-touch-icon-precomposed.png  Qti  :5      3   dist/assets/apple-touch-startup-image-2160x1620.png" Qti" A'      3   dist/assets/apple-touch-startup-image-1284x2778.pngh  Qtih  eX:      3   dist/assets/apple-touch-startup-image-1668x2224.pngl  Qtil  N      3   dist/assets/apple-touch-startup-image-2688x1242.png  Qti  v      &   dist/assets/apple-touch-icon-72x72.png  Qti  ^F W      3   dist/assets/apple-touch-startup-image-2778x1284.png  Qti   Z      3   dist/assets/apple-touch-startup-image-1536x2048.pngW  QtiW  q)ݤ      3   dist/assets/apple-touch-startup-image-2388x1668.png1 Qti1 [3j         dist/assets/mstile-150x150.png  Qti  	          dist/assets/manifest.webmanifest  Qti  `l      3   dist/assets/apple-touch-startup-image-2796x1290.png  Qti  3ق      $   dist/assets/android-chrome-36x36.png+  Qti+        $   dist/assets/android-chrome-96x96.png  Qti  l@w      (   dist/assets/apple-touch-icon-167x167.png  Qti  dP      $   dist/assets/android-chrome-72x72.png  Qti  hQ\      &   dist/assets/apple-touch-icon-60x60.png  Qti        3   dist/assets/apple-touch-startup-image-2160x1640.pngV& QtiV& 7E      3   dist/assets/apple-touch-startup-image-2048x2732.pngDE QtiDE bpF      (   dist/assets/apple-touch-icon-144x144.png	  Qti	  Np      $   dist/assets/yandex-browser-50x50.pngX  QtiX  X         dist/assets/browserconfig.xmlr  Qtir  v,      $   dist/assets/android-chrome-48x48.png  Qti  .i         dist/assets/favicon-32x32.png  Qti  ɹ      &   dist/assets/android-chrome-144x144.png  Qti        %   api/HttpKernel/ApiProblemResponse.php	  Qti	  TAW         api/console--A  QtiA  C~Ƥ         api/Config/UploadsConfig.php9  Qti9  Bɤ         api/Config/UserConfig.php%  Qti%   #         api/Config/ManagerConfig.php9  Qti9  v         api/Config/AbstractConfig.phpX  QtiX  z;a         api/Config/ComposerConfig.php  Qti  'e         api/Config/PartialConfig.php  Qti  7         api/Config/AuthConfig.php  Qti  rΤ      *   api/Security/PasswordlessAuthenticator.php	  Qti	  &j      &   api/Security/WebauthnAuthenticator.php()  Qti()  wA      #   api/Security/TokenAuthenticator.php  Qti  i}
c      ,   api/Security/AuthenticationTrustResolver.php  Qti           api/Security/UserProvider.php  Qti  I         api/Security/User.php
  Qti
        !   api/Security/JwtAuthenticator.php 	  Qti 	  u!Ѥ      -   api/Security/AbstractBrowserAuthenticator.php  Qti           api/Security/TotpBadge.php9  Qti9  I&Ȥ      #   api/Security/LoginAuthenticator.php  Qti  @G         api/Security/JwtManager.php  Qti  fHF      .   api/TaskOperation/Composer/RemoveOperation.php  Qti  g/      2   api/TaskOperation/Composer/ClearCacheOperation.php  Qti  J%      4   api/TaskOperation/Composer/DumpAutoloadOperation.php  Qti        /   api/TaskOperation/Composer/InstallOperation.phpm  Qtim  r      .   api/TaskOperation/Composer/UpdateOperation.php~  Qti~  >W      /   api/TaskOperation/Composer/RequireOperation.php  Qti  M      5   api/TaskOperation/Composer/CreateProjectOperation.php=  Qti=  S      -   api/TaskOperation/Composer/CloudOperation.php8  Qti8  B	      8   api/TaskOperation/Filesystem/InstallUploadsOperation.php
  Qti
  D(      9   api/TaskOperation/Filesystem/RemoveArtifactsOperation.php  Qti        6   api/TaskOperation/Filesystem/RemoveVendorOperation.phpk  Qtik  4      7   api/TaskOperation/Filesystem/RemoveUploadsOperation.php  Qti  Rfͤ      5   api/TaskOperation/Filesystem/RemoveCacheOperation.php  Qti  BRl      1   api/TaskOperation/Manager/SelfUpdateOperation.php  Qti        -   api/TaskOperation/AbstractInlineOperation.php  Qti        1   api/TaskOperation/SponsoredOperationInterface.php!  Qti!  hg      #   api/TaskOperation/ConsoleOutput.php=  Qti=  6Pڤ      .   api/TaskOperation/AbstractProcessOperation.php?  Qti?  h      5   api/TaskOperation/Contao/MaintenanceModeOperation.php5  Qti5  dm      2   api/TaskOperation/Contao/BackupCreateOperation.php  Qti  S      1   api/TaskOperation/Contao/CacheWarmupOperation.php  Qti  Q      2   api/TaskOperation/Contao/CreateContaoOperation.php.  Qti.  Q      3   api/TaskOperation/Contao/BackupRestoreOperation.php@  Qti@  t      0   api/TaskOperation/Contao/CacheClearOperation.php4  Qti4  R      ,   api/TaskOperation/TaskOperationInterface.php  Qti  (f         api/Composer/CloudResolver.php  Qti  $         api/Composer/CloudChanges.php[  Qti[  39         api/Composer/CloudJob.phpv	  Qtiv	  լ=         api/Composer/CloudException.php  Qti  Lؤ         api/Composer/Environment.phpq0  Qtiq0  ̌dD      2   api/Resources/cache/url_generating_routes.php.meta"  Qti"  aM      @   api/Resources/cache/Contao_ManagerApi_ApiKernelProdContainer.php  Qti        %   api/Resources/cache/serialization.phpx   Qtix   [J      E   api/Resources/cache/Contao_ManagerApi_ApiKernelProdContainer.php.lock    Qti              E   api/Resources/cache/Contao_ManagerApi_ApiKernelProdContainer.php.metaK QtiK       -   api/Resources/cache/url_generating_routes.php@s  Qti@s  &      +   api/Resources/cache/url_matching_routes.php
4  Qti
4  	
      0   api/Resources/cache/url_matching_routes.php.meta"  Qti"  aM      H   api/Resources/cache/Contao_ManagerApi_ApiKernelProdContainer.preload.phpr  Qtir  9      @   api/Resources/cache/Symfony/Config/Framework/HttpCacheConfig.php"  Qti"  -դ      F   api/Resources/cache/Symfony/Config/Framework/Webhook/RoutingConfig.phpn  Qtin  Ef      <   api/Resources/cache/Symfony/Config/Framework/CacheConfig.php#  Qti#  
z      @   api/Resources/cache/Symfony/Config/Framework/FragmentsConfig.php
  Qti
  ׼t      J   api/Resources/cache/Symfony/Config/Framework/Form/CsrfProtectionConfig.php  Qti  a2      P   api/Resources/cache/Symfony/Config/Framework/HttpClient/DefaultOptionsConfig.phpD  QtiD  +      i   api/Resources/cache/Symfony/Config/Framework/HttpClient/ScopedClientConfig/RetryFailed/HttpCodeConfig.php  Qti  hD      d   api/Resources/cache/Symfony/Config/Framework/HttpClient/ScopedClientConfig/PeerFingerprintConfig.php	  Qti	        `   api/Resources/cache/Symfony/Config/Framework/HttpClient/ScopedClientConfig/RetryFailedConfig.php\  Qti\        N   api/Resources/cache/Symfony/Config/Framework/HttpClient/ScopedClientConfig.phpR  QtiR  f      e   api/Resources/cache/Symfony/Config/Framework/HttpClient/DefaultOptions/RetryFailed/HttpCodeConfig.php  Qti  ]~      `   api/Resources/cache/Symfony/Config/Framework/HttpClient/DefaultOptions/PeerFingerprintConfig.php	  Qti	  9      \   api/Resources/cache/Symfony/Config/Framework/HttpClient/DefaultOptions/RetryFailedConfig.phpH  QtiH  ;      I   api/Resources/cache/Symfony/Config/Framework/Serializer/MappingConfig.php@  Qti@  \      A   api/Resources/cache/Symfony/Config/Framework/ValidationConfig.php&  Qti&  WQW      B   api/Resources/cache/Symfony/Config/Framework/RateLimiterConfig.php	  Qti	  rd      U   api/Resources/cache/Symfony/Config/Framework/RateLimiter/LimiterConfig/RateConfig.phpe  Qtie  Դn      J   api/Resources/cache/Symfony/Config/Framework/RateLimiter/LimiterConfig.php  Qti  w      A   api/Resources/cache/Symfony/Config/Framework/Cache/PoolConfig.php
  Qti
  J      A   api/Resources/cache/Symfony/Config/Framework/SerializerConfig.php}  Qti}  P7N      E   api/Resources/cache/Symfony/Config/Framework/CsrfProtectionConfig.php1  Qti1  jWQ      =   api/Resources/cache/Symfony/Config/Framework/AssetsConfig.php  Qti  *=      N   api/Resources/cache/Symfony/Config/Framework/Notifier/AdminRecipientConfig.phpR  QtiR  h      @   api/Resources/cache/Symfony/Config/Framework/MessengerConfig.phpB(  QtiB(  u#Ф      >   api/Resources/cache/Symfony/Config/Framework/WebhookConfig.php  Qti  ƙĹ      =   api/Resources/cache/Symfony/Config/Framework/RouterConfig.php  Qti  Lܤ      A   api/Resources/cache/Symfony/Config/Framework/TranslatorConfig.phpa   Qtia   T~      @   api/Resources/cache/Symfony/Config/Framework/WorkflowsConfig.php  Qti  w;      J   api/Resources/cache/Symfony/Config/Framework/Workflows/WorkflowsConfig.php)  Qti)  I\      [   api/Resources/cache/Symfony/Config/Framework/Workflows/WorkflowsConfig/AuditTrailConfig.phpH  QtiH  kҚL      ]   api/Resources/cache/Symfony/Config/Framework/Workflows/WorkflowsConfig/MarkingStoreConfig.php	  Qti	  FCS      [   api/Resources/cache/Symfony/Config/Framework/Workflows/WorkflowsConfig/TransitionConfig.php  Qti  iפ      V   api/Resources/cache/Symfony/Config/Framework/Workflows/WorkflowsConfig/PlaceConfig.php^  Qti^  XS      :   api/Resources/cache/Symfony/Config/Framework/EsiConfig.php'  Qti'  2)      >   api/Resources/cache/Symfony/Config/Framework/WebLinkConfig.php+  Qti+         F   api/Resources/cache/Symfony/Config/Framework/Mailer/EnvelopeConfig.php  Qti  _g      D   api/Resources/cache/Symfony/Config/Framework/Mailer/HeaderConfig.php&  Qti&  ?       :   api/Resources/cache/Symfony/Config/Framework/SsiConfig.php'  Qti'        T   api/Resources/cache/Symfony/Config/Framework/Translator/PseudoLocalizationConfig.php  Qti  -D      J   api/Resources/cache/Symfony/Config/Framework/Translator/ProviderConfig.php
  Qti
  ݝ      ?   api/Resources/cache/Symfony/Config/Framework/ProfilerConfig.php  Qti  )      @   api/Resources/cache/Symfony/Config/Framework/SemaphoreConfig.phpy  Qtiy  :      >   api/Resources/cache/Symfony/Config/Framework/SecretsConfig.php	  Qti	  	fJ      E   api/Resources/cache/Symfony/Config/Framework/PropertyAccessConfig.php  Qti        J   api/Resources/cache/Symfony/Config/Framework/Messenger/TransportConfig.php8  Qti8  h      ]   api/Resources/cache/Symfony/Config/Framework/Messenger/Serializer/SymfonySerializerConfig.php  Qti  B      K   api/Resources/cache/Symfony/Config/Framework/Messenger/SerializerConfig.php  Qti  )'      ^   api/Resources/cache/Symfony/Config/Framework/Messenger/TransportConfig/RetryStrategyConfig.php1  Qti1  Q'      H   api/Resources/cache/Symfony/Config/Framework/Messenger/RoutingConfig.phpW  QtiW  UZ      U   api/Resources/cache/Symfony/Config/Framework/Messenger/BusConfig/MiddlewareConfig.php  Qti  ,+      \   api/Resources/cache/Symfony/Config/Framework/Messenger/BusConfig/DefaultMiddlewareConfig.php
  Qti
  L      D   api/Resources/cache/Symfony/Config/Framework/Messenger/BusConfig.php  Qti  9      C   api/Resources/cache/Symfony/Config/Framework/PropertyInfoConfig.php/  Qti/  t'      =   api/Resources/cache/Symfony/Config/Framework/MailerConfig.php)  Qti)  O|      :   api/Resources/cache/Symfony/Config/Framework/UidConfig.php  Qti  uT      B   api/Resources/cache/Symfony/Config/Framework/RemoteeventConfig.php/  Qti/        B   api/Resources/cache/Symfony/Config/Framework/AssetMapperConfig.php;(  Qti;(  a7Ȥ      D   api/Resources/cache/Symfony/Config/Framework/HtmlSanitizerConfig.php 
  Qti 
  <      @   api/Resources/cache/Symfony/Config/Framework/ExceptionConfig.phpG  QtiG  LFN      >   api/Resources/cache/Symfony/Config/Framework/SessionConfig.php82  Qti82  +y      N   api/Resources/cache/Symfony/Config/Framework/HtmlSanitizer/SanitizerConfig.php8  Qti8  J`      A   api/Resources/cache/Symfony/Config/Framework/HttpClientConfig.phpf  Qtif  :+      @   api/Resources/cache/Symfony/Config/Framework/PhpErrorsConfig.php  Qti  
      ?   api/Resources/cache/Symfony/Config/Framework/NotifierConfig.php?  Qti?  F5๤      >   api/Resources/cache/Symfony/Config/Framework/RequestConfig.php_  Qti_  ;      B   api/Resources/cache/Symfony/Config/Framework/AnnotationsConfig.php  Qti  ZzP      E   api/Resources/cache/Symfony/Config/Framework/Assets/PackageConfig.php  Qti  o}      X   api/Resources/cache/Symfony/Config/Framework/Validation/NotCompromisedPasswordConfig.php1  Qti1        I   api/Resources/cache/Symfony/Config/Framework/Validation/MappingConfig.php@  Qti@  @      M   api/Resources/cache/Symfony/Config/Framework/Validation/AutoMappingConfig.phph  Qtih        ;   api/Resources/cache/Symfony/Config/Framework/LockConfig.php  Qti  ̤      @   api/Resources/cache/Symfony/Config/Framework/SchedulerConfig.php-  Qti-  ]      ;   api/Resources/cache/Symfony/Config/Framework/FormConfig.php  Qti  tȶ      P   api/Resources/cache/Symfony/Config/Security/ProviderConfig/Memory/UserConfig.php  Qti  D	      I   api/Resources/cache/Symfony/Config/Security/ProviderConfig/LdapConfig.php  Qti  m      K   api/Resources/cache/Symfony/Config/Security/ProviderConfig/MemoryConfig.phpG  QtiG  Q"z      J   api/Resources/cache/Symfony/Config/Security/ProviderConfig/ChainConfig.php  Qti  Bz      D   api/Resources/cache/Symfony/Config/Security/PasswordHasherConfig.php  Qti  ~      >   api/Resources/cache/Symfony/Config/Security/ProviderConfig.php  Qti  &      >   api/Resources/cache/Symfony/Config/Security/FirewallConfig.phpm  Qtim   ^      P   api/Resources/cache/Symfony/Config/Security/FirewallConfig/AccessTokenConfig.php  Qti  5․      O   api/Resources/cache/Symfony/Config/Security/FirewallConfig/RememberMeConfig.phpu1  Qtiu1  '=      N   api/Resources/cache/Symfony/Config/Security/FirewallConfig/FormLoginConfig.phpA  QtiA  9;ؤ      R   api/Resources/cache/Symfony/Config/Security/FirewallConfig/JsonLoginLdapConfig.php
*  Qti
*  1-      N   api/Resources/cache/Symfony/Config/Security/FirewallConfig/HttpBasicConfig.php  Qti  dA¤      ]   api/Resources/cache/Symfony/Config/Security/FirewallConfig/AccessToken/TokenHandlerConfig.php  Qti  }O      j   api/Resources/cache/Symfony/Config/Security/FirewallConfig/AccessToken/TokenHandler/OidcUserInfoConfig.php
  Qti
  ׎      b   api/Resources/cache/Symfony/Config/Security/FirewallConfig/AccessToken/TokenHandler/OidcConfig.php  Qti  e;      N   api/Resources/cache/Symfony/Config/Security/FirewallConfig/JsonLoginConfig.php  Qti  ?      X   api/Resources/cache/Symfony/Config/Security/FirewallConfig/Logout/DeleteCookieConfig.php  Qti  'Ť      O   api/Resources/cache/Symfony/Config/Security/FirewallConfig/SwitchUserConfig.php  Qti  _ɤ      T   api/Resources/cache/Symfony/Config/Security/FirewallConfig/LoginThrottlingConfig.php  Qti        N   api/Resources/cache/Symfony/Config/Security/FirewallConfig/LoginLinkConfig.phpx3  Qtix3  jݺ      f   api/Resources/cache/Symfony/Config/Security/FirewallConfig/RememberMe/TokenProvider/DoctrineConfig.php  Qti  C      ]   api/Resources/cache/Symfony/Config/Security/FirewallConfig/RememberMe/TokenProviderConfig.phpS  QtiS        R   api/Resources/cache/Symfony/Config/Security/FirewallConfig/FormLoginLdapConfig.phpN  QtiN  J      R   api/Resources/cache/Symfony/Config/Security/FirewallConfig/HttpBasicLdapConfig.php  Qti  :@j٤      I   api/Resources/cache/Symfony/Config/Security/FirewallConfig/X509Config.php  Qti  7H      O   api/Resources/cache/Symfony/Config/Security/FirewallConfig/RemoteUserConfig.php  Qti  λ      K   api/Resources/cache/Symfony/Config/Security/FirewallConfig/LogoutConfig.php   Qti          K   api/Resources/cache/Symfony/Config/Security/AccessDecisionManagerConfig.php  Qti  4G      C   api/Resources/cache/Symfony/Config/Security/AccessControlConfig.php  Qti  %_      5   api/Resources/cache/Symfony/Config/SecurityConfig.php0  Qti0        4   api/Resources/cache/Symfony/Config/MonologConfig.php  Qti  -      <   api/Resources/cache/Symfony/Config/Monolog/HandlerConfig.php: Qti: d      V   api/Resources/cache/Symfony/Config/Monolog/HandlerConfig/ProcessPsr3MessagesConfig.php
  Qti
  |́      L   api/Resources/cache/Symfony/Config/Monolog/HandlerConfig/PublisherConfig.php  Qti  Ǫݤ      H   api/Resources/cache/Symfony/Config/Monolog/HandlerConfig/RedisConfig.php  Qti  +       P   api/Resources/cache/Symfony/Config/Monolog/HandlerConfig/ElasticsearchConfig.php  Qti  Nw      Q   api/Resources/cache/Symfony/Config/Monolog/HandlerConfig/EmailPrototypeConfig.phpR  QtiR  0      J   api/Resources/cache/Symfony/Config/Monolog/HandlerConfig/MongodbConfig.phpA  QtiA  ^Þ      H   api/Resources/cache/Symfony/Config/Monolog/HandlerConfig/MongoConfig.php  Qti  (      R   api/Resources/cache/Symfony/Config/Monolog/HandlerConfig/VerbosityLevelsConfig.php  Qti  \<      I   api/Resources/cache/Symfony/Config/Monolog/HandlerConfig/PredisConfig.php2  Qti2  A      S   api/Resources/cache/Symfony/Config/Monolog/HandlerConfig/ExcludedHttpCodeConfig.phpv  Qtiv  ݂      K   api/Resources/cache/Symfony/Config/Monolog/HandlerConfig/ChannelsConfig.php  Qti  J,      6   api/Resources/cache/Symfony/Config/FrameworkConfig.php9 Qti9 a      T   api/Resources/cache/ContainerLiF9Qbu/getSecurity_Firewall_Map_Context_ApiService.php  Qti  `!/      W   api/Resources/cache/ContainerLiF9Qbu/getContainer_GetRoutingConditionServiceService.php  Qti  (A      F   api/Resources/cache/ContainerLiF9Qbu/getComposerController2Service.php  Qti  UEG      N   api/Resources/cache/ContainerLiF9Qbu/getSecurity_UserCheckerLocatorService.php  Qti  V      N   api/Resources/cache/ContainerLiF9Qbu/getConsole_Command_SecretsListService.php  Qti        P   api/Resources/cache/ContainerLiF9Qbu/getConsole_Command_SecretsRemoveService.php  Qti        C   api/Resources/cache/ContainerLiF9Qbu/getGraphicsLibCheckService.php  Qti  		k      C   api/Resources/cache/ContainerLiF9Qbu/getPhpCliControllerService.php  Qti  az      Y   api/Resources/cache/ContainerLiF9Qbu/getSecurity_Authenticator_ManagersLocatorService.php  Qti        D   api/Resources/cache/ContainerLiF9Qbu/getTaskDeleteCommandService.php  Qti         `   api/Resources/cache/ContainerLiF9Qbu/get_Console_Command_SecretsEncryptFromLocal_LazyService.phpy  Qtiy  :      G   api/Resources/cache/ContainerLiF9Qbu/getConstraintControllerService.php  Qti  ?      V   api/Resources/cache/ContainerLiF9Qbu/getArgumentResolver_BackedEnumResolverService.php  Qti  6T      4   api/Resources/cache/ContainerLiF9Qbu/removed-ids.php  Qti  ]      G   api/Resources/cache/ContainerLiF9Qbu/getProcessRunnerCommandService.php  Qti  Ex      C   api/Resources/cache/ContainerLiF9Qbu/getJwtAuthenticatorService.phpQ  QtiQ  D`      C   api/Resources/cache/ContainerLiF9Qbu/getContaoControllerService.php  Qti  zf       E   api/Resources/cache/ContainerLiF9Qbu/getSecurity_AccessMapService.php*  Qti*  oT      H   api/Resources/cache/ContainerLiF9Qbu/getIntegrityCheckFactoryService.php  Qti  l|<      Q   api/Resources/cache/ContainerLiF9Qbu/getConsole_Command_ContainerDebugService.php)  Qti)  `t٧      W   api/Resources/cache/ContainerLiF9Qbu/get_Console_Command_ContainerDebug_LazyService.php#  Qti#        H   api/Resources/cache/ContainerLiF9Qbu/getWebauthnAuthenticatorService.php8
  Qti8
  ϋs      F   api/Resources/cache/ContainerLiF9Qbu/getJwtCookieControllerService.php  Qti  at      E   api/Resources/cache/ContainerLiF9Qbu/getRouter_CacheWarmerService.phpu  Qtiu  o      D   api/Resources/cache/ContainerLiF9Qbu/getBackupRestoreTaskService.php  Qti  .ͤ      H   api/Resources/cache/ContainerLiF9Qbu/getConsole_CommandLoaderService.php&  Qti&   Ƥ      <   api/Resources/cache/ContainerLiF9Qbu/getCache_AppService.phpb  Qtib        M   api/Resources/cache/ContainerLiF9Qbu/getConsole_Command_SecretsSetService.php  Qti  hY      T   api/Resources/cache/ContainerLiF9Qbu/getSecurity_Command_UserPasswordHashService.php  Qti  w<      H   api/Resources/cache/ContainerLiF9Qbu/getConsoleProcessFactoryService.php>  Qti>  ܮ`)      \   api/Resources/cache/ContainerLiF9Qbu/get_Console_Command_ConfigDumpReference_LazyService.phpY  QtiY  |A      C   api/Resources/cache/ContainerLiF9Qbu/getCache_AppClearerService.php  Qti  R      A   api/Resources/cache/ContainerLiF9Qbu/getUserControllerService.php  Qti  xڞ      N   api/Resources/cache/ContainerLiF9Qbu/getConsole_Command_RouterDebugService.php  Qti  E      Q   api/Resources/cache/ContainerLiF9Qbu/Contao_ManagerApi_ApiKernelProdContainer.php&  Qti&  e      W   api/Resources/cache/ContainerLiF9Qbu/get_Console_Command_CachePoolPrune_LazyService.php  Qti  YӤ      D   api/Resources/cache/ContainerLiF9Qbu/getTaskUpdateCommandService.php  Qti  /      A   api/Resources/cache/ContainerLiF9Qbu/getTaskControllerService.php  Qti  >1      L   api/Resources/cache/ContainerLiF9Qbu/getMaintenanceModeControllerService.php_  Qti_        A   api/Resources/cache/ContainerLiF9Qbu/getFileControllerService.php  Qti  5^*      J   api/Resources/cache/ContainerLiF9Qbu/get_ServiceLocator_Y_Xs7MwService.phpD  QtiD  giv      A   api/Resources/cache/ContainerLiF9Qbu/getRouting_LoaderService.phpI
  QtiI
  'C      >   api/Resources/cache/ContainerLiF9Qbu/getEnvironmentService.php  Qti  }      T   api/Resources/cache/ContainerLiF9Qbu/getSecurity_Listener_UserChecker_ApiService.php  Qti  x      C   api/Resources/cache/ContainerLiF9Qbu/getServicesResetterService.phpR  QtiR  mP      e   api/Resources/cache/ContainerLiF9Qbu/getCache_SecurityIsGrantedAttributeExpressionLanguageService.php  Qti  m      D   api/Resources/cache/ContainerLiF9Qbu/getOpcacheControllerService.php  Qti  q      P   api/Resources/cache/ContainerLiF9Qbu/getConsole_Command_AssetsInstallService.php  Qti  20      Q   api/Resources/cache/ContainerLiF9Qbu/getSerializer_Mapping_CacheWarmerService.php  Qti  ^y      E   api/Resources/cache/ContainerLiF9Qbu/getLoginAuthenticatorService.phph  Qtih  Ĥ      O   api/Resources/cache/ContainerLiF9Qbu/getSecurity_EventDispatcher_ApiService.php  Qti  _w      ?   api/Resources/cache/ContainerLiF9Qbu/getCache_SystemService.php  Qti  f      A   api/Resources/cache/ContainerLiF9Qbu/getMonolog_LoggerService.php  Qti  ކ      X   api/Resources/cache/ContainerLiF9Qbu/get_Console_Command_CachePoolDelete_LazyService.php&  Qti&  }e      J   api/Resources/cache/ContainerLiF9Qbu/getMonolog_Logger_SecurityService.php  Qti  ~D`b      @   api/Resources/cache/ContainerLiF9Qbu/getUpdateCommandService.phpk  Qtik  %%      Q   api/Resources/cache/ContainerLiF9Qbu/getDebug_ErrorHandlerConfiguratorService.php\  Qti\        I   api/Resources/cache/ContainerLiF9Qbu/getTaskDeleteCommand_LazyService.php  Qti  d      U   api/Resources/cache/ContainerLiF9Qbu/getSecurity_Access_AuthenticatedVoterService.phpJ  QtiJ  d-E      ?   api/Resources/cache/ContainerLiF9Qbu/getProcessCheckService.php  Qti  2      D   api/Resources/cache/ContainerLiF9Qbu/getSessionControllerService.phpp  Qtip        V   api/Resources/cache/ContainerLiF9Qbu/getSecurity_Listener_PasswordMigratingService.php$  Qti$  E5      A   api/Resources/cache/ContainerLiF9Qbu/getSelfUpdateTaskService.php  Qti  >q      X   api/Resources/cache/ContainerLiF9Qbu/get_Console_Command_SerializerDebug_LazyService.php  Qti  eU      F   api/Resources/cache/ContainerLiF9Qbu/getCache_GlobalClearerService.phpn  Qtin  IC      >   api/Resources/cache/ContainerLiF9Qbu/getTaskManagerService.php
  Qti
  N      H   api/Resources/cache/ContainerLiF9Qbu/getConsole_ErrorListenerService.php  Qti  y      K   api/Resources/cache/ContainerLiF9Qbu/getUploadPackagesControllerService.phpu  Qtiu  ܫo      <   api/Resources/cache/ContainerLiF9Qbu/getContaoApiService.php8  Qti8  {1      C   api/Resources/cache/ContainerLiF9Qbu/getMemoryLimitCheckService.php  Qti  ,H      W   api/Resources/cache/ContainerLiF9Qbu/get_Security_Command_DebugFirewall_LazyService.php&  Qti&  5       B   api/Resources/cache/ContainerLiF9Qbu/getSysTempDirCheckService.phpY  QtiY  4f'      V   api/Resources/cache/ContainerLiF9Qbu/get_Console_Command_SecretsRemove_LazyService.php  Qti  (      _   api/Resources/cache/ContainerLiF9Qbu/getArgumentResolver_QueryParameterValueResolverService.php  Qti  ŧ      I   api/Resources/cache/ContainerLiF9Qbu/getTaskUpdateCommand_LazyService.php  Qti  'O*      C   api/Resources/cache/ContainerLiF9Qbu/getConfigControllerService.phpH  QtiH  䥎      =   api/Resources/cache/ContainerLiF9Qbu/getSelfUpdateService.php  Qti  qӾq      C   api/Resources/cache/ContainerLiF9Qbu/getTaskAbortCommandService.php  Qti  1s      @   api/Resources/cache/ContainerLiF9Qbu/getCloudResolverService.phpn  Qtin  %      ^   api/Resources/cache/ContainerLiF9Qbu/get_Console_Command_SecretsDecryptToLocal_LazyService.phpw  Qtiw  nÄ      F   api/Resources/cache/ContainerLiF9Qbu/getAccessKeyControllerService.php  Qti  ;       S   api/Resources/cache/ContainerLiF9Qbu/getPropertyInfo_SerializerExtractorService.php$  Qti$  vQ      ?   api/Resources/cache/ContainerLiF9Qbu/getUserProviderService.php  Qti  Ԥ      C   api/Resources/cache/ContainerLiF9Qbu/getPhpWebControllerService.php#  Qti#  1      D   api/Resources/cache/ContainerLiF9Qbu/getAboutCommand_LazyService.php  Qti        P   api/Resources/cache/ContainerLiF9Qbu/getConsole_Command_ContainerLintService.php<  Qti<  QE>      N   api/Resources/cache/ContainerLiF9Qbu/get_Console_Command_About_LazyService.php  Qti  _v      T   api/Resources/cache/ContainerLiF9Qbu/get_Console_Command_RouterMatch_LazyService.php  Qti  i"a      =   api/Resources/cache/ContainerLiF9Qbu/getTranslatorService.php  Qti  zp      G   api/Resources/cache/ContainerLiF9Qbu/getSelfUpdateControllerService.php  Qti  +      K   api/Resources/cache/ContainerLiF9Qbu/getSecurity_ChannelListenerService.php  Qti  ~Z      L   api/Resources/cache/ContainerLiF9Qbu/getArgumentResolver_VariadicService.php  Qti  ~<      D   api/Resources/cache/ContainerLiF9Qbu/getManagerControllerService.php  Qti  Ť      C   api/Resources/cache/ContainerLiF9Qbu/getBackupControllerService.php  Qti  ?
      B   api/Resources/cache/ContainerLiF9Qbu/getSecurity_HelperService.php  Qti  4      Q   api/Resources/cache/ContainerLiF9Qbu/getSecurity_Listener_UserProviderService.php  Qti  55      Q   api/Resources/cache/ContainerLiF9Qbu/get_Console_Command_YamlLint_LazyService.php  Qti        @   api/Resources/cache/ContainerLiF9Qbu/getSecrets_VaultService.phpE  QtiE  W      V   api/Resources/cache/ContainerLiF9Qbu/getConsole_Command_ConfigDumpReferenceService.phpN  QtiN  2^x      N   api/Resources/cache/ContainerLiF9Qbu/getConsole_Command_CacheWarmupService.phpS  QtiS  ?`f      U   api/Resources/cache/ContainerLiF9Qbu/getSecurity_Access_RoleHierarchyVoterService.php*  Qti*        T   api/Resources/cache/ContainerLiF9Qbu/getArgumentResolver_RequestAttributeService.php  Qti  ž~      C   api/Resources/cache/ContainerLiF9Qbu/getBackupCreateTaskService.php  Qti  J      L   api/Resources/cache/ContainerLiF9Qbu/getProcessRunnerCommand_LazyService.php  Qti  '`      R   api/Resources/cache/ContainerLiF9Qbu/getConsole_Command_CachePoolDeleteService.phpt  Qtit  j      B   api/Resources/cache/ContainerLiF9Qbu/getCloudControllerService.php	  Qti	  /%      <   api/Resources/cache/ContainerLiF9Qbu/getSetupTaskService.php  Qti  `ݼ      S   api/Resources/cache/ContainerLiF9Qbu/get_Console_Command_SecretsSet_LazyService.php  Qti  u      E   api/Resources/cache/ContainerLiF9Qbu/getTemplateControllerService.php  Qti  Պa      Z   api/Resources/cache/ContainerLiF9Qbu/getConsole_Command_CachePoolInvalidateTagsService.php  Qti  J      ]   api/Resources/cache/ContainerLiF9Qbu/get_Console_Command_EventDispatcherDebug_LazyService.phpb  Qtib  |      V   api/Resources/cache/ContainerLiF9Qbu/get_Console_Command_CachePoolList_LazyService.php  Qti  o 8      W   api/Resources/cache/ContainerLiF9Qbu/getConsole_Command_EventDispatcherDebugService.php  Qti  Q]"դ      K   api/Resources/cache/ContainerLiF9Qbu/getArgumentResolver_ServiceService.php  Qti  ~x      `   api/Resources/cache/ContainerLiF9Qbu/get_Console_Command_CachePoolInvalidateTags_LazyService.php  Qti  9      T   api/Resources/cache/ContainerLiF9Qbu/get_Console_Command_CacheWarmup_LazyService.php  Qti  ` Ǥ      F   api/Resources/cache/ContainerLiF9Qbu/getCache_SystemClearerService.php  Qti  #&      J   api/Resources/cache/ContainerLiF9Qbu/get_ServiceLocator_BvkMlPlService.phpH  QtiH  u(      G   api/Resources/cache/ContainerLiF9Qbu/getMonolog_Logger_TasksService.php  Qti  լ>      F   api/Resources/cache/ContainerLiF9Qbu/getAdminUserControllerService.php  Qti  (j      H   api/Resources/cache/ContainerLiF9Qbu/getIntegrityCheckCommandService.php  Qti  *K      V   api/Resources/cache/ContainerLiF9Qbu/get_Console_Command_AssetsInstall_LazyService.php$  Qti$  ʼ      [   api/Resources/cache/ContainerLiF9Qbu/getSecurity_Firewall_EventDispatcherLocatorService.php  Qti  P      R   api/Resources/cache/ContainerLiF9Qbu/getConsole_Command_SerializerDebugService.php  Qti  q%      E   api/Resources/cache/ContainerLiF9Qbu/getPhpExtensionsCheckService.php  Qti        K   api/Resources/cache/ContainerLiF9Qbu/getArgumentResolver_DefaultService.php  Qti  T      A   api/Resources/cache/ContainerLiF9Qbu/getAuthControllerService.phpq  Qtiq  E      L   api/Resources/cache/ContainerLiF9Qbu/getArgumentResolver_DatetimeService.php  Qti  ?      G   api/Resources/cache/ContainerLiF9Qbu/getArgumentResolver_UidService.php  Qti  &J      L   api/Resources/cache/ContainerLiF9Qbu/getInstallToolLockControllerService.php  Qti  /d      E   api/Resources/cache/ContainerLiF9Qbu/getUpdateCommand_LazyService.php  Qti  lȤ      E   api/Resources/cache/ContainerLiF9Qbu/getComposerControllerService.php  Qti  ֦6s      K   api/Resources/cache/ContainerLiF9Qbu/getArgumentResolver_SessionService.php  Qti  c      >   api/Resources/cache/ContainerLiF9Qbu/getCacheWarmerService.php{  Qti{  K疂      E   api/Resources/cache/ContainerLiF9Qbu/getRedirectControllerService.php  Qti        @   api/Resources/cache/ContainerLiF9Qbu/getUploadsConfigService.php  Qti        N   api/Resources/cache/ContainerLiF9Qbu/getDatabaseMigrationControllerService.php  Qti  -      K   api/Resources/cache/ContainerLiF9Qbu/getConsole_Command_YamlLintService.php	  Qti	  G9      G   api/Resources/cache/ContainerLiF9Qbu/getConfigBuilder_WarmerService.php  Qti  hd      L   api/Resources/cache/ContainerLiF9Qbu/getPasswordlessAuthenticatorService.php  Qti  4Q      A   api/Resources/cache/ContainerLiF9Qbu/getClearCacheTaskService.php  Qti  R      H   api/Resources/cache/ContainerLiF9Qbu/getRootPackageControllerService.php*  Qti*  Fn4      E   api/Resources/cache/ContainerLiF9Qbu/getCache_App_TaggableService.php  Qti        @   api/Resources/cache/ContainerLiF9Qbu/getContaoConsoleService.php  Qti  nh,      @   api/Resources/cache/ContainerLiF9Qbu/getManagerConfigService.php  Qti  ]|      M   api/Resources/cache/ContainerLiF9Qbu/getSecurity_UserValueResolverService.php  Qti  Z      X   api/Resources/cache/ContainerLiF9Qbu/get_Console_Command_DebugAutowiring_LazyService.php3  Qti3  0ä      Q   api/Resources/cache/ContainerLiF9Qbu/getSecurity_Command_DebugFirewallService.php  Qti  f"      b   api/Resources/cache/ContainerLiF9Qbu/getSecurity_Listener_CheckAuthenticatorCredentialsService.phpH  QtiH  ?       W   api/Resources/cache/ContainerLiF9Qbu/get_Console_Command_CachePoolClear_LazyService.php  Qti  'I      M   api/Resources/cache/ContainerLiF9Qbu/getConsole_Command_CacheClearService.php  Qti        D   api/Resources/cache/ContainerLiF9Qbu/getPhpinfoControllerService.php  Qti  8      P   api/Resources/cache/ContainerLiF9Qbu/getConsole_Command_CachePoolListService.php  Qti  )PҤ      U   api/Resources/cache/ContainerLiF9Qbu/getSecurity_Authenticator_Manager_ApiService.php(	  Qti(	  L~      E   api/Resources/cache/ContainerLiF9Qbu/getAllowUrlFopenCheckService.php  Qti  Ƶ      C   api/Resources/cache/ContainerLiF9Qbu/getRebuildCacheTaskService.php#  Qti#  /^      V   api/Resources/cache/ContainerLiF9Qbu/getSecurity_Firewall_Authenticator_ApiService.php  Qti  #L牤      [   api/Resources/cache/ContainerLiF9Qbu/get_Console_Command_SecretsGenerateKey_LazyService.php@  Qti@  )U      T   api/Resources/cache/ContainerLiF9Qbu/get_Console_Command_RouterDebug_LazyService.php  Qti  l       Q   api/Resources/cache/ContainerLiF9Qbu/getConsole_Command_CachePoolClearService.php_  Qti_  z2      @   api/Resources/cache/ContainerLiF9Qbu/getLogControllerService.php  Qti  uu      L   api/Resources/cache/ContainerLiF9Qbu/getContainer_EnvVarProcessorService.php+  Qti+  Qͤ      U   api/Resources/cache/ContainerLiF9Qbu/getSecurity_Listener_Api_UserProviderService.php  Qti   jt      >   api/Resources/cache/ContainerLiF9Qbu/getInstallTaskService.php  Qti  Ȇ      T   api/Resources/cache/ContainerLiF9Qbu/getContainer_EnvVarProcessorsLocatorService.php  Qti  xO      D   api/Resources/cache/ContainerLiF9Qbu/getExceptionListenerService.php  Qti  >_A      ?   api/Resources/cache/ContainerLiF9Qbu/getSymlinkCheckService.php  Qti  3]3      :   api/Resources/cache/ContainerLiF9Qbu/getRequestService.php  Qti  Ϳˤ      ?   api/Resources/cache/ContainerLiF9Qbu/getSessionCheckService.php  Qti  a      L   api/Resources/cache/ContainerLiF9Qbu/getMissingPackagesControllerService.php>  Qti>  MR?      U   api/Resources/cache/ContainerLiF9Qbu/getConsole_Command_SecretsGenerateKeyService.php8  Qti8  ¤      =   api/Resources/cache/ContainerLiF9Qbu/getUpdateTaskService.phpZ  QtiZ  s0      T   api/Resources/cache/ContainerLiF9Qbu/get_Console_Command_SecretsList_LazyService.php  Qti  ڤ      A   api/Resources/cache/ContainerLiF9Qbu/getComposerConfigService.php  Qti  x3      Z   api/Resources/cache/ContainerLiF9Qbu/getConsole_Command_SecretsEncryptFromLocalService.php`  Qti`  Q      J   api/Resources/cache/ContainerLiF9Qbu/getSecurity_AccessListenerService.php  Qti  ɲФ      Q   api/Resources/cache/ContainerLiF9Qbu/getConsole_Command_CachePoolPruneService.php  Qti  Қ}      Z   api/Resources/cache/ContainerLiF9Qbu/get_Security_Command_UserPasswordHash_LazyService.php1  Qti1  4      N   api/Resources/cache/ContainerLiF9Qbu/getSecurity_RouteLoader_LogoutService.php  Qti  jx      T   api/Resources/cache/ContainerLiF9Qbu/get_Console_Command_ConfigDebug_LazyService.php  Qti  gC%      e   api/Resources/cache/ContainerLiF9Qbu/getContaoManager_Security_AuthenticationTrustResolverService.php  Qti  e      E   api/Resources/cache/ContainerLiF9Qbu/getDatabaseControllerService.php~  Qti~  jl      X   api/Resources/cache/ContainerLiF9Qbu/getConsole_Command_SecretsDecryptToLocalService.phpd  Qtid  
c      J   api/Resources/cache/ContainerLiF9Qbu/getLocalPackagesControllerService.php4  Qti4  ޢ      ?   api/Resources/cache/ContainerLiF9Qbu/getAboutCommandService.php  Qti  /%      H   api/Resources/cache/ContainerLiF9Qbu/getTaskAbortCommand_LazyService.php  Qti  B      V   api/Resources/cache/ContainerLiF9Qbu/getSecurity_SecurityTokenValueResolverService.php@  Qti@  ˤ      E   api/Resources/cache/ContainerLiF9Qbu/getTokenAuthenticatorService.phpY  QtiY  +w=      R   api/Resources/cache/ContainerLiF9Qbu/getConsole_Command_DebugAutowiringService.php  Qti  _Ф      =   api/Resources/cache/ContainerLiF9Qbu/getServerInfoService.php]  Qti]  -k_U      N   api/Resources/cache/ContainerLiF9Qbu/getConsole_Command_RouterMatchService.php  Qti  Ft      M   api/Resources/cache/ContainerLiF9Qbu/getIntegrityCheckCommand_LazyService.php   Qti   Uh*      J   api/Resources/cache/ContainerLiF9Qbu/get_ServiceLocator_AH5O6SdService.php`  Qti`  %]g      B   api/Resources/cache/ContainerLiF9Qbu/getErrorControllerService.php  Qti  {|      J   api/Resources/cache/ContainerLiF9Qbu/get_ServiceLocator_EZsc_DOService.phpZ  QtiZ  Dx      S   api/Resources/cache/ContainerLiF9Qbu/get_Console_Command_CacheClear_LazyService.php  Qti  ~      K   api/Resources/cache/ContainerLiF9Qbu/getArgumentResolver_RequestService.php  Qti  uOc      P   api/Resources/cache/ContainerLiF9Qbu/RequestPayloadValueResolverGhost8d82153.phpR  QtiR        H   api/Resources/cache/ContainerLiF9Qbu/getConsole_Command_AboutService.php  Qti  3      C   api/Resources/cache/ContainerLiF9Qbu/getDumpAutoloadTaskService.php  Qti        V   api/Resources/cache/ContainerLiF9Qbu/get_Console_Command_ContainerLint_LazyService.php3  Qti3  .j̤      N   api/Resources/cache/ContainerLiF9Qbu/getConsole_Command_ConfigDebugService.php  Qti  x      #   api/Resources/cache/annotations.map  Qti  ;҂      "   api/Resources/config/services.yaml  Qti  Q]      $   api/Resources/config/config_dev.yaml  Qti        %   api/Resources/config/config_prod.yaml   Qti   H          api/Resources/config/config.yaml*  Qti*  "H         api/Resources/i18n/cs.yml  Qti  Ւ         api/Resources/i18n/br.yml  Qti           api/Resources/i18n/es.ymlj  Qtij  X?         api/Resources/i18n/pt.yml  Qti  hǤ         api/Resources/i18n/de.yml  Qti  V=         api/Resources/i18n/it.yml  Qti  `         api/Resources/i18n/pl.yml  Qti  Kޤ         api/Resources/i18n/fa.yml;	  Qti;	  1,         api/Resources/i18n/sv.ymlN  QtiN  tGDW         api/Resources/i18n/en.ymlm  Qtim  hDh>         api/Resources/i18n/ja.yml  Qti  8E~         api/Resources/i18n/ru.yml  Qti  (         api/Resources/i18n/sr.yml  Qti  jU         api/Resources/i18n/fr.ymlD  QtiD           api/Resources/i18n/lv.yml  Qti           api/Resources/i18n/tr.yml  Qti  ݇         api/Resources/i18n/nl.ymlo  Qtio  p         api/Resources/i18n/zh.yml  Qti  ^a         api/ApiApplication.php  Qti  ]      #   api/Tests/Composer/CloudJobTest.php  Qti  h      '   api/Tests/Controller/LogPatternTest.php1/  Qti1/  }/      !   api/Controller/FileController.phpy  Qtiy  :u      !   api/Controller/UserController.php=  Qti=  و          api/Controller/LogController.php  Qti  fz      (   api/Controller/Config/AuthController.php  Qti        2   api/Controller/Config/AbstractConfigController.php  Qti  V      ,   api/Controller/Config/ComposerController.php  Qti  a)      +   api/Controller/Config/ManagerController.php  Qti  _      !   api/Controller/TaskController.php  Qti  ''      *   api/Controller/Server/PhpWebController.php  Qti  P	      *   api/Controller/Server/ContaoController.php!  Qti!  9}      ,   api/Controller/Server/DatabaseController.phpQ  QtiQ  ,&      -   api/Controller/Server/AdminUserController.phpe  Qtie  gN      +   api/Controller/Server/PhpinfoController.php   Qti   ZФ      +   api/Controller/Server/OpcacheController.phpx  Qtix  *	      *   api/Controller/Server/ConfigController.php  Qti        ,   api/Controller/Server/ComposerController.php  Qti        *   api/Controller/Server/PhpCliController.php'  Qti'  v'      .   api/Controller/Server/SelfUpdateController.phpo  Qtio  A3      $   api/Controller/SessionController.php  Qti  ?F
      5   api/Controller/Packages/MissingPackagesController.php	  Qti	  4N      4   api/Controller/Packages/UploadPackagesController.php9(  Qti9(  M.      1   api/Controller/Packages/RootPackageController.php  Qti  1Py,      +   api/Controller/Packages/CloudController.php  Qti  T      3   api/Controller/Packages/LocalPackagesController.php  Qti  F%k      '   api/Controller/ConstraintController.php  Qti  Iؤ      3   api/Controller/Contao/InstallToolLockController.php
  Qti
  4/m      5   api/Controller/Contao/DatabaseMigrationController.phpn%  Qtin%  G0d      -   api/Controller/Contao/AccessKeyController.php  Qti  [ c      *   api/Controller/Contao/BackupController.php  Qti  %T      3   api/Controller/Contao/MaintenanceModeController.php  Qti  /6X      -   api/Controller/Contao/JwtCookieController.php+  Qti+  NV         api/ApiKernel.php!&  Qti!&  	q         api/System/ServerInfo.phpP  QtiP  GC         api/System/Request.phpG  QtiG  '9         api/System/SelfUpdate.php$  Qti$  9lߤ         api/Task/TaskStatus.php,  Qti,  Y|y      &   api/Task/Composer/DumpAutoloadTask.php  Qti  u      $   api/Task/Composer/ClearCacheTask.php  Qti  w      #   api/Task/Manager/SelfUpdateTask.php  Qti  DĤ         api/Task/AbstractTask.php  Qti  
         api/Task/Packages/SetupTask.php  Qti   v          api/Task/Packages/UpdateTask.php+  Qti+  w      !   api/Task/Packages/InstallTask.php*  Qti*  ڷ퀤      *   api/Task/Packages/AbstractPackagesTask.php
  Qti
  .ZK      $   api/Task/Contao/BackupCreateTask.php  Qti  @.v      %   api/Task/Contao/BackupRestoreTask.php  Qti  \z      $   api/Task/Contao/RebuildCacheTask.php  Qti  %         api/Task/TaskManager.php  Qti  F-C         api/Task/TaskInterface.php  Qti  ~3         api/Task/TaskConfig.php	  Qti	  {y=      %   api/Command/IntegrityCheckCommand.phpX	  QtiX	  ^W         api/Command/UpdateCommand.phpP  QtiP  $           api/Command/TaskAbortCommand.php  Qti  Z      !   api/Command/TaskUpdateCommand.phpA  QtiA  d/l      $   api/Command/ProcessRunnerCommand.phpA  QtiA  nnl         api/Command/AboutCommand.phpQ  QtiQ  Hz      !   api/Command/TaskDeleteCommand.php+  Qti+  Ĥ         api/I18n/Translator.php
  Qti
  ju      %   api/Exception/ApiProblemException.php4  Qti4  F0x      (   api/Exception/ProcessOutputException.php  Qti  	[      &   api/Exception/InvalidTotpException.php  Qti  M      &   api/Exception/InvalidJsonException.php  Qti  iR      "   api/Exception/RequestException.php  Qti  k%      )   api/IntegrityCheck/AllowUrlFopenCheck.php$  Qti$  꽤      '   api/IntegrityCheck/GraphicsLibCheck.php  Qti  Z{         api/IntegrityCheck/ZipCheck.php  Qti  x1A      &   api/IntegrityCheck/SysTempDirCheck.php  Qti  {x      .   api/IntegrityCheck/IntegrityCheckInterface.php}  Qti}        #   api/IntegrityCheck/ProcessCheck.php  Qti  ?      #   api/IntegrityCheck/SymlinkCheck.php  Qti  ɶ      #   api/IntegrityCheck/SessionCheck.php  Qti        '   api/IntegrityCheck/MemoryLimitCheck.phpE  QtiE  .d      )   api/IntegrityCheck/PhpExtensionsCheck.php  Qti  )      -   api/IntegrityCheck/AbstractIntegrityCheck.php  Qti  Z@      ,   api/IntegrityCheck/IntegrityCheckFactory.php  Qti  I         api/Process/ContaoApi.php8  Qti8  YO0      !   api/Process/ProcessController.php  Qti  W.      %   api/Process/Forker/AbstractForker.php
  Qti
  ^      &   api/Process/Forker/ForkerInterface.phph  Qtih         #   api/Process/Forker/DisownForker.php  Qti  ,      "   api/Process/Forker/NohupForker.php  Qti  ]e      )   api/Process/Forker/WindowsStartForker.php  Qti  D(      #   api/Process/Forker/InlineForker.php  Qti  [         api/Process/Utf8Process.phpp  Qtip           api/Process/ProcessRunner.phpy  Qtiy  $         api/Process/AbstractProcess.php  Qti  P<         api/Process/ContaoConsole.php   Qti   =      #   api/Process/PhpExecutableFinder.php  Qti  ä      %   api/Process/ConsoleProcessFactory.phpL  QtiL  0         api/console8  Qti8  i.      $   api/EventListener/LocaleListener.php  Qti  yݤ      '   api/EventListener/ExceptionListener.php?
  Qti?
        &   api/EventListener/SecurityListener.php  Qti  hR+Ф      '   api/EventListener/CheckTotpListener.php  Qti        )   api/EventListener/JsonRequestListener.php  Qti           downgrade.php63  Qti63  O      $   vendor/seld/phar-utils/composer.lock/  Qti/  cւ(         vendor/seld/phar-utils/LICENSE"  Qti"  ?e          vendor/seld/phar-utils/README.mde  Qtie  :N      $   vendor/seld/phar-utils/composer.json;  Qti;  =      %   vendor/seld/phar-utils/src/Linter.php  Qti  dȋ      )   vendor/seld/phar-utils/src/Timestamps.phpP  QtiP  Y         vendor/seld/jsonlint/LICENSE"  Qti"  asy      !   vendor/seld/jsonlint/bin/jsonlint  Qti  ƀ      !   vendor/seld/jsonlint/CHANGELOG.md	  Qti	  ݣʤ         vendor/seld/jsonlint/README.md  Qti  f      "   vendor/seld/jsonlint/composer.jsonU  QtiU  TR      @   vendor/seld/jsonlint/src/Seld/JsonLint/DuplicateKeyException.php  Qti  ArQ      ;   vendor/seld/jsonlint/src/Seld/JsonLint/ParsingException.php  Qti  m2;      0   vendor/seld/jsonlint/src/Seld/JsonLint/Lexer.phpn"  Qtin"  U      4   vendor/seld/jsonlint/src/Seld/JsonLint/Undefined.php*  Qti*        5   vendor/seld/jsonlint/src/Seld/JsonLint/JsonParser.php_  Qti_  }@      "   vendor/seld/signal-handler/LICENSE"  Qti"  ?e      (   vendor/seld/signal-handler/composer.json  Qti  c      0   vendor/seld/signal-handler/src/SignalHandler.phpO  QtiO  +Ҥ         vendor/autoload.php  Qti  ,V:      $   vendor/phpstan/phpdoc-parser/LICENSEQ  QtiQ  w      &   vendor/phpstan/phpdoc-parser/README.md  Qti  {N      )   vendor/phpstan/phpdoc-parser/UPGRADING.md#  Qti#  &~g      *   vendor/phpstan/phpdoc-parser/composer.json  Qti  R	      0   vendor/phpstan/phpdoc-parser/src/Lexer/Lexer.php  Qti  >7      5   vendor/phpstan/phpdoc-parser/src/Printer/DiffElem.php  Qti        3   vendor/phpstan/phpdoc-parser/src/Printer/Differ.phpe  Qtie  t      4   vendor/phpstan/phpdoc-parser/src/Printer/Printer.php&  Qti&  }{Ѥ      ;   vendor/phpstan/phpdoc-parser/src/Parser/ParserException.php	  Qti	  4      8   vendor/phpstan/phpdoc-parser/src/Parser/PhpDocParser.php  Qti  tѤ      ;   vendor/phpstan/phpdoc-parser/src/Parser/ConstExprParser.php!  Qti!  o)      ;   vendor/phpstan/phpdoc-parser/src/Parser/StringUnescaper.phpW
  QtiW
  ۔I       6   vendor/phpstan/phpdoc-parser/src/Parser/TypeParser.phpٔ  Qtiٔ  ĮP      9   vendor/phpstan/phpdoc-parser/src/Parser/TokenIterator.php)  Qti)  K:      1   vendor/phpstan/phpdoc-parser/src/ParserConfig.php`  Qti`  Kä      V   vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/PureUnlessCallableIsImpureTagValueNode.phpe  Qtie  <,      A   vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/MixinTagValueNode.phpY  QtiY  OWҤ      D   vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/TemplateTagValueNode.php'  Qti'  <1      B   vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/AssertTagValueNode.php?  Qti?  Z      B   vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/ThrowsTagValueNode.phpZ  QtiZ  \<J      U   vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/ParamLaterInvokedCallableTagValueNode.phpd  Qtid  ߤ      B   vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/PhpDocTagValueNode.php   Qti   ck      J   vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/AssertTagPropertyValueNode.php  Qti  <x)M      M   vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/RequireImplementsTagValueNode.phpe  Qtie  8)      B   vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/SealedTagValueNode.phpZ  QtiZ  5      F   vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/ImplementsTagValueNode.phps  Qtis  'ʤ      >   vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/PhpDocTextNode.php@  Qti@  gNm      :   vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/PhpDocNode.php,  Qti,  Kz;      L   vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/ParamClosureThisTagValueNode.php  Qti  Ou2Ԥ      C   vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/GenericTagValueNode.phpt  Qtit  VϤ      E   vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/TypeAliasTagValueNode.php  Qti  v{Ф      B   vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/ReturnTagValueNode.phpZ  QtiZ  >      @   vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/UsesTagValueNode.phpm  Qtim  #      K   vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/MethodTagValueParameterNode.php@  Qti@  
e      I   vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/Doctrine/DoctrineArgument.php  Qti  ,Md0      K   vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/Doctrine/DoctrineAnnotation.php  Qti  	㺤      M   vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/Doctrine/DoctrineTagValueNode.php  Qti  A      J   vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/Doctrine/DoctrineArrayItem.phpd  Qtid        F   vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/Doctrine/DoctrineArray.php"  Qti"  HdD      C   vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/InvalidTagValueNode.php  Qti  bAL      ?   vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/VarTagValueNode.php  Qti  -      =   vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/PhpDocTagNode.php  Qti  re      D   vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/ParamOutTagValueNode.php  Qti  A      I   vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/TypelessParamTagValueNode.php  Qti  S       H   vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/AssertTagMethodValueNode.php  Qti  \פ      K   vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/TypeAliasImportTagValueNode.php\  Qti\   fV      D   vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/PropertyTagValueNode.php  Qti  <l<      [   vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/ParamImmediatelyInvokedCallableTagValueNode.phpj  Qtij  Gy      ?   vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/PhpDocChildNode.php   Qti   )5Q      C   vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/ExtendsTagValueNode.phpp  Qtip        A   vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/ParamTagValueNode.php`  Qti`  /      B   vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/MethodTagValueNode.php  Qti  s      C   vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/SelfOutTagValueNode.php]  Qti]  Q      F   vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/DeprecatedTagValueNode.php  Qti  x_      J   vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/RequireExtendsTagValueNode.phpb  Qtib   譤      A   vendor/phpstan/phpdoc-parser/src/Ast/ConstExpr/ConstFetchNode.phpz  Qtiz  n      E   vendor/phpstan/phpdoc-parser/src/Ast/ConstExpr/ConstExprArrayNode.php  Qti  8X      @   vendor/phpstan/phpdoc-parser/src/Ast/ConstExpr/ConstExprNode.php   Qti         F   vendor/phpstan/phpdoc-parser/src/Ast/ConstExpr/ConstExprStringNode.php  Qti  qt      D   vendor/phpstan/phpdoc-parser/src/Ast/ConstExpr/ConstExprTrueNode.php  Qti  XSe
      G   vendor/phpstan/phpdoc-parser/src/Ast/ConstExpr/ConstExprIntegerNode.phpM  QtiM  [h      E   vendor/phpstan/phpdoc-parser/src/Ast/ConstExpr/ConstExprFalseNode.php  Qti  V      I   vendor/phpstan/phpdoc-parser/src/Ast/ConstExpr/ConstExprArrayItemNode.phpV  QtiV  ƫ      D   vendor/phpstan/phpdoc-parser/src/Ast/ConstExpr/ConstExprNullNode.php  Qti  Yn      N   vendor/phpstan/phpdoc-parser/src/Ast/ConstExpr/DoctrineConstExprStringNode.php  Qti  e^      E   vendor/phpstan/phpdoc-parser/src/Ast/ConstExpr/ConstExprFloatNode.phpK  QtiK  FB      4   vendor/phpstan/phpdoc-parser/src/Ast/NodeVisitor.php
  Qti
  Y? Ȥ      C   vendor/phpstan/phpdoc-parser/src/Ast/NodeVisitor/CloningVisitor.php  Qti  6֢Ƥ      2   vendor/phpstan/phpdoc-parser/src/Ast/Attribute.phpp  Qtip  B      -   vendor/phpstan/phpdoc-parser/src/Ast/Node.php  Qti  Q\      ;   vendor/phpstan/phpdoc-parser/src/Ast/Type/UnionTypeNode.php  Qti  եd      B   vendor/phpstan/phpdoc-parser/src/Ast/Type/IntersectionTypeNode.php  Qti  d      @   vendor/phpstan/phpdoc-parser/src/Ast/Type/IdentifierTypeNode.php;  Qti;  Kl      @   vendor/phpstan/phpdoc-parser/src/Ast/Type/ArrayShapeItemNode.php  Qti  㑤      ;   vendor/phpstan/phpdoc-parser/src/Ast/Type/ConstTypeNode.php  Qti        G   vendor/phpstan/phpdoc-parser/src/Ast/Type/CallableTypeParameterNode.php  Qti  Ф      >   vendor/phpstan/phpdoc-parser/src/Ast/Type/CallableTypeNode.phpn  Qtin  R	g      6   vendor/phpstan/phpdoc-parser/src/Ast/Type/TypeNode.php   Qti   9      A   vendor/phpstan/phpdoc-parser/src/Ast/Type/ObjectShapeItemNode.php  Qti  ug^      :   vendor/phpstan/phpdoc-parser/src/Ast/Type/ThisTypeNode.php  Qti        =   vendor/phpstan/phpdoc-parser/src/Ast/Type/ObjectShapeNode.php  Qti  />      =   vendor/phpstan/phpdoc-parser/src/Ast/Type/InvalidTypeNode.phpB  QtiB        B   vendor/phpstan/phpdoc-parser/src/Ast/Type/OffsetAccessTypeNode.phps  Qtis  Eͤ      A   vendor/phpstan/phpdoc-parser/src/Ast/Type/ConditionalTypeNode.php}  Qti}  A'      H   vendor/phpstan/phpdoc-parser/src/Ast/Type/ArrayShapeUnsealedTypeNode.php  Qti  {^Ҥ      M   vendor/phpstan/phpdoc-parser/src/Ast/Type/ConditionalTypeForParameterNode.php  Qti  QFCU      >   vendor/phpstan/phpdoc-parser/src/Ast/Type/NullableTypeNode.phpC  QtiC  ڢ      <   vendor/phpstan/phpdoc-parser/src/Ast/Type/ArrayShapeNode.php  Qti  "Ԥ      =   vendor/phpstan/phpdoc-parser/src/Ast/Type/GenericTypeNode.php  Qti        ;   vendor/phpstan/phpdoc-parser/src/Ast/Type/ArrayTypeNode.php  Qti  9Ĥ      <   vendor/phpstan/phpdoc-parser/src/Ast/AbstractNodeVisitor.php  Qti  ~]      0   vendor/phpstan/phpdoc-parser/src/Ast/Comment.php  Qti  7      7   vendor/phpstan/phpdoc-parser/src/Ast/NodeAttributes.php)  Qti)  mm      6   vendor/phpstan/phpdoc-parser/src/Ast/NodeTraverser.php*  Qti*  <         vendor/lcobucci/clock/LICENSE.  Qti.  >z      #   vendor/lcobucci/clock/renovate.json   Qti   ]G(      #   vendor/lcobucci/clock/composer.json,  Qti,  ;      #   vendor/lcobucci/clock/src/Clock.php   Qti   \      )   vendor/lcobucci/clock/src/FrozenClock.php'  Qti'  1      )   vendor/lcobucci/clock/src/SystemClock.php  Qti  VK         vendor/bin/yaml-lint  Qti  hT      "   vendor/bin/patch-type-declarationsH  QtiH  8b         vendor/bin/validate-json  Qti  ֍&          vendor/bin/composer  Qti  %5         vendor/bin/var-dump-server'  Qti'           vendor/bin/jsonlint  Qti  `~      .   vendor/marc-mabe/php-enum/stubs/Stringable.php  Qti  e6      #   vendor/marc-mabe/php-enum/README.md	>  Qti	>  FhU      %   vendor/marc-mabe/php-enum/LICENSE.txt  Qti  CѤ      '   vendor/marc-mabe/php-enum/composer.json"  Qti"  6~)      7   vendor/marc-mabe/php-enum/src/EnumSerializableTrait.php  Qti  eޤ      &   vendor/marc-mabe/php-enum/src/Enum.php7  Qti7  ;`d      )   vendor/marc-mabe/php-enum/src/EnumMap.php9-  Qti9-  ک6      )   vendor/marc-mabe/php-enum/src/EnumSet.php  Qti  ߲!      $   vendor/web-auth/webauthn-lib/LICENSE1  Qti1  2      *   vendor/web-auth/webauthn-lib/composer.json	  Qti	  =K      <   vendor/web-auth/webauthn-lib/src/FakeCredentialGenerator.php0  Qti0  5ܤ      1   vendor/web-auth/webauthn-lib/src/StringStream.php!  Qti!  4(      @   vendor/web-auth/webauthn-lib/src/CeremonyStep/CheckAlgorithm.php   Qti   %ڤ      D   vendor/web-auth/webauthn-lib/src/CeremonyStep/TopOriginValidator.php   Qti   $j      A   vendor/web-auth/webauthn-lib/src/CeremonyStep/CheckUserHandle.php  Qti  V+:u      P   vendor/web-auth/webauthn-lib/src/CeremonyStep/CheckHasAttestedCredentialData.phpB  QtiB        E   vendor/web-auth/webauthn-lib/src/CeremonyStep/CeremonyStepManager.php  Qti  .U      G   vendor/web-auth/webauthn-lib/src/CeremonyStep/CheckUserVerification.php2  Qti2  ?v      L   vendor/web-auth/webauthn-lib/src/CeremonyStep/CheckAllowedCredentialList.php  Qti  
      C   vendor/web-auth/webauthn-lib/src/CeremonyStep/CheckCredentialId.php  Qti  %      W   vendor/web-auth/webauthn-lib/src/CeremonyStep/CheckAttestationFormatIsKnownAndValid.phpF  QtiF  덤      @   vendor/web-auth/webauthn-lib/src/CeremonyStep/CheckSignature.php  Qti  $      H   vendor/web-auth/webauthn-lib/src/CeremonyStep/HostTopOriginValidator.php	  Qti	  24Ϥ      K   vendor/web-auth/webauthn-lib/src/CeremonyStep/CheckRelyingPartyIdIdHash.php
  Qti
  Oۜ      N   vendor/web-auth/webauthn-lib/src/CeremonyStep/CheckBackupBitsAreConsistent.php  Qti  /nK      E   vendor/web-auth/webauthn-lib/src/CeremonyStep/CheckUserWasPresent.php  Qti  U      N   vendor/web-auth/webauthn-lib/src/CeremonyStep/CheckClientDataCollectorType.php  Qti  ݷgڤ      @   vendor/web-auth/webauthn-lib/src/CeremonyStep/CheckChallenge.php  Qti  fX      >   vendor/web-auth/webauthn-lib/src/CeremonyStep/CeremonyStep.php  Qti  "      >   vendor/web-auth/webauthn-lib/src/CeremonyStep/CheckCounter.php  Qti  Ԥ      @   vendor/web-auth/webauthn-lib/src/CeremonyStep/CheckTopOrigin.php  Qti  4u      =   vendor/web-auth/webauthn-lib/src/CeremonyStep/CheckOrigin.php  Qti  
~      A   vendor/web-auth/webauthn-lib/src/CeremonyStep/CheckExtensions.phps  Qtis  X      H   vendor/web-auth/webauthn-lib/src/CeremonyStep/CheckMetadataStatement.php   Qti   B       L   vendor/web-auth/webauthn-lib/src/CeremonyStep/CeremonyStepManagerFactory.php  Qti  }2      B   vendor/web-auth/webauthn-lib/src/PublicKeyCredentialUserEntity.php  Qti  R_      7   vendor/web-auth/webauthn-lib/src/CertificateToolbox.php  Qti  µ      V   vendor/web-auth/webauthn-lib/src/AuthenticationExtensions/AuthenticationExtensions.phpp  Qtip        [   vendor/web-auth/webauthn-lib/src/AuthenticationExtensions/ExtensionOutputCheckerHandler.phpz  Qtiz  
      b   vendor/web-auth/webauthn-lib/src/AuthenticationExtensions/AuthenticationExtensionsClientInputs.php  Qti  `i      R   vendor/web-auth/webauthn-lib/src/AuthenticationExtensions/ExtensionOutputError.php  Qti  >      U   vendor/web-auth/webauthn-lib/src/AuthenticationExtensions/AuthenticationExtension.php	  Qti	  '^      T   vendor/web-auth/webauthn-lib/src/AuthenticationExtensions/ExtensionOutputChecker.php   Qti   	      c   vendor/web-auth/webauthn-lib/src/AuthenticationExtensions/AuthenticationExtensionsClientOutputs.php  Qti  QT      i   vendor/web-auth/webauthn-lib/src/AuthenticationExtensions/AuthenticationExtensionsClientOutputsLoader.php  Qti  3      e   vendor/web-auth/webauthn-lib/src/AttestationStatement/AndroidSafetyNetAttestationStatementSupport.php6  Qti6  Eww      \   vendor/web-auth/webauthn-lib/src/AttestationStatement/FidoU2FAttestationStatementSupport.phpQ  QtiQ        Z   vendor/web-auth/webauthn-lib/src/AttestationStatement/AppleAttestationStatementSupport.phpG  QtiG  Q      Y   vendor/web-auth/webauthn-lib/src/AttestationStatement/NoneAttestationStatementSupport.phpu  Qtiu  8ʤ      U   vendor/web-auth/webauthn-lib/src/AttestationStatement/AttestationStatementSupport.php  Qti  `      Q   vendor/web-auth/webauthn-lib/src/AttestationStatement/AttestationObjectLoader.php  Qti  \       [   vendor/web-auth/webauthn-lib/src/AttestationStatement/PackedAttestationStatementSupport.php+  Qti+  W      K   vendor/web-auth/webauthn-lib/src/AttestationStatement/AttestationObject.php  Qti  J      _   vendor/web-auth/webauthn-lib/src/AttestationStatement/AndroidKeyAttestationStatementSupport.phpC"  QtiC"  e      \   vendor/web-auth/webauthn-lib/src/AttestationStatement/AttestationStatementSupportManager.php  Qti  4      X   vendor/web-auth/webauthn-lib/src/AttestationStatement/TPMAttestationStatementSupport.php=  Qti=  cTx      N   vendor/web-auth/webauthn-lib/src/AttestationStatement/AttestationStatement.php  Qti        >   vendor/web-auth/webauthn-lib/src/PublicKeyCredentialLoader.php  Qti  nX      B   vendor/web-auth/webauthn-lib/src/SimpleFakeCredentialGenerator.php  Qti  gph!      >   vendor/web-auth/webauthn-lib/src/TokenBinding/TokenBinding.php  Qti  &B      H   vendor/web-auth/webauthn-lib/src/TokenBinding/SecTokenBindingHandler.php  Qti        K   vendor/web-auth/webauthn-lib/src/TokenBinding/IgnoreTokenBindingHandler.php  Qti  VQ+      Q   vendor/web-auth/webauthn-lib/src/TokenBinding/TokenBindingNotSupportedHandler.php  Qti  դ      E   vendor/web-auth/webauthn-lib/src/TokenBinding/TokenBindingHandler.phpg  Qtig  ,7      <   vendor/web-auth/webauthn-lib/src/Util/CoseSignatureFixer.php\  Qti\  ̿      0   vendor/web-auth/webauthn-lib/src/Util/Base64.phpr  Qtir  4kb      ;   vendor/web-auth/webauthn-lib/src/AttestedCredentialData.php  Qti  PŤ      /   vendor/web-auth/webauthn-lib/src/Credential.php  Qti  ~      N   vendor/web-auth/webauthn-lib/src/AuthenticatorAttestationResponseValidator.phpQ2  QtiQ2  %      B   vendor/web-auth/webauthn-lib/src/PublicKeyCredentialParameters.php		  Qti		  >t      B   vendor/web-auth/webauthn-lib/src/PublicKeyCredentialDescriptor.php  Qti  
      @   vendor/web-auth/webauthn-lib/src/PublicKeyCredentialRpEntity.phpS  QtiS  F      E   vendor/web-auth/webauthn-lib/src/AuthenticatorAttestationResponse.php  Qti  qѩ      ?   vendor/web-auth/webauthn-lib/src/PublicKeyCredentialOptions.php  Qti  o      6   vendor/web-auth/webauthn-lib/src/AuthenticatorData.phpa  Qtia  yޤ      L   vendor/web-auth/webauthn-lib/src/PublicKeyCredentialDescriptorCollection.php  Qti  (v      :   vendor/web-auth/webauthn-lib/src/AuthenticatorResponse.php  Qti  [פ      L   vendor/web-auth/webauthn-lib/src/AuthenticatorAssertionResponseValidator.php0  Qti0  RM      C   vendor/web-auth/webauthn-lib/src/AuthenticatorAssertionResponse.php:  Qti:  <'      W   vendor/web-auth/webauthn-lib/src/CertificateChainChecker/PhpCertificateChainChecker.php  Qti  {Ϥ      T   vendor/web-auth/webauthn-lib/src/CertificateChainChecker/CertificateChainChecker.php  Qti  2Ƥ      F   vendor/web-auth/webauthn-lib/src/PublicKeyCredentialRequestOptions.php!  Qti!  ܤ      <   vendor/web-auth/webauthn-lib/src/AuthenticatorDataLoader.phpu  Qtiu  ӌI      H   vendor/web-auth/webauthn-lib/src/PublicKeyCredentialSourceRepository.php  Qti        >   vendor/web-auth/webauthn-lib/src/TrustPath/TrustPathLoader.php  Qti  }      B   vendor/web-auth/webauthn-lib/src/TrustPath/EcdaaKeyIdTrustPath.php  Qti  h      8   vendor/web-auth/webauthn-lib/src/TrustPath/TrustPath.php  Qti        =   vendor/web-auth/webauthn-lib/src/TrustPath/EmptyTrustPath.php  Qti  F0)1      C   vendor/web-auth/webauthn-lib/src/TrustPath/CertificateTrustPath.php  Qti  ߤ      >   vendor/web-auth/webauthn-lib/src/PublicKeyCredentialEntity.php|  Qti|  fJ      L   vendor/web-auth/webauthn-lib/src/ClientDataCollector/ClientDataCollector.php?  Qti?  PkNv      S   vendor/web-auth/webauthn-lib/src/ClientDataCollector/ClientDataCollectorManager.php  Qti  8;ۤ      X   vendor/web-auth/webauthn-lib/src/ClientDataCollector/WebauthnAuthenticationCollector.php  Qti  2fo      D   vendor/web-auth/webauthn-lib/src/Counter/ThrowExceptionIfInvalid.phpu  Qtiu  9      ;   vendor/web-auth/webauthn-lib/src/Counter/CounterChecker.php  Qti  b      V   vendor/web-auth/webauthn-lib/src/Denormalizer/AuthenticationExtensionsDenormalizer.php	  Qti	  N<      R   vendor/web-auth/webauthn-lib/src/Denormalizer/AttestationStatementDenormalizer.php  Qti        S   vendor/web-auth/webauthn-lib/src/Denormalizer/AuthenticationExtensionNormalizer.php  Qti  @H      G   vendor/web-auth/webauthn-lib/src/Denormalizer/TrustPathDenormalizer.php  Qti  f <      Q   vendor/web-auth/webauthn-lib/src/Denormalizer/PublicKeyCredentialDenormalizer.php  Qti  h      K   vendor/web-auth/webauthn-lib/src/Denormalizer/WebauthnSerializerFactory.phpC  QtiC  `B      Q   vendor/web-auth/webauthn-lib/src/Denormalizer/CollectedClientDataDenormalizer.php  Qti  *3uŤ      [   vendor/web-auth/webauthn-lib/src/Denormalizer/PublicKeyCredentialParametersDenormalizer.php  Qti  E      ^   vendor/web-auth/webauthn-lib/src/Denormalizer/AuthenticatorAttestationResponseDenormalizer.php7  Qti7  ֢i      R   vendor/web-auth/webauthn-lib/src/Denormalizer/AttestedCredentialDataNormalizer.phpe  Qtie  4g      Y   vendor/web-auth/webauthn-lib/src/Denormalizer/PublicKeyCredentialDescriptorNormalizer.phpv  Qtiv  1yN      O   vendor/web-auth/webauthn-lib/src/Denormalizer/AuthenticatorDataDenormalizer.php{  Qti{        O   vendor/web-auth/webauthn-lib/src/Denormalizer/AttestationObjectDenormalizer.phpy  Qtiy  :q/      W   vendor/web-auth/webauthn-lib/src/Denormalizer/PublicKeyCredentialSourceDenormalizer.php  Qti  xv      [   vendor/web-auth/webauthn-lib/src/Denormalizer/PublicKeyCredentialUserEntityDenormalizer.php  Qti  P#       Q   vendor/web-auth/webauthn-lib/src/Denormalizer/ExtensionDescriptorDenormalizer.php%  Qti%  1      _   vendor/web-auth/webauthn-lib/src/Denormalizer/VerificationMethodANDCombinationsDenormalizer.php  Qti  Y_Τ      \   vendor/web-auth/webauthn-lib/src/Denormalizer/AuthenticatorAssertionResponseDenormalizer.php  Qti  ZS      S   vendor/web-auth/webauthn-lib/src/Denormalizer/AuthenticatorResponseDenormalizer.php  Qti  I4¤      X   vendor/web-auth/webauthn-lib/src/Denormalizer/PublicKeyCredentialOptionsDenormalizer.php  Qti  6      8   vendor/web-auth/webauthn-lib/src/PublicKeyCredential.php  Qti  \      D   vendor/web-auth/webauthn-lib/src/MetadataService/Psr18HttpClient.phpW  QtiW  I` L      K   vendor/web-auth/webauthn-lib/src/MetadataService/StatusReportRepository.php2  Qti2  7Kʤ      _   vendor/web-auth/webauthn-lib/src/MetadataService/CertificateChain/CertificateChainValidator.phpS  QtiS  vx      X   vendor/web-auth/webauthn-lib/src/MetadataService/CertificateChain/CertificateToolbox.php  Qti  g      b   vendor/web-auth/webauthn-lib/src/MetadataService/CertificateChain/PhpCertificateChainValidator.php'  Qti'  ~      ?   vendor/web-auth/webauthn-lib/src/MetadataService/CanLogData.php   Qti   8;      P   vendor/web-auth/webauthn-lib/src/MetadataService/MetadataStatementRepository.php  Qti  skHŤ      R   vendor/web-auth/webauthn-lib/src/MetadataService/Statement/ExtensionDescriptor.php  Qti  Ӥ      U   vendor/web-auth/webauthn-lib/src/MetadataService/Statement/CodeAccuracyDescriptor.php	  Qti	        X   vendor/web-auth/webauthn-lib/src/MetadataService/Statement/PatternAccuracyDescriptor.php	  Qti	  +      P   vendor/web-auth/webauthn-lib/src/MetadataService/Statement/MetadataStatement.phpwQ  QtiwQ  (      S   vendor/web-auth/webauthn-lib/src/MetadataService/Statement/AuthenticatorGetInfo.php  Qti  1b9      `   vendor/web-auth/webauthn-lib/src/MetadataService/Statement/VerificationMethodANDCombinations.php  Qti  B	      T   vendor/web-auth/webauthn-lib/src/MetadataService/Statement/BiometricStatusReport.php  Qti  _1      R   vendor/web-auth/webauthn-lib/src/MetadataService/Statement/AuthenticatorStatus.php  Qti  tT      Q   vendor/web-auth/webauthn-lib/src/MetadataService/Statement/AbstractDescriptor.phpA  QtiA  F      O   vendor/web-auth/webauthn-lib/src/MetadataService/Statement/EcdaaTrustAnchor.php'
  Qti'
        K   vendor/web-auth/webauthn-lib/src/MetadataService/Statement/StatusReport.php*  Qti*  Ƒ      [   vendor/web-auth/webauthn-lib/src/MetadataService/Statement/VerificationMethodDescriptor.php   Qti   }      V   vendor/web-auth/webauthn-lib/src/MetadataService/Statement/AlternativeDescriptions.php&  Qti&  07ه      Z   vendor/web-auth/webauthn-lib/src/MetadataService/Statement/BiometricAccuracyDescriptor.php  Qti  '      F   vendor/web-auth/webauthn-lib/src/MetadataService/Statement/Version.phpP	  QtiP	  o      N   vendor/web-auth/webauthn-lib/src/MetadataService/Statement/RgbPaletteEntry.phpU	  QtiU	  ؆      M   vendor/web-auth/webauthn-lib/src/MetadataService/Statement/RogueListEntry.php  Qti  V      b   vendor/web-auth/webauthn-lib/src/MetadataService/Statement/DisplayPNGCharacteristicsDescriptor.php  Qti        @   vendor/web-auth/webauthn-lib/src/MetadataService/ValueFilter.phpm  Qtim  wo      a   vendor/web-auth/webauthn-lib/src/MetadataService/Denormalizer/ExtensionDescriptorDenormalizer.php  Qti  Ћz      d   vendor/web-auth/webauthn-lib/src/MetadataService/Denormalizer/MetadataStatementSerializerFactory.php  Qti  '7'      a   vendor/web-auth/webauthn-lib/src/MetadataService/Service/FidoAllianceCompliantMetadataService.php'  Qti'  ްݐ      P   vendor/web-auth/webauthn-lib/src/MetadataService/Service/JsonMetadataService.php	  Qti	  o;ˤ      R   vendor/web-auth/webauthn-lib/src/MetadataService/Service/StringMetadataService.php  Qti  y0      U   vendor/web-auth/webauthn-lib/src/MetadataService/Service/MetadataBLOBPayloadEntry.php  Qti  	;      [   vendor/web-auth/webauthn-lib/src/MetadataService/Service/DistantResourceMetadataService.phpv  Qtiv  {      P   vendor/web-auth/webauthn-lib/src/MetadataService/Service/MetadataBLOBPayload.php  Qti  F      L   vendor/web-auth/webauthn-lib/src/MetadataService/Service/MetadataService.php  Qti  Bh      Y   vendor/web-auth/webauthn-lib/src/MetadataService/Service/LocalResourceMetadataService.php  Qti  <6ޤ      T   vendor/web-auth/webauthn-lib/src/MetadataService/Service/ChainedMetadataServices.php  Qti  8      Z   vendor/web-auth/webauthn-lib/src/MetadataService/Service/FolderResourceMetadataService.php
  Qti
  Šu      T   vendor/web-auth/webauthn-lib/src/MetadataService/Service/InMemoryMetadataService.php:  Qti:  oP'      Z   vendor/web-auth/webauthn-lib/src/MetadataService/Exception/InvalidCertificateException.php  Qti  z]      W   vendor/web-auth/webauthn-lib/src/MetadataService/Exception/MetadataServiceException.php  Qti  Y1ص      Z   vendor/web-auth/webauthn-lib/src/MetadataService/Exception/ExpiredCertificateException.php  Qti  g/      S   vendor/web-auth/webauthn-lib/src/MetadataService/Exception/CertificateException.phpq  Qtiq  h      `   vendor/web-auth/webauthn-lib/src/MetadataService/Exception/MissingMetadataStatementException.php  Qti  m %      Z   vendor/web-auth/webauthn-lib/src/MetadataService/Exception/RevokedCertificateException.php  Qti  /      `   vendor/web-auth/webauthn-lib/src/MetadataService/Exception/MetadataStatementLoadingException.php  Qti  /V      Y   vendor/web-auth/webauthn-lib/src/MetadataService/Exception/MetadataStatementException.php  Qti  c       X   vendor/web-auth/webauthn-lib/src/MetadataService/Exception/CertificateChainException.php  Qti  ]ཤ      a   vendor/web-auth/webauthn-lib/src/MetadataService/Exception/CertificateRevocationListException.php  Qti  [      L   vendor/web-auth/webauthn-lib/src/MetadataService/Event/CanDispatchEvents.phpU  QtiU  x      H   vendor/web-auth/webauthn-lib/src/MetadataService/Event/WebauthnEvent.phpA  QtiA  o      [   vendor/web-auth/webauthn-lib/src/MetadataService/Event/BeforeCertificateChainValidation.php  Qti  <s
      [   vendor/web-auth/webauthn-lib/src/MetadataService/Event/CertificateChainValidationFailed.php  Qti  @2      ^   vendor/web-auth/webauthn-lib/src/MetadataService/Event/CertificateChainValidationSucceeded.php  Qti  $      Q   vendor/web-auth/webauthn-lib/src/MetadataService/Event/MetadataStatementFound.phpp  Qtip  3	      N   vendor/web-auth/webauthn-lib/src/MetadataService/Event/NullEventDispatcher.phpa  Qtia  D
      C   vendor/web-auth/webauthn-lib/src/AuthenticatorSelectionCriteria.php:   Qti:   ^K      X   vendor/web-auth/webauthn-lib/src/Exception/AttestationStatementVerificationException.phpm  Qtim  O      J   vendor/web-auth/webauthn-lib/src/Exception/InvalidCertificateException.php  Qti  8ͤ      S   vendor/web-auth/webauthn-lib/src/Exception/InvalidAttestationStatementException.php  Qti  #-      G   vendor/web-auth/webauthn-lib/src/Exception/MetadataServiceException.php1  Qti1  \	      O   vendor/web-auth/webauthn-lib/src/Exception/AuthenticationExtensionException.php9  Qti9  1*      @   vendor/web-auth/webauthn-lib/src/Exception/WebauthnException.php*  Qti*  m2      H   vendor/web-auth/webauthn-lib/src/Exception/InvalidTrustPathException.php2  Qti2  Ki[      Y   vendor/web-auth/webauthn-lib/src/Exception/AuthenticatorResponseVerificationException.php=  Qti=  jz      J   vendor/web-auth/webauthn-lib/src/Exception/ExpiredCertificateException.php~  Qti~  _      J   vendor/web-auth/webauthn-lib/src/Exception/UnsupportedFeatureException.php4  Qti4  Cפ      C   vendor/web-auth/webauthn-lib/src/Exception/CertificateException.phpO  QtiO  Zl      P   vendor/web-auth/webauthn-lib/src/Exception/MissingMetadataStatementException.php:  Qti:  Q
      J   vendor/web-auth/webauthn-lib/src/Exception/RevokedCertificateException.php   Qti   cO      L   vendor/web-auth/webauthn-lib/src/Exception/AttestationStatementException.php   Qti   n      P   vendor/web-auth/webauthn-lib/src/Exception/MetadataStatementLoadingException.phpy  Qtiy  k      ?   vendor/web-auth/webauthn-lib/src/Exception/CounterException.phpK  QtiK  <ܤ      I   vendor/web-auth/webauthn-lib/src/Exception/MetadataStatementException.php   Qti   ng      H   vendor/web-auth/webauthn-lib/src/Exception/CertificateChainException.php  Qti  A      S   vendor/web-auth/webauthn-lib/src/Exception/AttestationStatementLoadingException.php  Qti        C   vendor/web-auth/webauthn-lib/src/Exception/InvalidDataException.php  Qti  bCΤ      Q   vendor/web-auth/webauthn-lib/src/Exception/CertificateRevocationListException.php  Qti  *      I   vendor/web-auth/webauthn-lib/src/Exception/InvalidUserHandleException.phpd  Qtid  V      1   vendor/web-auth/webauthn-lib/src/U2FPublicKey.php  Qti  eۤ      <   vendor/web-auth/webauthn-lib/src/Event/CanDispatchEvents.php  Qti  i`      c   vendor/web-auth/webauthn-lib/src/Event/AuthenticatorAttestationResponseValidationSucceededEvent.php2  Qti2  g~      8   vendor/web-auth/webauthn-lib/src/Event/WebauthnEvent.phpg   Qtig   >G      B   vendor/web-auth/webauthn-lib/src/Event/AttestationObjectLoaded.php  Qti  )[      a   vendor/web-auth/webauthn-lib/src/Event/AuthenticatorAssertionResponseValidationSucceededEvent.php  Qti  d      ^   vendor/web-auth/webauthn-lib/src/Event/AuthenticatorAssertionResponseValidationFailedEvent.php  Qti  lT      K   vendor/web-auth/webauthn-lib/src/Event/BeforeCertificateChainValidation.phpW  QtiW  l      K   vendor/web-auth/webauthn-lib/src/Event/CertificateChainValidationFailed.phpW  QtiW  r"*      N   vendor/web-auth/webauthn-lib/src/Event/CertificateChainValidationSucceeded.phpZ  QtiZ        A   vendor/web-auth/webauthn-lib/src/Event/MetadataStatementFound.php  Qti  i      >   vendor/web-auth/webauthn-lib/src/Event/NullEventDispatcher.php7  Qti7  >      `   vendor/web-auth/webauthn-lib/src/Event/AuthenticatorAttestationResponseValidationFailedEvent.php  Qti  YN      E   vendor/web-auth/webauthn-lib/src/Event/AttestationStatementLoaded.php  Qti  ;%      >   vendor/web-auth/webauthn-lib/src/PublicKeyCredentialSource.php  Qti  $M      G   vendor/web-auth/webauthn-lib/src/PublicKeyCredentialCreationOptions.php])  Qti])  4{      8   vendor/web-auth/webauthn-lib/src/CollectedClientData.phpe  Qtie        +   vendor/web-auth/cose-lib/CODE_OF_CONDUCT.md  Qti  q      $   vendor/web-auth/cose-lib/RELEASES.md  Qti  ]          vendor/web-auth/cose-lib/LICENSE,  Qti,  C      "   vendor/web-auth/cose-lib/README.mdA  QtiA  3:      &   vendor/web-auth/cose-lib/composer.jsonD  QtiD  b/      $   vendor/web-auth/cose-lib/SECURITY.md  Qti  Y{      :   vendor/web-auth/cose-lib/src/Encryption/CoseEncryptTag.php  Qti  ¤      ;   vendor/web-auth/cose-lib/src/Encryption/CoseEncrypt0Tag.php  Qti        %   vendor/web-auth/cose-lib/src/Hash.php  Qti  W      6   vendor/web-auth/cose-lib/src/Signature/CoseSignTag.phpq  Qtiq  Y      7   vendor/web-auth/cose-lib/src/Signature/CoseSign1Tag.php  Qti  )      5   vendor/web-auth/cose-lib/src/Signature/Signature1.phpM  QtiM  Y|      (   vendor/web-auth/cose-lib/src/Key/Key.php#	  Qti#	  ܤ      +   vendor/web-auth/cose-lib/src/Key/RsaKey.php  Qti        1   vendor/web-auth/cose-lib/src/Key/SymmetricKey.php  Qti  vA      +   vendor/web-auth/cose-lib/src/Key/Ec2Key.php  Qti  &}      +   vendor/web-auth/cose-lib/src/Key/OkpKey.php
  Qti
  JoMF      9   vendor/web-auth/cose-lib/src/Algorithm/ManagerFactory.php  Qti  5      @   vendor/web-auth/cose-lib/src/Algorithm/Signature/ECDSA/ES256.php  Qti  f      @   vendor/web-auth/cose-lib/src/Algorithm/Signature/ECDSA/ECDSA.php  Qti  bA      @   vendor/web-auth/cose-lib/src/Algorithm/Signature/ECDSA/ES384.php  Qti  ,      F   vendor/web-auth/cose-lib/src/Algorithm/Signature/ECDSA/ECSignature.php>  Qti>  )ʤ      A   vendor/web-auth/cose-lib/src/Algorithm/Signature/ECDSA/ES256K.php  Qti  ǀyf      @   vendor/web-auth/cose-lib/src/Algorithm/Signature/ECDSA/ES512.php  Qti  r~V      <   vendor/web-auth/cose-lib/src/Algorithm/Signature/RSA/RS1.php  Qti        <   vendor/web-auth/cose-lib/src/Algorithm/Signature/RSA/RSA.php  Qti  4&      >   vendor/web-auth/cose-lib/src/Algorithm/Signature/RSA/RS384.php  Qti  =G      >   vendor/web-auth/cose-lib/src/Algorithm/Signature/RSA/PS256.php  Qti  Z"X~      >   vendor/web-auth/cose-lib/src/Algorithm/Signature/RSA/PS384.php  Qti  ^IT      >   vendor/web-auth/cose-lib/src/Algorithm/Signature/RSA/RS256.php  Qti  d_ޤ      >   vendor/web-auth/cose-lib/src/Algorithm/Signature/RSA/RS512.php  Qti  .K      ?   vendor/web-auth/cose-lib/src/Algorithm/Signature/RSA/PSSRSA.phpH  QtiH  A      >   vendor/web-auth/cose-lib/src/Algorithm/Signature/RSA/PS512.php  Qti  U      @   vendor/web-auth/cose-lib/src/Algorithm/Signature/EdDSA/Ed512.php  Qti  ֢䩤      @   vendor/web-auth/cose-lib/src/Algorithm/Signature/EdDSA/EdDSA.php  Qti  ޤ      @   vendor/web-auth/cose-lib/src/Algorithm/Signature/EdDSA/Ed256.php  Qti  fi      B   vendor/web-auth/cose-lib/src/Algorithm/Signature/EdDSA/Ed25519.php>  Qti>  U      >   vendor/web-auth/cose-lib/src/Algorithm/Signature/Signature.phpT  QtiT  ǔ+D      4   vendor/web-auth/cose-lib/src/Algorithm/Algorithm.php   Qti         4   vendor/web-auth/cose-lib/src/Algorithm/Mac/HS512.php  Qti  1c      3   vendor/web-auth/cose-lib/src/Algorithm/Mac/Hmac.php  Qti  }C`0      2   vendor/web-auth/cose-lib/src/Algorithm/Mac/Mac.phpH  QtiH  k      4   vendor/web-auth/cose-lib/src/Algorithm/Mac/HS384.php  Qti  LԤ      ?   vendor/web-auth/cose-lib/src/Algorithm/Mac/HS256Truncated64.php  Qti  x      4   vendor/web-auth/cose-lib/src/Algorithm/Mac/HS256.php  Qti  =/?      2   vendor/web-auth/cose-lib/src/Algorithm/Manager.php  Qti  Q      +   vendor/web-auth/cose-lib/src/BigInteger.php  Qti  D0&      0   vendor/web-auth/cose-lib/src/Mac/CoseMac0Tag.phpJ  QtiJ  ߤ      /   vendor/web-auth/cose-lib/src/Mac/CoseMacTag.php  Qti        +   vendor/web-auth/cose-lib/src/Algorithms.phpV  QtiV  >賓      '   vendor/composer/autoload_namespaces.php   Qti   /t      &   vendor/composer/xdebug-handler/LICENSE)  Qti)  #;^      +   vendor/composer/xdebug-handler/CHANGELOG.md  Qti  !YsK      (   vendor/composer/xdebug-handler/README.md4  Qti4  S%      ,   vendor/composer/xdebug-handler/composer.jsony  Qtiy  -      0   vendor/composer/xdebug-handler/src/PhpConfig.php  Qti  Zǜ      -   vendor/composer/xdebug-handler/src/Status.php]  Qti]  \%      4   vendor/composer/xdebug-handler/src/XdebugHandler.phpU  QtiU  d      .   vendor/composer/xdebug-handler/src/Process.php<  Qti<  僈      +   vendor/composer/class-map-generator/LICENSE  Qti  DӤ      -   vendor/composer/class-map-generator/README.mdW  QtiW  S~
      1   vendor/composer/class-map-generator/composer.json  Qti  5n      =   vendor/composer/class-map-generator/src/ClassMapGenerator.php6  Qti6  G      :   vendor/composer/class-map-generator/src/PhpFileCleaner.php  Qti  $      4   vendor/composer/class-map-generator/src/FileList.phpa  Qtia  Z(      9   vendor/composer/class-map-generator/src/PhpFileParser.phpf  Qtif        4   vendor/composer/class-map-generator/src/ClassMap.php  Qti  {M         vendor/composer/LICENSE.  Qti.            vendor/composer/ClassLoader.php?  Qti?  2@u      +   vendor/composer/composer/phpstan/rules.neon  Qti  ~d      1   vendor/composer/composer/res/composer-schema.jsonj Qtij '      6   vendor/composer/composer/res/composer-lock-schema.json  Qti  rf      <   vendor/composer/composer/res/composer-repository-schema.json   Qti   븂      &   vendor/composer/composer/composer.lockc Qtic ϱ          vendor/composer/composer/LICENSE,  Qti,  Vg      %   vendor/composer/composer/bin/composer`  Qti`        $   vendor/composer/composer/bin/compile  Qti  I      &   vendor/composer/composer/composer.jsonD  QtiD  64;Q      S   vendor/composer/composer/src/Composer/PHPStan/RuleReasonDataReturnTypeExtension.php
  Qti
  N[      K   vendor/composer/composer/src/Composer/PHPStan/ConfigReturnTypeExtension.php!  Qti!  E?      1   vendor/composer/composer/src/Composer/Factory.php  Qti   \"      H   vendor/composer/composer/src/Composer/Repository/RepositoryInterface.php  Qti  й      R   vendor/composer/composer/src/Composer/Repository/InstalledFilesystemRepository.php  Qti  J=      F   vendor/composer/composer/src/Composer/Repository/PackageRepository.php  Qti  1p      H   vendor/composer/composer/src/Composer/Repository/LockArrayRepository.php  Qti  r,      G   vendor/composer/composer/src/Composer/Repository/PlatformRepository.php8  Qti8  ̴9Ĥ      F   vendor/composer/composer/src/Composer/Repository/RepositoryFactory.php  Qti  ,      Q   vendor/composer/composer/src/Composer/Repository/InstalledRepositoryInterface.php  Qti  +      P   vendor/composer/composer/src/Composer/Repository/WritableRepositoryInterface.php@  Qti@  ek      D   vendor/composer/composer/src/Composer/Repository/RepositoryUtils.php
  Qti
        P   vendor/composer/composer/src/Composer/Repository/RepositorySecurityException.php  Qti  l	Ф      H   vendor/composer/composer/src/Composer/Repository/CompositeRepository.php  Qti  @0>      D   vendor/composer/composer/src/Composer/Repository/ArrayRepository.phpc(  Qtic(  џ      L   vendor/composer/composer/src/Composer/Repository/WritableArrayRepository.php	  Qti	  X      B   vendor/composer/composer/src/Composer/Repository/VcsRepository.phpR  QtiR  iZ-      G   vendor/composer/composer/src/Composer/Repository/ComposerRepository.php Qti X      C   vendor/composer/composer/src/Composer/Repository/PearRepository.php`  Qti`        B   vendor/composer/composer/src/Composer/Repository/RepositorySet.phpF  QtiF  S      G   vendor/composer/composer/src/Composer/Repository/ArtifactRepository.phpT  QtiT  Ѥ      J   vendor/composer/composer/src/Composer/Repository/RootPackageRepository.php9  Qti9  F      F   vendor/composer/composer/src/Composer/Repository/RepositoryManager.php  Qti  <i      E   vendor/composer/composer/src/Composer/Repository/Vcs/GitHubDriver.php\  Qti\  FJE      B   vendor/composer/composer/src/Composer/Repository/Vcs/VcsDriver.php"  Qti"  1JѤ      B   vendor/composer/composer/src/Composer/Repository/Vcs/SvnDriver.php3  Qti3  j      F   vendor/composer/composer/src/Composer/Repository/Vcs/ForgejoDriver.php,  Qti,  2h:      A   vendor/composer/composer/src/Composer/Repository/Vcs/HgDriver.php  Qti  #t      G   vendor/composer/composer/src/Composer/Repository/Vcs/PerforceDriver.phpr  Qtir  \=Gp      K   vendor/composer/composer/src/Composer/Repository/Vcs/GitBitbucketDriver.php8  Qti8  wǤ      B   vendor/composer/composer/src/Composer/Repository/Vcs/GitDriver.php"  Qti"  l      E   vendor/composer/composer/src/Composer/Repository/Vcs/GitLabDriver.php#R  Qti#R  <"      K   vendor/composer/composer/src/Composer/Repository/Vcs/VcsDriverInterface.php  Qti  Vn      E   vendor/composer/composer/src/Composer/Repository/Vcs/FossilDriver.php  Qti  y      C   vendor/composer/composer/src/Composer/Repository/PathRepository.php"  Qti"  &      J   vendor/composer/composer/src/Composer/Repository/VersionCacheInterface.phpd  Qtid  ~      K   vendor/composer/composer/src/Composer/Repository/CanonicalPackagesTrait.php  Qti  =      E   vendor/composer/composer/src/Composer/Repository/FilterRepository.php  Qti  G)      H   vendor/composer/composer/src/Composer/Repository/InstalledRepository.php43  Qti43  sh      N   vendor/composer/composer/src/Composer/Repository/AdvisoryProviderInterface.php  Qti  mĤ      I   vendor/composer/composer/src/Composer/Repository/FilesystemRepository.php	D  Qti	D  ۾¤      M   vendor/composer/composer/src/Composer/Repository/InstalledArrayRepository.php  Qti  s+7      T   vendor/composer/composer/src/Composer/Repository/ConfigurableRepositoryInterface.php  Qti  F*'      O   vendor/composer/composer/src/Composer/Repository/InvalidRepositoryException.php  Qti  f=      <   vendor/composer/composer/src/Composer/Util/PackageSorter.phpD  QtiD  ܳ      >   vendor/composer/composer/src/Composer/Util/ConfigValidator.php1$  Qti1$  D      2   vendor/composer/composer/src/Composer/Util/Git.phps  Qtis  !L      2   vendor/composer/composer/src/Composer/Util/Svn.phpz%  Qtiz%  N      =   vendor/composer/composer/src/Composer/Util/NoProxyPattern.php)  Qti)  .I'      =   vendor/composer/composer/src/Composer/Util/ComposerMirror.php	  Qti	        :   vendor/composer/composer/src/Composer/Util/PackageInfo.php?  Qti?  |R      9   vendor/composer/composer/src/Composer/Util/AuthHelper.phpvA  QtivA  Y      2   vendor/composer/composer/src/Composer/Util/Zip.phpE  QtiE  @r      6   vendor/composer/composer/src/Composer/Util/Forgejo.phps  Qtis  &      7   vendor/composer/composer/src/Composer/Util/Silencer.php)  Qti)  -k      9   vendor/composer/composer/src/Composer/Util/ForgejoUrl.php  Qti  ÿ      9   vendor/composer/composer/src/Composer/Util/Filesystem.php-{  Qti-{  G      2   vendor/composer/composer/src/Composer/Util/Tar.php  Qti        5   vendor/composer/composer/src/Composer/Util/GitHub.php%  Qti%  5      5   vendor/composer/composer/src/Composer/Util/GitLab.php/  Qti/  ݥQ      8   vendor/composer/composer/src/Composer/Util/Bitbucket.php)&  Qti)&  A      =   vendor/composer/composer/src/Composer/Util/HttpDownloader.phpG  QtiG  i      8   vendor/composer/composer/src/Composer/Util/IniHelper.phpi  Qtii   Z      7   vendor/composer/composer/src/Composer/Util/Platform.php*  Qti*  "      C   vendor/composer/composer/src/Composer/Util/StreamContextFactory.php"  Qti"        8   vendor/composer/composer/src/Composer/Util/TlsHelper.php  Qti  	      2   vendor/composer/composer/src/Composer/Util/Url.php  Qti  Q      7   vendor/composer/composer/src/Composer/Util/Perforce.phpL  QtiL  S      @   vendor/composer/composer/src/Composer/Util/Http/ProxyManager.php  Qti  kc      <   vendor/composer/composer/src/Composer/Util/Http/Response.php
  Qti
  xפ      @   vendor/composer/composer/src/Composer/Util/Http/RequestProxy.php  Qti  k
      B   vendor/composer/composer/src/Composer/Util/Http/CurlDownloader.phpz  Qtiz  a%      @   vendor/composer/composer/src/Composer/Util/Http/CurlResponse.php  Qti  :؊      =   vendor/composer/composer/src/Composer/Util/Http/ProxyItem.php  Qti  >      ?   vendor/composer/composer/src/Composer/Util/MetadataMinifier.php  Qti  x      >   vendor/composer/composer/src/Composer/Util/ProcessExecutor.phpF  QtiF  kȤ      1   vendor/composer/composer/src/Composer/Util/Hg.php  Qti  &      ?   vendor/composer/composer/src/Composer/Util/RemoteFilesystem.php7l  Qti7l  pW%      ;   vendor/composer/composer/src/Composer/Util/ErrorHandler.php;  Qti;  Ѥ      D   vendor/composer/composer/src/Composer/Util/ForgejoRepositoryData.php  Qti  5      9   vendor/composer/composer/src/Composer/Util/SyncHelper.php
  Qti
  Uۤ      3   vendor/composer/composer/src/Composer/Util/Loop.php  Qti  ]1Z      A   vendor/composer/composer/src/Composer/Config/JsonConfigSource.php==  Qti==  {Ф      F   vendor/composer/composer/src/Composer/Config/ConfigSourceInterface.php
  Qti
  l      =   vendor/composer/composer/src/Composer/SelfUpdate/Versions.php  Qti  Aڤ      9   vendor/composer/composer/src/Composer/SelfUpdate/Keys.php  Qti  Y!      /   vendor/composer/composer/src/Composer/Cache.php+  Qti+  ]T      ?   vendor/composer/composer/src/Composer/EventDispatcher/Event.php  Qti  :      R   vendor/composer/composer/src/Composer/EventDispatcher/ScriptExecutionException.php  Qti  ;;      I   vendor/composer/composer/src/Composer/EventDispatcher/EventDispatcher.php[  Qti[  5Ep      R   vendor/composer/composer/src/Composer/EventDispatcher/EventSubscriberInterface.phpu  Qtiu  h_}      9   vendor/composer/composer/src/Composer/PartialComposer.php
  Qti
  dW      :   vendor/composer/composer/src/Composer/Platform/Runtime.php  Qti  U      ?   vendor/composer/composer/src/Composer/Platform/HhvmDetector.php  Qti   7      :   vendor/composer/composer/src/Composer/Platform/Version.php
  Qti
  WϤ      5   vendor/composer/composer/src/Composer/IO/BufferIO.phpF  QtiF  "      6   vendor/composer/composer/src/Composer/IO/ConsoleIO.php4  Qti4  A=      3   vendor/composer/composer/src/Composer/IO/BaseIO.php6*  Qti6*  aݤ      3   vendor/composer/composer/src/Composer/IO/NullIO.php	  Qti	  :      8   vendor/composer/composer/src/Composer/IO/IOInterface.phpZ   QtiZ         =   vendor/composer/composer/src/Composer/Plugin/PluginEvents.phpe  Qtie  1+ˤ      C   vendor/composer/composer/src/Composer/Plugin/PreCommandRunEvent.php0  Qti0  R      K   vendor/composer/composer/src/Composer/Plugin/Capability/CommandProvider.php  Qti  d,      F   vendor/composer/composer/src/Composer/Plugin/Capability/Capability.php  Qti  Lk      G   vendor/composer/composer/src/Composer/Plugin/PluginBlockedException.php  Qti  Nu      =   vendor/composer/composer/src/Composer/Plugin/CommandEvent.phpv  Qtiv  _      @   vendor/composer/composer/src/Composer/Plugin/PluginInterface.php?  Qti?  x󗵤      >   vendor/composer/composer/src/Composer/Plugin/PluginManager.php  Qti   c      E   vendor/composer/composer/src/Composer/Plugin/PreFileDownloadEvent.php1  Qti1  ,L}      F   vendor/composer/composer/src/Composer/Plugin/PostFileDownloadEvent.php  Qti  Jj      8   vendor/composer/composer/src/Composer/Plugin/Capable.php  Qti  u      C   vendor/composer/composer/src/Composer/Plugin/PrePoolCreateEvent.php  Qti  b)      B   vendor/composer/composer/src/Composer/Downloader/RarDownloader.php	  Qti	  -Ť      R   vendor/composer/composer/src/Composer/Downloader/VcsCapableDownloaderInterface.phpB  QtiB  LWJ      B   vendor/composer/composer/src/Composer/Downloader/VcsDownloader.php3  Qti3  )      H   vendor/composer/composer/src/Composer/Downloader/FilesystemException.php  Qti  J      D   vendor/composer/composer/src/Composer/Downloader/DownloadManager.php;  Qti;  &3Z      B   vendor/composer/composer/src/Composer/Downloader/TarDownloader.php  Qti  Vw      E   vendor/composer/composer/src/Composer/Downloader/FossilDownloader.php  Qti  o(5      Q   vendor/composer/composer/src/Composer/Downloader/MaxFileSizeExceededException.php  Qti  `ܤ      H   vendor/composer/composer/src/Composer/Downloader/DownloaderInterface.php  Qti  "      A   vendor/composer/composer/src/Composer/Downloader/XzDownloader.php,  Qti,  OӇE      A   vendor/composer/composer/src/Composer/Downloader/HgDownloader.php  Qti  ɤ      B   vendor/composer/composer/src/Composer/Downloader/SvnDownloader.phpH"  QtiH"  }Ͳ      C   vendor/composer/composer/src/Composer/Downloader/FileDownloader.php S  Qti S  OȤ      J   vendor/composer/composer/src/Composer/Downloader/ChangeReportInterface.php&  Qti&  =si      G   vendor/composer/composer/src/Composer/Downloader/TransportException.php<  Qti<  .4D      F   vendor/composer/composer/src/Composer/Downloader/ArchiveDownloader.php!  Qti!  K0      L   vendor/composer/composer/src/Composer/Downloader/DvcsDownloaderInterface.php5  Qti5  G5      C   vendor/composer/composer/src/Composer/Downloader/PharDownloader.php  Qti  x٤      C   vendor/composer/composer/src/Composer/Downloader/PathDownloader.php}6  Qti}6  *      G   vendor/composer/composer/src/Composer/Downloader/PerforceDownloader.phpv  Qtiv  ˤ      B   vendor/composer/composer/src/Composer/Downloader/GitDownloader.phpb  Qtib        B   vendor/composer/composer/src/Composer/Downloader/ZipDownloader.php4;  Qti4;  \'      C   vendor/composer/composer/src/Composer/Downloader/GzipDownloader.php|  Qti|        0   vendor/composer/composer/src/Composer/Config.phpd  Qtid  |(      6   vendor/composer/composer/src/Composer/Script/Event.php
  Qti
  P_ܤ      =   vendor/composer/composer/src/Composer/Script/ScriptEvents.php  Qti  KGꮤ      M   vendor/composer/composer/src/Composer/Question/StrictConfirmationQuestion.php  Qti  ۝      2   vendor/composer/composer/src/Composer/Composer.phpp  Qtip  рդ      F   vendor/composer/composer/src/Composer/Json/JsonValidationException.phpk  Qtik  .
      <   vendor/composer/composer/src/Composer/Json/JsonFormatter.phpU  QtiU  c*t      7   vendor/composer/composer/src/Composer/Json/JsonFile.php@7  Qti@7  (/      >   vendor/composer/composer/src/Composer/Json/JsonManipulator.php  Qti  +k      ;   vendor/composer/composer/src/Composer/InstalledVersions.phpC  QtiC  g){      W   vendor/composer/composer/src/Composer/DependencyResolver/Operation/InstallOperation.phpw  Qtiw  7Q      b   vendor/composer/composer/src/Composer/DependencyResolver/Operation/MarkAliasInstalledOperation.phpv  Qtiv  .x      Y   vendor/composer/composer/src/Composer/DependencyResolver/Operation/OperationInterface.php  Qti  }|(̤      V   vendor/composer/composer/src/Composer/DependencyResolver/Operation/UpdateOperation.phps  Qtis  |y      V   vendor/composer/composer/src/Composer/DependencyResolver/Operation/SolverOperation.php  Qti  $B      Y   vendor/composer/composer/src/Composer/DependencyResolver/Operation/UninstallOperation.php_  Qti_  "      d   vendor/composer/composer/src/Composer/DependencyResolver/Operation/MarkAliasUninstalledOperation.php|  Qti|  R֤      H   vendor/composer/composer/src/Composer/DependencyResolver/Transaction.php8  Qti8  q      L   vendor/composer/composer/src/Composer/DependencyResolver/PolicyInterface.php  Qti  ނդ      Q   vendor/composer/composer/src/Composer/DependencyResolver/LocalRepoTransaction.php(  Qti(  tʺ      K   vendor/composer/composer/src/Composer/DependencyResolver/RuleWatchGraph.php;  Qti;  ]      H   vendor/composer/composer/src/Composer/DependencyResolver/GenericRule.php  Qti  (d      L   vendor/composer/composer/src/Composer/DependencyResolver/LockTransaction.php  Qti  n?      C   vendor/composer/composer/src/Composer/DependencyResolver/Solver.phpg  Qtig  \      A   vendor/composer/composer/src/Composer/DependencyResolver/Rule.phpN  QtiN  h      J   vendor/composer/composer/src/Composer/DependencyResolver/Rule2Literals.php
  Qti
  EۀP      T   vendor/composer/composer/src/Composer/DependencyResolver/SolverProblemsException.phpt  Qtit  ;7E      O   vendor/composer/composer/src/Composer/DependencyResolver/SolverBugException.php  Qti  /d      J   vendor/composer/composer/src/Composer/DependencyResolver/DefaultPolicy.php*  Qti*  iÞ      J   vendor/composer/composer/src/Composer/DependencyResolver/RuleWatchNode.php  Qti  M      D   vendor/composer/composer/src/Composer/DependencyResolver/RuleSet.php+  Qti+  
]      A   vendor/composer/composer/src/Composer/DependencyResolver/Pool.php,  Qti,  H      N   vendor/composer/composer/src/Composer/DependencyResolver/MultiConflictRule.phpg  Qtig  "      D   vendor/composer/composer/src/Composer/DependencyResolver/Request.phpN!  QtiN!  KM      J   vendor/composer/composer/src/Composer/DependencyResolver/PoolOptimizer.phpVM  QtiVM  ް9'      M   vendor/composer/composer/src/Composer/DependencyResolver/RuleSetGenerator.php6  Qti6  ˽5      F   vendor/composer/composer/src/Composer/DependencyResolver/Decisions.php  Qti        H   vendor/composer/composer/src/Composer/DependencyResolver/PoolBuilder.phpo  Qtio  ؤ      D   vendor/composer/composer/src/Composer/DependencyResolver/Problem.php  Qti  ɷ      L   vendor/composer/composer/src/Composer/DependencyResolver/RuleSetIterator.php<
  Qti<
  b"      W   vendor/composer/composer/src/Composer/DependencyResolver/SecurityAdvisoryPoolFilter.php  Qti  v      K   vendor/composer/composer/src/Composer/DependencyResolver/RuleWatchChain.php  Qti  .3      D   vendor/composer/composer/src/Composer/Autoload/AutoloadGenerator.php  Qti  ɤ      >   vendor/composer/composer/src/Composer/Autoload/ClassLoader.php->  Qti->  w      D   vendor/composer/composer/src/Composer/Autoload/ClassMapGenerator.php  Qti  `      A   vendor/composer/composer/src/Composer/Command/SuggestsCommand.php8  Qti8  M      ?   vendor/composer/composer/src/Composer/Command/SearchCommand.phpX  QtiX  F0      =   vendor/composer/composer/src/Composer/Command/BumpCommand.php'  Qti'  C()      @   vendor/composer/composer/src/Composer/Command/ArchiveCommand.php!  Qti!  ]Qk      >   vendor/composer/composer/src/Composer/Command/AuditCommand.php8  Qti8  U      A   vendor/composer/composer/src/Composer/Command/ValidateCommand.php#  Qti#  )$      =   vendor/composer/composer/src/Composer/Command/FundCommand.php  Qti  j4>      G   vendor/composer/composer/src/Composer/Command/PackageDiscoveryTrait.phpO  QtiO  4٠      D   vendor/composer/composer/src/Composer/Command/ScriptAliasCommand.phpf  Qtif  B      F   vendor/composer/composer/src/Composer/Command/CreateProjectCommand.php_  Qti_  lw      =   vendor/composer/composer/src/Composer/Command/BaseCommand.phpiH  QtiiH  \      A   vendor/composer/composer/src/Composer/Command/OutdatedCommand.php?  Qti?  '      E   vendor/composer/composer/src/Composer/Command/DumpAutoloadCommand.php  Qti  :פ      =   vendor/composer/composer/src/Composer/Command/HomeCommand.php:  Qti:  u{      B   vendor/composer/composer/src/Composer/Command/ReinstallCommand.php#  Qti#  y4[Ҥ      ?   vendor/composer/composer/src/Composer/Command/RemoveCommand.php<  Qti<  7      =   vendor/composer/composer/src/Composer/Command/ShowCommand.phpx Qtix f&      @   vendor/composer/composer/src/Composer/Command/InstallCommand.php  Qti  |h{      =   vendor/composer/composer/src/Composer/Command/InitCommand.phpV[  QtiV[  I      B   vendor/composer/composer/src/Composer/Command/RunScriptCommand.php  Qti  54      ?   vendor/composer/composer/src/Composer/Command/ConfigCommand.php  Qti  n      C   vendor/composer/composer/src/Composer/Command/BaseConfigCommand.php  Qti  N      A   vendor/composer/composer/src/Composer/Command/LicensesCommand.php  Qti  0      ?   vendor/composer/composer/src/Composer/Command/UpdateCommand.phpO  QtiO  J2      C   vendor/composer/composer/src/Composer/Command/RepositoryCommand.php.  Qti.        ?   vendor/composer/composer/src/Composer/Command/StatusCommand.phph   Qtih   ȃ      G   vendor/composer/composer/src/Composer/Command/BaseDependencyCommand.php2  Qti2  K      @   vendor/composer/composer/src/Composer/Command/DependsCommand.php  Qti  7      B   vendor/composer/composer/src/Composer/Command/ProhibitsCommand.php  Qti  i      J   vendor/composer/composer/src/Composer/Command/CheckPlatformReqsCommand.php  Qti  C7      C   vendor/composer/composer/src/Composer/Command/SelfUpdateCommand.php>n  Qti>n        @   vendor/composer/composer/src/Composer/Command/RequireCommand.php6t  Qti6t  EF      A   vendor/composer/composer/src/Composer/Command/CompletionTrait.php#  Qti#        C   vendor/composer/composer/src/Composer/Command/ClearCacheCommand.phpU  QtiU  S6      A   vendor/composer/composer/src/Composer/Command/DiagnoseCommand.phpY  QtiY  A      ?   vendor/composer/composer/src/Composer/Command/GlobalCommand.phpu  Qtiu  EEz      >   vendor/composer/composer/src/Composer/Command/AboutCommand.php  Qti  *0k      =   vendor/composer/composer/src/Composer/Command/ExecCommand.php  Qti  nܤ      3   vendor/composer/composer/src/Composer/Installer.php  Qti  @۟      m   vendor/composer/composer/src/Composer/Filter/PlatformRequirementFilter/PlatformRequirementFilterInterface.php  Qti  Ӕv      m   vendor/composer/composer/src/Composer/Filter/PlatformRequirementFilter/IgnoreAllPlatformRequirementFilter.php  Qti  ?C      n   vendor/composer/composer/src/Composer/Filter/PlatformRequirementFilter/IgnoreListPlatformRequirementFilter.php  Qti  ,      q   vendor/composer/composer/src/Composer/Filter/PlatformRequirementFilter/IgnoreNothingPlatformRequirementFilter.php  Qti  ڥq      k   vendor/composer/composer/src/Composer/Filter/PlatformRequirementFilter/PlatformRequirementFilterFactory.php  Qti  e      A   vendor/composer/composer/src/Composer/Installer/PackageEvents.php"  Qti"  ]m      C   vendor/composer/composer/src/Composer/Installer/BinaryInstaller.php8  Qti8  @i      C   vendor/composer/composer/src/Composer/Installer/PluginInstaller.phps  Qtis  ބ?      K   vendor/composer/composer/src/Composer/Installer/BinaryPresenceInterface.php  Qti  <P      C   vendor/composer/composer/src/Composer/Installer/InstallerEvents.php  Qti  "e      @   vendor/composer/composer/src/Composer/Installer/PackageEvent.php  Qti        B   vendor/composer/composer/src/Composer/Installer/InstallerEvent.php  Qti  !7      D   vendor/composer/composer/src/Composer/Installer/LibraryInstaller.php+  Qti+  oI      F   vendor/composer/composer/src/Composer/Installer/InstallerInterface.php1  Qti1  K;      H   vendor/composer/composer/src/Composer/Installer/MetapackageInstaller.php  Qti  ն٤      D   vendor/composer/composer/src/Composer/Installer/ProjectInstaller.php  Qti  ܍      M   vendor/composer/composer/src/Composer/Installer/SuggestedPackagesReporter.php  Qti  SƤ      G   vendor/composer/composer/src/Composer/Installer/InstallationManager.php_  Qti_  dhFO      A   vendor/composer/composer/src/Composer/Installer/NoopInstaller.phpY  QtiY  ^.      C   vendor/composer/composer/src/Composer/Advisory/SecurityAdvisory.php  Qti  Qx      J   vendor/composer/composer/src/Composer/Advisory/PartialSecurityAdvisory.phpA
  QtiA
  ۠      >   vendor/composer/composer/src/Composer/Advisory/AuditConfig.php  Qti  EB      :   vendor/composer/composer/src/Composer/Advisory/Auditor.phpG  QtiG  	EuF      J   vendor/composer/composer/src/Composer/Advisory/IgnoredSecurityAdvisory.phpk  Qtik  5      R   vendor/composer/composer/src/Composer/Exception/IrrecoverableDownloadException.php  Qti        B   vendor/composer/composer/src/Composer/Exception/NoSslException.php  Qti  ;P      2   vendor/composer/composer/src/Composer/Compiler.phpd/  Qtid/  J      9   vendor/composer/composer/src/Composer/Package/Package.phpC  QtiC  :      6   vendor/composer/composer/src/Composer/Package/Link.php  Qti  ڗ2      J   vendor/composer/composer/src/Composer/Package/CompletePackageInterface.php  Qti  Wil      I   vendor/composer/composer/src/Composer/Package/Archiver/ArchiveManager.php$  Qti$  4      P   vendor/composer/composer/src/Composer/Package/Archiver/ArchivableFilesFinder.phpm  Qtim  nY      G   vendor/composer/composer/src/Composer/Package/Archiver/PharArchiver.php  Qti  y3      L   vendor/composer/composer/src/Composer/Package/Archiver/BaseExcludeFilter.php  Qti  2(      P   vendor/composer/composer/src/Composer/Package/Archiver/ArchivableFilesFilter.php  Qti  	2      K   vendor/composer/composer/src/Composer/Package/Archiver/GitExcludeFilter.phpy  Qtiy  ~Ԥ      P   vendor/composer/composer/src/Composer/Package/Archiver/ComposerExcludeFilter.php  Qti  ޣ      L   vendor/composer/composer/src/Composer/Package/Archiver/ArchiverInterface.php  Qti        F   vendor/composer/composer/src/Composer/Package/Archiver/ZipArchiver.phpZ  QtiZ  e      F   vendor/composer/composer/src/Composer/Package/CompleteAliasPackage.phpt  Qtit  `I      >   vendor/composer/composer/src/Composer/Package/AliasPackage.php3'  Qti3'  o]      8   vendor/composer/composer/src/Composer/Package/Locker.phpX  QtiX  'I      B   vendor/composer/composer/src/Composer/Package/PackageInterface.php>/  Qti>/  0T      G   vendor/composer/composer/src/Composer/Package/Version/VersionBumper.php<  Qti<  VNĤ      I   vendor/composer/composer/src/Composer/Package/Version/StabilityFilter.php  Qti        H   vendor/composer/composer/src/Composer/Package/Version/VersionGuesser.php?H  Qti?H  <      I   vendor/composer/composer/src/Composer/Package/Version/VersionSelector.php/  Qti/  4p:      G   vendor/composer/composer/src/Composer/Package/Version/VersionParser.php  Qti  8Ҥ      N   vendor/composer/composer/src/Composer/Package/Loader/ValidatingArrayLoader.php  Qti  =      P   vendor/composer/composer/src/Composer/Package/Loader/InvalidPackageException.phpj  Qtij  gZ      D   vendor/composer/composer/src/Composer/Package/Loader/ArrayLoader.phpxH  QtixH  )<=      H   vendor/composer/composer/src/Composer/Package/Loader/LoaderInterface.phpg  Qtig  #      J   vendor/composer/composer/src/Composer/Package/Loader/RootPackageLoader.php9.  Qti9.  A      C   vendor/composer/composer/src/Composer/Package/Loader/JsonLoader.phpd  Qtid  L`      =   vendor/composer/composer/src/Composer/Package/BasePackage.phpt  Qtit  EV$      C   vendor/composer/composer/src/Composer/Package/Comparer/Comparer.php  Qti  @      B   vendor/composer/composer/src/Composer/Package/RootAliasPackage.php  Qti  5      A   vendor/composer/composer/src/Composer/Package/CompletePackage.php'  Qti'  p      F   vendor/composer/composer/src/Composer/Package/RootPackageInterface.php  Qti  {      =   vendor/composer/composer/src/Composer/Package/RootPackage.phpN  QtiN  	!      D   vendor/composer/composer/src/Composer/Package/Dumper/ArrayDumper.php  Qti  ۘO      =   vendor/composer/composer/src/Composer/Console/Application.phpŌ  QtiŌ  7      C   vendor/composer/composer/src/Composer/Console/GithubActionError.phpa  Qtia  ~+#      E   vendor/composer/composer/src/Composer/Console/Input/InputArgument.php
  Qti
  ʟB      C   vendor/composer/composer/src/Composer/Console/Input/InputOption.php  Qti        E   vendor/composer/composer/src/Composer/Console/HtmlOutputFormatter.php,  Qti,  p      *   vendor/composer/composer/src/bootstrap.php4  Qti4  0h֤      (   vendor/composer/ca-bundle/res/cacert.pemxs Qtixs fO      !   vendor/composer/ca-bundle/LICENSE  Qti  *!^`      #   vendor/composer/ca-bundle/README.md1  Qti1  >VuĤ      '   vendor/composer/ca-bundle/composer.json5  Qti5  y:      *   vendor/composer/ca-bundle/src/CaBundle.php+  Qti+  &      !   vendor/composer/autoload_psr4.phpC  QtiC  !n      %   vendor/composer/autoload_classmap.phpW QtiW Um:      "   vendor/composer/platform_check.php  Qti  <E      #   vendor/composer/autoload_static.phpf!	 Qtif!	 5      !   vendor/composer/autoload_real.php  Qti  5M         vendor/composer/semver/LICENSE  Qti  Bh      #   vendor/composer/semver/CHANGELOG.mdi'  Qtii'  [L          vendor/composer/semver/README.mdH  QtiH   }Τ      $   vendor/composer/semver/composer.json  Qti  z)      /   vendor/composer/semver/src/CompilingMatcher.php
  Qti
        '   vendor/composer/semver/src/Interval.phpu  Qtiu         )   vendor/composer/semver/src/Comparator.php<
  Qti<
  <L      (   vendor/composer/semver/src/Intervals.phpO  QtiO  P֤      %   vendor/composer/semver/src/Semver.php  Qti  X\      ,   vendor/composer/semver/src/VersionParser.phpT  QtiT  ![      =   vendor/composer/semver/src/Constraint/ConstraintInterface.php  Qti  겤      9   vendor/composer/semver/src/Constraint/MultiConstraint.php#  Qti#  Sˤ      4   vendor/composer/semver/src/Constraint/Constraint.php<2  Qti<2  TA      <   vendor/composer/semver/src/Constraint/MatchAllConstraint.php,  Qti,  [j<      =   vendor/composer/semver/src/Constraint/MatchNoneConstraint.php(  Qti(  h      /   vendor/composer/semver/src/Constraint/Bound.php
  Qti
  0 {      "   vendor/composer/autoload_files.php  Qti  ɩ      %   vendor/composer/InstalledVersions.phpC  QtiC  g){         vendor/composer/installed.phpsc  Qtisc  ?m         vendor/composer/pcre/LICENSE  Qti  hg^         vendor/composer/pcre/README.md!  Qti!  B      #   vendor/composer/pcre/extension.neon  Qti  &&1      "   vendor/composer/pcre/composer.json  Qti  r7      E   vendor/composer/pcre/src/PHPStan/PregMatchTypeSpecifyingExtension.php  Qti  nS      L   vendor/composer/pcre/src/PHPStan/PregReplaceCallbackClosureTypeExtension.phpV  QtiV  ƚ      G   vendor/composer/pcre/src/PHPStan/PregMatchParameterOutTypeExtension.php  Qti  X      <   vendor/composer/pcre/src/PHPStan/InvalidRegexPatternRule.phpN  QtiN  w/V̤      3   vendor/composer/pcre/src/PHPStan/PregMatchFlags.php	  Qti	  /      ?   vendor/composer/pcre/src/PHPStan/UnsafeStrictGroupsCallRule.php  Qti  c      (   vendor/composer/pcre/src/MatchResult.php  Qti  ڇҤ      "   vendor/composer/pcre/src/Regex.php~  Qti~  5b      6   vendor/composer/pcre/src/MatchAllWithOffsetsResult.php  Qti        3   vendor/composer/pcre/src/MatchWithOffsetsResult.php  Qti  o      7   vendor/composer/pcre/src/MatchAllStrictGroupsResult.phpw  Qtiw  Q      9   vendor/composer/pcre/src/UnexpectedNullMatchException.php"  Qti"  _      4   vendor/composer/pcre/src/MatchStrictGroupsResult.php  Qti        +   vendor/composer/pcre/src/MatchAllResult.php  Qti  	Z      *   vendor/composer/pcre/src/ReplaceResult.php  Qti  /      !   vendor/composer/pcre/src/Preg.phpE  QtiE  ˺      *   vendor/composer/pcre/src/PcreException.phpo  Qtio  5      )   vendor/composer/metadata-minifier/LICENSE  Qti  hg^      +   vendor/composer/metadata-minifier/README.mdL  QtiL  Mv<      3   vendor/composer/metadata-minifier/phpstan.neon.distB   QtiB   #f      /   vendor/composer/metadata-minifier/composer.json  Qti  D0פ      :   vendor/composer/metadata-minifier/src/MetadataMinifier.php
  Qti
         6   vendor/composer/spdx-licenses/res/spdx-exceptions.json;  Qti;  W      4   vendor/composer/spdx-licenses/res/spdx-licenses.json1  Qti1  Yzx      %   vendor/composer/spdx-licenses/LICENSE  Qti  Bh      '   vendor/composer/spdx-licenses/README.md<  Qti<  se      +   vendor/composer/spdx-licenses/composer.json  Qti  N6      2   vendor/composer/spdx-licenses/src/SpdxLicenses.php%  Qti%  v0g      .   vendor/phpdocumentor/reflection-common/LICENSE9  Qti9  *2Ȑ      0   vendor/phpdocumentor/reflection-common/README.mdO  QtiO  һ      4   vendor/phpdocumentor/reflection-common/composer.json  Qti  k6      6   vendor/phpdocumentor/reflection-common/src/Element.php  Qti  ԇi      =   vendor/phpdocumentor/reflection-common/src/ProjectFactory.phpe  Qtie  vr      3   vendor/phpdocumentor/reflection-common/src/File.php  Qti  [q      6   vendor/phpdocumentor/reflection-common/src/Project.php  Qti  L^      4   vendor/phpdocumentor/reflection-common/src/Fqsen.php  Qti  $}      7   vendor/phpdocumentor/reflection-common/src/Location.php  Qti  Q      *   vendor/phpdocumentor/type-resolver/LICENSE8  Qti8  ʤ      2   vendor/phpdocumentor/type-resolver/phpdoc.dist.xml  Qti  DA낤      ,   vendor/phpdocumentor/type-resolver/README.md#  Qti#  ܵ\      0   vendor/phpdocumentor/type-resolver/composer.json  Qti  \[      7   vendor/phpdocumentor/type-resolver/src/TypeResolver.phpd  Qtid  x      ;   vendor/phpdocumentor/type-resolver/src/Types/Expression.phpD  QtiD  |      8   vendor/phpdocumentor/type-resolver/src/Types/Boolean.php{  Qti{  e,      8   vendor/phpdocumentor/type-resolver/src/Types/Integer.phpw  Qtiw  (      6   vendor/phpdocumentor/type-resolver/src/Types/Self_.php  Qti  Ϥ      6   vendor/phpdocumentor/type-resolver/src/Types/Void_.php  Qti  ym      6   vendor/phpdocumentor/type-resolver/src/Types/Null_.php  Qti  _+z      :   vendor/phpdocumentor/type-resolver/src/Types/Resource_.php  Qti  e	      7   vendor/phpdocumentor/type-resolver/src/Types/Float_.phpt  Qtit  Œ5      8   vendor/phpdocumentor/type-resolver/src/Types/Object_.php  Qti  1      8   vendor/phpdocumentor/type-resolver/src/Types/String_.php  Qti  >c      9   vendor/phpdocumentor/type-resolver/src/Types/Nullable.php^  Qti^  @x      :   vendor/phpdocumentor/type-resolver/src/Types/Callable_.php  Qti  3̤      @   vendor/phpdocumentor/type-resolver/src/Types/InterfaceString.php  Qti  o      :   vendor/phpdocumentor/type-resolver/src/Types/Iterable_.phpE  QtiE  NO      B   vendor/phpdocumentor/type-resolver/src/Types/CallableParameter.php  Qti  ƶ      9   vendor/phpdocumentor/type-resolver/src/Types/ArrayKey.php  Qti  50      7   vendor/phpdocumentor/type-resolver/src/Types/Never_.php  Qti  	n      8   vendor/phpdocumentor/type-resolver/src/Types/Static_.php  Qti  X      <   vendor/phpdocumentor/type-resolver/src/Types/ClassString.php\  Qti\  wP      8   vendor/phpdocumentor/type-resolver/src/Types/Parent_.php  Qti  ,      7   vendor/phpdocumentor/type-resolver/src/Types/Scalar.php  Qti  Bb      8   vendor/phpdocumentor/type-resolver/src/Types/Context.php  Qti  ɤ      =   vendor/phpdocumentor/type-resolver/src/Types/AbstractList.php  Qti        ;   vendor/phpdocumentor/type-resolver/src/Types/Collection.php  Qti   ri      =   vendor/phpdocumentor/type-resolver/src/Types/Intersection.php$  Qti$        ?   vendor/phpdocumentor/type-resolver/src/Types/ContextFactory.php
7  Qti
7  VǤ      ?   vendor/phpdocumentor/type-resolver/src/Types/AggregatedType.php
  Qti
  ,7R      9   vendor/phpdocumentor/type-resolver/src/Types/Compound.php  Qti        5   vendor/phpdocumentor/type-resolver/src/Types/This.phpf  Qtif  +&Ȥ      7   vendor/phpdocumentor/type-resolver/src/Types/Array_.php  Qti   NK      7   vendor/phpdocumentor/type-resolver/src/Types/Mixed_.php  Qti  H      /   vendor/phpdocumentor/type-resolver/src/Type.php  Qti  -ʤ      8   vendor/phpdocumentor/type-resolver/src/FqsenResolver.php	  Qti	  +&      B   vendor/phpdocumentor/type-resolver/src/PseudoTypes/StringValue.php  Qti  뛤      <   vendor/phpdocumentor/type-resolver/src/PseudoTypes/List_.php  Qti  qݤ      @   vendor/phpdocumentor/type-resolver/src/PseudoTypes/IntMaskOf.php  Qti  >      E   vendor/phpdocumentor/type-resolver/src/PseudoTypes/NonEmptyString.php{  Qti{  t      @   vendor/phpdocumentor/type-resolver/src/PseudoTypes/ShapeItem.php<  Qti<  R̤      <   vendor/phpdocumentor/type-resolver/src/PseudoTypes/KeyOf.php  Qti  ,      C   vendor/phpdocumentor/type-resolver/src/PseudoTypes/IntegerRange.php=  Qti=  L*̤      C   vendor/phpdocumentor/type-resolver/src/PseudoTypes/OffsetAccess.php  Qti        E   vendor/phpdocumentor/type-resolver/src/PseudoTypes/CallableString.phpz  Qtiz  ^@      D   vendor/phpdocumentor/type-resolver/src/PseudoTypes/ListShapeItem.php   Qti   곤      >   vendor/phpdocumentor/type-resolver/src/PseudoTypes/IntMask.phpI  QtiI        >   vendor/phpdocumentor/type-resolver/src/PseudoTypes/ValueOf.php  Qti  Ƥ      ?   vendor/phpdocumentor/type-resolver/src/PseudoTypes/Numeric_.php&  Qti&  .rg      =   vendor/phpdocumentor/type-resolver/src/PseudoTypes/False_.php  Qti  ߤ      F   vendor/phpdocumentor/type-resolver/src/PseudoTypes/ObjectShapeItem.php   Qti   IC3      B   vendor/phpdocumentor/type-resolver/src/PseudoTypes/TraitString.phpt  Qtit  tdQ      A   vendor/phpdocumentor/type-resolver/src/PseudoTypes/FloatValue.php  Qti  ?Q      D   vendor/phpdocumentor/type-resolver/src/PseudoTypes/NumericString.phpx  Qtix  V]      H   vendor/phpdocumentor/type-resolver/src/PseudoTypes/HtmlEscapedString.php  Qti  JS(      C   vendor/phpdocumentor/type-resolver/src/PseudoTypes/IntegerValue.php  Qti  :      D   vendor/phpdocumentor/type-resolver/src/PseudoTypes/LiteralString.phpx  Qtix  KaNC      C   vendor/phpdocumentor/type-resolver/src/PseudoTypes/NonEmptyList.php	  Qti	        F   vendor/phpdocumentor/type-resolver/src/PseudoTypes/ConstExpression.php  Qti  8      A   vendor/phpdocumentor/type-resolver/src/PseudoTypes/ArrayShape.php  Qti  |      N   vendor/phpdocumentor/type-resolver/src/PseudoTypes/ConditionalForParameter.php  Qti  
U      N   vendor/phpdocumentor/type-resolver/src/PseudoTypes/NonEmptyLowercaseString.php  Qti  7a      D   vendor/phpdocumentor/type-resolver/src/PseudoTypes/NonEmptyArray.php  Qti  P3      F   vendor/phpdocumentor/type-resolver/src/PseudoTypes/LowercaseString.php|  Qti|  Ө      <   vendor/phpdocumentor/type-resolver/src/PseudoTypes/True_.php  Qti        @   vendor/phpdocumentor/type-resolver/src/PseudoTypes/ListShape.php2  Qti2  'bӤ      F   vendor/phpdocumentor/type-resolver/src/PseudoTypes/NegativeInteger.phpu  Qtiu  S      E   vendor/phpdocumentor/type-resolver/src/PseudoTypes/ArrayShapeItem.phpe  Qtie  7      B   vendor/phpdocumentor/type-resolver/src/PseudoTypes/ObjectShape.phpJ  QtiJ  B      F   vendor/phpdocumentor/type-resolver/src/PseudoTypes/PositiveInteger.phpu  Qtiu  *e      B   vendor/phpdocumentor/type-resolver/src/PseudoTypes/Conditional.phpU  QtiU  κe      5   vendor/phpdocumentor/type-resolver/src/PseudoType.php{  Qti{  P      0   vendor/phpdocumentor/reflection-docblock/LICENSE8  Qti8  ʤ      2   vendor/phpdocumentor/reflection-docblock/README.md  Qti  }      6   vendor/phpdocumentor/reflection-docblock/composer.json  Qti  Z      @   vendor/phpdocumentor/reflection-docblock/src/DocBlockFactory.php/  Qti/  O      D   vendor/phpdocumentor/reflection-docblock/src/DocBlock/Serializer.phpC  QtiC  2      G   vendor/phpdocumentor/reflection-docblock/src/DocBlock/ExampleFinder.php>  Qti>  (B      =   vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tag.php  Qti  M'      D   vendor/phpdocumentor/reflection-docblock/src/DocBlock/TagFactory.php  Qti  ^      L   vendor/phpdocumentor/reflection-docblock/src/DocBlock/DescriptionFactory.php`  Qti`  Լ      D   vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Since.php
  Qti
  xԤ      L   vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/PropertyWrite.php  Qti  ̔      N   vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/MethodParameter.php  Qti  ଍A      C   vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Link.php  Qti  Cک}      I   vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/InvalidTag.php  Qti        F   vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/BaseTag.php  Qti  Go      C   vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Var_.php  Qti  }
'I      D   vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Param.php2  Qti2  Ѫ\      D   vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Mixin.php  Qti  (      P   vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/TemplateCovariant.php  Qti  \Ϥ      E   vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Method.php'  Qti'  >      H   vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Formatter.php+  Qti+  <g      C   vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Uses.phpQ
  QtiQ
  pM      F   vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Return_.php  Qti        ]   vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Formatter/PassthroughFormatter.php  Qti  p      W   vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Formatter/AlignFormatter.php  Qti  .      Q   vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/TemplateImplements.php  Qti  r      K   vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/PropertyRead.php  Qti  f      G   vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Property.php  Qti  0֤      F   vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Version.php
  Qti
  Ccg      B   vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/See.php.  Qti.        G   vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Extends_.php+  Qti+  z      F   vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Generic.php	  Qti	  *m      J   vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/TagWithType.php  Qti  N      E   vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Source.php  Qti  ˭      G   vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Template.phpH	  QtiH	  *g      J   vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Implements_.php4  Qti4        E   vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Author.php	  Qti	  t5a      E   vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Throws.php  Qti  Y(      X   vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Factory/ImplementsFactory.php  Qti  O      N   vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Factory/Factory.phpI  QtiI  
      Z   vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Factory/PropertyReadFactory.php(  Qti(         U   vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Factory/ExtendsFactory.php  Qti        S   vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Factory/StaticMethod.php%  Qti%  cTg      ]   vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Factory/AbstractPHPStanFactory.php  Qti  8~      [   vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Factory/PropertyWriteFactory.php,  Qti,        Q   vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Factory/VarFactory.php  Qti  _      T   vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Factory/MethodFactory.phpA
  QtiA
  c      V   vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Factory/TemplateFactory.phpH  QtiH  դ      `   vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Factory/TemplateImplementsFactory.php  Qti  F7      S   vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Factory/ParamFactory.php  Qti  Z       ]   vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Factory/MethodParameterFactory.phpF	  QtiF	  gq      U   vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Factory/PHPStanFactory.php  Qti  LKM      ]   vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Factory/TemplateExtendsFactory.php  Qti  5T      V   vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Factory/PropertyFactory.php  Qti        T   vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Factory/ReturnFactory.php  Qti  "X      R   vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Reference/Reference.php  Qti  	6r      L   vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Reference/Url.php  Qti  Z=      N   vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Reference/Fqsen.php)  Qti)  -{(      N   vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/TemplateExtends.php  Qti        F   vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Example.php  Qti  e@      I   vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Deprecated.php  Qti  xGo      E   vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Covers.phpz
  Qtiz
  ÿߤ      L   vendor/phpdocumentor/reflection-docblock/src/DocBlock/StandardTagFactory.php4  Qti4  Z\      E   vendor/phpdocumentor/reflection-docblock/src/DocBlock/Description.php8  Qti8        6   vendor/phpdocumentor/reflection-docblock/src/Utils.php	  Qti	        I   vendor/phpdocumentor/reflection-docblock/src/DocBlockFactoryInterface.php  Qti  .      9   vendor/phpdocumentor/reflection-docblock/src/DocBlock.php  Qti  .      H   vendor/phpdocumentor/reflection-docblock/src/Exception/PcreException.php  Qti  	i;      1   vendor/paragonie/constant_time_encoding/README.md~  Qti~  uLR      3   vendor/paragonie/constant_time_encoding/LICENSE.txte	  Qtie	  |[      5   vendor/paragonie/constant_time_encoding/composer.json  Qti  xm      =   vendor/paragonie/constant_time_encoding/src/Base64UrlSafe.php  Qti  җ.פ      9   vendor/paragonie/constant_time_encoding/src/Base32Hex.php  Qti  ZƩ      >   vendor/paragonie/constant_time_encoding/src/Base64DotSlash.php  Qti  0Ѥ      8   vendor/paragonie/constant_time_encoding/src/Encoding.php  Qti  KCӤ      @   vendor/paragonie/constant_time_encoding/src/EncoderInterface.phpH  QtiH  `jߤ      6   vendor/paragonie/constant_time_encoding/src/Base32.php">  Qti">  B      3   vendor/paragonie/constant_time_encoding/src/Hex.php  Qti  lA^      E   vendor/paragonie/constant_time_encoding/src/Base64DotSlashOrdered.php
  Qti
        6   vendor/paragonie/constant_time_encoding/src/Binary.php	  Qti	  _      7   vendor/paragonie/constant_time_encoding/src/RFC4648.php  Qti  z\      6   vendor/paragonie/constant_time_encoding/src/Base64.php-  Qti-  <li:      .   vendor/spomky-labs/cbor-php/CODE_OF_CONDUCT.md  Qti  m      '   vendor/spomky-labs/cbor-php/RELEASES.md  Qti  1}Ҥ      #   vendor/spomky-labs/cbor-php/LICENSE,  Qti,  C      %   vendor/spomky-labs/cbor-php/README.md *  Qti *  vƤ      )   vendor/spomky-labs/cbor-php/composer.json0  Qti0  _Ԥ      '   vendor/spomky-labs/cbor-php/SECURITY.md>  Qti>  ɤ      0   vendor/spomky-labs/cbor-php/src/StringStream.phps  Qtis        +   vendor/spomky-labs/cbor-php/src/Encoder.php  Qti  찤      :   vendor/spomky-labs/cbor-php/src/OtherObject/TrueObject.php  Qti  F      ;   vendor/spomky-labs/cbor-php/src/OtherObject/BreakObject.phpU  QtiU  e      D   vendor/spomky-labs/cbor-php/src/OtherObject/OtherObjectInterface.phpr  Qtir        J   vendor/spomky-labs/cbor-php/src/OtherObject/SinglePrecisionFloatObject.phpI
  QtiI
  Abˤ      =   vendor/spomky-labs/cbor-php/src/OtherObject/GenericObject.php  Qti  R1+      ;   vendor/spomky-labs/cbor-php/src/OtherObject/FalseObject.php  Qti  8%      ?   vendor/spomky-labs/cbor-php/src/OtherObject/UndefinedObject.phpa  Qtia  n      J   vendor/spomky-labs/cbor-php/src/OtherObject/DoublePrecisionFloatObject.php
  Qti
  s      K   vendor/spomky-labs/cbor-php/src/OtherObject/OtherObjectManagerInterface.php   Qti   X z?      H   vendor/spomky-labs/cbor-php/src/OtherObject/HalfPrecisionFloatObject.phph  Qtih  f0      <   vendor/spomky-labs/cbor-php/src/OtherObject/SimpleObject.php	  Qti	  ~      :   vendor/spomky-labs/cbor-php/src/OtherObject/NullObject.php  Qti  鞤      B   vendor/spomky-labs/cbor-php/src/OtherObject/OtherObjectManager.phpv  Qtiv  `H6      4   vendor/spomky-labs/cbor-php/src/DecoderInterface.php   Qti   U˧z      4   vendor/spomky-labs/cbor-php/src/ByteStringObject.phpl  Qtil  Z      D   vendor/spomky-labs/cbor-php/src/IndefiniteLengthTextStringObject.php#  Qti#  ~      '   vendor/spomky-labs/cbor-php/src/Tag.phpZ  QtiZ  βB      +   vendor/spomky-labs/cbor-php/src/Decoder.php#  Qti#  ڤ      4   vendor/spomky-labs/cbor-php/src/EncoderInterface.php   Qti   t͔0      9   vendor/spomky-labs/cbor-php/src/UnsignedIntegerObject.php  Qti  jK      6   vendor/spomky-labs/cbor-php/src/AbstractCBORObject.php:  Qti:  5@,      0   vendor/spomky-labs/cbor-php/src/Normalizable.php   Qti   xӤ      4   vendor/spomky-labs/cbor-php/src/LengthCalculator.phpq  Qtiq  'r      /   vendor/spomky-labs/cbor-php/src/OtherObject.php  Qti  ܁+H      *   vendor/spomky-labs/cbor-php/src/Stream.php   Qti   a      4   vendor/spomky-labs/cbor-php/src/TextStringObject.phpc  Qtic        D   vendor/spomky-labs/cbor-php/src/IndefiniteLengthByteStringObject.php'  Qti'  )      >   vendor/spomky-labs/cbor-php/src/IndefiniteLengthListObject.php  Qti  T      =   vendor/spomky-labs/cbor-php/src/IndefiniteLengthMapObject.phpy  Qtiy  p      +   vendor/spomky-labs/cbor-php/src/MapItem.php  Qti  E      )   vendor/spomky-labs/cbor-php/src/Utils.php  Qti  >Ĥ      .   vendor/spomky-labs/cbor-php/src/ListObject.phpQ  QtiQ  v      -   vendor/spomky-labs/cbor-php/src/MapObject.php2  Qti2        .   vendor/spomky-labs/cbor-php/src/CBORObject.phpt  Qtit  l      .   vendor/spomky-labs/cbor-php/src/Tag/UriTag.php  Qti  Zk      <   vendor/spomky-labs/cbor-php/src/Tag/Base64UrlEncodingTag.php  Qti        =   vendor/spomky-labs/cbor-php/src/Tag/NegativeBigIntegerTag.php  Qti        :   vendor/spomky-labs/cbor-php/src/Tag/DecimalFractionTag.php
  Qti
  /5"      ;   vendor/spomky-labs/cbor-php/src/Tag/TagManagerInterface.php  Qti  |x7`      4   vendor/spomky-labs/cbor-php/src/Tag/TagInterface.phpe  Qtie  ]K      4   vendor/spomky-labs/cbor-php/src/Tag/Base64UrlTag.php  Qti  zؤ      3   vendor/spomky-labs/cbor-php/src/Tag/BigFloatTag.php
  Qti
  IѤ      /   vendor/spomky-labs/cbor-php/src/Tag/CBORTag.phpz  Qtiz  &E      /   vendor/spomky-labs/cbor-php/src/Tag/MimeTag.php  Qti  \')      3   vendor/spomky-labs/cbor-php/src/Tag/DatetimeTag.php  Qti  ^      7   vendor/spomky-labs/cbor-php/src/Tag/CBOREncodingTag.php  Qti  P      1   vendor/spomky-labs/cbor-php/src/Tag/Base64Tag.php  Qti  y      9   vendor/spomky-labs/cbor-php/src/Tag/Base16EncodingTag.php  Qti  d{      =   vendor/spomky-labs/cbor-php/src/Tag/UnsignedBigIntegerTag.php  Qti  Q      2   vendor/spomky-labs/cbor-php/src/Tag/TagManager.php*  Qti*  G      4   vendor/spomky-labs/cbor-php/src/Tag/TimestampTag.php  Qti        2   vendor/spomky-labs/cbor-php/src/Tag/GenericTag.php  Qti  (}      9   vendor/spomky-labs/cbor-php/src/Tag/Base64EncodingTag.php  Qti  GGȤ      9   vendor/spomky-labs/cbor-php/src/NegativeIntegerObject.php  Qti  掤      (   vendor/spomky-labs/pki-framework/LICENSES  QtiS  t      *   vendor/spomky-labs/pki-framework/README.md  Qti  7/V      .   vendor/spomky-labs/pki-framework/composer.jsonK  QtiK  4      ,   vendor/spomky-labs/pki-framework/SECURITY.mdI  QtiI  ,)      5   vendor/spomky-labs/pki-framework/src/ASN1/Element.phpt<  Qtit<  )      9   vendor/spomky-labs/pki-framework/src/ASN1/Util/BigInt.phpv  Qtiv  X      8   vendor/spomky-labs/pki-framework/src/ASN1/Util/Flags.php  Qti   h      B   vendor/spomky-labs/pki-framework/src/ASN1/Component/Identifier.php}  Qti}  k      >   vendor/spomky-labs/pki-framework/src/ASN1/Component/Length.php  Qti        @   vendor/spomky-labs/pki-framework/src/ASN1/Type/PrimitiveType.php+  Qti+        =   vendor/spomky-labs/pki-framework/src/ASN1/Type/BaseString.php  Qti  ?q      F   vendor/spomky-labs/pki-framework/src/ASN1/Type/Primitive/BMPString.php]  Qti]  \L      D   vendor/spomky-labs/pki-framework/src/ASN1/Type/Primitive/Boolean.php5  Qti5  䖮      D   vendor/spomky-labs/pki-framework/src/ASN1/Type/Primitive/Integer.phpW  QtiW  B      H   vendor/spomky-labs/pki-framework/src/ASN1/Type/Primitive/RelativeOID.php  Qti  z      J   vendor/spomky-labs/pki-framework/src/ASN1/Type/Primitive/VisibleString.php  Qti  㶻      C   vendor/spomky-labs/pki-framework/src/ASN1/Type/Primitive/Number.php  Qti  4      G   vendor/spomky-labs/pki-framework/src/ASN1/Type/Primitive/UTF8String.php  Qti  ~9      F   vendor/spomky-labs/pki-framework/src/ASN1/Type/Primitive/BitString.php  Qti  A=      F   vendor/spomky-labs/pki-framework/src/ASN1/Type/Primitive/IA5String.php  Qti  -J      L   vendor/spomky-labs/pki-framework/src/ASN1/Type/Primitive/UniversalString.php  Qti  V8      J   vendor/spomky-labs/pki-framework/src/ASN1/Type/Primitive/GraphicString.php  Qti  .@      M   vendor/spomky-labs/pki-framework/src/ASN1/Type/Primitive/ObjectDescriptor.php  Qti  Cѐ      A   vendor/spomky-labs/pki-framework/src/ASN1/Type/Primitive/Real.phpQ  QtiQ  W]΃      L   vendor/spomky-labs/pki-framework/src/ASN1/Type/Primitive/PrintableString.php  Qti  ǃC      @   vendor/spomky-labs/pki-framework/src/ASN1/Type/Primitive/EOC.php  Qti  /      E   vendor/spomky-labs/pki-framework/src/ASN1/Type/Primitive/NullType.php  Qti        M   vendor/spomky-labs/pki-framework/src/ASN1/Type/Primitive/ObjectIdentifier.php  Qti  }v2      G   vendor/spomky-labs/pki-framework/src/ASN1/Type/Primitive/Enumerated.php7  Qti7  V      J   vendor/spomky-labs/pki-framework/src/ASN1/Type/Primitive/NumericString.php  Qti  3h      H   vendor/spomky-labs/pki-framework/src/ASN1/Type/Primitive/OctetString.php1  Qti1  k-Ф      L   vendor/spomky-labs/pki-framework/src/ASN1/Type/Primitive/GeneralizedTime.php  Qti  z&      D   vendor/spomky-labs/pki-framework/src/ASN1/Type/Primitive/UTCTime.php&	  Qti&	        K   vendor/spomky-labs/pki-framework/src/ASN1/Type/Primitive/VideotexString.php  Qti  =ߐ      L   vendor/spomky-labs/pki-framework/src/ASN1/Type/Primitive/CharacterString.php=  Qti=  h!8      F   vendor/spomky-labs/pki-framework/src/ASN1/Type/Primitive/T61String.php  Qti  	H      J   vendor/spomky-labs/pki-framework/src/ASN1/Type/Primitive/GeneralString.php  Qti  _v      ;   vendor/spomky-labs/pki-framework/src/ASN1/Type/TimeType.php:  Qti:  %e      I   vendor/spomky-labs/pki-framework/src/ASN1/Type/Tagged/ImplicitTagging.php  Qti  n>m      M   vendor/spomky-labs/pki-framework/src/ASN1/Type/Tagged/ContextSpecificType.php   Qti   X      N   vendor/spomky-labs/pki-framework/src/ASN1/Type/Tagged/ExplicitlyTaggedType.php!  Qti!  yn      E   vendor/spomky-labs/pki-framework/src/ASN1/Type/Tagged/PrivateType.php   Qti   4eY      I   vendor/spomky-labs/pki-framework/src/ASN1/Type/Tagged/ApplicationType.php   Qti   CF      N   vendor/spomky-labs/pki-framework/src/ASN1/Type/Tagged/ImplicitlyTaggedType.php;  Qti;  9iB      G   vendor/spomky-labs/pki-framework/src/ASN1/Type/Tagged/DERTaggedType.php  Qti  Qګ      H   vendor/spomky-labs/pki-framework/src/ASN1/Type/Tagged/TaggedTypeWrap.php&  Qti&  GI      I   vendor/spomky-labs/pki-framework/src/ASN1/Type/Tagged/ExplicitTagging.php  Qti        G   vendor/spomky-labs/pki-framework/src/ASN1/Type/Constructed/Sequence.phpV  QtiV  GB      B   vendor/spomky-labs/pki-framework/src/ASN1/Type/Constructed/Set.php  Qti  1O      P   vendor/spomky-labs/pki-framework/src/ASN1/Type/Constructed/ConstructedString.php  Qti  7      B   vendor/spomky-labs/pki-framework/src/ASN1/Type/PrimitiveString.php  Qti  :%      <   vendor/spomky-labs/pki-framework/src/ASN1/Type/Structure.php  Qti  ~      ;   vendor/spomky-labs/pki-framework/src/ASN1/Type/BaseTime.php  Qti        B   vendor/spomky-labs/pki-framework/src/ASN1/Type/UnspecifiedType.php ?  Qti ?  Nu      =   vendor/spomky-labs/pki-framework/src/ASN1/Type/TaggedType.php	  Qti	  fȤ      =   vendor/spomky-labs/pki-framework/src/ASN1/Type/StringType.php  Qti  &      A   vendor/spomky-labs/pki-framework/src/ASN1/Type/UniversalClass.php~  Qti~  O      5   vendor/spomky-labs/pki-framework/src/ASN1/DERData.php  Qti  kۤ      A   vendor/spomky-labs/pki-framework/src/ASN1/Feature/ElementBase.php  Qti  ZR      @   vendor/spomky-labs/pki-framework/src/ASN1/Feature/Stringable.phpq  Qtiq        ?   vendor/spomky-labs/pki-framework/src/ASN1/Feature/Encodable.php   Qti   5
      G   vendor/spomky-labs/pki-framework/src/ASN1/Exception/DecodeException.php   Qti   }Ӥ      ;   vendor/spomky-labs/pki-framework/src/CryptoEncoding/PEM.php  Qti  뿤      A   vendor/spomky-labs/pki-framework/src/CryptoEncoding/PEMBundle.php  Qti  ^Ȥ      J   vendor/spomky-labs/pki-framework/src/CryptoBridge/Crypto/OpenSSLCrypto.php  Qti  Ϗ      <   vendor/spomky-labs/pki-framework/src/CryptoBridge/Crypto.php  Qti  B      >   vendor/spomky-labs/pki-framework/src/X509/Certificate/Time.php-  Qti-  <j	D      b   vendor/spomky-labs/pki-framework/src/X509/Certificate/Extension/CRLDistributionPointsExtension.php
  Qti
  vfߤ      g   vendor/spomky-labs/pki-framework/src/X509/Certificate/Extension/SubjectDirectoryAttributesExtension.php  Qti  |8\      n   vendor/spomky-labs/pki-framework/src/X509/Certificate/Extension/AccessDescription/SubjectAccessDescription.phps  Qtis  Τ      g   vendor/spomky-labs/pki-framework/src/X509/Certificate/Extension/AccessDescription/AccessDescription.php  Qti  01      p   vendor/spomky-labs/pki-framework/src/X509/Certificate/Extension/AccessDescription/AuthorityAccessDescription.phpF  QtiF  g<      b   vendor/spomky-labs/pki-framework/src/X509/Certificate/Extension/NoRevocationAvailableExtension.php}  Qti}  .Ƥ      ^   vendor/spomky-labs/pki-framework/src/X509/Certificate/Extension/PolicyConstraintsExtension.php  Qti  L      g   vendor/spomky-labs/pki-framework/src/X509/Certificate/Extension/AuthorityInformationAccessExtension.php
  Qti
  쭤      e   vendor/spomky-labs/pki-framework/src/X509/Certificate/Extension/SubjectInformationAccessExtension.php
  Qti
  lwr      ^   vendor/spomky-labs/pki-framework/src/X509/Certificate/Extension/TargetInformationExtension.phpB  QtiB  }_[      U   vendor/spomky-labs/pki-framework/src/X509/Certificate/Extension/KeyUsageExtension.php  Qti  k      U   vendor/spomky-labs/pki-framework/src/X509/Certificate/Extension/Target/TargetName.php  Qti  Mt      R   vendor/spomky-labs/pki-framework/src/X509/Certificate/Extension/Target/Targets.php
  Qti
  7P      Q   vendor/spomky-labs/pki-framework/src/X509/Certificate/Extension/Target/Target.phpm  Qtim  s      V   vendor/spomky-labs/pki-framework/src/X509/Certificate/Extension/Target/TargetGroup.php  Qti  Ԥ      `   vendor/spomky-labs/pki-framework/src/X509/Certificate/Extension/PolicyMappings/PolicyMapping.phpc  Qtic  J~      \   vendor/spomky-labs/pki-framework/src/X509/Certificate/Extension/NameConstraintsExtension.phpi  Qtii  hh      X   vendor/spomky-labs/pki-framework/src/X509/Certificate/Extension/FreshestCRLExtension.phpT  QtiT  SZ      T   vendor/spomky-labs/pki-framework/src/X509/Certificate/Extension/UnknownExtension.php  Qti  Cb&      b   vendor/spomky-labs/pki-framework/src/X509/Certificate/Extension/IssuerAlternativeNameExtension.php  Qti  m      `   vendor/spomky-labs/pki-framework/src/X509/Certificate/Extension/CertificatePoliciesExtension.phpl  Qtil  jR      ]   vendor/spomky-labs/pki-framework/src/X509/Certificate/Extension/InhibitAnyPolicyExtension.phpb  Qtib  `M      b   vendor/spomky-labs/pki-framework/src/X509/Certificate/Extension/DistributionPoint/RelativeName.phpb  Qtib  m      g   vendor/spomky-labs/pki-framework/src/X509/Certificate/Extension/DistributionPoint/DistributionPoint.php  Qti  ;Z@      ^   vendor/spomky-labs/pki-framework/src/X509/Certificate/Extension/DistributionPoint/FullName.php  Qti  7Ť      a   vendor/spomky-labs/pki-framework/src/X509/Certificate/Extension/DistributionPoint/ReasonFlags.php  Qti  F)'      k   vendor/spomky-labs/pki-framework/src/X509/Certificate/Extension/DistributionPoint/DistributionPointName.php  Qti  \D      c   vendor/spomky-labs/pki-framework/src/X509/Certificate/Extension/NameConstraints/GeneralSubtrees.php  Qti  
<      b   vendor/spomky-labs/pki-framework/src/X509/Certificate/Extension/NameConstraints/GeneralSubtree.php~
  Qti~
        ]   vendor/spomky-labs/pki-framework/src/X509/Certificate/Extension/ExtendedKeyUsageExtension.php  Qti  f      W   vendor/spomky-labs/pki-framework/src/X509/Certificate/Extension/AAControlsExtension.php  Qti  0e+      e   vendor/spomky-labs/pki-framework/src/X509/Certificate/Extension/CertificatePolicy/NoticeReference.php@  Qti@  UC      i   vendor/spomky-labs/pki-framework/src/X509/Certificate/Extension/CertificatePolicy/PolicyQualifierInfo.php  Qti        i   vendor/spomky-labs/pki-framework/src/X509/Certificate/Extension/CertificatePolicy/UserNoticeQualifier.php	  Qti	  G[      g   vendor/spomky-labs/pki-framework/src/X509/Certificate/Extension/CertificatePolicy/PolicyInformation.phpb  Qtib  ;      a   vendor/spomky-labs/pki-framework/src/X509/Certificate/Extension/CertificatePolicy/DisplayText.php0  Qti0  R"      b   vendor/spomky-labs/pki-framework/src/X509/Certificate/Extension/CertificatePolicy/CPSQualifier.phpG  QtiG         [   vendor/spomky-labs/pki-framework/src/X509/Certificate/Extension/PolicyMappingsExtension.php  Qti  NK)      M   vendor/spomky-labs/pki-framework/src/X509/Certificate/Extension/Extension.php'  Qti'  Vu8      c   vendor/spomky-labs/pki-framework/src/X509/Certificate/Extension/AuthorityKeyIdentifierExtension.php  Qti  |ؤ      c   vendor/spomky-labs/pki-framework/src/X509/Certificate/Extension/SubjectAlternativeNameExtension.php  Qti  dd      ]   vendor/spomky-labs/pki-framework/src/X509/Certificate/Extension/BasicConstraintsExtension.php{	  Qti{	        a   vendor/spomky-labs/pki-framework/src/X509/Certificate/Extension/SubjectKeyIdentifierExtension.php  Qti  Bb      E   vendor/spomky-labs/pki-framework/src/X509/Certificate/Certificate.php  Qti  ::      J   vendor/spomky-labs/pki-framework/src/X509/Certificate/UniqueIdentifier.php  Qti  /      J   vendor/spomky-labs/pki-framework/src/X509/Certificate/CertificateChain.php  Qti  ]      B   vendor/spomky-labs/pki-framework/src/X509/Certificate/Validity.phpr  Qtir  E8      K   vendor/spomky-labs/pki-framework/src/X509/Certificate/CertificateBundle.php  Qti  [      H   vendor/spomky-labs/pki-framework/src/X509/Certificate/TBSCertificate.php8  Qti8  u      D   vendor/spomky-labs/pki-framework/src/X509/Certificate/Extensions.php}$  Qti}$  	~HG      F   vendor/spomky-labs/pki-framework/src/X509/GeneralName/RegisteredID.php  Qti  t6      G   vendor/spomky-labs/pki-framework/src/X509/GeneralName/DirectoryName.phpW  QtiW  FX      F   vendor/spomky-labs/pki-framework/src/X509/GeneralName/EDIPartyName.php  Qti  H/6      C   vendor/spomky-labs/pki-framework/src/X509/GeneralName/OtherName.php  Qti  ~Ǥ      C   vendor/spomky-labs/pki-framework/src/X509/GeneralName/IPAddress.php  Qti  >Ф      E   vendor/spomky-labs/pki-framework/src/X509/GeneralName/X400Address.php  Qti  ~l      E   vendor/spomky-labs/pki-framework/src/X509/GeneralName/IPv4Address.php  Qti        F   vendor/spomky-labs/pki-framework/src/X509/GeneralName/GeneralNames.php  Qti  k%      S   vendor/spomky-labs/pki-framework/src/X509/GeneralName/UniformResourceIdentifier.php  Qti  ]~A      D   vendor/spomky-labs/pki-framework/src/X509/GeneralName/RFC822Name.php  Qti  Fܤ      E   vendor/spomky-labs/pki-framework/src/X509/GeneralName/GeneralName.php<  Qti<        E   vendor/spomky-labs/pki-framework/src/X509/GeneralName/IPv6Address.php  Qti  Wä      A   vendor/spomky-labs/pki-framework/src/X509/GeneralName/DNSName.php#  Qti#  :䷤      D   vendor/spomky-labs/pki-framework/src/X509/Feature/DateTimeHelper.php  Qti  ]v,      c   vendor/spomky-labs/pki-framework/src/X509/CertificationPath/PathValidation/PathValidationConfig.phpv  Qtiv        c   vendor/spomky-labs/pki-framework/src/X509/CertificationPath/PathValidation/PathValidationResult.phpT  QtiT  o      ]   vendor/spomky-labs/pki-framework/src/X509/CertificationPath/PathValidation/ValidatorState.php(  Qti(  ?=-      \   vendor/spomky-labs/pki-framework/src/X509/CertificationPath/PathValidation/PathValidator.php6B  Qti6B  F.      e   vendor/spomky-labs/pki-framework/src/X509/CertificationPath/PathBuilding/CertificationPathBuilder.php  Qti  C      _   vendor/spomky-labs/pki-framework/src/X509/CertificationPath/Exception/PathBuildingException.php  Qti  v      a   vendor/spomky-labs/pki-framework/src/X509/CertificationPath/Exception/PathValidationException.phpC  QtiC  Wb'      Q   vendor/spomky-labs/pki-framework/src/X509/CertificationPath/Policy/PolicyNode.php=  Qti=  /      Q   vendor/spomky-labs/pki-framework/src/X509/CertificationPath/Policy/PolicyTree.php5  Qti5  m      Q   vendor/spomky-labs/pki-framework/src/X509/CertificationPath/CertificationPath.php  Qti  =      O   vendor/spomky-labs/pki-framework/src/X509/Exception/X509ValidationException.php   Qti   ?$      i   vendor/spomky-labs/pki-framework/src/X509/AttributeCertificate/Attribute/AccessIdentityAttributeValue.php3  Qti3  Jmߤ      Z   vendor/spomky-labs/pki-framework/src/X509/AttributeCertificate/Attribute/IetfAttrValue.php  Qti  Y      Y   vendor/spomky-labs/pki-framework/src/X509/AttributeCertificate/Attribute/SvceAuthInfo.php	  Qti	   ے:      m   vendor/spomky-labs/pki-framework/src/X509/AttributeCertificate/Attribute/AuthenticationInfoAttributeValue.phpL  QtiL  h      k   vendor/spomky-labs/pki-framework/src/X509/AttributeCertificate/Attribute/ChargingIdentityAttributeValue.php  Qti  :      `   vendor/spomky-labs/pki-framework/src/X509/AttributeCertificate/Attribute/GroupAttributeValue.php  Qti  dm      [   vendor/spomky-labs/pki-framework/src/X509/AttributeCertificate/Attribute/IetfAttrSyntax.php  Qti  U!      _   vendor/spomky-labs/pki-framework/src/X509/AttributeCertificate/Attribute/RoleAttributeValue.php  Qti  Z      M   vendor/spomky-labs/pki-framework/src/X509/AttributeCertificate/Attributes.php  Qti  '(	      O   vendor/spomky-labs/pki-framework/src/X509/AttributeCertificate/IssuerSerial.php  Qti  f̤      I   vendor/spomky-labs/pki-framework/src/X509/AttributeCertificate/Holder.php  Qti        I   vendor/spomky-labs/pki-framework/src/X509/AttributeCertificate/V2Form.php  Qti        [   vendor/spomky-labs/pki-framework/src/X509/AttributeCertificate/AttributeCertificateInfo.php/&  Qti/&  Vs      S   vendor/spomky-labs/pki-framework/src/X509/AttributeCertificate/ObjectDigestInfo.php	  Qti	  J      P   vendor/spomky-labs/pki-framework/src/X509/AttributeCertificate/AttCertIssuer.php=  Qti=  Y{yB      W   vendor/spomky-labs/pki-framework/src/X509/AttributeCertificate/AttributeCertificate.php  Qti        X   vendor/spomky-labs/pki-framework/src/X509/AttributeCertificate/AttCertValidityPeriod.php  Qti  /      Y   vendor/spomky-labs/pki-framework/src/X509/AttributeCertificate/Validation/ACValidator.php  Qti  -      m   vendor/spomky-labs/pki-framework/src/X509/AttributeCertificate/Validation/Exception/ACValidationException.php
  Qti
  K      `   vendor/spomky-labs/pki-framework/src/X509/AttributeCertificate/Validation/ACValidationConfig.php\	  Qti\	  g      W   vendor/spomky-labs/pki-framework/src/X509/CertificationRequest/CertificationRequest.php	  Qti	  4X      b   vendor/spomky-labs/pki-framework/src/X509/CertificationRequest/Attribute/ExtensionRequestValue.php;  Qti;  &      M   vendor/spomky-labs/pki-framework/src/X509/CertificationRequest/Attributes.php  Qti  b>      [   vendor/spomky-labs/pki-framework/src/X509/CertificationRequest/CertificationRequestInfo.php  Qti   m      6   vendor/spomky-labs/pki-framework/src/X501/ASN1/RDN.php  Qti  R]      @   vendor/spomky-labs/pki-framework/src/X501/ASN1/AttributeType.php@  Qti@  t      R   vendor/spomky-labs/pki-framework/src/X501/ASN1/Collection/SequenceOfAttributes.php  Qti  X/]      M   vendor/spomky-labs/pki-framework/src/X501/ASN1/Collection/SetOfAttributes.php-  Qti-  ,      Q   vendor/spomky-labs/pki-framework/src/X501/ASN1/Collection/AttributeCollection.php  Qti  ~      <   vendor/spomky-labs/pki-framework/src/X501/ASN1/Attribute.php  Qti  Ii      S   vendor/spomky-labs/pki-framework/src/X501/ASN1/AttributeValue/LocalityNameValue.php  Qti   꾤      P   vendor/spomky-labs/pki-framework/src/X501/ASN1/AttributeValue/GivenNameValue.php  Qti  u,Ȥ      W   vendor/spomky-labs/pki-framework/src/X501/ASN1/AttributeValue/OrganizationNameValue.php  Qti  H9      L   vendor/spomky-labs/pki-framework/src/X501/ASN1/AttributeValue/TitleValue.php  Qti  `+2      S   vendor/spomky-labs/pki-framework/src/X501/ASN1/AttributeValue/SerialNumberValue.php  Qti  8V      P   vendor/spomky-labs/pki-framework/src/X501/ASN1/AttributeValue/AttributeValue.php  Qti  Sޤ      R   vendor/spomky-labs/pki-framework/src/X501/ASN1/AttributeValue/DescriptionValue.php  Qti  /\ۤ      R   vendor/spomky-labs/pki-framework/src/X501/ASN1/AttributeValue/CountryNameValue.php  Qti  OR      Q   vendor/spomky-labs/pki-framework/src/X501/ASN1/AttributeValue/CommonNameValue.php  Qti  /=      N   vendor/spomky-labs/pki-framework/src/X501/ASN1/AttributeValue/SurnameValue.php  Qti        P   vendor/spomky-labs/pki-framework/src/X501/ASN1/AttributeValue/PseudonymValue.php  Qti  {      Z   vendor/spomky-labs/pki-framework/src/X501/ASN1/AttributeValue/StateOrProvinceNameValue.php  Qti  (      ^   vendor/spomky-labs/pki-framework/src/X501/ASN1/AttributeValue/Feature/PrintableStringValue.php  Qti  i;      Y   vendor/spomky-labs/pki-framework/src/X501/ASN1/AttributeValue/Feature/DirectoryString.php  Qti  j      W   vendor/spomky-labs/pki-framework/src/X501/ASN1/AttributeValue/UnknownAttributeValue.php4	  Qti4	  s      ]   vendor/spomky-labs/pki-framework/src/X501/ASN1/AttributeValue/OrganizationalUnitNameValue.php  Qti  A      K   vendor/spomky-labs/pki-framework/src/X501/ASN1/AttributeValue/NameValue.php~  Qti~  `G}      H   vendor/spomky-labs/pki-framework/src/X501/ASN1/AttributeTypeAndValue.php[  Qti[  |      7   vendor/spomky-labs/pki-framework/src/X501/ASN1/Name.php=  Qti=  v      9   vendor/spomky-labs/pki-framework/src/X501/DN/DNParser.php<(  Qti<(  w1      G   vendor/spomky-labs/pki-framework/src/X501/MatchingRule/MatchingRule.phpO  QtiO  pPD      J   vendor/spomky-labs/pki-framework/src/X501/MatchingRule/CaseIgnoreMatch.php  Qti  K       I   vendor/spomky-labs/pki-framework/src/X501/MatchingRule/CaseExactMatch.php  Qti  5n      Q   vendor/spomky-labs/pki-framework/src/X501/MatchingRule/StringPrepMatchingRule.phpy  Qtiy  gS      F   vendor/spomky-labs/pki-framework/src/X501/MatchingRule/BinaryMatch.php  Qti  $      @   vendor/spomky-labs/pki-framework/src/X501/StringPrep/MapStep.phpr  Qtir  O;      F   vendor/spomky-labs/pki-framework/src/X501/StringPrep/NormalizeStep.php  Qti  RX      D   vendor/spomky-labs/pki-framework/src/X501/StringPrep/PrepareStep.php  Qti  9P      F   vendor/spomky-labs/pki-framework/src/X501/StringPrep/TranscodeStep.php;	  Qti;	  7      F   vendor/spomky-labs/pki-framework/src/X501/StringPrep/CheckBidiStep.php  Qti  ä      G   vendor/spomky-labs/pki-framework/src/X501/StringPrep/StringPreparer.php  Qti  B      E   vendor/spomky-labs/pki-framework/src/X501/StringPrep/ProhibitStep.php  Qti  O      [   vendor/spomky-labs/pki-framework/src/X501/StringPrep/InsignificantNonSubstringSpaceStep.php  Qti  h      O   vendor/spomky-labs/pki-framework/src/CryptoTypes/Signature/Ed25519Signature.php  Qti  uH      M   vendor/spomky-labs/pki-framework/src/CryptoTypes/Signature/Ed448Signature.php  Qti  k      O   vendor/spomky-labs/pki-framework/src/CryptoTypes/Signature/GenericSignature.php?  Qti?  d      J   vendor/spomky-labs/pki-framework/src/CryptoTypes/Signature/ECSignature.php  Qti  i      K   vendor/spomky-labs/pki-framework/src/CryptoTypes/Signature/RSASignature.php&  Qti&  h      H   vendor/spomky-labs/pki-framework/src/CryptoTypes/Signature/Signature.php  Qti        P   vendor/spomky-labs/pki-framework/src/CryptoTypes/Asymmetric/OneAsymmetricKey.php)  Qti)  lB      d   vendor/spomky-labs/pki-framework/src/CryptoTypes/Asymmetric/Attribute/OneAsymmetricKeyAttributes.php  Qti  !      P   vendor/spomky-labs/pki-framework/src/CryptoTypes/Asymmetric/RSA/RSAPublicKey.php  Qti  _ӹȤ      Q   vendor/spomky-labs/pki-framework/src/CryptoTypes/Asymmetric/RSA/RSAPrivateKey.php>  Qti>  =#      W   vendor/spomky-labs/pki-framework/src/CryptoTypes/Asymmetric/RSA/RSASSAPSSPrivateKey.phpY  QtiY  K      N   vendor/spomky-labs/pki-framework/src/CryptoTypes/Asymmetric/EC/ECPublicKey.phpF  QtiF  Ƥ      O   vendor/spomky-labs/pki-framework/src/CryptoTypes/Asymmetric/EC/ECPrivateKey.php  Qti  @0      O   vendor/spomky-labs/pki-framework/src/CryptoTypes/Asymmetric/EC/ECConversion.php  Qti  6u      I   vendor/spomky-labs/pki-framework/src/CryptoTypes/Asymmetric/PublicKey.php/  Qti/  m>      N   vendor/spomky-labs/pki-framework/src/CryptoTypes/Asymmetric/PrivateKeyInfo.php  Qti  m      Y   vendor/spomky-labs/pki-framework/src/CryptoTypes/Asymmetric/RFC8410/RFC8410PrivateKey.phpc
  Qtic
  xu      X   vendor/spomky-labs/pki-framework/src/CryptoTypes/Asymmetric/RFC8410/RFC8410PublicKey.php  Qti        ^   vendor/spomky-labs/pki-framework/src/CryptoTypes/Asymmetric/RFC8410/Curve448/X448PublicKey.php  Qti  \פ      _   vendor/spomky-labs/pki-framework/src/CryptoTypes/Asymmetric/RFC8410/Curve448/Ed448PublicKey.php  Qti  5!դ      _   vendor/spomky-labs/pki-framework/src/CryptoTypes/Asymmetric/RFC8410/Curve448/X448PrivateKey.php  Qti  TA,      `   vendor/spomky-labs/pki-framework/src/CryptoTypes/Asymmetric/RFC8410/Curve448/Ed448PrivateKey.php  Qti  U      b   vendor/spomky-labs/pki-framework/src/CryptoTypes/Asymmetric/RFC8410/Curve25519/X25519PublicKey.php  Qti  45      f   vendor/spomky-labs/pki-framework/src/CryptoTypes/Asymmetric/RFC8410/Curve25519/Curve25519PublicKey.php  Qti   P      c   vendor/spomky-labs/pki-framework/src/CryptoTypes/Asymmetric/RFC8410/Curve25519/X25519PrivateKey.php  Qti  ]Б      g   vendor/spomky-labs/pki-framework/src/CryptoTypes/Asymmetric/RFC8410/Curve25519/Curve25519PrivateKey.php3  Qti3  5%      c   vendor/spomky-labs/pki-framework/src/CryptoTypes/Asymmetric/RFC8410/Curve25519/Ed25519PublicKey.php  Qti  .@      d   vendor/spomky-labs/pki-framework/src/CryptoTypes/Asymmetric/RFC8410/Curve25519/Ed25519PrivateKey.php  Qti  
      M   vendor/spomky-labs/pki-framework/src/CryptoTypes/Asymmetric/PublicKeyInfo.php  Qti  v_ޤ      J   vendor/spomky-labs/pki-framework/src/CryptoTypes/Asymmetric/PrivateKey.php*  Qti*  
ʤ      d   vendor/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/SpecificAlgorithmIdentifier.phpV  QtiV  E[      \   vendor/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/AlgorithmIdentifier.phpl  Qtil        }   vendor/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Signature/SHA384WithRSAEncryptionAlgorithmIdentifier.php  Qti  /      z   vendor/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Signature/MD2WithRSAEncryptionAlgorithmIdentifier.php  Qti  d      u   vendor/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Signature/ECDSAWithSHA256AlgorithmIdentifier.php  Qti   פ      u   vendor/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Signature/ECDSAWithSHA224AlgorithmIdentifier.php  Qti  :)D      z   vendor/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Signature/MD5WithRSAEncryptionAlgorithmIdentifier.php  Qti  X٤      y   vendor/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Signature/RFC3279RSASignatureAlgorithmIdentifier.php  Qti  Ä      z   vendor/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Signature/MD4WithRSAEncryptionAlgorithmIdentifier.php  Qti  Kɤ      y   vendor/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Signature/RFC4055RSASignatureAlgorithmIdentifier.phpk  Qtik  k[      u   vendor/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Signature/ECDSAWithSHA512AlgorithmIdentifier.php  Qti  	s      r   vendor/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Signature/RSASignatureAlgorithmIdentifier.php  Qti  s      }   vendor/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Signature/SHA256WithRSAEncryptionAlgorithmIdentifier.php  Qti  %o      s   vendor/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Signature/ECDSAWithSHA1AlgorithmIdentifier.php  Qti  g      u   vendor/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Signature/ECDSAWithSHA384AlgorithmIdentifier.php  Qti  U      q   vendor/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Signature/ECSignatureAlgorithmIdentifier.php  Qti  }Ϥ      }   vendor/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Signature/SHA512WithRSAEncryptionAlgorithmIdentifier.php  Qti  {Ȥ      {   vendor/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Signature/SHA1WithRSAEncryptionAlgorithmIdentifier.php  Qti  g      }   vendor/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Signature/SHA224WithRSAEncryptionAlgorithmIdentifier.php  Qti  fQ      o   vendor/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Hash/HMACWithSHA224AlgorithmIdentifier.php  Qti  E      g   vendor/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Hash/SHA224AlgorithmIdentifier.php  Qti        o   vendor/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Hash/HMACWithSHA256AlgorithmIdentifier.php  Qti  &o      g   vendor/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Hash/SHA256AlgorithmIdentifier.php  Qti  ?j      l   vendor/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Hash/RFC4231HMACAlgorithmIdentifier.phpr  Qtir  3U      o   vendor/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Hash/HMACWithSHA512AlgorithmIdentifier.php  Qti  XD>      g   vendor/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Hash/SHA512AlgorithmIdentifier.php  Qti  i3i      m   vendor/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Hash/HMACWithSHA1AlgorithmIdentifier.php  Qti  Jx      e   vendor/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Hash/SHA2AlgorithmIdentifier.php  Qti  gP      d   vendor/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Hash/MD5AlgorithmIdentifier.php  Qti  2t      e   vendor/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Hash/SHA1AlgorithmIdentifier.phpu  Qtiu  (      o   vendor/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Hash/HMACWithSHA384AlgorithmIdentifier.php  Qti  9}      g   vendor/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Hash/SHA384AlgorithmIdentifier.php  Qti  |w      i   vendor/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Cipher/RC2CBCAlgorithmIdentifier.php  Qti  'ˤ      m   vendor/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Cipher/DESEDE3CBCAlgorithmIdentifier.php_  Qti_  n      l   vendor/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Cipher/AES192CBCAlgorithmIdentifier.php  Qti  YlĤ      i   vendor/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Cipher/AESCBCAlgorithmIdentifier.php  Qti  n      i   vendor/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Cipher/CipherAlgorithmIdentifier.php3  Qti3  lG      i   vendor/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Cipher/DESCBCAlgorithmIdentifier.php  Qti        n   vendor/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Cipher/BlockCipherAlgorithmIdentifier.phpc  Qtic  ;      l   vendor/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Cipher/AES128CBCAlgorithmIdentifier.phpx  Qtix  Ǔ      l   vendor/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Cipher/AES256CBCAlgorithmIdentifier.php  Qti  (K      r   vendor/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Asymmetric/ECPublicKeyAlgorithmIdentifier.php)  Qti)  K      m   vendor/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Asymmetric/X25519AlgorithmIdentifier.php(  Qti(        k   vendor/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Asymmetric/X448AlgorithmIdentifier.php   Qti   㭬      p   vendor/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Asymmetric/RFC8410EdAlgorithmIdentifier.php  Qti  5Y      t   vendor/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Asymmetric/RSAEncryptionAlgorithmIdentifier.php  Qti  4Ȥ      l   vendor/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Asymmetric/Ed448AlgorithmIdentifier.php  Qti  *2      o   vendor/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Asymmetric/RFC8410XAlgorithmIdentifier.php  Qti  t3]      z   vendor/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Asymmetric/RSAPSSSSAEncryptionAlgorithmIdentifier.php  Qti  此      n   vendor/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Asymmetric/Ed25519AlgorithmIdentifier.php  Qti  솤      c   vendor/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/AlgorithmIdentifierFactory.php$  Qti$  mo      m   vendor/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Feature/SignatureAlgorithmIdentifier.php  Qti  щf      g   vendor/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Feature/PRFAlgorithmIdentifier.php   Qti   !$      t   vendor/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Feature/AsymmetricCryptoAlgorithmIdentifier.php  Qti  C      h   vendor/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Feature/HashAlgorithmIdentifier.php   Qti   &-      n   vendor/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Feature/EncryptionAlgorithmIdentifier.php   Qti   bO      h   vendor/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Feature/AlgorithmIdentifierType.phpv  Qtiv  5Z(      d   vendor/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/AlgorithmIdentifierProvider.php  Qti  VW      c   vendor/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/GenericAlgorithmIdentifier.php  Qti        +   vendor/spomky-labs/otphp/CODE_OF_CONDUCT.md  Qti  m      $   vendor/spomky-labs/otphp/RELEASES.md  Qti  vGW$          vendor/spomky-labs/otphp/LICENSE@  Qti@  xi      "   vendor/spomky-labs/otphp/README.md$  Qti$  /      &   vendor/spomky-labs/otphp/composer.json  Qti        $   vendor/spomky-labs/otphp/SECURITY.mdk  Qtik  5&      %   vendor/spomky-labs/otphp/src/TOTP.php  Qti  r.      (   vendor/spomky-labs/otphp/src/Factory.php  Qti  jg      -   vendor/spomky-labs/otphp/src/OTPInterface.php+  Qti+  bm       .   vendor/spomky-labs/otphp/src/TOTPInterface.php  Qti  Τۤ      $   vendor/spomky-labs/otphp/src/OTP.php2  Qti2  0      %   vendor/spomky-labs/otphp/src/HOTP.phpu  Qtiu  ~&      .   vendor/spomky-labs/otphp/src/HOTPInterface.php  Qti  u,Z      1   vendor/spomky-labs/otphp/src/FactoryInterface.php  Qti  IA      $   vendor/spomky-labs/otphp/src/Url.php
  Qti
  D%U|      @   vendor/spomky-labs/otphp/src/Exception/OTPExceptionInterface.phpN  QtiN  >      E   vendor/spomky-labs/otphp/src/Exception/ParameterNotFoundException.php
  Qti
  @      B   vendor/spomky-labs/otphp/src/Exception/SecretDecodingException.php  Qti  U,      @   vendor/spomky-labs/otphp/src/Exception/InvalidLabelException.phph  Qtih  s      J   vendor/spomky-labs/otphp/src/Exception/InvalidProvisioningUriException.php  Qti  1໤      D   vendor/spomky-labs/otphp/src/Exception/InvalidParameterException.php{  Qti{  jrI&      .   vendor/spomky-labs/otphp/src/InternalClock.phpD  QtiD  ty      $   vendor/doctrine/deprecations/LICENSE)  Qti)  "0      &   vendor/doctrine/deprecations/README.mda  Qtia  X      *   vendor/doctrine/deprecations/composer.json  Qti  ?=      ?   vendor/doctrine/deprecations/src/PHPUnit/VerifyDeprecations.php`  Qti`  (      0   vendor/doctrine/deprecations/src/Deprecation.phpu$  Qtiu$  ޤ         vendor/firebase/php-jwt/LICENSE  Qti  #      $   vendor/firebase/php-jwt/CHANGELOG.mdv2  Qtiv2        !   vendor/firebase/php-jwt/README.mdl4  Qtil4  w      %   vendor/firebase/php-jwt/composer.json  Qti  (ɹ4      9   vendor/firebase/php-jwt/src/SignatureInvalidException.phpu   Qtiu   Ͻ      4   vendor/firebase/php-jwt/src/BeforeValidException.phpr  Qtir  $Ѥ      ,   vendor/firebase/php-jwt/src/CachedKeySet.php  Qti  L      #   vendor/firebase/php-jwt/src/Key.php  Qti  LQ      #   vendor/firebase/php-jwt/src/JWK.php .  Qti .  ҋ      @   vendor/firebase/php-jwt/src/JWTExceptionWithPayloadInterface.php  Qti  z:      0   vendor/firebase/php-jwt/src/ExpiredException.phpR  QtiR  0      #   vendor/firebase/php-jwt/src/JWT.phpqh  Qtiqh  {s         vendor/brick/math/LICENSEA  QtiA  ݸL         vendor/brick/math/CHANGELOG.md`O  Qti`O        $   vendor/brick/math/psalm-baseline.xml	  Qti	           vendor/brick/math/composer.jsonR  QtiR  IG      &   vendor/brick/math/src/RoundingMode.php  Qti        ;   vendor/brick/math/src/Internal/Calculator/GmpCalculator.php	  Qti	  A!      >   vendor/brick/math/src/Internal/Calculator/BcMathCalculator.php  Qti  ៤      >   vendor/brick/math/src/Internal/Calculator/NativeCalculator.php7  Qti7  ڊ8      -   vendor/brick/math/src/Internal/Calculator.phpI  QtiI  6J4      $   vendor/brick/math/src/BigInteger.php  Qti  'ʵ      #   vendor/brick/math/src/BigNumber.phpp>  Qtip>  /      $   vendor/brick/math/src/BigDecimal.php?W  Qti?W  s#Ѥ      1   vendor/brick/math/src/Exception/MathException.php   Qti   }&      9   vendor/brick/math/src/Exception/NumberFormatException.php  Qti   [      ;   vendor/brick/math/src/Exception/NegativeNumberException.php  Qti  +;      ;   vendor/brick/math/src/Exception/DivisionByZeroException.php  Qti  KѤ      <   vendor/brick/math/src/Exception/IntegerOverflowException.php+  Qti+  f      >   vendor/brick/math/src/Exception/RoundingNecessaryException.php  Qti  *      %   vendor/brick/math/src/BigRational.php.  Qti.  =      (   vendor/justinrainbow/json-schema/LICENSE   Qti         =   vendor/justinrainbow/json-schema/bin/extract-release-notes.sh  Qti  rs      7   vendor/justinrainbow/json-schema/bin/prepare-release.shn  Qtin  HpҤ      2   vendor/justinrainbow/json-schema/bin/validate-json  Qti  oǈԤ      8   vendor/justinrainbow/json-schema/bin/update-changelog.sh&	  Qti&	  }X      -   vendor/justinrainbow/json-schema/CHANGELOG.md>  Qti>  ~      F   vendor/justinrainbow/json-schema/dist/schema/json-schema-draft-03.json  Qti  -aߤ      F   vendor/justinrainbow/json-schema/dist/schema/json-schema-draft-04.json  Qti  Nߤ      F   vendor/justinrainbow/json-schema/dist/schema/json-schema-draft-07.json  Qti  -X      F   vendor/justinrainbow/json-schema/dist/schema/json-schema-draft-06.json  Qti  vS      *   vendor/justinrainbow/json-schema/README.md"  Qti"  (2      /   vendor/justinrainbow/json-schema/UPGRADE-6.0.md?  Qti?  3      0   vendor/justinrainbow/json-schema/CONTRIBUTING.md!  Qti!  	      .   vendor/justinrainbow/json-schema/composer.json	  Qti	  oI      ,   vendor/justinrainbow/json-schema/SECURITY.md  Qti  -      ;   vendor/justinrainbow/json-schema/src/JsonSchema/Rfc3339.php,  Qti,  
{      =   vendor/justinrainbow/json-schema/src/JsonSchema/Validator.php{  Qti{         I   vendor/justinrainbow/json-schema/src/JsonSchema/UriRetrieverInterface.php-  Qti-  l3      P   vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/ObjectConstraint.php|  Qti|  H4      G   vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/Factory.php  Qti  y      O   vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/ConstConstraint.php  Qti  C4R       P   vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/NumberConstraint.phpf  Qtif  Eۤ      N   vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/TypeConstraint.php*  Qti*  2      N   vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/BaseConstraint.php  Qti  	f      N   vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/EnumConstraint.php  Qti        P   vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/StringConstraint.php@  Qti@  EG      V   vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/Drafts/Draft07/Factory.php  Qti  @EB      i   vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/Drafts/Draft07/ExclusiveMinimumConstraint.php+  Qti+  rjY      h   vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/Drafts/Draft07/AdditionalItemsConstraint.phpU  QtiU  ո      ^   vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/Drafts/Draft07/ConstConstraint.php  Qti        m   vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/Drafts/Draft07/AdditionalPropertiesConstraint.php  Qti  \      ]   vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/Drafts/Draft07/TypeConstraint.php  Qti  fm      ^   vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/Drafts/Draft07/AnyOfConstraint.php  Qti  %E	      `   vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/Drafts/Draft07/ContentConstraint.php  Qti  c      ]   vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/Drafts/Draft07/EnumConstraint.php  Qti  oeY      h   vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/Drafts/Draft07/PropertiesNamesConstraint.php  Qti  Uo      `   vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/Drafts/Draft07/MaximumConstraint.php  Qti  !'      `   vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/Drafts/Draft07/PatternConstraint.php  Qti  ͜      b   vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/Drafts/Draft07/MaxLengthConstraint.php(  Qti(  (l      a   vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/Drafts/Draft07/MinItemsConstraint.php  Qti  rT&      d   vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/Drafts/Draft07/UniqueItemsConstraint.php\  Qti\  Y      i   vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/Drafts/Draft07/ExclusiveMaximumConstraint.php+  Qti+  'Jq      e   vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/Drafts/Draft07/DependenciesConstraint.php  Qti  RM      c   vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/Drafts/Draft07/MultipleOfConstraint.php  Qti  6      ^   vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/Drafts/Draft07/AllOfConstraint.php  Qti  U      \   vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/Drafts/Draft07/RefConstraint.php  Qti  K2      ^   vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/Drafts/Draft07/ItemsConstraint.php  Qti  z      c   vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/Drafts/Draft07/PropertiesConstraint.php.  Qti.  	-[      f   vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/Drafts/Draft07/MaxPropertiesConstraint.phpJ  QtiJ  SL      \   vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/Drafts/Draft07/NotConstraint.php'  Qti'  njx      _   vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/Drafts/Draft07/FormatConstraint.phpO.  QtiO.  a      a   vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/Drafts/Draft07/ContainsConstraint.php  Qti  &       c   vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/Drafts/Draft07/IfThenElseConstraint.php  Qti  	      ^   vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/Drafts/Draft07/OneOfConstraint.phpg  Qtig  "      a   vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/Drafts/Draft07/MaxItemsConstraint.php  Qti  +      `   vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/Drafts/Draft07/MinimumConstraint.php  Qti  d&      j   vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/Drafts/Draft07/PatternPropertiesConstraint.php  Qti  ъ      `   vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/Drafts/Draft07/Draft07Constraint.php  Qti  p싾      b   vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/Drafts/Draft07/MinLengthConstraint.php(  Qti(  A-      a   vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/Drafts/Draft07/RequiredConstraint.phpi  Qtii  BE?      f   vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/Drafts/Draft07/MinPropertiesConstraint.phpJ  QtiJ  "L      V   vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/Drafts/Draft06/Factory.phpg  Qtig  J      i   vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/Drafts/Draft06/ExclusiveMinimumConstraint.php+  Qti+  m      h   vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/Drafts/Draft06/AdditionalItemsConstraint.phpU  QtiU  Τ      ^   vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/Drafts/Draft06/ConstConstraint.php  Qti  Nu\      m   vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/Drafts/Draft06/AdditionalPropertiesConstraint.php  Qti        `   vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/Drafts/Draft06/Draft06Constraint.php  Qti  +4T7      ]   vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/Drafts/Draft06/TypeConstraint.php  Qti  Uׇ      ^   vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/Drafts/Draft06/AnyOfConstraint.php  Qti  HC      ]   vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/Drafts/Draft06/EnumConstraint.php  Qti  FS_      h   vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/Drafts/Draft06/PropertiesNamesConstraint.php  Qti  ~s      `   vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/Drafts/Draft06/MaximumConstraint.php  Qti  b      `   vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/Drafts/Draft06/PatternConstraint.php  Qti  I      b   vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/Drafts/Draft06/MaxLengthConstraint.php(  Qti(  7      a   vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/Drafts/Draft06/MinItemsConstraint.php  Qti  Ҥ      d   vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/Drafts/Draft06/UniqueItemsConstraint.php\  Qti\  Uղ      i   vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/Drafts/Draft06/ExclusiveMaximumConstraint.php+  Qti+  $UK      e   vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/Drafts/Draft06/DependenciesConstraint.php  Qti  [      c   vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/Drafts/Draft06/MultipleOfConstraint.php  Qti  YZ      ^   vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/Drafts/Draft06/AllOfConstraint.php  Qti  &):      \   vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/Drafts/Draft06/RefConstraint.php  Qti  bh!@      ^   vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/Drafts/Draft06/ItemsConstraint.php  Qti  7
l      c   vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/Drafts/Draft06/PropertiesConstraint.php.  Qti.  ٲ      f   vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/Drafts/Draft06/MaxPropertiesConstraint.phpJ  QtiJ  `~ݤ      \   vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/Drafts/Draft06/NotConstraint.php'  Qti'  <"      _   vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/Drafts/Draft06/FormatConstraint.php  Qti  n*      a   vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/Drafts/Draft06/ContainsConstraint.php  Qti  rĤ      ^   vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/Drafts/Draft06/OneOfConstraint.phpg  Qtig  b(em      a   vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/Drafts/Draft06/MaxItemsConstraint.php  Qti  (hx      `   vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/Drafts/Draft06/MinimumConstraint.php  Qti  W?.      j   vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/Drafts/Draft06/PatternPropertiesConstraint.php  Qti  c      b   vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/Drafts/Draft06/MinLengthConstraint.php(  Qti(  g,J      a   vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/Drafts/Draft06/RequiredConstraint.phpi  Qtii  qە@      f   vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/Drafts/Draft06/MinPropertiesConstraint.phpJ  QtiJ  ݤ      S   vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/ConstraintInterface.php  Qti  l      T   vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/CollectionConstraint.phpQ  QtiQ  Ln      J   vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/Constraint.php  Qti  Ne~      P   vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/FormatConstraint.php  Qti  )Ԥ      \   vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/TypeCheck/TypeCheckInterface.php  Qti  ܎      Y   vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/TypeCheck/StrictTypeCheck.phpN  QtiN  f/n      X   vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/TypeCheck/LooseTypeCheck.php  Qti   %      S   vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/UndefinedConstraint.php>  Qti>  {      P   vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/SchemaConstraint.php  Qti  y/j      8   vendor/justinrainbow/json-schema/src/JsonSchema/Enum.php   Qti   2E      C   vendor/justinrainbow/json-schema/src/JsonSchema/Entity/ErrorBag.php>  Qti>  Fw      F   vendor/justinrainbow/json-schema/src/JsonSchema/Entity/JsonPointer.php~  Qti~        H   vendor/justinrainbow/json-schema/src/JsonSchema/Entity/ErrorBagProxy.php  Qti  lR      H   vendor/justinrainbow/json-schema/src/JsonSchema/UriResolverInterface.php:  Qti:  89      C   vendor/justinrainbow/json-schema/src/JsonSchema/ConstraintError.php  Qti  v>      K   vendor/justinrainbow/json-schema/src/JsonSchema/Iterator/ObjectIterator.php%  Qti%  XS      A   vendor/justinrainbow/json-schema/src/JsonSchema/SchemaStorage.php[   Qti[   b      D   vendor/justinrainbow/json-schema/src/JsonSchema/DraftIdentifiers.php  Qti  Τ&      X   vendor/justinrainbow/json-schema/src/JsonSchema/Uri/Retrievers/UriRetrieverInterface.php  Qti  }bU      T   vendor/justinrainbow/json-schema/src/JsonSchema/Uri/Retrievers/AbstractRetriever.php  Qti  	&      G   vendor/justinrainbow/json-schema/src/JsonSchema/Uri/Retrievers/Curl.php  Qti  ٪_%      R   vendor/justinrainbow/json-schema/src/JsonSchema/Uri/Retrievers/FileGetContents.php  Qti        R   vendor/justinrainbow/json-schema/src/JsonSchema/Uri/Retrievers/PredefinedArray.php%  Qti%  ޤ      D   vendor/justinrainbow/json-schema/src/JsonSchema/Uri/UriRetriever.php-$  Qti-$  8.;      C   vendor/justinrainbow/json-schema/src/JsonSchema/Uri/UriResolver.php  Qti  b      W   vendor/justinrainbow/json-schema/src/JsonSchema/Exception/ResourceNotFoundException.php|  Qti|  W      P   vendor/justinrainbow/json-schema/src/JsonSchema/Exception/ExceptionInterface.phpr   Qtir   3I      N   vendor/justinrainbow/json-schema/src/JsonSchema/Exception/RuntimeException.php  Qti  w5¤      W   vendor/justinrainbow/json-schema/src/JsonSchema/Exception/InvalidSourceUriException.php  Qti  !!      V   vendor/justinrainbow/json-schema/src/JsonSchema/Exception/InvalidArgumentException.php  Qti  &      ^   vendor/justinrainbow/json-schema/src/JsonSchema/Exception/UnresolvableJsonPointerException.php  Qti  uQ      Q   vendor/justinrainbow/json-schema/src/JsonSchema/Exception/ValidationException.phpA  QtiA  &}      T   vendor/justinrainbow/json-schema/src/JsonSchema/Exception/InvalidConfigException.phpy  Qtiy  !u      S   vendor/justinrainbow/json-schema/src/JsonSchema/Exception/JsonDecodingException.php
  Qti
        T   vendor/justinrainbow/json-schema/src/JsonSchema/Exception/InvalidSchemaException.phpv  Qtiv  N      R   vendor/justinrainbow/json-schema/src/JsonSchema/Exception/UriResolverException.phpr  Qtir  P      ]   vendor/justinrainbow/json-schema/src/JsonSchema/Exception/InvalidSchemaMediaTypeException.php  Qti        J   vendor/justinrainbow/json-schema/src/JsonSchema/SchemaStorageInterface.php  Qti  d      E   vendor/justinrainbow/json-schema/src/JsonSchema/Tool/DeepComparer.php  Qti  Ȥ      O   vendor/justinrainbow/json-schema/src/JsonSchema/Tool/Validator/UriValidator.php  Qti  ~       ]   vendor/justinrainbow/json-schema/src/JsonSchema/Tool/Validator/RelativeReferenceValidator.php}  Qti}  \|<      A   vendor/justinrainbow/json-schema/src/JsonSchema/Tool/DeepCopy.php  Qti        +   vendor/crell/api-problem/CODE_OF_CONDUCT.mda  Qtia  &          vendor/crell/api-problem/LICENSE'  Qti'  {^      %   vendor/crell/api-problem/CHANGELOG.md  Qti  BZ      "   vendor/crell/api-problem/README.md  Qti  $ؒ      (   vendor/crell/api-problem/CONTRIBUTING.md  Qti  Y      -   vendor/crell/api-problem/MAINTENANCE-TERMS.md  Qti  e誤      &   vendor/crell/api-problem/composer.json<  Qti<  'tAʤ      $   vendor/crell/api-problem/SECURITY.mdw	  Qtiw	  _yU      4   vendor/crell/api-problem/src/JsonEncodeException.php   Qti   ewF      .   vendor/crell/api-problem/src/HttpConverter.php3
  Qti3
  \=      3   vendor/crell/api-problem/src/JsonParseException.phpI  QtiI  :R      .   vendor/crell/api-problem/src/JsonException.php  Qti  w>      +   vendor/crell/api-problem/src/ApiProblem.phpG  QtiG  ɞ?         vendor/psr/cache/CHANGELOG.md  Qti  -	G         vendor/psr/cache/README.md"  Qti"  (AcӤ         vendor/psr/cache/LICENSE.txt8  Qti8  Df         vendor/psr/cache/composer.json4  Qti4  C      /   vendor/psr/cache/src/CacheItemPoolInterface.php~  Qti~  z      +   vendor/psr/cache/src/CacheItemInterface.php   Qti   :N      1   vendor/psr/cache/src/InvalidArgumentException.php:  Qti:  MY      '   vendor/psr/cache/src/CacheException.php   Qti   BJ      #   vendor/psr/event-dispatcher/LICENSE(  Qti(  }]      %   vendor/psr/event-dispatcher/README.mdE  QtiE  S      )   vendor/psr/event-dispatcher/composer.jsonb  Qtib  q      =   vendor/psr/event-dispatcher/src/ListenerProviderInterface.php  Qti  5      <   vendor/psr/event-dispatcher/src/EventDispatcherInterface.php  Qti        ;   vendor/psr/event-dispatcher/src/StoppableEventInterface.php   Qti   &&X         vendor/psr/http-message/LICENSE=  Qti=        $   vendor/psr/http-message/CHANGELOG.md3  Qti3  :\Y      !   vendor/psr/http-message/README.md  Qti        %   vendor/psr/http-message/composer.json  Qti  7      6   vendor/psr/http-message/src/ServerRequestInterface.php=(  Qti=(  aAP      ,   vendor/psr/http-message/src/UriInterface.php2  Qti2  Lxj      /   vendor/psr/http-message/src/StreamInterface.php  Qti  >      5   vendor/psr/http-message/src/UploadedFileInterface.php  Qti  ǎ      0   vendor/psr/http-message/src/RequestInterface.phpA  QtiA  	      1   vendor/psr/http-message/src/ResponseInterface.phpW
  QtiW
  -D      0   vendor/psr/http-message/src/MessageInterface.php  Qti  #U         vendor/psr/container/LICENSEy  Qtiy  Op         vendor/psr/container/README.mdB  QtiB  g?      "   vendor/psr/container/composer.json  Qti  nY      7   vendor/psr/container/src/NotFoundExceptionInterface.php   Qti   B@      /   vendor/psr/container/src/ContainerInterface.php$  Qti$  	aZ      8   vendor/psr/container/src/ContainerExceptionInterface.php   Qti              vendor/psr/http-client/LICENSE=  Qti=  S      #   vendor/psr/http-client/CHANGELOG.md  Qti  z򪌤          vendor/psr/http-client/README.md%  Qti%  F      $   vendor/psr/http-client/composer.json  Qti  bϤ      8   vendor/psr/http-client/src/NetworkExceptionInterface.php  Qti  B      8   vendor/psr/http-client/src/RequestExceptionInterface.phpg  Qtig        .   vendor/psr/http-client/src/ClientInterface.php   Qti   4g      7   vendor/psr/http-client/src/ClientExceptionInterface.php   Qti   xz         vendor/psr/log/LICENSE=  Qti=  pO         vendor/psr/log/README.mdB  QtiB  '         vendor/psr/log/composer.json`  Qti`  ],      +   vendor/psr/log/src/LoggerAwareInterface.php   Qti   9         vendor/psr/log/src/LogLevel.phpH  QtiH  u      '   vendor/psr/log/src/LoggerAwareTrait.phpi  Qtii  7'      /   vendor/psr/log/src/InvalidArgumentException.phpo   Qtio   MWd      !   vendor/psr/log/src/NullLogger.php  Qti  o_      &   vendor/psr/log/src/LoggerInterface.php
  Qti
  \]      "   vendor/psr/log/src/LoggerTrait.php
  Qti
  &      %   vendor/psr/log/src/AbstractLogger.php  Qti  q         vendor/psr/clock/LICENSE8  Qti8  l         vendor/psr/clock/CHANGELOG.md   Qti   <         vendor/psr/clock/README.md  Qti  GL[         vendor/psr/clock/composer.json2  Qti2  $DCM      '   vendor/psr/clock/src/ClockInterface.php   Qti   hܒ         vendor/psr/http-factory/LICENSE(  Qti(  }]      !   vendor/psr/http-factory/README.md,  Qti,  zwf      %   vendor/psr/http-factory/composer.json8  Qti8        8   vendor/psr/http-factory/src/ResponseFactoryInterface.php1  Qti1  w      6   vendor/psr/http-factory/src/StreamFactoryInterface.php  Qti  q=P٤      <   vendor/psr/http-factory/src/UploadedFileFactoryInterface.phpI  QtiI        3   vendor/psr/http-factory/src/UriFactoryInterface.phpT  QtiT  Y#k      =   vendor/psr/http-factory/src/ServerRequestFactoryInterface.php  Qti  !      7   vendor/psr/http-factory/src/RequestFactoryInterface.php  Qti           vendor/monolog/monolog/LICENSE'  Qti'        #   vendor/monolog/monolog/CHANGELOG.md  Qti  ۤ          vendor/monolog/monolog/README.md  Qti  vvy      $   vendor/monolog/monolog/composer.json;  Qti;  S+      >   vendor/monolog/monolog/src/Monolog/Handler/SendGridHandler.php  Qti  έ׸      @   vendor/monolog/monolog/src/Monolog/Handler/InsightOpsHandler.php  Qti  Z0H      :   vendor/monolog/monolog/src/Monolog/Handler/TestHandler.php:  Qti:  ?¡      ;   vendor/monolog/monolog/src/Monolog/Handler/IFTTTHandler.php  Qti  Q&٤      H   vendor/monolog/monolog/src/Monolog/Handler/WebRequestRecognizerTrait.php  Qti  BXN      <   vendor/monolog/monolog/src/Monolog/Handler/SocketHandler.php//  Qti//  rJ      C   vendor/monolog/monolog/src/Monolog/Handler/SymfonyMailerHandler.php  Qti  oä      :   vendor/monolog/monolog/src/Monolog/Handler/NoopHandler.php  Qti  _Uj      <   vendor/monolog/monolog/src/Monolog/Handler/BufferHandler.phpo  Qtio  R      <   vendor/monolog/monolog/src/Monolog/Handler/SyslogHandler.php  Qti  g      =   vendor/monolog/monolog/src/Monolog/Handler/RollbarHandler.php  Qti  (E      D   vendor/monolog/monolog/src/Monolog/Handler/FingersCrossedHandler.phpm   Qtim   *      >   vendor/monolog/monolog/src/Monolog/Handler/OverflowHandler.php  Qti  
L      =   vendor/monolog/monolog/src/Monolog/Handler/HandlerWrapper.phpF  QtiF  G9|      Y   vendor/monolog/monolog/src/Monolog/Handler/FingersCrossed/ActivationStrategyInterface.php  Qti  ?Ϥ      Z   vendor/monolog/monolog/src/Monolog/Handler/FingersCrossed/ErrorLevelActivationStrategy.php  Qti  sV      \   vendor/monolog/monolog/src/Monolog/Handler/FingersCrossed/ChannelLevelActivationStrategy.php	  Qti	  HФ      ;   vendor/monolog/monolog/src/Monolog/Handler/GroupHandler.php  Qti  ,ӕ      C   vendor/monolog/monolog/src/Monolog/Handler/ElasticsearchHandler.phpr  Qtir  \~      >   vendor/monolog/monolog/src/Monolog/Handler/SamplingHandler.phpt  Qtit  (6      6   vendor/monolog/monolog/src/Monolog/Handler/Handler.php  Qti   %      >   vendor/monolog/monolog/src/Monolog/Handler/AbstractHandler.php
  Qti
  >Ӥ      >   vendor/monolog/monolog/src/Monolog/Handler/FlowdockHandler.php=  Qti=  
N      >   vendor/monolog/monolog/src/Monolog/Handler/PushoverHandler.php>  Qti>  -H      J   vendor/monolog/monolog/src/Monolog/Handler/ProcessableHandlerInterface.php  Qti        H   vendor/monolog/monolog/src/Monolog/Handler/MissingExtensionException.php  Qti   l      D   vendor/monolog/monolog/src/Monolog/Handler/AbstractSyslogHandler.php  Qti        ?   vendor/monolog/monolog/src/Monolog/Handler/SyslogUdpHandler.php(  Qti(  "_      D   vendor/monolog/monolog/src/Monolog/Handler/BrowserConsoleHandler.php#  Qti#  :n      <   vendor/monolog/monolog/src/Monolog/Handler/FilterHandler.php  Qti  N&Q      9   vendor/monolog/monolog/src/Monolog/Handler/SqsHandler.php  Qti  Qդ      B   vendor/monolog/monolog/src/Monolog/Handler/RotatingFileHandler.php  Qti  m^+      C   vendor/monolog/monolog/src/Monolog/Handler/FallbackGroupHandler.php  Qti  3      B   vendor/monolog/monolog/src/Monolog/Handler/NativeMailerHandler.phpj  Qtij        =   vendor/monolog/monolog/src/Monolog/Handler/MongoDBHandler.php
  Qti
  M0}      =   vendor/monolog/monolog/src/Monolog/Handler/ProcessHandler.phpI  QtiI  L      F   vendor/monolog/monolog/src/Monolog/Handler/FormattableHandlerTrait.php  Qti  \	      :   vendor/monolog/monolog/src/Monolog/Handler/GelfHandler.php  Qti        A   vendor/monolog/monolog/src/Monolog/Handler/ZendMonitorHandler.php	  Qti	  fy4      @   vendor/monolog/monolog/src/Monolog/Handler/PHPConsoleHandler.php<0  Qti<0  ;R      >   vendor/monolog/monolog/src/Monolog/Handler/ErrorLogHandler.php
  Qti
  G1      @   vendor/monolog/monolog/src/Monolog/Handler/LogEntriesHandler.php  Qti  1      >   vendor/monolog/monolog/src/Monolog/Handler/LogmaticHandler.php	  Qti	  >0n      C   vendor/monolog/monolog/src/Monolog/Handler/DeduplicationHandler.phpj  Qtij  1f      =   vendor/monolog/monolog/src/Monolog/Handler/FirePHPHandler.php  Qti  y:      8   vendor/monolog/monolog/src/Monolog/Handler/Curl/Util.php#  Qti#  []      E   vendor/monolog/monolog/src/Monolog/Handler/DoctrineCouchDBHandler.php  Qti  D      >   vendor/monolog/monolog/src/Monolog/Handler/DynamoDbHandler.php  Qti  `C      J   vendor/monolog/monolog/src/Monolog/Handler/FormattableHandlerInterface.php  Qti  P\      A   vendor/monolog/monolog/src/Monolog/Handler/RedisPubSubHandler.php  Qti  U      :   vendor/monolog/monolog/src/Monolog/Handler/MailHandler.php  Qti  ,[      <   vendor/monolog/monolog/src/Monolog/Handler/StreamHandler.php'#  Qti'#  je      <   vendor/monolog/monolog/src/Monolog/Handler/LogglyHandler.phpG  QtiG  5      B   vendor/monolog/monolog/src/Monolog/Handler/SlackWebhookHandler.php  Qti  t      >   vendor/monolog/monolog/src/Monolog/Handler/ElasticaHandler.php  Qti  (t      F   vendor/monolog/monolog/src/Monolog/Handler/WhatFailureGroupHandler.php  Qti  nˤ      ?   vendor/monolog/monolog/src/Monolog/Handler/ChromePHPHandler.php  Qti  S      @   vendor/monolog/monolog/src/Monolog/Handler/Slack/SlackRecord.php|'  Qti|'  L      9   vendor/monolog/monolog/src/Monolog/Handler/PsrHandler.php	  Qti	  @      >   vendor/monolog/monolog/src/Monolog/Handler/NewRelicHandler.php  Qti  2p      F   vendor/monolog/monolog/src/Monolog/Handler/ProcessableHandlerTrait.php  Qti  ][	      ?   vendor/monolog/monolog/src/Monolog/Handler/HandlerInterface.php
  Qti
  [Ŀg      ;   vendor/monolog/monolog/src/Monolog/Handler/SlackHandler.php  Qti  @r      ?   vendor/monolog/monolog/src/Monolog/Handler/FleepHookHandler.phpC  QtiC  ~      :   vendor/monolog/monolog/src/Monolog/Handler/NullHandler.phpz  Qtiz   qG      :   vendor/monolog/monolog/src/Monolog/Handler/AmqpHandler.php  Qti  	]      A   vendor/monolog/monolog/src/Monolog/Handler/TelegramBotHandler.php4$  Qti4$  jNu      >   vendor/monolog/monolog/src/Monolog/Handler/MandrillHandler.php	  Qti	  (B      H   vendor/monolog/monolog/src/Monolog/Handler/AbstractProcessingHandler.php  Qti  C<      =   vendor/monolog/monolog/src/Monolog/Handler/CouchDBHandler.php	  Qti	  p      ;   vendor/monolog/monolog/src/Monolog/Handler/RedisHandler.php
  Qti
  [̤      :   vendor/monolog/monolog/src/Monolog/Handler/CubeHandler.php.  Qti.  %ע      B   vendor/monolog/monolog/src/Monolog/Handler/SyslogUdp/UdpSocket.php  Qti  -      H   vendor/monolog/monolog/src/Monolog/JsonSerializableDateTimeImmutable.php  Qti  }      -   vendor/monolog/monolog/src/Monolog/Logger.php	Y  Qti	Y  M"M      C   vendor/monolog/monolog/src/Monolog/Attribute/AsMonologProcessor.php  Qti  b      C   vendor/monolog/monolog/src/Monolog/Attribute/WithMonologChannel.php  Qti  GL      8   vendor/monolog/monolog/src/Monolog/DateTimeImmutable.phpe  Qtie  `      ;   vendor/monolog/monolog/src/Monolog/Test/MonologTestCase.php=  Qti=  4.N      4   vendor/monolog/monolog/src/Monolog/Test/TestCase.php  Qti  >7)      /   vendor/monolog/monolog/src/Monolog/Registry.php  Qti  JSߤ      B   vendor/monolog/monolog/src/Monolog/Processor/HostnameProcessor.php  Qti  ѻ6      G   vendor/monolog/monolog/src/Monolog/Processor/PsrLogMessageProcessor.phpD  QtiD  [~      =   vendor/monolog/monolog/src/Monolog/Processor/WebProcessor.phpQ  QtiQ  *L      I   vendor/monolog/monolog/src/Monolog/Processor/MemoryPeakUsageProcessor.phpz  Qtiz  U      C   vendor/monolog/monolog/src/Monolog/Processor/ProcessIdProcessor.php  Qti  ЪG      E   vendor/monolog/monolog/src/Monolog/Processor/LoadAverageProcessor.php  Qti  6Z      H   vendor/monolog/monolog/src/Monolog/Processor/ClosureContextProcessor.php  Qti  P`      C   vendor/monolog/monolog/src/Monolog/Processor/MercurialProcessor.php  Qti  5JM      =   vendor/monolog/monolog/src/Monolog/Processor/TagProcessor.php  Qti  Ҥ      =   vendor/monolog/monolog/src/Monolog/Processor/GitProcessor.php  Qti  ݆      @   vendor/monolog/monolog/src/Monolog/Processor/MemoryProcessor.php  Qti  Ҥ      G   vendor/monolog/monolog/src/Monolog/Processor/IntrospectionProcessor.phpT  QtiT  q	      =   vendor/monolog/monolog/src/Monolog/Processor/UidProcessor.php  Qti  +      C   vendor/monolog/monolog/src/Monolog/Processor/ProcessorInterface.php]  Qti]  l(      E   vendor/monolog/monolog/src/Monolog/Processor/MemoryUsageProcessor.phpg  Qtig  ^      :   vendor/monolog/monolog/src/Monolog/ResettableInterface.php  Qti  [p;      4   vendor/monolog/monolog/src/Monolog/SignalHandler.php  Qti  hS      ,   vendor/monolog/monolog/src/Monolog/Level.phpS  QtiS  ZK      B   vendor/monolog/monolog/src/Monolog/Formatter/LogmaticFormatter.php8  Qti8  LD      B   vendor/monolog/monolog/src/Monolog/Formatter/ElasticaFormatter.php  Qti  oؤ      >   vendor/monolog/monolog/src/Monolog/Formatter/LineFormatter.php&  Qti&  !O      >   vendor/monolog/monolog/src/Monolog/Formatter/JsonFormatter.php  Qti  PH      B   vendor/monolog/monolog/src/Monolog/Formatter/FlowdockFormatter.php	  Qti	        C   vendor/monolog/monolog/src/Monolog/Formatter/FormatterInterface.php  Qti  ̍Q      B   vendor/monolog/monolog/src/Monolog/Formatter/LogstashFormatter.phpN  QtiN  Ť      @   vendor/monolog/monolog/src/Monolog/Formatter/LogglyFormatter.php  Qti  5c_      G   vendor/monolog/monolog/src/Monolog/Formatter/ElasticsearchFormatter.phpC  QtiC  v      @   vendor/monolog/monolog/src/Monolog/Formatter/ScalarFormatter.php  Qti  hTo      A   vendor/monolog/monolog/src/Monolog/Formatter/MongoDBFormatter.php  Qti   %f      C   vendor/monolog/monolog/src/Monolog/Formatter/ChromePHPFormatter.php  Qti  dħ      A   vendor/monolog/monolog/src/Monolog/Formatter/FluentdFormatter.php  Qti  :R      E   vendor/monolog/monolog/src/Monolog/Formatter/GelfMessageFormatter.php  Qti  `2      B   vendor/monolog/monolog/src/Monolog/Formatter/WildfireFormatter.php=  Qti=  ¤      L   vendor/monolog/monolog/src/Monolog/Formatter/GoogleCloudLoggingFormatter.php  Qti  8      @   vendor/monolog/monolog/src/Monolog/Formatter/SyslogFormatter.php  Qti  b      D   vendor/monolog/monolog/src/Monolog/Formatter/NormalizerFormatter.php'  Qti'  6G      >   vendor/monolog/monolog/src/Monolog/Formatter/HtmlFormatter.php  Qti  o2      0   vendor/monolog/monolog/src/Monolog/LogRecord.php  Qti  o      3   vendor/monolog/monolog/src/Monolog/ErrorHandler.phpl'  Qtil'  K      ,   vendor/monolog/monolog/src/Monolog/Utils.php>"  Qti>"  ʝ      !   vendor/studio24/rotate/LICENSE.md>  Qti>  3ä      "   vendor/studio24/rotate/phpunit.xml   Qti   gE          vendor/studio24/rotate/README.md  Qti  ?/      $   vendor/studio24/rotate/composer.json  Qti  WѤ      .   vendor/studio24/rotate/src/RotateException.php_   Qti_    ;      %   vendor/studio24/rotate/src/Rotate.php  Qti  H      -   vendor/studio24/rotate/src/FilenameFormat.php  Qti  S      -   vendor/studio24/rotate/src/RotateAbstract.php  Qti  D      6   vendor/studio24/rotate/src/FilenameFormatException.phpg   Qtig   ܙ      %   vendor/studio24/rotate/src/Delete.php>#  Qti>#  "ޡ      0   vendor/studio24/rotate/src/DirectoryIterator.phpi  Qtii  &~      G   vendor/symfony/framework-bundle/DataCollector/AbstractDataCollector.php  Qti  0Ҥ      E   vendor/symfony/framework-bundle/DataCollector/RouterDataCollector.phpC  QtiC  <V      U   vendor/symfony/framework-bundle/DataCollector/TemplateAwareDataCollectorInterface.phpT  QtiT  D      '   vendor/symfony/framework-bundle/LICENSE,  Qti,  U      7   vendor/symfony/framework-bundle/Test/KernelTestCase.php  Qti  "      B   vendor/symfony/framework-bundle/Test/DomCrawlerAssertionsTrait.php  Qti  1U      >   vendor/symfony/framework-bundle/Test/MailerAssertionsTrait.phpP  QtiP  Ց`m      D   vendor/symfony/framework-bundle/Test/NotificationAssertionsTrait.php  Qti  Ǥ      B   vendor/symfony/framework-bundle/Test/HttpClientAssertionsTrait.php  Qti  ߐ      B   vendor/symfony/framework-bundle/Test/BrowserKitAssertionsTrait.php$  Qti$  f      9   vendor/symfony/framework-bundle/Test/TestBrowserToken.php|  Qti|  `      4   vendor/symfony/framework-bundle/Test/WebTestCase.php  Qti  W      ?   vendor/symfony/framework-bundle/Test/WebTestAssertionsTrait.php  Qti  *      6   vendor/symfony/framework-bundle/Test/TestContainer.php  Qti  	      ,   vendor/symfony/framework-bundle/CHANGELOG.mdZ  QtiZ        :   vendor/symfony/framework-bundle/Translation/Translator.php?  Qti?  7      7   vendor/symfony/framework-bundle/Secrets/SodiumVault.php#  Qti#  /      7   vendor/symfony/framework-bundle/Secrets/DotenvVault.php$  Qti$        9   vendor/symfony/framework-bundle/Secrets/AbstractVault.php  Qti  ꄨQ      I   vendor/symfony/framework-bundle/Resources/bin/check-unused-known-tags.php  Qti  ~fw      A   vendor/symfony/framework-bundle/Resources/config/asset_mapper.php$  Qti$  O)      8   vendor/symfony/framework-bundle/Resources/config/esi.php  Qti        @   vendor/symfony/framework-bundle/Resources/config/translation.phpM   QtiM   Tפ      ?   vendor/symfony/framework-bundle/Resources/config/serializer.phpy'  Qtiy'  PF      ?   vendor/symfony/framework-bundle/Resources/config/form_debug.php  Qti  "      >   vendor/symfony/framework-bundle/Resources/config/validator.php  Qti  V      >   vendor/symfony/framework-bundle/Resources/config/semaphore.php  Qti  4.      @   vendor/symfony/framework-bundle/Resources/config/annotations.php
  Qti
  ݋\      >   vendor/symfony/framework-bundle/Resources/config/profiling.php=  Qti=  +      ;   vendor/symfony/framework-bundle/Resources/config/mailer.php
  Qti
  븤      F   vendor/symfony/framework-bundle/Resources/config/fragment_listener.phpw  Qtiw  Vg      F   vendor/symfony/framework-bundle/Resources/config/translation_debug.php  Qti  $      C   vendor/symfony/framework-bundle/Resources/config/notifier_debug.php  Qti  w0      A   vendor/symfony/framework-bundle/Resources/config/rate_limiter.php  Qti  |s      9   vendor/symfony/framework-bundle/Resources/config/lock.php  Qti  z      H   vendor/symfony/framework-bundle/Resources/config/identity_translator.php  Qti  W      @   vendor/symfony/framework-bundle/Resources/config/http_client.phpx  Qtix  ^?Ϥ      A   vendor/symfony/framework-bundle/Resources/config/mailer_debug.php  Qti  `܄       =   vendor/symfony/framework-bundle/Resources/config/services.phpY#  QtiY#  [VLt      :   vendor/symfony/framework-bundle/Resources/config/cache.php"  Qti"  -l7      <   vendor/symfony/framework-bundle/Resources/config/session.phpq  Qtiq  	ۤ      F   vendor/symfony/framework-bundle/Resources/config/mailer_transports.php  Qti  i?      J   vendor/symfony/framework-bundle/Resources/config/translation_providers.php	  Qti	  ?H      :   vendor/symfony/framework-bundle/Resources/config/debug.php  Qti  L_      E   vendor/symfony/framework-bundle/Resources/config/notifier_webhook.php  Qti  ,      F   vendor/symfony/framework-bundle/Resources/config/fragment_renderer.php	  Qti	         =   vendor/symfony/framework-bundle/Resources/config/web_link.phpZ  QtiZ  Oj      <   vendor/symfony/framework-bundle/Resources/config/routing.php  Qti  A      G   vendor/symfony/framework-bundle/Resources/config/schema/symfony-1.0.xsd  Qti  ŁN      =   vendor/symfony/framework-bundle/Resources/config/notifier.php  Qti  Ec      F   vendor/symfony/framework-bundle/Resources/config/http_client_debug.php  Qti  "5$      <   vendor/symfony/framework-bundle/Resources/config/request.php  Qti  kP?      9   vendor/symfony/framework-bundle/Resources/config/test.php  Qti        <   vendor/symfony/framework-bundle/Resources/config/webhook.php  Qti  P쌤      D   vendor/symfony/framework-bundle/Resources/config/validator_debug.php  Qti  GU      C   vendor/symfony/framework-bundle/Resources/config/error_renderer.php/  Qti/        >   vendor/symfony/framework-bundle/Resources/config/mime_type.php  Qti  H̤      >   vendor/symfony/framework-bundle/Resources/config/messenger.phpc#  Qtic#   _&      <   vendor/symfony/framework-bundle/Resources/config/console.php3  Qti3  ̤ٓ      8   vendor/symfony/framework-bundle/Resources/config/uid.php=  Qti=  S      B   vendor/symfony/framework-bundle/Resources/config/property_info.php	  Qti	  j      >   vendor/symfony/framework-bundle/Resources/config/scheduler.php  Qti  1@w      8   vendor/symfony/framework-bundle/Resources/config/ssi.php  Qti  5{      8   vendor/symfony/framework-bundle/Resources/config/web.php  Qti  k?֓      D   vendor/symfony/framework-bundle/Resources/config/messenger_debug.php  Qti  o灤      ?   vendor/symfony/framework-bundle/Resources/config/collectors.phpq  Qtiq  %(      C   vendor/symfony/framework-bundle/Resources/config/routing/errors.xml  Qti  >      D   vendor/symfony/framework-bundle/Resources/config/routing/webhook.xml  Qti  Vc      C   vendor/symfony/framework-bundle/Resources/config/html_sanitizer.php  Qti  Pդ      <   vendor/symfony/framework-bundle/Resources/config/secrets.php  Qti  *n      9   vendor/symfony/framework-bundle/Resources/config/form.php  Qti  m17      E   vendor/symfony/framework-bundle/Resources/config/serializer_debug.php  Qti        C   vendor/symfony/framework-bundle/Resources/config/workflow_debug.php  Qti  RRT      C   vendor/symfony/framework-bundle/Resources/config/mailer_webhook.php
  Qti
  dea      >   vendor/symfony/framework-bundle/Resources/config/form_csrf.phpD  QtiD  A3U      =   vendor/symfony/framework-bundle/Resources/config/workflow.php  Qti  #m7Y      B   vendor/symfony/framework-bundle/Resources/config/security_csrf.php  Qti  ~ܤ      H   vendor/symfony/framework-bundle/Resources/config/notifier_transports.php^3  Qti^3  |      ?   vendor/symfony/framework-bundle/Resources/config/debug_prod.php  Qti  _Q      D   vendor/symfony/framework-bundle/Resources/config/property_access.php  Qti  Bʤ      ;   vendor/symfony/framework-bundle/Resources/config/assets.php  Qti  v'      @   vendor/symfony/framework-bundle/Resources/config/cache_debug.php  Qti  %]      A   vendor/symfony/framework-bundle/Resources/config/remote_event.php  Qti  ä      <   vendor/symfony/framework-bundle/Resources/config/process.phpc  Qtic        1   vendor/symfony/framework-bundle/KernelBrowser.phpg  Qtig  c      D   vendor/symfony/framework-bundle/CacheWarmer/ValidatorCacheWarmer.phpY  QtiY  p      H   vendor/symfony/framework-bundle/CacheWarmer/ConfigBuilderCacheWarmer.php_  Qti_  aZʤ      J   vendor/symfony/framework-bundle/CacheWarmer/AbstractPhpFileCacheWarmer.php
  Qti
  "8V      A   vendor/symfony/framework-bundle/CacheWarmer/RouterCacheWarmer.php  Qti  38      G   vendor/symfony/framework-bundle/CacheWarmer/TranslationsCacheWarmer.php  Qti  n      E   vendor/symfony/framework-bundle/CacheWarmer/SerializerCacheWarmer.php  Qti  /6      K   vendor/symfony/framework-bundle/CacheWarmer/CachePoolClearerCacheWarmer.php  Qti  S֤      F   vendor/symfony/framework-bundle/CacheWarmer/AnnotationsCacheWarmer.php  Qti  /      A   vendor/symfony/framework-bundle/Controller/AbstractController.phpH  QtiH         A   vendor/symfony/framework-bundle/Controller/TemplateController.php	  Qti	  	K      A   vendor/symfony/framework-bundle/Controller/ControllerResolver.php.  Qti.  +n8      A   vendor/symfony/framework-bundle/Controller/RedirectController.php  Qti  K      )   vendor/symfony/framework-bundle/README.md!  Qti!  q      7   vendor/symfony/framework-bundle/HttpCache/HttpCache.php
  Qti
  P5n      3   vendor/symfony/framework-bundle/FrameworkBundle.php3  Qti3  
V      >   vendor/symfony/framework-bundle/Command/SecretsListCommand.phpt  Qtit  v[      J   vendor/symfony/framework-bundle/Command/CachePoolInvalidateTagsCommand.php  Qti  #_8O      @   vendor/symfony/framework-bundle/Command/SecretsRemoveCommand.php;  Qti;        =   vendor/symfony/framework-bundle/Command/CacheClearCommand.php'  Qti'  Ro      <   vendor/symfony/framework-bundle/Command/XliffLintCommand.phpP  QtiP  4'T      H   vendor/symfony/framework-bundle/Command/SecretsDecryptToLocalCommand.php  Qti  cou      A   vendor/symfony/framework-bundle/Command/AbstractConfigCommand.php_  Qti_        >   vendor/symfony/framework-bundle/Command/RouterDebugCommand.php  Qti  a       D   vendor/symfony/framework-bundle/Command/TranslationUpdateCommand.phpC  QtiC  cj      F   vendor/symfony/framework-bundle/Command/ConfigDumpReferenceCommand.php  Qti  .      @   vendor/symfony/framework-bundle/Command/AssetsInstallCommand.php'  Qti'  -Ay      A   vendor/symfony/framework-bundle/Command/CachePoolPruneCommand.php  Qti  aLޤ      A   vendor/symfony/framework-bundle/Command/CachePoolClearCommand.phpQ  QtiQ  ]      @   vendor/symfony/framework-bundle/Command/ContainerLintCommand.php!  Qti!  I8      J   vendor/symfony/framework-bundle/Command/SecretsEncryptFromLocalCommand.php  Qti  Ȁy      B   vendor/symfony/framework-bundle/Command/DebugAutowiringCommand.php5  Qti5  Mw      >   vendor/symfony/framework-bundle/Command/CacheWarmupCommand.php  Qti  ֤      ?   vendor/symfony/framework-bundle/Command/WorkflowDumpCommand.php	  Qti	  +      G   vendor/symfony/framework-bundle/Command/EventDispatcherDebugCommand.php  Qti  y~.^      A   vendor/symfony/framework-bundle/Command/ContainerDebugCommand.php<  Qti<  v3      C   vendor/symfony/framework-bundle/Command/TranslationDebugCommand.php<  Qti<  ]      ;   vendor/symfony/framework-bundle/Command/YamlLintCommand.php
  Qti
  $<      @   vendor/symfony/framework-bundle/Command/CachePoolListCommand.php  Qti        F   vendor/symfony/framework-bundle/Command/SecretsGenerateKeysCommand.phpz  Qtiz  N      B   vendor/symfony/framework-bundle/Command/CachePoolDeleteCommand.phpU  QtiU  pӤ      D   vendor/symfony/framework-bundle/Command/BuildDebugContainerTrait.php
  Qti
  !t      8   vendor/symfony/framework-bundle/Command/AboutCommand.phpg  Qtig  i"ʬ      >   vendor/symfony/framework-bundle/Command/RouterMatchCommand.php  Qti  m~      =   vendor/symfony/framework-bundle/Command/SecretsSetCommand.php  Qti  Tݤ      >   vendor/symfony/framework-bundle/Command/ConfigDebugCommand.phpH*  QtiH*  tEǤ      J   vendor/symfony/framework-bundle/Routing/RedirectableCompiledUrlMatcher.php  Qti  Le      J   vendor/symfony/framework-bundle/Routing/AttributeRouteControllerLoader.php  Qti        O   vendor/symfony/framework-bundle/Routing/Attribute/AsRoutingConditionService.php  Qti  ny      @   vendor/symfony/framework-bundle/Routing/RouteLoaderInterface.php  Qti  b       2   vendor/symfony/framework-bundle/Routing/Router.php  Qti  >      <   vendor/symfony/framework-bundle/Routing/DelegatingLoader.php  Qti  Hݤ      J   vendor/symfony/framework-bundle/Routing/AnnotatedRouteControllerLoader.php  Qti        E   vendor/symfony/framework-bundle/DependencyInjection/Configuration.php@ Qti@ fv      J   vendor/symfony/framework-bundle/DependencyInjection/FrameworkExtension.php Qti eC      O   vendor/symfony/framework-bundle/DependencyInjection/VirtualRequestStackPass.php  Qti  1      ^   vendor/symfony/framework-bundle/DependencyInjection/Compiler/ContainerBuilderDebugDumpPass.phpS  QtiS  n>.      `   vendor/symfony/framework-bundle/DependencyInjection/Compiler/TestServiceContainerRealRefPass.php	  Qti	  j(v      c   vendor/symfony/framework-bundle/DependencyInjection/Compiler/AddExpressionLanguageProvidersPass.phpV  QtiV  Я5t      O   vendor/symfony/framework-bundle/DependencyInjection/Compiler/UnusedTagsPass.phpm  Qtim  ~6Ǥ      R   vendor/symfony/framework-bundle/DependencyInjection/Compiler/AssetsContextPass.php  Qti  o      X   vendor/symfony/framework-bundle/DependencyInjection/Compiler/ErrorLoggerCompilerPass.php  Qti  ]V      ]   vendor/symfony/framework-bundle/DependencyInjection/Compiler/TranslationUpdateCommandPass.php  Qti  ćY      Z   vendor/symfony/framework-bundle/DependencyInjection/Compiler/WorkflowGuardListenerPass.php"  Qti"  i/      Z   vendor/symfony/framework-bundle/DependencyInjection/Compiler/EnableLoggerDebugModePass.php  Qti  k
      `   vendor/symfony/framework-bundle/DependencyInjection/Compiler/TestServiceContainerWeakRefPass.php
  Qti
  LѤ      V   vendor/symfony/framework-bundle/DependencyInjection/Compiler/LoggingTranslatorPass.phpV  QtiV  uc      \   vendor/symfony/framework-bundle/DependencyInjection/Compiler/DataCollectorTranslatorPass.phpT  QtiT  OJ      _   vendor/symfony/framework-bundle/DependencyInjection/Compiler/AddAnnotationsCachedReaderPass.php  Qti  S.      M   vendor/symfony/framework-bundle/DependencyInjection/Compiler/ProfilerPass.php	  Qti	        j   vendor/symfony/framework-bundle/DependencyInjection/Compiler/RemoveUnusedSessionMarshallingHandlerPass.php   Qti   k)̤      Y   vendor/symfony/framework-bundle/DependencyInjection/Compiler/AddDebugLogProcessorPass.php  Qti  3p      -   vendor/symfony/framework-bundle/composer.json  Qti  cFD
      ;   vendor/symfony/framework-bundle/Kernel/MicroKernelTrait.phpR   QtiR   TCjv      7   vendor/symfony/framework-bundle/Console/Application.php9   Qti9   Ւ      E   vendor/symfony/framework-bundle/Console/Descriptor/TextDescriptor.phpnm  Qtinm  y%d      D   vendor/symfony/framework-bundle/Console/Descriptor/XmlDescriptor.phpaj  Qtiaj  '(      A   vendor/symfony/framework-bundle/Console/Descriptor/Descriptor.php]6  Qti]6  -T      E   vendor/symfony/framework-bundle/Console/Descriptor/JsonDescriptor.phpC  QtiC  ԌmW      I   vendor/symfony/framework-bundle/Console/Descriptor/MarkdownDescriptor.phpH  QtiH        C   vendor/symfony/framework-bundle/Console/Helper/DescriptorHelper.php  Qti  *      I   vendor/symfony/framework-bundle/EventListener/ConsoleProfilerListener.php  Qti  Ķ      Q   vendor/symfony/framework-bundle/EventListener/SuggestMissingPackageSubscriber.php	  Qti	  s      %   vendor/symfony/monolog-bundle/LICENSE)  Qti)  Ǥ      *   vendor/symfony/monolog-bundle/CHANGELOG.md  Qti  \      0   vendor/symfony/monolog-bundle/config/monolog.php^  Qti^  .qQ      ;   vendor/symfony/monolog-bundle/config/schema/monolog-1.0.xsd*  Qti*  eK      '   vendor/symfony/monolog-bundle/README.mdK  QtiK  w      +   vendor/symfony/monolog-bundle/composer.jsonC  QtiC  Mmä      @   vendor/symfony/monolog-bundle/src/SwiftMailer/MessageFactory.php   Qti   LS_      3   vendor/symfony/monolog-bundle/src/MonologBundle.phpH  QtiH  hh      J   vendor/symfony/monolog-bundle/src/DependencyInjection/MonologExtension.php  Qti        G   vendor/symfony/monolog-bundle/src/DependencyInjection/Configuration.phpf  Qtif  mQ      T   vendor/symfony/monolog-bundle/src/DependencyInjection/Compiler/AddProcessorsPass.phpz  Qtiz  u:      T   vendor/symfony/monolog-bundle/src/DependencyInjection/Compiler/LoggerChannelPass.phpk  Qtik  nd      S   vendor/symfony/monolog-bundle/src/DependencyInjection/Compiler/DebugHandlerPass.php  Qti  B      U   vendor/symfony/monolog-bundle/src/DependencyInjection/Compiler/FixEmptyLoggerPass.php  Qti  &y      ^   vendor/symfony/monolog-bundle/src/DependencyInjection/Compiler/AddSwiftMailerTransportPass.php  Qti  oQ      %   vendor/symfony/polyfill-php73/LICENSE,  Qti,        '   vendor/symfony/polyfill-php73/Php73.phpq  Qtiq  m      ?   vendor/symfony/polyfill-php73/Resources/stubs/JsonException.phpE  QtiE  8S      +   vendor/symfony/polyfill-php73/bootstrap.php  Qti  |      '   vendor/symfony/polyfill-php73/README.md/  Qti/  m      +   vendor/symfony/polyfill-php73/composer.json  Qti  t      C   vendor/symfony/serializer/DataCollector/SerializerDataCollector.php  Qti  4      (   vendor/symfony/serializer/Serializer.phpFH  QtiFH   ֤      I   vendor/symfony/serializer/Mapping/ClassDiscriminatorFromClassMetadata.phpk
  Qtik
  ]XO      <   vendor/symfony/serializer/Mapping/ClassMetadataInterface.php,  Qti,  64      3   vendor/symfony/serializer/Mapping/ClassMetadata.phpM  QtiM  ղ      <   vendor/symfony/serializer/Mapping/Loader/AttributeLoader.php6  Qti6  gA      7   vendor/symfony/serializer/Mapping/Loader/FileLoader.phpD  QtiD  cߗ      K   vendor/symfony/serializer/Mapping/Loader/AccessorCollisionResolverTrait.php  Qti  "      <   vendor/symfony/serializer/Mapping/Loader/LoaderInterface.phpX  QtiX  A      ;   vendor/symfony/serializer/Mapping/Loader/YamlFileLoader.php  Qti  pK      a   vendor/symfony/serializer/Mapping/Loader/schema/dic/serializer-mapping/serializer-mapping-1.0.xsd  Qti  7      :   vendor/symfony/serializer/Mapping/Loader/XmlFileLoader.php  Qti  eA      8   vendor/symfony/serializer/Mapping/Loader/LoaderChain.php  Qti  æL      =   vendor/symfony/serializer/Mapping/Loader/AnnotationLoader.php  Qti  ˟դ      I   vendor/symfony/serializer/Mapping/ClassDiscriminatorResolverInterface.php  Qti  SS+      @   vendor/symfony/serializer/Mapping/AttributeMetadataInterface.php  Qti  V      ?   vendor/symfony/serializer/Mapping/ClassDiscriminatorMapping.php  Qti  X      J   vendor/symfony/serializer/Mapping/Factory/ClassMetadataFactoryCompiler.phpn  Qtin  S8Ĥ      @   vendor/symfony/serializer/Mapping/Factory/ClassResolverTrait.php'  Qti'  \      B   vendor/symfony/serializer/Mapping/Factory/ClassMetadataFactory.php  Qti        G   vendor/symfony/serializer/Mapping/Factory/CacheClassMetadataFactory.php  Qti  ٭      J   vendor/symfony/serializer/Mapping/Factory/CompiledClassMetadataFactory.php2  Qti2  2b      K   vendor/symfony/serializer/Mapping/Factory/ClassMetadataFactoryInterface.php  Qti  28      7   vendor/symfony/serializer/Mapping/AttributeMetadata.php  Qti  KA      1   vendor/symfony/serializer/SerializerInterface.php{  Qti{  U}      F   vendor/symfony/serializer/Context/Encoder/CsvEncoderContextBuilder.php  Qti  _pɷ      F   vendor/symfony/serializer/Context/Encoder/XmlEncoderContextBuilder.php  Qti  d&#      G   vendor/symfony/serializer/Context/Encoder/YamlEncoderContextBuilder.php  Qti  )bԤ      G   vendor/symfony/serializer/Context/Encoder/JsonEncoderContextBuilder.php  Qti  O      9   vendor/symfony/serializer/Context/ContextBuilderTrait.php  Qti  %      >   vendor/symfony/serializer/Context/SerializerContextBuilder.php  Qti  "0B&      =   vendor/symfony/serializer/Context/ContextBuilderInterface.php  Qti  I|      O   vendor/symfony/serializer/Context/Normalizer/ObjectNormalizerContextBuilder.php#  Qti#  D      Q   vendor/symfony/serializer/Context/Normalizer/DateTimeNormalizerContextBuilder.php  Qti  r      R   vendor/symfony/serializer/Context/Normalizer/FormErrorNormalizerContextBuilder.php  Qti   r      U   vendor/symfony/serializer/Context/Normalizer/GetSetMethodNormalizerContextBuilder.php/  Qti/  gB      Y   vendor/symfony/serializer/Context/Normalizer/JsonSerializableNormalizerContextBuilder.php1  Qti1  z      P   vendor/symfony/serializer/Context/Normalizer/ProblemNormalizerContextBuilder.php  Qti  @0I      W   vendor/symfony/serializer/Context/Normalizer/AbstractObjectNormalizerContextBuilder.phpG  QtiG  P7      S   vendor/symfony/serializer/Context/Normalizer/BackedEnumNormalizerContextBuilder.phpf  Qtif  f      `   vendor/symfony/serializer/Context/Normalizer/ConstraintViolationListNormalizerContextBuilder.php2  Qti2        U   vendor/symfony/serializer/Context/Normalizer/UnwrappingDenormalizerContextBuilder.php   Qti   x]      Q   vendor/symfony/serializer/Context/Normalizer/AbstractNormalizerContextBuilder.php  Qti  Z      L   vendor/symfony/serializer/Context/Normalizer/UidNormalizerContextBuilder.php  Qti  &3      Q   vendor/symfony/serializer/Context/Normalizer/PropertyNormalizerContextBuilder.php  Qti  /7C      U   vendor/symfony/serializer/Context/Normalizer/DateIntervalNormalizerContextBuilder.phpA  QtiA  i      6   vendor/symfony/serializer/Attribute/SerializedName.php  Qti  J¤      .   vendor/symfony/serializer/Attribute/Ignore.php  Qti  }Ѫ      /   vendor/symfony/serializer/Attribute/Context.php  Qti  !M      8   vendor/symfony/serializer/Attribute/DiscriminatorMap.php  Qti  `k      6   vendor/symfony/serializer/Attribute/SerializedPath.php  Qti  z      0   vendor/symfony/serializer/Attribute/MaxDepth.php  Qti  \      .   vendor/symfony/serializer/Attribute/Groups.php  Qti  O      !   vendor/symfony/serializer/LICENSE,  Qti,  U      &   vendor/symfony/serializer/CHANGELOG.md6<  Qti6<  qSx      0   vendor/symfony/serializer/Encoder/CsvEncoder.php1'  Qti1'  ତ      B   vendor/symfony/serializer/Encoder/ContextAwareDecoderInterface.php  Qti  /0Ϥ      2   vendor/symfony/serializer/Encoder/ChainEncoder.phpc  Qtic  wZ      6   vendor/symfony/serializer/Encoder/DecoderInterface.php/  Qti/  
      B   vendor/symfony/serializer/Encoder/ContextAwareEncoderInterface.php  Qti        A   vendor/symfony/serializer/Encoder/NormalizationAwareInterface.phpv  Qtiv  
/g      6   vendor/symfony/serializer/Encoder/EncoderInterface.php  Qti  D      2   vendor/symfony/serializer/Encoder/ChainDecoder.php  Qti  }=      0   vendor/symfony/serializer/Encoder/JsonEncode.php  Qti  ]      1   vendor/symfony/serializer/Encoder/JsonEncoder.php  Qti  &W      0   vendor/symfony/serializer/Encoder/JsonDecode.php5  Qti5  2S75      1   vendor/symfony/serializer/Encoder/YamlEncoder.phpi  Qtii  0du      0   vendor/symfony/serializer/Encoder/XmlEncoder.phpH  QtiH  j3      J   vendor/symfony/serializer/CacheWarmer/CompiledClassMetadataCacheWarmer.php5  Qti5  ⋤      7   vendor/symfony/serializer/Annotation/SerializedName.phpZ  QtiZ  V;yP      /   vendor/symfony/serializer/Annotation/Ignore.phpB  QtiB  E      0   vendor/symfony/serializer/Annotation/Context.php  Qti  z|w      9   vendor/symfony/serializer/Annotation/DiscriminatorMap.phpA  QtiA  ۤ      7   vendor/symfony/serializer/Annotation/SerializedPath.phpZ  QtiZ        1   vendor/symfony/serializer/Annotation/MaxDepth.phpH  QtiH  DIzI      /   vendor/symfony/serializer/Annotation/Groups.php]  Qti]  v
      L   vendor/symfony/serializer/Extractor/ObjectPropertyListExtractorInterface.php]  Qti]  tԤ      C   vendor/symfony/serializer/Extractor/ObjectPropertyListExtractor.phpz  Qtiz  yQ      6   vendor/symfony/serializer/SerializerAwareInterface.php  Qti  M      #   vendor/symfony/serializer/README.mdJ  QtiJ  Mc%      B   vendor/symfony/serializer/NameConverter/NameConverterInterface.php  Qti  Q      J   vendor/symfony/serializer/NameConverter/AdvancedNameConverterInterface.php  Qti  D      F   vendor/symfony/serializer/NameConverter/MetadataAwareNameConverter.php  Qti  ˹      M   vendor/symfony/serializer/NameConverter/CamelCaseToSnakeCaseNameConverter.php.  Qti.  t6      2   vendor/symfony/serializer/Command/DebugCommand.php@  Qti@  곻      ;   vendor/symfony/serializer/Normalizer/DateTimeNormalizer.php  Qti  du      >   vendor/symfony/serializer/Normalizer/MimeMessageNormalizer.php8  Qti8  v j      @   vendor/symfony/serializer/Normalizer/DenormalizableInterface.phpv  Qtiv        :   vendor/symfony/serializer/Normalizer/ProblemNormalizer.php  Qti        I   vendor/symfony/serializer/Normalizer/CacheableSupportsMethodInterface.php!  Qti!  X      >   vendor/symfony/serializer/Normalizer/ObjectToPopulateTrait.php,  Qti,  m      <   vendor/symfony/serializer/Normalizer/FormErrorNormalizer.php	  Qti	  3      J   vendor/symfony/serializer/Normalizer/ContextAwareDenormalizerInterface.php6  Qti6  j>      :   vendor/symfony/serializer/Normalizer/ArrayDenormalizer.php  Qti  S#      A   vendor/symfony/serializer/Normalizer/AbstractObjectNormalizer.phpW  QtiW  !\}      ?   vendor/symfony/serializer/Normalizer/DateTimeZoneNormalizer.php  Qti  B      ?   vendor/symfony/serializer/Normalizer/UnwrappingDenormalizer.phpx
  Qtix
  `Je      =   vendor/symfony/serializer/Normalizer/NormalizerAwareTrait.phpk  Qtik  #      A   vendor/symfony/serializer/Normalizer/NormalizerAwareInterface.php%  Qti%  :]R      C   vendor/symfony/serializer/Normalizer/JsonSerializableNormalizer.php)
  Qti)
  7      :   vendor/symfony/serializer/Normalizer/DataUriNormalizer.php  Qti  -B      H   vendor/symfony/serializer/Normalizer/ContextAwareNormalizerInterface.php  Qti  .ǈ      9   vendor/symfony/serializer/Normalizer/CustomNormalizer.php9  Qti9  C]A^      C   vendor/symfony/serializer/Normalizer/DenormalizerAwareInterface.php/  Qti/  <ǖ      ?   vendor/symfony/serializer/Normalizer/DateIntervalNormalizer.phpu  Qtiu  2      ;   vendor/symfony/serializer/Normalizer/PropertyNormalizer.php#  Qti#  bdYR      9   vendor/symfony/serializer/Normalizer/ObjectNormalizer.php;!  Qti;!  *3      ;   vendor/symfony/serializer/Normalizer/AbstractNormalizer.phpb  Qtib  R      ?   vendor/symfony/serializer/Normalizer/TranslatableNormalizer.php  Qti         6   vendor/symfony/serializer/Normalizer/UidNormalizer.php  Qti  g.O      >   vendor/symfony/serializer/Normalizer/DenormalizerInterface.php  Qti  Vi3      >   vendor/symfony/serializer/Normalizer/NormalizableInterface.php  Qti  v      ?   vendor/symfony/serializer/Normalizer/GetSetMethodNormalizer.php!  Qti!  /+      =   vendor/symfony/serializer/Normalizer/BackedEnumNormalizer.php  Qti        J   vendor/symfony/serializer/Normalizer/ConstraintViolationListNormalizer.php  Qti  #K¤      <   vendor/symfony/serializer/Normalizer/NormalizerInterface.php  Qti  e      ?   vendor/symfony/serializer/Normalizer/DenormalizerAwareTrait.php{  Qti{  o      2   vendor/symfony/serializer/SerializerAwareTrait.php`  Qti`  ĝ|      @   vendor/symfony/serializer/DependencyInjection/SerializerPass.php  Qti  EBʤ      6   vendor/symfony/serializer/Exception/LogicException.php  Qti  A      :   vendor/symfony/serializer/Exception/ExceptionInterface.php  Qti  Za      L   vendor/symfony/serializer/Exception/MissingConstructorArgumentsException.php  Qti  ?e      @   vendor/symfony/serializer/Exception/UnexpectedValueException.php  Qti  rǤ      8   vendor/symfony/serializer/Exception/RuntimeException.php  Qti  VX      E   vendor/symfony/serializer/Exception/NotNormalizableValueException.php]  Qti]  M      @   vendor/symfony/serializer/Exception/InvalidArgumentException.php  Qti  n      B   vendor/symfony/serializer/Exception/CircularReferenceException.php  Qti  s5      >   vendor/symfony/serializer/Exception/BadMethodCallException.php  Qti  }
      8   vendor/symfony/serializer/Exception/MappingException.php  Qti  Ǡۤ      <   vendor/symfony/serializer/Exception/UnsupportedException.php  Qti         B   vendor/symfony/serializer/Exception/NotEncodableValueException.php  Qti  \53      G   vendor/symfony/serializer/Exception/PartialDenormalizationException.phpL  QtiL  n      B   vendor/symfony/serializer/Exception/UnsupportedFormatException.php  Qti  G`k      @   vendor/symfony/serializer/Exception/ExtraAttributesException.php  Qti  9      '   vendor/symfony/serializer/composer.json	  Qti	  ɮ      4   vendor/symfony/serializer/Debug/TraceableEncoder.php  Qti  nՏ      7   vendor/symfony/serializer/Debug/TraceableSerializer.php  Qti  QHoФ      7   vendor/symfony/serializer/Debug/TraceableNormalizer.phpM  QtiM  P      *   vendor/symfony/polyfill-php80/PhpToken.php  Qti  ':      %   vendor/symfony/polyfill-php80/LICENSE,  Qti,  K      :   vendor/symfony/polyfill-php80/Resources/stubs/PhpToken.phpw  Qtiw  =7T8      <   vendor/symfony/polyfill-php80/Resources/stubs/ValueError.php>  Qti>  g      ;   vendor/symfony/polyfill-php80/Resources/stubs/Attribute.php  Qti  MK<      E   vendor/symfony/polyfill-php80/Resources/stubs/UnhandledMatchError.phpG  QtiG  ֈ+      <   vendor/symfony/polyfill-php80/Resources/stubs/Stringable.php  Qti  t]\ڤ      +   vendor/symfony/polyfill-php80/bootstrap.php  Qti  .Ĥ      '   vendor/symfony/polyfill-php80/README.md  Qti  "tF      '   vendor/symfony/polyfill-php80/Php80.phpu  Qtiu  'n      +   vendor/symfony/polyfill-php80/composer.jsonb  Qtib  F      7   vendor/symfony/monolog-bridge/Handler/MailerHandler.php  Qti  u      H   vendor/symfony/monolog-bridge/Handler/CompatibilityProcessingHandler.php  Qti        8   vendor/symfony/monolog-bridge/Handler/ConsoleHandler.php  Qti        S   vendor/symfony/monolog-bridge/Handler/FingersCrossed/HttpCodeActivationStrategy.php  Qti  .p٤      S   vendor/symfony/monolog-bridge/Handler/FingersCrossed/NotFoundActivationStrategy.phpO  QtiO  ;2      :   vendor/symfony/monolog-bridge/Handler/ServerLogHandler.php  Qti  T      >   vendor/symfony/monolog-bridge/Handler/CompatibilityHandler.php  Qti        9   vendor/symfony/monolog-bridge/Handler/NotifierHandler.php	  Qti	  :Ӏ      8   vendor/symfony/monolog-bridge/Handler/FirePHPHandler.php  Qti  5      :   vendor/symfony/monolog-bridge/Handler/ChromePhpHandler.php,  Qti,  <Wͤ      F   vendor/symfony/monolog-bridge/Handler/ElasticsearchLogstashHandler.php  Qti  vf      (   vendor/symfony/monolog-bridge/Logger.php'
  Qti'
  &wD      %   vendor/symfony/monolog-bridge/LICENSE,  Qti,  U      *   vendor/symfony/monolog-bridge/CHANGELOG.md  Qti  `s      :   vendor/symfony/monolog-bridge/Processor/TokenProcessor.php:  Qti:        D   vendor/symfony/monolog-bridge/Processor/SwitchUserTokenProcessor.php  Qti  8      8   vendor/symfony/monolog-bridge/Processor/WebProcessor.php  Qti  08      B   vendor/symfony/monolog-bridge/Processor/CompatibilityProcessor.php  Qti  N1qR      :   vendor/symfony/monolog-bridge/Processor/RouteProcessor.php	  Qti	  hʕ      C   vendor/symfony/monolog-bridge/Processor/ConsoleCommandProcessor.phpH  QtiH  G      B   vendor/symfony/monolog-bridge/Processor/AbstractTokenProcessor.php  Qti  e>      :   vendor/symfony/monolog-bridge/Processor/DebugProcessor.php  Qti         '   vendor/symfony/monolog-bridge/README.md  Qti  =~      <   vendor/symfony/monolog-bridge/Formatter/ConsoleFormatter.php  Qti  j"      >   vendor/symfony/monolog-bridge/Formatter/VarDumperFormatter.php.  Qti.  $٤      B   vendor/symfony/monolog-bridge/Formatter/CompatibilityFormatter.php  Qti  X֭      :   vendor/symfony/monolog-bridge/Command/ServerLogCommand.phpS  QtiS  x      +   vendor/symfony/monolog-bridge/composer.json  Qti  -}b      9   vendor/symfony/cache/DataCollector/CacheDataCollector.phpm  Qtim  Y      "   vendor/symfony/cache/CacheItem.php  Qti  P      #   vendor/symfony/cache/Psr16Cache.php  Qti  .3         vendor/symfony/cache/LICENSE,  Qti,  X      +   vendor/symfony/cache/PruneableInterface.php  Qti  c      !   vendor/symfony/cache/CHANGELOG.mdo  Qtio  ʗXJ      5   vendor/symfony/cache/Traits/RedisClusterNodeProxy.php  Qti  &yF      /   vendor/symfony/cache/Traits/RelayProxyTrait.php  Qti  I֤      *   vendor/symfony/cache/Traits/RedisTrait.phpu  Qtiu  O      +   vendor/symfony/cache/Traits/Redis5Proxy.php  Qti  Zͤ      2   vendor/symfony/cache/Traits/RedisCluster6Proxy.php  Qti  ˺8      *   vendor/symfony/cache/Traits/ProxyTrait.php#  Qti#  ޲ݤ      5   vendor/symfony/cache/Traits/FilesystemCommonTrait.php  Qti  %Ф      1   vendor/symfony/cache/Traits/RedisClusterProxy.php  Qti  L~      *   vendor/symfony/cache/Traits/RedisProxy.php  Qti        .   vendor/symfony/cache/Traits/ContractsTrait.phpB  QtiB  Z      8   vendor/symfony/cache/Traits/RedisCluster62ProxyTrait.php  Qti  G      1   vendor/symfony/cache/Traits/Redis63ProxyTrait.php  Qti  .J      8   vendor/symfony/cache/Traits/RedisCluster61ProxyTrait.php  Qti  XW      *   vendor/symfony/cache/Traits/RelayProxy.phpZ  QtiZ  *      1   vendor/symfony/cache/Traits/Redis62ProxyTrait.phph  Qtih  [B      ,   vendor/symfony/cache/Traits/ValueWrapper.php	  Qti	  3j      2   vendor/symfony/cache/Traits/RedisCluster5Proxy.php  Qti  _*Ϥ      /   vendor/symfony/cache/Traits/FilesystemTrait.php  Qti  &      +   vendor/symfony/cache/Traits/Redis6Proxy.php  Qti  d      1   vendor/symfony/cache/Traits/Redis61ProxyTrait.php  Qti  ֤      8   vendor/symfony/cache/Traits/RedisCluster63ProxyTrait.php  Qti  +A      4   vendor/symfony/cache/Traits/Relay/GeosearchTrait.php  Qti  yGa      /   vendor/symfony/cache/Traits/Relay/MoveTrait.php  Qti  f       2   vendor/symfony/cache/Traits/Relay/Relay12Trait.phpz  Qtiz  犤      2   vendor/symfony/cache/Traits/Relay/PfcountTrait.php  Qti  t>      3   vendor/symfony/cache/Traits/Relay/Relay121Trait.phpS  QtiS  |q      2   vendor/symfony/cache/Traits/Relay/Relay21Trait.php  Qti  |(O      2   vendor/symfony/cache/Traits/Relay/Relay20Trait.phpi  Qtii  4'V      /   vendor/symfony/cache/Traits/Relay/CopyTrait.php  Qti  S      9   vendor/symfony/cache/Traits/Relay/NullableReturnTrait.phpx  Qtix  5      2   vendor/symfony/cache/Traits/Relay/Relay11Trait.phpB  QtiB        /   vendor/symfony/cache/Traits/Relay/HsetTrait.php  Qti  Uc^      1   vendor/symfony/cache/Traits/Relay/SwapdbTrait.php  Qti  aפ      3   vendor/symfony/cache/Traits/Relay/GetrangeTrait.php  Qti  P      4   vendor/symfony/cache/Traits/Relay/IsTrackedTrait.php  Qti  %      -   vendor/symfony/cache/Traits/Relay/FtTrait.php  Qti  HG      6   vendor/symfony/cache/Traits/Relay/GetWithMetaTrait.php  Qti  r      1   vendor/symfony/cache/Traits/Relay/BgsaveTrait.php  Qti  Z'7      4   vendor/symfony/cache/Traits/AbstractAdapterTrait.php$0  Qti$0        4   vendor/symfony/cache/Traits/CachedValueInterface.php  Qti  FMT      -   vendor/symfony/cache/Adapter/ProxyAdapter.phpN  QtiN  1      ,   vendor/symfony/cache/Adapter/ApcuAdapter.php&  Qti&  V*7      ;   vendor/symfony/cache/Adapter/CouchbaseCollectionAdapter.php  Qti  87      1   vendor/symfony/cache/Adapter/TraceableAdapter.phpg  Qtig  W      +   vendor/symfony/cache/Adapter/PdoAdapter.phpB  QtiB  i      -   vendor/symfony/cache/Adapter/ArrayAdapter.php./  Qti./  K      5   vendor/symfony/cache/Adapter/RedisTagAwareAdapter.php1  Qti1  4g      7   vendor/symfony/cache/Adapter/CouchbaseBucketAdapter.php  Qti  |Ҥ      ,   vendor/symfony/cache/Adapter/NullAdapter.php  Qti  k(      4   vendor/symfony/cache/Adapter/ParameterNormalizer.php  Qti  '      0   vendor/symfony/cache/Adapter/TagAwareAdapter.php,  Qti,  +h      0   vendor/symfony/cache/Adapter/PhpFilesAdapter.php(  Qti(  V<      4   vendor/symfony/cache/Adapter/DoctrineDbalAdapter.phpyD  QtiyD  :n      9   vendor/symfony/cache/Adapter/TagAwareAdapterInterface.php  Qti        1   vendor/symfony/cache/Adapter/MemcachedAdapter.php{4  Qti{4  ]      -   vendor/symfony/cache/Adapter/RedisAdapter.php   Qti   8b      1   vendor/symfony/cache/Adapter/AdapterInterface.php  Qti  cɤ      :   vendor/symfony/cache/Adapter/FilesystemTagAwareAdapter.php#  Qti#  9\      9   vendor/symfony/cache/Adapter/TraceableTagAwareAdapter.php  Qti        -   vendor/symfony/cache/Adapter/Psr16Adapter.php#  Qti#  e?      -   vendor/symfony/cache/Adapter/ChainAdapter.php"  Qti"  (Ҥ      2   vendor/symfony/cache/Adapter/FilesystemAdapter.php  Qti  (Acb      0   vendor/symfony/cache/Adapter/AbstractAdapter.php:  Qti:  ~      8   vendor/symfony/cache/Adapter/AbstractTagAwareAdapter.php1  Qti1  (p      0   vendor/symfony/cache/Adapter/PhpArrayAdapter.php.0  Qti.0  F{      %   vendor/symfony/cache/LockRegistry.php  Qti  E      ,   vendor/symfony/cache/ResettableInterface.php  Qti  NR         vendor/symfony/cache/README.md  Qti  `t:      9   vendor/symfony/cache/Messenger/EarlyExpirationHandler.php	  Qti	  8v*      9   vendor/symfony/cache/Messenger/EarlyExpirationMessage.php  Qti  
#      <   vendor/symfony/cache/Messenger/EarlyExpirationDispatcher.php	  Qti	  G£      5   vendor/symfony/cache/Marshaller/DefaultMarshaller.php5  Qti5  jT      5   vendor/symfony/cache/Marshaller/DeflateMarshaller.php  Qti        7   vendor/symfony/cache/Marshaller/MarshallerInterface.php1  Qti1  3      6   vendor/symfony/cache/Marshaller/TagAwareMarshaller.php  Qti        4   vendor/symfony/cache/Marshaller/SodiumMarshaller.phpX	  QtiX	  խ\      :   vendor/symfony/cache/DependencyInjection/CachePoolPass.php)  Qti)  !K      @   vendor/symfony/cache/DependencyInjection/CachePoolPrunerPass.php  Qti  ;      ?   vendor/symfony/cache/DependencyInjection/CacheCollectorPass.php  Qti  (_      A   vendor/symfony/cache/DependencyInjection/CachePoolClearerPass.php  Qti  Ł:      1   vendor/symfony/cache/Exception/LogicException.php  Qti  F      ;   vendor/symfony/cache/Exception/InvalidArgumentException.php   Qti   0       1   vendor/symfony/cache/Exception/CacheException.php  Qti  YlW      "   vendor/symfony/cache/composer.json  Qti  Fw      -   vendor/symfony/polyfill-ctype/bootstrap80.phpr  Qtir  F)      %   vendor/symfony/polyfill-ctype/LICENSE,  Qti,        +   vendor/symfony/polyfill-ctype/bootstrap.php@  Qti@  jQ9      '   vendor/symfony/polyfill-ctype/README.md^  Qti^  lHk      '   vendor/symfony/polyfill-ctype/Ctype.php  Qti  Ѥ      +   vendor/symfony/polyfill-ctype/composer.json  Qti  9      %   vendor/symfony/polyfill-php81/LICENSE,  Qti,  0      F   vendor/symfony/polyfill-php81/Resources/stubs/ReturnTypeWillChange.php  Qti  5+      @   vendor/symfony/polyfill-php81/Resources/stubs/CURLStringFile.php  Qti  JT      +   vendor/symfony/polyfill-php81/bootstrap.php  Qti  <P      '   vendor/symfony/polyfill-php81/README.md  Qti        '   vendor/symfony/polyfill-php81/Php81.php  Qti  1      +   vendor/symfony/polyfill-php81/composer.json  Qti  #@      F   vendor/symfony/security-bundle/DataCollector/SecurityDataCollector.php.  Qti.  Ҥ      &   vendor/symfony/security-bundle/LICENSE,  Qti,  U      +   vendor/symfony/security-bundle/CHANGELOG.mdCD  QtiCD  ;      ?   vendor/symfony/security-bundle/Security/LazyFirewallContext.php	  Qti	  #F@      =   vendor/symfony/security-bundle/Security/UserAuthenticator.php=  Qti=  >      ;   vendor/symfony/security-bundle/Security/FirewallContext.php  Qti  kF?¤      7   vendor/symfony/security-bundle/Security/FirewallMap.php8	  Qti8	  }kFä      :   vendor/symfony/security-bundle/Security/FirewallConfig.php	  Qti	  -      >   vendor/symfony/security-bundle/Security/FirewallAwareTrait.php  Qti  Ww@      W   vendor/symfony/security-bundle/Resources/config/security_authenticator_access_token.php  Qti  43MU      C   vendor/symfony/security-bundle/Resources/config/templating_twig.php  Qti  @']      F   vendor/symfony/security-bundle/Resources/config/security_listeners.php  Qti  Ne      U   vendor/symfony/security-bundle/Resources/config/security_authenticator_login_link.php	  Qti	  +      B   vendor/symfony/security-bundle/Resources/config/security_debug.php3  Qti3  6!H!      A   vendor/symfony/security-bundle/Resources/config/debug_console.php   Qti         G   vendor/symfony/security-bundle/Resources/config/schema/security-1.0.xsdX  QtiX  f#      ;   vendor/symfony/security-bundle/Resources/config/console.php  Qti  ,      C   vendor/symfony/security-bundle/Resources/config/password_hasher.php  Qti  J      >   vendor/symfony/security-bundle/Resources/config/collectors.php  Qti  u|      J   vendor/symfony/security-bundle/Resources/config/security_authenticator.php  Qti  VQ      <   vendor/symfony/security-bundle/Resources/config/security.php	.  Qti	.  អ      V   vendor/symfony/security-bundle/Resources/config/security_authenticator_remember_me.php  Qti  K      A   vendor/symfony/security-bundle/Resources/views/Collector/icon.svg  Qti  0צ      K   vendor/symfony/security-bundle/Resources/views/Collector/security.html.twige  Qtie  Y      D   vendor/symfony/security-bundle/CacheWarmer/ExpressionCacheWarmer.phpo  Qtio  1yI      1   vendor/symfony/security-bundle/SecurityBundle.php  Qti  (      (   vendor/symfony/security-bundle/README.md  Qti  [A      H   vendor/symfony/security-bundle/RememberMe/DecoratedRememberMeHandler.php[  Qti[  9i      L   vendor/symfony/security-bundle/RememberMe/FirewallAwareRememberMeHandler.php=  Qti=  ;A      ?   vendor/symfony/security-bundle/Command/DebugFirewallCommand.phpH"  QtiH"  4      <   vendor/symfony/security-bundle/Routing/LogoutRouteLoader.php<  Qti<  vL      +   vendor/symfony/security-bundle/Security.php&  Qti&  򚘤      J   vendor/symfony/security-bundle/LoginLink/FirewallAwareLoginLinkHandler.php  Qti  B      H   vendor/symfony/security-bundle/DependencyInjection/MainConfiguration.php#9  Qti#9  w      c   vendor/symfony/security-bundle/DependencyInjection/Security/AccessToken/OidcTokenHandlerFactory.php0  Qti0        k   vendor/symfony/security-bundle/DependencyInjection/Security/AccessToken/OidcUserInfoTokenHandlerFactory.php
  Qti
  :      f   vendor/symfony/security-bundle/DependencyInjection/Security/AccessToken/ServiceTokenHandlerFactory.php  Qti  'tm]      h   vendor/symfony/security-bundle/DependencyInjection/Security/AccessToken/TokenHandlerFactoryInterface.php  Qti  LP      X   vendor/symfony/security-bundle/DependencyInjection/Security/UserProvider/LdapFactory.php	  Qti	  Cv      \   vendor/symfony/security-bundle/DependencyInjection/Security/UserProvider/InMemoryFactory.php  Qti  g
      i   vendor/symfony/security-bundle/DependencyInjection/Security/UserProvider/UserProviderFactoryInterface.php  Qti  vi      X   vendor/symfony/security-bundle/DependencyInjection/Security/Factory/LoginLinkFactory.phph  Qtih  .wq      \   vendor/symfony/security-bundle/DependencyInjection/Security/Factory/HttpBasicLdapFactory.php  Qti  %̤      \   vendor/symfony/security-bundle/DependencyInjection/Security/Factory/JsonLoginLdapFactory.php  Qti  7      Z   vendor/symfony/security-bundle/DependencyInjection/Security/Factory/AccessTokenFactory.php  Qti  p[      X   vendor/symfony/security-bundle/DependencyInjection/Security/Factory/FormLoginFactory.phpq  Qtiq  \`      \   vendor/symfony/security-bundle/DependencyInjection/Security/Factory/FormLoginLdapFactory.phpJ  QtiJ  g      b   vendor/symfony/security-bundle/DependencyInjection/Security/Factory/CustomAuthenticatorFactory.php  Qti  TDp      Y   vendor/symfony/security-bundle/DependencyInjection/Security/Factory/RemoteUserFactory.php  Qti  L      e   vendor/symfony/security-bundle/DependencyInjection/Security/Factory/AuthenticatorFactoryInterface.phpD  QtiD  r      Y   vendor/symfony/security-bundle/DependencyInjection/Security/Factory/RememberMeFactory.php)  Qti)  d      W   vendor/symfony/security-bundle/DependencyInjection/Security/Factory/AbstractFactory.php  Qti        S   vendor/symfony/security-bundle/DependencyInjection/Security/Factory/X509Factory.php  Qti  ͤ      a   vendor/symfony/security-bundle/DependencyInjection/Security/Factory/SignatureAlgorithmFactory.phpd  Qtid  ~]      h   vendor/symfony/security-bundle/DependencyInjection/Security/Factory/FirewallListenerFactoryInterface.php  Qti  ;      X   vendor/symfony/security-bundle/DependencyInjection/Security/Factory/JsonLoginFactory.php  Qti        n   vendor/symfony/security-bundle/DependencyInjection/Security/Factory/StatelessAuthenticatorFactoryInterface.php  Qti  Zפ      X   vendor/symfony/security-bundle/DependencyInjection/Security/Factory/HttpBasicFactory.php  Qti  s      X   vendor/symfony/security-bundle/DependencyInjection/Security/Factory/LdapFactoryTrait.phpj	  Qtij	  rH      ^   vendor/symfony/security-bundle/DependencyInjection/Security/Factory/LoginThrottlingFactory.php  Qti  ູ      H   vendor/symfony/security-bundle/DependencyInjection/SecurityExtension.php:  Qti:  6j      b   vendor/symfony/security-bundle/DependencyInjection/Compiler/AddExpressionLanguageProvidersPass.php  Qti  ߐ*7      ^   vendor/symfony/security-bundle/DependencyInjection/Compiler/RegisterTokenUsageTrackingPass.php	  Qti	  a      W   vendor/symfony/security-bundle/DependencyInjection/Compiler/RegisterLdapLocatorPass.php  Qti  GOe      h   vendor/symfony/security-bundle/DependencyInjection/Compiler/RegisterGlobalSecurityEventListenersPass.php  Qti  [۹      Y   vendor/symfony/security-bundle/DependencyInjection/Compiler/SortFirewallListenersPass.phpH  QtiH  )#Ӥ      e   vendor/symfony/security-bundle/DependencyInjection/Compiler/ReplaceDecoratedRememberMeHandlerPass.php	  Qti	  xդ      ^   vendor/symfony/security-bundle/DependencyInjection/Compiler/AddSessionDomainConstraintPass.php  Qti        U   vendor/symfony/security-bundle/DependencyInjection/Compiler/AddSecurityVotersPass.php
  Qti
  Jݞ      V   vendor/symfony/security-bundle/DependencyInjection/Compiler/RegisterEntryPointPass.php  Qti  )      i   vendor/symfony/security-bundle/DependencyInjection/Compiler/MakeFirewallsEventDispatcherTraceablePass.php`
  Qti`
  Up3      [   vendor/symfony/security-bundle/DependencyInjection/Compiler/CleanRememberMeVerifierPass.php  Qti  "*A      X   vendor/symfony/security-bundle/DependencyInjection/Compiler/RegisterCsrfFeaturesPass.php~	  Qti~	  tФ      ,   vendor/symfony/security-bundle/composer.json  Qti  ֛      B   vendor/symfony/security-bundle/Debug/TraceableFirewallListener.phpL  QtiL        8   vendor/symfony/security-bundle/Debug/WrappedListener.php  Qti  "Ԥ      ?   vendor/symfony/security-bundle/Debug/TraceableListenerTrait.phpg  Qtig        <   vendor/symfony/security-bundle/Debug/WrappedLazyListener.php
  Qti
  u0      A   vendor/symfony/security-bundle/EventListener/FirewallListener.php  Qti  [zu      =   vendor/symfony/security-bundle/EventListener/VoteListener.php@  Qti@        4   vendor/symfony/config/ResourceCheckerConfigCache.phpk  Qtik  *PȤ         vendor/symfony/config/LICENSE,  Qti,  U      '   vendor/symfony/config/Util/XmlUtils.php$  Qti$  ]רL      <   vendor/symfony/config/Util/Exception/XmlParsingException.php  Qti  䢗      <   vendor/symfony/config/Util/Exception/InvalidXmlException.php4  Qti4        "   vendor/symfony/config/CHANGELOG.mde  Qtie  (,      .   vendor/symfony/config/ConfigCacheInterface.php  Qti  QK      .   vendor/symfony/config/FileLocatorInterface.php  Qti        %   vendor/symfony/config/ConfigCache.php  Qti  xɤ      5   vendor/symfony/config/ConfigCacheFactoryInterface.php  Qti  ^e      %   vendor/symfony/config/FileLocator.php+
  Qti+
  ?p      2   vendor/symfony/config/ResourceCheckerInterface.php  Qti  åؤ         vendor/symfony/config/README.mdT  QtiT        '   vendor/symfony/config/Loader/Loader.php  Qti  ^Ф      >   vendor/symfony/config/Loader/DirectoryAwareLoaderInterface.php  Qti  dh      +   vendor/symfony/config/Loader/FileLoader.php  Qti  %      2   vendor/symfony/config/Loader/ParamConfigurator.phpp  Qtip  {a	      0   vendor/symfony/config/Loader/LoaderInterface.phpy  Qtiy  ঽ      8   vendor/symfony/config/Loader/LoaderResolverInterface.php  Qti  O      /   vendor/symfony/config/Loader/LoaderResolver.phpD  QtiD  ŉ      1   vendor/symfony/config/Loader/DelegatingLoader.php  Qti  J3      /   vendor/symfony/config/Loader/GlobFileLoader.php  Qti  N      .   vendor/symfony/config/Definition/FloatNode.php  Qti  wͤ      -   vendor/symfony/config/Definition/BaseNode.php:  Qti:  3&      0   vendor/symfony/config/Definition/NumericNode.php'  Qti'        :   vendor/symfony/config/Definition/ConfigurableInterface.phpn  Qtin  Q_!      0   vendor/symfony/config/Definition/IntegerNode.phpT  QtiT  F      ;   vendor/symfony/config/Definition/PrototypeNodeInterface.phpp  Qtip  <5@      2   vendor/symfony/config/Definition/Configuration.php  Qti  jƤ      8   vendor/symfony/config/Definition/PrototypedArrayNode.php,  Qti,  Wڴ      .   vendor/symfony/config/Definition/Processor.php	  Qti	  :      @   vendor/symfony/config/Definition/Loader/DefinitionFileLoader.php  Qti  jU'      2   vendor/symfony/config/Definition/NodeInterface.phpD  QtiD  [W2Ӥ      -   vendor/symfony/config/Definition/EnumNode.php
  Qti
  3I      0   vendor/symfony/config/Definition/BooleanNode.php  Qti  &l      H   vendor/symfony/config/Definition/Configurator/DefinitionConfigurator.phpv  Qtiv  \ݎ      .   vendor/symfony/config/Definition/ArrayNode.php.  Qti.  Fj      /   vendor/symfony/config/Definition/ScalarNode.phpz  Qtiz  m      ;   vendor/symfony/config/Definition/ConfigurationInterface.php  Qti  _+      8   vendor/symfony/config/Definition/Builder/ExprBuilder.php<  Qti<  `MjΤ      ?   vendor/symfony/config/Definition/Builder/EnumNodeDefinition.php  Qti  B      9   vendor/symfony/config/Definition/Builder/MergeBuilder.php  Qti        B   vendor/symfony/config/Definition/Builder/NumericNodeDefinition.phpj  Qtij  kϤ      8   vendor/symfony/config/Definition/Builder/NodeBuilder.php  Qti  "3%V      C   vendor/symfony/config/Definition/Builder/VariableNodeDefinition.phpe  Qtie  t      @   vendor/symfony/config/Definition/Builder/ArrayNodeDefinition.php=  Qti=  {8=      B   vendor/symfony/config/Definition/Builder/BuilderAwareInterface.phpl  Qtil  %      >   vendor/symfony/config/Definition/Builder/ValidationBuilder.php  Qti  g      8   vendor/symfony/config/Definition/Builder/TreeBuilder.phpC  QtiC        B   vendor/symfony/config/Definition/Builder/IntegerNodeDefinition.php  Qti  9      @   vendor/symfony/config/Definition/Builder/NodeParentInterface.php  Qti  ʤ      A   vendor/symfony/config/Definition/Builder/NormalizationBuilder.php  Qti  |D      B   vendor/symfony/config/Definition/Builder/BooleanNodeDefinition.php  Qti  W      J   vendor/symfony/config/Definition/Builder/ParentNodeDefinitionInterface.php  Qti  /O      A   vendor/symfony/config/Definition/Builder/ScalarNodeDefinition.php  Qti  t      @   vendor/symfony/config/Definition/Builder/FloatNodeDefinition.php  Qti  L4Τ      ;   vendor/symfony/config/Definition/Builder/NodeDefinition.phpM  QtiM  w       D   vendor/symfony/config/Definition/Exception/DuplicateKeyException.phpS  QtiS  g      I   vendor/symfony/config/Definition/Exception/InvalidDefinitionException.php  Qti  re      C   vendor/symfony/config/Definition/Exception/InvalidTypeException.php  Qti  2      @   vendor/symfony/config/Definition/Exception/UnsetKeyException.php*  Qti*  %2d      L   vendor/symfony/config/Definition/Exception/InvalidConfigurationException.php  Qti  n:      J   vendor/symfony/config/Definition/Exception/ForbiddenOverwriteException.php_  Qti_  :      8   vendor/symfony/config/Definition/Exception/Exception.php  Qti  RrO      1   vendor/symfony/config/Definition/VariableNode.php  Qti  $      ?   vendor/symfony/config/Definition/Dumper/YamlReferenceDumper.phpz   Qtiz   "*      >   vendor/symfony/config/Definition/Dumper/XmlReferenceDumper.phpf'  Qtif'  J
Ĥ      @   vendor/symfony/config/Resource/SelfCheckingResourceInterface.php  Qti  1Ĥ      /   vendor/symfony/config/Resource/FileResource.php  Qti  1%      :   vendor/symfony/config/Resource/ReflectionClassResource.php  Qti        >   vendor/symfony/config/Resource/SelfCheckingResourceChecker.php{  Qti{  zN      3   vendor/symfony/config/Resource/ComposerResource.php'  Qti'  IAǤ      8   vendor/symfony/config/Resource/FileExistenceResource.php  Qti  %a      4   vendor/symfony/config/Resource/ResourceInterface.php  Qti  k       9   vendor/symfony/config/Resource/ClassExistenceResource.php5  Qti5  E`      4   vendor/symfony/config/Resource/DirectoryResource.php
  Qti
  m6M3      /   vendor/symfony/config/Resource/GlobResource.php"  Qti"  .sD      8   vendor/symfony/config/Builder/ConfigBuilderInterface.php  Qti  HZD      (   vendor/symfony/config/Builder/Method.php  Qti  G$      .   vendor/symfony/config/Builder/ClassBuilder.phpy  Qtiy  N      *   vendor/symfony/config/Builder/Property.php   Qti   Nc      A   vendor/symfony/config/Builder/ConfigBuilderGeneratorInterface.php  Qti  ;      8   vendor/symfony/config/Builder/ConfigBuilderGenerator.php6S  Qti6S  `      7   vendor/symfony/config/Exception/LoaderLoadException.php  Qti  H      N   vendor/symfony/config/Exception/FileLoaderImportCircularReferenceException.phpZ  QtiZ  ;-      D   vendor/symfony/config/Exception/FileLocatorFileNotFoundException.phpK  QtiK  f      #   vendor/symfony/config/composer.json   Qti   M      ,   vendor/symfony/config/ConfigCacheFactory.phpR  QtiR  Y
      ;   vendor/symfony/config/ResourceCheckerConfigCacheFactory.php4  Qti4  :¤      D   vendor/symfony/security-http/RateLimiter/DefaultLoginRateLimiter.php  Qti  &J%      4   vendor/symfony/security-http/Attribute/IsGranted.php  Qti  `A      6   vendor/symfony/security-http/Attribute/CurrentUser.php!  Qti!  C      $   vendor/symfony/security-http/LICENSE,  Qti,  U      5   vendor/symfony/security-http/Util/TargetPathTrait.php_  Qti_  )N      )   vendor/symfony/security-http/CHANGELOG.md  Qti  k      ,   vendor/symfony/security-http/FirewallMap.php  Qti  Hg      )   vendor/symfony/security-http/Firewall.php+  Qti+  =x      J   vendor/symfony/security-http/AccessToken/AccessTokenExtractorInterface.phpe  Qtie  96Ȥ      H   vendor/symfony/security-http/AccessToken/AccessTokenHandlerInterface.php  Qti  ?lF      G   vendor/symfony/security-http/AccessToken/HeaderAccessTokenExtractor.php0  Qti0  'ҧǤ      F   vendor/symfony/security-http/AccessToken/ChainAccessTokenExtractor.php&  Qti&  R\      J   vendor/symfony/security-http/AccessToken/Oidc/OidcUserInfoTokenHandler.phpc	  Qtic	  ۼa      ;   vendor/symfony/security-http/AccessToken/Oidc/OidcTrait.php  Qti  P      B   vendor/symfony/security-http/AccessToken/Oidc/OidcTokenHandler.php  Qti  Lgsn      U   vendor/symfony/security-http/AccessToken/Oidc/Exception/InvalidSignatureException.php  Qti  \      Q   vendor/symfony/security-http/AccessToken/Oidc/Exception/MissingClaimException.php  Qti  x      E   vendor/symfony/security-http/AccessToken/FormEncodedBodyExtractor.phpk  Qtik  <q      F   vendor/symfony/security-http/AccessToken/QueryAccessTokenExtractor.php  Qti  [L      :   vendor/symfony/security-http/Logout/LogoutUrlGenerator.php|  Qti|  5      /   vendor/symfony/security-http/SecurityEvents.php  Qti  7      8   vendor/symfony/security-http/Firewall/AccessListener.php  Qti  ш+d      9   vendor/symfony/security-http/Firewall/ContextListener.phpu5  Qtiu5  u⡤      :   vendor/symfony/security-http/Firewall/AbstractListener.phpo  Qtio  klY      F   vendor/symfony/security-http/Firewall/AuthenticatorManagerListener.phph  Qtih  C      ;   vendor/symfony/security-http/Firewall/ExceptionListener.phpY(  QtiY(  3R      C   vendor/symfony/security-http/Firewall/FirewallListenerInterface.php;  Qti;  No      9   vendor/symfony/security-http/Firewall/ChannelListener.php  Qti  a      <   vendor/symfony/security-http/Firewall/SwitchUserListener.php[$  Qti[$  +'      8   vendor/symfony/security-http/Firewall/LogoutListener.php  Qti  Bx      F   vendor/symfony/security-http/Controller/SecurityTokenValueResolver.php  Qti  xLq      =   vendor/symfony/security-http/Controller/UserValueResolver.php  Qti  `      &   vendor/symfony/security-http/README.md  Qti  k      <   vendor/symfony/security-http/RememberMe/ResponseListener.php  Qti  q      G   vendor/symfony/security-http/RememberMe/PersistentRememberMeHandler.php6   Qti6   oF      F   vendor/symfony/security-http/RememberMe/RememberMeHandlerInterface.php  Qti  &I      =   vendor/symfony/security-http/RememberMe/RememberMeDetails.php=  Qti=  k      E   vendor/symfony/security-http/RememberMe/AbstractRememberMeHandler.phpT  QtiT  hK      F   vendor/symfony/security-http/RememberMe/SignatureRememberMeHandler.php  Qti  w_0h      M   vendor/symfony/security-http/EntryPoint/AuthenticationEntryPointInterface.php  Qti  3i      N   vendor/symfony/security-http/EntryPoint/Exception/NotAnEntryPointException.php  Qti        *   vendor/symfony/security-http/HttpUtils.php  Qti  0      5   vendor/symfony/security-http/FirewallMapInterface.phpP  QtiP  !      L   vendor/symfony/security-http/Authenticator/Token/PostAuthenticationToken.phpO  QtiO  i Z      P   vendor/symfony/security-http/Authenticator/InteractiveAuthenticatorInterface.phpi  Qtii        M   vendor/symfony/security-http/Authenticator/AbstractLoginFormAuthenticator.php	  Qti	  v:      E   vendor/symfony/security-http/Authenticator/AuthenticatorInterface.phpN  QtiN  iN      A   vendor/symfony/security-http/Authenticator/FallbackUserLoader.php  Qti  ,      D   vendor/symfony/security-http/Authenticator/AbstractAuthenticator.php  Qti  D*      E   vendor/symfony/security-http/Authenticator/HttpBasicAuthenticator.php_  Qti_  c      E   vendor/symfony/security-http/Authenticator/LoginLinkAuthenticator.php9  Qti9  Vi*      E   vendor/symfony/security-http/Authenticator/JsonLoginAuthenticator.php  Qti  I      N   vendor/symfony/security-http/Authenticator/Passport/SelfValidatingPassport.php  Qti  YWW      @   vendor/symfony/security-http/Authenticator/Passport/Passport.php  Qti  vYb      X   vendor/symfony/security-http/Authenticator/Passport/Credentials/CredentialsInterface.php  Qti  P      U   vendor/symfony/security-http/Authenticator/Passport/Credentials/CustomCredentials.php  Qti  b      W   vendor/symfony/security-http/Authenticator/Passport/Credentials/PasswordCredentials.phpi  Qtii  Bx      W   vendor/symfony/security-http/Authenticator/Passport/Badge/PreAuthenticatedUserBadge.php  Qti  a      L   vendor/symfony/security-http/Authenticator/Passport/Badge/CsrfTokenBadge.php  Qti  d      R   vendor/symfony/security-http/Authenticator/Passport/Badge/PasswordUpgradeBadge.phpq  Qtiq  (      G   vendor/symfony/security-http/Authenticator/Passport/Badge/UserBadge.php  Qti  kۤ      M   vendor/symfony/security-http/Authenticator/Passport/Badge/RememberMeBadge.phpG  QtiG  hP      L   vendor/symfony/security-http/Authenticator/Passport/Badge/BadgeInterface.php  Qti        @   vendor/symfony/security-http/Authenticator/X509Authenticator.php	  Qti	  FU      G   vendor/symfony/security-http/Authenticator/AccessTokenAuthenticator.php  Qti  -7      F   vendor/symfony/security-http/Authenticator/RemoteUserAuthenticator.php  Qti  s      E   vendor/symfony/security-http/Authenticator/FormLoginAuthenticator.phpF  QtiF  k#      T   vendor/symfony/security-http/Authenticator/AbstractPreAuthenticatedAuthenticator.php  Qti  ]:      K   vendor/symfony/security-http/Authenticator/Debug/TraceableAuthenticator.php?  Qti?        Z   vendor/symfony/security-http/Authenticator/Debug/TraceableAuthenticatorManagerListener.php_  Qti_  $      F   vendor/symfony/security-http/Authenticator/RememberMeAuthenticator.php=  Qti=  TJ      K   vendor/symfony/security-http/Authorization/AccessDeniedHandlerInterface.phpy  Qtiy  ?      3   vendor/symfony/security-http/AccessMapInterface.phph  Qtih        ;   vendor/symfony/security-http/LoginLink/LoginLinkDetails.phpb  Qtib  n      ;   vendor/symfony/security-http/LoginLink/LoginLinkHandler.php  Qti        @   vendor/symfony/security-http/LoginLink/LoginLinkNotification.php
  Qti
  n      D   vendor/symfony/security-http/LoginLink/LoginLinkHandlerInterface.php  Qti  jI      W   vendor/symfony/security-http/LoginLink/Exception/InvalidLoginLinkExceptionInterface.php  Qti  HF      N   vendor/symfony/security-http/LoginLink/Exception/InvalidLoginLinkException.php  Qti        \   vendor/symfony/security-http/LoginLink/Exception/InvalidLoginLinkAuthenticationException.php  Qti  ܍¤      N   vendor/symfony/security-http/LoginLink/Exception/ExpiredLoginLinkException.phpI  QtiI  Z      S   vendor/symfony/security-http/Authentication/DefaultAuthenticationFailureHandler.phpc  Qtic  񉛤      M   vendor/symfony/security-http/Authentication/AuthenticatorManagerInterface.php  Qti  cdΤ      R   vendor/symfony/security-http/Authentication/CustomAuthenticationSuccessHandler.php  Qti  }ts      U   vendor/symfony/security-http/Authentication/AuthenticationFailureHandlerInterface.php=  Qti=  <L+      C   vendor/symfony/security-http/Authentication/AuthenticationUtils.php	  Qti	  [      R   vendor/symfony/security-http/Authentication/CustomAuthenticationFailureHandler.php	  Qti	  J       U   vendor/symfony/security-http/Authentication/AuthenticationSuccessHandlerInterface.phpH  QtiH  "      J   vendor/symfony/security-http/Authentication/UserAuthenticatorInterface.php  Qti  &       D   vendor/symfony/security-http/Authentication/AuthenticatorManager.php6  Qti6  P      S   vendor/symfony/security-http/Authentication/DefaultAuthenticationSuccessHandler.php  Qti  \=ޤ      *   vendor/symfony/security-http/AccessMap.php}  Qti}  "g\P      8   vendor/symfony/security-http/Event/LoginFailureEvent.php5
  Qti5
  	      8   vendor/symfony/security-http/Event/LoginSuccessEvent.php3  Qti3        8   vendor/symfony/security-http/Event/LazyResponseEvent.php   Qti   Ry      6   vendor/symfony/security-http/Event/SwitchUserEvent.php  Qti  oˤ      F   vendor/symfony/security-http/Event/AuthenticationTokenCreatedEvent.phpT  QtiT  ۤ      9   vendor/symfony/security-http/Event/CheckPassportEvent.php  Qti  >,ä      <   vendor/symfony/security-http/Event/InteractiveLoginEvent.phpE  QtiE  1դ      2   vendor/symfony/security-http/Event/LogoutEvent.php  Qti  alw      @   vendor/symfony/security-http/Event/TokenDeauthenticatedEvent.php  Qti  I>&      D   vendor/symfony/security-http/Impersonate/ImpersonateUrlGenerator.php  Qti  bA      2   vendor/symfony/security-http/ParameterBagUtils.php
  Qti
        *   vendor/symfony/security-http/composer.json\  Qti\  7      :   vendor/symfony/security-http/SecurityRequestAttributes.php  Qti  J      J   vendor/symfony/security-http/EventListener/ClearSiteDataLogoutListener.php  Qti  u٤      D   vendor/symfony/security-http/EventListener/SessionLogoutListener.php  Qti  C_>      D   vendor/symfony/security-http/EventListener/DefaultLogoutListener.phpk  Qtik        H   vendor/symfony/security-http/EventListener/PasswordMigratingListener.php  Qti  ԭ?%      A   vendor/symfony/security-http/EventListener/RememberMeListener.php  Qti  VT      F   vendor/symfony/security-http/EventListener/LoginThrottlingListener.php  Qti  ;2      C   vendor/symfony/security-http/EventListener/UserProviderListener.phpe  Qtie  ø7      K   vendor/symfony/security-http/EventListener/CookieClearingLogoutListener.php  Qti  R      G   vendor/symfony/security-http/EventListener/CheckCredentialsListener.php  Qti  *ʤ      F   vendor/symfony/security-http/EventListener/SessionStrategyListener.php  Qti  $0      N   vendor/symfony/security-http/EventListener/CsrfTokenClearingLogoutListener.phpn  Qtin  [      B   vendor/symfony/security-http/EventListener/UserCheckerListener.phpf  Qtif        I   vendor/symfony/security-http/EventListener/IsGrantedAttributeListener.php  Qti        E   vendor/symfony/security-http/EventListener/CsrfProtectionListener.php  Qti  	      P   vendor/symfony/security-http/EventListener/CheckRememberMeConditionsListener.php|
  Qti|
  7      O   vendor/symfony/security-http/Session/SessionAuthenticationStrategyInterface.phpC  QtiC  'ʤ      F   vendor/symfony/security-http/Session/SessionAuthenticationStrategy.php]  Qti]  Q         vendor/symfony/uid/UuidV8.phpK  QtiK  {dL      !   vendor/symfony/uid/BinaryUtil.php  Qti  o         vendor/symfony/uid/NilUuid.php  Qti  MzĤ         vendor/symfony/uid/LICENSE,  Qti,  K         vendor/symfony/uid/NilUlid.php  Qti  [         vendor/symfony/uid/CHANGELOG.md  Qti        "   vendor/symfony/uid/AbstractUid.php5  Qti5  T         vendor/symfony/uid/Ulid.php  Qti  lm         vendor/symfony/uid/Uuid.php  Qti  $l3         vendor/symfony/uid/MaxUlid.php  Qti  >Z         vendor/symfony/uid/MaxUuid.php  Qti  Sw4         vendor/symfony/uid/README.md\  Qti\        2   vendor/symfony/uid/Command/GenerateUuidCommand.php  Qti  %wTϤ      2   vendor/symfony/uid/Command/GenerateUlidCommand.php  Qti  yw      1   vendor/symfony/uid/Command/InspectUuidCommand.php
  Qti
  =@ؤ      1   vendor/symfony/uid/Command/InspectUlidCommand.phpm  Qtim  h         vendor/symfony/uid/UuidV1.phpA  QtiA  |b         vendor/symfony/uid/UuidV3.php^  Qti^  (L         vendor/symfony/uid/UuidV6.php:  Qti:  )^jA         vendor/symfony/uid/UuidV7.php  Qti  `      3   vendor/symfony/uid/Factory/TimeBasedUuidFactory.php,  Qti,  ǘ      *   vendor/symfony/uid/Factory/UuidFactory.php5  Qti5  c      5   vendor/symfony/uid/Factory/RandomBasedUuidFactory.phpZ  QtiZ  9      *   vendor/symfony/uid/Factory/UlidFactory.php  Qti  ̛C      3   vendor/symfony/uid/Factory/NameBasedUuidFactory.php  Qti  "n          vendor/symfony/uid/composer.json  Qti  s	ۤ      ,   vendor/symfony/uid/TimeBasedUidInterface.php  Qti  Th{         vendor/symfony/uid/UuidV5.php^  Qti^  A         vendor/symfony/uid/UuidV4.php  Qti  6紝      <   vendor/symfony/event-dispatcher/EventDispatcherInterface.php  Qti  K.¤      =   vendor/symfony/event-dispatcher/Attribute/AsEventListener.php  Qti  $      '   vendor/symfony/event-dispatcher/LICENSE,  Qti,  U      ,   vendor/symfony/event-dispatcher/CHANGELOG.md]  Qti]  uE~      3   vendor/symfony/event-dispatcher/EventDispatcher.php1#  Qti1#        )   vendor/symfony/event-dispatcher/README.mdW  QtiW  ,fB      <   vendor/symfony/event-dispatcher/EventSubscriberInterface.php  Qti  A{)      <   vendor/symfony/event-dispatcher/ImmutableEventDispatcher.php  Qti  qsͤ      0   vendor/symfony/event-dispatcher/GenericEvent.php  Qti        M   vendor/symfony/event-dispatcher/DependencyInjection/RegisterListenersPass.php   Qti   Ē      K   vendor/symfony/event-dispatcher/DependencyInjection/AddEventAliasesPass.php  Qti   |      -   vendor/symfony/event-dispatcher/composer.json  Qti  R      B   vendor/symfony/event-dispatcher/Debug/TraceableEventDispatcher.phpR7  QtiR7  0bd      9   vendor/symfony/event-dispatcher/Debug/WrappedListener.php  Qti  d      +   vendor/symfony/var-dumper/Cloner/Cursor.phpH  QtiH  cq      .   vendor/symfony/var-dumper/Cloner/VarCloner.php)  Qti)  a      4   vendor/symfony/var-dumper/Cloner/ClonerInterface.php  Qti  D.7      4   vendor/symfony/var-dumper/Cloner/DumperInterface.phpo  Qtio  k      3   vendor/symfony/var-dumper/Cloner/AbstractCloner.php+Z  Qti+Z  d7      )   vendor/symfony/var-dumper/Cloner/Data.php5  Qti5  ;      )   vendor/symfony/var-dumper/Cloner/Stub.php[  Qti[  閤      !   vendor/symfony/var-dumper/LICENSE,  Qti,  .z      5   vendor/symfony/var-dumper/Test/VarDumperTestTrait.phpI
  QtiI
  gk`      &   vendor/symfony/var-dumper/CHANGELOG.md	  Qti	  "D      .   vendor/symfony/var-dumper/Caster/GmpCaster.php
  Qti
  s|"      5   vendor/symfony/var-dumper/Caster/ReflectionCaster.phpc;  Qtic;  kפ      /   vendor/symfony/var-dumper/Caster/StubCaster.php	  Qti	  Y(      2   vendor/symfony/var-dumper/Caster/SymfonyCaster.phpT  QtiT  $ۤ      .   vendor/symfony/var-dumper/Caster/FrameStub.php  Qti  aa      7   vendor/symfony/var-dumper/Caster/ProxyManagerCaster.php"  Qti"  ׵      .   vendor/symfony/var-dumper/Caster/FFICaster.php  Qti  `_K      /   vendor/symfony/var-dumper/Caster/DateCaster.php1  Qti1  XL      .   vendor/symfony/var-dumper/Caster/PdoCaster.php  Qti  lO      6   vendor/symfony/var-dumper/Caster/XmlResourceCaster.phpx	  Qtix	  3      3   vendor/symfony/var-dumper/Caster/ResourceCaster.php  Qti  -      4   vendor/symfony/var-dumper/Caster/ExceptionCaster.php3A  Qti3A  l#      6   vendor/symfony/var-dumper/Caster/UninitializedStub.phpy  Qtiy  0:      -   vendor/symfony/var-dumper/Caster/DsCaster.phpO  QtiO  |o      -   vendor/symfony/var-dumper/Caster/LinkStub.php4  Qti4        4   vendor/symfony/var-dumper/Caster/MemcachedCaster.php  Qti  NJ@      3   vendor/symfony/var-dumper/Caster/DoctrineCaster.phpG  QtiG  55      2   vendor/symfony/var-dumper/Caster/RdKafkaCaster.php  Qti  :/      1   vendor/symfony/var-dumper/Caster/MysqliCaster.php  Qti  DZA      ,   vendor/symfony/var-dumper/Caster/ImgStub.php  Qti  ͤ      .   vendor/symfony/var-dumper/Caster/ClassStub.php"  Qti"  @F迤      .   vendor/symfony/var-dumper/Caster/TraceStub.php  Qti  _      1   vendor/symfony/var-dumper/Caster/CutArrayStub.php  Qti  e      0   vendor/symfony/var-dumper/Caster/PgSqlCaster.php  Qti  q      +   vendor/symfony/var-dumper/Caster/Caster.php   Qti   8      .   vendor/symfony/var-dumper/Caster/SplCaster.phpW  QtiW  &      .   vendor/symfony/var-dumper/Caster/ConstStub.php  Qti  ށ      /   vendor/symfony/var-dumper/Caster/ScalarStub.phpF  QtiF  fA      /   vendor/symfony/var-dumper/Caster/DsPairStub.phpn  Qtin  0
      /   vendor/symfony/var-dumper/Caster/IntlCaster.php  Qti  j̤      0   vendor/symfony/var-dumper/Caster/RedisCaster.php  Qti  .&      0   vendor/symfony/var-dumper/Caster/FiberCaster.phpf  Qtif  K      2   vendor/symfony/var-dumper/Caster/ImagineCaster.php  Qti  oj      /   vendor/symfony/var-dumper/Caster/AmqpCaster.phpE  QtiE  .g      .   vendor/symfony/var-dumper/Caster/DOMCaster.phpN  QtiN  t      /   vendor/symfony/var-dumper/Caster/UuidCaster.php  Qti  Y      4   vendor/symfony/var-dumper/Caster/XmlReaderCaster.php  Qti  5      -   vendor/symfony/var-dumper/Caster/ArgsStub.php	  Qti	  &n{J      -   vendor/symfony/var-dumper/Caster/EnumStub.php  Qti  `"      ,   vendor/symfony/var-dumper/Caster/CutStub.php  Qti  R      7   vendor/symfony/var-dumper/Resources/bin/var-dump-server  Qti  sH      :   vendor/symfony/var-dumper/Resources/css/htmlDescriptor.css  Qti  Dva      8   vendor/symfony/var-dumper/Resources/js/htmlDescriptor.jsb  Qtib  h|      6   vendor/symfony/var-dumper/Resources/functions/dump.phpQ  QtiQ  w      /   vendor/symfony/var-dumper/Server/Connection.php
  Qti
  N<K3      /   vendor/symfony/var-dumper/Server/DumpServer.phpn  Qtin  Pg      #   vendor/symfony/var-dumper/README.md_  Qti_  Fq      7   vendor/symfony/var-dumper/Command/ServerDumpCommand.php  Qti  `p      H   vendor/symfony/var-dumper/Command/Descriptor/DumpDescriptorInterface.php  Qti  .\      >   vendor/symfony/var-dumper/Command/Descriptor/CliDescriptor.php
  Qti
  A2      ?   vendor/symfony/var-dumper/Command/Descriptor/HtmlDescriptor.php  Qti  Ф      ?   vendor/symfony/var-dumper/Exception/ThrowingCasterException.php  Qti  ä      1   vendor/symfony/var-dumper/Dumper/ServerDumper.php  Qti  6q      8   vendor/symfony/var-dumper/Dumper/DataDumperInterface.php@  Qti@  o/      M   vendor/symfony/var-dumper/Dumper/ContextProvider/ContextProviderInterface.php'  Qti'  l      K   vendor/symfony/var-dumper/Dumper/ContextProvider/RequestContextProvider.php  Qti  k      G   vendor/symfony/var-dumper/Dumper/ContextProvider/CliContextProvider.php  Qti  E I      J   vendor/symfony/var-dumper/Dumper/ContextProvider/SourceContextProvider.php~  Qti~  i|      3   vendor/symfony/var-dumper/Dumper/AbstractDumper.phpZ  QtiZ  H      .   vendor/symfony/var-dumper/Dumper/CliDumper.phpZ  QtiZ  s      9   vendor/symfony/var-dumper/Dumper/ContextualizedDumper.php  Qti  U      /   vendor/symfony/var-dumper/Dumper/HtmlDumper.php  Qti  b      '   vendor/symfony/var-dumper/composer.json]  Qti]        '   vendor/symfony/var-dumper/VarDumper.php  Qti  FZp      !   vendor/symfony/filesystem/LICENSE,  Qti,  U      &   vendor/symfony/filesystem/CHANGELOG.md  Qti  I      (   vendor/symfony/filesystem/Filesystem.phpt  Qtit  Q	      "   vendor/symfony/filesystem/Path.phpe  Qtie  \k\P      #   vendor/symfony/filesystem/README.md  Qti        <   vendor/symfony/filesystem/Exception/IOExceptionInterface.php  Qti        :   vendor/symfony/filesystem/Exception/ExceptionInterface.php  Qti  (l`Ф      8   vendor/symfony/filesystem/Exception/RuntimeException.php  Qti  A      3   vendor/symfony/filesystem/Exception/IOException.php  Qti  3      @   vendor/symfony/filesystem/Exception/InvalidArgumentException.php  Qti  $
      =   vendor/symfony/filesystem/Exception/FileNotFoundException.php  Qti   [:      '   vendor/symfony/filesystem/composer.json{  Qti{  zq      G   vendor/symfony/security-csrf/TokenStorage/NativeSessionTokenStorage.php
  Qti
  1      A   vendor/symfony/security-csrf/TokenStorage/SessionTokenStorage.phpc  Qtic  s-      L   vendor/symfony/security-csrf/TokenStorage/ClearableTokenStorageInterface.php3  Qti3        C   vendor/symfony/security-csrf/TokenStorage/TokenStorageInterface.php  Qti  o      $   vendor/symfony/security-csrf/LICENSE,  Qti,  U      )   vendor/symfony/security-csrf/CHANGELOG.md  Qti  >*      *   vendor/symfony/security-csrf/CsrfToken.php  Qti  Lj      &   vendor/symfony/security-csrf/README.md  Qti        :   vendor/symfony/security-csrf/CsrfTokenManagerInterface.php  Qti  \h      E   vendor/symfony/security-csrf/TokenGenerator/UriSafeTokenGenerator.php  Qti  V      G   vendor/symfony/security-csrf/TokenGenerator/TokenGeneratorInterface.php  Qti        1   vendor/symfony/security-csrf/CsrfTokenManager.php  Qti  Ն      A   vendor/symfony/security-csrf/Exception/TokenNotFoundException.php  Qti   U      *   vendor/symfony/security-csrf/composer.json  Qti  -      ,   vendor/symfony/polyfill-uuid/bootstrap80.php  Qti  jx      $   vendor/symfony/polyfill-uuid/LICENSE,  Qti,        %   vendor/symfony/polyfill-uuid/Uuid.phpB  QtiB  2Ҟ      *   vendor/symfony/polyfill-uuid/bootstrap.php#  Qti#  )      &   vendor/symfony/polyfill-uuid/README.md[  Qti[  Ƥ      *   vendor/symfony/polyfill-uuid/composer.json  Qti  {Ĥ      7   vendor/symfony/polyfill-intl-normalizer/bootstrap80.php  Qti  ,      /   vendor/symfony/polyfill-intl-normalizer/LICENSE,  Qti,  H      6   vendor/symfony/polyfill-intl-normalizer/Normalizer.php$  Qti$  l      F   vendor/symfony/polyfill-intl-normalizer/Resources/stubs/Normalizer.php  Qti  %      L   vendor/symfony/polyfill-intl-normalizer/Resources/unidata/combiningClass.php.  Qti.  Cb      T   vendor/symfony/polyfill-intl-normalizer/Resources/unidata/canonicalDecomposition.phpx  Qtix        R   vendor/symfony/polyfill-intl-normalizer/Resources/unidata/canonicalComposition.php=  Qti=  V{      X   vendor/symfony/polyfill-intl-normalizer/Resources/unidata/compatibilityDecomposition.php  Qti  [
+      5   vendor/symfony/polyfill-intl-normalizer/bootstrap.php  Qti  #p      1   vendor/symfony/polyfill-intl-normalizer/README.md  Qti  +tK      5   vendor/symfony/polyfill-intl-normalizer/composer.jsonx  Qtix        F   vendor/symfony/event-dispatcher-contracts/EventDispatcherInterface.php+  Qti+  4פ      3   vendor/symfony/event-dispatcher-contracts/Event.php  Qti  #|ͤ      1   vendor/symfony/event-dispatcher-contracts/LICENSE,  Qti,        6   vendor/symfony/event-dispatcher-contracts/CHANGELOG.md   Qti   h{#      3   vendor/symfony/event-dispatcher-contracts/README.mdZ  QtiZ  9{Am      7   vendor/symfony/event-dispatcher-contracts/composer.json?  Qti?  ׿s      8   vendor/symfony/property-access/PropertyPathInterface.php  Qti  yƤ      7   vendor/symfony/property-access/PropertyPathIterator.php  Qti  i      &   vendor/symfony/property-access/LICENSE,  Qti,  U      @   vendor/symfony/property-access/PropertyPathIteratorInterface.php  Qti  %X{      +   vendor/symfony/property-access/CHANGELOG.md
  Qti
  <4      <   vendor/symfony/property-access/PropertyAccessorInterface.php	  Qti	  sΤ      /   vendor/symfony/property-access/PropertyPath.php  Qti  (1      :   vendor/symfony/property-access/PropertyAccessorBuilder.php  Qti  u      (   vendor/symfony/property-access/README.md1  Qti1  !Q      3   vendor/symfony/property-access/PropertyAccessor.php!{  Qti!{  	iD7      1   vendor/symfony/property-access/PropertyAccess.php  Qti         6   vendor/symfony/property-access/PropertyPathBuilder.php!  Qti!  i      <   vendor/symfony/property-access/Exception/AccessException.php  Qti  KW      K   vendor/symfony/property-access/Exception/UninitializedPropertyException.php  Qti  ,      ?   vendor/symfony/property-access/Exception/ExceptionInterface.php  Qti  l      A   vendor/symfony/property-access/Exception/OutOfBoundsException.php  Qti  ؤ      =   vendor/symfony/property-access/Exception/RuntimeException.php  Qti  Cn      E   vendor/symfony/property-access/Exception/InvalidArgumentException.php  Qti  IF[3      I   vendor/symfony/property-access/Exception/InvalidPropertyPathException.php  Qti  zޤ      D   vendor/symfony/property-access/Exception/UnexpectedTypeException.phpy  Qtiy  bR      A   vendor/symfony/property-access/Exception/NoSuchIndexException.php  Qti  NQp      D   vendor/symfony/property-access/Exception/NoSuchPropertyException.php  Qti  ?      ,   vendor/symfony/property-access/composer.json  Qti  +      %   vendor/symfony/finder/SplFileInfo.php  Qti  !Q      5   vendor/symfony/finder/Comparator/NumberComparator.php
  Qti
  f&      /   vendor/symfony/finder/Comparator/Comparator.php  Qti  %^      3   vendor/symfony/finder/Comparator/DateComparator.php  Qti  %          vendor/symfony/finder/Finder.phpba  Qtiba           vendor/symfony/finder/LICENSE,  Qti,  U      "   vendor/symfony/finder/CHANGELOG.md
  Qti
  3g         vendor/symfony/finder/Glob.php5  Qti5  E         vendor/symfony/finder/README.md  Qti  C      /   vendor/symfony/finder/Iterator/LazyIterator.php  Qti  ̓L      ;   vendor/symfony/finder/Iterator/VcsIgnoredFilterIterator.php  Qti  F      <   vendor/symfony/finder/Iterator/FilecontentFilterIterator.php  Qti  ŝ      =   vendor/symfony/finder/Iterator/MultiplePcreFilterIterator.php  Qti  NDZS      :   vendor/symfony/finder/Iterator/SizeRangeFilterIterator.phpj  Qtij  1*      9   vendor/symfony/finder/Iterator/FilenameFilterIterator.phpl  Qtil  Ť      :   vendor/symfony/finder/Iterator/DateRangeFilterIterator.php  Qti        7   vendor/symfony/finder/Iterator/CustomFilterIterator.php  Qti  v*\$      =   vendor/symfony/finder/Iterator/RecursiveDirectoryIterator.phpH  QtiH  fF      A   vendor/symfony/finder/Iterator/ExcludeDirectoryFilterIterator.php,  Qti,  ʡV      3   vendor/symfony/finder/Iterator/SortableIterator.php  Qti        ;   vendor/symfony/finder/Iterator/DepthRangeFilterIterator.phpm  Qtim  L0¤      9   vendor/symfony/finder/Iterator/FileTypeFilterIterator.php{  Qti{  N       5   vendor/symfony/finder/Iterator/PathFilterIterator.php  Qti  Fߤ      #   vendor/symfony/finder/Gitignore.php  Qti  ভ      9   vendor/symfony/finder/Exception/AccessDeniedException.php  Qti        >   vendor/symfony/finder/Exception/DirectoryNotFoundException.php  Qti  )      #   vendor/symfony/finder/composer.json*  Qti*  _      -   vendor/symfony/polyfill-php83/bootstrap80.php  Qti  [gɤ      -   vendor/symfony/polyfill-php83/bootstrap81.php  Qti  p$      %   vendor/symfony/polyfill-php83/LICENSE,  Qti,  t=      B   vendor/symfony/polyfill-php83/Resources/stubs/SQLite3Exception.phpH  QtiH  <ܐ      ;   vendor/symfony/polyfill-php83/Resources/stubs/DateError.php=  Qti=  ˤ      :   vendor/symfony/polyfill-php83/Resources/stubs/Override.php  Qti  NsE      ?   vendor/symfony/polyfill-php83/Resources/stubs/DateException.phpE  QtiE        O   vendor/symfony/polyfill-php83/Resources/stubs/DateInvalidOperationException.phpY  QtiY  Mߤ      A   vendor/symfony/polyfill-php83/Resources/stubs/DateObjectError.phpG  QtiG  
.I      T   vendor/symfony/polyfill-php83/Resources/stubs/DateMalformedPeriodStringException.php^  Qti^  K      N   vendor/symfony/polyfill-php83/Resources/stubs/DateMalformedStringException.phpX  QtiX  Wߤ      @   vendor/symfony/polyfill-php83/Resources/stubs/DateRangeError.phpF  QtiF  L;      N   vendor/symfony/polyfill-php83/Resources/stubs/DateInvalidTimeZoneException.phpX  QtiX  g      V   vendor/symfony/polyfill-php83/Resources/stubs/DateMalformedIntervalStringException.php`  Qti`  6      +   vendor/symfony/polyfill-php83/bootstrap.php  Qti  Xg      '   vendor/symfony/polyfill-php83/README.md  Qti  }      '   vendor/symfony/polyfill-php83/Php83.php  Qti  }篤      +   vendor/symfony/polyfill-php83/composer.json  Qti  {V      -   vendor/symfony/polyfill-php84/bootstrap80.php  Qti  -      -   vendor/symfony/polyfill-php84/bootstrap82.php  Qti  Y a      %   vendor/symfony/polyfill-php84/LICENSE,  Qti,         >   vendor/symfony/polyfill-php84/Resources/stubs/RoundingMode.php\  Qti\  <H      ;   vendor/symfony/polyfill-php84/Resources/stubs/Pdo/Mysql.php  Qti  Q=/      >   vendor/symfony/polyfill-php84/Resources/stubs/Pdo/Firebird.phpR  QtiR  ?f      ;   vendor/symfony/polyfill-php84/Resources/stubs/Pdo/Dblib.php  Qti  l8      ;   vendor/symfony/polyfill-php84/Resources/stubs/Pdo/Pgsql.phpO  QtiO  tj      :   vendor/symfony/polyfill-php84/Resources/stubs/Pdo/Odbc.php  Qti  }      <   vendor/symfony/polyfill-php84/Resources/stubs/Pdo/Sqlite.php
  Qti
  @&      D   vendor/symfony/polyfill-php84/Resources/stubs/ReflectionConstant.php  Qti  Է      <   vendor/symfony/polyfill-php84/Resources/stubs/Deprecated.phpD  QtiD  Ž      8   vendor/symfony/polyfill-php84/Resources/RoundingMode.php(  Qti(  il      6   vendor/symfony/polyfill-php84/Resources/Deprecated.php  Qti  _      +   vendor/symfony/polyfill-php84/bootstrap.php  Qti  \      '   vendor/symfony/polyfill-php84/README.md  Qti  y2      '   vendor/symfony/polyfill-php84/Php84.php<  Qti<  Px      +   vendor/symfony/polyfill-php84/composer.json  Qti  ¾g      >   vendor/symfony/http-kernel/DataCollector/DumpDataCollector.php*  Qti*  j      @   vendor/symfony/http-kernel/DataCollector/MemoryDataCollector.php  Qti  LqP      G   vendor/symfony/http-kernel/DataCollector/LateDataCollectorInterface.php/  Qti/  D      @   vendor/symfony/http-kernel/DataCollector/RouterDataCollector.php~	  Qti~	  ޤ      >   vendor/symfony/http-kernel/DataCollector/TimeDataCollector.php  Qti  *\      C   vendor/symfony/http-kernel/DataCollector/DataCollectorInterface.php  Qti        A   vendor/symfony/http-kernel/DataCollector/RequestDataCollector.php:>  Qti:>  ll      >   vendor/symfony/http-kernel/DataCollector/AjaxDataCollector.phpi  Qtii        :   vendor/symfony/http-kernel/DataCollector/DataCollector.php>  Qti>  GU      @   vendor/symfony/http-kernel/DataCollector/LoggerDataCollector.php')  Qti')  G      @   vendor/symfony/http-kernel/DataCollector/ConfigDataCollector.php  Qti  OK      ?   vendor/symfony/http-kernel/DataCollector/EventDataCollector.php<  Qti<  #      C   vendor/symfony/http-kernel/DataCollector/ExceptionDataCollector.phpT  QtiT  ~JA      5   vendor/symfony/http-kernel/Attribute/AsController.php  Qti  UT      @   vendor/symfony/http-kernel/Attribute/AsTargetedValueResolver.php  Qti  w      .   vendor/symfony/http-kernel/Attribute/Cache.phpX  QtiX  LҌ      7   vendor/symfony/http-kernel/Attribute/MapQueryString.php  Qti  u~      7   vendor/symfony/http-kernel/Attribute/WithHttpStatus.php^  Qti^  
      4   vendor/symfony/http-kernel/Attribute/MapDateTime.php   Qti   j      :   vendor/symfony/http-kernel/Attribute/MapRequestPayload.php)  Qti)  -"y      5   vendor/symfony/http-kernel/Attribute/WithLogLevel.php  Qti  ܀#      6   vendor/symfony/http-kernel/Attribute/ValueResolver.php  Qti  \      :   vendor/symfony/http-kernel/Attribute/MapQueryParameter.php\  Qti\  %      "   vendor/symfony/http-kernel/LICENSE,  Qti,  U      R   vendor/symfony/http-kernel/ControllerMetadata/ArgumentMetadataFactoryInterface.php  Qti  Xפ      B   vendor/symfony/http-kernel/ControllerMetadata/ArgumentMetadata.php  Qti  f6      I   vendor/symfony/http-kernel/ControllerMetadata/ArgumentMetadataFactory.php  Qti  0      '   vendor/symfony/http-kernel/CHANGELOG.mdQ  QtiQ        1   vendor/symfony/http-kernel/Config/FileLocator.phpv  Qtiv  6      /   vendor/symfony/http-kernel/HttpClientKernel.php  Qti  *ؤ      2   vendor/symfony/http-kernel/TerminableInterface.php  Qti        A   vendor/symfony/http-kernel/CacheClearer/CacheClearerInterface.php*  Qti*  雗      =   vendor/symfony/http-kernel/CacheClearer/ChainCacheClearer.phpI  QtiI  fv      <   vendor/symfony/http-kernel/CacheClearer/Psr6CacheClearer.php  Qti  ;uZ>      5   vendor/symfony/http-kernel/Resources/welcome.html.php  Qti  i      )   vendor/symfony/http-kernel/HttpKernel.phpl-  Qtil-  2?      ?   vendor/symfony/http-kernel/CacheWarmer/CacheWarmerAggregate.php  Qti  v+L      6   vendor/symfony/http-kernel/CacheWarmer/CacheWarmer.php  Qti  	ᓤ      <   vendor/symfony/http-kernel/CacheWarmer/WarmableInterface.php3  Qti3  P@ˤ      ?   vendor/symfony/http-kernel/CacheWarmer/CacheWarmerInterface.php  Qti  {w]b      ,   vendor/symfony/http-kernel/Bundle/Bundle.php}  Qti}  Pؤ      5   vendor/symfony/http-kernel/Bundle/BundleInterface.php  Qti  jp      4   vendor/symfony/http-kernel/Bundle/AbstractBundle.php  Qti  2̡      5   vendor/symfony/http-kernel/Bundle/BundleExtension.php	  Qti	  <Gn      .   vendor/symfony/http-kernel/KernelInterface.php  Qti  ',      :   vendor/symfony/http-kernel/Controller/ArgumentResolver.php  Qti  DX      =   vendor/symfony/http-kernel/Controller/ControllerReference.php5  Qti5  Ul      9   vendor/symfony/http-kernel/Controller/ErrorController.php<  Qti<  'ڔä      E   vendor/symfony/http-kernel/Controller/ContainerControllerResolver.php  Qti  /j      P   vendor/symfony/http-kernel/Controller/ArgumentResolver/VariadicValueResolver.php<  Qti<  wI      O   vendor/symfony/http-kernel/Controller/ArgumentResolver/ServiceValueResolver.phph  Qtih  ;Ӥ      O   vendor/symfony/http-kernel/Controller/ArgumentResolver/DefaultValueResolver.php  Qti  ~B      V   vendor/symfony/http-kernel/Controller/ArgumentResolver/QueryParameterValueResolver.php  Qti        K   vendor/symfony/http-kernel/Controller/ArgumentResolver/UidValueResolver.php  Qti  |      R   vendor/symfony/http-kernel/Controller/ArgumentResolver/BackedEnumValueResolver.php*  Qti*  Ef<      V   vendor/symfony/http-kernel/Controller/ArgumentResolver/RequestPayloadValueResolver.php%  Qti%  `,͌      P   vendor/symfony/http-kernel/Controller/ArgumentResolver/DateTimeValueResolver.php  Qti  5%      O   vendor/symfony/http-kernel/Controller/ArgumentResolver/RequestValueResolver.php  Qti        O   vendor/symfony/http-kernel/Controller/ArgumentResolver/SessionValueResolver.php  Qti  W)      X   vendor/symfony/http-kernel/Controller/ArgumentResolver/RequestAttributeValueResolver.php  Qti        [   vendor/symfony/http-kernel/Controller/ArgumentResolver/NotTaggedControllerValueResolver.php+  Qti+        Q   vendor/symfony/http-kernel/Controller/ArgumentResolver/TraceableValueResolver.php1  Qti1  	      C   vendor/symfony/http-kernel/Controller/ArgumentResolverInterface.phps  Qtis  ,      E   vendor/symfony/http-kernel/Controller/ControllerResolverInterface.phpx  Qtix  N      C   vendor/symfony/http-kernel/Controller/TraceableArgumentResolver.php  Qti  F      @   vendor/symfony/http-kernel/Controller/ValueResolverInterface.php  Qti  ЛѤ      <   vendor/symfony/http-kernel/Controller/ControllerResolver.php(  Qti(  T_      E   vendor/symfony/http-kernel/Controller/TraceableControllerResolver.phpI  QtiI  g`      H   vendor/symfony/http-kernel/Controller/ArgumentValueResolverInterface.php  Qti  R      $   vendor/symfony/http-kernel/README.md  Qti  7      E   vendor/symfony/http-kernel/Fragment/FragmentUriGeneratorInterface.php9  Qti9  "K#      >   vendor/symfony/http-kernel/Fragment/InlineFragmentRenderer.php  Qti  0      ;   vendor/symfony/http-kernel/Fragment/SsiFragmentRenderer.php$  Qti$  \fd      I   vendor/symfony/http-kernel/Fragment/AbstractSurrogateFragmentRenderer.php  Qti  8,h      A   vendor/symfony/http-kernel/Fragment/FragmentRendererInterface.php  Qti        <   vendor/symfony/http-kernel/Fragment/FragmentUriGenerator.php  Qti  EM]      ;   vendor/symfony/http-kernel/Fragment/EsiFragmentRenderer.php$  Qti$  a      @   vendor/symfony/http-kernel/Fragment/HIncludeFragmentRenderer.php)  Qti)  n      7   vendor/symfony/http-kernel/Fragment/FragmentHandler.php  Qti  }a      @   vendor/symfony/http-kernel/Fragment/RoutableFragmentRenderer.php*  Qti*  w=\      +   vendor/symfony/http-kernel/KernelEvents.phpd  Qtid  Z$      ,   vendor/symfony/http-kernel/HttpCache/Esi.php  Qti  wU      2   vendor/symfony/http-kernel/HttpCache/HttpCache.phpk  Qtik  -9Ĥ      .   vendor/symfony/http-kernel/HttpCache/Store.php9  Qti9  *      ;   vendor/symfony/http-kernel/HttpCache/SurrogateInterface.php  Qti  Tפ      G   vendor/symfony/http-kernel/HttpCache/ResponseCacheStrategyInterface.php:  Qti:  )Ou      >   vendor/symfony/http-kernel/HttpCache/ResponseCacheStrategy.php!  Qti!  m      7   vendor/symfony/http-kernel/HttpCache/StoreInterface.php  Qti  t=      ,   vendor/symfony/http-kernel/HttpCache/Ssi.phpG
  QtiG
  cu      @   vendor/symfony/http-kernel/HttpCache/CacheWasLockedException.phpy  Qtiy  Lv      :   vendor/symfony/http-kernel/HttpCache/AbstractSurrogate.php  Qti  SN      :   vendor/symfony/http-kernel/HttpCache/SubRequestHandler.php*  Qti*  \      2   vendor/symfony/http-kernel/HttpKernelInterface.php  Qti        )   vendor/symfony/http-kernel/Log/Logger.php  Qti        7   vendor/symfony/http-kernel/Log/DebugLoggerInterface.phpD  QtiD  'V      :   vendor/symfony/http-kernel/Log/DebugLoggerConfigurator.phpF  QtiF  d      ;   vendor/symfony/http-kernel/Profiler/FileProfilerStorage.php8(  Qti8(  R=      /   vendor/symfony/http-kernel/Profiler/Profile.php_  Qti_  y^      0   vendor/symfony/http-kernel/Profiler/Profiler.php  Qti  @      @   vendor/symfony/http-kernel/Profiler/ProfilerStorageInterface.php  Qti  [ޤ      G   vendor/symfony/http-kernel/DependencyInjection/FragmentRendererPass.php  Qti  |69      C   vendor/symfony/http-kernel/DependencyInjection/ServicesResetter.php  Qti  OA      R   vendor/symfony/http-kernel/DependencyInjection/RegisterLocaleAwareServicesPass.php  Qti  2@      H   vendor/symfony/http-kernel/DependencyInjection/ResettableServicePass.php  Qti  &ˏ      R   vendor/symfony/http-kernel/DependencyInjection/MergeExtensionConfigurationPass.php  Qti        Q   vendor/symfony/http-kernel/DependencyInjection/AddAnnotatedClassesToCachePass.php  Qti  :      H   vendor/symfony/http-kernel/DependencyInjection/ConfigurableExtension.php  Qti  Drߤ      =   vendor/symfony/http-kernel/DependencyInjection/LoggerPass.php)  Qti)  Q*      <   vendor/symfony/http-kernel/DependencyInjection/Extension.php]  Qti]  д      V   vendor/symfony/http-kernel/DependencyInjection/ControllerArgumentValueResolverPass.phpW  QtiW  2      Y   vendor/symfony/http-kernel/DependencyInjection/RegisterControllerArgumentLocatorsPass.php/  Qti/  0S      \   vendor/symfony/http-kernel/DependencyInjection/RemoveEmptyControllerArgumentLocatorsPass.php
  Qti
  5ᮤ      M   vendor/symfony/http-kernel/DependencyInjection/LazyLoadingFragmentHandler.php   Qti   `      E   vendor/symfony/http-kernel/Exception/TooManyRequestsHttpException.php  Qti  <      >   vendor/symfony/http-kernel/Exception/ConflictHttpException.phpc  Qtic        6   vendor/symfony/http-kernel/Exception/HttpException.phpL  QtiL  y3      B   vendor/symfony/http-kernel/Exception/UnauthorizedHttpException.php  Qti  8      A   vendor/symfony/http-kernel/Exception/InvalidMetadataException.phpj  Qtij  ;녤      D   vendor/symfony/http-kernel/Exception/LengthRequiredHttpException.phpi  Qtii  
l      I   vendor/symfony/http-kernel/Exception/UnprocessableEntityHttpException.phpw  Qtiw  3      H   vendor/symfony/http-kernel/Exception/PreconditionFailedHttpException.phpm  Qtim  m%      :   vendor/symfony/http-kernel/Exception/GoneHttpException.php_  Qti_  ey      J   vendor/symfony/http-kernel/Exception/UnsupportedMediaTypeHttpException.phpo  Qtio  aM}      H   vendor/symfony/http-kernel/Exception/UnexpectedSessionUsageException.php  Qti  Zis      <   vendor/symfony/http-kernel/Exception/LockedHttpException.phpe  Qtie  peh      H   vendor/symfony/http-kernel/Exception/ServiceUnavailableHttpException.phpm  Qtim  =      ?   vendor/symfony/http-kernel/Exception/HttpExceptionInterface.php{  Qti{  吘      B   vendor/symfony/http-kernel/Exception/AccessDeniedHttpException.php  Qti  6HHg      @   vendor/symfony/http-kernel/Exception/BadRequestHttpException.phpe  Qtie  Ց      Q   vendor/symfony/http-kernel/Exception/ControllerDoesNotReturnResponseException.php  Qti  x      C   vendor/symfony/http-kernel/Exception/NotAcceptableHttpException.phph  Qtih  (ޤ      J   vendor/symfony/http-kernel/Exception/PreconditionRequiredHttpException.php  Qti  cԤ      >   vendor/symfony/http-kernel/Exception/NotFoundHttpException.phpj  Qtij  Vz      F   vendor/symfony/http-kernel/Exception/MethodNotAllowedHttpException.php  Qti  1      B   vendor/symfony/http-kernel/Exception/ResolverNotFoundException.php  Qti  4      4   vendor/symfony/http-kernel/Event/ControllerEvent.php[  Qti[  P7e      3   vendor/symfony/http-kernel/Event/ExceptionEvent.php  Qti  5^      7   vendor/symfony/http-kernel/Event/FinishRequestEvent.php  Qti  TY      2   vendor/symfony/http-kernel/Event/ResponseEvent.php  Qti  5I      3   vendor/symfony/http-kernel/Event/TerminateEvent.php  Qti  S8      =   vendor/symfony/http-kernel/Event/ControllerArgumentsEvent.php  Qti  OZФ      0   vendor/symfony/http-kernel/Event/KernelEvent.php  Qti  E/      1   vendor/symfony/http-kernel/Event/RequestEvent.php  Qti  Nb?      .   vendor/symfony/http-kernel/Event/ViewEvent.php  Qti  _      (   vendor/symfony/http-kernel/composer.jsonq  Qtiq  H      2   vendor/symfony/http-kernel/RebootableInterface.php<  Qti<  pLX1      %   vendor/symfony/http-kernel/Kernel.phpx  Qtix  N      (   vendor/symfony/http-kernel/UriSigner.php  Qti  	T      8   vendor/symfony/http-kernel/Debug/VirtualRequestStack.phpD  QtiD  z      =   vendor/symfony/http-kernel/Debug/ErrorHandlerConfigurator.php  Qti  wH`      =   vendor/symfony/http-kernel/Debug/TraceableEventDispatcher.php  Qti  ^W"      6   vendor/symfony/http-kernel/Debug/FileLinkFormatter.php  Qti  Y      0   vendor/symfony/http-kernel/HttpKernelBrowser.php  Qti  ȎK      E   vendor/symfony/http-kernel/EventListener/StreamedResponseListener.php  Qti  2      =   vendor/symfony/http-kernel/EventListener/ResponseListener.php  Qti  5,S+      ;   vendor/symfony/http-kernel/EventListener/LocaleListener.php0  Qti0  5/ڤ      =   vendor/symfony/http-kernel/EventListener/FragmentListener.php2  Qti2  lS      C   vendor/symfony/http-kernel/EventListener/CacheAttributeListener.php  Qti  GA      D   vendor/symfony/http-kernel/EventListener/AbstractSessionListener.phpR0  QtiR0  V      D   vendor/symfony/http-kernel/EventListener/ValidateRequestListener.php  Qti  E      K   vendor/symfony/http-kernel/EventListener/DisallowRobotsIndexingListener.phpm  Qtim  5,       F   vendor/symfony/http-kernel/EventListener/AddRequestFormatsListener.php  Qti  Jj      =   vendor/symfony/http-kernel/EventListener/ProfilerListener.php1  Qti1  I]      >   vendor/symfony/http-kernel/EventListener/SurrogateListener.phpS  QtiS  u:!      B   vendor/symfony/http-kernel/EventListener/DebugHandlersListener.php  Qti        @   vendor/symfony/http-kernel/EventListener/LocaleAwareListener.php	  Qti	  銤      9   vendor/symfony/http-kernel/EventListener/DumpListener.php$  Qti$        :   vendor/symfony/http-kernel/EventListener/ErrorListener.php!  Qti!        <   vendor/symfony/http-kernel/EventListener/SessionListener.php  Qti  :1O      ;   vendor/symfony/http-kernel/EventListener/RouterListener.php  Qti  ;7Z         vendor/symfony/yaml/LICENSE,  Qti,  U         vendor/symfony/yaml/Parser.php_  Qti_  4L          vendor/symfony/yaml/CHANGELOG.md  Qti  Ĥ         vendor/symfony/yaml/Escaper.phpi  Qtii  *      +   vendor/symfony/yaml/Resources/bin/yaml-lint  Qti  Dw         vendor/symfony/yaml/README.md  Qti  ـT      !   vendor/symfony/yaml/Unescaper.php=  Qti=  K         vendor/symfony/yaml/Dumper.php  Qti  `ͤ         vendor/symfony/yaml/Inline.php  Qti  %9         vendor/symfony/yaml/Yaml.php  Qti  zO      +   vendor/symfony/yaml/Command/LintCommand.php'  Qti'  u      /   vendor/symfony/yaml/Exception/DumpException.php  Qti  ?<̤      4   vendor/symfony/yaml/Exception/ExceptionInterface.php  Qti  ,P      2   vendor/symfony/yaml/Exception/RuntimeException.php  Qti  #OU      0   vendor/symfony/yaml/Exception/ParseException.php  Qti  F4}      '   vendor/symfony/yaml/Tag/TaggedValue.php  Qti  $m      !   vendor/symfony/yaml/composer.json  Qti   Zܦ      )   vendor/symfony/string/CodePointString.php  Qti  |j         vendor/symfony/string/LICENSE,  Qti,  զ_Ϥ      "   vendor/symfony/string/CHANGELOG.mdz  Qtiz  ub      (   vendor/symfony/string/AbstractString.phpI  QtiI  Z^R      -   vendor/symfony/string/Resources/functions.php_  Qti_  ,      <   vendor/symfony/string/Resources/data/wcswidth_table_zero.phpF  QtiF  MI      <   vendor/symfony/string/Resources/data/wcswidth_table_wide.phpk  Qtik  /      3   vendor/symfony/string/Inflector/FrenchInflector.php  Qti        6   vendor/symfony/string/Inflector/InflectorInterface.phpP  QtiP  o^҅      4   vendor/symfony/string/Inflector/EnglishInflector.phpF  QtiF  &         vendor/symfony/string/README.md+  Qti+  L      /   vendor/symfony/string/AbstractUnicodeString.phpee  Qtiee  V[      $   vendor/symfony/string/LazyString.phpn  Qtin  ?ޢq      $   vendor/symfony/string/ByteString.php)9  Qti)9        '   vendor/symfony/string/UnicodeString.php:5  Qti:5  Ks]      6   vendor/symfony/string/Exception/ExceptionInterface.php_  Qti_  :      4   vendor/symfony/string/Exception/RuntimeException.php~  Qti~  )Ʉ      <   vendor/symfony/string/Exception/InvalidArgumentException.php  Qti  B;8      #   vendor/symfony/string/composer.json  Qti  ä      2   vendor/symfony/string/Slugger/SluggerInterface.php  Qti  pa      .   vendor/symfony/string/Slugger/AsciiSlugger.php  Qti  TO      4   vendor/symfony/security-core/Role/SwitchUserRole.php  Qti  'v      <   vendor/symfony/security-core/Role/RoleHierarchyInterface.php\  Qti\  Ҥ      *   vendor/symfony/security-core/Role/Role.php  Qti  `my      3   vendor/symfony/security-core/Role/RoleHierarchy.php  Qti  [      C   vendor/symfony/security-core/Validator/Constraints/UserPassword.php!  Qti!  <      L   vendor/symfony/security-core/Validator/Constraints/UserPasswordValidator.php}
  Qti}
  =d      $   vendor/symfony/security-core/LICENSE,  Qti,  U      D   vendor/symfony/security-core/Test/AccessDecisionStrategyTestCase.php
  Qti
  k      B   vendor/symfony/security-core/Signature/ExpiredSignatureStorage.php  Qti  }x      N   vendor/symfony/security-core/Signature/Exception/InvalidSignatureException.php  Qti  [.ܤ      N   vendor/symfony/security-core/Signature/Exception/ExpiredSignatureException.php  Qti  (:      :   vendor/symfony/security-core/Signature/SignatureHasher.php  Qti  "r      )   vendor/symfony/security-core/CHANGELOG.md  Qti  &      C   vendor/symfony/security-core/Resources/translations/security.sq.xlfS  QtiS  B&^      C   vendor/symfony/security-core/Resources/translations/security.ru.xlf  Qti  m      C   vendor/symfony/security-core/Resources/translations/security.hy.xlf  Qti  Y	Y      C   vendor/symfony/security-core/Resources/translations/security.fr.xlfU  QtiU  $      C   vendor/symfony/security-core/Resources/translations/security.fa.xlf  Qti  IѤ      C   vendor/symfony/security-core/Resources/translations/security.pl.xlf  Qti  u      C   vendor/symfony/security-core/Resources/translations/security.sv.xlf  Qti  '(      C   vendor/symfony/security-core/Resources/translations/security.el.xlf8  Qti8  yva      H   vendor/symfony/security-core/Resources/translations/security.sr_Cyrl.xlf  Qti        C   vendor/symfony/security-core/Resources/translations/security.en.xlfl  Qtil  gBZ      C   vendor/symfony/security-core/Resources/translations/security.ja.xlf  Qti  H      F   vendor/symfony/security-core/Resources/translations/security.pt_BR.xlf  Qti  iH!      C   vendor/symfony/security-core/Resources/translations/security.no.xlf  Qti  SQ      C   vendor/symfony/security-core/Resources/translations/security.vi.xlf,  Qti,  a      C   vendor/symfony/security-core/Resources/translations/security.ur.xlf  Qti  g      C   vendor/symfony/security-core/Resources/translations/security.nn.xlf  Qti  l      C   vendor/symfony/security-core/Resources/translations/security.nl.xlf  Qti  "֤      C   vendor/symfony/security-core/Resources/translations/security.cy.xlfv  Qtiv  FŤ      C   vendor/symfony/security-core/Resources/translations/security.af.xlf  Qti  bl      C   vendor/symfony/security-core/Resources/translations/security.lv.xlfc  Qtic  @ۤ      C   vendor/symfony/security-core/Resources/translations/security.ar.xlf  Qti  OD      C   vendor/symfony/security-core/Resources/translations/security.lb.xlf  Qti  &      C   vendor/symfony/security-core/Resources/translations/security.tr.xlf  Qti  0˵      C   vendor/symfony/security-core/Resources/translations/security.lt.xlfU  QtiU  ={0      F   vendor/symfony/security-core/Resources/translations/security.zh_CN.xlf  Qti  D      C   vendor/symfony/security-core/Resources/translations/security.ca.xlf  Qti  
      C   vendor/symfony/security-core/Resources/translations/security.be.xlfX  QtiX  \ä      C   vendor/symfony/security-core/Resources/translations/security.th.xlf  Qti  x=ݤ      C   vendor/symfony/security-core/Resources/translations/security.uz.xlfK  QtiK  ;r      C   vendor/symfony/security-core/Resources/translations/security.mk.xlf  Qti  ڞ      C   vendor/symfony/security-core/Resources/translations/security.bs.xlf  Qti  %}o      C   vendor/symfony/security-core/Resources/translations/security.bg.xlf  Qti  d캤      H   vendor/symfony/security-core/Resources/translations/security.sr_Latn.xlf6  Qti6  dξ      C   vendor/symfony/security-core/Resources/translations/security.uk.xlf  Qti  6V      F   vendor/symfony/security-core/Resources/translations/security.zh_TW.xlf  Qti  Ȉf      C   vendor/symfony/security-core/Resources/translations/security.cs.xlf  Qti  S0k3      C   vendor/symfony/security-core/Resources/translations/security.tl.xlfW  QtiW        C   vendor/symfony/security-core/Resources/translations/security.my.xlf  Qti  [v      C   vendor/symfony/security-core/Resources/translations/security.nb.xlf  Qti  SQ      C   vendor/symfony/security-core/Resources/translations/security.mn.xlf  Qti  އ      C   vendor/symfony/security-core/Resources/translations/security.az.xlf=  Qti=  c!      C   vendor/symfony/security-core/Resources/translations/security.eu.xlf  Qti  bs`      C   vendor/symfony/security-core/Resources/translations/security.he.xlfh  Qtih  u      C   vendor/symfony/security-core/Resources/translations/security.hr.xlf[  Qti[        C   vendor/symfony/security-core/Resources/translations/security.pt.xlf  Qti  5>      C   vendor/symfony/security-core/Resources/translations/security.et.xlf  Qti  
j      C   vendor/symfony/security-core/Resources/translations/security.de.xlfV  QtiV  :      C   vendor/symfony/security-core/Resources/translations/security.sl.xlf  Qti  A      C   vendor/symfony/security-core/Resources/translations/security.it.xlf  Qti  a      C   vendor/symfony/security-core/Resources/translations/security.gl.xlf  Qti  _      C   vendor/symfony/security-core/Resources/translations/security.es.xlf0  Qti0  |񗢤      C   vendor/symfony/security-core/Resources/translations/security.hu.xlf:  Qti:  KY      C   vendor/symfony/security-core/Resources/translations/security.da.xlf  Qti        C   vendor/symfony/security-core/Resources/translations/security.fi.xlf  Qti  j      C   vendor/symfony/security-core/Resources/translations/security.id.xlf  Qti  x"      C   vendor/symfony/security-core/Resources/translations/security.sk.xlf  Qti  ^P      C   vendor/symfony/security-core/Resources/translations/security.ro.xlfy  Qtiy  Aze      J   vendor/symfony/security-core/User/AttributesBasedUserProviderInterface.phpM  QtiM  Ƭs      .   vendor/symfony/security-core/User/OidcUser.php  Qti  {b      9   vendor/symfony/security-core/User/InMemoryUserChecker.php  Qti  l      3   vendor/symfony/security-core/User/UserInterface.php  Qti   _j      ;   vendor/symfony/security-core/User/UserProviderInterface.phpH	  QtiH	  ۤ      9   vendor/symfony/security-core/User/MissingUserProvider.php  Qti  a      6   vendor/symfony/security-core/User/ChainUserChecker.phpb  Qtib  c{      N   vendor/symfony/security-core/User/LegacyPasswordAuthenticatedUserInterface.php0  Qti0  ʤ      ?   vendor/symfony/security-core/User/PasswordUpgraderInterface.php  Qti   l      2   vendor/symfony/security-core/User/InMemoryUser.phpN  QtiN  WKWB      :   vendor/symfony/security-core/User/InMemoryUserProvider.php  Qti  V       8   vendor/symfony/security-core/User/EquatableInterface.phpl  Qtil  SPE      H   vendor/symfony/security-core/User/PasswordAuthenticatedUserInterface.php  Qti  ϶      :   vendor/symfony/security-core/User/UserCheckerInterface.phpb  Qtib  P      7   vendor/symfony/security-core/User/ChainUserProvider.phpI  QtiI  (      &   vendor/symfony/security-core/README.md  Qti  {u!      L   vendor/symfony/security-core/Authorization/AuthorizationCheckerInterface.php1  Qti1  [      I   vendor/symfony/security-core/Authorization/ExpressionLanguageProvider.phpU  QtiU  S~{      M   vendor/symfony/security-core/Authorization/TraceableAccessDecisionManager.phpu  Qtiu  q      D   vendor/symfony/security-core/Authorization/AccessDecisionManager.php`  Qti`  Z      M   vendor/symfony/security-core/Authorization/AccessDecisionManagerInterface.php|  Qti|  6c]      C   vendor/symfony/security-core/Authorization/Voter/VoterInterface.php  Qti  ])      L   vendor/symfony/security-core/Authorization/Voter/CacheableVoterInterface.php|  Qti|  b:O      D   vendor/symfony/security-core/Authorization/Voter/ExpressionVoter.php/  Qti/  'Y      G   vendor/symfony/security-core/Authorization/Voter/RoleHierarchyVoter.phpl  Qtil  H??      C   vendor/symfony/security-core/Authorization/Voter/TraceableVoter.php%  Qti%        :   vendor/symfony/security-core/Authorization/Voter/Voter.php`  Qti`  wʤ      >   vendor/symfony/security-core/Authorization/Voter/RoleVoter.php  Qti  y\      G   vendor/symfony/security-core/Authorization/Voter/AuthenticatedVoter.php@  Qti@  \      A   vendor/symfony/security-core/Authorization/ExpressionLanguage.php~  Qti~  u      C   vendor/symfony/security-core/Authorization/AuthorizationChecker.php  Qti  dzJ      H   vendor/symfony/security-core/Authorization/Strategy/PriorityStrategy.php  Qti  ŝY      I   vendor/symfony/security-core/Authorization/Strategy/UnanimousStrategy.php-  Qti-  eP      K   vendor/symfony/security-core/Authorization/Strategy/AffirmativeStrategy.php  Qti  ≤      I   vendor/symfony/security-core/Authorization/Strategy/ConsensusStrategy.php  Qti  %      W   vendor/symfony/security-core/Authorization/Strategy/AccessDecisionStrategyInterface.php\  Qti\  !֬S      )   vendor/symfony/security-core/Security.php	  Qti	  Bä      @   vendor/symfony/security-core/Exception/AccessDeniedException.php!  Qti!  ,      D   vendor/symfony/security-core/Exception/InvalidCsrfTokenException.php|  Qti|  o      :   vendor/symfony/security-core/Exception/LogoutException.php  Qti  y'פ      9   vendor/symfony/security-core/Exception/LogicException.php  Qti  $2      @   vendor/symfony/security-core/Exception/LazyResponseException.php  Qti  iQ      S   vendor/symfony/security-core/Exception/CustomUserMessageAuthenticationException.php  Qti  i	      =   vendor/symfony/security-core/Exception/ExceptionInterface.php  Qti  ^      B   vendor/symfony/security-core/Exception/BadCredentialsException.php  Qti  PR      ;   vendor/symfony/security-core/Exception/RuntimeException.php  Qti  >
      <   vendor/symfony/security-core/Exception/DisabledException.phpu  Qtiu  tX      A   vendor/symfony/security-core/Exception/TokenNotFoundException.php  Qti  ZJ|      D   vendor/symfony/security-core/Exception/ProviderNotFoundException.php  Qti  ֤      F   vendor/symfony/security-core/Exception/SessionUnavailableException.phpy  Qtiy  {      C   vendor/symfony/security-core/Exception/InvalidArgumentException.php  Qti  W.      B   vendor/symfony/security-core/Exception/AccountExpiredException.php  Qti  ]hB      I   vendor/symfony/security-core/Exception/AuthenticationExpiredException.phpF  QtiF  Ȩ      V   vendor/symfony/security-core/Exception/TooManyLoginAttemptsAuthenticationException.phpx  Qtix  03      ?   vendor/symfony/security-core/Exception/CookieTheftException.php  Qti  4'      I   vendor/symfony/security-core/Exception/AuthenticationServiceException.php  Qti  ֓      C   vendor/symfony/security-core/Exception/UnsupportedUserException.phpJ  QtiJ  jۤ      A   vendor/symfony/security-core/Exception/AccountStatusException.php  Qti  0s      R   vendor/symfony/security-core/Exception/CustomUserMessageAccountStatusException.php  Qti  5      N   vendor/symfony/security-core/Exception/InsufficientAuthenticationException.php%  Qti%  ^      :   vendor/symfony/security-core/Exception/LockedException.phpk  Qtik        B   vendor/symfony/security-core/Exception/AuthenticationException.php
  Qti
  ?      @   vendor/symfony/security-core/Exception/UserNotFoundException.php9  Qti9  P|      U   vendor/symfony/security-core/Exception/AuthenticationCredentialsNotFoundException.php  Qti  5v      F   vendor/symfony/security-core/Exception/CredentialsExpiredException.php  Qti  7      C   vendor/symfony/security-core/Authentication/Token/AbstractToken.phpS  QtiS  KH      ?   vendor/symfony/security-core/Authentication/Token/NullToken.php  Qti  lH      W   vendor/symfony/security-core/Authentication/Token/Storage/UsageTrackingTokenStorage.php|	  Qti|	        J   vendor/symfony/security-core/Authentication/Token/Storage/TokenStorage.php1  Qti1  q      S   vendor/symfony/security-core/Authentication/Token/Storage/TokenStorageInterface.php  Qti  	      E   vendor/symfony/security-core/Authentication/Token/RememberMeToken.php  Qti  ?      E   vendor/symfony/security-core/Authentication/Token/SwitchUserToken.phph  Qtih  '      K   vendor/symfony/security-core/Authentication/Token/PreAuthenticatedToken.php  Qti  hDy      D   vendor/symfony/security-core/Authentication/Token/TokenInterface.php(	  Qti(	  =      K   vendor/symfony/security-core/Authentication/Token/UsernamePasswordToken.php  Qti  Vd      T   vendor/symfony/security-core/Authentication/AuthenticationTrustResolverInterface.php]  Qti]  2	      K   vendor/symfony/security-core/Authentication/AuthenticationTrustResolver.phpt  Qtit        S   vendor/symfony/security-core/Authentication/RememberMe/PersistentTokenInterface.php  Qti  9e      P   vendor/symfony/security-core/Authentication/RememberMe/InMemoryTokenProvider.phpL  QtiL  _      M   vendor/symfony/security-core/Authentication/RememberMe/CacheTokenVerifier.php	  Qti	  =      J   vendor/symfony/security-core/Authentication/RememberMe/PersistentToken.php  Qti  ;W      Q   vendor/symfony/security-core/Authentication/RememberMe/TokenVerifierInterface.php^  Qti^  ؤ      Q   vendor/symfony/security-core/Authentication/RememberMe/TokenProviderInterface.php  Qti  ۤ      A   vendor/symfony/security-core/Event/AuthenticationSuccessEvent.phpu  Qtiu        :   vendor/symfony/security-core/Event/AuthenticationEvent.php  Qti  :7x      0   vendor/symfony/security-core/Event/VoteEvent.php)  Qti)  <M      *   vendor/symfony/security-core/composer.json  Qti  x4      5   vendor/symfony/security-core/AuthenticationEvents.php  Qti  "a䚤      ,   vendor/symfony/deprecation-contracts/LICENSE,  Qti,  K      1   vendor/symfony/deprecation-contracts/CHANGELOG.md   Qti   h{#      1   vendor/symfony/deprecation-contracts/function.php  Qti  Oݤ      .   vendor/symfony/deprecation-contracts/README.md  Qti  X      2   vendor/symfony/deprecation-contracts/composer.jsonS  QtiS  No      (   vendor/symfony/routing/CompiledRoute.php)  Qti)  E5t      *   vendor/symfony/routing/Attribute/Route.php  Qti  F         vendor/symfony/routing/LICENSE,  Qti,  U      (   vendor/symfony/routing/RouteCompiler.php28  Qti28  4      #   vendor/symfony/routing/CHANGELOG.md6  Qti6  V^      )   vendor/symfony/routing/RequestContext.phpC  QtiC  NS      +   vendor/symfony/routing/Annotation/Route.php  Qti  Q      :   vendor/symfony/routing/Matcher/RequestMatcherInterface.php*  Qti*        =   vendor/symfony/routing/Matcher/ExpressionLanguageProvider.php  Qti  }xx~      -   vendor/symfony/routing/Matcher/UrlMatcher.php['  Qti['  J
{      B   vendor/symfony/routing/Matcher/RedirectableUrlMatcherInterface.phpn  Qtin   +      6   vendor/symfony/routing/Matcher/UrlMatcherInterface.php  Qti  5g¤      5   vendor/symfony/routing/Matcher/CompiledUrlMatcher.php  Qti  *g      6   vendor/symfony/routing/Matcher/TraceableUrlMatcher.php^  Qti^  I8	      B   vendor/symfony/routing/Matcher/Dumper/CompiledUrlMatcherDumper.phpJ  QtiJ  .#      7   vendor/symfony/routing/Matcher/Dumper/MatcherDumper.php  Qti  IQ      @   vendor/symfony/routing/Matcher/Dumper/MatcherDumperInterface.phpe  Qtie  T      A   vendor/symfony/routing/Matcher/Dumper/CompiledUrlMatcherTrait.php  Qti  缝      @   vendor/symfony/routing/Matcher/Dumper/StaticPrefixCollection.php  Qti   R      9   vendor/symfony/routing/Matcher/RedirectableUrlMatcher.php/  Qti/            vendor/symfony/routing/README.md  Qti  rɤ      9   vendor/symfony/routing/Generator/CompiledUrlGenerator.php
  Qti
  j      1   vendor/symfony/routing/Generator/UrlGenerator.php;  Qti;  y      F   vendor/symfony/routing/Generator/ConfigurableRequirementsInterface.php  Qti  դ      :   vendor/symfony/routing/Generator/UrlGeneratorInterface.php  Qti  a      D   vendor/symfony/routing/Generator/Dumper/GeneratorDumperInterface.phpg  Qtig        F   vendor/symfony/routing/Generator/Dumper/CompiledUrlGeneratorDumper.php  Qti  ڤ      ;   vendor/symfony/routing/Generator/Dumper/GeneratorDumper.php#  Qti#  N       *   vendor/symfony/routing/RouteCollection.php+  Qti+        6   vendor/symfony/routing/Requirement/EnumRequirement.php  Qti  xgo      2   vendor/symfony/routing/Requirement/Requirement.phpR  QtiR  1$      7   vendor/symfony/routing/RequestContextAwareInterface.php5  Qti5  }      7   vendor/symfony/routing/Loader/AnnotationClassLoader.php  Qti  e      :   vendor/symfony/routing/Loader/AttributeDirectoryLoader.php  Qti  ]      5   vendor/symfony/routing/Loader/AttributeFileLoader.php(  Qti(  d      0   vendor/symfony/routing/Loader/YamlFileLoader.php/  Qti/  <      6   vendor/symfony/routing/Loader/AnnotationFileLoader.php  Qti  Dgi      <   vendor/symfony/routing/Loader/schema/routing/routing-1.0.xsd9  Qti9  *#      /   vendor/symfony/routing/Loader/PhpFileLoader.php  Qti  .x      5   vendor/symfony/routing/Loader/Psr4DirectoryLoader.php  Qti  l5      /   vendor/symfony/routing/Loader/XmlFileLoader.phpF  QtiF  K5      .   vendor/symfony/routing/Loader/ObjectLoader.phpe  Qtie        ?   vendor/symfony/routing/Loader/Configurator/Traits/HostTrait.php  Qti  t      A   vendor/symfony/routing/Loader/Configurator/Traits/PrefixTrait.php  Qti  A      I   vendor/symfony/routing/Loader/Configurator/Traits/LocalizedRouteTrait.php-
  Qti-
  p֤      @   vendor/symfony/routing/Loader/Configurator/Traits/RouteTrait.php-  Qti-  NX      >   vendor/symfony/routing/Loader/Configurator/Traits/AddTrait.phpP  QtiP  @      @   vendor/symfony/routing/Loader/Configurator/RouteConfigurator.php  Qti  U      E   vendor/symfony/routing/Loader/Configurator/CollectionConfigurator.php  Qti  r      @   vendor/symfony/routing/Loader/Configurator/AliasConfigurator.php  Qti  +(      B   vendor/symfony/routing/Loader/Configurator/RoutingConfigurator.php  Qti  P]      A   vendor/symfony/routing/Loader/Configurator/ImportConfigurator.php  Qti        6   vendor/symfony/routing/Loader/AttributeClassLoader.php>  Qti>  0      1   vendor/symfony/routing/Loader/ContainerLoader.php  Qti        1   vendor/symfony/routing/Loader/DirectoryLoader.php  Qti  U)      0   vendor/symfony/routing/Loader/GlobFileLoader.php  Qti  >Ф      /   vendor/symfony/routing/Loader/ClosureLoader.php  Qti        ;   vendor/symfony/routing/Loader/AnnotationDirectoryLoader.php  Qti  	{          vendor/symfony/routing/Route.phpB/  QtiB/  iv      *   vendor/symfony/routing/RouterInterface.php"  Qti"  WF      !   vendor/symfony/routing/Router.php_/  Qti_/  O      1   vendor/symfony/routing/RouteCompilerInterface.php  Qti  r|v          vendor/symfony/routing/Alias.php	  Qti	  ʤ      Q   vendor/symfony/routing/DependencyInjection/AddExpressionLanguageProvidersPass.php  Qti  _      B   vendor/symfony/routing/DependencyInjection/RoutingResolverPass.php"  Qti"  K˶      >   vendor/symfony/routing/Exception/ResourceNotFoundException.php2  Qti2  FL"1      7   vendor/symfony/routing/Exception/ExceptionInterface.php  Qti  &      ;   vendor/symfony/routing/Exception/RouteNotFoundException.php  Qti  	C      5   vendor/symfony/routing/Exception/RuntimeException.php  Qti  $>G      H   vendor/symfony/routing/Exception/MissingMandatoryParametersException.php?  Qti?  B      =   vendor/symfony/routing/Exception/InvalidArgumentException.php  Qti  ֤      >   vendor/symfony/routing/Exception/MethodNotAllowedException.phpn  Qtin  L#      =   vendor/symfony/routing/Exception/NoConfigurationException.php  Qti  r      D   vendor/symfony/routing/Exception/RouteCircularReferenceException.php=  Qti=  9      >   vendor/symfony/routing/Exception/InvalidParameterException.php  Qti  !N      $   vendor/symfony/routing/composer.jsony  Qtiy  P      ?   vendor/symfony/service-contracts/ServiceSubscriberInterface.php
  Qti
  wW      ?   vendor/symfony/service-contracts/ServiceCollectionInterface.php  Qti  }V      @   vendor/symfony/service-contracts/Attribute/SubscribedService.php  Qti  i      7   vendor/symfony/service-contracts/Attribute/Required.php  Qti  `e      (   vendor/symfony/service-contracts/LICENSE,  Qti,        @   vendor/symfony/service-contracts/Test/ServiceLocatorTestCase.phpM  QtiM  $      <   vendor/symfony/service-contracts/Test/ServiceLocatorTest.php  Qti  H      -   vendor/symfony/service-contracts/CHANGELOG.md   Qti   h{#      *   vendor/symfony/service-contracts/README.mdJ  QtiJ  Г      3   vendor/symfony/service-contracts/ResetInterface.php  Qti  B4      =   vendor/symfony/service-contracts/ServiceProviderInterface.php  Qti        ;   vendor/symfony/service-contracts/ServiceSubscriberTrait.php  Qti  iw      B   vendor/symfony/service-contracts/ServiceMethodsSubscriberTrait.php   Qti   @t      8   vendor/symfony/service-contracts/ServiceLocatorTrait.php7  Qti7  ٖ      .   vendor/symfony/service-contracts/composer.json  Qti  0_      9   vendor/symfony/property-info/PhpStan/NameScopeFactory.php  Qti  @R      2   vendor/symfony/property-info/PhpStan/NameScope.php  Qti        ?   vendor/symfony/property-info/PropertyInfoExtractorInterface.php  Qti  U-R      %   vendor/symfony/property-info/Type.php  Qti  W7쵤      $   vendor/symfony/property-info/LICENSE,  Qti,  H      6   vendor/symfony/property-info/Util/PhpDocTypeHelper.php  Qti  n      7   vendor/symfony/property-info/Util/PhpStanTypeHelper.php#  Qti#  ㋤      )   vendor/symfony/property-info/CHANGELOG.md  Qti  .      ;   vendor/symfony/property-info/PropertyInfoCacheExtractor.php;  Qti;  *Ƥ      D   vendor/symfony/property-info/PropertyWriteInfoExtractorInterface.php  Qti  L:      A   vendor/symfony/property-info/PropertyAccessExtractorInterface.php  Qti  2$C      ?   vendor/symfony/property-info/PropertyTypeExtractorInterface.phpQ  QtiQ        1   vendor/symfony/property-info/PropertyReadInfo.php  Qti  A      ;   vendor/symfony/property-info/Extractor/PhpStanExtractor.php.  Qti.        >   vendor/symfony/property-info/Extractor/SerializerExtractor.php  Qti  Xf      ?   vendor/symfony/property-info/Extractor/ConstructorExtractor.php  Qti        T   vendor/symfony/property-info/Extractor/ConstructorArgumentTypeExtractorInterface.php  Qti  IxX      >   vendor/symfony/property-info/Extractor/ReflectionExtractor.phpH  QtiH  NH      :   vendor/symfony/property-info/Extractor/PhpDocExtractor.php|5  Qti|5  ?ͤ      F   vendor/symfony/property-info/PropertyDescriptionExtractorInterface.php  Qti  }#y      2   vendor/symfony/property-info/PropertyWriteInfo.php  Qti  \ݍ      &   vendor/symfony/property-info/README.md  Qti  '7      C   vendor/symfony/property-info/PropertyReadInfoExtractorInterface.php  Qti  0YF      H   vendor/symfony/property-info/PropertyInitializableExtractorInterface.php  Qti        6   vendor/symfony/property-info/PropertyInfoExtractor.php  Qti  4      ?   vendor/symfony/property-info/PropertyListExtractorInterface.php  Qti  J$      P   vendor/symfony/property-info/DependencyInjection/PropertyInfoConstructorPass.phpX  QtiX         E   vendor/symfony/property-info/DependencyInjection/PropertyInfoPass.php)  Qti)         *   vendor/symfony/property-info/composer.json!  Qti!  2@eo      3   vendor/symfony/http-foundation/StreamedResponse.php  Qti  %      :   vendor/symfony/http-foundation/RequestMatcherInterface.php{  Qti{  N{      5   vendor/symfony/http-foundation/BinaryFileResponse.phpd2  Qtid2  vǤ      +   vendor/symfony/http-foundation/InputBag.php*  Qti*  tD      I   vendor/symfony/http-foundation/RateLimiter/AbstractRequestRateLimiter.php	  Qti	  j      J   vendor/symfony/http-foundation/RateLimiter/RequestRateLimiterInterface.php  Qti  %k      R   vendor/symfony/http-foundation/RateLimiter/PeekableRequestRateLimiterInterface.php  Qti  %f
ݤ      &   vendor/symfony/http-foundation/LICENSE,  Qti,  U      J   vendor/symfony/http-foundation/Test/Constraint/ResponseCookieValueSame.phpF  QtiF  m{      D   vendor/symfony/http-foundation/Test/Constraint/ResponseHasCookie.phpD  QtiD  B9r      M   vendor/symfony/http-foundation/Test/Constraint/ResponseHeaderLocationSame.php  Qti  AS      I   vendor/symfony/http-foundation/Test/Constraint/ResponseStatusCodeSame.php  Qti   YaƤ      G   vendor/symfony/http-foundation/Test/Constraint/ResponseIsSuccessful.php*  Qti*  Xy      J   vendor/symfony/http-foundation/Test/Constraint/ResponseIsUnprocessable.phpA  QtiA  r{      G   vendor/symfony/http-foundation/Test/Constraint/ResponseIsRedirected.php(  Qti(  1w      D   vendor/symfony/http-foundation/Test/Constraint/ResponseHasHeader.php9  Qti9  n      L   vendor/symfony/http-foundation/Test/Constraint/RequestAttributeValueSame.php  Qti  ቭѤ      E   vendor/symfony/http-foundation/Test/Constraint/ResponseFormatSame.php  Qti  q      E   vendor/symfony/http-foundation/Test/Constraint/ResponseHeaderSame.php  Qti  d       ,   vendor/symfony/http-foundation/ServerBag.php  Qti  T      +   vendor/symfony/http-foundation/CHANGELOG.mduL  QtiuL  M      ,   vendor/symfony/http-foundation/File/File.php  Qti        .   vendor/symfony/http-foundation/File/Stream.php  Qti  WC      4   vendor/symfony/http-foundation/File/UploadedFile.phpX(  QtiX(  48L      G   vendor/symfony/http-foundation/File/Exception/AccessDeniedException.phpi  Qtii  Y      A   vendor/symfony/http-foundation/File/Exception/NoFileException.php  Qti  -A      F   vendor/symfony/http-foundation/File/Exception/IniSizeFileException.php  Qti  I      J   vendor/symfony/http-foundation/File/Exception/CannotWriteFileException.php  Qti  :ݤ      H   vendor/symfony/http-foundation/File/Exception/ExtensionFileException.php  Qti  )      ?   vendor/symfony/http-foundation/File/Exception/FileException.php  Qti  j2      A   vendor/symfony/http-foundation/File/Exception/UploadException.php  Qti  S      I   vendor/symfony/http-foundation/File/Exception/UnexpectedTypeException.php8  Qti8        G   vendor/symfony/http-foundation/File/Exception/FormSizeFileException.php  Qti  m;      G   vendor/symfony/http-foundation/File/Exception/FileNotFoundException.phpY  QtiY  {WɈ      F   vendor/symfony/http-foundation/File/Exception/PartialFileException.php  Qti  *      G   vendor/symfony/http-foundation/File/Exception/NoTmpDirFileException.php  Qti  n      +   vendor/symfony/http-foundation/Response.phpʚ  Qtiʚ  pq      )   vendor/symfony/http-foundation/Cookie.php/  Qti/  m      /   vendor/symfony/http-foundation/AcceptHeader.php"  Qti"  $>      1   vendor/symfony/http-foundation/RequestMatcher.php  Qti  ʽ      4   vendor/symfony/http-foundation/ResponseHeaderBag.php  Qti  .]ؤ      .   vendor/symfony/http-foundation/HeaderUtils.phpR$  QtiR$  F      F   vendor/symfony/http-foundation/RequestMatcher/MethodRequestMatcher.php7  Qti7  m+=      D   vendor/symfony/http-foundation/RequestMatcher/PathRequestMatcher.phpa  Qtia  ԇ      F   vendor/symfony/http-foundation/RequestMatcher/IsJsonRequestMatcher.php  Qti  @¤      D   vendor/symfony/http-foundation/RequestMatcher/PortRequestMatcher.php  Qti  X      D   vendor/symfony/http-foundation/RequestMatcher/HostRequestMatcher.phpP  QtiP         J   vendor/symfony/http-foundation/RequestMatcher/AttributesRequestMatcher.php  Qti  u_      J   vendor/symfony/http-foundation/RequestMatcher/ExpressionRequestMatcher.php  Qti  ,&      F   vendor/symfony/http-foundation/RequestMatcher/SchemeRequestMatcher.php%  Qti%  ߩ4      C   vendor/symfony/http-foundation/RequestMatcher/IpsRequestMatcher.php,  Qti,         /   vendor/symfony/http-foundation/RequestStack.php  Qti  s      3   vendor/symfony/http-foundation/RedirectResponse.php5
  Qti5
  v      /   vendor/symfony/http-foundation/JsonResponse.phpN  QtiN  ~      (   vendor/symfony/http-foundation/README.md  Qti  &      *   vendor/symfony/http-foundation/Request.php9 Qti9 1v|^      ;   vendor/symfony/http-foundation/ExpressionRequestMatcher.php  Qti  J      /   vendor/symfony/http-foundation/ParameterBag.php  Qti  R'Z      *   vendor/symfony/http-foundation/IpUtils.php  Qti  L"      3   vendor/symfony/http-foundation/AcceptHeaderItem.php  Qti  J1      7   vendor/symfony/http-foundation/StreamedJsonResponse.phpw  Qtiw  PKV      ,   vendor/symfony/http-foundation/UrlHelper.php]  Qti]  B      6   vendor/symfony/http-foundation/ChainRequestMatcher.phpw  Qtiw  $      ,   vendor/symfony/http-foundation/HeaderBag.phpG  QtiG  6      *   vendor/symfony/http-foundation/FileBag.php  Qti        H   vendor/symfony/http-foundation/Exception/ConflictingHeadersException.php  Qti  ,Ň      E   vendor/symfony/http-foundation/Exception/UnexpectedValueException.phpx  Qtix   ȕ      F   vendor/symfony/http-foundation/Exception/RequestExceptionInterface.php  Qti  R      @   vendor/symfony/http-foundation/Exception/BadRequestException.php  Qti  Uڤ      I   vendor/symfony/http-foundation/Exception/SuspiciousOperationException.php  Qti  '      :   vendor/symfony/http-foundation/Exception/JsonException.php  Qti        E   vendor/symfony/http-foundation/Exception/SessionNotFoundException.phpY  QtiY  1      ,   vendor/symfony/http-foundation/composer.jsonv  Qtiv  ^D      ,   vendor/symfony/http-foundation/UriSigner.php/  Qti/  ;9k      J   vendor/symfony/http-foundation/Session/Attribute/AttributeBagInterface.php  Qti  b      A   vendor/symfony/http-foundation/Session/Attribute/AttributeBag.php
  Qti
  %ꛤ      H   vendor/symfony/http-foundation/Session/FlashBagAwareSessionInterface.php3  Qti3  q      B   vendor/symfony/http-foundation/Session/SessionFactoryInterface.php  Qti  2F      2   vendor/symfony/http-foundation/Session/Session.php  Qti  }!      7   vendor/symfony/http-foundation/Session/SessionUtils.php  Qti  )      M   vendor/symfony/http-foundation/Session/Storage/Handler/NullSessionHandler.phpp  Qtip  
$      Q   vendor/symfony/http-foundation/Session/Storage/Handler/AbstractSessionHandler.php?  Qti?  k      P   vendor/symfony/http-foundation/Session/Storage/Handler/SessionHandlerFactory.phpZ  QtiZ  $      L   vendor/symfony/http-foundation/Session/Storage/Handler/PdoSessionHandler.php  Qti  M}      T   vendor/symfony/http-foundation/Session/Storage/Handler/MarshallingSessionHandler.php  Qti  pqa      S   vendor/symfony/http-foundation/Session/Storage/Handler/NativeFileSessionHandler.php  Qti  =J      R   vendor/symfony/http-foundation/Session/Storage/Handler/MigratingSessionHandler.phpn  Qtin  I^      M   vendor/symfony/http-foundation/Session/Storage/Handler/IdentityMarshaller.php  Qti  [ޤ      P   vendor/symfony/http-foundation/Session/Storage/Handler/MongoDbSessionHandler.php  Qti  A      N   vendor/symfony/http-foundation/Session/Storage/Handler/RedisSessionHandler.php5  Qti5  *      O   vendor/symfony/http-foundation/Session/Storage/Handler/StrictSessionHandler.phph
  Qtih
  z      R   vendor/symfony/http-foundation/Session/Storage/Handler/MemcachedSessionHandler.phpD  QtiD  8      G   vendor/symfony/http-foundation/Session/Storage/NativeSessionStorage.php7  Qti7  }+ä      J   vendor/symfony/http-foundation/Session/Storage/SessionStorageInterface.php(  Qti(  ɤ      P   vendor/symfony/http-foundation/Session/Storage/MockFileSessionStorageFactory.php  Qti  浢      L   vendor/symfony/http-foundation/Session/Storage/Proxy/SessionHandlerProxy.php	  Qti	   2      F   vendor/symfony/http-foundation/Session/Storage/Proxy/AbstractProxy.php  Qti  <[c      N   vendor/symfony/http-foundation/Session/Storage/NativeSessionStorageFactory.php  Qti  j7s      J   vendor/symfony/http-foundation/Session/Storage/PhpBridgeSessionStorage.php  Qti  `|      Q   vendor/symfony/http-foundation/Session/Storage/SessionStorageFactoryInterface.phpv  Qtiv  JUP      I   vendor/symfony/http-foundation/Session/Storage/MockFileSessionStorage.php  Qti  "k      Q   vendor/symfony/http-foundation/Session/Storage/PhpBridgeSessionStorageFactory.php  Qti  ֤      >   vendor/symfony/http-foundation/Session/Storage/MetadataBag.php  Qti  /G      J   vendor/symfony/http-foundation/Session/Storage/MockArraySessionStorage.php  Qti  ~
ˤ      ;   vendor/symfony/http-foundation/Session/SessionInterface.php  Qti  LN      C   vendor/symfony/http-foundation/Session/Flash/AutoExpireFlashBag.php  Qti  )TҤ      B   vendor/symfony/http-foundation/Session/Flash/FlashBagInterface.php  Qti  ;      9   vendor/symfony/http-foundation/Session/Flash/FlashBag.php	  Qti	  c4ɤ      9   vendor/symfony/http-foundation/Session/SessionFactory.phpE  QtiE  eg      :   vendor/symfony/http-foundation/Session/SessionBagProxy.php  Qti  #ڤ      >   vendor/symfony/http-foundation/Session/SessionBagInterface.phpT  QtiT  c      ,   vendor/symfony/var-exporter/Instantiator.php	  Qti	  4g4A      +   vendor/symfony/var-exporter/ProxyHelper.php^  Qti^         #   vendor/symfony/var-exporter/LICENSE,  Qti,        (   vendor/symfony/var-exporter/CHANGELOG.md  Qti  t?      (   vendor/symfony/var-exporter/Hydrator.php  Qti  d{      8   vendor/symfony/var-exporter/Internal/LazyObjectState.php  Qti  B      ;   vendor/symfony/var-exporter/Internal/LazyObjectRegistry.phpJ  QtiJ  j&%      /   vendor/symfony/var-exporter/Internal/Values.php  Qti  `ǿ      8   vendor/symfony/var-exporter/Internal/LazyObjectTrait.php  Qti  T      1   vendor/symfony/var-exporter/Internal/Hydrator.php/  Qti/   @      1   vendor/symfony/var-exporter/Internal/Registry.php3  Qti3  ۤ      2   vendor/symfony/var-exporter/Internal/Reference.php
  Qti
  #Jn      1   vendor/symfony/var-exporter/Internal/Exporter.php=A  Qti=A   H}      .   vendor/symfony/var-exporter/LazyGhostTrait.phpl;  Qtil;  Dؤ      %   vendor/symfony/var-exporter/README.md-  Qti-  "      .   vendor/symfony/var-exporter/LazyProxyTrait.php1  Qti1  |      +   vendor/symfony/var-exporter/VarExporter.phpO  QtiO        3   vendor/symfony/var-exporter/LazyObjectInterface.php^  Qti^  Md      8   vendor/symfony/var-exporter/Exception/LogicException.php  Qti  -ʤ      <   vendor/symfony/var-exporter/Exception/ExceptionInterface.phpd  Qtid        @   vendor/symfony/var-exporter/Exception/ClassNotFoundException.php1  Qti1  w w      F   vendor/symfony/var-exporter/Exception/NotInstantiableTypeException.php>  Qti>  }      )   vendor/symfony/var-exporter/composer.jsonr  Qtir  ~j      E   vendor/symfony/error-handler/ErrorEnhancer/ErrorEnhancerInterface.php  Qti  tM!      I   vendor/symfony/error-handler/ErrorEnhancer/ClassNotFoundErrorEnhancer.php-  Qti-  :B      M   vendor/symfony/error-handler/ErrorEnhancer/UndefinedFunctionErrorEnhancer.php  Qti  3a      K   vendor/symfony/error-handler/ErrorEnhancer/UndefinedMethodErrorEnhancer.php  Qti  #      $   vendor/symfony/error-handler/LICENSE,  Qti,  զ_Ϥ      )   vendor/symfony/error-handler/CHANGELOG.md  Qti  D9      B   vendor/symfony/error-handler/Resources/bin/patch-type-declarations  Qti  x0      M   vendor/symfony/error-handler/Resources/bin/extract-tentative-return-types.php  Qti  Ӥ      ?   vendor/symfony/error-handler/Resources/views/exception.html.php/  Qti/        <   vendor/symfony/error-handler/Resources/views/traces.html.php
  Qti
  n       A   vendor/symfony/error-handler/Resources/views/traces_text.html.php  Qti  j+2      :   vendor/symfony/error-handler/Resources/views/logs.html.php)	  Qti)	  _&      ;   vendor/symfony/error-handler/Resources/views/trace.html.php`  Qti`  39      ;   vendor/symfony/error-handler/Resources/views/error.html.phpd  Qtid  x      D   vendor/symfony/error-handler/Resources/views/exception_full.html.php  Qti  Eޤ      ?   vendor/symfony/error-handler/Resources/assets/css/exception.css	B  Qti	B  R      D   vendor/symfony/error-handler/Resources/assets/css/exception_full.css
  Qti
  *bc      ;   vendor/symfony/error-handler/Resources/assets/css/error.css  Qti  %7      J   vendor/symfony/error-handler/Resources/assets/images/icon-minus-square.svgQ  QtiQ  p      B   vendor/symfony/error-handler/Resources/assets/images/icon-book.svg  Qti        E   vendor/symfony/error-handler/Resources/assets/images/icon-support.svgz  Qtiz  S̤      F   vendor/symfony/error-handler/Resources/assets/images/chevron-right.svg  Qti        J   vendor/symfony/error-handler/Resources/assets/images/symfony-ghost.svg.php   Qti   9꒤      I   vendor/symfony/error-handler/Resources/assets/images/icon-plus-square.svg  Qti  U      E   vendor/symfony/error-handler/Resources/assets/images/symfony-logo.svg  Qti  %0ɤ      B   vendor/symfony/error-handler/Resources/assets/images/icon-copy.svg	  Qti	  "Ȗ      G   vendor/symfony/error-handler/Resources/assets/images/favicon.png.base64  Qti  "i^      K   vendor/symfony/error-handler/Resources/assets/images/icon-plus-square-o.svg  Qti  -      L   vendor/symfony/error-handler/Resources/assets/images/icon-minus-square-o.svg  Qti  s0      =   vendor/symfony/error-handler/Resources/assets/js/exception.js4  Qti4  C#      8   vendor/symfony/error-handler/Internal/TentativeTypes.php  Qti        &   vendor/symfony/error-handler/Debug.phpk  Qtik  H6
      F   vendor/symfony/error-handler/ErrorRenderer/SerializerErrorRenderer.php  Qti  O      ?   vendor/symfony/error-handler/ErrorRenderer/CliErrorRenderer.php  Qti  1x      E   vendor/symfony/error-handler/ErrorRenderer/ErrorRendererInterface.php  Qti  R+      @   vendor/symfony/error-handler/ErrorRenderer/HtmlErrorRenderer.php]  Qti]        @   vendor/symfony/error-handler/ErrorRenderer/FileLinkFormatter.php9  Qti9  qJ      &   vendor/symfony/error-handler/README.md=  Qti=  \      1   vendor/symfony/error-handler/DebugClassLoader.phpf  Qtif  0)      0   vendor/symfony/error-handler/BufferingLogger.php,  Qti,  R      -   vendor/symfony/error-handler/ErrorHandler.php%k  Qti%k  2      /   vendor/symfony/error-handler/ThrowableUtils.phpz  Qtiz  ɻ      7   vendor/symfony/error-handler/Error/OutOfMemoryError.php[  Qti[  N      ;   vendor/symfony/error-handler/Error/UndefinedMethodError.php  Qti  V[      1   vendor/symfony/error-handler/Error/FatalError.php
  Qti
  aǤ      =   vendor/symfony/error-handler/Error/UndefinedFunctionError.php  Qti  lnB      9   vendor/symfony/error-handler/Error/ClassNotFoundError.php  Qti  Ep      ;   vendor/symfony/error-handler/Exception/FlattenException.php.  Qti.  :A      ?   vendor/symfony/error-handler/Exception/SilencedErrorContext.phpm  Qtim  IS      *   vendor/symfony/error-handler/composer.json  Qti  ny&      4   vendor/symfony/cache-contracts/CallbackInterface.php\  Qti\  v      0   vendor/symfony/cache-contracts/ItemInterface.php3  Qti3  Gz      &   vendor/symfony/cache-contracts/LICENSE,  Qti,        +   vendor/symfony/cache-contracts/CHANGELOG.md   Qti   h{#      1   vendor/symfony/cache-contracts/CacheInterface.php0	  Qti0	  _wZ      :   vendor/symfony/cache-contracts/NamespacedPoolInterface.php  Qti  ёe      (   vendor/symfony/cache-contracts/README.mdF  QtiF  _      -   vendor/symfony/cache-contracts/CacheTrait.php	  Qti	  R      9   vendor/symfony/cache-contracts/TagAwareCacheInterface.php  Qti  m,      ,   vendor/symfony/cache-contracts/composer.json  Qti  /      7   vendor/symfony/dependency-injection/EnvVarProcessor.php2  Qti2  |
      ;   vendor/symfony/dependency-injection/ContainerAwareTrait.phpM  QtiM  7      B   vendor/symfony/dependency-injection/ExpressionLanguageProvider.php[  Qti[        1   vendor/symfony/dependency-injection/Container.php6  Qti6  |4-      8   vendor/symfony/dependency-injection/ReverseContainer.php	  Qti	  q      0   vendor/symfony/dependency-injection/Variable.php  Qti  o      P   vendor/symfony/dependency-injection/Extension/ConfigurableExtensionInterface.php!  Qti!  ٤      D   vendor/symfony/dependency-injection/Extension/ExtensionInterface.php`  Qti`  ^N      C   vendor/symfony/dependency-injection/Extension/AbstractExtension.php  Qti  %Eq      @   vendor/symfony/dependency-injection/Extension/ExtensionTrait.php  Qti  G      ;   vendor/symfony/dependency-injection/Extension/Extension.php  Qti  ̤      K   vendor/symfony/dependency-injection/Extension/PrependExtensionInterface.phpS  QtiS  NC6      Q   vendor/symfony/dependency-injection/Extension/ConfigurationExtensionInterface.phpS  QtiS  )      ?   vendor/symfony/dependency-injection/Attribute/Autoconfigure.php  Qti  ZӤ      B   vendor/symfony/dependency-injection/Attribute/AutowireIterator.php  Qti  o      =   vendor/symfony/dependency-injection/Attribute/AsDecorator.phpo  Qtio  Y|      H   vendor/symfony/dependency-injection/Attribute/AutowireServiceClosure.php  Qti  ^#5      >   vendor/symfony/dependency-injection/Attribute/AsTaggedItem.php  Qti  k      8   vendor/symfony/dependency-injection/Attribute/Target.php
	  Qti
	  -      6   vendor/symfony/dependency-injection/Attribute/When.php  Qti  Xˤ      C   vendor/symfony/dependency-injection/Attribute/AutowireDecorated.php  Qti  bl      @   vendor/symfony/dependency-injection/Attribute/TaggedIterator.php  Qti  u      A   vendor/symfony/dependency-injection/Attribute/AutowireLocator.php\  Qti\        B   vendor/symfony/dependency-injection/Attribute/AutowireCallable.phpR  QtiR  chA      :   vendor/symfony/dependency-injection/Attribute/Autowire.phpy  Qtiy  `      B   vendor/symfony/dependency-injection/Attribute/AutoconfigureTag.php  Qti  	       ?   vendor/symfony/dependency-injection/Attribute/TaggedLocator.php  Qti  鱞      >   vendor/symfony/dependency-injection/Attribute/MapDecorated.phpa  Qtia  ~4      9   vendor/symfony/dependency-injection/Attribute/Exclude.php  Qti  a)      9   vendor/symfony/dependency-injection/Attribute/AsAlias.php  Qti        +   vendor/symfony/dependency-injection/LICENSE,  Qti,  U      0   vendor/symfony/dependency-injection/CHANGELOG.mdhI  QtihI  Z[      Q   vendor/symfony/dependency-injection/Config/ContainerParametersResourceChecker.php'  Qti'  ̤      J   vendor/symfony/dependency-injection/Config/ContainerParametersResource.php  Qti  I8      J   vendor/symfony/dependency-injection/Argument/ReferenceSetArgumentTrait.php  Qti  X      A   vendor/symfony/dependency-injection/Argument/AbstractArgument.php  Qti  _      D   vendor/symfony/dependency-injection/Argument/RewindableGenerator.php  Qti  ŭ      G   vendor/symfony/dependency-injection/Argument/ServiceLocatorArgument.php  Qti  Uu      >   vendor/symfony/dependency-injection/Argument/BoundArgument.php  Qti  w.      A   vendor/symfony/dependency-injection/Argument/IteratorArgument.php5  Qti5  cC      <   vendor/symfony/dependency-injection/Argument/LazyClosure.php9  Qti9  ڶ      G   vendor/symfony/dependency-injection/Argument/TaggedIteratorArgument.phpd  Qtid  QW      B   vendor/symfony/dependency-injection/Argument/ArgumentInterface.phpM  QtiM   "      ?   vendor/symfony/dependency-injection/Argument/ServiceLocator.php   Qti   U      G   vendor/symfony/dependency-injection/Argument/ServiceClosureArgument.php(  Qti(  SL      8   vendor/symfony/dependency-injection/ContainerBuilder.php@  Qti@  ;k[      7   vendor/symfony/dependency-injection/ChildDefinition.phpk
  Qtik
        1   vendor/symfony/dependency-injection/Reference.php  Qti  F%      J   vendor/symfony/dependency-injection/ParameterBag/ParameterBagInterface.php	  Qti	  eݤ      O   vendor/symfony/dependency-injection/ParameterBag/EnvPlaceholderParameterBag.php  Qti  Df      A   vendor/symfony/dependency-injection/ParameterBag/ParameterBag.php$  Qti$  Ѥ      J   vendor/symfony/dependency-injection/ParameterBag/ContainerBagInterface.php  Qti  $1M      A   vendor/symfony/dependency-injection/ParameterBag/ContainerBag.php  Qti  z~      G   vendor/symfony/dependency-injection/ParameterBag/FrozenParameterBag.php  Qti  0P      2   vendor/symfony/dependency-injection/Definition.php4P  Qti4P        @   vendor/symfony/dependency-injection/EnvVarProcessorInterface.php  Qti  ?      -   vendor/symfony/dependency-injection/README.mdC  QtiC  <      :   vendor/symfony/dependency-injection/ContainerInterface.php`	  Qti`	  |      9   vendor/symfony/dependency-injection/Loader/FileLoader.php;  Qti;  ^      =   vendor/symfony/dependency-injection/Loader/YamlFileLoader.php'  Qti'  ,+ڤ      O   vendor/symfony/dependency-injection/Loader/schema/dic/services/services-1.0.xsdB  QtiB  o      <   vendor/symfony/dependency-injection/Loader/PhpFileLoader.php!  Qti!  m      <   vendor/symfony/dependency-injection/Loader/XmlFileLoader.php?  Qti?  Ĥ      <   vendor/symfony/dependency-injection/Loader/IniFileLoader.php  Qti        P   vendor/symfony/dependency-injection/Loader/Configurator/ServicesConfigurator.php%  Qti%  ?      P   vendor/symfony/dependency-injection/Loader/Configurator/DefaultsConfigurator.php5	  Qti5	  %      Q   vendor/symfony/dependency-injection/Loader/Configurator/ReferenceConfigurator.php  Qti  &d      T   vendor/symfony/dependency-injection/Loader/Configurator/FromCallableConfigurator.php  Qti  6n      M   vendor/symfony/dependency-injection/Loader/Configurator/Traits/ClassTrait.php0  Qti0  ":פ      L   vendor/symfony/dependency-injection/Loader/Configurator/Traits/CallTrait.phpM  QtiM  ɍ      Q   vendor/symfony/dependency-injection/Loader/Configurator/Traits/SyntheticTrait.php  Qti  Vjפ      P   vendor/symfony/dependency-injection/Loader/Configurator/Traits/PropertyTrait.phpk  Qtik  j|h      P   vendor/symfony/dependency-injection/Loader/Configurator/Traits/ArgumentTrait.php  Qti  #      T   vendor/symfony/dependency-injection/Loader/Configurator/Traits/ConfiguratorTrait.php  Qti  Q      N   vendor/symfony/dependency-injection/Loader/Configurator/Traits/ParentTrait.php  Qti  $e      O   vendor/symfony/dependency-injection/Loader/Configurator/Traits/FactoryTrait.phpa  Qtia  QA      K   vendor/symfony/dependency-injection/Loader/Configurator/Traits/TagTrait.php  Qti        N   vendor/symfony/dependency-injection/Loader/Configurator/Traits/PublicTrait.php  Qti  i      P   vendor/symfony/dependency-injection/Loader/Configurator/Traits/DecorateTrait.phpz  Qtiz  vxm      U   vendor/symfony/dependency-injection/Loader/Configurator/Traits/AutoconfigureTrait.phpD  QtiD  Eߤ      T   vendor/symfony/dependency-injection/Loader/Configurator/Traits/FromCallableTrait.php	  Qti	  s<      Q   vendor/symfony/dependency-injection/Loader/Configurator/Traits/DeprecateTrait.phpa  Qtia  ă      L   vendor/symfony/dependency-injection/Loader/Configurator/Traits/BindTrait.phpZ  QtiZ  /R      L   vendor/symfony/dependency-injection/Loader/Configurator/Traits/LazyTrait.phpC  QtiC  #(      L   vendor/symfony/dependency-injection/Loader/Configurator/Traits/FileTrait.phpF  QtiF  yG      P   vendor/symfony/dependency-injection/Loader/Configurator/Traits/AbstractTrait.php  Qti  Hrdb      M   vendor/symfony/dependency-injection/Loader/Configurator/Traits/ShareTrait.phpK  QtiK        P   vendor/symfony/dependency-injection/Loader/Configurator/Traits/AutowireTrait.phpL  QtiL  =Lv!      S   vendor/symfony/dependency-injection/Loader/Configurator/Traits/ConstructorTrait.phpT  QtiT  ˌ      P   vendor/symfony/dependency-injection/Loader/Configurator/AbstractConfigurator.php  Qti  6 U      X   vendor/symfony/dependency-injection/Loader/Configurator/ClosureReferenceConfigurator.php  Qti  #y      K   vendor/symfony/dependency-injection/Loader/Configurator/EnvConfigurator.php-  Qti-  i(      W   vendor/symfony/dependency-injection/Loader/Configurator/AbstractServiceConfigurator.php  Qti  C      R   vendor/symfony/dependency-injection/Loader/Configurator/InstanceofConfigurator.php  Qti  ӊ      Q   vendor/symfony/dependency-injection/Loader/Configurator/ContainerConfigurator.php  Qti  ǐ+      M   vendor/symfony/dependency-injection/Loader/Configurator/AliasConfigurator.php  Qti  RF,b      U   vendor/symfony/dependency-injection/Loader/Configurator/InlineServiceConfigurator.phpR  QtiR  <      Q   vendor/symfony/dependency-injection/Loader/Configurator/PrototypeConfigurator.php
  Qti
  V>/      R   vendor/symfony/dependency-injection/Loader/Configurator/ParametersConfigurator.php  Qti  mnCE      O   vendor/symfony/dependency-injection/Loader/Configurator/ServiceConfigurator.php  Qti  A[_v      >   vendor/symfony/dependency-injection/Loader/DirectoryLoader.php,  Qti,        =   vendor/symfony/dependency-injection/Loader/GlobFileLoader.php^  Qti^  p4      <   vendor/symfony/dependency-injection/Loader/ClosureLoader.php  Qti  .dP      =   vendor/symfony/dependency-injection/LazyProxy/ProxyHelper.php  Qti  &ߤ      K   vendor/symfony/dependency-injection/LazyProxy/PhpDumper/DumperInterface.php  Qti  B˒=      M   vendor/symfony/dependency-injection/LazyProxy/PhpDumper/LazyServiceDumper.php  Qti  	tI      F   vendor/symfony/dependency-injection/LazyProxy/PhpDumper/NullDumper.php  Qti  E      V   vendor/symfony/dependency-injection/LazyProxy/Instantiator/LazyServiceInstantiator.php  Qti  ߤ      V   vendor/symfony/dependency-injection/LazyProxy/Instantiator/RealServiceInstantiator.phpc  Qtic  ;Գ      T   vendor/symfony/dependency-injection/LazyProxy/Instantiator/InstantiatorInterface.php~  Qti~  0ND      :   vendor/symfony/dependency-injection/ExpressionLanguage.php`  Qti`        6   vendor/symfony/dependency-injection/ServiceLocator.php  Qti  5k      6   vendor/symfony/dependency-injection/TypedReference.php1  Qti1  д      -   vendor/symfony/dependency-injection/Alias.phpz  Qtiz  jY       U   vendor/symfony/dependency-injection/Exception/ParameterCircularReferenceException.php  Qti  >di      @   vendor/symfony/dependency-injection/Exception/LogicException.php  Qti  }|Ȥ      F   vendor/symfony/dependency-injection/Exception/EnvNotFoundException.php  Qti  &      L   vendor/symfony/dependency-injection/Exception/ParameterNotFoundException.php!  Qti!  XbΤ      D   vendor/symfony/dependency-injection/Exception/ExceptionInterface.php~  Qti~        F   vendor/symfony/dependency-injection/Exception/OutOfBoundsException.php  Qti  On      S   vendor/symfony/dependency-injection/Exception/ServiceCircularReferenceException.php^  Qti^  u      J   vendor/symfony/dependency-injection/Exception/ServiceNotFoundException.php  Qti  ̅      B   vendor/symfony/dependency-injection/Exception/RuntimeException.php	  Qti	  
      J   vendor/symfony/dependency-injection/Exception/InvalidArgumentException.php'  Qti'        H   vendor/symfony/dependency-injection/Exception/BadMethodCallException.php  Qti  ,w      K   vendor/symfony/dependency-injection/Exception/AutowiringFailedException.php  Qti  j0      O   vendor/symfony/dependency-injection/Exception/InvalidParameterTypeException.php0  Qti0  I      G   vendor/symfony/dependency-injection/Exception/EnvParameterException.php  Qti  b¡I      @   vendor/symfony/dependency-injection/TaggedContainerInterface.php  Qti  X.p      1   vendor/symfony/dependency-injection/Parameter.phpe  Qtie  u A      E   vendor/symfony/dependency-injection/Compiler/DecoratorServicePass.php  Qti  oۤ      M   vendor/symfony/dependency-injection/Compiler/ResolveInvalidReferencesPass.php  Qti  r		      L   vendor/symfony/dependency-injection/Compiler/ValidateEnvPlaceholdersPass.php  Qti  v/      M   vendor/symfony/dependency-injection/Compiler/RegisterEnvVarProcessorsPass.php;  Qti;  -¤      T   vendor/symfony/dependency-injection/Compiler/RegisterAutoconfigureAttributesPass.php  Qti  7cI      L   vendor/symfony/dependency-injection/Compiler/CheckDefinitionValidityPass.phpm  Qtim  r?%      ;   vendor/symfony/dependency-injection/Compiler/PassConfig.php  Qti  G      F   vendor/symfony/dependency-injection/Compiler/ServiceReferenceGraph.php
  Qti
  :      E   vendor/symfony/dependency-injection/Compiler/ResolveNoPreloadPass.phpJ  QtiJ  t䠤      J   vendor/symfony/dependency-injection/Compiler/ServiceReferenceGraphNode.php  Qti  Tq      J   vendor/symfony/dependency-injection/Compiler/CheckTypeDeclarationsPass.php1  Qti1  s﷤      M   vendor/symfony/dependency-injection/Compiler/InlineServiceDefinitionsPass.php  Qti        H   vendor/symfony/dependency-injection/Compiler/ResolveFactoryClassPass.php  Qti  7      D   vendor/symfony/dependency-injection/Compiler/ResolveBindingsPass.php8*  Qti8*  ø      H   vendor/symfony/dependency-injection/Compiler/AutowireAsDecoratorPass.php  Qti  !u      K   vendor/symfony/dependency-injection/Compiler/PriorityTaggedServiceTrait.php   Qti   A      M   vendor/symfony/dependency-injection/Compiler/RegisterReverseContainerPass.php  Qti  QY      F   vendor/symfony/dependency-injection/Compiler/AbstractRecursivePass.php *  Qti *  rαФ      R   vendor/symfony/dependency-injection/Compiler/AliasDeprecatedPublicServicesPass.php  Qti  ,i      R   vendor/symfony/dependency-injection/Compiler/ResolveInstanceofConditionalsPass.php+  Qti+        O   vendor/symfony/dependency-injection/Compiler/ResolveReferencesToAliasesPass.php  Qti  aj/      K   vendor/symfony/dependency-injection/Compiler/CheckArgumentsValidityPass.php(  Qti(  t      O   vendor/symfony/dependency-injection/Compiler/AttributeAutoconfigurationPass.php  Qti  	      O   vendor/symfony/dependency-injection/Compiler/AutowireRequiredPropertiesPass.php  Qti  @      J   vendor/symfony/dependency-injection/Compiler/ResolveNamedArgumentsPass.php  Qti  'i      I   vendor/symfony/dependency-injection/Compiler/RemovePrivateAliasesPass.php  Qti  XB      P   vendor/symfony/dependency-injection/Compiler/MergeExtensionConfigurationPass.php!  Qti!  rN      J   vendor/symfony/dependency-injection/Compiler/ServiceReferenceGraphEdge.phpN	  QtiN	  Fh      M   vendor/symfony/dependency-injection/Compiler/DefinitionErrorExceptionPass.php  Qti  =      L   vendor/symfony/dependency-injection/Compiler/RemoveUnusedDefinitionsPass.php  Qti  `g}      =   vendor/symfony/dependency-injection/Compiler/AutowirePass.phpz  Qtiz  롤      F   vendor/symfony/dependency-injection/Compiler/ServiceLocatorTagPass.php  Qti  ;      R   vendor/symfony/dependency-injection/Compiler/ResolveTaggedIteratorArgumentPass.phpp  Qtip  *      K   vendor/symfony/dependency-injection/Compiler/ResolveEnvPlaceholdersPass.php  Qti  {r      L   vendor/symfony/dependency-injection/Compiler/CheckCircularReferencesPass.php  Qti  X      ]   vendor/symfony/dependency-injection/Compiler/CheckExceptionOnInvalidReferenceBehaviorPass.php  Qti        J   vendor/symfony/dependency-injection/Compiler/RemoveBuildParametersPass.phpM  QtiM  +ä      E   vendor/symfony/dependency-injection/Compiler/AutoAliasServicePass.php  Qti  zp
      Q   vendor/symfony/dependency-injection/Compiler/ResolveParameterPlaceHoldersPass.php  Qti  ނ      A   vendor/symfony/dependency-injection/Compiler/ResolveClassPass.phpB  QtiB        N   vendor/symfony/dependency-injection/Compiler/RemoveAbstractDefinitionsPass.php  Qti  lC      K   vendor/symfony/dependency-injection/Compiler/CheckReferenceValidityPass.php5  Qti5  걄X      O   vendor/symfony/dependency-injection/Compiler/RegisterServiceSubscribersPass.phpq  Qtiq  j      C   vendor/symfony/dependency-injection/Compiler/ResolveHotPathPass.phpA	  QtiA	  Z`      J   vendor/symfony/dependency-injection/Compiler/ResolveDecoratorStackPass.php  Qti  BŤ      N   vendor/symfony/dependency-injection/Compiler/ResolveServiceSubscribersPass.php  Qti  Lͤ      F   vendor/symfony/dependency-injection/Compiler/CompilerPassInterface.php  Qti  &      S   vendor/symfony/dependency-injection/Compiler/ReplaceAliasByActualDefinitionPass.phpg  Qtig        L   vendor/symfony/dependency-injection/Compiler/ResolveChildDefinitionsPass.php  Qti  G      9   vendor/symfony/dependency-injection/Compiler/Compiler.php
  Qti
  ؕK      F   vendor/symfony/dependency-injection/Compiler/ExtensionCompilerPass.php  Qti        M   vendor/symfony/dependency-injection/Compiler/AnalyzeServiceReferencesPass.php  Qti  e      L   vendor/symfony/dependency-injection/Compiler/AutowireRequiredMethodsPass.phpl  Qtil  qg(      =   vendor/symfony/dependency-injection/Dumper/GraphvizDumper.php#  Qti#  \      9   vendor/symfony/dependency-injection/Dumper/YamlDumper.php8  Qti8  O3      8   vendor/symfony/dependency-injection/Dumper/Preloader.php  Qti  ,{      8   vendor/symfony/dependency-injection/Dumper/XmlDumper.phpH  QtiH  ̤      >   vendor/symfony/dependency-injection/Dumper/DumperInterface.phpU  QtiU  *      5   vendor/symfony/dependency-injection/Dumper/Dumper.php  Qti  U;a      8   vendor/symfony/dependency-injection/Dumper/PhpDumper.php Qti J<      1   vendor/symfony/dependency-injection/composer.json  Qti  X~      =   vendor/symfony/dependency-injection/EnvVarLoaderInterface.php  Qti  0	      ?   vendor/symfony/dependency-injection/ContainerAwareInterface.php  Qti  =>         vendor/symfony/clock/LICENSE,  Qti,  t=      1   vendor/symfony/clock/Test/ClockSensitiveTrait.php=  Qti=  ~       !   vendor/symfony/clock/CHANGELOG.md  Qti  CJ      &   vendor/symfony/clock/Resources/now.php  Qti  c`      (   vendor/symfony/clock/ClockAwareTrait.php  Qti           vendor/symfony/clock/README.md  Qti  I      "   vendor/symfony/clock/MockClock.php  Qti  cZ         vendor/symfony/clock/Clock.php?	  Qti?	  N      '   vendor/symfony/clock/MonotonicClock.php
  Qti
  aR      '   vendor/symfony/clock/ClockInterface.phpJ  QtiJ  91      "   vendor/symfony/clock/DatePoint.php  Qti        "   vendor/symfony/clock/composer.json  Qti  GPҤ      $   vendor/symfony/clock/NativeClock.php  Qti  t5      :   vendor/symfony/password-hasher/PasswordHasherInterface.php  Qti  ol      >   vendor/symfony/password-hasher/Hasher/SodiumPasswordHasher.php  Qti  \      B   vendor/symfony/password-hasher/Hasher/CheckPasswordLengthTrait.php  Qti  \W      <   vendor/symfony/password-hasher/Hasher/UserPasswordHasher.php  Qti  a!      >   vendor/symfony/password-hasher/Hasher/Pbkdf2PasswordHasher.php+  Qti+  }[ܤ      F   vendor/symfony/password-hasher/Hasher/PasswordHasherAwareInterface.php  Qti  5ͤ      >   vendor/symfony/password-hasher/Hasher/NativePasswordHasher.php  Qti        E   vendor/symfony/password-hasher/Hasher/MessageDigestPasswordHasher.phpU  QtiU  3      E   vendor/symfony/password-hasher/Hasher/UserPasswordHasherInterface.php  Qti        A   vendor/symfony/password-hasher/Hasher/PlaintextPasswordHasher.php	  Qti	  @1      H   vendor/symfony/password-hasher/Hasher/PasswordHasherFactoryInterface.php  Qti  Ry      A   vendor/symfony/password-hasher/Hasher/MigratingPasswordHasher.php  Qti  KԤ      ?   vendor/symfony/password-hasher/Hasher/PasswordHasherFactory.php!  Qti!  V7C      &   vendor/symfony/password-hasher/LICENSE,  Qti,  U      +   vendor/symfony/password-hasher/CHANGELOG.md   Qti   ڰ      @   vendor/symfony/password-hasher/LegacyPasswordHasherInterface.php  Qti  U)      (   vendor/symfony/password-hasher/README.md  Qti  !      B   vendor/symfony/password-hasher/Command/UserPasswordHashCommand.php  Qti  H0      ;   vendor/symfony/password-hasher/Exception/LogicException.php  Qti  A      ?   vendor/symfony/password-hasher/Exception/ExceptionInterface.php  Qti  EWL      E   vendor/symfony/password-hasher/Exception/InvalidPasswordException.php  Qti  L      ,   vendor/symfony/password-hasher/composer.json  Qti           vendor/symfony/process/LICENSE,  Qti,  U      +   vendor/symfony/process/ExecutableFinder.php~  Qti~  cJ      #   vendor/symfony/process/CHANGELOG.md  Qti   %8          vendor/symfony/process/README.md  Qti  \3$Ϥ      *   vendor/symfony/process/Pipes/UnixPipes.php  Qti  r4z~      -   vendor/symfony/process/Pipes/WindowsPipes.php  Qti  3}g      .   vendor/symfony/process/Pipes/AbstractPipes.php  Qti        /   vendor/symfony/process/Pipes/PipesInterface.php  Qti  4ʤ      &   vendor/symfony/process/InputStream.php	  Qti	  H0      6   vendor/symfony/process/Messenger/RunProcessContext.php|  Qti|  ɔ      6   vendor/symfony/process/Messenger/RunProcessMessage.php  Qti  =o      =   vendor/symfony/process/Messenger/RunProcessMessageHandler.php$  Qti$        %   vendor/symfony/process/PhpProcess.php	  Qti	  Pnq      (   vendor/symfony/process/PhpSubprocess.php  Qti  &PpN      .   vendor/symfony/process/PhpExecutableFinder.php	  Qti	  ^      =   vendor/symfony/process/Exception/ProcessSignaledException.php  Qti  =      3   vendor/symfony/process/Exception/LogicException.php  Qti  iUQ      7   vendor/symfony/process/Exception/ExceptionInterface.php  Qti  
j%W      ;   vendor/symfony/process/Exception/ProcessFailedException.phpp  Qtip   ۋ      5   vendor/symfony/process/Exception/RuntimeException.php  Qti  P      =   vendor/symfony/process/Exception/ProcessTimedOutException.php  Qti  ו      =   vendor/symfony/process/Exception/InvalidArgumentException.php  Qti  ڴ      >   vendor/symfony/process/Exception/RunProcessFailedException.php  Qti  ؤ      $   vendor/symfony/process/composer.json  Qti  S.t      '   vendor/symfony/process/ProcessUtils.php  Qti  h      "   vendor/symfony/process/Process.phpi  Qtii  	3Ť      =   vendor/symfony/console/DataCollector/CommandDataCollector.php  Qti  m      (   vendor/symfony/console/ConsoleEvents.php  Qti  .      !   vendor/symfony/console/Cursor.php  Qti  Uhy      &   vendor/symfony/console/Application.php  Qti  A/      /   vendor/symfony/console/Logger/ConsoleLogger.phpT  QtiT  )A      .   vendor/symfony/console/Attribute/AsCommand.phpF  QtiF  L         vendor/symfony/console/LICENSE,  Qti,  U      #   vendor/symfony/console/CHANGELOG.md)  Qti)   b_e      9   vendor/symfony/console/Input/StreamableInputInterface.php  Qti  3y-      +   vendor/symfony/console/Input/ArrayInput.php:  Qti:  	      *   vendor/symfony/console/Input/ArgvInput.php0  Qti0  Q      .   vendor/symfony/console/Input/InputArgument.php1  Qti1  z0      4   vendor/symfony/console/Input/InputAwareInterface.phpc  Qtic  Q      ,   vendor/symfony/console/Input/InputOption.phpn!  Qtin!  8[      0   vendor/symfony/console/Input/InputDefinition.php?.  Qti?.  I       ,   vendor/symfony/console/Input/StringInput.php
  Qti
  Կ2      &   vendor/symfony/console/Input/Input.phpZ  QtiZ  !h      /   vendor/symfony/console/Input/InputInterface.phpu  Qtiu  I)      #   vendor/symfony/console/Terminal.php  Qti  ,      2   vendor/symfony/console/CI/GithubActionReporter.php!  Qti!  ǒ      0   vendor/symfony/console/Resources/completion.bash  Qti  xe      4   vendor/symfony/console/Resources/bin/hiddeninput.exe $  Qti $  v      /   vendor/symfony/console/Resources/completion.zsh  Qti  ʤ      0   vendor/symfony/console/Resources/completion.fish  Qti  Keդ      5   vendor/symfony/console/Output/TrimmedBufferOutput.phpW  QtiW  rm      8   vendor/symfony/console/Output/ConsoleOutputInterface.php;  Qti;  rƲ#      0   vendor/symfony/console/Output/BufferedOutput.phpP  QtiP  #¢      1   vendor/symfony/console/Output/OutputInterface.php/  Qti/  sm      /   vendor/symfony/console/Output/AnsiColorMode.php  Qti  |      (   vendor/symfony/console/Output/Output.php  Qti  'z      6   vendor/symfony/console/Output/ConsoleSectionOutput.php!  Qti!        /   vendor/symfony/console/Output/ConsoleOutput.php  Qti  7      ,   vendor/symfony/console/Output/NullOutput.phpH  QtiH  5      .   vendor/symfony/console/Output/StreamOutput.php  Qti        A   vendor/symfony/console/Completion/Output/FishCompletionOutput.php  Qti  a      A   vendor/symfony/console/Completion/Output/BashCompletionOutput.php  Qti         F   vendor/symfony/console/Completion/Output/CompletionOutputInterface.php  Qti  w7ؤ      @   vendor/symfony/console/Completion/Output/ZshCompletionOutput.php/  Qti/  92      0   vendor/symfony/console/Completion/Suggestion.php4  Qti4  R}      ;   vendor/symfony/console/Completion/CompletionSuggestions.phpX  QtiX  \8      5   vendor/symfony/console/Completion/CompletionInput.php  Qti  ܺ      ,   vendor/symfony/console/Style/OutputStyle.php  Qti  1      -   vendor/symfony/console/Style/SymfonyStyle.php;  Qti;  G      /   vendor/symfony/console/Style/StyleInterface.php
  Qti
  mŤ      2   vendor/symfony/console/Question/ChoiceQuestion.phpe  Qtie  xr      ,   vendor/symfony/console/Question/Question.php"  Qti"  e㨤      8   vendor/symfony/console/Question/ConfirmationQuestion.php+  Qti+  g          vendor/symfony/console/README.md  Qti  Æf      9   vendor/symfony/console/Formatter/OutputFormatterStyle.php  Qti  é      B   vendor/symfony/console/Formatter/OutputFormatterStyleInterface.php  Qti  Z      =   vendor/symfony/console/Formatter/NullOutputFormatterStyle.phpd  Qtid  ~      =   vendor/symfony/console/Formatter/OutputFormatterInterface.php  Qti  GR      4   vendor/symfony/console/Formatter/OutputFormatter.php$  Qti$  }3      8   vendor/symfony/console/Formatter/NullOutputFormatter.php  Qti  Ä;      F   vendor/symfony/console/Formatter/WrappableOutputFormatterInterface.php  Qti  *
      >   vendor/symfony/console/Formatter/OutputFormatterStyleStack.php9
  Qti9
  \      6   vendor/symfony/console/Messenger/RunCommandMessage.php  Qti  9      6   vendor/symfony/console/Messenger/RunCommandContext.php  Qti  !B      =   vendor/symfony/console/Messenger/RunCommandMessageHandler.php  Qti  ya          vendor/symfony/console/Color.php  Qti  MT      8   vendor/symfony/console/SignalRegistry/SignalRegistry.phpc  Qtic  jVN      3   vendor/symfony/console/SignalRegistry/SignalMap.php  Qti  ^֤      3   vendor/symfony/console/SingleCommandApplication.php;  Qti;  P      ?   vendor/symfony/console/CommandLoader/CommandLoaderInterface.phpS  QtiS  ]е      ?   vendor/symfony/console/CommandLoader/ContainerCommandLoader.php  Qti  X      =   vendor/symfony/console/CommandLoader/FactoryCommandLoader.phpG  QtiG  #Y
      4   vendor/symfony/console/Descriptor/TextDescriptor.phpm0  Qtim0        <   vendor/symfony/console/Descriptor/ApplicationDescription.php   Qti   y      3   vendor/symfony/console/Descriptor/XmlDescriptor.phpz&  Qtiz&  sg      9   vendor/symfony/console/Descriptor/DescriptorInterface.phpm  Qtim  B      0   vendor/symfony/console/Descriptor/Descriptor.php
  Qti
        @   vendor/symfony/console/Descriptor/ReStructuredTextDescriptor.php(  Qti(  xVW       4   vendor/symfony/console/Descriptor/JsonDescriptor.phpE  QtiE  B,      8   vendor/symfony/console/Descriptor/MarkdownDescriptor.php  Qti  ܨ      /   vendor/symfony/console/Tester/CommandTester.phpJ	  QtiJ	        -   vendor/symfony/console/Tester/TesterTrait.php  Qti  Ȏ      3   vendor/symfony/console/Tester/ApplicationTester.php  Qti  Df?h      9   vendor/symfony/console/Tester/CommandCompletionTester.php>  Qti>  Wf      @   vendor/symfony/console/Tester/Constraint/CommandIsSuccessful.php'  Qti'  4      3   vendor/symfony/console/Command/TraceableCommand.phpD(  QtiD(  ]      .   vendor/symfony/console/Command/LazyCommand.php  Qti  |      0   vendor/symfony/console/Command/LockableTrait.php0  Qti0   $      .   vendor/symfony/console/Command/HelpCommand.php	  Qti	  Ik^      2   vendor/symfony/console/Command/CompleteCommand.php#  Qti#  [T      .   vendor/symfony/console/Command/ListCommand.php	  Qti	  =      8   vendor/symfony/console/Command/DumpCompletionCommand.php{  Qti{  4N      =   vendor/symfony/console/Command/SignalableCommandInterface.phpD  QtiD  6}      *   vendor/symfony/console/Command/Command.phpY  QtiY  ߁^"      ,   vendor/symfony/console/Helper/TableStyle.php
1  Qti
1  N      +   vendor/symfony/console/Helper/TableRows.phpZ  QtiZ  ܚc      7   vendor/symfony/console/Helper/SymfonyQuestionHelper.php_  Qti_  >P      1   vendor/symfony/console/Helper/HelperInterface.phpU  QtiU  z6      +   vendor/symfony/console/Helper/TableCell.php  Qti  _      /   vendor/symfony/console/Helper/ProcessHelper.php  Qti  oYӤ      0   vendor/symfony/console/Helper/TableSeparator.php!  Qti!  n2      /   vendor/symfony/console/Helper/OutputWrapper.php  Qti  M"v      1   vendor/symfony/console/Helper/FormatterHelper.php  Qti        0   vendor/symfony/console/Helper/TableCellStyle.php  Qti  6Ȥ      -   vendor/symfony/console/Helper/ProgressBar.phpM  QtiM  >k      5   vendor/symfony/console/Helper/TerminalInputHelper.php  Qti  b`      6   vendor/symfony/console/Helper/DebugFormatterHelper.php  Qti  Z      +   vendor/symfony/console/Helper/HelperSet.php`  Qti`  O      (   vendor/symfony/console/Helper/Dumper.phpt  Qtit  q      2   vendor/symfony/console/Helper/InputAwareHelper.php  Qti  pc      0   vendor/symfony/console/Helper/QuestionHelper.phpN  QtiN  7      (   vendor/symfony/console/Helper/Helper.phpL  QtiL  l      '   vendor/symfony/console/Helper/Table.php9  Qti9        3   vendor/symfony/console/Helper/ProgressIndicator.php  Qti  dH      2   vendor/symfony/console/Helper/DescriptorHelper.php_
  Qti_
  ^<ä      D   vendor/symfony/console/DependencyInjection/AddConsoleCommandPass.php  Qti        3   vendor/symfony/console/Exception/LogicException.php  Qti  5      ;   vendor/symfony/console/Exception/InvalidOptionException.php  Qti  %:      >   vendor/symfony/console/Exception/RunCommandFailedException.php`  Qti`  py      7   vendor/symfony/console/Exception/ExceptionInterface.php  Qti  oOȤ      5   vendor/symfony/console/Exception/RuntimeException.php  Qti        ?   vendor/symfony/console/Exception/NamespaceNotFoundException.php  Qti  xD      =   vendor/symfony/console/Exception/InvalidArgumentException.php  Qti  xΤ      :   vendor/symfony/console/Exception/MissingInputException.php  Qti  L      =   vendor/symfony/console/Exception/CommandNotFoundException.php  Qti  $ִ      6   vendor/symfony/console/Event/ConsoleTerminateEvent.php  Qti  O      2   vendor/symfony/console/Event/ConsoleErrorEvent.php  Qti  \^      4   vendor/symfony/console/Event/ConsoleCommandEvent.php;  Qti;  4      -   vendor/symfony/console/Event/ConsoleEvent.php  Qti  BDE      3   vendor/symfony/console/Event/ConsoleSignalEvent.php  Qti  &WY      $   vendor/symfony/console/composer.jsonH  QtiH  +      +   vendor/symfony/console/Debug/CliRequest.phpl  Qtil  ?M      6   vendor/symfony/console/EventListener/ErrorListener.phpx  Qtix  @      0   vendor/symfony/polyfill-mbstring/bootstrap80.php'  Qti'  	~
      (   vendor/symfony/polyfill-mbstring/LICENSE,  Qti,  H      B   vendor/symfony/polyfill-mbstring/Resources/unidata/caseFolding.php  Qti  ]SC      @   vendor/symfony/polyfill-mbstring/Resources/unidata/lowerCase.phpU  QtiU  D׎      F   vendor/symfony/polyfill-mbstring/Resources/unidata/titleCaseRegexp.phpS  QtiS  ݤ      @   vendor/symfony/polyfill-mbstring/Resources/unidata/upperCase.phpO[  QtiO[  (      -   vendor/symfony/polyfill-mbstring/Mbstring.php4  Qti4  b<a      .   vendor/symfony/polyfill-mbstring/bootstrap.php   Qti   Nc)      *   vendor/symfony/polyfill-mbstring/README.mdr  Qtir  A`      .   vendor/symfony/polyfill-mbstring/composer.jsonR  QtiR  `P      5   vendor/symfony/polyfill-intl-grapheme/bootstrap80.php  Qti  iwP      -   vendor/symfony/polyfill-intl-grapheme/LICENSE,  Qti,  H      2   vendor/symfony/polyfill-intl-grapheme/Grapheme.php/  Qti/  6"b      3   vendor/symfony/polyfill-intl-grapheme/bootstrap.php
  Qti
        /   vendor/symfony/polyfill-intl-grapheme/README.md  Qti  6      3   vendor/symfony/polyfill-intl-grapheme/composer.json   Qti   +          vendor/ramsey/collection/LICENSE7  Qti7  ŸԤ      "   vendor/ramsey/collection/README.md  Qti  3 Ӥ      &   vendor/ramsey/collection/composer.json|  Qti|   v֤      $   vendor/ramsey/collection/SECURITY.md  Qti        1   vendor/ramsey/collection/src/DoubleEndedQueue.php  Qti        ,   vendor/ramsey/collection/src/AbstractSet.php  Qti  <      /   vendor/ramsey/collection/src/QueueInterface.php  Qti  jzä      3   vendor/ramsey/collection/src/AbstractCollection.phpN+  QtiN+  ~syȤ      .   vendor/ramsey/collection/src/AbstractArray.php  Qti  XϤ      &   vendor/ramsey/collection/src/Queue.php+  Qti+  Ť      $   vendor/ramsey/collection/src/Set.php/  Qti/  v      :   vendor/ramsey/collection/src/DoubleEndedQueueInterface.php(  Qti(  OD      6   vendor/ramsey/collection/src/Map/TypedMapInterface.php0  Qti0  -ˤ      5   vendor/ramsey/collection/src/Map/AbstractTypedMap.phpb  Qtib  踖      1   vendor/ramsey/collection/src/Map/MapInterface.php  Qti  N}      -   vendor/ramsey/collection/src/Map/TypedMap.php
  Qti
  v%      8   vendor/ramsey/collection/src/Map/AssociativeArrayMap.php0  Qti0  PǤ      6   vendor/ramsey/collection/src/Map/NamedParameterMap.php  Qti  x      0   vendor/ramsey/collection/src/Map/AbstractMap.php  Qti  xg      -   vendor/ramsey/collection/src/GenericArray.php  Qti        /   vendor/ramsey/collection/src/ArrayInterface.php$  Qti$  t      %   vendor/ramsey/collection/src/Sort.php{  Qti{  Ȥ      +   vendor/ramsey/collection/src/Collection.php	  Qti	  A#      4   vendor/ramsey/collection/src/CollectionInterface.php$  Qti$  0h      H   vendor/ramsey/collection/src/Exception/UnsupportedOperationException.phpL  QtiL  ff      ?   vendor/ramsey/collection/src/Exception/OutOfBoundsException.phpw  Qtiw        >   vendor/ramsey/collection/src/Exception/CollectionException.php  Qti  Ĵ@      C   vendor/ramsey/collection/src/Exception/InvalidArgumentException.phps  Qtis  ڤ      A   vendor/ramsey/collection/src/Exception/NoSuchElementException.phpD  QtiD  	Ln      B   vendor/ramsey/collection/src/Exception/InvalidPropertyOrMethod.php  Qti        F   vendor/ramsey/collection/src/Exception/CollectionMismatchException.phpM  QtiM  \ć      8   vendor/ramsey/collection/src/Tool/ValueToStringTrait.php	  Qti	  ϝUD      /   vendor/ramsey/collection/src/Tool/TypeTrait.phpC  QtiC  O      9   vendor/ramsey/collection/src/Tool/ValueExtractorTrait.php  Qti  8ヤ         vendor/ramsey/uuid/LICENSE7  Qti7  <[         vendor/ramsey/uuid/README.md.  Qti.            vendor/ramsey/uuid/composer.json  Qti  Yį      $   vendor/ramsey/uuid/src/functions.php  Qti  P      5   vendor/ramsey/uuid/src/Validator/GenericValidator.php%  Qti%  |$      7   vendor/ramsey/uuid/src/Validator/ValidatorInterface.php  Qti  %      >   vendor/ramsey/uuid/src/Converter/Time/GenericTimeConverter.php  Qti  eѤ      ;   vendor/ramsey/uuid/src/Converter/Time/UnixTimeConverter.php
  Qti
        :   vendor/ramsey/uuid/src/Converter/Time/PhpTimeConverter.phpD  QtiD  nՄ      ?   vendor/ramsey/uuid/src/Converter/Time/DegradedTimeConverter.phpv  Qtiv  פ      @   vendor/ramsey/uuid/src/Converter/Time/BigNumberTimeConverter.phps  Qtis  Hv      C   vendor/ramsey/uuid/src/Converter/Number/DegradedNumberConverter.php}  Qti}  Y{      >   vendor/ramsey/uuid/src/Converter/Number/BigNumberConverter.php  Qti   }¤      B   vendor/ramsey/uuid/src/Converter/Number/GenericNumberConverter.php  Qti  \      ;   vendor/ramsey/uuid/src/Converter/TimeConverterInterface.php  Qti  I      =   vendor/ramsey/uuid/src/Converter/NumberConverterInterface.php  Qti  ¿      5   vendor/ramsey/uuid/src/DeprecatedUuidMethodsTrait.php3  Qti3  D3      8   vendor/ramsey/uuid/src/Codec/TimestampFirstCombCodec.php  Qti  ~w      1   vendor/ramsey/uuid/src/Codec/OrderedTimeCodec.php  Qti  MV      /   vendor/ramsey/uuid/src/Codec/CodecInterface.php  Qti  !      0   vendor/ramsey/uuid/src/Codec/GuidStringCodec.php  Qti  _      ,   vendor/ramsey/uuid/src/Codec/StringCodec.php/  Qti/  ^      7   vendor/ramsey/uuid/src/Codec/TimestampLastCombCodec.php  Qti  e8         vendor/ramsey/uuid/src/Uuid.php^  Qti^  B5%      @   vendor/ramsey/uuid/src/Provider/DceSecurityProviderInterface.php  Qti        A   vendor/ramsey/uuid/src/Provider/Dce/SystemDceSecurityProvider.php  Qti  "      9   vendor/ramsey/uuid/src/Provider/NodeProviderInterface.php  Qti  v!      ;   vendor/ramsey/uuid/src/Provider/Time/SystemTimeProvider.php  Qti  fW      :   vendor/ramsey/uuid/src/Provider/Time/FixedTimeProvider.php  Qti  .      9   vendor/ramsey/uuid/src/Provider/TimeProviderInterface.phpR  QtiR  Ry      ;   vendor/ramsey/uuid/src/Provider/Node/RandomNodeProvider.phpm  Qtim  rZ      =   vendor/ramsey/uuid/src/Provider/Node/FallbackNodeProvider.phpv  Qtiv        ;   vendor/ramsey/uuid/src/Provider/Node/SystemNodeProvider.php  Qti  Q
ؤ      ?   vendor/ramsey/uuid/src/Provider/Node/NodeProviderCollection.phpA  QtiA  )F      ;   vendor/ramsey/uuid/src/Provider/Node/StaticNodeProvider.php1  Qti1  ݫ      %   vendor/ramsey/uuid/src/FeatureSet.php1  Qti1  K      2   vendor/ramsey/uuid/src/Rfc4122/FieldsInterface.php  Qti  !      )   vendor/ramsey/uuid/src/Rfc4122/UuidV8.php	  Qti	  RE      ,   vendor/ramsey/uuid/src/Rfc4122/Validator.phpV  QtiV  ׋      +   vendor/ramsey/uuid/src/Rfc4122/MaxTrait.phpU  QtiU  涤      /   vendor/ramsey/uuid/src/Rfc4122/VersionTrait.php  Qti  I      +   vendor/ramsey/uuid/src/Rfc4122/NilTrait.phpA  QtiA  X      )   vendor/ramsey/uuid/src/Rfc4122/Fields.php  Qti  e      *   vendor/ramsey/uuid/src/Rfc4122/NilUuid.php  Qti        *   vendor/ramsey/uuid/src/Rfc4122/MaxUuid.php  Qti  oޤ      0   vendor/ramsey/uuid/src/Rfc4122/UuidInterface.php  Qti  :J}      ,   vendor/ramsey/uuid/src/Rfc4122/TimeTrait.php@  Qti@        /   vendor/ramsey/uuid/src/Rfc4122/VariantTrait.php  Qti  iä      .   vendor/ramsey/uuid/src/Rfc4122/UuidBuilder.phpw  Qtiw  ) ֤      )   vendor/ramsey/uuid/src/Rfc4122/UuidV1.php  Qti  )]ߤ      )   vendor/ramsey/uuid/src/Rfc4122/UuidV3.php>  Qti>  H<      )   vendor/ramsey/uuid/src/Rfc4122/UuidV2.php  Qti  d~      )   vendor/ramsey/uuid/src/Rfc4122/UuidV6.php  Qti  e`      )   vendor/ramsey/uuid/src/Rfc4122/UuidV7.php  Qti  gE      )   vendor/ramsey/uuid/src/Rfc4122/UuidV5.phpC  QtiC  X      )   vendor/ramsey/uuid/src/Rfc4122/UuidV4.php  Qti        (   vendor/ramsey/uuid/src/UuidInterface.php  Qti  ͤ      ,   vendor/ramsey/uuid/src/Math/RoundingMode.php1  Qti1  {k3      3   vendor/ramsey/uuid/src/Math/CalculatorInterface.php  Qti   y      3   vendor/ramsey/uuid/src/Math/BrickMathCalculator.phpI  QtiI  Y~֤      /   vendor/ramsey/uuid/src/UuidFactoryInterface.php  Qti  l!h      9   vendor/ramsey/uuid/src/Generator/RandomBytesGenerator.phpS  QtiS  [S      9   vendor/ramsey/uuid/src/Generator/NameGeneratorFactory.php  Qti  4p:S      6   vendor/ramsey/uuid/src/Generator/UnixTimeGenerator.php:  Qti:  9      ;   vendor/ramsey/uuid/src/Generator/NameGeneratorInterface.php9  Qti9  )      ;   vendor/ramsey/uuid/src/Generator/RandomGeneratorFactory.php  Qti  ա      9   vendor/ramsey/uuid/src/Generator/DceSecurityGenerator.php  Qti  @k      B   vendor/ramsey/uuid/src/Generator/DceSecurityGeneratorInterface.php  Qti  VC      9   vendor/ramsey/uuid/src/Generator/TimeGeneratorFactory.phpw  Qtiw  O      9   vendor/ramsey/uuid/src/Generator/DefaultNameGenerator.phpS  QtiS  V      9   vendor/ramsey/uuid/src/Generator/DefaultTimeGenerator.php  Qti  *g      5   vendor/ramsey/uuid/src/Generator/RandomLibAdapter.php6  Qti6  2E      ;   vendor/ramsey/uuid/src/Generator/TimeGeneratorInterface.php  Qti  !      2   vendor/ramsey/uuid/src/Generator/CombGenerator.phpX  QtiX        =   vendor/ramsey/uuid/src/Generator/RandomGeneratorInterface.php  Qti  Ae      <   vendor/ramsey/uuid/src/Generator/PeclUuidRandomGenerator.php;  Qti;  N_      :   vendor/ramsey/uuid/src/Generator/PeclUuidNameGenerator.php  Qti   J      :   vendor/ramsey/uuid/src/Generator/PeclUuidTimeGenerator.phpz  Qtiz        &   vendor/ramsey/uuid/src/BinaryUtils.php#  Qti#  vՄ      &   vendor/ramsey/uuid/src/UuidFactory.phpJ<  QtiJ<  >      '   vendor/ramsey/uuid/src/Type/Integer.php*  Qti*  m+w      $   vendor/ramsey/uuid/src/Type/Time.php  Qti  7iZy      +   vendor/ramsey/uuid/src/Type/Hexadecimal.php  Qti  Z'      /   vendor/ramsey/uuid/src/Type/NumberInterface.php  Qti  iu      -   vendor/ramsey/uuid/src/Type/TypeInterface.php  Qti  +KФ      '   vendor/ramsey/uuid/src/Type/Decimal.php  Qti  <H      $   vendor/ramsey/uuid/src/Guid/Guid.php		  Qti		  M      &   vendor/ramsey/uuid/src/Guid/Fields.php  Qti  `      +   vendor/ramsey/uuid/src/Guid/GuidBuilder.phpK	  QtiK	  K֟      2   vendor/ramsey/uuid/src/Lazy/LazyUuidFromString.php5  Qti5        '   vendor/ramsey/uuid/src/DegradedUuid.php[  Qti[  ?^      1   vendor/ramsey/uuid/src/Fields/FieldsInterface.php  Qti  Fe      9   vendor/ramsey/uuid/src/Fields/SerializableFieldsTrait.phpu  Qtiu  R      2   vendor/ramsey/uuid/src/DeprecatedUuidInterface.php  Qti  y      6   vendor/ramsey/uuid/src/Builder/DegradedUuidBuilder.phpg  Qtig  _      7   vendor/ramsey/uuid/src/Builder/UuidBuilderInterface.php#  Qti#  hS̤      4   vendor/ramsey/uuid/src/Builder/BuilderCollection.php	  Qti	  6a      2   vendor/ramsey/uuid/src/Builder/FallbackBuilder.phpn  Qtin        5   vendor/ramsey/uuid/src/Builder/DefaultUuidBuilder.phpU  QtiU  "      :   vendor/ramsey/uuid/src/Exception/RandomSourceException.php  Qti        2   vendor/ramsey/uuid/src/Exception/NodeException.php`  Qti`  ]      6   vendor/ramsey/uuid/src/Exception/DateTimeException.phpa  Qtia  \      8   vendor/ramsey/uuid/src/Exception/TimeSourceException.phpQ  QtiQ        B   vendor/ramsey/uuid/src/Exception/UnsupportedOperationException.phpV  QtiV  JN      :   vendor/ramsey/uuid/src/Exception/InvalidBytesException.php_  Qti_  /٤      9   vendor/ramsey/uuid/src/Exception/DceSecurityException.phpm  Qtim  IC      2   vendor/ramsey/uuid/src/Exception/NameException.phpc  Qtic  sOS      =   vendor/ramsey/uuid/src/Exception/InvalidArgumentException.phpi  Qtii  v'ä      =   vendor/ramsey/uuid/src/Exception/BuilderNotFoundException.phpQ  QtiQ  @c      ?   vendor/ramsey/uuid/src/Exception/UnableToBuildUuidException.phpO  QtiO  Ro      ;   vendor/ramsey/uuid/src/Exception/UuidExceptionInterface.php  Qti  K;Ҥ      ?   vendor/ramsey/uuid/src/Exception/InvalidUuidStringException.php  Qti  <1i      -   vendor/ramsey/uuid/src/Nonstandard/Fields.php&  Qti&        +   vendor/ramsey/uuid/src/Nonstandard/Uuid.php  Qti        2   vendor/ramsey/uuid/src/Nonstandard/UuidBuilder.phpt	  Qtit	  P֤      -   vendor/ramsey/uuid/src/Nonstandard/UuidV6.php  Qti  9̤         vendor/webmozart/assert/LICENSE<  Qti<  t}      $   vendor/webmozart/assert/CHANGELOG.md  Qti  _      !   vendor/webmozart/assert/README.md>  Qti>  
      %   vendor/webmozart/assert/composer.json  Qti  3      %   vendor/webmozart/assert/src/Mixin.php Qti Ȧ<      8   vendor/webmozart/assert/src/InvalidArgumentException.phpi  Qtii  {Lä      &   vendor/webmozart/assert/src/Assert.php  Qti  h         vendor/react/promise/LICENSEg  Qtig  F      !   vendor/react/promise/CHANGELOG.md9  Qti9  OT:         vendor/react/promise/README.mdQY  QtiQY  1      "   vendor/react/promise/composer.json  Qti  T?      -   vendor/react/promise/src/PromiseInterface.php  Qti  ]ܤ      &   vendor/react/promise/src/functions.php-  Qti-  m      .   vendor/react/promise/src/functions_include.php~   Qti~   I      $   vendor/react/promise/src/Promise.php(  Qti(  v      %   vendor/react/promise/src/Deferred.php,  Qti,  F      5   vendor/react/promise/src/Internal/RejectedPromise.php  Qti  7      6   vendor/react/promise/src/Internal/FulfilledPromise.phpK	  QtiK	  LN      7   vendor/react/promise/src/Internal/CancellationQueue.php  Qti  !      6   vendor/react/promise/src/Exception/LengthException.php^   Qti^   ?q      9   vendor/react/promise/src/Exception/CompositeException.php`  Qti`  6         vendor/sebastian/diff/LICENSE  Qti  ܡ7      "   vendor/sebastian/diff/ChangeLog.md  Qti  A         vendor/sebastian/diff/README.mdx   Qtix   Z      #   vendor/sebastian/diff/composer.json  Qti  H      !   vendor/sebastian/diff/SECURITY.mdu  Qtiu  KJ      "   vendor/sebastian/diff/src/Diff.phpV  QtiV        $   vendor/sebastian/diff/src/Parser.php  Qti  QwԤ      M   vendor/sebastian/diff/src/TimeEfficientLongestCommonSubsequenceCalculator.php  Qti  \=Ť      :   vendor/sebastian/diff/src/Output/DiffOnlyOutputBuilder.php  Qti  낵      ?   vendor/sebastian/diff/src/Output/DiffOutputBuilderInterface.php  Qti  LG      =   vendor/sebastian/diff/src/Output/UnifiedDiffOutputBuilder.php  Qti  ̀ɤ      C   vendor/sebastian/diff/src/Output/StrictUnifiedDiffOutputBuilder.phph(  Qtih(  W      ?   vendor/sebastian/diff/src/Output/AbstractChunkOutputBuilder.php  Qti  (      @   vendor/sebastian/diff/src/LongestCommonSubsequenceCalculator.php  Qti        #   vendor/sebastian/diff/src/Chunk.php	  Qti	  [      $   vendor/sebastian/diff/src/Differ.php  Qti  ͉      "   vendor/sebastian/diff/src/Line.php  Qti  \Q      >   vendor/sebastian/diff/src/Exception/ConfigurationException.php)  Qti)  2ܤ      @   vendor/sebastian/diff/src/Exception/InvalidArgumentException.php  Qti  +U/ܤ      1   vendor/sebastian/diff/src/Exception/Exception.phpq  Qtiq  Z      O   vendor/sebastian/diff/src/MemoryEfficientLongestCommonSubsequenceCalculator.php  Qti  =      3   vendor/terminal42/composer-lock-validator/README.md#
  Qti#
  QG      7   vendor/terminal42/composer-lock-validator/composer.json#  Qti#  B      ;   vendor/terminal42/composer-lock-validator/src/Validator.php$  Qti$  ɜ      E   vendor/terminal42/composer-lock-validator/src/ValidationException.php*  Qti*  eP      <?php

namespace HumbugBox468\KevinGH\RequirementChecker;

if (isset($_SERVER['BOX_REQUIREMENT_CHECKER'])) {
    $enableRequirementChecker = $_SERVER['BOX_REQUIREMENT_CHECKER'];
    if (is_bool($enableRequirementChecker) && !$enableRequirementChecker) {
        return;
    }
    if (is_string($enableRequirementChecker) && in_array(strtolower($enableRequirementChecker), ['false', '0'], \true)) {
        return;
    }
    if (!is_bool($enableRequirementChecker) && !is_string($enableRequirementChecker)) {
        echo \PHP_EOL . 'Unhandled value type for "BOX_REQUIREMENT_CHECKER". Got "' . gettype($enableRequirementChecker) . '". Proceeding with the requirement checks.' . \PHP_EOL;
    }
}
if (\false === in_array(\PHP_SAPI, array('cli', 'phpdbg', 'embed', 'micro'), \true)) {
    echo \PHP_EOL . 'The application may only be invoked from a command line, got "' . \PHP_SAPI . '"' . \PHP_EOL;
    exit(1);
}
require __DIR__ . '/../vendor/autoload.php';
if (!Checker::checkRequirements()) {
    exit(1);
}
<?php

return array (
  0 => 
  array (
    'type' => 'php',
    'condition' => '^8.1',
    'source' => NULL,
    'message' => 'This application requires a PHP version matching "^8.1".',
    'helpMessage' => 'This application requires a PHP version matching "^8.1".',
  ),
  1 => 
  array (
    'type' => 'extension',
    'condition' => 'date',
    'source' => 'webmozart/assert',
    'message' => 'The package "webmozart/assert" requires the extension "date".',
    'helpMessage' => 'The package "webmozart/assert" requires the extension "date". You either need to enable it or request the application to be shipped with a polyfill for this extension.',
  ),
  2 => 
  array (
    'type' => 'extension',
    'condition' => 'filter',
    'source' => 'phpdocumentor/reflection-docblock',
    'message' => 'The package "phpdocumentor/reflection-docblock" requires the extension "filter".',
    'helpMessage' => 'The package "phpdocumentor/reflection-docblock" requires the extension "filter". You either need to enable it or request the application to be shipped with a polyfill for this extension.',
  ),
  3 => 
  array (
    'type' => 'extension',
    'condition' => 'filter',
    'source' => 'webmozart/assert',
    'message' => 'The package "webmozart/assert" requires the extension "filter".',
    'helpMessage' => 'The package "webmozart/assert" requires the extension "filter". You either need to enable it or request the application to be shipped with a polyfill for this extension.',
  ),
  4 => 
  array (
    'type' => 'extension',
    'condition' => 'iconv',
    'source' => 'symfony/polyfill-mbstring',
    'message' => 'The package "symfony/polyfill-mbstring" requires the extension "iconv".',
    'helpMessage' => 'The package "symfony/polyfill-mbstring" requires the extension "iconv". You either need to enable it or request the application to be shipped with a polyfill for this extension.',
  ),
  5 => 
  array (
    'type' => 'extension',
    'condition' => 'json',
    'source' => NULL,
    'message' => 'This application requires the extension "json".',
    'helpMessage' => 'This application requires the extension "json". You either need to enable it or request the application to be shipped with a polyfill for this extension.',
  ),
  6 => 
  array (
    'type' => 'extension',
    'condition' => 'json',
    'source' => 'composer/composer',
    'message' => 'The package "composer/composer" requires the extension "json".',
    'helpMessage' => 'The package "composer/composer" requires the extension "json". You either need to enable it or request the application to be shipped with a polyfill for this extension.',
  ),
  7 => 
  array (
    'type' => 'extension',
    'condition' => 'json',
    'source' => 'justinrainbow/json-schema',
    'message' => 'The package "justinrainbow/json-schema" requires the extension "json".',
    'helpMessage' => 'The package "justinrainbow/json-schema" requires the extension "json". You either need to enable it or request the application to be shipped with a polyfill for this extension.',
  ),
  8 => 
  array (
    'type' => 'extension',
    'condition' => 'json',
    'source' => 'web-auth/cose-lib',
    'message' => 'The package "web-auth/cose-lib" requires the extension "json".',
    'helpMessage' => 'The package "web-auth/cose-lib" requires the extension "json". You either need to enable it or request the application to be shipped with a polyfill for this extension.',
  ),
  9 => 
  array (
    'type' => 'extension',
    'condition' => 'json',
    'source' => 'web-auth/webauthn-lib',
    'message' => 'The package "web-auth/webauthn-lib" requires the extension "json".',
    'helpMessage' => 'The package "web-auth/webauthn-lib" requires the extension "json". You either need to enable it or request the application to be shipped with a polyfill for this extension.',
  ),
  10 => 
  array (
    'type' => 'extension',
    'condition' => 'openssl',
    'source' => 'composer/ca-bundle',
    'message' => 'The package "composer/ca-bundle" requires the extension "openssl".',
    'helpMessage' => 'The package "composer/ca-bundle" requires the extension "openssl". You either need to enable it or request the application to be shipped with a polyfill for this extension.',
  ),
  11 => 
  array (
    'type' => 'extension',
    'condition' => 'openssl',
    'source' => 'web-auth/cose-lib',
    'message' => 'The package "web-auth/cose-lib" requires the extension "openssl".',
    'helpMessage' => 'The package "web-auth/cose-lib" requires the extension "openssl". You either need to enable it or request the application to be shipped with a polyfill for this extension.',
  ),
  12 => 
  array (
    'type' => 'extension',
    'condition' => 'openssl',
    'source' => 'web-auth/webauthn-lib',
    'message' => 'The package "web-auth/webauthn-lib" requires the extension "openssl".',
    'helpMessage' => 'The package "web-auth/webauthn-lib" requires the extension "openssl". You either need to enable it or request the application to be shipped with a polyfill for this extension.',
  ),
  13 => 
  array (
    'type' => 'extension',
    'condition' => 'pcre',
    'source' => 'composer/ca-bundle',
    'message' => 'The package "composer/ca-bundle" requires the extension "pcre".',
    'helpMessage' => 'The package "composer/ca-bundle" requires the extension "pcre". You either need to enable it or request the application to be shipped with a polyfill for this extension.',
  ),
  14 => 
  array (
    'type' => 'extension',
    'condition' => 'reflection',
    'source' => 'marc-mabe/php-enum',
    'message' => 'The package "marc-mabe/php-enum" requires the extension "reflection".',
    'helpMessage' => 'The package "marc-mabe/php-enum" requires the extension "reflection". You either need to enable it or request the application to be shipped with a polyfill for this extension.',
  ),
  15 => 
  array (
    'type' => 'extension',
    'condition' => 'session',
    'source' => NULL,
    'message' => 'This application requires the extension "session".',
    'helpMessage' => 'This application requires the extension "session". You either need to enable it or request the application to be shipped with a polyfill for this extension.',
  ),
  16 => 
  array (
    'type' => 'extension',
    'condition' => 'xml',
    'source' => 'symfony/framework-bundle',
    'message' => 'The package "symfony/framework-bundle" requires the extension "xml".',
    'helpMessage' => 'The package "symfony/framework-bundle" requires the extension "xml". You either need to enable it or request the application to be shipped with a polyfill for this extension.',
  ),
  17 => 
  array (
    'type' => 'extension',
    'condition' => 'xml',
    'source' => 'symfony/security-bundle',
    'message' => 'The package "symfony/security-bundle" requires the extension "xml".',
    'helpMessage' => 'The package "symfony/security-bundle" requires the extension "xml". You either need to enable it or request the application to be shipped with a polyfill for this extension.',
  ),
  18 => 
  array (
    'type' => 'extension',
    'condition' => 'zip',
    'source' => NULL,
    'message' => 'This application requires the extension "zip".',
    'helpMessage' => 'This application requires the extension "zip". You either need to enable it or request the application to be shipped with a polyfill for this extension.',
  ),
  19 => 
  array (
    'type' => 'extension-conflict',
    'condition' => 'psr',
    'source' => 'symfony/dependency-injection',
    'message' => 'The package "symfony/dependency-injection" conflicts with the extension "psr".',
    'helpMessage' => 'The package "symfony/dependency-injection" conflicts with the extension "psr". You need to disable it in order to run this application.',
  ),
  20 => 
  array (
    'type' => 'extension-conflict',
    'condition' => 'psr',
    'source' => 'symfony/service-contracts',
    'message' => 'The package "symfony/service-contracts" conflicts with the extension "psr".',
    'helpMessage' => 'The package "symfony/service-contracts" conflicts with the extension "psr". You need to disable it in order to run this application.',
  ),
);<?php

// autoload.php @generated by Composer

if (PHP_VERSION_ID < 50600) {
    if (!headers_sent()) {
        header('HTTP/1.1 500 Internal Server Error');
    }
    $err = 'Composer 2.3.0 dropped support for autoloading on PHP <5.6 and you are running '.PHP_VERSION.', please upgrade PHP or use Composer 2.2 LTS via "composer self-update --2.2". Aborting.'.PHP_EOL;
    if (!ini_get('display_errors')) {
        if (PHP_SAPI === 'cli' || PHP_SAPI === 'phpdbg') {
            fwrite(STDERR, $err);
        } elseif (!headers_sent()) {
            echo $err;
        }
    }
    throw new RuntimeException($err);
}

require_once __DIR__ . '/composer/autoload_real.php';

return ComposerAutoloaderInitHumbugBox468::getLoader();
<?php

// autoload_namespaces.php @generated by Composer

$vendorDir = dirname(__DIR__);
$baseDir = dirname($vendorDir);

return array(
);

Copyright (c) Nils Adermann, Jordi Boggiano

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is furnished
to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

<?php

/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Composer\Autoload;

/**
 * ClassLoader implements a PSR-0, PSR-4 and classmap class loader.
 *
 *     $loader = new \Composer\Autoload\ClassLoader();
 *
 *     // register classes with namespaces
 *     $loader->add('Symfony\Component', __DIR__.'/component');
 *     $loader->add('Symfony',           __DIR__.'/framework');
 *
 *     // activate the autoloader
 *     $loader->register();
 *
 *     // to enable searching the include path (eg. for PEAR packages)
 *     $loader->setUseIncludePath(true);
 *
 * In this example, if you try to use a class in the Symfony\Component
 * namespace or one of its children (Symfony\Component\Console for instance),
 * the autoloader will first look for the class under the component/
 * directory, and it will then fallback to the framework/ directory if not
 * found before giving up.
 *
 * This class is loosely based on the Symfony UniversalClassLoader.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 * @author Jordi Boggiano <j.boggiano@seld.be>
 * @see    https://www.php-fig.org/psr/psr-0/
 * @see    https://www.php-fig.org/psr/psr-4/
 */
class ClassLoader
{
    /** @var \Closure(string):void */
    private static $includeFile;

    /** @var string|null */
    private $vendorDir;

    // PSR-4
    /**
     * @var array<string, array<string, int>>
     */
    private $prefixLengthsPsr4 = array();
    /**
     * @var array<string, list<string>>
     */
    private $prefixDirsPsr4 = array();
    /**
     * @var list<string>
     */
    private $fallbackDirsPsr4 = array();

    // PSR-0
    /**
     * List of PSR-0 prefixes
     *
     * Structured as array('F (first letter)' => array('Foo\Bar (full prefix)' => array('path', 'path2')))
     *
     * @var array<string, array<string, list<string>>>
     */
    private $prefixesPsr0 = array();
    /**
     * @var list<string>
     */
    private $fallbackDirsPsr0 = array();

    /** @var bool */
    private $useIncludePath = false;

    /**
     * @var array<string, string>
     */
    private $classMap = array();

    /** @var bool */
    private $classMapAuthoritative = false;

    /**
     * @var array<string, bool>
     */
    private $missingClasses = array();

    /** @var string|null */
    private $apcuPrefix;

    /**
     * @var array<string, self>
     */
    private static $registeredLoaders = array();

    /**
     * @param string|null $vendorDir
     */
    public function __construct($vendorDir = null)
    {
        $this->vendorDir = $vendorDir;
        self::initializeIncludeClosure();
    }

    /**
     * @return array<string, list<string>>
     */
    public function getPrefixes()
    {
        if (!empty($this->prefixesPsr0)) {
            return call_user_func_array('array_merge', array_values($this->prefixesPsr0));
        }

        return array();
    }

    /**
     * @return array<string, list<string>>
     */
    public function getPrefixesPsr4()
    {
        return $this->prefixDirsPsr4;
    }

    /**
     * @return list<string>
     */
    public function getFallbackDirs()
    {
        return $this->fallbackDirsPsr0;
    }

    /**
     * @return list<string>
     */
    public function getFallbackDirsPsr4()
    {
        return $this->fallbackDirsPsr4;
    }

    /**
     * @return array<string, string> Array of classname => path
     */
    public function getClassMap()
    {
        return $this->classMap;
    }

    /**
     * @param array<string, string> $classMap Class to filename map
     *
     * @return void
     */
    public function addClassMap(array $classMap)
    {
        if ($this->classMap) {
            $this->classMap = array_merge($this->classMap, $classMap);
        } else {
            $this->classMap = $classMap;
        }
    }

    /**
     * Registers a set of PSR-0 directories for a given prefix, either
     * appending or prepending to the ones previously set for this prefix.
     *
     * @param string              $prefix  The prefix
     * @param list<string>|string $paths   The PSR-0 root directories
     * @param bool                $prepend Whether to prepend the directories
     *
     * @return void
     */
    public function add($prefix, $paths, $prepend = false)
    {
        $paths = (array) $paths;
        if (!$prefix) {
            if ($prepend) {
                $this->fallbackDirsPsr0 = array_merge(
                    $paths,
                    $this->fallbackDirsPsr0
                );
            } else {
                $this->fallbackDirsPsr0 = array_merge(
                    $this->fallbackDirsPsr0,
                    $paths
                );
            }

            return;
        }

        $first = $prefix[0];
        if (!isset($this->prefixesPsr0[$first][$prefix])) {
            $this->prefixesPsr0[$first][$prefix] = $paths;

            return;
        }
        if ($prepend) {
            $this->prefixesPsr0[$first][$prefix] = array_merge(
                $paths,
                $this->prefixesPsr0[$first][$prefix]
            );
        } else {
            $this->prefixesPsr0[$first][$prefix] = array_merge(
                $this->prefixesPsr0[$first][$prefix],
                $paths
            );
        }
    }

    /**
     * Registers a set of PSR-4 directories for a given namespace, either
     * appending or prepending to the ones previously set for this namespace.
     *
     * @param string              $prefix  The prefix/namespace, with trailing '\\'
     * @param list<string>|string $paths   The PSR-4 base directories
     * @param bool                $prepend Whether to prepend the directories
     *
     * @throws \InvalidArgumentException
     *
     * @return void
     */
    public function addPsr4($prefix, $paths, $prepend = false)
    {
        $paths = (array) $paths;
        if (!$prefix) {
            // Register directories for the root namespace.
            if ($prepend) {
                $this->fallbackDirsPsr4 = array_merge(
                    $paths,
                    $this->fallbackDirsPsr4
                );
            } else {
                $this->fallbackDirsPsr4 = array_merge(
                    $this->fallbackDirsPsr4,
                    $paths
                );
            }
        } elseif (!isset($this->prefixDirsPsr4[$prefix])) {
            // Register directories for a new namespace.
            $length = strlen($prefix);
            if ('\\' !== $prefix[$length - 1]) {
                throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
            }
            $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
            $this->prefixDirsPsr4[$prefix] = $paths;
        } elseif ($prepend) {
            // Prepend directories for an already registered namespace.
            $this->prefixDirsPsr4[$prefix] = array_merge(
                $paths,
                $this->prefixDirsPsr4[$prefix]
            );
        } else {
            // Append directories for an already registered namespace.
            $this->prefixDirsPsr4[$prefix] = array_merge(
                $this->prefixDirsPsr4[$prefix],
                $paths
            );
        }
    }

    /**
     * Registers a set of PSR-0 directories for a given prefix,
     * replacing any others previously set for this prefix.
     *
     * @param string              $prefix The prefix
     * @param list<string>|string $paths  The PSR-0 base directories
     *
     * @return void
     */
    public function set($prefix, $paths)
    {
        if (!$prefix) {
            $this->fallbackDirsPsr0 = (array) $paths;
        } else {
            $this->prefixesPsr0[$prefix[0]][$prefix] = (array) $paths;
        }
    }

    /**
     * Registers a set of PSR-4 directories for a given namespace,
     * replacing any others previously set for this namespace.
     *
     * @param string              $prefix The prefix/namespace, with trailing '\\'
     * @param list<string>|string $paths  The PSR-4 base directories
     *
     * @throws \InvalidArgumentException
     *
     * @return void
     */
    public function setPsr4($prefix, $paths)
    {
        if (!$prefix) {
            $this->fallbackDirsPsr4 = (array) $paths;
        } else {
            $length = strlen($prefix);
            if ('\\' !== $prefix[$length - 1]) {
                throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
            }
            $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
            $this->prefixDirsPsr4[$prefix] = (array) $paths;
        }
    }

    /**
     * Turns on searching the include path for class files.
     *
     * @param bool $useIncludePath
     *
     * @return void
     */
    public function setUseIncludePath($useIncludePath)
    {
        $this->useIncludePath = $useIncludePath;
    }

    /**
     * Can be used to check if the autoloader uses the include path to check
     * for classes.
     *
     * @return bool
     */
    public function getUseIncludePath()
    {
        return $this->useIncludePath;
    }

    /**
     * Turns off searching the prefix and fallback directories for classes
     * that have not been registered with the class map.
     *
     * @param bool $classMapAuthoritative
     *
     * @return void
     */
    public function setClassMapAuthoritative($classMapAuthoritative)
    {
        $this->classMapAuthoritative = $classMapAuthoritative;
    }

    /**
     * Should class lookup fail if not found in the current class map?
     *
     * @return bool
     */
    public function isClassMapAuthoritative()
    {
        return $this->classMapAuthoritative;
    }

    /**
     * APCu prefix to use to cache found/not-found classes, if the extension is enabled.
     *
     * @param string|null $apcuPrefix
     *
     * @return void
     */
    public function setApcuPrefix($apcuPrefix)
    {
        $this->apcuPrefix = function_exists('apcu_fetch') && filter_var(ini_get('apc.enabled'), FILTER_VALIDATE_BOOLEAN) ? $apcuPrefix : null;
    }

    /**
     * The APCu prefix in use, or null if APCu caching is not enabled.
     *
     * @return string|null
     */
    public function getApcuPrefix()
    {
        return $this->apcuPrefix;
    }

    /**
     * Registers this instance as an autoloader.
     *
     * @param bool $prepend Whether to prepend the autoloader or not
     *
     * @return void
     */
    public function register($prepend = false)
    {
        spl_autoload_register(array($this, 'loadClass'), true, $prepend);

        if (null === $this->vendorDir) {
            return;
        }

        if ($prepend) {
            self::$registeredLoaders = array($this->vendorDir => $this) + self::$registeredLoaders;
        } else {
            unset(self::$registeredLoaders[$this->vendorDir]);
            self::$registeredLoaders[$this->vendorDir] = $this;
        }
    }

    /**
     * Unregisters this instance as an autoloader.
     *
     * @return void
     */
    public function unregister()
    {
        spl_autoload_unregister(array($this, 'loadClass'));

        if (null !== $this->vendorDir) {
            unset(self::$registeredLoaders[$this->vendorDir]);
        }
    }

    /**
     * Loads the given class or interface.
     *
     * @param  string    $class The name of the class
     * @return true|null True if loaded, null otherwise
     */
    public function loadClass($class)
    {
        if ($file = $this->findFile($class)) {
            $includeFile = self::$includeFile;
            $includeFile($file);

            return true;
        }

        return null;
    }

    /**
     * Finds the path to the file where the class is defined.
     *
     * @param string $class The name of the class
     *
     * @return string|false The path if found, false otherwise
     */
    public function findFile($class)
    {
        // class map lookup
        if (isset($this->classMap[$class])) {
            return $this->classMap[$class];
        }
        if ($this->classMapAuthoritative || isset($this->missingClasses[$class])) {
            return false;
        }
        if (null !== $this->apcuPrefix) {
            $file = apcu_fetch($this->apcuPrefix.$class, $hit);
            if ($hit) {
                return $file;
            }
        }

        $file = $this->findFileWithExtension($class, '.php');

        // Search for Hack files if we are running on HHVM
        if (false === $file && defined('HHVM_VERSION')) {
            $file = $this->findFileWithExtension($class, '.hh');
        }

        if (null !== $this->apcuPrefix) {
            apcu_add($this->apcuPrefix.$class, $file);
        }

        if (false === $file) {
            // Remember that this class does not exist.
            $this->missingClasses[$class] = true;
        }

        return $file;
    }

    /**
     * Returns the currently registered loaders keyed by their corresponding vendor directories.
     *
     * @return array<string, self>
     */
    public static function getRegisteredLoaders()
    {
        return self::$registeredLoaders;
    }

    /**
     * @param  string       $class
     * @param  string       $ext
     * @return string|false
     */
    private function findFileWithExtension($class, $ext)
    {
        // PSR-4 lookup
        $logicalPathPsr4 = strtr($class, '\\', DIRECTORY_SEPARATOR) . $ext;

        $first = $class[0];
        if (isset($this->prefixLengthsPsr4[$first])) {
            $subPath = $class;
            while (false !== $lastPos = strrpos($subPath, '\\')) {
                $subPath = substr($subPath, 0, $lastPos);
                $search = $subPath . '\\';
                if (isset($this->prefixDirsPsr4[$search])) {
                    $pathEnd = DIRECTORY_SEPARATOR . substr($logicalPathPsr4, $lastPos + 1);
                    foreach ($this->prefixDirsPsr4[$search] as $dir) {
                        if (file_exists($file = $dir . $pathEnd)) {
                            return $file;
                        }
                    }
                }
            }
        }

        // PSR-4 fallback dirs
        foreach ($this->fallbackDirsPsr4 as $dir) {
            if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr4)) {
                return $file;
            }
        }

        // PSR-0 lookup
        if (false !== $pos = strrpos($class, '\\')) {
            // namespaced class name
            $logicalPathPsr0 = substr($logicalPathPsr4, 0, $pos + 1)
                . strtr(substr($logicalPathPsr4, $pos + 1), '_', DIRECTORY_SEPARATOR);
        } else {
            // PEAR-like class name
            $logicalPathPsr0 = strtr($class, '_', DIRECTORY_SEPARATOR) . $ext;
        }

        if (isset($this->prefixesPsr0[$first])) {
            foreach ($this->prefixesPsr0[$first] as $prefix => $dirs) {
                if (0 === strpos($class, $prefix)) {
                    foreach ($dirs as $dir) {
                        if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {
                            return $file;
                        }
                    }
                }
            }
        }

        // PSR-0 fallback dirs
        foreach ($this->fallbackDirsPsr0 as $dir) {
            if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {
                return $file;
            }
        }

        // PSR-0 include paths.
        if ($this->useIncludePath && $file = stream_resolve_include_path($logicalPathPsr0)) {
            return $file;
        }

        return false;
    }

    /**
     * @return void
     */
    private static function initializeIncludeClosure()
    {
        if (self::$includeFile !== null) {
            return;
        }

        /**
         * Scope isolated include.
         *
         * Prevents access to $this/self from included files.
         *
         * @param  string $file
         * @return void
         */
        self::$includeFile = \Closure::bind(static function($file) {
            include $file;
        }, null, null);
    }
}
<?php

// autoload_psr4.php @generated by Composer

$vendorDir = dirname(__DIR__);
$baseDir = dirname($vendorDir);

return array(
    'HumbugBox468\\KevinGH\\RequirementChecker\\' => array($baseDir . '/src'),
    'HumbugBox468\\Composer\\Semver\\' => array($vendorDir . '/composer/semver/src'),
);
<?php

// autoload_classmap.php @generated by Composer

$vendorDir = dirname(__DIR__);
$baseDir = dirname($vendorDir);

return array(
    'Composer\\InstalledVersions' => $vendorDir . '/composer/InstalledVersions.php',
    'HumbugBox468\\Composer\\Semver\\Comparator' => $vendorDir . '/composer/semver/src/Comparator.php',
    'HumbugBox468\\Composer\\Semver\\CompilingMatcher' => $vendorDir . '/composer/semver/src/CompilingMatcher.php',
    'HumbugBox468\\Composer\\Semver\\Constraint\\Bound' => $vendorDir . '/composer/semver/src/Constraint/Bound.php',
    'HumbugBox468\\Composer\\Semver\\Constraint\\Constraint' => $vendorDir . '/composer/semver/src/Constraint/Constraint.php',
    'HumbugBox468\\Composer\\Semver\\Constraint\\ConstraintInterface' => $vendorDir . '/composer/semver/src/Constraint/ConstraintInterface.php',
    'HumbugBox468\\Composer\\Semver\\Constraint\\MatchAllConstraint' => $vendorDir . '/composer/semver/src/Constraint/MatchAllConstraint.php',
    'HumbugBox468\\Composer\\Semver\\Constraint\\MatchNoneConstraint' => $vendorDir . '/composer/semver/src/Constraint/MatchNoneConstraint.php',
    'HumbugBox468\\Composer\\Semver\\Constraint\\MultiConstraint' => $vendorDir . '/composer/semver/src/Constraint/MultiConstraint.php',
    'HumbugBox468\\Composer\\Semver\\Interval' => $vendorDir . '/composer/semver/src/Interval.php',
    'HumbugBox468\\Composer\\Semver\\Intervals' => $vendorDir . '/composer/semver/src/Intervals.php',
    'HumbugBox468\\Composer\\Semver\\Semver' => $vendorDir . '/composer/semver/src/Semver.php',
    'HumbugBox468\\Composer\\Semver\\VersionParser' => $vendorDir . '/composer/semver/src/VersionParser.php',
    'HumbugBox468\\KevinGH\\RequirementChecker\\Checker' => $baseDir . '/src/Checker.php',
    'HumbugBox468\\KevinGH\\RequirementChecker\\IO' => $baseDir . '/src/IO.php',
    'HumbugBox468\\KevinGH\\RequirementChecker\\IsExtensionConflictFulfilled' => $baseDir . '/src/IsExtensionConflictFulfilled.php',
    'HumbugBox468\\KevinGH\\RequirementChecker\\IsExtensionFulfilled' => $baseDir . '/src/IsExtensionFulfilled.php',
    'HumbugBox468\\KevinGH\\RequirementChecker\\IsFulfilled' => $baseDir . '/src/IsFulfilled.php',
    'HumbugBox468\\KevinGH\\RequirementChecker\\IsPhpVersionFulfilled' => $baseDir . '/src/IsPhpVersionFulfilled.php',
    'HumbugBox468\\KevinGH\\RequirementChecker\\Printer' => $baseDir . '/src/Printer.php',
    'HumbugBox468\\KevinGH\\RequirementChecker\\Requirement' => $baseDir . '/src/Requirement.php',
    'HumbugBox468\\KevinGH\\RequirementChecker\\RequirementCollection' => $baseDir . '/src/RequirementCollection.php',
    'HumbugBox468\\KevinGH\\RequirementChecker\\Terminal' => $baseDir . '/src/Terminal.php',
);
<?php

// autoload_static.php @generated by Composer

namespace Composer\Autoload;

class ComposerStaticInitHumbugBox468
{
    public static $prefixLengthsPsr4 = array (
        'H' => 
        array (
            'HumbugBox468\\KevinGH\\RequirementChecker\\' => 40,
            'HumbugBox468\\Composer\\Semver\\' => 29,
        ),
    );

    public static $prefixDirsPsr4 = array (
        'HumbugBox468\\KevinGH\\RequirementChecker\\' => 
        array (
            0 => __DIR__ . '/../..' . '/src',
        ),
        'HumbugBox468\\Composer\\Semver\\' => 
        array (
            0 => __DIR__ . '/..' . '/composer/semver/src',
        ),
    );

    public static $classMap = array (
        'Composer\\InstalledVersions' => __DIR__ . '/..' . '/composer/InstalledVersions.php',
        'HumbugBox468\\Composer\\Semver\\Comparator' => __DIR__ . '/..' . '/composer/semver/src/Comparator.php',
        'HumbugBox468\\Composer\\Semver\\CompilingMatcher' => __DIR__ . '/..' . '/composer/semver/src/CompilingMatcher.php',
        'HumbugBox468\\Composer\\Semver\\Constraint\\Bound' => __DIR__ . '/..' . '/composer/semver/src/Constraint/Bound.php',
        'HumbugBox468\\Composer\\Semver\\Constraint\\Constraint' => __DIR__ . '/..' . '/composer/semver/src/Constraint/Constraint.php',
        'HumbugBox468\\Composer\\Semver\\Constraint\\ConstraintInterface' => __DIR__ . '/..' . '/composer/semver/src/Constraint/ConstraintInterface.php',
        'HumbugBox468\\Composer\\Semver\\Constraint\\MatchAllConstraint' => __DIR__ . '/..' . '/composer/semver/src/Constraint/MatchAllConstraint.php',
        'HumbugBox468\\Composer\\Semver\\Constraint\\MatchNoneConstraint' => __DIR__ . '/..' . '/composer/semver/src/Constraint/MatchNoneConstraint.php',
        'HumbugBox468\\Composer\\Semver\\Constraint\\MultiConstraint' => __DIR__ . '/..' . '/composer/semver/src/Constraint/MultiConstraint.php',
        'HumbugBox468\\Composer\\Semver\\Interval' => __DIR__ . '/..' . '/composer/semver/src/Interval.php',
        'HumbugBox468\\Composer\\Semver\\Intervals' => __DIR__ . '/..' . '/composer/semver/src/Intervals.php',
        'HumbugBox468\\Composer\\Semver\\Semver' => __DIR__ . '/..' . '/composer/semver/src/Semver.php',
        'HumbugBox468\\Composer\\Semver\\VersionParser' => __DIR__ . '/..' . '/composer/semver/src/VersionParser.php',
        'HumbugBox468\\KevinGH\\RequirementChecker\\Checker' => __DIR__ . '/../..' . '/src/Checker.php',
        'HumbugBox468\\KevinGH\\RequirementChecker\\IO' => __DIR__ . '/../..' . '/src/IO.php',
        'HumbugBox468\\KevinGH\\RequirementChecker\\IsExtensionConflictFulfilled' => __DIR__ . '/../..' . '/src/IsExtensionConflictFulfilled.php',
        'HumbugBox468\\KevinGH\\RequirementChecker\\IsExtensionFulfilled' => __DIR__ . '/../..' . '/src/IsExtensionFulfilled.php',
        'HumbugBox468\\KevinGH\\RequirementChecker\\IsFulfilled' => __DIR__ . '/../..' . '/src/IsFulfilled.php',
        'HumbugBox468\\KevinGH\\RequirementChecker\\IsPhpVersionFulfilled' => __DIR__ . '/../..' . '/src/IsPhpVersionFulfilled.php',
        'HumbugBox468\\KevinGH\\RequirementChecker\\Printer' => __DIR__ . '/../..' . '/src/Printer.php',
        'HumbugBox468\\KevinGH\\RequirementChecker\\Requirement' => __DIR__ . '/../..' . '/src/Requirement.php',
        'HumbugBox468\\KevinGH\\RequirementChecker\\RequirementCollection' => __DIR__ . '/../..' . '/src/RequirementCollection.php',
        'HumbugBox468\\KevinGH\\RequirementChecker\\Terminal' => __DIR__ . '/../..' . '/src/Terminal.php',
    );

    public static function getInitializer(ClassLoader $loader)
    {
        return \Closure::bind(function () use ($loader) {
            $loader->prefixLengthsPsr4 = ComposerStaticInitHumbugBox468::$prefixLengthsPsr4;
            $loader->prefixDirsPsr4 = ComposerStaticInitHumbugBox468::$prefixDirsPsr4;
            $loader->classMap = ComposerStaticInitHumbugBox468::$classMap;

        }, null, ClassLoader::class);
    }
}
<?php

// autoload_real.php @generated by Composer

class ComposerAutoloaderInitHumbugBox468
{
    private static $loader;

    public static function loadClassLoader($class)
    {
        if ('Composer\Autoload\ClassLoader' === $class) {
            require __DIR__ . '/ClassLoader.php';
        }
    }

    /**
     * @return \Composer\Autoload\ClassLoader
     */
    public static function getLoader()
    {
        if (null !== self::$loader) {
            return self::$loader;
        }

        spl_autoload_register(array('ComposerAutoloaderInitHumbugBox468', 'loadClassLoader'), true, true);
        self::$loader = $loader = new \Composer\Autoload\ClassLoader(\dirname(__DIR__));
        spl_autoload_unregister(array('ComposerAutoloaderInitHumbugBox468', 'loadClassLoader'));

        require __DIR__ . '/autoload_static.php';
        call_user_func(\Composer\Autoload\ComposerStaticInitHumbugBox468::getInitializer($loader));

        $loader->setClassMapAuthoritative(true);
        $loader->register(true);

        return $loader;
    }
}
Copyright (C) 2015 Composer

Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
<?php

namespace HumbugBox468\Composer\Semver;

use HumbugBox468\Composer\Semver\Constraint\Constraint;
use HumbugBox468\Composer\Semver\Constraint\ConstraintInterface;
class CompilingMatcher
{
    /**
    @phpstan-var
    */
    private static $compiledCheckerCache = array();
    /**
    @phpstan-var
    */
    private static $resultCache = array();
    private static $enabled;
    /**
    @phpstan-var
    */
    private static $transOpInt = array(Constraint::OP_EQ => Constraint::STR_OP_EQ, Constraint::OP_LT => Constraint::STR_OP_LT, Constraint::OP_LE => Constraint::STR_OP_LE, Constraint::OP_GT => Constraint::STR_OP_GT, Constraint::OP_GE => Constraint::STR_OP_GE, Constraint::OP_NE => Constraint::STR_OP_NE);
    public static function clear()
    {
        self::$resultCache = array();
        self::$compiledCheckerCache = array();
    }
    /**
    @phpstan-param
    */
    public static function match(ConstraintInterface $constraint, $operator, $version)
    {
        $resultCacheKey = $operator . $constraint . ';' . $version;
        if (isset(self::$resultCache[$resultCacheKey])) {
            return self::$resultCache[$resultCacheKey];
        }
        if (self::$enabled === null) {
            self::$enabled = !\in_array('eval', explode(',', (string) ini_get('disable_functions')), \true);
        }
        if (!self::$enabled) {
            return self::$resultCache[$resultCacheKey] = $constraint->matches(new Constraint(self::$transOpInt[$operator], $version));
        }
        $cacheKey = $operator . $constraint;
        if (!isset(self::$compiledCheckerCache[$cacheKey])) {
            $code = $constraint->compile($operator);
            self::$compiledCheckerCache[$cacheKey] = $function = eval('return function($v, $b){return ' . $code . ';};');
        } else {
            $function = self::$compiledCheckerCache[$cacheKey];
        }
        return self::$resultCache[$resultCacheKey] = $function($version, strpos($version, 'dev-') === 0);
    }
}
<?php

namespace HumbugBox468\Composer\Semver;

use HumbugBox468\Composer\Semver\Constraint\Constraint;
class Interval
{
    private $start;
    private $end;
    public function __construct(Constraint $start, Constraint $end)
    {
        $this->start = $start;
        $this->end = $end;
    }
    public function getStart()
    {
        return $this->start;
    }
    public function getEnd()
    {
        return $this->end;
    }
    public static function fromZero()
    {
        static $zero;
        if (null === $zero) {
            $zero = new Constraint('>=', '0.0.0.0-dev');
        }
        return $zero;
    }
    public static function untilPositiveInfinity()
    {
        static $positiveInfinity;
        if (null === $positiveInfinity) {
            $positiveInfinity = new Constraint('<', \PHP_INT_MAX . '.0.0.0');
        }
        return $positiveInfinity;
    }
    public static function any()
    {
        return new self(self::fromZero(), self::untilPositiveInfinity());
    }
    public static function anyDev()
    {
        return array('names' => array(), 'exclude' => \true);
    }
    public static function noDev()
    {
        return array('names' => array(), 'exclude' => \false);
    }
}
<?php

namespace HumbugBox468\Composer\Semver;

use HumbugBox468\Composer\Semver\Constraint\Constraint;
class Comparator
{
    public static function greaterThan($version1, $version2)
    {
        return self::compare($version1, '>', $version2);
    }
    public static function greaterThanOrEqualTo($version1, $version2)
    {
        return self::compare($version1, '>=', $version2);
    }
    public static function lessThan($version1, $version2)
    {
        return self::compare($version1, '<', $version2);
    }
    public static function lessThanOrEqualTo($version1, $version2)
    {
        return self::compare($version1, '<=', $version2);
    }
    public static function equalTo($version1, $version2)
    {
        return self::compare($version1, '==', $version2);
    }
    public static function notEqualTo($version1, $version2)
    {
        return self::compare($version1, '!=', $version2);
    }
    /**
    @phpstan-param
    */
    public static function compare($version1, $operator, $version2)
    {
        $constraint = new Constraint($operator, $version2);
        return $constraint->matchSpecific(new Constraint('==', $version1), \true);
    }
}
<?php

namespace HumbugBox468\Composer\Semver;

use HumbugBox468\Composer\Semver\Constraint\Constraint;
use HumbugBox468\Composer\Semver\Constraint\ConstraintInterface;
use HumbugBox468\Composer\Semver\Constraint\MatchAllConstraint;
use HumbugBox468\Composer\Semver\Constraint\MatchNoneConstraint;
use HumbugBox468\Composer\Semver\Constraint\MultiConstraint;
class Intervals
{
    /**
    @phpstan-var
    */
    private static $intervalsCache = array();
    /**
    @phpstan-var
    */
    private static $opSortOrder = array('>=' => -3, '<' => -2, '>' => 2, '<=' => 3);
    public static function clear()
    {
        self::$intervalsCache = array();
    }
    public static function isSubsetOf(ConstraintInterface $candidate, ConstraintInterface $constraint)
    {
        if ($constraint instanceof MatchAllConstraint) {
            return \true;
        }
        if ($candidate instanceof MatchNoneConstraint || $constraint instanceof MatchNoneConstraint) {
            return \false;
        }
        $intersectionIntervals = self::get(new MultiConstraint(array($candidate, $constraint), \true));
        $candidateIntervals = self::get($candidate);
        if (\count($intersectionIntervals['numeric']) !== \count($candidateIntervals['numeric'])) {
            return \false;
        }
        foreach ($intersectionIntervals['numeric'] as $index => $interval) {
            if (!isset($candidateIntervals['numeric'][$index])) {
                return \false;
            }
            if ((string) $candidateIntervals['numeric'][$index]->getStart() !== (string) $interval->getStart()) {
                return \false;
            }
            if ((string) $candidateIntervals['numeric'][$index]->getEnd() !== (string) $interval->getEnd()) {
                return \false;
            }
        }
        if ($intersectionIntervals['branches']['exclude'] !== $candidateIntervals['branches']['exclude']) {
            return \false;
        }
        if (\count($intersectionIntervals['branches']['names']) !== \count($candidateIntervals['branches']['names'])) {
            return \false;
        }
        foreach ($intersectionIntervals['branches']['names'] as $index => $name) {
            if ($name !== $candidateIntervals['branches']['names'][$index]) {
                return \false;
            }
        }
        return \true;
    }
    public static function haveIntersections(ConstraintInterface $a, ConstraintInterface $b)
    {
        if ($a instanceof MatchAllConstraint || $b instanceof MatchAllConstraint) {
            return \true;
        }
        if ($a instanceof MatchNoneConstraint || $b instanceof MatchNoneConstraint) {
            return \false;
        }
        $intersectionIntervals = self::generateIntervals(new MultiConstraint(array($a, $b), \true), \true);
        return \count($intersectionIntervals['numeric']) > 0 || $intersectionIntervals['branches']['exclude'] || \count($intersectionIntervals['branches']['names']) > 0;
    }
    public static function compactConstraint(ConstraintInterface $constraint)
    {
        if (!$constraint instanceof MultiConstraint) {
            return $constraint;
        }
        $intervals = self::generateIntervals($constraint);
        $constraints = array();
        $hasNumericMatchAll = \false;
        if (\count($intervals['numeric']) === 1 && (string) $intervals['numeric'][0]->getStart() === (string) Interval::fromZero() && (string) $intervals['numeric'][0]->getEnd() === (string) Interval::untilPositiveInfinity()) {
            $constraints[] = $intervals['numeric'][0]->getStart();
            $hasNumericMatchAll = \true;
        } else {
            $unEqualConstraints = array();
            for ($i = 0, $count = \count($intervals['numeric']); $i < $count; $i++) {
                $interval = $intervals['numeric'][$i];
                if ($interval->getEnd()->getOperator() === '<' && $i + 1 < $count) {
                    $nextInterval = $intervals['numeric'][$i + 1];
                    if ($interval->getEnd()->getVersion() === $nextInterval->getStart()->getVersion() && $nextInterval->getStart()->getOperator() === '>') {
                        if (\count($unEqualConstraints) === 0 && (string) $interval->getStart() !== (string) Interval::fromZero()) {
                            $unEqualConstraints[] = $interval->getStart();
                        }
                        $unEqualConstraints[] = new Constraint('!=', $interval->getEnd()->getVersion());
                        continue;
                    }
                }
                if (\count($unEqualConstraints) > 0) {
                    if ((string) $interval->getEnd() !== (string) Interval::untilPositiveInfinity()) {
                        $unEqualConstraints[] = $interval->getEnd();
                    }
                    if (\count($unEqualConstraints) > 1) {
                        $constraints[] = new MultiConstraint($unEqualConstraints, \true);
                    } else {
                        $constraints[] = $unEqualConstraints[0];
                    }
                    $unEqualConstraints = array();
                    continue;
                }
                if ($interval->getStart()->getVersion() === $interval->getEnd()->getVersion() && $interval->getStart()->getOperator() === '>=' && $interval->getEnd()->getOperator() === '<=') {
                    $constraints[] = new Constraint('==', $interval->getStart()->getVersion());
                    continue;
                }
                if ((string) $interval->getStart() === (string) Interval::fromZero()) {
                    $constraints[] = $interval->getEnd();
                } elseif ((string) $interval->getEnd() === (string) Interval::untilPositiveInfinity()) {
                    $constraints[] = $interval->getStart();
                } else {
                    $constraints[] = new MultiConstraint(array($interval->getStart(), $interval->getEnd()), \true);
                }
            }
        }
        $devConstraints = array();
        if (0 === \count($intervals['branches']['names'])) {
            if ($intervals['branches']['exclude']) {
                if ($hasNumericMatchAll) {
                    return new MatchAllConstraint();
                }
            }
        } else {
            foreach ($intervals['branches']['names'] as $branchName) {
                if ($intervals['branches']['exclude']) {
                    $devConstraints[] = new Constraint('!=', $branchName);
                } else {
                    $devConstraints[] = new Constraint('==', $branchName);
                }
            }
            if ($intervals['branches']['exclude']) {
                if (\count($constraints) > 1) {
                    return new MultiConstraint(array_merge(array(new MultiConstraint($constraints, \false)), $devConstraints), \true);
                }
                if (\count($constraints) === 1 && (string) $constraints[0] === (string) Interval::fromZero()) {
                    if (\count($devConstraints) > 1) {
                        return new MultiConstraint($devConstraints, \true);
                    }
                    return $devConstraints[0];
                }
                return new MultiConstraint(array_merge($constraints, $devConstraints), \true);
            }
            $constraints = array_merge($constraints, $devConstraints);
        }
        if (\count($constraints) > 1) {
            return new MultiConstraint($constraints, \false);
        }
        if (\count($constraints) === 1) {
            return $constraints[0];
        }
        return new MatchNoneConstraint();
    }
    /**
    @phpstan-return
    */
    public static function get(ConstraintInterface $constraint)
    {
        $key = (string) $constraint;
        if (!isset(self::$intervalsCache[$key])) {
            self::$intervalsCache[$key] = self::generateIntervals($constraint);
        }
        return self::$intervalsCache[$key];
    }
    /**
    @phpstan-return
    */
    private static function generateIntervals(ConstraintInterface $constraint, $stopOnFirstValidInterval = \false)
    {
        if ($constraint instanceof MatchAllConstraint) {
            return array('numeric' => array(new Interval(Interval::fromZero(), Interval::untilPositiveInfinity())), 'branches' => Interval::anyDev());
        }
        if ($constraint instanceof MatchNoneConstraint) {
            return array('numeric' => array(), 'branches' => array('names' => array(), 'exclude' => \false));
        }
        if ($constraint instanceof Constraint) {
            return self::generateSingleConstraintIntervals($constraint);
        }
        if (!$constraint instanceof MultiConstraint) {
            throw new \UnexpectedValueException('The constraint passed in should be an MatchAllConstraint, Constraint or MultiConstraint instance, got ' . \get_class($constraint) . '.');
        }
        $constraints = $constraint->getConstraints();
        $numericGroups = array();
        $constraintBranches = array();
        foreach ($constraints as $c) {
            $res = self::get($c);
            $numericGroups[] = $res['numeric'];
            $constraintBranches[] = $res['branches'];
        }
        if ($constraint->isDisjunctive()) {
            $branches = Interval::noDev();
            foreach ($constraintBranches as $b) {
                if ($b['exclude']) {
                    if ($branches['exclude']) {
                        $branches['names'] = array_intersect($branches['names'], $b['names']);
                    } else {
                        $branches['exclude'] = \true;
                        $branches['names'] = array_diff($b['names'], $branches['names']);
                    }
                } else if ($branches['exclude']) {
                    $branches['names'] = array_diff($branches['names'], $b['names']);
                } else {
                    $branches['names'] = array_merge($branches['names'], $b['names']);
                }
            }
        } else {
            $branches = Interval::anyDev();
            foreach ($constraintBranches as $b) {
                if ($b['exclude']) {
                    if ($branches['exclude']) {
                        $branches['names'] = array_merge($branches['names'], $b['names']);
                    } else {
                        $branches['names'] = array_diff($branches['names'], $b['names']);
                    }
                } else if ($branches['exclude']) {
                    $branches['names'] = array_diff($b['names'], $branches['names']);
                    $branches['exclude'] = \false;
                } else {
                    $branches['names'] = array_intersect($branches['names'], $b['names']);
                }
            }
        }
        $branches['names'] = array_unique($branches['names']);
        if (\count($numericGroups) === 1) {
            return array('numeric' => $numericGroups[0], 'branches' => $branches);
        }
        $borders = array();
        foreach ($numericGroups as $group) {
            foreach ($group as $interval) {
                $borders[] = array('version' => $interval->getStart()->getVersion(), 'operator' => $interval->getStart()->getOperator(), 'side' => 'start');
                $borders[] = array('version' => $interval->getEnd()->getVersion(), 'operator' => $interval->getEnd()->getOperator(), 'side' => 'end');
            }
        }
        $opSortOrder = self::$opSortOrder;
        usort($borders, function ($a, $b) use ($opSortOrder) {
            $order = version_compare($a['version'], $b['version']);
            if ($order === 0) {
                return $opSortOrder[$a['operator']] - $opSortOrder[$b['operator']];
            }
            return $order;
        });
        $activeIntervals = 0;
        $intervals = array();
        $index = 0;
        $activationThreshold = $constraint->isConjunctive() ? \count($numericGroups) : 1;
        $start = null;
        foreach ($borders as $border) {
            if ($border['side'] === 'start') {
                $activeIntervals++;
            } else {
                $activeIntervals--;
            }
            if (!$start && $activeIntervals >= $activationThreshold) {
                $start = new Constraint($border['operator'], $border['version']);
            } elseif ($start && $activeIntervals < $activationThreshold) {
                if (version_compare($start->getVersion(), $border['version'], '=') && ($start->getOperator() === '>' && $border['operator'] === '<=' || $start->getOperator() === '>=' && $border['operator'] === '<')) {
                    unset($intervals[$index]);
                } else {
                    $intervals[$index] = new Interval($start, new Constraint($border['operator'], $border['version']));
                    $index++;
                    if ($stopOnFirstValidInterval) {
                        break;
                    }
                }
                $start = null;
            }
        }
        return array('numeric' => $intervals, 'branches' => $branches);
    }
    /**
    @phpstan-return
    */
    private static function generateSingleConstraintIntervals(Constraint $constraint)
    {
        $op = $constraint->getOperator();
        if (strpos($constraint->getVersion(), 'dev-') === 0) {
            $intervals = array();
            $branches = array('names' => array(), 'exclude' => \false);
            if ($op === '!=') {
                $intervals[] = new Interval(Interval::fromZero(), Interval::untilPositiveInfinity());
                $branches = array('names' => array($constraint->getVersion()), 'exclude' => \true);
            } elseif ($op === '==') {
                $branches['names'][] = $constraint->getVersion();
            }
            return array('numeric' => $intervals, 'branches' => $branches);
        }
        if ($op[0] === '>') {
            return array('numeric' => array(new Interval($constraint, Interval::untilPositiveInfinity())), 'branches' => Interval::noDev());
        }
        if ($op[0] === '<') {
            return array('numeric' => array(new Interval(Interval::fromZero(), $constraint)), 'branches' => Interval::noDev());
        }
        if ($op === '!=') {
            return array('numeric' => array(new Interval(Interval::fromZero(), new Constraint('<', $constraint->getVersion())), new Interval(new Constraint('>', $constraint->getVersion()), Interval::untilPositiveInfinity())), 'branches' => Interval::anyDev());
        }
        return array('numeric' => array(new Interval(new Constraint('>=', $constraint->getVersion()), new Constraint('<=', $constraint->getVersion()))), 'branches' => Interval::noDev());
    }
}
<?php

namespace HumbugBox468\Composer\Semver;

use HumbugBox468\Composer\Semver\Constraint\Constraint;
class Semver
{
    const SORT_ASC = 1;
    const SORT_DESC = -1;
    private static $versionParser;
    public static function satisfies($version, $constraints)
    {
        if (null === self::$versionParser) {
            self::$versionParser = new VersionParser();
        }
        $versionParser = self::$versionParser;
        $provider = new Constraint('==', $versionParser->normalize($version));
        $parsedConstraints = $versionParser->parseConstraints($constraints);
        return $parsedConstraints->matches($provider);
    }
    public static function satisfiedBy(array $versions, $constraints)
    {
        $versions = array_filter($versions, function ($version) use ($constraints) {
            return Semver::satisfies($version, $constraints);
        });
        return array_values($versions);
    }
    public static function sort(array $versions)
    {
        return self::usort($versions, self::SORT_ASC);
    }
    public static function rsort(array $versions)
    {
        return self::usort($versions, self::SORT_DESC);
    }
    private static function usort(array $versions, $direction)
    {
        if (null === self::$versionParser) {
            self::$versionParser = new VersionParser();
        }
        $versionParser = self::$versionParser;
        $normalized = array();
        foreach ($versions as $key => $version) {
            $normalizedVersion = $versionParser->normalize($version);
            $normalizedVersion = $versionParser->normalizeDefaultBranch($normalizedVersion);
            $normalized[] = array($normalizedVersion, $key);
        }
        usort($normalized, function (array $left, array $right) use ($direction) {
            if ($left[0] === $right[0]) {
                return 0;
            }
            if (Comparator::lessThan($left[0], $right[0])) {
                return -$direction;
            }
            return $direction;
        });
        $sorted = array();
        foreach ($normalized as $item) {
            $sorted[] = $versions[$item[1]];
        }
        return $sorted;
    }
}
<?php

namespace HumbugBox468\Composer\Semver;

use HumbugBox468\Composer\Semver\Constraint\ConstraintInterface;
use HumbugBox468\Composer\Semver\Constraint\MatchAllConstraint;
use HumbugBox468\Composer\Semver\Constraint\MultiConstraint;
use HumbugBox468\Composer\Semver\Constraint\Constraint;
class VersionParser
{
    private static $modifierRegex = '[._-]?(?:(stable|beta|b|RC|alpha|a|patch|pl|p)((?:[.-]?\d+)*+)?)?([.-]?dev)?';
    private static $stabilitiesRegex = 'stable|RC|beta|alpha|dev';
    /**
    @phpstan-return
    */
    public static function parseStability($version)
    {
        $version = (string) preg_replace('{#.+$}', '', (string) $version);
        if (strpos($version, 'dev-') === 0 || '-dev' === substr($version, -4)) {
            return 'dev';
        }
        preg_match('{' . self::$modifierRegex . '(?:\+.*)?$}i', strtolower($version), $match);
        if (!empty($match[3])) {
            return 'dev';
        }
        if (!empty($match[1])) {
            if ('beta' === $match[1] || 'b' === $match[1]) {
                return 'beta';
            }
            if ('alpha' === $match[1] || 'a' === $match[1]) {
                return 'alpha';
            }
            if ('rc' === $match[1]) {
                return 'RC';
            }
        }
        return 'stable';
    }
    public static function normalizeStability($stability)
    {
        $stability = strtolower((string) $stability);
        return $stability === 'rc' ? 'RC' : $stability;
    }
    public function normalize($version, $fullVersion = null)
    {
        $version = trim((string) $version);
        $origVersion = $version;
        if (null === $fullVersion) {
            $fullVersion = $version;
        }
        if (preg_match('{^([^,\s]++) ++as ++([^,\s]++)$}', $version, $match)) {
            $version = $match[1];
        }
        if (preg_match('{@(?:' . self::$stabilitiesRegex . ')$}i', $version, $match)) {
            $version = substr($version, 0, strlen($version) - strlen($match[0]));
        }
        if (\in_array($version, array('master', 'trunk', 'default'), \true)) {
            $version = 'dev-' . $version;
        }
        if (stripos($version, 'dev-') === 0) {
            return 'dev-' . substr($version, 4);
        }
        if (preg_match('{^([^,\s+]++)\+[^\s]++$}', $version, $match)) {
            $version = $match[1];
        }
        if (preg_match('{^v?(\d{1,5}+)(\.\d++)?(\.\d++)?(\.\d++)?' . self::$modifierRegex . '$}i', $version, $matches)) {
            $version = $matches[1] . (!empty($matches[2]) ? $matches[2] : '.0') . (!empty($matches[3]) ? $matches[3] : '.0') . (!empty($matches[4]) ? $matches[4] : '.0');
            $index = 5;
        } elseif (preg_match('{^v?(\d{4}(?:[.:-]?\d{2}){1,6}(?:[.:-]?\d{1,3}){0,2})' . self::$modifierRegex . '$}i', $version, $matches)) {
            $version = (string) preg_replace('{\D}', '.', $matches[1]);
            $index = 2;
        }
        if (isset($index)) {
            if (!empty($matches[$index])) {
                if ('stable' === $matches[$index]) {
                    return $version;
                }
                $version .= '-' . $this->expandStability($matches[$index]) . (isset($matches[$index + 1]) && '' !== $matches[$index + 1] ? ltrim($matches[$index + 1], '.-') : '');
            }
            if (!empty($matches[$index + 2])) {
                $version .= '-dev';
            }
            return $version;
        }
        if (preg_match('{(.*?)[.-]?dev$}i', $version, $match)) {
            try {
                $normalized = $this->normalizeBranch($match[1]);
                if (strpos($normalized, 'dev-') === \false) {
                    return $normalized;
                }
            } catch (\Exception $e) {
            }
        }
        $extraMessage = '';
        if (preg_match('{ +as +' . preg_quote($version) . '(?:@(?:' . self::$stabilitiesRegex . '))?$}', $fullVersion)) {
            $extraMessage = ' in "' . $fullVersion . '", the alias must be an exact version';
        } elseif (preg_match('{^' . preg_quote($version) . '(?:@(?:' . self::$stabilitiesRegex . '))? +as +}', $fullVersion)) {
            $extraMessage = ' in "' . $fullVersion . '", the alias source must be an exact version, if it is a branch name you should prefix it with dev-';
        }
        throw new \UnexpectedValueException('Invalid version string "' . $origVersion . '"' . $extraMessage);
    }
    public function parseNumericAliasPrefix($branch)
    {
        if (preg_match('{^(?P<version>(\d++\.)*\d++)(?:\.x)?-dev$}i', (string) $branch, $matches)) {
            return $matches['version'] . '.';
        }
        return \false;
    }
    public function normalizeBranch($name)
    {
        $name = trim((string) $name);
        if (preg_match('{^v?(\d++)(\.(?:\d++|[xX*]))?(\.(?:\d++|[xX*]))?(\.(?:\d++|[xX*]))?$}i', $name, $matches)) {
            $version = '';
            for ($i = 1; $i < 5; ++$i) {
                $version .= isset($matches[$i]) ? str_replace(array('*', 'X'), 'x', $matches[$i]) : '.x';
            }
            return str_replace('x', '9999999', $version) . '-dev';
        }
        return 'dev-' . $name;
    }
    public function normalizeDefaultBranch($name)
    {
        if ($name === 'dev-master' || $name === 'dev-default' || $name === 'dev-trunk') {
            return '9999999-dev';
        }
        return (string) $name;
    }
    public function parseConstraints($constraints)
    {
        $prettyConstraint = (string) $constraints;
        $orConstraints = preg_split('{\s*\|\|?\s*}', trim((string) $constraints));
        if (\false === $orConstraints) {
            throw new \RuntimeException('Failed to preg_split string: ' . $constraints);
        }
        $orGroups = array();
        foreach ($orConstraints as $orConstraint) {
            $andConstraints = preg_split('{(?<!^|as|[=>< ,]) *(?<!-)[, ](?!-) *(?!,|as|$)}', $orConstraint);
            if (\false === $andConstraints) {
                throw new \RuntimeException('Failed to preg_split string: ' . $orConstraint);
            }
            if (\count($andConstraints) > 1) {
                $constraintObjects = array();
                foreach ($andConstraints as $andConstraint) {
                    foreach ($this->parseConstraint($andConstraint) as $parsedAndConstraint) {
                        $constraintObjects[] = $parsedAndConstraint;
                    }
                }
            } else {
                $constraintObjects = $this->parseConstraint($andConstraints[0]);
            }
            if (1 === \count($constraintObjects)) {
                $constraint = $constraintObjects[0];
            } else {
                $constraint = new MultiConstraint($constraintObjects);
            }
            $orGroups[] = $constraint;
        }
        $parsedConstraint = MultiConstraint::create($orGroups, \false);
        $parsedConstraint->setPrettyString($prettyConstraint);
        return $parsedConstraint;
    }
    /**
    @phpstan-return
    */
    private function parseConstraint($constraint)
    {
        if (preg_match('{^([^,\s]++) ++as ++([^,\s]++)$}', $constraint, $match)) {
            $constraint = $match[1];
        }
        if (preg_match('{^([^,\s]*?)@(' . self::$stabilitiesRegex . ')$}i', $constraint, $match)) {
            $constraint = '' !== $match[1] ? $match[1] : '*';
            if ($match[2] !== 'stable') {
                $stabilityModifier = $match[2];
            }
        }
        if (preg_match('{^(dev-[^,\s@]+?|[^,\s@]+?\.x-dev)#.+$}i', $constraint, $match)) {
            $constraint = $match[1];
        }
        if (preg_match('{^(v)?[xX*](\.[xX*])*$}i', $constraint, $match)) {
            if (!empty($match[1]) || !empty($match[2])) {
                return array(new Constraint('>=', '0.0.0.0-dev'));
            }
            return array(new MatchAllConstraint());
        }
        $versionRegex = 'v?(\d++)(?:\.(\d++))?(?:\.(\d++))?(?:\.(\d++))?(?:' . self::$modifierRegex . '|\.([xX*][.-]?dev))(?:\+[^\s]+)?';
        if (preg_match('{^~>?' . $versionRegex . '$}i', $constraint, $matches)) {
            if (strpos($constraint, '~>') === 0) {
                throw new \UnexpectedValueException('Could not parse version constraint ' . $constraint . ': ' . 'Invalid operator "~>", you probably meant to use the "~" operator');
            }
            if (isset($matches[4]) && '' !== $matches[4] && null !== $matches[4]) {
                $position = 4;
            } elseif (isset($matches[3]) && '' !== $matches[3] && null !== $matches[3]) {
                $position = 3;
            } elseif (isset($matches[2]) && '' !== $matches[2] && null !== $matches[2]) {
                $position = 2;
            } else {
                $position = 1;
            }
            if (!empty($matches[8])) {
                $position++;
            }
            $stabilitySuffix = '';
            if (empty($matches[5]) && empty($matches[7]) && empty($matches[8])) {
                $stabilitySuffix .= '-dev';
            }
            $lowVersion = $this->normalize(substr($constraint . $stabilitySuffix, 1));
            $lowerBound = new Constraint('>=', $lowVersion);
            $highPosition = max(1, $position - 1);
            $highVersion = $this->manipulateVersionString($matches, $highPosition, 1) . '-dev';
            $upperBound = new Constraint('<', $highVersion);
            return array($lowerBound, $upperBound);
        }
        if (preg_match('{^\^' . $versionRegex . '($)}i', $constraint, $matches)) {
            if ('0' !== $matches[1] || '' === $matches[2] || null === $matches[2]) {
                $position = 1;
            } elseif ('0' !== $matches[2] || '' === $matches[3] || null === $matches[3]) {
                $position = 2;
            } else {
                $position = 3;
            }
            $stabilitySuffix = '';
            if (empty($matches[5]) && empty($matches[7]) && empty($matches[8])) {
                $stabilitySuffix .= '-dev';
            }
            $lowVersion = $this->normalize(substr($constraint . $stabilitySuffix, 1));
            $lowerBound = new Constraint('>=', $lowVersion);
            $highVersion = $this->manipulateVersionString($matches, $position, 1) . '-dev';
            $upperBound = new Constraint('<', $highVersion);
            return array($lowerBound, $upperBound);
        }
        if (preg_match('{^v?(\d++)(?:\.(\d++))?(?:\.(\d++))?(?:\.[xX*])++$}', $constraint, $matches)) {
            if (isset($matches[3]) && '' !== $matches[3] && null !== $matches[3]) {
                $position = 3;
            } elseif (isset($matches[2]) && '' !== $matches[2] && null !== $matches[2]) {
                $position = 2;
            } else {
                $position = 1;
            }
            $lowVersion = $this->manipulateVersionString($matches, $position) . '-dev';
            $highVersion = $this->manipulateVersionString($matches, $position, 1) . '-dev';
            if ($lowVersion === '0.0.0.0-dev') {
                return array(new Constraint('<', $highVersion));
            }
            return array(new Constraint('>=', $lowVersion), new Constraint('<', $highVersion));
        }
        if (preg_match('{^(?P<from>' . $versionRegex . ') +- +(?P<to>' . $versionRegex . ')($)}i', $constraint, $matches)) {
            $lowStabilitySuffix = '';
            if (empty($matches[6]) && empty($matches[8]) && empty($matches[9])) {
                $lowStabilitySuffix = '-dev';
            }
            $lowVersion = $this->normalize($matches['from']);
            $lowerBound = new Constraint('>=', $lowVersion . $lowStabilitySuffix);
            $empty = function ($x) {
                return $x === 0 || $x === '0' ? \false : empty($x);
            };
            if (!$empty($matches[12]) && !$empty($matches[13]) || !empty($matches[15]) || !empty($matches[17]) || !empty($matches[18])) {
                $highVersion = $this->normalize($matches['to']);
                $upperBound = new Constraint('<=', $highVersion);
            } else {
                $highMatch = array('', $matches[11], $matches[12], $matches[13], $matches[14]);
                $this->normalize($matches['to']);
                $highVersion = $this->manipulateVersionString($highMatch, $empty($matches[12]) ? 1 : 2, 1) . '-dev';
                $upperBound = new Constraint('<', $highVersion);
            }
            return array($lowerBound, $upperBound);
        }
        if (preg_match('{^(<>|!=|>=?|<=?|==?)?\s*(.*)}', $constraint, $matches)) {
            try {
                try {
                    $version = $this->normalize($matches[2]);
                } catch (\UnexpectedValueException $e) {
                    if (substr($matches[2], -4) === '-dev' && preg_match('{^[0-9a-zA-Z-./]+$}', $matches[2])) {
                        $version = $this->normalize('dev-' . substr($matches[2], 0, -4));
                    } else {
                        throw $e;
                    }
                }
                $op = $matches[1] ?: '=';
                if ($op !== '==' && $op !== '=' && !empty($stabilityModifier) && self::parseStability($version) === 'stable') {
                    $version .= '-' . $stabilityModifier;
                } elseif ('<' === $op || '>=' === $op) {
                    if (!preg_match('/-' . self::$modifierRegex . '$/', strtolower($matches[2]))) {
                        if (strpos($matches[2], 'dev-') !== 0) {
                            $version .= '-dev';
                        }
                    }
                }
                return array(new Constraint($matches[1] ?: '=', $version));
            } catch (\Exception $e) {
            }
        }
        $message = 'Could not parse version constraint ' . $constraint;
        if (isset($e)) {
            $message .= ': ' . $e->getMessage();
        }
        throw new \UnexpectedValueException($message);
    }
    /**
    @phpstan-param
    */
    private function manipulateVersionString(array $matches, $position, $increment = 0, $pad = '0')
    {
        for ($i = 4; $i > 0; --$i) {
            if ($i > $position) {
                $matches[$i] = $pad;
            } elseif ($i === $position && $increment) {
                $matches[$i] += $increment;
                if ($matches[$i] < 0) {
                    $matches[$i] = $pad;
                    --$position;
                    if ($i === 1) {
                        return null;
                    }
                }
            }
        }
        return $matches[1] . '.' . $matches[2] . '.' . $matches[3] . '.' . $matches[4];
    }
    private function expandStability($stability)
    {
        $stability = strtolower($stability);
        switch ($stability) {
            case 'a':
                return 'alpha';
            case 'b':
                return 'beta';
            case 'p':
            case 'pl':
                return 'patch';
            case 'rc':
                return 'RC';
            default:
                return $stability;
        }
    }
}
<?php

namespace HumbugBox468\Composer\Semver\Constraint;

interface ConstraintInterface
{
    public function matches(ConstraintInterface $provider);
    /**
    @phpstan-param
    */
    public function compile($otherOperator);
    public function getUpperBound();
    public function getLowerBound();
    public function getPrettyString();
    public function setPrettyString($prettyString);
    public function __toString();
}
<?php

namespace HumbugBox468\Composer\Semver\Constraint;

class MultiConstraint implements ConstraintInterface
{
    /**
    @phpstan-var
    */
    protected $constraints;
    protected $prettyString;
    protected $string;
    protected $conjunctive;
    protected $lowerBound;
    protected $upperBound;
    public function __construct(array $constraints, $conjunctive = \true)
    {
        if (\count($constraints) < 2) {
            throw new \InvalidArgumentException('Must provide at least two constraints for a MultiConstraint. Use ' . 'the regular Constraint class for one constraint only or MatchAllConstraint for none. You may use ' . 'MultiConstraint::create() which optimizes and handles those cases automatically.');
        }
        $this->constraints = $constraints;
        $this->conjunctive = $conjunctive;
    }
    public function getConstraints()
    {
        return $this->constraints;
    }
    public function isConjunctive()
    {
        return $this->conjunctive;
    }
    public function isDisjunctive()
    {
        return !$this->conjunctive;
    }
    public function compile($otherOperator)
    {
        $parts = array();
        foreach ($this->constraints as $constraint) {
            $code = $constraint->compile($otherOperator);
            if ($code === 'true') {
                if (!$this->conjunctive) {
                    return 'true';
                }
            } elseif ($code === 'false') {
                if ($this->conjunctive) {
                    return 'false';
                }
            } else {
                $parts[] = '(' . $code . ')';
            }
        }
        if (!$parts) {
            return $this->conjunctive ? 'true' : 'false';
        }
        return $this->conjunctive ? implode('&&', $parts) : implode('||', $parts);
    }
    public function matches(ConstraintInterface $provider)
    {
        if (\false === $this->conjunctive) {
            foreach ($this->constraints as $constraint) {
                if ($provider->matches($constraint)) {
                    return \true;
                }
            }
            return \false;
        }
        if ($provider instanceof MultiConstraint && $provider->isDisjunctive()) {
            return $provider->matches($this);
        }
        foreach ($this->constraints as $constraint) {
            if (!$provider->matches($constraint)) {
                return \false;
            }
        }
        return \true;
    }
    public function setPrettyString($prettyString)
    {
        $this->prettyString = $prettyString;
    }
    public function getPrettyString()
    {
        if ($this->prettyString) {
            return $this->prettyString;
        }
        return (string) $this;
    }
    public function __toString()
    {
        if ($this->string !== null) {
            return $this->string;
        }
        $constraints = array();
        foreach ($this->constraints as $constraint) {
            $constraints[] = (string) $constraint;
        }
        return $this->string = '[' . implode($this->conjunctive ? ' ' : ' || ', $constraints) . ']';
    }
    public function getLowerBound()
    {
        $this->extractBounds();
        if (null === $this->lowerBound) {
            throw new \LogicException('extractBounds should have populated the lowerBound property');
        }
        return $this->lowerBound;
    }
    public function getUpperBound()
    {
        $this->extractBounds();
        if (null === $this->upperBound) {
            throw new \LogicException('extractBounds should have populated the upperBound property');
        }
        return $this->upperBound;
    }
    public static function create(array $constraints, $conjunctive = \true)
    {
        if (0 === \count($constraints)) {
            return new MatchAllConstraint();
        }
        if (1 === \count($constraints)) {
            return $constraints[0];
        }
        $optimized = self::optimizeConstraints($constraints, $conjunctive);
        if ($optimized !== null) {
            list($constraints, $conjunctive) = $optimized;
            if (\count($constraints) === 1) {
                return $constraints[0];
            }
        }
        return new self($constraints, $conjunctive);
    }
    /**
    @phpstan-return
    */
    private static function optimizeConstraints(array $constraints, $conjunctive)
    {
        if (!$conjunctive) {
            $left = $constraints[0];
            $mergedConstraints = array();
            $optimized = \false;
            for ($i = 1, $l = \count($constraints); $i < $l; $i++) {
                $right = $constraints[$i];
                if ($left instanceof self && $left->conjunctive && $right instanceof self && $right->conjunctive && \count($left->constraints) === 2 && \count($right->constraints) === 2 && ($left0 = (string) $left->constraints[0]) && $left0[0] === '>' && $left0[1] === '=' && ($left1 = (string) $left->constraints[1]) && $left1[0] === '<' && ($right0 = (string) $right->constraints[0]) && $right0[0] === '>' && $right0[1] === '=' && ($right1 = (string) $right->constraints[1]) && $right1[0] === '<' && substr($left1, 2) === substr($right0, 3)) {
                    $optimized = \true;
                    $left = new MultiConstraint(array($left->constraints[0], $right->constraints[1]), \true);
                } else {
                    $mergedConstraints[] = $left;
                    $left = $right;
                }
            }
            if ($optimized) {
                $mergedConstraints[] = $left;
                return array($mergedConstraints, \false);
            }
        }
        return null;
    }
    private function extractBounds()
    {
        if (null !== $this->lowerBound) {
            return;
        }
        foreach ($this->constraints as $constraint) {
            if (null === $this->lowerBound || null === $this->upperBound) {
                $this->lowerBound = $constraint->getLowerBound();
                $this->upperBound = $constraint->getUpperBound();
                continue;
            }
            if ($constraint->getLowerBound()->compareTo($this->lowerBound, $this->isConjunctive() ? '>' : '<')) {
                $this->lowerBound = $constraint->getLowerBound();
            }
            if ($constraint->getUpperBound()->compareTo($this->upperBound, $this->isConjunctive() ? '<' : '>')) {
                $this->upperBound = $constraint->getUpperBound();
            }
        }
    }
}
<?php

namespace HumbugBox468\Composer\Semver\Constraint;

class Constraint implements ConstraintInterface
{
    const OP_EQ = 0;
    const OP_LT = 1;
    const OP_LE = 2;
    const OP_GT = 3;
    const OP_GE = 4;
    const OP_NE = 5;
    const STR_OP_EQ = '==';
    const STR_OP_EQ_ALT = '=';
    const STR_OP_LT = '<';
    const STR_OP_LE = '<=';
    const STR_OP_GT = '>';
    const STR_OP_GE = '>=';
    const STR_OP_NE = '!=';
    const STR_OP_NE_ALT = '<>';
    /**
    @phpstan-var
    */
    private static $transOpStr = array('=' => self::OP_EQ, '==' => self::OP_EQ, '<' => self::OP_LT, '<=' => self::OP_LE, '>' => self::OP_GT, '>=' => self::OP_GE, '<>' => self::OP_NE, '!=' => self::OP_NE);
    /**
    @phpstan-var
    */
    private static $transOpInt = array(self::OP_EQ => '==', self::OP_LT => '<', self::OP_LE => '<=', self::OP_GT => '>', self::OP_GE => '>=', self::OP_NE => '!=');
    /**
    @phpstan-var
    */
    protected $operator;
    protected $version;
    protected $prettyString;
    protected $lowerBound;
    protected $upperBound;
    /**
    @phpstan-param
    */
    public function __construct($operator, $version)
    {
        if (!isset(self::$transOpStr[$operator])) {
            throw new \InvalidArgumentException(sprintf('Invalid operator "%s" given, expected one of: %s', $operator, implode(', ', self::getSupportedOperators())));
        }
        $this->operator = self::$transOpStr[$operator];
        $this->version = $version;
    }
    public function getVersion()
    {
        return $this->version;
    }
    /**
    @phpstan-return
    */
    public function getOperator()
    {
        return self::$transOpInt[$this->operator];
    }
    public function matches(ConstraintInterface $provider)
    {
        if ($provider instanceof self) {
            return $this->matchSpecific($provider);
        }
        return $provider->matches($this);
    }
    public function setPrettyString($prettyString)
    {
        $this->prettyString = $prettyString;
    }
    public function getPrettyString()
    {
        if ($this->prettyString) {
            return $this->prettyString;
        }
        return $this->__toString();
    }
    /**
    @phpstan-return
    */
    public static function getSupportedOperators()
    {
        return array_keys(self::$transOpStr);
    }
    /**
    @phpstan-param
    @phpstan-return
    */
    public static function getOperatorConstant($operator)
    {
        return self::$transOpStr[$operator];
    }
    /**
    @phpstan-param
    */
    public function versionCompare($a, $b, $operator, $compareBranches = \false)
    {
        if (!isset(self::$transOpStr[$operator])) {
            throw new \InvalidArgumentException(sprintf('Invalid operator "%s" given, expected one of: %s', $operator, implode(', ', self::getSupportedOperators())));
        }
        $aIsBranch = strpos($a, 'dev-') === 0;
        $bIsBranch = strpos($b, 'dev-') === 0;
        if ($operator === '!=' && ($aIsBranch || $bIsBranch)) {
            return $a !== $b;
        }
        if ($aIsBranch && $bIsBranch) {
            return $operator === '==' && $a === $b;
        }
        if (!$compareBranches && ($aIsBranch || $bIsBranch)) {
            return \false;
        }
        return \version_compare($a, $b, $operator);
    }
    public function compile($otherOperator)
    {
        if (strpos($this->version, 'dev-') === 0) {
            if (self::OP_EQ === $this->operator) {
                if (self::OP_EQ === $otherOperator) {
                    return sprintf('$b && $v === %s', \var_export($this->version, \true));
                }
                if (self::OP_NE === $otherOperator) {
                    return sprintf('!$b || $v !== %s', \var_export($this->version, \true));
                }
                return 'false';
            }
            if (self::OP_NE === $this->operator) {
                if (self::OP_EQ === $otherOperator) {
                    return sprintf('!$b || $v !== %s', \var_export($this->version, \true));
                }
                if (self::OP_NE === $otherOperator) {
                    return 'true';
                }
                return '!$b';
            }
            return 'false';
        }
        if (self::OP_EQ === $this->operator) {
            if (self::OP_EQ === $otherOperator) {
                return sprintf('\version_compare($v, %s, \'==\')', \var_export($this->version, \true));
            }
            if (self::OP_NE === $otherOperator) {
                return sprintf('$b || \version_compare($v, %s, \'!=\')', \var_export($this->version, \true));
            }
            return sprintf('!$b && \version_compare(%s, $v, \'%s\')', \var_export($this->version, \true), self::$transOpInt[$otherOperator]);
        }
        if (self::OP_NE === $this->operator) {
            if (self::OP_EQ === $otherOperator) {
                return sprintf('$b || (!$b && \version_compare($v, %s, \'!=\'))', \var_export($this->version, \true));
            }
            if (self::OP_NE === $otherOperator) {
                return 'true';
            }
            return '!$b';
        }
        if (self::OP_LT === $this->operator || self::OP_LE === $this->operator) {
            if (self::OP_LT === $otherOperator || self::OP_LE === $otherOperator) {
                return '!$b';
            }
        } else if (self::OP_GT === $otherOperator || self::OP_GE === $otherOperator) {
            return '!$b';
        }
        if (self::OP_NE === $otherOperator) {
            return 'true';
        }
        $codeComparison = sprintf('\version_compare($v, %s, \'%s\')', \var_export($this->version, \true), self::$transOpInt[$this->operator]);
        if ($this->operator === self::OP_LE) {
            if ($otherOperator === self::OP_GT) {
                return sprintf('!$b && \version_compare($v, %s, \'!=\') && ', \var_export($this->version, \true)) . $codeComparison;
            }
        } elseif ($this->operator === self::OP_GE) {
            if ($otherOperator === self::OP_LT) {
                return sprintf('!$b && \version_compare($v, %s, \'!=\') && ', \var_export($this->version, \true)) . $codeComparison;
            }
        }
        return sprintf('!$b && %s', $codeComparison);
    }
    public function matchSpecific(Constraint $provider, $compareBranches = \false)
    {
        $noEqualOp = str_replace('=', '', self::$transOpInt[$this->operator]);
        $providerNoEqualOp = str_replace('=', '', self::$transOpInt[$provider->operator]);
        $isEqualOp = self::OP_EQ === $this->operator;
        $isNonEqualOp = self::OP_NE === $this->operator;
        $isProviderEqualOp = self::OP_EQ === $provider->operator;
        $isProviderNonEqualOp = self::OP_NE === $provider->operator;
        if ($isNonEqualOp || $isProviderNonEqualOp) {
            if ($isNonEqualOp && !$isProviderNonEqualOp && !$isProviderEqualOp && strpos($provider->version, 'dev-') === 0) {
                return \false;
            }
            if ($isProviderNonEqualOp && !$isNonEqualOp && !$isEqualOp && strpos($this->version, 'dev-') === 0) {
                return \false;
            }
            if (!$isEqualOp && !$isProviderEqualOp) {
                return \true;
            }
            return $this->versionCompare($provider->version, $this->version, '!=', $compareBranches);
        }
        if ($this->operator !== self::OP_EQ && $noEqualOp === $providerNoEqualOp) {
            return !(strpos($this->version, 'dev-') === 0 || strpos($provider->version, 'dev-') === 0);
        }
        $version1 = $isEqualOp ? $this->version : $provider->version;
        $version2 = $isEqualOp ? $provider->version : $this->version;
        $operator = $isEqualOp ? $provider->operator : $this->operator;
        if ($this->versionCompare($version1, $version2, self::$transOpInt[$operator], $compareBranches)) {
            return !(self::$transOpInt[$provider->operator] === $providerNoEqualOp && self::$transOpInt[$this->operator] !== $noEqualOp && \version_compare($provider->version, $this->version, '=='));
        }
        return \false;
    }
    public function __toString()
    {
        return self::$transOpInt[$this->operator] . ' ' . $this->version;
    }
    public function getLowerBound()
    {
        $this->extractBounds();
        return $this->lowerBound;
    }
    public function getUpperBound()
    {
        $this->extractBounds();
        return $this->upperBound;
    }
    private function extractBounds()
    {
        if (null !== $this->lowerBound) {
            return;
        }
        if (strpos($this->version, 'dev-') === 0) {
            $this->lowerBound = Bound::zero();
            $this->upperBound = Bound::positiveInfinity();
            return;
        }
        switch ($this->operator) {
            case self::OP_EQ:
                $this->lowerBound = new Bound($this->version, \true);
                $this->upperBound = new Bound($this->version, \true);
                break;
            case self::OP_LT:
                $this->lowerBound = Bound::zero();
                $this->upperBound = new Bound($this->version, \false);
                break;
            case self::OP_LE:
                $this->lowerBound = Bound::zero();
                $this->upperBound = new Bound($this->version, \true);
                break;
            case self::OP_GT:
                $this->lowerBound = new Bound($this->version, \false);
                $this->upperBound = Bound::positiveInfinity();
                break;
            case self::OP_GE:
                $this->lowerBound = new Bound($this->version, \true);
                $this->upperBound = Bound::positiveInfinity();
                break;
            case self::OP_NE:
                $this->lowerBound = Bound::zero();
                $this->upperBound = Bound::positiveInfinity();
                break;
        }
    }
}
<?php

namespace HumbugBox468\Composer\Semver\Constraint;

class MatchAllConstraint implements ConstraintInterface
{
    protected $prettyString;
    public function matches(ConstraintInterface $provider)
    {
        return \true;
    }
    public function compile($otherOperator)
    {
        return 'true';
    }
    public function setPrettyString($prettyString)
    {
        $this->prettyString = $prettyString;
    }
    public function getPrettyString()
    {
        if ($this->prettyString) {
            return $this->prettyString;
        }
        return (string) $this;
    }
    public function __toString()
    {
        return '*';
    }
    public function getUpperBound()
    {
        return Bound::positiveInfinity();
    }
    public function getLowerBound()
    {
        return Bound::zero();
    }
}
<?php

namespace HumbugBox468\Composer\Semver\Constraint;

class MatchNoneConstraint implements ConstraintInterface
{
    protected $prettyString;
    public function matches(ConstraintInterface $provider)
    {
        return \false;
    }
    public function compile($otherOperator)
    {
        return 'false';
    }
    public function setPrettyString($prettyString)
    {
        $this->prettyString = $prettyString;
    }
    public function getPrettyString()
    {
        if ($this->prettyString) {
            return $this->prettyString;
        }
        return (string) $this;
    }
    public function __toString()
    {
        return '[]';
    }
    public function getUpperBound()
    {
        return new Bound('0.0.0.0-dev', \false);
    }
    public function getLowerBound()
    {
        return new Bound('0.0.0.0-dev', \false);
    }
}
<?php

namespace HumbugBox468\Composer\Semver\Constraint;

class Bound
{
    private $version;
    private $isInclusive;
    public function __construct($version, $isInclusive)
    {
        $this->version = $version;
        $this->isInclusive = $isInclusive;
    }
    public function getVersion()
    {
        return $this->version;
    }
    public function isInclusive()
    {
        return $this->isInclusive;
    }
    public function isZero()
    {
        return $this->getVersion() === '0.0.0.0-dev' && $this->isInclusive();
    }
    public function isPositiveInfinity()
    {
        return $this->getVersion() === \PHP_INT_MAX . '.0.0.0' && !$this->isInclusive();
    }
    public function compareTo(Bound $other, $operator)
    {
        if (!\in_array($operator, array('<', '>'), \true)) {
            throw new \InvalidArgumentException('Does not support any other operator other than > or <.');
        }
        if ($this == $other) {
            return \false;
        }
        $compareResult = version_compare($this->getVersion(), $other->getVersion());
        if (0 !== $compareResult) {
            return ('>' === $operator ? 1 : -1) === $compareResult;
        }
        return '>' === $operator ? $other->isInclusive() : !$other->isInclusive();
    }
    public function __toString()
    {
        return sprintf('%s [%s]', $this->getVersion(), $this->isInclusive() ? 'inclusive' : 'exclusive');
    }
    public static function zero()
    {
        return new Bound('0.0.0.0-dev', \true);
    }
    public static function positiveInfinity()
    {
        return new Bound(\PHP_INT_MAX . '.0.0.0', \false);
    }
}
<?php

namespace HumbugBox468\Composer;

use HumbugBox468\Composer\Autoload\ClassLoader;
use HumbugBox468\Composer\Semver\VersionParser;
class InstalledVersions
{
    private static $selfDir = null;
    /**
    @psalm-var
    */
    private static $installed;
    private static $installedIsLocalDir;
    private static $canGetVendors;
    /**
    @psalm-var
    */
    private static $installedByVendor = array();
    /**
    @psalm-return
    */
    public static function getInstalledPackages()
    {
        $packages = array();
        foreach (self::getInstalled() as $installed) {
            $packages[] = array_keys($installed['versions']);
        }
        if (1 === \count($packages)) {
            return $packages[0];
        }
        return array_keys(array_flip(\call_user_func_array('array_merge', $packages)));
    }
    /**
    @psalm-return
    */
    public static function getInstalledPackagesByType($type)
    {
        $packagesByType = array();
        foreach (self::getInstalled() as $installed) {
            foreach ($installed['versions'] as $name => $package) {
                if (isset($package['type']) && $package['type'] === $type) {
                    $packagesByType[] = $name;
                }
            }
        }
        return $packagesByType;
    }
    public static function isInstalled($packageName, $includeDevRequirements = \true)
    {
        foreach (self::getInstalled() as $installed) {
            if (isset($installed['versions'][$packageName])) {
                return $includeDevRequirements || !isset($installed['versions'][$packageName]['dev_requirement']) || $installed['versions'][$packageName]['dev_requirement'] === \false;
            }
        }
        return \false;
    }
    public static function satisfies(VersionParser $parser, $packageName, $constraint)
    {
        $constraint = $parser->parseConstraints((string) $constraint);
        $provided = $parser->parseConstraints(self::getVersionRanges($packageName));
        return $provided->matches($constraint);
    }
    public static function getVersionRanges($packageName)
    {
        foreach (self::getInstalled() as $installed) {
            if (!isset($installed['versions'][$packageName])) {
                continue;
            }
            $ranges = array();
            if (isset($installed['versions'][$packageName]['pretty_version'])) {
                $ranges[] = $installed['versions'][$packageName]['pretty_version'];
            }
            if (array_key_exists('aliases', $installed['versions'][$packageName])) {
                $ranges = array_merge($ranges, $installed['versions'][$packageName]['aliases']);
            }
            if (array_key_exists('replaced', $installed['versions'][$packageName])) {
                $ranges = array_merge($ranges, $installed['versions'][$packageName]['replaced']);
            }
            if (array_key_exists('provided', $installed['versions'][$packageName])) {
                $ranges = array_merge($ranges, $installed['versions'][$packageName]['provided']);
            }
            return implode(' || ', $ranges);
        }
        throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
    }
    public static function getVersion($packageName)
    {
        foreach (self::getInstalled() as $installed) {
            if (!isset($installed['versions'][$packageName])) {
                continue;
            }
            if (!isset($installed['versions'][$packageName]['version'])) {
                return null;
            }
            return $installed['versions'][$packageName]['version'];
        }
        throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
    }
    public static function getPrettyVersion($packageName)
    {
        foreach (self::getInstalled() as $installed) {
            if (!isset($installed['versions'][$packageName])) {
                continue;
            }
            if (!isset($installed['versions'][$packageName]['pretty_version'])) {
                return null;
            }
            return $installed['versions'][$packageName]['pretty_version'];
        }
        throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
    }
    public static function getReference($packageName)
    {
        foreach (self::getInstalled() as $installed) {
            if (!isset($installed['versions'][$packageName])) {
                continue;
            }
            if (!isset($installed['versions'][$packageName]['reference'])) {
                return null;
            }
            return $installed['versions'][$packageName]['reference'];
        }
        throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
    }
    public static function getInstallPath($packageName)
    {
        foreach (self::getInstalled() as $installed) {
            if (!isset($installed['versions'][$packageName])) {
                continue;
            }
            return isset($installed['versions'][$packageName]['install_path']) ? $installed['versions'][$packageName]['install_path'] : null;
        }
        throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
    }
    /**
    @psalm-return
    */
    public static function getRootPackage()
    {
        $installed = self::getInstalled();
        return $installed[0]['root'];
    }
    /**
    @psalm-return
    */
    public static function getRawData()
    {
        @trigger_error('getRawData only returns the first dataset loaded, which may not be what you expect. Use getAllRawData() instead which returns all datasets for all autoloaders present in the process.', \E_USER_DEPRECATED);
        if (null === self::$installed) {
            if (substr(__DIR__, -8, 1) !== 'C') {
                self::$installed = include __DIR__ . '/installed.php';
            } else {
                self::$installed = array();
            }
        }
        return self::$installed;
    }
    /**
    @psalm-return
    */
    public static function getAllRawData()
    {
        return self::getInstalled();
    }
    /**
    @psalm-param
    */
    public static function reload($data)
    {
        self::$installed = $data;
        self::$installedByVendor = array();
        self::$installedIsLocalDir = \false;
    }
    private static function getSelfDir()
    {
        if (self::$selfDir === null) {
            self::$selfDir = strtr(__DIR__, '\\', '/');
        }
        return self::$selfDir;
    }
    /**
    @psalm-return
    */
    private static function getInstalled()
    {
        if (null === self::$canGetVendors) {
            self::$canGetVendors = method_exists('HumbugBox468\Composer\Autoload\ClassLoader', 'getRegisteredLoaders');
        }
        $installed = array();
        $copiedLocalDir = \false;
        if (self::$canGetVendors) {
            $selfDir = self::getSelfDir();
            foreach (ClassLoader::getRegisteredLoaders() as $vendorDir => $loader) {
                $vendorDir = strtr($vendorDir, '\\', '/');
                if (isset(self::$installedByVendor[$vendorDir])) {
                    $installed[] = self::$installedByVendor[$vendorDir];
                } elseif (is_file($vendorDir . '/composer/installed.php')) {
                    $required = require $vendorDir . '/composer/installed.php';
                    self::$installedByVendor[$vendorDir] = $required;
                    $installed[] = $required;
                    if (self::$installed === null && $vendorDir . '/composer' === $selfDir) {
                        self::$installed = $required;
                        self::$installedIsLocalDir = \true;
                    }
                }
                if (self::$installedIsLocalDir && $vendorDir . '/composer' === $selfDir) {
                    $copiedLocalDir = \true;
                }
            }
        }
        if (null === self::$installed) {
            if (substr(__DIR__, -8, 1) !== 'C') {
                $required = require __DIR__ . '/installed.php';
                self::$installed = $required;
            } else {
                self::$installed = array();
            }
        }
        if (self::$installed !== array() && !$copiedLocalDir) {
            $installed[] = self::$installed;
        }
        return $installed;
    }
}
<?php

namespace HumbugBox468;

return array('root' => array('name' => 'humbug/requirement-checker', 'pretty_version' => '4.x.x-dev', 'version' => '4.9999999.9999999.9999999-dev', 'reference' => null, 'type' => 'library', 'install_path' => __DIR__ . '/../../', 'aliases' => array(), 'dev' => \true), 'versions' => array('composer/semver' => array('pretty_version' => '3.4.0', 'version' => '3.4.0.0', 'reference' => '35e8d0af4486141bc745f23a29cc2091eb624a32', 'type' => 'library', 'install_path' => __DIR__ . '/./semver', 'aliases' => array(), 'dev_requirement' => \false), 'ergebnis/composer-normalize' => array('pretty_version' => '2.43.0', 'version' => '2.43.0.0', 'reference' => '4b46330c84bb8f43fac79f5c5a05162fc7c80d75', 'type' => 'composer-plugin', 'install_path' => __DIR__ . '/../ergebnis/composer-normalize', 'aliases' => array(), 'dev_requirement' => \true), 'ergebnis/json' => array('pretty_version' => '1.2.0', 'version' => '1.2.0.0', 'reference' => 'a457f25a5ba7ea11fc94f84d53678c5211abfce0', 'type' => 'library', 'install_path' => __DIR__ . '/../ergebnis/json', 'aliases' => array(), 'dev_requirement' => \true), 'ergebnis/json-normalizer' => array('pretty_version' => '4.5.0', 'version' => '4.5.0.0', 'reference' => 'f0ee9e70739f121b27fac8b743e4a52b23de2152', 'type' => 'library', 'install_path' => __DIR__ . '/../ergebnis/json-normalizer', 'aliases' => array(), 'dev_requirement' => \true), 'ergebnis/json-pointer' => array('pretty_version' => '3.4.0', 'version' => '3.4.0.0', 'reference' => 'b654757d873050622c2166f55ab25d04685261c5', 'type' => 'library', 'install_path' => __DIR__ . '/../ergebnis/json-pointer', 'aliases' => array(), 'dev_requirement' => \true), 'ergebnis/json-printer' => array('pretty_version' => '3.5.0', 'version' => '3.5.0.0', 'reference' => '549e16fe6de34b8c3aee7b421be12caa552f3ced', 'type' => 'library', 'install_path' => __DIR__ . '/../ergebnis/json-printer', 'aliases' => array(), 'dev_requirement' => \true), 'ergebnis/json-schema-validator' => array('pretty_version' => '4.2.0', 'version' => '4.2.0.0', 'reference' => '10ed514fdc3f9b71f8a92c567afea21a2f6fa1ef', 'type' => 'library', 'install_path' => __DIR__ . '/../ergebnis/json-schema-validator', 'aliases' => array(), 'dev_requirement' => \true), 'fidry/makefile' => array('pretty_version' => '1.0.1', 'version' => '1.0.1.0', 'reference' => 'be5a048dcc5648d04e924facce0f85b406d731e4', 'type' => 'library', 'install_path' => __DIR__ . '/../fidry/makefile', 'aliases' => array(), 'dev_requirement' => \true), 'humbug/requirement-checker' => array('pretty_version' => '4.x.x-dev', 'version' => '4.9999999.9999999.9999999-dev', 'reference' => null, 'type' => 'library', 'install_path' => __DIR__ . '/../../', 'aliases' => array(), 'dev_requirement' => \false), 'justinrainbow/json-schema' => array('pretty_version' => 'v5.2.13', 'version' => '5.2.13.0', 'reference' => 'fbbe7e5d79f618997bc3332a6f49246036c45793', 'type' => 'library', 'install_path' => __DIR__ . '/../justinrainbow/json-schema', 'aliases' => array(), 'dev_requirement' => \true), 'localheinz/diff' => array('pretty_version' => '1.1.1', 'version' => '1.1.1.0', 'reference' => '851bb20ea8358c86f677f5f111c4ab031b1c764c', 'type' => 'library', 'install_path' => __DIR__ . '/../localheinz/diff', 'aliases' => array(), 'dev_requirement' => \true), 'myclabs/deep-copy' => array('pretty_version' => '1.12.0', 'version' => '1.12.0.0', 'reference' => '3a6b9a42cd8f8771bd4295d13e1423fa7f3d942c', 'type' => 'library', 'install_path' => __DIR__ . '/../myclabs/deep-copy', 'aliases' => array(), 'dev_requirement' => \true), 'nikic/php-parser' => array('pretty_version' => 'v5.1.0', 'version' => '5.1.0.0', 'reference' => '683130c2ff8c2739f4822ff7ac5c873ec529abd1', 'type' => 'library', 'install_path' => __DIR__ . '/../nikic/php-parser', 'aliases' => array(), 'dev_requirement' => \true), 'phar-io/manifest' => array('pretty_version' => '2.0.4', 'version' => '2.0.4.0', 'reference' => '54750ef60c58e43759730615a392c31c80e23176', 'type' => 'library', 'install_path' => __DIR__ . '/../phar-io/manifest', 'aliases' => array(), 'dev_requirement' => \true), 'phar-io/version' => array('pretty_version' => '3.2.1', 'version' => '3.2.1.0', 'reference' => '4f7fd7836c6f332bb2933569e566a0d6c4cbed74', 'type' => 'library', 'install_path' => __DIR__ . '/../phar-io/version', 'aliases' => array(), 'dev_requirement' => \true), 'phpunit/php-code-coverage' => array('pretty_version' => '10.1.15', 'version' => '10.1.15.0', 'reference' => '5da8b1728acd1e6ffdf2ff32ffbdfd04307f26ae', 'type' => 'library', 'install_path' => __DIR__ . '/../phpunit/php-code-coverage', 'aliases' => array(), 'dev_requirement' => \true), 'phpunit/php-file-iterator' => array('pretty_version' => '4.1.0', 'version' => '4.1.0.0', 'reference' => 'a95037b6d9e608ba092da1b23931e537cadc3c3c', 'type' => 'library', 'install_path' => __DIR__ . '/../phpunit/php-file-iterator', 'aliases' => array(), 'dev_requirement' => \true), 'phpunit/php-invoker' => array('pretty_version' => '4.0.0', 'version' => '4.0.0.0', 'reference' => 'f5e568ba02fa5ba0ddd0f618391d5a9ea50b06d7', 'type' => 'library', 'install_path' => __DIR__ . '/../phpunit/php-invoker', 'aliases' => array(), 'dev_requirement' => \true), 'phpunit/php-text-template' => array('pretty_version' => '3.0.1', 'version' => '3.0.1.0', 'reference' => '0c7b06ff49e3d5072f057eb1fa59258bf287a748', 'type' => 'library', 'install_path' => __DIR__ . '/../phpunit/php-text-template', 'aliases' => array(), 'dev_requirement' => \true), 'phpunit/php-timer' => array('pretty_version' => '6.0.0', 'version' => '6.0.0.0', 'reference' => 'e2a2d67966e740530f4a3343fe2e030ffdc1161d', 'type' => 'library', 'install_path' => __DIR__ . '/../phpunit/php-timer', 'aliases' => array(), 'dev_requirement' => \true), 'phpunit/phpunit' => array('pretty_version' => '10.5.26', 'version' => '10.5.26.0', 'reference' => '42e2f13ceaa2e34461bc89bea75407550b40b2aa', 'type' => 'library', 'install_path' => __DIR__ . '/../phpunit/phpunit', 'aliases' => array(), 'dev_requirement' => \true), 'sebastian/cli-parser' => array('pretty_version' => '2.0.1', 'version' => '2.0.1.0', 'reference' => 'c34583b87e7b7a8055bf6c450c2c77ce32a24084', 'type' => 'library', 'install_path' => __DIR__ . '/../sebastian/cli-parser', 'aliases' => array(), 'dev_requirement' => \true), 'sebastian/code-unit' => array('pretty_version' => '2.0.0', 'version' => '2.0.0.0', 'reference' => 'a81fee9eef0b7a76af11d121767abc44c104e503', 'type' => 'library', 'install_path' => __DIR__ . '/../sebastian/code-unit', 'aliases' => array(), 'dev_requirement' => \true), 'sebastian/code-unit-reverse-lookup' => array('pretty_version' => '3.0.0', 'version' => '3.0.0.0', 'reference' => '5e3a687f7d8ae33fb362c5c0743794bbb2420a1d', 'type' => 'library', 'install_path' => __DIR__ . '/../sebastian/code-unit-reverse-lookup', 'aliases' => array(), 'dev_requirement' => \true), 'sebastian/comparator' => array('pretty_version' => '5.0.1', 'version' => '5.0.1.0', 'reference' => '2db5010a484d53ebf536087a70b4a5423c102372', 'type' => 'library', 'install_path' => __DIR__ . '/../sebastian/comparator', 'aliases' => array(), 'dev_requirement' => \true), 'sebastian/complexity' => array('pretty_version' => '3.2.0', 'version' => '3.2.0.0', 'reference' => '68ff824baeae169ec9f2137158ee529584553799', 'type' => 'library', 'install_path' => __DIR__ . '/../sebastian/complexity', 'aliases' => array(), 'dev_requirement' => \true), 'sebastian/diff' => array('pretty_version' => '5.1.1', 'version' => '5.1.1.0', 'reference' => 'c41e007b4b62af48218231d6c2275e4c9b975b2e', 'type' => 'library', 'install_path' => __DIR__ . '/../sebastian/diff', 'aliases' => array(), 'dev_requirement' => \true), 'sebastian/environment' => array('pretty_version' => '6.1.0', 'version' => '6.1.0.0', 'reference' => '8074dbcd93529b357029f5cc5058fd3e43666984', 'type' => 'library', 'install_path' => __DIR__ . '/../sebastian/environment', 'aliases' => array(), 'dev_requirement' => \true), 'sebastian/exporter' => array('pretty_version' => '5.1.2', 'version' => '5.1.2.0', 'reference' => '955288482d97c19a372d3f31006ab3f37da47adf', 'type' => 'library', 'install_path' => __DIR__ . '/../sebastian/exporter', 'aliases' => array(), 'dev_requirement' => \true), 'sebastian/global-state' => array('pretty_version' => '6.0.2', 'version' => '6.0.2.0', 'reference' => '987bafff24ecc4c9ac418cab1145b96dd6e9cbd9', 'type' => 'library', 'install_path' => __DIR__ . '/../sebastian/global-state', 'aliases' => array(), 'dev_requirement' => \true), 'sebastian/lines-of-code' => array('pretty_version' => '2.0.2', 'version' => '2.0.2.0', 'reference' => '856e7f6a75a84e339195d48c556f23be2ebf75d0', 'type' => 'library', 'install_path' => __DIR__ . '/../sebastian/lines-of-code', 'aliases' => array(), 'dev_requirement' => \true), 'sebastian/object-enumerator' => array('pretty_version' => '5.0.0', 'version' => '5.0.0.0', 'reference' => '202d0e344a580d7f7d04b3fafce6933e59dae906', 'type' => 'library', 'install_path' => __DIR__ . '/../sebastian/object-enumerator', 'aliases' => array(), 'dev_requirement' => \true), 'sebastian/object-reflector' => array('pretty_version' => '3.0.0', 'version' => '3.0.0.0', 'reference' => '24ed13d98130f0e7122df55d06c5c4942a577957', 'type' => 'library', 'install_path' => __DIR__ . '/../sebastian/object-reflector', 'aliases' => array(), 'dev_requirement' => \true), 'sebastian/recursion-context' => array('pretty_version' => '5.0.0', 'version' => '5.0.0.0', 'reference' => '05909fb5bc7df4c52992396d0116aed689f93712', 'type' => 'library', 'install_path' => __DIR__ . '/../sebastian/recursion-context', 'aliases' => array(), 'dev_requirement' => \true), 'sebastian/type' => array('pretty_version' => '4.0.0', 'version' => '4.0.0.0', 'reference' => '462699a16464c3944eefc02ebdd77882bd3925bf', 'type' => 'library', 'install_path' => __DIR__ . '/../sebastian/type', 'aliases' => array(), 'dev_requirement' => \true), 'sebastian/version' => array('pretty_version' => '4.0.1', 'version' => '4.0.1.0', 'reference' => 'c51fa83a5d8f43f1402e3f32a005e6262244ef17', 'type' => 'library', 'install_path' => __DIR__ . '/../sebastian/version', 'aliases' => array(), 'dev_requirement' => \true), 'symfony/deprecation-contracts' => array('pretty_version' => 'v3.5.0', 'version' => '3.5.0.0', 'reference' => '0e0d29ce1f20deffb4ab1b016a7257c4f1e789a1', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/deprecation-contracts', 'aliases' => array(), 'dev_requirement' => \true), 'symfony/polyfill-ctype' => array('pretty_version' => 'v1.30.0', 'version' => '1.30.0.0', 'reference' => '0424dff1c58f028c451efff2045f5d92410bd540', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/polyfill-ctype', 'aliases' => array(), 'dev_requirement' => \true), 'symfony/yaml' => array('pretty_version' => 'v6.4.8', 'version' => '6.4.8.0', 'reference' => '52903de178d542850f6f341ba92995d3d63e60c9', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/yaml', 'aliases' => array(), 'dev_requirement' => \true), 'thecodingmachine/safe' => array('pretty_version' => 'v2.5.0', 'version' => '2.5.0.0', 'reference' => '3115ecd6b4391662b4931daac4eba6b07a2ac1f0', 'type' => 'library', 'install_path' => __DIR__ . '/../thecodingmachine/safe', 'aliases' => array(), 'dev_requirement' => \true), 'theseer/tokenizer' => array('pretty_version' => '1.2.3', 'version' => '1.2.3.0', 'reference' => '737eda637ed5e28c3413cb1ebe8bb52cbf1ca7a2', 'type' => 'library', 'install_path' => __DIR__ . '/../theseer/tokenizer', 'aliases' => array(), 'dev_requirement' => \true)));
<?php

declare (strict_types=1);
namespace HumbugBox468\KevinGH\RequirementChecker;

use function exec;
use function fclose;
use function fopen;
use function function_exists;
use function getenv;
use function preg_match;
use function proc_close;
use function proc_open;
use function sapi_windows_cp_get;
use function sapi_windows_cp_set;
use function sapi_windows_vt100_support;
use function stream_get_contents;
use function trim;
use const DIRECTORY_SEPARATOR;
class Terminal
{
    private static $width;
    private static $height;
    private static $stty;
    public function getWidth(): int
    {
        $width = getenv('COLUMNS');
        if (\false !== $width) {
            return (int) trim($width);
        }
        if (!isset(self::$width)) {
            self::initDimensions();
        }
        return self::$width ?: 80;
    }
    public function getHeight(): int
    {
        $height = getenv('LINES');
        if (\false !== $height) {
            return (int) trim($height);
        }
        if (!isset(self::$height)) {
            self::initDimensions();
        }
        return self::$height ?: 50;
    }
    public static function hasSttyAvailable(): bool
    {
        if (isset(self::$stty)) {
            return self::$stty;
        }
        if (!function_exists('exec')) {
            return \false;
        }
        exec('stty 2>&1', $output, $exitcode);
        return self::$stty = 0 === $exitcode;
    }
    private static function initDimensions(): void
    {
        if ('\\' === DIRECTORY_SEPARATOR) {
            if (preg_match('/^(\d+)x(\d+)(?: \((\d+)x(\d+)\))?$/', trim(getenv('ANSICON') ?: ''), $matches)) {
                self::$width = (int) $matches[1];
                self::$height = isset($matches[4]) ? (int) $matches[4] : (int) $matches[2];
            } elseif (!self::hasVt100Support() && self::hasSttyAvailable()) {
                self::initDimensionsUsingStty();
            } elseif (null !== $dimensions = self::getConsoleMode()) {
                self::$width = (int) $dimensions[0];
                self::$height = (int) $dimensions[1];
            }
        } else {
            self::initDimensionsUsingStty();
        }
    }
    private static function hasVt100Support(): bool
    {
        return function_exists('sapi_windows_vt100_support') && sapi_windows_vt100_support(fopen('php://stdout', 'wb'));
    }
    private static function initDimensionsUsingStty(): void
    {
        if ($sttyString = self::getSttyColumns()) {
            if (preg_match('/rows.(\d+);.columns.(\d+);/i', $sttyString, $matches)) {
                self::$width = (int) $matches[2];
                self::$height = (int) $matches[1];
            } elseif (preg_match('/;.(\d+).rows;.(\d+).columns/i', $sttyString, $matches)) {
                self::$width = (int) $matches[2];
                self::$height = (int) $matches[1];
            }
        }
    }
    private static function getConsoleMode(): ?array
    {
        $info = self::readFromProcess('mode CON');
        if (null === $info || !preg_match('/--------+\r?\n.+?(\d+)\r?\n.+?(\d+)\r?\n/', $info, $matches)) {
            return null;
        }
        return [(int) $matches[2], (int) $matches[1]];
    }
    private static function getSttyColumns(): ?string
    {
        return self::readFromProcess('stty -a | grep columns');
    }
    private static function readFromProcess(string $command): ?string
    {
        if (!function_exists('proc_open')) {
            return null;
        }
        $descriptorspec = [1 => ['pipe', 'w'], 2 => ['pipe', 'w']];
        $cp = function_exists('sapi_windows_cp_set') ? sapi_windows_cp_get() : 0;
        if (!$process = @proc_open($command, $descriptorspec, $pipes, null, null, ['suppress_errors' => \true])) {
            return null;
        }
        $info = stream_get_contents($pipes[1]);
        fclose($pipes[1]);
        fclose($pipes[2]);
        proc_close($process);
        if ($cp) {
            sapi_windows_cp_set($cp);
        }
        return $info;
    }
}
<?php

declare (strict_types=1);
namespace HumbugBox468\KevinGH\RequirementChecker;

use function fstat;
use function function_exists;
use function getenv;
use function implode;
use function posix_isatty;
use function preg_match;
use function preg_quote;
use function sapi_windows_vt100_support;
use function sprintf;
use function str_replace;
use function stream_isatty;
use const DIRECTORY_SEPARATOR;
use const STDOUT;
final class IO
{
    public const VERBOSITY_QUIET = 16;
    public const VERBOSITY_NORMAL = 32;
    public const VERBOSITY_VERBOSE = 64;
    public const VERBOSITY_VERY_VERBOSE = 128;
    public const VERBOSITY_DEBUG = 256;
    private $interactive;
    private $verbosity = self::VERBOSITY_NORMAL;
    private $colorSupport;
    private $options;
    public function __construct()
    {
        $this->options = implode(' ', $_SERVER['argv']);
        $shellVerbosity = $this->configureVerbosity();
        $this->interactive = $this->checkInteractivity($shellVerbosity);
        $this->colorSupport = $this->checkColorSupport();
    }
    public function isInteractive(): bool
    {
        return $this->interactive;
    }
    public function getVerbosity(): int
    {
        return $this->verbosity;
    }
    public function hasColorSupport(): bool
    {
        return $this->colorSupport;
    }
    public function hasParameter($values): bool
    {
        $values = (array) $values;
        foreach ($values as $value) {
            $regexp = sprintf('/\s%s\b/', str_replace(' ', '\s+', preg_quote($value, '/')));
            if (1 === preg_match($regexp, $this->options)) {
                return \true;
            }
        }
        return \false;
    }
    private function checkInteractivity(int $shellVerbosity): bool
    {
        if (-1 === $shellVerbosity) {
            return \false;
        }
        if (\true === $this->hasParameter(['--no-interaction', '-n'])) {
            return \false;
        }
        if (function_exists('posix_isatty') && !@posix_isatty(STDOUT) && \false === getenv('SHELL_INTERACTIVE')) {
            return \false;
        }
        return \true;
    }
    private function configureVerbosity(): int
    {
        switch ($shellVerbosity = (int) getenv('SHELL_VERBOSITY')) {
            case -1:
                $this->verbosity = self::VERBOSITY_QUIET;
                break;
            case 1:
                $this->verbosity = self::VERBOSITY_VERBOSE;
                break;
            case 2:
                $this->verbosity = self::VERBOSITY_VERY_VERBOSE;
                break;
            case 3:
                $this->verbosity = self::VERBOSITY_DEBUG;
                break;
            default:
                $shellVerbosity = 0;
                break;
        }
        if ($this->hasParameter(['--quiet', '-q'])) {
            $this->verbosity = self::VERBOSITY_QUIET;
            $shellVerbosity = -1;
        } elseif ($this->hasParameter(['-vvv', '--verbose=3', '--verbose 3'])) {
            $this->verbosity = self::VERBOSITY_DEBUG;
            $shellVerbosity = 3;
        } elseif ($this->hasParameter(['-vv', '--verbose=2', '--verbose 2'])) {
            $this->verbosity = self::VERBOSITY_VERY_VERBOSE;
            $shellVerbosity = 2;
        } elseif ($this->hasParameter(['-v', '--verbose=1', '--verbose 1', '--verbose'])) {
            $this->verbosity = self::VERBOSITY_VERBOSE;
            $shellVerbosity = 1;
        }
        return $shellVerbosity;
    }
    private function checkColorSupport(): bool
    {
        if ($this->hasParameter(['--ansi'])) {
            return \true;
        }
        if ($this->hasParameter(['--no-ansi'])) {
            return \false;
        }
        if (DIRECTORY_SEPARATOR === '\\') {
            return function_exists('sapi_windows_vt100_support') && sapi_windows_vt100_support(STDOUT) || \false !== getenv('ANSICON') || 'ON' === getenv('ConEmuANSI') || 'xterm' === getenv('TERM');
        }
        if (function_exists('stream_isatty')) {
            return stream_isatty(STDOUT);
        }
        if (function_exists('posix_isatty')) {
            return posix_isatty(STDOUT);
        }
        $stat = fstat(STDOUT);
        return $stat ? 020000 === ($stat['mode'] & 0170000) : \false;
    }
}
<?php

declare (strict_types=1);
namespace HumbugBox468\KevinGH\RequirementChecker;

use function extension_loaded;
final class IsExtensionFulfilled implements IsFulfilled
{
    private $requiredExtension;
    public function __construct(string $requiredExtension)
    {
        $this->requiredExtension = $requiredExtension;
    }
    public function __invoke(): bool
    {
        return extension_loaded($this->requiredExtension);
    }
}
<?php

declare (strict_types=1);
namespace HumbugBox468\KevinGH\RequirementChecker;

use InvalidArgumentException;
use function count;
use function sprintf;
final class Checker
{
    private static $requirementsConfig;
    public static function checkRequirements(): bool
    {
        $requirements = self::retrieveRequirements();
        $checkPassed = $requirements->evaluateRequirements();
        $io = new IO();
        self::printCheck($checkPassed, new Printer($io->getVerbosity(), $io->hasColorSupport()), $requirements);
        return $checkPassed;
    }
    public static function printCheck($checkPassed, Printer $printer, RequirementCollection $requirements): void
    {
        if (\false === $checkPassed && IO::VERBOSITY_VERY_VERBOSE > $printer->getVerbosity()) {
            $printer->setVerbosity(IO::VERBOSITY_VERY_VERBOSE);
        }
        $verbosity = IO::VERBOSITY_VERY_VERBOSE;
        $iniPath = $requirements->getPhpIniPath();
        $printer->title('Box Requirements Checker', $verbosity);
        $printer->printv('> Using PHP ', $verbosity);
        $printer->printvln(\PHP_VERSION, $verbosity, 'green');
        if ($iniPath) {
            $printer->printvln('> PHP is using the following php.ini file:', $verbosity);
            $printer->printvln('  ' . $iniPath, $verbosity, 'green');
        } else {
            $printer->printvln('> PHP is not using any php.ini file.', $verbosity, 'yellow');
        }
        $printer->printvln('', $verbosity);
        if (count($requirements) > 0) {
            $printer->printvln('> Checking Box requirements:', $verbosity);
            $printer->printv('  ', $verbosity);
        } else {
            $printer->printvln('> No requirements found.', $verbosity);
        }
        $errorMessages = [];
        foreach ($requirements->getRequirements() as $requirement) {
            if ($errorMessage = $printer->getRequirementErrorMessage($requirement)) {
                if (IO::VERBOSITY_DEBUG === $printer->getVerbosity()) {
                    $printer->printvln('✘ ' . $requirement->getTestMessage(), IO::VERBOSITY_DEBUG, 'red');
                    $printer->printv('  ', IO::VERBOSITY_DEBUG);
                    $errorMessages[] = $errorMessage;
                } else {
                    $printer->printv('E', $verbosity, 'red');
                    $errorMessages[] = $errorMessage;
                }
                continue;
            }
            if (IO::VERBOSITY_DEBUG === $printer->getVerbosity()) {
                $printer->printvln('✔ ' . $requirement->getTestMessage(), IO::VERBOSITY_DEBUG, 'green');
                $printer->printv('  ', IO::VERBOSITY_DEBUG);
            } else {
                $printer->printv('.', $verbosity, 'green');
            }
        }
        if (IO::VERBOSITY_DEBUG !== $printer->getVerbosity() && count($requirements) > 0) {
            $printer->printvln('', $verbosity);
        }
        if ($requirements->evaluateRequirements()) {
            $printer->block('OK', 'Your system is ready to run the application.', $verbosity, 'success');
        } else {
            $printer->block('ERROR', 'Your system is not ready to run the application.', $verbosity, 'error');
            $printer->title('Fix the following mandatory requirements:', $verbosity, 'red');
            foreach ($errorMessages as $errorMessage) {
                $printer->printv(' * ' . $errorMessage, $verbosity);
            }
        }
        $printer->printvln('', $verbosity);
    }
    private static function retrieveRequirements(): RequirementCollection
    {
        if (null === self::$requirementsConfig) {
            self::$requirementsConfig = __DIR__ . '/../.requirements.php';
        }
        $config = require self::$requirementsConfig;
        $requirements = new RequirementCollection();
        foreach ($config as $constraint) {
            $requirements->addRequirement(self::createCondition($constraint['type'], $constraint['condition']), $constraint['message'], $constraint['helpMessage']);
        }
        return $requirements;
    }
    private static function createCondition($type, $condition): IsFulfilled
    {
        switch ($type) {
            case 'php':
                return new IsPhpVersionFulfilled($condition);
            case 'extension':
                return new IsExtensionFulfilled($condition);
            case 'extension-conflict':
                return new IsExtensionConflictFulfilled($condition);
            default:
                throw new InvalidArgumentException(sprintf('Unknown requirement type "%s".', $type));
        }
    }
}
<?php

declare (strict_types=1);
namespace HumbugBox468\KevinGH\RequirementChecker;

use HumbugBox468\Composer\Semver\Semver;
use function sprintf;
use const PHP_MAJOR_VERSION;
use const PHP_MINOR_VERSION;
use const PHP_RELEASE_VERSION;
final class IsPhpVersionFulfilled implements IsFulfilled
{
    private $requiredPhpVersion;
    public function __construct(string $requiredPhpVersion)
    {
        $this->requiredPhpVersion = $requiredPhpVersion;
    }
    public function __invoke(): bool
    {
        return Semver::satisfies(sprintf('%d.%d.%d', PHP_MAJOR_VERSION, PHP_MINOR_VERSION, PHP_RELEASE_VERSION), $this->requiredPhpVersion);
    }
}
<?php

declare (strict_types=1);
namespace HumbugBox468\KevinGH\RequirementChecker;

use ArrayIterator;
use Countable;
use IteratorAggregate;
use Traversable;
use function count;
use function get_cfg_var;
final class RequirementCollection implements IteratorAggregate, Countable
{
    private $requirements = [];
    private $phpIniPath;
    public function __construct($phpIniPath = null)
    {
        $this->phpIniPath = $phpIniPath ?? get_cfg_var('cfg_file_path');
    }
    public function getIterator(): Traversable
    {
        return new ArrayIterator($this->requirements);
    }
    public function count(): int
    {
        return count($this->requirements);
    }
    public function add(Requirement $requirement): void
    {
        $this->requirements[] = $requirement;
    }
    public function addRequirement(IsFulfilled $checkIsFulfilled, string $testMessage, string $helpText): void
    {
        $this->add(new Requirement($checkIsFulfilled, $testMessage, $helpText));
    }
    public function getRequirements(): array
    {
        return $this->requirements;
    }
    public function getPhpIniPath()
    {
        return $this->phpIniPath;
    }
    public function evaluateRequirements()
    {
        return array_reduce($this->requirements, static function (bool $checkPassed, Requirement $requirement): bool {
            return $checkPassed && $requirement->isFulfilled();
        }, \true);
    }
}
<?php

declare (strict_types=1);
namespace HumbugBox468\KevinGH\RequirementChecker;

use function extension_loaded;
final class IsExtensionConflictFulfilled implements IsFulfilled
{
    private $conflictingExtension;
    public function __construct(string $requiredExtension)
    {
        $this->conflictingExtension = $requiredExtension;
    }
    public function __invoke(): bool
    {
        return !extension_loaded($this->conflictingExtension);
    }
}
<?php

declare (strict_types=1);
namespace HumbugBox468\KevinGH\RequirementChecker;

use function array_shift;
use function count;
use function explode;
use function ltrim;
use function min;
use function sprintf;
use function str_pad;
use function str_repeat;
use function strlen;
use function trim;
use function wordwrap;
use const PHP_EOL;
final class Printer
{
    private $styles = ['reset' => "\x1b[0m", 'red' => "\x1b[31m", 'green' => "\x1b[32m", 'yellow' => "\x1b[33m", 'title' => "\x1b[33m", 'error' => "\x1b[37;41m", 'success' => "\x1b[30;42m"];
    private $verbosity;
    private $supportColors;
    private $width;
    public function __construct(int $verbosity, bool $supportColors, ?int $width = null)
    {
        if (null === $width) {
            $terminal = new Terminal();
            $width = $terminal->getWidth();
        }
        $this->verbosity = $verbosity;
        $this->supportColors = $supportColors;
        $this->width = $width ?: 80;
    }
    public function getVerbosity(): int
    {
        return $this->verbosity;
    }
    public function setVerbosity($verbosity): void
    {
        $this->verbosity = $verbosity;
    }
    public function title(string $title, int $verbosity, ?string $style = null): void
    {
        if (null === $style) {
            $style = 'title';
        }
        $this->printvln('', $verbosity, $style);
        $this->printvln($title, $verbosity, $style);
        $this->printvln(str_repeat('=', min(strlen($title), $this->width)), $verbosity, $style);
        $this->printvln('', $verbosity, $style);
    }
    public function getRequirementErrorMessage(Requirement $requirement): ?string
    {
        if ($requirement->isFulfilled()) {
            return null;
        }
        return wordwrap($requirement->getHelpText(), $this->width - 3, PHP_EOL . '   ') . PHP_EOL;
    }
    public function block(string $title, string $message, int $verbosity, ?string $style = null): void
    {
        $prefix = ' [' . $title . '] ';
        $lineLength = $this->width - strlen($prefix) - 1;
        if ($lineLength < 0) {
            $lineLength = 0;
        }
        $message = $prefix . trim($message);
        $lines = [];
        $remainingMessage = $message;
        $wrapped = wordwrap($remainingMessage, $lineLength, '¬');
        $wrapped = explode('¬', $wrapped);
        do {
            $line = array_shift($wrapped);
            if ($lines && $lineLength > 0) {
                $line = str_repeat(' ', strlen($prefix)) . ltrim($line);
            }
            $lines[] = str_pad($line, $this->width, ' ', \STR_PAD_RIGHT);
        } while (count($wrapped));
        $this->printvln('', $verbosity);
        $this->printvln(str_repeat(' ', $this->width), $verbosity, $style);
        foreach ($lines as $line) {
            $this->printvln($line, $verbosity, $style);
        }
        $this->printv(str_repeat(' ', $this->width), $verbosity, $style);
        $this->printvln('', $verbosity);
    }
    public function printvln(string $message, int $verbosity, ?string $style = null): void
    {
        $this->printv($message, $verbosity, $style);
        $this->printv(PHP_EOL, $verbosity, null);
    }
    public function printv(string $message, int $verbosity, ?string $style = null): void
    {
        if ($verbosity > $this->verbosity) {
            return;
        }
        $message = wordwrap($message, $this->width);
        $message = sprintf('%s%s%s', $this->supportColors && isset($this->styles[$style]) ? $this->styles[$style] : '', $message, $this->supportColors ? $this->styles['reset'] : '');
        if ('1' === getenv('BOX_REQUIREMENTS_CHECKER_LOG_TO_STDOUT')) {
            echo $message;
        } else {
            fwrite(\STDERR, $message);
        }
    }
}
<?php

declare (strict_types=1);
namespace HumbugBox468\KevinGH\RequirementChecker;

interface IsFulfilled
{
    public function __invoke(): bool;
}
<?php

declare (strict_types=1);
namespace HumbugBox468\KevinGH\RequirementChecker;

final class Requirement
{
    private $checkIsFulfilled;
    private $fulfilled;
    private $testMessage;
    private $helpText;
    public function __construct(IsFulfilled $checkIsFulfilled, string $testMessage, string $helpText)
    {
        $this->checkIsFulfilled = $checkIsFulfilled;
        $this->testMessage = $testMessage;
        $this->helpText = $helpText;
    }
    public function isFulfilled(): bool
    {
        if (!isset($this->fulfilled)) {
            $this->fulfilled = $this->checkIsFulfilled->__invoke();
        }
        return $this->fulfilled;
    }
    public function getIsFullfilledChecker(): IsFulfilled
    {
        return $this->checkIsFulfilled;
    }
    public function getTestMessage(): string
    {
        return $this->testMessage;
    }
    public function getHelpText(): string
    {
        return $this->helpText;
    }
}
                   GNU LESSER GENERAL PUBLIC LICENSE
                       Version 3, 29 June 2007

 Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
 Everyone is permitted to copy and distribute verbatim copies
 of this license document, but changing it is not allowed.


  This version of the GNU Lesser General Public License incorporates
the terms and conditions of version 3 of the GNU General Public
License, supplemented by the additional permissions listed below.

  0. Additional Definitions.

  As used herein, "this License" refers to version 3 of the GNU Lesser
General Public License, and the "GNU GPL" refers to version 3 of the GNU
General Public License.

  "The Library" refers to a covered work governed by this License,
other than an Application or a Combined Work as defined below.

  An "Application" is any work that makes use of an interface provided
by the Library, but which is not otherwise based on the Library.
Defining a subclass of a class defined by the Library is deemed a mode
of using an interface provided by the Library.

  A "Combined Work" is a work produced by combining or linking an
Application with the Library.  The particular version of the Library
with which the Combined Work was made is also called the "Linked
Version".

  The "Minimal Corresponding Source" for a Combined Work means the
Corresponding Source for the Combined Work, excluding any source code
for portions of the Combined Work that, considered in isolation, are
based on the Application, and not on the Linked Version.

  The "Corresponding Application Code" for a Combined Work means the
object code and/or source code for the Application, including any data
and utility programs needed for reproducing the Combined Work from the
Application, but excluding the System Libraries of the Combined Work.

  1. Exception to Section 3 of the GNU GPL.

  You may convey a covered work under sections 3 and 4 of this License
without being bound by section 3 of the GNU GPL.

  2. Conveying Modified Versions.

  If you modify a copy of the Library, and, in your modifications, a
facility refers to a function or data to be supplied by an Application
that uses the facility (other than as an argument passed when the
facility is invoked), then you may convey a copy of the modified
version:

   a) under this License, provided that you make a good faith effort to
   ensure that, in the event an Application does not supply the
   function or data, the facility still operates, and performs
   whatever part of its purpose remains meaningful, or

   b) under the GNU GPL, with none of the additional permissions of
   this License applicable to that copy.

  3. Object Code Incorporating Material from Library Header Files.

  The object code form of an Application may incorporate material from
a header file that is part of the Library.  You may convey such object
code under terms of your choice, provided that, if the incorporated
material is not limited to numerical parameters, data structure
layouts and accessors, or small macros, inline functions and templates
(ten or fewer lines in length), you do both of the following:

   a) Give prominent notice with each copy of the object code that the
   Library is used in it and that the Library and its use are
   covered by this License.

   b) Accompany the object code with a copy of the GNU GPL and this license
   document.

  4. Combined Works.

  You may convey a Combined Work under terms of your choice that,
taken together, effectively do not restrict modification of the
portions of the Library contained in the Combined Work and reverse
engineering for debugging such modifications, if you also do each of
the following:

   a) Give prominent notice with each copy of the Combined Work that
   the Library is used in it and that the Library and its use are
   covered by this License.

   b) Accompany the Combined Work with a copy of the GNU GPL and this license
   document.

   c) For a Combined Work that displays copyright notices during
   execution, include the copyright notice for the Library among
   these notices, as well as a reference directing the user to the
   copies of the GNU GPL and this license document.

   d) Do one of the following:

       0) Convey the Minimal Corresponding Source under the terms of this
       License, and the Corresponding Application Code in a form
       suitable for, and under terms that permit, the user to
       recombine or relink the Application with a modified version of
       the Linked Version to produce a modified Combined Work, in the
       manner specified by section 6 of the GNU GPL for conveying
       Corresponding Source.

       1) Use a suitable shared library mechanism for linking with the
       Library.  A suitable mechanism is one that (a) uses at run time
       a copy of the Library already present on the user's computer
       system, and (b) will operate properly with a modified version
       of the Library that is interface-compatible with the Linked
       Version.

   e) Provide Installation Information, but only if you would otherwise
   be required to provide such information under section 6 of the
   GNU GPL, and only to the extent that such information is
   necessary to install and execute a modified version of the
   Combined Work produced by recombining or relinking the
   Application with a modified version of the Linked Version. (If
   you use option 4d0, the Installation Information must accompany
   the Minimal Corresponding Source and Corresponding Application
   Code. If you use option 4d1, you must provide the Installation
   Information in the manner specified by section 6 of the GNU GPL
   for conveying Corresponding Source.)

  5. Combined Libraries.

  You may place library facilities that are a work based on the
Library side by side in a single library together with other library
facilities that are not Applications and are not covered by this
License, and convey such a combined library under terms of your
choice, if you do both of the following:

   a) Accompany the combined library with a copy of the same work based
   on the Library, uncombined with any other library facilities,
   conveyed under the terms of this License.

   b) Give prominent notice with the combined library that part of it
   is a work based on the Library, and explaining where to find the
   accompanying uncombined form of the same work.

  6. Revised Versions of the GNU Lesser General Public License.

  The Free Software Foundation may publish revised and/or new versions
of the GNU Lesser General Public License from time to time. Such new
versions will be similar in spirit to the present version, but may
differ in detail to address new problems or concerns.

  Each version is given a distinguishing version number. If the
Library as you received it specifies that a certain numbered version
of the GNU Lesser General Public License "or any later version"
applies to it, you have the option of following the terms and
conditions either of that published version or of any later version
published by the Free Software Foundation. If the Library as you
received it does not specify a version number of the GNU Lesser
General Public License, you may choose any version of the GNU Lesser
General Public License ever published by the Free Software Foundation.

  If the Library as you received it specifies that a proxy can decide
whether future versions of the GNU Lesser General Public License shall
apply, that proxy's public statement of acceptance of any version is
permanent authorization for you to choose that version for the
Library.
<!doctype html><html lang="en"><head><meta charset="utf-8"><title>Contao Manager</title><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=1"/><meta name="description" content=""><meta name="robots" content="noindex,follow"><meta http-equiv="Content-Security-Policy" content="img-src 'self' data: blob: contao.github.io extensions.contao.org; object-src 'none'"/><link rel="icon" type="image/x-icon" href="assets/favicon.ico"><link rel="icon" type="image/png" sizes="16x16" href="assets/favicon-16x16.png"><link rel="icon" type="image/png" sizes="32x32" href="assets/favicon-32x32.png"><link rel="icon" type="image/png" sizes="48x48" href="assets/favicon-48x48.png"><link rel="manifest" href="assets/manifest.webmanifest"><meta name="mobile-web-app-capable" content="yes"><meta name="theme-color" content="#ffffff"><meta name="application-name" content="Contao Manager"><link rel="apple-touch-icon" sizes="57x57" href="assets/apple-touch-icon-57x57.png"><link rel="apple-touch-icon" sizes="60x60" href="assets/apple-touch-icon-60x60.png"><link rel="apple-touch-icon" sizes="72x72" href="assets/apple-touch-icon-72x72.png"><link rel="apple-touch-icon" sizes="76x76" href="assets/apple-touch-icon-76x76.png"><link rel="apple-touch-icon" sizes="114x114" href="assets/apple-touch-icon-114x114.png"><link rel="apple-touch-icon" sizes="120x120" href="assets/apple-touch-icon-120x120.png"><link rel="apple-touch-icon" sizes="144x144" href="assets/apple-touch-icon-144x144.png"><link rel="apple-touch-icon" sizes="152x152" href="assets/apple-touch-icon-152x152.png"><link rel="apple-touch-icon" sizes="167x167" href="assets/apple-touch-icon-167x167.png"><link rel="apple-touch-icon" sizes="180x180" href="assets/apple-touch-icon-180x180.png"><link rel="apple-touch-icon" sizes="1024x1024" href="assets/apple-touch-icon-1024x1024.png"><meta name="apple-mobile-web-app-capable" content="yes"><meta name="apple-mobile-web-app-status-bar-style" content="black-translucent"><meta name="apple-mobile-web-app-title" content="Contao Manager"><link rel="apple-touch-startup-image" media="(device-width: 320px) and (device-height: 568px) and (-webkit-device-pixel-ratio: 2) and (orientation: portrait)" href="assets/apple-touch-startup-image-640x1136.png"><link rel="apple-touch-startup-image" media="(device-width: 320px) and (device-height: 568px) and (-webkit-device-pixel-ratio: 2) and (orientation: landscape)" href="assets/apple-touch-startup-image-1136x640.png"><link rel="apple-touch-startup-image" media="(device-width: 375px) and (device-height: 667px) and (-webkit-device-pixel-ratio: 2) and (orientation: portrait)" href="assets/apple-touch-startup-image-750x1334.png"><link rel="apple-touch-startup-image" media="(device-width: 375px) and (device-height: 667px) and (-webkit-device-pixel-ratio: 2) and (orientation: landscape)" href="assets/apple-touch-startup-image-1334x750.png"><link rel="apple-touch-startup-image" media="(device-width: 375px) and (device-height: 812px) and (-webkit-device-pixel-ratio: 3) and (orientation: portrait)" href="assets/apple-touch-startup-image-1125x2436.png"><link rel="apple-touch-startup-image" media="(device-width: 375px) and (device-height: 812px) and (-webkit-device-pixel-ratio: 3) and (orientation: landscape)" href="assets/apple-touch-startup-image-2436x1125.png"><link rel="apple-touch-startup-image" media="(device-width: 390px) and (device-height: 844px) and (-webkit-device-pixel-ratio: 3) and (orientation: portrait)" href="assets/apple-touch-startup-image-1170x2532.png"><link rel="apple-touch-startup-image" media="(device-width: 390px) and (device-height: 844px) and (-webkit-device-pixel-ratio: 3) and (orientation: landscape)" href="assets/apple-touch-startup-image-2532x1170.png"><link rel="apple-touch-startup-image" media="(device-width: 393px) and (device-height: 852px) and (-webkit-device-pixel-ratio: 3) and (orientation: portrait)" href="assets/apple-touch-startup-image-1179x2556.png"><link rel="apple-touch-startup-image" media="(device-width: 393px) and (device-height: 852px) and (-webkit-device-pixel-ratio: 3) and (orientation: landscape)" href="assets/apple-touch-startup-image-2556x1179.png"><link rel="apple-touch-startup-image" media="(device-width: 414px) and (device-height: 896px) and (-webkit-device-pixel-ratio: 2) and (orientation: portrait)" href="assets/apple-touch-startup-image-828x1792.png"><link rel="apple-touch-startup-image" media="(device-width: 414px) and (device-height: 896px) and (-webkit-device-pixel-ratio: 2) and (orientation: landscape)" href="assets/apple-touch-startup-image-1792x828.png"><link rel="apple-touch-startup-image" media="(device-width: 414px) and (device-height: 896px) and (-webkit-device-pixel-ratio: 3) and (orientation: portrait)" href="assets/apple-touch-startup-image-1242x2688.png"><link rel="apple-touch-startup-image" media="(device-width: 414px) and (device-height: 896px) and (-webkit-device-pixel-ratio: 3) and (orientation: landscape)" href="assets/apple-touch-startup-image-2688x1242.png"><link rel="apple-touch-startup-image" media="(device-width: 414px) and (device-height: 736px) and (-webkit-device-pixel-ratio: 3) and (orientation: portrait)" href="assets/apple-touch-startup-image-1242x2208.png"><link rel="apple-touch-startup-image" media="(device-width: 414px) and (device-height: 736px) and (-webkit-device-pixel-ratio: 3) and (orientation: landscape)" href="assets/apple-touch-startup-image-2208x1242.png"><link rel="apple-touch-startup-image" media="(device-width: 428px) and (device-height: 926px) and (-webkit-device-pixel-ratio: 3) and (orientation: portrait)" href="assets/apple-touch-startup-image-1284x2778.png"><link rel="apple-touch-startup-image" media="(device-width: 428px) and (device-height: 926px) and (-webkit-device-pixel-ratio: 3) and (orientation: landscape)" href="assets/apple-touch-startup-image-2778x1284.png"><link rel="apple-touch-startup-image" media="(device-width: 430px) and (device-height: 932px) and (-webkit-device-pixel-ratio: 3) and (orientation: portrait)" href="assets/apple-touch-startup-image-1290x2796.png"><link rel="apple-touch-startup-image" media="(device-width: 430px) and (device-height: 932px) and (-webkit-device-pixel-ratio: 3) and (orientation: landscape)" href="assets/apple-touch-startup-image-2796x1290.png"><link rel="apple-touch-startup-image" media="(device-width: 744px) and (device-height: 1133px) and (-webkit-device-pixel-ratio: 2) and (orientation: portrait)" href="assets/apple-touch-startup-image-1488x2266.png"><link rel="apple-touch-startup-image" media="(device-width: 744px) and (device-height: 1133px) and (-webkit-device-pixel-ratio: 2) and (orientation: landscape)" href="assets/apple-touch-startup-image-2266x1488.png"><link rel="apple-touch-startup-image" media="(device-width: 768px) and (device-height: 1024px) and (-webkit-device-pixel-ratio: 2) and (orientation: portrait)" href="assets/apple-touch-startup-image-1536x2048.png"><link rel="apple-touch-startup-image" media="(device-width: 768px) and (device-height: 1024px) and (-webkit-device-pixel-ratio: 2) and (orientation: landscape)" href="assets/apple-touch-startup-image-2048x1536.png"><link rel="apple-touch-startup-image" media="(device-width: 810px) and (device-height: 1080px) and (-webkit-device-pixel-ratio: 2) and (orientation: portrait)" href="assets/apple-touch-startup-image-1620x2160.png"><link rel="apple-touch-startup-image" media="(device-width: 810px) and (device-height: 1080px) and (-webkit-device-pixel-ratio: 2) and (orientation: landscape)" href="assets/apple-touch-startup-image-2160x1620.png"><link rel="apple-touch-startup-image" media="(device-width: 820px) and (device-height: 1080px) and (-webkit-device-pixel-ratio: 2) and (orientation: portrait)" href="assets/apple-touch-startup-image-1640x2160.png"><link rel="apple-touch-startup-image" media="(device-width: 820px) and (device-height: 1080px) and (-webkit-device-pixel-ratio: 2) and (orientation: landscape)" href="assets/apple-touch-startup-image-2160x1640.png"><link rel="apple-touch-startup-image" media="(device-width: 834px) and (device-height: 1194px) and (-webkit-device-pixel-ratio: 2) and (orientation: portrait)" href="assets/apple-touch-startup-image-1668x2388.png"><link rel="apple-touch-startup-image" media="(device-width: 834px) and (device-height: 1194px) and (-webkit-device-pixel-ratio: 2) and (orientation: landscape)" href="assets/apple-touch-startup-image-2388x1668.png"><link rel="apple-touch-startup-image" media="(device-width: 834px) and (device-height: 1112px) and (-webkit-device-pixel-ratio: 2) and (orientation: portrait)" href="assets/apple-touch-startup-image-1668x2224.png"><link rel="apple-touch-startup-image" media="(device-width: 834px) and (device-height: 1112px) and (-webkit-device-pixel-ratio: 2) and (orientation: landscape)" href="assets/apple-touch-startup-image-2224x1668.png"><link rel="apple-touch-startup-image" media="(device-width: 1024px) and (device-height: 1366px) and (-webkit-device-pixel-ratio: 2) and (orientation: portrait)" href="assets/apple-touch-startup-image-2048x2732.png"><link rel="apple-touch-startup-image" media="(device-width: 1024px) and (device-height: 1366px) and (-webkit-device-pixel-ratio: 2) and (orientation: landscape)" href="assets/apple-touch-startup-image-2732x2048.png"><meta name="msapplication-TileColor" content="#ffffff"><meta name="msapplication-TileImage" content="assets/mstile-144x144.png"><meta name="msapplication-config" content="assets/browserconfig.xml"><link rel="yandex-tableau-widget" href="assets/yandex-browser-manifest.json"><script defer="defer" src="js/chunk-vendors.921ece36.js"></script><script defer="defer" src="js/app.78f6a337.js"></script><link href="css/chunk-vendors.46f4dfde.css" rel="stylesheet"><link href="css/app.c74a3fc7.css" rel="stylesheet"></head><body><noscript><strong>We're sorry but the Contao Manager does not work without JavaScript enabled. Please enable it to continue.</strong></noscript></body></html><?php

declare(strict_types=1);

/*
 * This file is part of Contao Manager.
 *
 * (c) Contao Association
 *
 * @license LGPL-3.0-or-later
 */

use Contao\ManagerApi\ApiKernel;
use Contao\ManagerApi\HttpKernel\ApiProblemResponse;
use Symfony\Component\HttpFoundation\Request;

require __DIR__.'/../vendor/autoload.php';

try {
    // @phpstan-ignore identical.alwaysFalse
    $kernel = new ApiKernel('@symfony_env@' === 'prod' ? 'prod' : 'dev');

    $request = Request::createFromGlobals();
    $response = $kernel->handle($request);
    $response->send();
    $kernel->terminate($request, $response);
} catch (Throwable $throwable) {
    ApiProblemResponse::createFromException($throwable, '@symfony_env@' !== 'prod')->send();
}
.view-recovery__header{max-width:280px;margin-left:auto;margin-right:auto;padding:40px 0 10px;text-align:center}.view-recovery__icon{background:var(--contao);border-radius:10px;padding:10px}.view-recovery__headline{margin-top:15px;font-size:36px;font-weight:100;line-height:1}.view-recovery__content{margin:0 30px 50px}@media(min-width:960px){.view-recovery__content{margin-left:50px;margin-right:50px}}.view-recovery__description{font-weight:600;max-width:600px;margin:0 auto;text-align:center}.view-recovery__console{margin:30px 0 60px}.view-recovery__option{margin:50px 0 0;padding:20px 20px 30px;background:var(--table-odd-bg);text-align:center}.view-recovery__option h3{position:relative;top:-40px;margin-bottom:-25px;font-size:2em;font-weight:300}.view-recovery__option button{margin-top:1.5em}.view-recovery__failed{margin:10px 0;color:var(--btn-alert);font-weight:600}.popup-overlay{position:fixed;inset:0;z-index:1000;background:var(--popup-overlay-bg)}@media(min-width:960px){.popup-overlay{padding:20px 0;overflow-y:auto}}.popup-overlay__popup{position:fixed;display:block;top:50%;left:50%;width:500px;max-width:90%;background:var(--popup-bg);z-index:10;opacity:1;transform:translate(-50%,-50%);border-radius:var(--border-radius);overflow:hidden}.popup-overlay__headline{position:relative;margin-bottom:0;padding:7px 30px 6px;background:var(--popup-hl-bg);font-size:18px;color:#fff;font-weight:300;line-height:1.5em;text-align:center}.popup-overlay__headline--primary{background-color:var(--btn-primary)}.popup-overlay__headline--alert{background-color:var(--btn-alert)}.popup-overlay__content{padding:2em 20px}.popup-overlay__actions{display:flex;justify-content:center;gap:10px;flex-wrap:wrap;padding:0 20px 2em}.popup-overlay__actions .widget-button{width:auto;height:35px;padding:0 30px;line-height:35px}@media(min-width:550px){.popup-overlay__actions,.popup-overlay__content{padding-left:40px;padding-right:40px}}.loader__item{float:left;width:16px;height:16px;margin-right:1px;background-color:var(--contao);animation:loading 1.4s ease-in-out infinite both}.loader__item--20{animation-delay:-.64s}.loader__item--40{animation-delay:-.48s}.loader__item--60{animation-delay:-.32s}.loader__item--80{animation-delay:-.16s}@keyframes loading{0%,90%,to{opacity:0}20%{opacity:1}}.loader__text{float:left;width:40px}.sk-circle{width:25px;height:25px;position:relative}.sk-circle .sk-child{width:100%;height:100%;position:absolute;left:0;top:0}.sk-circle .sk-child:before{content:"";display:block;margin:0 auto;width:15%;height:15%;background-color:var(--text);border-radius:100%;animation:sk-circleBounceDelay 1.2s ease-in-out infinite both}.sk-circle .sk-circle2{transform:rotate(30deg)}.sk-circle .sk-circle3{transform:rotate(60deg)}.sk-circle .sk-circle4{transform:rotate(90deg)}.sk-circle .sk-circle5{transform:rotate(120deg)}.sk-circle .sk-circle6{transform:rotate(150deg)}.sk-circle .sk-circle7{transform:rotate(180deg)}.sk-circle .sk-circle8{transform:rotate(210deg)}.sk-circle .sk-circle9{transform:rotate(240deg)}.sk-circle .sk-circle10{transform:rotate(270deg)}.sk-circle .sk-circle11{transform:rotate(300deg)}.sk-circle .sk-circle12{transform:rotate(330deg)}.sk-circle .sk-circle2:before{animation-delay:-1.1s}.sk-circle .sk-circle3:before{animation-delay:-1s}.sk-circle .sk-circle4:before{animation-delay:-.9s}.sk-circle .sk-circle5:before{animation-delay:-.8s}.sk-circle .sk-circle6:before{animation-delay:-.7s}.sk-circle .sk-circle7:before{animation-delay:-.6s}.sk-circle .sk-circle8:before{animation-delay:-.5s}.sk-circle .sk-circle9:before{animation-delay:-.4s}.sk-circle .sk-circle10:before{animation-delay:-.3s}.sk-circle .sk-circle11:before{animation-delay:-.2s}.sk-circle .sk-circle12:before{animation-delay:-.1s}@keyframes sk-circleBounceDelay{0%,80%,to{transform:scale(0)}40%{transform:scale(1)}}.widget-button .loader{width:25px;margin:0 auto}.widget-button .sk-circle .sk-child:before{background-color:#fff}.loading-button{position:relative}.loading-button>.loader{position:absolute;left:calc(50% - 12.5px);top:calc(50% - 12.5px)}.loading-button>.loading{visibility:hidden}.loading-button.widget-button--small>.loader{left:calc(50% - 10px);top:calc(50% - 10px)}.loading-button.widget-button--small .sk-circle{width:20px;height:20px}.link-menu{position:absolute;display:grid;grid-template:1fr/1fr;left:50%;gap:2px;margin:0;padding:2px;text-align:center;list-style-type:none;white-space:nowrap;background:var(--form-bg);border-top:3px solid var(--text);border-radius:5px;z-index:100;box-shadow:0 0 1px var(--shadow);outline:none}.link-menu:before{position:absolute;left:50%;top:-7px;width:0;height:0;margin-left:-4px;border-style:solid;border-width:0 3.5px 4px 3.5px;border-color:transparent transparent var(--text) transparent;content:""}.link-menu--align-left{left:0;right:auto}.link-menu--align-left:before{left:17px;right:auto}.link-menu--align-right{left:auto;right:0}.link-menu--align-right:before{left:auto;right:17px}.link-menu--valign-top{bottom:0;border-top:none;border-bottom:3px solid var(--text);box-shadow:0 0 2px var(--shadow)}.link-menu--valign-top:before{top:auto;bottom:-7px;border-width:4px 3.5px 0 3.5px;border-color:var(--text) transparent transparent transparent}.link-menu--contao{border-color:var(--contao)}.link-menu--contao:before{border-bottom-color:var(--contao)}.link-menu--contao.link-menu--valign-top:before{border-bottom-color:transparent;border-top-color:var(--contao)}.link-menu--primary{border-color:var(--btn-primary)}.link-menu--primary:before{border-bottom-color:var(--btn-primary)}.link-menu--primary.link-menu--valign-top:before{border-bottom-color:transparent;border-top-color:var(--btn-primary)}.link-menu--warning{border-color:var(--btn-warning)}.link-menu--warning:before{border-bottom-color:var(--btn-warning)}.link-menu--warning.link-menu--valign-top:before{border-bottom-color:transparent;border-top-color:var(--btn-warning)}.link-menu--alert{border-color:var(--btn-alert)}.link-menu--alert:before{border-bottom-color:var(--btn-alert)}.link-menu--alert.link-menu--valign-top:before{border-bottom-color:transparent;border-top-color:var(--btn-alert)}.link-menu__item{margin:0;padding:0;display:block}.link-menu__action{display:block;width:100%;border-radius:5px;padding:8px 16px;color:var(--text);font-size:inherit;text-align:center;background:none;border:none;cursor:pointer}.link-menu__action:hover{color:var(--text);background:var(--focus);text-decoration:none}.link-menu__action--active{font-weight:600;background:var(--focus)}.footer-languages{position:relative;display:inline-block}.footer-languages__toggle{width:auto;height:auto;padding:0 0 0 25px;background:transparent;color:var(--text);font-size:12px;font-weight:300;line-height:20px;background:var(--svg--language) left center no-repeat;background-size:20px 20px;border:none;cursor:pointer}.footer-languages__toggle:hover{color:var(--black)}.footer-languages__menu{display:grid;grid-template:auto/1fr 1fr;bottom:25px;white-space:nowrap;transform:translateX(-50%)}.footer-languages__menu button{margin:0;padding:6px;text-align:left;font-size:inherit}.theme-switch{position:relative;display:inline-block}.theme-switch button{width:auto;height:auto;padding:0 0 0 24px;background:transparent;color:var(--text);font-size:12px;font-weight:300;line-height:20px;background:var(--svg--color-scheme) left center no-repeat;background-size:20px 20px;border:none;cursor:pointer}.theme-switch button:hover{color:var(--black)}.package-logo--fallback[data-v-9c1c5f6c]{display:flex;justify-content:center;align-items:center}svg[data-v-9c1c5f6c]{width:80px;height:80px;fill:#ccc}.discover-package{display:flex;flex-direction:column;position:relative;overflow:hidden;background:var(--tiles-bg);border:1px solid var(--tiles-bdr);border-radius:14px}.discover-package.is--hint{border-color:var(--border--light)}.discover-package.is--hint .discover-package__inside>*{opacity:.65}.discover-package__hint{position:relative;background:var(--border--light);padding:8px 16px;font-weight:400;font-size:12px;line-height:1.2;z-index:1}.discover-package__hint p a{display:inline-block;padding-right:10px}.discover-package__hint p a:first-child{margin-left:10px}.discover-package__hint p a:not(:first-child):before{padding-right:10px;content:"|"}.discover-package__inside{flex-grow:1;padding:16px}.discover-package__abandoned{display:inline-block;margin-bottom:1em;padding:2px 5px;color:#fff;font-size:12px;font-weight:600;background:var(--btn-alert);cursor:help;z-index:10}@media(min-width:600px){.discover-package__abandoned{position:absolute;top:20px;left:-25px;padding:2px 30px;border-top:1px solid var(--btn-alert-active);transform:rotate(-45deg)}}.discover-package__icon{border-radius:6px;height:60px;width:60px;background:#f7f7f7;margin:0 auto 10px;position:absolute;right:16px}.discover-package__icon>figure{display:flex;align-items:center;justify-content:center;height:100%;max-height:140px}.discover-package__icon img,.discover-package__icon svg{border-radius:4px;width:50px;height:50px;max-height:100%;object-fit:contain}.discover-package__details{display:flex;flex-direction:column;justify-content:space-between;min-height:96px}.discover-package__headline{margin-bottom:.2em;line-height:1;overflow-wrap:break-word;margin-right:70px}.discover-package__headline em{background-color:var(--highlight-bg);color:var(--highlight-color);font-style:normal}.discover-package__versions{display:flex;flex-wrap:wrap;gap:5px;list-style:none;margin:5px 0;padding:0}.discover-package__version{display:inline-flex;justify-content:center;padding:3px 5px;border-radius:4px;line-height:1;min-width:40px;font-size:13px;color:#fff;background:var(--badge-bg);pointer-events:none}.discover-package__description{display:-webkit-box;overflow:hidden;-webkit-line-clamp:2;-webkit-box-orient:vertical;margin-bottom:1em;margin-right:70px}.discover-package__description em{background-color:var(--highlight-bg);color:var(--highlight-color);font-style:normal}.discover-package__more{display:flex;flex-flow:row wrap;align-items:flex-end;flex-grow:1;gap:4px;line-height:28px}.discover-package__counts{flex-grow:1;justify-content:flex-start}.discover-package__count{display:inline-block;margin-right:15px;padding-left:18px;font-size:13px;background-position:0 50%;background-repeat:no-repeat;background-size:13px 13px}.discover-package__count--private{background-image:var(--svg--private)}.discover-package__count--updated{background-image:var(--svg--updated)}.discover-package__count--downloads{background-image:var(--svg--downloads)}.discover-package__count--favers{background-image:var(--svg--favers)}.discover-package__actions{flex-grow:1;display:flex;justify-content:flex-end;gap:8px}@media(max-width:599.98px){.discover-package__headline-container{display:flex;flex-direction:column-reverse}}@media(min-width:600px){.discover-package__inside{text-align:initial;display:flex;padding:0}.discover-package__icon{width:130px;height:100%;min-height:130px;margin:0;border-radius:0;position:revert;right:revert}.discover-package__icon img{width:100px;height:100px}.discover-package__icon svg{width:90px;height:90px}.discover-package__details{padding:16px;height:100%;min-height:90px;max-width:calc(100% - 130px);flex:1}.discover-package__versions{float:right;margin:-3px 0 0 16px}.discover-package__description,.discover-package__headline{margin-right:0}.discover-package__more{flex-direction:row}.discover-package__actions{justify-content:end}}.vueperslide{white-space:normal;background-size:cover;flex-shrink:0;display:block;width:100%;position:relative}.vueperslide--clone-1{position:absolute;top:0;bottom:0;right:100%}.vueperslides--rtl .vueperslide--clone-1{right:auto;left:100%}.vueperslide[href]{-webkit-user-drag:none}.vueperslide__image{background-size:cover}.vueperslide__image,.vueperslide__loader{position:absolute;top:0;left:0;right:0;bottom:0}.vueperslide__loader{display:flex;flex-direction:column;align-items:center;justify-content:center}.vueperslide__content-wrapper:not(.vueperslide__content-wrapper--outside-top):not(.vueperslide__content-wrapper--outside-bottom){height:100%;margin:auto}.vueperslides--fade .vueperslide{position:absolute;top:0;left:0;right:0;bottom:0;opacity:0;transition:opacity ease-in-out;transition-duration:inherit}.vueperslides--fade .vueperslide--active,.vueperslides--fade .vueperslide--visible{z-index:1;opacity:1}.vueperslides--slide-image-inside .vueperslide{overflow:hidden}.vueperslides--3d .vueperslide{position:absolute;z-index:-1;height:100%}.vueperslides--3d .vueperslide--active,.vueperslides--3d .vueperslide--next-slide,.vueperslides--3d .vueperslide--previous-slide{z-index:0}.vueperslides--3d .vueperslide--active{z-index:1}.vueperslides--3d .vueperslide[face=front]{transform:rotateY(90deg) translate(-50%) rotateY(-90deg)}.vueperslides--3d .vueperslide[face=right]{transform:rotateY(90deg) translate(50%);transform-origin:100% 0}.vueperslides--3d .vueperslide[face=back]{transform:rotateY(270deg) translate(-50%) rotateY(-90deg)}.vueperslides--3d .vueperslide[face=left]{transform:rotateY(270deg) translate(-50%);transform-origin:0 0}.vueperslides:not(.no-shadow):not(.vueperslides--3d) .vueperslides__parallax-wrapper:after,.vueperslides:not(.no-shadow):not(.vueperslides--3d) .vueperslides__parallax-wrapper:before{content:"";position:absolute;bottom:100%;left:-1em;right:-1em;height:2em;box-shadow:0 0 20px #00000040;z-index:2}.vueperslides:not(.no-shadow):not(.vueperslides--3d) .vueperslides__parallax-wrapper:after{top:100%;bottom:auto}.vueperslides__arrows{color:#fff}.vueperslides__arrows--outside{color:currentColor}.vueperslides__arrow{top:50%;background-color:transparent;border:none;opacity:.7}.vueperslides--rtl .vueperslides__arrow--next,.vueperslides__arrow--prev{right:auto;left:.5em}.vueperslides--rtl .vueperslides__arrow--prev,.vueperslides__arrow--next{left:auto;right:.5em}.vueperslides__arrow:hover{opacity:1}.vueperslides--rtl .vueperslides__arrows--outside .vueperslides__arrow--next,.vueperslides__arrows--outside .vueperslides__arrow--prev{right:auto;left:-3.5em}.vueperslides--rtl .vueperslides__arrows--outside .vueperslides__arrow--prev,.vueperslides__arrows--outside .vueperslides__arrow--next{left:auto;right:-3.5em}.vueperslides__paused{top:.7em;right:.7em;opacity:0;text-shadow:0 0 3px rgba(0,0,0,.4);z-index:1}.vueperslides:hover .vueperslides__paused{opacity:1}.vueperslides__bullets:not(.vueperslides__bullets--outside){color:#fff}.vueperslides__bullet{margin:1.5em .6em;padding:0;border:none;background:none}.vueperslides__bullet .default{width:12px;height:12px;border-radius:12px;border:1px solid currentColor;background-color:transparent;box-shadow:0 0 1px #00000080,0 0 3px #0000004d;transition:.4s ease-in-out;box-sizing:border-box}.vueperslides__bullet .default span{display:none}.vueperslides__bullet--active .default{border-width:6px}.vueperslide,.vueperslide__image{background-position:50%}.vueperslide__video{outline:none}.vueperslide--no-pointer-events:before{content:"";position:absolute;top:0;bottom:0;left:0;right:0}.vueperslide__content-wrapper:not(.vueperslide__content-wrapper--outside-top):not(.vueperslide__content-wrapper--outside-bottom){display:flex;flex:1 1 auto;flex-direction:column;align-items:center;justify-content:center;text-align:center}.vueperslide--has-image-inside .vueperslide__content-wrapper,.vueperslide--has-video .vueperslide__content-wrapper,.vueperslide__content-wrapper.parallax-fixed-content{position:absolute;z-index:2;top:0;bottom:0;left:0;right:0;display:flex;flex-direction:column;justify-content:center;align-items:center;pointer-events:none}.vueperslides{position:relative}.vueperslides--fixed-height .vueperslide,.vueperslides--fixed-height .vueperslides__inner,.vueperslides--fixed-height .vueperslides__parallax-wrapper{height:inherit}.vueperslides--fixed-height .vueperslides__parallax-wrapper{padding-bottom:0!important}.vueperslides--fixed-height.vueperslides--bullets-outside{margin-bottom:4em}.vueperslides__inner{position:relative;-webkit-user-select:none;-moz-user-select:none;user-select:none}.vueperslides__parallax-wrapper{position:relative;overflow:hidden}.vueperslides--3d .vueperslides__parallax-wrapper{overflow:visible}.vueperslides__track{position:absolute;top:0;height:100%;left:0;right:0;overflow:hidden;z-index:1}.vueperslides--parallax .vueperslides__track{height:200%;transform:translateY(0)}.vueperslides--touchable .vueperslides__track{cursor:ew-resize;cursor:grab}.vueperslides--touchable .vueperslides__track--dragging,.vueperslides--touchable .vueperslides__track--mousedown{cursor:grabbing}.vueperslides--3d .vueperslides__track{overflow:visible;perspective:100em}.vueperslides__track-inner{white-space:nowrap;transition:transform .5s ease-in-out;height:100%;display:flex}.vueperslides--no-animation .vueperslides__track-inner{transition-duration:0s!important}.vueperslides--fade .vueperslides__track-inner{white-space:normal;transition:none}.vueperslides--3d .vueperslides__track-inner{transform-style:preserve-3d}.vueperslides__track--mousedown .vueperslides__track-inner{transition:transform .25s ease-in-out!important}.vueperslides__track--dragging .vueperslides__track-inner{transition:none}.vueperslides__arrow{position:absolute;font-size:inherit;color:inherit;text-align:center;transform:translateY(-50%);transition:.3s ease-in-out;cursor:pointer;-webkit-user-select:none;-moz-user-select:none;user-select:none;outline:none;z-index:2;line-height:1}.vueperslides__arrow svg{vertical-align:middle;stroke:currentColor;fill:none;width:3.5em;padding:1em;stroke-width:1;transition:.3s ease-in-out;box-sizing:border-box}.vueperslides__arrow svg:hover{stroke-width:1.3}.vueperslides__paused{position:absolute;transition:.3s ease-in-out}.vueperslides__bullets{display:flex;justify-content:center;position:absolute;bottom:0;left:0;right:0}.vueperslides__bullets--outside{position:relative}.vueperslides__bullet,.vueperslides__bullets button{cursor:pointer;-webkit-user-select:none;-moz-user-select:none;user-select:none;outline:none;z-index:2;display:flex;justify-content:center;align-items:center;color:inherit}.vueperslides__bullet::-moz-focus-inner,.vueperslides__bullets button::-moz-focus-inner{border:0}.vueperslides__fractions{position:absolute;top:.8em;left:.5em;z-index:2;padding:.2em 1em;border:1px solid hsla(0,0%,100%,.5);border-radius:2em;background:#fff3;color:#fff}.vueperslides__progress{position:absolute;top:0;left:0;right:0;z-index:2;height:6px;color:#000000b3}.vueperslides__progress>*{position:absolute;top:0;bottom:0;left:0;background:currentColor;transition:.3s ease-in-out}@media(min-width:1200px){.ads{margin:59px 0 69px}}.ads .link{padding-top:5px;text-align:right}.ads .link a{padding-left:16px;font-size:.8em;color:inherit;background:var(--svg--link-blank) left center no-repeat;background-size:13px 13px}.ads .container{position:relative;background:var(--popup-bg);box-shadow:var(--ad-shadow);border-radius:14px;overflow:hidden}.ads .container a,.ads .container img{display:block}.ads .container img{width:100%;aspect-ratio:2}.vueperslides__arrow:focus-visible{outline:5px auto Highlight!important;outline:5px auto -webkit-focus-ring-color!important}.package-sorting{margin:20px 0 15px;text-align:right}.package-sorting__label{display:inline-block;text-transform:uppercase}.package-sorting__label:after{content:":"}.package-sorting__group{position:relative;display:inline-flex;flex-direction:column;margin:0;padding:0 15px 0 0;list-style-type:none;text-align:left}.package-sorting__group:after{content:"";position:absolute;top:.8em;right:0;width:0;height:0;border-left:5px solid transparent;border-right:5px solid transparent;border-top:5px solid #777}.package-sorting__item{display:none;margin:0 0 0 10px;padding:3px 0;border-bottom:2px solid transparent}.package-sorting__item:hover{color:var(--link)}.package-sorting__item--open{display:inline}.package-sorting__item--active{display:inline;color:var(--link);border-bottom:2px solid var(--link)}.package-sorting__item button{margin:0;padding:0;background:none;border:none;text-transform:uppercase;cursor:pointer}@media(min-width:600px){.package-sorting__group{flex-direction:row;justify-content:flex-end;padding:0}.package-sorting__group:after{content:none}.package-sorting__item{display:inline}}.search-bar{position:relative}.search-bar__input{height:50px!important;padding-right:45px!important;border-radius:50px!important}.search-bar__button{position:absolute;top:5px;right:5px;display:flex;align-items:center;width:38px;height:40px;margin:0;padding:7px;line-height:36px;border:none;border-radius:0 50px 50px 0;background:none}.package-search{position:relative}.package-search__input{max-width:400px;margin:0 20px}@media(min-width:1024px){.package-search__input{margin-right:0}}.package-search__headline{font-size:18px;font-weight:300;margin:30px 0 10px}.package-search__results{display:grid;gap:20px;margin-bottom:20px}@media(min-width:1024px){.package-search__results{grid-template-columns:repeat(2,1fr)}}.package-search__status{margin:100px 0;text-align:center;font-size:20px;line-height:1.5em}.package-search__status--empty{padding-top:140px;background:url(../img/sad.c7de6e95.svg) top no-repeat;background-size:100px 100px}.package-search__status--offline{padding-top:140px;background:url(../img/offline.0c23d1ce.svg) top no-repeat;background-size:100px 100px}.package-search__status--loader .sk-circle{width:100px;height:100px;margin:0 auto 40px}.package-search__status button{margin-top:2em}.package-search__explain{font-size:16px}.package-search__more{margin:10px 0 30px;text-align:center}.package-search__more-button{display:inline-block;margin:0 auto;padding:0;text-transform:uppercase;background:none;border:none;cursor:pointer}.package-search__more-button:hover{text-decoration:underline}.package-search__algolia{display:block;width:200px;margin:50px auto 0}.vjs-tree-brackets{cursor:pointer}.vjs-tree-brackets:hover{color:#1890ff}.vjs-check-controller{position:absolute;left:0}.vjs-check-controller.is-checked .vjs-check-controller-inner{background-color:#1890ff;border-color:#0076e4}.vjs-check-controller.is-checked .vjs-check-controller-inner.is-checkbox:after{-webkit-transform:rotate(45deg) scaleY(1);transform:rotate(45deg) scaleY(1)}.vjs-check-controller.is-checked .vjs-check-controller-inner.is-radio:after{-webkit-transform:translate(-50%,-50%) scale(1);transform:translate(-50%,-50%) scale(1)}.vjs-check-controller .vjs-check-controller-inner{display:inline-block;position:relative;border:1px solid #bfcbd9;border-radius:2px;vertical-align:middle;-webkit-box-sizing:border-box;box-sizing:border-box;width:16px;height:16px;background-color:#fff;z-index:1;cursor:pointer;-webkit-transition:border-color .25s cubic-bezier(.71,-.46,.29,1.46),background-color .25s cubic-bezier(.71,-.46,.29,1.46);transition:border-color .25s cubic-bezier(.71,-.46,.29,1.46),background-color .25s cubic-bezier(.71,-.46,.29,1.46)}.vjs-check-controller .vjs-check-controller-inner:after{-webkit-box-sizing:content-box;box-sizing:content-box;content:"";border:2px solid #fff;border-left:0;border-top:0;height:8px;left:4px;position:absolute;top:1px;-webkit-transform:rotate(45deg) scaleY(0);transform:rotate(45deg) scaleY(0);width:4px;-webkit-transition:-webkit-transform .15s cubic-bezier(.71,-.46,.88,.6) .05s;transition:-webkit-transform .15s cubic-bezier(.71,-.46,.88,.6) .05s;transition:transform .15s cubic-bezier(.71,-.46,.88,.6) .05s;transition:transform .15s cubic-bezier(.71,-.46,.88,.6) .05s,-webkit-transform .15s cubic-bezier(.71,-.46,.88,.6) .05s;-webkit-transform-origin:center;transform-origin:center}.vjs-check-controller .vjs-check-controller-inner.is-radio{border-radius:100%}.vjs-check-controller .vjs-check-controller-inner.is-radio:after{border-radius:100%;height:4px;background-color:#fff;left:50%;top:50%}.vjs-check-controller .vjs-check-controller-original{opacity:0;outline:none;position:absolute;z-index:-1;top:0;left:0;right:0;bottom:0;margin:0}.vjs-carets{position:absolute;right:0;cursor:pointer}.vjs-carets svg{-webkit-transition:-webkit-transform .3s;transition:-webkit-transform .3s;transition:transform .3s;transition:transform .3s,-webkit-transform .3s}.vjs-carets:hover{color:#1890ff}.vjs-carets-close{-webkit-transform:rotate(-90deg);transform:rotate(-90deg)}.vjs-tree-node{display:-webkit-box;display:-ms-flexbox;display:flex;position:relative;line-height:20px}.vjs-tree-node.has-carets{padding-left:15px}.vjs-tree-node.has-carets.has-selector,.vjs-tree-node.has-selector{padding-left:30px}.vjs-tree-node.is-highlight,.vjs-tree-node:hover{background-color:#e6f7ff;border-radius:4px}.vjs-tree-node.is-highlight .vjs-tree-node-actions,.vjs-tree-node:hover .vjs-tree-node-actions{display:block}.vjs-tree-node .vjs-indent{display:-webkit-box;display:-ms-flexbox;display:flex;position:relative}.vjs-tree-node .vjs-indent-unit.has-line{border-left:1px dashed #bfcbd9}.vjs-tree-node .vjs-tree-node-actions{display:none;position:absolute;right:0;top:0;padding:0 4px;background-color:#e6f7ff;border-radius:4px}.vjs-tree-node .vjs-tree-node-actions .vjs-tree-node-actions-item{cursor:pointer}.vjs-tree-node .vjs-tree-node-actions .vjs-tree-node-actions-item:hover{color:#1890ff}.vjs-tree-node.dark .vjs-tree-node-actions,.vjs-tree-node.dark.is-highlight,.vjs-tree-node.dark:hover{background-color:#2e4558}.vjs-node-index{position:absolute;right:100%;margin-right:4px;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.vjs-colon{white-space:pre}.vjs-comment{color:#bfcbd9}.vjs-key{white-space:nowrap}.vjs-value{word-break:break-word}.vjs-tree-node.dynamic-height .vjs-value{white-space:pre-wrap}.vjs-value-null,.vjs-value-undefined{color:#d55fde}.vjs-value-boolean,.vjs-value-number{color:#1d8ce0}.vjs-value-string{color:#13ce66}.vjs-tree{font-family:Monaco,Menlo,Consolas,Bitstream Vera Sans Mono,monospace;font-size:14px;text-align:left}.vjs-tree.is-virtual{overflow:auto}.vjs-tree.is-virtual .vjs-tree-node{white-space:nowrap}[data-notivue=promise-resolve],[data-notivue=success]{--nv-bg:var(--nv-success-bg);--nv-fg:var(--nv-success-fg);--nv-accent:var(--nv-success-accent,var(--nv-global-accent));--nv-border:var(--nv-success-border)}[data-notivue=error],[data-notivue=promise-reject]{--nv-bg:var(--nv-error-bg);--nv-fg:var(--nv-error-fg);--nv-accent:var(--nv-error-accent,var(--nv-global-accent));--nv-border:var(--nv-error-border)}[data-notivue=warning]{--nv-bg:var(--nv-warning-bg);--nv-fg:var(--nv-warning-fg);--nv-accent:var(--nv-warning-accent,var(--nv-global-accent));--nv-border:var(--nv-warning-border)}[data-notivue=info]{--nv-bg:var(--nv-info-bg);--nv-fg:var(--nv-info-fg);--nv-accent:var(--nv-info-accent,var(--nv-global-accent));--nv-border:var(--nv-info-border)}[data-notivue=promise]{--nv-bg:var(--nv-promise-bg);--nv-fg:var(--nv-promise-fg);--nv-accent:var(--nv-promise-accent,var(--nv-global-accent));--nv-border:var(--nv-promise-border)}.Notivue__notification{--tip-width:calc(var(--tip-width-fx, 1)*var(--nv-tip-width, 0px));box-sizing:border-box;position:relative;width:var(--nv-min-width,auto);max-width:var(--nv-width,100%);background-color:var(--nv-bg,var(--nv-global-bg));display:flex;align-items:var(--nv-y-align);border-radius:var(--nv-radius,0);border:var(--nv-border-width,0) solid var(--nv-border,var(--nv-global-border));box-shadow:var(--nv-shadow,0 0 transparent),inset var(--tip-width) 0 0 var(--nv-accent)}.Notivue__notification *{box-sizing:border-box;touch-action:manipulation}.Notivue__notification[data-notivue-has-title=true]{align-items:var(--nv-y-align-has-title,var(--nv-y-align))}.Notivue__icon{display:flex;justify-content:center;align-items:center;overflow:visible;min-width:var(--nv-icon-size);width:var(--nv-icon-size);height:var(--nv-icon-size);margin:var(--nv-spacing) 0 var(--nv-spacing) var(--nv-spacing);color:var(--nv-accent)}.Notivue__content{--nv-content-space:calc(var(--nv-spacing) + var(--nv-spacing)*0.15);display:flex;flex-direction:column;flex-grow:1;text-align:inherit;padding:var(--nv-content-space)}.Notivue__content-title{line-height:1.15;font-weight:700;color:var(--nv-fg,var(--nv-global-fg));font-size:var(--nv-title-size);margin:0 0 .33em;padding:0}.Notivue__transition-enter-active{--dur-easing:.5s cubic-bezier(.16,1,.3,1);transition:opacity var(--dur-easing),transform var(--dur-easing)}@media (prefers-reduced-motion:reduce){.Notivue__transition-enter-active{transition:none}}.Notivue__transition-enter-from{opacity:0;transform:scale(.8)}.Notivue__transition-enter-to{opacity:1;transform:scale(1)}.Notivue__transition-leave-active{transition:opacity 0ms ease}.Notivue__transition-leave-from,.Notivue__transition-leave-to{opacity:0}.Notivue__content-message{max-height:250px;overflow:auto;line-height:1.375;margin:0;padding:0;white-space:pre-line}.Notivue__close,.Notivue__content-message{color:var(--nv-fg,var(--nv-global-fg));font-size:var(--nv-message-size)}.Notivue__close{position:relative;cursor:pointer;padding:calc(var(--nv-spacing)/2);margin:var(--nv-spacing) var(--nv-spacing) var(--nv-spacing) 0;font-weight:700;border:none;background:none;line-height:1;-webkit-tap-highlight-color:rgba(0,0,0,0)}.Notivue__close:after{content:"";position:absolute;top:0;right:0;bottom:0;left:0;width:100%;height:100%;background-color:var(--nv-fg,var(--nv-global-fg));opacity:0;border-radius:calc(var(--nv-radius)/2);transition:opacity .1s ease-out}@media (hover:hover){.Notivue__close:hover{opacity:1}.Notivue__close:hover:after{opacity:.1}.Notivue__close:hover .Notivue__close-icon{opacity:1}}.Notivue__close-icon{width:var(--nv-icon-size);height:var(--nv-icon-size);display:flex;color:var(--nv-fg,var(--nv-global-fg));pointer-events:none;opacity:.65}.Notivue__spinner{transform-origin:center;animation:Notivue__spinner-kf .75s linear infinite}@keyframes Notivue__spinner-kf{to{transform:rotate(1turn)}}@media (prefers-reduced-motion:reduce){.Notivue__duplicate,.Notivue__spinner{animation:none}}[dir=rtl] .Notivue__notification{--tip-width-fx:-1}[dir=rtl] .Notivue__icon{margin:var(--nv-spacing) var(--nv-spacing) var(--nv-spacing) 0}[dir=rtl] .Notivue__content-message{font-size:calc(var(--nv-message-size) + .1em)}[dir=rtl] .Notivue__content-title{font-size:calc(var(--nv-title-size) + .1em)}[dir=rtl] .Notivue__close{margin:var(--nv-spacing) 0 var(--nv-spacing) var(--nv-spacing)}.Notivue__duplicate{animation:Notivue__duplicate-kf .3s cubic-bezier(.16,1,.3,1) forwards}@keyframes Notivue__duplicate-kf{0%{transform:scale(1);opacity:1}50%{transform:scale(1.035);opacity:.8}to{transform:scale(1);opacity:1}}[data-notivue-align=top] .Notivue__enter,[data-notivue-align=top] .Notivue__leave{--notivue-ty:-200%}[data-notivue-align=bottom] .Notivue__enter,[data-notivue-align=bottom] .Notivue__leave{--notivue-ty:200%}.Notivue__enter{animation:Notivue__enter-kf .35s cubic-bezier(.5,1,.25,1)}.Notivue__leave{animation:Notivue__leave-kf .35s ease}.Notivue__clearAll{animation:Notivue__clearAll-kf .5s cubic-bezier(.22,1,.36,1)}@keyframes Notivue__enter-kf{0%{transform:translate3d(0,var(--notivue-ty),0) scale(.25);opacity:0}to{transform:translateZ(0) scale(1);opacity:1}}@keyframes Notivue__leave-kf{0%{transform:translateZ(0) scale(1);opacity:.7}to{transform:translate3d(0,var(--notivue-ty),0) scale(0);opacity:0}}@keyframes Notivue__clearAll-kf{0%{opacity:1}to{opacity:0}}.boot-check{padding:10px}.boot-check:after{display:table;clear:both;content:""}.boot-check__icon{float:left}.boot-check__icon .sk-circle{width:34px;height:34px;margin:3px}.boot-check__icon svg{display:block;width:40px;height:40px}.boot-check__icon--success svg{fill:var(--btn-primary)}.boot-check__icon--info svg,.boot-check__icon--warning svg{fill:var(--btn-warning)}.boot-check__icon--error svg{fill:var(--btn-alert)}.boot-check__label{margin-left:50px}.boot-check__description,.boot-check__detail,.boot-check__title{margin:0;line-height:inherit;overflow:hidden;text-overflow:ellipsis}.boot-check ul.boot-check__description{padding:0 0 0 1em;list-style:"- "}.boot-check ul.boot-check__description li{padding:0;margin:0}.boot-check__detail{margin-top:5px;font-size:12px}.boot-check__action{margin-left:50px}.boot-check__action button{margin:15px 0 10px;height:33px;line-height:33px}@media(min-width:960px){.boot-check__label{float:left;width:540px;margin-left:10px}.boot-check__action{float:right;margin:0 0 0 10px;width:140px;text-align:center}.boot-check__action button{margin:3px 0}.boot-check__action a[target=_blank]{display:inline-block;margin:10px 0;padding-left:20px;background:var(--svg--link-blank) left center no-repeat;background-size:16px 16px}}.view-boot__header{margin-left:auto;margin-right:auto;padding:40px 0;text-align:center}.view-boot__icon{background:var(--contao);border-radius:10px;padding:10px}.view-boot__headline{margin-top:15px;font-size:36px;font-weight:100;line-height:1}.view-boot__description{margin:0;font-weight:600}.view-boot__loading{width:30px;margin:0 auto 40px}.view-boot__loading .sk-circle{width:30px;height:30px}.view-boot__checks{margin:0 16px 50px}.view-boot__checks .boot-check:nth-child(odd){border-radius:var(--border-radius);background:var(--table-odd-bg)}.view-boot__summary{margin:50px 0 0}.view-boot__summary--error svg{width:100%;height:40px;fill:var(--btn-alert)}.view-boot__issue{max-width:60%;margin:10px auto;text-align:center;color:var(--btn-alert);line-height:1.2em}.view-boot__safeMode{margin:2em auto 0}.view-boot__continue,.view-boot__safeMode{clear:both;display:block!important;width:220px!important}.view-boot__continue{margin:0 auto}@media(min-width:960px){.view-boot__checks{margin:0 80px 50px}}.link-more{position:relative;display:inline-block}p:empty+.link-more{margin-left:0}.link-more button{width:auto;height:auto;padding:0 0 5px;background:transparent;color:var(--link);font-size:13px;font-weight:300;line-height:inherit;border:none;cursor:pointer}.link-more button:hover{text-decoration:underline}.link-more__menu{outline:none}.link-more ul{transform:translateX(-50%)}.package-link{display:flex;column-gap:8px;justify-content:space-between;width:100%;padding-bottom:4px;margin-bottom:4px;border-bottom:1px solid var(--border--light)}.package-link:last-child{padding-bottom:0;margin-bottom:0;border-bottom:none}.package-link__details{padding:5px 0;line-height:18px}.package-link__name{display:inline;font-weight:600}.package-link__name:after{content:": "}.package-link__text{display:inline}.package-link__actions{display:flex;margin-left:20px;margin:0 -4px}.package-link__actions>*{margin:0 4px}.package-link--limit .package-link__details{display:flex}.package-link--limit .package-link__name{white-space:nowrap}.package-link--limit .package-link__text{display:-webkit-box;overflow:hidden;line-clamp:1;-webkit-line-clamp:1;-webkit-box-orient:vertical;padding:0 10px 0 5px}.package-funding[data-v-5a8fd14b]{padding:10px 20px 10px 50px;font-weight:400;font-size:12px;line-height:1.8;background:rgba(var(--funding-rgb),.025) url(../img/funding.cf78a0a0.svg) 15px 50% no-repeat;background-size:23px 23px;border:1px solid rgba(var(--funding-rgb),.5);border-radius:6px}.package-funding>div[data-v-5a8fd14b]{overflow:hidden}.package-funding span[data-v-5a8fd14b]{margin-right:15px}.package-funding a[data-v-5a8fd14b]{position:relative;display:inline-block;margin:0 20px 0 0;padding-left:16px;color:var(--funding);background:url(../img/link-funding.b25cd92d.svg) 0 50% no-repeat;background-size:13px 13px}.package-funding a[data-v-5a8fd14b]:before{content:"|";position:absolute;left:-12px}.package-funding a[data-v-5a8fd14b]:nth-child(2):before{content:none}.package-popup{position:fixed;display:flex;flex-direction:column;justify-content:flex-start;width:100%;max-width:none;height:100%;background:var(--popup-bg);z-index:10;opacity:1}.package-popup>*{flex-basis:auto;flex-grow:1}.package-popup__loader{display:flex;flex-direction:column;align-items:center;justify-content:center;padding:50px 0}.package-popup__loader p{margin:1em}.package-popup__headline{position:relative;flex-grow:0;flex-shrink:1;padding:7px 30px 6px;background:var(--popup-hl-bg);color:#fff;font-size:18px;font-weight:300;line-height:1.5;text-align:center}.package-popup__button{display:block;float:right;position:absolute;top:0;margin:4px 0;padding:4px;background:none;border:1px solid transparent;border-radius:5px;cursor:pointer}.package-popup__button--previous{left:4px}.package-popup__button--close{right:4px}.package-popup__button svg{display:block;width:22px;height:22px}.package-popup__button:hover{background-color:#db6f00}.package-popup__summary{flex-grow:0;padding:25px 35px}@media(min-width:600px){.package-popup__summary{display:flex}}.package-popup__logo{border-radius:6px;float:right;height:60px;width:60px;margin-left:1em;background:#f7f7f7}@media(min-width:600px){.package-popup__logo{display:block;float:left;width:110px;height:110px;margin:-10px 16px 0 -10px}}.package-popup__icon{display:flex;align-items:center;justify-content:center;height:100%}.package-popup__icon--fallback{display:none}.package-popup__icon img{width:50px;height:50px;max-height:100%;object-fit:contain}@media(min-width:600px){.package-popup__icon img{width:90px;height:90px}}.package-popup__text{display:flex;flex-direction:column;flex-grow:1}@media(min-width:600px){.package-popup__text{width:200px}}.package-popup__title{margin:0;line-height:1.4;overflow-wrap:break-word}.package-popup__authors{flex-grow:1;font-size:13px;margin-bottom:.5em}.package-popup__author{display:inline-block;margin-right:2px}.package-popup__author:after{color:var(--text);content:", "}.package-popup__author:last-child:after{content:none}.package-popup__stats{display:inline-block;margin-right:15px;margin-top:.5em;padding-left:18px;font-size:13px;background-position:0 50%;background-repeat:no-repeat;background-size:13px 13px}.package-popup__stats--private{padding-left:20px;background-image:var(--svg--private);background-size:15px 15px}.package-popup__stats--updated{background-image:var(--svg--updated)}.package-popup__stats--downloads{background-image:var(--svg--downloads)}.package-popup__stats--favers{background-image:var(--svg--favers)}.package-popup__actions{display:flex;flex-direction:column;gap:10px;margin-top:1em}@media(min-width:600px){.package-popup__actions{margin:0 0 0 25px;width:200px}}.package-popup__installed{margin-top:1em}.package-popup__abandoned{margin:0 0 20px;padding:10px 20px 10px 50px;font-weight:400;font-size:12px;line-height:1.8;background:rgba(var(--hint-rgb),.3) url(../img/hint.ba2ac97e.svg) 15px 50% no-repeat;background-size:23px 23px;border:1px solid var(--hint-link);border-radius:6px}.package-popup__funding{margin:0 0 20px}.package-popup__tabs{position:relative;flex-grow:revert}.package-popup__tabs:after,.package-popup__tabs:before{content:"";display:block;position:absolute;top:0;bottom:1px;width:7px;background:linear-gradient(-90deg,transparent 0,var(--popup-bg) 50%);z-index:1;pointer-events:none}.package-popup__tabs:after{background:linear-gradient(90deg,transparent 0,var(--popup-bg) 50%);right:0}.package-popup__tabs-list{flex-shrink:0;flex-grow:0;display:flex;column-gap:4px;height:40px;min-width:100%;overflow-x:auto;scrollbar-width:none;overflow-y:hidden;margin:0;padding:0 7px;list-style-type:none}.package-popup__tabs-list:after{content:"";position:absolute;inset:auto 0 0;height:1px;background:var(--border--light);z-index:-1}.package-popup__tab{position:relative;top:1px;flex-grow:1;padding:0;height:39px;line-height:39px;text-align:center;border:1px solid var(--border--light);border-top-left-radius:6px;border-top-right-radius:6px}.package-popup__tab--active{background:var(--tab-content);border-bottom:1px solid var(--tab-content)}.package-popup__tab button{display:flex;justify-content:center;align-items:center;width:100%;height:100%;margin:0;padding:0 10px;border:none;background:transparent;cursor:pointer}.package-popup__tab button:disabled{color:var(--border)!important;cursor:not-allowed}.package-popup__pill{position:relative;top:-2px;display:inline-block;margin-left:5px;padding:2px 5px;font-size:10px;font-weight:400;background:var(--border--light);border-radius:40%}.package-popup__pill--highlight{color:var(--clr-btn);background:var(--btn-primary)}.package-popup__tabcontent{position:relative;padding:25px 35px;overflow-y:auto;background:var(--tab-content);outline:0}@media(min-width:960px)and (min-height:700px){.package-popup__tabcontent{height:450px}}.package-popup__description{margin:1em 0;white-space:pre-wrap}@media(min-width:960px){.package-popup{position:relative;display:block;top:0;left:50%;width:750px;margin-left:-375px;height:auto;border-radius:8px;transform:none}.package-popup__headline{border-radius:8px 8px 0 0}.package-popup__tabcontent{border-radius:0 0 8px 8px}}@media(min-width:960px)and (min-height:700px){.package-popup{position:absolute;top:50%;transform:translateY(-50%)}}.package-popup__installed strong{margin-right:5px}@media(min-width:600px){.package-popup__installed{display:flex;flex-direction:column;justify-content:flex-end;text-align:center}.package-popup__installed strong{display:block;margin:0}}.package-popup__update{padding:10px 20px 10px 50px;background:var(--btn-primary) url(../img/button-update.ad79c617.svg) 15px 50% no-repeat;background-size:23px 23px}.package-popup__incompatible,.package-popup__update{margin:0 0 20px;color:var(--clr-btn);border-radius:var(--border-radius)}.package-popup__incompatible{display:flex;justify-content:space-between;align-items:center;gap:10px;padding:10px 10px 10px 50px;background:var(--contao) url(../img/button-incompatible.3eb2b686.svg) 15px 50% no-repeat;background-size:23px 23px}.package-popup__incompatible button{flex-shrink:0}.package-popup__funding+.package-popup__update{margin-top:-10px}.view-login__header{max-width:280px;margin:0 auto 60px;padding-top:40px;text-align:center}.view-login__product{margin-top:15px;font-size:38px;font-weight:100;line-height:1}.view-login__form{position:relative;max-width:280px;margin:0 auto 60px}.view-login__form input{padding-right:30px;margin:5px 0 10px}.view-login__locked{max-width:290px;margin:-20px auto 60px;padding:20px;background:var(--btn-alert);color:#fff;text-align:center}.view-login__locked strong{white-space:pre}.view-login__headline{margin-bottom:0}.view-login__description{margin-top:.5em;margin-bottom:20px}.view-login label{position:absolute;text-indent:-999em;pointer-events:none}.view-login label[for=ctrl_username]{top:0;bottom:0;margin:auto;right:13px;width:16px;height:16px;background:url(../img/person.00d78897.svg) 0 0 no-repeat;background-size:16px 16px;z-index:10}.view-login label[for=ctrl_password]{top:0;bottom:0;margin:auto;right:12px;width:16px;height:16px;background:url(../img/lock.3c42a55f.svg) 0 0 no-repeat;background-size:14px 14px;z-index:10}.view-login__password input,.view-login__user input{margin:0}.view-login__user input{border-radius:var(--border-radius) var(--border-radius) 0 0!important}.view-login__password{margin-top:-1px;margin-bottom:10px}.view-login__password input{border-radius:0 0 var(--border-radius) var(--border-radius)!important}.view-login .widget-text--password button{opacity:0}.view-login__link{display:block;margin-top:2em;font-size:12px;text-align:center}.view-login__button{margin:3px 0}.view-login__button .sk-circle{color:#fff;text-align:center}.view-login__or{display:grid;gap:15px;grid-template-columns:1fr auto 1fr;padding:12px}.view-login__or:after,.view-login__or:before{align-self:center;border-top:1px solid var(--border);content:""}.view-login .fragment-footer{display:block}.widget-radio-button legend{margin-bottom:2px}.widget-radio-button>div{position:relative;margin:.25em 0}.widget-radio-button input{border:0;clip:rect(0 0 0 0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.widget-radio-button label{display:block;padding-left:25px;background:url(../img/widget-radio--off.4e93f443.svg) 0 -1px no-repeat;background-size:20px 20px}.widget-radio-button input:checked+label{background-image:url(../img/widget-radio--on.181461b6.svg)}.widget-radio-button input:focus-visible+label{outline:5px auto Highlight;outline:5px auto -webkit-focus-ring-color}.widget-radio-button input:disabled+label{opacity:.5}.setup__directories{margin-top:2em}.setup__directories>dt{margin-top:1em;font-weight:600}.setup__directories>dd{margin:0;word-break:break-all}.setup__directories>dd span{background-color:var(--highlight-bg);color:var(--highlight-color);font-weight:400}.link-more{position:relative;display:inline-block}p:empty+.link-more{margin-left:0}.link-more button{width:auto;height:auto;padding:0 0 5px;background:transparent;color:var(--link);font-size:13px;font-weight:300;line-height:inherit;border:none;cursor:pointer}.link-more button:hover{text-decoration:underline}.link-more__menu{outline:none}.link-more ul{transform:translateX(-50%)}.package-link{display:flex;column-gap:8px;justify-content:space-between;width:100%;padding-bottom:4px;margin-bottom:4px;border-bottom:1px solid var(--border--light)}.package-link:last-child{padding-bottom:0;margin-bottom:0;border-bottom:none}.package-link__details{padding:5px 0;line-height:18px}.package-link__name{display:inline;font-weight:600}.package-link__name:after{content:": "}.package-link__text{display:inline}.package-link__actions{display:flex;margin-left:20px;margin:0 -4px}.package-link__actions>*{margin:0 4px}.package-link--limit .package-link__details{display:flex}.package-link--limit .package-link__name{white-space:nowrap}.package-link--limit .package-link__text{display:-webkit-box;overflow:hidden;line-clamp:1;-webkit-line-clamp:1;-webkit-box-orient:vertical;padding:0 10px 0 5px}.package-funding[data-v-5a8fd14b]{padding:10px 20px 10px 50px;font-weight:400;font-size:12px;line-height:1.8;background:rgba(var(--funding-rgb),.025) url(../img/funding.cf78a0a0.svg) 15px 50% no-repeat;background-size:23px 23px;border:1px solid rgba(var(--funding-rgb),.5);border-radius:6px}.package-funding>div[data-v-5a8fd14b]{overflow:hidden}.package-funding span[data-v-5a8fd14b]{margin-right:15px}.package-funding a[data-v-5a8fd14b]{position:relative;display:inline-block;margin:0 20px 0 0;padding-left:16px;color:var(--funding);background:url(../img/link-funding.b25cd92d.svg) 0 50% no-repeat;background-size:13px 13px}.package-funding a[data-v-5a8fd14b]:before{content:"|";position:absolute;left:-12px}.package-funding a[data-v-5a8fd14b]:nth-child(2):before{content:none}.package-popup{position:fixed;display:flex;flex-direction:column;justify-content:flex-start;width:100%;max-width:none;height:100%;background:var(--popup-bg);z-index:10;opacity:1}.package-popup>*{flex-basis:auto;flex-grow:1}.package-popup__loader{display:flex;flex-direction:column;align-items:center;justify-content:center;padding:50px 0}.package-popup__loader p{margin:1em}.package-popup__headline{position:relative;flex-grow:0;flex-shrink:1;padding:7px 30px 6px;background:var(--popup-hl-bg);color:#fff;font-size:18px;font-weight:300;line-height:1.5;text-align:center}.package-popup__button{display:block;float:right;position:absolute;top:0;margin:4px 0;padding:4px;background:none;border:1px solid transparent;border-radius:5px;cursor:pointer}.package-popup__button--previous{left:4px}.package-popup__button--close{right:4px}.package-popup__button svg{display:block;width:22px;height:22px}.package-popup__button:hover{background-color:#db6f00}.package-popup__summary{flex-grow:0;padding:25px 35px}@media(min-width:600px){.package-popup__summary{display:flex}}.package-popup__logo{border-radius:6px;float:right;height:60px;width:60px;margin-left:1em;background:#f7f7f7}@media(min-width:600px){.package-popup__logo{display:block;float:left;width:110px;height:110px;margin:-10px 16px 0 -10px}}.package-popup__icon{display:flex;align-items:center;justify-content:center;height:100%}.package-popup__icon--fallback{display:none}.package-popup__icon img{width:50px;height:50px;max-height:100%;object-fit:contain}@media(min-width:600px){.package-popup__icon img{width:90px;height:90px}}.package-popup__text{display:flex;flex-direction:column;flex-grow:1}@media(min-width:600px){.package-popup__text{width:200px}}.package-popup__title{margin:0;line-height:1.4;overflow-wrap:break-word}.package-popup__authors{flex-grow:1;font-size:13px;margin-bottom:.5em}.package-popup__author{display:inline-block;margin-right:2px}.package-popup__author:after{color:var(--text);content:", "}.package-popup__author:last-child:after{content:none}.package-popup__stats{display:inline-block;margin-right:15px;margin-top:.5em;padding-left:18px;font-size:13px;background-position:0 50%;background-repeat:no-repeat;background-size:13px 13px}.package-popup__stats--private{padding-left:20px;background-image:var(--svg--private);background-size:15px 15px}.package-popup__stats--updated{background-image:var(--svg--updated)}.package-popup__stats--downloads{background-image:var(--svg--downloads)}.package-popup__stats--favers{background-image:var(--svg--favers)}.package-popup__actions{display:flex;flex-direction:column;gap:10px;margin-top:1em}@media(min-width:600px){.package-popup__actions{margin:0 0 0 25px;width:200px}}.package-popup__installed{margin-top:1em}.package-popup__abandoned{margin:0 0 20px;padding:10px 20px 10px 50px;font-weight:400;font-size:12px;line-height:1.8;background:rgba(var(--hint-rgb),.3) url(../img/hint.ba2ac97e.svg) 15px 50% no-repeat;background-size:23px 23px;border:1px solid var(--hint-link);border-radius:6px}.package-popup__funding{margin:0 0 20px}.package-popup__tabs{position:relative;flex-grow:revert}.package-popup__tabs:after,.package-popup__tabs:before{content:"";display:block;position:absolute;top:0;bottom:1px;width:7px;background:linear-gradient(-90deg,transparent 0,var(--popup-bg) 50%);z-index:1;pointer-events:none}.package-popup__tabs:after{background:linear-gradient(90deg,transparent 0,var(--popup-bg) 50%);right:0}.package-popup__tabs-list{flex-shrink:0;flex-grow:0;display:flex;column-gap:4px;height:40px;min-width:100%;overflow-x:auto;scrollbar-width:none;overflow-y:hidden;margin:0;padding:0 7px;list-style-type:none}.package-popup__tabs-list:after{content:"";position:absolute;inset:auto 0 0;height:1px;background:var(--border--light);z-index:-1}.package-popup__tab{position:relative;top:1px;flex-grow:1;padding:0;height:39px;line-height:39px;text-align:center;border:1px solid var(--border--light);border-top-left-radius:6px;border-top-right-radius:6px}.package-popup__tab--active{background:var(--tab-content);border-bottom:1px solid var(--tab-content)}.package-popup__tab button{display:flex;justify-content:center;align-items:center;width:100%;height:100%;margin:0;padding:0 10px;border:none;background:transparent;cursor:pointer}.package-popup__tab button:disabled{color:var(--border)!important;cursor:not-allowed}.package-popup__pill{position:relative;top:-2px;display:inline-block;margin-left:5px;padding:2px 5px;font-size:10px;font-weight:400;background:var(--border--light);border-radius:40%}.package-popup__pill--highlight{color:var(--clr-btn);background:var(--btn-primary)}.package-popup__tabcontent{position:relative;padding:25px 35px;overflow-y:auto;background:var(--tab-content);outline:0}@media(min-width:960px)and (min-height:700px){.package-popup__tabcontent{height:450px}}.package-popup__description{margin:1em 0;white-space:pre-wrap}@media(min-width:960px){.package-popup{position:relative;display:block;top:0;left:50%;width:750px;margin-left:-375px;height:auto;border-radius:8px;transform:none}.package-popup__headline{border-radius:8px 8px 0 0}.package-popup__tabcontent{border-radius:0 0 8px 8px}}@media(min-width:960px)and (min-height:700px){.package-popup{position:absolute;top:50%;transform:translateY(-50%)}}.package-popup__installed strong{margin-right:5px}@media(min-width:600px){.package-popup__installed{display:flex;flex-direction:column;justify-content:flex-end;text-align:center}.package-popup__installed strong{display:block;margin:0}}.package-popup__update{padding:10px 20px 10px 50px;background:var(--btn-primary) url(../img/button-update.ad79c617.svg) 15px 50% no-repeat;background-size:23px 23px}.package-popup__incompatible,.package-popup__update{margin:0 0 20px;color:var(--clr-btn);border-radius:var(--border-radius)}.package-popup__incompatible{display:flex;justify-content:space-between;align-items:center;gap:10px;padding:10px 10px 10px 50px;background:var(--contao) url(../img/button-incompatible.3eb2b686.svg) 15px 50% no-repeat;background-size:23px 23px}.package-popup__incompatible button{flex-shrink:0}.package-popup__funding+.package-popup__update{margin-top:-10px}.theme-details__constraint{flex-grow:1}.file-tree{margin:0;padding:0;list-style:none}.file-tree__folder{position:relative;padding-left:20px}.file-tree__folder:before{content:"";position:absolute;left:10px;top:6px;width:0;height:0;border-top:5px solid transparent;border-bottom:5px solid transparent;border-left:5px solid var(--text);transition:transform .1s ease-in-out}.file-tree__folder--open:before{transform:rotate(90deg)}.file-tree__file{padding-left:20px}.file-tree button{background:none;border:none;font-weight:400;cursor:pointer}.setup__versions{margin:0;padding:0 0 0 15px}.setup__version{margin:.5em 0;text-align:left}.setup__version--warning{color:var(--btn-alert)}.setup__releaseplan{margin-top:1.5em}.setup__fielddesc--version{margin-bottom:-1em!important}.setup__core-features{margin:5px 0 0 5px;font-size:12px}.setup__theme-image{max-width:100%;height:auto;border:1px solid var(--border)}.setup__theme p{margin:1em 0}.setup__themes{padding:0 14px}.setup__themes-results{display:grid;gap:14px}@media(min-width:1024px){.setup__themes-results{grid-template-columns:repeat(2,1fr)}.setup__themes-results-item{flex-basis:calc(50% - 16px);margin-left:8px;margin-right:8px}}.setup__themes-item{border:1px solid var(--tiles-bdr)}.setup__themes-more{margin-top:20px;text-align:center}.setup__theme-search{margin:20px 0 0;text-align:center}.setup__theme-search--empty{padding-top:60px;background:url(../img/sad.c7de6e95.svg) top no-repeat;background-size:50px 50px}.setup__theme-search--offline{padding-top:60px;background:url(../img/offline.0c23d1ce.svg) top no-repeat;background-size:50px 50px}.setup__theme-search--loader .sk-circle{width:50px;height:50px;margin:0 auto 20px}.setup__theme-search button{margin-top:2em}.setup__fielddesc--warning{padding:10px 10px 10px 40px;background:var(--hint-bg) url(../img/hint.ba2ac97e.svg) 10px 10px no-repeat}.setup__tabs{margin:1em 0}.setup__tab-controls{display:flex}.setup__tab-control{flex-grow:1;padding:4px 10px;border:none;border-top:1px solid var(--border);border-left:1px solid var(--border);background:none;cursor:pointer}.setup__tab-control:last-child{border-right:1px solid var(--border)}.setup__tab-control--active{border-color:var(--btn);background:var(--btn);color:#fff}.setup__tab{border:1px solid var(--border)}.setup__tab--files{white-space:pre;overflow:scroll;height:200px}.setup__requires{width:100%;border-collapse:collapse}.setup__requires td,.setup__requires th{margin:0;padding:3px 10px;text-align:start;vertical-align:top}.setup__requires th{background:var(--btn);color:#fff}.setup__requires td{border-bottom:1px solid var(--border)}.setup__requires tr:last-child td{border-bottom:none}.setup__requires tr:nth-child(odd) td{background:var(--table-odd-bg)}.setup__theme-upload{padding:0 50px;text-align:center}@media(min-width:960px){.setup__theme-upload{padding:0 150px}}.setup__or{position:relative;overflow:hidden;margin:1em 0;text-align:center}.setup__or:before{content:"";position:absolute;top:.8em;left:0;right:0;display:block;height:1px;background:var(--border);z-index:1}.setup__or span{position:relative;padding:0 10px;background:var(--popup-bg);z-index:2}.view-setup{padding-top:40px}.view-setup footer{margin-top:40px}.view-setup__steps{padding:0 0 50px 0}.view-setup__steps ul{display:flex;margin:0;padding:0;list-style-type:none}.view-setup__steps li{display:flex;justify-content:center;align-items:center;flex-grow:1;position:relative;height:6px;margin:0;padding:0}.view-setup__steps li:before{content:"";position:absolute;left:-50%;right:50%;background:var(--border);height:5px}.view-setup__steps li:after{content:"";position:absolute;top:-18px;left:50%;margin-left:-21px;width:42px;height:42px;color:#fff;text-indent:0;text-align:center;line-height:35px;background:var(--border);border-radius:50%;z-index:1}.view-setup__steps li:first-child:before{content:none}.view-setup__steps li.active:after,.view-setup__steps li.active:before{background:var(--contao)}.view-setup__steps button{display:flex;justify-content:center;align-items:center;background:transparent;border:none;z-index:10;cursor:pointer}.view-setup__steps button:disabled{cursor:default}.view-setup__steps svg{fill:#fff}.view-setup__main{text-align:center}.view-setup__party{font-size:64px}.view-setup__headline{margin:10px 0 20px;padding:15px 0;font-size:42px;font-weight:100}.view-setup__description{max-width:500px;margin:1em 25px}.view-setup__start.widget-button{height:50px;margin:30px 10px 0;padding:0 50px;font-size:1.2em;line-height:50px}.view-setup__continue.widget-button{width:80%!important;margin:10px 0 0}.view-setup__funding{width:80%;margin:50px auto 0;padding:20px 25px;border:2px solid var(--funding);border-radius:var(--border-radius);background:rgba(var(--funding-rgb),.025);font-weight:400}.view-setup__funding figure{margin-bottom:1em}.view-setup__funding p{margin:0 0 .5em 0}.view-setup__funding-link{margin:1em 0 0}@media(min-width:960px){.view-setup{padding-top:80px}.view-setup footer{margin-top:80px}.view-setup__steps{padding-bottom:80px}.view-setup__headline{margin:20px 0 40px;font-size:64px}.view-setup__continue.widget-button{width:auto!important;margin:25px 10px 0;padding:0 20px}.view-setup__description{max-width:550px;margin:1em auto;font-size:1.2em}.view-setup__funding{display:flex;margin:60px auto -20px;text-align:left}.view-setup__funding figure{margin-right:25px}}.setup__header{max-width:280px;margin-left:auto;margin-right:auto;padding:40px 0;text-align:center}.setup__header .widget-button{margin-top:1em}.setup__icon{background:var(--contao);border-radius:10px;padding:10px}.setup__headline{margin-top:20px;margin-bottom:25px;font-size:36px;font-weight:100;line-height:1}.setup__description,.setup__warning{margin:1em 0;text-align:justify}.setup__warning{color:var(--btn-alert);font-weight:600}.setup__form{position:relative;max-width:280px;margin:0 auto 50px;opacity:1}.setup__form svg.setup__check{display:block;width:80px;height:80px;margin:0 auto 2em;fill:var(--btn-primary)}.setup__form .widget-select,.setup__form .widget-text{margin-top:10px}.setup__form .widget-select label,.setup__form .widget-text label{display:block;margin-bottom:5px;font-weight:400}.setup__form .widget-checkbox{margin-top:20px;font-weight:400}.setup__form .widget-radio-button{margin-top:20px}.setup__fields{margin-bottom:2em}.setup__fields--center{text-align:center}.setup__fields .button-group .widget-button{margin-bottom:1px}.setup__fieldtitle{margin-bottom:.5em;font-size:18px;font-weight:600;line-height:30px}.setup__fielddesc{margin-bottom:1em;text-align:left}.setup__fielddesc code{word-break:break-word}.setup__actions{display:flex;flex-wrap:wrap;gap:10px}.setup__actions--center{justify-content:center}.setup__actions .button-group,.setup__actions .widget-button{flex-grow:1}.setup__actions .button-group--inline,.setup__actions .widget-button--inline{flex-grow:0}@media(min-width:960px){.setup{padding-top:100px}.setup__header{float:left;width:470px;max-width:none;padding:0 60px 50px}.setup__form{float:left;width:370px;max-width:none;margin:0 50px 50px}.setup__form .widget-select label,.setup__form .widget-text label{display:block;float:left;width:120px;padding-top:10px;font-weight:400}.setup__form .widget-select input,.setup__form .widget-select select,.setup__form .widget-text input,.setup__form .widget-text select{width:250px!important}}.config-check__header{max-width:280px;margin-left:auto;margin-right:auto;padding:40px 0;text-align:center}.config-check__icon{background:var(--contao);border-radius:10px;padding:10px}.config-check__headline{margin-top:20px;margin-bottom:25px;font-size:36px;font-weight:100;line-height:1}.config-check__description{text-align:justify}.config-check__form{position:relative;max-width:280px;margin:0 auto 50px}.config-check__form .widget-select,.config-check__form .widget-text{margin-top:20px}.config-check__form .widget-select label,.config-check__form .widget-text label{display:block;margin-bottom:5px;font-weight:400}.config-check__fields{margin-bottom:2em}.config-check__fieldtitle{margin-bottom:.5em;font-size:18px;font-weight:600;line-height:30px}.config-check__fielddesc{margin-bottom:1em}.config-check__issues{margin-bottom:1em;color:var(--btn-alert)}.config-check__issues p{font-weight:600}.config-check__issues ul{margin:0;padding:0}.config-check__issues li{margin:.5em 0 0 25px;padding:0}.config-check .widget-button{margin-bottom:.5em}@media(min-width:960px){.config-check{padding-top:100px}.config-check__header{float:left;width:470px;max-width:none;padding:0 60px 100px}.config-check__form{float:left;width:370px;max-width:none;margin:20px 50px 0;padding-bottom:100px}.config-check__form .widget-select label,.config-check__form .widget-text label{display:block;float:left;width:120px;padding-top:10px;font-weight:400}}body.nav-active{overflow:hidden!important}#app{transition:transform .4s cubic-bezier(.55,0,.1,1)}.nav-active #app{overflow-y:visible;transform:translateX(-280px)}.nav-active #app .navigation__group--main{visibility:visible}@media(min-width:1024px){.nav-active #app{transform:none}}.navigation__toggle{display:block;float:right;position:relative;margin:5px 15px;padding:0;width:30px;height:30px;background:none;border:none;cursor:pointer;z-index:20}.navigation__toggle span,.navigation__toggle span:after,.navigation__toggle span:before{content:"";display:block;width:100%;height:4px;background:var(--text);border-radius:4px;position:absolute}.navigation__toggle span{transition-duration:75ms;transition-timing-function:cubic-bezier(.215,.61,.355,1);top:50%;margin-top:-2px}.navigation__toggle span:before{top:-10px;transition:top 75ms ease .12s,opacity 75ms ease}.navigation__toggle span:after{bottom:-10px;transition:bottom 75ms ease .12s,transform 75ms cubic-bezier(.55,.055,.675,.19)}.nav-active .navigation__toggle span{transform:rotate(45deg);transition-delay:.12s;transition-timing-function:cubic-bezier(.215,.61,.355,1)}.nav-active .navigation__toggle span:before{top:0;opacity:0;transition:top 75ms ease,opacity 75ms ease .12s}.nav-active .navigation__toggle span:after{transition:bottom 75ms ease,transform 75ms cubic-bezier(.215,.61,.355,1) .12s;bottom:0;transform:rotate(-90deg)}.navigation__group,.navigation__item{list-style-type:none;margin:0;padding:0}.navigation__group--main{position:fixed;top:0;bottom:0;right:-280px;width:280px;visibility:hidden;padding:20px;overflow-y:auto;overflow-scrolling:touch;background:var(--header-main-bg);border-left:1px solid var(--header-bdr);z-index:10}.navigation__item a,.navigation__item button{display:block;margin:0;padding:12px 10px;font-size:16px;color:var(--text);white-space:pre;background:none;border:none}.navigation__item a:hover,.navigation__item button:hover{text-decoration:none}.navigation__item a[href]:hover,.navigation__item button[href]:hover{color:var(--link)}.navigation__item--main>a,.navigation__item--main>button{text-transform:uppercase}.navigation__item--sub>a{margin-left:15px}.navigation__item--icon svg{display:none}.navigation__item-badge{position:relative;top:-2px;margin-left:8px;padding:2px 5px;font-size:10px;color:var(--clr-btn);font-weight:600;background:var(--contao);border-radius:40%}@media(min-width:1024px){.navigation__toggle{display:none}.navigation__group--main{display:flex;visibility:visible;position:inherit;inset:auto;width:auto;padding:0;overflow:visible;background:none;border:none;box-shadow:none;transform:none;transition:none}.navigation__group--sub{position:absolute;left:50%;min-width:180px;margin-top:-3px;text-align:center;background:var(--form-bg);border-top:3px solid var(--link);border-radius:5px;transform:translateX(-50%);z-index:100;box-shadow:0 0 2px var(--shadow);transition:opacity var(--am-close-transition-duration) ease}.navigation__group--sub:before{position:absolute;left:50%;top:-7px;width:0;height:0;margin-left:-4px;border-style:solid;border-width:0 3.5px 4px 3.5px;border-color:transparent transparent var(--link) transparent;content:""}.navigation__group--sub.hide{display:none!important}.navigation__group--sub.transitioning{display:block!important;opacity:0}.navigation__group--sub.show{display:block!important;opacity:1;transition:opacity var(--am-open-transition-duration) ease}.navigation__group--right{left:auto;right:7px;transform:translateX(0)}.navigation__group--right:before{left:auto;right:18px}.navigation__item{position:relative;padding:0 8px}.navigation__item.router-link-active>a,.navigation__item:hover>a{color:var(--link)!important;border-bottom:3px solid var(--link)}.navigation__item:hover>.navigation__group--sub{display:block}.navigation__item--sub{display:block;margin:calc(var(--border-radius)/2) 0;padding:0 2px;border-radius:var(--border-radius)}.navigation__item--sub a{margin:0;border:none!important}.navigation__item--sub.router-link-active,.navigation__item--sub:hover{background:var(--focus)}.navigation__item--sub.router-link-active a,.navigation__item--sub:hover a{color:var(--text)!important}.navigation__item--icon>button{padding-top:7px}.navigation__item--icon>button svg{display:inline;position:relative;top:4px;width:22px;height:22px;fill:var(--text)}.navigation__item--icon>button:hover svg{fill:var(--link)}.navigation__item--icon>button span{display:none}.navigation:hover li>a{border:none}.navigation:hover li:hover>a{border-bottom:3px solid var(--link)}.navigation:hover li:hover>a svg{fill:var(--link)}}.logout-warning{text-align:center}.logout-warning__countdown{margin:20px 0;font:600 4em/1.6 SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace;color:var(--btn-warning)}.fragment-footer{width:280px;margin:10px auto 0;padding:15px 0 25px;font-size:12px;text-align:center;border-top:1px solid var(--footer-bdr)}.fragment-footer--main{width:auto;margin-top:52px!important;padding:20px 0}.fragment-footer--boxed{border-color:var(--footer-fragment-bdr)}.fragment-footer__product{font-weight:300}.fragment-footer__links{margin:5px 0 0;padding:0;list-style-type:none}.fragment-footer__links li{display:inline-block}.fragment-footer__links li:not(:first-child):before{content:"|";padding:0 10px 0 8px}.fragment-footer__links a{display:inline!important;color:var(--link-footer)}.fragment-footer__settings{margin-top:10px;display:flex;flex-flow:column;justify-content:center;gap:10px}@media(min-width:960px){.fragment-footer{display:grid;grid-auto-flow:column;grid-auto-columns:minmax(0,1fr);gap:16px;align-content:center}.fragment-footer--boxed .fragment-footer__product,.fragment-footer--main .fragment-footer__product{margin-right:auto}.fragment-footer--boxed .fragment-footer__links,.fragment-footer--main .fragment-footer__links{order:15;margin:0 0 0 auto}.fragment-footer--boxed .fragment-footer__settings,.fragment-footer--main .fragment-footer__settings{flex-flow:row;margin-top:0}.fragment-footer--boxed{width:840px}}.layout-main{overflow:hidden;min-height:100vh}.layout-main__header{display:flex;justify-content:space-between;height:56px;padding:8px;background:var(--header-main-bg)}.layout-main__header--margin{margin-bottom:30px}.layout-main__badge-title{background:var(--border);color:var(--text);padding:2px 5px;position:relative;top:-5px;border-radius:8px;font-size:.75rem;font-weight:600;line-height:1;display:-webkit-box;-webkit-line-clamp:1;line-clamp:1;-webkit-box-orient:vertical;word-break:break-word;overflow:hidden;text-overflow:ellipsis}.layout-main__subheader{margin:0 0 45px;padding:20px 0;background:var(--header-bg);border-bottom:1px solid var(--header-bdr)}.layout-main__subheader-inside{display:flex;justify-content:center;align-items:center;flex-direction:column}.layout-main__news{width:320px;height:50px;margin-bottom:20px}.layout-main__news a,.layout-main__news img{display:block}.layout-main .search-bar{width:100%;margin:0}.layout-main__logo{display:inline;color:var(--text);text-decoration:none;font-weight:100;font-size:27px;line-height:40px}.layout-main__logo img{float:left;margin:0 10px 0 12px}@media(min-width:1024px){.layout-main__logo img{margin-left:0}}.layout-main footer,.layout-main__content,.layout-main__subheader-inside{position:relative;margin:0 20px}.layout-main__has-badge-title{display:flex;justify-content:space-between}.layout-main__has-badge-title .layout-main__logo{display:flex}.layout-main__has-badge-title .layout-main__title{display:flex;flex-wrap:wrap;align-items:center;line-height:1;column-gap:10px;row-gap:5px}@media(max-width:600px){.layout-main__badge-title{max-width:220px}}@media(min-width:700px){.layout-main__subheader-inside{flex-direction:row}.layout-main__news{margin:0 20px 0 0}}@media(min-width:1024px){.layout-main__has-badge-title .navigation__group--main{display:flex}.layout-main footer,.layout-main__content,.layout-main__subheader-inside{max-width:960px;margin:0 auto}}@media(min-width:1200px){.layout-main footer,.layout-main__content,.layout-main__subheader-inside{max-width:1180px}}.confirm-button{position:relative}.confirm-button__icon{display:none;position:absolute;opacity:0;z-index:100}.confirm-button__icon--confirm{display:block;animation:confirm_button .5s ease-out 0s}.confirm-button__icon svg{fill:var(--btn-primary);width:100%;height:100%}@keyframes confirm_button{0%{opacity:1;height:10px;width:10px;left:calc(50% - 5px);top:calc(50% - 5px)}to{opacity:0;height:150px;width:150px;left:calc(50% - 75px);top:calc(50% - 75px)}}.package-tools{position:relative;clear:both;text-align:center}@media(min-width:800px){.package-tools{margin-bottom:40px}}.package-tools__button.widget-button{margin-bottom:10px}@media(min-width:800px){.package-tools{display:flex;justify-content:center;align-items:center}.package-tools__button.widget-button{width:auto;margin:0 15px;padding:0 15px}}.package-actions{position:fixed;left:0;right:0;bottom:0;max-height:0;background:#000;background:rgba(0,0,0,.8);color:#fff;transition:max-height .4s ease;z-index:100}.package-actions--active{max-height:200px}.package-actions__inner{display:flex;flex-wrap:wrap;justify-content:flex-end;align-items:center;margin:0;padding:12px;text-align:right}@media(min-width:1024px){.package-actions__inner{max-width:976px;margin:0 auto;padding-left:0;padding-right:0}}@media(min-width:1200px){.package-actions__inner{max-width:1196px}}.package-actions__text{flex-grow:1;display:initial;margin:0 8px;font-weight:600}.package-actions__button{display:block;padding:0 15px!important;margin:8px}.package-actions__button--dryRun{width:auto!important;flex-grow:1}@media(min-width:600px){.package-actions__button{width:auto!important}.package-actions__button--dryRun{flex-grow:0}}.package-actions__button-group{display:block;width:100%;margin:8px}.package-actions__button-group>.button-group__primary{padding:0 15px!important}@media(min-width:600px){.package-actions__button-group{width:auto!important}}.package{position:relative;margin-bottom:20px;background:var(--tiles-bg);border:1px solid var(--tiles-bdr);border-radius:14px}.package.is--hint{border-color:var(--btn-alert)}.package--contao:not(:last-child){margin-bottom:5em}.package__hint{position:relative;background:var(--hint-bg);padding:8px 16px;font-weight:400;font-size:12px;line-height:1.8;border-radius:14px 14px 0 0;z-index:1}.package__hint p a{display:inline-block;padding-right:10px}.package__hint p a:first-child{margin-left:10px}.package__hint p a:not(:first-child):before{padding-right:10px;content:"|"}.package__hint-close{float:right;padding-left:18px;color:var(--hint-link);background:url(../img/close.8b27dbcb.svg) 0 no-repeat;background-size:14px 14px}.package__inside{position:relative;padding:16px}.package__inside:after{display:table;clear:both;content:""}.package__badge{display:inline-block;margin-bottom:.5em;padding:2px 5px;color:#fff;font-size:12px;font-weight:600;background:var(--btn-alert);border-radius:var(--border-radius);cursor:help}.package__icon{border-radius:6px;height:60px;width:60px;background:#f7f7f7;margin:0 auto 10px;position:absolute;right:16px}.package__icon>figure{display:flex;align-items:center;justify-content:center;height:100%}.package__icon img,.package__icon svg{border-radius:4px;width:50px;height:50px;max-height:100%;object-fit:contain}.package__details{min-height:96px}.package__about{margin-bottom:20px}.package__headline{position:relative;margin-bottom:.2em;line-height:1;overflow-wrap:break-word;margin-right:70px}.package__headline em{background-color:var(--highlight-bg);color:var(--highlight-color);font-style:normal}.package__title{display:block;margin-right:10px}.package__description{display:-webkit-box;overflow:hidden;-webkit-line-clamp:2;-webkit-box-orient:vertical;margin-bottom:1em;margin-right:70px}.package__description em{background-color:var(--highlight-bg);color:var(--highlight-color);font-style:normal}.package__additional{margin-top:-5px}.package .package__release{text-align:right;margin-bottom:5px}.package__version--additional{margin-bottom:5px}.package__version--additional strong{margin-right:10px}.package__version--release{display:none}.package__version--release time{display:block}.package__version--missing{padding:4px 8px;background:var(--btn-alert);border-radius:var(--border-radius);color:#fff;font-weight:700}.package__version-update{display:inline-block;margin:0 0 2px;padding:1px 8px;color:#fff;border-radius:var(--border-radius)}.package__version-update--available{background:var(--btn-primary)}.package__version-update--error{background:var(--btn-alert)}.package__version-update--none{background:var(--border)}.package__version-latest{float:right;position:relative;right:-7px;width:24px;height:20px;background:var(--btn-primary) url(../img/button-update.ad79c617.svg) center center/20px 20px no-repeat}.package__actions{display:flex;flex-flow:column;gap:5px}.package__actions .button-group button{margin-bottom:0!important}@media(min-width:600px){.package__description,.package__title{margin-right:0}.package__hint{padding-left:52px;background:rgba(var(--hint-rgb),.9) url(../img/hint.ba2ac97e.svg) 12px 5px no-repeat;background-size:28px 28px}.package__inside{display:flex;align-items:stretch;padding:0}.package__headline--badge{display:flex;gap:6px;align-items:flex-start}.package__headline{margin:0 0 8px}.package__badge{order:1;margin:0 0 0 2px}.package__icon{width:130px;height:auto;min-height:130px;margin:0;border-radius:12px 0 0 12px;position:revert;right:revert}.package__icon img,.package__icon svg{width:110px;height:110px}.is--hint .package__icon{border-top-left-radius:0}.package--contao{overflow:hidden}.package--contao .package__icon{border-radius:0}.package__details{padding:16px;height:100%;min-height:90px;max-width:calc(100% - 130px);flex:1}.package.is--hint .package__icon{border-top-left-radius:0}}@media(min-width:680px){.package .package__release{display:block;float:left;width:33%}.package__actions{float:right;width:64%;flex-flow:row;gap:4%;text-align:right}.package__actions>*{flex:1}}@media(min-width:1024px){.package__version--additional{display:none}.package__version--release{display:block;margin-top:15px;text-align:center}.package__version-update{display:block;margin:2px 0 0}.package__about{float:left;width:396px;margin-bottom:0}.package .package__release{width:180px;margin-left:20px;margin-bottom:0}.package__actions{flex-flow:column;gap:10px;width:180px;margin-left:20px}.package__details{display:flex;align-self:center;align-items:flex-start}}@media(min-width:1200px){.package__about{width:616px}}.progress-bar{--progress-color:var(--btn-warning);position:relative;width:100%;height:30px;background:var(--clr-btn);border:2px solid var(--progress-color);color:#000;font-weight:600;text-align:center;line-height:26px}.progress-bar__bar{position:absolute;overflow:hidden;left:0;right:0;top:0;bottom:0;background:var(--progress-color)}.progress-bar__bar span{display:block;color:var(--clr-btn);text-align:center}.progress-bar--primary{--progress-color:var(--btn-primary)}.progress-bar--alert{--progress-color:var(--btn-alert)}.feature-package{display:flex;flex-wrap:wrap;padding:6px 16px;border-top:1px solid var(--border--light)}.feature-package__name{font-weight:600;white-space:nowrap}.feature-package__name:after{content:": "}.feature-package__text{flex-grow:1;display:-webkit-box;overflow:hidden;-webkit-line-clamp:1;line-clamp:1;-webkit-box-orient:vertical;margin-right:.5em;padding:4px 0;line-height:20px}.feature-package__text--hint{display:inline;-webkit-line-clamp:none;line-clamp:none}.feature-package__badge{margin-left:5px;padding:2px 8px;background:var(--btn-alert);border-radius:var(--border-radius);font-size:12px;font-weight:600;line-height:19px;color:#fff;cursor:help}.feature-package__hint{line-height:1.2;padding:2px 5px;background:var(--hint-bg);font-size:12px}.feature-package__actions{flex-grow:1;display:flex;justify-content:flex-end;margin:0 -4px 0 0}.feature-package__actions>*{margin:0 4px}.feature-package__restore{padding-left:18px;font-size:12px;color:var(--hint-link);background:url(../img/close.8b27dbcb.svg) 0 no-repeat;background-size:14px 14px;border:none;cursor:pointer}.feature-package__restore:hover{text-decoration:underline}@media(min-width:800px){.feature-package{flex-wrap:nowrap}}@media(min-width:1024px){.feature-package__hint{padding:8px 10px 8px 36px;background:var(--hint-bg) url(../img/hint.ba2ac97e.svg) 10px 5px no-repeat;background-size:20px 20px}.feature-package__actions{margin:0 -4px 0 0}}.package-constraint input[type=text][data-v-00a118e4]{margin-right:2px;background:#fff;border:2px solid var(--btn-warning);color:var(--black);font-weight:600;text-align:center;border-top-right-radius:0;border-bottom-right-radius:0}.package-constraint input[type=text][data-v-00a118e4]::placeholder{color:#fff;-webkit-text-fill-color:#fff;opacity:1}.package-constraint input[type=text][data-v-00a118e4]:disabled{color:var(--clr-btn);opacity:1;background:var(--btn-warning);-webkit-text-fill-color:var(--clr-btn)}.package-constraint input[type=text].disabled[data-v-00a118e4]{background:var(--border);border-color:var(--border)}.package-constraint input[type=text].incompatible[data-v-00a118e4]{border-color:var(--btn-alert)}.package-constraint input[type=text].incompatible[data-v-00a118e4]:disabled{background:var(--btn-alert)}.package-constraint input[type=text].error[data-v-00a118e4]{animation:input-error .15s linear 3}.package-constraint>input[type=text][data-v-00a118e4],.package-constraint>input[type=text][data-v-00a118e4]:disabled{float:left;width:calc(100% - 32px)}.package-constraint button[data-v-00a118e4]{position:relative;width:30px;background:var(--btn-warning);line-height:20px;text-indent:-999em;border-top-left-radius:0;border-bottom-left-radius:0}.package-constraint button[data-v-00a118e4]:hover{background:var(--btn-warning-active);border-color:var(--btn-warning-active)}.package-constraint button[data-v-00a118e4]:before{position:absolute;left:50%;top:50%;margin:-10px 0 0 -10px}.package-constraint button.incompatible[data-v-00a118e4]{background:var(--btn-alert)}.package-constraint button.rotate[data-v-00a118e4]:before{animation:release-validating-00a118e4 2s linear infinite}@keyframes release-validating-00a118e4{to{transform:rotate(1turn)}}@media(min-width:1024px){.package-constraint button[data-v-00a118e4],.package-constraint input[type=text][data-v-00a118e4]{height:30px}}.button-group{display:flex;gap:1px;position:relative}.button-group__primary.widget-button{flex-grow:1;border-top-right-radius:0;border-bottom-right-radius:0}.button-group__more.widget-button{flex-shrink:0;width:38px;padding:7px;border-top-left-radius:0;border-bottom-left-radius:0}.button-group__more.widget-button svg{width:24px;height:24px}.button-group__group{position:absolute;top:39px;width:100%;padding-top:3px;z-index:100}.button-group__group:focus{outline:none}.button-group__group .widget-button{margin-top:1px}.button-group__group .link-menu{margin-top:3px}.button-group__group--top{top:auto;bottom:39px}.button-group__group--top .link-menu{margin-top:0;margin-bottom:3px}.composer-package__stats{display:inline-block;margin-right:15px;padding-left:18px;font-size:13px;background-position:0 50%;background-repeat:no-repeat;background-size:13px 13px}.composer-package__stats--license{padding-left:0}.composer-package__stats--versions{display:inline-flex;flex-wrap:wrap;gap:5px;list-style:none;margin:0 15px 0 0;padding:0}.composer-package__stats--version{padding:3px 5px;line-height:1;border:1px solid var(--border);border-radius:4px}.composer-package__stats--funding{width:16px;background-image:url(../img/funding.cf78a0a0.svg);background-size:16px 16px;background-repeat:no-repeat;text-decoration:none!important}.package-uploads__overlay{top:0;bottom:0;right:0;left:0;position:fixed;z-index:9999;opacity:.6;text-align:center;background:#000}.package-uploads__overlay div{margin:-.5em 0 0;position:absolute;top:50%;left:0;right:0;transform:translateY(-50%);font-size:40px;color:#fff;padding:0}.cloud-status{margin-left:8px;position:relative}.cloud-status__button{margin-left:0;margin-right:0;padding-left:8px;cursor:help!important}.cloud-status__popup{position:absolute;text-align:center;left:0;bottom:54px;margin:0;padding:0 0 15px;outline:none;background:var(--form-bg);color:var(--text);border-bottom:3px solid var(--contao);border-radius:5px;box-shadow:0 0 2px var(--shadow);z-index:100}.cloud-status__popup:after{position:absolute;left:38px;bottom:-6px;width:0;height:0;margin-left:-4px;border-style:solid;border-width:4px 3.5px 0 3.5px;border-color:var(--contao) transparent transparent transparent;content:""}.cloud-status__popup--error{color:var(--clr-btn);background-color:var(--btn-alert);border-color:var(--btn-alert)}.cloud-status__popup--error:after{left:27px;border-color:var(--btn-alert) transparent transparent transparent}.cloud-status__headline{padding:15px 20px 0;font-size:16px;white-space:pre}.cloud-status__version{margin:0 0 8px;font-size:12px}.cloud-status__link{display:inline-block;margin:15px 10px 0}.cloud-status__error{padding:8px 20px 8px;hyphens:auto}.cloud-status table{width:100%;margin-top:12px;text-align:left;border-spacing:0;border-collapse:collapse}.cloud-status th{padding:3px 5px 3px 20px}.cloud-status td{padding:3px 20px 3px 0}.cloud-status tr:nth-child(odd){background:var(--table-odd-bg)}.package-list{position:relative}.package-list__status{margin:100px 0;text-align:center;font-size:20px;line-height:1.5em}.package-list__status .sk-circle{width:100px;height:100px;margin:0 auto 40px}.package-list__headline{font-size:18px;font-weight:300;margin:30px 0 10px}.message-overlay{position:relative}.message-overlay__blur{opacity:.75;filter:blur(2px);transition:opacity .5s,filter .5s}.message-overlay__overlay{position:absolute;display:flex;justify-content:center;align-items:center;left:0;right:0;top:0;bottom:0}.message-overlay__message{padding:10px;font-size:2em;font-weight:400;text-align:center}.maintenance{margin-bottom:14px;background:var(--tiles-bg);border-radius:var(--border-radius)}.maintenance__inside{padding:10px 20px 20px}@media(min-width:1024px){.maintenance__inside{display:grid;grid-template:auto/90px auto 300px;column-gap:20px;padding:25px 20px}}.maintenance__image{display:none}.maintenance__image img{width:100%;border-radius:var(--border-radius);overflow:hidden;aspect-ratio:1;object-fit:contain}@media(min-width:1024px){.maintenance__image{display:flex;align-items:center}}.maintenance__about{margin-bottom:20px}@media(min-width:1024px){.maintenance__about{margin-bottom:0}}.maintenance__about h1{position:relative;margin-bottom:5px;display:flex;flex-wrap:wrap;column-gap:.5em;align-items:baseline}.maintenance__about p{margin:0 0 1em;display:inline}.maintenance__error,.maintenance__warning{position:relative;top:-2px;padding:4px 8px;font-size:14px;line-height:1em;font-weight:300;background:var(--btn-warning);color:var(--clr-btn);border-radius:var(--border-radius)}.maintenance__error{background:var(--btn-alert)}.maintenance__actions{display:flex;flex-direction:column;row-gap:10px;column-gap:20px}@media(min-width:600px){.maintenance__actions{flex-direction:row-reverse}}@media(min-width:1024px){.maintenance__actions{flex-direction:column;margin-left:20px}}.maintenance__actions>.button-group,.maintenance__actions>button{width:100%}@media(min-width:600px){.maintenance__actions>.button-group,.maintenance__actions>button{width:calc(50% - 10px)}}@media(min-width:1024px){.maintenance__actions>.button-group,.maintenance__actions>button{width:100%}}.maintenance__loader{width:50px;margin:0 auto}.maintenance__loader .sk-circle{width:50px;height:50px}.animate-blur-in,.animate-blur-out,.layout-boxed{display:table;width:100%;height:100%}.layout-boxed__cell{display:table-cell;overflow:hidden;vertical-align:middle;padding:10px}.layout-boxed__container{position:relative;max-width:380px;margin:0 auto;background:var(--popup-bg);border-radius:8px}@media(min-width:960px){.layout-boxed__container{margin-top:20px;margin-bottom:20px}.layout-boxed__container--wide{max-width:940px}}.button-menu{position:relative}.button-menu__primary.widget-button{float:left;width:calc(100% - 39px);border-top-right-radius:0;border-bottom-right-radius:0}.button-menu__more.widget-button{float:right;width:38px;padding:7px;border-top-left-radius:0;border-bottom-left-radius:0}.button-menu__more.widget-button svg{width:24px;height:24px}.button-menu__menu{display:flex;flex-direction:column;position:absolute;top:38px;right:0;width:auto;z-index:100;background:var(--form-bg);border-radius:var(--border-radius)}.button-menu__menu:before{content:"";position:absolute;top:-5px;right:15px;width:0;height:0;border-right:none;border-bottom:none;border-left:5px solid transparent;border-right:5px solid transparent;border-bottom:5px solid var(--form-bg)}.button-menu__menu:focus{outline:none}.button-menu__menu button{padding:8px 16px;background:none;border:none;text-align:left;white-space:nowrap;border-bottom:1px solid var(--border);cursor:pointer}.button-menu__menu button:hover{color:var(--text);background:var(--focus)}.button-menu__menu button:first-child{border-top-left-radius:2px;border-top-right-radius:2px}.button-menu__menu button:last-child{border-bottom:none;border-bottom-left-radius:2px;border-bottom-right-radius:2px}.button-menu__menu .link-menu{margin-top:3px}.console-operation{position:relative;padding:0 16px;text-align:left;font-size:12px;color:#959da5}.console-operation__summary{margin-left:13px;padding:8px;box-sizing:border-box}.console-operation__summary--console{margin-left:0}.console-operation summary{cursor:pointer}.console-operation__status{display:inline-block;position:relative;box-sizing:border-box;padding-right:8px;width:24px;height:18px;text-align:center;vertical-align:middle}.console-operation__icon{position:absolute;left:0;top:0}.console-operation__icon--skipped{fill:#666b71}.console-operation__icon--pending{fill:#dbab0a}.console-operation__icon--active{fill:#dbab0a;animation:console-active 1s linear infinite}@keyframes console-active{0%{transform:rotate(0deg)}50%{transform:rotate(180deg)}to{transform:rotate(359deg)}}.console-operation__icon--success{fill:var(--btn-primary)}.console-operation__icon--error{fill:var(--btn-alert)}.console-operation__label{display:inline-block;overflow:hidden;max-width:750px;vertical-align:top}.console-operation__title{display:inline;margin:0;color:#fff}.console-operation__title--disabled{text-decoration:line-through}.console-operation__description{display:inline;margin:0 0 0 10px}.console-operation__console{position:relative;overflow-y:auto;max-height:280px}.console-operation__lines{padding:8px 0 16px;font-family:SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace;color:#f6f8fa;line-height:1.5;white-space:pre-wrap;word-break:break-word;overflow-wrap:break-word}.console-operation__line{display:flex}.console-operation__line:hover{background-color:#2f363d}.console-operation__line-number{display:inline-block;overflow:hidden;width:48px;min-width:48px;color:#959da5;text-align:right;text-overflow:ellipsis;white-space:nowrap;vertical-align:middle;user-select:none}.console-operation__line-content{display:inline-block;margin-left:16px;vertical-align:middle}.console-operation__scroll{position:sticky;left:0;right:0;display:flex;justify-content:center;align-items:flex-end;width:100%;height:30px;padding:0;border:none;cursor:pointer}.console-operation__scroll svg{fill:#fff;width:16px;height:16px}.console-operation__scroll--top{top:0;background:linear-gradient(#24292e,rgba(36,41,46,.502) 50%)}.console-operation__scroll--top svg{transform:rotate(180deg)}.console-operation__scroll--bottom{bottom:0;background:linear-gradient(rgba(36,41,46,.502),#24292e 50%)}.console-operation__scroll--bottom svg{transform:rotate(0deg)}.console{background:#24292e;border-radius:8px}.console__header{display:flex;flex-wrap:nowrap;justify-content:space-between;align-items:center;padding:12px 12px 12px 24px;border-bottom:1px solid #444d56}.console__headline{margin:0;font-size:inherit;line-height:1.5;color:#fff}.console__description{color:#959da5;font-size:12px}.console__actions{display:flex;flex-wrap:nowrap;align-items:center}.console__action,.console__action>button{height:30px!important;line-height:30px!important;width:auto!important;min-width:0;margin:0 2px;padding:0 5px!important;border:none!important}.console__action:hover,.console__action>button:hover{background-color:#2f363d!important}.console__action--active,.console__action>button--active{background-color:#586069!important}.console__operations{padding:20px 0}.widget-checkbox input{border:0;clip:rect(0 0 0 0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.widget-checkbox label{position:relative;display:block;padding-left:25px;text-align:left}.widget-checkbox label:before{content:"";position:absolute;left:0;width:20px;height:20px;background:url(../img/widget-checkbox--off.73856538.svg) 0 0 no-repeat;background-size:20px 20px}.widget-checkbox input:checked+label:before{background-image:url(../img/widget-checkbox--on.8b830157.svg)}.widget-checkbox input:focus-visible+label{outline:5px auto Highlight;outline:5px auto -webkit-focus-ring-color}.widget-checkbox input:disabled+label{opacity:.5}.widget-checkbox .widget__description{padding-left:25px}.widget-checkbox .widget__description--disabled{opacity:.5}.database-migration__header{margin-left:auto;margin-right:auto;padding:40px 0;text-align:center}.database-migration__icon{background:var(--contao);border-radius:10px;padding:10px}.database-migration__headline{margin-top:.5em;margin-bottom:.5em;font-size:36px;font-weight:100;line-height:1}.database-migration__description{margin:0 50px;font-weight:600}.database-migration__actions{display:flex;flex-direction:column;justify-content:center;align-items:center;margin-top:2em;padding:0 50px}@media(min-width:960px){.database-migration__actions{flex-direction:row}}.database-migration .widget-button{width:280px;height:35px;margin:5px;padding:0 30px;line-height:35px}@media(min-width:960px){.database-migration .widget-button{width:auto}}.database-migration__main{margin:0 50px 50px;background:#24292e}.database-migration__loading{width:30px;margin:40px auto}.database-migration__loading .sk-circle{width:30px;height:30px}.log-viewer__status{margin:100px 0;text-align:center;font-size:20px;line-height:1.5em}.log-viewer__status--empty{padding-top:140px;background:url(../img/warning.9a7cd776.svg) top no-repeat;background-size:100px 100px}.log-viewer__status--loader .sk-circle{width:100px;height:100px;margin:0 auto 40px}.log-viewer__status button{margin-top:2em}.log-viewer__loading{width:30px;margin:40px auto}.log-viewer__loading .sk-circle{width:30px;height:30px}.log-viewer__filters{display:flex;justify-content:space-between;flex-wrap:wrap;gap:20px}.log-viewer__filters>div{display:flex;align-items:flex-end;gap:20px}.log-viewer__filters a{flex-shrink:0}.log-viewer__file{flex-shrink:1;display:flex;align-items:flex-end}.log-viewer__file select{border-right:none;border-top-right-radius:0;border-bottom-right-radius:0}.log-viewer__file button{border-top-left-radius:0;border-bottom-left-radius:0}.log-viewer__list{margin-top:2em;padding-bottom:1px;background:var(--form-bg);border-radius:var(--border-radius)}@media(min-width:600px){.log-viewer__list{overflow-y:scroll;max-height:calc(100vh - 300px)}}.log-viewer__line{position:relative;padding:10px 0;border-bottom:1px solid var(--border--light)}@media(min-width:600px){.log-viewer__line{display:flex}}.log-viewer__line:hover{background:var(--focus)}.log-viewer__line:last-child{border-bottom:none}.log-viewer__line--header{display:none}@media(min-width:600px){.log-viewer__line--header{display:flex;position:sticky;top:0;z-index:1;font-weight:600;background:var(--log-header-bg)!important;color:#fff;border-top-left-radius:2px;border-top-right-radius:2px;border-bottom-color:var(--border)}}.log-viewer__line--alert:before,.log-viewer__line--critical:before,.log-viewer__line--emergency:before,.log-viewer__line--error:before,.log-viewer__line--warning:before{content:"";position:absolute;left:0;top:-1px;bottom:-1px;width:4px;background:var(--btn-alert)}.log-viewer__line--warning:before{background:var(--btn-warning)}.log-viewer__line--raw{padding:5px 10px;background:#24292e;border-bottom:none;font-family:SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace;color:#f6f8fa;font-size:.8em;line-height:1.5;white-space:pre-wrap}.log-viewer__line--raw:hover{background:#2f363d}.log-viewer__more{display:flex;justify-content:center;padding:20px}.log-viewer__content,.log-viewer__meta{padding:10px 20px}.log-viewer__content--header,.log-viewer__meta--header{padding:0 20px!important}.log-viewer__meta{padding-bottom:0;flex-shrink:0;font-style:italic}.log-viewer__meta--header{font-style:normal}@media(min-width:600px){.log-viewer__meta{width:220px;padding-bottom:10px}}.log-viewer__content{flex-grow:1}.log-viewer__datetime{display:block}@media(min-width:600px){.log-viewer__datetime{margin-bottom:1em}}.log-viewer__badge{display:inline-block;margin-right:10px;padding:1px 4px;background:var(--border);border-radius:var(--border-radius);font-size:.9em;font-weight:400;text-transform:lowercase}.log-viewer__badge--desktop{display:none}@media(min-width:600px){.log-viewer__badge--desktop{display:inline-block}.log-viewer__badge--mobile{display:none}}.log-viewer__badge--channel{padding-top:0;padding-bottom:0;border:1px solid var(--border);background:var(--white)}.log-viewer__badge--level-warning{background:var(--btn-warning);color:#fff}.log-viewer__badge--level-alert,.log-viewer__badge--level-critical,.log-viewer__badge--level-emergency,.log-viewer__badge--level-error{background:var(--btn-alert);color:#fff}.log-viewer__message span:nth-child(2n){font-weight:600;color:var(--black)}.log-viewer__details{display:flex;align-items:center;margin-top:1em}.log-viewer__toggle{margin-right:10px;padding:0;border:none;background:none;color:var(--link);text-decoration:none;cursor:pointer}.log-viewer__toggle:hover{text-decoration:underline}.log-viewer__json{margin:10px 0 0}.user-scope__label{margin:0;padding:0}.user-scope__item{padding:5px 0 0}.user-scope__item--required label{opacity:1!important}.user-scope__item--required label:before{opacity:.5}.invite-user__check{text-align:center}.invite-user__check svg{width:60px;height:60px;fill:var(--btn-primary)}.invite-user__check,.invite-user__text{margin-bottom:1em}.invite-user__url{display:block;margin-top:2em}.invite-user__help{display:block;margin-top:1em;font-size:12px}.invite-user__clipboard{margin:1em 0}.widget-text input::-webkit-inner-spin-button,.widget-text input::-webkit-outer-spin-button{display:none}.widget-text input[type=number]{appearance:textfield!important}.widget-text--password input{padding-right:40px!important}.widget__password-toggle{position:absolute;right:8px;bottom:2px;padding:0;margin:0;background:none;border:none;cursor:pointer}.widget__password-toggle--hidden svg{fill:var(--btn-primary)}.widget__password-toggle--visible svg{fill:var(--btn)}.setup-totp__qr{margin:2em;text-align:center}.setup-totp__qr svg{width:200px;height:200px}.setup-totp__uri{display:block;margin:1em 0;word-break:break-all}.setup-totp .sk-circle{margin:20px auto}.disable-totp__text{margin-bottom:1em}.change-password .widget{margin:1em 0 0}.user-manager__loading{margin:100px 0;text-align:center;font-size:20px;line-height:1.5em}.user-manager__loading .sk-circle{width:100px;height:100px;margin:0 auto 40px}.user-manager__list{display:grid;grid-template:1fr/1fr;gap:20px}@media(min-width:600px){.user-manager__list{grid-template:1fr/repeat(2,1fr)}}@media(min-width:800px){.user-manager__list{grid-template:1fr/repeat(3,1fr)}}@media(min-width:1200px){.user-manager__list{grid-template:1fr/repeat(4,1fr)}}.user-manager__item{position:relative;overflow:hidden;display:flex;flex-direction:column;padding:16px;background:var(--tiles-bg);border:1px solid 1px solid var(--tiles-bdr);border-radius:14px}.user-manager__ribbon{position:absolute;top:18px;right:-22px;width:100px;font-size:12px;color:#fff;font-weight:600;line-height:1.5;text-align:center;background:var(--btn-info);transform-origin:center center;transform:rotate(45deg)}.user-manager__ribbon--hint{cursor:help}.user-manager__ribbon--primary{background:var(--btn-primary)}.user-manager__ribbon--warning{background:var(--btn-warning)}.user-manager__ribbon--alert{background:var(--btn-alert)}.user-manager__new{margin-top:60px;text-align:center}.user-manager__spacer{flex-grow:1;min-height:1em}.user-manager__username{font-size:18px;font-weight:600}.user-manager__scope{margin-top:1em}.user-manager .widget-button{margin-top:5px}.view-oauth__header{max-width:280px;margin:0 auto 40px;padding-top:40px;text-align:center}.view-oauth__icon{background:var(--contao);border-radius:10px;padding:10px}.view-oauth__product{margin-top:15px;font-size:36px;font-weight:100;line-height:1}.view-oauth__form{position:relative;max-width:280px;margin:0 auto 60px;text-align:center}.view-oauth__form input,.view-oauth__form select{margin:5px 0 10px}.view-oauth__description{margin-top:.5em;margin-bottom:.5em}.view-oauth__client{margin:1em 0;font-size:32px}.view-oauth__scopes{text-align:left}.view-oauth__warning{color:var(--btn-alert);margin-top:2em;margin-bottom:2em}.view-oauth__button{margin-top:1em}.view-oauth__button .sk-circle{color:#fff;text-align:center}.view-error{position:fixed;left:0;right:0;top:0;bottom:0;padding:10px;color:#e8e8e8;font-family:SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace;font-size:13px;line-height:1.2;background-color:rgba(0,0,0,.851);background-position:0 0;background-repeat:repeat;z-index:9998}.view-error,.view-error__close{display:flex;justify-content:center;align-items:center}.view-error__close{position:absolute;top:15px;right:10px;width:35px;height:35px;background:none;border:none;cursor:pointer;z-index:10}.view-error__close:hover{border:1px solid #fff}.view-error__content{display:flex;flex-direction:column;align-items:center;max-width:800px;max-height:100vh;line-height:1.5;text-align:center}.view-error__content--dump{text-align:left!important;overflow:auto!important;max-width:none!important;width:100vw!important;height:calc(100vh - 40px)!important;display:block!important;z-index:-1}.view-error__content--dump .sf-dump{background:none!important}.view-error__icon{display:block;height:100px;margin:2em 0;fill:#fff}.view-error__status{margin-bottom:1em;padding:2px 4px;background-color:#e36049;border-radius:var(--border-radius)}.view-error__headline{margin:0;font-size:1em;line-height:1.5}.view-error__status a{color:#e8e8e8;text-decoration:underline}.view-error__details{display:block;margin-top:2em;white-space:pre-line}.view-error__debug{align-self:flex-start;width:100%;max-height:60vh;overflow-y:auto;margin-top:2em;text-align:left;white-space:pre-line}.view-error__actions{margin:4em 0;text-align:center}.view-error__link{margin:10px;padding:10px 20px;border:1px solid #fff;border-radius:4px;color:#fff}.view-task__header{margin-left:auto;margin-right:auto;padding:40px 20px;text-align:center}.view-task__icon{background:var(--contao);border-radius:10px;padding:10px}.view-task__headline{margin-top:15px;font-size:36px;font-weight:100;line-height:1}.view-task__description{margin:0;font-weight:600}.view-task__actions{display:flex;flex-direction:column;justify-content:center;align-items:center;margin-top:2em}@media(min-width:960px){.view-task__actions{flex-direction:row}}.view-task .widget-button{width:280px;height:35px;margin:5px;padding:0 30px;line-height:35px}@media(min-width:960px){.view-task .widget-button{width:auto}}.view-task__main{margin:0 50px 50px}.view-task__loading{width:30px;margin:40px auto}.view-task__loading .sk-circle{width:30px;height:30px}.view-task__sponsor{margin:-30px 50px 50px;text-align:center}@media(min-width:960px){.view-task__sponsor br{display:none}}.view-task__donate{position:relative;top:5px;margin-left:.5em;line-height:0}:root{--text:#535353;--link:#f47c00;--placeholder:#a9a9a9;--body-bg:#ebe6db;--link-footer:#2a7887;--tiles-bg:#fff;--tiles-bdr:#ddd3bc;--popup-hl-bg:#f47c00;--popup-bg:#fff;--popup-header:#fff;--popup-overlay-bg:hsla(41,29%,89%,.35);--tab-content:#f8f9fb;--highlight-bg:#ff0;--highlight-color:#535353;--shadow:#ccbfa2;--contao:#f47c00;--badge-bg:var(--contao);--ad-shadow:0 1px 5px 1px rgba(0,0,0,.2);--black:#000;--funding:#ea4aaa;--funding-rgb:234,74,170;--form-bg:#fff;--border:#ccc;--border--light:#e9eef1;--focus:#f9f9f9;--clr-btn:#fff;--btn:#737373;--btn-active:#666;--btn-primary:#31a64b;--btn-primary-active:#2b9242;--btn-warning:#db8c41;--btn-warning-active:#d77f2c;--btn-alert:#db5041;--btn-alert-active:#d73c2c;--btn-info:#6a8ca6;--btn-info-active:#5c7f9a;--btn-funding:#ea4aaa;--btn-funding-active:#e7339f;--btn-disabled:#ccc;--hint-bg:#e8c8bc;--hint-rgb:232,200,188;--hint-link:#bd2e20;--header-bg:#e5dfcf;--header-bdr:#dcd8cc;--footer-bdr:#bbb;--svg--link-blank:url(../img/link-blank.eb57b3fa.svg);--svg--private:url(../img/private.a1c65662.svg);--svg--updated:url(../img/updated.3b47bebb.svg);--svg--downloads:url(../img/downloads.c1db2a9e.svg);--svg--favers:url(../img/favers.056e2836.svg);--svg--language:url(../img/language.582b2920.svg);--svg--color-scheme:url(../img/color_scheme.d527d153.svg)}html[data-color-scheme=dark]{color-scheme:dark;--text:#ddd;--link:#f47c00;--body-bg:#0f0f11;--tiles-bg:#212227;--tiles-bdr:#303236;--popup-hl-bg:#292c32;--popup-bg:#1b1d21;--popup-overlay-bg:rgba(0,0,0,.35);--tab-content:#212227;--highlight-bg:#f47c00;--highlight-color:#fff;--shadow:transparent;--badge-bg:var(--border--light);--ad-shadow:none;--btn:#3c3f4c;--btn-active:#25272f;--black:#fff;--form-bg:#151619;--border:#44464b;--border--light:#2e2e34;--focus:#1e2024;--btn-info:#25455f;--btn-info-active:#253846;--btn-disabled:#151517;--opacity-disabled:0.5;--hint-rgb:57,9,20;--header-bg:#1b1d21;--header-bdr:#1b1d21;--footer-bdr:#414448;--svg--link-blank:url(../img/link-blank--dark.07eeaee6.svg);--svg--private:url(../img/private--dark.41b90022.svg);--svg--updated:url(../img/updated--dark.c21fdd5b.svg);--svg--downloads:url(../img/downloads--dark.034bf7a3.svg);--svg--favers:url(../img/favers--dark.4765f7d4.svg);--svg--language:url(../img/language--dark.a24e849e.svg);--svg--color-scheme:url(../img/color_scheme--dark.ef0f0aed.svg)}html[data-color-scheme=dark] #contao-network{background:#292c32!important;color:#ddd!important}html{box-sizing:border-box}*,:after,:before{box-sizing:inherit}#app,body,html{height:100%}blockquote,body,figure,form,p{margin:0;padding:0}article,aside,figcaption,figure,footer,header,main,nav,section{display:block}body,div,fieldset,form,h1,h2,h3,h4,h5,h6,html,p{text-size-adjust:none}body{background:var(--body-bg);overflow-y:hidden}#app{overflow-y:scroll}fieldset{border:none;margin:0;padding:0}legend{-webkit-padding-start:0;-webkit-padding-end:0}figure{line-height:0}body,button,input,textarea{font:300 14px/1.4 -apple-system,system-ui,Segoe UI,Roboto,Oxygen-Sans,Ubuntu,Cantarell,Helvetica Neue,sans-serif;color:var(--text)}strong{font-weight:600}code{font-family:SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace}input,select,textarea{font-size:99%}input:disabled,select:disabled,textarea:disabled{color:var(--text);-webkit-text-fill-color:var(--text);cursor:text}input::-ms-clear,input::-ms-reveal,select::-ms-clear,select::-ms-reveal,textarea::-ms-clear,textarea::-ms-reveal{display:none}input::placeholder,select::placeholder,textarea::placeholder{color:var(--placeholder);-webkit-text-fill-color:var(--placeholder)}.invisible{border:0;clip:rect(0 0 0 0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.clearfix{*zoom:1}.clearfix:after,.clearfix:before{display:table;content:"";line-height:0}.clearfix:after{clear:both}h1,h2,h3,h4,h5,h6{font-size:inherit;line-height:inherit;font-weight:600;margin:0}a{color:var(--link);text-decoration:none}a:hover{text-decoration:underline}h1{font-size:18px;line-height:30px;margin-bottom:10px}@keyframes input-error{0%{left:0}25%{left:-5px}75%{left:5px}to{left:0}}.widget{position:relative}.widget__error{display:none;position:absolute;left:0;right:0;margin:0;padding:4px 10px;color:var(--clr-btn);background:var(--btn-alert);border-radius:2px;transform:translateY(6px);z-index:10;white-space:pre-line}.widget__error:after,.widget__error:before{bottom:100%;left:30px;border:solid transparent;content:" ";height:0;width:0;position:absolute;pointer-events:none}.widget__error:after{border-bottom-color:var(--btn-alert);border-width:3px;margin-left:-3px}.widget__error:before{border-bottom-color:var(--btn-alert);border-width:5px;margin-left:-5px}input:focus+*+.widget__error,input:focus+.widget__error,input:hover+*+.widget__error,input:hover+.widget__error,select:hover+.widget__error{display:block}.widget__description{margin-top:2px;font-size:12px}input:not([type=checkbox]):not([type=radio]),select{position:relative;width:100%;height:38px;padding:0 20px;background:var(--form-bg);border:1px solid var(--border);border-radius:6px;color:var(--text);appearance:none}input:not([type=checkbox]):not([type=radio]):focus,select:focus{outline:none;background-color:var(--focus)}.widget--validate input:not([type=checkbox]):not([type=radio]):not(:placeholder-shown):valid,.widget--validate select:not(:placeholder-shown):valid{border-color:var(--btn-primary)}.widget--validate input:not([type=checkbox]):not([type=radio]):not(:placeholder-shown):invalid,.widget--validate select:not(:placeholder-shown):invalid{border-color:var(--btn-alert)}.widget--error input:not([type=checkbox]):not([type=radio]),.widget--error select{border-color:var(--btn-alert);animation:input-error .15s linear 3}select{padding-right:30px}.widget-select:after{position:absolute;right:12px;bottom:16px;width:0;height:0;border-left:6px solid transparent;border-right:6px solid transparent;border-top:6px solid var(--border);content:"";pointer-events:none}.widget-button{display:inline-block;width:100%;height:38px;padding:0;border:none;background-color:var(--btn);color:var(--clr-btn);font-weight:600;line-height:38px;text-decoration:none;text-align:center;white-space:nowrap;cursor:pointer;border-radius:5px}.widget-button:active,.widget-button:hover{background-color:var(--btn-active)}.widget-button--inline{width:auto!important;min-width:100px;padding:0 20px}.widget-button--transparent{background:transparent}.widget-button--small{height:28px;width:auto!important;min-width:0;padding:0 15px;font-size:13px;line-height:28px;font-weight:300}.widget-button--small:before,.widget-button--small>:before{top:3px!important;width:15px!important;height:15px!important;margin-right:6px!important;background-size:15px 15px!important}.widget-button--primary{--btn:var(--btn-primary);--btn-active:var(--btn-primary-active)}.widget-button--warning{--btn:var(--btn-warning);--btn-active:var(--btn-warning-active)}.widget-button--alert{--btn:var(--btn-alert);--btn-active:var(--btn-alert-active)}.widget-button--info{--btn:var(--btn-info);--btn-active:var(--btn-info-active)}.widget-button--funding{--btn:var(--btn-funding);--btn-active:var(--btn-funding-active)}.widget-button:empty{min-width:auto;padding:0 10px}.widget-button:empty:before{margin-right:0!important}.widget-button:hover{text-decoration:none}.widget-button.disabled,.widget-button:disabled{background-color:var(--btn-disabled)!important;border-color:var(--btn-disabled)!important;cursor:not-allowed;opacity:var(--opacity-disabled,1)}.widget-button.disabled{pointer-events:none}.widget-button--anchor{height:auto;background:none!important;line-height:inherit;font-weight:inherit;color:var(--link);text-decoration:none;cursor:pointer}.widget-button--anchor:hover{text-decoration:underline!important}.widget-button--anchor.disabled,.widget-button--anchor:disabled{background:none!important}label{padding:0}.widget--required label:after{margin-left:2px;content:"*";color:var(--btn-alert)}input:-webkit-autofill,select:-webkit-autofill{-webkit-text-fill-color:var(--text);-webkit-box-shadow:inset 0 0 0 1000px hsla(0,0%,100%,0);transition:background-color 5000s ease-in-out 0s}.widget-button--details:before{background-image:url(../img/button-details.8ce780e9.svg)}.widget-button--link:before{background-image:url(../img/button-link.dd42e161.svg)}.widget-button--search:before{background-image:url(../img/button-search.44ce1d4b.svg)}.widget-button--add:before,.widget-button--check:before,.widget-button--clipboard:before,.widget-button--cloud-off:before,.widget-button--cloud:before,.widget-button--console:before,.widget-button--database:before,.widget-button--details:before,.widget-button--download:before,.widget-button--edit:before,.widget-button--gear:before,.widget-button--hide:before,.widget-button--link:before,.widget-button--lock:before,.widget-button--maintenance:before,.widget-button--more:before,.widget-button--passkey:before,.widget-button--power:before,.widget-button--run:before,.widget-button--save:before,.widget-button--search:before,.widget-button--show:before,.widget-button--trash:before,.widget-button--unlock:before,.widget-button--update:before,.widget-button--upload:before{position:relative;display:inline-block;top:5px;width:20px;height:20px;margin-right:8px;background-position:50%;background-repeat:no-repeat;background-size:18px 18px;content:""}.widget-button--add:empty:before,.widget-button--check:empty:before,.widget-button--clipboard:empty:before,.widget-button--cloud-off:empty:before,.widget-button--cloud:empty:before,.widget-button--console:empty:before,.widget-button--database:empty:before,.widget-button--details:empty:before,.widget-button--download:empty:before,.widget-button--edit:empty:before,.widget-button--gear:empty:before,.widget-button--hide:empty:before,.widget-button--link:empty:before,.widget-button--lock:empty:before,.widget-button--maintenance:empty:before,.widget-button--more:empty:before,.widget-button--passkey:empty:before,.widget-button--power:empty:before,.widget-button--run:empty:before,.widget-button--save:empty:before,.widget-button--search:empty:before,.widget-button--show:empty:before,.widget-button--trash:empty:before,.widget-button--unlock:empty:before,.widget-button--update:empty:before,.widget-button--upload:empty:before{margin-right:0!important}.animate-initializing{animation:initializing 1s linear infinite}@keyframes initializing{0%{opacity:.5}50%{opacity:1}to{opacity:.5}}.animate-blur-in{z-index:-1;opacity:.5;filter:blur(4px);transition:opacity .35s,filter .5s}.animate-blur-out{opacity:1;transition:opacity .35s}.animate-fade-enter-active,.animate-fade-leave-active{transition-duration:.2s;transition-property:opacity;transition-timing-function:ease}.animate-fade-enter,.animate-fade-leave-active{opacity:0}.animate-flip-enter-active,.animate-flip-leave-active{transform-style:preserve-3d;backface-visibility:hidden;transition-duration:.5s;transition-property:transform,opacity}.animate-flip-leave-active{transform:perspective(600px) rotateY(0deg);opacity:1}.animate-flip-leave-to{transform:perspective(600px) rotateY(90deg);transition-timing-function:ease-in;opacity:0}.animate-flip-enter-active{transform:perspective(400px) rotateY(270deg);opacity:0}.animate-flip-enter-to{transform:perspective(400px) rotateY(1turn);transition-timing-function:ease-out;opacity:1}:root{--header-main-bg:#fff;--footer-fragment-bdr:#eee;--table-odd-bg:#f5f9fa;--border-radius:6px;--log-header-bg:var(--shadow)}html[data-color-scheme=dark]{--header-main-bg:#292c32;--footer-fragment-bdr:var(--footer-bdr);--table-odd-bg:var(--tiles-bg);--link-footer:#fff;--hint-bg:#151619;--hint-rgb:21,22,25;--log-header-bg:var(--btn)}html[data-color-scheme=dark] .vjs-tree-node:hover{background-color:#2b3439}.color-scheme--light,html[data-color-scheme=dark] .color-scheme--dark{display:initial}.color-scheme--dark,html[data-color-scheme=dark] .color-scheme--light{display:none}.app-hint{position:absolute;top:0;left:0;right:0;height:27px;padding:4px 8px;background:var(--btn-info);color:#fff;text-align:center;z-index:100}.app-hint--warning{background:var(--btn-warning)}.app-hint--alert{background:var(--btn-alert)}.app-hint__description{display:none}@media(min-width:600px){.app-hint__description{display:inline}}.app-hint__link{margin:0;padding:0;background:none;border:none;color:#fff;text-decoration:underline;cursor:pointer}.app-hint+div{padding-top:25px}.view-init{display:table;width:100%;height:100%}.view-init__cell{display:table-cell;font-size:1.5em;text-align:center;vertical-align:middle}.widget-button--add:before{background-image:url(../img/button-add.759df12e.svg)}.widget-button--check:before{background-image:url(../img/button-check.7a3b5ada.svg)}.widget-button--clipboard:before{background-image:url(../img/button-clipboard.9ef63d39.svg)}.widget-button--cloud:before{background-image:url(../img/button-cloud.bc42f267.svg)}.widget-button--cloud-off:before{background-image:url(../img/button-cloud-off.dd8ba18e.svg)}.widget-button--console:before{background-image:url(../img/button-console.05dcdfc4.svg)}.widget-button--database:before{background-image:url(../img/button-database.5282fc7e.svg)}.widget-button--download:before{background-image:url(../img/button-download.e1ba6f25.svg)}.widget-button--edit:before{background-image:url(../img/button-edit.40a4be06.svg)}.widget-button--gear:before{background-image:url(../img/button-gear.a2dc1f09.svg)}.widget-button--hide:before{background-image:url(../img/button-hide.d23f6533.svg)}.widget-button--lock:before{background-image:url(../img/button-lock.98988f08.svg)}.widget-button--maintenance:before{background-image:url(../img/button-maintenance.93830369.svg)}.widget-button--more:before{background-image:url(../img/button-more.e3eb2622.svg)}.widget-button--passkey:before{background-image:url(../img/button-passkey.3806f98a.svg)}.widget-button--power:before{background-image:url(../img/button-power.298a8072.svg)}.widget-button--run:before{background-image:url(../img/button-run.b6310c5a.svg)}.widget-button--save:before{background-image:url(../img/button-save.3b5224de.svg)}.widget-button--show:before{background-image:url(../img/button-show.2336e1d9.svg)}.widget-button--trash:before{background-image:url(../img/button-trash.855f57fa.svg)}.widget-button--unlock:before{background-image:url(../img/button-unlock.51b76e07.svg)}.widget-button--update:before{background-image:url(../img/button-update.ad79c617.svg)}.widget-button--upload:before{background-image:url(../img/button-upload.ca8e9cfc.svg)}.view-account__header{max-width:280px;margin-left:auto;margin-right:auto;padding:40px 0;text-align:center}.view-account__product{margin-top:15px;margin-bottom:40px;font-weight:600}.view-account__product strong{display:block;margin-bottom:10px;font-size:54px;font-weight:100;line-height:1}.view-account__headline{margin-bottom:.5em;font-size:18px;font-weight:600;line-height:30px}.view-account__description{margin-bottom:1em;text-align:justify}.view-account__form,.view-account__totp{position:relative;max-width:280px;margin:0 auto}.view-account__form .widget-button,.view-account__totp .widget-button{margin-top:1.5em}.view-account__form .widget-text{margin-top:10px}.view-account__form .widget-text label{display:block;padding-bottom:5px}.view-account__contribute{max-width:280px;margin:60px auto 0;font-size:12px;text-align:center}.view-account__contribute br{display:none}@media(min-width:960px){.view-account{display:flex;flex-flow:row wrap;align-items:center;padding-top:50px}.view-account__form,.view-account__header,.view-account__totp{padding:50px;width:50%;max-width:none}.view-account__form .widget-text label{float:left;width:120px;padding-top:10px;font-weight:400}.view-account__form input[type=password],.view-account__form input[type=text],.view-account__form select{width:250px!important}.view-account__form .button-group,.view-account__form .widget-button--anchor{width:250px;margin-left:120px}.view-account__contribute{max-width:840px}.view-account__contribute br{display:block}}"use strict";(self["webpackChunkcontao_manager"]=self["webpackChunkcontao_manager"]||[]).push([[851],{6851:function(e){e.exports=JSON.parse('{"ui.app.httpsHeadline":"!! Connessione non sicura !!","ui.app.httpsDescription":"Senza protocollo HTTPS i tuoi dati riservati saranno trasferiti in chiaro.","ui.app.httpsLink":"Maggiori informazioni","ui.app.httpsHref":"https://https.cio.gov/everything/","ui.app.safeModeHeadline":"!! Safe Mode abilitato!!","ui.app.safeModeDescription":"Alcune funzionalità di Contao Manager non sono disponibili.","ui.app.safeModeExit":"Esci da Safe Mode","ui.app.limitedHeadline":"Autenticazione remota","ui.app.limitedDescription":"You have limited permissions due to passwordless login.","ui.app.limitedLogout":"Re-authenticate","ui.app.totpHeadline":"Security Notice","ui.app.totpDescription":"Configure two-factor authentication now to secure your account.","ui.app.totpSetup":"Setup","ui.app.loading":"Caricamento Contao Manager ....","ui.app.apiError":"Stato API inaspettato","ui.app.configSecurity1":"ALLARME DI SICUREZZA! La cartella di configurazione non è protetta","ui.app.configSecurity2":"Contao Manager ha rilevato che i tuoi file di configurazione sono accessibili al pubblico. Tutte le operazioni sono disabilitate fino a quando la cartella non viene protetta e messa in sicurezza, altrimenti un malintenzionato potrebbe accedere ai dati sensibili della tua installazione.\\n\\nPer risolvere questo problema, assicurati di impedire l\'accesso alla cartella \\"contao-manager\\" sul tuo server. Per sapere come farlo, fai riferimento al manuale del tuo webserver o contatta il tuo fornitore di hosting.","ui.account.welcome":"Benvenuto","ui.account.intro1":"Benvenuto in Contao Manager, uno strumento universale per installare e gestire CMS Open Source di Contao 4. Se sei nuovo, per favore {leggiTheManualToGetStarted}.","ui.account.introGetStarted":"{readTheManual} per iniziare","ui.account.introManual":"leggi il manuale","ui.account.intro2":"In caso di problemi, controlla {ourGithubIssues}. Nel caso sentiti libero di creare un nuovo problema per tutto ciò che non è stato ancora segnalato.","ui.account.introIssues":"segnalazioni in GitHub","ui.account.headline":"Account utente","ui.account.description":"Per gestire l\'installazione, crea un account specifico per Contao Manager. Tieni presente che questo account non è correlato al back end o al front end di Contao.","ui.account.username":"Nome utente","ui.account.password":"Password","ui.account.passwordPlaceholder":"min. 8 caratteri","ui.account.passwordLength":"Inserisci almeno 8 caratteri.","ui.account.loginInvalid":"There was an error when creating the account. Please try a different username.","ui.account.submit":"Crea account","ui.account.usePassword":"Use password for login","ui.account.usePasskey":"Use Passkey for login","ui.account.totpHeadline":"Two-factor authentication","ui.account.totpDescription":"Please enable two-factor authentication, which adds an extra layer of security to your account. In addition to your username and password, you will need to enter a verification code generated by a two-factor app such as 1Password, Authy, Google Authenticator, Microsoft Authenticator, LastPass Authenticator or any other TOTP app.","ui.account.totpSetup":"Configure now","ui.account.totpSkip":"Configure later","ui.account.login":"Decline Invitation","ui.account.contribute1":"Contao e il Contao Manager sono sponsorizzati dalla Contao Association senza scopo di lucro.","ui.account.contribute2":"Si prega di considerare di contribuire all\'open source con {donate}.","ui.account.contributeDonate":"Fare una donazione","ui.login.headline":"Registrati","ui.login.description":"Accedi per gestire la tua installazione","ui.login.username":"Nome utente","ui.login.password":"Password","ui.login.totpHeadline":"Two-factor authentication","ui.login.totpDescription":"Please enter your verification code to complete the login process.","ui.login.totp":"Verification code","ui.login.forgotPassword":"Password dimenticata?","ui.login.button":"Registrati","ui.login.passkey":"Sign In with Passkey","ui.login.cancel":"Annulla","ui.login.or":"oppure","ui.login.locked":"L\'accesso è stato negato perché il Contao Manager è bloccato. Per sbloccare, cancella il file {lockFile} nella directory principale di Contao.","ui.logout.headline":"Timeout sessione","ui.logout.warning":"Sei stato inattivo per più di 25 minuti. Per motivi di sicurezza, la sessione verrà chiusa a breve.","ui.logout.expired":"La sessione è stata chiusa automaticamente perché sei stato inattivo per più di 30 minuti.","ui.logout.renew":"Mantieni il login","ui.logout.logout":"Logout","ui.logout.login":"Torna al login","ui.oauth.error":"Tentativo di OAuth non valido. Controllare i parametri della richiesta.","ui.oauth.https":"L\'URI di reindirizzamento DEVE usare un protocollo sicuro (https:) per evitare che il token di autenticazione sia trasmesso in chiaro.","ui.oauth.headline":"Autenticazione remota","ui.oauth.description":"La seguente applicazione o servizio richiede l\'accesso remoto all\'istanza di Contao Manager.","ui.oauth.domain":"Prima di permettere l\'accesso, assicurati di conoscere questo URL e di fidarti del suo proprietario!","ui.oauth.outOfScope":"Unfortunately, you do not have the necessary permissions to grant this access.","ui.oauth.allow":"Consenti accesso","ui.oauth.deny":"Accesso negato","ui.oauth.switchUser":"Switch User","ui.scope.admin":"Admin access including user management","ui.scope.install":"Install new packages and change Contao configuration","ui.scope.update":"Update packages and execute maintenance tasks","ui.scope.read":"Read packages and configuration","ui.boot.headline":"Verifica del sistema","ui.boot.description":"Per favore attendi, stiamo analizzando il tuo server...","ui.boot.issue1":"Problemi di installazione rilevati","ui.boot.issue2":"L\'installazione presenta problemi che devono essere risolti prima di poter utilizzare Contao Manager.","ui.boot.run":"Avvia Contao Manager","ui.boot.safeMode":"Avvio in modalità sicura","ui.recovery.headline":"Sistema di recupero","ui.recovery.description":"Contao Manager ha rilevato file che assomigliano a Contao, ma l\'interfaccia della riga di comando non funziona come previsto.","ui.recovery.console":"Uscita console","ui.recovery.repairOptions":"Scegliere un\'opzione per riparare l\'installazione.","ui.recovery.repairHeadline":"Riparazione automatica","ui.recovery.repairDescription":"Tentativi di riparare automaticamente l\'installazione ricostruendo la cache dell\'applicazione e reinstallando i pacchetti Composer.","ui.recovery.repairWarning":"Qualsiasi modifica ai file del fornitore potrebbe essere cancellata durante il processo!","ui.recovery.repairFailed":"La riparazione automatica non ha avuto successo. Provare la modalità provvisoria per riparare manualmente l\'installazione.","ui.recovery.repairButton":"Esegui la riparazione del sistema","ui.recovery.safeModeHeadline":"Modalità Sicura","ui.recovery.safeModeDescription":"L\'avvio di Contao Manager in modalità provvisoria consente di gestire i pacchetti ed eseguire alcune operazioni di manutenzione, ma le funzioni che si basano su un\'installazione di Contao funzionante non saranno disponibili.","ui.recovery.safeModeButton":"Avvio in modalità sicura","ui.server.pending":"In attesa ...","ui.server.running":"Analizzando ...","ui.server.error":"Verifica non riuscita a causa di una risposta imprevista dal server.","ui.server.details":"Dettagli","ui.server.prerequisite":"Verifica annullata a causa di un prerequisito mancante.","ui.server.selfUpdate.title":"Aggiornamenti di Contao Manager","ui.server.selfUpdate.update":"È disponibile una nuova versione, la {latest} di Contao Manager.","ui.server.selfUpdate.manualUpdate":"È disponibile una nuova versione di Contao Manager {latest}. Il tuo server non supporta gli aggiornamenti automatici, scarica la nuova versione da {download}.","ui.server.selfUpdate.latest":"Stai usando l\'ultima versione disponibile {current}.","ui.server.selfUpdate.dev":"Il build di sviluppo non supportano gli aggiornamenti automatici.","ui.server.selfUpdate.unsupported":"Una nuova versione è disponibile ma non supporta la versione di PHP.","ui.server.selfUpdate.button":"Eseguire l\'auto-aggiornamento","ui.server.selfUpdate.continue":"Continuare","ui.server.config.title":"Configurazione del server","ui.server.config.setup":"Configura","ui.server.config.change":"Cambiamento","ui.server.config.save":"Salva","ui.server.config.cancel":"Annulla","ui.server.config.customOption":"Altri ...","ui.server.config.description":"Per eseguire correttamente le attività in background, Contao Manager deve sapere dove trovare il binario della riga di comando PHP e come eseguire i comandi separati dal processo web.","ui.server.config.formTitle":"Configurazione del server","ui.server.config.formText":"Inserisci il percorso del file binario PHP. Assicurati che il file binario PHP sia la stessa versione del processo del web server.","ui.server.config.cloudTitle":"Composer Resolver Cloud","ui.server.config.cloudText":"Composer Resolver Cloud consente di installare le dipendenze di Composer anche se il server non fornisce memoria locale sufficiente. Si noti che le informazioni del pacchetto verranno trasmesse a un server cloud gestito dalla Contao Association.","ui.server.config.cloud":"Utilizza Composer Resolver Cloud","ui.server.config.cli":"PHP binario","ui.server.config.stateErrorCli":"Nessun binario PHP valido è stato trovato sul server.","ui.server.config.stateErrorCloud":"Composer Resolver Cloud  non è supportato.","ui.server.config.stateSuccess":"Binario PHP in {php_cli}.","ui.server.config.cloudEnabled":"Package dependencies will be resolved using the Composer Resolver Cloud.","ui.server.config.cloudDisabled":"The Composer Resolver Cloud is disabled.","ui.server.php_web.title":"Processo Web PHP","ui.server.php_web.below7":"Trovata la versione di PHP {version}. Si prega di passare a PHP 7 il più presto possibile!","ui.server.php_web.success":"Trovata la versione di PHP {version}, non sono stati trovati problemi noti.","ui.server.php_cli.title":"Interfaccia a riga di comando PHP","ui.server.php_cli.success":"Trovata la versione di PHP {version}, non sono stati trovati problemi noti.","ui.server.composer.title":"Ambiente Composer","ui.server.composer.success":"Non sono stati trovati problemi noti.","ui.server.composer.install":"Le dipendenze del Composer non sono installate.","ui.server.composer.button":"Installa","ui.server.contao.title":"Installazione Contao","ui.server.contao.setup":"Setup","ui.server.contao.check":"Verifica il database","ui.server.contao.empty":"Non è stata trovata alcuna installazione di Contao.","ui.server.contao.old":"La versione {version} di Contao non è compatibile con Contao Manager, aggiorna manualmente l\'installazione.","ui.server.contao.found":"Trovato Contao {version} (versione API {api}).","ui.server.contao.connectionError":"Impossibile connettersi al server del database.","ui.server.contao.connectionProblem":"È stato trovato problema con il database.","ui.server.contao.missingUser":"Account amministratore non trovato.","ui.setup.continue":"Continuare","ui.setup.manager":"Avvia Contao Manager","ui.setup.cancel":"Annulla","ui.setup.welcome":"Benvenuto","ui.setup.welcome1":"Questa procedura guidata ti guiderà attraverso i passaggi necessari per configurare l\'installazione del tuo Contao CMS Open Source.","ui.setup.welcome2":"In caso di domande, puoi consultare la documentazione, forum, un canale Slack e altro nella pagina {support}.","ui.setup.support":"Supporto dalla comunità","ui.setup.start":"Iniziamo","ui.setup.complete":"Congratulazioni!","ui.setup.complete1":"Contao {version} è stato installato correttamente.","ui.setup.complete2":"Per completare il processo d\'installazione, apri lo strumento di installazione per configurare la connessione al database e creare un utente back-end.","ui.setup.complete3":"Ora puoi iniziare a creare il tuo sito web nel back-end di Contao. Se hai bisogno di ulteriori estensioni, vai su Contao Manager.","ui.setup.installTool":"Apri l\'Install Tool","ui.setup.login":"Effettua il login in Contao","ui.setup.funding":"Il software libero è \\"libero\\" come in \\"libertà di parola\\", non come in \\"birra gratis\\". Un progetto Open Source come Contao richiede somme di denaro che non possono essere raccolte da una singola persona o azienda.\\nSe hai un sito web o vendi siti web realizzati con Contao, ci piacerebbe vederti contribuire finanziariamente al prodotto su cui fa affidamento la tua attività.","ui.setup.fundingLink":"Scopri di più","ui.setup.document-root.headline":"Setup Webserver ","ui.setup.document-root.warning":"Per installare Contao tramite Contao Manager, è necessario correggere la document root sul server Web.","ui.setup.document-root.description1":"Contao utilizza una cartella separata per i file pubblici, i file dell\'applicazione vengono installati nella sua cartella principale. Contao non può essere installato se la struttura delle cartelle non è corretta o le cartelle non sono vuote.","ui.setup.document-root.description2":"Se non sai come configurare la document root, leggi la documentazione Contao o contatta il tuo provider di hosting.","ui.setup.document-root.documentation":"Leggi la documentazione","ui.setup.document-root.conflictsTitle":"La directory di installazione non è vuota","ui.setup.document-root.conflictsDirectory":"La directory principale della tua futura installazione di Contao non è vuota, abbiamo trovato {count} files che potrebbero essere sovrascritti dal processo di installazione. Si consiglia di creare una struttura di directory vuota per Contao, ma puoi anche rimuovere i seguenti file e ricontrollare se sei sicuro che non siano utilizzati.","ui.setup.document-root.ignoreConflicts":"Voglio installare Contao nella directory non vuota. Capisco che questo potrebbe sovrascrivere qualsiasi file esistente sul mio spazio web.","ui.setup.document-root.check":"Controlla nuovamente","ui.setup.document-root.create":"Creare elenchi","ui.setup.document-root.change":"Cambia directory","ui.setup.document-root.formTitle":"Setup cartella","ui.setup.document-root.formText1":"Contao Manager può creare automaticamente una nuova struttura di directory sul server.","ui.setup.document-root.formText2":"Dovrai configurare manualmente la nuova root document (ad es. Tramite un pannello di amministrazione di hosting).","ui.setup.document-root.autoconfig":"Comprendo che devo modificare la configurazione del mio server. La mancata configurazione della document root  interromperà Contao Manager ed esporrà i file di configurazione (inclusi i dettagli dell\'account e le password)!","ui.setup.document-root.directory":"Nuova directory","ui.setup.document-root.currentRoot":"Document root corrente","ui.setup.document-root.newRoot":"Nuova document root","ui.setup.document-root.finish":"Cartella di installazione","ui.setup.document-root.publicDir":"Usare {dir} per i file pubblici (per Contao {versione})","ui.setup.document-root.directoryInvalid":"Inserisci un nome di directory valido.","ui.setup.document-root.directoryExists":"La cartella di destinazione esiste già. Per favore, inserisci un nome diverso.","ui.setup.document-root.confirmation":"Contao Manager ha creato correttamente la cartella necessaria per l\'installazione di Contao. Ora devi configurare la radice del documento sul tuo server web. Non ricaricare questa pagina fino ad allora.","ui.setup.document-root.reload":"Ricarica pagina","ui.setup.document-root.success":"La struttura delle directory sul tuo server web è impostata correttamente!","ui.setup.document-root.installingProjectDir":"I file dell\'applicazione verranno installati in {dir}.","ui.setup.document-root.installingPublicDir":"I file pubblici verranno installati in {dir}.","ui.setup.document-root.installedProjectDir":"I file dell\'applicazione vengono installati in {dir}.","ui.setup.document-root.installedPublicDir":"I file pubblici vengono installati in {dir}.","ui.setup.create-project.headline":"Installazione Contao","ui.setup.create-project.description":"Lo sviluppo di Contao segue il principio di {semver}, una nuova versione minore viene rilasciata ogni sei mesi. Le versioni attualmente supportate sono:","ui.setup.create-project.semver":"Versione semantica","ui.setup.create-project.latestTitle":"Più recente","ui.setup.create-project.ltsTitle":"Long Term Support","ui.setup.create-project.latestQ1":"La nostra ultima versione offre la maggior parte delle funzionalità con supporto fino a febbraio {anno}.","ui.setup.create-project.latestQ3":"La nostra ultima versione offre la maggior parte delle funzionalità con supporto fino ad agosto {year}.","ui.setup.create-project.ltsText":"La nostra attuale versione LTS, è focalizzata al mantenimento della stabilità. Offre supporto a lungo termine fino a febbraio {year}.","ui.setup.create-project.pltsText":"La precedente versione LTS ha ancora il supporto a lungo termine fino a febbraio {year}.","ui.setup.create-project.requiresPHP":"Richiede almeno PHP {version}, tu hai PHP {current}.","ui.setup.create-project.releaseplan":"Vedi {contaoReleasePlan} per informazioni dettagliate.","ui.setup.create-project.releaseplanLink":"Piano di rilascio Contao","ui.setup.create-project.installed":"Contao  {version}  è stato installato correttamente sul server. Continua a configurare il tuo database o avvia Contao Manager per installare una versione diversa.","ui.setup.create-project.formTitle":"Seleziona una distribuzione","ui.setup.create-project.formText":"Scegliere quale versione deve essere installata.","ui.setup.create-project.version":"Versione","ui.setup.create-project.demo":"Installa il sito Web demo di Contao","ui.setup.create-project.demoDescription":"Il sito Web demo ti aiuta a familiarizzare con Contao e tutte le sue funzionalità principali. Altri temi possono essere trovati in {store}.","ui.setup.create-project.coreOnly":"Installazione minima (solo core)","ui.setup.create-project.noUpdate":"Salta l\'installazione (soltanto per esperti!)","ui.setup.create-project.theme":"Contao Theme","ui.setup.create-project.themeInstall":"Per installare un tema Contao, utilizza l\'input di ricerca o carica un file del tema (.cto/.zip) che supporti l\'installazione tramite Contao Manager.","ui.setup.create-project.themeBuy":"Assicurati di visitare lo {store} ufficiale.","ui.setup.create-project.themeStore":"Contao Themes Store","ui.setup.create-project.themeUpload":"Upload theme file (.cto/.zip)","ui.setup.create-project.themeInvalid":"Il file caricato non è un tema Contao o non supporta Contao Manager.","ui.setup.create-project.themeWarning":"Contao Manager non è in grado di stabilire se questo tema è compatibile con il tuo server. Per eventuali domande, contatta il fornitore del tema.","ui.setup.create-project.themeTitle":"Esamina i dettagli del tema","ui.setup.create-project.themeDetails":"Con questo tema verranno installati le seguenti dipendenze e file.","ui.setup.create-project.themeRequire":"{count} Dipendenze | {count} Dipendenze","ui.setup.create-project.themeFiles":"{count} File | {count} Files","ui.setup.create-project.theme.or":"oppure cerca dei temi pubblici","ui.setup.create-project.theme.search":"Cerca un tema","ui.setup.create-project.theme.more":"Più temi","ui.setup.create-project.theme.empty":"Nessun tema corrispondente {query}","ui.setup.create-project.theme.uploaded":"Il file del tema è stato caricato correttamente.","ui.setup.create-project.theme.packageName":"Nome Package","ui.setup.create-project.theme.version":"Versione","ui.setup.create-project.theme.authors":"Autore/i","ui.setup.create-project.theme.upload":"Uploading {name} ({size})","ui.setup.create-project.install":"Installa","ui.setup.create-project.cancel":"Annulla","ui.setup.create-project.fileError":"Could not find composer.json in {file}.","ui.setup.create-project.jsonError":"composer.json contains invalid JSON.","ui.setup.create-project.schemaError":"composer.json schema validation failed.","ui.setup.database-connection.headline":"Connessione al database","ui.setup.database-connection.description":"Contao richiede un database MySQL (o un fork compatibile come MariaDB) per memorizzare pagine, contenuti, utenti e altri dati relazionali. I parametri di connessione sono memorizzati nel file {env} nella radice del progetto dell\'installazione di Contao.","ui.setup.database-connection.formTitle":"Parametri connessione","ui.setup.database-connection.formText":"Immettere l\'URL di un database o compilare separatamente i campi nome utente, password, server e database.","ui.setup.database-connection.url":"URL Database","ui.setup.database-connection.validUrl":"URL Database non valido o connessione al server fallita.","ui.setup.database-connection.or":"oppure","ui.setup.database-connection.user":"Nome utente","ui.setup.database-connection.password":"Password","ui.setup.database-connection.server":"Server (:Port)","ui.setup.database-connection.database":"Nome del database","ui.setup.database-connection.connected":"Connessione riuscita al database {database} sul {server}.","ui.setup.database-connection.error":"Errore di connessione al database","ui.setup.database-connection.problem":"Contao ha rilevato un problema con il database server.","ui.setup.database-connection.schemaTitle":"Schema Database ","ui.setup.database-connection.migration":"C\'è una migrazione in sospeso. | Ci sono {count} migrazioni in sospeso.","ui.setup.database-connection.schema":"È presente un aggiornamento dello schema in sospeso. | Ci sono {count} aggiornamenti dello schema in sospeso.","ui.setup.database-connection.noChanges":"Lo schema del database è aggiornato.","ui.setup.database-connection.check":"Verifica il database","ui.setup.database-connection.skip":"Salta","ui.setup.database-connection.save":"Salva","ui.setup.database-connection.change":"Modifica le credenziali","ui.setup.database-connection.restoreTitle":"Importazione del database","ui.setup.database-connection.restoreText":"Il tema che hai appena installato contiene un backup del database. Ripristina il database per importare i dati del tema o salta questo passaggio per iniziare con un\'installazione vuota di Contao. | Il tema che hai appena installato contiene più backup di database. Seleziona un file di backup per importare i dati del tema o salta questo passaggio per iniziare con un\'installazione vuota di Contao.","ui.setup.database-connection.backup":"Eseguire il backup del database corrente prima dell\'importazione","ui.setup.database-connection.backupWarning":"Tutti i dati nel database verranno sovrascritti durante l\'importazione! Creare prima un backup se il database non è vuoto.","ui.setup.database-connection.restore":"Importa il database dei temi","ui.setup.database-connection.restoreOption":"Backup del {date} ({size})","ui.setup.database-connection.restored":"Il database del tuo tema è stato importato con successo. Continua con la convalida dello schema del database.","ui.setup.backend-user.success":"Nel tuo database è stato trovato un account amministratore per il back-end Contao. Usa il back-end Contao per aggiungere più utenti.","ui.setup.backend-user.error":"Impossibile recuperare l\'elenco degli utenti. Controlla l\'output della console per i dettagli.","ui.setup.backend-user.headline":"Utente di backend ","ui.setup.backend-user.description":"Per gestire il tuo sito web, devi avere almeno un account amministratore per il back-end di Contao. Tieni presente che questo account non è correlato a Contao Manager.","ui.setup.backend-user.formTitle":"Crea account","ui.setup.backend-user.formText":"Inserisci i dettagli per il nuovo account back-end.","ui.setup.backend-user.username":"Nome utente","ui.setup.backend-user.name":"Nome","ui.setup.backend-user.email":"Indirizzo e-mail","ui.setup.backend-user.emailInvalid":"Inserisci un indirizzo email valido","ui.setup.backend-user.password":"Password","ui.setup.backend-user.passwordPlaceholder":"min. 8 caratteri","ui.setup.backend-user.passwordLength":"Inserisci almeno 8 caratteri.","ui.setup.backend-user.create":"Aggiungi account","ui.task.headline":"Task in background ","ui.task.loading":"Caricamento dettagli…","ui.task.created":"Caricamento dettagli…","ui.task.active":"Attendere che Contao Manager esegua operazioni in background.","ui.task.complete":"Tutte le operazioni sono state completate correttamente. Controllare l\'output della console per i dettagli.","ui.task.paused":"Un\'operazione in background si è interrotta inaspettatamente. Controlla l\'output della console.","ui.task.aborting":"Attendi mentre le operazioni in background vengono annullate.","ui.task.stopped":"Alcune operazioni in background sono state annullate. Controlla l\'output della console.","ui.task.error":"Un\'operazione in background si è interrotta inaspettatamente. Controlla l\'output della console.","ui.task.failed":"Il Contao Manager non è riuscito ad avviare un\'attività in background!","ui.task.failedDescription1":"Qualcosa è andato storto durante il tentativo di eseguire operazioni in background.","ui.task.failedDescription2":"In questo caso, il tuo server potrebbe non essere supportato.","ui.task.reportProblem":"Segnala un problema","ui.task.pausedDescription":"Click \\"Continue\\" if you want to ignore the error and execute the remaining operations.","ui.task.sponsor":"Composer Cloud sponsorizzato da {sponsor}","ui.task.buttonAudit":"Aggiorna il database","ui.task.buttonClose":"Chiudi","ui.task.buttonConfirm":"Conferma e chiudi","ui.task.buttonContinue":"Continuare","ui.task.buttonCancel":"Annulla","ui.task.confirmCancel":"Sei sicuro di annullare questo compito? Questo potrebbe lasciare l\'installazione di Contao in uno stato danneggiato!","ui.task.autoclose":"Chiudi i dettagli dell\'attività in caso di successo","ui.console.toggle":"Visualizza/nasconde l\'uscita console","ui.console.showLog":"Mostra il registro completo della console","ui.console.copyLog":"Copia il registro negli appunti","ui.migrate.headline":"Aggiornamenti del database","ui.migrate.migrationsOnly":"(solo migrazioni)","ui.migrate.schemaOnly":"(solo schema)","ui.migrate.loading":"Attendi, stiamo controllando il database...","ui.migrate.empty":"Non è stato trovato nessuna migrazione in sospeso o aggiornamento dello schema. Il tuo database è aggiornato.","ui.migrate.emptyMigrations":"Non è stata trovata nessuna migrazione in sospeso. Controlla anche gli aggiornamenti dello schema.","ui.migrate.emptySchema":"Non è stato trovato nessun aggiornamento dello schema in sospeso. Assicurati di controllare anche le migrazioni.","ui.migrate.pending":"Il tuo database non è aggiornato. Si prega di rivedere l\'output della console di seguito ed eseguire le modifiche.","ui.migrate.previousChanges":"Una precedente migrazione del database non è stata confermata.\\nRivedi l\'output della console di seguito, quindi continua per vedere le modifiche successive.","ui.migrate.previousComplete":"Una precedente migrazione del database non è stata confermata, controlla l\'output della console di seguito.\\nNon ci sono più modifiche in sospeso.","ui.migrate.appliedChanges":"Database updates have been applied.\\nPlease review the console output below, then continue to see the next changes.","ui.migrate.appliedComplete":"Gli aggiornamenti del database sono stati applicati.\\nNon ci sono più migrazioni in sospeso o aggiornamenti dello schema. Il tuo database è aggiornato.","ui.migrate.problem":"Contao ha rilevato un problema con il database server.\\nSi prega di rivedere l\'output della console di seguito per scoprire cosa deve essere risolto. | Contao ha rilevato problemi con il database server.\\nSi prega di rivedere l\'output della console di seguito per scoprire cosa deve essere risolto.","ui.migrate.warning":"Contao ha rilevato una configurazione errata del database server.\\nGli avvisi possono essere ignorati temporaneamente, ma dovrebbero essere corretti per prestazioni e integrità dei dati ottimali.","ui.migrate.error":"Impossibile applicare le modifiche. Il tuo database potrebbe essere stato modificato, controlla di nuovo per riprovare.","ui.migrate.execute":"Esegui","ui.migrate.close":"Chiudi","ui.migrate.confirm":"Conferma e chiudi","ui.migrate.cancel":"Annulla","ui.migrate.continue":"Continuare","ui.migrate.setup":"Setup","ui.migrate.skip":"Salta","ui.migrate.retry":"Controlla nuovamente","ui.migrate.retryAll":"Seleziona tutto","ui.migrate.withDeletes":"Esegui tutte le modifiche al database comprese le query DROP.","ui.migrate.migrationTitle":"Migrazioni del database","ui.migrate.schemaTitle":"Aggiornamenti dello schema","ui.migrate.problemTitle":"Problemi al database","ui.migrate.warningTitle":"Avvisi sul database","ui.migrate.addTable":"Aggiungi tabella {table}","ui.migrate.dropTable":"Drop table {table}","ui.migrate.addField":"Aggiungi campo {table}.{field}","ui.migrate.changeField":"Cambia campo  {table}.{field}","ui.migrate.dropField":"Elimina campo {table}.{field}","ui.migrate.createIndex":"Crea indice \\"{name}\\" in {table}","ui.migrate.dropIndex":"Drop index \\"{name}\\" in {table}","ui.widget.mandatory":"Questo campo non deve essere vuoto.","ui.widget.blankOption":"Selezionare ...","ui.widget.showPassword":"Mostra password","ui.widget.hidePassword":"Nascondi password","ui.error.title":"Richiesta HTTP per \\"{metodo} {url}\\" fallita.","ui.error.server500":"Sembra che si sia verificato un errore imprevisto sul server. Controllare i file di log del proprio server web (Apache/Nginx) e i log di Contao Manager in \\"contao-manager/logs\\".","ui.error.response":"Il server ha restituito una risposta con il codice di stato {status}.","ui.error.moreLink":"Maggiori informazioni","ui.error.support":"Supporto Contao ","ui.error.permission":"You do not have permission to use this feature.","ui.footer.help":"Supporto","ui.footer.reportProblem":"Segnala un problema","ui.navigation.discover":"Scopri","ui.navigation.packages":"Pacchetti","ui.navigation.tools":"Strumenti","ui.navigation.installTool":"Strumento di installazione","ui.navigation.backend":"Contao Backend","ui.navigation.debug":"Modalità Debug Contao","ui.navigation.logViewer":"Log Viewer","ui.navigation.phpinfo":"Informazioni PHP","ui.navigation.phpinfoLoading":"Caricamento informazioni PHP","ui.navigation.maintenance":"Manutenzione","ui.navigation.rebuildCache":"Ricostruisci la cache","ui.navigation.users":"Accounts","ui.navigation.systemCheck":"Verifica del sistema","ui.navigation.advanced":"Avanzato","ui.navigation.logout":"Logout","ui.maintenance.database.title":"Database Migrations e Backups","ui.maintenance.database.description":"Database migrations ensure consistent data and table schemas.","ui.maintenance.database.migrations":"Una migrazione del database in sospeso | {count} migrazioni database in sospeso","ui.maintenance.database.schemaUpdates":"Un aggiornamento dello schema in sospeso | {count} aggiornamenti dello schema in attesa","ui.maintenance.database.error":"È stato trovato problema con il database.","ui.maintenance.database.warning":"Sono stati trovati degli avvisi del database","ui.maintenance.database.button":"Verifica il database","ui.maintenance.database.migrationOnly":"Controlla solo le migrazioni","ui.maintenance.database.schemaOnly":"Controlla solo lo schema","ui.maintenance.database.installTool":"Apri l\'Install Tool","ui.maintenance.database.createBackup":"Creare il backup","ui.maintenance.database.backupUnsupported":"I backup del database non sono supportati dalla tua versione di Contao.","ui.maintenance.database.backupList":"Hai un backup del database, creato il {date}. | Hai {count} backup del database, l\'ultimo è stato creato il {date}.","ui.maintenance.database.backupEmpty":"Al momento non hai backup del database.","ui.maintenance.rebuildCache.title":"Cache applicazione ","ui.maintenance.rebuildCache.description":"La ricostruzione della cache dell\'applicazione è necessaria dopo aver modificato uno qualsiasi dei file di configurazione.","ui.maintenance.rebuildCache.rebuildProd":"Ricostruire la cache di produzione","ui.maintenance.rebuildCache.rebuildDev":"Ricostruire la cache di sviluppo","ui.maintenance.rebuildCache.clearProd":"Cancella cache di produzione","ui.maintenance.rebuildCache.clearDev":"Cancella cache di sviluppo","ui.maintenance.installTool.title":"Contao Install Tool","ui.maintenance.installTool.description":"Lo strumento di installazione Contao viene bloccato automaticamente se si immette una password errata per tre volte di seguito.","ui.maintenance.installTool.unlock":"Sblocca Install Tool","ui.maintenance.installTool.lock":"Blocca Install Tool","ui.maintenance.dumpAutoload.title":"Composer Class Loader","ui.maintenance.dumpAutoload.description":"Il Composer autoloader è responsabile del caricamento della classe PHP. L\'autoloader deve essere scaricato solo dopo aver aggiunto i namespaces personalizzati nella root del composer.json.","ui.maintenance.dumpAutoload.button":"Dump Autoloader","ui.maintenance.composerInstall.title":"Dipendenze Composer","ui.maintenance.composerInstall.description":"Le dipendenze del Composer si trovano nella cartella {vendor} nella radice dell\'applicazione. La reinstallazione delle dipendenze può essere necessaria dopo la modifica o il caricamento manuale del file {composerLock}.","ui.maintenance.composerInstall.button":"Esegui Installer","ui.maintenance.composerInstall.update":"Esegui l\'aggiornamento Composer","ui.maintenance.composerCache.title":"Composer Cache","ui.maintenance.composerCache.description":"Composer mette in cache i pacchetti scaricati per migliorare le prestazioni. Se hai problemi con i file rotti, prova a cancellare la cache del Composer per forzare un nuovo download.","ui.maintenance.composerCache.button":"Cancella cache","ui.maintenance.maintenanceMode.title":"Modalità di manutenzione","ui.maintenance.maintenanceMode.description":"Mettendo Contao in modalità manutenzione, verrà visualizzato un modello \\"503 Service Unavailable\\" per il sito web.","ui.maintenance.maintenanceMode.enable":"Attiva","ui.maintenance.maintenanceMode.disable":"Disattiva","ui.maintenance.debugMode.title":"Debug Mode","ui.maintenance.debugMode.description":"Attiva la modalità debug impostando un utente e una password per il punto di ingresso {appDevPhp}.","ui.maintenance.debugMode.descriptionJwt":"Attiva la modalità debug impostando il cookie di debug per il dominio corrente.","ui.maintenance.debugMode.activate":"Attivare","ui.maintenance.debugMode.deactivate":"Disattiva","ui.maintenance.debugMode.credentials":"Credenziali","ui.maintenance.debugMode.user":"Inserisci un nome utente per la modalità di debug.","ui.maintenance.debugMode.password":"Inserisci una password per la modalità di debug.","ui.maintenance.opcodeCache.title":"Cache Opcode","ui.maintenance.opcodeCache.description":"Opcode mette in cache i file PHP sul processo web per un\'esecuzione più veloce. Deve essere cancellato in determinate circostanze se i file non vengono riconosciuti dopo la modifica.","ui.maintenance.opcodeCache.button":"Troncare la cache","ui.maintenance.safeMode":"Non disponibile in modalità Safe Mode","ui.maintenance.unsupported":"Non supportato dalla tua versione di Contao","ui.packages.updateButton":"Aggiorna pacchetti","ui.packages.searchButton":"Cerca pacchetti","ui.packages.searchPlaceholder":"Cerca pacchetti...","ui.packages.uploadOverlay":"Drag & drop files per caricarli","ui.packages.uploadButton":"Carica pacchetti","ui.packages.uploadMessage":"Hai una modifica non confermata. | Hai {count} modifiche non confermate.","ui.packages.uploadApply":"Conferma uploads","ui.packages.uploadReset":"Elimina Uploads","ui.packages.uploadIncomplete":"Questo file non è stato caricato completamente. Rimuovilo e riprova.","ui.packages.uploadDuplicate":"Questo file sembra essere caricato più volte. Rimuovi i duplicati.","ui.packages.uploadInstalled":"Questo file è già installato. Rimuovi i duplicati.","ui.packages.uploadUnsupported":"I caricamenti non sono supportati nella tua installazione. Assicurati che l\'estensione PHP ZIP sia installata e aggiorna le dipendenze.","ui.packages.changesMessage":"Hai una modifica non confermata. | Hai {count} modifiche non confermate.","ui.packages.changesDryrun":"Esecuzione a prova","ui.packages.changesApply":"Applicare le modifiche","ui.packages.changesApplyAll":"Aggiornare tutti i pacchetti","ui.packages.changesDryrunAll":"Esecuzione a prova di tutti i pacchetti","ui.packages.changesReset":"Ripristina modifiche","ui.packages.changesReview":"Revisione dei cambiamenti","ui.packagelist.loading":"Caricamento in corso ...","ui.packagelist.uploads":"Uploads","ui.packagelist.added":"Pacchetti nuovi","ui.packagelist.installed":"Pacchetti installati","ui.package.hintRevert":"Ripristina le modifiche","ui.package.hintNoupdate":"Non aggiornare","ui.package.hintConstraint":"Questo pacchetto sarà installato con vincolo {constraint} quando si applicano le modifiche.","ui.package.hintConstraintBest":"Questo pacchetto sarà installato nella migliore versione disponibile quando si applicano le modifiche.","ui.package.hintConstraintChange":"Il vincolo per questo pacchetto sarà cambiato da \\"{from}\\" a \\"{to}\\" quando si applicano le modifiche.","ui.package.hintConstraintUpdate":"Questo pacchetto sarà aggiornato quando si applicano le modifiche.","ui.package.hintAdded":"Questo pacchetto sarà aggiornato quando si applicano le modifiche.","ui.package.hintRemoved":"Questo pacchetto verrà rimosso quando si applicano le modifiche. ","ui.package.requiredTitle":"aggiunto manualmente","ui.package.requiredText":"Questo pacchetto è richiesto nel tuo composer.json ma non è installato.","ui.package.removedTitle":"rimosso manualmente","ui.package.removedText":"Questo pacchetto è stato rimosso dal tuo composer.json.","ui.package.installed":"Attualmente installato:","ui.package.version":"Versione {version}","ui.package.additionalDownloads":"{count} Download | {count} Downloads","ui.package.additionalStars":"{count} Stella | {count} Stelle","ui.package.editConstraint":"Modifica","ui.package.uploadConstraint":"Questo vincolo è definito dal pacchetto caricato.","ui.package.updateButton":"Aggiorna","ui.package.removeButton":"Rimuovi","ui.package.installButton":"Aggiungi pacchetto","ui.package.installButtonShort":"Aggiungi","ui.package.detailsButton":"Dettagli","ui.package.latestConstraint":"ultima versione","ui.package.update":"Aggiornamento disponibile","ui.package.updateLatest":"ultima versione","ui.package.updateAvailable":"{versione} disponibile","ui.package.updateUnknown":"versione sconosciuta","ui.package.updateConstraint":"È disponibile una versione più recente al di fuori del vincolo di versione.","ui.package.incompatible":"{package} does not work with Contao {constraint}.","ui.package.incompatibleWarning":"{package} does not work with Contao {constraint} in any of its stable releases. Do you want to add the package and set a version constraint to try installing a development branch?","ui.package.incompatibleConstraint":"This package does not have a stable release for Contao {constraint}. Set a version constraint to try installing a development branch.","ui.package.incompatibleButton":"Installa","ui.cloudStatus.headline":"Composer Resolver Cloud","ui.cloudStatus.version":"Versione {version}","ui.cloudStatus.waitingTime":"Tempo di attesa","ui.cloudStatus.jobs":"Lavori correnti","ui.cloudStatus.workers":"Lavoratori","ui.cloudStatus.approx":"{minutes} min","ui.cloudStatus.none":"nessuna","ui.cloudStatus.short":"circa {minutes} min","ui.cloudStatus.long":"circa {minutes} min {seconds} sec","ui.cloudStatus.error":"Impossibile ottenere lo stato del Composer Resolver Cloud. Potrebbe essere inattivo per problemi di manutenzione o di esercizio.","ui.cloudStatus.button":"Stato Cloud","ui.cloudStatus.refresh":"Aggiorna lo stato del cloud","ui.log-viewer.loading":"Caricamento in corso ...","ui.log-viewer.empty":"Non ci sono file di registro sul tuo server.","ui.log-viewer.reload":"Ricarica","ui.log-viewer.file":"Log file","ui.log-viewer.channel":"Canale","ui.log-viewer.channelTitle":"Il canale su cui è stato registrato questo messaggio.","ui.log-viewer.level":"Livello","ui.log-viewer.levelTitle":"Gravità del messaggio di log.","ui.log-viewer.timeHeader":"Tempo","ui.log-viewer.messageHeader":"Messaggio","ui.log-viewer.showContext":"Mostra contesto","ui.log-viewer.hideContext":"Nascondi contesto","ui.log-viewer.showExtra":"Mostra extra","ui.log-viewer.hideExtra":"Nascondi extra","ui.log-viewer.more":"Carica di più…","ui.log-viewer.download":"Download","ui.log-viewer.downloadTitle":"Download file \\"{file}\\"","ui.log-viewer.prodEnvironment":"Ambiente di produzione","ui.log-viewer.devEnvironment":"Ambiente di sviluppo (Modalità Debug)","ui.user-manager.loading":"Loading users …","ui.user-manager.changePassword":"Change Password","ui.user-manager.setupTotp":"Setup Two-Factor Authentication","ui.user-manager.disableTotp":"Disable Two-Factor Authentication","ui.user-manager.invite":"Invite User","ui.user-manager.delete":"Delete","ui.user-manager.deleteConfirm":"Do you really want to delete user \\"{username}\\"?","ui.user-manager.deleted":"User {username} deleted successfully","ui.user-manager.passwordHeadline":"Change Password","ui.user-manager.passwordText":"To change your password, please enter the current and a new password in the respective fields.","ui.user-manager.currentPassword":"Current password","ui.user-manager.newPassword":"New password","ui.user-manager.passwordPlaceholder":"min. 8 caratteri","ui.user-manager.submitPassword":"Submit","ui.user-manager.passwordChanged":"Your password has been changed successfully.","ui.user-manager.passwordError":"This password is incorrect.","ui.user-manager.inviteHeadline":"Invite User","ui.user-manager.inviteText":"If you need multiple logins for the Contao Manager, you can create an invitation link here. Share this link with someone or use it on another device to create a new account with the given permissions.","ui.user-manager.inviteSuccess1":"A new invitation link was created. The URL below can be used to create a new user account for this Contao Manager. The invitation expires on {expires} (one week from now).","ui.user-manager.inviteSuccess2":"Please copy the link to your clipboard. It will only work once and you will not be able to see it again after closing this dialog.","ui.user-manager.createInvitation":"Create Invitation Link","ui.user-manager.clipboard":"Copy to clipboard","ui.user-manager.permissions":"Learn about permissions","ui.user-manager.cancel":"Annulla","ui.user-manager.close":"Chiudi","ui.user-manager.you":"You","ui.user-manager.2fa":"2FA","ui.user-manager.2faEnabled":"This account is secured by two-factor authentication.","ui.user-manager.2faDisabled":"This account is insecure due to missing two-factor authentication.","ui.user-manager.passkey":"Passkey","ui.user-manager.passkeyTitle":"This account is secured by a Passkey.","ui.totp.headline":"Two-Factor Authentication","ui.totp.setupQr":"Please scan the QR code with your 2FA/TOTP app.","ui.totp.setupCode":"If you cannot scan the QR code, enter this key instead:","ui.totp.codeLabel":"Verification code","ui.totp.codeDescription":"Please enter the verification code generated by your 2FA/TOTP app.","ui.totp.disableText":"Please enter the verification code to disable two-factor authentication.","ui.totp.invalid":"The verification code is invalid.","ui.totp.enable":"Attiva","ui.totp.disable":"Disattiva","ui.totp.cancel":"Annulla","ui.totp.enabled":"Two-factor authentication was enabled successfully.","ui.totp.disabled":"Two-factor authentication was disabled successfully.","ui.totp.setup":"Setup Two-Factor Authentication","ui.totp.skip":"Skip Two-Factor Authentication"}')}}]);"use strict";(self["webpackChunkcontao_manager"]=self["webpackChunkcontao_manager"]||[]).push([[518],{2518:function(e){e.exports=JSON.parse('{"ui.app.title":"Contao Extensies","ui.app.loading":"Extensie Lijst laden …","ui.app.language":"Wijzig de taal voor de Contao Manager","ui.app.colorDark":"Donkere modus","ui.app.colorDarkTitle":"Verander het kleurenschema naar donker","ui.app.colorLight":"Lichte modus","ui.app.colorLightTitle":"Verander het kleurenschema naar licht","ui.discover.advertisement":"Advertentie in de extensielijst","ui.discover.loading":"Bezig met laden ...","ui.discover.offline":"Kon geen resultaten ophalen.","ui.discover.offlineExplain":"Controleer uw internetverbinding en schakel JavaScript blokkers uit in uw browser.","ui.discover.offlineButton":"Probeer opnieuw","ui.discover.searchPlaceholder":"Zoeken in {count} extensies…","ui.discover.empty":"Geen resultaten voor {query}","ui.discover.more":"Meer resultaten","ui.discover.sortBy":"Sorteren op","ui.discover.sortReleased":"Uitgebracht","ui.discover.sortReleasedTitle":"Sorteer de resultaten op releasedatum","ui.discover.sortLatest":"Updated","ui.discover.sortLatestTitle":"Sorteer de resultaten op laatst bijgewerkt","ui.discover.sortDownloads":"Downloads","ui.discover.sortDownloadsTitle":"Sorteer resultaten op aantal downloads","ui.discover.sortFavers":"Beoordeling","ui.discover.sortFaversTitle":"Sorteer de resultaten op beoordeling","ui.discover.detailsButton":"Details","ui.discover.latestPackages":"Nieuwste en bijgewerkte extensies","ui.discover.faversPackages":"Best beoordeelde extensies","ui.discover.downloadsPackages":"Meest gedownloade extensies","ui.discover.exactHit":"Exacte zoekopdrachtovereenkomst","ui.discover.results":"Meer zoekresultaten","ui.package.homepage":"Project Website","ui.package.private":"Privépakket","ui.package.privateTitle":"Privépakketten zijn alleen verkrijgbaar bij de leverancier (bijvoorbeeld als ZIP-download). Bezoek de website voor meer informatie.","ui.package.abandoned":"niet meer ondersteund","ui.package.abandonedText":"Dit pakket wordt niet langer ondersteund en onderhouden.","ui.package.abandonedReplace":"Dit pakket wordt niet langer ondersteund en onderhouden. De auteur stelt voor om in plaats daarvan het {vervangend} pakket te gebruiken.","ui.package.contaoVersion":"Beschikbaar voor Contao","ui.package-details.previous":"Vorige Extensie Details","ui.package-details.close":"Sluit Extensie Details","ui.package-details.loading":"Bezig met laden ...","ui.package-details.tabDescription":"Beschrijving","ui.package-details.tabRequire":"Vereisten","ui.package-details.tabFeatures":"Kenmerken","ui.package-details.tabSuggest":"Suggesties","ui.package-details.tabConflict":"Conflicten","ui.package-details.tabDependents":"Afhankelijkheden","ui.package-details.linkRequires":"vereist","ui.package-details.linkReplaces":"vervangt","ui.package-details.linkProvides":"biedt","ui.package-details.linkConflicts":"conflicten","ui.package-details.funding":"Fund package maintenance!","ui.package-details.contaoVersions":"Ondersteunde Contao versie(s)","ui.package-details.latest":"Laatste versie","ui.package-details.released":"uitgebracht op","ui.package-details.license":"Licentie(s)","ui.package-details.authors":"van","ui.package-details.more":"Meer","ui.package-details.packagist":"Details bundel","ui.package-details.metadata":"Bewerk Metadata","ui.package-details.support_docs":"Documentatie","ui.package-details.support_wiki":"Wiki","ui.package-details.support_forum":"Support Forum","ui.package-details.support_issues":"Problemen / Foutrapport","ui.package-details.support_source":"Broncode","ui.package-details.support_irc":"IRC / Chat","ui.package-details.support_email":"Support E-Mail","ui.package-details.support_rss":"RSS Feed"}')}}]);"use strict";(self["webpackChunkcontao_manager"]=self["webpackChunkcontao_manager"]||[]).push([[194],{194:function(a){a.exports=JSON.parse('{"ui.app.title":"Contao paplašinājumi","ui.app.loading":"Ielādē paplašinājumu sarakstu ...","ui.app.language":"Switch language for the Contao Manager","ui.app.colorDark":"Dark Mode","ui.app.colorDarkTitle":"Switch color scheme to dark","ui.app.colorLight":"Light Mode","ui.app.colorLightTitle":"Switch color scheme to light","ui.discover.advertisement":"Reklāma paplašinājumu sarakstā","ui.discover.loading":"Ielādē ...","ui.discover.offline":"Nevarēja iegūt nekādus rezultātus.","ui.discover.offlineExplain":"Pārbaudiet savu interneta savienojumu un atspējojiet JavaScript bloķētājus savā pārlūkprogrammā.","ui.discover.offlineButton":"Mēģini vēlreiz","ui.discover.searchPlaceholder":"Meklēt {count} paplašinājumos ...","ui.discover.empty":"Nav rezultātu {query}","ui.discover.more":"Vairāk rezultātu","ui.discover.sortBy":"Kārtot pēc","ui.discover.sortReleased":"Released","ui.discover.sortReleasedTitle":"Sort results by release date","ui.discover.sortLatest":"Atjaunināts","ui.discover.sortLatestTitle":"Sort results by last updated","ui.discover.sortDownloads":"Lejupielādes","ui.discover.sortDownloadsTitle":"Sort results by number of downloads","ui.discover.sortFavers":"Vērtējums","ui.discover.sortFaversTitle":"Sort results by rating","ui.discover.detailsButton":"Sīkāka informācija","ui.discover.latestPackages":"Jaunākie un atjauninātie paplašinājumi","ui.discover.faversPackages":"Visaugstāk novērtētie paplašinājumi","ui.discover.downloadsPackages":"Visvairāk lejupielādētie paplašinājumi","ui.discover.exactHit":"Exact query match","ui.discover.results":"More search results","ui.package.homepage":"Projekta mājaslapa","ui.package.private":"Privāta pakotne","ui.package.privateTitle":"Privātās pakotnes ir pieejamas tikai pie pārdevēja (piem., kā ZIP lejupielādes). Lūdzu, apmeklējiet vietni, lai iegūtu papildinformāciju.","ui.package.abandoned":"pamests","ui.package.abandonedText":"Šī pakotne ir pamesta un vairs netiek uzturēta.","ui.package.abandonedReplace":"Šī pakotne ir pamesta un vairs netiek uzturēta. Autors iesaka tās vietā izmantot pakotni {replacement}.","ui.package.contaoVersion":"Available for Contao","ui.package-details.previous":"Iepriekšējā paplašinājuma informācija","ui.package-details.close":"Aizvērt paplašinājuma informāciju","ui.package-details.loading":"Ielādē ...","ui.package-details.tabDescription":"Apraksts","ui.package-details.tabRequire":"Prasības","ui.package-details.tabFeatures":"Iespējas","ui.package-details.tabSuggest":"Ieteikumi","ui.package-details.tabConflict":"Konflikti","ui.package-details.tabDependents":"Atkarīgie","ui.package-details.linkRequires":"nepieciešams","ui.package-details.linkReplaces":"aizstāj","ui.package-details.linkProvides":"nodrošina","ui.package-details.linkConflicts":"konflikti","ui.package-details.funding":"Finansējiet paketes uzturēšanu!","ui.package-details.contaoVersions":"Supported Contao version(s)","ui.package-details.latest":"Jaunākā versija","ui.package-details.released":"izlaists","ui.package-details.license":"Licence(s)","ui.package-details.authors":"no","ui.package-details.more":"Vairāk","ui.package-details.packagist":"Pakotnes informācija","ui.package-details.metadata":"Rediģēt metadatus","ui.package-details.support_docs":"Dokumentācija","ui.package-details.support_wiki":"Wiki","ui.package-details.support_forum":"Atbalsta forums","ui.package-details.support_issues":"Problēmas / Kļūdu ziņojums","ui.package-details.support_source":"Avota kods","ui.package-details.support_irc":"IRC / Tērzēšana","ui.package-details.support_email":"Atbalsta e-pasts","ui.package-details.support_rss":"RSS barotne"}')}}]);"use strict";(self["webpackChunkcontao_manager"]=self["webpackChunkcontao_manager"]||[]).push([[554],{4554:function(e){e.exports=JSON.parse('{"ui.app.httpsHeadline":"!! Connexion non sécurisée !!","ui.app.httpsDescription":"Sans HTTPS, vos données confidentielles seront transférées non chiffrées.","ui.app.httpsLink":"Plus d\'infos","ui.app.httpsHref":"https://https.cio.gov/everything/","ui.app.safeModeHeadline":"!! Mode sans échec activé !!","ui.app.safeModeDescription":"Certaines fonctionnalités du Contao Manager ne sont pas disponibles.","ui.app.safeModeExit":"Quitter le mode sans échec","ui.app.limitedHeadline":"Authentification à distance","ui.app.limitedDescription":"Vos permissions sont limitées en raison d\'une connexion sans mot de passe.","ui.app.limitedLogout":"Se ré-authentifier","ui.app.totpHeadline":"Avis de sécurité","ui.app.totpDescription":"Configurez l\'authentification à deux facteurs maintenant pour sécuriser votre compte.","ui.app.totpSetup":"Configuration","ui.app.loading":"Chargement de Contao Manager …","ui.app.apiError":"Statut de l\'API inattendu","ui.app.configSecurity1":"ALERTE DE SÉCURITÉ !!! Répertoire de configuration non protégé détecté","ui.app.configSecurity2":"Le Contao Manager a détecté que ses fichiers de configuration sont accessibles au public. Toutes les opérations sont désactivées jusqu\'à ce que le répertoire soit sécurisé, sinon un attaquant pourrait accéder aux données sensibles de votre installation.\\n\\nPour résoudre ce problème, assurez-vous d\'empêcher l\'accès au répertoire \\"contao-manager\\" sur votre serveur. Pour savoir comment faire, veuillez vous référer au manuel de votre serveur web ou contactez votre hébergeur.","ui.account.welcome":"Bienvenue","ui.account.intro1":"Bienvenue dans le Contao Manager, un outil universel pour installer et gérer le CMS Open Source Contao. Si vous débutez, veuillez {readTheManualToGetStarted}.","ui.account.introGetStarted":"{readTheManual} pour commencer","ui.account.introManual":"lire le manuel","ui.account.intro2":"Si vous rencontrez des problèmes, consultez {ourGithubIssues} et n\'hésitez pas à en créer un nouveau pour tout ce qui n\'a pas encore été signalé.","ui.account.introIssues":"nos tickets GitHub","ui.account.headline":"Compte utilisateur","ui.account.description":"Pour gérer votre installation, veuillez créer un compte pour le Contao Manager. Sachez que ce compte n\'est pas lié au back office ou au front office de Contao.","ui.account.username":"Nom d\'utilisateur","ui.account.password":"Mot de passe","ui.account.passwordPlaceholder":"min. 8 caractères","ui.account.passwordLength":"Veuillez saisir au moins 8 caractères.","ui.account.loginInvalid":"Une erreur est survenue lors de la création du compte. Veuillez essayer un autre nom d\'utilisateur.","ui.account.submit":"Créer un compte","ui.account.usePassword":"Utiliser un mot de passe pour la connexion","ui.account.usePasskey":"Utiliser une clé d\'accès (Passkey) pour la connexion","ui.account.totpHeadline":"Authentification à deux facteurs","ui.account.totpDescription":"Veuillez activer l\'authentification à deux facteurs, qui ajoute une couche de sécurité supplémentaire à votre compte. En plus de votre nom d\'utilisateur et de votre mot de passe, vous devrez saisir un code de vérification généré par une application telle que 1Password, Authy, Google Authenticator, Microsoft Authenticator, LastPass Authenticator ou toute autre application TOTP.","ui.account.totpSetup":"Configurer maintenant","ui.account.totpSkip":"Configurer plus tard","ui.account.login":"Refuser l\'invitation","ui.account.contribute1":"Contao et le Contao Manager sont parrainés par l\'Association Contao à but non lucratif.","ui.account.contribute2":"Veuillez envisager de contribuer à l\'Open Source en {donate}.","ui.account.contributeDonate":"faisant un don","ui.login.headline":"Se connecter","ui.login.description":"Connectez-vous pour gérer votre installation.","ui.login.username":"Nom d\'utilisateur","ui.login.password":"Mot de passe","ui.login.totpHeadline":"Authentification à deux facteurs","ui.login.totpDescription":"Veuillez saisir votre code de vérification pour terminer le processus de connexion.","ui.login.totp":"Code de vérification","ui.login.forgotPassword":"Mot de passe oublié ?","ui.login.button":"Se connecter","ui.login.passkey":"Se connecter avec une Passkey","ui.login.cancel":"Annuler","ui.login.or":"ou","ui.login.locked":"L\'accès a été refusé car le Contao Manager est verrouillé. Pour déverrouiller, supprimez le fichier {lockFile} dans le répertoire racine de Contao.","ui.logout.headline":"Expiration de la session","ui.logout.warning":"Vous êtes inactif depuis plus de 25 minutes. Pour des raisons de sécurité, votre session sera interrompue sous peu.","ui.logout.expired":"Votre session a été automatiquement interrompue car vous avez été inactif pendant plus de 30 minutes.","ui.logout.renew":"Rester connecté","ui.logout.logout":"Se déconnecter","ui.logout.login":"Retour à la connexion","ui.oauth.error":"Tentative OAuth invalide. Vérifiez les paramètres de la requête.","ui.oauth.https":"L\'URI de redirection DOIT utiliser un protocole sécurisé (https:) pour empêcher la transmission du jeton d\'authentification en clair.","ui.oauth.headline":"Authentification à distance","ui.oauth.description":"L\'application ou le service suivant demande un accès à distance à votre instance Contao Manager.","ui.oauth.domain":"Avant d\'autoriser l\'accès, assurez-vous de connaître cette URL et de faire confiance à son propriétaire !","ui.oauth.outOfScope":"Malheureusement, vous ne disposez pas des permissions nécessaires pour accorder cet accès.","ui.oauth.allow":"Autoriser l\'accès","ui.oauth.deny":"Refuser l\'accès","ui.oauth.switchUser":"Changer d\'utilisateur","ui.scope.admin":"Accès administrateur incluant la gestion des utilisateurs","ui.scope.install":"Installer de nouveaux paquets et modifier la configuration de Contao","ui.scope.update":"Mettre à jour les paquets et exécuter les tâches de maintenance","ui.scope.read":"Lire les paquets et la configuration","ui.boot.headline":"Vérification du système","ui.boot.description":"Veuillez patienter, nous analysons votre serveur …","ui.boot.issue1":"Problèmes d\'installation détectés","ui.boot.issue2":"Votre installation présente des problèmes qui doivent être résolus avant que le Contao Manager puisse être utilisé.","ui.boot.run":"Lancer le Contao Manager","ui.boot.safeMode":"Lancer en mode sans échec","ui.recovery.headline":"Récupération du système","ui.recovery.description":"Le Contao Manager a détecté des fichiers qui ressemblent à Contao, mais l\'interface de ligne de commande ne fonctionne pas comme prévu.","ui.recovery.console":"Sortie de la console","ui.recovery.repairOptions":"Veuillez choisir une option pour réparer votre installation.","ui.recovery.repairHeadline":"Réparation automatique","ui.recovery.repairDescription":"Tente de réparer automatiquement l\'installation en reconstruisant le cache de l\'application et en réinstallant les paquets Composer.","ui.recovery.repairWarning":"Toutes les modifications apportées aux fichiers du dossier \'vendor\' pourraient être supprimées durant le processus !","ui.recovery.repairFailed":"La réparation automatique a échoué. Essayez le mode sans échec pour réparer manuellement l\'installation.","ui.recovery.repairButton":"Lancer la réparation du système","ui.recovery.safeModeHeadline":"Mode sans échec","ui.recovery.safeModeDescription":"Lancer le Contao Manager en mode sans échec permet de gérer les paquets et d\'exécuter certaines tâches de maintenance, mais les fonctionnalités reposant sur une installation fonctionnelle de Contao ne seront pas disponibles.","ui.recovery.safeModeButton":"Lancer en mode sans échec","ui.server.pending":"En attente …","ui.server.running":"Analyse en cours …","ui.server.error":"La vérification a échoué en raison d\'une réponse inattendue du serveur.","ui.server.details":"Détails","ui.server.prerequisite":"Vérification annulée en raison d\'un prérequis manquant.","ui.server.selfUpdate.title":"Mises à jour du Contao Manager","ui.server.selfUpdate.update":"Une nouvelle version {latest} du Contao Manager est disponible.","ui.server.selfUpdate.manualUpdate":"Une nouvelle version {latest} du Contao Manager est disponible. Votre serveur ne supporte pas les mises à jour automatiques, veuillez télécharger la nouvelle version sur {download}.","ui.server.selfUpdate.latest":"Vous utilisez la dernière version {current}.","ui.server.selfUpdate.dev":"Les versions de développement ne supportent pas les mises à jour automatiques.","ui.server.selfUpdate.unsupported":"Une nouvelle version est disponible mais elle ne supporte pas votre version de PHP.","ui.server.selfUpdate.button":"Lancer la mise à jour automatique","ui.server.selfUpdate.continue":"Continuer","ui.server.config.title":"Configuration du serveur","ui.server.config.setup":"Configurer","ui.server.config.change":"Modifier","ui.server.config.save":"Sauvegarder","ui.server.config.cancel":"Annuler","ui.server.config.customOption":"Autre …","ui.server.config.description":"Pour exécuter correctement les tâches de fond, le Contao Manager doit savoir où trouver le binaire PHP en ligne de commande et comment exécuter des commandes séparément du processus web.","ui.server.config.formTitle":"Configuration du serveur","ui.server.config.formText":"Veuillez saisir le chemin vers votre binaire PHP. Assurez-vous que le binaire correspond à la même version PHP que votre processus web.","ui.server.config.cloudTitle":"Composer Resolver Cloud","ui.server.config.cloudText":"Le Composer Resolver Cloud permet d\'installer les dépendances Composer même si votre serveur ne dispose pas d\'assez de mémoire locale. Sachez que les informations de vos paquets seront transmises à un serveur cloud géré par l\'Association Contao.","ui.server.config.cloud":"Utiliser le Composer Resolver Cloud","ui.server.config.cli":"Binaire PHP","ui.server.config.stateErrorCli":"Aucun binaire PHP valide n\'a été trouvé sur le serveur.","ui.server.config.stateErrorCloud":"Le Composer Resolver Cloud n\'est pas supporté.","ui.server.config.stateSuccess":"Binaire PHP trouvé à {php_cli}.","ui.server.config.cloudEnabled":"Les dépendances des paquets seront résolues via le Composer Resolver Cloud.","ui.server.config.cloudDisabled":"Le Composer Resolver Cloud est désactivé.","ui.server.php_web.title":"Processus Web PHP","ui.server.php_web.below7":"Version PHP {version} trouvée. Veuillez passer à PHP 7 dès que possible !","ui.server.php_web.success":"Version PHP {version} trouvée, aucun problème connu.","ui.server.php_cli.title":"Interface Ligne de Commande PHP (CLI)","ui.server.php_cli.success":"Version PHP {version} trouvée, aucun problème connu.","ui.server.composer.title":"Environnement Composer","ui.server.composer.success":"Aucun problème connu trouvé.","ui.server.composer.install":"Les dépendances Composer ne sont pas installées.","ui.server.composer.button":"Installer","ui.server.contao.title":"Installation de Contao","ui.server.contao.setup":"Configuration","ui.server.contao.check":"Vérifier la base de données","ui.server.contao.empty":"Aucune installation de Contao n\'a été trouvée.","ui.server.contao.old":"La version {version} de Contao n\'est pas compatible avec le Contao Manager, veuillez mettre à jour votre installation manuellement.","ui.server.contao.found":"Contao {version} détecté (version API {api}).","ui.server.contao.connectionError":"Impossible de se connecter au serveur de base de données.","ui.server.contao.connectionProblem":"Problème de base de données détecté.","ui.server.contao.missingUser":"Compte administrateur introuvable.","ui.setup.continue":"Continuer","ui.setup.manager":"Lancer le Contao Manager","ui.setup.cancel":"Annuler","ui.setup.welcome":"Bienvenue","ui.setup.welcome1":"Cet assistant va vous guider à travers les étapes nécessaires pour configurer votre installation du CMS Open Source Contao.","ui.setup.welcome2":"Si vous avez des questions, vous trouverez la documentation, les forums, un canal Slack et plus encore sur la page {support}.","ui.setup.support":"support de la communauté","ui.setup.start":"Commencer","ui.setup.complete":"Félicitations !","ui.setup.complete1":"Contao {version} a été installé avec succès.","ui.setup.complete2":"Pour terminer le processus de configuration, veuillez ouvrir l\'outil d\'installation pour configurer la connexion à la base de données et créer un utilisateur back office.","ui.setup.complete3":"Vous pouvez maintenant commencer à créer votre site web dans le back office de Contao. Si vous avez besoin d\'extensions supplémentaires, continuez vers le Contao Manager.","ui.setup.installTool":"Ouvrir l\'outil d\'installation","ui.setup.login":"Se connecter à Contao","ui.setup.funding":"Un logiciel libre est « libre » comme dans « liberté d\'expression », pas comme dans « entrée libre ». Un projet Open Source comme Contao nécessite des fonds qu\'une seule personne ou entreprise ne peut réunir.\\nSi vous possédez ou vendez des sites web construits avec Contao, nous serions ravis de vous voir contribuer financièrement au produit sur lequel repose votre activité.","ui.setup.fundingLink":"En savoir plus","ui.setup.document-root.headline":"Configuration du serveur web","ui.setup.document-root.warning":"Pour installer Contao via le Contao Manager, vous devez corriger la racine du site (document root) sur le serveur web.","ui.setup.document-root.description1":"Contao utilise un dossier séparé pour les fichiers publics, les fichiers de l\'application sont installés dans son dossier parent. Contao ne peut pas être installé si la structure des dossiers n\'est pas correcte ou si les dossiers ne sont pas vides.","ui.setup.document-root.description2":"Si vous ne savez pas comment configurer votre document root, veuillez lire la documentation de Contao ou contacter votre hébergeur.","ui.setup.document-root.documentation":"Lire la documentation","ui.setup.document-root.conflictsTitle":"Répertoire d\'installation non vide","ui.setup.document-root.conflictsDirectory":"Le répertoire racine de votre future installation Contao n\'est pas vide, nous avons trouvé {count} fichier(s) qui pourraient être écrasés par le processus d\'installation. Il est recommandé de créer une structure de répertoire vide pour Contao, mais vous pouvez également supprimer les fichiers suivants et vérifier à nouveau si vous êtes sûr qu\'ils sont inutilisés.","ui.setup.document-root.ignoreConflicts":"Je souhaite installer Contao dans le répertoire non vide. Je comprends que cela pourrait écraser tout fichier existant sur mon espace web.","ui.setup.document-root.check":"Vérifier à nouveau","ui.setup.document-root.create":"Créer les répertoires","ui.setup.document-root.change":"Modifier les répertoires","ui.setup.document-root.formTitle":"Configuration des répertoires","ui.setup.document-root.formText1":"Le Contao Manager peut créer automatiquement une nouvelle structure de répertoires sur le serveur.","ui.setup.document-root.formText2":"Vous devrez configurer manuellement le nouveau document root (ex: via un panneau d\'administration d\'hébergement).","ui.setup.document-root.autoconfig":"Je comprends que je dois modifier la configuration de mon serveur. Ne pas configurer le document root cassera le Contao Manager et exposera les fichiers de configuration (y compris les détails du compte et les mots de passe) !","ui.setup.document-root.directory":"Nouveau répertoire","ui.setup.document-root.currentRoot":"Document Root actuel","ui.setup.document-root.newRoot":"Nouveau Document Root","ui.setup.document-root.finish":"Configurer les répertoires","ui.setup.document-root.publicDir":"Utiliser {dir} pour les fichiers publics (pour Contao {version})","ui.setup.document-root.directoryInvalid":"Veuillez saisir un nom de répertoire valide.","ui.setup.document-root.directoryExists":"Le répertoire cible existe déjà. Veuillez saisir un nom différent.","ui.setup.document-root.confirmation":"Le Contao Manager a créé avec succès le répertoire nécessaire pour votre installation Contao. Vous devez maintenant configurer le document root sur votre serveur web. Ne rechargez pas cette page d\'ici là.","ui.setup.document-root.reload":"Recharger la page","ui.setup.document-root.success":"La structure des répertoires sur votre serveur web est correctement configurée !","ui.setup.document-root.installingProjectDir":"Les fichiers de l\'application seront installés dans {dir}.","ui.setup.document-root.installingPublicDir":"Les fichiers publics seront installés dans {dir}.","ui.setup.document-root.installedProjectDir":"Les fichiers de l\'application sont installés dans {dir}.","ui.setup.document-root.installedPublicDir":"Les fichiers publics sont installés dans {dir}.","ui.setup.create-project.headline":"Installation de Contao","ui.setup.create-project.description":"Le développement de Contao suit le principe de la {semver}, une nouvelle version mineure sort tous les six mois. Les versions actuellement supportées sont :","ui.setup.create-project.semver":"version sémantique (Semantic Versioning)","ui.setup.create-project.latestTitle":"Dernière version","ui.setup.create-project.ltsTitle":"Support à long terme (LTS)","ui.setup.create-project.latestQ1":"Notre dernière version offre le plus de fonctionnalités avec un support jusqu\'en février {year}.","ui.setup.create-project.latestQ3":"Notre dernière version offre le plus de fonctionnalités avec un support jusqu\'en août {year}.","ui.setup.create-project.ltsText":"Notre version LTS actuelle, si vous privilégiez la stabilité. Offre un support à long terme jusqu\'en février {year}.","ui.setup.create-project.pltsText":"La version LTS précédente, bénéficie toujours d\'un support à long terme jusqu\'en février {year}.","ui.setup.create-project.requiresPHP":"Nécessite au moins PHP {version}, vous avez PHP {current}.","ui.setup.create-project.releaseplan":"Consultez le {contaoReleasePlan} pour des informations détaillées.","ui.setup.create-project.releaseplanLink":"plan de publication de Contao","ui.setup.create-project.installed":"Contao {version} est correctement installé sur le serveur. Continuez pour configurer votre base de données ou lancez le Contao Manager pour installer une version différente.","ui.setup.create-project.formTitle":"Sélectionner une distribution","ui.setup.create-project.formText":"Veuillez choisir la version à installer.","ui.setup.create-project.version":"Version","ui.setup.create-project.demo":"Installer le site de démonstration Contao","ui.setup.create-project.demoDescription":"Le site de démonstration vous aide à vous familiariser avec Contao et toutes ses fonctionnalités de base. D\'autres thèmes sont disponibles dans le {store}.","ui.setup.create-project.coreOnly":"Installation minimale (Cœur uniquement)","ui.setup.create-project.noUpdate":"Passer l\'installation (Experts uniquement !)","ui.setup.create-project.theme":"Thème Contao","ui.setup.create-project.themeInstall":"Pour installer un thème Contao, utilisez le champ de recherche ou téléchargez un fichier de thème (.cto/.zip) supportant l\'installation via le Contao Manager.","ui.setup.create-project.themeBuy":"N\'oubliez pas de visiter le {store} officiel.","ui.setup.create-project.themeStore":"Boutique de thèmes Contao","ui.setup.create-project.themeUpload":"Télécharger un fichier de thème (.cto/.zip)","ui.setup.create-project.themeInvalid":"Le fichier téléchargé n\'est pas un thème Contao ou ne supporte pas le Contao Manager.","ui.setup.create-project.themeWarning":"Le Contao Manager ne peut pas dire si ce thème est compatible avec votre serveur. Veuillez vérifier auprès du vendeur du thème si vous avez des questions.","ui.setup.create-project.themeTitle":"Vérifier les détails du thème","ui.setup.create-project.themeDetails":"Les dépendances et fichiers suivants seront installés avec ce thème.","ui.setup.create-project.themeRequire":"{count} dépendance | {count} dépendances","ui.setup.create-project.themeFiles":"{count} fichier | {count} fichiers","ui.setup.create-project.theme.or":"ou rechercher des thèmes publics","ui.setup.create-project.theme.search":"Rechercher des thèmes","ui.setup.create-project.theme.more":"Plus de thèmes","ui.setup.create-project.theme.empty":"Aucun thème ne correspond à {query}","ui.setup.create-project.theme.uploaded":"Le fichier du thème a été téléchargé avec succès.","ui.setup.create-project.theme.packageName":"Nom du paquet","ui.setup.create-project.theme.version":"Version","ui.setup.create-project.theme.authors":"Auteur(s)","ui.setup.create-project.theme.upload":"Téléchargement de {name} ({size})","ui.setup.create-project.install":"Installer","ui.setup.create-project.cancel":"Annuler","ui.setup.create-project.fileError":"Impossible de trouver composer.json dans {file}.","ui.setup.create-project.jsonError":"composer.json contient du JSON invalide.","ui.setup.create-project.schemaError":"La validation du schéma de composer.json a échoué.","ui.setup.database-connection.headline":"Connexion à la base de données","ui.setup.database-connection.description":"Contao nécessite une base de données MySQL (ou un dérivé compatible comme MariaDB) pour stocker les pages, le contenu, les utilisateurs et d\'autres données relationnelles. Les paramètres de connexion sont stockés dans le fichier {env} à la racine du projet de votre installation Contao.","ui.setup.database-connection.formTitle":"Paramètres de connexion","ui.setup.database-connection.formText":"Saisissez une URL de base de données ou remplissez les champs nom d\'utilisateur, mot de passe, serveur et base de données séparément.","ui.setup.database-connection.url":"URL de la base de données","ui.setup.database-connection.validUrl":"L\'URL de la base de données est invalide ou la connexion au serveur a échoué.","ui.setup.database-connection.or":"ou","ui.setup.database-connection.user":"Nom d\'utilisateur","ui.setup.database-connection.password":"Mot de passe","ui.setup.database-connection.server":"Serveur (:Port)","ui.setup.database-connection.database":"Nom de la base de données","ui.setup.database-connection.connected":"Connexion réussie à la base de données {database} sur {server}.","ui.setup.database-connection.error":"Erreur lors de la connexion à la base de données.","ui.setup.database-connection.problem":"Contao a détecté un problème avec votre serveur de base de données.","ui.setup.database-connection.schemaTitle":"Schéma de la base de données","ui.setup.database-connection.migration":"Il y a une migration en attente. | Il y a {count} migrations en attente.","ui.setup.database-connection.schema":"Il y a une mise à jour de schéma en attente. | Il y a {count} mises à jour de schéma en attente.","ui.setup.database-connection.noChanges":"Le schéma de votre base de données est à jour.","ui.setup.database-connection.check":"Vérifier la base de données","ui.setup.database-connection.skip":"Passer","ui.setup.database-connection.save":"Sauvegarder","ui.setup.database-connection.change":"Modifier les identifiants","ui.setup.database-connection.restoreTitle":"Import de base de données","ui.setup.database-connection.restoreText":"Le thème que vous venez d\'installer contient une sauvegarde de base de données. Restaurez la base de données pour importer les données du thème ou passez cette étape pour commencer avec une installation Contao vierge. | Le thème que vous venez d\'installer contient plusieurs sauvegardes de base de données. Sélectionnez un fichier de sauvegarde pour importer les données du thème ou passez cette étape pour commencer avec une installation Contao vierge.","ui.setup.database-connection.backup":"Sauvegarder la base de données actuelle avant l\'import","ui.setup.database-connection.backupWarning":"Toutes les données de la base de données seront écrasées lors de l\'import ! Créez d\'abord une sauvegarde si la base de données n\'est pas vide.","ui.setup.database-connection.restore":"Importer la base de données du thème","ui.setup.database-connection.restoreOption":"Sauvegarde du {date} ({size})","ui.setup.database-connection.restored":"La base de données de votre thème a été importée avec succès. Continuez pour valider votre schéma de base de données.","ui.setup.backend-user.success":"Un compte administrateur pour le back office de Contao a été trouvé dans votre base de données. Utilisez le back office de Contao pour ajouter d\'autres utilisateurs.","ui.setup.backend-user.error":"Impossible de récupérer la liste des utilisateurs. Consultez la sortie de la console pour plus de détails.","ui.setup.backend-user.headline":"Compte Back office","ui.setup.backend-user.description":"Pour gérer votre site web, vous devez avoir au moins un compte administrateur pour le back office de Contao. Sachez que ce compte n\'est pas lié au Contao Manager.","ui.setup.backend-user.formTitle":"Créer un compte","ui.setup.backend-user.formText":"Veuillez saisir les détails pour le nouveau compte back office.","ui.setup.backend-user.username":"Nom d\'utilisateur","ui.setup.backend-user.name":"Nom","ui.setup.backend-user.email":"Adresse e-mail","ui.setup.backend-user.emailInvalid":"Veuillez saisir une adresse e-mail valide","ui.setup.backend-user.password":"Mot de passe","ui.setup.backend-user.passwordPlaceholder":"min. 8 caractères","ui.setup.backend-user.passwordLength":"Veuillez saisir au moins 8 caractères.","ui.setup.backend-user.create":"Ajouter le compte","ui.task.headline":"Tâche de fond","ui.task.loading":"Chargement des détails …","ui.task.created":"Chargement des détails …","ui.task.active":"Veuillez patienter pendant que le Contao Manager exécute des opérations en tâche de fond.","ui.task.complete":"Toutes les opérations se sont terminées avec succès. Consultez la sortie de la console pour plus de détails.","ui.task.paused":"Une opération en tâche de fond s\'est arrêtée de manière inattendue. Veuillez vérifier la sortie de la console.","ui.task.aborting":"Veuillez patienter pendant l\'annulation des opérations en tâche de fond.","ui.task.stopped":"Certaines opérations en tâche de fond ont été annulées. Veuillez vérifier la sortie de la console.","ui.task.error":"Une opération en tâche de fond s\'est arrêtée de manière inattendue. Veuillez vérifier la sortie de la console.","ui.task.failed":"Le Contao Manager n\'a pas pu démarrer une tâche de fond !","ui.task.failedDescription1":"Quelque chose s\'est mal passé lors de la tentative d\'exécution des opérations en tâche de fond.","ui.task.failedDescription2":"Si cela se reproduit, votre serveur pourrait ne pas être supporté.","ui.task.reportProblem":"Signaler un problème","ui.task.pausedDescription":"Cliquez sur \\"Continuer\\" si vous souhaitez ignorer l\'erreur et exécuter les opérations restantes.","ui.task.sponsor":"Composer Cloud parrainé par {sponsor}","ui.task.buttonAudit":"Mettre à jour la base de données","ui.task.buttonClose":"Fermer","ui.task.buttonConfirm":"Confirmer & Fermer","ui.task.buttonContinue":"Continuer","ui.task.buttonCancel":"Annuler","ui.task.confirmCancel":"Êtes-vous sûr de vouloir annuler cette tâche ? Cela pourrait laisser votre installation Contao dans un état instable !","ui.task.autoclose":"Fermer les détails de la tâche en cas de succès","ui.console.toggle":"Afficher/Masquer la sortie de la console","ui.console.showLog":"Afficher le journal complet de la console","ui.console.copyLog":"Copier le journal dans le presse-papiers","ui.migrate.headline":"Mises à jour de la base de données","ui.migrate.migrationsOnly":"(migrations uniquement)","ui.migrate.schemaOnly":"(schéma uniquement)","ui.migrate.loading":"Veuillez patienter, nous vérifions votre base de données …","ui.migrate.empty":"Aucune migration ou mise à jour de schéma en attente. Votre base de données est à jour.","ui.migrate.emptyMigrations":"Aucune migration en attente. Assurez-vous de vérifier également les mises à jour de schéma.","ui.migrate.emptySchema":"Aucune mise à jour de schéma en attente. Assurez-vous de vérifier également les migrations.","ui.migrate.pending":"Votre base de données n\'est pas à jour. Veuillez revoir la sortie de la console ci-dessous et exécuter les modifications.","ui.migrate.previousChanges":"Une migration de base de données précédente n\'a pas été confirmée.\\nVeuillez revoir la sortie de la console ci-dessous, puis continuez pour voir les modifications suivantes.","ui.migrate.previousComplete":"Une migration de base de données précédente n\'a pas été confirmée, veuillez revoir la sortie de la console ci-dessous.\\nIl n\'y a plus de modifications en attente.","ui.migrate.appliedChanges":"Les mises à jour de la base de données ont été appliquées.\\nVeuillez revoir la sortie de la console ci-dessous, puis continuez pour voir les modifications suivantes.","ui.migrate.appliedComplete":"Les mises à jour de la base de données ont été appliquées.\\nIl n\'y a plus de migrations ou de mises à jour de schéma en attente. Votre base de données est à jour.","ui.migrate.problem":"Contao a détecté un problème avec votre serveur de base de données.\\nVeuillez revoir la sortie de la console ci-dessous pour découvrir ce qui doit être corrigé. | Contao a détecté des problèmes avec votre serveur de base de données.\\nVeuillez revoir la sortie de la console ci-dessous pour découvrir ce qui doit être corrigé.","ui.migrate.warning":"Contao a détecté une mauvaise configuration de votre serveur de base de données.\\nLes avertissements peuvent être ignorés temporairement, mais devraient être corrigés pour des performances et une intégrité des données optimales.","ui.migrate.error":"Les modifications n\'ont pas pu être appliquées. Votre base de données a peut-être été modifiée, veuillez vérifier à nouveau pour réessayer.","ui.migrate.execute":"Exécuter","ui.migrate.close":"Fermer","ui.migrate.confirm":"Confirmer & Fermer","ui.migrate.cancel":"Annuler","ui.migrate.continue":"Continuer","ui.migrate.setup":"Configuration","ui.migrate.skip":"Passer","ui.migrate.retry":"Vérifier à nouveau","ui.migrate.retryAll":"Tout vérifier","ui.migrate.withDeletes":"Exécuter toutes les modifications de base de données, y compris les requêtes DROP.","ui.migrate.migrationTitle":"Migrations de base de données","ui.migrate.schemaTitle":"Mises à jour de schéma","ui.migrate.problemTitle":"Problèmes de base de données","ui.migrate.warningTitle":"Avertissements de base de données","ui.migrate.addTable":"Ajouter la table {table}","ui.migrate.dropTable":"Supprimer la table {table}","ui.migrate.addField":"Ajouter le champ {table}.{field}","ui.migrate.changeField":"Modifier le champ {table}.{field}","ui.migrate.dropField":"Supprimer le champ {table}.{field}","ui.migrate.createIndex":"Créer l\'index \\"{name}\\" sur {table}","ui.migrate.dropIndex":"Supprimer l\'index \\"{name}\\" sur {table}","ui.widget.mandatory":"Ce champ ne doit pas être vide.","ui.widget.blankOption":"Veuillez sélectionner …","ui.widget.showPassword":"Afficher le mot de passe","ui.widget.hidePassword":"Masquer le mot de passe","ui.error.title":"La requête HTTP pour \\"{method} {url}\\" a échoué.","ui.error.server500":"Il semble qu\'une erreur inattendue soit survenue sur votre serveur. Veuillez vérifier les fichiers journaux de votre serveur web (Apache/Nginx) et les journaux du Contao Manager dans \\"contao-manager/logs\\".","ui.error.response":"Le serveur a renvoyé une réponse avec le code statut {status}.","ui.error.moreLink":"Plus d\'informations","ui.error.support":"Support Contao","ui.error.permission":"Vous n\'avez pas la permission d\'utiliser cette fonctionnalité.","ui.footer.help":"Aide","ui.footer.reportProblem":"Signaler un problème","ui.navigation.discover":"Découvrir","ui.navigation.packages":"Paquets","ui.navigation.tools":"Outils","ui.navigation.installTool":"Outil d\'installation","ui.navigation.backend":"Back office de Contao","ui.navigation.debug":"Mode de débogage Contao","ui.navigation.logViewer":"Afficheur de journaux","ui.navigation.phpinfo":"Informations PHP","ui.navigation.phpinfoLoading":"Chargement des informations PHP …","ui.navigation.maintenance":"Maintenance","ui.navigation.rebuildCache":"Reconstruire le cache","ui.navigation.users":"Comptes","ui.navigation.systemCheck":"Vérification du système","ui.navigation.advanced":"Avancé","ui.navigation.logout":"Déconnexion","ui.maintenance.database.title":"Migrations et sauvegardes de base de données","ui.maintenance.database.description":"Les migrations de base de données garantissent la cohérence des données et des schémas de table.","ui.maintenance.database.migrations":"Une migration de base de données en attente | {count} migrations de base de données en attente","ui.maintenance.database.schemaUpdates":"Une mise à jour de schéma en attente | {count} mises à jour de schéma en attente","ui.maintenance.database.error":"Problème de base de données détecté.","ui.maintenance.database.warning":"Avertissements de base de données trouvés.","ui.maintenance.database.button":"Vérifier la base de données","ui.maintenance.database.migrationOnly":"Vérifier uniquement les migrations","ui.maintenance.database.schemaOnly":"Vérifier uniquement le schéma","ui.maintenance.database.installTool":"Ouvrir l\'outil d\'installation","ui.maintenance.database.createBackup":"Créer une sauvegarde","ui.maintenance.database.backupUnsupported":"Les sauvegardes de base de données ne sont pas supportées par votre version de Contao.","ui.maintenance.database.backupList":"Vous avez une sauvegarde de base de données, créée le {date}. | Vous avez {count} sauvegardes de base de données, la plus récente a été créée le {date}.","ui.maintenance.database.backupEmpty":"Vous n\'avez actuellement aucune sauvegarde de base de données.","ui.maintenance.rebuildCache.title":"Cache de l\'application","ui.maintenance.rebuildCache.description":"Reconstruire le cache de l\'application est nécessaire après la modification de n\'importe quel fichier de configuration.","ui.maintenance.rebuildCache.rebuildProd":"Reconstruire le cache de production","ui.maintenance.rebuildCache.rebuildDev":"Reconstruire le cache de développement","ui.maintenance.rebuildCache.clearProd":"Vider le cache de production","ui.maintenance.rebuildCache.clearDev":"Vider le cache de développement","ui.maintenance.installTool.title":"Outil d\'installation Contao","ui.maintenance.installTool.description":"L\'outil d\'installation Contao est automatiquement verrouillé si vous saisissez un mauvais mot de passe trois fois de suite.","ui.maintenance.installTool.unlock":"Déverrouiller l\'outil d\'installation","ui.maintenance.installTool.lock":"Verrouiller l\'outil d\'installation","ui.maintenance.dumpAutoload.title":"Chargeur de classes Composer (Class Loader)","ui.maintenance.dumpAutoload.description":"L\'autoloader de Composer est responsable du chargement des classes PHP. L\'autoloader doit être régénéré (dump) après avoir ajouté des namespaces personnalisés au fichier composer.json racine.","ui.maintenance.dumpAutoload.button":"Régénérer l\'autoloader","ui.maintenance.composerInstall.title":"Dépendances Composer","ui.maintenance.composerInstall.description":"Les dépendances Composer se trouvent dans le dossier {vendor} à la racine de votre application. Réinstaller les dépendances peut être nécessaire après manipulation ou téléchargement manuel du fichier {composerLock}.","ui.maintenance.composerInstall.button":"Lancer l\'installateur","ui.maintenance.composerInstall.update":"Lancer la mise à jour Composer","ui.maintenance.composerCache.title":"Cache Composer","ui.maintenance.composerCache.description":"Composer met en cache les paquets téléchargés pour améliorer les performances. Si vous rencontrez des problèmes tels que des fichiers corrompus, essayez de supprimer le cache Composer pour forcer un nouveau téléchargement.","ui.maintenance.composerCache.button":"Vider le cache","ui.maintenance.maintenanceMode.title":"Mode maintenance","ui.maintenance.maintenanceMode.description":"Activer le mode maintenance de Contao affichera un modèle \\"503 Service indisponible\\" pour le site web.","ui.maintenance.maintenanceMode.enable":"Activer","ui.maintenance.maintenanceMode.disable":"Désactiver","ui.maintenance.debugMode.title":"Mode de débogage","ui.maintenance.debugMode.description":"Activez le mode de débogage en définissant un utilisateur et un mot de passe pour le point d\'entrée {appDevPhp}.","ui.maintenance.debugMode.descriptionJwt":"Activez le mode de débogage en définissant le cookie de débogage pour le domaine actuel.","ui.maintenance.debugMode.activate":"Activer","ui.maintenance.debugMode.deactivate":"Désactiver","ui.maintenance.debugMode.credentials":"Identifiants","ui.maintenance.debugMode.user":"Veuillez saisir un nom d\'utilisateur pour le mode de débogage.","ui.maintenance.debugMode.password":"Veuillez saisir un mot de passe pour le mode de débogage.","ui.maintenance.opcodeCache.title":"Cache Opcode","ui.maintenance.opcodeCache.description":"Opcode met en cache les fichiers PHP sur le processus web pour une exécution plus rapide. Il doit être vidé dans certaines circonstances si les fichiers ne sont pas reconnus après modification.","ui.maintenance.opcodeCache.button":"Tronquer le cache","ui.maintenance.safeMode":"Non disponible en mode sans échec","ui.maintenance.unsupported":"Non supporté par votre version de Contao","ui.packages.updateButton":"Mettre à jour les paquets","ui.packages.searchButton":"Rechercher des paquets","ui.packages.searchPlaceholder":"Rechercher des paquets …","ui.packages.uploadOverlay":"Glisser-déposer les fichiers à télécharger","ui.packages.uploadButton":"Télécharger des paquets","ui.packages.uploadMessage":"Vous avez un téléchargement non confirmé. | Vous avez {count} téléchargements non confirmés.","ui.packages.uploadApply":"Confirmer les téléchargements","ui.packages.uploadReset":"Supprimer les téléchargements","ui.packages.uploadIncomplete":"Ce fichier n\'a pas été téléchargé complètement. Veuillez le supprimer et réessayer.","ui.packages.uploadDuplicate":"Ce fichier semble avoir été téléchargé plusieurs fois. Veuillez supprimer les doublons.","ui.packages.uploadInstalled":"Ce fichier est déjà installé. Veuillez supprimer les doublons.","ui.packages.uploadUnsupported":"Les téléchargements ne sont pas supportés dans votre installation. Veuillez vous assurer que l\'extension PHP ZIP est installée et mettez à jour vos dépendances.","ui.packages.changesMessage":"Vous avez un changement non confirmé. | Vous avez {count} changements non confirmés.","ui.packages.changesDryrun":"Test à blanc (Dry Run)","ui.packages.changesApply":"Appliquer les changements","ui.packages.changesApplyAll":"Mettre à jour tous les paquets","ui.packages.changesDryrunAll":"Tester tous les paquets à blanc","ui.packages.changesReset":"Réinitialiser les changements","ui.packages.changesReview":"Revoir les changements","ui.packagelist.loading":"Chargement …","ui.packagelist.uploads":"Téléchargements","ui.packagelist.added":"Nouveaux paquets","ui.packagelist.installed":"Paquets installés","ui.package.hintRevert":"Annuler les changements","ui.package.hintNoupdate":"Ne pas mettre à jour","ui.package.hintConstraint":"Ce paquet sera installé avec la contrainte {constraint} lorsque vous appliquerez les changements.","ui.package.hintConstraintBest":"Ce paquet sera installé dans la meilleure version disponible lorsque vous appliquerez les changements.","ui.package.hintConstraintChange":"La contrainte pour ce paquet sera modifiée de \\"{from}\\" à \\"{to}\\" lorsque vous appliquerez les changements.","ui.package.hintConstraintUpdate":"Ce paquet sera mis à jour lorsque vous appliquerez les changements.","ui.package.hintAdded":"Ce paquet sera installé lorsque vous appliquerez les changements.","ui.package.hintRemoved":"Ce paquet sera supprimé lorsque vous appliquerez les changements.","ui.package.requiredTitle":"ajouté manuellement","ui.package.requiredText":"Ce paquet est requis dans votre composer.json mais n\'est pas installé.","ui.package.removedTitle":"supprimé manuellement","ui.package.removedText":"Ce paquet a été supprimé de votre composer.json.","ui.package.installed":"Actuellement installé :","ui.package.version":"Version {version}","ui.package.additionalDownloads":"{count} téléchargement | {count} téléchargements","ui.package.additionalStars":"{count} étoile | {count} étoiles","ui.package.editConstraint":"Modifier","ui.package.uploadConstraint":"Cette contrainte est définie par le paquet téléchargé.","ui.package.updateButton":"Mettre à jour","ui.package.removeButton":"Supprimer","ui.package.installButton":"Ajouter le paquet","ui.package.installButtonShort":"Ajouter","ui.package.detailsButton":"Détails","ui.package.latestConstraint":"dernière version","ui.package.update":"Mise à jour disponible","ui.package.updateLatest":"dernière version","ui.package.updateAvailable":"{version} disponible","ui.package.updateUnknown":"version inconnue","ui.package.updateConstraint":"Une version plus récente, hors de votre contrainte de version, est disponible.","ui.package.incompatible":"{package} ne fonctionne pas avec Contao {constraint}.","ui.package.incompatibleWarning":"{package} ne fonctionne avec Contao {constraint} dans aucune de ses versions stables. Voulez-vous ajouter le paquet et définir une contrainte de version pour essayer d\'installer une branche de développement ?","ui.package.incompatibleConstraint":"Ce paquet n\'a pas de version stable pour Contao {constraint}. Définissez une contrainte de version pour essayer d\'installer une branche de développement.","ui.package.incompatibleButton":"Installer","ui.cloudStatus.headline":"Composer Resolver Cloud","ui.cloudStatus.version":"Version {version}","ui.cloudStatus.waitingTime":"Temps d\'attente","ui.cloudStatus.jobs":"Tâches actuelles","ui.cloudStatus.workers":"Workers","ui.cloudStatus.approx":"{minutes} min","ui.cloudStatus.none":"aucun","ui.cloudStatus.short":"env. {minutes} min","ui.cloudStatus.long":"env. {minutes} min {seconds} sec","ui.cloudStatus.error":"Impossible de récupérer le statut du Composer Resolver Cloud. Il est peut-être en maintenance ou rencontre des problèmes.","ui.cloudStatus.button":"Statut du Cloud","ui.cloudStatus.refresh":"Actualiser le statut du Cloud","ui.log-viewer.loading":"Chargement …","ui.log-viewer.empty":"Il n\'y a pas de fichiers journaux sur votre serveur.","ui.log-viewer.reload":"Recharger","ui.log-viewer.file":"Fichier journal","ui.log-viewer.channel":"Canal","ui.log-viewer.channelTitle":"Le canal sur lequel ce message a été enregistré.","ui.log-viewer.level":"Niveau","ui.log-viewer.levelTitle":"Gravité du message du journal.","ui.log-viewer.timeHeader":"Heure","ui.log-viewer.messageHeader":"Message","ui.log-viewer.showContext":"Afficher le contexte","ui.log-viewer.hideContext":"Masquer le contexte","ui.log-viewer.showExtra":"Afficher les extras","ui.log-viewer.hideExtra":"Masquer les extras","ui.log-viewer.more":"Charger plus …","ui.log-viewer.download":"Télécharger","ui.log-viewer.downloadTitle":"Télécharger le fichier \\"{file}\\"","ui.log-viewer.prodEnvironment":"Environnement de production","ui.log-viewer.devEnvironment":"Environnement de développement (Mode Débogage)","ui.user-manager.loading":"Chargement des utilisateurs …","ui.user-manager.changePassword":"Changer le mot de passe","ui.user-manager.setupTotp":"Configurer l\'authentification à deux facteurs","ui.user-manager.disableTotp":"Désactiver l\'authentification à deux facteurs","ui.user-manager.invite":"Inviter un utilisateur","ui.user-manager.delete":"Supprimer","ui.user-manager.deleteConfirm":"Voulez-vous vraiment supprimer l\'utilisateur \\"{username}\\" ?","ui.user-manager.deleted":"Utilisateur {username} supprimé avec succès","ui.user-manager.passwordHeadline":"Changer le mot de passe","ui.user-manager.passwordText":"Pour changer votre mot de passe, veuillez saisir le mot de passe actuel et un nouveau mot de passe dans les champs respectifs.","ui.user-manager.currentPassword":"Mot de passe actuel","ui.user-manager.newPassword":"Nouveau mot de passe","ui.user-manager.passwordPlaceholder":"min. 8 caractères","ui.user-manager.submitPassword":"Envoyer","ui.user-manager.passwordChanged":"Votre mot de passe a été modifié avec succès.","ui.user-manager.passwordError":"Ce mot de passe est incorrect.","ui.user-manager.inviteHeadline":"Inviter un utilisateur","ui.user-manager.inviteText":"Si vous avez besoin de plusieurs accès pour le Contao Manager, vous pouvez créer un lien d\'invitation ici. Partagez ce lien avec quelqu\'un ou utilisez-le sur un autre appareil pour créer un nouveau compte avec les permissions indiquées.","ui.user-manager.inviteSuccess1":"Un nouveau lien d\'invitation a été créé. L\'URL ci-dessous peut être utilisée pour créer un nouveau compte utilisateur pour ce Contao Manager. L\'invitation expire le {expires} (dans une semaine).","ui.user-manager.inviteSuccess2":"Veuillez copier le lien dans votre presse-papiers. Il ne fonctionnera qu\'une seule fois et vous ne pourrez plus le voir après avoir fermé cette fenêtre.","ui.user-manager.createInvitation":"Créer un lien d\'invitation","ui.user-manager.clipboard":"Copier dans le presse-papiers","ui.user-manager.permissions":"En savoir plus sur les permissions","ui.user-manager.cancel":"Annuler","ui.user-manager.close":"Fermer","ui.user-manager.you":"Vous","ui.user-manager.2fa":"2FA","ui.user-manager.2faEnabled":"Ce compte est sécurisé par l\'authentification à deux facteurs.","ui.user-manager.2faDisabled":"Ce compte n\'est pas sécurisé car l\'authentification à deux facteurs est manquante.","ui.user-manager.passkey":"Clé d\'accès","ui.user-manager.passkeyTitle":"Ce compte est sécurisé par une clé d\'accès (Passkey).","ui.totp.headline":"Authentification à deux facteurs","ui.totp.setupQr":"Veuillez scanner le QR code avec votre application 2FA/TOTP.","ui.totp.setupCode":"Si vous ne pouvez pas scanner le QR code, saisissez cette clé à la place :","ui.totp.codeLabel":"Code de vérification","ui.totp.codeDescription":"Veuillez saisir le code de vérification généré par votre application 2FA/TOTP.","ui.totp.disableText":"Veuillez saisir le code de vérification pour désactiver l\'authentification à deux facteurs.","ui.totp.invalid":"Le code de vérification est invalide.","ui.totp.enable":"Activer","ui.totp.disable":"Désactiver","ui.totp.cancel":"Annuler","ui.totp.enabled":"L\'authentification à deux facteurs a été activée avec succès.","ui.totp.disabled":"L\'authentification à deux facteurs a été désactivée avec succès.","ui.totp.setup":"Configurer l\'authentification à deux facteurs","ui.totp.skip":"Passer l\'authentification à deux facteurs"}')}}]);"use strict";(self["webpackChunkcontao_manager"]=self["webpackChunkcontao_manager"]||[]).push([[904],{5523:function(t,e,o){o.r(e),o.d(e,{default:function(){return I}});var s=o(641),a=o(33),i=o(3751),n=o(6894);const u={class:"view-account__header"},r={class:"view-account__product"},l=["href"],c={href:"https://github.com/contao/contao-manager/issues",target:"_blank"},d={key:0,class:"view-account__totp"},p={class:"view-account__headline"},h={class:"view-account__description"},g={key:1,class:"view-account__form"},m={class:"view-account__headline"},b={class:"view-account__description"},w={class:"view-account__fields"},k=["disabled"],_={class:"view-account__contribute"},v={href:"https://to.contao.org/donate",target:"_blank"};function $(t,e,o,$,f,L){const y=(0,s.g2)("i18n-t"),A=(0,s.g2)("text-field"),T=(0,s.g2)("button-group"),C=(0,s.g2)("loading-button"),P=(0,s.g2)("boxed-layout");return(0,s.uX)(),(0,s.Wv)(P,{wide:!0,slotClass:"view-account"},{default:(0,s.k6)(()=>[(0,s.Lk)("header",u,[e[11]||(e[11]=(0,s.Lk)("img",{src:n,width:"100",height:"100",alt:"Contao Logo"},null,-1)),(0,s.Lk)("p",r,[(0,s.Lk)("strong",null,(0,a.v_)(t.$t("ui.account.welcome")),1),e[8]||(e[8]=(0,s.eW)(" Contao Manager 1.10.13 ",-1))]),(0,s.Lk)("p",null,[(0,s.bF)(y,{keypath:"ui.account.intro1"},{readTheManualToGetStarted:(0,s.k6)(()=>[(0,s.bF)(y,{tag:"strong",keypath:"ui.account.introGetStarted"},{readTheManual:(0,s.k6)(()=>[(0,s.Lk)("a",{href:`https://to.contao.org/docs/contao-manager?lang=${t.$i18n.locale}`,target:"_blank"},(0,a.v_)(t.$t("ui.account.introManual")),9,l)]),_:1})]),_:1}),e[9]||(e[9]=(0,s.Lk)("br",null,null,-1)),e[10]||(e[10]=(0,s.Lk)("br",null,null,-1)),(0,s.bF)(y,{keypath:"ui.account.intro2"},{ourGithubIssues:(0,s.k6)(()=>[(0,s.Lk)("a",c,(0,a.v_)(t.$t("ui.account.introIssues")),1)]),_:1})])]),(0,s.bF)(i.eB,{name:"animate-flip",type:"transition",mode:"out-in"},{default:(0,s.k6)(()=>[t.currentUser&&!t.hasTotp?((0,s.uX)(),(0,s.CE)("main",d,[(0,s.Lk)("h1",p,(0,a.v_)(t.$t("ui.account.totpHeadline")),1),(0,s.Lk)("p",h,(0,a.v_)(t.$t("ui.account.totpDescription")),1),(0,s.Lk)("button",{class:"widget-button widget-button--primary",onClick:e[0]||(e[0]=(...t)=>L.setupTotp&&L.setupTotp(...t))},(0,a.v_)(t.$t("ui.totp.setup")),1),(0,s.Lk)("button",{class:"widget-button widget-button--alert",onClick:e[1]||(e[1]=(...t)=>L.skipTotp&&L.skipTotp(...t))},(0,a.v_)(t.$t("ui.totp.skip")),1)])):((0,s.uX)(),(0,s.CE)("main",g,[(0,s.Lk)("form",{onSubmit:e[7]||(e[7]=(0,i.D$)((...t)=>L.createAccount&&L.createAccount(...t),["prevent"]))},[(0,s.Lk)("h1",m,(0,a.v_)(t.$t("ui.account.headline")),1),(0,s.Lk)("p",b,(0,a.v_)(t.$t("ui.account.description")),1),(0,s.Lk)("fieldset",w,[(0,s.bF)(A,{ref:"username",name:"username",label:t.$t("ui.account.username"),disabled:t.logging_in,required:"",error:t.errors.username,onBlur:e[2]||(e[2]=e=>t.errors.username=""),modelValue:t.username,"onUpdate:modelValue":e[3]||(e[3]=e=>t.username=e)},null,8,["label","disabled","error","modelValue"]),t.usePassword?((0,s.uX)(),(0,s.Wv)(A,{key:0,ref:"password",name:"password",type:"password",label:t.$t("ui.account.password"),placeholder:t.$t("ui.account.passwordPlaceholder"),disabled:t.logging_in,required:"",pattern:".{8,}",error:t.errors.password,onBlur:L.validatePassword,modelValue:t.password,"onUpdate:modelValue":e[4]||(e[4]=e=>t.password=e)},null,8,["label","placeholder","disabled","error","onBlur","modelValue"])):(0,s.Q3)("",!0),t.supportsWebAuthn?((0,s.uX)(),(0,s.Wv)(T,{key:1,submit:"",color:"primary",disabled:!t.valid,loading:t.logging_in,label:t.$t("ui.account.submit")},{default:(0,s.k6)(()=>[(0,s.Lk)("button",{type:"button",class:"widget-button",disabled:t.logging_in,onClick:e[5]||(e[5]=e=>t.usePassword=!t.usePassword)},(0,a.v_)(t.$t("ui.account."+(t.usePassword?"usePasskey":"usePassword"))),9,k)]),_:1},8,["disabled","loading","label"])):((0,s.uX)(),(0,s.Wv)(C,{key:2,submit:"",color:"primary",disabled:!t.valid,loading:t.logging_in},{default:(0,s.k6)(()=>[(0,s.eW)((0,a.v_)(t.$t("ui.account.submit")),1)]),_:1},8,["disabled","loading"])),L.isInvitation?((0,s.uX)(),(0,s.CE)("button",{key:3,type:"button",class:"widget-button widget-button--anchor",onClick:e[6]||(e[6]=(...t)=>L.gotoLogin&&L.gotoLogin(...t))},(0,a.v_)(t.$t("ui.account.login")),1)):(0,s.Q3)("",!0)])],32)]))]),_:1}),(0,s.Lk)("aside",_,[(0,s.Lk)("p",null,[(0,s.eW)((0,a.v_)(t.$t("ui.account.contribute1")),1),e[12]||(e[12]=(0,s.Lk)("br",null,null,-1)),(0,s.bF)(y,{keypath:"ui.account.contribute2"},{donate:(0,s.k6)(()=>[(0,s.Lk)("a",v,(0,a.v_)(t.$t("ui.account.contributeDonate")),1)]),_:1})])])]),_:1})}o(3110);var f=o(6278),L=o(60),y=o(707),A=o(728),T=o(9757),C=o(5506),P=o(4676),V=o(9473),W={components:{BoxedLayout:A.A,TextField:T.A,LoadingButton:C.A,ButtonGroup:P.A},data:()=>({username:"",password:"",errors:{username:"",password:""},valid:!1,logging_in:!1,usePassword:!1,supportsWebAuthn:!0}),computed:{...(0,f.aH)("auth",{currentUser:"username",hasTotp:"totpEnabled"}),isInvitation:t=>!!t.$route.query.invitation},methods:{validate(){this.valid=this.$refs.username.checkValidity()&&(!this.usePassword||this.$refs.password.checkValidity())},validatePassword(){this.errors.password=null,""!==this.password&&this.password.length<8&&(this.errors.password=this.$t("ui.account.passwordLength"))},async createAccount(){if(!this.valid)return;this.logging_in=!0;const t={username:this.username};if(this.isInvitation&&(t.invitation=this.$route.query.invitation),this.usePassword)t.password=this.password;else{const o=(await this.$request.post("api/session/options",t)).data;let s;try{s=await(0,L.Ct)({optionsJSON:o})}catch(e){return void(this.logging_in=!1)}if(!s)return void(this.logging_in=!1);t.passkey=JSON.stringify(s)}201!==(await this.$store.dispatch("auth/login",t)).status&&(this.logging_in=!1,this.errors.username=this.$t("ui.account.loginInvalid"),setTimeout(()=>{this.$refs.username.focus()},0))},setupTotp(){this.$store.commit("modals/open",{id:"setup-totp",component:V.A})},skipTotp(){this.$store.commit("setView",y.A.BOOT)},gotoLogin(){this.$router.replace({name:this.$route.name,query:null}),this.$store.commit("setView",y.A.LOGIN)}},watch:{username(){this.validate()},password(){this.validate()},hasTotp(){this.$store.commit("setView",y.A.BOOT)}},mounted(){this.supportsWebAuthn="https:"===location.protocol&&(0,L.zZ)(),this.usePassword=!this.supportsWebAuthn,this.$refs.username&&this.$refs.username.focus()}},B=o(6262);const F=(0,B.A)(W,[["render",$]]);var I=F}}]);"use strict";(self["webpackChunkcontao_manager"]=self["webpackChunkcontao_manager"]||[]).push([[523],{523:function(e){e.exports=JSON.parse('{"ui.app.title":"Contao Erweiterungen","ui.app.loading":"Lade Erweiterungsliste …","ui.app.language":"Sprache für den Contao Manager wechseln","ui.app.colorDark":"Dunkles Design","ui.app.colorDarkTitle":"Farbschema auf dunkel umstellen","ui.app.colorLight":"Helles Design","ui.app.colorLightTitle":"Farbschema auf hell umstellen","ui.discover.advertisement":"Anzeigen in der Erweiterungsliste","ui.discover.loading":"Laden …","ui.discover.offline":"Konnte keine Ergebnisse laden.","ui.discover.offlineExplain":"Prüfe deine Internet-Verbindung und deaktiviere alle JavaScript-Blocker.","ui.discover.offlineButton":"Erneut versuchen","ui.discover.searchPlaceholder":"{count} Erweiterungen durchsuchen …","ui.discover.empty":"Keine Ergebnisse für {query}","ui.discover.more":"Mehr Resultate","ui.discover.sortBy":"Sortieren nach","ui.discover.sortReleased":"Veröffentlicht","ui.discover.sortReleasedTitle":"Ergebnisse nach der Veröffentlichung sortieren","ui.discover.sortLatest":"Aktualisiert","ui.discover.sortLatestTitle":"Ergebnisse nach der letzten Aktualisierung sortieren","ui.discover.sortDownloads":"Downloads","ui.discover.sortDownloadsTitle":"Ergebnisse nach Anzahl Downloads sortieren","ui.discover.sortFavers":"Bewertung","ui.discover.sortFaversTitle":"Ergebnisse nach Bewertung sortieren","ui.discover.detailsButton":"Details","ui.discover.latestPackages":"Neuste und aktualisierte Erweiterungen","ui.discover.faversPackages":"Bestbewertete Erweiterungen","ui.discover.downloadsPackages":"Meistgeladene Erweiterungen","ui.discover.exactHit":"Exakte Übereinstimmung der Suchanfrage","ui.discover.results":"Weitere Suchergebnisse","ui.package.homepage":"Projektwebseite","ui.package.private":"Privates Paket","ui.package.privateTitle":"Private Pakete sind nur vom jeweiligen Hersteller verfügbar (z.B. als ZIP-Download). Besuche die Webseite für weitere Informationen.","ui.package.abandoned":"verwaist","ui.package.abandonedText":"Diese Erweiterung ist verwaist und wird nicht mehr gepflegt.","ui.package.abandonedReplace":"Diese Erweiterung ist verwaist und wird nicht mehr gepflegt. Der Autor empfiehlt stattdessen das Paket {replacement} zu verwenden.","ui.package.contaoVersion":"Verfügbar für Contao","ui.package-details.previous":"Details der vorherigen Erweiterung","ui.package-details.close":"Details der Erweiterung schließen","ui.package-details.loading":"Laden …","ui.package-details.tabDescription":"Beschreibung","ui.package-details.tabRequire":"Abhängigkeiten","ui.package-details.tabFeatures":"Funktionen","ui.package-details.tabSuggest":"Empfehlungen","ui.package-details.tabConflict":"Konflikte","ui.package-details.tabDependents":"Abhängige","ui.package-details.linkRequires":"benötigt","ui.package-details.linkReplaces":"ersetzt","ui.package-details.linkProvides":"liefert","ui.package-details.linkConflicts":"inkompatibel mit","ui.package-details.funding":"Weiterentwicklung finanzieren!","ui.package-details.contaoVersions":"Unterstützte Contao-Version(en)","ui.package-details.latest":"Neuste Version","ui.package-details.released":"veröffentlicht am","ui.package-details.license":"Lizenz(en)","ui.package-details.authors":"von","ui.package-details.more":"Mehr","ui.package-details.packagist":"Paketdetails","ui.package-details.metadata":"Metadaten bearbeiten","ui.package-details.support_docs":"Dokumentation","ui.package-details.support_wiki":"Wiki","ui.package-details.support_forum":"Support-Forum","ui.package-details.support_issues":"Fehler melden","ui.package-details.support_source":"Quellcode","ui.package-details.support_irc":"IRC / Chat","ui.package-details.support_email":"Support E-Mail","ui.package-details.support_rss":"RSS-Feed"}')}}]);"use strict";(self["webpackChunkcontao_manager"]=self["webpackChunkcontao_manager"]||[]).push([[180],{2180:function(e){e.exports=JSON.parse('{"ui.app.title":"Extensiones Contao","ui.app.loading":"Cargando lista de extensiones ...","ui.app.language":"Cambiar idioma para el Contao Manager","ui.app.colorDark":"Modo oscuro","ui.app.colorDarkTitle":"Cambiar el esquema de color a oscuro","ui.app.colorLight":"Modo claro","ui.app.colorLightTitle":"Cambiar el esquema de color a claro","ui.discover.advertisement":"Aviso en la lista de extensiones","ui.discover.loading":"Cargando ...","ui.discover.offline":"No se pudo obtener ningún resultado.","ui.discover.offlineExplain":"Verifique su conexión a Internet y desactive los bloqueadores de JavaScript en su navegador.","ui.discover.offlineButton":"Inténtelo de nuevo","ui.discover.searchPlaceholder":"Buscar en {count} extensiones…","ui.discover.empty":"No hay resultados para {query}","ui.discover.more":"Más resultados","ui.discover.sortBy":"Ordenar por","ui.discover.sortReleased":"Publicado","ui.discover.sortReleasedTitle":"Ordenar resultados por fecha de lanzamiento","ui.discover.sortLatest":"Actualizado","ui.discover.sortLatestTitle":"Ordenar resultados por última actualización","ui.discover.sortDownloads":"Descargas","ui.discover.sortDownloadsTitle":"Ordenar resultados por número de descargas","ui.discover.sortFavers":"Clasificación","ui.discover.sortFaversTitle":"Ordenar resultados por calificación","ui.discover.detailsButton":"Detalles","ui.discover.latestPackages":"Extensiones más recientes y actualizadas","ui.discover.faversPackages":"Extensiones mejor calificadas","ui.discover.downloadsPackages":"Extensiones más descargadas","ui.discover.exactHit":"Coincidencia exacta de consulta","ui.discover.results":"Más resultados de búsqueda","ui.package.homepage":"Sitio web del proyecto","ui.package.private":"Paquete privado","ui.package.privateTitle":"Los paquetes privados solo están disponibles por parte del proveedor (por ejemplo, como descarga ZIP). Por favor, visite el sitio web para más información.","ui.package.abandoned":"abandonado","ui.package.abandonedText":"Este paquete está abandonado y ya no se mantiene.","ui.package.abandonedReplace":"su paquete es abandonado y ya no se mantiene. El autor sugiere usar el paquete {replacement} en su lugar.","ui.package.contaoVersion":"Disponible para Contao","ui.package-details.previous":"Detalles de extensiones anteriores","ui.package-details.close":"Cerrar detalles de extensión","ui.package-details.loading":"Cargando ...","ui.package-details.tabDescription":"Descripción","ui.package-details.tabRequire":"Requisitos","ui.package-details.tabFeatures":"Caracteristicas","ui.package-details.tabSuggest":"Sugerencias","ui.package-details.tabConflict":"Conflictos","ui.package-details.tabDependents":"Dependientes","ui.package-details.linkRequires":"requiere","ui.package-details.linkReplaces":"reemplaza","ui.package-details.linkProvides":"provee","ui.package-details.linkConflicts":"conflictos","ui.package-details.funding":"Mantenimiento del Fund Package!","ui.package-details.contaoVersions":"Version(es) compatible(s) de Contao","ui.package-details.latest":"Última versión","ui.package-details.released":"publicado el","ui.package-details.license":"Licencia(s)","ui.package-details.authors":"de","ui.package-details.more":"Más","ui.package-details.packagist":"Detalles del paquete","ui.package-details.metadata":"Editar metadatos","ui.package-details.support_docs":"Documentación","ui.package-details.support_wiki":"Wiki","ui.package-details.support_forum":"Foro de sopporte","ui.package-details.support_issues":"Problemas / Informe de error","ui.package-details.support_source":"Código fuente","ui.package-details.support_irc":"IRC / Chat","ui.package-details.support_email":"Email del soporte ","ui.package-details.support_rss":"RSS Feed"}')}}]);(self["webpackChunkcontao_manager"]=self["webpackChunkcontao_manager"]||[]).push([[710],{1710:function(e,t,r){
/*!

JSZip v3.10.1 - A JavaScript class for generating and reading zip files
<http://stuartk.com/jszip>

(c) 2009-2016 Stuart Knightley <stuart [at] stuartk.com>
Dual licenced under the MIT license or GPLv3. See https://raw.github.com/Stuk/jszip/main/LICENSE.markdown.

JSZip uses the library pako released under the MIT license :
https://github.com/nodeca/pako/blob/main/LICENSE
*/
!function(t){e.exports=t()}(function(){return function e(t,r,n){function i(a,o){if(!r[a]){if(!t[a]){var h=void 0;if(!o&&h)return require(a,!0);if(s)return s(a,!0);var u=new Error("Cannot find module '"+a+"'");throw u.code="MODULE_NOT_FOUND",u}var l=r[a]={exports:{}};t[a][0].call(l.exports,function(e){var r=t[a][1][e];return i(r||e)},l,l.exports,e,t,r,n)}return r[a].exports}for(var s=void 0,a=0;a<n.length;a++)i(n[a]);return i}({1:[function(e,t,r){"use strict";var n=e("./utils"),i=e("./support"),s="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";r.encode=function(e){for(var t,r,i,a,o,h,u,l=[],f=0,c=e.length,d=c,p="string"!==n.getTypeOf(e);f<e.length;)d=c-f,i=p?(t=e[f++],r=f<c?e[f++]:0,f<c?e[f++]:0):(t=e.charCodeAt(f++),r=f<c?e.charCodeAt(f++):0,f<c?e.charCodeAt(f++):0),a=t>>2,o=(3&t)<<4|r>>4,h=1<d?(15&r)<<2|i>>6:64,u=2<d?63&i:64,l.push(s.charAt(a)+s.charAt(o)+s.charAt(h)+s.charAt(u));return l.join("")},r.decode=function(e){var t,r,n,a,o,h,u=0,l=0,f="data:";if(e.substr(0,f.length)===f)throw new Error("Invalid base64 input, it looks like a data url.");var c,d=3*(e=e.replace(/[^A-Za-z0-9+/=]/g,"")).length/4;if(e.charAt(e.length-1)===s.charAt(64)&&d--,e.charAt(e.length-2)===s.charAt(64)&&d--,d%1!=0)throw new Error("Invalid base64 input, bad content length.");for(c=i.uint8array?new Uint8Array(0|d):new Array(0|d);u<e.length;)t=s.indexOf(e.charAt(u++))<<2|(a=s.indexOf(e.charAt(u++)))>>4,r=(15&a)<<4|(o=s.indexOf(e.charAt(u++)))>>2,n=(3&o)<<6|(h=s.indexOf(e.charAt(u++))),c[l++]=t,64!==o&&(c[l++]=r),64!==h&&(c[l++]=n);return c}},{"./support":30,"./utils":32}],2:[function(e,t,r){"use strict";var n=e("./external"),i=e("./stream/DataWorker"),s=e("./stream/Crc32Probe"),a=e("./stream/DataLengthProbe");function o(e,t,r,n,i){this.compressedSize=e,this.uncompressedSize=t,this.crc32=r,this.compression=n,this.compressedContent=i}o.prototype={getContentWorker:function(){var e=new i(n.Promise.resolve(this.compressedContent)).pipe(this.compression.uncompressWorker()).pipe(new a("data_length")),t=this;return e.on("end",function(){if(this.streamInfo.data_length!==t.uncompressedSize)throw new Error("Bug : uncompressed data size mismatch")}),e},getCompressedWorker:function(){return new i(n.Promise.resolve(this.compressedContent)).withStreamInfo("compressedSize",this.compressedSize).withStreamInfo("uncompressedSize",this.uncompressedSize).withStreamInfo("crc32",this.crc32).withStreamInfo("compression",this.compression)}},o.createWorkerFrom=function(e,t,r){return e.pipe(new s).pipe(new a("uncompressedSize")).pipe(t.compressWorker(r)).pipe(new a("compressedSize")).withStreamInfo("compression",t)},t.exports=o},{"./external":6,"./stream/Crc32Probe":25,"./stream/DataLengthProbe":26,"./stream/DataWorker":27}],3:[function(e,t,r){"use strict";var n=e("./stream/GenericWorker");r.STORE={magic:"\0\0",compressWorker:function(){return new n("STORE compression")},uncompressWorker:function(){return new n("STORE decompression")}},r.DEFLATE=e("./flate")},{"./flate":7,"./stream/GenericWorker":28}],4:[function(e,t,r){"use strict";var n=e("./utils"),i=function(){for(var e,t=[],r=0;r<256;r++){e=r;for(var n=0;n<8;n++)e=1&e?3988292384^e>>>1:e>>>1;t[r]=e}return t}();t.exports=function(e,t){return void 0!==e&&e.length?"string"!==n.getTypeOf(e)?function(e,t,r,n){var s=i,a=n+r;e^=-1;for(var o=n;o<a;o++)e=e>>>8^s[255&(e^t[o])];return-1^e}(0|t,e,e.length,0):function(e,t,r,n){var s=i,a=n+r;e^=-1;for(var o=n;o<a;o++)e=e>>>8^s[255&(e^t.charCodeAt(o))];return-1^e}(0|t,e,e.length,0):0}},{"./utils":32}],5:[function(e,t,r){"use strict";r.base64=!1,r.binary=!1,r.dir=!1,r.createFolders=!0,r.date=null,r.compression=null,r.compressionOptions=null,r.comment=null,r.unixPermissions=null,r.dosPermissions=null},{}],6:[function(e,t,r){"use strict";var n=null;n="undefined"!=typeof Promise?Promise:e("lie"),t.exports={Promise:n}},{lie:37}],7:[function(e,t,r){"use strict";var n="undefined"!=typeof Uint8Array&&"undefined"!=typeof Uint16Array&&"undefined"!=typeof Uint32Array,i=e("pako"),s=e("./utils"),a=e("./stream/GenericWorker"),o=n?"uint8array":"array";function h(e,t){a.call(this,"FlateWorker/"+e),this._pako=null,this._pakoAction=e,this._pakoOptions=t,this.meta={}}r.magic="\b\0",s.inherits(h,a),h.prototype.processChunk=function(e){this.meta=e.meta,null===this._pako&&this._createPako(),this._pako.push(s.transformTo(o,e.data),!1)},h.prototype.flush=function(){a.prototype.flush.call(this),null===this._pako&&this._createPako(),this._pako.push([],!0)},h.prototype.cleanUp=function(){a.prototype.cleanUp.call(this),this._pako=null},h.prototype._createPako=function(){this._pako=new i[this._pakoAction]({raw:!0,level:this._pakoOptions.level||-1});var e=this;this._pako.onData=function(t){e.push({data:t,meta:e.meta})}},r.compressWorker=function(e){return new h("Deflate",e)},r.uncompressWorker=function(){return new h("Inflate",{})}},{"./stream/GenericWorker":28,"./utils":32,pako:38}],8:[function(e,t,r){"use strict";function n(e,t){var r,n="";for(r=0;r<t;r++)n+=String.fromCharCode(255&e),e>>>=8;return n}function i(e,t,r,i,a,l){var f,c,d=e.file,p=e.compression,m=l!==o.utf8encode,_=s.transformTo("string",l(d.name)),g=s.transformTo("string",o.utf8encode(d.name)),b=d.comment,v=s.transformTo("string",l(b)),y=s.transformTo("string",o.utf8encode(b)),w=g.length!==d.name.length,k=y.length!==b.length,x="",S="",z="",C=d.dir,E=d.date,A={crc32:0,compressedSize:0,uncompressedSize:0};t&&!r||(A.crc32=e.crc32,A.compressedSize=e.compressedSize,A.uncompressedSize=e.uncompressedSize);var I=0;t&&(I|=8),m||!w&&!k||(I|=2048);var O=0,B=0;C&&(O|=16),"UNIX"===a?(B=798,O|=function(e,t){var r=e;return e||(r=t?16893:33204),(65535&r)<<16}(d.unixPermissions,C)):(B=20,O|=function(e){return 63&(e||0)}(d.dosPermissions)),f=E.getUTCHours(),f<<=6,f|=E.getUTCMinutes(),f<<=5,f|=E.getUTCSeconds()/2,c=E.getUTCFullYear()-1980,c<<=4,c|=E.getUTCMonth()+1,c<<=5,c|=E.getUTCDate(),w&&(S=n(1,1)+n(h(_),4)+g,x+="up"+n(S.length,2)+S),k&&(z=n(1,1)+n(h(v),4)+y,x+="uc"+n(z.length,2)+z);var R="";return R+="\n\0",R+=n(I,2),R+=p.magic,R+=n(f,2),R+=n(c,2),R+=n(A.crc32,4),R+=n(A.compressedSize,4),R+=n(A.uncompressedSize,4),R+=n(_.length,2),R+=n(x.length,2),{fileRecord:u.LOCAL_FILE_HEADER+R+_+x,dirRecord:u.CENTRAL_FILE_HEADER+n(B,2)+R+n(v.length,2)+"\0\0\0\0"+n(O,4)+n(i,4)+_+x+v}}var s=e("../utils"),a=e("../stream/GenericWorker"),o=e("../utf8"),h=e("../crc32"),u=e("../signature");function l(e,t,r,n){a.call(this,"ZipFileWorker"),this.bytesWritten=0,this.zipComment=t,this.zipPlatform=r,this.encodeFileName=n,this.streamFiles=e,this.accumulate=!1,this.contentBuffer=[],this.dirRecords=[],this.currentSourceOffset=0,this.entriesCount=0,this.currentFile=null,this._sources=[]}s.inherits(l,a),l.prototype.push=function(e){var t=e.meta.percent||0,r=this.entriesCount,n=this._sources.length;this.accumulate?this.contentBuffer.push(e):(this.bytesWritten+=e.data.length,a.prototype.push.call(this,{data:e.data,meta:{currentFile:this.currentFile,percent:r?(t+100*(r-n-1))/r:100}}))},l.prototype.openedSource=function(e){this.currentSourceOffset=this.bytesWritten,this.currentFile=e.file.name;var t=this.streamFiles&&!e.file.dir;if(t){var r=i(e,t,!1,this.currentSourceOffset,this.zipPlatform,this.encodeFileName);this.push({data:r.fileRecord,meta:{percent:0}})}else this.accumulate=!0},l.prototype.closedSource=function(e){this.accumulate=!1;var t=this.streamFiles&&!e.file.dir,r=i(e,t,!0,this.currentSourceOffset,this.zipPlatform,this.encodeFileName);if(this.dirRecords.push(r.dirRecord),t)this.push({data:function(e){return u.DATA_DESCRIPTOR+n(e.crc32,4)+n(e.compressedSize,4)+n(e.uncompressedSize,4)}(e),meta:{percent:100}});else for(this.push({data:r.fileRecord,meta:{percent:0}});this.contentBuffer.length;)this.push(this.contentBuffer.shift());this.currentFile=null},l.prototype.flush=function(){for(var e=this.bytesWritten,t=0;t<this.dirRecords.length;t++)this.push({data:this.dirRecords[t],meta:{percent:100}});var r=this.bytesWritten-e,i=function(e,t,r,i,a){var o=s.transformTo("string",a(i));return u.CENTRAL_DIRECTORY_END+"\0\0\0\0"+n(e,2)+n(e,2)+n(t,4)+n(r,4)+n(o.length,2)+o}(this.dirRecords.length,r,e,this.zipComment,this.encodeFileName);this.push({data:i,meta:{percent:100}})},l.prototype.prepareNextSource=function(){this.previous=this._sources.shift(),this.openedSource(this.previous.streamInfo),this.isPaused?this.previous.pause():this.previous.resume()},l.prototype.registerPrevious=function(e){this._sources.push(e);var t=this;return e.on("data",function(e){t.processChunk(e)}),e.on("end",function(){t.closedSource(t.previous.streamInfo),t._sources.length?t.prepareNextSource():t.end()}),e.on("error",function(e){t.error(e)}),this},l.prototype.resume=function(){return!!a.prototype.resume.call(this)&&(!this.previous&&this._sources.length?(this.prepareNextSource(),!0):this.previous||this._sources.length||this.generatedError?void 0:(this.end(),!0))},l.prototype.error=function(e){var t=this._sources;if(!a.prototype.error.call(this,e))return!1;for(var r=0;r<t.length;r++)try{t[r].error(e)}catch(e){}return!0},l.prototype.lock=function(){a.prototype.lock.call(this);for(var e=this._sources,t=0;t<e.length;t++)e[t].lock()},t.exports=l},{"../crc32":4,"../signature":23,"../stream/GenericWorker":28,"../utf8":31,"../utils":32}],9:[function(e,t,r){"use strict";var n=e("../compressions"),i=e("./ZipFileWorker");r.generateWorker=function(e,t,r){var s=new i(t.streamFiles,r,t.platform,t.encodeFileName),a=0;try{e.forEach(function(e,r){a++;var i=function(e,t){var r=e||t,i=n[r];if(!i)throw new Error(r+" is not a valid compression method !");return i}(r.options.compression,t.compression),o=r.options.compressionOptions||t.compressionOptions||{},h=r.dir,u=r.date;r._compressWorker(i,o).withStreamInfo("file",{name:e,dir:h,date:u,comment:r.comment||"",unixPermissions:r.unixPermissions,dosPermissions:r.dosPermissions}).pipe(s)}),s.entriesCount=a}catch(e){s.error(e)}return s}},{"../compressions":3,"./ZipFileWorker":8}],10:[function(e,t,r){"use strict";function n(){if(!(this instanceof n))return new n;if(arguments.length)throw new Error("The constructor with parameters has been removed in JSZip 3.0, please check the upgrade guide.");this.files=Object.create(null),this.comment=null,this.root="",this.clone=function(){var e=new n;for(var t in this)"function"!=typeof this[t]&&(e[t]=this[t]);return e}}(n.prototype=e("./object")).loadAsync=e("./load"),n.support=e("./support"),n.defaults=e("./defaults"),n.version="3.10.1",n.loadAsync=function(e,t){return(new n).loadAsync(e,t)},n.external=e("./external"),t.exports=n},{"./defaults":5,"./external":6,"./load":11,"./object":15,"./support":30}],11:[function(e,t,r){"use strict";var n=e("./utils"),i=e("./external"),s=e("./utf8"),a=e("./zipEntries"),o=e("./stream/Crc32Probe"),h=e("./nodejsUtils");function u(e){return new i.Promise(function(t,r){var n=e.decompressed.getContentWorker().pipe(new o);n.on("error",function(e){r(e)}).on("end",function(){n.streamInfo.crc32!==e.decompressed.crc32?r(new Error("Corrupted zip : CRC32 mismatch")):t()}).resume()})}t.exports=function(e,t){var r=this;return t=n.extend(t||{},{base64:!1,checkCRC32:!1,optimizedBinaryString:!1,createFolders:!1,decodeFileName:s.utf8decode}),h.isNode&&h.isStream(e)?i.Promise.reject(new Error("JSZip can't accept a stream when loading a zip file.")):n.prepareContent("the loaded zip file",e,!0,t.optimizedBinaryString,t.base64).then(function(e){var r=new a(t);return r.load(e),r}).then(function(e){var r=[i.Promise.resolve(e)],n=e.files;if(t.checkCRC32)for(var s=0;s<n.length;s++)r.push(u(n[s]));return i.Promise.all(r)}).then(function(e){for(var i=e.shift(),s=i.files,a=0;a<s.length;a++){var o=s[a],h=o.fileNameStr,u=n.resolve(o.fileNameStr);r.file(u,o.decompressed,{binary:!0,optimizedBinaryString:!0,date:o.date,dir:o.dir,comment:o.fileCommentStr.length?o.fileCommentStr:null,unixPermissions:o.unixPermissions,dosPermissions:o.dosPermissions,createFolders:t.createFolders}),o.dir||(r.file(u).unsafeOriginalName=h)}return i.zipComment.length&&(r.comment=i.zipComment),r})}},{"./external":6,"./nodejsUtils":14,"./stream/Crc32Probe":25,"./utf8":31,"./utils":32,"./zipEntries":33}],12:[function(e,t,r){"use strict";var n=e("../utils"),i=e("../stream/GenericWorker");function s(e,t){i.call(this,"Nodejs stream input adapter for "+e),this._upstreamEnded=!1,this._bindStream(t)}n.inherits(s,i),s.prototype._bindStream=function(e){var t=this;(this._stream=e).pause(),e.on("data",function(e){t.push({data:e,meta:{percent:0}})}).on("error",function(e){t.isPaused?this.generatedError=e:t.error(e)}).on("end",function(){t.isPaused?t._upstreamEnded=!0:t.end()})},s.prototype.pause=function(){return!!i.prototype.pause.call(this)&&(this._stream.pause(),!0)},s.prototype.resume=function(){return!!i.prototype.resume.call(this)&&(this._upstreamEnded?this.end():this._stream.resume(),!0)},t.exports=s},{"../stream/GenericWorker":28,"../utils":32}],13:[function(e,t,r){"use strict";var n=e("readable-stream").Readable;function i(e,t,r){n.call(this,t),this._helper=e;var i=this;e.on("data",function(e,t){i.push(e)||i._helper.pause(),r&&r(t)}).on("error",function(e){i.emit("error",e)}).on("end",function(){i.push(null)})}e("../utils").inherits(i,n),i.prototype._read=function(){this._helper.resume()},t.exports=i},{"../utils":32,"readable-stream":16}],14:[function(e,t,r){"use strict";t.exports={isNode:"undefined"!=typeof Buffer,newBufferFrom:function(e,t){if(Buffer.from&&Buffer.from!==Uint8Array.from)return Buffer.from(e,t);if("number"==typeof e)throw new Error('The "data" argument must not be a number');return new Buffer(e,t)},allocBuffer:function(e){if(Buffer.alloc)return Buffer.alloc(e);var t=new Buffer(e);return t.fill(0),t},isBuffer:function(e){return Buffer.isBuffer(e)},isStream:function(e){return e&&"function"==typeof e.on&&"function"==typeof e.pause&&"function"==typeof e.resume}}},{}],15:[function(e,t,r){"use strict";function n(e,t,r){var n,i=s.getTypeOf(t),o=s.extend(r||{},h);o.date=o.date||new Date,null!==o.compression&&(o.compression=o.compression.toUpperCase()),"string"==typeof o.unixPermissions&&(o.unixPermissions=parseInt(o.unixPermissions,8)),o.unixPermissions&&16384&o.unixPermissions&&(o.dir=!0),o.dosPermissions&&16&o.dosPermissions&&(o.dir=!0),o.dir&&(e=m(e)),o.createFolders&&(n=p(e))&&_.call(this,n,!0);var f="string"===i&&!1===o.binary&&!1===o.base64;r&&void 0!==r.binary||(o.binary=!f),(t instanceof u&&0===t.uncompressedSize||o.dir||!t||0===t.length)&&(o.base64=!1,o.binary=!0,t="",o.compression="STORE",i="string");var g=null;g=t instanceof u||t instanceof a?t:c.isNode&&c.isStream(t)?new d(e,t):s.prepareContent(e,t,o.binary,o.optimizedBinaryString,o.base64);var b=new l(e,g,o);this.files[e]=b}var i=e("./utf8"),s=e("./utils"),a=e("./stream/GenericWorker"),o=e("./stream/StreamHelper"),h=e("./defaults"),u=e("./compressedObject"),l=e("./zipObject"),f=e("./generate"),c=e("./nodejsUtils"),d=e("./nodejs/NodejsStreamInputAdapter"),p=function(e){"/"===e.slice(-1)&&(e=e.substring(0,e.length-1));var t=e.lastIndexOf("/");return 0<t?e.substring(0,t):""},m=function(e){return"/"!==e.slice(-1)&&(e+="/"),e},_=function(e,t){return t=void 0!==t?t:h.createFolders,e=m(e),this.files[e]||n.call(this,e,null,{dir:!0,createFolders:t}),this.files[e]};function g(e){return"[object RegExp]"===Object.prototype.toString.call(e)}var b={load:function(){throw new Error("This method has been removed in JSZip 3.0, please check the upgrade guide.")},forEach:function(e){var t,r,n;for(t in this.files)n=this.files[t],(r=t.slice(this.root.length,t.length))&&t.slice(0,this.root.length)===this.root&&e(r,n)},filter:function(e){var t=[];return this.forEach(function(r,n){e(r,n)&&t.push(n)}),t},file:function(e,t,r){if(1!==arguments.length)return e=this.root+e,n.call(this,e,t,r),this;if(g(e)){var i=e;return this.filter(function(e,t){return!t.dir&&i.test(e)})}var s=this.files[this.root+e];return s&&!s.dir?s:null},folder:function(e){if(!e)return this;if(g(e))return this.filter(function(t,r){return r.dir&&e.test(t)});var t=this.root+e,r=_.call(this,t),n=this.clone();return n.root=r.name,n},remove:function(e){e=this.root+e;var t=this.files[e];if(t||("/"!==e.slice(-1)&&(e+="/"),t=this.files[e]),t&&!t.dir)delete this.files[e];else for(var r=this.filter(function(t,r){return r.name.slice(0,e.length)===e}),n=0;n<r.length;n++)delete this.files[r[n].name];return this},generate:function(){throw new Error("This method has been removed in JSZip 3.0, please check the upgrade guide.")},generateInternalStream:function(e){var t,r={};try{if((r=s.extend(e||{},{streamFiles:!1,compression:"STORE",compressionOptions:null,type:"",platform:"DOS",comment:null,mimeType:"application/zip",encodeFileName:i.utf8encode})).type=r.type.toLowerCase(),r.compression=r.compression.toUpperCase(),"binarystring"===r.type&&(r.type="string"),!r.type)throw new Error("No output type specified.");s.checkSupport(r.type),"darwin"!==r.platform&&"freebsd"!==r.platform&&"linux"!==r.platform&&"sunos"!==r.platform||(r.platform="UNIX"),"win32"===r.platform&&(r.platform="DOS");var n=r.comment||this.comment||"";t=f.generateWorker(this,r,n)}catch(e){(t=new a("error")).error(e)}return new o(t,r.type||"string",r.mimeType)},generateAsync:function(e,t){return this.generateInternalStream(e).accumulate(t)},generateNodeStream:function(e,t){return(e=e||{}).type||(e.type="nodebuffer"),this.generateInternalStream(e).toNodejsStream(t)}};t.exports=b},{"./compressedObject":2,"./defaults":5,"./generate":9,"./nodejs/NodejsStreamInputAdapter":12,"./nodejsUtils":14,"./stream/GenericWorker":28,"./stream/StreamHelper":29,"./utf8":31,"./utils":32,"./zipObject":35}],16:[function(e,t,r){"use strict";t.exports=e("stream")},{stream:void 0}],17:[function(e,t,r){"use strict";var n=e("./DataReader");function i(e){n.call(this,e);for(var t=0;t<this.data.length;t++)e[t]=255&e[t]}e("../utils").inherits(i,n),i.prototype.byteAt=function(e){return this.data[this.zero+e]},i.prototype.lastIndexOfSignature=function(e){for(var t=e.charCodeAt(0),r=e.charCodeAt(1),n=e.charCodeAt(2),i=e.charCodeAt(3),s=this.length-4;0<=s;--s)if(this.data[s]===t&&this.data[s+1]===r&&this.data[s+2]===n&&this.data[s+3]===i)return s-this.zero;return-1},i.prototype.readAndCheckSignature=function(e){var t=e.charCodeAt(0),r=e.charCodeAt(1),n=e.charCodeAt(2),i=e.charCodeAt(3),s=this.readData(4);return t===s[0]&&r===s[1]&&n===s[2]&&i===s[3]},i.prototype.readData=function(e){if(this.checkOffset(e),0===e)return[];var t=this.data.slice(this.zero+this.index,this.zero+this.index+e);return this.index+=e,t},t.exports=i},{"../utils":32,"./DataReader":18}],18:[function(e,t,r){"use strict";var n=e("../utils");function i(e){this.data=e,this.length=e.length,this.index=0,this.zero=0}i.prototype={checkOffset:function(e){this.checkIndex(this.index+e)},checkIndex:function(e){if(this.length<this.zero+e||e<0)throw new Error("End of data reached (data length = "+this.length+", asked index = "+e+"). Corrupted zip ?")},setIndex:function(e){this.checkIndex(e),this.index=e},skip:function(e){this.setIndex(this.index+e)},byteAt:function(){},readInt:function(e){var t,r=0;for(this.checkOffset(e),t=this.index+e-1;t>=this.index;t--)r=(r<<8)+this.byteAt(t);return this.index+=e,r},readString:function(e){return n.transformTo("string",this.readData(e))},readData:function(){},lastIndexOfSignature:function(){},readAndCheckSignature:function(){},readDate:function(){var e=this.readInt(4);return new Date(Date.UTC(1980+(e>>25&127),(e>>21&15)-1,e>>16&31,e>>11&31,e>>5&63,(31&e)<<1))}},t.exports=i},{"../utils":32}],19:[function(e,t,r){"use strict";var n=e("./Uint8ArrayReader");function i(e){n.call(this,e)}e("../utils").inherits(i,n),i.prototype.readData=function(e){this.checkOffset(e);var t=this.data.slice(this.zero+this.index,this.zero+this.index+e);return this.index+=e,t},t.exports=i},{"../utils":32,"./Uint8ArrayReader":21}],20:[function(e,t,r){"use strict";var n=e("./DataReader");function i(e){n.call(this,e)}e("../utils").inherits(i,n),i.prototype.byteAt=function(e){return this.data.charCodeAt(this.zero+e)},i.prototype.lastIndexOfSignature=function(e){return this.data.lastIndexOf(e)-this.zero},i.prototype.readAndCheckSignature=function(e){return e===this.readData(4)},i.prototype.readData=function(e){this.checkOffset(e);var t=this.data.slice(this.zero+this.index,this.zero+this.index+e);return this.index+=e,t},t.exports=i},{"../utils":32,"./DataReader":18}],21:[function(e,t,r){"use strict";var n=e("./ArrayReader");function i(e){n.call(this,e)}e("../utils").inherits(i,n),i.prototype.readData=function(e){if(this.checkOffset(e),0===e)return new Uint8Array(0);var t=this.data.subarray(this.zero+this.index,this.zero+this.index+e);return this.index+=e,t},t.exports=i},{"../utils":32,"./ArrayReader":17}],22:[function(e,t,r){"use strict";var n=e("../utils"),i=e("../support"),s=e("./ArrayReader"),a=e("./StringReader"),o=e("./NodeBufferReader"),h=e("./Uint8ArrayReader");t.exports=function(e){var t=n.getTypeOf(e);return n.checkSupport(t),"string"!==t||i.uint8array?"nodebuffer"===t?new o(e):i.uint8array?new h(n.transformTo("uint8array",e)):new s(n.transformTo("array",e)):new a(e)}},{"../support":30,"../utils":32,"./ArrayReader":17,"./NodeBufferReader":19,"./StringReader":20,"./Uint8ArrayReader":21}],23:[function(e,t,r){"use strict";r.LOCAL_FILE_HEADER="PK",r.CENTRAL_FILE_HEADER="PK",r.CENTRAL_DIRECTORY_END="PK",r.ZIP64_CENTRAL_DIRECTORY_LOCATOR="PK",r.ZIP64_CENTRAL_DIRECTORY_END="PK",r.DATA_DESCRIPTOR="PK\b"},{}],24:[function(e,t,r){"use strict";var n=e("./GenericWorker"),i=e("../utils");function s(e){n.call(this,"ConvertWorker to "+e),this.destType=e}i.inherits(s,n),s.prototype.processChunk=function(e){this.push({data:i.transformTo(this.destType,e.data),meta:e.meta})},t.exports=s},{"../utils":32,"./GenericWorker":28}],25:[function(e,t,r){"use strict";var n=e("./GenericWorker"),i=e("../crc32");function s(){n.call(this,"Crc32Probe"),this.withStreamInfo("crc32",0)}e("../utils").inherits(s,n),s.prototype.processChunk=function(e){this.streamInfo.crc32=i(e.data,this.streamInfo.crc32||0),this.push(e)},t.exports=s},{"../crc32":4,"../utils":32,"./GenericWorker":28}],26:[function(e,t,r){"use strict";var n=e("../utils"),i=e("./GenericWorker");function s(e){i.call(this,"DataLengthProbe for "+e),this.propName=e,this.withStreamInfo(e,0)}n.inherits(s,i),s.prototype.processChunk=function(e){if(e){var t=this.streamInfo[this.propName]||0;this.streamInfo[this.propName]=t+e.data.length}i.prototype.processChunk.call(this,e)},t.exports=s},{"../utils":32,"./GenericWorker":28}],27:[function(e,t,r){"use strict";var n=e("../utils"),i=e("./GenericWorker");function s(e){i.call(this,"DataWorker");var t=this;this.dataIsReady=!1,this.index=0,this.max=0,this.data=null,this.type="",this._tickScheduled=!1,e.then(function(e){t.dataIsReady=!0,t.data=e,t.max=e&&e.length||0,t.type=n.getTypeOf(e),t.isPaused||t._tickAndRepeat()},function(e){t.error(e)})}n.inherits(s,i),s.prototype.cleanUp=function(){i.prototype.cleanUp.call(this),this.data=null},s.prototype.resume=function(){return!!i.prototype.resume.call(this)&&(!this._tickScheduled&&this.dataIsReady&&(this._tickScheduled=!0,n.delay(this._tickAndRepeat,[],this)),!0)},s.prototype._tickAndRepeat=function(){this._tickScheduled=!1,this.isPaused||this.isFinished||(this._tick(),this.isFinished||(n.delay(this._tickAndRepeat,[],this),this._tickScheduled=!0))},s.prototype._tick=function(){if(this.isPaused||this.isFinished)return!1;var e=null,t=Math.min(this.max,this.index+16384);if(this.index>=this.max)return this.end();switch(this.type){case"string":e=this.data.substring(this.index,t);break;case"uint8array":e=this.data.subarray(this.index,t);break;case"array":case"nodebuffer":e=this.data.slice(this.index,t)}return this.index=t,this.push({data:e,meta:{percent:this.max?this.index/this.max*100:0}})},t.exports=s},{"../utils":32,"./GenericWorker":28}],28:[function(e,t,r){"use strict";function n(e){this.name=e||"default",this.streamInfo={},this.generatedError=null,this.extraStreamInfo={},this.isPaused=!0,this.isFinished=!1,this.isLocked=!1,this._listeners={data:[],end:[],error:[]},this.previous=null}n.prototype={push:function(e){this.emit("data",e)},end:function(){if(this.isFinished)return!1;this.flush();try{this.emit("end"),this.cleanUp(),this.isFinished=!0}catch(e){this.emit("error",e)}return!0},error:function(e){return!this.isFinished&&(this.isPaused?this.generatedError=e:(this.isFinished=!0,this.emit("error",e),this.previous&&this.previous.error(e),this.cleanUp()),!0)},on:function(e,t){return this._listeners[e].push(t),this},cleanUp:function(){this.streamInfo=this.generatedError=this.extraStreamInfo=null,this._listeners=[]},emit:function(e,t){if(this._listeners[e])for(var r=0;r<this._listeners[e].length;r++)this._listeners[e][r].call(this,t)},pipe:function(e){return e.registerPrevious(this)},registerPrevious:function(e){if(this.isLocked)throw new Error("The stream '"+this+"' has already been used.");this.streamInfo=e.streamInfo,this.mergeStreamInfo(),this.previous=e;var t=this;return e.on("data",function(e){t.processChunk(e)}),e.on("end",function(){t.end()}),e.on("error",function(e){t.error(e)}),this},pause:function(){return!this.isPaused&&!this.isFinished&&(this.isPaused=!0,this.previous&&this.previous.pause(),!0)},resume:function(){if(!this.isPaused||this.isFinished)return!1;var e=this.isPaused=!1;return this.generatedError&&(this.error(this.generatedError),e=!0),this.previous&&this.previous.resume(),!e},flush:function(){},processChunk:function(e){this.push(e)},withStreamInfo:function(e,t){return this.extraStreamInfo[e]=t,this.mergeStreamInfo(),this},mergeStreamInfo:function(){for(var e in this.extraStreamInfo)Object.prototype.hasOwnProperty.call(this.extraStreamInfo,e)&&(this.streamInfo[e]=this.extraStreamInfo[e])},lock:function(){if(this.isLocked)throw new Error("The stream '"+this+"' has already been used.");this.isLocked=!0,this.previous&&this.previous.lock()},toString:function(){var e="Worker "+this.name;return this.previous?this.previous+" -> "+e:e}},t.exports=n},{}],29:[function(e,t,r){"use strict";var n=e("../utils"),i=e("./ConvertWorker"),s=e("./GenericWorker"),a=e("../base64"),o=e("../support"),h=e("../external"),u=null;if(o.nodestream)try{u=e("../nodejs/NodejsStreamOutputAdapter")}catch(e){}function l(e,t){return new h.Promise(function(r,i){var s=[],o=e._internalType,h=e._outputType,u=e._mimeType;e.on("data",function(e,r){s.push(e),t&&t(r)}).on("error",function(e){s=[],i(e)}).on("end",function(){try{var e=function(e,t,r){switch(e){case"blob":return n.newBlob(n.transformTo("arraybuffer",t),r);case"base64":return a.encode(t);default:return n.transformTo(e,t)}}(h,function(e,t){var r,n=0,i=null,s=0;for(r=0;r<t.length;r++)s+=t[r].length;switch(e){case"string":return t.join("");case"array":return Array.prototype.concat.apply([],t);case"uint8array":for(i=new Uint8Array(s),r=0;r<t.length;r++)i.set(t[r],n),n+=t[r].length;return i;case"nodebuffer":return Buffer.concat(t);default:throw new Error("concat : unsupported type '"+e+"'")}}(o,s),u);r(e)}catch(e){i(e)}s=[]}).resume()})}function f(e,t,r){var a=t;switch(t){case"blob":case"arraybuffer":a="uint8array";break;case"base64":a="string"}try{this._internalType=a,this._outputType=t,this._mimeType=r,n.checkSupport(a),this._worker=e.pipe(new i(a)),e.lock()}catch(e){this._worker=new s("error"),this._worker.error(e)}}f.prototype={accumulate:function(e){return l(this,e)},on:function(e,t){var r=this;return"data"===e?this._worker.on(e,function(e){t.call(r,e.data,e.meta)}):this._worker.on(e,function(){n.delay(t,arguments,r)}),this},resume:function(){return n.delay(this._worker.resume,[],this._worker),this},pause:function(){return this._worker.pause(),this},toNodejsStream:function(e){if(n.checkSupport("nodestream"),"nodebuffer"!==this._outputType)throw new Error(this._outputType+" is not supported by this method");return new u(this,{objectMode:"nodebuffer"!==this._outputType},e)}},t.exports=f},{"../base64":1,"../external":6,"../nodejs/NodejsStreamOutputAdapter":13,"../support":30,"../utils":32,"./ConvertWorker":24,"./GenericWorker":28}],30:[function(e,t,r){"use strict";if(r.base64=!0,r.array=!0,r.string=!0,r.arraybuffer="undefined"!=typeof ArrayBuffer&&"undefined"!=typeof Uint8Array,r.nodebuffer="undefined"!=typeof Buffer,r.uint8array="undefined"!=typeof Uint8Array,"undefined"==typeof ArrayBuffer)r.blob=!1;else{var n=new ArrayBuffer(0);try{r.blob=0===new Blob([n],{type:"application/zip"}).size}catch(e){try{var i=new(self.BlobBuilder||self.WebKitBlobBuilder||self.MozBlobBuilder||self.MSBlobBuilder);i.append(n),r.blob=0===i.getBlob("application/zip").size}catch(e){r.blob=!1}}}try{r.nodestream=!!e("readable-stream").Readable}catch(e){r.nodestream=!1}},{"readable-stream":16}],31:[function(e,t,r){"use strict";for(var n=e("./utils"),i=e("./support"),s=e("./nodejsUtils"),a=e("./stream/GenericWorker"),o=new Array(256),h=0;h<256;h++)o[h]=252<=h?6:248<=h?5:240<=h?4:224<=h?3:192<=h?2:1;function u(){a.call(this,"utf-8 decode"),this.leftOver=null}function l(){a.call(this,"utf-8 encode")}o[254]=o[254]=1,r.utf8encode=function(e){return i.nodebuffer?s.newBufferFrom(e,"utf-8"):function(e){var t,r,n,s,a,o=e.length,h=0;for(s=0;s<o;s++)55296==(64512&(r=e.charCodeAt(s)))&&s+1<o&&56320==(64512&(n=e.charCodeAt(s+1)))&&(r=65536+(r-55296<<10)+(n-56320),s++),h+=r<128?1:r<2048?2:r<65536?3:4;for(t=i.uint8array?new Uint8Array(h):new Array(h),s=a=0;a<h;s++)55296==(64512&(r=e.charCodeAt(s)))&&s+1<o&&56320==(64512&(n=e.charCodeAt(s+1)))&&(r=65536+(r-55296<<10)+(n-56320),s++),r<128?t[a++]=r:(r<2048?t[a++]=192|r>>>6:(r<65536?t[a++]=224|r>>>12:(t[a++]=240|r>>>18,t[a++]=128|r>>>12&63),t[a++]=128|r>>>6&63),t[a++]=128|63&r);return t}(e)},r.utf8decode=function(e){return i.nodebuffer?n.transformTo("nodebuffer",e).toString("utf-8"):function(e){var t,r,i,s,a=e.length,h=new Array(2*a);for(t=r=0;t<a;)if((i=e[t++])<128)h[r++]=i;else if(4<(s=o[i]))h[r++]=65533,t+=s-1;else{for(i&=2===s?31:3===s?15:7;1<s&&t<a;)i=i<<6|63&e[t++],s--;1<s?h[r++]=65533:i<65536?h[r++]=i:(i-=65536,h[r++]=55296|i>>10&1023,h[r++]=56320|1023&i)}return h.length!==r&&(h.subarray?h=h.subarray(0,r):h.length=r),n.applyFromCharCode(h)}(e=n.transformTo(i.uint8array?"uint8array":"array",e))},n.inherits(u,a),u.prototype.processChunk=function(e){var t=n.transformTo(i.uint8array?"uint8array":"array",e.data);if(this.leftOver&&this.leftOver.length){if(i.uint8array){var s=t;(t=new Uint8Array(s.length+this.leftOver.length)).set(this.leftOver,0),t.set(s,this.leftOver.length)}else t=this.leftOver.concat(t);this.leftOver=null}var a=function(e,t){var r;for((t=t||e.length)>e.length&&(t=e.length),r=t-1;0<=r&&128==(192&e[r]);)r--;return r<0||0===r?t:r+o[e[r]]>t?r:t}(t),h=t;a!==t.length&&(i.uint8array?(h=t.subarray(0,a),this.leftOver=t.subarray(a,t.length)):(h=t.slice(0,a),this.leftOver=t.slice(a,t.length))),this.push({data:r.utf8decode(h),meta:e.meta})},u.prototype.flush=function(){this.leftOver&&this.leftOver.length&&(this.push({data:r.utf8decode(this.leftOver),meta:{}}),this.leftOver=null)},r.Utf8DecodeWorker=u,n.inherits(l,a),l.prototype.processChunk=function(e){this.push({data:r.utf8encode(e.data),meta:e.meta})},r.Utf8EncodeWorker=l},{"./nodejsUtils":14,"./stream/GenericWorker":28,"./support":30,"./utils":32}],32:[function(e,t,r){"use strict";var n=e("./support"),i=e("./base64"),s=e("./nodejsUtils"),a=e("./external");function o(e){return e}function h(e,t){for(var r=0;r<e.length;++r)t[r]=255&e.charCodeAt(r);return t}e("setimmediate"),r.newBlob=function(t,n){r.checkSupport("blob");try{return new Blob([t],{type:n})}catch(e){try{var i=new(self.BlobBuilder||self.WebKitBlobBuilder||self.MozBlobBuilder||self.MSBlobBuilder);return i.append(t),i.getBlob(n)}catch(e){throw new Error("Bug : can't construct the Blob.")}}};var u={stringifyByChunk:function(e,t,r){var n=[],i=0,s=e.length;if(s<=r)return String.fromCharCode.apply(null,e);for(;i<s;)"array"===t||"nodebuffer"===t?n.push(String.fromCharCode.apply(null,e.slice(i,Math.min(i+r,s)))):n.push(String.fromCharCode.apply(null,e.subarray(i,Math.min(i+r,s)))),i+=r;return n.join("")},stringifyByChar:function(e){for(var t="",r=0;r<e.length;r++)t+=String.fromCharCode(e[r]);return t},applyCanBeUsed:{uint8array:function(){try{return n.uint8array&&1===String.fromCharCode.apply(null,new Uint8Array(1)).length}catch(e){return!1}}(),nodebuffer:function(){try{return n.nodebuffer&&1===String.fromCharCode.apply(null,s.allocBuffer(1)).length}catch(e){return!1}}()}};function l(e){var t=65536,n=r.getTypeOf(e),i=!0;if("uint8array"===n?i=u.applyCanBeUsed.uint8array:"nodebuffer"===n&&(i=u.applyCanBeUsed.nodebuffer),i)for(;1<t;)try{return u.stringifyByChunk(e,n,t)}catch(e){t=Math.floor(t/2)}return u.stringifyByChar(e)}function f(e,t){for(var r=0;r<e.length;r++)t[r]=e[r];return t}r.applyFromCharCode=l;var c={};c.string={string:o,array:function(e){return h(e,new Array(e.length))},arraybuffer:function(e){return c.string.uint8array(e).buffer},uint8array:function(e){return h(e,new Uint8Array(e.length))},nodebuffer:function(e){return h(e,s.allocBuffer(e.length))}},c.array={string:l,array:o,arraybuffer:function(e){return new Uint8Array(e).buffer},uint8array:function(e){return new Uint8Array(e)},nodebuffer:function(e){return s.newBufferFrom(e)}},c.arraybuffer={string:function(e){return l(new Uint8Array(e))},array:function(e){return f(new Uint8Array(e),new Array(e.byteLength))},arraybuffer:o,uint8array:function(e){return new Uint8Array(e)},nodebuffer:function(e){return s.newBufferFrom(new Uint8Array(e))}},c.uint8array={string:l,array:function(e){return f(e,new Array(e.length))},arraybuffer:function(e){return e.buffer},uint8array:o,nodebuffer:function(e){return s.newBufferFrom(e)}},c.nodebuffer={string:l,array:function(e){return f(e,new Array(e.length))},arraybuffer:function(e){return c.nodebuffer.uint8array(e).buffer},uint8array:function(e){return f(e,new Uint8Array(e.length))},nodebuffer:o},r.transformTo=function(e,t){if(t=t||"",!e)return t;r.checkSupport(e);var n=r.getTypeOf(t);return c[n][e](t)},r.resolve=function(e){for(var t=e.split("/"),r=[],n=0;n<t.length;n++){var i=t[n];"."===i||""===i&&0!==n&&n!==t.length-1||(".."===i?r.pop():r.push(i))}return r.join("/")},r.getTypeOf=function(e){return"string"==typeof e?"string":"[object Array]"===Object.prototype.toString.call(e)?"array":n.nodebuffer&&s.isBuffer(e)?"nodebuffer":n.uint8array&&e instanceof Uint8Array?"uint8array":n.arraybuffer&&e instanceof ArrayBuffer?"arraybuffer":void 0},r.checkSupport=function(e){if(!n[e.toLowerCase()])throw new Error(e+" is not supported by this platform")},r.MAX_VALUE_16BITS=65535,r.MAX_VALUE_32BITS=-1,r.pretty=function(e){var t,r,n="";for(r=0;r<(e||"").length;r++)n+="\\x"+((t=e.charCodeAt(r))<16?"0":"")+t.toString(16).toUpperCase();return n},r.delay=function(e,t,r){setImmediate(function(){e.apply(r||null,t||[])})},r.inherits=function(e,t){function r(){}r.prototype=t.prototype,e.prototype=new r},r.extend=function(){var e,t,r={};for(e=0;e<arguments.length;e++)for(t in arguments[e])Object.prototype.hasOwnProperty.call(arguments[e],t)&&void 0===r[t]&&(r[t]=arguments[e][t]);return r},r.prepareContent=function(e,t,s,o,u){return a.Promise.resolve(t).then(function(e){return n.blob&&(e instanceof Blob||-1!==["[object File]","[object Blob]"].indexOf(Object.prototype.toString.call(e)))&&"undefined"!=typeof FileReader?new a.Promise(function(t,r){var n=new FileReader;n.onload=function(e){t(e.target.result)},n.onerror=function(e){r(e.target.error)},n.readAsArrayBuffer(e)}):e}).then(function(t){var l=r.getTypeOf(t);return l?("arraybuffer"===l?t=r.transformTo("uint8array",t):"string"===l&&(u?t=i.decode(t):s&&!0!==o&&(t=function(e){return h(e,n.uint8array?new Uint8Array(e.length):new Array(e.length))}(t))),t):a.Promise.reject(new Error("Can't read the data of '"+e+"'. Is it in a supported JavaScript type (String, Blob, ArrayBuffer, etc) ?"))})}},{"./base64":1,"./external":6,"./nodejsUtils":14,"./support":30,setimmediate:54}],33:[function(e,t,r){"use strict";var n=e("./reader/readerFor"),i=e("./utils"),s=e("./signature"),a=e("./zipEntry"),o=e("./support");function h(e){this.files=[],this.loadOptions=e}h.prototype={checkSignature:function(e){if(!this.reader.readAndCheckSignature(e)){this.reader.index-=4;var t=this.reader.readString(4);throw new Error("Corrupted zip or bug: unexpected signature ("+i.pretty(t)+", expected "+i.pretty(e)+")")}},isSignature:function(e,t){var r=this.reader.index;this.reader.setIndex(e);var n=this.reader.readString(4)===t;return this.reader.setIndex(r),n},readBlockEndOfCentral:function(){this.diskNumber=this.reader.readInt(2),this.diskWithCentralDirStart=this.reader.readInt(2),this.centralDirRecordsOnThisDisk=this.reader.readInt(2),this.centralDirRecords=this.reader.readInt(2),this.centralDirSize=this.reader.readInt(4),this.centralDirOffset=this.reader.readInt(4),this.zipCommentLength=this.reader.readInt(2);var e=this.reader.readData(this.zipCommentLength),t=o.uint8array?"uint8array":"array",r=i.transformTo(t,e);this.zipComment=this.loadOptions.decodeFileName(r)},readBlockZip64EndOfCentral:function(){this.zip64EndOfCentralSize=this.reader.readInt(8),this.reader.skip(4),this.diskNumber=this.reader.readInt(4),this.diskWithCentralDirStart=this.reader.readInt(4),this.centralDirRecordsOnThisDisk=this.reader.readInt(8),this.centralDirRecords=this.reader.readInt(8),this.centralDirSize=this.reader.readInt(8),this.centralDirOffset=this.reader.readInt(8),this.zip64ExtensibleData={};for(var e,t,r,n=this.zip64EndOfCentralSize-44;0<n;)e=this.reader.readInt(2),t=this.reader.readInt(4),r=this.reader.readData(t),this.zip64ExtensibleData[e]={id:e,length:t,value:r}},readBlockZip64EndOfCentralLocator:function(){if(this.diskWithZip64CentralDirStart=this.reader.readInt(4),this.relativeOffsetEndOfZip64CentralDir=this.reader.readInt(8),this.disksCount=this.reader.readInt(4),1<this.disksCount)throw new Error("Multi-volumes zip are not supported")},readLocalFiles:function(){var e,t;for(e=0;e<this.files.length;e++)t=this.files[e],this.reader.setIndex(t.localHeaderOffset),this.checkSignature(s.LOCAL_FILE_HEADER),t.readLocalPart(this.reader),t.handleUTF8(),t.processAttributes()},readCentralDir:function(){var e;for(this.reader.setIndex(this.centralDirOffset);this.reader.readAndCheckSignature(s.CENTRAL_FILE_HEADER);)(e=new a({zip64:this.zip64},this.loadOptions)).readCentralPart(this.reader),this.files.push(e);if(this.centralDirRecords!==this.files.length&&0!==this.centralDirRecords&&0===this.files.length)throw new Error("Corrupted zip or bug: expected "+this.centralDirRecords+" records in central dir, got "+this.files.length)},readEndOfCentral:function(){var e=this.reader.lastIndexOfSignature(s.CENTRAL_DIRECTORY_END);if(e<0)throw this.isSignature(0,s.LOCAL_FILE_HEADER)?new Error("Corrupted zip: can't find end of central directory"):new Error("Can't find end of central directory : is this a zip file ? If it is, see https://stuk.github.io/jszip/documentation/howto/read_zip.html");this.reader.setIndex(e);var t=e;if(this.checkSignature(s.CENTRAL_DIRECTORY_END),this.readBlockEndOfCentral(),this.diskNumber===i.MAX_VALUE_16BITS||this.diskWithCentralDirStart===i.MAX_VALUE_16BITS||this.centralDirRecordsOnThisDisk===i.MAX_VALUE_16BITS||this.centralDirRecords===i.MAX_VALUE_16BITS||this.centralDirSize===i.MAX_VALUE_32BITS||this.centralDirOffset===i.MAX_VALUE_32BITS){if(this.zip64=!0,(e=this.reader.lastIndexOfSignature(s.ZIP64_CENTRAL_DIRECTORY_LOCATOR))<0)throw new Error("Corrupted zip: can't find the ZIP64 end of central directory locator");if(this.reader.setIndex(e),this.checkSignature(s.ZIP64_CENTRAL_DIRECTORY_LOCATOR),this.readBlockZip64EndOfCentralLocator(),!this.isSignature(this.relativeOffsetEndOfZip64CentralDir,s.ZIP64_CENTRAL_DIRECTORY_END)&&(this.relativeOffsetEndOfZip64CentralDir=this.reader.lastIndexOfSignature(s.ZIP64_CENTRAL_DIRECTORY_END),this.relativeOffsetEndOfZip64CentralDir<0))throw new Error("Corrupted zip: can't find the ZIP64 end of central directory");this.reader.setIndex(this.relativeOffsetEndOfZip64CentralDir),this.checkSignature(s.ZIP64_CENTRAL_DIRECTORY_END),this.readBlockZip64EndOfCentral()}var r=this.centralDirOffset+this.centralDirSize;this.zip64&&(r+=20,r+=12+this.zip64EndOfCentralSize);var n=t-r;if(0<n)this.isSignature(t,s.CENTRAL_FILE_HEADER)||(this.reader.zero=n);else if(n<0)throw new Error("Corrupted zip: missing "+Math.abs(n)+" bytes.")},prepareReader:function(e){this.reader=n(e)},load:function(e){this.prepareReader(e),this.readEndOfCentral(),this.readCentralDir(),this.readLocalFiles()}},t.exports=h},{"./reader/readerFor":22,"./signature":23,"./support":30,"./utils":32,"./zipEntry":34}],34:[function(e,t,r){"use strict";var n=e("./reader/readerFor"),i=e("./utils"),s=e("./compressedObject"),a=e("./crc32"),o=e("./utf8"),h=e("./compressions"),u=e("./support");function l(e,t){this.options=e,this.loadOptions=t}l.prototype={isEncrypted:function(){return 1==(1&this.bitFlag)},useUTF8:function(){return 2048==(2048&this.bitFlag)},readLocalPart:function(e){var t,r;if(e.skip(22),this.fileNameLength=e.readInt(2),r=e.readInt(2),this.fileName=e.readData(this.fileNameLength),e.skip(r),-1===this.compressedSize||-1===this.uncompressedSize)throw new Error("Bug or corrupted zip : didn't get enough information from the central directory (compressedSize === -1 || uncompressedSize === -1)");if(null===(t=function(e){for(var t in h)if(Object.prototype.hasOwnProperty.call(h,t)&&h[t].magic===e)return h[t];return null}(this.compressionMethod)))throw new Error("Corrupted zip : compression "+i.pretty(this.compressionMethod)+" unknown (inner file : "+i.transformTo("string",this.fileName)+")");this.decompressed=new s(this.compressedSize,this.uncompressedSize,this.crc32,t,e.readData(this.compressedSize))},readCentralPart:function(e){this.versionMadeBy=e.readInt(2),e.skip(2),this.bitFlag=e.readInt(2),this.compressionMethod=e.readString(2),this.date=e.readDate(),this.crc32=e.readInt(4),this.compressedSize=e.readInt(4),this.uncompressedSize=e.readInt(4);var t=e.readInt(2);if(this.extraFieldsLength=e.readInt(2),this.fileCommentLength=e.readInt(2),this.diskNumberStart=e.readInt(2),this.internalFileAttributes=e.readInt(2),this.externalFileAttributes=e.readInt(4),this.localHeaderOffset=e.readInt(4),this.isEncrypted())throw new Error("Encrypted zip are not supported");e.skip(t),this.readExtraFields(e),this.parseZIP64ExtraField(e),this.fileComment=e.readData(this.fileCommentLength)},processAttributes:function(){this.unixPermissions=null,this.dosPermissions=null;var e=this.versionMadeBy>>8;this.dir=!!(16&this.externalFileAttributes),0==e&&(this.dosPermissions=63&this.externalFileAttributes),3==e&&(this.unixPermissions=this.externalFileAttributes>>16&65535),this.dir||"/"!==this.fileNameStr.slice(-1)||(this.dir=!0)},parseZIP64ExtraField:function(){if(this.extraFields[1]){var e=n(this.extraFields[1].value);this.uncompressedSize===i.MAX_VALUE_32BITS&&(this.uncompressedSize=e.readInt(8)),this.compressedSize===i.MAX_VALUE_32BITS&&(this.compressedSize=e.readInt(8)),this.localHeaderOffset===i.MAX_VALUE_32BITS&&(this.localHeaderOffset=e.readInt(8)),this.diskNumberStart===i.MAX_VALUE_32BITS&&(this.diskNumberStart=e.readInt(4))}},readExtraFields:function(e){var t,r,n,i=e.index+this.extraFieldsLength;for(this.extraFields||(this.extraFields={});e.index+4<i;)t=e.readInt(2),r=e.readInt(2),n=e.readData(r),this.extraFields[t]={id:t,length:r,value:n};e.setIndex(i)},handleUTF8:function(){var e=u.uint8array?"uint8array":"array";if(this.useUTF8())this.fileNameStr=o.utf8decode(this.fileName),this.fileCommentStr=o.utf8decode(this.fileComment);else{var t=this.findExtraFieldUnicodePath();if(null!==t)this.fileNameStr=t;else{var r=i.transformTo(e,this.fileName);this.fileNameStr=this.loadOptions.decodeFileName(r)}var n=this.findExtraFieldUnicodeComment();if(null!==n)this.fileCommentStr=n;else{var s=i.transformTo(e,this.fileComment);this.fileCommentStr=this.loadOptions.decodeFileName(s)}}},findExtraFieldUnicodePath:function(){var e=this.extraFields[28789];if(e){var t=n(e.value);return 1!==t.readInt(1)||a(this.fileName)!==t.readInt(4)?null:o.utf8decode(t.readData(e.length-5))}return null},findExtraFieldUnicodeComment:function(){var e=this.extraFields[25461];if(e){var t=n(e.value);return 1!==t.readInt(1)||a(this.fileComment)!==t.readInt(4)?null:o.utf8decode(t.readData(e.length-5))}return null}},t.exports=l},{"./compressedObject":2,"./compressions":3,"./crc32":4,"./reader/readerFor":22,"./support":30,"./utf8":31,"./utils":32}],35:[function(e,t,r){"use strict";function n(e,t,r){this.name=e,this.dir=r.dir,this.date=r.date,this.comment=r.comment,this.unixPermissions=r.unixPermissions,this.dosPermissions=r.dosPermissions,this._data=t,this._dataBinary=r.binary,this.options={compression:r.compression,compressionOptions:r.compressionOptions}}var i=e("./stream/StreamHelper"),s=e("./stream/DataWorker"),a=e("./utf8"),o=e("./compressedObject"),h=e("./stream/GenericWorker");n.prototype={internalStream:function(e){var t=null,r="string";try{if(!e)throw new Error("No output type specified.");var n="string"===(r=e.toLowerCase())||"text"===r;"binarystring"!==r&&"text"!==r||(r="string"),t=this._decompressWorker();var s=!this._dataBinary;s&&!n&&(t=t.pipe(new a.Utf8EncodeWorker)),!s&&n&&(t=t.pipe(new a.Utf8DecodeWorker))}catch(e){(t=new h("error")).error(e)}return new i(t,r,"")},async:function(e,t){return this.internalStream(e).accumulate(t)},nodeStream:function(e,t){return this.internalStream(e||"nodebuffer").toNodejsStream(t)},_compressWorker:function(e,t){if(this._data instanceof o&&this._data.compression.magic===e.magic)return this._data.getCompressedWorker();var r=this._decompressWorker();return this._dataBinary||(r=r.pipe(new a.Utf8EncodeWorker)),o.createWorkerFrom(r,e,t)},_decompressWorker:function(){return this._data instanceof o?this._data.getContentWorker():this._data instanceof h?this._data:new s(this._data)}};for(var u=["asText","asBinary","asNodeBuffer","asUint8Array","asArrayBuffer"],l=function(){throw new Error("This method has been removed in JSZip 3.0, please check the upgrade guide.")},f=0;f<u.length;f++)n.prototype[u[f]]=l;t.exports=n},{"./compressedObject":2,"./stream/DataWorker":27,"./stream/GenericWorker":28,"./stream/StreamHelper":29,"./utf8":31}],36:[function(e,t,n){(function(e){"use strict";var r,n,i=e.MutationObserver||e.WebKitMutationObserver;if(i){var s=0,a=new i(l),o=e.document.createTextNode("");a.observe(o,{characterData:!0}),r=function(){o.data=s=++s%2}}else if(e.setImmediate||void 0===e.MessageChannel)r="document"in e&&"onreadystatechange"in e.document.createElement("script")?function(){var t=e.document.createElement("script");t.onreadystatechange=function(){l(),t.onreadystatechange=null,t.parentNode.removeChild(t),t=null},e.document.documentElement.appendChild(t)}:function(){setTimeout(l,0)};else{var h=new e.MessageChannel;h.port1.onmessage=l,r=function(){h.port2.postMessage(0)}}var u=[];function l(){var e,t;n=!0;for(var r=u.length;r;){for(t=u,u=[],e=-1;++e<r;)t[e]();r=u.length}n=!1}t.exports=function(e){1!==u.push(e)||n||r()}}).call(this,"undefined"!=typeof r.g?r.g:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{})},{}],37:[function(e,t,r){"use strict";var n=e("immediate");function i(){}var s={},a=["REJECTED"],o=["FULFILLED"],h=["PENDING"];function u(e){if("function"!=typeof e)throw new TypeError("resolver must be a function");this.state=h,this.queue=[],this.outcome=void 0,e!==i&&d(this,e)}function l(e,t,r){this.promise=e,"function"==typeof t&&(this.onFulfilled=t,this.callFulfilled=this.otherCallFulfilled),"function"==typeof r&&(this.onRejected=r,this.callRejected=this.otherCallRejected)}function f(e,t,r){n(function(){var n;try{n=t(r)}catch(n){return s.reject(e,n)}n===e?s.reject(e,new TypeError("Cannot resolve promise with itself")):s.resolve(e,n)})}function c(e){var t=e&&e.then;if(e&&("object"==typeof e||"function"==typeof e)&&"function"==typeof t)return function(){t.apply(e,arguments)}}function d(e,t){var r=!1;function n(t){r||(r=!0,s.reject(e,t))}function i(t){r||(r=!0,s.resolve(e,t))}var a=p(function(){t(i,n)});"error"===a.status&&n(a.value)}function p(e,t){var r={};try{r.value=e(t),r.status="success"}catch(e){r.status="error",r.value=e}return r}(t.exports=u).prototype.finally=function(e){if("function"!=typeof e)return this;var t=this.constructor;return this.then(function(r){return t.resolve(e()).then(function(){return r})},function(r){return t.resolve(e()).then(function(){throw r})})},u.prototype.catch=function(e){return this.then(null,e)},u.prototype.then=function(e,t){if("function"!=typeof e&&this.state===o||"function"!=typeof t&&this.state===a)return this;var r=new this.constructor(i);return this.state!==h?f(r,this.state===o?e:t,this.outcome):this.queue.push(new l(r,e,t)),r},l.prototype.callFulfilled=function(e){s.resolve(this.promise,e)},l.prototype.otherCallFulfilled=function(e){f(this.promise,this.onFulfilled,e)},l.prototype.callRejected=function(e){s.reject(this.promise,e)},l.prototype.otherCallRejected=function(e){f(this.promise,this.onRejected,e)},s.resolve=function(e,t){var r=p(c,t);if("error"===r.status)return s.reject(e,r.value);var n=r.value;if(n)d(e,n);else{e.state=o,e.outcome=t;for(var i=-1,a=e.queue.length;++i<a;)e.queue[i].callFulfilled(t)}return e},s.reject=function(e,t){e.state=a,e.outcome=t;for(var r=-1,n=e.queue.length;++r<n;)e.queue[r].callRejected(t);return e},u.resolve=function(e){return e instanceof this?e:s.resolve(new this(i),e)},u.reject=function(e){var t=new this(i);return s.reject(t,e)},u.all=function(e){var t=this;if("[object Array]"!==Object.prototype.toString.call(e))return this.reject(new TypeError("must be an array"));var r=e.length,n=!1;if(!r)return this.resolve([]);for(var a=new Array(r),o=0,h=-1,u=new this(i);++h<r;)l(e[h],h);return u;function l(e,i){t.resolve(e).then(function(e){a[i]=e,++o!==r||n||(n=!0,s.resolve(u,a))},function(e){n||(n=!0,s.reject(u,e))})}},u.race=function(e){var t=this;if("[object Array]"!==Object.prototype.toString.call(e))return this.reject(new TypeError("must be an array"));var r=e.length,n=!1;if(!r)return this.resolve([]);for(var a,o=-1,h=new this(i);++o<r;)a=e[o],t.resolve(a).then(function(e){n||(n=!0,s.resolve(h,e))},function(e){n||(n=!0,s.reject(h,e))});return h}},{immediate:36}],38:[function(e,t,r){"use strict";var n={};(0,e("./lib/utils/common").assign)(n,e("./lib/deflate"),e("./lib/inflate"),e("./lib/zlib/constants")),t.exports=n},{"./lib/deflate":39,"./lib/inflate":40,"./lib/utils/common":41,"./lib/zlib/constants":44}],39:[function(e,t,r){"use strict";var n=e("./zlib/deflate"),i=e("./utils/common"),s=e("./utils/strings"),a=e("./zlib/messages"),o=e("./zlib/zstream"),h=Object.prototype.toString,u=0,l=-1,f=0,c=8;function d(e){if(!(this instanceof d))return new d(e);this.options=i.assign({level:l,method:c,chunkSize:16384,windowBits:15,memLevel:8,strategy:f,to:""},e||{});var t=this.options;t.raw&&0<t.windowBits?t.windowBits=-t.windowBits:t.gzip&&0<t.windowBits&&t.windowBits<16&&(t.windowBits+=16),this.err=0,this.msg="",this.ended=!1,this.chunks=[],this.strm=new o,this.strm.avail_out=0;var r=n.deflateInit2(this.strm,t.level,t.method,t.windowBits,t.memLevel,t.strategy);if(r!==u)throw new Error(a[r]);if(t.header&&n.deflateSetHeader(this.strm,t.header),t.dictionary){var p;if(p="string"==typeof t.dictionary?s.string2buf(t.dictionary):"[object ArrayBuffer]"===h.call(t.dictionary)?new Uint8Array(t.dictionary):t.dictionary,(r=n.deflateSetDictionary(this.strm,p))!==u)throw new Error(a[r]);this._dict_set=!0}}function p(e,t){var r=new d(t);if(r.push(e,!0),r.err)throw r.msg||a[r.err];return r.result}d.prototype.push=function(e,t){var r,a,o=this.strm,l=this.options.chunkSize;if(this.ended)return!1;a=t===~~t?t:!0===t?4:0,"string"==typeof e?o.input=s.string2buf(e):"[object ArrayBuffer]"===h.call(e)?o.input=new Uint8Array(e):o.input=e,o.next_in=0,o.avail_in=o.input.length;do{if(0===o.avail_out&&(o.output=new i.Buf8(l),o.next_out=0,o.avail_out=l),1!==(r=n.deflate(o,a))&&r!==u)return this.onEnd(r),!(this.ended=!0);0!==o.avail_out&&(0!==o.avail_in||4!==a&&2!==a)||("string"===this.options.to?this.onData(s.buf2binstring(i.shrinkBuf(o.output,o.next_out))):this.onData(i.shrinkBuf(o.output,o.next_out)))}while((0<o.avail_in||0===o.avail_out)&&1!==r);return 4===a?(r=n.deflateEnd(this.strm),this.onEnd(r),this.ended=!0,r===u):2!==a||(this.onEnd(u),!(o.avail_out=0))},d.prototype.onData=function(e){this.chunks.push(e)},d.prototype.onEnd=function(e){e===u&&("string"===this.options.to?this.result=this.chunks.join(""):this.result=i.flattenChunks(this.chunks)),this.chunks=[],this.err=e,this.msg=this.strm.msg},r.Deflate=d,r.deflate=p,r.deflateRaw=function(e,t){return(t=t||{}).raw=!0,p(e,t)},r.gzip=function(e,t){return(t=t||{}).gzip=!0,p(e,t)}},{"./utils/common":41,"./utils/strings":42,"./zlib/deflate":46,"./zlib/messages":51,"./zlib/zstream":53}],40:[function(e,t,r){"use strict";var n=e("./zlib/inflate"),i=e("./utils/common"),s=e("./utils/strings"),a=e("./zlib/constants"),o=e("./zlib/messages"),h=e("./zlib/zstream"),u=e("./zlib/gzheader"),l=Object.prototype.toString;function f(e){if(!(this instanceof f))return new f(e);this.options=i.assign({chunkSize:16384,windowBits:0,to:""},e||{});var t=this.options;t.raw&&0<=t.windowBits&&t.windowBits<16&&(t.windowBits=-t.windowBits,0===t.windowBits&&(t.windowBits=-15)),!(0<=t.windowBits&&t.windowBits<16)||e&&e.windowBits||(t.windowBits+=32),15<t.windowBits&&t.windowBits<48&&0==(15&t.windowBits)&&(t.windowBits|=15),this.err=0,this.msg="",this.ended=!1,this.chunks=[],this.strm=new h,this.strm.avail_out=0;var r=n.inflateInit2(this.strm,t.windowBits);if(r!==a.Z_OK)throw new Error(o[r]);this.header=new u,n.inflateGetHeader(this.strm,this.header)}function c(e,t){var r=new f(t);if(r.push(e,!0),r.err)throw r.msg||o[r.err];return r.result}f.prototype.push=function(e,t){var r,o,h,u,f,c,d=this.strm,p=this.options.chunkSize,m=this.options.dictionary,_=!1;if(this.ended)return!1;o=t===~~t?t:!0===t?a.Z_FINISH:a.Z_NO_FLUSH,"string"==typeof e?d.input=s.binstring2buf(e):"[object ArrayBuffer]"===l.call(e)?d.input=new Uint8Array(e):d.input=e,d.next_in=0,d.avail_in=d.input.length;do{if(0===d.avail_out&&(d.output=new i.Buf8(p),d.next_out=0,d.avail_out=p),(r=n.inflate(d,a.Z_NO_FLUSH))===a.Z_NEED_DICT&&m&&(c="string"==typeof m?s.string2buf(m):"[object ArrayBuffer]"===l.call(m)?new Uint8Array(m):m,r=n.inflateSetDictionary(this.strm,c)),r===a.Z_BUF_ERROR&&!0===_&&(r=a.Z_OK,_=!1),r!==a.Z_STREAM_END&&r!==a.Z_OK)return this.onEnd(r),!(this.ended=!0);d.next_out&&(0!==d.avail_out&&r!==a.Z_STREAM_END&&(0!==d.avail_in||o!==a.Z_FINISH&&o!==a.Z_SYNC_FLUSH)||("string"===this.options.to?(h=s.utf8border(d.output,d.next_out),u=d.next_out-h,f=s.buf2string(d.output,h),d.next_out=u,d.avail_out=p-u,u&&i.arraySet(d.output,d.output,h,u,0),this.onData(f)):this.onData(i.shrinkBuf(d.output,d.next_out)))),0===d.avail_in&&0===d.avail_out&&(_=!0)}while((0<d.avail_in||0===d.avail_out)&&r!==a.Z_STREAM_END);return r===a.Z_STREAM_END&&(o=a.Z_FINISH),o===a.Z_FINISH?(r=n.inflateEnd(this.strm),this.onEnd(r),this.ended=!0,r===a.Z_OK):o!==a.Z_SYNC_FLUSH||(this.onEnd(a.Z_OK),!(d.avail_out=0))},f.prototype.onData=function(e){this.chunks.push(e)},f.prototype.onEnd=function(e){e===a.Z_OK&&("string"===this.options.to?this.result=this.chunks.join(""):this.result=i.flattenChunks(this.chunks)),this.chunks=[],this.err=e,this.msg=this.strm.msg},r.Inflate=f,r.inflate=c,r.inflateRaw=function(e,t){return(t=t||{}).raw=!0,c(e,t)},r.ungzip=c},{"./utils/common":41,"./utils/strings":42,"./zlib/constants":44,"./zlib/gzheader":47,"./zlib/inflate":49,"./zlib/messages":51,"./zlib/zstream":53}],41:[function(e,t,r){"use strict";var n="undefined"!=typeof Uint8Array&&"undefined"!=typeof Uint16Array&&"undefined"!=typeof Int32Array;r.assign=function(e){for(var t=Array.prototype.slice.call(arguments,1);t.length;){var r=t.shift();if(r){if("object"!=typeof r)throw new TypeError(r+"must be non-object");for(var n in r)r.hasOwnProperty(n)&&(e[n]=r[n])}}return e},r.shrinkBuf=function(e,t){return e.length===t?e:e.subarray?e.subarray(0,t):(e.length=t,e)};var i={arraySet:function(e,t,r,n,i){if(t.subarray&&e.subarray)e.set(t.subarray(r,r+n),i);else for(var s=0;s<n;s++)e[i+s]=t[r+s]},flattenChunks:function(e){var t,r,n,i,s,a;for(t=n=0,r=e.length;t<r;t++)n+=e[t].length;for(a=new Uint8Array(n),t=i=0,r=e.length;t<r;t++)s=e[t],a.set(s,i),i+=s.length;return a}},s={arraySet:function(e,t,r,n,i){for(var s=0;s<n;s++)e[i+s]=t[r+s]},flattenChunks:function(e){return[].concat.apply([],e)}};r.setTyped=function(e){e?(r.Buf8=Uint8Array,r.Buf16=Uint16Array,r.Buf32=Int32Array,r.assign(r,i)):(r.Buf8=Array,r.Buf16=Array,r.Buf32=Array,r.assign(r,s))},r.setTyped(n)},{}],42:[function(e,t,r){"use strict";var n=e("./common"),i=!0,s=!0;try{String.fromCharCode.apply(null,[0])}catch(e){i=!1}try{String.fromCharCode.apply(null,new Uint8Array(1))}catch(e){s=!1}for(var a=new n.Buf8(256),o=0;o<256;o++)a[o]=252<=o?6:248<=o?5:240<=o?4:224<=o?3:192<=o?2:1;function h(e,t){if(t<65537&&(e.subarray&&s||!e.subarray&&i))return String.fromCharCode.apply(null,n.shrinkBuf(e,t));for(var r="",a=0;a<t;a++)r+=String.fromCharCode(e[a]);return r}a[254]=a[254]=1,r.string2buf=function(e){var t,r,i,s,a,o=e.length,h=0;for(s=0;s<o;s++)55296==(64512&(r=e.charCodeAt(s)))&&s+1<o&&56320==(64512&(i=e.charCodeAt(s+1)))&&(r=65536+(r-55296<<10)+(i-56320),s++),h+=r<128?1:r<2048?2:r<65536?3:4;for(t=new n.Buf8(h),s=a=0;a<h;s++)55296==(64512&(r=e.charCodeAt(s)))&&s+1<o&&56320==(64512&(i=e.charCodeAt(s+1)))&&(r=65536+(r-55296<<10)+(i-56320),s++),r<128?t[a++]=r:(r<2048?t[a++]=192|r>>>6:(r<65536?t[a++]=224|r>>>12:(t[a++]=240|r>>>18,t[a++]=128|r>>>12&63),t[a++]=128|r>>>6&63),t[a++]=128|63&r);return t},r.buf2binstring=function(e){return h(e,e.length)},r.binstring2buf=function(e){for(var t=new n.Buf8(e.length),r=0,i=t.length;r<i;r++)t[r]=e.charCodeAt(r);return t},r.buf2string=function(e,t){var r,n,i,s,o=t||e.length,u=new Array(2*o);for(r=n=0;r<o;)if((i=e[r++])<128)u[n++]=i;else if(4<(s=a[i]))u[n++]=65533,r+=s-1;else{for(i&=2===s?31:3===s?15:7;1<s&&r<o;)i=i<<6|63&e[r++],s--;1<s?u[n++]=65533:i<65536?u[n++]=i:(i-=65536,u[n++]=55296|i>>10&1023,u[n++]=56320|1023&i)}return h(u,n)},r.utf8border=function(e,t){var r;for((t=t||e.length)>e.length&&(t=e.length),r=t-1;0<=r&&128==(192&e[r]);)r--;return r<0||0===r?t:r+a[e[r]]>t?r:t}},{"./common":41}],43:[function(e,t,r){"use strict";t.exports=function(e,t,r,n){for(var i=65535&e,s=e>>>16&65535,a=0;0!==r;){for(r-=a=2e3<r?2e3:r;s=s+(i=i+t[n++]|0)|0,--a;);i%=65521,s%=65521}return i|s<<16}},{}],44:[function(e,t,r){"use strict";t.exports={Z_NO_FLUSH:0,Z_PARTIAL_FLUSH:1,Z_SYNC_FLUSH:2,Z_FULL_FLUSH:3,Z_FINISH:4,Z_BLOCK:5,Z_TREES:6,Z_OK:0,Z_STREAM_END:1,Z_NEED_DICT:2,Z_ERRNO:-1,Z_STREAM_ERROR:-2,Z_DATA_ERROR:-3,Z_BUF_ERROR:-5,Z_NO_COMPRESSION:0,Z_BEST_SPEED:1,Z_BEST_COMPRESSION:9,Z_DEFAULT_COMPRESSION:-1,Z_FILTERED:1,Z_HUFFMAN_ONLY:2,Z_RLE:3,Z_FIXED:4,Z_DEFAULT_STRATEGY:0,Z_BINARY:0,Z_TEXT:1,Z_UNKNOWN:2,Z_DEFLATED:8}},{}],45:[function(e,t,r){"use strict";var n=function(){for(var e,t=[],r=0;r<256;r++){e=r;for(var n=0;n<8;n++)e=1&e?3988292384^e>>>1:e>>>1;t[r]=e}return t}();t.exports=function(e,t,r,i){var s=n,a=i+r;e^=-1;for(var o=i;o<a;o++)e=e>>>8^s[255&(e^t[o])];return-1^e}},{}],46:[function(e,t,r){"use strict";var n,i=e("../utils/common"),s=e("./trees"),a=e("./adler32"),o=e("./crc32"),h=e("./messages"),u=0,l=4,f=0,c=-2,d=-1,p=4,m=2,_=8,g=9,b=286,v=30,y=19,w=2*b+1,k=15,x=3,S=258,z=S+x+1,C=42,E=113,A=1,I=2,O=3,B=4;function R(e,t){return e.msg=h[t],t}function T(e){return(e<<1)-(4<e?9:0)}function D(e){for(var t=e.length;0<=--t;)e[t]=0}function F(e){var t=e.state,r=t.pending;r>e.avail_out&&(r=e.avail_out),0!==r&&(i.arraySet(e.output,t.pending_buf,t.pending_out,r,e.next_out),e.next_out+=r,t.pending_out+=r,e.total_out+=r,e.avail_out-=r,t.pending-=r,0===t.pending&&(t.pending_out=0))}function N(e,t){s._tr_flush_block(e,0<=e.block_start?e.block_start:-1,e.strstart-e.block_start,t),e.block_start=e.strstart,F(e.strm)}function U(e,t){e.pending_buf[e.pending++]=t}function P(e,t){e.pending_buf[e.pending++]=t>>>8&255,e.pending_buf[e.pending++]=255&t}function L(e,t){var r,n,i=e.max_chain_length,s=e.strstart,a=e.prev_length,o=e.nice_match,h=e.strstart>e.w_size-z?e.strstart-(e.w_size-z):0,u=e.window,l=e.w_mask,f=e.prev,c=e.strstart+S,d=u[s+a-1],p=u[s+a];e.prev_length>=e.good_match&&(i>>=2),o>e.lookahead&&(o=e.lookahead);do{if(u[(r=t)+a]===p&&u[r+a-1]===d&&u[r]===u[s]&&u[++r]===u[s+1]){s+=2,r++;do{}while(u[++s]===u[++r]&&u[++s]===u[++r]&&u[++s]===u[++r]&&u[++s]===u[++r]&&u[++s]===u[++r]&&u[++s]===u[++r]&&u[++s]===u[++r]&&u[++s]===u[++r]&&s<c);if(n=S-(c-s),s=c-S,a<n){if(e.match_start=t,o<=(a=n))break;d=u[s+a-1],p=u[s+a]}}}while((t=f[t&l])>h&&0!=--i);return a<=e.lookahead?a:e.lookahead}function j(e){var t,r,n,s,h,u,l,f,c,d,p=e.w_size;do{if(s=e.window_size-e.lookahead-e.strstart,e.strstart>=p+(p-z)){for(i.arraySet(e.window,e.window,p,p,0),e.match_start-=p,e.strstart-=p,e.block_start-=p,t=r=e.hash_size;n=e.head[--t],e.head[t]=p<=n?n-p:0,--r;);for(t=r=p;n=e.prev[--t],e.prev[t]=p<=n?n-p:0,--r;);s+=p}if(0===e.strm.avail_in)break;if(u=e.strm,l=e.window,f=e.strstart+e.lookahead,c=s,d=void 0,d=u.avail_in,c<d&&(d=c),r=0===d?0:(u.avail_in-=d,i.arraySet(l,u.input,u.next_in,d,f),1===u.state.wrap?u.adler=a(u.adler,l,d,f):2===u.state.wrap&&(u.adler=o(u.adler,l,d,f)),u.next_in+=d,u.total_in+=d,d),e.lookahead+=r,e.lookahead+e.insert>=x)for(h=e.strstart-e.insert,e.ins_h=e.window[h],e.ins_h=(e.ins_h<<e.hash_shift^e.window[h+1])&e.hash_mask;e.insert&&(e.ins_h=(e.ins_h<<e.hash_shift^e.window[h+x-1])&e.hash_mask,e.prev[h&e.w_mask]=e.head[e.ins_h],e.head[e.ins_h]=h,h++,e.insert--,!(e.lookahead+e.insert<x)););}while(e.lookahead<z&&0!==e.strm.avail_in)}function Z(e,t){for(var r,n;;){if(e.lookahead<z){if(j(e),e.lookahead<z&&t===u)return A;if(0===e.lookahead)break}if(r=0,e.lookahead>=x&&(e.ins_h=(e.ins_h<<e.hash_shift^e.window[e.strstart+x-1])&e.hash_mask,r=e.prev[e.strstart&e.w_mask]=e.head[e.ins_h],e.head[e.ins_h]=e.strstart),0!==r&&e.strstart-r<=e.w_size-z&&(e.match_length=L(e,r)),e.match_length>=x)if(n=s._tr_tally(e,e.strstart-e.match_start,e.match_length-x),e.lookahead-=e.match_length,e.match_length<=e.max_lazy_match&&e.lookahead>=x){for(e.match_length--;e.strstart++,e.ins_h=(e.ins_h<<e.hash_shift^e.window[e.strstart+x-1])&e.hash_mask,r=e.prev[e.strstart&e.w_mask]=e.head[e.ins_h],e.head[e.ins_h]=e.strstart,0!=--e.match_length;);e.strstart++}else e.strstart+=e.match_length,e.match_length=0,e.ins_h=e.window[e.strstart],e.ins_h=(e.ins_h<<e.hash_shift^e.window[e.strstart+1])&e.hash_mask;else n=s._tr_tally(e,0,e.window[e.strstart]),e.lookahead--,e.strstart++;if(n&&(N(e,!1),0===e.strm.avail_out))return A}return e.insert=e.strstart<x-1?e.strstart:x-1,t===l?(N(e,!0),0===e.strm.avail_out?O:B):e.last_lit&&(N(e,!1),0===e.strm.avail_out)?A:I}function W(e,t){for(var r,n,i;;){if(e.lookahead<z){if(j(e),e.lookahead<z&&t===u)return A;if(0===e.lookahead)break}if(r=0,e.lookahead>=x&&(e.ins_h=(e.ins_h<<e.hash_shift^e.window[e.strstart+x-1])&e.hash_mask,r=e.prev[e.strstart&e.w_mask]=e.head[e.ins_h],e.head[e.ins_h]=e.strstart),e.prev_length=e.match_length,e.prev_match=e.match_start,e.match_length=x-1,0!==r&&e.prev_length<e.max_lazy_match&&e.strstart-r<=e.w_size-z&&(e.match_length=L(e,r),e.match_length<=5&&(1===e.strategy||e.match_length===x&&4096<e.strstart-e.match_start)&&(e.match_length=x-1)),e.prev_length>=x&&e.match_length<=e.prev_length){for(i=e.strstart+e.lookahead-x,n=s._tr_tally(e,e.strstart-1-e.prev_match,e.prev_length-x),e.lookahead-=e.prev_length-1,e.prev_length-=2;++e.strstart<=i&&(e.ins_h=(e.ins_h<<e.hash_shift^e.window[e.strstart+x-1])&e.hash_mask,r=e.prev[e.strstart&e.w_mask]=e.head[e.ins_h],e.head[e.ins_h]=e.strstart),0!=--e.prev_length;);if(e.match_available=0,e.match_length=x-1,e.strstart++,n&&(N(e,!1),0===e.strm.avail_out))return A}else if(e.match_available){if((n=s._tr_tally(e,0,e.window[e.strstart-1]))&&N(e,!1),e.strstart++,e.lookahead--,0===e.strm.avail_out)return A}else e.match_available=1,e.strstart++,e.lookahead--}return e.match_available&&(n=s._tr_tally(e,0,e.window[e.strstart-1]),e.match_available=0),e.insert=e.strstart<x-1?e.strstart:x-1,t===l?(N(e,!0),0===e.strm.avail_out?O:B):e.last_lit&&(N(e,!1),0===e.strm.avail_out)?A:I}function M(e,t,r,n,i){this.good_length=e,this.max_lazy=t,this.nice_length=r,this.max_chain=n,this.func=i}function H(){this.strm=null,this.status=0,this.pending_buf=null,this.pending_buf_size=0,this.pending_out=0,this.pending=0,this.wrap=0,this.gzhead=null,this.gzindex=0,this.method=_,this.last_flush=-1,this.w_size=0,this.w_bits=0,this.w_mask=0,this.window=null,this.window_size=0,this.prev=null,this.head=null,this.ins_h=0,this.hash_size=0,this.hash_bits=0,this.hash_mask=0,this.hash_shift=0,this.block_start=0,this.match_length=0,this.prev_match=0,this.match_available=0,this.strstart=0,this.match_start=0,this.lookahead=0,this.prev_length=0,this.max_chain_length=0,this.max_lazy_match=0,this.level=0,this.strategy=0,this.good_match=0,this.nice_match=0,this.dyn_ltree=new i.Buf16(2*w),this.dyn_dtree=new i.Buf16(2*(2*v+1)),this.bl_tree=new i.Buf16(2*(2*y+1)),D(this.dyn_ltree),D(this.dyn_dtree),D(this.bl_tree),this.l_desc=null,this.d_desc=null,this.bl_desc=null,this.bl_count=new i.Buf16(k+1),this.heap=new i.Buf16(2*b+1),D(this.heap),this.heap_len=0,this.heap_max=0,this.depth=new i.Buf16(2*b+1),D(this.depth),this.l_buf=0,this.lit_bufsize=0,this.last_lit=0,this.d_buf=0,this.opt_len=0,this.static_len=0,this.matches=0,this.insert=0,this.bi_buf=0,this.bi_valid=0}function G(e){var t;return e&&e.state?(e.total_in=e.total_out=0,e.data_type=m,(t=e.state).pending=0,t.pending_out=0,t.wrap<0&&(t.wrap=-t.wrap),t.status=t.wrap?C:E,e.adler=2===t.wrap?0:1,t.last_flush=u,s._tr_init(t),f):R(e,c)}function K(e){var t=G(e);return t===f&&function(e){e.window_size=2*e.w_size,D(e.head),e.max_lazy_match=n[e.level].max_lazy,e.good_match=n[e.level].good_length,e.nice_match=n[e.level].nice_length,e.max_chain_length=n[e.level].max_chain,e.strstart=0,e.block_start=0,e.lookahead=0,e.insert=0,e.match_length=e.prev_length=x-1,e.match_available=0,e.ins_h=0}(e.state),t}function Y(e,t,r,n,s,a){if(!e)return c;var o=1;if(t===d&&(t=6),n<0?(o=0,n=-n):15<n&&(o=2,n-=16),s<1||g<s||r!==_||n<8||15<n||t<0||9<t||a<0||p<a)return R(e,c);8===n&&(n=9);var h=new H;return(e.state=h).strm=e,h.wrap=o,h.gzhead=null,h.w_bits=n,h.w_size=1<<h.w_bits,h.w_mask=h.w_size-1,h.hash_bits=s+7,h.hash_size=1<<h.hash_bits,h.hash_mask=h.hash_size-1,h.hash_shift=~~((h.hash_bits+x-1)/x),h.window=new i.Buf8(2*h.w_size),h.head=new i.Buf16(h.hash_size),h.prev=new i.Buf16(h.w_size),h.lit_bufsize=1<<s+6,h.pending_buf_size=4*h.lit_bufsize,h.pending_buf=new i.Buf8(h.pending_buf_size),h.d_buf=1*h.lit_bufsize,h.l_buf=3*h.lit_bufsize,h.level=t,h.strategy=a,h.method=r,K(e)}n=[new M(0,0,0,0,function(e,t){var r=65535;for(r>e.pending_buf_size-5&&(r=e.pending_buf_size-5);;){if(e.lookahead<=1){if(j(e),0===e.lookahead&&t===u)return A;if(0===e.lookahead)break}e.strstart+=e.lookahead,e.lookahead=0;var n=e.block_start+r;if((0===e.strstart||e.strstart>=n)&&(e.lookahead=e.strstart-n,e.strstart=n,N(e,!1),0===e.strm.avail_out))return A;if(e.strstart-e.block_start>=e.w_size-z&&(N(e,!1),0===e.strm.avail_out))return A}return e.insert=0,t===l?(N(e,!0),0===e.strm.avail_out?O:B):(e.strstart>e.block_start&&(N(e,!1),e.strm.avail_out),A)}),new M(4,4,8,4,Z),new M(4,5,16,8,Z),new M(4,6,32,32,Z),new M(4,4,16,16,W),new M(8,16,32,32,W),new M(8,16,128,128,W),new M(8,32,128,256,W),new M(32,128,258,1024,W),new M(32,258,258,4096,W)],r.deflateInit=function(e,t){return Y(e,t,_,15,8,0)},r.deflateInit2=Y,r.deflateReset=K,r.deflateResetKeep=G,r.deflateSetHeader=function(e,t){return e&&e.state?2!==e.state.wrap?c:(e.state.gzhead=t,f):c},r.deflate=function(e,t){var r,i,a,h;if(!e||!e.state||5<t||t<0)return e?R(e,c):c;if(i=e.state,!e.output||!e.input&&0!==e.avail_in||666===i.status&&t!==l)return R(e,0===e.avail_out?-5:c);if(i.strm=e,r=i.last_flush,i.last_flush=t,i.status===C)if(2===i.wrap)e.adler=0,U(i,31),U(i,139),U(i,8),i.gzhead?(U(i,(i.gzhead.text?1:0)+(i.gzhead.hcrc?2:0)+(i.gzhead.extra?4:0)+(i.gzhead.name?8:0)+(i.gzhead.comment?16:0)),U(i,255&i.gzhead.time),U(i,i.gzhead.time>>8&255),U(i,i.gzhead.time>>16&255),U(i,i.gzhead.time>>24&255),U(i,9===i.level?2:2<=i.strategy||i.level<2?4:0),U(i,255&i.gzhead.os),i.gzhead.extra&&i.gzhead.extra.length&&(U(i,255&i.gzhead.extra.length),U(i,i.gzhead.extra.length>>8&255)),i.gzhead.hcrc&&(e.adler=o(e.adler,i.pending_buf,i.pending,0)),i.gzindex=0,i.status=69):(U(i,0),U(i,0),U(i,0),U(i,0),U(i,0),U(i,9===i.level?2:2<=i.strategy||i.level<2?4:0),U(i,3),i.status=E);else{var d=_+(i.w_bits-8<<4)<<8;d|=(2<=i.strategy||i.level<2?0:i.level<6?1:6===i.level?2:3)<<6,0!==i.strstart&&(d|=32),d+=31-d%31,i.status=E,P(i,d),0!==i.strstart&&(P(i,e.adler>>>16),P(i,65535&e.adler)),e.adler=1}if(69===i.status)if(i.gzhead.extra){for(a=i.pending;i.gzindex<(65535&i.gzhead.extra.length)&&(i.pending!==i.pending_buf_size||(i.gzhead.hcrc&&i.pending>a&&(e.adler=o(e.adler,i.pending_buf,i.pending-a,a)),F(e),a=i.pending,i.pending!==i.pending_buf_size));)U(i,255&i.gzhead.extra[i.gzindex]),i.gzindex++;i.gzhead.hcrc&&i.pending>a&&(e.adler=o(e.adler,i.pending_buf,i.pending-a,a)),i.gzindex===i.gzhead.extra.length&&(i.gzindex=0,i.status=73)}else i.status=73;if(73===i.status)if(i.gzhead.name){a=i.pending;do{if(i.pending===i.pending_buf_size&&(i.gzhead.hcrc&&i.pending>a&&(e.adler=o(e.adler,i.pending_buf,i.pending-a,a)),F(e),a=i.pending,i.pending===i.pending_buf_size)){h=1;break}h=i.gzindex<i.gzhead.name.length?255&i.gzhead.name.charCodeAt(i.gzindex++):0,U(i,h)}while(0!==h);i.gzhead.hcrc&&i.pending>a&&(e.adler=o(e.adler,i.pending_buf,i.pending-a,a)),0===h&&(i.gzindex=0,i.status=91)}else i.status=91;if(91===i.status)if(i.gzhead.comment){a=i.pending;do{if(i.pending===i.pending_buf_size&&(i.gzhead.hcrc&&i.pending>a&&(e.adler=o(e.adler,i.pending_buf,i.pending-a,a)),F(e),a=i.pending,i.pending===i.pending_buf_size)){h=1;break}h=i.gzindex<i.gzhead.comment.length?255&i.gzhead.comment.charCodeAt(i.gzindex++):0,U(i,h)}while(0!==h);i.gzhead.hcrc&&i.pending>a&&(e.adler=o(e.adler,i.pending_buf,i.pending-a,a)),0===h&&(i.status=103)}else i.status=103;if(103===i.status&&(i.gzhead.hcrc?(i.pending+2>i.pending_buf_size&&F(e),i.pending+2<=i.pending_buf_size&&(U(i,255&e.adler),U(i,e.adler>>8&255),e.adler=0,i.status=E)):i.status=E),0!==i.pending){if(F(e),0===e.avail_out)return i.last_flush=-1,f}else if(0===e.avail_in&&T(t)<=T(r)&&t!==l)return R(e,-5);if(666===i.status&&0!==e.avail_in)return R(e,-5);if(0!==e.avail_in||0!==i.lookahead||t!==u&&666!==i.status){var p=2===i.strategy?function(e,t){for(var r;;){if(0===e.lookahead&&(j(e),0===e.lookahead)){if(t===u)return A;break}if(e.match_length=0,r=s._tr_tally(e,0,e.window[e.strstart]),e.lookahead--,e.strstart++,r&&(N(e,!1),0===e.strm.avail_out))return A}return e.insert=0,t===l?(N(e,!0),0===e.strm.avail_out?O:B):e.last_lit&&(N(e,!1),0===e.strm.avail_out)?A:I}(i,t):3===i.strategy?function(e,t){for(var r,n,i,a,o=e.window;;){if(e.lookahead<=S){if(j(e),e.lookahead<=S&&t===u)return A;if(0===e.lookahead)break}if(e.match_length=0,e.lookahead>=x&&0<e.strstart&&(n=o[i=e.strstart-1])===o[++i]&&n===o[++i]&&n===o[++i]){a=e.strstart+S;do{}while(n===o[++i]&&n===o[++i]&&n===o[++i]&&n===o[++i]&&n===o[++i]&&n===o[++i]&&n===o[++i]&&n===o[++i]&&i<a);e.match_length=S-(a-i),e.match_length>e.lookahead&&(e.match_length=e.lookahead)}if(e.match_length>=x?(r=s._tr_tally(e,1,e.match_length-x),e.lookahead-=e.match_length,e.strstart+=e.match_length,e.match_length=0):(r=s._tr_tally(e,0,e.window[e.strstart]),e.lookahead--,e.strstart++),r&&(N(e,!1),0===e.strm.avail_out))return A}return e.insert=0,t===l?(N(e,!0),0===e.strm.avail_out?O:B):e.last_lit&&(N(e,!1),0===e.strm.avail_out)?A:I}(i,t):n[i.level].func(i,t);if(p!==O&&p!==B||(i.status=666),p===A||p===O)return 0===e.avail_out&&(i.last_flush=-1),f;if(p===I&&(1===t?s._tr_align(i):5!==t&&(s._tr_stored_block(i,0,0,!1),3===t&&(D(i.head),0===i.lookahead&&(i.strstart=0,i.block_start=0,i.insert=0))),F(e),0===e.avail_out))return i.last_flush=-1,f}return t!==l?f:i.wrap<=0?1:(2===i.wrap?(U(i,255&e.adler),U(i,e.adler>>8&255),U(i,e.adler>>16&255),U(i,e.adler>>24&255),U(i,255&e.total_in),U(i,e.total_in>>8&255),U(i,e.total_in>>16&255),U(i,e.total_in>>24&255)):(P(i,e.adler>>>16),P(i,65535&e.adler)),F(e),0<i.wrap&&(i.wrap=-i.wrap),0!==i.pending?f:1)},r.deflateEnd=function(e){var t;return e&&e.state?(t=e.state.status)!==C&&69!==t&&73!==t&&91!==t&&103!==t&&t!==E&&666!==t?R(e,c):(e.state=null,t===E?R(e,-3):f):c},r.deflateSetDictionary=function(e,t){var r,n,s,o,h,u,l,d,p=t.length;if(!e||!e.state)return c;if(2===(o=(r=e.state).wrap)||1===o&&r.status!==C||r.lookahead)return c;for(1===o&&(e.adler=a(e.adler,t,p,0)),r.wrap=0,p>=r.w_size&&(0===o&&(D(r.head),r.strstart=0,r.block_start=0,r.insert=0),d=new i.Buf8(r.w_size),i.arraySet(d,t,p-r.w_size,r.w_size,0),t=d,p=r.w_size),h=e.avail_in,u=e.next_in,l=e.input,e.avail_in=p,e.next_in=0,e.input=t,j(r);r.lookahead>=x;){for(n=r.strstart,s=r.lookahead-(x-1);r.ins_h=(r.ins_h<<r.hash_shift^r.window[n+x-1])&r.hash_mask,r.prev[n&r.w_mask]=r.head[r.ins_h],r.head[r.ins_h]=n,n++,--s;);r.strstart=n,r.lookahead=x-1,j(r)}return r.strstart+=r.lookahead,r.block_start=r.strstart,r.insert=r.lookahead,r.lookahead=0,r.match_length=r.prev_length=x-1,r.match_available=0,e.next_in=u,e.input=l,e.avail_in=h,r.wrap=o,f},r.deflateInfo="pako deflate (from Nodeca project)"},{"../utils/common":41,"./adler32":43,"./crc32":45,"./messages":51,"./trees":52}],47:[function(e,t,r){"use strict";t.exports=function(){this.text=0,this.time=0,this.xflags=0,this.os=0,this.extra=null,this.extra_len=0,this.name="",this.comment="",this.hcrc=0,this.done=!1}},{}],48:[function(e,t,r){"use strict";t.exports=function(e,t){var r,n,i,s,a,o,h,u,l,f,c,d,p,m,_,g,b,v,y,w,k,x,S,z,C;r=e.state,n=e.next_in,z=e.input,i=n+(e.avail_in-5),s=e.next_out,C=e.output,a=s-(t-e.avail_out),o=s+(e.avail_out-257),h=r.dmax,u=r.wsize,l=r.whave,f=r.wnext,c=r.window,d=r.hold,p=r.bits,m=r.lencode,_=r.distcode,g=(1<<r.lenbits)-1,b=(1<<r.distbits)-1;e:do{p<15&&(d+=z[n++]<<p,p+=8,d+=z[n++]<<p,p+=8),v=m[d&g];t:for(;;){if(d>>>=y=v>>>24,p-=y,0===(y=v>>>16&255))C[s++]=65535&v;else{if(!(16&y)){if(0==(64&y)){v=m[(65535&v)+(d&(1<<y)-1)];continue t}if(32&y){r.mode=12;break e}e.msg="invalid literal/length code",r.mode=30;break e}w=65535&v,(y&=15)&&(p<y&&(d+=z[n++]<<p,p+=8),w+=d&(1<<y)-1,d>>>=y,p-=y),p<15&&(d+=z[n++]<<p,p+=8,d+=z[n++]<<p,p+=8),v=_[d&b];r:for(;;){if(d>>>=y=v>>>24,p-=y,!(16&(y=v>>>16&255))){if(0==(64&y)){v=_[(65535&v)+(d&(1<<y)-1)];continue r}e.msg="invalid distance code",r.mode=30;break e}if(k=65535&v,p<(y&=15)&&(d+=z[n++]<<p,(p+=8)<y&&(d+=z[n++]<<p,p+=8)),h<(k+=d&(1<<y)-1)){e.msg="invalid distance too far back",r.mode=30;break e}if(d>>>=y,p-=y,(y=s-a)<k){if(l<(y=k-y)&&r.sane){e.msg="invalid distance too far back",r.mode=30;break e}if(S=c,(x=0)===f){if(x+=u-y,y<w){for(w-=y;C[s++]=c[x++],--y;);x=s-k,S=C}}else if(f<y){if(x+=u+f-y,(y-=f)<w){for(w-=y;C[s++]=c[x++],--y;);if(x=0,f<w){for(w-=y=f;C[s++]=c[x++],--y;);x=s-k,S=C}}}else if(x+=f-y,y<w){for(w-=y;C[s++]=c[x++],--y;);x=s-k,S=C}for(;2<w;)C[s++]=S[x++],C[s++]=S[x++],C[s++]=S[x++],w-=3;w&&(C[s++]=S[x++],1<w&&(C[s++]=S[x++]))}else{for(x=s-k;C[s++]=C[x++],C[s++]=C[x++],C[s++]=C[x++],2<(w-=3););w&&(C[s++]=C[x++],1<w&&(C[s++]=C[x++]))}break}}break}}while(n<i&&s<o);n-=w=p>>3,d&=(1<<(p-=w<<3))-1,e.next_in=n,e.next_out=s,e.avail_in=n<i?i-n+5:5-(n-i),e.avail_out=s<o?o-s+257:257-(s-o),r.hold=d,r.bits=p}},{}],49:[function(e,t,r){"use strict";var n=e("../utils/common"),i=e("./adler32"),s=e("./crc32"),a=e("./inffast"),o=e("./inftrees"),h=1,u=2,l=0,f=-2,c=1,d=852,p=592;function m(e){return(e>>>24&255)+(e>>>8&65280)+((65280&e)<<8)+((255&e)<<24)}function _(){this.mode=0,this.last=!1,this.wrap=0,this.havedict=!1,this.flags=0,this.dmax=0,this.check=0,this.total=0,this.head=null,this.wbits=0,this.wsize=0,this.whave=0,this.wnext=0,this.window=null,this.hold=0,this.bits=0,this.length=0,this.offset=0,this.extra=0,this.lencode=null,this.distcode=null,this.lenbits=0,this.distbits=0,this.ncode=0,this.nlen=0,this.ndist=0,this.have=0,this.next=null,this.lens=new n.Buf16(320),this.work=new n.Buf16(288),this.lendyn=null,this.distdyn=null,this.sane=0,this.back=0,this.was=0}function g(e){var t;return e&&e.state?(t=e.state,e.total_in=e.total_out=t.total=0,e.msg="",t.wrap&&(e.adler=1&t.wrap),t.mode=c,t.last=0,t.havedict=0,t.dmax=32768,t.head=null,t.hold=0,t.bits=0,t.lencode=t.lendyn=new n.Buf32(d),t.distcode=t.distdyn=new n.Buf32(p),t.sane=1,t.back=-1,l):f}function b(e){var t;return e&&e.state?((t=e.state).wsize=0,t.whave=0,t.wnext=0,g(e)):f}function v(e,t){var r,n;return e&&e.state?(n=e.state,t<0?(r=0,t=-t):(r=1+(t>>4),t<48&&(t&=15)),t&&(t<8||15<t)?f:(null!==n.window&&n.wbits!==t&&(n.window=null),n.wrap=r,n.wbits=t,b(e))):f}function y(e,t){var r,n;return e?(n=new _,(e.state=n).window=null,(r=v(e,t))!==l&&(e.state=null),r):f}var w,k,x=!0;function S(e){if(x){var t;for(w=new n.Buf32(512),k=new n.Buf32(32),t=0;t<144;)e.lens[t++]=8;for(;t<256;)e.lens[t++]=9;for(;t<280;)e.lens[t++]=7;for(;t<288;)e.lens[t++]=8;for(o(h,e.lens,0,288,w,0,e.work,{bits:9}),t=0;t<32;)e.lens[t++]=5;o(u,e.lens,0,32,k,0,e.work,{bits:5}),x=!1}e.lencode=w,e.lenbits=9,e.distcode=k,e.distbits=5}function z(e,t,r,i){var s,a=e.state;return null===a.window&&(a.wsize=1<<a.wbits,a.wnext=0,a.whave=0,a.window=new n.Buf8(a.wsize)),i>=a.wsize?(n.arraySet(a.window,t,r-a.wsize,a.wsize,0),a.wnext=0,a.whave=a.wsize):(i<(s=a.wsize-a.wnext)&&(s=i),n.arraySet(a.window,t,r-i,s,a.wnext),(i-=s)?(n.arraySet(a.window,t,r-i,i,0),a.wnext=i,a.whave=a.wsize):(a.wnext+=s,a.wnext===a.wsize&&(a.wnext=0),a.whave<a.wsize&&(a.whave+=s))),0}r.inflateReset=b,r.inflateReset2=v,r.inflateResetKeep=g,r.inflateInit=function(e){return y(e,15)},r.inflateInit2=y,r.inflate=function(e,t){var r,d,p,_,g,b,v,y,w,k,x,C,E,A,I,O,B,R,T,D,F,N,U,P,L=0,j=new n.Buf8(4),Z=[16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15];if(!e||!e.state||!e.output||!e.input&&0!==e.avail_in)return f;12===(r=e.state).mode&&(r.mode=13),g=e.next_out,p=e.output,v=e.avail_out,_=e.next_in,d=e.input,b=e.avail_in,y=r.hold,w=r.bits,k=b,x=v,N=l;e:for(;;)switch(r.mode){case c:if(0===r.wrap){r.mode=13;break}for(;w<16;){if(0===b)break e;b--,y+=d[_++]<<w,w+=8}if(2&r.wrap&&35615===y){j[r.check=0]=255&y,j[1]=y>>>8&255,r.check=s(r.check,j,2,0),w=y=0,r.mode=2;break}if(r.flags=0,r.head&&(r.head.done=!1),!(1&r.wrap)||(((255&y)<<8)+(y>>8))%31){e.msg="incorrect header check",r.mode=30;break}if(8!=(15&y)){e.msg="unknown compression method",r.mode=30;break}if(w-=4,F=8+(15&(y>>>=4)),0===r.wbits)r.wbits=F;else if(F>r.wbits){e.msg="invalid window size",r.mode=30;break}r.dmax=1<<F,e.adler=r.check=1,r.mode=512&y?10:12,w=y=0;break;case 2:for(;w<16;){if(0===b)break e;b--,y+=d[_++]<<w,w+=8}if(r.flags=y,8!=(255&r.flags)){e.msg="unknown compression method",r.mode=30;break}if(57344&r.flags){e.msg="unknown header flags set",r.mode=30;break}r.head&&(r.head.text=y>>8&1),512&r.flags&&(j[0]=255&y,j[1]=y>>>8&255,r.check=s(r.check,j,2,0)),w=y=0,r.mode=3;case 3:for(;w<32;){if(0===b)break e;b--,y+=d[_++]<<w,w+=8}r.head&&(r.head.time=y),512&r.flags&&(j[0]=255&y,j[1]=y>>>8&255,j[2]=y>>>16&255,j[3]=y>>>24&255,r.check=s(r.check,j,4,0)),w=y=0,r.mode=4;case 4:for(;w<16;){if(0===b)break e;b--,y+=d[_++]<<w,w+=8}r.head&&(r.head.xflags=255&y,r.head.os=y>>8),512&r.flags&&(j[0]=255&y,j[1]=y>>>8&255,r.check=s(r.check,j,2,0)),w=y=0,r.mode=5;case 5:if(1024&r.flags){for(;w<16;){if(0===b)break e;b--,y+=d[_++]<<w,w+=8}r.length=y,r.head&&(r.head.extra_len=y),512&r.flags&&(j[0]=255&y,j[1]=y>>>8&255,r.check=s(r.check,j,2,0)),w=y=0}else r.head&&(r.head.extra=null);r.mode=6;case 6:if(1024&r.flags&&(b<(C=r.length)&&(C=b),C&&(r.head&&(F=r.head.extra_len-r.length,r.head.extra||(r.head.extra=new Array(r.head.extra_len)),n.arraySet(r.head.extra,d,_,C,F)),512&r.flags&&(r.check=s(r.check,d,C,_)),b-=C,_+=C,r.length-=C),r.length))break e;r.length=0,r.mode=7;case 7:if(2048&r.flags){if(0===b)break e;for(C=0;F=d[_+C++],r.head&&F&&r.length<65536&&(r.head.name+=String.fromCharCode(F)),F&&C<b;);if(512&r.flags&&(r.check=s(r.check,d,C,_)),b-=C,_+=C,F)break e}else r.head&&(r.head.name=null);r.length=0,r.mode=8;case 8:if(4096&r.flags){if(0===b)break e;for(C=0;F=d[_+C++],r.head&&F&&r.length<65536&&(r.head.comment+=String.fromCharCode(F)),F&&C<b;);if(512&r.flags&&(r.check=s(r.check,d,C,_)),b-=C,_+=C,F)break e}else r.head&&(r.head.comment=null);r.mode=9;case 9:if(512&r.flags){for(;w<16;){if(0===b)break e;b--,y+=d[_++]<<w,w+=8}if(y!==(65535&r.check)){e.msg="header crc mismatch",r.mode=30;break}w=y=0}r.head&&(r.head.hcrc=r.flags>>9&1,r.head.done=!0),e.adler=r.check=0,r.mode=12;break;case 10:for(;w<32;){if(0===b)break e;b--,y+=d[_++]<<w,w+=8}e.adler=r.check=m(y),w=y=0,r.mode=11;case 11:if(0===r.havedict)return e.next_out=g,e.avail_out=v,e.next_in=_,e.avail_in=b,r.hold=y,r.bits=w,2;e.adler=r.check=1,r.mode=12;case 12:if(5===t||6===t)break e;case 13:if(r.last){y>>>=7&w,w-=7&w,r.mode=27;break}for(;w<3;){if(0===b)break e;b--,y+=d[_++]<<w,w+=8}switch(r.last=1&y,w-=1,3&(y>>>=1)){case 0:r.mode=14;break;case 1:if(S(r),r.mode=20,6!==t)break;y>>>=2,w-=2;break e;case 2:r.mode=17;break;case 3:e.msg="invalid block type",r.mode=30}y>>>=2,w-=2;break;case 14:for(y>>>=7&w,w-=7&w;w<32;){if(0===b)break e;b--,y+=d[_++]<<w,w+=8}if((65535&y)!=(y>>>16^65535)){e.msg="invalid stored block lengths",r.mode=30;break}if(r.length=65535&y,w=y=0,r.mode=15,6===t)break e;case 15:r.mode=16;case 16:if(C=r.length){if(b<C&&(C=b),v<C&&(C=v),0===C)break e;n.arraySet(p,d,_,C,g),b-=C,_+=C,v-=C,g+=C,r.length-=C;break}r.mode=12;break;case 17:for(;w<14;){if(0===b)break e;b--,y+=d[_++]<<w,w+=8}if(r.nlen=257+(31&y),y>>>=5,w-=5,r.ndist=1+(31&y),y>>>=5,w-=5,r.ncode=4+(15&y),y>>>=4,w-=4,286<r.nlen||30<r.ndist){e.msg="too many length or distance symbols",r.mode=30;break}r.have=0,r.mode=18;case 18:for(;r.have<r.ncode;){for(;w<3;){if(0===b)break e;b--,y+=d[_++]<<w,w+=8}r.lens[Z[r.have++]]=7&y,y>>>=3,w-=3}for(;r.have<19;)r.lens[Z[r.have++]]=0;if(r.lencode=r.lendyn,r.lenbits=7,U={bits:r.lenbits},N=o(0,r.lens,0,19,r.lencode,0,r.work,U),r.lenbits=U.bits,N){e.msg="invalid code lengths set",r.mode=30;break}r.have=0,r.mode=19;case 19:for(;r.have<r.nlen+r.ndist;){for(;O=(L=r.lencode[y&(1<<r.lenbits)-1])>>>16&255,B=65535&L,!((I=L>>>24)<=w);){if(0===b)break e;b--,y+=d[_++]<<w,w+=8}if(B<16)y>>>=I,w-=I,r.lens[r.have++]=B;else{if(16===B){for(P=I+2;w<P;){if(0===b)break e;b--,y+=d[_++]<<w,w+=8}if(y>>>=I,w-=I,0===r.have){e.msg="invalid bit length repeat",r.mode=30;break}F=r.lens[r.have-1],C=3+(3&y),y>>>=2,w-=2}else if(17===B){for(P=I+3;w<P;){if(0===b)break e;b--,y+=d[_++]<<w,w+=8}w-=I,F=0,C=3+(7&(y>>>=I)),y>>>=3,w-=3}else{for(P=I+7;w<P;){if(0===b)break e;b--,y+=d[_++]<<w,w+=8}w-=I,F=0,C=11+(127&(y>>>=I)),y>>>=7,w-=7}if(r.have+C>r.nlen+r.ndist){e.msg="invalid bit length repeat",r.mode=30;break}for(;C--;)r.lens[r.have++]=F}}if(30===r.mode)break;if(0===r.lens[256]){e.msg="invalid code -- missing end-of-block",r.mode=30;break}if(r.lenbits=9,U={bits:r.lenbits},N=o(h,r.lens,0,r.nlen,r.lencode,0,r.work,U),r.lenbits=U.bits,N){e.msg="invalid literal/lengths set",r.mode=30;break}if(r.distbits=6,r.distcode=r.distdyn,U={bits:r.distbits},N=o(u,r.lens,r.nlen,r.ndist,r.distcode,0,r.work,U),r.distbits=U.bits,N){e.msg="invalid distances set",r.mode=30;break}if(r.mode=20,6===t)break e;case 20:r.mode=21;case 21:if(6<=b&&258<=v){e.next_out=g,e.avail_out=v,e.next_in=_,e.avail_in=b,r.hold=y,r.bits=w,a(e,x),g=e.next_out,p=e.output,v=e.avail_out,_=e.next_in,d=e.input,b=e.avail_in,y=r.hold,w=r.bits,12===r.mode&&(r.back=-1);break}for(r.back=0;O=(L=r.lencode[y&(1<<r.lenbits)-1])>>>16&255,B=65535&L,!((I=L>>>24)<=w);){if(0===b)break e;b--,y+=d[_++]<<w,w+=8}if(O&&0==(240&O)){for(R=I,T=O,D=B;O=(L=r.lencode[D+((y&(1<<R+T)-1)>>R)])>>>16&255,B=65535&L,!(R+(I=L>>>24)<=w);){if(0===b)break e;b--,y+=d[_++]<<w,w+=8}y>>>=R,w-=R,r.back+=R}if(y>>>=I,w-=I,r.back+=I,r.length=B,0===O){r.mode=26;break}if(32&O){r.back=-1,r.mode=12;break}if(64&O){e.msg="invalid literal/length code",r.mode=30;break}r.extra=15&O,r.mode=22;case 22:if(r.extra){for(P=r.extra;w<P;){if(0===b)break e;b--,y+=d[_++]<<w,w+=8}r.length+=y&(1<<r.extra)-1,y>>>=r.extra,w-=r.extra,r.back+=r.extra}r.was=r.length,r.mode=23;case 23:for(;O=(L=r.distcode[y&(1<<r.distbits)-1])>>>16&255,B=65535&L,!((I=L>>>24)<=w);){if(0===b)break e;b--,y+=d[_++]<<w,w+=8}if(0==(240&O)){for(R=I,T=O,D=B;O=(L=r.distcode[D+((y&(1<<R+T)-1)>>R)])>>>16&255,B=65535&L,!(R+(I=L>>>24)<=w);){if(0===b)break e;b--,y+=d[_++]<<w,w+=8}y>>>=R,w-=R,r.back+=R}if(y>>>=I,w-=I,r.back+=I,64&O){e.msg="invalid distance code",r.mode=30;break}r.offset=B,r.extra=15&O,r.mode=24;case 24:if(r.extra){for(P=r.extra;w<P;){if(0===b)break e;b--,y+=d[_++]<<w,w+=8}r.offset+=y&(1<<r.extra)-1,y>>>=r.extra,w-=r.extra,r.back+=r.extra}if(r.offset>r.dmax){e.msg="invalid distance too far back",r.mode=30;break}r.mode=25;case 25:if(0===v)break e;if(C=x-v,r.offset>C){if((C=r.offset-C)>r.whave&&r.sane){e.msg="invalid distance too far back",r.mode=30;break}E=C>r.wnext?(C-=r.wnext,r.wsize-C):r.wnext-C,C>r.length&&(C=r.length),A=r.window}else A=p,E=g-r.offset,C=r.length;for(v<C&&(C=v),v-=C,r.length-=C;p[g++]=A[E++],--C;);0===r.length&&(r.mode=21);break;case 26:if(0===v)break e;p[g++]=r.length,v--,r.mode=21;break;case 27:if(r.wrap){for(;w<32;){if(0===b)break e;b--,y|=d[_++]<<w,w+=8}if(x-=v,e.total_out+=x,r.total+=x,x&&(e.adler=r.check=r.flags?s(r.check,p,x,g-x):i(r.check,p,x,g-x)),x=v,(r.flags?y:m(y))!==r.check){e.msg="incorrect data check",r.mode=30;break}w=y=0}r.mode=28;case 28:if(r.wrap&&r.flags){for(;w<32;){if(0===b)break e;b--,y+=d[_++]<<w,w+=8}if(y!==(4294967295&r.total)){e.msg="incorrect length check",r.mode=30;break}w=y=0}r.mode=29;case 29:N=1;break e;case 30:N=-3;break e;case 31:return-4;case 32:default:return f}return e.next_out=g,e.avail_out=v,e.next_in=_,e.avail_in=b,r.hold=y,r.bits=w,(r.wsize||x!==e.avail_out&&r.mode<30&&(r.mode<27||4!==t))&&z(e,e.output,e.next_out,x-e.avail_out)?(r.mode=31,-4):(k-=e.avail_in,x-=e.avail_out,e.total_in+=k,e.total_out+=x,r.total+=x,r.wrap&&x&&(e.adler=r.check=r.flags?s(r.check,p,x,e.next_out-x):i(r.check,p,x,e.next_out-x)),e.data_type=r.bits+(r.last?64:0)+(12===r.mode?128:0)+(20===r.mode||15===r.mode?256:0),(0==k&&0===x||4===t)&&N===l&&(N=-5),N)},r.inflateEnd=function(e){if(!e||!e.state)return f;var t=e.state;return t.window&&(t.window=null),e.state=null,l},r.inflateGetHeader=function(e,t){var r;return e&&e.state?0==(2&(r=e.state).wrap)?f:((r.head=t).done=!1,l):f},r.inflateSetDictionary=function(e,t){var r,n=t.length;return e&&e.state?0!==(r=e.state).wrap&&11!==r.mode?f:11===r.mode&&i(1,t,n,0)!==r.check?-3:z(e,t,n,n)?(r.mode=31,-4):(r.havedict=1,l):f},r.inflateInfo="pako inflate (from Nodeca project)"},{"../utils/common":41,"./adler32":43,"./crc32":45,"./inffast":48,"./inftrees":50}],50:[function(e,t,r){"use strict";var n=e("../utils/common"),i=[3,4,5,6,7,8,9,10,11,13,15,17,19,23,27,31,35,43,51,59,67,83,99,115,131,163,195,227,258,0,0],s=[16,16,16,16,16,16,16,16,17,17,17,17,18,18,18,18,19,19,19,19,20,20,20,20,21,21,21,21,16,72,78],a=[1,2,3,4,5,7,9,13,17,25,33,49,65,97,129,193,257,385,513,769,1025,1537,2049,3073,4097,6145,8193,12289,16385,24577,0,0],o=[16,16,16,16,17,17,18,18,19,19,20,20,21,21,22,22,23,23,24,24,25,25,26,26,27,27,28,28,29,29,64,64];t.exports=function(e,t,r,h,u,l,f,c){var d,p,m,_,g,b,v,y,w,k=c.bits,x=0,S=0,z=0,C=0,E=0,A=0,I=0,O=0,B=0,R=0,T=null,D=0,F=new n.Buf16(16),N=new n.Buf16(16),U=null,P=0;for(x=0;x<=15;x++)F[x]=0;for(S=0;S<h;S++)F[t[r+S]]++;for(E=k,C=15;1<=C&&0===F[C];C--);if(C<E&&(E=C),0===C)return u[l++]=20971520,u[l++]=20971520,c.bits=1,0;for(z=1;z<C&&0===F[z];z++);for(E<z&&(E=z),x=O=1;x<=15;x++)if(O<<=1,(O-=F[x])<0)return-1;if(0<O&&(0===e||1!==C))return-1;for(N[1]=0,x=1;x<15;x++)N[x+1]=N[x]+F[x];for(S=0;S<h;S++)0!==t[r+S]&&(f[N[t[r+S]]++]=S);if(b=0===e?(T=U=f,19):1===e?(T=i,D-=257,U=s,P-=257,256):(T=a,U=o,-1),x=z,g=l,I=S=R=0,m=-1,_=(B=1<<(A=E))-1,1===e&&852<B||2===e&&592<B)return 1;for(;;){for(v=x-I,w=f[S]<b?(y=0,f[S]):f[S]>b?(y=U[P+f[S]],T[D+f[S]]):(y=96,0),d=1<<x-I,z=p=1<<A;u[g+(R>>I)+(p-=d)]=v<<24|y<<16|w,0!==p;);for(d=1<<x-1;R&d;)d>>=1;if(0!==d?(R&=d-1,R+=d):R=0,S++,0==--F[x]){if(x===C)break;x=t[r+f[S]]}if(E<x&&(R&_)!==m){for(0===I&&(I=E),g+=z,O=1<<(A=x-I);A+I<C&&!((O-=F[A+I])<=0);)A++,O<<=1;if(B+=1<<A,1===e&&852<B||2===e&&592<B)return 1;u[m=R&_]=E<<24|A<<16|g-l}}return 0!==R&&(u[g+R]=x-I<<24|64<<16),c.bits=E,0}},{"../utils/common":41}],51:[function(e,t,r){"use strict";t.exports={2:"need dictionary",1:"stream end",0:"","-1":"file error","-2":"stream error","-3":"data error","-4":"insufficient memory","-5":"buffer error","-6":"incompatible version"}},{}],52:[function(e,t,r){"use strict";var n=e("../utils/common"),i=0,s=1;function a(e){for(var t=e.length;0<=--t;)e[t]=0}var o=0,h=29,u=256,l=u+1+h,f=30,c=19,d=2*l+1,p=15,m=16,_=7,g=256,b=16,v=17,y=18,w=[0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0],k=[0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13],x=[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,3,7],S=[16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15],z=new Array(2*(l+2));a(z);var C=new Array(2*f);a(C);var E=new Array(512);a(E);var A=new Array(256);a(A);var I=new Array(h);a(I);var O,B,R,T=new Array(f);function D(e,t,r,n,i){this.static_tree=e,this.extra_bits=t,this.extra_base=r,this.elems=n,this.max_length=i,this.has_stree=e&&e.length}function F(e,t){this.dyn_tree=e,this.max_code=0,this.stat_desc=t}function N(e){return e<256?E[e]:E[256+(e>>>7)]}function U(e,t){e.pending_buf[e.pending++]=255&t,e.pending_buf[e.pending++]=t>>>8&255}function P(e,t,r){e.bi_valid>m-r?(e.bi_buf|=t<<e.bi_valid&65535,U(e,e.bi_buf),e.bi_buf=t>>m-e.bi_valid,e.bi_valid+=r-m):(e.bi_buf|=t<<e.bi_valid&65535,e.bi_valid+=r)}function L(e,t,r){P(e,r[2*t],r[2*t+1])}function j(e,t){for(var r=0;r|=1&e,e>>>=1,r<<=1,0<--t;);return r>>>1}function Z(e,t,r){var n,i,s=new Array(p+1),a=0;for(n=1;n<=p;n++)s[n]=a=a+r[n-1]<<1;for(i=0;i<=t;i++){var o=e[2*i+1];0!==o&&(e[2*i]=j(s[o]++,o))}}function W(e){var t;for(t=0;t<l;t++)e.dyn_ltree[2*t]=0;for(t=0;t<f;t++)e.dyn_dtree[2*t]=0;for(t=0;t<c;t++)e.bl_tree[2*t]=0;e.dyn_ltree[2*g]=1,e.opt_len=e.static_len=0,e.last_lit=e.matches=0}function M(e){8<e.bi_valid?U(e,e.bi_buf):0<e.bi_valid&&(e.pending_buf[e.pending++]=e.bi_buf),e.bi_buf=0,e.bi_valid=0}function H(e,t,r,n){var i=2*t,s=2*r;return e[i]<e[s]||e[i]===e[s]&&n[t]<=n[r]}function G(e,t,r){for(var n=e.heap[r],i=r<<1;i<=e.heap_len&&(i<e.heap_len&&H(t,e.heap[i+1],e.heap[i],e.depth)&&i++,!H(t,n,e.heap[i],e.depth));)e.heap[r]=e.heap[i],r=i,i<<=1;e.heap[r]=n}function K(e,t,r){var n,i,s,a,o=0;if(0!==e.last_lit)for(;n=e.pending_buf[e.d_buf+2*o]<<8|e.pending_buf[e.d_buf+2*o+1],i=e.pending_buf[e.l_buf+o],o++,0===n?L(e,i,t):(L(e,(s=A[i])+u+1,t),0!==(a=w[s])&&P(e,i-=I[s],a),L(e,s=N(--n),r),0!==(a=k[s])&&P(e,n-=T[s],a)),o<e.last_lit;);L(e,g,t)}function Y(e,t){var r,n,i,s=t.dyn_tree,a=t.stat_desc.static_tree,o=t.stat_desc.has_stree,h=t.stat_desc.elems,u=-1;for(e.heap_len=0,e.heap_max=d,r=0;r<h;r++)0!==s[2*r]?(e.heap[++e.heap_len]=u=r,e.depth[r]=0):s[2*r+1]=0;for(;e.heap_len<2;)s[2*(i=e.heap[++e.heap_len]=u<2?++u:0)]=1,e.depth[i]=0,e.opt_len--,o&&(e.static_len-=a[2*i+1]);for(t.max_code=u,r=e.heap_len>>1;1<=r;r--)G(e,s,r);for(i=h;r=e.heap[1],e.heap[1]=e.heap[e.heap_len--],G(e,s,1),n=e.heap[1],e.heap[--e.heap_max]=r,e.heap[--e.heap_max]=n,s[2*i]=s[2*r]+s[2*n],e.depth[i]=(e.depth[r]>=e.depth[n]?e.depth[r]:e.depth[n])+1,s[2*r+1]=s[2*n+1]=i,e.heap[1]=i++,G(e,s,1),2<=e.heap_len;);e.heap[--e.heap_max]=e.heap[1],function(e,t){var r,n,i,s,a,o,h=t.dyn_tree,u=t.max_code,l=t.stat_desc.static_tree,f=t.stat_desc.has_stree,c=t.stat_desc.extra_bits,m=t.stat_desc.extra_base,_=t.stat_desc.max_length,g=0;for(s=0;s<=p;s++)e.bl_count[s]=0;for(h[2*e.heap[e.heap_max]+1]=0,r=e.heap_max+1;r<d;r++)_<(s=h[2*h[2*(n=e.heap[r])+1]+1]+1)&&(s=_,g++),h[2*n+1]=s,u<n||(e.bl_count[s]++,a=0,m<=n&&(a=c[n-m]),o=h[2*n],e.opt_len+=o*(s+a),f&&(e.static_len+=o*(l[2*n+1]+a)));if(0!==g){do{for(s=_-1;0===e.bl_count[s];)s--;e.bl_count[s]--,e.bl_count[s+1]+=2,e.bl_count[_]--,g-=2}while(0<g);for(s=_;0!==s;s--)for(n=e.bl_count[s];0!==n;)u<(i=e.heap[--r])||(h[2*i+1]!==s&&(e.opt_len+=(s-h[2*i+1])*h[2*i],h[2*i+1]=s),n--)}}(e,t),Z(s,u,e.bl_count)}function X(e,t,r){var n,i,s=-1,a=t[1],o=0,h=7,u=4;for(0===a&&(h=138,u=3),t[2*(r+1)+1]=65535,n=0;n<=r;n++)i=a,a=t[2*(n+1)+1],++o<h&&i===a||(o<u?e.bl_tree[2*i]+=o:0!==i?(i!==s&&e.bl_tree[2*i]++,e.bl_tree[2*b]++):o<=10?e.bl_tree[2*v]++:e.bl_tree[2*y]++,s=i,u=(o=0)===a?(h=138,3):i===a?(h=6,3):(h=7,4))}function V(e,t,r){var n,i,s=-1,a=t[1],o=0,h=7,u=4;for(0===a&&(h=138,u=3),n=0;n<=r;n++)if(i=a,a=t[2*(n+1)+1],!(++o<h&&i===a)){if(o<u)for(;L(e,i,e.bl_tree),0!=--o;);else 0!==i?(i!==s&&(L(e,i,e.bl_tree),o--),L(e,b,e.bl_tree),P(e,o-3,2)):o<=10?(L(e,v,e.bl_tree),P(e,o-3,3)):(L(e,y,e.bl_tree),P(e,o-11,7));s=i,u=(o=0)===a?(h=138,3):i===a?(h=6,3):(h=7,4)}}a(T);var q=!1;function J(e,t,r,i){P(e,(o<<1)+(i?1:0),3),function(e,t,r,i){M(e),i&&(U(e,r),U(e,~r)),n.arraySet(e.pending_buf,e.window,t,r,e.pending),e.pending+=r}(e,t,r,!0)}r._tr_init=function(e){q||(function(){var e,t,r,n,i,s=new Array(p+1);for(n=r=0;n<h-1;n++)for(I[n]=r,e=0;e<1<<w[n];e++)A[r++]=n;for(A[r-1]=n,n=i=0;n<16;n++)for(T[n]=i,e=0;e<1<<k[n];e++)E[i++]=n;for(i>>=7;n<f;n++)for(T[n]=i<<7,e=0;e<1<<k[n]-7;e++)E[256+i++]=n;for(t=0;t<=p;t++)s[t]=0;for(e=0;e<=143;)z[2*e+1]=8,e++,s[8]++;for(;e<=255;)z[2*e+1]=9,e++,s[9]++;for(;e<=279;)z[2*e+1]=7,e++,s[7]++;for(;e<=287;)z[2*e+1]=8,e++,s[8]++;for(Z(z,l+1,s),e=0;e<f;e++)C[2*e+1]=5,C[2*e]=j(e,5);O=new D(z,w,u+1,l,p),B=new D(C,k,0,f,p),R=new D(new Array(0),x,0,c,_)}(),q=!0),e.l_desc=new F(e.dyn_ltree,O),e.d_desc=new F(e.dyn_dtree,B),e.bl_desc=new F(e.bl_tree,R),e.bi_buf=0,e.bi_valid=0,W(e)},r._tr_stored_block=J,r._tr_flush_block=function(e,t,r,n){var a,o,h=0;0<e.level?(2===e.strm.data_type&&(e.strm.data_type=function(e){var t,r=4093624447;for(t=0;t<=31;t++,r>>>=1)if(1&r&&0!==e.dyn_ltree[2*t])return i;if(0!==e.dyn_ltree[18]||0!==e.dyn_ltree[20]||0!==e.dyn_ltree[26])return s;for(t=32;t<u;t++)if(0!==e.dyn_ltree[2*t])return s;return i}(e)),Y(e,e.l_desc),Y(e,e.d_desc),h=function(e){var t;for(X(e,e.dyn_ltree,e.l_desc.max_code),X(e,e.dyn_dtree,e.d_desc.max_code),Y(e,e.bl_desc),t=c-1;3<=t&&0===e.bl_tree[2*S[t]+1];t--);return e.opt_len+=3*(t+1)+5+5+4,t}(e),a=e.opt_len+3+7>>>3,(o=e.static_len+3+7>>>3)<=a&&(a=o)):a=o=r+5,r+4<=a&&-1!==t?J(e,t,r,n):4===e.strategy||o===a?(P(e,2+(n?1:0),3),K(e,z,C)):(P(e,4+(n?1:0),3),function(e,t,r,n){var i;for(P(e,t-257,5),P(e,r-1,5),P(e,n-4,4),i=0;i<n;i++)P(e,e.bl_tree[2*S[i]+1],3);V(e,e.dyn_ltree,t-1),V(e,e.dyn_dtree,r-1)}(e,e.l_desc.max_code+1,e.d_desc.max_code+1,h+1),K(e,e.dyn_ltree,e.dyn_dtree)),W(e),n&&M(e)},r._tr_tally=function(e,t,r){return e.pending_buf[e.d_buf+2*e.last_lit]=t>>>8&255,e.pending_buf[e.d_buf+2*e.last_lit+1]=255&t,e.pending_buf[e.l_buf+e.last_lit]=255&r,e.last_lit++,0===t?e.dyn_ltree[2*r]++:(e.matches++,t--,e.dyn_ltree[2*(A[r]+u+1)]++,e.dyn_dtree[2*N(t)]++),e.last_lit===e.lit_bufsize-1},r._tr_align=function(e){P(e,2,3),L(e,g,z),function(e){16===e.bi_valid?(U(e,e.bi_buf),e.bi_buf=0,e.bi_valid=0):8<=e.bi_valid&&(e.pending_buf[e.pending++]=255&e.bi_buf,e.bi_buf>>=8,e.bi_valid-=8)}(e)}},{"../utils/common":41}],53:[function(e,t,r){"use strict";t.exports=function(){this.input=null,this.next_in=0,this.avail_in=0,this.total_in=0,this.output=null,this.next_out=0,this.avail_out=0,this.total_out=0,this.msg="",this.state=null,this.data_type=2,this.adler=0}},{}],54:[function(e,t,n){(function(e){!function(e,t){"use strict";if(!e.setImmediate){var r,n,i,s,a=1,o={},h=!1,u=e.document,l=Object.getPrototypeOf&&Object.getPrototypeOf(e);l=l&&l.setTimeout?l:e,r="[object process]"==={}.toString.call(e.process)?function(e){process.nextTick(function(){c(e)})}:function(){if(e.postMessage&&!e.importScripts){var t=!0,r=e.onmessage;return e.onmessage=function(){t=!1},e.postMessage("","*"),e.onmessage=r,t}}()?(s="setImmediate$"+Math.random()+"$",e.addEventListener?e.addEventListener("message",d,!1):e.attachEvent("onmessage",d),function(t){e.postMessage(s+t,"*")}):e.MessageChannel?((i=new MessageChannel).port1.onmessage=function(e){c(e.data)},function(e){i.port2.postMessage(e)}):u&&"onreadystatechange"in u.createElement("script")?(n=u.documentElement,function(e){var t=u.createElement("script");t.onreadystatechange=function(){c(e),t.onreadystatechange=null,n.removeChild(t),t=null},n.appendChild(t)}):function(e){setTimeout(c,0,e)},l.setImmediate=function(e){"function"!=typeof e&&(e=new Function(""+e));for(var t=new Array(arguments.length-1),n=0;n<t.length;n++)t[n]=arguments[n+1];var i={callback:e,args:t};return o[a]=i,r(a),a++},l.clearImmediate=f}function f(e){delete o[e]}function c(e){if(h)setTimeout(c,0,e);else{var r=o[e];if(r){h=!0;try{!function(e){var r=e.callback,n=e.args;switch(n.length){case 0:r();break;case 1:r(n[0]);break;case 2:r(n[0],n[1]);break;case 3:r(n[0],n[1],n[2]);break;default:r.apply(t,n)}}(r)}finally{f(e),h=!1}}}}function d(t){t.source===e&&"string"==typeof t.data&&0===t.data.indexOf(s)&&c(+t.data.slice(s.length))}}("undefined"==typeof self?void 0===e?this:e:self)}).call(this,"undefined"!=typeof r.g?r.g:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{})},{}]},{},[10])(10)})}}]);(self["webpackChunkcontao_manager"]=self["webpackChunkcontao_manager"]||[]).push([[504],{953:function(e,t,n){"use strict";n.d(t,{BA:function(){return He},C4:function(){return A},EW:function(){return tt},Gc:function(){return ke},IG:function(){return Pe},IJ:function(){return je},KR:function(){return $e},Kh:function(){return Te},PP:function(){return rt},Pr:function(){return Xe},QW:function(){return ze},QZ:function(){return T},R1:function(){return Ge},Tm:function(){return Ie},Ul:function(){return nt},X2:function(){return d},Yv:function(){return at},a1:function(){return Me},bl:function(){return R},ch:function(){return lt},ds:function(){return k},fE:function(){return Ne},g8:function(){return Re},hV:function(){return ct},hZ:function(){return U},i9:function(){return Fe},jr:function(){return u},ju:function(){return Le},lJ:function(){return De},lW:function(){return Je},mu:function(){return Ve},nD:function(){return Oe},o5:function(){return l},qA:function(){return G},rY:function(){return qe},tB:function(){return Ce},u4:function(){return j},uY:function(){return a},ux:function(){return xe},wB:function(){return ut},yC:function(){return s}});var r=n(33);
/**
* @vue/reactivity v3.5.32
* (c) 2018-present Yuxi (Evan) You and Vue contributors
* @license MIT
**/let o,i;class s{constructor(e=!1){this.detached=e,this._active=!0,this._on=0,this.effects=[],this.cleanups=[],this._isPaused=!1,this.__v_skip=!0,this.parent=o,!e&&o&&(this.index=(o.scopes||(o.scopes=[])).push(this)-1)}get active(){return this._active}pause(){if(this._active){let e,t;if(this._isPaused=!0,this.scopes)for(e=0,t=this.scopes.length;e<t;e++)this.scopes[e].pause();for(e=0,t=this.effects.length;e<t;e++)this.effects[e].pause()}}resume(){if(this._active&&this._isPaused){let e,t;if(this._isPaused=!1,this.scopes)for(e=0,t=this.scopes.length;e<t;e++)this.scopes[e].resume();for(e=0,t=this.effects.length;e<t;e++)this.effects[e].resume()}}run(e){if(this._active){const t=o;try{return o=this,e()}finally{o=t}}else 0}on(){1===++this._on&&(this.prevScope=o,o=this)}off(){this._on>0&&0===--this._on&&(o=this.prevScope,this.prevScope=void 0)}stop(e){if(this._active){let t,n;for(this._active=!1,t=0,n=this.effects.length;t<n;t++)this.effects[t].stop();for(this.effects.length=0,t=0,n=this.cleanups.length;t<n;t++)this.cleanups[t]();if(this.cleanups.length=0,this.scopes){for(t=0,n=this.scopes.length;t<n;t++)this.scopes[t].stop(!0);this.scopes.length=0}if(!this.detached&&this.parent&&!e){const e=this.parent.scopes.pop();e&&e!==this&&(this.parent.scopes[this.index]=e,e.index=this.index)}this.parent=void 0}}}function a(e){return new s(e)}function l(){return o}function u(e,t=!1){o&&o.cleanups.push(e)}const c=new WeakSet;class d{constructor(e){this.fn=e,this.deps=void 0,this.depsTail=void 0,this.flags=5,this.next=void 0,this.cleanup=void 0,this.scheduler=void 0,o&&o.active&&o.effects.push(this)}pause(){this.flags|=64}resume(){64&this.flags&&(this.flags&=-65,c.has(this)&&(c.delete(this),this.trigger()))}notify(){2&this.flags&&!(32&this.flags)||8&this.flags||m(this)}run(){if(!(1&this.flags))return this.fn();this.flags|=2,I(this),y(this);const e=i,t=C;i=this,C=!0;try{return this.fn()}finally{0,b(this),i=e,C=t,this.flags&=-3}}stop(){if(1&this.flags){for(let e=this.deps;e;e=e.nextDep)w(e);this.deps=this.depsTail=void 0,I(this),this.onStop&&this.onStop(),this.flags&=-2}}trigger(){64&this.flags?c.add(this):this.scheduler?this.scheduler():this.runIfDirty()}runIfDirty(){_(this)&&this.run()}get dirty(){return _(this)}}let f,h,p=0;function m(e,t=!1){if(e.flags|=8,t)return e.next=h,void(h=e);e.next=f,f=e}function v(){p++}function g(){if(--p>0)return;if(h){let e=h;h=void 0;while(e){const t=e.next;e.next=void 0,e.flags&=-9,e=t}}let e;while(f){let n=f;f=void 0;while(n){const r=n.next;if(n.next=void 0,n.flags&=-9,1&n.flags)try{n.trigger()}catch(t){e||(e=t)}n=r}}if(e)throw e}function y(e){for(let t=e.deps;t;t=t.nextDep)t.version=-1,t.prevActiveLink=t.dep.activeLink,t.dep.activeLink=t}function b(e){let t,n=e.depsTail,r=n;while(r){const e=r.prevDep;-1===r.version?(r===n&&(n=e),w(r),S(r)):t=r,r.dep.activeLink=r.prevActiveLink,r.prevActiveLink=void 0,r=e}e.deps=t,e.depsTail=n}function _(e){for(let t=e.deps;t;t=t.nextDep)if(t.dep.version!==t.version||t.dep.computed&&(E(t.dep.computed)||t.dep.version!==t.version))return!0;return!!e._dirty}function E(e){if(4&e.flags&&!(16&e.flags))return;if(e.flags&=-17,e.globalVersion===N)return;if(e.globalVersion=N,!e.isSSR&&128&e.flags&&(!e.deps&&!e._dirty||!_(e)))return;e.flags|=2;const t=e.dep,n=i,o=C;i=e,C=!0;try{y(e);const n=e.fn(e._value);(0===t.version||(0,r.$H)(n,e._value))&&(e.flags|=128,e._value=n,t.version++)}catch(s){throw t.version++,s}finally{i=n,C=o,b(e),e.flags&=-3}}function w(e,t=!1){const{dep:n,prevSub:r,nextSub:o}=e;if(r&&(r.nextSub=o,e.prevSub=void 0),o&&(o.prevSub=r,e.nextSub=void 0),n.subs===e&&(n.subs=r,!r&&n.computed)){n.computed.flags&=-5;for(let e=n.computed.deps;e;e=e.nextDep)w(e,!0)}t||--n.sc||!n.map||n.map.delete(n.key)}function S(e){const{prevDep:t,nextDep:n}=e;t&&(t.nextDep=n,e.prevDep=void 0),n&&(n.prevDep=t,e.nextDep=void 0)}function T(e,t){e.effect instanceof d&&(e=e.effect.fn);const n=new d(e);t&&(0,r.X$)(n,t);try{n.run()}catch(i){throw n.stop(),i}const o=n.run.bind(n);return o.effect=n,o}function k(e){e.effect.stop()}let C=!0;const O=[];function A(){O.push(C),C=!1}function R(){const e=O.pop();C=void 0===e||e}function I(e){const{cleanup:t}=e;if(e.cleanup=void 0,t){const e=i;i=void 0;try{t()}finally{i=e}}}let N=0;class L{constructor(e,t){this.sub=e,this.dep=t,this.version=t.version,this.nextDep=this.prevDep=this.nextSub=this.prevSub=this.prevActiveLink=void 0}}class x{constructor(e){this.computed=e,this.version=0,this.activeLink=void 0,this.subs=void 0,this.map=void 0,this.key=void 0,this.sc=0,this.__v_skip=!0}track(e){if(!i||!C||i===this.computed)return;let t=this.activeLink;if(void 0===t||t.sub!==i)t=this.activeLink=new L(i,this),i.deps?(t.prevDep=i.depsTail,i.depsTail.nextDep=t,i.depsTail=t):i.deps=i.depsTail=t,P(t);else if(-1===t.version&&(t.version=this.version,t.nextDep)){const e=t.nextDep;e.prevDep=t.prevDep,t.prevDep&&(t.prevDep.nextDep=e),t.prevDep=i.depsTail,t.nextDep=void 0,i.depsTail.nextDep=t,i.depsTail=t,i.deps===t&&(i.deps=e)}return t}trigger(e){this.version++,N++,this.notify(e)}notify(e){v();try{0;for(let e=this.subs;e;e=e.prevSub)e.sub.notify()&&e.sub.dep.notify()}finally{g()}}}function P(e){if(e.dep.sc++,4&e.sub.flags){const t=e.dep.computed;if(t&&!e.dep.subs){t.flags|=20;for(let e=t.deps;e;e=e.nextDep)P(e)}const n=e.dep.subs;n!==e&&(e.prevSub=n,n&&(n.nextSub=e)),e.dep.subs=e}}const D=new WeakMap,M=Symbol(""),F=Symbol(""),$=Symbol("");function j(e,t,n){if(C&&i){let t=D.get(e);t||D.set(e,t=new Map);let r=t.get(n);r||(t.set(n,r=new x),r.map=t,r.key=n),r.track()}}function U(e,t,n,o,i,s){const a=D.get(e);if(!a)return void N++;const l=e=>{e&&e.trigger()};if(v(),"clear"===t)a.forEach(l);else{const i=(0,r.cy)(e),s=i&&(0,r.yI)(n);if(i&&"length"===n){const e=Number(o);a.forEach((t,n)=>{("length"===n||n===$||!(0,r.Bm)(n)&&n>=e)&&l(t)})}else switch((void 0!==n||a.has(void 0))&&l(a.get(n)),s&&l(a.get($)),t){case"add":i?s&&l(a.get("length")):(l(a.get(M)),(0,r.CE)(e)&&l(a.get(F)));break;case"delete":i||(l(a.get(M)),(0,r.CE)(e)&&l(a.get(F)));break;case"set":(0,r.CE)(e)&&l(a.get(M));break}}g()}function B(e,t){const n=D.get(e);return n&&n.get(t)}function V(e){const t=xe(e);return t===e?t:(j(t,"iterate",$),Ne(e)?t:t.map(De))}function G(e){return j(e=xe(e),"iterate",$),e}function H(e,t){return Ie(e)?Re(e)?Me(De(t)):Me(t):De(t)}const W={__proto__:null,[Symbol.iterator](){return X(this,Symbol.iterator,e=>H(this,e))},concat(...e){return V(this).concat(...e.map(e=>(0,r.cy)(e)?V(e):e))},entries(){return X(this,"entries",e=>(e[1]=H(this,e[1]),e))},every(e,t){return q(this,"every",e,t,void 0,arguments)},filter(e,t){return q(this,"filter",e,t,e=>e.map(e=>H(this,e)),arguments)},find(e,t){return q(this,"find",e,t,e=>H(this,e),arguments)},findIndex(e,t){return q(this,"findIndex",e,t,void 0,arguments)},findLast(e,t){return q(this,"findLast",e,t,e=>H(this,e),arguments)},findLastIndex(e,t){return q(this,"findLastIndex",e,t,void 0,arguments)},forEach(e,t){return q(this,"forEach",e,t,void 0,arguments)},includes(...e){return Y(this,"includes",e)},indexOf(...e){return Y(this,"indexOf",e)},join(e){return V(this).join(e)},lastIndexOf(...e){return Y(this,"lastIndexOf",e)},map(e,t){return q(this,"map",e,t,void 0,arguments)},pop(){return Q(this,"pop")},push(...e){return Q(this,"push",e)},reduce(e,...t){return z(this,"reduce",e,t)},reduceRight(e,...t){return z(this,"reduceRight",e,t)},shift(){return Q(this,"shift")},some(e,t){return q(this,"some",e,t,void 0,arguments)},splice(...e){return Q(this,"splice",e)},toReversed(){return V(this).toReversed()},toSorted(e){return V(this).toSorted(e)},toSpliced(...e){return V(this).toSpliced(...e)},unshift(...e){return Q(this,"unshift",e)},values(){return X(this,"values",e=>H(this,e))}};function X(e,t,n){const r=G(e),o=r[t]();return r===e||Ne(e)||(o._next=o.next,o.next=()=>{const e=o._next();return e.done||(e.value=n(e.value)),e}),o}const K=Array.prototype;function q(e,t,n,r,o,i){const s=G(e),a=s!==e&&!Ne(e),l=s[t];if(l!==K[t]){const t=l.apply(e,i);return a?De(t):t}let u=n;s!==e&&(a?u=function(t,r){return n.call(this,H(e,t),r,e)}:n.length>2&&(u=function(t,r){return n.call(this,t,r,e)}));const c=l.call(s,u,r);return a&&o?o(c):c}function z(e,t,n,r){const o=G(e),i=o!==e&&!Ne(e);let s=n,a=!1;o!==e&&(i?(a=0===r.length,s=function(t,r,o){return a&&(a=!1,t=H(e,t)),n.call(this,t,H(e,r),o,e)}):n.length>3&&(s=function(t,r,o){return n.call(this,t,r,o,e)}));const l=o[t](s,...r);return a?H(e,l):l}function Y(e,t,n){const r=xe(e);j(r,"iterate",$);const o=r[t](...n);return-1!==o&&!1!==o||!Le(n[0])?o:(n[0]=xe(n[0]),r[t](...n))}function Q(e,t,n=[]){A(),v();const r=xe(e)[t].apply(e,n);return g(),R(),r}const J=(0,r.pD)("__proto__,__v_isRef,__isVue"),Z=new Set(Object.getOwnPropertyNames(Symbol).filter(e=>"arguments"!==e&&"caller"!==e).map(e=>Symbol[e]).filter(r.Bm));function ee(e){(0,r.Bm)(e)||(e=String(e));const t=xe(this);return j(t,"has",e),t.hasOwnProperty(e)}class te{constructor(e=!1,t=!1){this._isReadonly=e,this._isShallow=t}get(e,t,n){if("__v_skip"===t)return e["__v_skip"];const o=this._isReadonly,i=this._isShallow;if("__v_isReactive"===t)return!o;if("__v_isReadonly"===t)return o;if("__v_isShallow"===t)return i;if("__v_raw"===t)return n===(o?i?Ee:_e:i?be:ye).get(e)||Object.getPrototypeOf(e)===Object.getPrototypeOf(n)?e:void 0;const s=(0,r.cy)(e);if(!o){let e;if(s&&(e=W[t]))return e;if("hasOwnProperty"===t)return ee}const a=Reflect.get(e,t,Fe(e)?e:n);if((0,r.Bm)(t)?Z.has(t):J(t))return a;if(o||j(e,"get",t),i)return a;if(Fe(a)){const e=s&&(0,r.yI)(t)?a:a.value;return o&&(0,r.Gv)(e)?Ce(e):e}return(0,r.Gv)(a)?o?Ce(a):Te(a):a}}class ne extends te{constructor(e=!1){super(!1,e)}set(e,t,n,o){let i=e[t];const s=(0,r.cy)(e)&&(0,r.yI)(t);if(!this._isShallow){const e=Ie(i);if(Ne(n)||Ie(n)||(i=xe(i),n=xe(n)),!s&&Fe(i)&&!Fe(n))return e||(i.value=n),!0}const a=s?Number(t)<e.length:(0,r.$3)(e,t),l=Reflect.set(e,t,n,Fe(e)?e:o);return e===xe(o)&&(a?(0,r.$H)(n,i)&&U(e,"set",t,n,i):U(e,"add",t,n)),l}deleteProperty(e,t){const n=(0,r.$3)(e,t),o=e[t],i=Reflect.deleteProperty(e,t);return i&&n&&U(e,"delete",t,void 0,o),i}has(e,t){const n=Reflect.has(e,t);return(0,r.Bm)(t)&&Z.has(t)||j(e,"has",t),n}ownKeys(e){return j(e,"iterate",(0,r.cy)(e)?"length":M),Reflect.ownKeys(e)}}class re extends te{constructor(e=!1){super(!0,e)}set(e,t){return!0}deleteProperty(e,t){return!0}}const oe=new ne,ie=new re,se=new ne(!0),ae=new re(!0),le=e=>e,ue=e=>Reflect.getPrototypeOf(e);function ce(e,t,n){return function(...o){const i=this["__v_raw"],s=xe(i),a=(0,r.CE)(s),l="entries"===e||e===Symbol.iterator&&a,u="keys"===e&&a,c=i[e](...o),d=n?le:t?Me:De;return!t&&j(s,"iterate",u?F:M),(0,r.X$)(Object.create(c),{next(){const{value:e,done:t}=c.next();return t?{value:e,done:t}:{value:l?[d(e[0]),d(e[1])]:d(e),done:t}}})}}function de(e){return function(...t){return"delete"!==e&&("clear"===e?void 0:this)}}function fe(e,t){const n={get(n){const o=this["__v_raw"],i=xe(o),s=xe(n);e||((0,r.$H)(n,s)&&j(i,"get",n),j(i,"get",s));const{has:a}=ue(i),l=t?le:e?Me:De;return a.call(i,n)?l(o.get(n)):a.call(i,s)?l(o.get(s)):void(o!==i&&o.get(n))},get size(){const t=this["__v_raw"];return!e&&j(xe(t),"iterate",M),t.size},has(t){const n=this["__v_raw"],o=xe(n),i=xe(t);return e||((0,r.$H)(t,i)&&j(o,"has",t),j(o,"has",i)),t===i?n.has(t):n.has(t)||n.has(i)},forEach(n,r){const o=this,i=o["__v_raw"],s=xe(i),a=t?le:e?Me:De;return!e&&j(s,"iterate",M),i.forEach((e,t)=>n.call(r,a(e),a(t),o))}};(0,r.X$)(n,e?{add:de("add"),set:de("set"),delete:de("delete"),clear:de("clear")}:{add(e){const n=xe(this),o=ue(n),i=xe(e),s=t||Ne(e)||Ie(e)?e:i,a=o.has.call(n,s)||(0,r.$H)(e,s)&&o.has.call(n,e)||(0,r.$H)(i,s)&&o.has.call(n,i);return a||(n.add(s),U(n,"add",s,s)),this},set(e,n){t||Ne(n)||Ie(n)||(n=xe(n));const o=xe(this),{has:i,get:s}=ue(o);let a=i.call(o,e);a||(e=xe(e),a=i.call(o,e));const l=s.call(o,e);return o.set(e,n),a?(0,r.$H)(n,l)&&U(o,"set",e,n,l):U(o,"add",e,n),this},delete(e){const t=xe(this),{has:n,get:r}=ue(t);let o=n.call(t,e);o||(e=xe(e),o=n.call(t,e));const i=r?r.call(t,e):void 0,s=t.delete(e);return o&&U(t,"delete",e,void 0,i),s},clear(){const e=xe(this),t=0!==e.size,n=void 0,r=e.clear();return t&&U(e,"clear",void 0,void 0,n),r}});const o=["keys","values","entries",Symbol.iterator];return o.forEach(r=>{n[r]=ce(r,e,t)}),n}function he(e,t){const n=fe(e,t);return(t,o,i)=>"__v_isReactive"===o?!e:"__v_isReadonly"===o?e:"__v_raw"===o?t:Reflect.get((0,r.$3)(n,o)&&o in t?n:t,o,i)}const pe={get:he(!1,!1)},me={get:he(!1,!0)},ve={get:he(!0,!1)},ge={get:he(!0,!0)};const ye=new WeakMap,be=new WeakMap,_e=new WeakMap,Ee=new WeakMap;function we(e){switch(e){case"Object":case"Array":return 1;case"Map":case"Set":case"WeakMap":case"WeakSet":return 2;default:return 0}}function Se(e){return e["__v_skip"]||!Object.isExtensible(e)?0:we((0,r.Zf)(e))}function Te(e){return Ie(e)?e:Ae(e,!1,oe,pe,ye)}function ke(e){return Ae(e,!1,se,me,be)}function Ce(e){return Ae(e,!0,ie,ve,_e)}function Oe(e){return Ae(e,!0,ae,ge,Ee)}function Ae(e,t,n,o,i){if(!(0,r.Gv)(e))return e;if(e["__v_raw"]&&(!t||!e["__v_isReactive"]))return e;const s=Se(e);if(0===s)return e;const a=i.get(e);if(a)return a;const l=new Proxy(e,2===s?o:n);return i.set(e,l),l}function Re(e){return Ie(e)?Re(e["__v_raw"]):!(!e||!e["__v_isReactive"])}function Ie(e){return!(!e||!e["__v_isReadonly"])}function Ne(e){return!(!e||!e["__v_isShallow"])}function Le(e){return!!e&&!!e["__v_raw"]}function xe(e){const t=e&&e["__v_raw"];return t?xe(t):e}function Pe(e){return!(0,r.$3)(e,"__v_skip")&&Object.isExtensible(e)&&(0,r.yQ)(e,"__v_skip",!0),e}const De=e=>(0,r.Gv)(e)?Te(e):e,Me=e=>(0,r.Gv)(e)?Ce(e):e;function Fe(e){return!!e&&!0===e["__v_isRef"]}function $e(e){return Ue(e,!1)}function je(e){return Ue(e,!0)}function Ue(e,t){return Fe(e)?e:new Be(e,t)}class Be{constructor(e,t){this.dep=new x,this["__v_isRef"]=!0,this["__v_isShallow"]=!1,this._rawValue=t?e:xe(e),this._value=t?e:De(e),this["__v_isShallow"]=t}get value(){return this.dep.track(),this._value}set value(e){const t=this._rawValue,n=this["__v_isShallow"]||Ne(e)||Ie(e);e=n?e:xe(e),(0,r.$H)(e,t)&&(this._rawValue=e,this._value=n?e:De(e),this.dep.trigger())}}function Ve(e){e.dep&&e.dep.trigger()}function Ge(e){return Fe(e)?e.value:e}function He(e){return(0,r.Tn)(e)?e():Ge(e)}const We={get:(e,t,n)=>"__v_raw"===t?e:Ge(Reflect.get(e,t,n)),set:(e,t,n,r)=>{const o=e[t];return Fe(o)&&!Fe(n)?(o.value=n,!0):Reflect.set(e,t,n,r)}};function Xe(e){return Re(e)?e:new Proxy(e,We)}class Ke{constructor(e){this["__v_isRef"]=!0,this._value=void 0;const t=this.dep=new x,{get:n,set:r}=e(t.track.bind(t),t.trigger.bind(t));this._get=n,this._set=r}get value(){return this._value=this._get()}set value(e){this._set(e)}}function qe(e){return new Ke(e)}function ze(e){const t=(0,r.cy)(e)?new Array(e.length):{};for(const n in e)t[n]=Ze(e,n);return t}class Ye{constructor(e,t,n){this._object=e,this._defaultValue=n,this["__v_isRef"]=!0,this._value=void 0,this._key=(0,r.Bm)(t)?t:String(t),this._raw=xe(e);let o=!0,i=e;if(!(0,r.cy)(e)||(0,r.Bm)(this._key)||!(0,r.yI)(this._key))do{o=!Le(i)||Ne(i)}while(o&&(i=i["__v_raw"]));this._shallow=o}get value(){let e=this._object[this._key];return this._shallow&&(e=Ge(e)),this._value=void 0===e?this._defaultValue:e}set value(e){if(this._shallow&&Fe(this._raw[this._key])){const t=this._object[this._key];if(Fe(t))return void(t.value=e)}this._object[this._key]=e}get dep(){return B(this._raw,this._key)}}class Qe{constructor(e){this._getter=e,this["__v_isRef"]=!0,this["__v_isReadonly"]=!0,this._value=void 0}get value(){return this._value=this._getter()}}function Je(e,t,n){return Fe(e)?e:(0,r.Tn)(e)?new Qe(e):(0,r.Gv)(e)&&arguments.length>1?Ze(e,t,n):$e(e)}function Ze(e,t,n){return new Ye(e,t,n)}class et{constructor(e,t,n){this.fn=e,this.setter=t,this._value=void 0,this.dep=new x(this),this.__v_isRef=!0,this.deps=void 0,this.depsTail=void 0,this.flags=16,this.globalVersion=N-1,this.next=void 0,this.effect=this,this["__v_isReadonly"]=!t,this.isSSR=n}notify(){if(this.flags|=16,!(8&this.flags||i===this))return m(this,!0),!0}get value(){const e=this.dep.track();return E(this),e&&(e.version=this.dep.version),this._value}set value(e){this.setter&&this.setter(e)}}function tt(e,t,n=!1){let o,i;(0,r.Tn)(e)?o=e:(o=e.get,i=e.set);const s=new et(o,i,n);return s}const nt={GET:"get",HAS:"has",ITERATE:"iterate"},rt={SET:"set",ADD:"add",DELETE:"delete",CLEAR:"clear"},ot={},it=new WeakMap;let st;function at(){return st}function lt(e,t=!1,n=st){if(n){let t=it.get(n);t||it.set(n,t=[]),t.push(e)}else 0}function ut(e,t,n=r.MZ){const{immediate:o,deep:i,once:s,scheduler:a,augmentJob:u,call:c}=n,f=e=>i?e:Ne(e)||!1===i||0===i?ct(e,1):ct(e);let h,p,m,v,g=!1,y=!1;if(Fe(e)?(p=()=>e.value,g=Ne(e)):Re(e)?(p=()=>f(e),g=!0):(0,r.cy)(e)?(y=!0,g=e.some(e=>Re(e)||Ne(e)),p=()=>e.map(e=>Fe(e)?e.value:Re(e)?f(e):(0,r.Tn)(e)?c?c(e,2):e():void 0)):p=(0,r.Tn)(e)?t?c?()=>c(e,2):e:()=>{if(m){A();try{m()}finally{R()}}const t=st;st=h;try{return c?c(e,3,[v]):e(v)}finally{st=t}}:r.tE,t&&i){const e=p,t=!0===i?1/0:i;p=()=>ct(e(),t)}const b=l(),_=()=>{h.stop(),b&&b.active&&(0,r.TF)(b.effects,h)};if(s&&t){const e=t;t=(...t)=>{e(...t),_()}}let E=y?new Array(e.length).fill(ot):ot;const w=e=>{if(1&h.flags&&(h.dirty||e))if(t){const e=h.run();if(i||g||(y?e.some((e,t)=>(0,r.$H)(e,E[t])):(0,r.$H)(e,E))){m&&m();const n=st;st=h;try{const n=[e,E===ot?void 0:y&&E[0]===ot?[]:E,v];E=e,c?c(t,3,n):t(...n)}finally{st=n}}}else h.run()};return u&&u(w),h=new d(p),h.scheduler=a?()=>a(w,!1):w,v=e=>lt(e,!1,h),m=h.onStop=()=>{const e=it.get(h);if(e){if(c)c(e,4);else for(const t of e)t();it.delete(h)}},t?o?w(!0):E=h.run():a?a(w.bind(null,!0),!0):h.run(),_.pause=h.pause.bind(h),_.resume=h.resume.bind(h),_.stop=_,_}function ct(e,t=1/0,n){if(t<=0||!(0,r.Gv)(e)||e["__v_skip"])return e;if(n=n||new Map,(n.get(e)||0)>=t)return e;if(n.set(e,t),t--,Fe(e))ct(e.value,t,n);else if((0,r.cy)(e))for(let r=0;r<e.length;r++)ct(e[r],t,n);else if((0,r.vM)(e)||(0,r.CE)(e))e.forEach(e=>{ct(e,t,n)});else if((0,r.Qd)(e)){for(const r in e)ct(e[r],t,n);for(const r of Object.getOwnPropertySymbols(e))Object.prototype.propertyIsEnumerable.call(e,r)&&ct(e[r],t,n)}return e}},641:function(e,t,n){"use strict";n.d(t,{$V:function(){return it},$u:function(){return wt},$y:function(){return xt},BA:function(){return r.BA},Bi:function(){return xe},Bs:function(){return Uo},C4:function(){return o.C4},CE:function(){return Wr},Df:function(){return Ne},Dl:function(){return C},E:function(){return ln},E3:function(){return no},EW:function(){return Mo},EY:function(){return Pr},FK:function(){return xr},Fv:function(){return oo},Fw:function(){return q},GM:function(){return Yt},Gc:function(){return r.Gc},Gt:function(){return W},Gw:function(){return Ko},Gy:function(){return be},H4:function(){return h},HF:function(){return on},Ht:function(){return en},IG:function(){return r.IG},IJ:function(){return r.IJ},Ic:function(){return Et},Im:function(){return pe},K9:function(){return lr},KC:function(){return bt},KR:function(){return r.KR},Kf:function(){return o.rU},Kh:function(){return r.Kh},LJ:function(){return qo},LM:function(){return z},Lk:function(){return Jr},Lu:function(){return Qt},MZ:function(){return Ie},Mw:function(){return Dr},NP:function(){return Jt},Ng:function(){return to},OA:function(){return tn},OW:function(){return Oe},PP:function(){return r.PP},PR:function(){return ut},PS:function(){return K},PT:function(){return o.PT},Pn:function(){return et},Pr:function(){return r.Pr},Q3:function(){return io},QP:function(){return Ee},QW:function(){return r.QW},QZ:function(){return r.QZ},Qi:function(){return j},R1:function(){return r.R1},R8:function(){return Vo},RG:function(){return jt},SS:function(){return kt},Tb:function(){return Bt},Tm:function(){return r.Tm},Tq:function(){return nt},Tr:function(){return o.Tr},U4:function(){return l},U_:function(){return J},Ul:function(){return r.Ul},Vq:function(){return Gr},WQ:function(){return X},Wv:function(){return Xr},X2:function(){return r.X2},Y4:function(){return ft},Y5:function(){return zo},YY:function(){return B},Yj:function(){return Kt},Yv:function(){return r.Yv},ZH:function(){return o.ZH},ZQ:function(){return Go},_B:function(){return o._B},aT:function(){return Yo},bF:function(){return Zr},bU:function(){return jo},bj:function(){return Ct},bn:function(){return an},bo:function(){return G},ch:function(){return r.ch},ci:function(){return ur},dA:function(){return tt},dY:function(){return w},ds:function(){return r.ds},eW:function(){return ro},eX:function(){return $t},fE:function(){return r.fE},fn:function(){return An},g2:function(){return Nt},g8:function(){return r.g8},gN:function(){return Pt},gW:function(){return zr},gh:function(){return d},h:function(){return Fo},hi:function(){return Tt},i9:function(){return r.i9},iD:function(){return Wo},jC:function(){return Mr},jr:function(){return r.jr},jt:function(){return U},ju:function(){return r.ju},k6:function(){return V},lW:function(){return r.lW},lt:function(){return Ho},mu:function(){return r.mu},n:function(){return dt},nD:function(){return r.nD},nI:function(){return vo},nT:function(){return Y},o5:function(){return r.o5},p9:function(){return Q},pI:function(){return Ft},pM:function(){return Le},pR:function(){return ke},qG:function(){return At},qL:function(){return f},qP:function(){return qt},qR:function(){return Ot},rE:function(){return Bo},rO:function(){return Zt},rU:function(){return Je},rY:function(){return r.rY},rk:function(){return De},sV:function(){return _t},tB:function(){return r.tB},tC:function(){return Ao},tG:function(){return u},tY:function(){return wr},uX:function(){return jr},uY:function(){return r.uY},ux:function(){return r.ux},v6:function(){return uo},v_:function(){return o.v_},vv:function(){return Kr},wB:function(){return Z},wX:function(){return Ro},wk:function(){return zt},xo:function(){return St},y$:function(){return $o},yC:function(){return r.yC},zz:function(){return sn}});var r=n(953),o=n(33);
/**
* @vue/runtime-core v3.5.32
* (c) 2018-present Yuxi (Evan) You and Vue contributors
* @license MIT
**/
const i=[];function s(e){i.push(e)}function a(){i.pop()}function l(e,t){}const u={SETUP_FUNCTION:0,0:"SETUP_FUNCTION",RENDER_FUNCTION:1,1:"RENDER_FUNCTION",NATIVE_EVENT_HANDLER:5,5:"NATIVE_EVENT_HANDLER",COMPONENT_EVENT_HANDLER:6,6:"COMPONENT_EVENT_HANDLER",VNODE_HOOK:7,7:"VNODE_HOOK",DIRECTIVE_HOOK:8,8:"DIRECTIVE_HOOK",TRANSITION_HOOK:9,9:"TRANSITION_HOOK",APP_ERROR_HANDLER:10,10:"APP_ERROR_HANDLER",APP_WARN_HANDLER:11,11:"APP_WARN_HANDLER",FUNCTION_REF:12,12:"FUNCTION_REF",ASYNC_COMPONENT_LOADER:13,13:"ASYNC_COMPONENT_LOADER",SCHEDULER:14,14:"SCHEDULER",COMPONENT_UPDATE:15,15:"COMPONENT_UPDATE",APP_UNMOUNT_CLEANUP:16,16:"APP_UNMOUNT_CLEANUP"},c={["sp"]:"serverPrefetch hook",["bc"]:"beforeCreate hook",["c"]:"created hook",["bm"]:"beforeMount hook",["m"]:"mounted hook",["bu"]:"beforeUpdate hook",["u"]:"updated",["bum"]:"beforeUnmount hook",["um"]:"unmounted hook",["a"]:"activated hook",["da"]:"deactivated hook",["ec"]:"errorCaptured hook",["rtc"]:"renderTracked hook",["rtg"]:"renderTriggered hook",[0]:"setup function",[1]:"render function",[2]:"watcher getter",[3]:"watcher callback",[4]:"watcher cleanup function",[5]:"native event handler",[6]:"component event handler",[7]:"vnode hook",[8]:"directive hook",[9]:"transition hook",[10]:"app errorHandler",[11]:"app warnHandler",[12]:"ref function",[13]:"async component loader",[14]:"scheduler flush",[15]:"component update",[16]:"app unmount cleanup function"};function d(e,t,n,r){try{return r?e(...r):e()}catch(o){h(o,t,n)}}function f(e,t,n,r){if((0,o.Tn)(e)){const i=d(e,t,n,r);return i&&(0,o.yL)(i)&&i.catch(e=>{h(e,t,n)}),i}if((0,o.cy)(e)){const o=[];for(let i=0;i<e.length;i++)o.push(f(e[i],t,n,r));return o}}function h(e,t,n,i=!0){const s=t?t.vnode:null,{errorHandler:a,throwUnhandledErrorInProduction:l}=t&&t.appContext.config||o.MZ;if(t){let o=t.parent;const i=t.proxy,s=`https://vuejs.org/error-reference/#runtime-${n}`;while(o){const t=o.ec;if(t)for(let n=0;n<t.length;n++)if(!1===t[n](e,i,s))return;o=o.parent}if(a)return(0,r.C4)(),d(a,null,10,[e,i,s]),void(0,r.bl)()}p(e,n,s,i,l)}function p(e,t,n,r=!0,o=!1){if(o)throw e;console.error(e)}const m=[];let v=-1;const g=[];let y=null,b=0;const _=Promise.resolve();let E=null;function w(e){const t=E||_;return e?t.then(this?e.bind(this):e):t}function S(e){let t=v+1,n=m.length;while(t<n){const r=t+n>>>1,o=m[r],i=R(o);i<e||i===e&&2&o.flags?t=r+1:n=r}return t}function T(e){if(!(1&e.flags)){const t=R(e),n=m[m.length-1];!n||!(2&e.flags)&&t>=R(n)?m.push(e):m.splice(S(t),0,e),e.flags|=1,k()}}function k(){E||(E=_.then(I))}function C(e){(0,o.cy)(e)?g.push(...e):y&&-1===e.id?y.splice(b+1,0,e):1&e.flags||(g.push(e),e.flags|=1),k()}function O(e,t,n=v+1){for(0;n<m.length;n++){const t=m[n];if(t&&2&t.flags){if(e&&t.id!==e.uid)continue;0,m.splice(n,1),n--,4&t.flags&&(t.flags&=-2),t(),4&t.flags||(t.flags&=-2)}}}function A(e){if(g.length){const e=[...new Set(g)].sort((e,t)=>R(e)-R(t));if(g.length=0,y)return void y.push(...e);for(y=e,b=0;b<y.length;b++){const e=y[b];0,4&e.flags&&(e.flags&=-2),8&e.flags||e(),e.flags&=-2}y=null,b=0}}const R=e=>null==e.id?2&e.flags?-1:1/0:e.id;function I(e){o.tE;try{for(v=0;v<m.length;v++){const e=m[v];!e||8&e.flags||(4&e.flags&&(e.flags&=-2),d(e,e.i,e.i?15:14),4&e.flags||(e.flags&=-2))}}finally{for(;v<m.length;v++){const e=m[v];e&&(e.flags&=-2)}v=-1,m.length=0,A(e),E=null,(m.length||g.length)&&I(e)}}let N=!1;let L,x=[],P=!1;function D(e,t){var n,r;if(L=e,L)L.enabled=!0,x.forEach(({event:e,args:t})=>L.emit(e,...t)),x=[];else if("undefined"!==typeof window&&window.HTMLElement&&!(null==(r=null==(n=window.navigator)?void 0:n.userAgent)?void 0:r.includes("jsdom"))){const e=t.__VUE_DEVTOOLS_HOOK_REPLAY__=t.__VUE_DEVTOOLS_HOOK_REPLAY__||[];e.push(e=>{D(e,t)}),setTimeout(()=>{L||(t.__VUE_DEVTOOLS_HOOK_REPLAY__=null,P=!0,x=[])},3e3)}else P=!0,x=[]}let M=null,F=null;function $(e){const t=M;return M=e,F=e&&e.type.__scopeId||null,t}function j(e){F=e}function U(){F=null}const B=e=>V;function V(e,t=M,n){if(!t)return e;if(e._n)return e;const r=(...n)=>{r._d&&Gr(-1);const o=$(t);let i;try{i=e(...n)}finally{$(o),r._d&&Gr(1)}return i};return r._n=!0,r._c=!0,r._d=!0,r}function G(e,t){if(null===M)return e;const n=xo(M),i=e.dirs||(e.dirs=[]);for(let s=0;s<t.length;s++){let[e,a,l,u=o.MZ]=t[s];e&&((0,o.Tn)(e)&&(e={mounted:e,updated:e}),e.deep&&(0,r.hV)(a),i.push({dir:e,instance:n,value:a,oldValue:void 0,arg:l,modifiers:u}))}return e}function H(e,t,n,o){const i=e.dirs,s=t&&t.dirs;for(let a=0;a<i.length;a++){const l=i[a];s&&(l.oldValue=s[a].value);let u=l.dir[o];u&&((0,r.C4)(),f(u,n,8,[e.el,l,e,t]),(0,r.bl)())}}function W(e,t){if(mo){let n=mo.provides;const r=mo.parent&&mo.parent.provides;r===n&&(n=mo.provides=Object.create(r)),n[e]=t}}function X(e,t,n=!1){const r=vo();if(r||On){let i=On?On._context.provides:r?null==r.parent||r.ce?r.vnode.appContext&&r.vnode.appContext.provides:r.parent.provides:void 0;if(i&&e in i)return i[e];if(arguments.length>1)return n&&(0,o.Tn)(t)?t.call(r&&r.proxy):t}else 0}function K(){return!(!vo()&&!On)}const q=Symbol.for("v-scx"),z=()=>{{const e=X(q);return e}};function Y(e,t){return ee(e,null,t)}function Q(e,t){return ee(e,null,{flush:"post"})}function J(e,t){return ee(e,null,{flush:"sync"})}function Z(e,t,n){return ee(e,t,n)}function ee(e,t,n=o.MZ){const{immediate:i,deep:s,flush:a,once:l}=n;const u=(0,o.X$)({},n);const c=t&&i||!t&&"post"!==a;let d;if(To)if("sync"===a){const e=z();d=e.__watcherHandles||(e.__watcherHandles=[])}else if(!c){const e=()=>{};return e.stop=o.tE,e.resume=o.tE,e.pause=o.tE,e}const h=mo;u.call=(e,t,n)=>f(e,h,t,n);let p=!1;"post"===a?u.scheduler=e=>{ar(e,h&&h.suspense)}:"sync"!==a&&(p=!0,u.scheduler=(e,t)=>{t?e():T(e)}),u.augmentJob=e=>{t&&(e.flags|=4),p&&(e.flags|=2,h&&(e.id=h.uid,e.i=h))};const m=(0,r.wB)(e,t,u);return To&&(d?d.push(m):c&&m()),m}function te(e,t,n){const r=this.proxy,i=(0,o.Kg)(e)?e.includes(".")?ne(r,e):()=>r[e]:e.bind(r,r);let s;(0,o.Tn)(t)?s=t:(s=t.handler,n=t);const a=bo(this),l=ee(i,s.bind(r),n);return a(),l}function ne(e,t){const n=t.split(".");return()=>{let t=e;for(let e=0;e<n.length&&t;e++)t=t[n[e]];return t}}const re=new WeakMap,oe=Symbol("_vte"),ie=e=>e.__isTeleport,se=e=>e&&(e.disabled||""===e.disabled),ae=e=>e&&(e.defer||""===e.defer),le=e=>"undefined"!==typeof SVGElement&&e instanceof SVGElement,ue=e=>"function"===typeof MathMLElement&&e instanceof MathMLElement,ce=(e,t)=>{const n=e&&e.to;if((0,o.Kg)(n)){if(t){const e=t(n);return e}return null}return n},de={name:"Teleport",__isTeleport:!0,process(e,t,n,r,o,i,s,a,l,u){const{mc:c,pc:d,pbc:f,o:{insert:h,querySelector:p,createText:m,createComment:v}}=u,g=se(t.props);let{dynamicChildren:y}=t;const b=(e,t,n)=>{16&e.shapeFlag&&c(e.children,t,n,o,i,s,a,l)},_=(e=t)=>{const n=se(e.props),r=e.target=ce(e.props,p),i=ve(r,e,m,h);r&&("svg"!==s&&le(r)?s="svg":"mathml"!==s&&ue(r)&&(s="mathml"),o&&o.isCE&&(o.ce._teleportTargets||(o.ce._teleportTargets=new Set)).add(r),n||(b(e,r,i),me(e,!1)))},E=e=>{const t=()=>{re.get(e)===t&&(re.delete(e),se(e.props)&&(b(e,n,e.anchor),me(e,!0)),_(e))};re.set(e,t),ar(t,i)};if(null==e){const e=t.el=m(""),o=t.anchor=m("");if(h(e,n,r),h(o,n,r),ae(t.props)||i&&i.pendingBranch)return void E(t);g&&(b(t,n,o),me(t,!0)),_()}else{t.el=e.el;const r=t.anchor=e.anchor,c=re.get(e);if(c)return c.flags|=8,re.delete(e),void E(t);t.targetStart=e.targetStart;const h=t.target=e.target,m=t.targetAnchor=e.targetAnchor,v=se(e.props),b=v?n:h,_=v?r:m;if("svg"===s||le(h)?s="svg":("mathml"===s||ue(h))&&(s="mathml"),y?(f(e.dynamicChildren,y,b,o,i,s,a),pr(e,t,!0)):l||d(e,t,b,_,o,i,s,a,!1),g)v?t.props&&e.props&&t.props.to!==e.props.to&&(t.props.to=e.props.to):fe(t,n,r,u,1);else if((t.props&&t.props.to)!==(e.props&&e.props.to)){const e=t.target=ce(t.props,p);e&&fe(t,e,null,u,0)}else v&&fe(t,h,m,u,1);me(t,g)}},remove(e,t,n,{um:r,o:{remove:o}},i){const{shapeFlag:s,children:a,anchor:l,targetStart:u,targetAnchor:c,target:d,props:f}=e;let h=i||!se(f);const p=re.get(e);if(p&&(p.flags|=8,re.delete(e),h=!1),d&&(o(u),o(c)),i&&o(l),16&s)for(let m=0;m<a.length;m++){const e=a[m];r(e,t,n,h,!!e.dynamicChildren)}},move:fe,hydrate:he};function fe(e,t,n,{o:{insert:r},m:o},i=2){0===i&&r(e.targetAnchor,t,n);const{el:s,anchor:a,shapeFlag:l,children:u,props:c}=e,d=2===i;if(d&&r(s,t,n),(!d||se(c))&&16&l)for(let f=0;f<u.length;f++)o(u[f],t,n,2);d&&r(a,t,n)}function he(e,t,n,r,o,i,{o:{nextSibling:s,parentNode:a,querySelector:l,insert:u,createText:c}},d){function f(e,n){let r=n;while(r){if(r&&8===r.nodeType)if("teleport start anchor"===r.data)t.targetStart=r;else if("teleport anchor"===r.data){t.targetAnchor=r,e._lpa=t.targetAnchor&&s(t.targetAnchor);break}r=s(r)}}function h(e,t){t.anchor=d(s(e),t,a(e),n,r,o,i)}const p=t.target=ce(t.props,l),m=se(t.props);if(p){const l=p._lpa||p.firstChild;16&t.shapeFlag&&(m?(h(e,t),f(p,l),t.targetAnchor||ve(p,t,c,u,a(e)===p?e:null)):(t.anchor=s(e),f(p,l),t.targetAnchor||ve(p,t,c,u),d(l&&s(l),t,p,n,r,o,i))),me(t,m)}else m&&16&t.shapeFlag&&(h(e,t),t.targetStart=e,t.targetAnchor=s(e));return t.anchor&&s(t.anchor)}const pe=de;function me(e,t){const n=e.ctx;if(n&&n.ut){let r,o;t?(r=e.el,o=e.anchor):(r=e.targetStart,o=e.targetAnchor);while(r&&r!==o)1===r.nodeType&&r.setAttribute("data-v-owner",n.uid),r=r.nextSibling;n.ut()}}function ve(e,t,n,r,o=null){const i=t.targetStart=n(""),s=t.targetAnchor=n("");return i[oe]=s,e&&(r(i,e,o),r(s,e,o)),s}const ge=Symbol("_leaveCb"),ye=Symbol("_enterCb");function be(){const e={isMounted:!1,isLeaving:!1,isUnmounting:!1,leavingVNodes:new Map};return _t(()=>{e.isMounted=!0}),St(()=>{e.isUnmounting=!0}),e}const _e=[Function,Array],Ee={mode:String,appear:Boolean,persisted:Boolean,onBeforeEnter:_e,onEnter:_e,onAfterEnter:_e,onEnterCancelled:_e,onBeforeLeave:_e,onLeave:_e,onAfterLeave:_e,onLeaveCancelled:_e,onBeforeAppear:_e,onAppear:_e,onAfterAppear:_e,onAppearCancelled:_e},we=e=>{const t=e.subTree;return t.component?we(t.component):t},Se={name:"BaseTransition",props:Ee,setup(e,{slots:t}){const n=vo(),o=be();return()=>{const i=t.default&&Ne(t.default(),!0);if(!i||!i.length)return;const s=Te(i),a=(0,r.ux)(e),{mode:l}=a;if(o.isLeaving)return Ae(s);const u=Re(s);if(!u)return Ae(s);let c=Oe(u,a,o,n,e=>c=e);u.type!==Dr&&Ie(u,c);let d=n.subTree&&Re(n.subTree);if(d&&d.type!==Dr&&!qr(d,u)&&we(n).type!==Dr){let e=Oe(d,a,o,n);if(Ie(d,e),"out-in"===l&&u.type!==Dr)return o.isLeaving=!0,e.afterLeave=()=>{o.isLeaving=!1,8&n.job.flags||n.update(),delete e.afterLeave,d=void 0},Ae(s);"in-out"===l&&u.type!==Dr?e.delayLeave=(e,t,n)=>{const r=Ce(o,d);r[String(d.key)]=d,e[ge]=()=>{t(),e[ge]=void 0,delete c.delayedLeave,d=void 0},c.delayedLeave=()=>{n(),delete c.delayedLeave,d=void 0}}:d=void 0}else d&&(d=void 0);return s}}};function Te(e){let t=e[0];if(e.length>1){let n=!1;for(const r of e)if(r.type!==Dr){0,t=r,n=!0;break}}return t}const ke=Se;function Ce(e,t){const{leavingVNodes:n}=e;let r=n.get(t.type);return r||(r=Object.create(null),n.set(t.type,r)),r}function Oe(e,t,n,r,i){const{appear:s,mode:a,persisted:l=!1,onBeforeEnter:u,onEnter:c,onAfterEnter:d,onEnterCancelled:h,onBeforeLeave:p,onLeave:m,onAfterLeave:v,onLeaveCancelled:g,onBeforeAppear:y,onAppear:b,onAfterAppear:_,onAppearCancelled:E}=t,w=String(e.key),S=Ce(n,e),T=(e,t)=>{e&&f(e,r,9,t)},k=(e,t)=>{const n=t[1];T(e,t),(0,o.cy)(e)?e.every(e=>e.length<=1)&&n():e.length<=1&&n()},C={mode:a,persisted:l,beforeEnter(t){let r=u;if(!n.isMounted){if(!s)return;r=y||u}t[ge]&&t[ge](!0);const o=S[w];o&&qr(e,o)&&o.el[ge]&&o.el[ge](),T(r,[t])},enter(t){if(!N&&S[w]===e)return;let r=c,o=d,i=h;if(!n.isMounted){if(!s)return;r=b||c,o=_||d,i=E||h}let a=!1;t[ye]=e=>{a||(a=!0,T(e?i:o,[t]),C.delayedLeave&&C.delayedLeave(),t[ye]=void 0)};const l=t[ye].bind(null,!1);r?k(r,[t,l]):l()},leave(t,r){const o=String(e.key);if(t[ye]&&t[ye](!0),n.isUnmounting)return r();T(p,[t]);let i=!1;t[ge]=n=>{i||(i=!0,r(),T(n?g:v,[t]),t[ge]=void 0,S[o]===e&&delete S[o])};const s=t[ge].bind(null,!1);S[o]=e,m?k(m,[t,s]):s()},clone(e){const o=Oe(e,t,n,r,i);return i&&i(o),o}};return C}function Ae(e){if(at(e))return e=no(e),e.children=null,e}function Re(e){if(!at(e))return ie(e.type)&&e.children?Te(e.children):e;if(e.component)return e.component.subTree;const{shapeFlag:t,children:n}=e;if(n){if(16&t)return n[0];if(32&t&&(0,o.Tn)(n.default))return n.default()}}function Ie(e,t){6&e.shapeFlag&&e.component?(e.transition=t,Ie(e.component.subTree,t)):128&e.shapeFlag?(e.ssContent.transition=t.clone(e.ssContent),e.ssFallback.transition=t.clone(e.ssFallback)):e.transition=t}function Ne(e,t=!1,n){let r=[],o=0;for(let i=0;i<e.length;i++){let s=e[i];const a=null==n?s.key:String(n)+String(null!=s.key?s.key:i);s.type===xr?(128&s.patchFlag&&o++,r=r.concat(Ne(s.children,t,a))):(t||s.type!==Dr)&&r.push(null!=a?no(s,{key:a}):s)}if(o>1)for(let i=0;i<r.length;i++)r[i].patchFlag=-2;return r}function Le(e,t){return(0,o.Tn)(e)?(()=>(0,o.X$)({name:e.name},t,{setup:e}))():e}function xe(){const e=vo();return e?(e.appContext.config.idPrefix||"v")+"-"+e.ids[0]+e.ids[1]++:""}function Pe(e){e.ids=[e.ids[0]+e.ids[2]+++"-",0,0]}function De(e){const t=vo(),n=(0,r.IJ)(null);if(t){const r=t.refs===o.MZ?t.refs={}:t.refs;Object.defineProperty(r,e,{enumerable:!0,get:()=>n.value,set:e=>n.value=e})}else 0;const i=n;return i}function Me(e,t){let n;return!(!(n=Object.getOwnPropertyDescriptor(e,t))||n.configurable)}const Fe=new WeakMap;function $e(e,t,n,i,s=!1){if((0,o.cy)(e))return void e.forEach((e,r)=>$e(e,t&&((0,o.cy)(t)?t[r]:t),n,i,s));if(ot(i)&&!s)return void(512&i.shapeFlag&&i.type.__asyncResolved&&i.component.subTree.component&&$e(e,t,n,i.component.subTree));const a=4&i.shapeFlag?xo(i.component):i.el,l=s?null:a,{i:u,r:c}=e;const f=t&&t.r,h=u.refs===o.MZ?u.refs={}:u.refs,p=u.setupState,m=(0,r.ux)(p),v=p===o.MZ?o.NO:e=>!Me(h,e)&&(0,o.$3)(m,e),g=(e,t)=>!t||!Me(h,t);if(null!=f&&f!==c)if(je(t),(0,o.Kg)(f))h[f]=null,v(f)&&(p[f]=null);else if((0,r.i9)(f)){const e=t;g(f,e.k)&&(f.value=null),e.k&&(h[e.k]=null)}if((0,o.Tn)(c))d(c,u,12,[l,h]);else{const t=(0,o.Kg)(c),i=(0,r.i9)(c);if(t||i){const r=()=>{if(e.f){const n=t?v(c)?p[c]:h[c]:g(c)||!e.k?c.value:h[e.k];if(s)(0,o.cy)(n)&&(0,o.TF)(n,a);else if((0,o.cy)(n))n.includes(a)||n.push(a);else if(t)h[c]=[a],v(c)&&(p[c]=h[c]);else{const t=[a];g(c,e.k)&&(c.value=t),e.k&&(h[e.k]=t)}}else t?(h[c]=l,v(c)&&(p[c]=l)):i&&(g(c,e.k)&&(c.value=l),e.k&&(h[e.k]=l))};if(l){const t=()=>{r(),Fe.delete(e)};t.id=-1,Fe.set(e,t),ar(t,n)}else je(e),r()}else 0}}function je(e){const t=Fe.get(e);t&&(t.flags|=8,Fe.delete(e))}let Ue=!1;const Be=()=>{Ue||(console.error("Hydration completed but contains mismatches."),Ue=!0)},Ve=e=>e.namespaceURI.includes("svg")&&"foreignObject"!==e.tagName,Ge=e=>e.namespaceURI.includes("MathML"),He=e=>{if(1===e.nodeType)return Ve(e)?"svg":Ge(e)?"mathml":void 0},We=e=>8===e.nodeType;function Xe(e){const{mt:t,p:n,o:{patchProp:i,createText:s,nextSibling:a,parentNode:l,remove:u,insert:c,createComment:d}}=e,f=(e,t)=>{if(!t.hasChildNodes())return n(null,e,t),A(),void(t._vnode=e);h(t.firstChild,e,null,null,null),A(),t._vnode=e},h=(n,r,o,i,u,d=!1)=>{d=d||!!r.dynamicChildren;const f=We(n)&&"["===n.data,E=()=>g(n,r,o,i,u,f),{type:w,ref:S,shapeFlag:T,patchFlag:k}=r;let C=n.nodeType;r.el=n,-2===k&&(d=!1,r.dynamicChildren=null);let O=null;switch(w){case Pr:3!==C?""===r.children?(c(r.el=s(""),l(n),n),O=n):O=E():(n.data!==r.children&&(Be(),n.data=r.children),O=a(n));break;case Dr:_(n)?(O=a(n),b(r.el=n.content.firstChild,n,o)):O=8!==C||f?E():a(n);break;case Mr:if(f&&(n=a(n),C=n.nodeType),1===C||3===C){O=n;const e=!r.children.length;for(let t=0;t<r.staticCount;t++)e&&(r.children+=1===O.nodeType?O.outerHTML:O.data),t===r.staticCount-1&&(r.anchor=O),O=a(O);return f?a(O):O}E();break;case xr:O=f?v(n,r,o,i,u,d):E();break;default:if(1&T)O=1===C&&r.type.toLowerCase()===n.tagName.toLowerCase()||_(n)?p(n,r,o,i,u,d):E();else if(6&T){r.slotScopeIds=u;const e=l(n);if(O=f?y(n):We(n)&&"teleport start"===n.data?y(n,n.data,"teleport end"):a(n),t(r,e,null,o,i,He(e),d),ot(r)&&!r.type.__asyncResolved){let t;f?(t=Zr(xr),t.anchor=O?O.previousSibling:e.lastChild):t=3===n.nodeType?ro(""):Zr("div"),t.el=n,r.component.subTree=t}}else 64&T?O=8!==C?E():r.type.hydrate(n,r,o,i,u,d,e,m):128&T&&(O=r.type.hydrate(n,r,o,i,He(l(n)),u,d,e,h))}return null!=S&&$e(S,null,i,r),O},p=(e,t,n,s,a,l)=>{l=l||!!t.dynamicChildren;const{type:c,props:d,patchFlag:f,shapeFlag:h,dirs:p,transition:v}=t,g="input"===c||"option"===c;if(g||-1!==f){p&&H(t,null,n,"created");let c,y=!1;if(_(e)){y=hr(null,v)&&n&&n.vnode.props&&n.vnode.props.appear;const r=e.content.firstChild;if(y){const e=r.getAttribute("class");e&&(r.$cls=e),v.beforeEnter(r)}b(r,e,n),t.el=e=r}if(16&h&&(!d||!d.innerHTML&&!d.textContent)){let r=m(e.firstChild,t,e,n,s,a,l);while(r){ze(e,1)||Be();const t=r;r=r.nextSibling,u(t)}}else if(8&h){let n=t.children;"\n"!==n[0]||"PRE"!==e.tagName&&"TEXTAREA"!==e.tagName||(n=n.slice(1));const{textContent:r}=e;r!==n&&r!==n.replace(/\r\n|\r/g,"\n")&&(ze(e,0)||Be(),e.textContent=t.children)}if(d)if(g||!l||48&f){const t=e.tagName.includes("-");for(const r in d)(g&&(r.endsWith("value")||"indeterminate"===r)||(0,o.Mp)(r)&&!(0,o.SU)(r)||"."===r[0]||t&&!(0,o.SU)(r))&&i(e,r,null,d[r],void 0,n)}else if(d.onClick)i(e,"onClick",null,d.onClick,void 0,n);else if(4&f&&(0,r.g8)(d.style))for(const e in d.style)d.style[e];(c=d&&d.onVnodeBeforeMount)&&co(c,n,t),p&&H(t,null,n,"beforeMount"),((c=d&&d.onVnodeMounted)||p||y)&&Ir(()=>{c&&co(c,n,t),y&&v.enter(e),p&&H(t,null,n,"mounted")},s)}return e.nextSibling},m=(e,t,r,o,i,l,u)=>{u=u||!!t.dynamicChildren;const d=t.children,f=d.length;for(let p=0;p<f;p++){const t=u?d[p]:d[p]=so(d[p]),m=t.type===Pr;e?(m&&!u&&p+1<f&&so(d[p+1]).type===Pr&&(c(s(e.data.slice(t.children.length)),r,a(e)),e.data=t.children),e=h(e,t,o,i,l,u)):m&&!t.children?c(t.el=s(""),r):(ze(r,1)||Be(),n(null,t,r,null,o,i,He(r),l))}return e},v=(e,t,n,r,o,i)=>{const{slotScopeIds:s}=t;s&&(o=o?o.concat(s):s);const u=l(e),f=m(a(e),t,u,n,r,o,i);return f&&We(f)&&"]"===f.data?a(t.anchor=f):(Be(),c(t.anchor=d("]"),u,f),f)},g=(e,t,r,o,i,s)=>{if(ze(e.parentElement,1)||Be(),t.el=null,s){const t=y(e);while(1){const n=a(e);if(!n||n===t)break;u(n)}}const c=a(e),d=l(e);return u(e),n(null,t,d,c,r,o,He(d),i),r&&(r.vnode.el=t.el,Bn(r,t.el)),c},y=(e,t="[",n="]")=>{let r=0;while(e)if(e=a(e),e&&We(e)&&(e.data===t&&r++,e.data===n)){if(0===r)return a(e);r--}return e},b=(e,t,n)=>{const r=t.parentNode;r&&r.replaceChild(e,t);let o=n;while(o)o.vnode.el===t&&(o.vnode.el=o.subTree.el=e),o=o.parent},_=e=>1===e.nodeType&&"TEMPLATE"===e.tagName;return[f,h]}const Ke="data-allow-mismatch",qe={[0]:"text",[1]:"children",[2]:"class",[3]:"style",[4]:"attribute"};function ze(e,t){if(0===t||1===t)while(e&&!e.hasAttribute(Ke))e=e.parentElement;const n=e&&e.getAttribute(Ke);if(null==n)return!1;if(""===n)return!0;{const e=n.split(",");return!(0!==t||!e.includes("children"))||e.includes(qe[t])}}const Ye=(0,o.We)().requestIdleCallback||(e=>setTimeout(e,1)),Qe=(0,o.We)().cancelIdleCallback||(e=>clearTimeout(e)),Je=(e=1e4)=>t=>{const n=Ye(t,{timeout:e});return()=>Qe(n)};function Ze(e){const{top:t,left:n,bottom:r,right:o}=e.getBoundingClientRect(),{innerHeight:i,innerWidth:s}=window;return(t>0&&t<i||r>0&&r<i)&&(n>0&&n<s||o>0&&o<s)}const et=e=>(t,n)=>{const r=new IntersectionObserver(e=>{for(const n of e)if(n.isIntersecting){r.disconnect(),t();break}},e);return n(e=>{if(e instanceof Element)return Ze(e)?(t(),r.disconnect(),!1):void r.observe(e)}),()=>r.disconnect()},tt=e=>t=>{if(e){const n=matchMedia(e);if(!n.matches)return n.addEventListener("change",t,{once:!0}),()=>n.removeEventListener("change",t);t()}},nt=(e=[])=>(t,n)=>{(0,o.Kg)(e)&&(e=[e]);let r=!1;const i=e=>{r||(r=!0,s(),t(),e.target.dispatchEvent(new e.constructor(e.type,e)))},s=()=>{n(t=>{for(const n of e)t.removeEventListener(n,i)})};return n(t=>{for(const n of e)t.addEventListener(n,i,{once:!0})}),s};function rt(e,t){if(We(e)&&"["===e.data){let n=1,r=e.nextSibling;while(r){if(1===r.nodeType){const e=t(r);if(!1===e)break}else if(We(r))if("]"===r.data){if(0===--n)break}else"["===r.data&&n++;r=r.nextSibling}}else t(e)}const ot=e=>!!e.type.__asyncLoader;function it(e){(0,o.Tn)(e)&&(e={loader:e});const{loader:t,loadingComponent:n,errorComponent:i,delay:s=200,hydrate:a,timeout:l,suspensible:u=!0,onError:c}=e;let d,f=null,p=0;const m=()=>(p++,f=null,v()),v=()=>{let e;return f||(e=f=t().catch(e=>{if(e=e instanceof Error?e:new Error(String(e)),c)return new Promise((t,n)=>{const r=()=>t(m()),o=()=>n(e);c(e,r,o,p+1)});throw e}).then(t=>e!==f&&f?f:(t&&(t.__esModule||"Module"===t[Symbol.toStringTag])&&(t=t.default),d=t,t)))};return Le({name:"AsyncComponentWrapper",__asyncLoader:v,__asyncHydrate(e,t,n){let r=!1;(t.bu||(t.bu=[])).push(()=>r=!0);const o=()=>{r||n()},i=a?()=>{const n=a(o,t=>rt(e,t));n&&(t.bum||(t.bum=[])).push(n)}:o;d?i():v().then(()=>!t.isUnmounted&&i())},get __asyncResolved(){return d},setup(){const e=mo;if(Pe(e),d)return()=>st(d,e);const t=t=>{f=null,h(t,e,13,!i)};if(u&&e.suspense||To)return v().then(t=>()=>st(t,e)).catch(e=>(t(e),()=>i?Zr(i,{error:e}):null));const o=(0,r.KR)(!1),a=(0,r.KR)(),c=(0,r.KR)(!!s);return s&&setTimeout(()=>{c.value=!1},s),null!=l&&setTimeout(()=>{if(!o.value&&!a.value){const e=new Error(`Async component timed out after ${l}ms.`);t(e),a.value=e}},l),v().then(()=>{o.value=!0,e.parent&&at(e.parent.vnode)&&e.parent.update()}).catch(e=>{t(e),a.value=e}),()=>o.value&&d?st(d,e):a.value&&i?Zr(i,{error:a.value}):n&&!c.value?st(n,e):void 0}})}function st(e,t){const{ref:n,props:r,children:o,ce:i}=t.vnode,s=Zr(e,r,o);return s.ref=n,s.ce=i,delete t.vnode.ce,s}const at=e=>e.type.__isKeepAlive,lt={name:"KeepAlive",__isKeepAlive:!0,props:{include:[String,RegExp,Array],exclude:[String,RegExp,Array],max:[String,Number]},setup(e,{slots:t}){const n=vo(),r=n.ctx;if(!r.renderer)return()=>{const e=t.default&&t.default();return e&&1===e.length?e[0]:e};const i=new Map,s=new Set;let a=null;const l=n.suspense,{renderer:{p:u,m:c,um:d,o:{createElement:f}}}=r,h=f("div");function p(e){mt(e),d(e,n,l,!0)}function m(e){i.forEach((t,n)=>{const r=Po(ot(t)?t.type.__asyncResolved||{}:t.type);r&&!e(r)&&v(n)})}function v(e){const t=i.get(e);!t||a&&qr(t,a)?a&&mt(a):p(t),i.delete(e),s.delete(e)}r.activate=(e,t,n,r,i)=>{const s=e.component;c(e,t,n,0,l),u(s.vnode,e,t,n,s,l,r,e.slotScopeIds,i),ar(()=>{s.isDeactivated=!1,s.a&&(0,o.DY)(s.a);const t=e.props&&e.props.onVnodeMounted;t&&co(t,s.parent,e)},l)},r.deactivate=e=>{const t=e.component;gr(t.m),gr(t.a),c(e,h,null,1,l),ar(()=>{t.da&&(0,o.DY)(t.da);const n=e.props&&e.props.onVnodeUnmounted;n&&co(n,t.parent,e),t.isDeactivated=!0},l)},Z(()=>[e.include,e.exclude],([e,t])=>{e&&m(t=>ct(e,t)),t&&m(e=>!ct(t,e))},{flush:"post",deep:!0});let g=null;const y=()=>{null!=g&&(br(n.subTree.type)?ar(()=>{i.set(g,vt(n.subTree))},n.subTree.suspense):i.set(g,vt(n.subTree)))};return _t(y),wt(y),St(()=>{i.forEach(e=>{const{subTree:t,suspense:r}=n,o=vt(t);if(e.type===o.type&&e.key===o.key){mt(o);const e=o.component.da;return void(e&&ar(e,r))}p(e)})}),()=>{if(g=null,!t.default)return a=null;const n=t.default(),r=n[0];if(n.length>1)return a=null,n;if(!Kr(r)||!(4&r.shapeFlag)&&!(128&r.shapeFlag))return a=null,r;let o=vt(r);if(o.type===Dr)return a=null,o;const l=o.type,u=Po(ot(o)?o.type.__asyncResolved||{}:l),{include:c,exclude:d,max:f}=e;if(c&&(!u||!ct(c,u))||d&&u&&ct(d,u))return o.shapeFlag&=-257,a=o,r;const h=null==o.key?l:o.key,p=i.get(h);return o.el&&(o=no(o),128&r.shapeFlag&&(r.ssContent=o)),g=h,p?(o.el=p.el,o.component=p.component,o.transition&&Ie(o,o.transition),o.shapeFlag|=512,s.delete(h),s.add(h)):(s.add(h),f&&s.size>parseInt(f,10)&&v(s.values().next().value)),o.shapeFlag|=256,a=o,br(r.type)?r:o}}},ut=lt;function ct(e,t){return(0,o.cy)(e)?e.some(e=>ct(e,t)):(0,o.Kg)(e)?e.split(",").includes(t):!!(0,o.gd)(e)&&(e.lastIndex=0,e.test(t))}function dt(e,t){ht(e,"a",t)}function ft(e,t){ht(e,"da",t)}function ht(e,t,n=mo){const r=e.__wdc||(e.__wdc=()=>{let t=n;while(t){if(t.isDeactivated)return;t=t.parent}return e()});if(gt(t,r,n),n){let e=n.parent;while(e&&e.parent)at(e.parent.vnode)&&pt(r,t,n,e),e=e.parent}}function pt(e,t,n,r){const i=gt(t,e,r,!0);Tt(()=>{(0,o.TF)(r[t],i)},n)}function mt(e){e.shapeFlag&=-257,e.shapeFlag&=-513}function vt(e){return 128&e.shapeFlag?e.ssContent:e}function gt(e,t,n=mo,o=!1){if(n){const i=n[e]||(n[e]=[]),s=t.__weh||(t.__weh=(...o)=>{(0,r.C4)();const i=bo(n),s=f(t,n,e,o);return i(),(0,r.bl)(),s});return o?i.unshift(s):i.push(s),s}}const yt=e=>(t,n=mo)=>{To&&"sp"!==e||gt(e,(...e)=>t(...e),n)},bt=yt("bm"),_t=yt("m"),Et=yt("bu"),wt=yt("u"),St=yt("bum"),Tt=yt("um"),kt=yt("sp"),Ct=yt("rtg"),Ot=yt("rtc");function At(e,t=mo){gt("ec",e,t)}const Rt="components",It="directives";function Nt(e,t){return Dt(Rt,e,!0,t)||e}const Lt=Symbol.for("v-ndc");function xt(e){return(0,o.Kg)(e)?Dt(Rt,e,!1)||e:e||Lt}function Pt(e){return Dt(It,e)}function Dt(e,t,n=!0,r=!1){const i=M||mo;if(i){const n=i.type;if(e===Rt){const e=Po(n,!1);if(e&&(e===t||e===(0,o.PT)(t)||e===(0,o.ZH)((0,o.PT)(t))))return n}const s=Mt(i[e]||n[e],t)||Mt(i.appContext[e],t);return!s&&r?n:s}}function Mt(e,t){return e&&(e[t]||e[(0,o.PT)(t)]||e[(0,o.ZH)((0,o.PT)(t))])}function Ft(e,t,n,i){let s;const a=n&&n[i],l=(0,o.cy)(e);if(l||(0,o.Kg)(e)){const n=l&&(0,r.g8)(e);let o=!1,i=!1;n&&(o=!(0,r.fE)(e),i=(0,r.Tm)(e),e=(0,r.qA)(e)),s=new Array(e.length);for(let l=0,u=e.length;l<u;l++)s[l]=t(o?i?(0,r.a1)((0,r.lJ)(e[l])):(0,r.lJ)(e[l]):e[l],l,void 0,a&&a[l])}else if("number"===typeof e){s=new Array(e);for(let n=0;n<e;n++)s[n]=t(n+1,n,void 0,a&&a[n])}else if((0,o.Gv)(e))if(e[Symbol.iterator])s=Array.from(e,(e,n)=>t(e,n,void 0,a&&a[n]));else{const n=Object.keys(e);s=new Array(n.length);for(let r=0,o=n.length;r<o;r++){const o=n[r];s[r]=t(e[o],o,r,a&&a[r])}}else s=[];return n&&(n[i]=s),s}function $t(e,t){for(let n=0;n<t.length;n++){const r=t[n];if((0,o.cy)(r))for(let t=0;t<r.length;t++)e[r[t].name]=r[t].fn;else r&&(e[r.name]=r.key?(...e)=>{const t=r.fn(...e);return t&&(t.key=r.key),t}:r.fn)}return e}function jt(e,t,n={},r,i){if(M.ce||M.parent&&ot(M.parent)&&M.parent.ce){const e=Object.keys(n).length>0;return"default"!==t&&(n.name=t),jr(),Xr(xr,null,[Zr("slot",n,r&&r())],e?-2:64)}let s=e[t];s&&s._c&&(s._d=!1),jr();const a=s&&Ut(s(n)),l=n.key||a&&a.key,u=Xr(xr,{key:(l&&!(0,o.Bm)(l)?l:`_${t}`)+(!a&&r?"_fb":"")},a||(r?r():[]),a&&1===e._?64:-2);return!i&&u.scopeId&&(u.slotScopeIds=[u.scopeId+"-s"]),s&&s._c&&(s._d=!0),u}function Ut(e){return e.some(e=>!Kr(e)||e.type!==Dr&&!(e.type===xr&&!Ut(e.children)))?e:null}function Bt(e,t){const n={};for(const r in e)n[t&&/[A-Z]/.test(r)?`on:${r}`:(0,o.rU)(r)]=e[r];return n}const Vt=e=>e?Eo(e)?xo(e):Vt(e.parent):null,Gt=(0,o.X$)(Object.create(null),{$:e=>e,$el:e=>e.vnode.el,$data:e=>e.data,$props:e=>e.props,$attrs:e=>e.attrs,$slots:e=>e.slots,$refs:e=>e.refs,$parent:e=>Vt(e.parent),$root:e=>Vt(e.root),$host:e=>e.ce,$emit:e=>e.emit,$options:e=>pn(e),$forceUpdate:e=>e.f||(e.f=()=>{T(e.update)}),$nextTick:e=>e.n||(e.n=w.bind(e.proxy)),$watch:e=>te.bind(e)}),Ht=(e,t)=>e!==o.MZ&&!e.__isScriptSetup&&(0,o.$3)(e,t),Wt={get({_:e},t){if("__v_skip"===t)return!0;const{ctx:n,setupState:i,data:s,props:a,accessCache:l,type:u,appContext:c}=e;if("$"!==t[0]){const e=l[t];if(void 0!==e)switch(e){case 1:return i[t];case 2:return s[t];case 4:return n[t];case 3:return a[t]}else{if(Ht(i,t))return l[t]=1,i[t];if(s!==o.MZ&&(0,o.$3)(s,t))return l[t]=2,s[t];if((0,o.$3)(a,t))return l[t]=3,a[t];if(n!==o.MZ&&(0,o.$3)(n,t))return l[t]=4,n[t];un&&(l[t]=0)}}const d=Gt[t];let f,h;return d?("$attrs"===t&&(0,r.u4)(e.attrs,"get",""),d(e)):(f=u.__cssModules)&&(f=f[t])?f:n!==o.MZ&&(0,o.$3)(n,t)?(l[t]=4,n[t]):(h=c.config.globalProperties,(0,o.$3)(h,t)?h[t]:void 0)},set({_:e},t,n){const{data:r,setupState:i,ctx:s}=e;return Ht(i,t)?(i[t]=n,!0):r!==o.MZ&&(0,o.$3)(r,t)?(r[t]=n,!0):!(0,o.$3)(e.props,t)&&(("$"!==t[0]||!(t.slice(1)in e))&&(s[t]=n,!0))},has({_:{data:e,setupState:t,accessCache:n,ctx:r,appContext:i,props:s,type:a}},l){let u;return!!(n[l]||e!==o.MZ&&"$"!==l[0]&&(0,o.$3)(e,l)||Ht(t,l)||(0,o.$3)(s,l)||(0,o.$3)(r,l)||(0,o.$3)(Gt,l)||(0,o.$3)(i.config.globalProperties,l)||(u=a.__cssModules)&&u[l])},defineProperty(e,t,n){return null!=n.get?e._.accessCache[t]=0:(0,o.$3)(n,"value")&&this.set(e,t,n.value,null),Reflect.defineProperty(e,t,n)}};const Xt=(0,o.X$)({},Wt,{get(e,t){if(t!==Symbol.unscopables)return Wt.get(e,t,e)},has(e,t){const n="_"!==t[0]&&!(0,o.BH)(t);return n}});function Kt(){return null}function qt(){return null}function zt(e){0}function Yt(e){0}function Qt(){return null}function Jt(){0}function Zt(e,t){return null}function en(){return nn("useSlots").slots}function tn(){return nn("useAttrs").attrs}function nn(e){const t=vo();return t.setupContext||(t.setupContext=Lo(t))}function rn(e){return(0,o.cy)(e)?e.reduce((e,t)=>(e[t]=null,e),{}):e}function on(e,t){const n=rn(e);for(const r in t){if(r.startsWith("__skip"))continue;let e=n[r];e?(0,o.cy)(e)||(0,o.Tn)(e)?e=n[r]={type:e,default:t[r]}:e.default=t[r]:null===e&&(e=n[r]={default:t[r]}),e&&t[`__skip_${r}`]&&(e.skipFactory=!0)}return n}function sn(e,t){return e&&t?(0,o.cy)(e)&&(0,o.cy)(t)?e.concat(t):(0,o.X$)({},rn(e),rn(t)):e||t}function an(e,t){const n={};for(const r in e)t.includes(r)||Object.defineProperty(n,r,{enumerable:!0,get:()=>e[r]});return n}function ln(e){const t=vo(),n=To;let r=e();_o(),n&&yo(!1);const i=()=>{bo(t),n&&yo(!0)},s=()=>{vo()!==t&&t.scope.off(),_o(),n&&yo(!1)};return(0,o.yL)(r)&&(r=r.catch(e=>{throw i(),Promise.resolve().then(()=>Promise.resolve().then(s)),e})),[r,()=>{i(),Promise.resolve().then(s)}]}let un=!0;function cn(e){const t=pn(e),n=e.proxy,i=e.ctx;un=!1,t.beforeCreate&&fn(t.beforeCreate,e,"bc");const{data:s,computed:a,methods:l,watch:u,provide:c,inject:d,created:f,beforeMount:h,mounted:p,beforeUpdate:m,updated:v,activated:g,deactivated:y,beforeDestroy:b,beforeUnmount:_,destroyed:E,unmounted:w,render:S,renderTracked:T,renderTriggered:k,errorCaptured:C,serverPrefetch:O,expose:A,inheritAttrs:R,components:I,directives:N,filters:L}=t,x=null;if(d&&dn(d,i,x),l)for(const r in l){const e=l[r];(0,o.Tn)(e)&&(i[r]=e.bind(n))}if(s){0;const t=s.call(n,n);0,(0,o.Gv)(t)&&(e.data=(0,r.Kh)(t))}if(un=!0,a)for(const r in a){const e=a[r],t=(0,o.Tn)(e)?e.bind(n,n):(0,o.Tn)(e.get)?e.get.bind(n,n):o.tE;0;const s=!(0,o.Tn)(e)&&(0,o.Tn)(e.set)?e.set.bind(n):o.tE,l=Mo({get:t,set:s});Object.defineProperty(i,r,{enumerable:!0,configurable:!0,get:()=>l.value,set:e=>l.value=e})}if(u)for(const r in u)hn(u[r],i,n,r);if(c){const e=(0,o.Tn)(c)?c.call(n):c;Reflect.ownKeys(e).forEach(t=>{W(t,e[t])})}function P(e,t){(0,o.cy)(t)?t.forEach(t=>e(t.bind(n))):t&&e(t.bind(n))}if(f&&fn(f,e,"c"),P(bt,h),P(_t,p),P(Et,m),P(wt,v),P(dt,g),P(ft,y),P(At,C),P(Ot,T),P(Ct,k),P(St,_),P(Tt,w),P(kt,O),(0,o.cy)(A))if(A.length){const t=e.exposed||(e.exposed={});A.forEach(e=>{Object.defineProperty(t,e,{get:()=>n[e],set:t=>n[e]=t,enumerable:!0})})}else e.exposed||(e.exposed={});S&&e.render===o.tE&&(e.render=S),null!=R&&(e.inheritAttrs=R),I&&(e.components=I),N&&(e.directives=N),O&&Pe(e)}function dn(e,t,n=o.tE){(0,o.cy)(e)&&(e=bn(e));for(const i in e){const n=e[i];let s;s=(0,o.Gv)(n)?"default"in n?X(n.from||i,n.default,!0):X(n.from||i):X(n),(0,r.i9)(s)?Object.defineProperty(t,i,{enumerable:!0,configurable:!0,get:()=>s.value,set:e=>s.value=e}):t[i]=s}}function fn(e,t,n){f((0,o.cy)(e)?e.map(e=>e.bind(t.proxy)):e.bind(t.proxy),t,n)}function hn(e,t,n,r){let i=r.includes(".")?ne(n,r):()=>n[r];if((0,o.Kg)(e)){const n=t[e];(0,o.Tn)(n)&&Z(i,n)}else if((0,o.Tn)(e))Z(i,e.bind(n));else if((0,o.Gv)(e))if((0,o.cy)(e))e.forEach(e=>hn(e,t,n,r));else{const r=(0,o.Tn)(e.handler)?e.handler.bind(n):t[e.handler];(0,o.Tn)(r)&&Z(i,r,e)}else 0}function pn(e){const t=e.type,{mixins:n,extends:r}=t,{mixins:i,optionsCache:s,config:{optionMergeStrategies:a}}=e.appContext,l=s.get(t);let u;return l?u=l:i.length||n||r?(u={},i.length&&i.forEach(e=>mn(u,e,a,!0)),mn(u,t,a)):u=t,(0,o.Gv)(t)&&s.set(t,u),u}function mn(e,t,n,r=!1){const{mixins:o,extends:i}=t;i&&mn(e,i,n,!0),o&&o.forEach(t=>mn(e,t,n,!0));for(const s in t)if(r&&"expose"===s);else{const r=vn[s]||n&&n[s];e[s]=r?r(e[s],t[s]):t[s]}return e}const vn={data:gn,props:wn,emits:wn,methods:En,computed:En,beforeCreate:_n,created:_n,beforeMount:_n,mounted:_n,beforeUpdate:_n,updated:_n,beforeDestroy:_n,beforeUnmount:_n,destroyed:_n,unmounted:_n,activated:_n,deactivated:_n,errorCaptured:_n,serverPrefetch:_n,components:En,directives:En,watch:Sn,provide:gn,inject:yn};function gn(e,t){return t?e?function(){return(0,o.X$)((0,o.Tn)(e)?e.call(this,this):e,(0,o.Tn)(t)?t.call(this,this):t)}:t:e}function yn(e,t){return En(bn(e),bn(t))}function bn(e){if((0,o.cy)(e)){const t={};for(let n=0;n<e.length;n++)t[e[n]]=e[n];return t}return e}function _n(e,t){return e?[...new Set([].concat(e,t))]:t}function En(e,t){return e?(0,o.X$)(Object.create(null),e,t):t}function wn(e,t){return e?(0,o.cy)(e)&&(0,o.cy)(t)?[...new Set([...e,...t])]:(0,o.X$)(Object.create(null),rn(e),rn(null!=t?t:{})):t}function Sn(e,t){if(!e)return t;if(!t)return e;const n=(0,o.X$)(Object.create(null),e);for(const r in t)n[r]=_n(e[r],t[r]);return n}function Tn(){return{app:null,config:{isNativeTag:o.NO,performance:!1,globalProperties:{},optionMergeStrategies:{},errorHandler:void 0,warnHandler:void 0,compilerOptions:{}},mixins:[],components:{},directives:{},provides:Object.create(null),optionsCache:new WeakMap,propsCache:new WeakMap,emitsCache:new WeakMap}}let kn=0;function Cn(e,t){return function(n,r=null){(0,o.Tn)(n)||(n=(0,o.X$)({},n)),null==r||(0,o.Gv)(r)||(r=null);const i=Tn(),s=new WeakSet,a=[];let l=!1;const u=i.app={_uid:kn++,_component:n,_props:r,_container:null,_context:i,_instance:null,version:Bo,get config(){return i.config},set config(e){0},use(e,...t){return s.has(e)||(e&&(0,o.Tn)(e.install)?(s.add(e),e.install(u,...t)):(0,o.Tn)(e)&&(s.add(e),e(u,...t))),u},mixin(e){return i.mixins.includes(e)||i.mixins.push(e),u},component(e,t){return t?(i.components[e]=t,u):i.components[e]},directive(e,t){return t?(i.directives[e]=t,u):i.directives[e]},mount(o,s,a){if(!l){0;const c=u._ceVNode||Zr(n,r);return c.appContext=i,!0===a?a="svg":!1===a&&(a=void 0),s&&t?t(c,o):e(c,o,a),l=!0,u._container=o,o.__vue_app__=u,xo(c.component)}},onUnmount(e){a.push(e)},unmount(){l&&(f(a,u._instance,16),e(null,u._container),delete u._container.__vue_app__)},provide(e,t){return i.provides[e]=t,u},runWithContext(e){const t=On;On=u;try{return e()}finally{On=t}}};return u}}let On=null;function An(e,t,n=o.MZ){const i=vo();const s=(0,o.PT)(t);const a=(0,o.Tg)(t),l=Rn(e,s),u=(0,r.rY)((r,l)=>{let u,c,d=o.MZ;return J(()=>{const t=e[s];(0,o.$H)(u,t)&&(u=t,l())}),{get(){return r(),n.get?n.get(u):u},set(e){const r=n.set?n.set(e):e;if(!(0,o.$H)(r,u)&&(d===o.MZ||!(0,o.$H)(e,d)))return;const f=i.vnode.props;f&&(t in f||s in f||a in f)&&(`onUpdate:${t}`in f||`onUpdate:${s}`in f||`onUpdate:${a}`in f)||(u=e,l()),i.emit(`update:${t}`,r),(0,o.$H)(e,r)&&(0,o.$H)(e,d)&&!(0,o.$H)(r,c)&&l(),d=e,c=r}}});return u[Symbol.iterator]=()=>{let e=0;return{next(){return e<2?{value:e++?l||o.MZ:u,done:!1}:{done:!0}}}},u}const Rn=(e,t)=>"modelValue"===t||"model-value"===t?e.modelModifiers:e[`${t}Modifiers`]||e[`${(0,o.PT)(t)}Modifiers`]||e[`${(0,o.Tg)(t)}Modifiers`];function In(e,t,...n){if(e.isUnmounted)return;const r=e.vnode.props||o.MZ;let i=n;const s=t.startsWith("update:"),a=s&&Rn(r,t.slice(7));let l;a&&(a.trim&&(i=n.map(e=>(0,o.Kg)(e)?e.trim():e)),a.number&&(i=n.map(o.bB)));let u=r[l=(0,o.rU)(t)]||r[l=(0,o.rU)((0,o.PT)(t))];!u&&s&&(u=r[l=(0,o.rU)((0,o.Tg)(t))]),u&&f(u,e,6,i);const c=r[l+"Once"];if(c){if(e.emitted){if(e.emitted[l])return}else e.emitted={};e.emitted[l]=!0,f(c,e,6,i)}}const Nn=new WeakMap;function Ln(e,t,n=!1){const r=n?Nn:t.emitsCache,i=r.get(e);if(void 0!==i)return i;const s=e.emits;let a={},l=!1;if(!(0,o.Tn)(e)){const r=e=>{const n=Ln(e,t,!0);n&&(l=!0,(0,o.X$)(a,n))};!n&&t.mixins.length&&t.mixins.forEach(r),e.extends&&r(e.extends),e.mixins&&e.mixins.forEach(r)}return s||l?((0,o.cy)(s)?s.forEach(e=>a[e]=null):(0,o.X$)(a,s),(0,o.Gv)(e)&&r.set(e,a),a):((0,o.Gv)(e)&&r.set(e,null),null)}function xn(e,t){return!(!e||!(0,o.Mp)(t))&&(t=t.slice(2).replace(/Once$/,""),(0,o.$3)(e,t[0].toLowerCase()+t.slice(1))||(0,o.$3)(e,(0,o.Tg)(t))||(0,o.$3)(e,t))}function Pn(e){const{type:t,vnode:n,proxy:r,withProxy:i,propsOptions:[s],slots:a,attrs:l,emit:u,render:c,renderCache:d,props:f,data:p,setupState:m,ctx:v,inheritAttrs:g}=e,y=$(e);let b,_;try{if(4&n.shapeFlag){const e=i||r,t=e;b=so(c.call(t,e,d,f,m,p,v)),_=l}else{const e=t;0,b=so(e.length>1?e(f,{attrs:l,slots:a,emit:u}):e(f,null)),_=t.props?l:Mn(l)}}catch(w){Fr.length=0,h(w,e,1),b=Zr(Dr)}let E=b;if(_&&!1!==g){const e=Object.keys(_),{shapeFlag:t}=E;e.length&&7&t&&(s&&e.some(o.CP)&&(_=Fn(_,s)),E=no(E,_,!1,!0))}return n.dirs&&(E=no(E,null,!1,!0),E.dirs=E.dirs?E.dirs.concat(n.dirs):n.dirs),n.transition&&Ie(E,n.transition),b=E,$(y),b}function Dn(e,t=!0){let n;for(let r=0;r<e.length;r++){const t=e[r];if(!Kr(t))return;if(t.type!==Dr||"v-if"===t.children){if(n)return;n=t}}return n}const Mn=e=>{let t;for(const n in e)("class"===n||"style"===n||(0,o.Mp)(n))&&((t||(t={}))[n]=e[n]);return t},Fn=(e,t)=>{const n={};for(const r in e)(0,o.CP)(r)&&r.slice(9)in t||(n[r]=e[r]);return n};function $n(e,t,n){const{props:r,children:o,component:i}=e,{props:s,children:a,patchFlag:l}=t,u=i.emitsOptions;if(t.dirs||t.transition)return!0;if(!(n&&l>=0))return!(!o&&!a||a&&a.$stable)||r!==s&&(r?!s||jn(r,s,u):!!s);if(1024&l)return!0;if(16&l)return r?jn(r,s,u):!!s;if(8&l){const e=t.dynamicProps;for(let t=0;t<e.length;t++){const n=e[t];if(Un(s,r,n)&&!xn(u,n))return!0}}return!1}function jn(e,t,n){const r=Object.keys(t);if(r.length!==Object.keys(e).length)return!0;for(let o=0;o<r.length;o++){const i=r[o];if(Un(t,e,i)&&!xn(n,i))return!0}return!1}function Un(e,t,n){const r=e[n],i=t[n];return"style"===n&&(0,o.Gv)(r)&&(0,o.Gv)(i)?!(0,o.BX)(r,i):r!==i}function Bn({vnode:e,parent:t,suspense:n},r){while(t){const n=t.subTree;if(n.suspense&&n.suspense.activeBranch===e&&(n.suspense.vnode.el=n.el=r,e=n),n!==e)break;(e=t.vnode).el=r,t=t.parent}n&&n.activeBranch===e&&(n.vnode.el=r)}const Vn={},Gn=()=>Object.create(Vn),Hn=e=>Object.getPrototypeOf(e)===Vn;function Wn(e,t,n,o=!1){const i={},s=Gn();e.propsDefaults=Object.create(null),Kn(e,t,i,s);for(const r in e.propsOptions[0])r in i||(i[r]=void 0);n?e.props=o?i:(0,r.Gc)(i):e.type.props?e.props=i:e.props=s,e.attrs=s}function Xn(e,t,n,i){const{props:s,attrs:a,vnode:{patchFlag:l}}=e,u=(0,r.ux)(s),[c]=e.propsOptions;let d=!1;if(!(i||l>0)||16&l){let r;Kn(e,t,s,a)&&(d=!0);for(const i in u)t&&((0,o.$3)(t,i)||(r=(0,o.Tg)(i))!==i&&(0,o.$3)(t,r))||(c?!n||void 0===n[i]&&void 0===n[r]||(s[i]=qn(c,u,i,void 0,e,!0)):delete s[i]);if(a!==u)for(const e in a)t&&(0,o.$3)(t,e)||(delete a[e],d=!0)}else if(8&l){const n=e.vnode.dynamicProps;for(let r=0;r<n.length;r++){let i=n[r];if(xn(e.emitsOptions,i))continue;const l=t[i];if(c)if((0,o.$3)(a,i))l!==a[i]&&(a[i]=l,d=!0);else{const t=(0,o.PT)(i);s[t]=qn(c,u,t,l,e,!1)}else l!==a[i]&&(a[i]=l,d=!0)}}d&&(0,r.hZ)(e.attrs,"set","")}function Kn(e,t,n,i){const[s,a]=e.propsOptions;let l,u=!1;if(t)for(let r in t){if((0,o.SU)(r))continue;const c=t[r];let d;s&&(0,o.$3)(s,d=(0,o.PT)(r))?a&&a.includes(d)?(l||(l={}))[d]=c:n[d]=c:xn(e.emitsOptions,r)||r in i&&c===i[r]||(i[r]=c,u=!0)}if(a){const t=(0,r.ux)(n),i=l||o.MZ;for(let r=0;r<a.length;r++){const l=a[r];n[l]=qn(s,t,l,i[l],e,!(0,o.$3)(i,l))}}return u}function qn(e,t,n,r,i,s){const a=e[n];if(null!=a){const e=(0,o.$3)(a,"default");if(e&&void 0===r){const e=a.default;if(a.type!==Function&&!a.skipFactory&&(0,o.Tn)(e)){const{propsDefaults:o}=i;if(n in o)r=o[n];else{const s=bo(i);r=o[n]=e.call(null,t),s()}}else r=e;i.ce&&i.ce._setProp(n,r)}a[0]&&(s&&!e?r=!1:!a[1]||""!==r&&r!==(0,o.Tg)(n)||(r=!0))}return r}const zn=new WeakMap;function Yn(e,t,n=!1){const r=n?zn:t.propsCache,i=r.get(e);if(i)return i;const s=e.props,a={},l=[];let u=!1;if(!(0,o.Tn)(e)){const r=e=>{u=!0;const[n,r]=Yn(e,t,!0);(0,o.X$)(a,n),r&&l.push(...r)};!n&&t.mixins.length&&t.mixins.forEach(r),e.extends&&r(e.extends),e.mixins&&e.mixins.forEach(r)}if(!s&&!u)return(0,o.Gv)(e)&&r.set(e,o.Oj),o.Oj;if((0,o.cy)(s))for(let d=0;d<s.length;d++){0;const e=(0,o.PT)(s[d]);Qn(e)&&(a[e]=o.MZ)}else if(s){0;for(const e in s){const t=(0,o.PT)(e);if(Qn(t)){const n=s[e],r=a[t]=(0,o.cy)(n)||(0,o.Tn)(n)?{type:n}:(0,o.X$)({},n),i=r.type;let u=!1,c=!0;if((0,o.cy)(i))for(let e=0;e<i.length;++e){const t=i[e],n=(0,o.Tn)(t)&&t.name;if("Boolean"===n){u=!0;break}"String"===n&&(c=!1)}else u=(0,o.Tn)(i)&&"Boolean"===i.name;r[0]=u,r[1]=c,(u||(0,o.$3)(r,"default"))&&l.push(t)}}}const c=[a,l];return(0,o.Gv)(e)&&r.set(e,c),c}function Qn(e){return"$"!==e[0]&&!(0,o.SU)(e)}const Jn=e=>"_"===e||"_ctx"===e||"$stable"===e,Zn=e=>(0,o.cy)(e)?e.map(so):[so(e)],er=(e,t,n)=>{if(t._n)return t;const r=V((...e)=>Zn(t(...e)),n);return r._c=!1,r},tr=(e,t,n)=>{const r=e._ctx;for(const i in e){if(Jn(i))continue;const n=e[i];if((0,o.Tn)(n))t[i]=er(i,n,r);else if(null!=n){0;const e=Zn(n);t[i]=()=>e}}},nr=(e,t)=>{const n=Zn(t);e.slots.default=()=>n},rr=(e,t,n)=>{for(const r in t)!n&&Jn(r)||(e[r]=t[r])},or=(e,t,n)=>{const r=e.slots=Gn();if(32&e.vnode.shapeFlag){const e=t._;e?(rr(r,t,n),n&&(0,o.yQ)(r,"_",e,!0)):tr(t,r)}else t&&nr(e,t)},ir=(e,t,n)=>{const{vnode:r,slots:i}=e;let s=!0,a=o.MZ;if(32&r.shapeFlag){const e=t._;e?n&&1===e?s=!1:rr(i,t,n):(s=!t.$stable,tr(t,i)),a=t}else t&&(nr(e,t),a={default:1});if(s)for(const o in i)Jn(o)||null!=a[o]||delete i[o]};function sr(){}const ar=Ir;function lr(e){return cr(e)}function ur(e){return cr(e,Xe)}function cr(e,t){sr();const n=(0,o.We)();n.__VUE__=!0;const{insert:i,remove:s,patchProp:a,createElement:l,createText:u,createComment:c,setText:d,setElementText:f,parentNode:h,nextSibling:p,setScopeId:m=o.tE,insertStaticContent:v}=e,g=(e,t,n,r=null,o=null,i=null,s=void 0,a=null,l=!!t.dynamicChildren)=>{if(e===t)return;e&&!qr(e,t)&&(r=z(e),G(e,o,i,!0),e=null),-2===t.patchFlag&&(l=!1,t.dynamicChildren=null);const{type:u,ref:c,shapeFlag:d}=t;switch(u){case Pr:y(e,t,n,r);break;case Dr:b(e,t,n,r);break;case Mr:null==e&&_(t,n,r,s);break;case xr:x(e,t,n,r,o,i,s,a,l);break;default:1&d?S(e,t,n,r,o,i,s,a,l):6&d?P(e,t,n,r,o,i,s,a,l):(64&d||128&d)&&u.process(e,t,n,r,o,i,s,a,l,J)}null!=c&&o?$e(c,e&&e.ref,i,t||e,!t):null==c&&e&&null!=e.ref&&$e(e.ref,null,i,e,!0)},y=(e,t,n,r)=>{if(null==e)i(t.el=u(t.children),n,r);else{const n=t.el=e.el;t.children!==e.children&&d(n,t.children)}},b=(e,t,n,r)=>{null==e?i(t.el=c(t.children||""),n,r):t.el=e.el},_=(e,t,n,r)=>{[e.el,e.anchor]=v(e.children,t,n,r,e.el,e.anchor)},E=({el:e,anchor:t},n,r)=>{let o;while(e&&e!==t)o=p(e),i(e,n,r),e=o;i(t,n,r)},w=({el:e,anchor:t})=>{let n;while(e&&e!==t)n=p(e),s(e),e=n;s(t)},S=(e,t,n,r,o,i,s,a,l)=>{if("svg"===t.type?s="svg":"math"===t.type&&(s="mathml"),null==e)k(t,n,r,o,i,s,a,l);else{const n=e.el&&e.el._isVueCE?e.el:null;try{n&&n._beginPatch(),I(e,t,o,i,s,a,l)}finally{n&&n._endPatch()}}},k=(e,t,n,r,s,u,c,d)=>{let h,p;const{props:m,shapeFlag:v,transition:g,dirs:y}=e;if(h=e.el=l(e.type,u,m&&m.is,m),8&v?f(h,e.children):16&v&&R(e.children,h,null,r,s,dr(e,u),c,d),y&&H(e,null,r,"created"),C(h,e,e.scopeId,c,r),m){for(const e in m)"value"===e||(0,o.SU)(e)||a(h,e,null,m[e],u,r);"value"in m&&a(h,"value",null,m.value,u),(p=m.onVnodeBeforeMount)&&co(p,r,e)}y&&H(e,null,r,"beforeMount");const b=hr(s,g);if(b&&g.beforeEnter(h),i(h,t,n),(p=m&&m.onVnodeMounted)||b||y){ar(()=>{try{p&&co(p,r,e),b&&g.enter(h),y&&H(e,null,r,"mounted")}finally{0}},s)}},C=(e,t,n,r,o)=>{if(n&&m(e,n),r)for(let i=0;i<r.length;i++)m(e,r[i]);if(o){let n=o.subTree;if(t===n||br(n.type)&&(n.ssContent===t||n.ssFallback===t)){const t=o.vnode;C(e,t,t.scopeId,t.slotScopeIds,o.parent)}}},R=(e,t,n,r,o,i,s,a,l=0)=>{for(let u=l;u<e.length;u++){const l=e[u]=a?ao(e[u]):so(e[u]);g(null,l,t,n,r,o,i,s,a)}},I=(e,t,n,r,i,s,l)=>{const u=t.el=e.el;let{patchFlag:c,dynamicChildren:d,dirs:h}=t;c|=16&e.patchFlag;const p=e.props||o.MZ,m=t.props||o.MZ;let v;if(n&&fr(n,!1),(v=m.onVnodeBeforeUpdate)&&co(v,n,t,e),h&&H(t,e,n,"beforeUpdate"),n&&fr(n,!0),(p.innerHTML&&null==m.innerHTML||p.textContent&&null==m.textContent)&&f(u,""),d?N(e.dynamicChildren,d,u,n,r,dr(t,i),s):l||j(e,t,u,null,n,r,dr(t,i),s,!1),c>0){if(16&c)L(u,p,m,n,i);else if(2&c&&p.class!==m.class&&a(u,"class",null,m.class,i),4&c&&a(u,"style",p.style,m.style,i),8&c){const e=t.dynamicProps;for(let t=0;t<e.length;t++){const r=e[t],o=p[r],s=m[r];s===o&&"value"!==r||a(u,r,o,s,i,n)}}1&c&&e.children!==t.children&&f(u,t.children)}else l||null!=d||L(u,p,m,n,i);((v=m.onVnodeUpdated)||h)&&ar(()=>{v&&co(v,n,t,e),h&&H(t,e,n,"updated")},r)},N=(e,t,n,r,o,i,s)=>{for(let a=0;a<t.length;a++){const l=e[a],u=t[a],c=l.el&&(l.type===xr||!qr(l,u)||198&l.shapeFlag)?h(l.el):n;g(l,u,c,null,r,o,i,s,!0)}},L=(e,t,n,r,i)=>{if(t!==n){if(t!==o.MZ)for(const s in t)(0,o.SU)(s)||s in n||a(e,s,t[s],null,i,r);for(const s in n){if((0,o.SU)(s))continue;const l=n[s],u=t[s];l!==u&&"value"!==s&&a(e,s,u,l,i,r)}"value"in n&&a(e,"value",t.value,n.value,i)}},x=(e,t,n,r,o,s,a,l,c)=>{const d=t.el=e?e.el:u(""),f=t.anchor=e?e.anchor:u("");let{patchFlag:h,dynamicChildren:p,slotScopeIds:m}=t;m&&(l=l?l.concat(m):m),null==e?(i(d,n,r),i(f,n,r),R(t.children||[],n,f,o,s,a,l,c)):h>0&&64&h&&p&&e.dynamicChildren&&e.dynamicChildren.length===p.length?(N(e.dynamicChildren,p,n,o,s,a,l),(null!=t.key||o&&t===o.subTree)&&pr(e,t,!0)):j(e,t,n,f,o,s,a,l,c)},P=(e,t,n,r,o,i,s,a,l)=>{t.slotScopeIds=a,null==e?512&t.shapeFlag?o.ctx.activate(t,n,r,s,l):D(t,n,r,o,i,s,l):M(e,t,l)},D=(e,t,n,r,o,i,s)=>{const a=e.component=po(e,r,o);if(at(e)&&(a.ctx.renderer=J),ko(a,!1,s),a.asyncDep){if(o&&o.registerDep(a,F,s),!e.el){const r=a.subTree=Zr(Dr);b(null,r,t,n),e.placeholder=r.el}}else F(a,e,t,n,o,i,s)},M=(e,t,n)=>{const r=t.component=e.component;if($n(e,t,n)){if(r.asyncDep&&!r.asyncResolved)return void $(r,t,n);r.next=t,r.update()}else t.el=e.el,r.vnode=t},F=(e,t,n,i,s,a,l)=>{const u=()=>{if(e.isMounted){let{next:t,bu:n,u:r,parent:i,vnode:u}=e;{const n=vr(e);if(n)return t&&(t.el=u.el,$(e,t,l)),void n.asyncDep.then(()=>{ar(()=>{e.isUnmounted||d()},s)})}let c,f=t;0,fr(e,!1),t?(t.el=u.el,$(e,t,l)):t=u,n&&(0,o.DY)(n),(c=t.props&&t.props.onVnodeBeforeUpdate)&&co(c,i,t,u),fr(e,!0);const p=Pn(e);0;const m=e.subTree;e.subTree=p,g(m,p,h(m.el),z(m),e,s,a),t.el=p.el,null===f&&Bn(e,p.el),r&&ar(r,s),(c=t.props&&t.props.onVnodeUpdated)&&ar(()=>co(c,i,t,u),s)}else{let r;const{el:l,props:u}=t,{bm:c,m:d,parent:f,root:h,type:p}=e,m=ot(t);if(fr(e,!1),c&&(0,o.DY)(c),!m&&(r=u&&u.onVnodeBeforeMount)&&co(r,f,t),fr(e,!0),l&&ee){const t=()=>{e.subTree=Pn(e),ee(l,e.subTree,e,s,null)};m&&p.__asyncHydrate?p.__asyncHydrate(l,e,t):t()}else{h.ce&&h.ce._hasShadowRoot()&&h.ce._injectChildStyle(p,e.parent?e.parent.type:void 0);const r=e.subTree=Pn(e);0,g(null,r,n,i,e,s,a),t.el=r.el}if(d&&ar(d,s),!m&&(r=u&&u.onVnodeMounted)){const e=t;ar(()=>co(r,f,e),s)}(256&t.shapeFlag||f&&ot(f.vnode)&&256&f.vnode.shapeFlag)&&e.a&&ar(e.a,s),e.isMounted=!0,t=n=i=null}};e.scope.on();const c=e.effect=new r.X2(u);e.scope.off();const d=e.update=c.run.bind(c),f=e.job=c.runIfDirty.bind(c);f.i=e,f.id=e.uid,c.scheduler=()=>T(f),fr(e,!0),d()},$=(e,t,n)=>{t.component=e;const o=e.vnode.props;e.vnode=t,e.next=null,Xn(e,t.props,o,n),ir(e,t.children,n),(0,r.C4)(),O(e),(0,r.bl)()},j=(e,t,n,r,o,i,s,a,l=!1)=>{const u=e&&e.children,c=e?e.shapeFlag:0,d=t.children,{patchFlag:h,shapeFlag:p}=t;if(h>0){if(128&h)return void B(u,d,n,r,o,i,s,a,l);if(256&h)return void U(u,d,n,r,o,i,s,a,l)}8&p?(16&c&&q(u,o,i),d!==u&&f(n,d)):16&c?16&p?B(u,d,n,r,o,i,s,a,l):q(u,o,i,!0):(8&c&&f(n,""),16&p&&R(d,n,r,o,i,s,a,l))},U=(e,t,n,r,i,s,a,l,u)=>{e=e||o.Oj,t=t||o.Oj;const c=e.length,d=t.length,f=Math.min(c,d);let h;for(h=0;h<f;h++){const r=t[h]=u?ao(t[h]):so(t[h]);g(e[h],r,n,null,i,s,a,l,u)}c>d?q(e,i,s,!0,!1,f):R(t,n,r,i,s,a,l,u,f)},B=(e,t,n,r,i,s,a,l,u)=>{let c=0;const d=t.length;let f=e.length-1,h=d-1;while(c<=f&&c<=h){const r=e[c],o=t[c]=u?ao(t[c]):so(t[c]);if(!qr(r,o))break;g(r,o,n,null,i,s,a,l,u),c++}while(c<=f&&c<=h){const r=e[f],o=t[h]=u?ao(t[h]):so(t[h]);if(!qr(r,o))break;g(r,o,n,null,i,s,a,l,u),f--,h--}if(c>f){if(c<=h){const e=h+1,o=e<d?t[e].el:r;while(c<=h)g(null,t[c]=u?ao(t[c]):so(t[c]),n,o,i,s,a,l,u),c++}}else if(c>h)while(c<=f)G(e[c],i,s,!0),c++;else{const p=c,m=c,v=new Map;for(c=m;c<=h;c++){const e=t[c]=u?ao(t[c]):so(t[c]);null!=e.key&&v.set(e.key,c)}let y,b=0;const _=h-m+1;let E=!1,w=0;const S=new Array(_);for(c=0;c<_;c++)S[c]=0;for(c=p;c<=f;c++){const r=e[c];if(b>=_){G(r,i,s,!0);continue}let o;if(null!=r.key)o=v.get(r.key);else for(y=m;y<=h;y++)if(0===S[y-m]&&qr(r,t[y])){o=y;break}void 0===o?G(r,i,s,!0):(S[o-m]=c+1,o>=w?w=o:E=!0,g(r,t[o],n,null,i,s,a,l,u),b++)}const T=E?mr(S):o.Oj;for(y=T.length-1,c=_-1;c>=0;c--){const e=m+c,o=t[e],f=t[e+1],h=e+1<d?f.el||yr(f):r;0===S[c]?g(null,o,n,h,i,s,a,l,u):E&&(y<0||c!==T[y]?V(o,n,h,2):y--)}}},V=(e,t,n,r,o=null)=>{const{el:a,type:l,transition:u,children:c,shapeFlag:d}=e;if(6&d)return void V(e.component.subTree,t,n,r);if(128&d)return void e.suspense.move(t,n,r);if(64&d)return void l.move(e,t,n,J);if(l===xr){i(a,t,n);for(let e=0;e<c.length;e++)V(c[e],t,n,r);return void i(e.anchor,t,n)}if(l===Mr)return void E(e,t,n);const f=2!==r&&1&d&&u;if(f)if(0===r)u.beforeEnter(a),i(a,t,n),ar(()=>u.enter(a),o);else{const{leave:r,delayLeave:o,afterLeave:l}=u,c=()=>{e.ctx.isUnmounted?s(a):i(a,t,n)},d=()=>{a._isLeaving&&a[ge](!0),r(a,()=>{c(),l&&l()})};o?o(a,c,d):d()}else i(a,t,n)},G=(e,t,n,o=!1,i=!1)=>{const{type:s,props:a,ref:l,children:u,dynamicChildren:c,shapeFlag:d,patchFlag:f,dirs:h,cacheIndex:p,memo:m}=e;if(-2===f&&(i=!1),null!=l&&((0,r.C4)(),$e(l,null,n,e,!0),(0,r.bl)()),null!=p&&(t.renderCache[p]=void 0),256&d)return void t.ctx.deactivate(e);const v=1&d&&h,g=!ot(e);let y;if(g&&(y=a&&a.onVnodeBeforeUnmount)&&co(y,t,e),6&d)K(e.component,n,o);else{if(128&d)return void e.suspense.unmount(n,o);v&&H(e,null,t,"beforeUnmount"),64&d?e.type.remove(e,t,n,J,o):c&&!c.hasOnce&&(s!==xr||f>0&&64&f)?q(c,t,n,!1,!0):(s===xr&&384&f||!i&&16&d)&&q(u,t,n),o&&W(e)}const b=null!=m&&null==p;(g&&(y=a&&a.onVnodeUnmounted)||v||b)&&ar(()=>{y&&co(y,t,e),v&&H(e,null,t,"unmounted"),b&&(e.el=null)},n)},W=e=>{const{type:t,el:n,anchor:r,transition:o}=e;if(t===xr)return void X(n,r);if(t===Mr)return void w(e);const i=()=>{s(n),o&&!o.persisted&&o.afterLeave&&o.afterLeave()};if(1&e.shapeFlag&&o&&!o.persisted){const{leave:t,delayLeave:r}=o,s=()=>t(n,i);r?r(e.el,i,s):s()}else i()},X=(e,t)=>{let n;while(e!==t)n=p(e),s(e),e=n;s(t)},K=(e,t,n)=>{const{bum:r,scope:i,job:s,subTree:a,um:l,m:u,a:c}=e;gr(u),gr(c),r&&(0,o.DY)(r),i.stop(),s&&(s.flags|=8,G(a,e,t,n)),l&&ar(l,t),ar(()=>{e.isUnmounted=!0},t)},q=(e,t,n,r=!1,o=!1,i=0)=>{for(let s=i;s<e.length;s++)G(e[s],t,n,r,o)},z=e=>{if(6&e.shapeFlag)return z(e.component.subTree);if(128&e.shapeFlag)return e.suspense.next();const t=p(e.anchor||e.el),n=t&&t[oe];return n?p(n):t};let Y=!1;const Q=(e,t,n)=>{let r;null==e?t._vnode&&(G(t._vnode,null,null,!0),r=t._vnode.component):g(t._vnode||null,e,t,null,null,null,n),t._vnode=e,Y||(Y=!0,O(r),A(),Y=!1)},J={p:g,um:G,m:V,r:W,mt:D,mc:R,pc:j,pbc:N,n:z,o:e};let Z,ee;return t&&([Z,ee]=t(J)),{render:Q,hydrate:Z,createApp:Cn(Q,Z)}}function dr({type:e,props:t},n){return"svg"===n&&"foreignObject"===e||"mathml"===n&&"annotation-xml"===e&&t&&t.encoding&&t.encoding.includes("html")?void 0:n}function fr({effect:e,job:t},n){n?(e.flags|=32,t.flags|=4):(e.flags&=-33,t.flags&=-5)}function hr(e,t){return(!e||e&&!e.pendingBranch)&&t&&!t.persisted}function pr(e,t,n=!1){const r=e.children,i=t.children;if((0,o.cy)(r)&&(0,o.cy)(i))for(let o=0;o<r.length;o++){const e=r[o];let t=i[o];1&t.shapeFlag&&!t.dynamicChildren&&((t.patchFlag<=0||32===t.patchFlag)&&(t=i[o]=ao(i[o]),t.el=e.el),n||-2===t.patchFlag||pr(e,t)),t.type===Pr&&(-1===t.patchFlag&&(t=i[o]=ao(t)),t.el=e.el),t.type!==Dr||t.el||(t.el=e.el)}}function mr(e){const t=e.slice(),n=[0];let r,o,i,s,a;const l=e.length;for(r=0;r<l;r++){const l=e[r];if(0!==l){if(o=n[n.length-1],e[o]<l){t[r]=o,n.push(r);continue}i=0,s=n.length-1;while(i<s)a=i+s>>1,e[n[a]]<l?i=a+1:s=a;l<e[n[i]]&&(i>0&&(t[r]=n[i-1]),n[i]=r)}}i=n.length,s=n[i-1];while(i-- >0)n[i]=s,s=t[s];return n}function vr(e){const t=e.subTree.component;if(t)return t.asyncDep&&!t.asyncResolved?t:vr(t)}function gr(e){if(e)for(let t=0;t<e.length;t++)e[t].flags|=8}function yr(e){if(e.placeholder)return e.placeholder;const t=e.component;return t?yr(t.subTree):null}const br=e=>e.__isSuspense;let _r=0;const Er={name:"Suspense",__isSuspense:!0,process(e,t,n,r,o,i,s,a,l,u){if(null==e)Tr(t,n,r,o,i,s,a,l,u);else{if(i&&i.deps>0&&!e.suspense.isInFallback)return t.suspense=e.suspense,t.suspense.vnode=t,void(t.el=e.el);kr(e,t,n,r,o,s,a,l,u)}},hydrate:Or,normalize:Ar},wr=Er;function Sr(e,t){const n=e.props&&e.props[t];(0,o.Tn)(n)&&n()}function Tr(e,t,n,r,o,i,s,a,l){const{p:u,o:{createElement:c}}=l,d=c("div"),f=e.suspense=Cr(e,o,r,t,d,n,i,s,a,l);u(null,f.pendingBranch=e.ssContent,d,null,r,f,i,s),f.deps>0?(Sr(e,"onPending"),Sr(e,"onFallback"),u(null,e.ssFallback,t,n,r,null,i,s),Nr(f,e.ssFallback)):f.resolve(!1,!0)}function kr(e,t,n,r,o,i,s,a,{p:l,um:u,o:{createElement:c}}){const d=t.suspense=e.suspense;d.vnode=t,t.el=e.el;const f=t.ssContent,h=t.ssFallback,{activeBranch:p,pendingBranch:m,isInFallback:v,isHydrating:g}=d;if(m)d.pendingBranch=f,qr(m,f)?(l(m,f,d.hiddenContainer,null,o,d,i,s,a),d.deps<=0?d.resolve():v&&(g||(l(p,h,n,r,o,null,i,s,a),Nr(d,h)))):(d.pendingId=_r++,g?(d.isHydrating=!1,d.activeBranch=m):u(m,o,d),d.deps=0,d.effects.length=0,d.hiddenContainer=c("div"),v?(l(null,f,d.hiddenContainer,null,o,d,i,s,a),d.deps<=0?d.resolve():(l(p,h,n,r,o,null,i,s,a),Nr(d,h))):p&&qr(p,f)?(l(p,f,n,r,o,d,i,s,a),d.resolve(!0)):(l(null,f,d.hiddenContainer,null,o,d,i,s,a),d.deps<=0&&d.resolve()));else if(p&&qr(p,f))l(p,f,n,r,o,d,i,s,a),Nr(d,f);else if(Sr(t,"onPending"),d.pendingBranch=f,512&f.shapeFlag?d.pendingId=f.component.suspenseId:d.pendingId=_r++,l(null,f,d.hiddenContainer,null,o,d,i,s,a),d.deps<=0)d.resolve();else{const{timeout:e,pendingId:t}=d;e>0?setTimeout(()=>{d.pendingId===t&&d.fallback(h)},e):0===e&&d.fallback(h)}}function Cr(e,t,n,r,i,s,a,l,u,c,d=!1){const{p:f,m:p,um:m,n:v,o:{parentNode:g,remove:y}}=c;let b;const _=Lr(e);_&&t&&t.pendingBranch&&(b=t.pendingId,t.deps++);const E=e.props?(0,o.Ro)(e.props.timeout):void 0;const w=s,S={vnode:e,parent:t,parentComponent:n,namespace:a,container:r,hiddenContainer:i,deps:0,pendingId:_r++,timeout:"number"===typeof E?E:-1,activeBranch:null,isFallbackMountPending:!1,pendingBranch:null,isInFallback:!d,isHydrating:d,isUnmounted:!1,effects:[],resolve(e=!1,n=!1){const{vnode:r,activeBranch:o,pendingBranch:i,pendingId:a,effects:l,parentComponent:u,container:c,isInFallback:d}=S;let f=!1;S.isHydrating?S.isHydrating=!1:e||(f=o&&i.transition&&"out-in"===i.transition.mode,f&&(o.transition.afterLeave=()=>{a===S.pendingId&&(p(i,c,s===w?v(o):s,0),C(l),d&&r.ssFallback&&(r.ssFallback.el=null))}),o&&!S.isFallbackMountPending&&(g(o.el)===c&&(s=v(o)),m(o,u,S,!0),!f&&d&&r.ssFallback&&ar(()=>r.ssFallback.el=null,S)),f||p(i,c,s,0)),S.isFallbackMountPending=!1,Nr(S,i),S.pendingBranch=null,S.isInFallback=!1;let h=S.parent,y=!1;while(h){if(h.pendingBranch){h.effects.push(...l),y=!0;break}h=h.parent}y||f||C(l),S.effects=[],_&&t&&t.pendingBranch&&b===t.pendingId&&(t.deps--,0!==t.deps||n||t.resolve()),Sr(r,"onResolve")},fallback(e){if(!S.pendingBranch)return;const{vnode:t,activeBranch:n,parentComponent:r,container:o,namespace:i}=S;Sr(t,"onFallback");const s=v(n),a=()=>{S.isFallbackMountPending=!1,S.isInFallback&&(f(null,e,o,s,r,null,i,l,u),Nr(S,e))},c=e.transition&&"out-in"===e.transition.mode;c&&(S.isFallbackMountPending=!0,n.transition.afterLeave=a),S.isInFallback=!0,m(n,r,null,!0),c||a()},move(e,t,n){S.activeBranch&&p(S.activeBranch,e,t,n),S.container=e},next(){return S.activeBranch&&v(S.activeBranch)},registerDep(e,t,n){const r=!!S.pendingBranch;r&&S.deps++;const o=e.vnode.el;e.asyncDep.catch(t=>{h(t,e,0)}).then(i=>{if(e.isUnmounted||S.isUnmounted||S.pendingId!==e.suspenseId)return;_o(),e.asyncResolved=!0;const{vnode:s}=e;Oo(e,i,!1),o&&(s.el=o);const l=!o&&e.subTree.el;t(e,s,g(o||e.subTree.el),o?null:v(e.subTree),S,a,n),l&&(s.placeholder=null,y(l)),Bn(e,s.el),r&&0===--S.deps&&S.resolve()})},unmount(e,t){S.isUnmounted=!0,S.activeBranch&&m(S.activeBranch,n,e,t),S.pendingBranch&&m(S.pendingBranch,n,e,t)}};return S}function Or(e,t,n,r,o,i,s,a,l){const u=t.suspense=Cr(t,r,n,e.parentNode,document.createElement("div"),null,o,i,s,a,!0),c=l(e,u.pendingBranch=t.ssContent,n,u,i,s);return 0===u.deps&&u.resolve(!1,!0),c}function Ar(e){const{shapeFlag:t,children:n}=e,r=32&t;e.ssContent=Rr(r?n.default:n),e.ssFallback=r?Rr(n.fallback):Zr(Dr)}function Rr(e){let t;if((0,o.Tn)(e)){const n=Vr&&e._c;n&&(e._d=!1,jr()),e=e(),n&&(e._d=!0,t=$r,Ur())}if((0,o.cy)(e)){const t=Dn(e);0,e=t}return e=so(e),t&&!e.dynamicChildren&&(e.dynamicChildren=t.filter(t=>t!==e)),e}function Ir(e,t){t&&t.pendingBranch?(0,o.cy)(e)?t.effects.push(...e):t.effects.push(e):C(e)}function Nr(e,t){e.activeBranch=t;const{vnode:n,parentComponent:r}=e;let o=t.el;while(!o&&t.component)t=t.component.subTree,o=t.el;n.el=o,r&&r.subTree===n&&(r.vnode.el=o,Bn(r,o))}function Lr(e){const t=e.props&&e.props.suspensible;return null!=t&&!1!==t}const xr=Symbol.for("v-fgt"),Pr=Symbol.for("v-txt"),Dr=Symbol.for("v-cmt"),Mr=Symbol.for("v-stc"),Fr=[];let $r=null;function jr(e=!1){Fr.push($r=e?null:[])}function Ur(){Fr.pop(),$r=Fr[Fr.length-1]||null}let Br,Vr=1;function Gr(e,t=!1){Vr+=e,e<0&&$r&&t&&($r.hasOnce=!0)}function Hr(e){return e.dynamicChildren=Vr>0?$r||o.Oj:null,Ur(),Vr>0&&$r&&$r.push(e),e}function Wr(e,t,n,r,o,i){return Hr(Jr(e,t,n,r,o,i,!0))}function Xr(e,t,n,r,o){return Hr(Zr(e,t,n,r,o,!0))}function Kr(e){return!!e&&!0===e.__v_isVNode}function qr(e,t){return e.type===t.type&&e.key===t.key}function zr(e){Br=e}const Yr=({key:e})=>null!=e?e:null,Qr=({ref:e,ref_key:t,ref_for:n})=>("number"===typeof e&&(e=""+e),null!=e?(0,o.Kg)(e)||(0,r.i9)(e)||(0,o.Tn)(e)?{i:M,r:e,k:t,f:!!n}:e:null);function Jr(e,t=null,n=null,r=0,i=null,s=(e===xr?0:1),a=!1,l=!1){const u={__v_isVNode:!0,__v_skip:!0,type:e,props:t,key:t&&Yr(t),ref:t&&Qr(t),scopeId:F,slotScopeIds:null,children:n,component:null,suspense:null,ssContent:null,ssFallback:null,dirs:null,transition:null,el:null,anchor:null,target:null,targetStart:null,targetAnchor:null,staticCount:0,shapeFlag:s,patchFlag:r,dynamicProps:i,dynamicChildren:null,appContext:null,ctx:M};return l?(lo(u,n),128&s&&e.normalize(u)):n&&(u.shapeFlag|=(0,o.Kg)(n)?8:16),Vr>0&&!a&&$r&&(u.patchFlag>0||6&s)&&32!==u.patchFlag&&$r.push(u),u}const Zr=eo;function eo(e,t=null,n=null,i=0,s=null,a=!1){if(e&&e!==Lt||(e=Dr),Kr(e)){const r=no(e,t,!0);return n&&lo(r,n),Vr>0&&!a&&$r&&(6&r.shapeFlag?$r[$r.indexOf(e)]=r:$r.push(r)),r.patchFlag=-2,r}if(Do(e)&&(e=e.__vccOpts),t){t=to(t);let{class:e,style:n}=t;e&&!(0,o.Kg)(e)&&(t.class=(0,o.C4)(e)),(0,o.Gv)(n)&&((0,r.ju)(n)&&!(0,o.cy)(n)&&(n=(0,o.X$)({},n)),t.style=(0,o.Tr)(n))}const l=(0,o.Kg)(e)?1:br(e)?128:ie(e)?64:(0,o.Gv)(e)?4:(0,o.Tn)(e)?2:0;return Jr(e,t,n,i,s,l,a,!0)}function to(e){return e?(0,r.ju)(e)||Hn(e)?(0,o.X$)({},e):e:null}function no(e,t,n=!1,r=!1){const{props:i,ref:s,patchFlag:a,children:l,transition:u}=e,c=t?uo(i||{},t):i,d={__v_isVNode:!0,__v_skip:!0,type:e.type,props:c,key:c&&Yr(c),ref:t&&t.ref?n&&s?(0,o.cy)(s)?s.concat(Qr(t)):[s,Qr(t)]:Qr(t):s,scopeId:e.scopeId,slotScopeIds:e.slotScopeIds,children:l,target:e.target,targetStart:e.targetStart,targetAnchor:e.targetAnchor,staticCount:e.staticCount,shapeFlag:e.shapeFlag,patchFlag:t&&e.type!==xr?-1===a?16:16|a:a,dynamicProps:e.dynamicProps,dynamicChildren:e.dynamicChildren,appContext:e.appContext,dirs:e.dirs,transition:u,component:e.component,suspense:e.suspense,ssContent:e.ssContent&&no(e.ssContent),ssFallback:e.ssFallback&&no(e.ssFallback),placeholder:e.placeholder,el:e.el,anchor:e.anchor,ctx:e.ctx,ce:e.ce};return u&&r&&Ie(d,u.clone(d)),d}function ro(e=" ",t=0){return Zr(Pr,null,e,t)}function oo(e,t){const n=Zr(Mr,null,e);return n.staticCount=t,n}function io(e="",t=!1){return t?(jr(),Xr(Dr,null,e)):Zr(Dr,null,e)}function so(e){return null==e||"boolean"===typeof e?Zr(Dr):(0,o.cy)(e)?Zr(xr,null,e.slice()):Kr(e)?ao(e):Zr(Pr,null,String(e))}function ao(e){return null===e.el&&-1!==e.patchFlag||e.memo?e:no(e)}function lo(e,t){let n=0;const{shapeFlag:r}=e;if(null==t)t=null;else if((0,o.cy)(t))n=16;else if("object"===typeof t){if(65&r){const n=t.default;return void(n&&(n._c&&(n._d=!1),lo(e,n()),n._c&&(n._d=!0)))}{n=32;const r=t._;r||Hn(t)?3===r&&M&&(1===M.slots._?t._=1:(t._=2,e.patchFlag|=1024)):t._ctx=M}}else(0,o.Tn)(t)?(t={default:t,_ctx:M},n=32):(t=String(t),64&r?(n=16,t=[ro(t)]):n=8);e.children=t,e.shapeFlag|=n}function uo(...e){const t={};for(let n=0;n<e.length;n++){const r=e[n];for(const e in r)if("class"===e)t.class!==r.class&&(t.class=(0,o.C4)([t.class,r.class]));else if("style"===e)t.style=(0,o.Tr)([t.style,r.style]);else if((0,o.Mp)(e)){const n=t[e],i=r[e];!i||n===i||(0,o.cy)(n)&&n.includes(i)?null!=i||null!=n||(0,o.CP)(e)||(t[e]=i):t[e]=n?[].concat(n,i):i}else""!==e&&(t[e]=r[e])}return t}function co(e,t,n,r=null){f(e,t,7,[n,r])}const fo=Tn();let ho=0;function po(e,t,n){const i=e.type,s=(t?t.appContext:e.appContext)||fo,a={uid:ho++,vnode:e,type:i,parent:t,appContext:s,root:null,next:null,subTree:null,effect:null,update:null,job:null,scope:new r.yC(!0),render:null,proxy:null,exposed:null,exposeProxy:null,withProxy:null,provides:t?t.provides:Object.create(s.provides),ids:t?t.ids:["",0,0],accessCache:null,renderCache:[],components:null,directives:null,propsOptions:Yn(i,s),emitsOptions:Ln(i,s),emit:null,emitted:null,propsDefaults:o.MZ,inheritAttrs:i.inheritAttrs,ctx:o.MZ,data:o.MZ,props:o.MZ,attrs:o.MZ,slots:o.MZ,refs:o.MZ,setupState:o.MZ,setupContext:null,suspense:n,suspenseId:n?n.pendingId:0,asyncDep:null,asyncResolved:!1,isMounted:!1,isUnmounted:!1,isDeactivated:!1,bc:null,c:null,bm:null,m:null,bu:null,u:null,um:null,bum:null,da:null,a:null,rtg:null,rtc:null,ec:null,sp:null};return a.ctx={_:a},a.root=t?t.root:a,a.emit=In.bind(null,a),e.ce&&e.ce(a),a}let mo=null;const vo=()=>mo||M;let go,yo;{const e=(0,o.We)(),t=(t,n)=>{let r;return(r=e[t])||(r=e[t]=[]),r.push(n),e=>{r.length>1?r.forEach(t=>t(e)):r[0](e)}};go=t("__VUE_INSTANCE_SETTERS__",e=>mo=e),yo=t("__VUE_SSR_SETTERS__",e=>To=e)}const bo=e=>{const t=mo;return go(e),e.scope.on(),()=>{e.scope.off(),go(t)}},_o=()=>{mo&&mo.scope.off(),go(null)};function Eo(e){return 4&e.vnode.shapeFlag}let wo,So,To=!1;function ko(e,t=!1,n=!1){t&&yo(t);const{props:r,children:o}=e.vnode,i=Eo(e);Wn(e,r,i,t),or(e,o,n||t);const s=i?Co(e,t):void 0;return t&&yo(!1),s}function Co(e,t){const n=e.type;e.accessCache=Object.create(null),e.proxy=new Proxy(e.ctx,Wt);const{setup:i}=n;if(i){(0,r.C4)();const n=e.setupContext=i.length>1?Lo(e):null,s=bo(e),a=d(i,e,0,[e.props,n]),l=(0,o.yL)(a);if((0,r.bl)(),s(),!l&&!e.sp||ot(e)||Pe(e),l){if(a.then(_o,_o),t)return a.then(n=>{Oo(e,n,t)}).catch(t=>{h(t,e,0)});e.asyncDep=a}else Oo(e,a,t)}else Io(e,t)}function Oo(e,t,n){(0,o.Tn)(t)?e.type.__ssrInlineRender?e.ssrRender=t:e.render=t:(0,o.Gv)(t)&&(e.setupState=(0,r.Pr)(t)),Io(e,n)}function Ao(e){wo=e,So=e=>{e.render._rc&&(e.withProxy=new Proxy(e.ctx,Xt))}}const Ro=()=>!wo;function Io(e,t,n){const i=e.type;if(!e.render){if(!t&&wo&&!i.render){const t=i.template||pn(e).template;if(t){0;const{isCustomElement:n,compilerOptions:r}=e.appContext.config,{delimiters:s,compilerOptions:a}=i,l=(0,o.X$)((0,o.X$)({isCustomElement:n,delimiters:s},r),a);i.render=wo(t,l)}}e.render=i.render||o.tE,So&&So(e)}{const t=bo(e);(0,r.C4)();try{cn(e)}finally{(0,r.bl)(),t()}}}const No={get(e,t){return(0,r.u4)(e,"get",""),e[t]}};function Lo(e){const t=t=>{e.exposed=t||{}};return{attrs:new Proxy(e.attrs,No),slots:e.slots,emit:e.emit,expose:t}}function xo(e){return e.exposed?e.exposeProxy||(e.exposeProxy=new Proxy((0,r.Pr)((0,r.IG)(e.exposed)),{get(t,n){return n in t?t[n]:n in Gt?Gt[n](e):void 0},has(e,t){return t in e||t in Gt}})):e.proxy}function Po(e,t=!0){return(0,o.Tn)(e)?e.displayName||e.name:e.name||t&&e.__name}function Do(e){return(0,o.Tn)(e)&&"__vccOpts"in e}const Mo=(e,t)=>{const n=(0,r.EW)(e,t,To);return n};function Fo(e,t,n){try{Gr(-1);const r=arguments.length;return 2===r?(0,o.Gv)(t)&&!(0,o.cy)(t)?Kr(t)?Zr(e,null,[t]):Zr(e,t):Zr(e,null,t):(r>3?n=Array.prototype.slice.call(arguments,2):3===r&&Kr(n)&&(n=[n]),Zr(e,t,n))}finally{Gr(1)}}function $o(){return void 0}function jo(e,t,n,r){const o=n[r];if(o&&Uo(o,e))return o;const i=t();return i.memo=e.slice(),i.cacheIndex=r,n[r]=i}function Uo(e,t){const n=e.memo;if(n.length!=t.length)return!1;for(let r=0;r<n.length;r++)if((0,o.$H)(n[r],t[r]))return!1;return Vr>0&&$r&&$r.push(e),!0}const Bo="3.5.32",Vo=o.tE,Go=c,Ho=L,Wo=D,Xo={createComponentInstance:po,setupComponent:ko,renderComponentRoot:Pn,setCurrentRenderingInstance:$,isVNode:Kr,normalizeVNode:so,getComponentPublicInstance:xo,ensureValidVNode:Ut,pushWarningContext:s,popWarningContext:a},Ko=Xo,qo=null,zo=null,Yo=null},3751:function(e,t,n){"use strict";n.d(t,{$9:function(){return V},$V:function(){return r.$V},$u:function(){return r.$u},$y:function(){return r.$y},BA:function(){return r.BA},Bi:function(){return r.Bi},Bs:function(){return r.Bs},C4:function(){return r.C4},CE:function(){return r.CE},D:function(){return Se},D$:function(){return tt},Df:function(){return r.Df},Dl:function(){return r.Dl},E:function(){return r.E},E3:function(){return r.E3},EW:function(){return r.EW},EY:function(){return r.EY},Ef:function(){return dt},F:function(){return Ie},FK:function(){return r.FK},Fv:function(){return r.Fv},Fw:function(){return r.Fw},GI:function(){return he},GM:function(){return r.GM},Gc:function(){return r.Gc},Gt:function(){return r.Gt},Gw:function(){return r.Gw},Gy:function(){return r.Gy},H4:function(){return r.H4},HF:function(){return r.HF},Ht:function(){return r.Ht},IG:function(){return r.IG},IJ:function(){return r.IJ},Ib:function(){return vt},Ic:function(){return r.Ic},Im:function(){return r.Im},Jo:function(){return Be},K9:function(){return r.K9},KC:function(){return r.KC},KR:function(){return r.KR},KT:function(){return Ee},Kf:function(){return r.Kf},Kh:function(){return r.Kh},LJ:function(){return r.LJ},LM:function(){return r.LM},Lk:function(){return r.Lk},Lu:function(){return r.Lu},MZ:function(){return r.MZ},Mw:function(){return r.Mw},NP:function(){return r.NP},Ng:function(){return r.Ng},OA:function(){return r.OA},OW:function(){return r.OW},PP:function(){return r.PP},PR:function(){return r.PR},PS:function(){return r.PS},PT:function(){return r.PT},Pn:function(){return r.Pn},Po:function(){return ye},Pr:function(){return r.Pr},Q3:function(){return r.Q3},QP:function(){return r.QP},QW:function(){return r.QW},QZ:function(){return r.QZ},Qi:function(){return r.Qi},Qv:function(){return ct},R1:function(){return r.R1},R8:function(){return r.R8},RD:function(){return h},RG:function(){return r.RG},SS:function(){return r.SS},Tb:function(){return r.Tb},Tm:function(){return r.Tm},Tq:function(){return r.Tq},Tr:function(){return r.Tr},U4:function(){return r.U4},U_:function(){return r.U_},Ul:function(){return r.Ul},Vq:function(){return r.Vq},Vy:function(){return _e},WQ:function(){return r.WQ},Wv:function(){return r.Wv},X2:function(){return r.X2},XL:function(){return He},XX:function(){return ut},Xq:function(){return ge},Y4:function(){return r.Y4},Y5:function(){return r.Y5},YY:function(){return r.YY},Yj:function(){return r.Yj},Yv:function(){return r.Yv},ZH:function(){return r.ZH},ZQ:function(){return r.ZQ},_B:function(){return r._B},_U:function(){return we},aG:function(){return $},aT:function(){return r.aT},bF:function(){return r.bF},bU:function(){return r.bU},bj:function(){return r.bj},bn:function(){return r.bn},bo:function(){return r.bo},ch:function(){return r.ch},ci:function(){return r.ci},dA:function(){return r.dA},dY:function(){return r.dY},ds:function(){return r.ds},eB:function(){return _},eW:function(){return r.eW},eX:function(){return r.eX},fE:function(){return r.fE},fn:function(){return r.fn},g2:function(){return r.g2},g8:function(){return r.g8},gN:function(){return r.gN},gW:function(){return r.gW},gh:function(){return r.gh},h:function(){return r.h},hi:function(){return r.hi},hp:function(){return ze},i9:function(){return r.i9},iD:function(){return r.iD},jC:function(){return r.jC},jR:function(){return rt},jr:function(){return r.jr},jt:function(){return r.jt},ju:function(){return r.ju},k6:function(){return r.k6},lH:function(){return Ve},lW:function(){return r.lW},lt:function(){return r.lt},m1:function(){return ft},mu:function(){return r.mu},n:function(){return r.n},nD:function(){return r.nD},nI:function(){return r.nI},nT:function(){return r.nT},o5:function(){return r.o5},p9:function(){return r.p9},pI:function(){return r.pI},pM:function(){return r.pM},pR:function(){return r.pR},qG:function(){return r.qG},qL:function(){return r.qL},qP:function(){return r.qP},qR:function(){return r.qR},rE:function(){return r.rE},rO:function(){return r.rO},rU:function(){return r.rU},rY:function(){return r.rY},rk:function(){return r.rk},sV:function(){return r.sV},tB:function(){return r.tB},tC:function(){return r.tC},tG:function(){return r.tG},tY:function(){return r.tY},u1:function(){return We},uX:function(){return r.uX},uY:function(){return r.uY},ux:function(){return r.ux},v6:function(){return r.v6},v_:function(){return r.v_},vv:function(){return r.vv},wB:function(){return r.wB},wX:function(){return r.wX},wk:function(){return r.wk},xo:function(){return r.xo},y$:function(){return r.y$},yC:function(){return r.yC},zz:function(){return r.zz}});var r=n(641),o=n(953),i=n(33);
/**
* @vue/runtime-dom v3.5.32
* (c) 2018-present Yuxi (Evan) You and Vue contributors
* @license MIT
**/
let s;const a="undefined"!==typeof window&&window.trustedTypes;if(a)try{s=a.createPolicy("vue",{createHTML:e=>e})}catch(gt){}const l=s?e=>s.createHTML(e):e=>e,u="http://www.w3.org/2000/svg",c="http://www.w3.org/1998/Math/MathML",d="undefined"!==typeof document?document:null,f=d&&d.createElement("template"),h={insert:(e,t,n)=>{t.insertBefore(e,n||null)},remove:e=>{const t=e.parentNode;t&&t.removeChild(e)},createElement:(e,t,n,r)=>{const o="svg"===t?d.createElementNS(u,e):"mathml"===t?d.createElementNS(c,e):n?d.createElement(e,{is:n}):d.createElement(e);return"select"===e&&r&&null!=r.multiple&&o.setAttribute("multiple",r.multiple),o},createText:e=>d.createTextNode(e),createComment:e=>d.createComment(e),setText:(e,t)=>{e.nodeValue=t},setElementText:(e,t)=>{e.textContent=t},parentNode:e=>e.parentNode,nextSibling:e=>e.nextSibling,querySelector:e=>d.querySelector(e),setScopeId(e,t){e.setAttribute(t,"")},insertStaticContent(e,t,n,r,o,i){const s=n?n.previousSibling:t.lastChild;if(o&&(o===i||o.nextSibling)){while(1)if(t.insertBefore(o.cloneNode(!0),n),o===i||!(o=o.nextSibling))break}else{f.innerHTML=l("svg"===r?`<svg>${e}</svg>`:"mathml"===r?`<math>${e}</math>`:e);const o=f.content;if("svg"===r||"mathml"===r){const e=o.firstChild;while(e.firstChild)o.appendChild(e.firstChild);o.removeChild(e)}t.insertBefore(o,n)}return[s?s.nextSibling:t.firstChild,n?n.previousSibling:t.lastChild]}},p="transition",m="animation",v=Symbol("_vtc"),g={name:String,type:String,css:{type:Boolean,default:!0},duration:[String,Number,Object],enterFromClass:String,enterActiveClass:String,enterToClass:String,appearFromClass:String,appearActiveClass:String,appearToClass:String,leaveFromClass:String,leaveActiveClass:String,leaveToClass:String},y=(0,i.X$)({},r.QP,g),b=e=>(e.displayName="Transition",e.props=y,e),_=b((e,{slots:t})=>(0,r.h)(r.pR,S(e),t)),E=(e,t=[])=>{(0,i.cy)(e)?e.forEach(e=>e(...t)):e&&e(...t)},w=e=>!!e&&((0,i.cy)(e)?e.some(e=>e.length>1):e.length>1);function S(e){const t={};for(const i in e)i in g||(t[i]=e[i]);if(!1===e.css)return t;const{name:n="v",type:r,duration:o,enterFromClass:s=`${n}-enter-from`,enterActiveClass:a=`${n}-enter-active`,enterToClass:l=`${n}-enter-to`,appearFromClass:u=s,appearActiveClass:c=a,appearToClass:d=l,leaveFromClass:f=`${n}-leave-from`,leaveActiveClass:h=`${n}-leave-active`,leaveToClass:p=`${n}-leave-to`}=e,m=T(o),v=m&&m[0],y=m&&m[1],{onBeforeEnter:b,onEnter:_,onEnterCancelled:S,onLeave:k,onLeaveCancelled:R,onBeforeAppear:N=b,onAppear:L=_,onAppearCancelled:x=S}=t,D=(e,t,n,r)=>{e._enterCancelled=r,O(e,t?d:l),O(e,t?c:a),n&&n()},M=(e,t)=>{e._isLeaving=!1,O(e,f),O(e,p),O(e,h),t&&t()},F=e=>(t,n)=>{const o=e?L:_,i=()=>D(t,e,n);E(o,[t,i]),A(()=>{O(t,e?u:s),C(t,e?d:l),w(o)||I(t,r,v,i)})};return(0,i.X$)(t,{onBeforeEnter(e){E(b,[e]),C(e,s),C(e,a)},onBeforeAppear(e){E(N,[e]),C(e,u),C(e,c)},onEnter:F(!1),onAppear:F(!0),onLeave(e,t){e._isLeaving=!0;const n=()=>M(e,t);C(e,f),e._enterCancelled?(C(e,h),P(e)):(P(e),C(e,h)),A(()=>{e._isLeaving&&(O(e,f),C(e,p),w(k)||I(e,r,y,n))}),E(k,[e,n])},onEnterCancelled(e){D(e,!1,void 0,!0),E(S,[e])},onAppearCancelled(e){D(e,!0,void 0,!0),E(x,[e])},onLeaveCancelled(e){M(e),E(R,[e])}})}function T(e){if(null==e)return null;if((0,i.Gv)(e))return[k(e.enter),k(e.leave)];{const t=k(e);return[t,t]}}function k(e){const t=(0,i.Ro)(e);return t}function C(e,t){t.split(/\s+/).forEach(t=>t&&e.classList.add(t)),(e[v]||(e[v]=new Set)).add(t)}function O(e,t){t.split(/\s+/).forEach(t=>t&&e.classList.remove(t));const n=e[v];n&&(n.delete(t),n.size||(e[v]=void 0))}function A(e){requestAnimationFrame(()=>{requestAnimationFrame(e)})}let R=0;function I(e,t,n,r){const o=e._endId=++R,i=()=>{o===e._endId&&r()};if(null!=n)return setTimeout(i,n);const{type:s,timeout:a,propCount:l}=N(e,t);if(!s)return r();const u=s+"end";let c=0;const d=()=>{e.removeEventListener(u,f),i()},f=t=>{t.target===e&&++c>=l&&d()};setTimeout(()=>{c<l&&d()},a+1),e.addEventListener(u,f)}function N(e,t){const n=window.getComputedStyle(e),r=e=>(n[e]||"").split(", "),o=r(`${p}Delay`),i=r(`${p}Duration`),s=L(o,i),a=r(`${m}Delay`),l=r(`${m}Duration`),u=L(a,l);let c=null,d=0,f=0;t===p?s>0&&(c=p,d=s,f=i.length):t===m?u>0&&(c=m,d=u,f=l.length):(d=Math.max(s,u),c=d>0?s>u?p:m:null,f=c?c===p?i.length:l.length:0);const h=c===p&&/\b(?:transform|all)(?:,|$)/.test(r(`${p}Property`).toString());return{type:c,timeout:d,propCount:f,hasTransform:h}}function L(e,t){while(e.length<t.length)e=e.concat(e);return Math.max(...t.map((t,n)=>x(t)+x(e[n])))}function x(e){return"auto"===e?0:1e3*Number(e.slice(0,-1).replace(",","."))}function P(e){const t=e?e.ownerDocument:document;return t.body.offsetHeight}function D(e,t,n){const r=e[v];r&&(t=(t?[t,...r]:[...r]).join(" ")),null==t?e.removeAttribute("class"):n?e.setAttribute("class",t):e.className=t}const M=Symbol("_vod"),F=Symbol("_vsh"),$={name:"show",beforeMount(e,{value:t},{transition:n}){e[M]="none"===e.style.display?"":e.style.display,n&&t?n.beforeEnter(e):j(e,t)},mounted(e,{value:t},{transition:n}){n&&t&&n.enter(e)},updated(e,{value:t,oldValue:n},{transition:r}){!t!==!n&&(r?t?(r.beforeEnter(e),j(e,!0),r.enter(e)):r.leave(e,()=>{j(e,!1)}):j(e,t))},beforeUnmount(e,{value:t}){j(e,t)}};function j(e,t){e.style.display=t?e[M]:"none",e[F]=!t}function U(){$.getSSRProps=({value:e})=>{if(!e)return{style:{display:"none"}}}}const B=Symbol("");function V(e){const t=(0,r.nI)();if(!t)return;const n=t.ut=(n=e(t.proxy))=>{Array.from(document.querySelectorAll(`[data-v-owner="${t.uid}"]`)).forEach(e=>H(e,n))};const o=()=>{const r=e(t.proxy);t.ce?H(t.ce,r):G(t.subTree,r),n(r)};(0,r.Ic)(()=>{(0,r.Dl)(o)}),(0,r.sV)(()=>{(0,r.wB)(o,i.tE,{flush:"post"});const e=new MutationObserver(o);e.observe(t.subTree.el.parentNode,{childList:!0}),(0,r.hi)(()=>e.disconnect())})}function G(e,t){if(128&e.shapeFlag){const n=e.suspense;e=n.activeBranch,n.pendingBranch&&!n.isHydrating&&n.effects.push(()=>{G(n.activeBranch,t)})}while(e.component)e=e.component.subTree;if(1&e.shapeFlag&&e.el)H(e.el,t);else if(e.type===r.FK)e.children.forEach(e=>G(e,t));else if(e.type===r.jC){let{el:n,anchor:r}=e;while(n){if(H(n,t),n===r)break;n=n.nextSibling}}}function H(e,t){if(1===e.nodeType){const n=e.style;let r="";for(const e in t){const o=(0,i.pU)(t[e]);n.setProperty(`--${e}`,o),r+=`--${e}: ${o};`}n[B]=r}}const W=/(?:^|;)\s*display\s*:/;function X(e,t,n){const r=e.style,o=(0,i.Kg)(n);let s=!1;if(n&&!o){if(t)if((0,i.Kg)(t))for(const e of t.split(";")){const t=e.slice(0,e.indexOf(":")).trim();null==n[t]&&q(r,t,"")}else for(const e in t)null==n[e]&&q(r,e,"");for(const e in n)"display"===e&&(s=!0),q(r,e,n[e])}else if(o){if(t!==n){const e=r[B];e&&(n+=";"+e),r.cssText=n,s=W.test(n)}}else t&&e.removeAttribute("style");M in e&&(e[M]=s?r.display:"",e[F]&&(r.display="none"))}const K=/\s*!important$/;function q(e,t,n){if((0,i.cy)(n))n.forEach(n=>q(e,t,n));else if(null==n&&(n=""),t.startsWith("--"))e.setProperty(t,n);else{const r=Q(e,t);K.test(n)?e.setProperty((0,i.Tg)(r),n.replace(K,""),"important"):e[r]=n}}const z=["Webkit","Moz","ms"],Y={};function Q(e,t){const n=Y[t];if(n)return n;let r=(0,i.PT)(t);if("filter"!==r&&r in e)return Y[t]=r;r=(0,i.ZH)(r);for(let o=0;o<z.length;o++){const n=z[o]+r;if(n in e)return Y[t]=n}return t}const J="http://www.w3.org/1999/xlink";function Z(e,t,n,r,o,s=(0,i.J$)(t)){r&&t.startsWith("xlink:")?null==n?e.removeAttributeNS(J,t.slice(6,t.length)):e.setAttributeNS(J,t,n):null==n||s&&!(0,i.Y2)(n)?e.removeAttribute(t):e.setAttribute(t,s?"":(0,i.Bm)(n)?String(n):n)}function ee(e,t,n,r,o){if("innerHTML"===t||"textContent"===t)return void(null!=n&&(e[t]="innerHTML"===t?l(n):n));const s=e.tagName;if("value"===t&&"PROGRESS"!==s&&!s.includes("-")){const r="OPTION"===s?e.getAttribute("value")||"":e.value,o=null==n?"checkbox"===e.type?"on":"":String(n);return r===o&&"_value"in e||(e.value=o),null==n&&e.removeAttribute(t),void(e._value=n)}let a=!1;if(""===n||null==n){const r=typeof e[t];"boolean"===r?n=(0,i.Y2)(n):null==n&&"string"===r?(n="",a=!0):"number"===r&&(n=0,a=!0)}try{e[t]=n}catch(gt){0}a&&e.removeAttribute(o||t)}function te(e,t,n,r){e.addEventListener(t,n,r)}function ne(e,t,n,r){e.removeEventListener(t,n,r)}const re=Symbol("_vei");function oe(e,t,n,r,o=null){const i=e[re]||(e[re]={}),s=i[t];if(r&&s)s.value=r;else{const[n,a]=se(t);if(r){const s=i[t]=ce(r,o);te(e,n,s,a)}else s&&(ne(e,n,s,a),i[t]=void 0)}}const ie=/(?:Once|Passive|Capture)$/;function se(e){let t;if(ie.test(e)){let n;t={};while(n=e.match(ie))e=e.slice(0,e.length-n[0].length),t[n[0].toLowerCase()]=!0}const n=":"===e[2]?e.slice(3):(0,i.Tg)(e.slice(2));return[n,t]}let ae=0;const le=Promise.resolve(),ue=()=>ae||(le.then(()=>ae=0),ae=Date.now());function ce(e,t){const n=e=>{if(e._vts){if(e._vts<=n.attached)return}else e._vts=Date.now();(0,r.qL)(de(e,n.value),t,5,[e])};return n.value=e,n.attached=ue(),n}function de(e,t){if((0,i.cy)(t)){const n=e.stopImmediatePropagation;return e.stopImmediatePropagation=()=>{n.call(e),e._stopped=!0},t.map(e=>t=>!t._stopped&&e&&e(t))}return t}const fe=e=>111===e.charCodeAt(0)&&110===e.charCodeAt(1)&&e.charCodeAt(2)>96&&e.charCodeAt(2)<123,he=(e,t,n,r,o,s)=>{const a="svg"===o;"class"===t?D(e,r,a):"style"===t?X(e,n,r):(0,i.Mp)(t)?(0,i.CP)(t)||oe(e,t,n,r,s):("."===t[0]?(t=t.slice(1),1):"^"===t[0]?(t=t.slice(1),0):pe(e,t,r,a))?(ee(e,t,r),e.tagName.includes("-")||"value"!==t&&"checked"!==t&&"selected"!==t||Z(e,t,r,a,s,"value"!==t)):e._isVueCE&&(me(e,t)||e._def.__asyncLoader&&(/[A-Z]/.test(t)||!(0,i.Kg)(r)))?ee(e,(0,i.PT)(t),r,s,t):("true-value"===t?e._trueValue=r:"false-value"===t&&(e._falseValue=r),Z(e,t,r,a))};function pe(e,t,n,r){if(r)return"innerHTML"===t||"textContent"===t||!!(t in e&&fe(t)&&(0,i.Tn)(n));if("spellcheck"===t||"draggable"===t||"translate"===t||"autocorrect"===t)return!1;if("sandbox"===t&&"IFRAME"===e.tagName)return!1;if("form"===t)return!1;if("list"===t&&"INPUT"===e.tagName)return!1;if("type"===t&&"TEXTAREA"===e.tagName)return!1;if("width"===t||"height"===t){const t=e.tagName;if("IMG"===t||"VIDEO"===t||"CANVAS"===t||"SOURCE"===t)return!1}return(!fe(t)||!(0,i.Kg)(n))&&t in e}function me(e,t){const n=e._def.props;if(!n)return!1;const r=(0,i.PT)(t);return Array.isArray(n)?n.some(e=>(0,i.PT)(e)===r):Object.keys(n).some(e=>(0,i.PT)(e)===r)}const ve={};function ge(e,t,n){let o=(0,r.pM)(e,t);(0,i.Qd)(o)&&(o=(0,i.X$)({},o,t));class s extends _e{constructor(e){super(o,e,n)}}return s.def=o,s}const ye=(e,t)=>ge(e,t,ft),be="undefined"!==typeof HTMLElement?HTMLElement:class{};class _e extends be{constructor(e,t={},n=dt){super(),this._def=e,this._props=t,this._createApp=n,this._isVueCE=!0,this._instance=null,this._app=null,this._nonce=this._def.nonce,this._connected=!1,this._resolved=!1,this._patching=!1,this._dirty=!1,this._numberProps=null,this._styleChildren=new WeakSet,this._styleAnchors=new WeakMap,this._ob=null,this.shadowRoot&&n!==dt?this._root=this.shadowRoot:!1!==e.shadowRoot?(this.attachShadow((0,i.X$)({},e.shadowRootOptions,{mode:"open"})),this._root=this.shadowRoot):this._root=this}connectedCallback(){if(!this.isConnected)return;this.shadowRoot||this._resolved||this._parseSlots(),this._connected=!0;let e=this;while(e=e&&(e.assignedSlot||e.parentNode||e.host))if(e instanceof _e){this._parent=e;break}this._instance||(this._resolved?this._mount(this._def):e&&e._pendingResolve?this._pendingResolve=e._pendingResolve.then(()=>{this._pendingResolve=void 0,this._resolveDef()}):this._resolveDef())}_setParent(e=this._parent){e&&(this._instance.parent=e._instance,this._inheritParentContext(e))}_inheritParentContext(e=this._parent){e&&this._app&&Object.setPrototypeOf(this._app._context.provides,e._instance.provides)}disconnectedCallback(){this._connected=!1,(0,r.dY)(()=>{this._connected||(this._ob&&(this._ob.disconnect(),this._ob=null),this._app&&this._app.unmount(),this._instance&&(this._instance.ce=void 0),this._app=this._instance=null,this._teleportTargets&&(this._teleportTargets.clear(),this._teleportTargets=void 0))})}_processMutations(e){for(const t of e)this._setAttr(t.attributeName)}_resolveDef(){if(this._pendingResolve)return;for(let n=0;n<this.attributes.length;n++)this._setAttr(this.attributes[n].name);this._ob=new MutationObserver(this._processMutations.bind(this)),this._ob.observe(this,{attributes:!0});const e=(e,t=!1)=>{this._resolved=!0,this._pendingResolve=void 0;const{props:n,styles:r}=e;let o;if(n&&!(0,i.cy)(n))for(const s in n){const e=n[s];(e===Number||e&&e.type===Number)&&(s in this._props&&(this._props[s]=(0,i.Ro)(this._props[s])),(o||(o=Object.create(null)))[(0,i.PT)(s)]=!0)}this._numberProps=o,this._resolveProps(e),this.shadowRoot&&this._applyStyles(r),this._mount(e)},t=this._def.__asyncLoader;t?this._pendingResolve=t().then(t=>{t.configureApp=this._def.configureApp,e(this._def=t,!0)}):e(this._def)}_mount(e){this._app=this._createApp(e),this._inheritParentContext(),e.configureApp&&e.configureApp(this._app),this._app._ceVNode=this._createVNode(),this._app.mount(this._root);const t=this._instance&&this._instance.exposed;if(t)for(const n in t)(0,i.$3)(this,n)||Object.defineProperty(this,n,{get:()=>(0,o.R1)(t[n])})}_resolveProps(e){const{props:t}=e,n=(0,i.cy)(t)?t:Object.keys(t||{});for(const r of Object.keys(this))"_"!==r[0]&&n.includes(r)&&this._setProp(r,this[r]);for(const r of n.map(i.PT))Object.defineProperty(this,r,{get(){return this._getProp(r)},set(e){this._setProp(r,e,!0,!this._patching)}})}_setAttr(e){if(e.startsWith("data-v-"))return;const t=this.hasAttribute(e);let n=t?this.getAttribute(e):ve;const r=(0,i.PT)(e);t&&this._numberProps&&this._numberProps[r]&&(n=(0,i.Ro)(n)),this._setProp(r,n,!1,!0)}_getProp(e){return this._props[e]}_setProp(e,t,n=!0,r=!1){if(t!==this._props[e]&&(this._dirty=!0,t===ve?delete this._props[e]:(this._props[e]=t,"key"===e&&this._app&&(this._app._ceVNode.key=t)),r&&this._instance&&this._update(),n)){const n=this._ob;n&&(this._processMutations(n.takeRecords()),n.disconnect()),!0===t?this.setAttribute((0,i.Tg)(e),""):"string"===typeof t||"number"===typeof t?this.setAttribute((0,i.Tg)(e),t+""):t||this.removeAttribute((0,i.Tg)(e)),n&&n.observe(this,{attributes:!0})}}_update(){const e=this._createVNode();this._app&&(e.appContext=this._app._context),ut(e,this._root)}_createVNode(){const e={};this.shadowRoot||(e.onVnodeMounted=e.onVnodeUpdated=this._renderSlots.bind(this));const t=(0,r.bF)(this._def,(0,i.X$)(e,this._props));return this._instance||(t.ce=e=>{this._instance=e,e.ce=this,e.isCE=!0;const t=(e,t)=>{this.dispatchEvent(new CustomEvent(e,(0,i.Qd)(t[0])?(0,i.X$)({detail:t},t[0]):{detail:t}))};e.emit=(e,...n)=>{t(e,n),(0,i.Tg)(e)!==e&&t((0,i.Tg)(e),n)},this._setParent()}),t}_applyStyles(e,t,n){if(!e)return;if(t){if(t===this._def||this._styleChildren.has(t))return;this._styleChildren.add(t)}const r=this._nonce,o=this.shadowRoot,i=n?this._getStyleAnchor(n)||this._getStyleAnchor(this._def):this._getRootStyleInsertionAnchor(o);let s=null;for(let a=e.length-1;a>=0;a--){const l=document.createElement("style");r&&l.setAttribute("nonce",r),l.textContent=e[a],o.insertBefore(l,s||i),s=l,0===a&&(n||this._styleAnchors.set(this._def,l),t&&this._styleAnchors.set(t,l))}}_getStyleAnchor(e){if(!e)return null;const t=this._styleAnchors.get(e);return t&&t.parentNode===this.shadowRoot?t:(t&&this._styleAnchors.delete(e),null)}_getRootStyleInsertionAnchor(e){for(let t=0;t<e.childNodes.length;t++){const n=e.childNodes[t];if(!(n instanceof HTMLStyleElement))return n}return null}_parseSlots(){const e=this._slots={};let t;while(t=this.firstChild){const n=1===t.nodeType&&t.getAttribute("slot")||"default";(e[n]||(e[n]=[])).push(t),this.removeChild(t)}}_renderSlots(){const e=this._getSlots(),t=this._instance.type.__scopeId;for(let n=0;n<e.length;n++){const r=e[n],o=r.getAttribute("name")||"default",i=this._slots[o],s=r.parentNode;if(i)for(const e of i){if(t&&1===e.nodeType){const n=t+"-s",r=document.createTreeWalker(e,1);let o;e.setAttribute(n,"");while(o=r.nextNode())o.setAttribute(n,"")}s.insertBefore(e,r)}else while(r.firstChild)s.insertBefore(r.firstChild,r);s.removeChild(r)}}_getSlots(){const e=[this];this._teleportTargets&&e.push(...this._teleportTargets);const t=new Set;for(const n of e){const e=n.querySelectorAll("slot");for(let n=0;n<e.length;n++)t.add(e[n])}return Array.from(t)}_injectChildStyle(e,t){this._applyStyles(e.styles,e,t)}_beginPatch(){this._patching=!0,this._dirty=!1}_endPatch(){this._patching=!1,this._dirty&&this._instance&&this._update()}_hasShadowRoot(){return!1!==this._def.shadowRoot}_removeChildStyle(e){0}}function Ee(e){const t=(0,r.nI)(),n=t&&t.ce;return n||null}function we(){const e=Ee();return e&&e.shadowRoot}function Se(e="$style"){{const t=(0,r.nI)();if(!t)return i.MZ;const n=t.type.__cssModules;if(!n)return i.MZ;const o=n[e];return o||i.MZ}}const Te=new WeakMap,ke=new WeakMap,Ce=Symbol("_moveCb"),Oe=Symbol("_enterCb"),Ae=e=>(delete e.props.mode,e),Re=Ae({name:"TransitionGroup",props:(0,i.X$)({},y,{tag:String,moveClass:String}),setup(e,{slots:t}){const n=(0,r.nI)(),i=(0,r.Gy)();let s,a;return(0,r.$u)(()=>{if(!s.length)return;const t=e.moveClass||`${e.name||"v"}-move`;if(!De(s[0].el,n.vnode.el,t))return void(s=[]);s.forEach(Ne),s.forEach(Le);const r=s.filter(xe);P(n.vnode.el),r.forEach(e=>{const n=e.el,r=n.style;C(n,t),r.transform=r.webkitTransform=r.transitionDuration="";const o=n[Ce]=e=>{e&&e.target!==n||e&&!e.propertyName.endsWith("transform")||(n.removeEventListener("transitionend",o),n[Ce]=null,O(n,t))};n.addEventListener("transitionend",o)}),s=[]}),()=>{const l=(0,o.ux)(e),u=S(l);let c=l.tag||r.FK;if(s=[],a)for(let e=0;e<a.length;e++){const t=a[e];t.el&&t.el instanceof Element&&(s.push(t),(0,r.MZ)(t,(0,r.OW)(t,u,i,n)),Te.set(t,Pe(t.el)))}a=t.default?(0,r.Df)(t.default()):[];for(let e=0;e<a.length;e++){const t=a[e];null!=t.key&&(0,r.MZ)(t,(0,r.OW)(t,u,i,n))}return(0,r.bF)(c,null,a)}}}),Ie=Re;function Ne(e){const t=e.el;t[Ce]&&t[Ce](),t[Oe]&&t[Oe]()}function Le(e){ke.set(e,Pe(e.el))}function xe(e){const t=Te.get(e),n=ke.get(e),r=t.left-n.left,o=t.top-n.top;if(r||o){const t=e.el,n=t.style,i=t.getBoundingClientRect();let s=1,a=1;return t.offsetWidth&&(s=i.width/t.offsetWidth),t.offsetHeight&&(a=i.height/t.offsetHeight),Number.isFinite(s)&&0!==s||(s=1),Number.isFinite(a)&&0!==a||(a=1),Math.abs(s-1)<.01&&(s=1),Math.abs(a-1)<.01&&(a=1),n.transform=n.webkitTransform=`translate(${r/s}px,${o/a}px)`,n.transitionDuration="0s",e}}function Pe(e){const t=e.getBoundingClientRect();return{left:t.left,top:t.top}}function De(e,t,n){const r=e.cloneNode(),o=e[v];o&&o.forEach(e=>{e.split(/\s+/).forEach(e=>e&&r.classList.remove(e))}),n.split(/\s+/).forEach(e=>e&&r.classList.add(e)),r.style.display="none";const i=1===t.nodeType?t:t.parentNode;i.appendChild(r);const{hasTransform:s}=N(r);return i.removeChild(r),s}const Me=e=>{const t=e.props["onUpdate:modelValue"]||!1;return(0,i.cy)(t)?e=>(0,i.DY)(t,e):t};function Fe(e){e.target.composing=!0}function $e(e){const t=e.target;t.composing&&(t.composing=!1,t.dispatchEvent(new Event("input")))}const je=Symbol("_assign");function Ue(e,t,n){return t&&(e=e.trim()),n&&(e=(0,i.bB)(e)),e}const Be={created(e,{modifiers:{lazy:t,trim:n,number:r}},o){e[je]=Me(o);const i=r||o.props&&"number"===o.props.type;te(e,t?"change":"input",t=>{t.target.composing||e[je](Ue(e.value,n,i))}),(n||i)&&te(e,"change",()=>{e.value=Ue(e.value,n,i)}),t||(te(e,"compositionstart",Fe),te(e,"compositionend",$e),te(e,"change",$e))},mounted(e,{value:t}){e.value=null==t?"":t},beforeUpdate(e,{value:t,oldValue:n,modifiers:{lazy:r,trim:o,number:s}},a){if(e[je]=Me(a),e.composing)return;const l=!s&&"number"!==e.type||/^0\d/.test(e.value)?e.value:(0,i.bB)(e.value),u=null==t?"":t;if(l===u)return;const c=e.getRootNode();if((c instanceof Document||c instanceof ShadowRoot)&&c.activeElement===e&&"range"!==e.type){if(r&&t===n)return;if(o&&e.value.trim()===u)return}e.value=u}},Ve={deep:!0,created(e,t,n){e[je]=Me(n),te(e,"change",()=>{const t=e._modelValue,n=Ke(e),r=e.checked,o=e[je];if((0,i.cy)(t)){const e=(0,i.u3)(t,n),s=-1!==e;if(r&&!s)o(t.concat(n));else if(!r&&s){const n=[...t];n.splice(e,1),o(n)}}else if((0,i.vM)(t)){const e=new Set(t);r?e.add(n):e.delete(n),o(e)}else o(qe(e,r))})},mounted:Ge,beforeUpdate(e,t,n){e[je]=Me(n),Ge(e,t,n)}};function Ge(e,{value:t,oldValue:n},r){let o;if(e._modelValue=t,(0,i.cy)(t))o=(0,i.u3)(t,r.props.value)>-1;else if((0,i.vM)(t))o=t.has(r.props.value);else{if(t===n)return;o=(0,i.BX)(t,qe(e,!0))}e.checked!==o&&(e.checked=o)}const He={created(e,{value:t},n){e.checked=(0,i.BX)(t,n.props.value),e[je]=Me(n),te(e,"change",()=>{e[je](Ke(e))})},beforeUpdate(e,{value:t,oldValue:n},r){e[je]=Me(r),t!==n&&(e.checked=(0,i.BX)(t,r.props.value))}},We={deep:!0,created(e,{value:t,modifiers:{number:n}},o){const s=(0,i.vM)(t);te(e,"change",()=>{const t=Array.prototype.filter.call(e.options,e=>e.selected).map(e=>n?(0,i.bB)(Ke(e)):Ke(e));e[je](e.multiple?s?new Set(t):t:t[0]),e._assigning=!0,(0,r.dY)(()=>{e._assigning=!1})}),e[je]=Me(o)},mounted(e,{value:t}){Xe(e,t)},beforeUpdate(e,t,n){e[je]=Me(n)},updated(e,{value:t}){e._assigning||Xe(e,t)}};function Xe(e,t){const n=e.multiple,r=(0,i.cy)(t);if(!n||r||(0,i.vM)(t)){for(let o=0,s=e.options.length;o<s;o++){const s=e.options[o],a=Ke(s);if(n)if(r){const e=typeof a;s.selected="string"===e||"number"===e?t.some(e=>String(e)===String(a)):(0,i.u3)(t,a)>-1}else s.selected=t.has(a);else if((0,i.BX)(Ke(s),t))return void(e.selectedIndex!==o&&(e.selectedIndex=o))}n||-1===e.selectedIndex||(e.selectedIndex=-1)}}function Ke(e){return"_value"in e?e._value:e.value}function qe(e,t){const n=t?"_trueValue":"_falseValue";return n in e?e[n]:t}const ze={created(e,t,n){Qe(e,t,n,null,"created")},mounted(e,t,n){Qe(e,t,n,null,"mounted")},beforeUpdate(e,t,n,r){Qe(e,t,n,r,"beforeUpdate")},updated(e,t,n,r){Qe(e,t,n,r,"updated")}};function Ye(e,t){switch(e){case"SELECT":return We;case"TEXTAREA":return Be;default:switch(t){case"checkbox":return Ve;case"radio":return He;default:return Be}}}function Qe(e,t,n,r,o){const i=Ye(e.tagName,n.props&&n.props.type),s=i[o];s&&s(e,t,n,r)}function Je(){Be.getSSRProps=({value:e})=>({value:e}),He.getSSRProps=({value:e},t)=>{if(t.props&&(0,i.BX)(t.props.value,e))return{checked:!0}},Ve.getSSRProps=({value:e},t)=>{if((0,i.cy)(e)){if(t.props&&(0,i.u3)(e,t.props.value)>-1)return{checked:!0}}else if((0,i.vM)(e)){if(t.props&&e.has(t.props.value))return{checked:!0}}else if(e)return{checked:!0}},ze.getSSRProps=(e,t)=>{if("string"!==typeof t.type)return;const n=Ye(t.type.toUpperCase(),t.props&&t.props.type);return n.getSSRProps?n.getSSRProps(e,t):void 0}}const Ze=["ctrl","shift","alt","meta"],et={stop:e=>e.stopPropagation(),prevent:e=>e.preventDefault(),self:e=>e.target!==e.currentTarget,ctrl:e=>!e.ctrlKey,shift:e=>!e.shiftKey,alt:e=>!e.altKey,meta:e=>!e.metaKey,left:e=>"button"in e&&0!==e.button,middle:e=>"button"in e&&1!==e.button,right:e=>"button"in e&&2!==e.button,exact:(e,t)=>Ze.some(n=>e[`${n}Key`]&&!t.includes(n))},tt=(e,t)=>{if(!e)return e;const n=e._withMods||(e._withMods={}),r=t.join(".");return n[r]||(n[r]=(n,...r)=>{for(let e=0;e<t.length;e++){const r=et[t[e]];if(r&&r(n,t))return}return e(n,...r)})},nt={esc:"escape",space:" ",up:"arrow-up",left:"arrow-left",right:"arrow-right",down:"arrow-down",delete:"backspace"},rt=(e,t)=>{const n=e._withKeys||(e._withKeys={}),r=t.join(".");return n[r]||(n[r]=n=>{if(!("key"in n))return;const r=(0,i.Tg)(n.key);return t.some(e=>e===r||nt[e]===r)?e(n):void 0})},ot=(0,i.X$)({patchProp:he},h);let it,st=!1;function at(){return it||(it=(0,r.K9)(ot))}function lt(){return it=st?it:(0,r.ci)(ot),st=!0,it}const ut=(...e)=>{at().render(...e)},ct=(...e)=>{lt().hydrate(...e)},dt=(...e)=>{const t=at().createApp(...e);const{mount:n}=t;return t.mount=e=>{const r=pt(e);if(!r)return;const o=t._component;(0,i.Tn)(o)||o.render||o.template||(o.template=r.innerHTML),1===r.nodeType&&(r.textContent="");const s=n(r,!1,ht(r));return r instanceof Element&&(r.removeAttribute("v-cloak"),r.setAttribute("data-v-app","")),s},t},ft=(...e)=>{const t=lt().createApp(...e);const{mount:n}=t;return t.mount=e=>{const t=pt(e);if(t)return n(t,!0,ht(t))},t};function ht(e){return e instanceof SVGElement?"svg":"function"===typeof MathMLElement&&e instanceof MathMLElement?"mathml":void 0}function pt(e){if((0,i.Kg)(e)){const t=document.querySelector(e);return t}return e}let mt=!1;const vt=()=>{mt||(mt=!0,Je(),U())}},33:function(e,t,n){"use strict";
/**
* @vue/shared v3.5.32
* (c) 2018-present Yuxi (Evan) You and Vue contributors
* @license MIT
**/
function r(e){const t=Object.create(null);for(const n of e.split(","))t[n]=1;return e=>e in t}n.d(t,{$3:function(){return h},$H:function(){return F},BH:function(){return W},BX:function(){return re},Bm:function(){return E},C4:function(){return Q},CE:function(){return m},CP:function(){return u},DY:function(){return $},Gv:function(){return w},J$:function(){return ee},Kg:function(){return _},MZ:function(){return o},Mp:function(){return l},NO:function(){return a},Oj:function(){return i},PT:function(){return L},Qd:function(){return O},Ro:function(){return B},SU:function(){return R},TF:function(){return d},Tg:function(){return P},Tn:function(){return b},Tr:function(){return X},We:function(){return G},X$:function(){return c},Y2:function(){return te},ZH:function(){return D},Zf:function(){return C},_B:function(){return J},bB:function(){return U},cy:function(){return p},gd:function(){return y},pD:function(){return r},pU:function(){return ue},rU:function(){return M},tE:function(){return s},u3:function(){return oe},vM:function(){return v},v_:function(){return se},yI:function(){return A},yL:function(){return S},yQ:function(){return j}});const o={},i=[],s=()=>{},a=()=>!1,l=e=>111===e.charCodeAt(0)&&110===e.charCodeAt(1)&&(e.charCodeAt(2)>122||e.charCodeAt(2)<97),u=e=>e.startsWith("onUpdate:"),c=Object.assign,d=(e,t)=>{const n=e.indexOf(t);n>-1&&e.splice(n,1)},f=Object.prototype.hasOwnProperty,h=(e,t)=>f.call(e,t),p=Array.isArray,m=e=>"[object Map]"===k(e),v=e=>"[object Set]"===k(e),g=e=>"[object Date]"===k(e),y=e=>"[object RegExp]"===k(e),b=e=>"function"===typeof e,_=e=>"string"===typeof e,E=e=>"symbol"===typeof e,w=e=>null!==e&&"object"===typeof e,S=e=>(w(e)||b(e))&&b(e.then)&&b(e.catch),T=Object.prototype.toString,k=e=>T.call(e),C=e=>k(e).slice(8,-1),O=e=>"[object Object]"===k(e),A=e=>_(e)&&"NaN"!==e&&"-"!==e[0]&&""+parseInt(e,10)===e,R=r(",key,ref,ref_for,ref_key,onVnodeBeforeMount,onVnodeMounted,onVnodeBeforeUpdate,onVnodeUpdated,onVnodeBeforeUnmount,onVnodeUnmounted"),I=e=>{const t=Object.create(null);return n=>{const r=t[n];return r||(t[n]=e(n))}},N=/-\w/g,L=I(e=>e.replace(N,e=>e.slice(1).toUpperCase())),x=/\B([A-Z])/g,P=I(e=>e.replace(x,"-$1").toLowerCase()),D=I(e=>e.charAt(0).toUpperCase()+e.slice(1)),M=I(e=>{const t=e?`on${D(e)}`:"";return t}),F=(e,t)=>!Object.is(e,t),$=(e,...t)=>{for(let n=0;n<e.length;n++)e[n](...t)},j=(e,t,n,r=!1)=>{Object.defineProperty(e,t,{configurable:!0,enumerable:!1,writable:r,value:n})},U=e=>{const t=parseFloat(e);return isNaN(t)?e:t},B=e=>{const t=_(e)?Number(e):NaN;return isNaN(t)?e:t};let V;const G=()=>V||(V="undefined"!==typeof globalThis?globalThis:"undefined"!==typeof self?self:"undefined"!==typeof window?window:"undefined"!==typeof n.g?n.g:{});const H="Infinity,undefined,NaN,isFinite,isNaN,parseFloat,parseInt,decodeURI,decodeURIComponent,encodeURI,encodeURIComponent,Math,Number,Date,Array,Object,Boolean,String,RegExp,Map,Set,JSON,Intl,BigInt,console,Error,Symbol",W=r(H);function X(e){if(p(e)){const t={};for(let n=0;n<e.length;n++){const r=e[n],o=_(r)?Y(r):X(r);if(o)for(const e in o)t[e]=o[e]}return t}if(_(e)||w(e))return e}const K=/;(?![^(]*\))/g,q=/:([^]+)/,z=/\/\*[^]*?\*\//g;function Y(e){const t={};return e.replace(z,"").split(K).forEach(e=>{if(e){const n=e.split(q);n.length>1&&(t[n[0].trim()]=n[1].trim())}}),t}function Q(e){let t="";if(_(e))t=e;else if(p(e))for(let n=0;n<e.length;n++){const r=Q(e[n]);r&&(t+=r+" ")}else if(w(e))for(const n in e)e[n]&&(t+=n+" ");return t.trim()}function J(e){if(!e)return null;let{class:t,style:n}=e;return t&&!_(t)&&(e.class=Q(t)),n&&(e.style=X(n)),e}const Z="itemscope,allowfullscreen,formnovalidate,ismap,nomodule,novalidate,readonly",ee=r(Z);function te(e){return!!e||""===e}function ne(e,t){if(e.length!==t.length)return!1;let n=!0;for(let r=0;n&&r<e.length;r++)n=re(e[r],t[r]);return n}function re(e,t){if(e===t)return!0;let n=g(e),r=g(t);if(n||r)return!(!n||!r)&&e.getTime()===t.getTime();if(n=E(e),r=E(t),n||r)return e===t;if(n=p(e),r=p(t),n||r)return!(!n||!r)&&ne(e,t);if(n=w(e),r=w(t),n||r){if(!n||!r)return!1;const o=Object.keys(e).length,i=Object.keys(t).length;if(o!==i)return!1;for(const n in e){const r=e.hasOwnProperty(n),o=t.hasOwnProperty(n);if(r&&!o||!r&&o||!re(e[n],t[n]))return!1}}return String(e)===String(t)}function oe(e,t){return e.findIndex(e=>re(e,t))}const ie=e=>!(!e||!0!==e["__v_isRef"]),se=e=>_(e)?e:null==e?"":p(e)||w(e)&&(e.toString===T||!b(e.toString))?ie(e)?se(e.value):JSON.stringify(e,ae,2):String(e),ae=(e,t)=>ie(t)?ae(e,t.value):m(t)?{[`Map(${t.size})`]:[...t.entries()].reduce((e,[t,n],r)=>(e[le(t,r)+" =>"]=n,e),{})}:v(t)?{[`Set(${t.size})`]:[...t.values()].map(e=>le(e))}:E(t)?le(t):!w(t)||p(t)||O(t)?t:String(t),le=(e,t="")=>{var n;return E(e)?`Symbol(${null!=(n=e.description)?n:t})`:e};function ue(e){return null==e?"initial":"string"===typeof e?""===e?" ":e:("number"===typeof e&&Number.isFinite(e),String(e))}},3192:function(e,t,n){"use strict";n.d(t,{A:function(){return o}}),Object.defineProperty(o,"name",{value:"default",configurable:!0});var r=n(3751);async function o(e,t,n,o=()=>{}){if(await t.init(),void 0!==URLSearchParams){const e=new URLSearchParams(location.search);if(e.has("_locale")){await t.switch(e.get("_locale")),e.delete("_locale");const n=new URL(location.pathname,location);n.search=e.toString(),history.replaceState(history.state,"",n.toString())}}const i=(0,r.Ef)({...e});i.use(t.plugin),n.forEach(e=>{i.use(e)}),o(i),i.mount("body")}},4210:function(e,t,n){"use strict";let r;function o(e){r=e}n.d(t,{x:function(){return o}}),t.A=(e,t="short",n="medium")=>{if(!e)return"";const o=new Date(e);return isNaN(o.getTime())?e:t?n?o.toLocaleString(r,{dateStyle:n,timeStyle:t}):o.toLocaleTimeString(r,{timeStyle:t}):o.toLocaleDateString(r,{dateStyle:n})},(Object.getOwnPropertyDescriptor(t.A,"name")||{}).writable||Object.defineProperty(t.A,"name",{value:"default",configurable:!0})},266:function(e,t){"use strict";t.A=e=>e?Intl&&Intl.NumberFormat?(new Intl.NumberFormat).format(e):e:"",(Object.getOwnPropertyDescriptor(t.A,"name")||{}).writable||Object.defineProperty(t.A,"name",{value:"default",configurable:!0})},9451:function(e,t,n){"use strict";n.d(t,{A:function(){return i}}),Object.defineProperty(i,"name",{value:"default",configurable:!0});var r=n(641);const o=e=>e&&e.every(e=>e.type===r.Mw||(e.type===Text&&"string"===typeof e.children&&!e.children.trim()||!(e.type!==r.FK||!o(e.children))));function i(e){return!e||o(e())}},9376:function(e,t){"use strict";t.A={en:"English",de:"Deutsch (German)",br:"brezhoneg (Breton)",cs:"čeština (Czech)",es:"Español (Spanish)",fa:"فارسی (Persian)",fr:"Français (French)",it:"Italiano (Italian)",ja:"日本語 (Japanese)",lv:"latviešu valoda (Latvian)",nl:"Nederlands (Dutch)",pl:"polszczyzna (Polish)",pt:"Português (Portuguese)",ru:"русский (Russian)",sr:"српски језик (Serbian)",sv:"Svenska (Swedish)",tr:"Türkçe (Turkish)",zh:"中文 (Chinese)"}},416:function(e,t){"use strict";t.A={data:()=>({metadata:{}}),methods:{async loadMetadata(){if(!this.data)return void(this.metadata=null);this.metadata={};const e=await this.$store.dispatch("packages/metadata",this.data);this.metadata=e?Object.assign({},this.data,e):null}},watch:{data(){this.loadMetadata()}},created(){this.loadMetadata(),this.$watch(this.$i18n.locale,this.loadMetadata)}}},1881:function(e,t){"use strict";t.A={computed:{query:e=>e.$route.query.q,pages:e=>Number(e.$route.query.pages)||1,sorting:e=>e.$route.query.sort||"",isSearching:e=>e.query||e.pages>1||e.sorting},methods:{startSearch(e,t=1){const n={q:e};t&&(n.pages=t),this.sorting&&this.query===e&&(n.sort=this.sorting),this.$router.push({query:n,append:!0}).catch(()=>{})},stopSearch(e){const t=Object.assign({},this.$route);delete t.query,this.$router.push(t).catch(()=>{}),e&&e.target&&e.target.blur()},sortBy(e){this.$router.push({query:Object.assign({},this.$route.query,{sort:e})}).catch(()=>{})},loadMore(e){this.startSearch(this.query,this.pages+1),e&&e.target&&e.target.blur()}}}},7943:function(e,t,n){"use strict";n.d(t,{A:function(){return G}});var r=n(4335);function o(e){let t;const n=`algolia-client-js-${e.key}`;function r(){return void 0===t&&(t=e.localStorage||window.localStorage),t}function o(){return JSON.parse(r().getItem(n)||"{}")}function i(e){r().setItem(n,JSON.stringify(e))}function s(){const t=e.timeToLive?1e3*e.timeToLive:null,n=o(),r=Object.fromEntries(Object.entries(n).filter(([,e])=>void 0!==e.timestamp));if(i(r),!t)return;const s=Object.fromEntries(Object.entries(r).filter(([,e])=>{const n=(new Date).getTime(),r=e.timestamp+t<n;return!r}));i(s)}return{get(e,t,n={miss:()=>Promise.resolve()}){return Promise.resolve().then(()=>(s(),o()[JSON.stringify(e)])).then(e=>Promise.all([e?e.value:t(),void 0!==e])).then(([e,t])=>Promise.all([e,t||n.miss(e)])).then(([e])=>e)},set(e,t){return Promise.resolve().then(()=>{const i=o();return i[JSON.stringify(e)]={timestamp:(new Date).getTime(),value:t},r().setItem(n,JSON.stringify(i)),t})},delete(e){return Promise.resolve().then(()=>{const t=o();delete t[JSON.stringify(e)],r().setItem(n,JSON.stringify(t))})},clear(){return Promise.resolve().then(()=>{r().removeItem(n)})}}}function i(){return{get(e,t,n={miss:()=>Promise.resolve()}){const r=t();return r.then(e=>Promise.all([e,n.miss(e)])).then(([e])=>e)},set(e,t){return Promise.resolve(t)},delete(e){return Promise.resolve()},clear(){return Promise.resolve()}}}function s(e){const t=[...e.caches],n=t.shift();return void 0===n?i():{get(e,r,o={miss:()=>Promise.resolve()}){return n.get(e,r,o).catch(()=>s({caches:t}).get(e,r,o))},set(e,r){return n.set(e,r).catch(()=>s({caches:t}).set(e,r))},delete(e){return n.delete(e).catch(()=>s({caches:t}).delete(e))},clear(){return n.clear().catch(()=>s({caches:t}).clear())}}}function a(e={serializable:!0}){let t={};return{get(n,r,o={miss:()=>Promise.resolve()}){const i=JSON.stringify(n);if(i in t)return Promise.resolve(e.serializable?JSON.parse(t[i]):t[i]);const s=r();return s.then(e=>o.miss(e)).then(()=>s)},set(n,r){return t[JSON.stringify(n)]=e.serializable?JSON.stringify(r):r,Promise.resolve(r)},delete(e){return delete t[JSON.stringify(e)],Promise.resolve()},clear(){return t={},Promise.resolve()}}}function l(e){const t={value:`Algolia for JavaScript (${e})`,add(e){const n=`; ${e.segment}${void 0!==e.version?` (${e.version})`:""}`;return-1===t.value.indexOf(n)&&(t.value=`${t.value}${n}`),t}};return t}function u(e,t,n="WithinHeaders"){const r={"x-algolia-api-key":t,"x-algolia-application-id":e};return{headers(){return"WithinHeaders"===n?r:{}},queryParameters(){return"WithinQueryParameters"===n?r:{}}}}function c({algoliaAgents:e,client:t,version:n}){const r=l(n).add({segment:t,version:n});return e.forEach(e=>r.add(e)),r}function d(){return{debug(e,t){return Promise.resolve()},info(e,t){return Promise.resolve()},error(e,t){return Promise.resolve()}}}var f=750,h=12e4;function p(e,t="up"){const n=Date.now();function r(){return"up"===t||Date.now()-n>h}function o(){return"timed out"===t&&Date.now()-n<=h}return{...e,status:t,lastUpdate:n,isUp:r,isTimedOut:o}}var m=class extends Error{name="AlgoliaError";constructor(e,t){super(e),t&&(this.name=t)}},v=class extends m{stackTrace;constructor(e,t,n){super(e,n),this.stackTrace=t}},g=class extends v{constructor(e){super("Unreachable hosts - your application id may be incorrect. If the error persists, please visit our help center https://alg.li/support-unreachable-hosts or reach out to the Algolia Support team: https://alg.li/support",e,"RetryError")}},y=class extends v{status;constructor(e,t,n,r="ApiError"){super(e,n,r),this.status=t}},b=class extends m{response;constructor(e,t){super(e,"DeserializationError"),this.response=t}},_=class extends y{error;constructor(e,t,n,r){super(e,t,r,"DetailedApiError"),this.error=n}};function E(e){const t=e;for(let n=e.length-1;n>0;n--){const r=Math.floor(Math.random()*(n+1)),o=e[n];t[n]=e[r],t[r]=o}return t}function w(e,t,n){const r=S(n);let o=`${e.protocol}://${e.url}${e.port?`:${e.port}`:""}/${"/"===t.charAt(0)?t.substring(1):t}`;return r.length&&(o+=`?${r}`),o}function S(e){return Object.keys(e).filter(t=>void 0!==e[t]).sort().map(t=>`${t}=${encodeURIComponent("[object Array]"===Object.prototype.toString.call(e[t])?e[t].join(","):e[t]).replace(/\+/g,"%20")}`).join("&")}function T(e,t){if("GET"===e.method||void 0===e.data&&void 0===t.data)return;const n=Array.isArray(e.data)?e.data:{...e.data,...t.data};return JSON.stringify(n)}function k(e,t,n){const r={Accept:"application/json",...e,...t,...n},o={};return Object.keys(r).forEach(e=>{const t=r[e];o[e.toLowerCase()]=t}),o}function C(e){try{return JSON.parse(e.content)}catch(t){throw new b(t.message,e)}}function O({content:e,status:t},n){try{const r=JSON.parse(e);return"error"in r?new _(r.message,t,r.error,n):new y(r.message,t,n)}catch{}return new y(e,t,n)}function A({isTimedOut:e,status:t}){return!e&&0===~~t}function R({isTimedOut:e,status:t}){return e||A({isTimedOut:e,status:t})||2!==~~(t/100)&&4!==~~(t/100)}function I({status:e}){return 2===~~(e/100)}function N(e){return e.map(e=>L(e))}function L(e){const t=e.request.headers["x-algolia-api-key"]?{"x-algolia-api-key":"*****"}:{};return{...e,request:{...e.request,headers:{...e.request.headers,...t}}}}function x({hosts:e,hostsCache:t,baseHeaders:n,logger:r,baseQueryParameters:o,algoliaAgent:i,timeouts:s,requester:a,requestsCache:l,responsesCache:u,compress:c,compression:d}){async function h(e){const n=await Promise.all(e.map(e=>t.get(e,()=>Promise.resolve(p(e))))),r=n.filter(e=>e.isUp()),o=n.filter(e=>e.isTimedOut()),i=[...r,...o],s=i.length>0?i:e;return{hosts:s,getTimeout(e,t){const n=0===o.length&&0===e?1:o.length+3+e;return n*t}}}async function m(l,u,m){const v=[],y=T(l,u),b=k(n,l.headers,u.headers),_="gzip"===d&&void 0!==y&&y.length>f&&("POST"===l.method||"PUT"===l.method);_&&void 0===c&&r.info("Compression is disabled because no compress method is available.");const E=_&&void 0!==c,S=E?await c(y):y;E&&(b["content-encoding"]="gzip");const A="GET"===l.method?{...l.data,...u.data}:{},x={...o,...l.queryParameters,...A};if(i.value&&(x["x-algolia-agent"]=i.value),u&&u.queryParameters)for(const e of Object.keys(u.queryParameters))u.queryParameters[e]&&"[object Object]"!==Object.prototype.toString.call(u.queryParameters[e])?x[e]=u.queryParameters[e].toString():x[e]=u.queryParameters[e];let P=0;const D=async(e,n)=>{const o=e.pop();if(void 0===o)throw new g(N(v));const i={...s,...u.timeouts},c={data:S,headers:b,method:l.method,url:w(o,l.path,x),connectTimeout:n(P,i.connect),responseTimeout:n(P,m?i.read:i.write)},d=t=>{const n={request:c,response:t,host:o,triesLeft:e.length};return v.push(n),n},f=await a.send(c);if(R(f)){const i=d(f);return f.isTimedOut&&P++,r.info("Retryable failure",L(i)),await t.set(o,p(o,f.isTimedOut?"timed out":"down")),D(e,n)}if(I(f))return C(f);throw d(f),O(f,v)},M=e.filter(e=>"readWrite"===e.accept||(m?"read"===e.accept:"write"===e.accept)),F=await h(M);return D([...F.hosts].reverse(),F.getTimeout)}function v(e,t={}){const r=()=>m(e,t,i),i=e.useReadTransporter||"GET"===e.method,s=t.cacheable||e.cacheable;if(!0!==s)return r();const a={request:e,requestOptions:t,transporter:{queryParameters:o,headers:n}};return u.get(a,()=>l.get(a,()=>l.set(a,r()).then(e=>Promise.all([l.delete(a),e]),e=>Promise.all([l.delete(a),Promise.reject(e)])).then(([e,t])=>t)),{miss:e=>u.set(a,e)})}return{hostsCache:t,requester:a,timeouts:s,logger:r,algoliaAgent:i,baseHeaders:n,baseQueryParameters:o,hosts:e,request:v,requestsCache:l,responsesCache:u}}function P(){function e(e){return new Promise(t=>{let n=new XMLHttpRequest;n.open(e.method,e.url,!0),Object.keys(e.headers).forEach(t=>n.setRequestHeader(t,e.headers[t]));let r,o=(e,r)=>setTimeout(()=>{n.abort(),t({status:0,content:r,isTimedOut:!0})},e),i=o(e.connectTimeout,"Connection timeout");n.onreadystatechange=()=>{n.readyState>n.OPENED&&void 0===r&&(clearTimeout(i),r=o(e.responseTimeout,"Socket timeout"))},n.onerror=()=>{0===n.status&&(clearTimeout(i),clearTimeout(r),t({content:n.responseText||"Network request failed",status:n.status,isTimedOut:!1}))},n.onload=()=>{clearTimeout(i),clearTimeout(r),t({content:n.responseText,status:n.status,isTimedOut:!1})},n.send(e.data)})}return{send:e}}var D="5.50.2";function M(e){return[{url:`${e}-dsn.algolia.net`,accept:"read",protocol:"https"},{url:`${e}.algolia.net`,accept:"write",protocol:"https"}].concat(E([{url:`${e}-1.algolianet.com`,accept:"readWrite",protocol:"https"},{url:`${e}-2.algolianet.com`,accept:"readWrite",protocol:"https"},{url:`${e}-3.algolianet.com`,accept:"readWrite",protocol:"https"}]))}function F({appId:e,apiKey:t,authMode:n,algoliaAgents:r,...o}){const i=u(e,t,n),s=x({hosts:M(e),...o,algoliaAgent:c({algoliaAgents:r,client:"Lite",version:D}),baseHeaders:{"content-type":"text/plain",...i.headers(),...o.baseHeaders},baseQueryParameters:{...i.queryParameters(),...o.baseQueryParameters}});return{transporter:s,appId:e,apiKey:t,clearCache(){return Promise.all([s.requestsCache.clear(),s.responsesCache.clear()]).then(()=>{})},get _ua(){return s.algoliaAgent.value},addAlgoliaAgent(e,t){s.algoliaAgent.add({segment:e,version:t})},setClientApiKey({apiKey:e}){n&&"WithinHeaders"!==n?s.baseQueryParameters["x-algolia-api-key"]=e:s.baseHeaders["x-algolia-api-key"]=e},searchForHits(e,t){return this.search(e,t)},searchForFacets(e,t){return this.search(e,t)},customPost({path:e,parameters:t,body:n},r){if(!e)throw new Error("Parameter `path` is required when calling `customPost`.");const o="/{path}".replace("{path}",e),i={},a=t||{},l={method:"POST",path:o,queryParameters:a,headers:i,data:n||{}};return s.request(l,r)},getRecommendations(e,t){if(e&&Array.isArray(e)){const t={requests:e};e=t}if(!e)throw new Error("Parameter `getRecommendationsParams` is required when calling `getRecommendations`.");if(!e.requests)throw new Error("Parameter `getRecommendationsParams.requests` is required when calling `getRecommendations`.");const n="/1/indexes/*/recommendations",r={},o={},i={method:"POST",path:n,queryParameters:o,headers:r,data:e,useReadTransporter:!0,cacheable:!0};return s.request(i,t)},search(e,t){if(e&&Array.isArray(e)){const t={requests:e.map(({params:e,...t})=>"facet"===t.type?{...t,...e,type:"facet"}:{...t,...e,facet:void 0,maxFacetHits:void 0,facetQuery:void 0})};e=t}if(!e)throw new Error("Parameter `searchMethodParams` is required when calling `search`.");if(!e.requests)throw new Error("Parameter `searchMethodParams.requests` is required when calling `search`.");const n="/1/indexes/*/queries",r={},o={},i={method:"POST",path:n,queryParameters:o,headers:r,data:e,useReadTransporter:!0,cacheable:!0};return s.request(i,t)}}}function $(e,t,n){if(!e||"string"!==typeof e)throw new Error("`appId` is missing.");if(!t||"string"!==typeof t)throw new Error("`apiKey` is missing.");const{compression:r,...i}=n||{};return F({appId:e,apiKey:t,timeouts:{connect:1e3,read:2e3,write:3e4},logger:d(),requester:P(),algoliaAgents:[{segment:"Browser"}],authMode:"WithinQueryParameters",responsesCache:a(),requestsCache:a({serializable:!1}),hostsCache:s({caches:[o({key:`${D}-${e}`}),a()]}),...i})}var j=n(9589),U=n(9997);const B=$("60DW2LJW0P","13718a23f4e436f7e7614340bd87d913"),V=(e,t=6)=>{const n=Array.from(e),r=[];while(n.length>0&&r.length<t){let e=Math.floor(Math.random()*n.length);r.push(n[e]),n.splice(e,1)}return r};var G={namespaced:!0,state:{language:"en",metadata:{},discover:null,ads:[],news:[]},mutations:{setLanguage(e,t){e.language=t,e.metadata={}},cache(e,{name:t,data:n}){e.metadata[t]=n},uncache(e,t){delete e.metadata[t]},reset(e){e.metadata={}},setDiscover(e,t){e.discover=t,e.ads=t?t.ads:[],e.news=t?t.news:[]}},actions:{getPackage({state:e,commit:t},n){if(!n||!n.includes("/"))return new Promise(e=>e(null));if(Object.keys(e.metadata).includes(n))return e.metadata[n];const o=(async()=>{let t=null;try{const r=await B.search([{indexName:"v3_packages",params:{filters:`name:"${n}" AND languages:${e.language}`,hitsPerPage:1}}]);r.results[0].nbHits>0&&(t=r.results[0].hits[0])}catch(o){}try{if(t&&t.private)t=Object.assign({},(await r.A.get(`https://contao.github.io/package-metadata/meta/${n}/composer.json`)).data,t||{});else{let e,i=(await r.A.get(`https://packagist.org/packages/${n}.json`)).data.package,s=[];i.downloads=i.downloads.total,i.dependency=!0;try{const e=(await r.A.get(`https://repo.packagist.org/p2/${n}.json`)).data.packages[n];let t=null;Object.values(e).forEach(e=>{if(!t)return t=e,void s.push(JSON.parse(JSON.stringify(t)));Object.keys(e).forEach(n=>{"__unset"===e[n]?delete t[n]:t[n]=e[n]}),s.push(JSON.parse(JSON.stringify(t)))})}catch(o){s=Object.values(i.versions)}if(e=s.filter(e=>"dev-"!==e.version.substr(0,4)&&"-dev"!==e.version.substr(-4)&&e.require&&"contao/core-bundle"in e.require),e.length||(e=s.filter(e=>"dev-"!==e.version.substr(0,4)&&"-dev"!==e.version.substr(-4))),e.length||(e=s),e&&e.length||(e=[]),e=e.sort((e,t)=>{const n=(0,j.coerce)(e.version_normalized,{loose:!0}),r=(0,j.coerce)(t.version_normalized,{loose:!0}),o=(0,j.compare)(n,r);return 0===o?new Date(e.time)>new Date(t.time)?1:-1:o}),e.length){const t=e[e.length-1];i=Object.assign(i,t),i.latest={version:t.version,time:t.time}}t=Object.assign({},i,t||{},{versions:e})}}catch(o){console.info("No package metadata for "+n,o)}return t?(delete t.version,delete t.time,delete t.constraint,U.A[t.name]&&(t.features=U.A[t.name]),t):null})();return t("cache",{name:n,data:o}),o},async findPackages({state:e,dispatch:t},n){let r="",o="dependency:false";n.sorting&&(r=n.sorting?`_${n.sorting}`:"",o="discoverable:true",delete n.sorting),n.type&&(o=`type:${n.type}`,delete n.type),n.filters=`languages:${e.language} AND ${o}`,n.highlightPreTag="%%",n.highlightPostTag="%%";const i=(await B.search([{indexName:`v3_packages${r}`,params:n}])).results[0];if(n.query&&new RegExp("^[a-z0-9]([_.-]?[a-z0-9]+)*/[a-z0-9](([_.]|-{1,2})?[a-z0-9]+)*$").test(n.query)&&!i.hits.find(e=>e.name===n.query)){const e=await t("getPackage",n.query);e&&(e.dependency=!1,i.nbHits++,i.hits.push(e))}return i},async discover({state:e,commit:t}){try{const n=new Date,r=`${n.getFullYear()}${String(n.getMonth()+1).padStart(2,"0")}${String(n.getDate()).padStart(2,"0")}`,o=await B.search([{indexName:"v3_packages_latest",params:{hitsPerPage:6,filters:`languages:${e.language} AND discoverable:true`}},{indexName:"v3_packages_downloads",params:{hitsPerPage:4,filters:`languages:${e.language} AND discoverable:true`}},{indexName:"v3_packages_favers",params:{hitsPerPage:4,filters:`languages:${e.language} AND discoverable:true`}},{indexName:"v3_ads",params:{hitsPerPage:6,filters:`position:primary AND languages:${e.language} AND published:true AND validFrom <= ${r} AND validTo >= ${r}`}},{indexName:"v3_ads",params:{hitsPerPage:100,filters:`position:secondary AND languages:${e.language} AND published:true AND validFrom <= ${r} AND validTo >= ${r}`}},{indexName:"v3_ads",params:{hitsPerPage:100,filters:`position:subheader AND languages:${e.language} AND published:true AND validFrom <= ${r} AND validTo >= ${r}`}}]);t("setDiscover",{latest:o.results[0].hits,downloads:o.results[1].hits,favers:o.results[2].hits,ads:V(o.results[3].hits).concat(V(o.results[4].hits,6-o.results[3].nbHits)),news:V(o.results[5].hits)})}catch(n){t("setDiscover",null)}}}}},156:function(e,t,n){"use strict";var r=n(953);t.A={namespaced:!0,state:{modals:{}},getters:{hasModal:e=>Object.values(e.modals).reduce((e,t)=>e+Object.values(t).length,0)>0,currentModal(e){const t=Object.keys(e.modals).sort((e,t)=>t-e);for(const n of t){const t=Object.values(e.modals[n]);if(t.length>0)return t.find(()=>!0)}}},mutations:{open(e,{id:t,component:n,priority:o=0}){const i=Object.assign({},e.modals);i[o]||(i[o]={}),i[o][t]=(0,r.IG)(n),e.modals=i},close(e,t){const n=Object.assign({},e.modals);Object.keys(n).forEach(e=>{n[e]&&n[e][t]&&delete n[e][t]}),e.modals=n}}}},950:function(e,t){"use strict";let n=null,r=null;t.A={namespaced:!0,mutations:{setCurrent(e,t){r.$router.push({query:Object.assign({},r.$router.currentRoute.value.query,{p:t}),append:!0})},clearCurrent(){const e=Object.assign({},r.$router.currentRoute.value.query);delete e.p,r.$router.push({query:e,append:!0})},trackPackage(e,t){t?r.$store.commit("modals/open",{id:"package-details",component:n}):r.$store.commit("modals/close","package-details")}},actions:{init({commit:e},{vue:t,component:o}){r=t,n=o,r.$watch("$route.query.p",t=>e("trackPackage",t)),e("trackPackage",r.$route.query.p)}}}},9997:function(e,t){"use strict";t.A={"contao/manager-bundle":{"contao/news-bundle":"^4.0 || ^5.0","contao/calendar-bundle":"^4.0 || ^5.0","contao/faq-bundle":"^4.0 || ^5.0","contao/comments-bundle":"^4.0 || ^5.0","contao/newsletter-bundle":"^4.0 || ^5.0","contao/listing-bundle":"^4.0 || ^5.0","contao/loupe-bridge":"^5.7"}}},9348:function(){(function(){"use strict";var e=document.createElement("details"),t="undefined"!=typeof HTMLDetailsElement&&e instanceof HTMLDetailsElement,n={open:"open"in e||t,toggle:"ontoggle"in e},r='\ndetails, summary {\n  display: block;\n}\ndetails:not([open]) > *:not(summary) {\n  display: none;\n}\nsummary::before {\n  content: "►";\n  padding-right: 0.3rem;\n  font-size: 0.6rem;\n  cursor: default;\n}\n[open] > summary::before {\n  content: "▼";\n}\n',o=[],i=o.forEach,s=o.slice;function a(){document.head.insertAdjacentHTML("afterbegin","<style>"+r+"</style>")}function l(){var e=document.createElement("details").constructor.prototype,t=e.setAttribute,n=e.removeAttribute,r=Object.getOwnPropertyDescriptor(e,"open");Object.defineProperties(e,{open:{get:function(){return"DETAILS"==this.tagName?this.hasAttribute("open"):r&&r.get?r.get.call(this):void 0},set:function(e){return"DETAILS"==this.tagName?e?this.setAttribute("open",""):this.removeAttribute("open"):r&&r.set?r.set.call(this,e):void 0}},setAttribute:{value:function(e,n){var r=this,o=function(){return t.call(r,e,n)};if("open"==e&&"DETAILS"==this.tagName){var i=this.hasAttribute("open"),s=o();if(!i){var a=this.querySelector("summary");a&&a.setAttribute("aria-expanded",!0),m(this)}return s}return o()}},removeAttribute:{value:function(e){var t=this,r=function(){return n.call(t,e)};if("open"==e&&"DETAILS"==this.tagName){var o=this.hasAttribute("open"),i=r();if(o){var s=this.querySelector("summary");s&&s.setAttribute("aria-expanded",!1),m(this)}return i}return r()}}})}function u(){p(function(e){e.hasAttribute("open")?e.removeAttribute("open"):e.setAttribute("open","")})}function c(){window.MutationObserver?new MutationObserver(function(e){i.call(e,function(e){var t=e.target,n=e.attributeName;"DETAILS"==t.tagName&&"open"==n&&m(t)})}).observe(document.documentElement,{attributes:!0,subtree:!0}):p(function(e){var t=e.getAttribute("open");setTimeout(function(){var n=e.getAttribute("open");t!=n&&m(e)},1)})}function d(){f(document),window.MutationObserver?new MutationObserver(function(e){i.call(e,function(e){i.call(e.addedNodes,f)})}).observe(document.documentElement,{subtree:!0,childList:!0}):document.addEventListener("DOMNodeInserted",function(e){f(e.target)})}function f(e){v(e,"SUMMARY").forEach(function(e){var t=g(e,"DETAILS");e.setAttribute("aria-expanded",t.hasAttribute("open")),e.hasAttribute("tabindex")||e.setAttribute("tabindex","0"),e.hasAttribute("role")||e.setAttribute("role","button")})}function h(e){return!(e.defaultPrevented||e.ctrlKey||e.metaKey||e.shiftKey||e.target.isContentEditable)}function p(e){addEventListener("click",function(t){if(h(t)&&t.which<=1){var n=g(t.target,"SUMMARY");n&&n.parentNode&&"DETAILS"==n.parentNode.tagName&&e(n.parentNode)}},!1),addEventListener("keydown",function(t){if(h(t)&&(13==t.keyCode||32==t.keyCode)){var n=g(t.target,"SUMMARY");n&&n.parentNode&&"DETAILS"==n.parentNode.tagName&&(e(n.parentNode),t.preventDefault())}},!1)}function m(e){var t=document.createEvent("Event");t.initEvent("toggle",!1,!1),e.dispatchEvent(t)}function v(e,t){return(e.tagName==t?[e]:[]).concat("function"==typeof e.getElementsByTagName?s.call(e.getElementsByTagName(t)):[])}function g(e,t){if("function"==typeof e.closest)return e.closest(t);while(e){if(e.tagName==t)return e;e=e.parentNode}}n.open||(a(),l(),u(),d()),n.open&&!n.toggle&&c()})()},3904:function(e,t,n){"use strict";const r=Symbol("SemVer ANY");class o{static get ANY(){return r}constructor(e,t){if(t=i(t),e instanceof o){if(e.loose===!!t.loose)return e;e=e.value}e=e.trim().split(/\s+/).join(" "),u("comparator",e,t),this.options=t,this.loose=!!t.loose,this.parse(e),this.semver===r?this.value="":this.value=this.operator+this.semver.version,u("comp",this)}parse(e){const t=this.options.loose?s[a.COMPARATORLOOSE]:s[a.COMPARATOR],n=e.match(t);if(!n)throw new TypeError(`Invalid comparator: ${e}`);this.operator=void 0!==n[1]?n[1]:"","="===this.operator&&(this.operator=""),n[2]?this.semver=new c(n[2],this.options.loose):this.semver=r}toString(){return this.value}test(e){if(u("Comparator.test",e,this.options.loose),this.semver===r||e===r)return!0;if("string"===typeof e)try{e=new c(e,this.options)}catch(t){return!1}return l(e,this.operator,this.semver,this.options)}intersects(e,t){if(!(e instanceof o))throw new TypeError("a Comparator is required");return""===this.operator?""===this.value||new d(e.value,t).test(this.value):""===e.operator?""===e.value||new d(this.value,t).test(e.semver):(t=i(t),(!t.includePrerelease||"<0.0.0-0"!==this.value&&"<0.0.0-0"!==e.value)&&(!(!t.includePrerelease&&(this.value.startsWith("<0.0.0")||e.value.startsWith("<0.0.0")))&&(!(!this.operator.startsWith(">")||!e.operator.startsWith(">"))||(!(!this.operator.startsWith("<")||!e.operator.startsWith("<"))||(!(this.semver.version!==e.semver.version||!this.operator.includes("=")||!e.operator.includes("="))||(!!(l(this.semver,"<",e.semver,t)&&this.operator.startsWith(">")&&e.operator.startsWith("<"))||!!(l(this.semver,">",e.semver,t)&&this.operator.startsWith("<")&&e.operator.startsWith(">"))))))))}}e.exports=o;const i=n(8587),{safeRe:s,t:a}=n(9718),l=n(2111),u=n(7272),c=n(3908),d=n(8311)},8311:function(e,t,n){"use strict";const r=/\s+/g;class o{constructor(e,t){if(t=a(t),e instanceof o)return e.loose===!!t.loose&&e.includePrerelease===!!t.includePrerelease?e:new o(e.raw,t);if(e instanceof l)return this.raw=e.value,this.set=[[e]],this.formatted=void 0,this;if(this.options=t,this.loose=!!t.loose,this.includePrerelease=!!t.includePrerelease,this.raw=e.trim().replace(r," "),this.set=this.raw.split("||").map(e=>this.parseRange(e.trim())).filter(e=>e.length),!this.set.length)throw new TypeError(`Invalid SemVer Range: ${this.raw}`);if(this.set.length>1){const e=this.set[0];if(this.set=this.set.filter(e=>!y(e[0])),0===this.set.length)this.set=[e];else if(this.set.length>1)for(const t of this.set)if(1===t.length&&b(t[0])){this.set=[t];break}}this.formatted=void 0}get range(){if(void 0===this.formatted){this.formatted="";for(let e=0;e<this.set.length;e++){e>0&&(this.formatted+="||");const t=this.set[e];for(let e=0;e<t.length;e++)e>0&&(this.formatted+=" "),this.formatted+=t[e].toString().trim()}}return this.formatted}format(){return this.range}toString(){return this.range}parseRange(e){const t=(this.options.includePrerelease&&v)|(this.options.loose&&g),n=t+":"+e,r=s.get(n);if(r)return r;const o=this.options.loose,i=o?d[f.HYPHENRANGELOOSE]:d[f.HYPHENRANGE];e=e.replace(i,N(this.options.includePrerelease)),u("hyphen replace",e),e=e.replace(d[f.COMPARATORTRIM],h),u("comparator trim",e),e=e.replace(d[f.TILDETRIM],p),u("tilde trim",e),e=e.replace(d[f.CARETTRIM],m),u("caret trim",e);let a=e.split(" ").map(e=>E(e,this.options)).join(" ").split(/\s+/).map(e=>I(e,this.options));o&&(a=a.filter(e=>(u("loose invalid filter",e,this.options),!!e.match(d[f.COMPARATORLOOSE])))),u("range list",a);const c=new Map,b=a.map(e=>new l(e,this.options));for(const s of b){if(y(s))return[s];c.set(s.value,s)}c.size>1&&c.has("")&&c.delete("");const _=[...c.values()];return s.set(n,_),_}intersects(e,t){if(!(e instanceof o))throw new TypeError("a Range is required");return this.set.some(n=>_(n,t)&&e.set.some(e=>_(e,t)&&n.every(n=>e.every(e=>n.intersects(e,t)))))}test(e){if(!e)return!1;if("string"===typeof e)try{e=new c(e,this.options)}catch(t){return!1}for(let n=0;n<this.set.length;n++)if(L(this.set[n],e,this.options))return!0;return!1}}e.exports=o;const i=n(8794),s=new i,a=n(8587),l=n(3904),u=n(7272),c=n(3908),{safeRe:d,t:f,comparatorTrimReplace:h,tildeTrimReplace:p,caretTrimReplace:m}=n(9718),{FLAG_INCLUDE_PRERELEASE:v,FLAG_LOOSE:g}=n(6874),y=e=>"<0.0.0-0"===e.value,b=e=>""===e.value,_=(e,t)=>{let n=!0;const r=e.slice();let o=r.pop();while(n&&r.length)n=r.every(e=>o.intersects(e,t)),o=r.pop();return n},E=(e,t)=>(e=e.replace(d[f.BUILD],""),u("comp",e,t),e=k(e,t),u("caret",e),e=S(e,t),u("tildes",e),e=O(e,t),u("xrange",e),e=R(e,t),u("stars",e),e),w=e=>!e||"x"===e.toLowerCase()||"*"===e,S=(e,t)=>e.trim().split(/\s+/).map(e=>T(e,t)).join(" "),T=(e,t)=>{const n=t.loose?d[f.TILDELOOSE]:d[f.TILDE];return e.replace(n,(t,n,r,o,i)=>{let s;return u("tilde",e,t,n,r,o,i),w(n)?s="":w(r)?s=`>=${n}.0.0 <${+n+1}.0.0-0`:w(o)?s=`>=${n}.${r}.0 <${n}.${+r+1}.0-0`:i?(u("replaceTilde pr",i),s=`>=${n}.${r}.${o}-${i} <${n}.${+r+1}.0-0`):s=`>=${n}.${r}.${o} <${n}.${+r+1}.0-0`,u("tilde return",s),s})},k=(e,t)=>e.trim().split(/\s+/).map(e=>C(e,t)).join(" "),C=(e,t)=>{u("caret",e,t);const n=t.loose?d[f.CARETLOOSE]:d[f.CARET],r=t.includePrerelease?"-0":"";return e.replace(n,(t,n,o,i,s)=>{let a;return u("caret",e,t,n,o,i,s),w(n)?a="":w(o)?a=`>=${n}.0.0${r} <${+n+1}.0.0-0`:w(i)?a="0"===n?`>=${n}.${o}.0${r} <${n}.${+o+1}.0-0`:`>=${n}.${o}.0${r} <${+n+1}.0.0-0`:s?(u("replaceCaret pr",s),a="0"===n?"0"===o?`>=${n}.${o}.${i}-${s} <${n}.${o}.${+i+1}-0`:`>=${n}.${o}.${i}-${s} <${n}.${+o+1}.0-0`:`>=${n}.${o}.${i}-${s} <${+n+1}.0.0-0`):(u("no pr"),a="0"===n?"0"===o?`>=${n}.${o}.${i}${r} <${n}.${o}.${+i+1}-0`:`>=${n}.${o}.${i}${r} <${n}.${+o+1}.0-0`:`>=${n}.${o}.${i} <${+n+1}.0.0-0`),u("caret return",a),a})},O=(e,t)=>(u("replaceXRanges",e,t),e.split(/\s+/).map(e=>A(e,t)).join(" ")),A=(e,t)=>{e=e.trim();const n=t.loose?d[f.XRANGELOOSE]:d[f.XRANGE];return e.replace(n,(n,r,o,i,s,a)=>{u("xRange",e,n,r,o,i,s,a);const l=w(o),c=l||w(i),d=c||w(s),f=d;return"="===r&&f&&(r=""),a=t.includePrerelease?"-0":"",l?n=">"===r||"<"===r?"<0.0.0-0":"*":r&&f?(c&&(i=0),s=0,">"===r?(r=">=",c?(o=+o+1,i=0,s=0):(i=+i+1,s=0)):"<="===r&&(r="<",c?o=+o+1:i=+i+1),"<"===r&&(a="-0"),n=`${r+o}.${i}.${s}${a}`):c?n=`>=${o}.0.0${a} <${+o+1}.0.0-0`:d&&(n=`>=${o}.${i}.0${a} <${o}.${+i+1}.0-0`),u("xRange return",n),n})},R=(e,t)=>(u("replaceStars",e,t),e.trim().replace(d[f.STAR],"")),I=(e,t)=>(u("replaceGTE0",e,t),e.trim().replace(d[t.includePrerelease?f.GTE0PRE:f.GTE0],"")),N=e=>(t,n,r,o,i,s,a,l,u,c,d,f)=>(n=w(r)?"":w(o)?`>=${r}.0.0${e?"-0":""}`:w(i)?`>=${r}.${o}.0${e?"-0":""}`:s?`>=${n}`:`>=${n}${e?"-0":""}`,l=w(u)?"":w(c)?`<${+u+1}.0.0-0`:w(d)?`<${u}.${+c+1}.0-0`:f?`<=${u}.${c}.${d}-${f}`:e?`<${u}.${c}.${+d+1}-0`:`<=${l}`,`${n} ${l}`.trim()),L=(e,t,n)=>{for(let r=0;r<e.length;r++)if(!e[r].test(t))return!1;if(t.prerelease.length&&!n.includePrerelease){for(let n=0;n<e.length;n++)if(u(e[n].semver),e[n].semver!==l.ANY&&e[n].semver.prerelease.length>0){const r=e[n].semver;if(r.major===t.major&&r.minor===t.minor&&r.patch===t.patch)return!0}return!1}return!0}},3908:function(e,t,n){"use strict";const r=n(7272),{MAX_LENGTH:o,MAX_SAFE_INTEGER:i}=n(6874),{safeRe:s,t:a}=n(9718),l=n(8587),{compareIdentifiers:u}=n(1123);class c{constructor(e,t){if(t=l(t),e instanceof c){if(e.loose===!!t.loose&&e.includePrerelease===!!t.includePrerelease)return e;e=e.version}else if("string"!==typeof e)throw new TypeError(`Invalid version. Must be a string. Got type "${typeof e}".`);if(e.length>o)throw new TypeError(`version is longer than ${o} characters`);r("SemVer",e,t),this.options=t,this.loose=!!t.loose,this.includePrerelease=!!t.includePrerelease;const n=e.trim().match(t.loose?s[a.LOOSE]:s[a.FULL]);if(!n)throw new TypeError(`Invalid Version: ${e}`);if(this.raw=e,this.major=+n[1],this.minor=+n[2],this.patch=+n[3],this.major>i||this.major<0)throw new TypeError("Invalid major version");if(this.minor>i||this.minor<0)throw new TypeError("Invalid minor version");if(this.patch>i||this.patch<0)throw new TypeError("Invalid patch version");n[4]?this.prerelease=n[4].split(".").map(e=>{if(/^[0-9]+$/.test(e)){const t=+e;if(t>=0&&t<i)return t}return e}):this.prerelease=[],this.build=n[5]?n[5].split("."):[],this.format()}format(){return this.version=`${this.major}.${this.minor}.${this.patch}`,this.prerelease.length&&(this.version+=`-${this.prerelease.join(".")}`),this.version}toString(){return this.version}compare(e){if(r("SemVer.compare",this.version,this.options,e),!(e instanceof c)){if("string"===typeof e&&e===this.version)return 0;e=new c(e,this.options)}return e.version===this.version?0:this.compareMain(e)||this.comparePre(e)}compareMain(e){return e instanceof c||(e=new c(e,this.options)),this.major<e.major?-1:this.major>e.major?1:this.minor<e.minor?-1:this.minor>e.minor?1:this.patch<e.patch?-1:this.patch>e.patch?1:0}comparePre(e){if(e instanceof c||(e=new c(e,this.options)),this.prerelease.length&&!e.prerelease.length)return-1;if(!this.prerelease.length&&e.prerelease.length)return 1;if(!this.prerelease.length&&!e.prerelease.length)return 0;let t=0;do{const n=this.prerelease[t],o=e.prerelease[t];if(r("prerelease compare",t,n,o),void 0===n&&void 0===o)return 0;if(void 0===o)return 1;if(void 0===n)return-1;if(n!==o)return u(n,o)}while(++t)}compareBuild(e){e instanceof c||(e=new c(e,this.options));let t=0;do{const n=this.build[t],o=e.build[t];if(r("build compare",t,n,o),void 0===n&&void 0===o)return 0;if(void 0===o)return 1;if(void 0===n)return-1;if(n!==o)return u(n,o)}while(++t)}inc(e,t,n){if(e.startsWith("pre")){if(!t&&!1===n)throw new Error("invalid increment argument: identifier is empty");if(t){const e=`-${t}`.match(this.options.loose?s[a.PRERELEASELOOSE]:s[a.PRERELEASE]);if(!e||e[1]!==t)throw new Error(`invalid identifier: ${t}`)}}switch(e){case"premajor":this.prerelease.length=0,this.patch=0,this.minor=0,this.major++,this.inc("pre",t,n);break;case"preminor":this.prerelease.length=0,this.patch=0,this.minor++,this.inc("pre",t,n);break;case"prepatch":this.prerelease.length=0,this.inc("patch",t,n),this.inc("pre",t,n);break;case"prerelease":0===this.prerelease.length&&this.inc("patch",t,n),this.inc("pre",t,n);break;case"release":if(0===this.prerelease.length)throw new Error(`version ${this.raw} is not a prerelease`);this.prerelease.length=0;break;case"major":0===this.minor&&0===this.patch&&0!==this.prerelease.length||this.major++,this.minor=0,this.patch=0,this.prerelease=[];break;case"minor":0===this.patch&&0!==this.prerelease.length||this.minor++,this.patch=0,this.prerelease=[];break;case"patch":0===this.prerelease.length&&this.patch++,this.prerelease=[];break;case"pre":{const e=Number(n)?1:0;if(0===this.prerelease.length)this.prerelease=[e];else{let r=this.prerelease.length;while(--r>=0)"number"===typeof this.prerelease[r]&&(this.prerelease[r]++,r=-2);if(-1===r){if(t===this.prerelease.join(".")&&!1===n)throw new Error("invalid increment argument: identifier already exists");this.prerelease.push(e)}}if(t){let r=[t,e];!1===n&&(r=[t]),0===u(this.prerelease[0],t)?isNaN(this.prerelease[1])&&(this.prerelease=r):this.prerelease=r}break}default:throw new Error(`invalid increment argument: ${e}`)}return this.raw=this.format(),this.build.length&&(this.raw+=`+${this.build.join(".")}`),this}}e.exports=c},7414:function(e,t,n){"use strict";const r=n(144),o=(e,t)=>{const n=r(e.trim().replace(/^[=v]+/,""),t);return n?n.version:null};e.exports=o},2111:function(e,t,n){"use strict";const r=n(4641),o=n(3999),i=n(5580),s=n(4089),a=n(7059),l=n(5200),u=(e,t,n,u)=>{switch(t){case"===":return"object"===typeof e&&(e=e.version),"object"===typeof n&&(n=n.version),e===n;case"!==":return"object"===typeof e&&(e=e.version),"object"===typeof n&&(n=n.version),e!==n;case"":case"=":case"==":return r(e,n,u);case"!=":return o(e,n,u);case">":return i(e,n,u);case">=":return s(e,n,u);case"<":return a(e,n,u);case"<=":return l(e,n,u);default:throw new TypeError(`Invalid operator: ${t}`)}};e.exports=u},6170:function(e,t,n){"use strict";const r=n(3908),o=n(144),{safeRe:i,t:s}=n(9718),a=(e,t)=>{if(e instanceof r)return e;if("number"===typeof e&&(e=String(e)),"string"!==typeof e)return null;t=t||{};let n=null;if(t.rtl){const r=t.includePrerelease?i[s.COERCERTLFULL]:i[s.COERCERTL];let o;while((o=r.exec(e))&&(!n||n.index+n[0].length!==e.length))n&&o.index+o[0].length===n.index+n[0].length||(n=o),r.lastIndex=o.index+o[1].length+o[2].length;r.lastIndex=-1}else n=e.match(t.includePrerelease?i[s.COERCEFULL]:i[s.COERCE]);if(null===n)return null;const a=n[2],l=n[3]||"0",u=n[4]||"0",c=t.includePrerelease&&n[5]?`-${n[5]}`:"",d=t.includePrerelease&&n[6]?`+${n[6]}`:"";return o(`${a}.${l}.${u}${c}${d}`,t)};e.exports=a},909:function(e,t,n){"use strict";const r=n(3908),o=(e,t,n)=>{const o=new r(e,n),i=new r(t,n);return o.compare(i)||o.compareBuild(i)};e.exports=o},1763:function(e,t,n){"use strict";const r=n(560),o=(e,t)=>r(e,t,!0);e.exports=o},560:function(e,t,n){"use strict";const r=n(3908),o=(e,t,n)=>new r(e,n).compare(new r(t,n));e.exports=o},1832:function(e,t,n){"use strict";const r=n(144),o=(e,t)=>{const n=r(e,null,!0),o=r(t,null,!0),i=n.compare(o);if(0===i)return null;const s=i>0,a=s?n:o,l=s?o:n,u=!!a.prerelease.length,c=!!l.prerelease.length;if(c&&!u){if(!l.patch&&!l.minor)return"major";if(0===l.compareMain(a))return l.minor&&!l.patch?"minor":"patch"}const d=u?"pre":"";return n.major!==o.major?d+"major":n.minor!==o.minor?d+"minor":n.patch!==o.patch?d+"patch":"prerelease"};e.exports=o},4641:function(e,t,n){"use strict";const r=n(560),o=(e,t,n)=>0===r(e,t,n);e.exports=o},5580:function(e,t,n){"use strict";const r=n(560),o=(e,t,n)=>r(e,t,n)>0;e.exports=o},4089:function(e,t,n){"use strict";const r=n(560),o=(e,t,n)=>r(e,t,n)>=0;e.exports=o},3007:function(e,t,n){"use strict";const r=n(3908),o=(e,t,n,o,i)=>{"string"===typeof n&&(i=o,o=n,n=void 0);try{return new r(e instanceof r?e.version:e,n).inc(t,o,i).version}catch(s){return null}};e.exports=o},7059:function(e,t,n){"use strict";const r=n(560),o=(e,t,n)=>r(e,t,n)<0;e.exports=o},5200:function(e,t,n){"use strict";const r=n(560),o=(e,t,n)=>r(e,t,n)<=0;e.exports=o},2938:function(e,t,n){"use strict";const r=n(3908),o=(e,t)=>new r(e,t).major;e.exports=o},6254:function(e,t,n){"use strict";const r=n(3908),o=(e,t)=>new r(e,t).minor;e.exports=o},3999:function(e,t,n){"use strict";const r=n(560),o=(e,t,n)=>0!==r(e,t,n);e.exports=o},144:function(e,t,n){"use strict";const r=n(3908),o=(e,t,n=!1)=>{if(e instanceof r)return e;try{return new r(e,t)}catch(o){if(!n)return null;throw o}};e.exports=o},4493:function(e,t,n){"use strict";const r=n(3908),o=(e,t)=>new r(e,t).patch;e.exports=o},1729:function(e,t,n){"use strict";const r=n(144),o=(e,t)=>{const n=r(e,t);return n&&n.prerelease.length?n.prerelease:null};e.exports=o},9970:function(e,t,n){"use strict";const r=n(560),o=(e,t,n)=>r(t,e,n);e.exports=o},4277:function(e,t,n){"use strict";const r=n(909),o=(e,t)=>e.sort((e,n)=>r(n,e,t));e.exports=o},7638:function(e,t,n){"use strict";const r=n(8311),o=(e,t,n)=>{try{t=new r(t,n)}catch(o){return!1}return t.test(e)};e.exports=o},3927:function(e,t,n){"use strict";const r=n(909),o=(e,t)=>e.sort((e,n)=>r(e,n,t));e.exports=o},6953:function(e,t,n){"use strict";const r=n(144),o=(e,t)=>{const n=r(e,t);return n?n.version:null};e.exports=o},9589:function(e,t,n){"use strict";const r=n(9718),o=n(6874),i=n(3908),s=n(1123),a=n(144),l=n(6953),u=n(7414),c=n(3007),d=n(1832),f=n(2938),h=n(6254),p=n(4493),m=n(1729),v=n(560),g=n(9970),y=n(1763),b=n(909),_=n(3927),E=n(4277),w=n(5580),S=n(7059),T=n(4641),k=n(3999),C=n(4089),O=n(5200),A=n(2111),R=n(6170),I=n(3904),N=n(8311),L=n(7638),x=n(7631),P=n(9628),D=n(270),M=n(1261),F=n(3874),$=n(7075),j=n(5571),U=n(5342),B=n(6780),V=n(2525),G=n(5032);e.exports={parse:a,valid:l,clean:u,inc:c,diff:d,major:f,minor:h,patch:p,prerelease:m,compare:v,rcompare:g,compareLoose:y,compareBuild:b,sort:_,rsort:E,gt:w,lt:S,eq:T,neq:k,gte:C,lte:O,cmp:A,coerce:R,Comparator:I,Range:N,satisfies:L,toComparators:x,maxSatisfying:P,minSatisfying:D,minVersion:M,validRange:F,outside:$,gtr:j,ltr:U,intersects:B,simplifyRange:V,subset:G,SemVer:i,re:r.re,src:r.src,tokens:r.t,SEMVER_SPEC_VERSION:o.SEMVER_SPEC_VERSION,RELEASE_TYPES:o.RELEASE_TYPES,compareIdentifiers:s.compareIdentifiers,rcompareIdentifiers:s.rcompareIdentifiers}},6874:function(e){"use strict";const t="2.0.0",n=256,r=Number.MAX_SAFE_INTEGER||9007199254740991,o=16,i=n-6,s=["major","premajor","minor","preminor","patch","prepatch","prerelease"];e.exports={MAX_LENGTH:n,MAX_SAFE_COMPONENT_LENGTH:o,MAX_SAFE_BUILD_LENGTH:i,MAX_SAFE_INTEGER:r,RELEASE_TYPES:s,SEMVER_SPEC_VERSION:t,FLAG_INCLUDE_PRERELEASE:1,FLAG_LOOSE:2}},7272:function(e){"use strict";const t="object"===typeof process&&{NODE_ENV:"production",BASE_URL:""}.NODE_DEBUG&&/\bsemver\b/i.test({NODE_ENV:"production",BASE_URL:""}.NODE_DEBUG)?(...e)=>console.error("SEMVER",...e):()=>{};e.exports=t},1123:function(e){"use strict";const t=/^[0-9]+$/,n=(e,n)=>{if("number"===typeof e&&"number"===typeof n)return e===n?0:e<n?-1:1;const r=t.test(e),o=t.test(n);return r&&o&&(e=+e,n=+n),e===n?0:r&&!o?-1:o&&!r?1:e<n?-1:1},r=(e,t)=>n(t,e);e.exports={compareIdentifiers:n,rcompareIdentifiers:r}},8794:function(e){"use strict";class t{constructor(){this.max=1e3,this.map=new Map}get(e){const t=this.map.get(e);return void 0===t?void 0:(this.map.delete(e),this.map.set(e,t),t)}delete(e){return this.map.delete(e)}set(e,t){const n=this.delete(e);if(!n&&void 0!==t){if(this.map.size>=this.max){const e=this.map.keys().next().value;this.delete(e)}this.map.set(e,t)}return this}}e.exports=t},8587:function(e){"use strict";const t=Object.freeze({loose:!0}),n=Object.freeze({}),r=e=>e?"object"!==typeof e?t:e:n;e.exports=r},9718:function(e,t,n){"use strict";const{MAX_SAFE_COMPONENT_LENGTH:r,MAX_SAFE_BUILD_LENGTH:o,MAX_LENGTH:i}=n(6874),s=n(7272);t=e.exports={};const a=t.re=[],l=t.safeRe=[],u=t.src=[],c=t.safeSrc=[],d=t.t={};let f=0;const h="[a-zA-Z0-9-]",p=[["\\s",1],["\\d",i],[h,o]],m=e=>{for(const[t,n]of p)e=e.split(`${t}*`).join(`${t}{0,${n}}`).split(`${t}+`).join(`${t}{1,${n}}`);return e},v=(e,t,n)=>{const r=m(t),o=f++;s(e,o,t),d[e]=o,u[o]=t,c[o]=r,a[o]=new RegExp(t,n?"g":void 0),l[o]=new RegExp(r,n?"g":void 0)};v("NUMERICIDENTIFIER","0|[1-9]\\d*"),v("NUMERICIDENTIFIERLOOSE","\\d+"),v("NONNUMERICIDENTIFIER",`\\d*[a-zA-Z-]${h}*`),v("MAINVERSION",`(${u[d.NUMERICIDENTIFIER]})\\.(${u[d.NUMERICIDENTIFIER]})\\.(${u[d.NUMERICIDENTIFIER]})`),v("MAINVERSIONLOOSE",`(${u[d.NUMERICIDENTIFIERLOOSE]})\\.(${u[d.NUMERICIDENTIFIERLOOSE]})\\.(${u[d.NUMERICIDENTIFIERLOOSE]})`),v("PRERELEASEIDENTIFIER",`(?:${u[d.NONNUMERICIDENTIFIER]}|${u[d.NUMERICIDENTIFIER]})`),v("PRERELEASEIDENTIFIERLOOSE",`(?:${u[d.NONNUMERICIDENTIFIER]}|${u[d.NUMERICIDENTIFIERLOOSE]})`),v("PRERELEASE",`(?:-(${u[d.PRERELEASEIDENTIFIER]}(?:\\.${u[d.PRERELEASEIDENTIFIER]})*))`),v("PRERELEASELOOSE",`(?:-?(${u[d.PRERELEASEIDENTIFIERLOOSE]}(?:\\.${u[d.PRERELEASEIDENTIFIERLOOSE]})*))`),v("BUILDIDENTIFIER",`${h}+`),v("BUILD",`(?:\\+(${u[d.BUILDIDENTIFIER]}(?:\\.${u[d.BUILDIDENTIFIER]})*))`),v("FULLPLAIN",`v?${u[d.MAINVERSION]}${u[d.PRERELEASE]}?${u[d.BUILD]}?`),v("FULL",`^${u[d.FULLPLAIN]}$`),v("LOOSEPLAIN",`[v=\\s]*${u[d.MAINVERSIONLOOSE]}${u[d.PRERELEASELOOSE]}?${u[d.BUILD]}?`),v("LOOSE",`^${u[d.LOOSEPLAIN]}$`),v("GTLT","((?:<|>)?=?)"),v("XRANGEIDENTIFIERLOOSE",`${u[d.NUMERICIDENTIFIERLOOSE]}|x|X|\\*`),v("XRANGEIDENTIFIER",`${u[d.NUMERICIDENTIFIER]}|x|X|\\*`),v("XRANGEPLAIN",`[v=\\s]*(${u[d.XRANGEIDENTIFIER]})(?:\\.(${u[d.XRANGEIDENTIFIER]})(?:\\.(${u[d.XRANGEIDENTIFIER]})(?:${u[d.PRERELEASE]})?${u[d.BUILD]}?)?)?`),v("XRANGEPLAINLOOSE",`[v=\\s]*(${u[d.XRANGEIDENTIFIERLOOSE]})(?:\\.(${u[d.XRANGEIDENTIFIERLOOSE]})(?:\\.(${u[d.XRANGEIDENTIFIERLOOSE]})(?:${u[d.PRERELEASELOOSE]})?${u[d.BUILD]}?)?)?`),v("XRANGE",`^${u[d.GTLT]}\\s*${u[d.XRANGEPLAIN]}$`),v("XRANGELOOSE",`^${u[d.GTLT]}\\s*${u[d.XRANGEPLAINLOOSE]}$`),v("COERCEPLAIN",`(^|[^\\d])(\\d{1,${r}})(?:\\.(\\d{1,${r}}))?(?:\\.(\\d{1,${r}}))?`),v("COERCE",`${u[d.COERCEPLAIN]}(?:$|[^\\d])`),v("COERCEFULL",u[d.COERCEPLAIN]+`(?:${u[d.PRERELEASE]})?`+`(?:${u[d.BUILD]})?(?:$|[^\\d])`),v("COERCERTL",u[d.COERCE],!0),v("COERCERTLFULL",u[d.COERCEFULL],!0),v("LONETILDE","(?:~>?)"),v("TILDETRIM",`(\\s*)${u[d.LONETILDE]}\\s+`,!0),t.tildeTrimReplace="$1~",v("TILDE",`^${u[d.LONETILDE]}${u[d.XRANGEPLAIN]}$`),v("TILDELOOSE",`^${u[d.LONETILDE]}${u[d.XRANGEPLAINLOOSE]}$`),v("LONECARET","(?:\\^)"),v("CARETTRIM",`(\\s*)${u[d.LONECARET]}\\s+`,!0),t.caretTrimReplace="$1^",v("CARET",`^${u[d.LONECARET]}${u[d.XRANGEPLAIN]}$`),v("CARETLOOSE",`^${u[d.LONECARET]}${u[d.XRANGEPLAINLOOSE]}$`),v("COMPARATORLOOSE",`^${u[d.GTLT]}\\s*(${u[d.LOOSEPLAIN]})$|^$`),v("COMPARATOR",`^${u[d.GTLT]}\\s*(${u[d.FULLPLAIN]})$|^$`),v("COMPARATORTRIM",`(\\s*)${u[d.GTLT]}\\s*(${u[d.LOOSEPLAIN]}|${u[d.XRANGEPLAIN]})`,!0),t.comparatorTrimReplace="$1$2$3",v("HYPHENRANGE",`^\\s*(${u[d.XRANGEPLAIN]})\\s+-\\s+(${u[d.XRANGEPLAIN]})\\s*$`),v("HYPHENRANGELOOSE",`^\\s*(${u[d.XRANGEPLAINLOOSE]})\\s+-\\s+(${u[d.XRANGEPLAINLOOSE]})\\s*$`),v("STAR","(<|>)?=?\\s*\\*"),v("GTE0","^\\s*>=\\s*0\\.0\\.0\\s*$"),v("GTE0PRE","^\\s*>=\\s*0\\.0\\.0-0\\s*$")},5571:function(e,t,n){"use strict";const r=n(7075),o=(e,t,n)=>r(e,t,">",n);e.exports=o},6780:function(e,t,n){"use strict";const r=n(8311),o=(e,t,n)=>(e=new r(e,n),t=new r(t,n),e.intersects(t,n));e.exports=o},5342:function(e,t,n){"use strict";const r=n(7075),o=(e,t,n)=>r(e,t,"<",n);e.exports=o},9628:function(e,t,n){"use strict";const r=n(3908),o=n(8311),i=(e,t,n)=>{let i=null,s=null,a=null;try{a=new o(t,n)}catch(l){return null}return e.forEach(e=>{a.test(e)&&(i&&-1!==s.compare(e)||(i=e,s=new r(i,n)))}),i};e.exports=i},270:function(e,t,n){"use strict";const r=n(3908),o=n(8311),i=(e,t,n)=>{let i=null,s=null,a=null;try{a=new o(t,n)}catch(l){return null}return e.forEach(e=>{a.test(e)&&(i&&1!==s.compare(e)||(i=e,s=new r(i,n)))}),i};e.exports=i},1261:function(e,t,n){"use strict";const r=n(3908),o=n(8311),i=n(5580),s=(e,t)=>{e=new o(e,t);let n=new r("0.0.0");if(e.test(n))return n;if(n=new r("0.0.0-0"),e.test(n))return n;n=null;for(let o=0;o<e.set.length;++o){const t=e.set[o];let s=null;t.forEach(e=>{const t=new r(e.semver.version);switch(e.operator){case">":0===t.prerelease.length?t.patch++:t.prerelease.push(0),t.raw=t.format();case"":case">=":s&&!i(t,s)||(s=t);break;case"<":case"<=":break;default:throw new Error(`Unexpected operation: ${e.operator}`)}}),!s||n&&!i(n,s)||(n=s)}return n&&e.test(n)?n:null};e.exports=s},7075:function(e,t,n){"use strict";const r=n(3908),o=n(3904),{ANY:i}=o,s=n(8311),a=n(7638),l=n(5580),u=n(7059),c=n(5200),d=n(4089),f=(e,t,n,f)=>{let h,p,m,v,g;switch(e=new r(e,f),t=new s(t,f),n){case">":h=l,p=c,m=u,v=">",g=">=";break;case"<":h=u,p=d,m=l,v="<",g="<=";break;default:throw new TypeError('Must provide a hilo val of "<" or ">"')}if(a(e,t,f))return!1;for(let r=0;r<t.set.length;++r){const n=t.set[r];let s=null,a=null;if(n.forEach(e=>{e.semver===i&&(e=new o(">=0.0.0")),s=s||e,a=a||e,h(e.semver,s.semver,f)?s=e:m(e.semver,a.semver,f)&&(a=e)}),s.operator===v||s.operator===g)return!1;if((!a.operator||a.operator===v)&&p(e,a.semver))return!1;if(a.operator===g&&m(e,a.semver))return!1}return!0};e.exports=f},2525:function(e,t,n){"use strict";const r=n(7638),o=n(560);e.exports=(e,t,n)=>{const i=[];let s=null,a=null;const l=e.sort((e,t)=>o(e,t,n));for(const o of l){const e=r(o,t,n);e?(a=o,s||(s=o)):(a&&i.push([s,a]),a=null,s=null)}s&&i.push([s,null]);const u=[];for(const[r,o]of i)r===o?u.push(r):o||r!==l[0]?o?r===l[0]?u.push(`<=${o}`):u.push(`${r} - ${o}`):u.push(`>=${r}`):u.push("*");const c=u.join(" || "),d="string"===typeof t.raw?t.raw:String(t);return c.length<d.length?c:t}},5032:function(e,t,n){"use strict";const r=n(8311),o=n(3904),{ANY:i}=o,s=n(7638),a=n(560),l=(e,t,n={})=>{if(e===t)return!0;e=new r(e,n),t=new r(t,n);let o=!1;e:for(const r of e.set){for(const e of t.set){const t=d(r,e,n);if(o=o||null!==t,t)continue e}if(o)return!1}return!0},u=[new o(">=0.0.0-0")],c=[new o(">=0.0.0")],d=(e,t,n)=>{if(e===t)return!0;if(1===e.length&&e[0].semver===i){if(1===t.length&&t[0].semver===i)return!0;e=n.includePrerelease?u:c}if(1===t.length&&t[0].semver===i){if(n.includePrerelease)return!0;t=c}const r=new Set;let o,l,d,p,m,v,g;for(const i of e)">"===i.operator||">="===i.operator?o=f(o,i,n):"<"===i.operator||"<="===i.operator?l=h(l,i,n):r.add(i.semver);if(r.size>1)return null;if(o&&l){if(d=a(o.semver,l.semver,n),d>0)return null;if(0===d&&(">="!==o.operator||"<="!==l.operator))return null}for(const i of r){if(o&&!s(i,String(o),n))return null;if(l&&!s(i,String(l),n))return null;for(const e of t)if(!s(i,String(e),n))return!1;return!0}let y=!(!l||n.includePrerelease||!l.semver.prerelease.length)&&l.semver,b=!(!o||n.includePrerelease||!o.semver.prerelease.length)&&o.semver;y&&1===y.prerelease.length&&"<"===l.operator&&0===y.prerelease[0]&&(y=!1);for(const i of t){if(g=g||">"===i.operator||">="===i.operator,v=v||"<"===i.operator||"<="===i.operator,o)if(b&&i.semver.prerelease&&i.semver.prerelease.length&&i.semver.major===b.major&&i.semver.minor===b.minor&&i.semver.patch===b.patch&&(b=!1),">"===i.operator||">="===i.operator){if(p=f(o,i,n),p===i&&p!==o)return!1}else if(">="===o.operator&&!s(o.semver,String(i),n))return!1;if(l)if(y&&i.semver.prerelease&&i.semver.prerelease.length&&i.semver.major===y.major&&i.semver.minor===y.minor&&i.semver.patch===y.patch&&(y=!1),"<"===i.operator||"<="===i.operator){if(m=h(l,i,n),m===i&&m!==l)return!1}else if("<="===l.operator&&!s(l.semver,String(i),n))return!1;if(!i.operator&&(l||o)&&0!==d)return!1}return!(o&&v&&!l&&0!==d)&&(!(l&&g&&!o&&0!==d)&&(!b&&!y))},f=(e,t,n)=>{if(!e)return t;const r=a(e.semver,t.semver,n);return r>0?e:r<0||">"===t.operator&&">="===e.operator?t:e},h=(e,t,n)=>{if(!e)return t;const r=a(e.semver,t.semver,n);return r<0?e:r>0||"<"===t.operator&&"<="===e.operator?t:e};e.exports=l},7631:function(e,t,n){"use strict";const r=n(8311),o=(e,t)=>new r(e,t).set.map(e=>e.map(e=>e.value).join(" ").trim().split(" "));e.exports=o},3874:function(e,t,n){"use strict";const r=n(8311),o=(e,t)=>{try{return new r(e,t).range||"*"}catch(n){return null}};e.exports=o},4144:function(e,t,n){"use strict";n.d(t,{A:function(){return P}});var r=n(641),o=n(953),i={207:(e,t,n)=>{e.exports=n(452)},452:e=>{var t=function(e){var t,n=Object.prototype,r=n.hasOwnProperty,o="function"==typeof Symbol?Symbol:{},i=o.iterator||"@@iterator",s=o.asyncIterator||"@@asyncIterator",a=o.toStringTag||"@@toStringTag";function l(e,t,n){return Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}),e[t]}try{l({},"")}catch(e){l=function(e,t,n){return e[t]=n}}function u(e,t,n,r){var o=t&&t.prototype instanceof v?t:v,i=Object.create(o.prototype),s=new A(r||[]);return i._invoke=function(e,t,n){var r=d;return function(o,i){if(r===h)throw new Error("Generator is already running");if(r===p){if("throw"===o)throw i;return I()}for(n.method=o,n.arg=i;;){var s=n.delegate;if(s){var a=k(s,n);if(a){if(a===m)continue;return a}}if("next"===n.method)n.sent=n._sent=n.arg;else if("throw"===n.method){if(r===d)throw r=p,n.arg;n.dispatchException(n.arg)}else"return"===n.method&&n.abrupt("return",n.arg);r=h;var l=c(e,t,n);if("normal"===l.type){if(r=n.done?p:f,l.arg===m)continue;return{value:l.arg,done:n.done}}"throw"===l.type&&(r=p,n.method="throw",n.arg=l.arg)}}}(e,n,s),i}function c(e,t,n){try{return{type:"normal",arg:e.call(t,n)}}catch(e){return{type:"throw",arg:e}}}e.wrap=u;var d="suspendedStart",f="suspendedYield",h="executing",p="completed",m={};function v(){}function g(){}function y(){}var b={};l(b,i,function(){return this});var _=Object.getPrototypeOf,E=_&&_(_(R([])));E&&E!==n&&r.call(E,i)&&(b=E);var w=y.prototype=v.prototype=Object.create(b);function S(e){["next","throw","return"].forEach(function(t){l(e,t,function(e){return this._invoke(t,e)})})}function T(e,t){function n(o,i,s,a){var l=c(e[o],e,i);if("throw"!==l.type){var u=l.arg,d=u.value;return d&&"object"==typeof d&&r.call(d,"__await")?t.resolve(d.__await).then(function(e){n("next",e,s,a)},function(e){n("throw",e,s,a)}):t.resolve(d).then(function(e){u.value=e,s(u)},function(e){return n("throw",e,s,a)})}a(l.arg)}var o;this._invoke=function(e,r){function i(){return new t(function(t,o){n(e,r,t,o)})}return o=o?o.then(i,i):i()}}function k(e,n){var r=e.iterator[n.method];if(r===t){if(n.delegate=null,"throw"===n.method){if(e.iterator.return&&(n.method="return",n.arg=t,k(e,n),"throw"===n.method))return m;n.method="throw",n.arg=new TypeError("The iterator does not provide a 'throw' method")}return m}var o=c(r,e.iterator,n.arg);if("throw"===o.type)return n.method="throw",n.arg=o.arg,n.delegate=null,m;var i=o.arg;return i?i.done?(n[e.resultName]=i.value,n.next=e.nextLoc,"return"!==n.method&&(n.method="next",n.arg=t),n.delegate=null,m):i:(n.method="throw",n.arg=new TypeError("iterator result is not an object"),n.delegate=null,m)}function C(e){var t={tryLoc:e[0]};1 in e&&(t.catchLoc=e[1]),2 in e&&(t.finallyLoc=e[2],t.afterLoc=e[3]),this.tryEntries.push(t)}function O(e){var t=e.completion||{};t.type="normal",delete t.arg,e.completion=t}function A(e){this.tryEntries=[{tryLoc:"root"}],e.forEach(C,this),this.reset(!0)}function R(e){if(e){var n=e[i];if(n)return n.call(e);if("function"==typeof e.next)return e;if(!isNaN(e.length)){var o=-1,s=function n(){for(;++o<e.length;)if(r.call(e,o))return n.value=e[o],n.done=!1,n;return n.value=t,n.done=!0,n};return s.next=s}}return{next:I}}function I(){return{value:t,done:!0}}return g.prototype=y,l(w,"constructor",y),l(y,"constructor",g),g.displayName=l(y,a,"GeneratorFunction"),e.isGeneratorFunction=function(e){var t="function"==typeof e&&e.constructor;return!!t&&(t===g||"GeneratorFunction"===(t.displayName||t.name))},e.mark=function(e){return Object.setPrototypeOf?Object.setPrototypeOf(e,y):(e.__proto__=y,l(e,a,"GeneratorFunction")),e.prototype=Object.create(w),e},e.awrap=function(e){return{__await:e}},S(T.prototype),l(T.prototype,s,function(){return this}),e.AsyncIterator=T,e.async=function(t,n,r,o,i){void 0===i&&(i=Promise);var s=new T(u(t,n,r,o),i);return e.isGeneratorFunction(n)?s:s.next().then(function(e){return e.done?e.value:s.next()})},S(w),l(w,a,"Generator"),l(w,i,function(){return this}),l(w,"toString",function(){return"[object Generator]"}),e.keys=function(e){var t=[];for(var n in e)t.push(n);return t.reverse(),function n(){for(;t.length;){var r=t.pop();if(r in e)return n.value=r,n.done=!1,n}return n.done=!0,n}},e.values=R,A.prototype={constructor:A,reset:function(e){if(this.prev=0,this.next=0,this.sent=this._sent=t,this.done=!1,this.delegate=null,this.method="next",this.arg=t,this.tryEntries.forEach(O),!e)for(var n in this)"t"===n.charAt(0)&&r.call(this,n)&&!isNaN(+n.slice(1))&&(this[n]=t)},stop:function(){this.done=!0;var e=this.tryEntries[0].completion;if("throw"===e.type)throw e.arg;return this.rval},dispatchException:function(e){if(this.done)throw e;var n=this;function o(r,o){return a.type="throw",a.arg=e,n.next=r,o&&(n.method="next",n.arg=t),!!o}for(var i=this.tryEntries.length-1;i>=0;--i){var s=this.tryEntries[i],a=s.completion;if("root"===s.tryLoc)return o("end");if(s.tryLoc<=this.prev){var l=r.call(s,"catchLoc"),u=r.call(s,"finallyLoc");if(l&&u){if(this.prev<s.catchLoc)return o(s.catchLoc,!0);if(this.prev<s.finallyLoc)return o(s.finallyLoc)}else if(l){if(this.prev<s.catchLoc)return o(s.catchLoc,!0)}else{if(!u)throw new Error("try statement without catch or finally");if(this.prev<s.finallyLoc)return o(s.finallyLoc)}}}},abrupt:function(e,t){for(var n=this.tryEntries.length-1;n>=0;--n){var o=this.tryEntries[n];if(o.tryLoc<=this.prev&&r.call(o,"finallyLoc")&&this.prev<o.finallyLoc){var i=o;break}}i&&("break"===e||"continue"===e)&&i.tryLoc<=t&&t<=i.finallyLoc&&(i=null);var s=i?i.completion:{};return s.type=e,s.arg=t,i?(this.method="next",this.next=i.finallyLoc,m):this.complete(s)},complete:function(e,t){if("throw"===e.type)throw e.arg;return"break"===e.type||"continue"===e.type?this.next=e.arg:"return"===e.type?(this.rval=this.arg=e.arg,this.method="return",this.next="end"):"normal"===e.type&&t&&(this.next=t),m},finish:function(e){for(var t=this.tryEntries.length-1;t>=0;--t){var n=this.tryEntries[t];if(n.finallyLoc===e)return this.complete(n.completion,n.afterLoc),O(n),m}},catch:function(e){for(var t=this.tryEntries.length-1;t>=0;--t){var n=this.tryEntries[t];if(n.tryLoc===e){var r=n.completion;if("throw"===r.type){var o=r.arg;O(n)}return o}}throw new Error("illegal catch attempt")},delegateYield:function(e,n,r){return this.delegate={iterator:R(e),resultName:n,nextLoc:r},"next"===this.method&&(this.arg=t),m}},e}(e.exports);try{regeneratorRuntime=t}catch(e){"object"==typeof globalThis?globalThis.regeneratorRuntime=t:Function("r","regeneratorRuntime = r")(t)}}},s={};function a(e){var t=s[e];if(void 0!==t)return t.exports;var n=s[e]={exports:{}};return i[e](n,n.exports,a),n.exports}a.n=e=>{var t=e&&e.__esModule?()=>e.default:()=>e;return a.d(t,{a:t}),t},a.d=(e,t)=>{for(var n in t)a.o(t,n)&&!a.o(e,n)&&Object.defineProperty(e,n,{enumerable:!0,get:t[n]})},a.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t);var l={};function u(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=new Array(t);n<t;n++)r[n]=e[n];return r}function c(e,t){if(e){if("string"==typeof e)return u(e,t);var n=Object.prototype.toString.call(e).slice(8,-1);return"Object"===n&&e.constructor&&(n=e.constructor.name),"Map"===n||"Set"===n?Array.from(e):"Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)?u(e,t):void 0}}function d(e){return function(e){if(Array.isArray(e))return u(e)}(e)||function(e){if("undefined"!=typeof Symbol&&null!=e[Symbol.iterator]||null!=e["@@iterator"])return Array.from(e)}(e)||c(e)||function(){throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}()}function f(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}a.d(l,{A:()=>x});const h=(g={Fragment:()=>r.FK,computed:()=>r.EW,createTextVNode:()=>r.eW,createVNode:()=>r.bF,defineComponent:()=>r.pM,nextTick:()=>r.dY,reactive:()=>o.Kh,ref:()=>o.KR,watch:()=>r.wB,watchEffect:()=>r.nT},y={},a.d(y,g),y),p=(0,h.defineComponent)({props:{data:{required:!0,type:String},onClick:Function},render:function(){var e=this.data,t=this.onClick;return(0,h.createVNode)("span",{class:"vjs-tree-brackets",onClick:t},[e])}}),m=(0,h.defineComponent)({emits:["change","update:modelValue"],props:{checked:{type:Boolean,default:!1},isMultiple:Boolean,onChange:Function},setup:function(e,t){var n=t.emit;return{uiType:(0,h.computed)(function(){return e.isMultiple?"checkbox":"radio"}),model:(0,h.computed)({get:function(){return e.checked},set:function(e){return n("update:modelValue",e)}})}},render:function(){var e=this.uiType,t=this.model,n=this.$emit;return(0,h.createVNode)("label",{class:["vjs-check-controller",t?"is-checked":""],onClick:function(e){return e.stopPropagation()}},[(0,h.createVNode)("span",{class:"vjs-check-controller-inner is-".concat(e)},null),(0,h.createVNode)("input",{checked:t,class:"vjs-check-controller-original is-".concat(e),type:e,onChange:function(){return n("change",t)}},null)])}}),v=(0,h.defineComponent)({props:{nodeType:{required:!0,type:String},onClick:Function},render:function(){var e=this.nodeType,t=this.onClick,n="objectStart"===e||"arrayStart"===e;return n||"objectCollapsed"===e||"arrayCollapsed"===e?(0,h.createVNode)("span",{class:"vjs-carets vjs-carets-".concat(n?"open":"close"),onClick:t},[(0,h.createVNode)("svg",{viewBox:"0 0 1024 1024",focusable:"false","data-icon":"caret-down",width:"1em",height:"1em",fill:"currentColor","aria-hidden":"true"},[(0,h.createVNode)("path",{d:"M840.4 300H183.6c-19.7 0-30.7 20.8-18.5 35l328.4 380.8c9.4 10.9 27.5 10.9 37 0L858.9 335c12.2-14.2 1.2-35-18.5-35z"},null)])]):null}});var g,y;function b(e){return b="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},b(e)}function _(e){return Object.prototype.toString.call(e).slice(8,-1).toLowerCase()}function E(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"root",n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:0,r=(arguments.length>3?arguments[3]:void 0)||{},o=r.key,i=r.index,s=r.type,a=void 0===s?"content":s,l=r.showComma,u=void 0!==l&&l,c=r.length,d=void 0===c?1:c,f=_(e);if("array"===f){var h=w(e.map(function(e,r,o){return E(e,"".concat(t,"[").concat(r,"]"),n+1,{index:r,showComma:r!==o.length-1,length:d,type:a})}));return[E("[",t,n,{showComma:!1,key:o,length:e.length,type:"arrayStart"})[0]].concat(h,E("]",t,n,{showComma:u,length:e.length,type:"arrayEnd"})[0])}if("object"===f){var p=Object.keys(e),m=w(p.map(function(r,o,i){return E(e[r],/^[a-zA-Z_]\w*$/.test(r)?"".concat(t,".").concat(r):"".concat(t,'["').concat(r,'"]'),n+1,{key:r,showComma:o!==i.length-1,length:d,type:a})}));return[E("{",t,n,{showComma:!1,key:o,index:i,length:p.length,type:"objectStart"})[0]].concat(m,E("}",t,n,{showComma:u,length:p.length,type:"objectEnd"})[0])}return[{content:e,level:n,key:o,index:i,path:t,showComma:u,length:d,type:a}]}function w(e){if("function"==typeof Array.prototype.flat)return e.flat();for(var t=d(e),n=[];t.length;){var r=t.shift();Array.isArray(r)?t.unshift.apply(t,d(r)):n.push(r)}return n}function S(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:new WeakMap;if(null==e)return e;if(e instanceof Date)return new Date(e);if(e instanceof RegExp)return new RegExp(e);if("object"!==b(e))return e;if(t.get(e))return t.get(e);if(Array.isArray(e)){var n=e.map(function(e){return S(e,t)});return t.set(e,n),n}var r={};for(var o in e)r[o]=S(e[o],t);return t.set(e,r),r}function T(e,t,n,r,o,i,s){try{var a=e[i](s),l=a.value}catch(e){return void n(e)}a.done?t(l):Promise.resolve(l).then(r,o)}var k=a(207),C=a.n(k);function O(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter(function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable})),n.push.apply(n,r)}return n}function A(e){for(var t=1;t<arguments.length;t++){var n=null!=arguments[t]?arguments[t]:{};t%2?O(Object(n),!0).forEach(function(t){f(e,t,n[t])}):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(n)):O(Object(n)).forEach(function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(n,t))})}return e}var R={data:{type:[String,Number,Boolean,Array,Object],default:null},rootPath:{type:String,default:"root"},indent:{type:Number,default:2},showLength:{type:Boolean,default:!1},showDoubleQuotes:{type:Boolean,default:!0},renderNodeKey:Function,renderNodeValue:Function,renderNodeActions:{type:[Boolean,Function],default:void 0},selectableType:String,showSelectController:{type:Boolean,default:!1},showLine:{type:Boolean,default:!0},showLineNumber:{type:Boolean,default:!1},selectOnClickNode:{type:Boolean,default:!0},nodeSelectable:{type:Function,default:function(){return!0}},highlightSelectedNode:{type:Boolean,default:!0},showIcon:{type:Boolean,default:!1},theme:{type:String,default:"light"},showKeyValueSpace:{type:Boolean,default:!0},editable:{type:Boolean,default:!1},editableTrigger:{type:String,default:"click"},onNodeClick:{type:Function},onNodeMouseover:{type:Function},onBracketsClick:{type:Function},onIconClick:{type:Function},onValueChange:{type:Function}};const I=(0,h.defineComponent)({name:"TreeNode",props:A(A({},R),{},{node:{type:Object,required:!0},collapsed:Boolean,checked:Boolean,style:Object,onSelectedChange:{type:Function}}),emits:["nodeClick","nodeMouseover","bracketsClick","iconClick","selectedChange","valueChange"],setup:function(e,t){var n=t.emit,r=(0,h.computed)(function(){return _(e.node.content)}),o=(0,h.computed)(function(){return"vjs-value vjs-value-".concat(r.value)}),i=(0,h.computed)(function(){return e.showDoubleQuotes?'"'.concat(e.node.key,'"'):e.node.key}),s=(0,h.computed)(function(){return"multiple"===e.selectableType}),a=(0,h.computed)(function(){return"single"===e.selectableType}),l=(0,h.computed)(function(){return e.nodeSelectable(e.node)&&(s.value||a.value)}),u=(0,h.reactive)({editing:!1}),c=function(t){var r,o,i="null"===(o=null===(r=t.target)||void 0===r?void 0:r.value)?null:"undefined"===o?void 0:"true"===o||"false"!==o&&(o[0]+o[o.length-1]==='""'||o[0]+o[o.length-1]==="''"?o.slice(1,-1):"number"==typeof Number(o)&&!isNaN(Number(o))||"NaN"===o?Number(o):o);n("valueChange",i,e.node.path)},d=(0,h.computed)(function(){var t,n=null===(t=e.node)||void 0===t?void 0:t.content;return null===n?n="null":void 0===n&&(n="undefined"),"string"===r.value?'"'.concat(n,'"'):n+""}),g=function(){var t=e.renderNodeValue;return t?t({node:e.node,defaultValue:d.value}):d.value},y=function(){n("bracketsClick",!e.collapsed,e.node)},b=function(){n("iconClick",!e.collapsed,e.node)},E=function(){n("selectedChange",e.node)},w=function(){n("nodeClick",e.node),l.value&&e.selectOnClickNode&&n("selectedChange",e.node)},S=function(){n("nodeMouseover",e.node)},k=function(t){if(e.editable&&!u.editing){u.editing=!0;var n=function e(n){var r;n.target!==t.target&&(null===(r=n.target)||void 0===r?void 0:r.parentElement)!==t.target&&(u.editing=!1,document.removeEventListener("click",e))};document.removeEventListener("click",n),document.addEventListener("click",n)}},O=function(){var e=(0,h.ref)(!1),t=function(){var t,n=(t=C().mark(function t(n){return C().wrap(function(t){for(;;)switch(t.prev=t.next){case 0:return t.prev=0,t.next=3,navigator.clipboard.writeText(n);case 3:e.value=!0,setTimeout(function(){e.value=!1},300),t.next=10;break;case 7:t.prev=7,t.t0=t.catch(0),console.error("[vue-json-pretty] Copy failed: ",t.t0);case 10:case"end":return t.stop()}},t,null,[[0,7]])}),function(){var e=this,n=arguments;return new Promise(function(r,o){var i=t.apply(e,n);function s(e){T(i,r,o,s,a,"next",e)}function a(e){T(i,r,o,s,a,"throw",e)}s(void 0)})});return function(e){return n.apply(this,arguments)}}();return{copy:t}}().copy,A=function(){var t=e.node,n=t.key,r=t.path,o=e.rootPath,i=new Function("data","return data".concat(r.slice(o.length)))(e.data),s=JSON.stringify(n?f({},n,i):i,null,2);O(s)},R=function(){var t=e.renderNodeActions;if(!t)return null;var n={copy:A};return"function"==typeof t?t({node:e.node,defaultActions:n}):(0,h.createVNode)("span",{onClick:A,class:"vjs-tree-node-actions-item"},[(0,h.createTextVNode)("copy")])};return function(){var t,n=e.node;return(0,h.createVNode)("div",{class:{"vjs-tree-node":!0,"has-selector":e.showSelectController,"has-carets":e.showIcon,"is-highlight":e.highlightSelectedNode&&e.checked,dark:"dark"===e.theme},onClick:w,onMouseover:S,style:e.style},[e.showLineNumber&&(0,h.createVNode)("span",{class:"vjs-node-index"},[n.id+1]),e.showSelectController&&l.value&&"objectEnd"!==n.type&&"arrayEnd"!==n.type&&(0,h.createVNode)(m,{isMultiple:s.value,checked:e.checked,onChange:E},null),(0,h.createVNode)("div",{class:"vjs-indent"},[Array.from(Array(n.level)).map(function(t,n){return(0,h.createVNode)("div",{key:n,class:{"vjs-indent-unit":!0,"has-line":e.showLine}},[Array.from(Array(e.indent)).map(function(){return(0,h.createVNode)(h.Fragment,null,[(0,h.createTextVNode)(" ")])})])}),e.showIcon&&(0,h.createVNode)(v,{nodeType:n.type,onClick:b},null)]),n.key&&(0,h.createVNode)("span",{class:"vjs-key"},[(t=e.renderNodeKey,t?t({node:e.node,defaultKey:i.value||""}):i.value),(0,h.createVNode)("span",{class:"vjs-colon"},[":".concat(e.showKeyValueSpace?" ":"")])]),(0,h.createVNode)("span",null,["content"!==n.type&&n.content?(0,h.createVNode)(p,{data:n.content.toString(),onClick:y},null):(0,h.createVNode)("span",{class:o.value,onClick:!e.editable||e.editableTrigger&&"click"!==e.editableTrigger?void 0:k,onDblclick:e.editable&&"dblclick"===e.editableTrigger?k:void 0},[e.editable&&u.editing?(0,h.createVNode)("input",{value:d.value,onChange:c,style:{padding:"3px 8px",border:"1px solid #eee",boxShadow:"none",boxSizing:"border-box",borderRadius:5,fontFamily:"inherit"}},null):g()]),n.showComma&&(0,h.createVNode)("span",null,[","]),e.showLength&&e.collapsed&&(0,h.createVNode)("span",{class:"vjs-comment"},[(0,h.createTextVNode)(" // "),n.length,(0,h.createTextVNode)(" items ")])]),e.renderNodeActions&&(0,h.createVNode)("span",{class:"vjs-tree-node-actions"},[R()])])}}});function N(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter(function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable})),n.push.apply(n,r)}return n}function L(e){for(var t=1;t<arguments.length;t++){var n=null!=arguments[t]?arguments[t]:{};t%2?N(Object(n),!0).forEach(function(t){f(e,t,n[t])}):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(n)):N(Object(n)).forEach(function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(n,t))})}return e}const x=(0,h.defineComponent)({name:"Tree",props:L(L({},R),{},{collapsedNodeLength:{type:Number,default:1/0},deep:{type:Number,default:1/0},pathCollapsible:{type:Function,default:function(){return!1}},virtual:{type:Boolean,default:!1},height:{type:Number,default:400},itemHeight:{type:Number,default:20},dynamicHeight:{type:Boolean,default:!0},selectedValue:{type:[String,Array],default:function(){return""}},collapsedOnClickBrackets:{type:Boolean,default:!0},style:Object,onSelectedChange:{type:Function},theme:{type:String,default:"light"}}),slots:["renderNodeKey","renderNodeValue","renderNodeActions"],emits:["nodeClick","nodeMouseover","bracketsClick","iconClick","selectedChange","update:selectedValue","update:data"],setup:function(e,t){var n=t.emit,r=t.slots,o=(0,h.ref)(),i=(0,h.computed)(function(){return E(e.data,e.rootPath)}),s=function(t,n){return i.value.reduce(function(r,o){var i,s=o.level>=t||o.length>=n,a=null===(i=e.pathCollapsible)||void 0===i?void 0:i.call(e,o);return"objectStart"!==o.type&&"arrayStart"!==o.type||!s&&!a?r:L(L({},r),{},f({},o.path,1))},{})},a=(0,h.reactive)({translateY:0,visibleData:null,hiddenPaths:s(e.deep,e.collapsedNodeLength),startIndex:0,endIndex:0}),l=[],u=[],p=0,m={},v=function(t){l=Array(t).fill(0).map(function(){return e.itemHeight||20}),(u=new Array(t+1))[0]=0;for(var n=0;n<t;n++)u[n+1]=u[n]+l[n];p=u[t]||0},g=function(e){var t=l.length;e<0&&(e=0),e>t&&(e=t);for(var n=e;n<t;n++)u[n+1]=u[n]+l[n];p=u[t]||0},y=function(e,t){for(var n=0,r=e.length-1;n<r;){var o=n+r>>>1;e[o]<t?n=o+1:r=o}return n},b=(0,h.computed)(function(){for(var e=null,t=[],n=i.value.length,r=0;r<n;r++){var o=L(L({},i.value[r]),{},{id:r}),s=a.hiddenPaths[o.path];if(e&&e.path===o.path){var l="objectStart"===e.type,u=L(L(L({},o),e),{},{showComma:o.showComma,content:l?"{...}":"[...]",type:l?"objectCollapsed":"arrayCollapsed"});e=null,t.push(u)}else{if(s&&!e){e=o;continue}if(e)continue;t.push(o)}}return t}),_=(0,h.computed)(function(){var t=e.selectedValue;return t&&"multiple"===e.selectableType&&Array.isArray(t)?t:[t]}),w=(0,h.computed)(function(){return!e.selectableType||e.selectOnClickNode||e.showSelectController?"":"When selectableType is not null, selectOnClickNode and showSelectController cannot be false at the same time, because this will cause the selection to fail."}),T=(0,h.computed)(function(){return e.dynamicHeight?p||0:b.value.length*e.itemHeight}),k=function t(){var n=b.value;if(n)if(e.virtual){var r,i=(null===(r=o.value)||void 0===r?void 0:r.scrollTop)||0;if(e.dynamicHeight){l.length!==n.length&&v(n.length);var s=function(e){var t=y(u,e+1e-4);return Math.max(0,Math.min(t-1,l.length-1))}(i),c=function(e,t){var n=y(u,e+t);return Math.max(0,Math.min(n+1,l.length))}(i,e.height),d=Math.max(0,s-5),f=Math.min(n.length,c+5);a.startIndex=d,a.endIndex=f,a.translateY=u[d]||0,a.visibleData=n.slice(d,f),(0,h.nextTick)().then(function(){for(var e=!1,n=a.startIndex;n<a.endIndex;n++){var r=m[n];if(r){var o=r.offsetHeight;o&&l[n]!==o&&(l[n]=o,u[n+1]=u[n]+l[n],g(n+1),e=!0)}}e&&t()})}else{var p=e.height/e.itemHeight,_=Math.floor(i/e.itemHeight),E=_<0?0:_+p>n.length?n.length-p:_;E<0&&(E=0);var w=E+p;a.translateY=E*e.itemHeight,a.startIndex=E,a.endIndex=w,a.visibleData=n.slice(E,w)}}else a.translateY=0,a.startIndex=0,a.endIndex=n.length,a.visibleData=n},C=null,O=function(){C&&cancelAnimationFrame(C),C=requestAnimationFrame(function(){k()})},A=function(t){var r,o,i=t.path,s=e.selectableType;if("multiple"===s){var a=_.value.findIndex(function(e){return e===i}),l=d(_.value);-1!==a?l.splice(a,1):l.push(i),n("update:selectedValue",l),n("selectedChange",l,d(_.value))}else if("single"===s&&_.value[0]!==i){var u=(r=_.value,o=1,function(e){if(Array.isArray(e))return e}(r)||function(e,t){var n=null==e?null:"undefined"!=typeof Symbol&&e[Symbol.iterator]||e["@@iterator"];if(null!=n){var r,o,i=[],s=!0,a=!1;try{for(n=n.call(e);!(s=(r=n.next()).done)&&(i.push(r.value),!t||i.length!==t);s=!0);}catch(e){a=!0,o=e}finally{try{s||null==n.return||n.return()}finally{if(a)throw o}}return i}}(r,o)||c(r,o)||function(){throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}())[0],f=i;n("update:selectedValue",f),n("selectedChange",f,u)}},R=function(e){n("nodeClick",e)},N=function(e){n("nodeMouseover",e)},x=function(e,t){if(e)a.hiddenPaths=L(L({},a.hiddenPaths),{},f({},t,1));else{var n=L({},a.hiddenPaths);delete n[t],a.hiddenPaths=n}},P=function(t,r){e.collapsedOnClickBrackets&&x(t,r.path),n("bracketsClick",t,r)},D=function(e,t){x(e,t.path),n("iconClick",e,t)},M=function(t,r){var o=S(e.data),i=e.rootPath;new Function("data","val","data".concat(r.slice(i.length),"=val"))(o,t),n("update:data",o)};return(0,h.watchEffect)(function(){w.value&&function(e){throw new Error("[VueJSONPretty] ".concat(e))}(w.value)}),(0,h.watchEffect)(function(){b.value&&(e.virtual&&e.dynamicHeight&&l.length!==b.value.length&&v(b.value.length),k())}),(0,h.watch)(function(){return[e.dynamicHeight,e.itemHeight,i.value.length]},function(){e.virtual&&e.dynamicHeight&&(v(b.value.length),(0,h.nextTick)(k))}),(0,h.watch)(function(){return e.deep},function(t){t&&(a.hiddenPaths=s(t,e.collapsedNodeLength))}),(0,h.watch)(function(){return e.collapsedNodeLength},function(t){t&&(a.hiddenPaths=s(e.deep,t))}),function(){var t,n,s,l,u,c=null!==(t=e.renderNodeKey)&&void 0!==t?t:r.renderNodeKey,d=null!==(n=e.renderNodeValue)&&void 0!==n?n:r.renderNodeValue,f=null!==(s=null!==(l=e.renderNodeActions)&&void 0!==l?l:r.renderNodeActions)&&void 0!==s&&s,p=null===(u=a.visibleData)||void 0===u?void 0:u.map(function(t,n){var r=a.startIndex+n;return(0,h.createVNode)("div",{key:t.id,ref:function(e){return function(e,t){t?m[e]=t:delete m[e]}(r,e||null)}},[(0,h.createVNode)(I,{data:e.data,rootPath:e.rootPath,indent:e.indent,node:t,collapsed:!!a.hiddenPaths[t.path],theme:e.theme,showDoubleQuotes:e.showDoubleQuotes,showLength:e.showLength,checked:_.value.includes(t.path),selectableType:e.selectableType,showLine:e.showLine,showLineNumber:e.showLineNumber,showSelectController:e.showSelectController,selectOnClickNode:e.selectOnClickNode,nodeSelectable:e.nodeSelectable,highlightSelectedNode:e.highlightSelectedNode,editable:e.editable,editableTrigger:e.editableTrigger,showIcon:e.showIcon,showKeyValueSpace:e.showKeyValueSpace,renderNodeKey:c,renderNodeValue:d,renderNodeActions:f,onNodeClick:R,onNodeMouseover:N,onBracketsClick:P,onIconClick:D,onSelectedChange:A,onValueChange:M,class:e.dynamicHeight?"dynamic-height":void 0,style:e.dynamicHeight?{}:e.itemHeight&&20!==e.itemHeight?{lineHeight:"".concat(e.itemHeight,"px")}:{}},null)])});return(0,h.createVNode)("div",{ref:o,class:{"vjs-tree":!0,"is-virtual":e.virtual,dark:"dark"===e.theme},onScroll:e.virtual?O:void 0,style:e.showLineNumber?L({paddingLeft:"".concat(12*Number(i.value.length.toString().length),"px")},e.style):e.style},[e.virtual?(0,h.createVNode)("div",{class:"vjs-tree-list",style:{height:"".concat(e.height,"px")}},[(0,h.createVNode)("div",{class:"vjs-tree-list-holder",style:{height:"".concat(T.value,"px")}},[(0,h.createVNode)("div",{class:"vjs-tree-list-holder-inner",style:{transform:"translateY(".concat(a.translateY,"px)")}},[p])])]):p])}}});var P=l.A},6262:function(e,t){"use strict";t.A=(e,t)=>{const n=e.__vccOpts||e;for(const[r,o]of t)n[r]=o;return n}},9071:function(e,t,n){"use strict";n.d(t,{A:function(){return f}});var r=n(641),o=n(33),i=n(3751);const s=["href"];function a(e,t,n,a,l,u){return n.name.includes("/")?((0,r.uX)(),(0,r.CE)("a",{key:0,href:e.$router.resolve({query:{p:n.name}}).href,class:(0,o.C4)(["widget-button widget-button--details widget-button--info",{"widget-button--small":n.small,"widget-button--inline":n.inline}]),onClick:t[0]||(t[0]=(0,i.D$)(t=>e.setCurrent(n.name),["prevent"]))},(0,o.v_)(e.$t("ui.discover.detailsButton")),11,s)):(0,r.Q3)("",!0)}var l=n(6278),u={props:{name:{type:String,required:!0},small:Boolean,inline:Boolean},methods:{...(0,l.PY)("packages/details",["setCurrent"])}},c=n(6262);const d=(0,c.A)(u,[["render",a]]);var f=d},1080:function(e,t,n){"use strict";n.d(t,{A:function(){return Be}});var r=n(641),o=n(33),i=n.p+"img/search-by-algolia.72f0ac9a.svg";const s={class:"package-search__title"},a={key:1,class:"package-search__status package-search__status--offline"},l={class:"package-search__title"},u={class:"package-search__explain"},c={key:2,class:"package-search__status package-search__status--empty"},d={key:0,class:"package-search__headline"},f={class:"package-search__results"},h={key:1,class:"package-search__headline"},p={key:2,class:"package-search__results"},m={class:"package-search__more"},v={key:4},g={class:"package-search__headline"},y={class:"package-search__results"},b={class:"package-search__more"},_={class:"package-search__headline"},E={class:"package-search__results"},w={class:"package-search__more"},S={class:"package-search__headline"},T={class:"package-search__results"},k={class:"package-search__more"};function C(e,t,n,C,O,A){const R=(0,r.g2)("search-input"),I=(0,r.g2)("loading-spinner"),N=(0,r.g2)("i18n-t"),L=(0,r.g2)("search-sorting"),x=(0,r.g2)("discover-package"),P=(0,r.g2)("loading-button"),D=(0,r.g2)("ad-banner");return(0,r.uX)(),(0,r.Wv)((0,r.$y)(n.wrapper),null,{search:(0,r.k6)(()=>[(0,r.bF)(R,{placeholder:e.$tc("ui.discover.searchPlaceholder",e.extensionCount),class:"package-search__input"},null,8,["placeholder"])]),default:(0,r.k6)(()=>[!e.searching||e.results||e.exactHit?e.offline||null===e.discover?((0,r.uX)(),(0,r.CE)("div",a,[(0,r.Lk)("p",l,(0,o.v_)(e.$t("ui.discover.offline")),1),(0,r.Lk)("p",u,(0,o.v_)(e.$t("ui.discover.offlineExplain")),1),(0,r.Lk)("button",{class:"widget-button widget-button--inline widget-button--update",onClick:t[0]||(t[0]=(...e)=>A.getOnline&&A.getOnline(...e))},(0,o.v_)(e.$t("ui.discover.offlineButton")),1)])):e.isSearching&&e.results&&!Object.keys(e.results).length&&!e.exactHit?((0,r.uX)(),(0,r.CE)("div",c,[(0,r.bF)(N,{keypath:"ui.discover.empty",tag:"p",class:"package-search__title"},{query:(0,r.k6)(()=>[(0,r.Lk)("i",null,(0,o.v_)(e.query),1)]),_:1})])):e.isSearching?((0,r.uX)(),(0,r.CE)(r.FK,{key:3},[e.query?(0,r.Q3)("",!0):((0,r.uX)(),(0,r.Wv)(L,{key:0})),e.exactHit?((0,r.uX)(),(0,r.CE)(r.FK,{key:1},[A.hasResults?((0,r.uX)(),(0,r.CE)("h2",d,(0,o.v_)(e.$t("ui.discover.exactHit")),1)):(0,r.Q3)("",!0),(0,r.Lk)("div",f,[(0,r.bF)(x,{class:"package-search__item",data:e.exactHit},{hint:(0,r.k6)(()=>[(0,r.RG)(e.$slots,"package-hint",{data:e.exactHit})]),actions:(0,r.k6)(()=>[(0,r.RG)(e.$slots,"package-actions",{data:e.exactHit})]),_:3},8,["data"])]),A.hasResults?((0,r.uX)(),(0,r.CE)("h2",h,(0,o.v_)(e.$t("ui.discover.results")),1)):(0,r.Q3)("",!0)],64)):(0,r.Q3)("",!0),A.hasResults?((0,r.uX)(),(0,r.CE)("div",p,[((0,r.uX)(!0),(0,r.CE)(r.FK,null,(0,r.pI)(e.results,t=>((0,r.uX)(),(0,r.Wv)(x,{class:"package-search__item",data:t,key:t.name},{hint:(0,r.k6)(()=>[(0,r.RG)(e.$slots,"package-hint",{data:t})]),actions:(0,r.k6)(()=>[(0,r.RG)(e.$slots,"package-actions",{data:t})]),_:2},1032,["data"]))),128))])):(0,r.Q3)("",!0),(0,r.Lk)("div",m,[e.hasMore?((0,r.uX)(),(0,r.Wv)(P,{key:0,inline:"",icon:"search",loading:e.searching,onClick:e.loadMore},{default:(0,r.k6)(()=>[(0,r.eW)((0,o.v_)(e.$t("ui.discover.more")),1)]),_:1},8,["loading","onClick"])):(0,r.Q3)("",!0)])],64)):((0,r.uX)(),(0,r.CE)("div",v,[e.discover.ads.length?((0,r.uX)(),(0,r.Wv)(D,{key:0})):(0,r.Q3)("",!0),(0,r.Lk)("h2",g,(0,o.v_)(e.$t("ui.discover.latestPackages")),1),(0,r.Lk)("div",y,[((0,r.uX)(!0),(0,r.CE)(r.FK,null,(0,r.pI)(e.discover.latest,t=>((0,r.uX)(),(0,r.Wv)(x,{class:"package-search__item",data:t,key:t.name},{hint:(0,r.k6)(()=>[(0,r.RG)(e.$slots,"package-hint",{data:t})]),actions:(0,r.k6)(()=>[(0,r.RG)(e.$slots,"package-actions",{data:t})]),_:2},1032,["data"]))),128))]),(0,r.Lk)("div",b,[(0,r.Lk)("button",{class:"package-search__more-button",onClick:t[1]||(t[1]=e=>A.openSearch("latest"))},(0,o.v_)(e.$t("ui.discover.more")),1)]),(0,r.Lk)("h2",_,(0,o.v_)(e.$t("ui.discover.faversPackages")),1),(0,r.Lk)("div",E,[((0,r.uX)(!0),(0,r.CE)(r.FK,null,(0,r.pI)(e.discover.favers,t=>((0,r.uX)(),(0,r.Wv)(x,{class:"package-search__item",data:t,key:t.name},{hint:(0,r.k6)(()=>[(0,r.RG)(e.$slots,"package-hint",{data:t})]),actions:(0,r.k6)(()=>[(0,r.RG)(e.$slots,"package-actions",{data:t})]),_:2},1032,["data"]))),128))]),(0,r.Lk)("div",w,[(0,r.Lk)("button",{class:"package-search__more-button",onClick:t[2]||(t[2]=e=>A.openSearch("favers"))},(0,o.v_)(e.$t("ui.discover.more")),1)]),(0,r.Lk)("h2",S,(0,o.v_)(e.$t("ui.discover.downloadsPackages")),1),(0,r.Lk)("div",T,[((0,r.uX)(!0),(0,r.CE)(r.FK,null,(0,r.pI)(e.discover.downloads,t=>((0,r.uX)(),(0,r.Wv)(x,{class:"package-search__item",data:t,key:t.name},{hint:(0,r.k6)(()=>[(0,r.RG)(e.$slots,"package-hint",{data:t})]),actions:(0,r.k6)(()=>[(0,r.RG)(e.$slots,"package-actions",{data:t})]),_:2},1032,["data"]))),128))]),(0,r.Lk)("div",k,[(0,r.Lk)("button",{class:"package-search__more-button",onClick:t[3]||(t[3]=e=>A.openSearch("downloads"))},(0,o.v_)(e.$t("ui.discover.more")),1)])])):((0,r.uX)(),(0,r.Wv)(I,{key:0,class:"package-search__status package-search__status--loader"},{default:(0,r.k6)(()=>[(0,r.Lk)("p",s,(0,o.v_)(e.$t("ui.discover.loading")),1)]),_:1})),t[4]||(t[4]=(0,r.Lk)("a",{href:"https://www.algolia.com/",target:"_blank",class:"package-search__algolia"},[(0,r.Lk)("img",{src:i,alt:"Algolia | Fast, Reliable and Modern Search and Discovery",width:"200"})],-1))]),_:3})}var O=n(6278),A=n(1881),R=n(6435),I=n(9045),N=n(3751);const L={key:0,class:"ads"},x={class:"container"},P=["href","title","onClick"],D=["src"],M=["href","title"],F=["src"],$={key:0,class:"link"},j={href:"https://contao.org/de/anzeigen-erweiterungsliste.html",target:"_blank"},U={key:1,class:"link"},B={href:"https://contao.org/en/extension-ads.html",target:"_blank"};function V(e,t,n,i,s,a){const l=(0,r.g2)("vueper-slide"),u=(0,r.g2)("vueper-slides");return e.ads&&e.ads.length>1?((0,r.uX)(),(0,r.CE)("div",L,[(0,r.Lk)("div",x,[(0,r.bF)(u,{class:"no-shadow",autoplay:"",infinite:"",duration:1e4,"slide-ratio":1/4,"visible-slides":2,breakpoints:{630:{slideRatio:.5,visibleSlides:1}},bullets:!1,touchable:!1,"arrows-outside":!1},{default:(0,r.k6)(()=>[((0,r.uX)(!0),(0,r.CE)(r.FK,null,(0,r.pI)(e.ads,t=>((0,r.uX)(),(0,r.Wv)(l,{key:t.objectID},{content:(0,r.k6)(()=>[t.package?((0,r.uX)(),(0,r.CE)("a",{key:0,href:e.$router.resolve({query:{p:t.package}}).href,title:t.title,onClick:(0,N.D$)(n=>e.setCurrent(t.package),["prevent"])},[(0,r.Lk)("img",{src:t.image,alt:""},null,8,D)],8,P)):((0,r.uX)(),(0,r.CE)("a",{key:1,href:t.url,title:t.title,target:"_blank",rel:"noreferrer noopener"},[(0,r.Lk)("img",{src:t.image,alt:""},null,8,F)],8,M))]),_:2},1024))),128))]),_:1})]),"de"===e.$i18n.locale?((0,r.uX)(),(0,r.CE)("div",$,[(0,r.Lk)("a",j,(0,o.v_)(e.$t("ui.discover.advertisement")),1)])):((0,r.uX)(),(0,r.CE)("div",U,[(0,r.Lk)("a",B,(0,o.v_)(e.$t("ui.discover.advertisement")),1)]))])):(0,r.Q3)("",!0)}const G=["src"],H=["src"],W=["src"],X=["src"],K=["src"],q={key:2},z={class:"vueperslide__content-wrapper"},Y=["innerHTML"],Q=["innerHTML"],J={class:"vueperslide__content-wrapper"},Z=["innerHTML"],ee=["innerHTML"],te={key:4,class:"vueperslide__loader"};function ne(e,t,n,i,s,a){return(0,r.uX)(),(0,r.Wv)((0,r.$y)(n.link?"a":"div"),{class:(0,o.C4)(["vueperslide",a.slideClasses]),href:!(!n.link||a.justDragged)&&n.link,target:n.link&&n.openInNew?"boolean"==typeof n.openInNew?"_blank":n.openInNew:"_self",face:a.slideFace3d,style:(0,o.Tr)(a.slideStyles),"aria-hidden":a.slides.activeId===e._.uid||a.isSlideVisible?"false":"true",onMouseenter:t[0]||(t[0]=t=>e.$emit("mouse-enter",{slideIndex:a.slideIndex,title:n.title,content:n.content,image:n.image,link:n.link},e.$el)),onMouseleave:t[1]||(t[1]=t=>e.$emit("mouse-leave"))},{default:(0,r.k6)(()=>[a.videoObj?((0,r.uX)(),(0,r.CE)(r.FK,{key:0},[a.videoObj.webm||a.videoObj.mp4?((0,r.uX)(),(0,r.CE)("video",(0,r.v6)({key:0,class:"vueperslide__video",width:"100%",height:"100%"},a.videoObj.props||{}),[a.videoObj.webm?((0,r.uX)(),(0,r.CE)("source",{key:0,src:a.videoObj.webm,type:"video/webm"},null,8,G)):(0,r.Q3)("",!0),a.videoObj.mp4?((0,r.uX)(),(0,r.CE)("source",{key:1,src:a.videoObj.mp4,type:"video/mp4"},null,8,H)):(0,r.Q3)("",!0),a.videoObj.ogv?((0,r.uX)(),(0,r.CE)("source",{key:2,src:a.videoObj.ogv,type:"video/ogg"},null,8,W)):(0,r.Q3)("",!0),a.videoObj.avi?((0,r.uX)(),(0,r.CE)("source",{key:3,src:a.videoObj.avi,type:"video/avi"},null,8,X)):(0,r.Q3)("",!0),(0,r.eW)((0,o.v_)(a.videoObj.alt||"Sorry, your browser doesn't support embedded videos."),1)],16)):a.videoObj.url?((0,r.uX)(),(0,r.CE)("iframe",(0,r.v6)({key:1,class:"vueperslide__video",src:a.videoObj.url,type:"text/html",frameborder:"0",width:"100%",height:"100%"},a.videoObj.props||{}),null,16,K)):(0,r.Q3)("",!0)],64)):(0,r.Q3)("",!0),e.imageSrc&&a.conf.slideImageInside?((0,r.uX)(),(0,r.CE)("div",{key:1,class:"vueperslide__image",style:(0,o.Tr)(a.imageStyles)},null,4)):(0,r.Q3)("",!0),a.conf.slideContentOutside?(0,r.bo)(((0,r.uX)(),(0,r.CE)("div",q,[(0,r.RG)(e.$slots,"content",{},()=>[(0,r.Lk)("div",z,[n.title?((0,r.uX)(),(0,r.CE)("div",{key:0,class:"vueperslide__title",innerHTML:n.title},null,8,Y)):(0,r.Q3)("",!0),n.content?((0,r.uX)(),(0,r.CE)("div",{key:1,class:"vueperslide__content",innerHTML:n.content},null,8,Q)):(0,r.Q3)("",!0)])])],512)),[[N.aG,!1]]):(0,r.RG)(e.$slots,"content",{key:3},()=>[(0,r.Lk)("div",J,[n.title?((0,r.uX)(),(0,r.CE)("div",{key:0,class:"vueperslide__title",innerHTML:n.title},null,8,Z)):(0,r.Q3)("",!0),n.content?((0,r.uX)(),(0,r.CE)("div",{key:1,class:"vueperslide__content",innerHTML:n.content},null,8,ee)):(0,r.Q3)("",!0)])]),a.conf.lazy&&!e.loaded?((0,r.uX)(),(0,r.CE)("div",te,[(0,r.RG)(e.$slots,"loader")])):(0,r.Q3)("",!0)]),_:3},40,["href","target","class","face","style","aria-hidden"])}const re=(e,t)=>{const n=e.__vccOpts||e;for(const[r,o]of t)n[r]=o;return n},oe={inject:["slides","touch","updateSlide","addClone","addSlide","removeSlide"],props:{clone:{type:Boolean},image:{type:String,default:""},video:{type:[String,Object],default:""},title:{type:String,default:""},content:{type:String,default:""},link:{type:String,default:""},duration:{type:Number,default:0},lazyloaded:{type:Boolean},openInNew:{type:[Boolean,String]}},emits:["mouse-enter","mouse-leave"],data:()=>({imageSrc:"",loading:!1,loaded:!1}),computed:{conf(){return this.$parent.conf},slideClasses(){return{"vueperslide--active":this.slides.activeId===this._.uid,"vueperslide--previous-slide":this.isPreviousSlide,"vueperslide--next-slide":this.isNextSlide,"vueperslide--visible":this.isSlideVisible,"vueperslide--loading":this.conf.lazy&&!this.loaded,"vueperslide--has-video":this.videoObj,"vueperslide--has-image-inside":this.conf.slideImageInside,"vueperslide--no-pointer-events":this.videoObj&&!1===this.videoObj.pointerEvents}},slideStyles(){const{visibleSlides:e,fade:t,slideImageInside:n,gap:r,gapPx:o}=this.conf;return{...!n&&this.imageSrc&&{backgroundImage:`url("${this.imageSrc}")`},...e>1&&{width:(100-(r?r*(e-1):0))/e+"%"},...e>1&&t&&{[this.conf.rtl?"right":"left"]:this.slideIndex%e/e*100+"%"},...r&&{[this.conf.rtl?"marginLeft":"marginRight"]:r+(o?"px":"%")}}},videoObj(){if(!this.video)return null;let e={url:"",alt:"",props:{controls:!0}};return"object"==typeof this.video?e=Object.assign(e,this.video):"string"==typeof this.video&&(e.url=this.video),e},youtubeVideo(){return/youtube\.|youtu\.be/.test(this.videoObj.url)},imageStyles(){return{...this.conf.slideImageInside&&this.imageSrc&&{backgroundImage:`url("${this.imageSrc}")`}}},slideFace3d(){if(!this.conf["3d"])return!1;const e=["front","right","back","left"],t=(this.slides.current-1+this.slidesCount)%this.slidesCount,n=(this.slides.current+1)%this.slidesCount;let r="front";return this.slideIndex===t?r=e[(4+this.slides.current-1)%4]:this.slideIndex===n&&(r=e[(this.slides.current+1)%4]),r=e[this.slideIndex%4],this.conf.rtl&&"left"===r?r="right":this.conf.rtl&&"right"===r&&(r="left"),r},isPreviousSlide(){if(!this.conf["3d"])return!1;const e=(this.slides.current-1+this.slidesCount)%this.slidesCount;return this._.uid===this.slides.list[e].id},isNextSlide(){if(!this.conf["3d"])return!1;const e=(this.slides.current+1)%this.slidesCount;return this._.uid===this.slides.list[e].id},isSlideVisible(){return this.slideIndex>=this.slides.firstVisible&&this.slideIndex<this.slides.firstVisible+this.conf.visibleSlides},slidesList(){return this.slides.list.map(e=>e.id)},slidesCount(){return this.slidesList.length},slideIndex(){return this.slidesList.indexOf(this._.uid)},justDragged(){return this.touch.justDragged}},methods:{updateThisSlide(e){this.updateSlide(this._.uid,e)},loadImage(){if(!this.loading&&!this.loaded)return this.loading=!0,new Promise((e,t)=>{const n=document.createElement("img");n.onload=()=>{this.imageSrc=this.image,this.loading=!1,this.loaded=!0,this.$nextTick(()=>{e({image:this.imageSrc,style:((this.$el.attributes||{}).style||{}).value})})},n.onerror=(this.loading=!1)||t,n.src=this.image})},playVideo(){this.videoObj&&(this.videoObj.url?this.$el.querySelector("iframe").contentWindow.postMessage('{"event":"command","func":"playVideo","args":""}',"*"):this.$el.querySelector("video").play())},pauseVideo(){this.videoObj&&(this.videoObj.url?this.$el.querySelector("iframe").contentWindow.postMessage('{"event":"command","func":"pauseVideo","args":""}',"*"):this.$el.querySelector("video").pause())}},created(){if(this.imageSrc=this.conf.lazy?"":this.image,this.clone)return this.addClone();this.addSlide({id:this._.uid,image:this.imageSrc,video:this.videoObj&&{...this.videoObj,play:this.playVideo,pause:this.pauseVideo},title:this.title,content:this.content,contentSlot:this.$slots.content,loaderSlot:this.$slots.loader,link:this.link,style:"",loadImage:this.loadImage,duration:this.duration})},mounted(){this.clone||this.updateThisSlide({contentSlot:this.$slots.content,loaderSlot:this.$slots.loader,style:((this.$el.attributes||{}).style||{}).value})},beforeUnmount(){this.clone||this.removeSlide(this._.uid)},watch:{image(){this.imageSrc=this.conf.lazy&&!this.isSlideVisible?"":this.image,this.clone||this.updateThisSlide({image:this.imageSrc,...!this.conf.slideImageInside&&{style:this.slideStyles}})},title(){this.clone||this.updateThisSlide({title:this.title})},content(){this.clone||this.updateThisSlide({content:this.content})},link(){this.clone||this.updateThisSlide({link:this.link})},lazyloaded(){this.clone&&(this.loaded=this.lazyloaded)}}},ie=re(oe,[["render",ne]]),se=["innerHTML"],ae=["innerHTML"],le={class:"vueperslides__inner"},ue={key:0,class:"vueperslides__paused"},ce={key:1,class:"vueperslides__progress"},de={key:2,class:"vueperslides__fractions"},fe={viewBox:"0 0 9 18"},he=["d"],pe={viewBox:"0 0 9 18"},me=["d"],ve={key:4,class:"vueperslides__bullets",ref:"bullets",role:"tablist","aria-label":"Slideshow navigation"},ge=["aria-label","onClick"],ye={class:"default"},be={key:1,class:"vueperslides__bullets vueperslides__bullets--outside",ref:"bullets",role:"tablist","aria-label":"Slideshow navigation"},_e=["aria-label","onClick"],Ee={class:"default"},we=["innerHTML"],Se=["innerHTML"];function Te(e,t,n,i,s,a){const l=(0,r.g2)("vnodes"),u=(0,r.g2)("vueper-slide");return(0,r.uX)(),(0,r.CE)("div",{class:(0,o.C4)(["vueperslides",a.vueperslidesClasses]),ref:"vueperslides","aria-label":"Slideshow",style:(0,o.Tr)(a.vueperslidesStyles)},[a.slidesCount&&"top"===a.conf.slideContentOutside?((0,r.uX)(),(0,r.CE)("div",{key:0,class:(0,o.C4)(["vueperslide__content-wrapper vueperslide__content-wrapper--outside-top",a.conf.slideContentOutsideClass])},[a.currentSlide.contentSlot?((0,r.uX)(),(0,r.Wv)(l,{key:0,vnodes:a.currentSlide.contentSlot()},null,8,["vnodes"])):((0,r.uX)(),(0,r.CE)(r.FK,{key:1},[a.currentSlide.title?((0,r.uX)(),(0,r.CE)("div",{key:0,class:"vueperslide__title",innerHTML:a.currentSlide.title},null,8,se)):(0,r.Q3)("",!0),a.currentSlide.content?((0,r.uX)(),(0,r.CE)("div",{key:1,class:"vueperslide__content",innerHTML:a.currentSlide.content},null,8,ae)):(0,r.Q3)("",!0)],64))],2)):(0,r.Q3)("",!0),(0,r.Lk)("div",le,[(0,r.Lk)("div",{class:"vueperslides__parallax-wrapper",style:(0,o.Tr)(`padding-bottom: ${100*a.conf.slideRatio}%`),"aria-live":"polite"},[(0,r.Lk)("div",{class:(0,o.C4)(["vueperslides__track",{"vueperslides__track--dragging":e.touch.dragging,"vueperslides__track--mousedown":e.mouseDown}]),ref:"track",style:(0,o.Tr)(a.trackStyles)},[(0,r.Lk)("div",{class:"vueperslides__track-inner",style:(0,o.Tr)(a.trackInnerStyles)},[(0,r.RG)(e.$slots,"default"),e.isReady&&a.conf.infinite&&a.canSlide&&a.lastSlide?((0,r.uX)(),(0,r.Wv)(u,{key:0,class:"vueperslide--clone vueperslide--clone-1",clone:"",title:a.lastSlide.title,content:a.lastSlide.content,image:a.lastSlide.image,link:a.lastSlide.link,style:(0,o.Tr)(a.lastSlide.style),lazyloaded:a.lastSlide.loaded,"aria-hidden":"true"},(0,r.eX)({_:2},[a.lastSlide.contentSlot?{name:"content",fn:(0,r.k6)(()=>[(0,r.bF)(l,{vnodes:a.lastSlide.contentSlot()},null,8,["vnodes"])]),key:"0"}:void 0,a.conf.lazy&&!a.lastSlide.loaded&&a.lastSlide.loaderSlot?{name:"loader",fn:(0,r.k6)(()=>[(0,r.bF)(l,{vnodes:a.lastSlide.loaderSlot()},null,8,["vnodes"])]),key:"1"}:void 0]),1032,["title","content","image","link","style","lazyloaded"])):(0,r.Q3)("",!0),e.isReady&&a.conf.infinite&&a.canSlide&&a.firstSlide?((0,r.uX)(),(0,r.Wv)(u,{key:1,class:"vueperslide--clone vueperslide--clone-2",clone:"",title:a.firstSlide.title,content:a.firstSlide.content,image:a.firstSlide.image,link:a.firstSlide.link,style:(0,o.Tr)(a.firstSlide.style),lazyloaded:a.firstSlide.loaded,"aria-hidden":"true"},(0,r.eX)({_:2},[a.firstSlide.contentSlot?{name:"content",fn:(0,r.k6)(()=>[(0,r.bF)(l,{vnodes:a.firstSlide.contentSlot()},null,8,["vnodes"])]),key:"0"}:void 0,a.conf.lazy&&!a.firstSlide.loaded&&a.firstSlide.loaderSlot?{name:"loader",fn:(0,r.k6)(()=>[(0,r.bF)(l,{vnodes:a.firstSlide.loaderSlot()},null,8,["vnodes"])]),key:"1"}:void 0]),1032,["title","content","image","link","style","lazyloaded"])):(0,r.Q3)("",!0)],4)],6)],4),(a.conf.pauseOnHover||a.conf.pauseOnTouch)&&e.$slots.pause?((0,r.uX)(),(0,r.CE)("div",ue,[(0,r.RG)(e.$slots,"pause")])):(0,r.Q3)("",!0),a.conf.progress?((0,r.uX)(),(0,r.CE)("div",ce,[(0,r.RG)(e.$slots,"progress",{current:e.slides.current+1,total:a.slidesCount},()=>[(0,r.Lk)("div",{style:(0,o.Tr)(`width: ${100*(e.slides.current+1)/a.slidesCount}%`)},null,4)])])):(0,r.Q3)("",!0),a.conf.fractions?((0,r.uX)(),(0,r.CE)("div",de,[(0,r.RG)(e.$slots,"fraction",{current:e.slides.current+1,total:a.slidesCount},()=>[(0,r.eW)((0,o.v_)(`${e.slides.current+1} / ${a.slidesCount}`),1)])])):(0,r.Q3)("",!0),a.conf.arrows&&a.canSlide&&!n.disable?((0,r.uX)(),(0,r.CE)("div",{key:3,class:(0,o.C4)(["vueperslides__arrows",{"vueperslides__arrows--outside":a.conf.arrowsOutside}])},[(0,r.bo)((0,r.Lk)("button",{class:"vueperslides__arrow vueperslides__arrow--prev",type:"button",onClick:t[0]||(t[0]=e=>a.previous()),"aria-label":"Previous",onKeyup:[t[1]||(t[1]=(0,N.jR)(e=>a.conf.rtl?a.next():a.previous(),["left"])),t[2]||(t[2]=(0,N.jR)(e=>a.conf.rtl?a.previous():a.next(),["right"]))]},[(0,r.RG)(e.$slots,"arrow-"+(a.conf.rtl?"right":"left"),{},()=>[((0,r.uX)(),(0,r.CE)("svg",fe,[(0,r.Lk)("path",{"stroke-linecap":"round",d:a.conf.rtl?"m1 1 l7 8 -7 8":"m8 1 l-7 8 7 8"},null,8,he)]))])],544),[[N.aG,!a.arrowPrevDisabled]]),(0,r.bo)((0,r.Lk)("button",{class:"vueperslides__arrow vueperslides__arrow--next",type:"button",onClick:t[3]||(t[3]=e=>a.next()),"aria-label":"Next",onKeyup:[t[4]||(t[4]=(0,N.jR)(e=>a.conf.rtl?a.next():a.previous(),["left"])),t[5]||(t[5]=(0,N.jR)(e=>a.conf.rtl?a.previous():a.next(),["right"]))]},[(0,r.RG)(e.$slots,"arrow-"+(a.conf.rtl?"left":"right"),{},()=>[((0,r.uX)(),(0,r.CE)("svg",pe,[(0,r.Lk)("path",{"stroke-linecap":"round",d:a.conf.rtl?"m8 1 l-7 8 7 8":"m1 1 l7 8 -7 8"},null,8,me)]))])],544),[[N.aG,!a.arrowNextDisabled]])],2)):(0,r.Q3)("",!0),a.conf.bullets&&a.canSlide&&!n.disable&&!a.conf.bulletsOutside?((0,r.uX)(),(0,r.CE)("div",ve,[(0,r.RG)(e.$slots,"bullets",{currentSlide:e.slides.current,bulletIndexes:a.bulletIndexes,goToSlide:a.goToSlide,previous:a.previous,next:a.next},()=>[((0,r.uX)(!0),(0,r.CE)(r.FK,null,(0,r.pI)(a.bulletIndexes,(n,i)=>((0,r.uX)(),(0,r.CE)("button",{class:(0,o.C4)(["vueperslides__bullet",{"vueperslides__bullet--active":e.slides.current===n}]),type:"button",key:i,role:"tab","aria-label":`Slide ${i+1}`,onClick:e=>a.goToSlide(n),onKeyup:[t[6]||(t[6]=(0,N.jR)(e=>a.conf.rtl?a.next():a.previous(),["left"])),t[7]||(t[7]=(0,N.jR)(e=>a.conf.rtl?a.previous():a.next(),["right"]))]},[(0,r.RG)(e.$slots,"bullet",{active:e.slides.current===n,slideIndex:n,index:i+1},()=>[(0,r.Lk)("div",ye,[(0,r.Lk)("span",null,(0,o.v_)(i+1),1)])])],42,ge))),128))])],512)):(0,r.Q3)("",!0)]),a.conf.bullets&&a.canSlide&&!n.disable&&a.conf.bulletsOutside?((0,r.uX)(),(0,r.CE)("div",be,[(0,r.RG)(e.$slots,"bullets",{currentSlide:e.slides.current,bulletIndexes:a.bulletIndexes,goToSlide:a.goToSlide,previous:a.previous,next:a.next},()=>[((0,r.uX)(!0),(0,r.CE)(r.FK,null,(0,r.pI)(a.bulletIndexes,(n,i)=>((0,r.uX)(),(0,r.CE)("button",{class:(0,o.C4)(["vueperslides__bullet",{"vueperslides__bullet--active":e.slides.current===n}]),type:"button",key:i,role:"tab","aria-label":`Slide ${i+1}`,onClick:e=>a.goToSlide(n),onKeyup:[t[8]||(t[8]=(0,N.jR)(e=>a.conf.rtl?a.next():a.previous(),["left"])),t[9]||(t[9]=(0,N.jR)(e=>a.conf.rtl?a.previous():a.next(),["right"]))]},[(0,r.RG)(e.$slots,"bullet",{active:e.slides.current===n,slideIndex:n,index:i+1},()=>[(0,r.Lk)("div",Ee,[(0,r.Lk)("span",null,(0,o.v_)(i+1),1)])])],42,_e))),128))])],512)):(0,r.Q3)("",!0),a.slidesCount&&"bottom"===a.conf.slideContentOutside?((0,r.uX)(),(0,r.CE)("div",{key:2,class:(0,o.C4)(["vueperslide__content-wrapper vueperslide__content-wrapper--outside-bottom",a.conf.slideContentOutsideClass])},[a.currentSlide.contentSlot?((0,r.uX)(),(0,r.Wv)(l,{key:0,vnodes:a.currentSlide.contentSlot()},null,8,["vnodes"])):((0,r.uX)(),(0,r.CE)(r.FK,{key:1},[a.currentSlide.title?((0,r.uX)(),(0,r.CE)("div",{key:0,class:"vueperslide__title",innerHTML:a.currentSlide.title},null,8,we)):(0,r.Q3)("",!0),a.currentSlide.content?((0,r.uX)(),(0,r.CE)("div",{key:1,class:"vueperslide__content",innerHTML:a.currentSlide.content},null,8,Se)):(0,r.Q3)("",!0)],64))],2)):(0,r.Q3)("",!0)],6)}const ke={name:"vueper-slides",components:{VueperSlide:ie,vnodes:{render(){return this.$attrs.vnodes}}},provide(){return{conf:this.conf,slides:this.slides,touch:this.touch,updateSlide:this.updateSlide,addClone:this.addClone,addSlide:this.addSlide,removeSlide:this.removeSlide}},props:{alwaysRefreshClones:{type:Boolean,default:!1},arrows:{type:Boolean,default:!0},arrowsOutside:{type:Boolean,default:null},autoplay:{type:Boolean,default:!1},breakpoints:{type:Object,default:()=>({})},bullets:{type:Boolean,default:!0},bulletsOutside:{type:Boolean,default:null},disable:{type:Boolean,default:!1},disableArrowsOnEdges:{type:[Boolean,String],default:!1},draggingDistance:{type:Number,default:null},duration:{type:[Number,String],default:4e3},infinite:{type:Boolean,default:!0},fade:{type:Boolean,default:!1},fixedHeight:{type:[Boolean,String],default:!1},fractions:{type:Boolean,default:!1},gap:{type:Number,default:0},initSlide:{type:Number,default:1},lazy:{type:Boolean,default:!1},lazyLoadOnDrag:{type:Boolean,default:!1},pauseOnHover:{type:Boolean,default:!0},pauseOnTouch:{type:Boolean,default:!0},parallax:{type:[Boolean,Number],default:!1},pageScrollingElement:{type:String,default:""},parallaxFixedContent:{type:Boolean,default:!1},preventYScroll:{type:Boolean,default:!1},progress:{type:Boolean,default:!1},rtl:{type:Boolean,default:!1},slideContentOutside:{type:[Boolean,String],default:!1},slideContentOutsideClass:{type:String,default:""},slideImageInside:{type:Boolean,default:!1},slideMultiple:{type:[Boolean,Number],default:!1},slideRatio:{type:Number,default:1/3},touchable:{type:Boolean,default:!0},transitionSpeed:{type:[Number,String],default:600},visibleSlides:{type:Number,default:1},"3d":{type:Boolean,default:!1}},emits:["ready","next","previous","autoplay-pause","autoplay-resume","before-slide","slide","image-loaded","image-failed"],data:()=>({isReady:!1,isPaused:!1,container:null,slides:{list:[],activeId:null,current:0,focus:0,firstVisible:0},mouseDown:!1,mouseOver:!1,touch:{enabled:!0,dragging:!1,lazyloadTriggered:!1,justDragged:!1,dragStartX:0,dragNowX:0,dragAmount:0},transition:{currentTranslation:0,speed:0,animated:!1},autoplayTimer:null,nextSlideIsClone:!1,breakpointsData:{list:[],current:null},parallaxData:{translation:0,slideshowOffsetTop:null,isVisible:!1}}),computed:{conf(){const e={...this.$props,...this.$props.breakpoints&&this.$props.breakpoints[this.breakpointsData.current]||{}};return e.slideMultiple=e.slideMultiple?e.visibleSlides:1,e.gap=this.gap&&parseInt(this.gap)||0,e.visibleSlides>1&&(e["3d"]=!1),(e.fade||e.disableArrowsOnEdges||e.visibleSlides>1||e["3d"])&&(e.infinite=!1),e.visibleSlides>1&&null===e.arrowsOutside&&(e.arrowsOutside=!0),e.visibleSlides>1&&null===e.bulletsOutside&&(e.bulletsOutside=!0),this.touch.enabled!==e.touchable&&this.toggleTouchableOption(e.touchable),e.parallax&&e.parallaxFixedContent&&(e.slideContentOutside="top",e.slideContentOutsideClass="parallax-fixed-content"),e},slidesCount(){return this.slides.list.length},gapsCount(){const{fade:e,"3d":t,slideMultiple:n,gap:r}=this.conf;if(!r||e||t||this.multipleSlides1by1&&this.slides.current<this.preferredPosition)return 0;if(!this.slides.current&&this.nextSlideIsClone)return this.slidesCount;if(0===this.nextSlideIsClone)return-1;let o=this.slides.current/n-this.preferredPosition;return this.multipleSlides1by1&&this.slidePosAfterPreferred>0&&(o-=this.slidePosAfterPreferred),o},slidesAfterCurrent(){return this.slidesCount-(this.slides.current+1)},preferredPosition(){return this.multipleSlides1by1?Math.ceil(this.conf.visibleSlides/2)-1:0},slidePosAfterPreferred(){return this.conf.visibleSlides-this.preferredPosition-this.slidesAfterCurrent-1},multipleSlides1by1(){return this.conf.visibleSlides>1&&1===this.conf.slideMultiple},touchEnabled:{get(){return this.slidesCount>1&&this.touch.enabled},set(e){this.touch.enabled=e}},canSlide(){return this.slidesCount/this.conf.visibleSlides>1},firstSlide(){const e=this.slidesCount?this.slides.list[0]:{};return e.style&&"string"==typeof e.style&&(e.style=e.style.replace(/width: ?\d+.*?;?/,"")),e},lastSlide(){const e=this.slidesCount?this.slides.list[this.slidesCount-1]:{};return e.style&&"string"==typeof e.style&&(e.style=e.style.replace(/width: ?\d+.*?;?/,"")),e},currentSlide(){const e=this.slidesCount&&this.slides.list[this.slides.current]||{};return this.slides.current<this.slidesCount&&e.id!==this.slides.activeId&&this.goToSlide(this.slides.current,{animation:!1,autoPlaying:!0}),e},vueperslidesClasses(){return{"vueperslides--ready":this.isReady,"vueperslides--rtl":this.conf.rtl,"vueperslides--fade":this.conf.fade,"vueperslides--parallax":this.conf.parallax,"vueperslides--slide-image-inside":this.conf.slideImageInside,"vueperslides--touchable":this.touchEnabled&&!this.disable,"vueperslides--fixed-height":this.conf.fixedHeight,"vueperslides--3d":this.conf["3d"],"vueperslides--slide-multiple":this.conf.slideMultiple>1,"vueperslides--bullets-outside":this.conf.bulletsOutside,"vueperslides--animated":this.transition.animated,"vueperslides--no-animation":!this.isReady}},vueperslidesStyles(){return/^-?\d/.test(this.conf.fixedHeight)?`height: ${this.conf.fixedHeight}`:null},trackStyles(){const e={};return this.conf.parallax&&(e.transform=`translate3d(0, ${this.parallaxData.translation}%, 0)`,e.willChange=this.parallaxData.isVisible?"transform":"auto"),e},trackInnerStyles(){const e={},{fade:t,"3d":n}=this.conf;if(e.transitionDuration=`${this.transition.speed}ms`,n){const t=90*this.transition.currentTranslation/100;e.transform=`rotateY(-90deg) translateX(-50%) rotateY(90deg) rotateY(${t}deg)`}else t||(e.transform=`translate3d(${this.transition.currentTranslation}%, 0, 0)`,e.willChange=this.touch.dragging||this.transition.animated?"transform":"auto");return e},bulletIndexes(){return Array(Math.ceil(this.slidesCount/this.conf.slideMultiple)).fill().map((e,t)=>t*this.conf.slideMultiple)},arrowPrevDisabled(){return!this.slides.current&&this.conf.disableArrowsOnEdges},arrowNextDisabled(){const{disableArrowsOnEdges:e,visibleSlides:t,slideMultiple:n}=this.conf;return this.slides.current+(n>1&&t>1?t-1:0)===this.slidesCount-1&&e}},methods:{init(){this.container=this.$refs.vueperslides,this.touchEnabled=this.conf.touchable,this.transition.speed=this.conf.transitionSpeed,Object.keys(this.breakpoints).length&&(this.setBreakpointsList(),this.setBreakpointConfig(this.getCurrentBreakpoint()));const e={animation:!1,autoPlaying:this.conf.autoplay};this.goToSlide(this.conf.initSlide-1,e),this.bindEvents(),this.$nextTick(()=>{this.isReady=!0,this.emit("ready")})},emit(e,t=!0,n=!1){let r=null;if((t||"number"==typeof n)&&(r={},t&&this.slides.activeId&&this.slidesCount&&(r.currentSlide=this.getSlideData(this.slides.current)),"number"==typeof n&&this.slidesCount)){const{nextSlide:e}=this.getSlideInRange(n);r.nextSlide=this.getSlideData(e)}this.$emit(...r?[e,r]:[e])},getSlideData(e){const t=this.slides.list[e];let n={};return t&&(n={index:e,title:t.title,content:t.content,contentSlot:t.contentSlot,image:t.image,link:t.link}),n},setBreakpointsList(){this.breakpointsData.list=[99999,...Object.keys(this.breakpoints)].map(e=>parseInt(e)).sort((e,t)=>parseInt(t)-parseInt(e))},getCurrentBreakpoint(){const e=window.innerWidth||document.documentElement.clientWidth||document.body.clientWidth,t=[e,...this.breakpointsData.list].sort((e,t)=>parseInt(t)-parseInt(e));return this.breakpointsData.list[t.indexOf(e)-1]},hasBreakpointChanged(e){return this.breakpointsData.current!==parseInt(e)},setBreakpointConfig(e){const t=this.breakpoints&&this.breakpoints[e]||{},n=t.slideMultiple&&t.slideMultiple!==this.conf.slideMultiple,r=t.visibleSlides&&t.visibleSlides!==this.conf.visibleSlides;this.breakpointsData.current=e,this.slides.current=this.getFirstVisibleSlide(this.slides.focus),n||r?this.goToSlide(this.slides.current,{breakpointChange:!0}):this.updateTrackTranslation()},bindEvents(){const e="ontouchstart"in window;this.touchEnabled&&this.toggleTouchableOption(!0),this.conf.autoplay&&(this.conf.pauseOnHover&&!e?(this.container.addEventListener("mouseenter",this.onMouseEnter),this.container.addEventListener("mouseleave",this.onMouseLeave)):this.conf.pauseOnTouch&&e&&document.addEventListener("touchstart",e=>{this[this.$el.contains(e.target)?"onSlideshowTouch":"onOustideTouch"]()})),(this.breakpointsData.list.length||this.conf.parallax)&&window.addEventListener("resize",this.onResize),this.conf.parallax&&this.enableParallax()},getSlideshowOffsetTop(e=!1){if(null===this.parallaxData.slideshowOffsetTop||e){let e=this.container,t=e.offsetTop;for(;e=e.offsetParent;)t+=e.offsetTop;this.parallaxData.slideshowOffsetTop=t}return this.parallaxData.slideshowOffsetTop},enableParallax(){this.refreshParallax(),this.pageScrollingElement?(this.parallaxData.scrollingEl=document.querySelector(this.pageScrollingElement),this.parallaxData.scrollingEl.addEventListener("scroll",this.onScroll)):document.addEventListener("scroll",this.onScroll)},disableParallax(){(this.pageScrollingElement?document.querySelector(this.pageScrollingElement):document).removeEventListener("scroll",this.onScroll),this.parallaxData.scrollingEl=null,this.parallaxData.isVisible=!1,this.parallaxData.translation=0,this.parallaxData.slideshowOffsetTop=null},onScroll(){const{scrollingEl:e}=this.parallaxData,t=document.documentElement;let n=0;n=e?e.scrollTop:(window.pageYOffset||t.scrollTop)-(t.clientTop||0);const r=window.innerHeight||t.clientHeight||document.body.clientHeight,o=this.container.clientHeight,i=this.getSlideshowOffsetTop(),s=i+o-n,a=r+n-i;if(this.parallaxData.isVisible=s>0&&a>0,this.parallaxData.isVisible){const e=r+o,t=100*s/e,n=-1===this.conf.parallax?100-t:t;this.parallaxData.translation=-n/2}},onResize(){if(this.breakpointsData.list.length){const e=this.getCurrentBreakpoint();this.hasBreakpointChanged(e)&&this.setBreakpointConfig(e)}this.conf.parallax&&this.getSlideshowOffsetTop(!0)},onMouseEnter(){this.mouseOver=!0,this.conf.pauseOnHover&&this.conf.autoplay&&(this.isPaused=!0)},onMouseLeave(){this.mouseOver=!1,this.conf.pauseOnHover&&this.conf.autoplay&&(this.isPaused=!1)},onMouseDown(e){!this.touchEnabled||this.disable||(!e.touches&&this.preventYScroll&&e.preventDefault(),this.mouseDown=!0,this.touch.dragStartX=this.getCurrentMouseX(e),this.conf.draggingDistance||this.updateTrackTranslation(this.touch.dragStartX))},onMouseMove(e){if(this.mouseDown||this.touch.dragging)if(this.conf.autoplay&&(this.isPaused=!0),this.preventYScroll&&e.preventDefault(),this.mouseDown=!1,this.touch.dragging=!0,this.touch.dragNowX=this.getCurrentMouseX(e),this.conf.draggingDistance){this.touch.dragAmount=this.touch.dragNowX-this.touch.dragStartX;const e=this.touch.dragAmount/this.container.clientWidth;this.updateTrackTranslation(),this.transition.currentTranslation+=100*e}else this.updateTrackTranslation(this.touch.dragNowX)},onMouseUp(e){if(this.mouseDown=!1,!this.touch.dragging)return this.cancelSlideChange();this.conf.autoplay&&(("ontouchstart"in window||this.mouseOver)&&this.conf.pauseOnTouch||(this.isPaused=!1)),this.touch.dragging=!1;const t=this.conf.draggingDistance?-this.touch.dragAmount:0,n=(this.touch.dragStartX-this.container.offsetLeft)/this.container.clientWidth,r=(this.touch.dragNowX-this.container.offsetLeft)/this.container.clientWidth,o=100*((n<.5?0:1)-r);let i=(t||o)>0;if(this.conf.rtl&&(i=!i),[Math.abs(t)<this.conf.draggingDistance,!this.conf.draggingDistance&&Math.abs(o)<50,this.arrowPrevDisabled&&!this.slides.current&&!i,this.arrowNextDisabled&&this.slides.current===this.slidesCount-1&&i].includes(!0))this.cancelSlideChange();else{const e=this.slides.current+this.conf.slideMultiple*(i?1:-1);this.emit(i?"next":"previous"),this.goToSlide(e)}this.touch.dragStartX=null,this.touch.dragNowX=null,this.touch.dragAmount=null,this.touch.justDragged=!0,setTimeout(()=>this.touch.justDragged=!1,50),this.touch.lazyloadTriggered=!1},onSlideshowTouch(){this.isPaused=!0},onOustideTouch(){this.isPaused=!1},justDragged(){return this.touch.justDragged},cancelSlideChange(){this.conf.fade||this.updateTrackTranslation()},getCurrentMouseX(e){return"ontouchstart"in window?e.touches[0].clientX:e.clientX},getBasicTranslation(){return this.slides.current/this.conf.visibleSlides},updateTrackTranslation(e=null){let t=this.getBasicTranslation();const{infinite:n,visibleSlides:r,slideMultiple:o,gap:i,"3d":s,lazy:a,lazyLoadOnDrag:l}=this.conf;if(n&&!1!==this.nextSlideIsClone&&(t=(this.nextSlideIsClone?this.slidesCount:-1)/r),i&&(t+=this.gapsCount/(r/o)*i/100),this.touch.dragStartX&&e&&(!n||!1===this.nextSlideIsClone)){let o=0;const i=(this.touch.dragStartX-this.container.offsetLeft)/this.container.clientWidth;let u=(e-this.container.offsetLeft)/this.container.clientWidth;if(s){const e=Math.round(i)?[0,2]:[-1,1];u=Math.min(Math.max(u,e[0]),e[1])}if(o=(i<.5?0:1)-u,t+=o*(this.conf.rtl?-1:1),a&&l&&!this.touch.lazyloadTriggered){this.touch.lazyloadTriggered=!0;let e=this.slides.current+(o>0?1:-1)*r;n&&-1===e?e=this.slidesCount-1:n&&e===this.slidesCount&&(e=0);for(let t=0;t<r;t++){const n=this.slides.list[e+t];n&&!n.loaded&&this.loadSlide(n,e+t)}}}if(this.multipleSlides1by1&&!n){const e=this.slidePosAfterPreferred>0;let n=Math.min(this.preferredPosition,this.slides.current);e&&(n+=this.slidePosAfterPreferred),t-=n/r}this.transition.currentTranslation=100*-t*(this.conf.rtl?-1:1)},pauseAutoplay(){this.isPaused=!0,clearTimeout(this.autoplayTimer),this.autoplayTimer=0,this.emit("autoplay-pause")},resumeAutoplay(){this.isPaused=!1,this.doAutoplay(),this.emit("autoplay-resume")},doAutoplay(){clearTimeout(this.autoplayTimer),this.autoplayTimer=setTimeout(()=>{this.goToSlide(this.slides.current+this.conf.slideMultiple,{autoPlaying:!0})},this.currentSlide.duration||this.conf.duration)},previous(e=!0){e&&this.emit("previous"),this.goToSlide(this.slides.current-this.conf.slideMultiple)},next(e=!0){e&&this.emit("next"),this.goToSlide(this.slides.current+this.conf.slideMultiple)},refreshParallax(){setTimeout(()=>{this.onResize(),this.onScroll()},100)},getFirstVisibleSlide(e){const{slideMultiple:t,visibleSlides:n}=this.conf;let r=this.slides.current;return n>1&&t===n?r=Math.floor(e/n)*n:this.multipleSlides1by1&&(r=e-Math.min(e,this.preferredPosition)-Math.max(this.slidePosAfterPreferred,0)),r},getSlideInRange(e,t){let n=!1;this.conf.infinite&&-1===e?n=0:this.conf.infinite&&e===this.slidesCount&&(n=1);let r=(e+this.slidesCount)%this.slidesCount;if(this.conf.slideMultiple>1){const t=this.slidesCount%this.conf.slideMultiple||this.conf.slideMultiple,n=this.conf.slideMultiple-t;r+=e<0?n:0,r=this.getFirstVisibleSlide(r)}return this.conf.disableArrowsOnEdges&&(e<0||e>this.slidesCount-1)&&!t&&(r=this.slides.current),{nextSlide:r,clone:n}},goToSlide(e,{animation:t=!0,autoPlaying:n=!1,jumping:r=!1,breakpointChange:o=!1,emit:i=!0}={}){if(!this.slidesCount||this.disable)return;this.conf.autoplay&&!n&&!this.isPaused&&(this.isPaused=!0,this.$nextTick(()=>this.isPaused=!1)),this.transition.animated=t,setTimeout(()=>this.transition.animated=!1,this.transitionSpeed);const{nextSlide:s,clone:a}=this.getSlideInRange(e,n);if(this.nextSlideIsClone=a,!this.slides.list[s])return;if(this.conf.lazy)for(let u=0;u<this.conf.visibleSlides;u++){const e=this.slides.list[s+u];e&&!e.loaded&&this.loadSlide(e,s+u)}this.isReady&&!r&&i&&this.emit("before-slide",!0,s);const l=this.slides.list[s];if(this.isReady&&l.video){const e=this.slides.list[this.slides.current];e.video&&e.video.pause(),l.video.play()}if(!1!==a&&setTimeout(()=>{const t=-1===e&&this.slides.current!==this.slidesCount-1,n=e===this.slidesCount&&0!==this.slides.current;t||n||(this.transition.speed=0,this.goToSlide(a?0:this.slidesCount-1,{animation:!1,jumping:!0}),setTimeout(()=>this.transition.speed=this.conf.transitionSpeed,50))},this.transition.speed-50),this.slides.current=s,this.slides.firstVisible=this.getFirstVisibleSlide(s),o||(this.slides.focus=s),this.conf.fade||this.updateTrackTranslation(),this.slides.activeId=this.slides.list[this.slides.current].id,this.conf.autoplay&&n&&!this.isPaused&&this.doAutoplay(),this.slidesCount&&(this.isReady&&!r&&i&&this.emit("slide"),this.isReady&&this.conf.bullets&&!n&&!r&&this.$refs.bullets)){const e=this.$refs.bullets.children,t=e&&e[this.slides.current/this.conf.slideMultiple];if(t&&"button"===t.nodeName.toLowerCase()){let e=document.documentElement;this.pageScrollingElement&&(e=document.querySelector(this.pageScrollingElement));const n=e.scrollTop;t.focus({preventScroll:!0}),e.scrollTop=n}}},addSlide(e){return this.slides.list.push(e),this.isReady&&1===this.slidesCount&&this.conf.autoplay&&this.isPaused&&(this.isPaused=!1),this.slidesCount},addClone(){return this.updateTrackTranslation(),this.slidesCount},updateSlide(e,t){let n=this.slides.list.find(t=>t.id===e);n&&(n=Object.assign(n,t))},removeSlide(e){const t=this.slides.list.findIndex(t=>t.id===e);t>-1&&(this.slides.list.splice(t,1),this.slidesCount&&e===this.slides.activeId&&this.goToSlide(t-1,{autoPlaying:!0})),this.slides.current>=this.slidesCount&&this.goToSlide(0,{autoPlaying:!0})},loadSlide(e,t){e.loadImage().then(n=>{const{image:r,style:o}=n;e.loaded=!0,e.image=r,e.style=o,this.$emit("image-loaded",this.getSlideData(t))},()=>{e.loaded=!1,this.$emit("image-failed",this.getSlideData(t))})},toggleTouchableOption(e){const{track:t}=this.$refs;if(!t)return;this.touchEnabled=e;const n="ontouchstart"in window;e?(this.$refs.track.addEventListener(n?"touchstart":"mousedown",this.onMouseDown,{passive:!this.preventYScroll}),document.addEventListener(n?"touchmove":"mousemove",this.onMouseMove,{passive:!this.preventYScroll}),document.addEventListener(n?"touchend":"mouseup",this.onMouseUp,{passive:!0})):this.removeEventListeners()},removeEventListeners(){const e="ontouchstart"in window;this.$refs.track.removeEventListener(e?"touchstart":"mousedown",this.onMouseDown,{passive:!this.preventYScroll}),document.removeEventListener(e?"touchmove":"mousemove",this.onMouseMove,{passive:!this.preventYScroll}),document.removeEventListener(e?"touchend":"mouseup",this.onMouseUp,{passive:!0})}},watch:{isPaused(e){this[e?"pauseAutoplay":"resumeAutoplay"]()},parallax(e){this[e?"enableParallax":"disableParallax"]()}},mounted(){this.init()},beforeUnmount(){this.removeEventListeners(),this.conf.parallax&&this.disableParallax(),window.removeEventListener("resize",this.onResize),document.removeEventListener("touchstart",e=>{this[this.$el.contains(e.target)?"onSlideshowTouch":"onOustideTouch"]()}),this.container.removeEventListener("mouseenter",this.onMouseEnter),this.container.removeEventListener("mouseleave",this.onMouseLeave)}},Ce=re(ke,[["render",Te]]);var Oe={components:{VueperSlides:Ce,VueperSlide:ie},computed:{...(0,O.aH)("algolia",["ads"])},methods:{...(0,O.PY)("packages/details",["setCurrent"])}},Ae=n(6262);const Re=(0,Ae.A)(Oe,[["render",V]]);var Ie=Re;const Ne={class:"package-sorting__label"},Le=["title","onClick"];function xe(e,t,n,i,s,a){return(0,r.uX)(),(0,r.CE)("section",{class:"package-sorting",onClick:t[0]||(t[0]=t=>e.open=!e.open)},[(0,r.Lk)("label",Ne,(0,o.v_)(e.$t("ui.discover.sortBy")),1),(0,r.Lk)("ul",{class:(0,o.C4)(["package-sorting__group",{"package-sorting__group--open":e.open}])},[((0,r.uX)(!0),(0,r.CE)(r.FK,null,(0,r.pI)(e.sortOptions,(t,n)=>((0,r.uX)(),(0,r.CE)("li",{key:t,class:(0,o.C4)(["package-sorting__item",{"package-sorting__item--active":e.sorting===t,"package-sorting__item--open":e.open}])},[(0,r.Lk)("button",{title:e.$t(`ui.discover.sort${n}Title`),onClick:n=>e.sortBy(t)},(0,o.v_)(e.$t(`ui.discover.sort${n}`)),9,Le)],2))),128))],2)])}var Pe={mixins:[A.A],data:()=>({open:!1,sortOptions:{Released:"released",Latest:"latest",Favers:"favers",Downloads:"downloads"}})};const De=(0,Ae.A)(Pe,[["render",xe]]);var Me=De,Fe=n(791),$e=n(5506),je={mixins:[A.A],components:{LoadingButton:$e.A,SearchInput:Fe.A,SearchSorting:Me,AdBanner:Ie,LoadingSpinner:I.A,DiscoverPackage:R.A},props:{wrapper:{required:!0},hideThemes:{type:Boolean,default:!1}},data:()=>({offline:!1,searching:!1,extensionCount:0,results:null,hasMore:!1,exactHit:null}),computed:{...(0,O.aH)("algolia",["discover"]),hasResults:e=>e.results&&Object.keys(e.results).length},methods:{...(0,O.PY)("packages/details",["setCurrent"]),async searchPackages(){this.searching=!0,this.offline=!1;try{const e={hitsPerPage:10*this.pages};this.hideThemes&&(e.facetFilters=["type:-contao-theme"]),this.query?e.query=this.query:this.sorting&&(e.sorting=this.sorting);const t=await this.$store.dispatch("algolia/findPackages",e);if(this.hasMore=t.nbPages>1,0===t.nbHits)return this.results={},void(this.exactHit=null);const n={};t.hits.forEach(t=>{e.query===t.name?this.exactHit=t:n[t.name]=t}),this.results=n}catch(e){this.offline=!0}this.searching=!1},async getOnline(){this.searching=!0,this.offline=!1,await this.$store.dispatch("algolia/discover"),this.searching=!1},async openSearch(e){this.results=null,this.exactHit=null,await this.sortBy(e)}},watch:{sorting(){this.searchPackages()},query(){this.results=null,this.exactHit=null,this.searchPackages()},pages(){this.searchPackages()}},created(){this.$watch(this.$i18n.locale,()=>{this.isSearching&&this.searchPackages()})},async mounted(){const e={hitsPerPage:0,attributesToRetrieve:null,attributesToHighlight:null,analytics:!1};this.hideThemes&&(e.facetFilters=["type:-contao-theme"]),this.$store.dispatch("algolia/findPackages",e).then(e=>{this.extensionCount=e.nbHits},()=>{}),this.isSearching&&this.searchPackages()}};const Ue=(0,Ae.A)(je,[["render",C]]);var Be=Ue},6435:function(e,t,n){"use strict";n.d(t,{A:function(){return A}});var r=n(641),o=n(33);const i={key:0,class:"discover-package__hint"},s={class:"discover-package__inside"},a=["title"],l={class:"discover-package__details"},u={class:"discover-package__headline-container"},c=["title"],d=["title"],f={class:"discover-package__more"},h={class:"discover-package__counts"},p=["title"],m={key:1,class:"discover-package__count discover-package__count--updated"},v={key:2,class:"discover-package__count discover-package__count--downloads"},g={key:3,class:"discover-package__count discover-package__count--favers"},y={class:"discover-package__actions"};function b(e,t,n,b,_,E){const w=(0,r.g2)("package-logo"),S=(0,r.g2)("details-button");return(0,r.uX)(),(0,r.CE)("article",{class:(0,o.C4)(["discover-package",n.hint||!E.slotEmpty(e.$slots.hint)?"is--hint":""])},[n.hint||!E.slotEmpty(e.$slots.hint)?((0,r.uX)(),(0,r.CE)("div",i,[(0,r.RG)(e.$slots,"hint",{},()=>[(0,r.eW)((0,o.v_)(n.hint),1)])])):(0,r.Q3)("",!0),(0,r.Lk)("div",s,[n.data.abandoned?((0,r.uX)(),(0,r.CE)("div",{key:0,class:"discover-package__abandoned",title:E.abandonedText},(0,o.v_)(e.$t("ui.package.abandoned")),9,a)):(0,r.Q3)("",!0),(0,r.bF)(w,{class:(0,o.C4)(["discover-package__icon",{"discover-package__icon--fallback":!n.data.logo}]),src:n.data.logo},null,8,["class","src"]),(0,r.Lk)("div",l,[(0,r.Lk)("div",u,[n.data.contaoVersions?((0,r.uX)(),(0,r.CE)("ul",{key:0,class:(0,o.C4)(["discover-package__versions",{"discover-package__versions--fallback":!n.data.logo}]),title:`${e.$t("ui.package.contaoVersion")} ${n.data.contaoVersions.join(", ")}`},[((0,r.uX)(!0),(0,r.CE)(r.FK,null,(0,r.pI)(n.data.contaoVersions,(e,t)=>((0,r.uX)(),(0,r.CE)("li",{class:"discover-package__version",key:t},(0,o.v_)(e),1))),128))],10,c)):(0,r.Q3)("",!0),(0,r.Lk)("h1",{class:(0,o.C4)(["discover-package__headline",{"discover-package__headline--fallback":!n.data.logo}]),title:n.data.name!==n.data.title?n.data.name:""},[((0,r.uX)(!0),(0,r.CE)(r.FK,null,(0,r.pI)(E.title.split("%%"),(e,t)=>((0,r.uX)(),(0,r.CE)(r.FK,null,[t%2?((0,r.uX)(),(0,r.CE)("em",{key:t},(0,o.v_)(e),1)):((0,r.uX)(),(0,r.CE)(r.FK,{key:1},[(0,r.eW)((0,o.v_)(e),1)],64))],64))),256))],10,d)]),(0,r.Lk)("p",{class:(0,o.C4)(["discover-package__description",{"discover-package__description--fallback":!n.data.logo}])},[((0,r.uX)(!0),(0,r.CE)(r.FK,null,(0,r.pI)(E.description.split("%%"),(e,t)=>((0,r.uX)(),(0,r.CE)(r.FK,null,[t%2?((0,r.uX)(),(0,r.CE)("em",{key:t},(0,o.v_)(e),1)):((0,r.uX)(),(0,r.CE)(r.FK,{key:1},[(0,r.eW)((0,o.v_)(e),1)],64))],64))),256))],2),(0,r.Lk)("div",f,[(0,r.Lk)("p",h,[n.data.private?((0,r.uX)(),(0,r.CE)("span",{key:0,class:"discover-package__count discover-package__count--private",title:e.$t("ui.package.privateTitle")},(0,o.v_)(e.$t("ui.package.private")),9,p)):(0,r.Q3)("",!0),n.data.updated?((0,r.uX)(),(0,r.CE)("span",m,(0,o.v_)(E.datimFormat(n.data.updated,!1,"short")),1)):(0,r.Q3)("",!0),n.data.downloads?((0,r.uX)(),(0,r.CE)("span",v,(0,o.v_)(E.numberFormat(n.data.downloads)),1)):(0,r.Q3)("",!0),n.data.favers?((0,r.uX)(),(0,r.CE)("span",g,(0,o.v_)(E.numberFormat(n.data.favers)),1)):(0,r.Q3)("",!0)]),(0,r.Lk)("div",y,[(0,r.bF)(S,{small:"",name:n.data.name},null,8,["name"]),(0,r.RG)(e.$slots,"actions")])])])])],2)}var _=n(4210),E=n(266),w=n(9451),S=n(7423),T=n(9071),k={components:{PackageLogo:S.A,DetailsButton:T.A},props:{data:Object,hint:String},computed:{title:e=>e.data._highlightResult?.title?.value||e.data.title||e.data.name,description:e=>e.data._highlightResult?.description?.value||e.data.description||"",abandonedText:e=>!0===e.data.abandoned?e.$t("ui.package.abandonedText"):e.$t("ui.package.abandonedReplace",{replacement:e.data.abandoned})},methods:{datimFormat:_.A,numberFormat:E.A,slotEmpty:w.A}},C=n(6262);const O=(0,C.A)(k,[["render",b]]);var A=O},8823:function(e,t,n){"use strict";n.d(t,{A:function(){return h}});var r=n(641),o=n(33),i=n(3751);const s={class:"footer-languages"},a=["title"];function l(e,t,n,l,u,c){const d=(0,r.g2)("link-menu");return(0,r.uX)(),(0,r.CE)("div",s,[(0,r.Lk)("button",{class:"footer-languages__toggle",title:e.$t("ui.app.language"),onClick:t[0]||(t[0]=(...e)=>c.toggle&&c.toggle(...e))},(0,o.v_)(n.locales[n.current]),9,a),(0,r.bo)((0,r.bF)(d,{ref:"menu",class:"footer-languages__menu",color:"contao",valign:"top",tabindex:"-1",items:c.languageOptions,onFocusout:c.close,onClick:c.close},null,8,["items","onFocusout","onClick"]),[[i.aG,e.visible]])])}var u=n(4758),c={components:{LinkMenu:u.A},emits:["change"],props:{display:String,locales:Object,current:String},data:()=>({visible:!1}),computed:{languageOptions(){return Object.keys(this.locales).map(e=>({label:this.locales[e],active:e===this.current,action:()=>this.$emit("change",e)}))}},methods:{open(){this.visible=!0,setTimeout(()=>this.$refs.menu?.focus(),0)},close(e){e&&this.$refs.menu?.contains(e.relatedTarget)||(this.$refs.menu.blur(),setTimeout(()=>{this.visible=!1},100))},toggle(){this.visible?this.close():this.open()}}},d=n(6262);const f=(0,d.A)(c,[["render",l]]);var h=f},4758:function(e,t,n){"use strict";n.d(t,{A:function(){return d}});var r=n(641),o=n(33);const i=["href","target","onClick"],s=["onClick"];function a(e,t,n,a,l,u){return(0,r.uX)(),(0,r.CE)("ul",{ref:"menu",class:(0,o.C4)(u.cssClass)},[((0,r.uX)(!0),(0,r.CE)(r.FK,null,(0,r.pI)(n.items,(e,t)=>((0,r.uX)(),(0,r.CE)("li",{key:t,class:"link-menu__item"},[e.href?((0,r.uX)(),(0,r.CE)("a",{key:0,class:(0,o.C4)(["link-menu__action",{"link-menu__action--active":e.active}]),href:e.href,target:e.target,onClick:t=>u.click(t,e)},(0,o.v_)(e.label),11,i)):((0,r.uX)(),(0,r.CE)("button",{key:1,class:(0,o.C4)(["link-menu__action",{"link-menu__action--active":e.active}]),onClick:t=>u.click(t,e)},(0,o.v_)(e.label),11,s))]))),128))],2)}var l={props:{items:{type:Array,required:!0},color:String,align:String,valign:String},computed:{cssClass:e=>({"link-menu":!0,[`link-menu--${e.color}`]:!!e.color,[`link-menu--align-${e.align}`]:!!e.align,[`link-menu--valign-${e.valign}`]:!!e.valign})},methods:{focus(){this.$refs.menu?.focus()},blur(){this.$refs.menu?.blur()},contains(e){return this.$refs.menu.contains(e)},click(e,t){t.action&&(e.preventDefault(),t.action(t))}}},u=n(6262);const c=(0,u.A)(l,[["render",a]]);var d=c},5506:function(e,t,n){"use strict";n.d(t,{A:function(){return d}});var r=n(641),o=n(33),i=n(3751);function s(e,t,n,s,a,l){const u=(0,r.g2)("loading-spinner");return(0,r.uX)(),(0,r.Wv)((0,r.$y)(l.link?"a":"button"),{type:l.link?null:n.submit?"submit":"button",href:l.link,class:(0,o.C4)(l.buttonClass),disabled:n.disabled||n.loading,onClick:l.click,onMouseover:t[0]||(t[0]=t=>e.$emit("mouseover",t)),onMouseout:t[1]||(t[1]=t=>e.$emit("mouseout",t))},{default:(0,r.k6)(()=>[(0,r.Lk)("span",{class:(0,o.C4)(l.slotClass)},[(0,r.RG)(e.$slots,"default")],2),(0,r.bo)((0,r.bF)(u,null,null,512),[[i.aG,n.loading]])]),_:3},40,["type","href","class","disabled","onClick"])}var a=n(9045),l={components:{LoadingSpinner:a.A},emits:["click","mouseover","mouseout"],props:{href:String,to:[String,Object],color:String,icon:String,inline:Boolean,small:Boolean,loading:Boolean,disabled:Boolean,submit:Boolean},computed:{buttonClass:e=>({"loading-button":!0,"widget-button":!0,"widget-button--inline":e.inline,"widget-button--small":e.small,[`widget-button--${e.color}`]:e.color,disabled:e.link&&(e.loading||e.disabled)}),slotClass:e=>({loading:e.loading,[`widget-button--${e.icon}`]:e.icon}),link:e=>e.href||e.to&&e.$router.resolve(e.to).href||null},methods:{click(e){this.submit||this.link||(e.preventDefault(),this.$emit("click",e))}}},u=n(6262);const c=(0,u.A)(l,[["render",s]]);var d=c},9045:function(e,t,n){"use strict";n.d(t,{A:function(){return u}});var r=n(641),o=n(3751);function i(e,t,n,i,s,a){return n.horizontal?((0,r.uX)(),(0,r.CE)("div",{key:0,class:"loader",onTransitionend:t[0]||(t[0]=(0,o.D$)(()=>{},["stop"]))},[t[2]||(t[2]=(0,r.Fv)('<div class="loader__item loader__item--20"></div><div class="loader__item loader__item--40"></div><div class="loader__item loader__item--60"></div><div class="loader__item loader__item--80"></div><div class="loader__item loader__item--100"></div>',5)),(0,r.RG)(e.$slots,"default")],32)):((0,r.uX)(),(0,r.CE)("div",{key:1,class:"loader",onTransitionend:t[1]||(t[1]=(0,o.D$)(()=>{},["stop"]))},[t[3]||(t[3]=(0,r.Fv)('<div class="sk-circle"><div class="sk-circle1 sk-child"></div><div class="sk-circle2 sk-child"></div><div class="sk-circle3 sk-child"></div><div class="sk-circle4 sk-child"></div><div class="sk-circle5 sk-child"></div><div class="sk-circle6 sk-child"></div><div class="sk-circle7 sk-child"></div><div class="sk-circle8 sk-child"></div><div class="sk-circle9 sk-child"></div><div class="sk-circle10 sk-child"></div><div class="sk-circle11 sk-child"></div><div class="sk-circle12 sk-child"></div></div>',1)),(0,r.RG)(e.$slots,"default")],32))}var s={props:{horizontal:Boolean}},a=n(6262);const l=(0,a.A)(s,[["render",i]]);var u=l},7423:function(e,t,n){"use strict";n.d(t,{A:function(){return d}});var r=n(641),o=n(33);const i=["src"],s={key:1,xmlns:"http://www.w3.org/2000/svg",viewBox:"2 2 20 20"};function a(e,t,n,a,l,u){return(0,r.uX)(),(0,r.CE)("div",null,[(0,r.Lk)("figure",{class:(0,o.C4)(u.computedClass)},[n.src?((0,r.uX)(),(0,r.CE)("img",{key:0,src:n.src,loading:"lazy",alt:""},null,8,i)):((0,r.uX)(),(0,r.CE)("svg",s,[...t[0]||(t[0]=[(0,r.Lk)("path",{d:"M4 4h7V2H4a2 2 0 0 0-2 2v7h2V4zm6 9-4 5h12l-3-4-2 2.7-3-3.7zm7-4.5a1.5 1.5 0 1 0-3 0 1.5 1.5 0 0 0 3 0zM20 2h-7v2h7v7h2V4a2 2 0 0 0-2-2zm0 18h-7v2h7a2 2 0 0 0 2-2v-7h-2v7zM4 13H2v7c0 1.1.9 2 2 2h7v-2H4v-7z"},null,-1)])]))],2)])}var l={props:{src:String,componentClass:String},computed:{computedClass:e=>({"package-logo--fallback":!e.src,[e.componentClass]:!!e.componentClass,[`${e.componentClass}--fallback`]:!!e.componentClass&&!e.src})}},u=n(6262);const c=(0,u.A)(l,[["render",a],["__scopeId","data-v-9c1c5f6c"]]);var d=c},1687:function(e,t,n){"use strict";n.d(t,{A:function(){return ye}});var r=n(641),o=n(33),i=n(3751);const s={class:"popup-overlay__content"},a={key:1,class:"popup-overlay__actions"};function l(e,t,n,l,u,c){const d=(0,r.g2)("focus-trap");return(0,r.uX)(),(0,r.Wv)(d,{active:!0,"fallback-focus":".popup-overlay__popup","escape-deactivates":!0,onDeactivate:t[2]||(t[2]=e=>c.clearCurrent())},{default:(0,r.k6)(()=>[(0,r.Lk)("div",{class:"popup-overlay",onClick:t[1]||(t[1]=(...e)=>c.clearCurrent&&c.clearCurrent(...e))},[(0,r.Lk)("div",{ref:"popup",class:(0,o.C4)(["popup-overlay__popup",{[n.popupClass]:!!n.popupClass}]),tabindex:"-1"},[(0,r.RG)(e.$slots,"content",{},()=>[(0,r.Lk)("form",{onSubmit:t[0]||(t[0]=(0,i.D$)(t=>e.$emit("submit"),["prevent"]))},[n.headline||e.$slots.headline?(0,r.RG)(e.$slots,"headline",{key:0},()=>[(0,r.Lk)("h1",{class:(0,o.C4)(["popup-overlay__headline",{[`popup-overlay__headline--${n.headlineType}`]:!!n.headlineType}])},(0,o.v_)(n.headline),3)]):(0,r.Q3)("",!0),(0,r.Lk)("div",s,[(0,r.RG)(e.$slots,"default")]),e.$slots.actions?((0,r.uX)(),(0,r.CE)("div",a,[(0,r.RG)(e.$slots,"actions")])):(0,r.Q3)("",!0)],32)])],2)])]),_:3})}var u=n(953),c=["input:not([inert]):not([inert] *)","select:not([inert]):not([inert] *)","textarea:not([inert]):not([inert] *)","a[href]:not([inert]):not([inert] *)","button:not([inert]):not([inert] *)","[tabindex]:not(slot):not([inert]):not([inert] *)","audio[controls]:not([inert]):not([inert] *)","video[controls]:not([inert]):not([inert] *)",'[contenteditable]:not([contenteditable="false"]):not([inert]):not([inert] *)',"details>summary:first-of-type:not([inert]):not([inert] *)","details:not([inert]):not([inert] *)"],d=c.join(","),f="undefined"===typeof Element,h=f?function(){}:Element.prototype.matches||Element.prototype.msMatchesSelector||Element.prototype.webkitMatchesSelector,p=!f&&Element.prototype.getRootNode?function(e){var t;return null===e||void 0===e||null===(t=e.getRootNode)||void 0===t?void 0:t.call(e)}:function(e){return null===e||void 0===e?void 0:e.ownerDocument},m=function(e,t){var n;void 0===t&&(t=!0);var r=null===e||void 0===e||null===(n=e.getAttribute)||void 0===n?void 0:n.call(e,"inert"),o=""===r||"true"===r,i=o||t&&e&&("function"===typeof e.closest?e.closest("[inert]"):m(e.parentNode));return i},v=function(e){var t,n=null===e||void 0===e||null===(t=e.getAttribute)||void 0===t?void 0:t.call(e,"contenteditable");return""===n||"true"===n},g=function(e,t,n){if(m(e))return[];var r=Array.prototype.slice.apply(e.querySelectorAll(d));return t&&h.call(e,d)&&r.unshift(e),r=r.filter(n),r},y=function(e,t,n){var r=[],o=Array.from(e);while(o.length){var i=o.shift();if(!m(i,!1))if("SLOT"===i.tagName){var s=i.assignedElements(),a=s.length?s:i.children,l=y(a,!0,n);n.flatten?r.push.apply(r,l):r.push({scopeParent:i,candidates:l})}else{var u=h.call(i,d);u&&n.filter(i)&&(t||!e.includes(i))&&r.push(i);var c=i.shadowRoot||"function"===typeof n.getShadowRoot&&n.getShadowRoot(i),f=!m(c,!1)&&(!n.shadowRootFilter||n.shadowRootFilter(i));if(c&&f){var p=y(!0===c?i.children:c.children,!0,n);n.flatten?r.push.apply(r,p):r.push({scopeParent:i,candidates:p})}else o.unshift.apply(o,i.children)}}return r},b=function(e){return!isNaN(parseInt(e.getAttribute("tabindex"),10))},_=function(e){if(!e)throw new Error("No node provided");return e.tabIndex<0&&(/^(AUDIO|VIDEO|DETAILS)$/.test(e.tagName)||v(e))&&!b(e)?0:e.tabIndex},E=function(e,t){var n=_(e);return n<0&&t&&!b(e)?0:n},w=function(e,t){return e.tabIndex===t.tabIndex?e.documentOrder-t.documentOrder:e.tabIndex-t.tabIndex},S=function(e){return"INPUT"===e.tagName},T=function(e){return S(e)&&"hidden"===e.type},k=function(e){var t="DETAILS"===e.tagName&&Array.prototype.slice.apply(e.children).some(function(e){return"SUMMARY"===e.tagName});return t},C=function(e,t){for(var n=0;n<e.length;n++)if(e[n].checked&&e[n].form===t)return e[n]},O=function(e){if(!e.name)return!0;var t,n=e.form||p(e),r=function(e){return n.querySelectorAll('input[type="radio"][name="'+e+'"]')};if("undefined"!==typeof window&&"undefined"!==typeof window.CSS&&"function"===typeof window.CSS.escape)t=r(window.CSS.escape(e.name));else try{t=r(e.name)}catch(i){return console.error("Looks like you have a radio button with a name attribute containing invalid CSS selector characters and need the CSS.escape polyfill: %s",i.message),!1}var o=C(t,e.form);return!o||o===e},A=function(e){return S(e)&&"radio"===e.type},R=function(e){return A(e)&&!O(e)},I=function(e){var t,n=e&&p(e),r=null===(t=n)||void 0===t?void 0:t.host,o=!1;if(n&&n!==e){var i,s,a;o=!!(null!==(i=r)&&void 0!==i&&null!==(s=i.ownerDocument)&&void 0!==s&&s.contains(r)||null!==e&&void 0!==e&&null!==(a=e.ownerDocument)&&void 0!==a&&a.contains(e));while(!o&&r){var l,u,c;n=p(r),r=null===(l=n)||void 0===l?void 0:l.host,o=!(null===(u=r)||void 0===u||null===(c=u.ownerDocument)||void 0===c||!c.contains(r))}}return o},N=function(e){var t=e.getBoundingClientRect(),n=t.width,r=t.height;return 0===n&&0===r},L=function(e,t){var n=t.displayCheck,r=t.getShadowRoot;if("full-native"===n&&"checkVisibility"in e){var o=e.checkVisibility({checkOpacity:!1,opacityProperty:!1,contentVisibilityAuto:!0,visibilityProperty:!0,checkVisibilityCSS:!0});return!o}if("hidden"===getComputedStyle(e).visibility)return!0;var i=h.call(e,"details>summary:first-of-type"),s=i?e.parentElement:e;if(h.call(s,"details:not([open]) *"))return!0;if(n&&"full"!==n&&"full-native"!==n&&"legacy-full"!==n){if("non-zero-area"===n)return N(e)}else{if("function"===typeof r){var a=e;while(e){var l=e.parentElement,u=p(e);if(l&&!l.shadowRoot&&!0===r(l))return N(e);e=e.assignedSlot?e.assignedSlot:l||u===e.ownerDocument?l:u.host}e=a}if(I(e))return!e.getClientRects().length;if("legacy-full"!==n)return!0}return!1},x=function(e){if(/^(INPUT|BUTTON|SELECT|TEXTAREA)$/.test(e.tagName)){var t=e.parentElement;while(t){if("FIELDSET"===t.tagName&&t.disabled){for(var n=0;n<t.children.length;n++){var r=t.children.item(n);if("LEGEND"===r.tagName)return!!h.call(t,"fieldset[disabled] *")||!r.contains(e)}return!0}t=t.parentElement}}return!1},P=function(e,t){return!(t.disabled||T(t)||L(t,e)||k(t)||x(t))},D=function(e,t){return!(R(t)||_(t)<0||!P(e,t))},M=function(e){var t=parseInt(e.getAttribute("tabindex"),10);return!!(isNaN(t)||t>=0)},F=function(e){var t=[],n=[];return e.forEach(function(e,r){var o=!!e.scopeParent,i=o?e.scopeParent:e,s=E(i,o),a=o?F(e.candidates):i;0===s?o?t.push.apply(t,a):t.push(i):n.push({documentOrder:r,tabIndex:s,item:e,isScope:o,content:a})}),n.sort(w).reduce(function(e,t){return t.isScope?e.push.apply(e,t.content):e.push(t.content),e},[]).concat(t)},$=function(e,t){var n;return t=t||{},n=t.getShadowRoot?y([e],t.includeContainer,{filter:D.bind(null,t),flatten:!1,getShadowRoot:t.getShadowRoot,shadowRootFilter:M}):g(e,t.includeContainer,D.bind(null,t)),F(n)},j=function(e,t){var n;return t=t||{},n=t.getShadowRoot?y([e],t.includeContainer,{filter:P.bind(null,t),flatten:!0,getShadowRoot:t.getShadowRoot}):g(e,t.includeContainer,P.bind(null,t)),n},U=function(e,t){if(t=t||{},!e)throw new Error("No node provided");return!1!==h.call(e,d)&&D(t,e)},B=c.concat("iframe:not([inert]):not([inert] *)").join(","),V=function(e,t){if(t=t||{},!e)throw new Error("No node provided");return!1!==h.call(e,B)&&P(t,e)};
/*!
* focus-trap 7.8.0
* @license MIT, https://github.com/focus-trap/focus-trap/blob/master/LICENSE
*/
function G(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);n<t;n++)r[n]=e[n];return r}function H(e){if(Array.isArray(e))return G(e)}function W(e,t){var n="undefined"!=typeof Symbol&&e[Symbol.iterator]||e["@@iterator"];if(!n){if(Array.isArray(e)||(n=ee(e))||t){n&&(e=n);var r=0,o=function(){};return{s:o,n:function(){return r>=e.length?{done:!0}:{done:!1,value:e[r++]}},e:function(e){throw e},f:o}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}var i,s=!0,a=!1;return{s:function(){n=n.call(e)},n:function(){var e=n.next();return s=e.done,e},e:function(e){a=!0,i=e},f:function(){try{s||null==n.return||n.return()}finally{if(a)throw i}}}}function X(e,t,n){return(t=Z(t))in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function K(e){if("undefined"!=typeof Symbol&&null!=e[Symbol.iterator]||null!=e["@@iterator"])return Array.from(e)}function q(){throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}function z(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter(function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable})),n.push.apply(n,r)}return n}function Y(e){for(var t=1;t<arguments.length;t++){var n=null!=arguments[t]?arguments[t]:{};t%2?z(Object(n),!0).forEach(function(t){X(e,t,n[t])}):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(n)):z(Object(n)).forEach(function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(n,t))})}return e}function Q(e){return H(e)||K(e)||ee(e)||q()}function J(e,t){if("object"!=typeof e||!e)return e;var n=e[Symbol.toPrimitive];if(void 0!==n){var r=n.call(e,t);if("object"!=typeof r)return r;throw new TypeError("@@toPrimitive must return a primitive value.")}return("string"===t?String:Number)(e)}function Z(e){var t=J(e,"string");return"symbol"==typeof t?t:t+""}function ee(e,t){if(e){if("string"==typeof e)return G(e,t);var n={}.toString.call(e).slice(8,-1);return"Object"===n&&e.constructor&&(n=e.constructor.name),"Map"===n||"Set"===n?Array.from(e):"Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)?G(e,t):void 0}}var te={getActiveTrap:function(e){return(null===e||void 0===e?void 0:e.length)>0?e[e.length-1]:null},activateTrap:function(e,t){var n=te.getActiveTrap(e);t!==n&&te.pauseTrap(e);var r=e.indexOf(t);-1===r||e.splice(r,1),e.push(t)},deactivateTrap:function(e,t){var n=e.indexOf(t);-1!==n&&e.splice(n,1),te.unpauseTrap(e)},pauseTrap:function(e){var t=te.getActiveTrap(e);null===t||void 0===t||t._setPausedState(!0)},unpauseTrap:function(e){var t=te.getActiveTrap(e);t&&!t._isManuallyPaused()&&t._setPausedState(!1)}},ne=function(e){return e.tagName&&"input"===e.tagName.toLowerCase()&&"function"===typeof e.select},re=function(e){return"Escape"===(null===e||void 0===e?void 0:e.key)||"Esc"===(null===e||void 0===e?void 0:e.key)||27===(null===e||void 0===e?void 0:e.keyCode)},oe=function(e){return"Tab"===(null===e||void 0===e?void 0:e.key)||9===(null===e||void 0===e?void 0:e.keyCode)},ie=function(e){return oe(e)&&!e.shiftKey},se=function(e){return oe(e)&&e.shiftKey},ae=function(e){return setTimeout(e,0)},le=function(e){for(var t=arguments.length,n=new Array(t>1?t-1:0),r=1;r<t;r++)n[r-1]=arguments[r];return"function"===typeof e?e.apply(void 0,n):e},ue=function(e){return e.target.shadowRoot&&"function"===typeof e.composedPath?e.composedPath()[0]:e.target},ce=[],de=function(e,t){var n,r=(null===t||void 0===t?void 0:t.document)||document,o=(null===t||void 0===t?void 0:t.trapStack)||ce,i=Y({returnFocusOnDeactivate:!0,escapeDeactivates:!0,delayInitialFocus:!0,isolateSubtrees:!1,isKeyForward:ie,isKeyBackward:se},t),s={containers:[],containerGroups:[],tabbableGroups:[],adjacentElements:new Set,alreadySilent:new Set,nodeFocusedBeforeActivation:null,mostRecentlyFocusedNode:null,active:!1,paused:!1,manuallyPaused:!1,delayInitialFocusTimer:void 0,recentNavEvent:void 0},a=function(e,t,n){return e&&void 0!==e[t]?e[t]:i[n||t]},l=function(e,t){var n="function"===typeof(null===t||void 0===t?void 0:t.composedPath)?t.composedPath():void 0;return s.containerGroups.findIndex(function(t){var r=t.container,o=t.tabbableNodes;return r.contains(e)||(null===n||void 0===n?void 0:n.includes(r))||o.find(function(t){return t===e})})},u=function(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{},n=t.hasFallback,o=void 0!==n&&n,s=t.params,a=void 0===s?[]:s,l=i[e];if("function"===typeof l&&(l=l.apply(void 0,Q(a))),!0===l&&(l=void 0),!l){if(void 0===l||!1===l)return l;throw new Error("`".concat(e,"` was specified but was not a node, or did not return a node"))}var u=l;if("string"===typeof l){try{u=r.querySelector(l)}catch(c){throw new Error("`".concat(e,'` appears to be an invalid selector; error="').concat(c.message,'"'))}if(!u&&!o)throw new Error("`".concat(e,"` as selector refers to no known node"))}return u},c=function(){var e=u("initialFocus",{hasFallback:!0});if(!1===e)return!1;if(void 0===e||e&&!V(e,i.tabbableOptions))if(l(r.activeElement)>=0)e=r.activeElement;else{var t=s.tabbableGroups[0],n=t&&t.firstTabbableNode;e=n||u("fallbackFocus")}else null===e&&(e=u("fallbackFocus"));if(!e)throw new Error("Your focus-trap needs to have at least one focusable element");return e},d=function(){if(s.containerGroups=s.containers.map(function(e){var t=$(e,i.tabbableOptions),n=j(e,i.tabbableOptions),r=t.length>0?t[0]:void 0,o=t.length>0?t[t.length-1]:void 0,s=n.find(function(e){return U(e)}),a=n.slice().reverse().find(function(e){return U(e)}),l=!!t.find(function(e){return _(e)>0});return{container:e,tabbableNodes:t,focusableNodes:n,posTabIndexesFound:l,firstTabbableNode:r,lastTabbableNode:o,firstDomTabbableNode:s,lastDomTabbableNode:a,nextTabbableNode:function(e){var r=!(arguments.length>1&&void 0!==arguments[1])||arguments[1],o=t.indexOf(e);return o<0?r?n.slice(n.indexOf(e)+1).find(function(e){return U(e)}):n.slice(0,n.indexOf(e)).reverse().find(function(e){return U(e)}):t[o+(r?1:-1)]}}}),s.tabbableGroups=s.containerGroups.filter(function(e){return e.tabbableNodes.length>0}),s.tabbableGroups.length<=0&&!u("fallbackFocus"))throw new Error("Your focus-trap must have at least one container with at least one tabbable node in it at all times");if(s.containerGroups.find(function(e){return e.posTabIndexesFound})&&s.containerGroups.length>1)throw new Error("At least one node with a positive tabindex was found in one of your focus-trap's multiple containers. Positive tabindexes are only supported in single-container focus-traps.")},f=function(e){var t=e.activeElement;if(t)return t.shadowRoot&&null!==t.shadowRoot.activeElement?f(t.shadowRoot):t},h=function(e){!1!==e&&e!==f(document)&&(e&&e.focus?(e.focus({preventScroll:!!i.preventScroll}),s.mostRecentlyFocusedNode=e,ne(e)&&e.select()):h(c()))},p=function(e){var t=u("setReturnFocus",{params:[e]});return t||!1!==t&&e},m=function(e){var t=e.target,n=e.event,r=e.isBackward,o=void 0!==r&&r;t=t||ue(n),d();var a=null;if(s.tabbableGroups.length>0){var c=l(t,n),f=c>=0?s.containerGroups[c]:void 0;if(c<0)a=o?s.tabbableGroups[s.tabbableGroups.length-1].lastTabbableNode:s.tabbableGroups[0].firstTabbableNode;else if(o){var h=s.tabbableGroups.findIndex(function(e){var n=e.firstTabbableNode;return t===n});if(h<0&&(f.container===t||V(t,i.tabbableOptions)&&!U(t,i.tabbableOptions)&&!f.nextTabbableNode(t,!1))&&(h=c),h>=0){var p=0===h?s.tabbableGroups.length-1:h-1,m=s.tabbableGroups[p];a=_(t)>=0?m.lastTabbableNode:m.lastDomTabbableNode}else oe(n)||(a=f.nextTabbableNode(t,!1))}else{var v=s.tabbableGroups.findIndex(function(e){var n=e.lastTabbableNode;return t===n});if(v<0&&(f.container===t||V(t,i.tabbableOptions)&&!U(t,i.tabbableOptions)&&!f.nextTabbableNode(t))&&(v=c),v>=0){var g=v===s.tabbableGroups.length-1?0:v+1,y=s.tabbableGroups[g];a=_(t)>=0?y.firstTabbableNode:y.firstDomTabbableNode}else oe(n)||(a=f.nextTabbableNode(t))}}else a=u("fallbackFocus");return a},v=function(e){var t=ue(e);l(t,e)>=0||(le(i.clickOutsideDeactivates,e)?n.deactivate({returnFocus:i.returnFocusOnDeactivate}):le(i.allowOutsideClick,e)||e.preventDefault())},g=function(e){var t=ue(e),n=l(t,e)>=0;if(n||t instanceof Document)n&&(s.mostRecentlyFocusedNode=t);else{var r;e.stopImmediatePropagation();var o=!0;if(s.mostRecentlyFocusedNode)if(_(s.mostRecentlyFocusedNode)>0){var a=l(s.mostRecentlyFocusedNode),u=s.containerGroups[a].tabbableNodes;if(u.length>0){var d=u.findIndex(function(e){return e===s.mostRecentlyFocusedNode});d>=0&&(i.isKeyForward(s.recentNavEvent)?d+1<u.length&&(r=u[d+1],o=!1):d-1>=0&&(r=u[d-1],o=!1))}}else s.containerGroups.some(function(e){return e.tabbableNodes.some(function(e){return _(e)>0})})||(o=!1);else o=!1;o&&(r=m({target:s.mostRecentlyFocusedNode,isBackward:i.isKeyBackward(s.recentNavEvent)})),h(r||(s.mostRecentlyFocusedNode||c()))}s.recentNavEvent=void 0},y=function(e){var t=arguments.length>1&&void 0!==arguments[1]&&arguments[1];s.recentNavEvent=e;var n=m({event:e,isBackward:t});n&&(oe(e)&&e.preventDefault(),h(n))},b=function(e){(i.isKeyForward(e)||i.isKeyBackward(e))&&y(e,i.isKeyBackward(e))},E=function(e){re(e)&&!1!==le(i.escapeDeactivates,e)&&(e.preventDefault(),n.deactivate())},w=function(e){var t=ue(e);l(t,e)>=0||le(i.clickOutsideDeactivates,e)||le(i.allowOutsideClick,e)||(e.preventDefault(),e.stopImmediatePropagation())},S=function(){if(s.active)return te.activateTrap(o,n),s.delayInitialFocusTimer=i.delayInitialFocus?ae(function(){h(c())}):h(c()),r.addEventListener("focusin",g,!0),r.addEventListener("mousedown",v,{capture:!0,passive:!1}),r.addEventListener("touchstart",v,{capture:!0,passive:!1}),r.addEventListener("click",w,{capture:!0,passive:!1}),r.addEventListener("keydown",b,{capture:!0,passive:!1}),r.addEventListener("keydown",E),n},T=function(e){s.active&&!s.paused&&n._setSubtreeIsolation(!1),s.adjacentElements.clear(),s.alreadySilent.clear();var t,r=new Set,o=new Set,i=W(e);try{for(i.s();!(t=i.n()).done;){var a=t.value;r.add(a);var l="undefined"!==typeof ShadowRoot&&a.getRootNode()instanceof ShadowRoot,u=a;while(u){r.add(u);var c=u.parentElement,d=[];c?d=c.children:!c&&l&&(d=u.getRootNode().children,c=u.getRootNode().host,l="undefined"!==typeof ShadowRoot&&c.getRootNode()instanceof ShadowRoot);var f,h=W(d);try{for(h.s();!(f=h.n()).done;){var p=f.value;o.add(p)}}catch(m){h.e(m)}finally{h.f()}u=c}}}catch(m){i.e(m)}finally{i.f()}r.forEach(function(e){o["delete"](e)}),s.adjacentElements=o},k=function(){if(s.active)return r.removeEventListener("focusin",g,!0),r.removeEventListener("mousedown",v,!0),r.removeEventListener("touchstart",v,!0),r.removeEventListener("click",w,!0),r.removeEventListener("keydown",b,!0),r.removeEventListener("keydown",E),n},C=function(e){var t=e.some(function(e){var t=Array.from(e.removedNodes);return t.some(function(e){return e===s.mostRecentlyFocusedNode})});t&&h(c())},O="undefined"!==typeof window&&"MutationObserver"in window?new MutationObserver(C):void 0,A=function(){O&&(O.disconnect(),s.active&&!s.paused&&s.containers.map(function(e){O.observe(e,{subtree:!0,childList:!0})}))};return n={get active(){return s.active},get paused(){return s.paused},activate:function(e){if(s.active)return this;var t,l=a(e,"onActivate"),u=a(e,"onPostActivate"),c=a(e,"checkCanFocusTrap"),h=te.getActiveTrap(o),p=!1;h&&!h.paused&&(null===(t=h._setSubtreeIsolation)||void 0===t||t.call(h,!1),p=!0);try{c||d(),s.active=!0,s.paused=!1,s.nodeFocusedBeforeActivation=f(r),null===l||void 0===l||l();var m=function(){c&&d(),S(),A(),i.isolateSubtrees&&n._setSubtreeIsolation(!0),null===u||void 0===u||u()};if(c)return c(s.containers.concat()).then(m,m),this;m()}catch(g){var v;if(h===te.getActiveTrap(o)&&p)null===(v=h._setSubtreeIsolation)||void 0===v||v.call(h,!0);throw g}return this},deactivate:function(e){if(!s.active)return this;var t=Y({onDeactivate:i.onDeactivate,onPostDeactivate:i.onPostDeactivate,checkCanReturnFocus:i.checkCanReturnFocus},e);clearTimeout(s.delayInitialFocusTimer),s.delayInitialFocusTimer=void 0,s.paused||n._setSubtreeIsolation(!1),s.alreadySilent.clear(),k(),s.active=!1,s.paused=!1,A(),te.deactivateTrap(o,n);var r=a(t,"onDeactivate"),l=a(t,"onPostDeactivate"),u=a(t,"checkCanReturnFocus"),c=a(t,"returnFocus","returnFocusOnDeactivate");null===r||void 0===r||r();var d=function(){ae(function(){c&&h(p(s.nodeFocusedBeforeActivation)),null===l||void 0===l||l()})};return c&&u?(u(p(s.nodeFocusedBeforeActivation)).then(d,d),this):(d(),this)},pause:function(e){return s.active?(s.manuallyPaused=!0,this._setPausedState(!0,e)):this},unpause:function(e){return s.active?(s.manuallyPaused=!1,o[o.length-1]!==this?this:this._setPausedState(!1,e)):this},updateContainerElements:function(e){var t=[].concat(e).filter(Boolean);return s.containers=t.map(function(e){return"string"===typeof e?r.querySelector(e):e}),i.isolateSubtrees&&T(s.containers),s.active&&(d(),i.isolateSubtrees&&!s.paused&&n._setSubtreeIsolation(!0)),A(),this}},Object.defineProperties(n,{_isManuallyPaused:{value:function(){return s.manuallyPaused}},_setPausedState:{value:function(e,t){if(s.paused===e)return this;if(s.paused=e,e){var r=a(t,"onPause"),o=a(t,"onPostPause");null===r||void 0===r||r(),k(),A(),n._setSubtreeIsolation(!1),null===o||void 0===o||o()}else{var i=a(t,"onUnpause"),l=a(t,"onPostUnpause");null===i||void 0===i||i(),n._setSubtreeIsolation(!0),d(),S(),A(),null===l||void 0===l||l()}return this}},_setSubtreeIsolation:{value:function(e){i.isolateSubtrees&&s.adjacentElements.forEach(function(t){var n;if(e)switch(i.isolateSubtrees){case"aria-hidden":"true"!==t.ariaHidden&&"true"!==(null===(n=t.getAttribute("aria-hidden"))||void 0===n?void 0:n.toLowerCase())||s.alreadySilent.add(t),t.setAttribute("aria-hidden","true");break;default:(t.inert||t.hasAttribute("inert"))&&s.alreadySilent.add(t),t.setAttribute("inert",!0);break}else if(s.alreadySilent.has(t));else switch(i.isolateSubtrees){case"aria-hidden":t.removeAttribute("aria-hidden");break;default:t.removeAttribute("inert");break}})}}}),n.updateContainerElements(e),n};
/*!
  * focus-trap-vue v4.0.3
  * (c) 2025 Eduardo San Martin Morote
  * @license MIT
  */
function fe(e){return e}const he=fe({escapeDeactivates:{type:Boolean,default:!0},returnFocusOnDeactivate:{type:Boolean,default:!0},allowOutsideClick:{type:[Boolean,Function],default:!0},clickOutsideDeactivates:[Boolean,Function],initialFocus:[String,Function,Boolean],fallbackFocus:[String,Function],checkCanFocusTrap:Function,checkCanReturnFocus:Function,delayInitialFocus:{type:Boolean,default:!0},document:Object,preventScroll:Boolean,setReturnFocus:[Object,String,Boolean,Function],tabbableOptions:Object}),pe=(0,r.pM)({name:"FocusTrap",props:Object.assign({active:{type:Boolean,default:!0}},he),emits:["update:active","activate","postActivate","deactivate","postDeactivate"],render(){return this.renderImpl()},setup(e,{slots:t,emit:n}){let o;const i=(0,u.KR)(null),s=(0,r.EW)(()=>{const e=i.value;return e&&(e instanceof HTMLElement?e:e.$el)});function a(){return o||(o=de(s.value,{escapeDeactivates:e.escapeDeactivates,allowOutsideClick:e.allowOutsideClick,returnFocusOnDeactivate:e.returnFocusOnDeactivate,clickOutsideDeactivates:e.clickOutsideDeactivates,onActivate:()=>{n("update:active",!0),n("activate")},onDeactivate:()=>{n("update:active",!1),n("deactivate")},onPostActivate:()=>n("postActivate"),onPostDeactivate:()=>n("postDeactivate"),initialFocus:e.initialFocus,fallbackFocus:e.fallbackFocus,tabbableOptions:e.tabbableOptions,delayInitialFocus:e.delayInitialFocus,preventScroll:e.preventScroll}))}return(0,r.sV)(()=>{(0,r.wB)(()=>e.active,e=>{e&&s.value?a().activate():o&&(o.deactivate(),s.value&&s.value.nodeType!==Node.COMMENT_NODE||(o=null))},{immediate:!0,flush:"post"})}),(0,r.hi)(()=>{o&&o.deactivate(),o=null}),{activate(){a().activate()},deactivate(){o&&o.deactivate()},renderImpl(){if(!t.default)return null;const e=t.default().filter(e=>e.type!==r.Mw);if(!e||!e.length||e.length>1)return console.error("[focus-trap-vue]: FocusTrap requires exactly one child."),e;const n=(0,r.E3)(e[0],{ref:i});return n}}}});var me={components:{FocusTrap:pe},emits:["submit","clear"],props:{fixed:Boolean,popupClass:[String,Object,null],headline:String,headlineType:String},methods:{clearCurrent(e){(!e||this.$refs.popup&&!this.$refs.popup.contains(e.target)&&document.body.contains(e.target))&&this.$emit("clear")}}},ve=n(6262);const ge=(0,ve.A)(me,[["render",l]]);var ye=ge},791:function(e,t,n){"use strict";n.d(t,{A:function(){return f}});var r=n(641),o=n(3751);const i={class:"search-bar"},s=["placeholder","disabled","value"];function a(e,t,n,a,l,u){return(0,r.uX)(),(0,r.CE)("section",i,[(0,r.Lk)("input",{class:"search-bar__input",ref:"search",id:"search",type:"text",placeholder:n.placeholder,disabled:n.disabled,autocomplete:"off",value:e.query,onInput:t[0]||(t[0]=(...e)=>u.searchInput&&u.searchInput(...e)),onKeypress:t[1]||(t[1]=(0,o.jR)((0,o.D$)((...t)=>e.stopSearch&&e.stopSearch(...t),["prevent"]),["esc"]))},null,40,s),e.query?((0,r.uX)(),(0,r.CE)("button",{key:0,class:"search-bar__button search-bar__button--stop",onClick:t[2]||(t[2]=(...t)=>e.stopSearch&&e.stopSearch(...t))},[...t[4]||(t[4]=[(0,r.Lk)("svg",{height:"24",viewBox:"0 0 24 24",width:"24",fill:"#737373",xmlns:"http://www.w3.org/2000/svg"},[(0,r.Lk)("path",{d:"M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z"}),(0,r.Lk)("path",{d:"M0 0h24v24H0z",fill:"none"})],-1)])])):((0,r.uX)(),(0,r.CE)("button",{key:1,class:"search-bar__button search-bar__button--start",onClick:t[3]||(t[3]=t=>e.$refs.search.focus()),tabindex:"-1"},[...t[5]||(t[5]=[(0,r.Lk)("svg",{fill:"#737373",height:"24",viewBox:"0 0 24 24",width:"24",xmlns:"http://www.w3.org/2000/svg"},[(0,r.Lk)("path",{d:"M15.5 14h-.79l-.28-.27A6.471 6.471 0 0 0 16 9.5 6.5 6.5 0 1 0 9.5 16c1.61 0 3.09-.59 4.23-1.57l.27.28v.79l5 4.99L20.49 19l-4.99-5zm-6 0C7.01 14 5 11.99 5 9.5S7.01 5 9.5 5 14 7.01 14 9.5 11.99 14 9.5 14z"}),(0,r.Lk)("path",{d:"M0 0h24v24H0z",fill:"none"})],-1)])]))])}var l=n(1881),u={mixins:[l.A],props:{placeholder:String,disabled:Boolean},methods:{searchInput(e){this.startSearch(e.target.value)}}},c=n(6262);const d=(0,c.A)(u,[["render",a]]);var f=d},2273:function(e,t,n){"use strict";n.d(t,{A:function(){return f}});var r=n(641),o=n(33);const i={class:"theme-switch"},s=["title"],a=["title"];function l(e,t,n,l,u,c){return(0,r.uX)(),(0,r.CE)("div",i,["dark"===e.colorScheme?((0,r.uX)(),(0,r.CE)("button",{key:0,onClick:t[0]||(t[0]=(...e)=>c.toggle&&c.toggle(...e)),title:e.$t("ui.app.colorLightTitle")},(0,o.v_)(e.$t("ui.app.colorLight")),9,s)):((0,r.uX)(),(0,r.CE)("button",{key:1,onClick:t[1]||(t[1]=(...e)=>c.toggle&&c.toggle(...e)),title:e.$t("ui.app.colorDarkTitle")},(0,o.v_)(e.$t("ui.app.colorDark")),9,a))])}var u={data:()=>({colorScheme:"light"}),methods:{prefersDark(){const e=localStorage.getItem("contao--prefers-dark");return null===e?!!window.matchMedia("(prefers-color-scheme: dark)").matches:"true"===e},setColorScheme(){document.documentElement.dataset.colorScheme=this.colorScheme=this.prefersDark()?"dark":"light"},toggle(){const e=!this.prefersDark();e===window.matchMedia("(prefers-color-scheme: dark)").matches?localStorage.removeItem("contao--prefers-dark"):localStorage.setItem("contao--prefers-dark",String(e)),this.setColorScheme()}},mounted(){window.matchMedia("(prefers-color-scheme: dark)").addEventListener("change",this.setColorScheme),this.setColorScheme()},unmounted(){window.matchMedia("(prefers-color-scheme: dark)").removeEventListener("change",this.setColorScheme)}},c=n(6262);const d=(0,c.A)(u,[["render",l]]);var f=d},8568:function(e,t,n){
/*!
 Name: vue-upload-component 
Component URI: https://github.com/lian-yue/vue-upload-component#readme 
Version: 3.1.16 
Author: LianYue 
License: Apache-2.0 
Description: Vue.js file upload component, Multi-file upload, Upload directory, Drag upload, Drag the directory, Upload multiple files at the same time, html4 (IE 9), `PUT` method, Customize the filter 
 */
(function(t,r){e.exports=r(n(8756))})(0,function(e){"use strict";function t(e){return i(e)||o(e)||r(e)||n()}function n(){throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}function r(e,t){if(e){if("string"===typeof e)return s(e,t);var n=Object.prototype.toString.call(e).slice(8,-1);return"Object"===n&&e.constructor&&(n=e.constructor.name),"Map"===n||"Set"===n?Array.from(e):"Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)?s(e,t):void 0}}function o(e){if("undefined"!==typeof Symbol&&null!=e[Symbol.iterator]||null!=e["@@iterator"])return Array.from(e)}function i(e){if(Array.isArray(e))return s(e)}function s(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=new Array(t);n<t;n++)r[n]=e[n];return r}function a(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter(function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable})),n.push.apply(n,r)}return n}function l(e){for(var t=1;t<arguments.length;t++){var n=null!=arguments[t]?arguments[t]:{};t%2?a(Object(n),!0).forEach(function(t){u(e,t,n[t])}):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(n)):a(Object(n)).forEach(function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(n,t))})}return e}function u(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function c(e){return c="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},c(e)}function d(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter(function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable})),n.push.apply(n,r)}return n}function f(e){for(var t=1;t<arguments.length;t++){var n=null!=arguments[t]?arguments[t]:{};t%2?d(Object(n),!0).forEach(function(t){v(e,t,n[t])}):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(n)):d(Object(n)).forEach(function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(n,t))})}return e}function h(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function p(e,t){for(var n=0;n<t.length;n++){var r=t[n];r.enumerable=r.enumerable||!1,r.configurable=!0,"value"in r&&(r.writable=!0),Object.defineProperty(e,r.key,r)}}function m(e,t,n){return t&&p(e.prototype,t),n&&p(e,n),Object.defineProperty(e,"prototype",{writable:!1}),e}function v(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}var g=function(e){var t=new XMLHttpRequest;return t.open(e.method||"GET",e.url),t.responseType="json",e.headers&&Object.keys(e.headers).forEach(function(n){t.setRequestHeader(n,e.headers[n])}),t},y=function(e,t){return new Promise(function(n,r){e.onload=function(){if(e.status>=200&&e.status<300){var t;try{t=JSON.parse(e.response)}catch(o){t=e.response}n(t)}else r(e.response)},e.onerror=function(){return r(e.response)},e.send(JSON.stringify(t))})},b=function(e,t){var n=new FormData;for(var r in t)n.append(r,t[r]);return new Promise(function(t,r){e.onload=function(){if(e.status>=200&&e.status<300){var n;try{n=JSON.parse(e.response)}catch(o){n=e.response}t(n)}else r(e.response)},e.onerror=function(){return r(e.response)},e.send(n)})};function _(e){var t=g(e);return y(t,e.body)}var E=function(){function e(t,n){h(this,e),this.file=t,this.options=n,this.chunks=[],this.sessionId=null,this.chunkSize=null,this.speedInterval=null}return m(e,[{key:"maxRetries",get:function(){return parseInt(this.options.maxRetries,10)}},{key:"maxActiveChunks",get:function(){return parseInt(this.options.maxActive,10)}},{key:"fileType",get:function(){return this.file.type}},{key:"fileSize",get:function(){return this.file.size}},{key:"fileName",get:function(){return this.file.name}},{key:"action",get:function(){return this.options.action||null}},{key:"startBody",get:function(){return this.options.startBody||{}}},{key:"uploadBody",get:function(){return this.options.uploadBody||{}}},{key:"finishBody",get:function(){return this.options.finishBody||{}}},{key:"headers",get:function(){return this.options.headers||{}}},{key:"readyToUpload",get:function(){return!!this.chunks}},{key:"progress",get:function(){var e=this,t=this.chunksUploaded.length/this.chunks.length*100,n=this.chunksUploading.reduce(function(t,n){return t+(0|n.progress)/e.chunks.length},0);return Math.min(t+n,100)}},{key:"chunksToUpload",get:function(){return this.chunks.filter(function(e){return!e.active&&!e.uploaded})}},{key:"hasChunksToUpload",get:function(){return this.chunksToUpload.length>0}},{key:"chunksUploading",get:function(){return this.chunks.filter(function(e){return!!e.xhr&&!!e.active})}},{key:"chunksUploaded",get:function(){return this.chunks.filter(function(e){return!!e.uploaded})}},{key:"createChunks",value:function(){this.chunks=[];var e=0,t=this.chunkSize;while(e<this.fileSize)this.chunks.push({blob:this.file.file.slice(e,t),startOffset:e,active:!1,retries:this.maxRetries}),e=t,t=e+this.chunkSize}},{key:"updateFileProgress",value:function(){this.file.progress=this.progress}},{key:"pause",value:function(){this.file.active=!1,this.stopChunks()}},{key:"stopChunks",value:function(){this.chunksUploading.forEach(function(e){e.xhr.abort(),e.active=!1}),this.stopSpeedCalc()}},{key:"resume",value:function(){this.file.active=!0,this.startChunking()}},{key:"upload",value:function(){var e=this;return this.promise=new Promise(function(t,n){e.resolve=t,e.reject=n}),this.start(),this.promise}},{key:"start",value:function(){var e=this;_({method:"POST",headers:f(f({},this.headers),{},{"Content-Type":"application/json"}),url:this.action,body:Object.assign(this.startBody,{phase:"start",mime_type:this.fileType,size:this.fileSize,name:this.fileName})}).then(function(t){if("success"!==t.status)return e.file.response=t,e.reject("server");e.sessionId=t.data.session_id,e.chunkSize=t.data.end_offset,e.createChunks(),e.startChunking()}).catch(function(t){e.file.response=t,e.reject("server")})}},{key:"startChunking",value:function(){for(var e=0;e<this.maxActiveChunks;e++)this.uploadNextChunk();this.startSpeedCalc()}},{key:"uploadNextChunk",value:function(){if(this.file.active){if(this.hasChunksToUpload)return this.uploadChunk(this.chunksToUpload[0]);if(0===this.chunksUploading.length)return this.finish()}}},{key:"uploadChunk",value:function(e){var t=this;e.progress=0,e.active=!0,this.updateFileProgress(),e.xhr=g({method:"POST",headers:this.headers,url:this.action}),e.xhr.upload.addEventListener("progress",function(t){t.lengthComputable&&(e.progress=Math.round(t.loaded/t.total*100))},!1),b(e.xhr,Object.assign(this.uploadBody,{phase:"upload",session_id:this.sessionId,start_offset:e.startOffset,chunk:e.blob})).then(function(n){if(e.active=!1,"success"===n.status)e.uploaded=!0;else if(e.retries--<=0)return t.stopChunks(),t.reject("upload");t.uploadNextChunk()}).catch(function(){if(e.active=!1,e.retries--<=0)return t.stopChunks(),t.reject("upload");t.uploadNextChunk()})}},{key:"finish",value:function(){var e=this;this.updateFileProgress(),this.stopSpeedCalc(),_({method:"POST",headers:f(f({},this.headers),{},{"Content-Type":"application/json"}),url:this.action,body:Object.assign(this.finishBody,{phase:"finish",session_id:this.sessionId})}).then(function(t){if(e.file.response=t,"success"!==t.status)return e.reject("server");e.resolve(t)}).catch(function(t){e.file.response=t,e.reject("server")})}},{key:"startSpeedCalc",value:function(){var e=this;this.file.speed=0;var t=0;this.speedInterval||(this.speedInterval=window.setInterval(function(){var n=e.progress/100*e.fileSize;e.file.speed=n-t,t=n},1e3))}},{key:"stopSpeedCalc",value:function(){this.speedInterval&&window.clearInterval(this.speedInterval),this.speedInterval=null,this.file.speed=0}}]),e}(),w={headers:{},action:"",minSize:1048576,maxActive:3,maxRetries:5,handler:E},S=e.defineComponent({compatConfig:{MODE:3},props:{inputId:{type:String},name:{type:String,default:"file"},accept:{type:String},capture:{},disabled:{default:!1},multiple:{type:Boolean,default:!1},maximum:{type:Number},addIndex:{type:[Boolean,Number]},directory:{type:Boolean},createDirectory:{type:Boolean,default:!1},postAction:{type:String},putAction:{type:String},customAction:{type:Function},headers:{type:Object,default:function(){return{}}},data:{type:Object,default:function(){return{}}},timeout:{type:Number,default:0},drop:{type:[Boolean,String,HTMLElement],default:function(){return!1}},dropDirectory:{type:Boolean,default:!0},size:{type:Number,default:0},extensions:{type:[RegExp,String,Array],default:function(){return[]}},modelValue:{type:Array,default:function(){return[]}},thread:{type:Number,default:1},chunkEnabled:{type:Boolean,default:!1},chunk:{type:Object,default:function(){return w}}},emits:["update:modelValue","input-filter","input-file"],data:function(){return{files:this.modelValue,features:{html5:!0,directory:!1,drop:!1},active:!1,dropActive:!1,dropElementActive:!1,uploading:0,destroy:!1,maps:{},dropElement:null,dropTimeout:null,reload:!1}},mounted:function(){var e=this,t=document.createElement("input");if(t.type="file",t.multiple=!0,window.FormData&&t.files?("boolean"!==typeof t.webkitdirectory&&"boolean"!==typeof t.directory||(this.features.directory=!0),this.features.html5&&"undefined"!==typeof t.ondrop&&this.isRelatedTargetSupported()&&(this.features.drop=!0)):this.features.html5=!1,this.maps={},this.files)for(var n=0;n<this.files.length;n++){var r=this.files[n];this.maps[r.id]=r}this.$nextTick(function(){e.$parent?(e.$parent.$forceUpdate(),e.$parent.$nextTick(function(){e.watchDrop(e.drop)})):e.watchDrop(e.drop)})},beforeUnmount:function(){this.destroy=!0,this.active=!1,this.watchDrop(!1),this.watchActive(!1)},computed:{uploaded:function(){for(var e,t=0;t<this.files.length;t++)if(e=this.files[t],e.fileObject&&!e.error&&!e.success)return!1;return!0},chunkOptions:function(){return Object.assign(w,this.chunk)},className:function(){return["file-uploads",this.features.html5?"file-uploads-html5":"file-uploads-html4",this.features.directory&&this.directory?"file-uploads-directory":void 0,this.features.drop&&this.drop?"file-uploads-drop":void 0,this.disabled?"file-uploads-disabled":void 0]},forId:function(){return this.inputId||this.name},iMaximum:function(){return void 0===this.maximum?this.multiple?0:1:this.maximum},iExtensions:function(){if(this.extensions){if(this.extensions instanceof RegExp)return this.extensions;if(this.extensions.length){var e=[];return e="string"===typeof this.extensions?this.extensions.split(","):this.extensions,e=e.map(function(e){return e.trim()}).filter(function(e){return e}),new RegExp("\\.("+e.join("|").replace(/\./g,"\\.")+")$","i")}}},iDirectory:function(){if(this.directory&&this.features.directory)return!0}},watch:{active:function(e){this.watchActive(e)},dropActive:function(e){this.watchDropActive(e),this.$parent&&this.$parent.$forceUpdate()},drop:function(e){this.watchDrop(e)},modelValue:function(e){if(this.files!==e){this.files=e;var t=this.maps;this.maps={};for(var n=0;n<this.files.length;n++){var r=this.files[n];this.maps[r.id]=r}for(var o in this.maps){var i=this.maps[o],s=t[o];i!==s&&this.emitFile(i,s)}for(var a in t)this.maps[a]||this.emitFile(void 0,t[a])}}},methods:{newId:function(){return Math.random().toString(36).substr(2)},clear:function(){if(this.files.length){var e=this.files;this.files=[],this.maps={},this.emitInput();for(var t=0;t<e.length;t++)this.emitFile(void 0,e[t])}return!0},get:function(e){return!!e&&("object"===c(e)?this.maps[e.id||""]||!1:this.maps[e]||!1)},add:function(e,n){var r;r=e instanceof Array?e:[e],void 0===n&&(n=this.addIndex);for(var o=[],i=0;i<r.length;i++){var s=r[i];this.features.html5&&s instanceof Blob&&(s={id:"",file:s,size:s.size,name:s.webkitRelativePath||s.relativePath||s.name||"unknown",type:s.type});var a=!1;if(!1===s.fileObject||(s.fileObject||"undefined"!==typeof Element&&s.el instanceof HTMLInputElement||"undefined"!==typeof Blob&&s.file instanceof Blob)&&(a=!0),a&&(s=l(l({fileObject:!0,size:-1,name:"Filename",type:"",active:!1,error:"",success:!1,putAction:this.putAction,postAction:this.postAction,timeout:this.timeout},s),{},{response:{},progress:"0.00",speed:0}),s.data=l(l({},this.data),s.data?s.data:{}),s.headers=l(l({},this.headers),s.headers?s.headers:{})),s.id||(s.id=this.newId()),!this.emitFilter(s,void 0)){if(this.iMaximum>1&&o.length+this.files.length>=this.iMaximum)break;if(o.push(s),1===this.iMaximum)break}}if(o.length){var u;if(1===this.iMaximum&&this.clear(),!0===n||0===n)u=o.concat(this.files);else if(n){var c;u=this.files.concat([]),(c=u).splice.apply(c,[n,0].concat(t(o)))}else u=this.files.concat(o);this.files=u;var d=0;!0===n||0===n?d=0:n?n>=0?d=n+o.length>this.files.length?this.files.length-o.length:n:(d=this.files.length-o.length+n,d<0&&(d=0)):d=this.files.length-o.length,o=this.files.slice(d,d+o.length);for(var f=0;f<o.length;f++){var h=o[f];this.maps[h.id]=h}this.emitInput();for(var p=0;p<o.length;p++)this.emitFile(o[p],void 0);return e instanceof Array?o:o[0]}},addInputFile:function(e){var t=this,n=[];this.iMaximum;var r=e.webkitEntries||e.entries||void 0;if(null!==r&&void 0!==r&&r.length)return this.getFileSystemEntry(r).then(function(e){return t.add(e)});if(e.files)for(var o=0;o<e.files.length;o++){var i=e.files[o];n.push({id:"",size:i.size,name:i.webkitRelativePath||i.relativePath||i.name,type:i.type,file:i})}else{var s=e.value.replace(/\\/g,"/").split("/");s&&s.length||(s=[e.value]),delete e.__vuex__,n.push({id:"",name:s[s.length-1],el:e})}return Promise.resolve(this.add(n))},addDataTransfer:function(e){var t,n=this;if(null!==e&&void 0!==e&&null!==(t=e.items)&&void 0!==t&&t.length){for(var r=[],o=0;o<e.items.length;o++){var i=e.items[o],s=void 0;s=i.getAsEntry?i.getAsEntry()||i.getAsFile():i.webkitGetAsEntry&&i.webkitGetAsEntry()||i.getAsFile(),s&&r.push(s)}return this.getFileSystemEntry(r).then(function(e){return n.add(e)})}var a=this.iMaximum,l=[];if(e.files.length){for(var u=0;u<e.files.length;u++)if(l.push(e.files[u]),a>0&&l.length>=a)break;return Promise.resolve(this.add(l))}return Promise.resolve([])},getFileSystemEntry:function(e){var n=this,r=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"";return new Promise(function(o){var i=n.iMaximum;if(e)if(e instanceof Array){var s=[],a=function a(l){var u=e[l];if(!u||i>0&&s.length>=i)return o(s);n.getFileSystemEntry(u,r).then(function(e){s.push.apply(s,t(e)),a(l+1)})};a(0)}else if(e instanceof Blob)o([{id:"",size:e.size,name:r+e.name,type:e.type,file:e}]);else if(e.isFile){var l=e;l.file(function(e){o([{id:"",size:e.size,name:r+e.name,type:e.type,file:e}])})}else if(e.isDirectory&&n.dropDirectory){var u=e,c=[];n.createDirectory&&c.push({id:"",name:r+u.name,size:0,type:"text/directory",file:new File([],r+u.name,{type:"text/directory"})});var d=u.createReader(),f=function e(){d.readEntries(function(s){var a=function a(l){return!s[l]&&0===l||i>0&&c.length>=i?o(c):s[l]?void n.getFileSystemEntry(s[l],r+u.name+"/").then(function(e){c.push.apply(c,t(e)),a(l+1)}):e()};a(0)})};f()}else o([]);else o([])})},replace:function(e,t){var n=this.get(e),r=this.get(t);if(!n||!r||n===r)return!1;var o=this.files.concat([]),i=o.indexOf(n),s=o.indexOf(r);return-1!==i&&-1!==s&&(o[i]=r,o[s]=n,this.files=o,this.emitInput(),!0)},remove:function(e){var t=this.get(e);if(t){if(this.emitFilter(void 0,t))return!1;var n=this.files.concat([]),r=n.indexOf(t);if(-1===r)return console.error("remove",t),!1;n.splice(r,1),this.files=n,delete this.maps[t.id],this.emitInput(),this.emitFile(void 0,t)}return t},update:function(e,t){var n=this.get(e);if(n){var r=l(l({},n),t);if(!n.fileObject||!n.active||r.active||r.error||r.success||(r.error="abort"),this.emitFilter(r,n))return!1;var o=this.files.concat([]),i=o.indexOf(n);return-1===i?(console.error("update",n),!1):(o.splice(i,1,r),this.files=o,r=this.files[i],delete this.maps[n.id],this.maps[r.id]=r,this.emitInput(),this.emitFile(r,n),r)}return!1},emitFilter:function(e,t){var n=!1;return this.$emit("input-filter",e,t,function(){var e=!(arguments.length>0&&void 0!==arguments[0])||arguments[0];return n=e,n}),n},emitFile:function(e,t){var n,r=this;this.$emit("input-file",e,t),null===(n=e)||void 0===n||!n.fileObject||!e.active||t&&t.active?e&&e.fileObject&&e.active||!t||!t.fileObject||!t.active||this.uploading--:(this.uploading++,this.$nextTick(function(){setTimeout(function(){e&&r.upload(e).then(function(){var t;e&&(e=r.get(e)||void 0),null!==(t=e)&&void 0!==t&&t.fileObject&&r.update(e,{active:!1,success:!e.error})}).catch(function(t){e&&r.update(e,{active:!1,success:!1,error:t.code||t.error||t.message||t})})},Math.ceil(50*Math.random()+50))})),!this.active||Boolean(e)===Boolean(t)&&e.active===t.active||this.watchActive(!0)},emitInput:function(){this.$emit("update:modelValue",this.files)},upload:function(e){var t=this.get(e);if(!t)return Promise.reject(new Error("not_exists"));if(!t.fileObject)return Promise.reject(new Error("file_object"));if(t.error)return t.error instanceof Error?Promise.reject(t.error):Promise.reject(new Error(t.error));if(t.success)return Promise.resolve(t);if(t.name&&this.iExtensions&&"text/directory"!==t.type&&-1===t.name.search(this.iExtensions))return Promise.reject(new Error("extension"));if(this.size>0&&void 0!==t.size&&t.size>=0&&t.size>this.size&&"text/directory"!==t.type)return Promise.reject(new Error("size"));if(this.customAction)return this.customAction(t,this);if(this.features.html5){if(this.shouldUseChunkUpload(t))return this.uploadChunk(t);if(t.putAction)return this.uploadPut(t);if(t.postAction)return this.uploadHtml5(t)}return t.postAction?this.uploadHtml4(t):Promise.reject(new Error("No action configured"))},shouldUseChunkUpload:function(e){return this.chunkEnabled&&!!this.chunkOptions.handler&&e.size&&e.size>this.chunkOptions.minSize},uploadChunk:function(e){var t=this.chunkOptions.handler;return e.chunk=new t(e,this.chunkOptions),e.chunk.upload().then(function(t){return e})},uploadPut:function(e){var t,n=[];for(var r in e.data)t=e.data[r],null!==t&&void 0!==t&&n.push(encodeURIComponent(r)+"="+encodeURIComponent(t));var o=e.putAction||"",i=n.length?(-1===o.indexOf("?")?"?":"&")+n.join("&"):"",s=new XMLHttpRequest;return s.open("PUT",o+i),this.uploadXhr(s,e,e.file)},uploadHtml5:function(e){var t,n=new window.FormData;for(var r in e.data)t=e.data[r],t&&"object"===c(t)&&"function"!==typeof t.toString?t instanceof File?n.append(r,t,t.name):n.append(r,JSON.stringify(t)):null!==t&&void 0!==t&&n.append(r,t);n.append(this.name,e.file,e.name||e.file.name||e.file.filename);var o=new XMLHttpRequest;return o.open("POST",e.postAction||""),this.uploadXhr(o,e,n)},uploadXhr:function(e,t,n){var r=this,o=t,i=0,s=0;e.upload.onprogress=function(e){if(o&&(o=r.get(o),e.lengthComputable&&o&&o.fileObject&&o.active)){var t=Math.round(Date.now()/1e3);t!==i&&(i=t,o=r.update(o,{progress:(e.loaded/e.total*100).toFixed(2),speed:e.loaded-s}),s=e.loaded)}};var a=window.setInterval(function(){var t;if(o&&((o=r.get(o))&&null!==(t=o)&&void 0!==t&&t.fileObject&&!o.success&&!o.error&&o.active))return;a&&(clearInterval(a),a=void 0);try{e.abort(),e.timeout=1}catch(n){}},100);return new Promise(function(t,i){if(o){var s,l=function(n){if(!s){if(s=!0,a&&(clearInterval(a),a=void 0),!o)return i(new Error("not_exists"));if(o=r.get(o),!o)return i(new Error("not_exists"));if(!o.fileObject)return i(new Error("file_object"));if(o.error)return o.error instanceof Error?i(o.error):i(new Error(o.error));if(!o.active)return i(new Error("abort"));if(o.success)return t(o);var l={};switch(n.type){case"timeout":case"abort":l.error=n.type;break;case"error":e.status?e.status>=500?l.error="server":e.status>=400&&(l.error="denied"):l.error="network";break;default:e.status>=500?l.error="server":e.status>=400?l.error="denied":l.progress="100.00"}if(e.responseText){var u=e.getResponseHeader("Content-Type");u&&-1!==u.indexOf("/json")?l.response=JSON.parse(e.responseText):l.response=e.responseText}return o=r.update(o,l),o?o.error?o.error instanceof Error?i(o.error):i(new Error(o.error)):t(o):i(new Error("abort"))}};for(var u in e.onload=l,e.onerror=l,e.onabort=l,e.ontimeout=l,o.timeout&&(e.timeout=o.timeout),o.headers)e.setRequestHeader(u,o.headers[u]);o=r.update(o,{xhr:e}),o&&e.send(n)}else i(new Error("not_exists"))})},uploadHtml4:function(e){var t=this,n=e;if(!n)return Promise.reject(new Error("not_exists"));var r=function(e){27===e.keyCode&&e.preventDefault()},o=document.createElement("iframe");o.id="upload-iframe-"+n.id,o.name="upload-iframe-"+n.id,o.src="about:blank",o.setAttribute("style","width:1px;height:1px;top:-999em;position:absolute; margin-top:-999em;");var i=document.createElement("form");for(var s in i.setAttribute("action",n.postAction||""),i.name="upload-form-"+n.id,i.setAttribute("method","POST"),i.setAttribute("target","upload-iframe-"+n.id),i.setAttribute("enctype","multipart/form-data"),n.data){var a=n.data[s];if(a&&"object"===c(a)&&"function"!==typeof a.toString&&(a=JSON.stringify(a)),null!==a&&void 0!==a){var l=document.createElement("input");l.type="hidden",l.name=s,l.value=a,i.appendChild(l)}}i.appendChild(n.el),document.body.appendChild(o).appendChild(i);var u=function(){var e,t;try{o.contentWindow&&(t=o.contentWindow.document)}catch(n){}if(!t)try{t=o.contentDocument?o.contentDocument:o.document}catch(n){t=o.document}return null!==(e=t)&&void 0!==e&&e.body?t.body.innerHTML:null};return new Promise(function(e,s){setTimeout(function(){if(n){if(n=t.update(n,{iframe:o}),!n)return s(new Error("not_exists"));var a,l=window.setInterval(function(){n&&(n=t.get(n))&&n.fileObject&&!n.success&&!n.error&&n.active||(l&&(clearInterval(l),l=void 0),o.onabort({type:n?"abort":"not_exists"}))},100),c=function(o){var i;if(!a){if(a=!0,l&&(clearInterval(l),l=void 0),document.body.removeEventListener("keydown",r),!n)return s(new Error("not_exists"));if(n=t.get(n),!n)return s(new Error("not_exists"));if(!n.fileObject)return s(new Error("file_object"));if(n.error)return n.error instanceof Error?s(n.error):s(new Error(n.error));if(!n.active)return s(new Error("abort"));if(n.success)return e(n);var c=u(),d={};if("string"===typeof o)return s(new Error(o));switch(o.type){case"abort":d.error="abort";break;case"error":n.error?d.error=n.error:d.error=null===c?"network":"denied";break;default:n.error?d.error=n.error:null===c?d.error="network":d.progress="100.00"}if(null!==c){if(c&&"{"===c.substr(0,1)&&"}"===c.substr(c.length-1,1))try{c=JSON.parse(c)}catch(f){}d.response=c}return n=t.update(n,d),n?null!==(i=n)&&void 0!==i&&i.error?n.error instanceof Error?s(n.error):s(new Error(n.error)):e(n):s(new Error("not_exists"))}};o.onload=c,o.onerror=c,o.onabort=c,document.body.addEventListener("keydown",r),i.submit()}else s(new Error("not_exists"))},50)}).then(function(e){var t;return null===o||void 0===o||null===(t=o.parentNode)||void 0===t||t.removeChild(o),e}).catch(function(e){var t;return null===o||void 0===o||null===(t=o.parentNode)||void 0===t||t.removeChild(o),e})},watchActive:function(e){var t,n=0;while(t=this.files[n])if(n++,t.fileObject)if(e&&!this.destroy){if(this.uploading>=this.thread||this.uploading&&!this.features.html5)break;t.active||t.error||t.success||this.update(t,{active:!0})}else t.active&&this.update(t,{active:!1});else;0===this.uploading&&(this.active=!1)},watchDrop:function(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:void 0;if(this.features.drop&&e!==t){if(this.dropElement)try{document.removeEventListener("dragenter",this.onDocumentDragenter,!1),document.removeEventListener("dragleave",this.onDocumentDragleave,!1),document.removeEventListener("dragover",this.onDocumentDragover,!1),document.removeEventListener("drop",this.onDocumentDrop,!1),this.dropElement.removeEventListener("dragenter",this.onDragenter,!1),this.dropElement.removeEventListener("dragleave",this.onDragleave,!1),this.dropElement.removeEventListener("dragover",this.onDragover,!1),this.dropElement.removeEventListener("drop",this.onDrop,!1)}catch(i){}var n=null;if(e)if("string"===typeof e)n=document.querySelector(e)||this.$root.$el.querySelector(e);else if(!0===e){var r,o;if(n=this.$parent.$el,!n||8===(null===(r=n)||void 0===r?void 0:r.nodeType))n=this.$root.$el,n&&8!==(null===(o=n)||void 0===o?void 0:o.nodeType)||(n=document.body)}else n=e;else;this.dropElement=n,this.dropElement&&(document.addEventListener("dragenter",this.onDocumentDragenter,!1),document.addEventListener("dragleave",this.onDocumentDragleave,!1),document.addEventListener("dragover",this.onDocumentDragover,!1),document.addEventListener("drop",this.onDocumentDrop,!1),this.dropElement.addEventListener("dragenter",this.onDragenter,!1),this.dropElement.addEventListener("dragleave",this.onDragleave,!1),this.dropElement.addEventListener("dragover",this.onDragover,!1),this.dropElement.addEventListener("drop",this.onDrop,!1))}},watchDropActive:function(e,t){e!==t&&(!e&&this.dropElementActive&&(this.dropElementActive=!1),this.dropTimeout&&(clearTimeout(this.dropTimeout),this.dropTimeout=null),e&&(this.dropTimeout=setTimeout(this.onDocumentDrop,1e3)))},onDocumentDragenter:function(e){var t,n;if(!this.dropActive&&e.dataTransfer){var r=e.dataTransfer;null!==r&&void 0!==r&&null!==(t=r.files)&&void 0!==t&&t.length?this.dropActive=!0:r.types?(r.types.indexOf&&-1!==r.types.indexOf("Files")||null!==(n=r.types)&&void 0!==n&&n.contains&&r.types.contains("Files"))&&(this.dropActive=!0):this.dropActive=!0,this.dropActive&&this.watchDropActive(!0)}},onDocumentDragleave:function(e){this.dropActive&&(e.target===e.explicitOriginalTarget||!e.fromElement&&(e.clientX<=0||e.clientY<=0||e.clientX>=window.innerWidth||e.clientY>=window.innerHeight))&&(this.dropActive=!1,this.watchDropActive(!1))},onDocumentDragover:function(){this.watchDropActive(!0)},onDocumentDrop:function(){this.dropActive=!1,this.watchDropActive(!1)},onDragenter:function(e){this.dropActive&&!this.dropElementActive&&(this.dropElementActive=!0)},onDragleave:function(e){var t;if(this.dropElementActive){var n=e.relatedTarget;if(n)if(null!==(t=this.dropElement)&&void 0!==t&&t.contains)this.dropElement.contains(n)||(this.dropElementActive=!1);else{var r=n;while(r){if(r===this.dropElement)break;r=r.parentNode}r!==this.dropElement&&(this.dropElementActive=!1)}else this.dropElementActive=!1}},onDragover:function(e){e.preventDefault()},onDrop:function(e){e.preventDefault(),e.dataTransfer&&this.addDataTransfer(e.dataTransfer)},inputOnChange:async function(e){var t=this;if(!(e.target instanceof HTMLInputElement))return Promise.reject(new Error("not HTMLInputElement"));e.target;var n=function(e){return t.reload=!0,t.$nextTick(function(){t.reload=!1}),e};return this.addInputFile(e.target).then(n).catch(n)},isRelatedTargetSupported:function(){try{var e=new MouseEvent("mouseout",{relatedTarget:document.body});return"relatedTarget"in e}catch(t){return!1}}}}),T=["for"],k=["name","id","accept","capture","disabled","webkitdirectory","allowdirs","directory","multiple"];function C(t,n,r,o,i,s){return e.openBlock(),e.createElementBlock("span",{class:e.normalizeClass(t.className)},[e.renderSlot(t.$slots,"default"),e.createElementVNode("label",{for:t.forId},null,8,T),t.reload?e.createCommentVNode("",!0):(e.openBlock(),e.createElementBlock("input",{key:0,ref:"input",type:"file",name:t.name,id:t.forId,accept:t.accept,capture:t.capture,disabled:t.disabled,webkitdirectory:t.iDirectory,allowdirs:t.iDirectory,directory:t.iDirectory,multiple:t.multiple&&t.features.html5,onChange:n[0]||(n[0]=function(){return t.inputOnChange&&t.inputOnChange.apply(t,arguments)})},null,40,k))],2)}function O(e,t){void 0===t&&(t={});var n=t.insertAt;if(e&&"undefined"!==typeof document){var r=document.head||document.getElementsByTagName("head")[0],o=document.createElement("style");o.type="text/css","top"===n&&r.firstChild?r.insertBefore(o,r.firstChild):r.appendChild(o),o.styleSheet?o.styleSheet.cssText=e:o.appendChild(document.createTextNode(e))}}var A="\n.file-uploads {\n  overflow: hidden;\n  position: relative;\n  text-align: center;\n  display: inline-block;\n}\n.file-uploads.file-uploads-html4 input,\n.file-uploads.file-uploads-html5 label {\n  /* background fix ie  click */\n  background: #fff;\n  opacity: 0;\n  font-size: 20em;\n  z-index: 1;\n  top: 0;\n  left: 0;\n  right: 0;\n  bottom: 0;\n  position: absolute;\n  width: 100%;\n  height: 100%;\n}\n.file-uploads.file-uploads-html5 input,\n.file-uploads.file-uploads-html4 label {\n  /* background fix ie  click */\n  position: absolute;\n  background: rgba(255, 255, 255, 0);\n  overflow: hidden;\n  position: fixed;\n  width: 1px;\n  height: 1px;\n  z-index: -1;\n  opacity: 0;\n}\n";return O(A),S.render=C,S})},8756:function(e,t,n){"use strict";n.r(t),n.d(t,{BaseTransition:function(){return r.pR},BaseTransitionPropsValidators:function(){return r.QP},Comment:function(){return r.Mw},DeprecationTypes:function(){return r.aT},EffectScope:function(){return r.yC},ErrorCodes:function(){return r.tG},ErrorTypeStrings:function(){return r.ZQ},Fragment:function(){return r.FK},KeepAlive:function(){return r.PR},ReactiveEffect:function(){return r.X2},Static:function(){return r.jC},Suspense:function(){return r.tY},Teleport:function(){return r.Im},Text:function(){return r.EY},TrackOpTypes:function(){return r.Ul},Transition:function(){return r.eB},TransitionGroup:function(){return r.F},TriggerOpTypes:function(){return r.PP},VueElement:function(){return r.Vy},assertNumber:function(){return r.U4},callWithAsyncErrorHandling:function(){return r.qL},callWithErrorHandling:function(){return r.gh},camelize:function(){return r.PT},capitalize:function(){return r.ZH},cloneVNode:function(){return r.E3},compatUtils:function(){return r.Y5},compile:function(){return o},computed:function(){return r.EW},createApp:function(){return r.Ef},createBlock:function(){return r.Wv},createCommentVNode:function(){return r.Q3},createElementBlock:function(){return r.CE},createElementVNode:function(){return r.Lk},createHydrationRenderer:function(){return r.ci},createPropsRestProxy:function(){return r.bn},createRenderer:function(){return r.K9},createSSRApp:function(){return r.m1},createSlots:function(){return r.eX},createStaticVNode:function(){return r.Fv},createTextVNode:function(){return r.eW},createVNode:function(){return r.bF},customRef:function(){return r.rY},defineAsyncComponent:function(){return r.$V},defineComponent:function(){return r.pM},defineCustomElement:function(){return r.Xq},defineEmits:function(){return r.qP},defineExpose:function(){return r.wk},defineModel:function(){return r.NP},defineOptions:function(){return r.GM},defineProps:function(){return r.Yj},defineSSRCustomElement:function(){return r.Po},defineSlots:function(){return r.Lu},devtools:function(){return r.lt},effect:function(){return r.QZ},effectScope:function(){return r.uY},getCurrentInstance:function(){return r.nI},getCurrentScope:function(){return r.o5},getCurrentWatcher:function(){return r.Yv},getTransitionRawChildren:function(){return r.Df},guardReactiveProps:function(){return r.Ng},h:function(){return r.h},handleError:function(){return r.H4},hasInjectionContext:function(){return r.PS},hydrate:function(){return r.Qv},hydrateOnIdle:function(){return r.rU},hydrateOnInteraction:function(){return r.Tq},hydrateOnMediaQuery:function(){return r.dA},hydrateOnVisible:function(){return r.Pn},initCustomFormatter:function(){return r.y$},initDirectivesForSSR:function(){return r.Ib},inject:function(){return r.WQ},isMemoSame:function(){return r.Bs},isProxy:function(){return r.ju},isReactive:function(){return r.g8},isReadonly:function(){return r.Tm},isRef:function(){return r.i9},isRuntimeOnly:function(){return r.wX},isShallow:function(){return r.fE},isVNode:function(){return r.vv},markRaw:function(){return r.IG},mergeDefaults:function(){return r.HF},mergeModels:function(){return r.zz},mergeProps:function(){return r.v6},nextTick:function(){return r.dY},nodeOps:function(){return r.RD},normalizeClass:function(){return r.C4},normalizeProps:function(){return r._B},normalizeStyle:function(){return r.Tr},onActivated:function(){return r.n},onBeforeMount:function(){return r.KC},onBeforeUnmount:function(){return r.xo},onBeforeUpdate:function(){return r.Ic},onDeactivated:function(){return r.Y4},onErrorCaptured:function(){return r.qG},onMounted:function(){return r.sV},onRenderTracked:function(){return r.qR},onRenderTriggered:function(){return r.bj},onScopeDispose:function(){return r.jr},onServerPrefetch:function(){return r.SS},onUnmounted:function(){return r.hi},onUpdated:function(){return r.$u},onWatcherCleanup:function(){return r.ch},openBlock:function(){return r.uX},patchProp:function(){return r.GI},popScopeId:function(){return r.jt},provide:function(){return r.Gt},proxyRefs:function(){return r.Pr},pushScopeId:function(){return r.Qi},queuePostFlushCb:function(){return r.Dl},reactive:function(){return r.Kh},readonly:function(){return r.tB},ref:function(){return r.KR},registerRuntimeCompiler:function(){return r.tC},render:function(){return r.XX},renderList:function(){return r.pI},renderSlot:function(){return r.RG},resolveComponent:function(){return r.g2},resolveDirective:function(){return r.gN},resolveDynamicComponent:function(){return r.$y},resolveFilter:function(){return r.LJ},resolveTransitionHooks:function(){return r.OW},setBlockTracking:function(){return r.Vq},setDevtoolsHook:function(){return r.iD},setTransitionHooks:function(){return r.MZ},shallowReactive:function(){return r.Gc},shallowReadonly:function(){return r.nD},shallowRef:function(){return r.IJ},ssrContextKey:function(){return r.Fw},ssrUtils:function(){return r.Gw},stop:function(){return r.ds},toDisplayString:function(){return r.v_},toHandlerKey:function(){return r.Kf},toHandlers:function(){return r.Tb},toRaw:function(){return r.ux},toRef:function(){return r.lW},toRefs:function(){return r.QW},toValue:function(){return r.BA},transformVNodeArgs:function(){return r.gW},triggerRef:function(){return r.mu},unref:function(){return r.R1},useAttrs:function(){return r.OA},useCssModule:function(){return r.D},useCssVars:function(){return r.$9},useHost:function(){return r.KT},useId:function(){return r.Bi},useModel:function(){return r.fn},useSSRContext:function(){return r.LM},useShadowRoot:function(){return r._U},useSlots:function(){return r.Ht},useTemplateRef:function(){return r.rk},useTransitionState:function(){return r.Gy},vModelCheckbox:function(){return r.lH},vModelDynamic:function(){return r.hp},vModelRadio:function(){return r.XL},vModelSelect:function(){return r.u1},vModelText:function(){return r.Jo},vShow:function(){return r.aG},version:function(){return r.rE},warn:function(){return r.R8},watch:function(){return r.wB},watchEffect:function(){return r.nT},watchPostEffect:function(){return r.p9},watchSyncEffect:function(){return r.U_},withAsyncContext:function(){return r.E},withCtx:function(){return r.k6},withDefaults:function(){return r.rO},withDirectives:function(){return r.bo},withKeys:function(){return r.jR},withMemo:function(){return r.bU},withModifiers:function(){return r.D$},withScopeId:function(){return r.YY}});var r=n(3751);
/**
* vue v3.5.32
* (c) 2018-present Yuxi (Evan) You and Vue contributors
* @license MIT
**/const o=()=>{0}},6278:function(e,t,n){"use strict";n.d(t,{y$:function(){return ee},i0:function(){return se},L8:function(){return ie},PY:function(){return oe},aH:function(){return re}});var r=n(641),o=n(953);function i(){return s().__VUE_DEVTOOLS_GLOBAL_HOOK__}function s(){return"undefined"!==typeof navigator&&"undefined"!==typeof window?window:"undefined"!==typeof globalThis?globalThis:{}}const a="function"===typeof Proxy,l="devtools-plugin:setup",u="plugin:settings:set";let c,d;function f(){var e;return void 0!==c||("undefined"!==typeof window&&window.performance?(c=!0,d=window.performance):"undefined"!==typeof globalThis&&(null===(e=globalThis.perf_hooks)||void 0===e?void 0:e.performance)?(c=!0,d=globalThis.perf_hooks.performance):c=!1),c}function h(){return f()?d.now():Date.now()}class p{constructor(e,t){this.target=null,this.targetQueue=[],this.onQueue=[],this.plugin=e,this.hook=t;const n={};if(e.settings)for(const s in e.settings){const t=e.settings[s];n[s]=t.defaultValue}const r=`__vue-devtools-plugin-settings__${e.id}`;let o=Object.assign({},n);try{const e=localStorage.getItem(r),t=JSON.parse(e);Object.assign(o,t)}catch(i){}this.fallbacks={getSettings(){return o},setSettings(e){try{localStorage.setItem(r,JSON.stringify(e))}catch(i){}o=e},now(){return h()}},t&&t.on(u,(e,t)=>{e===this.plugin.id&&this.fallbacks.setSettings(t)}),this.proxiedOn=new Proxy({},{get:(e,t)=>this.target?this.target.on[t]:(...e)=>{this.onQueue.push({method:t,args:e})}}),this.proxiedTarget=new Proxy({},{get:(e,t)=>this.target?this.target[t]:"on"===t?this.proxiedOn:Object.keys(this.fallbacks).includes(t)?(...e)=>(this.targetQueue.push({method:t,args:e,resolve:()=>{}}),this.fallbacks[t](...e)):(...e)=>new Promise(n=>{this.targetQueue.push({method:t,args:e,resolve:n})})})}async setRealTarget(e){this.target=e;for(const t of this.onQueue)this.target.on[t.method](...t.args);for(const t of this.targetQueue)t.resolve(await this.target[t.method](...t.args))}}function m(e,t){const n=e,r=s(),o=i(),u=a&&n.enableEarlyProxy;if(!o||!r.__VUE_DEVTOOLS_PLUGIN_API_AVAILABLE__&&u){const e=u?new p(n,o):null,i=r.__VUE_DEVTOOLS_PLUGINS__=r.__VUE_DEVTOOLS_PLUGINS__||[];i.push({pluginDescriptor:n,setupFn:t,proxy:e}),e&&t(e.proxiedTarget)}else o.emit(l,e,t)}
/*!
 * vuex v4.1.0
 * (c) 2022 Evan You
 * @license MIT
 */
var v="store";function g(e,t){Object.keys(e).forEach(function(n){return t(e[n],n)})}function y(e){return null!==e&&"object"===typeof e}function b(e){return e&&"function"===typeof e.then}function _(e,t){return function(){return e(t)}}function E(e,t,n){return t.indexOf(e)<0&&(n&&n.prepend?t.unshift(e):t.push(e)),function(){var n=t.indexOf(e);n>-1&&t.splice(n,1)}}function w(e,t){e._actions=Object.create(null),e._mutations=Object.create(null),e._wrappedGetters=Object.create(null),e._modulesNamespaceMap=Object.create(null);var n=e.state;T(e,n,[],e._modules.root,!0),S(e,n,t)}function S(e,t,n){var i=e._state,s=e._scope;e.getters={},e._makeLocalGettersCache=Object.create(null);var a=e._wrappedGetters,l={},u={},c=(0,o.uY)(!0);c.run(function(){g(a,function(t,n){l[n]=_(t,e),u[n]=(0,r.EW)(function(){return l[n]()}),Object.defineProperty(e.getters,n,{get:function(){return u[n].value},enumerable:!0})})}),e._state=(0,o.Kh)({data:t}),e._scope=c,e.strict&&I(e),i&&n&&e._withCommit(function(){i.data=null}),s&&s.stop()}function T(e,t,n,r,o){var i=!n.length,s=e._modules.getNamespace(n);if(r.namespaced&&(e._modulesNamespaceMap[s],e._modulesNamespaceMap[s]=r),!i&&!o){var a=N(t,n.slice(0,-1)),l=n[n.length-1];e._withCommit(function(){a[l]=r.state})}var u=r.context=k(e,s,n);r.forEachMutation(function(t,n){var r=s+n;O(e,r,t,u)}),r.forEachAction(function(t,n){var r=t.root?n:s+n,o=t.handler||t;A(e,r,o,u)}),r.forEachGetter(function(t,n){var r=s+n;R(e,r,t,u)}),r.forEachChild(function(r,i){T(e,t,n.concat(i),r,o)})}function k(e,t,n){var r=""===t,o={dispatch:r?e.dispatch:function(n,r,o){var i=L(n,r,o),s=i.payload,a=i.options,l=i.type;return a&&a.root||(l=t+l),e.dispatch(l,s)},commit:r?e.commit:function(n,r,o){var i=L(n,r,o),s=i.payload,a=i.options,l=i.type;a&&a.root||(l=t+l),e.commit(l,s,a)}};return Object.defineProperties(o,{getters:{get:r?function(){return e.getters}:function(){return C(e,t)}},state:{get:function(){return N(e.state,n)}}}),o}function C(e,t){if(!e._makeLocalGettersCache[t]){var n={},r=t.length;Object.keys(e.getters).forEach(function(o){if(o.slice(0,r)===t){var i=o.slice(r);Object.defineProperty(n,i,{get:function(){return e.getters[o]},enumerable:!0})}}),e._makeLocalGettersCache[t]=n}return e._makeLocalGettersCache[t]}function O(e,t,n,r){var o=e._mutations[t]||(e._mutations[t]=[]);o.push(function(t){n.call(e,r.state,t)})}function A(e,t,n,r){var o=e._actions[t]||(e._actions[t]=[]);o.push(function(t){var o=n.call(e,{dispatch:r.dispatch,commit:r.commit,getters:r.getters,state:r.state,rootGetters:e.getters,rootState:e.state},t);return b(o)||(o=Promise.resolve(o)),e._devtoolHook?o.catch(function(t){throw e._devtoolHook.emit("vuex:error",t),t}):o})}function R(e,t,n,r){e._wrappedGetters[t]||(e._wrappedGetters[t]=function(e){return n(r.state,r.getters,e.state,e.getters)})}function I(e){(0,r.wB)(function(){return e._state.data},function(){0},{deep:!0,flush:"sync"})}function N(e,t){return t.reduce(function(e,t){return e[t]},e)}function L(e,t,n){return y(e)&&e.type&&(n=t,t=e,e=e.type),{type:e,payload:t,options:n}}var x="vuex bindings",P="vuex:mutations",D="vuex:actions",M="vuex",F=0;function $(e,t){m({id:"org.vuejs.vuex",app:e,label:"Vuex",homepage:"https://next.vuex.vuejs.org/",logo:"https://vuejs.org/images/icons/favicon-96x96.png",packageName:"vuex",componentStateTypes:[x]},function(n){n.addTimelineLayer({id:P,label:"Vuex Mutations",color:j}),n.addTimelineLayer({id:D,label:"Vuex Actions",color:j}),n.addInspector({id:M,label:"Vuex",icon:"storage",treeFilterPlaceholder:"Filter stores..."}),n.on.getInspectorTree(function(n){if(n.app===e&&n.inspectorId===M)if(n.filter){var r=[];W(r,t._modules.root,n.filter,""),n.rootNodes=r}else n.rootNodes=[H(t._modules.root,"")]}),n.on.getInspectorState(function(n){if(n.app===e&&n.inspectorId===M){var r=n.nodeId;C(t,r),n.state=X(q(t._modules,r),"root"===r?t.getters:t._makeLocalGettersCache,r)}}),n.on.editInspectorState(function(n){if(n.app===e&&n.inspectorId===M){var r=n.nodeId,o=n.path;"root"!==r&&(o=r.split("/").filter(Boolean).concat(o)),t._withCommit(function(){n.set(t._state.data,o,n.state.value)})}}),t.subscribe(function(e,t){var r={};e.payload&&(r.payload=e.payload),r.state=t,n.notifyComponentUpdate(),n.sendInspectorTree(M),n.sendInspectorState(M),n.addTimelineEvent({layerId:P,event:{time:Date.now(),title:e.type,data:r}})}),t.subscribeAction({before:function(e,t){var r={};e.payload&&(r.payload=e.payload),e._id=F++,e._time=Date.now(),r.state=t,n.addTimelineEvent({layerId:D,event:{time:e._time,title:e.type,groupId:e._id,subtitle:"start",data:r}})},after:function(e,t){var r={},o=Date.now()-e._time;r.duration={_custom:{type:"duration",display:o+"ms",tooltip:"Action duration",value:o}},e.payload&&(r.payload=e.payload),r.state=t,n.addTimelineEvent({layerId:D,event:{time:Date.now(),title:e.type,groupId:e._id,subtitle:"end",data:r}})}})})}var j=8702998,U=6710886,B=16777215,V={label:"namespaced",textColor:B,backgroundColor:U};function G(e){return e&&"root"!==e?e.split("/").slice(-2,-1)[0]:"Root"}function H(e,t){return{id:t||"root",label:G(t),tags:e.namespaced?[V]:[],children:Object.keys(e._children).map(function(n){return H(e._children[n],t+n+"/")})}}function W(e,t,n,r){r.includes(n)&&e.push({id:r||"root",label:r.endsWith("/")?r.slice(0,r.length-1):r||"Root",tags:t.namespaced?[V]:[]}),Object.keys(t._children).forEach(function(o){W(e,t._children[o],n,r+o+"/")})}function X(e,t,n){t="root"===n?t:t[n];var r=Object.keys(t),o={state:Object.keys(e.state).map(function(t){return{key:t,editable:!0,value:e.state[t]}})};if(r.length){var i=K(t);o.getters=Object.keys(i).map(function(e){return{key:e.endsWith("/")?G(e):e,editable:!1,value:z(function(){return i[e]})}})}return o}function K(e){var t={};return Object.keys(e).forEach(function(n){var r=n.split("/");if(r.length>1){var o=t,i=r.pop();r.forEach(function(e){o[e]||(o[e]={_custom:{value:{},display:e,tooltip:"Module",abstract:!0}}),o=o[e]._custom.value}),o[i]=z(function(){return e[n]})}else t[n]=z(function(){return e[n]})}),t}function q(e,t){var n=t.split("/").filter(function(e){return e});return n.reduce(function(e,r,o){var i=e[r];if(!i)throw new Error('Missing module "'+r+'" for path "'+t+'".');return o===n.length-1?i:i._children},"root"===t?e:e.root._children)}function z(e){try{return e()}catch(t){return t}}var Y=function(e,t){this.runtime=t,this._children=Object.create(null),this._rawModule=e;var n=e.state;this.state=("function"===typeof n?n():n)||{}},Q={namespaced:{configurable:!0}};Q.namespaced.get=function(){return!!this._rawModule.namespaced},Y.prototype.addChild=function(e,t){this._children[e]=t},Y.prototype.removeChild=function(e){delete this._children[e]},Y.prototype.getChild=function(e){return this._children[e]},Y.prototype.hasChild=function(e){return e in this._children},Y.prototype.update=function(e){this._rawModule.namespaced=e.namespaced,e.actions&&(this._rawModule.actions=e.actions),e.mutations&&(this._rawModule.mutations=e.mutations),e.getters&&(this._rawModule.getters=e.getters)},Y.prototype.forEachChild=function(e){g(this._children,e)},Y.prototype.forEachGetter=function(e){this._rawModule.getters&&g(this._rawModule.getters,e)},Y.prototype.forEachAction=function(e){this._rawModule.actions&&g(this._rawModule.actions,e)},Y.prototype.forEachMutation=function(e){this._rawModule.mutations&&g(this._rawModule.mutations,e)},Object.defineProperties(Y.prototype,Q);var J=function(e){this.register([],e,!1)};function Z(e,t,n){if(t.update(n),n.modules)for(var r in n.modules){if(!t.getChild(r))return void 0;Z(e.concat(r),t.getChild(r),n.modules[r])}}J.prototype.get=function(e){return e.reduce(function(e,t){return e.getChild(t)},this.root)},J.prototype.getNamespace=function(e){var t=this.root;return e.reduce(function(e,n){return t=t.getChild(n),e+(t.namespaced?n+"/":"")},"")},J.prototype.update=function(e){Z([],this.root,e)},J.prototype.register=function(e,t,n){var r=this;void 0===n&&(n=!0);var o=new Y(t,n);if(0===e.length)this.root=o;else{var i=this.get(e.slice(0,-1));i.addChild(e[e.length-1],o)}t.modules&&g(t.modules,function(t,o){r.register(e.concat(o),t,n)})},J.prototype.unregister=function(e){var t=this.get(e.slice(0,-1)),n=e[e.length-1],r=t.getChild(n);r&&r.runtime&&t.removeChild(n)},J.prototype.isRegistered=function(e){var t=this.get(e.slice(0,-1)),n=e[e.length-1];return!!t&&t.hasChild(n)};function ee(e){return new te(e)}var te=function(e){var t=this;void 0===e&&(e={});var n=e.plugins;void 0===n&&(n=[]);var r=e.strict;void 0===r&&(r=!1);var o=e.devtools;this._committing=!1,this._actions=Object.create(null),this._actionSubscribers=[],this._mutations=Object.create(null),this._wrappedGetters=Object.create(null),this._modules=new J(e),this._modulesNamespaceMap=Object.create(null),this._subscribers=[],this._makeLocalGettersCache=Object.create(null),this._scope=null,this._devtools=o;var i=this,s=this,a=s.dispatch,l=s.commit;this.dispatch=function(e,t){return a.call(i,e,t)},this.commit=function(e,t,n){return l.call(i,e,t,n)},this.strict=r;var u=this._modules.root.state;T(this,u,[],this._modules.root),S(this,u),n.forEach(function(e){return e(t)})},ne={state:{configurable:!0}};te.prototype.install=function(e,t){e.provide(t||v,this),e.config.globalProperties.$store=this;var n=void 0!==this._devtools&&this._devtools;n&&$(e,this)},ne.state.get=function(){return this._state.data},ne.state.set=function(e){0},te.prototype.commit=function(e,t,n){var r=this,o=L(e,t,n),i=o.type,s=o.payload,a=(o.options,{type:i,payload:s}),l=this._mutations[i];l&&(this._withCommit(function(){l.forEach(function(e){e(s)})}),this._subscribers.slice().forEach(function(e){return e(a,r.state)}))},te.prototype.dispatch=function(e,t){var n=this,r=L(e,t),o=r.type,i=r.payload,s={type:o,payload:i},a=this._actions[o];if(a){try{this._actionSubscribers.slice().filter(function(e){return e.before}).forEach(function(e){return e.before(s,n.state)})}catch(u){0}var l=a.length>1?Promise.all(a.map(function(e){return e(i)})):a[0](i);return new Promise(function(e,t){l.then(function(t){try{n._actionSubscribers.filter(function(e){return e.after}).forEach(function(e){return e.after(s,n.state)})}catch(u){0}e(t)},function(e){try{n._actionSubscribers.filter(function(e){return e.error}).forEach(function(t){return t.error(s,n.state,e)})}catch(u){0}t(e)})})}},te.prototype.subscribe=function(e,t){return E(e,this._subscribers,t)},te.prototype.subscribeAction=function(e,t){var n="function"===typeof e?{before:e}:e;return E(n,this._actionSubscribers,t)},te.prototype.watch=function(e,t,n){var o=this;return(0,r.wB)(function(){return e(o.state,o.getters)},t,Object.assign({},n))},te.prototype.replaceState=function(e){var t=this;this._withCommit(function(){t._state.data=e})},te.prototype.registerModule=function(e,t,n){void 0===n&&(n={}),"string"===typeof e&&(e=[e]),this._modules.register(e,t),T(this,this.state,e,this._modules.get(e),n.preserveState),S(this,this.state)},te.prototype.unregisterModule=function(e){var t=this;"string"===typeof e&&(e=[e]),this._modules.unregister(e),this._withCommit(function(){var n=N(t.state,e.slice(0,-1));delete n[e[e.length-1]]}),w(this)},te.prototype.hasModule=function(e){return"string"===typeof e&&(e=[e]),this._modules.isRegistered(e)},te.prototype.hotUpdate=function(e){this._modules.update(e),w(this,!0)},te.prototype._withCommit=function(e){var t=this._committing;this._committing=!0,e(),this._committing=t},Object.defineProperties(te.prototype,ne);var re=ue(function(e,t){var n={};return ae(t).forEach(function(t){var r=t.key,o=t.val;n[r]=function(){var t=this.$store.state,n=this.$store.getters;if(e){var r=ce(this.$store,"mapState",e);if(!r)return;t=r.context.state,n=r.context.getters}return"function"===typeof o?o.call(this,t,n):t[o]},n[r].vuex=!0}),n}),oe=ue(function(e,t){var n={};return ae(t).forEach(function(t){var r=t.key,o=t.val;n[r]=function(){var t=[],n=arguments.length;while(n--)t[n]=arguments[n];var r=this.$store.commit;if(e){var i=ce(this.$store,"mapMutations",e);if(!i)return;r=i.context.commit}return"function"===typeof o?o.apply(this,[r].concat(t)):r.apply(this.$store,[o].concat(t))}}),n}),ie=ue(function(e,t){var n={};return ae(t).forEach(function(t){var r=t.key,o=t.val;o=e+o,n[r]=function(){if(!e||ce(this.$store,"mapGetters",e))return this.$store.getters[o]},n[r].vuex=!0}),n}),se=ue(function(e,t){var n={};return ae(t).forEach(function(t){var r=t.key,o=t.val;n[r]=function(){var t=[],n=arguments.length;while(n--)t[n]=arguments[n];var r=this.$store.dispatch;if(e){var i=ce(this.$store,"mapActions",e);if(!i)return;r=i.context.dispatch}return"function"===typeof o?o.apply(this,[r].concat(t)):r.apply(this.$store,[o].concat(t))}}),n});function ae(e){return le(e)?Array.isArray(e)?e.map(function(e){return{key:e,val:e}}):Object.keys(e).map(function(t){return{key:t,val:e[t]}}):[]}function le(e){return Array.isArray(e)||y(e)}function ue(e){return function(t,n){return"string"!==typeof t?(n=t,t=""):"/"!==t.charAt(t.length-1)&&(t+="/"),e(t,n)}}function ce(e,t,n){var r=e._modulesNamespaceMap[n];return r}},3382:function(e,t,n){"use strict";e.exports=n.p+"img/funding.cf78a0a0.svg"},9306:function(e,t,n){"use strict";var r=n(4901),o=n(6823),i=TypeError;e.exports=function(e){if(r(e))return e;throw new i(o(e)+" is not a function")}},6469:function(e,t,n){"use strict";var r=n(8227),o=n(2360),i=n(4913).f,s=r("unscopables"),a=Array.prototype;void 0===a[s]&&i(a,s,{configurable:!0,value:o(null)}),e.exports=function(e){a[s][e]=!0}},679:function(e,t,n){"use strict";var r=n(1625),o=TypeError;e.exports=function(e,t){if(r(t,e))return e;throw new o("Incorrect invocation")}},8551:function(e,t,n){"use strict";var r=n(34),o=String,i=TypeError;e.exports=function(e){if(r(e))return e;throw new i(o(e)+" is not an object")}},9617:function(e,t,n){"use strict";var r=n(5397),o=n(5610),i=n(6198),s=function(e){return function(t,n,s){var a=r(t),l=i(a);if(0===l)return!e&&-1;var u,c=o(s,l);if(e&&n!==n){while(l>c)if(u=a[c++],u!==u)return!0}else for(;l>c;c++)if((e||c in a)&&a[c]===n)return e||c||0;return!e&&-1}};e.exports={includes:s(!0),indexOf:s(!1)}},4527:function(e,t,n){"use strict";var r=n(3724),o=n(4376),i=TypeError,s=Object.getOwnPropertyDescriptor,a=r&&!function(){if(void 0!==this)return!0;try{Object.defineProperty([],"length",{writable:!1}).length=1}catch(e){return e instanceof TypeError}}();e.exports=a?function(e,t){if(o(e)&&!s(e,"length").writable)throw new i("Cannot set read only .length");return e.length=t}:function(e,t){return e.length=t}},6319:function(e,t,n){"use strict";var r=n(8551),o=n(9539);e.exports=function(e,t,n,i){try{return i?t(r(n)[0],n[1]):t(n)}catch(s){o(e,"throw",s)}}},2195:function(e,t,n){"use strict";var r=n(9504),o=r({}.toString),i=r("".slice);e.exports=function(e){return i(o(e),8,-1)}},6955:function(e,t,n){"use strict";var r=n(2140),o=n(4901),i=n(2195),s=n(8227),a=s("toStringTag"),l=Object,u="Arguments"===i(function(){return arguments}()),c=function(e,t){try{return e[t]}catch(n){}};e.exports=r?i:function(e){var t,n,r;return void 0===e?"Undefined":null===e?"Null":"string"==typeof(n=c(t=l(e),a))?n:u?i(t):"Object"===(r=i(t))&&o(t.callee)?"Arguments":r}},7740:function(e,t,n){"use strict";var r=n(9297),o=n(5031),i=n(7347),s=n(4913);e.exports=function(e,t,n){for(var a=o(t),l=s.f,u=i.f,c=0;c<a.length;c++){var d=a[c];r(e,d)||n&&r(n,d)||l(e,d,u(t,d))}}},2211:function(e,t,n){"use strict";var r=n(9039);e.exports=!r(function(){function e(){}return e.prototype.constructor=null,Object.getPrototypeOf(new e)!==e.prototype})},2529:function(e){"use strict";e.exports=function(e,t){return{value:e,done:t}}},6699:function(e,t,n){"use strict";var r=n(3724),o=n(4913),i=n(6980);e.exports=r?function(e,t,n){return o.f(e,t,i(1,n))}:function(e,t,n){return e[t]=n,e}},6980:function(e){"use strict";e.exports=function(e,t){return{enumerable:!(1&e),configurable:!(2&e),writable:!(4&e),value:t}}},2278:function(e,t,n){"use strict";var r=n(3724),o=n(4913),i=n(6980);e.exports=function(e,t,n){r?o.f(e,t,i(0,n)):e[t]=n}},2106:function(e,t,n){"use strict";var r=n(283),o=n(4913);e.exports=function(e,t,n){return n.get&&r(n.get,t,{getter:!0}),n.set&&r(n.set,t,{setter:!0}),o.f(e,t,n)}},6840:function(e,t,n){"use strict";var r=n(4901),o=n(4913),i=n(283),s=n(9433);e.exports=function(e,t,n,a){a||(a={});var l=a.enumerable,u=void 0!==a.name?a.name:t;if(r(n)&&i(n,u,a),a.global)l?e[t]=n:s(t,n);else{try{a.unsafe?e[t]&&(l=!0):delete e[t]}catch(c){}l?e[t]=n:o.f(e,t,{value:n,enumerable:!1,configurable:!a.nonConfigurable,writable:!a.nonWritable})}return e}},6279:function(e,t,n){"use strict";var r=n(6840);e.exports=function(e,t,n){for(var o in t)r(e,o,t[o],n);return e}},9433:function(e,t,n){"use strict";var r=n(4576),o=Object.defineProperty;e.exports=function(e,t){try{o(r,e,{value:t,configurable:!0,writable:!0})}catch(n){r[e]=t}return t}},3724:function(e,t,n){"use strict";var r=n(9039);e.exports=!r(function(){return 7!==Object.defineProperty({},1,{get:function(){return 7}})[1]})},4055:function(e,t,n){"use strict";var r=n(4576),o=n(34),i=r.document,s=o(i)&&o(i.createElement);e.exports=function(e){return s?i.createElement(e):{}}},6837:function(e){"use strict";var t=TypeError,n=9007199254740991;e.exports=function(e){if(e>n)throw new t("Maximum allowed index exceeded");return e}},8727:function(e){"use strict";e.exports=["constructor","hasOwnProperty","isPrototypeOf","propertyIsEnumerable","toLocaleString","toString","valueOf"]},2839:function(e,t,n){"use strict";var r=n(4576),o=r.navigator,i=o&&o.userAgent;e.exports=i?String(i):""},9519:function(e,t,n){"use strict";var r,o,i=n(4576),s=n(2839),a=i.process,l=i.Deno,u=a&&a.versions||l&&l.version,c=u&&u.v8;c&&(r=c.split("."),o=r[0]>0&&r[0]<4?1:+(r[0]+r[1])),!o&&s&&(r=s.match(/Edge\/(\d+)/),(!r||r[1]>=74)&&(r=s.match(/Chrome\/(\d+)/),r&&(o=+r[1]))),e.exports=o},6518:function(e,t,n){"use strict";var r=n(4576),o=n(7347).f,i=n(6699),s=n(6840),a=n(9433),l=n(7740),u=n(2796);e.exports=function(e,t){var n,c,d,f,h,p,m=e.target,v=e.global,g=e.stat;if(c=v?r:g?r[m]||a(m,{}):r[m]&&r[m].prototype,c)for(d in t){if(h=t[d],e.dontCallGetSet?(p=o(c,d),f=p&&p.value):f=c[d],n=u(v?d:m+(g?".":"#")+d,e.forced),!n&&void 0!==f){if(typeof h==typeof f)continue;l(h,f)}(e.sham||f&&f.sham)&&i(h,"sham",!0),s(c,d,h,e)}}},9039:function(e){"use strict";e.exports=function(e){try{return!!e()}catch(t){return!0}}},8745:function(e,t,n){"use strict";var r=n(616),o=Function.prototype,i=o.apply,s=o.call;e.exports="object"==typeof Reflect&&Reflect.apply||(r?s.bind(i):function(){return s.apply(i,arguments)})},6080:function(e,t,n){"use strict";var r=n(7476),o=n(9306),i=n(616),s=r(r.bind);e.exports=function(e,t){return o(e),void 0===t?e:i?s(e,t):function(){return e.apply(t,arguments)}}},616:function(e,t,n){"use strict";var r=n(9039);e.exports=!r(function(){var e=function(){}.bind();return"function"!=typeof e||e.hasOwnProperty("prototype")})},9565:function(e,t,n){"use strict";var r=n(616),o=Function.prototype.call;e.exports=r?o.bind(o):function(){return o.apply(o,arguments)}},350:function(e,t,n){"use strict";var r=n(3724),o=n(9297),i=Function.prototype,s=r&&Object.getOwnPropertyDescriptor,a=o(i,"name"),l=a&&"something"===function(){}.name,u=a&&(!r||r&&s(i,"name").configurable);e.exports={EXISTS:a,PROPER:l,CONFIGURABLE:u}},7476:function(e,t,n){"use strict";var r=n(2195),o=n(9504);e.exports=function(e){if("Function"===r(e))return o(e)}},9504:function(e,t,n){"use strict";var r=n(616),o=Function.prototype,i=o.call,s=r&&o.bind.bind(i,i);e.exports=r?s:function(e){return function(){return i.apply(e,arguments)}}},7751:function(e,t,n){"use strict";var r=n(4576),o=n(4901),i=function(e){return o(e)?e:void 0};e.exports=function(e,t){return arguments.length<2?i(r[e]):r[e]&&r[e][t]}},1767:function(e){"use strict";e.exports=function(e){return{iterator:e,next:e.next,done:!1}}},851:function(e,t,n){"use strict";var r=n(6955),o=n(5966),i=n(4117),s=n(6269),a=n(8227),l=a("iterator");e.exports=function(e){if(!i(e))return o(e,l)||o(e,"@@iterator")||s[r(e)]}},81:function(e,t,n){"use strict";var r=n(9565),o=n(9306),i=n(8551),s=n(6823),a=n(851),l=TypeError;e.exports=function(e,t){var n=arguments.length<2?a(e):t;if(o(n))return i(r(n,e));throw new l(s(e)+" is not iterable")}},5966:function(e,t,n){"use strict";var r=n(9306),o=n(4117);e.exports=function(e,t){var n=e[t];return o(n)?void 0:r(n)}},4576:function(e,t,n){"use strict";var r=function(e){return e&&e.Math===Math&&e};e.exports=r("object"==typeof globalThis&&globalThis)||r("object"==typeof window&&window)||r("object"==typeof self&&self)||r("object"==typeof n.g&&n.g)||r("object"==typeof this&&this)||function(){return this}()||Function("return this")()},9297:function(e,t,n){"use strict";var r=n(9504),o=n(8981),i=r({}.hasOwnProperty);e.exports=Object.hasOwn||function(e,t){return i(o(e),t)}},421:function(e){"use strict";e.exports={}},397:function(e,t,n){"use strict";var r=n(7751);e.exports=r("document","documentElement")},5917:function(e,t,n){"use strict";var r=n(3724),o=n(9039),i=n(4055);e.exports=!r&&!o(function(){return 7!==Object.defineProperty(i("div"),"a",{get:function(){return 7}}).a})},7055:function(e,t,n){"use strict";var r=n(9504),o=n(9039),i=n(2195),s=Object,a=r("".split);e.exports=o(function(){return!s("z").propertyIsEnumerable(0)})?function(e){return"String"===i(e)?a(e,""):s(e)}:s},3706:function(e,t,n){"use strict";var r=n(9504),o=n(4901),i=n(7629),s=r(Function.toString);o(i.inspectSource)||(i.inspectSource=function(e){return s(e)}),e.exports=i.inspectSource},1181:function(e,t,n){"use strict";var r,o,i,s=n(8622),a=n(4576),l=n(34),u=n(6699),c=n(9297),d=n(7629),f=n(6119),h=n(421),p="Object already initialized",m=a.TypeError,v=a.WeakMap,g=function(e){return i(e)?o(e):r(e,{})},y=function(e){return function(t){var n;if(!l(t)||(n=o(t)).type!==e)throw new m("Incompatible receiver, "+e+" required");return n}};if(s||d.state){var b=d.state||(d.state=new v);b.get=b.get,b.has=b.has,b.set=b.set,r=function(e,t){if(b.has(e))throw new m(p);return t.facade=e,b.set(e,t),t},o=function(e){return b.get(e)||{}},i=function(e){return b.has(e)}}else{var _=f("state");h[_]=!0,r=function(e,t){if(c(e,_))throw new m(p);return t.facade=e,u(e,_,t),t},o=function(e){return c(e,_)?e[_]:{}},i=function(e){return c(e,_)}}e.exports={set:r,get:o,has:i,enforce:g,getterFor:y}},4209:function(e,t,n){"use strict";var r=n(8227),o=n(6269),i=r("iterator"),s=Array.prototype;e.exports=function(e){return void 0!==e&&(o.Array===e||s[i]===e)}},4376:function(e,t,n){"use strict";var r=n(2195);e.exports=Array.isArray||function(e){return"Array"===r(e)}},4901:function(e){"use strict";var t="object"==typeof document&&document.all;e.exports="undefined"==typeof t&&void 0!==t?function(e){return"function"==typeof e||e===t}:function(e){return"function"==typeof e}},2796:function(e,t,n){"use strict";var r=n(9039),o=n(4901),i=/#|\.prototype\./,s=function(e,t){var n=l[a(e)];return n===c||n!==u&&(o(t)?r(t):!!t)},a=s.normalize=function(e){return String(e).replace(i,".").toLowerCase()},l=s.data={},u=s.NATIVE="N",c=s.POLYFILL="P";e.exports=s},4117:function(e){"use strict";e.exports=function(e){return null===e||void 0===e}},34:function(e,t,n){"use strict";var r=n(4901);e.exports=function(e){return"object"==typeof e?null!==e:r(e)}},6395:function(e){"use strict";e.exports=!1},757:function(e,t,n){"use strict";var r=n(7751),o=n(4901),i=n(1625),s=n(4659),a=Object;e.exports=s?function(e){return"symbol"==typeof e}:function(e){var t=r("Symbol");return o(t)&&i(t.prototype,a(e))}},2652:function(e,t,n){"use strict";var r=n(6080),o=n(9565),i=n(8551),s=n(6823),a=n(4209),l=n(6198),u=n(1625),c=n(81),d=n(851),f=n(9539),h=TypeError,p=function(e,t){this.stopped=e,this.result=t},m=p.prototype;e.exports=function(e,t,n){var v,g,y,b,_,E,w,S=n&&n.that,T=!(!n||!n.AS_ENTRIES),k=!(!n||!n.IS_RECORD),C=!(!n||!n.IS_ITERATOR),O=!(!n||!n.INTERRUPTED),A=r(t,S),R=function(e){var t=v;return v=void 0,t&&f(t,"normal"),new p(!0,e)},I=function(e){return T?(i(e),O?A(e[0],e[1],R):A(e[0],e[1])):O?A(e,R):A(e)};if(k)v=e.iterator;else if(C)v=e;else{if(g=d(e),!g)throw new h(s(e)+" is not iterable");if(a(g)){for(y=0,b=l(e);b>y;y++)if(_=I(e[y]),_&&u(m,_))return _;return new p(!1)}v=c(e,g)}E=k?e.next:v.next;while(!(w=o(E,v)).done){var N=w.value;try{_=I(N)}catch(L){if(!v)throw L;f(v,"throw",L)}if("object"==typeof _&&_&&u(m,_))return _}return new p(!1)}},1385:function(e,t,n){"use strict";var r=n(9539);e.exports=function(e,t,n){for(var o=e.length-1;o>=0;o--)if(void 0!==e[o])try{n=r(e[o].iterator,t,n)}catch(i){t="throw",n=i}if("throw"===t)throw n;return n}},9539:function(e,t,n){"use strict";var r=n(9565),o=n(8551),i=n(5966);e.exports=function(e,t,n){var s,a;o(e);try{if(s=i(e,"return"),!s){if("throw"===t)throw n;return n}s=r(s,e)}catch(l){a=!0,s=l}if("throw"===t)throw n;if(a)throw s;return o(s),n}},9462:function(e,t,n){"use strict";var r=n(9565),o=n(2360),i=n(6699),s=n(6279),a=n(8227),l=n(1181),u=n(5966),c=n(7657).IteratorPrototype,d=n(2529),f=n(9539),h=n(1385),p=a("toStringTag"),m="IteratorHelper",v="WrapForValidIterator",g="normal",y="throw",b=l.set,_=function(e){var t=l.getterFor(e?v:m);return s(o(c),{next:function(){var n=t(this);if(e)return n.nextHandler();if(n.done)return d(void 0,!0);try{var r=n.nextHandler();return n.returnHandlerResult?r:d(r,n.done)}catch(o){throw n.done=!0,o}},return:function(){var n=t(this),o=n.iterator,i=n.done;if(n.done=!0,e){var s=u(o,"return");return s?r(s,o):d(void 0,!0)}if(i)return d(void 0,!0);if(n.inner)try{f(n.inner.iterator,g)}catch(a){return f(o,y,a)}if(n.openIters)try{h(n.openIters,g)}catch(a){if(o)return f(o,y,a);throw a}return o&&f(o,g),d(void 0,!0)}})},E=_(!0),w=_(!1);i(w,p,"Iterator Helper"),e.exports=function(e,t,n){var r=function(r,o){o?(o.iterator=r.iterator,o.next=r.next):o=r,o.type=t?v:m,o.returnHandlerResult=!!n,o.nextHandler=e,o.counter=0,o.done=!1,b(this,o)};return r.prototype=t?E:w,r}},684:function(e){"use strict";e.exports=function(e,t){var n="function"==typeof Iterator&&Iterator.prototype[e];if(n)try{n.call({next:null},t).next()}catch(r){return!0}}},4549:function(e,t,n){"use strict";var r=n(4576);e.exports=function(e,t){var n=r.Iterator,o=n&&n.prototype,i=o&&o[e],s=!1;if(i)try{i.call({next:function(){return{done:!0}},return:function(){s=!0}},-1)}catch(a){a instanceof t||(s=!1)}if(!s)return i}},7657:function(e,t,n){"use strict";var r,o,i,s=n(9039),a=n(4901),l=n(34),u=n(2360),c=n(2787),d=n(6840),f=n(8227),h=n(6395),p=f("iterator"),m=!1;[].keys&&(i=[].keys(),"next"in i?(o=c(c(i)),o!==Object.prototype&&(r=o)):m=!0);var v=!l(r)||s(function(){var e={};return r[p].call(e)!==e});v?r={}:h&&(r=u(r)),a(r[p])||d(r,p,function(){return this}),e.exports={IteratorPrototype:r,BUGGY_SAFARI_ITERATORS:m}},6269:function(e){"use strict";e.exports={}},6198:function(e,t,n){"use strict";var r=n(8014);e.exports=function(e){return r(e.length)}},283:function(e,t,n){"use strict";var r=n(9504),o=n(9039),i=n(4901),s=n(9297),a=n(3724),l=n(350).CONFIGURABLE,u=n(3706),c=n(1181),d=c.enforce,f=c.get,h=String,p=Object.defineProperty,m=r("".slice),v=r("".replace),g=r([].join),y=a&&!o(function(){return 8!==p(function(){},"length",{value:8}).length}),b=String(String).split("String"),_=e.exports=function(e,t,n){"Symbol("===m(h(t),0,7)&&(t="["+v(h(t),/^Symbol\(([^)]*)\).*$/,"$1")+"]"),n&&n.getter&&(t="get "+t),n&&n.setter&&(t="set "+t),(!s(e,"name")||l&&e.name!==t)&&(a?p(e,"name",{value:t,configurable:!0}):e.name=t),y&&n&&s(n,"arity")&&e.length!==n.arity&&p(e,"length",{value:n.arity});try{n&&s(n,"constructor")&&n.constructor?a&&p(e,"prototype",{writable:!1}):e.prototype&&(e.prototype=void 0)}catch(o){}var r=d(e);return s(r,"source")||(r.source=g(b,"string"==typeof t?t:"")),e};Function.prototype.toString=_(function(){return i(this)&&f(this).source||u(this)},"toString")},741:function(e){"use strict";var t=Math.ceil,n=Math.floor;e.exports=Math.trunc||function(e){var r=+e;return(r>0?n:t)(r)}},6043:function(e,t,n){"use strict";var r=n(9306),o=TypeError,i=function(e){var t,n;this.promise=new e(function(e,r){if(void 0!==t||void 0!==n)throw new o("Bad Promise constructor");t=e,n=r}),this.resolve=r(t),this.reject=r(n)};e.exports.f=function(e){return new i(e)}},2360:function(e,t,n){"use strict";var r,o=n(8551),i=n(6801),s=n(8727),a=n(421),l=n(397),u=n(4055),c=n(6119),d=">",f="<",h="prototype",p="script",m=c("IE_PROTO"),v=function(){},g=function(e){return f+p+d+e+f+"/"+p+d},y=function(e){e.write(g("")),e.close();var t=e.parentWindow.Object;return e=null,t},b=function(){var e,t=u("iframe"),n="java"+p+":";return t.style.display="none",l.appendChild(t),t.src=String(n),e=t.contentWindow.document,e.open(),e.write(g("document.F=Object")),e.close(),e.F},_=function(){try{r=new ActiveXObject("htmlfile")}catch(t){}_="undefined"!=typeof document?document.domain&&r?y(r):b():y(r);var e=s.length;while(e--)delete _[h][s[e]];return _()};a[m]=!0,e.exports=Object.create||function(e,t){var n;return null!==e?(v[h]=o(e),n=new v,v[h]=null,n[m]=e):n=_(),void 0===t?n:i.f(n,t)}},6801:function(e,t,n){"use strict";var r=n(3724),o=n(8686),i=n(4913),s=n(8551),a=n(5397),l=n(1072);t.f=r&&!o?Object.defineProperties:function(e,t){s(e);var n,r=a(t),o=l(t),u=o.length,c=0;while(u>c)i.f(e,n=o[c++],r[n]);return e}},4913:function(e,t,n){"use strict";var r=n(3724),o=n(5917),i=n(8686),s=n(8551),a=n(6969),l=TypeError,u=Object.defineProperty,c=Object.getOwnPropertyDescriptor,d="enumerable",f="configurable",h="writable";t.f=r?i?function(e,t,n){if(s(e),t=a(t),s(n),"function"===typeof e&&"prototype"===t&&"value"in n&&h in n&&!n[h]){var r=c(e,t);r&&r[h]&&(e[t]=n.value,n={configurable:f in n?n[f]:r[f],enumerable:d in n?n[d]:r[d],writable:!1})}return u(e,t,n)}:u:function(e,t,n){if(s(e),t=a(t),s(n),o)try{return u(e,t,n)}catch(r){}if("get"in n||"set"in n)throw new l("Accessors not supported");return"value"in n&&(e[t]=n.value),e}},7347:function(e,t,n){"use strict";var r=n(3724),o=n(9565),i=n(8773),s=n(6980),a=n(5397),l=n(6969),u=n(9297),c=n(5917),d=Object.getOwnPropertyDescriptor;t.f=r?d:function(e,t){if(e=a(e),t=l(t),c)try{return d(e,t)}catch(n){}if(u(e,t))return s(!o(i.f,e,t),e[t])}},8480:function(e,t,n){"use strict";var r=n(1828),o=n(8727),i=o.concat("length","prototype");t.f=Object.getOwnPropertyNames||function(e){return r(e,i)}},3717:function(e,t){"use strict";t.f=Object.getOwnPropertySymbols},2787:function(e,t,n){"use strict";var r=n(9297),o=n(4901),i=n(8981),s=n(6119),a=n(2211),l=s("IE_PROTO"),u=Object,c=u.prototype;e.exports=a?u.getPrototypeOf:function(e){var t=i(e);if(r(t,l))return t[l];var n=t.constructor;return o(n)&&t instanceof n?n.prototype:t instanceof u?c:null}},1625:function(e,t,n){"use strict";var r=n(9504);e.exports=r({}.isPrototypeOf)},1828:function(e,t,n){"use strict";var r=n(9504),o=n(9297),i=n(5397),s=n(9617).indexOf,a=n(421),l=r([].push);e.exports=function(e,t){var n,r=i(e),u=0,c=[];for(n in r)!o(a,n)&&o(r,n)&&l(c,n);while(t.length>u)o(r,n=t[u++])&&(~s(c,n)||l(c,n));return c}},1072:function(e,t,n){"use strict";var r=n(1828),o=n(8727);e.exports=Object.keys||function(e){return r(e,o)}},8773:function(e,t){"use strict";var n={}.propertyIsEnumerable,r=Object.getOwnPropertyDescriptor,o=r&&!n.call({1:2},1);t.f=o?function(e){var t=r(this,e);return!!t&&t.enumerable}:n},4270:function(e,t,n){"use strict";var r=n(9565),o=n(4901),i=n(34),s=TypeError;e.exports=function(e,t){var n,a;if("string"===t&&o(n=e.toString)&&!i(a=r(n,e)))return a;if(o(n=e.valueOf)&&!i(a=r(n,e)))return a;if("string"!==t&&o(n=e.toString)&&!i(a=r(n,e)))return a;throw new s("Can't convert object to primitive value")}},5031:function(e,t,n){"use strict";var r=n(7751),o=n(9504),i=n(8480),s=n(3717),a=n(8551),l=o([].concat);e.exports=r("Reflect","ownKeys")||function(e){var t=i.f(a(e)),n=s.f;return n?l(t,n(e)):t}},8235:function(e,t,n){"use strict";var r=n(9504),o=n(9297),i=SyntaxError,s=parseInt,a=String.fromCharCode,l=r("".charAt),u=r("".slice),c=r(/./.exec),d={'\\"':'"',"\\\\":"\\","\\/":"/","\\b":"\b","\\f":"\f","\\n":"\n","\\r":"\r","\\t":"\t"},f=/^[\da-f]{4}$/i,h=/^[\u0000-\u001F]$/;e.exports=function(e,t){var n=!0,r="";while(t<e.length){var p=l(e,t);if("\\"===p){var m=u(e,t,t+2);if(o(d,m))r+=d[m],t+=2;else{if("\\u"!==m)throw new i('Unknown escape sequence: "'+m+'"');t+=2;var v=u(e,t,t+4);if(!c(f,v))throw new i("Bad Unicode escape at: "+t);r+=a(s(v,16)),t+=4}}else{if('"'===p){n=!1,t++;break}if(c(h,p))throw new i("Bad control character in string literal at: "+t);r+=p,t++}}if(n)throw new i("Unterminated string at: "+t);return{value:r,end:t}}},7750:function(e,t,n){"use strict";var r=n(4117),o=TypeError;e.exports=function(e){if(r(e))throw new o("Can't call method on "+e);return e}},6119:function(e,t,n){"use strict";var r=n(5745),o=n(3392),i=r("keys");e.exports=function(e){return i[e]||(i[e]=o(e))}},7629:function(e,t,n){"use strict";var r=n(6395),o=n(4576),i=n(9433),s="__core-js_shared__",a=e.exports=o[s]||i(s,{});(a.versions||(a.versions=[])).push({version:"3.49.0",mode:r?"pure":"global",copyright:"© 2013–2025 Denis Pushkarev (zloirock.ru), 2025–2026 CoreJS Company (core-js.io). All rights reserved.",license:"https://github.com/zloirock/core-js/blob/v3.49.0/LICENSE",source:"https://github.com/zloirock/core-js"})},5745:function(e,t,n){"use strict";var r=n(7629);e.exports=function(e,t){return r[e]||(r[e]=t||{})}},4495:function(e,t,n){"use strict";var r=n(9519),o=n(9039),i=n(4576),s=i.String;e.exports=!!Object.getOwnPropertySymbols&&!o(function(){var e=Symbol("symbol detection");return!s(e)||!(Object(e)instanceof Symbol)||!Symbol.sham&&r&&r<41})},5610:function(e,t,n){"use strict";var r=n(1291),o=Math.max,i=Math.min;e.exports=function(e,t){var n=r(e);return n<0?o(n+t,0):i(n,t)}},5397:function(e,t,n){"use strict";var r=n(7055),o=n(7750);e.exports=function(e){return r(o(e))}},1291:function(e,t,n){"use strict";var r=n(741);e.exports=function(e){var t=+e;return t!==t||0===t?0:r(t)}},8014:function(e,t,n){"use strict";var r=n(1291),o=Math.min;e.exports=function(e){var t=r(e);return t>0?o(t,9007199254740991):0}},8981:function(e,t,n){"use strict";var r=n(7750),o=Object;e.exports=function(e){return o(r(e))}},2777:function(e,t,n){"use strict";var r=n(9565),o=n(34),i=n(757),s=n(5966),a=n(4270),l=n(8227),u=TypeError,c=l("toPrimitive");e.exports=function(e,t){if(!o(e)||i(e))return e;var n,l=s(e,c);if(l){if(void 0===t&&(t="default"),n=r(l,e,t),!o(n)||i(n))return n;throw new u("Can't convert object to primitive value")}return void 0===t&&(t="number"),a(e,t)}},6969:function(e,t,n){"use strict";var r=n(2777),o=n(757);e.exports=function(e){var t=r(e,"string");return o(t)?t:t+""}},2140:function(e,t,n){"use strict";var r=n(8227),o=r("toStringTag"),i={};i[o]="z",e.exports="[object z]"===String(i)},655:function(e,t,n){"use strict";var r=n(6955),o=String;e.exports=function(e){if("Symbol"===r(e))throw new TypeError("Cannot convert a Symbol value to a string");return o(e)}},6823:function(e){"use strict";var t=String;e.exports=function(e){try{return t(e)}catch(n){return"Object"}}},3392:function(e,t,n){"use strict";var r=n(9504),o=0,i=Math.random(),s=r(1.1.toString);e.exports=function(e){return"Symbol("+(void 0===e?"":e)+")_"+s(++o+i,36)}},4659:function(e,t,n){"use strict";var r=n(4495);e.exports=r&&!Symbol.sham&&"symbol"==typeof Symbol.iterator},8686:function(e,t,n){"use strict";var r=n(3724),o=n(9039);e.exports=r&&o(function(){return 42!==Object.defineProperty(function(){},"prototype",{value:42,writable:!1}).prototype})},2812:function(e){"use strict";var t=TypeError;e.exports=function(e,n){if(e<n)throw new t("Not enough arguments");return e}},8622:function(e,t,n){"use strict";var r=n(4576),o=n(4901),i=r.WeakMap;e.exports=o(i)&&/native code/.test(String(i))},8227:function(e,t,n){"use strict";var r=n(4576),o=n(5745),i=n(9297),s=n(3392),a=n(4495),l=n(4659),u=r.Symbol,c=o("wks"),d=l?u["for"]||u:u&&u.withoutSetter||s;e.exports=function(e){return i(c,e)||(c[e]=a&&i(u,e)?u[e]:d("Symbol."+e)),c[e]}},4423:function(e,t,n){"use strict";var r=n(6518),o=n(9617).includes,i=n(9039),s=n(6469),a=i(function(){return!Array(1).includes()}),l=i(function(){return[,1].includes(void 0,1)});r({target:"Array",proto:!0,forced:a||l},{includes:function(e){return o(this,e,arguments.length>1?arguments[1]:void 0)}}),s("includes")},4114:function(e,t,n){"use strict";var r=n(6518),o=n(8981),i=n(6198),s=n(4527),a=n(6837),l=n(9039),u=l(function(){return 4294967297!==[].push.call({length:4294967296},1)}),c=function(){try{Object.defineProperty([],"length",{writable:!1}).push()}catch(e){return e instanceof TypeError}},d=u||!c();r({target:"Array",proto:!0,arity:1,forced:d},{push:function(e){var t=o(this),n=i(t),r=arguments.length;a(n+r);for(var l=0;l<r;l++)t[n]=arguments[l],n++;return s(t,n),n}})},8111:function(e,t,n){"use strict";var r=n(6518),o=n(4576),i=n(679),s=n(8551),a=n(4901),l=n(2787),u=n(2106),c=n(2278),d=n(9039),f=n(9297),h=n(8227),p=n(7657).IteratorPrototype,m=n(3724),v=n(6395),g="constructor",y="Iterator",b=h("toStringTag"),_=TypeError,E=o[y],w=v||!a(E)||E.prototype!==p||!d(function(){E({})}),S=function(){if(i(this,p),l(this)===p)throw new _("Abstract class Iterator not directly constructable")},T=function(e,t){m?u(p,e,{configurable:!0,get:function(){return t},set:function(t){if(s(this),this===p)throw new _("You can't redefine this property");f(this,e)?this[e]=t:c(this,e,t)}}):p[e]=t};f(p,b)||T(b,y),!w&&f(p,g)&&p[g]!==Object||T(g,S),S.prototype=p,r({global:!0,constructor:!0,forced:w},{Iterator:S})},2489:function(e,t,n){"use strict";var r=n(6518),o=n(9565),i=n(9306),s=n(8551),a=n(1767),l=n(9462),u=n(6319),c=n(6395),d=n(9539),f=n(684),h=n(4549),p=!c&&!f("filter",function(){}),m=!c&&!p&&h("filter",TypeError),v=c||p||m,g=l(function(){var e,t,n,r=this.iterator,i=this.predicate,a=this.next;while(1){if(e=s(o(a,r)),t=this.done=!!e.done,t)return;if(n=e.value,u(r,i,[n,this.counter++],!0))return n}});r({target:"Iterator",proto:!0,real:!0,forced:v},{filter:function(e){s(this);try{i(e)}catch(t){d(this,"throw",t)}return m?o(m,this,e):new g(a(this),{predicate:e})}})},116:function(e,t,n){"use strict";var r=n(6518),o=n(9565),i=n(2652),s=n(9306),a=n(8551),l=n(1767),u=n(9539),c=n(4549),d=c("find",TypeError);r({target:"Iterator",proto:!0,real:!0,forced:d},{find:function(e){a(this);try{s(e)}catch(r){u(this,"throw",r)}if(d)return o(d,this,e);var t=l(this),n=0;return i(t,function(t,r){if(e(t,n++))return r(t)},{IS_RECORD:!0,INTERRUPTED:!0}).result}})},7588:function(e,t,n){"use strict";var r=n(6518),o=n(9565),i=n(2652),s=n(9306),a=n(8551),l=n(1767),u=n(9539),c=n(4549),d=c("forEach",TypeError);r({target:"Iterator",proto:!0,real:!0,forced:d},{forEach:function(e){a(this);try{s(e)}catch(r){u(this,"throw",r)}if(d)return o(d,this,e);var t=l(this),n=0;i(t,function(t){e(t,n++)},{IS_RECORD:!0})}})},1701:function(e,t,n){"use strict";var r=n(6518),o=n(9565),i=n(9306),s=n(8551),a=n(1767),l=n(9462),u=n(6319),c=n(9539),d=n(684),f=n(4549),h=n(6395),p=!h&&!d("map",function(){}),m=!h&&!p&&f("map",TypeError),v=h||p||m,g=l(function(){var e=this.iterator,t=s(o(this.next,e)),n=this.done=!!t.done;if(!n)return u(e,this.mapper,[t.value,this.counter++],!0)});r({target:"Iterator",proto:!0,real:!0,forced:v},{map:function(e){s(this);try{i(e)}catch(t){c(this,"throw",t)}return m?o(m,this,e):new g(a(this),{mapper:e})}})},8237:function(e,t,n){"use strict";var r=n(6518),o=n(2652),i=n(9306),s=n(8551),a=n(1767),l=n(9539),u=n(4549),c=n(8745),d=n(9039),f=TypeError,h=d(function(){[].keys().reduce(function(){},void 0)}),p=!h&&u("reduce",f);r({target:"Iterator",proto:!0,real:!0,forced:h||p},{reduce:function(e){s(this);try{i(e)}catch(d){l(this,"throw",d)}var t=arguments.length<2,n=t?void 0:arguments[1];if(p)return c(p,this,t?[e]:[e,n]);var r=a(this),u=0;if(o(r,function(r){t?(t=!1,n=r):n=e(n,r,u),u++},{IS_RECORD:!0}),t)throw new f("Reduce of empty iterator with no initial value");return n}})},9112:function(e,t,n){"use strict";var r=n(6518),o=n(3724),i=n(4576),s=n(7751),a=n(9504),l=n(9565),u=n(4901),c=n(34),d=n(4376),f=n(9297),h=n(655),p=n(6198),m=n(2278),v=n(9039),g=n(8235),y=n(4495),b=i.JSON,_=i.Number,E=i.SyntaxError,w=b&&b.parse,S=s("Object","keys"),T=Object.getOwnPropertyDescriptor,k=a("".charAt),C=a("".slice),O=a(/./.exec),A=a([].push),R=/^\d$/,I=/^[1-9]$/,N=/^[\d-]$/,L=/^[\t\n\r ]$/,x=0,P=1,D=function(e,t){e=h(e);var n=new j(e,0,""),r=n.parse(),o=r.value,i=n.skip(L,r.end);if(i<e.length)throw new E('Unexpected extra character: "'+k(e,i)+'" after the parsed data at: '+i);return u(t)?M({"":o},"",t,r):o},M=function(e,t,n,r){var o,i,s,a,u,h=e[t],m=r&&h===r.value,v=m&&"string"==typeof r.source?{source:r.source}:{};if(c(h)){var g=d(h),y=m?r.nodes:g?[]:{};if(g)for(o=y.length,s=p(h),a=0;a<s;a++)F(h,a,M(h,""+a,n,a<o?y[a]:void 0));else for(i=S(h),s=p(i),a=0;a<s;a++)u=i[a],F(h,u,M(h,u,n,f(y,u)?y[u]:void 0))}return l(n,e,t,h,v)},F=function(e,t,n){if(o){var r=T(e,t);if(r&&!r.configurable)return}void 0===n?delete e[t]:m(e,t,n)},$=function(e,t,n,r){this.value=e,this.end=t,this.source=n,this.nodes=r},j=function(e,t){this.source=e,this.index=t};j.prototype={fork:function(e){return new j(this.source,e)},parse:function(){var e=this.source,t=this.skip(L,this.index),n=this.fork(t),r=k(e,t);if(O(N,r))return n.number();switch(r){case"{":return n.object();case"[":return n.array();case'"':return n.string();case"t":return n.keyword(!0);case"f":return n.keyword(!1);case"n":return n.keyword(null)}throw new E('Unexpected character: "'+r+'" at: '+t)},node:function(e,t,n,r,o){return new $(t,r,e?null:C(this.source,n,r),o)},object:function(){var e=this.source,t=this.index+1,n=!1,r={},o={},i=!1;while(t<e.length){if(t=this.until(['"',"}"],t),"}"===k(e,t)&&!n){t++,i=!0;break}var s=this.fork(t).string(),a=s.value;t=s.end,t=this.until([":"],t)+1,t=this.skip(L,t),s=this.fork(t).parse(),m(o,a,s),m(r,a,s.value),t=this.until([",","}"],s.end);var l=k(e,t);if(","===l)n=!0,t++;else if("}"===l){t++,i=!0;break}}if(!i)throw new E("Unterminated object at: "+t);return this.node(P,r,this.index,t,o)},array:function(){var e=this.source,t=this.index+1,n=!1,r=[],o=[],i=!1;while(t<e.length){if(t=this.skip(L,t),"]"===k(e,t)&&!n){t++,i=!0;break}var s=this.fork(t).parse();if(A(o,s),A(r,s.value),t=this.until([",","]"],s.end),","===k(e,t))n=!0,t++;else if("]"===k(e,t)){t++,i=!0;break}}if(!i)throw new E("Unterminated array at: "+t);return this.node(P,r,this.index,t,o)},string:function(){var e=this.index,t=g(this.source,this.index+1);return this.node(x,t.value,e,t.end)},number:function(){var e=this.source,t=this.index,n=t;if("-"===k(e,n)&&n++,"0"===k(e,n))n++;else{if(!O(I,k(e,n)))throw new E("Failed to parse number at: "+n);n=this.skip(R,n+1)}if("."===k(e,n)){var r=n+1;if(n=this.skip(R,r),r===n)throw new E("Failed to parse number's fraction at: "+n)}if("e"===k(e,n)||"E"===k(e,n)){n++,"+"!==k(e,n)&&"-"!==k(e,n)||n++;var o=n;if(n=this.skip(R,n),o===n)throw new E("Failed to parse number's exponent value at: "+n)}return this.node(x,_(C(e,t,n)),t,n)},keyword:function(e){var t=""+e,n=this.index,r=n+t.length;if(C(this.source,n,r)!==t)throw new E("Failed to parse value at: "+n);return this.node(x,e,n,r)},skip:function(e,t){for(var n=this.source;t<n.length;t++)if(!O(e,k(n,t)))break;return t},until:function(e,t){t=this.skip(L,t);for(var n=k(this.source,t),r=0;r<e.length;r++)if(e[r]===n)return t;throw new E('Unexpected character: "'+n+'" at: '+t)}};var U=v(function(){var e,t="9007199254740993";return w(t,function(t,n,r){e=r.source}),e!==t}),B=y&&!v(function(){return 1/w("-0 \t")!==-1/0});r({target:"JSON",stat:!0,forced:U},{parse:function(e,t){return B&&!u(t)?w(e):D(e,t)}})},4628:function(e,t,n){"use strict";var r=n(6518),o=n(6043);r({target:"Promise",stat:!0},{withResolvers:function(){var e=o.f(this);return{promise:e.promise,resolve:e.resolve,reject:e.reject}}})},4603:function(e,t,n){"use strict";var r=n(6840),o=n(9504),i=n(655),s=n(2812),a=URLSearchParams,l=a.prototype,u=o(l.append),c=o(l["delete"]),d=o(l.forEach),f=o([].push),h=new a("a=1&a=2&b=3");h["delete"]("a",1),h["delete"]("b",void 0),h+""!=="a=2"&&r(l,"delete",function(e){var t=arguments.length,n=t<2?void 0:arguments[1];if(t&&void 0===n)return c(this,e);var r=[];d(this,function(e,t){f(r,{key:t,value:e})}),s(t,1);var o,a=i(e),l=i(n),h=0,p=r.length;while(h<p)o=r[h],c(this,o.key),h++;h=0;while(h<p)o=r[h++],o.key===a&&o.value===l||u(this,o.key,o.value)},{enumerable:!0,unsafe:!0})},7566:function(e,t,n){"use strict";var r=n(6840),o=n(9504),i=n(655),s=n(2812),a=URLSearchParams,l=a.prototype,u=o(l.getAll),c=o(l.has),d=new a("a=1");!d.has("a",2)&&d.has("a",void 0)||r(l,"has",function(e){var t=arguments.length,n=t<2?void 0:arguments[1];if(t&&void 0===n)return c(this,e);var r=u(this,e);s(t,1);var o=i(n),a=0;while(a<r.length)if(r[a++]===o)return!0;return!1},{enumerable:!0,unsafe:!0})},8721:function(e,t,n){"use strict";var r=n(3724),o=n(9504),i=n(2106),s=URLSearchParams.prototype,a=o(s.forEach);r&&!("size"in s)&&i(s,"size",{get:function(){var e=0;return a(this,function(){e++}),e},configurable:!0,enumerable:!0})},3513:function(e,t,n){"use strict";n.d(t,{iDZ:function(){return S}});var r=n(953),o=n(641);function i(e){return!!(0,r.o5)()&&((0,r.jr)(e),!0)}const s="undefined"!==typeof window&&"undefined"!==typeof document,a=("undefined"!==typeof WorkerGlobalScope&&(globalThis,WorkerGlobalScope),Object.prototype.toString),l=e=>"[object Object]"===a.call(e);function u(e){let t;function n(){return t||(t=e()),t}return n.reset=async()=>{const e=t;t=void 0,e&&await e},n}function c(e){return Array.isArray(e)?e:[e]}function d(e){const t=Object.create(null);return n=>{const r=t[n];return r||(t[n]=e(n))}}const f=/\B([A-Z])/g,h=(d(e=>e.replace(f,"-$1").toLowerCase()),/-(\w)/g);d(e=>e.replace(h,(e,t)=>t?t.toUpperCase():""));function p(e,t,n={}){const{immediate:o=!0,immediateCallback:a=!1}=n,l=(0,r.IJ)(!1);let u;function c(){u&&(clearTimeout(u),u=void 0)}function d(){l.value=!1,c()}function f(...n){a&&e(),c(),l.value=!0,u=setTimeout(()=>{l.value=!1,u=void 0,e(...n)},(0,r.BA)(t))}return o&&(l.value=!0,s&&f()),i(d),{isPending:(0,r.nD)(l),start:f,stop:d}}function m(e,t,n){return(0,o.wB)(e,t,{...n,immediate:!0})}const v=s?window:void 0,g=(s&&window.document,s?window.navigator:void 0);s&&window.location;function y(e){var t;const n=(0,r.BA)(e);return null!=(t=null==n?void 0:n.$el)?t:n}function b(...e){const t=[],n=()=>{t.forEach(e=>e()),t.length=0},s=(e,t,n,r)=>(e.addEventListener(t,n,r),()=>e.removeEventListener(t,n,r)),a=(0,o.EW)(()=>{const t=c((0,r.BA)(e[0])).filter(e=>null!=e);return t.every(e=>"string"!==typeof e)?t:void 0}),u=m(()=>{var t,n;return[null!=(n=null==(t=a.value)?void 0:t.map(e=>y(e)))?n:[v].filter(e=>null!=e),c((0,r.BA)(a.value?e[1]:e[0])),c((0,r.R1)(a.value?e[2]:e[1])),(0,r.BA)(a.value?e[3]:e[2])]},([e,r,o,i])=>{if(n(),!(null==e?void 0:e.length)||!(null==r?void 0:r.length)||!(null==o?void 0:o.length))return;const a=l(i)?{...i}:i;t.push(...e.flatMap(e=>r.flatMap(t=>o.map(n=>s(e,t,n,a)))))},{flush:"post"}),d=()=>{u(),n()};return i(n),d}function _(){const e=(0,r.IJ)(!1),t=(0,o.nI)();return t&&(0,o.sV)(()=>{e.value=!0},t),e}function E(e){const t=_();return(0,o.EW)(()=>(t.value,Boolean(e())))}Symbol("vueuse-ssr-width");function w(e,t={}){const{controls:n=!1,navigator:o=g}=t,i=E(()=>o&&"permissions"in o),s=(0,r.IJ)(),a="string"===typeof e?{name:e}:e,l=(0,r.IJ)(),c=()=>{var e,t;l.value=null!=(t=null==(e=s.value)?void 0:e.state)?t:"prompt"};b(s,"change",c,{passive:!0});const d=u(async()=>{if(i.value){if(!s.value)try{s.value=await o.permissions.query(a)}catch(e){s.value=void 0}finally{c()}return n?(0,r.ux)(s.value):void 0}});return d(),n?{state:l,isSupported:i,query:d}:l}function S(e={}){const{navigator:t=g,read:n=!1,source:i,copiedDuring:s=1500,legacy:a=!1}=e,l=E(()=>t&&"clipboard"in t),u=w("clipboard-read"),c=w("clipboard-write"),d=(0,o.EW)(()=>l.value||a),f=(0,r.IJ)(""),h=(0,r.IJ)(!1),m=p(()=>h.value=!1,s,{immediate:!1});async function v(){let e=!(l.value&&T(u.value));if(!e)try{f.value=await t.clipboard.readText()}catch(n){e=!0}e&&(f.value=S())}async function y(e=(0,r.BA)(i)){if(d.value&&null!=e){let r=!(l.value&&T(c.value));if(!r)try{await t.clipboard.writeText(e)}catch(n){r=!0}r&&_(e),f.value=e,h.value=!0,m.start()}}function _(e){const t=document.createElement("textarea");t.value=null!=e?e:"",t.style.position="absolute",t.style.opacity="0",document.body.appendChild(t),t.select(),document.execCommand("copy"),t.remove()}function S(){var e,t,n;return null!=(n=null==(t=null==(e=null==document?void 0:document.getSelection)?void 0:e.call(document))?void 0:t.toString())?n:""}function T(e){return"granted"===e||"prompt"===e}return d.value&&n&&b(["copy","cut"],v,{passive:!0}),{isSupported:d,text:f,copied:h,copy:y}}"undefined"!==typeof globalThis?globalThis:"undefined"!==typeof window?window:"undefined"!==typeof n.g?n.g:"undefined"!==typeof self&&self;Number.POSITIVE_INFINITY},3936:function(e,t,n){"use strict";function r(e,t){""===e||0===e.length||("string"==typeof e?t.classList.add(e):t.classList.add(...e))}function o(e,t){""===e||0===e.length||("string"==typeof e?t.classList.remove(e):t.classList.remove(...e))}function i(e,t){try{if("object"!=typeof t){const e=typeof t;throw new TypeError(`Elements given to isValidInstance() must be inside of an object. "${e}" given.`)}for(const n in t)if(!(t[n]instanceof e)){const r=typeof t[n];throw new TypeError(`${n} must be an instance of ${e.name}. "${r}" given.`)}return{status:!0,error:null}}catch(n){return{status:!1,error:n}}}function s(e,t){try{if("object"!=typeof t){const e=typeof t;throw new TypeError(`Values given to isValidType() must be inside of an object. "${e}" given.`)}for(const n in t){const r=typeof t[n];if(r!==e)throw new TypeError(`${n} must be a ${e}. "${r}" given.`)}return{status:!0,error:null}}catch(n){return{status:!1,error:n}}}function a(e){try{if("object"!=typeof e){const t=typeof e;throw new TypeError(`Values given to isQuerySelector() must be inside of an object. "${t}" given.`)}for(const t in e)try{if(null===e[t])throw new Error;document.querySelector(e[t])}catch{throw new TypeError(`${t} must be a valid query selector. "${e[t]}" given.`)}return{status:!0,error:null}}catch(t){return{status:!1,error:t}}}function l(e){try{if("object"!=typeof e||Array.isArray(e)){const t=typeof e;throw new TypeError(`Values given to isValidClassList() must be inside of an object. "${t}" given.`)}for(const t in e){const n=typeof e[t];if("string"!==n){if(!Array.isArray(e[t]))throw new TypeError(`${t} must be a string or an array of strings. "${n}" given.`);e[t].forEach(e=>{if("string"!=typeof e)throw new TypeError(`${t} must be a string or an array of strings. An array containing non-strings given.`)})}else{const n={};n[t]=e[t],a(n)}}return{status:!0,error:null}}catch(t){return{status:!1,error:t}}}function u(e){try{if("object"!=typeof e){const t=typeof e;throw new TypeError(`Values given to isValidState() must be inside of an object. "${t}" given.`)}const t=["none","self","child"];for(const n in e)if(!t.includes(e[n]))throw new TypeError(`${n} must be one of the following values: ${t.join(", ")}. "${e[n]}" given.`);return{status:!0,error:null}}catch(t){return{status:!1,error:t}}}function c(e){try{if("object"!=typeof e){const t=typeof e;throw new TypeError(`Values given to isValidEvent() must be inside of an object. "${t}" given.`)}const t=["none","mouse","keyboard","character"];for(const n in e)if(!t.includes(e[n]))throw new TypeError(`${n} must be one of the following values: ${t.join(", ")}. "${e[n]}" given.`);return{status:!0,error:null}}catch(t){return{status:!1,error:t}}}function d(e){try{if("object"!=typeof e){const t=typeof e;throw new TypeError(`Values given to isValidHoverType() must be inside of an object. "${t}" given.`)}const t=["off","on","dynamic"];for(const n in e)if(!t.includes(e[n]))throw new TypeError(`${n} must be one of the following values: ${t.join(", ")}. "${e[n]}" given.`);return{status:!0,error:null}}catch(t){return{status:!1,error:t}}}function f(e,t){if(s("string",{tagName:e}).status&&i(HTMLElement,t).status){const n=e.toLowerCase();let r=!0;for(const e in t)t[e].tagName.toLowerCase()!==n&&(r=!1);return r}return!1}n.d(t,{A:function(){return _}});class h{_dom={toggle:null,parent:null};_elements={controlledMenu:null,parentMenu:null};_open=!1;_expandEvent=new CustomEvent("accessibleMenuExpand",{bubbles:!0,detail:{toggle:this}});_collapseEvent=new CustomEvent("accessibleMenuCollapse",{bubbles:!0,detail:{toggle:this}});constructor({menuToggleElement:e,parentElement:t,controlledMenu:n,parentMenu:r=null}){this._dom.toggle=e,this._dom.parent=t,this._elements.controlledMenu=n,this._elements.parentMenu=r}initialize(){this._setIds(),this._setAriaAttributes(),this._collapse(!1)}get dom(){return this._dom}get elements(){return this._elements}get isOpen(){return this._open}set isOpen(e){s("boolean",{isOpen:e}),this._open=e}_setIds(){if(""===this.dom.toggle.id||""===this.elements.controlledMenu.dom.menu.id){let e=this.dom.toggle.innerText?.replace(/[^a-zA-Z0-9\s]/g,"")||"",t=this.elements.controlledMenu.key;!e.replace(/\s/g,"").length&&this.dom.toggle.getAttribute("aria-label")&&(e=this.dom.toggle.getAttribute("aria-label").replace(/[^a-zA-Z0-9\s]/g,"")),e.replace(/\s/g,"").length>0&&(e=e.toLowerCase().replace(/\s+/g,"-"),e.startsWith("-")&&(e=e.substring(1)),e.endsWith("-")&&(e=e.slice(0,-1)),t=`${e}-${t}`),this.dom.toggle.id=this.dom.toggle.id||`menu-button-${t}`,this.elements.controlledMenu.dom.menu.id=this.elements.controlledMenu.dom.menu.id||`menu-${t}`}}_setAriaAttributes(){this.dom.toggle.setAttribute("aria-expanded","false"),this.elements.controlledMenu.dom.menu.setAttribute("aria-labelledby",this.dom.toggle.id)}_expand(e=!0){const{closeClass:t,openClass:n,transitionClass:i,openDuration:s}=this.elements.controlledMenu;this.dom.toggle.setAttribute("aria-expanded","true"),this.elements.controlledMenu.elements.rootMenu.hasOpened=!0,""!==i?(r(i,this.elements.controlledMenu.dom.menu),requestAnimationFrame(()=>{o(t,this.elements.controlledMenu.dom.menu),requestAnimationFrame(()=>{r(n,this.elements.controlledMenu.dom.menu),requestAnimationFrame(()=>{setTimeout(()=>{o(i,this.elements.controlledMenu.dom.menu)},s)})})})):(r(n,this.elements.controlledMenu.dom.menu),o(t,this.elements.controlledMenu.dom.menu)),e&&this.dom.toggle.dispatchEvent(this._expandEvent)}_collapse(e=!0){const{closeClass:t,openClass:n,transitionClass:i,closeDuration:s}=this.elements.controlledMenu;this.dom.toggle.setAttribute("aria-expanded","false"),""!==i?(r(i,this.elements.controlledMenu.dom.menu),requestAnimationFrame(()=>{o(n,this.elements.controlledMenu.dom.menu),requestAnimationFrame(()=>{r(t,this.elements.controlledMenu.dom.menu),requestAnimationFrame(()=>{setTimeout(()=>{o(i,this.elements.controlledMenu.dom.menu)},s)})})})):(r(t,this.elements.controlledMenu.dom.menu),o(n,this.elements.controlledMenu.dom.menu)),e&&this.dom.toggle.dispatchEvent(this._collapseEvent)}open(){this.elements.controlledMenu.focusState="self",this.isOpen||(this._expand(),this.isOpen=!0)}preview(){this.elements.parentMenu&&(this.elements.parentMenu.focusState="self"),this.isOpen||(this._expand(),this.isOpen=!0)}close(){this.isOpen&&(this.elements.controlledMenu.blur(),this.elements.parentMenu&&(this.elements.parentMenu.focusState="self"),this._collapse(),this.isOpen=!1)}toggle(){this.isOpen?this.close():this.open()}closeSiblings(){this.elements.parentMenu&&this.elements.parentMenu.elements.submenuToggles.forEach(e=>{e!==this&&e.close()})}closeChildren(){this.elements.controlledMenu.elements.submenuToggles.forEach(e=>e.close())}}class p{_dom={item:null,link:null};_elements={parentMenu:null,childMenu:null,toggle:null};_submenu=!1;constructor({menuItemElement:e,menuLinkElement:t,parentMenu:n,isSubmenuItem:r=!1,childMenu:o=null,toggle:i=null}){this._dom.item=e,this._dom.link=t,this._elements.parentMenu=n,this._elements.childMenu=o,this._elements.toggle=i,this._submenu=r}initialize(){}get dom(){return this._dom}get elements(){return this._elements}get isSubmenuItem(){return this._submenu}focus(){this.elements.parentMenu.shouldFocus&&requestAnimationFrame(()=>{this.dom.link.focus()})}blur(){this.elements.parentMenu.shouldFocus&&requestAnimationFrame(()=>{this.dom.link.blur()})}}function m(e){try{const t=e.key||e.keyCode,n={Enter:"Enter"===t||13===t,Space:" "===t||"Spacebar"===t||32===t,Escape:"Escape"===t||"Esc"===t||27===t,ArrowUp:"ArrowUp"===t||"Up"===t||38===t,ArrowRight:"ArrowRight"===t||"Right"===t||39===t,ArrowDown:"ArrowDown"===t||"Down"===t||40===t,ArrowLeft:"ArrowLeft"===t||"Left"===t||37===t,Home:"Home"===t||36===t,End:"End"===t||35===t,Character:isNaN(t)&&!!t.match(/^[a-zA-Z]{1}$/),Tab:"Tab"===t||9===t,Asterisk:"*"===t||56===t};return Object.keys(n).find(e=>!0===n[e])||""}catch{return""}}function v(e){e.preventDefault(),e.stopPropagation()}class g{_MenuType=g;_MenuItemType=p;_MenuToggleType=h;_dom={menu:null,menuItems:[],submenuItems:[],submenuToggles:[],submenus:[],controller:null,container:null};_selectors={menuItems:"",menuLinks:"",submenuItems:"",submenuToggles:"",submenus:""};_elements={menuItems:[],submenuToggles:[],controller:null,parentMenu:null,rootMenu:null};_openClass="show";_closeClass="hide";_transitionClass="transitioning";_transitionDuration=250;_openDuration=-1;_closeDuration=-1;_root=!0;_currentChild=0;_focusState="none";_currentEvent="none";_hoverType="off";_hoverDelay=250;_enterDelay=-1;_leaveDelay=-1;_prefix="am-";_hoverTimeout=null;_hasOpened=!1;_key="";_errors=[];constructor({menuElement:e,menuItemSelector:t="li",menuLinkSelector:n="a",submenuItemSelector:r="li:has(ul)",submenuToggleSelector:o="a",submenuSelector:i="ul",controllerElement:s=null,containerElement:a=null,openClass:l="show",closeClass:u="hide",transitionClass:c="transitioning",transitionDuration:d=250,openDuration:f=-1,closeDuration:h=-1,isTopLevel:p=!0,parentMenu:m=null,hoverType:v="off",hoverDelay:g=250,enterDelay:y=-1,leaveDelay:b=-1,prefix:_="am-",key:E=null}){this._dom.menu=e,this._dom.controller=s,this._dom.container=a,this._selectors.menuItems=t,this._selectors.menuLinks=n,this._selectors.submenuItems=r,this._selectors.submenuToggles=o,this._selectors.submenus=i,this._elements.menuItems=[],this._elements.submenuToggles=[],this._elements.controller=null,this._elements.parentMenu=m,this._elements.rootMenu=p?this:null,this._openClass=l||"",this._closeClass=u||"",this._transitionClass=c||"",this._transitionDuration=d,this._openDuration=f,this._closeDuration=h,this._prefix=_||"",this._key=E||"",this._root=p,this._hoverType=v,this._hoverDelay=g,this._enterDelay=y,this._leaveDelay=b}initialize(){if(!this._validate())throw new Error(`AccessibleMenu: cannot initialize menu. The following errors have been found:\n - ${this.errors.join("\n - ")}`);if(null===this.elements.rootMenu&&this._findRootMenu(this),this._generateKey(),this._setDOMElements(),this.isTopLevel){if(this._setIds(),this.dom.controller&&this.dom.container){const e=new this._MenuToggleType({menuToggleElement:this.dom.controller,parentElement:this.dom.container,controlledMenu:this});f("button",{toggle:e.dom.toggle})||e.dom.toggle.setAttribute("role","button"),e.dom.toggle.setAttribute("aria-controls",this.dom.menu.id),this._elements.controller=e}window.AccessibleMenu=window.AccessibleMenu||{menus:{}},"object"!=typeof window.AccessibleMenu.menus&&(window.AccessibleMenu.menus={}),window.AccessibleMenu.menus[this.dom.menu.id]=this}this._createChildElements(),this._setTransitionDurations()}get dom(){return this._dom}get selectors(){return this._selectors}get elements(){return this._elements}get isTopLevel(){return this._root}get key(){if(this.isTopLevel)return this._key;const e=this.elements.parentMenu.dom.submenus.indexOf(this.dom.menu)||0;return`${this.elements.parentMenu.key}-${e}`}get errors(){return this._errors}get openClass(){return this.isTopLevel?this._openClass:this.elements.rootMenu.openClass}set openClass(e){l({openClass:e}),this._openClass!==e&&(this._openClass=e)}get closeClass(){return this.isTopLevel?this._closeClass:this.elements.rootMenu.closeClass}set closeClass(e){l({closeClass:e}),this._closeClass!==e&&(this._closeClass=e)}get transitionClass(){return this.isTopLevel?this._transitionClass:this.elements.rootMenu.transitionClass}set transitionClass(e){l({transitionClass:e}),this._transitionClass!==e&&(this._transitionClass=e)}get transitionDuration(){return this.isTopLevel?this._transitionDuration:this.elements.rootMenu.transitionDuration}set transitionDuration(e){s("number",{transitionDuration:e}),this._transitionDuration!==e&&(this._transitionDuration=e,this._setTransitionDurations())}get openDuration(){return-1===this._openDuration?this.transitionDuration:this.isTopLevel?this._openDuration:this.elements.rootMenu.openDuration}set openDuration(e){s("number",{openDuration:e}),this._openDuration!==e&&(this._openDuration=e,this._setTransitionDurations())}get closeDuration(){return-1===this._closeDuration?this.transitionDuration:this.isTopLevel?this._closeDuration:this.elements.rootMenu.closeDuration}set closeDuration(e){s("number",{closeDuration:e}),this._closeDuration!==e&&(this._closeDuration=e,this._setTransitionDurations())}get currentChild(){return this._currentChild}set currentChild(e){function t(e){if(["mouse","character"].includes(e.currentEvent)&&e.elements.parentMenu){let t=0,n=!1;for(;!n&&t<e.elements.parentMenu.elements.menuItems.length;){const r=e.elements.parentMenu.elements.menuItems[t];r.isSubmenuItem&&r.elements.toggle.elements.controlledMenu===e&&(n=!0,e.elements.parentMenu.currentEvent=e.currentEvent,e.elements.parentMenu.currentChild=t),t++}}}s("number",{currentChild:e}),e<-1?(this._currentChild=-1,t(this)):e>=this.elements.menuItems.length?(this._currentChild=this.elements.menuItems.length-1,t(this)):this.focusChild!==e&&(this._currentChild=e,t(this))}get focusState(){return this._focusState}set focusState(e){u({focusState:e}),this._focusState!==e&&(this._focusState=e),this.elements.submenuToggles.length>0&&("self"===e||"none"===e)&&this.elements.submenuToggles.forEach(e=>{e.elements.controlledMenu.focusState="none"}),this.elements.parentMenu&&("self"===e||"child"===e)&&(this.elements.parentMenu.focusState="child")}get currentEvent(){return this._currentEvent}set currentEvent(e){c({currentEvent:e}),this._currentEvent!==e&&(this._currentEvent=e,this.elements.submenuToggles.length>0&&this.elements.submenuToggles.forEach(t=>{t.elements.controlledMenu.currentEvent=e}))}get currentMenuItem(){return this.elements.menuItems[this.currentChild]}get hoverType(){return this._root?this._hoverType:this.elements.rootMenu.hoverType}set hoverType(e){d({hoverType:e}),this._hoverType!==e&&(this._hoverType=e)}get hoverDelay(){return this._root?this._hoverDelay:this.elements.rootMenu.hoverDelay}set hoverDelay(e){s("number",{hoverDelay:e}),this._hoverDelay!==e&&(this._hoverDelay=e)}get enterDelay(){return-1===this._enterDelay?this.hoverDelay:this._root?this._enterDelay:this.elements.rootMenu.enterDelay}set enterDelay(e){s("number",{enterDelay:e}),this._enterDelay!==e&&(this._enterDelay=e)}get leaveDelay(){return-1===this._leaveDelay?this.hoverDelay:this._root?this._leaveDelay:this.elements.rootMenu.leaveDelay}set leaveDelay(e){s("number",{leaveDelay:e}),this._leaveDelay!==e&&(this._leaveDelay=e)}get prefix(){return this._root?this._prefix:this.elements.rootMenu.prefix}set prefix(e){s("string",{prefix:e}),this._prefix!==e&&(this._prefix=e)}get shouldFocus(){let e=!1;return("keyboard"===this.currentEvent||"character"===this.currentEvent)&&(e=!0),"mouse"===this.currentEvent&&"dynamic"===this.hoverType&&(e=!0),e}get hasOpened(){return this._root?this._hasOpened:this.elements.rootMenu.hasOpened}set hasOpened(e){s("boolean",{hasOpened:e}),this._hasOpened!==e&&(this._hasOpened=e)}_validate(){let e,t,n=!0;if(e=null!==this._dom.container||null!==this._dom.controller?i(HTMLElement,{menuElement:this._dom.menu,controllerElement:this._dom.controller,containerElement:this._dom.container}):i(HTMLElement,{menuElement:this._dom.menu}),e.status||(this._errors.push(e.error.message),n=!1),t=""!==this._selectors.submenuItems?a({menuItemSelector:this._selectors.menuItems,menuLinkSelector:this._selectors.menuLinks,submenuItemSelector:this._selectors.submenuItems,submenuToggleSelector:this._selectors.submenuToggles,submenuSelector:this._selectors.submenus}):a({menuItemSelector:this._selectors.menuItems,menuLinkSelector:this._selectors.menuLinks}),t.status||(this._errors.push(t.error.message),n=!1),""!==this._openClass){const e=l({openClass:this._openClass});e.status||(this._errors.push(e.error.message),n=!1)}if(""!==this._closeClass){const e=l({closeClass:this._closeClass});e.status||(this._errors.push(e.error.message),n=!1)}if(""!==this._transitionClass){const e=l({transitionClass:this._transitionClass});e.status||(this._errors.push(e.error.message),n=!1)}const r=s("number",{transitionDuration:this._transitionDuration});r.status||(this._errors.push(r.error.message),n=!1);const o=s("number",{openDuration:this._openDuration});o.status||(this._errors.push(o.error.message),n=!1);const u=s("number",{closeDuration:this._closeDuration});u.status||(this._errors.push(u.error.message),n=!1);const c=s("boolean",{isTopLevel:this._root});if(c.status||(this._errors.push(c.error.message),n=!1),null!==this._elements.parentMenu){const e=i(g,{parentMenu:this._elements.parentMenu});e.status||(this._errors.push(e.error.message),n=!1)}const f=d({hoverType:this._hoverType});f.status||(this._errors.push(f.error.message),n=!1);const h=s("number",{hoverDelay:this._hoverDelay});h.status||(this._errors.push(h.error.message),n=!1);const p=s("number",{enterDelay:this._enterDelay});p.status||(this._errors.push(p.error.message),n=!1);const m=s("number",{leaveDelay:this._leaveDelay});if(m.status||(this._errors.push(m.error.message),n=!1),""!==this._key){const e=s("string",{key:this._key});e.status||(this._errors.push(e.error.message),n=!1)}const v=s("string",{prefix:this._prefix});return v.status||(this._errors.push(v.error.message),n=!1),n}_setDOMElementType(e,t=this.dom.menu,n=!0){if("string"!=typeof this.selectors[e])throw new Error(`AccessibleMenu: "${e}" is not a valid element type within the menu.`);{if(!Array.isArray(this.dom[e]))throw new Error(`AccessibleMenu: The "${e}" element cannot be set through _setDOMElementType.`);t!==this.dom.menu&&i(HTMLElement,{base:t});const r=Array.from(t.querySelectorAll(this.selectors[e])).filter(e=>e.parentElement===t);this._dom[e]=n?r:[...this._dom[e],...r]}}_resetDOMElementType(e){if(!(typeof this.dom[e]<"u"))throw new Error(`AccessibleMenu: "${e}" is not a valid element type within the menu.`);if(!Array.isArray(this.dom[e]))throw new Error(`AccessibleMenu: The "${e}" element cannot be reset through _resetDOMElementType.`);this._dom[e]=[]}_setDOMElements(){this._setDOMElementType("menuItems"),""!==this.selectors.submenuItems&&(this._setDOMElementType("submenuItems"),this._resetDOMElementType("submenuToggles"),this._resetDOMElementType("submenus"),this.dom.submenuItems.forEach(e=>{this._setDOMElementType("submenuToggles",e,!1),this._setDOMElementType("submenus",e,!1)}))}_generateKey(e=!1){(""===this.key||e)&&(this._key=Math.random().toString(36).replace(/[^a-z]+/g,"").substring(0,10))}_setIds(){this.dom.menu.id=this.dom.menu.id||`menu-${this.key}`,this.dom.container&&(this.dom.container.id=this.dom.container.id||`menu-container-${this.key}`),this.dom.controller&&(this.dom.controller.id=this.dom.controller.id||`menu-controller-${this.key}`)}_findRootMenu(e){if(e.isTopLevel)this._elements.rootMenu=e;else{if(null===e.elements.parentMenu)throw new Error("Cannot find root menu.");this._findRootMenu(e.elements.parentMenu)}}_createChildElements(){this.dom.menuItems.forEach(e=>{let t;if(this.dom.submenuItems.includes(e)){const n=e.querySelector(this.selectors.submenuToggles),r=e.querySelector(this.selectors.submenus),o=new this._MenuType({menuElement:r,menuItemSelector:this.selectors.menuItems,menuLinkSelector:this.selectors.menuLinks,submenuItemSelector:this.selectors.submenuItems,submenuToggleSelector:this.selectors.submenuToggles,submenuSelector:this.selectors.submenus,openClass:this.openClass,closeClass:this.closeClass,transitionClass:this.transitionClass,transitionDuration:this.transitionDuration,openDuration:this.openDuration,closeDuration:this.closeDuration,isTopLevel:!1,parentMenu:this,hoverType:this.hoverType,hoverDelay:this.hoverDelay,enterDelay:this.enterDelay,leaveDelay:this.leaveDelay}),i=new this._MenuToggleType({menuToggleElement:n,parentElement:e,controlledMenu:o,parentMenu:this});this._elements.submenuToggles.push(i),t=new this._MenuItemType({menuItemElement:e,menuLinkElement:n,parentMenu:this,isSubmenuItem:!0,childMenu:o,toggle:i})}else{const n=e.querySelector(this.selectors.menuLinks);t=new this._MenuItemType({menuItemElement:e,menuLinkElement:n,parentMenu:this})}this._elements.menuItems.push(t)})}_clearTimeout(){clearTimeout(this._hoverTimeout)}_setTimeout(e,t){s("function",{callback:e}),s("number",{delay:t}),this._hoverTimeout=setTimeout(e,t)}_handleFocus(){this.elements.menuItems.forEach((e,t)=>{e.dom.link.addEventListener("focus",()=>{this.focusState="self",this.currentChild=t})}),this.dom.menu.addEventListener("focusout",e=>{"keyboard"!==this.currentEvent||null===e.relatedTarget||this.dom.menu.contains(e.relatedTarget)||(this.focusState="none",this.closeChildren())})}_handleClick(){function e(e,t,n){v(n),0===n.button&&(t.toggle(),t.isOpen&&(e.focusState="self",t.elements.controlledMenu.focusState="none"))}this.elements.menuItems.forEach((t,n)=>{t.dom.link.addEventListener("click",()=>{this.currentEvent="mouse",this.elements.rootMenu.blurChildren(),this._clearTimeout(),this.focusChild(n)},{passive:!0}),t.isSubmenuItem&&t.elements.toggle.dom.toggle.addEventListener("click",n=>{this.currentEvent="mouse",e(this,t.elements.toggle,n)})}),this.isTopLevel&&this.elements.controller&&this.elements.controller.dom.toggle.addEventListener("click",t=>{this.currentEvent="mouse",e(this,this.elements.controller,t)}),document.addEventListener("click",e=>{"none"!==this.focusState&&(this.currentEvent="mouse",!this.dom.menu.contains(e.target)&&!this.dom.menu!==e.target&&(this.elements.rootMenu.hasOpened=this.elements.submenuToggles.some(e=>e.isOpen)))})}_handleHover(){this.elements.menuItems.forEach((e,t)=>{e.dom.link.addEventListener("pointerenter",n=>{"pen"===n.pointerType||"touch"===n.pointerType||("on"===this.hoverType?(this.currentEvent="mouse",this.elements.rootMenu.blurChildren(),this.focusChild(t),e.isSubmenuItem&&(this.enterDelay>0?(this._clearTimeout(),this._setTimeout(()=>{e.elements.toggle.preview()},this.enterDelay)):e.elements.toggle.preview())):"dynamic"===this.hoverType&&(this.currentChild=t,(!this.isTopLevel||"none"!==this.focusState)&&(this.currentEvent="mouse",this.elements.rootMenu.blurChildren(),this.focusCurrentChild()),(!this.isTopLevel||this.hasOpened)&&(this.currentEvent="mouse",this.elements.rootMenu.blurChildren(),this.focusCurrentChild(),e.isSubmenuItem?this.enterDelay>0?(this._clearTimeout(),this._setTimeout(()=>{e.elements.toggle.preview()},this.enterDelay)):e.elements.toggle.preview():this.enterDelay>0?(this._clearTimeout(),this._setTimeout(()=>{this.closeChildren()},this.enterDelay)):this.closeChildren())))}),e.isSubmenuItem&&(e.dom.item.addEventListener("pointerleave",t=>{"pen"===t.pointerType||"touch"===t.pointerType||("on"===this.hoverType?this.leaveDelay>0?(this._clearTimeout(),this._setTimeout(()=>{this.currentEvent="mouse",e.elements.toggle.close()},this.leaveDelay)):(this.currentEvent="mouse",e.elements.toggle.close()):"dynamic"===this.hoverType&&(this.leaveDelay>0?(this._clearTimeout(),this._setTimeout(()=>{this.currentEvent="mouse"},this.leaveDelay)):this.currentEvent="mouse"))}),e.dom.item.addEventListener("pointerenter",t=>{"pen"===t.pointerType||"touch"===t.pointerType||e.isSubmenuItem&&("on"===this.hoverType||"dynamic"===this.hoverType)&&this.leaveDelay>0&&this._clearTimeout()}))})}_handleKeydown(){this.isTopLevel&&this.elements.controller&&this.elements.controller.dom.toggle.addEventListener("keydown",e=>{this.currentEvent="keyboard";const t=m(e);("Space"===t||"Enter"===t)&&v(e)})}_handleKeyup(){this.isTopLevel&&this.elements.controller&&this.elements.controller.dom.toggle.addEventListener("keyup",e=>{this.currentEvent="keyboard";const t=m(e);("Space"===t||"Enter"===t)&&(v(e),this.elements.controller.toggle(),this.elements.controller.isOpen&&this.focusFirstChild())})}_setTransitionDurations(){this.dom.menu.style.setProperty(`--${this.prefix}transition-duration`,`${this.transitionDuration}ms`),this.dom.menu.style.setProperty(`--${this.prefix}open-transition-duration`,`${this.openDuration}ms`),this.dom.menu.style.setProperty(`--${this.prefix}close-transition-duration`,`${this.closeDuration}ms`)}focus(){this.focusState="self",this.shouldFocus&&this.dom.menu.focus()}blur(){this.focusState="none",this.shouldFocus&&this.dom.menu.blur()}focusCurrentChild(){this.focusState="self",-1!==this.currentChild&&this.currentMenuItem.focus()}focusChild(e){this.blurCurrentChild(),this.currentChild=e,this.focusCurrentChild()}focusFirstChild(){this.focusChild(0)}focusLastChild(){this.focusChild(this.elements.menuItems.length-1)}focusNextChild(){this.currentChild<this.elements.menuItems.length-1?this.focusChild(this.currentChild+1):this.focusCurrentChild()}focusPreviousChild(){this.currentChild>0?this.focusChild(this.currentChild-1):this.focusCurrentChild()}blurCurrentChild(){this.focusState="none",-1!==this.currentChild&&this.currentMenuItem.blur()}focusController(){this.dom.controller&&(this.shouldFocus&&this.dom.controller.focus(),this.focusState="none")}focusContainer(){this.dom.container&&(this.shouldFocus&&this.dom.container.focus(),this.focusState="none")}closeChildren(){this.elements.submenuToggles.forEach(e=>e.close())}blurChildren(){this.elements.menuItems.forEach(e=>{e.blur(),e.isSubmenuItem&&e.elements.childMenu.blurChildren()})}}class y extends p{constructor({menuItemElement:e,menuLinkElement:t,parentMenu:n,isSubmenuItem:r=!1,childMenu:o=null,toggle:i=null,initialize:s=!0}){super({menuItemElement:e,menuLinkElement:t,parentMenu:n,isSubmenuItem:r,childMenu:o,toggle:i}),s&&this.initialize()}}class b extends h{constructor({menuToggleElement:e,parentElement:t,controlledMenu:n,parentMenu:r=null,initialize:o=!0}){super({menuToggleElement:e,parentElement:t,controlledMenu:n,parentMenu:r}),o&&this.initialize()}_setAriaAttributes(){super._setAriaAttributes(),f("button",{toggle:this.dom.toggle})||this.dom.toggle.setAttribute("role","button"),this.dom.toggle.setAttribute("aria-controls",this.elements.controlledMenu.dom.menu.id)}open(){this.closeSiblings(),super.open()}preview(){this.closeSiblings(),super.preview()}close(){this.isOpen&&this.closeChildren(),super.close()}}class _ extends g{_MenuType=_;_MenuItemType=y;_MenuToggleType=b;_currentChild=-1;_optionalSupport=!1;constructor({menuElement:e,menuItemSelector:t="li",menuLinkSelector:n="a",submenuItemSelector:r="li:has(ul)",submenuToggleSelector:o="button",submenuSelector:i="ul",controllerElement:s=null,containerElement:a=null,openClass:l="show",closeClass:u="hide",transitionClass:c="transitioning",transitionDuration:d=250,openDuration:f=-1,closeDuration:h=-1,isTopLevel:p=!0,parentMenu:m=null,hoverType:v="off",hoverDelay:g=250,enterDelay:y=-1,leaveDelay:b=-1,optionalKeySupport:_=!1,prefix:E="am-",key:w=null,initialize:S=!0}){super({menuElement:e,menuItemSelector:t,menuLinkSelector:n,submenuItemSelector:r,submenuToggleSelector:o,submenuSelector:i,controllerElement:s,containerElement:a,openClass:l,closeClass:u,transitionClass:c,transitionDuration:d,openDuration:f,closeDuration:h,isTopLevel:p,parentMenu:m,hoverType:v,hoverDelay:g,enterDelay:y,leaveDelay:b,prefix:E,key:w}),this._optionalSupport=_,S&&this.initialize()}initialize(){try{super.initialize(),this._handleFocus(),this._handleClick(),this._handleHover(),this._handleKeydown(),this._handleKeyup()}catch(e){console.error(e)}}get optionalKeySupport(){return this.isTopLevel?this._optionalSupport:this.elements.rootMenu.optionalKeySupport}set optionalKeySupport(e){s("boolean",{optionalKeySupport:e}),this._optionalSupport=e}_validate(){let e=super._validate();const t=s("boolean",{optionalKeySupport:this._optionalSupport});return t.status||(this._errors.push(t.error.message),e=!1),e}_handleClick(){super._handleClick(),document.addEventListener("click",e=>{"none"!==this.focusState&&(this.currentEvent="mouse",!this.dom.menu.contains(e.target)&&!this.dom.menu!==e.target&&(this.closeChildren(),this.blur(),this.elements.controller&&this.elements.controller.close(),this.elements.rootMenu.hasOpened=!1))})}_handleKeydown(){super._handleKeydown(),this.dom.menu.addEventListener("keydown",e=>{this.currentEvent="keyboard";const t=m(e);if("self"===this.focusState){const n=["Space","Enter"],r=["Escape"],o=["Escape"],i=["ArrowUp","ArrowRight","ArrowDown","ArrowLeft","Home","End"];(n.includes(t)||this.optionalKeySupport&&i.includes(t)||this.elements.controller&&r.includes(t)||this.elements.parentMenu&&o.includes(t))&&v(e)}})}_handleKeyup(){super._handleKeyup(),this.dom.menu.addEventListener("keyup",e=>{this.currentEvent="keyboard";const t=m(e);"self"===this.focusState&&("Space"===t||"Enter"===t?(v(e),this.currentMenuItem.isSubmenuItem?this.currentMenuItem.elements.toggle.isOpen?this.currentMenuItem.elements.toggle.close():this.currentMenuItem.elements.toggle.preview():this.currentMenuItem.dom.link.click()):"Escape"===t?this.elements.submenuToggles.some(e=>e.isOpen)?(v(e),this.closeChildren()):this.elements.parentMenu?(v(e),this.elements.parentMenu.currentEvent=this.currentEvent,this.elements.parentMenu.closeChildren(),this.elements.parentMenu.focusCurrentChild()):this.isTopLevel&&this.elements.controller&&this.elements.controller.isOpen&&(this.elements.controller.close(),this.focusController()):this.optionalKeySupport&&("ArrowDown"===t||"ArrowRight"===t?(v(e),this.currentMenuItem.isSubmenuItem&&this.currentMenuItem.elements.toggle.isOpen?(this.currentMenuItem.elements.childMenu.currentEvent="keyboard",this.currentMenuItem.elements.childMenu.focusFirstChild()):this.focusNextChild()):"ArrowUp"===t||"ArrowLeft"===t?(v(e),this.focusPreviousChild()):"Home"===t?(v(e),this.focusFirstChild()):"End"===t&&(v(e),this.focusLastChild())))})}}},4335:function(e,t,n){"use strict";n.d(t,{A:function(){return Tn}});var r={};function o(e,t){return function(){return e.apply(t,arguments)}}n.r(r),n.d(r,{hasBrowserEnv:function(){return Be},hasStandardBrowserEnv:function(){return Ge},hasStandardBrowserWebWorkerEnv:function(){return He},navigator:function(){return Ve},origin:function(){return We}});const{toString:i}=Object.prototype,{getPrototypeOf:s}=Object,{iterator:a,toStringTag:l}=Symbol,u=(e=>t=>{const n=i.call(t);return e[n]||(e[n]=n.slice(8,-1).toLowerCase())})(Object.create(null)),c=e=>(e=e.toLowerCase(),t=>u(t)===e),d=e=>t=>typeof t===e,{isArray:f}=Array,h=d("undefined");function p(e){return null!==e&&!h(e)&&null!==e.constructor&&!h(e.constructor)&&y(e.constructor.isBuffer)&&e.constructor.isBuffer(e)}const m=c("ArrayBuffer");function v(e){let t;return t="undefined"!==typeof ArrayBuffer&&ArrayBuffer.isView?ArrayBuffer.isView(e):e&&e.buffer&&m(e.buffer),t}const g=d("string"),y=d("function"),b=d("number"),_=e=>null!==e&&"object"===typeof e,E=e=>!0===e||!1===e,w=e=>{if("object"!==u(e))return!1;const t=s(e);return(null===t||t===Object.prototype||null===Object.getPrototypeOf(t))&&!(l in e)&&!(a in e)},S=e=>{if(!_(e)||p(e))return!1;try{return 0===Object.keys(e).length&&Object.getPrototypeOf(e)===Object.prototype}catch(t){return!1}},T=c("Date"),k=c("File"),C=e=>!(!e||"undefined"===typeof e.uri),O=e=>e&&"undefined"!==typeof e.getParts,A=c("Blob"),R=c("FileList"),I=e=>_(e)&&y(e.pipe);function N(){return"undefined"!==typeof globalThis?globalThis:"undefined"!==typeof self?self:"undefined"!==typeof window?window:"undefined"!==typeof n.g?n.g:{}}const L=N(),x="undefined"!==typeof L.FormData?L.FormData:void 0,P=e=>{let t;return e&&(x&&e instanceof x||y(e.append)&&("formdata"===(t=u(e))||"object"===t&&y(e.toString)&&"[object FormData]"===e.toString()))},D=c("URLSearchParams"),[M,F,$,j]=["ReadableStream","Request","Response","Headers"].map(c),U=e=>e.trim?e.trim():e.replace(/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,"");function B(e,t,{allOwnKeys:n=!1}={}){if(null===e||"undefined"===typeof e)return;let r,o;if("object"!==typeof e&&(e=[e]),f(e))for(r=0,o=e.length;r<o;r++)t.call(null,e[r],r,e);else{if(p(e))return;const o=n?Object.getOwnPropertyNames(e):Object.keys(e),i=o.length;let s;for(r=0;r<i;r++)s=o[r],t.call(null,e[s],s,e)}}function V(e,t){if(p(e))return null;t=t.toLowerCase();const n=Object.keys(e);let r,o=n.length;while(o-- >0)if(r=n[o],t===r.toLowerCase())return r;return null}const G=(()=>"undefined"!==typeof globalThis?globalThis:"undefined"!==typeof self?self:"undefined"!==typeof window?window:n.g)(),H=e=>!h(e)&&e!==G;function W(){const{caseless:e,skipUndefined:t}=H(this)&&this||{},n={},r=(r,o)=>{if("__proto__"===o||"constructor"===o||"prototype"===o)return;const i=e&&V(n,o)||o;w(n[i])&&w(r)?n[i]=W(n[i],r):w(r)?n[i]=W({},r):f(r)?n[i]=r.slice():t&&h(r)||(n[i]=r)};for(let o=0,i=arguments.length;o<i;o++)arguments[o]&&B(arguments[o],r);return n}const X=(e,t,n,{allOwnKeys:r}={})=>(B(t,(t,r)=>{n&&y(t)?Object.defineProperty(e,r,{value:o(t,n),writable:!0,enumerable:!0,configurable:!0}):Object.defineProperty(e,r,{value:t,writable:!0,enumerable:!0,configurable:!0})},{allOwnKeys:r}),e),K=e=>(65279===e.charCodeAt(0)&&(e=e.slice(1)),e),q=(e,t,n,r)=>{e.prototype=Object.create(t.prototype,r),Object.defineProperty(e.prototype,"constructor",{value:e,writable:!0,enumerable:!1,configurable:!0}),Object.defineProperty(e,"super",{value:t.prototype}),n&&Object.assign(e.prototype,n)},z=(e,t,n,r)=>{let o,i,a;const l={};if(t=t||{},null==e)return t;do{o=Object.getOwnPropertyNames(e),i=o.length;while(i-- >0)a=o[i],r&&!r(a,e,t)||l[a]||(t[a]=e[a],l[a]=!0);e=!1!==n&&s(e)}while(e&&(!n||n(e,t))&&e!==Object.prototype);return t},Y=(e,t,n)=>{e=String(e),(void 0===n||n>e.length)&&(n=e.length),n-=t.length;const r=e.indexOf(t,n);return-1!==r&&r===n},Q=e=>{if(!e)return null;if(f(e))return e;let t=e.length;if(!b(t))return null;const n=new Array(t);while(t-- >0)n[t]=e[t];return n},J=(e=>t=>e&&t instanceof e)("undefined"!==typeof Uint8Array&&s(Uint8Array)),Z=(e,t)=>{const n=e&&e[a],r=n.call(e);let o;while((o=r.next())&&!o.done){const n=o.value;t.call(e,n[0],n[1])}},ee=(e,t)=>{let n;const r=[];while(null!==(n=e.exec(t)))r.push(n);return r},te=c("HTMLFormElement"),ne=e=>e.toLowerCase().replace(/[-_\s]([a-z\d])(\w*)/g,function(e,t,n){return t.toUpperCase()+n}),re=(({hasOwnProperty:e})=>(t,n)=>e.call(t,n))(Object.prototype),oe=c("RegExp"),ie=(e,t)=>{const n=Object.getOwnPropertyDescriptors(e),r={};B(n,(n,o)=>{let i;!1!==(i=t(n,o,e))&&(r[o]=i||n)}),Object.defineProperties(e,r)},se=e=>{ie(e,(t,n)=>{if(y(e)&&-1!==["arguments","caller","callee"].indexOf(n))return!1;const r=e[n];y(r)&&(t.enumerable=!1,"writable"in t?t.writable=!1:t.set||(t.set=()=>{throw Error("Can not rewrite read-only method '"+n+"'")}))})},ae=(e,t)=>{const n={},r=e=>{e.forEach(e=>{n[e]=!0})};return f(e)?r(e):r(String(e).split(t)),n},le=()=>{},ue=(e,t)=>null!=e&&Number.isFinite(e=+e)?e:t;function ce(e){return!!(e&&y(e.append)&&"FormData"===e[l]&&e[a])}const de=e=>{const t=new Array(10),n=(e,r)=>{if(_(e)){if(t.indexOf(e)>=0)return;if(p(e))return e;if(!("toJSON"in e)){t[r]=e;const o=f(e)?[]:{};return B(e,(e,t)=>{const i=n(e,r+1);!h(i)&&(o[t]=i)}),t[r]=void 0,o}}return e};return n(e,0)},fe=c("AsyncFunction"),he=e=>e&&(_(e)||y(e))&&y(e.then)&&y(e.catch),pe=((e,t)=>e?setImmediate:t?((e,t)=>(G.addEventListener("message",({source:n,data:r})=>{n===G&&r===e&&t.length&&t.shift()()},!1),n=>{t.push(n),G.postMessage(e,"*")}))(`axios@${Math.random()}`,[]):e=>setTimeout(e))("function"===typeof setImmediate,y(G.postMessage)),me="undefined"!==typeof queueMicrotask?queueMicrotask.bind(G):"undefined"!==typeof process&&process.nextTick||pe,ve=e=>null!=e&&y(e[a]);var ge={isArray:f,isArrayBuffer:m,isBuffer:p,isFormData:P,isArrayBufferView:v,isString:g,isNumber:b,isBoolean:E,isObject:_,isPlainObject:w,isEmptyObject:S,isReadableStream:M,isRequest:F,isResponse:$,isHeaders:j,isUndefined:h,isDate:T,isFile:k,isReactNativeBlob:C,isReactNative:O,isBlob:A,isRegExp:oe,isFunction:y,isStream:I,isURLSearchParams:D,isTypedArray:J,isFileList:R,forEach:B,merge:W,extend:X,trim:U,stripBOM:K,inherits:q,toFlatObject:z,kindOf:u,kindOfTest:c,endsWith:Y,toArray:Q,forEachEntry:Z,matchAll:ee,isHTMLForm:te,hasOwnProperty:re,hasOwnProp:re,reduceDescriptors:ie,freezeMethods:se,toObjectSet:ae,toCamelCase:ne,noop:le,toFiniteNumber:ue,findKey:V,global:G,isContextDefined:H,isSpecCompliantForm:ce,toJSONObject:de,isAsyncFn:fe,isThenable:he,setImmediate:pe,asap:me,isIterable:ve};class ye extends Error{static from(e,t,n,r,o,i){const s=new ye(e.message,t||e.code,n,r,o);return s.cause=e,s.name=e.name,null!=e.status&&null==s.status&&(s.status=e.status),i&&Object.assign(s,i),s}constructor(e,t,n,r,o){super(e),Object.defineProperty(this,"message",{value:e,enumerable:!0,writable:!0,configurable:!0}),this.name="AxiosError",this.isAxiosError=!0,t&&(this.code=t),n&&(this.config=n),r&&(this.request=r),o&&(this.response=o,this.status=o.status)}toJSON(){return{message:this.message,name:this.name,description:this.description,number:this.number,fileName:this.fileName,lineNumber:this.lineNumber,columnNumber:this.columnNumber,stack:this.stack,config:ge.toJSONObject(this.config),code:this.code,status:this.status}}}ye.ERR_BAD_OPTION_VALUE="ERR_BAD_OPTION_VALUE",ye.ERR_BAD_OPTION="ERR_BAD_OPTION",ye.ECONNABORTED="ECONNABORTED",ye.ETIMEDOUT="ETIMEDOUT",ye.ERR_NETWORK="ERR_NETWORK",ye.ERR_FR_TOO_MANY_REDIRECTS="ERR_FR_TOO_MANY_REDIRECTS",ye.ERR_DEPRECATED="ERR_DEPRECATED",ye.ERR_BAD_RESPONSE="ERR_BAD_RESPONSE",ye.ERR_BAD_REQUEST="ERR_BAD_REQUEST",ye.ERR_CANCELED="ERR_CANCELED",ye.ERR_NOT_SUPPORT="ERR_NOT_SUPPORT",ye.ERR_INVALID_URL="ERR_INVALID_URL";var be=ye,_e=null;function Ee(e){return ge.isPlainObject(e)||ge.isArray(e)}function we(e){return ge.endsWith(e,"[]")?e.slice(0,-2):e}function Se(e,t,n){return e?e.concat(t).map(function(e,t){return e=we(e),!n&&t?"["+e+"]":e}).join(n?".":""):t}function Te(e){return ge.isArray(e)&&!e.some(Ee)}const ke=ge.toFlatObject(ge,{},null,function(e){return/^is[A-Z]/.test(e)});function Ce(e,t,n){if(!ge.isObject(e))throw new TypeError("target must be an object");t=t||new(_e||FormData),n=ge.toFlatObject(n,{metaTokens:!0,dots:!1,indexes:!1},!1,function(e,t){return!ge.isUndefined(t[e])});const r=n.metaTokens,o=n.visitor||c,i=n.dots,s=n.indexes,a=n.Blob||"undefined"!==typeof Blob&&Blob,l=a&&ge.isSpecCompliantForm(t);if(!ge.isFunction(o))throw new TypeError("visitor must be a function");function u(e){if(null===e)return"";if(ge.isDate(e))return e.toISOString();if(ge.isBoolean(e))return e.toString();if(!l&&ge.isBlob(e))throw new be("Blob is not supported. Use a Buffer instead.");return ge.isArrayBuffer(e)||ge.isTypedArray(e)?l&&"function"===typeof Blob?new Blob([e]):Buffer.from(e):e}function c(e,n,o){let a=e;if(ge.isReactNative(t)&&ge.isReactNativeBlob(e))return t.append(Se(o,n,i),u(e)),!1;if(e&&!o&&"object"===typeof e)if(ge.endsWith(n,"{}"))n=r?n:n.slice(0,-2),e=JSON.stringify(e);else if(ge.isArray(e)&&Te(e)||(ge.isFileList(e)||ge.endsWith(n,"[]"))&&(a=ge.toArray(e)))return n=we(n),a.forEach(function(e,r){!ge.isUndefined(e)&&null!==e&&t.append(!0===s?Se([n],r,i):null===s?n:n+"[]",u(e))}),!1;return!!Ee(e)||(t.append(Se(o,n,i),u(e)),!1)}const d=[],f=Object.assign(ke,{defaultVisitor:c,convertValue:u,isVisitable:Ee});function h(e,n){if(!ge.isUndefined(e)){if(-1!==d.indexOf(e))throw Error("Circular reference detected in "+n.join("."));d.push(e),ge.forEach(e,function(e,r){const i=!(ge.isUndefined(e)||null===e)&&o.call(t,e,ge.isString(r)?r.trim():r,n,f);!0===i&&h(e,n?n.concat(r):[r])}),d.pop()}}if(!ge.isObject(e))throw new TypeError("data must be an object");return h(e),t}var Oe=Ce;function Ae(e){const t={"!":"%21","'":"%27","(":"%28",")":"%29","~":"%7E","%20":"+","%00":"\0"};return encodeURIComponent(e).replace(/[!'()~]|%20|%00/g,function(e){return t[e]})}function Re(e,t){this._pairs=[],e&&Oe(e,this,t)}const Ie=Re.prototype;Ie.append=function(e,t){this._pairs.push([e,t])},Ie.toString=function(e){const t=e?function(t){return e.call(this,t,Ae)}:Ae;return this._pairs.map(function(e){return t(e[0])+"="+t(e[1])},"").join("&")};var Ne=Re;function Le(e){return encodeURIComponent(e).replace(/%3A/gi,":").replace(/%24/g,"$").replace(/%2C/gi,",").replace(/%20/g,"+")}function xe(e,t,n){if(!t)return e;const r=n&&n.encode||Le,o=ge.isFunction(n)?{serialize:n}:n,i=o&&o.serialize;let s;if(s=i?i(t,o):ge.isURLSearchParams(t)?t.toString():new Ne(t,o).toString(r),s){const t=e.indexOf("#");-1!==t&&(e=e.slice(0,t)),e+=(-1===e.indexOf("?")?"?":"&")+s}return e}class Pe{constructor(){this.handlers=[]}use(e,t,n){return this.handlers.push({fulfilled:e,rejected:t,synchronous:!!n&&n.synchronous,runWhen:n?n.runWhen:null}),this.handlers.length-1}eject(e){this.handlers[e]&&(this.handlers[e]=null)}clear(){this.handlers&&(this.handlers=[])}forEach(e){ge.forEach(this.handlers,function(t){null!==t&&e(t)})}}var De=Pe,Me={silentJSONParsing:!0,forcedJSONParsing:!0,clarifyTimeoutError:!1,legacyInterceptorReqResOrdering:!0},Fe="undefined"!==typeof URLSearchParams?URLSearchParams:Ne,$e="undefined"!==typeof FormData?FormData:null,je="undefined"!==typeof Blob?Blob:null,Ue={isBrowser:!0,classes:{URLSearchParams:Fe,FormData:$e,Blob:je},protocols:["http","https","file","blob","url","data"]};const Be="undefined"!==typeof window&&"undefined"!==typeof document,Ve="object"===typeof navigator&&navigator||void 0,Ge=Be&&(!Ve||["ReactNative","NativeScript","NS"].indexOf(Ve.product)<0),He=(()=>"undefined"!==typeof WorkerGlobalScope&&self instanceof WorkerGlobalScope&&"function"===typeof self.importScripts)(),We=Be&&window.location.href||"http://localhost";var Xe={...r,...Ue};function Ke(e,t){return Oe(e,new Xe.classes.URLSearchParams,{visitor:function(e,t,n,r){return Xe.isNode&&ge.isBuffer(e)?(this.append(t,e.toString("base64")),!1):r.defaultVisitor.apply(this,arguments)},...t})}function qe(e){return ge.matchAll(/\w+|\[(\w*)]/g,e).map(e=>"[]"===e[0]?"":e[1]||e[0])}function ze(e){const t={},n=Object.keys(e);let r;const o=n.length;let i;for(r=0;r<o;r++)i=n[r],t[i]=e[i];return t}function Ye(e){function t(e,n,r,o){let i=e[o++];if("__proto__"===i)return!0;const s=Number.isFinite(+i),a=o>=e.length;if(i=!i&&ge.isArray(r)?r.length:i,a)return ge.hasOwnProp(r,i)?r[i]=[r[i],n]:r[i]=n,!s;r[i]&&ge.isObject(r[i])||(r[i]=[]);const l=t(e,n,r[i],o);return l&&ge.isArray(r[i])&&(r[i]=ze(r[i])),!s}if(ge.isFormData(e)&&ge.isFunction(e.entries)){const n={};return ge.forEachEntry(e,(e,r)=>{t(qe(e),r,n,0)}),n}return null}var Qe=Ye;function Je(e,t,n){if(ge.isString(e))try{return(t||JSON.parse)(e),ge.trim(e)}catch(r){if("SyntaxError"!==r.name)throw r}return(n||JSON.stringify)(e)}const Ze={transitional:Me,adapter:["xhr","http","fetch"],transformRequest:[function(e,t){const n=t.getContentType()||"",r=n.indexOf("application/json")>-1,o=ge.isObject(e);o&&ge.isHTMLForm(e)&&(e=new FormData(e));const i=ge.isFormData(e);if(i)return r?JSON.stringify(Qe(e)):e;if(ge.isArrayBuffer(e)||ge.isBuffer(e)||ge.isStream(e)||ge.isFile(e)||ge.isBlob(e)||ge.isReadableStream(e))return e;if(ge.isArrayBufferView(e))return e.buffer;if(ge.isURLSearchParams(e))return t.setContentType("application/x-www-form-urlencoded;charset=utf-8",!1),e.toString();let s;if(o){if(n.indexOf("application/x-www-form-urlencoded")>-1)return Ke(e,this.formSerializer).toString();if((s=ge.isFileList(e))||n.indexOf("multipart/form-data")>-1){const t=this.env&&this.env.FormData;return Oe(s?{"files[]":e}:e,t&&new t,this.formSerializer)}}return o||r?(t.setContentType("application/json",!1),Je(e)):e}],transformResponse:[function(e){const t=this.transitional||Ze.transitional,n=t&&t.forcedJSONParsing,r="json"===this.responseType;if(ge.isResponse(e)||ge.isReadableStream(e))return e;if(e&&ge.isString(e)&&(n&&!this.responseType||r)){const n=t&&t.silentJSONParsing,i=!n&&r;try{return JSON.parse(e,this.parseReviver)}catch(o){if(i){if("SyntaxError"===o.name)throw be.from(o,be.ERR_BAD_RESPONSE,this,null,this.response);throw o}}}return e}],timeout:0,xsrfCookieName:"XSRF-TOKEN",xsrfHeaderName:"X-XSRF-TOKEN",maxContentLength:-1,maxBodyLength:-1,env:{FormData:Xe.classes.FormData,Blob:Xe.classes.Blob},validateStatus:function(e){return e>=200&&e<300},headers:{common:{Accept:"application/json, text/plain, */*","Content-Type":void 0}}};ge.forEach(["delete","get","head","post","put","patch"],e=>{Ze.headers[e]={}});var et=Ze;const tt=ge.toObjectSet(["age","authorization","content-length","content-type","etag","expires","from","host","if-modified-since","if-unmodified-since","last-modified","location","max-forwards","proxy-authorization","referer","retry-after","user-agent"]);var nt=e=>{const t={};let n,r,o;return e&&e.split("\n").forEach(function(e){o=e.indexOf(":"),n=e.substring(0,o).trim().toLowerCase(),r=e.substring(o+1).trim(),!n||t[n]&&tt[n]||("set-cookie"===n?t[n]?t[n].push(r):t[n]=[r]:t[n]=t[n]?t[n]+", "+r:r)}),t};(Object.getOwnPropertyDescriptor(nt,"name")||{}).writable||Object.defineProperty(nt,"name",{value:"default",configurable:!0});const rt=Symbol("internals"),ot=e=>!/[\r\n]/.test(e);function it(e,t){if(!1!==e&&null!=e)if(ge.isArray(e))e.forEach(e=>it(e,t));else if(!ot(String(e)))throw new Error(`Invalid character in header content ["${t}"]`)}function st(e){return e&&String(e).trim().toLowerCase()}function at(e){let t=e.length;while(t>0){const n=e.charCodeAt(t-1);if(10!==n&&13!==n)break;t-=1}return t===e.length?e:e.slice(0,t)}function lt(e){return!1===e||null==e?e:ge.isArray(e)?e.map(lt):at(String(e))}function ut(e){const t=Object.create(null),n=/([^\s,;=]+)\s*(?:=\s*([^,;]+))?/g;let r;while(r=n.exec(e))t[r[1]]=r[2];return t}const ct=e=>/^[-_a-zA-Z0-9^`|~,!#$%&'*+.]+$/.test(e.trim());function dt(e,t,n,r,o){return ge.isFunction(r)?r.call(this,t,n):(o&&(t=n),ge.isString(t)?ge.isString(r)?-1!==t.indexOf(r):ge.isRegExp(r)?r.test(t):void 0:void 0)}function ft(e){return e.trim().toLowerCase().replace(/([a-z\d])(\w*)/g,(e,t,n)=>t.toUpperCase()+n)}function ht(e,t){const n=ge.toCamelCase(" "+t);["get","set","has"].forEach(r=>{Object.defineProperty(e,r+n,{value:function(e,n,o){return this[r].call(this,t,e,n,o)},configurable:!0})})}class pt{constructor(e){e&&this.set(e)}set(e,t,n){const r=this;function o(e,t,n){const o=st(t);if(!o)throw new Error("header name must be a non-empty string");const i=ge.findKey(r,o);(!i||void 0===r[i]||!0===n||void 0===n&&!1!==r[i])&&(it(e,t),r[i||t]=lt(e))}const i=(e,t)=>ge.forEach(e,(e,n)=>o(e,n,t));if(ge.isPlainObject(e)||e instanceof this.constructor)i(e,t);else if(ge.isString(e)&&(e=e.trim())&&!ct(e))i(nt(e),t);else if(ge.isObject(e)&&ge.isIterable(e)){let n,r,o={};for(const t of e){if(!ge.isArray(t))throw TypeError("Object iterator must return a key-value pair");o[r=t[0]]=(n=o[r])?ge.isArray(n)?[...n,t[1]]:[n,t[1]]:t[1]}i(o,t)}else null!=e&&o(t,e,n);return this}get(e,t){if(e=st(e),e){const n=ge.findKey(this,e);if(n){const e=this[n];if(!t)return e;if(!0===t)return ut(e);if(ge.isFunction(t))return t.call(this,e,n);if(ge.isRegExp(t))return t.exec(e);throw new TypeError("parser must be boolean|regexp|function")}}}has(e,t){if(e=st(e),e){const n=ge.findKey(this,e);return!(!n||void 0===this[n]||t&&!dt(this,this[n],n,t))}return!1}delete(e,t){const n=this;let r=!1;function o(e){if(e=st(e),e){const o=ge.findKey(n,e);!o||t&&!dt(n,n[o],o,t)||(delete n[o],r=!0)}}return ge.isArray(e)?e.forEach(o):o(e),r}clear(e){const t=Object.keys(this);let n=t.length,r=!1;while(n--){const o=t[n];e&&!dt(this,this[o],o,e,!0)||(delete this[o],r=!0)}return r}normalize(e){const t=this,n={};return ge.forEach(this,(r,o)=>{const i=ge.findKey(n,o);if(i)return t[i]=lt(r),void delete t[o];const s=e?ft(o):String(o).trim();s!==o&&delete t[o],t[s]=lt(r),n[s]=!0}),this}concat(...e){return this.constructor.concat(this,...e)}toJSON(e){const t=Object.create(null);return ge.forEach(this,(n,r)=>{null!=n&&!1!==n&&(t[r]=e&&ge.isArray(n)?n.join(", "):n)}),t}[Symbol.iterator](){return Object.entries(this.toJSON())[Symbol.iterator]()}toString(){return Object.entries(this.toJSON()).map(([e,t])=>e+": "+t).join("\n")}getSetCookie(){return this.get("set-cookie")||[]}get[Symbol.toStringTag](){return"AxiosHeaders"}static from(e){return e instanceof this?e:new this(e)}static concat(e,...t){const n=new this(e);return t.forEach(e=>n.set(e)),n}static accessor(e){const t=this[rt]=this[rt]={accessors:{}},n=t.accessors,r=this.prototype;function o(e){const t=st(e);n[t]||(ht(r,e),n[t]=!0)}return ge.isArray(e)?e.forEach(o):o(e),this}}pt.accessor(["Content-Type","Content-Length","Accept","Accept-Encoding","User-Agent","Authorization"]),ge.reduceDescriptors(pt.prototype,({value:e},t)=>{let n=t[0].toUpperCase()+t.slice(1);return{get:()=>e,set(e){this[n]=e}}}),ge.freezeMethods(pt);var mt=pt;function vt(e,t){const n=this||et,r=t||n,o=mt.from(r.headers);let i=r.data;return ge.forEach(e,function(e){i=e.call(n,i,o.normalize(),t?t.status:void 0)}),o.normalize(),i}function gt(e){return!(!e||!e.__CANCEL__)}class yt extends be{constructor(e,t,n){super(null==e?"canceled":e,be.ERR_CANCELED,t,n),this.name="CanceledError",this.__CANCEL__=!0}}var bt=yt;function _t(e,t,n){const r=n.config.validateStatus;n.status&&r&&!r(n.status)?t(new be("Request failed with status code "+n.status,[be.ERR_BAD_REQUEST,be.ERR_BAD_RESPONSE][Math.floor(n.status/100)-4],n.config,n.request,n)):e(n)}function Et(e){const t=/^([-+\w]{1,25})(:?\/\/|:)/.exec(e);return t&&t[1]||""}function wt(e,t){e=e||10;const n=new Array(e),r=new Array(e);let o,i=0,s=0;return t=void 0!==t?t:1e3,function(a){const l=Date.now(),u=r[s];o||(o=l),n[i]=a,r[i]=l;let c=s,d=0;while(c!==i)d+=n[c++],c%=e;if(i=(i+1)%e,i===s&&(s=(s+1)%e),l-o<t)return;const f=u&&l-u;return f?Math.round(1e3*d/f):void 0}}var St=wt;function Tt(e,t){let n,r,o=0,i=1e3/t;const s=(t,i=Date.now())=>{o=i,n=null,r&&(clearTimeout(r),r=null),e(...t)},a=(...e)=>{const t=Date.now(),a=t-o;a>=i?s(e,t):(n=e,r||(r=setTimeout(()=>{r=null,s(n)},i-a)))},l=()=>n&&s(n);return[a,l]}var kt=Tt;const Ct=(e,t,n=3)=>{let r=0;const o=St(50,250);return kt(n=>{const i=n.loaded,s=n.lengthComputable?n.total:void 0,a=i-r,l=o(a),u=i<=s;r=i;const c={loaded:i,total:s,progress:s?i/s:void 0,bytes:a,rate:l||void 0,estimated:l&&s&&u?(s-i)/l:void 0,event:n,lengthComputable:null!=s,[t?"download":"upload"]:!0};e(c)},n)},Ot=(e,t)=>{const n=null!=e;return[r=>t[0]({lengthComputable:n,total:e,loaded:r}),t[1]]},At=e=>(...t)=>ge.asap(()=>e(...t));var Rt=Xe.hasStandardBrowserEnv?((e,t)=>n=>(n=new URL(n,Xe.origin),e.protocol===n.protocol&&e.host===n.host&&(t||e.port===n.port)))(new URL(Xe.origin),Xe.navigator&&/(msie|trident)/i.test(Xe.navigator.userAgent)):()=>!0,It=Xe.hasStandardBrowserEnv?{write(e,t,n,r,o,i,s){if("undefined"===typeof document)return;const a=[`${e}=${encodeURIComponent(t)}`];ge.isNumber(n)&&a.push(`expires=${new Date(n).toUTCString()}`),ge.isString(r)&&a.push(`path=${r}`),ge.isString(o)&&a.push(`domain=${o}`),!0===i&&a.push("secure"),ge.isString(s)&&a.push(`SameSite=${s}`),document.cookie=a.join("; ")},read(e){if("undefined"===typeof document)return null;const t=document.cookie.match(new RegExp("(?:^|; )"+e+"=([^;]*)"));return t?decodeURIComponent(t[1]):null},remove(e){this.write(e,"",Date.now()-864e5,"/")}}:{write(){},read(){return null},remove(){}};function Nt(e){return"string"===typeof e&&/^([a-z][a-z\d+\-.]*:)?\/\//i.test(e)}function Lt(e,t){return t?e.replace(/\/?\/$/,"")+"/"+t.replace(/^\/+/,""):e}function xt(e,t,n){let r=!Nt(t);return e&&(r||0==n)?Lt(e,t):t}const Pt=e=>e instanceof mt?{...e}:e;function Dt(e,t){t=t||{};const n={};function r(e,t,n,r){return ge.isPlainObject(e)&&ge.isPlainObject(t)?ge.merge.call({caseless:r},e,t):ge.isPlainObject(t)?ge.merge({},t):ge.isArray(t)?t.slice():t}function o(e,t,n,o){return ge.isUndefined(t)?ge.isUndefined(e)?void 0:r(void 0,e,n,o):r(e,t,n,o)}function i(e,t){if(!ge.isUndefined(t))return r(void 0,t)}function s(e,t){return ge.isUndefined(t)?ge.isUndefined(e)?void 0:r(void 0,e):r(void 0,t)}function a(n,o,i){return i in t?r(n,o):i in e?r(void 0,n):void 0}const l={url:i,method:i,data:i,baseURL:s,transformRequest:s,transformResponse:s,paramsSerializer:s,timeout:s,timeoutMessage:s,withCredentials:s,withXSRFToken:s,adapter:s,responseType:s,xsrfCookieName:s,xsrfHeaderName:s,onUploadProgress:s,onDownloadProgress:s,decompress:s,maxContentLength:s,maxBodyLength:s,beforeRedirect:s,transport:s,httpAgent:s,httpsAgent:s,cancelToken:s,socketPath:s,responseEncoding:s,validateStatus:a,headers:(e,t,n)=>o(Pt(e),Pt(t),n,!0)};return ge.forEach(Object.keys({...e,...t}),function(r){if("__proto__"===r||"constructor"===r||"prototype"===r)return;const i=ge.hasOwnProp(l,r)?l[r]:o,s=i(e[r],t[r],r);ge.isUndefined(s)&&i!==a||(n[r]=s)}),n}var Mt=e=>{const t=Dt({},e);let{data:n,withXSRFToken:r,xsrfHeaderName:o,xsrfCookieName:i,headers:s,auth:a}=t;if(t.headers=s=mt.from(s),t.url=xe(xt(t.baseURL,t.url,t.allowAbsoluteUrls),e.params,e.paramsSerializer),a&&s.set("Authorization","Basic "+btoa((a.username||"")+":"+(a.password?unescape(encodeURIComponent(a.password)):""))),ge.isFormData(n))if(Xe.hasStandardBrowserEnv||Xe.hasStandardBrowserWebWorkerEnv)s.setContentType(void 0);else if(ge.isFunction(n.getHeaders)){const e=n.getHeaders(),t=["content-type","content-length"];Object.entries(e).forEach(([e,n])=>{t.includes(e.toLowerCase())&&s.set(e,n)})}if(Xe.hasStandardBrowserEnv&&(r&&ge.isFunction(r)&&(r=r(t)),r||!1!==r&&Rt(t.url))){const e=o&&i&&It.read(i);e&&s.set(o,e)}return t};(Object.getOwnPropertyDescriptor(Mt,"name")||{}).writable||Object.defineProperty(Mt,"name",{value:"default",configurable:!0});const Ft="undefined"!==typeof XMLHttpRequest;var $t=Ft&&function(e){return new Promise(function(t,n){const r=Mt(e);let o=r.data;const i=mt.from(r.headers).normalize();let s,a,l,u,c,{responseType:d,onUploadProgress:f,onDownloadProgress:h}=r;function p(){u&&u(),c&&c(),r.cancelToken&&r.cancelToken.unsubscribe(s),r.signal&&r.signal.removeEventListener("abort",s)}let m=new XMLHttpRequest;function v(){if(!m)return;const r=mt.from("getAllResponseHeaders"in m&&m.getAllResponseHeaders()),o=d&&"text"!==d&&"json"!==d?m.response:m.responseText,i={data:o,status:m.status,statusText:m.statusText,headers:r,config:e,request:m};_t(function(e){t(e),p()},function(e){n(e),p()},i),m=null}m.open(r.method.toUpperCase(),r.url,!0),m.timeout=r.timeout,"onloadend"in m?m.onloadend=v:m.onreadystatechange=function(){m&&4===m.readyState&&(0!==m.status||m.responseURL&&0===m.responseURL.indexOf("file:"))&&setTimeout(v)},m.onabort=function(){m&&(n(new be("Request aborted",be.ECONNABORTED,e,m)),m=null)},m.onerror=function(t){const r=t&&t.message?t.message:"Network Error",o=new be(r,be.ERR_NETWORK,e,m);o.event=t||null,n(o),m=null},m.ontimeout=function(){let t=r.timeout?"timeout of "+r.timeout+"ms exceeded":"timeout exceeded";const o=r.transitional||Me;r.timeoutErrorMessage&&(t=r.timeoutErrorMessage),n(new be(t,o.clarifyTimeoutError?be.ETIMEDOUT:be.ECONNABORTED,e,m)),m=null},void 0===o&&i.setContentType(null),"setRequestHeader"in m&&ge.forEach(i.toJSON(),function(e,t){m.setRequestHeader(t,e)}),ge.isUndefined(r.withCredentials)||(m.withCredentials=!!r.withCredentials),d&&"json"!==d&&(m.responseType=r.responseType),h&&([l,c]=Ct(h,!0),m.addEventListener("progress",l)),f&&m.upload&&([a,u]=Ct(f),m.upload.addEventListener("progress",a),m.upload.addEventListener("loadend",u)),(r.cancelToken||r.signal)&&(s=t=>{m&&(n(!t||t.type?new bt(null,e,m):t),m.abort(),m=null)},r.cancelToken&&r.cancelToken.subscribe(s),r.signal&&(r.signal.aborted?s():r.signal.addEventListener("abort",s)));const g=Et(r.url);g&&-1===Xe.protocols.indexOf(g)?n(new be("Unsupported protocol "+g+":",be.ERR_BAD_REQUEST,e)):m.send(o||null)})};const jt=(e,t)=>{const{length:n}=e=e?e.filter(Boolean):[];if(t||n){let n,r=new AbortController;const o=function(e){if(!n){n=!0,s();const t=e instanceof Error?e:this.reason;r.abort(t instanceof be?t:new bt(t instanceof Error?t.message:t))}};let i=t&&setTimeout(()=>{i=null,o(new be(`timeout of ${t}ms exceeded`,be.ETIMEDOUT))},t);const s=()=>{e&&(i&&clearTimeout(i),i=null,e.forEach(e=>{e.unsubscribe?e.unsubscribe(o):e.removeEventListener("abort",o)}),e=null)};e.forEach(e=>e.addEventListener("abort",o));const{signal:a}=r;return a.unsubscribe=()=>ge.asap(s),a}};var Ut=jt;const Bt=function*(e,t){let n=e.byteLength;if(!t||n<t)return void(yield e);let r,o=0;while(o<n)r=o+t,yield e.slice(o,r),o=r},Vt=async function*(e,t){for await(const n of Gt(e))yield*Bt(n,t)},Gt=async function*(e){if(e[Symbol.asyncIterator])return void(yield*e);const t=e.getReader();try{for(;;){const{done:e,value:n}=await t.read();if(e)break;yield n}}finally{await t.cancel()}},Ht=(e,t,n,r)=>{const o=Vt(e,t);let i,s=0,a=e=>{i||(i=!0,r&&r(e))};return new ReadableStream({async pull(e){try{const{done:t,value:r}=await o.next();if(t)return a(),void e.close();let i=r.byteLength;if(n){let e=s+=i;n(e)}e.enqueue(new Uint8Array(r))}catch(t){throw a(t),t}},cancel(e){return a(e),o.return()}},{highWaterMark:2})},Wt=65536,{isFunction:Xt}=ge,Kt=(({Request:e,Response:t})=>({Request:e,Response:t}))(ge.global),{ReadableStream:qt,TextEncoder:zt}=ge.global,Yt=(e,...t)=>{try{return!!e(...t)}catch(n){return!1}},Qt=e=>{e=ge.merge.call({skipUndefined:!0},Kt,e);const{fetch:t,Request:n,Response:r}=e,o=t?Xt(t):"function"===typeof fetch,i=Xt(n),s=Xt(r);if(!o)return!1;const a=o&&Xt(qt),l=o&&("function"===typeof zt?(e=>t=>e.encode(t))(new zt):async e=>new Uint8Array(await new n(e).arrayBuffer())),u=i&&a&&Yt(()=>{let e=!1;const t=new qt,r=new n(Xe.origin,{body:t,method:"POST",get duplex(){return e=!0,"half"}}).headers.has("Content-Type");return t.cancel(),e&&!r}),c=s&&a&&Yt(()=>ge.isReadableStream(new r("").body)),d={stream:c&&(e=>e.body)};o&&(()=>{["text","arrayBuffer","blob","formData","stream"].forEach(e=>{!d[e]&&(d[e]=(t,n)=>{let r=t&&t[e];if(r)return r.call(t);throw new be(`Response type '${e}' is not supported`,be.ERR_NOT_SUPPORT,n)})})})();const f=async e=>{if(null==e)return 0;if(ge.isBlob(e))return e.size;if(ge.isSpecCompliantForm(e)){const t=new n(Xe.origin,{method:"POST",body:e});return(await t.arrayBuffer()).byteLength}return ge.isArrayBufferView(e)||ge.isArrayBuffer(e)?e.byteLength:(ge.isURLSearchParams(e)&&(e+=""),ge.isString(e)?(await l(e)).byteLength:void 0)},h=async(e,t)=>{const n=ge.toFiniteNumber(e.getContentLength());return null==n?f(t):n};return async e=>{let{url:o,method:s,data:a,signal:l,cancelToken:f,timeout:p,onDownloadProgress:m,onUploadProgress:v,responseType:g,headers:y,withCredentials:b="same-origin",fetchOptions:_}=Mt(e),E=t||fetch;g=g?(g+"").toLowerCase():"text";let w=Ut([l,f&&f.toAbortSignal()],p),S=null;const T=w&&w.unsubscribe&&(()=>{w.unsubscribe()});let k;try{if(v&&u&&"get"!==s&&"head"!==s&&0!==(k=await h(y,a))){let e,t=new n(o,{method:"POST",body:a,duplex:"half"});if(ge.isFormData(a)&&(e=t.headers.get("content-type"))&&y.setContentType(e),t.body){const[e,n]=Ot(k,Ct(At(v)));a=Ht(t.body,Wt,e,n)}}ge.isString(b)||(b=b?"include":"omit");const t=i&&"credentials"in n.prototype,l={..._,signal:w,method:s.toUpperCase(),headers:y.normalize().toJSON(),body:a,duplex:"half",credentials:t?b:void 0};S=i&&new n(o,l);let f=await(i?E(S,_):E(o,l));const p=c&&("stream"===g||"response"===g);if(c&&(m||p&&T)){const e={};["status","statusText","headers"].forEach(t=>{e[t]=f[t]});const t=ge.toFiniteNumber(f.headers.get("content-length")),[n,o]=m&&Ot(t,Ct(At(m),!0))||[];f=new r(Ht(f.body,Wt,n,()=>{o&&o(),T&&T()}),e)}g=g||"text";let C=await d[ge.findKey(d,g)||"text"](f,e);return!p&&T&&T(),await new Promise((t,n)=>{_t(t,n,{data:C,headers:mt.from(f.headers),status:f.status,statusText:f.statusText,config:e,request:S})})}catch(C){if(T&&T(),C&&"TypeError"===C.name&&/Load failed|fetch/i.test(C.message))throw Object.assign(new be("Network Error",be.ERR_NETWORK,e,S,C&&C.response),{cause:C.cause||C});throw be.from(C,C&&C.code,e,S,C&&C.response)}}},Jt=new Map,Zt=e=>{let t=e&&e.env||{};const{fetch:n,Request:r,Response:o}=t,i=[r,o,n];let s,a,l=i.length,u=l,c=Jt;while(u--)s=i[u],a=c.get(s),void 0===a&&c.set(s,a=u?new Map:Qt(t)),c=a;return a};Zt();const en={http:_e,xhr:$t,fetch:{get:Zt}};ge.forEach(en,(e,t)=>{if(e){try{Object.defineProperty(e,"name",{value:t})}catch(n){}Object.defineProperty(e,"adapterName",{value:t})}});const tn=e=>`- ${e}`,nn=e=>ge.isFunction(e)||null===e||!1===e;function rn(e,t){e=ge.isArray(e)?e:[e];const{length:n}=e;let r,o;const i={};for(let s=0;s<n;s++){let n;if(r=e[s],o=r,!nn(r)&&(o=en[(n=String(r)).toLowerCase()],void 0===o))throw new be(`Unknown adapter '${n}'`);if(o&&(ge.isFunction(o)||(o=o.get(t))))break;i[n||"#"+s]=o}if(!o){const e=Object.entries(i).map(([e,t])=>`adapter ${e} `+(!1===t?"is not supported by the environment":"is not available in the build"));let t=n?e.length>1?"since :\n"+e.map(tn).join("\n"):" "+tn(e[0]):"as no adapter specified";throw new be("There is no suitable adapter to dispatch the request "+t,"ERR_NOT_SUPPORT")}return o}var on={getAdapter:rn,adapters:en};function sn(e){if(e.cancelToken&&e.cancelToken.throwIfRequested(),e.signal&&e.signal.aborted)throw new bt(null,e)}function an(e){sn(e),e.headers=mt.from(e.headers),e.data=vt.call(e,e.transformRequest),-1!==["post","put","patch"].indexOf(e.method)&&e.headers.setContentType("application/x-www-form-urlencoded",!1);const t=on.getAdapter(e.adapter||et.adapter,e);return t(e).then(function(t){return sn(e),t.data=vt.call(e,e.transformResponse,t),t.headers=mt.from(t.headers),t},function(t){return gt(t)||(sn(e),t&&t.response&&(t.response.data=vt.call(e,e.transformResponse,t.response),t.response.headers=mt.from(t.response.headers))),Promise.reject(t)})}const ln="1.15.0",un={};["object","boolean","number","function","string","symbol"].forEach((e,t)=>{un[e]=function(n){return typeof n===e||"a"+(t<1?"n ":" ")+e}});const cn={};function dn(e,t,n){if("object"!==typeof e)throw new be("options must be an object",be.ERR_BAD_OPTION_VALUE);const r=Object.keys(e);let o=r.length;while(o-- >0){const i=r[o],s=t[i];if(s){const t=e[i],n=void 0===t||s(t,i,e);if(!0!==n)throw new be("option "+i+" must be "+n,be.ERR_BAD_OPTION_VALUE);continue}if(!0!==n)throw new be("Unknown option "+i,be.ERR_BAD_OPTION)}}un.transitional=function(e,t,n){function r(e,t){return"[Axios v"+ln+"] Transitional option '"+e+"'"+t+(n?". "+n:"")}return(n,o,i)=>{if(!1===e)throw new be(r(o," has been removed"+(t?" in "+t:"")),be.ERR_DEPRECATED);return t&&!cn[o]&&(cn[o]=!0,console.warn(r(o," has been deprecated since v"+t+" and will be removed in the near future"))),!e||e(n,o,i)}},un.spelling=function(e){return(t,n)=>(console.warn(`${n} is likely a misspelling of ${e}`),!0)};var fn={assertOptions:dn,validators:un};const hn=fn.validators;class pn{constructor(e){this.defaults=e||{},this.interceptors={request:new De,response:new De}}async request(e,t){try{return await this._request(e,t)}catch(n){if(n instanceof Error){let e={};Error.captureStackTrace?Error.captureStackTrace(e):e=new Error;const t=(()=>{if(!e.stack)return"";const t=e.stack.indexOf("\n");return-1===t?"":e.stack.slice(t+1)})();try{if(n.stack){if(t){const e=t.indexOf("\n"),r=-1===e?-1:t.indexOf("\n",e+1),o=-1===r?"":t.slice(r+1);String(n.stack).endsWith(o)||(n.stack+="\n"+t)}}else n.stack=t}catch(r){}}throw n}}_request(e,t){"string"===typeof e?(t=t||{},t.url=e):t=e||{},t=Dt(this.defaults,t);const{transitional:n,paramsSerializer:r,headers:o}=t;void 0!==n&&fn.assertOptions(n,{silentJSONParsing:hn.transitional(hn.boolean),forcedJSONParsing:hn.transitional(hn.boolean),clarifyTimeoutError:hn.transitional(hn.boolean),legacyInterceptorReqResOrdering:hn.transitional(hn.boolean)},!1),null!=r&&(ge.isFunction(r)?t.paramsSerializer={serialize:r}:fn.assertOptions(r,{encode:hn.function,serialize:hn.function},!0)),void 0!==t.allowAbsoluteUrls||(void 0!==this.defaults.allowAbsoluteUrls?t.allowAbsoluteUrls=this.defaults.allowAbsoluteUrls:t.allowAbsoluteUrls=!0),fn.assertOptions(t,{baseUrl:hn.spelling("baseURL"),withXsrfToken:hn.spelling("withXSRFToken")},!0),t.method=(t.method||this.defaults.method||"get").toLowerCase();let i=o&&ge.merge(o.common,o[t.method]);o&&ge.forEach(["delete","get","head","post","put","patch","common"],e=>{delete o[e]}),t.headers=mt.concat(i,o);const s=[];let a=!0;this.interceptors.request.forEach(function(e){if("function"===typeof e.runWhen&&!1===e.runWhen(t))return;a=a&&e.synchronous;const n=t.transitional||Me,r=n&&n.legacyInterceptorReqResOrdering;r?s.unshift(e.fulfilled,e.rejected):s.push(e.fulfilled,e.rejected)});const l=[];let u;this.interceptors.response.forEach(function(e){l.push(e.fulfilled,e.rejected)});let c,d=0;if(!a){const e=[an.bind(this),void 0];e.unshift(...s),e.push(...l),c=e.length,u=Promise.resolve(t);while(d<c)u=u.then(e[d++],e[d++]);return u}c=s.length;let f=t;while(d<c){const e=s[d++],t=s[d++];try{f=e(f)}catch(h){t.call(this,h);break}}try{u=an.call(this,f)}catch(h){return Promise.reject(h)}d=0,c=l.length;while(d<c)u=u.then(l[d++],l[d++]);return u}getUri(e){e=Dt(this.defaults,e);const t=xt(e.baseURL,e.url,e.allowAbsoluteUrls);return xe(t,e.params,e.paramsSerializer)}}ge.forEach(["delete","get","head","options"],function(e){pn.prototype[e]=function(t,n){return this.request(Dt(n||{},{method:e,url:t,data:(n||{}).data}))}}),ge.forEach(["post","put","patch"],function(e){function t(t){return function(n,r,o){return this.request(Dt(o||{},{method:e,headers:t?{"Content-Type":"multipart/form-data"}:{},url:n,data:r}))}}pn.prototype[e]=t(),pn.prototype[e+"Form"]=t(!0)});var mn=pn;class vn{constructor(e){if("function"!==typeof e)throw new TypeError("executor must be a function.");let t;this.promise=new Promise(function(e){t=e});const n=this;this.promise.then(e=>{if(!n._listeners)return;let t=n._listeners.length;while(t-- >0)n._listeners[t](e);n._listeners=null}),this.promise.then=e=>{let t;const r=new Promise(e=>{n.subscribe(e),t=e}).then(e);return r.cancel=function(){n.unsubscribe(t)},r},e(function(e,r,o){n.reason||(n.reason=new bt(e,r,o),t(n.reason))})}throwIfRequested(){if(this.reason)throw this.reason}subscribe(e){this.reason?e(this.reason):this._listeners?this._listeners.push(e):this._listeners=[e]}unsubscribe(e){if(!this._listeners)return;const t=this._listeners.indexOf(e);-1!==t&&this._listeners.splice(t,1)}toAbortSignal(){const e=new AbortController,t=t=>{e.abort(t)};return this.subscribe(t),e.signal.unsubscribe=()=>this.unsubscribe(t),e.signal}static source(){let e;const t=new vn(function(t){e=t});return{token:t,cancel:e}}}var gn=vn;function yn(e){return function(t){return e.apply(null,t)}}function bn(e){return ge.isObject(e)&&!0===e.isAxiosError}const _n={Continue:100,SwitchingProtocols:101,Processing:102,EarlyHints:103,Ok:200,Created:201,Accepted:202,NonAuthoritativeInformation:203,NoContent:204,ResetContent:205,PartialContent:206,MultiStatus:207,AlreadyReported:208,ImUsed:226,MultipleChoices:300,MovedPermanently:301,Found:302,SeeOther:303,NotModified:304,UseProxy:305,Unused:306,TemporaryRedirect:307,PermanentRedirect:308,BadRequest:400,Unauthorized:401,PaymentRequired:402,Forbidden:403,NotFound:404,MethodNotAllowed:405,NotAcceptable:406,ProxyAuthenticationRequired:407,RequestTimeout:408,Conflict:409,Gone:410,LengthRequired:411,PreconditionFailed:412,PayloadTooLarge:413,UriTooLong:414,UnsupportedMediaType:415,RangeNotSatisfiable:416,ExpectationFailed:417,ImATeapot:418,MisdirectedRequest:421,UnprocessableEntity:422,Locked:423,FailedDependency:424,TooEarly:425,UpgradeRequired:426,PreconditionRequired:428,TooManyRequests:429,RequestHeaderFieldsTooLarge:431,UnavailableForLegalReasons:451,InternalServerError:500,NotImplemented:501,BadGateway:502,ServiceUnavailable:503,GatewayTimeout:504,HttpVersionNotSupported:505,VariantAlsoNegotiates:506,InsufficientStorage:507,LoopDetected:508,NotExtended:510,NetworkAuthenticationRequired:511,WebServerIsDown:521,ConnectionTimedOut:522,OriginIsUnreachable:523,TimeoutOccurred:524,SslHandshakeFailed:525,InvalidSslCertificate:526};Object.entries(_n).forEach(([e,t])=>{_n[t]=e});var En=_n;function wn(e){const t=new mn(e),n=o(mn.prototype.request,t);return ge.extend(n,mn.prototype,t,{allOwnKeys:!0}),ge.extend(n,t,null,{allOwnKeys:!0}),n.create=function(t){return wn(Dt(e,t))},n}const Sn=wn(et);Sn.Axios=mn,Sn.CanceledError=bt,Sn.CancelToken=gn,Sn.isCancel=gt,Sn.VERSION=ln,Sn.toFormData=Oe,Sn.AxiosError=be,Sn.Cancel=Sn.CanceledError,Sn.all=function(e){return Promise.all(e)},Sn.spread=yn,Sn.isAxiosError=bn,Sn.mergeConfig=Dt,Sn.AxiosHeaders=mt,Sn.formToJSON=e=>Qe(ge.isHTMLForm(e)?new FormData(e):e),Sn.getAdapter=on.getAdapter,Sn.HttpStatusCode=En,Sn.default=Sn;var Tn=Sn},5633:function(e,t,n){"use strict";n.d(t,{Bx:function(){return Re},Eg:function(){return At},FD:function(){return ne},VC:function(){return O}});var r=n(953),o=n(641),i=n(3751),s=n(33),a=Object.defineProperty,l=Object.defineProperties,u=Object.getOwnPropertyDescriptors,c=Object.getOwnPropertySymbols,d=Object.prototype.hasOwnProperty,f=Object.prototype.propertyIsEnumerable,h=(e,t,n)=>t in e?a(e,t,{enumerable:!0,configurable:!0,writable:!0,value:n}):e[t]=n,p=(e,t)=>{for(var n in t||(t={}))d.call(t,n)&&h(e,n,t[n]);if(c)for(var n of c(t))f.call(t,n)&&h(e,n,t[n]);return e},m=(e,t)=>l(e,u(t)),v=(e,t)=>{var n={};for(var r in e)d.call(e,r)&&t.indexOf(r)<0&&(n[r]=e[r]);if(null!=e&&c)for(var r of c(e))t.indexOf(r)<0&&f.call(e,r)&&(n[r]=e[r]);return n};const g="Notivue__",y=6e3,b={SUCCESS:"success",ERROR:"error",WARNING:"warning",INFO:"info",PROMISE:"promise",PROMISE_RESOLVE:"promise-resolve",PROMISE_REJECT:"promise-reject"},_={title:"",message:"",duration:y,ariaLive:"polite",ariaRole:"status"},E=m(p({},_),{ariaLive:"assertive",ariaRole:"alert"}),w=m(p({},_),{duration:1/0}),S=m(p({},E),{ariaLive:"polite"}),T=p({},_),k={[b.SUCCESS]:_,[b.ERROR]:E,[b.WARNING]:S,[b.INFO]:T,[b.PROMISE]:w,[b.PROMISE_RESOLVE]:_,[b.PROMISE_REJECT]:E},C={pauseOnHover:!0,pauseOnTouch:!0,pauseOnTabChange:!0,enqueue:!1,position:"top-center",teleportTo:"body",notifications:k,limit:1/0,avoidDuplicates:!1,transition:"transform 0.35s cubic-bezier(0.5, 1, 0.25, 1)",animations:{enter:g+"enter",leave:g+"leave",clearAll:g+"clearAll"}},O=I();function A(e){Object.assign(O,e)}function R(e){let t=0;function n(n,o,i=""+t++){return"string"===typeof(0,r.R1)(n)&&(n={message:n}),e.push(m(p({},n),{id:i,type:o})),{id:i,clear:()=>e.clear(i),destroy:()=>e.clear(i,{isDestroy:!0})}}return{success:e=>n(e,b.SUCCESS),error:e=>n(e,b.ERROR),warning:e=>n(e,b.WARNING),info:e=>n(e,b.INFO),promise:e=>{const{id:t,clear:r,destroy:o}=n(e,b.PROMISE);return{resolve:e=>n(e,b.PROMISE_RESOLVE,t),reject:e=>n(e,b.PROMISE_REJECT,t),success:e=>n(e,b.PROMISE_RESOLVE,t),error:e=>n(e,b.PROMISE_REJECT,t),clear:r,destroy:o}},load(e){return this.promise(e)},clearAll:()=>e.clearAll(),destroyAll:()=>e.destroyAll()}}function I(){const e=new Proxy({},{get:()=>()=>{}});return R(e)}const N="undefined"===typeof window;function L(e,t){const n=p({},e);for(const r in t)t.hasOwnProperty(r)&&(P(t[r])?n[r]=L(e[r],t[r]):n[r]=t[r]);return n}function x(e,t){return t.props||(t.props={}),p(p(p(p({},e[t.type]),e.global),t),"promise"===t.type?{duration:1/0}:{})}function P(e){if("[object Object]"!==Object.prototype.toString.call(e))return!1;const t=Object.getPrototypeOf(e);return null===t||null===Object.getPrototypeOf(t)}function D(e,t,n){const o=L(e,t);function i(e){return(0,r.rY)((t,r)=>({get(){return t(),e},set(t){n.value&&(e=t,r())}}))}for(const r in o)o[r]=i(o[r]);return o}function M(e){return Object.entries(e).reduce((e,[t,{value:n}])=>m(p({},e),{[t]:(0,r.ux)(n)}),{})}const F=e=>e===b.SUCCESS||e===b.ERROR||e===b.WARNING||e===b.INFO,$=["timeout","resumedAt","remaining","animationAttrs","positionStyles"];function j(e){return Object.fromEntries(Object.entries(e).filter(([e])=>!$.includes(e)))}let U=()=>{};function B(e,t){const n=V(e,t),r=G(),o=H(n,r),i=W(),s=X(n,o,r,i),a=K(o,s);return{config:n,queue:r,items:o,elements:i,animations:s,timeouts:a}}function V(e,t){const n=D(C,e,t);function r(e){if(t.value){"function"===typeof e&&(e=e(M(n)));for(const t in e)"object"===typeof n[t].value?n[t].value=L(n[t].value,e[t]):n[t].value=e[t]}}return U=r,m(p({},n),{update:r})}function G(){return{entries:(0,r.IJ)([]),get length(){return this.entries.value.length},add(e){this.entries.value.push(e),this.triggerRef()},get(e){return this.entries.value.find(t=>t.id===e)},update(e,t){const n=this.get(e);n&&Object.assign(n,t)},remove(e){this.entries.value=this.entries.value.filter(t=>t.id!==e)},triggerRef(){(0,r.mu)(this.entries)},clear(){this.entries.value=[]}}}function H(e,t){return{entries:(0,r.IJ)([]),get length(){return this.entries.value.length},lifecycleEventsCount:(0,r.KR)(0),addLifecycleEvent(){this.lifecycleEventsCount.value++},clearLifecycleEvents(){this.lifecycleEventsCount.value=0},add(e){this.entries.value.unshift(e),this.triggerRef(),this.addLifecycleEvent()},addFromQueue(){const e=m(p({},t.entries.value[0]),{timeout:t.entries.value[0].timeout(),createdAt:Date.now()});t.remove(e.id),this.add(e)},findDupe(e){return this.entries.value.find(t=>(0,r.R1)(t.message).replace(/\uFEFF/g,"")===(0,r.R1)(e.message).replace(/\uFEFF/g,"")&&(0,r.R1)(t.title)===(0,r.R1)(e.title)&&t.type===e.type)},get(e){return this.entries.value.find(t=>t.id===e)},update(e,t){const n=this.get(e);n&&Object.assign(n,t)},triggerRef(){(0,r.mu)(this.entries)},updateAll(e){this.entries.value=this.entries.value.map(e)},remove(n){this.entries.value=this.entries.value.filter(e=>e.id!==n);const r=t.length>0&&this.length<e.limit.value;r&&this.addFromQueue()},clear(){this.entries.value=[]}}}function W(){return{root:(0,r.KR)(null),rootAttrs:(0,r.IJ)({}),setRootAttrs(e){this.rootAttrs.value=e},items:(0,r.KR)([]),getSortedItems(){return this.items.value.sort((e,t)=>+t.dataset.notivueItem-+e.dataset.notivueItem)},containers:(0,r.KR)([])}}function X(e,t,n,o){return{isReducedMotion:(0,r.KR)(!1),setReducedMotion(e){this.isReducedMotion.value=e},playLeave(n,{isDestroy:r=!1,isUserTriggered:o=!1}={}){const{leave:i=""}=e.animations.value,s=t.get(n);window.clearTimeout(null==s?void 0:s.timeout);const a=e=>{var r;e&&e.currentTarget!==e.target||(null==(r=null==s?void 0:s[o?"onManualClear":"onAutoClear"])||r.call(s,j(s)),t.remove(n))};if(!s||!i||r||this.isReducedMotion.value)return t.addLifecycleEvent(),a();t.update(n,{positionStyles:m(p({},s.positionStyles),{zIndex:-1}),animationAttrs:{class:i,onAnimationend:a}}),t.addLifecycleEvent()},playClearAll(){t.entries.value.forEach(e=>window.clearTimeout(e.timeout));const{clearAll:r=""}=e.animations.value,i=()=>{n.clear(),t.clear()};if(!r||this.isReducedMotion.value)return i();o.setRootAttrs({class:r,onAnimationend:i})},updatePositions({isImmediate:n=!1}={}){const r=this.isReducedMotion.value||n,i=0===e.position.value.indexOf("top"),s=e.animations.value.leave;let a=0;for(const l of o.getSortedItems()){const n=l.dataset.notivueItem,o=t.get(n);l&&o&&o.animationAttrs.class!==s&&(t.update(n,{positionStyles:{transform:`translate3d(0, ${a}px, 0)`,transition:r?"none":e.transition.value}}),a+=(i?1:-1)*l.clientHeight)}t.triggerRef()}}}function K(e,t){return{isStreamPaused:(0,r.KR)(!1),isStreamFocused:(0,r.KR)(!1),debounceTimeout:void 0,setStreamPause(e=!0){this.isStreamPaused.value=e},setStreamFocus(e=!0){this.isStreamFocused.value=e},clearDebounceTimeout(){window.clearTimeout(this.debounceTimeout)},reset(){this.clearDebounceTimeout(),this.setStreamPause(!1),this.setStreamFocus(!1)},create(e,n){if(!this.isStreamPaused.value)return Number.isFinite(n)&&n>0?window.setTimeout(()=>t.playLeave(e),n):void 0},pause(){0===e.length||this.isStreamPaused.value||(this.setStreamPause(),e.updateAll(e=>{var t;if(window.clearTimeout(e.timeout),e.duration===1/0)return e;let n=0;return n=null==e.remaining?e.duration-(Date.now()-(null!=(t=e.resumedAt)?t:e.createdAt)):e.remaining-(Date.now()-e.resumedAt),m(p({},e),{remaining:n})}))},resume(){0!==e.length&&this.isStreamPaused.value&&(this.setStreamPause(!1),e.updateAll(e=>{var t;return window.clearTimeout(e.timeout),e.duration===1/0?e:m(p({},e),{timeout:this.create(e.id,null!=(t=e.remaining)?t:e.duration),resumedAt:Date.now()})}))},resumeWithDebounce(e){this.debounceTimeout=window.setTimeout(()=>{this.resume()},e)}}}function q({config:e,items:t,queue:n,animations:o,timeouts:i}){return{destroyAll(){n.clear(),t.clear()},clearAll(){o.playClearAll()},clear(e,{isDestroy:n=!1}={}){var r;const s=(null==(r=t.entries.value[t.entries.value.length-1])?void 0:r.id)===e;s&&i.resume(),o.playLeave(e,{isUserTriggered:!0,isDestroy:n})},push(s){const a=x(e.notifications.value,s),l=Date.now();if(e.avoidDuplicates.value&&F(a.type)){const e=t.findDupe(a);e&&(window.clearTimeout(e.timeout),t.update(e.id,{createdAt:l,duration:a.duration,remaining:void 0,timeout:i.create(e.id,a.duration),duplicateCount:e.duplicateCount+1}),(0,r.i9)(e.message)?e.message.value+="\ufeff":e.message+="\ufeff",t.triggerRef());const o=t.findDupe.call(n,a);if(o&&(n.update(o.id,{duration:a.duration,createdAt:l,duplicateCount:o.duplicateCount+1}),n.triggerRef()),o||e)return}const u=()=>i.create(a.id,a.duration);if(s.type===b.PROMISE_RESOLVE||s.type===b.PROMISE_REJECT)n.get(a.id)?(n.update(a.id,m(p({},a),{createdAt:l,timeout:u})),n.triggerRef()):(t.update(a.id,m(p({},a),{createdAt:l,timeout:u()})),t.triggerRef());else{const r=e.enqueue.value,c=t.length>=e.limit.value,d=!r&&c,f=r&&!s.skipQueue&&c;d&&t.entries.value.slice(e.limit.value-1).forEach(e=>i.create(e.id,1));const h=m(p({},a),{createdAt:l,duplicateCount:0,animationAttrs:{class:o.isReducedMotion.value?"":e.animations.value.enter,onAnimationend(){h.animationAttrs.class===e.animations.value.enter&&t.update(a.id,{animationAttrs:{class:"",onAnimationend:()=>{}}})}},timeout:f?u:u(),clear:()=>this.clear(a.id),destroy:()=>this.clear(a.id,{isDestroy:!0})});f?n.add(h):t.add(h)}}}}const z=Symbol(),Y=Symbol();function Q(e){return[(0,o.wB)(e.items.lifecycleEventsCount,()=>{e.animations.updatePositions()},{flush:"post"}),(0,o.wB)(e.config.position,()=>{e.animations.updatePositions({isImmediate:!0})},{flush:"post"}),(0,o.wB)(()=>0===e.items.length&&0===e.queue.length,t=>{t&&(e.timeouts.reset(),e.elements.setRootAttrs({}))},{flush:"post"})]}let J=()=>{},Z=()=>{};function ee(e){const t=(0,r.KR)(e),n=(0,r.tB)(t);function o(r,o){const i=()=>Q(r);e&&A(o);let s=e?i():[()=>{}];const a={isRunning:n,startInstance(){t.value||(A(o),s=i(),t.value=!0)},stopInstance(){t.value&&(r.items.clear(),r.queue.clear(),r.items.clearLifecycleEvents(),A(I()),s.forEach(e=>e()),t.value=!1)}};return J=()=>a.startInstance(),Z=()=>a.stopInstance(),a}return{isRunning:n,setupInstance:o}}function te(e,t){const{setupInstance:n,isRunning:r}=ee(e),o=B(t,r),i=q(o),s=Object.freeze(R(i)),a=n(o,s);return{store:o,instance:a,push:s}}function ne(e={}){return{install(t){var n;const r=e,{startOnCreation:o=!0}=r,i=v(r,["startOnCreation"]),{store:s,instance:a,push:l}=te(o,i);t.provide(z,a),t.provide(Y,s),(n=t.config.globalProperties).$push||(n.$push=l)}}}function re(){return(0,o.WQ)(Y)}function oe(){return N?{isRunning:(0,r.KR)(!0),startInstance:()=>{},stopInstance:()=>{}}:(0,o.WQ)(z)}function ie(){if(N)return m(p({},(0,r.QW)((0,r.Kh)(C))),{update:()=>{},isTopAlign:(0,o.EW)(()=>!0),isStreamPaused:(0,r.KR)(!1)});const e=re();return m(p({},e.config),{isStreamPaused:(0,r.tB)(e.timeouts.isStreamPaused),isTopAlign:(0,o.EW)(()=>0===e.config.position.value.indexOf("top"))})}const se=Symbol(""),ae='a[href], area[href], input:not([disabled]), select:not([disabled]), textarea:not([disabled]), button:not([disabled]), [tabindex="0"]',le={comboKey:"n",handleClicks:!0,leaveMessage:"You're leaving the notifications stream. Press Control + N to navigate it again.",emptyMessage:"No notifications to navigate",renderAnnouncement:!0,maxAnnouncements:2};const ue={listAriaLabel:"Notifications"},ce=(0,o.pM)({setup(e,{slots:t,attrs:n}){const i=(0,r.KR)(!1);return(0,o.sV)(()=>i.value=!0),()=>{var e;return i.value?null==(e=t.default)?void 0:e.call(t):(0,o.CE)("span",n,"")}}}),de=e=>"mouse"===e.pointerType;function fe(e){return`${e.title?`${e.title}: `:""}${e.message}`}const he=["role","aria-live"],pe=(0,o.pM)({__name:"AriaLive",props:{item:{}},setup(e){const t=e,n={position:"absolute",width:"1px",height:"1px",padding:"0",margin:"-1px",overflow:"hidden",clip:"rect(0, 0, 0, 0)",whiteSpace:"nowrap",border:"0"};return(e,i)=>((0,o.uX)(),(0,o.CE)("div",{style:n,role:t.item.ariaRole,"aria-live":t.item.ariaLive,key:`${e.item.id}_${e.item.type}`,"aria-atomic":"true"},(0,s.v_)((0,r.R1)(fe)(t.item)),9,he))}});function me(){const{timeouts:e,config:t}=re();function n(t){de(t)&&e.pause()}function r(t){de(t)&&e.resume()}return(0,o.EW)(()=>t.pauseOnHover.value&&!e.isStreamFocused.value?{onPointerenter:n,onPointerleave:r}:{})}function ve(){const{timeouts:e,config:t}=re();function n(t){de(t)||(e.clearDebounceTimeout(),e.pause(),e.resumeWithDebounce(2e3))}return(0,o.xo)(()=>{e.clearDebounceTimeout()}),(0,o.EW)(()=>t.pauseOnTouch.value&&!e.isStreamFocused.value?{onPointerdown:n}:{})}const ge={boxSizing:"border-box"},ye={list:m(p({},ge),{display:"flex",justifyContent:"center",listStyle:"none",margin:"0 auto",maxWidth:"var(--nv-root-width, 100%)",padding:"0",pointerEvents:"none",position:"fixed",zIndex:"var(--nv-z, 500)"}),listItem:m(p({},ge),{display:"flex",margin:"0",position:"absolute",transitionProperty:"transform",width:"100%"}),itemContainer:m(p({},ge),{maxWidth:"100%",padding:"0 0 var(--nv-gap, 0.75rem) 0",pointerEvents:"auto"})};function be(){const{isTopAlign:e,position:t}=ie(),n=(0,o.EW)(()=>{const t=e.value,n=[`var(--nv-root-top, ${t?"1.25rem":"0px"})`,"var(--nv-root-right, 1.25rem)",`var(--nv-root-bottom, ${t?"0px":"1.25rem"})`,"var(--nv-root-left, 1.25rem)"],r=n.map(e=>`calc(-1 * ${e})`);return t?r.splice(2,1,"0px"):r.splice(0,1,"0px"),{inset:n.join(" "),clipPath:`inset(${r.join(" ")})`}}),r=(0,o.EW)(()=>({[e.value?"top":"bottom"]:"0",justifyContent:`var(--nv-root-x-align, ${t.value.endsWith("left")?"flex-start":t.value.endsWith("right")?"flex-end":"center"})`}));return(0,o.EW)(()=>({list:p(p({},ye.list),n.value),listItem:p(p({},ye.listItem),r.value),itemContainer:ye.itemContainer}))}function _e(e){function t(){window.matchMedia("(max-width: 1100px)").matches&&e()}(0,o.sV)(()=>{window.addEventListener("resize",t)}),(0,o.xo)(()=>{window.removeEventListener("resize",t)})}function Ee(e,t){let n;const r=new WeakSet;(0,o.sV)(()=>{n=new ResizeObserver((e,n)=>{for(const o of e)r.has(o.target)?Object.values(o.contentRect.toJSON()).every(e=>0===e)?(r.delete(o.target),n.unobserve(o.target)):(t(),r.delete(o.target),n.unobserve(o.target)):r.add(o.target)})}),(0,o.wB)(e,e=>{e.length>0&&e.forEach(e=>null==n?void 0:n.observe(e))},{flush:"post"}),(0,o.xo)(()=>{null==n||n.disconnect()})}function we(){const{elements:e,animations:t}=re();_e(()=>t.updatePositions({isImmediate:!0})),Ee(e.items.value,()=>t.updatePositions())}function Se(){const{config:e,timeouts:t}=re();function n(){t.isStreamFocused.value||e.pauseOnTabChange.value&&t.resume()}function r(){t.isStreamFocused.value||e.pauseOnTabChange.value&&t.pause()}(0,o.sV)(()=>{window.addEventListener("focus",n),window.addEventListener("blur",r)}),(0,o.xo)(()=>{window.removeEventListener("focus",n),window.removeEventListener("blur",r)})}function Te(){const{animations:e}=re(),t=window.matchMedia("(prefers-reduced-motion: reduce)"),n=()=>e.setReducedMotion(t.matches);(0,o.sV)(()=>{var e;n(),null==(e=t.addEventListener)||e.call(t,"change",n)}),(0,o.xo)(()=>{var e;null==(e=t.removeEventListener)||e.call(t,"change",n)})}const ke=["data-notivue-align","aria-label"],Ce=["data-notivue-item","aria-setsize","aria-posinset"],Oe=["aria-label","tabindex","data-notivue-container"],Ae=(0,o.pM)({__name:"NotivueImpl",props:(0,o.HF)({class:{},containersTabIndex:{},listAriaLabel:{},styles:{}},ue),setup(e){const t=e,{config:n,items:i,elements:a}=re(),l=be(),u=me(),c=ve();return Te(),Se(),we(),(e,d)=>{var f;return(0,o.uX)(),(0,o.Wv)(o.Im,{to:!1===(0,r.R1)(n).teleportTo.value?void 0:(0,r.R1)(n).teleportTo.value,disabled:!1===(0,r.R1)(n).teleportTo.value},[(0,r.R1)(i).entries.value.length>0?((0,o.uX)(),(0,o.CE)("ol",(0,o.v6)({key:0},p(p(p({},(0,r.R1)(u)),(0,r.R1)(c)),(0,r.R1)(a).rootAttrs.value),{"data-notivue-align":(0,r.R1)(n).position.value.split("-")[0],"aria-label":t.listAriaLabel,ref:(0,r.R1)(a).root,class:t.class,style:p(p({},(0,r.R1)(l).list),null==(f=t.styles)?void 0:f.list)}),[((0,o.uX)(!0),(0,o.CE)(o.FK,null,(0,o.pI)((0,r.R1)(i).entries.value,(n,u)=>{var c,d,f,h;return(0,o.uX)(),(0,o.CE)("li",{tabindex:"-1",key:n.id,"data-notivue-item":n.id,"aria-setsize":(0,r.R1)(i).length,"aria-posinset":u+1,ref_for:!0,ref:(0,r.R1)(a).items,style:(0,s.Tr)(p(p(p({},(0,r.R1)(l).listItem),n.positionStyles),null==(c=t.styles)?void 0:c.listItem))},[n.ariaLiveOnly?((0,o.uX)(),(0,o.Wv)(pe,{key:0,item:n},null,8,["item"])):((0,o.uX)(),(0,o.CE)("div",(0,o.v6)({key:1,ref_for:!0},n.animationAttrs,{"aria-label":(0,r.R1)(fe)(n),tabindex:null!=(f=null==(d=e.containersTabIndex)?void 0:d[n.id])?f:-1,"data-notivue-container":n.id,ref_for:!0,ref:(0,r.R1)(a).containers,style:p(p({},(0,r.R1)(l).itemContainer),null==(h=t.styles)?void 0:h.itemContainer)}),[(0,o.RG)(e.$slots,"default",(0,o.v6)({ref_for:!0},(0,r.R1)(j)(n)))],16,Oe))],12,Ce)}),128))],16,ke)):(0,o.Q3)("",!0)],8,["to","disabled"])}}}),Re=(0,o.pM)({__name:"Notivue",props:(0,o.HF)({class:{},containersTabIndex:{},listAriaLabel:{},styles:{}},ue),setup(e){const t=e,{isRunning:n}=oe();return(e,i)=>((0,o.uX)(),(0,o.Wv)((0,r.R1)(ce),null,{default:(0,o.k6)(()=>[(0,r.R1)(n)?((0,o.uX)(),(0,o.Wv)(Ae,(0,s._B)((0,o.v6)({key:0},t)),{default:(0,o.k6)(t=>[(0,o.RG)(e.$slots,"default",(0,s._B)((0,o.Ng)(t)))]),_:3},16)):(0,o.Q3)("",!0)]),_:3}))}}),Ie={touchOnly:!1,exclude:"a, button",disabled:!1,threshold:.5},Ne=300,Le={Mouse:200,Touch:1e3,TouchExternal:1400};Boolean,Boolean,Boolean;function xe(){const e=(0,r.KR)(!1),t=()=>e.value=!0,n=()=>e.value=!1,i=[["keydown",t],["mousedown",n],["touchstart",n]];return(0,o.sV)(()=>{i.forEach(([e,t])=>document.addEventListener(e,t))}),(0,o.xo)(()=>{i.forEach(([e,t])=>document.removeEventListener(e,t))}),{isKeyboardFocus:e}}function Pe(){const{root:e}=re().elements,t=(0,r.KR)(null);function n(n){var r;const o=n.target instanceof HTMLElement;o&&(null==(r=e.value)?void 0:r.contains(n.target))||o&&(t.value=n.target)}function i(){t.value?t.value.focus():(document.activeElement instanceof HTMLElement&&document.activeElement.blur(),document.body.focus())}return(0,o.sV)(()=>{document.addEventListener("focus",n,!0)}),(0,o.xo)(()=>{document.removeEventListener("focus",n,!0)}),{focusLastElement:i}}const De=(0,o.pM)({__name:"NotivueKeyboardImpl",props:(0,o.HF)({comboKey:{},handleClicks:{type:Boolean},leaveMessage:{},emptyMessage:{},renderAnnouncement:{type:Boolean},maxAnnouncements:{}},le),setup(e){const t=e,{comboKey:n,handleClicks:i,leaveMessage:a,emptyMessage:l,renderAnnouncement:u,maxAnnouncements:c}=(0,r.QW)(t),d={ariaRole:"alert",ariaLive:"assertive",skipQueue:!0,ariaLiveOnly:!u.value,props:{isNotivueKeyboard:!0}},f=(0,o.EW)(()=>p({message:a.value},d)),h=(0,o.EW)(()=>p({message:l.value},d)),{elements:m,timeouts:v,queue:g}=re(),y=ie(),{focusLastElement:b}=Pe(),{isKeyboardFocus:_}=xe(),E=(0,r.KR)({qualified:[],unqualified:[]}),w=(0,r.KR)([]),S=(0,r.KR)([]),T=(0,r.KR)(-1);function k(e){T.value=e}let C=0,A=!0,R=[];const I=(0,o.EW)(()=>{const e={};return E.value.qualified.forEach(t=>e[t]=T.value),E.value.unqualified.forEach(t=>e[t]=-1),e});function N(){0!==w.value.length&&(k(0),v.setStreamFocus(),v.pause(),(0,o.dY)(()=>{w.value[0].focus()}))}function L({announce:e=!0}={}){b(),k(-1),v.setStreamFocus(!1),v.resume(),e&&C<c.value&&(C++,O.info(f.value))}function x(e){const t={qualified:[],unqualified:[]};let n=[],r=[],o=[];e.map(e=>({id:e.dataset.notivueContainer,container:e})).sort((e,t)=>+t.id-+e.id).forEach(({id:e,container:i})=>{const s=Array.from(i.querySelectorAll(ae)).filter(e=>e instanceof HTMLElement);o.push(...s),s.length>1?(t.qualified.push(e),n.push(i)):(t.unqualified.push(e),r.push(i))}),E.value=t,w.value=n,S.value=r,R=o}function P(e){!e.shiftKey&&"Tab"===e.key&&w.value.length>0&&(e.preventDefault(),A&&(A=!1),N(),(0,o.dY)(M))}function D(){M(),document.addEventListener("keydown",P)}function M(){document.removeEventListener("keydown",P)}(0,o.Gt)(se,{containersTabIndex:I,elementsTabIndex:(0,r.tB)(T)}),(0,o.wB)(m.containers,x,{deep:!0}),(0,o.wB)(w,(e,t,n)=>{if(0===e.length)return;const r=e.length>0,o=e.some(e=>!t.some(t=>t===e)),i=o&&v.isStreamFocused.value,s=o&&!v.isStreamFocused.value||r&&A;i?e[0].focus():s&&D(),n(()=>{s&&M()})},{flush:"post"}),(0,o.wB)(S,e=>{y.enqueue.value&&v.isStreamFocused.value&&e.length>0&&(w.value.length>0?w.value[0].focus():L({announce:!1}))},{flush:"post"});let F=!1;function $(e){let t=0;const n=w.value.some((n,r)=>{if(n.contains(e.target)||n===e.target)return t=r,!0});if(n){if("Escape"===e.key)return e.preventDefault(),F=!0,L();if(!i.value)return;const n=e.target instanceof HTMLButtonElement||e.target instanceof HTMLAnchorElement;if(n&&(" "===e.key||" "===e.key||"Enter"===e.key)){if(e.preventDefault(),F=!0,e.target.click(),g.length>0)return;const n=w.value[t+1];n?n.focus():L()}}}function j(e){if(e.ctrlKey&&(e.key===n.value.toLowerCase()||e.key===n.value.toUpperCase())){if(e.preventDefault(),v.isStreamFocused.value)return F=!0,L();w.value.length>0?N():O.info(h.value)}}function U(e){var t;v.isStreamFocused.value&&!_.value&&((null==(t=m.root.value)?void 0:t.contains(e.target))||L(),R.includes(e.target)&&L())}(0,o.wB)(m.root,(e,t,n)=>{function r(t){if(t.preventDefault(),t.stopPropagation(),v.isStreamFocused.value&&_.value)return F?F=!1:void((null==e?void 0:e.contains(t.relatedTarget))||L())}e&&e.addEventListener("focusout",r),n(()=>{e&&e.removeEventListener("focusout",r)})},{immediate:!0,flush:"post"});const B=[["click",U],["keydown",$],["keydown",j]];return(0,o.sV)(()=>{B.forEach(([e,t])=>document.addEventListener(e,t))}),(0,o.xo)(()=>{B.forEach(([e,t])=>{document.removeEventListener(e,t)})}),(e,t)=>(0,o.RG)(e.$slots,"default",(0,s._B)((0,o.Ng)({containersTabIndex:I.value,elementsTabIndex:T.value})))}}),Me=(Boolean,Boolean,(0,o.Lk)("path",{d:"M6,-0c-3.308,-0 -6,2.692 -6,6c-0,3.308 2.692,6 6,6c3.308,-0 6,-2.692 6,-6c-0,-3.308 -2.692,-6 -6,-6Zm3.123,3.989l-3.877,4.616c-0.086,0.102 -0.213,0.162 -0.346,0.164l-0.008,0c-0.131,0 -0.256,-0.055 -0.343,-0.153l-1.662,-1.846c-0.081,-0.085 -0.126,-0.199 -0.126,-0.316c0,-0.254 0.209,-0.462 0.462,-0.462c0.135,0 0.263,0.059 0.35,0.161l1.307,1.451l3.536,-4.209c0.087,-0.101 0.215,-0.159 0.349,-0.159c0.253,-0 0.461,0.208 0.461,0.461c0,0.107 -0.036,0.21 -0.103,0.292Z"},null,-1)),Fe=[Me],$e=(0,o.pM)({__name:"SuccessIcon",setup(e){return(e,t)=>((0,o.uX)(),(0,o.CE)("svg",(0,s._B)((0,o.Ng)((0,r.R1)(pt))),Fe,16))}}),je=(0,o.Lk)("path",{d:"M6,-0c-3.308,-0 -6,2.692 -6,6c-0,3.308 2.692,6 6,6c3.308,-0 6,-2.692 6,-6c-0,-3.308 -2.692,-6 -6,-6Zm-0,9.228c-0.316,0 -0.577,-0.26 -0.577,-0.577c0,-0.316 0.261,-0.577 0.577,-0.577c0.316,0 0.577,0.261 0.577,0.577c-0,0.317 -0.261,0.577 -0.577,0.577Zm0.627,-5.802l-0.166,3.519c-0,0.253 -0.208,0.462 -0.462,0.462c-0.253,-0 -0.461,-0.209 -0.461,-0.462l-0.166,-3.518l0,-0.001c-0,-0.009 -0,-0.018 -0,-0.027c-0,-0.344 0.283,-0.627 0.627,-0.627c0.344,0 0.627,0.283 0.627,0.627c-0,0.009 -0,0.018 -0.001,0.027l0.002,-0Z"},null,-1),Ue=[je],Be=(0,o.pM)({__name:"ErrorIcon",setup(e){return(e,t)=>((0,o.uX)(),(0,o.CE)("svg",(0,s._B)((0,o.Ng)((0,r.R1)(pt))),Ue,16))}}),Ve=(0,o.Lk)("path",{d:"M6,0c-3.308,0 -6,2.692 -6,6c0,3.308 2.692,6 6,6c3.308,0 6,-2.692 6,-6c0,-3.308 -2.692,-6 -6,-6Zm0,2.46c0.428,0 0.78,0.352 0.78,0.78c-0,0.428 -0.352,0.78 -0.78,0.78c-0.428,0 -0.78,-0.352 -0.78,-0.78c0,-0.428 0.352,-0.78 0.78,-0.78Zm1.44,6.78l-2.64,0c-0.263,0 -0.48,-0.217 -0.48,-0.48c0,-0.263 0.217,-0.48 0.48,-0.48l0.84,0l0,-2.64l-0.48,0c-0.263,0 -0.48,-0.217 -0.48,-0.48c0,-0.263 0.217,-0.48 0.48,-0.48l0.96,0c0.263,0 0.48,0.217 0.48,0.48l0,3.12l0.84,0c0.263,0 0.48,0.217 0.48,0.48c0,0.263 -0.217,0.48 -0.48,0.48Z"},null,-1),Ge=[Ve],He=(0,o.pM)({__name:"InfoIcon",setup(e){return(e,t)=>((0,o.uX)(),(0,o.CE)("svg",(0,s._B)((0,o.Ng)((0,r.R1)(pt))),Ge,16))}}),We=(0,o.Lk)("path",{d:"M11.963,6.037c-0,3.292 -2.671,5.963 -5.963,5.963c-3.292,0 -5.963,-2.671 -5.963,-5.963c0,-3.292 2.671,-5.962 5.963,-5.962c3.292,-0 5.963,2.67 5.963,5.962Zm-0.918,0c0,-2.785 -2.26,-5.045 -5.045,-5.045c-2.785,0 -5.045,2.26 -5.045,5.045c-0,2.786 2.26,5.046 5.045,5.046c2.785,-0 5.045,-2.26 5.045,-5.046Z"},null,-1),Xe=(0,o.Lk)("path",{d:"M8.401,3.449c0.163,-0.194 0.452,-0.219 0.646,-0.056c0.194,0.163 0.219,0.452 0.056,0.646l-3.853,4.587c-0.085,0.101 -0.21,0.161 -0.343,0.163c-0.133,0.003 -0.26,-0.053 -0.349,-0.151l-1.651,-1.835c-0.169,-0.188 -0.154,-0.479 0.034,-0.648c0.188,-0.169 0.479,-0.154 0.648,0.034l1.298,1.443l3.514,-4.183Z"},null,-1),Ke=[We,Xe],qe=(0,o.pM)({__name:"SuccessOutlineIcon",setup(e){return(e,t)=>((0,o.uX)(),(0,o.CE)("svg",(0,s._B)((0,o.Ng)((0,r.R1)(pt))),Ke,16))}}),ze=(0,o.Lk)("path",{d:"M12, 6c0, 3.313 -2.687, 6 -6, 6c-3.313,-0 -6,-2.688 -6,-6c0,-3.313 2.688,-6 6,-6c3.313,-0 6,2.687 6,6Zm-0.923,-0c-0,-2.803 -2.274,-5.077 -5.077,-5.077c-2.803,0 -5.077,2.274 -5.077,5.077c0,2.803 2.274,5.077 5.077,5.077c2.803,-0 5.077,-2.274 5.077,-5.077Z"},null,-1),Ye=(0,o.Lk)("path",{d:"M5.373,3.426c-0,-0.009 -0,-0.019 -0,-0.028c-0,-0.342 0.279,-0.624 0.621,-0.627c0.002,-0 0.004,-0 0.006,-0c0.344,-0 0.627,0.283 0.627,0.627c-0,0.009 -0,0.019 -0.001,0.028l0,0.001l-0.165,3.518c-0.012,0.246 -0.215,0.44 -0.461,0.44c-0.246,-0 -0.449,-0.194 -0.461,-0.44l-0.166,-3.518l0,-0.001Z"},null,-1),Qe=(0,o.Lk)("path",{d:"M6,9.228c-0.316,0 -0.577,-0.26 -0.577,-0.577c0,-0.316 0.261,-0.577 0.577,-0.577c0.316,0 0.577,0.261 0.577,0.577c-0,0.317 -0.261,0.577 -0.577,0.577Z"},null,-1),Je=[ze,Ye,Qe],Ze=(0,o.pM)({__name:"ErrorOutlineIcon",setup(e){return(e,t)=>((0,o.uX)(),(0,o.CE)("svg",(0,s._B)((0,o.Ng)((0,r.R1)(pt))),Je,16))}}),et=(0,o.Lk)("path",{d:"M6, 0c3.313, 0 6, 2.687 6, 6c-0, 3.313 -2.687, 6 -6, 6c-3.313,-0 -6,-2.687 -6,-6c0,-3.313 2.687,-6 6,-6Zm0, 0.96c-2.783, 0 -5.04, 2.257 -5.04, 5.04c0, 2.783 2.257, 5.04 5.04, 5.04c2.783, 0 5.04,-2.257 5.04,-5.04c-0,-2.783 -2.257,-5.04 -5.04,-5.04Z"},null,-1),tt=(0,o.Lk)("path",{d:"M6.6, 8.28l0.84, 0c0.265, 0 0.48, 0.215 0.48, 0.48c-0, 0.265 -0.215, 0.48 -0.48, 0.48l-2.64,-0c-0.265, 0 -0.48,-0.215 -0.48,-0.48c-0,-0.265 0.215,-0.48 0.48,-0.48l0.84, 0l-0,-2.64l-0.48, 0c-0.265, 0 -0.48,-0.215 -0.48,-0.48c-0,-0.265 0.215,-0.48 0.48,-0.48l0.96, 0c0.265, 0 0.48, 0.215 0.48, 0.48l-0, 3.12Z"},null,-1),nt=(0,o.Lk)("path",{d:"M6, 2.46c-0.428, 0 -0.78, 0.352 -0.78, 0.78c-0, 0.428 0.352, 0.78 0.78, 0.78c0.428, 0 0.78,-0.352 0.78,-0.78c-0,-0.428 -0.352,-0.78 -0.78,-0.78Z"},null,-1),rt=[et,tt,nt],ot=(0,o.pM)({__name:"InfoOutlineIcon",setup(e){return(e,t)=>((0,o.uX)(),(0,o.CE)("svg",(0,s._B)((0,o.Ng)((0,r.R1)(pt))),rt,16))}}),it=(0,o.Lk)("path",{d:"M12,1A11,11,0,1,0,23,12,11,11,0,0,0,12,1Zm0,19a8,8,0,1,1,8-8A8,8,0,0,1,12,20Z",opacity:".25"},null,-1),st=(0,o.Lk)("path",{d:"M10.14,1.16a11,11,0,0,0-9,8.92A1.59,1.59,0,0,0,2.46,12,1.52,1.52,0,0,0,4.11,10.7a8,8,0,0,1,6.66-6.61A1.42,1.42,0,0,0,12,2.69h0A1.57,1.57,0,0,0,10.14,1.16Z",class:"Notivue__spinner"},null,-1),at=[it,st],lt=(0,o.pM)({__name:"PromiseIcon",setup(e){return(e,t)=>((0,o.uX)(),(0,o.CE)("svg",(0,s._B)((0,o.Ng)(m(p({},(0,r.R1)(ht)),{width:28,height:28,fill:"currentColor"}))),at,16))}}),ut=(0,o.Lk)("line",{x1:"18",y1:"6",x2:"6",y2:"18"},null,-1),ct=(0,o.Lk)("line",{x1:"6",y1:"6",x2:"18",y2:"18"},null,-1),dt=[ut,ct],ft=(0,o.pM)({__name:"CloseIcon",setup(e){return(e,t)=>((0,o.uX)(),(0,o.CE)("svg",(0,s._B)((0,o.Ng)((0,r.R1)(mt))),dt,16))}}),ht={xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 24 24","aria-hidden":"true"},pt=m(p({},ht),{fill:"currentColor",viewBox:"0 0 12 12"}),mt=m(p({},ht),{stroke:"currentColor","stroke-width":2,"stroke-linecap":"round","stroke-linejoin":"round"}),vt={[b.SUCCESS]:(0,r.IG)($e),[b.ERROR]:(0,r.IG)(Be),[b.INFO]:(0,r.IG)(He),[b.WARNING]:(0,r.IG)(Be),[b.PROMISE]:(0,r.IG)(lt),[b.PROMISE_RESOLVE]:(0,r.IG)($e),[b.PROMISE_REJECT]:(0,r.IG)(Be),close:(0,r.IG)(ft)},gt=(b.SUCCESS,(0,r.IG)(qe),b.ERROR,(0,r.IG)(Ze),b.INFO,(0,r.IG)(ot),b.WARNING,(0,r.IG)(Ze),b.PROMISE,(0,r.IG)(lt),b.PROMISE_RESOLVE,(0,r.IG)(qe),b.PROMISE_REJECT,(0,r.IG)(Ze),(0,r.IG)(ft),{"--nv-width":"350px","--nv-spacing":"0.625rem","--nv-radius":"0.625rem","--nv-icon-size":"1.25rem","--nv-title-size":"0.925rem","--nv-message-size":"0.925rem","--nv-y-align":"center"}),yt={"--nv-shadow":"rgba(0, 0, 0, 0.06) 0px 4px 6px -1px, rgba(0, 0, 0, 0.03) 0px 2px 4px -1px"},bt=m(p(p({},gt),yt),{"--nv-global-bg":"#FFF","--nv-global-fg":"#171717","--nv-success-accent":"#28B780","--nv-error-accent":"#E74C3C","--nv-warning-accent":"#F59E0B","--nv-info-accent":"#3E8EFF","--nv-promise-accent":"#171717"}),_t=(m(p(p({},gt),yt),{"--nv-success-bg":"#E9FAEF","--nv-success-accent":"#059669","--nv-success-fg":"#057452","--nv-error-bg":"#FEEFEF","--nv-error-accent":"#E6523C","--nv-error-fg":"#C5412C","--nv-warning-bg":"#FFF0D8","--nv-warning-accent":"#F48533","--nv-warning-fg":"#81471D","--nv-info-bg":"#DEF0FA","--nv-info-accent":"#1F70AC","--nv-info-fg":"#1F70AC","--nv-promise-bg":"#FFF","--nv-promise-accent":"#334155","--nv-promise-fg":"#334155"}),m(p(p({},gt),yt),{"--nv-global-accent":"#FFF","--nv-global-fg":"#FFF","--nv-success-bg":"#178570","--nv-error-bg":"#C94430","--nv-info-bg":"#117AAE","--nv-warning-bg":"#FFE556","--nv-warning-fg":"#4F5358","--nv-warning-accent":"#4F5358","--nv-promise-bg":"#FFF","--nv-promise-fg":"#334155","--nv-promise-accent":"#64748B"}),m(p({},gt),{"--nv-border-width":"1px","--nv-global-bg":"#1F1F1F","--nv-global-border":"#414141","--nv-global-fg":"#D0D0D0","--nv-success-accent":"#8EF997","--nv-error-accent":"#FF7777","--nv-warning-accent":"#FFE554","--nv-info-accent":"#5FD4FF","--nv-promise-accent":"#D0D0D0"}),m(p({},gt),{"--nv-border-width":"1px","--nv-global-bg":"#20252E","--nv-global-border":"#353b45","--nv-global-fg":"#dfdfdf","--nv-success-accent":"#34D399","--nv-error-accent":"#FF7777","--nv-warning-accent":"#FFE554","--nv-info-accent":"#5FD4FF","--nv-promise-accent":"#D0D0D0"}),{NOTIFICATION:g+"notification",ICON:g+"icon",CONTENT:g+"content",TITLE:g+"content-title",MESSAGE:g+"content-message",CLOSE:g+"close",CLOSE_ICON:g+"close-icon",TRANSITION:g+"transition",PROGRESS:g+"progress",DUPLICATE:g+"duplicate"}),Et={icons:()=>vt,theme:()=>bt,hideClose:!1,closeAriaLabel:"Close"},wt=["data-notivue","data-notivue-has-title"],St=["aria-live","role"],Tt=["textContent"],kt=["textContent"],Ct=["aria-label"],Ot=["textContent"],At=(0,o.pM)({__name:"Notification",props:(0,o.HF)({item:{},icons:{},theme:{},closeAriaLabel:{},hideClose:{type:Boolean}},Et),setup(e){const t=e,n=(0,r.IJ)(t.icons[t.item.type]),a=t.icons.close;return(0,o.wB)(()=>t.item.type,e=>n.value=t.icons[e],{flush:"sync"}),(e,l)=>((0,o.uX)(),(0,o.CE)("div",{class:(0,s.C4)([(0,r.R1)(_t).NOTIFICATION,{[(0,r.R1)(_t).DUPLICATE]:e.item.duplicateCount>0}]),key:e.item.duplicateCount,"data-notivue":e.item.type,"data-notivue-has-title":Boolean(e.item.title),style:(0,s.Tr)(e.theme)},[n.value?((0,o.uX)(),(0,o.CE)(o.FK,{key:0},["object"===typeof n.value?((0,o.uX)(),(0,o.Wv)(i.eB,{key:0,name:(0,r.R1)(_t).TRANSITION,mode:"out-in"},{default:(0,o.k6)(()=>["object"===typeof n.value?((0,o.uX)(),(0,o.Wv)((0,o.$y)(n.value),{key:0,class:(0,s.C4)((0,r.R1)(_t).ICON),"aria-hidden":"true"},null,8,["class"])):(0,o.Q3)("",!0)]),_:1},8,["name"])):"string"===typeof n.value?((0,o.uX)(),(0,o.CE)("div",{key:1,class:(0,s.C4)((0,r.R1)(_t).ICON),"aria-hidden":"true"},(0,s.v_)(n.value),3)):(0,o.Q3)("",!0)],64)):(0,o.Q3)("",!0),(0,o.Lk)("div",{class:(0,s.C4)((0,r.R1)(_t).CONTENT),"aria-live":e.item.ariaLive,role:e.item.ariaRole,"aria-atomic":"true"},[e.item.title?((0,o.uX)(),(0,o.CE)("h3",{key:0,class:(0,s.C4)((0,r.R1)(_t).TITLE),textContent:(0,s.v_)((0,r.R1)(e.item.title))},null,10,Tt)):(0,o.Q3)("",!0),(0,o.Lk)("p",{class:(0,s.C4)((0,r.R1)(_t).MESSAGE),textContent:(0,s.v_)((0,r.R1)(e.item.message))},null,10,kt)],10,St),!t.hideClose&&(0,r.R1)(a)&&"promise"!==e.item.type?((0,o.uX)(),(0,o.CE)("button",{key:1,class:(0,s.C4)((0,r.R1)(_t).CLOSE),"aria-label":e.closeAriaLabel,type:"button",tabindex:"-1",onClick:l[0]||(l[0]=(...t)=>e.item.clear&&e.item.clear(...t))},["object"===typeof(0,r.R1)(a)?((0,o.uX)(),(0,o.Wv)((0,o.$y)((0,r.R1)(a)),{key:0,class:(0,s.C4)((0,r.R1)(_t).CLOSE_ICON)},null,8,["class"])):"string"===typeof(0,r.R1)(a)?((0,o.uX)(),(0,o.CE)("div",{key:1,"aria-hidden":"true",textContent:(0,s.v_)((0,r.R1)(a))},null,8,Ot)):(0,o.Q3)("",!0)],10,Ct)):(0,o.Q3)("",!0),(0,o.RG)(e.$slots,"default")],14,wt))}})},7944:function(e,t,n){"use strict";n.d(t,{dv:function(){return w}});var r,o=n(641),i=n(953),s=function(){return s=Object.assign||function(e){for(var t,n=1,r=arguments.length;n<r;n++)for(var o in t=arguments[n],t)Object.prototype.hasOwnProperty.call(t,o)&&(e[o]=t[o]);return e},s.apply(this,arguments)};"function"===typeof SuppressedError&&SuppressedError,function(e){var t=function(){function t(e,n,r,i){if(this.version=e,this.errorCorrectionLevel=n,this.modules=[],this.isFunction=[],e<t.MIN_VERSION||e>t.MAX_VERSION)throw new RangeError("Version value out of range");if(i<-1||i>7)throw new RangeError("Mask value out of range");this.size=4*e+17;for(var s=[],a=0;a<this.size;a++)s.push(!1);for(a=0;a<this.size;a++)this.modules.push(s.slice()),this.isFunction.push(s.slice());this.drawFunctionPatterns();var l=this.addEccAndInterleave(r);if(this.drawCodewords(l),-1==i){var u=1e9;for(a=0;a<8;a++){this.applyMask(a),this.drawFormatBits(a);var c=this.getPenaltyScore();c<u&&(i=a,u=c),this.applyMask(a)}}o(0<=i&&i<=7),this.mask=i,this.applyMask(i),this.drawFormatBits(i),this.isFunction=[]}return t.encodeText=function(n,r){var o=e.QrSegment.makeSegments(n);return t.encodeSegments(o,r)},t.encodeBinary=function(n,r){var o=e.QrSegment.makeBytes(n);return t.encodeSegments([o],r)},t.encodeSegments=function(e,r,s,a,l,u){if(void 0===s&&(s=1),void 0===a&&(a=40),void 0===l&&(l=-1),void 0===u&&(u=!0),!(t.MIN_VERSION<=s&&s<=a&&a<=t.MAX_VERSION)||l<-1||l>7)throw new RangeError("Invalid value");var c,d;for(c=s;;c++){var f=8*t.getNumDataCodewords(c,r),h=i.getTotalBits(e,c);if(h<=f){d=h;break}if(c>=a)throw new RangeError("Data too long")}for(var p=0,m=[t.Ecc.MEDIUM,t.Ecc.QUARTILE,t.Ecc.HIGH];p<m.length;p++){var v=m[p];u&&d<=8*t.getNumDataCodewords(c,v)&&(r=v)}for(var g=[],y=0,b=e;y<b.length;y++){var _=b[y];n(_.mode.modeBits,4,g),n(_.numChars,_.mode.numCharCountBits(c),g);for(var E=0,w=_.getData();E<w.length;E++){var S=w[E];g.push(S)}}o(g.length==d);var T=8*t.getNumDataCodewords(c,r);o(g.length<=T),n(0,Math.min(4,T-g.length),g),n(0,(8-g.length%8)%8,g),o(g.length%8==0);for(var k=236;g.length<T;k^=253)n(k,8,g);var C=[];while(8*C.length<g.length)C.push(0);return g.forEach(function(e,t){return C[t>>>3]|=e<<7-(7&t)}),new t(c,r,C,l)},t.prototype.getModule=function(e,t){return 0<=e&&e<this.size&&0<=t&&t<this.size&&this.modules[t][e]},t.prototype.getModules=function(){return this.modules},t.prototype.drawFunctionPatterns=function(){for(var e=0;e<this.size;e++)this.setFunctionModule(6,e,e%2==0),this.setFunctionModule(e,6,e%2==0);this.drawFinderPattern(3,3),this.drawFinderPattern(this.size-4,3),this.drawFinderPattern(3,this.size-4);var t=this.getAlignmentPatternPositions(),n=t.length;for(e=0;e<n;e++)for(var r=0;r<n;r++)0==e&&0==r||0==e&&r==n-1||e==n-1&&0==r||this.drawAlignmentPattern(t[e],t[r]);this.drawFormatBits(0),this.drawVersion()},t.prototype.drawFormatBits=function(e){for(var t=this.errorCorrectionLevel.formatBits<<3|e,n=t,i=0;i<10;i++)n=n<<1^1335*(n>>>9);var s=21522^(t<<10|n);o(s>>>15==0);for(i=0;i<=5;i++)this.setFunctionModule(8,i,r(s,i));this.setFunctionModule(8,7,r(s,6)),this.setFunctionModule(8,8,r(s,7)),this.setFunctionModule(7,8,r(s,8));for(i=9;i<15;i++)this.setFunctionModule(14-i,8,r(s,i));for(i=0;i<8;i++)this.setFunctionModule(this.size-1-i,8,r(s,i));for(i=8;i<15;i++)this.setFunctionModule(8,this.size-15+i,r(s,i));this.setFunctionModule(8,this.size-8,!0)},t.prototype.drawVersion=function(){if(!(this.version<7)){for(var e=this.version,t=0;t<12;t++)e=e<<1^7973*(e>>>11);var n=this.version<<12|e;o(n>>>18==0);for(t=0;t<18;t++){var i=r(n,t),s=this.size-11+t%3,a=Math.floor(t/3);this.setFunctionModule(s,a,i),this.setFunctionModule(a,s,i)}}},t.prototype.drawFinderPattern=function(e,t){for(var n=-4;n<=4;n++)for(var r=-4;r<=4;r++){var o=Math.max(Math.abs(r),Math.abs(n)),i=e+r,s=t+n;0<=i&&i<this.size&&0<=s&&s<this.size&&this.setFunctionModule(i,s,2!=o&&4!=o)}},t.prototype.drawAlignmentPattern=function(e,t){for(var n=-2;n<=2;n++)for(var r=-2;r<=2;r++)this.setFunctionModule(e+r,t+n,1!=Math.max(Math.abs(r),Math.abs(n)))},t.prototype.setFunctionModule=function(e,t,n){this.modules[t][e]=n,this.isFunction[t][e]=!0},t.prototype.addEccAndInterleave=function(e){var n=this.version,r=this.errorCorrectionLevel;if(e.length!=t.getNumDataCodewords(n,r))throw new RangeError("Invalid argument");for(var i=t.NUM_ERROR_CORRECTION_BLOCKS[r.ordinal][n],s=t.ECC_CODEWORDS_PER_BLOCK[r.ordinal][n],a=Math.floor(t.getNumRawDataModules(n)/8),l=i-a%i,u=Math.floor(a/i),c=[],d=t.reedSolomonComputeDivisor(s),f=0,h=0;f<i;f++){var p=e.slice(h,h+u-s+(f<l?0:1));h+=p.length;var m=t.reedSolomonComputeRemainder(p,d);f<l&&p.push(0),c.push(p.concat(m))}var v=[],g=function(e){c.forEach(function(t,n){(e!=u-s||n>=l)&&v.push(t[e])})};for(f=0;f<c[0].length;f++)g(f);return o(v.length==a),v},t.prototype.drawCodewords=function(e){if(e.length!=Math.floor(t.getNumRawDataModules(this.version)/8))throw new RangeError("Invalid argument");for(var n=0,i=this.size-1;i>=1;i-=2){6==i&&(i=5);for(var s=0;s<this.size;s++)for(var a=0;a<2;a++){var l=i-a,u=0==(i+1&2),c=u?this.size-1-s:s;!this.isFunction[c][l]&&n<8*e.length&&(this.modules[c][l]=r(e[n>>>3],7-(7&n)),n++)}}o(n==8*e.length)},t.prototype.applyMask=function(e){if(e<0||e>7)throw new RangeError("Mask value out of range");for(var t=0;t<this.size;t++)for(var n=0;n<this.size;n++){var r=void 0;switch(e){case 0:r=(n+t)%2==0;break;case 1:r=t%2==0;break;case 2:r=n%3==0;break;case 3:r=(n+t)%3==0;break;case 4:r=(Math.floor(n/3)+Math.floor(t/2))%2==0;break;case 5:r=n*t%2+n*t%3==0;break;case 6:r=(n*t%2+n*t%3)%2==0;break;case 7:r=((n+t)%2+n*t%3)%2==0;break;default:throw new Error("Unreachable")}!this.isFunction[t][n]&&r&&(this.modules[t][n]=!this.modules[t][n])}},t.prototype.getPenaltyScore=function(){for(var e=0,n=0;n<this.size;n++){for(var r=!1,i=0,s=[0,0,0,0,0,0,0],a=0;a<this.size;a++)this.modules[n][a]==r?(i++,5==i?e+=t.PENALTY_N1:i>5&&e++):(this.finderPenaltyAddHistory(i,s),r||(e+=this.finderPenaltyCountPatterns(s)*t.PENALTY_N3),r=this.modules[n][a],i=1);e+=this.finderPenaltyTerminateAndCount(r,i,s)*t.PENALTY_N3}for(a=0;a<this.size;a++){r=!1;var l=0;for(s=[0,0,0,0,0,0,0],n=0;n<this.size;n++)this.modules[n][a]==r?(l++,5==l?e+=t.PENALTY_N1:l>5&&e++):(this.finderPenaltyAddHistory(l,s),r||(e+=this.finderPenaltyCountPatterns(s)*t.PENALTY_N3),r=this.modules[n][a],l=1);e+=this.finderPenaltyTerminateAndCount(r,l,s)*t.PENALTY_N3}for(n=0;n<this.size-1;n++)for(a=0;a<this.size-1;a++){var u=this.modules[n][a];u==this.modules[n][a+1]&&u==this.modules[n+1][a]&&u==this.modules[n+1][a+1]&&(e+=t.PENALTY_N2)}for(var c=0,d=0,f=this.modules;d<f.length;d++){var h=f[d];c=h.reduce(function(e,t){return e+(t?1:0)},c)}var p=this.size*this.size,m=Math.ceil(Math.abs(20*c-10*p)/p)-1;return o(0<=m&&m<=9),e+=m*t.PENALTY_N4,o(0<=e&&e<=2568888),e},t.prototype.getAlignmentPatternPositions=function(){if(1==this.version)return[];for(var e=Math.floor(this.version/7)+2,t=2*Math.floor((8*this.version+3*e+5)/(4*e-4)),n=[6],r=this.size-7;n.length<e;r-=t)n.splice(1,0,r);return n},t.getNumRawDataModules=function(e){if(e<t.MIN_VERSION||e>t.MAX_VERSION)throw new RangeError("Version number out of range");var n=(16*e+128)*e+64;if(e>=2){var r=Math.floor(e/7)+2;n-=(25*r-10)*r-55,e>=7&&(n-=36)}return o(208<=n&&n<=29648),n},t.getNumDataCodewords=function(e,n){return Math.floor(t.getNumRawDataModules(e)/8)-t.ECC_CODEWORDS_PER_BLOCK[n.ordinal][e]*t.NUM_ERROR_CORRECTION_BLOCKS[n.ordinal][e]},t.reedSolomonComputeDivisor=function(e){if(e<1||e>255)throw new RangeError("Degree out of range");for(var n=[],r=0;r<e-1;r++)n.push(0);n.push(1);var o=1;for(r=0;r<e;r++){for(var i=0;i<n.length;i++)n[i]=t.reedSolomonMultiply(n[i],o),i+1<n.length&&(n[i]^=n[i+1]);o=t.reedSolomonMultiply(o,2)}return n},t.reedSolomonComputeRemainder=function(e,n){for(var r=n.map(function(e){return 0}),o=function(e){var o=e^r.shift();r.push(0),n.forEach(function(e,n){return r[n]^=t.reedSolomonMultiply(e,o)})},i=0,s=e;i<s.length;i++){var a=s[i];o(a)}return r},t.reedSolomonMultiply=function(e,t){if(e>>>8!=0||t>>>8!=0)throw new RangeError("Byte out of range");for(var n=0,r=7;r>=0;r--)n=n<<1^285*(n>>>7),n^=(t>>>r&1)*e;return o(n>>>8==0),n},t.prototype.finderPenaltyCountPatterns=function(e){var t=e[1];o(t<=3*this.size);var n=t>0&&e[2]==t&&e[3]==3*t&&e[4]==t&&e[5]==t;return(n&&e[0]>=4*t&&e[6]>=t?1:0)+(n&&e[6]>=4*t&&e[0]>=t?1:0)},t.prototype.finderPenaltyTerminateAndCount=function(e,t,n){return e&&(this.finderPenaltyAddHistory(t,n),t=0),t+=this.size,this.finderPenaltyAddHistory(t,n),this.finderPenaltyCountPatterns(n)},t.prototype.finderPenaltyAddHistory=function(e,t){0==t[0]&&(e+=this.size),t.pop(),t.unshift(e)},t.MIN_VERSION=1,t.MAX_VERSION=40,t.PENALTY_N1=3,t.PENALTY_N2=3,t.PENALTY_N3=40,t.PENALTY_N4=10,t.ECC_CODEWORDS_PER_BLOCK=[[-1,7,10,15,20,26,18,20,24,30,18,20,24,26,30,22,24,28,30,28,28,28,28,30,30,26,28,30,30,30,30,30,30,30,30,30,30,30,30,30,30],[-1,10,16,26,18,24,16,18,22,22,26,30,22,22,24,24,28,28,26,26,26,26,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28],[-1,13,22,18,26,18,24,18,22,20,24,28,26,24,20,30,24,28,28,26,30,28,30,30,30,30,28,30,30,30,30,30,30,30,30,30,30,30,30,30,30],[-1,17,28,22,16,22,28,26,26,24,28,24,28,22,24,24,30,28,28,26,28,30,24,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30]],t.NUM_ERROR_CORRECTION_BLOCKS=[[-1,1,1,1,1,1,2,2,2,2,4,4,4,4,4,6,6,6,6,7,8,8,9,9,10,12,12,12,13,14,15,16,17,18,19,19,20,21,22,24,25],[-1,1,1,1,2,2,4,4,4,5,5,5,8,9,9,10,10,11,13,14,16,17,17,18,20,21,23,25,26,28,29,31,33,35,37,38,40,43,45,47,49],[-1,1,1,2,2,4,4,6,6,8,8,8,10,12,16,12,17,16,18,21,20,23,23,25,27,29,34,34,35,38,40,43,45,48,51,53,56,59,62,65,68],[-1,1,1,2,4,4,4,5,6,8,8,11,11,16,16,18,16,19,21,25,25,25,34,30,32,35,37,40,42,45,48,51,54,57,60,63,66,70,74,77,81]],t}();function n(e,t,n){if(t<0||t>31||e>>>t!=0)throw new RangeError("Value out of range");for(var r=t-1;r>=0;r--)n.push(e>>>r&1)}function r(e,t){return 0!=(e>>>t&1)}function o(e){if(!e)throw new Error("Assertion error")}e.QrCode=t;var i=function(){function e(e,t,n){if(this.mode=e,this.numChars=t,this.bitData=n,t<0)throw new RangeError("Invalid argument");this.bitData=n.slice()}return e.makeBytes=function(t){for(var r=[],o=0,i=t;o<i.length;o++){var s=i[o];n(s,8,r)}return new e(e.Mode.BYTE,t.length,r)},e.makeNumeric=function(t){if(!e.isNumeric(t))throw new RangeError("String contains non-numeric characters");for(var r=[],o=0;o<t.length;){var i=Math.min(t.length-o,3);n(parseInt(t.substring(o,o+i),10),3*i+1,r),o+=i}return new e(e.Mode.NUMERIC,t.length,r)},e.makeAlphanumeric=function(t){if(!e.isAlphanumeric(t))throw new RangeError("String contains unencodable characters in alphanumeric mode");var r,o=[];for(r=0;r+2<=t.length;r+=2){var i=45*e.ALPHANUMERIC_CHARSET.indexOf(t.charAt(r));i+=e.ALPHANUMERIC_CHARSET.indexOf(t.charAt(r+1)),n(i,11,o)}return r<t.length&&n(e.ALPHANUMERIC_CHARSET.indexOf(t.charAt(r)),6,o),new e(e.Mode.ALPHANUMERIC,t.length,o)},e.makeSegments=function(t){return""==t?[]:e.isNumeric(t)?[e.makeNumeric(t)]:e.isAlphanumeric(t)?[e.makeAlphanumeric(t)]:[e.makeBytes(e.toUtf8ByteArray(t))]},e.makeEci=function(t){var r=[];if(t<0)throw new RangeError("ECI assignment value out of range");if(t<128)n(t,8,r);else if(t<16384)n(2,2,r),n(t,14,r);else{if(!(t<1e6))throw new RangeError("ECI assignment value out of range");n(6,3,r),n(t,21,r)}return new e(e.Mode.ECI,0,r)},e.isNumeric=function(t){return e.NUMERIC_REGEX.test(t)},e.isAlphanumeric=function(t){return e.ALPHANUMERIC_REGEX.test(t)},e.prototype.getData=function(){return this.bitData.slice()},e.getTotalBits=function(e,t){for(var n=0,r=0,o=e;r<o.length;r++){var i=o[r],s=i.mode.numCharCountBits(t);if(i.numChars>=1<<s)return 1/0;n+=4+s+i.bitData.length}return n},e.toUtf8ByteArray=function(e){e=encodeURI(e);for(var t=[],n=0;n<e.length;n++)"%"!=e.charAt(n)?t.push(e.charCodeAt(n)):(t.push(parseInt(e.substring(n+1,n+3),16)),n+=2);return t},e.NUMERIC_REGEX=/^[0-9]*$/,e.ALPHANUMERIC_REGEX=/^[A-Z0-9 $%*+.\/:-]*$/,e.ALPHANUMERIC_CHARSET="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ $%*+-./:",e}();e.QrSegment=i}(r||(r={})),function(e){(function(e){var t=function(){function e(e,t){this.ordinal=e,this.formatBits=t}return e.LOW=new e(0,1),e.MEDIUM=new e(1,0),e.QUARTILE=new e(2,3),e.HIGH=new e(3,2),e}();e.Ecc=t})(e.QrCode||(e.QrCode={}))}(r||(r={})),function(e){(function(e){var t=function(){function e(e,t){this.modeBits=e,this.numBitsCharCount=t}return e.prototype.numCharCountBits=function(e){return this.numBitsCharCount[Math.floor((e+7)/17)]},e.NUMERIC=new e(1,[10,12,14]),e.ALPHANUMERIC=new e(2,[9,11,13]),e.BYTE=new e(4,[8,16,16]),e.KANJI=new e(8,[8,10,12]),e.ECI=new e(7,[0,0,0]),e}();e.Mode=t})(e.QrSegment||(e.QrSegment={}))}(r||(r={}));var a=r,l=0,u="L",c=100,d=0,f=.1,h=2,p={L:a.QrCode.Ecc.LOW,M:a.QrCode.Ecc.MEDIUM,Q:a.QrCode.Ecc.QUARTILE,H:a.QrCode.Ecc.HIGH},m=function(){try{(new Path2D).addPath(new Path2D)}catch(e){return!1}return!0}();function v(e){return e in p}function g(e,t){void 0===t&&(t=0);for(var n=[],r=0;r<e.length;r++)for(var o=e[r],i=null,s=0;s<o.length;s++){var a=o[s];if(a||null===i)if(s!==o.length-1)a&&null===i&&(i=s);else{if(!a)continue;null===i?n.push("M".concat(s+t,",").concat(r+t," h1v1H").concat(s+t,"z")):n.push("M".concat(i+t,",").concat(r+t," h").concat(s+1-i,"v1H").concat(i+t,"z"))}else n.push("M".concat(i+t," ").concat(r+t,"h").concat(s-i,"v1H").concat(i+t,"z")),i=null}return n.join("")}function y(e,t,n,r){var o=r.width,i=r.height,s=r.x,a=r.y,l=e.length+2*n,u=Math.floor(t*f),c=l/t,d=(o||u)*c,h=(i||u)*c,p=null==s?e.length/2-d/2:s*c,m=null==a?e.length/2-h/2:a*c,v=(r.borderRadius||0)*c,g=null;if(r.excavate){var y=Math.floor(p),b=Math.floor(m),_=Math.ceil(d+p-y),E=Math.ceil(h+m-b);g={x:y,y:b,w:_,h:E}}return{x:p,y:m,h:h,w:d,borderRadius:v,excavation:g}}function b(e){var t=(0,o.EW)(function(){var t;return(null!==(t=e.margin)&&void 0!==t?t:d)>>>0}),n=(0,o.EW)(function(){var t=v(e.level)?e.level:u;return a.QrCode.encodeText(e.value,p[t]).getModules()}),r=(0,o.EW)(function(){return n.value.length+2*t.value}),i=(0,o.EW)(function(){return g(n.value,t.value)}),s=(0,o.EW)(function(){if(!e.imageSettings.src)return{x:0,y:0,width:0,height:0,borderRadius:0};var r=y(n.value,e.size,t.value,e.imageSettings);return{x:r.x+t.value,y:r.y+t.value,width:r.w,height:r.h,borderRadius:r.borderRadius}}),l=(0,o.EW)(function(){if(!e.imageSettings.excavate||!e.imageSettings.src)return null;var t=h/(e.size/r.value);return{x:s.value.x-t,y:s.value.y-t,width:s.value.width+2*t,height:s.value.height+2*t,borderRadius:s.value.borderRadius}});return{margin:t,numCells:r,cells:n,fgPath:i,imageProps:s,imageBorderProps:l}}var _={value:{type:String,required:!0,default:""},size:{type:Number,default:c},level:{type:String,default:u,validator:function(e){return v(e)}},background:{type:String,default:"#fff"},foreground:{type:String,default:"#000"},margin:{type:Number,required:!1,default:d},imageSettings:{type:Object,required:!1,default:function(){return{}}},gradient:{type:Boolean,required:!1,default:!1},gradientType:{type:String,required:!1,default:"linear",validator:function(e){return["linear","radial"].indexOf(e)>-1}},gradientStartColor:{type:String,required:!1,default:"#000"},gradientEndColor:{type:String,required:!1,default:"#fff"}},E=s(s({},_),{renderAs:{type:String,required:!1,default:"canvas",validator:function(e){return["canvas","svg"].indexOf(e)>-1}}}),w=(0,o.pM)({name:"QRCodeSvg",props:_,setup:function(e){var t=b(e),n=t.numCells,r=t.fgPath,i=t.imageProps,a=t.imageBorderProps,u=l++,c="qrcode.vue-gradient-".concat(u),d="qrcode.vue-logo-clip-path-".concat(u),f=function(){if(!e.gradient)return null;var t="linear"===e.gradientType?{x1:"0%",y1:"0%",x2:"100%",y2:"100%"}:{cx:"50%",cy:"50%",r:"50%",fx:"50%",fy:"50%"};return(0,o.h)("linear"===e.gradientType?"linearGradient":"radialGradient",s({id:c},t),[(0,o.h)("stop",{offset:"0%",style:{stopColor:e.gradientStartColor}}),(0,o.h)("stop",{offset:"100%",style:{stopColor:e.gradientEndColor}})])},h=function(){var t=i.value.borderRadius;return e.imageSettings.src?t<=0?null:(0,o.h)("clipPath",{id:d},[(0,o.h)("rect",{x:i.value.x,y:i.value.y,width:i.value.width,height:i.value.height,rx:t,ry:t})]):null};return function(){return(0,o.h)("svg",{width:e.size,height:e.size,"shape-rendering":"crispEdges",xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 ".concat(n.value," ").concat(n.value),role:"img","aria-label":e.value},[(0,o.h)("defs",{},[f(),h()]),(0,o.h)("rect",{width:"100%",height:"100%",fill:e.background}),(0,o.h)("path",{fill:e.gradient?"url(#".concat(c,")"):e.foreground,d:r.value}),a.value&&(0,o.h)("rect",{x:a.value.x,y:a.value.y,width:a.value.width,height:a.value.height,fill:e.background,rx:a.value.borderRadius,ry:a.value.borderRadius}),e.imageSettings.src&&(0,o.h)("image",s(s({href:e.imageSettings.src},i.value),i.value.borderRadius>0?{"clip-path":"url(#".concat(d,")")}:{}))])}}}),S=(0,o.pM)({name:"QRCodeCanvas",props:_,setup:function(e,t){var n=b(e),r=n.margin,a=n.cells,l=n.numCells,u=n.fgPath,c=n.imageProps,d=n.imageBorderProps,f=(0,i.KR)(null),h=(0,i.KR)(null),p=function(e,t,n,r,o,i){e.beginPath(),e.roundRect?e.roundRect(t,n,r,o,i):e.rect(t,n,r,o)},v=function(){var t=e.size,n=e.background,o=e.foreground,i=e.gradient,s=e.gradientType,v=e.gradientStartColor,g=e.gradientEndColor,y=f.value;if(y){var b=y.getContext("2d");if(b){var _=h.value,E="undefined"!==typeof window&&window.devicePixelRatio||1,w=t/l.value*E;if(y.height=y.width=t*E,b.scale(w,w),b.fillStyle=n,b.fillRect(0,0,l.value,l.value),i){var S=void 0;S="linear"===s?b.createLinearGradient(0,0,l.value,l.value):b.createRadialGradient(l.value/2,l.value/2,0,l.value/2,l.value/2,l.value/2),S.addColorStop(0,v),S.addColorStop(1,g),b.fillStyle=S}else b.fillStyle=o;m?b.fill(new Path2D(u.value)):a.value.forEach(function(e,t){e.forEach(function(e,n){e&&b.fillRect(n+r.value,t+r.value,1,1)})});var T=e.imageSettings.src&&_&&0!==_.naturalWidth&&0!==_.naturalHeight;if(T){if(d.value){var k=d.value;b.fillStyle=e.background,p(b,k.x,k.y,k.width,k.height,k.borderRadius),b.fill()}var C=c.value.borderRadius;C>0?(b.save(),p(b,c.value.x,c.value.y,c.value.width,c.value.height,C),b.clip(),b.drawImage(_,c.value.x,c.value.y,c.value.width,c.value.height),b.restore()):b.drawImage(_,c.value.x,c.value.y,c.value.width,c.value.height)}}}};(0,o.sV)(v),(0,o.nT)(v);var g=t.attrs.style;return function(){return(0,o.h)(o.FK,[(0,o.h)("canvas",s(s({},t.attrs),{ref:f,role:"img","aria-label":e.value,style:s(s({},g),{width:"".concat(e.size,"px"),height:"".concat(e.size,"px")})})),e.imageSettings.src&&(0,o.h)("img",{ref:h,src:e.imageSettings.src,style:{display:"none"},onLoad:v})])}}});(0,o.pM)({name:"Qrcode",props:E,setup:function(e){return function(){return(0,o.h)("svg"===e.renderAs?w:S,{value:e.value,size:e.size,margin:e.margin,level:e.level,background:e.background,foreground:e.foreground,imageSettings:e.imageSettings,gradient:e.gradient,gradientType:e.gradientType,gradientStartColor:e.gradientStartColor,gradientEndColor:e.gradientEndColor})}}})},6992:function(e,t,n){"use strict";
/*!
  * shared v9.14.5
  * (c) 2025 kazuya kawaguchi
  * Released under the MIT License.
  */
function r(e,t){"undefined"!==typeof console&&(console.warn("[intlify] "+e),t&&console.warn(t.stack))}n.d(t,{hU:function(){return Nr}});const o="undefined"!==typeof window;const i=(e,t=!1)=>t?Symbol.for(e):Symbol(e),s=(e,t,n)=>a({l:e,k:t,s:n}),a=e=>JSON.stringify(e).replace(/\u2028/g,"\\u2028").replace(/\u2029/g,"\\u2029").replace(/\u0027/g,"\\u0027"),l=e=>"number"===typeof e&&isFinite(e),u=e=>"[object Date]"===R(e),c=e=>"[object RegExp]"===R(e),d=e=>I(e)&&0===Object.keys(e).length,f=Object.assign,h=Object.create,p=(e=null)=>h(e);let m;const v=()=>m||(m="undefined"!==typeof globalThis?globalThis:"undefined"!==typeof self?self:"undefined"!==typeof window?window:"undefined"!==typeof n.g?n.g:p());function g(e){return e.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;").replace(/'/g,"&apos;").replace(/\//g,"&#x2F;").replace(/=/g,"&#x3D;")}function y(e){return e.replace(/&(?![a-zA-Z0-9#]{2,6};)/g,"&amp;").replace(/"/g,"&quot;").replace(/'/g,"&apos;").replace(/</g,"&lt;").replace(/>/g,"&gt;")}function b(e){e=e.replace(/(\w+)\s*=\s*"([^"]*)"/g,(e,t,n)=>`${t}="${y(n)}"`),e=e.replace(/(\w+)\s*=\s*'([^']*)'/g,(e,t,n)=>`${t}='${y(n)}'`);const t=/\s*on\w+\s*=\s*["']?[^"'>]+["']?/gi;t.test(e)&&(e=e.replace(/(\s+)(on)(\w+\s*=)/gi,"$1&#111;n$3"));const n=[/(\s+(?:href|src|action|formaction)\s*=\s*["']?)\s*javascript:/gi,/(style\s*=\s*["'][^"']*url\s*\(\s*)javascript:/gi];return n.forEach(t=>{e=e.replace(t,"$1javascript&#58;")}),e}const _=Object.prototype.hasOwnProperty;function E(e,t){return _.call(e,t)}const w=Array.isArray,S=e=>"function"===typeof e,T=e=>"string"===typeof e,k=e=>"boolean"===typeof e,C=e=>null!==e&&"object"===typeof e,O=e=>C(e)&&S(e.then)&&S(e.catch),A=Object.prototype.toString,R=e=>A.call(e),I=e=>{if(!C(e))return!1;const t=Object.getPrototypeOf(e);return null===t||t.constructor===Object},N=e=>null==e?"":w(e)||I(e)&&e.toString===A?JSON.stringify(e,null,2):String(e);function L(e,t=""){return e.reduce((e,n,r)=>0===r?e+n:e+t+n,"")}function x(e){let t=e;return()=>++t}const P=e=>!C(e)||w(e);function D(e,t){if(P(e)||P(t))throw new Error("Invalid value");const n=[{src:e,des:t}];while(n.length){const{src:e,des:t}=n.pop();Object.keys(e).forEach(r=>{"__proto__"!==r&&(C(e[r])&&!C(t[r])&&(t[r]=Array.isArray(e[r])?[]:p()),P(t[r])||P(e[r])?t[r]=e[r]:n.push({src:e[r],des:t[r]}))})}}function M(e,t,n){return{line:e,column:t,offset:n}}function F(e,t,n){const r={start:e,end:t};return null!=n&&(r.source=n),r}const $=/\{([0-9a-zA-Z]+)\}/g;function j(e,...t){return 1===t.length&&V(t[0])&&(t=t[0]),t&&t.hasOwnProperty||(t={}),e.replace($,(e,n)=>t.hasOwnProperty(n)?t[n]:"")}const U=Object.assign,B=e=>"string"===typeof e,V=e=>null!==e&&"object"===typeof e;function G(e,t=""){return e.reduce((e,n,r)=>0===r?e+n:e+t+n,"")}const H={USE_MODULO_SYNTAX:1,__EXTEND_POINT__:2},W={[H.USE_MODULO_SYNTAX]:"Use modulo before '{{0}}'."};function X(e,t,...n){const r=j(W[e]||"",...n||[]),o={message:String(r),code:e};return t&&(o.location=t),o}const K={EXPECTED_TOKEN:1,INVALID_TOKEN_IN_PLACEHOLDER:2,UNTERMINATED_SINGLE_QUOTE_IN_PLACEHOLDER:3,UNKNOWN_ESCAPE_SEQUENCE:4,INVALID_UNICODE_ESCAPE_SEQUENCE:5,UNBALANCED_CLOSING_BRACE:6,UNTERMINATED_CLOSING_BRACE:7,EMPTY_PLACEHOLDER:8,NOT_ALLOW_NEST_PLACEHOLDER:9,INVALID_LINKED_FORMAT:10,MUST_HAVE_MESSAGES_IN_PLURAL:11,UNEXPECTED_EMPTY_LINKED_MODIFIER:12,UNEXPECTED_EMPTY_LINKED_KEY:13,UNEXPECTED_LEXICAL_ANALYSIS:14,UNHANDLED_CODEGEN_NODE_TYPE:15,UNHANDLED_MINIFIER_NODE_TYPE:16,__EXTEND_POINT__:17},q={[K.EXPECTED_TOKEN]:"Expected token: '{0}'",[K.INVALID_TOKEN_IN_PLACEHOLDER]:"Invalid token in placeholder: '{0}'",[K.UNTERMINATED_SINGLE_QUOTE_IN_PLACEHOLDER]:"Unterminated single quote in placeholder",[K.UNKNOWN_ESCAPE_SEQUENCE]:"Unknown escape sequence: \\{0}",[K.INVALID_UNICODE_ESCAPE_SEQUENCE]:"Invalid unicode escape sequence: {0}",[K.UNBALANCED_CLOSING_BRACE]:"Unbalanced closing brace",[K.UNTERMINATED_CLOSING_BRACE]:"Unterminated closing brace",[K.EMPTY_PLACEHOLDER]:"Empty placeholder",[K.NOT_ALLOW_NEST_PLACEHOLDER]:"Not allowed nest placeholder",[K.INVALID_LINKED_FORMAT]:"Invalid linked format",[K.MUST_HAVE_MESSAGES_IN_PLURAL]:"Plural must have messages",[K.UNEXPECTED_EMPTY_LINKED_MODIFIER]:"Unexpected empty linked modifier",[K.UNEXPECTED_EMPTY_LINKED_KEY]:"Unexpected empty linked key",[K.UNEXPECTED_LEXICAL_ANALYSIS]:"Unexpected lexical analysis in token: '{0}'",[K.UNHANDLED_CODEGEN_NODE_TYPE]:"unhandled codegen node type: '{0}'",[K.UNHANDLED_MINIFIER_NODE_TYPE]:"unhandled mimifier node type: '{0}'"};function z(e,t,n={}){const{domain:r,messages:o,args:i}=n,s=j((o||q)[e]||"",...i||[]),a=new SyntaxError(String(s));return a.code=e,t&&(a.location=t),a.domain=r,a}function Y(e){throw e}const Q=" ",J="\r",Z="\n",ee=String.fromCharCode(8232),te=String.fromCharCode(8233);function ne(e){const t=e;let n=0,r=1,o=1,i=0;const s=e=>t[e]===J&&t[e+1]===Z,a=e=>t[e]===Z,l=e=>t[e]===te,u=e=>t[e]===ee,c=e=>s(e)||a(e)||l(e)||u(e),d=()=>n,f=()=>r,h=()=>o,p=()=>i,m=e=>s(e)||l(e)||u(e)?Z:t[e],v=()=>m(n),g=()=>m(n+i);function y(){return i=0,c(n)&&(r++,o=0),s(n)&&n++,n++,o++,t[n]}function b(){return s(n+i)&&i++,i++,t[n+i]}function _(){n=0,r=1,o=1,i=0}function E(e=0){i=e}function w(){const e=n+i;while(e!==n)y();i=0}return{index:d,line:f,column:h,peekOffset:p,charAt:m,currentChar:v,currentPeek:g,next:y,peek:b,reset:_,resetPeek:E,skipToPeek:w}}const re=void 0,oe="'",ie="tokenizer";function se(e,t={}){const n=!1!==t.location,r=ne(e),o=()=>r.index(),i=()=>M(r.line(),r.column(),r.index()),s=i(),a=o(),l={currentType:14,offset:a,startLoc:s,endLoc:s,lastType:14,lastOffset:a,lastStartLoc:s,lastEndLoc:s,braceNest:0,inLinked:!1,text:""},u=()=>l,{onError:c}=t;function d(e,t,r,...o){const i=u();if(t.column+=r,t.offset+=r,c){const r=n?F(i.startLoc,t):null,s=z(e,r,{domain:ie,args:o});c(s)}}function f(e,t,r){e.endLoc=i(),e.currentType=t;const o={type:t};return n&&(o.loc=F(e.startLoc,e.endLoc)),null!=r&&(o.value=r),o}const h=e=>f(e,14);function p(e,t){return e.currentChar()===t?(e.next(),t):(d(K.EXPECTED_TOKEN,i(),0,t),"")}function m(e){let t="";while(e.currentPeek()===Q||e.currentPeek()===Z)t+=e.currentPeek(),e.peek();return t}function v(e){const t=m(e);return e.skipToPeek(),t}function g(e){if(e===re)return!1;const t=e.charCodeAt(0);return t>=97&&t<=122||t>=65&&t<=90||95===t}function y(e){if(e===re)return!1;const t=e.charCodeAt(0);return t>=48&&t<=57}function b(e,t){const{currentType:n}=t;if(2!==n)return!1;m(e);const r=g(e.currentPeek());return e.resetPeek(),r}function _(e,t){const{currentType:n}=t;if(2!==n)return!1;m(e);const r="-"===e.currentPeek()?e.peek():e.currentPeek(),o=y(r);return e.resetPeek(),o}function E(e,t){const{currentType:n}=t;if(2!==n)return!1;m(e);const r=e.currentPeek()===oe;return e.resetPeek(),r}function w(e,t){const{currentType:n}=t;if(8!==n)return!1;m(e);const r="."===e.currentPeek();return e.resetPeek(),r}function S(e,t){const{currentType:n}=t;if(9!==n)return!1;m(e);const r=g(e.currentPeek());return e.resetPeek(),r}function T(e,t){const{currentType:n}=t;if(8!==n&&12!==n)return!1;m(e);const r=":"===e.currentPeek();return e.resetPeek(),r}function k(e,t){const{currentType:n}=t;if(10!==n)return!1;const r=()=>{const t=e.currentPeek();return"{"===t?g(e.peek()):!("@"===t||"%"===t||"|"===t||":"===t||"."===t||t===Q||!t)&&(t===Z?(e.peek(),r()):A(e,!1))},o=r();return e.resetPeek(),o}function C(e){m(e);const t="|"===e.currentPeek();return e.resetPeek(),t}function O(e){const t=m(e),n="%"===e.currentPeek()&&"{"===e.peek();return e.resetPeek(),{isModulo:n,hasSpace:t.length>0}}function A(e,t=!0){const n=(t=!1,r="",o=!1)=>{const i=e.currentPeek();return"{"===i?"%"!==r&&t:"@"!==i&&i?"%"===i?(e.peek(),n(t,"%",!0)):"|"===i?!("%"!==r&&!o)||!(r===Q||r===Z):i===Q?(e.peek(),n(!0,Q,o)):i!==Z||(e.peek(),n(!0,Z,o)):"%"===r||t},r=n();return t&&e.resetPeek(),r}function R(e,t){const n=e.currentChar();return n===re?re:t(n)?(e.next(),n):null}function I(e){const t=e.charCodeAt(0);return t>=97&&t<=122||t>=65&&t<=90||t>=48&&t<=57||95===t||36===t}function N(e){return R(e,I)}function L(e){const t=e.charCodeAt(0);return t>=97&&t<=122||t>=65&&t<=90||t>=48&&t<=57||95===t||36===t||45===t}function x(e){return R(e,L)}function P(e){const t=e.charCodeAt(0);return t>=48&&t<=57}function D(e){return R(e,P)}function $(e){const t=e.charCodeAt(0);return t>=48&&t<=57||t>=65&&t<=70||t>=97&&t<=102}function j(e){return R(e,$)}function U(e){let t="",n="";while(t=D(e))n+=t;return n}function B(e){v(e);const t=e.currentChar();return"%"!==t&&d(K.EXPECTED_TOKEN,i(),0,t),e.next(),"%"}function V(e){let t="";while(1){const n=e.currentChar();if("{"===n||"}"===n||"@"===n||"|"===n||!n)break;if("%"===n){if(!A(e))break;t+=n,e.next()}else if(n===Q||n===Z)if(A(e))t+=n,e.next();else{if(C(e))break;t+=n,e.next()}else t+=n,e.next()}return t}function G(e){v(e);let t="",n="";while(t=x(e))n+=t;return e.currentChar()===re&&d(K.UNTERMINATED_CLOSING_BRACE,i(),0),n}function H(e){v(e);let t="";return"-"===e.currentChar()?(e.next(),t+=`-${U(e)}`):t+=U(e),e.currentChar()===re&&d(K.UNTERMINATED_CLOSING_BRACE,i(),0),t}function W(e){return e!==oe&&e!==Z}function X(e){v(e),p(e,"'");let t="",n="";while(t=R(e,W))n+="\\"===t?q(e):t;const r=e.currentChar();return r===Z||r===re?(d(K.UNTERMINATED_SINGLE_QUOTE_IN_PLACEHOLDER,i(),0),r===Z&&(e.next(),p(e,"'")),n):(p(e,"'"),n)}function q(e){const t=e.currentChar();switch(t){case"\\":case"'":return e.next(),`\\${t}`;case"u":return Y(e,t,4);case"U":return Y(e,t,6);default:return d(K.UNKNOWN_ESCAPE_SEQUENCE,i(),0,t),""}}function Y(e,t,n){p(e,t);let r="";for(let o=0;o<n;o++){const n=j(e);if(!n){d(K.INVALID_UNICODE_ESCAPE_SEQUENCE,i(),0,`\\${t}${r}${e.currentChar()}`);break}r+=n}return`\\${t}${r}`}function J(e){return"{"!==e&&"}"!==e&&e!==Q&&e!==Z}function ee(e){v(e);let t="",n="";while(t=R(e,J))n+=t;return n}function te(e){let t="",n="";while(t=N(e))n+=t;return n}function se(e){const t=n=>{const r=e.currentChar();return"{"!==r&&"%"!==r&&"@"!==r&&"|"!==r&&"("!==r&&")"!==r&&r?r===Q?n:(n+=r,e.next(),t(n)):n};return t("")}function ae(e){v(e);const t=p(e,"|");return v(e),t}function le(e,t){let n=null;const r=e.currentChar();switch(r){case"{":return t.braceNest>=1&&d(K.NOT_ALLOW_NEST_PLACEHOLDER,i(),0),e.next(),n=f(t,2,"{"),v(e),t.braceNest++,n;case"}":return t.braceNest>0&&2===t.currentType&&d(K.EMPTY_PLACEHOLDER,i(),0),e.next(),n=f(t,3,"}"),t.braceNest--,t.braceNest>0&&v(e),t.inLinked&&0===t.braceNest&&(t.inLinked=!1),n;case"@":return t.braceNest>0&&d(K.UNTERMINATED_CLOSING_BRACE,i(),0),n=ue(e,t)||h(t),t.braceNest=0,n;default:{let r=!0,o=!0,s=!0;if(C(e))return t.braceNest>0&&d(K.UNTERMINATED_CLOSING_BRACE,i(),0),n=f(t,1,ae(e)),t.braceNest=0,t.inLinked=!1,n;if(t.braceNest>0&&(5===t.currentType||6===t.currentType||7===t.currentType))return d(K.UNTERMINATED_CLOSING_BRACE,i(),0),t.braceNest=0,ce(e,t);if(r=b(e,t))return n=f(t,5,G(e)),v(e),n;if(o=_(e,t))return n=f(t,6,H(e)),v(e),n;if(s=E(e,t))return n=f(t,7,X(e)),v(e),n;if(!r&&!o&&!s)return n=f(t,13,ee(e)),d(K.INVALID_TOKEN_IN_PLACEHOLDER,i(),0,n.value),v(e),n;break}}return n}function ue(e,t){const{currentType:n}=t;let r=null;const o=e.currentChar();switch(8!==n&&9!==n&&12!==n&&10!==n||o!==Z&&o!==Q||d(K.INVALID_LINKED_FORMAT,i(),0),o){case"@":return e.next(),r=f(t,8,"@"),t.inLinked=!0,r;case".":return v(e),e.next(),f(t,9,".");case":":return v(e),e.next(),f(t,10,":");default:return C(e)?(r=f(t,1,ae(e)),t.braceNest=0,t.inLinked=!1,r):w(e,t)||T(e,t)?(v(e),ue(e,t)):S(e,t)?(v(e),f(t,12,te(e))):k(e,t)?(v(e),"{"===o?le(e,t)||r:f(t,11,se(e))):(8===n&&d(K.INVALID_LINKED_FORMAT,i(),0),t.braceNest=0,t.inLinked=!1,ce(e,t))}}function ce(e,t){let n={type:14};if(t.braceNest>0)return le(e,t)||h(t);if(t.inLinked)return ue(e,t)||h(t);const r=e.currentChar();switch(r){case"{":return le(e,t)||h(t);case"}":return d(K.UNBALANCED_CLOSING_BRACE,i(),0),e.next(),f(t,3,"}");case"@":return ue(e,t)||h(t);default:{if(C(e))return n=f(t,1,ae(e)),t.braceNest=0,t.inLinked=!1,n;const{isModulo:r,hasSpace:o}=O(e);if(r)return o?f(t,0,V(e)):f(t,4,B(e));if(A(e))return f(t,0,V(e));break}}return n}function de(){const{currentType:e,offset:t,startLoc:n,endLoc:s}=l;return l.lastType=e,l.lastOffset=t,l.lastStartLoc=n,l.lastEndLoc=s,l.offset=o(),l.startLoc=i(),r.currentChar()===re?f(l,14):ce(r,l)}return{nextToken:de,currentOffset:o,currentPosition:i,context:u}}const ae="parser",le=/(?:\\\\|\\'|\\u([0-9a-fA-F]{4})|\\U([0-9a-fA-F]{6}))/g;function ue(e,t,n){switch(e){case"\\\\":return"\\";case"\\'":return"'";default:{const e=parseInt(t||n,16);return e<=55295||e>=57344?String.fromCodePoint(e):"�"}}}function ce(e={}){const t=!1!==e.location,{onError:n,onWarn:r}=e;function o(e,r,o,i,...s){const a=e.currentPosition();if(a.offset+=i,a.column+=i,n){const e=t?F(o,a):null,i=z(r,e,{domain:ae,args:s});n(i)}}function i(e,n,o,i,...s){const a=e.currentPosition();if(a.offset+=i,a.column+=i,r){const e=t?F(o,a):null;r(X(n,e,s))}}function s(e,n,r){const o={type:e};return t&&(o.start=n,o.end=n,o.loc={start:r,end:r}),o}function a(e,n,r,o){o&&(e.type=o),t&&(e.end=n,e.loc&&(e.loc.end=r))}function l(e,t){const n=e.context(),r=s(3,n.offset,n.startLoc);return r.value=t,a(r,e.currentOffset(),e.currentPosition()),r}function u(e,t){const n=e.context(),{lastOffset:r,lastStartLoc:o}=n,i=s(5,r,o);return i.index=parseInt(t,10),e.nextToken(),a(i,e.currentOffset(),e.currentPosition()),i}function c(e,t,n){const r=e.context(),{lastOffset:o,lastStartLoc:i}=r,l=s(4,o,i);return l.key=t,!0===n&&(l.modulo=!0),e.nextToken(),a(l,e.currentOffset(),e.currentPosition()),l}function d(e,t){const n=e.context(),{lastOffset:r,lastStartLoc:o}=n,i=s(9,r,o);return i.value=t.replace(le,ue),e.nextToken(),a(i,e.currentOffset(),e.currentPosition()),i}function f(e){const t=e.nextToken(),n=e.context(),{lastOffset:r,lastStartLoc:i}=n,l=s(8,r,i);return 12!==t.type?(o(e,K.UNEXPECTED_EMPTY_LINKED_MODIFIER,n.lastStartLoc,0),l.value="",a(l,r,i),{nextConsumeToken:t,node:l}):(null==t.value&&o(e,K.UNEXPECTED_LEXICAL_ANALYSIS,n.lastStartLoc,0,de(t)),l.value=t.value||"",a(l,e.currentOffset(),e.currentPosition()),{node:l})}function h(e,t){const n=e.context(),r=s(7,n.offset,n.startLoc);return r.value=t,a(r,e.currentOffset(),e.currentPosition()),r}function p(e){const t=e.context(),n=s(6,t.offset,t.startLoc);let r=e.nextToken();if(9===r.type){const t=f(e);n.modifier=t.node,r=t.nextConsumeToken||e.nextToken()}switch(10!==r.type&&o(e,K.UNEXPECTED_LEXICAL_ANALYSIS,t.lastStartLoc,0,de(r)),r=e.nextToken(),2===r.type&&(r=e.nextToken()),r.type){case 11:null==r.value&&o(e,K.UNEXPECTED_LEXICAL_ANALYSIS,t.lastStartLoc,0,de(r)),n.key=h(e,r.value||"");break;case 5:null==r.value&&o(e,K.UNEXPECTED_LEXICAL_ANALYSIS,t.lastStartLoc,0,de(r)),n.key=c(e,r.value||"");break;case 6:null==r.value&&o(e,K.UNEXPECTED_LEXICAL_ANALYSIS,t.lastStartLoc,0,de(r)),n.key=u(e,r.value||"");break;case 7:null==r.value&&o(e,K.UNEXPECTED_LEXICAL_ANALYSIS,t.lastStartLoc,0,de(r)),n.key=d(e,r.value||"");break;default:{o(e,K.UNEXPECTED_EMPTY_LINKED_KEY,t.lastStartLoc,0);const i=e.context(),l=s(7,i.offset,i.startLoc);return l.value="",a(l,i.offset,i.startLoc),n.key=l,a(n,i.offset,i.startLoc),{nextConsumeToken:r,node:n}}}return a(n,e.currentOffset(),e.currentPosition()),{node:n}}function m(e){const t=e.context(),n=1===t.currentType?e.currentOffset():t.offset,r=1===t.currentType?t.endLoc:t.startLoc,f=s(2,n,r);f.items=[];let h=null,m=null;do{const n=h||e.nextToken();switch(h=null,n.type){case 0:null==n.value&&o(e,K.UNEXPECTED_LEXICAL_ANALYSIS,t.lastStartLoc,0,de(n)),f.items.push(l(e,n.value||""));break;case 6:null==n.value&&o(e,K.UNEXPECTED_LEXICAL_ANALYSIS,t.lastStartLoc,0,de(n)),f.items.push(u(e,n.value||""));break;case 4:m=!0;break;case 5:null==n.value&&o(e,K.UNEXPECTED_LEXICAL_ANALYSIS,t.lastStartLoc,0,de(n)),f.items.push(c(e,n.value||"",!!m)),m&&(i(e,H.USE_MODULO_SYNTAX,t.lastStartLoc,0,de(n)),m=null);break;case 7:null==n.value&&o(e,K.UNEXPECTED_LEXICAL_ANALYSIS,t.lastStartLoc,0,de(n)),f.items.push(d(e,n.value||""));break;case 8:{const t=p(e);f.items.push(t.node),h=t.nextConsumeToken||null;break}}}while(14!==t.currentType&&1!==t.currentType);const v=1===t.currentType?t.lastOffset:e.currentOffset(),g=1===t.currentType?t.lastEndLoc:e.currentPosition();return a(f,v,g),f}function v(e,t,n,r){const i=e.context();let l=0===r.items.length;const u=s(1,t,n);u.cases=[],u.cases.push(r);do{const t=m(e);l||(l=0===t.items.length),u.cases.push(t)}while(14!==i.currentType);return l&&o(e,K.MUST_HAVE_MESSAGES_IN_PLURAL,n,0),a(u,e.currentOffset(),e.currentPosition()),u}function g(e){const t=e.context(),{offset:n,startLoc:r}=t,o=m(e);return 14===t.currentType?o:v(e,n,r,o)}function y(n){const r=se(n,U({},e)),i=r.context(),l=s(0,i.offset,i.startLoc);return t&&l.loc&&(l.loc.source=n),l.body=g(r),e.onCacheKey&&(l.cacheKey=e.onCacheKey(n)),14!==i.currentType&&o(r,K.UNEXPECTED_LEXICAL_ANALYSIS,i.lastStartLoc,0,n[i.offset]||""),a(l,r.currentOffset(),r.currentPosition()),l}return{parse:y}}function de(e){if(14===e.type)return"EOF";const t=(e.value||"").replace(/\r?\n/gu,"\\n");return t.length>10?t.slice(0,9)+"…":t}function fe(e,t={}){const n={ast:e,helpers:new Set},r=()=>n,o=e=>(n.helpers.add(e),e);return{context:r,helper:o}}function he(e,t){for(let n=0;n<e.length;n++)pe(e[n],t)}function pe(e,t){switch(e.type){case 1:he(e.cases,t),t.helper("plural");break;case 2:he(e.items,t);break;case 6:{const n=e;pe(n.key,t),t.helper("linked"),t.helper("type");break}case 5:t.helper("interpolate"),t.helper("list");break;case 4:t.helper("interpolate"),t.helper("named");break}}function me(e,t={}){const n=fe(e);n.helper("normalize"),e.body&&pe(e.body,n);const r=n.context();e.helpers=Array.from(r.helpers)}function ve(e){const t=e.body;return 2===t.type?ge(t):t.cases.forEach(e=>ge(e)),e}function ge(e){if(1===e.items.length){const t=e.items[0];3!==t.type&&9!==t.type||(e.static=t.value,delete t.value)}else{const t=[];for(let n=0;n<e.items.length;n++){const r=e.items[n];if(3!==r.type&&9!==r.type)break;if(null==r.value)break;t.push(r.value)}if(t.length===e.items.length){e.static=G(t);for(let t=0;t<e.items.length;t++){const n=e.items[t];3!==n.type&&9!==n.type||delete n.value}}}}const ye="minifier";function be(e){switch(e.t=e.type,e.type){case 0:{const t=e;be(t.body),t.b=t.body,delete t.body;break}case 1:{const t=e,n=t.cases;for(let e=0;e<n.length;e++)be(n[e]);t.c=n,delete t.cases;break}case 2:{const t=e,n=t.items;for(let e=0;e<n.length;e++)be(n[e]);t.i=n,delete t.items,t.static&&(t.s=t.static,delete t.static);break}case 3:case 9:case 8:case 7:{const t=e;t.value&&(t.v=t.value,delete t.value);break}case 6:{const t=e;be(t.key),t.k=t.key,delete t.key,t.modifier&&(be(t.modifier),t.m=t.modifier,delete t.modifier);break}case 5:{const t=e;t.i=t.index,delete t.index;break}case 4:{const t=e;t.k=t.key,delete t.key;break}default:throw z(K.UNHANDLED_MINIFIER_NODE_TYPE,null,{domain:ye,args:[e.type]})}delete e.type}const _e="parser";function Ee(e,t){const{sourceMap:n,filename:r,breakLineCode:o,needIndent:i}=t,s=!1!==t.location,a={filename:r,code:"",column:1,line:1,offset:0,map:void 0,breakLineCode:o,needIndent:i,indentLevel:0};s&&e.loc&&(a.source=e.loc.source);const l=()=>a;function u(e,t){a.code+=e}function c(e,t=!0){const n=t?o:"";u(i?n+"  ".repeat(e):n)}function d(e=!0){const t=++a.indentLevel;e&&c(t)}function f(e=!0){const t=--a.indentLevel;e&&c(t)}function h(){c(a.indentLevel)}const p=e=>`_${e}`,m=()=>a.needIndent;return{context:l,push:u,indent:d,deindent:f,newline:h,helper:p,needIndent:m}}function we(e,t){const{helper:n}=e;e.push(`${n("linked")}(`),Ce(e,t.key),t.modifier?(e.push(", "),Ce(e,t.modifier),e.push(", _type")):e.push(", undefined, _type"),e.push(")")}function Se(e,t){const{helper:n,needIndent:r}=e;e.push(`${n("normalize")}([`),e.indent(r());const o=t.items.length;for(let i=0;i<o;i++){if(Ce(e,t.items[i]),i===o-1)break;e.push(", ")}e.deindent(r()),e.push("])")}function Te(e,t){const{helper:n,needIndent:r}=e;if(t.cases.length>1){e.push(`${n("plural")}([`),e.indent(r());const o=t.cases.length;for(let n=0;n<o;n++){if(Ce(e,t.cases[n]),n===o-1)break;e.push(", ")}e.deindent(r()),e.push("])")}}function ke(e,t){t.body?Ce(e,t.body):e.push("null")}function Ce(e,t){const{helper:n}=e;switch(t.type){case 0:ke(e,t);break;case 1:Te(e,t);break;case 2:Se(e,t);break;case 6:we(e,t);break;case 8:e.push(JSON.stringify(t.value),t);break;case 7:e.push(JSON.stringify(t.value),t);break;case 5:e.push(`${n("interpolate")}(${n("list")}(${t.index}))`,t);break;case 4:e.push(`${n("interpolate")}(${n("named")}(${JSON.stringify(t.key)}))`,t);break;case 9:e.push(JSON.stringify(t.value),t);break;case 3:e.push(JSON.stringify(t.value),t);break;default:throw z(K.UNHANDLED_CODEGEN_NODE_TYPE,null,{domain:_e,args:[t.type]})}}const Oe=(e,t={})=>{const n=B(t.mode)?t.mode:"normal",r=B(t.filename)?t.filename:"message.intl",o=!!t.sourceMap,i=null!=t.breakLineCode?t.breakLineCode:"arrow"===n?";":"\n",s=t.needIndent?t.needIndent:"arrow"!==n,a=e.helpers||[],l=Ee(e,{mode:n,filename:r,sourceMap:o,breakLineCode:i,needIndent:s});l.push("normal"===n?"function __msg__ (ctx) {":"(ctx) => {"),l.indent(s),a.length>0&&(l.push(`const { ${G(a.map(e=>`${e}: _${e}`),", ")} } = ctx`),l.newline()),l.push("return "),Ce(l,e),l.deindent(s),l.push("}"),delete e.helpers;const{code:u,map:c}=l.context();return{ast:e,code:u,map:c?c.toJSON():void 0}};function Ae(e,t={}){const n=U({},t),r=!!n.jit,o=!!n.minify,i=null==n.optimize||n.optimize,s=ce(n),a=s.parse(e);return r?(i&&ve(a),o&&be(a),{ast:a,code:""}):(me(a,n),Oe(a,n))}
/*!
  * core-base v9.14.5
  * (c) 2025 kazuya kawaguchi
  * Released under the MIT License.
  */
function Re(){"boolean"!==typeof __INTLIFY_PROD_DEVTOOLS__&&(v().__INTLIFY_PROD_DEVTOOLS__=!1),"boolean"!==typeof __INTLIFY_JIT_COMPILATION__&&(v().__INTLIFY_JIT_COMPILATION__=!1),"boolean"!==typeof __INTLIFY_DROP_MESSAGE_COMPILER__&&(v().__INTLIFY_DROP_MESSAGE_COMPILER__=!1)}function Ie(e){return C(e)&&0===Ue(e)&&(E(e,"b")||E(e,"body"))}const Ne=["b","body"];function Le(e){return Ke(e,Ne)}const xe=["c","cases"];function Pe(e){return Ke(e,xe,[])}const De=["s","static"];function Me(e){return Ke(e,De)}const Fe=["i","items"];function $e(e){return Ke(e,Fe,[])}const je=["t","type"];function Ue(e){return Ke(e,je)}const Be=["v","value"];function Ve(e,t){const n=Ke(e,Be);if(null!=n)return n;throw ze(t)}const Ge=["m","modifier"];function He(e){return Ke(e,Ge)}const We=["k","key"];function Xe(e){const t=Ke(e,We);if(t)return t;throw ze(6)}function Ke(e,t,n){for(let r=0;r<t.length;r++){const n=t[r];if(E(e,n)&&null!=e[n])return e[n]}return n}const qe=[...Ne,...xe,...De,...Fe,...We,...Ge,...Be,...je];function ze(e){return new Error(`unhandled node type: ${e}`)}const Ye=[];Ye[0]={["w"]:[0],["i"]:[3,0],["["]:[4],["o"]:[7]},Ye[1]={["w"]:[1],["."]:[2],["["]:[4],["o"]:[7]},Ye[2]={["w"]:[2],["i"]:[3,0],["0"]:[3,0]},Ye[3]={["i"]:[3,0],["0"]:[3,0],["w"]:[1,1],["."]:[2,1],["["]:[4,1],["o"]:[7,1]},Ye[4]={["'"]:[5,0],['"']:[6,0],["["]:[4,2],["]"]:[1,3],["o"]:8,["l"]:[4,0]},Ye[5]={["'"]:[4,0],["o"]:8,["l"]:[5,0]},Ye[6]={['"']:[4,0],["o"]:8,["l"]:[6,0]};const Qe=/^\s?(?:true|false|-?[\d.]+|'[^']*'|"[^"]*")\s?$/;function Je(e){return Qe.test(e)}function Ze(e){const t=e.charCodeAt(0),n=e.charCodeAt(e.length-1);return t!==n||34!==t&&39!==t?e:e.slice(1,-1)}function et(e){if(void 0===e||null===e)return"o";const t=e.charCodeAt(0);switch(t){case 91:case 93:case 46:case 34:case 39:return e;case 95:case 36:case 45:return"i";case 9:case 10:case 13:case 160:case 65279:case 8232:case 8233:return"w"}return"i"}function tt(e){const t=e.trim();return("0"!==e.charAt(0)||!isNaN(parseInt(e)))&&(Je(t)?Ze(t):"*"+t)}function nt(e){const t=[];let n,r,o,i,s,a,l,u=-1,c=0,d=0;const f=[];function h(){const t=e[u+1];if(5===c&&"'"===t||6===c&&'"'===t)return u++,o="\\"+t,f[0](),!0}f[0]=()=>{void 0===r?r=o:r+=o},f[1]=()=>{void 0!==r&&(t.push(r),r=void 0)},f[2]=()=>{f[0](),d++},f[3]=()=>{if(d>0)d--,c=4,f[0]();else{if(d=0,void 0===r)return!1;if(r=tt(r),!1===r)return!1;f[1]()}};while(null!==c)if(u++,n=e[u],"\\"!==n||!h()){if(i=et(n),l=Ye[c],s=l[i]||l["l"]||8,8===s)return;if(c=s[0],void 0!==s[1]&&(a=f[s[1]],a&&(o=n,!1===a())))return;if(7===c)return t}}const rt=new Map;function ot(e,t){return C(e)?e[t]:null}function it(e,t){if(!C(e))return null;let n=rt.get(t);if(n||(n=nt(t),n&&rt.set(t,n)),!n)return null;const r=n.length;let o=e,i=0;while(i<r){const e=n[i];if(qe.includes(e)&&Ie(o))return null;const t=o[e];if(void 0===t)return null;if(S(o))return null;o=t,i++}return o}const st=e=>e,at=e=>"",lt="text",ut=e=>0===e.length?"":L(e),ct=N;function dt(e,t){return e=Math.abs(e),2===t?e?e>1?1:0:1:e?Math.min(e,2):0}function ft(e){const t=l(e.pluralIndex)?e.pluralIndex:-1;return e.named&&(l(e.named.count)||l(e.named.n))?l(e.named.count)?e.named.count:l(e.named.n)?e.named.n:t:t}function ht(e,t){t.count||(t.count=e),t.n||(t.n=e)}function pt(e={}){const t=e.locale,n=ft(e),r=C(e.pluralRules)&&T(t)&&S(e.pluralRules[t])?e.pluralRules[t]:dt,o=C(e.pluralRules)&&T(t)&&S(e.pluralRules[t])?dt:void 0,i=e=>e[r(n,e.length,o)],s=e.list||[],a=e=>s[e],u=e.named||p();l(e.pluralIndex)&&ht(n,u);const c=e=>u[e];function d(t){const n=S(e.messages)?e.messages(t):!!C(e.messages)&&e.messages[t];return n||(e.parent?e.parent.message(t):at)}const h=t=>e.modifiers?e.modifiers[t]:st,m=I(e.processor)&&S(e.processor.normalize)?e.processor.normalize:ut,v=I(e.processor)&&S(e.processor.interpolate)?e.processor.interpolate:ct,g=I(e.processor)&&T(e.processor.type)?e.processor.type:lt,y=(e,...t)=>{const[n,r]=t;let o="text",i="";1===t.length?C(n)?(i=n.modifier||i,o=n.type||o):T(n)&&(i=n||i):2===t.length&&(T(n)&&(i=n||i),T(r)&&(o=r||o));const s=d(e)(b),a="vnode"===o&&w(s)&&i?s[0]:s;return i?h(i)(a,o):a},b={["list"]:a,["named"]:c,["plural"]:i,["linked"]:y,["message"]:d,["type"]:g,["interpolate"]:v,["normalize"]:m,["values"]:f(p(),s,u)};return b}let mt=null;function vt(e){mt=e}function gt(e,t,n){mt&&mt.emit("i18n:init",{timestamp:Date.now(),i18n:e,version:t,meta:n})}const yt=bt("function:translate");function bt(e){return t=>mt&&mt.emit(e,t)}const _t=H.__EXTEND_POINT__,Et=x(_t),wt={NOT_FOUND_KEY:_t,FALLBACK_TO_TRANSLATE:Et(),CANNOT_FORMAT_NUMBER:Et(),FALLBACK_TO_NUMBER_FORMAT:Et(),CANNOT_FORMAT_DATE:Et(),FALLBACK_TO_DATE_FORMAT:Et(),EXPERIMENTAL_CUSTOM_MESSAGE_COMPILER:Et(),__EXTEND_POINT__:Et()};wt.NOT_FOUND_KEY,wt.FALLBACK_TO_TRANSLATE,wt.CANNOT_FORMAT_NUMBER,wt.FALLBACK_TO_NUMBER_FORMAT,wt.CANNOT_FORMAT_DATE,wt.FALLBACK_TO_DATE_FORMAT,wt.EXPERIMENTAL_CUSTOM_MESSAGE_COMPILER;const St=K.__EXTEND_POINT__,Tt=x(St),kt={INVALID_ARGUMENT:St,INVALID_DATE_ARGUMENT:Tt(),INVALID_ISO_DATE_ARGUMENT:Tt(),NOT_SUPPORT_NON_STRING_MESSAGE:Tt(),NOT_SUPPORT_LOCALE_PROMISE_VALUE:Tt(),NOT_SUPPORT_LOCALE_ASYNC_FUNCTION:Tt(),NOT_SUPPORT_LOCALE_TYPE:Tt(),__EXTEND_POINT__:Tt()};function Ct(e){return z(e,null,void 0)}kt.INVALID_ARGUMENT,kt.INVALID_DATE_ARGUMENT,kt.INVALID_ISO_DATE_ARGUMENT,kt.NOT_SUPPORT_NON_STRING_MESSAGE,kt.NOT_SUPPORT_LOCALE_PROMISE_VALUE,kt.NOT_SUPPORT_LOCALE_ASYNC_FUNCTION,kt.NOT_SUPPORT_LOCALE_TYPE;function Ot(e,t){return null!=t.locale?Rt(t.locale):Rt(e.locale)}let At;function Rt(e){if(T(e))return e;if(S(e)){if(e.resolvedOnce&&null!=At)return At;if("Function"===e.constructor.name){const t=e();if(O(t))throw Ct(kt.NOT_SUPPORT_LOCALE_PROMISE_VALUE);return At=t}throw Ct(kt.NOT_SUPPORT_LOCALE_ASYNC_FUNCTION)}throw Ct(kt.NOT_SUPPORT_LOCALE_TYPE)}function It(e,t,n){return[...new Set([n,...w(t)?t:C(t)?Object.keys(t):T(t)?[t]:[n]])]}function Nt(e,t,n){const r=T(n)?n:Ft,o=e;o.__localeChainCache||(o.__localeChainCache=new Map);let i=o.__localeChainCache.get(r);if(!i){i=[];let e=[n];while(w(e))e=Lt(i,e,t);const s=w(t)||!I(t)?t:t["default"]?t["default"]:null;e=T(s)?[s]:s,w(e)&&Lt(i,e,!1),o.__localeChainCache.set(r,i)}return i}function Lt(e,t,n){let r=!0;for(let o=0;o<t.length&&k(r);o++){const i=t[o];T(i)&&(r=xt(e,t[o],n))}return r}function xt(e,t,n){let r;const o=t.split("-");do{const t=o.join("-");r=Pt(e,t,n),o.splice(-1,1)}while(o.length&&!0===r);return r}function Pt(e,t,n){let r=!1;if(!e.includes(t)&&(r=!0,t)){r="!"!==t[t.length-1];const o=t.replace(/!/g,"");e.push(o),(w(n)||I(n))&&n[o]&&(r=n[o])}return r}const Dt="9.14.5",Mt=-1,Ft="en-US",$t="",jt=e=>`${e.charAt(0).toLocaleUpperCase()}${e.substr(1)}`;function Ut(){return{upper:(e,t)=>"text"===t&&T(e)?e.toUpperCase():"vnode"===t&&C(e)&&"__v_isVNode"in e?e.children.toUpperCase():e,lower:(e,t)=>"text"===t&&T(e)?e.toLowerCase():"vnode"===t&&C(e)&&"__v_isVNode"in e?e.children.toLowerCase():e,capitalize:(e,t)=>"text"===t&&T(e)?jt(e):"vnode"===t&&C(e)&&"__v_isVNode"in e?jt(e.children):e}}let Bt,Vt,Gt;function Ht(e){Bt=e}function Wt(e){Vt=e}function Xt(e){Gt=e}let Kt=null;const qt=e=>{Kt=e},zt=()=>Kt;let Yt=null;const Qt=e=>{Yt=e},Jt=()=>Yt;let Zt=0;function en(e={}){const t=S(e.onWarn)?e.onWarn:r,n=T(e.version)?e.version:Dt,o=T(e.locale)||S(e.locale)?e.locale:Ft,i=S(o)?Ft:o,s=w(e.fallbackLocale)||I(e.fallbackLocale)||T(e.fallbackLocale)||!1===e.fallbackLocale?e.fallbackLocale:i,a=I(e.messages)?e.messages:tn(i),l=I(e.datetimeFormats)?e.datetimeFormats:tn(i),u=I(e.numberFormats)?e.numberFormats:tn(i),d=f(p(),e.modifiers,Ut()),h=e.pluralRules||p(),m=S(e.missing)?e.missing:null,v=!k(e.missingWarn)&&!c(e.missingWarn)||e.missingWarn,g=!k(e.fallbackWarn)&&!c(e.fallbackWarn)||e.fallbackWarn,y=!!e.fallbackFormat,b=!!e.unresolving,_=S(e.postTranslation)?e.postTranslation:null,E=I(e.processor)?e.processor:null,O=!k(e.warnHtmlMessage)||e.warnHtmlMessage,A=!!e.escapeParameter,R=S(e.messageCompiler)?e.messageCompiler:Bt;const N=S(e.messageResolver)?e.messageResolver:Vt||ot,L=S(e.localeFallbacker)?e.localeFallbacker:Gt||It,x=C(e.fallbackContext)?e.fallbackContext:void 0,P=e,D=C(P.__datetimeFormatters)?P.__datetimeFormatters:new Map,M=C(P.__numberFormatters)?P.__numberFormatters:new Map,F=C(P.__meta)?P.__meta:{};Zt++;const $={version:n,cid:Zt,locale:o,fallbackLocale:s,messages:a,modifiers:d,pluralRules:h,missing:m,missingWarn:v,fallbackWarn:g,fallbackFormat:y,unresolving:b,postTranslation:_,processor:E,warnHtmlMessage:O,escapeParameter:A,messageCompiler:R,messageResolver:N,localeFallbacker:L,fallbackContext:x,onWarn:t,__meta:F};return $.datetimeFormats=l,$.numberFormats=u,$.__datetimeFormatters=D,$.__numberFormatters=M,__INTLIFY_PROD_DEVTOOLS__&&gt($,n,F),$}const tn=e=>({[e]:p()});function nn(e,t,n,r,o){const{missing:i,onWarn:s}=e;if(null!==i){const r=i(e,n,t,o);return T(r)?r:t}return t}function rn(e,t,n){const r=e;r.__localeChainCache=new Map,e.localeFallbacker(e,n,t)}function on(e,t){return e!==t&&e.split("-")[0]===t.split("-")[0]}function sn(e,t){const n=t.indexOf(e);if(-1===n)return!1;for(let r=n+1;r<t.length;r++)if(on(e,t[r]))return!0;return!1}function an(e){const t=t=>ln(t,e);return t}function ln(e,t){const n=Le(t);if(null==n)throw ze(0);const r=Ue(n);if(1===r){const t=n,r=Pe(t);return e.plural(r.reduce((t,n)=>[...t,un(e,n)],[]))}return un(e,n)}function un(e,t){const n=Me(t);if(null!=n)return"text"===e.type?n:e.normalize([n]);{const n=$e(t).reduce((t,n)=>[...t,cn(e,n)],[]);return e.normalize(n)}}function cn(e,t){const n=Ue(t);switch(n){case 3:return Ve(t,n);case 9:return Ve(t,n);case 4:{const r=t;if(E(r,"k")&&r.k)return e.interpolate(e.named(r.k));if(E(r,"key")&&r.key)return e.interpolate(e.named(r.key));throw ze(n)}case 5:{const r=t;if(E(r,"i")&&l(r.i))return e.interpolate(e.list(r.i));if(E(r,"index")&&l(r.index))return e.interpolate(e.list(r.index));throw ze(n)}case 6:{const n=t,r=He(n),o=Xe(n);return e.linked(cn(e,o),r?cn(e,r):void 0,e.type)}case 7:return Ve(t,n);case 8:return Ve(t,n);default:throw new Error(`unhandled node on format message part: ${n}`)}}const dn=e=>e;let fn=p();function hn(e,t={}){let n=!1;const r=t.onError||Y;return t.onError=e=>{n=!0,r(e)},{...Ae(e,t),detectError:n}}const pn=(e,t)=>{if(!T(e))throw Ct(kt.NOT_SUPPORT_NON_STRING_MESSAGE);{!k(t.warnHtmlMessage)||t.warnHtmlMessage;const n=t.onCacheKey||dn,r=n(e),o=fn[r];if(o)return o;const{code:i,detectError:s}=hn(e,t),a=new Function(`return ${i}`)();return s?a:fn[r]=a}};function mn(e,t){if(__INTLIFY_JIT_COMPILATION__&&!__INTLIFY_DROP_MESSAGE_COMPILER__&&T(e)){!k(t.warnHtmlMessage)||t.warnHtmlMessage;const n=t.onCacheKey||dn,r=n(e),o=fn[r];if(o)return o;const{ast:i,detectError:s}=hn(e,{...t,location:!1,jit:!0}),a=an(i);return s?a:fn[r]=a}{0;const t=e.cacheKey;if(t){const n=fn[t];return n||(fn[t]=an(e))}return an(e)}}const vn=()=>"",gn=e=>S(e);function yn(e,...t){const{fallbackFormat:n,postTranslation:r,unresolving:o,messageCompiler:i,fallbackLocale:s,messages:a}=e,[l,u]=Sn(...t),c=k(u.missingWarn)?u.missingWarn:e.missingWarn,d=k(u.fallbackWarn)?u.fallbackWarn:e.fallbackWarn,h=k(u.escapeParameter)?u.escapeParameter:e.escapeParameter,m=!!u.resolvedMessage,v=T(u.default)||k(u.default)?k(u.default)?i?l:()=>l:u.default:n?i?l:()=>l:"",g=n||""!==v,y=Ot(e,u);h&&bn(u);let[_,E,w]=m?[l,y,a[y]||p()]:_n(e,l,y,s,d,c),S=_,C=l;if(m||T(S)||Ie(S)||gn(S)||g&&(S=v,C=S),!m&&(!(T(S)||Ie(S)||gn(S))||!T(E)))return o?Mt:l;let O=!1;const A=()=>{O=!0},R=gn(S)?S:En(e,l,E,S,C,A);if(O)return S;const I=kn(e,E,w,u),N=pt(I),L=wn(e,R,N);let x=r?r(L,l):L;if(h&&T(x)&&(x=b(x)),__INTLIFY_PROD_DEVTOOLS__){const t={timestamp:Date.now(),key:T(l)?l:gn(S)?S.key:"",locale:E||(gn(S)?S.locale:""),format:T(S)?S:gn(S)?S.source:"",message:x};t.meta=f({},e.__meta,zt()||{}),yt(t)}return x}function bn(e){w(e.list)?e.list=e.list.map(e=>T(e)?g(e):e):C(e.named)&&Object.keys(e.named).forEach(t=>{T(e.named[t])&&(e.named[t]=g(e.named[t]))})}function _n(e,t,n,r,o,i){const{messages:s,onWarn:a,messageResolver:l,localeFallbacker:u}=e,c=u(e,r,n);let d,f=p(),h=null,m=n,v=null;const g="translate";for(let y=0;y<c.length;y++){d=v=c[y],f=s[d]||p();if(null===(h=l(f,t))&&(h=f[t]),T(h)||Ie(h)||gn(h))break;if(!sn(d,c)){const n=nn(e,t,d,i,g);n!==t&&(h=n)}m=v}return[h,d,f]}function En(e,t,n,r,o,i){const{messageCompiler:s,warnHtmlMessage:a}=e;if(gn(r)){const e=r;return e.locale=e.locale||n,e.key=e.key||t,e}if(null==s){const e=()=>r;return e.locale=n,e.key=t,e}const l=s(r,Tn(e,n,o,r,a,i));return l.locale=n,l.key=t,l.source=r,l}function wn(e,t,n){const r=t(n);return r}function Sn(...e){const[t,n,r]=e,o=p();if(!T(t)&&!l(t)&&!gn(t)&&!Ie(t))throw Ct(kt.INVALID_ARGUMENT);const i=l(t)?String(t):(gn(t),t);return l(n)?o.plural=n:T(n)?o.default=n:I(n)&&!d(n)?o.named=n:w(n)&&(o.list=n),l(r)?o.plural=r:T(r)?o.default=r:I(r)&&f(o,r),[i,o]}function Tn(e,t,n,r,o,i){return{locale:t,key:n,warnHtmlMessage:o,onError:e=>{throw i&&i(e),e},onCacheKey:e=>s(t,n,e)}}function kn(e,t,n,r){const{modifiers:o,pluralRules:i,messageResolver:s,fallbackLocale:a,fallbackWarn:u,missingWarn:c,fallbackContext:d}=e,f=r=>{let o=s(n,r);if(null==o&&d){const[,,e]=_n(d,r,t,a,u,c);o=s(e,r)}if(T(o)||Ie(o)){let n=!1;const i=()=>{n=!0},s=En(e,r,t,o,r,i);return n?vn:s}return gn(o)?o:vn},h={locale:t,modifiers:o,pluralRules:i,messages:f};return e.processor&&(h.processor=e.processor),r.list&&(h.list=r.list),r.named&&(h.named=r.named),l(r.plural)&&(h.pluralIndex=r.plural),h}const Cn="undefined"!==typeof Intl;Cn&&Intl.DateTimeFormat,Cn&&Intl.NumberFormat;function On(e,...t){const{datetimeFormats:n,unresolving:r,fallbackLocale:o,onWarn:i,localeFallbacker:s}=e,{__datetimeFormatters:a}=e;const[l,u,c,h]=Rn(...t),p=k(c.missingWarn)?c.missingWarn:e.missingWarn,m=(k(c.fallbackWarn)?c.fallbackWarn:e.fallbackWarn,!!c.part),v=Ot(e,c),g=s(e,o,v);if(!T(l)||""===l)return new Intl.DateTimeFormat(v,h).format(u);let y,b={},_=null,E=v,w=null;const S="datetime format";for(let d=0;d<g.length;d++){if(y=w=g[d],b=n[y]||{},_=b[l],I(_))break;nn(e,l,y,p,S),E=w}if(!I(_)||!T(y))return r?Mt:l;let C=`${y}__${l}`;d(h)||(C=`${C}__${JSON.stringify(h)}`);let O=a.get(C);return O||(O=new Intl.DateTimeFormat(y,f({},_,h)),a.set(C,O)),m?O.formatToParts(u):O.format(u)}const An=["localeMatcher","weekday","era","year","month","day","hour","minute","second","timeZoneName","formatMatcher","hour12","timeZone","dateStyle","timeStyle","calendar","dayPeriod","numberingSystem","hourCycle","fractionalSecondDigits"];function Rn(...e){const[t,n,r,o]=e,i=p();let s,a=p();if(T(t)){const e=t.match(/(\d{4}-\d{2}-\d{2})(T|\s)?(.*)/);if(!e)throw Ct(kt.INVALID_ISO_DATE_ARGUMENT);const n=e[3]?e[3].trim().startsWith("T")?`${e[1].trim()}${e[3].trim()}`:`${e[1].trim()}T${e[3].trim()}`:e[1].trim();s=new Date(n);try{s.toISOString()}catch(c){throw Ct(kt.INVALID_ISO_DATE_ARGUMENT)}}else if(u(t)){if(isNaN(t.getTime()))throw Ct(kt.INVALID_DATE_ARGUMENT);s=t}else{if(!l(t))throw Ct(kt.INVALID_ARGUMENT);s=t}return T(n)?i.key=n:I(n)&&Object.keys(n).forEach(e=>{An.includes(e)?a[e]=n[e]:i[e]=n[e]}),T(r)?i.locale=r:I(r)&&(a=r),I(o)&&(a=o),[i.key||"",s,i,a]}function In(e,t,n){const r=e;for(const o in n){const e=`${t}__${o}`;r.__datetimeFormatters.has(e)&&r.__datetimeFormatters.delete(e)}}function Nn(e,...t){const{numberFormats:n,unresolving:r,fallbackLocale:o,onWarn:i,localeFallbacker:s}=e,{__numberFormatters:a}=e;const[l,u,c,h]=xn(...t),p=k(c.missingWarn)?c.missingWarn:e.missingWarn,m=(k(c.fallbackWarn)?c.fallbackWarn:e.fallbackWarn,!!c.part),v=Ot(e,c),g=s(e,o,v);if(!T(l)||""===l)return new Intl.NumberFormat(v,h).format(u);let y,b={},_=null,E=v,w=null;const S="number format";for(let d=0;d<g.length;d++){if(y=w=g[d],b=n[y]||{},_=b[l],I(_))break;nn(e,l,y,p,S),E=w}if(!I(_)||!T(y))return r?Mt:l;let C=`${y}__${l}`;d(h)||(C=`${C}__${JSON.stringify(h)}`);let O=a.get(C);return O||(O=new Intl.NumberFormat(y,f({},_,h)),a.set(C,O)),m?O.formatToParts(u):O.format(u)}const Ln=["localeMatcher","style","currency","currencyDisplay","currencySign","useGrouping","minimumIntegerDigits","minimumFractionDigits","maximumFractionDigits","minimumSignificantDigits","maximumSignificantDigits","compactDisplay","notation","signDisplay","unit","unitDisplay","roundingMode","roundingPriority","roundingIncrement","trailingZeroDisplay"];function xn(...e){const[t,n,r,o]=e,i=p();let s=p();if(!l(t))throw Ct(kt.INVALID_ARGUMENT);const a=t;return T(n)?i.key=n:I(n)&&Object.keys(n).forEach(e=>{Ln.includes(e)?s[e]=n[e]:i[e]=n[e]}),T(r)?i.locale=r:I(r)&&(s=r),I(o)&&(s=o),[i.key||"",a,i,s]}function Pn(e,t,n){const r=e;for(const o in n){const e=`${t}__${o}`;r.__numberFormatters.has(e)&&r.__numberFormatters.delete(e)}}Re();var Dn=n(641),Mn=n(953);
/*!
  * vue-i18n v9.14.5
  * (c) 2025 kazuya kawaguchi
  * Released under the MIT License.
  */
const Fn="9.14.5";function $n(){"boolean"!==typeof __VUE_I18N_FULL_INSTALL__&&(v().__VUE_I18N_FULL_INSTALL__=!0),"boolean"!==typeof __VUE_I18N_LEGACY_API__&&(v().__VUE_I18N_LEGACY_API__=!0),"boolean"!==typeof __INTLIFY_JIT_COMPILATION__&&(v().__INTLIFY_JIT_COMPILATION__=!1),"boolean"!==typeof __INTLIFY_DROP_MESSAGE_COMPILER__&&(v().__INTLIFY_DROP_MESSAGE_COMPILER__=!1),"boolean"!==typeof __INTLIFY_PROD_DEVTOOLS__&&(v().__INTLIFY_PROD_DEVTOOLS__=!1)}const jn=wt.__EXTEND_POINT__,Un=x(jn),Bn={FALLBACK_TO_ROOT:jn,NOT_SUPPORTED_PRESERVE:Un(),NOT_SUPPORTED_FORMATTER:Un(),NOT_SUPPORTED_PRESERVE_DIRECTIVE:Un(),NOT_SUPPORTED_GET_CHOICE_INDEX:Un(),COMPONENT_NAME_LEGACY_COMPATIBLE:Un(),NOT_FOUND_PARENT_SCOPE:Un(),IGNORE_OBJ_FLATTEN:Un(),NOTICE_DROP_ALLOW_COMPOSITION:Un(),NOTICE_DROP_TRANSLATE_EXIST_COMPATIBLE_FLAG:Un()};Bn.FALLBACK_TO_ROOT,Bn.NOT_SUPPORTED_PRESERVE,Bn.NOT_SUPPORTED_FORMATTER,Bn.NOT_SUPPORTED_PRESERVE_DIRECTIVE,Bn.NOT_SUPPORTED_GET_CHOICE_INDEX,Bn.COMPONENT_NAME_LEGACY_COMPATIBLE,Bn.NOT_FOUND_PARENT_SCOPE,Bn.IGNORE_OBJ_FLATTEN,Bn.NOTICE_DROP_ALLOW_COMPOSITION,Bn.NOTICE_DROP_TRANSLATE_EXIST_COMPATIBLE_FLAG;const Vn=kt.__EXTEND_POINT__,Gn=x(Vn),Hn={UNEXPECTED_RETURN_TYPE:Vn,INVALID_ARGUMENT:Gn(),MUST_BE_CALL_SETUP_TOP:Gn(),NOT_INSTALLED:Gn(),NOT_AVAILABLE_IN_LEGACY_MODE:Gn(),REQUIRED_VALUE:Gn(),INVALID_VALUE:Gn(),CANNOT_SETUP_VUE_DEVTOOLS_PLUGIN:Gn(),NOT_INSTALLED_WITH_PROVIDE:Gn(),UNEXPECTED_ERROR:Gn(),NOT_COMPATIBLE_LEGACY_VUE_I18N:Gn(),BRIDGE_SUPPORT_VUE_2_ONLY:Gn(),MUST_DEFINE_I18N_OPTION_IN_ALLOW_COMPOSITION:Gn(),NOT_AVAILABLE_COMPOSITION_IN_LEGACY:Gn(),__EXTEND_POINT__:Gn()};function Wn(e,...t){return z(e,null,void 0)}Hn.UNEXPECTED_RETURN_TYPE,Hn.INVALID_ARGUMENT,Hn.MUST_BE_CALL_SETUP_TOP,Hn.NOT_INSTALLED,Hn.UNEXPECTED_ERROR,Hn.NOT_AVAILABLE_IN_LEGACY_MODE,Hn.REQUIRED_VALUE,Hn.INVALID_VALUE,Hn.CANNOT_SETUP_VUE_DEVTOOLS_PLUGIN,Hn.NOT_INSTALLED_WITH_PROVIDE,Hn.NOT_COMPATIBLE_LEGACY_VUE_I18N,Hn.BRIDGE_SUPPORT_VUE_2_ONLY,Hn.MUST_DEFINE_I18N_OPTION_IN_ALLOW_COMPOSITION,Hn.NOT_AVAILABLE_COMPOSITION_IN_LEGACY;const Xn=i("__translateVNode"),Kn=i("__datetimeParts"),qn=i("__numberParts"),zn=i("__setPluralRules");i("__intlifyMeta");const Yn=i("__injectWithOption"),Qn=i("__dispose");function Jn(e){if(!C(e))return e;if(Ie(e))return e;for(const t in e)if(E(e,t))if(t.includes(".")){const n=t.split("."),r=n.length-1;let o=e,i=!1;for(let e=0;e<r;e++){if("__proto__"===n[e])throw new Error(`unsafe key: ${n[e]}`);if(n[e]in o||(o[n[e]]=p()),!C(o[n[e]])){i=!0;break}o=o[n[e]]}if(i||(Ie(o)?qe.includes(n[r])||delete e[t]:(o[n[r]]=e[t],delete e[t])),!Ie(o)){const e=o[n[r]];C(e)&&Jn(e)}}else C(e[t])&&Jn(e[t]);return e}function Zn(e,t){const{messages:n,__i18n:r,messageResolver:o,flatJson:i}=t,s=I(n)?n:w(r)?p():{[e]:p()};if(w(r)&&r.forEach(e=>{if("locale"in e&&"resource"in e){const{locale:t,resource:n}=e;t?(s[t]=s[t]||p(),D(n,s[t])):D(n,s)}else T(e)&&D(JSON.parse(e),s)}),null==o&&i)for(const a in s)E(s,a)&&Jn(s[a]);return s}function er(e){return e.type}function tr(e,t,n){let r=C(t.messages)?t.messages:p();"__i18nGlobal"in n&&(r=Zn(e.locale.value,{messages:r,__i18n:n.__i18nGlobal}));const o=Object.keys(r);if(o.length&&o.forEach(t=>{e.mergeLocaleMessage(t,r[t])}),C(t.datetimeFormats)){const n=Object.keys(t.datetimeFormats);n.length&&n.forEach(n=>{e.mergeDateTimeFormat(n,t.datetimeFormats[n])})}if(C(t.numberFormats)){const n=Object.keys(t.numberFormats);n.length&&n.forEach(n=>{e.mergeNumberFormat(n,t.numberFormats[n])})}}function nr(e){return(0,Dn.bF)(Dn.EY,null,e,0)}const rr="__INTLIFY_META__",or=()=>[],ir=()=>!1;let sr=0;function ar(e){return(t,n,r,o)=>e(n,r,(0,Dn.nI)()||void 0,o)}const lr=()=>{const e=(0,Dn.nI)();let t=null;return e&&(t=er(e)[rr])?{[rr]:t}:null};function ur(e={},t){const{__root:n,__injectWithOption:r}=e,i=void 0===n,s=e.flatJson,a=o?Mn.KR:Mn.IJ,u=!!e.translateExistCompatible;let d=!k(e.inheritLocale)||e.inheritLocale;const h=a(n&&d?n.locale.value:T(e.locale)?e.locale:Ft),p=a(n&&d?n.fallbackLocale.value:T(e.fallbackLocale)||w(e.fallbackLocale)||I(e.fallbackLocale)||!1===e.fallbackLocale?e.fallbackLocale:h.value),m=a(Zn(h.value,e)),v=a(I(e.datetimeFormats)?e.datetimeFormats:{[h.value]:{}}),g=a(I(e.numberFormats)?e.numberFormats:{[h.value]:{}});let y=n?n.missingWarn:!k(e.missingWarn)&&!c(e.missingWarn)||e.missingWarn,b=n?n.fallbackWarn:!k(e.fallbackWarn)&&!c(e.fallbackWarn)||e.fallbackWarn,_=n?n.fallbackRoot:!k(e.fallbackRoot)||e.fallbackRoot,O=!!e.fallbackFormat,A=S(e.missing)?e.missing:null,R=S(e.missing)?ar(e.missing):null,N=S(e.postTranslation)?e.postTranslation:null,L=n?n.warnHtmlMessage:!k(e.warnHtmlMessage)||e.warnHtmlMessage,x=!!e.escapeParameter;const P=n?n.modifiers:I(e.modifiers)?e.modifiers:{};let M,F=e.pluralRules||n&&n.pluralRules;const $=()=>{i&&Qt(null);const t={version:Fn,locale:h.value,fallbackLocale:p.value,messages:m.value,modifiers:P,pluralRules:F,missing:null===R?void 0:R,missingWarn:y,fallbackWarn:b,fallbackFormat:O,unresolving:!0,postTranslation:null===N?void 0:N,warnHtmlMessage:L,escapeParameter:x,messageResolver:e.messageResolver,messageCompiler:e.messageCompiler,__meta:{framework:"vue"}};t.datetimeFormats=v.value,t.numberFormats=g.value,t.__datetimeFormatters=I(M)?M.__datetimeFormatters:void 0,t.__numberFormatters=I(M)?M.__numberFormatters:void 0;const n=en(t);return i&&Qt(n),n};function j(){return[h.value,p.value,m.value,v.value,g.value]}M=$(),rn(M,h.value,p.value);const U=(0,Dn.EW)({get:()=>h.value,set:e=>{h.value=e,M.locale=h.value}}),B=(0,Dn.EW)({get:()=>p.value,set:e=>{p.value=e,M.fallbackLocale=p.value,rn(M,h.value,e)}}),V=(0,Dn.EW)(()=>m.value),G=(0,Dn.EW)(()=>v.value),H=(0,Dn.EW)(()=>g.value);function W(){return S(N)?N:null}function X(e){N=e,M.postTranslation=e}function K(){return A}function q(e){null!==e&&(R=ar(e)),A=e,M.missing=R}const z=(e,t,r,o,s,a)=>{let u;j();try{__INTLIFY_PROD_DEVTOOLS__&&qt(lr()),i||(M.fallbackContext=n?Jt():void 0),u=e(M)}finally{__INTLIFY_PROD_DEVTOOLS__&&qt(null),i||(M.fallbackContext=void 0)}if("translate exists"!==r&&l(u)&&u===Mt||"translate exists"===r&&!u){const[e,r]=t();return n&&_?o(n):s(e)}if(a(u))return u;throw Wn(Hn.UNEXPECTED_RETURN_TYPE)};function Y(...e){return z(t=>Reflect.apply(yn,null,[t,...e]),()=>Sn(...e),"translate",t=>Reflect.apply(t.t,t,[...e]),e=>e,e=>T(e))}function Q(...e){const[t,n,r]=e;if(r&&!C(r))throw Wn(Hn.INVALID_ARGUMENT);return Y(t,n,f({resolvedMessage:!0},r||{}))}function J(...e){return z(t=>Reflect.apply(On,null,[t,...e]),()=>Rn(...e),"datetime format",t=>Reflect.apply(t.d,t,[...e]),()=>$t,e=>T(e))}function Z(...e){return z(t=>Reflect.apply(Nn,null,[t,...e]),()=>xn(...e),"number format",t=>Reflect.apply(t.n,t,[...e]),()=>$t,e=>T(e))}function ee(e){return e.map(e=>T(e)||l(e)||k(e)?nr(String(e)):e)}const te=e=>e,ne={normalize:ee,interpolate:te,type:"vnode"};function re(...e){return z(t=>{let n;const r=t;try{r.processor=ne,n=Reflect.apply(yn,null,[r,...e])}finally{r.processor=null}return n},()=>Sn(...e),"translate",t=>t[Xn](...e),e=>[nr(e)],e=>w(e))}function oe(...e){return z(t=>Reflect.apply(Nn,null,[t,...e]),()=>xn(...e),"number format",t=>t[qn](...e),or,e=>T(e)||w(e))}function ie(...e){return z(t=>Reflect.apply(On,null,[t,...e]),()=>Rn(...e),"datetime format",t=>t[Kn](...e),or,e=>T(e)||w(e))}function se(e){F=e,M.pluralRules=F}function ae(e,t){return z(()=>{if(!e)return!1;const n=T(t)?t:h.value,r=ce(n),o=M.messageResolver(r,e);return u?null!=o:Ie(o)||gn(o)||T(o)},()=>[e],"translate exists",n=>Reflect.apply(n.te,n,[e,t]),ir,e=>k(e))}function le(e){let t=null;const n=Nt(M,p.value,h.value);for(let r=0;r<n.length;r++){const o=m.value[n[r]]||{},i=M.messageResolver(o,e);if(null!=i){t=i;break}}return t}function ue(e){const t=le(e);return null!=t?t:n&&n.tm(e)||{}}function ce(e){return m.value[e]||{}}function de(e,t){if(s){const n={[e]:t};for(const e in n)E(n,e)&&Jn(n[e]);t=n[e]}m.value[e]=t,M.messages=m.value}function fe(e,t){m.value[e]=m.value[e]||{};const n={[e]:t};if(s)for(const r in n)E(n,r)&&Jn(n[r]);t=n[e],D(t,m.value[e]),M.messages=m.value}function he(e){return v.value[e]||{}}function pe(e,t){v.value[e]=t,M.datetimeFormats=v.value,In(M,e,t)}function me(e,t){v.value[e]=f(v.value[e]||{},t),M.datetimeFormats=v.value,In(M,e,t)}function ve(e){return g.value[e]||{}}function ge(e,t){g.value[e]=t,M.numberFormats=g.value,Pn(M,e,t)}function ye(e,t){g.value[e]=f(g.value[e]||{},t),M.numberFormats=g.value,Pn(M,e,t)}sr++,n&&o&&((0,Dn.wB)(n.locale,e=>{d&&(h.value=e,M.locale=e,rn(M,h.value,p.value))}),(0,Dn.wB)(n.fallbackLocale,e=>{d&&(p.value=e,M.fallbackLocale=e,rn(M,h.value,p.value))}));const be={id:sr,locale:U,fallbackLocale:B,get inheritLocale(){return d},set inheritLocale(e){d=e,e&&n&&(h.value=n.locale.value,p.value=n.fallbackLocale.value,rn(M,h.value,p.value))},get availableLocales(){return Object.keys(m.value).sort()},messages:V,get modifiers(){return P},get pluralRules(){return F||{}},get isGlobal(){return i},get missingWarn(){return y},set missingWarn(e){y=e,M.missingWarn=y},get fallbackWarn(){return b},set fallbackWarn(e){b=e,M.fallbackWarn=b},get fallbackRoot(){return _},set fallbackRoot(e){_=e},get fallbackFormat(){return O},set fallbackFormat(e){O=e,M.fallbackFormat=O},get warnHtmlMessage(){return L},set warnHtmlMessage(e){L=e,M.warnHtmlMessage=e},get escapeParameter(){return x},set escapeParameter(e){x=e,M.escapeParameter=e},t:Y,getLocaleMessage:ce,setLocaleMessage:de,mergeLocaleMessage:fe,getPostTranslationHandler:W,setPostTranslationHandler:X,getMissingHandler:K,setMissingHandler:q,[zn]:se};return be.datetimeFormats=G,be.numberFormats=H,be.rt=Q,be.te=ae,be.tm=ue,be.d=J,be.n=Z,be.getDateTimeFormat=he,be.setDateTimeFormat=pe,be.mergeDateTimeFormat=me,be.getNumberFormat=ve,be.setNumberFormat=ge,be.mergeNumberFormat=ye,be[Yn]=r,be[Xn]=re,be[Kn]=ie,be[qn]=oe,be}function cr(e){const t=T(e.locale)?e.locale:Ft,n=T(e.fallbackLocale)||w(e.fallbackLocale)||I(e.fallbackLocale)||!1===e.fallbackLocale?e.fallbackLocale:t,r=S(e.missing)?e.missing:void 0,o=!k(e.silentTranslationWarn)&&!c(e.silentTranslationWarn)||!e.silentTranslationWarn,i=!k(e.silentFallbackWarn)&&!c(e.silentFallbackWarn)||!e.silentFallbackWarn,s=!k(e.fallbackRoot)||e.fallbackRoot,a=!!e.formatFallbackMessages,l=I(e.modifiers)?e.modifiers:{},u=e.pluralizationRules,d=S(e.postTranslation)?e.postTranslation:void 0,h=!T(e.warnHtmlInMessage)||"off"!==e.warnHtmlInMessage,p=!!e.escapeParameterHtml,m=!k(e.sync)||e.sync;let v=e.messages;if(I(e.sharedMessages)){const t=e.sharedMessages,n=Object.keys(t);v=n.reduce((e,n)=>{const r=e[n]||(e[n]={});return f(r,t[n]),e},v||{})}const{__i18n:g,__root:y,__injectWithOption:b}=e,_=e.datetimeFormats,E=e.numberFormats,C=e.flatJson,O=e.translateExistCompatible;return{locale:t,fallbackLocale:n,messages:v,flatJson:C,datetimeFormats:_,numberFormats:E,missing:r,missingWarn:o,fallbackWarn:i,fallbackRoot:s,fallbackFormat:a,modifiers:l,pluralRules:u,postTranslation:d,warnHtmlMessage:h,escapeParameter:p,messageResolver:e.messageResolver,inheritLocale:m,translateExistCompatible:O,__i18n:g,__root:y,__injectWithOption:b}}function dr(e={},t){{const t=ur(cr(e)),{__extender:n}=e,r={id:t.id,get locale(){return t.locale.value},set locale(e){t.locale.value=e},get fallbackLocale(){return t.fallbackLocale.value},set fallbackLocale(e){t.fallbackLocale.value=e},get messages(){return t.messages.value},get datetimeFormats(){return t.datetimeFormats.value},get numberFormats(){return t.numberFormats.value},get availableLocales(){return t.availableLocales},get formatter(){return{interpolate(){return[]}}},set formatter(e){},get missing(){return t.getMissingHandler()},set missing(e){t.setMissingHandler(e)},get silentTranslationWarn(){return k(t.missingWarn)?!t.missingWarn:t.missingWarn},set silentTranslationWarn(e){t.missingWarn=k(e)?!e:e},get silentFallbackWarn(){return k(t.fallbackWarn)?!t.fallbackWarn:t.fallbackWarn},set silentFallbackWarn(e){t.fallbackWarn=k(e)?!e:e},get modifiers(){return t.modifiers},get formatFallbackMessages(){return t.fallbackFormat},set formatFallbackMessages(e){t.fallbackFormat=e},get postTranslation(){return t.getPostTranslationHandler()},set postTranslation(e){t.setPostTranslationHandler(e)},get sync(){return t.inheritLocale},set sync(e){t.inheritLocale=e},get warnHtmlInMessage(){return t.warnHtmlMessage?"warn":"off"},set warnHtmlInMessage(e){t.warnHtmlMessage="off"!==e},get escapeParameterHtml(){return t.escapeParameter},set escapeParameterHtml(e){t.escapeParameter=e},get preserveDirectiveContent(){return!0},set preserveDirectiveContent(e){},get pluralizationRules(){return t.pluralRules||{}},__composer:t,t(...e){const[n,r,o]=e,i={};let s=null,a=null;if(!T(n))throw Wn(Hn.INVALID_ARGUMENT);const l=n;return T(r)?i.locale=r:w(r)?s=r:I(r)&&(a=r),w(o)?s=o:I(o)&&(a=o),Reflect.apply(t.t,t,[l,s||a||{},i])},rt(...e){return Reflect.apply(t.rt,t,[...e])},tc(...e){const[n,r,o]=e,i={plural:1};let s=null,a=null;if(!T(n))throw Wn(Hn.INVALID_ARGUMENT);const u=n;return T(r)?i.locale=r:l(r)?i.plural=r:w(r)?s=r:I(r)&&(a=r),T(o)?i.locale=o:w(o)?s=o:I(o)&&(a=o),Reflect.apply(t.t,t,[u,s||a||{},i])},te(e,n){return t.te(e,n)},tm(e){return t.tm(e)},getLocaleMessage(e){return t.getLocaleMessage(e)},setLocaleMessage(e,n){t.setLocaleMessage(e,n)},mergeLocaleMessage(e,n){t.mergeLocaleMessage(e,n)},d(...e){return Reflect.apply(t.d,t,[...e])},getDateTimeFormat(e){return t.getDateTimeFormat(e)},setDateTimeFormat(e,n){t.setDateTimeFormat(e,n)},mergeDateTimeFormat(e,n){t.mergeDateTimeFormat(e,n)},n(...e){return Reflect.apply(t.n,t,[...e])},getNumberFormat(e){return t.getNumberFormat(e)},setNumberFormat(e,n){t.setNumberFormat(e,n)},mergeNumberFormat(e,n){t.mergeNumberFormat(e,n)},getChoiceIndex(e,t){return-1}};return r.__extender=n,r}}const fr={tag:{type:[String,Object]},locale:{type:String},scope:{type:String,validator:e=>"parent"===e||"global"===e,default:"parent"},i18n:{type:Object}};function hr({slots:e},t){if(1===t.length&&"default"===t[0]){const t=e.default?e.default():[];return t.reduce((e,t)=>[...e,...t.type===Dn.FK?t.children:[t]],[])}return t.reduce((t,n)=>{const r=e[n];return r&&(t[n]=r()),t},p())}function pr(e){return Dn.FK}const mr=(0,Dn.pM)({name:"i18n-t",props:f({keypath:{type:String,required:!0},plural:{type:[Number,String],validator:e=>l(e)||!isNaN(e)}},fr),setup(e,t){const{slots:n,attrs:r}=t,o=e.i18n||Lr({useScope:e.scope,__useComponent:!0});return()=>{const i=Object.keys(n).filter(e=>"_"!==e),s=p();e.locale&&(s.locale=e.locale),void 0!==e.plural&&(s.plural=T(e.plural)?+e.plural:e.plural);const a=hr(t,i),l=o[Xn](e.keypath,a,s),u=f(p(),r),c=T(e.tag)||C(e.tag)?e.tag:pr();return(0,Dn.h)(c,u,l)}}}),vr=mr;function gr(e){return w(e)&&!T(e[0])}function yr(e,t,n,r){const{slots:o,attrs:i}=t;return()=>{const t={part:!0};let s=p();e.locale&&(t.locale=e.locale),T(e.format)?t.key=e.format:C(e.format)&&(T(e.format.key)&&(t.key=e.format.key),s=Object.keys(e.format).reduce((t,r)=>n.includes(r)?f(p(),t,{[r]:e.format[r]}):t,p()));const a=r(e.value,t,s);let l=[t.key];w(a)?l=a.map((e,t)=>{const n=o[e.type],r=n?n({[e.type]:e.value,index:t,parts:a}):[e.value];return gr(r)&&(r[0].key=`${e.type}-${t}`),r}):T(a)&&(l=[a]);const u=f(p(),i),c=T(e.tag)||C(e.tag)?e.tag:pr();return(0,Dn.h)(c,u,l)}}const br=(0,Dn.pM)({name:"i18n-n",props:f({value:{type:Number,required:!0},format:{type:[String,Object]}},fr),setup(e,t){const n=e.i18n||Lr({useScope:e.scope,__useComponent:!0});return yr(e,t,Ln,(...e)=>n[qn](...e))}}),_r=br,Er=(0,Dn.pM)({name:"i18n-d",props:f({value:{type:[Number,Date],required:!0},format:{type:[String,Object]}},fr),setup(e,t){const n=e.i18n||Lr({useScope:e.scope,__useComponent:!0});return yr(e,t,An,(...e)=>n[Kn](...e))}}),wr=Er;function Sr(e,t){const n=e;if("composition"===e.mode)return n.__getInstance(t)||e.global;{const r=n.__getInstance(t);return null!=r?r.__composer:e.global.__composer}}function Tr(e){const t=t=>{const{instance:n,modifiers:r,value:o}=t;if(!n||!n.$)throw Wn(Hn.UNEXPECTED_ERROR);const i=Sr(e,n.$);const s=kr(o);return[Reflect.apply(i.t,i,[...Cr(s)]),i]},n=(n,r)=>{const[i,s]=t(r);o&&e.global===s&&(n.__i18nWatcher=(0,Dn.wB)(s.locale,()=>{r.instance&&r.instance.$forceUpdate()})),n.__composer=s,n.textContent=i},r=e=>{o&&e.__i18nWatcher&&(e.__i18nWatcher(),e.__i18nWatcher=void 0,delete e.__i18nWatcher),e.__composer&&(e.__composer=void 0,delete e.__composer)},i=(e,{value:t})=>{if(e.__composer){const n=e.__composer,r=kr(t);e.textContent=Reflect.apply(n.t,n,[...Cr(r)])}},s=e=>{const[n]=t(e);return{textContent:n}};return{created:n,unmounted:r,beforeUpdate:i,getSSRProps:s}}function kr(e){if(T(e))return{path:e};if(I(e)){if(!("path"in e))throw Wn(Hn.REQUIRED_VALUE,"path");return e}throw Wn(Hn.INVALID_VALUE)}function Cr(e){const{path:t,locale:n,args:r,choice:o,plural:i}=e,s={},a=r||{};return T(n)&&(s.locale=n),l(o)&&(s.plural=o),l(i)&&(s.plural=i),[t,a,s]}function Or(e,t,...n){const r=I(n[0])?n[0]:{},o=!!r.useI18nComponentName,i=!k(r.globalInstall)||r.globalInstall;i&&([o?"i18n":vr.name,"I18nT"].forEach(t=>e.component(t,vr)),[_r.name,"I18nN"].forEach(t=>e.component(t,_r)),[wr.name,"I18nD"].forEach(t=>e.component(t,wr))),e.directive("t",Tr(t))}function Ar(e,t,n){return{beforeCreate(){const r=(0,Dn.nI)();if(!r)throw Wn(Hn.UNEXPECTED_ERROR);const o=this.$options;if(o.i18n){const r=o.i18n;if(o.__i18n&&(r.__i18n=o.__i18n),r.__root=t,this===this.$root)this.$i18n=Rr(e,r);else{r.__injectWithOption=!0,r.__extender=n.__vueI18nExtend,this.$i18n=dr(r);const e=this.$i18n;e.__extender&&(e.__disposer=e.__extender(this.$i18n))}}else if(o.__i18n)if(this===this.$root)this.$i18n=Rr(e,o);else{this.$i18n=dr({__i18n:o.__i18n,__injectWithOption:!0,__extender:n.__vueI18nExtend,__root:t});const e=this.$i18n;e.__extender&&(e.__disposer=e.__extender(this.$i18n))}else this.$i18n=e;o.__i18nGlobal&&tr(t,o,o),this.$t=(...e)=>this.$i18n.t(...e),this.$rt=(...e)=>this.$i18n.rt(...e),this.$tc=(...e)=>this.$i18n.tc(...e),this.$te=(e,t)=>this.$i18n.te(e,t),this.$d=(...e)=>this.$i18n.d(...e),this.$n=(...e)=>this.$i18n.n(...e),this.$tm=e=>this.$i18n.tm(e),n.__setInstance(r,this.$i18n)},mounted(){0},unmounted(){const e=(0,Dn.nI)();if(!e)throw Wn(Hn.UNEXPECTED_ERROR);const t=this.$i18n;delete this.$t,delete this.$rt,delete this.$tc,delete this.$te,delete this.$d,delete this.$n,delete this.$tm,t.__disposer&&(t.__disposer(),delete t.__disposer,delete t.__extender),n.__deleteInstance(e),delete this.$i18n}}}function Rr(e,t){e.locale=t.locale||e.locale,e.fallbackLocale=t.fallbackLocale||e.fallbackLocale,e.missing=t.missing||e.missing,e.silentTranslationWarn=t.silentTranslationWarn||e.silentFallbackWarn,e.silentFallbackWarn=t.silentFallbackWarn||e.silentFallbackWarn,e.formatFallbackMessages=t.formatFallbackMessages||e.formatFallbackMessages,e.postTranslation=t.postTranslation||e.postTranslation,e.warnHtmlInMessage=t.warnHtmlInMessage||e.warnHtmlInMessage,e.escapeParameterHtml=t.escapeParameterHtml||e.escapeParameterHtml,e.sync=t.sync||e.sync,e.__composer[zn](t.pluralizationRules||e.pluralizationRules);const n=Zn(e.locale,{messages:t.messages,__i18n:t.__i18n});return Object.keys(n).forEach(t=>e.mergeLocaleMessage(t,n[t])),t.datetimeFormats&&Object.keys(t.datetimeFormats).forEach(n=>e.mergeDateTimeFormat(n,t.datetimeFormats[n])),t.numberFormats&&Object.keys(t.numberFormats).forEach(n=>e.mergeNumberFormat(n,t.numberFormats[n])),e}const Ir=i("global-vue-i18n");function Nr(e={},t){const n=__VUE_I18N_LEGACY_API__&&k(e.legacy)?e.legacy:__VUE_I18N_LEGACY_API__,r=!k(e.globalInjection)||e.globalInjection,o=!__VUE_I18N_LEGACY_API__||!n||!!e.allowComposition,s=new Map,[a,l]=xr(e,n),u=i("");function c(e){return s.get(e)||null}function d(e,t){s.set(e,t)}function f(e){s.delete(e)}{const e={get mode(){return __VUE_I18N_LEGACY_API__&&n?"legacy":"composition"},get allowComposition(){return o},async install(t,...o){if(t.__VUE_I18N_SYMBOL__=u,t.provide(t.__VUE_I18N_SYMBOL__,e),I(o[0])){const t=o[0];e.__composerExtend=t.__composerExtend,e.__vueI18nExtend=t.__vueI18nExtend}let i=null;!n&&r&&(i=Gr(t,e.global)),__VUE_I18N_FULL_INSTALL__&&Or(t,e,...o),__VUE_I18N_LEGACY_API__&&n&&t.mixin(Ar(l,l.__composer,e));const s=t.unmount;t.unmount=()=>{i&&i(),e.dispose(),s()}},get global(){return l},dispose(){a.stop()},__instances:s,__getInstance:c,__setInstance:d,__deleteInstance:f};return e}}function Lr(e={}){const t=(0,Dn.nI)();if(null==t)throw Wn(Hn.MUST_BE_CALL_SETUP_TOP);if(!t.isCE&&null!=t.appContext.app&&!t.appContext.app.__VUE_I18N_SYMBOL__)throw Wn(Hn.NOT_INSTALLED);const n=Pr(t),r=Mr(n),o=er(t),i=Dr(e,o);if(__VUE_I18N_LEGACY_API__&&"legacy"===n.mode&&!e.__useComponent){if(!n.allowComposition)throw Wn(Hn.NOT_AVAILABLE_IN_LEGACY_MODE);return Ur(t,i,r,e)}if("global"===i)return tr(r,e,o),r;if("parent"===i){let o=Fr(n,t,e.__useComponent);return null==o&&(o=r),o}const s=n;let a=s.__getInstance(t);if(null==a){const n=f({},e);"__i18n"in o&&(n.__i18n=o.__i18n),r&&(n.__root=r),a=ur(n),s.__composerExtend&&(a[Qn]=s.__composerExtend(a)),jr(s,t,a),s.__setInstance(t,a)}return a}function xr(e,t,n){const r=(0,Mn.uY)();{const n=__VUE_I18N_LEGACY_API__&&t?r.run(()=>dr(e)):r.run(()=>ur(e));if(null==n)throw Wn(Hn.UNEXPECTED_ERROR);return[r,n]}}function Pr(e){{const t=(0,Dn.WQ)(e.isCE?Ir:e.appContext.app.__VUE_I18N_SYMBOL__);if(!t)throw Wn(e.isCE?Hn.NOT_INSTALLED_WITH_PROVIDE:Hn.UNEXPECTED_ERROR);return t}}function Dr(e,t){return d(e)?"__i18n"in t?"local":"global":e.useScope?e.useScope:"local"}function Mr(e){return"composition"===e.mode?e.global:e.global.__composer}function Fr(e,t,n=!1){let r=null;const o=t.root;let i=$r(t,n);while(null!=i){const t=e;if("composition"===e.mode)r=t.__getInstance(i);else if(__VUE_I18N_LEGACY_API__){const e=t.__getInstance(i);null!=e&&(r=e.__composer,n&&r&&!r[Yn]&&(r=null))}if(null!=r)break;if(o===i)break;i=i.parent}return r}function $r(e,t=!1){return null==e?null:t&&e.vnode.ctx||e.parent}function jr(e,t,n){(0,Dn.sV)(()=>{0},t),(0,Dn.hi)(()=>{const r=n;e.__deleteInstance(t);const o=r[Qn];o&&(o(),delete r[Qn])},t)}function Ur(e,t,n,r={}){const o="local"===t,i=(0,Mn.IJ)(null);if(o&&e.proxy&&!e.proxy.$options.i18n&&!e.proxy.$options.__i18n)throw Wn(Hn.MUST_DEFINE_I18N_OPTION_IN_ALLOW_COMPOSITION);const s=k(r.inheritLocale)?r.inheritLocale:!T(r.locale),a=(0,Mn.KR)(!o||s?n.locale.value:T(r.locale)?r.locale:Ft),l=(0,Mn.KR)(!o||s?n.fallbackLocale.value:T(r.fallbackLocale)||w(r.fallbackLocale)||I(r.fallbackLocale)||!1===r.fallbackLocale?r.fallbackLocale:a.value),u=(0,Mn.KR)(Zn(a.value,r)),d=(0,Mn.KR)(I(r.datetimeFormats)?r.datetimeFormats:{[a.value]:{}}),f=(0,Mn.KR)(I(r.numberFormats)?r.numberFormats:{[a.value]:{}}),h=o?n.missingWarn:!k(r.missingWarn)&&!c(r.missingWarn)||r.missingWarn,p=o?n.fallbackWarn:!k(r.fallbackWarn)&&!c(r.fallbackWarn)||r.fallbackWarn,m=o?n.fallbackRoot:!k(r.fallbackRoot)||r.fallbackRoot,v=!!r.fallbackFormat,g=S(r.missing)?r.missing:null,y=S(r.postTranslation)?r.postTranslation:null,b=o?n.warnHtmlMessage:!k(r.warnHtmlMessage)||r.warnHtmlMessage,_=!!r.escapeParameter,E=o?n.modifiers:I(r.modifiers)?r.modifiers:{},C=r.pluralRules||o&&n.pluralRules;function O(){return[a.value,l.value,u.value,d.value,f.value]}const A=(0,Dn.EW)({get:()=>i.value?i.value.locale.value:a.value,set:e=>{i.value&&(i.value.locale.value=e),a.value=e}}),R=(0,Dn.EW)({get:()=>i.value?i.value.fallbackLocale.value:l.value,set:e=>{i.value&&(i.value.fallbackLocale.value=e),l.value=e}}),N=(0,Dn.EW)(()=>i.value?i.value.messages.value:u.value),L=(0,Dn.EW)(()=>d.value),x=(0,Dn.EW)(()=>f.value);function P(){return i.value?i.value.getPostTranslationHandler():y}function D(e){i.value&&i.value.setPostTranslationHandler(e)}function M(){return i.value?i.value.getMissingHandler():g}function F(e){i.value&&i.value.setMissingHandler(e)}function $(e){return O(),e()}function j(...e){return i.value?$(()=>Reflect.apply(i.value.t,null,[...e])):$(()=>"")}function U(...e){return i.value?Reflect.apply(i.value.rt,null,[...e]):""}function B(...e){return i.value?$(()=>Reflect.apply(i.value.d,null,[...e])):$(()=>"")}function V(...e){return i.value?$(()=>Reflect.apply(i.value.n,null,[...e])):$(()=>"")}function G(e){return i.value?i.value.tm(e):{}}function H(e,t){return!!i.value&&i.value.te(e,t)}function W(e){return i.value?i.value.getLocaleMessage(e):{}}function X(e,t){i.value&&(i.value.setLocaleMessage(e,t),u.value[e]=t)}function K(e,t){i.value&&i.value.mergeLocaleMessage(e,t)}function q(e){return i.value?i.value.getDateTimeFormat(e):{}}function z(e,t){i.value&&(i.value.setDateTimeFormat(e,t),d.value[e]=t)}function Y(e,t){i.value&&i.value.mergeDateTimeFormat(e,t)}function Q(e){return i.value?i.value.getNumberFormat(e):{}}function J(e,t){i.value&&(i.value.setNumberFormat(e,t),f.value[e]=t)}function Z(e,t){i.value&&i.value.mergeNumberFormat(e,t)}const ee={get id(){return i.value?i.value.id:-1},locale:A,fallbackLocale:R,messages:N,datetimeFormats:L,numberFormats:x,get inheritLocale(){return i.value?i.value.inheritLocale:s},set inheritLocale(e){i.value&&(i.value.inheritLocale=e)},get availableLocales(){return i.value?i.value.availableLocales:Object.keys(u.value)},get modifiers(){return i.value?i.value.modifiers:E},get pluralRules(){return i.value?i.value.pluralRules:C},get isGlobal(){return!!i.value&&i.value.isGlobal},get missingWarn(){return i.value?i.value.missingWarn:h},set missingWarn(e){i.value&&(i.value.missingWarn=e)},get fallbackWarn(){return i.value?i.value.fallbackWarn:p},set fallbackWarn(e){i.value&&(i.value.missingWarn=e)},get fallbackRoot(){return i.value?i.value.fallbackRoot:m},set fallbackRoot(e){i.value&&(i.value.fallbackRoot=e)},get fallbackFormat(){return i.value?i.value.fallbackFormat:v},set fallbackFormat(e){i.value&&(i.value.fallbackFormat=e)},get warnHtmlMessage(){return i.value?i.value.warnHtmlMessage:b},set warnHtmlMessage(e){i.value&&(i.value.warnHtmlMessage=e)},get escapeParameter(){return i.value?i.value.escapeParameter:_},set escapeParameter(e){i.value&&(i.value.escapeParameter=e)},t:j,getPostTranslationHandler:P,setPostTranslationHandler:D,getMissingHandler:M,setMissingHandler:F,rt:U,d:B,n:V,tm:G,te:H,getLocaleMessage:W,setLocaleMessage:X,mergeLocaleMessage:K,getDateTimeFormat:q,setDateTimeFormat:z,mergeDateTimeFormat:Y,getNumberFormat:Q,setNumberFormat:J,mergeNumberFormat:Z};function te(e){e.locale.value=a.value,e.fallbackLocale.value=l.value,Object.keys(u.value).forEach(t=>{e.mergeLocaleMessage(t,u.value[t])}),Object.keys(d.value).forEach(t=>{e.mergeDateTimeFormat(t,d.value[t])}),Object.keys(f.value).forEach(t=>{e.mergeNumberFormat(t,f.value[t])}),e.escapeParameter=_,e.fallbackFormat=v,e.fallbackRoot=m,e.fallbackWarn=p,e.missingWarn=h,e.warnHtmlMessage=b}return(0,Dn.KC)(()=>{if(null==e.proxy||null==e.proxy.$i18n)throw Wn(Hn.NOT_AVAILABLE_COMPOSITION_IN_LEGACY);const n=i.value=e.proxy.$i18n.__composer;"global"===t?(a.value=n.locale.value,l.value=n.fallbackLocale.value,u.value=n.messages.value,d.value=n.datetimeFormats.value,f.value=n.numberFormats.value):o&&te(n)}),ee}const Br=["locale","fallbackLocale","availableLocales"],Vr=["t","rt","d","n","tm","te"];function Gr(e,t){const n=Object.create(null);Br.forEach(e=>{const r=Object.getOwnPropertyDescriptor(t,e);if(!r)throw Wn(Hn.UNEXPECTED_ERROR);const o=(0,Mn.i9)(r.value)?{get(){return r.value.value},set(e){r.value.value=e}}:{get(){return r.get&&r.get()}};Object.defineProperty(n,e,o)}),e.config.globalProperties.$i18n=n,Vr.forEach(n=>{const r=Object.getOwnPropertyDescriptor(t,n);if(!r||!r.value)throw Wn(Hn.UNEXPECTED_ERROR);Object.defineProperty(e.config.globalProperties,`$${n}`,r)});const r=()=>{delete e.config.globalProperties.$i18n,Vr.forEach(t=>{delete e.config.globalProperties[`$${t}`]})};return r}if($n(),__INTLIFY_JIT_COMPILATION__?Ht(mn):Ht(pn),Wt(it),Xt(Nt),__INTLIFY_PROD_DEVTOOLS__){const e=v();e.__INTLIFY__=!0,vt(e.__INTLIFY_DEVTOOLS_GLOBAL_HOOK__)}},1029:function(e,t,n){"use strict";n.d(t,{aE:function(){return ft},Bt:function(){return Ie}});
/*!
 * vue-router v4.6.4
 * (c) 2025 Eduardo San Martin Morote
 * @license MIT
 */
const r="undefined"!==typeof document;function o(e){return"object"===typeof e||"displayName"in e||"props"in e||"__vccOpts"in e}function i(e){return e.__esModule||"Module"===e[Symbol.toStringTag]||e.default&&o(e.default)}const s=Object.assign;function a(e,t){const n={};for(const r in t){const o=t[r];n[r]=u(o)?o.map(e):e(o)}return n}const l=()=>{},u=Array.isArray;function c(e,t){const n={};for(const r in e)n[r]=r in t?t[r]:e[r];return n}const d=/#/g,f=/&/g,h=/\//g,p=/=/g,m=/\?/g,v=/\+/g,g=/%5B/g,y=/%5D/g,b=/%5E/g,_=/%60/g,E=/%7B/g,w=/%7C/g,S=/%7D/g,T=/%20/g;function k(e){return null==e?"":encodeURI(""+e).replace(w,"|").replace(g,"[").replace(y,"]")}function C(e){return k(e).replace(E,"{").replace(S,"}").replace(b,"^")}function O(e){return k(e).replace(v,"%2B").replace(T,"+").replace(d,"%23").replace(f,"%26").replace(_,"`").replace(E,"{").replace(S,"}").replace(b,"^")}function A(e){return O(e).replace(p,"%3D")}function R(e){return k(e).replace(d,"%23").replace(m,"%3F")}function I(e){return R(e).replace(h,"%2F")}function N(e){if(null==e)return null;try{return decodeURIComponent(""+e)}catch(t){}return""+e}const L=/\/$/,x=e=>e.replace(L,"");function P(e,t,n="/"){let r,o={},i="",s="";const a=t.indexOf("#");let l=t.indexOf("?");return l=a>=0&&l>a?-1:l,l>=0&&(r=t.slice(0,l),i=t.slice(l,a>0?a:t.length),o=e(i.slice(1))),a>=0&&(r=r||t.slice(0,a),s=t.slice(a,t.length)),r=V(null!=r?r:t,n),{fullPath:r+i+s,path:r,query:o,hash:N(s)}}function D(e,t){const n=t.query?e(t.query):"";return t.path+(n&&"?")+n+(t.hash||"")}function M(e,t){return t&&e.toLowerCase().startsWith(t.toLowerCase())?e.slice(t.length)||"/":e}function F(e,t,n){const r=t.matched.length-1,o=n.matched.length-1;return r>-1&&r===o&&$(t.matched[r],n.matched[o])&&j(t.params,n.params)&&e(t.query)===e(n.query)&&t.hash===n.hash}function $(e,t){return(e.aliasOf||e)===(t.aliasOf||t)}function j(e,t){if(Object.keys(e).length!==Object.keys(t).length)return!1;for(var n in e)if(!U(e[n],t[n]))return!1;return!0}function U(e,t){return u(e)?B(e,t):u(t)?B(t,e):e?.valueOf()===t?.valueOf()}function B(e,t){return u(t)?e.length===t.length&&e.every((e,n)=>e===t[n]):1===e.length&&e[0]===t}function V(e,t){if(e.startsWith("/"))return e;if(!e)return t;const n=t.split("/"),r=e.split("/"),o=r[r.length-1];".."!==o&&"."!==o||r.push("");let i,s,a=n.length-1;for(i=0;i<r.length;i++)if(s=r[i],"."!==s){if(".."!==s)break;a>1&&a--}return n.slice(0,a).join("/")+"/"+r.slice(i).join("/")}const G={path:"/",name:void 0,params:{},query:{},hash:"",fullPath:"/",matched:[],meta:{},redirectedFrom:void 0};let H=function(e){return e["pop"]="pop",e["push"]="push",e}({}),W=function(e){return e["back"]="back",e["forward"]="forward",e["unknown"]="",e}({});function X(e){if(!e)if(r){const t=document.querySelector("base");e=t&&t.getAttribute("href")||"/",e=e.replace(/^\w+:\/\/[^\/]+/,"")}else e="/";return"/"!==e[0]&&"#"!==e[0]&&(e="/"+e),x(e)}const K=/^[^#]+#/;function q(e,t){return e.replace(K,"#")+t}function z(e,t){const n=document.documentElement.getBoundingClientRect(),r=e.getBoundingClientRect();return{behavior:t.behavior,left:r.left-n.left-(t.left||0),top:r.top-n.top-(t.top||0)}}const Y=()=>({left:window.scrollX,top:window.scrollY});function Q(e){let t;if("el"in e){const n=e.el,r="string"===typeof n&&n.startsWith("#");0;const o="string"===typeof n?r?document.getElementById(n.slice(1)):document.querySelector(n):n;if(!o)return;t=z(o,e)}else t=e;"scrollBehavior"in document.documentElement.style?window.scrollTo(t):window.scrollTo(null!=t.left?t.left:window.scrollX,null!=t.top?t.top:window.scrollY)}function J(e,t){return(history.state?history.state.position-t:-1)+e}const Z=new Map;function ee(e,t){Z.set(e,t)}function te(e){const t=Z.get(e);return Z.delete(e),t}function ne(e){return"string"===typeof e||e&&"object"===typeof e}function re(e){return"string"===typeof e||"symbol"===typeof e}let oe=function(e){return e[e["MATCHER_NOT_FOUND"]=1]="MATCHER_NOT_FOUND",e[e["NAVIGATION_GUARD_REDIRECT"]=2]="NAVIGATION_GUARD_REDIRECT",e[e["NAVIGATION_ABORTED"]=4]="NAVIGATION_ABORTED",e[e["NAVIGATION_CANCELLED"]=8]="NAVIGATION_CANCELLED",e[e["NAVIGATION_DUPLICATED"]=16]="NAVIGATION_DUPLICATED",e}({});const ie=Symbol("");oe.MATCHER_NOT_FOUND,oe.NAVIGATION_GUARD_REDIRECT,oe.NAVIGATION_ABORTED,oe.NAVIGATION_CANCELLED,oe.NAVIGATION_DUPLICATED;function se(e,t){return s(new Error,{type:e,[ie]:!0},t)}function ae(e,t){return e instanceof Error&&ie in e&&(null==t||!!(e.type&t))}const le=["params","query","hash"];function ue(e){if("string"===typeof e)return e;if(null!=e.path)return e.path;const t={};for(const n of le)n in e&&(t[n]=e[n]);return JSON.stringify(t,null,2)}function ce(e){const t={};if(""===e||"?"===e)return t;const n=("?"===e[0]?e.slice(1):e).split("&");for(let r=0;r<n.length;++r){const e=n[r].replace(v," "),o=e.indexOf("="),i=N(o<0?e:e.slice(0,o)),s=o<0?null:N(e.slice(o+1));if(i in t){let e=t[i];u(e)||(e=t[i]=[e]),e.push(s)}else t[i]=s}return t}function de(e){let t="";for(let n in e){const r=e[n];n=A(n),null!=r?(u(r)?r.map(e=>e&&O(e)):[r&&O(r)]).forEach(e=>{void 0!==e&&(t+=(t.length?"&":"")+n,null!=e&&(t+="="+e))}):void 0!==r&&(t+=(t.length?"&":"")+n)}return t}function fe(e){const t={};for(const n in e){const r=e[n];void 0!==r&&(t[n]=u(r)?r.map(e=>null==e?null:""+e):null==r?r:""+r)}return t}const he=Symbol(""),pe=Symbol(""),me=Symbol(""),ve=Symbol(""),ge=Symbol("");function ye(){let e=[];function t(t){return e.push(t),()=>{const n=e.indexOf(t);n>-1&&e.splice(n,1)}}function n(){e=[]}return{add:t,list:()=>e.slice(),reset:n}}function be(e,t,n,r,o,i=e=>e()){const s=r&&(r.enterCallbacks[o]=r.enterCallbacks[o]||[]);return()=>new Promise((a,l)=>{const u=e=>{!1===e?l(se(oe.NAVIGATION_ABORTED,{from:n,to:t})):e instanceof Error?l(e):ne(e)?l(se(oe.NAVIGATION_GUARD_REDIRECT,{from:t,to:e})):(s&&r.enterCallbacks[o]===s&&"function"===typeof e&&s.push(e),a())},c=i(()=>e.call(r&&r.instances[o],t,n,u));let d=Promise.resolve(c);e.length<3&&(d=d.then(u)),d.catch(e=>l(e))})}function _e(e,t,n,r,s=e=>e()){const a=[];for(const l of e){0;for(const e in l.components){let u=l.components[e];if("beforeRouteEnter"===t||l.instances[e])if(o(u)){const o=(u.__vccOpts||u)[t];o&&a.push(be(o,n,r,l,e,s))}else{let o=u();0,a.push(()=>o.then(o=>{if(!o)throw new Error(`Couldn't resolve component "${e}" at "${l.path}"`);const a=i(o)?o.default:o;l.mods[e]=o,l.components[e]=a;const u=(a.__vccOpts||a)[t];return u&&be(u,n,r,l,e,s)()}))}}}return a}function Ee(e,t){const n=[],r=[],o=[],i=Math.max(t.matched.length,e.matched.length);for(let s=0;s<i;s++){const i=t.matched[s];i&&(e.matched.find(e=>$(e,i))?r.push(i):n.push(i));const a=e.matched[s];a&&(t.matched.find(e=>$(e,a))||o.push(a))}return[n,r,o]}var we=n(641),Se=n(953);
/*!
 * vue-router v4.6.4
 * (c) 2025 Eduardo San Martin Morote
 * @license MIT
 */
let Te=()=>location.protocol+"//"+location.host;function ke(e,t){const{pathname:n,search:r,hash:o}=t,i=e.indexOf("#");if(i>-1){let t=o.includes(e.slice(i))?e.slice(i).length:1,n=o.slice(t);return"/"!==n[0]&&(n="/"+n),M(n,"")}return M(n,e)+r+o}function Ce(e,t,n,r){let o=[],i=[],a=null;const l=({state:i})=>{const s=ke(e,location),l=n.value,u=t.value;let c=0;if(i){if(n.value=s,t.value=i,a&&a===l)return void(a=null);c=u?i.position-u.position:0}else r(s);o.forEach(e=>{e(n.value,l,{delta:c,type:H.pop,direction:c?c>0?W.forward:W.back:W.unknown})})};function u(){a=n.value}function c(e){o.push(e);const t=()=>{const t=o.indexOf(e);t>-1&&o.splice(t,1)};return i.push(t),t}function d(){if("hidden"===document.visibilityState){const{history:e}=window;if(!e.state)return;e.replaceState(s({},e.state,{scroll:Y()}),"")}}function f(){for(const e of i)e();i=[],window.removeEventListener("popstate",l),window.removeEventListener("pagehide",d),document.removeEventListener("visibilitychange",d)}return window.addEventListener("popstate",l),window.addEventListener("pagehide",d),document.addEventListener("visibilitychange",d),{pauseListeners:u,listen:c,destroy:f}}function Oe(e,t,n,r=!1,o=!1){return{back:e,current:t,forward:n,replaced:r,position:window.history.length,scroll:o?Y():null}}function Ae(e){const{history:t,location:n}=window,r={value:ke(e,n)},o={value:t.state};function i(r,i,s){const a=e.indexOf("#"),l=a>-1?(n.host&&document.querySelector("base")?e:e.slice(a))+r:Te()+e+r;try{t[s?"replaceState":"pushState"](i,"",l),o.value=i}catch(u){console.error(u),n[s?"replace":"assign"](l)}}function a(e,n){i(e,s({},t.state,Oe(o.value.back,e,o.value.forward,!0),n,{position:o.value.position}),!0),r.value=e}function l(e,n){const a=s({},o.value,t.state,{forward:e,scroll:Y()});i(a.current,a,!0),i(e,s({},Oe(r.value,e,null),{position:a.position+1},n),!1),r.value=e}return o.value||i(r.value,{back:null,current:r.value,forward:null,position:t.length-1,replaced:!0,scroll:null},!0),{location:r,state:o,push:l,replace:a}}function Re(e){e=X(e);const t=Ae(e),n=Ce(e,t.state,t.location,t.replace);function r(e,t=!0){t||n.pauseListeners(),history.go(e)}const o=s({location:"",base:e,go:r,createHref:q.bind(null,e)},t,n);return Object.defineProperty(o,"location",{enumerable:!0,get:()=>t.location.value}),Object.defineProperty(o,"state",{enumerable:!0,get:()=>t.state.value}),o}function Ie(e){return e=location.host?e||location.pathname+location.search:"",e.includes("#")||(e+="#"),Re(e)}let Ne=function(e){return e[e["Static"]=0]="Static",e[e["Param"]=1]="Param",e[e["Group"]=2]="Group",e}({});var Le=function(e){return e[e["Static"]=0]="Static",e[e["Param"]=1]="Param",e[e["ParamRegExp"]=2]="ParamRegExp",e[e["ParamRegExpEnd"]=3]="ParamRegExpEnd",e[e["EscapeNext"]=4]="EscapeNext",e}(Le||{});const xe={type:Ne.Static,value:""},Pe=/[a-zA-Z0-9_]/;function De(e){if(!e)return[[]];if("/"===e)return[[xe]];if(!e.startsWith("/"))throw new Error(`Invalid path "${e}"`);function t(e){throw new Error(`ERR (${n})/"${u}": ${e}`)}let n=Le.Static,r=n;const o=[];let i;function s(){i&&o.push(i),i=[]}let a,l=0,u="",c="";function d(){u&&(n===Le.Static?i.push({type:Ne.Static,value:u}):n===Le.Param||n===Le.ParamRegExp||n===Le.ParamRegExpEnd?(i.length>1&&("*"===a||"+"===a)&&t(`A repeatable param (${u}) must be alone in its segment. eg: '/:ids+.`),i.push({type:Ne.Param,value:u,regexp:c,repeatable:"*"===a||"+"===a,optional:"*"===a||"?"===a})):t("Invalid state to consume buffer"),u="")}function f(){u+=a}while(l<e.length)if(a=e[l++],"\\"!==a||n===Le.ParamRegExp)switch(n){case Le.Static:"/"===a?(u&&d(),s()):":"===a?(d(),n=Le.Param):f();break;case Le.EscapeNext:f(),n=r;break;case Le.Param:"("===a?n=Le.ParamRegExp:Pe.test(a)?f():(d(),n=Le.Static,"*"!==a&&"?"!==a&&"+"!==a&&l--);break;case Le.ParamRegExp:")"===a?"\\"==c[c.length-1]?c=c.slice(0,-1)+a:n=Le.ParamRegExpEnd:c+=a;break;case Le.ParamRegExpEnd:d(),n=Le.Static,"*"!==a&&"?"!==a&&"+"!==a&&l--,c="";break;default:t("Unknown state");break}else r=n,n=Le.EscapeNext;return n===Le.ParamRegExp&&t(`Unfinished custom RegExp for param "${u}"`),d(),s(),o}const Me="[^/]+?",Fe={sensitive:!1,strict:!1,start:!0,end:!0};var $e=function(e){return e[e["_multiplier"]=10]="_multiplier",e[e["Root"]=90]="Root",e[e["Segment"]=40]="Segment",e[e["SubSegment"]=30]="SubSegment",e[e["Static"]=40]="Static",e[e["Dynamic"]=20]="Dynamic",e[e["BonusCustomRegExp"]=10]="BonusCustomRegExp",e[e["BonusWildcard"]=-50]="BonusWildcard",e[e["BonusRepeatable"]=-20]="BonusRepeatable",e[e["BonusOptional"]=-8]="BonusOptional",e[e["BonusStrict"]=.7000000000000001]="BonusStrict",e[e["BonusCaseSensitive"]=.25]="BonusCaseSensitive",e}($e||{});const je=/[.+*?^${}()[\]/\\]/g;function Ue(e,t){const n=s({},Fe,t),r=[];let o=n.start?"^":"";const i=[];for(const s of e){const e=s.length?[]:[$e.Root];n.strict&&!s.length&&(o+="/");for(let t=0;t<s.length;t++){const r=s[t];let a=$e.Segment+(n.sensitive?$e.BonusCaseSensitive:0);if(r.type===Ne.Static)t||(o+="/"),o+=r.value.replace(je,"\\$&"),a+=$e.Static;else if(r.type===Ne.Param){const{value:e,repeatable:n,optional:l,regexp:u}=r;i.push({name:e,repeatable:n,optional:l});const c=u||Me;c!==Me&&(a+=$e.BonusCustomRegExp);let d=n?`((?:${c})(?:/(?:${c}))*)`:`(${c})`;t||(d=l&&s.length<2?`(?:/${d})`:"/"+d),l&&(d+="?"),o+=d,a+=$e.Dynamic,l&&(a+=$e.BonusOptional),n&&(a+=$e.BonusRepeatable),".*"===c&&(a+=$e.BonusWildcard)}e.push(a)}r.push(e)}if(n.strict&&n.end){const e=r.length-1;r[e][r[e].length-1]+=$e.BonusStrict}n.strict||(o+="/?"),n.end?o+="$":n.strict&&!o.endsWith("/")&&(o+="(?:/|$)");const a=new RegExp(o,n.sensitive?"":"i");function l(e){const t=e.match(a),n={};if(!t)return null;for(let r=1;r<t.length;r++){const e=t[r]||"",o=i[r-1];n[o.name]=e&&o.repeatable?e.split("/"):e}return n}function c(t){let n="",r=!1;for(const o of e){r&&n.endsWith("/")||(n+="/"),r=!1;for(const e of o)if(e.type===Ne.Static)n+=e.value;else if(e.type===Ne.Param){const{value:i,repeatable:s,optional:a}=e,l=i in t?t[i]:"";if(u(l)&&!s)throw new Error(`Provided param "${i}" is an array but it is not repeatable (* or + modifiers)`);const c=u(l)?l.join("/"):l;if(!c){if(!a)throw new Error(`Missing required param "${i}"`);o.length<2&&(n.endsWith("/")?n=n.slice(0,-1):r=!0)}n+=c}}return n||"/"}return{re:a,score:r,keys:i,parse:l,stringify:c}}function Be(e,t){let n=0;while(n<e.length&&n<t.length){const r=t[n]-e[n];if(r)return r;n++}return e.length<t.length?1===e.length&&e[0]===$e.Static+$e.Segment?-1:1:e.length>t.length?1===t.length&&t[0]===$e.Static+$e.Segment?1:-1:0}function Ve(e,t){let n=0;const r=e.score,o=t.score;while(n<r.length&&n<o.length){const e=Be(r[n],o[n]);if(e)return e;n++}if(1===Math.abs(o.length-r.length)){if(Ge(r))return 1;if(Ge(o))return-1}return o.length-r.length}function Ge(e){const t=e[e.length-1];return e.length>0&&t[t.length-1]<0}const He={strict:!1,end:!0,sensitive:!1};function We(e,t,n){const r=Ue(De(e.path),n);const o=s(r,{record:e,parent:t,children:[],alias:[]});return t&&!o.record.aliasOf===!t.record.aliasOf&&t.children.push(o),o}function Xe(e,t){const n=[],r=new Map;function o(e){return r.get(e)}function i(e,n,r){const o=!r,u=qe(e);u.aliasOf=r&&r.record;const f=c(t,e),h=[u];if("alias"in e){const t="string"===typeof e.alias?[e.alias]:e.alias;for(const e of t)h.push(qe(s({},u,{components:r?r.record.components:u.components,path:e,aliasOf:r?r.record:u})))}let p,m;for(const t of h){const{path:s}=t;if(n&&"/"!==s[0]){const e=n.record.path,r="/"===e[e.length-1]?"":"/";t.path=n.record.path+(s&&r+s)}if(p=We(t,n,f),r?r.alias.push(p):(m=m||p,m!==p&&m.alias.push(p),o&&e.name&&!Ye(p)&&a(e.name)),et(p)&&d(p),u.children){const e=u.children;for(let t=0;t<e.length;t++)i(e[t],p,r&&r.children[t])}r=r||p}return m?()=>{a(m)}:l}function a(e){if(re(e)){const t=r.get(e);t&&(r.delete(e),n.splice(n.indexOf(t),1),t.children.forEach(a),t.alias.forEach(a))}else{const t=n.indexOf(e);t>-1&&(n.splice(t,1),e.record.name&&r.delete(e.record.name),e.children.forEach(a),e.alias.forEach(a))}}function u(){return n}function d(e){const t=Je(e,n);n.splice(t,0,e),e.record.name&&!Ye(e)&&r.set(e.record.name,e)}function f(e,t){let o,i,a,l={};if("name"in e&&e.name){if(o=r.get(e.name),!o)throw se(oe.MATCHER_NOT_FOUND,{location:e});0,a=o.record.name,l=s(Ke(t.params,o.keys.filter(e=>!e.optional).concat(o.parent?o.parent.keys.filter(e=>e.optional):[]).map(e=>e.name)),e.params&&Ke(e.params,o.keys.map(e=>e.name))),i=o.stringify(l)}else if(null!=e.path)i=e.path,o=n.find(e=>e.re.test(i)),o&&(l=o.parse(i),a=o.record.name);else{if(o=t.name?r.get(t.name):n.find(e=>e.re.test(t.path)),!o)throw se(oe.MATCHER_NOT_FOUND,{location:e,currentLocation:t});a=o.record.name,l=s({},t.params,e.params),i=o.stringify(l)}const u=[];let c=o;while(c)u.unshift(c.record),c=c.parent;return{name:a,path:i,params:l,matched:u,meta:Qe(u)}}function h(){n.length=0,r.clear()}return t=c(He,t),e.forEach(e=>i(e)),{addRoute:i,resolve:f,removeRoute:a,clearRoutes:h,getRoutes:u,getRecordMatcher:o}}function Ke(e,t){const n={};for(const r of t)r in e&&(n[r]=e[r]);return n}function qe(e){const t={path:e.path,redirect:e.redirect,name:e.name,meta:e.meta||{},aliasOf:e.aliasOf,beforeEnter:e.beforeEnter,props:ze(e),children:e.children||[],instances:{},leaveGuards:new Set,updateGuards:new Set,enterCallbacks:{},components:"components"in e?e.components||null:e.component&&{default:e.component}};return Object.defineProperty(t,"mods",{value:{}}),t}function ze(e){const t={},n=e.props||!1;if("component"in e)t.default=n;else for(const r in e.components)t[r]="object"===typeof n?n[r]:n;return t}function Ye(e){while(e){if(e.record.aliasOf)return!0;e=e.parent}return!1}function Qe(e){return e.reduce((e,t)=>s(e,t.meta),{})}function Je(e,t){let n=0,r=t.length;while(n!==r){const o=n+r>>1;Ve(e,t[o])<0?r=o:n=o+1}const o=Ze(e);return o&&(r=t.lastIndexOf(o,r-1)),r}function Ze(e){let t=e;while(t=t.parent)if(et(t)&&0===Ve(e,t))return t}function et({record:e}){return!!(e.name||e.components&&Object.keys(e.components).length||e.redirect)}function tt(e){const t=(0,we.WQ)(me),n=(0,we.WQ)(ve);const r=(0,we.EW)(()=>{const n=(0,Se.R1)(e.to);return t.resolve(n)}),o=(0,we.EW)(()=>{const{matched:e}=r.value,{length:t}=e,o=e[t-1],i=n.matched;if(!o||!i.length)return-1;const s=i.findIndex($.bind(null,o));if(s>-1)return s;const a=at(e[t-2]);return t>1&&at(o)===a&&i[i.length-1].path!==a?i.findIndex($.bind(null,e[t-2])):s}),i=(0,we.EW)(()=>o.value>-1&&st(n.params,r.value.params)),s=(0,we.EW)(()=>o.value>-1&&o.value===n.matched.length-1&&j(n.params,r.value.params));function a(n={}){if(it(n)){const n=t[(0,Se.R1)(e.replace)?"replace":"push"]((0,Se.R1)(e.to)).catch(l);return e.viewTransition&&"undefined"!==typeof document&&"startViewTransition"in document&&document.startViewTransition(()=>n),n}return Promise.resolve()}return{route:r,href:(0,we.EW)(()=>r.value.href),isActive:i,isExactActive:s,navigate:a}}function nt(e){return 1===e.length?e[0]:e}const rt=(0,we.pM)({name:"RouterLink",compatConfig:{MODE:3},props:{to:{type:[String,Object],required:!0},replace:Boolean,activeClass:String,exactActiveClass:String,custom:Boolean,ariaCurrentValue:{type:String,default:"page"},viewTransition:Boolean},useLink:tt,setup(e,{slots:t}){const n=(0,Se.Kh)(tt(e)),{options:r}=(0,we.WQ)(me),o=(0,we.EW)(()=>({[lt(e.activeClass,r.linkActiveClass,"router-link-active")]:n.isActive,[lt(e.exactActiveClass,r.linkExactActiveClass,"router-link-exact-active")]:n.isExactActive}));return()=>{const r=t.default&&nt(t.default(n));return e.custom?r:(0,we.h)("a",{"aria-current":n.isExactActive?e.ariaCurrentValue:null,href:n.href,onClick:n.navigate,class:o.value},r)}}}),ot=rt;function it(e){if(!(e.metaKey||e.altKey||e.ctrlKey||e.shiftKey)&&!e.defaultPrevented&&(void 0===e.button||0===e.button)){if(e.currentTarget&&e.currentTarget.getAttribute){const t=e.currentTarget.getAttribute("target");if(/\b_blank\b/i.test(t))return}return e.preventDefault&&e.preventDefault(),!0}}function st(e,t){for(const n in t){const r=t[n],o=e[n];if("string"===typeof r){if(r!==o)return!1}else if(!u(o)||o.length!==r.length||r.some((e,t)=>e.valueOf()!==o[t].valueOf()))return!1}return!0}function at(e){return e?e.aliasOf?e.aliasOf.path:e.path:""}const lt=(e,t,n)=>null!=e?e:null!=t?t:n,ut=(0,we.pM)({name:"RouterView",inheritAttrs:!1,props:{name:{type:String,default:"default"},route:Object},compatConfig:{MODE:3},setup(e,{attrs:t,slots:n}){const r=(0,we.WQ)(ge),o=(0,we.EW)(()=>e.route||r.value),i=(0,we.WQ)(pe,0),a=(0,we.EW)(()=>{let e=(0,Se.R1)(i);const{matched:t}=o.value;let n;while((n=t[e])&&!n.components)e++;return e}),l=(0,we.EW)(()=>o.value.matched[a.value]);(0,we.Gt)(pe,(0,we.EW)(()=>a.value+1)),(0,we.Gt)(he,l),(0,we.Gt)(ge,o);const u=(0,Se.KR)();return(0,we.wB)(()=>[u.value,l.value,e.name],([e,t,n],[r,o,i])=>{t&&(t.instances[n]=e,o&&o!==t&&e&&e===r&&(t.leaveGuards.size||(t.leaveGuards=o.leaveGuards),t.updateGuards.size||(t.updateGuards=o.updateGuards))),!e||!t||o&&$(t,o)&&r||(t.enterCallbacks[n]||[]).forEach(t=>t(e))},{flush:"post"}),()=>{const r=o.value,i=e.name,a=l.value,c=a&&a.components[i];if(!c)return ct(n.default,{Component:c,route:r});const d=a.props[i],f=d?!0===d?r.params:"function"===typeof d?d(r):d:null,h=e=>{e.component.isUnmounted&&(a.instances[i]=null)},p=(0,we.h)(c,s({},f,t,{onVnodeUnmounted:h,ref:u}));return ct(n.default,{Component:p,route:r})||p}}});function ct(e,t){if(!e)return null;const n=e(t);return 1===n.length?n[0]:n}const dt=ut;function ft(e){const t=Xe(e.routes,e),n=e.parseQuery||ce,o=e.stringifyQuery||de,i=e.history;const c=ye(),d=ye(),f=ye(),h=(0,Se.IJ)(G);let p=G;r&&e.scrollBehavior&&"scrollRestoration"in history&&(history.scrollRestoration="manual");const m=a.bind(null,e=>""+e),v=a.bind(null,I),g=a.bind(null,N);function y(e,n){let r,o;return re(e)?(r=t.getRecordMatcher(e),o=n):o=e,t.addRoute(o,r)}function b(e){const n=t.getRecordMatcher(e);n&&t.removeRoute(n)}function _(){return t.getRoutes().map(e=>e.record)}function E(e){return!!t.getRecordMatcher(e)}function w(e,r){if(r=s({},r||h.value),"string"===typeof e){const o=P(n,e,r.path),a=t.resolve({path:o.path},r),l=i.createHref(o.fullPath);return s(o,a,{params:g(a.params),hash:N(o.hash),redirectedFrom:void 0,href:l})}let a;if(null!=e.path)a=s({},e,{path:P(n,e.path,r.path).path});else{const t=s({},e.params);for(const e in t)null==t[e]&&delete t[e];a=s({},e,{params:v(t)}),r.params=v(r.params)}const l=t.resolve(a,r),u=e.hash||"";l.params=m(g(l.params));const c=D(o,s({},e,{hash:C(u),path:l.path})),d=i.createHref(c);return s({fullPath:c,hash:u,query:o===de?fe(e.query):e.query||{}},l,{redirectedFrom:void 0,href:d})}function S(e){return"string"===typeof e?P(n,e,h.value.path):s({},e)}function T(e,t){if(p!==e)return se(oe.NAVIGATION_CANCELLED,{from:t,to:e})}function k(e){return R(e)}function O(e){return k(s(S(e),{replace:!0}))}function A(e,t){const n=e.matched[e.matched.length-1];if(n&&n.redirect){const{redirect:r}=n;let o="function"===typeof r?r(e,t):r;return"string"===typeof o&&(o=o.includes("?")||o.includes("#")?o=S(o):{path:o},o.params={}),s({query:e.query,hash:e.hash,params:null!=o.path?{}:e.params},o)}}function R(e,t){const n=p=w(e),r=h.value,i=e.state,a=e.force,l=!0===e.replace,u=A(n,r);if(u)return R(s(S(u),{state:"object"===typeof u?s({},i,u.state):i,force:a,replace:l}),t||n);const c=n;let d;return c.redirectedFrom=t,!a&&F(o,r,n)&&(d=se(oe.NAVIGATION_DUPLICATED,{to:c,from:r}),Z(r,r,!0,!1)),(d?Promise.resolve(d):M(c,r)).catch(e=>ae(e)?ae(e,oe.NAVIGATION_GUARD_REDIRECT)?e:z(e):K(e,c,r)).then(e=>{if(e){if(ae(e,oe.NAVIGATION_GUARD_REDIRECT))return R(s({replace:l},S(e.to),{state:"object"===typeof e.to?s({},i,e.to.state):i,force:a}),t||c)}else e=j(c,r,!0,l,i);return $(c,r,e),e})}function L(e,t){const n=T(e,t);return n?Promise.reject(n):Promise.resolve()}function x(e){const t=le.values().next().value;return t&&"function"===typeof t.runWithContext?t.runWithContext(e):e()}function M(e,t){let n;const[r,o,i]=Ee(e,t);n=_e(r.reverse(),"beforeRouteLeave",e,t);for(const a of r)a.leaveGuards.forEach(r=>{n.push(be(r,e,t))});const s=L.bind(null,e,t);return n.push(s),he(n).then(()=>{n=[];for(const r of c.list())n.push(be(r,e,t));return n.push(s),he(n)}).then(()=>{n=_e(o,"beforeRouteUpdate",e,t);for(const r of o)r.updateGuards.forEach(r=>{n.push(be(r,e,t))});return n.push(s),he(n)}).then(()=>{n=[];for(const r of i)if(r.beforeEnter)if(u(r.beforeEnter))for(const o of r.beforeEnter)n.push(be(o,e,t));else n.push(be(r.beforeEnter,e,t));return n.push(s),he(n)}).then(()=>(e.matched.forEach(e=>e.enterCallbacks={}),n=_e(i,"beforeRouteEnter",e,t,x),n.push(s),he(n))).then(()=>{n=[];for(const r of d.list())n.push(be(r,e,t));return n.push(s),he(n)}).catch(e=>ae(e,oe.NAVIGATION_CANCELLED)?e:Promise.reject(e))}function $(e,t,n){f.list().forEach(r=>x(()=>r(e,t,n)))}function j(e,t,n,o,a){const l=T(e,t);if(l)return l;const u=t===G,c=r?history.state:{};n&&(o||u?i.replace(e.fullPath,s({scroll:u&&c&&c.scroll},a)):i.push(e.fullPath,a)),h.value=e,Z(e,t,n,u),z()}let U;function B(){U||(U=i.listen((e,t,n)=>{if(!ue.listening)return;const o=w(e),a=A(o,ue.currentRoute.value);if(a)return void R(s(a,{replace:!0,force:!0}),o).catch(l);p=o;const u=h.value;r&&ee(J(u.fullPath,n.delta),Y()),M(o,u).catch(e=>ae(e,oe.NAVIGATION_ABORTED|oe.NAVIGATION_CANCELLED)?e:ae(e,oe.NAVIGATION_GUARD_REDIRECT)?(R(s(S(e.to),{force:!0}),o).then(e=>{ae(e,oe.NAVIGATION_ABORTED|oe.NAVIGATION_DUPLICATED)&&!n.delta&&n.type===H.pop&&i.go(-1,!1)}).catch(l),Promise.reject()):(n.delta&&i.go(-n.delta,!1),K(e,o,u))).then(e=>{e=e||j(o,u,!1),e&&(n.delta&&!ae(e,oe.NAVIGATION_CANCELLED)?i.go(-n.delta,!1):n.type===H.pop&&ae(e,oe.NAVIGATION_ABORTED|oe.NAVIGATION_DUPLICATED)&&i.go(-1,!1)),$(o,u,e)}).catch(l)}))}let V,W=ye(),X=ye();function K(e,t,n){z(e);const r=X.list();return r.length?r.forEach(r=>r(e,t,n)):console.error(e),Promise.reject(e)}function q(){return V&&h.value!==G?Promise.resolve():new Promise((e,t)=>{W.add([e,t])})}function z(e){return V||(V=!e,B(),W.list().forEach(([t,n])=>e?n(e):t()),W.reset()),e}function Z(t,n,o,i){const{scrollBehavior:s}=e;if(!r||!s)return Promise.resolve();const a=!o&&te(J(t.fullPath,0))||(i||!o)&&history.state&&history.state.scroll||null;return(0,we.dY)().then(()=>s(t,n,a)).then(e=>e&&Q(e)).catch(e=>K(e,t,n))}const ne=e=>i.go(e);let ie;const le=new Set,ue={currentRoute:h,listening:!0,addRoute:y,removeRoute:b,clearRoutes:t.clearRoutes,hasRoute:E,getRoutes:_,resolve:w,options:e,push:k,replace:O,go:ne,back:()=>ne(-1),forward:()=>ne(1),beforeEach:c.add,beforeResolve:d.add,afterEach:f.add,onError:X.add,isReady:q,install(e){e.component("RouterLink",ot),e.component("RouterView",dt),e.config.globalProperties.$router=ue,Object.defineProperty(e.config.globalProperties,"$route",{enumerable:!0,get:()=>(0,Se.R1)(h)}),r&&!ie&&h.value===G&&(ie=!0,k(i.location).catch(e=>{0}));const t={};for(const r in G)Object.defineProperty(t,r,{get:()=>h.value[r],enumerable:!0});e.provide(me,ue),e.provide(ve,(0,Se.Gc)(t)),e.provide(ge,h);const n=e.unmount;le.add(e),e.unmount=function(){le.delete(e),le.size<1&&(p=G,U&&U(),U=null,h.value=G,ie=!1,V=!1),n()}}};function he(e){return e.reduce((e,t)=>e.then(()=>x(t)),Promise.resolve())}return ue}}}]);"use strict";(self["webpackChunkcontao_manager"]=self["webpackChunkcontao_manager"]||[]).push([[414],{414:function(e,o,i){i.r(o),i.d(o,{default:function(){return C}});var t=i(641),s=i(3751),l=i(33),n=i(6894);const a={key:0,class:"view-login__locked"},g={key:0,class:"view-login__form"},r={class:"view-login__headline"},d={class:"view-login__description"},u={class:"view-login__or"},p=["href"],c={key:1,class:"view-login__form"},_={class:"view-login__headline"},h={class:"view-login__description"};function m(e,o,i,m,k,w){const b=(0,t.g2)("i18n-t"),v=(0,t.g2)("text-field"),f=(0,t.g2)("loading-button"),y=(0,t.g2)("boxed-layout");return(0,t.uX)(),(0,t.Wv)(y,{slotClass:"view-login"},{default:(0,t.k6)(()=>[o[7]||(o[7]=(0,t.Lk)("header",{class:"view-login__header"},[(0,t.Lk)("img",{src:n,width:"80",height:"80",alt:"Contao Logo"}),(0,t.Lk)("p",{class:"view-login__product"},"Contao Manager")],-1)),e.locked?((0,t.uX)(),(0,t.CE)("main",a,[(0,t.bF)(b,{tag:"p",keypath:"ui.login.locked"},{lockFile:(0,t.k6)(()=>[...o[6]||(o[6]=[(0,t.Lk)("strong",null,"contao-manager/login.lock",-1),(0,t.Lk)("br",null,null,-1)])]),_:1})])):((0,t.uX)(),(0,t.Wv)(s.eB,{key:1,name:"animate-flip",type:"transition",mode:"out-in"},{default:(0,t.k6)(()=>[e.requires_totp?((0,t.uX)(),(0,t.CE)("main",c,[(0,t.Lk)("form",{onSubmit:o[5]||(o[5]=(0,s.D$)((...e)=>w.login&&w.login(...e),["prevent"]))},[(0,t.Lk)("h1",_,(0,l.v_)(e.$t("ui.login.totpHeadline")),1),(0,t.Lk)("p",h,(0,l.v_)(e.$t("ui.login.totpDescription")),1),(0,t.bF)(v,{name:"totp",required:"",minlength:"6",maxlength:"6",autocomplete:"one-time-code",label:e.$t("ui.login.totp"),placeholder:e.$t("ui.login.totp"),class:(0,l.C4)(["view-login__totp",e.login_failed?"widget--error":""]),disabled:e.logging_in,modelValue:e.totp,"onUpdate:modelValue":o[3]||(o[3]=o=>e.totp=o),onInput:w.reset},null,8,["label","placeholder","class","disabled","modelValue","onInput"]),(0,t.bF)(f,{submit:"",class:"view-login__button",color:"primary",disabled:!w.totpValid||e.login_failed,loading:e.logging_in},{default:(0,t.k6)(()=>[(0,t.eW)((0,l.v_)(e.$t("ui.login.button")),1)]),_:1},8,["disabled","loading"]),(0,t.Lk)("button",{class:"widget-button view-login__button",onClick:o[4]||(o[4]=(...e)=>w.cancelTotp&&w.cancelTotp(...e))},(0,l.v_)(e.$t("ui.login.cancel")),1)],32)])):((0,t.uX)(),(0,t.CE)("main",g,[(0,t.Lk)("form",{onSubmit:o[2]||(o[2]=(0,s.D$)((...e)=>w.login&&w.login(...e),["prevent"]))},[(0,t.Lk)("h1",r,(0,l.v_)(e.$t("ui.login.headline")),1),(0,t.Lk)("p",d,(0,l.v_)(e.$t("ui.login.description")),1),(0,t.bF)(v,{ref:"username",name:"username",autocomplete:"username webauthn",label:e.$t("ui.login.username"),placeholder:e.$t("ui.login.username"),class:(0,l.C4)(["view-login__user",e.login_failed?"widget--error":""]),disabled:e.logging_in||e.passkey_login,modelValue:e.username,"onUpdate:modelValue":o[0]||(o[0]=o=>e.username=o),onInput:w.reset},null,8,["label","placeholder","class","disabled","modelValue","onInput"]),(0,t.bF)(v,{type:"password",name:"password",autocomplete:"current-password",label:e.$t("ui.login.password"),placeholder:e.$t("ui.login.password"),minlength:"8",class:(0,l.C4)(["view-login__password",e.login_failed?"widget--error":""]),disabled:e.logging_in||e.passkey_login,modelValue:e.password,"onUpdate:modelValue":o[1]||(o[1]=o=>e.password=o),onInput:w.reset},null,8,["label","placeholder","class","disabled","modelValue","onInput"]),(0,t.bF)(f,{submit:"",class:"view-login__button",color:"primary",disabled:!w.inputValid||e.login_failed||e.passkey_login,loading:e.logging_in&&!e.passkey_login},{default:(0,t.k6)(()=>[(0,t.eW)((0,l.v_)(e.$t("ui.login.button")),1)]),_:1},8,["disabled","loading"]),(0,t.Lk)("p",u,(0,l.v_)(e.$t("ui.login.or")),1),e.showPasskey?((0,t.uX)(),(0,t.Wv)(f,{key:0,class:"view-login__button",icon:"passkey",color:"primary",loading:e.passkey_login,disabled:e.logging_in,onClick:(0,s.D$)(w.passkeyLogin,["prevent"])},{default:(0,t.k6)(()=>[(0,t.eW)((0,l.v_)(e.$t("ui.login.passkey")),1)]),_:1},8,["loading","disabled","onClick"])):(0,t.Q3)("",!0),(0,t.Lk)("a",{href:`https://to.contao.org/docs/manager-password?lang=${e.$i18n.locale}`,target:"_blank",class:"view-login__link"},(0,l.v_)(e.$t("ui.login.forgotPassword")),9,p)],32)]))]),_:1}))]),_:1})}i(3110);var k=i(6278),w=i(60),b=i(707),v=i(728),f=i(9757),y=i(5506),$={components:{BoxedLayout:v.A,TextField:f.A,LoadingButton:y.A},data:()=>({username:"",password:"",totp:"",logging_in:!1,passkey_login:!1,requires_totp:!1,login_failed:!1,showPasskey:!1}),computed:{...(0,k.aH)(["locked"]),inputValid(){return""!==this.username&&""!==this.password&&this.password.length>=8},totpValid(){return""!==this.totp&&/^\d{6}$/.test(this.totp)}},methods:{async login(){this.inputValid&&this.doLogin({username:this.username,password:this.password,totp:this.totp})},async passkeyLogin({useBrowserAutofill:e}){this.passkey_login=!e;const o=(await this.$request.get("api/session/options")).data;try{const i=await(0,w.HS)({optionsJSON:o,useBrowserAutofill:!!e});await this.doLogin({passkey:JSON.stringify(i)})}catch(i){}this.passkey_login=!1},async doLogin(e){this.logging_in=!0;const o=await this.$store.dispatch("auth/login",e);201===o.status?this.$store.commit("setView",b.A.BOOT):401===o.status&&o.data.totp_enabled?(this.logging_in=!1,this.requires_totp=!0,this.login_failed=!!this.totp):(this.logging_in=!1,this.login_failed=!0)},reset(){this.login_failed=!1},cancelTotp(){this.username="",this.password="",this.totp="",this.logging_in=!1,this.requires_totp=!1,this.login_failed=!1}},async mounted(){this.$store.commit("setError",null),this.locked||(this.$refs.username&&this.$refs.username.focus(),"https:"===location.protocol?this.showPasskey=(0,w.zZ)():this.showPasskey=!1)}},L=i(6262);const V=(0,L.A)($,[["render",m]]);var C=V}}]);"use strict";(self["webpackChunkcontao_manager"]=self["webpackChunkcontao_manager"]||[]).push([[557],{1557:function(a){a.exports=JSON.parse('{"ui.app.title":"Расширения Contao","ui.app.loading":"Загрузка списка расширений...","ui.app.language":"Переключить язык Contao Manager","ui.app.colorDark":"Темный режим","ui.app.colorDarkTitle":"Переключить цветовую схему на темную","ui.app.colorLight":"Светлый режим","ui.app.colorLightTitle":"Переключить цветовую схему на светлую","ui.discover.advertisement":"Реклама в списке расширений","ui.discover.loading":"Загрузка...","ui.discover.offline":"Не удалось получить результаты.","ui.discover.offlineExplain":"Проверьте подключение к сети Интернет и отключите блокировку JavaScript в своем браузере.","ui.discover.offlineButton":"Попробовать еще раз","ui.discover.searchPlaceholder":"Поиск в {count} расширениях...","ui.discover.empty":"Нет результатов для {query}","ui.discover.more":"Другие результаты","ui.discover.sortBy":"Сортировать по","ui.discover.sortReleased":"Выпуск","ui.discover.sortReleasedTitle":"Сортировать результаты по дате выпуска","ui.discover.sortLatest":"Обновлено","ui.discover.sortLatestTitle":"Сортировать результаты по последнему обновлению","ui.discover.sortDownloads":"Загрузки","ui.discover.sortDownloadsTitle":"Сортировать результаты по количеству загрузок","ui.discover.sortFavers":"Рейтинг","ui.discover.sortFaversTitle":"Сортировать результаты по рейтингу","ui.discover.detailsButton":"Сведения","ui.discover.latestPackages":"Последние и обновленные расширения","ui.discover.faversPackages":"Расширения с высоким рейтингом","ui.discover.downloadsPackages":"Самые загружаемые расширения","ui.discover.exactHit":"Точное соответствие запросу","ui.discover.results":"Больше результатов поиска","ui.package.homepage":"Веб-сайт проекта","ui.package.private":"Частный пакет","ui.package.privateTitle":"Частные пакеты доступны только у поставщика (наприм., в виде загрузки ZIP-файла). Посетите веб-сайт для получения дополнительной информации.","ui.package.abandoned":"Заброшенный","ui.package.abandonedText":"Этот пакет отмечен как заброшенный и больше не поддерживается.","ui.package.abandonedReplace":"Этот пакет имеет статус заброшенного и больше не поддерживается. Автор предлагает вместо него использовать пакет {replacement}.","ui.package.contaoVersion":"Доступно для Contao","ui.package-details.previous":"Детали предыдущего расширения","ui.package-details.close":"Закрыть детали расширения","ui.package-details.loading":"Загрузка...","ui.package-details.tabDescription":"Описание","ui.package-details.tabRequire":"Требования","ui.package-details.tabFeatures":"Особенности","ui.package-details.tabSuggest":"Предложения","ui.package-details.tabConflict":"Конфликты","ui.package-details.tabDependents":"Зависимые","ui.package-details.linkRequires":"требует","ui.package-details.linkReplaces":"заменяет","ui.package-details.linkProvides":"обеспечивает","ui.package-details.linkConflicts":"конфликты","ui.package-details.funding":"Финансировать дальнейшее развитие!","ui.package-details.contaoVersions":"Поддерживаемые версии Contao","ui.package-details.latest":"Последняя версия","ui.package-details.released":"выпуск от","ui.package-details.license":"Лицензия(и)","ui.package-details.authors":"из","ui.package-details.more":"Еще","ui.package-details.packagist":"Сведения о пакете","ui.package-details.metadata":"Редактировать метаданные","ui.package-details.support_docs":"Документация","ui.package-details.support_wiki":"Вики","ui.package-details.support_forum":"Форум поддержки","ui.package-details.support_issues":"Проблемы / Отчет об ошибках","ui.package-details.support_source":"Исходный код","ui.package-details.support_irc":"IRC / Чат","ui.package-details.support_email":"E-Mail поддержки","ui.package-details.support_rss":"RSS-канал"}')}}]);"use strict";(self["webpackChunkcontao_manager"]=self["webpackChunkcontao_manager"]||[]).push([[219],{3219:function(e){e.exports=JSON.parse('{"ui.app.title":"Contao Extensions","ui.app.loading":"Loading Extension List …","ui.app.language":"Switch language for the Contao Manager","ui.app.colorDark":"Dark Mode","ui.app.colorDarkTitle":"Switch color scheme to dark","ui.app.colorLight":"Light Mode","ui.app.colorLightTitle":"Switch color scheme to light","ui.discover.advertisement":"Advertisement in the extension list","ui.discover.loading":"Loading …","ui.discover.offline":"Could not fetch any results.","ui.discover.offlineExplain":"Check your internet connection and disable JavaScript blockers in your browser.","ui.discover.offlineButton":"Try again","ui.discover.searchPlaceholder":"Search in {count} extensions …","ui.discover.empty":"No results for {query}","ui.discover.more":"More Results","ui.discover.sortBy":"Sort by","ui.discover.sortReleased":"Released","ui.discover.sortReleasedTitle":"Sort results by release date","ui.discover.sortLatest":"Updated","ui.discover.sortLatestTitle":"Sort results by last updated","ui.discover.sortDownloads":"Downloads","ui.discover.sortDownloadsTitle":"Sort results by number of downloads","ui.discover.sortFavers":"Rating","ui.discover.sortFaversTitle":"Sort results by rating","ui.discover.detailsButton":"Details","ui.discover.latestPackages":"Latest and updated extensions","ui.discover.faversPackages":"Top rated extensions","ui.discover.downloadsPackages":"Most downloaded extensions","ui.discover.exactHit":"Exact query match","ui.discover.results":"More search results","ui.package.homepage":"Project Website","ui.package.private":"Private Package","ui.package.privateTitle":"Private packages are only available from the vendor (e.g. as a ZIP download). Please visit the website for more information.","ui.package.abandoned":"abandoned","ui.package.abandonedText":"This package is abandoned and no longer maintained.","ui.package.abandonedReplace":"This package is abandoned and no longer maintained. The author suggests using the {replacement} package instead.","ui.package.contaoVersion":"Available for Contao","ui.package-details.previous":"Previous Extension Details","ui.package-details.close":"Close Extension Details","ui.package-details.loading":"Loading …","ui.package-details.tabDescription":"Description","ui.package-details.tabRequire":"Requirements","ui.package-details.tabFeatures":"Features","ui.package-details.tabSuggest":"Suggestions","ui.package-details.tabConflict":"Conflicts","ui.package-details.tabDependents":"Dependents","ui.package-details.linkRequires":"requires","ui.package-details.linkReplaces":"replaces","ui.package-details.linkProvides":"provides","ui.package-details.linkConflicts":"conflicts","ui.package-details.funding":"Fund package maintenance!","ui.package-details.contaoVersions":"Supported Contao version(s)","ui.package-details.latest":"Latest version","ui.package-details.released":"released on","ui.package-details.license":"License(s)","ui.package-details.authors":"from","ui.package-details.more":"More","ui.package-details.packagist":"Package Details","ui.package-details.metadata":"Edit Metadata","ui.package-details.support_docs":"Documentation","ui.package-details.support_wiki":"Wiki","ui.package-details.support_forum":"Support Forum","ui.package-details.support_issues":"Issues / Bug Report","ui.package-details.support_source":"Source Code","ui.package-details.support_irc":"IRC / Chat","ui.package-details.support_email":"Support E-Mail","ui.package-details.support_rss":"RSS Feed"}')}}]);"use strict";(self["webpackChunkcontao_manager"]=self["webpackChunkcontao_manager"]||[]).push([[721],{9721:function(a){a.exports=JSON.parse('{"ui.app.title":"Contao機能拡張","ui.app.loading":"機能拡張の一覧を読み込み中...","ui.app.language":"Contao Managerの言語を切り替え","ui.app.colorDark":"ダークモード","ui.app.colorDarkTitle":"配色をダークモードに切り替え","ui.app.colorLight":"ライトモード","ui.app.colorLightTitle":"配色をライトモードに切り替え","ui.discover.advertisement":"機能拡張のリストに広告","ui.discover.loading":"読み込み中...","ui.discover.offline":"何も結果を取得できませんでした。","ui.discover.offlineExplain":"Internet接続を確認し、ブラウザーのJavaScriptのブロッカーを無効にしてください。","ui.discover.offlineButton":"再実行","ui.discover.searchPlaceholder":"{count}の機能拡張から検索中...","ui.discover.empty":"{query}の結果はありません。","ui.discover.more":"さらに結果を表示","ui.discover.sortBy":"並べ替え","ui.discover.sortReleased":"リリース","ui.discover.sortReleasedTitle":"リリース日で並べ替え","ui.discover.sortLatest":"更新日時","ui.discover.sortLatestTitle":"更新日時で並べ替え","ui.discover.sortDownloads":"ダウンロード","ui.discover.sortDownloadsTitle":"ダウンロード数で並べ替え","ui.discover.sortFavers":"評価","ui.discover.sortFaversTitle":"評価の結果で並べ替え","ui.discover.detailsButton":"詳細","ui.discover.latestPackages":"最新と更新された機能拡張","ui.discover.faversPackages":"最上位のレートの機能拡張","ui.discover.downloadsPackages":"もっともダウンロードされた機能拡張","ui.discover.exactHit":"問い合わせに完全一致","ui.discover.results":"その他の検索結果","ui.package.homepage":"プロジェクトのウェブサイト","ui.package.private":"私的なパッケージ","ui.package.privateTitle":"私的なパッケージはベンダーからだけ(例えば、ZIPのダウンロードで)入手できます。詳細はウェブサイトを参照してください。","ui.package.abandoned":"放棄","ui.package.abandonedText":"このパッケージは放棄され、もう保守されていません。","ui.package.abandonedReplace":"このパッケージは放棄され、もう保守されていません。代わりに{replacement}パッケージの使用を作者は推奨しています。","ui.package.contaoVersion":"Contaoで利用可能","ui.package-details.previous":"以前の機能拡張の詳細","ui.package-details.close":"機能拡張の詳細を閉じる","ui.package-details.loading":"読み込み中...","ui.package-details.tabDescription":"説明","ui.package-details.tabRequire":"必須要件","ui.package-details.tabFeatures":"機能","ui.package-details.tabSuggest":"提案","ui.package-details.tabConflict":"競合","ui.package-details.tabDependents":"依存関係","ui.package-details.linkRequires":"必要","ui.package-details.linkReplaces":"置き換え","ui.package-details.linkProvides":"提供","ui.package-details.linkConflicts":"競合","ui.package-details.funding":"パッケージの保守に資金を提供!","ui.package-details.contaoVersions":"サポートしているContaoのバージョン","ui.package-details.latest":"最新版","ui.package-details.released":"リリース日","ui.package-details.license":"ライセンス","ui.package-details.authors":"次から","ui.package-details.more":"詳細","ui.package-details.packagist":"パッケージの詳細","ui.package-details.metadata":"メタデータを編集","ui.package-details.support_docs":"ドキュメント","ui.package-details.support_wiki":"Wiki","ui.package-details.support_forum":"サポートフォーラム","ui.package-details.support_issues":"問題 / バグ報告","ui.package-details.support_source":"ソースコード","ui.package-details.support_irc":"IRC / チャット","ui.package-details.support_email":"サポートの電子メール","ui.package-details.support_rss":"RSSフィード"}')}}]);"use strict";(self["webpackChunkcontao_manager"]=self["webpackChunkcontao_manager"]||[]).push([[769],{4769:function(i){i.exports=JSON.parse('{"ui.app.title":"Estensioni Contao","ui.app.loading":"Caricamento lista estensioni...","ui.app.language":"Switch language for the Contao Manager","ui.app.colorDark":"Dark Mode","ui.app.colorDarkTitle":"Switch color scheme to dark","ui.app.colorLight":"Light Mode","ui.app.colorLightTitle":"Switch color scheme to light","ui.discover.advertisement":"Pubblicità nell\'elenco delle estensioni","ui.discover.loading":"Caricamento in corso ...","ui.discover.offline":"Non è stato possibile ottenere alcun risultato.","ui.discover.offlineExplain":"Controlla la tua connessione internet e disabilita i blocchi JavaScript nel tuo browser.","ui.discover.offlineButton":"Riprova","ui.discover.searchPlaceholder":"Cerca in {conti} estensioni ...","ui.discover.empty":"Nessun risultato per {query}","ui.discover.more":"Ulteriori risultati","ui.discover.sortBy":"Ordina per","ui.discover.sortReleased":"Rilasciato","ui.discover.sortReleasedTitle":"Ordina i risultati per data di rilascio","ui.discover.sortLatest":"Aggiornamento eseguito","ui.discover.sortLatestTitle":"Ordina i risultati per ultimo aggiornamento","ui.discover.sortDownloads":"Downloads","ui.discover.sortDownloadsTitle":"Ordina i risultati per numero di download","ui.discover.sortFavers":"Valutazione","ui.discover.sortFaversTitle":"Ordina i risultati per valutazione","ui.discover.detailsButton":"Dettagli","ui.discover.latestPackages":"Estensioni più recenti e aggiornate","ui.discover.faversPackages":"Estensioni più votate","ui.discover.downloadsPackages":"Estensioni più scaricate","ui.discover.exactHit":"Exact query match","ui.discover.results":"More search results","ui.package.homepage":"Sito web del progetto","ui.package.private":"Pacchetto privato","ui.package.privateTitle":"I pacchetti privati sono disponibili solo attraverso il fornitore (ad es. Come download ZIP). Per ulteriori informazioni, visitare il sito Web.","ui.package.abandoned":"dismesso","ui.package.abandonedText":"Questo pacchetto è abbandonato e non è più mantenuto.","ui.package.abandonedReplace":"Questo pacchetto è abbandonato e non è più mantenuto. L\'autore suggerisce di usare il pacchetto {sostituzione}.","ui.package.contaoVersion":"Available for Contao","ui.package-details.previous":"Dettagli estensione precedente","ui.package-details.close":"Chiudi dettagli estensione","ui.package-details.loading":"Caricamento in corso ...","ui.package-details.tabDescription":"Descrizione","ui.package-details.tabRequire":"Requisiti","ui.package-details.tabFeatures":"Caratteristiche","ui.package-details.tabSuggest":"Suggerimenti","ui.package-details.tabConflict":"Conflitti","ui.package-details.tabDependents":"Dipendenti","ui.package-details.linkRequires":"richiede","ui.package-details.linkReplaces":"sostituisce","ui.package-details.linkProvides":"fornisce","ui.package-details.linkConflicts":"Conflitti","ui.package-details.funding":"Manutenzione del pacchetto!","ui.package-details.contaoVersions":"Supported Contao version(s)","ui.package-details.latest":"Ultima versione","ui.package-details.released":"rilasciato il","ui.package-details.license":"Licenza","ui.package-details.authors":"da","ui.package-details.more":"Altro","ui.package-details.packagist":"Dettagli del pacchetto","ui.package-details.metadata":"Modifica metadati","ui.package-details.support_docs":"Documentazione","ui.package-details.support_wiki":"Wiki","ui.package-details.support_forum":"Forum di supporto","ui.package-details.support_issues":"Problemi / Bug Report","ui.package-details.support_source":"Source Code","ui.package-details.support_irc":"IRC / Chat","ui.package-details.support_email":"E-Mail di supporto","ui.package-details.support_rss":"Feed RSS"}')}}]);"use strict";(self["webpackChunkcontao_manager"]=self["webpackChunkcontao_manager"]||[]).push([[606],{4606:function(e){e.exports=JSON.parse('{"ui.app.httpsHeadline":"!! Ligação Insegura !!","ui.app.httpsDescription":"Sem recurso a HTTPS os seus dados confidenciais serão transferidos sem encriptação.","ui.app.httpsLink":"Mais info","ui.app.httpsHref":"https://https.cio.gov/everything/","ui.app.safeModeHeadline":"!! Modo Guardar activado !!","ui.app.safeModeDescription":"Algumas características do Gestor de Contacto não estão disponíveis.","ui.app.safeModeExit":"Sair do modo seguro","ui.app.limitedHeadline":"Autenticação remota","ui.app.limitedDescription":"You have limited permissions due to passwordless login.","ui.app.limitedLogout":"Re-authenticate","ui.app.totpHeadline":"Security Notice","ui.app.totpDescription":"Configure two-factor authentication now to secure your account.","ui.app.totpSetup":"Configuração","ui.app.loading":"A iniciar o Contao Manager ...","ui.app.apiError":"API status não esperado -erro","ui.app.configSecurity1":"ALERTA DE SEGURANÇA!!! Directório de configuração sem protecção detectado","ui.app.configSecurity2":"O Contao Manager detetou que os seus ficheiros de configuração estão acessíveis publicamente. Todas as operações estão desativadas até que o directório esteja seguro, caso contrário um atacante poderá aceder a informações sensíveis sobre a sua instalação.\\n\\nPara corrigir esta situação, certifique-se que previne o acesso ao directório \\"contao-manager\\" no seu servidor. Para saber como o fazer, consulte o manual do seu webserver ou contacte o fornecedor de alojamento web.","ui.account.welcome":"Bem Vindo","ui.account.intro1":"Bem-vindo ao Contao Manager, uma ferramenta universal para instalar e gerir o Contao Open Source CMS. Se é novo nele, por favor {readTheManualToGetStarted}.","ui.account.introGetStarted":"{readTheManual} para começar","ui.account.introManual":"ler o manual","ui.account.intro2":"Se encontrar algum problema, verifique {ourGithubIssues} e sinta-se à vontade para criar um novo para qualquer coisa que ainda não tenha sido relatada.","ui.account.introIssues":"as nossas edições GitHub","ui.account.headline":"Utilizador","ui.account.description":"Para gerir a sua instalação, por favor crie uma conta para utilizar no Contao Manager. Certifique-se que é distinta da conta utilizada no Contao back e front end.","ui.account.username":"Utilizador","ui.account.password":"Senha","ui.account.passwordPlaceholder":"min. 8 caracteres","ui.account.passwordLength":"Por favor utilize o minimo de 8 caracteres.","ui.account.loginInvalid":"There was an error when creating the account. Please try a different username.","ui.account.submit":"Criar Conta","ui.account.usePassword":"Use password for login","ui.account.usePasskey":"Use Passkey for login","ui.account.totpHeadline":"Two-factor authentication","ui.account.totpDescription":"Please enable two-factor authentication, which adds an extra layer of security to your account. In addition to your username and password, you will need to enter a verification code generated by a two-factor app such as 1Password, Authy, Google Authenticator, Microsoft Authenticator, LastPass Authenticator or any other TOTP app.","ui.account.totpSetup":"Configure now","ui.account.totpSkip":"Configure later","ui.account.login":"Decline Invitation","ui.account.contribute1":"O Contao e o Contao Manager são patrocinados pela Associação Contao sem fins lucrativos.","ui.account.contribute2":"Por favor, considere contribuir para o código aberto por {donate}.","ui.account.contributeDonate":"fazer um donativo","ui.login.headline":"Iniciar sessão","ui.login.description":"Iniciar sessão para gerir a sua instalação.","ui.login.username":"Utilizador","ui.login.password":"Senha","ui.login.totpHeadline":"Two-factor authentication","ui.login.totpDescription":"Please enter your verification code to complete the login process.","ui.login.totp":"Verification code","ui.login.forgotPassword":"Esqueceu a sua senha?","ui.login.button":"Iniciar sessão","ui.login.passkey":"Sign In with Passkey","ui.login.cancel":"Cancelar","ui.login.or":"or","ui.login.locked":"O acesso foi negado porque o Gestor de Contacto está bloqueado. Para desbloquear, apagar o ficheiro {lockFile} no directório raiz do seu Contao.","ui.logout.headline":"Tempo de Sessão expirado.","ui.logout.warning":"Esteve inactivo por mais de 25 minutos. Por razões de segurança a sua sessão será terminada em breve.","ui.logout.expired":"A sua sessão foi terminada automaticamente porque esteve inactivo por mais de 30 minutos.","ui.logout.renew":"Manter sessão ativa","ui.logout.logout":"Terminar Sessão","ui.logout.login":"Voltar para inicio de sessão","ui.oauth.error":"Tentativa OAuth inválida. Verifique os parâmetros pedidos.","ui.oauth.https":"O redireccionamento do URI DEVE utilizar um protocolo seguro (https:) para evitar que o símbolo de autenticação seja transmitido em texto claro.","ui.oauth.headline":"Autenticação remota","ui.oauth.description":"A seguinte aplicação ou serviço está a solicitar acesso remoto ao Contao Manager.","ui.oauth.domain":"Antes de permitir o acesso, certifique-se de que conhece este URL e confie no seu proprietário!","ui.oauth.outOfScope":"Unfortunately, you do not have the necessary permissions to grant this access.","ui.oauth.allow":"Permitir Acesso","ui.oauth.deny":"Negar Acesso","ui.oauth.switchUser":"Switch User","ui.scope.admin":"Admin access including user management","ui.scope.install":"Install new packages and change Contao configuration","ui.scope.update":"Update packages and execute maintenance tasks","ui.scope.read":"Read packages and configuration","ui.boot.headline":"Verificar Sistema","ui.boot.description":"Por favor espere, estamos a analisar o seu servidor...","ui.boot.issue1":"Problemas com a instalação detectados","ui.boot.issue2":"A sua instalação tem problemas que têm de ser resolvidos antes que o Gestor de Contacto possa ser utilizado.","ui.boot.run":"Iniciar o Contao Manager","ui.boot.safeMode":"Executar em Modo de Segurança","ui.recovery.headline":"Recuperação de Sistema","ui.recovery.description":"O Contao Manager detectou ficheiros que podem pertencer ao Contao, mas a linha de comandos não funciona como previsto.","ui.recovery.console":"Saída da Consola","ui.recovery.repairOptions":"Por favor escolha uma opção para reparar a sua instalação.","ui.recovery.repairHeadline":"Reparação Automática","ui.recovery.repairDescription":"Efectua uma tentativa de reparar automaticamente a instalação ao reconstruir a cache da aplicação e reinstalando os pacotes Composer.","ui.recovery.repairWarning":"Quaisquer modificações aos ficheiros vendor poderão ser apagadas durante o processo!","ui.recovery.repairFailed":"A reparação automática não teve sucesso. Usar o modo de segurança para reparar manualmente a instalação poderá resolver o problema.","ui.recovery.repairButton":"Executar Reparação de Sistema","ui.recovery.safeModeHeadline":"Modo de Segurança ","ui.recovery.safeModeDescription":"Executar o Contao Manager em Modo de Segurança permite gerir pacotes e correr tarefas de manutenção específicas, mas implementações que dependam de uma instalação Contao funcional não estarão disponíveis.","ui.recovery.safeModeButton":"Executar em Modo de Segurança","ui.server.pending":"Aguarde ...","ui.server.running":"A analisar ...","ui.server.error":"A verificação falhou devido a uma resposta inesperada do servidor.","ui.server.details":"Detalhes","ui.server.prerequisite":"A verificação falhou devido a um pré-requisito em falta.","ui.server.selfUpdate.title":"Actualizações Contao Manager","ui.server.selfUpdate.update":"Uma nova versão do Contao Manager {latest} está disponivel.","ui.server.selfUpdate.manualUpdate":"Está disponível uma nova versão do Contao Manager {latest}. O seu servidor não suporta actualizações automáticas, por favor descarregue a nova versão a partir de {download}.","ui.server.selfUpdate.latest":"Está a usar a versão mais recente {current}.","ui.server.selfUpdate.dev":"Versões de testes não suportam actualizações automáticas.","ui.server.selfUpdate.unsupported":"Uma nova versão está disponível mas não é  compatível com a sua versão de PHP.","ui.server.selfUpdate.button":"Executar Auto-Update","ui.server.selfUpdate.continue":"Continuar","ui.server.config.title":"Configuração do Servidor","ui.server.config.setup":"Configurar","ui.server.config.change":"Alterar","ui.server.config.save":"Guardar","ui.server.config.cancel":"Cancelar","ui.server.config.customOption":"Outros ...","ui.server.config.description":"Para executar correctamente as tarefas de fundo, o Gestor de Contacto precisa de saber onde encontrar o binário de linha de comando PHP e como executar comandos separados do processo web.","ui.server.config.formTitle":"Configuração do Servidor","ui.server.config.formText":"Por favor introduza o caminho para o seu binário PHP. Certifique-se que o seu binário usa a mesma versao PHP que o seu processo web.","ui.server.config.cloudTitle":"Composer Resolver Cloud","ui.server.config.cloudText":"A Composer Resolver Cloud permite instalar dependências Composer mesmo se o seu servidor não possuir memória local suficiente. Tenha em consideração que a sua informação de pacotes será transmitida para um servidor em nuvem mantido pela Contao Association.","ui.server.config.cloud":"Usar a Composer Resolver Cloud","ui.server.config.cli":"Binário PHP","ui.server.config.stateErrorCli":"Nenhum binário PHP válido foi encontrado no servidor. ","ui.server.config.stateErrorCloud":"A Composer Resolver Cloud não é suportada.","ui.server.config.stateSuccess":"Binário PHP em {php_cli}.","ui.server.config.cloudEnabled":"Package dependencies will be resolved using the Composer Resolver Cloud.","ui.server.config.cloudDisabled":"The Composer Resolver Cloud is disabled.","ui.server.php_web.title":"Processo Web PHP","ui.server.php_web.below7":"Encontrada a versão {version} PHP. Actualize para a versão PHP 7 assim que possivel!","ui.server.php_web.success":"Encontrada a versão PHP {version}, nenhum problema a reportar.","ui.server.php_cli.title":"Interface PHP Linha de Comandos","ui.server.php_cli.success":"Encontrada a versão PHP {version}, nenhum problema a reportar.","ui.server.composer.title":"Ambiente Composer","ui.server.composer.success":"Nenhum problema encontrado.","ui.server.composer.install":"Dependências Composer não instaladas.","ui.server.composer.button":"Instalar","ui.server.contao.title":"Instalação Contao","ui.server.contao.setup":"Configuração","ui.server.contao.check":"Check database","ui.server.contao.empty":"Nenhuma instalação Contao foi encontrada.","ui.server.contao.old":"A versão {version} do Contao não é compatível com o Contao Manager,  actualize a sua instalação manualmente.","ui.server.contao.found":"Encontrado Contao com versão {version} (Versão API {api}).","ui.server.contao.connectionError":"Incapaz de se ligar ao servidor da base de dados.","ui.server.contao.connectionProblem":"Database problem found.","ui.server.contao.missingUser":"Conta administrativa não encontrada.","ui.setup.continue":"Continuar","ui.setup.manager":"Iniciar o Contao Manager","ui.setup.cancel":"Cancelar","ui.setup.welcome":"Bem Vindo","ui.setup.welcome1":"Este assistente irá levá-lo através dos passos necessários para configurar a sua instalação do CMS Contao Open Source.","ui.setup.welcome2":"If you have any questions, please find documentation, forums, a Slack channel and more on the {support} page.","ui.setup.support":"Apoio à Comunidade","ui.setup.start":"ComeceComece","ui.setup.complete":"Parabéns!","ui.setup.complete1":"Contao {version} has been installed successfully.","ui.setup.complete2":"To finish the setup process, please open the install tool to configure the database connection and create a back end user.","ui.setup.complete3":"You can now start to create your website in the Contao back end. If you need additional extensions, continue to the Contao Manager.","ui.setup.installTool":"Open the Install Tool","ui.setup.login":"Login to Contao","ui.setup.funding":"Free software is \\"free\\" as in \\"free speech\\", not as in \\"free beer\\". An Open Source project like Contao requires amounts of money that can\'t be raised by a single person or company.\\nIf you have a website or sell websites built with Contao, we would love to see you contribute back financially to the product your business relies upon.","ui.setup.fundingLink":"Learn more","ui.setup.document-root.headline":"Configuração do Webserver","ui.setup.document-root.warning":"Para instalar o Contao através do Contao Manager, é necessário fixar a raiz do documento no servidor web.","ui.setup.document-root.description1":"Contao uses a separate folder for public files, application files are installed in its parent folder. Contao cannot be installed if the folder structure is not correct or the folders are not empty.","ui.setup.document-root.description2":"Se não souber como configurar a raiz do seu documento, leia a documentação do Contacto ou contacte o seu fornecedor de alojamento.","ui.setup.document-root.documentation":"Ler a Documentação","ui.setup.document-root.conflictsTitle":"Directório de instalação não vazio","ui.setup.document-root.conflictsDirectory":"The root directory of your future Contao installation is not empty, we have found {count} file(s) that might be overwritten by the installation process. It is recommended to create an empty directory structure for Contao, but you can also remove the following files and check again if you are sure they are unused.","ui.setup.document-root.ignoreConflicts":"Quero instalar o Contao no directório dos não vazios. Compreendo que isto pode substituir quaisquer ficheiros existentes no meu espaço web.","ui.setup.document-root.check":"Check again","ui.setup.document-root.create":"Criar directórios","ui.setup.document-root.change":"Change directories","ui.setup.document-root.formTitle":"Configuração de directório","ui.setup.document-root.formText1":"O Contao Manager pode criar automaticamente uma nova estrutura de directório no servidor.","ui.setup.document-root.formText2":"Será necessário configurar manualmente a raiz do novo documento (por exemplo, através de um painel de administração de alojamento).","ui.setup.document-root.autoconfig":"Compreendo que tenho de alterar a configuração do meu servidor. Não configurar a raiz do documento irá quebrar o Contao Manager e expor os ficheiros de configuração (incluindo detalhes de conta e palavras-passe)!","ui.setup.document-root.directory":"Novo Directório","ui.setup.document-root.currentRoot":"Raiz do documento actual","ui.setup.document-root.newRoot":"Novo Documento Raiz","ui.setup.document-root.finish":"Directórios de configuração","ui.setup.document-root.publicDir":"Utilizar {dir} para ficheiros públicos (para Contao {version})","ui.setup.document-root.directoryInvalid":"Por favor, introduza um nome de directório válido.","ui.setup.document-root.directoryExists":"O directório alvo já existe. Por favor, introduza um nome diferente.","ui.setup.document-root.confirmation":"O Contao Manager criou com sucesso o directório necessário para a sua instalação de Contao. Tem agora de configurar a raiz do documento no seu servidor web. Não volte a carregar esta página até lá.","ui.setup.document-root.reload":"Recarregar Página","ui.setup.document-root.success":"The directory structure on your web server is set up correctly!","ui.setup.document-root.installingProjectDir":"Application files will be installed to {dir}.","ui.setup.document-root.installingPublicDir":"Public files will be installed to {dir}.","ui.setup.document-root.installedProjectDir":"Application files are installed in {dir}.","ui.setup.document-root.installedPublicDir":"Public files are installed in {dir}.","ui.setup.create-project.headline":"Instalação Contao","ui.setup.create-project.description":"Contao development follows the principle of {semver}, a new minor version is released every six months. The currently supported releases are:","ui.setup.create-project.semver":"Semantic Versioning","ui.setup.create-project.latestTitle":"Mais Recente","ui.setup.create-project.ltsTitle":"Suporte a Longo Prazo (LTS)","ui.setup.create-project.latestQ1":"Our latest version, offers the most features with support until February {year}.","ui.setup.create-project.latestQ3":"Our latest version, offers the most features with support until August {year}.","ui.setup.create-project.ltsText":"Our current LTS version, if you focus on stability. Offers long term support until February {year}.","ui.setup.create-project.pltsText":"The previous LTS version, still has long term support until February {year}.","ui.setup.create-project.requiresPHP":"Requires at least PHP {version}, you have PHP {current}.","ui.setup.create-project.releaseplan":"Ver o {contaoReleasePlan} para informações detalhadas.","ui.setup.create-project.releaseplanLink":"Plano de lançamento do Contao","ui.setup.create-project.installed":"Contao {version} is successfully installed on the server. Continue to set up your database or launch the Contao Manager to install a different version.","ui.setup.create-project.formTitle":"Select a distribution","ui.setup.create-project.formText":"Please choose which version should be installed.","ui.setup.create-project.version":"Versão","ui.setup.create-project.demo":"Install the Contao demo website","ui.setup.create-project.demoDescription":"The demo website helps you to get familiar with Contao and all of its core features. More themes can be found in the {store}.","ui.setup.create-project.coreOnly":"Instalação Mínima ( Apenas o \\"core\\")","ui.setup.create-project.noUpdate":"Ignorar Instalação (Utilizador avançado!)","ui.setup.create-project.theme":"Contao Theme","ui.setup.create-project.themeInstall":"To install a Contao theme, use the search input or upload a theme file (.cto/.zip) that supports installation through the Contao Manager.","ui.setup.create-project.themeBuy":"Make sure to visit the official {store}.","ui.setup.create-project.themeStore":"Contao Themes Store","ui.setup.create-project.themeUpload":"Upload theme file (.cto/.zip)","ui.setup.create-project.themeInvalid":"The uploaded file is not a Contao theme or does not support the Contao Manager.","ui.setup.create-project.themeWarning":"The Contao Manager cannot tell whether this theme is compatible with your server. Please check with the theme vendor if you have any questions.","ui.setup.create-project.themeTitle":"Review theme details","ui.setup.create-project.themeDetails":"The following dependencies and files will be installed with this theme.","ui.setup.create-project.themeRequire":"{count} Dependencies | {count} Dependencies","ui.setup.create-project.themeFiles":"{count} File | {count} Files","ui.setup.create-project.theme.or":"or search public themes","ui.setup.create-project.theme.search":"Search themes","ui.setup.create-project.theme.more":"More themes","ui.setup.create-project.theme.empty":"No themes matching {query}","ui.setup.create-project.theme.uploaded":"The theme file was uploaded successfully.","ui.setup.create-project.theme.packageName":"Package name","ui.setup.create-project.theme.version":"Versão","ui.setup.create-project.theme.authors":"Author(s)","ui.setup.create-project.theme.upload":"Uploading {name} ({size})","ui.setup.create-project.install":"Instalar","ui.setup.create-project.cancel":"Cancelar","ui.setup.create-project.fileError":"Could not find composer.json in {file}.","ui.setup.create-project.jsonError":"composer.json contains invalid JSON.","ui.setup.create-project.schemaError":"composer.json schema validation failed.","ui.setup.database-connection.headline":"Database Connection","ui.setup.database-connection.description":"Contao requires a MySQL database (or a compatible fork like MariaDB) to store pages, content, users and other relational data. Connection parameters are stored in the {env} file in the project root of your Contao installation.","ui.setup.database-connection.formTitle":"Connection Parameters","ui.setup.database-connection.formText":"Enter a database URL or fill in the username, password, server and database fields separately.","ui.setup.database-connection.url":"Database URL","ui.setup.database-connection.validUrl":"Database URL is invalid or connection to server failed.","ui.setup.database-connection.or":"or","ui.setup.database-connection.user":"Utilizador","ui.setup.database-connection.password":"Senha","ui.setup.database-connection.server":"Server (:Port)","ui.setup.database-connection.database":"Database Name","ui.setup.database-connection.connected":"Successfully connected to database {database} on {server}.","ui.setup.database-connection.error":"Error connecting to the database.","ui.setup.database-connection.problem":"Contao has detected a problem with your database server.","ui.setup.database-connection.schemaTitle":"Database Schema","ui.setup.database-connection.migration":"There is one pending migration. | There are {count} pending migrations.","ui.setup.database-connection.schema":"There is one pending schema update. | There are {count} pending schema updates.","ui.setup.database-connection.noChanges":"Your database schema is up to date.","ui.setup.database-connection.check":"Check database","ui.setup.database-connection.skip":"Skip","ui.setup.database-connection.save":"Guardar","ui.setup.database-connection.change":"Change credentials","ui.setup.database-connection.restoreTitle":"Database Import","ui.setup.database-connection.restoreText":"The theme you just installed contains a database backup. Restore the database to import theme data or skip this step to start with a blank Contao installation. | The theme you just installed contains multiple database backups. Select a backup file to import theme data or skip this step to start with a blank Contao installation.","ui.setup.database-connection.backup":"Backup current database before import","ui.setup.database-connection.backupWarning":"All data in database will be overwritten on import! Create a backup first if the database is not empty.","ui.setup.database-connection.restore":"Import theme database","ui.setup.database-connection.restoreOption":"Backup from {date} ({size})","ui.setup.database-connection.restored":"Your theme database was successfully imported. Continue to validate your database schema.","ui.setup.backend-user.success":"An admin account for the Contao back end was found in your database. Use the Contao back end to add more users.","ui.setup.backend-user.error":"Unable to retrieve user list. Check the console output for details.","ui.setup.backend-user.headline":"Backend Account","ui.setup.backend-user.description":"To manage your website, you need to have at least one admin account for the Contao back end. Be aware that this account is not related to the Contao Manager.","ui.setup.backend-user.formTitle":"Criar Conta","ui.setup.backend-user.formText":"Please enter the details for the new back end account.","ui.setup.backend-user.username":"Utilizador","ui.setup.backend-user.name":"Name","ui.setup.backend-user.email":"E-mail address","ui.setup.backend-user.emailInvalid":"Please enter a valid e-mail address","ui.setup.backend-user.password":"Senha","ui.setup.backend-user.passwordPlaceholder":"min. 8 caracteres","ui.setup.backend-user.passwordLength":"Por favor utilize o minimo de 8 caracteres.","ui.setup.backend-user.create":"Add account","ui.task.headline":"Tarefa de fundo","ui.task.loading":"Carregamento de detalhes ...","ui.task.created":"Carregamento de detalhes ...","ui.task.active":"Por favor aguarde enquanto o Gestor de Contacto está a executar operações de tarefas em segundo plano.","ui.task.complete":"Todas as operações são concluídas com sucesso. Verifique a saída da consola para mais detalhes.","ui.task.paused":"Uma operação de fundo parou inesperadamente. Por favor, verifique a saída da consola.","ui.task.aborting":"Por favor aguarde enquanto as operações de fundo estão a ser canceladas.","ui.task.stopped":"Algumas operações de fundo foram canceladas. Por favor, verifique a saída da consola.","ui.task.error":"Uma operação de fundo parou inesperadamente. Por favor, verifique a saída da consola.","ui.task.failed":"O Gestor de Contao não conseguiu iniciar uma tarefa de fundo!","ui.task.failedDescription1":"Alguma coisa correu mal ao tentar executar operações em segundo plano.","ui.task.failedDescription2":"Se isto acontecer novamente, o seu servidor poderá não ser suportado.","ui.task.reportProblem":"Reportar um Problema","ui.task.pausedDescription":"Click \\"Continue\\" if you want to ignore the error and execute the remaining operations.","ui.task.sponsor":"Composer Cloud sponsored by {sponsor}","ui.task.buttonAudit":"Actualizar base de dados ","ui.task.buttonClose":"Fechar","ui.task.buttonConfirm":"Confirmar e Fechar","ui.task.buttonContinue":"Continuar","ui.task.buttonCancel":"Cancelar","ui.task.confirmCancel":"Tem a certeza que pretende interromper esta tarefa? Poderá afectar a instalação do Contao negativamente!","ui.task.autoclose":"Detalhes sobre o sucesso da tarefa","ui.console.toggle":"Mostrar/Esconder saída de Consola","ui.console.showLog":"Mostrar registo completo da consola","ui.console.copyLog":"Copiar log para prancheta","ui.migrate.headline":"Database Updates","ui.migrate.migrationsOnly":"(migrations only)","ui.migrate.schemaOnly":"(schema only)","ui.migrate.loading":"Please wait, we are checking your database …","ui.migrate.empty":"No pending migrations or schema updates found. Your database is up to date.","ui.migrate.emptyMigrations":"No pending migrations found. Make sure to also check for schema updates.","ui.migrate.emptySchema":"No pending schema updates found. Make sure to also check for migrations.","ui.migrate.pending":"Your database is not up to date. Please review the console output below and execute the changes.","ui.migrate.previousChanges":"A previous database migration was not confirmed.\\nPlease review the console output below, then continue to see the next changes.","ui.migrate.previousComplete":"A previous database migration was not confirmed, please review the console output below.\\nThere are no more pending changes.","ui.migrate.appliedChanges":"Database updates have been applied.\\nPlease review the console output below, then continue to see the next changes.","ui.migrate.appliedComplete":"Database updates have been applied.\\nThere are no more pending migrations or schema updates. Your database is up to date.","ui.migrate.problem":"Contao has detected a problem with your database server.\\nPlease review the console output below to find out what needs to be fixed. | Contao has detected problems with your database server.\\nPlease review the console output below to find out what needs to be fixed.","ui.migrate.warning":"Contao has detected a misconfiguration of your database server.\\nWarnings can be skipped temporarily, but should be fixed for optimal performance and data integrity.","ui.migrate.error":"The changes could not be applied. Your database might have been changed, please check again to retry.","ui.migrate.execute":"Execute","ui.migrate.close":"Fechar","ui.migrate.confirm":"Confirmar e Fechar","ui.migrate.cancel":"Cancelar","ui.migrate.continue":"Continuar","ui.migrate.setup":"Configuração","ui.migrate.skip":"Skip","ui.migrate.retry":"Check again","ui.migrate.retryAll":"Check all","ui.migrate.withDeletes":"Execute all database changes including DROP queries.","ui.migrate.migrationTitle":"Database Migrations","ui.migrate.schemaTitle":"Schema Updates","ui.migrate.problemTitle":"Database Problems","ui.migrate.warningTitle":"Database Warnings","ui.migrate.addTable":"Add table {table}","ui.migrate.dropTable":"Drop table {table}","ui.migrate.addField":"Add field {table}.{field}","ui.migrate.changeField":"Change field {table}.{field}","ui.migrate.dropField":"Drop field {table}.{field}","ui.migrate.createIndex":"Create index \\"{name}\\" on {table}","ui.migrate.dropIndex":"Drop index \\"{name}\\" on {table}","ui.widget.mandatory":"Este campo não pode estar vazio.","ui.widget.blankOption":"Por favor seleccione ...","ui.widget.showPassword":"Show password","ui.widget.hidePassword":"Hide password","ui.error.title":"O pedido HTTP de \\"{method} {url}\\" falhou.","ui.error.server500":"Parece que ocorreu um erro inesperado no seu servidor. Por favor verifique os ficheiros de registo do seu servidor web (Apache/Nginx) e os registos do Contao Manager em \\"Contao-manager/logs\\".","ui.error.response":"O servidor devolveu uma resposta com o código de estado {status}.","ui.error.moreLink":"Mais informação ","ui.error.support":"Contao Support","ui.error.permission":"You do not have permission to use this feature.","ui.footer.help":"Ajuda","ui.footer.reportProblem":"Reportar um Problema","ui.navigation.discover":"Descubra","ui.navigation.packages":"Pacotes","ui.navigation.tools":"Ferramentas","ui.navigation.installTool":"Ferramenta de Instalação","ui.navigation.backend":"Backend Contao","ui.navigation.debug":"Depuração Contao","ui.navigation.logViewer":"Log Viewer","ui.navigation.phpinfo":"Informação PHP","ui.navigation.phpinfoLoading":"Carregamento de informação PHP","ui.navigation.maintenance":"Manutenção","ui.navigation.rebuildCache":"Reconstruir Cache","ui.navigation.users":"Accounts","ui.navigation.systemCheck":"Verificar Sistema","ui.navigation.advanced":"Avançado","ui.navigation.logout":"Terminar Sessão","ui.maintenance.database.title":"Database Migrations and Backups","ui.maintenance.database.description":"Database migrations ensure consistent data and table schemas.","ui.maintenance.database.migrations":"One pending database migration | {count} pending database migrations","ui.maintenance.database.schemaUpdates":"One pending schema update | {count} pending schema updates","ui.maintenance.database.error":"Database problem found.","ui.maintenance.database.warning":"Database warnings found.","ui.maintenance.database.button":"Check database","ui.maintenance.database.migrationOnly":"Check migrations only","ui.maintenance.database.schemaOnly":"Check schema only","ui.maintenance.database.installTool":"Open Install Tool","ui.maintenance.database.createBackup":"Create Backup","ui.maintenance.database.backupUnsupported":"Database backups are not supported by your Contao version.","ui.maintenance.database.backupList":"You have one database backup, created on {date}. | You have {count} database backups, the latest one was created on {date}.","ui.maintenance.database.backupEmpty":"You currently have no database backups.","ui.maintenance.rebuildCache.title":"Cache de Aplicação","ui.maintenance.rebuildCache.description":"Reconstruir a cache da aplicação é necessário após modificar quaisquer dos ficheiros de configuração.","ui.maintenance.rebuildCache.rebuildProd":"Reconstruir Cache de Produção","ui.maintenance.rebuildCache.rebuildDev":"Reconstruir Cache Desenvolvimento","ui.maintenance.rebuildCache.clearProd":"Limpar Cache Produção","ui.maintenance.rebuildCache.clearDev":"Limpar Cache Desenvolvimento","ui.maintenance.installTool.title":"Ferramenta de Instalação do Contao","ui.maintenance.installTool.description":"A Ferramenta de Instalação do Contao bloqueia automaticamente caso a senha seja introduzida erradamente três vezes.","ui.maintenance.installTool.unlock":"Desbloquear ferramenta de instalação","ui.maintenance.installTool.lock":"Bloquear ferramenta de instalação","ui.maintenance.dumpAutoload.title":"Carregador de Classes Composer","ui.maintenance.dumpAutoload.description":"O Composer autoloader é responsável por carregar classes PHP. O autoloader tem que ser \\"dumped\\" após adicionar namespaces personalizados ao root compser.json .","ui.maintenance.dumpAutoload.button":"Dump Autoloader","ui.maintenance.composerInstall.title":"Dependências Composer ","ui.maintenance.composerInstall.description":"As dependências dos Composer estão localizadas na pasta {vendor} na raiz da sua aplicação. A reinstalação das dependências pode ser necessária após manipulação ou carregamento manual do ficheiro {composerLock}.","ui.maintenance.composerInstall.button":"Executar Instalador","ui.maintenance.composerInstall.update":"Executar Actualizador Composer","ui.maintenance.composerCache.title":"Cache Composer","ui.maintenance.composerCache.description":"O Composer guarda cache de pacotes provenientes de download para melhor performance. Caso tenha problemas com ficheiros não funcionais, apagar a Composer cache para forçar um novo download poderá resolver o problema.","ui.maintenance.composerCache.button":"Apagar Cache","ui.maintenance.maintenanceMode.title":"Modo Manutenção","ui.maintenance.maintenanceMode.description":"Colocar o Contao em modo de manutenção exibirá um modelo \\"503 Serviço Indisponível\\" para o website.","ui.maintenance.maintenanceMode.enable":"Activar","ui.maintenance.maintenanceMode.disable":"Desactivar","ui.maintenance.debugMode.title":"Modo Depuração","ui.maintenance.debugMode.description":"Activar o modo de depuração definindo um utilizador e uma palavra-passe para o ponto de entrada {appDevPhp}.","ui.maintenance.debugMode.descriptionJwt":"Active o modo de depuração ao definir o cookie de depuração para o domínio corrente.","ui.maintenance.debugMode.activate":"Activar","ui.maintenance.debugMode.deactivate":"Desactivar","ui.maintenance.debugMode.credentials":"Credenciais","ui.maintenance.debugMode.user":"Por favor introduza um nome de utilizador para o modo de depuração.","ui.maintenance.debugMode.password":"Por favor introduza uma senha para o modo de depuração.","ui.maintenance.opcodeCache.title":"Cache Opcode","ui.maintenance.opcodeCache.description":"O Opcode efectua cache de ficheiros PHP no processo web para mais rápida execução. Deverá ser apagado dentro de certas  circunstâncias caso ficheiros não sejam reconhecidos após edição.","ui.maintenance.opcodeCache.button":"Truncar Cache","ui.maintenance.safeMode":"Nao disponível em Modo Segurança","ui.maintenance.unsupported":"Não suportado pela sua versão Contao","ui.packages.updateButton":"Actualizar Pacotes","ui.packages.searchButton":"Procurar Pacotes","ui.packages.searchPlaceholder":"Procurar Pacotes ...","ui.packages.uploadOverlay":"Arrastar e largar ficheiros para upload","ui.packages.uploadButton":"Carregar Packages","ui.packages.uploadMessage":"Tem um carregamento não confirmado. | Tem {count} uploads não confirmados.","ui.packages.uploadApply":"Confirmar Uploads","ui.packages.uploadReset":"Apagar Uploads","ui.packages.uploadIncomplete":"Este ficheiro não foi uploaded completamente. Por favor remova-o e tente novamente.","ui.packages.uploadDuplicate":"Este ficheiro aparenta ter sido uploaded  várias vezes. Por favor remova os duplicados.","ui.packages.uploadInstalled":"Este ficheiro já se encontra instalado. Por favor remova os duplicados.","ui.packages.uploadUnsupported":"Uploads are not supported in your installation. Please make sure that the PHP ZIP extension is installed and update your dependencies.","ui.packages.changesMessage":"Tem uma alteração não confirmada. | Tem {count} alterações não confirmadas.","ui.packages.changesDryrun":"Dry Run","ui.packages.changesApply":"Aplicar Alterações","ui.packages.changesApplyAll":"Actualizar todos os pacotes","ui.packages.changesDryrunAll":"Funcionamento a seco todos os pacotes","ui.packages.changesReset":"Reverter Alterações","ui.packages.changesReview":"Rever Alterações","ui.packagelist.loading":"A Carregar ...","ui.packagelist.uploads":"Uploads","ui.packagelist.added":"Novos pacotes","ui.packagelist.installed":"Pacotes instalados","ui.package.hintRevert":"Reverter Alterações","ui.package.hintNoupdate":"Não actualizar","ui.package.hintConstraint":" Este pacote será instalado com limitações de entrada {constraint} quando aplicar alterações.","ui.package.hintConstraintBest":"Este pacote será instalado com a melhor versão disponível quando aplicar alterações.","ui.package.hintConstraintChange":"As limitações de entrada para este pacote serão alteradas de \\"{from}\\" para \\"{to}\\" quando  aplicar alterações.","ui.package.hintConstraintUpdate":"Este pacote será actualizado quando aplicar alterações. ","ui.package.hintAdded":"Este pacote vai ser instalado quando aplicar as alterações.","ui.package.hintRemoved":"Este pacote será removido quando aplicar alterações.","ui.package.requiredTitle":"manualmente adicionado","ui.package.requiredText":"Este pacote é requerido pelo seu composer.json mas não está instalado.","ui.package.removedTitle":"manualmente removido","ui.package.removedText":"Este pacote vai ser removido do seu composer.json.","ui.package.installed":"Actualmente instalado:","ui.package.version":"Versão {version}","ui.package.additionalDownloads":"{count} Descarregar | {count} Descarregar","ui.package.additionalStars":"{count} Estrela | {count} Estrelas","ui.package.editConstraint":"Editar","ui.package.uploadConstraint":"Esta restrição está definida pelo pacote que foi uploaded.","ui.package.updateButton":"Actualizar","ui.package.removeButton":"Remover","ui.package.installButton":"Adicionar Pacote","ui.package.installButtonShort":"Adicionar","ui.package.detailsButton":"Detalhes","ui.package.latestConstraint":"versão mais recente","ui.package.update":"Actualização disponível","ui.package.updateLatest":"versão mais recente","ui.package.updateAvailable":"{version} disponível","ui.package.updateUnknown":"versão desconhecida","ui.package.updateConstraint":"A newer version outside your version constraint is available.","ui.package.incompatible":"{package} does not work with Contao {constraint}.","ui.package.incompatibleWarning":"{package} does not work with Contao {constraint} in any of its stable releases. Do you want to add the package and set a version constraint to try installing a development branch?","ui.package.incompatibleConstraint":"This package does not have a stable release for Contao {constraint}. Set a version constraint to try installing a development branch.","ui.package.incompatibleButton":"Instalar","ui.cloudStatus.headline":"Composer Resolver Cloud","ui.cloudStatus.version":"Versão {version}","ui.cloudStatus.waitingTime":"Tempo de Espera","ui.cloudStatus.jobs":"Tarefas Actuais","ui.cloudStatus.workers":"Trabalhadores","ui.cloudStatus.approx":"{minutes} min","ui.cloudStatus.none":"nenhum","ui.cloudStatus.short":"ca. {minutes} min","ui.cloudStatus.long":"ca. {minutes} min {seconds} seg","ui.cloudStatus.error":"Incapaz de obter o estatuto de Composer Resolver Cloud. Pode ser para questões de manutenção ou de experiência.","ui.cloudStatus.button":"Estado das nuvens","ui.cloudStatus.refresh":"Actualizar o estado das nuvens","ui.log-viewer.loading":"A Carregar ...","ui.log-viewer.empty":"There are no log files on your server.","ui.log-viewer.reload":"Reload","ui.log-viewer.file":"Log file","ui.log-viewer.channel":"Channel","ui.log-viewer.channelTitle":"The channel this message was logged to.","ui.log-viewer.level":"Level","ui.log-viewer.levelTitle":"Severity of the log message.","ui.log-viewer.timeHeader":"Time","ui.log-viewer.messageHeader":"Message","ui.log-viewer.showContext":"Show Context","ui.log-viewer.hideContext":"Hide Context","ui.log-viewer.showExtra":"Show Extra","ui.log-viewer.hideExtra":"Hide Extra","ui.log-viewer.more":"Load more …","ui.log-viewer.download":"Download","ui.log-viewer.downloadTitle":"Download file \\"{file}\\"","ui.log-viewer.prodEnvironment":"Production Environment","ui.log-viewer.devEnvironment":"Development Environment (Debug Mode)","ui.user-manager.loading":"Loading users …","ui.user-manager.changePassword":"Change Password","ui.user-manager.setupTotp":"Setup Two-Factor Authentication","ui.user-manager.disableTotp":"Disable Two-Factor Authentication","ui.user-manager.invite":"Invite User","ui.user-manager.delete":"Delete","ui.user-manager.deleteConfirm":"Do you really want to delete user \\"{username}\\"?","ui.user-manager.deleted":"User {username} deleted successfully","ui.user-manager.passwordHeadline":"Change Password","ui.user-manager.passwordText":"To change your password, please enter the current and a new password in the respective fields.","ui.user-manager.currentPassword":"Current password","ui.user-manager.newPassword":"New password","ui.user-manager.passwordPlaceholder":"min. 8 caracteres","ui.user-manager.submitPassword":"Submit","ui.user-manager.passwordChanged":"Your password has been changed successfully.","ui.user-manager.passwordError":"This password is incorrect.","ui.user-manager.inviteHeadline":"Invite User","ui.user-manager.inviteText":"If you need multiple logins for the Contao Manager, you can create an invitation link here. Share this link with someone or use it on another device to create a new account with the given permissions.","ui.user-manager.inviteSuccess1":"A new invitation link was created. The URL below can be used to create a new user account for this Contao Manager. The invitation expires on {expires} (one week from now).","ui.user-manager.inviteSuccess2":"Please copy the link to your clipboard. It will only work once and you will not be able to see it again after closing this dialog.","ui.user-manager.createInvitation":"Create Invitation Link","ui.user-manager.clipboard":"Copy to clipboard","ui.user-manager.permissions":"Learn about permissions","ui.user-manager.cancel":"Cancelar","ui.user-manager.close":"Fechar","ui.user-manager.you":"You","ui.user-manager.2fa":"2FA","ui.user-manager.2faEnabled":"This account is secured by two-factor authentication.","ui.user-manager.2faDisabled":"This account is insecure due to missing two-factor authentication.","ui.user-manager.passkey":"Passkey","ui.user-manager.passkeyTitle":"This account is secured by a Passkey.","ui.totp.headline":"Two-Factor Authentication","ui.totp.setupQr":"Please scan the QR code with your 2FA/TOTP app.","ui.totp.setupCode":"If you cannot scan the QR code, enter this key instead:","ui.totp.codeLabel":"Verification code","ui.totp.codeDescription":"Please enter the verification code generated by your 2FA/TOTP app.","ui.totp.disableText":"Please enter the verification code to disable two-factor authentication.","ui.totp.invalid":"The verification code is invalid.","ui.totp.enable":"Activar","ui.totp.disable":"Desactivar","ui.totp.cancel":"Cancelar","ui.totp.enabled":"Two-factor authentication was enabled successfully.","ui.totp.disabled":"Two-factor authentication was disabled successfully.","ui.totp.setup":"Setup Two-Factor Authentication","ui.totp.skip":"Skip Two-Factor Authentication"}')}}]);"use strict";(self["webpackChunkcontao_manager"]=self["webpackChunkcontao_manager"]||[]).push([[312],{3312:function(a,e,t){t.r(e),t.d(e,{default:function(){return Pa}});var s=t(641),n=t(33);const i={class:"package-popup__installed"},l=["dateTime","title"],o=["href"],p={key:3},c={class:"package-popup__update"},r={class:"package-popup__incompatible"};function u(a,e,t,u,d,k){const g=(0,s.g2)("package-constraint"),m=(0,s.g2)("install-button"),h=(0,s.g2)("package-details",!0);return(0,s.uX)(),(0,s.Wv)(h,{local:k.data,dependents:k.dependents},(0,s.eX)({"package-actions":(0,s.k6)(()=>[(0,s.RG)(a.$slots,"package-actions",{},()=>[a.isInstalled?((0,s.uX)(),(0,s.CE)(s.FK,{key:0},[!a.isFeature&&a.isVisible?((0,s.uX)(),(0,s.Wv)(g,{key:0,data:k.data},null,8,["data"])):(0,s.Q3)("",!0),(0,s.Lk)("p",i,[(0,s.Lk)("strong",null,(0,n.v_)(a.$t("ui.package.installed")),1),a.installedTime?((0,s.uX)(),(0,s.CE)("time",{key:0,dateTime:a.installedTime,title:k.datimFormat(a.installedTime)},(0,n.v_)(a.$t("ui.package.version",{version:a.installedVersion})),9,l)):((0,s.uX)(),(0,s.CE)(s.FK,{key:1},[(0,s.eW)((0,n.v_)(a.$t("ui.package.version",{version:a.installedVersion})),1)],64))])],64)):a.canBeInstalled&&a.isCompatible||a.isAdded||a.isRequired?((0,s.uX)(),(0,s.CE)(s.FK,{key:1},[(0,s.bF)(m,{data:k.data},null,8,["data"]),a.isAdded||a.isRequired?((0,s.uX)(),(0,s.Wv)(g,{key:0,data:k.data},null,8,["data"])):(0,s.Q3)("",!0)],64)):a.isPrivate?((0,s.uX)(),(0,s.CE)("a",{key:2,class:"widget-button widget-button--primary widget-button--link",target:"_blank",href:a.metadata.homepage},(0,n.v_)(a.$t("ui.package.homepage")),9,o)):((0,s.uX)(),(0,s.CE)("div",p))])]),"suggest-actions":(0,s.k6)(({name:e})=>[a.packageSuggested(e)?((0,s.uX)(),(0,s.Wv)(m,{key:0,inline:"",small:"",data:{name:e}},null,8,["data"])):(0,s.Q3)("",!0)]),"features-actions":(0,s.k6)(({name:e})=>[!a.hasRoot||a.packageInstalled(e)||a.packageRoot(e)?(0,s.Q3)("",!0):((0,s.uX)(),(0,s.Wv)(m,{key:0,inline:"",small:"",data:{name:e}},null,8,["data"]))]),_:2},[a.metadata.update&&a.metadata.update.valid&&!a.metadata.update.latest?{name:"package-update",fn:(0,s.k6)(()=>[(0,s.Lk)("p",c,[(0,s.Lk)("strong",null,(0,n.v_)(a.$t("ui.package.update"))+":",1),(0,s.eW)(" "+(0,n.v_)(a.$t("ui.package.version",{version:a.metadata.update.version}))+" ("+(0,n.v_)(a.$t("ui.package-details.released"))+" "+(0,n.v_)(k.datimFormat(a.metadata.update.time,"short","long"))+") ",1)])]),key:"0"}:a.isInstalled||a.isCompatible?void 0:{name:"package-update",fn:(0,s.k6)(()=>[(0,s.Lk)("p",r,[(0,s.eW)((0,n.v_)(a.$t("ui.package.incompatible",{package:k.data.name,constraint:a.packageConstraint("contao/manager-bundle")}))+" ",1),!a.canBeInstalled||a.isRootInstalled||a.isAdded||a.isRequired?(0,s.Q3)("",!0):((0,s.uX)(),(0,s.CE)("button",{key:0,type:"button",class:"widget-button widget-button--small widget-button--transparent widget-button--add",onClick:e[0]||(e[0]=(...e)=>a.install&&a.install(...e))},(0,n.v_)(a.$t("ui.package.incompatibleButton")),1))])]),key:"1"}]),1032,["local","dependents"])}t(4423),t(8111),t(7588);var d=t(6278),k=t(4210),g=t(8200);const m={class:"package-popup__headline"},h=["title"],_=["title"],v={key:0,class:"package-popup__loader"},b={class:"package-popup__summary"},f={class:"package-popup__text"},y={class:"package-popup__title"},$={key:0,class:"package-popup__authors"},C=["href"],X={class:"package-popup__statistics"},E=["title"],L={key:1,class:"package-popup__stats package-popup__stats--updated"},w={key:2,class:"package-popup__stats package-popup__stats--downloads"},F={key:3,class:"package-popup__stats package-popup__stats--favers"},A={class:"package-popup__actions"},W=["href"],Q=["href"],T={class:"package-popup__tabs"},x={class:"package-popup__tabs-list"},R={key:0,class:"package-popup__abandoned"},q={key:2},I={key:3},P={key:4},B={class:"package-popup__description"};function G(a,e,t,i,l,o){const p=(0,s.g2)("loading-spinner"),c=(0,s.g2)("package-logo"),r=(0,s.g2)("more-links"),u=(0,s.g2)("details-tab"),d=(0,s.g2)("router-link"),k=(0,s.g2)("i18n-t"),g=(0,s.g2)("package-funding"),G=(0,s.g2)("details-content"),O=(0,s.g2)("popup-overlay");return(0,s.uX)(),(0,s.Wv)(O,{fixed:!0,"popup-class":"package-popup",tabindex:"-1",onClear:e[8]||(e[8]=e=>a.clearCurrent())},{content:(0,s.k6)(()=>[(0,s.Lk)("div",m,[a.hasPrevious?((0,s.uX)(),(0,s.CE)("button",{key:0,class:"package-popup__button package-popup__button--previous",title:a.$t("ui.package-details.previous"),onClick:e[0]||(e[0]=e=>a.$router.go(-1))},[...e[9]||(e[9]=[(0,s.Lk)("svg",{xmlns:"http://www.w3.org/2000/svg",fill:"#fff",width:"24",height:"24",viewBox:"0 0 24 24"},[(0,s.Lk)("path",{d:"M0 0h24v24H0z",fill:"none"}),(0,s.Lk)("path",{d:"M21 11H6.83l3.58-3.59L9 6l-6 6 6 6 1.41-1.41L6.83 13H21z"})],-1)])],8,h)):(0,s.Q3)("",!0),(0,s.eW)(" "+(0,n.v_)(o.data.name)+" ",1),(0,s.Lk)("button",{class:"package-popup__button package-popup__button--close",title:a.$t("ui.package-details.close"),onClick:e[1]||(e[1]=e=>a.clearCurrent())},[...e[10]||(e[10]=[(0,s.Lk)("svg",{height:"24",viewBox:"0 0 24 24",width:"24",fill:"#fff",xmlns:"http://www.w3.org/2000/svg"},[(0,s.Lk)("path",{d:"M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z"}),(0,s.Lk)("path",{d:"M0 0h24v24H0z",fill:"none"})],-1)])],8,_)]),a.metadata&&a.metadata.hasOwnProperty("name")?((0,s.uX)(),(0,s.CE)(s.FK,{key:1},[(0,s.Lk)("div",b,[(0,s.bF)(c,{class:"package-popup__logo","component-class":"package-popup__icon",src:a.metadata.logo},null,8,["src"]),(0,s.Lk)("div",f,[(0,s.Lk)("h1",y,(0,n.v_)(a.metadata.title||o.data.name),1),o.authors?((0,s.uX)(),(0,s.CE)("p",$,[(0,s.eW)((0,n.v_)(a.$t("ui.package-details.authors"))+" ",1),((0,s.uX)(!0),(0,s.CE)(s.FK,null,(0,s.pI)(o.authors,(a,e)=>((0,s.uX)(),(0,s.CE)(s.FK,null,[a.homepage?((0,s.uX)(),(0,s.CE)("a",{class:"package-popup__author",key:e,href:a.homepage,target:"_blank",rel:"noreferrer noopener"},(0,n.v_)(a.name),9,C)):((0,s.uX)(),(0,s.CE)("span",{class:"package-popup__author",key:e},(0,n.v_)(a.name),1))],64))),256))])):(0,s.Q3)("",!0),(0,s.Lk)("p",X,[a.metadata.private?((0,s.uX)(),(0,s.CE)("span",{key:0,class:"package-popup__stats package-popup__stats--private",title:a.$t("ui.package.privateTitle")},(0,n.v_)(a.$t("ui.package.private")),9,E)):(0,s.Q3)("",!0),a.metadata.updated?((0,s.uX)(),(0,s.CE)("span",L,(0,n.v_)(o.datimFormat(a.metadata.updated,!1)),1)):(0,s.Q3)("",!0),a.metadata.downloads>0?((0,s.uX)(),(0,s.CE)("span",w,(0,n.v_)(o.numberFormat(a.metadata.downloads)),1)):(0,s.Q3)("",!0),a.metadata.favers>0?((0,s.uX)(),(0,s.CE)("span",F,(0,n.v_)(o.numberFormat(a.metadata.favers)),1)):(0,s.Q3)("",!0),(0,s.bF)(r,{name:a.metadata.name,homepage:a.metadata.homepage,support:Object.assign({},a.metadata.support),metadata:a.metadata.metadata,"hide-packagist":a.metadata.private},null,8,["name","homepage","support","metadata","hide-packagist"])])]),(0,s.Lk)("div",A,[(0,s.RG)(a.$slots,"package-actions",(0,n._B)((0,s.Ng)({data:a.metadata})),()=>[a.metadata&&a.metadata.homepage?((0,s.uX)(),(0,s.CE)("a",{key:0,class:"widget-button widget-button--primary widget-button--link",target:"_blank",href:a.metadata.homepage},(0,n.v_)(a.$t("ui.package.homepage")),9,W)):a.metadata.private?(0,s.Q3)("",!0):((0,s.uX)(),(0,s.CE)("a",{key:1,class:"widget-button widget-button--primary widget-button--link",target:"_blank",href:`https://packagist.org/packages/${o.data.name}`},(0,n.v_)(a.$t("ui.package-details.packagist")),9,Q))])])]),(0,s.Lk)("div",T,[(0,s.Lk)("ul",x,[(0,s.bF)(u,{"show-empty":"",links:!1,active:""===o.tab,onClick:e[2]||(e[2]=a=>o.setTab(""))},{default:(0,s.k6)(()=>[(0,s.eW)((0,n.v_)(a.$t("ui.package-details.tabDescription")),1)]),_:1},8,["active"]),a.metadata.features?((0,s.uX)(),(0,s.Wv)(u,{key:0,highlight:"",links:a.metadata.features,active:"features"===o.tab,onClick:e[3]||(e[3]=a=>o.setTab("features"))},{default:(0,s.k6)(()=>[(0,s.eW)((0,n.v_)(a.$t("ui.package-details.tabFeatures")),1)]),_:1},8,["links","active"])):(0,s.Q3)("",!0),(0,s.bF)(u,{highlight:"",active:"suggest"===o.tab,links:a.metadata.suggest,onClick:e[4]||(e[4]=a=>o.setTab("suggest"))},{default:(0,s.k6)(()=>[(0,s.eW)((0,n.v_)(a.$t("ui.package-details.tabSuggest")),1)]),_:1},8,["active","links"]),(0,s.bF)(u,{"show-empty":"",active:"require"===o.tab,links:a.metadata.require,onClick:e[5]||(e[5]=a=>o.setTab("require"))},{default:(0,s.k6)(()=>[(0,s.eW)((0,n.v_)(a.$t("ui.package-details.tabRequire")),1)]),_:1},8,["active","links"]),(0,s.bF)(u,{"show-empty":"",active:"conflict"===o.tab,links:a.metadata.conflict,onClick:e[6]||(e[6]=a=>o.setTab("conflict"))},{default:(0,s.k6)(()=>[(0,s.eW)((0,n.v_)(a.$t("ui.package-details.tabConflict")),1)]),_:1},8,["active","links"]),t.dependents?((0,s.uX)(),(0,s.Wv)(u,{key:1,active:"dependents"===o.tab,links:t.dependents,onClick:e[7]||(e[7]=a=>o.setTab("dependents"))},{default:(0,s.k6)(()=>[(0,s.eW)((0,n.v_)(a.$t("ui.package-details.tabDependents")),1)]),_:1},8,["active","links"])):(0,s.Q3)("",!0)])]),(0,s.bF)(G,{active:""===o.tab},{default:(0,s.k6)(()=>[a.metadata.abandoned?((0,s.uX)(),(0,s.CE)("div",R,[!0===a.metadata.abandoned?((0,s.uX)(),(0,s.CE)(s.FK,{key:0},[(0,s.eW)((0,n.v_)(a.$t("ui.package.abandonedText")),1)],64)):((0,s.uX)(),(0,s.Wv)(k,{key:1,keypath:"ui.package.abandonedReplace"},{replacement:(0,s.k6)(()=>[(0,s.bF)(d,{to:{query:{p:a.metadata.abandoned}}},{default:(0,s.k6)(()=>[(0,s.eW)((0,n.v_)(a.metadata.abandoned),1)]),_:1},8,["to"])]),_:1}))])):(0,s.Q3)("",!0),a.metadata.funding?((0,s.uX)(),(0,s.Wv)(g,{key:1,class:"package-popup__funding",items:a.metadata.funding},null,8,["items"])):(0,s.Q3)("",!0),(0,s.RG)(a.$slots,"package-update"),a.metadata.contaoVersions?((0,s.uX)(),(0,s.CE)("p",q,[(0,s.Lk)("strong",null,(0,n.v_)(a.$t("ui.package-details.contaoVersions"))+":",1),(0,s.eW)(" "+(0,n.v_)(a.metadata.contaoVersions.join(", ")),1)])):(0,s.Q3)("",!0),a.metadata.latest?((0,s.uX)(),(0,s.CE)("p",I,[(0,s.Lk)("strong",null,(0,n.v_)(a.$t("ui.package-details.latest"))+":",1),(0,s.eW)(" "+(0,n.v_)(a.metadata.latest.version)+" ("+(0,n.v_)(a.$t("ui.package-details.released"))+" "+(0,n.v_)(o.datimFormat(a.metadata.latest.time,"short","long"))+")",1)])):(0,s.Q3)("",!0),a.metadata.license?((0,s.uX)(),(0,s.CE)("p",P,[(0,s.Lk)("strong",null,(0,n.v_)(a.$t("ui.package-details.license"))+":",1),(0,s.eW)(" "+(0,n.v_)(o.license),1)])):(0,s.Q3)("",!0),(0,s.Lk)("p",B,(0,n.v_)(a.metadata.description),1)]),_:3},8,["active"]),a.metadata.features?((0,s.uX)(),(0,s.Wv)(G,{key:0,active:"features"===o.tab,links:a.metadata.features},{actions:(0,s.k6)(({name:e})=>[(0,s.RG)(a.$slots,"features-actions",(0,n._B)((0,s.Ng)({name:e})))]),_:3},8,["active","links"])):(0,s.Q3)("",!0),(0,s.bF)(G,{active:"suggest"===o.tab,links:a.metadata.suggest},{actions:(0,s.k6)(({name:e})=>[(0,s.RG)(a.$slots,"suggest-actions",(0,n._B)((0,s.Ng)({name:e})))]),_:3},8,["active","links"]),(0,s.bF)(G,{active:"require"===o.tab,links:a.metadata.require},{actions:(0,s.k6)(({name:e})=>[(0,s.RG)(a.$slots,"require-actions",(0,n._B)((0,s.Ng)({name:e})))]),_:3},8,["active","links"]),(0,s.bF)(G,{active:"conflict"===o.tab,links:a.metadata.conflict},{actions:(0,s.k6)(({name:e})=>[(0,s.RG)(a.$slots,"conflict-actions",(0,n._B)((0,s.Ng)({name:e})))]),_:3},8,["active","links"]),t.dependents?((0,s.uX)(),(0,s.Wv)(G,{key:1,active:"dependents"===o.tab,links:t.dependents},{actions:(0,s.k6)(({name:e})=>[(0,s.RG)(a.$slots,"dependents-actions",(0,n._B)((0,s.Ng)({name:e})))]),_:3},8,["active","links"])):(0,s.Q3)("",!0)],64)):((0,s.uX)(),(0,s.CE)("div",v,[(0,s.bF)(p,{horizontal:""}),(0,s.Lk)("p",null,(0,n.v_)(a.$t("ui.package-details.loading")),1)]))]),_:3})}var O=t(9376),S=t(416),j=t(266),K=t(7423),V=t(9045);const D={key:0,class:"link-more"};function H(a,e,t,i,l,o){const p=(0,s.g2)("link-menu");return o.linkItems.length?((0,s.uX)(),(0,s.CE)("div",D,[(0,s.Lk)("button",{onClick:e[0]||(e[0]=(...a)=>o.toggle&&o.toggle(...a))},(0,n.v_)(a.$t("ui.package-details.more")),1),a.visible?((0,s.uX)(),(0,s.CE)("div",{key:0,ref:"menu",class:"link-more__menu",tabindex:"-1",onFocusout:e[1]||(e[1]=(...a)=>o.close&&o.close(...a)),onClick:e[2]||(e[2]=(...a)=>o.close&&o.close(...a))},[(0,s.bF)(p,{items:o.linkItems,color:"contao"},null,8,["items"])],544)):(0,s.Q3)("",!0)])):(0,s.Q3)("",!0)}var M=t(4758),N={components:{LinkMenu:M.A},props:{name:String,homepage:String,support:Object,metadata:String,hidePackagist:Boolean},data:()=>({visible:!1}),computed:{linkItems(){const a=[];return this.homepage&&a.push({label:this.$t("ui.package.homepage"),href:this.homepage,target:"_blank"}),this.name&&!this.hidePackagist&&a.push({label:this.$t("ui.package-details.packagist"),href:`https://packagist.org/packages/${this.name}`,target:"_blank"}),this.support&&Object.keys(this.support).forEach(e=>{const t=`ui.package-details.support_${e}`;let s=this.$t(`ui.package-details.support_${e}`);s===t&&(s=e),"email"===e?a.push({label:s,href:`mailto:${this.support[e]}`}):a.push({label:s,href:this.support[e],target:"_blank"})}),this.metadata&&a.push({label:this.$t("ui.package-details.metadata"),href:this.metadata,target:"_blank"}),a}},methods:{open(){this.visible=!0,setTimeout(()=>this.$refs.menu?.focus(),0)},close(a){a&&this.$refs.menu?.contains(a.relatedTarget)||(this.$refs.menu.blur(),setTimeout(()=>{this.visible=!1},100))},toggle(){this.visible?this.close():this.open()}}},z=t(6262);const U=(0,z.A)(N,[["render",H]]);var Y=U;const J=["disabled"];function Z(a,e,t,i,l,o){return t.showEmpty||o.count>0?((0,s.uX)(),(0,s.CE)("li",{key:0,class:(0,n.C4)(["package-popup__tab",{"package-popup__tab--active":t.active}])},[(0,s.Lk)("button",{onClick:e[0]||(e[0]=e=>a.$emit("click")),disabled:0===o.count&&!1!==t.links},[(0,s.RG)(a.$slots,"default"),!1!==t.links?((0,s.uX)(),(0,s.CE)("span",{key:0,class:(0,n.C4)({"package-popup__pill":!0,"package-popup__pill--highlight":t.highlight&&o.count>0})},(0,n.v_)(o.count),3)):(0,s.Q3)("",!0)],8,J)],2)):(0,s.Q3)("",!0)}var aa={emits:["click"],props:{active:Boolean,showEmpty:Boolean,highlight:Boolean,links:[Object,Array,Boolean]},computed:{count(){return this.links?this.links instanceof Array?this.links.length:Object.values(this.links).length:0}}};const ea=(0,z.A)(aa,[["render",Z]]);var ta=ea,sa=t(3751);const na={class:"package-popup__tabcontent",tabindex:"-1"},ia={key:0,class:"package-popup__packagelist"};function la(a,e,t,n,i,l){const o=(0,s.g2)("package-link");return(0,s.bo)(((0,s.uX)(),(0,s.CE)("div",na,[(0,s.RG)(a.$slots,"default",{},()=>[t.links?((0,s.uX)(),(0,s.CE)("div",ia,[((0,s.uX)(!0),(0,s.CE)(s.FK,null,(0,s.pI)(l.iterableLinks,(e,t)=>(0,s.RG)(a.$slots,"links",(0,s.v6)({ref_for:!0},{name:t,text:e}),()=>[((0,s.uX)(),(0,s.Wv)(o,{name:t,key:t,text:e},{default:(0,s.k6)(()=>[(0,s.RG)(a.$slots,"actions",(0,s.v6)({ref_for:!0},{name:t}))]),_:2},1032,["name","text"]))])),256))])):(0,s.Q3)("",!0)])],512)),[[sa.aG,t.active]])}const oa={class:"package-link__details"},pa=["title"],ca={class:"package-link__text"},ra={class:"package-link__actions"};function ua(a,e,t,i,l,o){const p=(0,s.g2)("details-button");return(0,s.uX)(),(0,s.CE)("article",{class:(0,n.C4)(["package-link",{"package-link--limit":!t.text}])},[(0,s.Lk)("div",oa,[(0,s.Lk)("p",{class:"package-link__name",title:t.name},(0,n.v_)(a.metadata&&a.metadata.title||t.name),9,pa),(0,s.Lk)("p",ca,(0,n.v_)(t.text||a.metadata&&a.metadata.description),1)]),(0,s.Lk)("div",ra,[(0,s.RG)(a.$slots,"default"),(0,s.bF)(p,{small:"",name:t.name},null,8,["name"])])],2)}var da=t(9071),ka={mixins:[S.A],components:{DetailsButton:da.A},props:{name:String,text:String},computed:{data:a=>({name:a.name})}};const ga=(0,z.A)(ka,[["render",ua]]);var ma=ga,ha={components:{PackageLink:ma},props:{active:Boolean,links:[Object,Array]},computed:{iterableLinks(){if(this.links instanceof Array){const a={};return this.links.forEach(e=>{a[e]=null}),a}return this.links}},watch:{active(){setTimeout(()=>{this.$el.focus()},0)}}};const _a=(0,z.A)(ha,[["render",la]]);var va=_a,ba=t(1687);const fa={key:0,class:"package-funding"},ya=["href"],$a=["href"],Ca=["href"],Xa=["href"],Ea=["href"];function La(a,e,t,i,l,o){return t.items&&t.items.length?((0,s.uX)(),(0,s.CE)("div",fa,[(0,s.Lk)("div",null,[(0,s.Lk)("span",null,(0,n.v_)(a.$t("ui.package-details.funding")),1),((0,s.uX)(!0),(0,s.CE)(s.FK,null,(0,s.pI)(t.items,(a,e)=>((0,s.uX)(),(0,s.CE)(s.FK,null,["github"===a.type?((0,s.uX)(),(0,s.CE)("a",{href:o.githubUrl(a),target:"_blank",rel:"noreferrer noopener",key:e},"GitHub",8,ya)):"tidelift"===a.type?((0,s.uX)(),(0,s.CE)("a",{href:a.url,target:"_blank",rel:"noreferrer noopener",key:e},"Tidelift",8,$a)):"patreon"===a.type?((0,s.uX)(),(0,s.CE)("a",{href:a.url,target:"_blank",rel:"noreferrer noopener",key:e},"Patreon",8,Ca)):"opencollective"===a.type?((0,s.uX)(),(0,s.CE)("a",{href:a.url,target:"_blank",rel:"noreferrer noopener",key:e},"OpenCollective",8,Xa)):((0,s.uX)(),(0,s.CE)("a",{href:a.url,target:"_blank",rel:"noreferrer noopener",key:e},(0,n.v_)(a.url.replace(/^https?:\/\/(www.)?([^/]+).*$/,"$2")),9,Ea))],64))),256))])])):(0,s.Q3)("",!0)}var wa={name:"PackageFunding",props:{items:{type:Array,required:!0}},computed:{githubUrl:()=>a=>a.url.replace(/^https:\/\/github.com\/([^/]+)$/,"https://github.com/sponsors/$1")}};const Fa=(0,z.A)(wa,[["render",La],["__scopeId","data-v-5a8fd14b"]]);var Aa=Fa,Wa={mixins:[S.A],components:{PopupOverlay:ba.A,MoreLinks:Y,LoadingSpinner:V.A,PackageLogo:K.A,PackageFunding:Aa,DetailsTab:ta,DetailsContent:va},props:{local:{type:Object},dependents:{type:Object}},data:()=>({appTitle:"",links:[],hasPrevious:!1}),computed:{current:a=>a.$route.query.p,tab:a=>String(a.$route.hash).substring(1),exists:a=>a.metadata,data:a=>a.local||{name:a.current},authors:a=>a.metadata.authors&&a.metadata.authors.length?a.metadata.authors.filter(a=>!!a.name):null,license:a=>a.metadata.license?a.metadata.license instanceof Array?a.metadata.license.join(", "):a.metadata.license:"–",contaoVersions:a=>a.metadata.contaoVersions||null},methods:{datimFormat:k.A,numberFormat:j.A,...(0,d.PY)("packages/details",["clearCurrent"]),setTab(a){this.$router.replace({query:this.$route.query,hash:`#${a}`,append:!0})},updatePage(){let a=`${this.current} - ${this.appTitle}`,e="";this.metadata&&(this.metadata.title&&(a=`${this.metadata.title} (${this.current}) - ${this.appTitle}`),e=this.metadata.description||""),document.title=a,document.head.querySelector('meta[name="description"]').setAttribute("content",e)},addLink(a,e,t=null){const s=new URL(location.pathname,location);s.search=a;const n=document.createElement("link");n.setAttribute("rel",e),n.setAttribute("href",s.toString()),t&&n.setAttribute("hrefLang",t),document.head.appendChild(n),this.links.push(n)}},watch:{current(){this.updatePage(),this.hasPrevious=/[?&]p=/.test(window.history.state?.back)},exists(a){a||this.clearCurrent()},metadata(){this.updatePage()}},created(){this.appTitle=document.title},mounted(){document.head.querySelector('meta[name="robots"]').setAttribute("content","index,follow"),this.updatePage(),this.addLink(`?p=${this.current}&_locale=${this.$i18n.locale}`,"canonical"),Object.keys(O.A).forEach(a=>{this.addLink(`?p=${this.current}&_locale=${a}`,"alternate",a)})},beforeUnmount(){document.title=this.appTitle,document.head.querySelector('meta[name="description"]').setAttribute("content",""),this.links.forEach(a=>{document.head.removeChild(a)})}};const Qa=(0,z.A)(Wa,[["render",G]]);var Ta=Qa,xa=t(8875),Ra=t(4290),qa={mixins:[g.A],components:{PackageConstraint:Ra.A,PackageDetails:Ta,InstallButton:xa.A},computed:{...(0,d.aH)("packages",{allInstalled:"installed"}),...(0,d.L8)("packages",["packageConstraint"]),current:a=>a.$route.query.p,data:a=>a.add[a.current]||a.allInstalled&&a.allInstalled[a.current]||{name:a.current},dependents(){if(!this.allInstalled||!this.allInstalled[this.data.name]?.dependents)return null;const a={},e=["requires","replaces","provides","conflicts"];return Object.values(this.allInstalled[this.data.name].dependents).forEach(t=>{if("__root__"===t.source||!e.includes(t.description)||t.source===this.data.name&&"replaces"===t.description)return;const s=this.$t(`ui.package-details.link${t.description[0].toUpperCase()}${t.description.slice(1)}`);let n=t.target;n===this.data.name&&this.metadata&&this.metadata.title&&(n=this.metadata.title),a[t.source]=`${s} ${n} ${t.constraint}`}),a}},methods:{datimFormat:k.A}};const Ia=(0,z.A)(qa,[["render",u]]);var Pa=Ia}}]);"use strict";(self["webpackChunkcontao_manager"]=self["webpackChunkcontao_manager"]||[]).push([[669],{9669:function(e){e.exports=JSON.parse('{"ui.app.title":"افزونه‌های کنتائو","ui.app.loading":"بارگذاری لیست افزونه...","ui.app.language":"Switch language for the Contao Manager","ui.app.colorDark":"Dark Mode","ui.app.colorDarkTitle":"Switch color scheme to dark","ui.app.colorLight":"Light Mode","ui.app.colorLightTitle":"Switch color scheme to light","ui.discover.advertisement":"Advertisement in the extension list","ui.discover.loading":"بارگذاری ...","ui.discover.offline":"Could not fetch any results.","ui.discover.offlineExplain":"Check your internet connection and disable JavaScript blockers in your browser.","ui.discover.offlineButton":"دوباره تلاش کنید","ui.discover.searchPlaceholder":"Search in {count} extensions …","ui.discover.empty":"هیچ نتیجه‌ای برای {query}","ui.discover.more":"نتایج بیشتر","ui.discover.sortBy":"مرتب‌سازی براساس","ui.discover.sortReleased":"Released","ui.discover.sortReleasedTitle":"Sort results by release date","ui.discover.sortLatest":"بروزرسانی شده","ui.discover.sortLatestTitle":"Sort results by last updated","ui.discover.sortDownloads":"دانلودها","ui.discover.sortDownloadsTitle":"Sort results by number of downloads","ui.discover.sortFavers":"امتیاز","ui.discover.sortFaversTitle":"Sort results by rating","ui.discover.detailsButton":"جزئیات","ui.discover.latestPackages":"Latest and updated extensions","ui.discover.faversPackages":"افزونه‌های با امتیاز بالا","ui.discover.downloadsPackages":"Most downloaded extensions","ui.discover.exactHit":"Exact query match","ui.discover.results":"More search results","ui.package.homepage":"وب‌سایت پروژه","ui.package.private":"بسته اختصاصی","ui.package.privateTitle":"Private packages are only available from the vendor (e.g. as a ZIP download). Please visit the website for more information.","ui.package.abandoned":"منع شده","ui.package.abandonedText":"This package is abandoned and no longer maintained.","ui.package.abandonedReplace":"This package is abandoned and no longer maintained. The author suggests using the {replacement} package instead.","ui.package.contaoVersion":"Available for Contao","ui.package-details.previous":"جزئیات افزونه قبلی","ui.package-details.close":"بستن جزئیات افزونه","ui.package-details.loading":"بارگذاری ...","ui.package-details.tabDescription":"توضیح","ui.package-details.tabRequire":"نیازمندی‌ها","ui.package-details.tabFeatures":"ویژگی‌ها","ui.package-details.tabSuggest":"پیشنهادها","ui.package-details.tabConflict":"ناسازگاری‌ها","ui.package-details.tabDependents":"وابسته‌ها","ui.package-details.linkRequires":"نیاز دارد","ui.package-details.linkReplaces":"جایگزین می‌کند","ui.package-details.linkProvides":"فراهم می‌کند","ui.package-details.linkConflicts":"ناسازگار است","ui.package-details.funding":"Fund package maintenance!","ui.package-details.contaoVersions":"Supported Contao version(s)","ui.package-details.latest":"آخرین نسخه","ui.package-details.released":"منتشر شده در","ui.package-details.license":"مجوز(ها)","ui.package-details.authors":"از","ui.package-details.more":"بیشتر","ui.package-details.packagist":"جژئیات بسته","ui.package-details.metadata":"ویرایش فرداده","ui.package-details.support_docs":"مستندات","ui.package-details.support_wiki":"ویکی","ui.package-details.support_forum":"انجمن پشتیبانی","ui.package-details.support_issues":"مشکلات / گزارش باگ","ui.package-details.support_source":"کد منبع","ui.package-details.support_irc":"IRC / چت","ui.package-details.support_email":"ایمیل پشتیبانی","ui.package-details.support_rss":"خوراک RSS"}')}}]);"use strict";(self["webpackChunkcontao_manager"]=self["webpackChunkcontao_manager"]||[]).push([[139],{4139:function(e){e.exports=JSON.parse('{"ui.app.httpsHeadline":"!! اتصال ناامن !!","ui.app.httpsDescription":"Without HTTPS your confidential data will be transferred unencrypted.","ui.app.httpsLink":"اطلاعات بیشتر","ui.app.httpsHref":"https://https.cio.gov/everything/","ui.app.loading":"Loading Contao Manager …","ui.app.apiError":"وضعیت API غیرمنتظره","ui.app.configSecurity1":"SECURITY ALERT !!! Unprotected config directory detected","ui.app.configSecurity2":"The Contao Manager has detected that its config files are publicly accessible. All operations are disabled until the directory is secured, otherwise an attacker could access sensitive data of your installation.\\n\\nTo fix this issue, make sure to prevent access to the \\"contao-manager\\" directory on your server. To learn how to do this, please refer to the manual of your webserver or contact your hosting provider.","ui.account.welcome":"Welcome","ui.account.intro1":"Welcome to the Contao Manager, a universal tool to install and manage Contao Open Source CMS. If you are new to it, please {readTheManualToGetStarted}.","ui.account.introGetStarted":"{readTheManual} to get started","ui.account.introManual":"read the manual","ui.account.intro2":"If you encounter any problems, check {ourGithubIssues} and feel free to create new one for anything that has not been reported yet.","ui.account.introIssues":"our GitHub issues","ui.account.headline":"حساب کاربری","ui.account.description":"To manage your installation, please create an account for the Contao Manager. Be aware that this account is not related to the Contao back end or front end.","ui.account.username":"نام کاربری","ui.account.password":"گذرواژه","ui.account.passwordConfirm":"تایپ مجدد گذرواژه","ui.account.passwordPlaceholder":"حداقل ۸ نویسه","ui.account.passwortLength":"لطفا حداقل ۸ نویسه وارد نمایید.","ui.account.passwortDifferent":"The password does not match the confirmation.","ui.account.submit":"ایجاد حساب","ui.account.contribute1":"Contao and the Contao Manager are sponsored by the non-profit Contao Association.","ui.account.contribute2":"Please consider contributing to open source by {donate}.","ui.account.contributeDonate":"making a donation","ui.login.headline":"ورود","ui.login.description":"برای مدیریت نصب‌تان وارد شوید.","ui.login.username":"نام کاربری","ui.login.password":"گذرواژه","ui.login.forgotPassword":"گذرواژه‌ی خود را فراموش کرده‌اید؟","ui.login.button":"ورود","ui.login.locked":"Access has been denied because the Contao Manager is locked. To unlock, delete the {lockFile} file in your Contao root directory.","ui.logout.headline":"Session Timeout","ui.logout.warning":"Your have been inactive for more than 25 minutes. For security reasons your session will be terminated shortly.","ui.logout.expired":"Your session was automatically terminated because you have been inactive for more than 30 minutes.","ui.logout.renew":"Keep Logged In","ui.logout.logout":"خروج","ui.logout.login":"Back To Login","ui.oauth.error":"Invalid OAuth attempt. Check the request parameters.","ui.oauth.https":"The redirect URI MUST use a secure protocol (https:) to prevent the authentication token from being transmitted in clear-text.","ui.oauth.headline":"Remote Authentication","ui.oauth.description":"The following application or service is requesting remote access to your Contao Manager instance.","ui.oauth.domain":"Before allowing access, make sure you know this URL and trust its owner!","ui.oauth.allow":"Allow Access","ui.oauth.deny":"Deny Access","ui.boot.headline":"System Check","ui.boot.description":"Please wait, we are analyzing your server …","ui.boot.issue1":"Installation Issues Detected","ui.boot.issue2":"Your installation has issues that have to be fixed before the Contao Manager can be used.","ui.boot.run":"Launch Contao Manager","ui.recovery.headline":"System Recovery","ui.recovery.description":"The Contao Manager detected files that look like Contao, but the Command Line Interface does not work as expected.","ui.recovery.console":"Console Output","ui.recovery.repairOptions":"Please choose an option to repair your installation.","ui.recovery.repairHeadline":"Automatic Repair","ui.recovery.repairDescription":"Attempts to automatically repair the installation by rebuilding the application cache and re-installing the Composer packages.","ui.recovery.repairWarning":"Any modifications to the vendor files might be deleted in the process!","ui.recovery.repairFailed":"Automatic repair was not successful. Try the Safe Mode to manually repair the installation.","ui.recovery.repairButton":"Run System Repair","ui.recovery.safeModeHeadline":"Safe Mode","ui.recovery.safeModeDescription":"Launching the Contao Manager in Safe Mode allows to manage packages and run certain maintenance tasks, but features that rely on a working Contao installation will not be available.","ui.recovery.safeModeButton":"Launch in Safe Mode","ui.server.pending":"Waiting …","ui.server.running":"Analyzing …","ui.server.error":"Check failed due to an unexpected response from the server.","ui.server.details":"جزئیات","ui.server.prerequisite":"Check cancelled due to a missing prerequisite.","ui.server.selfUpdate.title":"Updates of Contao Manager","ui.server.selfUpdate.update":"A new Contao Manager version {latest} is available.","ui.server.selfUpdate.manualUpdate":"A new Contao Manager version {latest} is available. Your server does not support automatic updates, please download the new version from {download}.","ui.server.selfUpdate.latest":"You are using the latest version {current}.","ui.server.selfUpdate.dev":"Development builds do not support automatic updates.","ui.server.selfUpdate.unsupported":"A new version is available but it does not support your PHP version.","ui.server.selfUpdate.button":"Run Self-Update","ui.server.selfUpdate.continue":"Continue","ui.server.config.title":"Server Configuration","ui.server.config.setup":"Configure","ui.server.config.change":"Change","ui.server.config.save":"Save","ui.server.config.blankOption":"Please select …","ui.server.config.customOption":"Other …","ui.server.config.description":"To correctly run background tasks, the Contao Manager needs to know where to find the PHP command line binary and how to run commands separated from the web process.","ui.server.config.formTitle":"Server Configuration","ui.server.config.formText":"لطفا مسیر باینری PHP‌ تان را وارد نمایید. مطمئن شوید که باینری همان نسخه‌ی PHP روند وب‌تان باشد.","ui.server.config.cloudTitle":"Composer Resolver Cloud","ui.server.config.cloudText":"The Composer Resolver Cloud allows to install Composer dependencies even if your server does not provide enough local memory. Please be aware that your package information will be transmitted to a cloud server operated by the Contao Association.","ui.server.config.cloud":"Use the Composer Resolver Cloud","ui.server.config.cli":"PHP Binary","ui.server.config.stateErrorCli":"No valid PHP binary was found on the server.","ui.server.config.stateErrorCloud":"The Composer Resolver Cloud is not supported.","ui.server.config.stateSuccess":"PHP binary at {php_cli}.","ui.server.php_web.title":"PHP Web Process","ui.server.php_web.below7":"Found PHP version {version}. Please switch to PHP 7 as soon as possible!","ui.server.php_web.success":"Found PHP version {version}, no known issues found.","ui.server.php_cli.title":"PHP Command Line Interface","ui.server.php_cli.success":"Found PHP version {version}, no known issues found.","ui.server.composer.title":"Composer Environment","ui.server.composer.success":"No known issues found.","ui.server.composer.install":"Composer dependencies are not installed.","ui.server.composer.button":"Run Composer","ui.server.composer.safeMode":"Run Safe Mode","ui.server.contao.title":"نصب کانتائو","ui.server.contao.setup":"Setup","ui.server.contao.empty":"No Contao installation has been found.","ui.server.contao.old":"Contao version {version} is not compatible with the Contao Manager, please update your installation manually.","ui.server.contao.found":"Found Contao {version} (API version {api}).","ui.server.contao.headline":"Contao Setup","ui.server.contao.description":"Welcome to the setup process of your Contao Open Source CMS. You can choose between two versions to install.","ui.server.contao.publicDir":"Use {dir} for public files (for Contao {version})","ui.server.contao.ltsTitle":"Long Term Support","ui.server.contao.ltsText":"The LTS version has an extended support period of up to four years.","ui.server.contao.latestTitle":"Latest","ui.server.contao.latestText":"A new latest version is released every six months in February and August.","ui.server.contao.noLatest":"Requires at least PHP {version}.","ui.server.contao.releaseplan":"See the {contaoReleasePlan} for detailed information.","ui.server.contao.releaseplanLink":"Contao Release Plan","ui.server.contao.formTitle":"نصب کانتائو","ui.server.contao.formText":"نسخه‌ی کانتائو برای نصب را انتخاب کنید.","ui.server.contao.version":"نسخه","ui.server.contao.coreOnly":"Initial Setup","ui.server.contao.coreOnlyNo":"Full Installation (News, Calendar, etc.)","ui.server.contao.coreOnlyYes":"Minimal Installation (Core only)","ui.server.contao.coreOnlyFeatures":"What\'s the difference?","ui.server.contao.noUpdate":"Skip Installation (Expert Only!)","ui.server.contao.install":"Finish","ui.server.docroot.headline":"Webserver Setup","ui.server.docroot.warning":"To install Contao through the Contao Manager, you have to fix the document root on the web server.","ui.server.docroot.description1":"Contao uses a separate folder for public files, application files are installed in its parent folder. Contao cannot be installed right now, because your folder structure is not correct or the folders are not empty.","ui.server.docroot.description2":"If you don\'t know how to configure your document root, please read the Contao documentation or contact your hosting provider.","ui.server.docroot.documentation":"Read the Documentation","ui.server.docroot.conflictsTitle":"Installation directory not empty","ui.server.docroot.conflictsDirectory":"The root directory of your future Contao installation is not empty, we have found {count} file(s) that might be overwritten by the installation process. It is recommended to create an empty directory structure for Contao, but you can also remove the following files and reload the page if you are sure they are unused.","ui.server.docroot.ignoreConflicts":"I want to install Contao into the non-empty directory. I understand that this might overwrite any existing files on my webspace.","ui.server.docroot.create":"Create directories","ui.server.docroot.formTitle":"Directory Setup","ui.server.docroot.formText1":"The Contao Manager can automatically create a new directory structure on the server.","ui.server.docroot.formText2":"You will need to manually configure the new document root (e.g. through a hosting admin panel).","ui.server.docroot.autoconfig":"I understand that I have to change my server configuration. Not configuring the document root will break the Contao Manager and expose configuration files (including account details and passwords)!","ui.server.docroot.directory":"New Directory","ui.server.docroot.currentRoot":"Current Document Root","ui.server.docroot.newRoot":"New Document Root","ui.server.docroot.finish":"Setup Directories","ui.server.docroot.directoryInvalid":"Please enter a valid directory name.","ui.server.docroot.directoryExists":"The target directory already exists. Please enter a different name.","ui.server.docroot.confirmation":"The Contao Manager has successfully created the necessary directory for your Contao installation. You now have to configure the document root on your web server. Do not reload this page until then.","ui.server.docroot.reload":"Reload Page","ui.task.headline":"Background Task","ui.task.loading":"Loading details …","ui.task.created":"Loading details …","ui.task.active":"Please wait while the Contao Manager is running task operations in the background.","ui.task.complete":"All operations are completed successfully. Check the console output for details.","ui.task.aborting":"Please wait while the background operations are being cancelled.","ui.task.stopped":"Some background operations were cancelled. Please check the console output.","ui.task.error":"A background operation stopped unexpectedly. Please check the console output.","ui.task.failed":"The Contao Manager failed to start a background task!","ui.task.failedDescription1":"Something went wrong while trying to execute operations in the background.","ui.task.failedDescription2":"If this happens again, your server might not be supported.","ui.task.reportProblem":"گزارش یک مشکل","ui.task.buttonAudit":"Update Database","ui.task.buttonClose":"بستن","ui.task.buttonConfirm":"تایید و بستن","ui.task.buttonCancel":"لغو","ui.task.confirmCancel":"Are you sure to cancel this task? This might leave your Contao installation in a broken state!","ui.task.autoclose":"Close task details on success","ui.console.toggle":"Show/Hide Console Output","ui.console.showLog":"Show full console log","ui.console.copyLog":"Copy log to clipboard","ui.widget.mandatory":"این فیلد نباید خالی باشد.","ui.error.title":"HTTP request for \\"{method} {url}\\" failed.","ui.error.server500":"Looks like an unexpected error happened on your server. Please check the log files of your web server (Apache/Nginx) and the Contao Manager logs at \\"contao-manager/logs\\".","ui.error.response":"The server returned a response with status code {status}.","ui.error.moreLink":"اطلاعات بیشتر","ui.error.support":"Contao Support","ui.footer.help":"کمک","ui.footer.reportProblem":"گزارش یک مشکل","ui.navigation.discover":"Discover","ui.navigation.packages":"بسته‌ها","ui.navigation.tools":"ابزارها","ui.navigation.installTool":"ابزار نصب","ui.navigation.backend":"Contao Backend","ui.navigation.debug":"Contao Debug Mode","ui.navigation.phpinfo":"PHP Information","ui.navigation.maintenance":"نگهداشت","ui.navigation.rebuildCache":"بازسازی نهان‌گاه","ui.navigation.systemCheck":"System Check","ui.navigation.advanced":"پیشرفته","ui.navigation.logout":"خروج","ui.maintenance.rebuildCache.title":"Application Cache","ui.maintenance.rebuildCache.description":"Rebuilding the application cache is required after modifying any of the configuration files.","ui.maintenance.rebuildCache.rebuildProd":"Rebuild Production Cache","ui.maintenance.rebuildCache.rebuildDev":"Rebuild Development Cache","ui.maintenance.rebuildCache.clearProd":"Clear Production Cache","ui.maintenance.rebuildCache.clearDev":"Clear Development Cache","ui.maintenance.installTool.title":"Contao Install Tool","ui.maintenance.installTool.description":"The Contao Install Tool is automatically locked if you enter a wrong password three times in a row.","ui.maintenance.installTool.unlock":"Unlock Install Tool","ui.maintenance.installTool.lock":"Lock Install Tool","ui.maintenance.dumpAutoload.title":"Composer Class Loader","ui.maintenance.dumpAutoload.description":"The Composer autoloader is responsible for PHP class loading. The autoloader must be dumped after adding custom namespaces to the root composer.json.","ui.maintenance.dumpAutoload.button":"Dump Autoloader","ui.maintenance.composerInstall.title":"Composer Dependencies","ui.maintenance.composerInstall.description":"Composer dependencies are located in the {vendor} folder in your application root. Reinstalling the dependencies can be necessary after manipulation or manually uploading the {composerLock} file.","ui.maintenance.composerInstall.button":"Run Installer","ui.maintenance.composerInstall.update":"Run Composer Update","ui.maintenance.composerCache.title":"Composer Cache","ui.maintenance.composerCache.description":"Composer caches downloaded packages for improved performance. If you have issues like broken files, try to delete the Composer cache to force a new download.","ui.maintenance.composerCache.button":"Clear Cache","ui.maintenance.maintenanceMode.title":"Maintenance Mode","ui.maintenance.maintenanceMode.description":"Putting Contao in maintenance mode will display a \\"503 Service Unavailable\\" template for the website.","ui.maintenance.maintenanceMode.enable":"Enable","ui.maintenance.maintenanceMode.disable":"Disable","ui.maintenance.debugMode.title":"Debug Mode","ui.maintenance.debugMode.description":"Activate the debug mode by setting a user and password for the {appDevPhp} entry point.","ui.maintenance.debugMode.descriptionJwt":"Activate the debug mode by setting the debug cookie for the current domain.","ui.maintenance.debugMode.activate":"Activate","ui.maintenance.debugMode.deactivate":"Deactivate","ui.maintenance.debugMode.credentials":"Credentials","ui.maintenance.debugMode.user":"Please enter a username for the debug mode.","ui.maintenance.debugMode.password":"Please enter a password for the debug mode.","ui.maintenance.opcodeCache.title":"Opcode Cache","ui.maintenance.opcodeCache.description":"Opcode caches PHP files on the web process for faster execution. It must be deleted under certain circumstances if files are not recognized after changing.","ui.maintenance.opcodeCache.button":"Truncate Cache","ui.maintenance.safeMode":"Not available in Safe Mode","ui.maintenance.unsupported":"Not supported by your Contao version","ui.packages.updateButton":"بروزرسانی بسته‌ها","ui.packages.searchButton":"Search Packages","ui.packages.searchPlaceholder":"Search Packages …","ui.packages.uploadOverlay":"Drag & drop files to upload","ui.packages.uploadButton":"Upload Packages","ui.packages.uploadMessage":"You have one unconfirmed upload. | You have {count} unconfirmed uploads.","ui.packages.uploadApply":"Confirm Uploads","ui.packages.uploadReset":"Delete Uploads","ui.packages.uploadIncomplete":"This file was not uploaded completely. Please remove it and try again.","ui.packages.uploadDuplicate":"This file seems to be uploaded multiple times. Please remove the duplicates.","ui.packages.uploadInstalled":"This file is already installed. Please remove the duplicates.","ui.packages.uploadUnsupported":"Uploads are not supported in your installation. Please make sure to update your dependencies.","ui.packages.changesMessage":"You have one unconfirmed change. | You have {count} unconfirmed changes.","ui.packages.changesDryrun":"Dry Run","ui.packages.changesApply":"Apply Changes","ui.packages.changesApplyAll":"Update all packages","ui.packages.changesDryrunAll":"Dry run all packages","ui.packages.changesReset":"Reset Changes","ui.packages.changesReview":"Review Changes","ui.packagelist.loading":"بارگذاری ...","ui.packagelist.uploads":"Uploads","ui.packagelist.added":"New packages","ui.packagelist.installed":"Installed packages","ui.package.hintRevert":"بازگرداندن تغییرات","ui.package.hintNoupdate":"Do not update","ui.package.hintConstraint":"این بسته با محدودیت بهترین {constraint} نصب خواهد شد وقتی شما تغییرات را اعمال کنید.","ui.package.hintConstraintBest":"این بسته در بهترین نسخه‌ی موجود نصب خواهد شد وقتی شما تغییرات را اعمال کنید.","ui.package.hintConstraintChange":"محدودیت برای این بسته از «{from}» به «{to}» وقتی شما تغییرات را اعمال کنید تغییر داده خواهد شد.","ui.package.hintConstraintUpdate":"This package will be updated when you apply the changes.","ui.package.hintAdded":"This package will be installed when you apply the changes.","ui.package.hintRemoved":"این بسته حذف خواهد وقتی شما تغییرات را اعمال کنید.","ui.package.requiredTitle":"manually added","ui.package.requiredText":"This package is required in your composer.json but not installed.","ui.package.removedTitle":"manually removed","ui.package.removedText":"This package was removed from your composer.json.","ui.package.installed":"Currently installed:","ui.package.version":"نسخه {version}","ui.package.additionalDownloads":"{count} Download | {count} Downloads","ui.package.additionalStars":"{count} Star | {count} Stars","ui.package.editConstraint":"ویرایش","ui.package.uploadConstraint":"This constraint is defined by the uploaded package.","ui.package.updateButton":"Update","ui.package.removeButton":"حذف","ui.package.installButton":"Add Package","ui.package.installButtonShort":"Add","ui.package.detailsButton":"جزئیات","ui.package.latestConstraint":"آخرین نسخه","ui.package.update":"Update available","ui.package.updateLatest":"آخرین نسخه","ui.package.updateAvailable":"{version} available","ui.package.updateUnknown":"unknown version","ui.cloudStatus.headline":"Composer Resolver Cloud","ui.cloudStatus.version":"نسخه {version}","ui.cloudStatus.waitingTime":"Waiting Time","ui.cloudStatus.jobs":"Current Jobs","ui.cloudStatus.workers":"Workers","ui.cloudStatus.approx":"{minutes} min","ui.cloudStatus.none":"none","ui.cloudStatus.short":"ca. {minutes} min","ui.cloudStatus.long":"ca. {minutes} min {seconds} sec","ui.cloudStatus.error":"Unable to fetch the status of the Composer Resolver Cloud. It might be down for maintenance or experience issues.","ui.cloudStatus.button":"Cloud Status","ui.cloudStatus.refresh":"Refresh Cloud Status"}')}}]);"use strict";(self["webpackChunkcontao_manager"]=self["webpackChunkcontao_manager"]||[]).push([[739],{8120:function(e){e.exports=JSON.parse('{"ui.app.title":"Extensions Contao","ui.app.loading":"Chargement de la liste des extensions…","ui.app.language":"Switch language for the Contao Manager","ui.app.colorDark":"Dark Mode","ui.app.colorDarkTitle":"Switch color scheme to dark","ui.app.colorLight":"Light Mode","ui.app.colorLightTitle":"Switch color scheme to light","ui.discover.advertisement":"Publicité dans la liste des extensions","ui.discover.loading":"Chargement…","ui.discover.offline":"Impossible de récupérer des résultats.","ui.discover.offlineExplain":"Vérifiez votre connexion Internet et désactivez les bloqueurs JavaScript dans votre navigateur.","ui.discover.offlineButton":"Réessayer","ui.discover.searchPlaceholder":"Search in {count} extensions …","ui.discover.empty":"Pas de résultats pour {query}","ui.discover.more":"Plus de résulats","ui.discover.sortBy":"Trier par","ui.discover.sortReleased":"Released","ui.discover.sortReleasedTitle":"Sort results by release date","ui.discover.sortLatest":"Mis à jour","ui.discover.sortLatestTitle":"Sort results by last updated","ui.discover.sortDownloads":"Téléchargements","ui.discover.sortDownloadsTitle":"Sort results by number of downloads","ui.discover.sortFavers":"Note","ui.discover.sortFaversTitle":"Sort results by rating","ui.discover.detailsButton":"Détails","ui.discover.latestPackages":"Extensions les plus récentes et mises à jour","ui.discover.faversPackages":"Extensions les mieux notées","ui.discover.downloadsPackages":"Extensions les plus téléchargées","ui.discover.exactHit":"Exact query match","ui.discover.results":"More search results","ui.package.homepage":"Site web du projet","ui.package.private":"Package privé","ui.package.privateTitle":"Les packages privés ne sont disponibles que chez le fournisseur (par exemple sous forme de téléchargement ZIP). Veuillez visiter le site Web pour plus d\'informations","ui.package.abandoned":"abandonné","ui.package.abandonedText":"Ce package est abandonné et n\'est plus maintenu.","ui.package.abandonedReplace":"Ce package est abandonné et n\'est plus maintenu. L\'auteur suggère d\'utiliser le package {replacement} à la place.","ui.package.contaoVersion":"Available for Contao","ui.package-details.previous":"Extension précédente","ui.package-details.close":"Fermer les détails","ui.package-details.loading":"Chargement…","ui.package-details.tabDescription":"Description","ui.package-details.tabRequire":"Prérequis","ui.package-details.tabFeatures":"Fonctionnalités","ui.package-details.tabSuggest":"Suggestions","ui.package-details.tabConflict":"Conflits","ui.package-details.tabDependents":"Dépendants","ui.package-details.linkRequires":"nécessite","ui.package-details.linkReplaces":"remplaces","ui.package-details.linkProvides":"fournis","ui.package-details.linkConflicts":"conflits","ui.package-details.funding":"Fund package maintenance!","ui.package-details.contaoVersions":"Supported Contao version(s)","ui.package-details.latest":"Dernière version","ui.package-details.released":"Publié le","ui.package-details.license":"License(s)","ui.package-details.authors":"de","ui.package-details.more":"Plus","ui.package-details.packagist":"Détails du Package","ui.package-details.metadata":"Editer les Metadata","ui.package-details.support_docs":"Documentation","ui.package-details.support_wiki":"Wiki","ui.package-details.support_forum":"Support","ui.package-details.support_issues":"Issues / Bug Report","ui.package-details.support_source":"Code source","ui.package-details.support_irc":"IRC / Chat","ui.package-details.support_email":"Support E-Mail","ui.package-details.support_rss":"RSS Feed"}')}}]);"use strict";(self["webpackChunkcontao_manager"]=self["webpackChunkcontao_manager"]||[]).push([[958],{2958:function(e){e.exports=JSON.parse('{"ui.app.httpsHeadline":"!! Kevreadur diasur !!","ui.app.httpsDescription":"Hep HTTPS ho roadennoù kuzhut a vo treuzkaset dirinegañ.","ui.app.httpsLink":"Muioc\'h a ditouroù","ui.app.httpsHref":"https://https.cio.gov/everything/","ui.app.loading":"O kargañ Contao Manager ...","ui.app.apiError":"Statud API dic\'hortoz","ui.app.configSecurity1":"SECURITY ALERT !!! Unprotected config directory detected","ui.app.configSecurity2":"The Contao Manager has detected that its config files are publicly accessible. All operations are disabled until the directory is secured, otherwise an attacker could access sensitive data of your installation.\\n\\nTo fix this issue, make sure to prevent access to the \\"contao-manager\\" directory on your server. To learn how to do this, please refer to the manual of your webserver or contact your hosting provider.","ui.account.welcome":"Degemer mat","ui.account.intro1":"Welcome to the Contao Manager, a universal tool to install and manage Contao Open Source CMS. If you are new to it, please {readTheManualToGetStarted}.","ui.account.introGetStarted":"{readTheManual} to get started","ui.account.introManual":"read the manual","ui.account.intro2":"If you encounter any problems, check {ourGithubIssues} and feel free to create new one for anything that has not been reported yet.","ui.account.introIssues":"our GitHub issues","ui.account.headline":"Kont implijer","ui.account.description":"Da verañ ho staliadur, krouit ur gont mar plij evit Contao Manager. Deoc\'h da c\'houzout n\'eo ket liammet d\'ar c\'hontoù Contao back end pe front end.","ui.account.username":"Anv-implijer","ui.account.password":"Ger-tremen","ui.account.passwordConfirm":"Adskrivit ar ger-tremen","ui.account.passwordPlaceholder":"min. 8 arouezenn","ui.account.passwortLength":"Ebarzhit da vihanañ 8 arouezenn.","ui.account.passwortDifferent":"Ar ger-tremen na glot ket gant ar c\'hadarnadur.","ui.account.submit":"Krouiñ ur gont","ui.account.contribute1":"Contao and the Contao Manager are sponsored by the non-profit Contao Association.","ui.account.contribute2":"Please consider contributing to open source by {donate}.","ui.account.contributeDonate":"making a donation","ui.login.headline":"Kevreañ","ui.login.description":"Kevreit evit merañ ho staliadur.","ui.login.username":"Anv-implijer","ui.login.password":"Ger-tremen","ui.login.forgotPassword":"Ankouaet ho ker-tremen?","ui.login.button":"Kevreañ","ui.login.locked":"Access has been denied because the Contao Manager is locked. To unlock, delete the {lockFile} file in your Contao root directory.","ui.logout.headline":"Session Timeout","ui.logout.warning":"Your have been inactive for more than 25 minutes. For security reasons your session will be terminated shortly.","ui.logout.expired":"Your session was automatically terminated because you have been inactive for more than 30 minutes.","ui.logout.renew":"Keep Logged In","ui.logout.logout":"Digevreañ","ui.logout.login":"Back To Login","ui.oauth.error":"Invalid OAuth attempt. Check the request parameters.","ui.oauth.https":"The redirect URI MUST use a secure protocol (https:) to prevent the authentication token from being transmitted in clear-text.","ui.oauth.headline":"Remote Authentication","ui.oauth.description":"The following application or service is requesting remote access to your Contao Manager instance.","ui.oauth.domain":"Before allowing access, make sure you know this URL and trust its owner!","ui.oauth.allow":"Allow Access","ui.oauth.deny":"Deny Access","ui.boot.headline":"Gwiriadur ar reizhad","ui.boot.description":"Please wait, we are analyzing your server …","ui.boot.issue1":"Kudennoù diguzhet en ur staliañ","ui.boot.issue2":"Your installation has issues that have to be fixed before the Contao Manager can be used.","ui.boot.run":"Loc\'hañ Contao Manager","ui.recovery.headline":"System Recovery","ui.recovery.description":"The Contao Manager detected files that look like Contao, but the Command Line Interface does not work as expected.","ui.recovery.console":"Console Output","ui.recovery.repairOptions":"Please choose an option to repair your installation.","ui.recovery.repairHeadline":"Automatic Repair","ui.recovery.repairDescription":"Attempts to automatically repair the installation by rebuilding the application cache and re-installing the Composer packages.","ui.recovery.repairWarning":"Any modifications to the vendor files might be deleted in the process!","ui.recovery.repairFailed":"Automatic repair was not successful. Try the Safe Mode to manually repair the installation.","ui.recovery.repairButton":"Run System Repair","ui.recovery.safeModeHeadline":"Safe Mode","ui.recovery.safeModeDescription":"Launching the Contao Manager in Safe Mode allows to manage packages and run certain maintenance tasks, but features that rely on a working Contao installation will not be available.","ui.recovery.safeModeButton":"Launch in Safe Mode","ui.server.pending":"Waiting …","ui.server.running":"Oc\'h analizañ ...","ui.server.error":"Check failed due to an unexpected response from the server.","ui.server.details":"Munudoù","ui.server.prerequisite":"Check cancelled due to a missing prerequisite.","ui.server.selfUpdate.title":"Hizivadurioù Contao Manager","ui.server.selfUpdate.update":"Ur stumm nevez eus Contao Managaer a zo hegerz: {latest}.","ui.server.selfUpdate.manualUpdate":"A new Contao Manager version {latest} is available. Your server does not support automatic updates, please download the new version from {download}.","ui.server.selfUpdate.latest":"You are using the latest version {current}.","ui.server.selfUpdate.dev":"Development builds do not support automatic updates.","ui.server.selfUpdate.unsupported":"A new version is available but it does not support your PHP version.","ui.server.selfUpdate.button":"Seveniñ an em-hizivaat","ui.server.selfUpdate.continue":"Continue","ui.server.config.title":"Kefluniadur ar servijer","ui.server.config.setup":"Kefluniañ","ui.server.config.change":"Cheñch","ui.server.config.save":"Enrollañ","ui.server.config.blankOption":"Diuzit mar plij ...","ui.server.config.customOption":"Traoù all ...","ui.server.config.description":"To correctly run background tasks, the Contao Manager needs to know where to find the PHP command line binary and how to run commands separated from the web process.","ui.server.config.formTitle":"Kefluniadur ar servijer","ui.server.config.formText":"Please enter the path to your PHP binary. Make sure the binary is the same PHP version as your web process.","ui.server.config.cloudTitle":"Composer Resolver Cloud","ui.server.config.cloudText":"The Composer Resolver Cloud allows to install Composer dependencies even if your server does not provide enough local memory. Please be aware that your package information will be transmitted to a cloud server operated by the Contao Association.","ui.server.config.cloud":"Use the Composer Resolver Cloud","ui.server.config.cli":"PHP daouel","ui.server.config.stateErrorCli":"No valid PHP binary was found on the server.","ui.server.config.stateErrorCloud":"The Composer Resolver Cloud is not supported.","ui.server.config.stateSuccess":"PHP binary at {php_cli}.","ui.server.php_web.title":"PHP Web Process","ui.server.php_web.below7":"Found PHP version {version}. Please switch to PHP 7 as soon as possible!","ui.server.php_web.success":"Found PHP version {version}, no known issues found.","ui.server.php_cli.title":"PHP Command Line Interface","ui.server.php_cli.success":"Found PHP version {version}, no known issues found.","ui.server.composer.title":"Endro kompozer","ui.server.composer.success":"N\'eus bet kavet kudenn ebet.","ui.server.composer.install":"Composer dependencies are not installed.","ui.server.composer.button":"Run Composer","ui.server.composer.safeMode":"Run Safe Mode","ui.server.contao.title":"Staliadur Contao","ui.server.contao.setup":"Setup","ui.server.contao.empty":"Staliadur Contao ebet bet kavet","ui.server.contao.old":"Contao version {version} is not compatible with the Contao Manager, please update your installation manually.","ui.server.contao.found":"Kavet Contao {version} (API stumm {api}).","ui.server.contao.headline":"Kefluniadur Contao","ui.server.contao.description":"Welcome to the setup process of your Contao Open Source CMS. You can choose between two versions to install.","ui.server.contao.publicDir":"Use {dir} for public files (for Contao {version})","ui.server.contao.ltsTitle":"Skor war hir amzer","ui.server.contao.ltsText":"The LTS version has an extended support period of up to four years.","ui.server.contao.latestTitle":"Diwezhatañ","ui.server.contao.latestText":"A new latest version is released every six months in February and August.","ui.server.contao.noLatest":"Requires at least PHP {version}.","ui.server.contao.releaseplan":"See the {contaoReleasePlan} for detailed information.","ui.server.contao.releaseplanLink":"Contao Release Plan","ui.server.contao.formTitle":"Staliadur Contao","ui.server.contao.formText":"Select the Contao version to install.","ui.server.contao.version":"Stumm","ui.server.contao.coreOnly":"Initial Setup","ui.server.contao.coreOnlyNo":"Full Installation (News, Calendar, etc.)","ui.server.contao.coreOnlyYes":"Minimal Installation (Core only)","ui.server.contao.coreOnlyFeatures":"What\'s the difference?","ui.server.contao.noUpdate":"Skip Installation (Expert Only!)","ui.server.contao.install":"Finish","ui.server.docroot.headline":"Webserver Setup","ui.server.docroot.warning":"To install Contao through the Contao Manager, you have to fix the document root on the web server.","ui.server.docroot.description1":"Contao uses a separate folder for public files, application files are installed in its parent folder. Contao cannot be installed right now, because your folder structure is not correct or the folders are not empty.","ui.server.docroot.description2":"If you don\'t know how to configure your document root, please read the Contao documentation or contact your hosting provider.","ui.server.docroot.documentation":"Read the Documentation","ui.server.docroot.conflictsTitle":"Installation directory not empty","ui.server.docroot.conflictsDirectory":"The root directory of your future Contao installation is not empty, we have found {count} file(s) that might be overwritten by the installation process. It is recommended to create an empty directory structure for Contao, but you can also remove the following files and reload the page if you are sure they are unused.","ui.server.docroot.ignoreConflicts":"I want to install Contao into the non-empty directory. I understand that this might overwrite any existing files on my webspace.","ui.server.docroot.create":"Create directories","ui.server.docroot.formTitle":"Directory Setup","ui.server.docroot.formText1":"The Contao Manager can automatically create a new directory structure on the server.","ui.server.docroot.formText2":"You will need to manually configure the new document root (e.g. through a hosting admin panel).","ui.server.docroot.autoconfig":"I understand that I have to change my server configuration. Not configuring the document root will break the Contao Manager and expose configuration files (including account details and passwords)!","ui.server.docroot.directory":"New Directory","ui.server.docroot.currentRoot":"Current Document Root","ui.server.docroot.newRoot":"New Document Root","ui.server.docroot.finish":"Setup Directories","ui.server.docroot.directoryInvalid":"Please enter a valid directory name.","ui.server.docroot.directoryExists":"The target directory already exists. Please enter a different name.","ui.server.docroot.confirmation":"The Contao Manager has successfully created the necessary directory for your Contao installation. You now have to configure the document root on your web server. Do not reload this page until then.","ui.server.docroot.reload":"Reload Page","ui.task.headline":"Background Task","ui.task.loading":"Loading details …","ui.task.created":"Loading details …","ui.task.active":"Please wait while the Contao Manager is running task operations in the background.","ui.task.complete":"All operations are completed successfully. Check the console output for details.","ui.task.aborting":"Please wait while the background operations are being cancelled.","ui.task.stopped":"Some background operations were cancelled. Please check the console output.","ui.task.error":"A background operation stopped unexpectedly. Please check the console output.","ui.task.failed":"The Contao Manager failed to start a background task!","ui.task.failedDescription1":"Something went wrong while trying to execute operations in the background.","ui.task.failedDescription2":"If this happens again, your server might not be supported.","ui.task.reportProblem":"Danevelliñ ur gudenn","ui.task.buttonAudit":"Update Database","ui.task.buttonClose":"Serriñ","ui.task.buttonConfirm":"Kadarnaat & ha serriñ","ui.task.buttonCancel":"Nullañ","ui.task.confirmCancel":"Are you sure to cancel this task? This might leave your Contao installation in a broken state!","ui.task.autoclose":"Close task details on success","ui.console.toggle":"Show/Hide Console Output","ui.console.showLog":"Show full console log","ui.console.copyLog":"Copy log to clipboard","ui.widget.mandatory":"Ar vaezienn-mañ n\'hall ket bezañ goullo.","ui.error.title":"HTTP request for \\"{method} {url}\\" failed.","ui.error.server500":"Looks like an unexpected error happened on your server. Please check the log files of your web server (Apache/Nginx) and the Contao Manager logs at \\"contao-manager/logs\\".","ui.error.response":"The server returned a response with status code {status}.","ui.error.moreLink":"Muioc\'h a ditouroù","ui.error.support":"Contao Support","ui.footer.help":"Skoazell","ui.footer.reportProblem":"Danevelliñ ur gudenn","ui.navigation.discover":"Discover","ui.navigation.packages":"Pakadoù","ui.navigation.tools":"Ostilhoù","ui.navigation.installTool":"Staliañ an ostilh","ui.navigation.backend":"Contao Backend","ui.navigation.debug":"Contao Debug Mode","ui.navigation.phpinfo":"PHP Information","ui.navigation.maintenance":"Trezalc\'h","ui.navigation.rebuildCache":"Adsevel ar c\'hrubuilh","ui.navigation.systemCheck":"Gwiriadur ar reizhad","ui.navigation.advanced":"Araokaet","ui.navigation.logout":"Digevreañ","ui.maintenance.rebuildCache.title":"Application Cache","ui.maintenance.rebuildCache.description":"Rebuilding the application cache is required after modifying any of the configuration files.","ui.maintenance.rebuildCache.rebuildProd":"Rebuild Production Cache","ui.maintenance.rebuildCache.rebuildDev":"Rebuild Development Cache","ui.maintenance.rebuildCache.clearProd":"Clear Production Cache","ui.maintenance.rebuildCache.clearDev":"Clear Development Cache","ui.maintenance.installTool.title":"Contao Install Tool","ui.maintenance.installTool.description":"The Contao Install Tool is automatically locked if you enter a wrong password three times in a row.","ui.maintenance.installTool.unlock":"Unlock Install Tool","ui.maintenance.installTool.lock":"Lock Install Tool","ui.maintenance.dumpAutoload.title":"Composer Class Loader","ui.maintenance.dumpAutoload.description":"The Composer autoloader is responsible for PHP class loading. The autoloader must be dumped after adding custom namespaces to the root composer.json.","ui.maintenance.dumpAutoload.button":"Dump Autoloader","ui.maintenance.composerInstall.title":"Composer Dependencies","ui.maintenance.composerInstall.description":"Composer dependencies are located in the {vendor} folder in your application root. Reinstalling the dependencies can be necessary after manipulation or manually uploading the {composerLock} file.","ui.maintenance.composerInstall.button":"Run Installer","ui.maintenance.composerInstall.update":"Run Composer Update","ui.maintenance.composerCache.title":"Composer Cache","ui.maintenance.composerCache.description":"Composer caches downloaded packages for improved performance. If you have issues like broken files, try to delete the Composer cache to force a new download.","ui.maintenance.composerCache.button":"Clear Cache","ui.maintenance.maintenanceMode.title":"Maintenance Mode","ui.maintenance.maintenanceMode.description":"Putting Contao in maintenance mode will display a \\"503 Service Unavailable\\" template for the website.","ui.maintenance.maintenanceMode.enable":"Enable","ui.maintenance.maintenanceMode.disable":"Disable","ui.maintenance.debugMode.title":"Debug Mode","ui.maintenance.debugMode.description":"Activate the debug mode by setting a user and password for the {appDevPhp} entry point.","ui.maintenance.debugMode.descriptionJwt":"Activate the debug mode by setting the debug cookie for the current domain.","ui.maintenance.debugMode.activate":"Activate","ui.maintenance.debugMode.deactivate":"Deactivate","ui.maintenance.debugMode.credentials":"Credentials","ui.maintenance.debugMode.user":"Please enter a username for the debug mode.","ui.maintenance.debugMode.password":"Please enter a password for the debug mode.","ui.maintenance.opcodeCache.title":"Opcode Cache","ui.maintenance.opcodeCache.description":"Opcode caches PHP files on the web process for faster execution. It must be deleted under certain circumstances if files are not recognized after changing.","ui.maintenance.opcodeCache.button":"Truncate Cache","ui.maintenance.safeMode":"Not available in Safe Mode","ui.maintenance.unsupported":"Not supported by your Contao version","ui.packages.updateButton":"Hizivaat ar pakadoù","ui.packages.searchButton":"Search Packages","ui.packages.searchPlaceholder":"Klask war-lerc\'h pakadoù ...","ui.packages.uploadOverlay":"Drag & drop files to upload","ui.packages.uploadButton":"Upload Packages","ui.packages.uploadMessage":"You have one unconfirmed upload. | You have {count} unconfirmed uploads.","ui.packages.uploadApply":"Confirm Uploads","ui.packages.uploadReset":"Delete Uploads","ui.packages.uploadIncomplete":"This file was not uploaded completely. Please remove it and try again.","ui.packages.uploadDuplicate":"This file seems to be uploaded multiple times. Please remove the duplicates.","ui.packages.uploadInstalled":"This file is already installed. Please remove the duplicates.","ui.packages.uploadUnsupported":"Uploads are not supported in your installation. Please make sure to update your dependencies.","ui.packages.changesMessage":"You have one unconfirmed change. | You have {count} unconfirmed changes.","ui.packages.changesDryrun":"Dry Run","ui.packages.changesApply":"Arloañ ar c\'hemmoù","ui.packages.changesApplyAll":"Update all packages","ui.packages.changesDryrunAll":"Dry run all packages","ui.packages.changesReset":"Adderaouekaat ar cheñchamantoù","ui.packages.changesReview":"Review Changes","ui.packagelist.loading":"O kargañ ...","ui.packagelist.uploads":"Uploads","ui.packagelist.added":"New packages","ui.packagelist.installed":"Installed packages","ui.package.hintRevert":"Adlakaat ar cheñchamantoù","ui.package.hintNoupdate":"Do not update","ui.package.hintConstraint":"This package will be installed with constraint {constraint} when you apply the changes.","ui.package.hintConstraintBest":"This package will be installed in the best available version when you apply the changes.","ui.package.hintConstraintChange":"The constraint for this package will be changed from \\"{from}\\" to \\"{to}\\" when you apply the changes.","ui.package.hintConstraintUpdate":"This package will be updated when you apply the changes.","ui.package.hintAdded":"This package will be installed when you apply the changes.","ui.package.hintRemoved":"This package will be removed when you apply the changes.","ui.package.requiredTitle":"manually added","ui.package.requiredText":"This package is required in your composer.json but not installed.","ui.package.removedTitle":"manually removed","ui.package.removedText":"This package was removed from your composer.json.","ui.package.installed":"Currently installed:","ui.package.version":"Stumm {version}","ui.package.additionalDownloads":"{count} Download | {count} Downloads","ui.package.additionalStars":"{count} Star | {count} Stars","ui.package.editConstraint":"Kemm","ui.package.uploadConstraint":"This constraint is defined by the uploaded package.","ui.package.updateButton":"Update","ui.package.removeButton":"Dilemel","ui.package.installButton":"Add Package","ui.package.installButtonShort":"Add","ui.package.detailsButton":"Munudoù","ui.package.latestConstraint":"stumm diwezhañ","ui.package.update":"Update available","ui.package.updateLatest":"stumm diwezhañ","ui.package.updateAvailable":"{version} available","ui.package.updateUnknown":"unknown version","ui.cloudStatus.headline":"Composer Resolver Cloud","ui.cloudStatus.version":"Stumm {version}","ui.cloudStatus.waitingTime":"Waiting Time","ui.cloudStatus.jobs":"Current Jobs","ui.cloudStatus.workers":"Workers","ui.cloudStatus.approx":"{minutes} min","ui.cloudStatus.none":"none","ui.cloudStatus.short":"ca. {minutes} min","ui.cloudStatus.long":"ca. {minutes} min {seconds} sec","ui.cloudStatus.error":"Unable to fetch the status of the Composer Resolver Cloud. It might be down for maintenance or experience issues.","ui.cloudStatus.button":"Cloud Status","ui.cloudStatus.refresh":"Refresh Cloud Status"}')}}]);"use strict";(self["webpackChunkcontao_manager"]=self["webpackChunkcontao_manager"]||[]).push([[859],{7680:function(e,t,r){var n=r(9504);e.exports=n([].slice)},5810:function(e,t,r){var n=r(34),o=r(1181).get;e.exports=function(e){if(!n(e))return!1;var t=o(e);return!!t&&"RawJSON"===t.type}},7819:function(e,t,r){var n=r(9039);e.exports=!n(function(){var e="9007199254740993",t=JSON.rawJSON(e);return!JSON.isRawJSON(t)||JSON.stringify(t)!==e})},3110:function(e,t,r){var n=r(6518),o=r(7751),i=r(8745),a=r(9565),s=r(9504),c=r(9039),u=r(4376),l=r(4901),d=r(5810),h=r(757),f=r(2195),p=r(655),g=r(7680),R=r(8235),w=r(3392),b=r(4495),E=r(7819),m=String,A=o("JSON","stringify"),y=s(/./.exec),O=s("".charAt),S=s("".charCodeAt),_=s("".replace),T=s("".slice),I=s([].push),N=s(1.1.toString),v=/[\uD800-\uDFFF]/g,C=/^[\uD800-\uDBFF]$/,P=/^[\uDC00-\uDFFF]$/,D=w(),U=D.length,K=!b||c(function(){var e=o("Symbol")("stringify detection");return"[null]"!==A([e])||"{}"!==A({a:e})||"{}"!==A(Object(e))}),x=c(function(){return'"\\udf06\\ud834"'!==A("\udf06\ud834")||'"\\udead"'!==A("\udead")}),J=K?function(e,t){var r=g(arguments),n=H(t);if(l(n)||void 0!==e&&!h(e))return r[1]=function(e,t){if(l(n)&&(t=a(n,this,m(e),t)),!h(t))return t},i(A,null,r)}:A,L=function(e,t,r){var n=O(r,t-1),o=O(r,t+1);return y(C,e)&&!y(P,o)||y(P,e)&&!y(C,n)?"\\u"+N(S(e,0),16):e},H=function(e){if(l(e))return e;if(u(e)){for(var t=e.length,r=[],n=0;n<t;n++){var o=e[n];"string"==typeof o?I(r,o):"number"!=typeof o&&"Number"!==f(o)&&"String"!==f(o)||I(r,p(o))}var i=r.length,a=!0;return function(e,t){if(a)return a=!1,t;if(u(this))return t;for(var n=0;n<i;n++)if(r[n]===e)return t}}};A&&n({target:"JSON",stat:!0,arity:3,forced:K||x||!E},{stringify:function(e,t,r){var n=H(t),o=[],i=J(e,function(e,t){var r=l(n)?a(n,this,m(e),t):t;return!E&&d(r)?D+(I(o,r.rawJSON)-1):r},r);if("string"!=typeof i)return i;if(x&&(i=_(i,v,L)),E)return i;for(var s="",c=i.length,u=0;u<c;u++){var h=O(i,u);if('"'===h){var f=R(i,++u).end-1,p=T(i,u,f);s+=T(p,0,U)===D?o[T(p,U)]:'"'+p+'"',u=f}else s+=h}return s}})},60:function(e,t,r){function n(e){const t=new Uint8Array(e);let r="";for(const o of t)r+=String.fromCharCode(o);const n=btoa(r);return n.replace(/\+/g,"-").replace(/\//g,"_").replace(/=/g,"")}function o(e){const t=e.replace(/-/g,"+").replace(/_/g,"/"),r=(4-t.length%4)%4,n=t.padEnd(t.length+r,"="),o=atob(n),i=new ArrayBuffer(o.length),a=new Uint8Array(i);for(let s=0;s<o.length;s++)a[s]=o.charCodeAt(s);return i}function i(){return a.stubThis(void 0!==globalThis?.PublicKeyCredential&&"function"===typeof globalThis.PublicKeyCredential)}r.d(t,{zZ:function(){return i},HS:function(){return m},Ct:function(){return g}});const a={stubThis:e=>e};function s(e){const{id:t}=e;return{...e,id:o(t),transports:e.transports}}function c(e){return"localhost"===e||/^((xn--[a-z0-9-]+|[a-z0-9]+(-[a-z0-9]+)*)\.)+([a-z]{2,}|xn--[a-z0-9-]+)$/i.test(e)}class u extends Error{constructor({message:e,code:t,cause:r,name:n}){super(e,{cause:r}),Object.defineProperty(this,"code",{enumerable:!0,configurable:!0,writable:!0,value:void 0}),this.name=n??r.name,this.code=t}}function l({error:e,options:t}){const{publicKey:r}=t;if(!r)throw Error("options was missing required publicKey property");if("AbortError"===e.name){if(t.signal instanceof AbortSignal)return new u({message:"Registration ceremony was sent an abort signal",code:"ERROR_CEREMONY_ABORTED",cause:e})}else if("ConstraintError"===e.name){if(!0===r.authenticatorSelection?.requireResidentKey)return new u({message:"Discoverable credentials were required but no available authenticator supported it",code:"ERROR_AUTHENTICATOR_MISSING_DISCOVERABLE_CREDENTIAL_SUPPORT",cause:e});if("conditional"===t.mediation&&"required"===r.authenticatorSelection?.userVerification)return new u({message:"User verification was required during automatic registration but it could not be performed",code:"ERROR_AUTO_REGISTER_USER_VERIFICATION_FAILURE",cause:e});if("required"===r.authenticatorSelection?.userVerification)return new u({message:"User verification was required but no available authenticator supported it",code:"ERROR_AUTHENTICATOR_MISSING_USER_VERIFICATION_SUPPORT",cause:e})}else{if("InvalidStateError"===e.name)return new u({message:"The authenticator was previously registered",code:"ERROR_AUTHENTICATOR_PREVIOUSLY_REGISTERED",cause:e});if("NotAllowedError"===e.name)return new u({message:e.message,code:"ERROR_PASSTHROUGH_SEE_CAUSE_PROPERTY",cause:e});if("NotSupportedError"===e.name){const t=r.pubKeyCredParams.filter(e=>"public-key"===e.type);return 0===t.length?new u({message:'No entry in pubKeyCredParams was of type "public-key"',code:"ERROR_MALFORMED_PUBKEYCREDPARAMS",cause:e}):new u({message:"No available authenticator supported any of the specified pubKeyCredParams algorithms",code:"ERROR_AUTHENTICATOR_NO_SUPPORTED_PUBKEYCREDPARAMS_ALG",cause:e})}if("SecurityError"===e.name){const t=globalThis.location.hostname;if(!c(t))return new u({message:`${globalThis.location.hostname} is an invalid domain`,code:"ERROR_INVALID_DOMAIN",cause:e});if(r.rp.id!==t)return new u({message:`The RP ID "${r.rp.id}" is invalid for this domain`,code:"ERROR_INVALID_RP_ID",cause:e})}else if("TypeError"===e.name){if(r.user.id.byteLength<1||r.user.id.byteLength>64)return new u({message:"User ID was not between 1 and 64 characters",code:"ERROR_INVALID_USER_ID_LENGTH",cause:e})}else if("UnknownError"===e.name)return new u({message:"The authenticator was unable to process the specified options, or could not create a new credential",code:"ERROR_AUTHENTICATOR_GENERAL_ERROR",cause:e})}return e}class d{constructor(){Object.defineProperty(this,"controller",{enumerable:!0,configurable:!0,writable:!0,value:void 0})}createNewAbortSignal(){if(this.controller){const e=new Error("Cancelling existing WebAuthn API call for new one");e.name="AbortError",this.controller.abort(e)}const e=new AbortController;return this.controller=e,e.signal}cancelCeremony(){if(this.controller){const e=new Error("Manually cancelling existing WebAuthn API call");e.name="AbortError",this.controller.abort(e),this.controller=void 0}}}const h=new d,f=["cross-platform","platform"];function p(e){if(e&&!(f.indexOf(e)<0))return e}async function g(e){!e.optionsJSON&&e.challenge&&(console.warn("startRegistration() was not called correctly. It will try to continue with the provided options, but this call should be refactored to use the expected call structure instead. See https://simplewebauthn.dev/docs/packages/browser#typeerror-cannot-read-properties-of-undefined-reading-challenge for more information."),e={optionsJSON:e});const{optionsJSON:t,useAutoRegister:r=!1}=e;if(!i())throw new Error("WebAuthn is not supported in this browser");const a={...t,challenge:o(t.challenge),user:{...t.user,id:o(t.user.id)},excludeCredentials:t.excludeCredentials?.map(s)},c={};let u;r&&(c.mediation="conditional"),c.publicKey=a,c.signal=h.createNewAbortSignal();try{u=await navigator.credentials.create(c)}catch(y){throw l({error:y,options:c})}if(!u)throw new Error("Registration was not completed");const{id:d,rawId:f,response:g,type:w}=u;let b,E,m,A;if("function"===typeof g.getTransports&&(b=g.getTransports()),"function"===typeof g.getPublicKeyAlgorithm)try{E=g.getPublicKeyAlgorithm()}catch(O){R("getPublicKeyAlgorithm()",O)}if("function"===typeof g.getPublicKey)try{const e=g.getPublicKey();null!==e&&(m=n(e))}catch(O){R("getPublicKey()",O)}if("function"===typeof g.getAuthenticatorData)try{A=n(g.getAuthenticatorData())}catch(O){R("getAuthenticatorData()",O)}return{id:d,rawId:n(f),response:{attestationObject:n(g.attestationObject),clientDataJSON:n(g.clientDataJSON),transports:b,publicKeyAlgorithm:E,publicKey:m,authenticatorData:A},type:w,clientExtensionResults:u.getClientExtensionResults(),authenticatorAttachment:p(u.authenticatorAttachment)}}function R(e,t){console.warn(`The browser extension that intercepted this WebAuthn API call incorrectly implemented ${e}. You should report this error to them.\n`,t)}function w(){if(!i())return b.stubThis(new Promise(e=>e(!1)));const e=globalThis.PublicKeyCredential;return void 0===e?.isConditionalMediationAvailable?b.stubThis(new Promise(e=>e(!1))):b.stubThis(e.isConditionalMediationAvailable())}const b={stubThis:e=>e};function E({error:e,options:t}){const{publicKey:r}=t;if(!r)throw Error("options was missing required publicKey property");if("AbortError"===e.name){if(t.signal instanceof AbortSignal)return new u({message:"Authentication ceremony was sent an abort signal",code:"ERROR_CEREMONY_ABORTED",cause:e})}else{if("NotAllowedError"===e.name)return new u({message:e.message,code:"ERROR_PASSTHROUGH_SEE_CAUSE_PROPERTY",cause:e});if("SecurityError"===e.name){const t=globalThis.location.hostname;if(!c(t))return new u({message:`${globalThis.location.hostname} is an invalid domain`,code:"ERROR_INVALID_DOMAIN",cause:e});if(r.rpId!==t)return new u({message:`The RP ID "${r.rpId}" is invalid for this domain`,code:"ERROR_INVALID_RP_ID",cause:e})}else if("UnknownError"===e.name)return new u({message:"The authenticator was unable to process the specified options, or could not create a new assertion signature",code:"ERROR_AUTHENTICATOR_GENERAL_ERROR",cause:e})}return e}async function m(e){!e.optionsJSON&&e.challenge&&(console.warn("startAuthentication() was not called correctly. It will try to continue with the provided options, but this call should be refactored to use the expected call structure instead. See https://simplewebauthn.dev/docs/packages/browser#typeerror-cannot-read-properties-of-undefined-reading-challenge for more information."),e={optionsJSON:e});const{optionsJSON:t,useBrowserAutofill:r=!1,verifyBrowserAutofillInput:a=!0}=e;if(!i())throw new Error("WebAuthn is not supported in this browser");let c;0!==t.allowCredentials?.length&&(c=t.allowCredentials?.map(s));const u={...t,challenge:o(t.challenge),allowCredentials:c},l={};if(r){if(!await w())throw Error("Browser does not support WebAuthn autofill");const e=document.querySelectorAll("input[autocomplete$='webauthn']");if(e.length<1&&a)throw Error('No <input> with "webauthn" as the only or last value in its `autocomplete` attribute was detected');l.mediation="conditional",u.allowCredentials=[]}let d;l.publicKey=u,l.signal=h.createNewAbortSignal();try{d=await navigator.credentials.get(l)}catch(A){throw E({error:A,options:l})}if(!d)throw new Error("Authentication was not completed");const{id:f,rawId:g,response:R,type:b}=d;let m;return R.userHandle&&(m=n(R.userHandle)),{id:f,rawId:n(g),response:{authenticatorData:n(R.authenticatorData),clientDataJSON:n(R.clientDataJSON),signature:n(R.signature),userHandle:m},type:b,clientExtensionResults:d.getClientExtensionResults(),authenticatorAttachment:p(d.authenticatorAttachment)}}}}]);"use strict";(self["webpackChunkcontao_manager"]=self["webpackChunkcontao_manager"]||[]).push([[164],{6164:function(e){e.exports=JSON.parse('{"ui.app.httpsHeadline":"!! Onveilige Verbinding !!","ui.app.httpsDescription":"Zonder HTTPS worden vertrouwelijke gegevens ongecodeerd overgedragen. ","ui.app.httpsLink":"Meer info","ui.app.httpsHref":"https://https.cio.gov/everything/","ui.app.safeModeHeadline":"!! Veilige modus ingeschakeld !!","ui.app.safeModeDescription":"Sommige functies van de Contao Manager zijn niet beschikbaar.","ui.app.safeModeExit":"Verlaat veilige modus","ui.app.limitedHeadline":"Verificatie op afstand","ui.app.limitedDescription":"Je hebt beperkte rechten omdat je zonder wachtwoord kunt inloggen.","ui.app.limitedLogout":"Opnieuw authenticeren","ui.app.totpHeadline":"Beveiligingsmelding","ui.app.totpDescription":"Configureer nu tweefactorauthenticatie om uw account te beveiligen.","ui.app.totpSetup":"Setup","ui.app.loading":"Contao Manager laden","ui.app.apiError":"Onverwachte API status","ui.app.configSecurity1":"VEILIGHEIDSWAARSCHUWING !!! De configuratie-map is niet beveiligd","ui.app.configSecurity2":"Contao Manager heeft vastgesteld dat de configuratiebestanden openbaar toegankelijk zijn. Alle bewerkingen zijn geblokkeerd totdat de map is beveiligd, anders zou een aanvaller toegang kunnen krijgen tot gevoelige gegevens van uw installatie.\\n\\nOm dit probleem op te lossen, moet u ervoor zorgen dat er geen toegang tot de map \\"contao-manager\\" is op uw server. Raadpleeg de handleiding van uw webserver voor meer informatie of neem contact op met uw hostingprovider.","ui.account.welcome":"Welkom","ui.account.intro1":"Welkom bij de Contao Manager, een universeel hulpmiddel om Contao Open Source CMS te installeren en te beheren. Bent u hier nieuw? {ReadthemanualTogetStarted}.","ui.account.introGetStarted":"{ReadTheManual} om te beginnen","ui.account.introManual":"lees de handleiding","ui.account.intro2":"Als u problemen ondervindt, kijk dan op {ourGithubIssues} en voel je vrij om nieuwe te maken voor iets dat nog niet is gemeld.","ui.account.introIssues":"Onze GitHub issues","ui.account.headline":"Gebruikers Account","ui.account.description":"Om uw installatie te beheren maakt u een account aan voor de Contao Manager. Houd er rekening mee dat dit account niet gerelateerd is aan het Contao-backend of frontend.","ui.account.username":"Gebruikersnaam","ui.account.password":"Wachtwoord","ui.account.passwordPlaceholder":"min. 8 tekens","ui.account.passwordLength":"Vul minstens 8 tekens in.","ui.account.loginInvalid":"Er is een fout opgetreden tijdens het aanmaken van het account. Probeer een andere gebruikersnaam.","ui.account.submit":"Maak een Account","ui.account.usePassword":"Gebruik je wachtwoord om in te loggen","ui.account.usePasskey":"Gebruik Passkey om in te loggen","ui.account.totpHeadline":"Tweefactorauthenticatie","ui.account.totpDescription":"Schakel tweefactorauthenticatie in. Dit voegt een extra beveiligingslaag toe aan uw account. Naast uw gebruikersnaam en wachtwoord moet u een verificatiecode invoeren die is gegenereerd door een tweefactorauthenticatie-app zoals 1Password, Authy, Google Authenticator, Microsoft Authenticator, LastPass Authenticator of een andere TOTP-app.","ui.account.totpSetup":"Nu configureren","ui.account.totpSkip":"Later configureren","ui.account.login":"Uitnodiging afwijzen","ui.account.contribute1":"Contao en de Contao Manager worden gesponsord door de non-profit Contao Association.","ui.account.contribute2":"Overweeg om bij te dragen aan Open Source door te {donate}.","ui.account.contributeDonate":"een donatie doen","ui.login.headline":"Aanmelden","ui.login.description":"Log in om uw installatie te beheren.","ui.login.username":"Gebruikersnaam","ui.login.password":"Wachtwoord","ui.login.totpHeadline":"Tweefactorauthenticatie","ui.login.totpDescription":"Voer uw verificatiecode in om het inlogproces te voltooien.","ui.login.totp":"Verificatiecode","ui.login.forgotPassword":"Wachtwoord vergeten?","ui.login.button":"Aanmelden","ui.login.passkey":"Aanmelden met Passkey","ui.login.cancel":"Annuleer","ui.login.or":"of","ui.login.locked":"Toegang is geweigerd omdat de Contao Manager is vergrendeld. Om te ontgrendelen, verwijdert u het {LockFile} -bestand in uw Contao Root map.","ui.logout.headline":"Time-out sessie","ui.logout.warning":"U bent meer dan 25 minuten inactief geweest. Om veiligheidsredenen wordt uw sessie binnenkort beëindigd.","ui.logout.expired":"Uw sessie is automatisch beëindigd omdat u meer dan 30 minuten inactief bent geweest.","ui.logout.renew":"Ingelogd blijven","ui.logout.logout":"Uitloggen","ui.logout.login":"Terug naar inloggen","ui.oauth.error":"Ongeldige OAuth-poging. Controleer de request parameters.","ui.oauth.https":"De omleidings-URI MOET een beveiligd protocol gebruiken (HTTPS :) om te voorkomen dat het authenticatie-token in duidelijke tekst wordt verzonden.","ui.oauth.headline":"Verificatie op afstand","ui.oauth.description":"De volgende toepassing of service vraagt om externe toegang tot uw Contao Manager.","ui.oauth.domain":"Zorg ervoor dat u deze URL en eigenaar vertrouwt, voordat u toegang toestaat!","ui.oauth.outOfScope":"Helaas beschikt u niet over de benodigde machtigingen om deze toegang te verlenen.","ui.oauth.allow":"Toegang verlenen","ui.oauth.deny":"Toegang ontzeggen","ui.oauth.switchUser":"Gebruikers wisselen","ui.scope.admin":"Beheerdersrechten, inclusief gebruikersbeheer.","ui.scope.install":"Installeer nieuwe pakketten en wijzig de Contao-configuratie.","ui.scope.update":"Update pakketten en voer onderhoudstaken uit.","ui.scope.read":"Pakketten en configuratie lezen","ui.boot.headline":"Systeem Controle","ui.boot.description":"Even geduld we analyseren uw server ...","ui.boot.issue1":"Installatieproblemen gedetecteerd","ui.boot.issue2":"Uw installatie heeft problemen die moeten worden opgelost voordat de Contao Manager kan worden gebruikt.","ui.boot.run":"Contao Manager Starten","ui.boot.safeMode":"Start in Veilige Modus","ui.recovery.headline":"Systeemherstel","ui.recovery.description":"De Contao Manager heeft bestanden gevonden die op Contao lijken, maar de opdrachtregel interface werkt niet zoals verwacht.","ui.recovery.console":"Console Uitvoer","ui.recovery.repairOptions":"Kies een optie om de installatie te repareren.","ui.recovery.repairHeadline":"Automatisch herstel","ui.recovery.repairDescription":"Pogingen om de installatie automatisch te herstellen door de cache van de toepassing opnieuw op te bouwen en de Composer-pakketten te herinstalleren.","ui.recovery.repairWarning":"Handmatige wijzigingen aan de vendor bestanden kunnen verloren gaan!","ui.recovery.repairFailed":"Automatisch herstel is mislukt. Probeer de Veilige Modus om de installatie handmatig te repareren.","ui.recovery.repairButton":"Voer systeemreparatie uit","ui.recovery.safeModeHeadline":"Veilige Modus","ui.recovery.safeModeDescription":"Door de Contao Manager te starten in de veilige modus kunnen pakketten worden beheerd en bepaalde onderhoudstaken worden uitgevoerd, maar functies die afhankelijk zijn van een werkende Contao-installatie zijn niet beschikbaar.","ui.recovery.safeModeButton":"Start in Veilige Modus","ui.server.pending":"Wachtend …","ui.server.running":"Analyseren …","ui.server.error":"Controle mislukt vanwege een onverwachte reactie van de server.","ui.server.details":"Details","ui.server.prerequisite":"Controle geannuleerd als gevolg van een ontbrekende voorwaarde.","ui.server.selfUpdate.title":"Updates van de Contao Manager","ui.server.selfUpdate.update":"Een nieuwe versie van Contao Manager {latest} is beschikbaar.","ui.server.selfUpdate.manualUpdate":"Er is een nieuwe Contao Manager-versie {latest} beschikbaar. Uw server ondersteunt geen automatische updates, download de nieuwe versie van {download}.","ui.server.selfUpdate.latest":"U gebruikt de laatste versie {huidige}.","ui.server.selfUpdate.dev":"Ontwikkelingsversies ondersteunen geen automatische updates.","ui.server.selfUpdate.unsupported":"Een nieuwe versie is beschikbaar, maar deze ondersteunt uw PHP-versie niet.","ui.server.selfUpdate.button":"Voer Zelf-Update uit","ui.server.selfUpdate.continue":"Ga verder","ui.server.config.title":"Server Configuratie","ui.server.config.setup":"Configureer","ui.server.config.change":"Wijzig","ui.server.config.save":"Bewaar","ui.server.config.cancel":"Annuleer","ui.server.config.customOption":"Ander ...","ui.server.config.description":"Om achtergrondtaken correct uit te voeren, moet de Contao Manager weten waar hij de PHP -opdrachtregel binair kan vinden en hoe de opdrachten uit te voeren die zijn gescheiden van het web proces.","ui.server.config.formTitle":"Server Configuratie","ui.server.config.formText":"Voer het pad naar uw PHP-binair bestand in. Zorg ervoor dat het binaire bestand dezelfde PHP-versie is als gebruikt in het web proces.","ui.server.config.cloudTitle":"Composer Resolver Cloud","ui.server.config.cloudText":"Met de Composer Cloud Resolver kunt u Composer-afhankelijkheden installeren, zelfs als uw server niet voldoende lokaal geheugen heeft. Houd er rekening mee dat uw pakketinformatie wordt verzonden naar een cloudserver die wordt beheerd door de Contao Association.","ui.server.config.cloud":"De Composer Cloud Resolver gebruiken","ui.server.config.cli":"PHP Binary","ui.server.config.stateErrorCli":"Ongeldige PHP binary gevonden op de server.","ui.server.config.stateErrorCloud":"De Composer Cloud Resolver wordt niet ondersteund.","ui.server.config.stateSuccess":"PHP binary in {php_cli}.","ui.server.config.cloudEnabled":"Pakketafhankelijkheden worden opgelost met behulp van de Composer Resolver Cloud.","ui.server.config.cloudDisabled":"De Composer Resolver Cloud is uitgeschakeld.","ui.server.php_web.title":"PHP Web Proces","ui.server.php_web.below7":"PHP versie gevonden {version}, stap zo spoedig mogelijk over op PHP 7.","ui.server.php_web.success":"PHP versie gevonden {version}, geen bekende problemen gevonden.","ui.server.php_cli.title":"PHP Command Line Interface","ui.server.php_cli.success":"PHP versie gevonden {version}, geen bekende problemen gevonden.","ui.server.composer.title":"Composer Omgeving","ui.server.composer.success":"Geen bekende problemen gevonden.","ui.server.composer.install":"Afhankelijkheden van Composer zijn niet geïnstalleerd.","ui.server.composer.button":"Installeren","ui.server.contao.title":"Contao Installatie","ui.server.contao.setup":"Setup","ui.server.contao.check":"Controleer database","ui.server.contao.empty":"Er is geen Contao installatie gevonden.","ui.server.contao.old":"Contao versie {version} is niet compatibel met de Contao Manager, installatie handmatig updaten.","ui.server.contao.found":"Gevonden Contao {version} (API versie {api}).","ui.server.contao.connectionError":"Kan geen verbinding maken met de databaseserver.","ui.server.contao.connectionProblem":"Databaseprobleem gevonden.","ui.server.contao.missingUser":"Beheerdersaccount niet gevonden.","ui.setup.continue":"Ga verder","ui.setup.manager":"Contao Manager Starten","ui.setup.cancel":"Annuleer","ui.setup.welcome":"Welkom","ui.setup.welcome1":"Deze wizard leidt u door de nodige stappen om uw Contao Open Source CMS-installatie in te stellen.","ui.setup.welcome2":"Als je vragen hebt, vind je documentatie, forums, een Slack-kanaal en meer op de {support}-pagina.","ui.setup.support":"Community ondersteuning","ui.setup.start":"Begin","ui.setup.complete":"Gefeliciteerd!","ui.setup.complete1":"Contao {version} is succesvol geïnstalleerd.","ui.setup.complete2":"Om het installatieproces te voltooien, opent u de installatietool om de databaseverbinding te configureren en een back-endgebruiker aan te maken.","ui.setup.complete3":"U kunt nu beginnen met het maken van uw website in de backend van Contao. Als u extra extensies nodig heeft, gaat u verder naar de Contao Manager.","ui.setup.installTool":"Open de installatietool","ui.setup.login":"Log in op Contao","ui.setup.funding":"Gratis software is \\"gratis\\" zoals in \\"aardig zijn voor iemand\\", niet zoals in \\"gratis bier\\". Voor een Open Source-project als Contao zijn bedragen nodig die niet door één persoon of bedrijf kunnen worden bijeengebracht.\\nAls u een website heeft of websites verkoopt die met Contao zijn gebouwd, zouden we graag zien dat u een financiële bijdrage levert aan het product waar uw bedrijf van afhankelijk is.","ui.setup.fundingLink":"Kom meer te weten","ui.setup.document-root.headline":"Webserver Instellingen","ui.setup.document-root.warning":"Om Contao via de Contao Manager te installeren, moet u de documentroot op de webserver repareren.","ui.setup.document-root.description1":"Contao gebruikt een aparte map voor openbare bestanden, toepassingsbestanden worden in de bovenliggende map geïnstalleerd. Contao kan niet worden geïnstalleerd als de mappenstructuur niet correct is of als de mappen niet leeg zijn.","ui.setup.document-root.description2":"Als u niet weet hoe u uw document root moet configureren, lees dan de Contao documentatie of neem contact op met uw hostingprovider.","ui.setup.document-root.documentation":"Lees de Documentatie","ui.setup.document-root.conflictsTitle":"Installatiemap niet leeg","ui.setup.document-root.conflictsDirectory":"De hoofdmap van uw toekomstige Contao-installatie is niet leeg, we hebben {count} bestand(en) gevonden die mogelijk worden overschreven door het installatieproces. Het wordt aanbevolen om een lege mappenstructuur voor Contao aan te maken, maar u kunt ook de volgende bestanden verwijderen en opnieuw controleren of u zeker weet dat ze niet worden gebruikt.","ui.setup.document-root.ignoreConflicts":"Ik wil Contao installeren in de niet-lege map. Ik begrijp dat dit alle bestaande bestanden op mijn webruimte kan overschrijven.","ui.setup.document-root.check":"Opnieuw controleren","ui.setup.document-root.create":"Maak mappen","ui.setup.document-root.change":"Wijzig mappen","ui.setup.document-root.formTitle":"Mapinstellingen","ui.setup.document-root.formText1":"De Contao Manager kan automatisch een nieuwe mappen structuur op de server maken.","ui.setup.document-root.formText2":"U moet de nieuwe document root handmatig configureren (bijv. via een hosting admin paneel).","ui.setup.document-root.autoconfig":"Ik begrijp dat ik mijn serverconfiguratie moet wijzigen. Het niet configureren van de document root zal de Contao Manager stuk maken en configuratiebestanden openbaar maken (inclusief accountgegevens en wachtwoorden)!","ui.setup.document-root.directory":"Nieuwe Map","ui.setup.document-root.currentRoot":"Huidig Document Root","ui.setup.document-root.newRoot":"Nieuwe Document Root","ui.setup.document-root.finish":"Stel Mappen In","ui.setup.document-root.publicDir":"Gebruik {dir} voor publieke bestanden (voor Contao {version})","ui.setup.document-root.directoryInvalid":"Voer een geldige mapnaam in.","ui.setup.document-root.directoryExists":"De doelmap bestaat al. Voer een andere naam in.","ui.setup.document-root.confirmation":"De Contao Manager heeft met succes de benodigde map gemaakt voor uw Contao installatie. U moet nu de document root configureren op uw webserver. Laad deze pagina niet opnieuw.","ui.setup.document-root.reload":"Pagina herladen","ui.setup.document-root.success":"De mappenstructuur op uw webserver is correct ingesteld!","ui.setup.document-root.installingProjectDir":"Applicatiebestanden worden geïnstalleerd in {dir}.","ui.setup.document-root.installingPublicDir":"Openbare bestanden worden geïnstalleerd in {dir}.","ui.setup.document-root.installedProjectDir":"Applicatiebestanden zijn geïnstalleerd in {dir}.","ui.setup.document-root.installedPublicDir":"Openbare bestanden zijn geïnstalleerd in {dir}.","ui.setup.create-project.headline":"Contao Installatie","ui.setup.create-project.description":"De ontwikkeling van Contao volgt het principe van {semver}, er wordt elke zes maanden een nieuwe secundaire versie uitgebracht. De momenteel ondersteunde releases zijn:","ui.setup.create-project.semver":"Semantische versiebeheer","ui.setup.create-project.latestTitle":"Nieuwste","ui.setup.create-project.ltsTitle":"Lange Termijn Support","ui.setup.create-project.latestQ1":"Onze nieuwste versie biedt de meeste functies met ondersteuning tot februari {jaar}.","ui.setup.create-project.latestQ3":"Onze nieuwste versie biedt de meeste functies met ondersteuning tot augustus {jaar}.","ui.setup.create-project.ltsText":"Onze huidige LTS-versie, als je focust op stabiliteit. Biedt langdurige ondersteuning tot februari {jaar}.","ui.setup.create-project.pltsText":"De vorige LTS-versie heeft nog steeds ondersteuning op lange termijn tot februari {jaar}.","ui.setup.create-project.requiresPHP":"Vereist minimaal PHP {version}, je hebt PHP {current}.","ui.setup.create-project.releaseplan":"Bekijk het {ContaoReleasePlan} voor gedetailleerde informatie.","ui.setup.create-project.releaseplanLink":"Contao Release Plan","ui.setup.create-project.installed":"Contao {version} is succesvol op de server geïnstalleerd. Ga door met het instellen van uw database of start de Contao Manager om een andere versie te installeren.","ui.setup.create-project.formTitle":"Selecteer een distributie","ui.setup.create-project.formText":"Kies welke versie moet worden geïnstalleerd.","ui.setup.create-project.version":"Versie","ui.setup.create-project.demo":"Installeer de Contao demo website","ui.setup.create-project.demoDescription":"De demowebsite helpt u vertrouwd te raken met Contao en alle kernfuncties ervan. Meer thema\'s zijn te vinden in de {store}.","ui.setup.create-project.coreOnly":"Minimale installatie (alleen de kern)","ui.setup.create-project.noUpdate":"Installatie overslaan (alleen expert!)","ui.setup.create-project.theme":"Contao Thema","ui.setup.create-project.themeInstall":"Om een Contao-thema te installeren, gebruikt u de zoekinvoer of uploadt u een themabestand (.cto/.zip) dat installatie via Contao Manager ondersteunt.","ui.setup.create-project.themeBuy":"Zorg ervoor dat je de officiële {store} bezoekt.","ui.setup.create-project.themeStore":"Contao Thema\'s Winkel","ui.setup.create-project.themeUpload":"Themabestand uploaden (.cto/.zip)","ui.setup.create-project.themeInvalid":"Het geüploade bestand is geen Contao-thema of ondersteunt de Contao Manager niet.","ui.setup.create-project.themeWarning":"De Contao Manager weet niet of dit thema compatibel is met uw server. Als u vragen heeft, neem dan contact op met de themaleverancier.","ui.setup.create-project.themeTitle":"Themadetails bekijken","ui.setup.create-project.themeDetails":"De volgende afhankelijkheden en bestanden worden met dit thema geïnstalleerd.","ui.setup.create-project.themeRequire":"{count} Afhankelijkheden | {count} Afhankelijkheden","ui.setup.create-project.themeFiles":"{count} Bestand | {count} Bestanden","ui.setup.create-project.theme.or":"of zoek naar openbare thema\'s","ui.setup.create-project.theme.search":"Thema\'s zoeken","ui.setup.create-project.theme.more":"Meer thema\'s","ui.setup.create-project.theme.empty":"Geen thema\'s die overeenkomen met {query}","ui.setup.create-project.theme.uploaded":"Het themabestand is succesvol geüpload.","ui.setup.create-project.theme.packageName":"Pakketnaam","ui.setup.create-project.theme.version":"Versie","ui.setup.create-project.theme.authors":"Auteur(s)","ui.setup.create-project.theme.upload":"{name} ({size}) uploaden","ui.setup.create-project.install":"Installeren","ui.setup.create-project.cancel":"Annuleer","ui.setup.create-project.fileError":"Het bestand composer.json kon niet worden gevonden in {file}.","ui.setup.create-project.jsonError":"composer.json bevat ongeldige JSON.","ui.setup.create-project.schemaError":"de schemavalidatie van composer.json is mislukt.","ui.setup.database-connection.headline":"Database verbinding","ui.setup.database-connection.description":"Contao vereist een MySQL-database (of een compatibele fork zoals MariaDB) om pagina\'s, inhoud, gebruikers en andere relationele gegevens op te slaan. Verbindingsparameters worden opgeslagen in het bestand {env} in de projectroot van uw Contao-installatie.","ui.setup.database-connection.formTitle":"Verbindingsparameters","ui.setup.database-connection.formText":"Voer een database-URL in of vul de velden gebruikersnaam, wachtwoord, server en database apart in.","ui.setup.database-connection.url":"Database URL","ui.setup.database-connection.validUrl":"Database-URL is ongeldig of verbinding met de server is mislukt.","ui.setup.database-connection.or":"of","ui.setup.database-connection.user":"Gebruikersnaam","ui.setup.database-connection.password":"Wachtwoord","ui.setup.database-connection.server":"Server (:Port) ","ui.setup.database-connection.database":"Database Naam","ui.setup.database-connection.connected":"Succesvol verbonden met database {database} op {server}.","ui.setup.database-connection.error":"Fout bij het verbinden met de database.","ui.setup.database-connection.problem":"Contao heeft een probleem gedetecteerd met uw database server.","ui.setup.database-connection.schemaTitle":"Database Schema","ui.setup.database-connection.migration":"Er is één migratie in behandeling. | Er zijn {count} migraties in behandeling.","ui.setup.database-connection.schema":"Er is één schema-update in behandeling. | Er zijn {count} schema-updates in behandeling.","ui.setup.database-connection.noChanges":"Uw databaseschema is up-to-date.","ui.setup.database-connection.check":"Controleer database","ui.setup.database-connection.skip":"Overslaan","ui.setup.database-connection.save":"Bewaar","ui.setup.database-connection.change":"Inloggegevens wijzigen","ui.setup.database-connection.restoreTitle":"Database importeren","ui.setup.database-connection.restoreText":"Het thema dat u zojuist hebt geïnstalleerd, bevat een databaseback-up. Herstel de database om themagegevens te importeren of sla deze stap over om te beginnen met een lege Contao-installatie. | Het thema dat u zojuist hebt geïnstalleerd, bevat meerdere databaseback-ups. Selecteer een back-upbestand om themagegevens te importeren of sla deze stap over om te beginnen met een lege Contao-installatie.","ui.setup.database-connection.backup":"Maak een back-up van de huidige database vóór het importeren","ui.setup.database-connection.backupWarning":"Alle gegevens in de database worden bij het importeren overschreven! Maak eerst een back-up als de database niet leeg is.","ui.setup.database-connection.restore":"Themadatabase importeren","ui.setup.database-connection.restoreOption":"Back-up van {date} ({size})","ui.setup.database-connection.restored":"Uw themadatabase is succesvol geïmporteerd. Ga door met het valideren van uw databaseschema.","ui.setup.backend-user.success":"Er is een beheerdersaccount voor de Contao-backend gevonden in uw database. Gebruik de Contao-backend om meer gebruikers toe te voegen.","ui.setup.backend-user.error":"Kan gebruikerslijst niet ophalen. Controleer de console-uitvoer voor details.","ui.setup.backend-user.headline":"Backend Account","ui.setup.backend-user.description":"Om uw website te beheren, moet u ten minste één beheerdersaccount hebben voor de Contao-backend. Houd er rekening mee dat dit account niet gerelateerd is aan de Contao Manager.","ui.setup.backend-user.formTitle":"Maak een Account","ui.setup.backend-user.formText":"Voer de gegevens in voor het nieuwe backend-account.","ui.setup.backend-user.username":"Gebruikersnaam","ui.setup.backend-user.name":"Naam","ui.setup.backend-user.email":"Emailadres","ui.setup.backend-user.emailInvalid":"Vul a.u.b. een geldig e-mailadres in","ui.setup.backend-user.password":"Wachtwoord","ui.setup.backend-user.passwordPlaceholder":"min. 8 tekens","ui.setup.backend-user.passwordLength":"Vul minstens 8 tekens in.","ui.setup.backend-user.create":"Account toevoegen","ui.task.headline":"Achtergrond taak","ui.task.loading":"Details laden ...","ui.task.created":"Details laden ...","ui.task.active":"Wacht terwijl de Contao Manager taakbewerkingen op de achtergrond uitvoert.","ui.task.complete":"Alle bewerkingen zijn met succes voltooid. Controleer de console uitvoer voor meer informatie.","ui.task.paused":"Een achtergrondbewerking stopte onverwacht. Controleer de console -uitvoer.","ui.task.aborting":"Wacht terwijl de achtergrondbewerkingen worden geannuleerd.","ui.task.stopped":"Sommige achtergrondbewerkingen werden geannuleerd. Controleer de console -uitvoer.","ui.task.error":"Een achtergrondbewerking stopte onverwacht. Controleer de console -uitvoer.","ui.task.failed":"De Contao -manager kon geen achtergrondtaak starten!","ui.task.failedDescription1":"Er ging iets mis bij het uitvoeren van bewerkingen op de achtergrond.","ui.task.failedDescription2":"Als dit opnieuw gebeurt, wordt uw server mogelijk niet ondersteund.","ui.task.reportProblem":"Een probleem melden","ui.task.pausedDescription":"Klik op \\"Doorgaan\\" als u de foutmelding wilt negeren en de resterende bewerkingen wilt uitvoeren.","ui.task.sponsor":"Composer Cloud gesponsord door {sponsor}","ui.task.buttonAudit":"Update Database","ui.task.buttonClose":"Sluit","ui.task.buttonConfirm":"Bevestig & Sluit","ui.task.buttonContinue":"Ga verder","ui.task.buttonCancel":"Annuleer","ui.task.confirmCancel":"Weet u zeker om deze taak te annuleren? Dit kan uw Contao-installatie in een niet werkende staat achterlaten!","ui.task.autoclose":"Sluit taakdetails bij succes","ui.console.toggle":"Toon/Verberg Console Output","ui.console.showLog":"Toon volledig consolelogboek","ui.console.copyLog":"Kopieer logboek naar klembord","ui.migrate.headline":"Database Updates","ui.migrate.migrationsOnly":"(alleen migraties)","ui.migrate.schemaOnly":"(alleen schema)","ui.migrate.loading":"Even geduld a.u.b., we controleren uw database …","ui.migrate.empty":"Geen lopende migraties of schema-updates gevonden. Uw database is up-to-date.","ui.migrate.emptyMigrations":"Geen lopende migraties gevonden. Zorg ervoor dat u ook controleert op schema-updates.","ui.migrate.emptySchema":"Geen lopende schema-updates gevonden. Zorg ervoor dat u ook controleert op migraties.","ui.migrate.pending":"Uw database is niet up-to-date. Bekijk de console-uitvoer hieronder en voer de wijzigingen door.","ui.migrate.previousChanges":"Een eerdere databasemigratie is niet bevestigd.\\nBekijk de console-uitvoer hieronder en ga verder met het bekijken van de volgende wijzigingen.","ui.migrate.previousComplete":"Een eerdere databasemigratie is niet bevestigd. Bekijk de console-uitvoer hieronder.\\nEr zijn geen wijzigingen meer in behandeling.","ui.migrate.appliedChanges":"Database-updates zijn toegepast.\\nBekijk de console-uitvoer hieronder en ga verder met het bekijken van de volgende wijzigingen.","ui.migrate.appliedComplete":"Database-updates zijn toegepast.\\nEr zijn geen lopende migraties of schema-updates meer. Uw database is up-to-date.","ui.migrate.problem":"Contao heeft een probleem gedetecteerd met uw database server.\\nBekijk de console-uitvoer hieronder om erachter te komen wat er moet worden opgelost. | Contao heeft problemen met uw database server gedetecteerd.\\nBekijk de console-uitvoer hieronder om erachter te komen wat er moet worden opgelost.","ui.migrate.warning":"Contao heeft een verkeerde configuratie van uw database server gedetecteerd.\\nWaarschuwingen kunnen tijdelijk worden overgeslagen, maar moeten worden opgelost voor optimale prestaties en gegevensintegriteit.","ui.migrate.error":"De wijzigingen kunnen niet worden toegepast. Uw database is mogelijk gewijzigd. Controleer het nogmaals om het opnieuw te proberen.","ui.migrate.execute":"Uitvoeren","ui.migrate.close":"Sluit","ui.migrate.confirm":"Bevestig & Sluit","ui.migrate.cancel":"Annuleer","ui.migrate.continue":"Ga verder","ui.migrate.setup":"Setup","ui.migrate.skip":"Overslaan","ui.migrate.retry":"Opnieuw controleren","ui.migrate.retryAll":"Alles controleren","ui.migrate.withDeletes":"Voer alle database wijzigingen uit, inclusief DROP-query\'s.","ui.migrate.migrationTitle":"Database Migraties","ui.migrate.schemaTitle":"Schema Updates","ui.migrate.problemTitle":"Database Problemen","ui.migrate.warningTitle":"Database Waarschuwingen","ui.migrate.addTable":"Tabel {tabel} toevoegen","ui.migrate.dropTable":"Drop tabel {table}","ui.migrate.addField":"Veld {tabel}.{field} toevoegen","ui.migrate.changeField":"Veld {table}.{field} wijzigen","ui.migrate.dropField":"Drop veld {table}.{field}","ui.migrate.createIndex":"Maak index \\"{name}\\" op {table}","ui.migrate.dropIndex":"Drop index \\"{name}\\" op {table}","ui.widget.mandatory":"Dit veld mag niet leeg zijn.","ui.widget.blankOption":"Selecteer ...","ui.widget.showPassword":"Toon wachtwoord","ui.widget.hidePassword":"Verberg wachtwoord","ui.error.title":"HTTP verzoek voor \\"{method} {url}\\" mislukt.","ui.error.server500":"Het lijkt erop dat er een onverwachte fout is gebeurd op uw server. Controleer de logbestanden van uw webserver (Apache/Nginx) en de Contao Manager-logboeken in \\"contao-manager/logs\\".","ui.error.response":"De server heeft een antwoord geretourneerd met statuscode {status}.","ui.error.moreLink":"Meer informatie","ui.error.support":"Contao Ondersteuning","ui.error.permission":"Je hebt geen toestemming om deze functie te gebruiken.","ui.footer.help":"Help","ui.footer.reportProblem":"Een probleem melden","ui.navigation.discover":"Ontdekken","ui.navigation.packages":"Pakketten","ui.navigation.tools":"Hulpmiddelen","ui.navigation.installTool":"Installatie Tool","ui.navigation.backend":"Contao Backend","ui.navigation.debug":"Contao foutopsporingsmodus","ui.navigation.logViewer":"Log viewer","ui.navigation.phpinfo":"PHP Informatie","ui.navigation.phpinfoLoading":"PHP informatie laden","ui.navigation.maintenance":"Onderhoud","ui.navigation.rebuildCache":"Cache opnieuw opbouwen","ui.navigation.users":"Accounts","ui.navigation.systemCheck":"Systeem Controle","ui.navigation.advanced":"Gevorderd","ui.navigation.logout":"Uitloggen","ui.maintenance.database.title":"Databasemigraties en back-ups","ui.maintenance.database.description":"Databasemigraties zorgen voor consistente gegevens en tabelschema\'s.","ui.maintenance.database.migrations":"Eén databasemigratie in behandeling | {count} lopende databasemigraties","ui.maintenance.database.schemaUpdates":"Eén schema update in behandeling | {count} schema updates in behandeling","ui.maintenance.database.error":"Databaseprobleem gevonden.","ui.maintenance.database.warning":"Database waarschuwingen gevonden.","ui.maintenance.database.button":"Controleer database","ui.maintenance.database.migrationOnly":"Controleer alleen migraties","ui.maintenance.database.schemaOnly":"Alleen schema controleren","ui.maintenance.database.installTool":"Open de installatietool","ui.maintenance.database.createBackup":"Een backup maken","ui.maintenance.database.backupUnsupported":"Databaseback-ups worden niet ondersteund door uw Contao-versie.","ui.maintenance.database.backupList":"U heeft één databaseback-up, gemaakt op {date}. | U heeft {count} databaseback-ups, de laatste is gemaakt op {date}.","ui.maintenance.database.backupEmpty":"U heeft momenteel geen databaseback-ups.","ui.maintenance.rebuildCache.title":"Applicatie Cache","ui.maintenance.rebuildCache.description":"Het opnieuw opbouwen van de applicatie-cache is vereist na het wijzigen van een van de configuratiebestanden.","ui.maintenance.rebuildCache.rebuildProd":"Produktieomgeving Cache opnieuw opbouwen","ui.maintenance.rebuildCache.rebuildDev":"Cache ontwikkelingsomgeving opnieuw opbouwen","ui.maintenance.rebuildCache.clearProd":"Cache van de productieomgeving leegmaken","ui.maintenance.rebuildCache.clearDev":"Cache ontwikkelingsomgeving legen","ui.maintenance.installTool.title":"Contao Installatie Programma","ui.maintenance.installTool.description":"Het Contao-installatie programma wordt automatisch vergrendeld als u een wachtwoord drie keer achter elkaar verkeerd invoert.","ui.maintenance.installTool.unlock":"Installatie Programma Ontgrendelen","ui.maintenance.installTool.lock":"Installatie Programma Vergrendelen","ui.maintenance.dumpAutoload.title":"Composer Class Loader","ui.maintenance.dumpAutoload.description":"De autoloader van Composer is verantwoordelijk voor PHP class loading. De autoloader moet worden gedumpt nadat aangepaste namespaces zijn toegevoegd aan de root van composer.json.","ui.maintenance.dumpAutoload.button":"Dump Autoloader","ui.maintenance.composerInstall.title":"Composer Afhankelijkheden","ui.maintenance.composerInstall.description":"Composerafhankelijkheden bevinden zich in de map {vendor} in uw applicatie root. Het opnieuw installeren van de afhankelijkheden kan nodig zijn na manipulatie of het handmatig uploaden van het {composerLock} bestand.","ui.maintenance.composerInstall.button":"Installatieprogramma Uitvoeren","ui.maintenance.composerInstall.update":"Start Composer update","ui.maintenance.composerCache.title":"Composer Cache","ui.maintenance.composerCache.description":"Composer cached gedownloade pakketten voor betere prestaties. Als u problemen hebt zoals onvolledige bestanden, probeer dan de Composer-cache te verwijderen om een nieuwe download te forceren.","ui.maintenance.composerCache.button":"Cache Wissen","ui.maintenance.maintenanceMode.title":"Onderhoudsmodus","ui.maintenance.maintenanceMode.description":"Contao in de onderhoudsmodus zetten toont een \\"503 service niet beschikbaar\\" -template voor de website.","ui.maintenance.maintenanceMode.enable":"Inschakelen","ui.maintenance.maintenanceMode.disable":"Uitschakelen","ui.maintenance.debugMode.title":"Foutopsporingsmodus","ui.maintenance.debugMode.description":"Activeer de foutopsporingsmodus door een gebruiker en wachtwoord in te stellen voor het ingangspunt {AppDevphp}.","ui.maintenance.debugMode.descriptionJwt":"Schakelt foutopsporingsmodus in door een cookie in te stellen voor het huidige domein.","ui.maintenance.debugMode.activate":"Activeren","ui.maintenance.debugMode.deactivate":"Deactiveren","ui.maintenance.debugMode.credentials":"Aanmeldgegevens","ui.maintenance.debugMode.user":"Geef een gebruikersnaam op voor de foutopsporingsmodus.","ui.maintenance.debugMode.password":"Geef een wachtwoord op voor de foutopsporingsmodus.","ui.maintenance.opcodeCache.title":"Opcode Cache","ui.maintenance.opcodeCache.description":"Opcode slaat PHP-bestanden op in het web-proces voor snellere uitvoering. Het moet onder bepaalde omstandigheden worden verwijderd als bestanden niet worden herkend na wijziging.","ui.maintenance.opcodeCache.button":"Wis Cache","ui.maintenance.safeMode":"Niet beschikbaar in Veilige Modus","ui.maintenance.unsupported":"Wordt niet ondersteund door uw Contao versie","ui.packages.updateButton":"Pakketten Updaten","ui.packages.searchButton":"Pakketten zoeken","ui.packages.searchPlaceholder":"Zoek pakketten...","ui.packages.uploadOverlay":"Sleep bestanden om ze te uploaden","ui.packages.uploadButton":"Pakketten uploaden","ui.packages.uploadMessage":"U heeft één onbevestigde upload. | U heeft {count} onbevestigde uploads.","ui.packages.uploadApply":"Bevestig Uploads","ui.packages.uploadReset":"Verwijder Uploads","ui.packages.uploadIncomplete":"Dit bestand is niet volledig geüpload. Verwijder het en probeer opnieuw.","ui.packages.uploadDuplicate":"Dit bestand lijkt meerdere keren te zijn geüpload. Verwijder de duplicaten.","ui.packages.uploadInstalled":"Dit bestand is al geïnstalleerd. Verwijder de duplicaten.","ui.packages.uploadUnsupported":"Uploads worden niet ondersteund in uw installatie. Zorg ervoor dat de PHP ZIP-extensie is geïnstalleerd en werk uw afhankelijkheden bij.","ui.packages.changesMessage":"U heeft één onbevestigde wijziging. | U heeft {count} onbevestigde wijzigingen.","ui.packages.changesDryrun":"Testloop","ui.packages.changesApply":"Wijzigingen toepassen","ui.packages.changesApplyAll":"Update alle pakketten","ui.packages.changesDryrunAll":"Dry Run alle pakketten","ui.packages.changesReset":"Reset wijzigingen","ui.packages.changesReview":"Wijzigingen controleren","ui.packagelist.loading":"Bezig met laden ...","ui.packagelist.uploads":"Uploads","ui.packagelist.added":"Nieuwe pakketten","ui.packagelist.installed":"Geïnstalleerde pakketten","ui.package.hintRevert":"Wijzigingen terugdraaien","ui.package.hintNoupdate":"Niet updaten","ui.package.hintConstraint":"Dit pakket wordt geïnstalleerd met beperkingen {constraint} wanneer u de wijzigingen toepast.","ui.package.hintConstraintBest":"Dit pakket wordt geïnstalleerd in de best beschikbare versie wanneer u de wijzigingen toepast.","ui.package.hintConstraintChange":"De beperking voor dit pakket wordt gewijzigd van \\"{from}\\" naar \\"{to}\\" wanneer u de wijzigingen toepast.","ui.package.hintConstraintUpdate":"Dit pakket wordt bijgewerkt wanneer u de wijzigingen toepast.","ui.package.hintAdded":"Dit pakket wordt geïnstalleerd wanneer u de wijzigingen toepast.","ui.package.hintRemoved":"Dit pakket wordt verwijderd wanneer u de wijzigingen toepast.","ui.package.requiredTitle":"handmatig toegevoegd","ui.package.requiredText":"Dit pakket is vereist in composer.json maar is niet geïnstalleerd.","ui.package.removedTitle":"handmatig verwijderd","ui.package.removedText":"Dit pakket is verwijderd van uw composer.json.","ui.package.installed":"Momenteel geïnstalleerd:","ui.package.version":"Versie {version}","ui.package.additionalDownloads":"{count} Download | {count} Downloads","ui.package.additionalStars":"{count} Ster | {count} Sterren","ui.package.editConstraint":"Bewerk","ui.package.uploadConstraint":"Deze beperking wordt bepaald door het geüploade pakket.","ui.package.updateButton":"Update","ui.package.removeButton":"Verwijder","ui.package.installButton":"Pakket toevoegen","ui.package.installButtonShort":"Toevoegen","ui.package.detailsButton":"Details","ui.package.latestConstraint":"laatste versie","ui.package.update":"Update beschikbaar","ui.package.updateLatest":"laatste versie","ui.package.updateAvailable":"{version} beschikbaar","ui.package.updateUnknown":"Onbekende versie","ui.package.updateConstraint":"Er is een nieuwere versie beschikbaar buiten uw versiebeperking.","ui.package.incompatible":"{package} werkt niet met Contao {constraint}.","ui.package.incompatibleWarning":"{package} werkt niet met Contao {constraint} in geen van de stabiele releases. Wilt u het pakket toevoegen en een versiebeperking instellen om te proberen een ontwikkelingsbranch te installeren?","ui.package.incompatibleConstraint":"Dit pakket heeft geen stabiele release voor Contao {constraint}. Stel een versiebeperking in om te proberen een ontwikkelingsbranch te installeren.","ui.package.incompatibleButton":"Installeren","ui.cloudStatus.headline":"Composer Resolver Cloud","ui.cloudStatus.version":"Versie {version}","ui.cloudStatus.waitingTime":"Wacht Tijd","ui.cloudStatus.jobs":"Huidige Taken","ui.cloudStatus.workers":"Werkers","ui.cloudStatus.approx":"{minutes} min","ui.cloudStatus.none":"geen","ui.cloudStatus.short":"ca. {minutes} min","ui.cloudStatus.long":"ong. {minutes} min {seconds} sec","ui.cloudStatus.error":"Niet in staat om de status van de Composer Resolver Cloud op te halen. Het kan down zijn voor onderhouds- of ervaringsproblemen.","ui.cloudStatus.button":"Cloud Status","ui.cloudStatus.refresh":"Vernieuw de Cloud Status","ui.log-viewer.loading":"Bezig met laden ...","ui.log-viewer.empty":"Er zijn geen logbestanden op uw server.","ui.log-viewer.reload":"Herladen","ui.log-viewer.file":"Logbestand","ui.log-viewer.channel":"Kanaal","ui.log-viewer.channelTitle":"Het kanaal waarop dit bericht is geregistreerd.","ui.log-viewer.level":"Niveau","ui.log-viewer.levelTitle":"Ernst van het logbericht.","ui.log-viewer.timeHeader":"Tijd","ui.log-viewer.messageHeader":"Bericht","ui.log-viewer.showContext":"Context tonen","ui.log-viewer.hideContext":"Context verbergen","ui.log-viewer.showExtra":"Extra tonen","ui.log-viewer.hideExtra":"Extra verbergen","ui.log-viewer.more":"Meer laden …","ui.log-viewer.download":"Download","ui.log-viewer.downloadTitle":"Download bestand \\"{file}\\"","ui.log-viewer.prodEnvironment":"Productieomgeving","ui.log-viewer.devEnvironment":"Ontwikkelomgeving (foutopsporingsmodus)","ui.user-manager.loading":"Gebruikers laden…","ui.user-manager.changePassword":"Wachtwoord wijzigen","ui.user-manager.setupTotp":"Tweefactorauthenticatie instellen","ui.user-manager.disableTotp":"Schakel tweefactorauthenticatie uit","ui.user-manager.invite":"Gebruiker uitnodigen","ui.user-manager.delete":"Verwijderen","ui.user-manager.deleteConfirm":"Wil je gebruiker \\"{username}\\" echt verwijderen?","ui.user-manager.deleted":"Gebruiker {username} succesvol verwijderd","ui.user-manager.passwordHeadline":"Wachtwoord wijzigen","ui.user-manager.passwordText":"Om uw wachtwoord te wijzigen, vult u uw huidige wachtwoord en een nieuw wachtwoord in de daarvoor bestemde velden in.","ui.user-manager.currentPassword":"Huidig wachtwoord","ui.user-manager.newPassword":"Nieuw wachtwoord","ui.user-manager.passwordPlaceholder":"min. 8 tekens","ui.user-manager.submitPassword":"Indienen","ui.user-manager.passwordChanged":"Je wachtwoord is succesvol gewijzigd.","ui.user-manager.passwordError":"Dit wachtwoord is onjuist.","ui.user-manager.inviteHeadline":"Gebruiker uitnodigen","ui.user-manager.inviteText":"Als u meerdere inloggegevens nodig heeft voor de Contao Manager, kunt u hier een uitnodigingslink aanmaken. Deel deze link met iemand of gebruik hem op een ander apparaat om een ​​nieuw account met de gewenste machtigingen aan te maken.","ui.user-manager.inviteSuccess1":"Er is een nieuwe uitnodigingslink aangemaakt. De onderstaande URL kan worden gebruikt om een ​​nieuw gebruikersaccount voor deze Contao Manager aan te maken. De uitnodiging verloopt op {expires} (over een week).","ui.user-manager.inviteSuccess2":"Kopieer de link naar uw klembord. Deze link werkt slechts één keer en is na het sluiten van dit dialoogvenster niet meer zichtbaar.","ui.user-manager.createInvitation":"Maak een uitnodigingslink aan","ui.user-manager.clipboard":"Kopiëren naar het klembord","ui.user-manager.permissions":"Meer informatie over permissies","ui.user-manager.cancel":"Annuleer","ui.user-manager.close":"Sluit","ui.user-manager.you":"U","ui.user-manager.2fa":"2FA","ui.user-manager.2faEnabled":"Dit account is beveiligd met tweefactorauthenticatie.","ui.user-manager.2faDisabled":"Dit account is onveilig omdat tweefactorauthenticatie ontbreekt.","ui.user-manager.passkey":"Passkey","ui.user-manager.passkeyTitle":"Dit account is beveiligd met een Passkey.","ui.totp.headline":"Tweefactorauthenticatie","ui.totp.setupQr":"Scan de QR-code met uw 2FA/TOTP-app.","ui.totp.setupCode":"Als u de QR-code niet kunt scannen, voer dan deze sleutel in:","ui.totp.codeLabel":"Verificatiecode","ui.totp.codeDescription":"Voer de verificatiecode in die is gegenereerd door uw 2FA/TOTP-app.","ui.totp.disableText":"Voer de verificatiecode in om tweefactorauthenticatie uit te schakelen.","ui.totp.invalid":"De verificatiecode is ongeldig.","ui.totp.enable":"Inschakelen","ui.totp.disable":"Uitschakelen","ui.totp.cancel":"Annuleer","ui.totp.enabled":"Tweefactorauthenticatie is succesvol ingeschakeld.","ui.totp.disabled":"Tweefactorauthenticatie is succesvol uitgeschakeld.","ui.totp.setup":"Tweefactorauthenticatie instellen","ui.totp.skip":"Tweefactorauthenticatie overslaan"}')}}]);"use strict";(self["webpackChunkcontao_manager"]=self["webpackChunkcontao_manager"]||[]).push([[748],{8367:function(e){e.exports=JSON.parse('{"ui.app.httpsHeadline":"!! Веза није безбедна !!","ui.app.httpsDescription":"Ако не користите HTTPS ваши поверљиви подаци ће се преносити без енкрипције.","ui.app.httpsLink":"Детаљније","ui.app.httpsHref":"https://https.cio.gov/everything/","ui.app.safeModeHeadline":"!! Сигурни мод је омогућен !!","ui.app.safeModeDescription":"Неке функционалности Contao Manager-a нису доступне.","ui.app.safeModeExit":"Изађи из Сигурног мода","ui.app.limitedHeadline":"Даљинска аутентификација","ui.app.limitedDescription":"You have limited permissions due to passwordless login.","ui.app.limitedLogout":"Re-authenticate","ui.app.totpHeadline":"Security Notice","ui.app.totpDescription":"Configure two-factor authentication now to secure your account.","ui.app.totpSetup":"Покретање инсталације","ui.app.loading":"Contao Manager се учитава...","ui.app.apiError":"Неочекиван статус API","ui.app.configSecurity1":"УПОЗОРЕЊЕ !!! Пронађен је незаштићен config фолдер","ui.app.configSecurity2":"Contao Manager је открио да су конфигурациони фајлови јавно доступни. Све операције су обустављене док се config фолдер не заштити. У супротном би потенцијални нападач могао да приступи осетљивим подацима о Вашој инсталацији.\\n\\nДа поправите ово, осигурајте да приступ фолдеру \\"contao-manager\\" на Вашем серверу буде спречен. Ако је потребно да прво научите како то да урадите, прочитајте упутство за ваш сервер или контактирајте корисничку подршку Вашег хостинг провајдера.","ui.account.welcome":"Добро дошли","ui.account.intro1":"Добродошли у Contao Manager, универзални алат за инсталацију и управљање са Вашом инсталацијом Contao Open Source CMS. Ако се први пут срећете са њим, погледајте {readTheManualToGetStarted}.","ui.account.introGetStarted":"{readTheManual} да почнете","ui.account.introManual":"прочитајте приручник","ui.account.intro2":"Ако наиђете на неки проблем, проверите {ourGithubIssues}  и слободно креирајте нову тему за било шта што до сада није пријављено.","ui.account.introIssues":"наши GitHub проблеми","ui.account.headline":"Кориснички налог","ui.account.description":"Да управљате Вашом инсталацијом, потребно је да креирате налог за Contao Manager. Имајте на уму да овај налог није исто што и налог за Contao Фронт- и БекЕнд.","ui.account.username":"Корисничко име","ui.account.password":"Лозинка","ui.account.passwordPlaceholder":"мин. 8 знакова","ui.account.passwordLength":"Унесите барем 8 знакова.","ui.account.loginInvalid":"There was an error when creating the account. Please try a different username.","ui.account.submit":"Креирај налог","ui.account.usePassword":"Use password for login","ui.account.usePasskey":"Use Passkey for login","ui.account.totpHeadline":"Two-factor authentication","ui.account.totpDescription":"Please enable two-factor authentication, which adds an extra layer of security to your account. In addition to your username and password, you will need to enter a verification code generated by a two-factor app such as 1Password, Authy, Google Authenticator, Microsoft Authenticator, LastPass Authenticator or any other TOTP app.","ui.account.totpSetup":"Configure now","ui.account.totpSkip":"Configure later","ui.account.login":"Decline Invitation","ui.account.contribute1":"Contao и Contao Manager су под покровитељством непрофитне организације Contao Association.","ui.account.contribute2":"Молимо Вас да размислите о томе да помогнете отвореном пројекту својом {donate}.","ui.account.contributeDonate":"донирање","ui.login.headline":"Пријава","ui.login.description":"Пријави се ради управљања инсталацијом.","ui.login.username":"Корисничко име","ui.login.password":"Лозинка","ui.login.totpHeadline":"Two-factor authentication","ui.login.totpDescription":"Please enter your verification code to complete the login process.","ui.login.totp":"Verification code","ui.login.forgotPassword":"Заборавили сте лозинку?","ui.login.button":"Пријава","ui.login.passkey":"Sign In with Passkey","ui.login.cancel":"Откажи","ui.login.or":"или","ui.login.locked":"Приступ је одбијен јер је Contao Manager закључан. Да бисте га откључали, обришите {lockFile} у почетном директоријуму ваше Contao инсталације.","ui.logout.headline":"Сесија је истекла","ui.logout.warning":"Нисте били активни дуже од 25 минута. Из безбедносних разлога ваша сесија ће бити ускоро прекинута.","ui.logout.expired":"Ваша сесија је аутоматски прекинута јер сте били неактивни дуже од 30 минута.","ui.logout.renew":"Остани пријављен","ui.logout.logout":"Одјава","ui.logout.login":"Назад на пријаву","ui.oauth.error":"Неисправан OAuth покушај. Проверите параметре.","ui.oauth.https":"URI за редирекцију МОРА да користи сигурни протокол (https:) чиме се спречава да се аутентификациони токен преноси као обични текст.","ui.oauth.headline":"Даљинска аутентификација","ui.oauth.description":"Следеће апликације или сервиси захтевају удаљени приступ Вашој инстанци Contao Manager-а.","ui.oauth.domain":"Пре него што дозволите приступ, будите сигурни да познајете овај URL и имате поверење у власника!","ui.oauth.outOfScope":"Unfortunately, you do not have the necessary permissions to grant this access.","ui.oauth.allow":"Дозволи приступ","ui.oauth.deny":"Одбиј приступ","ui.oauth.switchUser":"Switch User","ui.scope.admin":"Admin access including user management","ui.scope.install":"Install new packages and change Contao configuration","ui.scope.update":"Update packages and execute maintenance tasks","ui.scope.read":"Read packages and configuration","ui.boot.headline":"Провера система","ui.boot.description":"Молимо сачекајте, анализирам ваш сервер ...","ui.boot.issue1":"Пронађен је проблем приликом инсталације","ui.boot.issue2":"Ваша инсталација има проблеме који морају бити решени како бисте могли да користите Contao Manager.","ui.boot.run":"Покрени Contao Manager","ui.boot.safeMode":"Покрени у Safe Mode","ui.recovery.headline":"Опоравак система","ui.recovery.description":"Contao Manager је открио фајлове који наликују на Contaо, али интерфејс командне линије - Command Line Interface - не ради како би требао.","ui.recovery.console":"Испис конзоле","ui.recovery.repairOptions":"Одаберите опцију за опоравак инсталације.","ui.recovery.repairHeadline":"Аутоматска поправка","ui.recovery.repairDescription":"Аутоматска поправка инсталације поновним креирањем апликативног cache-а и реинсталацијом пакета Композера.","ui.recovery.repairWarning":"Било која модификација vendor фајлова можда ће бити обрисана приликом процедуре!","ui.recovery.repairFailed":"Аутоматска поправка није успела. Пробајте ручно да поправите инсталацију у Safe Mode-у.","ui.recovery.repairButton":"Покрени системску поправку","ui.recovery.safeModeHeadline":"Safe Mode","ui.recovery.safeModeDescription":"Покретањем Contao Manager-а у Safe Mode-у омогућиће управљање пакетима и одређеним задацима одржавања, али могућности које се ослањају на постојећу инсталацију Contao неће бити доступне.","ui.recovery.safeModeButton":"Покрени у Safe Mode","ui.server.pending":"Причекајте...","ui.server.running":"Анализа је у току...","ui.server.error":"Провера није успела због неочекиваног одговора са сервера.","ui.server.details":"Детаљи","ui.server.prerequisite":"Провера је заустављена због тога што потребни предуслови нису задовољени.","ui.server.selfUpdate.title":"Ажурирања Contao Manager-а","ui.server.selfUpdate.update":"Нова верзија Contao Manager {latest} је доступна.","ui.server.selfUpdate.manualUpdate":"Нова верзија Contao Manager {latest} је доступна. Ваш сервер не подржава аутоматско ажурирање, панову верзију преузмите са {download}.","ui.server.selfUpdate.latest":"Користите последњу верзију {current}.","ui.server.selfUpdate.dev":"Развојне верзије не подржавају аутоматско ажурирање.","ui.server.selfUpdate.unsupported":"Нова верзија је доступна али не подржава вашу верзију PHP-а.","ui.server.selfUpdate.button":"Покрени Само-ажурирање","ui.server.selfUpdate.continue":"Настави","ui.server.config.title":"Конфигурација сервера","ui.server.config.setup":"Конфигуриши","ui.server.config.change":"Промени","ui.server.config.save":"Сачувај","ui.server.config.cancel":"Откажи","ui.server.config.customOption":"Остало...","ui.server.config.description":"Да би исправно извршавао позадинске задатке, Contao Manager треба да зна где се налази PHP command line binary и како да извршава команде одвојено од мрежних процеса.","ui.server.config.formTitle":"Конфигурација сервера","ui.server.config.formText":"Унесите путању до вашег PHP binary. Проверите да ли је binary у истој верзији PHP као ваш веб процес.","ui.server.config.cloudTitle":"Composer Resolver Cloud","ui.server.config.cloudText":"Composer Resolver Cloud омогућава инсталацију Composer зависности и у случају када ваш локални сервер не поседује довољно радне меморије. Имајте на уму да ће информације о вашим пакетима бити пренете на сервер којим управља Contao Association.","ui.server.config.cloud":"Користи Composer Resolver Cloud","ui.server.config.cli":"PHP binary","ui.server.config.stateErrorCli":"На серверу није пронађен валидан PHP binary.","ui.server.config.stateErrorCloud":"Употреба Composer Resolver Cloud није подржана.","ui.server.config.stateSuccess":"PHP binary на {php_cli}.","ui.server.config.cloudEnabled":"Package dependencies will be resolved using the Composer Resolver Cloud.","ui.server.config.cloudDisabled":"The Composer Resolver Cloud is disabled.","ui.server.php_web.title":"PHP Web Process","ui.server.php_web.below7":"Пронађена је верзија PHP {version}. Молимо Вас да што пре пређете на PHP 7!","ui.server.php_web.success":"Пронађена верзија PHP {version}, нема познатих проблема.","ui.server.php_cli.title":"PHP Command Line Interface","ui.server.php_cli.success":"Пронађена верзија PHP {version}, нема познатих проблема.","ui.server.composer.title":"Composer Environment","ui.server.composer.success":"Нема познатих проблема.","ui.server.composer.install":"Зависности Композера нису инсталиране.","ui.server.composer.button":"Инсталирај","ui.server.contao.title":"Инсталација Contao","ui.server.contao.setup":"Покретање инсталације","ui.server.contao.check":"Провери базу података","ui.server.contao.empty":"Није пронађена инсталација Contao.","ui.server.contao.old":"Верзија Contao {version} није усклађена са Contao Менаџером, па ћете морати ручно да ажурирате вашу инсталацију.","ui.server.contao.found":"Пронађен Contao {version} (API version {api}).","ui.server.contao.connectionError":"Неуспешно повезивање са сервером базе података.","ui.server.contao.connectionProblem":"Пронађен је проблем у бази података.","ui.server.contao.missingUser":"Није пронађен администраторски налог.","ui.setup.continue":"Настави","ui.setup.manager":"Покрени Contao Manager","ui.setup.cancel":"Откажи","ui.setup.welcome":"Добро дошли","ui.setup.welcome1":"Овај чаробњак ће вас водити кроз неопходне кораке за инсталацију  Contao Open Source CMS.","ui.setup.welcome2":"У случају да имате било каква питања, претражите документацију, форуме, канал на Slack-у и остале ресурсе на страници {support}.","ui.setup.support":"подршка из заједнице","ui.setup.start":"Почни","ui.setup.complete":"Честитамо!","ui.setup.complete1":"Contao {version} је успешно инсталиран.","ui.setup.complete2":"За завршетак процеса инсталације, отворите алат за инсталацију да бисте пдесили параметре конекције са базом података и креирали корисника за Бек Енд.","ui.setup.complete3":"Сада можете почети да развијате свој сајт у Бек Енду. Ако су вам потребне додатне екстензије, наставите у Contao Manager.","ui.setup.installTool":"Отвори Инсталациони алат","ui.setup.login":"Пријави се у Contao","ui.setup.funding":"Free software is \\"free\\" as in \\"free speech\\", not as in \\"free beer\\". Пројекат Отвореног кода попут Contao захтева новац који не може да обезбеди само један појединац или комапнија.\\nАко имате сајт или продајете сајтове засноване на Contao, волели бисмо да добијемо вашу подршку у виду донације те да на тај начин подржите пројекат од кога зависи и ваш пословни резултат.","ui.setup.fundingLink":"Више информација","ui.setup.document-root.headline":"Подешавања мрежног сервера","ui.setup.document-root.warning":"Да бисте инсталирали Contao уз помоћ Contao Manager-а, морате да исправно подесите локацију  root-а на Вашем мрежном серверу.","ui.setup.document-root.description1":"Contao користи посебан фолдер за јавно доступне фајлове, а апликативни фајлови су инсталирани у надређеном фолдеру. Contao сада није могуће инсталирати јер структура фолдера није тачна или фолдери нису празни.","ui.setup.document-root.description2":"Ако нисте сигурни како да подесите root, прочитајте документацију или контактирајте администратора Вашег хостинг провајдера.","ui.setup.document-root.documentation":"Прочитајте документацију","ui.setup.document-root.conflictsTitle":"Инсталациони фолдер није празан","ui.setup.document-root.conflictsDirectory":"Основни директоријум ваше будуће инсталације Contao није празан. Пронашли смо {count} фајла(ова) који ће можда бити обрисани приликом инсталације. Препоручујемо да направите празну структуру директоријума, али можете и да преместите следеће фајлове и проверите поново ако нисте сигурни да ли су у употреби.","ui.setup.document-root.ignoreConflicts":"Желим да инсталирам Contao у директоријум који није празан. Разумем да ће ово можда обрисати постојеће фајлове.","ui.setup.document-root.check":"Провери поново","ui.setup.document-root.create":"Направи директоријуме","ui.setup.document-root.change":"Промени директоријуме","ui.setup.document-root.formTitle":"Подешавање директоријума","ui.setup.document-root.formText1":"Contao Manager може аутоматски да креира нову структуру директоријума на серверу.","ui.setup.document-root.formText2":"Мораћете рућно да подесите нови root за документе (нпр. преко администраторског контрол панела на хостингу).","ui.setup.document-root.autoconfig":"Разумем да морам да променим моју конфигурацију сервера. Ако то не урадим, конфигурациони фајлови ће бити изложени (укључујући детаље налога и лозинке)!","ui.setup.document-root.directory":"Нови директоријум","ui.setup.document-root.currentRoot":"Тренутни Document Root","ui.setup.document-root.newRoot":"Нови Document Root","ui.setup.document-root.finish":"Постављање директоријума","ui.setup.document-root.publicDir":"Користи {dir} за јавне фајлове (за Contao {version})","ui.setup.document-root.directoryInvalid":"Унесите исправан назив за директоријум.","ui.setup.document-root.directoryExists":"Одредишни директоријум већ постоји. Унесите други назив.","ui.setup.document-root.confirmation":"Contao Manager је успешно завршио креирање потребног директоријума за Вашу Contao инсталацију. Сада треба да подесите document root на Вашем мрежном серверу. Немојте да поново учитавате ову страницу пре тога.","ui.setup.document-root.reload":"Поново учитај страницу","ui.setup.document-root.success":"Структура директоријума на вашем серверу је исправно постављена.","ui.setup.document-root.installingProjectDir":"Апликативни фајлови ће бити инсталирани у {dir}.","ui.setup.document-root.installingPublicDir":"Јавни фајлови ће бити инсталирани у {dir}.","ui.setup.document-root.installedProjectDir":"Апликативни фајлови су инсталирани у {dir}.","ui.setup.document-root.installedPublicDir":"Јавни фајлови су инсталирани у {dir}.","ui.setup.create-project.headline":"Инсталација Contao","ui.setup.create-project.description":"Развој Contao следи принципе {semver}, што значи да се нова мања верзија објављује сваких шест месеци. Тренутно подржана издања су:","ui.setup.create-project.semver":"Семантичко верзионисање","ui.setup.create-project.latestTitle":"Последња верзија","ui.setup.create-project.ltsTitle":"Long Term Support","ui.setup.create-project.latestQ1":"Наша последња верзија нуди највише функционалности са подршком до фебруара {year}.","ui.setup.create-project.latestQ3":"Напа последња верзија нуди највише функционалности са подршком до августа {year}.","ui.setup.create-project.ltsText":"Наша тренутна LTS верзија, ако сте фокусирани на стабилност. Нуди дугорочну подршку до фебруара {year}.","ui.setup.create-project.pltsText":"Претходна LTS верзија, још увек нуди дугорочну подршку до фебруара {year}.","ui.setup.create-project.requiresPHP":"Захтева минималну верзију PHP {version}, а ви имате PHP {current}.","ui.setup.create-project.releaseplan":"За више информација, проверите {contaoReleasePlan}.","ui.setup.create-project.releaseplanLink":"План издања за Contao","ui.setup.create-project.installed":"Contao {version} је успешно инсталиран на сервер. Наставите са постављањем ваше базе података или покрените Contao Manager да инсталирате другу верзију.","ui.setup.create-project.formTitle":"Изабери дистрибуцију","ui.setup.create-project.formText":"Изаберите верзију која треба да се инсталира.","ui.setup.create-project.version":"Верзија","ui.setup.create-project.demo":"Инсталирај Contao демо сајт.","ui.setup.create-project.demoDescription":"Демо сајт помаже да се упознате са Contao и са основним функционалностима. Више тема можете пронаћи у {store}.","ui.setup.create-project.coreOnly":"Минимална инсталација (само основни модули)","ui.setup.create-project.noUpdate":"Прескочи инсталацију (само за експерте!)","ui.setup.create-project.theme":"Теме за Contao","ui.setup.create-project.themeInstall":"Да инсталирате тему за Contao, користите претрагу или учитајте фајл теме (.cto/.zip) који подржава инсталацију помоћу Contao Manager.","ui.setup.create-project.themeBuy":"Не заборавите да посетите званични {store}.","ui.setup.create-project.themeStore":"Продавница тема за Contao ","ui.setup.create-project.themeUpload":"Учитај фајл теме (.cto/.zip)","ui.setup.create-project.themeInvalid":"Учитани фајл није тема за Contao или не подржава Contao Manager.","ui.setup.create-project.themeWarning":"Contao Manager не може да процени да ли је ова тема компатибилна са вашим сервером. Проверите то са испоручиоцем од кога сте набавили тему ако имате било каква питања.","ui.setup.create-project.themeTitle":"Прегледај детаље теме","ui.setup.create-project.themeDetails":"Следеће зависности и фајлови ће бити инсталирани са овом темом.","ui.setup.create-project.themeRequire":"{count} Зависности | {count} Зависности","ui.setup.create-project.themeFiles":"{count} Фајл | {count} Фајлови","ui.setup.create-project.theme.or":"или претраже јавне теме","ui.setup.create-project.theme.search":"Претражи теме","ui.setup.create-project.theme.more":"Више тема","ui.setup.create-project.theme.empty":"Нема тема које се поклапају са {query}","ui.setup.create-project.theme.uploaded":"Фајл теме је успешно учитан.","ui.setup.create-project.theme.packageName":"Име пакета","ui.setup.create-project.theme.version":"Верзија","ui.setup.create-project.theme.authors":"Аутор(и)","ui.setup.create-project.theme.upload":"Uploading {name} ({size})","ui.setup.create-project.install":"Инсталирај","ui.setup.create-project.cancel":"Откажи","ui.setup.create-project.fileError":"Could not find composer.json in {file}.","ui.setup.create-project.jsonError":"composer.json contains invalid JSON.","ui.setup.create-project.schemaError":"composer.json schema validation failed.","ui.setup.database-connection.headline":"Конекција са базом података","ui.setup.database-connection.description":"Да би могао да чува странице, садржај, кориснике и остале релационе податке, Contao захтева MySQL базу података (или компатибилну варијанту као што је MariaDB). Параметри за повезивање су сачувани у фајлу {env} који се чува у основном фолдеру ваше Contao инсталације.","ui.setup.database-connection.formTitle":"Параметри за повезивање","ui.setup.database-connection.formText":"Унесите URL базе података или испуните корисничко име, лозинку, сервер и име базе података.","ui.setup.database-connection.url":"URL базе података","ui.setup.database-connection.validUrl":"URL базе података није исправан или повезивање са сервером није успело.","ui.setup.database-connection.or":"или","ui.setup.database-connection.user":"Корисничко име","ui.setup.database-connection.password":"Лозинка","ui.setup.database-connection.server":"Сервер (:Порт)","ui.setup.database-connection.database":"Назив базе података","ui.setup.database-connection.connected":"Повезивање са базом података {database} на серверу {server} је успело.","ui.setup.database-connection.error":"Грешка приликом повезивања са базом података.","ui.setup.database-connection.problem":"Contao је поронашао проблем са вашим сервером базе података.","ui.setup.database-connection.schemaTitle":"Шема базе података","ui.setup.database-connection.migration":"На чекању је једна миграција. | На чекању је {count} миграција.","ui.setup.database-connection.schema":"Једно ажурирање шеме је на чекању. | На чекању је {count} ажурирања шеме.","ui.setup.database-connection.noChanges":"Ваша шема у оквиру базе података је ажурна.","ui.setup.database-connection.check":"Провери базу података","ui.setup.database-connection.skip":"ПрескочиПрескочи","ui.setup.database-connection.save":"Сачувај","ui.setup.database-connection.change":"Промени креденцијале","ui.setup.database-connection.restoreTitle":"Увоз базе података","ui.setup.database-connection.restoreText":"Тема коју сте управо инсталирали садржи копију базе података. Увезите базу података да бисте увезли податке теме или прескочите овај корак да почнете са празном инсталацијом Contao. | Тема коју сте управо инсталирали садржи неколико копија базе података. Изаберите копију да увезете податке теме или прескочите овај корак да почнете са празном инсталацијом Contao.","ui.setup.database-connection.backup":"Спреми копију тренутне базе података прије увоза","ui.setup.database-connection.backupWarning":"Сви подаци у бази података ће бити обрисани и уместо њих ће се уписати нови подаци! Ако база није празна, прво направите резервну копију. ","ui.setup.database-connection.restore":"Увоз базе података","ui.setup.database-connection.restoreOption":"Резервна копија од {date} ({size})","ui.setup.database-connection.restored":"Ваша база података која припада теми је успешно увезена. Наставите према валидацији шеме базе података.","ui.setup.backend-user.success":"У бази је пронађен администраторски налог за Contao Бек Енд. Употребите Contao Бек Енд да додате нове кориснике.","ui.setup.backend-user.error":"Повлачење листе корисника није успело. Проверите испис конзоле за више детаља.","ui.setup.backend-user.headline":"Налог за Бек Енд","ui.setup.backend-user.description":"Да бисте управљали својим сајтом, морате да имате барем један администраторски налог за Contao Бек Енд. Имајте на уму да овај налог није повезан са Contao Manager.","ui.setup.backend-user.formTitle":"Креирај налог","ui.setup.backend-user.formText":"Унесите податке за нови налог Бек Енда.","ui.setup.backend-user.username":"Корисничко име","ui.setup.backend-user.name":"Име","ui.setup.backend-user.email":"E-mail адреса","ui.setup.backend-user.emailInvalid":"Унесите исправну адресу e-mailа.","ui.setup.backend-user.password":"Лозинка","ui.setup.backend-user.passwordPlaceholder":"мин. 8 знакова","ui.setup.backend-user.passwordLength":"Унесите барем 8 знакова.","ui.setup.backend-user.create":"Додај налог","ui.task.headline":"Позадински задаци","ui.task.loading":"Учитавам детаље...","ui.task.created":"Учитавам детаље...","ui.task.active":"Сачекајте док Contao Manager заврши са позадинским задацима и операцијама.","ui.task.complete":"Сви задаци су успешно завршени. За више детаља, проверите излаз конзоле.","ui.task.paused":"Позадински задатак је неочекивано заустављен. Проверите излаз конзоле.","ui.task.aborting":"Сачекајте док се позадински задаци не откажу.","ui.task.stopped":"Неки позадински задаци су отказани. Проверите излаз конзоле.","ui.task.error":"Позадински задатак је неочекивано заустављен. Проверите излаз конзоле.","ui.task.failed":"Contao Manager није успео да покрене позадински задатак!","ui.task.failedDescription1":"Нешто је кренуло погрешно приликом извршавања операција у позадини.","ui.task.failedDescription2":"Ако се ово деси поново, Ваш сервер можда не подржава инсталацију.","ui.task.reportProblem":"Пријави проблем","ui.task.pausedDescription":"Click \\"Continue\\" if you want to ignore the error and execute the remaining operations.","ui.task.sponsor":"Composer Cloud је подржан од {sponsor}","ui.task.buttonAudit":"Ажурирај базу података","ui.task.buttonClose":"Затвори","ui.task.buttonConfirm":"Потврди и затвори","ui.task.buttonContinue":"Настави","ui.task.buttonCancel":"Откажи","ui.task.confirmCancel":"Да ли сте сигурни да желите да откажете задатак? Ово ће можда довести до тога да Contao инсталација не буде комплетна.","ui.task.autoclose":"Затвори детаље задатка након успешног завршетка.","ui.console.toggle":"Прикажи/Сакриј конзолу","ui.console.showLog":"Прикажи сав лог конзоле","ui.console.copyLog":"Копирај лог у привремену меморију.","ui.migrate.headline":"Ажурирања базе података","ui.migrate.migrationsOnly":"(само миграције)","ui.migrate.schemaOnly":"(само шема)","ui.migrate.loading":"Молимо да сачекате док проверимо вашу базу података ...","ui.migrate.empty":"Нису пронађене миграције или ажурирања шеме базе података на чекању. Ваша база података је ажурна.","ui.migrate.emptyMigrations":"Нису пронађене миграције на чекању. Не заборавите да проверите и ажурирања шеме.","ui.migrate.emptySchema":"Нису пронађена ажурирања шеме на чекању. Не заборавите да проверите и миграције.","ui.migrate.pending":"Ваша база података није ажурна. Проучите испис конзоле и извршите захтеване промене.","ui.migrate.previousChanges":"Миграција претходне базе података није потврђена..\\nПроверите испис конзоле испод, а онда наставите са променама.","ui.migrate.previousComplete":"Претходна миграција базе података није потврђена, проверите испис конзоле испод.\\nНема других промена на чекању.","ui.migrate.appliedChanges":"Извршена су ажурирања базе података.\\nПроверите испис конзоле испод, а онда наставите са променама.","ui.migrate.appliedComplete":"Извршена су ажуриања базе података.\\nСада је ваша база ажурна. Нема других миграција и ажурирања шеме на чекању.","ui.migrate.problem":"Contao је пронашао проблем са вашим сервером базе података.\\nПроверите испис конзоле како бисте сазнали шта треба да се поправи. | Contao је пронашао проблем са вашим сервером базе података. \\nПроверите испис конзоле како бисте сазнали шта треба да се поправи.","ui.migrate.warning":"Contao је пронашао грешку у подешавању сервера базе података.\\nУпозорења за сада можете да занемарите, али би било добро да их поправите како бисте добили оптималне перформансе и интегритет података.","ui.migrate.error":"Промене не могу да се сачувају. Изгледа да је дошло до промена у вашој бази података, освежите податке и покушајте поново.","ui.migrate.execute":"Изврши","ui.migrate.close":"Затвори","ui.migrate.confirm":"Потврди и затвори","ui.migrate.cancel":"Откажи","ui.migrate.continue":"Настави","ui.migrate.setup":"Покретање инсталације","ui.migrate.skip":"ПрескочиПрескочи","ui.migrate.retry":"Провери поново","ui.migrate.retryAll":"Провери све","ui.migrate.withDeletes":"Изврши све промене у бази података, укључујучи DROP упите.","ui.migrate.migrationTitle":"Миграције базе података","ui.migrate.schemaTitle":"Ажурирања шема","ui.migrate.problemTitle":"Проблеми базе података","ui.migrate.warningTitle":"Упозорења базе података","ui.migrate.addTable":"Додај табелу {table}","ui.migrate.dropTable":"Обриши табелу {table}","ui.migrate.addField":"Додај колону {table}.{field}","ui.migrate.changeField":"Промени колону {table}.{field}","ui.migrate.dropField":"Обриши колону {table}.{field}","ui.migrate.createIndex":"Креирај индекс \\"{name}\\" над табелом {table}","ui.migrate.dropIndex":"Обриши индекс \\"{name}\\" над табелом {table}","ui.widget.mandatory":"Ово поље не сме бити празно.","ui.widget.blankOption":"Одаберите...","ui.widget.showPassword":"Прикажи лозинку","ui.widget.hidePassword":"Сакриј лозинку","ui.error.title":"HTTP захтев за \\"{method} {url}\\" није успео.","ui.error.server500":" Изгледа да се десила нека неочекивана грешка на серверу. Проверите логове на Вашем серверу  (Apache/Nginx) и логове Contao Manager на локацији \\"contao-manager/logs\\".","ui.error.response":"Сервер је договорио са кодом  {status}.","ui.error.moreLink":"Више информација","ui.error.support":"Подршка за  Contao","ui.error.permission":"You do not have permission to use this feature.","ui.footer.help":"Помоћ","ui.footer.reportProblem":"Пријави проблем","ui.navigation.discover":"Истражи","ui.navigation.packages":"Пакети","ui.navigation.tools":"Алати","ui.navigation.installTool":"Алат за инсталацију","ui.navigation.backend":"Contao БекЕнд","ui.navigation.debug":"Contao мод за дебаговање","ui.navigation.logViewer":"Преглед логова","ui.navigation.phpinfo":"Информације о PHP","ui.navigation.phpinfoLoading":"Учитавање информација о PHP...","ui.navigation.maintenance":"Одржавање","ui.navigation.rebuildCache":"Поновно креирај кеш","ui.navigation.users":"Accounts","ui.navigation.systemCheck":"Провера система","ui.navigation.advanced":"Напредно","ui.navigation.logout":"Одјава","ui.maintenance.database.title":"Миграције и резервне копије базе података","ui.maintenance.database.description":"Миграције базе података осигуравају конзистентност података и табела у оквиру шема.","ui.maintenance.database.migrations":"Једна миграција базе података на чекању | {count} миграција базе података на чекању","ui.maintenance.database.schemaUpdates":"Једно ажурирање шеме на чекању | {count} ажурирања шеме на чекању","ui.maintenance.database.error":"Пронађен је проблем у бази података.","ui.maintenance.database.warning":"Пронађена су упозорења за базу података.","ui.maintenance.database.button":"Провери базу података","ui.maintenance.database.migrationOnly":"Провери само миграције","ui.maintenance.database.schemaOnly":"Провери само шеме","ui.maintenance.database.installTool":"Отвори Инсталациони алат","ui.maintenance.database.createBackup":"Креирај резервну копију","ui.maintenance.database.backupUnsupported":"Резервне копије базе података нису подржане у оквиру ваше верзије Contao.","ui.maintenance.database.backupList":"Имате једну резервну копију базе података, креирану {date}. | Имате {count} резервних копија базе података, а последња је креирана {date}.","ui.maintenance.database.backupEmpty":"Тренутно немате резервне копије базе података.","ui.maintenance.rebuildCache.title":"Апликативни cache","ui.maintenance.rebuildCache.description":"Поновно креирање апликативног cache-a је потребно сваки пут када мењате било који конфигурациони фајл.","ui.maintenance.rebuildCache.rebuildProd":"Обнови продукциони Cache","ui.maintenance.rebuildCache.rebuildDev":"Обнови развојни Cache","ui.maintenance.rebuildCache.clearProd":"Обриши продукциони Cache","ui.maintenance.rebuildCache.clearDev":"Обриши развојни Cache","ui.maintenance.installTool.title":"Инсталациони алат за Contao","ui.maintenance.installTool.description":"Инсталациони алат за Contao је аутоматски закључан ако три пута заредом погрешите лозинку.","ui.maintenance.installTool.unlock":"Откључај Инсталациони алат","ui.maintenance.installTool.lock":"Закључај Инсталациони алат","ui.maintenance.dumpAutoload.title":"Composer Class Loader","ui.maintenance.dumpAutoload.description":"The Composer autoloader је одговоран за учитавање PHP класа.  Аutoloader мора бити испражњен након додавања властитих namespaces у root composer.json.","ui.maintenance.dumpAutoload.button":"Испразни Autoloader","ui.maintenance.composerInstall.title":"Композер зависности - dependencies","ui.maintenance.composerInstall.description":"Композер зависности су смештене у фолдер {vendor} у root фолдеру ваше апликације. Реинсталирање зависности ће можда бити неопходно након измене или ручног копирања на сервер фајла {composerLock}.","ui.maintenance.composerInstall.button":"Покрени Инсталер","ui.maintenance.composerInstall.update":"Покрени ажурирање Композера","ui.maintenance.composerCache.title":"Композер Cache","ui.maintenance.composerCache.description":"Композер кешира преузете пакете како би побољшао перформансе. Ако имате проблеме са непотпуним фајловима, покушајте да обришете cache Композера како бисте га присилили на поновно преузимање читавог пакета.","ui.maintenance.composerCache.button":"Обриши Cache","ui.maintenance.maintenanceMode.title":"Мод одржавања","ui.maintenance.maintenanceMode.description":"Када Contao пребаците у Мод одржавања, сајт ће да приказује шаблон за \\"503 Service Unavailable\\".","ui.maintenance.maintenanceMode.enable":"Омогући","ui.maintenance.maintenanceMode.disable":"Онемогући","ui.maintenance.debugMode.title":"Мод за дебаговање","ui.maintenance.debugMode.description":"Активирајте мод за дебаговање тако што ћете поставити корисничко име и лозинку за улазну тачку {appDevPhp}.","ui.maintenance.debugMode.descriptionJwt":"Активирајте debug мод тако што ћете поставити debug колачић за тренутни домен.","ui.maintenance.debugMode.activate":"Активирај","ui.maintenance.debugMode.deactivate":"Деактивирај","ui.maintenance.debugMode.credentials":"Креденцијали","ui.maintenance.debugMode.user":"Унесите корисничко име за Мод за дебаговање.","ui.maintenance.debugMode.password":"Унесите лозинку за Мод за дебаговање.","ui.maintenance.opcodeCache.title":"Opcode Cache","ui.maintenance.opcodeCache.description":"Opcode кешира PHP фајлове ради бржег извршавања. У неким околностима мора бити обрисан ако фајлови нису препознати након измене.","ui.maintenance.opcodeCache.button":"Испразни Cache","ui.maintenance.safeMode":"Није доступно у Safe Mode","ui.maintenance.unsupported":"Није подржан у вашој верзији Contao","ui.packages.updateButton":"Ажурирај Пакете","ui.packages.searchButton":"Претрага пакета","ui.packages.searchPlaceholder":"Претрага Пакета...","ui.packages.uploadOverlay":"Превуците & пустите фајлове да бисте их пренели на сервер","ui.packages.uploadButton":"Постави пакете","ui.packages.uploadMessage":"Имате непотврђено пребацивање на сервер. | Имате {count} непотврђених пребацивања на сервер.","ui.packages.uploadApply":"Потврди преносе","ui.packages.uploadReset":"Обриши преносе","ui.packages.uploadIncomplete":"Фајл није пренесен у потпуности. Уклоните га и пробајте поново.","ui.packages.uploadDuplicate":"Изгледа да је овај фајл пренесен неколико пута. Уклоните дупликате.","ui.packages.uploadInstalled":"Овај фајл је већ инсталиран. Уклоните дупликате.","ui.packages.uploadUnsupported":"Учитавања нису подржана у вашој инсталацији. Проверите да је инсталирана екстензија PHP ZIP и ажурирајте зависности.","ui.packages.changesMessage":"Имате једну непотврђену промену. | Имате {count} непотврђених промена.","ui.packages.changesDryrun":"Dry Run","ui.packages.changesApply":"Примени промене","ui.packages.changesApplyAll":"Ажурирај све пакете","ui.packages.changesDryrunAll":"Обави \\"dry-run\\" симулацију свих пакета.","ui.packages.changesReset":"Врати на почетно стање","ui.packages.changesReview":"Прегледај промене","ui.packagelist.loading":"Учитавам ...","ui.packagelist.uploads":"Преноси","ui.packagelist.added":"Нови пакети","ui.packagelist.installed":"Инсталирани пакети","ui.package.hintRevert":"Опозови измене","ui.package.hintNoupdate":"Не ажурирај","ui.package.hintConstraint":"Када сачувате измене, овај пакет ће бити инсталиран са ограничењима {constraint}.","ui.package.hintConstraintBest":"Када сачувате измене, овај пакет ће бити инсталиран са најбољом доступном верзијом.","ui.package.hintConstraintChange":"Када сачувате измене, ограничење овог пакета биће промењено из \\"{from}\\" у \\"{to}\\" .","ui.package.hintConstraintUpdate":"Ови пакети ће бити ажурирани када потврдите измене.","ui.package.hintAdded":"Ови пакети ће бити инсталирани када потврдите измене.","ui.package.hintRemoved":"Када сачувате измене, овај пакет ће бити уклоњен.","ui.package.requiredTitle":"ручно додати","ui.package.requiredText":"Овај пакет је захтеван у Вашем composer.json али није инсталиран.","ui.package.removedTitle":"ручно уклоњено","ui.package.removedText":"Овај пакет је уклоњен из вашег composer.json.","ui.package.installed":"Тренутно инсталирано:","ui.package.version":"Верзија {version}","ui.package.additionalDownloads":"{count} Преузимање | {count} Преузимања","ui.package.additionalStars":"{count} Звезда | {count} Звезде","ui.package.editConstraint":"Уреди","ui.package.uploadConstraint":"Ова зависности је дефинисана од пренесеног пакета.","ui.package.updateButton":"Ажурирај","ui.package.removeButton":"Уклони","ui.package.installButton":"Додај пакет","ui.package.installButtonShort":"Додавање","ui.package.detailsButton":"Детаљи","ui.package.latestConstraint":"последња верзија","ui.package.update":"Доступно је ажурирање","ui.package.updateLatest":"последња верзија","ui.package.updateAvailable":"{version} доступна","ui.package.updateUnknown":"непозната верзија","ui.package.updateConstraint":"Новија верзија изван вашег опсега верзија је доступна.","ui.package.incompatible":"{package} does not work with Contao {constraint}.","ui.package.incompatibleWarning":"{package} does not work with Contao {constraint} in any of its stable releases. Do you want to add the package and set a version constraint to try installing a development branch?","ui.package.incompatibleConstraint":"This package does not have a stable release for Contao {constraint}. Set a version constraint to try installing a development branch.","ui.package.incompatibleButton":"Инсталирај","ui.cloudStatus.headline":"Composer Resolver Cloud","ui.cloudStatus.version":"Верзија {version}","ui.cloudStatus.waitingTime":"Време чекања","ui.cloudStatus.jobs":"Тренутни задаци","ui.cloudStatus.workers":"Радници","ui.cloudStatus.approx":"{minutes} min","ui.cloudStatus.none":"нема","ui.cloudStatus.short":"ca. {minutes} min","ui.cloudStatus.long":"ca. {minutes} min {seconds} sec","ui.cloudStatus.error":"Није могуће проверити стање сервиса Composer Resolver Cloud. Можда је у току одржавање или постоје проблеми.","ui.cloudStatus.button":"Статус Cloud-а","ui.cloudStatus.refresh":"Освежи статус Cloud-а","ui.log-viewer.loading":"Учитавам ...","ui.log-viewer.empty":"Нема лог фајлова на вашем серверу. ","ui.log-viewer.reload":"Поново учитај","ui.log-viewer.file":"Лог фајл","ui.log-viewer.channel":"Канал","ui.log-viewer.channelTitle":"Канал у ком је ова порука забиљежена.","ui.log-viewer.level":"Ниво","ui.log-viewer.levelTitle":"Озбиљност лог поруке.","ui.log-viewer.timeHeader":"Време","ui.log-viewer.messageHeader":"Порука","ui.log-viewer.showContext":"Прикажи контекст","ui.log-viewer.hideContext":"Сакриј контектст","ui.log-viewer.showExtra":"Прикажи додатне информације","ui.log-viewer.hideExtra":"Сакриј додатне информације","ui.log-viewer.more":"Учитај више ...","ui.log-viewer.download":"Преузми локално","ui.log-viewer.downloadTitle":"Преузми фајл \\"{file}\\"","ui.log-viewer.prodEnvironment":"Продукционо окружење","ui.log-viewer.devEnvironment":"Развојно окружење (Debug Mode)","ui.user-manager.loading":"Loading users …","ui.user-manager.changePassword":"Change Password","ui.user-manager.setupTotp":"Setup Two-Factor Authentication","ui.user-manager.disableTotp":"Disable Two-Factor Authentication","ui.user-manager.invite":"Invite User","ui.user-manager.delete":"Delete","ui.user-manager.deleteConfirm":"Do you really want to delete user \\"{username}\\"?","ui.user-manager.deleted":"User {username} deleted successfully","ui.user-manager.passwordHeadline":"Change Password","ui.user-manager.passwordText":"To change your password, please enter the current and a new password in the respective fields.","ui.user-manager.currentPassword":"Current password","ui.user-manager.newPassword":"New password","ui.user-manager.passwordPlaceholder":"мин. 8 знакова","ui.user-manager.submitPassword":"Submit","ui.user-manager.passwordChanged":"Your password has been changed successfully.","ui.user-manager.passwordError":"This password is incorrect.","ui.user-manager.inviteHeadline":"Invite User","ui.user-manager.inviteText":"If you need multiple logins for the Contao Manager, you can create an invitation link here. Share this link with someone or use it on another device to create a new account with the given permissions.","ui.user-manager.inviteSuccess1":"A new invitation link was created. The URL below can be used to create a new user account for this Contao Manager. The invitation expires on {expires} (one week from now).","ui.user-manager.inviteSuccess2":"Please copy the link to your clipboard. It will only work once and you will not be able to see it again after closing this dialog.","ui.user-manager.createInvitation":"Create Invitation Link","ui.user-manager.clipboard":"Copy to clipboard","ui.user-manager.permissions":"Learn about permissions","ui.user-manager.cancel":"Откажи","ui.user-manager.close":"Затвори","ui.user-manager.you":"You","ui.user-manager.2fa":"2FA","ui.user-manager.2faEnabled":"This account is secured by two-factor authentication.","ui.user-manager.2faDisabled":"This account is insecure due to missing two-factor authentication.","ui.user-manager.passkey":"Passkey","ui.user-manager.passkeyTitle":"This account is secured by a Passkey.","ui.totp.headline":"Two-Factor Authentication","ui.totp.setupQr":"Please scan the QR code with your 2FA/TOTP app.","ui.totp.setupCode":"If you cannot scan the QR code, enter this key instead:","ui.totp.codeLabel":"Verification code","ui.totp.codeDescription":"Please enter the verification code generated by your 2FA/TOTP app.","ui.totp.disableText":"Please enter the verification code to disable two-factor authentication.","ui.totp.invalid":"The verification code is invalid.","ui.totp.enable":"Омогући","ui.totp.disable":"Онемогући","ui.totp.cancel":"Откажи","ui.totp.enabled":"Two-factor authentication was enabled successfully.","ui.totp.disabled":"Two-factor authentication was disabled successfully.","ui.totp.setup":"Setup Two-Factor Authentication","ui.totp.skip":"Skip Two-Factor Authentication"}')}}]);"use strict";(self["webpackChunkcontao_manager"]=self["webpackChunkcontao_manager"]||[]).push([[874],{2874:function(e){e.exports=JSON.parse('{"ui.app.title":"Rozšíření Contaa","ui.app.loading":"Načítání seznamu rozšíření...","ui.app.language":"Změnit jazyk Správce Contaa","ui.app.colorDark":"Tmavé zobrazení","ui.app.colorDarkTitle":"Změnit na tmavé prostředí","ui.app.colorLight":"Světlé zobrazení","ui.app.colorLightTitle":"Změnit na světlé prostředí","ui.discover.advertisement":"Reklama v seznamu rozšíření","ui.discover.loading":"Spouštění…","ui.discover.offline":"Nemůžu načíst žádné výsledky.","ui.discover.offlineExplain":"Zkontrolujte prosím Vaše internetové připojení a deaktivujte blokování JavaScriptu ve Vašem prohlížeči.","ui.discover.offlineButton":"Zkusit znovu","ui.discover.searchPlaceholder":"Prohledat {count} rozšíření...","ui.discover.empty":"Žádné výsledky pro {query}","ui.discover.more":"Více výsledků","ui.discover.sortBy":"Seřadit podle","ui.discover.sortReleased":"Zveřejněno","ui.discover.sortReleasedTitle":"Seřadit výsledky podle zveřejnění","ui.discover.sortLatest":"Zaktualizované","ui.discover.sortLatestTitle":"Seřadit výsledky podle naposledy zaktualizovaných","ui.discover.sortDownloads":"Stažení","ui.discover.sortDownloadsTitle":"Seřadit výsledky podle počtu stažení","ui.discover.sortFavers":"Hodnocení","ui.discover.sortFaversTitle":"Seřadit výsledky podle hodnocení","ui.discover.detailsButton":"Podrobnosti","ui.discover.latestPackages":"Poslední a naposledy zaktualizovaná rozšíření","ui.discover.faversPackages":"Nejlépe hodnocená rozšíření","ui.discover.downloadsPackages":"Nejvíce stahovaná rozšíření","ui.discover.exactHit":"Přesný souhlas query","ui.discover.results":"Více výsledků vyhledávání","ui.package.homepage":"Stránka projektu","ui.package.private":"Soukromý balíček","ui.package.privateTitle":"Soukromé balíčky jsou dostupné pouze z vendoru (např. jako soubor ZIP). Více informací získáte na následujícím webu. ","ui.package.abandoned":"nepřijatý","ui.package.abandonedText":"Tento balíček je označený jako nepřijatý a již se dál vyvíjí.","ui.package.abandonedReplace":"Tento balíček je označený jako nepřijatý a již se dál vyvíjí. Autor místo něho doporučuje použít {replacement}. ","ui.package.contaoVersion":"Dostupné pro Contao","ui.package-details.previous":"Předešlé podrobné informace k rozšíření","ui.package-details.close":"Zavřít podrobné informace k rozšíření","ui.package-details.loading":"Spouštění…","ui.package-details.tabDescription":"Popis","ui.package-details.tabRequire":"Požadavky","ui.package-details.tabFeatures":"Funkce","ui.package-details.tabSuggest":"Doporučení","ui.package-details.tabConflict":"Konflikty","ui.package-details.tabDependents":"Závislosti","ui.package-details.linkRequires":"vyžaduje","ui.package-details.linkReplaces":"nahrazuje","ui.package-details.linkProvides":"poskytuje","ui.package-details.linkConflicts":"konflikty","ui.package-details.funding":"Nalezen vyvíjený balíček!","ui.package-details.contaoVersions":"Podporováno verzí Contaa","ui.package-details.latest":"Poslední verze","ui.package-details.released":"Zveřejněno","ui.package-details.license":"Licence","ui.package-details.authors":"od","ui.package-details.more":"Více","ui.package-details.packagist":"Podrobnosti k balíčku","ui.package-details.metadata":"Upravit meta informace","ui.package-details.support_docs":"Dokumentace","ui.package-details.support_wiki":"Wiki","ui.package-details.support_forum":"Podpora ve fóru","ui.package-details.support_issues":"Chyby / nahlášení chyb","ui.package-details.support_source":"Zdrojový kód","ui.package-details.support_irc":"IRC / Chat","ui.package-details.support_email":"Mail podpory","ui.package-details.support_rss":"Kanál RSS"}')}}]);"use strict";(self["webpackChunkcontao_manager"]=self["webpackChunkcontao_manager"]||[]).push([[540],{4540:function(e){e.exports=JSON.parse('{"ui.app.httpsHeadline":"!!  Nezabezpečené připojení !!","ui.app.httpsDescription":"Bez HTTPS budou citlivá data přenášena nezabezpečeně.","ui.app.httpsLink":"Více informací","ui.app.httpsHref":"https://https.cio.gov/everything/","ui.app.safeModeHeadline":"!! Je zapnutý bezpečnostní režim !!","ui.app.safeModeDescription":"Některé funkce nejsou k dispozici ve Správci Contaa.","ui.app.safeModeExit":"Ukončit bezpečnostní režim","ui.app.limitedHeadline":"Smazat autorizaci","ui.app.limitedDescription":"Máte omezená přístupová práva kvůli přihlášení bez hesla.","ui.app.limitedLogout":"Opětovné ověření","ui.app.totpHeadline":"Bezpečnostní poznámka","ui.app.totpDescription":"Nastavte si dvoufaktorové ověření pro vyšší zabezpečení vašeho účtu. ","ui.app.totpSetup":"Nastavení","ui.app.loading":"Nahrávání Správce Contaa","ui.app.apiError":"Nečekaný status API","ui.app.configSecurity1":"BEZPEČNOSTNÍ UPOZORNĚNÍ!!! Byla objevená nechráněná konfigurační složka ","ui.app.configSecurity2":"Správce Contaa zjistil, že jsou veřejně dostupné jeho konfigurační soubory. Všechny operace byly pozastavené, dokud nebude daná složka chráněná, jinak může dojít k útoku na choulostivá data Vaší instalace.\\n\\nPro opravení této potíže zajistěte omezený přístup ke složce \\"contao-manager\\" na Vašem serveru. Jak to lze provést, se dozvíte od Vašeho hostingového poskytovatele nebo v příručce ke správě serveru.","ui.account.welcome":"Vítejte","ui.account.intro1":"Vítejte ve Správci Contaa, univerzálním nástroji k instalaci a správě Contaa Open Source CMS. Pokud jste tu poprvé, přečtěte si prosím návod {readTheManualToGetStarted}.","ui.account.introGetStarted":"Začínáme {readTheManual}.","ui.account.introManual":"přečíst návod","ui.account.intro2":"Pokud si všimnete jakýchkoli nesrovnalostí, podívejte se na seznam nahlášených chyb  {ourGithubIssues}  a případně nahlaste novou, kterou ještě nikdo nenahlásil. ","ui.account.introIssues":"Chyby na GitHubu","ui.account.headline":"Uživatelský účet","ui.account.description":"Abyste mohli spravovat instalaci, vytvořte prosím uživatelský účet. Uvědomte si prosím, že tento účet není stejný pro přihlášení do Contaa. ","ui.account.username":"Uživatelské jméno","ui.account.password":"Heslo","ui.account.passwordPlaceholder":"min. 8 znaků","ui.account.passwordLength":"Zadejte prosím nejméně 8 znaků.","ui.account.loginInvalid":"Došlo k chybě při vytváření účtu. Zkuste jiné úživatelské jméno. ","ui.account.submit":"Vytvořit účet","ui.account.usePassword":"Použít heslo pro příhlášení","ui.account.usePasskey":"Použít passkey pro přihlášení","ui.account.totpHeadline":"Dvoufaktorové ověření","ui.account.totpDescription":"Aktivujte prosím dvoufaktorové ověření, které přidá vašemu uživatelskému účtu další bezpečnostní úroveň. To znamená, že budete muset navíc zadat ověřovací kód generovaný dvoufaktorovými aplikacemi jako 1Password, Authy, Google Authenticator, Microsoft Authenticator, LastPass Authenticator nebo jakoukoli jinou  TOTP aplilkací.","ui.account.totpSetup":"Nastavit nyní","ui.account.totpSkip":"Nastavit později","ui.account.login":"Odmítnout pozvání","ui.account.contribute1":"Contao a Správce Contaa je podporovaný neziskovou Contao Association.","ui.account.contribute2":"Prosím zvažte, zda se chcete stát členem a spolupracovníkem tohoto open source projektu {becomingAMember}.","ui.account.contributeDonate":"Staňte se dárcem","ui.login.headline":"Přihlásit se","ui.login.description":"Přihlaste se, abyste mohli spravovat Vaši instalaci.","ui.login.username":"Uživatelské jméno","ui.login.password":"Heslo","ui.login.totpHeadline":"Dvoufaktorové ověření","ui.login.totpDescription":"Zadejte prosím doufaktorový kód, abyste dokončili přihlášení.","ui.login.totp":"Ověřovací kód","ui.login.forgotPassword":"Zapomněli jste heslo?","ui.login.button":"Přihlásit se","ui.login.passkey":"Přihlásit se pomocí passkey","ui.login.cancel":"Zrušit","ui.login.or":"nebo","ui.login.locked":"Přístup byl zamítnut, protože je Správce Contaa uzamčen. Pro odemknutí smažte soubor {lockFile} na Vašem serveru v kořenové složce Contaa.","ui.logout.headline":"Vypršení sezení","ui.logout.warning":"Byli jste neaktivní po dobu 25 minut. Z bezpečnostních důvodů bude Vaše sezení zakrátko ukončené. ","ui.logout.expired":"Vaše sezení bylo automaticky ukončeno, protože jste byli neaktivní více než 30 minut.","ui.logout.renew":"Zůstat přihlášený/á","ui.logout.logout":"Odhlásit","ui.logout.login":"Zpátky k přihlášení","ui.oauth.error":"Neplatný pokus o ověření totožnosti. Zkontrolujte požadované parametry.","ui.oauth.https":"Přeposílací URL musí používat zabezpečený protokol (https), aby nedošlo k přenosu autorizačního kódu v čirém textu.","ui.oauth.headline":"Smazat autorizaci","ui.oauth.description":"Následující aplikace nebo servis požadují vzdálený přístup k Vašemu Správci Contaa. ","ui.oauth.domain":"Ještě než povolíte přístup, ujistěte se, že znáte tuto URL a důvěřujete jejímu majiteli!","ui.oauth.outOfScope":"Bohužel nemáte potřebné přihlašovací práva, abyste se mohl(a) přihlásit.","ui.oauth.allow":"Povolit přístup","ui.oauth.deny":"Odmítnout přístup","ui.oauth.switchUser":"Přejít na jiného uživatele","ui.scope.admin":"Přístup správce včetně správy uživatelů","ui.scope.install":"Nainstalovat nové balíčky a změnit konfiguraci Contaa","ui.scope.update":"Aktualizovat balíčky a provést úkoly údržby","ui.scope.read":"Načíst balíčky a nastavení","ui.boot.headline":"Kontrola systému","ui.boot.description":"Prosím počkejte, analyzujeme Váš server...","ui.boot.issue1":"Byly zjištěny chyby","ui.boot.issue2":"Vaše instalace obsahuje několik chyb a je ji třeba opravit, než se bude moct použít Správce Contaa.","ui.boot.run":"Spustit Správce Contaa","ui.boot.safeMode":"Spustit v Bezpečnostním módu","ui.recovery.headline":"Záchrana systému","ui.recovery.description":"Správce Contaa našel soubory, které vypadají jako soubory Contaa, ale Příkazový řádek nepracuje tak, jak by měl.","ui.recovery.console":"Výstup konzoly","ui.recovery.repairOptions":"Vyberte prosím jednu z možností pro zotavení Vaší instalace.","ui.recovery.repairHeadline":"Automatická oprava","ui.recovery.repairDescription":"Bude provedené automatické opravení instalace tím, že se přestaví meziúložiště a přeinstalují se balíčky závislé na Composeru.","ui.recovery.repairWarning":"Veškeré úpravy provedené na souborech ve složce vendor budou ztraceny!","ui.recovery.repairFailed":"Automatická oprava neproběhla úspěšně. Pro opravení instalace se pokuste se použít Bezpečnostní mód.","ui.recovery.repairButton":"Spustit opravu systému","ui.recovery.safeModeHeadline":"Bezpečnostní mód","ui.recovery.safeModeDescription":"Spuštěním Správce Contaa v Bezpečnostním módu lze spravovat balíčky a spouštět základní příkazy/úlohy, nejsou ovšem dostupné funkce závislé na instalaci Contaa.","ui.recovery.safeModeButton":"Spustit v Bezpečnostním módu","ui.server.pending":"Čekám…","ui.server.running":"Analyzování…","ui.server.error":"Kontrola selhala kvůli neočekávané odezvě ze strany serveru.","ui.server.details":"Podrobnosti","ui.server.prerequisite":"Kontrola zrušena kvůli chybějící podmínce.","ui.server.selfUpdate.title":"Aktualizace Správce Contaa","ui.server.selfUpdate.update":"Je k dispozici nová verze Správce Contaa {latest}.","ui.server.selfUpdate.manualUpdate":"Je dostupná nová verze Správce Contaa {latest}. Váš server nepodporuje automatické instalace. Stáhněte si proto prosím novou verzi {download}.","ui.server.selfUpdate.latest":"Používáte poslední verzi {current}.","ui.server.selfUpdate.dev":"Vývojové verze nepodporují automatické aktualizace.","ui.server.selfUpdate.unsupported":"Je dostupná novější verze, ale ta nepodporuje Vaši verzi PHP.","ui.server.selfUpdate.button":"Spustit automatické aktualizace","ui.server.selfUpdate.continue":"Pokračovat","ui.server.config.title":"Nastavení serveru","ui.server.config.setup":"Nastavit","ui.server.config.change":"Změnit","ui.server.config.save":"Uložit","ui.server.config.cancel":"Zrušit","ui.server.config.customOption":"Jíné…","ui.server.config.description":"Pro správný běh úloh na pozadí potřebuje Správce Contaa vědět, kde může najít binární příkazový řádek PHP a jak spouštět příkazy odděleně od webové stránky. ","ui.server.config.formTitle":"Nastavení serveru","ui.server.config.formText":"Zadejte prosím cestu k binární PHP. Ujistěte se, že je binární soubor stejný jako Vámi používaná verze PHP. ","ui.server.config.cloudTitle":"Composer Resolver Cloud","ui.server.config.cloudText":"Composer Resolver Cloud umožňuje nainstalovat na Composeru závislých rozšířeních, i když Váš server nemá dostatek paměti. Mějte na paměti, že informaci o Vaši balíčcích budou odeslané na cloudový server vlastněný Asociací Contaa.","ui.server.config.cloud":"Použít Composer Resolver Cloud","ui.server.config.cli":"Binární PHP","ui.server.config.stateErrorCli":"Na Vašem serveru nebyla nalezena žádná platná binární PHP.","ui.server.config.stateErrorCloud":"Composer Resolver Cloud není podporován.","ui.server.config.stateSuccess":"Binární PHP na {php_cli}.","ui.server.config.cloudEnabled":"Závislosti se budou řešit pomocí Composer Resolver Cloudu.","ui.server.config.cloudDisabled":"Composer Resolver Cloud není aktivní.","ui.server.php_web.title":"Webový proces PHP","ui.server.php_web.below7":"Byla nalezena následující verze PHP {version}. Prosím přejděte co nejdříve na PHP 7. ","ui.server.php_web.success":"Byla nalezena následující verze PHP {version}, nejsou známé žádné chyby.","ui.server.php_cli.title":"Rozhraní příkazového řádku PHP","ui.server.php_cli.success":"Byla nalezena následující verze PHP {version}, nejsou známé žádné chyby.","ui.server.composer.title":"Prostředí Composeru","ui.server.composer.success":"Nebyly nalezeny žádné chyby.","ui.server.composer.install":"Věci závislé na Composorovi nejsou nainstalované.","ui.server.composer.button":"Nainstalovat","ui.server.contao.title":"Instalace Contaa","ui.server.contao.setup":"Nastavení","ui.server.contao.check":"Zkontrolovat databázi","ui.server.contao.empty":"Nebyla nalezena žádná instalace Contaa.","ui.server.contao.old":"Verze Contaa {version} není kompatabilní se Správcem Contaa. Zaktualizujte prosím Vaši instalaci manuálně.","ui.server.contao.found":"Nalezeno Contao {version} (verze API {api})","ui.server.contao.connectionError":"Nepodařilo se připojit k serveru databáze.","ui.server.contao.connectionProblem":"Nalezen problém s databází.","ui.server.contao.missingUser":"Nebyl nalezen žádný administrační účet.","ui.setup.continue":"Pokračovat","ui.setup.manager":"Spustit Správce Contaa","ui.setup.cancel":"Zrušit","ui.setup.welcome":"Vítejte","ui.setup.welcome1":"Tento průvodce Vás provede důležitými kroky pro nastavení instalace CMS Contao.","ui.setup.welcome2":"Pokud máte jakýkoli dotaz, prohlédněte si prosím dokumentaci, fóra, kanál Slacku nebo se obraťte na stránku {podpory}.  ","ui.setup.support":"podpora komunity","ui.setup.start":"Začít","ui.setup.complete":"Blahopřejeme!","ui.setup.complete1":"Úspěšně byla nainstalována {version} Contaa.","ui.setup.complete2":"Pro ukončení tohoto procesu otevřete prosím instalační nástroj, abyste nastavili připojení k databázi a vytvořili účet administrátora.","ui.setup.complete3":"Nyní můžete začít vytvářet Vaši webovou stránku v backendu Contaa. Potřebujete-li dodatečná rozšíření, vraťte se do Správce Contaa.","ui.setup.installTool":"Otevřít instalační nástroj","ui.setup.login":"Přihlásit se do Contaa","ui.setup.funding":"Volný software je \\"volný\\" jako \\"volný projev\\", ale ne jako \\"pivo zdarma\\". Open source projekt jako Contaa vyžaduje řadu peněz a nedá se ho uskutečnit bez jediné osoby nebo firmy. \\nPokud máte vytvořenou webovou stránku pomocí Contaa nebo je prodáváte, potěšilo by nás, kdybyste nás finančně podpořili poměrně k Vašemu obchodu.","ui.setup.fundingLink":"Dozvědět se víc","ui.setup.document-root.headline":"Nastavení webového serveru","ui.setup.document-root.warning":"Abyste mohli nainstalovat Contao prostřednictvím Správce Contaa, musíte opravit kořenový dokument na webovém serveru.","ui.setup.document-root.description1":"Contao používá zvláštní složku pro veřejné soubory. Aplikační soubory jsou nainstalované v rodičovské složce. Contao právě nelze nainstalovat, protože Vaše složková struktura není správná nebo složky nejsou prázdné.","ui.setup.document-root.description2":"Pokud nevíte, jak nastavit kořenový dokument, přečtěte si prosím dokumentaci Contaa nebo se obraťte na svého poskytovatele webových služeb.","ui.setup.document-root.documentation":"Přečíst si dokumentaci","ui.setup.document-root.conflictsTitle":"Instalační složka není prázdná","ui.setup.document-root.conflictsDirectory":"Kořenová složka Vaší budoucí instalace Contaa není prázdná. Našli jsem následující počet souborů {count}, které se musí přepsat během instalace. Doporučujeme vytvořit prázdnou složku pro instalaci Contaa, nebo můžete také smazat veškeré věci, které se právě nachází ve vybrané složce, pokud jste si jistí, že je již nepotřebujete. ","ui.setup.document-root.ignoreConflicts":"Chci nainstalova Contao do nevyprázděné složky. Souhlasím s tím, že budou dané soubory přepsány. ","ui.setup.document-root.check":"Znovu zkontrolovat","ui.setup.document-root.create":"Vytvořit složky","ui.setup.document-root.change":"Změnit složky","ui.setup.document-root.formTitle":"Nastavení adresáře","ui.setup.document-root.formText1":"Správce Contaa může automaticky vytvořit novou adresářovou strukturu na tomto webovém serveru.","ui.setup.document-root.formText2":"Budete muset nastavit nový kořenový dokument (např. pomocí správního panelu ve Vašem účtu webových služeb).","ui.setup.document-root.autoconfig":"Rozumím tomu, že musím změnit nastavení serveru. Pokud se tak nestane, může dojít k poruše Správce Contaa a poničení souborů nastavení (včetně podrobností k účtu a heslu)!","ui.setup.document-root.directory":"Nový adresář","ui.setup.document-root.currentRoot":"Současný kořenový dokument","ui.setup.document-root.newRoot":"Nový kořenový dokument","ui.setup.document-root.finish":"Nastavení adresářů","ui.setup.document-root.publicDir":"Použijte {dir} pro veřejné soubory (pro Contao {version})","ui.setup.document-root.directoryInvalid":"Zadejte prosím platný název adresáře","ui.setup.document-root.directoryExists":"Cílový adresář již existuje. Zadejte prosím jiný název.","ui.setup.document-root.confirmation":"Správce Contaa úspěšně vytvořil potřebný adresář pro instalaci Contaa. Nyní musíte nastavit kořenový dokument na svém webovém serveru. Nenačítejte tuto stránku do té doby.","ui.setup.document-root.reload":"Načíst stránku znovu","ui.setup.document-root.success":"Struktura složek je nastavená na Vašem serveru správně!","ui.setup.document-root.installingProjectDir":"Aplikační soubory se nainstalují do {dir}.","ui.setup.document-root.installingPublicDir":"Veřejné soubory se nainstalují do {dir}.","ui.setup.document-root.installedProjectDir":"Aplikační soubory jsou nainstalované v {dir}.","ui.setup.document-root.installedPublicDir":"Veřejné soubory jsou nainstalované v {dir}.","ui.setup.create-project.headline":"Instalace Contaa","ui.setup.create-project.description":"Vývoj Contaa se drží principů {semver}, nová menší verze vychází každých šest měsíců. Současná verze, která se udržuje, je:","ui.setup.create-project.semver":"Sémantické číslování verzí","ui.setup.create-project.latestTitle":"Poslední","ui.setup.create-project.ltsTitle":"Několikaletá podpora - Long Term Support","ui.setup.create-project.latestQ1":"Naše poslední verze nabízí nejnovější funkce s podporou do února {year}.","ui.setup.create-project.latestQ3":"Naše poslední verze nabízí nejnovější funkce s podporou do srpna {year}.","ui.setup.create-project.ltsText":"Naše současná verze LTS, chcete-li se zaměřit na stabilitu. Nabízí dlouhodobou podporu do února {year}.","ui.setup.create-project.pltsText":"Naše předešlá verze LTS má podporu do února {year}.","ui.setup.create-project.requiresPHP":"Vyžaduje přinejmenším PHP {version}, používáte PHP {current}.","ui.setup.create-project.releaseplan":"Více informací: {contaoReleasePlan} ","ui.setup.create-project.releaseplanLink":"Plán vydávání nových verzí Contaa","ui.setup.create-project.installed":"Contao {version} je úspěšně nainstalována na vašem serveru. Pokračujte, abyste nastavili vaši databázi nebo spustili Správce Contaa pro nainstalování jiné verze.","ui.setup.create-project.formTitle":"Vyberte distribuci","ui.setup.create-project.formText":"Vyberte prosím verzi, kterou chcete nainstalovat.","ui.setup.create-project.version":"Verze","ui.setup.create-project.demo":"Nainstalovat demoverzi Contaa","ui.setup.create-project.demoDescription":"Demoverze vám pomůže se seznámit s Contaa a pochopit jeho základní fukce. Více předloh můžete najít v {store}.","ui.setup.create-project.coreOnly":"Minimální instalace (pouze jádro)","ui.setup.create-project.noUpdate":"Přeskočit instalaci (pouze pro pokročilé!)","ui.setup.create-project.theme":"Předloha Contaa","ui.setup.create-project.themeInstall":"Abyste nainstalovali předlohu Contaa, použijte vyhledávací políčko nebo načtete soubor (.cto/.zip), který podporuje instalace pomocí Správce Contaa.","ui.setup.create-project.themeBuy":"Podívejte se na další předlohy v obchodě {store}.","ui.setup.create-project.themeStore":"Obchod předloh Contaa","ui.setup.create-project.themeUpload":"Načíst soubor předlohy (.cto/.zip)","ui.setup.create-project.themeInvalid":"Načtený soubor není předloha Contaa nebo ho Správce Contaa nepodporuje.","ui.setup.create-project.themeWarning":"Správce Contaa nemůže říct, jestli je tato předloha kompatibilní s vaším serverem. Podívejte se prosím na informace předlohy pro získání dalších informací.","ui.setup.create-project.themeTitle":"Podívat se na hodnocení předlohy","ui.setup.create-project.themeDetails":"Následující závislosti a soubory se nainstalují spolu s vybranou předlohou.","ui.setup.create-project.themeRequire":"{count} závilostí | {count} závislostí","ui.setup.create-project.themeFiles":"{count} soubor | {count} souborů","ui.setup.create-project.theme.or":"nebo prohledejte veřejně dostupné předlohy","ui.setup.create-project.theme.search":"Prohledat předlohy","ui.setup.create-project.theme.more":"Více předloh","ui.setup.create-project.theme.empty":"Nenalezeny žádné předlohy pro {query}","ui.setup.create-project.theme.uploaded":"Soubory předlohy byly úspěšně nahrány.","ui.setup.create-project.theme.packageName":"Název balíčku","ui.setup.create-project.theme.version":"Verze","ui.setup.create-project.theme.authors":"Autor/Autoři","ui.setup.create-project.theme.upload":"Nahrávání {name} ({size})","ui.setup.create-project.install":"Nainstalovat","ui.setup.create-project.cancel":"Zrušit","ui.setup.create-project.fileError":"Nepodařilo se najít composer.json v {file}.","ui.setup.create-project.jsonError":"composer.json obsahuje neplatný JSON.","ui.setup.create-project.schemaError":"Ověření schématu composer.json selhalo.","ui.setup.database-connection.headline":"Připojení k databázi","ui.setup.database-connection.description":"Contao vyžaduje přinejmenším jednu databázi MySQL (nebo kompatibilní druh jako MariaDB) pro ukládání stránek, obsahu, uživatelů a příslušných dat. Přihlašovací údaje jsou uložené v souboru {env} v kořenové složce instalace Contaa.","ui.setup.database-connection.formTitle":"Připojovací údaje","ui.setup.database-connection.formText":"Zadejte prosím cestu k databázi nebo vyplňte zvlášť uživatelské jméno, heslo, server a pole databáze.","ui.setup.database-connection.url":"Cesta k databázi","ui.setup.database-connection.validUrl":"Cesta k databázi je neplatná nebo selhalo spojit se se serverem.","ui.setup.database-connection.or":"nebo","ui.setup.database-connection.user":"Uživatelské jméno","ui.setup.database-connection.password":"Heslo","ui.setup.database-connection.server":"Server (:Port)","ui.setup.database-connection.database":"Jméno databáze","ui.setup.database-connection.connected":"Došlo k úspěšnému připojení k {database} na {server}.","ui.setup.database-connection.error":"Při připojení k databázi došlo k chybě.","ui.setup.database-connection.problem":"Contao zjistil problém s Vaší serverovou databází.","ui.setup.database-connection.schemaTitle":"Databázové schéma","ui.setup.database-connection.migration":"Existuje jedna nedokončená migrace. | Existují následující nedokončené migrace: {count}.","ui.setup.database-connection.schema":"Existuje jedna nedokončená schematická aktualizace. | Existují následující nedokončené schematické aktualizace: {count}.","ui.setup.database-connection.noChanges":"Vaše databáze je aktuální. ","ui.setup.database-connection.check":"Zkontrolovat databázi","ui.setup.database-connection.skip":"Přeskočit","ui.setup.database-connection.save":"Uložit","ui.setup.database-connection.change":"Změnit pověření","ui.setup.database-connection.restoreTitle":"Import databáze","ui.setup.database-connection.restoreText":"Předlohu, kterou jste právě nainstalovali, obsahuje již připravenou databázi s definovaným obsahem. Pokud ji chcete nahrát a začít tak používat Contao s již definovaným obsahem, nahrajte danou databázi, nebo přeskočte tento krok. |  Předlohu, kterou jste právě nainstalovali, obsahuje několik připravených databází s již definovaným obsahem. Pokud je chcete nahrát a začít tak používat Contao s již definovaným obsahem, nahrajte dané databázi, nebo přeskočte tento krok","ui.setup.database-connection.backup":"Uložit současnou databázi před importem.","ui.setup.database-connection.backupWarning":"Veškerá data budou v databázi přepsána! Ponejprv si uložte současnou databázi, pokud již není prázdná.","ui.setup.database-connection.restore":"Importovat předlohu databáze","ui.setup.database-connection.restoreOption":"Uložená databáze {date} ({size})","ui.setup.database-connection.restored":"Vaše databáze byla úspěšně importovaná. Pokračujte prosím, abyste provedli aktualizaci schématu databáze.","ui.setup.backend-user.success":"Ve vaší databázi byl nalezen jeden administrátorský účet pro backend Contaa. Pokud si přejete přidat další účty, přihlašte se do backendu Contaa a vytvořte je v sekci Uživatelé.","ui.setup.backend-user.error":"Nebylo možné najít jakýkoli seznam uživatelů. Zkontrolujete prosím výstup příkazového řádku.","ui.setup.backend-user.headline":"Účet backendu","ui.setup.backend-user.description":"Abyste mohli spravovat Vaši webovou stránku, musíte vytvořit alespoň jeden administrativní účet. Uvědomte si prosím, že tento účet není stejný pro přihlášení do Správce Contaa. ","ui.setup.backend-user.formTitle":"Vytvořit účet","ui.setup.backend-user.formText":"Zadejte prosím údaje pro nový účet backendu.","ui.setup.backend-user.username":"Uživatelské jméno","ui.setup.backend-user.name":"Jméno","ui.setup.backend-user.email":"Mailová adresa","ui.setup.backend-user.emailInvalid":"Zadejte prosím platnou mailovou adresu","ui.setup.backend-user.password":"Heslo","ui.setup.backend-user.passwordPlaceholder":"min. 8 znaků","ui.setup.backend-user.passwordLength":"Zadejte prosím nejméně 8 znaků.","ui.setup.backend-user.create":"Přidat účet","ui.task.headline":"Úloha na pozadí","ui.task.loading":"Načítání podrobností...","ui.task.created":"Načítání podrobností...","ui.task.active":"Počkejte prosím, zatímco Spráce Contaa na pozadí vyřizuje operační úlohy.","ui.task.complete":"Všechny operace byly úspěšně provedené. Další podrobnosti získáte v protokolu konzoly.","ui.task.paused":"Příkaz na pozadí byl znenadání zastaven. Zkontrolujte prosím protokol konzoly.","ui.task.aborting":"Počkejte prosím, zatímco se na pozadí zastavují operace.","ui.task.stopped":"Některé z operačních úloh byly zrušené. Zkontrolujte prosím protokol konzoly.","ui.task.error":"Příkaz na pozadí byl znenadání zastaven. Zkontrolujte prosím protokol konzoly.","ui.task.failed":"Správci Contaa se nepodařilo spustit úlohu!","ui.task.failedDescription1":"Něco se pokazilo, zatímco probíhaly úlohy na pozadí.","ui.task.failedDescription2":"Pokud se to bude opakovat, nejspíš není Váš server podporovaný.","ui.task.reportProblem":"Oznámit problém","ui.task.pausedDescription":"Klikněte na \\"Pokačovat\\", pokud chcete ignorovat danou chybu a provést zbývající operace.","ui.task.sponsor":"Cloud Composeru spozorován: {sponsor}","ui.task.buttonAudit":"Zaktualizovat dabázi","ui.task.buttonClose":"Zavřít","ui.task.buttonConfirm":"Potvrdit a zavřít","ui.task.buttonContinue":"Pokračovat","ui.task.buttonCancel":"Zrušit","ui.task.confirmCancel":"Jste si jistí, že chcete zrušit tuto úlohu? To může zanechat instalaci Contaa v špatném stavu!","ui.task.autoclose":"Zavřít podrobnosti o úloze po úspěšném dokončení","ui.console.toggle":"Zobrazit/skrýt výstup příkazového řádku","ui.console.showLog":"Zobrazit celý protokol konzoly","ui.console.copyLog":"Zkopírovat protokol do schránky.","ui.migrate.headline":"Aktualizace databáze","ui.migrate.migrationsOnly":"(pouze migrace)","ui.migrate.schemaOnly":"(pouze schémata)","ui.migrate.loading":"Prosím počkejte, analyzujeme Vaši databázi...","ui.migrate.empty":"Nebyl nalezené žádné aktualizace pro migraci nebo schémata. Vaši databáze je aktuální.","ui.migrate.emptyMigrations":"Nebyla nalezené žádné nedokončené migrace. Ujistěte se prosím, zda není potřeba také zaktualizovat schémata.","ui.migrate.emptySchema":"Nebyla nalezené žádné nedokončené schémata. Ujistěte se prosím, zda není potřeba také zaktualizovat migrace.","ui.migrate.pending":"Vaše databáze není aktuální. Prohlídněte si prosím níže konzolu a zaktualizujte Vaši databázi.","ui.migrate.previousChanges":"Předešlá migrace nebyla potvrzená.\\nProhlédněte si prosím níže výsledky v konzole a pak proveďte potřebné změny.","ui.migrate.previousComplete":"Předešlá migrace nebyla potvrzená. Prohlédněte si prosím níže výsledky v konzole.\\nExistuje několik nedokončených změn.","ui.migrate.appliedChanges":"Databáze byla zaktualizovaná. \\nProhlédněte si prosím níže výsledky v konzole, pak pokračujte dalšími kroky, abyste provedli další změny. ","ui.migrate.appliedComplete":"Databáze byla zaktualizovaná. \\nNeexistují žádné další nedokončené migrace nebo schémata. Vaše databáze je aktuální. ","ui.migrate.problem":"Contao zjistil problém s Vaším databázovým serverem. \\nProhlédněte si prosím níže výsledky v konzole, abyste se dozvěděli více o tom, co je potřeba opravit.  | Contao zjistil problém s Vaším databázovým serverem. \\nProhlédněte si prosím níže výsledky v konzole, abyste se dozvěděli více o tom, co je potřeba opravit. ","ui.migrate.warning":"Contao zjistil nesprávné nastavení Vašeho databázového serveru. \\nVarování lze dočasně přeskočit, měly by se ale opravit, aby docházelo k dobrému výkonu a zacházení s daty. ","ui.migrate.error":"Změny nelze provést. Vaše databáze se možná změnila. Zkontrolujte to prosím ještě jednou a proveďte daný krok ještě jednou.","ui.migrate.execute":"Provést","ui.migrate.close":"Zavřít","ui.migrate.confirm":"Potvrdit a zavřít","ui.migrate.cancel":"Zrušit","ui.migrate.continue":"Pokračovat","ui.migrate.setup":"Nastavení","ui.migrate.skip":"Přeskočit","ui.migrate.retry":"Znovu zkontrolovat","ui.migrate.retryAll":"Vybrat vše","ui.migrate.withDeletes":"Provést všechny změny databáze včetně příkazu ke smazání. ","ui.migrate.migrationTitle":"Migrace databáze","ui.migrate.schemaTitle":"Schématická aktualizace","ui.migrate.problemTitle":"Problémy databáze","ui.migrate.warningTitle":"Varování databáze","ui.migrate.addTable":"Přidat tabulku {table}","ui.migrate.dropTable":"Odstranit tabulku {table}","ui.migrate.addField":"Přidat pole {table}. {field}","ui.migrate.changeField":"Změnit pole {table}.{field}","ui.migrate.dropField":"Odstranit pole {table}.{field}","ui.migrate.createIndex":"Vytvořit index \\"{name}\\" v {table}","ui.migrate.dropIndex":"Odstranit index \\"{name}\\" v {table}","ui.widget.mandatory":"Toto pole nesmí být prázdné.","ui.widget.blankOption":"Vyberte prosím…","ui.widget.showPassword":"Zobrazit heslo","ui.widget.hidePassword":"Skrýt heslo","ui.error.title":"Požadavek HTTP pro \\"{method} {url}\\" selhal.","ui.error.server500":"Vypadá to, že došlo k nečekané chybě na Vašem webovém serveru. Zkontrolujte prosím protokolové soubory na serveru (Apache/Nginx) a protokol Správce Contaa v \\"contao-manager/logs\\".","ui.error.response":"Server odpověděl statusovým kódem {status}.","ui.error.moreLink":"Více informací","ui.error.support":"Podpora Contaa","ui.error.permission":"Nemáte povolení pro použití této funkce.","ui.footer.help":"Nápověda","ui.footer.reportProblem":"Oznámit problém","ui.navigation.discover":"Prohlédnout","ui.navigation.packages":"Balíčky","ui.navigation.tools":"Nástroje","ui.navigation.installTool":"Instalační nástroj","ui.navigation.backend":"Backend Contaa","ui.navigation.debug":"Debugový mód Contaa","ui.navigation.logViewer":"Prohlížeč protokolu","ui.navigation.phpinfo":"Informace o PHP","ui.navigation.phpinfoLoading":"Načítání informací o PHP…","ui.navigation.maintenance":"Údržba","ui.navigation.rebuildCache":"Přetvoření meziúložiště","ui.navigation.users":"Účty","ui.navigation.systemCheck":"Kontrola systému","ui.navigation.advanced":"Rozšířené","ui.navigation.logout":"Odhlásit","ui.maintenance.database.title":"Migrace databáze","ui.maintenance.database.description":"Migrace databáze zajišťuje konzistentní data a tabulková schémata.","ui.maintenance.database.migrations":"Jedna nedokončená migrace databáze | Počet nedokončených migrací databáze {count} ","ui.maintenance.database.schemaUpdates":"Jedna nedokončená schématická aktualizace | Počet nedokončených schematických aktualizací {count} ","ui.maintenance.database.error":"Nalezen problém s databází.","ui.maintenance.database.warning":"Byly nalezená varování databáze.","ui.maintenance.database.button":"Zkontrolovat databázi","ui.maintenance.database.migrationOnly":"Vybrat pouze migrace","ui.maintenance.database.schemaOnly":"Vybrat pouze schémata","ui.maintenance.database.installTool":"Otevřít instalační nástroj","ui.maintenance.database.createBackup":"Vytvořit uložení databáze","ui.maintenance.database.backupUnsupported":"Ukládání databází není vaší verzí Contaa podporováno.","ui.maintenance.database.backupList":"Máte pouze jednou uloženou vaší databázi, a sice {date}. | Počet uložených databází {count}. Naposledy byla uložená {date}.","ui.maintenance.database.backupEmpty":"Momentálně nemáte žádné uložené databáze.","ui.maintenance.rebuildCache.title":"Meziúložiště aplikace","ui.maintenance.rebuildCache.description":"Přetvoření meziúložiště aplikace je nutné provést po každé změně konfiguračních souborů. ","ui.maintenance.rebuildCache.rebuildProd":"Přetvořit produktivní meziúložiště ","ui.maintenance.rebuildCache.rebuildDev":"Přetvořit vývojářské meziúložiště ","ui.maintenance.rebuildCache.clearProd":"Vyprázdnit produktivní meziúložiště ","ui.maintenance.rebuildCache.clearDev":"Vyprázdnit vývojářské meziúložiště ","ui.maintenance.installTool.title":"Instalační nástroj Contaa","ui.maintenance.installTool.description":"Instalační nástroj Contaa se automaticky uzamkne, pokud nesprávně zadáte heslo třikrát po sobě. ","ui.maintenance.installTool.unlock":"Odemknout Instalační nástroj","ui.maintenance.installTool.lock":"Uzamknout Instalační nástroj","ui.maintenance.dumpAutoload.title":"Composer Class Loader","ui.maintenance.dumpAutoload.description":"Composer autoloader je zodpovědný za načítání tříd PHP. Autoloader musí být spuštěný po přidání vlastních namespace do kořenové composer.json.","ui.maintenance.dumpAutoload.button":"Spustit Autoloadera","ui.maintenance.composerInstall.title":"Na Compseru závislá rozšíření","ui.maintenance.composerInstall.description":"Na Composeru závislá rozšíření se nachází ve složce {vendor} Vaší instalace. Přeinstalování těchto závislostí může být důležité po manipulaci nebo manuálnímu přenosu souboru {composerLock}.","ui.maintenance.composerInstall.button":"Spustit instalátor","ui.maintenance.composerInstall.update":"Spustit aktualizaci Composeru","ui.maintenance.composerCache.title":"Meziúložiště Composeru","ui.maintenance.composerCache.description":"Meziúložiště Composeru stáhla balíčky, aby zlepšily výkonost. Pokud máte potíže jako poničené soubory, pokuste se smazat meziúložiště Composeru, abyste vyvolali nové stáhnutí. ","ui.maintenance.composerCache.button":"Smazat meziúložiště","ui.maintenance.maintenanceMode.title":"Mód údržby","ui.maintenance.maintenanceMode.description":"Když se spustí mód údržby, zobrazí se předloha pro \\"503 service Unavailable\\".","ui.maintenance.maintenanceMode.enable":"Aktivovat","ui.maintenance.maintenanceMode.disable":"Deaktivovat","ui.maintenance.debugMode.title":"Vývojářský mód","ui.maintenance.debugMode.description":"Aktivujte vývojářský mód zadáním uživatele a hesla pro {appDevPhp}.","ui.maintenance.debugMode.descriptionJwt":"Aktivujte vývojářský mód nastavením vývojářské cookie pro danou doménu.","ui.maintenance.debugMode.activate":"Aktivovat","ui.maintenance.debugMode.deactivate":"Deaktivovat","ui.maintenance.debugMode.credentials":"Uživatelské informace","ui.maintenance.debugMode.user":"Zadejte prosím uživatelské jméno pro vývojářský mód.","ui.maintenance.debugMode.password":"Zadejte prosím heslo pro uživatele vývojářského módu.","ui.maintenance.opcodeCache.title":"Operační kód mezinúložiště","ui.maintenance.opcodeCache.description":"Operační kód meziúložiště souborů PHP dokáže rychleji zpracovat data. Musí být smazán za určitých podmínek, pokud se nepodařilo rozpoznat soubory po jejich změně.","ui.maintenance.opcodeCache.button":"Zkrátit meziúložiště","ui.maintenance.safeMode":"Není to dostupné v Bezpečnostním módu","ui.maintenance.unsupported":"Nepodporované Vaší verzí Contaa. ","ui.packages.updateButton":"Zaktualizovat balíčky","ui.packages.searchButton":"Vyhledat balíčky","ui.packages.searchPlaceholder":"Hledají se balíčky…","ui.packages.uploadOverlay":"Přetáhněte a pusťte soubory, které chcete nahrát","ui.packages.uploadButton":"Nahrát balíčky","ui.packages.uploadMessage":"Máte jeden nepotvrzený přenos. | Máte celkem {count} nepotvrzených přenosů.","ui.packages.uploadApply":"Potvrdit nahrání","ui.packages.uploadReset":"Smazat nahráné soubory","ui.packages.uploadIncomplete":"Tyto soubory nebyly zcela nahrány. Smažte je prosím a zkuste to znovu.","ui.packages.uploadDuplicate":"Zdá se, že byly tyto soubory nahrány několikrát. Smažte prosím dané duplikáty.","ui.packages.uploadInstalled":"Tento soubor je již nainstalovaný. Smažte prosím daný duplikát.","ui.packages.uploadUnsupported":"Nahrávání souborů není ve Vaší instalaci podporováno. Ujistěte se prosím, zda je funkce PHP ZIP nainstalovaná a zaktualizujte veškeré závislosti.","ui.packages.changesMessage":"Máte jednu nepotvrzenou změnu. | Máte celkem {count} nepotvrzených změn.","ui.packages.changesDryrun":"Zkouška nanečisto","ui.packages.changesApply":"Provést změny","ui.packages.changesApplyAll":"Zaktualizovat všechny balíčky","ui.packages.changesDryrunAll":"Vyzkoušet všechny balíčky nanečisto","ui.packages.changesReset":"Vrátit změny","ui.packages.changesReview":"Ukázat změny","ui.packagelist.loading":"Spouštění…","ui.packagelist.uploads":"Nahrání/přenos souborů","ui.packagelist.added":"Nové balíčky","ui.packagelist.installed":"Nainstalované balíčky","ui.package.hintRevert":"Vrátit změny","ui.package.hintNoupdate":"Neaktualizovat","ui.package.hintConstraint":"Tento balíček bude nainstalovaný s omezením {constraint}, pokud provedete změny.","ui.package.hintConstraintBest":"Tento balíček bude nainstalovaný v nejnověji dostupné verzi, pokud provedete změny.","ui.package.hintConstraintChange":"Toto omezení pro tento balíček bude změněno z \\"{from}\\" na \\"{to}\\", pokud provedete změny.","ui.package.hintConstraintUpdate":"Tento balíček bude zaktualizovaný, pokud aplikujete tyto změny.","ui.package.hintAdded":"Tento balíček bude nainstalovaný, když aplikujete tyto změny.","ui.package.hintRemoved":"Tento balíček bude smazaný, pokud provedete změny.","ui.package.requiredTitle":"přidáno manuálně","ui.package.requiredText":"Tento balíček je už sice uvedený ve Vašem souboru composer.json, ale ještě není nainstalovaný.","ui.package.removedTitle":"odstaněno manuálně","ui.package.removedText":"Tento balíček byl odstraněn z Vašeho souboru composer.json.","ui.package.installed":"Momentálně nainstalováno:","ui.package.version":"Verze {version}","ui.package.additionalDownloads":"{count} Stažení | {count} Stažení","ui.package.additionalStars":"{count} Hvězda | {count} hvězd","ui.package.editConstraint":"Upravit","ui.package.uploadConstraint":"Toto omezení je nadefinováno nahraným balíčkem.","ui.package.updateButton":"Zaktualizovat","ui.package.removeButton":"Smazat","ui.package.installButton":"Přidat balíček","ui.package.installButtonShort":"Přidat","ui.package.detailsButton":"Podrobnosti","ui.package.latestConstraint":"poslední verze","ui.package.update":"Existuje nová aktualizace","ui.package.updateLatest":"poslední verze","ui.package.updateAvailable":"{version}","ui.package.updateUnknown":"neznámá verze","ui.package.updateConstraint":"Je k dispozici nová verze než ta, kterou právě používáte.","ui.package.incompatible":"{package} nefunguje s Contao {constraint}.","ui.package.incompatibleWarning":"Tento balíček {package} nepracuje správně s žádnou stabilní verzí Contaa {constraint}. Chcete přidat daný balíček a nastavit mu jinou verzi, abyste tím nainstalovali vývojářskou verzi?","ui.package.incompatibleConstraint":"Tento balíček nemá žádný stabilní verzi {constraint}. Nastavte verzi, abyste mohli nainstalovat vývojářskou verzi.","ui.package.incompatibleButton":"Nainstalovat","ui.cloudStatus.headline":"Composer Resolver Cloud","ui.cloudStatus.version":"Verze {version}","ui.cloudStatus.waitingTime":"Doba čekání","ui.cloudStatus.jobs":"Současné úlohy","ui.cloudStatus.workers":"Účastníků","ui.cloudStatus.approx":"{minutes} min.","ui.cloudStatus.none":"ne","ui.cloudStatus.short":"ca. {minutes} min.","ui.cloudStatus.long":"ca. {minutes} min. {seconds} sek.","ui.cloudStatus.error":"Nebylo možné získat status Composer Resolver Cloud. Může být zrovna neaktivní nebo má nějaké problémy.","ui.cloudStatus.button":"Status Cloudu","ui.cloudStatus.refresh":"Znovu načíst status Cloudu","ui.log-viewer.loading":"Spouštění…","ui.log-viewer.empty":"Na Vašem serveru se nenacházejí žádné protokolové soubory.","ui.log-viewer.reload":"Načíst znovu","ui.log-viewer.file":"Protokolový soubor","ui.log-viewer.channel":"Kanál","ui.log-viewer.channelTitle":"Kanál zpráv byl přihlášen.","ui.log-viewer.level":"Úroveň","ui.log-viewer.levelTitle":"Vážnost protokolované zprávy.","ui.log-viewer.timeHeader":"Čas","ui.log-viewer.messageHeader":"Zpráva","ui.log-viewer.showContext":"Zobrazit kontext","ui.log-viewer.hideContext":"Skrýt kontext","ui.log-viewer.showExtra":"Zobrazit extra","ui.log-viewer.hideExtra":"Smazat extra","ui.log-viewer.more":"Dozvědět se víc...","ui.log-viewer.download":"Stáhnout","ui.log-viewer.downloadTitle":"Stáhnout soubor \\"{file}\\"","ui.log-viewer.prodEnvironment":"Produktivní prostředí","ui.log-viewer.devEnvironment":"Vývojářské prostředí (vychytávací mód)","ui.user-manager.loading":"Načítám uživatele...","ui.user-manager.changePassword":"Změnit heslo","ui.user-manager.setupTotp":"Nastavení dvoufaktorového ověření","ui.user-manager.disableTotp":"Deaktivovat dvoufaktorové ověření","ui.user-manager.invite":"Pozvat uživatele","ui.user-manager.delete":"Smazat","ui.user-manager.deleteConfirm":"Opravdu chcete smazat \\"{username}\\"?","ui.user-manager.deleted":"Úspěšně došlo ke smazání {username}","ui.user-manager.passwordHeadline":"Změnit heslo","ui.user-manager.passwordText":"Abyste mohli změnit heslo, zadajte nejdřív vaše stávající a pak vaše nové v odpovídajících polích. ","ui.user-manager.currentPassword":"Současné heslo","ui.user-manager.newPassword":"Nové heslo","ui.user-manager.passwordPlaceholder":"min. 8 znaků","ui.user-manager.submitPassword":"Odeslat","ui.user-manager.passwordChanged":"Vaše heslo bylo úspěšně změněno.","ui.user-manager.passwordError":"Heslo není správné.","ui.user-manager.inviteHeadline":"Pozvat uživatele","ui.user-manager.inviteText":"Pokud potřebujete více přihlášení pro Správce Contaa, můžete zde vytvořit odkaz na pozvání. Sdílejte tento odkaz s někým nebo jej použijte na jiném zařízení k vytvoření nového účtu s danými oprávněními.","ui.user-manager.inviteSuccess1":"Byl vytvořen nový odkaz na pozvání. Níže uvedenou adresu lze použít k vytvoření nového uživatelského účtu pro Správce Contaa. Pozvánka vyprší na {expires} (za týden od nynějška).","ui.user-manager.inviteSuccess2":"Zkopírujte prosím tento odkaz do vaší schránky. Platí jen jednou a již se nezobrazí po zavření tohoto dialogu.","ui.user-manager.createInvitation":"Vytvořit odkaz na pozvání","ui.user-manager.clipboard":"Zkopírovat do schránky","ui.user-manager.permissions":"Dozvědět se víc o povolení","ui.user-manager.cancel":"Zrušit","ui.user-manager.close":"Zavřít","ui.user-manager.you":"Vy","ui.user-manager.2fa":"Dvoufázové ověření 2FA","ui.user-manager.2faEnabled":"Tento účet je zabezpečený dvoufázovým ověřením. ","ui.user-manager.2faDisabled":"Tento účet není dostatečně zabezpečený, protože nepoužívá dvoufázové ověření.","ui.user-manager.passkey":"Passkey","ui.user-manager.passkeyTitle":"Tento účet je zabezpečený pomocí passkey","ui.totp.headline":"Dvoufaktorové ověření","ui.totp.setupQr":"Naskenujte prosím QR kód pomocí vaší 2FA/TOTP aplikace.","ui.totp.setupCode":"Nemůžete-li naskenovat QR kód, zadejte místo toho následující klíč:","ui.totp.codeLabel":"Ověřovací kód","ui.totp.codeDescription":"Zadejte prosím ověřovací kód vygenerovaný vaší 2FA/TOTP aplikací.","ui.totp.disableText":"Zadejte prosím ověřovací kód, abyste deaktivovali dvoufaktorové ověření. ","ui.totp.invalid":"Ověřovací kód není platný.","ui.totp.enable":"Aktivovat","ui.totp.disable":"Deaktivovat","ui.totp.cancel":"Zrušit","ui.totp.enabled":"Dvoufaktorové ověření bylo úspěšně aktivováno.","ui.totp.disabled":"Dvoufaktorové ověření bylo úspěšně deaktivováno.","ui.totp.setup":"Nastavení dvoufaktorového ověření","ui.totp.skip":"Přeskočit dvoufázové ověření"}')}}]);"use strict";(self["webpackChunkcontao_manager"]=self["webpackChunkcontao_manager"]||[]).push([[551],{2551:function(e){e.exports=JSON.parse('{"ui.app.httpsHeadline":"!! この接続は安全ではありません !!","ui.app.httpsDescription":"HTTPSでないと秘密のデータも暗号化しないで送信してしまいます。","ui.app.httpsLink":"詳細な情報","ui.app.httpsHref":"https://https.cio.gov/everything/","ui.app.safeModeHeadline":"!! セーフモードが有効です !!","ui.app.safeModeDescription":"Contao Managerの一部の機能は利用できません。","ui.app.safeModeExit":"セーフモードを終了","ui.app.limitedHeadline":"リモート認証","ui.app.limitedDescription":"パスワードなしのログインのため限れた権限になっています。","ui.app.limitedLogout":"再認証","ui.app.totpHeadline":"セキュリティの注意","ui.app.totpDescription":"すぐに2ファクタ認証を構成してアカウントを安全にします。","ui.app.totpSetup":"セットアップ","ui.app.loading":"Contao Managerを読み込み中…","ui.app.apiError":"予期しないAPIの状態","ui.app.configSecurity1":"セキュリティ警告!!!  保護していない設定ディレクトリを検出","ui.app.configSecurity2":"Contao Managerは設定ファイルが公開してアクセスできる状態を検出しました。ディレクトリを安全な状態にするまで、すべての操作は動作しません、そうしないとインストールに含まれている極秘データを攻撃者がアクセスできる可能性があるためです。\\n\\nこれを修正するには\\"contao-manager\\"のディレクトリへのアクセスを禁止してください。この方法を学ぶには、ウェブサーバーのマニュアルを参照するかホスティング提供者に連絡してください。","ui.account.welcome":"ようこそ","ui.account.intro1":"Contao Managerにようこそ。Contao ManagerはContaoオープンソースCMSのインストールと管理を行う多才なツールです。Contao Managerを初めて利用する場合は{readTheManualToGetStarted}","ui.account.introGetStarted":"最初に{readTheManual} ","ui.account.introManual":"マニュアルを読んでください","ui.account.intro2":"何か問題があった場合は、{ourGithubIssues} を確認して、まだ報告されていない新しいどの様な問題は自由に新しいIssueを作成してください。","ui.account.introIssues":"GitHubのIssue","ui.account.headline":"ユーザーアカウント","ui.account.description":"インストールしたContaoを管理するには新しいアカウントを作成してください。このアカウントはContaoのバックエンドやフロントエンドとはまったく関係ないことに注意してください。","ui.account.username":"ユーザー名","ui.account.password":"パスワード","ui.account.passwordPlaceholder":"最小で8文字","ui.account.passwordLength":"少なくとも8文字を入力してください。","ui.account.loginInvalid":"アカウントの作成でエラーとなりました。異なるユーザー名で試してください。","ui.account.submit":"アカウントを作成","ui.account.usePassword":"ログインにパスワードを使用","ui.account.usePasskey":"パスキーをログインに使用","ui.account.totpHeadline":"2ファクター認証","ui.account.totpDescription":"2ファクター認証を有効にしてセキュリティレベルを高めてください。ユーザー名とパスワードに加えて、1Password、Authy、Google Authenticator、LastPass Authenticatorや他のTOTP(Time-based One-Time Password)アプリの確認コードの入力が必要となります。","ui.account.totpSetup":"すぐに設定","ui.account.totpSkip":"後で設定","ui.account.login":"申し出を拒否","ui.account.contribute1":"ContaoとContao Managerは非営利のContao Associationが支援しています。","ui.account.contribute2":"{donate}でオープンソースに貢献することをご検討ください。","ui.account.contributeDonate":"寄付をする","ui.login.headline":"サインイン","ui.login.description":"インストールを管理するにはログインします。","ui.login.username":"ユーザー名","ui.login.password":"パスワード","ui.login.totpHeadline":"2ファクター認証","ui.login.totpDescription":"確認コードを入力してログイン処理を完了してください。","ui.login.totp":"確認コード","ui.login.forgotPassword":"パスワードを忘れましたか?","ui.login.button":"サインイン","ui.login.passkey":"パスキーでサインイン","ui.login.cancel":"取り止め","ui.login.or":"または","ui.login.locked":"Contao Managerはロック状態のためアクセスを拒否しました。ロックを解除するには、Contaoのルートディレクトリにあるファイル: {lockFile}を削除してください。","ui.logout.headline":"セッションタイムアウト","ui.logout.warning":"25分以上アクセスがありません。セキュリティ上の理由から、セッションを間もなく終了します。","ui.logout.expired":"30分以上アクセスがなかったため自動的にセッションを終了しました。","ui.logout.renew":"ログインを維持","ui.logout.logout":"ログアウト","ui.logout.login":"ログイン画面に戻る","ui.oauth.error":"不正なOAuthの試みです。リクエストのパラメーターを確認してください。","ui.oauth.https":"平文で認証トークンが転送されることを防ぐため、リダイレクトのURIは安全なプロトコル(https:)を*使用*しなければなりません。","ui.oauth.headline":"リモート認証","ui.oauth.description":"以下のアプリケーションやサービスが、このContao Managerへのリモートアクセスを要求しています。","ui.oauth.domain":"アクセスを許可する前に、このURLのことを知っていて所有者を信頼できることを確認してください!","ui.oauth.outOfScope":"残念ですが、このアクセスを許可するのに十分な権限がありません。","ui.oauth.allow":"アクセスを許可","ui.oauth.deny":"アクセスを拒否","ui.oauth.switchUser":"ユーザーを切り替え","ui.scope.admin":"ユーザー管理を含んだ管理者アクセス","ui.scope.install":"新しいパッケージのインストールとContaoの構成の変更","ui.scope.update":"パッケージの更新と保守の作業の実行","ui.scope.read":"パッケージと構成の読み取り","ui.boot.headline":"システム検査","ui.boot.description":"しばらくお待ちください、サーバーを解析中です...","ui.boot.issue1":"インストール上の問題を検出","ui.boot.issue2":"Contao Managerを使用できるようにする前に修正しなければならない問題があります。","ui.boot.run":"Contao Managerを開始","ui.boot.safeMode":"セーフモードで開始","ui.recovery.headline":"システム回復","ui.recovery.description":"Contao ManagerはContaoと思われるファイルを検出しましたが、コマンド行のインターフェイスは期待した様に動作しませんでした。","ui.recovery.console":"コンソール出力","ui.recovery.repairOptions":"インストールしたContaoを修正する方法を選択してください。","ui.recovery.repairHeadline":"自動修復","ui.recovery.repairDescription":"アプリケーションキャッシュの再構築とComposerパッケージを再インストールすることで、自動的にインストールの修復を試みます。","ui.recovery.repairWarning":"この処理でベンダーのファイルに行った変更は取り消されるかもしれません!","ui.recovery.repairFailed":"自動修復できませんでした。セーフモードで手作業でインストールを修復してみてください。","ui.recovery.repairButton":"システム修復を実行","ui.recovery.safeModeHeadline":"セーフモード","ui.recovery.safeModeDescription":"Contao Managerをセーフモードで開始するとパッケージの管理と特定の保守のタスクを実行できます。しかし、インストールしたContaoの動作に依存した機能は利用できません。","ui.recovery.safeModeButton":"セーフモードで開始","ui.server.pending":"待機中...","ui.server.running":"解析中…","ui.server.error":"サーバーからの予期しない応答のため検査に失敗しました。","ui.server.details":"詳細","ui.server.prerequisite":"前提条件を満たせていないため検査を取り止めました。","ui.server.selfUpdate.title":"Contao Managerを更新","ui.server.selfUpdate.update":"新しいContao Managerのバージョン {latest} を利用できます。","ui.server.selfUpdate.manualUpdate":"新しいContao Managerバージョン{latest}を利用できます。使用しているサーバーは自動的な更新をサポートしていません、新しいバージョンを {download} からダウンロードしてください。","ui.server.selfUpdate.latest":"最新のバージョン: {current}を使用しています。","ui.server.selfUpdate.dev":"開発版は自動的な更新をサポートしていません。","ui.server.selfUpdate.unsupported":"新しいバージョンを利用できますが、使用しているPHPのバージョンをサポートしていません。","ui.server.selfUpdate.button":"自己更新を実行","ui.server.selfUpdate.continue":"続ける","ui.server.config.title":"サーバーの構成","ui.server.config.setup":"構成","ui.server.config.change":"変更","ui.server.config.save":"保存","ui.server.config.cancel":"取り止め","ui.server.config.customOption":"その他…","ui.server.config.description":"バックグラウンドのタスクを正しく実行するため、Contao ManagerはPHPのコマンド行の実行ファイルがある場所と、ウェブのプロセスから切り離してコマンドを実行する方法を知る必要があります。","ui.server.config.formTitle":"サーバーの構成","ui.server.config.formText":"PHPの実行ファイルのパスを入力してください。Webのプロセスと同じバージョンのPHPであることを忘れずに確認してください。","ui.server.config.cloudTitle":"Composerリゾルバークラウド","ui.server.config.cloudText":"Composerリゾルバークラウドによって、サーバーが十分なローカルのメモリを提供しない場合でもComposerの依存関係のインストールが可能になります。パッケージの情報がContao Associationが運用するクラウドに送信されることに注意してください。","ui.server.config.cloud":"Composerリゾルバークラウドを使用","ui.server.config.cli":"PHPの実行ファイル","ui.server.config.stateErrorCli":"有効なPHPの実行ファイルをサーバー上に見つけられませんでした。","ui.server.config.stateErrorCloud":"Composerリゾルバークラウドをサポートしていません。","ui.server.config.stateSuccess":"PHPの実行ファイルは{php_cli}です。","ui.server.config.cloudEnabled":"パッケージの依存関係はComposerリゾルバークラウドを使用して解決します。","ui.server.config.cloudDisabled":"Composerリゾルバークラウドは無効です。","ui.server.php_web.title":"PHPのWebプロセス","ui.server.php_web.below7":"PHPのバージョン {version} を検出しました。可能な限りPHP 7に切り替えてください!","ui.server.php_web.success":"PHPのバージョン {version} を検出しました、既知の問題はありませんでした。","ui.server.php_cli.title":"PHPコマンド行インターフェイス","ui.server.php_cli.success":"PHPのバージョン {version} を検出しました、既知の問題はありませんでした。","ui.server.composer.title":"Composer環境","ui.server.composer.success":"既知の問題はありませんでした。","ui.server.composer.install":"Composerの依存関係はインストールしていません。","ui.server.composer.button":"インストール","ui.server.contao.title":"Contaoのインストール","ui.server.contao.setup":"セットアップ","ui.server.contao.check":"データベースを検査","ui.server.contao.empty":"インストールしているContaoは見つかりませんでした。","ui.server.contao.old":"Contaoのバージョン{version}はContao Managerと互換性がありません。インストールしているContaoを手作業で更新してください。","ui.server.contao.found":"Contao {version} (APIバージョン {api})を検出しました。","ui.server.contao.connectionError":"データベースサーバーに接続できません。","ui.server.contao.connectionProblem":"データベースの問題が見つかりました。","ui.server.contao.missingUser":"管理者のアカウントがありません。","ui.setup.continue":"続ける","ui.setup.manager":"Contao Managerを開始","ui.setup.cancel":"取り止め","ui.setup.welcome":"ようこそ","ui.setup.welcome1":"このウィザードはContaoオープンソースCMSを設定するのに必要な段階を案内します。","ui.setup.welcome2":"もし質問がありましたらドキュメント、フォーラム、Slackのチャンネル、さらに多くの情報を{support}のページから探してください。","ui.setup.support":"コミュニティサポート","ui.setup.start":"始める","ui.setup.complete":"おめでとうございます!","ui.setup.complete1":"Contao {version}をうまくインストールしました。","ui.setup.complete2":"設定の処理を終えるには、インストールツールを開いて、データベース接続を構成し、バックエンドのユーザーを作成してください。","ui.setup.complete3":"Contaoのバックエンドでウェブサイトを作成できるようになりました。追加の機能拡張が必要な場合は、Contao Managerを続けてください。","ui.setup.installTool":"インストールツールを開く","ui.setup.login":"Contaoにログイン","ui.setup.funding":"フリーソフトウェアの「フリー」は「言論の自由」の自由であって、「無料のビール」の「無料」ではありません。Contaoのようなオープンソースのプロジェクトは一人の個人や1つの会社では集められない資金を必要とします。\\nContaoでウェブサイトを構築したり、構築したウェブサイトを販売される場合は、ビジネスが依存する製品に金銭的に貢献されることを期待しています。","ui.setup.fundingLink":"さらに学ぶ","ui.setup.document-root.headline":"Webサーバーの設定","ui.setup.document-root.warning":"Contao ManagerからContaoをインストールするには、Webサーバーのドキュメントルートを修正しなければなりません。","ui.setup.document-root.description1":"Contaoは公開するファイルに別のフォルダーを使用し、その親のフォルダーにアプリケーションのファイルをインストールします。フォルダーの構造が正しくないか、またはフォルダーが空でない場合はContaoをインストールできません。","ui.setup.document-root.description2":"ドキュメントルートを構成する方法を知らない場合は、Contaoのドキュメントを読むかホスティングサービスの提供者に連絡してください。","ui.setup.document-root.documentation":"ドキュメントを読む","ui.setup.document-root.conflictsTitle":"インストール先のディレクトリが空ではありません","ui.setup.document-root.conflictsDirectory":"Contaoをインストールしようとしているルートのディレクトリが空ではありません、インストールの処理で{count}個のファイルを上書きするかもしれません。Contaoのために空のディレクトリ構造の作成を推奨しますが、以下のファイルを使用していないことが確かな場合は、これらを削除して再検査することもできます。","ui.setup.document-root.ignoreConflicts":"空でないディレクトリにContaoをインストールしようとしています。Web領域の既存のファイルを上書きする可能性を理解しています。","ui.setup.document-root.check":"再検査","ui.setup.document-root.create":"ディレクトリを作成","ui.setup.document-root.change":"ディレクトリを変更","ui.setup.document-root.formTitle":"ディレクトリ設定","ui.setup.document-root.formText1":"Contao Managerはサーバー上に新しいディレクトリ構成を自動的に作成できます。","ui.setup.document-root.formText2":"手作業で(例えば、ホスティングの管理パネルから)新しいドキュメントルートを構成する必要があります。","ui.setup.document-root.autoconfig":"サーバーの構成を変更しなければならないことを理解しました。ドキュメントルートを構成しないとContao Managerは壊れ、(アカウントの詳細とパスワードを含んだ)構成ファイルを剥き出しの状態にしてしまいます。","ui.setup.document-root.directory":"新しいディレクトリ","ui.setup.document-root.currentRoot":"現在のドキュメントルート","ui.setup.document-root.newRoot":"新しいドキュメントルート","ui.setup.document-root.finish":"ディレクトリの設定","ui.setup.document-root.publicDir":"{dir}を(Contao {version}の)公開ファイルの場所として使用","ui.setup.document-root.directoryInvalid":"有効なディレクトリの名前を入力してください。","ui.setup.document-root.directoryExists":"目的のディレクトリは既に存在します。異なる名前を入力してください。","ui.setup.document-root.confirmation":"Contao ManagerはContaoのインストールに必要なディレクトリを作成しました。次にウェブサーバーのドキュメントルートを構成しなければなりません。このページをそれまで再読み込みしないでください。","ui.setup.document-root.reload":"ページを再読み込み","ui.setup.document-root.success":"ウェブサーバーにディレクトリ構造を正しく設定できました!","ui.setup.document-root.installingProjectDir":"{dir}にアプリケーションのファイルをインストールします。","ui.setup.document-root.installingPublicDir":"{dir}に公開するファイルをインストールします。","ui.setup.document-root.installedProjectDir":"{dir}にアプリケーションのファイルをインストールしました。","ui.setup.document-root.installedPublicDir":"{dir}に公開するファイルをインストールしました。","ui.setup.create-project.headline":"Contaoのインストール","ui.setup.create-project.description":"Contaoの開発は{semver}の概念にしたがっていて、新しいマイナーバージョンを6か月毎にリリースします。現在サポートしているリリース:","ui.setup.create-project.semver":"セマンティックバージョニング","ui.setup.create-project.latestTitle":"最新","ui.setup.create-project.ltsTitle":"長期サポート版","ui.setup.create-project.latestQ1":"最新のバージョン、もっとも多くの機能を提供して{year}年2月までサポートします。","ui.setup.create-project.latestQ3":"最新のバージョン、もっとも多くの機能を提供して{year}年8月までサポートします。","ui.setup.create-project.ltsText":"現在のLTSバージョン、安定性を重視する場合に選んでください。さらに{year}年2月までの長期サポートを提供します。","ui.setup.create-project.pltsText":"以前のLTSバージョン、さらに{year}年2月までの長期サポートを提供します。","ui.setup.create-project.requiresPHP":"少なくともPHP {version}が必要です、現在はPHP {current}です。","ui.setup.create-project.releaseplan":"詳細な情報は{contaoReleasePlan}を参照してください。","ui.setup.create-project.releaseplanLink":"Contaoのリリース計画","ui.setup.create-project.installed":"サーバーにContao {version}のインストールに成功しました。データベースの設定を続けるか、異なるバージョンをインストールするにはContao Managerを起動してください。","ui.setup.create-project.formTitle":"配布の選択","ui.setup.create-project.formText":"インストールするバージョンを選択してください。","ui.setup.create-project.version":"バージョン","ui.setup.create-project.demo":"Contaoのデモ版のWebサイトをインストール","ui.setup.create-project.demoDescription":"デモ版のWebサイトはContaoと、その基本的な特徴を知る助けとなります。テーマはさらに{store}で入手できます。","ui.setup.create-project.coreOnly":"最小のインストール(コアだけ)","ui.setup.create-project.noUpdate":"インストールを省く(専門家だけ!)","ui.setup.create-project.theme":"Contaoのテーマ","ui.setup.create-project.themeInstall":"Contaoのテーマをインストールするには、検索入力を使用するか、Contao Managerからのインストールをサポートしたテーマのファイル(.ctoまたは.zip)をアップロードしてください。","ui.setup.create-project.themeBuy":"必ず公式の{store}にアクセスしてください。","ui.setup.create-project.themeStore":"Contaoのテーマのストア","ui.setup.create-project.themeUpload":"テーマのファイル(.cto/.zip)をアップロード","ui.setup.create-project.themeInvalid":"アップロードしたファイルはContaoのテーマではないか、Contao Managerをサポートしていません。","ui.setup.create-project.themeWarning":"このテーマがサーバーと互換性があるかどうか、COntao Managerは判断できません。何か疑問がある場合はテーマのベンダーに相談してください。","ui.setup.create-project.themeTitle":"テーマの詳細を調査","ui.setup.create-project.themeDetails":"このテーマは以下の依存関係とファイルもインストールします。","ui.setup.create-project.themeRequire":"{count} 依存関係 | {count} 依存関係","ui.setup.create-project.themeFiles":"{count} ファイル | {count} ファイル","ui.setup.create-project.theme.or":"または公開テーマを検索","ui.setup.create-project.theme.search":"テーマを検索","ui.setup.create-project.theme.more":"さらにテーマ","ui.setup.create-project.theme.empty":"{query}に一致するテーマがありません。","ui.setup.create-project.theme.uploaded":"テーマのファイルのアップロードに成功しました。","ui.setup.create-project.theme.packageName":"パッケージ名","ui.setup.create-project.theme.version":"バージョン","ui.setup.create-project.theme.authors":"作成者","ui.setup.create-project.theme.upload":"{name} ({size})をアップロード中","ui.setup.create-project.install":"インストール","ui.setup.create-project.cancel":"取り止め","ui.setup.create-project.fileError":"{file}にcomposer.jsonがありません。","ui.setup.create-project.jsonError":"composer.jsonが不正なJSONを含んでいます。","ui.setup.create-project.schemaError":"composer.jsonのスキーマの検証に失敗しました。","ui.setup.database-connection.headline":"データベース接続","ui.setup.database-connection.description":"Contaoはページ、コンテント、ユーザー、他の関係のあるデータを保管するためにMySQLデータベース(またはMariaDBの様な互換性のある分岐)を必要とします。接続のパラメーターは、Contaoをインストールしたプロジェクトのルートにある{env}ファイルに保存します。","ui.setup.database-connection.formTitle":"接続パラメーター","ui.setup.database-connection.formText":"データベースのURLを入力するか、ユーザー名、パスワード、サーバー、データベースの欄を別々に入力してください。","ui.setup.database-connection.url":"データベースのURL","ui.setup.database-connection.validUrl":"データベースのURLが正しくないか、サーバーへの接続に失敗しました。","ui.setup.database-connection.or":"または","ui.setup.database-connection.user":"ユーザー名","ui.setup.database-connection.password":"パスワード","ui.setup.database-connection.server":"サーバー(:ポート)","ui.setup.database-connection.database":"データベース名","ui.setup.database-connection.connected":"{server}のデータベース{database}に接続しました。","ui.setup.database-connection.error":"データベースの接続のエラーです。","ui.setup.database-connection.problem":"Contaoはデータベースサーバーの問題を検出しました。","ui.setup.database-connection.schemaTitle":"データベーススキーマ","ui.setup.database-connection.migration":"未解決の移行が1件あります。 | 未解決の移行が{count}件あります。","ui.setup.database-connection.schema":"未解決のスキーマの更新が1件あります。 | 未解決のスキーマの更新が{count}件あります。","ui.setup.database-connection.noChanges":"データベースのスキーマは最新です。","ui.setup.database-connection.check":"データベースを検査","ui.setup.database-connection.skip":"飛ばす","ui.setup.database-connection.save":"保存","ui.setup.database-connection.change":"認証情報を変更","ui.setup.database-connection.restoreTitle":"データベースをインポート","ui.setup.database-connection.restoreText":"先ほどインストールしたテーマはデータベースのバックアップを含んでいます。データベースを復元してテーマのデータを取り込むか、空のContaoのインストールから始める場合はこの段階を飛ばしてください。 | 先ほどインストールしたテーマは複数のデータベースのバックアップを含んでいます。バックアップのファイルを選択してテーマのデータをインポートするか、空のContaoのインストールから始める場合はこの段階を飛ばしてください。","ui.setup.database-connection.backup":"インポート前に現在のデータベースをバックアップ","ui.setup.database-connection.backupWarning":"データベースのすべてのデータを上書きします。データベースが空でない場合は最初にバックアップを作成してください。","ui.setup.database-connection.restore":"テーマのデータベースをインポート","ui.setup.database-connection.restoreOption":"{date} ({size})からバックアップ","ui.setup.database-connection.restored":"テーマのデータベースのインポートに成功しました。データベースのスキーマの検証に進んでください。","ui.setup.backend-user.success":"データベースにContaoのバックエンドの管理者のアカウントがあります。さらにユーザーを追加するにはContaoのバックエンドを使用してください。","ui.setup.backend-user.error":"ユーザーのリストを取り出せません。詳細はコンソールの出力を確認してください。","ui.setup.backend-user.headline":"バックエンドのアカウント","ui.setup.backend-user.description":"ウェブサイトを管理するには、少なくともContaoのバックエンドの管理者のアカウントが1つ必要です。このアカウントはContao Managerと無関係なことに注意してください。","ui.setup.backend-user.formTitle":"アカウントを作成","ui.setup.backend-user.formText":"新しいバックエンドのアカウントの詳細を入力してください。","ui.setup.backend-user.username":"ユーザー名","ui.setup.backend-user.name":"名前","ui.setup.backend-user.email":"電子メールアドレス","ui.setup.backend-user.emailInvalid":"有効な電子メールアドレスを入力してください。","ui.setup.backend-user.password":"パスワード","ui.setup.backend-user.passwordPlaceholder":"最小で8文字","ui.setup.backend-user.passwordLength":"少なくとも8文字を入力してください。","ui.setup.backend-user.create":"アカウントを追加","ui.task.headline":"バックグランドのタスク","ui.task.loading":"詳細を読み込み中...","ui.task.created":"詳細を読み込み中...","ui.task.active":"Contao Managerがバックグラウンドでタスクの処理を実行を開始するまで、しばらくお待ちください。","ui.task.complete":"すべての処理を正常に完了しました。詳細はコンソールの出力を確認してください。","ui.task.paused":"バックグラウンドの処理が予期せず停止しました。コンソールの出力を確認してください。","ui.task.aborting":"バックグラウンドの処理を取り消すまで、しばらくお待ちください。","ui.task.stopped":"バックグラウンドの処理の一部を取り消しました。コンソールの出力を確認してください。","ui.task.error":"バックグラウンドの処理が予期せず停止しました。コンソールの出力を確認してください。","ui.task.failed":"Contao Managerはバックグラウンドのタスクを開始できませんでした!","ui.task.failedDescription1":"バックグラウンドで処理を実行しようとするときに何か問題がありました。","ui.task.failedDescription2":"これが再度起きる場合は、サーバーはサポートされていないかもしれません。","ui.task.reportProblem":"問題を報告","ui.task.pausedDescription":"エラーを無視して残る作業を実行したい場合は「続ける」をクリックしてください。","ui.task.sponsor":"{sponsor}が後援のComposer Cloud","ui.task.buttonAudit":"データベースを更新","ui.task.buttonClose":"閉じる","ui.task.buttonConfirm":"確認して閉じる","ui.task.buttonContinue":"続ける","ui.task.buttonCancel":"取り止め","ui.task.confirmCancel":"このタスクを本当に取り止めて良いですか?  取り止めるとContaoのインストールを壊れた状態のままにするかもしれません。","ui.task.autoclose":"正常に終了したときにタスクの詳細を閉じる","ui.console.toggle":"コンソールの出力を表示・非表示","ui.console.showLog":"完全なコンソールのログを表示","ui.console.copyLog":"ログをクリップボードにコピー","ui.migrate.headline":"データベースの更新","ui.migrate.migrationsOnly":"(移行だけ)","ui.migrate.schemaOnly":"(スキーマだけ)","ui.migrate.loading":"しばらくお待ちください、データベースを検査中です...","ui.migrate.empty":"未解決な移行やスキーマの更新はありません。データベースは最新です。","ui.migrate.emptyMigrations":"未解決な移行はありません。スキーマの更新も忘れずにしてください。","ui.migrate.emptySchema":"未解決なスキーマの更新はありません。移行の確認も忘れずにしてください。","ui.migrate.pending":"データベースが最新ではありません。以下のコンソール出力を再確認して変更を実行してください。","ui.migrate.previousChanges":"以前のデータベース移行を確認できませんでした。\\n以下のコンソール出力を再確認して、次の変更の確認に進んでください。","ui.migrate.previousComplete":"以前のデータベース移行を確認できませんでしたので、以下のコンソール出力を再確認してください。\\nこれ以上の未解決な変更はありません。","ui.migrate.appliedChanges":"データベースの更新を適用しました。\\n以下のコンソール出力を再確認して、次の変更の確認に進んでください。","ui.migrate.appliedComplete":"データベースの更新を適用しました。\\n未確認の移行やスキーマの更新はありません。データベースは最新の状態です。","ui.migrate.problem":"Contaoはデータベースサーバーの問題を検出しました。\\n下のコンソール出力を再確認して修正しなければならない事項を調査してください!","ui.migrate.warning":"Contaoはデータベースサーバーの誤った設定を検出しました。\\n一時的に警告は無視できますが、最適な性能とデータの一貫性のためには修正しなければなりません。","ui.migrate.error":"変更を適用できませんでした。データベースは変更されているかもしれません、再確認して再実行してください。","ui.migrate.execute":"実行","ui.migrate.close":"閉じる","ui.migrate.confirm":"確認して閉じる","ui.migrate.cancel":"取り止め","ui.migrate.continue":"続ける","ui.migrate.setup":"セットアップ","ui.migrate.skip":"飛ばす","ui.migrate.retry":"再検査","ui.migrate.retryAll":"すべて検査","ui.migrate.withDeletes":"DROPの処理を含む、すべてのデータベースの変更を実行します。","ui.migrate.migrationTitle":"データベースの移行","ui.migrate.schemaTitle":"スキーマの更新","ui.migrate.problemTitle":"データベースの問題","ui.migrate.warningTitle":"データベースの警告","ui.migrate.addTable":"テーブルを追加","ui.migrate.dropTable":"テーブルを削除","ui.migrate.addField":"項目{table}.{field}を追加","ui.migrate.changeField":"項目{table}.{field}を変更","ui.migrate.dropField":"項目{table}.{field}を削除","ui.migrate.createIndex":"{table}にインデックス\\"{name}\\"を作成","ui.migrate.dropIndex":"{table}のインデックス\\"{name}\\"を削除","ui.widget.mandatory":"この欄の入力は必須です。","ui.widget.blankOption":"選択してください…","ui.widget.showPassword":"パスワードを表示","ui.widget.hidePassword":"パスワードを非表示","ui.error.title":"\\"{method} {url}\\"というHTTPの要求に失敗しました。","ui.error.server500":"予期しないエラーがサーバーで発生したようです。Webサーバー(Apache/Nginx)のログファイルと、Contao Managerの\\"contao-manager/logs\\"へのログを確認してください。","ui.error.response":"サーバーは{status}という応答コードを返しました。","ui.error.moreLink":"詳細な情報","ui.error.support":"Contaoサポート","ui.error.permission":"この機能を使用する権限がありません。","ui.footer.help":"ヘルプ","ui.footer.reportProblem":"問題を報告","ui.navigation.discover":"発見","ui.navigation.packages":"パッケージ","ui.navigation.tools":"ツール","ui.navigation.installTool":"インストールツール","ui.navigation.backend":"Contaoのバックエンド","ui.navigation.debug":"Contaoのデバッグモード","ui.navigation.logViewer":"ログ表示","ui.navigation.phpinfo":"PHPの情報","ui.navigation.phpinfoLoading":"PHPの情報を読み込み中...","ui.navigation.maintenance":"保守","ui.navigation.rebuildCache":"キャッシュを再作成","ui.navigation.users":"アカウント","ui.navigation.systemCheck":"システム検査","ui.navigation.advanced":"詳細","ui.navigation.logout":"ログアウト","ui.maintenance.database.title":"データベースの移行とバックアップ","ui.maintenance.database.description":"データベースの移行はデータとテーブルのスキーマの一貫性を確保します。","ui.maintenance.database.migrations":"未解決のデータベース移行が1件 | 未解決のデータベース移行が{count}件","ui.maintenance.database.schemaUpdates":"未解決のスキーマの更新が1件 | 未解決のスキーマの更新が{count}件","ui.maintenance.database.error":"データベースの問題が見つかりました。","ui.maintenance.database.warning":"データベースの警告が見つかりました。","ui.maintenance.database.button":"データベースを検査","ui.maintenance.database.migrationOnly":"移行だけを検査","ui.maintenance.database.schemaOnly":"スキーマだけを検査","ui.maintenance.database.installTool":"インストールツールを開く","ui.maintenance.database.createBackup":"バックアップを作成","ui.maintenance.database.backupUnsupported":"このContaoのバージョンではデータベースのバックアップをサポートしていません。","ui.maintenance.database.backupList":"データベースのバックアップが1個あって、{date}に作成されています。 | データベースのバックアップが{count}個あって、最新のものは{date}に作成されています。","ui.maintenance.database.backupEmpty":"現在データベースのバックアップはありません。","ui.maintenance.rebuildCache.title":"アプリケーションキャッシュ","ui.maintenance.rebuildCache.description":"構成ファイルのいずれかを修正した後はアプリケーションキャッシュの再構築が必要です。","ui.maintenance.rebuildCache.rebuildProd":"実稼働用のキャッシュを再構築","ui.maintenance.rebuildCache.rebuildDev":"開発用のキャッシュを再構築","ui.maintenance.rebuildCache.clearProd":"実稼働用のキャッシュを消去","ui.maintenance.rebuildCache.clearDev":"開発用のキャッシュを消去","ui.maintenance.installTool.title":"Contaoインストールツール","ui.maintenance.installTool.description":"連続して3回誤ったパスワードを入力すると、Contaoのインストールツールは自動的にロック状態となります。","ui.maintenance.installTool.unlock":"インストールツールのロックを解除","ui.maintenance.installTool.lock":"インストールツールをロック","ui.maintenance.dumpAutoload.title":"Composerクラスローダー","ui.maintenance.dumpAutoload.description":"ComposerのオートローダーがPHPのクラスの読み込み担当します。rootのcomposer.jsonに独自のネームスペースを追加した後は、オートローダーを書き出さなければなりません。","ui.maintenance.dumpAutoload.button":"オートローダーを書き出し","ui.maintenance.composerInstall.title":"Composerの依存関係","ui.maintenance.composerInstall.description":"Composerの依存関係はアプリケーションのルートの{vendor}フォルダーに配置されています。{composerLock}ファイルを操作や手動でアップロードした後は依存関係の再インストールが必要な場合があります。","ui.maintenance.composerInstall.button":"インストーラーを実行","ui.maintenance.composerInstall.update":"Composerで更新を実行","ui.maintenance.composerCache.title":"Composerキャッシュ","ui.maintenance.composerCache.description":"Composerは性能向上のためにダウンロードしたパッケージをキャッシュします。壊れたファイルのような問題がある場合は、Composerキャッシュを削除して強制的に新しいダウンロードを行ってみてください。","ui.maintenance.composerCache.button":"キャッシュを消去","ui.maintenance.maintenanceMode.title":"保守モード","ui.maintenance.maintenanceMode.description":"Contaoを保守モードにするとウェブサイトでは\\"503 Service Unavailable\\"のテンプレートを表示します。","ui.maintenance.maintenanceMode.enable":"有効","ui.maintenance.maintenanceMode.disable":"無効","ui.maintenance.debugMode.title":"デバッグモード","ui.maintenance.debugMode.description":"{appDevPhp}のエントリーポイントにユーザーとパスワードを設定してデバッグモードを有効にします。","ui.maintenance.debugMode.descriptionJwt":"現在のドメインにデバッグ用のクッキーを設定してデバッグモードを有効にします。","ui.maintenance.debugMode.activate":"有効化","ui.maintenance.debugMode.deactivate":"無効化","ui.maintenance.debugMode.credentials":"認証情報","ui.maintenance.debugMode.user":"デバッグモードのユーザー名を入力してください。","ui.maintenance.debugMode.password":"デバッグモードのパスワードを入力してください。","ui.maintenance.opcodeCache.title":"Opcodeキャッシュ","ui.maintenance.opcodeCache.description":"Opcodeは高速な実行のためにPHPのファイルをウェブプロセス常にキャッシュします。変更後にファイルの変化を認識していないといった、特定の状況では削除しなければなりません。","ui.maintenance.opcodeCache.button":"キャッシュを切り詰め","ui.maintenance.safeMode":"セーフモードでは利用不可","ui.maintenance.unsupported":"このContaoのバージョンでは非サポート","ui.packages.updateButton":"パッケージを更新","ui.packages.searchButton":"パッケージを検索","ui.packages.searchPlaceholder":"パッケージを検索中…","ui.packages.uploadOverlay":"アップロードするファイルをドラッグアンドドロップ","ui.packages.uploadButton":"パッケージをアップロード","ui.packages.uploadMessage":"未確認の1個のアップロードがあります。 | 未確認の{count}個のアップロードがあります。","ui.packages.uploadApply":"アップロードを実行","ui.packages.uploadReset":"アップロードを削除","ui.packages.uploadIncomplete":"このファイルは完全にアップロードできていません。一旦削除削除してもう一度アップロードしてください。","ui.packages.uploadDuplicate":"このファイルを複数回アップロードした様です。重複しているファイルを削除してください。","ui.packages.uploadInstalled":"このファイルを既にインストールしています。重複しているファイルを削除してください。","ui.packages.uploadUnsupported":"インストールしたContaoはアップロードをサポートしていません。PHPのzip拡張のインストールと依存関係の更新を確認してください。","ui.packages.changesMessage":"未確認の1個の変更があります。 | 未確認の{count}個の変更があります。","ui.packages.changesDryrun":"変更を試行","ui.packages.changesApply":"変更を適用","ui.packages.changesApplyAll":"すべてのパッケージを更新","ui.packages.changesDryrunAll":"すべてのパッケージの変更を試行","ui.packages.changesReset":"変更をリセット","ui.packages.changesReview":"変更を見直し","ui.packagelist.loading":"読み込み中...","ui.packagelist.uploads":"アップロード","ui.packagelist.added":"新しいパッケージ","ui.packagelist.installed":"インストール済みのパッケージ","ui.package.hintRevert":"変更を取り消す","ui.package.hintNoupdate":"更新しない","ui.package.hintConstraint":"この変更を適用すると、このパッケージを{constraint}の制約によりインストールします。","ui.package.hintConstraintBest":"変更を適用すると、このパッケージの利用できる一番良いバージョンをインストールします。","ui.package.hintConstraintChange":"変更を適用すると、このパッケージへの制約は\\"{from}\\"から\\"{to}\\"に変更します。","ui.package.hintConstraintUpdate":"変更を適用すると、このパッケージを更新します。","ui.package.hintAdded":"変更を適用すると、このパッケージをインストールします。","ui.package.hintRemoved":"変更を適用すると、このパッケージを削除します。","ui.package.requiredTitle":"手作業で追加済み","ui.package.requiredText":"このパッケージはcomposer.jsonで必要としていますが、インストールされていません。","ui.package.removedTitle":"手作業で削除済み","ui.package.removedText":"このパッケージはcomposer.jsonから削除されています。","ui.package.installed":"インストール済み:","ui.package.version":"バージョン{version}","ui.package.additionalDownloads":"{count}個のダウンロード | {count}個のダウンロード","ui.package.additionalStars":"{count}のスター | {count}のスター","ui.package.editConstraint":"編集","ui.package.uploadConstraint":"この定数はアップロードしたパッケージで定義されています。","ui.package.updateButton":"更新","ui.package.removeButton":"削除","ui.package.installButton":"パッケージを追加","ui.package.installButtonShort":"追加","ui.package.detailsButton":"詳細","ui.package.latestConstraint":"最新のバージョン","ui.package.update":"更新を利用可能","ui.package.updateLatest":"最新のバージョン","ui.package.updateAvailable":"バージョン{version}を利用可能","ui.package.updateUnknown":"不明なバージョン","ui.package.updateConstraint":"バージョンの制約外に利用できる新しいバージョンがあります。","ui.package.incompatible":"{package}はContao {constraint}では動作しません。","ui.package.incompatibleWarning":"どの安定版のリリースの{package}もContao {constraint}では動作しません。パッケージの追加とバージョンの制約を設定して、開発ブランチのインストールを試しますか?","ui.package.incompatibleConstraint":"このパッケージにはContao {constraint}のための安定版のリリースがありません。開発ブランチのインストールを試すには、バージョンの制約を設定してください。","ui.package.incompatibleButton":"インストール","ui.cloudStatus.headline":"Composerリゾルバークラウド","ui.cloudStatus.version":"バージョン{version}","ui.cloudStatus.waitingTime":"待ち時間","ui.cloudStatus.jobs":"現在のジョブ","ui.cloudStatus.workers":"ワーカー","ui.cloudStatus.approx":"{minutes}分","ui.cloudStatus.none":"なし","ui.cloudStatus.short":"ca. {minutes}分","ui.cloudStatus.long":"ca. {minutes}分{seconds}秒","ui.cloudStatus.error":"Composerリゾルバークラウドの状態を取得できません。保守または技術的な問題のため停止しているかもしれません。","ui.cloudStatus.button":"クラウドの状態","ui.cloudStatus.refresh":"クラウドの状態を更新","ui.log-viewer.loading":"読み込み中...","ui.log-viewer.empty":"サーバーにログファイルはありません。","ui.log-viewer.reload":"際読み込み","ui.log-viewer.file":"ログファイル","ui.log-viewer.channel":"チャネル","ui.log-viewer.channelTitle":"このメッセージを記録する先のチャネルです。","ui.log-viewer.level":"レベル","ui.log-viewer.levelTitle":"ログメッセージの深刻さです。","ui.log-viewer.timeHeader":"時刻","ui.log-viewer.messageHeader":"メッセージ","ui.log-viewer.showContext":"コンテキストを表示","ui.log-viewer.hideContext":"コンテキストを非表示","ui.log-viewer.showExtra":"追加を表示","ui.log-viewer.hideExtra":"追加を非表示","ui.log-viewer.more":" さらに読み込む...","ui.log-viewer.download":"ダウンロード","ui.log-viewer.downloadTitle":"\\"{file}\\"をダウンロード","ui.log-viewer.prodEnvironment":"実運用環境","ui.log-viewer.devEnvironment":"開発環境(デバッグモード)","ui.user-manager.loading":"ユーザーを読み込み中...","ui.user-manager.changePassword":"パスワードを変更","ui.user-manager.setupTotp":"2ファクター認証を設定","ui.user-manager.disableTotp":"2ファクター認証を無効","ui.user-manager.invite":"ユーザーを招待","ui.user-manager.delete":"削除","ui.user-manager.deleteConfirm":"ほんとうにユーザー: \\"{username}\\"を削除しますか?","ui.user-manager.deleted":"ユーザー: {username}を削除しました。","ui.user-manager.passwordHeadline":"パスワードを変更","ui.user-manager.passwordText":"パスワードを変更するには、現在のパスワードと新しいパスワードをそれぞれの欄に入力してください。","ui.user-manager.currentPassword":"現在のパスワード","ui.user-manager.newPassword":"新しいパスワード","ui.user-manager.passwordPlaceholder":"最小で8文字","ui.user-manager.submitPassword":"送信","ui.user-manager.passwordChanged":"パスワードを変更しました。","ui.user-manager.passwordError":"このパスワードは間違っています。","ui.user-manager.inviteHeadline":"ユーザーを招待","ui.user-manager.inviteText":"Contao Managerに複数のログイン情報が必要な場合、ここで招待のリンクを作成できます。このリンクを誰か、または他の機器で使用して、指定した権限の新しいアカウントを作成してください。","ui.user-manager.inviteSuccess1":"新しい招待のリンクを作成しました。以下のURLを使用して、このContao Managerの新しいユーザーを作成できます。この招待は(今から1週間後の){expires}に期限が切れます。","ui.user-manager.inviteSuccess2":"リンクをクリップボードにコピーしてください。一度だけ動作し、このダイアログを閉じた後に再び見ることはできません。","ui.user-manager.createInvitation":"招待のリンクを作成","ui.user-manager.clipboard":"クリップボードにコピー","ui.user-manager.permissions":"権限について学ぶ","ui.user-manager.cancel":"取り止め","ui.user-manager.close":"閉じる","ui.user-manager.you":"あなた","ui.user-manager.2fa":"2FA","ui.user-manager.2faEnabled":"このアカウントは2ファクター認証により安全です。","ui.user-manager.2faDisabled":"このアカウントはに2ファクター認証が設定されていないため安全ではありません。","ui.user-manager.passkey":"パスキー","ui.user-manager.passkeyTitle":"このアカウントはパスキーにより安全です。","ui.totp.headline":"2ファクター認証","ui.totp.setupQr":"2FA/TOTPアプリでQRコードを読み取ってください。","ui.totp.setupCode":"QRコードを読み取れない場合は、このキーを代わりに入力してください: ","ui.totp.codeLabel":"確認コード","ui.totp.codeDescription":"2FA/TOTPアプリが生成した確認コードを入力してください。","ui.totp.disableText":"2ファクター認証を無効にするには確認コードを入力してください。","ui.totp.invalid":"確認コードが無効です。","ui.totp.enable":"有効","ui.totp.disable":"無効","ui.totp.cancel":"取り止め","ui.totp.enabled":"2ファクター認証を有効にしました。","ui.totp.disabled":"2ファクター認証を無効にしました。","ui.totp.setup":"2ファクター認証を設定","ui.totp.skip":"2ファクター認証を飛ばす"}')}}]);"use strict";(self["webpackChunkcontao_manager"]=self["webpackChunkcontao_manager"]||[]).push([[186],{8582:function(t,e,s){s.r(e),s.d(e,{default:function(){return _t}});var o=s(641),i=s(33),r=s.p+"img/boot.92149bf5.svg";const a={class:"view-boot__header"},n={class:"view-boot__headline"},c={class:"view-boot__description"},u={key:0,class:"view-boot__checks"},l={key:0,class:"view-boot__summary view-boot__summary--error"},h={class:"view-boot__issue"},d={class:"view-boot__issue"},p={key:1,class:"view-boot__summary"},b={key:2,class:"view-boot__summary"},v=["disabled"],m={key:1,class:"view-boot__loading"};function g(t,e,s,g,w,f){const k=(0,o.g2)("boot-php-web"),_=(0,o.g2)("boot-config"),$=(0,o.g2)("boot-php-cli"),S=(0,o.g2)("boot-self-update"),C=(0,o.g2)("boot-composer"),y=(0,o.g2)("boot-contao"),L=(0,o.g2)("loading-spinner"),A=(0,o.g2)("boxed-layout");return(0,o.uX)(),(0,o.Wv)(A,{wide:!0,slotClass:"view-boot"},{default:(0,o.k6)(()=>[(0,o.Lk)("header",a,[e[9]||(e[9]=(0,o.Lk)("img",{src:r,width:"80",height:"80",alt:"",class:"view-boot__icon"},null,-1)),(0,o.Lk)("h1",n,(0,i.v_)(t.$t("ui.boot.headline")),1),(0,o.Lk)("p",c,(0,i.v_)(t.$t("ui.boot.description")),1)]),t.tasksInitialized?((0,o.uX)(),(0,o.CE)("main",u,[(0,o.Lk)("div",null,[(0,o.bF)(k,{ready:f.canShow("PhpWeb"),onResult:e[0]||(e[0]=(...t)=>f.result("PhpWeb",...t))},null,8,["ready"]),(0,o.bF)(_,{ready:f.canShow("Config"),onResult:e[1]||(e[1]=(...t)=>f.result("Config",...t))},null,8,["ready"]),(0,o.bF)($,{ready:f.canShow("PhpCli"),onResult:e[2]||(e[2]=(...t)=>f.result("PhpCli",...t))},null,8,["ready"]),t.isGranted(f.scopes.UPDATE)?((0,o.uX)(),(0,o.Wv)(S,{key:0,ready:f.canShow("SelfUpdate"),onResult:e[3]||(e[3]=(...t)=>f.result("SelfUpdate",...t))},null,8,["ready"])):(0,o.Q3)("",!0),f.isOAuth?(0,o.Q3)("",!0):((0,o.uX)(),(0,o.Wv)(C,{key:1,ready:f.canShow("Composer"),onResult:e[4]||(e[4]=(...t)=>f.result("Composer",...t))},null,8,["ready"])),f.isOAuth?(0,o.Q3)("",!0):((0,o.uX)(),(0,o.Wv)(y,{key:2,ready:f.canShow("Contao"),onResult:e[5]||(e[5]=(...t)=>f.result("Contao",...t))},null,8,["ready"]))]),e[11]||(e[11]=(0,o.Lk)("div",{class:"clearfix"},null,-1)),f.hasError?((0,o.uX)(),(0,o.CE)("div",l,[e[10]||(e[10]=(0,o.Lk)("svg",{height:"24",viewBox:"0 0 24 24",width:"24",xmlns:"http://www.w3.org/2000/svg"},[(0,o.Lk)("path",{d:"M0 0h24v24H0z",fill:"none"}),(0,o.Lk)("path",{d:"M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm1 15h-2v-2h2v2zm0-4h-2V7h2v6z"})],-1)),(0,o.Lk)("h1",h,(0,i.v_)(t.$t("ui.boot.issue1")),1),(0,o.Lk)("p",d,(0,i.v_)(t.$t("ui.boot.issue2")),1),t.safeMode?((0,o.uX)(),(0,o.CE)("button",{key:0,onClick:e[6]||(e[6]=(...t)=>f.runSafeMode&&f.runSafeMode(...t)),class:"widget-button widget-button--warning view-boot__safeMode"},(0,i.v_)(t.$t("ui.boot.safeMode")),1)):(0,o.Q3)("",!0)])):t.safeMode?((0,o.uX)(),(0,o.CE)("div",p,[(0,o.Lk)("button",{onClick:e[7]||(e[7]=(...t)=>f.runSafeMode&&f.runSafeMode(...t)),class:"widget-button widget-button--warning view-boot__safeMode"},(0,i.v_)(t.$t("ui.boot.safeMode")),1)])):f.autoContinue?(0,o.Q3)("",!0):((0,o.uX)(),(0,o.CE)("div",b,[(0,o.Lk)("button",{onClick:e[8]||(e[8]=(...t)=>f.finish&&f.finish(...t)),class:"widget-button widget-button--primary view-boot__continue",disabled:!f.canContinue},(0,i.v_)(t.$t("ui.boot.run")),9,v)]))])):((0,o.uX)(),(0,o.CE)("main",m,[(0,o.bF)(L)]))]),_:1})}var w=s(6278),f=s(70),k=s(707),_=s(3723),$=s(728),S=s(9045);const C=["href"];function y(t,e,s,r,a,n){const c=(0,o.g2)("boot-check");return(0,o.uX)(),(0,o.Wv)(c,{progress:t.bootState,title:t.$t("ui.server.php_web.title"),description:t.bootDescription,detail:t.problem&&t.problem.detail},{default:(0,o.k6)(()=>[t.problem&&t.problem.type?((0,o.uX)(),(0,o.CE)("a",{key:0,href:t.problem.type,target:"_blank"},(0,i.v_)(t.$t("ui.server.details")),9,C)):(0,o.Q3)("",!0)]),_:1},8,["progress","title","description","detail"])}var L={props:{ready:!1,current:!1},data:()=>({booted:!1,bootState:"loading",bootDescription:""}),watch:{ready(t){t&&(this.booted=!0,this.boot())}},created(){this.bootDescription=this.$t("ui.server.pending"),this.ready&&(this.booted=!0,this.boot())}};const A={class:"boot-check"},D={key:1,class:"boot-check__icon boot-check__icon--success"},x={key:2,class:"boot-check__icon boot-check__icon--info"},E={key:3,class:"boot-check__icon boot-check__icon--warning"},X={key:4,class:"boot-check__icon boot-check__icon--error"},U={class:"boot-check__label"},O={class:"boot-check__title"},M={class:"boot-check__description"},P={key:0,class:"boot-check__detail"},j={class:"boot-check__action"};function z(t,e,s,r,a,n){const c=(0,o.g2)("loading-spinner");return(0,o.uX)(),(0,o.CE)("div",A,["loading"===s.progress?((0,o.uX)(),(0,o.Wv)(c,{key:0,class:"boot-check__icon"})):"success"===s.progress?((0,o.uX)(),(0,o.CE)("div",D,[...e[0]||(e[0]=[(0,o.Lk)("svg",{height:"24",viewBox:"0 0 24 24",width:"24",xmlns:"http://www.w3.org/2000/svg"},[(0,o.Lk)("circle",{cx:"12",cy:"12",r:"8",fill:"#fff"}),(0,o.Lk)("path",{d:"M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-2 15l-5-5 1.41-1.41L10 14.17l7.59-7.59L19 8l-9 9z"})],-1)])])):"info"===s.progress||"action"===s.progress?((0,o.uX)(),(0,o.CE)("div",x,[...e[1]||(e[1]=[(0,o.Lk)("svg",{height:"24",viewBox:"0 0 24 24",width:"24",xmlns:"http://www.w3.org/2000/svg"},[(0,o.Lk)("circle",{cx:"12",cy:"12",r:"8",fill:"#fff"}),(0,o.Lk)("path",{d:"M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm1 15h-2v-6h2v6zm0-8h-2V7h2v2z"})],-1)])])):"warning"===s.progress?((0,o.uX)(),(0,o.CE)("div",E,[...e[2]||(e[2]=[(0,o.Lk)("svg",{xmlns:"http://www.w3.org/2000/svg",width:"24",height:"24",viewBox:"0 0 24 24"},[(0,o.Lk)("path",{d:"M5 19h15L12 5",fill:"#fff"}),(0,o.Lk)("path",{d:"M1 21h22L12 2 1 21zm12-3h-2v-2h2v2zm0-4h-2v-4h2v4z"})],-1)])])):((0,o.uX)(),(0,o.CE)("div",X,[...e[3]||(e[3]=[(0,o.Lk)("svg",{height:"24",viewBox:"0 0 24 24",width:"24",xmlns:"http://www.w3.org/2000/svg"},[(0,o.Lk)("circle",{cx:"12",cy:"12",r:"8",fill:"#fff"}),(0,o.Lk)("path",{d:"M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm1 15h-2v-2h2v2zm0-4h-2V7h2v6z"})],-1)])])),(0,o.Lk)("div",U,[(0,o.Lk)("h2",O,(0,i.v_)(s.title),1),(0,o.RG)(t.$slots,"description",{},()=>[(0,o.Lk)("p",M,(0,i.v_)(s.description),1)]),s.detail?((0,o.uX)(),(0,o.CE)("p",P,(0,i.v_)(s.detail),1)):(0,o.Q3)("",!0)]),(0,o.Lk)("div",j,[(0,o.RG)(t.$slots,"default")])])}var B={components:{LoadingSpinner:S.A},props:{title:String,description:String,detail:String,progress:{type:String,required:!0,validator:t=>-1!==["ready","loading","success","info","warning","error","action"].indexOf(t)}}},G=s(6262);const I=(0,G.A)(B,[["render",z]]);var W=I,Q={mixins:[L],components:{BootCheck:W},data:()=>({problem:{}}),methods:{async boot(){this.bootDescription=this.$t("ui.server.running");const t=await this.$store.dispatch("server/php-web/get");200===t.status?t.data.problem?(this.problem=t.data.problem,this.bootState="error",this.bootDescription=t.data.problem.title):t.data.version_id<7e4?(this.bootState="info",this.bootDescription=this.$t("ui.server.php_web.below7",t.data)):(this.bootState="success",this.bootDescription=this.$t("ui.server.php_web.success",t.data)):(this.bootState="error",this.bootDescription=this.$t("ui.server.error")),this.$emit("result",this.bootState)}}};const R=(0,G.A)(Q,[["render",y]]);var T=R;const V={class:"boot-check__description"},N=["disabled"],F=["disabled"];function H(t,e,s,r,a,n){const c=(0,o.g2)("boot-check");return(0,o.uX)(),(0,o.Wv)(c,{progress:t.bootState,title:t.$t("ui.server.config.title"),description:t.bootDescription},(0,o.eX)({default:(0,o.k6)(()=>["error"===t.bootState||"action"===t.bootState?((0,o.uX)(),(0,o.CE)("button",{key:0,class:"widget-button widget-button--alert",disabled:!t.isGranted(n.scopes.INSTALL),onClick:e[0]||(e[0]=(...t)=>n.showConfiguration&&n.showConfiguration(...t))},(0,i.v_)(t.$t("ui.server.config.setup")),9,N)):"loading"!==t.bootState?((0,o.uX)(),(0,o.CE)("button",{key:1,class:"widget-button widget-button--edit",disabled:!t.isGranted(n.scopes.INSTALL),onClick:e[1]||(e[1]=(...t)=>n.showConfiguration&&n.showConfiguration(...t))},(0,i.v_)(t.$t("ui.server.config.change")),9,F)):(0,o.Q3)("",!0)]),_:2},["success"===t.bootState?{name:"description",fn:(0,o.k6)(()=>[(0,o.Lk)("ul",V,[(0,o.Lk)("li",null,(0,i.v_)(t.bootDescription),1),(0,o.Lk)("li",null,(0,i.v_)(t.$t("ui.server.config.cloud"+(t.cloud?"Enabled":"Disabled"))),1)])]),key:"0"}:void 0]),1032,["progress","title","description"])}var q={mixins:[L],components:{BootCheck:W},computed:{...(0,w.L8)("auth",["isGranted"]),scopes:()=>f.A},methods:{async boot(){this.bootDescription=this.$t("ui.server.running"),this.$store.dispatch("server/config/get").then(t=>{this.php_cli=t.php_cli,this.cloud=t.cloud.enabled,this.cloudIssues=t.cloud.issues,t.php_cli?t.cloud.enabled&&t.cloud.issues.length>0?(this.bootState="error",this.bootDescription=this.$t("ui.server.config.stateErrorCloud")):(this.bootState="success",this.bootDescription=this.$t("ui.server.config.stateSuccess",{php_cli:t.php_cli})):(this.bootState="error",this.bootDescription=this.$t("ui.server.config.stateErrorCli"))}).catch(()=>{this.bootState="error",this.bootDescription=this.$t("ui.server.error")}).then(()=>{this.$emit("result",this.bootState)})},showConfiguration(){this.$store.commit("setView",k.A.CONFIG)}}};const Y=(0,G.A)(q,[["render",H]]);var J=Y;const K=["href"];function Z(t,e,s,r,a,n){const c=(0,o.g2)("boot-check");return(0,o.uX)(),(0,o.Wv)(c,{progress:t.bootState,title:t.$t("ui.server.php_cli.title"),description:t.bootDescription,detail:t.problem&&t.problem.detail},{default:(0,o.k6)(()=>[t.problem&&t.problem.type?((0,o.uX)(),(0,o.CE)("a",{key:0,href:t.problem.type,target:"_blank"},(0,i.v_)(t.$t("ui.server.details")),9,K)):(0,o.Q3)("",!0)]),_:1},8,["progress","title","description","detail"])}var tt={mixins:[L],components:{BootCheck:W},data:()=>({problem:{}}),methods:{boot(){this.bootDescription=this.$t("ui.server.running"),this.$store.dispatch("server/php-cli/get").then(t=>{t.problem?(this.problem=t.problem,this.bootState="error",this.bootDescription=t.problem.title):(this.bootState="success",this.bootDescription=this.$t("ui.server.php_cli.success",{version:t.version}))}).catch(t=>{503===t.status?(this.bootState="error",this.bootDescription=this.$t("ui.server.prerequisite")):(this.bootState="error",this.bootDescription=this.$t("ui.server.error"))}).then(()=>{this.$emit("result",this.bootState)})}}};const et=(0,G.A)(tt,[["render",Z]]);var st=et;const ot={class:"boot-check__description"};function it(t,e,s,r,a,n){const c=(0,o.g2)("i18n-t"),u=(0,o.g2)("boot-check");return(0,o.uX)(),(0,o.Wv)(u,{progress:t.bootState,title:t.$t("ui.server.selfUpdate.title"),description:t.bootDescription},(0,o.eX)({default:(0,o.k6)(()=>[t.isSupported||"action"!==t.bootState?t.hasUpdate?((0,o.uX)(),(0,o.CE)("button",{key:1,class:"widget-button widget-button--alert",onClick:e[1]||(e[1]=(...t)=>n.update&&n.update(...t))},(0,i.v_)(t.$t("ui.server.selfUpdate.button")),1)):(0,o.Q3)("",!0):((0,o.uX)(),(0,o.CE)("button",{key:0,class:"widget-button widget-button--warning",onClick:e[0]||(e[0]=(...t)=>n.next&&n.next(...t))},(0,i.v_)(t.$t("ui.server.selfUpdate.continue")),1))]),_:2},[t.latestDownload?{name:"description",fn:(0,o.k6)(()=>[(0,o.Lk)("p",ot,[(0,o.bF)(c,{keypath:"ui.server.selfUpdate.manualUpdate"},{latest:(0,o.k6)(()=>[(0,o.eW)((0,i.v_)(t.latestDownload),1)]),download:(0,o.k6)(()=>[...e[2]||(e[2]=[(0,o.Lk)("a",{href:"https://to.contao.org/download?lang=${this.$i18n.locale}",target:"_blank",rel:"noreferrer noopener"},"https://to.contao.org/download",-1)])]),_:1})])]),key:"0"}:void 0]),1032,["progress","title","description"])}var rt={mixins:[L],components:{BootCheck:W},data:()=>({hasUpdate:!1,isSupported:!0,latestDownload:null}),methods:{async boot(){let t;this.bootDescription=this.$t("ui.server.running");try{t=await this.$store.dispatch("server/self-update/get")}catch(s){return void this.emitState("error",this.$t("ui.server.error"))}const e={current:t.current_version,latest:t.latest_version};if(null!==t.latest_version)if(t.error){if("dev"===t.channel)return void this.emitState("warning",t.error);try{const s=await this.$store.dispatch("server/self-update/latest");s===t.current_version?this.emitState("success",this.$t("ui.server.selfUpdate.latest",e)):(this.latestDownload=s,this.emitState("error",this.$t("ui.server.selfUpdate.manualUpdate",{latest:s,download:`<a href="https://to.contao.org/download?lang=${this.$i18n.locale}" target="_blank" rel="noreferrer noopener">https://to.contao.org/download</a>`})))}catch(s){this.emitState("warning",t.error)}}else if(t.current_version!==t.latest_version){if(!t.supported)return this.isSupported=!1,void this.emitState("action",this.$t("ui.server.selfUpdate.unsupported",e));if("dev"===t.channel)return this.hasUpdate=!0,void this.emitState("warning",this.$t("ui.server.selfUpdate.update",e));this.hasUpdate=!0,this.emitState("error",this.$t("ui.server.selfUpdate.update",e))}else this.emitState("success",this.$t("ui.server.selfUpdate.latest",e));else this.emitState("info",this.$t("ui.server.selfUpdate.dev"))},async update(){try{await this.$store.dispatch("tasks/execute",{name:"manager/self-update",ignoreErrors:!0})}catch(t){}setTimeout(()=>{window.location.reload(!0)},3e3)},next(){this.bootState="info",this.$emit("result",this.bootState)},emitState(t,e){this.bootState=t,this.bootDescription=e,this.$emit("result",t)}}};const at=(0,G.A)(rt,[["render",it]]);var nt=at;function ct(t,e,s,r,a,n){const c=(0,o.g2)("boot-check");return(0,o.uX)(),(0,o.Wv)(c,{progress:t.bootState,title:t.$t("ui.server.composer.title"),description:t.bootDescription},{default:(0,o.k6)(()=>["action"===t.bootState?((0,o.uX)(),(0,o.CE)("button",{key:0,onClick:e[0]||(e[0]=(...t)=>n.install&&n.install(...t)),class:"widget-button widget-button--primary widget-button--run"},(0,i.v_)(t.$t("ui.server.composer.button")),1)):(0,o.Q3)("",!0)]),_:1},8,["progress","title","description"])}var ut={mixins:[L],components:{BootCheck:W},computed:{...(0,w.aH)("tasks",{taskStatus:"status"}),...(0,w.L8)("auth",["isGranted"])},methods:{async boot(){this.bootState="loading",this.bootDescription=this.$t("ui.server.running");try{const t=await this.$store.dispatch("server/composer/get");t.json.found&&!t.json.valid?(this.bootState="error",this.bootDescription=t.json.error):t.json.found&&!t.vendor.found?(this.bootState="action",this.bootDescription=this.$t("ui.server.composer.install"),this.$store.commit("setSafeMode",!0)):(this.bootState="success",this.bootDescription=this.$t("ui.server.composer.success"))}catch(t){503===t.status?(this.bootState="error",this.bootDescription=this.$t("ui.server.prerequisite")):(this.bootState="error",this.bootDescription=this.$t("ui.server.error"))}this.$emit("result",this.bootState)},async install(){await this.$store.dispatch("tasks/execute",{name:"composer/install"}),"complete"===this.taskStatus&&await this.$store.dispatch("tasks/deleteCurrent")}}};const lt=(0,G.A)(ut,[["render",ct]]);var ht=lt;const dt=["disabled"],pt=["disabled"],bt=["disabled"];function vt(t,e,s,r,a,n){const c=(0,o.g2)("boot-check");return(0,o.uX)(),(0,o.Wv)(c,{progress:t.bootState,title:t.$t("ui.server.contao.title"),description:t.bootDescription},{default:(0,o.k6)(()=>["action"===t.bootState?((0,o.uX)(),(0,o.CE)("button",{key:0,class:"widget-button widget-button--primary widget-button--run",disabled:!t.isGranted(n.scopes.INSTALL),onClick:e[0]||(e[0]=(...t)=>n.setup&&n.setup(...t))},(0,i.v_)(t.$t("ui.server.contao."+(t.databaseProblem&&!t.databaseAccessProblem?"check":"setup"))),9,dt)):(0,o.Q3)("",!0),"warning"===t.bootState?((0,o.uX)(),(0,o.CE)("button",{key:1,class:"widget-button widget-button--alert",disabled:!t.isGranted(n.scopes.INSTALL),onClick:e[1]||(e[1]=(...t)=>n.setup&&n.setup(...t))},(0,i.v_)(t.$t("ui.server.contao."+(t.databaseProblem&&!t.databaseAccessProblem?"check":"setup"))),9,pt)):(0,o.Q3)("",!0),"success"===t.bootState&&t.databaseSupported?((0,o.uX)(),(0,o.CE)("button",{key:2,class:"widget-button",disabled:!t.isGranted(n.scopes.INSTALL),onClick:e[2]||(e[2]=(...t)=>n.setup&&n.setup(...t))},(0,i.v_)(t.$t("ui.server.contao.setup")),9,bt)):(0,o.Q3)("",!0)]),_:1},8,["progress","title","description"])}var mt={mixins:[L],components:{BootCheck:W},data:()=>({processing:!1}),computed:{...(0,w.aH)("server/database",{databaseSupported:"supported",databaseStatus:"status"}),...(0,w.aH)("server/adminUser",{userSupported:"supported",hasUser:"hasUser"}),...(0,w.L8)("auth",["isGranted"]),...(0,w.L8)("server/database",{databaseProblem:"hasError",databaseAccessProblem:"accessProblem"}),scopes:()=>f.A},methods:{async boot(){this.bootState="loading",this.bootDescription=this.$t("ui.server.running");const t=await this.$store.dispatch("server/contao/get",!1),e=t.data;let s=this.bootState,o=this.bootDescription;if(200===t.status?e.version?e.supported?(s="success",o=this.$t("ui.server.contao.found",{version:e.version,api:e.api.version})):(s="error",o=this.$t("ui.server.contao.old",e)):(s="action",o=this.$t("ui.server.contao.empty")):503===t.status?(s="error",o=this.$t("ui.server.prerequisite")):502===t.status?(window.localStorage.removeItem("contao_manager_booted"),this.$store.commit("setView",k.A.RECOVERY)):(s="error",o=this.$t("ui.server.error")),"success"===s&&this.isGranted(f.A.UPDATE)&&(await Promise.all([this.$store.dispatch("contao/install-tool/fetch",!1),this.$store.dispatch("server/database/get",!1)]),this.databaseSupported&&(this.databaseAccessProblem?(s="warning",o+=` ${this.$t("ui.server.contao.connectionError")}`):this.databaseProblem?(s="warning",o+=` ${this.$t("ui.server.contao.connectionProblem")}`):this.isGranted(f.A.INSTALL)&&(await this.$store.dispatch("server/adminUser/get",!1),this.userSupported&&!this.hasUser&&(s="warning",o+=` ${this.$t("ui.server.contao.missingUser")}`)))),"warning"===s)this.$store.commit("setSafeMode",!0);else if("action"===s){const t=await this.$store.dispatch("server/composer/get");t.json.found&&t.json.valid&&this.$store.commit("setSafeMode",!0)}this.bootState=s,this.bootDescription=o,this.$emit("result",this.bootState)},async setup(){this.$store.commit("setSafeMode",!1);const t=await this.$store.dispatch("server/composer/get");t.json.found?this.databaseAccessProblem?this.$store.commit("setup",3):this.databaseProblem?this.$store.commit("setView",k.A.MIGRATION):this.hasUser?this.$store.commit("setup",0):this.$store.commit("setup",null===this.hasUser?3:4):this.$store.commit("setup",0)}}};const gt=(0,G.A)(mt,[["render",vt]]);var wt=gt,ft={components:{BoxedLayout:$.A,LoadingSpinner:S.A,BootPhpWeb:T,BootConfig:J,BootPhpCli:st,BootSelfUpdate:nt,BootComposer:ht,BootContao:wt},data:()=>({status:{}}),computed:{...(0,w.aH)(["safeMode"]),...(0,w.aH)("tasks",{tasksInitialized:"initialized"}),...(0,w.L8)("auth",["isGranted"]),scopes:()=>f.A,isOAuth:t=>t.$route.name===_.A.oauth.name,hasError:t=>-1!==Object.values(t.status).indexOf("error"),autoContinue:t=>"1"===window.localStorage.getItem("contao_manager_booted")&&-1===Object.values(t.status).indexOf("error")&&-1===Object.values(t.status).indexOf("action")&&-1===Object.values(t.status).indexOf("warning"),canContinue:t=>-1===Object.values(t.status).indexOf(null)&&-1===Object.values(t.status).indexOf("error")&&-1===Object.values(t.status).indexOf("action"),shouldContinue:t=>-1===Object.values(t.status).indexOf(null)&&-1===Object.values(t.status).indexOf("error")&&-1===Object.values(t.status).indexOf("action")&&-1===Object.values(t.status).indexOf("warning")},methods:{runSafeMode(){this.$store.commit("setSafeMode",!0),this.$store.commit("setView",k.A.READY)},finish(){window.localStorage.setItem("contao_manager_booted","1"),this.$store.commit("setSafeMode",!1),this.$store.commit("setView",k.A.READY)},result(t,e){this.status[t]=e},canShow(t){const e=Object.keys(this.status);for(let s=0;s<e.length;s+=1){if(e[s]===t)return!0;if(null===this.status[e[s]]||"error"===this.status[e[s]]||"action"===this.status[e[s]])return!1}return!1}},watch:{shouldContinue(t){t&&this.autoContinue&&this.finish()}},async mounted(){await this.$store.dispatch("reset"),this.isGranted(f.A.UPDATE)?await this.$store.dispatch("tasks/init"):this.$store.commit("tasks/setInitialized",!0);const t={PhpWeb:null,Config:null,PhpCli:null};this.isGranted(f.A.UPDATE)&&(t.SelfUpdate=null),this.$route.name!==_.A.oauth.name&&(t.Composer=null,t.Contao=null),this.status=t}};const kt=(0,G.A)(ft,[["render",g]]);var _t=kt}}]);"use strict";(self["webpackChunkcontao_manager"]=self["webpackChunkcontao_manager"]||[]).push([[560],{1560:function(e){e.exports=JSON.parse('{"ui.app.httpsHeadline":"!! Nedrošs savienojums !!","ui.app.httpsDescription":"Bez HTTPS jūsu konfidenciālie dati tiks pārsūtīti nešifrēti.","ui.app.httpsLink":"Vairāk informācijas","ui.app.httpsHref":"https://https.cio.gov/everything/","ui.app.safeModeHeadline":"!! Ieslēgts drošais režīms !!","ui.app.safeModeDescription":"Dažas Contao Manager funkcijas nav pieejamas.","ui.app.safeModeExit":"Iziet no drošā režīma","ui.app.limitedHeadline":"Attālā autentifikācija","ui.app.limitedDescription":"Jums ir ierobežotas atļaujas, jo pieslēgšanās notiek bez paroles.","ui.app.limitedLogout":"Atkārtoti autentificēties","ui.app.totpHeadline":"Drošības paziņojums","ui.app.totpDescription":"Konfigurējiet divfaktoru autentifikāciju, lai aizsargātu savu kontu.","ui.app.totpSetup":"Uzstādīt","ui.app.loading":"Ielādē Contao pārvaldnieku ...","ui.app.apiError":"Negaidīts API statuss","ui.app.configSecurity1":"DROŠĪBAS BRĪDINĀJUMS !!! Konstatēts neaizsargāts konfigurācijas direktorijs","ui.app.configSecurity2":"The Contao Manager has detected that its config files are publicly accessible. All operations are disabled until the directory is secured, otherwise an attacker could access sensitive data of your installation.\\n\\nTo fix this issue, make sure to prevent access to the \\"contao-manager\\" directory on your server. To learn how to do this, please refer to the manual of your webserver or contact your hosting provider.","ui.account.welcome":"Laipni lūdzam","ui.account.intro1":"Laipni lūgti Contao pārvaldniekā, kas ir universāls rīks Contao atvērtā koda CMS instalēšanai un pārvaldībai. Ja esat jauns lietotājs, lūdzu, {readTheManualToGetStarted}.","ui.account.introGetStarted":"{readTheManual}, lai sāktu","ui.account.introManual":"izlasiet rokasgrāmatu","ui.account.intro2":"Ja jums rodas kādas problēmas, pārbaudiet {ourGithubIssues} un nekautrējieties izveidot jaunu problēmu, ja par to vēl nav ziņots.","ui.account.introIssues":"mūsu GitHub problēmas","ui.account.headline":"Lietotāja konts","ui.account.description":"Lai pārvaldītu savu instalāciju, lūdzu, izveidojiet Contao pārvaldnieka kontu. Ņemiet vērā, ka šis konts nav saistīts ar Contao aizmuguri vai priekšu.","ui.account.username":"Lietotājvārds","ui.account.password":"Parole","ui.account.passwordPlaceholder":"min. 8 rakstzīmes","ui.account.passwordLength":"Lūdzu, ievadiet vismaz 8 rakstzīmes.","ui.account.loginInvalid":"There was an error when creating the account. Please try a different username.","ui.account.submit":"Izveidot kontu","ui.account.usePassword":"Izmantot paroli, lai pieslēgtos","ui.account.usePasskey":"Pieslēdzoties izmantot Passkey","ui.account.totpHeadline":"Divu faktoru autentifikācija","ui.account.totpDescription":"Please enable two-factor authentication, which adds an extra layer of security to your account. In addition to your username and password, you will need to enter a verification code generated by a two-factor app such as 1Password, Authy, Google Authenticator, Microsoft Authenticator, LastPass Authenticator or any other TOTP app.","ui.account.totpSetup":"Konfigurēt tagad","ui.account.totpSkip":"Konfigurēt vēlāk","ui.account.login":"Noraidīt ielūgumu","ui.account.contribute1":"Contao un Contao Manager sponsorē bezpeļņas organizācija Contao Association.","ui.account.contribute2":"Lūdzu, apsveriet iespēju sniegt ieguldījumu atvērtajā pirmkodā {donate}.","ui.account.contributeDonate":"ziedojuma veikšana","ui.login.headline":"Pierakstīties","ui.login.description":"Pierakstīties, lai pārvaldītu savu instalāciju.","ui.login.username":"Lietotājvārds","ui.login.password":"Parole","ui.login.totpHeadline":"Divu faktoru autentifikācija","ui.login.totpDescription":"Lūdzu, ievadiet verifikācijas kodu, lai pabeigtu pieslēgšanās procesu.","ui.login.totp":"Verifikācijas kods","ui.login.forgotPassword":"Aizmirsāt paroli?","ui.login.button":"Pierakstīties","ui.login.passkey":"Pieslēgties ar Passkey","ui.login.cancel":"Atcelt","ui.login.or":"vai","ui.login.locked":"Piekļuve ir liegta, jo Contao Manager ir bloķēts. Lai atbloķētu, izdzēsiet {lockFile} datni Contao galvenajā direktorijā.","ui.logout.headline":"Sesijas laika limits","ui.logout.warning":"Jūs esat bijis neaktīvs ilgāk par 25 minūtēm. Drošības apsvērumu dēļ jūsu sesija drīz tiks pārtraukta.","ui.logout.expired":"Jūsu sesija tika automātiski pārtraukta, jo esat bijis neaktīvs ilgāk par 30 minūtēm.","ui.logout.renew":"Palikt pieteikušamies","ui.logout.logout":"Izrakstīties","ui.logout.login":"Atpakaļ uz pieteikšanos","ui.oauth.error":"Nederīgs OAuth mēģinājums. Pārbaudiet pieprasījuma parametrus.","ui.oauth.https":"The redirect URI MUST use a secure protocol (https:) to prevent the authentication token from being transmitted in clear-text.","ui.oauth.headline":"Attālā autentifikācija","ui.oauth.description":"Šāda lietojumprogramma vai pakalpojums pieprasa attālo piekļuvi jūsu Contao Manager instancei.","ui.oauth.domain":"Pirms atļaujat piekļuvi, pārliecinieties, ka zināt šo URL un uzticaties tā īpašniekam!","ui.oauth.outOfScope":"Unfortunately, you do not have the necessary permissions to grant this access.","ui.oauth.allow":"Atļaut piekļuvi","ui.oauth.deny":"Liegt piekļuvi","ui.oauth.switchUser":"Pārslēgt lietotāju","ui.scope.admin":"Admin access including user management","ui.scope.install":"Install new packages and change Contao configuration","ui.scope.update":"Update packages and execute maintenance tasks","ui.scope.read":"Read packages and configuration","ui.boot.headline":"Sistēmas pārbaude","ui.boot.description":"Lūdzu, uzgaidiet, mēs analizējam jūsu serveri ...","ui.boot.issue1":"Konstatētās  instalēšanas problēmas","ui.boot.issue2":"Jūsu instalācijā ir problēmas, kas jānovērš, pirms var izmantot Contao Manager.","ui.boot.run":"Palaist Contao pārvaldnieku","ui.boot.safeMode":"Palaist drošajā režīmā","ui.recovery.headline":"Sistēmas atkopšana","ui.recovery.description":"Contao Manager atklāja datnes, kas izskatās kā Contao, bet komandrindas saskarne nedarbojas, kā paredzēts.","ui.recovery.console":"Konsoles izvade","ui.recovery.repairOptions":"Lūdzu, izvēlieties iespēju, lai salabotu instalāciju.","ui.recovery.repairHeadline":"Automātiskā izlabošana","ui.recovery.repairDescription":"Mēģina automātiski labot instalāciju, atjaunojot lietojumprogrammu kešatmiņu un atkārtoti instalējot Composer paketes.","ui.recovery.repairWarning":"Procesa laikā var tikt dzēstas visas piegādātāja datņu izmaiņas!","ui.recovery.repairFailed":"Automātiskā labošana nebija veiksmīga. Izmēģiniet instalāciju labot manuāli drošajā režīmā.","ui.recovery.repairButton":"Palaist sistēmas izlabošanu","ui.recovery.safeModeHeadline":"Drošais režīms","ui.recovery.safeModeDescription":"Programmas Contao Manager palaišana drošajā režīmā ļauj pārvaldīt paketes un veikt dažus uzturēšanas uzdevumus, taču funkcijas, kas ir atkarīgas no darbojošās Contao instalācijas, nebūs pieejamas.","ui.recovery.safeModeButton":"Palaist drošajā režīmā","ui.server.pending":"Gaida ...","ui.server.running":"Analizē ...","ui.server.error":"Pārbaude neizdevās, jo no servera saņemta neparedzēta atbilde.","ui.server.details":"Sīkāka informācija","ui.server.prerequisite":"Pārbaude atcelta trūkstošā priekšnosacījuma dēļ.","ui.server.selfUpdate.title":"Contao pārvaldnieka atjauninājumi","ui.server.selfUpdate.update":"Ir pieejama jauna Contao pārvaldnieka versija {latest}.","ui.server.selfUpdate.manualUpdate":"Ir pieejama jauna Contao Manager versija {latest}. Jūsu serveris neatbalsta automātiskus atjauninājumus, lūdzu, lejupielādējiet jauno versiju no {download}.","ui.server.selfUpdate.latest":"Jūs izmantojat jaunāko versiju {current}.","ui.server.selfUpdate.dev":"Izstrādes būves neatbalsta automātiskus atjauninājumus.","ui.server.selfUpdate.unsupported":"Ir pieejama jauna versija, taču tā neatbalsta jūsu PHP versiju.","ui.server.selfUpdate.button":"Palaist pašatjauninājumu","ui.server.selfUpdate.continue":"Turpināt","ui.server.config.title":"Servera konfigurācija","ui.server.config.setup":"Konfigurēt","ui.server.config.change":"Mainīt","ui.server.config.save":"Saglabāt","ui.server.config.cancel":"Atcelt","ui.server.config.customOption":"Cits ...","ui.server.config.description":"To correctly run background tasks, the Contao Manager needs to know where to find the PHP command line binary and how to run commands separated from the web process.","ui.server.config.formTitle":"Servera konfigurācija","ui.server.config.formText":"Please enter the path to your PHP binary. Make sure the binary is the same PHP version as your web process.","ui.server.config.cloudTitle":"Composer Resolver Cloud","ui.server.config.cloudText":"The Composer Resolver Cloud allows to install Composer dependencies even if your server does not provide enough local memory. Please be aware that your package information will be transmitted to a cloud server operated by the Contao Association.","ui.server.config.cloud":"Izmantot Composer Resolver Cloud","ui.server.config.cli":"PHP binārs","ui.server.config.stateErrorCli":"Serverī netika atrasts derīgs PHP binārs.","ui.server.config.stateErrorCloud":"Composer Resolver Cloud netiek atbalstīts.","ui.server.config.stateSuccess":"PHP binārais kodols {php_cli}.","ui.server.config.cloudEnabled":"Package dependencies will be resolved using the Composer Resolver Cloud.","ui.server.config.cloudDisabled":"The Composer Resolver Cloud is disabled.","ui.server.php_web.title":"PHP Web process","ui.server.php_web.below7":"Atrasta PHP versija {versija}. Lūdzu, pēc iespējas ātrāk pārejiet uz PHP 7!","ui.server.php_web.success":"Atrasta PHP versija {versija}, neviena zināma problēma nav atrasta.","ui.server.php_cli.title":"PHP komandrindas saskarne","ui.server.php_cli.success":"Atrasta PHP versija {versija}, neviena zināma problēma nav atrasta.","ui.server.composer.title":"Composer vide","ui.server.composer.success":"Netika atrastas zināmas problēmas.","ui.server.composer.install":"Composer dependencies are not installed.","ui.server.composer.button":"Uzstādīt","ui.server.contao.title":"Contao instalācija","ui.server.contao.setup":"Uzstādīt","ui.server.contao.check":"Pārbaudīt datubāzi","ui.server.contao.empty":"Neviena Contao instalācija nav atrasta.","ui.server.contao.old":"Contao versija {versija} nav savietojama ar Contao pārvaldnieku, lūdzu, manuāli atjauniniet instalāciju.","ui.server.contao.found":"Atrasts Contao {versija} (API versija {api}).","ui.server.contao.connectionError":"Nevar izveidot savienojumu ar datubāzes serveri.","ui.server.contao.connectionProblem":"Atrasta datubāzes problēma.","ui.server.contao.missingUser":"Administratora konts nav atrasts.","ui.setup.continue":"Turpināt","ui.setup.manager":"Palaist Contao pārvaldnieku","ui.setup.cancel":"Atcelt","ui.setup.welcome":"Laipni lūdzam","ui.setup.welcome1":"This wizard will take you through the necessary steps to set up your Contao Open Source CMS installation.","ui.setup.welcome2":"If you have any questions, please find documentation, forums, a Slack channel and more on the {support} page.","ui.setup.support":"kopienas atbalsts","ui.setup.start":"Sākt","ui.setup.complete":"Apsveicam!","ui.setup.complete1":"Contao {versija} ir veiksmīgi instalēta.","ui.setup.complete2":"To finish the setup process, please open the install tool to configure the database connection and create a back end user.","ui.setup.complete3":"You can now start to create your website in the Contao back end. If you need additional extensions, continue to the Contao Manager.","ui.setup.installTool":"Atveriet instalēšanas rīku","ui.setup.login":"Pieslēgties Contao","ui.setup.funding":"Free software is \\"free\\" as in \\"free speech\\", not as in \\"free beer\\". An Open Source project like Contao requires amounts of money that can\'t be raised by a single person or company.\\nIf you have a website or sell websites built with Contao, we would love to see you contribute back financially to the product your business relies upon.","ui.setup.fundingLink":"Uzzināt vairāk","ui.setup.document-root.headline":"Tīmekļa servera iestatīšana","ui.setup.document-root.warning":"Lai instalētu Contao, izmantojot Contao Manager, tīmekļa serverī ir jānosaka dokumenta sakne.","ui.setup.document-root.description1":"Contao uses a separate folder for public files, application files are installed in its parent folder. Contao cannot be installed if the folder structure is not correct or the folders are not empty.","ui.setup.document-root.description2":"Ja nezināt, kā konfigurēt dokumentu sakni, izlasiet Contao dokumentāciju vai sazinieties ar savu hostinga pakalpojumu sniedzēju.","ui.setup.document-root.documentation":"Izlasiet dokumentāciju","ui.setup.document-root.conflictsTitle":"Instalācijas direktorijs nav tukšs","ui.setup.document-root.conflictsDirectory":"The root directory of your future Contao installation is not empty, we have found {count} file(s) that might be overwritten by the installation process. It is recommended to create an empty directory structure for Contao, but you can also remove the following files and check again if you are sure they are unused.","ui.setup.document-root.ignoreConflicts":"I want to install Contao into the non-empty directory. I understand that this might overwrite any existing files on my webspace.","ui.setup.document-root.check":"Pārbaudiet vēlreiz","ui.setup.document-root.create":"Izveidot direktorijus","ui.setup.document-root.change":"Mainīt direktorijus","ui.setup.document-root.formTitle":"Direktoriju iestatīšana","ui.setup.document-root.formText1":"Contao Manager var automātiski izveidot jaunu direktoriju struktūru serverī.","ui.setup.document-root.formText2":"Jums būs manuāli jākonfigurē jaunā dokumenta sakne (piemēram, izmantojot hostinga administratora paneli).","ui.setup.document-root.autoconfig":"Es saprotu, ka man ir jāmaina servera konfigurācija. Dokumenta saknes nekonfigurēšana sabojās Contao Manager un atklās konfigurācijas failus (tostarp konta informāciju un paroles)!","ui.setup.document-root.directory":"Jauns direktorijs","ui.setup.document-root.currentRoot":"Pašreizējā dokumenta sakne","ui.setup.document-root.newRoot":"Jauna dokumenta sakne","ui.setup.document-root.finish":"Direktoriju iestatīšana","ui.setup.document-root.publicDir":"Izmantojiet {dir} publiskajām datnēm (Contao {version})","ui.setup.document-root.directoryInvalid":"Lūdzu, ievadiet derīgu direktorija nosaukumu.","ui.setup.document-root.directoryExists":"Mērķa direktorijs jau pastāv. Lūdzu, ievadiet citu nosaukumu.","ui.setup.document-root.confirmation":"Contao pārvaldnieks ir veiksmīgi izveidojis nepieciešamo direktoriju jūsu Contao instalācijai. Tagad jums ir jākonfigurē dokumenta sakne tīmekļa serverī. Līdz tam nepārlādējiet šo lapu no jauna.","ui.setup.document-root.reload":"Pārlādēt lapu","ui.setup.document-root.success":"The directory structure on your web server is set up correctly!","ui.setup.document-root.installingProjectDir":"Lietojumprogrammas datnes tiks instalētas {dir}.","ui.setup.document-root.installingPublicDir":"Publiskās datnes tiks instalētas {dir}.","ui.setup.document-root.installedProjectDir":"Lietojumprogrammas datnes ir instalētas {dir}.","ui.setup.document-root.installedPublicDir":"Publiskās datnes ir instalētas {dir}.","ui.setup.create-project.headline":"Contao instalācija","ui.setup.create-project.description":"Contao development follows the principle of {semver}, a new minor version is released every six months. The currently supported releases are:","ui.setup.create-project.semver":"Semantic Versioning","ui.setup.create-project.latestTitle":"Jaunākais","ui.setup.create-project.ltsTitle":"Ilgtermiņa atbalsts","ui.setup.create-project.latestQ1":"Our latest version, offers the most features with support until February {year}.","ui.setup.create-project.latestQ3":"Our latest version, offers the most features with support until August {year}.","ui.setup.create-project.ltsText":"Our current LTS version, if you focus on stability. Offers long term support until February {year}.","ui.setup.create-project.pltsText":"The previous LTS version, still has long term support until February {year}.","ui.setup.create-project.requiresPHP":"Requires at least PHP {version}, you have PHP {current}.","ui.setup.create-project.releaseplan":"Sīkāku informāciju skatiet {contaoReleasePlan}.","ui.setup.create-project.releaseplanLink":"Contao izlaišanas plāns","ui.setup.create-project.installed":"Contao {version} is successfully installed on the server. Continue to set up your database or launch the Contao Manager to install a different version.","ui.setup.create-project.formTitle":"Izvēlēties distribūciju","ui.setup.create-project.formText":"Lūdzu, izvēlieties, kura versija jāuzstāda.","ui.setup.create-project.version":"Versija","ui.setup.create-project.demo":"Instalēt Contao demo vietni","ui.setup.create-project.demoDescription":"The demo website helps you to get familiar with Contao and all of its core features. More themes can be found in the {store}.","ui.setup.create-project.coreOnly":"Minimāla instalācija (tikai Core)","ui.setup.create-project.noUpdate":"Izlaist instalāciju (tikai eksperts!)","ui.setup.create-project.theme":"Contao tēma","ui.setup.create-project.themeInstall":"To install a Contao theme, use the search input or upload a theme file (.cto/.zip) that supports installation through the Contao Manager.","ui.setup.create-project.themeBuy":"Noteikti apmeklējiet oficiālo {store}.","ui.setup.create-project.themeStore":"Contao tēmu veikals","ui.setup.create-project.themeUpload":"Augšupielādēt tēmas datni (.cto/.zip)","ui.setup.create-project.themeInvalid":"The uploaded file is not a Contao theme or does not support the Contao Manager.","ui.setup.create-project.themeWarning":"The Contao Manager cannot tell whether this theme is compatible with your server. Please check with the theme vendor if you have any questions.","ui.setup.create-project.themeTitle":"Review theme details","ui.setup.create-project.themeDetails":"The following dependencies and files will be installed with this theme.","ui.setup.create-project.themeRequire":"{count} Dependencies | {count} Dependencies","ui.setup.create-project.themeFiles":"{count} File | {count} Files","ui.setup.create-project.theme.or":"or search public themes","ui.setup.create-project.theme.search":"Meklēt tēmas","ui.setup.create-project.theme.more":"Vairāk tēmas","ui.setup.create-project.theme.empty":"No themes matching {query}","ui.setup.create-project.theme.uploaded":"Tēmas datne tika veiksmīgi augšupielādēta.","ui.setup.create-project.theme.packageName":"Package name","ui.setup.create-project.theme.version":"Versija","ui.setup.create-project.theme.authors":"Autors(i)","ui.setup.create-project.theme.upload":"Uploading {name} ({size})","ui.setup.create-project.install":"Uzstādīt","ui.setup.create-project.cancel":"Atcelt","ui.setup.create-project.fileError":"Could not find composer.json in {file}.","ui.setup.create-project.jsonError":"composer.json contains invalid JSON.","ui.setup.create-project.schemaError":"composer.json schema validation failed.","ui.setup.database-connection.headline":"Datubāzes savienojums","ui.setup.database-connection.description":"Contao requires a MySQL database (or a compatible fork like MariaDB) to store pages, content, users and other relational data. Connection parameters are stored in the {env} file in the project root of your Contao installation.","ui.setup.database-connection.formTitle":"Savienojuma parametri","ui.setup.database-connection.formText":"Ievadiet datubāzes URL vai atsevišķi aizpildiet lietotājvārdu, paroli, serveri un datubāzes laukus.","ui.setup.database-connection.url":"Datubāzes URL","ui.setup.database-connection.validUrl":"Datubāzes URL ir nederīgs vai neizdevās izveidot savienojumu ar serveri.","ui.setup.database-connection.or":"vai","ui.setup.database-connection.user":"Lietotājvārds","ui.setup.database-connection.password":"Parole","ui.setup.database-connection.server":"Serveris (:ports)","ui.setup.database-connection.database":"Datubāzes nosaukums","ui.setup.database-connection.connected":"Successfully connected to database {database} on {server}.","ui.setup.database-connection.error":"Kļūda, savienojoties ar datubāzi.","ui.setup.database-connection.problem":"Contao ir atklājis problēmu ar jūsu datubāzes serveri.","ui.setup.database-connection.schemaTitle":"Database Schema","ui.setup.database-connection.migration":"There is one pending migration. | There are {count} pending migrations.","ui.setup.database-connection.schema":"There is one pending schema update. | There are {count} pending schema updates.","ui.setup.database-connection.noChanges":"Jūsu datubāzes shēma ir aktuāla.","ui.setup.database-connection.check":"Pārbaudīt datubāzi","ui.setup.database-connection.skip":"Izlaist","ui.setup.database-connection.save":"Saglabāt","ui.setup.database-connection.change":"Mainīt akreditācijas datus","ui.setup.database-connection.restoreTitle":"Datubāzes imports","ui.setup.database-connection.restoreText":"The theme you just installed contains a database backup. Restore the database to import theme data or skip this step to start with a blank Contao installation. | The theme you just installed contains multiple database backups. Select a backup file to import theme data or skip this step to start with a blank Contao installation.","ui.setup.database-connection.backup":"Dublējiet pašreizējo datu bāzi pirms importēšanas","ui.setup.database-connection.backupWarning":"All data in database will be overwritten on import! Create a backup first if the database is not empty.","ui.setup.database-connection.restore":"Importēt tēmas datubāzi","ui.setup.database-connection.restoreOption":"Backup from {date} ({size})","ui.setup.database-connection.restored":"Your theme database was successfully imported. Continue to validate your database schema.","ui.setup.backend-user.success":"An admin account for the Contao back end was found in your database. Use the Contao back end to add more users.","ui.setup.backend-user.error":"Unable to retrieve user list. Check the console output for details.","ui.setup.backend-user.headline":"Aizmugures konts","ui.setup.backend-user.description":"To manage your website, you need to have at least one admin account for the Contao back end. Be aware that this account is not related to the Contao Manager.","ui.setup.backend-user.formTitle":"Izveidot kontu","ui.setup.backend-user.formText":"Please enter the details for the new back end account.","ui.setup.backend-user.username":"Lietotājvārds","ui.setup.backend-user.name":"Vārds","ui.setup.backend-user.email":"E-pasta adrese","ui.setup.backend-user.emailInvalid":"Lūdzu, ievadiet derīgu e-pasta adresi","ui.setup.backend-user.password":"Parole","ui.setup.backend-user.passwordPlaceholder":"min. 8 rakstzīmes","ui.setup.backend-user.passwordLength":"Lūdzu, ievadiet vismaz 8 rakstzīmes.","ui.setup.backend-user.create":"Pievienot kontu","ui.task.headline":"Fona uzdevums","ui.task.loading":"Ielādē informāciju ...","ui.task.created":"Ielādē informāciju ...","ui.task.active":"Lūdzu, pagaidiet, kamēr Contao Manager fona režīmā tiek veiktas uzdevumu operācijas.","ui.task.complete":"Visas operācijas ir veiksmīgi pabeigtas. Sīkāku informāciju skatiet konsoles izvades failā.","ui.task.paused":"Fona operācija negaidīti apstājās. Lūdzu, pārbaudiet konsoles izvadi.","ui.task.aborting":"Lūdzu, uzgaidiet, kamēr tiek atceltas fona operācijas.","ui.task.stopped":"Dažas fona darbības tika atceltas. Lūdzu, pārbaudiet konsoles izvadi.","ui.task.error":"Fona operācija negaidīti apstājās. Lūdzu, pārbaudiet konsoles izvadi.","ui.task.failed":"Contao pārvaldniekam neizdevās palaist fona uzdevumu!","ui.task.failedDescription1":"Mēģinot izpildīt operācijas fonā, kaut kas notika nepareizi.","ui.task.failedDescription2":"Ja tas atkārtojas, iespējams, ka jūsu serveris netiek atbalstīts.","ui.task.reportProblem":"Ziņot par problēmu","ui.task.pausedDescription":"Click \\"Continue\\" if you want to ignore the error and execute the remaining operations.","ui.task.sponsor":"Composer Cloud sponsored by {sponsor}","ui.task.buttonAudit":"Atjaunināt datubāzi","ui.task.buttonClose":"Aizvērt","ui.task.buttonConfirm":"Apstiprināt & aizvērt","ui.task.buttonContinue":"Turpināt","ui.task.buttonCancel":"Atcelt","ui.task.confirmCancel":"Vai noteikti vēlaties atcelt šo uzdevumu? Tas var atstāt jūsu Contao instalāciju bojātā stāvoklī!","ui.task.autoclose":"Aizvērt uzdevuma informāciju pēc izdošanās","ui.console.toggle":"Rādīt/slēpt konsoles izvadi","ui.console.showLog":"Rādīt pilnu konsoles žurnālu","ui.console.copyLog":"Kopēt žurnālu uz starpliktuvi","ui.migrate.headline":"Datubāzes atjauninājumi","ui.migrate.migrationsOnly":"(migrations only)","ui.migrate.schemaOnly":"(schema only)","ui.migrate.loading":"Lūdzu, uzgaidiet, mēs pārbaudām jūsu datubāzi...","ui.migrate.empty":"No pending migrations or schema updates found. Your database is up to date.","ui.migrate.emptyMigrations":"No pending migrations found. Make sure to also check for schema updates.","ui.migrate.emptySchema":"No pending schema updates found. Make sure to also check for migrations.","ui.migrate.pending":"Your database is not up to date. Please review the console output below and execute the changes.","ui.migrate.previousChanges":"A previous database migration was not confirmed.\\nPlease review the console output below, then continue to see the next changes.","ui.migrate.previousComplete":"A previous database migration was not confirmed, please review the console output below.\\nThere are no more pending changes.","ui.migrate.appliedChanges":"Database updates have been applied.\\nPlease review the console output below, then continue to see the next changes.","ui.migrate.appliedComplete":"Database updates have been applied.\\nThere are no more pending migrations or schema updates. Your database is up to date.","ui.migrate.problem":"Contao has detected a problem with your database server.\\nPlease review the console output below to find out what needs to be fixed. | Contao has detected problems with your database server.\\nPlease review the console output below to find out what needs to be fixed.","ui.migrate.warning":"Contao has detected a misconfiguration of your database server.\\nWarnings can be skipped temporarily, but should be fixed for optimal performance and data integrity.","ui.migrate.error":"The changes could not be applied. Your database might have been changed, please check again to retry.","ui.migrate.execute":"Izpildīt","ui.migrate.close":"Aizvērt","ui.migrate.confirm":"Apstiprināt & aizvērt","ui.migrate.cancel":"Atcelt","ui.migrate.continue":"Turpināt","ui.migrate.setup":"Uzstādīt","ui.migrate.skip":"Izlaist","ui.migrate.retry":"Pārbaudiet vēlreiz","ui.migrate.retryAll":"Atzīmēt visus","ui.migrate.withDeletes":"Izpildīt visas datubāzes izmaiņas, tostarp DROP vaicājumus.","ui.migrate.migrationTitle":"Datubāzu migrācija","ui.migrate.schemaTitle":"Shēmas atjauninājumi","ui.migrate.problemTitle":"Datubāzes problēmas","ui.migrate.warningTitle":"Datubāzes brīdinājumi","ui.migrate.addTable":"Pievienot tabulu {table}","ui.migrate.dropTable":"Nomest tabulu {table}","ui.migrate.addField":"Pievienot lauku {table}.{field}","ui.migrate.changeField":"Mainīt lauku {table}.{field}","ui.migrate.dropField":"Nomest lauku {table}.{field}","ui.migrate.createIndex":"Izveidot indeksu \\"{name}\\" uz {table}","ui.migrate.dropIndex":"Nomest indeksu \\"{name}\\" uz {table}","ui.widget.mandatory":"Šis lauks nedrīkst būt tukšs.","ui.widget.blankOption":"Lūdzu, izvēlieties ...","ui.widget.showPassword":"Rādīt paroli","ui.widget.hidePassword":"Slēpt paroli","ui.error.title":"HTTP pieprasījums \\"{metod} {url}\\" neizdevās.","ui.error.server500":"Looks like an unexpected error happened on your server. Please check the log files of your web server (Apache/Nginx) and the Contao Manager logs at \\"contao-manager/logs\\".","ui.error.response":"Serveris atbildēja ar statusa kodu {status}.","ui.error.moreLink":"Vairāk informācijas","ui.error.support":"Contao atbalsts","ui.error.permission":"You do not have permission to use this feature.","ui.footer.help":"Palīdzība","ui.footer.reportProblem":"Ziņot par problēmu","ui.navigation.discover":"Atklāt","ui.navigation.packages":"Pakotnes","ui.navigation.tools":"Rīki","ui.navigation.installTool":"Instalēšanas rīks","ui.navigation.backend":"Contao aizmugure","ui.navigation.debug":"Contao atkļūdošanas režīms","ui.navigation.logViewer":"Žurnāla skatītājs","ui.navigation.phpinfo":"PHP informācija","ui.navigation.phpinfoLoading":"PHP informācijas ielāde...","ui.navigation.maintenance":"Uzturēšana","ui.navigation.rebuildCache":"Pārbūvēt kešatmiņu","ui.navigation.users":"Konti","ui.navigation.systemCheck":"Sistēmas pārbaude","ui.navigation.advanced":"Papildu","ui.navigation.logout":"Izrakstīties","ui.maintenance.database.title":"Datubāžu migrācija un dublējumi","ui.maintenance.database.description":"Database migrations ensure consistent data and table schemas.","ui.maintenance.database.migrations":"One pending database migration | {count} pending database migrations","ui.maintenance.database.schemaUpdates":"One pending schema update | {count} pending schema updates","ui.maintenance.database.error":"Atrasta datubāzes problēma.","ui.maintenance.database.warning":"Atrasti datubāzes brīdinājumi.","ui.maintenance.database.button":"Pārbaudīt datubāzi","ui.maintenance.database.migrationOnly":"Pārbaudīt tikai migrācijas","ui.maintenance.database.schemaOnly":"Pārbaudīt tikai shēmu","ui.maintenance.database.installTool":"Atvērt instalēšanas rīku","ui.maintenance.database.createBackup":"Izveidot dublējumu","ui.maintenance.database.backupUnsupported":"Database backups are not supported by your Contao version.","ui.maintenance.database.backupList":"You have one database backup, created on {date}. | You have {count} database backups, the latest one was created on {date}.","ui.maintenance.database.backupEmpty":"You currently have no database backups.","ui.maintenance.rebuildCache.title":"Lietojumprogrammas kešatmiņa","ui.maintenance.rebuildCache.description":"Rebuilding the application cache is required after modifying any of the configuration files.","ui.maintenance.rebuildCache.rebuildProd":"Ražošanas kešatmiņas pārbūve","ui.maintenance.rebuildCache.rebuildDev":"Izstrādes kešatmiņas pārbūve","ui.maintenance.rebuildCache.clearProd":"Notīrīt ražošanas kešatmiņu","ui.maintenance.rebuildCache.clearDev":"Notīrīt izstrādes kešatmiņu","ui.maintenance.installTool.title":"Contao instalēšanas rīks","ui.maintenance.installTool.description":"Contao instalēšanas rīks tiek automātiski bloķēts, ja trīs reizes pēc kārtas ievadāt nepareizu paroli.","ui.maintenance.installTool.unlock":"Atbloķēt instalēšanas rīku","ui.maintenance.installTool.lock":"Bloķēt instalēšanas rīku","ui.maintenance.dumpAutoload.title":"Composer Class Loader","ui.maintenance.dumpAutoload.description":"The Composer autoloader is responsible for PHP class loading. The autoloader must be dumped after adding custom namespaces to the root composer.json.","ui.maintenance.dumpAutoload.button":"Dump Autoloader","ui.maintenance.composerInstall.title":"Composer Dependencies","ui.maintenance.composerInstall.description":"Composer dependencies are located in the {vendor} folder in your application root. Reinstalling the dependencies can be necessary after manipulation or manually uploading the {composerLock} file.","ui.maintenance.composerInstall.button":"Palaist instalētāju","ui.maintenance.composerInstall.update":"Palaist Composer jauninājumu","ui.maintenance.composerCache.title":"Composer kešatmiņa","ui.maintenance.composerCache.description":"Composer caches downloaded packages for improved performance. If you have issues like broken files, try to delete the Composer cache to force a new download.","ui.maintenance.composerCache.button":"Iztīrīt kešatmiņu","ui.maintenance.maintenanceMode.title":"Uzturēšanas režīms","ui.maintenance.maintenanceMode.description":"Putting Contao in maintenance mode will display a \\"503 Service Unavailable\\" template for the website.","ui.maintenance.maintenanceMode.enable":"Iespējot","ui.maintenance.maintenanceMode.disable":"Atspējot","ui.maintenance.debugMode.title":"Atkļūdošanas režīms","ui.maintenance.debugMode.description":"Activate the debug mode by setting a user and password for the {appDevPhp} entry point.","ui.maintenance.debugMode.descriptionJwt":"Activate the debug mode by setting the debug cookie for the current domain.","ui.maintenance.debugMode.activate":"Aktivizēt","ui.maintenance.debugMode.deactivate":"Deaktivizēt","ui.maintenance.debugMode.credentials":"Akreditācijas dati","ui.maintenance.debugMode.user":"Lūdzu, ievadiet atkļūdošanas režīma lietotājvārdu.","ui.maintenance.debugMode.password":"Lūdzu, ievadiet paroli atkļūdošanas režīmam.","ui.maintenance.opcodeCache.title":"Opcode Cache","ui.maintenance.opcodeCache.description":"Opcode caches PHP files on the web process for faster execution. It must be deleted under certain circumstances if files are not recognized after changing.","ui.maintenance.opcodeCache.button":"Saīsināt kešatmiņu","ui.maintenance.safeMode":"Nav pieejams drošajā režīmā","ui.maintenance.unsupported":"Neatbalsta jūsu Contao versija","ui.packages.updateButton":"Atjaunināt pakotnes","ui.packages.searchButton":"Meklēt pakotnes","ui.packages.searchPlaceholder":"Meklēt pakotnes ...","ui.packages.uploadOverlay":"Lai augšupielādētu, velciet un nometiet failus","ui.packages.uploadButton":"Augšupielādēt pakotnes","ui.packages.uploadMessage":"Jums ir viena neapstiprināta augšupielāde. | Jums ir {count} neapstiprināta/u augšupielāde/žu.","ui.packages.uploadApply":"Apstiprināt augšupielādi","ui.packages.uploadReset":"Dzēst augšupielādes","ui.packages.uploadIncomplete":"Šis datne netika augšupielādēts pilnībā. Lūdzu, noņemiet to un mēģiniet vēlreiz.","ui.packages.uploadDuplicate":"Šķiet, ka šī datne ir augšupielādēts vairākas reizes. Lūdzu, izdzēsiet dublikātus.","ui.packages.uploadInstalled":"Šis datne jau ir instalēta. Lūdzu, izdzēsiet dublikātus.","ui.packages.uploadUnsupported":"Uploads are not supported in your installation. Please make sure that the PHP ZIP extension is installed and update your dependencies.","ui.packages.changesMessage":"You have one unconfirmed change. | You have {count} unconfirmed changes.","ui.packages.changesDryrun":"Dry Run","ui.packages.changesApply":"Pielietot izmaiņas","ui.packages.changesApplyAll":"Atjaunināt visas pakotnes","ui.packages.changesDryrunAll":"Dry run all packages","ui.packages.changesReset":"Atiestatīt izmaiņas","ui.packages.changesReview":"Pārskatīt izmaiņas","ui.packagelist.loading":"Ielādē ...","ui.packagelist.uploads":"Augšupielādes","ui.packagelist.added":"Jaunas pakotnes","ui.packagelist.installed":"Instalētās pakotnes","ui.package.hintRevert":"Atgriezt izmaiņas","ui.package.hintNoupdate":"Neatjaunināt","ui.package.hintConstraint":"This package will be installed with constraint {constraint} when you apply the changes.","ui.package.hintConstraintBest":"This package will be installed in the best available version when you apply the changes.","ui.package.hintConstraintChange":"The constraint for this package will be changed from \\"{from}\\" to \\"{to}\\" when you apply the changes.","ui.package.hintConstraintUpdate":"Šī pakotne tiks atjaunināta, kad piemērosiet izmaiņas.","ui.package.hintAdded":"Šī pakotne tiks instalēta, kad piemērosiet izmaiņas.","ui.package.hintRemoved":"Šī pakotne tiks noņemta, kad piemērosiet izmaiņas.","ui.package.requiredTitle":"manuāli pievienots","ui.package.requiredText":"Šī pakotne ir nepieciešama jūsu composer.json, bet nav instalēta.","ui.package.removedTitle":"manuāli noņemts","ui.package.removedText":"Šī pakotne tika noņemta no jūsu composer.json.","ui.package.installed":"Pašlaik instalēts:","ui.package.version":"Versija {version}","ui.package.additionalDownloads":"{count} Lejupielāde | {count} Lejupielādes","ui.package.additionalStars":"{count} Star | {count} Stars","ui.package.editConstraint":"Rediģēt","ui.package.uploadConstraint":"This constraint is defined by the uploaded package.","ui.package.updateButton":"Jaunināt","ui.package.removeButton":"Noņemt","ui.package.installButton":"Pievienot pakotni","ui.package.installButtonShort":"Pievienot","ui.package.detailsButton":"Sīkāka informācija","ui.package.latestConstraint":"jaunākā versija","ui.package.update":"Pieejams atjauninājums","ui.package.updateLatest":"jaunākā versija","ui.package.updateAvailable":"Pieejama {versija}","ui.package.updateUnknown":"nezināma versija","ui.package.updateConstraint":"A newer version outside your version constraint is available.","ui.package.incompatible":"{package} does not work with Contao {constraint}.","ui.package.incompatibleWarning":"{package} does not work with Contao {constraint} in any of its stable releases. Do you want to add the package and set a version constraint to try installing a development branch?","ui.package.incompatibleConstraint":"This package does not have a stable release for Contao {constraint}. Set a version constraint to try installing a development branch.","ui.package.incompatibleButton":"Uzstādīt","ui.cloudStatus.headline":"Composer Resolver Cloud","ui.cloudStatus.version":"Versija {version}","ui.cloudStatus.waitingTime":"Gaidīšanas laiks","ui.cloudStatus.jobs":"Pašreizējie darbi","ui.cloudStatus.workers":"Strādnieki","ui.cloudStatus.approx":"{minutes} min","ui.cloudStatus.none":"nav","ui.cloudStatus.short":"apt. {minutes} min","ui.cloudStatus.long":"apt. {minutes} min {seconds} sek","ui.cloudStatus.error":"Unable to fetch the status of the Composer Resolver Cloud. It might be down for maintenance or experience issues.","ui.cloudStatus.button":"Mākoņa statuss","ui.cloudStatus.refresh":"Atjaunināt mākoņa statusu","ui.log-viewer.loading":"Ielādē ...","ui.log-viewer.empty":"There are no log files on your server.","ui.log-viewer.reload":"Pārlādēt","ui.log-viewer.file":"Žurnāla datne","ui.log-viewer.channel":"Kanāls","ui.log-viewer.channelTitle":"The channel this message was logged to.","ui.log-viewer.level":"Līmenis","ui.log-viewer.levelTitle":"Severity of the log message.","ui.log-viewer.timeHeader":"Laiks","ui.log-viewer.messageHeader":"Ziņa","ui.log-viewer.showContext":"Rādīt kontekstu","ui.log-viewer.hideContext":"Slēpt kontekstu","ui.log-viewer.showExtra":"Show Extra","ui.log-viewer.hideExtra":"Hide Extra","ui.log-viewer.more":"Load more …","ui.log-viewer.download":"Lejupielādēt","ui.log-viewer.downloadTitle":"Lejupielādēt datni \\"{file}\\"","ui.log-viewer.prodEnvironment":"Production Environment","ui.log-viewer.devEnvironment":"Development Environment (Debug Mode)","ui.user-manager.loading":"Loading users …","ui.user-manager.changePassword":"Mainīt paroli","ui.user-manager.setupTotp":"Divfaktoru autentifikācijas iestatīšana","ui.user-manager.disableTotp":"Atspējot divfaktoru autentifikāciju","ui.user-manager.invite":"Uzaicināt lietotāju","ui.user-manager.delete":"Dzēst","ui.user-manager.deleteConfirm":"Vai tiešām vēlaties dzēst lietotāju “{username}”?","ui.user-manager.deleted":"Lietotājs {username} veiksmīgi dzēsts","ui.user-manager.passwordHeadline":"Mainīt paroli","ui.user-manager.passwordText":"To change your password, please enter the current and a new password in the respective fields.","ui.user-manager.currentPassword":"Pašreizējā parole","ui.user-manager.newPassword":"Jauna parole","ui.user-manager.passwordPlaceholder":"min. 8 rakstzīmes","ui.user-manager.submitPassword":"Iesniegt","ui.user-manager.passwordChanged":"Jūsu parole ir veiksmīgi nomainīta.","ui.user-manager.passwordError":"Šī parole ir nepareiza.","ui.user-manager.inviteHeadline":"Uzaicināt lietotāju","ui.user-manager.inviteText":"If you need multiple logins for the Contao Manager, you can create an invitation link here. Share this link with someone or use it on another device to create a new account with the given permissions.","ui.user-manager.inviteSuccess1":"A new invitation link was created. The URL below can be used to create a new user account for this Contao Manager. The invitation expires on {expires} (one week from now).","ui.user-manager.inviteSuccess2":"Please copy the link to your clipboard. It will only work once and you will not be able to see it again after closing this dialog.","ui.user-manager.createInvitation":"Izveidot ielūguma saiti","ui.user-manager.clipboard":"Kopēt uz starpliktuvi","ui.user-manager.permissions":"Uzzināt par atļaujām","ui.user-manager.cancel":"Atcelt","ui.user-manager.close":"Aizvērt","ui.user-manager.you":"Jūs","ui.user-manager.2fa":"2FA","ui.user-manager.2faEnabled":"This account is secured by two-factor authentication.","ui.user-manager.2faDisabled":"This account is insecure due to missing two-factor authentication.","ui.user-manager.passkey":"Passkey","ui.user-manager.passkeyTitle":"This account is secured by a Passkey.","ui.totp.headline":"Divfaktoru autentifikācija","ui.totp.setupQr":"Please scan the QR code with your 2FA/TOTP app.","ui.totp.setupCode":"If you cannot scan the QR code, enter this key instead:","ui.totp.codeLabel":"Verifikācijas kods","ui.totp.codeDescription":"Please enter the verification code generated by your 2FA/TOTP app.","ui.totp.disableText":"Please enter the verification code to disable two-factor authentication.","ui.totp.invalid":"Verifikācijas kods ir nederīgs.","ui.totp.enable":"Iespējot","ui.totp.disable":"Atspējot","ui.totp.cancel":"Atcelt","ui.totp.enabled":"Two-factor authentication was enabled successfully.","ui.totp.disabled":"Two-factor authentication was disabled successfully.","ui.totp.setup":"Iestatīt divfaktoru autentifikāciju","ui.totp.skip":"Izlaist divfaktoru autentifikāciju"}')}}]);"use strict";(self["webpackChunkcontao_manager"]=self["webpackChunkcontao_manager"]||[]).push([[715],{3715:function(e){e.exports=JSON.parse('{"ui.app.httpsHeadline":"!! Небезопасное соединение !!","ui.app.httpsDescription":"Без использования HTTPS ваши конфиденциальные данные будут переданы не зашифрованными.","ui.app.httpsLink":"Больше информации","ui.app.httpsHref":"https://https.cio.gov/everything/","ui.app.safeModeHeadline":"!! Включен безопасный режим !!","ui.app.safeModeDescription":"Некоторые функции Contao Manager недоступны.","ui.app.safeModeExit":"Выйти из безопасного режима","ui.app.limitedHeadline":"Удаленная авторизация ","ui.app.limitedDescription":"У вас ограничены разрешения, поскольку вы вошли без ввода пароля.","ui.app.limitedLogout":"Повторная авторизация","ui.app.totpHeadline":"Примечание о безопасности","ui.app.totpDescription":"Настройте двухфакторную авторизацию сейчас, чтобы защитить ваш аккаунт.","ui.app.totpSetup":"Настроить","ui.app.loading":"Загрузка Contao Manager...","ui.app.apiError":"Неожиданный статус API","ui.app.configSecurity1":"ПРЕДУПРЕЖДЕНИЕ СИСТЕМЫ БЕЗОПАСНОСТИ !!! Обнаружен незащищенный каталог конфигурации","ui.app.configSecurity2":"Contao Manager обнаружил, что файлы его конфигурации общедоступны. Все операции отключены до тех пор, пока каталог не будет защищен, в противном случае злоумышленник сможет получить доступ к конфиденциальным данным установки.\\n\\nЧтобы устранить эту проблему, обязательно запретите доступ к каталогу \\"contao-manager\\" на вашем сервере. Чтобы узнать, как это сделать, обратитесь к руководству пользователя веб-сервера или свяжитесь с вашим хостинг-провайдером.","ui.account.welcome":"Приветствие","ui.account.intro1":"Добро пожаловать в Contao Manager, универсальный набор инструментов для установки и управления Contao Open Source CMS. Если вы новичок в этом, {readTheManualToGetStarted}.","ui.account.introGetStarted":"{readTheManual} чтобы начать работу","ui.account.introManual":"прочтите руководство","ui.account.intro2":"Если у вас возникли какие-либо проблемы, см. {ourGithubIssues}, а так-же не стесняйтесь создавать новые вопросы для всего, о чем еще не сообщалось.","ui.account.introIssues":"наши GitHub вопросы","ui.account.headline":"Учетная запись","ui.account.description":"Для управления установкой, создайте учетную запись для Contao Manager. Имейте в виду, что эта учетная запись не связана с панелью управления Contao, либо внешним интерфейсом.","ui.account.username":"Имя пользователя","ui.account.password":"Пароль","ui.account.passwordPlaceholder":"мин. 8 символов","ui.account.passwordLength":"Введите не менее 8 символов.","ui.account.loginInvalid":"Произошла ошибка при создании аккаунта. Попробуйте другое имя пользователя.","ui.account.submit":"Создать учетную запись","ui.account.usePassword":"Использовать пароль для входа","ui.account.usePasskey":"Использовать Passkey для входа","ui.account.totpHeadline":"Двухфакторная авторизация","ui.account.totpDescription":"Включите двухфакторную авторизацию, которая добавит дополнительный уровень безопасности к вашей учетной записи. В дополнение к вашему имени пользователя и паролю вам нужно будет ввести код подтверждения, сгенерированный двухфакторным приложением, таким как 1Password, Authy, Google Authenticator, Microsoft Authenticator, LastPass Authenticator или любым другим приложением TOTP.","ui.account.totpSetup":"Настроить сейчас","ui.account.totpSkip":"Настроить потом","ui.account.login":"Отклонить приглашение","ui.account.contribute1":"Contao и Contao Manager спонсируются некоммерческой ассоциацией Contao.","ui.account.contribute2":"Пожалуйста, подумайте о внесении вклада в открытый исходный код {donate}.","ui.account.contributeDonate":"сделать пожертвование","ui.login.headline":"Вход в систему","ui.login.description":"Войдите в систему для управления установкой.","ui.login.username":"Имя пользователя","ui.login.password":"Пароль","ui.login.totpHeadline":"Двухфакторная авторизация","ui.login.totpDescription":"Введите проверочный код для завершения процесса входа.","ui.login.totp":"Проверочный код","ui.login.forgotPassword":"Забыли пароль?","ui.login.button":"Вход в систему","ui.login.passkey":"Войти с помощью Passkey","ui.login.cancel":"Отмена","ui.login.or":"или","ui.login.locked":"Доступ запрещен, потому, что Contao Manager заблокирован. Чтобы разблокировать, удалите файл {lockFile} в корневом каталоге Contao.","ui.logout.headline":"Тайм-аут сессии","ui.logout.warning":"Вы были неактивны более 25 минут. Из соображений безопасности ваша сессия будет прервана в ближайшее время.","ui.logout.expired":"Ваша сессия была автоматически прервана, потому, что вы были неактивны более 30 минут.","ui.logout.renew":"Оставаться в системе","ui.logout.logout":"Выход","ui.logout.login":"Вернуться на страницу входа","ui.oauth.error":"Неверная попытка OAuth. Проверьте параметры запроса.","ui.oauth.https":"URI перенаправления ДОЛЖЕН использовать защищенный протокол (https:), чтобы предотвратить передачу токена авторизации в виде открытого текста.","ui.oauth.headline":"Удаленная авторизация ","ui.oauth.description":"Следующее приложение или служба запрашивает удаленный доступ к экземпляру Contao Manager.","ui.oauth.domain":"Прежде чем разрешить доступ, убедитесь, что этот URL вам известен и вы доверяете его владельцу!","ui.oauth.outOfScope":"К сожалению, у вас нет необходимых разрешений для предоставления такого доступа.","ui.oauth.allow":"Разрешить доступ","ui.oauth.deny":"Запретить доступ","ui.oauth.switchUser":"Сменить пользователя","ui.scope.admin":"Административный доступ, включая управление пользователями","ui.scope.install":"Установка новых пакетов и изменение конфигурации Contao","ui.scope.update":"Обновление пакетов и выполнение задач по техническому обслуживанию","ui.scope.read":"Чтение пакетов и конфигурации","ui.boot.headline":"Проверка системы","ui.boot.description":"Подождите, мы анализируем ваш сервер...","ui.boot.issue1":"Обнаруженные проблемы установки","ui.boot.issue2":"Ваша установка имеет проблемы, которые должны быть исправлены, перед использованием Contao Manager.","ui.boot.run":"Запуск Contao Manager","ui.boot.safeMode":"Запуск в безопасном режиме","ui.recovery.headline":"Восстановление системы","ui.recovery.description":"Contao Manager обнаружил файлы, которые выглядят как файлы Contao, но интерфейс командной строки не работает как положено.","ui.recovery.console":"Вывод консоли","ui.recovery.repairOptions":"Выберите вариант восстановления вашей установки.","ui.recovery.repairHeadline":"Автоматическое восстановление","ui.recovery.repairDescription":"Пытаться автоматически восстановить установку путем перестроения кеша приложения и повторной установки пакетов Composer.","ui.recovery.repairWarning":"Любые изменения в файлах каталога vendor могут быть удалены в процессе!","ui.recovery.repairFailed":"Автоматическое восстановление не удалось. Используйте безопасный режим, чтобы восстановить установку вручную.","ui.recovery.repairButton":"Запустить системное восстановление","ui.recovery.safeModeHeadline":"Безопасный режим","ui.recovery.safeModeDescription":"Запуск Contao Manager в безопасном режиме позволяет управлять пакетами и запускать определенные задачи обслуживания, но функции, которые опираются на рабочую установку Contao, будут недоступны.","ui.recovery.safeModeButton":"Запуск в безопасном режиме","ui.server.pending":"Ожидание...","ui.server.running":"Анализ...","ui.server.error":"Проверка завершилась неудачно из-за неожиданного ответа с сервера.","ui.server.details":"Сведения","ui.server.prerequisite":"Проверка отменена из-за отсутствия необходимых условий.","ui.server.selfUpdate.title":"Обновления Contao Manager","ui.server.selfUpdate.update":"Доступна новая версия Contao Manager {latest}.","ui.server.selfUpdate.manualUpdate":"Доступна новая версия Contao Manager {latest}. Ваш сервер не поддерживает автоматическое обновление, загрузите новую версию из {download}.","ui.server.selfUpdate.latest":"Вы используете последнюю версию {current}.","ui.server.selfUpdate.dev":"Тестовые сборки не поддерживает автоматическое обновление.","ui.server.selfUpdate.unsupported":"Доступна новая версия, но она не поддерживает вашу версию PHP.","ui.server.selfUpdate.button":"Запустить самообновление","ui.server.selfUpdate.continue":"Продолжить","ui.server.config.title":"Конфигурация сервера","ui.server.config.setup":"Настроить","ui.server.config.change":"Изменить","ui.server.config.save":"Сохранить","ui.server.config.cancel":"Отмена","ui.server.config.customOption":"Другие…","ui.server.config.description":"Для правильного выполнения фоновых задач, Contao Manager необходимо знать, где найти двоичный файл командной строки PHP и как выполнять команды, отделенные от веб-процесса.","ui.server.config.formTitle":"Конфигурация сервера","ui.server.config.formText":"Введите путь к вашему бинарному файлу PHP. Убедитесь, что бинарный файл той же версии PHP, что и ваш веб-процесс.","ui.server.config.cloudTitle":"Composer Resolver Cloud","ui.server.config.cloudText":"Composer Resolver Cloud позволяет устанавливать зависимости Composer даже если сервер не предоставляет достаточно локальной памяти. Имейте в виду, что информация о пакетах будет передана на облачный сервер, управляемый Contao Association.","ui.server.config.cloud":"Использовать Composer Resolver Cloud","ui.server.config.cli":"Бинарный файл PHP","ui.server.config.stateErrorCli":"На сервере не найден верный бинарный файл PHP.","ui.server.config.stateErrorCloud":"Composer Resolver Cloud не поддерживается.","ui.server.config.stateSuccess":"Бинарный файл PHP {php_cli}.","ui.server.config.cloudEnabled":"Зависимости пакетов будут разрешены с помощью Composer Resolver Cloud.","ui.server.config.cloudDisabled":"Composer Resolver Cloud отключено.","ui.server.php_web.title":"Веб-процесс PHP","ui.server.php_web.below7":"Найдена версия PHP {version}. Перейдите на PHP 7 как можно скорее!","ui.server.php_web.success":"Найдена версия PHP {version}, известные проблемы не найдены.","ui.server.php_cli.title":"Интерфейс командной строки PHP","ui.server.php_cli.success":"Найдена версия PHP {version}, известные проблемы не найдены.","ui.server.composer.title":"Окружающая среда Composer","ui.server.composer.success":"Известных проблем не обнаружено.","ui.server.composer.install":"Зависимости Composer не установлены.","ui.server.composer.button":"Установить","ui.server.contao.title":"Установка Contao","ui.server.contao.setup":"Настроить","ui.server.contao.check":"Проверить базу данных","ui.server.contao.empty":"Установка Contao не найдена.","ui.server.contao.old":"Contao версии {version} не совместима с Contao Manager, пожалуйста, обновите установку Contao вручную.","ui.server.contao.found":"Найдена Contao {version} (версия API {api}).","ui.server.contao.connectionError":"Не удается подключиться к серверу базы данных.","ui.server.contao.connectionProblem":"Обнаружена проблема с базой данных.","ui.server.contao.missingUser":"Учетная запись администратора не найдена.","ui.setup.continue":"Продолжить","ui.setup.manager":"Запуск Contao Manager","ui.setup.cancel":"Отмена","ui.setup.welcome":"Приветствие","ui.setup.welcome1":"Этот мастер проведет вас через необходимые шаги для настройки и установки системы с открытым исходным кодом Contao CMS.","ui.setup.welcome2":"Если у вас есть какие-либо вопросы, найдите документацию, форумы, канал Slack и многое другое на странице {support}.","ui.setup.support":"поддержка сообщества","ui.setup.start":"Начать","ui.setup.complete":"Поздравляем!","ui.setup.complete1":"Contao {version} успешно установлена.","ui.setup.complete2":"Для завершения установки, откройте мастер установки, настройте подключение к базе данных и создайте учетную запись панели управления.","ui.setup.complete3":"Теперь можно приступить к созданию своего веб-сайта, с помощью панели управления Contao. Если нужны дополнительные расширения, перейдите в Contao Manager.","ui.setup.installTool":"Открыть мастер установки","ui.setup.login":"Войти в Contao","ui.setup.funding":"Свободное программное обеспечение означает \\"бесплатно\\" как \\"свобода слова\\", а не как \\"бесплатное пиво\\". Для такого проекта с открытым исходным кодом, как Contao, требуются суммы денег, которые не могут быть собраны одним человеком или компанией.\\nЕсли у Вас есть веб-сайт или Вы продаете веб-сайты, созданные с помощью Contao, мы были бы рады, если бы Вы внесли посильный финансовый вклад в продукт, на который опирается Ваш бизнес.","ui.setup.fundingLink":"Узнать больше","ui.setup.document-root.headline":"Настройка веб-сервера","ui.setup.document-root.warning":"Чтобы установить Contao с помощью Contao Manager, необходимо исправить корень документа на веб-сервере.","ui.setup.document-root.description1":"Contao использует отдельный каталог для общедоступных файлов, файлы приложений устанавливаются в родительский каталог. Contao не может быть установлен, если структура каталогов неверна или каталоги не пусты.","ui.setup.document-root.description2":"Если вы не знаете, как настроить корень документа, ознакомьтесь с документацией Contao или обратитесь к хостинг-провайдеру.","ui.setup.document-root.documentation":"Читать документацию","ui.setup.document-root.conflictsTitle":"Каталог установки не пустой","ui.setup.document-root.conflictsDirectory":"Корневой каталог будущей установки Contao не пустой, найдено {count} файла(ов), которые могут быть перезаписаны в процессе установки. Рекомендуется создать пустую структуру каталогов для установки Contao. Также вы можете удалить следующие файлы и проверить еще раз, уверены ли вы, что они не используются.","ui.setup.document-root.ignoreConflicts":"Я хочу установить Contao в непустой каталог. Я понимаю, что это может перезаписать любые существующие файлы в моем веб-пространстве.","ui.setup.document-root.check":"Проверить еще раз","ui.setup.document-root.create":"Создать каталоги","ui.setup.document-root.change":"Изменить каталоги","ui.setup.document-root.formTitle":"Настройка каталога","ui.setup.document-root.formText1":"Contao Manager может автоматически создать новую структуру каталогов на сервере.","ui.setup.document-root.formText2":"Необходимо вручную настроить новый корень документа (например, через панель администратора хостинга).","ui.setup.document-root.autoconfig":"Я понимаю, что мне нужно изменить конфигурацию сервера. Если не настроить корневой каталог документа, это сломает Contao Manager и откроет файлы конфигурации (включая данные учетной записи и пароли)!","ui.setup.document-root.directory":"Новый каталог","ui.setup.document-root.currentRoot":"Текущий корень документа","ui.setup.document-root.newRoot":"Новый корень документа","ui.setup.document-root.finish":"Каталоги установки","ui.setup.document-root.publicDir":"Использовать {dir} для общедоступных файлов (Contao {version})","ui.setup.document-root.directoryInvalid":"Введите допустимое имя каталога.","ui.setup.document-root.directoryExists":"Целевой каталог уже существует. Введите другое имя.","ui.setup.document-root.confirmation":"Contao Manager успешно создал каталог, необходимый для установки Contao. Теперь необходимо настроить корневой каталог документа на веб-сервере. Не перезагружайте эту страницу до тех пор.","ui.setup.document-root.reload":"Перезагрузить страницу","ui.setup.document-root.success":"Структура каталогов на веб-сервере настроена правильно!","ui.setup.document-root.installingProjectDir":"Файлы приложения будут установлены в {dir}.","ui.setup.document-root.installingPublicDir":"Общедоступные файлы будут установлены в {dir}.","ui.setup.document-root.installedProjectDir":"Файлы приложения устанавливаются в {dir}.","ui.setup.document-root.installedPublicDir":"Общедоступные файлы устанавливаются в {dir}.","ui.setup.create-project.headline":"Установка Contao","ui.setup.create-project.description":"Разработка Contao следует принципу {semver}, новая минорная версия выпускается каждые шесть месяцев. В настоящее время поддерживаются следующие релизы:","ui.setup.create-project.semver":"Семантическое управление версиями","ui.setup.create-project.latestTitle":"Последняя версия","ui.setup.create-project.ltsTitle":"Версия с долгосрочной поддержкой","ui.setup.create-project.latestQ1":"Последняя версия предлагает большинство функций с поддержкой до февраля {year}.","ui.setup.create-project.latestQ3":"Последняя версия предлагает большинство функций с поддержкой до августа {year}.","ui.setup.create-project.ltsText":"Текущая LTS-версия, если вы предпочитаете стабильность, предлагает долгосрочную поддержку до февраля {year}.","ui.setup.create-project.pltsText":"Предыдущая LTS-версия, по-прежнему имеет долгосрочную поддержку до февраля {year}.","ui.setup.create-project.requiresPHP":"Требуется PHP версии минимум {version}, у вас PHP {current}.","ui.setup.create-project.releaseplan":"Для получения дополнительной информации см. {contaoReleasePlan}.","ui.setup.create-project.releaseplanLink":"План выпуска Contao","ui.setup.create-project.installed":"Contao {version} успешно установлена на сервере. Продолжайте настройку базы данных или запустите Contao Manager для установки другой версии.","ui.setup.create-project.formTitle":"Выберите дистрибутив","ui.setup.create-project.formText":"Выберите, какую версию следует установить.","ui.setup.create-project.version":"Версия","ui.setup.create-project.demo":"Установить демонстрационный веб-сайт Contao.","ui.setup.create-project.demoDescription":"Демонстрационный веб-сайт поможет вам познакомиться с Contao и всеми его основными функциями. Дополнительные темы можно найти в {store}.","ui.setup.create-project.coreOnly":"Минимальная установка (Только ядро)","ui.setup.create-project.noUpdate":"Пропустить установку (Только для экспертов!)","ui.setup.create-project.theme":"Contao тема","ui.setup.create-project.themeInstall":"Для установки темы Contao, используйте поиск или загрузите файл темы (.cto/.zip), который поддерживает установку через Contao Manager.","ui.setup.create-project.themeBuy":"Обязательно посетите официальный {store}.","ui.setup.create-project.themeStore":"Магазин тем Contao","ui.setup.create-project.themeUpload":"Загрузить файл темы (.cto/.zip)","ui.setup.create-project.themeInvalid":"Загруженный файл не является темой Contao или не поддерживает Contao Manager.","ui.setup.create-project.themeWarning":"Contao Manager не может определить, совместима ли эта тема с вашим сервером. Если у вас возникают вопросы, обратитесь к поставщику темы.","ui.setup.create-project.themeTitle":"Просмотр сведений о теме","ui.setup.create-project.themeDetails":"С этой темой будут установлены следующие зависимости и файлы.","ui.setup.create-project.themeRequire":"{count} зависимость | {count} зависимостей","ui.setup.create-project.themeFiles":"{count} файл | {count} файлов","ui.setup.create-project.theme.or":"или выполните поиск в общедоступных темах","ui.setup.create-project.theme.search":"Поиск тем","ui.setup.create-project.theme.more":"Больше тем","ui.setup.create-project.theme.empty":"Нет соответствующих тем {query}","ui.setup.create-project.theme.uploaded":"Файл темы загружен успешно.","ui.setup.create-project.theme.packageName":"Имя пакета","ui.setup.create-project.theme.version":"Версия","ui.setup.create-project.theme.authors":"Автор(ы)","ui.setup.create-project.theme.upload":"Загрузка {name} ({size})","ui.setup.create-project.install":"Установить","ui.setup.create-project.cancel":"Отмена","ui.setup.create-project.fileError":"Файл composer.json не найден в {file}.","ui.setup.create-project.jsonError":"composer.json содержит некорректный JSON.","ui.setup.create-project.schemaError":"composer.json не соответствует проверяемой схеме.","ui.setup.database-connection.headline":"Подключение к базе данных","ui.setup.database-connection.description":"Contao требуется базы данных MySQL (или совместимого форка, такого как MariaDB) для хранения страниц, контента, пользователей и других реляционных данных. Параметры подключения хранятся в файле {env} в корне проекта вашей установки Contao.","ui.setup.database-connection.formTitle":"Параметры подключения","ui.setup.database-connection.formText":"Введите URL-адрес базы данных или заполните поля имени пользователя, пароля, сервера и базы данных отдельно.","ui.setup.database-connection.url":"URL базы данных","ui.setup.database-connection.validUrl":"URL-адрес базы данных недействителен или соединение с сервером не выполнено.","ui.setup.database-connection.or":"или","ui.setup.database-connection.user":"Имя пользователя","ui.setup.database-connection.password":"Пароль","ui.setup.database-connection.server":"Сервер (:Порт)","ui.setup.database-connection.database":"Имя базы данных","ui.setup.database-connection.connected":"Соединение с базой данных {database} на {server} успешно установлено.","ui.setup.database-connection.error":"Ошибка подключения к базе данных.","ui.setup.database-connection.problem":"Contao обнаружила проблему с сервером базы данных.","ui.setup.database-connection.schemaTitle":"Схема базы данных","ui.setup.database-connection.migration":"Существует одна незавершенная миграция. | Есть {count} ожидающие миграции.","ui.setup.database-connection.schema":"Существует одна ожидающая обновления схема. | Есть {count} ожидающих обновления схем.","ui.setup.database-connection.noChanges":"Схема базы данных обновлена.","ui.setup.database-connection.check":"Проверить базу данных","ui.setup.database-connection.skip":"Пропустить","ui.setup.database-connection.save":"Сохранить","ui.setup.database-connection.change":"Изменить учетные данные","ui.setup.database-connection.restoreTitle":"Импорт базы данных","ui.setup.database-connection.restoreText":"Только что установленная тема содержит резервную копию базы данных. Восстановите базу данных, чтобы импортировать данные темы или пропустите этот шаг, чтобы начать с чистой установки Contao. | Только что установленная тема содержит несколько резервных копий базы данных. Выберите файл резервной копии для импорта данных темы или пропустите этот шаг, чтобы начать с чистой установки Contao.","ui.setup.database-connection.backup":"Резервное копирование текущей базы данных перед импортом","ui.setup.database-connection.backupWarning":"При импорте все данные в базе данных будут перезаписаны! Если база данных не пуста, сначала создайте резервную копию.","ui.setup.database-connection.restore":"Импорт базы данных темы","ui.setup.database-connection.restoreOption":"Резервная копия из {date} ({size})","ui.setup.database-connection.restored":"База данных темы была успешно импортирована. Продолжайте проверять схему базы данных.","ui.setup.backend-user.success":"В базе данных обнаружена учетная запись администратора для панели управления Contao. Используйте панель управления Contao, чтобы добавить больше пользователей.","ui.setup.backend-user.error":"Не удалось получить список пользователей. Для получения подробной информации см. вывод консоли.","ui.setup.backend-user.headline":"Учетная запись панели управления","ui.setup.backend-user.description":"Для управления своим веб-сайтом, вам необходимо иметь хотя бы одну учетную запись администратора в панели управления Contao. Имейте в виду, что эта учетная запись не связана с Contao Manager.","ui.setup.backend-user.formTitle":"Создать учетную запись","ui.setup.backend-user.formText":"Введите данные для новой учетной записи панели управления.","ui.setup.backend-user.username":"Имя пользователя","ui.setup.backend-user.name":"Имя","ui.setup.backend-user.email":"E-mail адрес","ui.setup.backend-user.emailInvalid":"Введите допустимый e-mail","ui.setup.backend-user.password":"Пароль","ui.setup.backend-user.passwordPlaceholder":"мин. 8 символов","ui.setup.backend-user.passwordLength":"Введите не менее 8 символов.","ui.setup.backend-user.create":"Добавить учетную запись","ui.task.headline":"Фоновая задача","ui.task.loading":"Загрузка сведений...","ui.task.created":"Загрузка сведений...","ui.task.active":"Подождите, пока Contao Manager выполняет задачи в фоновом режиме.","ui.task.complete":"Все операции успешно завершены. Дополнительные сведения см. в протоколе консоли.","ui.task.paused":"Непредвиденная остановка фоновой операции. Проверьте протокол консоли.","ui.task.aborting":"Подождите, пока отменяются фоновые операции.","ui.task.stopped":"Некоторые фоновые операции были отменены. Проверьте протокол консоли.","ui.task.error":"Непредвиденная остановка фоновой операции. Проверьте протокол консоли.","ui.task.failed":"Contao Manager не удалось запустить фоновую задачу!","ui.task.failedDescription1":"Что-то пошло не так при попытке выполнения операций в фоновом режиме.","ui.task.failedDescription2":"Если это событие произойдет снова, ваш сервер может не поддерживаться.","ui.task.reportProblem":"Сообщить о проблеме","ui.task.pausedDescription":"Нажмите \\"Продолжить\\", если хотите проигнорировать ошибку и выполнить оставшиеся операции.","ui.task.sponsor":"Composer Cloud спонсируется {sponsor}","ui.task.buttonAudit":"Обновить базу данных","ui.task.buttonClose":"Закрыть","ui.task.buttonConfirm":"Подтвердить и закрыть","ui.task.buttonContinue":"Продолжить","ui.task.buttonCancel":"Отмена","ui.task.confirmCancel":"Вы действительно хотите отменить задачу? Это может оставить вашу установку Contao в не работающем состоянии!","ui.task.autoclose":"Закрыть сведения об успешном выполнении задачи","ui.console.toggle":"Показать/Скрыть вывод консоли","ui.console.showLog":"Показать полный журнал консоли","ui.console.copyLog":"Скопировать журнал в буфер обмена","ui.migrate.headline":"Обновления базы данных","ui.migrate.migrationsOnly":"(только миграции)","ui.migrate.schemaOnly":"(только схема)","ui.migrate.loading":"Подождите, идет проверка базы данных...","ui.migrate.empty":"Отложенных миграций или обновлений схемы не обнаружено. Ваша база данных актуальна.","ui.migrate.emptyMigrations":"Отложенных миграций не найдено. Не забудьте проверить наличие обновлений схемы.","ui.migrate.emptySchema":"Отложенных обновлений схемы не найдено. Не забудьте проверить миграции.","ui.migrate.pending":"Ваша база данных не обновлена. Просмотрите приведенный ниже вывод консоли и внесите изменения.","ui.migrate.previousChanges":"Предыдущая миграция базы данных не была подтверждена.\\nПросмотрите приведенный ниже вывод консоли, а затем продолжите просмотр следующих изменений.","ui.migrate.previousComplete":"Предыдущая миграция базы данных не была подтверждена, просмотрите вывод консоли ниже.\\nОжидаемых изменений больше нет.","ui.migrate.appliedChanges":"Были применены обновления базы данных.\\nПросмотрите приведенный ниже вывод консоли, а затем продолжите просмотр следующих изменений.","ui.migrate.appliedComplete":"Были применены обновления базы данных.\\nБольше нет ожидающих миграций или обновлений схемы. База данных обновлена.","ui.migrate.problem":"Contao обнаружила проблему с сервером базы данных.\\nПросмотрите вывод консоли ниже, чтобы узнать, что необходимо исправить. | Contao обнаружила проблемы с сервером базы данных.\\nПросмотрите вывод консоли ниже, чтобы узнать, что необходимо исправить.","ui.migrate.warning":"Contao обнаружила неправильную конфигурацию сервера базы данных.\\nПредупреждения могут быть временно пропущены, но должны быть исправлены для обеспечения оптимальной производительности и целостности данных.","ui.migrate.error":"Изменения не могут быть применены. Возможно, ваша база данных была изменена, проверьте еще раз, чтобы повторить попытку.","ui.migrate.execute":"Выполнить","ui.migrate.close":"Закрыть","ui.migrate.confirm":"Подтвердить и закрыть","ui.migrate.cancel":"Отмена","ui.migrate.continue":"Продолжить","ui.migrate.setup":"Настроить","ui.migrate.skip":"Пропустить","ui.migrate.retry":"Проверить еще раз","ui.migrate.retryAll":"Проверить все","ui.migrate.withDeletes":"Выполнить все изменения базы данных, включая запросы DROP.","ui.migrate.migrationTitle":"Миграции базы данных","ui.migrate.schemaTitle":"Обновления схемы","ui.migrate.problemTitle":"Проблемы с базой данных","ui.migrate.warningTitle":"Предупреждения базы данных","ui.migrate.addTable":"Добавить таблицу {table}","ui.migrate.dropTable":"Удалить таблицу {table}","ui.migrate.addField":"Добавить поле {table}.{field}","ui.migrate.changeField":"Изменить поле {table}.{field}","ui.migrate.dropField":"Удалить поле {table}.{field}","ui.migrate.createIndex":"Создать индекс \\"{name}\\" в {table}","ui.migrate.dropIndex":"Удалить индекс \\"{name}\\" в {table}","ui.widget.mandatory":"Поле не должно быть пустым.","ui.widget.blankOption":"Пожалуйста, выберите…","ui.widget.showPassword":"Показать пароль","ui.widget.hidePassword":"Скрыть пароль","ui.error.title":"HTTP запрос для \\"{method} {url}\\" не выполнен.","ui.error.server500":"Вероятно, на сервере произошла непредвиденная ошибка. Проверьте файлы журнала вашего веб-сервера (Apache/Nginx) и журналы Contao Manager по адресу \\"contao-manager/logs\\".","ui.error.response":"Сервер вернул ответ с кодом состояния {status}.","ui.error.moreLink":"Больше информации","ui.error.support":"Поддержка Contao","ui.error.permission":"У вас нет разрешения на использование этой функции.","ui.footer.help":"Справка","ui.footer.reportProblem":"Сообщить о проблеме","ui.navigation.discover":"Обзор","ui.navigation.packages":"Пакеты","ui.navigation.tools":"Инструменты","ui.navigation.installTool":"Мастер установки","ui.navigation.backend":"Панель управления Contao","ui.navigation.debug":"Режим отладки Contao","ui.navigation.logViewer":"Просмотр журнала","ui.navigation.phpinfo":"Информация о PHP","ui.navigation.phpinfoLoading":"Загрузка информации о PHP...","ui.navigation.maintenance":"Обслуживание","ui.navigation.rebuildCache":"Восстановить кеш","ui.navigation.users":"Учетные записи","ui.navigation.systemCheck":"Проверка системы","ui.navigation.advanced":"Расширенный","ui.navigation.logout":"Выход","ui.maintenance.database.title":"Миграция баз данных и резервное копирование","ui.maintenance.database.description":"Миграция базы данных обеспечивает согласованность данных и схем таблиц.","ui.maintenance.database.migrations":"Одна отложенная миграция базы данных | {count} незавершенных миграций базы данных.","ui.maintenance.database.schemaUpdates":"Одно ожидающее обновление схемы | {count} ожидающих обновлений схемы","ui.maintenance.database.error":"Обнаружена проблема с базой данных.","ui.maintenance.database.warning":"Обнаружены предупреждения базы данных.","ui.maintenance.database.button":"Проверить базу данных","ui.maintenance.database.migrationOnly":"Проверить только миграции","ui.maintenance.database.schemaOnly":"Проверить только схему","ui.maintenance.database.installTool":"Открыть мастер установки","ui.maintenance.database.createBackup":"Создать резервную копию","ui.maintenance.database.backupUnsupported":"Резервное копирование баз данных не поддерживается вашей версией Contao.","ui.maintenance.database.backupList":"У вас есть одна резервная копия базы данных, созданная {date}. | У вас есть {count} резервных копий базы данных, последняя из которых была создана {date}.","ui.maintenance.database.backupEmpty":"На данный момент у вас нет резервных копий базы данных.","ui.maintenance.rebuildCache.title":"Кеш приложения","ui.maintenance.rebuildCache.description":"После изменения любого из файлов конфигурации требуется восстановление кеша приложений.","ui.maintenance.rebuildCache.rebuildProd":"Перестроить производственный кеш","ui.maintenance.rebuildCache.rebuildDev":"Перестроить кеш разработки","ui.maintenance.rebuildCache.clearProd":"Очистить производственный кеш","ui.maintenance.rebuildCache.clearDev":"Очистить кеш разработки","ui.maintenance.installTool.title":"Мастер установки Contao","ui.maintenance.installTool.description":"Мастер установки Contao автоматически блокируется, если вы введете неправильный пароль три раза подряд.","ui.maintenance.installTool.unlock":"Разблокировать мастер установки","ui.maintenance.installTool.lock":"Заблокировать мастер установки","ui.maintenance.dumpAutoload.title":"Загрузчик класса Composer","ui.maintenance.dumpAutoload.description":"Автозагрузчик Composer отвечает за загрузку классов PHP. Автозагрузчик должен быть сброшен после добавления пользовательских пространств имен в корневой файл composer.json.","ui.maintenance.dumpAutoload.button":"Дамп автозапуска","ui.maintenance.composerInstall.title":"Зависимости Composer","ui.maintenance.composerInstall.description":"Зависимости Composer находятся в каталоге {vendor}, в корне приложения. Повторная установка зависимостей может потребоваться после различных манипуляций или ручной загрузки файла {composerLock}.","ui.maintenance.composerInstall.button":"Запустить установщик","ui.maintenance.composerInstall.update":"Запустить обновление Composer","ui.maintenance.composerCache.title":"Кеш Composer","ui.maintenance.composerCache.description":"Composer кеширует загруженные пакеты для улучшения производительности. Если у вас есть проблемы, например, испорченные файлы, попробуйте очистить кеш Composer, чтобы запустить новую загрузку.","ui.maintenance.composerCache.button":"Очистить кеш","ui.maintenance.maintenanceMode.title":"Режим обслуживания","ui.maintenance.maintenanceMode.description":"Перевод Contao в режим обслуживания отобразит шаблон \\"503 Service Unavailable\\" для веб-сайта.","ui.maintenance.maintenanceMode.enable":"Включить","ui.maintenance.maintenanceMode.disable":"Выключить","ui.maintenance.debugMode.title":"Режим отладки","ui.maintenance.debugMode.description":"Активируйте режим отладки, задав имя пользователя и пароль для точки входа {appDevPhp}.","ui.maintenance.debugMode.descriptionJwt":"Активируйте режим отладки, установив файл отладки cookie для текущего домена.","ui.maintenance.debugMode.activate":"Активировать","ui.maintenance.debugMode.deactivate":"Деактивировать","ui.maintenance.debugMode.credentials":"Полномочия","ui.maintenance.debugMode.user":"Введите имя пользователя для режима отладки.","ui.maintenance.debugMode.password":"Введите пароль для режима отладки.","ui.maintenance.opcodeCache.title":"Кеш Opcode","ui.maintenance.opcodeCache.description":"Opcode кеширует PHP-файлы в веб-процессе для более быстрого выполнения. Он должен быть удален при определенных обстоятельствах, если файлы не распознаются после изменения.","ui.maintenance.opcodeCache.button":"Усечение кеша","ui.maintenance.safeMode":"Недоступно в безопасном режиме","ui.maintenance.unsupported":"Не поддерживается этой версией Contao","ui.packages.updateButton":"Обновить пакеты","ui.packages.searchButton":"Поиск пакетов","ui.packages.searchPlaceholder":"Поиск пакетов...","ui.packages.uploadOverlay":"Перетащите файлы для загрузки","ui.packages.uploadButton":"Загрузить пакеты","ui.packages.uploadMessage":"У вас одна неподтвержденная загрузка. | У вас неподтвержденных загрузок {count}.","ui.packages.uploadApply":"Подтвердить загрузки","ui.packages.uploadReset":"Удалить загрузки","ui.packages.uploadIncomplete":"Этот файл не был загружен полностью. Удалите его и попробуйте еще раз.","ui.packages.uploadDuplicate":"Этот файл загружен несколько раз. Удалите дубликаты.","ui.packages.uploadInstalled":"Этот файл уже установлен. Удалите дубликаты.","ui.packages.uploadUnsupported":"Загрузка не поддерживается текущей установкой. Убедитесь, что установлено расширение PHP ZIP и не забудьте обновить зависимости.","ui.packages.changesMessage":"У вас одно неподтвержденное изменение. | У вас неподтвержденных изменений {count}.","ui.packages.changesDryrun":"Пробный прогон","ui.packages.changesApply":"Применить изменения","ui.packages.changesApplyAll":"Обновить все пакеты","ui.packages.changesDryrunAll":"Пробный прогон всех пакетов","ui.packages.changesReset":"Сброс изменений","ui.packages.changesReview":"Обзор изменений","ui.packagelist.loading":"Загрузка...","ui.packagelist.uploads":"Загрузки","ui.packagelist.added":"Новые пакеты","ui.packagelist.installed":"Установленные пакеты","ui.package.hintRevert":"Отменить изменения","ui.package.hintNoupdate":"Не обновлять","ui.package.hintConstraint":"Этот пакет будет установлен с ограничением {constraint} при применении изменений.","ui.package.hintConstraintBest":"Этот пакет будет установлен в наилучшей доступной версии при применении изменений.","ui.package.hintConstraintChange":"Ограничение этого пакета будет изменено с \\"{from}\\" на \\"{to}\\" при применении изменений.","ui.package.hintConstraintUpdate":"Этот пакет будет обновлен при применении изменений.","ui.package.hintAdded":"Этот пакет будет установлен при применении изменений.","ui.package.hintRemoved":"Этот пакет будет удален при применении изменений.","ui.package.requiredTitle":"добавлено вручную","ui.package.requiredText":"Этот пакет необходим в composer.json, но он не установлен.","ui.package.removedTitle":"удалено вручную","ui.package.removedText":"Этот пакет удален из вашего composer.json.","ui.package.installed":"Установлена:","ui.package.version":"Версия {version}","ui.package.additionalDownloads":"Загрузок {count} | Загрузок {count}","ui.package.additionalStars":"Звёзд {count} | Звёзд {count}","ui.package.editConstraint":"Редактировать","ui.package.uploadConstraint":"Это ограничение определяется загруженным пакетом.","ui.package.updateButton":"Обновить","ui.package.removeButton":"Удалить","ui.package.installButton":"Добавить пакет","ui.package.installButtonShort":"Добавить","ui.package.detailsButton":"Сведения","ui.package.latestConstraint":"последняя версия","ui.package.update":"Доступно обновление","ui.package.updateLatest":"последняя версия","ui.package.updateAvailable":"{version} доступна","ui.package.updateUnknown":"неизвестная версия","ui.package.updateConstraint":"Доступна более новая версия, выходящая за рамки вашего ограничения версии.","ui.package.incompatible":"{package} не работает с Contao {constraint}.","ui.package.incompatibleWarning":"{package} не работает с Contao {constraint} ни в одной из его стабильных версий. Хотите добавить пакет и установить ограничение версии, чтобы попробовать установить ветку разработки?","ui.package.incompatibleConstraint":"У этого пакета нет стабильной версии для Contao {constraint}. Установите ограничение версии, чтобы попробовать установить ветку разработки.","ui.package.incompatibleButton":"Установить","ui.cloudStatus.headline":"Composer Resolver Cloud","ui.cloudStatus.version":"Версия {version}","ui.cloudStatus.waitingTime":"Время ожидания","ui.cloudStatus.jobs":"Текущие задания","ui.cloudStatus.workers":"Рабочие","ui.cloudStatus.approx":"{minutes} мин","ui.cloudStatus.none":"ни один","ui.cloudStatus.short":"прим. {minutes} мин","ui.cloudStatus.long":"прим. {minutes} мин {seconds} сек","ui.cloudStatus.error":"Не удалось получить статус облака Resolver Composer. Вероятно, он не работает из-за проблем с обслуживанием или неполадок.","ui.cloudStatus.button":"Статус облака","ui.cloudStatus.refresh":"Обновить статус облака","ui.log-viewer.loading":"Загрузка...","ui.log-viewer.empty":"На вашем сервере нет файлов журнала.","ui.log-viewer.reload":"Перезагрузить","ui.log-viewer.file":"Файл журнала","ui.log-viewer.channel":"Канал","ui.log-viewer.channelTitle":"Канал, на который было зарегистрировано это сообщение.","ui.log-viewer.level":"Уровень","ui.log-viewer.levelTitle":"Уровень журнала или серьезность сообщения журнала.","ui.log-viewer.timeHeader":"Время","ui.log-viewer.messageHeader":"Сообщение","ui.log-viewer.showContext":"Показать контекст","ui.log-viewer.hideContext":"Скрыть контекст","ui.log-viewer.showExtra":"Показать дополнительное","ui.log-viewer.hideExtra":"Скрыть дополнительное","ui.log-viewer.more":"Загрузить больше...","ui.log-viewer.download":"Загрузка","ui.log-viewer.downloadTitle":"Загрузка файла \\"{file}\\"","ui.log-viewer.prodEnvironment":"Рабочая среда","ui.log-viewer.devEnvironment":"Среда разработки (режим отладки)","ui.user-manager.loading":"Загрузка пользователей…","ui.user-manager.changePassword":"Изменить пароль","ui.user-manager.setupTotp":"Настройка двухфакторной авторизации","ui.user-manager.disableTotp":"Отключить двухфакторную авторизацию","ui.user-manager.invite":"Пригласить пользователя","ui.user-manager.delete":"Удалить","ui.user-manager.deleteConfirm":"Вы действительно хотите удалить пользователя \\"{username}\\"?","ui.user-manager.deleted":"Пользователь {username} успешно удален","ui.user-manager.passwordHeadline":"Изменить пароль","ui.user-manager.passwordText":"Чтобы изменить пароль, введите текущий и новый пароль в соответствующие поля.","ui.user-manager.currentPassword":"Текущий пароль","ui.user-manager.newPassword":"Новый пароль","ui.user-manager.passwordPlaceholder":"мин. 8 символов","ui.user-manager.submitPassword":"Отправить","ui.user-manager.passwordChanged":"Ваш пароль был успешно изменён.","ui.user-manager.passwordError":"Этот пароль неверный.","ui.user-manager.inviteHeadline":"Пригласить пользователя","ui.user-manager.inviteText":"Если вам нужно несколько учётных записей для Contao Manager, вы можете создать здесь ссылку-приглашение. Поделитесь этой ссылкой или используйте её на другом устройстве, чтобы создать новую учётную запись с заданными правами доступа.","ui.user-manager.inviteSuccess1":"Создана новая ссылка-приглашение. URL-адрес ниже можно использовать для создания новой учетной записи пользователя для Contao Manager. Приглашение истекает {expires} (через неделю).","ui.user-manager.inviteSuccess2":"Скопируйте ссылку в буфер обмена. Эта ссылка сработает только один раз, и вы больше не сможете её увидеть после закрытия этого диалогового окна.","ui.user-manager.createInvitation":"Создать ссылку-приглашение","ui.user-manager.clipboard":"Копировать в буфер обмена","ui.user-manager.permissions":"Узнать о разрешениях","ui.user-manager.cancel":"Отмена","ui.user-manager.close":"Закрыть","ui.user-manager.you":"Вы","ui.user-manager.2fa":"2FA","ui.user-manager.2faEnabled":"Эта учетная запись защищена двухфакторной авторизацией.","ui.user-manager.2faDisabled":"Эта учетная запись небезопасна из-за отсутствия двухфакторной авторизации.","ui.user-manager.passkey":"Passkey","ui.user-manager.passkeyTitle":"Эта учетная запись защищена с помощью Passkey.","ui.totp.headline":"Двухфакторная авторизация","ui.totp.setupQr":"Пожалуйста, отсканируйте QR-код с помощью вашего приложения для 2FA/TOTP.","ui.totp.setupCode":"Если вы не можете отсканировать QR-код, введите этот ключ вместо него:","ui.totp.codeLabel":"Проверочный код","ui.totp.codeDescription":"Пожалуйста, введите проверочный код, сгенерированный с помощью вашего приложения для 2FA/TOTP.","ui.totp.disableText":"Пожалуйста, введите проверочный код для отключения двухфакторной авторизации.","ui.totp.invalid":"Проверочный код неверный.","ui.totp.enable":"Включить","ui.totp.disable":"Выключить","ui.totp.cancel":"Отмена","ui.totp.enabled":"Двухфакторная авторизация успешно включена.","ui.totp.disabled":"Двухфакторная авторизация успешно отключена.","ui.totp.setup":"Настройка двухфакторной авторизации","ui.totp.skip":"Пропустить двухфакторную авторизацию"}')}}]);"use strict";(self["webpackChunkcontao_manager"]=self["webpackChunkcontao_manager"]||[]).push([[335],{1035:function(e,s,c){c.r(s),c.d(s,{default:function(){return V}});var i=c(641),l=c(33),o=c(3751),t=c.p+"img/server-config.1a2d0888.svg";const n={class:"config-check__header"},r={class:"config-check__headline"},a={class:"config-check__description"},d={class:"config-check__form"},u={class:"config-check__fields"},g={class:"config-check__fieldtitle"},h={class:"config-check__fielddesc"},f={class:"config-check__fields"},_={class:"config-check__fieldtitle"},p={class:"config-check__fielddesc"},k={key:0,class:"config-check__issues"},v=["disabled"];function b(e,s,c,b,m,L){const $=(0,i.g2)("text-field"),w=(0,i.g2)("check-box"),C=(0,i.g2)("loading-button"),x=(0,i.g2)("boxed-layout");return(0,i.uX)(),(0,i.Wv)(x,{wide:!0,slotClass:"config-check"},{default:(0,i.k6)(()=>[(0,i.Lk)("header",n,[s[4]||(s[4]=(0,i.Lk)("img",{src:t,width:"80",height:"80",class:"config-check__icon",alt:""},null,-1)),(0,i.Lk)("h1",r,(0,l.v_)(e.$t("ui.server.config.title")),1),(0,i.Lk)("p",a,(0,l.v_)(e.$t("ui.server.config.description")),1)]),(0,i.Lk)("main",d,[(0,i.Lk)("form",{onSubmit:s[3]||(s[3]=(0,o.D$)((...e)=>L.save&&L.save(...e),["prevent"]))},[(0,i.Lk)("fieldset",u,[(0,i.Lk)("legend",g,(0,l.v_)(e.$t("ui.server.config.formTitle")),1),(0,i.Lk)("p",h,(0,l.v_)(e.$t("ui.server.config.formText")),1),(0,i.bF)($,{ref:"cli",name:"php_cli",label:e.$t("ui.server.config.cli"),required:"",disabled:e.processing,error:e.error,modelValue:e.php_cli,"onUpdate:modelValue":s[0]||(s[0]=s=>e.php_cli=s)},null,8,["label","disabled","error","modelValue"])]),(0,i.Lk)("fieldset",f,[(0,i.Lk)("legend",_,(0,l.v_)(e.$t("ui.server.config.cloudTitle")),1),(0,i.Lk)("p",p,(0,l.v_)(e.$t("ui.server.config.cloudText")),1),e.cloudIssues&&e.cloudIssues.length?((0,i.uX)(),(0,i.CE)("div",k,[(0,i.Lk)("p",null,(0,l.v_)(e.$t("ui.server.config.stateErrorCloud")),1),(0,i.Lk)("ul",null,[((0,i.uX)(!0),(0,i.CE)(i.FK,null,(0,i.pI)(e.cloudIssues,(e,s)=>((0,i.uX)(),(0,i.CE)("li",{key:s},(0,l.v_)(e),1))),128))])])):(0,i.Q3)("",!0),(0,i.bF)(w,{name:"cloud",label:e.$t("ui.server.config.cloud"),disabled:e.processing,modelValue:e.cloud,"onUpdate:modelValue":s[1]||(s[1]=s=>e.cloud=s)},null,8,["label","disabled","modelValue"])]),(0,i.bF)(C,{submit:"",color:"primary",disabled:!e.php_cli,loading:e.processing},{default:(0,i.k6)(()=>[(0,i.eW)((0,l.v_)(e.$t("ui.server.config.save")),1)]),_:1},8,["disabled","loading"]),(0,i.Lk)("button",{type:"button",class:"widget-button",disabled:e.processing,onClick:s[2]||(s[2]=(...e)=>L.cancel&&L.cancel(...e))},(0,l.v_)(e.$t("ui.server.config.cancel")),9,v)],32)])]),_:1})}var m=c(728),L=c(9757),$=c(3480),w=c(5506),C=c(707),x={components:{BoxedLayout:m.A,TextField:L.A,CheckBox:$.A,LoadingButton:w.A},data:()=>({processing:!0,error:"",php_cli:"",cloud:!0,cloudIssues:[]}),methods:{async save(){this.processing=!0,this.error="";const e={php_cli:this.php_cli,cloud:this.cloud},s=await this.$store.dispatch("server/config/set",e);400===s.status&&s.detail?(this.error=s.detail,this.processing=!1,setTimeout(()=>{this.$refs.cli.focus()},0)):window.location.reload(!0)},cancel(){this.$store.commit("setView",C.A.BOOT)}},async mounted(){const e=await this.$store.dispatch("server/config/get");this.php_cli=e.php_cli,this.cloud=e.cloud.enabled,this.cloudIssues=e.cloud.issues,this.processing=!1}},y=c(6262);const T=(0,y.A)(x,[["render",b]]);var V=T}}]);"use strict";(self["webpackChunkcontao_manager"]=self["webpackChunkcontao_manager"]||[]).push([[542],{7542:function(e){e.exports=JSON.parse('{"ui.app.title":"Contao 扩展","ui.app.loading":"扩展列表加载中 …","ui.app.language":"Switch language for the Contao Manager","ui.app.colorDark":"Dark Mode","ui.app.colorDarkTitle":"Switch color scheme to dark","ui.app.colorLight":"Light Mode","ui.app.colorLightTitle":"Switch color scheme to light","ui.discover.advertisement":"Advertisement in the extension list","ui.discover.loading":"加载 …","ui.discover.offline":"无法获取任何结果","ui.discover.offlineExplain":"检查网络连接并在浏览器中禁用JavaScript拦截器。","ui.discover.offlineButton":"重试","ui.discover.searchPlaceholder":"Search in {count} extensions …","ui.discover.empty":"No results for {query}","ui.discover.more":"更多","ui.discover.sortBy":"排序","ui.discover.sortReleased":"Released","ui.discover.sortReleasedTitle":"Sort results by release date","ui.discover.sortLatest":"已更新","ui.discover.sortLatestTitle":"Sort results by last updated","ui.discover.sortDownloads":"下载","ui.discover.sortDownloadsTitle":"Sort results by number of downloads","ui.discover.sortFavers":"评级","ui.discover.sortFaversTitle":"Sort results by rating","ui.discover.detailsButton":"详情","ui.discover.latestPackages":"最新和已更新扩展","ui.discover.faversPackages":"最高评级扩展","ui.discover.downloadsPackages":"下载最多扩展","ui.discover.exactHit":"Exact query match","ui.discover.results":"More search results","ui.package.homepage":"项目网站","ui.package.private":"私有包","ui.package.privateTitle":"私有包仅可从提供商获取 (e.g. ZIP 下载)。请访问网站获取更多信息。","ui.package.abandoned":"放弃","ui.package.abandonedText":"该程序包已放弃不再维护。","ui.package.abandonedReplace":"该程序包已放弃不再维护。作者建议使用 {replacement} 包替代.","ui.package.contaoVersion":"Available for Contao","ui.package-details.previous":"以前的扩展详细信息","ui.package-details.close":"关闭扩展详情","ui.package-details.loading":"加载 …","ui.package-details.tabDescription":"描述","ui.package-details.tabRequire":"需求","ui.package-details.tabFeatures":"特征","ui.package-details.tabSuggest":"建议","ui.package-details.tabConflict":"冲突","ui.package-details.tabDependents":"依赖","ui.package-details.linkRequires":"需要","ui.package-details.linkReplaces":"替换","ui.package-details.linkProvides":"提供","ui.package-details.linkConflicts":"冲突","ui.package-details.funding":"Fund package maintenance!","ui.package-details.contaoVersions":"Supported Contao version(s)","ui.package-details.latest":"最新版","ui.package-details.released":"发布于","ui.package-details.license":"许可(s)","ui.package-details.authors":"from","ui.package-details.more":"更多","ui.package-details.packagist":"包详情","ui.package-details.metadata":"编辑元数据","ui.package-details.support_docs":"文档","ui.package-details.support_wiki":"Wiki","ui.package-details.support_forum":"支持论坛","ui.package-details.support_issues":"问题 / 错误 报告","ui.package-details.support_source":"源代码","ui.package-details.support_irc":"IRC / 聊天","ui.package-details.support_email":"支持 E-Mail","ui.package-details.support_rss":"RSS"}')}}]);"use strict";(self["webpackChunkcontao_manager"]=self["webpackChunkcontao_manager"]||[]).push([[120,756],{4686:function(e,t){var s=this&&this.__extends||function(){var e=function(t,s){return e=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var s in t)Object.prototype.hasOwnProperty.call(t,s)&&(e[s]=t[s])},e(t,s)};return function(t,s){if("function"!==typeof s&&null!==s)throw new TypeError("Class extends value "+String(s)+" is not a constructor or null");function i(){this.constructor=t}e(t,s),t.prototype=null===s?Object.create(s):(i.prototype=s.prototype,new i)}}();Object.defineProperty(t,"__esModule",{value:!0}),t.treeifyPaths=t.Node=t.PathTree=void 0;var i=function(){function e(e){void 0===e&&(e=""),this.path=e,this.name="",this.children=[]}return e}();t.PathTree=i;var a=function(e){function t(){return null!==e&&e.apply(this,arguments)||this}return s(t,e),t}(i);function o(e,t,s){void 0===s&&(s={});var a={};t.forEach(function(t){var s=t[0],o=t[1],n=r(s).split("/"),l=n[0];if(!a[l]){var u="".concat(e.path,"/").concat(n[0]);a[l]={paths:[],obj:new i(r(u))}}if(1==n.length)a[l].obj.name=l,a[l].obj.ctx=o;else{n.shift();var c=n.join("/");a[l].paths.push([c,o]),a[l].obj.ctx=o}});var n=Object.keys(a);return s.caseInsensitive?n.sort(function(e,t){return e.toLocaleLowerCase().localeCompare(t.toLocaleLowerCase())}):n.sort(),n.forEach(function(t){var i=a[t].obj;o(i,a[t].paths,s),(i.name||i.path||i.children.length)&&e.children.push(i)}),s.directoriesFirst?e.children.sort(function(e,t){return e.children.length&&!t.children.length?-1:t.children.length&&!e.children.length?1:0}):s.directoriesLast&&e.children.sort(function(e,t){return e.children.length&&!t.children.length?1:t.children.length&&!e.children.length?-1:0}),e}function n(e,t){void 0===e&&(e=[]),void 0===t&&(t={});var s=l(e)?e.map(function(e){return[e,void 0]}):e;return o(new i,s,t)}t.Node=a,t.treeifyPaths=n,t["default"]=n;var r=function(e){return e.replace(/^\/*/,"").replace(/\/*$/,"")},l=function(e){return"string"===typeof e[0]}},8938:function(e,t,s){s.r(t),s.d(t,{default:function(){return yi}});var i=s(641),a=s(33),o=s(3382),n=s(6894);const r={key:0,class:"view-setup__steps"},l=["onClick","disabled"],u=["src"],c={key:1,class:"view-setup__main"},d={class:"view-setup__headline"},p={class:"view-setup__description"},h={class:"view-setup__description"},m={href:"/contao/install",class:"widget-button widget-button--primary view-setup__continue"},_={class:"view-setup__description"},v={href:"/contao",class:"widget-button widget-button--primary view-setup__continue"},k={class:"view-setup__funding"},b={class:"view-setup__funding-link widget-button widget-button--small widget-button--funding widget-button--link",href:"https://to.contao.org/donate",target:"_blank"},g={key:3,class:"view-setup__main"},f={class:"view-setup__headline"},y={class:"view-setup__description"},w={href:"https://to.contao.org/support",target:"_blank"};function L(e,t,s,L,$,C){const E=(0,i.g2)("i18n-t"),X=(0,i.g2)("boxed-layout");return(0,i.uX)(),(0,i.Wv)(X,{wide:!0,slotClass:"view-setup"},{default:(0,i.k6)(()=>[C.currentStep>0?((0,i.uX)(),(0,i.CE)("section",r,[(0,i.Lk)("ul",null,[((0,i.uX)(!0),(0,i.CE)(i.FK,null,(0,i.pI)(C.steps,(e,t)=>((0,i.uX)(),(0,i.CE)("li",{class:(0,a.C4)({active:C.currentStep>t}),key:e.name},[(0,i.Lk)("button",{onClick:e=>C.currentStep=t+1,disabled:C.currentStep<=t+1},[(0,i.Lk)("img",{src:e.icon,width:"24",height:"24",alt:""},null,8,u)],8,l)],2))),128)),(0,i.Lk)("li",{class:(0,a.C4)({active:C.currentStep>C.steps.length})},[...t[4]||(t[4]=[(0,i.Lk)("button",{disabled:""},[(0,i.Lk)("svg",{xmlns:"http://www.w3.org/2000/svg",height:"24px",viewBox:"0 0 24 24",width:"24px"},[(0,i.Lk)("path",{d:"M0 0h24v24H0z",fill:"none"}),(0,i.Lk)("path",{d:"M9 16.2L4.8 12l-1.4 1.4L9 19 21 7l-1.4-1.4L9 16.2z"})])],-1)])],2)])])):(0,i.Q3)("",!0),C.currentStep>C.steps.length?((0,i.uX)(),(0,i.CE)("main",c,[t[6]||(t[6]=(0,i.Lk)("span",{class:"view-setup__party"},"🎉",-1)),(0,i.Lk)("h1",d,(0,a.v_)(e.$t("ui.setup.complete")),1),(0,i.Lk)("p",p,(0,a.v_)(e.$t("ui.setup.complete1",{version:e.contaoVersion})),1),e.showInstallTool?((0,i.uX)(),(0,i.CE)(i.FK,{key:0},[(0,i.Lk)("p",h,(0,a.v_)(e.$t("ui.setup.complete2")),1),(0,i.Lk)("button",{class:"widget-button widget-button--inline",onClick:t[0]||(t[0]=(...e)=>C.launch&&C.launch(...e))},(0,a.v_)(e.$t("ui.setup.manager")),1),(0,i.Lk)("a",m,(0,a.v_)(e.$t("ui.setup.installTool")),1)],64)):((0,i.uX)(),(0,i.CE)(i.FK,{key:1},[(0,i.Lk)("p",_,(0,a.v_)(e.$t("ui.setup.complete3")),1),(0,i.Lk)("button",{class:"widget-button view-setup__continue",onClick:t[1]||(t[1]=(...e)=>C.launch&&C.launch(...e))},(0,a.v_)(e.$t("ui.setup.manager")),1),(0,i.Lk)("a",v,(0,a.v_)(e.$t("ui.setup.login")),1)],64)),(0,i.Lk)("div",k,[t[5]||(t[5]=(0,i.Lk)("figure",null,[(0,i.Lk)("img",{src:o,width:"80",height:"80",alt:""})],-1)),(0,i.Lk)("div",null,[((0,i.uX)(!0),(0,i.CE)(i.FK,null,(0,i.pI)(e.$t("ui.setup.funding").split("\n"),(e,t)=>((0,i.uX)(),(0,i.CE)("p",{key:t},(0,a.v_)(e),1))),128)),(0,i.Lk)("p",null,[(0,i.Lk)("a",b,(0,a.v_)(e.$t("ui.setup.fundingLink")),1)])])])])):C.currentStep>0?((0,i.uX)(),(0,i.Wv)((0,i.$y)(C.steps[C.currentStep-1].component),{key:2,onContinue:t[2]||(t[2]=e=>C.currentStep+=1)},null,32)):((0,i.uX)(),(0,i.CE)("main",g,[t[7]||(t[7]=(0,i.Lk)("img",{src:n,width:"100",height:"100",alt:"Contao Logo",class:"view-setup__icon"},null,-1)),(0,i.Lk)("h1",f,(0,a.v_)(e.$t("ui.setup.welcome")),1),(0,i.Lk)("p",y,(0,a.v_)(e.$t("ui.setup.welcome1")),1),(0,i.bF)(E,{tag:"p",class:"view-setup__description",keypath:"ui.setup.welcome2"},{support:(0,i.k6)(()=>[(0,i.Lk)("a",w,(0,a.v_)(e.$t("ui.setup.support")),1)]),_:1}),(0,i.Lk)("button",{class:"widget-button widget-button--inline widget-button--primary view-setup__start",onClick:t[3]||(t[3]=e=>C.currentStep=1)},(0,a.v_)(e.$t("ui.setup.start")),1)]))]),_:1})}s(4114);var $=s(707),C=s(6278),E=s(728),X=s(3751),j=s.p+"img/document-root.0e6dd2e4.svg",F=s.p+"img/button-update.ad79c617.svg";const A={class:"setup__header"},V={class:"setup__headline"},U={key:0,class:"setup__warning"},x={class:"setup__description"},D={class:"setup__description"},S=["href"],P={class:"setup__form setup__form--center",key:"updated"},T={class:"setup__fields"},W={class:"setup__fielddesc"},I={class:"setup__directories"},q={key:0},H={key:1},R={key:2},B={key:3},M={key:4},O={key:5},Q={key:6},K={class:"setup__actions setup__actions--center"},J={class:"setup__form",key:"conflicts"},N={class:"setup__fields"},z={class:"setup__fieldtitle"},Z={class:"setup__fielddesc"},Y={key:0},G={class:"setup__actions setup__actions--center"},ee=["disabled"],te={class:"setup__form",key:"setup"},se={class:"setup__fields"},ie={class:"setup__fieldtitle"},ae={class:"setup__fielddesc"},oe={class:"setup__directories"},ne={key:0},re={key:1},le={key:2},ue={key:3},ce={key:4},de={key:5},pe={key:6},he={class:"setup__actions setup__actions--center"},me=["disabled"],_e={class:"setup__form",key:"confirmation"},ve={class:"setup__fields setup__fields--center"},ke={class:"setup__fielddesc"},be={class:"setup__actions setup__actions--center"};function ge(e,t,s,o,n,r){const l=(0,i.g2)("loading-button"),u=(0,i.g2)("check-box"),c=(0,i.g2)("text-field"),d=(0,i.g2)("radio-button"),p=(0,i.g2)("i18n-t");return(0,i.uX)(),(0,i.CE)("section",null,[(0,i.Lk)("header",A,[t[10]||(t[10]=(0,i.Lk)("img",{src:j,width:"80",height:"80",alt:"",class:"setup__icon"},null,-1)),(0,i.Lk)("h1",V,(0,a.v_)(e.$t("ui.setup.document-root.headline")),1),r.needsFix?((0,i.uX)(),(0,i.CE)("p",U,(0,a.v_)(e.$t("ui.setup.document-root.warning")),1)):(0,i.Q3)("",!0),(0,i.Lk)("p",x,(0,a.v_)(e.$t("ui.setup.document-root.description1")),1),(0,i.Lk)("p",D,(0,a.v_)(e.$t("ui.setup.document-root.description2")),1),(0,i.Lk)("a",{class:"widget-button widget-button--inline widget-button--info widget-button--link",href:`https://to.contao.org/docs/webroot?lang=${e.$i18n.locale}`,target:"_blank"},(0,a.v_)(e.$t("ui.setup.document-root.documentation")),9,S)]),null!==e.projectDir?((0,i.uX)(),(0,i.Wv)(X.eB,{key:0,name:e.forceInstall?"none":"animate-flip",type:"transition",mode:"out-in"},{default:(0,i.k6)(()=>[r.needsFix||e.wantsFix?((0,i.uX)(),(0,i.CE)(i.FK,{key:0},[e.directoryUpdated?((0,i.uX)(),(0,i.CE)("main",P,[(0,i.Lk)("div",T,[t[13]||(t[13]=(0,i.Lk)("svg",{class:"setup__check",xmlns:"http://www.w3.org/2000/svg",width:"24",height:"24",viewBox:"0 0 24 24"},[(0,i.Lk)("path",{d:"M12,2A10,10 0 0,1 22,12A10,10 0 0,1 12,22A10,10 0 0,1 2,12A10,10 0 0,1 12,2M12,4A8,8 0 0,0 4,12A8,8 0 0,0 12,20A8,8 0 0,0 20,12A8,8 0 0,0 12,4M11,16.5L6.5,12L7.91,10.59L11,13.67L16.59,8.09L18,9.5L11,16.5Z"})],-1)),(0,i.Lk)("p",W,(0,a.v_)(e.$t("ui.setup.document-root.confirmation")),1),(0,i.Lk)("dl",I,[(0,i.Lk)("dt",null,(0,a.v_)(e.$t("ui.setup.document-root.currentRoot")),1),e.isWeb?((0,i.uX)(),(0,i.CE)("dd",q,(0,a.v_)(e.projectDir)+"/web",1)):e.isPublic?((0,i.uX)(),(0,i.CE)("dd",H,(0,a.v_)(e.projectDir)+"/public",1)):((0,i.uX)(),(0,i.CE)("dd",R,(0,a.v_)(e.projectDir),1)),(0,i.Lk)("dt",null,(0,a.v_)(e.$t("ui.setup.document-root.newRoot")),1),!e.isEmpty||e.wantsFix&&e.directory||!r.canUsePublicDir||!e.usePublicDir?!e.isEmpty||e.wantsFix&&e.directory?r.canUsePublicDir&&e.usePublicDir?((0,i.uX)(),(0,i.CE)("dd",O,[(0,i.eW)((0,a.v_)(e.projectDir),1),(0,i.Lk)("span",null,"/"+(0,a.v_)(e.directory)+"/public",1)])):((0,i.uX)(),(0,i.CE)("dd",Q,[(0,i.eW)((0,a.v_)(e.projectDir),1),(0,i.Lk)("span",null,"/"+(0,a.v_)(e.directory)+"/web",1)])):((0,i.uX)(),(0,i.CE)("dd",M,[(0,i.eW)((0,a.v_)(e.projectDir),1),t[12]||(t[12]=(0,i.Lk)("span",null,"/web",-1))])):((0,i.uX)(),(0,i.CE)("dd",B,[(0,i.eW)((0,a.v_)(e.projectDir),1),t[11]||(t[11]=(0,i.Lk)("span",null,"/public",-1))]))])]),(0,i.Lk)("div",K,[(0,i.bF)(l,{inline:"",loading:e.processing,color:"primary",icon:"update",onClick:r.reload},{default:(0,i.k6)(()=>[(0,i.eW)((0,a.v_)(e.$t("ui.setup.document-root.reload")),1)]),_:1},8,["loading","onClick"])])])):e.conflicts.length?((0,i.uX)(),(0,i.CE)("main",J,[(0,i.Lk)("div",N,[(0,i.Lk)("h2",z,(0,a.v_)(e.$t("ui.setup.document-root.conflictsTitle")),1),(0,i.Lk)("p",Z,(0,a.v_)(e.$t("ui.setup.document-root.conflictsDirectory",{count:e.conflicts.length})),1),(0,i.Lk)("ul",null,[((0,i.uX)(!0),(0,i.CE)(i.FK,null,(0,i.pI)(e.conflicts.slice(0,5),e=>((0,i.uX)(),(0,i.CE)("li",{key:e},(0,a.v_)(e),1))),128)),e.conflicts.length>5?((0,i.uX)(),(0,i.CE)("li",Y,"...")):(0,i.Q3)("",!0)]),e.isPublic||e.isWeb?((0,i.uX)(),(0,i.Wv)(u,{key:0,name:"ignoreConflicts",label:e.$t("ui.setup.document-root.ignoreConflicts"),disabled:e.processing,modelValue:e.forceInstall,"onUpdate:modelValue":t[0]||(t[0]=t=>e.forceInstall=t)},null,8,["label","disabled","modelValue"])):(0,i.Q3)("",!0)]),(0,i.Lk)("div",G,[e.forceInstall?((0,i.uX)(),(0,i.CE)("button",{key:0,class:"widget-button widget-button--alert widget-button--run",onClick:t[1]||(t[1]=t=>e.$emit("continue"))},(0,a.v_)(e.$t("ui.server.contao.setup")),1)):((0,i.uX)(),(0,i.CE)(i.FK,{key:1},[(0,i.bF)(l,{inline:"",icon:"update",loading:e.processing,onClick:t[2]||(t[2]=e=>r.init(!1))},{default:(0,i.k6)(()=>[(0,i.eW)((0,a.v_)(e.$t("ui.setup.document-root.check")),1)]),_:1},8,["loading"]),(0,i.Lk)("button",{class:"widget-button widget-button--inline widget-button--primary widget-button--gear",disabled:e.processing,onClick:t[3]||(t[3]=t=>e.conflicts=[])},(0,a.v_)(e.$t("ui.setup.document-root.create")),9,ee)],64))])])):((0,i.uX)(),(0,i.CE)("main",te,[t[14]||(t[14]=(0,i.Lk)("img",{src:F,class:"invisible",alt:""},null,-1)),(0,i.Lk)("div",se,[(0,i.Lk)("h2",ie,(0,a.v_)(e.$t("ui.setup.document-root.formTitle")),1),(0,i.Lk)("p",ae,[(0,i.eW)((0,a.v_)(e.$t("ui.setup.document-root.formText1"))+" ",1),(0,i.Lk)("u",null,(0,a.v_)(e.$t("ui.setup.document-root.formText2")),1)]),!e.isEmpty||e.wantsFix?((0,i.uX)(),(0,i.Wv)(c,{key:0,ref:"directory",name:"directory",label:e.$t("ui.setup.document-root.directory"),error:r.directoryError,required:!e.isEmpty,pattern:"^[^/]+$",validate:"",modelValue:e.directory,"onUpdate:modelValue":t[4]||(t[4]=t=>e.directory=t)},null,8,["label","error","required","modelValue"])):(0,i.Q3)("",!0),r.canUsePublicDir?((0,i.uX)(),(0,i.Wv)(d,{key:1,name:"usePublicDir",options:r.publicDirOptions,"allow-html":"",modelValue:e.usePublicDir,"onUpdate:modelValue":t[5]||(t[5]=t=>e.usePublicDir=t)},null,8,["options","modelValue"])):(0,i.Q3)("",!0),(0,i.Lk)("dl",oe,[(0,i.Lk)("dt",null,(0,a.v_)(e.$t("ui.setup.document-root.currentRoot")),1),e.isWeb?((0,i.uX)(),(0,i.CE)("dd",ne,(0,a.v_)(e.projectDir)+(0,a.v_)(e.directorySeparator)+"web",1)):e.isPublic?((0,i.uX)(),(0,i.CE)("dd",re,(0,a.v_)(e.projectDir)+(0,a.v_)(e.directorySeparator)+"public",1)):((0,i.uX)(),(0,i.CE)("dd",le,(0,a.v_)(e.projectDir),1)),(0,i.Lk)("dt",null,(0,a.v_)(e.$t("ui.setup.document-root.newRoot")),1),!e.isEmpty||e.wantsFix&&e.directory||!r.canUsePublicDir||!e.usePublicDir?!e.isEmpty||e.wantsFix&&e.directory?r.canUsePublicDir&&e.usePublicDir?((0,i.uX)(),(0,i.CE)("dd",de,[(0,i.eW)((0,a.v_)(e.projectDir),1),(0,i.Lk)("span",null,(0,a.v_)(e.directorySeparator)+(0,a.v_)(e.directory)+(0,a.v_)(e.directorySeparator)+"public",1)])):((0,i.uX)(),(0,i.CE)("dd",pe,[(0,i.eW)((0,a.v_)(e.projectDir),1),(0,i.Lk)("span",null,(0,a.v_)(e.directorySeparator)+(0,a.v_)(e.directory)+(0,a.v_)(e.directorySeparator)+"web",1)])):((0,i.uX)(),(0,i.CE)("dd",ce,[(0,i.eW)((0,a.v_)(e.projectDir),1),(0,i.Lk)("span",null,(0,a.v_)(e.directorySeparator)+"web",1)])):((0,i.uX)(),(0,i.CE)("dd",ue,[(0,i.eW)((0,a.v_)(e.projectDir),1),(0,i.Lk)("span",null,(0,a.v_)(e.directorySeparator)+"public",1)]))]),(0,i.bF)(u,{name:"autoconfig",label:e.$t("ui.setup.document-root.autoconfig"),disabled:e.processing,modelValue:e.autoconfig,"onUpdate:modelValue":t[6]||(t[6]=t=>e.autoconfig=t)},null,8,["label","disabled","modelValue"])]),(0,i.Lk)("div",he,[(0,i.bF)(l,{color:"primary",icon:"run",loading:e.processing,disabled:!e.autoconfig||!!r.directoryError||e.wantsFix&&!e.directory&&(e.isPublic&&e.usePublicDir||e.isWeb&&!e.usePublicDir),onClick:r.setupDocroot},{default:(0,i.k6)(()=>[(0,i.eW)((0,a.v_)(e.$t("ui.setup.document-root.finish")),1)]),_:1},8,["loading","disabled","onClick"]),e.wantsFix?((0,i.uX)(),(0,i.CE)("button",{key:0,type:"button",class:"widget-button",disabled:e.processing,onClick:t[7]||(t[7]=(...e)=>r.init&&r.init(...e))},(0,a.v_)(e.$t("ui.setup.cancel")),9,me)):(0,i.Q3)("",!0)])]))],64)):((0,i.uX)(),(0,i.CE)("main",_e,[(0,i.Lk)("div",ve,[t[15]||(t[15]=(0,i.Lk)("svg",{class:"setup__check",xmlns:"http://www.w3.org/2000/svg",width:"24",height:"24",viewBox:"0 0 24 24"},[(0,i.Lk)("path",{d:"M12,2A10,10 0 0,1 22,12A10,10 0 0,1 12,22A10,10 0 0,1 2,12A10,10 0 0,1 12,2M12,4A8,8 0 0,0 4,12A8,8 0 0,0 12,20A8,8 0 0,0 20,12A8,8 0 0,0 12,4M11,16.5L6.5,12L7.91,10.59L11,13.67L16.59,8.09L18,9.5L11,16.5Z"})],-1)),(0,i.Lk)("p",ke,(0,a.v_)(e.$t("ui.setup.document-root.success")),1),(0,i.bF)(p,{tag:"p",class:"setup__fielddesc",keypath:`ui.setup.document-root.${e.contaoVersion?"installed":"installing"}ProjectDir`},{dir:(0,i.k6)(()=>[(0,i.Lk)("code",null,(0,a.v_)(e.projectDir),1)]),_:1},8,["keypath"]),(0,i.bF)(p,{tag:"p",class:"setup__fielddesc",keypath:`ui.setup.document-root.${e.contaoVersion?"installed":"installing"}PublicDir`},{dir:(0,i.k6)(()=>[(0,i.Lk)("code",null,(0,a.v_)(r.publicDir),1)]),_:1},8,["keypath"])]),(0,i.Lk)("div",be,[e.contaoVersion?(0,i.Q3)("",!0):((0,i.uX)(),(0,i.CE)("button",{key:0,class:"widget-button widget-button--inline widget-button--gear",onClick:t[8]||(t[8]=t=>e.wantsFix=!0)},(0,a.v_)(e.$t("ui.setup.document-root.change")),1)),(0,i.Lk)("button",{class:"widget-button widget-button--inline widget-button--primary",onClick:t[9]||(t[9]=t=>e.$emit("continue"))},(0,a.v_)(e.$t("ui.setup.continue")),1)])]))]),_:1},8,["name"])):(0,i.Q3)("",!0)])}var fe=s(9757);const ye={key:0},we=["id","name","disabled","required","checked","onClick"],Le=["for","innerHTML"],$e=["for"];function Ce(e,t,s,o,n,r){return(0,i.uX)(),(0,i.CE)("fieldset",{class:(0,a.C4)(["widget widget-radio-button",{"widget--required":s.required}])},[s.label||e.$slots.label?((0,i.uX)(),(0,i.CE)("legend",ye,[(0,i.RG)(e.$slots,"label",{},()=>[(0,i.eW)((0,a.v_)(s.label),1)])])):(0,i.Q3)("",!0),((0,i.uX)(!0),(0,i.CE)(i.FK,null,(0,i.pI)(s.options,(e,t)=>((0,i.uX)(),(0,i.CE)("div",{key:t},[(0,i.Lk)("input",{ref_for:!0,ref:"input",type:"radio",id:`ctrl_${s.name}_${e.value}`,name:s.name,disabled:e.disabled,required:s.required,checked:s.modelValue===e.value,onClick:t=>r.input(e.value)},null,8,we),s.allowHtml?((0,i.uX)(),(0,i.CE)("label",{key:0,for:`ctrl_${s.name}_${e.value}`,innerHTML:e.label},null,8,Le)):((0,i.uX)(),(0,i.CE)("label",{key:1,for:`ctrl_${s.name}_${e.value}`},(0,a.v_)(e.label),9,$e))]))),128))],2)}var Ee={emits:["input","update:modelValue"],props:{name:{type:String,required:!0},options:{type:Array,required:!0},label:String,modelValue:{required:!0},disabled:Boolean,required:Boolean,allowHtml:{type:Boolean,default:!1}},methods:{input(e){this.$emit("input"),this.$emit("update:modelValue",e)}}},Xe=s(6262);const je=(0,Xe.A)(Ee,[["render",Ce]]);var Fe=je,Ae=s(3480),Ve=s(5506),Ue={components:{TextField:fe.A,RadioButton:Fe,CheckBox:Ae.A,LoadingButton:Ve.A},data:()=>({processing:!1,usePublicDir:!1,wantsFix:!1,conflicts:[],isEmpty:!0,isWeb:!0,isPublic:!1,projectDir:null,autoconfig:!1,forceInstall:!1,directory:"",directoryExists:!1,directoryUpdated:!1,directorySeparator:"/"}),computed:{...(0,C.aH)("server/php-web",["phpVersionId"]),...(0,C.aH)("server/contao",["contaoVersion"]),needsFix:e=>!e.isEmpty||!e.isWeb&&(!e.isPublic||!e.canUsePublicDir),publicDirOptions:e=>[{label:e.$t("ui.setup.document-root.publicDir",{dir:"<code>web</code>",version:"4.9+"}),value:!1},{label:e.$t("ui.setup.document-root.publicDir",{dir:"<code>public</code>",version:"4.13+"}),value:!0}],canUsePublicDir:e=>e.phpVersionId>=70400,publicDir:e=>e.isWeb?`${e.projectDir}${e.directorySeparator}web`:`${e.projectDir}${e.directorySeparator}public`,directoryError(){return this.directoryExists?this.$t("ui.setup.document-root.directoryExists"):this.directory&&!this.directory.match(/^[^/]+$/)?this.$t("ui.setup.document-root.directoryInvalid"):this.wantsFix||this.isEmpty||this.directory?"":this.$t("ui.setup.document-root.directoryInvalid")}},methods:{reload(){this.processing=!0,window.location.reload()},async setupDocroot(){this.processing=!0;const e=await this.$store.dispatch("server/contao/documentRoot",{directory:!this.isEmpty||this.wantsFix?this.directory:null,usePublicDir:this.canUsePublicDir&&this.usePublicDir});if(403===e.status)return this.directoryExists=!0,this.processing=!1,void this.$refs.directory.focus();this.processing=!1,this.directoryUpdated=!0,this.$store.commit("auth/resetCountdown")},async init(e=!0){this.processing=!0;const t=await this.$store.dispatch("server/contao/get",e);this.projectDir=t.data.project_dir,this.conflicts=t.data.conflicts,this.isEmpty=0===t.data.conflicts.length,this.isWeb="web"===t.data.public_dir,this.isPublic="public"===t.data.public_dir,this.usePublicDir="public"===t.data.public_dir,this.wantsFix=!1,this.directory=this.isEmpty?"":location.hostname,this.directorySeparator=t.data.directory_separator,this.processing=!1}},watch:{directory(){this.directoryExists=!1}},async mounted(){this.init()}};const xe=(0,Xe.A)(Ue,[["render",ge]]);var De=xe,Se=(s(8111),s(1701),s.p+"img/create-project.b22522ee.svg"),Pe=s(7591);const Te={key:0,class:"setup__theme-upload"},We={key:1},Ie=["disabled"],qe={class:"setup__header"},He=["src","alt"],Re={key:1,src:Se,width:"80",height:"80",alt:"",class:"setup__icon"},Be={class:"setup__headline"},Me={class:"setup__description"},Oe={class:"setup__version"},Qe={class:"setup__version"},Ke={key:2,class:"setup__version"},Je={key:3,class:"setup__version"},Ne={key:4,class:"setup__version"},ze=["href"],Ze={class:"setup__form"},Ye={key:0,class:"setup__fields"},Ge={class:"setup__fieldtitle"},et={class:"setup__fielddesc"},tt={class:"setup__tabs"},st={class:"setup__tab-controls"},it={key:0,class:"setup__tab"},at={class:"setup__requires"},ot={key:1,class:"setup__tab setup__tab--files"},nt={class:"setup__fielddesc setup__fielddesc--warning"},rt={class:"setup__actions"},lt=["disabled"],ut={class:"setup__header"},ct={class:"setup__headline"},dt={href:"https://semver.org",target:"_blank",rel:"noreferrer noopener"},pt={class:"setup__versions"},ht={class:"setup__version--warning"},mt=["href"],_t={key:0,class:"setup__form"},vt={class:"setup__fields setup__fields--center"},kt={class:"setup__fielddesc"},bt={class:"setup__actions setup__actions--center"},gt={key:1,class:"setup__form"},ft={class:"setup__fields"},yt={class:"setup__fieldtitle"},wt={class:"setup__fielddesc setup__fielddesc--version"},Lt={key:0,class:"setup__theme"},$t={href:"https://themes.contao.org",target:"_blank"},Ct={class:"package-uploads__overlay"},Et={href:"https://themes.contao.org",target:"_blank"},Xt={class:"setup__fields"},jt={class:"setup__or"},Ft=["disabled"],At=["disabled"],Vt={key:2,class:"setup__themes"},Ut={key:1,class:"setup__theme-search setup__theme-search--offline"},xt={key:2,class:"setup__theme-search setup__theme-search--empty"},Dt={class:"setup__themes-results"},St={class:"setup__themes-more"};function Pt(e,t,s,o,n,r){const l=(0,i.g2)("file-upload"),u=(0,i.g2)("progress-bar"),c=(0,i.g2)("console-output"),d=(0,i.g2)("file-tree"),p=(0,i.g2)("loading-button"),h=(0,i.g2)("i18n-t"),m=(0,i.g2)("radio-button"),_=(0,i.g2)("check-box"),v=(0,i.g2)("search-input"),k=(0,i.g2)("button-group"),b=(0,i.g2)("loading-spinner"),g=(0,i.g2)("discover-package");return(0,i.uX)(),(0,i.CE)("div",null,[(0,i.bF)(l,{name:"package",ref:"uploader","post-action":"api/packages/uploads",multiple:!0,drop:!0,"drop-directory":!1,"chunk-enabled":!0,chunk:{action:"api/packages/uploads"},onInputFile:r.uploadTheme,onInputFilter:r.filterTheme},null,8,["onInputFile","onInputFilter"]),e.upload?((0,i.uX)(),(0,i.CE)("main",Te,[(0,i.Lk)("h1",null,(0,a.v_)(e.$t("ui.setup.create-project.theme.upload",{name:e.upload.name,size:r.uploadSize})),1),(0,i.bF)(u,{amount:e.upload.progress,color:e.upload.active||e.upload.success?"":"alert"},null,8,["amount","color"]),e.upload.active||e.upload.success?(0,i.Q3)("",!0):((0,i.uX)(),(0,i.CE)(i.FK,{key:0},[t[13]||(t[13]=(0,i.Lk)("br",null,null,-1)),e.upload.response.exception?((0,i.uX)(),(0,i.Wv)(c,{key:0,title:e.$t(`ui.setup.create-project.${e.upload.response.error}Error`,{file:e.upload.name}),operations:[{status:"error",summary:`composer validate ${e.upload.name}#composer.json`,console:e.upload.response.exception}],"console-output":e.upload.response.exception,"force-console":!0},null,8,["title","operations","console-output"])):((0,i.uX)(),(0,i.CE)("p",We,(0,a.v_)(e.$t(`ui.setup.create-project.${e.upload.response.error}Error`,{file:e.upload.name})),1)),t[14]||(t[14]=(0,i.Lk)("br",null,null,-1)),(0,i.Lk)("button",{class:"widget-button widget-button--inline",onClick:t[0]||(t[0]=(...e)=>r.cancelTheme&&r.cancelTheme(...e)),disabled:e.processing},(0,a.v_)(e.$t("ui.setup.create-project.cancel")),9,Ie)],64))])):e.theme?((0,i.uX)(),(0,i.CE)(i.FK,{key:1},[(0,i.Lk)("header",qe,[e.themeImage?((0,i.uX)(),(0,i.CE)("img",{key:0,class:"setup__theme-image",src:e.themeImage,alt:e.theme.composerJson.name},null,8,He)):((0,i.uX)(),(0,i.CE)("img",Re)),(0,i.Lk)("h1",Be,(0,a.v_)(e.$t("ui.setup.create-project.headline")),1),(0,i.Lk)("p",Me,(0,a.v_)(e.$t("ui.setup.create-project.theme.uploaded")),1),(0,i.Lk)("div",Oe,[(0,i.Lk)("strong",null,(0,a.v_)(e.$t("ui.setup.create-project.theme.packageName"))+":",1),(0,i.eW)(" "+(0,a.v_)(e.theme.composerJson.name),1)]),(0,i.Lk)("div",Qe,[(0,i.Lk)("strong",null,(0,a.v_)(e.$t("ui.setup.create-project.theme.version"))+":",1),(0,i.eW)(" "+(0,a.v_)(e.theme.composerJson.version),1)]),e.theme.composerJson.authors||e.theme.authors?((0,i.uX)(),(0,i.CE)("div",Ke,[(0,i.Lk)("strong",null,(0,a.v_)(e.$t("ui.setup.create-project.theme.authors"))+": ",1),e.theme.composerJson.authors?((0,i.uX)(),(0,i.CE)(i.FK,{key:0},[(0,i.eW)((0,a.v_)(e.theme.composerJson.authors.map(e=>e.name).join(", ")),1)],64)):((0,i.uX)(),(0,i.CE)(i.FK,{key:1},[(0,i.eW)((0,a.v_)(e.theme.authors),1)],64))])):(0,i.Q3)("",!0),e.theme.composerJson.license?((0,i.uX)(),(0,i.CE)("div",Je,[(0,i.Lk)("strong",null,(0,a.v_)(e.$t("ui.package-details.license"))+":",1),(0,i.eW)(" "+(0,a.v_)(Array.isArray(e.theme.composerJson.license)?e.theme.composerJson.license.join(", "):e.theme.composerJson.license),1)])):(0,i.Q3)("",!0),e.theme.composerJson.homepage?((0,i.uX)(),(0,i.CE)("div",Ne,[(0,i.Lk)("strong",null,(0,a.v_)(e.$t("ui.package.homepage"))+": ",1),(0,i.Lk)("a",{href:e.theme.composerJson.homepage,target:"_blank"},(0,a.v_)(e.theme.composerJson.homepage),9,ze)])):(0,i.Q3)("",!0),(0,i.Lk)("button",{class:"widget-button widget-button--info widget-button--details",onClick:t[1]||(t[1]=(...e)=>r.themeDetails&&r.themeDetails(...e))},(0,a.v_)(e.$t("ui.package.detailsButton")),1)]),(0,i.Lk)("main",Ze,[e.theme.files?((0,i.uX)(),(0,i.CE)("div",Ye,[(0,i.Lk)("h2",Ge,(0,a.v_)(e.$t("ui.setup.create-project.themeTitle")),1),(0,i.Lk)("p",et,(0,a.v_)(e.$t("ui.setup.create-project.themeDetails")),1),(0,i.Lk)("div",tt,[(0,i.Lk)("div",st,[(0,i.Lk)("button",{class:(0,a.C4)(["setup__tab-control",{"setup__tab-control--active":"require"===e.view}]),onClick:t[2]||(t[2]=t=>e.view="require")},(0,a.v_)(e.$tc("ui.setup.create-project.themeRequire",Object.keys(e.theme.composerJson.require).length)),3),(0,i.Lk)("button",{class:(0,a.C4)(["setup__tab-control",{"setup__tab-control--active":"files"===e.view}]),onClick:t[3]||(t[3]=t=>e.view="files")},(0,a.v_)(e.$tc("ui.setup.create-project.themeFiles",e.theme.files.length)),3)]),"require"===e.view?((0,i.uX)(),(0,i.CE)("div",it,[(0,i.Lk)("table",at,[(0,i.Lk)("tbody",null,[((0,i.uX)(!0),(0,i.CE)(i.FK,null,(0,i.pI)(e.theme.composerJson.require,(e,t)=>((0,i.uX)(),(0,i.CE)("tr",{key:t},[(0,i.Lk)("td",null,(0,a.v_)(t)+":",1),(0,i.Lk)("td",null,(0,a.v_)(e),1)]))),128))])])])):(0,i.Q3)("",!0),"files"===e.view?((0,i.uX)(),(0,i.CE)("div",ot,[(0,i.bF)(d,{files:r.themeFiles},null,8,["files"])])):(0,i.Q3)("",!0)]),(0,i.Lk)("p",nt,(0,a.v_)(e.$t("ui.setup.create-project.themeWarning")),1)])):(0,i.Q3)("",!0),(0,i.Lk)("div",rt,[(0,i.bF)(p,{color:"primary",icon:"run",loading:e.processing,onClick:r.installTheme},{default:(0,i.k6)(()=>[(0,i.eW)((0,a.v_)(e.$t("ui.setup.create-project.install")),1)]),_:1},8,["loading","onClick"]),(0,i.Lk)("button",{class:"widget-button",onClick:t[4]||(t[4]=(...e)=>r.cancelTheme&&r.cancelTheme(...e)),disabled:e.processing},(0,a.v_)(e.$t("ui.setup.create-project.cancel")),9,lt)])])],64)):((0,i.uX)(),(0,i.CE)(i.FK,{key:2},[(0,i.Lk)("header",ut,[t[17]||(t[17]=(0,i.Lk)("img",{src:Se,width:"80",height:"80",alt:"",class:"setup__icon"},null,-1)),(0,i.Lk)("h1",ct,(0,a.v_)(e.$t("ui.setup.create-project.headline")),1),(0,i.bF)(h,{tag:"p",keypath:"ui.setup.create-project.description",class:"setup__description"},{semver:(0,i.k6)(()=>[(0,i.Lk)("a",dt,(0,a.v_)(e.$t("ui.setup.create-project.semver")),1)]),_:1}),(0,i.Lk)("ul",pt,[((0,i.uX)(!0),(0,i.CE)(i.FK,null,(0,i.pI)(r.versions,e=>((0,i.uX)(),(0,i.CE)(i.FK,null,[e.disabled?((0,i.uX)(),(0,i.CE)("li",{class:"setup__version",key:e.value},[(0,i.Lk)("strong",null,(0,a.v_)(e.label),1),t[16]||(t[16]=(0,i.Lk)("br",null,null,-1)),(0,i.Lk)("span",ht,(0,a.v_)(e.problem),1)])):((0,i.uX)(),(0,i.CE)("li",{class:"setup__version",key:e.value},[(0,i.Lk)("strong",null,(0,a.v_)(e.label),1),t[15]||(t[15]=(0,i.Lk)("br",null,null,-1)),(0,i.eW)(" "+(0,a.v_)(e.description),1)]))],64))),256))]),(0,i.bF)(h,{tag:"p",keypath:"ui.setup.create-project.releaseplan",class:"setup__releaseplan"},{contaoReleasePlan:(0,i.k6)(()=>[(0,i.Lk)("a",{href:`https://to.contao.org/release-plan?lang=${e.$i18n.locale}`,target:"_blank",rel:"noreferrer noopener"},(0,a.v_)(e.$t("ui.setup.create-project.releaseplanLink")),9,mt)]),_:1})]),e.contaoVersion?((0,i.uX)(),(0,i.CE)("main",_t,[(0,i.Lk)("div",vt,[t[18]||(t[18]=(0,i.Lk)("svg",{class:"setup__check",xmlns:"http://www.w3.org/2000/svg",width:"24",height:"24",viewBox:"0 0 24 24"},[(0,i.Lk)("path",{d:"M12,2A10,10 0 0,1 22,12A10,10 0 0,1 12,22A10,10 0 0,1 2,12A10,10 0 0,1 12,2M12,4A8,8 0 0,0 4,12A8,8 0 0,0 12,20A8,8 0 0,0 20,12A8,8 0 0,0 12,4M11,16.5L6.5,12L7.91,10.59L11,13.67L16.59,8.09L18,9.5L11,16.5Z"})],-1)),(0,i.Lk)("p",kt,(0,a.v_)(e.$t("ui.setup.create-project.installed",{version:e.contaoVersion})),1)]),(0,i.Lk)("div",bt,[(0,i.Lk)("button",{class:"widget-button widget-button--inline",onClick:t[5]||(t[5]=(...e)=>r.launch&&r.launch(...e))},(0,a.v_)(e.$t("ui.setup.manager")),1),(0,i.Lk)("button",{class:"widget-button widget-button--inline widget-button--primary",onClick:t[6]||(t[6]=t=>e.$emit("continue"))},(0,a.v_)(e.$t("ui.setup.continue")),1)])])):((0,i.uX)(),(0,i.CE)("main",gt,[(0,i.Lk)("div",ft,[(0,i.Lk)("h2",yt,(0,a.v_)(e.$t("ui.setup.create-project.formTitle")),1),(0,i.Lk)("p",wt,(0,a.v_)(e.$t("ui.setup.create-project.formText")),1),(0,i.bF)(m,{name:"version",options:r.versions,disabled:e.processing,modelValue:e.version,"onUpdate:modelValue":t[7]||(t[7]=t=>e.version=t)},null,8,["options","disabled","modelValue"]),"theme"===e.version?((0,i.uX)(),(0,i.CE)("div",Lt,[(0,i.Lk)("p",null,(0,a.v_)(e.$t("ui.setup.create-project.themeInstall")),1),(0,i.bF)(h,{keypath:"ui.setup.create-project.themeBuy",tag:"p"},{store:(0,i.k6)(()=>[(0,i.Lk)("a",$t,(0,a.v_)(e.$t("ui.setup.create-project.themeStore")),1)]),_:1}),(0,i.bo)((0,i.Lk)("div",Ct,[(0,i.Lk)("div",null,[t[19]||(t[19]=(0,i.Lk)("img",{src:Pe,alt:"",width:"128",height:"128"},null,-1)),(0,i.Lk)("p",null,(0,a.v_)(e.$t("ui.packages.uploadOverlay")),1)])],512),[[X.aG,e.$refs.uploader&&e.$refs.uploader.dropActive]])])):((0,i.uX)(),(0,i.Wv)(_,{key:1,name:"demo",label:e.$t("ui.setup.create-project.demo"),disabled:e.processing||!1===this.current.demo,modelValue:e.demo,"onUpdate:modelValue":t[8]||(t[8]=t=>e.demo=t)},{description:(0,i.k6)(()=>[(0,i.bF)(h,{tag:"p",keypath:"ui.setup.create-project.demoDescription"},{store:(0,i.k6)(()=>[(0,i.Lk)("a",Et,(0,a.v_)(e.$t("ui.setup.create-project.themeStore")),1)]),_:1})]),_:1},8,["label","disabled","modelValue"]))]),(0,i.Lk)("div",Xt,["theme"===e.version?((0,i.uX)(),(0,i.CE)(i.FK,{key:0},[(0,i.bF)(p,{color:"primary",icon:"upload",loading:e.processing,onClick:r.openFileSelector},{default:(0,i.k6)(()=>[(0,i.eW)((0,a.v_)(e.$t("ui.setup.create-project.themeUpload")),1)]),_:1},8,["loading","onClick"]),(0,i.Lk)("div",jt,[(0,i.Lk)("span",null,(0,a.v_)(e.$t("ui.setup.create-project.theme.or")),1)]),(0,i.bF)(v,{placeholder:e.$t("ui.setup.create-project.theme.search"),disabled:e.processing},null,8,["placeholder","disabled"])],64)):((0,i.uX)(),(0,i.Wv)(k,{key:1,color:"primary",icon:"run",disabled:!e.version,loading:e.processing,onClick:t[11]||(t[11]=()=>r.install()),label:e.$t("ui.setup.create-project.install")},{default:(0,i.k6)(()=>[e.demo?(0,i.Q3)("",!0):((0,i.uX)(),(0,i.CE)("button",{key:0,class:"widget-button",disabled:!e.version||e.processing,onClick:t[9]||(t[9]=(...e)=>r.installCoreOnly&&r.installCoreOnly(...e))},(0,a.v_)(e.$t("ui.setup.create-project.coreOnly")),9,Ft)),(0,i.Lk)("button",{class:"widget-button",disabled:!e.version||e.processing,onClick:t[10]||(t[10]=(...e)=>r.installNoUpdate&&r.installNoUpdate(...e))},(0,a.v_)(e.$t("ui.setup.create-project.noUpdate")),9,At)]),_:1},8,["disabled","loading","label"]))])])),t[20]||(t[20]=(0,i.Lk)("div",{class:"clearfix"},null,-1)),e.searching||e.results||e.offline?((0,i.uX)(),(0,i.CE)("div",Vt,[e.searching&&!e.results?((0,i.uX)(),(0,i.Wv)(b,{key:0,class:"setup__theme-search setup__theme-search--loader"},{default:(0,i.k6)(()=>[(0,i.Lk)("p",null,(0,a.v_)(e.$t("ui.discover.loading")),1)]),_:1})):e.offline?((0,i.uX)(),(0,i.CE)("div",Ut,[(0,i.Lk)("p",null,(0,a.v_)(e.$t("ui.discover.offline")),1),(0,i.Lk)("p",null,(0,a.v_)(e.$t("ui.discover.offlineExplain")),1),(0,i.Lk)("button",{class:"widget-button widget-button--inline widget-button--update",onClick:t[12]||(t[12]=(...e)=>r.searchThemes&&r.searchThemes(...e))},(0,a.v_)(e.$t("ui.discover.offlineButton")),1)])):e.isSearching&&e.results&&!Object.keys(e.results).length?((0,i.uX)(),(0,i.CE)("div",xt,[(0,i.bF)(h,{tag:"p",keypath:"ui.setup.create-project.theme.empty"},{query:(0,i.k6)(()=>[(0,i.Lk)("i",null,(0,a.v_)(e.query),1)]),_:1})])):e.isSearching&&e.results?((0,i.uX)(),(0,i.CE)(i.FK,{key:3},[(0,i.Lk)("div",Dt,[((0,i.uX)(!0),(0,i.CE)(i.FK,null,(0,i.pI)(e.results,e=>((0,i.uX)(),(0,i.Wv)(g,{class:"setup__themes-item",data:e,key:e.name},null,8,["data"]))),128))]),(0,i.Lk)("div",St,[e.hasMore?((0,i.uX)(),(0,i.Wv)(p,{key:0,inline:"",icon:"search",loading:e.searching,onClick:e.loadMore},{default:(0,i.k6)(()=>[(0,i.eW)((0,a.v_)(e.$t("ui.setup.create-project.theme.more")),1)]),_:1},8,["loading","onClick"])):(0,i.Q3)("",!0)])],64)):(0,i.Q3)("",!0)])):(0,i.Q3)("",!0)],64))])}s(4423),s(2489),s(116),s(7588),s(9112),s(4603),s(7566),s(8721);var Tt=s(4686),Wt=s.n(Tt),It=s(1881),qt=s(8568),Ht=s.n(qt);const Rt=["href"],Bt=["href"],Mt={key:3};function Ot(e,t,s,o,n,r){const l=(0,i.g2)("package-constraint"),u=(0,i.g2)("package-details");return(0,i.uX)(),(0,i.Wv)(u,null,{"package-actions":(0,i.k6)(()=>[!e.isTheme||r.data.uploaded||r.isPrivate?r.data.homepage||e.metadata.homepage?((0,i.uX)(),(0,i.CE)("a",{key:1,class:"widget-button widget-button--primary widget-button--link",target:"_blank",href:r.data.homepage||e.metadata.homepage},(0,a.v_)(e.$t("ui.package.homepage")),9,Rt)):r.isPrivate?((0,i.uX)(),(0,i.CE)("div",Mt)):((0,i.uX)(),(0,i.CE)("a",{key:2,class:"widget-button widget-button--primary widget-button--link",target:"_blank",href:`https://packagist.org/packages/${r.data.name}`},(0,a.v_)(e.$t("ui.package-details.packagist")),9,Bt)):((0,i.uX)(),(0,i.CE)(i.FK,{key:0},[(0,i.Lk)("button",{class:"widget-button widget-button--primary widget-button--run",onClick:t[0]||(t[0]=(...e)=>r.install&&r.install(...e))},(0,a.v_)(e.$t("ui.setup.create-project.install")),1),(0,i.bF)(l,{class:"theme-details__constraint",emit:!0,data:r.data,modelValue:e.version,"onUpdate:modelValue":t[1]||(t[1]=t=>e.version=t)},null,8,["data","modelValue"])],64))]),_:1})}var Qt=s(3312),Kt=s(4290),Jt=s(416),Nt=s(8200),zt={mixins:[Jt.A,Nt.A],components:{PackageConstraint:Kt.A,PackageDetails:Qt["default"]},data:()=>({version:""}),computed:{...(0,C.aH)("packages",{allInstalled:"installed"}),current:e=>e.$route.query.p,data:e=>e.allInstalled&&e.allInstalled[e.current]||{name:e.current},isPrivate:e=>e.metadata&&!!e.metadata.private},methods:{install(){this.$store.commit("contao/installTheme",{package:this.data.name,version:this.version})}}};const Zt=(0,Xe.A)(zt,[["render",Ot]]);var Yt=Zt,Gt=s(791),es=s(9045),ts=s(6435);const ss={class:"file-tree"},is=["onClick"],as={key:1,class:"file-tree__file"};function os(e,t,s,o,n,r){const l=(0,i.g2)("file-tree",!0);return(0,i.uX)(),(0,i.CE)("ul",ss,[((0,i.uX)(!0),(0,i.CE)(i.FK,null,(0,i.pI)(s.files,(e,t)=>((0,i.uX)(),(0,i.CE)(i.FK,{key:t},[e.children.length?((0,i.uX)(),(0,i.CE)("li",{key:0,class:(0,a.C4)("file-tree__folder"+(r.isOpen(e)?" file-tree__folder--open":""))},[(0,i.Lk)("button",{onClick:t=>r.toggle(e)},(0,a.v_)(r.name(e)),9,is),r.isOpen(e)?((0,i.uX)(),(0,i.Wv)(l,{key:0,files:e.children},null,8,["files"])):(0,i.Q3)("",!0)],2)):((0,i.uX)(),(0,i.CE)("li",as,[(0,i.Lk)("span",null,(0,a.v_)(r.name(e)),1)]))],64))),128))])}var ns={name:"FileTree",props:{files:{type:Array,required:!0}},data:()=>({open:[]}),computed:{name:()=>e=>e.name?e.name:e.path.substring(e.path.lastIndexOf("/")+1),isOpen:e=>t=>e.open.includes(t)},methods:{toggle(e){this.open.includes(e)?this.open=this.open.filter(t=>t!==e):this.open.push(e)}}};const rs=(0,Xe.A)(ns,[["render",os]]);var ls=rs,us=s(4676),cs=s(1298),ds=s(2864),ps=s(4960),hs={mixins:[It.A],components:{ButtonGroup:us.A,FileTree:ls,DiscoverPackage:ts.A,LoadingSpinner:es.A,SearchInput:Gt.A,FileUpload:Ht(),RadioButton:Fe,CheckBox:Ae.A,LoadingButton:Ve.A,ProgressBar:cs.A,ConsoleOutput:ds.A},data:()=>({processing:!1,isWeb:!0,version:"5.7",demo:!1,view:"require",theme:null,themeImage:null,upload:null,searching:!1,results:null,hasMore:!1,offline:!1,showHidden:!1}),computed:{...(0,C.aH)("tasks",{taskStatus:"status"}),...(0,C.aH)("server/php-web",["phpVersionId","phpVersion"]),...(0,C.aH)("server/contao",["contaoVersion"]),...(0,C.aH)("contao",{themeName:"package",themeVersion:"version"}),themeFiles:e=>Wt()(e.theme.files,{directoriesFirst:!0}).children,uploadSize:e=>e.upload&&(0,ps.A)(e.upload.size)||"",versions(){const e=[];return e.push({value:"5.7",label:`Contao 5.7 (${this.$t("ui.setup.create-project.latestTitle")})`,disabled:this.phpVersionId<80300,description:this.$t("ui.setup.create-project.ltsText",{year:"2029"}),problem:this.$t("ui.setup.create-project.requiresPHP",{version:"8.3.0",current:this.phpVersion})}),e.push({value:"5.3",label:`Contao 5.3 (${this.$t("ui.setup.create-project.ltsTitle")})`,disabled:this.phpVersionId<80100,description:this.$t("ui.setup.create-project.pltsText",{year:"2027"}),problem:this.$t("ui.setup.create-project.requiresPHP",{version:"8.1.0",current:this.phpVersion})}),e.push({value:"4.13",label:`Contao 4.13 (${this.$t("ui.setup.create-project.ltsTitle")})`,disabled:this.phpVersionId<70400,hidden:!0,description:this.$t("ui.setup.create-project.pltsText",{year:"2025"}),problem:this.$t("ui.setup.create-project.requiresPHP",{version:"7.4.0",current:this.phpVersion})}),e.push({value:"theme",label:this.$t("ui.setup.create-project.theme")}),e.filter(e=>!e.hidden||e.value===this.version||this.showHidden)},current(){return this.versions.find(e=>e.value===this.version)}},watch:{version(){this.stopSearch(),this.searching=!1,this.results=null,this.hasMore=!1,this.demo&&!1===this.current.demo&&(this.demo=!1)},sorting(){this.searchThemes()},query(){this.results=null,this.query?this.searchThemes():(this.searching=!1,this.hasMore=!1)},pages(){this.searchThemes()},themeName(){this.themeName&&(this.closePopup(),setTimeout(()=>{this.install({package:this.themeName,version:this.themeVersion})},100))}},methods:{...(0,C.PY)("packages/details",{closePopup:"clearCurrent"}),async searchThemes(){this.searching=!0,this.offline=!1;try{const e={facetFilters:["type:contao-theme"],hitsPerPage:10*this.pages};this.query?e.query=this.query:this.sorting&&(e.sorting=this.sorting);const t=await this.$store.dispatch("algolia/findPackages",e);if(this.hasMore=t.nbPages>1,0===t.nbHits)return void(this.results={});const s={};t.hits.forEach(e=>{s[e.name]=e}),this.results=s}catch(e){this.offline=!0}this.searching=!1},async install(e,t=null){let s;this.processing=!0,s=e||(this.theme?{upload:this.theme.upload.id}:this.demo?{package:"contao/contao-demo",version:this.version,"no-update":"no-update"===t?"1":"0"}:{version:this.version,"core-only":"core-only"===t?"1":"0","no-update":"no-update"===t?"1":"0"});try{await this.$store.dispatch("contao/install",s)}catch(i){}this.processing=!1,"complete"===this.taskStatus&&(this.$store.commit("tasks/setDeleting",!0),await this.$store.dispatch("server/composer/get",!1),"no-update"===t?(this.$store.commit("setSafeMode",!0),this.$store.commit("setView",$.A.READY)):(this.isWeb="web"===(await this.$store.dispatch("server/contao/get",!1)).data.public_dir,await Promise.all([this.$store.dispatch("contao/install-tool/fetch",!1),this.$store.dispatch("server/database/get",!1),this.$store.dispatch("contao/backup/fetch",!1)]),this.$store.commit("contao/backup/setRestore",!0),this.$store.commit("setup",3)),await this.$store.dispatch("tasks/deleteCurrent"))},installNoUpdate(){this.install(null,"no-update")},installCoreOnly(){this.install(null,"core-only")},launch(){this.$store.commit("setView",$.A.READY)},openFileSelector(){this.$refs.uploader&&this.$refs.uploader.$el.querySelector("input").click()},async filterTheme(e,t,s){if(e&&!t&&!/(\.cto|\.zip)$/i.test(e.name))return console&&console.debug(`${e.name} is not a .zip or .cto`),alert(this.$t("ui.setup.create-project.themeInvalid")),s()},async uploadTheme(e,t){if(e)if(this.processing=!0,this.$refs.uploader.uploaded&&e&&t&&!e.active&&t.active)if(this.theme.upload=e.response.data,e.success)try{await this.install()}catch(i){this.upload=null,this.processing=!1}else this.upload=e,this.processing=!1;else if(!e.active||t.active){e.url=URL.createObjectURL(e.file);try{const t=new File([e.file],e.name,{type:e.type}),a=(await s.e(710).then(s.t.bind(s,1710,23))).default,o=await a.loadAsync(t),n=o.filter(e=>!["composer.json","theme.xml"].includes(e)&&!e.startsWith("__MACOSX/")&&!e.includes(".DS_Store")&&!e.endsWith("/")).map(e=>e.name);let r=n[0].substring(0,n[0].indexOf("/")+1);n.find(e=>e.substr(0,r.length)!==r)&&(r="");const l=JSON.parse(await o.file(`${r}composer.json`).async("string")),u=await o.file(`${r}theme.xml`).async("string"),c=new DOMParser,d=c.parseFromString(u,"application/xml");if(this.theme={tstamp:d.querySelector('table[name="tl_theme"] field[name="tstamp"]')?.innerHTML,name:d.querySelector('table[name="tl_theme"] field[name="name"]')?.innerHTML,author:d.querySelector('table[name="tl_theme"] field[name="author"]')?.innerHTML,screenshot:d.querySelector('table[name="tl_theme"] field[name="screenshot"]')?.innerHTML,composerJson:l,files:n},this.theme.screenshot&&"NULL"!==this.theme.screenshot)try{const e=await o.file(`${r}${this.theme.screenshot}`);this.themeImage=e?URL.createObjectURL(await e.async("blob")):null}catch(i){}}catch(i){console&&console.debug(i),alert(this.$t("ui.setup.create-project.themeInvalid")),this.cancelTheme()}this.processing=!1}else this.upload=e},cancelTheme(){this.theme=null,this.upload=null,this.$refs.uploader.clear()},themeDetails(){this.$store.commit("packages/setInstalled",{local:{[this.theme.composerJson.name]:Object.assign({},this.theme.composerJson,{uploaded:!0})}}),this.$store.commit("packages/details/setCurrent",this.theme.composerJson.name)},installTheme(){this.$refs.uploader.active||(this.processing=!0,this.$refs.uploader.active=!0)},toggleHidden(e){18===e.keyCode&&(this.showHidden="keydown"===e.type)}},async mounted(){await this.$router.isReady(),Object.keys(this.$route.query).length&&this.$router.replace({query:null}),await this.$store.dispatch("packages/details/init",{vue:this,component:Yt}),this.$store.commit("packages/setInstalled",{}),this.isWeb="web"===(await this.$store.dispatch("server/contao/get")).data.public_dir,this.version=this.versions.find(e=>!e.disabled).value,window.addEventListener("keydown",this.toggleHidden),window.addEventListener("keyup",this.toggleHidden)},unmounted(){window.removeEventListener("keydown",this.toggleHidden),window.removeEventListener("keyup",this.toggleHidden)}};const ms=(0,Xe.A)(hs,[["render",Pt]]);var _s=ms,vs=s(9472);const ks={class:"setup__header"},bs={class:"setup__headline"},gs={class:"setup__form",key:"setup"},fs={class:"setup__fields"},ys={class:"setup__fieldtitle"},ws={class:"setup__fielddesc"},Ls={key:0,class:"setup__warning"},$s={class:"setup__or"},Cs={class:"setup__actions"},Es=["disabled"],Xs={class:"setup__form",key:"confirmation"},js={class:"setup__fields"},Fs={class:"setup__fieldtitle"},As={key:"migrate"},Vs={class:"setup__fields"},Us={class:"setup__fieldtitle"},xs={key:0,class:"setup__fielddesc setup__warning"},Ds={key:1,class:"setup__fielddesc"},Ss={class:"setup__actions setup__actions--center"},Ps={key:"restored"},Ts={class:"setup__fields"},Ws={class:"setup__fieldtitle"},Is={class:"setup__fielddesc"},qs={class:"setup__actions setup__actions--center"},Hs={key:"backup"},Rs={class:"setup__fields"},Bs={class:"setup__fieldtitle"},Ms={class:"setup__fielddesc"},Os={class:"setup__fielddesc setup__warning"},Qs={class:"setup__actions"},Ks=["disabled"];function Js(e,t,s,o,n,r){const l=(0,i.g2)("i18n-t"),u=(0,i.g2)("text-field"),c=(0,i.g2)("loading-button"),d=(0,i.g2)("radio-button");return(0,i.uX)(),(0,i.CE)("section",null,[(0,i.Lk)("header",ks,[t[17]||(t[17]=(0,i.Lk)("img",{src:vs,width:"80",height:"80",class:"setup__icon",alt:""},null,-1)),(0,i.Lk)("h1",bs,(0,a.v_)(e.$t("ui.setup.database-connection.headline")),1),(0,i.bF)(l,{tag:"p",keypath:"ui.setup.database-connection.description",class:"setup__description"},{env:(0,i.k6)(()=>[...t[16]||(t[16]=[(0,i.Lk)("code",null,".env.local",-1)])]),_:1})]),e.currentState?((0,i.uX)(),(0,i.Wv)(X.eB,{key:0,name:"animate-flip",type:"transition",mode:"out-in"},{default:(0,i.k6)(()=>["error"===e.currentState||"edit"===e.currentState?((0,i.uX)(),(0,i.CE)("main",gs,[(0,i.Lk)("form",{onSubmit:t[7]||(t[7]=(0,X.D$)((...e)=>r.save&&r.save(...e),["prevent"]))},[(0,i.Lk)("div",fs,[(0,i.Lk)("h2",ys,(0,a.v_)(e.$t("ui.setup.database-connection.formTitle")),1),(0,i.Lk)("p",ws,(0,a.v_)(e.$t("ui.setup.database-connection.formText")),1),"edit"!==e.currentState&&""!==e.currentUrl?((0,i.uX)(),(0,i.CE)("p",Ls,(0,a.v_)(e.$t("ui.setup.database-connection.error")),1)):(0,i.Q3)("",!0),(0,i.bF)(u,{ref:"url",name:"url",type:"url",label:e.$t("ui.setup.database-connection.url"),placeholder:"mysql://user:password@server:port/database",required:"",pattern:e.urlPattern,validate:"",disabled:e.processing,modelValue:e.url,"onUpdate:modelValue":t[0]||(t[0]=t=>e.url=t),onKeyup:t[1]||(t[1]=t=>e.validUrl=!0),onBlur:r.parseUrl,error:e.validUrl?void 0:e.$t("ui.setup.database-connection.validUrl")},null,8,["label","pattern","disabled","modelValue","onBlur","error"]),(0,i.Lk)("div",$s,[(0,i.Lk)("span",null,(0,a.v_)(e.$t("ui.setup.database-connection.or")),1)]),(0,i.bF)(u,{name:"user",label:e.$t("ui.setup.database-connection.user"),disabled:e.processing,modelValue:e.user,"onUpdate:modelValue":t[2]||(t[2]=t=>e.user=t)},null,8,["label","disabled","modelValue"]),(0,i.bF)(u,{name:"password",type:"password",label:e.$t("ui.setup.database-connection.password"),disabled:e.processing,modelValue:e.password,"onUpdate:modelValue":t[3]||(t[3]=t=>e.password=t)},null,8,["label","disabled","modelValue"]),(0,i.bF)(u,{name:"server",label:e.$t("ui.setup.database-connection.server"),disabled:e.processing,required:"",modelValue:e.server,"onUpdate:modelValue":t[4]||(t[4]=t=>e.server=t)},null,8,["label","disabled","modelValue"]),(0,i.bF)(u,{name:"database",label:e.$t("ui.setup.database-connection.database"),disabled:e.processing,required:"",modelValue:e.database,"onUpdate:modelValue":t[5]||(t[5]=t=>e.database=t)},null,8,["label","disabled","modelValue"])]),(0,i.Lk)("div",Cs,[(0,i.bF)(c,{submit:"",color:"primary",icon:"save",loading:e.processing,disabled:!e.valid},{default:(0,i.k6)(()=>[(0,i.eW)((0,a.v_)(e.$t("ui.setup.database-connection.save")),1)]),_:1},8,["loading","disabled"]),"edit"===e.currentState?((0,i.uX)(),(0,i.CE)("button",{key:0,type:"button",class:"widget-button",disabled:e.processing,onClick:t[6]||(t[6]=(...e)=>r.load&&r.load(...e))},(0,a.v_)(e.$t("ui.setup.cancel")),9,Es)):(0,i.Q3)("",!0)])],32)])):((0,i.uX)(),(0,i.CE)("main",Xs,[(0,i.Lk)("div",js,[(0,i.Lk)("h2",Fs,(0,a.v_)(e.$t("ui.setup.database-connection.formTitle")),1),e.url?((0,i.uX)(),(0,i.Wv)(l,{key:0,tag:"p",keypath:"ui.setup.database-connection.connected",class:"setup__fielddesc"},{database:(0,i.k6)(()=>[(0,i.Lk)("i",null,(0,a.v_)(e.database),1)]),server:(0,i.k6)(()=>[(0,i.Lk)("i",null,(0,a.v_)(e.server),1)]),_:1})):(0,i.Q3)("",!0),(0,i.Lk)("button",{type:"button",class:"widget-button widget-button--edit widget-button--small",onClick:t[8]||(t[8]=t=>e.currentState="edit")},(0,a.v_)(e.$t("ui.setup.database-connection.change")),1)]),(0,i.bF)(X.eB,{name:"animate-flip",type:"transition",mode:"out-in"},{default:(0,i.k6)(()=>[!e.hasDatabaseError&&e.backupRestore&&e.hasBackups?e.backupRestored?((0,i.uX)(),(0,i.CE)("div",Ps,[(0,i.Lk)("div",Ts,[(0,i.Lk)("h2",Ws,(0,a.v_)(e.$t("ui.setup.database-connection.restoreTitle")),1),t[18]||(t[18]=(0,i.Lk)("svg",{class:"setup__check",xmlns:"http://www.w3.org/2000/svg",width:"24",height:"24",viewBox:"0 0 24 24"},[(0,i.Lk)("path",{d:"M12,2A10,10 0 0,1 22,12A10,10 0 0,1 12,22A10,10 0 0,1 2,12A10,10 0 0,1 12,2M12,4A8,8 0 0,0 4,12A8,8 0 0,0 12,20A8,8 0 0,0 20,12A8,8 0 0,0 12,4M11,16.5L6.5,12L7.91,10.59L11,13.67L16.59,8.09L18,9.5L11,16.5Z"})],-1)),(0,i.Lk)("p",Is,(0,a.v_)(e.$t("ui.setup.database-connection.restored")),1)]),(0,i.Lk)("div",qs,[(0,i.Lk)("button",{type:"button",class:"widget-button widget-button--primary",onClick:t[12]||(t[12]=t=>e.$store.commit("contao/backup/setRestore",!1))},(0,a.v_)(e.$t("ui.setup.continue")),1)])])):((0,i.uX)(),(0,i.CE)("div",Hs,[(0,i.Lk)("div",Rs,[(0,i.Lk)("h2",Bs,(0,a.v_)(e.$t("ui.setup.database-connection.restoreTitle")),1),(0,i.Lk)("p",Ms,(0,a.v_)(e.$tc("ui.setup.database-connection.restoreText",e.files.length)),1),e.files.length>1?((0,i.uX)(),(0,i.Wv)(d,{key:0,required:"","allow-html":"",options:r.fileOptions,name:"selection",modelValue:e.selection,"onUpdate:modelValue":t[13]||(t[13]=t=>e.selection=t)},null,8,["options","modelValue"])):(0,i.Q3)("",!0),(0,i.Lk)("p",Os,(0,a.v_)(e.$t("ui.setup.database-connection.backupWarning")),1)]),(0,i.Lk)("div",Qs,[(0,i.Lk)("button",{type:"button",class:"widget-button widget-button--inline",onClick:t[14]||(t[14]=t=>e.$store.commit("contao/backup/setRestore",!1))},(0,a.v_)(e.$t("ui.setup.database-connection.skip")),1),(0,i.Lk)("button",{type:"button",class:"widget-button widget-button--inline widget-button--primary",disabled:e.files.length>1&&!e.selection,onClick:t[15]||(t[15]=(...e)=>r.restore&&r.restore(...e))},(0,a.v_)(e.$t("ui.setup.database-connection.restore")),9,Ks)])])):((0,i.uX)(),(0,i.CE)("div",As,[(0,i.Lk)("div",Vs,[(0,i.Lk)("h2",Us,(0,a.v_)(e.$t("ui.setup.database-connection.schemaTitle")),1),e.status&&e.status.total>0?((0,i.uX)(),(0,i.CE)("p",xs,(0,a.v_)(e.$tc(`ui.setup.database-connection.${e.currentState}`,e.status.total)),1)):((0,i.uX)(),(0,i.CE)("p",Ds,(0,a.v_)(e.$t("ui.setup.database-connection.noChanges")),1))]),(0,i.Lk)("div",Ss,[e.status&&e.status.total>0?((0,i.uX)(),(0,i.CE)(i.FK,{key:0},[e.hasDatabaseError?(0,i.Q3)("",!0):((0,i.uX)(),(0,i.CE)("button",{key:0,type:"button",class:"widget-button widget-button--inline",onClick:t[9]||(t[9]=t=>e.$emit("continue"))},(0,a.v_)(e.$t("ui.setup.database-connection.skip")),1)),(0,i.Lk)("button",{type:"button",class:"widget-button widget-button--inline widget-button--primary",onClick:t[10]||(t[10]=(...e)=>r.checkMigrations&&r.checkMigrations(...e))},(0,a.v_)(e.$t("ui.setup.database-connection.check")),1)],64)):((0,i.uX)(),(0,i.CE)("button",{key:1,type:"button",class:"widget-button widget-button--primary",onClick:t[11]||(t[11]=t=>e.$emit("continue"))},(0,a.v_)(e.$t("ui.setup.continue")),1))])]))]),_:1})]))]),_:1})):(0,i.Q3)("",!0)])}var Ns=s(4210),zs={components:{RadioButton:Fe,TextField:fe.A,LoadingButton:Ve.A},data:()=>({processing:!1,validUrl:!0,valid:!1,validating:!1,currentState:null,url:"",user:"",password:"",server:"localhost",database:"",backup:!0,selection:null}),computed:{...(0,C.aH)("tasks",{taskStatus:"status"}),...(0,C.aH)("contao/backup",{backupRestored:"restored",backupRestore:"restore"}),...(0,C.aH)("server/database",{currentUrl:"url",urlPattern:"pattern",status:"status"}),...(0,C.aH)("contao/backup",["files"]),...(0,C.L8)("server/database",{hasDatabaseError:"hasError"}),...(0,C.L8)("contao/backup",["hasBackups"]),fileOptions(){return this.files.map(e=>({value:e.name,label:this.$t("ui.setup.database-connection.restoreOption",{date:(0,Ns.A)(e.createdAt),size:(0,ps.A)(e.size)})}))}},methods:{datimFormat(e){return(0,Ns.A)(e,"short","long")},checkMigrations(){this.$store.commit("checkMigrations")},parseUrl(){if(!this.validateUrl())return;this.validating=!0;const e=new RegExp(this.urlPattern,"i").exec(this.url);this.user=e[3]?decodeURIComponent(e[3]):"",this.password=e[5]?decodeURIComponent(e[5]):"",this.server=decodeURIComponent(e[6]),this.database=decodeURIComponent(e[8]),":3306"===this.server.substring(this.server.length-5)?this.server=this.server.substring(0,this.server.length-5):this.server.includes(":")||(this.server=`${this.server}:3306`),this.valid=this.validateUrl(),this.validating=!1},updateUrl(){if(this.validating)return;if(this.valid=!1,!this.server)return;const e=this.server.split(":",2),t=`${encodeURIComponent(e[0])}:${e[1]||"3306"}`;let s="mysql://";this.user&&(s+=encodeURIComponent(this.user),this.password&&(s+=":"+encodeURIComponent(this.password)),s+="@"),s+=t,this.database&&(s+="/"+encodeURIComponent(this.database)),this.url=s,this.valid=this.validateUrl()},validateUrl(){return this.validUrl=!0,this.valid=!1,""!==this.url&&(this.validUrl=new RegExp(this.urlPattern,"i").test(this.url),this.validUrl)},async load(){this.url=(await this.$store.dispatch("server/database/get")).data.url,this.currentState=this.status?.type,this.parseUrl(),"error"===this.currentState&&(this.validUrl=!1,this.valid=!1)},async save(){this.processing=!0;const e=await this.$store.dispatch("server/database/set",this.url);if("error"===e.data.status.type)return this.processing=!1,this.validUrl=!1,void(this.valid=!1);await this.$store.dispatch("server/adminUser/get",!1),this.processing=!1},async restore(){await this.$store.dispatch("tasks/execute",{name:"contao/backup-restore",config:{file:this.files.length>1?this.selection:this.files[0].name,backup:!1}}),"complete"===this.taskStatus&&(this.$store.commit("contao/backup/setRestored"),await this.$store.dispatch("tasks/deleteCurrent"))}},watch:{user(){this.updateUrl()},password(){this.updateUrl()},server(){this.updateUrl()},database(){this.updateUrl()},status(){this.currentState=this.status?.type}},mounted(){this.load(),this.selection=null,this.backup=!0}};const Zs=(0,Xe.A)(zs,[["render",Js]]);var Ys=Zs,Gs=s.p+"img/user.129e863d.svg";const ei={class:"setup__header"},ti={class:"setup__headline"},si={class:"setup__description"},ii={key:0,class:"setup__form"},ai={class:"setup__fields"},oi={class:"setup__warning"},ni={class:"setup__form setup__form--center",key:"confirmation"},ri={class:"setup__fields"},li={class:"setup__fielddesc"},ui={class:"setup__actions setup__actions--center"},ci={class:"setup__form",key:"setup"},di={class:"setup__fields"},pi={class:"setup__fieldtitle"},hi={class:"setup__fielddesc"},mi={class:"setup__actions setup__actions--center"};function _i(e,t,s,o,n,r){const l=(0,i.g2)("console-output"),u=(0,i.g2)("text-field"),c=(0,i.g2)("loading-button");return(0,i.uX)(),(0,i.CE)("section",null,[(0,i.Lk)("header",ei,[t[8]||(t[8]=(0,i.Lk)("img",{src:Gs,width:"80",height:"80",class:"setup__icon",alt:""},null,-1)),(0,i.Lk)("h1",ti,(0,a.v_)(e.$t("ui.setup.backend-user.headline")),1),(0,i.Lk)("p",si,(0,a.v_)(e.$t("ui.setup.backend-user.description")),1)]),null===e.hasUser?((0,i.uX)(),(0,i.CE)("main",ii,[(0,i.Lk)("div",ai,[(0,i.Lk)("p",oi,(0,a.v_)(e.$t("ui.setup.backend-user.error")),1),502===e.response.status?((0,i.uX)(),(0,i.Wv)(l,{key:0,class:"view-recovery__console",title:e.$t("ui.recovery.console"),operations:[{status:"error",summary:"vendor/bin/contao-console contao:user:list",console:e.response.data.detail}],"console-output":e.response.data.detail,"show-console":"","force-console":""},null,8,["title","operations","console-output"])):(0,i.Q3)("",!0)])])):((0,i.uX)(),(0,i.Wv)(X.eB,{key:1,name:"animate-flip",type:"transition",mode:"out-in"},{default:(0,i.k6)(()=>[e.hasUser?((0,i.uX)(),(0,i.CE)("main",ni,[(0,i.Lk)("div",ri,[t[9]||(t[9]=(0,i.Lk)("svg",{class:"setup__check",xmlns:"http://www.w3.org/2000/svg",width:"24",height:"24",viewBox:"0 0 24 24"},[(0,i.Lk)("path",{d:"M12,2A10,10 0 0,1 22,12A10,10 0 0,1 12,22A10,10 0 0,1 2,12A10,10 0 0,1 12,2M12,4A8,8 0 0,0 4,12A8,8 0 0,0 12,20A8,8 0 0,0 20,12A8,8 0 0,0 12,4M11,16.5L6.5,12L7.91,10.59L11,13.67L16.59,8.09L18,9.5L11,16.5Z"})],-1)),(0,i.Lk)("p",li,(0,a.v_)(e.$t("ui.setup.backend-user.success")),1)]),(0,i.Lk)("div",ui,[(0,i.Lk)("button",{type:"button",class:"widget-button widget-button--inline widget-button--primary",onClick:t[0]||(t[0]=t=>e.$emit("continue"))},(0,a.v_)(e.$t("ui.setup.continue")),1)])])):((0,i.uX)(),(0,i.CE)("main",ci,[(0,i.Lk)("form",{onSubmit:t[7]||(t[7]=(0,X.D$)((...e)=>r.save&&r.save(...e),["prevent"]))},[(0,i.Lk)("div",di,[(0,i.Lk)("h2",pi,(0,a.v_)(e.$t("ui.setup.backend-user.formTitle")),1),(0,i.Lk)("p",hi,(0,a.v_)(e.$t("ui.setup.backend-user.formText")),1),(0,i.bF)(u,{ref:"username",name:"username",label:e.$t("ui.setup.backend-user.username"),disabled:e.processing,required:"",validate:"",modelValue:e.username,"onUpdate:modelValue":t[1]||(t[1]=t=>e.username=t)},null,8,["label","disabled","modelValue"]),(0,i.bF)(u,{ref:"name",name:"name",label:e.$t("ui.setup.backend-user.name"),disabled:e.processing,required:"",validate:"",modelValue:e.name,"onUpdate:modelValue":t[2]||(t[2]=t=>e.name=t)},null,8,["label","disabled","modelValue"]),(0,i.bF)(u,{ref:"email",name:"email",type:"email",label:e.$t("ui.setup.backend-user.email"),disabled:e.processing,required:"",validate:"",error:e.errors.email,onFocus:t[3]||(t[3]=t=>e.errors.email=""),onBlur:r.validateEmail,modelValue:e.email,"onUpdate:modelValue":t[4]||(t[4]=t=>e.email=t)},null,8,["label","disabled","error","onBlur","modelValue"]),(0,i.bF)(u,{ref:"password",name:"password",type:"password",label:e.$t("ui.setup.backend-user.password"),placeholder:e.$t("ui.setup.backend-user.passwordPlaceholder"),disabled:e.processing,required:"",minlength:"8",validate:"",error:e.errors.password,onFocus:t[5]||(t[5]=t=>e.errors.password=""),onBlur:r.validatePassword,modelValue:e.password,"onUpdate:modelValue":t[6]||(t[6]=t=>e.password=t)},null,8,["label","placeholder","disabled","error","onBlur","modelValue"])]),(0,i.Lk)("div",mi,[(0,i.bF)(c,{submit:"",color:"primary",loading:e.processing,disabled:!e.valid},{default:(0,i.k6)(()=>[(0,i.eW)((0,a.v_)(e.$t("ui.setup.backend-user.create")),1)]),_:1},8,["loading","disabled"])])],32)]))]),_:1}))])}var vi={components:{TextField:fe.A,LoadingButton:Ve.A,ConsoleOutput:ds.A},data:()=>({processing:!1,valid:!1,username:"",name:"",email:"",password:"",errors:{email:"",password:""}}),computed:{...(0,C.aH)("server/adminUser",{hasUser:"hasUser",response:"cache"})},methods:{validate(){this.valid=this.$refs.username.checkValidity()&&this.$refs.name.checkValidity()&&this.$refs.email.checkValidity()&&this.$refs.password.checkValidity()},validateEmail(){this.errors.email=null,""!==this.email&&(this.$refs.email.checkValidity()||(this.errors.email=this.$t("ui.setup.backend-user.emailInvalid")))},validatePassword(){this.errors.password=null,""!==this.password&&this.password.length<8&&(this.errors.password=this.$t("ui.setup.backend-user.passwordLength"))},async save(){this.processing=!0,await this.$store.dispatch("server/adminUser/set",{username:this.username,name:this.name,email:this.email,password:this.password}),this.processing=!1,this.$store.commit("setup",5)}},watch:{username(){this.validate()},name(){this.validate()},email(){this.validate()},password(){this.validate()}}};const ki=(0,Xe.A)(vi,[["render",_i]]);var bi=ki,gi={components:{BoxedLayout:E.A,DocumentRoot:De,CreateProject:_s,DatabaseConnection:Ys,BackendUser:bi},computed:{...(0,C.aH)(["setupStep"]),...(0,C.aH)("server/contao",["contaoVersion"]),...(0,C.aH)("server/database",{databaseSupported:"supported"}),...(0,C.aH)("server/adminUser",{userSupported:"supported"}),...(0,C.aH)("contao/install-tool",{showInstallTool:"isSupported"}),currentStep:{get(){return this.setupStep},set(e){this.$store.commit("setup",e)}},steps(){const e=[];return e.push({name:"document-root",icon:j,component:De}),e.push({name:"create-project",icon:Se,component:_s}),this.databaseSupported&&e.push({name:"database-connection",icon:vs,component:Ys}),this.userSupported&&e.push({name:"backend-user",icon:Gs,component:bi}),e}},methods:{launch(){this.$store.commit("setView",$.A.READY)}},mounted(){this.$store.dispatch("server/adminUser/get"),this.$store.dispatch("contao/backup/fetch")}};const fi=(0,Xe.A)(gi,[["render",L]]);var yi=fi}}]);"use strict";(self["webpackChunkcontao_manager"]=self["webpackChunkcontao_manager"]||[]).push([[44],{44:function(e){e.exports=JSON.parse('{"ui.app.httpsHeadline":"!! Bağlantı güvenli değil !!","ui.app.httpsDescription":"HTTPS olmadan verileriniz şifrelenmeden aktarılır ve başkaları tarafından görülebilir.","ui.app.httpsLink":"Ayrıntılı bilgi alın","ui.app.httpsHref":"https://https.cio.gov/everything/","ui.app.safeModeHeadline":"!! Güvenli kip etkin !!","ui.app.safeModeDescription":"Bazı Contao Manager özellikleri kullanılamaz.","ui.app.safeModeExit":"Güvenli kipten çık","ui.app.limitedHeadline":"Uzaktan kimlik doğrulama","ui.app.limitedDescription":"Parolasız oturum açma kullandığınızdan izinleriniz sınırlı.","ui.app.limitedLogout":"Kimliği yeniden doğrula","ui.app.totpHeadline":"Güvenlik bildirimi","ui.app.totpDescription":"Hesabınızın güvenliğini sağlamak için iki adımlı doğrulamayı yapılandırın.","ui.app.totpSetup":"Kurulum","ui.app.loading":"Contao Manager yükleniyor…","ui.app.apiError":"Beklenmeyen API durumu","ui.app.configSecurity1":"GÜVENLİK UYARISI !!! Yapılandırma klasörünün korunmadığı algılandı","ui.app.configSecurity2":"Contao Manager, yapılandırma dosyalarının herkese açık olduğunu algıladı. Klasörün güvenliği sağlanana kadar tüm işlemler etkisizleştirilecek. Yoksa bir saldırgan kurulumunuzun hassas verilerine erişebilir.\\n\\nBu sorunu gidermek için sunucunuzdaki \\"contao-manager\\" klasörüne erişimi engellediğinizden emin olun. Bunu nasıl yapacağınızı öğrenmek için site sunucunuzun belgelerine bakın veya barındırma hizmeti sağlayıcınızla görüşün.","ui.account.welcome":"Hoş geldiniz","ui.account.intro1":"Contao açık kaynaklı içerik yönetimi sistemini kurmak ve yönetmek için kullanılan Contao Manager uygulamasına hoş geldiniz. İlk kez kullanıyorsanız {readTheManualToGetStarted}.","ui.account.introGetStarted":"Başlamak için {readTheManualToGetStarted}.","ui.account.introManual":"rehberi okuyun","ui.account.intro2":"Herhangi bir sorunla karşılaşırsanız,  {ourGithubIssues} bakın ve henüz bildirilmemiş bir sorunu bildirmekten çekinmeyin.","ui.account.introIssues":"GitHub sorunlarımıza","ui.account.headline":"Kullanıcı hesabı","ui.account.description":"Kuurlumunuzu yönetmek için bir Contao Manager hesabı açın. Bu hesabın Contao ön yüzü ve yönetim bölümü ile ilgili olmadığını unutmayın. ","ui.account.username":"Kullanıcı adı","ui.account.password":"Parola","ui.account.passwordPlaceholder":"en az 8 karakter","ui.account.passwordLength":"Lütfen en az 8 karakter yazın.","ui.account.loginInvalid":"Hesap açılırken bir sorun çıktı. Başka bir kullanıcı adı deneyin.","ui.account.submit":"Hesap aç","ui.account.usePassword":"Parola ile oturum aç","ui.account.usePasskey":"Geçiş anahtarı ile oturum aç","ui.account.totpHeadline":"İki adımlı doğrulama","ui.account.totpDescription":"Hesabınıza ek bir güvenlik katmanı ekleyen iki adımlı doğrulamayı açın. Kullanıcı adınız ve parolanıza ek olarak, 1Password, Authy, Google Authenticator, Microsoft Authenticator, LastPass Authenticator veya başka herhangi bir tek kullanımlık parola uygulaması gibi bir iki adımlı doğrulama uygulaması tarafından oluşturulan bir kodu yazmanız gerekir.","ui.account.totpSetup":"Şimdi yapılandır","ui.account.totpSkip":"Sonra yapılandır","ui.account.login":"Daveti reddet","ui.account.contribute1":"Contao ve Contao Manager kar amacı gütmeyen Contao Association tarafından desteklenmektedir.","ui.account.contribute2":"Lütfen {donate} açık kaynak dünyasına destek vermeyi değerlendirin.","ui.account.contributeDonate":"bir bağış yaparak","ui.login.headline":"Oturum aç","ui.login.description":"Kurulumunuzu yönetmek için oturum açın.","ui.login.username":"Kullanıcı adı","ui.login.password":"Parola","ui.login.totpHeadline":"İki adımlı doğrulama","ui.login.totpDescription":"Oturum açmak için lütfen doğrulama kodunuzu yazın.","ui.login.totp":"Doğrulama kodu","ui.login.forgotPassword":"Parolamı unuttum","ui.login.button":"Oturum aç","ui.login.passkey":"Geçiş anahtarı ile oturum aç","ui.login.cancel":"İptal","ui.login.or":"ya da","ui.login.locked":"Contao Manager kilitlenmiş olduğundan erişim reddedildi. Kilidi açmak için Contao kök klasöründeki {lockFile} dosyasını silin.","ui.logout.headline":"Oturum zaman aşımına uğradı","ui.logout.warning":"25 dakikadan uzun süredir işlem yapmadınız. Güvenlik nedeniyle oturumunuz kısa bir süre içinde sonlandırılacak.","ui.logout.expired":"30 dakikadan uzun süredir işlem yapmadığınız için oturumunuz otomatik olarak sonlandırıldı.","ui.logout.renew":"Oturumu açık tut","ui.logout.logout":"Oturumu kapat","ui.logout.login":"Oturum açmaya dön","ui.oauth.error":"OAuth girişimi geçersiz. İstek parametrelerini denetleyin.","ui.oauth.https":"Yönlendirme adresi, kimlik doğrulama belirtecinin düz yazı olarak iletilmesini önlemek için güvenli bir iletişim kuralı (https:) kullanmalıdır.","ui.oauth.headline":"Uzaktan kimlik doğrulama","ui.oauth.description":"Şu uygulama ya da hizmet Contao Manager kopyanıza uzaktan erişmek istiyor.","ui.oauth.domain":"Erişim izni vermeden önce bu adresi bildiğinizden ve sahibine güvendiğinizden emin olun!","ui.oauth.outOfScope":"Ne yazık ki, bu izni vermek için yeterli izinleriniz yok.","ui.oauth.allow":"Erişme izni ver","ui.oauth.deny":"Erişimi reddet","ui.oauth.switchUser":"Kullanıcıyı değiştir","ui.scope.admin":"Yönetici erişiminde kullanıcı yönetimi bulunur","ui.scope.install":"Yeni paketleri kurun ve Contao yapılandırmasını değiştirin","ui.scope.update":"Paketleri güncelleyin ve bakım görevlerini yürütün","ui.scope.read":"Paketleri ve yapılandırmayı okuyun","ui.boot.headline":"Sistem denetimi","ui.boot.description":"Lütfen sunucunuz incelenirken bekleyin…","ui.boot.issue1":"Kurulum sorunları algılandı","ui.boot.issue2":"Kurulumunuzda Contao Manager kullanabilmek için düzeltmeniz gereken sorunlar var.","ui.boot.run":"Contao Manager uygulamasını başlat","ui.boot.safeMode":"Güvenli kipte başlat","ui.recovery.headline":"Sistem kurtarma","ui.recovery.description":"Contao Manager, Contao kurulumuna benzeyen dosyalar algıladı, ancak komut satırı arabirimi beklendiği gibi çalışmıyor.","ui.recovery.console":"Konsol çıktısı","ui.recovery.repairOptions":"Lütfen kurulumunuzu onarmak için bir seçim yapın.","ui.recovery.repairHeadline":"Otomatik onarım","ui.recovery.repairDescription":"Uygulama ön belleğini yeniden oluşturup Composer paketlerini yeniden kurarak kurulumu otomatik olarak onarmayı dener.","ui.recovery.repairWarning":"İşlem sırasında üretici dosyalarında yapılmış herhangi bir değişiklik silinebilir!","ui.recovery.repairFailed":"Otomatik onarım başarılı olmadı. Kurulumu el ile onarmak için güvenli kipi deneyin.","ui.recovery.repairButton":"Sistem onarımını başlat","ui.recovery.safeModeHeadline":"Güvenli kip","ui.recovery.safeModeDescription":"Contao Manager güvenli kipte çalıştırıldığında, paketlerin yönetimine ve belirli bakım işlemlerine izin verir. Ancak çalışan bir Contao kurulumu ile ilgili özellikleri kullanılamaz.","ui.recovery.safeModeButton":"Güvenli kipte başlat","ui.server.pending":"Bekleniyor…","ui.server.running":"İnceleniyor…","ui.server.error":"Sunucudan alınan beklenmeyen bir yanıt nedeniyle denetim tamamlanamadı.","ui.server.details":"Ayrıntılar","ui.server.prerequisite":"Eksik bir ön koşul nedeniyle denetim iptal edildi.","ui.server.selfUpdate.title":"Contao Manager güncellemeleri","ui.server.selfUpdate.update":"Yeni Contao Manager {latest} sürümü yayınlanmış.","ui.server.selfUpdate.manualUpdate":"Yeni Contao Manager {latest} sürümü yayınlanmış. Sunucunuz otomatik güncellemeleri desteklemiyor. Lütfen {download} adresinden yeni sürümü indirin.","ui.server.selfUpdate.latest":"Güncel {current} sürümünü kullanıyorsunuz.","ui.server.selfUpdate.dev":"Geliştirme yapımları otomatik güncellemeleri desteklemez.","ui.server.selfUpdate.unsupported":"Yeni bir sürüm yayınlanmış ancak PHP sürümünüzü desteklemiyor.","ui.server.selfUpdate.button":"Otomatik güncelle","ui.server.selfUpdate.continue":"İlerle","ui.server.config.title":"Sunucu yapılandırması","ui.server.config.setup":"Yapılandır","ui.server.config.change":"Değiştir","ui.server.config.save":"Kaydet","ui.server.config.cancel":"İptal","ui.server.config.customOption":"Diğer…","ui.server.config.description":"Arka plan görevlerini doğru bir şekilde çalıştırmak için Contao Manager uygulamasının, PHP komut satırı binary dosyasını nerede bulacağını ve site sürecinden ayrı olarak komutları nasıl çalıştıracağını bilmesi gerekir.","ui.server.config.formTitle":"Sunucu yapılandırması","ui.server.config.formText":"Lütfen PHP binary dosyanızın yolunu yazın. Binary programın PHP sürümünün site işleminizle aynı olduğundan emin olun.","ui.server.config.cloudTitle":"Composer Resolver Cloud","ui.server.config.cloudText":"Composer Resolver Cloud, sunucunuz yeterli yerel bellek sunmasa bile Composer bağımlılıklarının kurulmasını sağlar. Paket bilgilerinizin Contao Association tarafından işletilen bir bulut sunucusuna aktarılacağını unutmayın.","ui.server.config.cloud":"Composer Resolver Cloud kullanılsın","ui.server.config.cli":"PHP binary dosyası","ui.server.config.stateErrorCli":"Sunucuda geçerli bir PHP binary dosyası bulunamadı.","ui.server.config.stateErrorCloud":"Composer Resolver Cloud desteklenmiyor.","ui.server.config.stateSuccess":"PHP binary dosyası {php_cli} konumunda.","ui.server.config.cloudEnabled":"Paket bağımlılıkları Composer Resolver Cloud ile çözümlenecek.","ui.server.config.cloudDisabled":"Composer Resolver Cloud kapalı.","ui.server.php_web.title":"PHP site işlemi","ui.server.php_web.below7":"PHP {version} sürümü bulundu. Lütfen en kısa sürede PHP 7 sürümüne geçin!","ui.server.php_web.success":"PHP {version} sürümü bulundu. Bilinen bir sorun bulunamadı.","ui.server.php_cli.title":"PHP komut satırı arayüzü","ui.server.php_cli.success":"PHP {version} sürümü bulundu. Bilinen bir sorun bulunamadı.","ui.server.composer.title":"Composer ortamı","ui.server.composer.success":"Bilinen bir sorun bulunamadı.","ui.server.composer.install":"Composer bağımlılıkları kurulmamış.","ui.server.composer.button":"Kur","ui.server.contao.title":"Contao kurulumu","ui.server.contao.setup":"Kurulum","ui.server.contao.check":"Veri tabanını denetle","ui.server.contao.empty":"Herhangi bir Contao sürümünü bulunamadı.","ui.server.contao.old":"Contao {version} sürümü Contao Manager ile uyumlu değil. Lütfen kurulumunuzu el ile güncelleyin.","ui.server.contao.found":"Contao {version} sürümü bulundu (API sürümü {api}).","ui.server.contao.connectionError":"Veri tabanı sunucusu ile bağlantı kurulamadı.","ui.server.contao.connectionProblem":"Veri tabanı sorunu bulundu.","ui.server.contao.missingUser":"Yönetici hesabı bulunamadı.","ui.setup.continue":"İlerle","ui.setup.manager":"Contao Manager uygulamasını başlat","ui.setup.cancel":"İptal","ui.setup.welcome":"Hoş geldiniz","ui.setup.welcome1":"Bu yardımcı, açık kaynaklı Contao içerik yönetimi sistemi kurulumunu yapmanız için gerekli adımlarda size yol gösterecek.","ui.setup.welcome2":"Herhangi bir sorunuz varsa belgelere, forumlara, Slack kanalına ve {destek} sayfasına bakabilirsiniz.","ui.setup.support":"topluluk desteği","ui.setup.start":"Başlayalım","ui.setup.complete":"Tebrikler!","ui.setup.complete1":"Contao {version} kuruldu.","ui.setup.complete2":"Kurulum işlemini tamamlamak için gereken veri tabanı bağlantısını yapılandırmak ve yönetim bölümü kullanıcısı oluşturacak kurulum aracını açın.","ui.setup.complete3":"Artık Contao yönetim bölümüne giderek sitenizi oluşturmaya başlayabilirsiniz. Çeşitli eklentilere gerek duyuyorsanız Contao Manager ile ilerleyin.","ui.setup.installTool":"Kurulum aracını açın","ui.setup.login":"Contao oturumu açın","ui.setup.funding":"Özgür yazılım, \\"konuşma özgürlüğü\\" ifadesindeki gibi \\"özgürdür\\". \\"Ücretsiz\\" olmasına rağmen o anlama gelmez. Contao gibi bir açık kaynaklı proje, tek bir kişi veya şirket tarafından toplanamayacak miktarda para gerektirir.\\nContao ile oluşturulmuş bir siteniz varsa veya böyle siteler satıyorsanız, işinizin destekleyen ürüne mali katkıda bulunduğunuzu görmek isteriz.","ui.setup.fundingLink":"Ayrıntılı bilgi alın","ui.setup.document-root.headline":"Site sunucusu kurulumu","ui.setup.document-root.warning":"Contao Manager ile Contao kurmak için site sunucusunun belge kök klasörünü düzeltmeniz gerekir.","ui.setup.document-root.description1":"Contao, herkese açık dosyalar için ayrı bir klasör kullanır. Uygulama dosyaları bu klasörün üst klasörüne kurulur. Klasör yapısı doğru değilse veya klasörler boş değilse Contao kurulamaz.","ui.setup.document-root.description2":"Belge kök klasörünüzü nasıl yapılandıracağınızı bilmiyorsanız, Contao belgelerini okuyun ya da barındırma hizmeti sağlayıcınızla görüşün.","ui.setup.document-root.documentation":"Belgeleri okuyun","ui.setup.document-root.conflictsTitle":"Kurulum klasörü boş değil","ui.setup.document-root.conflictsDirectory":"Gelecekteki Contao kurulumunuzun kök klasörü boş değil. Kurulum işlemi tarafından üzerine yazılabilecek {count} dosya bulundu. Contao için boş bir klasör yapısı oluşturmanız önerilir. Ancak kullanılmadıklarından eminseniz aşağıdaki dosyaları silerek yeniden denetleyebilirsiniz.","ui.setup.document-root.ignoreConflicts":"Boş olmayan bir klasöre Contao kurmak istiyorum. Bu işlemin site alanımdaki var olabilecek dosyaların üzerine yazabileceğini anlıyorum.","ui.setup.document-root.check":"Yeniden denetle","ui.setup.document-root.create":"Klasörleri oluştur","ui.setup.document-root.change":"Klasörleri değiştir","ui.setup.document-root.formTitle":"Klasör kurulumu","ui.setup.document-root.formText1":"Contao Manager, otomatik olarak sunucuda yeni bir klasör yapısı oluşturabilir.","ui.setup.document-root.formText2":"Yeni belge kök klasörünü el ile yapılandırmanız gerekir (örneğin, bir barındırma hizmeti yönetim panosu üzerinden).","ui.setup.document-root.autoconfig":"Sunucu yapılandırmamı değiştirmem gerektiğini anlıyorum. Belge kök klasörünü yapılandırmamak Contao Manager uygulamasını bozacak ve yapılandırma dosyalarını (hesap bilgileri ve parolalar ile birlikte) açığa çıkaracak!","ui.setup.document-root.directory":"Yeni klasör","ui.setup.document-root.currentRoot":"Geçerli belge kök klasörü","ui.setup.document-root.newRoot":"Yeni belge kök klasörü","ui.setup.document-root.finish":"Klasörleri kur","ui.setup.document-root.publicDir":"Herkese açık dosyalar için {dir} klasörünü kullanın (Contao {version} için)","ui.setup.document-root.directoryInvalid":"Lütfen geçerli bir klasör adı yazın.","ui.setup.document-root.directoryExists":"Hedef klasör zaten var. Lütfen farklı bir ad yazın.","ui.setup.document-root.confirmation":"Contao Manager, Contao kurulumunuz için gerekli klasörü oluşturdu. Şimdi site sunucunuzda belge kök klasörünü yapılandırmanız gerekiyor. Bu işlemi yapana kadar bu sayfayı yeniden yüklemeyin.","ui.setup.document-root.reload":"Sayfayı yeniden yükle","ui.setup.document-root.success":"Site sunucunuzdaki klasör yapısı doğru şekilde hazırlanmış!","ui.setup.document-root.installingProjectDir":"Uygulama dosyaları {dir} klasörüne kurulacak.","ui.setup.document-root.installingPublicDir":"Herkese açık dosyalar {dir} klasörüne kurulacak.","ui.setup.document-root.installedProjectDir":"Uygulama dosyaları {dir} klasörüne kuruldu.","ui.setup.document-root.installedPublicDir":"Herkese açık dosyalar {dir} klasörüne kuruldu.","ui.setup.create-project.headline":"Contao kurulumu","ui.setup.create-project.description":"Contao geliştirmesi {semver} ilkesini izler. Her altı ayda bir yeni bir küçük sürüm yayınlanır. Şu anda desteklenen sürümler şunlardır:","ui.setup.create-project.semver":"Anlamsal sürümleme","ui.setup.create-project.latestTitle":"Güncel","ui.setup.create-project.ltsTitle":"Uzun dönemli destek","ui.setup.create-project.latestQ1":"Güncel sürümümüz en fazla özelliği sunar ve {year} Şubat ayına kadar desteklenir.","ui.setup.create-project.latestQ3":"Güncel sürümümüz en fazla özelliği sunar ve {year} Ağustos ayına kadar desteklenir.","ui.setup.create-project.ltsText":"Güncel uzun dönem desteklenen sürümümümüz, kararlılık isteyenler içindir. {year} Şubat ayına kadar uzun dönem desteği sunar.","ui.setup.create-project.pltsText":"Önceki uzun dönem desteklenen sürümümüz. Hala {year} Şubat ayına kadar uzun dönem desteği sunuyor.","ui.setup.create-project.requiresPHP":"En az PHP {version} sürümü gereklidir. Sizin sürümünüz PHP {current}.","ui.setup.create-project.releaseplan":"Ayrıntılı bilgi almak için {contaoReleasePlan} bölümüne bakabilirsiniz.","ui.setup.create-project.releaseplanLink":"Contao yayınlanma planı","ui.setup.create-project.installed":"Contao {version} sunucuya kuruldu. Veri tabanınızı kurmaya geçin ya da farklı bir sürüm kurmak için Contao Manager uygulamasını başlatın.","ui.setup.create-project.formTitle":"Bir dağıtım seçin","ui.setup.create-project.formText":"Lütfen kurmak istediğiniz sürümü seçin.","ui.setup.create-project.version":"Sürüm","ui.setup.create-project.demo":"Contao tanıtım sitesini kur","ui.setup.create-project.demoDescription":"Tanıtım sitesi Contao ve onun tüm temel özelliklerini tanımanıza yardımcı olur. Daha fazla temayı {store} üzerinde bulabilirsiniz.","ui.setup.create-project.coreOnly":"En küçük kurulum (yalnızca çekirdek)","ui.setup.create-project.noUpdate":"Kurulumu atla (yalnızca uzmanlar)","ui.setup.create-project.theme":"Contao teması","ui.setup.create-project.themeInstall":"Bir Contao teması kurmak için arama girişini kullanın ya da Contao Manager ile kurulabilen bir tema dosyası (.cto/.zip) yükleyin.","ui.setup.create-project.themeBuy":"Resmi {store} adresini açtığınızdan emin olun.","ui.setup.create-project.themeStore":"Contao tema mağazası","ui.setup.create-project.themeUpload":"Tema dosyasını yükle (.cto/.zip)","ui.setup.create-project.themeInvalid":"Yüklenen dosya bir Contao teması değil ya da Contao Manager uygulamasını desteklemiyor.","ui.setup.create-project.themeWarning":"Contao Manager bu temanın sunucunuzla uyumlu olup olmadığını söyleyemez. Sorularınız varsa lütfen tema satıcısına sorun.","ui.setup.create-project.themeTitle":"Tema bilgilerini gözden geçir","ui.setup.create-project.themeDetails":"Bu temayla birlikte şu bağımlılıklar ve dosyalar yüklenecek.","ui.setup.create-project.themeRequire":"{count} bağımlılık | {count} bağımlılık","ui.setup.create-project.themeFiles":"{count} dosya | {count} dosya","ui.setup.create-project.theme.or":"ya da herkese açık temalar arayın","ui.setup.create-project.theme.search":"Tema ara","ui.setup.create-project.theme.more":"Diğer temalar","ui.setup.create-project.theme.empty":"{query} ile eşleşen bir tema yok","ui.setup.create-project.theme.uploaded":"Tema dosyası yüklendi.","ui.setup.create-project.theme.packageName":"Paket adı","ui.setup.create-project.theme.version":"Sürüm","ui.setup.create-project.theme.authors":"Geliştirici(ler)","ui.setup.create-project.theme.upload":"{name} yükleniyor ({size})","ui.setup.create-project.install":"Kur","ui.setup.create-project.cancel":"İptal","ui.setup.create-project.fileError":"{file} içinde composer.json bulunamadı.","ui.setup.create-project.jsonError":"composer.json içindeki JSON geçersiz.","ui.setup.create-project.schemaError":"composer.json şeması doğrulanamadı.","ui.setup.database-connection.headline":"Veri tabanı bağlantısı","ui.setup.database-connection.description":"Contao, sayfaları, içerikleri, kullanıcıları ve diğer ilişkisel verileri depolamak için bir MySQL veri tabanı (ya da MariaDB gibi uyumlu bir dalı) kullanır. Bağlantı parametreleri, Contao kurulumunuzun proje kök klasöründeki {env} dosyasında bulunur.","ui.setup.database-connection.formTitle":"Bağlantı parametreleri","ui.setup.database-connection.formText":"Bir veri tabanı adresi yazın ya da tek tek kullanıcı adı, parola, sunucu ve veri tabanı alanlarını doldurun.","ui.setup.database-connection.url":"Veri tabanı adresi","ui.setup.database-connection.validUrl":"Veri tabanı adresi geçersiz ya da sunucu bağlantısı kurulamadı.","ui.setup.database-connection.or":"ya da","ui.setup.database-connection.user":"Kullanıcı adı","ui.setup.database-connection.password":"Parola","ui.setup.database-connection.server":"Sunucu (:bağlantı noktası)","ui.setup.database-connection.database":"Veri tabanı adı","ui.setup.database-connection.connected":"{server} üzerindeki {database} veri tabanı ile bağlantı kuruldu.","ui.setup.database-connection.error":"Veri tabanı bağlantısı kurulurken sorun çıktı.","ui.setup.database-connection.problem":"Contao veri tabanı sunucunuzda bir sorunla karşılaştı.","ui.setup.database-connection.schemaTitle":"Veri tabanı şeması","ui.setup.database-connection.migration":"Bekleyen bir aktarım var. | Bekleyen {count} aktarım var.","ui.setup.database-connection.schema":"Bekleyen bir şema güncellemesi var. | Bekleyen {count} şema güncellemesi var.","ui.setup.database-connection.noChanges":"Veri tabanı şemanız güncel","ui.setup.database-connection.check":"Veri tabanını denetle","ui.setup.database-connection.skip":"Atla","ui.setup.database-connection.save":"Kaydet","ui.setup.database-connection.change":"Kimlik doğrulama bilgilerini değiştir","ui.setup.database-connection.restoreTitle":"Veri tabanı içe aktarma","ui.setup.database-connection.restoreText":"Yeni kurduğunuz temada bir veri tabanı yedeği var. Tema verilerini içe aktarmak için veri tabanını geri yükleyin ya da boş bir Contao kurulumuyla başlamak için bu adımı atlayın. | Yeni kurduğunuz temada birkaç veri tabanı yedeği var. Tema verilerini içe aktarmak için bir yedekleme dosyası seçin ya da boş bir Contao kurulumuyla başlamak için bu adımı atlayın.","ui.setup.database-connection.backup":"İçe aktarma işleminden önce geçerli veri tabanının yedeğini alın","ui.setup.database-connection.backupWarning":"İçe aktarım işlemi sırasında veri tabanındaki tüm verilerin üzerine yazılır! Veri tabanı boş değilse öncelikle bir yedeğini alın.","ui.setup.database-connection.restore":"Tema veri tabanını içe aktar","ui.setup.database-connection.restoreOption":"{date} yedeği ({size})","ui.setup.database-connection.restored":"Tema veri tabanınız içe aktarıldı. Veri tabanı şemanızı doğrulamak için ilerleyin.","ui.setup.backend-user.success":"Veri tabanınızda Contao yönetim bölümü için bir yönetici hesabı bulundu. Daha fazla kullanıcı eklemek için Contao yönetim bölümünü kullanın.","ui.setup.backend-user.error":"Kullanıcı listesi alınamadı. Ayrıntılar için konsol çıktısına bakın.","ui.setup.backend-user.headline":"Yönetim bölümü hesabı","ui.setup.backend-user.description":"Sitenizi yönetmek için Contao yönetim bölümüne erişebilecek en az bir yönetici hesabınızın olması gerekir. Bu hesabın Contao Manager ile ilgili olmadığını unutmayın.","ui.setup.backend-user.formTitle":"Hesap aç","ui.setup.backend-user.formText":"Yeni yönetim bölümü hesabının ayrıntılarını yazın.","ui.setup.backend-user.username":"Kullanıcı adı","ui.setup.backend-user.name":"Ad","ui.setup.backend-user.email":"E-posta adresi","ui.setup.backend-user.emailInvalid":"Lütfen geçerli bir e-posta adresi yazın","ui.setup.backend-user.password":"Parola","ui.setup.backend-user.passwordPlaceholder":"en az 8 karakter","ui.setup.backend-user.passwordLength":"Lütfen en az 8 karakter yazın.","ui.setup.backend-user.create":"Hesap ekle","ui.task.headline":"Arka plan görevi","ui.task.loading":"Ayrıntılar yükleniyor…","ui.task.created":"Ayrıntılar yükleniyor…","ui.task.active":"Lütfen Contao Manager arka planda görev işlemlerini yürütürken bekleyin.","ui.task.complete":"Tüm işlemler tamamlandı. Ayrıntılı bilgi almak için konsol çıktısına bakın.","ui.task.paused":"Bir arka plan görevi beklenmedik şekilde durdu. Lütfen konsol çıktısını denetleyin.","ui.task.aborting":"Lütfen arka plan işlemleri iptal edilirken bekleyin.","ui.task.stopped":"Bazı arka plan görevleri iptal edildi. Lütfen konsol çıktısını denetleyin.","ui.task.error":"Bir arka plan görevi beklenmedik şekilde durdu. Lütfen konsol çıktısını denetleyin.","ui.task.failed":"Contao Manager bir arka plan görevini başlatamadı!","ui.task.failedDescription1":"İşlemler arka planda yürütülmeye çalışılırken bir sorun çıktı.","ui.task.failedDescription2":"Bu sorun yeniden yaşanırsa sunucunuz desteklenmiyor olabilir.","ui.task.reportProblem":"Sorun bildir","ui.task.pausedDescription":"Hatayı yok saymak ve kalan işlemleri gerçekleştirmek istiyorsanız \\"İlerle\\" üzerine tıklayın.","ui.task.sponsor":"Composer Cloud {sponsor} tarafından destekleniyor","ui.task.buttonAudit":"Veri tabanını güncelle","ui.task.buttonClose":"Kapat","ui.task.buttonConfirm":"Onaylayıp kapat","ui.task.buttonContinue":"İlerle","ui.task.buttonCancel":"İptal","ui.task.confirmCancel":"Bu görevi iptal etmek istediğinize emin misiniz? Bu durum Contoa kurulumunuzu bozuk bir durumda bırakabilir!","ui.task.autoclose":"Başarılı işlemlerin görev ayrıntıları kapatılsın","ui.console.toggle":"Konsol çıktısını görüntüle/gizle","ui.console.showLog":"Tüm konsol günlüğünü görüntüle","ui.console.copyLog":"Günlüğü panoya kopyala","ui.migrate.headline":"Veri tabanı güncellemeleri","ui.migrate.migrationsOnly":"(yalnızca aktarımlar)","ui.migrate.schemaOnly":"(yalnızca şema)","ui.migrate.loading":"Lütfen veri tabanınız incelenirken bekleyin…","ui.migrate.empty":"Bekleyen bir aktarım ya da şema güncellemesi bulunamadı. Veri tabanınız güncel.","ui.migrate.emptyMigrations":"Bekleyen bir aktarım bulunamadı. Şema güncellemelerini de denetlediğinizden emin olun.","ui.migrate.emptySchema":"Bekleyen bir şema güncellemesi bulunamadı. Aktarımları da denetlediğinizden emin olun.","ui.migrate.pending":"Veri tabanınız güncel değil. Lütfen aşağıdaki konsol çıktısını denetleyip istenilen değişiklikleri yapın.","ui.migrate.previousChanges":"Daha önceki bir veri tabanı aktarma işlemi onaylanmamış.\\nLütfen aşağıdaki konsol çıktısını denetleyip sonraki değişiklikleri görmek için ilerleyin.","ui.migrate.previousComplete":"Daha önceki bir veri tabanı aktarma işlemi onaylanmamış. Lütfen aşağıdaki konsol çıktısını denetleyin. Bekleyen başka bir değişiklik yok.","ui.migrate.appliedChanges":"Veri tabanı güncellemeleri yapıldı.\\nLütfen aşağıdaki konsol çıktısını denetleyip sonraki değişiklikleri görmek için ilerleyin.","ui.migrate.appliedComplete":"Veri tabanı güncellemeleri yapıldı.\\nBekleyen başka bir aktarım ya da şema güncellemesi yok. Veri tabanınız güncel.","ui.migrate.problem":"Contao, veri tabanı sunucunuzda bazı sorunlarla karşılaştı.\\nNeyin düzeltilmesi gerektiğini öğrenmek için aşağıdaki konsol çıktısını inceleyin. | Contao, veri tabanı sunucunuzda bazı sorunlarla karşılaştı.\\nNeyin düzeltilmesi gerektiğini öğrenmek için aşağıdaki konsol çıktısını inceleyin.","ui.migrate.warning":"Contao, veri tabanı sunucunuzun yanlış yapılandırıldığını algıladı.\\nUyarıları geçici olarak atlayabilirsiniz. Ancak en iyi başarım ve veri bütünlüğü için bu sorunları düzeltmelisiniz.","ui.migrate.error":"Değişiklikler uygulanamadı. Veri tabanınız değişmiş olabilir. Lütfen yeniden denetleyin.","ui.migrate.execute":"Yürüt","ui.migrate.close":"Kapat","ui.migrate.confirm":"Onaylayıp kapat","ui.migrate.cancel":"İptal","ui.migrate.continue":"İlerle","ui.migrate.setup":"Kurulum","ui.migrate.skip":"Atla","ui.migrate.retry":"Yeniden denetle","ui.migrate.retryAll":"Tümünü denetle","ui.migrate.withDeletes":"DROP sorguları ile birlikte tüm veri tabanı değişikliklerini yürütür.","ui.migrate.migrationTitle":"Veri tabanı aktarımları","ui.migrate.schemaTitle":"Şema güncellemeleri","ui.migrate.problemTitle":"Veri tabanı sorunları","ui.migrate.warningTitle":"Veri tabanı uyarıları","ui.migrate.addTable":"{table} tablosunu ekle","ui.migrate.dropTable":"{table} tablosunu sil","ui.migrate.addField":"{table}.{field} alanını ekle","ui.migrate.changeField":"{table}.{field} alanını değiştir","ui.migrate.dropField":"{table}.{field} alanını sil","ui.migrate.createIndex":"{table} tablosuna \\"{name}\\" dizinini ekle ","ui.migrate.dropIndex":"{table} tablosundan \\"{name}\\" dizinini kaldır","ui.widget.mandatory":"Bu alan boş bırakılamaz.","ui.widget.blankOption":"Lütfen seçin…","ui.widget.showPassword":"Parolayı görüntüle","ui.widget.hidePassword":"Parolayı gizle","ui.error.title":"\\"{method} {url}\\" için HTTP isteği başarısız oldu.","ui.error.server500":"Sunucunuzda beklenmeyen bir sorun çıkmış gibi görünüyor. Lütfen site sunucunuzun (Apache/Nginx) günlük dosyalarını ve \\"contao-manager/logs\\" konumundaki Contao Manager günlüklerini denetleyin.","ui.error.response":"Sunucu, {status} durum koduyla bir yanıt verdi.","ui.error.moreLink":"Ayrıntılı bilgiler","ui.error.support":"Contao desteği","ui.error.permission":"Bu özelliği kullanma izniniz yok.","ui.footer.help":"Yardım","ui.footer.reportProblem":"Sorun bildir","ui.navigation.discover":"Keşfet","ui.navigation.packages":"Paketler","ui.navigation.tools":"Araçlar","ui.navigation.installTool":"Kurulum aracı","ui.navigation.backend":"Contao yönetim bölümü","ui.navigation.debug":"Contao hata ayıklama kipi","ui.navigation.logViewer":"Günlük görüntüleyici","ui.navigation.phpinfo":"PHP bilgileri","ui.navigation.phpinfoLoading":"PHP bilgileri yükleniyor…","ui.navigation.maintenance":"Bakım","ui.navigation.rebuildCache":"Ön belleği yeniden oluştur","ui.navigation.users":"Hesaplar","ui.navigation.systemCheck":"Sistem denetimi","ui.navigation.advanced":"Gelişmiş","ui.navigation.logout":"Oturumu kapat","ui.maintenance.database.title":"Veri tabanı aktarımları ve yedekler","ui.maintenance.database.description":"Veri tabanı aktarımları verilerin ve tablo şemalarının tutarlı olduğundan emin olur.","ui.maintenance.database.migrations":"Bekleyen bir veri tabanı aktarımı var | Bekleyen {count} veri tabanı aktarımı var","ui.maintenance.database.schemaUpdates":"Bekleyen bir şema güncellemesi var. | Bekleyen {count} şema güncellemesi var","ui.maintenance.database.error":"Veri tabanı sorunu bulundu.","ui.maintenance.database.warning":"Veri tabanı uyarıları bulundu.","ui.maintenance.database.button":"Veri tabanını denetle","ui.maintenance.database.migrationOnly":"Yalnızca aktarımları denetle","ui.maintenance.database.schemaOnly":"Yalnızca şemayı denetle","ui.maintenance.database.installTool":"Kurulum aracını aç","ui.maintenance.database.createBackup":"Yedek oluştur","ui.maintenance.database.backupUnsupported":"Contao sürümünüzde veri tabanı yedekleri desteklenmiyor.","ui.maintenance.database.backupList":"{date} tarihinde oluşturulmuş bir veri tabanı yedeğiniz var. | {count} veri tabanı yedeğiniz var. En sonuncusu {date} tarihinde oluşturulmuş.","ui.maintenance.database.backupEmpty":"Şu anda herhangi bir veri tabanı yedeğiniz yok.","ui.maintenance.rebuildCache.title":"Uygulama ön belleği","ui.maintenance.rebuildCache.description":"Yapılandırma dosyalarında bir değişiklik yapıldığında uygulama ön belleğinin yeniden oluşturulması gerekir.","ui.maintenance.rebuildCache.rebuildProd":"Üretim ön belleğini yeniden oluştur","ui.maintenance.rebuildCache.rebuildDev":"Geliştirme ön belleğini yeniden oluştur","ui.maintenance.rebuildCache.clearProd":"Üretim ön belleğini temizle","ui.maintenance.rebuildCache.clearDev":"Geliştirme ön belleğini temizle","ui.maintenance.installTool.title":"Contao kurulum aracı","ui.maintenance.installTool.description":"Arka arkaya üç kez yanlış parola yazarsanız Contao kurulum aracı otomatik olarak kilitlenir.","ui.maintenance.installTool.unlock":"Kurulum aracının kilidini aç","ui.maintenance.installTool.lock":"Kurulum aracını kilitle","ui.maintenance.dumpAutoload.title":"Composer sınıf yükleyicisi","ui.maintenance.dumpAutoload.description":"Composer otomatik yükleyici, PHP sınıfının yüklenmesinden sorumludur. Kök klasördeki composer.json dıosyasına özel ad alanları eklendikten sonra otomatik yükleyici indirilmelidir.","ui.maintenance.dumpAutoload.button":"Otomatik yükleyiciyi indir","ui.maintenance.composerInstall.title":"Composer bağımlılıkları","ui.maintenance.composerInstall.description":"Composer bağımlılıkları uygulama kök klasörünüzün altındaki [vendor] klasöründe bulunur. [composerLock] dosyası değiştirildikten ya da el ile yüklendikten sonra bağımlılıkları yeniden kurmak gerekebilir.","ui.maintenance.composerInstall.button":"Kurucuyu başlat","ui.maintenance.composerInstall.update":"Composer güncellemesini başlat","ui.maintenance.composerCache.title":"Composer ön belleği","ui.maintenance.composerCache.description":"Composer, daha iyi başarım sağlamak için indirilen paketleri ön belleğe alır. Ön bellekte bozuk dosyalar gibi sorunlarınız varsa, paketlerin yeniden indirilmesini dayatmak için Composer ön belleğini silmeyi deneyin.","ui.maintenance.composerCache.button":"Ön belleği temizle","ui.maintenance.maintenanceMode.title":"Bakım kipi","ui.maintenance.maintenanceMode.description":"Contao bakım kipine geçirildiğinde, sitede \\"503 Hizmet Kullanılamıyor\\" kalıbı görüntülenir.","ui.maintenance.maintenanceMode.enable":"Etkinleştir","ui.maintenance.maintenanceMode.disable":"Etkisizleştir","ui.maintenance.debugMode.title":"Hata ayıklama kipi","ui.maintenance.debugMode.description":"[appDevPhp] giriş noktası için bir kullanıcı adı ve parola ayarlayarak hata ayıklama kipini etkinleştirin.","ui.maintenance.debugMode.descriptionJwt":"Geçerli etki alanı için hata ayıklama çerezini ayarlayarak hata ayıklama kipini etkinleştirin.","ui.maintenance.debugMode.activate":"Etkinleştir","ui.maintenance.debugMode.deactivate":"Etkisizleştir","ui.maintenance.debugMode.credentials":"Kimlik doğrulama bilgileri","ui.maintenance.debugMode.user":"Lütfen hata ayıklama kipi için bir kullanıcı adı yazın.","ui.maintenance.debugMode.password":"Lütfen hata ayıklama kipi için bir parola yazın.","ui.maintenance.opcodeCache.title":"Opcode ön belleği","ui.maintenance.opcodeCache.description":"Opcode, daha hızlı işlem yapmak için PHP dosyalarını site işleminde ön belleğe alır. Dosyaların değiştirildikten sonra tanınmaması gibi belirli durumlarda silinmelidir.","ui.maintenance.opcodeCache.button":"Ön belleği buda","ui.maintenance.safeMode":"Güvenli kipte kullanılamaz","ui.maintenance.unsupported":"Contao sürümünüz tarafından desteklenmiyor","ui.packages.updateButton":"Paketleri güncelle","ui.packages.searchButton":"Paket arama","ui.packages.searchPlaceholder":"Paketleri ara…","ui.packages.uploadOverlay":"Yüklemek için dosyaları sürükleyip buraya bırakın","ui.packages.uploadButton":"Paketleri yükle","ui.packages.uploadMessage":"Bir onaylanmamış yüklemeniz var. | {count} onaylanmamış yüklemeniz var.","ui.packages.uploadApply":"Yüklemeleri onayla","ui.packages.uploadReset":"Yüklemeleri sil","ui.packages.uploadIncomplete":"Bu dosya tam olarak yüklenmedi. Lütfen kaldırıp yeniden deneyin.","ui.packages.uploadDuplicate":"Bu dosya birden çok kez yüklenmiş gibi görünüyor. Lütfen kopyaları kaldırın.","ui.packages.uploadInstalled":"Bu dosya zaten kurulmuş. Lütfen kopyaları kaldırın.","ui.packages.uploadUnsupported":"Kurulumunuzda yükleme özelliği desteklenmiyor. Lütfen PHP ZIP eklentisinin kurulmuş olduğundan ve bağımlılıklarınızı güncellediğinizden emin olun.","ui.packages.changesMessage":"Bir onaylanmamış değişikliğiniz var. | {count} onaylanmamış değişikliğiniz var.","ui.packages.changesDryrun":"Değişiklik yapmadan dene","ui.packages.changesApply":"Değişiklikleri uygula","ui.packages.changesApplyAll":"Tüm paketleri güncelle","ui.packages.changesDryrunAll":"Tüm paketleri değişiklik yapmadan dene","ui.packages.changesReset":"Değişiklikleri sıfırla","ui.packages.changesReview":"Değişiklikleri gözden geçir","ui.packagelist.loading":"Yükleniyor…","ui.packagelist.uploads":"Yüklemeler","ui.packagelist.added":"Yeni paketler","ui.packagelist.installed":"Kurulmuş paketler","ui.package.hintRevert":"Değişiklikleri geri al","ui.package.hintNoupdate":"Güncelleme","ui.package.hintConstraint":"Değişiklikleri uyguladığınızda, bu paket {constraint} kısıtlaması ile kurulacak.","ui.package.hintConstraintBest":"Değişiklikleri uyguladığınızda, bu paket kullanılabilecek en iyi sürüm ile kurulacak.","ui.package.hintConstraintChange":"Değişiklikleri uyguladığınızda, bu paketin kısıtlamaları \\"{from}\\" yerine \\"{to}\\" olarak değiştirilecek.","ui.package.hintConstraintUpdate":"Değişiklikleri uyguladığınızda, bu paket güncellenecek.","ui.package.hintAdded":"Değişiklikleri uyguladığınızda, bu paket kurulacak.","ui.package.hintRemoved":"Değişiklikleri uyguladığınızda, bu paket kaldırılacak.","ui.package.requiredTitle":"el ile eklendi","ui.package.requiredText":"Bu paket composer.json dosyanızda gerekli olarak belirtilmiş ancak kurulmamış.","ui.package.removedTitle":"el ile kaldırıldı","ui.package.removedText":"Bu paket composer.json dosyanızdan kaldırılmış.","ui.package.installed":"Şu anda kurulu olan:","ui.package.version":"{version} sürümü","ui.package.additionalDownloads":"{count} indirme | {count} indirme","ui.package.additionalStars":"{count} yıldız | {count} yıldız","ui.package.editConstraint":"Düzenle","ui.package.uploadConstraint":"Bu kısıtlama yüklenen paket tarafından tanımlandı.","ui.package.updateButton":"Güncelle","ui.package.removeButton":"Kaldır","ui.package.installButton":"Paket ekle","ui.package.installButtonShort":"Ekle","ui.package.detailsButton":"Ayrıntılar","ui.package.latestConstraint":"güncel sürüm","ui.package.update":"Güncelleme yayınlanmış","ui.package.updateLatest":"güncel sürüm","ui.package.updateAvailable":"{version} yayınlanmış","ui.package.updateUnknown":"sürüm bilinmiyor","ui.package.updateConstraint":"Sürüm kısıtlamanızın dışında yeni bir sürüm yayınlanmış.","ui.package.incompatible":"{package} Contao {constraint} ile çalışmayacak.","ui.package.incompatibleWarning":"{Package} kararlı sürümlerinin hiçbiri Contao {constraint} ile çalışmaz. Bir geliştirme dalı kurmayı denemek için paketi eklemek ve bir sürüm kısıtlaması ayarlamak ister misiniz?","ui.package.incompatibleConstraint":"Bu paketin Contao {constraint} için kararlı bir sürümü yok. Bir geliştirme dalı kurmayı denemek için bir sürüm kısıtlaması ayarlayın.","ui.package.incompatibleButton":"Kur","ui.cloudStatus.headline":"Composer Resolver Cloud","ui.cloudStatus.version":"{version} sürümü","ui.cloudStatus.waitingTime":"Bekleme zamanı","ui.cloudStatus.jobs":"Geçerli görevler","ui.cloudStatus.workers":"İşlemler","ui.cloudStatus.approx":"{minutes} dakika","ui.cloudStatus.none":"yok","ui.cloudStatus.short":"ca. {minutes} dakika","ui.cloudStatus.long":"ca. {minutes} dakika {seconds} saniye","ui.cloudStatus.error":"Composer Resolver Cloud durumu alınamıyor. Kaynak bakım yüzünden kapalı ya da sorunlar nedeniyle erişilemiyor olabilir.","ui.cloudStatus.button":"Cloud durumu","ui.cloudStatus.refresh":"Cloud durumunu yenile","ui.log-viewer.loading":"Yükleniyor…","ui.log-viewer.empty":"Sunucunuzda herhangi bir günlük dosyası yok.","ui.log-viewer.reload":"Yeniden yükle","ui.log-viewer.file":"Günlük dosyası","ui.log-viewer.channel":"Kanal","ui.log-viewer.channelTitle":"Bu iletinin günlüğe kaydedileceği kanal.","ui.log-viewer.level":"Düzey","ui.log-viewer.levelTitle":"Günlük iletisinin önem düzeyi.","ui.log-viewer.timeHeader":"Zaman","ui.log-viewer.messageHeader":"İleti","ui.log-viewer.showContext":"Bağlamı görüntüle","ui.log-viewer.hideContext":"Bağlamı gizle","ui.log-viewer.showExtra":"Ekleri görüntüle","ui.log-viewer.hideExtra":"Ekleri gizle","ui.log-viewer.more":"Sonrakileri yükle…","ui.log-viewer.download":"İndir","ui.log-viewer.downloadTitle":"\\"{file}\\" dosyasını indir","ui.log-viewer.prodEnvironment":"Üretim ortamı","ui.log-viewer.devEnvironment":"Geliştirme ortamı (hata ayıklama kipi)","ui.user-manager.loading":"Kullanıcılar yükleniyor…","ui.user-manager.changePassword":"Parolayı değiştir","ui.user-manager.setupTotp":"İki adımlı doğrulamayı kur","ui.user-manager.disableTotp":"İki adımlı doğrulamayı kapat","ui.user-manager.invite":"Kullanıcı davet et","ui.user-manager.delete":"Sil","ui.user-manager.deleteConfirm":"\\"{username}\\" kullanıcısını silmek istediğinize emin misiniz?","ui.user-manager.deleted":"{username} kullanıcı adı silindi","ui.user-manager.passwordHeadline":"Parolayı değiştir","ui.user-manager.passwordText":"Parolanızı değiştirmek için, ilgili alanlara geçerli ve yeni parolayı yazın.","ui.user-manager.currentPassword":"Geçerli parola","ui.user-manager.newPassword":"Yeni parola","ui.user-manager.passwordPlaceholder":"en az 8 karakter","ui.user-manager.submitPassword":"Gönder","ui.user-manager.passwordChanged":"Parolanız değiştirildi.","ui.user-manager.passwordError":"Parola yanlış.","ui.user-manager.inviteHeadline":"Kullanıcı davet et","ui.user-manager.inviteText":"Contao Manager için birden fazla oturum açmaya gerek duyuyorsanız, buradan bir davet bağlantısı oluşturabilirsiniz. Bu bağlantıyı biriyle paylaşın veya verilen izinlerle yeni bir hesap açmak için başka bir aygıt üzerinde kullanın.","ui.user-manager.inviteSuccess1":"Yeni bir davet bağlantısı oluşturuldu. Aşağıdaki adres, bu Contao Manager üzerinde yeni bir kullanıcı hesabı oluşturmak için kullanılabilir. Davetiyenin geçerliliği {expires} tarihinde sona erecek (bir hafta sonra).","ui.user-manager.inviteSuccess2":"Lütfen bağlantıyı panonuza kopyalayın. Yalnızca bir kez çalışacak ve bu pencereyi kapattıktan sonra yeniden göremeyeceksiniz.","ui.user-manager.createInvitation":"Davet bağlantısı oluştur","ui.user-manager.clipboard":"Panoya kopyala","ui.user-manager.permissions":"İzinler hakkında bilgi alın","ui.user-manager.cancel":"İptal","ui.user-manager.close":"Kapat","ui.user-manager.you":"Siz","ui.user-manager.2fa":"İki adımlı doğrulama","ui.user-manager.2faEnabled":"Bu hesap iki adımlı doğrulama ile korunuyor.","ui.user-manager.2faDisabled":"Bu hesap iki adımlı doğrulama kullanmadığından güvende değil.","ui.user-manager.passkey":"Geçiş anahtarı","ui.user-manager.passkeyTitle":"Bu hesap bir geçiş anahtarı ile korunuyor.","ui.totp.headline":"İki adımlı doğrulama","ui.totp.setupQr":"Lütfen kare kodu iki adımlı doğrulama uygulamanızla tarayın.","ui.totp.setupCode":"Kare kodu tarayamıyorsanız şu anahtarı yazabilirsiniz:","ui.totp.codeLabel":"Doğrulama kodu","ui.totp.codeDescription":"Lütfen iki adımlı doğrulama uygulamanızın ürettiği doğrulama kodunu yazın.","ui.totp.disableText":"İki adımlı doğrulamayı kapatmak için lütfen doğrulama kodunu yazın.","ui.totp.invalid":"Doğrulama kodu geçersiz.","ui.totp.enable":"Etkinleştir","ui.totp.disable":"Etkisizleştir","ui.totp.cancel":"İptal","ui.totp.enabled":"İki adımlı doğrulama açıldı.","ui.totp.disabled":"İki adımlı doğrulama kapatıldı.","ui.totp.setup":"İki adımlı doğrulamayı kur","ui.totp.skip":"İki adımlı doğrulamayı atla"}')}}]);"use strict";(self["webpackChunkcontao_manager"]=self["webpackChunkcontao_manager"]||[]).push([[716],{3716:function(e){e.exports=JSON.parse('{"ui.app.title":"Rozszerzenia Contao","ui.app.loading":"Ładowanie listy rozszerzeń …","ui.app.language":"Switch language for the Contao Manager","ui.app.colorDark":"Dark Mode","ui.app.colorDarkTitle":"Switch color scheme to dark","ui.app.colorLight":"Light Mode","ui.app.colorLightTitle":"Switch color scheme to light","ui.discover.advertisement":"Reklama w liście rozszerzeń","ui.discover.loading":"Ładowanie …","ui.discover.offline":"Nie znaleziono żadnych wyników.","ui.discover.offlineExplain":"Sprawdź swoje połączenie internetowe i wyłącz narzędzia blokujące JavaScript w przeglądarce.","ui.discover.offlineButton":"Spróbuj ponownie","ui.discover.searchPlaceholder":"Szukaj w {count} rozszerzeniach ...","ui.discover.empty":"Brak wyników dla {query}","ui.discover.more":"Więcej Wyników","ui.discover.sortBy":"Sortuj według","ui.discover.sortReleased":"Released","ui.discover.sortReleasedTitle":"Sort results by release date","ui.discover.sortLatest":"Data aktualizacji","ui.discover.sortLatestTitle":"Sort results by last updated","ui.discover.sortDownloads":"Pobrania","ui.discover.sortDownloadsTitle":"Sort results by number of downloads","ui.discover.sortFavers":"Ocena","ui.discover.sortFaversTitle":"Sort results by rating","ui.discover.detailsButton":"Szczegóły","ui.discover.latestPackages":"Najnowsze i zaktualizowane rozszerzenia","ui.discover.faversPackages":"Najwyżej oceniane rozszerzenia","ui.discover.downloadsPackages":"Najczęściej pobierane rozszerzenia","ui.discover.exactHit":"Exact query match","ui.discover.results":"More search results","ui.package.homepage":"Strona Projektu","ui.package.private":"Prywatny Pakiet","ui.package.privateTitle":"Prywatne pakiety są dostępne tylko bezpośrednio od dostawcy (np. jako plik ZIP). Odwiedź stronę po więcej informacji.","ui.package.abandoned":"porzucony","ui.package.abandonedText":"Ten pakiet jest porzucony i nie jest już wspierany.","ui.package.abandonedReplace":"Ten pakiet jest porzucony i nie jest już wspierany. Autor sugeruje użycie pakietu {replacement} zamiast niego.","ui.package.contaoVersion":"Available for Contao","ui.package-details.previous":"Szczegóły poprzedniego rozszerzenia","ui.package-details.close":"Zamknij szczegóły rozszerzenia","ui.package-details.loading":"Ładowanie …","ui.package-details.tabDescription":"Opis","ui.package-details.tabRequire":"Wymagania","ui.package-details.tabFeatures":"Funkcjonalności","ui.package-details.tabSuggest":"Sugestie","ui.package-details.tabConflict":"Konflikty","ui.package-details.tabDependents":"Zależności","ui.package-details.linkRequires":"wymaga","ui.package-details.linkReplaces":"zastępuje","ui.package-details.linkProvides":"dostarcza","ui.package-details.linkConflicts":"koliduje","ui.package-details.funding":"Finansuj rozwój pakietu!","ui.package-details.contaoVersions":"Supported Contao version(s)","ui.package-details.latest":"Ostatnia wersja","ui.package-details.released":"data wydania","ui.package-details.license":"Licencje","ui.package-details.authors":"od","ui.package-details.more":"Więcej","ui.package-details.packagist":"Szczegóły Pakietu","ui.package-details.metadata":"Edytuj metadane","ui.package-details.support_docs":"Dokumentacja","ui.package-details.support_wiki":"Wiki","ui.package-details.support_forum":"Forum","ui.package-details.support_issues":"Issues / Bug Report","ui.package-details.support_source":"Kod źródłowy","ui.package-details.support_irc":"IRC / Chat","ui.package-details.support_email":"Wsparcie E-mail","ui.package-details.support_rss":"Kanał RSS"}')}}]);"use strict";(self["webpackChunkcontao_manager"]=self["webpackChunkcontao_manager"]||[]).push([[706],{2706:function(e){e.exports=JSON.parse('{"ui.app.httpsHeadline":"!! Conexión insegura !!","ui.app.httpsDescription":"Sin HTTPS, sus datos confidenciales se transferirán sin cifrar.","ui.app.httpsLink":"Mas información","ui.app.httpsHref":"https://https.cio.gov/everything/","ui.app.safeModeHeadline":"¡Modo seguro habilitado!","ui.app.safeModeDescription":"Algunas funciones de Contao Manager no están disponibles.","ui.app.safeModeExit":"Salida del modo seguro","ui.app.limitedHeadline":"Autenticación remota ","ui.app.limitedDescription":"Tiene permisos limitados debido al inicio de sesión sin contraseña.","ui.app.limitedLogout":"Volver a autenticar","ui.app.totpHeadline":"Aviso de seguridad","ui.app.totpDescription":"Configure la autenticación de dos factores ahora para proteger su cuenta.","ui.app.totpSetup":"Configuración","ui.app.loading":"Cargando Contao Manager ...","ui.app.apiError":"Estado inesperado de la API","ui.app.configSecurity1":"ALERTA DE SEGURIDAD !!! Detectado directorio de configuración desprotegido","ui.app.configSecurity2":"Contao Manager ha detectado que sus archivos de configuración son de acceso público. Todas las operaciones están deshabilitadas hasta que el directorio esté seguro; de lo contrario, un atacante podría acceder a datos confidenciales de su instalación.\\n\\nPara solucionar este problema, asegúrese de evitar el acceso al directorio \\"contao-manager\\" en su servidor. Para saber cómo hacer esto, consulte el manual de su servidor web o póngase en contacto con su proveedor de alojamiento.","ui.account.welcome":"Bienvenido","ui.account.intro1":"Bienvenido a Contao Manager, una herramienta universal para instalar y administrar Contao Open Source CMS. Si es nuevo en esto, {readTheManualToGetStarted}.","ui.account.introGetStarted":"{readTheManual} para comenzar","ui.account.introManual":"lea el manual","ui.account.intro2":"Si encuentra algún problema, consulte {ourGithubIssues} y siéntase libre de crear uno nuevo para cualquier cosa que aún no se haya informado.","ui.account.introIssues":"nuestros problemas de GitHub","ui.account.headline":"Cuenta de usuario","ui.account.description":"Para administrar su instalación, cree una cuenta para Contao Manager. Tenga en cuenta que esta cuenta no está relacionada con el back end o front end de Contao.","ui.account.username":"Nombre de usuario","ui.account.password":"Contraseña","ui.account.passwordPlaceholder":"min. 8 caracteres","ui.account.passwordLength":"Por favor introduzca al menos 8 caracteres.","ui.account.loginInvalid":"Se produjo un error al crear la cuenta. Intente con otro nombre de usuario.","ui.account.submit":"Crear una cuenta","ui.account.usePassword":"Utilice contraseña para iniciar sesión","ui.account.usePasskey":"Utilice la clave de acceso (Passkey) para iniciar sesión","ui.account.totpHeadline":"Autenticación de dos factores","ui.account.totpDescription":"Habilite la autenticación de dos factores, que agrega una capa adicional de seguridad a su cuenta. Además de su nombre de usuario y contraseña, deberá ingresar un código de verificación generado por una aplicación de dos factores como 1Password, Authy, Google Authenticator, Microsoft Authenticator, LastPass Authenticator o cualquier otra aplicación TOTP.","ui.account.totpSetup":"Configurar ahora","ui.account.totpSkip":"Configurar más tarde","ui.account.login":"Rechazar invitación","ui.account.contribute1":"Contao y Contao Manager están patrocinados por la Asociación Contao sin fines de lucro.","ui.account.contribute2":"Considere contribuir al código abierto con {donate}.","ui.account.contributeDonate":"hacer una donación","ui.login.headline":"Registrarse","ui.login.description":"Inicie sesión para administrar su instalación.","ui.login.username":"Nombre de usuario","ui.login.password":"Contraseña","ui.login.totpHeadline":"Autenticación de dos factores","ui.login.totpDescription":"Ingrese su código de verificación para completar el proceso de inicio de sesión.","ui.login.totp":"Código de verificación","ui.login.forgotPassword":"¿Ha olvidado su contraseña?","ui.login.button":"Registrarse","ui.login.passkey":"Iniciar sesión con clave de acceso (Passkey)","ui.login.cancel":"Cancelar","ui.login.or":"o","ui.login.locked":"Se ha denegado el acceso porque Contao Manager está bloqueado. Para desbloquear, elimine el archivo {lockFile} en su directorio raíz de Contao.","ui.logout.headline":"Timeout de la sesión","ui.logout.warning":"Ha estado inactivo por más de 25 minutos. Por razones de seguridad, su sesión finalizará en breve.","ui.logout.expired":"Su sesión finalizó automáticamente porque ha estado inactivo durante más de 30 minutos.","ui.logout.renew":"Mantener conectado","ui.logout.logout":"Cerrar sesión","ui.logout.login":"Volver para iniciar sesión","ui.oauth.error":"Intento de OAuth no válido Verifique los parámetros de solicitud.","ui.oauth.https":"El URI de redireccionamiento DEBE usar un protocolo seguro (https :) para evitar que el token de autenticación se transmita en texto sin cifrar. ","ui.oauth.headline":"Autenticación remota ","ui.oauth.description":"La siguiente aplicación o servicio está solicitando acceso remoto a su instancia del Contao Manager.","ui.oauth.domain":"Antes de permitir el acceso, asegúrese de conocer esta URL y confíe en su propietario.","ui.oauth.outOfScope":"Lamentablemente, no tienes los permisos necesarios para otorgar este acceso.","ui.oauth.allow":"Permitir el acceso","ui.oauth.deny":"Acceso denegado","ui.oauth.switchUser":"Cambiar de usuario","ui.scope.admin":"Acceso de administrador, incluida la gestión de usuarios","ui.scope.install":"Instalar nuevos paquetes y cambiar la configuración de Contao","ui.scope.update":"Actualizar paquetes y ejecutar tareas de mantenimiento","ui.scope.read":"Leer paquetes y configuración","ui.boot.headline":"Comprobar sistema","ui.boot.description":"Por favor espere, estamos analizando su servidor ...","ui.boot.issue1":"Se han detectado problemas de instalación","ui.boot.issue2":"Su instalación tiene problemas que deben solucionarse antes de que se pueda utilizar Contao Manager.","ui.boot.run":"Lanzamiento de Contao Manager","ui.boot.safeMode":"Lanzamiento en modo seguro","ui.recovery.headline":"Recuperación del sistema","ui.recovery.description":"El Contao Manager detectó archivos que se parecen a Contao, pero la Interfaz de línea de comandos no funciona como se esperaba.","ui.recovery.console":"Salida de consola","ui.recovery.repairOptions":"Por favor, elija una opción para reparar su instalación.","ui.recovery.repairHeadline":"Reparación automática","ui.recovery.repairDescription":"Intenta reparar automáticamente la instalación reconstruyendo el caché de la aplicación y reinstalando los paquetes de Composer.","ui.recovery.repairWarning":"¡Cualquier modificación de los archivos del proveedor podría ser eliminada en el proceso!","ui.recovery.repairFailed":"La reparación automática no tuvo éxito. Pruebe el Modo seguro para reparar manualmente la instalación.","ui.recovery.repairButton":"Ejecutar la reparación del sistema","ui.recovery.safeModeHeadline":"Modo seguro","ui.recovery.safeModeDescription":"Iniciar el Contao Manager en Modo seguro permite administrar paquetes y ejecutar ciertas tareas de mantenimiento, pero las funciones que dependen de una instalación de Contao que funcione no estarán disponibles.","ui.recovery.safeModeButton":"Lanzamiento en modo seguro","ui.server.pending":"Esperando …","ui.server.running":"Analizando ...","ui.server.error":"La comprobación falló debido a una respuesta inesperada del servidor.","ui.server.details":"Detalles","ui.server.prerequisite":"Verificación cancelada debido a un prerrequisito faltante.","ui.server.selfUpdate.title":"Actualizaciones del Contao Manager","ui.server.selfUpdate.update":"Una nueva versión {latest} de Contao Manager está disponible.","ui.server.selfUpdate.manualUpdate":"Hay disponible una nueva versión {latest} de Contao Manager. Su servidor no admite actualizaciones automáticas, descargue la nueva versión de {download}.","ui.server.selfUpdate.latest":"Estás utilizando la última versión {current}.","ui.server.selfUpdate.dev":"Las compilaciones de desarrollo no admiten actualizaciones automáticas.","ui.server.selfUpdate.unsupported":"Hay una nueva versión disponible pero no es compatible con su versión de PHP.","ui.server.selfUpdate.button":"Ejecutar autoactualización","ui.server.selfUpdate.continue":"Continuar","ui.server.config.title":"Configuración del servidor","ui.server.config.setup":"Configurar","ui.server.config.change":"Cambiar","ui.server.config.save":"Guardar","ui.server.config.cancel":"Cancelar","ui.server.config.customOption":"Otros ...","ui.server.config.description":"Para ejecutar correctamente las tareas en segundo plano, Contao Manager necesita saber dónde encontrar el binario de la línea de comandos PHP y cómo ejecutar comandos separados del proceso web.","ui.server.config.formTitle":"Configuración del servidor","ui.server.config.formText":"Por favor ingrese la ruta a su binario de PHP. Asegúrese de que el binario sea la misma versión PHP que su proceso web.","ui.server.config.cloudTitle":"Compositor Resolver Cloud","ui.server.config.cloudText":"El Composer Resolver Cloud permite instalar dependencias de Composer incluso si su servidor no proporciona suficiente memoria local. Tenga en cuenta que la información de su paquete se transmitirá a un servidor en la nube operado por la Asociación Contao.","ui.server.config.cloud":"Utilice la nube Composer Resolver Cloud","ui.server.config.cli":"PHP binario","ui.server.config.stateErrorCli":"No se encontró ningún binario PHP válido en el servidor.","ui.server.config.stateErrorCloud":"Composer Resolver Cloud no es compatible.","ui.server.config.stateSuccess":"PHP binario en {php_cli}.","ui.server.config.cloudEnabled":"Las dependencias del paquete se resolverán mediante Composer Resolver Cloud.","ui.server.config.cloudDisabled":"El Compositor Resolver Cloud está deshabilitado.","ui.server.php_web.title":"Proceso web de PHP","ui.server.php_web.below7":"Versión PHP encontrada {versión}. ¡Cambie a PHP 7 lo antes posible!","ui.server.php_web.success":"Se encontró la versión PHP {versión}, no se encontraron problemas conocidos.","ui.server.php_cli.title":"Interfaz de línea de comandos de PHP","ui.server.php_cli.success":"Se encontró la versión PHP {versión}, no se encontraron problemas conocidos.","ui.server.composer.title":"Entorno Composer","ui.server.composer.success":"No se encontraron problemas conocidos.","ui.server.composer.install":"Las dependencias del Composer no están instaladas.","ui.server.composer.button":"Instalar","ui.server.contao.title":"Instalación de Contao","ui.server.contao.setup":"Configuración","ui.server.contao.check":"Consultar base de datos","ui.server.contao.empty":"No se ha encontrado una instalación de Contao.","ui.server.contao.old":"La versión de Contao {versión} no es compatible con Contao Manager, actualice su instalación manualmente.","ui.server.contao.found":"Se ha encontrado Contao {version} (API version {api}).","ui.server.contao.connectionError":"No se puede conectar con el servidor de la base de datos.","ui.server.contao.connectionProblem":"Problema de base de datos encontrado.","ui.server.contao.missingUser":"Cuenta de administrador no encontrada.","ui.setup.continue":"Continuar","ui.setup.manager":"Lanzamiento de Contao Manager","ui.setup.cancel":"Cancelar","ui.setup.welcome":"Bienvenido","ui.setup.welcome1":"Este asistente le guiará a través de los pasos necesarios para configurar su instalación de CMS de código abierto de Contao.","ui.setup.welcome2":"Si tiene alguna pregunta, busque documentación, foros, un canal de Slack y más en la página de {support}.","ui.setup.support":"soporte comunitario","ui.setup.start":"Empezar","ui.setup.complete":"¡Enhorabuena!","ui.setup.complete1":"Contao {versión} se ha instalado correctamente.","ui.setup.complete2":"Para finalizar el proceso de configuración, abra la herramienta de instalación para configurar la conexión de la base de datos y crear un usuario final.","ui.setup.complete3":"Ahora puede comenzar a crear su sitio web en el back-end de Contao. Si necesita extensiones adicionales, continúe con Contao Manager.","ui.setup.installTool":"Abra la herramienta de instalación","ui.setup.login":"Iniciar sesión en Contao","ui.setup.funding":"El software libre es \\"libre\\" como en \\"libertad de expresión\\", no como en \\"cerveza gratis\\". Un proyecto de código abierto como Contao requiere cantidades de dinero que no pueden ser recaudadas por una sola persona o empresa.\\nSi tiene un sitio web o vende sitios web creados con Contao, nos encantaría ver que contribuye financieramente al producto del que depende su negocio.","ui.setup.fundingLink":"Aprende más","ui.setup.document-root.headline":"Configuración del servidor web","ui.setup.document-root.warning":"Para instalar Contao a través de Contao Manager, debe arreglar la raíz del documento en el servidor web.","ui.setup.document-root.description1":"Contao usa una carpeta separada para los archivos públicos, los archivos de la aplicación se instalan en su carpeta principal. Contao no se puede instalar si la estructura de carpetas no es correcta o las carpetas no están vacías.","ui.setup.document-root.description2":"Si no sabe cómo configurar la raíz de su documento, lea la documentación de Contao o comuníquese con su proveedor de alojamiento.","ui.setup.document-root.documentation":"Lea la documentación","ui.setup.document-root.conflictsTitle":"El directorio de instalación no está vacío","ui.setup.document-root.conflictsDirectory":"El directorio raíz de su futura instalación de Contao no está vacío, hemos encontrado (un) archivo(s) {count} que podrían sobrescribirse durante el proceso de instalación. Se recomienda crear una estructura de directorios vacía para Contao, pero también puede eliminar los siguientes archivos y verificar nuevamente si está seguro de que no se utilizan.","ui.setup.document-root.ignoreConflicts":"Quiero instalar Contao en el directorio no vacío. Entiendo que esto podría sobrescribir cualquier archivo existente en mi espacio web.","ui.setup.document-root.check":"Revisar otra vez","ui.setup.document-root.create":"Crear directorios","ui.setup.document-root.change":"Cambiar directorios","ui.setup.document-root.formTitle":"Configuración de directorio","ui.setup.document-root.formText1":"Contao Manager puede crear automáticamente una nueva estructura de directorio en el servidor.","ui.setup.document-root.formText2":"Deberá configurar manualmente la nueva raíz del documento (por ejemplo, a través de un panel de administración de alojamiento).","ui.setup.document-root.autoconfig":"Entiendo que tengo que cambiar la configuración de mi servidor. ¡No configurar la raíz del documento romperá el Contao Manager y expondrá los archivos de configuración (incluidos los detalles de la cuenta y las contraseñas)!","ui.setup.document-root.directory":"Nuevo directorio","ui.setup.document-root.currentRoot":"Raíz del documento actual","ui.setup.document-root.newRoot":"Nueva raíz del documento","ui.setup.document-root.finish":"Configurar directorios","ui.setup.document-root.publicDir":"Use {dir} para archivos públicos (para Contao {version})","ui.setup.document-root.directoryInvalid":"Introduzca un nombre de directorio válido.","ui.setup.document-root.directoryExists":"El directorio de destino ya existe. Ingrese un nombre diferente.","ui.setup.document-root.confirmation":"Contao Manager ha creado con éxito el directorio necesario para su instalación de Contao. Ahora debe configurar la raíz del documento en su servidor web. No recargues esta página hasta entonces.","ui.setup.document-root.reload":"Recargar página","ui.setup.document-root.success":"¡La estructura de directorios en su servidor web está configurada correctamente!","ui.setup.document-root.installingProjectDir":"Los archivos de la aplicación se instalarán en {dir}.","ui.setup.document-root.installingPublicDir":"Los archivos públicos se instalarán en {dir}.","ui.setup.document-root.installedProjectDir":"Los archivos de la aplicación se instalan en {dir}.","ui.setup.document-root.installedPublicDir":"Los archivos públicos se instalan en {dir}.","ui.setup.create-project.headline":"Instalación de Contao","ui.setup.create-project.description":"El desarrollo de Contao sigue el principio de {semver}, se lanza una nueva versión secundaria cada seis meses. Las versiones admitidas actualmente son:","ui.setup.create-project.semver":"Versionado semántico","ui.setup.create-project.latestTitle":"Última","ui.setup.create-project.ltsTitle":"Soporte a largo plazo","ui.setup.create-project.latestQ1":"Nuestra última versión ofrece la mayoría de las funciones con soporte hasta febrero de {year}.","ui.setup.create-project.latestQ3":"Nuestra última versión ofrece la mayor cantidad de funciones con soporte hasta agosto del {year}.","ui.setup.create-project.ltsText":"Nuestra versión LTS actual, si te enfocas en la estabilidad. Ofrece soporte a largo plazo hasta febrero {year}.","ui.setup.create-project.pltsText":"La versión anterior de LTS todavía tiene soporte a largo plazo hasta febrero de {year}.","ui.setup.create-project.requiresPHP":"Requiere al menos PHP {version}, tiene PHP {current}.","ui.setup.create-project.releaseplan":"Consulte el {contaoReleasePlan} para obtener información detallada.","ui.setup.create-project.releaseplanLink":"Plan de lanzamiento de Contao","ui.setup.create-project.installed":"Contao {version} se instaló correctamente en el servidor. Continúe configurando su base de datos o inicie Contao Manager para instalar una versión diferente.","ui.setup.create-project.formTitle":"Seleccione una distribución","ui.setup.create-project.formText":"Elija qué versión debe instalarse.","ui.setup.create-project.version":"Versión","ui.setup.create-project.demo":"Instale el sitio web de demostración de Contao","ui.setup.create-project.demoDescription":"The demo website helps you to get familiar with Contao and all of its core features. More themes can be found in the {store}.Instale el sitio web de demostración de Contao","ui.setup.create-project.coreOnly":"Instalación mínima (solo el núcleo)","ui.setup.create-project.noUpdate":"Omitir instalación (¡Solo experto!)","ui.setup.create-project.theme":"Tema Contao","ui.setup.create-project.themeInstall":"Para instalar un tema de Contao, utilice la entrada de búsqueda o cargue un archivo de tema (.cto/.zip) que admita la instalación a través de Contao Manager.","ui.setup.create-project.themeBuy":"Asegúrate de visitar la {store} oficial.","ui.setup.create-project.themeStore":"Tienda de temas Contao","ui.setup.create-project.themeUpload":"Cargar archivo de tema (.cto/.zip)","ui.setup.create-project.themeInvalid":"El archivo cargado no es un tema de Contao o no es compatible con Contao Manager.","ui.setup.create-project.themeWarning":"El Contao Manager no puede saber si este tema es compatible con su servidor. Consulte con el proveedor del tema si tiene alguna pregunta.","ui.setup.create-project.themeTitle":"Revisar los detalles del tema","ui.setup.create-project.themeDetails":"Las siguientes dependencias y archivos se instalarán con este tema.","ui.setup.create-project.themeRequire":"{count} Dependencias | {count} Dependencias","ui.setup.create-project.themeFiles":"{count} Archivo | {count} Archivos","ui.setup.create-project.theme.or":"o buscar temas públicos","ui.setup.create-project.theme.search":"Buscar temas","ui.setup.create-project.theme.more":"Más temas","ui.setup.create-project.theme.empty":"No hay temas que coincidan con {query}","ui.setup.create-project.theme.uploaded":"El archivo del tema se cargó correctamente.","ui.setup.create-project.theme.packageName":"Nombre del paquete","ui.setup.create-project.theme.version":"Versión","ui.setup.create-project.theme.authors":"Autor(es)","ui.setup.create-project.theme.upload":"Subiendo {name} ({size})","ui.setup.create-project.install":"Instalar","ui.setup.create-project.cancel":"Cancelar","ui.setup.create-project.fileError":"No se pudo encontrar composer.json en {file}.","ui.setup.create-project.jsonError":"composer.json contiene JSON no válido.","ui.setup.create-project.schemaError":"La validación del esquema composer.json falló.","ui.setup.database-connection.headline":"Conexión de base de datos","ui.setup.database-connection.description":"Contao requiere una base de datos MySQL (o una bifurcación compatible como MariaDB) para almacenar páginas, contenido, usuarios y otros datos relacionales. Los parámetros de conexión se almacenan en el archivo {env} en la raíz del proyecto de su instalación de Contao.","ui.setup.database-connection.formTitle":"Parámetros de conexión","ui.setup.database-connection.formText":"Ingrese una URL de base de datos o complete los campos de nombre de usuario, contraseña, servidor y base de datos por separado.","ui.setup.database-connection.url":"URL de la base de datos","ui.setup.database-connection.validUrl":"La URL de la base de datos no es válida o la conexión con el servidor falló.","ui.setup.database-connection.or":"o","ui.setup.database-connection.user":"Nombre de usuario","ui.setup.database-connection.password":"Contraseña","ui.setup.database-connection.server":"Servidor (:Port)","ui.setup.database-connection.database":"Nombre de la base de datos","ui.setup.database-connection.connected":"Conexión exitosa a la base de datos {database} en {server}.","ui.setup.database-connection.error":"Error al conectarse a la base de datos.","ui.setup.database-connection.problem":"Contao ha detectado un problema con su servidor de base de datos.","ui.setup.database-connection.schemaTitle":"Esquema de base de datos","ui.setup.database-connection.migration":"Hay una migración pendiente. | Hay {count} migraciones pendientes.","ui.setup.database-connection.schema":"Hay una actualización de esquema pendiente. | Hay {count} actualizaciones de esquema pendientes.","ui.setup.database-connection.noChanges":"El esquema de su base de datos está actualizado.","ui.setup.database-connection.check":"Consultar base de datos","ui.setup.database-connection.skip":"Saltar","ui.setup.database-connection.save":"Guardar","ui.setup.database-connection.change":"Cambiar credenciales","ui.setup.database-connection.restoreTitle":"Importar base de datos","ui.setup.database-connection.restoreText":"El tema que acaba de instalar contiene una copia de seguridad de la base de datos. Restaure la base de datos para importar datos del tema u omita este paso para comenzar con una instalación de Contao en blanco. | El tema que acaba de instalar contiene múltiples copias de seguridad de bases de datos. Seleccione un archivo de respaldo para importar datos del tema u omita este paso para comenzar con una instalación de Contao en blanco.","ui.setup.database-connection.backup":"Copia de seguridad de la base de datos actual antes de importar","ui.setup.database-connection.backupWarning":"¡Todos los datos de la base de datos se sobrescribirán al importar! Primero cree una copia de seguridad si la base de datos no está vacía.","ui.setup.database-connection.restore":"Importar base de datos de temas","ui.setup.database-connection.restoreOption":"Copia de seguridad de {date} ({size})","ui.setup.database-connection.restored":"Su base de datos de temas se importó correctamente. Continúe validando el esquema de su base de datos.","ui.setup.backend-user.success":"Se encontró una cuenta de administrador para el back-end de Contao en su base de datos. Use el back-end de Contao para agregar más usuarios.","ui.setup.backend-user.error":"No se puede recuperar la lista de usuarios. Consulte la salida de la consola para obtener más detalles.","ui.setup.backend-user.headline":"Cuenta back-end","ui.setup.backend-user.description":"Para administrar su sitio web, debe tener al menos una cuenta de administrador para el back-end de Contao. Tenga en cuenta que esta cuenta no está relacionada con Contao Manager.","ui.setup.backend-user.formTitle":"Crear una cuenta","ui.setup.backend-user.formText":"Introduzca los detalles de la nueva cuenta back-end.","ui.setup.backend-user.username":"Nombre de usuario","ui.setup.backend-user.name":"Nombre","ui.setup.backend-user.email":"Dirección de correo electrónico","ui.setup.backend-user.emailInvalid":"Por favor, introduzca una dirección de correo electrónico válida","ui.setup.backend-user.password":"Contraseña","ui.setup.backend-user.passwordPlaceholder":"min. 8 caracteres","ui.setup.backend-user.passwordLength":"Por favor introduzca al menos 8 caracteres.","ui.setup.backend-user.create":"Añadir cuenta","ui.task.headline":"Tarea de fondo","ui.task.loading":"Cargando detalles…","ui.task.created":"Cargando detalles…","ui.task.active":"Espere mientras Contao Manager ejecuta las operaciones de tareas en segundo plano.","ui.task.complete":"Todas las operaciones se completan con éxito. Consulte la salida de la consola para obtener más detalles.","ui.task.paused":"Una operación en segundo plano se detuvo inesperadamente. Compruebe la salida de la consola.","ui.task.aborting":"Espere mientras se cancelan las operaciones en segundo plano.","ui.task.stopped":"Se cancelaron algunas operaciones en segundo plano. Compruebe la salida de la consola.","ui.task.error":"Una operación en segundo plano se detuvo inesperadamente. Compruebe la salida de la consola.","ui.task.failed":"¡El Contao Manager no pudo iniciar una tarea en segundo plano!","ui.task.failedDescription1":"Algo salió mal al intentar ejecutar operaciones en segundo plano.","ui.task.failedDescription2":"Si esto vuelve a suceder, es posible que su servidor no sea compatible.","ui.task.reportProblem":"Informar de un problema","ui.task.pausedDescription":"Haga clic en \\"Continuar\\" si desea ignorar el error y ejecutar las operaciones restantes.","ui.task.sponsor":"Composer Cloud patrocinado por {sponsor}","ui.task.buttonAudit":"Actualizar base de datos","ui.task.buttonClose":"Cerrar","ui.task.buttonConfirm":"Confirmar y cerrar","ui.task.buttonContinue":"Continuar","ui.task.buttonCancel":"Cancelar","ui.task.confirmCancel":"¿Está seguro de cancelar esta tarea? ¡Esto podría dejar su instalación de Contao en un estado roto!","ui.task.autoclose":"Cerrar los detalles de la tarea en caso de éxito","ui.console.toggle":"Mostrar / Ocultar salida de consola","ui.console.showLog":"Mostrar registro completo de la consola","ui.console.copyLog":"Copiar registro al portapapeles","ui.migrate.headline":"Actualizaciones de la base de datos","ui.migrate.migrationsOnly":"(solo migraciones)","ui.migrate.schemaOnly":"(solo esquema)","ui.migrate.loading":"Por favor espere, estamos revisando su base de datos...","ui.migrate.empty":"No se encontraron migraciones pendientes ni actualizaciones de esquema. Su base de datos está actualizada.","ui.migrate.emptyMigrations":"No se encontraron migraciones pendientes. Asegúrese de verificar también las actualizaciones del esquema.","ui.migrate.emptySchema":"No se encontraron actualizaciones de esquema pendientes. Asegúrese de verificar también las migraciones.","ui.migrate.pending":"Su base de datos no está actualizada. Revise la salida de la consola a continuación y ejecute los cambios.","ui.migrate.previousChanges":"No se confirmó una migración de base de datos anterior.\\nRevise el resultado de la consola a continuación, luego continúe para ver los próximos cambios.","ui.migrate.previousComplete":"No se confirmó una migración de base de datos anterior, revise el resultado de la consola a continuación.\\nNo hay más cambios pendientes.","ui.migrate.appliedChanges":"Se han aplicado actualizaciones de la base de datos.\\nRevise el resultado de la consola a continuación, luego continúe para ver los próximos cambios.","ui.migrate.appliedComplete":"Se han aplicado actualizaciones de la base de datos.\\nNo hay más migraciones pendientes ni actualizaciones de esquemas. Su base de datos está actualizada.","ui.migrate.problem":"Contao ha detectado un problema con su servidor de base de datos.\\nRevise la salida de la consola a continuación para averiguar qué debe corregirse. | Contao ha detectado problemas con su servidor de base de datos.\\nRevise la salida de la consola a continuación para averiguar qué debe corregirse.","ui.migrate.warning":"Contao ha detectado una configuración incorrecta de su servidor de base de datos.\\nLas advertencias se pueden omitir temporalmente, pero se deben corregir para lograr un rendimiento y una integridad de los datos óptimos.","ui.migrate.error":"No se pudieron aplicar los cambios. Es posible que su base de datos haya cambiado, verifique nuevamente para volver a intentarlo.","ui.migrate.execute":"Ejecutar","ui.migrate.close":"Cerrar","ui.migrate.confirm":"Confirmar y cerrar","ui.migrate.cancel":"Cancelar","ui.migrate.continue":"Continuar","ui.migrate.setup":"Configuración","ui.migrate.skip":"Saltar","ui.migrate.retry":"Revisar otra vez","ui.migrate.retryAll":"Comprobar todo","ui.migrate.withDeletes":"Ejecute todos los cambios de la base de datos, incluidas las consultas DROP.","ui.migrate.migrationTitle":"Migraciones de bases de datos","ui.migrate.schemaTitle":"Actualizaciones de esquema","ui.migrate.problemTitle":"Problemas de base de datos","ui.migrate.warningTitle":"Advertencias de la base de datos","ui.migrate.addTable":"Añadir tabla {table}","ui.migrate.dropTable":"Soltar tabla {table}","ui.migrate.addField":"Añadir campo {table}.{field}","ui.migrate.changeField":"Cambiar campo {table}.{field}","ui.migrate.dropField":"Soltar campo {table}.{field}","ui.migrate.createIndex":"Crear índice \\"{name}\\" en {table}","ui.migrate.dropIndex":"Coloque el índice \\"{name}\\" en {table}","ui.widget.mandatory":"Este campo no debe estar vacío.","ui.widget.blankOption":"Por favor seleccione","ui.widget.showPassword":"Mostrar contraseña","ui.widget.hidePassword":"Ocultar contraseña","ui.error.title":"Error en la solicitud HTTP para \\"{method} {url}\\".","ui.error.server500":"Parece que ocurrió un error inesperado en su servidor. Consulte los archivos de registro de su servidor web (Apache/Nginx) y los registros de Contao Manager en \\"contao-manager/logs\\".","ui.error.response":"El servidor devolvió una respuesta con el código de estado {status}.","ui.error.moreLink":"Más información","ui.error.support":"Soporte Contao","ui.error.permission":"No tiene permiso para utilizar esta función.","ui.footer.help":"Ayuda","ui.footer.reportProblem":"Informar de un problema","ui.navigation.discover":"Descubrir","ui.navigation.packages":"Paquetes","ui.navigation.tools":"Herramientas","ui.navigation.installTool":"Herramienta de instalación","ui.navigation.backend":"Backend de Contao","ui.navigation.debug":"Modo Contao Debug","ui.navigation.logViewer":"Visor de registros","ui.navigation.phpinfo":"Información PHP","ui.navigation.phpinfoLoading":"Cargando información de PHP…","ui.navigation.maintenance":"Mantenimiento","ui.navigation.rebuildCache":"Reconstruir caché","ui.navigation.users":"Cuentas","ui.navigation.systemCheck":"Comprobar sistema","ui.navigation.advanced":"Avanzado","ui.navigation.logout":"Cerrar sesión","ui.maintenance.database.title":"Migraciones y copias de seguridad de bases de datos","ui.maintenance.database.description":"Las migraciones de bases de datos garantizan esquemas de tablas y datos coherentes.","ui.maintenance.database.migrations":"Una migración de base de datos pendiente | {count} migraciones de bases de datos pendientes","ui.maintenance.database.schemaUpdates":"Una actualización de esquema pendiente | {count} actualizaciones de esquema pendientes","ui.maintenance.database.error":"Problema de base de datos encontrado.","ui.maintenance.database.warning":"Se encontraron advertencias de la base de datos.","ui.maintenance.database.button":"Consultar base de datos","ui.maintenance.database.migrationOnly":"Comprobar solo migraciones","ui.maintenance.database.schemaOnly":"Comprobar solamente esquema ","ui.maintenance.database.installTool":"Abrir herramienta de instalación","ui.maintenance.database.createBackup":"Crear copia de seguridad","ui.maintenance.database.backupUnsupported":"Las copias de seguridad de bases de datos no son compatibles con su versión de Contao.","ui.maintenance.database.backupList":"Tiene una copia de seguridad de la base de datos, creada el {fecha}. | Tiene {count} copias de seguridad de la base de datos; la última se creó el {fecha}.","ui.maintenance.database.backupEmpty":"Actualmente no tiene copias de seguridad de la base de datos.","ui.maintenance.rebuildCache.title":"Caché de la aplicación","ui.maintenance.rebuildCache.description":"Es necesario volver a generar la caché de la aplicación después de modificar cualquiera de los archivos de configuración.","ui.maintenance.rebuildCache.rebuildProd":"Reconstruir caché de producción","ui.maintenance.rebuildCache.rebuildDev":"Reconstruir caché de desarrollo","ui.maintenance.rebuildCache.clearProd":"Borrar caché de producción","ui.maintenance.rebuildCache.clearDev":"Borrar caché de desarrollo","ui.maintenance.installTool.title":"Herramienta de Instalación Contao","ui.maintenance.installTool.description":"La herramienta de instalación de Contao se bloquea automáticamente si introduce una contraseña incorrecta tres veces seguidas.","ui.maintenance.installTool.unlock":"Desbloquear herramienta de instalación","ui.maintenance.installTool.lock":"Bloquear herramienta de instalación","ui.maintenance.dumpAutoload.title":"Cargador Composer Class","ui.maintenance.dumpAutoload.description":"El autocargador Composer es responsable de la carga de la clase PHP. El autocargador debe volcarse después de agregar espacios de nombres personalizados a la raíz composer.json.","ui.maintenance.dumpAutoload.button":"Dump Autoloader","ui.maintenance.composerInstall.title":"Dependencias Composer","ui.maintenance.composerInstall.description":"Las dependencias de Composer se encuentran en la carpeta {vendor} en la raíz de su aplicación. Puede ser necesario reinstalar las dependencias después de la manipulación o de cargar manualmente el archivo {composerLock}.","ui.maintenance.composerInstall.button":"Ejecutar instalador","ui.maintenance.composerInstall.update":"Ejecutar actualización de Composer","ui.maintenance.composerCache.title":"Caché del Composer","ui.maintenance.composerCache.description":"El Composer almacena en el caché los paquetes descargados para un mejor rendimiento. Si tiene problemas como archivos rotos, intente eliminar el caché de Composer para forzar una nueva descarga.","ui.maintenance.composerCache.button":"Limpiar cache","ui.maintenance.maintenanceMode.title":"Modo de mantenimiento","ui.maintenance.maintenanceMode.description":"Poner a Contao en modo de mantenimiento mostrará una plantilla \\"503 Servicio no disponible\\" para el sitio web.","ui.maintenance.maintenanceMode.enable":"Habilitar","ui.maintenance.maintenanceMode.disable":"Deshabilitar","ui.maintenance.debugMode.title":"Modo Debug","ui.maintenance.debugMode.description":"Active el modo de depuración configurando un usuario y una contraseña para el punto de entrada {appDevPhp}.","ui.maintenance.debugMode.descriptionJwt":"Active el modo de depuración configurando la cookie de depuración para el dominio actual.","ui.maintenance.debugMode.activate":"Activar","ui.maintenance.debugMode.deactivate":"Desactivar","ui.maintenance.debugMode.credentials":"Credenciales","ui.maintenance.debugMode.user":"Introduzca un nombre de usuario para el modo Debug.","ui.maintenance.debugMode.password":"Introduzca una contraseña de usuario para el modo Debug.","ui.maintenance.opcodeCache.title":"Caché Opcode","ui.maintenance.opcodeCache.description":"Opcode guarda en caché los archivos PHP en el proceso web para una ejecución más rápida. Debe borrarse bajo ciertas circunstancias si los archivos no son reconocidos después de cambiarlos.","ui.maintenance.opcodeCache.button":"Truncar caché","ui.maintenance.safeMode":"No disponible en modo seguro","ui.maintenance.unsupported":"No es compatible con su versión de Contao","ui.packages.updateButton":"Paquetes de actualización","ui.packages.searchButton":"Buscar paquetes","ui.packages.searchPlaceholder":"Buscando paquetes ...","ui.packages.uploadOverlay":"Arrastra y suelta archivos para subir","ui.packages.uploadButton":"Subir paquetes","ui.packages.uploadMessage":"Tiene una carga sin confirmar. | Tienes {count} cargas sin confirmar.","ui.packages.uploadApply":"Confirmar subidas","ui.packages.uploadReset":"Eliminar subidas","ui.packages.uploadIncomplete":"Este archivo no se cargó por completo. Elimínelo e intente nuevamente.","ui.packages.uploadDuplicate":"Este archivo parece haberse cargado varias veces. Por favor, elimine los duplicados.","ui.packages.uploadInstalled":"Este archivo ya está instalado. Por favor, elimine los duplicados.","ui.packages.uploadUnsupported":"Las cargas no son compatibles con su instalación. Asegúrese de que la extensión PHP ZIP esté instalada y actualice sus dependencias.","ui.packages.changesMessage":"Tiene un cambio sin confirmar. | Tiene {count} cambios sin confirmar.","ui.packages.changesDryrun":"Funcionamiento en seco","ui.packages.changesApply":"Aplicar cambios","ui.packages.changesApplyAll":"Actualizar todos los paquetes ","ui.packages.changesDryrunAll":"Ejecutar en seco todos los paquetes","ui.packages.changesReset":"Restablecer cambios","ui.packages.changesReview":"Revisar cambios","ui.packagelist.loading":"Cargando ...","ui.packagelist.uploads":"Subidas","ui.packagelist.added":"Neuvos paquetes","ui.packagelist.installed":"paquetes instalados","ui.package.hintRevert":"Revertir cambios","ui.package.hintNoupdate":"No actualice","ui.package.hintConstraint":"Este paquete se instalará con restricción {constraint} al aplicar los cambios.","ui.package.hintConstraintBest":"Este paquete se instalará en la mejor versión disponible cuando aplique los cambios.","ui.package.hintConstraintChange":"La restricción para este paquete cambiará de \\"{from}\\" a \\"{to}\\" cuando aplique los cambios.","ui.package.hintConstraintUpdate":"Este paquete se actualizará cuando aplique los cambios.","ui.package.hintAdded":"Este paquete se instalará cuando aplique los cambios.","ui.package.hintRemoved":"Este paquete se eliminará cuando aplique los cambios.","ui.package.requiredTitle":"agregado manualmente","ui.package.requiredText":"Este paquete es obligatorio en su composer.json pero no está instalado.","ui.package.removedTitle":"Eliminado manualmente","ui.package.removedText":"Este paquete se eliminó de su composer.json.","ui.package.installed":"Actualmente instalado:","ui.package.version":"Versión {version}","ui.package.additionalDownloads":"{count} Descargar | {count} Descargas","ui.package.additionalStars":"{count} estrella | {count} estrellas","ui.package.editConstraint":"Editar","ui.package.uploadConstraint":"Esta restricción está definida por el paquete cargado.","ui.package.updateButton":"Actualizar","ui.package.removeButton":"Eliminar","ui.package.installButton":"Agregar paquete","ui.package.installButtonShort":"Añadir","ui.package.detailsButton":"Detalles","ui.package.latestConstraint":"Última versión","ui.package.update":"Actualización disponible ","ui.package.updateLatest":"Última versión","ui.package.updateAvailable":"{version} disponible","ui.package.updateUnknown":"versión desconocida ","ui.package.updateConstraint":"Hay disponible una versión más nueva fuera de su restricción de versión.","ui.package.incompatible":"{package} no funciona con Contao {constraint}.","ui.package.incompatibleWarning":"{package} no funciona con Contao {constraint} en ninguna de sus versiones estables. ¿Desea agregar el paquete y establecer una restricción de versión para intentar instalar una rama de desarrollo?","ui.package.incompatibleConstraint":"Este paquete no tiene una versión estable para Contao {constraint}. Establezca una restricción de versión para intentar instalar una rama de desarrollo.","ui.package.incompatibleButton":"Instalar","ui.cloudStatus.headline":"Compositor Resolver Cloud","ui.cloudStatus.version":"Versión {version}","ui.cloudStatus.waitingTime":"Tiempo de espera","ui.cloudStatus.jobs":"Trabajos actuales","ui.cloudStatus.workers":"Trabajadores","ui.cloudStatus.approx":"{minutes} min","ui.cloudStatus.none":"ninguno","ui.cloudStatus.short":"aprox. {minutes} min","ui.cloudStatus.long":"aprox. {minutes} min {seconds} seg","ui.cloudStatus.error":"No se puede obtener el estado del Composer Resolver Cloud. Puede haber una ventana de mantenimiento o problemas del sistema.","ui.cloudStatus.button":"Cloud-Status ","ui.cloudStatus.refresh":"Actualizar el Cloud-Status","ui.log-viewer.loading":"Cargando ...","ui.log-viewer.empty":"No hay archivos de registro en su servidor.","ui.log-viewer.reload":"Recargar","ui.log-viewer.file":"Archivo de registro","ui.log-viewer.channel":"Canal","ui.log-viewer.channelTitle":"El canal en el que se registró este mensaje.","ui.log-viewer.level":"Nivel","ui.log-viewer.levelTitle":"Gravedad del mensaje de registro.","ui.log-viewer.timeHeader":"Tiempo","ui.log-viewer.messageHeader":"Mensaje","ui.log-viewer.showContext":"Mostrar contenido","ui.log-viewer.hideContext":"Ocultar contenido","ui.log-viewer.showExtra":"Mostrar Extra","ui.log-viewer.hideExtra":"Ocultar Extra","ui.log-viewer.more":"Cargar más ...","ui.log-viewer.download":"Descargar","ui.log-viewer.downloadTitle":"Descargar archivo \\"{file}\\"","ui.log-viewer.prodEnvironment":"Entorno de producción","ui.log-viewer.devEnvironment":"Entorno de desarrollo (Debug Mode)","ui.user-manager.loading":"Cargando usuarios…","ui.user-manager.changePassword":"Cambiar contraseña","ui.user-manager.setupTotp":"Configurar la autenticación de dos factores","ui.user-manager.disableTotp":"Deshabilitar la autenticación de dos factores","ui.user-manager.invite":"Invitar usuario","ui.user-manager.delete":"Borrar","ui.user-manager.deleteConfirm":"¿Está seguro de que desea eliminar el usuario \\"{username}\\"?","ui.user-manager.deleted":"El usuario {username} fue eliminado exitosamente","ui.user-manager.passwordHeadline":"Cambiar contraseña","ui.user-manager.passwordText":"Para cambiar su contraseña, ingrese la contraseña actual y la nueva en los campos respectivos.","ui.user-manager.currentPassword":"Contraseña actual","ui.user-manager.newPassword":"Nueva contraseña","ui.user-manager.passwordPlaceholder":"min. 8 caracteres","ui.user-manager.submitPassword":"Enviar","ui.user-manager.passwordChanged":"Su contraseña ha sido cambiada exitosamente","ui.user-manager.passwordError":"Esta contraseña es incorrecta.","ui.user-manager.inviteHeadline":"Invitar usuario","ui.user-manager.inviteText":"Si necesita varios inicios de sesión para Contao Manager, puede crear un enlace de invitación aquí. Comparta este enlace con alguien o úselo en otro dispositivo para crear una nueva cuenta con los permisos otorgados.","ui.user-manager.inviteSuccess1":"Se ha creado un nuevo enlace de invitación. La URL que aparece a continuación se puede utilizar para crear una nueva cuenta de usuario para este administrador de cuentas. La invitación vence el {expires} (dentro de una semana).","ui.user-manager.inviteSuccess2":"Copie el enlace en su portapapeles. Solo funcionará una vez y no podra verlo nuevamente luego de cerrar este cuadro de diálogo.","ui.user-manager.createInvitation":"Crear enlace de invitación","ui.user-manager.clipboard":"Copiar al portapapeles","ui.user-manager.permissions":"Obtenga más información sobre los permisos","ui.user-manager.cancel":"Cancelar","ui.user-manager.close":"Cerrar","ui.user-manager.you":"Usted","ui.user-manager.2fa":"2FA","ui.user-manager.2faEnabled":"Esta cuenta está protegida mediante autenticación de dos factores.","ui.user-manager.2faDisabled":"Esta cuenta no es segura debido a la falta de autenticación de dos factores.","ui.user-manager.passkey":"Passkey","ui.user-manager.passkeyTitle":"Esta cuenta está segura con una Passkey.","ui.totp.headline":"Autenticación de dos factores","ui.totp.setupQr":"Escanee el código QR con su aplicación 2FA/TOTP.","ui.totp.setupCode":"Si no puede escanear el código QR, ingrese esta clave en su lugar:","ui.totp.codeLabel":"Código de verificación","ui.totp.codeDescription":"Ingrese el código de verificación generado por su aplicación 2FA/TOTP.","ui.totp.disableText":"Ingrese el código de verificación para desactivar la autenticación de dos factores.","ui.totp.invalid":"El código de verificación no es válido.","ui.totp.enable":"Habilitar","ui.totp.disable":"Deshabilitar","ui.totp.cancel":"Cancelar","ui.totp.enabled":"La autenticación de dos factores se habilitó correctamente.","ui.totp.disabled":"La autenticación de dos factores se deshabilitó correctamente.","ui.totp.setup":"Configurar la autenticación de dos factores","ui.totp.skip":"Omitir la autenticación de dos factores"}')}}]);"use strict";(self["webpackChunkcontao_manager"]=self["webpackChunkcontao_manager"]||[]).push([[28],{4028:function(e){e.exports=JSON.parse('{"ui.app.httpsHeadline":"!! 不安全连接 !!","ui.app.httpsDescription":"没有HTTPS情况下，机密数据将会未加密传输。","ui.app.httpsLink":"更多信息","ui.app.httpsHref":"https://https.cio.gov/everything/","ui.app.safeModeHeadline":"!! Safe Mode enabled !!","ui.app.safeModeDescription":"Some features of the Contao Manager are not available.","ui.app.safeModeExit":"Exit Safe Mode","ui.app.loading":"加载 Contao 管理器 …","ui.app.apiError":"意外的API状态","ui.app.configSecurity1":"安全警报 !!! 检测到未受保护的配置目录","ui.app.configSecurity2":"Contao管理器检测到其配置文件可以公开访问。目录受到保护之前会禁止所有操作，否则攻击者可以访问安装的敏感数据。\\n\\n为了修复这个问题，请确保阻止访问服务器上的\\"contao-manager\\"目录。要了解如何执行此操作，请参阅您的网络服务器手册或联系您的托管服务提供商。","ui.account.welcome":"欢迎","ui.account.intro1":"Welcome to the Contao Manager, a universal tool to install and manage Contao Open Source CMS. If you are new to it, please {readTheManualToGetStarted}.","ui.account.introGetStarted":"{readTheManual} to get started","ui.account.introManual":"read the manual","ui.account.intro2":"If you encounter any problems, check {ourGithubIssues} and feel free to create new one for anything that has not been reported yet.","ui.account.introIssues":"our GitHub issues","ui.account.headline":"用户账户","ui.account.description":"为了管理安装，请为Contao管理器创建一个账号。请注意该账号和Contao后台和前端没有关联。","ui.account.username":"用户名","ui.account.password":"密码","ui.account.passwordPlaceholder":"最少8个字符","ui.account.passwordLength":"请输入最少8个字符","ui.account.submit":"创建账号","ui.account.contribute1":"Contao and the Contao Manager are sponsored by the non-profit Contao Association.","ui.account.contribute2":"Please consider contributing to open source by {donate}.","ui.account.contributeDonate":"making a donation","ui.login.headline":"登录","ui.login.description":"登录来管理安装。","ui.login.username":"用户名","ui.login.password":"密码","ui.login.forgotPassword":"忘记密码","ui.login.button":"登录","ui.login.locked":"Access has been denied because the Contao Manager is locked. To unlock, delete the {lockFile} file in your Contao root directory.","ui.logout.headline":"会话超时","ui.logout.warning":"超过25分钟没有活动。安全原因您的会话将很快被终止。","ui.logout.expired":"由于超过30分钟没有活动，您的会话已自动终止。","ui.logout.renew":"保持登入","ui.logout.logout":"注销","ui.logout.login":"返回登录","ui.oauth.error":"无效的OAuth尝试。检查请求参数。","ui.oauth.https":"The redirect URI MUST use a secure protocol (https:) to prevent the authentication token from being transmitted in clear-text.","ui.oauth.headline":"Remote Authentication","ui.oauth.description":"以下应用程序或者服务正在请求对您的Contao Manager实例远程访问。","ui.oauth.domain":"Before allowing access, make sure you know this URL and trust its owner!","ui.oauth.allow":"允许访问","ui.oauth.deny":"拒绝访问","ui.boot.headline":"系统检查","ui.boot.description":"请稍等，正在分析您的服务器 …","ui.boot.issue1":"监测到安装问题","ui.boot.issue2":"Your installation has issues that have to be fixed before the Contao Manager can be used.","ui.boot.run":"运行Contao管理器","ui.boot.safeMode":"安全模式下运行","ui.recovery.headline":"系统恢复","ui.recovery.description":"The Contao Manager detected files that look like Contao, but the Command Line Interface does not work as expected.","ui.recovery.console":"Console Output","ui.recovery.repairOptions":"Please choose an option to repair your installation.","ui.recovery.repairHeadline":"自动修复","ui.recovery.repairDescription":"尝试通过重建应用缓存并重新安装Composer包来自动修复安装。","ui.recovery.repairWarning":"此过程可能会删除vendor中文件的任何修改!","ui.recovery.repairFailed":"自动修复没有成功。请尝试安全模式手动修复安装。","ui.recovery.repairButton":"运行系统修复","ui.recovery.safeModeHeadline":"安全模式","ui.recovery.safeModeDescription":"安全模式下运行Contao管理器允许管理包并运行某些维护任务，但依赖于正在运行的Contao安装的功能将不可用。","ui.recovery.safeModeButton":"安全模式下运行","ui.server.pending":"等待 …","ui.server.running":"分析中 …","ui.server.error":"由于服务器的意外响应，检查失败。","ui.server.details":"详情","ui.server.prerequisite":"由于缺少必要的条件，检查已取消。","ui.server.selfUpdate.title":"Contao管理器更新","ui.server.selfUpdate.update":"新的Contao管理器版本 {latest} .","ui.server.selfUpdate.manualUpdate":"新版本的Contao管理器 {latest} 可用。服务器不支持自动更新，请从{download}下载新版本。","ui.server.selfUpdate.latest":"正在使用最新版本 {current}。","ui.server.selfUpdate.dev":"开发版不支持自动更新。","ui.server.selfUpdate.unsupported":"有新版本，但您的PHP版本不支持。","ui.server.selfUpdate.button":"运行自更新","ui.server.selfUpdate.continue":"继续","ui.server.config.title":"服务器配置","ui.server.config.setup":"配置","ui.server.config.change":"更改","ui.server.config.save":"保存","ui.server.config.cancel":"取消","ui.server.config.customOption":"其他 …","ui.server.config.description":"To correctly run background tasks, the Contao Manager needs to know where to find the PHP command line binary and how to run commands separated from the web process.","ui.server.config.formTitle":"服务器配置","ui.server.config.formText":"请输入PHP二进制文件位置。确认二进制文件和服务器web进程是相同的PHP版本。","ui.server.config.cloudTitle":"Composer Resolver Cloud","ui.server.config.cloudText":"Composer Resolver Cloud 允许安装Composer依赖即使服务器无法提供足够的内存。您的包信息将被传输到由Contao Association运营的云服务器。","ui.server.config.cloud":"使用Composer Resolver Cloud","ui.server.config.cli":"PHP二进制","ui.server.config.stateErrorCli":"服务器中没有发现有效的PHP二进制文件。","ui.server.config.stateErrorCloud":"不支持Composer Resolver Cloud。","ui.server.config.stateSuccess":"PHP 二进制文件在 {php_cli}.","ui.server.php_web.title":"PHP Web 进程","ui.server.php_web.below7":"发现 PHP 版本 {version}。请尽快切换到PHP 7!","ui.server.php_web.success":"发现PHP版本 {version}, 没有发现已知问题。","ui.server.php_cli.title":"PHP命令行接口","ui.server.php_cli.success":"发现PHP版本 {version}, 没有发现已知问题。","ui.server.composer.title":"Composer环境","ui.server.composer.success":"没有发现已知问题","ui.server.composer.install":"没有安装Composer依赖。","ui.server.composer.button":"Install","ui.server.contao.title":"Contao 安装","ui.server.contao.setup":"安装","ui.server.contao.check":"Check database","ui.server.contao.empty":"没有发现安装Contao。","ui.server.contao.old":"Contao版本 {version}不兼容Contao Manager，请手动更新当前安装的系统。","ui.server.contao.found":"发现Contao {version} (API 版本 {api}).","ui.server.contao.connectionError":"Unable to connect to the database server.","ui.server.contao.connectionProblem":"Database problem found.","ui.server.contao.missingUser":"Admin account not found.","ui.setup.continue":"继续","ui.setup.manager":"运行Contao管理器","ui.setup.cancel":"取消","ui.setup.welcome":"欢迎","ui.setup.welcome1":"This wizard will take you through the necessary steps to set up your Contao Open Source CMS installation.","ui.setup.welcome2":"If you have any questions, please find documentation, forums, a Slack channel and more on the {support} page.","ui.setup.support":"community support","ui.setup.start":"Get started","ui.setup.complete":"Congratulations!","ui.setup.complete1":"Contao {version} has been installed successfully.","ui.setup.complete2":"To finish the setup process, please open the install tool to configure the database connection and create a back end user.","ui.setup.complete3":"You can now start to create your website in the Contao back end. If you need additional extensions, continue to the Contao Manager.","ui.setup.installTool":"Open the Install Tool","ui.setup.login":"Login to Contao","ui.setup.funding":"Free software is \\"free\\" as in \\"free speech\\", not as in \\"free beer\\". An Open Source project like Contao requires amounts of money that can\'t be raised by a single person or company.\\nIf you have a website or sell websites built with Contao, we would love to see you contribute back financially to the product your business relies upon.","ui.setup.fundingLink":"Learn more","ui.setup.document-root.headline":"Webserver Setup","ui.setup.document-root.warning":"To install Contao through the Contao Manager, you have to fix the document root on the web server.","ui.setup.document-root.description1":"Contao uses a separate folder for public files, application files are installed in its parent folder. Contao cannot be installed if the folder structure is not correct or the folders are not empty.","ui.setup.document-root.description2":"If you don\'t know how to configure your document root, please read the Contao documentation or contact your hosting provider.","ui.setup.document-root.documentation":"Read the Documentation","ui.setup.document-root.conflictsTitle":"Installation directory not empty","ui.setup.document-root.conflictsDirectory":"The root directory of your future Contao installation is not empty, we have found {count} file(s) that might be overwritten by the installation process. It is recommended to create an empty directory structure for Contao, but you can also remove the following files and check again if you are sure they are unused.","ui.setup.document-root.ignoreConflicts":"I want to install Contao into the non-empty directory. I understand that this might overwrite any existing files on my webspace.","ui.setup.document-root.check":"Check again","ui.setup.document-root.create":"Create directories","ui.setup.document-root.change":"Change directories","ui.setup.document-root.formTitle":"Directory Setup","ui.setup.document-root.formText1":"The Contao Manager can automatically create a new directory structure on the server.","ui.setup.document-root.formText2":"You will need to manually configure the new document root (e.g. through a hosting admin panel).","ui.setup.document-root.autoconfig":"I understand that I have to change my server configuration. Not configuring the document root will break the Contao Manager and expose configuration files (including account details and passwords)!","ui.setup.document-root.directory":"New Directory","ui.setup.document-root.currentRoot":"Current Document Root","ui.setup.document-root.newRoot":"New Document Root","ui.setup.document-root.finish":"Setup Directories","ui.setup.document-root.publicDir":"Use {dir} for public files (for Contao {version})","ui.setup.document-root.directoryInvalid":"Please enter a valid directory name.","ui.setup.document-root.directoryExists":"The target directory already exists. Please enter a different name.","ui.setup.document-root.confirmation":"The Contao Manager has successfully created the necessary directory for your Contao installation. You now have to configure the document root on your web server. Do not reload this page until then.","ui.setup.document-root.reload":"Reload Page","ui.setup.document-root.success":"The directory structure on your web server is set up correctly!","ui.setup.document-root.installingProjectDir":"Application files will be installed to {dir}.","ui.setup.document-root.installingPublicDir":"Public files will be installed to {dir}.","ui.setup.document-root.installedProjectDir":"Application files are installed in {dir}.","ui.setup.document-root.installedPublicDir":"Public files are installed in {dir}.","ui.setup.create-project.headline":"Contao 安装","ui.setup.create-project.description":"Contao development follows the principle of {semver}, a new minor version is released every six months. The currently supported releases are:","ui.setup.create-project.semver":"Semantic Versioning","ui.setup.create-project.latestTitle":"最新","ui.setup.create-project.ltsTitle":"长期支持","ui.setup.create-project.latestQ1":"Our latest version, offers the most features with support until February {year}.","ui.setup.create-project.latestQ3":"Our latest version, offers the most features with support until August {year}.","ui.setup.create-project.ltsText":"Our current LTS version, if you focus on stability. Offers long term support until February {year}.","ui.setup.create-project.pltsText":"The previous LTS version, still has long term support until February {year}.","ui.setup.create-project.requiresPHP":"Requires at least PHP {version}, you have PHP {current}.","ui.setup.create-project.requiresDocroot":"The document root must be \\"{folder}\\".","ui.setup.create-project.releaseplan":"See the {contaoReleasePlan} for detailed information.","ui.setup.create-project.releaseplanLink":"Contao Release Plan","ui.setup.create-project.formTitle":"Select a distribution","ui.setup.create-project.formText":"Please choose which version should be installed.","ui.setup.create-project.version":"版本","ui.setup.create-project.coreOnly":"初始化安装","ui.setup.create-project.coreOnlyNo":"全部安装 (新闻, 日历, 等.)","ui.setup.create-project.coreOnlyYes":"最小化安装 (仅核心)","ui.setup.create-project.coreOnlyFeatures":"What\'s the difference?","ui.setup.create-project.noUpdate":"跳过安装 (仅限专家!)","ui.setup.create-project.install":"Install","ui.setup.database-connection.headline":"Database Connection","ui.setup.database-connection.description":"Contao requires a MySQL database (or a compatible fork like MariaDB) to store pages, content, users and other relational data. Connection parameters are stored in the {env} file in the project root of your Contao installation.","ui.setup.database-connection.formTitle":"Connection Parameters","ui.setup.database-connection.formText":"Enter a database URL or fill in the username, password, server and database fields separately.","ui.setup.database-connection.url":"Database URL","ui.setup.database-connection.validUrl":"Database URL is invalid or connection to server failed.","ui.setup.database-connection.or":"or","ui.setup.database-connection.user":"用户名","ui.setup.database-connection.password":"密码","ui.setup.database-connection.server":"Server (:Port)","ui.setup.database-connection.database":"Database Name","ui.setup.database-connection.serverVersion":"Server Version","ui.setup.database-connection.oldVersion":"Older MySQL or MariaDB","ui.setup.database-connection.connected":"Successfully connected to database {database} on {server} {version}.","ui.setup.database-connection.error":"Error connecting to the database.","ui.setup.database-connection.problem":"Contao has detected a problem with your database server.","ui.setup.database-connection.migration":"There is one pending migration. | There are {count} pending migrations.","ui.setup.database-connection.schema":"There is one pending schema update. | There are {count} pending schema updates.","ui.setup.database-connection.noChanges":"Your database schema is up to date.","ui.setup.database-connection.check":"Check database","ui.setup.database-connection.save":"保存","ui.setup.database-connection.change":"Change credentials","ui.setup.backend-user.success":"An admin account for the Contao back end was found in your database. Use the Contao back end to add more users.","ui.setup.backend-user.error":"Unable to retrieve user list. Check the console output for details.","ui.setup.backend-user.headline":"Backend Account","ui.setup.backend-user.description":"To manage your website, you need to have at least one admin account for the Contao back end. Be aware that this account is not related to the Contao Manager.","ui.setup.backend-user.formTitle":"创建账号","ui.setup.backend-user.formText":"Please enter the details for the new back end account.","ui.setup.backend-user.username":"用户名","ui.setup.backend-user.name":"Name","ui.setup.backend-user.email":"E-mail address","ui.setup.backend-user.emailInvalid":"Please enter a valid e-mail address","ui.setup.backend-user.password":"密码","ui.setup.backend-user.passwordPlaceholder":"最少8个字符","ui.setup.backend-user.passwordLength":"请输入最少8个字符","ui.setup.backend-user.create":"Add account","ui.task.headline":"Background Task","ui.task.loading":"Loading details …","ui.task.created":"Loading details …","ui.task.active":"Please wait while the Contao Manager is running task operations in the background.","ui.task.complete":"All operations are completed successfully. Check the console output for details.","ui.task.aborting":"Please wait while the background operations are being cancelled.","ui.task.stopped":"Some background operations were cancelled. Please check the console output.","ui.task.error":"A background operation stopped unexpectedly. Please check the console output.","ui.task.failed":"The Contao Manager failed to start a background task!","ui.task.failedDescription1":"Something went wrong while trying to execute operations in the background.","ui.task.failedDescription2":"If this happens again, your server might not be supported.","ui.task.reportProblem":"报告问题","ui.task.sponsor":"Composer Cloud sponsored by {sponsor}","ui.task.buttonAudit":"更新数据库","ui.task.buttonClose":"关闭","ui.task.buttonConfirm":"确认 & 关闭","ui.task.buttonCancel":"取消","ui.task.confirmCancel":"确认取消此任务? 将会使Contao安装处于损坏状态!","ui.task.autoclose":"Close task details on success","ui.console.toggle":"显示/隐藏命令行输出","ui.console.showLog":"Show full console log","ui.console.copyLog":"Copy log to clipboard","ui.migrate.headline":"Database Updates","ui.migrate.migrationsOnly":"(migrations only)","ui.migrate.schemaOnly":"(schema only)","ui.migrate.loading":"Please wait, we are checking your database …","ui.migrate.empty":"No pending migrations or schema updates found. Your database is up to date.","ui.migrate.emptyMigrations":"No pending migrations found. Make sure to also check for schema updates.","ui.migrate.emptySchema":"No pending schema updates found. Make sure to also check for migrations.","ui.migrate.pending":"Your database is not up to date. Please review the console output below and execute the changes.","ui.migrate.previousChanges":"A previous database migration was not confirmed.\\nPlease review the console output below, then continue to see the next changes.","ui.migrate.previousComplete":"A previous database migration was not confirmed, please review the console output below.\\nThere are no more pending changes.","ui.migrate.appliedChanges":"Database updates have been applied.\\nPlease review the console output below, then continue to see the next changes.","ui.migrate.appliedComplete":"Database updates have been applied.\\nThere are no more pending migrations or schema updates. Your database is up to date.","ui.migrate.problem":"Contao has detected a problem with your database server.\\nPlease review the console output below to find out what needs to be fixed. | Contao has detected problems with your database server.\\nPlease review the console output below to find out what needs to be fixed.","ui.migrate.warning":"Contao has detected a misconfiguration of your database server.\\nWarnings can be skipped temporarily, but should be fixed for optimal performance and data integrity.","ui.migrate.error":"The changes could not be applied. Your database might have been changed, please check again to retry.","ui.migrate.execute":"Execute","ui.migrate.close":"关闭","ui.migrate.confirm":"确认 & 关闭","ui.migrate.cancel":"取消","ui.migrate.continue":"继续","ui.migrate.setup":"安装","ui.migrate.skip":"Skip","ui.migrate.retry":"Check again","ui.migrate.retryAll":"Check all","ui.migrate.withDeletes":"Execute all database changes including DROP queries.","ui.migrate.migrationTitle":"Database Migrations","ui.migrate.schemaTitle":"Schema Updates","ui.migrate.problemTitle":"Database Problems","ui.migrate.warningTitle":"Database Warnings","ui.migrate.addTable":"Add table {table}","ui.migrate.dropTable":"Drop table {table}","ui.migrate.addField":"Add field {table}.{field}","ui.migrate.changeField":"Change field {table}.{field}","ui.migrate.dropField":"Drop field {table}.{field}","ui.migrate.createIndex":"Create index \\"{name}\\" on {table}","ui.migrate.dropIndex":"Drop index \\"{name}\\" on {table}","ui.widget.mandatory":"该字段不能为空。","ui.widget.blankOption":"请选择 …","ui.widget.showPassword":"Show password","ui.widget.hidePassword":"Hide password","ui.error.title":"HTTP request for \\"{method} {url}\\" failed.","ui.error.server500":"Looks like an unexpected error happened on your server. Please check the log files of your web server (Apache/Nginx) and the Contao Manager logs at \\"contao-manager/logs\\".","ui.error.response":"The server returned a response with status code {status}.","ui.error.moreLink":"更多信息","ui.error.support":"Contao Support","ui.footer.help":"帮助","ui.footer.reportProblem":"报告问题","ui.navigation.discover":"发现","ui.navigation.packages":"包","ui.navigation.tools":"工具","ui.navigation.installTool":"安装工具","ui.navigation.backend":"Contao 后台","ui.navigation.debug":"Contao调试模式","ui.navigation.logViewer":"Log Viewer","ui.navigation.phpinfo":"PHP信息","ui.navigation.phpinfoLoading":"Loading PHP Information…","ui.navigation.maintenance":"维护","ui.navigation.rebuildCache":"重建缓存","ui.navigation.systemCheck":"系统检查","ui.navigation.advanced":"高级","ui.navigation.logout":"注销","ui.maintenance.databaseMigration.title":"Database Migrations","ui.maintenance.databaseMigration.description":"Database migrations ensure consistent data and table schemas.","ui.maintenance.databaseMigration.migrations":"One pending database migration | {count} pending database migrations","ui.maintenance.databaseMigration.schemaUpdates":"One pending schema update | {count} pending schema updates","ui.maintenance.databaseMigration.error":"Database problem found.","ui.maintenance.databaseMigration.warning":"Database warnings found.","ui.maintenance.databaseMigration.button":"Check database","ui.maintenance.databaseMigration.migrationOnly":"Check migrations only","ui.maintenance.databaseMigration.schemaOnly":"Check schema only","ui.maintenance.databaseMigration.installTool":"Open Install Tool","ui.maintenance.rebuildCache.title":"应用缓存","ui.maintenance.rebuildCache.description":"修改任何配置文件后，必须重建应用程序缓存。","ui.maintenance.rebuildCache.rebuildProd":"重建生产环境缓存","ui.maintenance.rebuildCache.rebuildDev":"重建开发环境缓存","ui.maintenance.rebuildCache.clearProd":"清除生产环境缓存","ui.maintenance.rebuildCache.clearDev":"清除开发环境缓存","ui.maintenance.installTool.title":"Contao安装工具","ui.maintenance.installTool.description":"连续输入3次错误密码会自动锁定Contao安装工具。","ui.maintenance.installTool.unlock":"解锁安装工具","ui.maintenance.installTool.lock":"锁定安装工具","ui.maintenance.dumpAutoload.title":"Composer类加载器","ui.maintenance.dumpAutoload.description":"Composer的自动加载器负责PHP类加载。添加自定义命名空间到根下的composer.json后必须转储自动加载器。","ui.maintenance.dumpAutoload.button":"打印Autoloader","ui.maintenance.composerInstall.title":"Composer依赖","ui.maintenance.composerInstall.description":"Composer dependencies are located in the {vendor} folder in your application root. Reinstalling the dependencies can be necessary after manipulation or manually uploading the {composerLock} file.","ui.maintenance.composerInstall.button":"运行安装器","ui.maintenance.composerInstall.update":"运行Composer更新","ui.maintenance.composerCache.title":"Composer缓存","ui.maintenance.composerCache.description":"Composer缓存下载的软件包以提高性能。 如果您遇到文件损坏等问题，请尝试删除Composer缓存以强制进行新的下载。","ui.maintenance.composerCache.button":"清楚缓存","ui.maintenance.maintenanceMode.title":"Maintenance Mode","ui.maintenance.maintenanceMode.description":"Putting Contao in maintenance mode will display a \\"503 Service Unavailable\\" template for the website.","ui.maintenance.maintenanceMode.enable":"Enable","ui.maintenance.maintenanceMode.disable":"Disable","ui.maintenance.debugMode.title":"调试模式","ui.maintenance.debugMode.description":"Activate the debug mode by setting a user and password for the {appDevPhp} entry point.","ui.maintenance.debugMode.descriptionJwt":"通过对于当前域名设置调试cookie来激活调试模式。","ui.maintenance.debugMode.activate":"激活","ui.maintenance.debugMode.deactivate":"未激活","ui.maintenance.debugMode.credentials":"证书","ui.maintenance.debugMode.user":"请输入用于调试模式的用户名。","ui.maintenance.debugMode.password":"请输入用于调试模式的密码。","ui.maintenance.opcodeCache.title":"Opcode缓存","ui.maintenance.opcodeCache.description":"Opcode在Web进程上缓存PHP文件以加快执行速度。 如果文件在更改后无法识别，则在某些情况下必须将其删除。","ui.maintenance.opcodeCache.button":"清除缓存","ui.maintenance.safeMode":"安装模式下无效","ui.maintenance.unsupported":"您的Contao版本不支持","ui.packages.updateButton":"更新包","ui.packages.searchButton":"搜索包","ui.packages.searchPlaceholder":"搜索包","ui.packages.uploadOverlay":"拖拽文件上传","ui.packages.uploadButton":"上传包","ui.packages.uploadMessage":"You have one unconfirmed upload. | You have {count} unconfirmed uploads.","ui.packages.uploadApply":"确认上传","ui.packages.uploadReset":"删除上传","ui.packages.uploadIncomplete":"此文件未完全上传。 请将其删除，然后重试。","ui.packages.uploadDuplicate":"此文件似乎多次上传。 请删除重复项。","ui.packages.uploadInstalled":"此文件已安装。请移除重复项。","ui.packages.uploadUnsupported":"Uploads are not supported in your installation. Please make sure that the PHP ZIP extension is installed and update your dependencies.","ui.packages.changesMessage":"You have one unconfirmed change. | You have {count} unconfirmed changes.","ui.packages.changesDryrun":"Dry Run","ui.packages.changesApply":"应用更改","ui.packages.changesApplyAll":"Update all packages","ui.packages.changesDryrunAll":"Dry run all packages","ui.packages.changesReset":"重置更改","ui.packages.changesReview":"预览更改","ui.packagelist.loading":"加载 …","ui.packagelist.uploads":"上传","ui.packagelist.added":"新包","ui.packagelist.installed":"已安装的包","ui.package.hintRevert":"恢复更改","ui.package.hintNoupdate":"不要更新","ui.package.hintConstraint":"应用更改时，此包将会带约束 {constraint} 安装。","ui.package.hintConstraintBest":"应用更改时，此包将会安装最佳版本。","ui.package.hintConstraintChange":"应用更改时，此包的约束将从\\"{from}\\"更改为\\"{to}\\"。","ui.package.hintConstraintUpdate":"应用更改后此包会被更新","ui.package.hintAdded":"应用更改后此包会被安装","ui.package.hintRemoved":"应用更改时，该程序包将被移除。","ui.package.requiredTitle":"手动添加","ui.package.requiredText":"composer.json中需要此包，但是没有安装","ui.package.removedTitle":"手动移除","ui.package.removedText":"此包已从composer.json移除。","ui.package.installed":"当前已安装:","ui.package.version":"版本 {version}","ui.package.additionalDownloads":"{count} Download | {count} Downloads","ui.package.additionalStars":"{count} Star | {count} Stars","ui.package.editConstraint":"编辑","ui.package.uploadConstraint":"此约束由上传的包定义。","ui.package.updateButton":"更新","ui.package.removeButton":"移除","ui.package.installButton":"添加包","ui.package.installButtonShort":"添加","ui.package.detailsButton":"详情","ui.package.latestConstraint":"最新版","ui.package.update":"Update available","ui.package.updateLatest":"最新版","ui.package.updateAvailable":"{version} available","ui.package.updateUnknown":"unknown version","ui.package.updateConstraint":"A newer version outside your version constraint is available.","ui.cloudStatus.headline":"Composer Resolver Cloud","ui.cloudStatus.version":"版本 {version}","ui.cloudStatus.waitingTime":"等待时间","ui.cloudStatus.jobs":"当前工作","ui.cloudStatus.workers":"工作者","ui.cloudStatus.approx":"{minutes} 分钟","ui.cloudStatus.none":"无","ui.cloudStatus.short":"ca. {minutes} 分钟","ui.cloudStatus.long":"ca. {minutes} 分钟 {seconds} 秒","ui.cloudStatus.error":"Unable to fetch the status of the Composer Resolver Cloud. It might be down for maintenance or experience issues.","ui.cloudStatus.button":"Cloud Status","ui.cloudStatus.refresh":"Refresh Cloud Status","ui.log-viewer.loading":"加载 …","ui.log-viewer.empty":"There are no log files on your server.","ui.log-viewer.reload":"Reload","ui.log-viewer.file":"Log file","ui.log-viewer.channel":"Channel","ui.log-viewer.channelTitle":"The channel this message was logged to.","ui.log-viewer.level":"Level","ui.log-viewer.levelTitle":"Severity of the log message.","ui.log-viewer.timeHeader":"Time","ui.log-viewer.messageHeader":"Message","ui.log-viewer.showContext":"Show Context","ui.log-viewer.hideContext":"Hide Context","ui.log-viewer.showExtra":"Show Extra","ui.log-viewer.hideExtra":"Hide Extra","ui.log-viewer.more":"Load more …","ui.log-viewer.download":"Download","ui.log-viewer.downloadTitle":"Download file \\"{file}\\"","ui.log-viewer.prodEnvironment":"Production Environment","ui.log-viewer.devEnvironment":"Development Environment (Debug Mode)"}')}}]);"use strict";(self["webpackChunkcontao_manager"]=self["webpackChunkcontao_manager"]||[]).push([[477],{6477:function(e){e.exports=JSON.parse('{"ui.app.httpsHeadline":"!! Unsichere Verbindung !!","ui.app.httpsDescription":"Ohne HTTPS werden deine vertraulichen Daten unverschlüsselt übertragen.","ui.app.httpsLink":"Weitere Informationen","ui.app.httpsHref":"https://https.cio.gov/everything/","ui.app.safeModeHeadline":"!! Abgesicherter Modus !!","ui.app.safeModeDescription":"Einige Funktionen des Contao Managers sind nicht verfügbar.","ui.app.safeModeExit":"Beenden","ui.app.limitedHeadline":"Remote-Anmeldung","ui.app.limitedDescription":"Du hast eingeschränkte Berechtigungen wegen automatischer Anmeldung.","ui.app.limitedLogout":"Neu anmelden","ui.app.totpHeadline":"Sicherheitshinweis","ui.app.totpDescription":"Konfiguriere jetzt die Zwei-Faktor-Anmeldung, um dein Konto sicherer zu machen.","ui.app.totpSetup":"Einrichtung","ui.app.loading":"Contao Manager wird geladen …","ui.app.apiError":"Unerwarteter API-Status","ui.app.configSecurity1":"SICHERHEITSWARNUNG !!! Das Konfigurationsverzeichnis ist ungeschützt","ui.app.configSecurity2":"Der Contao Manager hat erkannt, dass seine Konfigurationsdateien öffentlich erreichbar sind. Du musst diese Dateien schützen, bevor der Manager verwendet werden kann, da ein Angreifer sonst auf sensible Daten zugreifen könnte.\\n\\nUm dieses Problem zu beheben, schütze das Verzeichnis \\"contao-manager\\" auf deinem Server. Bei Fragen lies das Handbuch deines Webservers oder wende dich an deinen Hosting-Anbieter.","ui.account.welcome":"Willkommen","ui.account.intro1":"Willkommen zum Contao Manager, einem universellen Werkzeug, um das Contao Open Source CMS zu installieren, zu konfigurieren und zu warten. Wenn du den Manager zum ersten Mal einsetzt, {readTheManualToGetStarted}.","ui.account.introGetStarted":"{readTheManual} bevor du beginnst","ui.account.introManual":"lies die Dokumentation","ui.account.intro2":"Sollten Probleme auftreten, dann prüfe {ourGithubIssues}. Falls für dein Anliegen noch kein Ticket existiert, kannst du gern ein Neues erstellen.","ui.account.introIssues":"die Tickets auf GitHub","ui.account.headline":"Benutzerkonto","ui.account.description":"Erstelle ein Benutzerkonto, um deine Installation zu verwalten. Beachte, dass dieses Konto in keinem Zusammenhang mit dem Contao Backend oder Frontend steht.","ui.account.username":"Benutzername","ui.account.password":"Passwort","ui.account.passwordPlaceholder":"min. 8 Zeichen","ui.account.passwordLength":"Bitte gib mindestens 8 Zeichen ein.","ui.account.loginInvalid":"Beim erstellen des Konto ist ein Fehler aufgetreten. Bitte versuche einen anderen Benutzernamen.","ui.account.submit":"Benutzerkonto erstellen","ui.account.usePassword":"Mit Passwort anmelden","ui.account.usePasskey":"Mit Passkey anmelden","ui.account.totpHeadline":"Zwei-Faktor Anmeldung","ui.account.totpDescription":"Bitte aktivieren die Zwei-Faktor-Anmeldung, welche dein Konto sicherer macht. Zusätzlich zu deinem Benutzernamen und Passwort musst du einen Sicherheitscode eingeben, welcher von einer Zwei-Faktor-App wie 1Password, Authy, Google Authenticator, Microsoft Authenticator, LassPass Authenticator oder einer beliebigen anderen TOTP-App erzeugt wird.","ui.account.totpSetup":"Jetzt einrichten","ui.account.totpSkip":"Später einrichten","ui.account.login":"Einladung ablehnen","ui.account.contribute1":"Contao und der Contao Manager werden durch die Contao Association gefördert.","ui.account.contribute2":"{donate} und leiste deinen Beitrag zu Open Source!","ui.account.contributeDonate":"Mach eine Spende","ui.login.headline":"Anmeldung","ui.login.description":"Melde dich an, um deine Installation zu verwalten.","ui.login.username":"Benutzername","ui.login.password":"Passwort","ui.login.totpHeadline":"Zwei-Faktor Anmeldung","ui.login.totpDescription":"Bitte gibt den Sicherheitscode ein, um die Anmeldung abzuschliessen.","ui.login.totp":"Sicherheitscode","ui.login.forgotPassword":"Passwort vergessen?","ui.login.button":"Anmelden","ui.login.passkey":"Mit Passkey anmelden","ui.login.cancel":"Abbrechen","ui.login.or":"oder","ui.login.locked":"Der Zugriff wurde verweigert, da der Contao Manager gesperrt ist. Zum Entsperren lösche die Datei {lockFile} in deinem Contao Hauptverzeichnis.","ui.logout.headline":"Session-Timeout","ui.logout.warning":"Du warst mehr als 25 Minuten inaktiv. Aus Sicherheitsgründen wird deine Sitzung in Kürze beendet.","ui.logout.expired":"Deine Sitzung wurde automatisch beendet, da du mehr als 30 Minuten inaktiv warst.","ui.logout.renew":"Angemeldet bleiben","ui.logout.logout":"Abmelden","ui.logout.login":"Zurück zum Login","ui.oauth.error":"Ungültiger OAuth-Versuch. Bitte überprüfe die Request-Parameter.","ui.oauth.https":"Die Rückleitungs-URL MUSS eine sichere Verbindung (https:) nutzen, um die Übertragung der Anmeldedaten im Klartext zu verhindern.","ui.oauth.headline":"Remote-Anmeldung","ui.oauth.description":"Die folgende Anwendung oder der folgende Dienst fordert den Fernzugriff auf deine Contao Manager-Instanz an.","ui.oauth.domain":"Bevor du diesen Zugriff erlaubst, stelle sicher, dass du die URL kennst und ihr vertraust!","ui.oauth.outOfScope":"Du hast leider nicht genügend Berechtigungen um diesen Zugriff zu gewähren.","ui.oauth.allow":"Zugriff erlauben","ui.oauth.deny":"Zugriff verweigern","ui.oauth.switchUser":"Benutzer wechseln","ui.scope.admin":"Admin-Zugriff inkl. Benutzerverwaltung","ui.scope.install":"Pakete installieren und Contao-Konfiguration ändern","ui.scope.update":"Pakete aktualisieren und Wartungsaufgaben ausführen","ui.scope.read":"Pakete und Konfiguration sehen","ui.boot.headline":"Systemprüfung","ui.boot.description":"Bitte warten, dein Server wird überprüft …","ui.boot.issue1":"Installationsprobleme erkannt","ui.boot.issue2":"Du musst die Installationsprobleme beheben, bevor der Contao Manager verwendet werden kann.","ui.boot.run":"Contao Manager starten","ui.boot.safeMode":"Abgesicherten Modus starten","ui.recovery.headline":"Systemwiederherstellung","ui.recovery.description":"Es wurden Dateien erkannt, die nach einer Contao-Installation aussehen, aber die Kommandozeile scheint nicht korrekt zu funktionieren.","ui.recovery.console":"Konsolenausgabe","ui.recovery.repairOptions":"Wähle eine Option, um das System zu reparieren.","ui.recovery.repairHeadline":"Automatische Reparatur","ui.recovery.repairDescription":"Versucht eine automatische Systemreparatur, indem der Cache neu aufgebaut und die Composer-Pakete neu installiert werden.","ui.recovery.repairWarning":"Manuelle Änderungen an den vendor-Dateien können dabei verloren gehen!","ui.recovery.repairFailed":"Die automatische Reparatur ist fehlgeschlagen. Versuche den abgesicherten Modus, um die Installation von Hand zu reparieren.","ui.recovery.repairButton":"Reparatur ausführen","ui.recovery.safeModeHeadline":"Abgesicherter Modus","ui.recovery.safeModeDescription":"Der abgesicherte Modus erlaubt die Paketverwaltung und gewisse Wartungsaufgaben, aber Funktionen, welche ein funktionierendes Contao benötigen, sind nicht verfügbar.","ui.recovery.safeModeButton":"Abgesicherten Modus starten","ui.server.pending":"Warten …","ui.server.running":"Analysiere …","ui.server.error":"Die Prüfung ist aufgrund einer unerwarteten Server-Antwort fehlgeschlagen.","ui.server.details":"Details","ui.server.prerequisite":"Prüfung aufgrund fehlender Abhängigkeiten abgebrochen.","ui.server.selfUpdate.title":"Updates für den Contao Manager","ui.server.selfUpdate.update":"Die neue Version {latest} des Contao Managers ist verfügbar.","ui.server.selfUpdate.manualUpdate":"Eine neue Version {latest} des Contao Manager ist verfügbar. Dein Server unterstützt keine automatischen Updates, bitte lade die neue Version von {download} herunter.","ui.server.selfUpdate.latest":"Du verwendest die aktuelle Version {current}.","ui.server.selfUpdate.dev":"Entwicklungs-Versionen können nicht automatisch aktualisiert werden.","ui.server.selfUpdate.unsupported":"Eine neue Version ist verfügbar, aber diese funktioniert nicht mit deiner PHP-Version.","ui.server.selfUpdate.button":"Aktualisieren","ui.server.selfUpdate.continue":"Weiter","ui.server.config.title":"Serverkonfiguration","ui.server.config.setup":"Konfigurieren","ui.server.config.change":"Ändern","ui.server.config.save":"Speichern","ui.server.config.cancel":"Abbrechen","ui.server.config.customOption":"Andere …","ui.server.config.description":"Der Contao Manager benötigt den Pfad zum PHP-Binary und weitere Server-Informationen, um Hintergrund-Prozesse korrekt auszuführen.","ui.server.config.formTitle":"Serverkonfiguration","ui.server.config.formText":"Bitte gib den Pfad zu deinem PHP-Binary ein. Das Binary muss dieselbe PHP-Version sein wie der Webprozess.","ui.server.config.cloudTitle":"Composer Resolver Cloud","ui.server.config.cloudText":"Die Composer Resolver Cloud erlaubt die Installation von Composer-Abhängigkeiten, selbst wenn der lokale Server nicht über genug Arbeitsspeicher verfügt. Beachte, dass deine Paketinformationen an einen Cloud-Dienst der Contao Association übermittelt werden.","ui.server.config.cloud":"Die Composer Resolver Cloud verwenden","ui.server.config.cli":"PHP-Binary","ui.server.config.stateErrorCli":"Es wurde kein valides PHP-Programm auf dem Server gefunden.","ui.server.config.stateErrorCloud":"Die Composer Resolver Cloud wird nicht unterstützt.","ui.server.config.stateSuccess":"PHP-Binary in {php_cli}.","ui.server.config.cloudEnabled":"Erweiterungen werden mit Hilfe der Composer Resolver Cloud aktualisiert.","ui.server.config.cloudDisabled":"Die Composer Resolver Cloud ist deaktiviert.","ui.server.php_web.title":"PHP-Webprozess","ui.server.php_web.below7":"PHP Version {version} gefunden. Bitte wechsle baldmöglichst auf PHP 7!","ui.server.php_web.success":"PHP Version {version}, keine bekannten Probleme gefunden.","ui.server.php_cli.title":"PHP Kommandozeilen-Programm","ui.server.php_cli.success":"PHP Version {version}, keine bekannten Probleme gefunden.","ui.server.composer.title":"Composer-Umgebung","ui.server.composer.success":"Keine bekannten Probleme gefunden.","ui.server.composer.install":"Composer-Abhängigkeiten sind nicht installiert.","ui.server.composer.button":"Installieren","ui.server.contao.title":"Contao-Installation","ui.server.contao.setup":"Einrichtung","ui.server.contao.check":"Datenbank prüfen","ui.server.contao.empty":"Es wurde keine Contao-Installation gefunden.","ui.server.contao.old":"Contao {version} ist nicht kompatibel mit dem Contao Manager; bitte aktualisiere deine Installation manuell.","ui.server.contao.found":"Contao {version} (API-Version {api}) gefunden.","ui.server.contao.connectionError":"Verbindung zum Datenbank-Server fehlgeschlagen.","ui.server.contao.connectionProblem":"Datenbank-Problem gefunden.","ui.server.contao.missingUser":"Administratorkonto nicht gefunden.","ui.setup.continue":"Weiter","ui.setup.manager":"Contao Manager starten","ui.setup.cancel":"Abbrechen","ui.setup.welcome":"Willkommen","ui.setup.welcome1":"Dieser Assistent führt dich durch die Installation und Einrichtung deines Contao Open Source CMS.","ui.setup.welcome2":"Solltest du Fragen haben, findest du die Dokumentation, das Forum, den Slack Kanal und weiteres auf der {support}-Seite.","ui.setup.support":"Contao-Support","ui.setup.start":"Los geht\'s","ui.setup.complete":"Geschafft!","ui.setup.complete1":"Contao {version} wurde erfolgreich installiert.","ui.setup.complete2":"Um die Installation fertig zu stellen, öffne bitte das Install-Tool um die Datenbank zu verbinden und ein Backend-Konto hinzuzufügen.","ui.setup.complete3":"Du kannst nun deine Webseite im Contao Backend einrichten. Willst du Erweiterungen installieren, fahre mit dem Contao Manager fort.","ui.setup.installTool":"Install-Tool öffnen","ui.setup.login":"Contao Login","ui.setup.funding":"Ohne seine Community wäre Contao nicht das, was es heute ist. Wenn du professionell Webseiten mit Contao erstellst, sind wir auf deine Unterstützung angewiesen. Mit einer Investition in das Projekt sicherst du die Entwicklung für die Zukunft, damit dein Unternehmen weiterhin von Contao profitieren kann.","ui.setup.fundingLink":"Weitere Informationen","ui.setup.document-root.headline":"Webserver-Einrichtung","ui.setup.document-root.warning":"Um Contao über den Contao Manager zu installieren, muss das Wurzelverzeichnis des Webservers angepasst werden.","ui.setup.document-root.description1":"Contao verwendet einen Unterordner für öffentliche Dateien, die Systemdaten werden im übergeordneten Ordner installiert. Contao kann nicht installiert werden, wenn die Struktur nicht stimmt oder die Ordner nicht leer sind.","ui.setup.document-root.description2":"Falls du nicht weisst, wie dein Wurzelverzeichnis konfiguriert werden kann, lies die Contao Dokumentation oder kontaktiere deinen Hosting-Anbieter.","ui.setup.document-root.documentation":"Dokumentation lesen","ui.setup.document-root.conflictsTitle":"Installationsverzeichnis nicht leer","ui.setup.document-root.conflictsDirectory":"Das Wurzelverzeichnis deiner zukünftigen Contao-Installation ist nicht leer, es wurden {count} Datei(en) gefunden, die bei der Installation überschrieben werden könnten. Es wird empfohlen Contao in ein leeres Verzeichnis zu installieren, aber du kannst auch die Dateien löschen und erneut prüfen lassen, wenn du sicher bist, dass diese nicht benötigt werden.","ui.setup.document-root.ignoreConflicts":"Ich will Contao in ein nicht-leeres Verzeichnis installieren. Ich verstehe, dass dadurch bestehende Dateien auf meinem Server möglicherweise überschrieben werden.","ui.setup.document-root.check":"Erneut prüfen","ui.setup.document-root.create":"Verzeichnisse erstellen","ui.setup.document-root.change":"Verzeichnisse ändern","ui.setup.document-root.formTitle":"Verzeichnisstruktur einrichten","ui.setup.document-root.formText1":"Der Contao Manager kann automatisch eine neue Verzeichnisstruktur auf dem Server einrichten.","ui.setup.document-root.formText2":"Du musst das Wurzelverzeichnis danach manuell umkonfigurieren (z. B. über die Hosting-Administration).","ui.setup.document-root.autoconfig":"Ich habe verstanden, dass meine Server-Konfiguration geändert werden muss. Wenn ich dies nicht tue, funktioniert der Contao Manager nicht mehr und meine Konfigurationsdateien (inklusive Benutzer & Passwörter) werden öffentlich erreichbar!","ui.setup.document-root.directory":"Neuer Ordner","ui.setup.document-root.currentRoot":"Aktuelles Wurzelverzeichnis","ui.setup.document-root.newRoot":"Neues Wurzelverzeichnis","ui.setup.document-root.finish":"Ordner erstellen","ui.setup.document-root.publicDir":"{dir} für öffentliche Dateien nutzen (Contao {version})","ui.setup.document-root.directoryInvalid":"Bitte gib einen gültigen Ordnernamen ein.","ui.setup.document-root.directoryExists":"Das Zielverzeichnis ist bereits vorhanden. Bitte gibt einen anderen Namen ein.","ui.setup.document-root.confirmation":"Der Contao Manager hat die benötigten Verzeichnisse erfolgreich angelegt. Nun musst du dein Wurzelverzeichnis anpassen. Lade die Seite nicht neu, bis dies erledigt ist.","ui.setup.document-root.reload":"Neu laden","ui.setup.document-root.success":"Die Verzeichnisstruktur auf deinem Server ist korrekt eingerichtet!","ui.setup.document-root.installingProjectDir":"Systemdateien werden nach {dir} installiert.","ui.setup.document-root.installingPublicDir":"Öffentliche Dateien werden nach {dir} installiert.","ui.setup.document-root.installedProjectDir":"Systemdateien sind in {dir} installiert.","ui.setup.document-root.installedPublicDir":"Öffentliche Dateien sind in {dir} installiert.","ui.setup.create-project.headline":"Contao-Installation","ui.setup.create-project.description":"Die Contao-Entwicklung folgt dem Prinzip von {semver}, eine neue Minor-Version wird alle sechs Monate veröffentlicht. Die aktuell unterstützten Versionen sind:","ui.setup.create-project.semver":"Semantic Versioning","ui.setup.create-project.latestTitle":"Neuste","ui.setup.create-project.ltsTitle":"Langzeit-Support","ui.setup.create-project.latestQ1":"Unsere neuste Version mit den meisten Funktionen, wird bis Februar {year} unterstützt.","ui.setup.create-project.latestQ3":"Unsere neuste Version mit den meisten Funktionen, wird bis August {year} unterstützt.","ui.setup.create-project.ltsText":"Unsere aktuelle LTS-Version mit Fokus auf Stabilität. Bietet einen verlängerten Supportzeitraum bis Februar {year}.","ui.setup.create-project.pltsText":"Die vorherige LTS-Version, hat einen verlängerten Supportzeitraum bis Februar {year}","ui.setup.create-project.requiresPHP":"Benötigt mindestens PHP {version}, du hast PHP {current}.","ui.setup.create-project.releaseplan":"Weitere Details findest du im {contaoReleasePlan}.","ui.setup.create-project.releaseplanLink":"Contao Release-Plan","ui.setup.create-project.installed":"Contao {version} wurde erfolgreich auf dem Server installiert. Fahre weiter, um die Datenbank einzurichten, oder gehe zum Contao Manager um eine andere Version zu installieren.","ui.setup.create-project.formTitle":"Wähle eine Distribution","ui.setup.create-project.formText":"Bitte wähle die zu installierende Version.","ui.setup.create-project.version":"Version","ui.setup.create-project.demo":"Beispiel-Webseite installieren","ui.setup.create-project.demoDescription":"Die Beispiel-Webseite von Contao hilft dir dabei, dich mit dem System und seinen Hauptfunktionen vertraut zu machen. Weitere Themes findest du im {store}.","ui.setup.create-project.coreOnly":"Minimale Installation (nur Core)","ui.setup.create-project.noUpdate":"Installation überspringen (Expertenmodus!)","ui.setup.create-project.theme":"Theme für Contao","ui.setup.create-project.themeInstall":"Um ein Theme für Contao zu installieren, benutze die Sucheingabe oder lade eine Theme-Datei (.cto/.zip) hoch, die den Contao Manager unterstützt.","ui.setup.create-project.themeBuy":"Besuche auch den {store}.","ui.setup.create-project.themeStore":"Contao Themes-Store","ui.setup.create-project.themeUpload":"Theme-Datei (.cto/.zip) hochladen","ui.setup.create-project.themeInvalid":"Die hochgeladene Datei ist kein Theme für Contao oder unterstützt die Installation im Contao Manager nicht.","ui.setup.create-project.themeWarning":"Der Contao Manager kann nicht beurteilen, ob dieses Theme mit deinem Server kompatibel ist. Wende dich bei Fragen bitte direkt an den Theme-Hersteller.","ui.setup.create-project.themeTitle":"Theme-Details überprüfen","ui.setup.create-project.themeDetails":"Die nachfolgenden Abhängigkeiten und Dateien werden mit diesem Theme installiert.","ui.setup.create-project.themeRequire":"{count} Abhängigkeit | {count} Abhängigkeiten","ui.setup.create-project.themeFiles":"{count} Datei | {count} Dateien","ui.setup.create-project.theme.or":"oder suche öffentliche Themes","ui.setup.create-project.theme.search":"Themes durchsuchen","ui.setup.create-project.theme.more":"Weitere Themes","ui.setup.create-project.theme.empty":"Keine Theme für {query} gefunden","ui.setup.create-project.theme.uploaded":"Die Theme-Datei wurde erfolgreich hochgeladen.","ui.setup.create-project.theme.packageName":"Paketname","ui.setup.create-project.theme.version":"Version","ui.setup.create-project.theme.authors":"Autor(en)","ui.setup.create-project.theme.upload":"{name} ({size}) wird hochgeladen","ui.setup.create-project.install":"Installieren","ui.setup.create-project.cancel":"Abbrechen","ui.setup.create-project.fileError":"Es wurde keine composer.json in {file} gefunden.","ui.setup.create-project.jsonError":"Die composer.json enthält ungültiges JSON.","ui.setup.create-project.schemaError":"Die composer.json enthält ein ungültiges Schema.","ui.setup.database-connection.headline":"Datenbank-Verbindung","ui.setup.database-connection.description":"Contao benötigt eine MySQL Datenbank (oder ein kompatibler Fork wie MariaDB), um Seiten, Inhalte und andere Daten zu speichern. Die Verbindungsdaten werden in der Datei {env} im Systemverzeichnis von Contao gespeichert werden.","ui.setup.database-connection.formTitle":"Verbindungs-Parameter","ui.setup.database-connection.formText":"Gib eine Datenbank-URL ein, oder fülle die Felder für Benutzername, Passwort, Server und Datenbank separat aus.","ui.setup.database-connection.url":"Datenbank-URL","ui.setup.database-connection.validUrl":"Datenbank-URL ungültig oder Verbindung zum Server fehlgeschlagen.","ui.setup.database-connection.or":"oder","ui.setup.database-connection.user":"Benutzername","ui.setup.database-connection.password":"Passwort","ui.setup.database-connection.server":"Server (:Port)","ui.setup.database-connection.database":"Datenbankname","ui.setup.database-connection.connected":"Erfolgreich verbunden mit Datenbank {database} auf {server}.","ui.setup.database-connection.error":"Fehler beim Verbinden mit der Datenbank.","ui.setup.database-connection.problem":"Contao hat ein Problem mit dem Datenbank-Server gefunden.","ui.setup.database-connection.schemaTitle":"Datenbank-Schema","ui.setup.database-connection.migration":"Es gibt eine ausstehende Migration. | Es gibt {count} ausstehende Migrationen.","ui.setup.database-connection.schema":"Es gibt eine ausstehende Schema-Änderung. | Es gibt {count} ausstehende Schema-Änderungen.","ui.setup.database-connection.noChanges":"Dein Datenbank-Schema ist aktuell.","ui.setup.database-connection.check":"Datenbank prüfen","ui.setup.database-connection.skip":"Überspringen","ui.setup.database-connection.save":"Speichern","ui.setup.database-connection.change":"Zugangsdaten ändern","ui.setup.database-connection.restoreTitle":"Datenbank-Import","ui.setup.database-connection.restoreText":"Das soeben installierte Theme enthält ein Datenbank-Backup. Du kannst diese Theme-Daten in die Datenbank importieren oder diesen Schritt überspringen und mit einem leeren Contao beginnen. | Das soeben installierte Theme enthält mehrere Datenbank-Backups. Wähle eine Backup-Datei für den Import oder überspringe diesen Schritt, um mit einem leeren Contao zu beginnen.","ui.setup.database-connection.backup":"Datenbank vor dem Import sichern","ui.setup.database-connection.backupWarning":"Alle Daten in der Datenbank werden beim Import überschrieben! Erstelle zuerst ein Backup, falls die Datenbank nicht leer ist.","ui.setup.database-connection.restore":"Theme importieren","ui.setup.database-connection.restoreOption":"Backup vom {date} ({size})","ui.setup.database-connection.restored":"Die Theme-Datenbank wurde erfolgreich importiert. Fahre fort, um das Datenbank-Schema zu überprüfen.","ui.setup.backend-user.success":"Es ist bereits ein Benutzerkonto in der Datenbank vorhanden. Weitere Konten können über das Backend hinzugefügt werden.","ui.setup.backend-user.error":"Die Benutzerliste konnte nicht gelesen werden. Weitere Details findest du in der Konsolen-Ausgabe.","ui.setup.backend-user.headline":"Backend-Konto","ui.setup.backend-user.description":"Um deine Webseite zu verwalten, benötigst du mindestens ein Administratorkonto für das Contao Backend. Beachte, dass dieses Konto nicht mit dem Contao Manager zusammenhängt.","ui.setup.backend-user.formTitle":"Benutzerkonto erstellen","ui.setup.backend-user.formText":"Bitte gib die Details für das neue Backend-Konto ein.","ui.setup.backend-user.username":"Benutzername","ui.setup.backend-user.name":"Name","ui.setup.backend-user.email":"E-Mail-Adresse","ui.setup.backend-user.emailInvalid":"Bitte gib eine gültige E-Mail-Adresse ein","ui.setup.backend-user.password":"Passwort","ui.setup.backend-user.passwordPlaceholder":"min. 8 Zeichen","ui.setup.backend-user.passwordLength":"Bitte gib mindestens 8 Zeichen ein.","ui.setup.backend-user.create":"Konto hinzufügen","ui.task.headline":"Hintergrund-Prozess","ui.task.loading":"Lade Details …","ui.task.created":"Lade Details …","ui.task.active":"Bitte warte, während der Contao Manager die nötigen Operationen im Hintergrund ausführt.","ui.task.complete":"Alle Operationen erfolgreich abgeschlossen. Weitere Details findest du in der Konsolen-Ausgabe.","ui.task.paused":"Ein Hintergrund-Prozess wurde unerwartet beendet. Bitte prüfe die Konsolen-Ausgabe.","ui.task.aborting":"Bitte warte, während der Hintergrund-Prozess abgebrochen wird.","ui.task.stopped":"Einige Operationen wurden abgebrochen. Bitte prüfe die Konsolen-Ausgabe.","ui.task.error":"Ein Hintergrund-Prozess wurde unerwartet beendet. Bitte prüfe die Konsolen-Ausgabe.","ui.task.failed":"Der Contao Manager konnte den Hintergrund-Prozess nicht starten.","ui.task.failedDescription1":"Die Ausführung der Aufgabe ist fehlgeschlagen.","ui.task.failedDescription2":"Sollte dies wiederholt geschehen, wird dein Server möglicherweise nicht unterstützt.","ui.task.reportProblem":"Probleme melden","ui.task.pausedDescription":"Klick auf \\"Weiter\\", um den Fehler zu ignorieren und die verbleibenden Aufgaben auszuführen.","ui.task.sponsor":"Composer Cloud gesponsert von {sponsor}","ui.task.buttonAudit":"Datenbank aktualisieren","ui.task.buttonClose":"Schließen","ui.task.buttonConfirm":"Bestätigen & Schließen","ui.task.buttonContinue":"Weiter","ui.task.buttonCancel":"Abbrechen","ui.task.confirmCancel":"Möchtest du diesen Prozess wirklich abbrechen? Deine Contao-Installation könnte in einem defekten Zustand zurückbleiben!","ui.task.autoclose":"Fenster bei Erfolg schließen","ui.console.toggle":"Konsolenausgabe anzeigen/verstecken","ui.console.showLog":"Vollständige Konsole anzeigen","ui.console.copyLog":"Konsole in Zwischenablage kopieren","ui.migrate.headline":"Datenbank-Änderungen","ui.migrate.migrationsOnly":"(nur Migrationen)","ui.migrate.schemaOnly":"(nur Schema)","ui.migrate.loading":"Bitte warten, die Datenbank wird überprüft …","ui.migrate.empty":"Keine ausstehenden Migrationen oder Schema-Änderungen gefunden. Deine Datenbank ist auf dem aktuellsten Stand.","ui.migrate.emptyMigrations":"Keine ausstehenden Migrationen gefunden. Bitte prüfe auch die Schema-Änderungen.","ui.migrate.emptySchema":"Keine ausstehenden Schema-Änderungen gefunden. Bitte prüfe auch die Migrationen.","ui.migrate.pending":"Die Datenbank ist nicht aktuell. Bitte prüfe die untenstehende Konsolenausgabe und führe die Änderungen aus.","ui.migrate.previousChanges":"Eine vorherige Datenbankmigration wurde nicht bestätigt.\\nBitte prüfen die untenstehende Konsolenausgabe und klicke weiter, um die nächsten Änderungen zu sehen.","ui.migrate.previousComplete":"Eine vorherige Datenbankmigration wurde nicht bestätigt, bitte prüfe die untenstehende Konsolenausgabe.\\nEs gibt keine weiteren ausstehenden Änderungen.","ui.migrate.appliedChanges":"Die Datenbankänderungen wurden übernommen.\\nBitte prüfe die untenstehende Konsolenausgabe, dann klicke weiter, um die nächsten Änderungen zu sehen.","ui.migrate.appliedComplete":"Die Datenbankänderungen wurden übernommen.\\nEs gibt keine weiteren Migrationen oder Schema-Änderungen. Deine Datenbank ist auf dem aktuellen Stand.","ui.migrate.problem":"Contao hat ein Problem mit dem Datenbank-Server gefunden.\\nBitte prüfe die Konsolen-Ausgabe unten, um zu sehen was angepasst werden muss. | Contao hat Probleme mit dem Datenbank-Server gefunden.\\nBitte prüfe die Konsolen-Ausgabe unten, um zu sehen was angepasst werden muss.","ui.migrate.warning":"Contao hat eine Fehlkonfiguration des Datenbank-Servers gefunden.\\nDie unten stehenden Warnungen sollten für optimalen Betrieb und Datensicherheit behoben werden.","ui.migrate.error":"Die Änderungen konnten nicht angewendet werden. Möglicherweise wurde die Datenbank geändert, bitte prüfe nochmals und versuche es erneut.","ui.migrate.execute":"Ausführen","ui.migrate.close":"Schließen","ui.migrate.confirm":"Bestätigen & Schließen","ui.migrate.cancel":"Abbrechen","ui.migrate.continue":"Weiter","ui.migrate.setup":"Einrichtung","ui.migrate.skip":"Überspringen","ui.migrate.retry":"Erneut prüfen","ui.migrate.retryAll":"Alles überprüfen","ui.migrate.withDeletes":"Alle Änderungen inklusive Löschungen anwenden.","ui.migrate.migrationTitle":"Datenbank-Migrationen","ui.migrate.schemaTitle":"Schema-Änderungen","ui.migrate.problemTitle":"Datenbank-Probleme","ui.migrate.warningTitle":"Datenbank-Warnungen","ui.migrate.addTable":"Tabelle {table} hinzufügen","ui.migrate.dropTable":"Tabelle {table} löschen","ui.migrate.addField":"Feld {table}.{field} hinzufügen","ui.migrate.changeField":"Feld {table}.{field} ändern","ui.migrate.dropField":"Feld {table}.{field} löschen","ui.migrate.createIndex":"Index \\"{name}\\" zu {table} hinzufügen","ui.migrate.dropIndex":"Index \\"{name}\\" aus {table} löschen","ui.widget.mandatory":"Dieses Feld darf nicht leer sein.","ui.widget.blankOption":"Bitte wählen …","ui.widget.showPassword":"Passwort anzeigen","ui.widget.hidePassword":"Passwort ausblenden","ui.error.title":"HTTP-Anfrage für \\"{method} {url}\\" fehlgeschlagen.","ui.error.server500":"Es scheint ein unbekannter Fehler aufgetreten zu sein. Prüfe die Log-Dateien deines Webservers (Apache/Nginx) und des Contao Managers im Ordner \\"contao-manager/logs\\".","ui.error.response":"Der Server hat eine Antwort mit Status-Code {status} gesendet.","ui.error.moreLink":"Weitere Informationen","ui.error.support":"Contao Support","ui.error.permission":"Du hast keine Berechtigung für diese Funktion.","ui.footer.help":"Hilfe","ui.footer.reportProblem":"Probleme melden","ui.navigation.discover":"Entdecken","ui.navigation.packages":"Pakete","ui.navigation.tools":"Tools","ui.navigation.installTool":"Installtool","ui.navigation.backend":"Contao-Backend","ui.navigation.debug":"Contao-Debug-Modus","ui.navigation.logViewer":"System-Log","ui.navigation.phpinfo":"PHP-Informationen","ui.navigation.phpinfoLoading":"Lade PHP-Informationen…","ui.navigation.maintenance":"Systemwartung","ui.navigation.rebuildCache":"Cache erneuern","ui.navigation.users":"Konten","ui.navigation.systemCheck":"Systemprüfung","ui.navigation.advanced":"Fortgeschritten","ui.navigation.logout":"Abmelden","ui.maintenance.database.title":"Datenbank-Migrationen und -Backups","ui.maintenance.database.description":"Datenbankmigrationen stellen konsistente Daten und Tabellenschemas sicher.","ui.maintenance.database.migrations":"Eine ausstehende Datenbank-Migration | {count} ausstehende Datenbank-Migrationen","ui.maintenance.database.schemaUpdates":"Eine ausstehende Schema-Änderung | {count} ausstehende Schema-Änderungen","ui.maintenance.database.error":"Datenbank-Problem gefunden.","ui.maintenance.database.warning":"Datenbank-Warnung gefunden.","ui.maintenance.database.button":"Datenbank prüfen","ui.maintenance.database.migrationOnly":"Nur Migrationen prüfen","ui.maintenance.database.schemaOnly":"Nur Schema prüfen","ui.maintenance.database.installTool":"Install-Tool öffnen","ui.maintenance.database.createBackup":"Backup erstellen","ui.maintenance.database.backupUnsupported":"Datenbank-Backups werden von deiner Contao-Version nicht unterstützt.","ui.maintenance.database.backupList":"Du hast ein Datenbank-Backup, erstellt am {date}. | Du hast {count} Datenbank-Backups, das neuste wurde am {date} erstellt.","ui.maintenance.database.backupEmpty":"Du hast noch keine Datenbank-Backups.","ui.maintenance.rebuildCache.title":"Anwendungs-Cache","ui.maintenance.rebuildCache.description":"Nach dem Ändern einer der Konfigurationsdateien muss der Anwendungs-Cache neu aufgebaut werden.","ui.maintenance.rebuildCache.rebuildProd":"Prod.-Cache erneuern","ui.maintenance.rebuildCache.rebuildDev":"Dev.-Cache erneuern","ui.maintenance.rebuildCache.clearProd":"Prod.-Cache leeren","ui.maintenance.rebuildCache.clearDev":"Dev.-Cache leeren","ui.maintenance.installTool.title":"Contao-Installtool","ui.maintenance.installTool.description":"Das Contao-Installtool wird automatisch gesperrt, wenn das Passwort drei Mal falsch eingegeben wird.","ui.maintenance.installTool.unlock":"Installtool entsperren","ui.maintenance.installTool.lock":"Installtool sperren","ui.maintenance.dumpAutoload.title":"Composer Class Loader","ui.maintenance.dumpAutoload.description":"Der Composer-Autoloader ist für das Laden der PHP-Klassen verantwortlich. Der Autoloader muss nach dem Hinzufügen von eigenen Namespaces in die composer.json neu geschrieben werden.","ui.maintenance.dumpAutoload.button":"Datei aktualisieren","ui.maintenance.composerInstall.title":"Composer-Abhängigkeiten","ui.maintenance.composerInstall.description":"Composer-Abhängigkeiten befinden sich im Ordner {vendor} im Hauptverzeichnis deiner Anwendung. Eine Neuinstallation der Abhängigkeiten kann nach der Bearbeitung oder dem manuellen Hochladen der Datei {composerLock} notwendig sein.","ui.maintenance.composerInstall.button":"Installer ausführen","ui.maintenance.composerInstall.update":"Composer Update ausführen","ui.maintenance.composerCache.title":"Composer-Cache","ui.maintenance.composerCache.description":"Composer speichert heruntergeladene Pakete im Cache, um die Performance zu verbessern. Wenn Du z. B. Probleme mit korrupten Dateien hast, kannst du den Composer-Cache leeren, um einen neuen Download zu erzwingen.","ui.maintenance.composerCache.button":"Cache leeren","ui.maintenance.maintenanceMode.title":"Wartungsmodus","ui.maintenance.maintenanceMode.description":"Im Wartungsmodus zeigt Contao das \\"503 Dienst nicht verfügbar\\"-Template anstelle der Webseite an.","ui.maintenance.maintenanceMode.enable":"Aktivieren","ui.maintenance.maintenanceMode.disable":"Deaktivieren","ui.maintenance.debugMode.title":"Debug-Modus","ui.maintenance.debugMode.description":"Aktiviere den Debug-Modus, indem du einen Benutzer und ein Passwort für den Einstiegspunkt {appDevPhp} festlegen.","ui.maintenance.debugMode.descriptionJwt":"Aktiviert den Debug-Modus, indem für die aktuelle Domain ein entsprechendes Cookie gesetzt wird.","ui.maintenance.debugMode.activate":"Aktivieren","ui.maintenance.debugMode.deactivate":"Deaktivieren","ui.maintenance.debugMode.credentials":"Anmeldedaten","ui.maintenance.debugMode.user":"Bitte gib einen Benutzernamen für den Debug-Modus ein.","ui.maintenance.debugMode.password":"Bitte gib ein Passwort für den Debug-Modus ein.","ui.maintenance.opcodeCache.title":"Opcode-Cache","ui.maintenance.opcodeCache.description":"Der Opcode-Cache speichert PHP-Dateien im Webprozess für eine schnellere Ausführung. Er muss unter Umständen gelöscht werden, wenn Dateien nach dem Ändern nicht erkannt werden.","ui.maintenance.opcodeCache.button":"Cache leeren","ui.maintenance.safeMode":"Deaktiviert im abgesicherten Modus","ui.maintenance.unsupported":"Von deiner Contao-Version nicht unterstützt","ui.packages.updateButton":"Pakete aktualisieren","ui.packages.searchButton":"Pakete suchen","ui.packages.searchPlaceholder":"Pakete suchen …","ui.packages.uploadOverlay":"Lege Dateien hier ab, um sie hochzuladen","ui.packages.uploadButton":"Pakete hochladen","ui.packages.uploadMessage":"Du hast einen unbestätigten Upload. | Du hast {count} unbestätigte Uploads.","ui.packages.uploadApply":"Uploads bestätigen","ui.packages.uploadReset":"Uploads löschen","ui.packages.uploadIncomplete":"Diese Datei wurde nicht vollständig hochgeladen. Bitte entferne sie und versuchen es noch einmal.","ui.packages.uploadDuplicate":"Diese Datei scheint mehrfach hochgeladen worden zu sein. Bitte entferne die Duplikate.","ui.packages.uploadInstalled":"Diese Datei ist bereits installiert. Bitte entferne die Duplikate.","ui.packages.uploadUnsupported":"Uploads werden in deiner Installation nicht unterstützt. Stelle sicher, dass die PHP ZIP-Erweiterung installiert ist und aktualisiere die Abhängigkeiten.","ui.packages.changesMessage":"Du hast eine unbestätigte Änderung. | Du hast {count} unbestätigte Änderungen.","ui.packages.changesDryrun":"Testlauf","ui.packages.changesApply":"Änderungen anwenden","ui.packages.changesApplyAll":"Alle Pakete aktualisieren","ui.packages.changesDryrunAll":"Testlauf mit allen Paketen","ui.packages.changesReset":"Änderungen verwerfen","ui.packages.changesReview":"Änderungen prüfen","ui.packagelist.loading":"Laden …","ui.packagelist.uploads":"Uploads","ui.packagelist.added":"Neue Pakete","ui.packagelist.installed":"Installierte Pakete","ui.package.hintRevert":"Änderung verwerfen","ui.package.hintNoupdate":"Nicht aktualisieren","ui.package.hintConstraint":"Dieses Paket wird mit der Versionsbedingung {constraint} installiert, wenn du die Änderungen anwendest.","ui.package.hintConstraintBest":"Dieses Paket wird in der besten verfügbaren Version installiert, wenn du die Änderungen anwendest.","ui.package.hintConstraintChange":"Die Versionsbedingung dieses Pakets wird von \\"{from}\\" in \\"{to}\\" geändert, wenn du die Änderungen anwendest.","ui.package.hintConstraintUpdate":"Dieses Paket wird aktualisiert, wenn du die Änderungen anwendest.","ui.package.hintAdded":"Dieses Paket wird installiert, wenn du die Änderungen anwendest.","ui.package.hintRemoved":"Dieses Paket wird entfernt, wenn du die Änderungen anwendest.","ui.package.requiredTitle":"manuell hinzugefügt","ui.package.requiredText":"Dieses Paket wurde in der composer.json hinzugefügt, ist aber nicht installiert.","ui.package.removedTitle":"manuell entfernt","ui.package.removedText":"Dieses Paket wurde aus der composer.json entfernt.","ui.package.installed":"Aktuell installiert:","ui.package.version":"Version {version}","ui.package.additionalDownloads":"{count} Download | {count} Downloads","ui.package.additionalStars":"{count} Stern | {count} Sterne","ui.package.editConstraint":"Bearbeiten","ui.package.uploadConstraint":"Diese Versionsbedingung wird von dem hochgeladenen Paket definiert.","ui.package.updateButton":"Aktualisieren","ui.package.removeButton":"Entfernen","ui.package.installButton":"Paket hinzufügen","ui.package.installButtonShort":"Hinzufügen","ui.package.detailsButton":"Details","ui.package.latestConstraint":"neuste Version","ui.package.update":"Update verfügbar","ui.package.updateLatest":"neuste Version","ui.package.updateAvailable":"{version} verfügbar","ui.package.updateUnknown":"unbekannte Version","ui.package.updateConstraint":"Es ist eine neuere Version ausserhalb der Versionsbedingung verfügbar.","ui.package.incompatible":"{package} funktioniert nicht mit Contao {constraint}.","ui.package.incompatibleWarning":"{package} bietet keine stabile Version für Contao {constraint} an. Möchtest du das Paket hinzufügen und eine Versionsbedingung setzen, um eine Entwicklungsversion zu installieren?","ui.package.incompatibleConstraint":"Diese Erweiterung bietet keine stabile Version für Contao {constraint}. Gib eine Versionsbedingung ein, um eine Entwicklungsversion zu installieren.","ui.package.incompatibleButton":"Installieren","ui.cloudStatus.headline":"Composer Resolver Cloud","ui.cloudStatus.version":"Version {version}","ui.cloudStatus.waitingTime":"Wartezeit","ui.cloudStatus.jobs":"Aktive Aufgaben","ui.cloudStatus.workers":"Server","ui.cloudStatus.approx":"{minutes} min","ui.cloudStatus.none":"keine","ui.cloudStatus.short":"ca. {minutes} min","ui.cloudStatus.long":"ca. {minutes} min {seconds} sek","ui.cloudStatus.error":"Status der Composer Resolver Cloud konnte nicht abgerufen werden. Möglicherweise gibt es ein Wartungsfenster oder Systemprobleme.","ui.cloudStatus.button":"Cloud-Status","ui.cloudStatus.refresh":"Cloud-Status aktualisieren","ui.log-viewer.loading":"Laden …","ui.log-viewer.empty":"Auf dem Server sind keine Logdateien vorhanden.","ui.log-viewer.reload":"Neu laden","ui.log-viewer.file":"Logdatei","ui.log-viewer.channel":"Kanal","ui.log-viewer.channelTitle":"Kanal in welcher die Nachricht geschrieben wurde.","ui.log-viewer.level":"Stufe","ui.log-viewer.levelTitle":"Wichtigkeit der Log-Nachricht.","ui.log-viewer.timeHeader":"Uhrzeit","ui.log-viewer.messageHeader":"Nachricht","ui.log-viewer.showContext":"Kontext anzeigen","ui.log-viewer.hideContext":"Kontext ausblenden","ui.log-viewer.showExtra":"Extras anzeigen","ui.log-viewer.hideExtra":"Extras ausblenden","ui.log-viewer.more":"Mehr laden …","ui.log-viewer.download":"Herunterladen","ui.log-viewer.downloadTitle":"Datei \\"{file}\\" herunterladen","ui.log-viewer.prodEnvironment":"Produktivumgebung","ui.log-viewer.devEnvironment":"Entwicklungsumgebung (Debug Modus)","ui.user-manager.loading":"Lade Benutzer:innen …","ui.user-manager.changePassword":"Passwort ändern","ui.user-manager.setupTotp":"Zwei-Faktor konfigurieren","ui.user-manager.disableTotp":"Zwei-Faktor deaktivieren","ui.user-manager.invite":"Benutzer:in einladen","ui.user-manager.delete":"Löschen","ui.user-manager.deleteConfirm":"Möchtest du das Konto von \\"{username}\\" wirklich löschen?","ui.user-manager.deleted":"Das Konto für {username} wurde gelöscht.","ui.user-manager.passwordHeadline":"Passwort ändern","ui.user-manager.passwordText":"Um dein Passwort zu ändern, gibt dein bestehendes und ein neues Passwort in den entsprechenden Feldern ein.","ui.user-manager.currentPassword":"Aktuelles Passwort","ui.user-manager.newPassword":"Neues Passwort","ui.user-manager.passwordPlaceholder":"min. 8 Zeichen","ui.user-manager.submitPassword":"Absenden","ui.user-manager.passwordChanged":"Dein Passwort wurde erfolgreich geändert.","ui.user-manager.passwordError":"Dieses Passwort stimmt nicht.","ui.user-manager.inviteHeadline":"Benutzer:in einladen","ui.user-manager.inviteText":"Falls du mehrere Logins zum Contao Manager benötigst, kannst du hier einen Einladungs-Link erstellen. Teile diesen Link mit jemandem oder benutze ihn auf einem anderen Gerät, um ein neues Konto mit den entsprechenden Berechtigungen zu erstellen.","ui.user-manager.inviteSuccess1":"Ein Einladungs-Link wurde erstellt. Mit der untenstehenden URL kann ein neues Konto für diesen Contao Manager erstellt werden. Die Einladung läuft ab am {expires} (eine Woche ab jetzt).","ui.user-manager.inviteSuccess2":"Kopiere den Link in deine Zwischenablage. Er funktioniert nur einmal, und du kannst ihn nach dem Schliessen dieses Fensterns nicht mehr sehen.","ui.user-manager.createInvitation":"Einladungs-Link erstellen","ui.user-manager.clipboard":"In Zwischenablage kopieren","ui.user-manager.permissions":"Mehr über Berechtigungen","ui.user-manager.cancel":"Abbrechen","ui.user-manager.close":"Schließen","ui.user-manager.you":"Du","ui.user-manager.2fa":"2FA","ui.user-manager.2faEnabled":"Dieses Konto ist duch Zwei-Faktor-Anmeldung abgesichert.","ui.user-manager.2faDisabled":"Dieses Konto ist unsicher, da keine Zwei-Faktor-Anmeldung konfiguriert wurde.","ui.user-manager.passkey":"Passkey","ui.user-manager.passkeyTitle":"Dieses Konto ist durch einen Passkey abgesichert.","ui.totp.headline":"Zwei-Faktor Anmeldung","ui.totp.setupQr":"Scanne den QR-Code mit deiner 2FA/TOTP-Applikation.","ui.totp.setupCode":"Falls du den QR-Code nicht scannen kannst, gibt folgenden Schlüssel ein:","ui.totp.codeLabel":"Sicherheitscode","ui.totp.codeDescription":"Bitte gibt den Sicherheitscode ein, welcher von deiner 2FA/TOTP-Applikation generiert wurde.","ui.totp.disableText":"Gib den Sicherheitscode ein, um die Zwei-Faktor-Anmeldung zu deaktivieren.","ui.totp.invalid":"Der Sicherheitscode ist ungültig.","ui.totp.enable":"Aktivieren","ui.totp.disable":"Deaktivieren","ui.totp.cancel":"Abbrechen","ui.totp.enabled":"Die Zwei-Faktor-Anmeldung wurde erfolgreich aktiviert.","ui.totp.disabled":"Die Zwei-Faktor-Anmeldung wurde erfolgreich deaktiviert.","ui.totp.setup":"Zwei-Faktor-Anmeldung konfigurieren","ui.totp.skip":"Zwei-Faktor-Anmeldung überspringen"}')}}]);"use strict";(self["webpackChunkcontao_manager"]=self["webpackChunkcontao_manager"]||[]).push([[553],{5553:function(e){e.exports=JSON.parse('{"ui.app.httpsHeadline":"!! Insecure Connection !!","ui.app.httpsDescription":"Without HTTPS your confidential data will be transferred unencrypted.","ui.app.httpsLink":"More Info","ui.app.httpsHref":"https://https.cio.gov/everything/","ui.app.safeModeHeadline":"!! Safe Mode enabled !!","ui.app.safeModeDescription":"Some features of the Contao Manager are not available.","ui.app.safeModeExit":"Exit Safe Mode","ui.app.limitedHeadline":"Remote Authentication","ui.app.limitedDescription":"You have limited permissions due to passwordless login.","ui.app.limitedLogout":"Re-authenticate","ui.app.totpHeadline":"Security Notice","ui.app.totpDescription":"Configure two-factor authentication now to secure your account.","ui.app.totpSetup":"Setup","ui.app.loading":"Loading Contao Manager …","ui.app.apiError":"Unexpected API status","ui.app.configSecurity1":"SECURITY ALERT !!! Unprotected config directory detected","ui.app.configSecurity2":"The Contao Manager has detected that its config files are publicly accessible. All operations are disabled until the directory is secured, otherwise an attacker could access sensitive data of your installation.\\n\\nTo fix this issue, make sure to prevent access to the \\"contao-manager\\" directory on your server. To learn how to do this, please refer to the manual of your webserver or contact your hosting provider.","ui.account.welcome":"Welcome","ui.account.intro1":"Welcome to the Contao Manager, a universal tool to install and manage Contao Open Source CMS. If you are new to it, please {readTheManualToGetStarted}.","ui.account.introGetStarted":"{readTheManual} to get started","ui.account.introManual":"read the manual","ui.account.intro2":"If you encounter any problems, check {ourGithubIssues} and feel free to create new one for anything that has not been reported yet.","ui.account.introIssues":"our GitHub issues","ui.account.headline":"User Account","ui.account.description":"To manage your installation, please create an account for the Contao Manager. Be aware that this account is not related to the Contao back end or front end.","ui.account.username":"Username","ui.account.password":"Password","ui.account.passwordPlaceholder":"min. 8 characters","ui.account.passwordLength":"Please enter at least 8 characters.","ui.account.loginInvalid":"There was an error when creating the account. Please try a different username.","ui.account.submit":"Create Account","ui.account.usePassword":"Use password for login","ui.account.usePasskey":"Use Passkey for login","ui.account.totpHeadline":"Two-factor authentication","ui.account.totpDescription":"Please enable two-factor authentication, which adds an extra layer of security to your account. In addition to your username and password, you will need to enter a verification code generated by a two-factor app such as 1Password, Authy, Google Authenticator, Microsoft Authenticator, LastPass Authenticator or any other TOTP app.","ui.account.totpSetup":"Configure now","ui.account.totpSkip":"Configure later","ui.account.login":"Decline Invitation","ui.account.contribute1":"Contao and the Contao Manager are sponsored by the non-profit Contao Association.","ui.account.contribute2":"Please consider contributing to open source by {donate}.","ui.account.contributeDonate":"making a donation","ui.login.headline":"Sign In","ui.login.description":"Login to manage your installation.","ui.login.username":"Username","ui.login.password":"Password","ui.login.totpHeadline":"Two-factor authentication","ui.login.totpDescription":"Please enter your verification code to complete the login process.","ui.login.totp":"Verification code","ui.login.forgotPassword":"Forgot your password?","ui.login.button":"Sign In","ui.login.passkey":"Sign In with Passkey","ui.login.cancel":"Cancel","ui.login.or":"or","ui.login.locked":"Access has been denied because the Contao Manager is locked. To unlock, delete the {lockFile} file in your Contao root directory.","ui.logout.headline":"Session Timeout","ui.logout.warning":"Your have been inactive for more than 25 minutes. For security reasons your session will be terminated shortly.","ui.logout.expired":"Your session was automatically terminated because you have been inactive for more than 30 minutes.","ui.logout.renew":"Keep Logged In","ui.logout.logout":"Logout","ui.logout.login":"Back To Login","ui.oauth.error":"Invalid OAuth attempt. Check the request parameters.","ui.oauth.https":"The redirect URI MUST use a secure protocol (https:) to prevent the authentication token from being transmitted in clear-text.","ui.oauth.headline":"Remote Authentication","ui.oauth.description":"The following application or service is requesting remote access to your Contao Manager instance.","ui.oauth.domain":"Before allowing access, make sure you know this URL and trust its owner!","ui.oauth.outOfScope":"Unfortunately, you do not have the necessary permissions to grant this access.","ui.oauth.allow":"Allow Access","ui.oauth.deny":"Deny Access","ui.oauth.switchUser":"Switch User","ui.scope.admin":"Admin access including user management","ui.scope.install":"Install new packages and change Contao configuration","ui.scope.update":"Update packages and execute maintenance tasks","ui.scope.read":"Read packages and configuration","ui.boot.headline":"System Check","ui.boot.description":"Please wait, we are analyzing your server …","ui.boot.issue1":"Installation Issues Detected","ui.boot.issue2":"Your installation has issues that have to be fixed before the Contao Manager can be used.","ui.boot.run":"Launch Contao Manager","ui.boot.safeMode":"Launch in Safe Mode","ui.recovery.headline":"System Recovery","ui.recovery.description":"The Contao Manager detected files that look like Contao, but the Command Line Interface does not work as expected.","ui.recovery.console":"Console Output","ui.recovery.repairOptions":"Please choose an option to repair your installation.","ui.recovery.repairHeadline":"Automatic Repair","ui.recovery.repairDescription":"Attempts to automatically repair the installation by rebuilding the application cache and re-installing the Composer packages.","ui.recovery.repairWarning":"Any modifications to the vendor files might be deleted in the process!","ui.recovery.repairFailed":"Automatic repair was not successful. Try the Safe Mode to manually repair the installation.","ui.recovery.repairButton":"Run System Repair","ui.recovery.safeModeHeadline":"Safe Mode","ui.recovery.safeModeDescription":"Launching the Contao Manager in Safe Mode allows to manage packages and run certain maintenance tasks, but features that rely on a working Contao installation will not be available.","ui.recovery.safeModeButton":"Launch in Safe Mode","ui.server.pending":"Waiting …","ui.server.running":"Analyzing …","ui.server.error":"Check failed due to an unexpected response from the server.","ui.server.details":"Details","ui.server.prerequisite":"Check cancelled due to a missing prerequisite.","ui.server.selfUpdate.title":"Updates of Contao Manager","ui.server.selfUpdate.update":"A new Contao Manager version {latest} is available.","ui.server.selfUpdate.manualUpdate":"A new Contao Manager version {latest} is available. Your server does not support automatic updates, please download the new version from {download}.","ui.server.selfUpdate.latest":"You are using the latest version {current}.","ui.server.selfUpdate.dev":"Development builds do not support automatic updates.","ui.server.selfUpdate.unsupported":"A new version is available but it does not support your PHP version.","ui.server.selfUpdate.button":"Run Self-Update","ui.server.selfUpdate.continue":"Continue","ui.server.config.title":"Server Configuration","ui.server.config.setup":"Configure","ui.server.config.change":"Change","ui.server.config.save":"Save","ui.server.config.cancel":"Cancel","ui.server.config.customOption":"Other …","ui.server.config.description":"To correctly run background tasks, the Contao Manager needs to know where to find the PHP command line binary and how to run commands separated from the web process.","ui.server.config.formTitle":"Server Configuration","ui.server.config.formText":"Please enter the path to your PHP binary. Make sure the binary is the same PHP version as your web process.","ui.server.config.cloudTitle":"Composer Resolver Cloud","ui.server.config.cloudText":"The Composer Resolver Cloud allows to install Composer dependencies even if your server does not provide enough local memory. Please be aware that your package information will be transmitted to a cloud server operated by the Contao Association.","ui.server.config.cloud":"Use the Composer Resolver Cloud","ui.server.config.cli":"PHP Binary","ui.server.config.stateErrorCli":"No valid PHP binary was found on the server.","ui.server.config.stateErrorCloud":"The Composer Resolver Cloud is not supported.","ui.server.config.stateSuccess":"PHP binary at {php_cli}.","ui.server.config.cloudEnabled":"Package dependencies will be resolved using the Composer Resolver Cloud.","ui.server.config.cloudDisabled":"The Composer Resolver Cloud is disabled.","ui.server.php_web.title":"PHP Web Process","ui.server.php_web.below7":"Found PHP version {version}. Please switch to PHP 7 as soon as possible!","ui.server.php_web.success":"Found PHP version {version}, no known issues found.","ui.server.php_cli.title":"PHP Command Line Interface","ui.server.php_cli.success":"Found PHP version {version}, no known issues found.","ui.server.composer.title":"Composer Environment","ui.server.composer.success":"No known issues found.","ui.server.composer.install":"Composer dependencies are not installed.","ui.server.composer.button":"Install","ui.server.contao.title":"Contao Installation","ui.server.contao.setup":"Setup","ui.server.contao.check":"Check database","ui.server.contao.empty":"No Contao installation has been found.","ui.server.contao.old":"Contao version {version} is not compatible with the Contao Manager, please update your installation manually.","ui.server.contao.found":"Found Contao {version} (API version {api}).","ui.server.contao.connectionError":"Unable to connect to the database server.","ui.server.contao.connectionProblem":"Database problem found.","ui.server.contao.missingUser":"Admin account not found.","ui.setup.continue":"Continue","ui.setup.manager":"Launch Contao Manager","ui.setup.cancel":"Cancel","ui.setup.welcome":"Welcome","ui.setup.welcome1":"This wizard will take you through the necessary steps to set up your Contao Open Source CMS installation.","ui.setup.welcome2":"If you have any questions, please find documentation, forums, a Slack channel and more on the {support} page.","ui.setup.support":"community support","ui.setup.start":"Get started","ui.setup.complete":"Congratulations!","ui.setup.complete1":"Contao {version} has been installed successfully.","ui.setup.complete2":"To finish the setup process, please open the install tool to configure the database connection and create a back end user.","ui.setup.complete3":"You can now start to create your website in the Contao back end. If you need additional extensions, continue to the Contao Manager.","ui.setup.installTool":"Open the Install Tool","ui.setup.login":"Login to Contao","ui.setup.funding":"Free software is \\"free\\" as in \\"free speech\\", not as in \\"free beer\\". An Open Source project like Contao requires amounts of money that can\'t be raised by a single person or company.\\nIf you have a website or sell websites built with Contao, we would love to see you contribute back financially to the product your business relies upon.","ui.setup.fundingLink":"Learn more","ui.setup.document-root.headline":"Webserver Setup","ui.setup.document-root.warning":"To install Contao through the Contao Manager, you have to fix the document root on the web server.","ui.setup.document-root.description1":"Contao uses a separate folder for public files, application files are installed in its parent folder. Contao cannot be installed if the folder structure is not correct or the folders are not empty.","ui.setup.document-root.description2":"If you don\'t know how to configure your document root, please read the Contao documentation or contact your hosting provider.","ui.setup.document-root.documentation":"Read the Documentation","ui.setup.document-root.conflictsTitle":"Installation directory not empty","ui.setup.document-root.conflictsDirectory":"The root directory of your future Contao installation is not empty, we have found {count} file(s) that might be overwritten by the installation process. It is recommended to create an empty directory structure for Contao, but you can also remove the following files and check again if you are sure they are unused.","ui.setup.document-root.ignoreConflicts":"I want to install Contao into the non-empty directory. I understand that this might overwrite any existing files on my webspace.","ui.setup.document-root.check":"Check again","ui.setup.document-root.create":"Create directories","ui.setup.document-root.change":"Change directories","ui.setup.document-root.formTitle":"Directory Setup","ui.setup.document-root.formText1":"The Contao Manager can automatically create a new directory structure on the server.","ui.setup.document-root.formText2":"You will need to manually configure the new document root (e.g. through a hosting admin panel).","ui.setup.document-root.autoconfig":"I understand that I have to change my server configuration. Not configuring the document root will break the Contao Manager and expose configuration files (including account details and passwords)!","ui.setup.document-root.directory":"New Directory","ui.setup.document-root.currentRoot":"Current Document Root","ui.setup.document-root.newRoot":"New Document Root","ui.setup.document-root.finish":"Setup Directories","ui.setup.document-root.publicDir":"Use {dir} for public files (for Contao {version})","ui.setup.document-root.directoryInvalid":"Please enter a valid directory name.","ui.setup.document-root.directoryExists":"The target directory already exists. Please enter a different name.","ui.setup.document-root.confirmation":"The Contao Manager has successfully created the necessary directory for your Contao installation. You now have to configure the document root on your web server. Do not reload this page until then.","ui.setup.document-root.reload":"Reload Page","ui.setup.document-root.success":"The directory structure on your web server is set up correctly!","ui.setup.document-root.installingProjectDir":"Application files will be installed to {dir}.","ui.setup.document-root.installingPublicDir":"Public files will be installed to {dir}.","ui.setup.document-root.installedProjectDir":"Application files are installed in {dir}.","ui.setup.document-root.installedPublicDir":"Public files are installed in {dir}.","ui.setup.create-project.headline":"Contao Installation","ui.setup.create-project.description":"Contao development follows the principle of {semver}, a new minor version is released every six months. The currently supported releases are:","ui.setup.create-project.semver":"Semantic Versioning","ui.setup.create-project.latestTitle":"Latest","ui.setup.create-project.ltsTitle":"Long Term Support","ui.setup.create-project.latestQ1":"Our latest version, offers the most features with support until February {year}.","ui.setup.create-project.latestQ3":"Our latest version, offers the most features with support until August {year}.","ui.setup.create-project.ltsText":"Our current LTS version, if you focus on stability. Offers long term support until February {year}.","ui.setup.create-project.pltsText":"The previous LTS version, still has long term support until February {year}.","ui.setup.create-project.requiresPHP":"Requires at least PHP {version}, you have PHP {current}.","ui.setup.create-project.releaseplan":"See the {contaoReleasePlan} for detailed information.","ui.setup.create-project.releaseplanLink":"Contao Release Plan","ui.setup.create-project.installed":"Contao {version} is successfully installed on the server. Continue to set up your database or launch the Contao Manager to install a different version.","ui.setup.create-project.formTitle":"Select a distribution","ui.setup.create-project.formText":"Please choose which version should be installed.","ui.setup.create-project.version":"Version","ui.setup.create-project.demo":"Install the Contao demo website","ui.setup.create-project.demoDescription":"The demo website helps you to get familiar with Contao and all of its core features. More themes can be found in the {store}.","ui.setup.create-project.coreOnly":"Minimal Installation (Core only)","ui.setup.create-project.noUpdate":"Skip Installation (Expert Only!)","ui.setup.create-project.theme":"Contao Theme","ui.setup.create-project.themeInstall":"To install a Contao theme, use the search input or upload a theme file (.cto/.zip) that supports installation through the Contao Manager.","ui.setup.create-project.themeBuy":"Make sure to visit the official {store}.","ui.setup.create-project.themeStore":"Contao Themes Store","ui.setup.create-project.themeUpload":"Upload theme file (.cto/.zip)","ui.setup.create-project.themeInvalid":"The uploaded file is not a Contao theme or does not support the Contao Manager.","ui.setup.create-project.themeWarning":"The Contao Manager cannot tell whether this theme is compatible with your server. Please check with the theme vendor if you have any questions.","ui.setup.create-project.themeTitle":"Review theme details","ui.setup.create-project.themeDetails":"The following dependencies and files will be installed with this theme.","ui.setup.create-project.themeRequire":"{count} Dependencies | {count} Dependencies","ui.setup.create-project.themeFiles":"{count} File | {count} Files","ui.setup.create-project.theme.or":"or search public themes","ui.setup.create-project.theme.search":"Search themes","ui.setup.create-project.theme.more":"More themes","ui.setup.create-project.theme.empty":"No themes matching {query}","ui.setup.create-project.theme.uploaded":"The theme file was uploaded successfully.","ui.setup.create-project.theme.packageName":"Package name","ui.setup.create-project.theme.version":"Version","ui.setup.create-project.theme.authors":"Author(s)","ui.setup.create-project.theme.upload":"Uploading {name} ({size})","ui.setup.create-project.install":"Install","ui.setup.create-project.cancel":"Cancel","ui.setup.create-project.fileError":"Could not find composer.json in {file}.","ui.setup.create-project.jsonError":"composer.json contains invalid JSON.","ui.setup.create-project.schemaError":"composer.json schema validation failed.","ui.setup.database-connection.headline":"Database Connection","ui.setup.database-connection.description":"Contao requires a MySQL database (or a compatible fork like MariaDB) to store pages, content, users and other relational data. Connection parameters are stored in the {env} file in the project root of your Contao installation.","ui.setup.database-connection.formTitle":"Connection Parameters","ui.setup.database-connection.formText":"Enter a database URL or fill in the username, password, server and database fields separately.","ui.setup.database-connection.url":"Database URL","ui.setup.database-connection.validUrl":"Database URL is invalid or connection to server failed.","ui.setup.database-connection.or":"or","ui.setup.database-connection.user":"Username","ui.setup.database-connection.password":"Password","ui.setup.database-connection.server":"Server (:Port)","ui.setup.database-connection.database":"Database Name","ui.setup.database-connection.connected":"Successfully connected to database {database} on {server}.","ui.setup.database-connection.error":"Error connecting to the database.","ui.setup.database-connection.problem":"Contao has detected a problem with your database server.","ui.setup.database-connection.schemaTitle":"Database Schema","ui.setup.database-connection.migration":"There is one pending migration. | There are {count} pending migrations.","ui.setup.database-connection.schema":"There is one pending schema update. | There are {count} pending schema updates.","ui.setup.database-connection.noChanges":"Your database schema is up to date.","ui.setup.database-connection.check":"Check database","ui.setup.database-connection.skip":"Skip","ui.setup.database-connection.save":"Save","ui.setup.database-connection.change":"Change credentials","ui.setup.database-connection.restoreTitle":"Database Import","ui.setup.database-connection.restoreText":"The theme you just installed contains a database backup. Restore the database to import theme data or skip this step to start with a blank Contao installation. | The theme you just installed contains multiple database backups. Select a backup file to import theme data or skip this step to start with a blank Contao installation.","ui.setup.database-connection.backup":"Backup current database before import","ui.setup.database-connection.backupWarning":"All data in database will be overwritten on import! Create a backup first if the database is not empty.","ui.setup.database-connection.restore":"Import theme database","ui.setup.database-connection.restoreOption":"Backup from {date} ({size})","ui.setup.database-connection.restored":"Your theme database was successfully imported. Continue to validate your database schema.","ui.setup.backend-user.success":"An admin account for the Contao back end was found in your database. Use the Contao back end to add more users.","ui.setup.backend-user.error":"Unable to retrieve user list. Check the console output for details.","ui.setup.backend-user.headline":"Backend Account","ui.setup.backend-user.description":"To manage your website, you need to have at least one admin account for the Contao back end. Be aware that this account is not related to the Contao Manager.","ui.setup.backend-user.formTitle":"Create Account","ui.setup.backend-user.formText":"Please enter the details for the new back end account.","ui.setup.backend-user.username":"Username","ui.setup.backend-user.name":"Name","ui.setup.backend-user.email":"E-mail address","ui.setup.backend-user.emailInvalid":"Please enter a valid e-mail address","ui.setup.backend-user.password":"Password","ui.setup.backend-user.passwordPlaceholder":"min. 8 characters","ui.setup.backend-user.passwordLength":"Please enter at least 8 characters.","ui.setup.backend-user.create":"Add account","ui.task.headline":"Background Task","ui.task.loading":"Loading details …","ui.task.created":"Loading details …","ui.task.active":"Please wait while the Contao Manager is running task operations in the background.","ui.task.complete":"All operations are completed successfully. Check the console output for details.","ui.task.paused":"A background operation stopped unexpectedly. Please check the console output.","ui.task.aborting":"Please wait while the background operations are being cancelled.","ui.task.stopped":"Some background operations were cancelled. Please check the console output.","ui.task.error":"A background operation stopped unexpectedly. Please check the console output.","ui.task.failed":"The Contao Manager failed to start a background task!","ui.task.failedDescription1":"Something went wrong while trying to execute operations in the background.","ui.task.failedDescription2":"If this happens again, your server might not be supported.","ui.task.reportProblem":"Report a Problem","ui.task.pausedDescription":"Click \\"Continue\\" if you want to ignore the error and execute the remaining operations.","ui.task.sponsor":"Composer Cloud sponsored by {sponsor}","ui.task.buttonAudit":"Update Database","ui.task.buttonClose":"Close","ui.task.buttonConfirm":"Confirm & Close","ui.task.buttonContinue":"Continue","ui.task.buttonCancel":"Cancel","ui.task.confirmCancel":"Are you sure to cancel this task? This might leave your Contao installation in a broken state!","ui.task.autoclose":"Close task details on success","ui.console.toggle":"Show/Hide Console Output","ui.console.showLog":"Show full console log","ui.console.copyLog":"Copy log to clipboard","ui.migrate.headline":"Database Updates","ui.migrate.migrationsOnly":"(migrations only)","ui.migrate.schemaOnly":"(schema only)","ui.migrate.loading":"Please wait, we are checking your database …","ui.migrate.empty":"No pending migrations or schema updates found. Your database is up to date.","ui.migrate.emptyMigrations":"No pending migrations found. Make sure to also check for schema updates.","ui.migrate.emptySchema":"No pending schema updates found. Make sure to also check for migrations.","ui.migrate.pending":"Your database is not up to date. Please review the console output below and execute the changes.","ui.migrate.previousChanges":"A previous database migration was not confirmed.\\nPlease review the console output below, then continue to see the next changes.","ui.migrate.previousComplete":"A previous database migration was not confirmed, please review the console output below.\\nThere are no more pending changes.","ui.migrate.appliedChanges":"Database updates have been applied.\\nPlease review the console output below, then continue to see the next changes.","ui.migrate.appliedComplete":"Database updates have been applied.\\nThere are no more pending migrations or schema updates. Your database is up to date.","ui.migrate.problem":"Contao has detected a problem with your database server.\\nPlease review the console output below to find out what needs to be fixed. | Contao has detected problems with your database server.\\nPlease review the console output below to find out what needs to be fixed.","ui.migrate.warning":"Contao has detected a misconfiguration of your database server.\\nWarnings can be skipped temporarily, but should be fixed for optimal performance and data integrity.","ui.migrate.error":"The changes could not be applied. Your database might have been changed, please check again to retry.","ui.migrate.execute":"Execute","ui.migrate.close":"Close","ui.migrate.confirm":"Confirm & Close","ui.migrate.cancel":"Cancel","ui.migrate.continue":"Continue","ui.migrate.setup":"Setup","ui.migrate.skip":"Skip","ui.migrate.retry":"Check again","ui.migrate.retryAll":"Check all","ui.migrate.withDeletes":"Execute all database changes including DROP queries.","ui.migrate.migrationTitle":"Database Migrations","ui.migrate.schemaTitle":"Schema Updates","ui.migrate.problemTitle":"Database Problems","ui.migrate.warningTitle":"Database Warnings","ui.migrate.addTable":"Add table {table}","ui.migrate.dropTable":"Drop table {table}","ui.migrate.addField":"Add field {table}.{field}","ui.migrate.changeField":"Change field {table}.{field}","ui.migrate.dropField":"Drop field {table}.{field}","ui.migrate.createIndex":"Create index \\"{name}\\" on {table}","ui.migrate.dropIndex":"Drop index \\"{name}\\" on {table}","ui.widget.mandatory":"This field must not be empty.","ui.widget.blankOption":"Please select …","ui.widget.showPassword":"Show password","ui.widget.hidePassword":"Hide password","ui.error.title":"HTTP request for \\"{method} {url}\\" failed.","ui.error.server500":"Looks like an unexpected error happened on your server. Please check the log files of your web server (Apache/Nginx) and the Contao Manager logs at \\"contao-manager/logs\\".","ui.error.response":"The server returned a response with status code {status}.","ui.error.moreLink":"More Information","ui.error.support":"Contao Support","ui.error.permission":"You do not have permission to use this feature.","ui.footer.help":"Help","ui.footer.reportProblem":"Report a Problem","ui.navigation.discover":"Discover","ui.navigation.packages":"Packages","ui.navigation.tools":"Tools","ui.navigation.installTool":"Install Tool","ui.navigation.backend":"Contao Backend","ui.navigation.debug":"Contao Debug Mode","ui.navigation.logViewer":"Log Viewer","ui.navigation.phpinfo":"PHP Information","ui.navigation.phpinfoLoading":"Loading PHP Information…","ui.navigation.maintenance":"Maintenance","ui.navigation.rebuildCache":"Rebuild Cache","ui.navigation.users":"Accounts","ui.navigation.systemCheck":"System Check","ui.navigation.advanced":"Advanced","ui.navigation.logout":"Logout","ui.maintenance.database.title":"Database Migrations and Backups","ui.maintenance.database.description":"Database migrations ensure consistent data and table schemas.","ui.maintenance.database.migrations":"One pending database migration | {count} pending database migrations","ui.maintenance.database.schemaUpdates":"One pending schema update | {count} pending schema updates","ui.maintenance.database.error":"Database problem found.","ui.maintenance.database.warning":"Database warnings found.","ui.maintenance.database.button":"Check database","ui.maintenance.database.migrationOnly":"Check migrations only","ui.maintenance.database.schemaOnly":"Check schema only","ui.maintenance.database.installTool":"Open Install Tool","ui.maintenance.database.createBackup":"Create Backup","ui.maintenance.database.backupUnsupported":"Database backups are not supported by your Contao version.","ui.maintenance.database.backupList":"You have one database backup, created on {date}. | You have {count} database backups, the latest one was created on {date}.","ui.maintenance.database.backupEmpty":"You currently have no database backups.","ui.maintenance.rebuildCache.title":"Application Cache","ui.maintenance.rebuildCache.description":"Rebuilding the application cache is required after modifying any of the configuration files.","ui.maintenance.rebuildCache.rebuildProd":"Rebuild Production Cache","ui.maintenance.rebuildCache.rebuildDev":"Rebuild Development Cache","ui.maintenance.rebuildCache.clearProd":"Clear Production Cache","ui.maintenance.rebuildCache.clearDev":"Clear Development Cache","ui.maintenance.installTool.title":"Contao Install Tool","ui.maintenance.installTool.description":"The Contao Install Tool is automatically locked if you enter a wrong password three times in a row.","ui.maintenance.installTool.unlock":"Unlock Install Tool","ui.maintenance.installTool.lock":"Lock Install Tool","ui.maintenance.dumpAutoload.title":"Composer Class Loader","ui.maintenance.dumpAutoload.description":"The Composer autoloader is responsible for PHP class loading. The autoloader must be dumped after adding custom namespaces to the root composer.json.","ui.maintenance.dumpAutoload.button":"Dump Autoloader","ui.maintenance.composerInstall.title":"Composer Dependencies","ui.maintenance.composerInstall.description":"Composer dependencies are located in the {vendor} folder in your application root. Reinstalling the dependencies can be necessary after manipulation or manually uploading the {composerLock} file.","ui.maintenance.composerInstall.button":"Run Installer","ui.maintenance.composerInstall.update":"Run Composer Update","ui.maintenance.composerCache.title":"Composer Cache","ui.maintenance.composerCache.description":"Composer caches downloaded packages for improved performance. If you have issues like broken files, try to delete the Composer cache to force a new download.","ui.maintenance.composerCache.button":"Clear Cache","ui.maintenance.maintenanceMode.title":"Maintenance Mode","ui.maintenance.maintenanceMode.description":"Putting Contao in maintenance mode will display a \\"503 Service Unavailable\\" template for the website.","ui.maintenance.maintenanceMode.enable":"Enable","ui.maintenance.maintenanceMode.disable":"Disable","ui.maintenance.debugMode.title":"Debug Mode","ui.maintenance.debugMode.description":"Activate the debug mode by setting a user and password for the {appDevPhp} entry point.","ui.maintenance.debugMode.descriptionJwt":"Activate the debug mode by setting the debug cookie for the current domain.","ui.maintenance.debugMode.activate":"Activate","ui.maintenance.debugMode.deactivate":"Deactivate","ui.maintenance.debugMode.credentials":"Credentials","ui.maintenance.debugMode.user":"Please enter a username for the debug mode.","ui.maintenance.debugMode.password":"Please enter a password for the debug mode.","ui.maintenance.opcodeCache.title":"Opcode Cache","ui.maintenance.opcodeCache.description":"Opcode caches PHP files on the web process for faster execution. It must be deleted under certain circumstances if files are not recognized after changing.","ui.maintenance.opcodeCache.button":"Truncate Cache","ui.maintenance.safeMode":"Not available in Safe Mode","ui.maintenance.unsupported":"Not supported by your Contao version","ui.packages.updateButton":"Update Packages","ui.packages.searchButton":"Search Packages","ui.packages.searchPlaceholder":"Search Packages …","ui.packages.uploadOverlay":"Drag & drop files to upload","ui.packages.uploadButton":"Upload Packages","ui.packages.uploadMessage":"You have one unconfirmed upload. | You have {count} unconfirmed uploads.","ui.packages.uploadApply":"Confirm Uploads","ui.packages.uploadReset":"Delete Uploads","ui.packages.uploadIncomplete":"This file was not uploaded completely. Please remove it and try again.","ui.packages.uploadDuplicate":"This file seems to be uploaded multiple times. Please remove the duplicates.","ui.packages.uploadInstalled":"This file is already installed. Please remove the duplicates.","ui.packages.uploadUnsupported":"Uploads are not supported in your installation. Please make sure that the PHP ZIP extension is installed and update your dependencies.","ui.packages.changesMessage":"You have one unconfirmed change. | You have {count} unconfirmed changes.","ui.packages.changesDryrun":"Dry Run","ui.packages.changesApply":"Apply Changes","ui.packages.changesApplyAll":"Update all packages","ui.packages.changesDryrunAll":"Dry run all packages","ui.packages.changesReset":"Reset Changes","ui.packages.changesReview":"Review Changes","ui.packagelist.loading":"Loading …","ui.packagelist.uploads":"Uploads","ui.packagelist.added":"New packages","ui.packagelist.installed":"Installed packages","ui.package.hintRevert":"Revert Changes","ui.package.hintNoupdate":"Do not update","ui.package.hintConstraint":"This package will be installed with constraint {constraint} when you apply the changes.","ui.package.hintConstraintBest":"This package will be installed in the best available version when you apply the changes.","ui.package.hintConstraintChange":"The constraint for this package will be changed from \\"{from}\\" to \\"{to}\\" when you apply the changes.","ui.package.hintConstraintUpdate":"This package will be updated when you apply the changes.","ui.package.hintAdded":"This package will be installed when you apply the changes.","ui.package.hintRemoved":"This package will be removed when you apply the changes.","ui.package.requiredTitle":"manually added","ui.package.requiredText":"This package is required in your composer.json but not installed.","ui.package.removedTitle":"manually removed","ui.package.removedText":"This package was removed from your composer.json.","ui.package.installed":"Currently installed:","ui.package.version":"Version {version}","ui.package.additionalDownloads":"{count} Download | {count} Downloads","ui.package.additionalStars":"{count} Star | {count} Stars","ui.package.editConstraint":"Edit","ui.package.uploadConstraint":"This constraint is defined by the uploaded package.","ui.package.updateButton":"Update","ui.package.removeButton":"Remove","ui.package.installButton":"Add Package","ui.package.installButtonShort":"Add","ui.package.detailsButton":"Details","ui.package.latestConstraint":"latest version","ui.package.update":"Update available","ui.package.updateLatest":"latest version","ui.package.updateAvailable":"{version} available","ui.package.updateUnknown":"unknown version","ui.package.updateConstraint":"A newer version outside your version constraint is available.","ui.package.incompatible":"{package} does not work with Contao {constraint}.","ui.package.incompatibleWarning":"{package} does not work with Contao {constraint} in any of its stable releases. Do you want to add the package and set a version constraint to try installing a development branch?","ui.package.incompatibleConstraint":"This package does not have a stable release for Contao {constraint}. Set a version constraint to try installing a development branch.","ui.package.incompatibleButton":"Install","ui.cloudStatus.headline":"Composer Resolver Cloud","ui.cloudStatus.version":"Version {version}","ui.cloudStatus.waitingTime":"Waiting Time","ui.cloudStatus.jobs":"Current Jobs","ui.cloudStatus.workers":"Workers","ui.cloudStatus.approx":"{minutes} min","ui.cloudStatus.none":"none","ui.cloudStatus.short":"ca. {minutes} min","ui.cloudStatus.long":"ca. {minutes} min {seconds} sec","ui.cloudStatus.error":"Unable to fetch the status of the Composer Resolver Cloud. It might be down for maintenance or experience issues.","ui.cloudStatus.button":"Cloud Status","ui.cloudStatus.refresh":"Refresh Cloud Status","ui.log-viewer.loading":"Loading …","ui.log-viewer.empty":"There are no log files on your server.","ui.log-viewer.reload":"Reload","ui.log-viewer.file":"Log file","ui.log-viewer.channel":"Channel","ui.log-viewer.channelTitle":"The channel this message was logged to.","ui.log-viewer.level":"Level","ui.log-viewer.levelTitle":"Severity of the log message.","ui.log-viewer.timeHeader":"Time","ui.log-viewer.messageHeader":"Message","ui.log-viewer.showContext":"Show Context","ui.log-viewer.hideContext":"Hide Context","ui.log-viewer.showExtra":"Show Extra","ui.log-viewer.hideExtra":"Hide Extra","ui.log-viewer.more":"Load more …","ui.log-viewer.download":"Download","ui.log-viewer.downloadTitle":"Download file \\"{file}\\"","ui.log-viewer.prodEnvironment":"Production Environment","ui.log-viewer.devEnvironment":"Development Environment (Debug Mode)","ui.user-manager.loading":"Loading users …","ui.user-manager.changePassword":"Change Password","ui.user-manager.setupTotp":"Setup Two-Factor Authentication","ui.user-manager.disableTotp":"Disable Two-Factor Authentication","ui.user-manager.invite":"Invite User","ui.user-manager.delete":"Delete","ui.user-manager.deleteConfirm":"Do you really want to delete user \\"{username}\\"?","ui.user-manager.deleted":"User {username} deleted successfully","ui.user-manager.passwordHeadline":"Change Password","ui.user-manager.passwordText":"To change your password, please enter the current and a new password in the respective fields.","ui.user-manager.currentPassword":"Current password","ui.user-manager.newPassword":"New password","ui.user-manager.passwordPlaceholder":"min. 8 characters","ui.user-manager.submitPassword":"Submit","ui.user-manager.passwordChanged":"Your password has been changed successfully.","ui.user-manager.passwordError":"This password is incorrect.","ui.user-manager.inviteHeadline":"Invite User","ui.user-manager.inviteText":"If you need multiple logins for the Contao Manager, you can create an invitation link here. Share this link with someone or use it on another device to create a new account with the given permissions.","ui.user-manager.inviteSuccess1":"A new invitation link was created. The URL below can be used to create a new user account for this Contao Manager. The invitation expires on {expires} (one week from now).","ui.user-manager.inviteSuccess2":"Please copy the link to your clipboard. It will only work once and you will not be able to see it again after closing this dialog.","ui.user-manager.createInvitation":"Create Invitation Link","ui.user-manager.clipboard":"Copy to clipboard","ui.user-manager.permissions":"Learn about permissions","ui.user-manager.cancel":"Cancel","ui.user-manager.close":"Close","ui.user-manager.you":"You","ui.user-manager.2fa":"2FA","ui.user-manager.2faEnabled":"This account is secured by two-factor authentication.","ui.user-manager.2faDisabled":"This account is insecure due to missing two-factor authentication.","ui.user-manager.passkey":"Passkey","ui.user-manager.passkeyTitle":"This account is secured by a Passkey.","ui.totp.headline":"Two-Factor Authentication","ui.totp.setupQr":"Please scan the QR code with your 2FA/TOTP app.","ui.totp.setupCode":"If you cannot scan the QR code, enter this key instead:","ui.totp.codeLabel":"Verification code","ui.totp.codeDescription":"Please enter the verification code generated by your 2FA/TOTP app.","ui.totp.disableText":"Please enter the verification code to disable two-factor authentication.","ui.totp.invalid":"The verification code is invalid.","ui.totp.enable":"Enable","ui.totp.disable":"Disable","ui.totp.cancel":"Cancel","ui.totp.enabled":"Two-factor authentication was enabled successfully.","ui.totp.disabled":"Two-factor authentication was disabled successfully.","ui.totp.setup":"Setup Two-Factor Authentication","ui.totp.skip":"Skip Two-Factor Authentication"}')}}]);"use strict";(self["webpackChunkcontao_manager"]=self["webpackChunkcontao_manager"]||[]).push([[643],{6643:function(e){e.exports=JSON.parse('{"ui.app.httpsHeadline":"!! Osäker anslutning !!","ui.app.httpsDescription":"Utan HTTPS kommer din konfidentiella data att överföras okrypterad.","ui.app.httpsLink":"Mer information","ui.app.httpsHref":"https://https.cio.gov/everything/","ui.app.safeModeHeadline":"!! Säkert läge aktiverat !!","ui.app.safeModeDescription":"Vissa funktioner i Contao Manager är inte tillgängliga.","ui.app.safeModeExit":"Avsluta felsäkert läge","ui.app.limitedHeadline":"Fjärrautentisering","ui.app.limitedDescription":"Du har begränsade behörigheter på grund av lösenordslös inloggning.","ui.app.limitedLogout":"Autentisera på nytt","ui.app.totpHeadline":"Säkerhetsmeddelande","ui.app.totpDescription":"Konfigurera tvåfaktorsautentisering nu för att säkra ditt konto.","ui.app.totpSetup":"Setup","ui.app.loading":"Laddar Contao Manager …","ui.app.apiError":"Oväntad API-status","ui.app.configSecurity1":"SÄKERHETSVARNING !!! Oskyddad konfigurationskatalog upptäcktes","ui.app.configSecurity2":"Contao Manager har upptäckt att dess konfigurationsfiler är offentligt tillgängliga. Alla operationer är inaktiverade tills katalogen är säker, annars kan en angripare komma åt känsliga data från din installation.\\n\\nFör att åtgärda det här problemet, se till att förhindra åtkomst till \\"contao-manager\\"-katalogen på din server. För att lära dig hur du gör detta, se manualen för din webbserver eller kontakta din värdleverantör.","ui.account.welcome":"Välkommen","ui.account.intro1":"Välkommen till Contao Manager, ett universellt verktyg för att installera och hantera Contao Open Source CMS. Om du är ny på det, vänligen {readTheManualToGetStarted}.","ui.account.introGetStarted":"{readTheManual} för att komma igång","ui.account.introManual":"läs manualen","ui.account.intro2":"Om du stöter på några problem, kolla {ourGithubIssues} och skapa gärna ett nytt för allt som inte har rapporterats ännu.","ui.account.introIssues":"våra GitHub-problem","ui.account.headline":"Användarkonto","ui.account.description":"För att hantera din installation, skapa ett konto för Contao Manager. Var medveten om att det här kontot inte är relaterat till Contao backend eller frontend.","ui.account.username":"Användarnamn","ui.account.password":"Lösenord","ui.account.passwordPlaceholder":"min. 8 tecken","ui.account.passwordLength":"Ange minst 8 tecken.","ui.account.loginInvalid":"Det uppstod ett fel när du skapade kontot. Vänligen försök med ett annat användarnamn.","ui.account.submit":"Skapa konto","ui.account.usePassword":"Använd lösenord för inloggning","ui.account.usePasskey":"Använd Passkey för inloggning","ui.account.totpHeadline":"Tvåfaktorsautentisering","ui.account.totpDescription":"Vänligen aktivera tvåfaktorsautentisering, vilket ger ditt konto ett extra säkerhetslager. Förutom ditt användarnamn och lösenord måste du ange en verifieringskod som genereras av en tvåfaktorsapp som 1Password, Authy, Google Authenticator, Microsoft Authenticator, LastPass Authenticator eller någon annan TOTP-app.","ui.account.totpSetup":"Konfigurera nu","ui.account.totpSkip":"Konfigureras senare","ui.account.login":"Avvisa inbjudan","ui.account.contribute1":"Contao och Contao Manager är sponsrade av den ideella Contao Association.","ui.account.contribute2":"Vänligen överväg att bidra till öppen källkod genom att {donate}.","ui.account.contributeDonate":"göra en donation","ui.login.headline":"Logga in","ui.login.description":"Logga in för att hantera din installation.","ui.login.username":"Användarnamn","ui.login.password":"Lösenord","ui.login.totpHeadline":"Tvåfaktorsautentisering","ui.login.totpDescription":"Ange din verifieringskod för att slutföra inloggningsprocessen.","ui.login.totp":"Verifieringskod","ui.login.forgotPassword":"Glömt ditt lösenord?","ui.login.button":"Logga in","ui.login.passkey":"Logga in med Passkey","ui.login.cancel":"Avbryt","ui.login.or":"eller","ui.login.locked":"Åtkomst har nekats eftersom Contao Manager är låst. För att låsa upp, radera {lockFile}-filen i din Contao-rotkatalog.","ui.logout.headline":"Sessionen har gått ut","ui.logout.warning":"Du har varit inaktiv i mer än 25 minuter. Av säkerhetsskäl kommer din session att avslutas inom kort.","ui.logout.expired":"Din session avslutades automatiskt eftersom du har varit inaktiv i mer än 30 minuter.","ui.logout.renew":"Håll inloggad","ui.logout.logout":"Logga ut","ui.logout.login":"Tillbaka till login","ui.oauth.error":"Ogiltigt OAuth-försök. Kontrollera request-parametrarna.","ui.oauth.https":"Omdirigerings-URI:n MÅSTE använda ett säkert protokoll (https:) för att förhindra att autentiseringstoken sänds i klartext.","ui.oauth.headline":"Fjärrautentisering","ui.oauth.description":"Följande applikation eller tjänst begär fjärråtkomst till din Contao Manager-instans.","ui.oauth.domain":"Innan du tillåter åtkomst, se till att du känner till den här webbadressen och litar på dess ägare!","ui.oauth.outOfScope":"Tyvärr har du inte de nödvändiga behörigheterna för att bevilja denna åtkomst.","ui.oauth.allow":"Tillåta åtkomst","ui.oauth.deny":"Neka åtkomst","ui.oauth.switchUser":"Växla användare","ui.scope.admin":"Admin-åtkomst inklusive användarhantering","ui.scope.install":"Installera nya paket och ändra Contao-konfigurationen","ui.scope.update":"Uppdatera paket och utföra underhållsåtgärder","ui.scope.read":"Läs paket och konfiguration","ui.boot.headline":"Systemkontroll","ui.boot.description":"Vänta, vi analyserar din server...","ui.boot.issue1":"Installationsproblem upptäcktes","ui.boot.issue2":"Din installation har problem som måste åtgärdas innan Contao Manager kan användas.","ui.boot.run":"Starta Contao Manager","ui.boot.safeMode":"Starta i felsäkert läge Safe Mode","ui.recovery.headline":"Systemåterställning","ui.recovery.description":"Contao Manager upptäckte filer som ser ut som Contao, men kommandoradsgränssnittet fungerar inte som förväntat.","ui.recovery.console":"Konsolutgång","ui.recovery.repairOptions":"Välj ett alternativ för att reparera din installation.","ui.recovery.repairHeadline":"Automatisk reparation","ui.recovery.repairDescription":"Försöker att automatiskt reparera installationen genom att bygga om programcachen och installera om Composer-paketen.","ui.recovery.repairWarning":"Eventuella ändringar av vendor-filerna kan raderas under processen!","ui.recovery.repairFailed":"Den automatiska reparationen lyckades inte. Prova felsäkert läge Safe Mode för att manuellt reparera installationen.","ui.recovery.repairButton":"Kör systemreparation","ui.recovery.safeModeHeadline":"Säkert läge Safe Mode","ui.recovery.safeModeDescription":"Att starta Contao Manager i felsäkert läge gör det möjligt att hantera paket och köra vissa underhållsuppgifter, men funktioner som förlitar sig på en fungerande Contao-installation kommer inte att vara tillgängliga.","ui.recovery.safeModeButton":"Starta i felsäkert läge Safe Mode","ui.server.pending":"Väntar …","ui.server.running":"Analyserar …","ui.server.error":"Kontrollen misslyckades på grund av ett oväntat svar från servern.","ui.server.details":"Detaljer","ui.server.prerequisite":"Checken annullerad på grund av att förutsättning saknas.","ui.server.selfUpdate.title":"Uppdateringar av Contao Manager","ui.server.selfUpdate.update":"En ny version av Contao Manager {latest} är tillgänglig.","ui.server.selfUpdate.manualUpdate":"En ny version av Contao Manager {latest} är tillgänglig. Din server stöder inte automatiska uppdateringar, ladda ner den nya versionen från {download}.","ui.server.selfUpdate.latest":"Du använder den senaste versionen {current}.","ui.server.selfUpdate.dev":"Utvecklingsbyggen stöder inte automatiska uppdateringar.","ui.server.selfUpdate.unsupported":"En ny version är tillgänglig men den stöder inte din PHP-version.","ui.server.selfUpdate.button":"Kör självuppdatering","ui.server.selfUpdate.continue":"Fortsätta","ui.server.config.title":"Serverkonfiguration","ui.server.config.setup":"Konfigurera","ui.server.config.change":"Förändra","ui.server.config.save":"Spara","ui.server.config.cancel":"Avbryt","ui.server.config.customOption":"Övrig …","ui.server.config.description":"För att köra bakgrundsuppgifter korrekt måste Contao Manager veta var man hittar PHP-kommandoradens binära filer och hur man kör kommandon separerade från webbprocessen.","ui.server.config.formTitle":"Serverkonfiguration","ui.server.config.formText":"Ange sökvägen till din PHP-binär. Se till att binären är samma PHP-version som din webbprocess.","ui.server.config.cloudTitle":"Composer Resolver Cloud","ui.server.config.cloudText":"Composer Resolver Cloud gör det möjligt att installera Composer-beroenden även om din server inte tillhandahåller tillräckligt med lokalt minne. Var medveten om att din paketinformation kommer att överföras till en molnserver som drivs av Contao Association.","ui.server.config.cloud":"Använd Composer Resolver Cloud","ui.server.config.cli":"PHP binär","ui.server.config.stateErrorCli":"Ingen giltig PHP-binär hittades på servern.","ui.server.config.stateErrorCloud":"Composer Resolver Cloud stöds inte.","ui.server.config.stateSuccess":"PHP binär på {php_cli}.","ui.server.config.cloudEnabled":"Paketberoenden kommer att lösas med hjälp av Composer Resolver Cloud.","ui.server.config.cloudDisabled":"Composer Resolver Cloud är inaktiverat.","ui.server.php_web.title":"PHP webbprocess","ui.server.php_web.below7":"Hittade PHP-versionen {version}. Byt till PHP 7 så snart som möjligt!","ui.server.php_web.success":"Hittade PHP-versionen {version}, inga kända problem hittades.","ui.server.php_cli.title":"PHP kommandoradsgränssnitt","ui.server.php_cli.success":"Hittade PHP-versionen {version}, inga kända problem hittades.","ui.server.composer.title":"Composer-Miljö","ui.server.composer.success":"Inga kända problem hittades.","ui.server.composer.install":"Composer-beroenden är inte installerade.","ui.server.composer.button":"Installera","ui.server.contao.title":"Contao installation","ui.server.contao.setup":"Setup","ui.server.contao.check":"Kontrollera databasen","ui.server.contao.empty":"Ingen Contao-installation har hittats.","ui.server.contao.old":"Contao version {version} är inte kompatibel med Contao Manager, uppdatera din installation manuellt.","ui.server.contao.found":"Hittade Contao {version} (API-version {api}).","ui.server.contao.connectionError":"Det går inte att ansluta till databasservern.","ui.server.contao.connectionProblem":"Databasproblem hittades.","ui.server.contao.missingUser":"Administratörskonto hittades inte.","ui.setup.continue":"Fortsätta","ui.setup.manager":"Starta Contao Manager","ui.setup.cancel":"Avbryt","ui.setup.welcome":"Välkommen","ui.setup.welcome1":"Den här guiden tar dig igenom de nödvändiga stegen för att konfigurera din Contao Open Source CMS-installation.","ui.setup.welcome2":"Om du har några frågor kan du hitta dokumentation, forum, en Slack-kanal och mer på sidan {support}.","ui.setup.support":"community support","ui.setup.start":"Komma igång","ui.setup.complete":"Grattis!","ui.setup.complete1":"Contao {version} har installerats.","ui.setup.complete2":"För att avsluta installationsprocessen, öppna installationsverktyget för att konfigurera databasanslutningen och skapa en backend-användare.","ui.setup.complete3":"Du kan nu börja skapa din webbplats i Contaos back end. Om du behöver ytterligare tillägg, fortsätt till Contao Manager.","ui.setup.installTool":"Öppna installationsverktyget","ui.setup.login":"Logga in på Contao","ui.setup.funding":"Fri programvara är \\"fri\\" som i \\"yttrandefritt\\", inte som i \\"gratis öl\\". Ett Open Source-projekt som Contao kräver summor pengar som inte kan samlas in av en enda person eller företag.\\nOm du har en webbplats eller säljer webbplatser byggda med Contao, skulle vi gärna se att du bidrar ekonomiskt till den produkt som ditt företag är beroende av.","ui.setup.fundingLink":"Läs mer","ui.setup.document-root.headline":"Webserverinstallation","ui.setup.document-root.warning":"För att installera Contao via Contao Manager måste du fixa dokumentroten på webbservern.","ui.setup.document-root.description1":"Contao använder en separat mapp för offentliga filer, programfiler installeras i dess överordnade mapp. Contao kan inte installeras om mappstrukturen inte är korrekt eller om mapparna inte är tomma.","ui.setup.document-root.description2":"Om du inte vet hur du konfigurerar din dokumentrot, läs Contao-dokumentationen eller kontakta din värdleverantör.","ui.setup.document-root.documentation":"Läs dokumentationen","ui.setup.document-root.conflictsTitle":"Installationskatalogen är inte tom","ui.setup.document-root.conflictsDirectory":"Rotkatalogen för din framtida Contao-installation är inte tom, vi har hittat {count} fil(er) som kan skrivas över av installationsprocessen. Det rekommenderas att skapa en tom katalogstruktur för Contao, men du kan också ta bort följande filer och kontrollera igen om du är säker på att de är oanvända.","ui.setup.document-root.ignoreConflicts":"Jag vill installera Contao i den icke-tomma katalogen. Jag förstår att detta kan skriva över alla befintliga filer på mitt webbutrymme.","ui.setup.document-root.check":"Kolla igen","ui.setup.document-root.create":"Skapa kataloger","ui.setup.document-root.change":"Byt kataloger","ui.setup.document-root.formTitle":"Kataloginställningar","ui.setup.document-root.formText1":"Contao Manager kan automatiskt skapa en ny katalogstruktur på servern.","ui.setup.document-root.formText2":"Du måste konfigurera den nya dokumentroten manuellt (t.ex. via en värdadministratörspanel).","ui.setup.document-root.autoconfig":"Jag förstår att jag måste ändra min serverkonfiguration. Att inte konfigurera dokumentroten kommer att bryta Contao Manager och exponera konfigurationsfiler (inklusive kontodetaljer och lösenord)!","ui.setup.document-root.directory":"Ny katalog","ui.setup.document-root.currentRoot":"Aktuell dokumentrot","ui.setup.document-root.newRoot":"Ny dokumentrot","ui.setup.document-root.finish":"Installera kataloger","ui.setup.document-root.publicDir":"Använd {dir} för offentliga filer (för Contao {version})","ui.setup.document-root.directoryInvalid":"Vänligen ange ett giltigt katalognamn.","ui.setup.document-root.directoryExists":"Vänligen ange ett giltigt katalognamn.","ui.setup.document-root.confirmation":"Contao Manager har skapat den nödvändiga katalogen för din Contao-installation. Du måste nu konfigurera dokumentroten på din webbserver. Ladda inte om den här sidan förrän då.","ui.setup.document-root.reload":"Ladda om sidan","ui.setup.document-root.success":"Katalogstrukturen på din webbserver är korrekt inställd!","ui.setup.document-root.installingProjectDir":"Programfiler kommer att installeras i {dir}.","ui.setup.document-root.installingPublicDir":"Offentliga filer kommer att installeras i {dir}.","ui.setup.document-root.installedProjectDir":"Programfiler installeras i {dir}.","ui.setup.document-root.installedPublicDir":"Offentliga filer installeras i {dir}.","ui.setup.create-project.headline":"Contao installation","ui.setup.create-project.description":"Contao-utvecklingen följer principen för {semver}, en ny minor version släpps var sjätte månad. De utgåvor som för närvarande stöds är:","ui.setup.create-project.semver":"Semantisk versionering","ui.setup.create-project.latestTitle":"Senast","ui.setup.create-project.ltsTitle":"Långtidssupport","ui.setup.create-project.latestQ1":"Vår senaste version erbjuder de flesta funktionerna med support fram till februari {year}.","ui.setup.create-project.latestQ3":"Vår senaste version erbjuder de flesta funktionerna med support fram till augusti {year}.","ui.setup.create-project.ltsText":"Vår nuvarande LTS-version, om du fokuserar på stabilitet. Erbjuder långsiktig support till februari {year}.","ui.setup.create-project.pltsText":"Den tidigare LTS-versionen har fortfarande långtidssupport fram till februari {year}.","ui.setup.create-project.requiresPHP":"Kräver minst PHP {version}, du har PHP {current}.","ui.setup.create-project.releaseplan":"Se {contaoReleasePlan} för detaljerad information.","ui.setup.create-project.releaseplanLink":"Contao Release Plan","ui.setup.create-project.installed":"Contao {version} har installerats på servern. Fortsätt att ställa in din databas eller starta Contao Manager för att installera en annan version.","ui.setup.create-project.formTitle":"Välj en distribution","ui.setup.create-project.formText":"Välj vilken version som ska installeras.","ui.setup.create-project.version":"Version","ui.setup.create-project.demo":"Installera Contaos demowebbplats","ui.setup.create-project.demoDescription":"Demowebbplatsen hjälper dig att bli bekant med Contao och alla dess kärnfunktioner. Fler teman finns i {butiken}.","ui.setup.create-project.coreOnly":"Minimal installation (endast kärna core)","ui.setup.create-project.noUpdate":"Hoppa över installationen (endast experter!)","ui.setup.create-project.theme":"Contao Theme","ui.setup.create-project.themeInstall":"För att installera ett Contao-tema, använd sökingången eller ladda upp en temafil (.cto/.zip) som stöder installation via Contao Manager.","ui.setup.create-project.themeBuy":"Se till att besöka den officiella {butiken}.","ui.setup.create-project.themeStore":"Contao Themes Store","ui.setup.create-project.themeUpload":"Ladda upp temafil (.cto/.zip)","ui.setup.create-project.themeInvalid":"Den uppladdade filen är inte ett Contao-tema eller stöder inte Contao Manager.","ui.setup.create-project.themeWarning":"Contao Manager kan inte avgöra om detta tema är kompatibelt med din server. Kontrollera med temaleverantören om du har några frågor.","ui.setup.create-project.themeTitle":"Granska temadetaljer","ui.setup.create-project.themeDetails":"Följande beroenden och filer kommer att installeras med detta tema.","ui.setup.create-project.themeRequire":"{count} beroenden | {count} beroenden","ui.setup.create-project.themeFiles":"{count} Fil | {count} filer","ui.setup.create-project.theme.or":"eller sök efter offentliga teman","ui.setup.create-project.theme.search":"Sök teman","ui.setup.create-project.theme.more":"Fler teman","ui.setup.create-project.theme.empty":"Inga teman matchar {query}","ui.setup.create-project.theme.uploaded":"Temafilen laddades upp.","ui.setup.create-project.theme.packageName":"Paketnamn","ui.setup.create-project.theme.version":"Version","ui.setup.create-project.theme.authors":"Författare","ui.setup.create-project.theme.upload":"Laddar upp {namn} ({storlek})","ui.setup.create-project.install":"Installera","ui.setup.create-project.cancel":"Avbryt","ui.setup.create-project.fileError":"Kunde inte hitta composer.json i {fil}.","ui.setup.create-project.jsonError":"composer.json innehåller ogiltig JSON.","ui.setup.create-project.schemaError":"validering av composer.json-schema misslyckades.","ui.setup.database-connection.headline":"Databasanslutning","ui.setup.database-connection.description":"Contao kräver en MySQL-databas (eller en kompatibel databas som MariaDB) för att lagra sidor, innehåll, användare och annan relationsdata. Anslutningsparametrar lagras i filen {env} i projektroten för din Contao-installation.","ui.setup.database-connection.formTitle":"Anslutningsparametrar","ui.setup.database-connection.formText":"Ange en databas-URL eller fyll i användarnamn, lösenord, server och databasfält separat.","ui.setup.database-connection.url":"Databas URL","ui.setup.database-connection.validUrl":"Databas-URL är ogiltig eller anslutningen till servern misslyckades.","ui.setup.database-connection.or":"eller","ui.setup.database-connection.user":"Användarnamn","ui.setup.database-connection.password":"Lösenord","ui.setup.database-connection.server":"Server (:Port)","ui.setup.database-connection.database":"Databas namn","ui.setup.database-connection.connected":"Ansluten till databasen {database} på {server}.","ui.setup.database-connection.error":"Fel vid anslutning till databasen.","ui.setup.database-connection.problem":"Contao har upptäckt ett problem med din databasserver.","ui.setup.database-connection.schemaTitle":"Databasschema","ui.setup.database-connection.migration":"Det finns en väntande migrering. | Det finns {count} väntande migreringar.","ui.setup.database-connection.schema":"Det finns en väntande schemauppdatering. | Det finns {count} väntande schemauppdateringar.","ui.setup.database-connection.noChanges":"Ditt databasschema är uppdaterat.","ui.setup.database-connection.check":"Kontrollera databasen","ui.setup.database-connection.skip":"Hoppa över","ui.setup.database-connection.save":"Spara","ui.setup.database-connection.change":"Ändra autentiseringsuppgifter","ui.setup.database-connection.restoreTitle":"Databasimport","ui.setup.database-connection.restoreText":"Temat du just installerade innehåller en databassäkerhetskopiering. Återställ databasen för att importera temadata eller hoppa över detta steg för att börja med en tom Contao-installation. | Temat du just installerade innehåller flera säkerhetskopior av databaser. Välj en säkerhetskopia för att importera temadata eller hoppa över det här steget för att börja med en tom Contao-installation.","ui.setup.database-connection.backup":"Säkerhetskopiera aktuell databas före import","ui.setup.database-connection.backupWarning":"All data i databasen kommer att skrivas över vid import! Skapa en säkerhetskopia först om databasen inte är tom.","ui.setup.database-connection.restore":"Importera temadatabas","ui.setup.database-connection.restoreOption":"Säkerhetskopiering från {date} ({size})","ui.setup.database-connection.restored":"Din temadatabas har importerats. Fortsätt att validera ditt databasschema.","ui.setup.backend-user.success":"Ett administratörskonto för Contao backend hittades i din databas. Använd Contaos backend för att lägga till fler användare.","ui.setup.backend-user.error":"Det gick inte att hämta användarlistan. Kontrollera konsolutgången för detaljer.","ui.setup.backend-user.headline":"Backend-konto","ui.setup.backend-user.description":"För att hantera din webbplats måste du ha minst ett administratörskonto för Contaos backend. Var medveten om att detta konto inte är relaterat till Contao Manager.","ui.setup.backend-user.formTitle":"Skapa konto","ui.setup.backend-user.formText":"Vänligen ange detaljerna för det nya backend-kontot.","ui.setup.backend-user.username":"Användarnamn","ui.setup.backend-user.name":"namn","ui.setup.backend-user.email":"E-postadress","ui.setup.backend-user.emailInvalid":"Vänligen ange en giltig e-postadress","ui.setup.backend-user.password":"Lösenord","ui.setup.backend-user.passwordPlaceholder":"min. 8 tecken","ui.setup.backend-user.passwordLength":"Ange minst 8 tecken.","ui.setup.backend-user.create":"Lägg till konto","ui.task.headline":"Bakgrundsuppgift","ui.task.loading":"Läser in detaljer...","ui.task.created":"Läser in detaljer...","ui.task.active":"Vänta medan Contao Manager kör uppgiftsoperationer i bakgrunden.","ui.task.complete":"Alla operationer har slutförts framgångsrikt. Kontrollera konsolutgången för detaljer.","ui.task.paused":"En bakgrundsåtgärd avbröts oväntat. Kontrollera konsolutgången.","ui.task.aborting":"Vänta medan bakgrundsåtgärderna avbryts.","ui.task.stopped":"Vissa bakgrundsoperationer avbröts. Kontrollera konsolutgången.","ui.task.error":"En bakgrundsåtgärd avbröts oväntat. Kontrollera konsolutgången.","ui.task.failed":"Contao Manager kunde inte starta en bakgrundsuppgift!","ui.task.failedDescription1":"Något gick fel när man försökte utföra åtgärder i bakgrunden.","ui.task.failedDescription2":"Om detta händer igen kanske din server inte stöds.","ui.task.reportProblem":"Rapportera ett problem","ui.task.pausedDescription":"Klicka på ”Fortsätt” om du vill ignorera felet och utföra de återstående åtgärderna.","ui.task.sponsor":"Composer Cloud sponsras av {sponsor}","ui.task.buttonAudit":"Uppdatera databas","ui.task.buttonClose":"Stänga","ui.task.buttonConfirm":"Bekräfta och stäng","ui.task.buttonContinue":"Fortsätta","ui.task.buttonCancel":"Avbryt","ui.task.confirmCancel":"Är du säker på att du avbryter den här uppgiften? Detta kan lämna din Contao-installation i ett trasigt tillstånd!","ui.task.autoclose":"Stäng uppgiftsinformation om framgång","ui.console.toggle":"Visa/dölj konsol-output","ui.console.showLog":"Visa hela konsolloggen","ui.console.copyLog":"Kopiera loggen till urklipp","ui.migrate.headline":"Databasuppdateringar","ui.migrate.migrationsOnly":"(endast migrering)","ui.migrate.schemaOnly":"(endast schema)","ui.migrate.loading":"Vänta, vi kontrollerar din databas...","ui.migrate.empty":"Inga pågående migreringar eller schemauppdateringar hittades. Din databas är uppdaterad.","ui.migrate.emptyMigrations":"Inga väntande migrering hittades. Se till att även leta efter schemauppdateringar.","ui.migrate.emptySchema":"Inga väntande schemauppdateringar hittades. Se till att även kontrollera migrering.","ui.migrate.pending":"Din databas är inte uppdaterad. Granska konsolutgången nedan och verkställ ändringarna.","ui.migrate.previousChanges":"En tidigare databasmigrering har inte bekräftats.\\nGranska konsolutgången nedan och fortsätt sedan för att se nästa ändringar.","ui.migrate.previousComplete":"En tidigare databasmigrering har inte bekräftats, vänligen granska konsolutdata nedan.\\nDet finns inga fler väntande ändringar.","ui.migrate.appliedChanges":"Databasuppdateringar har tillämpats.\\nGranska konsolutgången nedan och fortsätt sedan för att se nästa ändringar.","ui.migrate.appliedComplete":"Databasuppdateringar har tillämpats.\\nDet finns inga fler väntande migreringar eller schemauppdateringar. Din databas är uppdaterad.","ui.migrate.problem":"Contao har upptäckt ett problem med din databasserver.\\nGranska konsolutgången nedan för att ta reda på vad som behöver åtgärdas. | Contao har upptäckt problem med din databasserver.\\nGranska konsolutgången nedan för att ta reda på vad som behöver åtgärdas.","ui.migrate.warning":"Contao har upptäckt en felaktig konfiguration av din databasserver.\\nVarningar kan hoppas över tillfälligt, men bör åtgärdas för optimal prestanda och dataintegritet.","ui.migrate.error":"Ändringarna kunde inte tillämpas. Din databas kan ha ändrats, kontrollera igen för att försöka igen.","ui.migrate.execute":"Kör","ui.migrate.close":"Stänga","ui.migrate.confirm":"Bekräfta och stäng","ui.migrate.cancel":"Avbryt","ui.migrate.continue":"Fortsätta","ui.migrate.setup":"Setup","ui.migrate.skip":"Hoppa över","ui.migrate.retry":"Kolla igen","ui.migrate.retryAll":"Kontrollera alla","ui.migrate.withDeletes":"Utför alla databasändringar inklusive DROP-queries.","ui.migrate.migrationTitle":"Databasmigreringar","ui.migrate.schemaTitle":"Schemauppdateringar","ui.migrate.problemTitle":"Databasproblem","ui.migrate.warningTitle":"Databasvarningar","ui.migrate.addTable":"Lägg till tabell {table}","ui.migrate.dropTable":"Släpp tabell {table}","ui.migrate.addField":"Lägg till fält {table}.{field}","ui.migrate.changeField":"Ändra fält {table}.{field}","ui.migrate.dropField":"Släpp fältet {table}.{field}","ui.migrate.createIndex":"Skapa index \\"{name}\\" på {table}","ui.migrate.dropIndex":"Släpp index \\"{name}\\" på {table}","ui.widget.mandatory":"Detta fält får inte vara tomt.","ui.widget.blankOption":"Vänligen välj …","ui.widget.showPassword":"Visa lösenord","ui.widget.hidePassword":"Dölj lösenord","ui.error.title":"HTTP-begäran för \\"{method} {url}\\" misslyckades.","ui.error.server500":"Det verkar som att ett oväntat fel inträffade på din server. Kontrollera loggfilerna för din webbserver (Apache/Nginx) och Contao Manager-loggarna på \\"contao-manager/logs\\".","ui.error.response":"Servern returnerade ett svar med statuskoden {status}.","ui.error.moreLink":"Mer information","ui.error.support":"Contao Support","ui.error.permission":"Du har inte tillstånd att använda den här funktionen.","ui.footer.help":"Hjälp","ui.footer.reportProblem":"Rapportera ett problem","ui.navigation.discover":"Upptäck","ui.navigation.packages":"Paket","ui.navigation.tools":"Verktyg","ui.navigation.installTool":"Installera verktyg","ui.navigation.backend":"Contao Backend","ui.navigation.debug":"Contao Debug Mode Felsökningsläge","ui.navigation.logViewer":"Logg visare","ui.navigation.phpinfo":"PHP-information","ui.navigation.phpinfoLoading":"Laddar PHP-information...","ui.navigation.maintenance":"Underhåll","ui.navigation.rebuildCache":"Bygg om cachen","ui.navigation.users":"Konton","ui.navigation.systemCheck":"Systemkontroll","ui.navigation.advanced":"Avancerad","ui.navigation.logout":"Logga ut","ui.maintenance.database.title":"Databasmigreringar och säkerhetskopieringar","ui.maintenance.database.description":"Databasmigreringar säkerställer konsekventa data och tabellscheman.","ui.maintenance.database.migrations":"En väntande databasmigrering | {count} väntande databasmigreringar","ui.maintenance.database.schemaUpdates":"En väntande schemauppdatering | {count} väntande schemauppdateringar","ui.maintenance.database.error":"Databasproblem hittades.","ui.maintenance.database.warning":"Databasvarningar hittades.","ui.maintenance.database.button":"Kontrollera databasen","ui.maintenance.database.migrationOnly":"Kontrollera endast migrering","ui.maintenance.database.schemaOnly":"Kontrollera endast schemat","ui.maintenance.database.installTool":"Öppna installationsverktyget","ui.maintenance.database.createBackup":"Skapa backup","ui.maintenance.database.backupUnsupported":"Databassäkerhetskopior stöds inte av din Contao-version.","ui.maintenance.database.backupList":"Du har en databassäkerhetskopia, skapad den {date}. | Du har {count} databassäkerhetskopior, den senaste skapades den {date}.","ui.maintenance.database.backupEmpty":"Du har för närvarande inga säkerhetskopior av databasen.","ui.maintenance.rebuildCache.title":"Applikationscache","ui.maintenance.rebuildCache.description":"Att bygga om applikationscachen krävs efter att ha ändrat någon av konfigurationsfilerna.","ui.maintenance.rebuildCache.rebuildProd":"Bygg om produktionscachen","ui.maintenance.rebuildCache.rebuildDev":"Bygg om utvecklingscachen","ui.maintenance.rebuildCache.clearProd":"Rensa produktionscache","ui.maintenance.rebuildCache.clearDev":"Rensa utvecklingscache","ui.maintenance.installTool.title":"Contao installationsverktyg","ui.maintenance.installTool.description":"Contao Install Tool låses automatiskt om du anger fel lösenord tre gånger i rad.","ui.maintenance.installTool.unlock":"Lås upp installationsverktyget","ui.maintenance.installTool.lock":"Lås installationsverktyg","ui.maintenance.dumpAutoload.title":"Composer Class Loader","ui.maintenance.dumpAutoload.description":"Composer autoloader ansvarar för PHP-klassladdning. Autoloadern måste dumpas efter att anpassade namnområden har lagts till i roten composer.json.","ui.maintenance.dumpAutoload.button":"Dumpa Autoloader","ui.maintenance.composerInstall.title":"Composer beroenden","ui.maintenance.composerInstall.description":"Composer-beroenden finns i mappen {vendor} i din programrot. Att installera om beroenden kan vara nödvändigt efter manipulering eller manuell uppladdning av {composerLock}-filen.","ui.maintenance.composerInstall.button":"Kör installationsprogrammet","ui.maintenance.composerInstall.update":"Kör Composer Update","ui.maintenance.composerCache.title":"Composer Cache","ui.maintenance.composerCache.description":"Composer cachar nedladdade paket för förbättrad prestanda. Om du har problem som trasiga filer, försök att ta bort Composer-cachen för att tvinga fram en ny nedladdning.","ui.maintenance.composerCache.button":"Rensa cache","ui.maintenance.maintenanceMode.title":"Underhållsläge","ui.maintenance.maintenanceMode.description":"Om du sätter Contao i underhållsläge visas en \\"503 Service Unavailable\\"-mall för webbplatsen.","ui.maintenance.maintenanceMode.enable":"Aktivera","ui.maintenance.maintenanceMode.disable":"Inaktivera","ui.maintenance.debugMode.title":"Felsökningsläge Debug Mode","ui.maintenance.debugMode.description":"Aktivera felsökningsläget genom att ställa in en användare och lösenord för ingångspunkten för {appDevPhp}.","ui.maintenance.debugMode.descriptionJwt":"Aktivera felsökningsläget genom att ställa in felsökningscookien för den aktuella domänen.","ui.maintenance.debugMode.activate":"Aktivera","ui.maintenance.debugMode.deactivate":"Avaktivera","ui.maintenance.debugMode.credentials":"Referenser","ui.maintenance.debugMode.user":"Ange ett användarnamn för felsökningsläget.","ui.maintenance.debugMode.password":"Ange ett lösenord för felsökningsläget.","ui.maintenance.opcodeCache.title":"Opcode Cache","ui.maintenance.opcodeCache.description":"Opcode cachar PHP-filer på webbprocessen för snabbare exekvering. Det måste tas bort under vissa omständigheter om filer inte känns igen efter ändring.","ui.maintenance.opcodeCache.button":"Stympa Cache","ui.maintenance.safeMode":"Ej tillgängligt i felsäkert läge Safe Mode","ui.maintenance.unsupported":"Stöds inte av din Contao-version","ui.packages.updateButton":"Uppdatera paket","ui.packages.searchButton":"Sök paket","ui.packages.searchPlaceholder":"Sök paket …","ui.packages.uploadOverlay":"Dra och släpp filer för att ladda upp","ui.packages.uploadButton":"Ladda upp paket","ui.packages.uploadMessage":"Du har en obekräftad uppladdning. | Du har {count} obekräftade uppladdningar.","ui.packages.uploadApply":"Bekräfta uppladdningar","ui.packages.uploadReset":"Ta bort uppladdningar","ui.packages.uploadIncomplete":"Den här filen laddades inte upp helt. Ta bort den och försök igen.","ui.packages.uploadDuplicate":"Den här filen verkar ha laddats upp flera gånger. Ta bort dubbletterna.","ui.packages.uploadInstalled":"Den här filen är redan installerad. Ta bort dubbletterna.","ui.packages.uploadUnsupported":"Uppladdningar stöds inte i din installation. Se till att PHP ZIP-tillägget är installerat och uppdatera dina beroenden.","ui.packages.changesMessage":"Du har en obekräftad förändring. | Du har {count} obekräftade ändringar.","ui.packages.changesDryrun":"Testkörning","ui.packages.changesApply":"Applicera förändringar","ui.packages.changesApplyAll":"Uppdatera alla paket","ui.packages.changesDryrunAll":"Testkör alla paket","ui.packages.changesReset":"Återställ ändringar","ui.packages.changesReview":"Granska ändringar","ui.packagelist.loading":"Laddning ...","ui.packagelist.uploads":"Uppladdningar","ui.packagelist.added":"Nya paket","ui.packagelist.installed":"Installerade paket","ui.package.hintRevert":"Återställ ändringar","ui.package.hintNoupdate":"Uppdatera inte","ui.package.hintConstraint":"Det här paketet kommer att installeras med begränsningen {constraint} när du tillämpar ändringarna.","ui.package.hintConstraintBest":"Det här paketet kommer att installeras i den bästa tillgängliga versionen när du tillämpar ändringarna.","ui.package.hintConstraintChange":"Begränsningen för detta paket kommer att ändras från \\"{from}\\" till \\"{to}\\" när du tillämpar ändringarna.","ui.package.hintConstraintUpdate":"Detta paket kommer att uppdateras när du tillämpar ändringarna.","ui.package.hintAdded":"Det här paketet kommer att installeras när du tillämpar ändringarna.","ui.package.hintRemoved":"Detta paket kommer att tas bort när du tillämpar ändringarna.","ui.package.requiredTitle":"manuellt lagt till","ui.package.requiredText":"Det här paketet krävs i din composer.json men är inte installerat.","ui.package.removedTitle":"tas bort manuellt","ui.package.removedText":"Det här paketet togs bort från din composer.json.","ui.package.installed":"För närvarande installerad:","ui.package.version":"Version {version}","ui.package.additionalDownloads":"{count} Nedladdning | {count} nedladdningar","ui.package.additionalStars":"{count} stjärna | {count} stjärnor","ui.package.editConstraint":"Redigera","ui.package.uploadConstraint":"Denna begränsning definieras av det uppladdade paketet.","ui.package.updateButton":"Uppdatering","ui.package.removeButton":"Ta bort","ui.package.installButton":"Lägg till paket","ui.package.installButtonShort":"Lägg till","ui.package.detailsButton":"Detaljer","ui.package.latestConstraint":"senaste versionen","ui.package.update":"Uppdatering tillgänglig","ui.package.updateLatest":"senaste versionen","ui.package.updateAvailable":"{version} tillgänglig","ui.package.updateUnknown":"okänd version","ui.package.updateConstraint":"En nyare version utanför din versionsbegränsning är tillgänglig.","ui.package.incompatible":"{package} fungerar inte med Contao {constraint}.","ui.package.incompatibleWarning":"{paket} fungerar inte med Contao {begränsning} i någon av dess stabila versioner. Vill du lägga till paketet och ställa in en versionsbegränsning för att försöka installera en utvecklingsgren?","ui.package.incompatibleConstraint":"Det här paketet har ingen stabil version för Contao {begränsning}. Ange en versionsbegränsning för att försöka installera en utvecklingsgren.","ui.package.incompatibleButton":"Installera","ui.cloudStatus.headline":"Composer Resolver Cloud","ui.cloudStatus.version":"Version {version}","ui.cloudStatus.waitingTime":"Väntetid","ui.cloudStatus.jobs":"Aktuella jobb","ui.cloudStatus.workers":"Arbetare","ui.cloudStatus.approx":"{minutes} min","ui.cloudStatus.none":"ingen","ui.cloudStatus.short":"ca. {minutes} min","ui.cloudStatus.long":"ca. {minutes} min {seconds} sek","ui.cloudStatus.error":"Det går inte att hämta status för Composer Resolver Cloud. Det kan vara nere på grund av underhåll eller upplevelseproblem.","ui.cloudStatus.button":"Molnstatus","ui.cloudStatus.refresh":"Uppdatera molnstatus","ui.log-viewer.loading":"Laddning ...","ui.log-viewer.empty":"Det finns inga loggfiler på din server.","ui.log-viewer.reload":"Ladda om","ui.log-viewer.file":"Loggfil","ui.log-viewer.channel":"Kanal","ui.log-viewer.channelTitle":"Kanalen som detta meddelande loggades på.","ui.log-viewer.level":"Nivå","ui.log-viewer.levelTitle":"Allvaret i loggmeddelandet.","ui.log-viewer.timeHeader":"Tid","ui.log-viewer.messageHeader":"Meddelande","ui.log-viewer.showContext":"Visa sammanhang","ui.log-viewer.hideContext":"Dölj sammanhang","ui.log-viewer.showExtra":"Visa extra","ui.log-viewer.hideExtra":"Dölj extra","ui.log-viewer.more":"Ladda mer …","ui.log-viewer.download":"Ladda ner","ui.log-viewer.downloadTitle":"Nedladdning fil \\"{file}\\"","ui.log-viewer.prodEnvironment":"Produktionsmiljö","ui.log-viewer.devEnvironment":"Utvecklingsmiljö (felsökningsläge)","ui.user-manager.loading":"Laddar användare ...","ui.user-manager.changePassword":"Ändra lösenord","ui.user-manager.setupTotp":"Konfigurera tvåfaktorsautentisering","ui.user-manager.disableTotp":"Inaktivera tvåfaktorsautentisering","ui.user-manager.invite":"Bjud in användare","ui.user-manager.delete":"Radera","ui.user-manager.deleteConfirm":"Vill du verkligen ta bort användaren ”{användarnamn}”?","ui.user-manager.deleted":"Användaren {användarnamn} raderades framgångsrikt","ui.user-manager.passwordHeadline":"Ändra lösenord","ui.user-manager.passwordText":"Om du vill ändra ditt lösenord anger du det nuvarande och ett nytt lösenord i respektive fält.","ui.user-manager.currentPassword":"Aktuellt lösenord","ui.user-manager.newPassword":"Nytt lösenord","ui.user-manager.passwordPlaceholder":"min. 8 tecken","ui.user-manager.submitPassword":"Skicka","ui.user-manager.passwordChanged":"Ditt lösenord har ändrats framgångsrikt.","ui.user-manager.passwordError":"Det här lösenordet är felaktigt.","ui.user-manager.inviteHeadline":"Bjud in användare","ui.user-manager.inviteText":"Om du behöver flera inloggningar för Contao Manager kan du skapa en inbjudningslänk här. Dela den här länken med någon eller använd den på en annan enhet för att skapa ett nytt konto med de angivna behörigheterna.","ui.user-manager.inviteSuccess1":"En ny inbjudningslänk har skapats. URL:en nedan kan användas för att skapa ett nytt användarkonto för denna Contao Manager. Inbjudan löper ut den {expires} (one week from now).","ui.user-manager.inviteSuccess2":"Kopiera länken till ditt urklipp. Den fungerar bara en gång och du kommer inte att kunna se den igen efter att du har stängt den här dialogen.","ui.user-manager.createInvitation":"Skapa länk till inbjudan","ui.user-manager.clipboard":"Kopiera till urklipp","ui.user-manager.permissions":"Läs mer om behörigheter","ui.user-manager.cancel":"Avbryt","ui.user-manager.close":"Stänga","ui.user-manager.you":"Du","ui.user-manager.2fa":"2FA","ui.user-manager.2faEnabled":"Detta konto är säkrat med tvåfaktorsautentisering.","ui.user-manager.2faDisabled":"Det här kontot är osäkert eftersom det saknas tvåfaktorsautentisering.","ui.user-manager.passkey":"Passkey","ui.user-manager.passkeyTitle":"Detta konto är skyddat med en passkey.","ui.totp.headline":"Tvåfaktorsautentisering","ui.totp.setupQr":"Vänligen skanna QR-koden med din 2FA/TOTP-app.","ui.totp.setupCode":"Om du inte kan skanna QR-koden, ange den här nyckeln istället:","ui.totp.codeLabel":"Verifieringskod","ui.totp.codeDescription":"Ange verifieringskoden som genereras av din 2FA/TOTP-app.","ui.totp.disableText":"Ange verifieringskoden för att inaktivera tvåfaktorsautentisering.","ui.totp.invalid":"Verifieringskoden är ogiltig.","ui.totp.enable":"Aktivera","ui.totp.disable":"Inaktivera","ui.totp.cancel":"Avbryt","ui.totp.enabled":"Tvåfaktorsautentisering aktiverades framgångsrikt.","ui.totp.disabled":"Tvåfaktorsautentisering avaktiverades framgångsrikt.","ui.totp.setup":"Konfigurera tvåfaktorsautentisering","ui.totp.skip":"Hoppa över tvåfaktorsautentisering"}')}}]);"use strict";(self["webpackChunkcontao_manager"]=self["webpackChunkcontao_manager"]||[]).push([[52],{9052:function(e){e.exports=JSON.parse('{"ui.app.title":"Extensões Contao","ui.app.loading":"A preparar a Lista de Extensões ...","ui.app.language":"Switch language for the Contao Manager","ui.app.colorDark":"Dark Mode","ui.app.colorDarkTitle":"Switch color scheme to dark","ui.app.colorLight":"Light Mode","ui.app.colorLightTitle":"Switch color scheme to light","ui.discover.advertisement":"Anúncio na lista de extensão","ui.discover.loading":"A Carregar ...","ui.discover.offline":"Falha ao obter resultados.","ui.discover.offlineExplain":"Verifique a sua conexão à internet e desactive bloqueadores JavaScript no seu browser.","ui.discover.offlineButton":"Tente novamente","ui.discover.searchPlaceholder":"Pesquisar em extensões {count} ...","ui.discover.empty":"Sem resultados para {query}","ui.discover.more":"Mais resultados","ui.discover.sortBy":"Ordenar por","ui.discover.sortReleased":"Released","ui.discover.sortReleasedTitle":"Sort results by release date","ui.discover.sortLatest":"Actualizado","ui.discover.sortLatestTitle":"Sort results by last updated","ui.discover.sortDownloads":"Downloads","ui.discover.sortDownloadsTitle":"Sort results by number of downloads","ui.discover.sortFavers":"Classificação","ui.discover.sortFaversTitle":"Sort results by rating","ui.discover.detailsButton":"Detalhes","ui.discover.latestPackages":"Extensões mais recentes e mais recentemente actualizadas","ui.discover.faversPackages":"Extensões com melhor classificação","ui.discover.downloadsPackages":"Extensões com maior numero de downloads","ui.discover.exactHit":"Exact query match","ui.discover.results":"More search results","ui.package.homepage":"Website do Projecto","ui.package.private":"Pacote Privado","ui.package.privateTitle":"Pacotes privados apenas são disponibilizados pelo proprietário. (por ex. Como um download .zip). Por favor visite o website para mais informação.","ui.package.abandoned":"abandonado","ui.package.abandonedText":"Este pacote é obsoleto e já não recebe actualizações e suporte.","ui.package.abandonedReplace":"Este pacote é obsoleto e já não recebe actualizações e suporte. O autor sugere que utilize como alternativa {replacement} .","ui.package.contaoVersion":"Available for Contao","ui.package-details.previous":"Detalhes da Extensão Anterior","ui.package-details.close":"Fechar Detalhes da Extensão","ui.package-details.loading":"A Carregar ...","ui.package-details.tabDescription":"Descrição","ui.package-details.tabRequire":"Requerimentos","ui.package-details.tabFeatures":"Funcionalidades","ui.package-details.tabSuggest":"Sugestões","ui.package-details.tabConflict":"Conflitos","ui.package-details.tabDependents":"Dependências","ui.package-details.linkRequires":"necessita","ui.package-details.linkReplaces":"substitui","ui.package-details.linkProvides":"fornece","ui.package-details.linkConflicts":"tem conflito","ui.package-details.funding":"Manutenção do pacote de fundos!","ui.package-details.contaoVersions":"Supported Contao version(s)","ui.package-details.latest":"Última versão","ui.package-details.released":"lançada em","ui.package-details.license":"Licença(s)","ui.package-details.authors":"a partir de","ui.package-details.more":"Mais","ui.package-details.packagist":"Detalhes do Pacote","ui.package-details.metadata":"Editar Metadata","ui.package-details.support_docs":"Documentação","ui.package-details.support_wiki":"Wiki","ui.package-details.support_forum":"Forum de Suporte","ui.package-details.support_issues":"Submissão de erros e problemas","ui.package-details.support_source":"Código Fonte","ui.package-details.support_irc":"IRC / Chat","ui.package-details.support_email":"E-mail de Suporte","ui.package-details.support_rss":"RSS Feed"}')}}]);"use strict";(self["webpackChunkcontao_manager"]=self["webpackChunkcontao_manager"]||[]).push([[367],{7390:function(e,r,t){t.r(r),t.d(r,{default:function(){return b}});var o=t(641),i=t(33),a=t.p+"img/recovery.70ee118a.svg";const s={class:"view-recovery__header"},n={class:"view-recovery__headline"},c={class:"view-recovery__content"},l={class:"view-recovery__description"},d={class:"view-recovery__description"},u={class:"view-recovery__option"},v={key:0,class:"view-recovery__failed"},p={class:"view-recovery__option"},h=["disabled"];function _(e,r,t,_,k,y){const w=(0,o.g2)("console-output"),m=(0,o.g2)("loading-button"),f=(0,o.g2)("boxed-layout");return(0,o.uX)(),(0,o.Wv)(f,{wide:!0,slotClass:"view-recovery"},{default:(0,o.k6)(()=>[(0,o.Lk)("header",s,[r[1]||(r[1]=(0,o.Lk)("img",{src:a,width:"80",height:"80",alt:"",class:"view-recovery__icon"},null,-1)),(0,o.Lk)("h1",n,(0,i.v_)(e.$t("ui.recovery.headline")),1)]),(0,o.Lk)("main",c,[(0,o.Lk)("p",l,(0,i.v_)(e.$t("ui.recovery.description")),1),console?((0,o.uX)(),(0,o.Wv)(w,{key:0,class:"view-recovery__console",title:e.$t("ui.recovery.console"),operations:[{status:"error",summary:"vendor/bin/contao-console list",console:this.error}],"console-output":e.error,"show-console":"","force-console":""},null,8,["title","operations","console-output"])):(0,o.Q3)("",!0),(0,o.Lk)("p",d,(0,i.v_)(e.$t("ui.recovery.repairOptions")),1),(0,o.Lk)("div",u,[(0,o.Lk)("h3",null,(0,i.v_)(e.$t("ui.recovery.repairHeadline")),1),(0,o.Lk)("p",null,(0,i.v_)(e.$t("ui.recovery.repairDescription")),1),(0,o.Lk)("p",null,[(0,o.Lk)("strong",null,(0,i.v_)(e.$t("ui.recovery.repairWarning")),1)]),e.repairFailed?((0,o.uX)(),(0,o.CE)("p",v,(0,i.v_)(e.$t("ui.recovery.repairFailed")),1)):(0,o.Q3)("",!0),(0,o.bF)(m,{inline:"",color:"alert",icon:"run",disabled:e.repairFailed,loading:e.repairStarted&&!e.repairFailed,onClick:y.runRepair},{default:(0,o.k6)(()=>[(0,o.eW)((0,i.v_)(e.$t("ui.recovery.repairButton")),1)]),_:1},8,["disabled","loading","onClick"])]),(0,o.Lk)("div",p,[(0,o.Lk)("h3",null,(0,i.v_)(e.$t("ui.recovery.safeModeHeadline")),1),(0,o.Lk)("p",null,(0,i.v_)(e.$t("ui.recovery.safeModeDescription")),1),(0,o.Lk)("button",{class:"widget-button widget-button--inline widget-button--primary",disabled:e.repairStarted&&!e.repairFailed,onClick:r[0]||(r[0]=(...e)=>y.runSafeMode&&y.runSafeMode(...e))},(0,i.v_)(e.$t("ui.recovery.safeModeButton")),9,h)])])]),_:1})}var k=t(6278),y=t(707),w=t(728),m=t(5506),f=t(2864),g={components:{BoxedLayout:w.A,LoadingButton:m.A,ConsoleOutput:f.A},data:()=>({repairStarted:!1,repairFailed:!1,error:""}),computed:{...(0,k.aH)("tasks",{taskStatus:"status"})},methods:{async runRepair(){let e;this.repairStarted=!0;const r=[{name:"contao/rebuild-cache"},{name:"composer/install"},{name:"composer/install",config:{"remove-vendor":!0}}];while(void 0!==(e=r.shift()))try{return await this.$store.dispatch("tasks/execute",e),await this.$store.dispatch("tasks/deleteCurrent"),void window.location.reload(!0)}catch(t){if("failed"===this.taskStatus){await this.$store.dispatch("tasks/deleteCurrent");break}await this.$store.dispatch("tasks/deleteCurrent")}this.repairFailed=!0},runSafeMode(){this.$store.commit("setSafeMode",!0),this.$store.commit("setView",y.A.READY)}},async mounted(){const e=await this.$store.dispatch("server/contao/get");502===e.status&&e.data.error&&(this.error=e.data.error)}},$=t(6262);const L=(0,$.A)(g,[["render",_]]);var b=L}}]);"use strict";(self["webpackChunkcontao_manager"]=self["webpackChunkcontao_manager"]||[]).push([[140],{1140:function(e){e.exports=JSON.parse('{"ui.app.title":"Contao Extensions","ui.app.loading":"Loading Extension List …","ui.discover.advertisement":"Advertisement in the extension list","ui.discover.loading":"O kargañ ...","ui.discover.offline":"N\'eo ket gouest da adtapout disoc\'hoù.","ui.discover.offlineExplain":"Check your internet connection and disable JavaScript blockers in your browser.","ui.discover.offlineButton":"Try again","ui.discover.searchPlaceholder":"Search in {count} extensions …","ui.discover.empty":"No results for {query}","ui.discover.more":"More Results","ui.discover.sortBy":"Sort by","ui.discover.sortLatest":"Updated","ui.discover.sortLatestTitle":"Sort search results by last updated","ui.discover.sortDownloads":"Downloads","ui.discover.sortDownloadsTitle":"Sort search results by number of downloads","ui.discover.sortFavers":"Rating","ui.discover.sortFaversTitle":"Sort search results by rating","ui.discover.detailsButton":"Munudoù","ui.discover.latestPackages":"Latest and updated extensions","ui.discover.faversPackages":"Top rated extensions","ui.discover.downloadsPackages":"Most downloaded extensions","ui.package.homepage":"Lec\'hienn ar raktres","ui.package.private":"Private Package","ui.package.privateTitle":"Private packages are only available from the vendor (e.g. as a ZIP download). Please visit the website for more information.","ui.package.abandoned":"dilezet","ui.package.abandonedText":"This package is abandoned and no longer maintained.","ui.package.abandonedReplace":"This package is abandoned and no longer maintained. The author suggests using the {replacement} package instead.","ui.package-details.previous":"Previous Extension Details","ui.package-details.close":"Close Extension Details","ui.package-details.loading":"O kargañ ...","ui.package-details.tabDescription":"Description","ui.package-details.tabRequire":"Requirements","ui.package-details.tabFeatures":"Features","ui.package-details.tabSuggest":"Suggestions","ui.package-details.tabConflict":"Conflicts","ui.package-details.tabDependents":"Dependents","ui.package-details.linkRequires":"requires","ui.package-details.linkReplaces":"replaces","ui.package-details.linkProvides":"provides","ui.package-details.linkConflicts":"conflicts","ui.package-details.funding":"Fund package maintenance!","ui.package-details.latest":"Latest version","ui.package-details.released":"released on","ui.package-details.license":"License(s)","ui.package-details.authors":"from","ui.package-details.more":"Muioc\'h","ui.package-details.packagist":"Munudoù ar pakaj","ui.package-details.metadata":"Edit Metadata","ui.package-details.support_docs":"Titouroù","ui.package-details.support_wiki":"Wiki","ui.package-details.support_forum":"Forom skoazell","ui.package-details.support_issues":"Kudennoù/Danevell beugoù","ui.package-details.support_source":"Kod mamenn","ui.package-details.support_irc":"IRC/Flapva","ui.package-details.support_email":"Skoazell dre Bostel","ui.package-details.support_rss":"Froud RSS"}')}}]);"use strict";(self["webpackChunkcontao_manager"]=self["webpackChunkcontao_manager"]||[]).push([[486],{8486:function(e){e.exports=JSON.parse('{"ui.app.title":"Contao eklentileri","ui.app.loading":"Eklenti listesi yükleniyor…","ui.app.language":"Contao Manager dilini değiştir","ui.app.colorDark":"Koyu kip","ui.app.colorDarkTitle":"Renk temasını koyu olarak değiştir","ui.app.colorLight":"Açık kip","ui.app.colorLightTitle":"Renk temasını açık olarak değiştir","ui.discover.advertisement":"Eklenti listesinde duyuru","ui.discover.loading":"Yükleniyor…","ui.discover.offline":"Herhangi bir sonuç alınamadı.","ui.discover.offlineExplain":"İnternet bağlantınızı denetleyin ve tarayıcınızdaki JavaScript engelleyicileri etkisizleştirin.","ui.discover.offlineButton":"Yeniden dene","ui.discover.searchPlaceholder":"{count} eklentide ara…","ui.discover.empty":"{query} ile eşleşen bir sonuç bulunamadı","ui.discover.more":"Diğer sonuçlar","ui.discover.sortBy":"Sıralama","ui.discover.sortReleased":"Yayınlandı","ui.discover.sortReleasedTitle":"Sonuçlar yayınlanma tarihine göre sıralansın","ui.discover.sortLatest":"Güncellendi","ui.discover.sortLatestTitle":"Sonuçlar güncellenme tarihine göre sıralansın","ui.discover.sortDownloads":"İndirmeler","ui.discover.sortDownloadsTitle":"Sonuçlar indirme sayılarına göre sıralansın","ui.discover.sortFavers":"Değerlendirme","ui.discover.sortFaversTitle":"Sonuçlar değerlendirmeye göre sıralansın","ui.discover.detailsButton":"Ayrıntılar","ui.discover.latestPackages":"Yeni ve güncellenmiş eklentiler","ui.discover.faversPackages":"İyi değerlendirilmiş eklentiler","ui.discover.downloadsPackages":"En çok indirilen eklentiler","ui.discover.exactHit":"Tam sorgu eşleşmesi","ui.discover.results":"Diğer arama sonuçları","ui.package.homepage":"Proje sitesi","ui.package.private":"Özel paket","ui.package.privateTitle":"Özel paketler yalnızca üretici tarafından sağlanabilir (ZIP indirmesi gibi). Ayrıntılı bilgi almak için siteye bakabilirsiniz.","ui.package.abandoned":"kullanımdan kaldırıldı","ui.package.abandonedText":"Bu paket kullanımdan kaldırıldı ve artık geliştirilmiyor.","ui.package.abandonedReplace":"Bu paket kullanımdan kaldırıldı ve artık geliştirilmiyor. Geliştirici bunun yerine  {replacement} paketinin kullanılmasını öneriyor.","ui.package.contaoVersion":"Contao ile kullanılabilir","ui.package-details.previous":"Önceki eklenti bilgileri","ui.package-details.close":"Eklenti bilgilerini kapat","ui.package-details.loading":"Yükleniyor…","ui.package-details.tabDescription":"Açıklama","ui.package-details.tabRequire":"Gereksinimler","ui.package-details.tabFeatures":"Özellikler","ui.package-details.tabSuggest":"Öneriler","ui.package-details.tabConflict":"Çakışmalar","ui.package-details.tabDependents":"Bağımlılar","ui.package-details.linkRequires":"gereksinimi","ui.package-details.linkReplaces":"değişikliği","ui.package-details.linkProvides":"sundukları","ui.package-details.linkConflicts":"çakışması","ui.package-details.funding":"Paketin geliştirilmesine destek olun!","ui.package-details.contaoVersions":"Desteklenen Contao sürümleri","ui.package-details.latest":"Son sürüm","ui.package-details.released":"yayınlanma tarihi","ui.package-details.license":"Lisanslar","ui.package-details.authors":"geliştiren","ui.package-details.more":"Ayrıntılar","ui.package-details.packagist":"Paket bilgileri","ui.package-details.metadata":"Üst verileri düzenle","ui.package-details.support_docs":"Belgeler","ui.package-details.support_wiki":"Viki","ui.package-details.support_forum":"Destek forumu","ui.package-details.support_issues":"Sorunlar / Hata bildirimi","ui.package-details.support_source":"Kaynak kodu","ui.package-details.support_irc":"IRC / Sohbet","ui.package-details.support_email":"Destek e-postası","ui.package-details.support_rss":"RSS akışı"}')}}]);"use strict";(self["webpackChunkcontao_manager"]=self["webpackChunkcontao_manager"]||[]).push([[581],{4581:function(a){a.exports=JSON.parse('{"ui.app.title":"Contao проширења","ui.app.loading":"Учитавам листу проширења...","ui.app.language":"Switch language for the Contao Manager","ui.app.colorDark":"Dark Mode","ui.app.colorDarkTitle":"Switch color scheme to dark","ui.app.colorLight":"Light Mode","ui.app.colorLightTitle":"Switch color scheme to light","ui.discover.advertisement":"Оглашавање у листи екстензија","ui.discover.loading":"Учитавам ...","ui.discover.offline":"Нема пронађених резултата.","ui.discover.offlineExplain":"Проверите вашу интернет конекцију и искључите блокаду JavaScript-а у вашем прегледачу.","ui.discover.offlineButton":"Покушајте поново","ui.discover.searchPlaceholder":"Претражи у {count} екстензија ...","ui.discover.empty":"Нема резултата за {query}","ui.discover.more":"Више резултата","ui.discover.sortBy":"Сортирај по","ui.discover.sortReleased":"Објављено","ui.discover.sortReleasedTitle":"Поредај резултате по датуму објаве","ui.discover.sortLatest":"Ажурирано","ui.discover.sortLatestTitle":"Поредај резултате по датуму ажурирања","ui.discover.sortDownloads":"Преузимања","ui.discover.sortDownloadsTitle":"Поредај резултате по броју преузимања","ui.discover.sortFavers":"Оцене","ui.discover.sortFaversTitle":"Поредај резултате по оцени","ui.discover.detailsButton":"Детаљи","ui.discover.latestPackages":"Последње и ажуриране екстензије","ui.discover.faversPackages":"Најбоље оцењене екстензије","ui.discover.downloadsPackages":"Екстензије са највише преузимања","ui.discover.exactHit":"Exact query match","ui.discover.results":"More search results","ui.package.homepage":"Вебсајт пројекта","ui.package.private":"Приватни пакети","ui.package.privateTitle":"Приватни пакети су доступни само од вендора (нпр. као ZIP преузимање). Посетите сајт ради више информација.","ui.package.abandoned":"напуштено","ui.package.abandonedText":"Овај пакет је напуштен и више се не одржава.","ui.package.abandonedReplace":"Овај пакет је напуштен и више се не одржава. Аутор предлаже да користите {replacement} као замену.","ui.package.contaoVersion":"Available for Contao","ui.package-details.previous":"Детаљи претходне екстензије","ui.package-details.close":"Затвори детаље екстензије","ui.package-details.loading":"Учитавам ...","ui.package-details.tabDescription":"Опис","ui.package-details.tabRequire":"Захтеви","ui.package-details.tabFeatures":"Могућности","ui.package-details.tabSuggest":"Предлози","ui.package-details.tabConflict":"Конфликти","ui.package-details.tabDependents":"Зависности","ui.package-details.linkRequires":"захтева","ui.package-details.linkReplaces":"мења","ui.package-details.linkProvides":"пружа","ui.package-details.linkConflicts":"сукобљава се са","ui.package-details.funding":"Спонзорирајте одржавање пакета!","ui.package-details.contaoVersions":"Supported Contao version(s)","ui.package-details.latest":"Последња верзија","ui.package-details.released":"објављено","ui.package-details.license":"Лиценца(е)","ui.package-details.authors":"од","ui.package-details.more":"Детаљније","ui.package-details.packagist":"Детаљи пакета","ui.package-details.metadata":"Уреди мета податке","ui.package-details.support_docs":"Документација","ui.package-details.support_wiki":"Wiki","ui.package-details.support_forum":"Форум за подршку","ui.package-details.support_issues":"Пријава проблема/Баг","ui.package-details.support_source":"Изворни код","ui.package-details.support_irc":"IRC / Chat","ui.package-details.support_email":"Имејл подршке","ui.package-details.support_rss":"RSS сажетак"}')}}]);"use strict";(self["webpackChunkcontao_manager"]=self["webpackChunkcontao_manager"]||[]).push([[953],{3953:function(e){e.exports=JSON.parse('{"ui.app.title":"Contao Extensions","ui.app.loading":"Laddar tilläggslista …","ui.app.language":"Byt språk för Contao Manager","ui.app.colorDark":"Mörkt läge","ui.app.colorDarkTitle":"Byt färgschema till mörkt","ui.app.colorLight":"Ljusläge","ui.app.colorLightTitle":"Byt färgschema till ljus","ui.discover.advertisement":"Annons i tilläggslistan","ui.discover.loading":"Laddning ...","ui.discover.offline":"Det gick inte att hämta några resultat.","ui.discover.offlineExplain":"Kontrollera din internetanslutning och inaktivera JavaScript-blockerare i din webbläsare.","ui.discover.offlineButton":"Försök igen","ui.discover.searchPlaceholder":"Sök i {count} tillägg …","ui.discover.empty":"Inga resultat för {query}","ui.discover.more":"Fler resultat","ui.discover.sortBy":"Sortera efter","ui.discover.sortReleased":"Släppte","ui.discover.sortReleasedTitle":"Sortera resultat efter releasedatum","ui.discover.sortLatest":"Uppdaterad","ui.discover.sortLatestTitle":"Sortera resultat efter senast uppdaterade","ui.discover.sortDownloads":"Nedladdningar","ui.discover.sortDownloadsTitle":"Sortera resultat efter antal nedladdningar","ui.discover.sortFavers":"Betyg","ui.discover.sortFaversTitle":"Sortera resultat efter betyg","ui.discover.detailsButton":"Detaljer","ui.discover.latestPackages":"Senaste och uppdaterade tillägg","ui.discover.faversPackages":"Högst rankade tillägg","ui.discover.downloadsPackages":"Mest nedladdade tillägg","ui.discover.exactHit":"Exakt matchning av sökfrågan","ui.discover.results":"Fler sökresultat","ui.package.homepage":"Projektets hemsida","ui.package.private":"Privat paket","ui.package.privateTitle":"Privata paket är endast tillgängliga från leverantören (t.ex. som en ZIP-nedladdning). Besök gärna webbplatsen för mer information.","ui.package.abandoned":"övergiven","ui.package.abandonedText":"Detta paket är övergivet och underhålls inte längre.","ui.package.abandonedReplace":"Detta paket är övergivet och underhålls inte längre. Författaren föreslår att du istället använder paketet {replacement}.","ui.package.contaoVersion":"Tillgänglig för Contao","ui.package-details.previous":"Tidigare tilläggsinformation","ui.package-details.close":"Stäng tilläggsinformation","ui.package-details.loading":"Laddning ...","ui.package-details.tabDescription":"Beskrivning","ui.package-details.tabRequire":"Krav","ui.package-details.tabFeatures":"Funktioner","ui.package-details.tabSuggest":"Förslag","ui.package-details.tabConflict":"Konflikter","ui.package-details.tabDependents":"Anhöriga","ui.package-details.linkRequires":"kräver","ui.package-details.linkReplaces":"ersätter","ui.package-details.linkProvides":"tillhandahåller","ui.package-details.linkConflicts":"konflikter","ui.package-details.funding":"Underhåll av fondpaket!","ui.package-details.contaoVersions":"Stödd Contao version(er)","ui.package-details.latest":"Senaste versionen","ui.package-details.released":"släppt på","ui.package-details.license":"Licens(er)","ui.package-details.authors":"från","ui.package-details.more":"Mer","ui.package-details.packagist":"Paketdetaljer","ui.package-details.metadata":"Redigera metadata","ui.package-details.support_docs":"Dokumentation","ui.package-details.support_wiki":"Wiki","ui.package-details.support_forum":"Supportforum","ui.package-details.support_issues":"Problem/felrapport","ui.package-details.support_source":"Källkod","ui.package-details.support_irc":"IRC / Chat","ui.package-details.support_email":"Support E-post","ui.package-details.support_rss":"RSS Feed"}')}}]);(function(){"use strict";var e={8044:function(e,t,a){a(4423);var s=a(6992),i=a(4173),n=a(4210);const o=async(...e)=>{let t,a={};for(t=0;t<e.length;t++)a=Object.assign(a,(await e[t]).default);return a},l={en:()=>o(a.e(219).then(a.t.bind(a,3219,19)),a.e(553).then(a.t.bind(a,5553,19))),de:()=>o(a.e(523).then(a.t.bind(a,523,19)),a.e(477).then(a.t.bind(a,6477,19))),br:()=>o(a.e(140).then(a.t.bind(a,1140,19)),a.e(958).then(a.t.bind(a,2958,19))),cs:()=>o(a.e(874).then(a.t.bind(a,2874,19)),a.e(540).then(a.t.bind(a,4540,19))),es:()=>o(a.e(180).then(a.t.bind(a,2180,19)),a.e(706).then(a.t.bind(a,2706,19))),fa:()=>o(a.e(669).then(a.t.bind(a,9669,19)),a.e(139).then(a.t.bind(a,4139,19))),fr:()=>o(a.e(739).then(a.t.bind(a,8120,19)),a.e(554).then(a.t.bind(a,4554,19))),it:()=>o(a.e(769).then(a.t.bind(a,4769,19)),a.e(851).then(a.t.bind(a,6851,19))),ja:()=>o(a.e(721).then(a.t.bind(a,9721,19)),a.e(551).then(a.t.bind(a,2551,19))),lv:()=>o(a.e(194).then(a.t.bind(a,194,19)),a.e(560).then(a.t.bind(a,1560,19))),nl:()=>o(a.e(518).then(a.t.bind(a,2518,19)),a.e(164).then(a.t.bind(a,6164,19))),pl:()=>o(a.e(716).then(a.t.bind(a,3716,19)),a.e(638).then(a.t.bind(a,3638,19))),pt:()=>o(a.e(52).then(a.t.bind(a,9052,19)),a.e(606).then(a.t.bind(a,4606,19))),ru:()=>o(a.e(557).then(a.t.bind(a,1557,19)),a.e(715).then(a.t.bind(a,3715,19))),sr:()=>o(a.e(581).then(a.t.bind(a,4581,19)),a.e(748).then(a.t.bind(a,8367,19))),sv:()=>o(a.e(953).then(a.t.bind(a,3953,19)),a.e(643).then(a.t.bind(a,6643,19))),tr:()=>o(a.e(486).then(a.t.bind(a,8486,19)),a.e(44).then(a.t.bind(a,44,19))),zh:()=>o(a.e(542).then(a.t.bind(a,7542,19)),a.e(28).then(a.t.bind(a,4028,19)))},r=(0,s.hU)(),c=e=>{r.global.locale=e,(0,n.x)(e),i.A.commit("algolia/setLanguage",e),document.querySelector("html").setAttribute("lang",e)};t.A={plugin:r,async init(){r.global.fallbackLocale="en",await this.load("en");const e=localStorage.getItem("contao_manager_locale");if(e&&l[e])return this.load(e);const t=Array.from(navigator.languages);for(let a=0;a<t.length;a+=1)if(l[t[a]])return this.load(t[a])},async switch(e){window.localStorage.setItem("contao_manager_locale",e),await this.load(e),await i.A.dispatch("algolia/discover")},async load(e){if(r.global.availableLocales.includes(e))c(e);else{if(!l[e]){if(5===e.length)return this.load(e.slice(0,2));throw`Locale ${e} does not exist.`}r.global.setLocaleMessage(e,Object.assign({},await l[e]())),c(e)}}}},7040:function(e,t,a){a(4423);var s=a(4335),i=a(5633),n=a(3192),o=a(1029),l=a(3723),r=a(641),c=a(33);const u={key:0},d=["href"];function p(e,t,a,s,i,n){const o=(0,r.g2)("install-button"),l=(0,r.g2)("discover-list");return(0,r.uX)(),(0,r.Wv)(l,{wrapper:n.wrapper,"hide-themes":""},{"package-hint":(0,r.k6)(({data:t})=>[e.contaoSupported(t.contaoConstraint)?(0,r.Q3)("",!0):((0,r.uX)(),(0,r.CE)("p",u,(0,c.v_)(e.$t("ui.package.incompatible",{package:t.name,constraint:e.packageConstraint("contao/manager-bundle")})),1))]),"package-actions":(0,r.k6)(({data:t})=>[t&&t.private&&!e.packageSuggested(t.name)?((0,r.uX)(),(0,r.CE)("a",{key:0,class:"widget-button widget-button--small widget-button--primary widget-button--link",target:"_blank",href:t.homepage},(0,c.v_)(e.$t("ui.package.homepage")),9,d)):((0,r.uX)(),(0,r.Wv)(o,{key:1,small:"",inline:"",data:t},null,8,["data"]))]),_:1},8,["wrapper"])}var g=a(6278),h=a(6894);const m={class:"layout-main"},k={class:"layout-main__logo"},v={class:"layout-main__title"},b={key:0,class:"layout-main__badge-title"},_={key:0,class:"layout-main__subheader"},f={class:"layout-main__subheader-inside"},w={key:0,class:"layout-main__news"},y=["href","title"],C=["src","alt"],$={class:"layout-main__content"};function L(e,t,a,s,i,n){const o=(0,r.g2)("navigation-fragment"),l=(0,r.g2)("footer-fragment");return(0,r.uX)(),(0,r.CE)("div",m,[(0,r.Lk)("header",{class:(0,c.C4)(["layout-main__header",{"layout-main__header--margin":!e.$slots.search,"layout-main__has-badge-title":e.badgeTitle}])},[(0,r.Lk)("div",k,[t[1]||(t[1]=(0,r.Lk)("img",{src:h,width:"40",height:"40",alt:"Contao Logo"},null,-1)),(0,r.Lk)("span",v,[t[0]||(t[0]=(0,r.Lk)("span",{class:"layout-main__manager-title"},"Contao Manager",-1)),e.badgeTitle?((0,r.uX)(),(0,r.CE)("span",b,(0,c.v_)(e.badgeTitle),1)):(0,r.Q3)("",!0)])]),(0,r.bF)(o)],2),e.$slots.search?((0,r.uX)(),(0,r.CE)("div",_,[(0,r.Lk)("div",f,[n.currentNews?((0,r.uX)(),(0,r.CE)("div",w,[(0,r.Lk)("a",{href:n.currentNews.url,title:n.currentNews.title,target:"_blank",rel:"noreferrer noopener"},[(0,r.Lk)("img",{src:n.currentNews.image,width:"320",height:"50",alt:n.currentNews.title},null,8,C)],8,y)])):(0,r.Q3)("",!0),(0,r.RG)(e.$slots,"search")])])):(0,r.Q3)("",!0),(0,r.Lk)("main",$,[(0,r.RG)(e.$slots,"default")]),(0,r.bF)(l,{display:"main"})])}var A=a(3751);const E={id:"main-navigation",role:"navigation",class:"navigation"},X={ref:"menu",class:"navigation__group navigation__group--main"},S={key:0,class:"navigation__item-badge"},x={key:0,class:"navigation__item-badge"},T={class:"navigation__item navigation__item--main navigation__item--children"},M={class:"navigation__group navigation__group--sub"},O={key:0,class:"navigation__item navigation__item--sub"},F=["href"],I={key:1,class:"navigation__item navigation__item--sub"},P={href:"/app_dev.php/",target:"_blank"},R={key:2,class:"navigation__item navigation__item--sub"},B=["href"],D={key:3,class:"navigation__item navigation__item--sub"},j=["href"],U={class:"navigation__item navigation__item--sub"},q={class:"navigation__item navigation__item--main navigation__item--children navigation__item--icon"},W={class:"navigation__group navigation__group--sub navigation__group--right"},V={class:"navigation__item navigation__item--sub"},Q={class:"navigation__item navigation__item--sub"};function H(e,t,a,s,i,n){const o=(0,r.g2)("navigation-item");return(0,r.uX)(),(0,r.CE)("nav",E,[(0,r.Lk)("button",{class:"navigation__toggle",onClick:t[0]||(t[0]=(0,A.D$)((...e)=>n.toggleNavigation&&n.toggleNavigation(...e),["prevent"]))},[...t[4]||(t[4]=[(0,r.Lk)("span",null,null,-1)])]),(0,r.Lk)("ul",X,[(0,r.bF)(o,{to:e.routes.discover,onNavigate:n.closeNavigation},{default:(0,r.k6)(()=>[(0,r.eW)((0,c.v_)(e.$t("ui.navigation.discover")),1)]),_:1},8,["to","onNavigate"]),(0,r.bF)(o,{to:e.routes.packages,onNavigate:n.closeNavigation},{default:(0,r.k6)(()=>[(0,r.eW)((0,c.v_)(e.$t("ui.navigation.packages")),1),n.packageChanges>0?((0,r.uX)(),(0,r.CE)("span",S,(0,c.v_)(n.packageChanges),1)):(0,r.Q3)("",!0)]),_:1},8,["to","onNavigate"]),e.isGranted(n.scopes.UPDATE)?((0,r.uX)(),(0,r.Wv)(o,{key:0,to:e.routes.maintenance,onNavigate:n.closeNavigation},{default:(0,r.k6)(()=>[(0,r.eW)((0,c.v_)(e.$t("ui.navigation.maintenance")),1),e.hasDatabaseChanges||e.hasDatabaseWarning||e.hasDatabaseError?((0,r.uX)(),(0,r.CE)("span",x,"1")):(0,r.Q3)("",!0)]),_:1},8,["to","onNavigate"])):(0,r.Q3)("",!0),(0,r.Lk)("li",T,[(0,r.Lk)("button",null,(0,c.v_)(e.$t("ui.navigation.tools")),1),(0,r.Lk)("ul",M,[e.safeMode?(0,r.Q3)("",!0):((0,r.uX)(),(0,r.CE)("li",O,[(0,r.Lk)("a",{href:n.backendUrl},(0,c.v_)(e.$t("ui.navigation.backend")),9,F)])),!e.safeMode&&e.showAppDev?((0,r.uX)(),(0,r.CE)("li",I,[(0,r.Lk)("a",P,(0,c.v_)(e.$t("ui.navigation.debug")),1)])):(0,r.Q3)("",!0),!e.safeMode&&e.showPreview?((0,r.uX)(),(0,r.CE)("li",R,[(0,r.Lk)("a",{href:n.previewUrl,target:"_blank"},(0,c.v_)(e.$t("ui.navigation.debug")),9,B)])):(0,r.Q3)("",!0),!e.safeMode&&e.showInstallTool?((0,r.uX)(),(0,r.CE)("li",D,[(0,r.Lk)("a",{href:n.installToolUrl,target:"_blank"},(0,c.v_)(e.$t("ui.navigation.installTool")),9,j)])):(0,r.Q3)("",!0),(0,r.bF)(o,{to:e.routes.logViewer,sub:"",onNavigate:n.closeNavigation},{default:(0,r.k6)(()=>[(0,r.eW)((0,c.v_)(e.$t("ui.navigation.logViewer")),1)]),_:1},8,["to","onNavigate"]),(0,r.Lk)("li",U,[(0,r.Lk)("a",{href:"#",onClick:t[1]||(t[1]=(0,A.D$)((...e)=>n.phpinfo&&n.phpinfo(...e),["prevent"]))},(0,c.v_)(e.$t("ui.navigation.phpinfo")),1)])])]),(0,r.Lk)("li",q,[(0,r.Lk)("button",null,[t[5]||(t[5]=(0,r.Lk)("svg",{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 204.993 204.993"},[(0,r.Lk)("path",{d:"M113.711 202.935H92.163c-3.242 0-4.373.007-15.421-27.364l-8.532-3.468c-23.248 10.547-26 10.547-26.92 10.547h-1.779l-1.517-1.303-15.275-14.945c-2.323-2.319-3.128-3.124 8.825-30.137l-3.479-8.231C0 117.977 0 116.81 0 113.496V92.37c0-3.31 0-4.355 27.972-15.171l3.479-8.249c-12.644-26.602-11.774-27.428-9.28-29.776l16.427-16.105 2.04-.064c2.48 0 11.681 3.357 27.371 9.981l8.507-3.454C86.758 2.054 88.015 2.058 91.246 2.058h21.548c3.228 0 4.363.004 15.411 27.382l8.546 3.443c23.212-10.533 26-10.533 26.927-10.533h1.768l1.517 1.281 15.275 14.92c2.323 2.344 3.117 3.146-8.836 30.17l3.489 8.278c28.101 10.014 28.101 11.177 28.101 14.498v21.101c0 3.232 0 4.37-28.008 15.192l-3.457 8.256c12.58 26.487 11.749 27.317 9.394 29.69l-16.552 16.205-2.051.057c-2.469 0-11.649-3.361-27.317-9.992l-8.557 3.457c-10.27 27.472-11.437 27.472-14.733 27.472zm-19.308-8.722h16.996c1.95-3.976 6.166-14.516 9.541-23.595l.68-1.807 15.475-6.249 1.664.705c9.223 3.933 20.124 8.292 24.372 9.631l11.943-11.681c-1.517-4.205-6.116-14.494-10.264-23.173l-.837-1.764 6.403-15.285 1.743-.673c9.316-3.586 20.11-8.013 24.143-10.032V93.88c-4.08-1.918-14.831-6.009-24.096-9.294l-1.814-.648-6.445-15.3.769-1.725c3.965-8.947 8.375-19.501 9.788-23.753l-11.975-11.706c-3.865 1.349-14.688 5.987-23.817 10.153l-1.7.78-15.475-6.238-.691-1.721c-3.658-9.13-8.203-19.716-10.253-23.635H93.569c-1.961 3.965-6.163 14.509-9.53 23.585l-.669 1.797-15.432 6.27-1.664-.712c-9.244-3.926-20.167-8.278-24.429-9.616L29.923 43.805c1.496 4.198 6.109 14.48 10.243 23.159l.848 1.768-6.435 15.278-1.732.669c-9.301 3.582-20.077 8.006-24.111 10.017v16.431c4.08 1.925 14.82 6.027 24.079 9.326l1.8.655 6.446 15.249-.769 1.721c-3.965 8.94-8.371 19.48-9.788 23.724l12 11.742c3.854-1.36 14.663-5.998 23.803-10.168l1.711-.784 15.443 6.277.691 1.721c3.669 9.133 8.2 19.701 10.251 23.623zm8.092-56.56c-19.759 0-35.849-15.772-35.849-35.159 0-19.372 16.087-35.134 35.849-35.134 19.748 0 35.799 15.765 35.799 35.134 0 19.387-16.051 35.159-35.799 35.159zm0-61.563c-14.956 0-27.113 11.846-27.113 26.405 0 14.569 12.154 26.426 27.113 26.426 14.931 0 27.078-11.857 27.078-26.426-.004-14.559-12.147-26.405-27.078-26.405z"})],-1)),(0,r.Lk)("span",null,(0,c.v_)(e.$t("ui.navigation.advanced")),1)]),(0,r.Lk)("ul",W,[e.limited?(0,r.Q3)("",!0):((0,r.uX)(),(0,r.Wv)(o,{key:0,to:e.routes.userManager,sub:"",onNavigate:n.closeNavigation},{default:(0,r.k6)(()=>[(0,r.eW)((0,c.v_)(e.$t("ui.navigation.users")),1)]),_:1},8,["to","onNavigate"])),(0,r.Lk)("li",V,[(0,r.Lk)("a",{href:"#",onClick:t[2]||(t[2]=(0,A.D$)((...e)=>n.systemCheck&&n.systemCheck(...e),["prevent"]))},(0,c.v_)(e.$t("ui.navigation.systemCheck")),1)]),(0,r.Lk)("li",Q,[(0,r.Lk)("a",{href:"#",onClick:t[3]||(t[3]=(0,A.D$)((...e)=>n.doLogout&&n.doLogout(...e),["prevent"]))},(0,c.v_)(e.$t("ui.navigation.logout")),1)])])])],512)])}var G=a(3936),N=a(707);const z=["href","onClick","onKeypress"];function K(e,t,a,s,i,n){const o=(0,r.g2)("router-link");return(0,r.uX)(),(0,r.Wv)(o,{to:a.to,custom:""},{default:(0,r.k6)(({isActive:t,href:s,navigate:i})=>[(0,r.Lk)("li",{class:(0,c.C4)({["navigation__item navigation__item--"+(a.sub?"sub":"main")]:!0,"router-link-active":t})},[(0,r.Lk)("a",{href:s,onClick:e=>n.go(i),onKeypress:(0,A.jR)(e=>n.go(i),["enter"])},[(0,r.RG)(e.$slots,"default")],40,z)],2)]),_:3},8,["to"])}var J={props:{to:Object,sub:Boolean},methods:{go(e){this.$emit("navigate"),e()}}},Z=a(6262);const Y=(0,Z.A)(J,[["render",K]]);var ee=Y,te=a(70),ae={components:{NavigationItem:ee},data:()=>({routes:l.A,databaseChanges:0}),computed:{...(0,g.aH)(["safeMode"]),...(0,g.aH)("auth",["limited"]),...(0,g.aH)("contao/install-tool",{showInstallTool:"isSupported"}),...(0,g.aH)("contao/access-key",{showAppDev:"isEnabled"}),...(0,g.aH)("contao/jwt-cookie",{showPreview:"isDebugEnabled"}),...(0,g.aH)("server/contao",["contaoConfig"]),...(0,g.L8)("auth",["isGranted"]),...(0,g.L8)("packages",["totalChanges"]),...(0,g.L8)("packages/uploads",["totalUploads"]),...(0,g.L8)("server/database",{hasDatabaseChanges:"hasChanges",hasDatabaseWarning:"hasWarning",hasDatabaseError:"hasError"}),scopes:()=>te.A,packageChanges:e=>e.totalChanges+e.totalUploads,backendUrl:e=>e.contaoConfig?.backend?.route_prefix||"/contao",previewUrl:e=>`${e.contaoConfig?.backend?.preview_script||"/preview.php"}/`,installToolUrl:e=>`${e.contaoConfig?.backend?.route_prefix||"/contao"}/install`},methods:{...(0,g.i0)("auth",["logout"]),toggleNavigation(){document.body.classList.toggle("nav-active")},closeNavigation(){document.body.classList.remove("nav-active")},phpinfo(){const e=window.open();e&&(e.document.open(),e.document.write('<p class="phpinfo__loading" style="display: flex; justify-content: center; align-items: center; min-height: 100vh; font: 4vmin -apple-system, system-ui, &quot;Segoe UI&quot;, Roboto, Oxygen-Sans, Ubuntu, Cantarell, &quot;Helvetica Neue&quot;, sans-serif;">'),e.document.write(this.$t("ui.navigation.phpinfoLoading")),e.document.write("</p>"),this.$store.dispatch("server/phpinfo/get").then(t=>{e.document.write(t),e.document.close(),e.document.body.removeChild(e.document.querySelector(".phpinfo__loading"))}))},systemCheck(){this.closeNavigation(),window.localStorage.removeItem("contao_manager_booted"),this.$store.commit("setView",N.A.BOOT)},doLogout(){this.closeNavigation(),this.logout()}},mounted(){new G.A({menuElement:this.$refs.menu,hoverType:"on",submenuItemSelector:".navigation__item--children"}),this.isGranted(te.A.UPDATE)&&(this.$store.dispatch("contao/install-tool/fetch"),this.$store.dispatch("contao/jwt-cookie/get").catch(()=>{}),this.$store.dispatch("contao/access-key/get").catch(()=>{}),this.$store.dispatch("server/database/get"))}};const se=(0,Z.A)(ae,[["render",H]]);var ie=se,ne=a(1218),oe={components:{NavigationFragment:ie,FooterFragment:ne.A},computed:{...(0,g.aH)("algolia",["news"]),...(0,g.L8)("server/contao",["badgeTitle"]),currentNews:e=>e.news.length?e.news[0]:null},mounted(){this.$store.dispatch("server/contao/get")}};const le=(0,Z.A)(oe,[["render",L]]);var re=le,ce=a(1080),ue=a(8875),de={components:{DiscoverList:ce.A,InstallButton:ue.A},computed:{...(0,g.L8)("packages",["packageSuggested","contaoSupported","packageConstraint"]),wrapper:()=>re}};const pe=(0,Z.A)(de,[["render",p]]);var ge=pe;const he={class:"package-list"},me={key:1,class:"package-list__headline"},ke={key:2,class:"package-list__headline"},ve={key:0,class:"package-actions__inner"},be={class:"package-actions__text"},_e=["disabled"],fe={key:1,class:"package-actions__inner"},we={class:"package-actions__text"},ye=["disabled"];function Ce(e,t,a,s,i,n){const o=(0,r.g2)("package-uploads"),l=(0,r.g2)("composer-package"),u=(0,r.g2)("loading-button"),d=(0,r.g2)("cloud-status"),p=(0,r.g2)("link-menu"),g=(0,r.g2)("button-group"),h=(0,r.g2)("package-base");return(0,r.uX)(),(0,r.Wv)(h,{onStartUpload:t[3]||(t[3]=e=>n.openFileSelector())},{actions:(0,r.k6)(()=>[e.hasUploads&&!e.uploading?((0,r.uX)(),(0,r.CE)("div",ve,[(0,r.Lk)("p",be,(0,c.v_)(e.$tc("ui.packages.uploadMessage",e.totalUploads)),1),(0,r.Lk)("button",{class:"package-actions__button widget-button widget-button--primary",disabled:!e.canConfirmUploads||n.removingUploads,onClick:t[0]||(t[0]=(...e)=>n.confirmUploads&&n.confirmUploads(...e))},(0,c.v_)(e.$t("ui.packages.uploadApply")),9,_e),(0,r.bF)(u,{class:"package-actions__button",color:"alert",loading:n.removingUploads,onClick:n.removeUploads},{default:(0,r.k6)(()=>[(0,r.eW)((0,c.v_)(e.$t("ui.packages.uploadReset")),1)]),_:1},8,["loading","onClick"])])):e.totalChanges&&!e.uploading?((0,r.uX)(),(0,r.CE)("div",fe,[(0,r.bF)(d,{"button-class":"package-actions__button package-actions__button--cloud"}),(0,r.Lk)("p",we,(0,c.v_)(e.$tc("ui.packages.changesMessage",e.totalChanges)),1),(0,r.bF)(g,{class:"package-actions__button-group","align-top":"",type:"primary",icon:"update",loading:e.cloudLoading,disabled:e.cloudError||e.packageIncompatible,"more-disabled":e.cloudLoading||e.cloudError||e.packageIncompatible,label:e.$t("ui.packages.changesApply"),onClick:t[1]||(t[1]=t=>e.hasLockFile?n.applyChanges():n.applyChangesAll())},{default:(0,r.k6)(()=>[(0,r.bF)(p,{align:"right",valign:"top",items:n.applyActions,color:"primary"},null,8,["items"])]),_:1},8,["loading","disabled","more-disabled","label"]),(0,r.Lk)("button",{class:"package-actions__button widget-button widget-button--alert",disabled:!e.canResetChanges&&!e.confirmed.length,onClick:t[2]||(t[2]=(...e)=>n.resetChanges&&n.resetChanges(...e))},(0,c.v_)(e.$t("ui.packages.changesReset")),9,ye)])):(0,r.Q3)("",!0)]),default:(0,r.k6)(()=>[(0,r.Lk)("div",he,[!1!==e.uploads&&e.isGranted(n.scopes.INSTALL)?((0,r.uX)(),(0,r.Wv)(o,{key:0,ref:"uploader"},null,512)):(0,r.Q3)("",!0),n.hasAdded?((0,r.uX)(),(0,r.CE)("h2",me,(0,c.v_)(e.$t("ui.packagelist.added")),1)):(0,r.Q3)("",!0),((0,r.uX)(!0),(0,r.CE)(r.FK,null,(0,r.pI)(n.addedPackages,e=>((0,r.uX)(),(0,r.Wv)(l,{data:e,key:e.name},null,8,["data"]))),128)),n.showHeadline?((0,r.uX)(),(0,r.CE)("h2",ke,(0,c.v_)(e.$t("ui.packagelist.installed")),1)):(0,r.Q3)("",!0),((0,r.uX)(!0),(0,r.CE)(r.FK,null,(0,r.pI)(n.installedPackages,e=>((0,r.uX)(),(0,r.Wv)(l,{data:e,key:e.name},null,8,["data"]))),128))])]),_:1})}a(8111),a(2489);const $e={key:0,class:"package-tools"},Le=["disabled"],Ae=["disabled","title"];function Ee(e,t,a,s,i,n){const o=(0,r.g2)("main-layout");return(0,r.uX)(),(0,r.Wv)(o,null,{default:(0,r.k6)(()=>[e.isGranted(n.scopes.UPDATE)?((0,r.uX)(),(0,r.CE)("section",$e,[(0,r.RG)(e.$slots,"search",{},()=>[(0,r.Lk)("button",{class:"package-tools__button widget-button widget-button--update",disabled:e.totalChanges>0||e.uploading,onClick:t[0]||(t[0]=(...t)=>e.updateAll&&e.updateAll(...t))},(0,c.v_)(e.$t("ui.packages.updateButton")),9,Le),(0,r.Lk)("button",{class:"package-tools__button widget-button widget-button--upload",disabled:!e.uploads||e.uploading||!e.isGranted(n.scopes.INSTALL),title:n.uploadError,onClick:t[1]||(t[1]=(0,A.D$)(t=>e.$emit("start-upload"),["prevent"]))},(0,c.v_)(e.$t("ui.packages.uploadButton")),9,Ae)])])):(0,r.Q3)("",!0),(0,r.RG)(e.$slots,"default"),(0,r.Lk)("div",{class:(0,c.C4)({"package-actions":!0,"package-actions--active":!n.slotEmpty(e.$slots.actions)})},[(0,r.RG)(e.$slots,"actions")],2)]),_:3})}var Xe=a(9451),Se={components:{MainLayout:re},computed:{...(0,g.L8)("auth",["isGranted"]),...(0,g.L8)("packages",["totalChanges"]),...(0,g.aH)("packages/uploads",["uploads","uploading"]),scopes:()=>te.A,uploadError:e=>!1===e.uploads?e.$t("ui.packages.uploadUnsupported"):e.isGranted(te.A.INSTALL)?"":e.$t("ui.error.permission")},methods:{slotEmpty:Xe.A,...(0,g.i0)("packages",["updateAll"])}};const xe=(0,Z.A)(Se,[["render",Ee]]);var Te=xe,Me=a(7591);const Oe={key:0},Fe={class:"package-uploads__overlay"},Ie={key:0,class:"package-list__headline"};function Pe(e,t,a,s,i,n){const o=(0,r.g2)("file-upload"),l=(0,r.g2)("uploading-package"),u=(0,r.g2)("uploaded-package");return null!==e.uploads?((0,r.uX)(),(0,r.CE)("div",Oe,[(0,r.bo)((0,r.Lk)("div",Fe,[(0,r.Lk)("div",null,[t[0]||(t[0]=(0,r.Lk)("img",{src:Me,alt:"",width:"128",height:"128"},null,-1)),(0,r.Lk)("p",null,(0,c.v_)(e.$t("ui.packages.uploadOverlay")),1)])],512),[[A.aG,e.$refs.uploader&&e.$refs.uploader.dropActive]]),(0,r.bF)(o,{name:"package",ref:"uploader","post-action":"api/packages/uploads",multiple:!0,drop:!0,"drop-directory":!1,"chunk-enabled":!0,chunk:{action:"api/packages/uploads"},"onUpdate:modelValue":e.setFiles,onInputFile:n.updateFile,onInputFilter:n.filterFile},null,8,["onUpdate:modelValue","onInputFile","onInputFilter"]),e.$refs.uploader?((0,r.uX)(),(0,r.CE)(r.FK,{key:0},[e.hasUploads||e.files.length?((0,r.uX)(),(0,r.CE)("h2",Ie,(0,c.v_)(e.$t("ui.packagelist.uploads")),1)):(0,r.Q3)("",!0),((0,r.uX)(!0),(0,r.CE)(r.FK,null,(0,r.pI)(e.files,e=>((0,r.uX)(),(0,r.Wv)(l,{file:e,key:e.id},null,8,["file"]))),128)),((0,r.uX)(!0),(0,r.CE)(r.FK,null,(0,r.pI)(e.unconfirmedUploads,t=>((0,r.uX)(),(0,r.Wv)(u,{upload:t,uploader:e.$refs.uploader,key:t.id},null,8,["upload","uploader"]))),128))],64)):(0,r.Q3)("",!0)])):(0,r.Q3)("",!0)}a(9112);var Re=a(8568),Be=a.n(Re);const De={class:"package__version package__version--release"};function je(e,t,a,s,i,n){const o=(0,r.g2)("progress-bar"),l=(0,r.g2)("base-package");return(0,r.uX)(),(0,r.Wv)(l,{title:a.file.name},{release:(0,r.k6)(()=>[(0,r.bF)(o,{amount:a.file.progress},null,8,["amount"]),(0,r.Lk)("div",De,[(0,r.Lk)("p",null,[(0,r.Lk)("strong",null,(0,c.v_)(n.filesize),1)])])]),_:1},8,["title"])}const Ue={key:0,class:"package__hint"},qe={class:"package__inside"},We={class:"package__details"},Ve={class:"package__about"},Qe=["title"],He={class:"package__title"},Ge={class:"package__description"},Ne={class:"package__additional"},ze={class:"package__release"},Ke={class:"package__actions"};function Je(e,t,a,s,i,n){const o=(0,r.g2)("package-logo");return(0,r.uX)(),(0,r.CE)("article",{class:(0,c.C4)(["package",a.hint||!n.slotEmpty(e.$slots.hint)?"is--hint":""])},[a.hint||!n.slotEmpty(e.$slots.hint)?((0,r.uX)(),(0,r.CE)("div",Ue,[(0,r.RG)(e.$slots,"hint",{},()=>[a.hintClose?((0,r.uX)(),(0,r.CE)("a",{key:0,href:"#",class:"package__hint-close",onClick:t[0]||(t[0]=(0,A.D$)(t=>e.$emit("close-hint"),["prevent"]))},(0,c.v_)(a.hintClose),1)):(0,r.Q3)("",!0),(0,r.Lk)("p",null,(0,c.v_)(a.hint),1)])])):(0,r.Q3)("",!0),(0,r.Lk)("div",qe,[(0,r.bF)(o,{class:"package__icon",src:a.logo},null,8,["src"]),(0,r.Lk)("div",We,[(0,r.Lk)("div",Ve,[(0,r.Lk)("h1",{class:(0,c.C4)({package__headline:!0,"package__headline--badge":a.badge})},[a.badge?((0,r.uX)(),(0,r.CE)("span",{key:0,class:"package__badge",title:a.badge.title},(0,c.v_)(a.badge.text),9,Qe)):(0,r.Q3)("",!0),(0,r.Lk)("span",He,(0,c.v_)(a.title),1)],2),(0,r.Lk)("p",Ge,(0,c.v_)(a.description),1),(0,r.Lk)("p",Ne,[(0,r.RG)(e.$slots,"additional")])]),(0,r.Lk)("div",ze,[(0,r.RG)(e.$slots,"release",{},()=>[t[1]||(t[1]=(0,r.Lk)("div",null,null,-1))])]),(0,r.Lk)("fieldset",Ke,[(0,r.RG)(e.$slots,"actions",{},()=>[t[2]||(t[2]=(0,r.Lk)("div",null,null,-1))])])])]),(0,r.RG)(e.$slots,"features")],2)}var Ze=a(7423),Ye={components:{PackageLogo:Ze.A},props:{title:String,logo:String,badge:Object,description:String,hint:String,hintClose:String},methods:{slotEmpty:Xe.A}};const et=(0,Z.A)(Ye,[["render",Je]]);var tt=et,at=a(1298),st=a(4960),it={components:{ProgressBar:at.A,BasePackage:tt},props:{file:{type:Object,required:!0}},computed:{filesize:e=>(0,st.A)(e.file.size)}};const nt=(0,Z.A)(it,[["render",je]]);var ot=nt;const lt={class:"package__version package__version--release"},rt={key:0},ct={key:1},ut={key:2},dt=["disabled"];function pt(e,t,a,s,i,n){const o=(0,r.g2)("progress-bar"),l=(0,r.g2)("loading-button"),u=(0,r.g2)("base-package"),d=(0,r.g2)("composer-package");return!a.upload.success||a.upload.error?((0,r.uX)(),(0,r.Wv)(u,{key:0,title:a.upload.name,hint:n.hintUploading},(0,r.eX)({release:(0,r.k6)(()=>[(0,r.bF)(o,{amount:n.progress},null,8,["amount"]),(0,r.Lk)("div",lt,[(0,r.Lk)("p",null,[(0,r.Lk)("strong",null,(0,c.v_)(n.filesize(a.upload.size)),1)])])]),actions:(0,r.k6)(()=>[(0,r.bF)(l,{color:"alert",icon:"trash",loading:n.removing,onClick:n.removeUpload},{default:(0,r.k6)(()=>[(0,r.eW)((0,c.v_)(e.$t("ui.package.removeButton")),1)]),_:1},8,["loading","onClick"])]),_:2},[a.upload.error?{name:"hint",fn:(0,r.k6)(()=>[(0,r.Lk)("p",null,[(0,r.eW)((0,c.v_)(a.upload.error)+" ",1),a.upload.exception?((0,r.uX)(),(0,r.CE)(r.FK,{key:0},[(0,r.eW)((0,c.v_)(a.upload.exception),1)],64)):(0,r.Q3)("",!0)])]),key:"0"}:void 0]),1032,["title","hint"])):((0,r.uX)(),(0,r.Wv)(d,{key:1,"uncloseable-hint":"",data:n.pkg},{hint:(0,r.k6)(()=>[e.isDuplicate(a.upload.id,n.pkg.name)?((0,r.uX)(),(0,r.CE)("p",rt,(0,c.v_)(e.$t("ui.packages.uploadDuplicate")),1)):e.versionInstalled(n.pkg.name,n.pkg.version)?((0,r.uX)(),(0,r.CE)("p",ct,(0,c.v_)(e.$t("ui.packages.uploadInstalled")),1)):n.isCompatible?(0,r.Q3)("",!0):((0,r.uX)(),(0,r.CE)("p",ut,(0,c.v_)(e.$t("ui.package.incompatible",{package:n.pkg.name,constraint:e.packageConstraint("contao/manager-bundle")})),1))]),actions:(0,r.k6)(()=>[(0,r.Lk)("button",{class:"widget-button widget-button--primary widget-button--add",disabled:!n.canBeInstalled,onClick:t[0]||(t[0]=(...e)=>n.addPackage&&n.addPackage(...e))},(0,c.v_)(e.$t("ui.package.installButton")),9,dt),(0,r.bF)(l,{color:"alert",icon:"trash",loading:n.removing,onClick:n.removeUpload},{default:(0,r.k6)(()=>[(0,r.eW)((0,c.v_)(e.$t("ui.package.removeButton")),1)]),_:1},8,["loading","onClick"])]),_:1},8,["data"]))}a(4114);var gt=a(416);const ht={key:0,class:"package__version package__version--additional"},mt=["title"],kt={key:0,class:"package__version-update package__version-update--error"},vt={key:1,class:"package__version-update package__version-update--available"},bt={key:2,class:"package__version-update package__version-update--none"},_t=["title"],ft={key:1,class:"composer-package__stats composer-package__stats--license"},wt=["title"],yt={key:0,class:"package__version package__version--release"},Ct=["title"],$t={key:0,class:"package__version-update package__version-update--error"},Lt={key:1,class:"package__version-update package__version-update--available"},At={key:2,class:"package__version-update package__version-update--none"},Et=["title"],Xt=["disabled"],St=["disabled"],xt=["disabled"],Tt=["disabled"],Mt=["disabled"],Ot={class:"package__features"};function Ft(e,t,a,s,i,n){const o=(0,r.g2)("router-link"),l=(0,r.g2)("package-constraint"),u=(0,r.g2)("details-button"),d=(0,r.g2)("button-group"),p=(0,r.g2)("feature-package"),g=(0,r.g2)("base-package");return(0,r.uX)(),(0,r.Wv)(g,{class:(0,c.C4)({"package--contao":e.isContao}),title:n.packageData.title||a.data.name,logo:n.packageData.logo,badge:n.badge,description:n.packageData.description,hint:n.packageHint,"hint-close":n.packageHintClose,onCloseHint:n.restore},(0,r.eX)({additional:(0,r.k6)(()=>[n.packageData.version?((0,r.uX)(),(0,r.CE)("div",ht,[(0,r.Lk)("strong",{title:n.packageData.time?n.datimFormat(n.packageData.time):""},(0,c.v_)(e.$t("ui.package.version",{version:n.packageData.version})),9,mt),n.packageData.update?((0,r.uX)(),(0,r.CE)(r.FK,{key:0},[n.packageData.update.valid?n.packageData.update.latest?((0,r.uX)(),(0,r.CE)("div",bt,[(0,r.eW)((0,c.v_)(e.$t("ui.package.updateLatest"))+" ",1),n.packageData.latest&&!n.packageData.latest.active?((0,r.uX)(),(0,r.CE)("span",{key:0,class:"package__version-latest",title:e.$t("ui.package.updateConstraint")},null,8,_t)):(0,r.Q3)("",!0)])):((0,r.uX)(),(0,r.CE)("div",vt,(0,c.v_)(e.$t("ui.package.updateAvailable",{version:n.packageData.update.version})),1)):((0,r.uX)(),(0,r.CE)("div",kt,(0,c.v_)(e.$t("ui.package.updateUnknown")),1))],64)):(0,r.Q3)("",!0)])):(0,r.Q3)("",!0),n.license?((0,r.uX)(),(0,r.CE)("span",ft,(0,c.v_)(n.license),1)):(0,r.Q3)("",!0),n.packageData.contaoVersions&&!e.isContao?((0,r.uX)(),(0,r.CE)("ul",{key:2,class:"composer-package__stats composer-package__stats--versions",title:`${e.$t("ui.package.contaoVersion")} ${n.packageData.contaoVersions.join(", ")}`},[((0,r.uX)(!0),(0,r.CE)(r.FK,null,(0,r.pI)(n.packageData.contaoVersions,(e,t)=>((0,r.uX)(),(0,r.CE)("li",{class:"composer-package__stats--version",key:t},(0,c.v_)(e),1))),128))],8,wt)):(0,r.Q3)("",!0),n.packageData.funding?((0,r.uX)(),(0,r.Wv)(o,{key:3,class:"composer-package__stats composer-package__stats--funding",to:{query:{p:a.data.name}}},{default:(0,r.k6)(()=>[...t[5]||(t[5]=[(0,r.eW)(" ",-1)])]),_:1},8,["to"])):(0,r.Q3)("",!0)]),release:(0,r.k6)(()=>[(0,r.RG)(e.$slots,"release",{},()=>[(0,r.bF)(l,{class:"package__constraint",data:a.data},null,8,["data"]),n.packageData.version?((0,r.uX)(),(0,r.CE)("div",yt,[(0,r.Lk)("strong",{title:n.packageData.time?n.datimFormat(n.packageData.time):""},(0,c.v_)(e.$t("ui.package.version",{version:n.packageData.version})),9,Ct),n.packageData.update?((0,r.uX)(),(0,r.CE)(r.FK,{key:0},[n.packageData.update.valid?n.packageData.update.latest?((0,r.uX)(),(0,r.CE)("div",At,[(0,r.eW)((0,c.v_)(e.$t("ui.package.updateLatest"))+" ",1),n.packageData.latest&&!n.packageData.latest.active?((0,r.uX)(),(0,r.CE)("span",{key:0,class:"package__version-latest",title:e.$t("ui.package.updateConstraint")},null,8,Et)):(0,r.Q3)("",!0)])):((0,r.uX)(),(0,r.CE)("div",Lt,(0,c.v_)(e.$t("ui.package.updateAvailable",{version:n.packageData.update.version})),1)):((0,r.uX)(),(0,r.CE)("div",$t,(0,c.v_)(e.$t("ui.package.updateUnknown")),1))],64)):(0,r.Q3)("",!0)])):(0,r.Q3)("",!0)])]),actions:(0,r.k6)(()=>[(0,r.RG)(e.$slots,"actions",{},()=>[a.data.name?((0,r.uX)(),(0,r.Wv)(u,{key:0,name:a.data.name},null,8,["name"])):(0,r.Q3)("",!0),e.isGranted(n.scopes.UPDATE)?((0,r.uX)(),(0,r.CE)(r.FK,{key:1},[e.isContao?((0,r.uX)(),(0,r.CE)(r.FK,{key:0},[e.isRequired?(0,r.Q3)("",!0):((0,r.uX)(),(0,r.CE)("button",{key:0,class:"widget-button widget-button--update",disabled:e.isModified,onClick:t[0]||(t[0]=(...t)=>e.update&&e.update(...t))},(0,c.v_)(e.$t("ui.package.updateButton")),9,Xt))],64)):((0,r.uX)(),(0,r.CE)(r.FK,{key:1},[e.isMissing?((0,r.uX)(),(0,r.CE)("button",{key:0,class:"widget-button widget-button--primary widget-button--add",disabled:e.willBeInstalled,onClick:t[1]||(t[1]=(...t)=>e.install&&e.install(...t))},(0,c.v_)(e.$t("ui.package.installButton")),9,St)):e.isRequired?((0,r.uX)(),(0,r.CE)("button",{key:1,class:"widget-button widget-button--alert widget-button--trash",disabled:e.willBeRemoved,onClick:t[2]||(t[2]=(...t)=>e.uninstall&&e.uninstall(...t))},(0,c.v_)(e.$t("ui.package.removeButton")),9,xt)):e.isRootInstalled?((0,r.uX)(),(0,r.CE)(r.FK,{key:2},[e.isGranted(n.scopes.INSTALL)?((0,r.uX)(),(0,r.Wv)(d,{key:0,label:e.$t("ui.package.updateButton"),icon:"update",disabled:e.isModified,onClick:e.update},{default:(0,r.k6)(()=>[(0,r.Lk)("button",{class:"widget-button widget-button--alert widget-button--trash",disabled:e.willBeRemoved,onClick:t[3]||(t[3]=(...t)=>e.uninstall&&e.uninstall(...t))},(0,c.v_)(e.$t("ui.package.removeButton")),9,Tt)]),_:1},8,["label","disabled","onClick"])):((0,r.uX)(),(0,r.CE)("button",{key:1,class:"widget-button widget-button--update",disabled:e.isModified,onClick:t[4]||(t[4]=(...t)=>e.update&&e.update(...t))},(0,c.v_)(e.$t("ui.package.updateButton")),9,Mt))],64)):(0,r.Q3)("",!0)],64))],64)):(0,r.Q3)("",!0)])]),_:2},[n.slotEmpty(e.$slots.hint)?void 0:{name:"hint",fn:(0,r.k6)(()=>[(0,r.RG)(e.$slots,"hint")]),key:"0"},Object.keys(e.packageFeatures(a.data.name)||{}).length?{name:"features",fn:(0,r.k6)(()=>[(0,r.Lk)("section",Ot,[((0,r.uX)(!0),(0,r.CE)(r.FK,null,(0,r.pI)(Object.keys(e.packageFeatures(a.data.name)),e=>((0,r.uX)(),(0,r.Wv)(p,{name:e,key:e},null,8,["name"]))),128))])]),key:"1"}:void 0]),1032,["class","title","logo","badge","description","hint","hint-close","onCloseHint"])}var It=a(4210),Pt=a(266),Rt=a(8200);const Bt={key:0,class:"feature-package"},Dt={class:"feature-package__name"},jt={key:0,class:"feature-package__hint"},Ut=["title"],qt=["title"],Wt={class:"feature-package__actions"},Vt=["title"];function Qt(e,t,a,s,i,n){const o=(0,r.g2)("details-button");return e.isRequired||e.isMissing||e.isRootInstalled||e.willBeInstalled?((0,r.uX)(),(0,r.CE)("article",Bt,[(0,r.Lk)("p",{class:(0,c.C4)(["feature-package__text",{"feature-package__text--hint":this.packageHint}])},[(0,r.Lk)("strong",Dt,(0,c.v_)(n.packageTitle),1),this.packageHint?((0,r.uX)(),(0,r.CE)("span",jt,(0,c.v_)(n.packageHint),1)):e.isMissing?((0,r.uX)(),(0,r.CE)("span",{key:1,class:"feature-package__badge",title:e.$t("ui.package.removedText")},(0,c.v_)(e.$t("ui.package.removedTitle")),9,Ut)):e.isRequired?((0,r.uX)(),(0,r.CE)("span",{key:2,class:"feature-package__badge",title:e.$t("ui.package.requiredText")},(0,c.v_)(e.$t("ui.package.requiredTitle")),9,qt)):((0,r.uX)(),(0,r.CE)(r.FK,{key:3},[(0,r.eW)((0,c.v_)(e.metadata.description),1)],64))],2),(0,r.Lk)("div",Wt,[n.packageHint&&e.isGranted(n.scopes.INSTALL)?((0,r.uX)(),(0,r.CE)("button",{key:0,class:"feature-package__restore",onClick:t[0]||(t[0]=(...e)=>n.restore&&n.restore(...e))},(0,c.v_)(e.$t("ui.package.hintRevert")),1)):(0,r.Q3)("",!0),(0,r.bF)(o,{small:"",name:a.name},null,8,["name"]),(e.isRequired||e.isRootInstalled)&&!e.willBeRemoved&&e.isGranted(n.scopes.INSTALL)?((0,r.uX)(),(0,r.CE)("button",{key:1,title:e.$t("ui.package.removeButton"),class:"widget-button widget-button--alert widget-button--trash widget-button--small",onClick:t[1]||(t[1]=(...t)=>e.uninstall&&e.uninstall(...t))},null,8,Vt)):(0,r.Q3)("",!0)])])):(0,r.Q3)("",!0)}var Ht=a(9071),Gt={mixins:[Rt.A],components:{DetailsButton:Ht.A},props:{name:String,reason:String},computed:{...(0,g.L8)("auth",["isGranted"]),scopes:()=>te.A,data:e=>({name:e.name}),packageTitle(){return this.metadata?.name?this.metadata.title||this.metadata.name:this.data.name},packageHint(){return this.willBeRemoved?this.$t("ui.package.hintRemoved"):this.willBeInstalled?this.$t("ui.package.hintAdded"):null}},methods:{restore(){this.$store.commit("packages/restore",this.data.name)}}};const Nt=(0,Z.A)(Gt,[["render",Qt]]);var zt=Nt,Kt=a(4290),Jt=a(4676),Zt={mixins:[Rt.A],components:{BasePackage:tt,FeaturePackage:zt,PackageConstraint:Kt.A,ButtonGroup:Jt.A,DetailsButton:Ht.A},props:{data:{type:Object,required:!0},hint:String,uncloseableHint:Boolean},computed:{...(0,g.L8)("auth",["isGranted"]),...(0,g.L8)("packages",["packageFeatures"]),scopes:()=>te.A,packageData:e=>Object.assign({},e.data,e.installed[e.data.name]||{},e.metadata||{}),license:e=>e.packageData.license instanceof Array?e.packageData.license.join("/"):e.packageData.license,packageHint(){return this.hint?this.hint:this.willBeRemoved||this.isMissing&&!this.willBeInstalled?this.$t("ui.package.hintRemoved"):this.isRequired?this.$t("ui.package.hintConstraint",{constraint:this.constraintRequired}):this.willBeInstalled?this.constraintAdded?this.$t("ui.package.hintConstraint",{constraint:this.constraintAdded}):this.isCompatible?this.$t("ui.package.hintConstraintBest"):this.$t("ui.package.incompatibleConstraint",{constraint:this.packageConstraint("contao/manager-bundle")}):this.isChanged?this.$t("ui.package.hintConstraintChange",{from:this.constraintInstalled,to:this.constraintChanged}):this.isUpdated?this.$t("ui.package.hintConstraintUpdate"):null},packageHintClose(){return this.uncloseableHint||this.isRequired&&!this.willBeRemoved&&!this.isChanged||this.isMissing&&!this.willBeInstalled?null:this.isUpdated?this.$t("ui.package.hintNoupdate"):this.$t("ui.package.hintRevert")},packageUpdates(){return this.isInstalled&&(Object.keys(this.$store.state.packages.add).length>0||Object.keys(this.$store.state.packages.change).length>0||this.$store.state.packages.update.length>0||this.$store.state.packages.remove.length>0)},badge(){return this.isRequired?{title:this.$t("ui.package.requiredText"),text:this.$t("ui.package.requiredTitle")}:this.isMissing?{title:this.$t("ui.package.removedText"),text:this.$t("ui.package.removedTitle")}:this.packageData.abandoned?{title:!0===this.packageData.abandoned?this.$t("ui.package.abandonedText"):this.$t("ui.package.abandonedReplace",{replacement:this.packageData.abandoned}),text:this.$t("ui.package.abandoned")}:null}},methods:{datimFormat:It.A,numberFormat:Pt.A,slotEmpty:Xe.A,restore(){this.$store.commit("packages/restore",this.data.name),this.$store.dispatch("packages/uploads/unconfirm",this.data.name)}}};const Yt=(0,Z.A)(Zt,[["render",Ft]]);var ea=Yt,ta=a(5506),aa={mixins:[gt.A],components:{ProgressBar:at.A,BasePackage:tt,ComposerPackage:ea,LoadingButton:ta.A},props:{upload:{type:Object,required:!0},uploader:{type:Object,required:!0}},computed:{...(0,g.L8)("packages",["packageRemoved","versionInstalled","contaoSupported","packageConstraint"]),...(0,g.L8)("packages/uploads",["isDuplicate","isRemoving"]),removing:e=>e.isRemoving(e.upload.id),progress:e=>100/e.upload.size*e.upload.filesize,isTheme:e=>"contao-theme"===e.data.type,isCompatible:e=>!e.data.require||e.contaoSupported(e.data.require["contao/core-bundle"]||e.data.require["contao/manager-bundle"]||null),canBeInstalled:e=>!e.isDuplicate(e.upload.id,e.pkg.name)&&!e.versionInstalled(e.pkg.name,e.pkg.version)&&!e.removing&&!e.packageRemoved(e.pkg.name)&&!e.isTheme&&e.isCompatible,data:e=>e.upload.package||{name:""},pkg:e=>Object.assign({name:e.upload.name,version:null},e.upload.package||{}),hintUploading(){return this.upload.error?this.upload.error:this.upload.size!==this.upload.filesize?this.$t("ui.packages.uploadIncomplete"):""},additional(){const e=[];return this.pkg.license&&(this.pkg.license instanceof Array?e.push(this.pkg.license.join("/")):e.push(this.pkg.license)),this.pkg.downloads&&e.push(this.$tc("ui.package.additionalDownloads",this.pkg.downloads)),this.pkg.favers&&e.push(this.$tc("ui.package.additionalStars",this.pkg.favers)),e}},methods:{filesize:st.A,addPackage(){this.$store.dispatch("packages/uploads/confirm",this.upload.id)},removeUpload(){this.$store.dispatch("packages/uploads/remove",this.upload.id)}}};const sa=(0,Z.A)(aa,[["render",pt]]);var ia=sa,na={components:{FileUpload:Be(),UploadingPackage:ot,UploadedPackage:ia},computed:{...(0,g.aH)("packages/uploads",["uploads","files"]),...(0,g.L8)("packages/uploads",["hasUploads","unconfirmedUploads"])},methods:{...(0,g.PY)("packages/uploads",["setUploading","setFiles"]),openFileSelector(){this.$refs.uploader&&this.$refs.uploader.$el.querySelector("input").click()},async filterFile(e,t,a){if(e&&!t&&!/\.zip$/i.test(e.name))return a()},async updateFile(e,t){this.setUploading(!this.$refs.uploader.uploaded),!t||e?(e.error&&e.xhr&&(401===e.xhr.status?this.$store.commit("setView",N.A.LOGIN):"application/problem+json"===e.xhr.getResponseHeader("Content-Type")&&this.$store.commit("setError",JSON.parse(e.response))),Boolean(e)===Boolean(t)&&t.error===e.error||this.$refs.uploader.active||(this.$refs.uploader.active=!0),this.$refs.uploader.uploaded&&e&&t&&!e.active&&t.active&&(await this.$store.dispatch("packages/uploads/load"),this.$refs.uploader.remove(e))):this.$refs.uploader.uploaded&&!this.$refs.uploader.active&&this.setFiles([])}}};const oa=(0,Z.A)(na,[["render",Pe]]);var la=oa;const ra={class:"cloud-status__headline"},ca={class:"cloud-status__version"},ua={class:"widget-button widget-button--info widget-button--link widget-button--small cloud-status__link",href:"https://composer-resolver-cloud.statuspage.io/",target:"_blank",rel:"noreferrer noopener"},da={key:1,class:"cloud-status__popup cloud-status__popup--error",tabindex:"-1"},pa={class:"cloud-status__headline cloud-status__headline--error"},ga={class:"cloud-status__error"},ha={class:"widget-button widget-button--info widget-button--link widget-button--small cloud-status__link",href:"https://composer-resolver-cloud.statuspage.io/",target:"_blank",rel:"noreferrer noopener"},ma=["title"];function ka(e,t,a,s,i,n){const o=(0,r.g2)("loading-button");return e.enabled?((0,r.uX)(),(0,r.CE)("div",{key:0,class:"cloud-status",onMouseenter:t[3]||(t[3]=(...e)=>n.open&&n.open(...e)),onMouseleave:t[4]||(t[4]=(...e)=>n.close&&n.close(...e))},[(0,r.bF)(o,{class:(0,c.C4)(`cloud-status__button ${a.buttonClass}`),color:"info",icon:e.hasError?"cloud-off":"cloud",loading:e.isLoading,disabled:e.hasError,onClick:n.open},{default:(0,r.k6)(()=>[e.isReady?((0,r.uX)(),(0,r.CE)(r.FK,{key:0},[(0,r.eW)((0,c.v_)(e.$t("ui.cloudStatus.approx",{minutes:n.approxMinutes})),1)],64)):(0,r.Q3)("",!0)]),_:1},8,["class","icon","loading","disabled","onClick"]),e.isReady?(0,r.bo)(((0,r.uX)(),(0,r.CE)("div",{key:0,ref:"menu",class:"cloud-status__popup",tabindex:"-1",onFocusout:t[0]||(t[0]=(...e)=>n.close&&n.close(...e)),onClick:t[1]||(t[1]=(...e)=>n.open&&n.open(...e))},[(0,r.Lk)("h2",ra,(0,c.v_)(e.$t("ui.cloudStatus.headline")),1),(0,r.Lk)("p",ca,(0,c.v_)(e.$t("ui.cloudStatus.version",{version:e.status.appVersion})),1),(0,r.Lk)("table",null,[(0,r.Lk)("tbody",null,[(0,r.Lk)("tr",null,[(0,r.Lk)("th",null,(0,c.v_)(e.$t("ui.cloudStatus.waitingTime"))+":",1),(0,r.Lk)("td",null,(0,c.v_)(n.waitingLabel),1)]),(0,r.Lk)("tr",null,[(0,r.Lk)("th",null,(0,c.v_)(e.$t("ui.cloudStatus.jobs"))+":",1),(0,r.Lk)("td",null,(0,c.v_)(e.status.numberOfJobsInQueue>0?e.status.numberOfJobsInQueue+e.status.numberOfWorkers:`≤ ${e.status.numberOfWorkers}`),1)]),(0,r.Lk)("tr",null,[(0,r.Lk)("th",null,(0,c.v_)(e.$t("ui.cloudStatus.workers"))+":",1),(0,r.Lk)("td",null,(0,c.v_)(e.status.numberOfWorkers),1)])])]),(0,r.Lk)("a",ua,(0,c.v_)(e.$t("ui.cloudStatus.button")),1)],544)),[[A.aG,e.visible]]):e.hasError?((0,r.uX)(),(0,r.CE)("div",da,[(0,r.Lk)("h2",pa,(0,c.v_)(e.$t("ui.cloudStatus.headline")),1),(0,r.Lk)("p",ga,(0,c.v_)(e.$t("ui.cloudStatus.error")),1),(0,r.Lk)("a",ha,(0,c.v_)(e.$t("ui.cloudStatus.button")),1),(0,r.Lk)("button",{class:"widget-button widget-button--update widget-button--small",onClick:t[2]||(t[2]=(...e)=>n.refreshCloud&&n.refreshCloud(...e)),title:e.$t("ui.cloudStatus.approxError")},null,8,ma)])):(0,r.Q3)("",!0)],32)):(0,r.Q3)("",!0)}var va={components:{LoadingButton:ta.A},props:{buttonClass:String},data:()=>({visible:!1,timeout:null,mouseout:null}),computed:{...(0,g.aH)("cloud",["enabled","status"]),...(0,g.L8)("cloud",["isLoading","isReady","hasError"]),waitingTime:e=>Math.round(e.status.numberOfJobsInQueue*(e.status.averageProcessingTimeInMs/1e3)/Math.max(e.status.numberOfWorkers,1)),waitingMinutes:e=>Math.floor(e.waitingTime/60),waitingSeconds:e=>e.waitingTime-60*e.waitingMinutes,approxMinutes:e=>Math.round(e.waitingTime/60),waitingLabel(){return this.waitingTime?this.waitingSeconds?this.$t("ui.cloudStatus.long",{minutes:this.waitingMinutes,seconds:this.waitingSeconds}):this.$t("ui.cloudStatus.short",{minutes:this.waitingMinutes}):this.$t("ui.cloudStatus.none")}},methods:{open(){this.visible=!0,setTimeout(()=>this.$refs.menu?.focus(),0)},close(e){e&&this.$refs.menu?.contains(e.relatedTarget)||(this.$refs.menu.blur(),setTimeout(()=>{this.visible=!1},100))},refreshCloud(){this.$store.commit("cloud/setStatus",null),this.fetchCloud()},async fetchCloud(){await this.$store.dispatch("cloud/fetch"),this.enabled&&!this.hasError&&(this.timeout=setTimeout(this.fetchCloud,6e4))}},mounted(){this.fetchCloud()},beforeUnmount(){clearTimeout(this.timeout)}};const ba=(0,Z.A)(va,[["render",ka]]);var _a=ba,fa=a(4758);const wa=(e,t)=>"contao/manager-bundle"===e.name?-1:"contao/manager-bundle"===t.name?1:0;var ya={components:{PackageBase:Te,PackageUploads:la,ComposerPackage:ea,LoadingButton:ta.A,CloudStatus:_a,ButtonGroup:Jt.A,LinkMenu:fa.A},data:()=>({hasLockFile:!0}),computed:{...(0,g.L8)("auth",["isGranted"]),...(0,g.L8)("cloud",{cloudLoading:"isLoading",cloudError:"hasError"}),...(0,g.aH)("packages",{requiredPackages:"required"}),...(0,g.aH)("packages/uploads",["uploads","uploading","files","removing","confirmed"]),...(0,g.L8)("packages",["totalChanges","packageMissing","packageIncompatible","canResetChanges","visibleRequired","visibleInstalled","visibleAdded"]),...(0,g.L8)("packages/uploads",["hasUploads","totalUploads","canConfirmUploads"]),scopes:()=>te.A,addedPackages:e=>e.visibleRequired.concat(e.visibleAdded).filter(t=>!e.packageMissing(t.name)).sort(wa),installedPackages:e=>e.visibleRequired.filter(t=>e.packageMissing(t.name)).concat(e.visibleInstalled).sort(wa),removingUploads:e=>e.removing.length>0,showHeadline:e=>e.installedPackages.length>0&&(e.hasAdded||e.hasUploads||e.files.length),hasAdded:e=>e.addedPackages.length,applyActions(){return this.hasLockFile?[{label:this.$t("ui.packages.changesDryrun"),action:this.dryrunChanges},{label:this.$t("ui.packages.changesDryrunAll"),action:this.dryrunChangesAll},{label:this.$t("ui.packages.changesApplyAll"),action:this.applyChangesAll}]:[{label:this.$t("ui.packages.changesDryrun"),action:this.dryrunChanges}]}},methods:{openFileSelector(){this.$refs.uploader&&this.isGranted(te.A.INSTALL)&&this.$refs.uploader.openFileSelector()},confirmUploads(){this.$store.dispatch("packages/uploads/confirmAll")},async removeUploads(){await this.$store.dispatch("packages/uploads/removeAll")},dryrunChanges(){this.$store.dispatch("packages/apply",{dry_run:!0})},dryrunChangesAll(){this.$store.dispatch("packages/apply",{dry_run:!0,update_all:!0})},async applyChanges(){try{await this.$store.dispatch("packages/apply"),await this.$store.dispatch("packages/load")}catch(e){await this.$store.dispatch("packages/load",!1)}await this.$store.dispatch("packages/uploads/load")},async applyChangesAll(){try{await this.$store.dispatch("packages/apply",{update_all:!0}),await this.$store.dispatch("packages/load")}catch(e){await this.$store.dispatch("packages/load",!1)}await this.$store.dispatch("packages/uploads/load")},resetChanges(){this.$store.commit("packages/reset"),this.$store.dispatch("packages/uploads/unconfirmAll")}},mounted(){this.$store.dispatch("server/composer/get").then(e=>{this.hasLockFile=e.lock.found})}};const Ca=(0,Z.A)(ya,[["render",Ce]]);var $a=Ca;function La(e,t,a,s,i,n){const o=(0,r.g2)("rebuild-cache"),l=(0,r.g2)("database-status"),c=(0,r.g2)("maintenance-mode"),u=(0,r.g2)("install-tool"),d=(0,r.g2)("debug-mode"),p=(0,r.g2)("dump-autoload"),g=(0,r.g2)("composer-install"),h=(0,r.g2)("composer-cache"),m=(0,r.g2)("opcode-cache"),k=(0,r.g2)("main-layout");return(0,r.uX)(),(0,r.Wv)(k,null,{default:(0,r.k6)(()=>[(0,r.bF)(o),(0,r.bF)(l),(0,r.bF)(c),(0,r.bF)(u),(0,r.bF)(d),(0,r.bF)(p),(0,r.bF)(g),(0,r.bF)(h),(0,r.bF)(m)]),_:1})}const Aa={class:"maintenance"},Ea={class:"maintenance__inside"},Xa={class:"maintenance__about"},Sa={key:0,class:"maintenance__error"},xa={key:1,class:"maintenance__warning"},Ta={key:2,class:"maintenance__warning"},Ma={key:3,class:"maintenance__warning"},Oa={key:0},Fa={key:1},Ia={key:2},Pa={class:"maintenance__actions"},Ra={key:1,class:"widget-button widget-button--alert",href:"/contao/install"};function Ba(e,t,a,s,i,n){const o=(0,r.g2)("loading-spinner"),l=(0,r.g2)("link-menu"),u=(0,r.g2)("button-group"),d=(0,r.g2)("loading-button"),p=(0,r.g2)("message-overlay");return(0,r.uX)(),(0,r.Wv)(p,{message:n.overlayMessage,active:e.safeMode||!1===e.supported},{default:(0,r.k6)(()=>[(0,r.Lk)("section",Aa,[(0,r.Lk)("div",Ea,[t[2]||(t[2]=(0,r.Lk)("figure",{class:"maintenance__image"},[(0,r.Lk)("img",{src:h,alt:""})],-1)),(0,r.Lk)("div",Xa,[(0,r.Lk)("h1",null,[(0,r.eW)((0,c.v_)(e.$t("ui.maintenance.database.title"))+" ",1),e.hasError?((0,r.uX)(),(0,r.CE)("span",Sa,(0,c.v_)(e.$t("ui.maintenance.database.error")),1)):(0,r.Q3)("",!0),e.hasWarning?((0,r.uX)(),(0,r.CE)("span",xa,(0,c.v_)(e.$t("ui.maintenance.database.warning")),1)):e.totalMigrations?((0,r.uX)(),(0,r.CE)("span",Ta,(0,c.v_)(e.$tc("ui.maintenance.database.migrations",e.totalMigrations)),1)):e.totalSchemaUpdates?((0,r.uX)(),(0,r.CE)("span",Ma,(0,c.v_)(e.$tc("ui.maintenance.database.schemaUpdates",e.totalSchemaUpdates)),1)):(0,r.Q3)("",!0)]),(0,r.Lk)("p",null,(0,c.v_)(e.$t("ui.maintenance.database.description")),1),t[1]||(t[1]=(0,r.Lk)("br",null,null,-1)),e.supportsBackups||e.loadingBackups?e.supportsBackups&&e.backupFiles.length?((0,r.uX)(),(0,r.CE)("p",Fa,(0,c.v_)(e.$tc("ui.maintenance.database.backupList",e.backupFiles.length,{date:n.datimFormat(e.backupFiles[0].createdAt)})),1)):e.supportsBackups?((0,r.uX)(),(0,r.CE)("p",Ia,(0,c.v_)(e.$t("ui.maintenance.database.backupEmpty")),1)):(0,r.Q3)("",!0):((0,r.uX)(),(0,r.CE)("p",Oa,(0,c.v_)(e.$t("ui.maintenance.database.backupUnsupported")),1))]),(0,r.Lk)("fieldset",Pa,[e.loading?((0,r.uX)(),(0,r.Wv)(o,{key:0,class:"maintenance__loader"})):e.hasError&&!e.supported?((0,r.uX)(),(0,r.CE)("a",Ra,(0,c.v_)(e.$t("ui.maintenance.database.installTool")),1)):e.hasError?((0,r.uX)(),(0,r.CE)("button",{key:2,class:"widget-button widget-button--alert",onClick:t[0]||(t[0]=(...e)=>n.checkMigrations&&n.checkMigrations(...e))},(0,c.v_)(e.$t("ui.maintenance.database.button")),1)):((0,r.uX)(),(0,r.Wv)(u,{key:3,label:e.$t("ui.maintenance.database.button"),type:e.hasChanges||e.hasWarning?"warning":"primary",icon:"database",onClick:n.checkMigrations},{default:(0,r.k6)(()=>[(0,r.bF)(l,{align:"right",items:n.advancedActions(),color:e.hasChanges?"warning":"primary"},null,8,["items","color"])]),_:1},8,["label","type","onClick"])),(0,r.bF)(d,{class:"widget-button",onClick:n.createBackup,disabled:!e.supportsBackups,loading:e.loadingBackups},{default:(0,r.k6)(()=>[(0,r.eW)((0,c.v_)(e.$t("ui.maintenance.database.createBackup")),1)]),_:1},8,["onClick","disabled","loading"])])])])]),_:1},8,["message","active"])}const Da={class:"message-overlay"},ja={key:0,class:"message-overlay__overlay"},Ua={class:"message-overlay__message"};function qa(e,t,a,s,i,n){return(0,r.uX)(),(0,r.CE)("div",Da,[(0,r.Lk)("div",{class:(0,c.C4)({"message-overlay__blur":a.active})},[(0,r.RG)(e.$slots,"default")],2),a.active?((0,r.uX)(),(0,r.CE)("div",ja,[(0,r.Lk)("span",Ua,(0,c.v_)(a.message),1)])):(0,r.Q3)("",!0)])}var Wa={props:{message:{type:String,required:!0},active:{type:Boolean,required:!0}}};const Va=(0,Z.A)(Wa,[["render",qa]]);var Qa=Va,Ha=a(9045),Ga={components:{MessageOverlay:Qa,LoadingSpinner:Ha.A,ButtonGroup:Jt.A,LinkMenu:fa.A,LoadingButton:ta.A},computed:{...(0,g.aH)(["safeMode"]),...(0,g.aH)("server/database",["loading","supported","status"]),...(0,g.aH)("contao/backup",{supportsBackups:"supported",backupFiles:"files",loadingBackups:"loading"}),...(0,g.L8)("server/database",["hasError","hasChanges","hasWarning","totalMigrations","totalSchemaUpdates"]),overlayMessage:e=>e.safeMode?e.$t("ui.maintenance.safeMode"):e.$t("ui.maintenance.unsupported")},methods:{datimFormat(e){return(0,It.A)(e,"short","long")},checkMigrations(){this.$store.commit("checkMigrations")},advancedActions(){return[{label:this.$t("ui.maintenance.database.migrationOnly"),action:()=>{this.$store.commit("checkMigrations","migrations-only")}},{label:this.$t("ui.maintenance.database.schemaOnly"),action:()=>{this.$store.commit("checkMigrations","schema-only")}}]},async createBackup(){await this.$store.dispatch("tasks/execute",{name:"contao/backup-create"}),await this.$store.dispatch("contao/backup/fetch",!1)}},mounted(){this.$store.dispatch("server/database/get"),this.$store.dispatch("contao/backup/fetch")}};const Na=(0,Z.A)(Ga,[["render",Ba]]);var za=Na,Ka=a.p+"img/symfony-logo.5c162c73.svg",Ja=a.p+"img/symfony-logo--dark.ea265042.svg";const Za={class:"maintenance"},Ya={class:"maintenance__inside"},es={class:"maintenance__about"},ts={class:"maintenance__actions"};function as(e,t,a,s,i,n){const o=(0,r.g2)("link-menu"),l=(0,r.g2)("button-group");return(0,r.uX)(),(0,r.CE)("section",Za,[(0,r.Lk)("div",Ya,[t[0]||(t[0]=(0,r.Lk)("figure",{class:"maintenance__image"},[(0,r.Lk)("img",{class:"color-scheme--light",src:Ka,alt:""}),(0,r.Lk)("img",{class:"color-scheme--dark",src:Ja,alt:""})],-1)),(0,r.Lk)("div",es,[(0,r.Lk)("h1",null,(0,c.v_)(e.$t("ui.maintenance.rebuildCache.title")),1),(0,r.Lk)("p",null,(0,c.v_)(e.$t("ui.maintenance.rebuildCache.description")),1)]),(0,r.Lk)("fieldset",ts,[(0,r.bF)(l,{label:e.$t("ui.maintenance.rebuildCache.rebuildProd"),type:"primary",icon:"update",onClick:n.rebuildProd},{default:(0,r.k6)(()=>[(0,r.bF)(o,{align:"right",items:n.advancedActions(),color:"primary"},null,8,["items"])]),_:1},8,["label","onClick"])])])])}var ss={components:{ButtonGroup:Jt.A,LinkMenu:fa.A},methods:{advancedActions(){return[{label:this.$t("ui.maintenance.rebuildCache.rebuildDev"),action:this.rebuildDev},{label:this.$t("ui.maintenance.rebuildCache.clearProd"),action:this.clearProd},{label:this.$t("ui.maintenance.rebuildCache.clearDev"),action:this.clearDev}]},rebuildProd(){this.execute("prod",!0)},rebuildDev(){this.execute("dev",!0)},clearProd(){this.execute("prod",!1)},clearDev(){this.execute("dev",!1)},execute(e,t){const a={name:"contao/rebuild-cache",config:{environment:e,warmup:t}};this.$store.dispatch("tasks/execute",a)}}};const is=(0,Z.A)(ss,[["render",as]]);var ns=is;const os={class:"maintenance"},ls={class:"maintenance__inside"},rs={class:"maintenance__about"},cs={key:0,class:"maintenance__actions"};function us(e,t,a,s,i,n){const o=(0,r.g2)("loading-spinner"),l=(0,r.g2)("loading-button"),u=(0,r.g2)("message-overlay");return(0,r.uX)(),(0,r.Wv)(u,{message:n.overlayMessage,active:e.safeMode||!1===e.isSupported},{default:(0,r.k6)(()=>[(0,r.Lk)("section",os,[(0,r.Lk)("div",ls,[t[0]||(t[0]=(0,r.Lk)("figure",{class:"maintenance__image"},[(0,r.Lk)("img",{src:h,alt:""})],-1)),(0,r.Lk)("div",rs,[(0,r.Lk)("h1",null,(0,c.v_)(e.$t("ui.maintenance.installTool.title")),1),(0,r.Lk)("p",null,(0,c.v_)(e.$t("ui.maintenance.installTool.description")),1)]),e.safeMode||!1===e.isSupported?(0,r.Q3)("",!0):((0,r.uX)(),(0,r.CE)("fieldset",cs,[null===e.isLocked?((0,r.uX)(),(0,r.Wv)(o,{key:0,class:"maintenance__loader"})):e.isLocked?((0,r.uX)(),(0,r.Wv)(l,{key:1,class:"widget-button widget-button--primary widget-button--unlock",loading:e.loading,disabled:!e.isSupported,onClick:n.unlock},{default:(0,r.k6)(()=>[(0,r.eW)((0,c.v_)(e.$t("ui.maintenance.installTool.unlock")),1)]),_:1},8,["loading","disabled","onClick"])):((0,r.uX)(),(0,r.Wv)(l,{key:2,class:"widget-button widget-button--primary widget-button--lock",loading:e.loading,disabled:!e.isSupported,onClick:n.lock},{default:(0,r.k6)(()=>[(0,r.eW)((0,c.v_)(e.$t("ui.maintenance.installTool.lock")),1)]),_:1},8,["loading","disabled","onClick"]))]))])])]),_:1},8,["message","active"])}var ds={components:{MessageOverlay:Qa,LoadingSpinner:Ha.A,LoadingButton:ta.A},data:()=>({loading:!1}),computed:{...(0,g.aH)(["safeMode"]),...(0,g.aH)("contao/install-tool",["isLocked","isSupported"]),overlayMessage:e=>e.safeMode?e.$t("ui.maintenance.safeMode"):e.$t("ui.maintenance.unsupported")},methods:{async unlock(){this.loading=!0,await this.$store.dispatch("contao/install-tool/unlock"),this.loading=!1},async lock(){this.loading=!0,await this.$store.dispatch("contao/install-tool/lock"),this.loading=!1}},mounted(){this.$store.dispatch("contao/install-tool/fetch")}};const ps=(0,Z.A)(ds,[["render",us]]);var gs=ps;const hs={class:"maintenance"},ms={class:"maintenance__inside"},ks={class:"maintenance__about"},vs={key:0},bs={key:0,class:"maintenance__actions"},_s={key:1,class:"maintenance__actions"},fs={key:2,class:"maintenance__actions"};function ws(e,t,a,s,i,n){const o=(0,r.g2)("i18n-t"),l=(0,r.g2)("loading-spinner"),u=(0,r.g2)("loading-button"),d=(0,r.g2)("message-overlay");return(0,r.uX)(),(0,r.Wv)(d,{message:n.overlayMessage,active:e.safeMode||!e.loading&&!e.supportsJwtCookie&&!e.supportsAccessKey},{default:(0,r.k6)(()=>[(0,r.Lk)("section",hs,[(0,r.Lk)("div",ms,[t[1]||(t[1]=(0,r.Lk)("figure",{class:"maintenance__image"},[(0,r.Lk)("img",{src:h,alt:""})],-1)),(0,r.Lk)("div",ks,[(0,r.Lk)("h1",null,(0,c.v_)(e.$t("ui.maintenance.debugMode.title")),1),e.supportsJwtCookie?((0,r.uX)(),(0,r.CE)("p",vs,(0,c.v_)(e.$t("ui.maintenance.debugMode.descriptionJwt")),1)):e.supportsAccessKey?((0,r.uX)(),(0,r.Wv)(o,{key:1,tag:"p",keypath:"ui.maintenance.debugMode.description"},{appDevPhp:(0,r.k6)(()=>[...t[0]||(t[0]=[(0,r.Lk)("code",null,"app_dev.php",-1)])]),_:1})):(0,r.Q3)("",!0)]),!e.loading||e.supportsJwtCookie||e.supportsAccessKey?e.supportsJwtCookie?((0,r.uX)(),(0,r.CE)("fieldset",_s,[e.hasJwtDebug?((0,r.uX)(),(0,r.Wv)(u,{key:1,class:"widget-button widget-button--alert widget-button--hide",loading:e.loading,onClick:n.removeJwtCookie},{default:(0,r.k6)(()=>[(0,r.eW)((0,c.v_)(e.$t("ui.maintenance.debugMode.deactivate")),1)]),_:1},8,["loading","onClick"])):((0,r.uX)(),(0,r.Wv)(u,{key:0,class:"widget-button widget-button--primary widget-button--show",loading:e.loading,onClick:n.enableJwtDebugMode},{default:(0,r.k6)(()=>[(0,r.eW)((0,c.v_)(e.$t("ui.maintenance.debugMode.activate")),1)]),_:1},8,["loading","onClick"]))])):e.supportsAccessKey?((0,r.uX)(),(0,r.CE)("fieldset",fs,[e.hasAccessKey?((0,r.uX)(),(0,r.Wv)(u,{key:1,class:"widget-button widget-button--alert widget-button--hide",loading:e.loading,onClick:n.removeAccessKey},{default:(0,r.k6)(()=>[(0,r.eW)((0,c.v_)(e.$t("ui.maintenance.debugMode.deactivate")),1)]),_:1},8,["loading","onClick"])):((0,r.uX)(),(0,r.Wv)(u,{key:0,class:"widget-button widget-button--primary widget-button--show",loading:e.loading,onClick:n.setAccessKey},{default:(0,r.k6)(()=>[(0,r.eW)((0,c.v_)(e.$t("ui.maintenance.debugMode.activate")),1)]),_:1},8,["loading","onClick"])),e.hasAccessKey?((0,r.uX)(),(0,r.Wv)(u,{key:2,class:"widget-button widget-button--edit",loading:e.loading,onClick:n.setAccessKey},{default:(0,r.k6)(()=>[(0,r.eW)((0,c.v_)(e.$t("ui.maintenance.debugMode.credentials")),1)]),_:1},8,["loading","onClick"])):(0,r.Q3)("",!0)])):(0,r.Q3)("",!0):((0,r.uX)(),(0,r.CE)("fieldset",bs,[(0,r.bF)(l,{class:"maintenance__loader"})]))])])]),_:1},8,["message","active"])}var ys={components:{MessageOverlay:Qa,LoadingSpinner:Ha.A,LoadingButton:ta.A},data:()=>({supportsJwtCookie:!1,supportsAccessKey:!1,loading:!0}),computed:{...(0,g.aH)(["safeMode"]),...(0,g.aH)("contao/access-key",{hasAccessKey:"isEnabled"}),...(0,g.aH)("contao/jwt-cookie",{hasJwtDebug:"isDebugEnabled"}),overlayMessage:e=>e.safeMode?e.$t("ui.maintenance.safeMode"):e.$t("ui.maintenance.unsupported")},methods:{async enableJwtDebugMode(){this.loading=!0,await this.$store.dispatch("contao/jwt-cookie/enableDebug"),this.loading=!1},async removeJwtCookie(){this.loading=!0,await this.$store.dispatch("contao/jwt-cookie/delete"),this.loading=!1},async setAccessKey(){const e=prompt(this.$t("ui.maintenance.debugMode.user"));if(!e)return;const t=prompt(this.$t("ui.maintenance.debugMode.password"));t&&(this.loading=!0,await this.$store.dispatch("contao/access-key/set",{user:e,password:t}),this.loading=!1)},async removeAccessKey(){this.loading=!0,await this.$store.dispatch("contao/access-key/delete"),this.loading=!1}},mounted(){this.$store.dispatch("contao/jwt-cookie/get").then(()=>{this.supportsJwtCookie=!0,this.supportsAccessKey=!1,this.loading=!1},()=>this.$store.dispatch("contao/access-key/get").then(()=>{this.supportsJwtCookie=!1,this.supportsAccessKey=!0,this.loading=!1},()=>{this.supportsJwtCookie=!1,this.supportsAccessKey=!1,this.loading=!1}))}};const Cs=(0,Z.A)(ys,[["render",ws]]);var $s=Cs,Ls="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAFoAAABaCAMAAAAPdrEwAAABgFBMVEX///94Xz5KNyUGBQX15cxyWjucYTRqVDgAAACJVjD//+oXFxb8/PwdHRz5+fkICg709PR9ZEH///IoJyYQERMtLS2UXDI4LCBbPiciISH/+d5hTzVWRjAuJBvV1dX77dPOzs+mZzb//uNubnBLTEw4Myz04snv8PD/9No5ODY+PTqWl5cUCwPa2tump6eDVC9IRkP15Mvs7Oz+8daHbEnHyMlBQT+xp5abnJ3///je39/m5udYWFXCwsNWU0uRkZKJiotySitpRSosHA766c+hoaLEuKN1dnjz4chnZ2e6sJ2ysrN8fH1HKRJbXF6NhHZybWMfEwj35s2jm4phYWNSUlTj4+NTTUO8vLzp4crp6eqTjH18UC62t7h7dWn46tGPj4+sra2flIJiW1BmYlrKv6pwaV3a0LrVybOBgoOFfG/89d7k1b3LxrXo3MXz4Mbv5s7Rw6xhNhaSkonv69Ssd0/e1MGSVyqGSh3KnXt4RB1ocXqDTyiBhHz6+ebw7uYmf38+AAAM/0lEQVRYw61ZB1viWtc9JAY2CSEhBQhVmtJFQRBF7Nh7772Xabe+9a9/+4DM6Nx3BO8353miecLJysrea5dzQsi7h8329dROfuqwF2dvtxqnWWP4ZyLbNqBWEiPd9Dx2thr4idARIZJ4JMvpETxPzX1kbT8PekEg8+kc4bfVDLHp5Pz2J9I2YuQ/OntNasIAmVrn2e6/adj52Lc7+5/1oE4QsgL7JJwcHbogy5t/SwvzqXNo6ktOGjJeikQHSSVWJiWo4gNylSdFHGoHqukSGUFIZrRY2k027xuAFP03AuvCiT2yrZBdI1c+BiiR5Wgb0DHx2QwA/dlYcp/sCs8C3hLUhmFkfZlcJYY3jxSeTx49redWlLjQ2tq2KDtQP0ksn0H1WiFzxeebpuH066zZJHmMFdkzJR6sxcv5m2PlKtWa9W0pQS0xIhCSTBD+DjrrlzNaUn4xa0rkyRELJSUY7+rCw/Mp1xo6e/ZpCd8ZHsKee6F4frc8Sh2wADuvpw3DLnmoQincUR+TnlhriwzmSGyP6Ffl3jh6SCfxGCpOgtzod1moE64Jv3/maUD3KtX+Nvx4/ylyKITD14kbsqvuk+WBBTBqJB35bl4AdnlS7pppYPPLA23khzNShRteuQOjRO5zp1cgrsfJJfwlB92K/6klj4LHdWjPXBvBfrhNano8eL9+OSes/PcIxDkPX/70GtneObCxGQUJNZRvsM7fzLaGlvW8crXMz3g8JKwBJHfLQc9HeGXJjFG9uDur3SyXlPizQfLX7QRNcU75tH/f5VEec8LKo8czc6z4s69mRP0fFUJ4Dx/u7W0gdwRnYm1Um4FzJR8MKh8vQH0s88GurvJd4ru4CgxUc0cdylpXR3PEr/U2knafGs8rnn2AfZ5HVl2eXZD/GrX9S+J6uWkOVMhRW8kPVTcnwPZHJUhZrSnJ6f85bU/c9ijxyWfofa0d6OHtC9DmlHAXNWQXfwm2H1VI4ctuWMl/oLa+T3e2kfoXAI48ymTdkL2TxLXww6mdOogrx3Gk0KVcVdqABjgj+YaHuibJOrzl+swtnBNqOM+D1IZEbKkY3zDhTLhcghbpMgBX8SDNIrFG0u1+Wykwp1DWvfndKrSMsoA0x6OQ+JqOrp3S4W3yo+IvQZoqw7rQhnMWcnwwrPAPQiUBQk5/e3I31DAR93oetHaaly0I85dHBrDixnC33MKb/fo9JrQ1fnukraLPJg0A/RZfsB82pt+YiMfGPrV1/EFtw+eZWwOkaHavUdjUyI+lSqJ6qt+4weQzyS+/nmbb6p9PTfX3vUrBLBjTwy/MNh/5MbS6MJpT9eLdZZxsv/ShLSuw6YnFxVW22P/SzlOv7h5ST96AHsQ/pxsJQ92GzAt6wupnq5mOnkVY+iawhReK2BuILgV+7HhZsGUTtKRsDVSSam4kUEfpLrL/CJmt9eEMWVlJ/ha7z0VRzi6pE2zizZRKdFhqlvfUppCkF2HC/AxMh9mcjg4NTw3XG7Ys1FvODTW96jY50rkfsx4skhHt9EVfgm7Zg8WQ9cXoMfew7MRiGgS61pCmA9M6m2ZMDs7LOeDwx1VXfd2rLPUj588U2Yl2duIfJ56H/P5Q6PfClLhEOxIJGIuJs+DgvC/985eMIEQj0yPzgWeNqWhN5Ow0W8fcjMvvdzHuHrPV7DacVufvf27pRXypyGrB0himQvr0jRjo0yDNspqYiP7zZGd0liRXQ07zgUs0XAzjxsG43E7zuL+n56Dnj19/Y7Fx05k6ZQvnc3lXs28FmOBDq7ldE2kAFvpP2bOQ1aX53Q3pUfUxjLNHZNwM41oMlaB7GJ5Jc17GgM43E7AJZ3Emh8PhE2xDUinkloSxFwpBzu5xP3XnuEsbZ9TuKGN6Nkih4H8rvQ+Bz9FkIZHU/p8TEvNSelR9Y5rLXH9IYckPgUFoQnMO5s28M886mjON6NTDqnTwSnpUIWbRT6F7Dqx/TunRW6F5g8U08WYXlWGbJEwu2LlgrS8pO51jFJoRUdx4Mrb46x379TXxDjh9s6FkOW9joiMmqpqzjvE1EP3I13ngHnNZnXjdeRDzC6LlKxff/2iHXvYhX1k7fJLwDZmGy5jAjpmtIcYVcvtR39Ye568jmsg1STvYt0tpJzSnOmISfW8nDUKz9WDMLbKolZ7QgcSEzOPGOPXBH7VD8Jmafoeh9qA5L8tguFgPxmmkMH6JFTBarKEDEdL4tAOxrpw/Pv1TbEpqItGiMoIFsdHcJlUImRETh8tvYJCPI7DT7BYgVkmb8VwU8crvv95pDdac5fvV1F9ZN30i9Ixh1NXBkfcBTU+hz35VwvZKBWso5HQJfmb8X2OixcE1BGVrBe3lKAVHzM+IY24XpqTxHnMoFDI7/7W4ur1gwFVY2RWBoeDj9KF+NcYhcVN6ulU7BF76gpzJ0CQGwRHzH58/Ly4uTky4cqNzRb0Ujn/gg7iWwUc6e8bRE4ua5nVYuDcy6nM1AF/99XySoUqu0MFE2l+9uFg5+veX0o2H1Eq7HmzZZ8L8FxY0v2EYmqbGVE3yoVRbdUR7z9AuySeKZj+o/34M4hKR/lQOl1dqn6rl+ORaV1D5bZtdXRyzjouqyeJldIer2Kpr6QaayTiLxJgkZpFdDyue+PG5mNhe2Z97WobroHbmCfM4FM/ceWxVmBA0lXOYOG61lamJzLqpG30CxwkClPh8x9r9sl7N6RrLAqzz/BkI0dx5pXp+ScK7j+LFCoCKyjax861ZeznOwjGMg1Ml9jKxrvR+eAg+hZVwbfncyHs6+OsYnOcq649fLuMepVKr+pMQwxeFlns53WlUkpfzejmTqsHVsv5LMP/xKiHosdzscfWc7+otH+srpcu56spT0FOrzYG34NIsnFto2deiG70urDOcpcBIGjys7/PHT9e7R+r5zUd+2UAXrnme9isCHPH5D2H+QURxOMRkYTHZuqndAEw4VCQcZ4hpg+fDH9aCeT5MW8w54UOcD87ElfDTTPj4Az9XFEDE9/MlCxNLbXTM8qbL8ZwVDJ+QTD3cY0+8NrmGLfdVklcuLjyTvWv5+Bou5DX2s2bQ6PUVVkfb6cYz4GtUaTR6gYGkEmwsxj2XkCBH8Jhfq6/PwuUqHIyJYj0xmFrGYmOkgHE0+iG0uA/TUX3l23Ec/E0Eun8TxHjMK79UJC/jjgkU2uHS29w67ASqkwbz7VV2XwnP9M54+K7a+kXpl9LRTb4jf72ig8Phd3kFGr0maHuzWc5hNa0TNyXH/JDbVXo96zHVSC6vVC8Sl56O+8svF0LBJIoFEaMXG4t37JGnwN9Iwz6Xi0tLj8p96bxEnpK5Wpkusz/ESdRvMsVEB4PQJp/xnv3UALAWGsCM5Cs4/PDIx8vls0Tlqnj1MUiX5SUJg9aiehvPLxI50P5Gtj0KNA3rMby5MAG/8fwRXNzEn9avg7gU5nUXysgUo8nMVHBJUeh8D/EpcHGWOi2HC/T7sHRHPJP5cLCrd5LcwbbDi7R9nMMywc7uwN77NpkDzcD0wmFkm1RvPFThvV0ess5uilRDJodvIj09SPpkknnXFnmmXt6pwQVsj0uExs5anleCK7g+0hiTyeFOiwO0ZQocRrPtiMQe6JO3+nCmbdZlavQkYob0q3dxBVPK8SU2ereERNIFho0dovNsw7Narj3O9ltgO4dPItPDI2DCCkK7OboSjURX9leSKkCCLi93sAbQzqP7BGsEdA4F5PbAU1kbkTtTEYNNu3wOr5Yl8sD0QlEDMVLUpyOVzXkyK9C6MhhBXC3SPyS3bebB5wVz3+mmtJpW6aozuzOqQ6KyaURGUrPCziyqLaADGCeB936ussuyvX6PPbPE0gVhZlOYHrLJtu6RSvRkEFd+QxLA6OD7UPuyqY3NoiBoaEVJHd2hm+OBxLeNqCVhMxrB36KBd39Ksvf19XXLOLqHMp0DUSQ3m4LZ09R8XQa2RIJ+8BCnZPL/H/ahw4VEZQMfEekjdiwI5DS68/fhujN1Q8ud3/atsydYCk5gg/QlErZX3xrtnSftx+IIWpJGOjoKbT+CZhigmxSigBbfqP+WApqR5jVBCmzhSr3ttHoCmb0+sgVZ9B4hGh46Vr+NBAKSipqZgr5B2DpJkaw2MDJlL8ZIBNqVSKOKwgLSZ8kpLOGtrI2A3Q5ZugdiB9sexZKxcKFdICB/t1f0xua73iiRaFFp3oZGGWFnNXxgBbIEMAjnEXcJj0O0xDQukXUYbVcRiDCYHMoaFJ7k1CUJ5CkdjTHajUQpzYguE3WBRKOdOzYyoA2jb9usuiCyoNtSmr0f5B2QNXRYUeuDSH2bbKtbihADMgOQ0cRZYZMkRGTQZuojESkySBmDtDeI9SOyQ7+wZVnqABtbFw2ZYuEkoCUjI8M2QAGdArwrkwwGCNl83ruzyaQR1XLnM4bclLbcnPveT7B/P+r+D5q++1kip6P4AAAAAElFTkSuQmCC";const As={class:"maintenance"},Es={class:"maintenance__inside"},Xs={class:"maintenance__about"},Ss={class:"maintenance__actions"};function xs(e,t,a,s,i,n){return(0,r.uX)(),(0,r.CE)("section",As,[(0,r.Lk)("div",Es,[t[1]||(t[1]=(0,r.Lk)("figure",{class:"maintenance__image"},[(0,r.Lk)("img",{src:Ls,alt:""})],-1)),(0,r.Lk)("div",Xs,[(0,r.Lk)("h1",null,(0,c.v_)(e.$t("ui.maintenance.dumpAutoload.title")),1),(0,r.Lk)("p",null,(0,c.v_)(e.$t("ui.maintenance.dumpAutoload.description")),1)]),(0,r.Lk)("fieldset",Ss,[(0,r.Lk)("button",{class:"widget-button widget-button--primary widget-button--update",onClick:t[0]||(t[0]=(...e)=>n.execute&&n.execute(...e))},(0,c.v_)(e.$t("ui.maintenance.dumpAutoload.button")),1)])])])}var Ts={methods:{execute(){this.$store.dispatch("tasks/execute",{name:"composer/dump-autoload"})}}};const Ms=(0,Z.A)(Ts,[["render",xs]]);var Os=Ms;const Fs={class:"maintenance"},Is={class:"maintenance__inside"},Ps={class:"maintenance__about"},Rs={class:"maintenance__actions"};function Bs(e,t,a,s,i,n){const o=(0,r.g2)("i18n-t"),l=(0,r.g2)("link-menu"),u=(0,r.g2)("button-group");return(0,r.uX)(),(0,r.CE)("section",Fs,[(0,r.Lk)("div",Is,[t[2]||(t[2]=(0,r.Lk)("figure",{class:"maintenance__image"},[(0,r.Lk)("img",{src:Ls,alt:""})],-1)),(0,r.Lk)("div",Ps,[(0,r.Lk)("h1",null,(0,c.v_)(e.$t("ui.maintenance.composerInstall.title")),1),(0,r.bF)(o,{tag:"p",keypath:"ui.maintenance.composerInstall.description"},{vendor:(0,r.k6)(()=>[...t[0]||(t[0]=[(0,r.Lk)("code",null,"/vendor",-1)])]),composerLock:(0,r.k6)(()=>[...t[1]||(t[1]=[(0,r.Lk)("code",null,"composer.lock",-1)])]),_:1})]),(0,r.Lk)("fieldset",Rs,[(0,r.bF)(u,{label:e.$t("ui.maintenance.composerInstall.button"),type:"primary",icon:"run",onClick:n.composerInstall},{default:(0,r.k6)(()=>[(0,r.bF)(l,{align:"right",items:n.advancedActions,color:"primary"},null,8,["items"])]),_:1},8,["label","onClick"])])])])}var Ds={components:{ButtonGroup:Jt.A,LinkMenu:fa.A},computed:{advancedActions(){return[{label:this.$t("ui.maintenance.composerInstall.update"),action:this.composerUpdate}]}},methods:{composerInstall(){this.$store.dispatch("tasks/execute",{name:"composer/install"})},composerUpdate(){this.$store.dispatch("tasks/execute",{name:"composer/update"})}}};const js=(0,Z.A)(Ds,[["render",Bs]]);var Us=js;const qs={class:"maintenance"},Ws={class:"maintenance__inside"},Vs={class:"maintenance__about"},Qs={class:"maintenance__actions"};function Hs(e,t,a,s,i,n){return(0,r.uX)(),(0,r.CE)("section",qs,[(0,r.Lk)("div",Ws,[t[1]||(t[1]=(0,r.Lk)("figure",{class:"maintenance__image"},[(0,r.Lk)("img",{src:Ls,alt:""})],-1)),(0,r.Lk)("div",Vs,[(0,r.Lk)("h1",null,(0,c.v_)(e.$t("ui.maintenance.composerCache.title")),1),(0,r.Lk)("p",null,(0,c.v_)(e.$t("ui.maintenance.composerCache.description")),1)]),(0,r.Lk)("fieldset",Qs,[(0,r.Lk)("button",{class:"widget-button widget-button--primary widget-button--trash",onClick:t[0]||(t[0]=(...e)=>n.execute&&n.execute(...e))},(0,c.v_)(e.$t("ui.maintenance.composerCache.button")),1)])])])}var Gs={methods:{execute(){this.$store.dispatch("tasks/execute",{name:"composer/clear-cache"})}}};const Ns=(0,Z.A)(Gs,[["render",Hs]]);var zs=Ns,Ks=a.p+"img/php-logo.7376e212.svg";const Js={key:0,class:"maintenance"},Zs={class:"maintenance__inside"},Ys={class:"maintenance__about"},ei={class:"maintenance__actions"};function ti(e,t,a,s,i,n){const o=(0,r.g2)("loading-spinner");return e.status.opcache_enabled?((0,r.uX)(),(0,r.CE)("section",Js,[(0,r.Lk)("div",Zs,[t[1]||(t[1]=(0,r.Lk)("figure",{class:"maintenance__image"},[(0,r.Lk)("img",{src:Ks,alt:""})],-1)),(0,r.Lk)("div",Ys,[(0,r.Lk)("h1",null,(0,c.v_)(e.$t("ui.maintenance.opcodeCache.title")),1),(0,r.Lk)("p",null,(0,c.v_)(e.$t("ui.maintenance.opcodeCache.description")),1)]),(0,r.Lk)("fieldset",ei,[e.loading?((0,r.uX)(),(0,r.Wv)(o,{key:0,class:"maintenance__loader"})):((0,r.uX)(),(0,r.CE)("button",{key:1,class:"widget-button widget-button--primary widget-button--trash",onClick:t[0]||(t[0]=(...e)=>n.execute&&n.execute(...e))},(0,c.v_)(e.$t("ui.maintenance.opcodeCache.button")),1))])])])):(0,r.Q3)("",!0)}var ai={components:{LoadingSpinner:Ha.A},data:()=>({opcodeEnabled:!1,loading:!1,status:{opcache_enabled:!1}}),methods:{execute(){this.loading=!0,this.$store.dispatch("server/opcache/delete",this.status.reset_token).then(e=>{this.loading=!1,this.status=e})}},mounted(){this.$store.dispatch("server/opcache/get").then(e=>{this.status=e},()=>{this.status={opcache_enabled:!1}})}};const si=(0,Z.A)(ai,[["render",ti]]);var ii=si;const ni={class:"maintenance"},oi={class:"maintenance__inside"},li={class:"maintenance__about"},ri={class:"maintenance__actions"};function ci(e,t,a,s,i,n){const o=(0,r.g2)("loading-spinner"),l=(0,r.g2)("loading-button"),u=(0,r.g2)("message-overlay");return(0,r.uX)(),(0,r.Wv)(u,{message:n.overlayMessage,active:e.safeMode||!e.loading&&!e.supported},{default:(0,r.k6)(()=>[(0,r.Lk)("section",ni,[(0,r.Lk)("div",oi,[t[0]||(t[0]=(0,r.Lk)("figure",{class:"maintenance__image"},[(0,r.Lk)("img",{src:h,alt:""})],-1)),(0,r.Lk)("div",li,[(0,r.Lk)("h1",null,(0,c.v_)(e.$t("ui.maintenance.maintenanceMode.title")),1),(0,r.Lk)("p",null,(0,c.v_)(e.$t("ui.maintenance.maintenanceMode.description")),1)]),(0,r.Lk)("fieldset",ri,[e.loading&&!e.supported?((0,r.uX)(),(0,r.Wv)(o,{key:0,class:"maintenance__loader"})):e.enabled?((0,r.uX)(),(0,r.Wv)(l,{key:2,class:"widget-button widget-button--alert widget-button--maintenance",loading:e.loading,disabled:!e.supported,onClick:n.disableMaintenanceMode},{default:(0,r.k6)(()=>[(0,r.eW)((0,c.v_)(e.$t("ui.maintenance.maintenanceMode.disable")),1)]),_:1},8,["loading","disabled","onClick"])):((0,r.uX)(),(0,r.Wv)(l,{key:1,class:"widget-button widget-button--primary widget-button--maintenance",loading:e.loading,disabled:!e.supported,onClick:n.enableMaintenanceMode},{default:(0,r.k6)(()=>[(0,r.eW)((0,c.v_)(e.$t("ui.maintenance.maintenanceMode.enable")),1)]),_:1},8,["loading","disabled","onClick"]))])])])]),_:1},8,["message","active"])}var ui={components:{MessageOverlay:Qa,LoadingSpinner:Ha.A,LoadingButton:ta.A},data:()=>({loading:!0,supported:!1,enabled:!1}),computed:{...(0,g.aH)(["safeMode"]),overlayMessage:e=>e.safeMode?e.$t("ui.maintenance.safeMode"):e.$t("ui.maintenance.unsupported")},methods:{async enableMaintenanceMode(){this.loading=!0,this.enabled=await this.$store.dispatch("contao/maintenance-mode/enable"),this.loading=!1},async disableMaintenanceMode(){this.loading=!0,this.enabled=await this.$store.dispatch("contao/maintenance-mode/disable"),this.loading=!1}},async mounted(){const e=await this.$store.dispatch("server/contao/get");if(200===e.status){const t=Object.keys(e.data?.cli?.commands);this.supported=t.includes("contao:maintenance-mode")||t.includes("lexik:maintenance:lock")&&t.includes("lexik:maintenance:unlock"),this.supported&&(this.enabled=await this.$store.dispatch("contao/maintenance-mode/isEnabled"))}this.loading=!1}};const di=(0,Z.A)(ui,[["render",ci]]);var pi=di,gi={components:{MainLayout:re,DatabaseStatus:za,RebuildCache:ns,InstallTool:gs,MaintenanceMode:pi,DebugMode:$s,DumpAutoload:Os,ComposerInstall:Us,ComposerCache:zs,OpcodeCache:ii},computed:{...(0,g.L8)("auth",["isGranted"])},mounted(){this.isGranted(te.A.UPDATE)||this.$router.push("/")}};const hi=(0,Z.A)(gi,[["render",La]]);var mi=hi;function ki(e,t,a,s,i,n){const o=(0,r.g2)("migration-view");return(0,r.uX)(),(0,r.Wv)(o,{onClose:n.close},null,8,["onClose"])}var vi=a(8733),bi={components:{MigrationView:vi["default"]},methods:{close(){this.$router.push(l.A.discover)}}};const _i=(0,Z.A)(bi,[["render",ki]]);var fi=_i;const wi={class:"log-viewer__title"},yi={key:1,class:"log-viewer__status log-viewer__status--empty"},Ci={class:"log-viewer__title"},$i={key:2},Li={class:"log-viewer__filters"},Ai={class:"log-viewer__file"},Ei=["title"],Xi=["href","download","title"],Si={class:"log-viewer__list",ref:"list"},xi={class:"log-viewer__line log-viewer__line--header"},Ti={class:"log-viewer__meta log-viewer__meta--header"},Mi={class:"log-viewer__content log-viewer__content--header"},Oi={class:"log-viewer__meta"},Fi=["datetime"],Ii=["title"],Pi=["title"],Ri={class:"log-viewer__content"},Bi={class:"log-viewer__message"},Di={class:"log-viewer__details"},ji=["title"],Ui=["title"],qi=["onClick"],Wi=["onClick"],Vi={key:1,class:"log-viewer__line log-viewer__more"},Qi={key:2,class:"log-viewer__loading"};function Hi(e,t,a,s,i,n){const o=(0,r.g2)("loading-spinner"),l=(0,r.g2)("select-menu"),u=(0,r.g2)("vue-json-pretty"),d=(0,r.g2)("main-layout");return(0,r.uX)(),(0,r.Wv)(d,null,{default:(0,r.k6)(()=>[null===e.files?((0,r.uX)(),(0,r.Wv)(o,{key:0,class:"log-viewer__status log-viewer__status--loader"},{default:(0,r.k6)(()=>[(0,r.Lk)("p",wi,(0,c.v_)(e.$t("ui.log-viewer.loading")),1)]),_:1})):e.files&&0===e.files.length?((0,r.uX)(),(0,r.CE)("div",yi,[(0,r.Lk)("p",Ci,(0,c.v_)(e.$t("ui.log-viewer.empty")),1),(0,r.Lk)("button",{class:"widget-button widget-button--inline widget-button--update",onClick:t[0]||(t[0]=(...e)=>n.load&&n.load(...e))},(0,c.v_)(e.$t("ui.log-viewer.reload")),1)])):((0,r.uX)(),(0,r.CE)("div",$i,[(0,r.Lk)("div",Li,[(0,r.Lk)("div",null,[(0,r.Lk)("div",Ai,[(0,r.bF)(l,{options:n.fileOptions,name:"file",label:e.$t("ui.log-viewer.file"),modelValue:e.file,"onUpdate:modelValue":t[1]||(t[1]=t=>e.file=t)},null,8,["options","label","modelValue"]),(0,r.Lk)("button",{class:"widget-button widget-button--inline widget-button--update",title:e.$t("ui.log-viewer.reload"),onClick:t[2]||(t[2]=(...e)=>n.load&&n.load(...e))},null,8,Ei)]),(0,r.Lk)("a",{href:`api/logs/${encodeURIComponent(e.file)}`,download:`${e.file}.log`,target:"_blank",class:(0,c.C4)(["widget-button widget-button--inline widget-button--download",{disabled:!e.file}]),title:e.$t("ui.log-viewer.downloadTitle",{file:`${e.file}.log`})},(0,c.v_)(e.$t("ui.log-viewer.download")),11,Xi)]),(0,r.Lk)("div",null,[(0,r.bF)(l,{options:n.channelOptions,name:"channel",label:e.$t("ui.log-viewer.channel"),modelValue:e.channel,"onUpdate:modelValue":t[3]||(t[3]=t=>e.channel=t)},null,8,["options","label","modelValue"]),(0,r.bF)(l,{options:n.levelOptions,name:"level",label:e.$t("ui.log-viewer.level"),modelValue:e.level,"onUpdate:modelValue":t[4]||(t[4]=t=>e.level=t)},null,8,["options","label","modelValue"])])]),(0,r.Lk)("div",Si,[(0,r.Lk)("div",xi,[(0,r.Lk)("div",Ti,(0,c.v_)(e.$t("ui.log-viewer.timeHeader")),1),(0,r.Lk)("div",Mi,(0,c.v_)(e.$t("ui.log-viewer.messageHeader")),1)]),n.lines?((0,r.uX)(!0),(0,r.CE)(r.FK,{key:0},(0,r.pI)(n.lines,(t,a)=>((0,r.uX)(),(0,r.CE)(r.FK,{key:a},["string"===typeof t?((0,r.uX)(),(0,r.CE)("div",{class:"log-viewer__line log-viewer__line--raw",key:a},(0,c.v_)(t),1)):((0,r.uX)(),(0,r.CE)("div",{key:1,class:(0,c.C4)(`log-viewer__line log-viewer__line--${t.level.toLowerCase()}`)},[(0,r.Lk)("div",Oi,[(0,r.Lk)("time",{class:"log-viewer__datetime",datetime:t.datetime},(0,c.v_)(n.datimFormat(t.datetime,"medium")),9,Fi),(0,r.Lk)("span",{class:(0,c.C4)(`log-viewer__badge log-viewer__badge--desktop log-viewer__badge--level-${t.level.toLowerCase()}`),title:e.$t("ui.log-viewer.levelTitle")},(0,c.v_)(t.level),11,Ii),(0,r.Lk)("span",{class:"log-viewer__badge log-viewer__badge--desktop log-viewer__badge--channel",title:e.$t("ui.log-viewer.channelTitle")},(0,c.v_)(t.channel),9,Pi)]),(0,r.Lk)("div",Ri,[(0,r.Lk)("div",Bi,[((0,r.uX)(!0),(0,r.CE)(r.FK,null,(0,r.pI)(n.pieces(t.message),(e,t)=>((0,r.uX)(),(0,r.CE)("span",{key:t},(0,c.v_)(e),1))),128))]),(0,r.Lk)("div",Di,[(0,r.Lk)("span",{class:(0,c.C4)(`log-viewer__badge log-viewer__badge--mobile log-viewer__badge--level-${t.level.toLowerCase()}`),title:e.$t("ui.log-viewer.levelTitle")},(0,c.v_)(t.level),11,ji),(0,r.Lk)("span",{class:"log-viewer__badge log-viewer__badge--mobile log-viewer__badge--channel",title:e.$t("ui.log-viewer.channelTitle")},(0,c.v_)(t.channel),9,Ui),n.canShow(t.context)?((0,r.uX)(),(0,r.CE)("button",{key:0,class:(0,c.C4)(["log-viewer__toggle",{"log-viewer__toggle--active":e.showContext[a]}]),onClick:e=>n.toggleContext(a)},(0,c.v_)(e.$t(`ui.log-viewer.${e.showContext[a]?"hide":"show"}Context`)),11,qi)):(0,r.Q3)("",!0),n.canShow(t.extra)?((0,r.uX)(),(0,r.CE)("button",{key:1,class:(0,c.C4)(["log-viewer__toggle",{"log-viewer__toggle--active":e.showExtra[a]}]),onClick:e=>n.toggleExtra(a)},(0,c.v_)(e.$t(`ui.log-viewer.${e.showExtra[a]?"hide":"show"}Extra`)),11,Wi)):(0,r.Q3)("",!0)]),n.canShow(t.context)&&e.showContext[a]?((0,r.uX)(),(0,r.Wv)(u,{key:0,data:t.context,deep:1,class:"log-viewer__json"},null,8,["data"])):(0,r.Q3)("",!0),n.canShow(t.extra)&&e.showExtra[a]?((0,r.uX)(),(0,r.Wv)(u,{key:1,data:t.extra,deep:1,class:"log-viewer__json"},null,8,["data"])):(0,r.Q3)("",!0)])],2))],64))),128)):(0,r.Q3)("",!0),n.current&&0!==e.offset?((0,r.uX)(),(0,r.CE)("div",Vi,[(0,r.Lk)("button",{class:"widget-button widget-button--inline widget-button--add",onClick:t[5]||(t[5]=(...e)=>n.next&&n.next(...e))},(0,c.v_)(e.$t("ui.log-viewer.more")),1)])):(0,r.Q3)("",!0),e.loading?((0,r.uX)(),(0,r.CE)("div",Qi,[(0,r.bF)(o)])):(0,r.Q3)("",!0)],512)]))]),_:1})}a(116),a(7588),a(1701);var Gi=a(4144);const Ni=["for"],zi=["id","name","disabled","required"],Ki={key:0,value:""},Ji=["label"],Zi=["value","disabled","selected"],Yi=["value","disabled","selected"],en={key:1,class:"widget__error"};function tn(e,t,a,s,i,n){return(0,r.uX)(),(0,r.CE)("div",{class:(0,c.C4)(["widget widget-select",{"widget--error":a.error,"widget--required":a.required}])},[a.label?((0,r.uX)(),(0,r.CE)("label",{key:0,for:"ctrl_"+a.name},(0,c.v_)(a.label),9,Ni)):(0,r.Q3)("",!0),(0,r.Lk)("select",{ref:"input",id:a.label?"ctrl_"+a.name:"",name:a.name,disabled:a.disabled,required:a.required,onChange:t[0]||(t[0]=e=>n.input(e.target.value))},[a.includeBlank?((0,r.uX)(),(0,r.CE)("option",Ki,(0,c.v_)(e.$t("ui.widget.blankOption")),1)):(0,r.Q3)("",!0),((0,r.uX)(!0),(0,r.CE)(r.FK,null,(0,r.pI)(a.options,(e,t)=>((0,r.uX)(),(0,r.CE)(r.FK,null,[e.options?((0,r.uX)(),(0,r.CE)("optgroup",{label:e.label,key:t},[((0,r.uX)(!0),(0,r.CE)(r.FK,null,(0,r.pI)(e.options,e=>((0,r.uX)(),(0,r.CE)("option",{value:e.value,disabled:e.disabled,selected:e.value===a.modelValue,key:e.value},(0,c.v_)(e.label),9,Zi))),128))],8,Ji)):((0,r.uX)(),(0,r.CE)("option",{value:e.value,disabled:e.disabled,selected:e.value===a.modelValue,key:e.value},(0,c.v_)(e.label),9,Yi))],64))),256))],40,zi),a.error?((0,r.uX)(),(0,r.CE)("p",en,(0,c.v_)(a.error),1)):(0,r.Q3)("",!0)],2)}var an={emits:["input","update:modelValue"],props:{name:{type:String,required:!0},options:{type:Array,required:!0},label:String,modelValue:String,disabled:Boolean,required:Boolean,error:String,includeBlank:Boolean},methods:{input(e){this.$emit("input"),this.$emit("update:modelValue",e)}},mounted(){this.$emit("update:modelValue",this.$refs.input.value)},updated(){this.$emit("update:modelValue",this.$refs.input.value)}};const sn=(0,Z.A)(an,[["render",tn]]);var nn=sn,on={components:{MainLayout:re,LoadingSpinner:Ha.A,SelectMenu:nn,VueJsonPretty:Gi.A},data:()=>({files:null,loading:!1,file:null,offset:0,limit:100,content:[],channel:"",level:"",showContext:{},showExtra:{}}),computed:{channelOptions:e=>e.countOptions("channel"),levelOptions:e=>e.countOptions("level",{emergency:0,alert:0,critical:0,error:0,warning:0,notice:0,info:0,debug:0}),fileOptions(){if(!this.files)return[];const e={},t=[];return this.files.forEach(a=>{const s=a.name.match(/^([a-z]+)-(\d{4}-\d{2}-\d{2})$/i);s?(e[s[1]]||(e[s[1]]={label:this.$te(`ui.log-viewer.${s[1]}Environment`)?this.$t(`ui.log-viewer.${s[1]}Environment`):s[1],options:[]}),e[s[1]].options.push({value:a.name,label:`${(0,It.A)(s[2],null,"long")} (${(0,st.A)(a.size)})`})):t.push({value:a.name,label:`${a.name} (${(0,st.A)(a.size)})`})}),[...Object.values(e),...t]},current:e=>e.files?.find(t=>t.name===e.file),lines:e=>e.content?.filter(t=>"string"===typeof t||(!e.channel||t.channel===e.channel)&&(!e.level||t.level.toLowerCase()===e.level)).reverse()},methods:{datimFormat:It.A,canShow:e=>e&&(!Array.isArray(e)||e.length),pieces:e=>{let t=[];const a=e.split(' "'),s=a.length-1;let i=0;for(let n=0;n<=s;n++){let e=a[n];if(0!==i)while(i>0){while(!a[n].includes('"')&&n!==s)e=`${e} "${a[n+1]}`,i++,n++;if(i--,0===i){t[t.length-1]+=' "';const a=e.indexOf('" ')||e.lastIndexOf('"');t.push(e.slice(0,a)),t.push(e.slice(a)),i++;break}}else t.push(e),i++}return t},toggleContext(e){this.showContext[e]=!this.showContext[e]},toggleExtra(e){this.showExtra[e]=!this.showExtra[e]},countOptions(e,t={}){return this.content.forEach(a=>{"string"!==typeof a&&(t[a[e].toLowerCase()]||(t[a[e].toLowerCase()]=0),t[a[e].toLowerCase()]+=1)}),[{label:"all",value:""}].concat(Object.keys(t).map(e=>({value:e,label:`${e.at(0).toUpperCase()}${e.slice(1)} (${t[e]})`})))},next(){this.limit=Math.min(this.offset,100),this.offset=Math.max(this.offset-100,0)},async load(){const e=this.file;this.files=null,this.file=null,this.files=(await s.A.get("api/logs")).data,this.file=this.files.find(t=>t.name===e)?.name||(this.files.length?this.files[0].name:null)},async fetch(){if(!this.current)return;this.loading=!0;const e=(await s.A.get(`api/logs/${encodeURIComponent(this.current.name)}?offset=${this.offset}&limit=${this.limit}`)).data;this.content=this.content.concat(Array.from(e.content.reverse())),this.loading=!1}},watch:{async file(){this.content=[],this.channel="",this.level="",this.showContext={},this.showExtra={},this.limit=100,this.offset=this.current?Math.max(this.current.lines-100,0):0,await this.fetch()},async offset(){await this.fetch()}},async created(){await this.load()}};const ln=(0,Z.A)(on,[["render",Hi]]);var rn=ln;const cn={key:1},un={class:"user-manager__list"},dn={key:0,class:"user-manager__ribbon"},pn=["title"],gn=["title"],hn=["title"],mn={class:"user-manager__username"},kn=["onClick"],vn={class:"user-manager__new"};function bn(e,t,a,s,i,n){const o=(0,r.g2)("loading-spinner"),l=(0,r.g2)("user-scope"),u=(0,r.g2)("main-layout");return(0,r.uX)(),(0,r.Wv)(u,{class:"user-manager"},{default:(0,r.k6)(()=>[null===e.users?((0,r.uX)(),(0,r.Wv)(o,{key:0,class:"user-manager__loading"},{default:(0,r.k6)(()=>[(0,r.Lk)("p",null,(0,c.v_)(e.$t("ui.user-manager.loading")),1)]),_:1})):((0,r.uX)(),(0,r.CE)("div",cn,[(0,r.Lk)("div",un,[((0,r.uX)(!0),(0,r.CE)(r.FK,null,(0,r.pI)(e.users,(a,s)=>((0,r.uX)(),(0,r.CE)("div",{key:s,class:"user-manager__item"},[e.currentUser===a.username?((0,r.uX)(),(0,r.CE)("div",dn,(0,c.v_)(e.$t("ui.user-manager.you")),1)):a.passkey?((0,r.uX)(),(0,r.CE)("div",{key:1,class:"user-manager__ribbon user-manager__ribbon--hint user-manager__ribbon--primary",title:e.$t("ui.user-manager.passkeyTitle")},(0,c.v_)(e.$t("ui.user-manager.passkey")),9,pn)):a.totp_enabled?((0,r.uX)(),(0,r.CE)("div",{key:2,class:"user-manager__ribbon user-manager__ribbon--hint user-manager__ribbon--primary",title:e.$t("ui.user-manager.2faEnabled")},(0,c.v_)(e.$t("ui.user-manager.2fa")),9,gn)):((0,r.uX)(),(0,r.CE)("div",{key:3,class:"user-manager__ribbon user-manager__ribbon--hint user-manager__ribbon--warning",title:e.$t("ui.user-manager.2faDisabled")},(0,c.v_)(e.$t("ui.user-manager.2fa")),9,hn)),(0,r.Lk)("div",mn,(0,c.v_)(a.username),1),(0,r.bF)(l,{readonly:"",label:"Permissions","model-value":a.scope,class:"user-manager__scope"},null,8,["model-value"]),t[4]||(t[4]=(0,r.Lk)("div",{class:"user-manager__spacer"},null,-1)),e.currentUser!==a.username||e.hasPasskey?(0,r.Q3)("",!0):((0,r.uX)(),(0,r.CE)("button",{key:4,class:"widget-button",onClick:t[0]||(t[0]=(...e)=>n.changePassword&&n.changePassword(...e))},(0,c.v_)(e.$t("ui.user-manager.changePassword")),1)),e.currentUser!==a.username||e.hasPasskey||e.hasTotp?(0,r.Q3)("",!0):((0,r.uX)(),(0,r.CE)("button",{key:5,class:"widget-button",onClick:t[1]||(t[1]=(...e)=>n.setupTotp&&n.setupTotp(...e))},(0,c.v_)(e.$t("ui.user-manager.setupTotp")),1)),e.currentUser===a.username&&!e.hasPasskey&&e.hasTotp?((0,r.uX)(),(0,r.CE)("button",{key:6,class:"widget-button",onClick:t[2]||(t[2]=(...e)=>n.disableTotp&&n.disableTotp(...e))},(0,c.v_)(e.$t("ui.user-manager.disableTotp")),1)):(0,r.Q3)("",!0),e.currentUser!==a.username?((0,r.uX)(),(0,r.CE)("button",{key:7,class:"widget-button widget-button--alert widget-button--trash",onClick:e=>n.deleteUser(a.username)},(0,c.v_)(e.$t("ui.user-manager.delete")),9,kn)):(0,r.Q3)("",!0)]))),128))]),(0,r.Lk)("div",vn,[e.isGranted(n.scopes.ADMIN)?((0,r.uX)(),(0,r.CE)("button",{key:0,class:"widget-button widget-button--inline widget-button--add",onClick:t[3]||(t[3]=(...e)=>n.addUser&&n.addUser(...e))},(0,c.v_)(e.$t("ui.user-manager.invite")),1)):(0,r.Q3)("",!0)])]))]),_:1})}const _n={class:"user-scope"},fn={key:0,class:"user-scope__label"};function wn(e,t,a,s,i,n){const o=(0,r.g2)("check-box");return(0,r.uX)(),(0,r.CE)("fieldset",_n,[a.label?((0,r.uX)(),(0,r.CE)("legend",fn,(0,c.v_)(a.label),1)):(0,r.Q3)("",!0),((0,r.uX)(!0),(0,r.CE)(r.FK,null,(0,r.pI)(n.all,t=>((0,r.uX)(),(0,r.Wv)(o,{key:t,class:(0,c.C4)(["user-scope__item",{"user-scope__item--required":a.readonly||n.isRequired(t)}]),name:`${t}_${e.randomKey}`,label:e.$t(`ui.scope.${t}`),disabled:a.readonly||!n.isRequested(t)||n.isRequired(t),"model-value":e.model[t],"onUpdate:modelValue":e=>n.setEnabled(t,e)},null,8,["class","name","label","disabled","model-value","onUpdate:modelValue"]))),128))])}var yn=a(3480),Cn={components:{CheckBox:yn.A},props:{allowed:Array,label:String,modelValue:String,readonly:Boolean},data:()=>({randomKey:(Math.random()+1).toString(36).substring(7),model:{admin:!1,install:!1,update:!1,read:!1}}),computed:{all:()=>Object.values(te.A).reverse(),scopes:e=>e.all.filter(t=>!e.allowed||e.allowed.includes(t)),isRequested:e=>t=>e.scopes.includes(t),isRequired:e=>t=>e.all.indexOf(t)<=e.all.indexOf(e.all.find(t=>e.scopes.includes(t)))},methods:{init(){this.all.forEach(e=>{this.model[e]=!1}),this.setEnabled(this.modelValue||this.scopes[this.scopes.length-1],!0)},setEnabled(e,t){this.all.forEach(a=>{this.isRequired(a)?this.model[a]=!0:this.model[a]=t?this.all.indexOf(a)<=this.all.indexOf(e):this.isRequested(a)&&this.all.indexOf(a)<this.all.indexOf(e)}),this.$emit("update:modelValue",Array.from(this.all).reverse().find(e=>this.model[e]))}},watch:{scopes:{handler(){this.init()},deep:!0}},mounted(){this.init()}};const $n=(0,Z.A)(Cn,[["render",wn]]);var Ln=$n;const An={class:"invite-user__text"},En={class:"invite-user__url"},Xn={class:"invite-user__text"},Sn=["href"],xn=["disabled"];function Tn(e,t,a,s,i,n){const o=(0,r.g2)("i18n-t"),l=(0,r.g2)("user-scope"),u=(0,r.g2)("loading-button"),d=(0,r.g2)("popup-overlay");return(0,r.uX)(),(0,r.Wv)(d,{class:"invite-user",headline:e.$t("ui.user-manager.inviteHeadline"),onSubmit:n.submit,onClear:n.close},{actions:(0,r.k6)(()=>[(0,r.Lk)("button",{type:"button",class:"widget-button",disabled:e.loading,onClick:t[2]||(t[2]=(...e)=>n.close&&n.close(...e))},(0,c.v_)(e.token?e.$t("ui.user-manager.close"):e.$t("ui.user-manager.cancel")),9,xn),e.token?(0,r.Q3)("",!0):((0,r.uX)(),(0,r.Wv)(u,{key:0,submit:"",color:"primary",loading:e.loading},{default:(0,r.k6)(()=>[(0,r.eW)((0,c.v_)(e.$t("ui.user-manager.createInvitation")),1)]),_:1},8,["loading"]))]),default:(0,r.k6)(()=>[e.token?((0,r.uX)(),(0,r.CE)(r.FK,{key:0},[t[3]||(t[3]=(0,r.Lk)("div",{class:"invite-user__check"},[(0,r.Lk)("svg",{xmlns:"http://www.w3.org/2000/svg",width:"24",height:"24",viewBox:"0 0 24 24"},[(0,r.Lk)("path",{d:"M12,2A10,10 0 0,1 22,12A10,10 0 0,1 12,22A10,10 0 0,1 2,12A10,10 0 0,1 12,2M12,4A8,8 0 0,0 4,12A8,8 0 0,0 12,20A8,8 0 0,0 20,12A8,8 0 0,0 12,4M11,16.5L6.5,12L7.91,10.59L11,13.67L16.59,8.09L18,9.5L11,16.5Z"})])],-1)),(0,r.bF)(o,{tag:"p",keypath:"ui.user-manager.inviteSuccess1",class:"invite-user__text"},{expires:(0,r.k6)(()=>[(0,r.eW)((0,c.v_)(n.datimFormat(1e3*e.token.expires,"short","long")),1)]),_:1}),(0,r.Lk)("p",An,(0,c.v_)(e.$t("ui.user-manager.inviteSuccess2")),1),(0,r.Lk)("code",En,(0,c.v_)(e.token.url),1),e.clipboard.isSupported?((0,r.uX)(),(0,r.CE)("button",{key:0,type:"button",class:(0,c.C4)(["widget-button widget-button--small invite-user__clipboard",{"widget-button--clipboard":!e.clipboard.copied,"widget-button--check":e.clipboard.copied}]),onClick:t[0]||(t[0]=t=>e.clipboard.copy(e.token.url))},(0,c.v_)(e.$t("ui.user-manager.clipboard")),3)):(0,r.Q3)("",!0)],64)):((0,r.uX)(),(0,r.CE)(r.FK,{key:1},[(0,r.Lk)("p",Xn,(0,c.v_)(e.$t("ui.user-manager.inviteText")),1),(0,r.bF)(l,{modelValue:e.scope,"onUpdate:modelValue":t[1]||(t[1]=t=>e.scope=t)},null,8,["modelValue"]),(0,r.Lk)("a",{class:"invite-user__help",href:`https://to.contao.org/docs/manager-users?lang=${e.$i18n.locale}`,target:"_blank"},(0,c.v_)(e.$t("ui.user-manager.permissions")),9,Sn)],64))]),_:1},8,["headline","onSubmit","onClear"])}var Mn=a(3513),On=a(1687),Fn={components:{PopupOverlay:On.A,LoadingButton:ta.A,UserScope:Ln},data:()=>({loading:!1,scope:"admin",token:null,clipboard:(0,Mn.iDZ)()}),methods:{datimFormat:It.A,async submit(){this.loading=!0,this.$request.post("api/invitations",{scope:this.scope},null,{201:e=>{this.token=e.data,this.loading=!1}})},close(){this.$store.commit("modals/close","invite-user")}}};const In=(0,Z.A)(Fn,[["render",Tn]]);var Pn=In,Rn=a(9473);const Bn={class:"disable-totp__text"},Dn=["disabled"];function jn(e,t,a,s,i,n){const o=(0,r.g2)("text-field"),l=(0,r.g2)("loading-button"),u=(0,r.g2)("popup-overlay");return(0,r.uX)(),(0,r.Wv)(u,{class:"disable-totp",headline:e.$t("ui.totp.headline"),onSubmit:n.submit,onClear:n.close},{actions:(0,r.k6)(()=>[(0,r.Lk)("button",{type:"button",class:"widget-button",disabled:e.loading,onClick:t[2]||(t[2]=(...e)=>n.close&&n.close(...e))},(0,c.v_)(e.$t("ui.totp.cancel")),9,Dn),(0,r.bF)(l,{submit:"",color:"primary",loading:e.loading},{default:(0,r.k6)(()=>[(0,r.eW)((0,c.v_)(e.$t("ui.totp.disable")),1)]),_:1},8,["loading"])]),default:(0,r.k6)(()=>[(0,r.Lk)("p",Bn,(0,c.v_)(e.$t("ui.totp.disableText")),1),(0,r.bF)(o,{ref:"totp",name:"totp",required:"",pattern:"\\d+",minlength:"6",maxlength:"6",autocomplete:"one-time-code",error:e.error,onKeyup:t[0]||(t[0]=t=>e.error=""),modelValue:e.totp,"onUpdate:modelValue":t[1]||(t[1]=t=>e.totp=t)},null,8,["error","modelValue"])]),_:1},8,["headline","onSubmit","onClear"])}var Un=a(9757),qn={components:{PopupOverlay:On.A,LoadingButton:ta.A,TextField:Un.A},data:()=>({loading:!1,error:"",totp:null}),computed:{...(0,g.aH)("auth",["username"])},methods:{submit(){this.loading=!0,this.$request.delete(`api/users/${this.username}/totp`,{data:{totp:this.totp}},null,{200:async()=>{await this.$store.dispatch("auth/status"),this.$notify.success(this.$t("ui.totp.disabled")),this.close()},422:()=>{this.loading=!1,this.error=this.$t("ui.totp.invalid"),this.$refs.totp.focus()}})},close(){this.$store.commit("modals/close","disable-totp")}},mounted(){setTimeout(()=>{this.$refs.totp.focus()},0)}};const Wn=(0,Z.A)(qn,[["render",jn]]);var Vn=Wn;const Qn=["disabled"];function Hn(e,t,a,s,i,n){const o=(0,r.g2)("text-field"),l=(0,r.g2)("loading-button"),u=(0,r.g2)("popup-overlay");return(0,r.uX)(),(0,r.Wv)(u,{class:"change-password",headline:e.$t("ui.user-manager.passwordHeadline"),onSubmit:n.submit,onClear:n.close},{actions:(0,r.k6)(()=>[(0,r.Lk)("button",{type:"button",class:"widget-button",disabled:e.loading,onClick:t[3]||(t[3]=(...e)=>n.close&&n.close(...e))},(0,c.v_)(e.$t("ui.user-manager.cancel")),9,Qn),(0,r.bF)(l,{submit:"",color:"primary",loading:e.loading,disabled:!n.inputValid},{default:(0,r.k6)(()=>[(0,r.eW)((0,c.v_)(e.$t("ui.user-manager.submitPassword")),1)]),_:1},8,["loading","disabled"])]),default:(0,r.k6)(()=>[(0,r.Lk)("p",null,(0,c.v_)(e.$t("ui.user-manager.passwordText")),1),(0,r.bF)(o,{ref:"password",name:"current-password",type:"password",label:e.$t("ui.user-manager.currentPassword"),required:"",minlength:"8",autocomplete:"current-password",error:e.error,onKeyup:t[0]||(t[0]=t=>e.error=""),modelValue:e.currentPassword,"onUpdate:modelValue":t[1]||(t[1]=t=>e.currentPassword=t),disabled:e.loading},null,8,["label","error","modelValue","disabled"]),(0,r.bF)(o,{name:"new-password",type:"password",label:e.$t("ui.user-manager.newPassword"),placeholder:e.$t("ui.user-manager.passwordPlaceholder"),required:"",minlength:"8",autocomplete:"new-password",modelValue:e.newPassword,"onUpdate:modelValue":t[2]||(t[2]=t=>e.newPassword=t),disabled:e.loading},null,8,["label","placeholder","modelValue","disabled"])]),_:1},8,["headline","onSubmit","onClear"])}var Gn={components:{PopupOverlay:On.A,LoadingButton:ta.A,TextField:Un.A},data:()=>({loading:!1,currentPassword:"",newPassword:"",error:""}),computed:{...(0,g.aH)("auth",["username"]),inputValid:e=>e.currentPassword.length>=8&&e.newPassword.length>=8},methods:{async submit(){this.loading=!0,await this.$request.put(`api/users/${this.username}/password`,{current_password:this.currentPassword,new_password:this.newPassword},null,{200:()=>{this.$notify.success(this.$t("ui.user-manager.passwordChanged")),this.close()},422:()=>{this.error=this.$t("ui.user-manager.passwordError"),setTimeout(()=>{this.$refs.password.focus()},0)}}),this.loading=!1},close(){this.$store.commit("modals/close","change-password")}},mounted(){this.$refs.password.focus()}};const Nn=(0,Z.A)(Gn,[["render",Hn]]);var zn=Nn,Kn={components:{MainLayout:re,LoadingSpinner:Ha.A,UserScope:Ln},data:()=>({users:null}),computed:{...(0,g.aH)("auth",{currentUser:"username",hasTotp:"totpEnabled",hasPasskey:"passkey"}),...(0,g.L8)("auth",["isGranted"]),scopes:()=>te.A},methods:{load(){this.$request.get("api/users",null,{200:e=>{this.users=e.data}})},changePassword(){this.$store.commit("modals/open",{id:"change-password",component:zn})},setupTotp(){this.$store.commit("modals/open",{id:"setup-totp",component:Rn.A})},disableTotp(){this.$store.commit("modals/open",{id:"disable-totp",component:Vn})},addUser(){this.$store.commit("modals/open",{id:"invite-user",component:Pn})},async deleteUser(e){confirm(this.$t("ui.user-manager.deleteConfirm",{username:e}))&&(await this.$request.delete(`api/users/${e}`),this.$notify.success(this.$t("ui.user-manager.deleted")),this.load())}},async mounted(){this.load()}};const Jn=(0,Z.A)(Kn,[["render",bn]]);var Zn=Jn,Yn=a.p+"img/oauth.1243e742.svg";const eo={class:"view-oauth__header"},to={class:"view-oauth__product"},ao={class:"view-oauth__form"},so={class:"view-oauth__description"},io={class:"view-oauth__client"},no={class:"view-oauth__warning"},oo=["disabled"],lo={class:"view-oauth__warning"},ro=["disabled"];function co(e,t,a,s,i,n){const o=(0,r.g2)("user-scope"),l=(0,r.g2)("loading-button"),u=(0,r.g2)("boxed-layout");return(0,r.uX)(),(0,r.Wv)(u,{slotClass:"view-oauth"},{default:(0,r.k6)(()=>[(0,r.Lk)("header",eo,[t[5]||(t[5]=(0,r.Lk)("img",{src:Yn,width:"80",height:"80",alt:"",class:"view-oauth__icon"},null,-1)),(0,r.Lk)("p",to,(0,c.v_)(e.$t("ui.oauth.headline")),1)]),(0,r.Lk)("main",ao,[(0,r.Lk)("p",so,(0,c.v_)(e.$t("ui.oauth.description")),1),(0,r.Lk)("p",io,(0,c.v_)(n.hostname),1),n.scopes.length?((0,r.uX)(),(0,r.CE)(r.FK,{key:0},[(0,r.bF)(o,{class:"view-oauth__scopes",allowed:n.scopes,modelValue:e.scope,"onUpdate:modelValue":t[0]||(t[0]=t=>e.scope=t)},null,8,["allowed","modelValue"]),(0,r.Lk)("p",no,(0,c.v_)(e.$t("ui.oauth.domain")),1),(0,r.bF)(l,{class:"view-oauth__button",color:"primary",disabled:!e.valid,loading:e.authenticating,onClick:n.allowAccess},{default:(0,r.k6)(()=>[(0,r.eW)((0,c.v_)(e.$t("ui.oauth.allow")),1)]),_:1},8,["disabled","loading","onClick"]),(0,r.Lk)("button",{class:"view-oauth__button widget-button",onClick:t[1]||(t[1]=(0,A.D$)((...e)=>n.denyAccess&&n.denyAccess(...e),["prevent"])),disabled:!e.valid||e.authenticating},(0,c.v_)(e.$t("ui.oauth.deny")),9,oo),(0,r.Lk)("button",{class:"view-oauth__button widget-button widget-button--anchor",onClick:t[2]||(t[2]=(0,A.D$)((...t)=>e.logout&&e.logout(...t),["prevent"]))},(0,c.v_)(e.$t("ui.oauth.switchUser")),1)],64)):((0,r.uX)(),(0,r.CE)(r.FK,{key:1},[(0,r.Lk)("p",lo,(0,c.v_)(e.$t("ui.oauth.outOfScope")),1),(0,r.Lk)("button",{class:"view-oauth__button widget-button",onClick:t[3]||(t[3]=(0,A.D$)((...e)=>n.denyAccess&&n.denyAccess(...e),["prevent"])),disabled:!e.valid},(0,c.v_)(e.$t("ui.oauth.deny")),9,ro),(0,r.Lk)("button",{class:"view-oauth__button widget-button widget-button--anchor",onClick:t[4]||(t[4]=(0,A.D$)((...t)=>e.logout&&e.logout(...t),["prevent"]))},(0,c.v_)(e.$t("ui.oauth.switchUser")),1)],64))])]),_:1})}a(4603),a(7566),a(8721);var uo=a(728),po={components:{BoxedLayout:uo.A,LoadingButton:ta.A,UserScope:Ln},data:()=>({valid:!1,authenticating:!1,scope:null}),computed:{...(0,g.L8)("auth",["isGranted"]),hostname:e=>e.$route.query.redirect_uri?new URL(e.$route.query.redirect_uri).hostname:"???",scopes:e=>e.$route.query.scope.split(" ").filter(t=>e.isGranted(t))},methods:{...(0,g.i0)("auth",["logout"]),async allowAccess(){this.authenticating=!0;try{const e=await s.A.post(`api/users/${encodeURIComponent(this.$store.state.auth.username)}/tokens`,{client_id:this.$route.query.client_id,scope:this.scope});this.redirect({access_token:e.data.token,token_type:"bearer",scope:this.scope,endpoint:`${location.origin}${location.pathname}`})}catch(e){this.redirect({error:"server_error"})}},denyAccess(){this.redirect({error:this.scopes.length?"access_denied":"invalid_scope"})},redirect(e){const t=[];for(let i in e)t.push(encodeURIComponent(i)+"="+encodeURIComponent(e[i]));this.$route.query.state&&t.push(encodeURIComponent("state")+"="+encodeURIComponent(this.$route.query.state));const a=t.join("&"),s=this.$route.query.redirect_uri;s.includes("#")?document.location.href=`${s}&${a}`:document.location.href=`${s}#${a}`}},async mounted(){await this.$router.isReady();let e=!1;try{const t=new URL(this.$route.query.redirect_uri);"https:"!==t.protocol&&"localhost"!==t.hostname&&(e=!0)}catch(t){e=!0}if(!e)return"token"!==this.$route.query.response_type?this.redirect({error:"unsupported_response_type"}):this.$route.query.client_id?void(this.valid=!0):this.redirect({error:"invalid_request"});this.$store.commit("setError",{title:this.$t("ui.oauth.error"),detail:this.$t("ui.oauth.https"),type:"https://tools.ietf.org/html/rfc6749#section-3.1.2.1",status:400})}};const go=(0,Z.A)(po,[["render",co]]);var ho=go;const mo=e=>(0,o.aE)({history:(0,o.Bt)(),routes:[{name:l.A.discover.name,path:"/discover",component:ge},{name:l.A.packages.name,path:"/packages",component:$a},{name:l.A.maintenance.name,path:"/maintenance",component:mi},{name:l.A.migrations.name,path:"/migrations/:type(.*)*",component:fi},{name:l.A.logViewer.name,path:"/logs",component:rn},{name:l.A.userManager.name,path:"/users",component:Zn,beforeEnter:(t,a,s)=>{e.state.auth.limited?s(a):s()}},{name:l.A.oauth.name,path:"/oauth",component:ho,props:!0},{path:"/:pathMatch(.*)*",redirect:"/discover"}]});var ko=mo,vo=a(4173),bo=a(8044),_o=a(4710);const fo={id:"app"},wo={key:0,class:"app-hint app-hint--alert"},yo={class:"app-hint__headline"},Co={class:"app-hint__description"},$o={key:1,class:"app-hint"},Lo={class:"app-hint__headline"},Ao={class:"app-hint__description"},Eo={key:2,class:"app-hint app-hint--warning"},Xo={class:"app-hint__headline"},So={class:"app-hint__description"},xo=["href"],To={key:3,class:"app-hint app-hint--warning"},Mo={class:"app-hint__headline"},Oo={class:"app-hint__description"},Fo=["inert"],Io={class:"view-init__cell animate-initializing"},Po={class:"view-init__message"},Ro={key:3};function Bo(e,t,a,s,i,n){const o=(0,r.g2)("Notification"),l=(0,r.g2)("Notivue"),u=(0,r.g2)("error-view"),d=(0,r.g2)("task-view"),p=(0,r.g2)("router-view");return(0,r.uX)(),(0,r.CE)("div",fo,[(0,r.bF)(l,null,{default:(0,r.k6)(e=>[(0,r.bF)(o,{item:e},null,8,["item"])]),_:1}),e.safeMode&&"ready"===e.view?((0,r.uX)(),(0,r.CE)("div",wo,[(0,r.Lk)("strong",yo,(0,c.v_)(e.$t("ui.app.safeModeHeadline")),1),t[3]||(t[3]=(0,r.eW)("  ",-1)),(0,r.Lk)("span",Co,(0,c.v_)(e.$t("ui.app.safeModeDescription")),1),t[4]||(t[4]=(0,r.eW)("  ",-1)),(0,r.Lk)("button",{class:"app-hint__link",onClick:t[0]||(t[0]=(...e)=>n.exitSafeMode&&n.exitSafeMode(...e))},(0,c.v_)(e.$t("ui.app.safeModeExit")),1)])):e.limited?((0,r.uX)(),(0,r.CE)("div",$o,[(0,r.Lk)("strong",Lo,(0,c.v_)(e.$t("ui.app.limitedHeadline")),1),t[5]||(t[5]=(0,r.eW)("  ",-1)),(0,r.Lk)("span",Ao,(0,c.v_)(e.$t("ui.app.limitedDescription")),1),t[6]||(t[6]=(0,r.eW)("  ",-1)),(0,r.Lk)("button",{class:"app-hint__link",onClick:t[1]||(t[1]=(...t)=>e.logout&&e.logout(...t))},(0,c.v_)(e.$t("ui.app.limitedLogout")),1)])):n.isInsecure?((0,r.uX)(),(0,r.CE)("div",Eo,[(0,r.Lk)("strong",Xo,(0,c.v_)(e.$t("ui.app.httpsHeadline")),1),t[7]||(t[7]=(0,r.eW)("  ",-1)),(0,r.Lk)("span",So,(0,c.v_)(e.$t("ui.app.httpsDescription")),1),t[8]||(t[8]=(0,r.eW)("  ",-1)),(0,r.Lk)("a",{href:e.$t("ui.app.httpsHref"),target:"_blank",class:"app-hint__link"},(0,c.v_)(e.$t("ui.app.httpsLink")),9,xo)])):e.loaded&&e.username&&!e.totpEnabled?((0,r.uX)(),(0,r.CE)("div",To,[(0,r.Lk)("strong",Mo,(0,c.v_)(e.$t("ui.app.totpHeadline")),1),t[9]||(t[9]=(0,r.eW)("  ",-1)),(0,r.Lk)("span",Oo,(0,c.v_)(e.$t("ui.app.totpDescription")),1),t[10]||(t[10]=(0,r.eW)("  ",-1)),(0,r.Lk)("button",{class:"app-hint__link",onClick:t[2]||(t[2]=(...e)=>n.setupTotp&&n.setupTotp(...e))},(0,c.v_)(e.$t("ui.app.totpSetup")),1)])):(0,r.Q3)("",!0),e.error?((0,r.uX)(),(0,r.Wv)(u,{key:4})):(0,r.Q3)("",!0),(0,r.bF)(A.eB,{name:"animate-fade",mode:"out-in",style:{height:"100%"}},{default:(0,r.k6)(()=>[n.isInitializing||n.isReady?((0,r.uX)(),(0,r.CE)("div",{key:0,class:"view-init",inert:e.hasModal},[(0,r.Lk)("div",Io,[t[11]||(t[11]=(0,r.Lk)("img",{src:h,width:"100",height:"100",alt:"Contao Logo"},null,-1)),(0,r.Lk)("p",Po,(0,c.v_)(e.$t("ui.app.loading")),1)])],8,Fo)):e.username&&e.taskStatus?((0,r.uX)(),(0,r.Wv)(d,{key:1,class:(0,c.C4)(e.hasModal?"animate-blur-in":"animate-blur-out"),inert:e.hasModal},null,8,["class","inert"])):n.currentView?((0,r.uX)(),(0,r.Wv)((0,r.$y)(n.currentView),{key:2,class:(0,c.C4)(e.hasModal?"animate-blur-in":"animate-blur-out"),inert:e.hasModal},null,8,["class","inert"])):((0,r.uX)(),(0,r.CE)("div",Ro,[(0,r.bF)(p,{class:(0,c.C4)(e.hasModal?"animate-blur-in":"animate-blur-out"),inert:e.hasModal},null,8,["class","inert"])]))]),_:1}),e.hasModal?((0,r.uX)(),(0,r.Wv)((0,r.$y)(e.currentModal),{key:5})):(0,r.Q3)("",!0)])}var Do=a(953);const jo={class:"view-error"},Uo={class:"view-error__content",ref:"debug"},qo={class:"view-error__status"},Wo=["href"],Vo={class:"view-error__headline"},Qo={key:0,class:"view-error__details"},Ho={key:1,class:"view-error__debug"},Go={class:"view-error__actions"},No=["href"],zo=["href"];function Ko(e,t,a,s,i,n){return(0,r.uX)(),(0,r.CE)("div",jo,[n.isDebug?((0,r.uX)(),(0,r.CE)("button",{key:0,type:"button",class:"view-error__close",onClick:t[0]||(t[0]=(...e)=>n.close&&n.close(...e))},[...t[1]||(t[1]=[(0,r.Lk)("svg",{height:"24",viewBox:"0 0 24 24",width:"24",fill:"#fff",xmlns:"http://www.w3.org/2000/svg"},[(0,r.Lk)("path",{d:"M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z"}),(0,r.Lk)("path",{d:"M0 0h24v24H0z",fill:"none"})],-1)])])):(0,r.Q3)("",!0),(0,r.Lk)("div",Uo,[t[3]||(t[3]=(0,r.Lk)("svg",{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 512 512",class:"view-error__icon"},[(0,r.Lk)("path",{d:"M473.7 73.8l-2.4-2.5c-46-47-118-51.7-169.6-14.8L336 159.9l-96 64 48 128-144-144 96-64-28.6-86.5C159.7 19.6 87 24 40.7 71.4l-2.4 2.4C-10.4 123.6-12.5 202.9 31 256l212.1 218.6c7.1 7.3 18.6 7.3 25.7 0L481 255.9c43.5-53 41.4-132.3-7.3-182.1z"})],-1)),(0,r.Lk)("div",qo,[t[2]||(t[2]=(0,r.eW)(" ERROR ",-1)),e.error.status?((0,r.uX)(),(0,r.CE)("a",{key:0,href:`https://developer.mozilla.org/${e.$i18n.locale}/docs/Web/HTTP/Status/${e.error.status}`,target:"_blank"},(0,c.v_)(e.error.status),9,Wo)):(0,r.Q3)("",!0)]),(0,r.Lk)("h1",Vo,(0,c.v_)(n.title),1),n.detail?((0,r.uX)(),(0,r.CE)("div",Qo,(0,c.v_)(n.detail),1)):(0,r.Q3)("",!0),n.debug?((0,r.uX)(),(0,r.CE)("div",Ho,(0,c.v_)(n.debug),1)):(0,r.Q3)("",!0),(0,r.Lk)("div",Go,["about:blank"!==e.error.type?((0,r.uX)(),(0,r.CE)("a",{key:0,href:e.error.type,target:"_blank",class:"view-error__link"},(0,c.v_)(e.$t("ui.error.moreLink")),9,No)):(0,r.Q3)("",!0),(0,r.Lk)("a",{href:`https://to.contao.org/support?lang=${e.$i18n.locale}`,target:"_blank",class:"view-error__link view-error__link--support"},(0,c.v_)(e.$t("ui.error.support")),9,zo)])],512)])}var Jo={computed:{...(0,g.aH)(["error"]),response:e=>e.error.response,isDebug:()=>!1,title(){return this.error.title?this.error.title:this.response?this.$t("ui.error.title",{method:(this.response.config.headers["X-HTTP-Method-Override"]||this.response.config.method).toUpperCase(),url:this.response.config.url}):this.$t("ui.app.apiError")},detail(){return this.error.detail?this.error.detail:this.error.debug?"":500===this.error.status?this.$t("ui.error.server500"):this.response?this.$t("ui.error.response",this.error):""},debug(){return this.error.debug?this.error.debug:this.response&&this.response.data?this.response.data:""}},methods:{close(){this.$store.commit("setError",null)}},mounted(){this.debug&&this.debug.includes("window.Sfdump")&&(this.$refs.debug.innerHTML="",this.$refs.debug.classList.add("view-error__content--dump"),this.$refs.debug.append(document.createRange().createContextualFragment(this.debug)))}};const Zo=(0,Z.A)(Jo,[["render",Ko]]);var Yo=Zo,el=a.p+"img/task.e9e5333f.svg",tl=a(3382);const al={class:"view-task__header"},sl={class:"view-task__headline"},il={key:0,class:"view-task__description"},nl={class:"view-task__text"},ol={class:"view-task__text"},ll={href:"https://github.com/contao/contao-manager/issues/new",target:"_blank"},rl={class:"view-task__actions"},cl={class:"view-task__text"},ul={class:"view-task__actions"},dl={key:3,class:"view-task__actions"},pl={key:4,class:"view-task__loading"},gl={key:1,class:"view-task__sponsor"},hl=["href"];function ml(e,t,a,s,i,n){const o=(0,r.g2)("loading-button"),l=(0,r.g2)("check-box"),u=(0,r.g2)("loading-spinner"),d=(0,r.g2)("console-output"),p=(0,r.g2)("i18n-t"),g=(0,r.g2)("boxed-layout");return(0,r.uX)(),(0,r.Wv)(g,{wide:!0,slotClass:"view-task"},{default:(0,r.k6)(()=>[(0,r.Lk)("header",al,[t[3]||(t[3]=(0,r.Lk)("img",{src:el,width:"80",height:"80",alt:"",class:"view-task__icon"},null,-1)),(0,r.Lk)("h1",sl,(0,c.v_)(e.$t("ui.task.headline")),1),e.taskStatus?((0,r.uX)(),(0,r.CE)("p",il,(0,c.v_)(e.$t(`ui.task.${e.taskStatus}`)),1)):(0,r.Q3)("",!0),e.isFailed?((0,r.uX)(),(0,r.CE)(r.FK,{key:1},[(0,r.Lk)("p",nl,[(0,r.eW)((0,c.v_)(e.$t("ui.task.failedDescription1")),1),t[1]||(t[1]=(0,r.Lk)("br",null,null,-1)),(0,r.eW)(" "+(0,c.v_)(e.$t("ui.task.failedDescription2")),1)]),(0,r.Lk)("p",ol,[t[2]||(t[2]=(0,r.Lk)("br",null,null,-1)),(0,r.Lk)("a",ll,(0,c.v_)(e.$t("ui.task.reportProblem")),1)]),(0,r.Lk)("div",rl,[(0,r.bF)(o,{class:"view-task__action",loading:e.deletingTask,onClick:n.deleteTask},{default:(0,r.k6)(()=>[(0,r.eW)((0,c.v_)(e.$t("ui.task.buttonClose")),1)]),_:1},8,["loading","onClick"])])],64)):e.isPaused&&e.allowContinue?((0,r.uX)(),(0,r.CE)(r.FK,{key:2},[(0,r.Lk)("p",cl,(0,c.v_)(e.$t("ui.task.pausedDescription")),1),(0,r.Lk)("div",ul,[(0,r.bF)(o,{class:"view-task__action",color:"primary",loading:e.deletingTask,onClick:n.continueTask},{default:(0,r.k6)(()=>[(0,r.eW)((0,c.v_)(e.$t("ui.task.buttonContinue")),1)]),_:1},8,["loading","onClick"]),(0,r.bF)(o,{class:"view-task__action",loading:e.deletingTask,onClick:n.deleteTask},{default:(0,r.k6)(()=>[(0,r.eW)((0,c.v_)(e.$t("ui.task.buttonClose")),1)]),_:1},8,["loading","onClick"])])],64)):e.hasTask?((0,r.uX)(),(0,r.CE)("div",dl,[e.allowCancel&&(e.isActive||e.isAborting)?((0,r.uX)(),(0,r.Wv)(o,{key:0,class:"view-task__action",color:"alert",loading:e.isAborting,onClick:n.cancelTask},{default:(0,r.k6)(()=>[(0,r.eW)((0,c.v_)(e.$t("ui.task.buttonCancel")),1)]),_:1},8,["loading","onClick"])):(0,r.Q3)("",!0),e.requiresAudit?((0,r.uX)(),(0,r.Wv)(o,{key:1,class:"view-task__action",color:"primary",loading:e.loadingMigrations,disabled:e.supportsMigrations&&!e.hasDatabaseChanges||e.deletingTask,onClick:n.updateDatabase},{default:(0,r.k6)(()=>[(0,r.eW)((0,c.v_)(e.$t("ui.task.buttonAudit")),1)]),_:1},8,["loading","disabled","onClick"])):(0,r.Q3)("",!0),e.isActive||e.isAborting?(0,r.Q3)("",!0):((0,r.uX)(),(0,r.Wv)(o,{key:2,class:"view-task__action",loading:e.deletingTask,onClick:n.deleteTask},{default:(0,r.k6)(()=>[(0,r.eW)((0,c.v_)(e.$t("ui.task.buttonConfirm")),1)]),_:1},8,["loading","onClick"])),e.isActive&&e.allowAutoClose?((0,r.uX)(),(0,r.Wv)(l,{key:3,name:"autoclose",label:e.$t("ui.task.autoclose"),modelValue:e.autoClose,"onUpdate:modelValue":t[0]||(t[0]=t=>e.autoClose=t)},null,8,["label","modelValue"])):(0,r.Q3)("",!0)])):((0,r.uX)(),(0,r.CE)("div",pl,[(0,r.bF)(u)]))]),e.hasTask?((0,r.uX)(),(0,r.Wv)(d,{key:0,class:"view-task__main",title:e.hasTask?e.currentTask.title:e.$t("ui.task.loading"),operations:e.currentTask.operations,"console-output":e.currentTask.console},null,8,["title","operations","console-output"])):(0,r.Q3)("",!0),e.currentTask&&e.currentTask.sponsor?((0,r.uX)(),(0,r.CE)("div",gl,[(0,r.bF)(p,{keypath:"ui.task.sponsor"},{sponsor:(0,r.k6)(()=>[t[4]||(t[4]=(0,r.Lk)("br",null,null,-1)),(0,r.Lk)("a",{href:e.currentTask.sponsor.link,target:"_blank",rel:"noreferrer noopener"},(0,c.v_)(e.currentTask.sponsor.name),9,hl)]),_:1}),t[5]||(t[5]=(0,r.Lk)("a",{href:"https://to.contao.org/donate",target:"_blank",rel:"noreferrer noopener",class:"view-task__donate"},[(0,r.Lk)("img",{src:tl,alt:"",width:"20",height:"20"})],-1))])):(0,r.Q3)("",!0)]),_:1})}var kl={computed:{...(0,g.aH)("tasks",{taskStatus:"status",currentTask:"current",deletingTask:"deleting"}),hasTask:e=>e.currentTask&&e.currentTask.status,isActive:e=>e.hasTask&&"active"===e.taskStatus,isComplete:e=>e.hasTask&&"complete"===e.taskStatus,isPaused:e=>e.hasTask&&"paused"===e.taskStatus,isAborting:e=>e.hasTask&&"aborting"===e.taskStatus,isFailed:e=>"failed"===e.taskStatus,isError:e=>e.hasTask&&("error"===e.taskStatus||"stopped"===e.taskStatus||"failed"===e.taskStatus),allowAutoClose:e=>e.hasTask&&e.currentTask.autoclose,allowCancel:e=>e.hasTask&&e.currentTask.cancellable,allowContinue:e=>e.hasTask&&e.currentTask.continuable,requiresAudit:e=>e.isComplete&&e.currentTask.audit}},vl=a(2864),bl={name:"TaskView",mixins:[kl],components:{BoxedLayout:uo.A,LoadingSpinner:Ha.A,LoadingButton:ta.A,ConsoleOutput:vl.A,CheckBox:yn.A},data:()=>({autoClose:!1,favicons:null,faviconInterval:null}),computed:{...(0,g.aH)("server/database",{supportsMigrations:"supported",loadingMigrations:"loading"}),...(0,g.L8)("server/database",{hasDatabaseChanges:"hasChanges"})},methods:{cancelTask(){confirm(this.$t("ui.task.confirmCancel"))&&this.$store.dispatch("tasks/abort")},continueTask(){this.$store.dispatch("tasks/continue")},async deleteTask(){await this.$store.dispatch("tasks/deleteCurrent")},async updateDatabase(){this.supportsMigrations?(await this.$store.dispatch("tasks/deleteCurrent"),this.$store.commit("checkMigrations")):window.open("/contao/install")},updateFavicon(){let e;this.faviconInterval&&clearInterval(this.faviconInterval);const t=e=>{this.favicons.forEach(t=>{t.href=`${e}/${t.href.split("/").pop()}`})};switch(this.taskStatus){case"active":e="icons/task-active";break;case"complete":e="icons/task-success";break;case"error":case"failed":case"stopped":e="icons/task-error";break;default:return void setTimeout(t.bind(this,"icons"),2e3)}let a=!1;this.faviconInterval=setInterval(()=>{a=!a,t(a?e:"icons")},2e3)}},watch:{taskStatus(){this.updateFavicon()},autoClose(e){window.localStorage.setItem("contao_manager_autoclose",e?"1":"0")},isComplete(){this.isComplete&&this.$store.dispatch("server/database/get",!1)}},mounted(){this.favicons=document.querySelectorAll('link[class="favicon"]'),this.updateFavicon(),this.autoClose="1"===window.localStorage.getItem("contao_manager_autoclose"),this.$store.dispatch("server/database/get")},beforeUnmount(){this.updateFavicon()}};const _l=(0,Z.A)(bl,[["render",ml]]);var fl=_l,wl={components:{ErrorView:Yo,TaskView:fl,Notivue:i.Bx,Notification:i.Eg},data:()=>({views:{[N.A.ACCOUNT]:(0,Do.IG)((0,r.$V)(()=>Promise.all([a.e(859),a.e(904)]).then(a.bind(a,5523)))),[N.A.LOGIN]:(0,Do.IG)((0,r.$V)(()=>Promise.all([a.e(859),a.e(414)]).then(a.bind(a,414)))),[N.A.BOOT]:(0,Do.IG)((0,r.$V)(()=>a.e(186).then(a.bind(a,8582)))),[N.A.CONFIG]:(0,Do.IG)((0,r.$V)(()=>a.e(335).then(a.bind(a,1035)))),[N.A.SETUP]:(0,Do.IG)((0,r.$V)(()=>Promise.all([a.e(312),a.e(120)]).then(a.bind(a,8938)))),[N.A.RECOVERY]:(0,Do.IG)((0,r.$V)(()=>a.e(367).then(a.bind(a,7390)))),[N.A.MIGRATION]:(0,Do.IG)((0,r.$V)(()=>Promise.resolve().then(a.bind(a,8733))))},loaded:!1}),computed:{...(0,g.aH)(["safeMode"]),...(0,g.aH)(["view","error"]),...(0,g.aH)("auth",["username","limited","totpEnabled"]),...(0,g.aH)("tasks",{taskStatus:"status"}),...(0,g.L8)("modals",["hasModal","currentModal"]),isInitializing:e=>e.view===N.A.INIT,isReady:e=>!e.isInitializing&&!e.currentView&&!e.loaded,isInsecure:()=>"https:"!==location.protocol&&"localhost"!==location.hostname,currentView:e=>e.views[e.view]||null},methods:{...(0,g.i0)("auth",["logout"]),exitSafeMode(){window.location.reload()},initColorMode(){let e=localStorage.getItem("contao--prefers-dark");null===e&&(e=String(window.matchMedia("(prefers-color-scheme: dark)").matches)),document.documentElement.dataset.colorScheme="true"===e?"dark":"light"},async checkPublicConfig(){const e=location.pathname.split("/").filter(e=>""!==e);e.unshift("");while(void 0!==e.pop()&&e.length){let a;try{a=(await s.A.get(`${e.join("/")}/contao-manager/users.json`)).data}catch(t){continue}if(a.users||a.version)throw this.$store.commit("setError",{title:this.$t("ui.app.configSecurity1"),type:"about:blank",status:"500",detail:this.$t("ui.app.configSecurity2")}),new Error(this.$t("ui.app.configSecurity1"))}},setupTotp(){this.$store.commit("modals/open",{id:"setup-totp",component:Rn.A})}},watch:{async isReady(e){if(e){try{await this.$store.dispatch("packages/uploads/load"),await this.$store.dispatch("packages/load"),await this.$store.dispatch("algolia/discover")}catch(t){}this.loaded=!0,this.$store.dispatch("packages/details/init",{vue:this,component:(0,r.$V)(()=>Promise.all([a.e(312),a.e(756)]).then(a.bind(a,3312)))})}},username(e){null===e&&(this.$store.commit("tasks/setCurrent",null),this.$store.commit("tasks/setInitialized",!1))}},async mounted(){if(this.initColorMode(),await this.checkPublicConfig(),await this.$router.isReady(),this.$route.query.invitation)return void this.$store.commit("setView",N.A.ACCOUNT);if(this.$route.query.token){try{await s.A.post("api/session",{token:this.$route.query.token})}catch(t){}this.$router.replace({name:this.$route.name,query:null})}const e=await this.$store.dispatch("auth/status");200===e?this.$store.commit("setView",N.A.BOOT):204===e?this.$store.commit("setView",N.A.ACCOUNT):401===e||403===e?this.$store.commit("setView",N.A.LOGIN):this.$store.commit("setError",{type:"about:blank",status:e})},created(){document.title=`Contao Manager | ${location.hostname}`}};const yl=(0,Z.A)(wl,[["render",Bo]]);var Cl=yl;s.A.defaults.headers.common["Accept"]="application/json",s.A.interceptors.request.use(function(e){return"api/"===e.url.slice(0,4)&&(e.headers["Accept-Language"]=bo.A.plugin.global.locale,["PUT","PATCH","DELETE"].includes(e.method)&&(e.headers["X-HTTP-Method-Override"]=e.method,e.method="POST")),e}),s.A.interceptors.response.use(e=>(vo.A.commit("auth/renewCountdown"),e),function(e){if(!e.response)return Promise.reject(e);const t=e.response,a=t.config.url;return 401===t.status&&"api/session"!==a?(vo.A.commit("auth/reset"),vo.A.commit("setView",N.A.LOGIN),t):"application/problem+json"===t.headers["content-type"]?(500===t.status&&vo.A.commit("setError",t.data),Promise.reject(e)):"api/session"===a&&200!==t.status?t:"api/"===a.substring(0,4)&&"application/json"!==t.headers["content-type"]&&t.status>=400&&t.status<=599?(vo.A.commit("setError",{type:"about:blank",status:t.status,response:t}),Promise.reject(e)):Promise.reject(e)});const $l=(0,i.FD)({position:"bottom-right",limit:4,enqueue:!0});(0,n.A)(Cl,bo.A,[vo.A,ko(vo.A),$l],e=>{e.config.globalProperties.$notify=i.VC,e.config.globalProperties.$request=_o.A})},8200:function(e,t,a){var s=a(6278),i=a(416);t.A={mixins:[i.A],computed:{...(0,s.aH)("packages",["required","add","change"]),...(0,s.L8)("packages",["installed","hasRoot","packageInstalled","packageRoot","packageRequired","packageMissing","packageAdded","packageUpdated","packageChanged","packageRemoved","packageFeature","packageVisible","packageSuggested","packageConstraint","packageConstraintAdded","packageConstraintChanged","packageConstraintInstalled","packageConstraintRequired","contaoSupported"]),isInstalled:e=>e.packageInstalled(e.data.name),isRootInstalled:e=>e.isInstalled&&e.packageRoot(e.data.name),isRequired:e=>e.packageRequired(e.data.name),isAdded:e=>e.packageAdded(e.data.name),isMissing:e=>e.packageMissing(e.data.name),isChanged:e=>e.packageChanged(e.data.name),isUpdated:e=>e.packageUpdated(e.data.name),willBeRemoved:e=>e.packageRemoved(e.data.name),willBeInstalled:e=>e.packageAdded(e.data.name),isModified:e=>e.isUpdated||e.isChanged||e.willBeRemoved||e.willBeInstalled,isSuggested:e=>e.packageSuggested(e.data.name),isPrivate:e=>e.metadata&&!!e.metadata.private,isDependency:e=>e.metadata&&!!e.metadata.dependency,isFeature:e=>e.packageFeature(e.data.name),isVisible:e=>e.packageVisible(e.data.name),isTheme:e=>"contao-theme"===e.data.type||e.metadata&&"contao-theme"===e.metadata.type,isContao:e=>"contao/manager-bundle"===e.data.name,isUpload:e=>e.metadata&&"dist"===e.metadata["installation-source"]&&e.metadata.dist&&new RegExp("/contao-manager/packages/[^/]+.zip$","i").test(e.metadata.dist.url),installedVersion:e=>e.installed[e.data.name]?e.installed[e.data.name].version:null,installedTime:e=>e.installed[e.data.name]?e.installed[e.data.name].time:null,isCompatible:e=>e.isFeature||e.contaoSupported(e.metadata.contaoConstraint),canBeInstalled:e=>(!e.isPrivate||e.isSuggested)&&!e.isTheme&&(!e.isDependency||e.isSuggested),constraintInstalled:e=>e.packageConstraintInstalled(e.data.name),constraintRequired:e=>e.packageConstraintRequired(e.data.name),constraintAdded:e=>e.packageConstraintAdded(e.data.name),constraintChanged:e=>e.packageConstraintChanged(e.data.name),targetConstraint:e=>e.$store.state.packages?.change[e.data.name]||e.$store.state.packages?.root?.require[e.data.name]},methods:{install(){(this.isCompatible||confirm(this.$t("ui.package.incompatibleWarning",{package:this.data.name,constraint:this.packageConstraint("contao/manager-bundle")})))&&this.$store.commit("packages/add",this.metadata||this.data)},update(){this.$store.commit("packages/update",this.data.name)},uninstall(){this.willBeInstalled&&!this.isInstalled?this.$store.commit("packages/restore",this.data.name):(this.$store.commit("packages/restore",this.data.name),this.$store.dispatch("packages/uploads/unconfirm",this.data.name),this.$store.commit("packages/remove",this.data.name))}},watch:{targetConstraint(){this.$store.commit("algolia/uncache",this.data.name),this.loadMetadata()}}}},3723:function(e,t){t.A={discover:{name:"discover"},packages:{name:"packages"},maintenance:{name:"maintenance"},migrations:{name:"migrations"},logViewer:{name:"logs"},userManager:{name:"users"},oauth:{name:"oauth"}}},707:function(e,t){t.A={INIT:"init",ACCOUNT:"account",LOGIN:"login",BOOT:"boot",CONFIG:"config",SETUP:"setup",RECOVERY:"recovery",MIGRATION:"migration",READY:"ready"}},70:function(e,t){t.A={ADMIN:"admin",INSTALL:"install",UPDATE:"update",READ:"read"}},4173:function(e,t,a){a.d(t,{A:function(){return ke}});var s=a(6278),i=a(707),n=a(4335),o=a(4710),l=a(70),r=a(641),c=a(33);const u={class:"logout-warning__text"},d={class:"logout-warning__countdown"},p={key:1,class:"logout-warning__text"};function g(e,t,a,s,i,n){const o=(0,r.g2)("loading-button"),l=(0,r.g2)("popup-overlay");return(0,r.uX)(),(0,r.Wv)(l,{class:"logout-warning",headline:e.$t("ui.logout.headline"),headlineType:0===e.countdown?"alert":null},{actions:(0,r.k6)(()=>[e.countdown>0?((0,r.uX)(),(0,r.CE)(r.FK,{key:0},[(0,r.bF)(o,{color:"primary",loading:e.renew,disabled:e.logout,onClick:n.keepAlive},{default:(0,r.k6)(()=>[(0,r.eW)((0,c.v_)(e.$t("ui.logout.renew")),1)]),_:1},8,["loading","disabled","onClick"]),(0,r.bF)(o,{onClick:n.doLogout,loading:e.logout,disabled:e.renew},{default:(0,r.k6)(()=>[(0,r.eW)((0,c.v_)(e.$t("ui.logout.logout")),1)]),_:1},8,["onClick","loading","disabled"])],64)):((0,r.uX)(),(0,r.Wv)(o,{key:1,onClick:n.close},{default:(0,r.k6)(()=>[(0,r.eW)((0,c.v_)(e.$t("ui.logout.login")),1)]),_:1},8,["onClick"]))]),default:(0,r.k6)(()=>[e.countdown>0?((0,r.uX)(),(0,r.CE)(r.FK,{key:0},[(0,r.Lk)("p",u,(0,c.v_)(e.$t("ui.logout.warning")),1),(0,r.Lk)("p",d,(0,c.v_)(n.minutes)+":"+(0,c.v_)(n.seconds),1)],64)):((0,r.uX)(),(0,r.CE)("p",p,(0,c.v_)(e.$t("ui.logout.expired")),1))]),_:1},8,["headline","headlineType"])}var h=a(1687),m=a(5506),k={components:{PopupOverlay:h.A,LoadingButton:m.A},data:()=>({renew:!1,logout:!1}),computed:{...(0,s.aH)("auth",["countdown"]),minutes(){return Math.floor(this.countdown/60)},seconds(){const e=this.countdown%60;return e<10?`0${e}`:e}},methods:{async keepAlive(){this.renew=!0,await this.$store.dispatch("auth/status"),this.renew=!1},async doLogout(){this.logout=!0,await this.$store.dispatch("auth/logout"),this.logout=!1},close(){this.$store.commit("auth/resetCountdown")}}},v=a(6262);const b=(0,v.A)(k,[["render",g]]);var _=b;let f,w,y,C;const $=function(){clearInterval(f),y=Date.now()+18e5,w=1800,f=setInterval(A,1e3),C.commit("setCountdown",w),C.commit("modals/close","logout-warning",{root:!0})},L=function(){y=null,w=null,clearInterval(f),f=void 0,C.commit("setCountdown",w),C.commit("modals/close","logout-warning",{root:!0})},A=function(){w>0&&(w=Math.floor(Math.max(y-Date.now(),0)/1e3)),w<=300&&C.commit("modals/open",{id:"logout-warning",component:_,priority:255},{root:!0}),0===w&&(C.dispatch("logout"),clearInterval(f)),C.commit("setCountdown",w)};var E={namespaced:!0,state:{username:null,scope:null,limited:!1,totpEnabled:!1,passkey:!1,countdown:null},getters:{isGranted:e=>t=>{const a=Object.values(l.A);return e.scope&&a.indexOf(e.scope)<=a.indexOf(t)}},mutations:{setUser(e,t){e.username=t?.username||null,e.scope=t?.scope||null,e.limited=t?.limited||!1,e.totpEnabled=t?.totp_enabled||t?.passkey||!1,e.passkey=t?.passkey||!1},setCountdown(e,t){e.countdown=t},renewCountdown(){C&&$()},resetCountdown(){C&&L()}},actions:{status(e){return C=e,n.A.get("api/session").then(t=>(t.data.username?(e.commit("setUser",t.data),$()):(e.commit("setUser",null),L()),t.status)).catch(t=>(e.commit("setUser",null),L(),403===t.response?.status&&e.commit("setLocked",null,{root:!0}),t.response?.status))},async login(e,t){return C=e,await o.A.post("api/session",t,null,{201:t=>(e.commit("setUser",t.data),$(),t),401:e=>e,403:t=>(e.commit("setLocked",null,{root:!0}),t),422:e=>e})},logout({commit:e}){return n.A.delete("api/session").then(()=>!0,e=>401===e.status).then(t=>(t&&(e("setUser",null),e("setView",i.A.LOGIN,{root:!0}),L()),t))}}},X=a(7943),S={namespaced:!0,state:{enabled:null,status:null},getters:{isLoading:e=>null===e.enabled||null===e.status,isReady:e=>e.enabled&&null!==e.status&&!!e.status.appVersion,hasError:(e,t)=>e.enabled&&!t.isLoading&&!t.isReady},mutations:{setEnabled(e,t){e.enabled=t},setStatus(e,t){e.status=t}},actions:{async fetch({state:e,commit:t,dispatch:a}){let s=e.enabled;if(null===e.enabled){try{const e=await a("server/config/get",null,{root:!0});s=!!e.cloud?.enabled}catch(i){s=!1}t("setEnabled",s)}if(s)try{const e=await n.A.get("https://www.composer-resolver.cloud/",{timeout:2500,responseType:"json",headers:{"Composer-Resolver-Client":"contao"}});if(!e.data?.appVersion)return void t("setStatus",{});t("setStatus",e.data)}catch(i){t("setStatus",{})}else t("setStatus",{})}}},x={namespaced:!0,actions:{get(){return n.A.get("api/config/composer").then(e=>e.data)},put(e,t){return n.A.put("api/config/composer",t).then(e=>e.data)},patch(e,t){return n.A.patch("api/config/composer",t).then(e=>e.data)}}},T={namespaced:!0,modules:{composer:x}},M=a(156),O=(a(4423),a(4114),a(8111),a(2489),a(116),a(7588),a(9589)),F=a(950),I=a(9997);a(1701),a(8237);const P=e=>{const t=Object.values(e).reduce((e,t)=>(e[t.hash]=(e[t.hash]||0)+1,e),{});return!!Object.values(t).find(e=>e>1)};var R={namespaced:!0,state:{uploads:null,uploading:!1,files:[],confirmed:[],removing:[]},getters:{hasUploads:(e,t)=>t.totalUploads>0,isDuplicate:e=>(t,a)=>Object.values(e.uploads).find(s=>s.id!==t&&(s.hash===e.uploads[t].hash||e.uploads[s.id]?.package?.name===a)),isRemoving:e=>t=>e.removing.includes(t),totalUploads:(e,t)=>e.uploads?t.unconfirmedUploads.length:0,unconfirmedUploads:e=>Object.values(e.uploads).filter(t=>!e.confirmed.includes(t.id)),canConfirmUploads:(e,t,a,s)=>!!e.uploads&&(void 0===Object.values(e.uploads).find(e=>!e.success||e.error||Object.keys(a.packages.installed).includes(e.package.name)&&a.packages.installed[e.package.name].version===e.package.version||e.package.require&&!s["packages/contaoSupported"](e.package.require["contao/core-bundle"]||e.package.require["contao/manager-bundle"]))&&!P(e.uploads))},mutations:{setUploads(e,t){e.uploads=t},setUploading(e,t){e.uploading=!!t},setFiles(e,t){e.files=t},setConfirmed(e,t){e.confirmed.push(t)},setUnconfirmed(e,t){delete e.confirmed[e.confirmed.indexOf(t)]},setRemoving(e,t){e.removing.push(t)},setRemoved(e,t){e.removing=e.removing.filter(e=>e!==t)}},actions:{async load({commit:e}){try{e("setUploads",(await n.A.get("api/packages/uploads")).data)}catch(t){if(501!==t.status)throw t;e("setUploads",!1)}},async confirm({state:e,commit:t},a){const s=e.uploads[a].package;s&&(this.getters["packages/packageInstalled"](s.name)?this.commit("packages/change",s):this.commit("packages/add",Object.assign({},s,{constraint:s.version})),s.suggest&&await Promise.all(Object.keys(s.suggest).map(async e=>{if(!this.getters["packages/packageInstalled"](e)){const t=await this.dispatch("packages/metadata",{name:e});t.contaoConstraint&&!this.getters["packages/contaoSupported"](t.contaoConstraint)||this.commit("packages/add",t)}})),t("setConfirmed",a))},confirmAll({state:e,dispatch:t}){Object.keys(e.uploads).forEach(e=>t("confirm",e))},unconfirm({state:e,commit:t},a){const s=e.confirmed.includes(a)?a:Object.keys(e.uploads).find(t=>e.uploads[t].package&&e.uploads[t].package.name===a&&e.confirmed.includes(t));if(!s)return;t("setUnconfirmed",s);const i=e.uploads[s].package;i&&i.suggest&&Object.keys(i.suggest).forEach(e=>{this.getters["packages/packageAdded"](e)&&this.commit("packages/restore",e)})},unconfirmAll({state:e,dispatch:t}){Object.keys(e.uploads).forEach(e=>t("unconfirm",e))},async remove({commit:e,dispatch:t},a){e("setRemoving",a),await n.A.delete(`api/packages/uploads/${a}`),await t("load"),e("setRemoved",a),await t("unconfirm",a)},async removeAll({state:e,commit:t,dispatch:a}){await Promise.all(Object.keys(e.uploads).map(async a=>{e.confirmed.includes(a)||(t("setRemoving",a),await n.A.delete(`api/packages/uploads/${a}`),t("setRemoved",a))})),await a("load")}}};const B=["contao/core-bundle","contao/installation-bundle","contao/conflicts"],D=e=>e.includes("/")&&!B.includes(e),j=(e,t)=>D(e)&&!t.packageFeature(e);var U={namespaced:!0,modules:{details:F.A,uploads:R},state:{root:null,local:null,installed:null,required:{},add:{},change:{},update:[],remove:[]},getters:{hasRoot:e=>!!e.root,packageInstalled:(e,t)=>a=>Object.keys(e.installed).includes(a)&&!t.packageMissing(a),versionInstalled:e=>(t,a)=>Object.keys(e.installed).includes(t)&&e.installed[t].version===a,packageRoot:e=>t=>!!e.root&&Object.keys(e.root.require).includes(t),packageRequired:e=>t=>Object.keys(e.required).includes(t)&&!!e.required[t].constraint,packageMissing:e=>t=>Object.keys(e.required).includes(t)&&!e.required[t].constraint,packageAdded:e=>t=>Object.keys(e.add).includes(t),packageChanged:e=>t=>Object.keys(e.change).includes(t),packageUpdated:e=>t=>e.update.includes(t),packageRemoved:e=>t=>e.remove.includes(t),packageFeatures:()=>e=>I.A[e]?I.A[e]:{},packageFeature:(e,t)=>e=>!!Object.keys(I.A).find(a=>I.A[a][e]&&(t.packageInstalled(a)||t.packageRequired(a))),packageVisible:(e,t)=>e=>j(e,t),packageSuggested:e=>t=>!!Object.values(e.local||{}).concat(Object.values(e.add||{})).find(e=>e.type&&("contao-"===e.type.substr(0,7)||"contao/"===e.name.substr(0,7))&&e.suggest&&Object.prototype.hasOwnProperty.call(e.suggest,t)),totalChanges:e=>Object.keys(e.add).filter(D).length+Object.keys(e.required).filter(D).length+Object.keys(e.change).filter(D).length+e.update.length+e.remove.length-Object.values(e.add).filter(t=>Object.keys(e.required).includes(t.name)).length-Object.values(e.change).filter(t=>Object.keys(e.required).includes(t.name)).length-e.remove.filter(t=>Object.keys(e.required).includes(t)).length,totalRequired:e=>Object.keys(e.required).length-Object.values(e.add).filter(t=>Object.keys(e.required).includes(t.name)).length-Object.values(e.change).filter(t=>Object.keys(e.required).includes(t.name)).length-e.remove.filter(t=>Object.keys(e.required).includes(t)).length,packageIncompatible:(e,t)=>!!Object.values(e.add).find(e=>!e.constraint&&!t.contaoSupported(e.contaoConstraint)&&!t.packageFeature(e.name)),canResetChanges:(e,t)=>t.totalChanges>t.totalRequired,visibleRequired:(e,t)=>Object.values(e.required).filter(e=>j(e.name,t)),visibleInstalled:(e,t)=>Object.values(t.installed).filter(e=>j(e.name,t)),visibleAdded:(e,t)=>Object.values(e.add).filter(e=>j(e.name,t)),installed:e=>{if(!e.root||!e.installed)return{};const t={};return Object.keys(e.root.require).forEach(a=>{a.includes("/")&&e.installed[a]&&(t[a]={name:a,version:!1,constraint:e.root.require[a]},t[a]=Object.assign(t[a],e.installed[a]))}),t},packageConstraint:(e,t)=>e=>t.packageConstraintAdded(e)||t.packageConstraintChanged(e)||t.packageConstraintInstalled(e)||t.packageConstraintRequired(e),packageConstraintAdded:(e,t)=>a=>t.packageAdded(a)?e.add[a].constraint:null,packageConstraintChanged:(e,t)=>a=>t.packageChanged(a)?e.change[a]:null,packageConstraintInstalled:(e,t)=>e=>t.packageInstalled(e)&&t.packageRoot(e)?t.installed[e].constraint:null,packageConstraintRequired:(e,t)=>a=>t.packageRequired(a)?null:t.packageChanged(a)?t.constraintChanged(a):e.required[a]?.constraint,contaoConstraint:(e,t)=>t.packageConstraint("contao/manager-bundle")?(0,O.coerce)(t.packageConstraint("contao/manager-bundle"),{includePrerelease:!0}).toString():"",contaoSupported:(e,t)=>e=>!e||(0,O.intersects)(e,t.contaoConstraint,{includePrerelease:!0,loose:!0})},mutations:{setInstalled(e,{root:t,local:a,missing:s}){const i={},n={};a&&Object.keys(a).forEach(e=>{!1===a[e].version?n[e]=a[e]:i[e]=a[e]}),t&&Object.keys(t.require).forEach(e=>{e.includes("/")&&(Object.prototype.hasOwnProperty.call(i,e)||Object.prototype.hasOwnProperty.call(n,e)||(n[e]={name:e,constraint:t.require[e]}))}),s&&s.forEach(e=>{n[e]={name:e,constraint:null}}),e.root=t,e.local=a,e.installed=i,e.required=n},clearInstalled(e){e.root=null,e.local=null,e.installed=null,e.required={}},add(e,t){e.add[t.name]=t},change(e,{name:t,version:a}){this.commit("packages/restore",t),e.change[t]=a},update(e,t){this.commit("packages/restore",t),e.update.push(t)},remove(e,t){this.commit("packages/restore",t),e.remove.push(t)},restore(e,t){delete e.add[t],delete e.change[t],e.remove.includes(t)&&e.remove.splice(e.remove.indexOf(t),1),e.update.includes(t)&&e.update.splice(e.update.indexOf(t),1)},reset(e){e.add={},e.change={},e.update=[],e.remove=[]}},actions:{async metadata({state:e,dispatch:t},a){const s=a.name;if(a&&!a.source&&a.extra&&a.extra["contao-metadata-url"])return a;const i=await t("algolia/getPackage",s,{root:!0});if(!i)return a;const n=e=>e.version&&(0,O.valid)(e.version)?(0,O.parse)(e.version):e.version_normalized?(0,O.coerce)(e.version_normalized,{loose:!0}):null,o=e.change[s]||e.root?.require[s],l=e.installed?n(a):null;if(i.update=null,i.versions&&o&&"dev-"!==o.substr(0,4)&&"-dev"!==o.substr(-4)&&l&&i.versions.find(e=>e.version===l.version)){const e=i.versions.filter(e=>e.version===l.version||(0,O.satisfies)(n(e),o)).pop();e?(i.update={valid:!0,latest:(0,O.eq)(n(e),l),version:e.version,time:e.time},i.latest&&i.latest.version&&(i.latest.active=(0,O.eq)(n(e),i.latest.version))):i.update={valid:!1,latest:!0,version:null,time:null}}let r=i?.features?Object.keys(i.features):[];l&&(r=r.filter(e=>(0,O.satisfies)(l,i.features[e])));const c=Object.assign({},i,{dependents:a.dependents||i.dependents,conflict:a.conflict||i.conflict,require:a.require||i.require,"require-dev":a["require-dev"]||i["require-dev"],suggest:i.suggest,features:r});return a.suggest&&(c.suggest={},Object.keys(a.suggest).forEach(e=>{c.suggest[e]=i.suggest&&i.suggest[e]||a.suggest[e]})),c},async load({state:e,commit:t,getters:a},s=!0){t("clearInstalled"),t("algolia/reset",null,{root:!0}),s&&t("reset");const i=[n.A.get("api/packages/root"),n.A.get("api/packages/local"),n.A.get("api/packages/missing")];t("setInstalled",{root:(await i[0]).data,local:(await i[1]).data,missing:(await i[2]).data}),s||(Object.keys(e.add).forEach(e=>{a.packageInstalled(e)&&(t("restore",e),t("update",e))}),Object.keys(e.change).forEach(s=>{a.versionInstalled(s,e.change[s])&&(t("restore",s),t("update",s))}),e.remove.forEach(e=>{a.packageInstalled(e)||t("restore",e)}))},apply({state:e,dispatch:t},a={dry_run:!1,update_all:!1}){const s=Object.assign({},e.change),i=Array.from(e.remove),n=Array.from(e.update).concat(Object.keys(e.required),Object.keys(e.change).filter(t=>!Object.keys(e.required).includes(t)),Array.from(e.remove).filter(t=>!Object.keys(e.required).includes(t)));Object.keys(e.add).forEach(t=>{s[e.add[t].name]=e.add[t].constraint||null,n.push(e.add[t].name)}),Object.keys(I.A).forEach(t=>{Object.keys(I.A[t]).forEach(a=>{if(e.root&&Object.keys(e.root.require).includes(a)||e.installed&&Object.keys(e.installed).includes(a))return n.includes(t)&&n.push(a),void(s[t]?s[a]=s[t]:i.includes(t)&&i.push(a));Object.prototype.hasOwnProperty.call(s,a)&&(n.includes(a)||n.push(a),!Object.prototype.hasOwnProperty.call(s,t)&&e.root?.require[t]?s[a]=e.root.require[t]:Object.prototype.hasOwnProperty.call(s,t)&&(s[a]=s[t]))})});const o={require:s,remove:i,uploads:!0,dry_run:!!a.dry_run};a.update_all||(o.update=n);const l={name:"composer/update",config:o};return t("tasks/execute",l,{root:!0})},updateAll({state:e,getters:t,commit:a}){Object.keys(e.root.require).forEach(e=>{j(e,t)&&a("update",e)})}}};const q=(e,{commit:t})=>new Promise((a,s)=>{e.then(e=>{t("setCache",e.data["access-key"]),t("setIsEnabled",""!==e.data["access-key"]),a(e.data["access-key"])}).catch(()=>{t("setIsEnabled",!1),s()})});var W={namespaced:!0,state:{cache:null,isEnabled:null},mutations:{setCache(e,t){e.cache=t},setIsEnabled(e,t){e.isEnabled=t}},actions:{get(e,t=!0){return t&&e.state.cache?Promise.resolve(e.state.cache):e.rootState.safeMode||e.rootState.server.contao.contaoApi.version<1||!e.rootState.server.contao.contaoApi.features?.["contao/manager-bundle"]?.["dot-env"]?.includes("APP_DEV_ACCESSKEY")?Promise.reject():q(n.A.get("api/contao/access-key"),e)},set(e,t){return q(n.A.put("api/contao/access-key",t),e)},delete(e){return q(n.A.delete("api/contao/access-key"),e)}}},V={namespaced:!0,state:{cache:null,isSupported:null,isLocked:null},mutations:{setCache(e,t){e.cache=t,e.isSupported=!t&&null,e.isLocked=null,t&&200===t.status&&(e.isSupported=!0,e.isLocked=!0===t.data.locked)}},actions:{fetch(e,t=!0){if(t&&e.state.cache)return Promise.resolve(e.state.cache);if(e.rootState.safeMode)return e.commit("setCache"),Promise.resolve();const a=t=>(e.commit("setCache",t),Promise.resolve(t));return n.A.get("api/contao/install-tool/lock").then(a).catch(e=>a(e.response))},lock(e){const t=t=>(e.commit("setCache",t),Promise.resolve(t));return n.A.put("api/contao/install-tool/lock").then(t).catch(e=>t(e.response))},unlock(e){const t=t=>(e.commit("setCache",t),Promise.resolve(t));return n.A.delete("api/contao/install-tool/lock").then(t).catch(e=>t(e.response))}}};const Q=(e,{commit:t})=>new Promise((a,s)=>{e.then(e=>{t("setCache",e.data),t("setIsDebugEnabled",204!==e.status&&e.data.debug),a(e.data)}).catch(()=>{t("setIsDebugEnabled",!1),s()})});var H={namespaced:!0,state:{cache:null,isDebugEnabled:null},mutations:{setCache(e,t){e.cache=t},setIsDebugEnabled(e,t){e.isDebugEnabled=t}},actions:{get(e,t=!0){return t&&e.state.cache?Promise.resolve(e.state.cache):e.rootState.safeMode||e.rootState.server.contao.contaoApi.version<2||!e.rootState.server.contao.contaoApi.features?.["contao/manager-bundle"]?.["jwt-cookie"]?.includes("debug")?Promise.reject():Q(n.A.get("api/contao/jwt-cookie"),e)},enableDebug(e){return Q(n.A.put("api/contao/jwt-cookie",{debug:!0}),e)},disableDebug(e){return Q(n.A.put("api/contao/jwt-cookie",{debug:!1}),e)},delete(e){return Q(n.A.delete("api/contao/jwt-cookie"),e)}}};const G=(e,{commit:t})=>new Promise((a,s)=>{e.then(e=>{t("setCache",e.data.enabled),t("setIsEnabled",!0===e.data.enabled),a(e.data.enabled)}).catch(()=>{t("setIsEnabled",!1),s()})});var N={namespaced:!0,state:{cache:null,isEnabled:null},mutations:{setCache(e,t){e.cache=t},setIsEnabled(e,t){e.isEnabled=t}},actions:{isEnabled(e,t=!0){return t&&e.state.cache?Promise.resolve(e.state.cache):e.rootState.safeMode?Promise.reject():G(n.A.get("api/contao/maintenance-mode"),e)},enable(e){return G(n.A.put("api/contao/maintenance-mode"),e)},disable(e){return G(n.A.delete("api/contao/maintenance-mode"),e)}}},z={namespaced:!0,state:{cache:null,loading:!1,supported:!1,files:[],restore:!1,restored:!1},getters:{hasBackups:e=>e.supported&&e.files&&e.files.length>0},mutations:{setLoading(e,t){e.loading=!!t},setCache(e,t){e.cache=t,e.loading=!1,e.supported=!t&&null,e.files=[],t&&200===t.status&&(e.supported=!0,e.files=t.data)},setRestore(e,t){e.restore=t},setRestored(e){e.restored=!0}},actions:{fetch({state:e,commit:t},a=!0){if(a&&e.cache)return new Promise(t=>{t(e.cache)});const s=e=>(t("setCache",e),e);return t("setLoading",!0),n.A.get("api/contao/backup").then(s).catch(e=>s(e.response))}}},K={namespaced:!0,modules:{"access-key":W,backup:z,"install-tool":V,"jwt-cookie":H,"maintenance-mode":N},state:{package:null,version:null},mutations:{installTheme(e,{package:t,version:a}){e.package=t,e.version=a}},actions:{install({commit:e,dispatch:t},a){e("installTheme",{package:null,version:null});const s={name:"contao/install",config:a};return t("tasks/execute",s,{root:!0})}}},J={namespaced:!0,state:{cache:null},mutations:{setCache(e,t){e.cache=t}},actions:{get({state:e,commit:t},a=!0){return a&&e.cache?new Promise(t=>{t(e.cache)}):n.A.get("api/server/composer").then(e=>e.data).then(e=>(t("setCache",e),e))}}},Z={namespaced:!0,state:{cache:null},mutations:{setCache(e,t){e.cache=t}},actions:{async get({state:e,commit:t},a=!0){if(a&&e.cache)return e.cache;const s=(await n.A.get("api/server/config")).data;return t("setCache",s),s},async set({commit:e},t){try{const a=(await n.A.put("api/server/config",t)).data;return e("setCache",a),a}catch(a){if(!a.response)throw a;return a.response.data}}}},Y={namespaced:!0,state:{cache:null,contaoVersion:null,contaoApi:null,contaoConfig:null},getters:{badgeTitle:e=>e.contaoConfig?.backend?.badge_title},mutations:{setCache(e,t){e.cache=t,e.contaoVersion=null,e.contaoApi=null,e.contaoConfig=null,t&&(e.contaoVersion=t.data.version,e.contaoApi=t.data.api,e.contaoConfig=t.data.config)}},actions:{get({state:e,commit:t},a=!0){if(a&&e.cache)return new Promise(t=>{t(e.cache)});const s=e=>(t("setCache",e),e);return n.A.get("api/server/contao").then(s).catch(e=>s(e.response))},documentRoot(e,{directory:t,usePublicDir:a=!1}){const s={usePublicDir:a};return t&&(s.directory=t),n.A.post("api/server/contao",s).catch(e=>e)}}},ee={namespaced:!0,state:{cache:null,loading:!1,supported:null,status:null,pattern:null,url:null},getters:{totalMigrations:e=>e.status&&"migration"===e.status.type?e.status.total:0,totalSchemaUpdates:e=>e.status&&"schema"===e.status.type?e.status.total:0,hasError:e=>!!e.status&&("error"===e.status.type||"problem"===e.status.type),hasWarning:e=>!!e.status&&e.status.warnings>0,hasChanges:(e,t)=>!!t.totalMigrations||!!t.totalSchemaUpdates,totalChanges:(e,t)=>t.totalMigrations+t.totalSchemaUpdates,accessProblem:e=>!!e.status&&"error"===e.status.type&&e.status.message.toLowerCase().includes("access denied")},mutations:{setLoading(e,t){e.loading=!!t},setCache(e,t){e.cache=t,e.loading=!1,e.supported=!t&&null,e.status=null,e.url=null,t&&200===t.status&&(e.supported=!0,e.status=t.data.status,e.pattern=t.data.pattern,e.url=t.data.url)}},actions:{get({state:e,commit:t},a=!0){if(a&&e.cache)return new Promise(t=>{t(e.cache)});const s=e=>(t("setCache",e),e);return t("setLoading",!0),n.A.get("api/server/database").then(s).catch(e=>s(e.response))},set({commit:e},t){const a=t=>(e("setCache",t),t);return e("setLoading",!0),n.A.post("api/server/database",{url:t}).then(a).catch(e=>a(e.response))}}},te={namespaced:!0,state:{cache:null,supported:!1,hasUser:null},mutations:{setCache(e,t){e.cache=t,e.supported=!1,e.hasUser=null,!t||200!==t.status&&201!==t.status||(e.supported=!0,e.hasUser=!!t.data.hasUser)}},actions:{get({state:e,commit:t},a=!0){if(a&&e.cache)return new Promise(t=>{t(e.cache)});const s=e=>(t("setCache",e),e);return n.A.get("api/server/admin-user").then(s).catch(e=>s(e.response))},set({commit:e},t){const a=t=>(e("setCache",t),t);return n.A.post("api/server/admin-user",t).then(a).catch(e=>a(e.response))}}},ae={namespaced:!0,state:{cache:null},mutations:{setCache(e,t){e.cache=t}},actions:{get({state:e,commit:t},a=!0){return a&&e.cache?new Promise(t=>{t(e.cache)}):n.A.get("api/server/opcache").then(e=>e.data).then(e=>(t("setCache",e),e))},delete({commit:e},t){return n.A.delete(`api/server/opcache?opcache_reset=${encodeURIComponent(t)}`).then(e=>e.data).then(t=>(e("setCache",t),t))}}},se={namespaced:!0,state:{cache:null},mutations:{setCache(e,t){e.cache=t}},actions:{get({state:e,commit:t},a=!0){return a&&e.cache?new Promise(t=>{t(e.cache)}):n.A.get("api/server/php-cli").then(e=>e.data).then(e=>(t("setCache",e),e))}}},ie={namespaced:!0,state:{cache:null},mutations:{setCache(e,t){e.cache=t}},actions:{async get({state:e,commit:t},a=!0){if(a&&e.cache)return e.cache;const s=(await n.A.get("api/server/phpinfo",{responseType:"text"})).data;return t("setCache",s),s}}},ne={namespaced:!0,state:{cache:null,phpVersion:null,phpVersionId:null},mutations:{setCache(e,t){e.cache=t,e.phpVersion=null,e.phpVersionId=null,t&&200===t.status&&(e.phpVersion=t.data.version,e.phpVersionId=t.data.version_id)}},actions:{get({state:e,commit:t},a=!0){if(a&&e.cache)return new Promise(t=>{t(e.cache)});const s=e=>(t("setCache",e),Promise.resolve(e));return n.A.get("api/server/php-web").then(s).catch(e=>s(e.response))}}},oe={namespaced:!0,state:{cache:null},mutations:{setCache(e,t){e.cache=t}},actions:{get({state:e,commit:t},a=!0){return a&&e.cache?new Promise(t=>{t(e.cache)}):n.A.get("api/server/self-update").then(e=>e.data).catch(e=>{if(501===e.response?.status)return{current_version:null,latest_version:null,channel:"dev",supported:!1,error:null};throw e}).then(e=>(t("setCache",e),e))},async latest(){const e=await n.A.get("https://download.contao.org/contao-manager/stable/contao-manager.version");return e.data.version}}},le={namespaced:!0,modules:{composer:J,config:Z,contao:Y,database:ee,adminUser:te,opcache:ae,phpinfo:ie,"php-cli":se,"php-web":ne,"self-update":oe}};a(4628);let re,ce,ue,de=0,pe=!1;const ge=(e,t,a,s=5e3,i=1)=>{setTimeout(()=>{n.A.get("api/task",{timeout:5e3*i}).then(s=>re(s,e,t,a)).catch(s=>ce(s,e,t,a))},s)};re=(e,t,a,s)=>{if(de=0,204===e.status)return void a();if(!(e.data instanceof Object))return pe||t.commit("apiError",e,{root:!0}),void s();const i=e.data;switch(t.commit("setCurrent",i),i.status){case"paused":break;case"active":case"aborting":ge(t,a,s);break;case"terminated":case"complete":i.autoclose&&"1"===window.localStorage.getItem("contao_manager_autoclose")&&t.dispatch("deleteCurrent"),a(i);break;case"stopped":case"error":s(i);break;default:s(i);break}},ce=(e,t,a,s)=>{e.request&&!e.response&&(de+=1,de<=5)?ge(t,a,s,5e3,de+1):(pe||t.commit("setStatus","failed"),s())};var he={namespaced:!0,state:{status:null,current:null,deleting:!1,initialized:!1},mutations:{setStatus(e,t){e.status=t},setCurrent(e,t){e.deleting=!1,e.current=t,e.status=t?t.status:null},setDeleting(e,t){e.deleting=!!t},setInitialized(e,t){e.initialized=!!t}},actions:{async init(e){if(e.state.initialized)return Promise.resolve();if(ue)return ue.promise;ue=Promise.withResolvers();const t=()=>{e.commit("setInitialized",!0),ue.resolve(),ue=null};return ge(e,t,t),ue.promise},execute(e,t){return null!==e.state.status?Promise.reject():(ue=Promise.withResolvers(),pe=!!t.ignoreErrors,delete t.ignoreErrors,e.commit("setCurrent",t),e.commit("setStatus","created"),n.A.put("api/task",t).then(t=>re(t,e,ue.resolve,ue.reject)).catch(t=>ce(t,e,ue.resolve,ue.reject)),ue.promise)},abort(e){return null===e.state.status?Promise.reject():(e.commit("setStatus","aborting"),ue||(ue=Promise.withResolvers()),n.A.patch("api/task",{status:"aborting"}).then(t=>re(t,e,ue.resolve,ue.reject)).catch(t=>ce(t,e,ue.resolve,ue.reject)),ue.promise)},continue(e){if(!ue||!e.state.current?.continuable)return Promise.reject();e.commit("setStatus","active"),n.A.patch("api/task",{status:"active"}).then(t=>re(t,e,ue.resolve,ue.reject)).catch(t=>ce(t,e,ue.resolve,ue.reject))},async deleteCurrent({commit:e,dispatch:t},a=2){e("setDeleting",!0),ue&&(ue.resolve(),ue=null);try{await n.A.delete("api/task"),e("setCurrent",null),await t("server/contao/get",!1,{root:!0})}catch(s){const i=s.response;if(400===i.status)return void e("setCurrent",null);if(403===i.status&&a>0)return new Promise(e=>{setTimeout(()=>{e(t("deleteCurrent",a-1))},5e3)});"application/problem+json"===i.headers.get("Content-Type")?e("setError",i.data,{root:!0}):e("setError",{type:"about:blank",status:i.status,response:i},{root:!0})}}}};const me=(0,s.y$)({modules:{auth:E,algolia:X.A,cloud:S,config:T,modals:M.A,packages:U,contao:K,server:le,tasks:he},state:{view:i.A.INIT,setupStep:0,migrationsType:"",error:null,locked:!1,safeMode:!1},mutations:{setView(e,t){e.view=t,t===i.A.READY&&(e.setupStep=0)},setLocked(e){e.view=i.A.LOGIN,e.locked=!0},setError(e,t){t&&e.error||(e.error=t)},setSafeMode(e,t){e.safeMode=!!t},setup(e,t){e.view=i.A.SETUP,e.setupStep=t},checkMigrations(e,t=""){e.view=i.A.MIGRATION,e.migrationsType=t},apiError:(e,t)=>{if(!e.error)if("application/problem+json"===t.headers["content-type"]){const a=t.data;a.response=t,e.error=a}else e.error={type:"about:blank",status:t.status||"",response:t}}},actions:{reset({commit:e}){e("server/composer/setCache"),e("server/config/setCache"),e("server/contao/setCache"),e("server/database/setCache"),e("server/adminUser/setCache"),e("server/opcache/setCache"),e("server/phpinfo/setCache"),e("server/php-cli/setCache"),e("server/php-web/setCache"),e("server/self-update/setCache"),e("contao/install-tool/setCache"),e("contao/backup/setCache"),e("tasks/setInitialized",!1),e("cloud/setStatus",null),e("setSafeMode",!1)}}});var ke=me},4960:function(e,t){t.A=e=>{let t=["KB","MB","GB"],a="Bytes";while(e>1024)e/=1024,a=t.shift();return`${Math.round(100*e)/100} ${a}`},(Object.getOwnPropertyDescriptor(t.A,"name")||{}).writable||Object.defineProperty(t.A,"name",{value:"default",configurable:!0})},4710:function(e,t,a){a(4423);var s=a(4335),i=a(4173);const n=new Proxy(s.A,{get(e,t){const a={request:1,get:2,delete:2,head:2,options:2,post:3,put:3,patch:3};return Object.keys(a).includes(t)?async(...s)=>{let n,o={};s.length>a[t]&&(o=s.pop());try{n=await e[t](...s)}catch(l){n=l.response}return o[n.status]?o[n.status](n):(n.status>=400&&n.status<=599&&i.A.commit("apiError",n),n)}:Reflect.get(...arguments)}});t.A=n},2864:function(e,t,a){a.d(t,{A:function(){return D}});var s=a(641),i=a(33);const n={class:"console"},o={class:"console__header"},l={class:"console__headline"},r={key:0,class:"console__description"},c={class:"console__actions"},u=["title"],d={class:"console__operations"};function p(e,t,a,p,g,h){const m=(0,s.g2)("button-menu"),k=(0,s.g2)("console-operation");return(0,s.uX)(),(0,s.CE)("div",n,[(0,s.Lk)("section",o,[(0,s.Lk)("div",null,[(0,s.Lk)("h1",l,(0,i.v_)(a.title),1),a.description?((0,s.uX)(),(0,s.CE)("p",r,(0,i.v_)(a.description),1)):(0,s.Q3)("",!0)]),(0,s.Lk)("div",c,[a.forceConsole?(0,s.Q3)("",!0):((0,s.uX)(),(0,s.CE)("button",{key:0,class:(0,i.C4)(["widget-button widget-button--transparent widget-button--console console__action",{"console__action--active":e.showConsole}]),title:e.$t("ui.console.toggle"),onClick:t[0]||(t[0]=(...e)=>h.toggleConsole&&h.toggleConsole(...e))},null,10,u)),(0,s.bF)(m,{transparent:"","button-class":"console__action"},{default:(0,s.k6)(()=>[(0,s.Lk)("button",{onClick:t[1]||(t[1]=(...e)=>h.showLog&&h.showLog(...e))},(0,i.v_)(e.$t("ui.console.showLog")),1),(0,s.Lk)("button",{onClick:t[2]||(t[2]=t=>e.clipboard.copy(a.consoleOutput))},(0,i.v_)(e.$t("ui.console.copyLog")),1)]),_:1})])]),(0,s.Lk)("div",d,[((0,s.uX)(!0),(0,s.CE)(s.FK,null,(0,s.pI)(a.operations,(t,i)=>((0,s.uX)(),(0,s.Wv)(k,(0,s.v6)({key:i,ref_for:!0},t,{"show-console":e.showConsole,"force-console":a.forceConsole}),null,16,["show-console","force-console"]))),128))])])}var g=a(3513),h=a(3751);const m={class:"button-menu"};function k(e,t,a,n,o,l){return(0,s.uX)(),(0,s.CE)("div",m,[(0,s.Lk)("button",{class:(0,i.C4)(l.classes),onClick:t[0]||(t[0]=(...e)=>l.toggle&&l.toggle(...e))},null,2),(0,s.bo)((0,s.Lk)("div",{ref:"menu",class:"button-menu__menu",tabindex:"-1",onFocusout:t[1]||(t[1]=(...e)=>l.close&&l.close(...e)),onClick:t[2]||(t[2]=(...e)=>l.close&&l.close(...e))},[(0,s.RG)(e.$slots,"default")],544),[[h.aG,e.showMenu]])])}var v={name:"ButtonMenu",props:{buttonClass:String,type:String,icon:{type:String,default:"more"},transparent:Boolean,disabled:Boolean},data:()=>({showMenu:!1}),computed:{classes(){let e=`widget-button widget-button--${this.icon} button-menu__button ${this.buttonClass}`;return this.type&&(e+=` widget-button--${this.type}`),this.transparent&&(e+=" widget-button--transparent"),e}},methods:{open(){this.showMenu=!0,setTimeout(()=>this.$refs.menu?.focus(),0)},close(e){e&&this.$refs.menu?.contains(e.relatedTarget)||(this.$refs.menu.blur(),setTimeout(()=>{this.showMenu=!1},100))},toggle(){this.showMenu?this.close():this.open()}}},b=a(6262);const _=(0,b.A)(v,[["render",k]]);var f=_;const w={class:"console-operation__status"},y={key:0,class:"console-operation__icon console-operation__icon--active",width:"18",height:"18",fill:"none",xmlns:"http://www.w3.org/2000/svg",stroke:"#dbab0a"},C={key:1,class:"console-operation__icon console-operation__icon--success",viewBox:"0 0 16 16",width:"16",height:"16","aria-hidden":"true"},$={key:2,class:"console-operation__icon console-operation__icon--error",viewBox:"0 0 16 16",width:"16",height:"16","aria-hidden":"true"},L={key:3,class:"console-operation__icon console-operation__icon--skipped",viewBox:"0 0 16 16",width:"16",height:"16","aria-hidden":"true"},A={key:4,class:"console-operation__icon console-operation__icon--pending",viewBox:"0 0 16 16",width:"16",height:"16","aria-hidden":"true"},E={class:"console-operation__label"},X={key:0,class:"console-operation__description"},S={class:"console-operation__lines"},x=["data-index"],T={class:"console-operation__line-number"},M={class:"console-operation__line-content"};function O(e,t,a,n,o,l){return(0,s.uX)(),(0,s.Wv)((0,s.$y)(console&&!a.forceConsole?"details":"div"),{ref:"details",class:"console-operation",onToggle:l.toggleConsole},{default:(0,s.k6)(()=>[((0,s.uX)(),(0,s.Wv)((0,s.$y)(console&&!a.forceConsole?"summary":"div"),{class:(0,i.C4)(["console-operation__summary",{"console-operation__summary--console":!!console}])},{default:(0,s.k6)(()=>[(0,s.Lk)("div",w,[l.isActive?((0,s.uX)(),(0,s.CE)("svg",y,[...t[3]||(t[3]=[(0,s.Lk)("g",{fill:"none",fillrule:"evenodd"},[(0,s.Lk)("g",{transform:"translate(1 1)","stroke-width":"2"},[(0,s.Lk)("circle",{opacity:".5",cx:"8",cy:"8",r:"7"}),(0,s.Lk)("path",{d:" M 15 8 A 7 7 0 0 1 8 15"})])],-1),(0,s.Lk)("path",{"fill-rule":"evenodd",d:"M9 5a4 4 0 100 8 4 4 0 000-8z"},null,-1)])])):l.isSuccess?((0,s.uX)(),(0,s.CE)("svg",C,[...t[4]||(t[4]=[(0,s.Lk)("path",{"fill-rule":"evenodd",d:"M13.78 4.22a.75.75 0 010 1.06l-7.25 7.25a.75.75 0 01-1.06 0L2.22 9.28a.75.75 0 011.06-1.06L6 10.94l6.72-6.72a.75.75 0 011.06 0z"},null,-1)])])):l.isError||l.isStopped?((0,s.uX)(),(0,s.CE)("svg",$,[...t[5]||(t[5]=[(0,s.Lk)("path",{"fill-rule":"evenodd",d:"M3.72 3.72a.75.75 0 011.06 0L8 6.94l3.22-3.22a.75.75 0 111.06 1.06L9.06 8l3.22 3.22a.75.75 0 11-1.06 1.06L8 9.06l-3.22 3.22a.75.75 0 01-1.06-1.06L6.94 8 3.72 4.78a.75.75 0 010-1.06z"},null,-1)])])):l.isSkipped?((0,s.uX)(),(0,s.CE)("svg",L,[...t[6]||(t[6]=[(0,s.Lk)("path",{"fill-rule":"evenodd",d:"M8 4a4 4 0 100 8 4 4 0 000-8z"},null,-1)])])):((0,s.uX)(),(0,s.CE)("svg",A,[...t[7]||(t[7]=[(0,s.Lk)("path",{"fill-rule":"evenodd",d:"M8 4a4 4 0 100 8 4 4 0 000-8z"},null,-1)])]))]),(0,s.Lk)("div",E,[Array.isArray(a.summary)?((0,s.uX)(!0),(0,s.CE)(s.FK,{key:0},(0,s.pI)(a.summary,(e,n)=>((0,s.uX)(),(0,s.CE)(s.FK,{key:`${n}_title`},[(0,s.Lk)("h2",{class:(0,i.C4)(["console-operation__title",{"console-operation__title--disabled":e.match(/^~.+~$/)}])},(0,i.v_)(e.replace(/^~(.+)~$/,"$1")),3),a.details[n]?((0,s.uX)(),(0,s.CE)("p",{class:"console-operation__description",key:`${n}_details`},(0,i.v_)(a.details[n]),1)):(0,s.Q3)("",!0),t[8]||(t[8]=(0,s.Lk)("br",null,null,-1))],64))),128)):((0,s.uX)(),(0,s.CE)(s.FK,{key:1},[(0,s.Lk)("h2",{class:(0,i.C4)(["console-operation__title",{"console-operation__title--disabled":a.summary.match(/^~.+~$/)}])},(0,i.v_)(a.summary.replace(/^~(.+)~$/,"$1")),3),a.details?((0,s.uX)(),(0,s.CE)("p",X,(0,i.v_)(a.details),1)):(0,s.Q3)("",!0)],64))])]),_:1})),a.console?((0,s.uX)(),(0,s.CE)("div",{key:0,class:"console-operation__console",ref:"console",onScroll:t[2]||(t[2]=(...e)=>l.scrolled&&l.scrolled(...e))},[(0,s.bo)((0,s.Lk)("button",{class:"console-operation__scroll console-operation__scroll--top",onClick:t[0]||(t[0]=(...e)=>l.scrollToTop&&l.scrollToTop(...e))},[...t[9]||(t[9]=[(0,s.Lk)("svg",{xmlns:"http://www.w3.org/2000/svg",height:"24",viewBox:"0 0 24 24",width:"24"},[(0,s.Lk)("path",{d:"M0 0h24v24H0z",fill:"none"}),(0,s.Lk)("path",{d:"M16.59 8.59L12 13.17 7.41 8.59 6 10l6 6 6-6z"})],-1)])],512),[[h.aG,!e.isScrolledTop]]),(0,s.Lk)("div",S,[((0,s.uX)(!0),(0,s.CE)(s.FK,null,(0,s.pI)(l.consoleLines,(e,t)=>((0,s.uX)(),(0,s.CE)("div",{key:t,class:"console-operation__line","data-index":t},[(0,s.Lk)("span",T,(0,i.v_)(t+1),1),(0,s.Lk)("span",M,(0,i.v_)(e),1)],8,x))),128))]),(0,s.bo)((0,s.Lk)("button",{class:"console-operation__scroll console-operation__scroll--bottom",onClick:t[1]||(t[1]=(...e)=>l.scrollToBottom&&l.scrollToBottom(...e))},[...t[10]||(t[10]=[(0,s.Lk)("svg",{xmlns:"http://www.w3.org/2000/svg",height:"24",viewBox:"0 0 24 24",width:"24"},[(0,s.Lk)("path",{d:"M0 0h24v24H0z",fill:"none"}),(0,s.Lk)("path",{d:"M16.59 8.59L12 13.17 7.41 8.59 6 10l6 6 6-6z"})],-1)])],512),[[h.aG,!e.isScrolledBottom]])],544)):(0,s.Q3)("",!0)]),_:1},40,["onToggle"])}a(9348);var F={name:"ConsoleOperation",props:{status:String,summary:[String,Array],details:[String,Array],console:String,showConsole:Boolean,forceConsole:Boolean},data:()=>({openConsole:!0,isScrolledTop:!0,isScrolledBottom:!0,autoScroll:!0,swallowScroll:!0}),computed:{isPending:e=>"pending"===e.status,isActive:e=>"active"===e.status,isSuccess:e=>"complete"===e.status,isError:e=>"error"===e.status,isStopped:e=>"stopped"===e.status,isSkipped:e=>"skipped"===e.status,consoleLines:e=>e.console.trim().split("\n")},methods:{toggleConsole(){this.openConsole=this.$refs.details.open,this.openConsole&&this.$refs.console&&(this.autoScroll=!0,this.$refs.console.scrollTop=this.$refs.console.scrollHeight,this.updatePosition())},scrolled(){this.swallowScroll||this.updatePosition(),this.swallowScroll=!1},updatePosition(){const e=this.$refs.console,t=e.scrollTop+e.clientHeight;this.autoScroll=t===e.scrollHeight,this.isScrolledTop=e.clientHeight<=250||e.scrollHeight>250&&e.scrollTop<16,this.isScrolledBottom=e.clientHeight<=250||e.scrollHeight>250&&t>=e.scrollHeight-16},scrollToTop(){this.$refs.console.scrollTop=0},scrollToBottom(){this.$refs.console.scrollTop=this.$refs.console.scrollHeight},updateConsole(e=!0){this.isError&&(e=!0),this.$refs.details&&(this.$refs.details.open=e)}},watch:{console(e){e&&(this.updateConsole(this.openConsole),this.autoScroll&&setTimeout(()=>{this.swallowScroll=!0,this.$refs.console.scrollTop=this.$refs.console.scrollHeight},0))},showConsole(e){this.openConsole=e,this.updateConsole(e)}},mounted(){this.openConsole=this.showConsole,this.updateConsole(this.openConsole)}};const I=(0,b.A)(F,[["render",O]]);var P=I,R={components:{ConsoleOperation:P,ButtonMenu:f},props:{title:{type:String,required:!0},description:String,operations:{type:Array,required:!0},forceConsole:{type:Boolean,default:!1},consoleOutput:String},data:()=>({showConsole:!1,clipboard:(0,g.iDZ)()}),methods:{toggleConsole(){this.showConsole=!this.showConsole,window.localStorage.setItem("contao_manager_console",this.showConsole?"1":"0")},showLog(){const e=window.open();e&&(e.document.open(),e.document.write(`<pre>${this.consoleOutput}</pre>`),e.document.close())}},mounted(){this.showConsole="1"===window.localStorage.getItem("contao_manager_console")}};const B=(0,b.A)(R,[["render",p]]);var D=B},1218:function(e,t,a){a.d(t,{A:function(){return _}});var s=a(641),i=a(33);const n={key:0,class:"fragment-footer__product"},o={class:"fragment-footer__links"},l={href:"https://docs.contao.org",target:"_blank"},r={href:"https://to.contao.org/support",target:"_blank"},c={class:"fragment-footer__settings"};function u(e,t,a,u,d,p){const g=(0,s.g2)("footer-languages"),h=(0,s.g2)("theme-toggle");return(0,s.uX)(),(0,s.CE)("footer",{class:(0,i.C4)("fragment-footer"+(a.display?" fragment-footer--"+a.display:""))},[p.isLogin?(0,s.Q3)("",!0):((0,s.uX)(),(0,s.CE)("strong",n,"Contao Manager 1.10.13")),(0,s.Lk)("ul",o,[(0,s.Lk)("li",null,[(0,s.Lk)("a",l,(0,i.v_)(e.$t("ui.footer.help")),1)]),(0,s.Lk)("li",null,[(0,s.Lk)("a",r,(0,i.v_)(e.$t("ui.footer.reportProblem")),1)])]),(0,s.Lk)("div",c,[(0,s.bF)(g,{locales:p.languageOptions,current:p.currentLanguage,onChange:p.updateLanguage},null,8,["locales","current","onChange"]),(0,s.bF)(h)])],2)}var d=a(8044),p=a(9376),g=a(707),h=a(8823),m=a(2273),k={components:{FooterLanguages:h.A,ThemeToggle:m.A},props:{display:String},computed:{isLogin:e=>e.$store.state.view===g.A.LOGIN,currentLanguage(){return this.$i18n.locale},languageOptions(){return p.A}},methods:{updateLanguage(e){d.A.switch(e)}}},v=a(6262);const b=(0,v.A)(k,[["render",u]]);var _=b},8875:function(e,t,a){a.d(t,{A:function(){return v}});var s=a(641),i=a(33);function n(e,t,a,n,o,l){const r=(0,s.g2)("confirm-button");return e.isGranted(l.scopes.INSTALL)?((0,s.uX)(),(0,s.Wv)(r,{key:0,color:"primary",icon:"add",small:a.small,inline:a.inline,disabled:a.disabled||e.isRootInstalled||e.isAdded||e.isRequired||!e.canBeInstalled||!e.isCompatible,onClick:e.install},{default:(0,s.k6)(()=>[(0,s.eW)((0,i.v_)(e.$t(a.small?"ui.package.installButtonShort":"ui.package.installButton")),1)]),_:1},8,["small","inline","disabled","onClick"])):(0,s.Q3)("",!0)}var o=a(6278),l=a(70),r=a(8200);const c=["disabled"];function u(e,t,a,n,o,l){return(0,s.uX)(),(0,s.CE)("button",{type:"button",class:(0,i.C4)(l.buttonClass),disabled:a.disabled,onClick:t[0]||(t[0]=(...e)=>l.click&&l.click(...e))},[(0,s.Lk)("span",{class:(0,i.C4)(l.slotClass)},[(0,s.RG)(e.$slots,"default")],2),(0,s.Lk)("span",{class:(0,i.C4)(["confirm-button__icon",{"confirm-button__icon--confirm":e.confirm}])},[...t[1]||(t[1]=[(0,s.Lk)("svg",{xmlns:"http://www.w3.org/2000/svg",width:"24",height:"24",viewBox:"0 0 24 24"},[(0,s.Lk)("path",{d:"M0 0h24v24H0z",fill:"none"}),(0,s.Lk)("path",{d:"M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-2 15l-5-5 1.41-1.41L10 14.17l7.59-7.59L19 8l-9 9z"})],-1)])],2)],10,c)}var d={emits:["click"],props:{color:String,icon:String,inline:Boolean,small:Boolean,disabled:Boolean},data:()=>({confirm:!1}),computed:{buttonClass:e=>({"confirm-button":!0,"widget-button":!0,"widget-button--inline":e.inline,"widget-button--small":e.small,[`widget-button--${e.color}`]:e.color}),slotClass:e=>({[`widget-button--${e.icon}`]:e.icon})},methods:{click(e){this.confirm||(e.preventDefault(),e.target.blur(),this.$emit("click",e),this.confirm=!0,setTimeout(()=>{this.confirm=!1},1e3))}}},p=a(6262);const g=(0,p.A)(d,[["render",u]]);var h=g,m={components:{ConfirmButton:h},mixins:[r.A],props:{data:{type:Object,required:!0},small:Boolean,inline:Boolean,disabled:Boolean},computed:{...(0,o.L8)("auth",["isGranted"]),scopes:()=>l.A}};const k=(0,p.A)(m,[["render",n]]);var v=k},4290:function(e,t,a){a.d(t,{A:function(){return v}});var s=a(641),i=a(33),n=a(3751);const o={key:0,class:"package-constraint"},l=["placeholder","title","disabled"],r=["title","disabled"];function c(e,t,a,c,u,d){return!e.isFeature&&e.isVisible?((0,s.uX)(),(0,s.CE)("fieldset",o,[(0,s.bo)((0,s.Lk)("input",{ref:"constraint",type:"text",placeholder:d.inputPlaceholder,title:d.inputTitle,"onUpdate:modelValue":t[0]||(t[0]=e=>d.inputValue=e),class:(0,i.C4)({disabled:!a.emit&&(e.willBeRemoved||!e.isInstalled&&!e.willBeInstalled&&!e.isRequired||e.isUpload||!e.isGranted(d.scopes.INSTALL)),incompatible:d.isIncompatible,error:e.constraintError}),disabled:!e.constraintEditable||e.willBeRemoved||!a.emit&&!e.isInstalled&&!e.willBeInstalled&&!e.isRequired||e.isUpload||!e.isGranted(d.scopes.INSTALL),onKeypress:[t[1]||(t[1]=(0,n.jR)((0,n.D$)((...e)=>d.saveConstraint&&d.saveConstraint(...e),["prevent"]),["enter"])),t[2]||(t[2]=(0,n.jR)((0,n.D$)((...e)=>d.resetConstraint&&d.resetConstraint(...e),["prevent"]),["esc"]))],onBlur:t[3]||(t[3]=(...e)=>d.saveConstraint&&d.saveConstraint(...e))},null,42,l),[[n.Jo,d.inputValue]]),(0,s.Lk)("button",{class:(0,i.C4)({"widget-button widget-button--gear":!0,rotate:e.constraintValidating,incompatible:d.isIncompatible}),title:d.buttonTitle,onClick:t[4]||(t[4]=(...e)=>d.editConstraint&&d.editConstraint(...e)),disabled:!a.emit&&(e.willBeRemoved||!e.isInstalled&&!e.willBeInstalled&&!e.isRequired||e.isUpload||!e.isGranted(d.scopes.INSTALL))},(0,i.v_)(d.buttonValue),11,r)])):(0,s.Q3)("",!0)}a(4423);var u=a(6278),d=a(4335),p=a(70),g=a(8200),h={mixins:[g.A],emits:["update:modelValue"],props:{data:{type:Object,required:!0},emit:{type:Boolean,default:!1},modelValue:{type:String,default:""}},data:()=>({constraint:"",constraintEditable:!1,constraintValidating:!1,constraintError:!1}),computed:{...(0,u.L8)("auth",["isGranted"]),scopes:()=>p.A,buttonTitle:e=>e.isUpload?e.$t("ui.package.uploadConstraint"):"",buttonValue:e=>e.isUpload?e.$t("ui.package.editConstraint"):e.$t("ui.package.private"),inputTitle:e=>e.isUpload?e.$t("ui.package.privateTitle"):e.constraint,inputPlaceholder:e=>e.isUpload||e.$store.state.packages.root&&Object.keys(e.$store.state.packages.root.require).includes(e.data.name)?"":e.$t("ui.package.latestConstraint"),isIncompatible:e=>!e.isCompatible&&!e.constraint,inputValue:{get:e=>e.isUpload?e.$t("ui.package.private"):e.constraint,set(e){this.isUpload||(this.constraint=e)}}},methods:{editConstraint(){this.constraintValidating||(this.constraintEditable=!0,setTimeout(()=>{this.$refs.constraint.focus()},0))},async saveConstraint(){if(this.constraintEditable){if(this.constraintEditable=!1,this.constraintError=!1,!this.emit&&(this.isInstalled&&(!this.constraint||this.constraintInstalled===this.constraint)||this.isRequired&&(!this.constraint||this.constraintRequired===this.constraint)))return this.$store.commit("packages/restore",this.data.name),this.$store.dispatch("packages/uploads/unconfirm",this.data.name),void this.resetConstraint();if(!this.emit&&!this.isRequired&&this.willBeInstalled&&!this.constraint)return this.$store.commit("packages/add",Object.assign({},this.data,{constraint:null})),void this.resetConstraint();if(this.emit&&!this.constraint)return this.$emit("update:modelValue",this.constraint),void this.resetConstraint();this.$refs.constraint.blur(),this.constraintValidating=!0;try{const e=await d.A.post("api/constraint",{constraint:this.constraint});this.constraintValidating=!1,e.data.valid?this.emit?this.$emit("update:modelValue",this.constraint):this.isRootInstalled||this.isRequired?this.$store.commit("packages/change",{name:this.data.name,version:this.constraint}):this.$store.commit("packages/add",Object.assign({},this.data,{constraint:this.constraint})):(this.constraintError=!0,setTimeout(()=>this.editConstraint(),0))}catch(e){this.constraintValidating=!1,this.constraintError=!0,setTimeout(()=>this.editConstraint(),0)}}},resetConstraint(){this.emit?this.constraint=this.modelValue:this.willBeInstalled?this.constraint=this.constraintAdded:this.isChanged?this.constraint=this.constraintChanged:this.isInstalled?this.constraint=this.constraintInstalled:this.isRequired&&(this.constraint=this.constraintRequired),this.constraintEditable&&(this.constraintEditable=!1,this.constraintError=!1,this.constraintValidating=!1)}},watch:{modelValue(e){this.constraint=e},constraintAdded(e){this.constraint=e},constraintChanged(e){this.constraint=e||this.constraintInstalled||this.constraintRequired}},mounted(){this.resetConstraint()}},m=a(6262);const k=(0,m.A)(h,[["render",c],["__scopeId","data-v-00a118e4"]]);var v=k},1298:function(e,t,a){a.d(t,{A:function(){return c}});var s=a(641),i=a(33);function n(e,t,a,n,o,l){return(0,s.uX)(),(0,s.CE)("div",{class:(0,i.C4)(["progress-bar",{[`progress-bar--${a.color}`]:!!a.color}])},[(0,s.Lk)("div",{class:"progress-bar__label",ref:"bar"},(0,i.v_)(a.label?a.label:`${l.progress}%`),513),(0,s.Lk)("div",{class:"progress-bar__bar",style:(0,i.Tr)(`width:${l.progress}%`)},[(0,s.Lk)("span",{style:(0,i.Tr)(`width:${e.width}px`)},(0,i.v_)(a.label?a.label:`${l.progress}%`),5)],4)],2)}var o={props:{amount:[String,Number],label:String,color:String},data:()=>({width:0}),computed:{progress(){return Math.floor(this.amount)}},methods:{updateWidth(){this.$refs.bar&&(this.width=this.$refs.bar.clientWidth)}},mounted(){setTimeout(this.updateWidth,0)}},l=a(6262);const r=(0,l.A)(o,[["render",n]]);var c=r},728:function(e,t,a){a.d(t,{A:function(){return p}});var s=a(641),i=a(33);const n={class:"layout-boxed"},o={class:"layout-boxed__cell"};function l(e,t,a,l,r,c){const u=(0,s.g2)("footer-fragment");return(0,s.uX)(),(0,s.CE)("div",n,[(0,s.Lk)("div",o,[(0,s.Lk)("div",{class:(0,i.C4)("layout-boxed__container "+(a.wide?" layout-boxed__container--wide ":"")+a.slotClass)},[(0,s.RG)(e.$slots,"default"),(0,s.bF)(u,{display:a.wide?"boxed":""},null,8,["display"])],2)])])}var r=a(1218),c={components:{FooterFragment:r.A},props:{slotClass:String,wide:Boolean}},u=a(6262);const d=(0,u.A)(c,[["render",l]]);var p=d},9473:function(e,t,a){a.d(t,{A:function(){return _}});var s=a(641),i=a(33);const n={class:"setup-totp__qr"},o={class:"setup-totp__uri"},l=["disabled"];function r(e,t,a,r,c,u){const d=(0,s.g2)("qrcode-svg"),p=(0,s.g2)("text-field"),g=(0,s.g2)("loading-spinner"),h=(0,s.g2)("loading-button"),m=(0,s.g2)("popup-overlay");return(0,s.uX)(),(0,s.Wv)(m,{class:"setup-totp",headline:e.$t("ui.totp.headline"),onSubmit:u.submit,onClear:u.close},(0,s.eX)({default:(0,s.k6)(()=>[e.provisioning_uri?((0,s.uX)(),(0,s.CE)(s.FK,{key:0},[(0,s.Lk)("p",null,(0,i.v_)(e.$t("ui.totp.setupQr")),1),(0,s.Lk)("div",n,[(0,s.bF)(d,{value:e.provisioning_uri,level:"H"},null,8,["value"])]),(0,s.Lk)("p",null,(0,i.v_)(e.$t("ui.totp.setupCode")),1),(0,s.Lk)("code",o,(0,i.v_)(e.provisioning_uri),1),(0,s.bF)(p,{ref:"totp",name:"totp",label:e.$t("ui.totp.codeLabel"),description:e.$t("ui.totp.codeDescription"),required:"",pattern:"\\d+",minlength:"6",maxlength:"6",autocomplete:"one-time-code",error:e.error,onKeyup:t[0]||(t[0]=t=>e.error=""),modelValue:e.totp,"onUpdate:modelValue":t[1]||(t[1]=t=>e.totp=t)},null,8,["label","description","error","modelValue"])],64)):((0,s.uX)(),(0,s.Wv)(g,{key:1}))]),_:2},[e.provisioning_uri?{name:"actions",fn:(0,s.k6)(()=>[(0,s.Lk)("button",{type:"button",class:"widget-button",disabled:e.loading,onClick:t[2]||(t[2]=(...e)=>u.close&&u.close(...e))},(0,i.v_)(e.$t("ui.totp.cancel")),9,l),(0,s.bF)(h,{submit:"",color:"primary",loading:e.loading},{default:(0,s.k6)(()=>[(0,s.eW)((0,i.v_)(e.$t("ui.totp.enable")),1)]),_:1},8,["loading"])]),key:"0"}:void 0]),1032,["headline","onSubmit","onClear"])}var c=a(4335),u=a(6278),d=a(1687),p=a(9045),g=a(5506),h=a(9757),m=a(7944),k={components:{PopupOverlay:d.A,LoadingSpinner:p.A,LoadingButton:g.A,TextField:h.A,QrcodeSvg:m.dv},data:()=>({loading:!1,provisioning_uri:null,totp:null,error:""}),computed:{...(0,u.aH)("auth",["username"])},methods:{submit(){this.loading=!0,this.$request.put(`api/users/${this.username}/totp`,{provisioning_uri:this.provisioning_uri,totp:this.totp},null,{201:async()=>{await this.$store.dispatch("auth/status"),this.$notify.success(this.$t("ui.totp.enabled")),this.close()},422:()=>{this.loading=!1,this.error=this.$t("ui.totp.invalid"),this.$refs.totp.focus()}})},close(){this.$store.commit("modals/close","setup-totp")}},async mounted(){const e=await c.A.get(`api/users/${this.username}/totp`);this.provisioning_uri=e.data.provisioning_uri,setTimeout(()=>{this.$refs.totp.focus()},0)}},v=a(6262);const b=(0,v.A)(k,[["render",r]]);var _=b},8733:function(e,t,a){a.r(t),a.d(t,{default:function(){return B}});var s=a(641),i=a(33),n=a(9472);const o={class:"database-migration__header"},l={class:"database-migration__headline"},r={key:0,class:"database-migration__text"},c={key:1,class:"database-migration__text"},u={class:"database-migration__description"},d={class:"database-migration__loading"},p={key:0,class:"database-migration__description"},g={key:1,class:"database-migration__description"},h={key:2,class:"database-migration__description"},m={class:"database-migration__actions"},k=["disabled"],v={class:"database-migration__actions"},b=["disabled"],_=["disabled"],f=["disabled"],w=["disabled"],y=["disabled"],C={class:"database-migration__description"},$={class:"database-migration__actions"},L={key:0,class:"database-migration__actions"};function A(e,t,a,A,E,X){const S=(0,s.g2)("loading-spinner"),x=(0,s.g2)("loading-button"),T=(0,s.g2)("check-box"),M=(0,s.g2)("console-output"),O=(0,s.g2)("boxed-layout");return(0,s.uX)(),(0,s.Wv)(O,{wide:!0,slotClass:"database-migration"},{default:(0,s.k6)(()=>[(0,s.Lk)("header",o,[t[7]||(t[7]=(0,s.Lk)("img",{src:n,width:"80",height:"80",alt:"",class:"database-migration__icon"},null,-1)),(0,s.Lk)("h1",l,(0,i.v_)(e.$t("ui.migrate.headline")),1),"migrations-only"===e.type?((0,s.uX)(),(0,s.CE)("p",r,(0,i.v_)(e.$t("ui.migrate.migrationsOnly")),1)):(0,s.Q3)("",!0),"schema-only"===e.type?((0,s.uX)(),(0,s.CE)("p",c,(0,i.v_)(e.$t("ui.migrate.schemaOnly")),1)):(0,s.Q3)("",!0),e.checking?((0,s.uX)(),(0,s.CE)(s.FK,{key:2},[(0,s.Lk)("p",u,(0,i.v_)(e.$t("ui.migrate.loading")),1),(0,s.Lk)("div",d,[(0,s.bF)(S)])],64)):X.isEmpty?((0,s.uX)(),(0,s.CE)(s.FK,{key:3},["migrations-only"===e.type?((0,s.uX)(),(0,s.CE)("p",p,(0,i.v_)(e.$t("ui.migrate.emptyMigrations")),1)):"schema-only"===e.type?((0,s.uX)(),(0,s.CE)("p",g,(0,i.v_)(e.$t("ui.migrate.emptySchema")),1)):((0,s.uX)(),(0,s.CE)("p",h,(0,i.v_)(e.$t("ui.migrate.empty")),1)),(0,s.Lk)("div",m,["migrations-only"===e.type||"schema-only"===e.type?((0,s.uX)(),(0,s.CE)("button",{key:0,class:"widget-button widget-button--primary",disabled:e.closing,onClick:t[0]||(t[0]=e=>X.checkAll())},(0,i.v_)(e.$t("ui.migrate.retryAll")),9,k)):(0,s.Q3)("",!0),(0,s.bF)(x,{loading:e.closing,onClick:X.close},{default:(0,s.k6)(()=>[(0,s.eW)((0,i.v_)(e.$t("ui.migrate.close")),1)]),_:1},8,["loading","onClick"])])],64)):!e.executing&&(X.isComplete||X.hasError||X.hasProblem)?((0,s.uX)(),(0,s.CE)(s.FK,{key:4},[((0,s.uX)(!0),(0,s.CE)(s.FK,null,(0,s.pI)(X.description.split("\n"),(e,t)=>((0,s.uX)(),(0,s.CE)("p",{class:"database-migration__description",key:t},(0,i.v_)(e),1))),128)),(0,s.Lk)("div",v,["problem"===e.type?((0,s.uX)(),(0,s.CE)(s.FK,{key:0},[(0,s.bF)(x,{loading:e.closing,onClick:X.close},{default:(0,s.k6)(()=>[(0,s.eW)((0,i.v_)(e.$t("ui.migrate.cancel")),1)]),_:1},8,["loading","onClick"]),(0,s.Lk)("button",{class:"widget-button",disabled:e.closing,onClick:t[1]||(t[1]=(...e)=>X.setup&&X.setup(...e))},(0,i.v_)(e.$t("ui.migrate.setup")),9,b),(0,s.Lk)("button",{class:"widget-button widget-button--primary",disabled:e.closing,onClick:t[2]||(t[2]=e=>X.checkAll())},(0,i.v_)(e.$t("ui.migrate.retry")),9,_)],64)):"warning"===e.type?((0,s.uX)(),(0,s.CE)(s.FK,{key:1},[(0,s.bF)(x,{loading:e.closing,onClick:X.close},{default:(0,s.k6)(()=>[(0,s.eW)((0,i.v_)(e.$t("ui.migrate.cancel")),1)]),_:1},8,["loading","onClick"]),(0,s.Lk)("button",{class:"widget-button widget-button",disabled:e.closing,onClick:t[3]||(t[3]=e=>X.checkAll())},(0,i.v_)(e.$t("ui.migrate.retry")),9,f),(0,s.Lk)("button",{class:"widget-button widget-button--primary",disabled:e.closing,onClick:t[4]||(t[4]=e=>X.checkAll(!0))},(0,i.v_)(e.$t("ui.migrate.skip")),9,w)],64)):e.hasChanges?((0,s.uX)(),(0,s.CE)(s.FK,{key:2},[(0,s.bF)(x,{loading:e.closing,onClick:X.close},{default:(0,s.k6)(()=>[(0,s.eW)((0,i.v_)(e.$t("ui.migrate.cancel")),1)]),_:1},8,["loading","onClick"]),(0,s.Lk)("button",{class:"widget-button widget-button--primary",disabled:e.closing,onClick:t[5]||(t[5]=e=>X.check())},(0,i.v_)(e.$t("ui.migrate.continue")),9,y)],64)):((0,s.uX)(),(0,s.Wv)(x,{key:3,loading:e.closing,onClick:X.close},{default:(0,s.k6)(()=>[(0,s.eW)((0,i.v_)(e.$t("ui.migrate.confirm")),1)]),_:1},8,["loading","onClick"]))])],64)):((0,s.uX)(),(0,s.CE)(s.FK,{key:5},[(0,s.Lk)("p",C,(0,i.v_)(e.$t("ui.migrate.pending")),1),(0,s.Lk)("div",$,[(0,s.bF)(x,{class:"database-migration__action",loading:e.closing,disabled:e.executing,onClick:X.close},{default:(0,s.k6)(()=>[(0,s.eW)((0,i.v_)(e.$t("ui.migrate.cancel")),1)]),_:1},8,["loading","disabled","onClick"]),(0,s.bF)(x,{class:"database-migration__action",color:"primary",loading:e.executing,disabled:e.closing,onClick:X.execute},{default:(0,s.k6)(()=>[(0,s.eW)((0,i.v_)(e.$t("ui.migrate.execute")),1)]),_:1},8,["loading","disabled","onClick"])]),e.hasDeletes?((0,s.uX)(),(0,s.CE)("div",L,[(0,s.bF)(T,{name:"withDeletes",label:e.$t("ui.migrate.withDeletes"),disabled:e.executing,modelValue:e.withDeletes,"onUpdate:modelValue":t[6]||(t[6]=t=>e.withDeletes=t)},null,8,["label","disabled","modelValue"])])):(0,s.Q3)("",!0)],64))]),!e.checking&&e.operations&&e.operations.length?((0,s.uX)(),(0,s.Wv)(M,{key:0,class:"database-migration__main",title:X.consoleTitle,operations:e.operations,"console-output":X.console,"force-console":X.hasProblem},null,8,["title","operations","console-output","force-console"])):(0,s.Q3)("",!0)]),_:1})}a(4114),a(8111),a(7588),a(1701);var E=a(6278),X=a(4335),S=a(707),x=a(728),T=a(9045),M=a(5506),O=a(2864),F=a(3480),I={components:{BoxedLayout:x.A,LoadingSpinner:T.A,LoadingButton:M.A,ConsoleOutput:O.A,CheckBox:F.A},data:()=>({type:null,status:"",changes:null,hasDeletes:!1,operations:null,hash:null,withDeletes:!1,previousResult:!0,checking:!0,executing:!1,closing:!1}),computed:{...(0,E.aH)("server/database",["supported"]),...(0,E.aH)(["setupStep"]),...(0,E.L8)("server/database",["hasChanges"]),isEmpty:e=>"active"!==e.status&&e.operations&&!e.operations.length,isComplete:e=>"complete"===e.status,hasError:e=>"error"===e.status,hasProblem:e=>"problem"===e.type||"warning"===e.type,description(){return"problem"===this.type?this.$tc("ui.migrate.problem",this.operations?.length||0):"warning"===this.type?this.$t("ui.migrate.warning"):this.previousResult&&this.hasChanges?this.$t("ui.migrate.previousChanges"):this.previousResult?this.$t("ui.migrate.previousComplete"):this.isComplete&&this.hasChanges?this.$t("ui.migrate.appliedChanges"):this.isComplete?this.$t("ui.migrate.appliedComplete"):this.$t("ui.migrate.error")},consoleTitle(){switch(this.type){case"migrations":case"migrations-only":return this.$t("ui.migrate.migrationTitle");case"schema":case"schema-only":return this.$t("ui.migrate.schemaTitle");case"problem":return this.$t("ui.migrate.problemTitle");case"warning":return this.$t("ui.migrate.warningTitle")}return""},console(){if(!this.changes||!this.changes.length)return"";let e="";return this.changes.forEach(t=>{e+=`${t.name}\n`}),e}},methods:{async poll(e){if(201===e.status)return new Promise(e=>{setTimeout(async()=>{await this.poll(await X.A.get("api/contao/database-migration")),e()},1e3)});const t=e.data;return this.changes&&!t.status||(this.type=t.type,this.status=t.status,this.hash=t.hash,this.changes=t.operations),t.status&&"active"!==t.status?void 0:new Promise(e=>{setTimeout(async()=>{await this.poll(await X.A.get("api/contao/database-migration")),e()},1e3)})},async execute(){this.executing=!0,await X.A.put("api/contao/database-migration",{type:this.type,hash:this.hash,withDeletes:this.withDeletes&&this.hasDeletes}),setTimeout(async()=>{await this.poll(await X.A.get("api/contao/database-migration")),await this.$store.dispatch("server/database/get",!1),this.executing=!1},1e3)},async check(e=!1){this.checking=!0;const t=this.type||this.$store.state.migrationsType;this.status&&(this.type=null,this.status="",this.changes=null,this.hash=null,await X.A.delete("api/contao/database-migration"));let a=await X.A.get("api/contao/database-migration");204===a.status&&(this.previousResult=!1,a=await X.A.put("api/contao/database-migration",{type:t,skipWarnings:e})),await this.poll(a),await X.A.delete("api/contao/database-migration"),this.checking=!1},checkAll(e=!1){this.type=null,this.check(e)},generateStatus(e,t){return t?`~${e}~`:e},async close(){this.closing=!0,await X.A.delete("api/contao/database-migration"),await this.$store.dispatch("server/database/get",!1),this.setupStep>0?(await this.$store.dispatch("server/adminUser/get",!1),this.$store.commit("setView",S.A.SETUP)):this.$store.commit("setView",S.A.READY),this.$emit("close"),this.closing=!1},async setup(){this.$store.commit("setup",3)},updateOperations(){if(this.hasDeletes=!1,this.operations=null,!this.changes)return;if(this.hasProblem)return void(this.operations=this.changes.map(e=>({status:e.status,summary:e.name,details:e.message,console:e.trace})));if("migrations"===this.type||"migrations-only"===this.type)return void(this.operations=this.changes.map(e=>({status:e.status,summary:e.name,details:e.message})));const e=[];this.changes.forEach(t=>{let a;if(a=new RegExp("^CREATE TABLE ([^ ]+) .+$").exec(t.name),a)e.push({status:t.status,summary:this.$t("ui.migrate.addTable",{table:a[1]}),details:t.message,console:t.name});else{if(a=new RegExp("^DROP TABLE (.+)$").exec(t.name),a)return e.push({status:this.withDeletes?t.status:"skipped",summary:this.generateStatus(this.$t("ui.migrate.dropTable",{table:a[1]}),!this.withDeletes),details:t.message,console:t.name}),void(this.hasDeletes=!0);if(a=new RegExp("^CREATE INDEX ([^ ]+) ON ([^ ]+) \\(([^)]+)\\)$").exec(t.name),a)e.push({status:t.status,summary:this.$t("ui.migrate.createIndex",{name:a[1],table:a[2]}),details:t.message||a[3],console:t.name});else if(a=new RegExp("^DROP INDEX ([^ ]+) ON ([^ ]+)$").exec(t.name),a)e.push({status:t.status,summary:this.$t("ui.migrate.dropIndex",{name:a[1],table:a[2]}),details:t.message,console:t.name});else{if(a=new RegExp("^ALTER TABLE ([^ ]+) (.+)$").exec(t.name),a){const s=a[1],i={status:t.status,summary:[],details:[],console:t.name};t.message&&i.details.push(t.message);let n="";a[2].split("'").forEach((e,t)=>{n=t%2?`${n}'${e.replace(",","%comma%")}'`:`${n}${e}`});const o=n.split(",").map(e=>e.trim().replace("%comma%",","));let l=0;return o.forEach(e=>{let a;return a=new RegExp("^ADD ([^ ]+) (.+)$").exec(e),a?(i.summary.push(this.$t("ui.migrate.addField",{table:s,field:a[1]})),void(t.message||i.details.push(a[2]))):(a=new RegExp("^CHANGE ([^ ]+) ([^ ]+) (.+)$").exec(e),a?(i.summary.push(this.$t("ui.migrate.changeField",{table:s,field:a[1]})),void(t.message||i.details.push(a[3]))):(a=new RegExp("^DROP (.+)$").exec(e),a?(i.summary.push(this.generateStatus(this.$t("ui.migrate.dropField",{table:s,field:a[1]}),!this.withDeletes)),i.details.push(""),this.hasDeletes=!0,void l++):(i.summary.push(`ALTER TABLE ${s} ${e}`),void i.details.push(""))))}),l===o.length&&(i.status=this.withDeletes?t.status:"skipped"),void e.push(i)}e.push({status:t.status,summary:t.name,details:t.message,console:t.name}),this.hasDeletes=!0}}}),this.operations=e}},watch:{changes(){this.updateOperations()},withDeletes(){this.updateOperations()}},mounted(){this.check()}},P=a(6262);const R=(0,P.A)(I,[["render",A]]);var B=R},4676:function(e,t,a){a.d(t,{A:function(){return g}});var s=a(641),i=a(33),n=a(3751);const o={class:"button-group"},l=["disabled"];function r(e,t,a,r,c,u){const d=(0,s.g2)("loading-button");return(0,s.uX)(),(0,s.CE)("div",o,[(0,s.bF)(d,{href:a.href,to:a.to,class:(0,i.C4)(u.primaryClass),onClick:t[0]||(t[0]=t=>e.$emit("click",t)),disabled:a.disabled,loading:a.loading,submit:a.submit},{default:(0,s.k6)(()=>[(0,s.eW)((0,i.v_)(a.label),1)]),_:1},8,["href","to","class","disabled","loading","submit"]),(0,s.Lk)("button",{type:"button",class:(0,i.C4)(u.moreClass),onClick:t[1]||(t[1]=(...e)=>u.toggle&&u.toggle(...e)),disabled:a.moreDisabled},[...t[4]||(t[4]=[(0,s.Lk)("svg",{fill:"#FFF",height:"24",viewBox:"0 0 24 24",width:"24",xmlns:"http://www.w3.org/2000/svg"},[(0,s.Lk)("path",{d:"M16.59 8.59L12 13.17 7.41 8.59 6 10l6 6 6-6z"}),(0,s.Lk)("path",{d:"M0 0h24v24H0z",fill:"none"})],-1)])],10,l),(0,s.bo)((0,s.Lk)("div",{ref:"group",class:(0,i.C4)({"button-group__group":!0,["button-group__group--top"]:a.alignTop}),tabindex:"-1",onFocusout:t[2]||(t[2]=(...e)=>u.close&&u.close(...e)),onClick:t[3]||(t[3]=(...e)=>u.close&&u.close(...e))},[(0,s.RG)(e.$slots,"default")],34),[[n.aG,e.showGroup]])])}var c=a(5506),u={components:{LoadingButton:c.A},emits:["click"],props:{label:{type:String,required:!0},type:String,href:String,to:[String,Object],icon:String,color:String,disabled:Boolean,loading:Boolean,submit:Boolean,moreDisabled:Boolean,alignTop:Boolean},data:()=>({showGroup:!1}),computed:{primaryClass(){let e="widget-button button-group__primary";return this.type&&(e+=` widget-button--${this.type}`),this.icon&&(e+=` widget-button--${this.icon}`),this.color&&(e+=` widget-button--${this.color}`),e},moreClass(){let e="widget-button button-group__more";return this.type&&(e+=` widget-button--${this.type}`),this.color&&(e+=` widget-button--${this.color}`),e}},methods:{open(){this.showGroup=!0,setTimeout(()=>this.$refs.group?.focus(),0)},close(e){e&&this.$refs.group?.contains(e.relatedTarget)||(this.$refs.group?.blur(),setTimeout(()=>{this.showGroup=!1},100))},toggle(){this.showGroup?this.close():this.open()}}},d=a(6262);const p=(0,d.A)(u,[["render",r]]);var g=p},3480:function(e,t,a){a.d(t,{A:function(){return d}});var s=a(641),i=a(33);const n=["id","name","disabled","required","checked"],o=["for"];function l(e,t,a,l,r,c){return(0,s.uX)(),(0,s.CE)("div",null,[(0,s.Lk)("div",{class:(0,i.C4)(["widget widget-checkbox",{"widget--required":a.required}])},[(0,s.Lk)("input",{ref:"input",type:"checkbox",id:a.label?"ctrl_"+a.name:"",name:a.name,disabled:a.disabled,required:a.required,checked:a.modelValue||null,onChange:t[0]||(t[0]=e=>c.toggle(e.target.checked))},null,40,n),a.label?((0,s.uX)(),(0,s.CE)("label",{key:0,for:"ctrl_"+a.name},(0,i.v_)(a.label),9,o)):(0,s.Q3)("",!0)],2),a.description||e.$slots.description?((0,s.uX)(),(0,s.CE)("div",{key:0,class:(0,i.C4)(["widget__description",{"widget__description--disabled":a.disabled}])},[(0,s.RG)(e.$slots,"description",{},()=>[(0,s.Lk)("p",null,(0,i.v_)(a.description),1)])],2)):(0,s.Q3)("",!0)])}var r={emits:["input","update:modelValue"],props:{name:{type:String,required:!0},label:{type:String,required:!0},description:String,modelValue:Boolean,disabled:Boolean,required:Boolean},methods:{toggle(e){this.$emit("input"),this.$emit("update:modelValue",!!e)}}},c=a(6262);const u=(0,c.A)(r,[["render",l]]);var d=u},9757:function(e,t,a){a.d(t,{A:function(){return g}});var s=a(641),i=a(33);const n=["for"],o=["type","id","name","placeholder","required","pattern","minlength","maxlength","disabled","autocomplete","autocapitalize","value"],l=["title"],r={key:2,class:"widget__error"};function c(e,t,a,c,u,d){return(0,s.uX)(),(0,s.CE)("div",{class:(0,i.C4)(["widget widget-text",{[`widget-text--${a.type}`]:!!a.type,"widget--error":a.error,"widget--validate":a.validate&&!a.error,"widget--required":a.required}])},[a.label?((0,s.uX)(),(0,s.CE)("label",{key:0,for:"ctrl_"+a.name},(0,i.v_)(a.label),9,n)):(0,s.Q3)("",!0),(0,s.Lk)("input",{ref:"input",type:d.inputType,id:a.label?"ctrl_"+a.name:"",name:a.name,placeholder:a.validate?a.placeholder||" ":a.placeholder,required:a.required,pattern:a.pattern,minlength:a.minlength,maxlength:a.maxlength,disabled:a.disabled,autocomplete:a.autocomplete,autocapitalize:a.autocapitalize||"none",value:a.modelValue,onInput:t[0]||(t[0]=e=>d.input(e.target.value)),onKeyup:t[1]||(t[1]=t=>e.$emit("keyup")),onFocus:t[2]||(t[2]=t=>e.$emit("focus")),onBlur:t[3]||(t[3]=t=>e.$emit("blur"))},null,40,o),"password"===a.type?((0,s.uX)(),(0,s.CE)("button",{key:1,type:"button",class:(0,i.C4)(["widget__password-toggle",{"widget__password-toggle--visible":e.showPassword,"widget__password-toggle--hidden":!e.showPassword}]),title:e.$t("ui.widget."+(e.showPassword?"hidePassword":"showPassword")),onClick:t[4]||(t[4]=(...e)=>d.togglePassword&&d.togglePassword(...e))},[...t[5]||(t[5]=[(0,s.Lk)("svg",{height:"24",viewBox:"0 0 24 24",width:"24",xmlns:"http://www.w3.org/2000/svg"},[(0,s.Lk)("path",{d:"M0 0h24v24H0z",fill:"none"}),(0,s.Lk)("path",{d:"M12 4.5C7 4.5 2.73 7.61 1 12c1.73 4.39 6 7.5 11 7.5s9.27-3.11 11-7.5c-1.73-4.39-6-7.5-11-7.5zM12 17c-2.76 0-5-2.24-5-5s2.24-5 5-5 5 2.24 5 5-2.24 5-5 5zm0-8c-1.66 0-3 1.34-3 3s1.34 3 3 3 3-1.34 3-3-1.34-3-3-3z"})],-1)])],10,l)):(0,s.Q3)("",!0),a.error?((0,s.uX)(),(0,s.CE)("p",r,(0,i.v_)(a.error),1)):(0,s.Q3)("",!0),a.description||e.$slots.description?((0,s.uX)(),(0,s.CE)("div",{key:3,class:(0,i.C4)(["widget__description",{"widget__description--disabled":a.disabled}])},[(0,s.RG)(e.$slots,"description",{},()=>[(0,s.Lk)("p",null,(0,i.v_)(a.description),1)])],2)):(0,s.Q3)("",!0)],2)}a(4423);var u={emits:["input","keyup","focus","blur","update:modelValue"],props:{type:{type:String,validator:e=>["text","tel","email","url","password","search"].includes(e)},name:{type:String,required:!0},label:String,description:String,modelValue:String,pattern:String,placeholder:String,disabled:Boolean,required:Boolean,validate:Boolean,error:String,autocomplete:String,autocapitalize:String,minlength:String,maxlength:String},data:()=>({showPassword:!1}),computed:{inputType(){return"password"===this.type&&this.showPassword?"text":this.type?this.type:"text"}},methods:{input(e){this.$emit("input"),this.$emit("update:modelValue",e)},enter(){this.$emit("enter")},focus(){this.$refs.input.focus()},checkValidity(){return this.$refs.input.checkValidity()},togglePassword(){this.showPassword=!this.showPassword,this.focus()}},mounted(){this.$emit("update:modelValue",this.$refs.input.value)}},d=a(6262);const p=(0,d.A)(u,[["render",c]]);var g=p},7591:function(e,t,a){e.exports=a.p+"img/button-upload.ca8e9cfc.svg"},9472:function(e,t,a){e.exports=a.p+"img/database.7f0a8c49.svg"},6894:function(e,t,a){e.exports=a.p+"img/logo.d9707286.svg"}},t={};function a(s){var i=t[s];if(void 0!==i)return i.exports;var n=t[s]={exports:{}};return e[s].call(n.exports,n,n.exports,a),n.exports}a.m=e,function(){var e=[];a.O=function(t,s,i,n){if(!s){var o=1/0;for(u=0;u<e.length;u++){s=e[u][0],i=e[u][1],n=e[u][2];for(var l=!0,r=0;r<s.length;r++)(!1&n||o>=n)&&Object.keys(a.O).every(function(e){return a.O[e](s[r])})?s.splice(r--,1):(l=!1,n<o&&(o=n));if(l){e.splice(u--,1);var c=i();void 0!==c&&(t=c)}}return t}n=n||0;for(var u=e.length;u>0&&e[u-1][2]>n;u--)e[u]=e[u-1];e[u]=[s,i,n]}}(),function(){a.n=function(e){var t=e&&e.__esModule?function(){return e["default"]}:function(){return e};return a.d(t,{a:t}),t}}(),function(){var e,t=Object.getPrototypeOf?function(e){return Object.getPrototypeOf(e)}:function(e){return e.__proto__};a.t=function(s,i){if(1&i&&(s=this(s)),8&i)return s;if("object"===typeof s&&s){if(4&i&&s.__esModule)return s;if(16&i&&"function"===typeof s.then)return s}var n=Object.create(null);a.r(n);var o={};e=e||[null,t({}),t([]),t(t)];for(var l=2&i&&s;("object"==typeof l||"function"==typeof l)&&!~e.indexOf(l);l=t(l))Object.getOwnPropertyNames(l).forEach(function(e){o[e]=function(){return s[e]}});return o["default"]=function(){return s},a.d(n,o),n}}(),function(){a.d=function(e,t){for(var s in t)a.o(t,s)&&!a.o(e,s)&&Object.defineProperty(e,s,{enumerable:!0,get:t[s]})}}(),function(){a.f={},a.e=function(e){return Promise.all(Object.keys(a.f).reduce(function(t,s){return a.f[s](e,t),t},[]))}}(),function(){a.u=function(e){return"js/"+e+"."+{28:"44aaa9cb",44:"5dc282ff",52:"cc5d0f06",120:"0b468899",139:"31ca6808",140:"6c8f8c32",164:"4e598192",180:"42df9004",186:"836851cb",194:"7e05c25f",219:"8a6252ad",312:"cc0c9fd5",335:"11020416",367:"8d3af137",414:"a23ef62c",477:"fb77fe74",486:"d2c3c316",518:"7d262c02",523:"7617c212",540:"456d5d6d",542:"70ad2246",551:"01beb249",553:"48a1739b",554:"80f1af85",557:"69b9338e",560:"36aa04d8",581:"5db3a790",606:"2974c6f2",638:"f63623a3",643:"372ea4d9",669:"4d0edf1c",706:"abaff9c8",710:"24c4cd7c",715:"0c82c54e",716:"aac3cea9",721:"a298060e",739:"4c59edac",748:"766e08c8",769:"92e42b5f",851:"bccade28",859:"dbf1a05f",874:"f11456c0",904:"469c423c",953:"b6fc1039",958:"d35ccdeb"}[e]+".js"}}(),function(){a.miniCssF=function(e){return"css/"+e+"."+{120:"ce753a3c",186:"9aa9997d",335:"e18cb2b2",367:"25211792",414:"2589534e",756:"71b41ac9",904:"3a60e65a"}[e]+".css"}}(),function(){a.g=function(){if("object"===typeof globalThis)return globalThis;try{return this||new Function("return this")()}catch(e){if("object"===typeof window)return window}}()}(),function(){a.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)}}(),function(){var e={},t="contao-manager:";a.l=function(s,i,n,o){if(e[s])e[s].push(i);else{var l,r;if(void 0!==n)for(var c=document.getElementsByTagName("script"),u=0;u<c.length;u++){var d=c[u];if(d.getAttribute("src")==s||d.getAttribute("data-webpack")==t+n){l=d;break}}l||(r=!0,l=document.createElement("script"),l.charset="utf-8",a.nc&&l.setAttribute("nonce",a.nc),l.setAttribute("data-webpack",t+n),l.src=s,0!==l.src.indexOf(window.location.origin+"/")&&(l.crossOrigin="anonymous")),e[s]=[i];var p=function(t,a){l.onerror=l.onload=null,clearTimeout(g);var i=e[s];if(delete e[s],l.parentNode&&l.parentNode.removeChild(l),i&&i.forEach(function(e){return e(a)}),t)return t(a)},g=setTimeout(p.bind(null,void 0,{type:"timeout",target:l}),12e4);l.onerror=p.bind(null,l.onerror),l.onload=p.bind(null,l.onload),r&&document.head.appendChild(l)}}}(),function(){a.r=function(e){"undefined"!==typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})}}(),function(){a.p=""}(),function(){if("undefined"!==typeof document){var e=function(e,t,s,i,n){var o=document.createElement("link");o.rel="stylesheet",o.type="text/css",a.nc&&(o.nonce=a.nc);var l=function(a){if(o.onerror=o.onload=null,"load"===a.type)i();else{var s=a&&a.type,l=a&&a.target&&a.target.href||t,r=new Error("Loading CSS chunk "+e+" failed.\n("+s+": "+l+")");r.name="ChunkLoadError",r.code="CSS_CHUNK_LOAD_FAILED",r.type=s,r.request=l,o.parentNode&&o.parentNode.removeChild(o),n(r)}};return o.onerror=o.onload=l,o.href=t,0!==o.href.indexOf(window.location.origin+"/")&&(o.crossOrigin="anonymous"),s?s.parentNode.insertBefore(o,s.nextSibling):document.head.appendChild(o),o},t=function(e,t){for(var a=document.getElementsByTagName("link"),s=0;s<a.length;s++){var i=a[s],n=i.getAttribute("data-href")||i.getAttribute("href");if("stylesheet"===i.rel&&(n===e||n===t))return i}var o=document.getElementsByTagName("style");for(s=0;s<o.length;s++){i=o[s],n=i.getAttribute("data-href");if(n===e||n===t)return i}},s=function(s){return new Promise(function(i,n){var o=a.miniCssF(s),l=a.p+o;if(t(o,l))return i();e(s,l,null,i,n)})},i={524:0};a.f.miniCss=function(e,t){var a={120:1,186:1,335:1,367:1,414:1,756:1,904:1};i[e]?t.push(i[e]):0!==i[e]&&a[e]&&t.push(i[e]=s(e).then(function(){i[e]=0},function(t){throw delete i[e],t}))}}}(),function(){var e={524:0};a.f.j=function(t,s){var i=a.o(e,t)?e[t]:void 0;if(0!==i)if(i)s.push(i[2]);else if(756!=t){var n=new Promise(function(a,s){i=e[t]=[a,s]});s.push(i[2]=n);var o=a.p+a.u(t),l=new Error,r=function(s){if(a.o(e,t)&&(i=e[t],0!==i&&(e[t]=void 0),i)){var n=s&&("load"===s.type?"missing":s.type),o=s&&s.target&&s.target.src;l.message="Loading chunk "+t+" failed.\n("+n+": "+o+")",l.name="ChunkLoadError",l.type=n,l.request=o,i[1](l)}};a.l(o,r,"chunk-"+t,t)}else e[t]=0},a.O.j=function(t){return 0===e[t]};var t=function(t,s){var i,n,o=s[0],l=s[1],r=s[2],c=0;if(o.some(function(t){return 0!==e[t]})){for(i in l)a.o(l,i)&&(a.m[i]=l[i]);if(r)var u=r(a)}for(t&&t(s);c<o.length;c++)n=o[c],a.o(e,n)&&e[n]&&e[n][0](),e[n]=0;return a.O(u)},s=self["webpackChunkcontao_manager"]=self["webpackChunkcontao_manager"]||[];s.forEach(t.bind(null,0)),s.push=t.bind(null,s.push.bind(s))}();var s=a.O(void 0,[504],function(){return a(7040)});s=a.O(s)})();"use strict";(self["webpackChunkcontao_manager"]=self["webpackChunkcontao_manager"]||[]).push([[638],{3638:function(e){e.exports=JSON.parse('{"ui.app.httpsHeadline":"!! Niezabezpieczone połączenie !!","ui.app.httpsDescription":"Bez HTTPS twoje poufne dane są przesyłane w postaci niezaszyfrowanej.","ui.app.httpsLink":"Więcej informacji","ui.app.httpsHref":"https://https.cio.gov/everything/","ui.app.safeModeHeadline":"!! Tryb bezpieczny włączony !!","ui.app.safeModeDescription":"Część funkcji Contao Managera jest niedostępna.","ui.app.safeModeExit":"Wyłącz tryb bezpieczny","ui.app.limitedHeadline":"Uwierzytelnianie zdalne","ui.app.limitedDescription":"Masz ograniczone uprawnienia, ponieważ logowanie odbyło się bez hasła.","ui.app.limitedLogout":"Ponownie uwierzytelnij","ui.app.totpHeadline":"Komunikat bezpieczeństwa","ui.app.totpDescription":"Skonfiguruj teraz uwierzytelnianie dwuskładnikowe, aby zabezpieczyć konto.","ui.app.totpSetup":"Konfiguracja","ui.app.loading":"Ładowanie Contao Managera …","ui.app.apiError":"Nieoczekiwany status API","ui.app.configSecurity1":"ALERT BEZPIECZEŃSTWA !!! Wykryto niezabezpieczony katalog konfiguracyjny","ui.app.configSecurity2":"Contao Manager wykrył, że jego pliki konfiguracyjne są publicznie dostępne. Wszystkie operacje zostały zablokowane do czasu zabezpieczenia katalogu, gdyż w przeciwnym razie napastnik może uzyskać dostęp do wrażliwych danych twojej instalacji.\\n\\nAby naprawić problem, zablokuj dostęp do katalogu \\"contao-manager\\" na serwerze. Jeśli nie wiesz jak to zrobić, skorzystaj z dokumentacji serwera lub skontaktuj się z dostawcą hostingu.","ui.account.welcome":"Witaj","ui.account.intro1":"Witamy w Contao Managerze, uniwersalnym narzędziu do instalacji i administracji Contao Open Source CMS. Jeżeli dopiero zaczynasz, {readTheManualToGetStarted}.","ui.account.introGetStarted":"{readTheManual}, aby rozpocząć","ui.account.introManual":"przeczytaj instrukcję","ui.account.intro2":"Jeśli natrafisz na problemy, sprawdź {ourGithubIssues} i zgłoś każdy temat, którego nie ma na liście.","ui.account.introIssues":"naszą listę zgłoszeń na GitHubie","ui.account.headline":"Konto użytkownika","ui.account.description":"Aby zarządzać instalacją, utwórz konto w Contao Managerze. To konto nie jest powiązane z frontendem ani backendem Contao.","ui.account.username":"Nazwa użytkownika","ui.account.password":"Hasło","ui.account.passwordPlaceholder":"min. 8 znaków","ui.account.passwordLength":"Wprowadź co najmniej 8 znaków.","ui.account.loginInvalid":"Podczas tworzenia konta wystąpił błąd. Spróbuj nadać inną nazwę użytkownika.","ui.account.submit":"Utwórz konto","ui.account.usePassword":"Loguj przy użyciu hasła","ui.account.usePasskey":"Loguj przy użyciu klucza Passkey","ui.account.totpHeadline":"Uwierzytelnianie dwuskładnikowe","ui.account.totpDescription":"Włącz uwierzytelnianie dwuskładnikowe, aby dodać kolejną warstwę ochrony konta. Oprócz nazwy użytkownika i hasła należy podać kod weryfikacyjny generowany przez aplikację 2FA, np. 1Password, Authy, Google Authenticator, Microsoft Authenticator, LastPass Authenticator lub dowolną inną aplikację TOTP.","ui.account.totpSetup":"Skonfiguruj teraz","ui.account.totpSkip":"Skonfiguruj później","ui.account.login":"Odrzuć zaproszenie","ui.account.contribute1":"Contao oraz Contao Manager są finansowane przez organizację Contao Association.","ui.account.contribute2":"Rozważ wsparcie open source poprzez {donate}.","ui.account.contributeDonate":"przekazanie darowizny","ui.login.headline":"Zaloguj się","ui.login.description":"Zaloguj się, aby zarządzać instalacją.","ui.login.username":"Nazwa użytkownika","ui.login.password":"Hasło","ui.login.totpHeadline":"Uwierzytelnianie dwuskładnikowe","ui.login.totpDescription":"Wprowadź kod weryfikacyjny, aby zakończyć logowanie.","ui.login.totp":"Kod weryfikacyjny","ui.login.forgotPassword":"Zapomniałeś hasła?","ui.login.button":"Zaloguj się","ui.login.passkey":"Zaloguj się kluczem Passkey","ui.login.cancel":"Anuluj","ui.login.or":"lub","ui.login.locked":"Odmówiono dostępu, ponieważ Contao Manager jest zablokowany. Aby odblokować, usuń plik {lockFile} w katalogu głównym Contao.","ui.logout.headline":"Limit czasu sesji","ui.logout.warning":"Jesteś nieaktywny od ponad 25 minut. Ze względów bezpieczeństwa sesja zostanie wkrótce zamknięta.","ui.logout.expired":"Sesja została automatycznie zakończona po ponad 30 minutach bezczynności.","ui.logout.renew":"Pozostań zalogowany","ui.logout.logout":"Wyloguj","ui.logout.login":"Powrót do logowania","ui.oauth.error":"Nieprawidłowa próba OAuth. Sprawdź parametry żądania.","ui.oauth.https":"URI przekierowania MUSI używać bezpiecznego protokołu (https:), aby token uwierzytelniający nie był przesyłany w postaci jawnej.","ui.oauth.headline":"Uwierzytelnianie zdalne","ui.oauth.description":"Poniższa aplikacja żąda dostępu do Contao Managera, aby wykonywać operacje w twoim imieniu.","ui.oauth.domain":"Przed nadaniem dostępu upewnij się, że rozpoznajesz ten adres URL i ufasz jego właścicielowi!","ui.oauth.outOfScope":"Niestety nie masz wymaganych uprawnień do nadania takiego dostępu.","ui.oauth.allow":"Zezwól na dostęp","ui.oauth.deny":"Odrzuć","ui.oauth.switchUser":"Zmień użytkownika","ui.scope.admin":"Dostęp administracyjny obejmujący zarządzanie użytkownikami","ui.scope.install":"Instalowanie pakietów i modyfikacja konfiguracji Contao","ui.scope.update":"Aktualizacja pakietów i wykonywanie zadań serwisowych","ui.scope.read":"Odczyt pakietów i konfiguracji","ui.boot.headline":"Kontrola systemu","ui.boot.description":"Trwa analiza serwera …","ui.boot.issue1":"Wykryto problemy instalacyjne","ui.boot.issue2":"Zidentyfikowano problemy, które należy usunąć przed użyciem Contao Managera.","ui.boot.run":"Uruchom Contao Managera","ui.boot.safeMode":"Uruchom w trybie bezpiecznym","ui.recovery.headline":"Odzyskiwanie systemu","ui.recovery.description":"Contao Manager wykrył pliki przypominające Contao, ale interfejs CLI nie działa zgodnie z oczekiwaniami.","ui.recovery.console":"Wyjście konsoli","ui.recovery.repairOptions":"Wybierz metodę naprawy instalacji.","ui.recovery.repairHeadline":"Automatyczna naprawa","ui.recovery.repairDescription":"Próbuje automatycznie naprawić instalację, przebudowując cache aplikacji i reinstalując pakiety Composera.","ui.recovery.repairWarning":"Podczas procesu wszelkie modyfikacje w katalogu vendor mogą zostać usunięte!","ui.recovery.repairFailed":"Automatyczna naprawa nie powiodła się. Uruchom tryb bezpieczny i napraw instalację ręcznie.","ui.recovery.repairButton":"Uruchom naprawę systemu","ui.recovery.safeModeHeadline":"Tryb bezpieczny","ui.recovery.safeModeDescription":"Uruchomienie Contao Managera w trybie bezpiecznym umożliwia zarządzanie pakietami i wykonywanie wybranych działań serwisowych, lecz funkcje zależne od działającej instalacji Contao będą niedostępne.","ui.recovery.safeModeButton":"Uruchom w trybie bezpiecznym","ui.server.pending":"Oczekiwanie …","ui.server.running":"Analiza …","ui.server.error":"Kontrola nie powiodła się z powodu nieoczekiwanej odpowiedzi serwera.","ui.server.details":"Szczegóły","ui.server.prerequisite":"Kontrolę anulowano z powodu niespełnionego wymagania.","ui.server.selfUpdate.title":"Aktualizacje Contao Managera","ui.server.selfUpdate.update":"Dostępna jest nowa wersja Contao Managera {latest}.","ui.server.selfUpdate.manualUpdate":"Dostępna jest nowa wersja Contao Managera {latest}. Ten serwer nie obsługuje automatycznych aktualizacji; pobierz nowe wydanie z {download}.","ui.server.selfUpdate.latest":"Używasz najnowszej wersji {current}.","ui.server.selfUpdate.dev":"Wydania deweloperskie nie obsługują automatycznych aktualizacji.","ui.server.selfUpdate.unsupported":"Dostępna jest nowa wersja, ale nie obsługuje używanej wersji PHP.","ui.server.selfUpdate.button":"Uruchom autoaktualizację","ui.server.selfUpdate.continue":"Kontynuuj","ui.server.config.title":"Konfiguracja serwera","ui.server.config.setup":"Skonfiguruj","ui.server.config.change":"Zmień","ui.server.config.save":"Zapisz","ui.server.config.cancel":"Anuluj","ui.server.config.customOption":"Inna …","ui.server.config.description":"Aby prawidłowo uruchamiać zadania w tle, Contao Manager musi znać lokalizację pliku wykonywalnego PHP CLI i sposób uruchamiania poleceń poza procesem WWW.","ui.server.config.formTitle":"Konfiguracja serwera","ui.server.config.formText":"Podaj ścieżkę do pliku wykonywalnego PHP zgodnego wersją z procesem WWW.","ui.server.config.cloudTitle":"Chmura Composer Resolver","ui.server.config.cloudText":"Composer Resolver Cloud umożliwia instalowanie zależności nawet wtedy, gdy serwer nie dysponuje wystarczającą pamięcią. Informacje o pakietach zostaną przesłane do chmury zarządzanej przez Contao Association.","ui.server.config.cloud":"Korzystaj z Composer Resolver Cloud","ui.server.config.cli":"Plik wykonywalny PHP","ui.server.config.stateErrorCli":"Na serwerze nie znaleziono prawidłowego pliku wykonywalnego PHP.","ui.server.config.stateErrorCloud":"Composer Resolver Cloud nie jest obsługiwany.","ui.server.config.stateSuccess":"Plik PHP znajduje się pod {php_cli}.","ui.server.config.cloudEnabled":"Zależności pakietów będą rozwiązywane przy użyciu Composer Resolver Cloud.","ui.server.config.cloudDisabled":"Composer Resolver Cloud jest wyłączony.","ui.server.php_web.title":"Proces PHP (WWW)","ui.server.php_web.below7":"Wykryto PHP {version}. Jak najszybciej przełącz się na PHP 7.","ui.server.php_web.success":"Wykryto PHP {version}; brak znanych problemów.","ui.server.php_cli.title":"Interfejs PHP w wierszu poleceń","ui.server.php_cli.success":"Wykryto PHP {version}; brak znanych problemów.","ui.server.composer.title":"Środowisko Composera","ui.server.composer.success":"Nie wykryto znanych problemów.","ui.server.composer.install":"Zależności Composera nie są zainstalowane.","ui.server.composer.button":"Zainstaluj","ui.server.contao.title":"Instalacja Contao","ui.server.contao.setup":"Konfiguracja","ui.server.contao.check":"Sprawdź bazę danych","ui.server.contao.empty":"Nie znaleziono instalacji Contao.","ui.server.contao.old":"Contao {version} nie jest zgodne z Contao Managerem; zaktualizuj instalację ręcznie.","ui.server.contao.found":"Wykryto Contao {version} (wersja API {api}).","ui.server.contao.connectionError":"Nie można połączyć się z serwerem bazy danych.","ui.server.contao.connectionProblem":"Wykryto problem z bazą danych.","ui.server.contao.missingUser":"Nie znaleziono konta administratora.","ui.setup.continue":"Kontynuuj","ui.setup.manager":"Uruchom Contao Managera","ui.setup.cancel":"Anuluj","ui.setup.welcome":"Witaj","ui.setup.welcome1":"Ten kreator przeprowadzi Cię przez wszystkie kroki konfiguracji Contao Open Source CMS.","ui.setup.welcome2":"Dokumentację, forum, kanał Slack i inne zasoby znajdziesz na stronie {support}.","ui.setup.support":"dziale społeczności","ui.setup.start":"Rozpocznij konfigurację","ui.setup.complete":"Gratulacje!","ui.setup.complete1":"Contao {version} zostało pomyślnie zainstalowane.","ui.setup.complete2":"Aby zakończyć konfigurację, otwórz narzędzie instalacyjne, skonfiguruj połączenie z bazą i utwórz konto backendu.","ui.setup.complete3":"Możesz już budować witrynę w backendzie Contao. Jeśli potrzebujesz rozszerzeń, kontynuuj w Contao Managerze.","ui.setup.installTool":"Otwórz narzędzie instalacyjne","ui.setup.login":"Zaloguj się do Contao","ui.setup.funding":"Otwarte oprogramowanie jest \\"wolne\\" jak \\"wolność słowa\\", a nie \\"darmowe piwo\\". Projekt open source taki jak Contao wymaga nakładów finansowych, których nie pokryje pojedyncza osoba ani firma.\\nJeśli prowadzisz witrynę lub sprzedajesz witryny oparte na Contao, rozważ wsparcie finansowe produktu, z którego korzysta twój biznes.","ui.setup.fundingLink":"Dowiedz się więcej","ui.setup.document-root.headline":"Konfiguracja serwera WWW","ui.setup.document-root.warning":"Aby zainstalować Contao poprzez Contao Managera, musisz poprawnie ustawić katalog główny (document root) na serwerze WWW.","ui.setup.document-root.description1":"Contao używa oddzielnego katalogu na pliki publiczne, a pliki aplikacji są instalowane w katalogu nadrzędnym. Instalacja Contao nie powiedzie się, jeśli struktura katalogów jest niepoprawna lub foldery nie są puste.","ui.setup.document-root.description2":"Jeżeli nie wiesz jak skonfigurować document root, przeczytaj dokumentację Contao lub skontaktuj się z administratorem hostingu.","ui.setup.document-root.documentation":"Przeczytaj dokumentację","ui.setup.document-root.conflictsTitle":"Katalog instalacyjny nie jest pusty","ui.setup.document-root.conflictsDirectory":"Katalog główny przyszłej instalacji Contao nie jest pusty; znaleziono {count} plik(i), które mogą zostać nadpisane podczas instalacji. Zaleca się utworzenie pustej struktury katalogów dla Contao, jednak możesz usunąć poniższe pliki i sprawdzić ponownie, jeśli masz pewność, że nie są używane.","ui.setup.document-root.ignoreConflicts":"Chcę zainstalować Contao w katalogu, który nie jest pusty. Rozumiem, że istniejące pliki w przestrzeni dyskowej mogą zostać nadpisane.","ui.setup.document-root.check":"Sprawdź ponownie","ui.setup.document-root.create":"Utwórz katalogi","ui.setup.document-root.change":"Zmień katalogi","ui.setup.document-root.formTitle":"Konfiguracja katalogów","ui.setup.document-root.formText1":"Contao Manager może automatycznie utworzyć nową strukturę katalogów na serwerze.","ui.setup.document-root.formText2":"Nowy document root trzeba skonfigurować ręcznie (np. w panelu administracyjnym hostingu).","ui.setup.document-root.autoconfig":"Rozumiem, że muszę zmienić konfigurację serwera. Nieprawidłowy document root unieruchomi Contao Managera i ujawni pliki konfiguracyjne (w tym dane kont i hasła)!","ui.setup.document-root.directory":"Nowy katalog","ui.setup.document-root.currentRoot":"Bieżący document root","ui.setup.document-root.newRoot":"Nowy document root","ui.setup.document-root.finish":"Zastosuj katalogi","ui.setup.document-root.publicDir":"Użyj {dir} dla plików publicznych (Contao {version})","ui.setup.document-root.directoryInvalid":"Podaj prawidłową nazwę katalogu.","ui.setup.document-root.directoryExists":"Docelowy katalog już istnieje. Podaj inną nazwę.","ui.setup.document-root.confirmation":"Contao Manager utworzył wymagane katalogi dla instalacji Contao. Teraz skonfiguruj document root na serwerze WWW. Nie przeładowuj tej strony przed zakończeniem.","ui.setup.document-root.reload":"Przeładuj stronę","ui.setup.document-root.success":"Struktura katalogów na serwerze została poprawnie skonfigurowana!","ui.setup.document-root.installingProjectDir":"Pliki aplikacji zostaną zainstalowane w {dir}.","ui.setup.document-root.installingPublicDir":"Pliki publiczne zostaną zainstalowane w {dir}.","ui.setup.document-root.installedProjectDir":"Pliki aplikacji zostały zainstalowane w {dir}.","ui.setup.document-root.installedPublicDir":"Pliki publiczne zostały zainstalowane w {dir}.","ui.setup.create-project.headline":"Instalacja Contao","ui.setup.create-project.description":"Rozwój Contao podąża za zasadą {semver}; co pół roku udostępniana jest nowa wersja minor. Aktualnie wspierane wydania to:","ui.setup.create-project.semver":"Wersjonowanie semantyczne","ui.setup.create-project.latestTitle":"Najnowsze","ui.setup.create-project.ltsTitle":"Wsparcie długoterminowe","ui.setup.create-project.latestQ1":"Najnowsza wersja oferująca pełną funkcjonalność, wspierana do lutego {year}.","ui.setup.create-project.latestQ3":"Najnowsza wersja oferująca pełną funkcjonalność, wspierana do sierpnia {year}.","ui.setup.create-project.ltsText":"Aktualna wersja LTS dla maksymalnej stabilności, wspierana do lutego {year}.","ui.setup.create-project.pltsText":"Poprzednia wersja LTS, nadal ze wsparciem do lutego {year}.","ui.setup.create-project.requiresPHP":"Wymaga przynajmniej PHP {version}; aktualnie dostępne PHP {current}.","ui.setup.create-project.releaseplan":"Pełne zestawienie znajdziesz w {contaoReleasePlan}.","ui.setup.create-project.releaseplanLink":"Plan wydań Contao","ui.setup.create-project.installed":"Contao {version} zostało pomyślnie zainstalowane na serwerze. Skonfiguruj bazę danych lub uruchom Contao Managera, aby zainstalować inną wersję.","ui.setup.create-project.formTitle":"Wybierz dystrybucję","ui.setup.create-project.formText":"Wskaż wersję, która ma zostać zainstalowana.","ui.setup.create-project.version":"Wersja","ui.setup.create-project.demo":"Zainstaluj witrynę demonstracyjną Contao","ui.setup.create-project.demoDescription":"Witryna demo ułatwia poznanie Contao i kluczowych funkcji. Więcej motywów znajdziesz w {store}.","ui.setup.create-project.coreOnly":"Instalacja minimalna (tylko core)","ui.setup.create-project.noUpdate":"Pomiń instalację (tylko eksperci)","ui.setup.create-project.theme":"Motyw Contao","ui.setup.create-project.themeInstall":"Aby zainstalować motyw, skorzystaj z wyszukiwania lub prześlij plik motywu (.cto/.zip) kompatybilny z Contao Managerem.","ui.setup.create-project.themeBuy":"Odwiedź oficjalny {store}.","ui.setup.create-project.themeStore":"Sklep z motywami Contao","ui.setup.create-project.themeUpload":"Wyślij plik motywu (.cto/.zip)","ui.setup.create-project.themeInvalid":"Przesłany plik nie jest motywem Contao albo nie obsługuje instalacji w Contao Managerze.","ui.setup.create-project.themeWarning":"Contao Manager nie może ocenić zgodności motywu z serwerem. W razie wątpliwości skontaktuj się z dostawcą motywu.","ui.setup.create-project.themeTitle":"Zweryfikuj szczegóły motywu","ui.setup.create-project.themeDetails":"Ten motyw zainstaluje następujące zależności i pliki.","ui.setup.create-project.themeRequire":"{count} zależność | {count} zależności","ui.setup.create-project.themeFiles":"{count} plik | {count} pliki","ui.setup.create-project.theme.or":"lub wyszukaj motywy publiczne","ui.setup.create-project.theme.search":"Szukaj motywów","ui.setup.create-project.theme.more":"Więcej motywów","ui.setup.create-project.theme.empty":"Brak motywów spełniających warunek {query}","ui.setup.create-project.theme.uploaded":"Plik motywu został pomyślnie przesłany.","ui.setup.create-project.theme.packageName":"Nazwa pakietu","ui.setup.create-project.theme.version":"Wersja","ui.setup.create-project.theme.authors":"Autorzy","ui.setup.create-project.theme.upload":"Przesyłanie {name} ({size})","ui.setup.create-project.install":"Zainstaluj","ui.setup.create-project.cancel":"Anuluj","ui.setup.create-project.fileError":"Nie znaleziono composer.json w {file}.","ui.setup.create-project.jsonError":"Plik composer.json zawiera nieprawidłowy JSON.","ui.setup.create-project.schemaError":"Walidacja schematu composer.json nie powiodła się.","ui.setup.database-connection.headline":"Połączenie z bazą danych","ui.setup.database-connection.description":"Contao wymaga bazy MySQL (lub zgodnego forka, np. MariaDB) do przechowywania stron, treści, użytkowników i innych danych relacyjnych. Parametry połączenia są zapisywane w pliku {env} w katalogu głównym projektu.","ui.setup.database-connection.formTitle":"Parametry połączenia","ui.setup.database-connection.formText":"Podaj URL bazy danych lub wypełnij pola użytkownika, hasła, serwera i nazwy bazy.","ui.setup.database-connection.url":"URL bazy danych","ui.setup.database-connection.validUrl":"URL bazy danych jest nieprawidłowy lub nie udało się połączyć z serwerem.","ui.setup.database-connection.or":"lub","ui.setup.database-connection.user":"Użytkownik","ui.setup.database-connection.password":"Hasło","ui.setup.database-connection.server":"Serwer (:port)","ui.setup.database-connection.database":"Nazwa bazy","ui.setup.database-connection.connected":"Pomyślnie połączono z bazą {database} na serwerze {server}.","ui.setup.database-connection.error":"Błąd połączenia z bazą danych.","ui.setup.database-connection.problem":"Wykryto problem z serwerem bazy danych.","ui.setup.database-connection.schemaTitle":"Schemat bazy danych","ui.setup.database-connection.migration":"Oczekuje jedna migracja. | Oczekuje {count} migracji.","ui.setup.database-connection.schema":"Oczekuje jedna aktualizacja schematu. | Oczekuje {count} aktualizacji schematu.","ui.setup.database-connection.noChanges":"Schemat bazy danych jest aktualny.","ui.setup.database-connection.check":"Sprawdź bazę","ui.setup.database-connection.skip":"Pomiń","ui.setup.database-connection.save":"Zapisz","ui.setup.database-connection.change":"Zmień dane logowania","ui.setup.database-connection.restoreTitle":"Import bazy danych","ui.setup.database-connection.restoreText":"Właśnie zainstalowany motyw zawiera kopię zapasową bazy danych. Przywróć ją, aby zaimportować dane motywu, lub pomiń ten krok, jeżeli chcesz startować z pustą instalacją Contao. | Właśnie zainstalowany motyw zawiera wiele kopii zapasowych. Wybierz plik kopii, aby zaimportować dane motywu, lub pomiń ten krok, jeśli chcesz rozpocząć od pustej instalacji Contao.","ui.setup.database-connection.backup":"Utwórz kopię bieżącej bazy przed importem","ui.setup.database-connection.backupWarning":"Podczas importu wszystkie dane w bazie zostaną nadpisane! Utwórz kopię zapasową, jeśli baza nie jest pusta.","ui.setup.database-connection.restore":"Importuj bazę motywu","ui.setup.database-connection.restoreOption":"Kopia z {date} ({size})","ui.setup.database-connection.restored":"Baza danych motywu została zaimportowana. Kontynuuj weryfikację schematu bazy.","ui.setup.backend-user.success":"W bazie danych znaleziono konto administracyjne backendu Contao. Dodawaj kolejnych użytkowników z poziomu backendu.","ui.setup.backend-user.error":"Nie można pobrać listy użytkowników. Szczegóły znajdziesz w konsoli.","ui.setup.backend-user.headline":"Konto backendu","ui.setup.backend-user.description":"Do zarządzania witryną potrzebne jest co najmniej jedno konto administratora backendu Contao. To konto nie ma związku z Contao Managerem.","ui.setup.backend-user.formTitle":"Utwórz konto","ui.setup.backend-user.formText":"Wprowadź dane dla nowego konta backendu.","ui.setup.backend-user.username":"Nazwa użytkownika","ui.setup.backend-user.name":"Imię i nazwisko","ui.setup.backend-user.email":"Adres e-mail","ui.setup.backend-user.emailInvalid":"Podaj poprawny adres e-mail","ui.setup.backend-user.password":"Hasło","ui.setup.backend-user.passwordPlaceholder":"min. 8 znaków","ui.setup.backend-user.passwordLength":"Wprowadź co najmniej 8 znaków.","ui.setup.backend-user.create":"Dodaj konto","ui.task.headline":"Zadanie w tle","ui.task.loading":"Ładowanie szczegółów …","ui.task.created":"Ładowanie szczegółów …","ui.task.active":"Contao Manager wykonuje operacje w tle, proszę czekać.","ui.task.complete":"Wszystkie operacje zakończyły się powodzeniem. Szczegóły znajdują się w konsoli.","ui.task.paused":"Operacja w tle została niespodziewanie zatrzymana. Sprawdź konsolę.","ui.task.aborting":"Trwa anulowanie operacji w tle, proszę czekać.","ui.task.stopped":"Niektóre operacje w tle zostały anulowane. Sprawdź konsolę.","ui.task.error":"Operacja w tle została niespodziewanie zatrzymana. Sprawdź konsolę.","ui.task.failed":"Contao Manager nie mógł uruchomić zadania w tle!","ui.task.failedDescription1":"Wystąpił błąd podczas uruchamiania operacji w tle.","ui.task.failedDescription2":"Jeśli problem się powtórzy, środowisko serwera może być nieobsługiwane.","ui.task.reportProblem":"Zgłoś problem","ui.task.pausedDescription":"Kliknij \\"Kontynuuj\\", aby zignorować błąd i wykonać pozostałe operacje.","ui.task.sponsor":"Composer Cloud sponsorowany przez {sponsor}","ui.task.buttonAudit":"Aktualizuj bazę danych","ui.task.buttonClose":"Zamknij","ui.task.buttonConfirm":"Potwierdź i zamknij","ui.task.buttonContinue":"Kontynuuj","ui.task.buttonCancel":"Anuluj","ui.task.confirmCancel":"Na pewno chcesz anulować to zadanie? Instalacja Contao może pozostać w stanie niespójnym.","ui.task.autoclose":"Zamknij szczegóły zadania po powodzeniu","ui.console.toggle":"Pokaż/ukryj wyjście konsoli","ui.console.showLog":"Pokaż pełny log konsoli","ui.console.copyLog":"Skopiuj log do schowka","ui.migrate.headline":"Aktualizacje bazy danych","ui.migrate.migrationsOnly":"(tylko migracje)","ui.migrate.schemaOnly":"(tylko schemat)","ui.migrate.loading":"Trwa weryfikacja bazy danych …","ui.migrate.empty":"Brak oczekujących migracji ani aktualizacji schematu. Baza jest aktualna.","ui.migrate.emptyMigrations":"Brak oczekujących migracji. Pamiętaj również o sprawdzeniu aktualizacji schematu.","ui.migrate.emptySchema":"Brak oczekujących aktualizacji schematu. Pamiętaj także o migracjach.","ui.migrate.pending":"Baza danych nie jest aktualna. Przejrzyj log konsoli poniżej i wykonaj zmiany.","ui.migrate.previousChanges":"Poprzednia migracja bazy nie została potwierdzona.\\nPrzejrzyj log konsoli poniżej, a następnie kontynuuj, aby zobaczyć kolejne zmiany.","ui.migrate.previousComplete":"Poprzednia migracja bazy nie została potwierdzona, przejrzyj log konsoli poniżej.\\nNie ma już dalszych zmian.","ui.migrate.appliedChanges":"Zmiany w bazie zostały zastosowane.\\nPrzejrzyj log konsoli poniżej, a następnie kontynuuj, aby zobaczyć kolejne zmiany.","ui.migrate.appliedComplete":"Zmiany w bazie zostały zastosowane.\\nBrak oczekujących migracji ani aktualizacji schematu. Baza jest aktualna.","ui.migrate.problem":"Contao wykryło problem z serwerem bazy danych.\\nSprawdź log konsoli poniżej, aby ustalić, co należy naprawić. | Contao wykryło problemy z serwerem bazy danych.\\nSprawdź log konsoli poniżej, aby ustalić, co należy naprawić.","ui.migrate.warning":"Contao wykryło niepoprawną konfigurację serwera bazy danych.\\nOstrzeżenia można tymczasowo pominąć, ale należy je usunąć dla optymalnej wydajności i integralności danych.","ui.migrate.error":"Nie udało się zastosować zmian. Baza mogła zostać częściowo zmodyfikowana, uruchom kontrolę ponownie.","ui.migrate.execute":"Wykonaj","ui.migrate.close":"Zamknij","ui.migrate.confirm":"Potwierdź i zamknij","ui.migrate.cancel":"Anuluj","ui.migrate.continue":"Kontynuuj","ui.migrate.setup":"Konfiguracja","ui.migrate.skip":"Pomiń","ui.migrate.retry":"Sprawdź ponownie","ui.migrate.retryAll":"Sprawdź wszystko","ui.migrate.withDeletes":"Wykonaj wszystkie zmiany w bazie, w tym zapytania DROP.","ui.migrate.migrationTitle":"Migracje bazy danych","ui.migrate.schemaTitle":"Aktualizacje schematu","ui.migrate.problemTitle":"Problemy bazy danych","ui.migrate.warningTitle":"Ostrzeżenia bazy danych","ui.migrate.addTable":"Dodaj tabelę {table}","ui.migrate.dropTable":"Usuń tabelę {table}","ui.migrate.addField":"Dodaj pole {table}.{field}","ui.migrate.changeField":"Zmień pole {table}.{field}","ui.migrate.dropField":"Usuń pole {table}.{field}","ui.migrate.createIndex":"Utwórz indeks \\"{name}\\" w tabeli {table}","ui.migrate.dropIndex":"Usuń indeks \\"{name}\\" z tabeli {table}","ui.widget.mandatory":"To pole nie może być puste.","ui.widget.blankOption":"Wybierz …","ui.widget.showPassword":"Pokaż hasło","ui.widget.hidePassword":"Ukryj hasło","ui.error.title":"Żądanie HTTP \\"{method} {url}\\" zakończyło się błędem.","ui.error.server500":"Wygląda na to, że na serwerze wystąpił nieoczekiwany błąd. Sprawdź logi serwera WWW (Apache/Nginx) oraz logi Contao Managera w \\"contao-manager/logs\\".","ui.error.response":"Serwer zwrócił status {status}.","ui.error.moreLink":"Więcej informacji","ui.error.support":"Wsparcie Contao","ui.error.permission":"Nie masz uprawnień do tej funkcji.","ui.footer.help":"Pomoc","ui.footer.reportProblem":"Zgłoś problem","ui.navigation.discover":"Odkrywaj","ui.navigation.packages":"Pakiety","ui.navigation.tools":"Narzędzia","ui.navigation.installTool":"Narzędzie instalacyjne","ui.navigation.backend":"Backend Contao","ui.navigation.debug":"Tryb debugowania Contao","ui.navigation.logViewer":"Przeglądaj logi","ui.navigation.phpinfo":"Informacje PHP","ui.navigation.phpinfoLoading":"Ładowanie informacji PHP…","ui.navigation.maintenance":"Konserwacja","ui.navigation.rebuildCache":"Przebuduj cache","ui.navigation.users":"Konta","ui.navigation.systemCheck":"Kontrola systemu","ui.navigation.advanced":"Zaawansowane","ui.navigation.logout":"Wyloguj","ui.maintenance.database.title":"Migracje i kopie bazy danych","ui.maintenance.database.description":"Migracje bazy danych utrzymują spójność danych i struktury tabel.","ui.maintenance.database.migrations":"Jedna oczekująca migracja | {count} oczekujących migracji","ui.maintenance.database.schemaUpdates":"Jedna aktualizacja schematu | {count} aktualizacji schematu","ui.maintenance.database.error":"Wykryto problem z bazą danych.","ui.maintenance.database.warning":"Wykryto ostrzeżenia bazy danych.","ui.maintenance.database.button":"Sprawdź bazę","ui.maintenance.database.migrationOnly":"Sprawdź tylko migracje","ui.maintenance.database.schemaOnly":"Sprawdź tylko schemat","ui.maintenance.database.installTool":"Otwórz narzędzie instalacyjne","ui.maintenance.database.createBackup":"Utwórz kopię zapasową","ui.maintenance.database.backupUnsupported":"Twoja wersja Contao nie obsługuje kopii zapasowych bazy.","ui.maintenance.database.backupList":"Masz jedną kopię bazy utworzoną {date}. | Masz {count} kopii bazy, ostatnia powstała {date}.","ui.maintenance.database.backupEmpty":"Brak kopii zapasowych bazy danych.","ui.maintenance.rebuildCache.title":"Pamięć podręczna aplikacji","ui.maintenance.rebuildCache.description":"Po każdej zmianie plików konfiguracyjnych należy przebudować cache aplikacji.","ui.maintenance.rebuildCache.rebuildProd":"Przebuduj cache produkcyjny","ui.maintenance.rebuildCache.rebuildDev":"Przebuduj cache deweloperski","ui.maintenance.rebuildCache.clearProd":"Wyczyść cache produkcyjny","ui.maintenance.rebuildCache.clearDev":"Wyczyść cache deweloperski","ui.maintenance.installTool.title":"Narzędzie instalacyjne Contao","ui.maintenance.installTool.description":"Narzędzie instalacyjne Contao jest automatycznie blokowane po trzykrotnym błędnym haśle.","ui.maintenance.installTool.unlock":"Odblokuj narzędzie","ui.maintenance.installTool.lock":"Zablokuj narzędzie","ui.maintenance.dumpAutoload.title":"Autoloader klas Composera","ui.maintenance.dumpAutoload.description":"Autoloader Composera odpowiada za ładowanie klas PHP. Po dodaniu własnych przestrzeni nazw do głównego composer.json należy przebudować autoloader.","ui.maintenance.dumpAutoload.button":"Dumpuj autoloader","ui.maintenance.composerInstall.title":"Zależności Composera","ui.maintenance.composerInstall.description":"Zależności Composera znajdują się w katalogu {vendor} w katalogu aplikacji. Reinstalacja zależności może być wymagana po ręcznych zmianach lub przesłaniu pliku {composerLock}.","ui.maintenance.composerInstall.button":"Uruchom instalator","ui.maintenance.composerInstall.update":"Uruchom composer update","ui.maintenance.composerCache.title":"Cache Composera","ui.maintenance.composerCache.description":"Composer buforuje pobrane pakiety dla wydajności. W przypadku uszkodzonych plików usuń cache, aby wymusić ponowne pobranie.","ui.maintenance.composerCache.button":"Wyczyść cache","ui.maintenance.maintenanceMode.title":"Tryb serwisowy","ui.maintenance.maintenanceMode.description":"Włączenie trybu serwisowego wyświetli witrynie szablon \\"503 Service Unavailable\\".","ui.maintenance.maintenanceMode.enable":"Włącz","ui.maintenance.maintenanceMode.disable":"Wyłącz","ui.maintenance.debugMode.title":"Tryb debugowania","ui.maintenance.debugMode.description":"Aktywuj tryb debug, ustawiając użytkownika i hasło dla punktu wejścia {appDevPhp}.","ui.maintenance.debugMode.descriptionJwt":"Aktywuj tryb debug, ustawiając ciasteczko debugujące dla bieżącej domeny.","ui.maintenance.debugMode.activate":"Aktywuj","ui.maintenance.debugMode.deactivate":"Dezaktywuj","ui.maintenance.debugMode.credentials":"Dane logowania","ui.maintenance.debugMode.user":"Podaj nazwę użytkownika dla trybu debug.","ui.maintenance.debugMode.password":"Podaj hasło dla trybu debug.","ui.maintenance.opcodeCache.title":"Cache opcode","ui.maintenance.opcodeCache.description":"Cache opcode przechowuje skompilowane pliki PHP w procesie WWW. W razie problemów należy go wyczyścić, aby wymusić przeładowanie plików.","ui.maintenance.opcodeCache.button":"Opróżnij cache","ui.maintenance.safeMode":"Niedostępne w trybie bezpiecznym","ui.maintenance.unsupported":"Nieobsługiwane przez tę wersję Contao","ui.packages.updateButton":"Aktualizuj pakiety","ui.packages.searchButton":"Szukaj pakietów","ui.packages.searchPlaceholder":"Szukaj pakietów …","ui.packages.uploadOverlay":"Upuść pliki, aby przesłać","ui.packages.uploadButton":"Prześlij pakiety","ui.packages.uploadMessage":"Masz jeden niezatwierdzony plik. | Masz {count} niezatwierdzonych plików.","ui.packages.uploadApply":"Zatwierdź przesłane","ui.packages.uploadReset":"Usuń przesłane","ui.packages.uploadIncomplete":"Plik nie został przesłany w całości. Usuń go i spróbuj ponownie.","ui.packages.uploadDuplicate":"Plik wydaje się przesłany wielokrotnie. Usuń duplikaty.","ui.packages.uploadInstalled":"Ten pakiet jest już zainstalowany. Usuń duplikaty.","ui.packages.uploadUnsupported":"Przesyłanie pakietów nie jest wspierane w tej instalacji. Upewnij się, że rozszerzenie PHP ZIP jest dostępne i zaktualizuj zależności.","ui.packages.changesMessage":"Masz jedną niezatwierdzoną zmianę. | Masz {count} niezatwierdzonych zmian.","ui.packages.changesDryrun":"Symulacja (dry run)","ui.packages.changesApply":"Zastosuj zmiany","ui.packages.changesApplyAll":"Aktualizuj wszystkie pakiety","ui.packages.changesDryrunAll":"Przetestuj wszystkie pakiety (dry run)","ui.packages.changesReset":"Wycofaj zmiany","ui.packages.changesReview":"Przejrzyj zmiany","ui.packagelist.loading":"Ładowanie …","ui.packagelist.uploads":"Przesłane","ui.packagelist.added":"Nowe pakiety","ui.packagelist.installed":"Zainstalowane pakiety","ui.package.hintRevert":"Wycofaj zmiany","ui.package.hintNoupdate":"Nie aktualizuj","ui.package.hintConstraint":"Pakiet zostanie zainstalowany z ograniczeniem {constraint} po zastosowaniu zmian.","ui.package.hintConstraintBest":"Pakiet zostanie zainstalowany w najlepszej dostępnej wersji po zastosowaniu zmian.","ui.package.hintConstraintChange":"Ograniczenie wersji zostanie zmienione z \\"{from}\\" na \\"{to}\\" po zastosowaniu zmian.","ui.package.hintConstraintUpdate":"Pakiet zostanie zaktualizowany po zastosowaniu zmian.","ui.package.hintAdded":"Pakiet zostanie zainstalowany po zastosowaniu zmian.","ui.package.hintRemoved":"Pakiet zostanie usunięty po zastosowaniu zmian.","ui.package.requiredTitle":"dodano ręcznie","ui.package.requiredText":"Pakiet jest wymagany w composer.json, ale nie został zainstalowany.","ui.package.removedTitle":"usunięto ręcznie","ui.package.removedText":"Pakiet został usunięty z composer.json.","ui.package.installed":"Aktualnie zainstalowane:","ui.package.version":"Wersja {version}","ui.package.additionalDownloads":"{count} pobranie | {count} pobrań","ui.package.additionalStars":"{count} gwiazdka | {count} gwiazdek","ui.package.editConstraint":"Edytuj","ui.package.uploadConstraint":"To ograniczenie jest narzucone przez przesłany pakiet.","ui.package.updateButton":"Aktualizuj","ui.package.removeButton":"Usuń","ui.package.installButton":"Dodaj pakiet","ui.package.installButtonShort":"Dodaj","ui.package.detailsButton":"Szczegóły","ui.package.latestConstraint":"najnowsza wersja","ui.package.update":"Dostępna aktualizacja","ui.package.updateLatest":"najnowsza wersja","ui.package.updateAvailable":"dostępna {version}","ui.package.updateUnknown":"nieznana wersja","ui.package.updateConstraint":"Dostępna jest nowsza wersja poza zadanym ograniczeniem.","ui.package.incompatible":"{package} nie jest kompatybilny z Contao {constraint}.","ui.package.incompatibleWarning":"{package} nie działa z Contao {constraint} w żadnym stabilnym wydaniu. Czy chcesz dodać pakiet i ustawić ograniczenie wersji, aby spróbować zainstalować gałąź rozwojową?","ui.package.incompatibleConstraint":"Pakiet nie udostępnia stabilnej wersji dla Contao {constraint}. Ustaw ograniczenie wersji, aby spróbować zainstalować gałąź rozwojową.","ui.package.incompatibleButton":"Zainstaluj","ui.cloudStatus.headline":"Chmura Composer Resolver","ui.cloudStatus.version":"Wersja","ui.cloudStatus.waitingTime":"Czas oczekiwania","ui.cloudStatus.jobs":"Bieżące zadania","ui.cloudStatus.workers":"Procesy robocze","ui.cloudStatus.approx":"ok. {minutes} min","ui.cloudStatus.none":"brak","ui.cloudStatus.short":"ok. {minutes} min","ui.cloudStatus.long":"ok. {minutes} min {seconds} s","ui.cloudStatus.error":"Nie można pobrać statusu Composer Resolver Cloud. Usługa może być w konserwacji albo mieć problemy.","ui.cloudStatus.button":"Status chmury","ui.cloudStatus.refresh":"Odśwież status chmury","ui.log-viewer.loading":"Ładowanie …","ui.log-viewer.empty":"Na serwerze brak plików logów.","ui.log-viewer.reload":"Przeładuj","ui.log-viewer.file":"Plik logu","ui.log-viewer.channel":"Kanał","ui.log-viewer.channelTitle":"Kanał, do którego zapisano ten komunikat.","ui.log-viewer.level":"Poziom","ui.log-viewer.levelTitle":"Poziom ważności komunikatu w logu.","ui.log-viewer.timeHeader":"Czas","ui.log-viewer.messageHeader":"Komunikat","ui.log-viewer.showContext":"Pokaż kontekst","ui.log-viewer.hideContext":"Ukryj kontekst","ui.log-viewer.showExtra":"Pokaż szczegóły","ui.log-viewer.hideExtra":"Ukryj szczegóły","ui.log-viewer.more":"Wczytaj więcej …","ui.log-viewer.download":"Pobierz","ui.log-viewer.downloadTitle":"Pobierz plik \\"{file}\\"","ui.log-viewer.prodEnvironment":"Środowisko produkcyjne","ui.log-viewer.devEnvironment":"Środowisko deweloperskie (tryb debugowania)","ui.user-manager.loading":"Ładowanie użytkowników …","ui.user-manager.changePassword":"Zmień hasło","ui.user-manager.setupTotp":"Skonfiguruj uwierzytelnianie dwuskładnikowe","ui.user-manager.disableTotp":"Wyłącz uwierzytelnianie dwuskładnikowe","ui.user-manager.invite":"Zaproś użytkownika","ui.user-manager.delete":"Usuń","ui.user-manager.deleteConfirm":"Czy na pewno chcesz usunąć użytkownika \\"{username}\\"?","ui.user-manager.deleted":"Użytkownik {username} został usunięty.","ui.user-manager.passwordHeadline":"Zmień hasło","ui.user-manager.passwordText":"Aby zmienić hasło, wprowadź aktualne oraz nowe hasło w odpowiednich polach.","ui.user-manager.currentPassword":"Aktualne hasło","ui.user-manager.newPassword":"Nowe hasło","ui.user-manager.passwordPlaceholder":"min. 8 znaków","ui.user-manager.submitPassword":"Zatwierdź","ui.user-manager.passwordChanged":"Hasło zostało zmienione.","ui.user-manager.passwordError":"Podane hasło jest nieprawidłowe.","ui.user-manager.inviteHeadline":"Zaproś użytkownika","ui.user-manager.inviteText":"Jeśli potrzebujesz wielu logowań do Contao Managera, możesz tutaj utworzyć link zaproszenia. Udostępnij go innej osobie lub użyj na innym urządzeniu, aby utworzyć konto z podanymi uprawnieniami.","ui.user-manager.inviteSuccess1":"Utworzono nowy link zaproszenia. Poniższy adres służy do założenia nowego konta w tym Contao Managerze. Zaproszenie wygasa {expires} (za tydzień).","ui.user-manager.inviteSuccess2":"Skopiuj link do schowka. Zadziała tylko raz i nie będzie widoczny po zamknięciu okna.","ui.user-manager.createInvitation":"Utwórz link zaproszenia","ui.user-manager.clipboard":"Skopiuj do schowka","ui.user-manager.permissions":"Więcej o uprawnieniach","ui.user-manager.cancel":"Anuluj","ui.user-manager.close":"Zamknij","ui.user-manager.you":"Ty","ui.user-manager.2fa":"2FA","ui.user-manager.2faEnabled":"To konto jest zabezpieczone uwierzytelnianiem dwuskładnikowym.","ui.user-manager.2faDisabled":"To konto jest niezabezpieczone z powodu braku uwierzytelniania dwuskładnikowego.","ui.user-manager.passkey":"Klucz Passkey","ui.user-manager.passkeyTitle":"To konto jest chronione kluczem Passkey.","ui.totp.headline":"Uwierzytelnianie dwuskładnikowe","ui.totp.setupQr":"Zeskanuj kod QR aplikacją 2FA/TOTP.","ui.totp.setupCode":"Jeśli nie możesz zeskanować kodu QR, wprowadź zamiast niego ten klucz:","ui.totp.codeLabel":"Kod weryfikacyjny","ui.totp.codeDescription":"Podaj kod wygenerowany przez aplikację 2FA/TOTP.","ui.totp.disableText":"Wprowadź kod weryfikacyjny, aby wyłączyć uwierzytelnianie dwuskładnikowe.","ui.totp.invalid":"Kod weryfikacyjny jest nieprawidłowy.","ui.totp.enable":"Włącz","ui.totp.disable":"Wyłącz","ui.totp.cancel":"Anuluj","ui.totp.enabled":"Uwierzytelnianie dwuskładnikowe zostało włączone.","ui.totp.disabled":"Uwierzytelnianie dwuskładnikowe zostało wyłączone.","ui.totp.setup":"Skonfiguruj uwierzytelnianie dwuskładnikowe","ui.totp.skip":"Pomiń uwierzytelnianie dwuskładnikowe"}')}}]);<svg fill="#fff" height="24" width="24" xmlns="http://www.w3.org/2000/svg"><path d="M0 0h24v24H0z" fill="none"/><path d="M12 4.5C7 4.5 2.73 7.61 1 12c1.73 4.39 6 7.5 11 7.5s9.27-3.11 11-7.5c-1.73-4.39-6-7.5-11-7.5zM12 17c-2.76 0-5-2.24-5-5s2.24-5 5-5 5 2.24 5 5-2.24 5-5 5zm0-8c-1.66 0-3 1.34-3 3s1.34 3 3 3 3-1.34 3-3-1.34-3-3-3z"/></svg><svg xmlns="http://www.w3.org/2000/svg" height="24" width="24" fill="#737373"><path fill="none" d="M0 0h24v24H0z"/><path d="M12 5.99 19.53 19H4.47L12 5.99M12 2 1 21h22L12 2z"/><path d="M13 16h-2v2h2zm0-6h-2v5h2z"/></svg><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 178.6 155.9"><path d="M11.8-.1C5.3-.1 0 5.2 0 11.7v132.4c0 6.5 5.3 11.8 11.8 11.8h155c6.5 0 11.8-5.2 11.8-11.7V11.7c0-6.5-5.3-11.8-11.8-11.8h-155z" style="fill:#fff"/><path d="M15.9 94.6c5 23.3 9.2 45.4 23.7 61.4H11.8C5.3 156 0 150.8 0 144.3V11.7C0 5.2 5.3-.1 11.8-.1h20.1C27 4.4 22.7 9.5 19.1 15.1 3.2 39.4 9.8 65.9 15.9 94.6zM166.8-.1h-31.5c7.5 7.5 13.8 17.1 18.5 29.1l-47.9 10.1C100.6 29.1 92.6 20.8 77 24c-8.6 1.8-14.3 6.6-16.9 11.9-3.1 6.5-4.6 13.8 2.8 48.6s11.8 40.8 17.3 45.5c4.5 3.8 11.7 5.9 20.3 4.1 15.6-3.3 19.5-14.2 20.1-25.5l47.9-10.1c1.1 24.8-6.5 44-20.1 57.3h18.2c6.5 0 11.8-5.2 11.8-11.7V11.7c.2-6.5-5.1-11.8-11.6-11.8z" style="fill:#f47c00"/></svg><svg fill="#FFF" height="24" width="24" xmlns="http://www.w3.org/2000/svg"><path d="M0 0h24v24H0z" fill="none"/><path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm5 11h-4v4h-2v-4H7v-2h4V7h2v4h4v2z"/></svg><svg fill="#535353" height="24" width="24" xmlns="http://www.w3.org/2000/svg"><path d="M12 .25a.75.75 0 0 1 .673.418l3.058 6.197 6.839.994a.75.75 0 0 1 .415 1.279l-4.948 4.823 1.168 6.811a.75.75 0 0 1-1.088.791L12 18.347l-6.117 3.216a.75.75 0 0 1-1.088-.79l1.168-6.812-4.948-4.823a.75.75 0 0 1 .416-1.28l6.838-.993L11.328.668A.75.75 0 0 1 12 .25zm0 2.445L9.44 7.882a.75.75 0 0 1-.565.41l-5.725.832 4.143 4.038a.75.75 0 0 1 .215.664l-.978 5.702 5.121-2.692a.75.75 0 0 1 .698 0l5.12 2.692-.977-5.702a.75.75 0 0 1 .215-.664l4.143-4.038-5.725-.831a.75.75 0 0 1-.565-.41L12 2.694z"/></svg><svg fill="#FFF" height="24" width="24" xmlns="http://www.w3.org/2000/svg"><path d="M-74 29h48v48h-48V29z" fill="none"/><path d="M22 9V7h-2V5c0-1.1-.9-2-2-2H4c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2v-2h2v-2h-2v-2h2v-2h-2V9h2zm-4 10H4V5h14v14zM6 13h5v4H6zm6-6h4v3h-4zM6 7h5v5H6zm6 4h4v6h-4z"/><path d="M0 0h24v24H0zm0 0h24v24H0z" fill="none"/></svg><svg xmlns="http://www.w3.org/2000/svg" height="24" width="24" fill="#fff"><path fill="none" d="M0 0h24v24H0z"/><path d="M3 10h11v2H3zm0-4h11v2H3zm0 8h7v2H3zm17.59-2.07-4.25 4.24-2.12-2.12-1.41 1.41L16.34 19 22 13.34z"/></svg><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 134.3 162.8"><path d="M121.9 56.1c0 31-25.1 56.1-56.1 56.1S9.7 87.1 9.7 56.1 34.8 0 65.8 0c31 .1 56.1 25.2 56.1 56.1z"/><path d="M90.3 20.8c-5.7.2-10.7 3.3-14.4 7.7-4.1 4.8-6.8 10.4-8.8 16.2-3.5-2.9-6.2-6.6-11.9-8.2-4.4-1.3-8.9-.7-13.1 2.4-2 1.5-3.4 3.7-4 5.9-1.7 5.5 1.8 10.4 3.4 12.2l3.4 3.7c.7.7 2.4 2.6 1.6 5.3-.9 2.9-4.5 4.8-8.1 3.7-1.6-.5-4-1.7-3.4-3.4.2-.7.7-1.2 1-1.8.2-.5.4-.9.4-1.1.7-2.2-.2-5-2.6-5.7-2.2-.7-4.4-.1-5.3 2.7-1 3.2.5 8.9 8.7 11.4 9.5 2.9 17.6-2.3 18.7-9 .7-4.2-1.2-7.4-4.7-11.4L48.4 48c-1.7-1.7-2.3-4.7-.5-6.9 1.5-1.9 3.7-2.7 7.2-1.8 5.2 1.4 7.4 5 11.3 7.9-1.6 5.2-2.6 10.4-3.5 15.1l-.6 3.5C59.5 80 57.4 87.9 52 92.4c-1.1.8-2.7 1.9-5 2-1.2 0-1.6-.8-1.7-1.2 0-.9.7-1.3 1.2-1.7.7-.4 1.8-1.1 1.7-3.2-.1-2.5-2.1-4.6-5.1-4.5-2.2.1-5.6 2.2-5.5 6 .1 4 3.8 6.9 9.4 6.8 3-.1 9.6-1.3 16.2-9.1 7.6-8.9 9.8-19.2 11.4-26.7l1.8-9.9c1 .1 2.1.2 3.2.2 9.5.2 14.3-4.7 14.3-8.3 0-2.2-1.4-4.3-3.5-4.3-1.5 0-3.3 1-3.8 3.1-.4 2 3 3.8.3 5.6-1.9 1.2-5.4 2.1-10.2 1.4l.9-4.9c1.8-9.2 4-20.6 12.4-20.9.6 0 2.9 0 2.9 1.5 0 .5-.1.6-.7 1.8-.6.9-.8 1.6-.8 2.5.1 2.4 1.9 3.9 4.5 3.8 3.5-.1 4.5-3.5 4.4-5.2 0-4-4.3-6.6-10-6.4z" style="fill:#fff"/><path d="M86.6 135.6c5.7 0 9.5 4.1 9.5 9.8 0 5.3-3.9 9.8-9.5 9.8s-9.5-4.4-9.5-9.8c0-5.7 3.8-9.8 9.5-9.8zm0 16.7c4 0 5.8-3.7 5.8-7 0-3.5-2.2-7-5.8-7-3.7 0-5.8 3.4-5.8 7 0 3.4 1.8 7 5.8 7zm-10-15V136h-4.9v-1.8c0-2.5.4-4.4 3.3-4.4h.2c.8.1 1.5-.6 1.5-1.4l.1-1.1c-.7-.1-1.4-.2-2.3-.2-5.1 0-6.2 3-6.2 7.5v1.5h-4.4v1.4c.1.8.8 1.3 1.5 1.3h2.8v15.9h1.9c.8 0 1.4-.6 1.5-1.3v-14.5H75c1-.1 1.6-.8 1.6-1.6zM30.9 136c-.7 0-1.4.5-1.7 1.2l-4.7 14.2h-.1l-4.6-14.2c-.3-.7-1-1.2-1.7-1.2h-2.4l6.3 17.4c.2.6.7 1.6.7 2 0 .4-1 4.6-4.1 4.6h-.2c-.8 0-1.4.5-1.5 1.3l-.1 1.2c.6.1 1.2.3 2.3.3 4.5 0 5.9-4.1 7.2-7.7l6.9-19-2.3-.1zM9 139.8c-2.8-1.5-5.9-2.4-6-5.4 0-3.1 2.9-3.9 5.1-3.9 1 0 1.7.1 2.5.3.8.1 1.4-.6 1.5-1.3l.1-1.1c-1.4-.3-2.8-.5-4.3-.5-4.8 0-8.3 2.4-8.3 7 0 4 2.7 5.6 5.6 7 2.9 1.4 6 2.5 6 5.8 0 3.5-3.3 4.7-5.6 4.7-1.3 0-2.8-.3-4-.7-.8-.1-1.4.6-1.5 1.5l-.1.8c1.7.5 3.4 1 5.2 1 5.3 0 9.5-2.2 9.5-7.7 0-4.2-2.8-6-5.7-7.5zm52 14.8c.7 0 1.4-.5 1.5-1.2v-10.7c0-4.1-1.7-7.1-6.5-7.1-1.7 0-4.5 1-5.8 3.6-1-2.5-3.1-3.6-5.3-3.6-2.7 0-4.6 1-5.9 3.1v-1.2c0-.9-.7-1.5-1.6-1.5h-1.6v18.6h1.9c.9 0 1.6-.7 1.6-1.6v-7.8c0-3.5 1.4-6.9 4.9-6.9 2.8 0 3.3 2.9 3.3 5.2v11.1h1.9c.8 0 1.5-.6 1.5-1.4v-8c0-3.5 1.4-6.9 4.9-6.9 2.8 0 3.3 2.9 3.3 5.2v11.1H61zm53.1 0c.8 0 1.5-.7 1.6-1.5v-9.6c0-5-2.2-8-7-8-2.6 0-5.1 1.3-6.1 3.4h-.1v-1.4c0-.9-.7-1.6-1.6-1.6h-1.8v18.6h1.9c.8 0 1.5-.6 1.5-1.4V146c0-4.5 1.8-7.7 5.7-7.7 3 .2 3.9 2.3 3.9 6.6v9.6l2 .1zm18.5-18.6c-.7 0-1.4.5-1.7 1.2l-4.7 14.2h-.2l-4.6-14.2c-.3-.7-1-1.2-1.7-1.2h-2.4l6.3 17.4c.2.6.7 1.6.7 2 0 .4-1 4.6-4.1 4.6h-.2c-.8 0-1.4.5-1.5 1.3l-.1 1.2c.6.1 1.2.3 2.3.3 4.5 0 5.9-4.1 7.2-7.7l6.9-19-2.2-.1z"/></svg><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="#fff"><path d="M0 0h24v24H0z" fill="none"/><path d="M19 19H5V5h7V3H5a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14c1.1 0 2-.9 2-2v-7h-2v7zM14 3v2h3.59l-9.83 9.83 1.41 1.41L19 6.41V10h2V3h-7z"/></svg><svg xmlns="http://www.w3.org/2000/svg" height="24" width="24" fill="#fff"><path fill="none" d="M0 0h24v24H0z"/><path d="M6.83 4H20a2 2 0 0 1 2 2v12c0 .34-.09.66-.23.94L20 17.17V8h-9.17l-4-4zm13.66 19.31L17.17 20H4a2 2 0 0 1-2-2V6c0-.34.08-.66.23-.94L.69 3.51 2.1 2.1l19.8 19.8-1.41 1.41zM15.17 18l-10-10H4v10h11.17z"/></svg><svg xmlns="http://www.w3.org/2000/svg" height="24" width="24" fill="#fff"><path fill="none" d="M0 0h24v24H0z"/><path d="M5 20h14v-2H5v2zM19 9h-4V3H9v6H5l7 7 7-7z"/></svg><svg xmlns="http://www.w3.org/2000/svg" height="24" width="24" fill="#fff"><path fill="none" d="M0 0h24v24H0z"/><path d="M21.19 21.19 2.81 2.81 1.39 4.22l2.27 2.27A9.91 9.91 0 0 0 2 12c0 5.52 4.48 10 10 10 2.04 0 3.93-.61 5.51-1.66l2.27 2.27 1.41-1.42zm-10.6-4.59-4.24-4.24 1.41-1.41 2.83 2.83.18-.18 1.41 1.41-1.59 1.59zm3-5.84-7.1-7.1A9.91 9.91 0 0 1 12 2c5.52 0 10 4.48 10 10 0 2.04-.61 3.93-1.66 5.51L15 12.17l2.65-2.65-1.41-1.41-2.65 2.65z"/></svg><svg xmlns="http://www.w3.org/2000/svg" height="24" width="24" fill="#fff"><path d="M0 0h24v24H0z" fill="none"/><path d="M10 4H4c-1.1 0-1.99.9-1.99 2L2 18c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V8c0-1.1-.9-2-2-2h-8l-2-2z"/></svg><svg xmlns="http://www.w3.org/2000/svg" width="168" height="24"><g fill="none"><path fill="#5468FF" d="M78.988.938h16.594a2.968 2.968 0 0 1 2.966 2.966V20.5a2.967 2.967 0 0 1-2.966 2.964H78.988a2.967 2.967 0 0 1-2.966-2.964V3.897A2.961 2.961 0 0 1 78.988.938zm41.937 17.866c-4.386.02-4.386-3.54-4.386-4.106l-.007-13.336 2.675-.424v13.254c0 .322 0 2.358 1.718 2.364v2.248zm-10.846-2.18c.821 0 1.43-.047 1.855-.129v-2.719a6.334 6.334 0 0 0-1.574-.199 5.7 5.7 0 0 0-.897.069 2.699 2.699 0 0 0-.814.24c-.24.116-.439.28-.582.491-.15.212-.219.335-.219.656 0 .628.219.991.616 1.23s.938.362 1.615.362zm-.233-9.7c.883 0 1.629.109 2.231.328.602.218 1.088.525 1.444.915.363.396.609.922.76 1.483.157.56.232 1.175.232 1.85v6.874a32.5 32.5 0 0 1-1.868.314c-.834.123-1.772.185-2.813.185-.69 0-1.327-.069-1.895-.198a4.001 4.001 0 0 1-1.471-.636 3.085 3.085 0 0 1-.951-1.134c-.226-.465-.343-1.12-.343-1.803 0-.656.13-1.073.384-1.525a3.24 3.24 0 0 1 1.047-1.106c.445-.287.95-.492 1.532-.615a8.8 8.8 0 0 1 1.82-.185 8.404 8.404 0 0 1 1.972.24v-.438c0-.307-.035-.6-.11-.874a1.88 1.88 0 0 0-.384-.73 1.784 1.784 0 0 0-.724-.493 3.164 3.164 0 0 0-1.143-.205c-.616 0-1.177.075-1.69.164a7.735 7.735 0 0 0-1.26.307l-.321-2.192c.335-.117.834-.233 1.478-.349a10.98 10.98 0 0 1 2.073-.178zm52.842 9.626c.822 0 1.43-.048 1.854-.13V13.7a6.347 6.347 0 0 0-1.574-.199c-.294 0-.595.021-.896.069a2.7 2.7 0 0 0-.814.24 1.46 1.46 0 0 0-.582.491c-.15.212-.218.335-.218.656 0 .628.218.991.615 1.23.404.245.938.362 1.615.362zm-.226-9.694c.883 0 1.629.108 2.231.327.602.219 1.088.526 1.444.915.355.39.609.923.759 1.483a6.8 6.8 0 0 1 .233 1.852v6.873c-.41.088-1.034.19-1.868.314-.834.123-1.772.184-2.813.184-.69 0-1.327-.068-1.895-.198a4.001 4.001 0 0 1-1.471-.635 3.085 3.085 0 0 1-.951-1.134c-.226-.465-.343-1.12-.343-1.804 0-.656.13-1.073.384-1.524.26-.45.608-.82 1.047-1.107.445-.286.95-.491 1.532-.614a8.803 8.803 0 0 1 2.751-.13c.329.034.671.096 1.04.185v-.437a3.3 3.3 0 0 0-.109-.875 1.873 1.873 0 0 0-.384-.731 1.784 1.784 0 0 0-.724-.492 3.165 3.165 0 0 0-1.143-.205c-.616 0-1.177.075-1.69.164a7.75 7.75 0 0 0-1.26.307l-.321-2.193c.335-.116.834-.232 1.478-.348a11.633 11.633 0 0 1 2.073-.177zm-8.034-1.271a1.626 1.626 0 0 1-1.628-1.62c0-.895.725-1.62 1.628-1.62.904 0 1.63.725 1.63 1.62 0 .895-.733 1.62-1.63 1.62zm1.348 13.22h-2.689V7.27l2.69-.423v11.956zm-4.714 0c-4.386.02-4.386-3.54-4.386-4.107l-.008-13.336 2.676-.424v13.254c0 .322 0 2.358 1.718 2.364v2.248zm-8.698-5.903c0-1.156-.253-2.119-.746-2.788-.493-.677-1.183-1.01-2.067-1.01-.882 0-1.574.333-2.065 1.01-.493.676-.733 1.632-.733 2.788 0 1.168.246 1.953.74 2.63.492.683 1.183 1.018 2.066 1.018.882 0 1.574-.342 2.067-1.019.492-.683.738-1.46.738-2.63zm2.737-.007c0 .902-.13 1.584-.397 2.33a5.52 5.52 0 0 1-1.128 1.906 4.986 4.986 0 0 1-1.752 1.223c-.685.286-1.739.45-2.265.45-.528-.006-1.574-.157-2.252-.45a5.096 5.096 0 0 1-1.744-1.223c-.487-.527-.863-1.162-1.137-1.906a6.345 6.345 0 0 1-.41-2.33c0-.902.123-1.77.397-2.508a5.554 5.554 0 0 1 1.15-1.892 5.133 5.133 0 0 1 1.75-1.216c.679-.287 1.425-.423 2.232-.423.808 0 1.553.142 2.237.423a4.88 4.88 0 0 1 1.753 1.216 5.644 5.644 0 0 1 1.135 1.892c.287.738.431 1.606.431 2.508zm-20.138 0c0 1.12.246 2.363.738 2.882.493.52 1.13.78 1.91.78.424 0 .828-.062 1.204-.178.377-.116.677-.253.917-.417V9.33a10.476 10.476 0 0 0-1.766-.226c-.971-.028-1.71.37-2.23 1.004-.513.636-.773 1.75-.773 2.788zm7.438 5.274c0 1.824-.466 3.156-1.404 4.004-.936.846-2.367 1.27-4.296 1.27-.705 0-2.17-.137-3.34-.396l.431-2.118c.98.205 2.272.26 2.95.26 1.074 0 1.84-.219 2.299-.656.459-.437.684-1.086.684-1.948v-.437a8.07 8.07 0 0 1-1.047.397c-.43.13-.93.198-1.492.198-.739 0-1.41-.116-2.018-.349a4.206 4.206 0 0 1-1.567-1.025c-.431-.45-.774-1.017-1.013-1.694-.24-.677-.363-1.885-.363-2.773 0-.834.13-1.88.384-2.577.26-.696.629-1.298 1.129-1.796.493-.498 1.095-.881 1.8-1.162a6.605 6.605 0 0 1 2.428-.457c.87 0 1.67.109 2.45.24.78.129 1.444.265 1.985.415V18.17z"/><path fill="#5D6494" d="M6.972 6.677v1.627c-.712-.446-1.52-.67-2.425-.67-.585 0-1.045.13-1.38.391a1.24 1.24 0 0 0-.502 1.03c0 .425.164.765.494 1.02.33.256.835.532 1.516.83.447.192.795.356 1.045.495.25.138.537.332.862.582.324.25.563.548.718.894.154.345.23.741.23 1.188 0 .947-.334 1.691-1.004 2.234-.67.542-1.537.814-2.601.814-1.18 0-2.16-.229-2.936-.686v-1.708c.84.628 1.814.942 2.92.942.585 0 1.048-.136 1.388-.407.34-.271.51-.646.51-1.125 0-.287-.1-.55-.302-.79-.203-.24-.42-.42-.655-.542-.234-.123-.585-.29-1.053-.503a61.27 61.27 0 0 1-.582-.271 13.67 13.67 0 0 1-.55-.287 4.275 4.275 0 0 1-.567-.351 6.92 6.92 0 0 1-.455-.4c-.18-.17-.31-.34-.39-.51-.08-.17-.155-.37-.224-.598a2.553 2.553 0 0 1-.104-.742c0-.915.333-1.638.998-2.17.664-.532 1.523-.798 2.576-.798.968 0 1.793.17 2.473.51zm7.468 5.696v-.287c-.022-.607-.187-1.088-.495-1.444-.309-.357-.75-.535-1.324-.535-.532 0-.99.194-1.373.583-.382.388-.622.949-.717 1.683h3.909zm1.005 2.792v1.404c-.596.34-1.383.51-2.362.51-1.255 0-2.255-.377-3-1.132-.744-.755-1.116-1.744-1.116-2.968 0-1.297.34-2.316 1.021-3.055.68-.74 1.548-1.11 2.6-1.11 1.033 0 1.852.323 2.458.966.606.644.91 1.572.91 2.784 0 .33-.033.676-.096 1.038h-5.314c.107.702.405 1.239.894 1.611.49.372 1.106.558 1.85.558.862 0 1.58-.202 2.155-.606zm6.605-1.77h-1.212c-.596 0-1.045.116-1.349.35-.303.234-.454.532-.454.894 0 .372.117.664.35.877.235.213.575.32 1.022.32.51 0 .912-.142 1.204-.424.293-.281.44-.651.44-1.108v-.91zm-4.068-2.554V9.325c.627-.361 1.457-.542 2.489-.542 2.116 0 3.175 1.026 3.175 3.08V17h-1.548v-.957c-.415.68-1.143 1.02-2.186 1.02-.766 0-1.38-.22-1.843-.661-.462-.442-.694-1.003-.694-1.684 0-.776.293-1.38.878-1.81.585-.431 1.404-.647 2.457-.647h1.34V11.8c0-.554-.133-.971-.399-1.253-.266-.282-.707-.423-1.324-.423a4.07 4.07 0 0 0-2.345.718zm9.333-1.93v1.42c.394-1 1.101-1.5 2.123-1.5.148 0 .313.016.494.048v1.531a1.885 1.885 0 0 0-.75-.143c-.542 0-.989.24-1.34.718-.351.479-.527 1.048-.527 1.707V17h-1.563V8.91h1.563zm5.01 4.084c.022.82.272 1.492.75 2.019.479.526 1.15.79 2.01.79.639 0 1.235-.176 1.788-.527v1.404c-.521.319-1.186.479-1.995.479-1.265 0-2.276-.4-3.031-1.197-.755-.798-1.133-1.792-1.133-2.984 0-1.16.38-2.151 1.14-2.975.761-.825 1.79-1.237 3.088-1.237.702 0 1.346.149 1.93.447v1.436a3.242 3.242 0 0 0-1.77-.495c-.84 0-1.513.266-2.019.798-.505.532-.758 1.213-.758 2.042zM40.24 5.72v4.579c.458-1 1.293-1.5 2.505-1.5.787 0 1.42.245 1.899.734.479.49.718 1.17.718 2.042V17h-1.564v-5.106c0-.553-.14-.98-.422-1.284-.282-.303-.652-.455-1.11-.455-.531 0-1.002.202-1.411.606-.41.405-.615 1.022-.615 1.851V17h-1.563V5.72h1.563zm14.966 10.02c.596 0 1.096-.253 1.5-.758.404-.506.606-1.157.606-1.955 0-.915-.202-1.62-.606-2.114-.404-.495-.92-.742-1.548-.742-.553 0-1.05.224-1.491.67-.442.447-.662 1.133-.662 2.058 0 .958.212 1.67.638 2.138.425.469.946.703 1.563.703zM53.004 5.72v4.42c.574-.894 1.388-1.341 2.44-1.341 1.022 0 1.857.383 2.506 1.149.649.766.973 1.781.973 3.047 0 1.138-.309 2.109-.925 2.912-.617.803-1.463 1.205-2.537 1.205-1.075 0-1.894-.447-2.457-1.34V17h-1.58V5.72h1.58zm9.908 11.104-3.223-7.913h1.739l1.005 2.632 1.26 3.415c.096-.32.48-1.458 1.15-3.415l.909-2.632h1.66l-2.92 7.866c-.777 2.074-1.963 3.11-3.559 3.11a2.92 2.92 0 0 1-.734-.079v-1.34c.17.042.351.064.543.064 1.032 0 1.755-.57 2.17-1.708z"/><path fill="#FFF" d="M89.632 5.967v-.772a.978.978 0 0 0-.978-.977h-2.28a.978.978 0 0 0-.978.977v.793c0 .088.082.15.171.13a7.127 7.127 0 0 1 1.984-.28c.65 0 1.295.088 1.917.259.082.02.164-.04.164-.13m-6.248 1.01-.39-.389a.977.977 0 0 0-1.382 0l-.465.465a.973.973 0 0 0 0 1.38l.383.383c.062.061.15.047.205-.014.226-.307.472-.601.746-.874.281-.28.568-.526.883-.751.068-.042.075-.137.02-.2m4.16 2.453v3.341c0 .096.104.165.192.117l2.97-1.537c.068-.034.089-.117.055-.184a3.695 3.695 0 0 0-3.08-1.866c-.068 0-.136.054-.136.13m0 8.048a4.489 4.489 0 0 1-4.49-4.482 4.488 4.488 0 0 1 4.49-4.482 4.488 4.488 0 0 1 4.489 4.482 4.484 4.484 0 0 1-4.49 4.482m0-10.85a6.363 6.363 0 1 0 0 12.729 6.37 6.37 0 0 0 6.372-6.368 6.358 6.358 0 0 0-6.371-6.36"/></g></svg><svg fill="#FFF" height="24" width="24" xmlns="http://www.w3.org/2000/svg"><path d="M0 0h24v24H0z" fill="none"/><path d="m17.73 12.02 3.98-3.98a.996.996 0 0 0 0-1.41l-4.34-4.34a.996.996 0 0 0-1.41 0l-3.98 3.98L8 2.29a1.001 1.001 0 0 0-1.41 0L2.25 6.63a.996.996 0 0 0 0 1.41l3.98 3.98L2.25 16a.996.996 0 0 0 0 1.41l4.34 4.34c.39.39 1.02.39 1.41 0l3.98-3.98 3.98 3.98c.2.2.45.29.71.29.26 0 .51-.1.71-.29l4.34-4.34a.996.996 0 0 0 0-1.41l-3.99-3.98zM12 9c.55 0 1 .45 1 1s-.45 1-1 1-1-.45-1-1 .45-1 1-1zm-4.71 1.96L3.66 7.34l3.63-3.63 3.62 3.62-3.62 3.63zM10 13c-.55 0-1-.45-1-1s.45-1 1-1 1 .45 1 1-.45 1-1 1zm2 2c-.55 0-1-.45-1-1s.45-1 1-1 1 .45 1 1-.45 1-1 1zm2-4c.55 0 1 .45 1 1s-.45 1-1 1-1-.45-1-1 .45-1 1-1zm2.66 9.34-3.63-3.62 3.63-3.63 3.62 3.62-3.62 3.63z"/></svg><svg height="24" width="24" fill="#fff" xmlns="http://www.w3.org/2000/svg"><path d="M15.5 14h-.79l-.28-.27A6.471 6.471 0 0 0 16 9.5 6.5 6.5 0 1 0 9.5 16c1.61 0 3.09-.59 4.23-1.57l.27.28v.79l5 4.99L20.49 19l-4.99-5zm-6 0C7.01 14 5 11.99 5 9.5S7.01 5 9.5 5 14 7.01 14 9.5 11.99 14 9.5 14z"/><path d="M0 0h24v24H0z" fill="none"/></svg><svg xmlns="http://www.w3.org/2000/svg" height="24" width="24" fill="#fff"><path fill="none" d="M0 0h24v24H0z"/><path d="M21 10h-8.35A5.99 5.99 0 0 0 7 6c-3.31 0-6 2.69-6 6s2.69 6 6 6a5.99 5.99 0 0 0 5.65-4H13l2 2 2-2 2 2 4-4.04L21 10zM7 15c-1.65 0-3-1.35-3-3s1.35-3 3-3 3 1.35 3 3-1.35 3-3 3z"/></svg><svg fill="none" height="24" width="24" stroke="#535353" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><path d="M22.61 16.95A5 5 0 0 0 18 10h-1.26a8 8 0 0 0-7.05-6M5 5a8 8 0 0 0 4 15h9a5 5 0 0 0 1.7-.3M1 1l22 22"/></svg><svg xmlns="http://www.w3.org/2000/svg" height="24" width="24" fill="#fff"><path d="M0 0h24v24H0z" fill="none"/><path d="M19.35 10.04A7.49 7.49 0 0 0 12 4C9.11 4 6.6 5.64 5.35 8.04A5.994 5.994 0 0 0 0 14c0 3.31 2.69 6 6 6h13c2.76 0 5-2.24 5-5 0-2.64-2.05-4.78-4.65-4.96zM17 13l-5 5-5-5h3V9h4v4h3z"/></svg><svg height="24" width="24" fill="#737373" xmlns="http://www.w3.org/2000/svg"><path d="M12 12c2.21 0 4-1.79 4-4s-1.79-4-4-4-4 1.79-4 4 1.79 4 4 4zm0 2c-2.67 0-8 1.34-8 4v2h16v-2c0-2.66-5.33-4-8-4z"/><path d="M0 0h24v24H0z" fill="none"/></svg><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="#737373"><path d="M0 0h24v24H0z" fill="none"/><path d="M19 3H5a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2V5a2 2 0 0 0-2-2zm-9 14-5-5 1.41-1.41L10 14.17l7.59-7.59L19 8l-9 9z"/></svg><svg height="24" width="24" fill="#fff" xmlns="http://www.w3.org/2000/svg"><path d="M0 0h24v24H0z" fill="none"/><path d="M18 8h-1V6c0-2.76-2.24-5-5-5S7 3.24 7 6v2H6c-1.1 0-2 .9-2 2v10c0 1.1.9 2 2 2h12c1.1 0 2-.9 2-2V10c0-1.1-.9-2-2-2zm-6 9c-1.1 0-2-.9-2-2s.9-2 2-2 2 .9 2 2-.9 2-2 2zm3.1-9H8.9V6c0-1.71 1.39-3.1 3.1-3.1 1.71 0 3.1 1.39 3.1 3.1v2z"/></svg><svg fill="#fff" height="24" width="24" xmlns="http://www.w3.org/2000/svg"><path d="M0 0h24v24H0z" fill="none"/><path d="M9 16.17 4.83 12l-1.42 1.41L9 19 21 7l-1.41-1.41z"/></svg><svg height="24" width="24" fill="#fff" xmlns="http://www.w3.org/2000/svg"><path d="M12 12c2.21 0 4-1.79 4-4s-1.79-4-4-4-4 1.79-4 4 1.79 4 4 4zm0 2c-2.67 0-8 1.34-8 4v2h16v-2c0-2.66-5.33-4-8-4z"/><path d="M0 0h24v24H0z" fill="none"/></svg><svg height="24" width="24" fill="#737373" xmlns="http://www.w3.org/2000/svg"><path d="M0 0h24v24H0z" fill="none"/><path d="M19.35 10.04A7.49 7.49 0 0 0 12 4c-1.48 0-2.85.43-4.01 1.17l1.46 1.46a5.497 5.497 0 0 1 8.05 4.87v.5H19c1.66 0 3 1.34 3 3 0 1.13-.64 2.11-1.56 2.62l1.45 1.45C23.16 18.16 24 16.68 24 15c0-2.64-2.05-4.78-4.65-4.96zM3 5.27l2.75 2.74C2.56 8.15 0 10.77 0 14c0 3.31 2.69 6 6 6h11.73l2 2L21 20.73 4.27 4 3 5.27zM7.73 10l8 8H6c-2.21 0-4-1.79-4-4s1.79-4 4-4h1.73z"/></svg><svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="none" stroke="#fff" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" viewBox="0 0 24 24"><path d="M11.5 15H7a4 4 0 0 0-4 4v2"/><circle cx="9.375" cy="7" r="4"/><path stroke-width="1.5" d="M16.836 21.022a1.1 1.1 0 0 0 .323.779l.846.846a.55.55 0 0 0 .779 0l1.168-1.169a.55.55 0 0 0 0-.779l-.39-.39a.55.55 0 0 1 0-.779l.39-.389a.55.55 0 0 0 0-.78l-.39-.389a.55.55 0 0 1 0-.779l.068-.067a1.1 1.1 0 0 0 .322-.779v-.634a3.58 3.58 0 1 0-3.116 0z"/><circle cx="18.362" cy="11.575" r=".275"/></svg><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 134.3 162.8"><path d="M121.9 56.1c0 31-25.1 56.1-56.1 56.1S9.7 87.1 9.7 56.1 34.8 0 65.8 0c31 .1 56.1 25.2 56.1 56.1zm-35.3 79.5c5.7 0 9.5 4.1 9.5 9.8 0 5.3-3.9 9.8-9.5 9.8s-9.5-4.4-9.5-9.8c0-5.7 3.8-9.8 9.5-9.8zm0 16.7c4 0 5.8-3.7 5.8-7 0-3.5-2.2-7-5.8-7-3.7 0-5.8 3.4-5.8 7 0 3.4 1.8 7 5.8 7zm-10-15V136h-4.9v-1.8c0-2.5.4-4.4 3.3-4.4h.2c.8.1 1.5-.6 1.5-1.4l.1-1.1c-.7-.1-1.4-.2-2.3-.2-5.1 0-6.2 3-6.2 7.5v1.5h-4.4v1.4c.1.8.8 1.3 1.5 1.3h2.8v15.9h1.9c.8 0 1.4-.6 1.5-1.3v-14.5H75c1-.1 1.6-.8 1.6-1.6zM30.9 136c-.7 0-1.4.5-1.7 1.2l-4.7 14.2h-.1l-4.6-14.2c-.3-.7-1-1.2-1.7-1.2h-2.4l6.3 17.4c.2.6.7 1.6.7 2 0 .4-1 4.6-4.1 4.6h-.2c-.8 0-1.4.5-1.5 1.3l-.1 1.2c.6.1 1.2.3 2.3.3 4.5 0 5.9-4.1 7.2-7.7l6.9-19-2.3-.1zM9 139.8c-2.8-1.5-5.9-2.4-6-5.4 0-3.1 2.9-3.9 5.1-3.9 1 0 1.7.1 2.5.3.8.1 1.4-.6 1.5-1.3l.1-1.1c-1.4-.3-2.8-.5-4.3-.5-4.8 0-8.3 2.4-8.3 7 0 4 2.7 5.6 5.6 7 2.9 1.4 6 2.5 6 5.8 0 3.5-3.3 4.7-5.6 4.7-1.3 0-2.8-.3-4-.7-.8-.1-1.4.6-1.5 1.5l-.1.8c1.7.5 3.4 1 5.2 1 5.3 0 9.5-2.2 9.5-7.7 0-4.2-2.8-6-5.7-7.5zm52 14.8c.7 0 1.4-.5 1.5-1.2v-10.7c0-4.1-1.7-7.1-6.5-7.1-1.7 0-4.5 1-5.8 3.6-1-2.5-3.1-3.6-5.3-3.6-2.7 0-4.6 1-5.9 3.1v-1.2c0-.9-.7-1.5-1.6-1.5h-1.6v18.6h1.9c.9 0 1.6-.7 1.6-1.6v-7.8c0-3.5 1.4-6.9 4.9-6.9 2.8 0 3.3 2.9 3.3 5.2v11.1h1.9c.8 0 1.5-.6 1.5-1.4v-8c0-3.5 1.4-6.9 4.9-6.9 2.8 0 3.3 2.9 3.3 5.2v11.1H61zm53.1 0c.8 0 1.5-.7 1.6-1.5v-9.6c0-5-2.2-8-7-8-2.6 0-5.1 1.3-6.1 3.4h-.1v-1.4c0-.9-.7-1.6-1.6-1.6h-1.8v18.6h1.9c.8 0 1.5-.6 1.5-1.4V146c0-4.5 1.8-7.7 5.7-7.7 3 .2 3.9 2.3 3.9 6.6v9.6l2 .1zm18.5-18.6c-.7 0-1.4.5-1.7 1.2l-4.7 14.2h-.2l-4.6-14.2c-.3-.7-1-1.2-1.7-1.2h-2.4l6.3 17.4c.2.6.7 1.6.7 2 0 .4-1 4.6-4.1 4.6h-.2c-.8 0-1.4.5-1.5 1.3l-.1 1.2c.6.1 1.2.3 2.3.3 4.5 0 5.9-4.1 7.2-7.7l6.9-19-2.2-.1z" style="fill:#fff"/><path d="M90.3 20.8c-5.7.2-10.7 3.3-14.4 7.7-4.1 4.8-6.8 10.4-8.8 16.2-3.5-2.9-6.2-6.6-11.9-8.2-4.4-1.3-8.9-.7-13.1 2.4-2 1.5-3.4 3.7-4 5.9-1.7 5.5 1.8 10.4 3.4 12.2l3.4 3.7c.7.7 2.4 2.6 1.6 5.3-.9 2.9-4.5 4.8-8.1 3.7-1.6-.5-4-1.7-3.4-3.4.2-.7.7-1.2 1-1.8.2-.5.4-.9.4-1.1.7-2.2-.2-5-2.6-5.7-2.2-.7-4.4-.1-5.3 2.7-1 3.2.5 8.9 8.7 11.4 9.5 2.9 17.6-2.3 18.7-9 .7-4.2-1.2-7.4-4.7-11.4L48.4 48c-1.7-1.7-2.3-4.7-.5-6.9 1.5-1.9 3.7-2.7 7.2-1.8 5.2 1.4 7.4 5 11.3 7.9-1.6 5.2-2.6 10.4-3.5 15.1l-.6 3.5C59.5 80 57.4 87.9 52 92.4c-1.1.8-2.7 1.9-5 2-1.2 0-1.6-.8-1.7-1.2 0-.9.7-1.3 1.2-1.7.7-.4 1.8-1.1 1.7-3.2-.1-2.5-2.1-4.6-5.1-4.5-2.2.1-5.6 2.2-5.5 6 .1 4 3.8 6.9 9.4 6.8 3-.1 9.6-1.3 16.2-9.1 7.6-8.9 9.8-19.2 11.4-26.7l1.8-9.9c1 .1 2.1.2 3.2.2 9.5.2 14.3-4.7 14.3-8.3 0-2.2-1.4-4.3-3.5-4.3-1.5 0-3.3 1-3.8 3.1-.4 2 3 3.8.3 5.6-1.9 1.2-5.4 2.1-10.2 1.4l.9-4.9c1.8-9.2 4-20.6 12.4-20.9.6 0 2.9 0 2.9 1.5 0 .5-.1.6-.7 1.8-.6.9-.8 1.6-.8 2.5.1 2.4 1.9 3.9 4.5 3.8 3.5-.1 4.5-3.5 4.4-5.2 0-4-4.3-6.6-10-6.4z" style="fill:#212227"/></svg><svg fill="none" height="24" width="24" stroke="#ddd" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><path d="M22.61 16.95A5 5 0 0 0 18 10h-1.26a8 8 0 0 0-7.05-6M5 5a8 8 0 0 0 4 15h9a5 5 0 0 0 1.7-.3M1 1l22 22"/></svg><svg xmlns="http://www.w3.org/2000/svg" height="24" width="24" fill="#fff"><path d="M0 0h24v24H0z" fill="none"/><path d="M19.35 10.04A7.49 7.49 0 0 0 12 4c-1.48 0-2.85.43-4.01 1.17l1.46 1.46a5.497 5.497 0 0 1 8.05 4.87v.5H19c1.66 0 3 1.34 3 3 0 1.13-.64 2.11-1.56 2.62l1.45 1.45C23.16 18.16 24 16.68 24 15c0-2.64-2.05-4.78-4.65-4.96zM3 5.27l2.75 2.74C2.56 8.15 0 10.77 0 14c0 3.31 2.69 6 6 6h11.73l2 2L21 20.73 4.27 4 3 5.27zM7.73 10l8 8H6c-2.21 0-4-1.79-4-4s1.79-4 4-4h1.73z"/></svg><svg height="24" width="24" fill="#fff" xmlns="http://www.w3.org/2000/svg"><path d="M0 0h24v24H0z" fill="none"/><path d="M13 3h-2v10h2V3zm4.83 2.17-1.42 1.42A6.92 6.92 0 0 1 19 12c0 3.87-3.13 7-7 7A6.995 6.995 0 0 1 7.58 6.58L6.17 5.17A8.932 8.932 0 0 0 3 12a9 9 0 0 0 18 0c0-2.74-1.23-5.18-3.17-6.83z"/></svg><svg fill="#ddd" height="24" width="24" xmlns="http://www.w3.org/2000/svg"><path d="M4.97 11.03a.75.75 0 1 1 1.06-1.06L11 14.94V2.75a.75.75 0 0 1 1.5 0v12.19l4.97-4.97a.75.75 0 1 1 1.06 1.06l-6.25 6.25a.75.75 0 0 1-1.06 0l-6.25-6.25zm-.22 9.47a.75.75 0 0 0 0 1.5h14.5a.75.75 0 0 0 0-1.5H4.75z"/></svg><svg height="24" width="24" fill="#fff" xmlns="http://www.w3.org/2000/svg"><path d="M0 0h24v24H0V0z" fill="none"/><path d="M6 19c0 1.1.9 2 2 2h8c1.1 0 2-.9 2-2V7H6v12zm2.46-7.12 1.41-1.41L12 12.59l2.12-2.12 1.41 1.41L13.41 14l2.12 2.12-1.41 1.41L12 15.41l-2.12 2.12-1.41-1.41L10.59 14l-2.13-2.12zM15.5 4l-1-1h-5l-1 1H5v2h14V4z"/><path d="M0 0h24v24H0z" fill="none"/></svg><svg fill="#535353" height="24" width="24" xmlns="http://www.w3.org/2000/svg"><path d="M19 19H5V5h7V3H5a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14c1.1 0 2-.9 2-2v-7h-2v7zM14 3v2h3.59l-9.83 9.83 1.41 1.41L19 6.41V10h2V3h-7z"/></svg><svg xmlns="http://www.w3.org/2000/svg" height="24" width="24" fill="#fff"><path d="M0 0h24v24H0z" fill="none"/><path d="M19 2h-4.18C14.4.84 13.3 0 12 0c-1.3 0-2.4.84-2.82 2H5c-1.1 0-2 .9-2 2v16c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V4c0-1.1-.9-2-2-2zm-7 0c.55 0 1 .45 1 1s-.45 1-1 1-1-.45-1-1 .45-1 1-1zm7 18H5V4h2v3h10V4h2v16z"/></svg><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="#737373"><path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm0 18c-4.42 0-8-3.58-8-8s3.58-8 8-8 8 3.58 8 8-3.58 8-8 8z"/><path d="M0 0h24v24H0z" fill="none"/></svg><svg fill="#fff" xmlns="http://www.w3.org/2000/svg" height="24" width="24"><path fill="none" d="M0 0h24v24H0z"/><path d="m14.17 13.71 1.4-2.42c.09-.15.05-.34-.08-.45l-1.48-1.16c.03-.22.05-.45.05-.68s-.02-.46-.05-.69l1.48-1.16c.13-.11.17-.3.08-.45l-1.4-2.42c-.09-.15-.27-.21-.43-.15l-1.74.7c-.36-.28-.75-.51-1.18-.69l-.26-1.85a.364.364 0 0 0-.35-.29h-2.8c-.17 0-.32.13-.35.3L6.8 4.15c-.42.18-.82.41-1.18.69l-1.74-.7c-.16-.06-.34 0-.43.15l-1.4 2.42c-.09.15-.05.34.08.45l1.48 1.16c-.03.22-.05.45-.05.68s.02.46.05.69l-1.48 1.16c-.13.11-.17.3-.08.45l1.4 2.42c.09.15.27.21.43.15l1.74-.7c.36.28.75.51 1.18.69l.26 1.85c.03.16.18.29.35.29h2.8c.17 0 .32-.13.35-.3l.26-1.85c.42-.18.82-.41 1.18-.69l1.74.7c.16.06.34 0 .43-.15zM8.81 11c-1.1 0-2-.9-2-2s.9-2 2-2 2 .9 2 2-.9 2-2 2zm13.11 7.67-.96-.74c.02-.14.04-.29.04-.44 0-.15-.01-.3-.04-.44l.95-.74c.08-.07.11-.19.05-.29l-.9-1.55c-.05-.1-.17-.13-.28-.1l-1.11.45c-.23-.18-.48-.33-.76-.44l-.17-1.18a.216.216 0 0 0-.21-.2h-1.79c-.11 0-.21.08-.22.19l-.17 1.18c-.27.12-.53.26-.76.44l-1.11-.45a.23.23 0 0 0-.28.1l-.9 1.55c-.05.1-.04.22.05.29l.95.74a3.145 3.145 0 0 0 0 .88l-.95.74c-.08.07-.11.19-.05.29l.9 1.55c.05.1.17.13.28.1l1.11-.45c.23.18.48.33.76.44l.17 1.18c.02.11.11.19.22.19h1.79c.11 0 .21-.08.22-.19l.17-1.18c.27-.12.53-.26.75-.44l1.12.45c.1.04.22 0 .28-.1l.9-1.55c.06-.09.03-.21-.05-.28zm-4.29.16a1.35 1.35 0 1 1 .001-2.701 1.35 1.35 0 0 1-.001 2.701z"/></svg><svg fill="#fff" height="24" width="24" xmlns="http://www.w3.org/2000/svg"><path d="m19 8-4 4h3c0 3.31-2.69 6-6 6a5.87 5.87 0 0 1-2.8-.7l-1.46 1.46A7.93 7.93 0 0 0 12 20c4.42 0 8-3.58 8-8h3l-4-4zM6 12c0-3.31 2.69-6 6-6 1.01 0 1.97.25 2.8.7l1.46-1.46A7.93 7.93 0 0 0 12 4c-4.42 0-8 3.58-8 8H1l4 4 4-4H6z"/><path d="M0 0h24v24H0z" fill="none"/></svg><svg height="24" width="24" fill="#bd2e20" xmlns="http://www.w3.org/2000/svg"><path d="M0 0h24v24H0z" fill="none"/><path d="M11 17h2v-6h-2v6zm1-15C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm0 18c-4.41 0-8-3.59-8-8s3.59-8 8-8 8 3.59 8 8-3.59 8-8 8zM11 9h2V7h-2v2z"/></svg><svg fill="#fff" height="24" width="24" xmlns="http://www.w3.org/2000/svg"><path d="M0 0h24v24H0zm0 0h24v24H0zm0 0h24v24H0zm0 0h24v24H0z" fill="none"/><path d="M12 7c2.76 0 5 2.24 5 5 0 .65-.13 1.26-.36 1.83l2.92 2.92c1.51-1.26 2.7-2.89 3.43-4.75-1.73-4.39-6-7.5-11-7.5-1.4 0-2.74.25-3.98.7l2.16 2.16C10.74 7.13 11.35 7 12 7zM2 4.27l2.28 2.28.46.46A11.804 11.804 0 0 0 1 12c1.73 4.39 6 7.5 11 7.5 1.55 0 3.03-.3 4.38-.84l.42.42L19.73 22 21 20.73 3.27 3 2 4.27zM7.53 9.8l1.55 1.55c-.05.21-.08.43-.08.65 0 1.66 1.34 3 3 3 .22 0 .44-.03.65-.08l1.55 1.55c-.67.33-1.41.53-2.2.53-2.76 0-5-2.24-5-5 0-.79.2-1.53.53-2.2zm4.31-.78 3.15 3.15.02-.16c0-1.66-1.34-3-3-3l-.17.01z"/></svg><svg xmlns="http://www.w3.org/2000/svg" height="24" width="24" fill="#fff"><path d="M0 0h24v24H0z" fill="none"/><path d="M20 13H4c-.55 0-1 .45-1 1v6c0 .55.45 1 1 1h16c.55 0 1-.45 1-1v-6c0-.55-.45-1-1-1zM7 19c-1.1 0-2-.9-2-2s.9-2 2-2 2 .9 2 2-.9 2-2 2zM20 3H4c-.55 0-1 .45-1 1v6c0 .55.45 1 1 1h16c.55 0 1-.45 1-1V4c0-.55-.45-1-1-1zM7 9c-1.1 0-2-.9-2-2s.9-2 2-2 2 .9 2 2-.9 2-2 2z"/></svg><svg fill="#535353" height="24" width="24" xmlns="http://www.w3.org/2000/svg"><path d="M12.5 7.25a.75.75 0 0 0-1.5 0v5.5c0 .27.144.518.378.651l3.5 2a.75.75 0 0 0 .744-1.302L12.5 12.315V7.25z"/><path d="M12 1C5.925 1 1 5.925 1 12s4.925 11 11 11 11-4.925 11-11S18.075 1 12 1zM2.5 12a9.5 9.5 0 1 1 19 0 9.5 9.5 0 0 1-19 0z"/></svg><svg fill="#ddd" height="24" width="24" xmlns="http://www.w3.org/2000/svg"><path d="M11.99 2C6.47 2 2 6.48 2 12s4.47 10 9.99 10C17.52 22 22 17.52 22 12S17.52 2 11.99 2zm6.93 6h-2.95a15.65 15.65 0 0 0-1.38-3.56A8.03 8.03 0 0 1 18.92 8zM12 4.04c.83 1.2 1.48 2.53 1.91 3.96h-3.82c.43-1.43 1.08-2.76 1.91-3.96zM4.26 14C4.1 13.36 4 12.69 4 12s.1-1.36.26-2h3.38c-.08.66-.14 1.32-.14 2 0 .68.06 1.34.14 2H4.26zm.82 2h2.95c.32 1.25.78 2.45 1.38 3.56A7.987 7.987 0 0 1 5.08 16zm2.95-8H5.08a7.987 7.987 0 0 1 4.33-3.56A15.65 15.65 0 0 0 8.03 8zM12 19.96c-.83-1.2-1.48-2.53-1.91-3.96h3.82c-.43 1.43-1.08 2.76-1.91 3.96zM14.34 14H9.66c-.09-.66-.16-1.32-.16-2 0-.68.07-1.35.16-2h4.68c.09.65.16 1.32.16 2 0 .68-.07 1.34-.16 2zm.25 5.56c.6-1.11 1.06-2.31 1.38-3.56h2.95a8.03 8.03 0 0 1-4.33 3.56zM16.36 14c.08-.66.14-1.32.14-2 0-.68-.06-1.34-.14-2h3.38c.16.64.26 1.31.26 2s-.1 1.36-.26 2h-3.38z"/></svg><svg fill="#fff" height="24" width="24" xmlns="http://www.w3.org/2000/svg"><path d="M0 0h24v24H0z" fill="none"/><path d="M17 3H5a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14c1.1 0 2-.9 2-2V7l-4-4zm-5 16c-1.66 0-3-1.34-3-3s1.34-3 3-3 3 1.34 3 3-1.34 3-3 3zm3-10H5V5h10v4z"/></svg><svg height="24" width="24" fill="#737373" xmlns="http://www.w3.org/2000/svg"><path d="M0 0h24v24H0z" fill="none"/><path d="M18 8h-1V6c0-2.76-2.24-5-5-5S7 3.24 7 6v2H6c-1.1 0-2 .9-2 2v10c0 1.1.9 2 2 2h12c1.1 0 2-.9 2-2V10c0-1.1-.9-2-2-2zm-6 9c-1.1 0-2-.9-2-2s.9-2 2-2 2 .9 2 2-.9 2-2 2zm3.1-9H8.9V6c0-1.71 1.39-3.1 3.1-3.1 1.71 0 3.1 1.39 3.1 3.1v2z"/></svg><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="#fff"><path fill="none" d="M0 0h24v24H0z"/><path d="M11.5 9a2.5 2.5 0 0 0 0 5 2.5 2.5 0 0 0 0-5zM20 4H4c-1.1 0-2 .9-2 2v12c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V6c0-1.1-.9-2-2-2zm-3.21 14.21-2.91-2.91c-.69.44-1.51.7-2.39.7C9.01 16 7 13.99 7 11.5S9.01 7 11.5 7 16 9.01 16 11.5c0 .88-.26 1.69-.7 2.39l2.91 2.9-1.42 1.42z"/></svg><svg fill="#535353" height="24" width="24" xmlns="http://www.w3.org/2000/svg"><path d="M4.97 11.03a.75.75 0 1 1 1.06-1.06L11 14.94V2.75a.75.75 0 0 1 1.5 0v12.19l4.97-4.97a.75.75 0 1 1 1.06 1.06l-6.25 6.25a.75.75 0 0 1-1.06 0l-6.25-6.25zm-.22 9.47a.75.75 0 0 0 0 1.5h14.5a.75.75 0 0 0 0-1.5H4.75z"/></svg><svg fill="none" stroke="#535353" height="24" width="24" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><path d="M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z"/></svg><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="#fff"><path d="M0 0h24v24H0z" fill="none"/><path d="M1 21h22L12 2 1 21zm12-3h-2v-2h2v2zm0-4h-2v-4h2v4z"/></svg><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="#fff"><path d="M0 0h24v24H0z" fill="none"/><path d="M19.35 10.04A7.49 7.49 0 0 0 12 4C9.11 4 6.6 5.64 5.35 8.04A5.994 5.994 0 0 0 0 14c0 3.31 2.69 6 6 6h13c2.76 0 5-2.24 5-5 0-2.64-2.05-4.78-4.65-4.96zM14 13v4h-4v-4H7l5-5 5 5h-3z"/></svg><svg fill="#fff" height="24" width="24" xmlns="http://www.w3.org/2000/svg"><path d="M3 17.25V21h3.75L17.81 9.94l-3.75-3.75L3 17.25zM20.71 7.04a.996.996 0 0 0 0-1.41l-2.34-2.34a.996.996 0 0 0-1.41 0l-1.83 1.83 3.75 3.75 1.83-1.83z"/><path d="M0 0h24v24H0z" fill="none"/></svg><svg fill="#ddd" height="24" width="24" xmlns="http://www.w3.org/2000/svg"><path d="M19 19H5V5h7V3H5a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14c1.1 0 2-.9 2-2v-7h-2v7zM14 3v2h3.59l-9.83 9.83 1.41 1.41L19 6.41V10h2V3h-7z"/></svg><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="#ea4aaa"><path fill-rule="evenodd" d="M6.736 4C4.657 4 2.5 5.88 2.5 8.514c0 3.107 2.324 5.96 4.861 8.12a29.66 29.66 0 0 0 4.566 3.175l.073.041.073-.04c.271-.153.661-.38 1.13-.674.94-.588 2.19-1.441 3.436-2.502 2.537-2.16 4.861-5.013 4.861-8.12C21.5 5.88 19.343 4 17.264 4c-2.106 0-3.801 1.389-4.553 3.643a.75.75 0 0 1-1.422 0C10.537 5.389 8.841 4 6.736 4zM12 20.703l.343.667a.75.75 0 0 1-.686 0l.343-.667zM1 8.513C1 5.053 3.829 2.5 6.736 2.5 9.03 2.5 10.881 3.726 12 5.605 13.12 3.726 14.97 2.5 17.264 2.5 20.17 2.5 23 5.052 23 8.514c0 3.818-2.801 7.06-5.389 9.262a31.146 31.146 0 0 1-5.233 3.576l-.025.013-.007.003-.002.001-.344-.666-.343.667-.003-.002-.007-.003-.025-.013A29.308 29.308 0 0 1 10 20.408a31.147 31.147 0 0 1-3.611-2.632C3.8 15.573 1 12.332 1 8.514z"/></svg><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="#fff"><path d="M0 0h24v24H0z" fill="none"/><path d="M12 17c1.1 0 2-.9 2-2s-.9-2-2-2-2 .9-2 2 .9 2 2 2zm6-9h-1V6c0-2.76-2.24-5-5-5S7 3.24 7 6h1.9c0-1.71 1.39-3.1 3.1-3.1 1.71 0 3.1 1.39 3.1 3.1v2H6c-1.1 0-2 .9-2 2v10c0 1.1.9 2 2 2h12c1.1 0 2-.9 2-2V10c0-1.1-.9-2-2-2zm0 12H6V10h12v10z"/></svg><svg data-name="Layer 3" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 552.96 290.88"><defs><radialGradient id="a" cx="137.48" cy="58.44" r="363.06" gradientTransform="translate(28.52 -7.31)" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#fff"/><stop offset=".5" stop-color="#4d6998"/><stop offset="1" stop-color="#1d1d1b"/></radialGradient></defs><ellipse cx="276.48" cy="145.44" rx="276.48" ry="145.44" style="fill:url(#a)"/><ellipse cx="276.48" cy="145.44" rx="265.68" ry="134.64" style="fill:#6682ba"/><path d="m328.3 187 13.18-67.83c3-15.31.5-26.73-7.35-33.94-7.6-7-20.51-10.38-39.46-10.38h-22.83l6.54-33.6a4.32 4.32 0 0 0-4.24-5.15h-31.5a4.34 4.34 0 0 0-4.25 3.5l-14 72A40.48 40.48 0 0 0 215 90.75c-9.24-10.58-23.85-15.94-43.44-15.94h-61a4.32 4.32 0 0 0-4.24 3.5L77.91 224.06a4.32 4.32 0 0 0 4.24 5.14h31.75a4.31 4.31 0 0 0 4.24-3.49l6.86-35.26h23.64c12.4 0 22.82-1.34 31-4a60.61 60.61 0 0 0 22.72-13.61 70 70 0 0 0 13.43-16.67l-5.66 29.13a4.31 4.31 0 0 0 4.24 5.14h31.5a4.32 4.32 0 0 0 4.24-3.49l15.55-80h21.61c9.21 0 11.91 1.84 12.64 2.63s2 3.25.5 11.24l-12.53 64.49a4.31 4.31 0 0 0 4.24 5.14h32a4.32 4.32 0 0 0 4.18-3.45Zm-146-56c-2 10.16-5.71 17.42-11.08 21.56s-14.2 6.33-26 6.33h-14.08l10.18-52.36h18.19c13.36 0 18.75 2.86 20.91 5.26 3 3.21 3.63 9.88 1.84 19.13ZM463 90.75c-9.23-10.58-23.85-15.94-43.44-15.94h-61.05a4.32 4.32 0 0 0-4.24 3.5l-28.33 145.75a4.32 4.32 0 0 0 4.24 5.14h31.75a4.31 4.31 0 0 0 4.24-3.49l6.83-35.26h23.64c12.4 0 22.82-1.34 30.95-4a60.54 60.54 0 0 0 22.72-13.61 67.71 67.71 0 0 0 21.26-38.06c3.63-18.56.74-33.37-8.57-44.03Zm-32.92 40.17c-2 10.16-5.71 17.42-11.09 21.56s-14.19 6.33-26 6.33H379l10.17-52.36h18.19c13.37 0 18.75 2.86 20.92 5.26 2.95 3.29 3.59 9.96 1.8 19.21Z" transform="translate(2 2)" style="fill:#fff"/><path d="M159.51 102.13q18.09 0 24.12 6.68t2.87 22.93q-3.28 16.92-12.69 24.16t-28.6 7.23H125.9l11.85-61ZM82.15 224.88h31.75l7.53-38.75h27.2q18 0 29.62-3.78a56.14 56.14 0 0 0 21.13-12.68A63.35 63.35 0 0 0 219.32 134q5-25.92-7.6-40.38t-40.19-14.49h-61Zm160.49-184.5h31.5l-7.54 38.75h28.07q26.47 0 36.54 9.24t6 29.94l-13.18 67.82h-32l12.53-64.49q2.13-11-1.58-15t-15.8-4H262l-16.22 83.5h-31.5Zm164.68 61.75q18.1 0 24.13 6.68t2.87 22.93q-3.3 16.92-12.69 24.16T393 163.13h-19.28l11.85-61ZM330 224.88h31.75l7.53-38.75h27.19q18 0 29.62-3.78a56.17 56.17 0 0 0 21.14-12.68 63.26 63.26 0 0 0 19.9-35.67q5-25.92-7.59-40.38t-40.19-14.49h-61.06Z" transform="translate(2 2)" style="fill:#00000e"/></svg><svg fill="#ddd" height="24" width="24" xmlns="http://www.w3.org/2000/svg"><path d="M12.5 7.25a.75.75 0 0 0-1.5 0v5.5c0 .27.144.518.378.651l3.5 2a.75.75 0 0 0 .744-1.302L12.5 12.315V7.25z"/><path d="M12 1C5.925 1 1 5.925 1 12s4.925 11 11 11 11-4.925 11-11S18.075 1 12 1zM2.5 12a9.5 9.5 0 1 1 19 0 9.5 9.5 0 0 1-19 0z"/></svg><svg xmlns="http://www.w3.org/2000/svg" height="24" width="24" fill="#fff"><path d="M0 0h24v24H0z" fill="none"/><path d="M19.35 10.04A7.49 7.49 0 0 0 12 4C9.11 4 6.6 5.64 5.35 8.04A5.994 5.994 0 0 0 0 14c0 3.31 2.69 6 6 6h13c2.76 0 5-2.24 5-5 0-2.64-2.05-4.78-4.65-4.96zM19 18H6c-2.21 0-4-1.79-4-4s1.79-4 4-4h.71C7.37 7.69 9.48 6 12 6c3.04 0 5.5 2.46 5.5 5.5v.5H19c1.66 0 3 1.34 3 3s-1.34 3-3 3z"/></svg><svg fill="#ddd" height="24" width="24" xmlns="http://www.w3.org/2000/svg"><path d="M12 .25a.75.75 0 0 1 .673.418l3.058 6.197 6.839.994a.75.75 0 0 1 .415 1.279l-4.948 4.823 1.168 6.811a.75.75 0 0 1-1.088.791L12 18.347l-6.117 3.216a.75.75 0 0 1-1.088-.79l1.168-6.812-4.948-4.823a.75.75 0 0 1 .416-1.28l6.838-.993L11.328.668A.75.75 0 0 1 12 .25zm0 2.445L9.44 7.882a.75.75 0 0 1-.565.41l-5.725.832 4.143 4.038a.75.75 0 0 1 .215.664l-.978 5.702 5.121-2.692a.75.75 0 0 1 .698 0l5.12 2.692-.977-5.702a.75.75 0 0 1 .215-.664l4.143-4.038-5.725-.831a.75.75 0 0 1-.565-.41L12 2.694z"/></svg><svg xmlns="http://www.w3.org/2000/svg" height="24" width="24" fill="#fff"><path d="M0 0h24v24H0z" fill="none"/><path d="M6 10c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2zm12 0c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2zm-6 0c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2z"/></svg><svg fill="#535353" height="24" width="24" xmlns="http://www.w3.org/2000/svg"><path d="M11.99 2C6.47 2 2 6.48 2 12s4.47 10 9.99 10C17.52 22 22 17.52 22 12S17.52 2 11.99 2zm6.93 6h-2.95a15.65 15.65 0 0 0-1.38-3.56A8.03 8.03 0 0 1 18.92 8zM12 4.04c.83 1.2 1.48 2.53 1.91 3.96h-3.82c.43-1.43 1.08-2.76 1.91-3.96zM4.26 14C4.1 13.36 4 12.69 4 12s.1-1.36.26-2h3.38c-.08.66-.14 1.32-.14 2 0 .68.06 1.34.14 2H4.26zm.82 2h2.95c.32 1.25.78 2.45 1.38 3.56A7.987 7.987 0 0 1 5.08 16zm2.95-8H5.08a7.987 7.987 0 0 1 4.33-3.56A15.65 15.65 0 0 0 8.03 8zM12 19.96c-.83-1.2-1.48-2.53-1.91-3.96h3.82c-.43 1.43-1.08 2.76-1.91 3.96zM14.34 14H9.66c-.09-.66-.16-1.32-.16-2 0-.68.07-1.35.16-2h4.68c.09.65.16 1.32.16 2 0 .68-.07 1.34-.16 2zm.25 5.56c.6-1.11 1.06-2.31 1.38-3.56h2.95a8.03 8.03 0 0 1-4.33 3.56zM16.36 14c.08-.66.14-1.32.14-2 0-.68-.06-1.34-.14-2h3.38c.16.64.26 1.31.26 2s-.1 1.36-.26 2h-3.38z"/></svg><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="#737373"><path d="M12 7c-2.76 0-5 2.24-5 5s2.24 5 5 5 5-2.24 5-5-2.24-5-5-5zm0-5C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm0 18c-4.42 0-8-3.58-8-8s3.58-8 8-8 8 3.58 8 8-3.58 8-8 8z"/><path d="M0 0h24v24H0z" fill="none"/></svg><svg fill="#FFF" width="24" height="24" xmlns="http://www.w3.org/2000/svg"><path fill="none" d="M0 0h24v24H0V0z"/><path d="M9.4 16.6 4.8 12l4.6-4.6L8 6l-6 6 6 6 1.4-1.4zm5.2 0 4.6-4.6-4.6-4.6L16 6l6 6-6 6-1.4-1.4z"/></svg><svg fill="none" stroke="#ddd" height="24" width="24" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><circle cx="12" cy="12" r="5"/><path d="M12 1v2m0 18v2M4.22 4.22l1.42 1.42m12.72 12.72 1.42 1.42M1 12h2m18 0h2M4.22 19.78l1.42-1.42M18.36 5.64l1.42-1.42"/></svg><svg height="24" width="24" fill="#fff" xmlns="http://www.w3.org/2000/svg"><path d="M0 0h24v24H0z" fill="none"/><path d="M19.43 12.98c.04-.32.07-.64.07-.98s-.03-.66-.07-.98l2.11-1.65c.19-.15.24-.42.12-.64l-2-3.46c-.12-.22-.39-.3-.61-.22l-2.49 1c-.52-.4-1.08-.73-1.69-.98l-.38-2.65A.488.488 0 0 0 14 2h-4c-.25 0-.46.18-.49.42l-.38 2.65c-.61.25-1.17.59-1.69.98l-2.49-1c-.23-.09-.49 0-.61.22l-2 3.46c-.13.22-.07.49.12.64l2.11 1.65c-.04.32-.07.65-.07.98s.03.66.07.98l-2.11 1.65c-.19.15-.24.42-.12.64l2 3.46c.12.22.39.3.61.22l2.49-1c.52.4 1.08.73 1.69.98l.38 2.65c.03.24.24.42.49.42h4c.25 0 .46-.18.49-.42l.38-2.65c.61-.25 1.17-.59 1.69-.98l2.49 1c.23.09.49 0 .61-.22l2-3.46c.12-.22.07-.49-.12-.64l-2.11-1.65zM12 15.5c-1.93 0-3.5-1.57-3.5-3.5s1.57-3.5 3.5-3.5 3.5 1.57 3.5 3.5-1.57 3.5-3.5 3.5z"/></svg><svg height="24" width="24" fill="#737373" xmlns="http://www.w3.org/2000/svg"><path d="M11.99 2C6.47 2 2 6.47 2 12s4.47 10 9.99 10S22 17.53 22 12 17.52 2 11.99 2zM12 20c-4.42 0-8-3.58-8-8s3.58-8 8-8 8 3.58 8 8-3.58 8-8 8zm4.18-12.24-1.06 1.06-1.06-1.06L13 8.82l1.06 1.06L13 10.94 14.06 12l1.06-1.06L16.18 12l1.06-1.06-1.06-1.06 1.06-1.06zM7.82 12l1.06-1.06L9.94 12 11 10.94 9.94 9.88 11 8.82 9.94 7.76 8.88 8.82 7.82 7.76 6.76 8.82l1.06 1.06-1.06 1.06zM12 14c-2.33 0-4.31 1.46-5.11 3.5h10.22c-.8-2.04-2.78-3.5-5.11-3.5z"/><path d="M0 0h24v24H0z" fill="none"/></svg><svg fill="#fff" height="24" width="24" xmlns="http://www.w3.org/2000/svg"><path d="M0 0h24v24H0z" fill="none"/><path d="m10 16.5 6-4.5-6-4.5v9zM12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm0 18c-4.41 0-8-3.59-8-8s3.59-8 8-8 8 3.59 8 8-3.59 8-8 8z"/></svg><svg height="24" width="24" fill="#bd2e20" xmlns="http://www.w3.org/2000/svg"><path d="M19 6.41 17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z"/><path d="M0 0h24v24H0z" fill="none"/></svg><svg fill="#ea4aaa" height="24" width="24" xmlns="http://www.w3.org/2000/svg"><path d="M0 0h24v24H0z" fill="none"/><path d="M19 19H5V5h7V3H5a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14c1.1 0 2-.9 2-2v-7h-2v7zM14 3v2h3.59l-9.83 9.83 1.41 1.41L19 6.41V10h2V3h-7z"/></svg><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="#737373"><path d="M19 5v14H5V5h14m0-2H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2z"/><path d="M0 0h24v24H0z" fill="none"/></svg>PNG

   IHDR         (-S   gAMA  a    cHRM  z&         u0  `  :  pQ<   PLTE   } | | } z  | | | | | } w v | | |  | |  |  { | { y | { ~ { y |   { {  { { { } } | | | z { |  | { } | | | z | } | 8mpA   ;tRNS /.PR(OGW&{Ux-0Mh͠,s+&O   bKGD<ja   	pHYs  	  	Ǡ   tIME	 =z$   IDATc`
YX\6vkNN.n^_@PAHKD, %Q2r TPb`PVQR
k05utA`-@-Fj0CMbXg
sa`}cani <.+   %tEXtdate:create 2019-08-13T09:12:00+02:00:   %tEXtdate:modify 2019-08-13T09:12:00+02:00g
   tEXtSoftware www.inkscape.org<   WzTXtRaw profile type iptc  xqV((OIR #.c#K D4d#T ˀHJ. tB5    IENDB`    00     %  6            %       h  6  (   0   `           $                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        {6 |s | | | | | | | | {r }5                                                                                                                                   | | | | | | | | | | | | | | | } {                                                                                                                 x | | | | | | | | | | | | | | | | | | | |                                                                                                      {U | | | | | | | | | | | | | | | | | | | | | | |R                                                                                         f | | | | | | | | | {_ }5 z U U z {6 {_ | | | | | | | | |                                                                              t { | | | | | { |a                                           }b | | | | | | { t                                                                      { | | | | | |                                                          q	 } | | | | | }                                                                  { | | | | | {>                                                                         }? | | | | | |                                                             {W | | | | | {                                                                                   } | | | | |R                                                      | | | | | $                                                                                         $ | | | | | v                                                 | | | | | {6                                                                                                 {8 | | | | }                                             { | | | | {r                                     | v                                                             {v | | | |                                          } | | | }                                      | | z0                                                          | | | | |                                     U | | | | }b                                         | | | }h                                                         |e | | | |                                  {: | | | | 
                                         | | | | | v                                                 t | | | | {6                                 |{ | | | |                                             | | | | | | z0                                                 | | | | |w                                 } | | | |c                                             | | | | | | | }h                                             |g | | | |                                 | | | | }5                                             | | | | | | | | | v                                     {8 | | | |                                 | | | |                                              | | | | | | | | | | z0                                  | | | |                                 | | | | f                                             | | | | | | | | | | | }h                             m | | | |                                 | | | |                                              | | | | | | | | | | | }f                             m | | | |                                 | | | |                                              | | | | | | | | | | |%                                  | | | |                                 | | | | }5                                             | | | | | | | | |                                      {8 | | | |                                 } | | | |c                                             | | | | | | | {W                                             |g | | | |                                 |{ | | | |                                             | | | | | | |%                                                 | | | | |w                                 {: | | | | 
                                         | | | | |                                                  t | | | | {6                                 U | | | | }f                                         | | | {W                                                         |e | | | |                                      } | | | | 
                                     | | |%                                                          | | | | |                                         { | | | | {z                                     |                                                              {v | | | |                                              | | | | | {6                                                                                                 {8 | | | | {                                                  | | | | |                                                                                          z | | | | |                                                      {W | | | | | {                                                                                  | | | | | |R                                                             { | | | | | }5                                                                         }7 | | | | | |                                                                  { | | | | | {v q	                                                          {p | | | | | }                                                                      t { | | | | | | }b                                           {_ | | | | | | { t                                                                             f | | | | | | | | | {_ }5 z x x z {6 {_ | | | | | | | | |                                                                                          {U | | | | | | | | | | | | | | | | | | | | | | |R                                                                                                     x | | | | | | | | | | | | | | | | | | | |                                                                                                                   | | | | | | | | | | | | | | | } {                                                                                                                                  {6 |s | | | | | | | | {r }5                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     ?                  ?  ??  ?      ?                  ?      ?  ??  ?                    ?                (       @                                                                                                                                                                                                                                                                                                                                                   y( {> {> y(                                                                                              |% | | | | | | | | | | $                                                                         y } | | | | | | | | | | | | }                                                              {8 | | | | | | {| {] {] |} } | | | | | }5                                                     }V | | | | }\                          m }^ | | | | |T                                             }9 | | | {                                          q	 { | | | {6                                     y | | | {p                                                         {t | | |                                  | | | |                                                                 | | | |                             |! | | | m                     } z0                                      | | | {                         | | | }Z                         } | }h                                     {] | | |}                         | | |                          } | | }                               | | |                      | | |                             } | | | | z0                             | | |                  }/ | | |{                             } | | | | | {]                         |} | | }-                 zI | | }`                             } | | | | | | | v                 }b | | |H                 zI | | |a                             } | | | | | | | t                 }b | | |H                 z0 | | {z                             } | | | | | }f                         {| | | z.                  | | |                             } | | | | |%                             | | |                      | | |                          } | | | t                             f | | |                         | | | }Z                         } | {W                                     {] | | |}                         |! | | | m                     {z |%                                      | | | {                             | | | |                                                                 | | | |                                 y | | | {p                                                         {t | | |                                      }9 | | | {                                          q	 { | | | {6                                             }V | | | | }\                          m }^ | | | | |T                                                     {8 | | | | | | {| {] {] |} } | | | | | }5                                                             y } | | | | | | | | | | | | }                                                                          |% | | | | | | | | | | $                                                                                              y( {> {> y(                                                                                                                                                                                                                                                                                                                     ??????(                                                                                                                         z, |s { { |s }+                                  | | | | | | | |                      v | | |P           |R | |                  | |                          { | {             y( | {O         {M }h                 |R | y&         |{ |           {U | |           | {x         { {             {U | | | z0         { |         { {             {U | | } }-         | |         |{ |           {U | {           | {x         y( | {O         ~G {W                 |R | y&             | |                          { | {                 v | | |P           |R | |                       | | | | | | | } w                                 }/ | | | } z.                                                                                                {  9  9  {          ?    PNG

   IHDR           D   gAMA  a    cHRM  z&         u0  `  :  pQ<  PLTE    y { | | | | | |  y } | | }  { | | | { { | } | | } } | | }  m } | | | } {  q { { y | { { | | | | | { { } } { | |  | t f | |  | | | z | } z z | } | } | v } | | } | | } } | | | | kb   \tRNS (>%$8|]}5V\^T9	6pt!zZWΩ0f.IabH`/{-h5   bKGD]0   	pHYs    c   tIME	J}  $IDAT8˭gS@C	X@PŎc];Iqӻ>s(d*L|LmjGݙBF'BQA!H	ʣ;CmO
Az<,\U>`9T^ɳZT#-Li*j)	tGn uN9!)9&kiBprj'E89\%\u wp4;1'3ܤҢP@}A^Ք	؅__{%Xc|M.Q_G#   %tEXtdate:create 2019-08-13T09:12:01+02:00=M   %tEXtdate:modify 2019-08-13T09:12:01+02:00L   tEXtSoftware www.inkscape.org<   WzTXtRaw profile type iptc  xqV((OIR #.c#K D4d#T ˀHJ. tB5    IENDB`PNG

   IHDR         (-S   gAMA  a    cHRM  z&         u0  `  :  pQ<   PLTE   QAPAOANCP@PAPAPAPAPAQBUDQAQAP@QAPAPAMDRBOAPAO>QAM@QBMAPB  QAQBOBPAPBP@PBOAQAQAPBPAQ@P@Q@PAS@PAQCPAN;PAPBU@QAQ@OBP@PA>˝i   ;tRNS /.PRЬ-Oe+|bxaypnm{`_(&,tsn܌   bKGD<ja   	pHYs  	  	Ǡ   tIME;b   IDATm0E#8ЪXPZgQRYws2F0MYV[v,n05Lܩ84@CXJ
Y#L6.=AI]8kRMnjͽZ>Þ/.GoP4V|   %tEXtdate:create 2019-08-13T08:08:59+02:00Mxo   %tEXtdate:modify 2019-08-13T08:08:59+02:00<%"   tEXtSoftware www.inkscape.org<   WzTXtRaw profile type iptc  xqV((OIR #.c#K D4d#T ˀHJ. tB5    IENDB`    00     %  6            %       h  6  (   0   `           $                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      BP6BOtAPۨBPAPAPAPAPAQAPۨ@PsCR5                                                                                                                                @RAP܉AQAPAPAPAPAPAPAPAPAPAPAPAPAPBQۈBL                                                                                                                GUAO۔APAPAPAPAPAPAPAPAPAPAPAPAPAPAPAPAPAPAOܑ<K                                                                                                    @OWAPAPAPAPAPAPAPAPAPAPAPAPAPAPAPAPAPAPAPAPAPAP@OT                                                                                        UUAPڙAPAPAPAPAPAPAPAPۢ@Q_CR5CNUUUUCNBP6@Q_BPۣAPAPAPAPAPAPAPAPۖ3f                                                                            @U@PۺAPAPAPAPAPAPBOa@`                                        @`AQbAPAPAPAPAPAPAO۷FF                                                                    3fAP۸APAPAPAPAP@P@`                                                        9U	AOہAPAPAPAPAPAPڵ@@                                                                @OܗAPAPAPAPAPBN>                                                                        AQ?APAPAPAPAPAPڒ                                                            @QXAPAPAPAPAQBR                                                                                @P APAPAPAPAP@OT                                                    IIAPAPAPAPAP@N$                                                                                        @N$APAPAPAPAP;N                                                APەAPAPAPAPBP6                                                                                                @R8AOAPAPAPBPܐ                                            @RAPAPAPAPAQr                                                                                                        APvAPAPAPAO=R                                        BQۈAPAPAPAP@@                        3fAP۬@P\                                @P\BQ۫3f                        UUAPAPAPAPAQۅ                                    UUAPAPAPAPAQb                        @@AP۬APAP@P\                        @P\APAPBQ۫@@                        BQeAPAPAPAP                                 BO:APAPAPAPMM
                        APۥAPAPAPAP@Q[                @Q[APAPAPAPAOۤ                        FFAPAPAPAPBP6                                @Q{APAPAPAPۥ                            @QXAPAPAPAPAPAOZ        AOZAPAPAPAPAP@OW                            AP۩APAPAP@Ow                                @QڮAPAPAP@Pc                                APVAPAPAPAPAPBPYBPYAPAPAPAPAPBQU                                @OgAPAPAPBQ۫                                AQAPAPAPCR5                                    @OTAPAPAPAPAPAPAPAPAPAPAPS                                    @R8APAPAPBP                                APAPAPAP@M                                        AQRAPAPAPAPAPAPAPAPBOQ                                        FQAPAPAPAP                                APAPAPAP3f                                            @PPAPAPAPAPAPAP@PP                                            IIAPAPAPAP                                APAPAPAPUU                                            APSAPAPAPAPAPAPAPS                                            IIAPAPAPAP                                APAPAPAP@M                                        @P\APAPAPAPAPAPAPAP@P\                                        FQAPAPAPAP                                AQAPAPAPCR5                                    @Q[APAPAPAPAPAPAPAPAPAP@Q[                                    @R8APAPAPBP                                @QڮAPAPAP@Pc                                AOZAPAPAPAPAP@OW@QXAPAPAPAPAPAOZ                                @OgAPAPAPBQ۫                                @Q{APAPAPAPۥ                            BPYAPAPAPAPAPBQU        APVAPAPAPAPAPBPY                            AP۩APAPAP@Ow                                BO:APAPAPAPMM
                        BPۣAPAPAPAPAPS                @OTAPAPAPAPAPۢ                        FFAPAPAPAPBP6                                UUAPAPAPAPAPf                        UUAPۥAPAPBOQ                        AQRAPAPAOۤUU                        BQeAPAPAPAP                                     BQۈAPAPAPAPMM
                        UUAP۝@PP                                @PPAP۝UU                        UUAPAPAPAPAQۅ                                        >OAPAPAPAPAOz                                                                                                        APvAPAPAPAPBL                                            AP۝APAPAPAPBP6                                                                                                @R8AOAPAPAPAPڙ                                                BLAPAPAPAPAP@U                                                                                        =RAPAPAPAPAPCN                                                    AOZAPAPAPAPAP>O                                                                                DMAQAPAPAPAPAPV                                                            AQۡAPAPAPAPAPCR5                                                                        AO7AOAPAPAPAPAP۝                                                                IIAP۽APAPAPAPAPAPv9U	                                                        @@BPpAPAPAPAPAP@PۺUU                                                                    @U@PۺAPAPAPAPAPAPAQb@`                                        @`@Q_BPAPAPAPAPAPAO۷@U                                                                            UUAPڙAPAPAPAPAPAPAPAPۢ@Q_CR5CN<K<KCNBP6@Q_BPۣAPAPAPAPAPAPAPAPۖ3f                                                                                        @OWAPAPAPAPAPAPAPAPAPAPAPAPAPAPAPAPAPAPAPAPAPAP@OT                                                                                                    GUAO۔APAPAPAPAPAPAPAPAPAPAPAPAPAPAPAPAPAPAOܑ<K                                                                                                                @RAP܉AQAPAPAPAPAPAPAPAPAPAPAPAPAPBQۈBL                                                                                                                                BP6BOtAPۨBPAPAPAPAPAQAPۨ@PsCR5                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    ?                  ?  ??  ?                              ?  ??  ?                    ?                (       @                                                                                                                                                                                                                                                                                                                                                 @U@S(BN>BN>@S(@U                                                                                            >S%AOہAPAPAPAPAPAPAPAPBPۀ@N$                                                                        @MAPڒAPAPAPAPAPAPAPAPAPAPAPAPBPܐCQ                                                            @R8APAPAPAPAPBQ۫BP|BP]BP]AP}AP۬APAPAPAPAPAO7                                                    @OWAPAPAPAP@P\UU                        IIAO^APAPAPAOAPV                                            CQ9APAPAP@Oܗ@`                                        9U	BQۛAPAPAOAO7                                    =UAOAPAPBPp                                                        BOtAPAPAPCQ                                APۍAPAPAPڠ                                                                APۢAPAPAP܉                            >M!APAPAPII                CN                        CN                @`APAPAPBR                        BPۀAPAPAOZ                AOJAPAO^                @Q_APBPI                BP]APAPAP}                        APAPAP3f            @RAOAPAPAQb        AQbAPAPAP@R            IIAPAPAP                    @MAPAPAPܦ                    @OdAPAPAPBQeAPfAPAPAP@Od                    AP۩APAPGU                @P0APAPAOz                        BOaAPAPAPAPAPAP@P`                        BP|APAPCN.                BPIAPAP@P`                            BP]APAPAPAPBP]                            AQbAPAP@QH                BPIAPAPBOa                            BOaAPAPAPAPBOa                            AQbAPAP@QH                AQ/APAP@Q{                        BPiAPAPAPAPAPAPBPi                        AP}APAP>O-                @MAPAPAPܦ                    BQhAPAPAPBQeAPfAPAPAPBQh                    AP۩APAPGU                    APAPAP3f            @RAOAPAPAQb        AQbAPAPAO@R            IIAPAPAP                        BPۀAPAPAOZ                AOJAPAO^                @Q_APBPI                BP]APAPAP}                        >M!APAPAPII                CN                        CN                @`APAPAPBR                            APۖAPAPAQێ                                                                APڒAPAPAPڒ                                =UAOAPAPBPp                                                        BOtAPAPAPCQ                                    CQ9APAPAP@Oܗ@`                                        9U	BQۛAPAPAOAO7                                            @OWAPAPAPAP@P\UU                        IIAO^APAPAPAOAPV                                                    @R8APAPAPAPAPBQ۫BP|BP]BP]AP}AP۬APAPAPAPAPAO7                                                            @MAPڒAPAPAPAPAPAPAPAPAPAPAPAPBPܐCQ                                                                        >S%AOہAPAPAPAPAPAPAPAPBPۀ@N$                                                                                            @U@S(BN>BN>@S(@U                                                                                                                                                                                                                                                                                                                    ??????(                                                                                                                        @Q,BOtBPܟBPܟ@PsAM+                                ;NAQۡAPAPAPܻAPܻAPAPBPܟ@U                    ;NAPAQ@PP        AQRAPBP@U                APۢAPDM                        BRAOAQ۞            @S(APAQO    @MBQe        BQe@M    AQRAPCQ&        @Q{AO      @P`APBQxBQxAP@Q_    APBQx        BPܟ@P۶            AQnAPAPBPm            AP۸AQ۞        BPܟ@P۶            BPpAPAPBPp            AO۷AQ۞        BP|AQ      AQbAPBQxBQxAPBOa    APAPy        >O-APAQO    @MBQe        BQe@M    AQRAPAM+            AP۬APDM                        BRAOAPۨ                @PAQAQ@PP        AQRAPAPDU                    @PAPܭAPAPAPܻAPܻAPAPBQ۫DU                                AQ/AP܂AOۤAOۤAP܂CN.                                                                                                ݻ  y  y  ݻ          ?    PNG

   IHDR           D   gAMA  a    cHRM  z&         u0  `  :  pQ<  PLTE   U@S@NBS>OAPAPAPAPBN@M@PAPAPBQCR@PAPAQBPBPBPAPAPAPAOAO@PAPAP@UUIIOAPAOAPAQCO@`@U9QBU=OAPBOBPAQAM>PAPANCRBOAOAPAQ@PBPAPAf3R@PAQAPAPAQBQBPAPAUGQAQ@PBO>OBQ@P@PAP@OANCO@PAPAPAPAPAPA   XtRNS (>%ˀ$8|]}7W\^V9	pt!ZJ_Ibͦhef/{i-aH`0z.d   bKGDY   	pHYs    c   tIME	 AϺa  0IDAT8˭R1P#zX
b+ؾsrg㸓7϶l%Ţ=}%?>{LЖp?2c)JO(89Og ;3ʿXKˊceւ!UN.9`׳]U̒	qwA)RQ}'JU
H0lI*QuKĕƣBged˰E40T
S,)"e3X6mz?va+_Zڏ_PCZ   %tEXtdate:create 2019-08-13T08:09:00+02:00O   %tEXtdate:modify 2019-08-13T08:09:00+02:00   tEXtSoftware www.inkscape.org<   WzTXtRaw profile type iptc  xqV((OIR #.c#K D4d#T ˀHJ. tB5    IENDB`PNG

   IHDR         (-S   gAMA  a    cHRM  z&         u0  `  :  pQ<   PLTE   1L1K2K1K2N0P1K1K1K1K1K1K3D1J1K0M 2K1K1L5O3M1K1J3J1K1I3M/M1J  1K1L0L0J3J0K$I1K+U1K1K2K1M1K2K0J1K'N2K1K0K1J3M1J/J1L1K2L1J.K0K1K1Kw   @tRNS /.PRЬ-N*<+|y7?0{x(&Ρ,ts[   bKGDAlN   	pHYs  	  	Ǡ   tIME}_   IDATm0D(Bbq_.`qUB^&ssN&ȭBQJꕷaVk__FSiIKOG6uPǖ320/j vE1yF'[;>'.Xj"4=]7/',{
   %tEXtdate:create 2019-08-13T08:05:08+02:00V   %tEXtdate:modify 2019-08-13T08:05:08+02:00'LYB   tEXtSoftware www.inkscape.org<   WzTXtRaw profile type iptc  xqV((OIR #.c#K D4d#T ˀHJ. tB5    IENDB`    00     %  6            %       h  6  (   0   `           $                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       L/6K1sJ1K1K1K1K1K1J1J1K1sM05                                                                                                                                 I.J0K1K1K1K1K1K1K1K1K1K1K1K1K1K1L1L/                                                                                                                K-K1K1K1K1K1K1K1K1K1K1K1K1K1K1K1K1K1K1K1L1P0                                                                                                    J2VK1K1K1K1K1K1K1K1K1K1K1K1K1K1K1K1K1K1K1K1K1K1J1S                                                                                        33K0K1K1K1K1K1K1K1L1L1^M05N,UUUUN,L/6K0_K0K1K1K1K1K1K1K1K233                                                                            U+J2K1K1K1K1K1K1K1c@@                                        @@L2aK1K1K1K1K1K1K1F.                                                                    33K1K1K1K1K1K1L1U+                                                        @@L2K1K1K1K1K1K2@@                                                                K1K1K1K1K1L1K2=                                                                        J1>K1K1K1K1K1L1                                                            L2WK1K1K1K1K2M3                                                                                J1K1K1K1K1K1J1S                                                    I7K1K1K1K1K1I3#                                                                                        N2$K1K1K1K1K1N'                                                L0K1K1K1K1M05                                                                                                I28K1K1K1K1J2                                            L/K1K1K1K1J2q                                        K1K1                                                        L2vK1K1K1K1G3                                        L1K1K1K1L2@@                                    K1K1K1K1                                                    U+K1K1K1K1K2                                    UUK1K1K1K1K1b                                    K1K1K1K1K1K1                                                    L0eK1K1K1J1                                  K0:K1K1K1K1M3
                                K1K1K1K1K1K1K1K1                                                F.K1K1K1K1L/6                                K2{K1K1K1L1                                K1K1K1K1K1K1K1K1K1K1                                                K0K1K1K1K1w                                K0K1K1K1K1c                            K1K1K1K1K1K1K1K1K1K1K1K1                                            J2gK1K1K1K1                                K1K1K1K1M05                        K1K1K1K1K1K1K23K23K1K1K1K1K1K1                                        I28K1K1K1K1                                K1K1K1K1M3                    K1K1K1K1K1K1K23        J14K1K1K1K1K1K1                                    F.K1K1K1K1                                K1K1K1K133                K1K1K1K1K1K1J14                J14K1K1K1K1K1K1                                I$K1K1K1K1                                K1K1K1K1U+                K1K1K1K1K1M1?                        M1?K1K1K1K1K1L2                            I$K1K1K1K1                                K1K1K1K1M3                    K1~K1K1M05                                M05K1K1K1K1K1K1                        F.K1K1K1K1                                K1K1K1K1M05                        L0yL/6                                        M05K1K1K1K1K1K1                    I28K1K1K1K1                                K0K1K1K1K1c                                                                            M05K1K1K1K1K1K1                J2gK1K1K1K1                                K2{K1K1K1L1                                                                                L/6K1K1K1K1K1K1            K0K1K1K1K1w                                K0:K1K1K1K1M3
                                                                                L/6K1K1K1K1L0y        F.K1K1K1K1L/6                                UUK1K1K1K1K1b                                                                                    L/6K1K1K1}            K1iK1K1K1J1                                      L1K1K1K1L2@@                                                                                    J37L0y            F.K1K1K1K1K2                                        O5K1K1K1K1J2q                                                                                                        J1|K1K1K1K1L/                                            K1K1K1K1K1K.,                                                                                                I28K1K1K1K1K1                                                I1K1K1K1K1K1N,                                                                                        O5K1K1K1K1K1Q6                                                    L2WK1K1K1K1K1F.                                                                                O5K2K1K1K1K1J1S                                                            K1K1K1K1K1L2K2)                                                                        M05K1K1K1K1K1L1                                                                33K1K1K1K1K1K1K1mUU                                                        @@L0oK1K1K1K1K1K2@@                                                                    U+J2K1K1K1K1K1K1J1]@@                                        @@L1^K1K1K1K1K1K1K1F.                                                                            33K0K1K1K1K1K1K1K1L1L1^M05N,K-K-N,L/6K0_K0K1K1K1K1K1K1K1K233                                                                                        J2VK1K1K1K1K1K1K1K1K1K1K1K1K1K1K1K1K1K1K1K1K1K1J1S                                                                                                    K-K1K1K1K1K1K1K1K1K1K1K1K1K1K1K1K1K1K1K1L1P0                                                                                                                I.J0K1K1K1K1K1K1K1K1K1K1K1K1K1K1L1L/                                                                                                                                 L/6K1sJ1K1K1K1K1K1J1J1K1sM05                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     ?                  ?  ??  ?    ?             ?    ?        >  ?  ??  ?                    ?                (       @                                                                                                                                                                                                                                                                                                                                                 U+M3(J1>J1>M3(U+                                                                                            L0%K1K1K1K1K1K1K1K1J1L2N2$                                                                        Q6K1K1K1K1K1K1K1K1K1K1K1K1K1K0G+                                                            I28K1K1K1K1K1K1J1|J1]J1]K1}K1K0K1K1K1K1L/6                                                    J2VK1K1K1K1L0[U+                        U+J1]K1K1K1K1K0U                                            L19K1K1K1K1@@                                        @@K2K1K1K1L/6                                    I1K1K1K1L0o                                                        L1rK1K1K1Q6                                K1K1K1K1                                                                L1K1K1J0                            M.!K1K1K0U+                    K-K1J1>                                @@K1K1K1J1                        L2K1K1J1Y                    K-K1K1K1J1>                                K2\K1K1K1}                        L2K1K1U+                F.K1K1K1K1K1K23                            @@K1K1K1                    M3K1K1K1                K-K1K1K1K1K1K1K1J1>                            K0K1K1G+                L1/K1K1K2{            F.K1K1K1K1M3K1K1K1K1K23                        K1}K1K1J3-                I1IK1K1J0`        K-K1K1K1K1J5      K0K1K1K1J1>                    K1bK1K1J2H                I1IK1K1L2a        K-L2K1K1H0             UUK1K1K1K1K23                K1bK1K1J2H                L1/K1K1K2{            I7K2G3                      K0K1K1K1J1>            K1}K1K1J3-                M3K1K1K1                                                  K2K1K1K1J1>        K0K1K1G+                    K1K1K133                                                 K2K1K1K1    I$K1K1K1                        L2K1K1J1Y                                                     L1L1N'    K2\K1K1K1}                        M.!K1K1K0U+                                                     U+    @@K1K1K1J1                            K1K1K1J1                                                                L1K1K1K1                                I1K1K1K1L0o                                                        L1rK1K1K1Q6                                    L19K1K1K1K1@@                                        @@K2K1K1K1L/6                                            J2VK1K1K1K1L0[U+                        U+J1]K1K1K1K1K0U                                                    I28K1K1K1K1K1K1J1|J1]J1]K1}K1K0K1K1K1K1L/6                                                            Q6K1K1K1K1K1K1K1K1K1K1K1K1K1K0G+                                                                        L0%K1K1K1K1K1K1K1K1J1L2N2$                                                                                            U+M3(J1>J1>M3(U+                                                                                                                                                                                                                                                                                                                    ???珇??(                                                                                                                        K.,K0tK2K2K1sM/+                                N'J1K1K1K1K1K1K1K2U+                    N'K1K1M0P          K2RK1L2U+                L1K1O5                        M3K1J0            M3(K1K1N        M1?J1P0            K2RK1J/&        K2{K1      M1?K1K1K0D3         K1J1x        K2L1    M1?K1K2J00K1K1N'        K1J0        J0L1    J37K0I$    I1*K1K1U+    K1K1        J1|K1                      I1*K1L1 K1L0y        J3-K1K1N                        I1*M3<K2RK1M/+            L1K1O5                        M3K1J1                P0J1K1M0P          K2RK1K1D3                    P0K1K1K1K1K1K1K1K1D3                                L1/K1K2K2K1N2.                                                                                                {  9              ?    PNG

   IHDR           D   gAMA  a    cHRM  z&         u0  `  :  pQ<  )PLTE   +U3M1J0L1K1K1K1K1J2L2N6Q1K1K1K0K+G2I1K1K1K1J1J1K0K1K/L2J1K1K0L+U1K1K0K1L1K@@2K1I1K0L1L1J1L.M0K 1J1J1L1L'N2K1K1K331K$I1K3M1K  1K0K1L2K7I2K3G0K1K3J1I2L-K2L0HUU1K1K2K1K2J0J1K1K5J.F1K1K3M1K1K1L0J1K}   atRNS (>%ʀ$8|]}6V[U9or!Y\/{-Ia 3bH`1   bKGDb+<   	pHYs    c   tIME	M  ;IDAT8˭V@'DAD%X{EN&GٽΙ%_MZZm_L::+J[UBo{¼#uhs=cD8$LE~&Y#D$2u]|qiV իX[q.q6l9zyyE&EiÏpNTA`uy\XpS/8W<ׁ׆/\iPxHAdɬ mF}.ހFށ?wď\Ə=~~zOq(Xv'B   %tEXtdate:create 2019-08-13T08:05:09+02:00fJ   %tEXtdate:modify 2019-08-13T08:05:09+02:00;R   tEXtSoftware www.inkscape.org<   WzTXtRaw profile type iptc  xqV((OIR #.c#K D4d#T ˀHJ. tB5    IENDB`<?php

declare (strict_types=1);
namespace _ContaoManager;

/*
 * This file is part of Contao Manager.
 *
 * (c) Contao Association
 *
 * @license LGPL-3.0-or-later
 */
use _ContaoManager\Contao\ManagerApi\ApiKernel;
use _ContaoManager\Contao\ManagerApi\HttpKernel\ApiProblemResponse;
use _ContaoManager\Symfony\Component\HttpFoundation\Request;
require __DIR__ . '/../vendor/autoload.php';
try {
    // @phpstan-ignore identical.alwaysFalse
    $kernel = new ApiKernel('prod' === 'prod' ? 'prod' : 'dev');
    $request = Request::createFromGlobals();
    $response = $kernel->handle($request);
    $response->send();
    $kernel->terminate($request, $response);
} catch (\Throwable $throwable) {
    ApiProblemResponse::createFromException($throwable, 'prod' !== 'prod')->send();
}
PNG

   IHDR         a   	pHYs    {Rk  GIDATxc`|fK_G~hRfXa 1~O4CY*OO~Ss[#><apg]<%~vH֧a)
qa:ı x2?wU`@"ul"j,|xDP&_8 B# 'jjhcCg.
1  %p^+#PmFNpxv_6d'&{a ac:7+B	i!u,>:NWVRf JȊ$    IENDB`PNG

   IHDR  6  6   뼾   	pHYs    {Rk  IDATxwUՙ/ 1j,q1&j2Klfq̲Rd9zGQE&U@@UO/{>D"J[w=gK%B!B!B!B!B!B!B!B!B!B!B!BHq'2g]g~VeXT7*[%!Zr|^,ѲQ\ܢSأ}~@%^_݊KJg%ʕzsv{]{Zuu]w{Y͇#I2vv[l63QX/1<)y.;8nzdVZM bv?'$5wmD3BHm2j=GHY6iw>"Όq4;.9{NT֕ڠۥ-tRV<T$ݱ|lRyp$o{цR4;>"u;AG'//52w{($GGHu}Nk6O,=52޵SV9)PisNt!t=]l$-KнDHpG5Mwt)¯/Ҵߛ!BG%zMo_kӪ;b*&!',* v)I675:wG!'\91Gbkى#q_)ޔ*Eq}&ʼݮk9P:orjY?SR/B[)㝫mBHVi >˝pߗ{}!LU=*?),)-^k5k x/=l?$ڞ/`qX8F!ǷR.WQMjKi{|ݽv Dµ[;Fm~)wOD}53}@vxl؆x]B$pxq̕>!$oh4_bkz6;!;|7El\AHyjs|k/6uzRE^o5;UF;EיJUl6b$і%əhh'6Y>7Q[ed54!{L;~tM	!RJF;dovBHiu.M}CBC?\H#PݿRa=]BBAKbqt1% ύp1NlґBCb*ؒŸFHk˩0b!(˩bSI!zBpA^ltH淒^%'	ồdjrbzM` r-6Y_8{7p(ѿvղѱվi~tG-9dn/+e7]"r; qICSb݃s%OUՓG? [?{}sGӓ_spObVZ-΀*wbs!6Ä~r?rG6tݒ"{axNlqoKvi;tܠo'H~-7r#6gy@In[·7Q^+36|_Elބ?a4ajɎ7vdqzɃ%t?FlѦEzT#;TחN!%QPM- "V7V:ɺ*%b5G,W/PYp+h@GfxmY.1ɤG7S9b*$N()r-uυؒIYPK#rFkA)ҟZ:C,æ^Fm[.6uRz]bz20_s{HwT}Uօײ0bS<lwx<#<q,+dɚ@+lWlNِG7O^'+IO$ooXǺfI]lΠ5֛(Nߛ0M{1=\33yyo5Bw$;	7MҴ6.Z2ںToN]'y[~.Em(P/?dֳ$k>tkn->=
D\ezy;Z1"tSdP ,EH%K<b-!6uO]՟HLjsld`~o+i?&Ulp(E;'ڱ296Nnɠ@TzeQuQ
ʺ2Zz6pv'GledfbZ<!x1jY	~f;IMlj(I.
\KAW7[k@p A P/;W%[{NN˔'6){ejS[ۓbO_Zς_S*r~s@
J)$=0hUA)㎸#Lu49F,6ښ$1F.6]	1F.6ޒ.`aظknc7È
6p#LʘGWabSSʁ{nSMmLR"M0IGl;E@b{)F<->Іv3)F<M.@1L)'bYA1L)'b;C3~(6)Dl6mM0IIld25|#
><q}"bmj	xc0(pRvVXm?o/j.
0t9.Њd4ŶgZ#*L	~2 1FT.u]ޤ'0&WN@@+9]03@@+xaDb[υ7È
ӏߛn7È
6)zGRT77Zau9F,6wO}0%؜7={0dY.F{@;}Kts00Ylr.[abS/[]55ts00]lі%hhua^lʉhhaa؂Ex00Ylfhh*AF,6w}hh?9AF,6.Mn_0`YC{@;K0d:Rz=)N7	cƵl`w"IF,prIF,6VG{&aaؼvo7	ڡ[abڞ~DA-QF*6+IFaa53n0%؂f{x00Yl</}0d9oC{@;⽛0dh6Xm΁7SŦ;g0d=
x00YlhhGl4YF,6wT#޽,#Lhhz0nMTח2pabSnZvx+0d=jbt00Yl˿G{@;=0d9ÔpbZ.e=3?7SŦm[vxSM0do=vab?v{7abs݌X΃7S&Dyaa-KoJ5qF,` #\18#L7!g 0L	+6uhh|x00Ul0 gaas0%׻=Yaa=+Eӓ0T].Ek@Kabudlvx7cŦQ^9<o &͟NSMMp!F*6hh;&baT❫NWx10YlЎh<x10Yl+~~'F*6Mhhx#10UliIo0X>6-B{@;e0d{=
o$&}hhx310Ulv+5F*6QYWnßL#cd#F,6zk#ba؜!w5%j\0TYmE;@Kٝ0TĻע=j3FkH׵=%QM+65>[FFeCjwtiVf}@{S+6oa_gNe!T
(ck{eqŦv  ofX?,KWlj1OlӉ6opƀTחv5{w2X4h(7BĖf*A>DJՙgKh{by{*`~dܡLqcl$A뾘V[lql'S4?ڿjGƝ>!ڱ?a$iJc2ڲ$u77.De;%VRw'I[\ljG-qG>jI}4Ql^lޔTCኞl9ğӭbS2$}
o'|2'~_W;/Z\KVjqBa?1#?MŦv%Om}Ѧos!6ɗ3NN71,&㝫[zy/z,$6zM	\t7PDٝKmQowkBߔ2\3CJO^hܑ!6v3z<Dm艮	kS07bIqh3\-;I@E'C$߃WĻסˬvw60czHWn&622,Qԓ:x5ltB4=Y#^G8kFWb6JlU
.g˫wU[mMW.6+''*g&&]Z϶vVJCDxѥorb@\v*&7I^̝؜Jip:EmIxbNN,FQ'>\}8T BOZm΁X3HJ^bS"&^c-;mYZmr)67-1O&%EJt)"X<LowŤoYkԗ7	tKiG~ƍ2'X:^㢇cŦt |	EK
j2fmgImSl.^z;í5jżSZ-7nBO+sSQ~Ŧ-~=CcҌ]6SV+bsG5AڜuaRYGF[˦Z!/=ڣ6D׺(QOHX/2Gl*ц72Fr V}h2t#ݒzr/6ZsuÝrA)l>7d48n;ڞ+cwDZM|<%݈{#H<o#cŦΫA1s띷x/]m2T9s#^\ʍOGĦFFkc@ƻעˡ5nJgSlNOk`j۬Vg&ll9CxG	VE~퉶.ͬ:Lǜugڞ+MnJt-$\6:X{uvD1,(؜g~x%ՌzkɁҤ<;WgzFĖ<4䣄kg[S?'zhß>ӺKlb]6!x{}=҈nA}v`3ތ(H~bx9$1z$rX8%ZQMWOK,ڝ<юX2uĖle\84}qݿ\#_qE$jM/Cniw"=ҲQN${JrF`ıWO,YIC,#{{>>^z/=,_H_d>%g+j)6Y/-YV]+rC_C%"wr˥j6;`VJ޸M&xz!ǈz)CulI	[[pkɯPlGmϿ䕼bS	W!8IKiL	!MKM%&n>3>Ĩ&WBr{".ZMT7MB;;ZM8C-!kv
nD!q7ڈMş`K)3іuBu>	ZMş\RB&\3_m \T)Ub$جgXlEטjiVl ΄;~?PlIU}B2'Z?7W1:j/$7[W	}i*_s^I>;D_HV	F9nWF_HV:}'ƅ#y3;-+YB2[gUWBŷr>X/>_rYLdm}h7Q>"}ڿ(A߾}1Yw3O'$%USr>ꄧK
˥;uOUWB%"v,0Z"y}AYjqwA!%
s;;\(bեY>r"%^|.ۤJ`~*![Jv/IY_>$Ey6VF=T*`Ɉy_m5R[}X}8vdKm	1XlvKspq?fI)/-Zyg">7b?H:o?˭O/	=nBIIwOspk;*[ځyYJƷ9ބ?ab?HY1ImfDjOB>]򐩪'	%=7NkN@Yr]@ɹ9fxIJ٨TscSlᲊ;.%F,z*5jKq*B(շy?,CGu)=qu\Vα4~xkv~qU֑~ƔD{6厸w3=}8J)e!B!B!B!B!B!B!B!B!B!B!B!BHisEx}d    IENDB`PNG

   IHDR       ǵ   	pHYs    {Rk    IDATxyUe8ieum2o6?V`eY2ou/,*"((,ȸ鹯gdp眽wg߯^f?ZcY                                                                       !Ԕ惃YܿN{w|d7uVvP>R{-><gi#=[߽7+=-n>qﱉ?4ۥ? &{,ޤo.\u^07|eQqg4#} %pׯg]:+oY9ߛ2S6'TIg F(E.M;NU-?+JEt_I"roKW\U;\ФoK|3}Ng]4.Ա?ܱg .r">3NjC75ЛH-ƜTJ $ݵQ9)>;:5oށmsVIZ^1z; m$yIex7emvL]k't+9v?wwv}[zԻIU`?Jw/ tpAybP*XxZ3or9!0(l]![ N?~bs􋬩QyZKӭCFIEO,U zFy)a/WCy=3
 u$Y5vozTJڏ	  |3SRv􋪕Sy,&}S|3\>3-/:ޡݛ#	 $u_S] Y[ϼÍۡ*t@d?9ԥύRYެ^&bjax ׊! :=Py˛_LG @ѿL<bޖ;+_HGtR#= 7@s.q3-wۥ_H{uzVKg rD&d`A3$WhT@Prr;~!џs@NI{s?V{\,Bڪ;Qq  -H*;z,^4 }%v/^?  ~J귉-; Q+  #zFeb@7dY"> 6,%_ c %yYR t`g#Q zW ߕm/>ӺB@8tn '4;' !P*3 ;[|90Ik" 0drew=P~Q -OD:' `(;s؏z?& 0tFew?L|Q 1|dt> p{$>(  IGʻs %!\_|Q E< @<x :'  %#Z2N~ [. $V') @IU|  ۾+ P|@|( + JNCt qǋR@a dsi
 Wr~p.E-P RU#T@
fZ_PuQ5Gw?*{eTbJ^{A9'C|8_ V*MDg~XoczoW2WáC:RwrzI|@] ^C)I^]]wnrz)A/h% `{H6=9WB-ˤ&$ݹS
Lg
*6Mw9\,)-H^^* ug?NSGJh0gϸpG~Fz]īfgwHf6uRt:Ef7gϤ-Po3]7GpY$]/9c
+0tZ-P7Jo`6[B^ ޤjM~F@7Z*^~
@	x֌(ۤjHE/TcS'̽KBl]x֊\ (k	5"Z<2g^:yQ?Hϗ3~Q<c.'t?Gͣ!~2VڇT@x
] ѳS:H{r}B<y~Jפ
Je(fUIɌvHk:dr7AwǳL!_fwez)̆w㗤:@iIvǋt`W\vfz>ǈ.SIg Iq>J<ETW:*^ aֿ{9^ <>_L+ZdE>$J6?'(ϕ{ǌ.ZO	)kAkgV>S%|.Zs|x@M2Z6UzUE{)!ʟm=V|mlHpgH4GdKOBWp`OP/^v	4uRU:^eăi 9oYT06q鵱Kh@?L!ݵ;~L@?(oYq՘tx7C<eDnv-Q:P%,NTlS&^y|]䬦-Z)U1jCzx ˤh[!Z- u pp0x*;׫h*{e4'b%MtP9cIz;T½*+H_~_*~Y4Pw ن~Nӟq)ۺ@ڍ7]:&.`毕;SU)
@Ӏ|O;!fo?klJ ][|oߓ!5^=uӇ+~i1\ޖMTvC|4&a@%볳ݡ=\?;3@& 33/ۻ#+K
 TmR[o͓]m
 ^p"Zf%~H:|hX g@~qG.>D+l/I퟈R 3GBex2 [SzA+D*<D, }`&!ef{K8h-3 Z<RzA+x"Z3Z!ef//=-3 yy􌃖H"!en;H9h.:D. {Hw"ZjIʳCD߱vCPϖ"Zf(_ h׭ ~V Ѯ[=VzA+P h׭ '=MO-C3Z!ٺB<thZ -=ҝCV./:CV.GyCD qPCD&pz)<De+\^!e`4uV*Mg;4!ey Mx2 vmq
?"Z	uV^)<D-I8hp !efīJ8hh!efD˦J8hŃZ<xhY A3*I<|hX vqP}tt2 9-=ߠSÇyO|
x"Z7fZ<|hW 'K7 !b]
}|
إ֥ *tgB3CDH(=5Bgۺ@v
8 "Z@m*y "e^oPy̽JzAy=yOHzAg&-
s|
$// "Z*n,BD* }s{Ca߲\zA*BD+x]*x2 T@,BD+`e*[(BD+ oWT v-
U=V<hU vJ%|
x""Z>`f].DD+x=*@V){_#=ߠADD˼_"=ߠ= FD* wiA0"eV8=P*MT?ÈYMwmoPaDD˼N.FD+p H(FD+ ϤT"MkY:]zAx?+HD* ב	T ҁDDˬв'P$"ZMR@"e^4K7D*ۡDDˬ&}SzAO%"Zf3Uoٕ%"ZfIv%"Z!y*T<hW :@`"eV_,=ޠ
kO&"Zf;ҳvx02 惕З꤃aRɦ%*{X<hW 㣤T"t!6 J7-
~l*_"ND*  "OzA#ÉaްHzADD˼@~x@2 ;~*=ޠ
ܑ("Zfg#ZF+R v
lN("ZzBH("Z@PH<B<hU H7oCY>QzAY<hU 6W)"Z!9*[Cy>]zA8O*"Zf7<U="eV8}ޢTJ7 GD"ZF*Z t*T<hW 3J7D+!aEDˬf_!=ޠ
2NpG!=۠
Y-
vhv[ÊaܴDzA/-
 Z<BzA8},"Zfҳ[EDˬpl*(XD*lgPo|
@e( 3K7D*CYx*Ɯ)ZD* o7gT'!ZƘp'=۠
-"Zf6ݵAzAvSg eVD˦I7
"Zf@pgT/ĳY9KzADKo
"ZfpXzA)nYADˬ&oP΀wg-
 z|l*@<+hU KgT.j eV[!$
"Zf TyA4惔;Tzs	
@҃ҳrxVMw&~MUJnysG|#ųXd^oVsT@WޥR{k7w( } dJ oTϪ`oUtJ,S*MycP`g ־v=0;֟v
RNt?egb] }/pRSϚ7 ;h 6Re8|WV!5}i4Π xVzݾS`g<A</5n_K?,OUI$C;Ŀ%* v-3ųؚNcwWUT꼪?r~0qN0m<\%5}~>!,nDi 'JP%-`ɮ,ux&`7ujuoyAtz[0=2rA
@N!P`A5}-nz
 O5}~x7x^ }-nR
Cpx^ Q-$޸W vr4D7K>_m|\*wnIx^_ʙq?]O#h,ϔ GJP%ur=Y_EU	P:n½#, IP%{ntJ, gIP-m'lUe~儰`̮C>XaS ѲK U=>Z</>OT.`KTIjo]n'ɖ. wik ,c}uzI:6. }ϱ
ݖA6tlX. 1ܺ[z g;fJgtlvv |_Kw)tdl @	V~I0y
uRI, |h8@]5/Thl=^Q`-t]ּp>W<3Xn@轙+ }.&tl'I`:-h8gp9B7L`z"htKu[Exxfu(ko݋X @
(X``s DKoۺ ߑ^h#`6uVC:"^u[B-=Z0UsW5ş}!@ #Mݤs̼L:
oZ gC5^=W:Im[ ބ/A>Iwm䠘8<;nIa@EŃ%VxŌq@/m$~?ԷB~	 Jw'ĳ{/8@+SPZFJ`V?(B@`)"qO՜vH]3P0"LųSfݡ'bI6<V 8Ǵr+=yt@`
vkSFgM6-^+hǋl]/P#
 ׳rHhx~ʤ.\H-Ƀ>	y%88F*␃'* Ll}}(;\<G9~/+nH&( [:>G:CF@2CxcА\S Vl]92U
B`0
`ﶶA`Rq(P%Yˆ1Y{9şm*ݱFzYװ|U ?m9$l@lwH/)7,#F@vX|{1xecSzj^eĨkK!Ԁh,`毥AdlcsbZ.o9$y*z&9p]L!M3U$)gsLCb\h>`I\."=_~
L҃όe HbOH<W
'JA~Yibdg$qGVwT<[yMo\/+Pg+/bP|doXzMNDK5l\g`W13/ɒ<&ٸ8K:gEl~ZZ&wH- mljM	ETKs֨s|q`񚿈зn[=tȗ~N觶etĩZD`Qv7COR70M't(] zCGJ/14t{Qq3wmyDOM͜^kBJ4[挎
vr9GH"Syng1}
Rk/HC DsS@CH=*zvt=@#>W9 l,E=ިRzCH=ZƜqS_:Ud%s[gc9
@?x~Vnl~Jūfgkz`U?eY=us^ A%*=KU SZ  -]h}a ZCW"=KY 0  &O Ts} `_
, {~ wB| ^o>l h8%w["P  UIDAT Jg JFpG[B?; gDG>
= lC MjoQNg//' 0߈:
`?N Lcmv2 Z0~^ ~$>(V  ֕?3 x&>(*tG|CfcH   &ts{ga` 0]'n@iI^{Ae@;ԇs7 羚ϱ6;-ɋ  !^1xnA-3DWUv  IP΀wϯ6.^/$O<@P|n[1g~!y3^3_:S P ^ɦ'&Z)Bry[hIg rL\Vy.T^ay7/& oszӭmGa7$rgCTut  DKϨ?WJdiܡ'm~Ays&O>|9O1~i
`C_P^@y<?E|.u7N.{x1{N_XuzI;K r?QRX3S_X^&|E:w  LDYQ>Ǩdֿ;`#i&槲['PGqRGS _?9WUُ? P.Ror_|uTw臔w]a#G/4OU*wO@)Ha:h]RX {/}'X`ґ̾B|Bi/86uRҹ:>vޘ
Zբ'>#h\'O s3 YQ>kT=^WX9׼g? `8 I6-QNË?&(:YaKu3}˥!y5{tV;+;?GF{/KG_y> RU^{\K#eoUKa v;DkHg :x[=~~ǩpɍkR{	4v;E\>^Cb $w+wisv;D3/RJh՛s3%/?o P B']z~ww槆)3q2y$OmǟY4 TCeBG)wIuO]/VJF?7߱_tF|j3C>oo5 TA@l{<9?'&}g`^Ei#U蝛                                                                         `b쩶    IENDB`PNG

   IHDR  e  	   %ӹ   	pHYs    {Rk    IDATx{uAYY4SV^rF2	/55ڤ45499!D.@**
qppk"Г@pYk7]}/{*    ,'   e    D    Q    @   e    D    Q    @   e    D    Q    @   e    D    Q    @   e    D    Q    @   e    D    Q    @   e    D    Q    @   e    D    Q    @   e    D    Q    @   e    D    Q    @   e    D    Q    @   e    D    Q    @   e    D    Q    @   e    D    Q    @   e    D    Q    @   e    D    Q    @   e    D    Q    @   e    D    Q    @   e    D    Q    @   e    D    Q    @   e    D    Q    @   e    D    Q    @   e    D    Q    @   e    D    Q    @   e    D    Q    @   e    D    Q    @   e    D    Q    @   e    D    Q    @   e    D    Q    @   e    D    Q    @   e    D    Q    @   e    D    Q    @   e    D    Q    @   e    D    Q    @   e    D    Q    @   e    D    Q    @   e    D    Q    @   e    D    Q    @   e    D    Q    @   e    D    Q    @   e    D    Q    @   e    D    Q    @   e    D    Q    @   e    D    Q    @   e    D    Q    @   e    D    Q    @   e    D    Q    @   e    D    Q    @   e    D    Q    @   e    D    Q    @   e    D    Q    @   e    D    Q    @   e    D    Q    @   e    D    Q    @   e    D    Q    @   e    D    Q    @   e    D    Q    @   e    D    Q    @   e    D    Q    @   e    D    Q    @   e    D    Q    @   e    D    Q    @   e    D    Q    @   e    D    Q    @   e    D    Q    @   e    D    Q    @   e    D    Q    @   e    D    Q    @   e    D    Q    @   e    D    Q    @   e    D    Q    @   e    D    Q    @   e    D    Q    @   e    D    Q    @   e    D    Q    @   e    D    Q    @   e    D    Q    @   e    D    Q    @   e    D    Q    @   e    D    Q    @   e    D    Q    @   e    D    Q    @   e    D    Q    @   e    D    Q    @   e    D    Q    @   e    D    Q    @   e    D    Q    @   e    D    Q    @   e    D    Q    @   e    D    Q    @   e    D    Q    @   e    D    Q    @   e    D    Q    @   e    D    Q    @   e    D    Q    @   e    D    Q    @   e    D    Q    @   e    D    Q    @   e    D    Q    @   e    D    Q    @   e    D    Q    @   e    D    Q    @   e    D    Q    @   e    D    Q    @   e    D    Q    @   e    D    Q    @   e    D    Q    @   e    D    Q    @   e    D    Q    @   e    D    Q    @   e    D    Q    @   e    D    Q    @   e    D    Q    @   e    D    Q    @   e    D    Q    @   e    D    Q    @   e    D    Q    @   e    D    Q    @   e    D    Q    @   e    D    Q    @   e    D    Q    @   e    D    Q    @   e    D    Q    @   e    D    Q    @   e    D    Q    @   e    D    Q    @   e    D    Q    @   e    D    Q    @   e    D    Q    @   e    D    Q    @   e    D    Q    @   e    D    Q    @   e    D    Q    @   e    D    Q    @   e    D    Q    @   e    D    Q    @   e    D    Q    @   e    D    Q    @   e    D    Q    @   e    D    Q    @   e    D    Q    @   e    D    Q    @   e    D    Q    @   e    D    Q    @   e    D    Q    @   e    D    Q    @   e    D    Q    @   e    D    Q    @   e    D    Q    @   e    D    Q    @   e    D    Q    @   e    D    Q    @   e    D    Q    @   e    D    Q    @   e    D    Q    @   e    D    Q    @   e    D    Q    @   e    D    Q    @   e    D    Q    @   e    D    Q    @   e    D    Q    @   e    D    Q    @   e    D    Q    @   e    D    Q    @   e    D    Q    @   e    D    Q    @   e    D    Q    @   e    D    Q    @   e    D    Q    @   e    D    Q    @   e    D    Q    @   e    D    Q    @   e    D    Q    @   e    D    Q    @   e    D    Q    @   e    D    Q    @   e    D    Q    @   e    D    Q    @   e    D    Q    @   e    D    Q    @   e    D    Q    @   e    eF\O+Ww_Q5jE=~Ri 4JԽf35N˻'/X]O<7FQ]]Vh霸W?lfܟRg1  `T5alx{_tHbWseFJEN\ Xt7=~/k6[=epʨP'ez5'=0?Yl?{RY ,{fs5LގdpɥelXz_p^X܏Ok  f0c|[[R2f+ԃɟ'xujץn  Š]~׬IkG~{Y2Q~>msەp  ̸pYvJ>>34Qf+ˏ*Ձ/mecg9  sj{tz]׬[{_aL28T$i;Sg:  snܹtU׬/՟t(SqIi;8R_fT !_5x#^S]TDQtO?Z[> hA/5y+/3:i1QfpK ٥Է> hו5}6VJӣotN+b27< Է_4.C͌2ÛF<[S7: `_a>EѰHVn[3/.i  Of'o_6RzF29o57dnr  .Tʣ(Sɯ֤ sr  U;YytOz=p|EMjĿ֐ޱן6  lYCYylw]5Qfp屓7՚;wN_  Ϩ.$/mfѵm&3e}mj2椥< `i:ͬ<;f3/\ZÂ̆: `ɍΡ/[Yylv((ӿ`7ΚO>R  fh}fV3מ<Qao5j[  b۾Q}6֖_ze=dlY7~y
 TXxDVfښ]֯OgY(F&Yc?{:} `~@Z[sK}ue;(gſ9֜NRƣ8} `j`Z[wOG=p{XcݰW)ᢼ   `{{p3kmo,eGA|maY72n  bQ{q3km92xo`YN.H  4n+/ߓYk>!e:.[s+ʸ}6  0z[{JÛ7ʌTkw֌~  @?ͪ)[חR)ԃ0E[3^{maNn  Gs>O7uDP|WmՉ  sLǽ5~nfo6ԛo(վ;Xk	}yO &w/~5nf-|:uKeFui&+  <ѽJ{߿YytK?4Qfp_5cVm5	  /j{x3kMJGō2CZG_Qx-%  hEͬzgQQ6R\  z;~?ofGMeFR;(u>2>#  hAtUZu7cqL16k2~Ÿ @c-SlZEK/wkv-]"  hz9Z}>Jwm[鞲w9ުJż @_7H뻯ۺ(3zɛĿ.R\  ƣ=~Jm]}oi).?  B_}Yf2}zQf}Tkwz{פ  KgtוwY׿pӋ2K>?h-|L_WKy   fM_З2=(>7m󷅏R_w  ;}goo<(Sqi`mzR   ?i-#^&0kzgE.~6^~r\n  19sK(3jZ,  x<>60kɣsi1o,/  xB~F0kzgɣL@"}/qy91  K?+5q(eT?AJuKis5]W2  ݳTkv?3h껮z(39ړ  )^qtlE6ce__?8_   OCԽfU=me:yslݰW)Q  <Csğ!̪m}e2Tk?8-aظe  x:Fw^Q;ş%̪;[F+eg  `+.>4<aV5hë2/dl} `Fǥ{g
!럽ϖQ{{e9J^B  m4)?[UX7meڟAlskK  `ן0A/yu*a?(x^k  ,0+˱QkUo?ܮԛI_3  E~)ab7k5[+^   KR!aV0y?u  ?ǟ;̪9&Vޑ}  `)Ճɇz?̪9]ՓZ{٪J}җ  `X}w?u  1pzkxu`l=mGk  =~Y5gKUt}K˸s_r   {NĬu{ժֽ ~06[}o }   W61[1?~&Vxړl  [3Y5wQf.U    IDAT\.  S`mnj̛'ƦpkUFޘ  LUVǽej-gH`l6{  `鸷ğW̪(cOIH  [K{-fO]+? )6Y5e	>w  `ڍG{aVDHG;  0#>ħjm1  <]o1fpޔy  ̚Q]:G&Lcb&c  RzFƬ2ȉ?N .%TE.EDE5(5^zyQ,gf2-=!BB2e3)d=63}s19{sz^p2Y<sIF_	m !2Wb[$IҨSm׷8GRãG$I1{I;#Q_3[$IҘ8#Q꿶y-I$i̚3j_@>e*saѳZ$IҘ־t!(SQ>RQDiI$IZbs $I$i.=xUlA>e*s͡ѳY$IREj!(S~mI$IU4קo	߅ B2R[_[$I4u;*||9THCg$I*Vqȇw"ȇLE%I$I^0e*UXw_$ITZ?A>De*}^ѳW$IRQ2նCps>R={%I$iI	Gqp[sS̕$IM}/D<G1Z0zJ$IսҔϟ3AQfL:Y+I$Iy_MsG_^=c%I$E+?j_?DG1<sU$I6YeeLmIE*I$ILGAQft=,zJ$IҴ|byG18C)EL$I5DSp6OG$I4z\#IU(3&Zg}-zJ$IR5
9(3j;h*g$I$])sQftn<.z~J$Ij~rq^+I$i\*O߳ #2lf^+I$ij_[sQf!z^J$IRu[-瀣̈-{m*jGKI$I*ǆ\Gվb9)I$ISQAۄ]2GT=)ucR$If|Y(3w=%I$ikY(3bGA\$I9ɮJ>eF#1z.J$IҜ_b01;eFH󻟉$I4# 2bVX@<$I9yd0Q>G:o~$I9ʌoLEs}$IZg|%|7d2#}~O$IB+jڒWgQfv{GJV$IZMhQfu?:zI$IPT4֥ڲׅiQf^ܓ$I}%qb[Nw$I4\T%pR>RQD;I$IڗA^G!ս9'I$IYj;%|o|@2CqoF8I$Iڗ}#|w|@2C{eM$IvݻeHQf4Hh$I}.;p2{.k$I4:Ĵ8(3DNH$I}}r"{.g$I4RgRm7sQfH4&zI$IH>QNyeDsL$IF.Ֆ6||e$Ij7?||e@Ӣ$I$tET[p	VgR*zK$IF9A>2:=$I$i,*j|+<ȧQ&PmmG-I$IZ9|׃|e;z^I$IXU? G _R+W$I4v5T48i(zNI$IX{五ϟA	2m5*It*?㷧CW'LSwT*K4Uߏ`be4O$IRA{Esѩ}u?w258C{Sm׷ڲז/HeK=~*5&5<uDj3uv{I*~8#IӺwA	2sm[sS|$Sv=Խ^GjũT[uoSm{ljGuW^߽T<hWV4{s&^\$IxyYu`j8cR`lggOtM[RuKHFǆ? G9ֽ$I&2=?<ᯧ~%_Ysl(,~ԯDMjwRK4F&6Qf"z,IN3u4/156vxc3klҩԽkԯsI_'Y(3&\OxV,zOS%5v?IsS釢sKkRm>s#f19$Ix'M'94%~S¥S/C$UI0eHC9xꮩԘ_~wL▤jUԟLůA2s1uNƻv=uwfj;=l܂R㰏εM:$ik-|&~\|}$e|S?J?oOm֩$IX[<8́ˣ$OJuT1SϾlKX6ȟQfv}[Jn$R;iI͓vRRQ{"O$ĺyefY$zݒZ9v|s?:R?2*Tȟ(3n|Mؑ$ͤn+un8&5pspg_Ơ{?W`Y2y'$ikIs}V/zIhV4N̬qV$mbDl`,"5Ol*y$O$&55Y2[WWV{tuS\Z4&1_Ysk8̎Ol$ߏ+/%ve:6IIh8p_FIsSkT[gc/WF$M]+p/=_$Iǘu_g`:RX- ID>A2GYй"I?Zg}-۽,@#$I(SOflji%;ڲ׆?4T<pw$iC멶ßd(SGI^E/unN lHmkRgՁ):	r)Y3E*UsS}_0#>FHW;R>^3eJT]>
S/P/V0S?&߽o!Ij;Jr)QEѳDƿn;/K|yz]:7\ $G̟%4u0zȮ[sS$N~4@V92e}!1"Ic[̣yg=̆ڒWlIZ{3reJҹ"IWQL}b'Dym_ZIRLSw'{1s)ÂS!4VMQ?a5&<'IqGßd(SFI:7jۿ!|CoI6JֽJq)ACg$EEs}jm:-)Iիי:?HU(3[d萤wT]sHO[I4wV,d(3mg$vnj)_YLa<`IÊL74zÙ:=3$id+jO>a5ݩ_$M(|U { IR\jY#/釢u%i+kSkłOV	2|y!I#YꃧsFMm׷ޓwDKi=SJ=ޝ=Ye8sa#DFN35OR%i$++uVZ)5?9k橨==S$id?aԶC=tM${7Z[j|SmpwDIzkn㤶թ{ߥޒ4ͧSKR{y_nӐOLڗ=w$i$sa-{m܆{4u[}S?=0Q(ӏRQ$IC_6̶E/Oݻ/vY΍8rCF%I&|س'f8^xԽuyjXGnjۿ>~qC¥ѳJZc-}M=tuiW4ק]+RRj;%|B>e{%IYQχiaƧ2Iz[s?D-L8XmZ:$I/扟PuޘzO|/z"HrEzߖ:5ӳȷ{i||9PE8Iz<hY;^Iy #Qf&$&|>?ϧ6zBH3{%S/8> a23Rjע$A3AoVJf4NYYl|8uGǢ$OE #y'$I|Kz sMt|9@G$M5|.:k#CҐU<9o~j

rGNIW>\u@U+̟>Qfj-zJPԹ#h{׊"i8h/2~iCeygǫ$׽ou~W>|gM4un:>zJRhGK`{T*OEI}TkRRkł!mdqd;1P_ {"icy*pɒWYuFOIU=00QM201qTZg|%|`<-=0@Gi|$UG``Ԗ*=jh{א.156vxc>GM)ѳ\B^_"/m9xmCW{QfS_C>=%iΛ|ym׷``n4#{`>u>$5OT})_y3GM=OIZc?>YuPF=05߷@6e6{_5^ v/EIiWq~"v|S(ƑxU<uw-:~!{;ͧG4y0Qfc_C~3!IsWћzVb5Oi${`ܔ:Hӿm3w@VY2:o~cC.0:=R*ݗ:7Zg?<2 GqVsDn>w0eVSSo_$5TK &8ʼ/IEc]Ef^715}!:y qy}9rF(i⩻^ %py_~HҬW<ԯ)D\`HmR9xԽuyjXGnj^ 01;e^D纣G45y>MӌWӊԽԾpijTGsQEk~FIҬ6Yֹ=4:8ɟ	Gcя,I:T6O\^=vK\{xjT)_ee(c41&I;g-0mE/{`}Y|8l@k4kgRm7Z`L.R|:u$W1qԵg Q2нkENf֊sQ~zy@M2/4^*4+T[Y~O׍g"5uV+NT?Sg c2/P4kNRF_oD3P/xl(+IX^	c+R豦O5?G $Gh3)IRυX`|4xXӋmރR}SO{ry}E?F%iV%/*|{IMyԹȩ_Q)e6 ȦQ/m=hKlSxԽ:o"5T[? d}sy?k׼5=6ƞg$^+0lz=F^'ܔ:xא{l4eg %iuS}wW`5i7rO?Q8h/zyG 9(<N~>KRunNlarh{S 8rTG{G=~[3[J~g+P]ޚR+OUo=0\ڗ쒚~"v}[ Yq
TJL{ëSgՁ{ fQ9~%.I<^!?4(GL$ӏזl>[qh{/1k@6ve^G_J
TyS>9Ru۩S<*z% i9<{Ҫ
TWM57#R/=qUs"HR)>|to;5{`"k se&?q$Vk*@}ϟt (3E8sIT[
0s7(3Y_0Hֹ
_&Rh>]{`!u>$5Ol)_y? (38/45
|&{!	@ &ƓO^4&|0|muj=0t'T%29\$ivy
!?8Uz L8ʤ|Tb7)I*z 2%/|[ `bxT(Sg(I*c`  d#Gޥ$i|  d#G֙KI5d<  Q}ѻ$VjK_>O lF*yN:%IսY
  d3VL$T  @6c>,2^7zy
  Qǻw)ITl>O l*}i|ES4PN  @֗JeZ)zjY
  d}Qr}J/R   K2[Nާ$Zyl>K />\RIRu:/|  Y*})?SIRߵ/X>G o=,,^7zkY
  ~U(S-$TmR   [e2~%z+jQ   He28z~9
  dQ;$](  Gˢw*I
  @6e:SIR9
  dQ{;$WKWQ   He257GUW{g(  G.z~z  U(;$]{s  HQީ$Z9|  *yiJq(  G?SIRyo  U(<ow*Iڒ(  G֙_ީ$3  JQɣLe{$U3  JQɣL*I  @Vjen<.z\sh  RT(ӽJ}3  JQɣLk*Is    IDAT_  @VJeDUWc?>C <4EUWov  RT(p"z9
  2T(SM;$]m>G ;JUs  JQLmw*I^'Q   +E2GAZ%I}UԞ  @Ve~"z=yG  T(s⧣*Iëg(  rG/DUW.  @VeZ^%I}ս
  dQfłJ{
  dQ}{$Ucg(  zG{DUWk  @Ve:ޫ$W>C 4;\wT^%I}5~3  JSL擢*IP   +M2wWIR_/9|  YiwJjg(  rGރ*IKg(  zG57GUWP   +M2{*I֊3  JS*Iy3  JS3DUWg(  zGJ}
  dQD^%I}վpY  T(S*zj_c  T(\WIR_/5|  Yiwi=WIR_/F  T(ڵJ}^3  JSLWIR_u?|  Yiw鶣*IεP   +M2n^%I}չ
  dQ(*I-'P   +M2ETw;Ί  @*K26ީ$\?G TjenSIR*~  ,:lJs  HeQff;$];(  RO_EUW3P   +M2V^%Ig(  zGVVIRM~\  RT(S4FTwe  @VeǢw*Iڮo  @Ve~(zs  JQ{w*IAۄQ   +E2'ީ$G|,|  Y)wyJyܟQ   +E2SIR5O\  RT(5;$]  @Ve"zk_k  RT(ӽJsas  JQGTw[Q   +E2SIRu4|  Y)*wt|N%I}{9
  dQãw*I"_>G ;ʴ'zuR>^,  U(sN+$Tmkg)  rG֊$T}wR   X2gs>%I87g)  rG)ާ$iY,  U(s_ES4PS>K l`;4}J}Y
  dQ氏DS4PUR   X2~=zrr,  U({)IR   X2D>%IU<uw,  U(S$V>K l`;,~e:%IW[y
  dQfR궣)I^	  @6Je}JjrxGR   H%2oާ$i'Y
  dQˣ)Iֹ>K l <to?=zj_o,  T(ӹ}J{  RɣL)Iރg)  GES4PR   H%23OI`)_y<  U(<o)I?>O o<4]J~௅S   [52mKI5y
  d}QDR4p5|  Y*y]J}>  _%2-w)ImS   G,g)Iޣ7R   [u2OOI@  V٣Lˣ)IWS   Ke2[Nޥ$i7|  Y_*{:0zkm<  T(Ӿ`q.%I:  R٣"#I^)  G1KIun:>|  Y_*{i]J5  R٣L?KIu  R٣Lmѻ$Rmg*  Xe2RKIy
  d3VL]Jy')  X2ޥ$iZg=|  ٌU(ӽuy.%I׹y
  d3VLꃣw)IS   Je,ޥ$i
  @6c>4O]JIg*  H2# zR
  d3RL}EQTJ>>S lF*}m=JJ3  fGI]ޥ$iڗ}#|  ٌT({]J{i  fG]+w)Is<  Q]JN-g*  M[2FRTJ"|  ٴU(<(I*  @6m?46zRj3  ȦGGIR)/+|  ٴU(S{$R{gT   e&v-z=yg<  isRER4xnn>S lZe&ԽkE*%IT=3  ȦQf"KkGIR)5
  d(3y{$<  @6-2Yj=JJs3  ȦQf"K~=zR=|mL  iqRmޣ$ڵTy  q4"#IPm׷U   mszGIR)5XL  MryN3(I*֙_  @I2i_o%IԹ
  d(YGIR)u4|@I2ig{$RQ2|  &9<(I*o  @Q2ϩ-{]%I8s  6Qyƺ=JJy߇T   (G=r]%I^gL  ry'EQTJ;	  @Q2Ӿx=JJX@L  ryw?GIR9E-:|  ًryGQTZ?>W E9<Omޡ$'M\  (|祢t%IԾh
  (WGQTJ[N  @e^sw(I*㷇T   {Q2/оpY%I|U    Gh5JJφU    G~A&zjgs  6Qj;1zj7?|  9l@XGIR)un86|  9l@U{$R[g*  mtv%I|Vs  ~_FIRi
  d?Qf*zj
  d?Qf?zj_[\  (!_RQDQTJ;ύ  @z!GQ/zR*g*  Gѽ=JJ*   G^G%I8#s  ~̋hJJuW*   G;$V*   GQGw(I*CׄU   2QԞޣ$:͔/<|  9lDK(I*?>W e6s;$V?  @}21i%4./\>W e69c;$Vs  ȾQf#j#z*>W e6fKRjע(I*H  @(	^$(|  GM\wd%IZ
  dSe6uοEPTZ  @6QfS_#ޡ$]>W l&v}[%IU4Ny  e6iT4GQTZ?[ (3WFPTZ(|  ttVCIRiΛ  @(3ӿCIRiun<.|  ̴Hn%I{
  d2QM;$WE[V  5JJ*  T]QfzwCIRi5*  T]QfzڗCIRi'| @5eyw(I*+*  T]Qfzz%Iծ|f  
sWTk$V}V  +QfFPTZ*| @^a23нJJ}ns  
sw(I*U  +Qfi%IU4֥|
  U(3CIRv{gl efbT4GPTZc,~ D59P;$Ves  rUGPTZ>W  (Gj;$V	  WJJ[g+  (3S_Rыޡ$Gn?[ `ze{JJbA\ eйJJ{w*  (ӇUqXw_\ eJJg+  (Ӈڮoޟ$}$| @^12?/;$V  0Q-2}}A%Iչ
  y8};$V*  (ӧ	CIRyE-:| @^!2}s+$Z  WLlRCIRiNrl p@+w(I*εU  +Qf ޡ$z\>W  G4Ol%I|V  p@}DPTjs-z @^2e)u;$VV  G!z\u@\ "eY}D%I{
  yE8uWw(I*N#  W̠_C>BIRy_l eT[uJECIRi5
  y8ʔ;$ @6'eJйJJs  
p)Aޡ$/*| @>e"~W(I*>[  s2CIRiN
  s)Iۢw(I*oU  ǜLI:CIRi%| @>eJ:㟢w(I*H  1GF
%IoV  ǘLIj_RCIRi
  s)QoM;$VU  ǘL:CIRik	  1GNJJg+  cQD-zRk
  r)v/Kێޡ$Z+V  O2%=r]%Iս
  r)YCw(I*"_>W  S2%k-|%IV  1(Sޟ$Ԛ  1(S[mEPTZv  01~efAkw(I*]U  ǐ,:0z*g  ds͓?CIRxwl |8̂~?IR5Tl |8̆[iDPTZ{V  /2;$V*  cQf7zjק~
0z @>FefI󤿍^$/| @>FefI}FOTj~&| @>Fef˂Rj;$VgՁ  &Ƈ,|1$K  GY^g%Im|V  1(3'M
%IV?Wg+  cQfzO$I:g+  cQf6I*w(I*oV  2{׊JJحs  1(3mCIRyE-}Ml |8?^$Nl |8̲N??IR
  pw(I*U  ǀ|b%IUk*  cQfz%IV  (3_oV$I_V  G-~eJn%I^gl |9̑ޣ7FPTZ  8G9ҹJʫNg+  #Qf4O\
%IV?g+  #QfIJuWg+  #Qf,,VCIRiun<.~ rC{/ޡ$U  Gj_k%IVg+  #Qf5d$IV  GIJ}  (3Ǌgޡ$\>W  Q2s{Jʫ]Kg+  #QfΛBIR
  r/?IR>| @>eXmkR*JJs  (;$V*  #Q&@gw(I*H_>[  12ZC
%I8  (~DOTjg+  #Q&-S4w(I*Ό  01Ze2z*k  d3(}^;$Z}ϟ  G *zRk
  q	R$Zg+  #Q&y=CIRi^?[ `bt8qV%IWV  GLW(I*!  G/FOTj>[  2j;H$Iֽ
  p	V'z*~8| @>"eun86zR
  p	:$Z?   G (zRk_{l |8D[zJJw  &=:z궧ѳ  !(3:WBIR5
  s͓6zRk  !(3{\$Iֽ
  s_JJhm  &̐}~%I6Sѳ  !(3$?IR5O\l |9w$IY
  s<zR++| @>eHJJ[g+  CQfto>)zRkg  !(3DZ[$I־  !(3DN$I{pUl |H9ڒWTw(I*^'2| @>eLo+$OFV  ȇ̐\sh$I:o~l |9)?IRu8+| @>eL}_ޟ$Ԋ/,| @>de-Rjעw(I*>  01\ePK'I*֩_  G!ԾlIJsg+  CQf5IJXw_l |8nޟ$j5| @>DeT??IRM`l |8mEOTj+  G!:o~$I{xul a(3~$IWW  ȇ̐-}MJEBIR5
  pboޟ$/
  	G!YIJ{y  !(3Z~1zrk)_y| |8>IR{| |8[ԮGOTjӿ?_ `"̐ݿ2zRx\l |8='I*g+  CQf5EOTzod| <̐IJτW  ȃ9ʌ"_?IRu;2| @Qfto;-zR+?<\<x51LNɘՌ1FdLbF1ƬΘ8I@}A@AvdmVeϩ<PFd{oUT}>?${~oy:uol$I,ejP缙'k~G$If)SZ} 	`ڧ|*|J$IY`25()ePV>_%I,0KT[}0TVI$)R&V}0tno$IRLM|o }_WI$)R&5}w=4|J$IYP2ui)uO CU>zg|$Id)S{.~|$IRL^{еO*If6K=2O]?O@25}OMO    IDAT wU$I/_mj9irz*zM>3?_D25*큗M Q=|J$i۽,xoOυYԬ2[;$wyk|$I<['?t'SSbN;KL]i*IMR{ڿ뒔z^<Rfu_2j]}`|$I&&d$
]#Y>0 xU$iWi|iLGd)S_RY` K3V$i31|aM;-ejXnMA	$ISsn3UIﺣFY԰#/|J$MBoKU׻[D25󕿉>/ CW5|J$խSˈ,ejXswGW)|J$>0E?M}cK }XI}u+ya*,LM+< ]}$IR7^?u4M7R;U`ko$I#oKyLӬx,ejWLLo$IcHN)#* K30>>c%Izǐn?7n
RMgнb*I);>P^<לRUn73"K׿`uWIg>0#U>@q@25ss0.?>c%Ids2[Lks0SG$Iӓ+GY{]D$i2˷œC:whl=؈RDѼ}ufQ$I5oϻ񏗀,ej^og`${3|J׎~Iæ񏡀,ej^+}t F>c%IRM31/_X^;1Lk0o-|Jjou7ʍETa؊^,"Kt0.{q$IǐNLd)3\}| FuoXI4M=XL@`u/>|J>0<lqg)3Ox+g$I_J>:-~rT\6]}v F^EYI-*5'o{QX}`;e /w&U?$aiEd`d)i~o9- D}g$I3>K?_>B #Q<+IҴo:O~i|LRfBjG`d>g%I詯]*ޔRYD?33̤%)c0/e$i>>cC5ug$"K	x`u1ǆXIj}sx^egcRf]o92_<OI#lo?KYLP<Ls$>0Lh
Rfjt9+IR}`d;7.KIjf0?g%I}`gz3̄_sFY^+e˶
$|Kvǐ`O<~.#:D%i9+IB31~@̄:g	`d_)|J,Jߑ'~"u/#\>x'?YLXv/u&VqUsV/*)~#|Xe_>g%IYR_|#`Sό01?YL`>O #>sV4}|u4s>O #[}D$MQw/L7~ʃҿ9Ȕs$i~z_sflRfYcg
`d+~JъM3>V2OYLhω>S #9oq$U%?}`:O[&]L	RfB^<LLoYIRu3XgJD2ZF)))V4_ǐw6{ϙ,e&e>+Lq>k%I#jLϞ,e&bݭ
`dz>g%IC}`RQ@2\âȔ|\$->0C@">3
`{\$=wv/}`6>TTχϬ,e&^>W #9_g$-̙8jbO@t7s, KInfT>[ #ӿY+Iس׎~Z j}'g[@2^h{׆ZI4~ &L菆Ϻ,e&KHMUfo<apcuQk/"K	uoE-p\ڶt'?tSoX{SJe=ځ)gb@2ފT;k"|JRw{ ⏆Ȉ,ekHY+Iտq^>7#} F{nVa $[>HnT:g}>z4l^;|nFe)3} F?>o%*ucXde6|nFe)3%} Fsg$UUGeMV-|nFe)3%n86Tg$UM'FeMVM܌RfJ|oh)VP2&ya܌RfJjs`fol=o%
^=6Y[ͨ,e%DY[I@{G2&]{X܌Rf~nYxʖn>o%)mFdMֽdU܌Rf^,\G1tBRfj0r+Y-ѣ`Nڧ|*|vFe)3E۽,} F|,
UswFb9i̔U<:\s_UEa9i;-e7>o #׽hy+IQX1|vFe)3eOxybMVc`N^>;]} Ƣ;g$EԽd~}Vn7\χ[Iw1#`
YLa>w #׿V"ɦc-KsG;+˔C3W]	fYfgT2SXswE;|g$ɢ/&|r܌Rf[T>{ #7E0'+YLiΊ>{ W)_m̕qѓ`N:/	YLis5E4},zI>;#Z7Eg$Y=vuggd2-S`~wz]ܕ1Խb0'ͽ>;#w^} b+iz93zɴǳ9i>s%i=r6]E32K)uoFAwSë$%/\ E]sql2S굣!XI;G-F̂w_}Ƣ3WFY먏DZ9xB̢gt׽hs0eۆ]IUe,8K)u!tsWFUꃢ,tٙg)3+^Rы> cѿ+Iҁiٙg)T{EYL.o4)0'C>;,e}Ʀs$م3@43RFuEE):|JҰk
07e[,z~[(U0-#|J0ѣ`N	YѠg`l:/	4z7=Z3@2Խ|3	06R6(|JҰ*VhggV,e4}FIj+ICi)
0'YhP_0-W>{%ixoH>?
d)W`)[+IsG*U K=U%Xh앤ֻq
0g.oYSOs	0VN
ЊGSwSdU K=Ur	0^Nw|Mjj|U$K=ٯ&*|J|k;c`w>?d)ջ	0V>{%iu/\=Fl3z~fRFO}ei'$ͧw. s9Ϭ"Yi;璁ӽdU9)u#`ZG~]\,e􌊇n> cUn|(eK4ZjRnYn)> c:WR sW􋞡YE3jc
0v[N4=:x3P2zFv/Kߍ> URr,I-S=9Wgd)gm+bM/_IڔZfЬBYY^<]nMf`Iz=2}ghV,e
uo`Iz 2{=C
e)go)u
0v<;1 9U(K=go-_o
\OI	0/eU,K=g>}fBt,IUc$~3|fRFYs> !Jْ$=Wa7DIy><~.V2zf2{8h9,I?PFGyOs4X2zz7}nBojw`Z} |fRFwLHnoÒT3r`Uo4^k:W"#s4`2zǾ}~¾1_9,I.s4`2zzW}~tNlG6={tq> LȷCѳXt:䷢!?giV,e;>> aZN,49$z,Hs_Y&U<tC簤)nV{\VYlKe)M/Fc8e{D,4)W`fRFTEcPŒ-E@|r,*6|Fe8vWn>%MWsk0:/YE&׿gs`c |fRF\> oy,iJ,}'z,XRF\swGep>>%MG#~7z,XyU8Kdk4@r})[eL4ujX_	Yќ]wd>SXdzKJE/z,Xe35p2S?}oOْdI[ѣ`(ZG~(|fRFs*)E>3YdoTs CU8K͹⾫5@bm-#i$u\gjV,e4m}*}dI֒S`(z7?WW;K͹ց}*xۃ,irj'ѣ`h:K\*ޒ3wOx\4180IZ?|fRFwIoqoICu䇣Gewxul*U}*>%ռEq04gg)yv S|,H(uG֬Yh> 9sYR%sߕc`ڧ}&~.~2w> Q6M
͒Wߏa Cτ׬Yh5sP),f-<= l=fFw6S[糤>ѓ`kYMт><TJoYR=W4O<= sج&YhAP-eZ7|>K~݋vX #:7glV,e_R}*DhI-_y~7e˷	YMтya>%UGG)(2|f5RFs=@唏ߝ/	ђg?09(K-?}*{3ZRZe*Vx?kkRP=E/5-:u_= F*_mjR=>@%u74;R굢Y,K!}*}iI8/zTgmV,e4nc3 Y-))E #>mV,e4|#s]LSR= F,SgnV,e4f <1>%R;E+>~._2ZkG*7>^>%ι=z Ƣ/ܬYhY PikՒSsK߉; c:s7a2j>= *uG絤|T9z GKv/뗥ZM<|]Wn>%wLnV,e4	 ׿,
ْ_F^}j^	 9g|0uZ/|f5RFC	 k)|nKNIcwEORl4Kbѣ|WmIl澅Jύ뛥FR]g@mn>e׽lQ>g)=ѳV:g~.|vK_SWpV,e4frý>:W緤9:C)	|9<Ke{DZ)u)m[ҦRz<zt ~sY<KA=# jx`uV$|KzUo``굎p<jFf|9P;n+U|ץbѣ o>g)ֻrQPKᒞYëhv
d)< 㒾ۤ]DJsyqh[TfGz*uGg-: z* TF,~6/2yk Uv6>
Tl_sF8 bmydd):wg@*Osi*[Կ1 P)ϋ'#K[x ٯw.MM}<TNlBX>"zn L[>ӥi(xcP9eє-"|NgREP5+>ץI._m*}*i?Gl>\=? &BnMW%~KXsw{9@eYMP2ߠw`bݕyLb>>x ϧ =z^g``8N/.MBS?Rы> ֿyMX2_K6OƇD)7>벥dW'}2~n/,e4ֺ+z LRsR#PE/;:|vgZ_% N~1|KuϻRG6w>	RFmf @7O~/~Ko7`uNl&0KFUSR%[u]sp)Lœ^s_) {vw'F|*X{solBQHۢ
><eKRh3N}$jsRF!u/!z Lmg|})|N;/> V)_Mh2
i[bݚG7g4},G@0|g*:z L!hF]SӢhٞMp2
C    IDATs?FR{)[ys4f6|u?} &GKN'7K5{g9 5{/4I57 0\5gl³Qh5gFT>zgj+BwxU^& _?لg)'|<z LǙn| J'E*7>} &W^?Ov2m֩l==n ZЍN6k`n:)|gS]{XN&l=*ojIc0|gSk[멹O?7H+mw0Fe)RFlF MKV|K#4p~s ޵?dS*QsP>qjMWnoOv:)RF; <mgdgSc
@b)YMI2L}WE K^|ɪu௤-Tяr RJf)RFsg /;|W?o-{qjTsy#W)'KU|Wͣ lO|?>+4xܔ0 Ϣٔe)Jջ9O<:_-&9Dmfͧ_@ŵOӕ*UߊC Cz|97?:_i9|' \?4ƞ̢ݾ~'V>V|ykgƽ һrl
Qꜿ$zPekc[UjԻzG =)/KU|[|`}v{{smRU7D? Xbݭ-3KUmgG% ,RsR]\>/Rӽ#`t|L6YʨGSS_Oْßw,,JͽSϩ) k|?,,eT͖n|]x``},e+^4;nлj |G?dS*[= cV0}|?M÷%`^2I Sy/?eS*[sϟO D*Mgo*o禺vNe`z^4,eTw_= ^;sQꜿ4G]*݊~9uwñ>3tN)e)*>s
wSh:g}jޔ-:+0/fٿ; ๔>*8>KUe[/ s[<x]]sH|RNnoOْMsSssg^}Pz,@u'MRF{.
IX֬-o;+uW:#$[E]ëRsw>>Rew$s^ ;ß԰Qk~?x!
XXw~fo}9: u/>u]7S?ڧrg}5[s>Jaxgv2;өs?]_|r냏JE LScjQs  Dhk<5Yʨ  P{evpk<5Yʨ-yѓ  `:/S^2MWD/  Sïx*Kզ|JG1  Z]spuORFis  ~253tj<-K  ~Nyk)T<x}<  SYʨvOy  Pź55Yʨ~-&#s  fvuҳe)Zֽxe\  >e+^~Ƴf)Z֔^|  Eۇ_Yʨn:)z  TWo
vS9Qmkk#  W~ݦ_Zʨ_=   4MRF}u   [}D/ݲrC  :25kJ/j_#  2ruj_S6  @%4456)KMD+{   ~}&g)(탻  L!>ScԻ  25攥&   aZG}$L9e)s  `N̢k25攥&Q=  ƮuïԘ5&EX{S<  +Kfq=>S3  `lf/죯ԘW2nFE  uI5|D9ѳ  `ZZRFYS|4z>  LsïXP2غ,   #:WïXP2_cs  `kRcYh^C  L}~ƂDTv6FL  x|CRF_]g&  p?~Pė	  `RchYh*^g  X?:G__1,e4ޒR=C  s_[1,e45?z  K)[MuCRFSS[Swg)  OT5CRFSUꃢg)  koJْïz2w˸  P##?~-H囘  k(5F|ץ1z  <H}~ȲTֽx
  zW~HToT6   jze]Nj4KMmDY  g߅_31,e4+^lm  xb)[E5#RFS]G[  iJj%KMw˶J{g.  @㯓ƕ韍   )u)G¯[2-S  L㯏ƙ},z  S|-&Hf)#}ݗFa  `Jk"5ƞݚ'  9#zH,ewI  &}Oo2  LwuaYH?P=2  0nH-¯RF_c  de5B= 	ֽb5k-SlT>vW  &PoZcq6?T'Y  Lq~F%jǃD#U?Tf6KŽWDk  `לT'qv~c#Uoހ  `C9jTٯDwFbk  h/ïoԨTݯ8xl47X}E6   ;K̢5*UF󨏆0RU3  ǖ~]Fc6*[E*= jW4JUxcѹ`E#U!  @8ǖwQjtWHUwӉ3  Dw5*Ykz4zw]IUoR'  @=OL5u<Xi׆@R7: %e/P~ҘCIoV|  TXzǖ^<})<?TZG~(r  >,jT˞iPR]xB  *wñ*jTe/NzR{	?Tߘc  r})*j&O-e'ޘ	  beZ/EZ9>s)3+m?Tf6K1 
^KR]kϾig?T_݈  T@u{D_QoRKR~}ǈ  DSs&Q6g<ZqfRU˷N= `3!zDNus/efR)խ֡e  _sff_Qf6K?RsTas   ;6DZ:7Lݶ}<wz]*uz   ":Wï?Ԩ]+}̬Ju}i   9_¯;Ԩ_˶JeȦ-e:+jZ\   YPvOs>)[˶:6rC~>   ƨ`w~c煛:ho|>   }~-:CZS*˹-ew_Kuwq|Z   Ƥs__QzW𼏯g]{O/յ|  WSd5jYS淔xb/ չ1u  \TG_WQۺ\ʤHn?KHuwQC~j   FM~=F?=ްe>(\+v  >ڧk	5j]UX{ޥLR?Huu  F_CQۦ͇}uGBR]}0  *fʖ8AZ׻M~̽Rfpo>j݊bݚ>E   Rn|(T;RfSLw_E῜T|JB'  Q(zuЯ_3Qf]顷IKY?J5s  P猿VP z6y)S<~_ʶ{y/)պR|P ]wTuRW)F<X?^ͩa  -&A׿y=純IeV/+սѿ?  Gn4's[SῴTzW7  ,@7O}~MFk~?2﵇R[M*ּ/  0eaR[E*rAy-efN?T_zb  `u MF+^qK!?T:gÂ2  zH̢k M}d_{KV,!սލ',(  /)[}ahxXRfV/Hu.Xf(  x;S_H*7>8悗2:_)#ս~fpx  `x_;z_2̬i	IuoXK  f?ICK|M@˷I.CthKTSߋCI5wC;  02O5-*o?g$-efu۩y`R[U*vG  M/ĿW[e=NiAj\~  A}_kZ֗GXRfL퍩yo:o  6]S6Yyջ|W]:@3^jdG  &Xgo:^._RbtKYnj?Tۖ(`  &W~eqkxպ^L{R{w>oIX?T_GQ *p_w#?c}~)]GK#KuIeg㸎+  F|45qK6OWTcm)3)[Cp7  )[Rc]*GRKus̸,  TSZNktշ֡|-ؗ2E:6."AU3RB-  TFK?\l֩/|\K?xcʿ3 RZu** @/9SUZz*ݚ"t)3i_H(GK.oMe6 uN_oHLU7|%եR}t `l:YKH3>SUf)3P{)pRjO-  E;V,T>zGj-ehoLs%m\u?T}d `fo[5ZT)A%2S<`ji㲭a6od `bu{-᯻U햽xpSTz)=ņS/زRK*  U}-d|嶩sTn|0Q-2S6%lVk*n  Qz֖nZG4o9=~7Y2O)Ի:>$}_noKƇO(  ,Hӏ~}
d:ཀྵ{kz.eOK+M̓ߗ6:Rj)u	  һ Uo'wIKWl\WZAʶ{EHuGR*G  ;d%?CR4{wץsylW?Ȥ1DB  dk_;os?0}WԙwORe?|kp|j85I{ɪ  /LW5RRSﶳSSߪzGZLR   B,e    X       `)   R       @ K    2    ,e    X       `)   R       @ K    2    ,e    X       `)   R       @ K    2    ,e    X       `)   R       @ K    2    ,e    X       `)   R       @ K    2    ,e    X       `)   R       @ K    2    ,e    X       `)   R       @ K    2    ,e    X       `)   R       @ K    2    ,e    X       `)   R       @ K    2    ,e    X       `)   R       @ K    2    ,e    X       `)   R       @ K    2    ,e    X       `)   R       @ K    2    ,e    X       `)   R       @ K    2    ,e    X       `)   R       @ K    2    ,e    X       `)   R       @ K    2    ,e    X       `)   R       @ K    2    ,e    X       `)   R       @ K    2    ,e  ׎  0s< O       @@       @@       @@       @@       @@       @@       @@       @@       @@       @@       @@       @@       @@       @@       @@       @@       @@       @@       @@       @@       @@       @@       @@       @@       @@       @@       @@       @@       @@       @@       @@       @@       @@       @@       @@       @@       @@       @@       @@       @@       @@       @@       @@       @@       @@       @@       @@       @@       @@       @@       @@       @@       @@       @@       @@xgCn  .IDAT       @@       @@       @@       @@       @@       @@       @@       @@       @@       @@       @@       @@       @@       @@       @@       @@       @@       @@       @@       @@       @@       @@       @@       @@       @@       @@       @@       @@       @@       @@       @@       @@       @@       @@       @@       @@       @@       @@       @@       @@       @@       @@       @@       @@       @@       @@       @@       @@       @@       @@       @@       @@       @@       @@       @@       @@       @@       @@       @@       @@       @@       @@       @@       @@       @@       @@       @@       @@       @@       @@       @@       @@       @@       @@       @@       @@       @@       @@       @@       @@       @@       @@       @@       @@       @@       @@       @@       @@       @@       @@       @@       @@       @@       @@       @@       @@       @@       @@       @@       @@       @@       @@       @@       @@       @@       @@       @@       @@       @@       @@       @@       @@       @@       @@       @@       @@       @@       @@       @@       @@       @@       @@       @@       @@       @@       @@       @@       @@       @@       @@       @@       @@       @@       @@       @@       @@       @@       @@       @@       @@       @@       @@       @@       @@       @@       @@       @@       @@       @@       @@       @@       @@       @@       @@       @@       @@       @@       @@       @@       @@       @@       @@       @@       @@       @@       @@       @@       @@       @@       @@       @@       @@       @@       @@       @@       @@       @@       @@       @@       @@       @@       @@       @@       @@       @@       @@       @@       @@       @@       @@       @@       @@       @@       @@       @@       @@       @@       @@       @@       @@       @@       @@       @@       @@       @@       @@       @@       @@       @@       @@       @@       @@       @@       @@       @@       @@       @@       @@       @@       @@       @@       @@       @@       @@       @@       @@       @@       @@       @@       @@       @@       @@       @@       @@       @@       @@       @@       @@       @@    Ѩ<}r    IENDB`PNG

   IHDR     <   P   	pHYs    {Rk    IDATxyewY{+AdDEZmDmm\glEQWP[ට$Uy 3!!3	IHH 		!sRkJw<_\{_{:g_ Wҿxu9kJk6oߧ)mťѷ J{KߏMnɶ3Q_V3?; 1g龥{(կlso3 P=x]iw%iK핥?)+o~ `&X 31-gVf[W  TuWK{ƿ3IMK-ïUhT 0=Jkg?dY-ٶ;. xZսW/w.;ݗD?j 0U, {%{o~5>n>= $#ϋX{3Uo}# Y S]zg}??|Մyetѷ  fyAi-{n4V>Zwoc iY w6<8?LnVB Z];4<kσV~  @ wVQ?0YWT_}' lϜ.w+ib-߾Λ Y @)exiW핥z[ k?UZs[cIm+c? Hz
e \q@{Qȷj͝я   `aҿxZTWT|= ߷˟WW@@ H|R^R=tc-	 0V9K{61 `Asyi!TWT}K _]g$KD? 0Q ,?yޥdSWT+ &g4(ݣ&93! , ̾atS) ~t1)>PJ5~`, iUo}Q{ꁯEߖ  aJgׇIuOxw)~ ce̪*g=^{/}_- k(U/?"k` f  3ZsgiC-* HcQkiRdRя#   3Z{wiaR9j In:o&E>Mꮋ~q ̔Hi!RIZ2  ſIu>R eK_['Eߕ  w7)gj8@c, ~QI[TW}W L*OA;\+iX 0'7|XT}K LAt8)~ LS[ `*խK{ׄI#~Uя# l1@ JksD?Dߒ  Sz^C{Y{*U   ӫP9 `ˌn:
"G   S{{B{JoI 1`w<)GD? Y 0|2|TR)N-	 0[Nw=)ۗۢF xF, :UgmizY0:ԝ5ѷ$ lvK"' @ N>*zѷ# L[ګ_'E6G 6  SetUxP-ۮT\}; ,}WֲƿJAm\ކG 6  ӣoFߍ  OſJ_f `j8(|S| j/^?& `::Cb; `᪆_'e`zX 0_#|Slc9g` SoxpТ=T~`X 0%Þ  Fw^XZ	G"G 6  <$|S\=_;/ c=ڻXJoC# ߓ  UUi!OA/*#D߅  |.8}Qh?R, HmxÝZM~~- SJgo&\7G?~ =Y Z?
o?  ꑯ/w&k? xZ Umx<+|ѷ  hx	ҤG   i/7|{ѷ  '=Rd^9   iuNW  \nIi*d@J{KknNlv+ѷ  PM|JiB; xJ 4aNlnQ~ -4wKiBuzK# O:^0?ѷ  Ki"-޺TG9 xR 3sHc~  hH[_:h{47  =qL}^_[ U^7Ҹя <)@ y!N㯽z 1\_;45Q'e@:(|^w\ 8u~w;qR6 x@ i!N?Ff  L@zW,Sg՚;5 x@ RJknQ 9-{ѷ  25 TFw_>i|wٱkX wEq5tG T>iL-*N  o>?N*~ 	, HMcX @ޫJkɶRNxw O`@*ݓ>Ra @ysX HT:G-|xSW  Ƞ?*5Y5'  o
`s[m_  Hz^wU{6'  ?>}K Uj)'  /LZJ]ER  dTWߛ*5Q{( x@ Ri->|xS_  H^s?b	 TZK޴;.V `
.;U; Q'  M[^  uU:B;   M[Vgו>6 `T|m.+=, T7mA)=EB  LEgg  Y Jg]o  ?), H%zp3{/Ro  Xͥ9f@F =ڻo  fo, H%zp7 YQK?+mN dd@*у6Ie  1/)uM, H%zpfԝ5ѷ  3w߆J  Y JMotөѷ  3>6΢yM, H%zpӦ;/o  fOJ  Y JMӟF*  , #+}, T7}F7}  @TZZK,=] dd@*уIE  X`_Z,=] dd@*уf? 0~%}Xz, T7=uN=  XFw^PZs߉', H%zpӓ;ϣo  	/,@ 2  MO2̮z?	 @zbc黳  #@ RF7}[  +ߏ, H%zpw;o	  O~ҷg@F =ۇzݽѷ  |-g+Kߞ  Y Jlâo  xROVY   Dnz'~  IUZZK,m, H%zp z[  VĿ;K $e@*у.56  o(/, T^g72G  I-Y   DnG  th-, T\? `U\ZZsߧp  #@ Rj;z}?  <#c/Z7@ 2  m6|  ꑯ֒m߫0  #@ Rb~j ZY   DnѝF  #߯  #@ RZ4# .\  Y JචZ] @sߵ  #@ RR/. qk>  Y JPjR  Wץsτskd@F =-Q ،nB;N dd@*уBsh  e#~-[#@ 2  m!4  Ʈ5([  Y J6u?1  LLwk  #@ Rf۔ᛢ?b  Jknwqt dd@*у,??^  gGf;@ 2  mVkx~7< U|}aDkv  #@ Rf?Z  ;5Y   DnX{& 0cwgk6  #@ RfE?V  5Y   DnV{K?V  ;[˷Ge@F =Z+H  Ge@F =R=_[ʨ @Jkvꚭ, TYjx'  ?ꚭ, TY  <z9욝, TYixա%  ?5;Y   DnP{W?  xc֒gk6  #@ RfE  ^Կ	wld@F =M{^Yʰ1 @zKk6, Tiop!  Lg@F =Ms;.# Q=zg@F =Mss> g, Tmɶ^  Nu5(^S  Y J6N  Vwkz  #@ Rܦk?:  Z;N, H%zpƺGFJY3_v m:%^ә  Y J6nB0^sG22t?_KԿ)UGt+J{7,_}iK{*\Gf?_exetzR+06, Tis?2Rox>XGgm{AꗗaN~o|iExr-PJg?5}Y   Dnc?2Opn%{9[w; _PR5X=|s*+?5}Y   DnT{W2Dd խJߋU/-pOVu7\ x
Ni|I٭, H%zp_3H^8oٙjw: |iyY, H%zp˟W޺ [}翯j2tpѪR=z[G	ByoFkj  #@ Rܦi e箳YsϗezÃџ2@~&kz  #@ Rܦ꾯DT U8tygi-{n9<-ަt2ڧK?~>[籦"@ 2  m3DoO]_=~wy)k% &{, Tihxաԝ5eJ_۪ٚt?Z:Vǟ, TWP	Y~^B~.%
?k2RQ0V2U, TO1U+W={.ݧa7v}* dd@*у[l*۾Pzǿo~6.q7~_cw@Erg@F =esE< X][,=^~jFn U  #@ R27`(su;LQMΡP{. Q?vZf@F =eJ?MV`i-.UPsJPzqY   DnY&NxߔepTTy  #@ RܲV=x}Gwމ^Zs[Y7Fߪ X7ʙ  Y J? <?C祦%ۖKo]6QRf@F =elpep>?>'5}uR{U]ye3T  #@ R5U}3ck?Uڻ2td2rLY~*] dd@*у[5#գQo?5[u?+^woIo.Egre@F =ekxա	@)n響ilw}qrFI6#sS  #@ RRY< g^?5-*?TJ5L, H%zpTߍ8-,,koG6ʗʓ  Y J8jtA-ڻT^( <9	?+'@ 2  -K/eЎ8]9U9(>9: xRR  Y JIQ LOw4, xRݣ~#T, T,qvG, +?w_R0Q9  #@ R2^r1)?M{䯗.Oհw{E, T>w TZ:g9uRox aT\V[z'Yic٨, Tn\iNz&|mD2?{/焟ʗ  Y J]{K?`Vu響wҖ5z'
1o'9)u<td@F =E;]0asNj뢟,`Jսetep>w{8\f@F =E4+#=r'K@{J}}^h dd@*у[h.u 1K瀟?q.1QWן{4, TȺ̘K{WoҸk~y5-N-s?VGZi!L, H%zpl=/?0CZڻ(l&ewGP#m, H%zpo. Mwya&M^+A	N5U9#=Y dd@*у[T~<3+ˎUg,uwml-.<65@ 2  -YoIZʰHO^|z響tygisCڒ, T{.W~IYǥU	^[WFw|.ZUzt dd@*rX\?Hͥ3)[%e4(սWY:ۧ  Y JQwG_v`ʿ3k2)k+~La4oэ    IDAT<ӂ, H%zphxї?9瘔۔m_~\aݵϒ퓞  Y JQLQt|[&MCzFPFw]\Sz'?Yf@F =(Sj>äi&хwexAwJg([?4e@F =Mi\[%MckTG}osßMiڳ  #@ R&/90eF7f4ϛ~!{VJ  Y J6zÃї"ڻV'G?м~7(@ dd@*у$ї&Ng4w~AjX)ë)SzIqY   Dn?G_n`NsK:a7цMR=z[~ӥֿ>)a dd@*у$rFS,iF?uE{I"  #@ R&mJ[})Pw}Q%h
+O, TI9E_j`u~,ih[#ig!Fz2?)%
$my dd@*уۤKLeW҂9(gl\,;PK|{]x  #@ R&F_j ꑯֲ+i4pec*U_\Zvi)4, TIUox0Ru~GY%->T|-g>Iߕ  Y J6:{.2JZuxc)~@[{UR, TI;Ϣ/3X[Wڻ"jGWF7^/)cYڻ0?@ 2  m./2?sJZ-ަT߼"(`Bbtŏ)Uګ^I, TI䇊So~NIV#&:et%/Nxw#, H%zp{K㻅=7)I??@v'ibY   Dnn 讋(IVetG{v$-, Tq?CїHs?$}g~xOGG][FS_ZQ^D, Tq7K$4Iғ2CJ7̌'$黳  #@ R]=їȦJg?$=EK]o}#}uUn,ïYC3d_6!@ 2  
W<	n:5|u|[Q1s|oY, H%zpguInxgU֗])<%, Tq?ߢ//L+&IV{J},ȯ>}]z퓴   #@ Rƙ [~6Ig(H<ןPg~h^I&  Y J6Ϊo@"Kkgh6PE$%, H%zp[K3' ]?$mv˭uYh7<\Iʘ  Y J6:)ԝ5ggLKuepKξo}Y   Dnw_F_Z Ky;-.J4g@F =@"T$i޾_;I, Tq5їH3IR-ۮԏ]2|o$d@F =P3IR3m0հTP=<;IRP dd@*39)IJk璤۪T}e2S|IR, Tq=mїHbpgfϊvχ)OISg@F =Y}Y$:l$F_?s˾J?*_$i  #@ Rʃ/+@=5(L|}l;6{mK,@ 2  mm^ /~I_+ބ{nNIRY   Dn^{ge3IxjzYtZ響tE$I, H%zpk.E_V XҚ*L$IRY   DncN `\oy$Id@F =5]wF_R '~9<$Ix  #@ Rܚ?E_R Xzo~I$i<Y   DnM7|K
^H$I, H%zpk7Ύ@?$I4, T5ڻ2,$I  #@ Rm6їT=tcY$If@F =5Yg@E$Io dd@*у[uz{NH$I, H%zpkީ}9`=_~I$iY   DnM?o.rC$I dd@*у[<8rF76$I  #@ Rܚltї?I9$Ig@F =5Yuї=$IƟ  Y Jd/'!I$?@ 2  l[J]E_N H~$$ID  #@ RpWG_J !I$M&@ 2  :|<8$Id  #@ RܚwF_J P
?$I4, Tї=7!I$M&@ 2  @^?$I4, T~K	DFY$I&  Y JT[>}) cA$I\ dd@*у[SU\}) ;/?$I4, T9RA~I$irY   DnMU@A$I\ dd@*у[#-*F_J H?$I4, Tfc{AesH$I, He&=_}@Or9$Ie@F =5Q7E_F PgׇC$I\ dd@*у[uz{ew1$I  #@ Rܚ?@.[C$I\ dd@*у[OA$Il dd@*у[~I$iY   DnM4x&$Id  #@ RܚhpŁї2Kg$I&  Y JDï} ~I$iY   DnM43ї23H$I, H%zpk-gD_F  I$M6@ 2  F} +?$I4, T&,2A~I$iY   DnMT=pme.\~I$iY   DnMT=zke<$Id  #@ Rܚ^woe_~I$iY   DnMTwD_F H?$I4, T&*^eX$If@F =mq@9I$iY   Dn[/!!I$M4@ 2  V}	@sH$I, H%zp3[G!I$M6s  Y ~(_$I&  Y ~+w@K!I$M6@ 2  V4_Z~I$iY   L/!hp.$I&  Y ~"?$I4, T~ї4tsH$I, He=^}	@ë	?$I4, T-/!hx'!I$M6@ 2  mK#ї4sH$I, H%zp:>F~I$iY   Dn[Zg@煟C$5d  #@ Rܶ^?}	@/	?$I4, T~/!zk$I&  Y ~_}	@;!I$M6@ 2  V}	@u[$I&  Y Jfh~I$iT-nїZ]Y$Ie@F =mqK}	`U/?$I4, T-nnQ%uH$I, H%zpkR/#s[!I$M.@ 2  ʰ}@ݣ~I$irY   DnMTG_F P錄?$I4, T&;k/#!I$M.@ 2  D_F U$I&  Y JD;/#hx$I&  Y JDՃG_F !I$M.@ 2  {.@g@9$Ie@F =5/#zsH$I, H%zpkME_F P},$I  #@ Rܚhc/#g$I&  Y JDë@ꗇE$IL dd@*у[.+2:H$I, H%zpkVD_F X_?$I4, T&g$I&  Y JD} 2g~0,$Id  #@ Rܚw/#l>$I4, T&~H$I, H%zpkQo@ѭ?$I4, T&1,$Id  #@ Rܚ/#?$I4, Tfbe$^Cy$Ig@F =5VUuH$Ic, H%zpk&RGfY$Ig@F =5Umї;g$IƟ  Y JTսWE_J "I$?@ 2  F})`ë?$I4, T^w|nBY$Ig@F =5/%zH$I, H%zpkD_J ڠ~I$iY   DnM@]v?$I4, TїH
?$I4, TK	$=#I$7@ 2  :)R	>w$Iƛ  Y "R	.%<$Ix  #@ Rk6U9:<$IX  #@ Rܚn+rFw^~I$iY   DnMV=tc?$I4, T&	DZH$I, H%zpkuE_N ?~I$i|Y   DnM6t	$=w#I$/@ 2  ~,r	py$Ie@F =5YE_N G$I_ dd@*у[u?[їH`t9$IƗ  Y Jd}95G$I_ dd@*35zi2FYg$IƓ  Y JhsJ/)@g?$I4, T}IGfy$Id@F =5讋/)@?$I4, T~K
$0dH$I, H%zpkE/)#I$'@ 2  @%)<$Ix  #@ Rܚߏ@^im~&I$, TK
$Ug$I, HeU/@5L$IRY   Dn7U)~e7g$I, H%zpG;/+$I, H%zpG.@O?$I| dd@*у8~
$P=tcy$I  #@ R/+hPZK?$Il dd@*у8їH$I$5  Y J6GZe{g$I, He&=_}Y$~,L$IRY   Dnci6TK$0g$I, H%zpWڻ/-@uU$I, H%zpW;}iҚ[~&I$, Tq5K$g$I, H%zpW/-D?$I\ dd@*у۸їH?I$Ij.@ 2  m\uїHbx!g$I, Hef^}i$Fw]~&I$, T5U)NۏğI$Ij,@ 2  mU}y$ڻ8L$IR3Y   DnltөїH{/I$Ij&@ 2  m.-IN3I$Id@F =i@K?$IL dd@*у8$1g$I, He^}y$?$IL dd@*уX[TKdPץy$I8@ 2  mU\}$:9L$IҖg@F =<\:Uc4f$&ڶIbbޘ6CNv+tt6csjB@bDJFAD&ADFbzass޵~?>GUs"7/1DoN3I$I۟  9 J[%|c3I$I۟  9 JN/1/$I$m d @*ыb=_b ;g$I?@ 2r  /`H$I/@ 2r  mU_f ~-|&I$ir  #@ R^&ίF$0|&I$ir  #@ R^&#@	I$Iھ TI?#_f I$Iھ TI=@Vi,K$I TI'@"s3!z.I$is  #@ R^&R/5D?K$I TI5/5D$Im H%zqTkRI;1|&I$is  #@ R^&`/5xӆ$Im H%zqTQȢ֪%I$m[ d @*ыۤ/5H砷%I$m[ d @*ыZRƣ/7D?$IM9   D/nl_n kg$I-@ 2r  mn8%$1u}L$IҶ @F MyF$3I$Iۖ  9 J6z/7H{
K$I TI_n Q
K$I T|RF/9D̏%I$mu d @*ыۤwmHbxgg$I>@ 2r  m9.K$1$I H%zqts5Kd1%I$m] d @*ыۤ~FɁD:>|.I$ir  #@ R^&]a2C    IDATgN|_\$I @F M[_v {%I$mU d @*ы[D.In]>$Iu9   D/n8"$Qu.%sI$I[  9 JQGفD{:|.I$is  #@ R^"/;H%I$my d @*S,~i)U:|.I$is  #@ R^ܢ#K$1g$I<@ 2r  -эF$$I- H%zqj~EH%I$mY d @*ы[Tc K$=$I,@ 2r  ]zUHl\$IҖ @F 5T_~ '%I$mQ d @*ы[d΋IT>$Ie9   D/n.^i$Ig H%zqwҟGDG3|.I$s  #@ R^"_~ Y>$I9   D/n-n)~# ^s\\$Iҳ @F E7G $1޴!|&I$s  #@ R^ܢ~я ȢJ{%I$} Tg|8 t$I  9 J]߈~@"u
K$I9   D/n)Ǫ~@s8z.I$ @F ez $1$I  9 J□'G? V |.I$s  #@ R^2?wyc $Ig H%zqP51 N$Ig H%zqP?D>$I9   D/n)YRG$1$Ig H%zq/G?
 afwK$Iz T,.d sI$IO  9 J▥{ sI$IO  9 J▥~1Q /;4|.I$s  #@ R^4~+q I2~.I$is  #@ R^25d1%I$=5@ 2r  -SD? !>$I TL8DvK$Izj d @*ы[:6q ::|.I$9   D/nYZޣяHb$I @F ektW	EUR\$Iғs  #@ R^ܲ5pG$=sI$IO H%zqV?~$@">>$I Tluּ& [>$I Tt,)U$Q=|G\$Iғr  #@ R^26$$I H%zq=HK$Iz"@ 2r  -c[c_>$ID d @*ы[{: 6K$Iz"@ 2r  -e3KJ~  IT$I  9 J▵gE? '~<|.I$ T[hDzǽ'|.I$ TG$28$Is  #@ R^ܲE? ѭ$I H%zq\x$ޣ54|.I$ H%zqhú$g$I T֯~<@";%I$9   D/nяHd}$I T̵wE$I$@ rr  -{գwG?" a>$I=@ 2r  -{O~D@">$I=@ 2r  -{s5Ny\$I Tu?[яHdxasI$is  #@ R^ܲ^R*1I*|.I$M{ d @*ы[o)1YGEsI$is  #@ R^D?& >$I9@ 2r  ŭO`c$I4 @F աDF7>$I9@ 2r  ŭ-n)^Z$I @F ե.~T@"Ox\$I T4я
H?
K$IӚ  9 JVz'/Q.;|.I$Mk d @*ы[]yMyq\$I T4TŰWZ+?$I0@ 2r  ŭNn>3qt~k\$I T:5$_$I49   D/nu{E?. ǆ%Ii H%zqS}6>$I1@ 2r  ŭn?%Ii H%zq[k~d@"c~?|.I$M[ d @*ы[sI$ir  #@ R^VG?2 -%Ii H%zq]+_Ph؀$ޣ5,~6I$MQ d @*ы[$sI$ir  #@ R^҃H%Ii H%zqc"8<|.I$MS d @*ы[$2x]\$I TZ6TGEU#Tl$I T6u}$I4-9   D/numpяHL\$I T;/%Ii H%zqk=~(TJkfIl$I T:W=rW|$I4 @F չ'E?> މK$IӐ  9 JV_$2d$I49   D/nu{;$I4 @F չ./.G?B ѠV |6I$5=@ 2r  ŭ7^D$I T7G$?$IRs  #@ R^^DFօ%I @F ս΁o~@"UҚY>$I  9 JVXʠD:>~6I$58@ 2r  ŭ	01j$I T&4h$2$I T&G?F jsI$9   D/nM׫#L{	M$IM H%zqkJUkc$I T4яHdp$I T?w6Q,|.I$55@ 2r  ŭ)uzW2K{Ջg$IRs  #@ R^ܚR{RUяH{;g$IRs  #@ R^ܚoD?N _=$I  9 J֤W8DF7>$I  9 J֤v~@"UҚ]>$I  9 J֤:5qt$IԴ TFy{яHg$IRr  #@ R^ܚK)c$IRr  #@ R^ܚ)HsI$i9   D/nMvG
$&I& @F 5ΚD?R 	>$I  9 Jָf@cI$A9   D/nMltяHd|ϕsI$I9   D/nMl~ec2J{ח&I @F 5ѿXd$IԔ T&eTU$IԔ TVm%n97|.I$5%@ 2r  ŭ>6[|$IԄ T_G$9g$IRr  #@ R^ܚZ_~@2/cl$IjB d @*ы[c[R$2g$IRr  #@ R^ܚˢ/H J$-@ d @*ы[\$IT T&[SI$9   D/nM5яHfa]l$I{ d @*ы[YRяH=ZZ;'I @F 5gF?b AoM$Iu H%zqkz+1L̿M$Iu H%zqkzݣ7Ɍn:=|6I$9@ 2r  ŭ?яH>\Z$Ijn=~t?28ou};} @B MC[3L7&IԌګ^TJ۹<7^{}Y HTihxяHſM$P:T)//?=_ TihF7>$IR{t282Rm`f}] HTis/E?f $IO+}sэi1w@l H%zqV<a/Qt$I~nB\O~ $ @*ы۴4G$3끣g$I
ܾh^vHas  #@ R^ܦ%G?j '&I4kGL $ @*ы۴4_{UҚY>$IG׺d4} @ R^ܦΚD?j oO$i[§~n_U:tzos  #@ R^ܦ%j?d_$I'}nK]yvts  #@ R^ܦgF?n ukg$Izs7N}itǅ_}^ $ @*ы45X2qTM?!=$I=w~>pT]5:   D/n?2 |~O$5nBseX Ti/S'Iϕ)YV^]xG}
>  9 J6mUo~@2NM$5s?oY H%zqWȁd?=$I\{ח<<hxZZ>8   D/nV݇9P_
O$iss @F M[s̄'IB]V:T)/(e؋qͷ? H%zqV<?h O1+IInܯlcx*TѬ H%zqw]؁lF^$IBŏnܯR=v_Szf[ $ @*ы46d$'Is~)}	U,` d @*ы46& ipI-Nպ?Y Ti5яHh|5I_yY  	9 J6,&SU?(IT^.sccF	5=u  !@ R^ܦgF?z މO)jK_.u;Uǔ>  ,>@ R^ܦ__?2|>I[{WucB|  ,>@ R^ܦQ~@B#w'IRS??T=v_o@ r  mZ_Xq%IW]tGjLz HTin|яHOP:nWy/;7^?,YU.` d @*ы47$4$I<{ǿ]nk  	9 J6Nyzg$)c6Ҭ@ r  m$59N3J4%l7 @B Mu3KK{$ ɏ%IZ|n}9   D/ns_ xOܾA'xs  !@ R^ܦyF@Fai%Iږ<k} @B M{sXt%IzrsqFTg}|VE|Yߋ $ @*ы۴RUѯ}g$Muw,\M~_sO-` d @*ыS 	7>$i}n3f}:   D/nzN^utk $g$5A}Lцul H%zqsJD@R/m^=WJexQe7v  !@ R^9Mѯ_QTfw(}_Wzkw*הݗ2Es7ߟ  9 J[ѯѰ7+sJj})/T HT7=趯D
@Rs=$)PK^y  8 JG $5ځ3J&ު>s*z$Cm.D @F A $U=|gEmvٓ>oWyepޮ  9 J[`xe $?)IZU<f@ r  MOT=t{ $?g$mK]_<}G*L߰ @> 鉆: In;/|FI}naZ_2Rm5z|_ψ H%zqO` d5CWosVz'iX T7=Q_~zǽ'|NIޞ}VXof  	9 JR~%W?$M=v_SSְ9 @>  Ojm,sJRZc_s^yToysfs  #@ R^WD@b>$տ	RR\9@zUY T7=~%Ά)Ij?=΀	kٳ9   D/nEv-e<~-w~5|NIy3K]ܯ?  9 J⦧6 N5.@Tګ_=ɀI7 HT7=%G@b;)IOE1`ª=  9 J⦧;O_ 5Ǉ)Is/F1`ƛ6Ϟ H%zq,H=RZ+>$ճQ=ƀ	uiY T7=}#ߊ~5ĺ9%N|_&lٳ9   D/nz~. ^~XT>=	^yTY T7=}u;G@bU{Si>$կ#{Ϟ H%zq9Mѯ\S>$կ%G/`gsY T7=C;X$6xMTW=	ٳ9   D/nzFz U|f*Ijty>{:@ 2r  M˫_ AoUULX_=  9 Jgz [>$ըѣ>??8@ 2r  MeťGѯxӆY%>h3@ r  M߽WG"@r}^>$գ!=Iƥ5,|,t d @*ы{ Y%{O&j?>"Ԯ    IDAT{#@ 2r  M߽	 ɍ<|VIG/Lkgb @F Y=^ 5UJRWn>+|,F d @*ы7G&@r3w'E+`W>{#@ 2r  Mã_ m_	U7+28oٳ9   D/nzzѯ	]5._>$jmVOٳ9   D/nڂ? 5;+IykzQ)U=	͜i $ @*ы;_ -*Iy19   D/nڲW u5{pމO4 d @*ы) 5?JR_^=IJkv9   D/nڲ:k^ 50y%)gkOQU>{+@ 2r  M[^=ѯP5?>$k|	ݗϞ H%zqӖ7JR?Q?z<6H9   D/n uj`7KkfI̒?= >>+@ 2r  M[^gG.@Mt%)O;E% @gr  #@ R^ܴ,)U{S+53KR= c~?|,V d @*ы'E2@TWZgn>3z,:!|,V d @*ы~e~gU#	{b @F iW?>$Phls  !@ R^ܴ.+Uhi|AܒZs= .?  9 J⦭oa]kD,I.;zם>3@ 2r  M[_F6@Mn89|fImtǅѣ0`9   D/n:5b/>$ѓ?3hs  #@ R^ܴPѯP??$9䗣G{Իgb @F ixjޫg_i'gb @F i9js/-Ioa]"5,|-f d @*ыξ!jdp~sK҄]VC0? @F iYRG~}:Kkg9ѣ29   D/nW 5;O疤`zKZ T7m{ѯP#[	[&c;}3hs  #@ R^ܴK? uRU5KZR99   D/nھƛ6DB@.xܒu?qj99   D/nھ_; jj?PZ+>$-n~ ӫz4 T7m_Wi\ iYR5@C H%zqv._Zx52%i/`zpD d @*ы]EF@t%iq:z zUD d @*ыGF@/=(|vIZ1@ΡoC H%zq=ѯP7vi%ia|򧣧J{ϢI @F iZRW	_=Z@[Фr  #@ R^ܴ0n97UjzҚ!|~IZ-@'ϡI @F iaѯPC>$-L=R`/
E H%zq9ѯPC/_E{G XϢI @F i]VCѯPCs?5>$m'z :l<P d @*ы Zk_Q=Jh=&  9 J⦅_'ƣ3LҶ?w_>&  9 J\zUk0IV{W2D ҃k9   D/nZƛn~:vK{W0I[_	$;ϣI @F ia\W
W0I[R=t{ 3i9   D/nZغG3j<Xڻ|ou?d0g$s  #@ R^ܴx^EV@MOsL7$0y4 T7-|O~)@&uzK |u4 T7-|:jG瘤gox	HgҤs  #@ R^ܴ,jjo*U/
e^*e<@}^;}s H%zq4x}X̏1IkF	 n.K H%zq4ѯPcUgsi~i,R1$1霅 $ @*ы~k,Ԇ=D>"r  #@ R^ܴH-nzF^@[+癤'=D}tC@ r  M膓_/>$=CIUǾ?|6E @F iѯPw~LsJgϔ2DO )*@ 2r  M#U0^y&9eti Hfx)*@ 2r  Mk_1Gf<)z 	N  9 Jmpѯ {,e3MfݗG _>r  #@ R^ܴu?ѯGLNU{Si,	QQ9   D/nZXѯ cc[\n/+Uo эN|t  !@ R^ܴ[13MWm$?#3*2@ 2r  M_,j\:%|IPSVJUEIu}[ H%zq?,ݗ&5-GIU
 H%zqdqQ4HsMjr+́FS9   D/nL>M2h?>ۤ&9M@b/Y  9 JOGj@Ìnri,	oRZ2޴!Hs/ϫ T7M񦛢_7az&5G[UJkfi H%zqG4L{zU|P+׭Wr  #@ R^4:-uhtǅ5,|Iu-U{S3P:|fe H%zqYZ~;?㤺|2oc&:k~&~n% H%zqd^Wht'ձE5Q=zwʒ  9 J=Dr@CU^ڻ<|Iuwu^%@ 2r  MnJ,jt9>P:A;	> @F i\k4=眔?\Gvd<*^> @F ioѯdU5?gg.[^
΋W T7,˫^Tʠ6;>|I]VF7-
P(@ 2r  M1n89n7q.zIiYRW	T7ϱD9   D/nw_=`
nO<E<)CDK5U69)@ 2r  MQKJ_?`
<j']~s,[ d @*ыmXSb=goAzY-@ 2r  MqN"?>I?z@ݍGY T7.ͻ0E5F0y1@ 2r  Myv+LQt'-j3KOD?#s-a d @*ыbѯ 0eޣs矴(,-6O϶9   D/nJk@G2Uԯ@iA[2o/A]?ے @F )цuѯ!0=3PZڻn 
h-k d @*ыV^sPڞ:T4PgqYs  #@ R^_{2FrTR.|k˜  9 J?)UhPzY(mq3KJ)e<jp.q d @*ыr4 ]>g|~.躇=|e H%zqSV~OE epҚY?s-bZKkvY˜  9 J<>6u7sysQzү\RFo`
/;$~% H%zqS}wm;/.^>+?/{ d @*ыyl~%m|5QS[oퟕp0EG? @ 2r  M^zp+	$sǗ1>5]?etIѯ?0`f H%zqS=x*w/sRofIݩTz`Ju~k,A d @*ы5To~-簵W4~Vu2ѯ90Ūͷ}<z!@ 2r  M|yUk	(#>+ՠVp'LxzSnpX T7嫳5ѯ%wWࢽKkgjw_{hy?k  9 J⦜uI	/>3UGfwM+mou H%zqS 2~韻Oj2)kS d @*ыr奌ѯ'?xsu~kxZk
zUS d @*ыJ:]OxU?πFu H%zqSzǽ'6VJkgb~'P>7  9 J-nZG lnhix^Lv2W`UJ{Ջghr  #@ R^ܔk_QV=t{Қ]>Wzu{Dj [mxhs  #@ R^ܔo~EkK:6e)N/GZ ۬{gjs  #@ R^ܔ]E |mJ?	PwQZ3Kgks  #@ R^ܔi,:n#V\{K_?غ @F &,Q>t|gi,zNin> Xx e{p  !@ R^TWLDe~ei;m?cCetWaFu H%zqS=W`qrn祽p#ݡt}u|ץTUSg?k  9 J⦚4f
c<Y-*~&׸,;'9f: @F >ϙ~]UOOs[եCoD?=^=  9 JzF_YTceͳTZ3KuXJgו)/+*CG?|gvs  #@ R^T>Hjo*O*tgb%{KyuI)V u'& @F ^u|g+P;#wэw~V~OLߒ9wetɥ|kG_᳽	9   D/nY3K_[FnJ^qON=7JgחXYRڻt=WJ.u;E,O-} lw @F ~`~\,w/s]o222R/L|Sr  #@ R^T~b{ѯ.  Ǡ]ګ_w @F :& ^zPᛔ  9 Jz=ѯ.  CU>;|r  #@ R^T] @zw @F O  7-@ 2r  M5n`+  iﻶfݽa9   D/nw~  Iw& @F uyD	EhGZ7:ULTgZG)^87&nҀbdD% AQh )H${陸U[ds=g9y5t/JF?c  NUq-<*|f ȑ  Y^4u[  ;Ú  9r  +ыƚF?c  K'Ú  9r  +ыrw2  d}s  G d%zqp\wjS <T?30 @ J!iѼT;3  | @ J᩽aEs XU^>{ D/n^R  Lus( @ Js4  ~cL>
9 #@ i:yg  `txS<>*9 #@ ic 9XY|Tr  G d%zqXg  sܲ)| ȑ  Y^4[~  0gW3| ȑ  Y^45y_ 9}{r  G d%zqӐ6T|0y @	{r  G d%zqֺo7  Us( @ J!nѩ*G?q  e#  9r  +ыMcO  WQ9 M]T5vE?s  uoG5@ r @V7-~  0?b=9 #@ i+='UͽO  fGUEG9@ r @V7FgD?u  |:| ȑ  Y^4ˎOUk< t[Xzs  G d%zqԾ  3xV\-@  @V7NŊ_N]~  Гk[Gr  O d%zqhtQ ,|Or  G d%zqhU:g  R~$>O{  r  +ыFF?{  >>Gs  G d%zqUE ));9 MY{O  qg| D/n͊eIUsO |Y' Ȑ  Y^40 8Es& @ JѭX|LjOD  _:. @ JѮG  0IT[tt @ JoѼT  i}O @ J&n8-3  }3  9r  +ыT[pd*w)  @Je7/Y9 MWs{?  Hu ȑ  Y^ܤ}xc  >ǅ:t D/nϪ۳g܀  gIDATTUџ  #=3  9r  +ы:^I  0>k9 #@ IOX: Q.RYX Ȑ  Y^ܤ׾ ZzU,{NI JmMz2_5vE  rwSm33 8 £7W  WUꗾ)|+~QI Jm×7iRJ?  X{sz~+ L @VjO_ޤ?<  RծS? `@ RM:P_D  6UW#|U5>W 8 I~omE&  Ν\ͬS L @VW;|yV{Ê !Q~$Kq5ᖥO	 &q  +/C&b1ڳ5S `~wϷy~&5$ duy˛ty uY\٩|	 &q  +_ޤC6vX>1s `@UMZnP5D?) ;_)T5)O A+>jv*V ` KUc8i*X  0`߸ |ո]O
 W)|RT  0 ߛjϱVD?+ /@ ?/qTk~O?  A93f#F, /@ ӾsK4l  \ksfE& #@ S}<_)Vjt  Tsfƕ~Z p@ dXur2'M֗>  CUcW*zaٯ} ,5<|#Rџ  i^YU}ܾ9y9 C/st_N @&:߾2|FUf_  SYڊ/utko<+  bɳSi'  @_8-|ݢS H"W*~6U;,UO0A9 ;RUFB  i_Ϥ㼿O <|z}۹џ  :E:|6!9 ֭+×;ݾ9 `O|?Eշ'iF?5 8$@ V;yKKKߔRٍ  z:9|Uk/ 5%OgGB  ́SgO}wgU28 ˞SM  ë5s^kO =@ TT[xT̩V,96U S @>4>vD'Z{Ê YV՞HY/5Z7/~n 0- u
_[T>vwg l);q[L_KU~q 0- rT[r\'Z.?%  fA
/57u}sis `n??|fRDF  P瞵sU ' L%_Խo] @Iſ>SjZ4/UO> ' oOJ=V,;>U{) 0MU#yI<O z @3ˠ42S `Ը-s7iE:   l⼗/Ljo<3S `>>?jn*?7U{F?9 @ VwyˡsLMџ  pF쨹i}`}s `d(͠yx t[7q57n `V8 0~ |IfRGF  GݩX|LqD?;  f-2|YfR$  X*zA~kS `8 0]ڙsp ]%5'T? `V9 04O'/RU=S me75~Wl9T=PY Pn3p+>  ѺPsS yg/RoY ς'GwE?9 @ R7J?)3 )oIgA9/I   C囩Rb	ڳ53 	_Nꗼ.UG?9 ;@ ZwǃX%SſR }?Y;#QcR `N8 0=W/R/5`' 0便=ύZOOӊ~r 0g 	ecOj|Oڷ  ξ[/V>멿˟; 0j )o_Jj? QSWykj0 9mK/_FT,Tn  ;/N}l3SkSv q `4_O-Tb_6  QHN	ԿW8  lHŪ×Ti:A#O `t۩?ԟ3:w_   mڒc×Vi*֟  k>ǩ-Z/)5ǣ_ d ~ܻ-5@Uu}E' 025P٭Xr<@ i;L/]_V:`L  䭪RneǧRY~] 5@ 8ɇSM
_rrw? |N4;W!7]R ` 8 !{O͛'/+|~lL  2<}8|V̪҉ۯ  R~BK)|~V}ɩjB  g?L9u-%@s ^tZߟOk"Ֆ$K+ޞRe  ĪGg3MS}ի&oWr#/   TUoƕqSmFux  #{LOkXqb_\ZԹ듩eSJW C ܽ%u6ߘZ_?#5T-Cp|3pu͛Ƣ? @V[T=~o*w>ѯ Ҩ_\ܣR>:    IENDB`PNG

   IHDR  6     I   	pHYs    {Rk    IDATxwwY{w
#RU@@)k;E
ŋrX;C:$!l{LH'NzHBz=`^{f<~^ߙ>?֬( zto9/ޫN87Km+U?խ1 t/s&KKֳw  V^۾4|g"aK<* Ơ{ofϖi.ݛ(ӈh ː&tf\stiRQsҽw 0F`!}o[>4~^w|)VGX&,6dԶ{aFkf{嗢J Xnjfyy_mGT,6s՗K} Zһ?Q ^!-R}7GRYpómΕ^1ճJ3U gicҹ0(M`q^u͝^T, `ڧgivyeU_Q`	lP+JpU%Uo- `ڪgi68M/>eh4ۿ& DJ?Hf?Vo 3bo:v5KM `AQ_|G4T;AI,6'u֚R$EN{.~ 3j=Vl34T7+V/1J}q;V4& }ڃUa-`&p[,^	WD U=RGYw%!`Xl
ai&{~R wpch4l]7Yl
OsVy7b @+[?HCiã?B@ MXmTo1  ՇܪgiVoZ:'#؄u?|h2mһ T[?H#־s! & m˷5O+N~ ɵNDs4JsJC?BYl
ѹ`^\[i^sd[ Xz<oQZy|z"MXןPj7deb 2R֗^oΑF=G)؄ew%Lw~ P]ӏ?H#G)؄exvyU&R W.qgiV)U?cL&,c#$BuGJ u;+mm˞&,S F }\4R7+;.d	P+Jm{o1 `%:AHo>)&b~>o-]~ +QV{%yHW)L&,3
pN
 zR%EЭټ>#L&,#/m~0AcsK^  W+Ɓ `	H?0h̭yZ} {Hu=&&,;^js4VD  O넏?+ICVե:`,6ah|]
os~[ <^4%iغWb}WieVRUo- ԷQs4L=XJb<WK鵣V  ջR[i4LO cb	6	8xjR5~[ sP05+`L,6!`Tťz p4׽7YJ޽WFr1؄:RyCk6/΍~G j/_L%XOGl1؄:<<@{o' %RU w1DMHq?hOd[	 `,|!J_ Kd	IWj7jv XVZG}(Kqbj_[V}W XUGK}W?kIutHbj|=T  QKKm{QSj[='!@#6t92] 0Q%mΥET%؄zw\ k&- 0yUU%-V؏FR%؄_&@/< '^GßODL%؄3@7%U Tn;6	6T`DPm-Jˢ:  !ڧ&yL@[Ό #؄d>5ҥFu  :&eGBYlB2o>5\> Rfғk`DL}JZ 	?|&= Fd	ɴNY?  <wӤ啕ۢ?,6!ƺ~V_~  ̜걻J}[SS}E,YlB2>'m[ `fu=&yM[?'#bkR
 LmBsJ?,6!??9m 0CKßߤJ0MHÇ6\"  in8)Mk`Lmg}=u  Hu'YlBND}}_Qo tڃ紲+zG&$=mRz>' V#鴢؄,6!聯}E-  қZ:,6!'MH&z筥o J"؄,6!聯igwn~K  ,ݫ?iEf	9YlB2_F  br؄du
  R&d	D|@oR~+  ,[vbr؄d~t=:m  τ?id	9YlB2:O  +BKJmZYlBNL_t j7πZYlBNL_t Z?&d	DZ?~ VՇ?jg	9YlB2%W b5}W3w&$=Wbk~ V[Kmß|؄,6!聿j~_r  Йl&d	D_A !ZgD-,6!'MH&z௤Wr =!!M*Mb+~ x&d	D-J_j  BkKmfόZVYlBNL_	uY2 ɟfbr؄drהmF  ,j<|؄,6!聿[Uz 0%~Բbr؄druG_^  o	br؄drJU{0 `o&d	DZ_Z  F?K*&$=c/~i AKmfϔʝ&d	Deך7D  ,A넿T,6!'MH&z/ڧsK
 UJ}?[*o&$=SmT_R  ƠsKbr؄dr󍽣_N  ƥ(^YlBNL_.5v})N	 u/?9S9؄,6!聿\tJK	 {ß5/Mbˡ~ '?o*_&$=ӷzҿ 	jKϝJ&d	DNDK n;/S؄,6!聟)E  LA_T,6!'MH&zgs/  SҿR[YlBNLZ}WmE|  LQs{ßC#MbY^qPK ￦6	g	9YlB2?cϽ~7  @?j؄,6!聟U_6  R[y3f;Mbj{/  Z,T&d	Dlu>"%  X𭥶zgSn&$=3J/  3uGO5YlBNLTc_.  fDԦ6&d	D,5| iTf&$=Ի
 R$YU&d	D5yk)UR 0ZG| yU&d	Dn:%e `F￺V?j؄,6!?5z `Qܪbr؄d׽j]K {br؄d,W:/  	4{ϯ,6!'MH&zr  Dsß_5;YlBNL[?TG_  iKϱ,6!'MH&zj dbr؄dLfR=zgK0UU[O.(v.J/iyௗ>o}':uG;nS_zןPzw|^;5dTϳ
br؄d,:Ϣ_nt/?ׅcP;?Lۤw<Jyەuǖ[ u/7yVYlBNLj	 p}ҹ?1g38^^'rG߹1Xm/	O&d	DYk(2ZM٫Ks{J}Wߡj~A0vT'0:n~w*6MbVӣ_Tn8OLi_!ۿp^sTF4 O~_*.MbTc) `fTGwc?Z껼2nQ¯ϟhw²؄,6!?K'@ה;Vo~/\rҽT=z|g	9YlB2fZRտr +M/+vYGfDm~OT?x}`#8>TL&$=gR +HkK5ￕPcD
ӻkwb؄,6!?+n  wn\Ͻ&[w~y\[)ZXAq%؄,6!?5vI4^{ 5R[~۽p'fC`{Obr؄d,ԹhXfGn/3wxiW9sR~ YU;$t؄,6!ޖ(UX&zUVoiۿtOLOGun&$=k XJ?~ii1 Jm9M/MbzK d,|oZc7eo~.,3,~؄,6!Yc7E?QS:ػw~E=	i}ƿ4nԲ؄,6!?~Mׄ_^]_Uz~~i:YlBNLkzyQiK1ͭ*>^"\C4M%MbQ5~/淿26K}g|&$= ik[}sJO-|*(_Lbr؄d~Hk^G̨ލ'.45zoW C,#I=f	9YlB2?}4wTJߺ@B~iYlBNLw̘%_(~?)asJ眵TUH{Q&&d	DiWt[̈@i{oݤ5}9?~wirYlBNLv*ȁѻREO=~j >_-M.MbӮsV/?~iy6,uqHzR$d؄,6!?ݧ{G#->} 6yYH&$=Y+}@uǖBZi|c=0ҿ:+M$MbӬwDJ5~O!OL' {JQw/AIbr؄doB+PUniwVv?Q j<\z7^:_ݺ4׽wxi=g	9YlB2Zzۥi։(G,quJkK}KoZbr؄d]w\QSԿRw&dVKJJ-}Zjk6[4YlBNLJk(Uk}QS2HOQ븿,?&HߋCwd	9YlB25}W1S2:ޑ}GT'-gι۔wB؄,6!?׹hR[~H
Anﺸtߋ9}Ɯ&d	D7T}u.l}#Y?:b~{Q}ʧJsڧ؄,6!?_#&]iVD`y/v/kEf	9YlB2O|u1ԚKS?J{1o=tۮ4ӏbr؄duҽw4zV}IG
f[9\Wi祱O&_iYlBNLd$x	5i\wxi#[>#s*&d	DI6W.Kmg1ҸkSj=|aQZj&$='Yו?~HyE`bwsn;iYlBNLdգwF/0FURw4ڧ:ݗ7.c?bjd	9YlB2R5v{m~HSinU^sdF^̅_)?3S+>Mbu'?}HӬճKk?zAUһLߋ)m Mb{GIuwQs)U ^Li,6!'MH&zOMJUNcп
ʨ]?KϗqQ{t4 ebr؄d$j3
C^.N\gK!Mb>V`'M}"DkX	:bnL؄,6!?z7}n>m/CG'ҬOXGLڵ^L4,6!'MH&z՛>X%/OuG?̪~ｲt/ݷXiFߋ)g	9YlB25zsK:w4?!#?tK~>|/4YlBNLw$KYm;Uj>į~/߇6&d	Dq׽#FmnGY?2)NsŔA&$=];7F)0Y~HY5dJkKCJO=+kޒ4,6!'MH&z6?XJUE)0wUjk~Hf^]]Pn8^SFme	9YlB25F\;DVzYs_$M7MbsFпCNe_{1%=E&$=_Si-գwFWbBuKc﷔f/MbcknUG'0޷HkR_oI9؄,6!?>(aUUitJ'rjL    IDAT:?t%/]%br؄dj5Uեt<:һ'g"5؄,6!?:_#(!5CZNϚXb>pm^yHimvKbr؄dvnQCw,5O+o(+Ŕ4YlBNLWUG	ui9<7JR+/xWʏ@@؄,6!?;,!TYjk6;Z#ʲ<+[Z|4xCm~ޒTYlBNLGC~'!O{CZwdLוIS?HJ&d	Dq>}wj%걻JcKϔV[?'%i)YlBNLGݫE#0_
3̢|/1.]_^4,6!'MH&zWG#0w!ZGIG~ż:SҊbr؄d[y)v1R[oH+UwǅSW)k*S>U>=$) MbKכP+~gH+ƾTJUMlٻ>{MiR}%iV؄,6!聿ZGiJ}JwqKWGKֳJJP;h/I,6!'MH&z/̾ꊾ/Zs).Q:UZyiSbr؄dR^{t\ߋ3JR,6!'MH&z/WF!1NoBZCZWDH$؄,6!聿Ԫ#6wөw(AVJ&$=R}F0q~_H$M3MbKi{UWI؄,6!聿Z~$zv]!I4,6!'MH&z/W>>`#gK]!I4,6!'MH&z/7>>`#R]!I4,6!'MH&z/ݗDx<$Iv&$=Rx8En>-$Ibr؄dշ{A>$IYlBNL>?}tF4B$)"Mb<G,kJ&d	DQkѻ{B$)*MbVG,s$IRT&$=G{G,u	I,6!'MH&zZ[_>:`p$IZYlBNLWG!UԷzv=!I&d	DQEn#$I"؄,6!?Rk^JUE뎋'$I؄,6!?J]_}l":'$I"؄,6!?J}l"ZG}($Ibr؄d(c;	I,6!'MH&zROF
'$I"؄,6!?J梏ؐ*[$IYlBNL΅>6`#$I؄,6!?J+>6`w_~GH$Eg	9YlB2z7}l?>$Ibr؄d(0؀\g!I&d	DQ?xC>3w$IRt&$=Gi uGI,6!'MH&zܪRzc6y	I,6!'MH&z[}E'$I؄,6!?l]_}d"_{B$):Mb-G,	I,6!'MH&z[sEN/'$I؄,6!?l̓~3ȀEn=!I&d	Dak~ؐ*՛$IYlBNLQ>2`Cڵ;B$i؄,6!?l?}dT~GH$B&$=}En#$If!Mb>Gl@IYbr؄d^}dXlJ$=&d	Da뜿c`)ID&$=sGlŦ$IYlBNLD$IOd	9YlB2غW>2`߹1$I,6!'MH&z[ã MI'؄,6!?lk>2`,6%Ibr؄du=:Ȁؔ$Iz"Mbֽ#6bS$,6!'MH&z[ MI'؄,6!?lN>2`V!I4YlBNLލ}dT~GH$B&$=DU;B$i؄,6!?lO>2`Cz;B$i؄,6!?l[Ό>2`5$IYlBNLޭgG'$I؄,6!?l[ϊ>2`_~OH$Eg	9YlB2z7}d".$Ibr؄dn<9ȀE4yk=!I&d	Da]w\h~$IRt&$={͑G,y$IYlBNLU뢏XD$IYlBNLEֱ'$I؄,6!?lK>2`?~OH$Eg	9YlB2:;ȀE{B$):Mbֹh#ѹh{B$):Mbֹ`#	I,6!'MH&z[XD3	I,6!'MH&z[G,$IRt&$=>2`cw$IYlBNL։}dbzR[~WH$Ef	9YlB2ZGYQw$IRd&$=y؈g<$Ibr؄d5#6/$IYlBNL~}dF4׽'$Ibr؄d5zs:/
I,6!'MH&zw}
I,6!'MH&z[}Fv+$I"؄,6!?l}dFt88$Ibr؄dmRJUE޷WH$f	9YlB2c,$IRd&$=GzcQև$IYlBNLWD~WH$Ee	9YlB2z}lF4B$)*MbԽc6yo$IQYlBNLEG]!I&d	DQꜿC9gB$)*Mb>3lD
I,6!'MH&zR넏G[+$I؄,6!?J(؀?xC]!I&d	DQjc6]+$I؄,6!?J&؀Է}~}!I&d	DQcM$IRD&$=GjJ6yI,6!'MH&zZx8耍hw$IRD&$=Gm/.s6w$IRD&$=Gw۹GlD/$IYlBNL5GF;~WH$Ed	9YlB2:}tFT~WH$Ed	9YlB2gkoB$iYlBNL>:` ~_H$M;Mb<GuIig	9YlB2@O$Ibr؄dw~E^o}!I4,6!'MH&zܚRUlDֳI)g	9YlB2)U}|FT~WH$M;MbKelL/[$Ibr؄dR]|hB$iYlBNL_J>>` C~_H$M3MbK}g@/$I&d	D:O@{$Ibr؄dRj~w)$I4؄,6!聿껾:sS}!I4,6!'MH&z/[RUGlL]j73$I&d	DV>B` ]^~_H$M+MbKeGyo$Ibr؄dR]|hw$IҴ؄,6!聿:~.t.+$IV&$=ZOE!0ޭg$Ibr؄dRk{O~_H$M+MbKP}$Ibr؄dRo#Iid	9YlB2UD#0q~_H$M#Mb%sN$I4؄,6!?} z7G}!I4,6!'MH&z;D#0[Iid	9YlB2ND13IIg	9YlB25cw$IҤ؄,6!?{M1j'w$IҤ؄,6!?l^J} :lgH$M8Mb-G	{Q$IҤ؄,6!?z7} _~_H$M:MbsG	.՛$Ibr؄djwG	h~E$Ibr؄djG	w$I$؄,6!?껾:(OL!I4,6!'MH&z՛mE'0$Ibr؄d8?x}q}I}!I4,6!'MH&z'E'0Nc᧬IIe	9YlB2ukqj;C$iRYlBNLg:8!I4,6!'MH&z}:3$I&&d	DqV%	wqw$IҤ؄,6!?G
-$IҤ؄,6!?w^} Է~N!I4,6!'MH&zD)0ƾ~gH$M"Mb}?G)0	3$I&&d	Dq<]G
sw$I$؄,6!?껾:Hn;/ΐ$ID&$=&t
j>RjsI1g	9YlB2f;C$iYlBNLDݫ>V`@ߋ}gH$;Mb}c>_Iqg	9YlB2@~;C$iYlBNLD2X&ΐ$Iw&$='J鶢D[jk7$IƘ&d	DIտ-w$I8؄,6!?W>Z`@c>~gH$3Mbj/-9t.)ΐ$Ig&$='Us{PIqf	9YlB2Rw}U~gH$3MbknUZ룏P}$Icbr؄d$uqjw$IҸ؄,6!?ɺ}ڧ&ΐ$IW&$='Y}W~gH$+Mby;P
3$Iƕ&d	DIVJ}$Ibr؄d+5;C$iYlBNLtO>b`@S>ΐ$IG&$='][E10$Ibr؄dk#Կ;C$iYlBNLtxJmg$IKbr؄dě[U񅟏7$I&d	DiԻc:w$IR؄,6!?:_#u/7ΐ$IZj&$=QE30ݗ$IKbr؄d4jcmښId	9YlB2*ݢ^'5zs!I,6!'MH&zOWG50ֱ3$I&d	DiսKGsw$IR؄,6!?_Ի;C$i)YlBNLV}6I!I4j&$=U}D50n7$IFbr؄d43`!I4j&$=YP炝IQ؄,6!?:_*n93ΐ$I5MbӬuF70pͭ
7$IFbr؄d4PIQ؄,6!?Vhj{C$i,6!'MH&zOmE90ιۆ$Id	9YlB2u.=ȁn9#ΐ$I%MbӮu̟G90? $IRf	9YlB25xCCh|'Ia؄,6!?6)Uk}j{C$i,6!'MH&zGA?~gH$&d	D:_5؁n ΐ$I6MbPKmf$I0YlBNLkBc7$Id	9YlB2?Uj>}Ze!I4D&$=zv^;C$i,6!'MH&zG9Կ;C$i,6!'MH&zG:⏣TSjk~oH$&d	D껾:!4$IҠYlBNLBF?0ɟ7$Ibr؄d~dO>~`@+3$Ibr؄d~ds>~`@3$Ibr؄d~d0AUR$I YlBNL+B~oH$&d	D/0i~gH$&d	Dz7 ^sd!I4H&$=뜳eK zw$I YlBNL/0/
7$I6&d	D;4% <wIe	9YlB22 j5~gH$m,MbP_`@N
3$I6&d	DY}P}w$IƲ؄,6!?gG}$Ie	9YlB2oCTUKyIŲ؄,6!?+9 9o;C$i,6!'MH&zJݫEz>'ΐ$IZ,MbROEڵR[Y!I,6!'MH&zJ}1 M$I҆؄,6!?3ݢn+ :$I؄,6!?K4 Խ;C$iCYlBNL:r ?p]!I,6!'MH&zRc< UUIbr؄d,/0~oH$=U&$=gUj< j5oH$=E&$=g-gD$z7G!ITYlBNL:n ]I{C$YlBNL Ch|5$Iғ؄,6!?kշqKu̇I'g	9YlB2#eԹx;C$YlBNLź sY!I,6!'MH&zb9eږ7$I7MbX~Y!4{!IYlBNLɶ|f)nKhIbr؄dֿPڣIbr؄d    IDATֽtP;C${؄,6!?/0N/7$I+MbZc7E4ZQ!I_YlBNLVoZ/0;$I&d	DYw۹/0$I&d	DYsN/0Nl~oH$g	9YlB2> >o7$I؄,6!?w~E}'I,6!'MH&zz{_"`@+~gH$g	9YlB2]BKo$IYlBNLgkKJ}$I&$=gACh{o!Id	9YlB2֫oR~s$I&d	D>eԻ;C$br؄d~W2JmI؄,6!聟I2Ch{C$,6!'MH&zg~!OL!IVv&$=SfR:
PI؄,6!聟ETå6I!IVn&$=Թh
Bc7$if	9YlB2?K>RChW$IZYlBNLR?RC^qp!IVn&$=4TD\oH&d	DLn:5PI2؄,6!ޝ[V J`L:V;Ѥێt$Q߄vHӉIISU@1TY C!L%R2(   S1sA1SY{^ysHG✳>~?ֳgys>#pREяʏIT,6!O?@fssC$3Mȓ&d&ϩbRGPyߥsC$3Mȓ&d&ϭۣ0SNi!I&b2}VwGB$~YlB,6!3~nOR#f}ֿIT,6!O?N#fwisC$/Mȓ&d&ϮE[kG?6`4`!Ij&b2}XyяIT,6!O?:,~l,O!I&b2}X0k>7$IR؄<YlBf/kB]sC$+Mȓ&d&ϲMRU<Y("~vHd	y؄D_ֻGB?$>YlB,6!3~u9н!I&b2}ZF?:`ʇo$>YlB,6!3~mRUE?>`*{J$Ibd	szB菇IT,6!O?纫VF?>`:>7$IR=؄<YlBf/kBsC$#Mȓ&d&ϹA~/$i؄<YlBf/[eJV#f?$i؄<YlBf/+<йd!I?Mȓ&d&Ͻ%ˣ!0k$Izl_G'ML{w~lgsIӊ%ۧJMxj~؄<YlBf/kGRs埄IZ/;uk{_~؄<YlBf/$UţяE{I-Rc7IKݫW{bF9;&b2}C~Y(&|nH4{v#bR|_w.XO?YlB,6!389wFUbg$I\od	y؄D_PF?F`G}8|vHb>8{ŷ'Mȓ&d&~kO
$kwG'ML?.U(Y(*|nH4ߋL{nbd	ǥяl.6|vH4Nߋ9H﫟,6!O\jG	R;>;$IV.{1^L9qv~؄<YlBf/qqD?J`:>;$IHLߞ_{SM|{#Mȓ&d&mR8Y(<~vH4_)o^A؄<YlBf/qjHKI6VeyGRRdП&b2}SKG?N`!I҆|TW僫G?YlB,6!38:~	R}g$-<5};d^bVe82}?>؄<YlBf/q'0K7IRMӈG@~fd	y؄D_c&*~,K_??$Icl>{atJG씏bd	ǭm?~,NT$[}/Tlbd	ǭι;G?R`>;$I}/ԯCR=qw#Mȓ&d&G~0T[3UC4R9ߋ9Ϫ?~؄<YlBf/qm*$)byG_OV=@'Mȓ&d&ǦK/I</!LԽT=yOUĳT~؄<YlBf/qjecfwiC4nfjԽT.}0>;}d	y؄D_X/F?V`ړirіC4Ŵ`QOb2}c+s0+C4/c"XlBf/lb&dsCv~AjCj{T>t?8ƪ'?s}d	y؄D_ZD?Z`{/kfSS碽^;`MAsG'ML?u.\h*{CӿR~YBe?9Ð'ML?XyG${1~b>=A#7~؄<YlBf/qXGACƪ[7dʇn?}d	y؄D__rR>rK쐤lP3G'ML?u?.sP,{usWʛODpH5g,6!Okя։4jm+%?H1W2&b2}sS_䧻je|/&#BYlB,6!3Xh++G'.|H|}/~>LWTvG1ޝ>bd	ǽˢ10~;|~HҼ|/fջK?YlB,6!3׹hGA眝$[/N5_wl֭0cN&b2}{c?9(<|~HҬs7I󽘌?W}d	y؄D_^k10U%/!=_Z:zw_R=9aW9'Mȓ&d&¯Cպ30?>?$iߋX􈄡\g,6!On<)1s0}tCRͿzq!:.<&b2}ס_~TY=C${1#>؄<YlBf/:<30GS"i=`d4'Mȓ&d&¯E; 9\4~Hʲb+Rs埤{ޝL80s1sO'ML_WD?j`5ׅI_6^_I'Mȓ&d&¯K~^>C$P6{11u/?bD罏,6!O.x}߆IqKO?{1a5W?O'ML_%/~n:%|H%f?UhjO'ML_'~\t4h"ixu?.Uk6hk᳡,6!ONuW:#X믌}d	y؄D_u}70GS ,zHNS`_>bd	Tc[70GwI#Ħ,6!OV-,Uя1~HxC?z R
f	y؄D_uwя_	!_=^gc^ѳ,6!On^ȁ9*8|H|?=^g)&|6&b2}׭a~\UU*"|Hl%z һG᳡,6!Ovnc#Z=G,kf	y؄D_u\}ecj$YãG,Kf	y؄D_usяݶ#WS',sφ~؄<YlBf/::ϣ;Ї	#WcxWl7Mȓ&d&¯cҗG?vN#Wx,z :᳡,6!OUO聹R6sD iGwχ>؄<YlBf/ֽяC菅IMXχ~؄<YlBf/6A@VI<=Xb+CYlB,6!3~]k,KP֦E[I_E٪*M.|^|7Mȓ&d&¯mx4}h~DR_u)z RM>>&b2}׹{ŷ爤^ux(|0,6!OεO*I6%^G	,>&b2}׹o~@3|H{壷F`L#bd	k݂ͧ 	Iskі)1<KEa YlB,6!3~zz ~]ʲD`=Z'u|D'ML_gs <}DkGχAd	y؄D_uyG SDxq ֣oχAd	y؄D_o@Sir牤Yջ{XbχAd	w SOI|<[&'6bd	}c wD,ZUJe/zt 2À؄<YlBf/|Bj Wݶ'fwwaPYlB,6!3F u牤:/Gbd	t/>
@zw>K$ͬyG`=g~-|>*Mȓ&d&u~kQ UUXy"؄<YlBf/|=]E` g|%|Hz&6IUqGψe	y؄D_zbN oׄIϛG/bd	.> 4y"iõNT ֧=93bPYlB,6!3~Z炥?J=O$m%ˣC7χAf	y؄D_i> TON6)_1GS ؄<YlBf/|L;mR}$h"*v2zD ѹ3bYlB,6!3Y0 >O$|SM1,6!O_Ϭ}#BUb٫ggֹpYt 6>#&b2}5!H >{aLWD`_>#&b2}Y-<Uj}irfsEtn/03bYlB,6!3~C)u_F`{/bd	Or wg^sdH 6{3bYlB,6!3~~},A)X"վMRnMD 6}?ωg	y؄D_z0h >_TV( 6sbYlB,6!3_wQG;ĦsEsvF4yct'ML_E`'|Hu|1 lH&l>'&b2}k^}4G)z Q"|N#Mȓ&d&׆+-x R_+R[`tu:<|N#Mȓ&d&׆^v` ssEck?FOrF'ML:cN^>[:7?shY1,6!O_m__ԯFNu.zx/bd	>" U֤E[MlE쁍=?+&b2}ku.X}Dk"աϡwbXYlB,6!36^F`&EqCebXYlB,6!3E[. 6-4{JJvGxc?>/&b2}cX3g4εZ^bd	ܵOcZU~>_lbT>v{xUjMȓ&d&sWcAw"cqgϋaf	y؄D_Y7F`Ъ255|HV?t-|^3Mȓ&d&\gQ{	E-cPkGg0؄<YlBf/|ͬ>*k>cq{1џj`2|f3Mȓ&d&[TE`z7 ~HcPcץTv?Tόag	y؄D_yO>.4#^ã??YlB,6!3f^E`Hz>ckz?	i0|n;Mȓ&d&+" C<sFʵ+?,4{Wv'MLU. Cһ#Xc7iMIM.ۄώag	y؄D_]D`+0|Hջ.0+|d	y؄D_]C? CT>v[\eri+t.'|vG'MLYpT5>6JrhbTyG&b2}kuo8! CTץbg4NT?=?#Mȓ&d&k}F`Ⱥ|'|H\/jU`'&b2}kKO0dS=oQsQ`
&b2}kn\}t!+&M.,|HVTQ`ڧ|!|W'ML􅯹9w̃:@iF-<\樱<e	y؄D_[}tyP5OŒiTj/K`Vϐbd	5&6I0z9;Rp3^;#	Q#|f	y؄D_{pG뤿9RhJ?@Z'~&~c'ML􅯹</sGsџBOŲWϒbd	G#̓]ɉMg45`JUP>v{,,6!O_ս#̣;|HYU*}^~P<,6!O_:GOVjkG\}E1)&b2}᫿ۦD#`^&w:|Hî{7`*4|w'ML~f1Y#g4Z'>cH&b2}Z'M1ObQTv?bt%|Dd	y؄D_b_IE%`<3Hd}ߜџ.`  IDAT#|Dd	y؄D_L~} պ5X$bz0@U4`&b2}k0G	RwI\ecxWEZ>_؄<YlBf/|ؚ@&HK.ۤK?F1|De	y؄D_\E' PsHu;=?<7CUN|	bd	5ڧcqj,fܢRӣ?6_?g؄<YlBf/|b٫::]U	GsUԻO0DsϚ,6!O_#D+y瑴]_{/ C7YlB,6!3[D)`t<g즾o|O0dwYlB,6!3[U~xZG/|.IoHcE2yйh&b2}kS󨏄%y|8̓!>w؄<YlBf/|_>V(SkGg:@=T#ir':Mȓ&d&+lRUF-`:I5kfsѧg+?#&b2}k8<7h.|>rvF44
YlB,6!3SG-`ĦsJ[[=UO>@.M.*|B'MLT_=XNU&6M3^{t,,6!O_ëwa;N*GŲWޝDk Xs埄ϣQbd	5Z'|*x#|T,{uR޵NlZk3lj5f	y؄D_^.xSU<'|f)=CtrFDsiy؄D_nUGE1 U:
ifMlZ8G/~>P'ML\#d{wSqRyG1U?J,6!O_CnZ`12R=yOjK#U/ΥTGAS&b2}ku~W1rSU{Airg[:s|8T#yϫbd	5f12U>t}j|1}		^;ד&b2}k~ZN IKݛuibU'Dek؄<YlBf/|O3}ԀM}__Z|E4MSrGLc[gf	y؄D_r ջǩsMjugR-GPyeslD؄<YlBf/|_~}܀qQMsSIO)_g&b2}kj^'u^eqYoxp}6SڨfB,6!3E[x4Hъ]I>{/>)^{t|,6!O_[}0Ϊ2n:%5~G}S:j>jY7YlB,6!3淩?0zwG}$M.<|mwwgC55c&l>F9Mȓ&d&W25R=@ꜿ$5yc&6I>|DǻϿbd	5w=*b,̺E[aJupĳ؄<YlBf/|M0V~VjX}\̡bצIKMUkmjw31,6!O_1uW>z O+{wy}ڗRc7Q5u{!zG}8|F&b2}+桿} ֫Zf~:q弴`OD+R]я`'Gf&b2}+MR9UߙW{':n9<x>{Aړf9K'ML􅯸 ;UGoMkN3Z7R6s[Y*j['~6u~8n^c KN*,~f&b2}+b^5=?ueb/qG755K_><;wz~*bz<=u'S:,JLLcMqӽלy؄D_{aG Dx鞼w')\}E*W_9oYw&b2}+Ɓ} qSg;ڣ]sbd	O( N\;knYlB,6!3zQ ɝ_Κ['ML_G 4آWsbd	5u~ Sdw؄<YlBf/|FŞ xUG&b2}kttJq `4w\؄<YlBf/|N} ;	?9Mȓ&d&5I*>H 0ӌ؄<YlBf/|V&H |49iiYlB,6!3FNUh  P74,6!O_W%  w&b2}k**}4 0D&b2}k4Z}4 gպ䢭E!Mȓ&d&hX֔*x 0?qbd	5n?+x 0Ocewqbd	55xo `tY9NYlB,6!3F򁫢(  CV5HŮ/,6!O_]븿>  Y,6!O_#ނS !G}؄<YlBf/|~Ӿ}L O8f	y؄D__8_ /պN[oc'ML<jh" 0`S9YlB,6!3X鿖	 xz Mqbd	Osw>  Hχ_s'ML|*v.U,  }*%M."r؄<YlBf/|U炥G >5WI{g	y؄D_ʫb_ ދ&wfȓ&d&W~u.; 0G̓wC'ML*lR}t 'K%Mȓ&d&Wu./ 0e75yS{d]؄<YlBf/|YH=}| ΥC)Mȓ&d&Wu# 0U?X,6!O_V,6Uǣ0  ϡ}ڗ&b2}+g/>  lDirubd	w/LC hx;c؄<YlBf/|_} Xލ'+5Mȓ&d&hT/( zƯƿ+4Mȓ&d&x>o2  ?snubd	5&-"} H)Uk.wg	y؄D_G}88 Rj}O&b2}kqv ޭbre	5^5͔2X SHŞ'&b2}kZ} j}Wt'MLXꔺ P+kc.uGMȌ_>  Qq;oMlR G/5v8Uţ i0Gɥ5w `UONmӊݶ>YlBf}~kL[Y*& Q3j0G_ߚnJU} R{N b28ƻ `<}Wߗ?̑&dy§/~wҗ. >uY}<9؄̴=>󟣏: +]F`,6!3NU>/} W=@*v;m򁫢	0G7_Go  d?
F$d1bru6P- i^}L>XlB}zT,}EZOEy L}/k?
MP	P}jG  /e75|{{?b2Թ ըMSy  pQMP9)%@-
 I\Yf'MT[_T:|= 6{6M3u磏'MT/fT=qW YS&M3wG&d{/_>  #{jyŒFOJŞ!P:* %=M3}W0 ً_Tۦj `4th]O0 ut<C `$NtfW〷E`@,6!sonYoG PݫWiW}t؄u=&@ũzjuG   DW3ÊeJێ>>XlB2{1Ay?  jK}Sf_0@0:Wս  :`}Œ0>,6aTճbR=џ yѹ`iV}0`0&:+EAy{R PQ\yf_5aYl¸uS[_T:.  or;VS00Fw_&'6	iPM[E*,c  0xfj_߷4Z|"Cb	cyg_T{~ ։*v&Uk>BXl)'Mn:s \w^}0D0:Wz׻ @z&ln<C)%3MS2EB_ Sx*}L2MSek]*~c[wT?
  V^[EcMcK=?Bs 鵧m{xhSMs+	P4na  `Z9YBXlBNշbj w'ͽw4^7b꠪Rφh5_ UU+&M[C?N#bʏpOџ yN\eVc[Sx<,6N8/iE
  \sm*o9fP9p1XlBݴ&Sc;0)  V/K_<)c؄:uR8Q15%P  Vx,5ySVCA&VUBz:g  DN94ixMu6AQꜻs w8]HX}M <{6EE5cB}҉Ҭk\:#bV6H͕¢15F .K͓?Yp9o^	F&KO=?F5*> k4{k>:~N}y_Ȩ>5R굣> 0Lf^e{2 #bؠͧbׅبOB P9a;mg|%	M`:>w4ˋ_t4u.7 c{irbwmb}ֿrCGȌ&0#ek]jir_|4Ml7}1н4`mb_Nx, fJH^ҘSyE' Xck-,5ߡٞ>*@,6){{y_u;mcGr  CUGIQkb<xԹ,>"kꝫLߛ/Pߐ dj(4IjRן`	&0XԽ:㫩8Һ	/{ߑR}lSd^2:s{É\&8 5a	U|*uo;#//NBj4gF)+?:  mejX]uD\|vf{IꭹOb)&/:    IENDB`PNG

   IHDR         F   	pHYs    {Rk  IDATxwibh1p4&@$DHǒĔWw,R-"%,eiW!]|73}7wgw'I@ @ @
:szW
;_`m)Aʑ) #o(Պز{Glm/? );K}Lq@l8]ڂ&_WPxo_Ƕ@-{2\2%Pz &H-j_dl@Wa(u]"mnWɣWܗe5YW 0AzWe7}MS)E]}s~_-z`BHZWcū}Z\X7$Q(h|I-vp*Z-T5#%׆?,;
\:[CH[\}_&pN2f͌ZFI)t>D)` :'!	oSz \I`7X;. QO[ e#;eL+uw	0wN):G.c2+j]S#-17FG -p```_QY厰zn4R((u` mA2<֡enWd-PF}@fLJ(Lc!V16+<n\|gҔq>[QQ/>;@!*8OkV`n
QC[?k!
ا<Cp\җ!
}x6#{wrwtC߆ɍ`lZ3 ݳ@ڬuQUqjص{KTY	XMgI@'	WFVXǪ=KgYe,zygo eY?Ly||ϱ j;漏/er_Qd:O``ƦN^F@jc@ɮFS/@|	IےoT }_*xioU
;57p4BȬTZIdOIyh{@8B@ ,I $)y"'<(i@H(\YcGBpR*7'<މbl=,X.@c(	d1H$.aR.a*bPx'<4~
.p@H<4N"0bJ9Xۻ0Spr. `$rS*wY[E޹@}ܓbܶ	;!N"qx+Tebޖv8E(I\ y@ybޖ6ge
ő)IQv/PE_wd1sT}udb7[ !]y'0<D2Q?=,}͜[;;,.@|;,@@LHJ }t3	e1R&>
Q?=,f\VhrO(Y$ݭroc	e1=(ub}HHZeqfhDH
ZRn:/EjMw	/$b)	mx'(RQN,I$/'$R8@f^".8X	TOWsO,I,Fb \HY u@;DQoil=,jqݶ8Uc `>	ɤ?ch(ȣ 8pkȃn~+6>
p><K7~(~kn/;XUZZ,`m'33?_g&ځP'LC~h?wk?4Ɔ
GVepo,idї.-b8W`?8c<>R:Q"?+<6F_kl]XnlU*X0	eO$31jyBxK	u }}Hk @pwQu'OT(:adN4x!} P:(z#<2iǽY-&U̚	O:ԡg^_OP|;wia@9:FU>wiX@W:z-yw
5D^W.%
x9:~1w/]w@) C~7ٗ5.GCp󠌺?|yBz?QWYx/lNhRb`e`rAQ<@zdȂȭRQ©?n<MA_kD _9,wr.Fb;E	L86x\<^ܙڟgJOբ4 6:US?Z<.Pm`n/DCI"0n)߄7H$=P%Y=1\2#-_bCЀu`qj*A
D}+<OQWjKm̽sR>BΑzXFR\R"J7<	$v@O@o4rڒJjYa`c\ԙ=>칒VLI}es&sT,[HƜ>]4 V&ZR@GBqՅ!7_s#c(U_Υ\y\*z&QآG V+G +Ѵ'V"QVXGe0ڽ?&6-rywÐHff2?omXWP!5V6DkS!=ư/"5Q=KPgl%vNŒ6^G)ꪪs06@ @ @A嫟(]=    IENDB`PNG

   IHDR  
  
   .   	pHYs    {Rk    IDATx1 0')(zF;    :     g    F!    `    F!        0
        0
       Q        Q    (    B    (    B     F!    `    F!    `    1
        0
        Q        Q        @B    (    B    (    b    F!    `    F!        0
        0
       Q        Q    (    B    (    B     F!    `    F!    `    1
        0
        Q        Q        @B    (    B    (    b    F!    `    F!        0
        0
       Q        Q    (    B    (    B     F!    `    F!    `    1
        0
        Q        Q        @B    (    B    (    b    F!    `    F!        0
        0
       Q        Q    (    B    (    B     F!    `    F!    `    1
        0
        Q        Q        @B    (    B    (    b    F!    `    F!        0
        0
       Q        Q    (    B    (    B     F!    `    F!    `    1
        0
        Q        Q        @B    (    B    (    b    F!    `    F!        0
        0
       Q        Q    (    B    (    B     F!    `    F!    `    1
        0
        Q        Q        @B    (    B    (    b    F!    `    F!        0
        0
       Q        Q    (    B    (    B     F!    `    F!    `    1
        0
        Q        Q        @B    (    B    (    b    F!    `    F!        0
        0
       Q        Q    (    B    (    B     F!    `    F!    `    1
        0
        Q        Q        @B    (    B    (    b    F!    `    F!        0
        0
       Q        Q    (    B    (    B     F!    `    F!    `    1
        0
        Q        Q        @B    (    B    (    b    F!    `    F!        0
        0
       Q        Q    (    B    (    B     F!    `    F!    `    1
        0
        Q        Q        @B    (    B    (    b    F!    `    F!        0
        0
       Q        Q    (    B    (    B     F!    `    F!    `    1
        0
        Q        Q        @B    (    B    (    b    F!    `    F!        0
        0
       Q        Q    (    B    (    B     F!    `    F!    `    1
        0
        Q        Q        @B    (    B    (    b    F!    `    F!        0
        0
       Q        Q    (    B    (    B     F!    `    F!    `    1
        0
        Q        Q        @B    (    B    (    b    F!    `    F!        0
        0
       Q        Q    (    B    (    B     F!    `    F!    `    1
        0
        Q        Q        @B    (    B    (    b    F!    `    F!        0
        0
       Q        Q    (    B    (    B     F!    `    F!    `    1
        0
        Q        Q        @B    (    B    (    b    F!    `    F!        0
        0
       Q        Q    (    B    (    B     F!    `    F!    `    1
        0
        Q        Q        @B    (    B    (    b    F!    `    F!        0
        0
       Q        Q    (    B    (    B     F!    `    F!    `    1
        0
        Q        Q        @B    (    B    (    b    F!    `    F!        0
        0
       Q        Q    (    B    (    B     F!    `    F!    `    1
        0
        Q        Q        @B    (    B    (    b    F!    `    F!        0
        0
       Q        Q    (    B    (    B     F!    `    F!    `    1
        0
        Q        Q        @B    (    B    (    b    F!    `    F!        0
        0
       Q        Q    (    B    (    B     F!    `    F!    `    1
        0
        Q        Q        @B    (    B    (    b    F!    `    F!        0
        0
       Q        Q    (    B    (    B     F!    `    F!    `    1
        0
        Q        Q        @B    (    B    (    b    F!    `    F!        0
        0
       Q        Q    (    B    (    B     F!    `    F!    `    1
        0
        Q        Q        @B    (    B    (    b    F!    `    F!        0
        0
       Q        Q    (    B    (    B     F!    `    F!    `    1
        0
        Q        Q        @B    (    B    (    b    F!    `    F!        0
        0
       Q        Q    (    B    (    B     F!    `    F!    `    1
        0
        Q        Q        @B    (    B    (    b    F!    `    F!        0
        0
       Q        Q    (    B    (    B     F!    `    F!    `    1
        0
        Q        Q        @B    (    B    (    b    F!    `    F!        0
       }GIv. L`k`cql/s8\ñ%͌((BJPF9g	HHwW8zzRwuUg_^{J]]U`Q    (    ,
    B        gQ    X        E!    0΢    (    ,
    B    `E!    `Q    X        8B        (    ,
   q    E!    `Q    X    ,
    3oՇƙߗ%IٜR6Vf|k  f=|vt&ՏxjΡ३>NNEHL?ͫʖ/yu*5Y  lIYٟ!$M|z;G;SUoQܐ:w g.R/R{  ,l,!-zej|S^uZ5XS}T?M\P  VE75ODL!iT_+Q
FwQخǧ߶V?䝩x  'El!i^j:4FnQ}Լ)[o"i3{O*󧢟2  @?𤏅f=v][ҨEaRӉ55@*뢟6  @t[qGgI[}z1`vj߰"\75K iƊfw/u;i碰'#HR?2  kS
=$Ŕ/Ծ+/FC(l~Zz{xi[k%7  0ֆT?}3C!u>7YvW'li[k)~  ᳈|(u-_SϦlq~  |7$<R\@/
?5&'JSuG?  @|ׄ&%I;Ll źGR?(Mօ_~*  xk"i0jשȞJhOO^/&MyT  H)[YEҀxYƿYG?  Խ)c"i@]o:4(bQ}@4k{Je  Tc{ˁEKX*EaFY$  CI^/KYEaIs?BCsђ  j+|4`1.߯TPRY<  5Eq߅o/
uw?R?rc  `ʊnjs~異~wlׅ?R?jiI  LO-|4x~1V械m)[YG֒  2*|K#6pKߖEa{>%Q^"   /|+Ik7FcQ}ʔ-%APiI  ̈S6GRm0kEaM)ԇ+>R7S  jvJl>H\?碰])[[(f  C$w"zŚU)[OGeJecL<U   &<g!I~įnǢhm74TnxO  +qDjY㤏T(R?XR?ym*<ק  Vk~FjYk^6IGW;   fRg$Ikv}I(l_<PǋSȵzj   LKYIRmEalN4=?uﻰO  {~?3IJV~[{2"{2e.AS3  e{M 8/cQڟ?Ҵ]\T_T   3y$A}q?R?j_ߴL   3H>CI\c'J?tk}klZO"  Y$do&ilG}0;ˋ¢Kӭu?N  x-xaL%6p.
[W[?HL  si[$%EafUSʦ  o=_I\>>;W +M|7rSz   H4|ΒT:}sftxI*u(   ]j*zޒT#n{VʗL?Rr󞟺߽x
.  `+׬J.Iij_w,
[W.ISnvsWr  +S6wKR_.
f^Zӹo  B%@.
[/GISyM  e_9LRm`<uY5)(i*5`5  lm}A<&60.ۻ?cT?䝩l=  0Tշ|.s@4aGMsQR1Tެ\PY  ҹLRm`j_|zՇ#mmfc7~  J>>ID6⢰|'!mSswHݻΞ  `8񳚤4u;mCfj  Zzo=I8Ꮷ(wÿxi[jS  ^U)MR-;b۶(,<{	g/me;    IDAT#ޗR9*  Pk_y`&^mQ֜/Z}_O}
  0'},|T]۰(,/Zڪ00W)  h(R \*Umݢ/Vڪl:8w)  (J}­[6/_5.ٸC  FNg:I޽¢2T+~  `
25NNR-7(>te)mAoｯ   SWO>$Bj_}͋;6WKS{g  YUl᳞ڬ7Wś]~16Rsg  y{lkJb>6  ge+>>Iz݇|Qؾ/NT&  rc)_['6/{Eaɪ)w%  @et=+jڟO(/NouDܑ   ӺsڬEcO95gԽ  zT?WAIi*6<EaoQϏ  *x/%|&Tv9eQҏ8C)Ȼ  :>JJ+|q'ÿ(TfOFމ   %f8~΢h`]uy]  @J?ȗ:~Nfѿ}-)k_E  t:;|NT}^|x/HqT    <35g4j.Tt*k?   &jesڌU{to8&Qśs*!  `G뽧|()D#y_]#<   QRmF?qYbTݚU]  (:~ϑj}sWzOZŨyU  V*/w	'%Z;QŨz_,œwFq   lBL)ڗ-=k!bT:}  0e+>>WJE{zײ}ŨZ5Ok  i(׬J//%R/۵l¿U|7.N  `>cJ{^ײ=_Ũ"1_}  ^,Qu{OZE_Q   }TyЧ Kc_/ӵlN_FƑRэ   UϜjӪ{>ײyb4{-   #,RϞjS΢PV-   fP=)[SRmJYjVj
  Yо|TRmJYjS**   f%G?|T,
51u2  `Oޕ;ϤҶdQ}	   KϤj۔Ef?5OE7n   BI/rl*YjF5k   T<~s-gTIʢP3R#   @/Ϩj[E^EC   V>Jm1B|+R    {W%նEZS   P?Y%6E  )z|=Jm2B%w   `ϯj̢P}s)   ,R_a%&͢PӮqG_5   S6wYVRm,
5  m:_YI(Դvr  )SgZIdQ)%   LUZIdQ)/z  0-(|TaR[}   0ʵlg\I^   оda+ˢP۔  WfyWR͢PV   FL3]I5Bm}0   `D5sTZښ=^ʵG   ;S6yU8BmUkE   ;|
gQ-V_k)E}  +Sk`)h|󞟊wD   TD4V,
/#   콲-z
fQMV?gR4   *x>|.eQɛ}>tE   @E5tl,U+BMZ}'   Pae:{>KY(FK^ƚ;  k_y@,eʢPչ    RS}d)HzN#	S   0w>+KYE(ԏc*5   hY,
7   S6gYF<B}}*[~   T
lĳ(TgD   Ilg),
^y   [Ժ3pUoSg=   lQXE̢.s   Zgi),
+\xT6F   T?-3`s;   lR6YVwTg;   LI_lĲ(bsKUE   0eͷ346:YV機>  `ښ'<|Ɩʢj-|Q*}/,  i+?e?kKcEaj}  @4\-e#Ea3   \h |斲ȢBu=<  kgn),
+R}R*:g7   ]?=^>{KِgQXw}n  i}kN-eCEaj   fTXE/l(l>  `Ƶ/[?KcÛE<4   ̎v=6|!͢pT<}_1   Cqil8(g.|  m|7R6YjwNڇg   u˥ˢpDk2   (~gs),
G|.VG   sY#Xk   be/{W.eCEሕT6D   ssQ#Va   *<gu),
G|ɫSj0   U(ն:}/   HC~.|f!ȢpDʗ_  $:7>KdQ8"/7  TtS}[gw),
G|+R}  pL.eEԾlIy   No
l(E/Oes}q   s9^8!}s   
{c,/eET6E   04,l@(Z+E   0\:͔^0amS=}  i_4~/!u*   N#{dl/eE06y\*X  վ|^,
i}  P+SOR6@Y[sKE   0Ɨ"s468YY0  Pnx"ewl@(]}  h᳾HCT}{O   )Swl3@CT經O v{Ru{Essѩ}偩}:S>3.5O;yS/ۗ-I:->xi*Vߑɔ2 8Og~),
|ߟJD 0Z:TY{k\ziLc>#{s@6w/yUsqS!sRn	 Cx^ϢpHj_o	 é꽤{7RRJI~o-5y~OW~'!T6E 8si,6!(_K*kL lFe콤w|a1.mvǡy^ܽ_Q ս{[͢pv )ϤS	{O~gS/en{#?ێ
 2;Z(l>. L{yq|ɫlÇ TRcd)̢p% 2[{4x3JP_Oag n;>b(߽$U<uO3.՗5$ݡm_8O- 3}>w4E 7 0jԽ<Sk[m{ҺSo' 軲dQ8Y}>@_OݝW|KGˋrf 7~JY@Zǋ{q C]O{O>W5>5@\wa z JcE:矢E 6zvrj)[TYxJ ISl(`P({Ey'SKO^E2 CWߣR6Y`?}E><s)_{SQxr }J,fQ8un;%,^ZO*sj|oi آMߝeQ8`{&n;,gu_`Տx_>[@R46;YXoE w<{~7jě]jxo{ TkR,
9ۥ@ `cŇ{wR5W<~s3 VlNBTE TP6}JROrO i#Ϣp
)z~J5yg{ ъGoϢp@zY`u!^^a('RR*:O *·)@R> qU? {OKߖ3i@un=)>΢p@ ̈HݻI/r]'e/ DIl(Jq)ԹT?-=wMz92 }{Pf0sg #deߤ]^*RwP9g: F@؍#w4{^j_ n;)@E4t'L5O3!W}(5l~IQyg*!@\~IeQTS/:=>;ۊ~z0ꇽ'ޓEa`Wz ۮ>!.T FX#;),
#sw> !+w4{8un>.)*[RK;)s\}0$/m5Odo~kO9 =L`Hm.iX/}[*))%>gQTEg xX;K:-~Z0bIcˢ09ۥr̓ a%3ewyg|*2 }ӹMEa@}08w4Տx_*?t`)ew)W}0{JB?~0Z}>^>eQ8>>  edj'wT:7} 0'X&M?YqoDa '/yU$U_H, XgRև,
gw> 
gk:!չLEl6wTnx" X{SwKS}{S?}D 0-Q,
g1> ֽ)'$IW?S}G Cu1)fX Qnj}?ѵ4{&}j 0$}`ej}0)fi^vPI/elp]$ixq>Amk{?<oS{KE,ӎi~IBwJݻΎ>F T4un;%=5x ~f.Y} sѽEC$i{~qFq,(?wZwjVbTw< fKYyw>5wԹqE@ԾjijT?4E,T_3RtRτ=ܜRꃣO bsӱ{&Ϣpj_ X`>·H#,fYQe*'un>٥lw46YB㿹 `f/ȣI3ܜRã ~lI/K㸏|+
ilx(t	PO9f9ۧE= 3
.^F'~}>Ovr0+؍sSO!?;{iĳ(߽8x`&w	k$eY7GSsR/OقƟX(=wMێ>o.Lق5Խ#	`Խ멵rnj)_\RϢpk0$0_}4V}ɢptl@u=?ewc$VW⩻(XE!opݟ}	])jD1@u9ϒP&}}*}/\9/5V|
JcßEU_kg6 }Խ\KBI[~;SX}d]XK/[}4w?s%Eվda9@tXe3ѿR}tL];v)xy_|7jEU<z}@ݔ=^~HuJe}l
>~K\djT?R6wsTR-$z3T= T}8.^4/#
xϟ?/%&y_E LS?;E7gԹٗ_45O/yU()r3P ѮO$@wN}Um<퓩~;z?%aʢp C	~H%!\}{tlj{j)T,
om ^o}HޕR+>!U}(un?5.Bj)_K&6Y=w SΡѭy_FsP/IdQ} 0W%w}0h+8
n~VIU6~6lmj FSkISD{@&$(>8 ۪JC$U|n\abԹԺqSǋIʶEa?̕" QφW_Iӌ>>)}2)l
Yw/ ;$Uٟ>4Sթ}y_ҷlvg$#~5+T<vc?$Uέ'EE*Vߑ:7~%T/lIf(>870 Vꇼ3|.xSr{9jє/zy9!I,fQد7%ސ[xB}%Q}>By>aT=un:Afߑ9ۇ?%),
'
e{C&6gԽcF%ĝNIswO#ޟ;?%il(C##`+4w$m|rG%
yVj]_)s$eCEa?ċ+n`:7/$i~]G&9+{	 <w%),
PoDߗ lF1] ihj_y@	N#ץ5R46YN9ۥt
f4Ox}!I[R-G'ļsR/=^|jeQ8l}
>x I1;#fLg+qMW?$I5<w, iҷ4ZG)
}}%64YN7`0/^~OHҔ}>xiQ
ސg]c;?$Iik(fE_ Lb|~OHt{cﯱ`Py_AIT(_[&4$ֹ}BOX_\$,
Q?_6Dח <h+३}y_|7?$Ii(Fo}0QY~GHR?/}kJz	˨*X}{tlj/!6JRbӨ{    IDAT7t &rIZ|!eWp%+>/$"©6gT֟qvs!I3䇮>i2ecm˖}w^$A͢p|K$i&_ZٳKiL[IRmh(bS?c  ?|ɫIڗ.>qWP4,
o K$iVZT<}K
.|Q$)ZS .{D IU+}2ԽԾx~j|SsZ%(JswLG /nYsˉ/Ο}_+H͓҇rIRdS~; ?xߟ
$i˗*gOaw
^$)ASy_Gtn>.^g.f35R經SO>}%Iiг(B+/{w Ia>߻&({	UKSg$IcۖE>2 _u|߅w$EW/TGrtϾy'Swlv$e̢p

 +>~'H Թ#yty_AIXu(
 sIARX}4r{9r^jє$eE68Ꮳv KE	4H/G;JfQʹ? T^{^ IRG4Rթ}Ay'R}[e$Ic͢pqF8 ׾tq} IXFу,RԹqEj~{I-gQ߿7j+T?-$jU+$eCE4ާIߜRFU\<)Mᏹ$IوdQ՗+"k@PtRԹ<볩~;R6gWlD(܆8eT~HҠ3s_Bܹ:w8WD?$eʢpj_(g'Jk_o] IRJC^ITZ[_,}[] IC{;{̎q|?>$)M̢p*y g,>{@4$)k[ۂT =l~H]ueNZT?W$IcÛEVV_k)_K] IX}{{~(?wZwjH5'Ij}ˢp+k}
m׹{@o[6Sx -$6cYnr l7$i/}kJV`Sx_AIƪEVֹٛ.ew$i\{]օ_J#ޟ/$IR-<­x1%Q(_[j|SKÿIT,
h`yٱ$I$f%­(5s2@5)[{@$I
dQ5`PI}H$IRV,
Y*y߇$IU$­}ѳ2@eʗ:$I"YnEO*x_$I
eQ^=/TN%$I$eʢp+*D 8C$I$eʢp{=+TO/$I$)P[2@t0$IbYn=/T}K$IRV,
 ]yrGF/I$IYŲ(B=/TK	%I$il(Bݻ=2TJUg$I$e̢p=3TJ}~I$I*E*G 8O~I$I*EZyr}^K$IX(Lo*V$IU4XR~K$IRV,
7SOG Ҿd_$IfQgR|$I$²(L뎈*%g$I$e͢p3uzP,es?%I$)hx2G?%I$)p\HP?%I$)pjv)us3@e._$IƪE&2zf	~K$IRV,
7Q*~τ$IU8MX:"ew
?%I$)pyD Q^/I$IUeQ*s_$I^ˢp+znMǆ$ITZ׹2/?%I$,
's)s3@e4OT/I$IUeQ8y/*qo$ITZW<vcPo?%I$,
'\*zn|$ITZW6G |I$IR͢p=/*xs_$I,
')_2]~K$IjU?s3@etn?-ܗ$I$,
'~fh_,ܗ$I$,
'qE ѾxA/I$IYNVOE :$I$fQ8r*y߆$IEd/#zn{>%I$I5c} fG?%I$I5rbPC~K$Ijսs3@e6ܗ$I$,
'2=^~K$IjU<|uP}I$IR͢po
?%I$I^T<}_P	ecM/I$I(r#ѳ3@%?%I$I^T֟*x3_$ITeQ8Iӌ*x3_$ITeQ8;D Q|s_$IƳ(Pp2^~K$Ij,
'/-zn+}I$IRE=7TFo$IZ/	~GP{?%I$I^fs_$ITeQ8Q*{$I$ˢpBNP;?%I$I^js3@etn?5ܗ$I$zYNy_E ѹs_$ITeQ8i=7TE$I$&	5OTP^z,I$IɢpB3>=7T3$IdQ8=7TF}I$IREᄚg.zn=熟$IZ/9=7TF}I$IRE=7TF}I$IREݣf~s_$ITeQ89s3@etW]~K$Ij,
'> [PW$IZ/=7TFM$I$ˢprᗢf(;ܗ$I$zYngPڇ}I$IRE[cs3@es_$ITeQ8Y97zn>ܗ$I$zYN|@V΋?%I$I^j_0zllg$I$fQ81Bٕ_$IT( *__$IT(R~K$Ij= |!zf?~K$Ij= }>zfƑ~K$Ij= _R__$IT(XF </~I$IR͢pb3.zf_D$IEĚuP)"}K$IjkR/?%I$I55ORW~K$Ijk33@t?*$I$,
'8wgfJ~Z/I$IYNq̇gfJ~_$IT(XD R<~K/I$IYN~gfJ)=~K$Ijgfj4~I$IR͢pbe*'[_$IE=z^|ׅ$ITZ-eʩ$I$UEs<z^ѿ~K$IRkYNhN2@4$I$UEƥ=3TJφ$ITZW6D Һ~I$Iz-+?=3TJg$I$UE߿7zfέ_?%I$,
7xR߽$$Iײ(ܸˣgfJ)3$Iײ(ܸG R֟?%I$,
7si33@erI$IR-4ItlP9>?%I$)pԾfYP9~1$IYNR}ei{$I$e΢peyr*$IYN\yrZ~)$IYNR*}_$I
gQ8IS?=/TNSI$I*E$52@t2$IYNR}E SY~K$IRV,
'2@t)} I$IYE(|+eJ~H$IRV,
'k)eP9e$I$iYn.z^q?%I$)hhM]ͳ?~K$IRV,
7Q؍2@/^~K$IRV,
7Q2@t?*$IYnF ӽ_|MI&c `0nlhv0`0ƀ[AUJE%J	PB9rN(I(RZ'n8}~c|ík5Ug Se(܈Dߗ%F_~  BYnD˒T\U   ʢpc?>}_"km3    Ȣp#}2,IEg   @*EFt軲$Yg{g   @*EFtxG]Yw?   T hweI*_&=   R,
7ˣʒTdk   @weI*]   XnBy4,IU=vO  
dQ	n/KRyUl&  <cYn˒Tdկ   00nm]Yg   @*E&[]Y{_   TMpΘ+KR\>   Ra,
7{'ʒTd+   09}weI*_&=   Ra,
7ߏ+KRU>   Ra,
7/Gߕ%̪*>   RA,
7eD_%_}m   *EfTǣʒTd5	    1z軲$Y>   RA,
7cxweI*;   T\wT]Ylxq3    Ģp3}W"M   H(eweI*^i9   
aQc>}Ubkm9   
aQ8,IMs    ¢p3_}m=Ys    ¢p3Z}Ob럵"|   BX@y4,IE6   
aQ8+KR$|   BXDߕ%ȦEw   H(eFߕ%Z_9   
`Q8ҙˣɒTl>   R,
g{Dߓ%غG}$|   X@?'KR^>   R,
gɒTlk    3Z{$+   @*EUǢʒTdU.	   ,
ghweI*/   ,
ghx˩dI*ξo   ,
ghp~dI*1   ,
g֊{$[   @j8{$c   @j8{$   @j8jKdI*a?[  `3lUIRL]^?   ˢpuEߓ%:9   ̢p}Ob9   ̢p}Ob\~@   HfQ8_'KR0|   ('KRU   @j0Yh{$]k  PwdI*ξo   ,
gc钜{$[O  f(у7Dߓ%>   RCY擣ɒTlÛN   ,
gݣɒTlo	   ,
g;?ɒTnaN[?'|   (}Mk    5E,|CY{g  @j Yjm;$]mg  @j 9ZEߓ%؆>   RYɒTln
   ,
`pAdI* 
   a,
C;dI*n>   RXA#KRug  @j9hwdI*Y[  0sZ*,I6Y   Ƣp'KR!|   (Fߓ%c  <ns4lk$]{_   A,
;wdI*@=   RXQGߑ%zg.   A,
稽ȒTtֆ   ssrFdI*C7  (ѻɒTnaN[T,   HaQ8Ό&KRѵzc,   h
y\;$]  wdI*_	   !,
wGߑ%膷>   RCXCk+ȒTtUY   ¢p>ns}Okmy   05,
iȒTt8|   (5Gߑ%zG,   H`Q8ˢȒTt+   ,
{_Dߑ%F]>   RXS{_#KR9-*|   	gQ8_+h}Mkk   `jY[ȒTt#?>   ҄('Dߑ%~)|   	gQ8v#KRo:1|   	gQ8c>}G+|   	gQ8}Gkmy   &EV ~,I    M01/,IE;S    M01vfYnpg  @`cwdI*  4,
<ȒTtU.	   iBYIg?#KRV2|   	eQ8&m_}?    M(1%)Kg  @Pc4;$#g  @PcԿ`uYnM    M(1;$h?>   (~/,I    M qZܜQYn_w  cQ8fպۢȒTt>   (Gߑ%膷>   (9Dߑ%C    M 1;$_k  4a,
ǬۯGߏ%:+|   	cQ8n˷y؋#KRNB<   ,`uwdI*ukg  @0`pwdI*jm    M1}Gg  @ sF_%:=|   	bQ Z_}?y   &EBX$WǢȒTt   Sâp ,IE7zY   &E_GYn4is  @{'ȒT|>   ҄(\ ~Xw  @essFwdI*e  `QF}GwE,   H¢p[}GrZy   &EBpϘ"KR|C<   HpuǒT|c&|   	`QZ;<~,I    M VEߑ%Fw_>   (\`;Ή#KR[9-2|   (\`o}Eky   j΢pMD_[w  @9cI*  @9srȒTtϊ   SfQF}G:tI<   H5fQW}Gk~e<   H5fQ?S#~,I=  @C    IDAT1E9cI*9ۆ  Tc\UwdI*wO	   ,
IȝwdI**=>   RY.Fߑ%Z_y   jʢp~g.KRuּ7|   (\$ӗSIRl&z   (\$_w$6y   jʢpUO}G+|   (\D[N#KRs    ՐE"ꟻ]Xs  TC{_Fߏ%z}.|   (\D:~,I7y   jȢp1-]ΣwdI*C7  (\d;ϋ#KRUZy   jƢp/%,Im    ՌE"$_φ  T3oDߏ%>   RX.e[KwdI*;  TXuaYK  @ }?y   jĢ0@Dߏ%zg.   F,
w}]XoxӉ    ՈEa[xYJ  (2;$_k_   &,
/X}?y   j¢0HFߏ%n>   RMXicI*mg  TQ.U;$]yt/
	   S,
o;3,I7/  @@vKRu~(|   (=/ǒT|v	   ,
V2~,I7y   j0~}GsZUL   eQlxiWdI*>   R0`sKRuy   Y$ҽ  @
fQˣǒT|   )EaTO|?,Ie7s  @
dQXÛO"KR~S<   H,
kcI*79|   @59}cI*_   )EaiXo    ({ȒTvU[ۼ0|    51+$_g  Ģ&zg.KRN\<   HA,
kwGߏ%׭   )EaM{qXzy   XH]wdI*v/	   )Ea?:~,IYy   XH/Dߏ%g   )Eat$  @
`QX#m_sUEߑ%`<   H,
kZw[Y/  ,
kfp7ǒT|<|   EfQX3S?}?럷C<   H̢f:aXoxY    -2ºYܜG;$]},[  cQXC#KR  @ZD54l$_
   iYPOFߏ%>   "(}?{y<   HȢms/Eߑ%F`*|&   L-y~Y[  @Z$5տ`uXwg  @Z$5KR;*|   EbQXSկKRU>   "(*=}Gk    -$_   iXXcI*;  ,
ksǒT|û.   iXXk\UwdI*A'  @*Ea͍5,I    -0\}hXw?  ,
kwFߏ%W	   iY\{Dߏ%F>   (y؏#KR{IL   Z8`tcI*Κ  ,
'ǒT|W  ,
'@Eߏ%>   ( ]-~,IWuiٖ3   -It\u#KRw{}L   ZbxYcI*>   (󶏾KR.7|   bQ8!?~,I7y   Eh}Eߏ%I(V |&   `Q8A"KRuxG<   XdxñcI*_   iXN_KRo<!|   `Q8A:3~,IW  @Z O$)ί
	   i,
'ǒT|ݵ
   i,
'ǒT|o>   ҘYNމKR$|   1(0}?$9m   Ȣp,*~;,I-3  `j|,
'ǒT|S=|   1(@vKRF<   HcdQ8G~ ~,IW=zW<   HcdQ8;*~,I93   EᄪcI*a   iL,
'擢ǒT|v   iL,
'TecI*  4&s}?$[9-{fL   Hc`Q8Z۾(窊"KR   p~$_O  4lp՚$o  4KRU>   XN~/~,I9v   ɢp-rtǒT|ݵ	   ScQ8F߻8~,I7dy   ɢpkXot5    ͓EPXTrk  4WG_%I9
	   i,
'%j ~,I?g   05w0)cI*g  4?kEXog  H̢:_wXsng  @#h}gs$_	   i,
bcI*G  4G1$_    ͑EaCN$i=;JL   Hs`Q}7$圻G4|&   9(lyЍKR.'~&   L͞Ea4~,I7zy   A=~,Iυ  4K=#cIRι3   ͒EawyMXs]L   HdQ$K䪽.~,I7   05;3$iiųg  @韽*z,I9yKL   H`Q0/З$;3   ͂Eaô{IX4	   i,
Zw{Xj=LE  4C4$i=&|&   (l}7$圻ML   H3dQ@ӿiSg  @!&Z윇$衛g  X6ˢǒZg  @_GXs3   ̀EaCuHXscL   H3`QP]^}7$Mg  @¦Z$WucIҰ??   6͢~+z,I~Oo	   i3,
軱$);3   mEauּ7n,IwO		   i3,
݋ƒs{"e   i,
Zw{Xsn   6}7$Mτ  	;ߢƒp\L   H`Qp}}7$MpNK   i#,
nųsǒs  `j,
0軱$i='SL   HaQX{Dߍ%I9G  軱$i=遜.	   i,
5wcIғMs   mEa	.U{]Xs   0,
1軱$i=W		   i,
?{UX4Ǿ>   XwcIғV"|.   (,DkDߋ%IO=s  JZmw36ʢ պۣƒ^L  Zu{_Eѽ<6?q,
2k$?=|KL  hչC?\
}Q΃&?vxYTSt$m֎/  0iZۼ0w|g<o<!W1iJRw  >#Nt\yp=p]U56T=Ydųsp$7) X叽WpxhSdQX/$W-|&  @vּ_!E,>,
ӿxE{$I/  XhӿexWO| sxwLRMY{GBFIҏ   ^qYT=YkGIғ80|.  $WpuT=Yf\E?>zW\  	x8^lF,SMYhxiϤ$Z_>  g>M5eQX+IIғuX\  p˷=g?SdQX&,IGĢ  Wp%;sSdQXv/~&%IOV=zw\  
NH.EK)BUn~.%IOUs ZWp+'[ngjʢPk~.%IO=o  ^"+8Φr7UOϥ$W>  {w{}<kyt9c'%{NՓEa{9$=Y}s W.#k\wq)Rxv^)IzW^?  {Ѵ./=ՔEaF\lJ{߅  ؊gUC7{`@+0UO_G)Izz=  WQg<?A'c?{_,
=#Ϧ$ɪrZEl  `\|8#6C(,X{D?g  ZWʃs菒Ek;jʢdKITz|&~6  =3w}O\?:j;*T=Ynxiϧ$Ɇ7>  J7ὂnxñRMYSR6 +A'B-BRMYn@$էξo  eW~
jxISMY݋OISꟵ"|6  L<&rjѩz(og5  0췣?֩o==l)BãQI6ZLl  +|~VTSJRw :h|ޏWpWy6۩,
JRg @{B<2Ԃ4SdQHN+Jltߕ `!-]ۻjp_<9:TH/ɢF\JjG qim9}<\uĥua3jʢ-9$==  {Uw(dE?4t  Y˷=ߐ}\~aG)io?;ٙ'BkTG  Oe潹yx9[Y7g)ՔE!zgU_yul  慹s;syx	JF<{2TS_Tz'cl  
?^8$-HMՓE!?pUISpll  hٖrvW>Ң5T=Y_:=Y$=G \[O^AßTS<D? `b~?^?Hkx1j)B~WE??k  Ԕ
JsjpQT=Yc|-y$= @x4~#'B~L迎~^%IOm4̭m_> 
R1>,O5eQȏiUY|  
JCTSKrA3+IzJӯ x,*~ςz('o>9$=;g 0
-\~@0UOޙˢYIj شNGe_Sq
J5mp~E)B~B?~f%IOw #U/{B|푹zfX;!,
ts5~n%IOixq sr{IWG@<_:\'B6hu%I>j X+(59ğ5SdQM__T:-|> @ӴvxYyo<o<!Wu#_;c*I5eQuV> Y~xP?RMYA^JW ˷Wd\y_]?ɢ[E:F?g Pk+^NؖTӺMjʢgW|W-iP9jʢꟽ2ٕ$=uG XLU{<8Wnǒ&~(d:_w+IzZU\  =<ҽWP҂Yn,
٨ֶ/ʹ_I 
q^AIZ~(dFJV/ {[?
[TSl_IwE| ٽW)IU{7,
٤J^U?># `=4as,
٤J6P '+oGEIUկ?KSMYi˞ϰ$iF 
smsy4zJҼ>ۢTSl3aIӪǜ@sV w{<\=q'IRkTSlVϰ$iuWp+ģ{/^AIe4tI9<UOlV?~%Ig 5^AIE958SMY2 Lo%Ij3im9w<\YTG?SY2#_,K6P{_	 ę~Vg{'}:<8.z4IRMٝj̢_g,I@%|F ^AY5|,
G?˒4[3z`+zH7=՘E!3ZgYZ9o<>W퇣'$55,
{gIg31YeU=Z$.;/BflpY># ֶ/+9O5fQȌNY@NK _{WEIjt3,
^<K6R{7	 毽DIjt>~֧(do7IRM럽*~N 0o=R$u>՘E!2gZF]># _P%IZ?O5fQȬ&$mʭ_>' 1(:3O5fQȬtgZz9Nl8Fg}1BfsFϵ$io;#|N 0?w'Z;rYj̢Y=p]s-IPAnm3s\qP4FV>7O5fQȬ.;$m	 nxIѣD۠~Χ(dֺG}$і$muk s7Q"Izs>՜E!U϶$i#U'rZYT=J$"O5gQȜT|K6Rg{ s1"ImxTsoIF\O `"InpgTY2'S=$msZE `v;JF׿g}9B椽oI&jYt!Iw>՜E!s|+O?oYt`F;TssqIF=tS `vz|&z|HRg}9Bvϸ$iwY/J萤Fg}9B欳ϸ$i\>+ GFIjt^~֧(dZL(9$ma    IDATׄ
 fnxׅѣC]k,
G?璤M53zlHRslͲ(d^K6Q/
 f`V9cC[z(?B{uI&wE `Z_=2$эuY&E!eϺ$i3w~U `:#z\HR|rY&E!6z]z}.|V ic6z\HR\_Y&E!6|]F߻8|V isg?(d޺G4y$mʭ~)|^ q}Y&E!闣wIfouaF9}g} E]ϼ$i |V qUz0zTHRk>M Bbp՚g^|Z۾(zJHRk>M BƢ{'yIf-#BhӲ-4,
.~%Iitϥ=#B]4!,
{}Ifj?o In4!,
߈~%IwT o8.z<HRplY&E!c;SϾ$i3!|^ F=${Y&E!cϾ$iM3'xV~hF;d(d|.U_l?3 XoEIj|ݣ?~ާ	aQXM_Tu;3gJ~~ާ	aQXN_4{n  I/iBX2V=Kf4zf <[#AݰӲ-4!,
e[H1 ILPUz z$HR=|KY&E!c7s@4:3|f ˢG$5᭧iX2v>}HfʯuQ Iop>} ]{7EKysT3'$5_?(d=3W'Ip (ǀ$5?(dAL@T>3 JU=~_7>MBDg$i&U/Ҵv|y"jm3?MBDg?>$I3wg@iy/Iͯi3?MBƊg<D	4Py;DF~ާ	cQȂqN Ia3|n dxYG$5'iX`g>$I3Ns˷ʹ~Ij|?&E!ۢI/ѳ~/IE;4a,
Y$iu? >}KRuּ'OƢ5sA4Æ7>7 J0}Jο~	cQȂsA4Fg@-"WGO|Ij~^N˞OMBT{7GY4 zv 4Y{ߊ>%F\~	dQZ\u>$I3ltI hI>%~	dQȂA4:A h鋫$i럻]&E!wgI,\q` hm:FTDݣ:ܟ<,}>HfS/֪ےiw&DiY8٭3B4} h9FTLm_~	dQȢ\wT!IE_>; fteǻ$Q?ӄ(dQNT9!Ie0>^s5>%w~	eQȢh$i<8|~ 4Ew퇣uI*eiBYh>+$Iiɭ/l hUDTLS?~	eQȢ\&$Ͳ)	 oV<}KR1uy_?5,
Y4ݣ?}VHf[0:Iq.IEZ?M(BMkϹI,0|-(r%{j,
YT>2$IlpQ`b-"W}KR1(쟚\,ED6֎>C &Q{7GTTK	?(dQuּ7̐$͡ۅI?#\w?iYZ+}nHfYAN[T(KPūƟSˢE7sC4}2| Lo>%Z۾(O̢E;ci!ICӿj_DInG$Ugp,:eU&΁>G &²gmI*'şS͢ŷl\E94s`t#[/{ƼYbx1$i.UUn\}h-I=p$iMs+z YkrZۯπ4,
	ʫI\rK?>K {GOjI*a/m=c,
	S=$ͱY+@]0}?5E!a}HXAN+>K ꦽ룏hI*Ukg@j Bt{9"IG>>K f=ggE!aZ^}HX9-*| U{],IE-s`jYjxyg$iu~(| EE˒TfLE!z18$ͣtI<},KRE&BB|Cy"Ig5	' |>RCXk\=q"IG{/
>,8bws 5E!$i' J/铤{N,HaQHG)y6 Jǰ$۠ӊgςk}rFG$iuZ^ΣG${ς KI<}Q<XlS?}JR/#|(g>[$Ics;g
YU;蕤y0Bg}Hg
b7Ǯ$_{A,
e[檽.|$+ 	}JR[9-{fLjBjcp#F4F]-
BVox 5E!=cg$iLu@\XMx{Q+I?o0,Fk\I@l4U>f%Iӯ9}3!5E!2sF4z'C\XMG$rkυf(Vzg.>j$IczV>7| S>^%I~ȢZiF4z1| Kkr>Z%I9υ@%zF41~i$MB蹐Ȣ\_y#Ic- stTIғwِȢI8F\sDi*Izo$Fφ@NkrtIusj]ST7>RCYRK[}H\/ tI}Q*IzJ>?ɢZ/$iUniS:ʢZj~e#IZg
1 3*=}tJڠӊgψP衛IҸr1 31SSw>RYR[VG?hx3`s:/DjXgDj0BjۣI=s`V<;9$mSeQH}-2W IT=qnmY>&%Ijϭ,
_>$IT=ӵw/ʗ$/'|Ƃ(ҳ%DQTPD̀ 8QPqAEjdtbB&!IB!	YHwnIzOB],Oתnw<{NEC ̕Lc~Hғ-.}:	KF;CGS}0GuIl~7F<CFE ̡U5XKJe}$)E6
55xq\*z}#i|w{A*};//1P/e.+ܑ%	s$g>؂/1P3	9S%E<? &~[l2j^ s$O~=V}ec]n~odcPCQEK AD#i>qX}{$to?3$C 7~H&έFw LRk;GBM+> ֹ	w$n?}0-$CƊwFM Kv#ij%n;`VmPiV> rݽ)}GȔ/9> Ǆe(Pչ3
>qn&?|َxc)jkQBU/A@.B#i[u 2Eo,oBWIe
~*q{ ICJN{/C1Pz KY_KwuDa LS5ZE#٘e(8* oOn/$O?RYD_ LSK1Pkvl>}^{SpHHӈ> U)~dcPCY禯DY i_{H`8)
\wT}aBe4 Pk$fկUk
pl3j8[`EjH@UP	LuޛzALBm[O> Ԯo$F^VFL ̂/	W1Py. ék$I07H`lL3jh˗>$ r)_s$)KDE ̢A~dcPC]{gG_ bRK%I~R> E/g(P<o0 Dzoz-Q>`_qBua41 D+SlIΣ @l3j~f9 ):廽0~475O9lVwM6
5c XuCxq%ivk"`t=2ZB}KֆS<|[zi=%i-:shk;gk
5
un>)<`P?yS_R X|,ewƽPPFi b)χU^Rc>tBP#SX}0GJ>$MS/|M@4OG5CF_> `{R}׆Wļ:s)c~4Sl;HPzS ؜Hjxg%i˞:}T g5RP­S=}0:<i{KӪ 0~g|,RP#U#7 AM~*ޒx>R;> PtSK"z
5R5~Wi_GТ/i㢏 uxi}ړ
5ZMOc+9 H5RW?x# `ͳ9NRW}0dw}Mw4-!_Je@n;{8nRIB\}05w~I\7;T{ZBdŚGw Xj{LnZ|>n+R}UZMDw Lo{Lv*V4˂P,_sA SNw4廽0? zj]ڳ2jd{y+ޝF&URKe:[<,gf(< 轷_E\}_Nݻ/`:[Cڳ2jdwQJfM_3ryJv* CsqwjPsi #l>Mm(="c)m,CFW$`U!*>'{O H?4eJPnѶ}0VI}q{RoA T#26P#_;D g|/w\W?M{r Q~G-`Եu-.ޓfƑHRYF0ulb~ݦ&3j,*}0GLc~I:,i]0~Sm
5U KSRş)71ޛŏm)oײ`3j,ʗ; oyj_Ww)آmSԿJŃ7E 0w_)m)CƦ]F pB{lj]T>o F\=նPcSD 2_dۇ߉R	ƝkHӈ `GS9j[Pi>s{SO­FWG 0f:*M&Cƪ>\{wj/}^2q1U?jP?`~})IN/Ū_ b)~76Uߍ>'ٺԹT?-wWO5uwNJE' =h#&PcWk>'`2u 5-:Ԁh8sQl~ݔRi
5vR}\Zrׇߟo;=6u/S ؤߛJSPs% LI+R1-_<#s)# LJߡM)CƲƗ0i)[R/Qw|WٟHoC 0-&>UmJ
5MOM 2_..~Z8ݩ}^Xy] f}Ui
5U vij=I41?}S w]k 1Ys]4}_RYD 0:Gó){u'Zm:s{YJ9Qst2j A[NIͳ>~K{Jܺx?1خG /Ǿ7VmZ
55'' ]εGN^/G[oH.u9,7 Kڻ}ڂPn֩|G( *}KH>Gp{@k'4;7 z}W6Z/>G`Խ}yҮ~௦lvߚ_+){rݽ4 0:͔{\i
5{,n;8Pצbu<l_WSOw{A>o}_{?O|ekC_5 M_ߕfP>3S B,)uﾨоԺh"5DjOyM>՛7O:_SҥCSSS?'k%^e(5D 0yޛW+T_zܽ#w=o   ~Wm
   `Z_TL3JOԺ?U   :eє/{~sj3FU:   J}USx   }_<ڬd(R	M   tn>)Y^YP(=ꓚ   -;ZBd9   gxfw1JhsRY$  <igxP(mˣ[   X{Spwf5C;>	   xvWm3J{.   Xw{AsjPD?  Ӿjgv$Co>  `pTIBi35#   FUZ]*a   4W
-Ծls   uz3jsPB/Oێ>   TFWmN3Js1   ):\9P(f=?    IDATMƑ>   L?6
IV<pM   }W<xc&?6
I<ϣf   &W/
ɶpT<rg   }S<rWnLԏj}Sg4   MWPBKlu9   s|d/UBi.^}V  kw0JS+)   L=W
ig6   ̙V
iʔN   |lU=U{Biun99  YڧßUP(Mao>  `VLْUP(͠/>  `4gm2J3qp   {}h3J3ib^*),  klkg9   Hȝ)[u3j
61?}  5Ok,<g:   LK?MTe(f[?>  `ʚ'ys d(f}  {Kgj"C4[-&>  `Ǽ'yZiP2JX>  `Rw~=9ZP(fKD   yeVs e(fy}  funrjPoVE   qFyEҠe(}  F/+YP(EKlu   OSצ|⟛1C4G.?   <Mφ?/6
9*_TfG   S'e^Vm`3JsXE   <#ɪtBi.[C*} .   `+KļdAP(qs>}   025c>C4-&k   S6VRj   㨝|W?6
~pT=z   `̴.B3Ұd(T]   H6XßURU7D   VRk{  1нg`Ն.C\}_   0ʊNϿ]B5V}e   0WPf(yA  *S{UR@ߐRэ?   13>̫f(pL  ):eßwURP/OE#   g]Ն:CXeW	   #}>ϸ}B)|R  !V|P(:w
   CqmURtJ÷F+   m?*JBi    LE|,_gZF&C4 u(  `gYFEVmâ¿i2  `+뽕Uj#UeW-[c#{k   teꇿ5V}>X-_4wNӈr   `~Um$k_u@5V~y#-  `@O?6u?:e_Hls{?   <MYƗ0UiT~VV}S#'E  \"yU{ߕZ~1~ZDA   )EϪtŚ^o	b$AODE   ƱNUm+^o>H  0:)T/_㓯Z=ÿ IO2[z!  ǯ+S־/Hҳk   q_RƢIHS5   ϤJR{W+6$maoN,B/(   |l_9VgV<U#_׹;
  >jϡUŏwÿ(I/gSXyO  D?6^MO=}(l~a6YDU   ̱r)_cjcU~iPؾ/L>+   RYQ4n5Og¿0I~S*:Q   s}gNg0u;)[/Nk_<  `.~xk6ϛϊnPX}=<   V6YScYzѡyD(i5}o  ,kOϘߚ'^O;/%M-'  `uo?+R]#7=vJCRKSY_k  Pf|xWo3Ca>Q)ir5~c   ̆LL~7|P!_I61?uﻲ_W   '5.PX/e¿XI~௥m>  `UMß%[<VJ|o֏  ([R_	+%Mۧbs}  0͓?(-=k(,]6,0U?wR*s}  0kn\wJߏ%M  4}	ƱuCaǅᒦ6f   %T6`uo;cCaj7SN_U?~  `@4OD){|mOc(^{@k_\o   LA#ß)_
k~CMa̯   *9eKv><^y?2R
HzC޸'  `T?uυRZۤ^
;~+"izl]s   LR󔏄?JS[m*;󡰒?hޏ  +<ٟkxCa$M!W  KRp@){jO?R_KLҴj_x&w   [P?{$OʞQN<s0Il6Xyt;   6H'-xzn/LezJKJ^[   ̮擲Ծj)'=v-m*)iz5)   lZ;?IFi}fJ	J~N!  _Eۆ?IFi4)gfa  ?'eyGڞPXi_sDXkbڇ  XSc;ßl#U]k7L4ڗ9C  `5D3mM']x҆;%MEۤkftx   U?I6^5>Һr IӯkR0C  `t8/e
	
{|"$M?C  `o}8d3m{ųZU)!]疓g0  Ee:2M6QEzPX|i H^+7;'
  (4}± 8)4G=n{6  <oפls=X7Y
SMc$iY9   FA=ӤlvLC6k__}_%iun=u  չDD?IZU~9yPX>xKʖ=?/LҴʗ=??l   CXy}ʖ>7L6Q纣?Casim$MoH]  `U2)DM'$dikWsq4   cRZ_PXi]O_Qf  iƊ]äl5xJe9CauɲHIlXݹ<"   Ejg`҂<o{~ӡJ^^{  Q:_ßl5DF¾7+iz5N`_~  W|1K6Q{iHk__G  @_tnJ&?oI3޷aipISk6{<.   LShg-i3ZԹlTϤr>2   fU-)XR^	PX>p}zY?U?7Sje  K.JʞQIEbJG)?!$MIp  `J_L%eϨOmA6q?HZK   SQצ,%eO)_cx|$C76,!H$:}t   lY;O?GI~Z;Ӡ}(I+_T<ts  ifj')IIoRMh`n;5/Z6,'iwNe:   x{&){ץA6XC:w_}_(i5~Wo  e}4yIzEAȡUO>6,:Tk/'  O~NyߦiXPRwJlk>.   R/?IkӰ,SSВ6ѢmRoF  k_wƺ!p?n7Ln/
wJŚG  j_}`&|8bԽ
P47e`Tnx(   H#
q;R{@8COuuɒ_~Zʢ  `sPmyߤbwӨIVjpl^?S*:ѧ  0:׭}lƣڗ|MU1DY]Nmƽ9>  չp?I9kz]<xc5>E?ZWޒ6KתO  MޓPsT?MuMŪҸ١𩊵{7~71/un>1   F_7l<sqNl,§*]'Ev)(EK{.  \Q^/McޝZ.un;=~Y
SR㔿L>;`Q-EX}{w=  0:H-/}^ʗG=5OV޽2CFٚԹq?oO^/+,/E  =ݻ.Xy]>pm>xs*} v#:        0    B    b(            0    C!    `(            
    C!    `(        @P    
    C!    `(    *B    P    
    C!    P1    B    P    
       0    B    P    T        0    B    b(            0    C!    `(            
    C!    `(        @P    
    C!    `(    *B    P    
    C!    P1    B    P    
       0    B    P    T        0    B    b(            0    C!    `(            
    C!    `(        @P    
    C!    `(    *B    P    
    C!    P1    B    P    
       0    B    P    T        0    B    b(            0    C!    `(            
    C!    `(        @P    
    C!    `(    *B    P    
    C!    P1    B    P    
       0    B    P    T        0    B    b(            0    C!    `(            
    C!    `(        @P    
    C!    `(    *B    P    
    C!    P1    B    P    
       0    B    P    T        0    B    b(            0    C!    `(            
    C!    `(        @P    
    C!    `(    *B    P    
    C!    P1    B    P    
       0    B    P    T        0    B    b(            0    C!    `(            
    C!    `(        @P    
    C!    `(    *B    P    
    C!    P1    B    P    
       0    B    P    T        0    B    b(            0    C!    `(            
    C!    `(        @P    
    C!    `(    *B    P    
    C!    P1    B    P    
       0    B    P    T        0    B    b(            0    C!    `(            
    C!    `(        @P    
    C!    `(    *B    P    
    C!    P1    B    P    
       0    B    P    T        0    B    b(            0    C!    `(            
    C!    `(        @P    
    C!    `(    *B    P    
    C!    P1    B    P    
       0    B    P    T        0    B    b(            0    C!    `(            
    C!    `(        @P    
    C!    `(    *B   ;v@  0j{@         (    D!    Q    B    @        (    D!     
    Q    D            (    "
    Q    B    @        (    D!     
   B    @            @D!     
    Q    B             (    D!    Q    B    @        (    D!     
    Q    D            (    "
    Q    B    @        (    D!     
   B    @            @D!     
    Q    B             (    D!    Q    B    @        (    D!     
    Q    D            (    "
    Q    B    @        (    D!     
   B    @            @D!     
    Q    B             (    D!    Q    B    @        (pP&  	IDAT    D!     
    Q    D            (    "
    Q    B    @        (    D!     
   B    @            @D!     
    Q    B             (    D!    Q    B    @        (    D!     
    Q    D            (    "
    Q    B    @        (    D!     
   B    @            @D!     
    Q    B             (    D!    Q    B    @        (    D!     
    Q    D            (    "
    Q    B    @        (    D!     
   B    @            @D!     
    Q    B             (    D!    Q    B    @        (    D!     
    Q    D            (    "
    Q    B    @        (    D!     
   B    @            @D!     
    Q    B             (    D!    Q    B    @        (    D!     
    Q    D            (    "
    Q    B    @        (    D!     
   B    @            @D!     
    Q    B             (    D!    Q    B    @        (    D!     
    Q    D            (    "
    Q    B    @        (    D!     
   B    @            @D!     
    Q    B             (    D!    Q    B    @        (    D!     
    Q    D            (    "
    Q    B    @        (    D!     
   B    @            @D!     
    Q    B             (    D!    Q    B    @        (    D!     
    Q    D            (    "
    Q    B    @        (    D!     
   B    @            @D!     
    Q    B             (    D!    Q    B    @        (    D!     
    Q    D            (    "
    Q    B    @        (    D!     
   B    @            @D!     
    Q    B             (    D!    Q    B    @        (    D!     
    Q    D            (    "
    Q    B    @        (    D!     
   B    @            @D!     
    Q    B             (    D!    Q    B    @        (    D!     
    Q    D            (    "
    Q    B    @        (    D!     
   B    @            @D!     
    Q    B             (    D!    Q    B    @        (    D!     
    Q    D            (    "
    Q    B    @        (    D!     
   B    @            @D!     
    Q    B             (    D!    Q    B    @        (    D!     
    Q    D        [/B˜    IENDB`         (  V        (	  ~         (    00     ($    @@     (@  A  (                                                                                                    3 |~}> | |gU | |2 |, |s | | |X	 |S) | | |f | | | | | | | | | | | | | | | | | | |}x | | | | | | | | |P | | | | | | | | |$/ | | | | | | | | |O | | |SN | | | |W#qq | |W7 |4 | | |8                                                                (      0          @                                                                                                                                                                                                                  U
 | |cc	 | | |$ | | | |8 | | | | |] | |~ | | | |PR | |; | | | | |} | |z9 | | | | | |a | |~ | | | | | | | | |Ik | | | | | | | | | | | | | | | | || | | | | | | | | | | | | | | |SI | | | | | | | | | | | | | | |~ | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |. | | | | | | | |}S | | | |Na+} | | |+C6~p | | | |
 | |	 |\ | | |X
 |; | | |
Y                                                                                                (       @                                                                                                                                                                                                                                                                                             jg" | | | |H#,{_ | | | | | |+ | | | | |v | |
 | | | | |	 | | | |r | |a |	 | | | |} | | | | |^ |	 | | | | | | | | |} |	 | | |[ | | | | | | | |	 | | |Z | | | | | | | |<	 | | | | | | | | | | | | | |S'	 | | | | | | | | | | | | | | | | | |~+	 | |@ | | | | | | | | | | | | | | | | | | |	 | |tY | | | | | | | | | | | | | | | | | | |	 | |% | | | | | | | | | | | | | | | | | | |	 | |} | | | | | | | | | | | | | | | | | | |	 | | | | | | | | | | | | | | | | | | | | |	 |  | | | | | | | | | | | | | | | | | | | |	 |=w | | | | | | | | | | | | | | | | | | | |	 |U^ | | | | | | | | | | | | | | | | | | | |	 |RW | | | | | | | | | | | | | | | | | | | |	 |Ap | | | | | | |} | | | | | | | | | | | |	 |} | | | | | |`L | | | | | | |	 | |} | | | |9s& | | |	 | |~n=D: | | |	 | | | | | |	 | | |e2 | | | |	  | | | | | | | |&nj" | |} | | | |"ph                                                                                                                                                                                                                                                                (   0   `           	                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  UW"} | | | | |~V1oV | | | | | | | |1 | | | | |o | | | | | | |- | | | |.} | | | | | | | | | | | | | | | | | |D# | | | | | | | | | | | | | | | | | | |m | | |d | | | | | | | |y+ | | | | | | |S | | | | | | | |J | | | | | | | | | | | | | | | | | | | | | | | | | | |L | | | | | | |RH | | | | | | | | | | |~	 | | | | | | | | | | | | | | | | | |% | | | | | | | | | | | | | | | | | | |< | | | | |J | | | | | | | | | | | | | |4jI | | | | |H | | | | | | | | | | | | | | | | | | |;nI | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |O! | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |Q | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |! | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |V | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |{ | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |K | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |= | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |Y | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |m | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |~ | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |z | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |k | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |C} | | | | | | | | | | |_W! | | | | | | | | | | | | | | | | | |K | | | | | | | | | |<I | | | | | | | | | | | | | |" | | | | | | | |p;	 | | | | | | | | |Y} | | | | |+# | | | | | | | |'eUm | | | | | | | | | |E | | | | | | | | | | | | | | | | |} | | | |k( | | | | | | | | | | | |m | | | | | | | |([ | | | | |} | | | | | | | |_\"} | | | | | | | | |}"]                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                (   @                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    i"H~ | | | | | | | |2      .`    k& | | | | | | | | | |s | | | | | | |3E | | | | | | | | | | |F | | | | | | |_ | | | | | | | | | |V | | | | | |)} | | | | | | | | | | | | | | | | | | | | | | | | |t; | | | | | | | | | | | | | | | | | | | | | | | | | | | |`/ | | | | | | | | | | | | |S | | | |S | | | | | | | | | | | |! | | | | | | | | |N~ | | | | | | | | | | |w} | | | | | | | | | | |*@ | | | | | | | | | | |
 | | | | | | | | | | | | |S | | | | | | | | | |Z | | | | | | | | | | | | | | | | | | | | | | | | |Y~ | | | | | | | | | | | | | | |h} | | | | | | | | | | | | | | | | | | | | | | | | |! | | | | | | | | |# | | | | | | | | | | | | | | | |}4 | | | | | | | | | | | | | | | | | | | | | | | | | |K | | | | | | | |N | | | | | | | | | | | | | | | | | |I_ | | | | | | | |? | | | | | | | | | | | | | | | | | | | | | | |!Wa | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |~*]a | | | | | | |~ | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |=s9 | | | | | | |/ | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |eJ | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |7a | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |k1 | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |~ | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |$q | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |KA | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |l | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |m	 | | | | | | | | | | | | | | |}~ | | | | | | | | | | | | | | | | | | | | | | | | | | |EU | | | | | | | | | | | | | | |c]*} | | | | | | | | | | | | | | | | | | | | | |~ | | | | | | | | | | | | ||G | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |n9 | | | | | | | | | | | | | | | | | | | | | | |
~ | | | | | | | | | | |5[ | | | | | |E | | | | | | | | | | | | |px= | | | | | | | | | | | | |R | | | | | | | | | | | | | |}> | | | | | | | | | | | | | | |. | | | | | | | | | |} | | | | | |o | | | | | | | | | | | | | | | |}[ | | | | | | | | | | |!I | | | | | | | | | | | | | | | | | | |Oy( | | | | | | |	 | | | | | | | | | | | %    x&K~ | | | | |! | | | | | | | | |~L|%                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    PNG

   IHDR   x   x   9d6   	pHYs    {Rk  	IDATx}VU4B2&'f2f>Kɦ/مXEFEkEV TB@#\	AVhaϽϧy	ssϞ3r)Ak
`9Fckw_1 k+Ax hT&y짱Y2r= xsw`5UH :?/$oɨ=;*q{ 1Gn)"͟']<S`~jz?G^)98C/Q^_.U2*_VsnrAx`M7Ky`u%@x
|و?R]K=(x&(vWCzvu&_`{p(0= DV!j
a0DTCR<ds8m7!ؙ>6P	 Xph qW
vW<CDnO7\[.RrO=7I)S֘rgAxd76vBu2(OmμpۏJLgEBjPZxqFomK<j^.3Μ@5W:јi?C%/?8tJ
<pNnӐNSVk>I,\QuəTŲ&c!:Bokc-\tTJ0^ i.M.;9OHߡf'pg䬆wiK	V׃
 ].;CMm#~U==F2؂fFҖ
o6X7Έm
eWW)quZ=QQaN_xe#9U2[?Gw̬n9(;رܧ*Z^ł%]YM*pھ=$%E7~n,yX`qvC_|A$`7X8@ `R8C =O
y΂71V>7
\I I%:A,MS'<~Ln1_t52'٨rj`O<I,Q|Ay!OU0V%P>qyX|Ro]3yXxEǄ+0$Gs?R$GɪЋ@5=b
Və3syXNtFj6:QLW|o4&޵b9_]pZsi<&GYp'm)dFyo/p\@1ކ{ɓr9/֑'*غ )c>c%I0h$F=	c
~I0`wm~J0`he:a,gQ~9)Q$R'(bk8sI4/z]3_4'*?#juҘ1
*RA`cg\O8`c$ya!xtc7jK{9]~;9k!nJ1bAJjC,=_4(ǵ%tK%'{RM:UXqTRZk╢[7<+f⒚`@%XV2k?
rx?V7T{S_f`љ[%T*	D!Xc/%NF@dSKߝg=
F.v.\rDL_---:jTif6Q*-W >LS_GQsK*]'P>frx&|P`xbm+9@NRqG@l	q`;
OL5}b'#rjd*KRſ>83(G0
$UbU6>oPkWG1{j6V,[;T}/	<0V`\W|wA[
R{X^[/V%R床\GƋ%ƽys+~K\j,܎#x%7ά/j`_KI,L	/(gT٥/xXl%bԈǣ2vtkU-JصKT#] pEF|2PrWKMXLZkSDX
K&^ki+灯g+<)`;3m=ƙ5EgVfb#2JA|c,X̰&q؏|Y7SBK]=HU0Fgu>p"k`M*uϐBԽ7u{MPK~`&(SlcE+)n(9nrS5ujh;_T{VS}.<_o
F|kl%)lCy`ˆU).woOt b$X-C50{)[!*F][v3p~,05#Xs`15#*4    IENDB`PNG

   IHDR  
      Y   	pHYs    {Rk    IDATxyإu}̰XcVMLbRcc&&6&&lib}Y`]vYqdUٗgohAY|s~aʧVsw҇}ܿ~Dk6IҼջp&    C5 {$I~2Nt{E e A7GG܏Eߎ*y,d     Łu%I2ǽ3_{LW]1e_ cc
LT:?.֒xJV1#    `K ҿJ4_-&߲/([;z*0uI98MyIkv1K%    D_Ww^Î(x+0UVTcѻthњYQ;''    Dsｒ$7.lW2f3X&F~27 Z^P6b+\"    
K$)=^/yo\W3&1XW/G֒MQ>rcI
    0Uzͦ$->'Ao8x@O6b]|    `*.tw`IjՒyuW5s2Xjc҇T%M|Ce     S߃%IeKw;FbM<8C~.$A~-    `UUhwaI\qwQg @}FWg8s;>}    4GUE$-qÿz[Z}{f
O9m_ȷ9s;>i    FXI8É~-4*0]q`y].I:';b>n    =Z=ߋ%IeÞ#b`<VyS>pt/\_#K)t\     ߍ%Iv{YtXOʾ́)g
̹~ȴoJ?Q]     ߎqL~,IDhA|0XLnt}#JY    g뵢s̿J,IĶtX}S`be^(ZKw$Icf
    PcUhɒ$MtK_'W;0%VkE~H1[>    xUXʒ$M|^w`epۗ?$i_     6ACQ/ӿ/K4}`$ѿ#H]%G0     \sw{XwfIξ	d
lrC9#њ*$ѿc    -P>(2$IҢm{Ǣl?}`xa0zW/#Icի>    +toϒ$MS{Ho<5&*𼆏cޑFƪW}    0\$ijEW=PswZ]IU>    Ύߢ%Iao_x.WDqU    nMZ)ߌ[{VDk;Z3HRZ3cpݱ'2     cп|Ғ$MkGeԈ*j)+̂\sd    .tiIrW>PdUFk?P$)oVS    s{wjI=~$9'j`\:'aIX['f     dՒ$My/~0Wd@"UhˣkHRz[f     dtsܿn-IҔW5Be.s@+$g
    3Tݵ>-߯%I/}	V!|OtHR-2V    9TF-IҴ7 >b8Ⱦ12X>zK?֒c՛N>    rQ߳%Ij@~;uf_vvv{YIE3bp1G3     5W>zs<$IMhk`VaZet/qVICƪ     l=Ekv߷%IjBK^[̾yf
hЍ<Ǆ$եѿ    	3\n[&4U<8*LXcޑ#BjTg     &TӿsKԤr 0E5DqϤp:տt    	׻$IO}oD c0%+֞I Iu    iPUM-IR*|[ !U{.֒(HR}ﲏg     ɰ/$IM8|jU `|+Z}IS>}<    0>ҿKԨ95wg *LMEk6?$FX    ~(vN.IR*1|2X	տhn@T̿#    )W5eH..IR*zm9g Va>"Z3HR~/"2    !]ۥ$I{&ߐ3 L0azW~KR~"a    @n>-Z3ҿKԤ=^oZ	e
$=)1g     4T+$w3 D0!7$թth     wҿKԴv?M`
`pњ::>ע>     *s{ӿKԴ!ʧ% l$U]_/xISC>#     ~;G-$IM8,$0Xwi~KRjƨZh     GҿKԴGfD) UwEkW_T䫞?    U5_M]"aOBFq$թbDG4     ]ˣ5uuIVOe ^*M_O%N/ˇ}B    F\wluIX `,_ܒT.>    `";$IMk61s0X$թ%;Kg     <U/$5b+cd `j1闵$ժEsg     2vz[wwIV6 PUWGk$զ1     D(%$I}{"2 =\:Z.:տ     T(v{Y7xIVf `2ho/fISe     0/w-V%IjT[K ˿%Fu7G3     ̫$i{hk g
I$եΩ(3     ̻CwyIVGz?V!Ah-)"9]n     1Gw$iu/ f
6Gqԯ_TڇbT'Og     &!;$Ijv>pE h,U/_IIvjݣG3     (=_^&U(;k@#|}JR*񨞼/h    Tû(IҘ?VaLQk+Iu|     jo$5md1X1|$բ%;˲e     9/IR*(~$' 4*A3/YIE[;+5      :N|IT? b
<^~JRz3bp2     VU</IRK`lVaup*IunG2     ^ۢe%IjJ~;G}:' 4*̣l/VIʮ{ևd     Ί$5Of_0_(zc*IuNzwD9>    `.Z_4u>g
/SIJ}D[}$    䩪%IjJ#5b/cd
`ˋT2kSQVg     0C>$IM?L5U7̊=^cg     0'bI/IRZ'Z0~yJRjKvWd     05_EHԀzCS`Ҡ_V1K٧1     LHԄoe_0VaG)I><(    =Co$5,ڇd
s|h-)zcQ     mЍQoK$iY/Ͼa$%#*(    W=2=_6 IҴ9淲}:0~;Z3/JIʨsD{G1     4ދ5u$I}*0:R2jOd     8O'$ik׳|*^$bWGc     {I/$iܹ<ʇa
[}һ/FI{rG0     4[#ޒn Iod05VaW]oWԼfS`      "'bWH40ʇ`
[}/DIwo,>~    g}~fJC$iZk*l}_4_/     ,MG$i&*lIN%iu}GĠ}     ϥ{$I:Qm`6pњY~JҸj3Q>~    PuoHW$i*YʾafW$bWEG/     Go֒/H4xU`6Qh->h{I     lM1H4e&*l7򓤱4 7}     {G$IW}2XMkEk٫/>IGKf     t}[$IQozH	W~I8~#*     @ĽQ,{E$If_0Var'I:E     ́Fkfa$ITg_0Va#W]~I|WQ}0     POAH4U-6+&*lYɿ$i>[C^}     s*sEH4E:,c
>;_t4o,ͧe     <Z'$$IGj`6Bڣ/9I/>j    yV\0~$iZ*9zb
8W/8I?Z     `6!IҴ[&*#7_n4_xKD>j    q7
Ib&*!rQ=2     Ƭj?~UH4f`^DO_l4->ʕ+X      Ih-6B	;ab&R9ofAn<%     O$I<*Z`
/K$i]     Ωv!IҤW>|C`OYFkߝ/4It>a    ǣuo$Mrft<\~I\>Qu>^    )W]EۤeH4&*<W?~I\U(#h     j$Mr嚻s=Ux_d4',f     @UUtNwI&GdP{5_b4W,X     &@^~;mH4uO{_Ug
ϡKLqUe     YfJ$i*2*r5UxKL?Uwm
     Lŋ9$IʇϾơVh-yI&I[RQ+D     &QUFI$is[j`epy闗$mQ3cxWS     `UkWEǫ=$I:'~f
=c闗$mI>J    )0h,H$ibZA7
2Xg)K6}DUe     I&rj`l?ξ$isjVQ
     LA7ڇb;$IR!ٷ7Ԗ*<`?iQK6b+\sw1
     LrI&92XgKK61ky
     LG翉H4zce
>闖$mjKv>>    ~?HTfDy2چZ2X3&Q'(      7~HT\}mC-W^~YIҦTOd     @<Z[HT}eC-80nQ>     hEo%$ոi!Z2X闕$ml>6    *oHTڇ9Z2X)J6>2    'vJ7$-.f_P;ް_V"~;     /eHT(UXW}闔$XŲWDĽG&     ?o($ձ_;vV!"7~II60w}\     ODR$IY+ȾvVaH$_8     xNû/odHT_+j`"}һ/)Iz:'nD9>*     Wk"IRj`"闔$=W~D^}L     A7ڇbۊ$Iuuٷ3Ԏ*h-&hvQ>xm)	     QշDko,$աEDTebJOޟAIsԿ#     `<8ETVg_P+4K/'IzvSQUG$     |ߦHTʇoȾVVi'_N̊v&x     ,X7Ikj`^(rn6Q\}4     l'忻HcdUsI$W},     ̉O{$)%KcU};/'IZ_e      s*bצHU}CxŁoH$okD     95kyfHQȾVViH$5EDrEq     0/g}8=F:'a5bJh,L$5COC     kE]d$Iwc;Z1Xu/&Iͮs{"*8     W.Vo3$o;VVi/&IͭokB     -D$I}_Umpeh(W>     gЍ?N#IҘ*j`Fvv$<(     7o5$be_P+4Z/&IͫsFTU     wL{$Icivkj`F84bԨ~4uf      yAxk$Iz7RԠf>     t#7FkѶ7$g3\Ue;=     ](Fw`    IDATymfaubJ?@U_=     (>8$[[e߶P+4Z̿$M}җFG     @픏EۦH4/n}Bh6b4n<%     Ks$Im}BhݯIT=CG     @h+:$y;eVVi1ItTuG     @핏ܴaԓ#IҜx+j`FIth(W]}     L%Kx$IVa*f*i_     0YAxK;$Is*0XV%G?8     S>rӆ.G9`Fhb:x     X?#IҜd
#Vi4UIŝ     `{>o?$mi0`F3X4h     0UWEkvI(UaJJUo]     05z}<H-`Fh٭\uu     0]E I67UaJJ=8     J{/̂ I6+UaJJG=fg      S{_	IYU`Ut(3(     jU(!I65UaJJڒ}     4IU`U9G     @t?߈$IڤVa*f*is*ǲ0     FZUoE$mt0`F3X,_>      iߋ$IVa*f*iS     *:'n$I*0XV%mJog]      V>~gv$Iҋf
#Vi4UIQ>xm     @D,H`Fh6E,      D_LC$3X4}/E{G      P*Z3ߒ$IzVa*f*E[]ܔ}\     z|4=I`Fh^{fU      <6}~"MI`Fh^g~=fU      -g+IU`Ux(Wߚ}L     :7}Igg
#Vi4UIW(      6RCQoL$d
#Vi4UIUwDTe     &8$IVa*f*Zck>      TU~-Ig
#Vi4UInp͑G      |hn$I҆Va*f*uWDUeM      l9Mw$iC0`F3X8>      BUwm{x$I0`F3X:!H     `n:5I$UeJJZ_ߍ#	     99]Pg
#Vi4UIn/#      XZ}{$U`U#"      IOGI*0XVf9#*(     `>ߥ$I`FhR[(ܕ}     0φw-$53UaJJͭG      c=}Sf
#Vi4Ur}     0&UQS;$aU`Uj`r-      c>oUfe
#Vi4Uy/-      C9?^%IjP0`F3XU_      0JԠVa*f*5٭|c     dCە$U`UjN>}      PUZc$U`UjF1d9      D߰$I`FhRY.>n      A7!-K4U`Uz_G      54oY)`FhtWQu>j      Ω%IVa*f*Mw>f      %Z)`Fh>b       mI4UaJJYGCG      `ЍoH$Ma0`F3Xe/      LmgqI0UaJJWwFTU     o])`FhҔd(ܕ}      0EyI'UaJJU      &X܏yI(UaJJS_      &X~"=^%IVa*f*MI[EuG
      S_`Fht[     iQ7~o`)`FhWKTu	      Sdx`)`Fh7G	      S?I$Mx0`F3X&9     `JUOۧI&8UaJJ[ˢzc     )ֻSb	`Fhֿ#     i/_I&4UaJJY_(G      01I҄f
#Vi4UiY媫      }$I*0XVɫwG      \yefI&,UaJJUkj?}t      @ޗ^&IVa*f*MV>}l      PleI&(UaJJSߊc     }$I*0XV	iv(1      ΓQ3Idd
#Vi4Ui2-dq      W~&IVa*f*տb.      R}ț$I*0XV7      FsN;$i2X4T:'^1      ϩs¿IO$<UaJJ5nvQ>vG1      ϩ|hn&Io0`F3X[#      ^P̿LW$8UaJJu"      T=P&Ii0`F3Xӳ      (g$I5`FhRj>      `TuQw6IR3X4TfFG      lU念I*0XVz=      t )MTVa*f*էbEc      6/Ij*0XVԿ#      HLw$(UaJJ}DG      lrh,H$$UaJJhxy      ̉Ω&II0`F3XG      ̙ۣ5u;$U`UJnѶ;      L&-N*0XVz?}      Zm8IRr0`F3X*|MT      f$IU`UkpݱG       ̛%]N*0XVG%*       W+J$%f
#Vi4U)d     7E$IIU`U >      ['I2X44fog     )>oug
#Vi4Uiup{      gI2X44ƖU      E3f'Io0`F3XW?      fxߥov1g
#Vi4Ui<{&?      s勵IƘ*0XV4?      |h,H$)UaJJ_7F     ?O4Va*f*|9:      Fњ:O4Va*f*ocߑ      j{և$Ic`Fh<6 UWg1     کZI7UaJJW#      Jӓ$s0`F3XEF?      P[պG%o{`Fh;     z?'IVa*f*}җFZ      j*bI)UaJJs_?      01z~:O4OػhSjj{1Zb奭m_4Dƨ@BPFdH  N_dpyｿZ?rw7u*f*l#_e[      FF~"GY$i2X
Uj`UzW-ɾ     `8">I,d
Ԛ4s5*̾     `m<If8U0XVwǲoi      YuǦ'IV`Z3Xfwoi      ]v4}ug`*V5Uifxf      #$I3*TRkZA?v     Wty?$PPaJJ_oe      $i2X
Uj`UڽZ')d      0>^4Ox}g`*V5Ui*nRm      ciJf U0XV][      [V]g`*V5Ui+uE-      cݩ	Jv3U0XV]}od߾      0ފn4%I*TRkҮU{u      cw)Jv#U0XVϷ     ~MPB*f*|櫲o]      ޵'F(IV`Z3XvoϾm     ^|˪$nPaJJ;Wqϕٷ-      N?+$BPaJJ;^}     @=;<5Jv2U0XVٷ,      Vf(IV`Z3Xvf߮      PoeUF/U0XV      j~ig`*V5Uk[      خߎ83DIf
Ԛw^}      ջjIg`*V5Ukٷ)      =h%I;*TRksW      x%I;*TRkҳ:#26      l?#HLQ<B*f*={Ŧٷ(      ,~03EId
Ԛ̵NzoW     !V6/HlQB*f*=sξ=     ]-J#U0XVy#      x8l%Iϒ*TRk׻[      A/Ugg`*V5UZWFZٷ&      '5J!U0XVj}[      ;5J!U0XVyċl=}[      ;ihL$iB*f*{/ٷ$      :#3GI2X
Uj`Un{G}ٷ$      ߾.sGIR5U0XV|=ٷ#      gjg`*V5U1G5v      vSq%?J=U0XV9Ⱦ     : %I`*V5Ubp߿fߊ       %I`*V5Uս}      3iPD?Y$``Z3XU+46      fX맧)I2X3XVUZ'l-      ̆~;$%B*f:׿[      %&)I`*V5UյWE;ٷ    ;l?(n\o:{{뎋GD,:3:#g>uAOuyPgϛ?]ѹ~Eݩ߰"ϟoĽQveO  PKehy@gTV`Z3XU]}eq  PO"ʩbMQqwѽ}Y0+~3Zb!G<L&ֲۢ}Eod}1[nrjF   ̌L(Iu`*V5Uղ5  ?E7+ѻ^?%?yυޢ=yk$o-r54  (=4`$5U0XVU:[  `4(/{Έy)acԹjb^4hk]7G}MsGĠ}   *YN*TRk]b7o=  V>yw_kO>+~3ZK0uz&ֲ9]ѻ(n\szl  PWGnlTV`Z3XUj  `8<tso>oz8M9G(MuA_Dbp^+*  3/L*TRk["  nⶋw19uқ1O3[W>3ѹϣwbp߿F;ٗ+  (:9L*TRkS?Qٷ  ciѹhh1P`5?[>j  99K*TRkSkOɾ   fNŽ_f?:g1wƯ	?4<ޙ}  -?cIR2X
Uj`Uuyԁf-  kEuV;ZGcўZg~t:xfߓ}w   ADs$*U0XVU~0v  ae(6eOJ4asl5Ox}t.<$[>e  9=99Jj*TRkE{Gٷ  3+lߞ0Z(iW;ڟ/ѻla  *f4~y$%U0XVU:q  ]sRt}g4yes4[5*:O]og}   Ӻk?/IRm2X
Uj`Uuhpٷ  Pg;P=TUAtyG7;  5N:d
Ԛƽ֩oξ  *D3?1H6E{E_uFx8  js!FTV`Z3Xոb  YoGqeѽ:hLKFE{F{[4me  @M={?IҸg
ԚƹQFZٷ  0[o>gjr{aEmٷ9  0gA4B*fq̾  qR94'>GAtV-(ٯ   *6_#I*TRk&web  +ۏGD#_#մ汯÷f,   cuӟy$i3X
Uj`UZ{oe^  *V/6757kf\   cO?HXg
ԚƵⶋo/  `o~jhLK5xqt.<$ܘ  784B*fqy"E  򱻣wՒhrPsݫu/DOF/-  }IV`Z3X8g  gTy]sh=    IDATr  h4A3$ePaJj:l<}k  ClluY$M9[Wd  #s!24B*fqjam  ^+<'+'JVW7EÊ  [$FPaJjMm  d)Ql^7sͣ_|"ij.yUtNFz,
  R~#E.U0XV5NN[
  H0x^<ҟK$#%Ԗ/  `w\"Ic*TRk"  J>O듴kMoe  â,uO?H8e
ԚƥQ/5o)  `nQ?H&ܑ  u?H8e
ԚƥE};  m73T%^{Dw`-ٯz  @^+G,E%U0XV5.ؐ};  3lmG?sHp?  PcK9D%U0XV5N9(V  fJ9ⶋ}o6UI-+:OOܛ  ̱oGcrIV`Z3X8Կ[	  MehTir\xHSdT  ssG$i2X
Uj`U#l?}+  h_E?_Hsu{Let  sؼ.9D!U0XV5u.  }+Dcb^s$Lͣ_K#R  `N9(DF>U0XV5ʾ  Uش:Zb$n?~e  fQO?{Hg
ԚF(  xew[hIڟb/  lwy+ӟ;$i3X
Uj`U\oݱٷ  mFFȗ??HҬh|ᯢl>  ̰!I*TRk57  0|mEDc~4mZQt_ R>qg4B*fQ}   OS>~76&IfZ(e  `ll29CF6U0XV5ɾ}  v:
4LW._ T|IV`Z3X(<5" +;:g$9jy@/o  0Z')BF2U0XV5u.ʾu  'PuIZ|}]K8  _?=BF2U0XV5rM1s  +FcrgI݋kf  ;׌Q?WHҨe
ԚF}  @픭G{xgI'xw~y  vR?OHe
ԚFge6  Pew[8"G, Icļ\?l?r  򱻧2yBF)U0XV5R-?Tm  oЏ5'EW?HҘ<QlZ  ~;9BF*U0XV5Ju[  ^qE:I[4o  I$TPaJj*r-  ck"I5jo  `hIV`Z3XըD[  N9%:E{%I?yӯew[[  ,zW I*TRk?v kF+qޯe[   Ϡl<<=~n`*V5UJoʾ]  `lVGץ%IӢ={"^[  4(AF!U0XV5
N[  ;wDS~Ɨ$\~!ޕ6  |bU
4B*fQwٷ
  ^3k'T$p#^o~G  Gc? IC*TRkٷ
  7ύ汯?Kfew[  o=9A>U0XV5  Fۣ_I?Kf։oC~ +;Sӿ IC*TRk7}  hwՒhoy^4o/~ |$i3X
Uj`U\Ftٷ	  uϧ%IsWgB~  ޔ\ IC*TRk:y-  #s/}4&H?Kֲ1x#  ӟ$ih3X
Uj`U\qٷ  bhwIRn#^ŭ~[ Z4B*faU" U6a]4DM̋Ɉ~ zwy	$i3X
Uj`U3  Yqy풤ᬽwl?v  ҽ}4B*fa  QC뒤᯵1x.  #MA$]PaJjk   Rh$itj(n0-  j_N`*V5Uc݋ߟ}k  (;O>C+M̋Ɉ~K g IV`Z3X06[  Bq<ugtI5  `;<IV`Z3Xհ<  EZɽ蒤uқ|[r  0ֺ_gIV`Z3Xհսٷ  *폿-l.I϶ow  0oļ$MPaJj<!  4yK咤17~ 发%{2X
Uj`UTkOe  ׊C䒤51/zW}8  RÊ3$KPaJj^>}K  <h}'㒤zֽ   KͣL?KPd
Ԛ֍ٷ  m,?,.Iw t$B*faɾ  `{$[)#  06ߚ~Η`*V5UK};  <rle%IzzD3  Fk[*TRkܞ};  tv4a[gU1r}[&  g%)=U0XV5NzS   Fw{ޒ$HK  0rʩ-QlZݵ>8{IJ`*V5UC  `\s[j^  <DE%^ K~(/IØ*TRk}3V  Y1xh3$Iļ]S  Wb_Uly9.I*TRkʮyo  >%I'd 1غ1VDw͡^~*l.I*TRkʮ{o  Y~t/~_Y[#a `VoEOr4a[*U0XV]qٷ  ̘h|{9[٨{j `]qxW.J?gKg
Ԛ2  6  1xhs$IYs  E/[7FGgh-ygjI]PaJ*ɾ  `F[c^~Ɩ$i.~/  T+h/?xz }v$Rkʬ[   v[F}ג$es5U  Ŧ];yKȒg`*V5Ue<%E7  ]Wѻj$ն߉跳ߑ se(69\$i'2X
Uj`U?  ߉~$)Ya
 cp߿Foӟ'KҨg
ԚrA  l?OrZaiO%  vZ9[]hhL~$pPaJ*Etٗ?  rۃ:Ԓ$Y/eU 0ʩ-QlZݵ<s$i2X
Uj`U?ٗ>  򱻣H?OK4uA?- !Pvؼ.zFgh$))U0XVQç/}  )o=Ǽ2,-IҰYv Fl+s!Z6?{M%IC*TRkeK  vXqץ<giIFQo  ̆rov/hј'*IV`Z3X\/g_  <Ǉ.$BF  |Q^>עygMI҈e
Ԛ޺c/{  !?$Iڍk! Pvؼ.zFgh-~$APaJjl% տTcUIf~[ 1غ1VDCIld
Ԛ˾ yZ~v$i}eq; @e->/}NP9QTV`Z3X\ֽ/y  xNƪ$N}4m 6ʩش:k'rA4~yyPTV`Z3X\Vqq%  Ϫ{̒$m UvEy]/ΪZ6?'If
ԚGٗ<  |53$Ia?k FWыw)ѹϟNΓ$2X
Uj`UsUӿ} 3^OeIR`o  #Ŧѽ^~p4~$i3X
Uj`UsUg_  }~0,IRj|c  P)ۏGqe];L6If$U0XV5'M̋/w  ^/geIjZ#!me  RmQl^KjaO?I4kB*fue_  Pѽ|",IRk(;S 5`oX5F{ј;,&IҜe
Ԛʾ ;6,I}ƯF; SNmb^ƩO?sI*TRk{} ǧ%IRQ V6FqE](+~3G~$i2X
Uj`U]GK  '11/,I>*  <n#{cιM?CI4B*fٮٗ9  DqXWX$={kN>2  <eP`oX5F{ј'$IHf
ԚfMgg_  \D}ƒ$yZO ̵rjKVGwd|{46$i\2X
Uj`Uļ([/s  jlyċƒ$i=xG `'ؼ.zW-<g I:U0XV5NOٗ8  56>t$ik: ̌-GoZep%#IR2X
Uj`UYʾ O53$Iڵ[D}  Fɠo΅#Z'l4~$B*f٬K *ۦ?<,IvΪwg+ !UMv2+Dȗ_$I3d
ԚfEZٗ8  u3(?Kw٧ `'ؼ.zW-yj)$i3X
Uj`UU{of_  PM?Klb^yN KE/[Y0ZO	%$i2X
Uj`UU/o  jw1`I4-/_}  fà֍߰"kG-I4sB*fjٗ7  5ҿhL~$IS?e9 TNmb讝<I4B*f٨( 8ls$IZke= T/Gß.$IJ`*V5UF, &ʩy$in lUl_B$IOe
Ԛf7>}i PvN$Izמ}
+;VDw͡^~% I4U0XV5M̋rۃٗ6  ,s%I7w> @mS[ش:k'rA4:0< IF'U0XV5ӵN }$IʫU `f(6Y0ǿ.}_$xPaJj^Oٗ5  ch,3+Irk}4Ubuc~8l~4&H$Ic*TRk銻.; cGn/J?Jᨻ	 rDƳ:ј;\$ U0XV5Mmd_  n#ZcW$U> )DiutNF{hu`{$IiPaJj&kmٗ4  cg^I4o\}T4eg*뢷~itV-	$IV`Z3XLֽCٗ4  cwI]I45mG, 0l+s!Z6?{K$=kPaJj&+, `vϻ$ikA}tUNmEw͡^~7gJ$TPaJjƚ'Ⱦ 3eQ?e(Ivg_ `SDiutNF{hVI`*V5UT  fTYFS~֕$I#Ԣ=S <dwޕD3c_>*I4B*f{/g  LϹ$i>)de 1غ1VDw͡:hL)I4'B*f 12x8ls$I+~k C9%77=Nu7J$e
Ԛf}" qmD7s%IH[w\(b讝<$IC*TRk[ |/ϸ$iZW[}`mQl^Kja$IV`Z3XLԽCٗ2  c$IXG8 A?[7FÊ94ZE{I$\PaJj&*4R `#H?Js;9 w7>8D}$I"U0XVMmd_  Y$IcYړO; xw]ݵ^ Ǽ"J$il3X
Uj`U[{ٗ1  c$I<pcFEoZe11/I$.B*fݭ{ξ ]l,?l+Iƻ7Dݖ}`6п|/+L$IuPaJjw+re (Zs$IGE4x~N"\c~5$IzZPaJj#ٗ1  #wՇϵ$Vo>/.yDqe];y+S$IB*fݩuқ/a  F`-8ls$IWͣ_B <n#WEsy?$IB*fݩٗ0  Dk[ϴ$>ݠ֍߰"k1O{$If(U0XV;o:; `DXyV$ջ޵d jŦ];3'H$i3X
Uj`US=ٗ0  #dϳ$-?ܖ}4ke(6UKrA4ye$I6U0XV5?#ٗ/  #}寧g%I:堈}<E/[Y0ZGcb^k$I3X
Uj`UZwf_  ϲ$I[w#1غ1VDw͡^~!5]$ICe    IDAT*TRkն4  쌲d4}uYV$ҢbpP+DiutNF{hoI$FPaJjWm ~o9V$j}'n>.(8z_Y8WNK$i3X
Uj`U"n <te%I΅d ^ыUja͏ļdI$QPaJjWjd_  ߖ~$Izۿ}r=b	7|2:_ha$If?U0XV+u/K 3$IҎDz,0#ʩ-QlZݵ^ G4uV$I5`*V5UJk/]  FDٙ~da%Ivߓ}ie(69\SI$i:U0XVM̋h ~ϰ$I;ļ(r1
lUl~4&$I)U0XVm/  7Ecr3$I<<5NhrP4&N$Iv8U0XVu>ٗ-  #~~$Iն Z9%Mv2+D_%I`*V5UlN;l =W]%IvyQui
cۿɹؼ.zFgh>I$i3X
Uj`U;`ٗ-  î,u[Ϯ$I[Eݖ}aEt.<$ZGcb9I$i3X
Uj`U;aF !׿3gWI0ni/?x׳_$IV`Z3X:/Y  ]эGCU$iƚ#{>eCŦ];y_$Ia`*V5UL/}% ]}|U$ikFQeg*뢷~itV-~}~$I:U0XV3m"  x6eI$$Iƶ>nskwIYho]~=$IF*U0XV3- `8*I4k-3[n>rϋCh,/G$IV`Z3XՎ<r} 0<VI٬u#EQlZݵ^EH$I*TRkgZ
 ^>~f$IzO>z;nb_Ul~k$ITV`Z3XՎֽٗ+  Cl~'G8*I45xQOޟ}͠aEtS$IRm3X
Uj`U;Z/W  ?n>J$e~rjKVGD{X_k$I`*V5Uhf_  H4ayU$i+n0(Sn{0M_Y#_Z I$y2X
Uj`U;Rsɫ/U  T$IRF~4TqVu[4:Fk^$I.d
Ԛv7R `u<eUI__'2~n]shN9(L%I$@PaJjG}eq
 }#gUI-g`sGo:;k!ZͿ%I$NPaJjG*n(R `hcgUIZ'CϬl?]EwdW.1Ho%I$aPaJjG*?R `o8#*I4,n#뢷~itV-ֲј~J$IJ`*V5U=_ͣ_} 0lAN$IҰ<EQ>S̭A?lO2Zh,3~$I4dB*f}۳/S  Lqϩ$IV?>*DiutNNqc$I`*V5U=_݋ߟ} 0dZ%*I4ߺ"3l<m_|jⷦ+$I4B*fOg_  ޯQ%IֲE/;`[4:N_Ǎy$I1`*V5U=_/S  H?H?J$s}4nPLoÊ94>$I1`*V5U=g1g_  XW9U$ik(>rjKVGwd|{4A="I$fB*fu} 0D/*I4
u.5Tb]$+DW$Id
UԚ΅d_  3#H?Jٻ`2	LIJJ$ԡB	&M4i.aj⤄ -6^&Ɔ-o«","el/Hٟ眎k?d?+=_7ѽ7>zvMxznvw  `U*2XUVی?>J$ii|) IWl}ƩͦdhÁ  ^V"U`k$IfӺKS g'D_rzVn[_6g  f**u̵b~$Iz^}
 ,;+W?9N=-  ?+U`U3XeG?OI$!N{]}
 l5]zzrpu(  @V"U`yyS$I| b:lZ|z=«Uω   m3XV:U_uH$IhÁ) Fuj{s%VNw;  =Td2$Iޡ/M `u]uwMxT;E  `e**u3{)I&7~ tE?Qדahq={xk=znvza	  Y`U*2XUVY_|o]ϦS$IOxUm
 !MGFx;l9m8J  Td~$I
nzϵw) @`_zm}=ڸw  1XV:UW[I$)ws~ tOUtzy?{   TdՇE?MI$VO rz-'_ٷ8Nza^{  V"U`Lo\Ӕ$IR`} t_>:UzrhÁ+  =Td걻$I _}=kǩmU׽P  TdAϭj4%I졯ߤ  	?Su=G{tpG=ݾo^S_y  `U*2XUVy?,%Ihߤ  Y;.sM[ɖ3zrb   DRRg3}k$IRTQ;7) @~}5xNWUճld=u_Xf  JEJ*4td$IRPQ lF}zՎhzpGe  JEJ*4g)IgN=
 _|o]=qoݕz}S=޼ۿ7c  @U`U3X噪ǷG?KI$ԫ~ d4<鸞S=zx=9N]w  =Tdtϯ몊~$I
h|1( @Z+gomѥW/};   lRRgO')I'B=
 7{R^~   BRRgyK$IR@cw+
G {pnT7kX   RRgӍpP$IR@	E ҫ뺪=fzzzzp~ª  (U`U3X&_L$IR@^~ ɭzՎ>9N=G   1XV:Un$IZnmw(  u=njx=zqU=8u}   H`U*2XUVm^u5$%Ir? Pp[7k}g  Tdޑ/~$I
oQ  J~;hM[ɖ3ц)'	   'U`U3X)^%IrnC XpG_OSzn   QV"U`/< 9J$F;     0U`U3X)k~$Ij}P     V"U`Lo(9J$f~     g**u<eoD?GI$Gߠ     @JEJ*V=(I|5w(     mRRg.TS$IRUo+;     :`U*2XUVep$IZlOߠ     @RRg.K%IbO^
     $`**u2(IA    V"U`]w\%IRo\~     IJEJ*̾(I]     H`U*2XUVYXw]OOQ$I-?7(     Td;_G?CI$Tza^7(     Td28$IZj     H`U*2XUVg(I     H`U*2XUV_:J$     H`U*2XUV|g(I=     H`U*2XUVsm3$IRxt	     $c**uT;~$Ij~{     JEJjr}_]WU3$IR&u?    \V"U`5}$IZhvM'     Td68w$IZhyM	     $d**u.zo$IR?     H`U*2XUVs_{L$IRW'     Td6'(I+     2XV:f%Ip-gߝ     @RRRg['(I^     H`U*2XUV[=u]͢$IoO      'U`U3Xͫџ~~$IjXb     H`U*2XUV|5O$I7     H`U*2XUV'I_uH	     $f**uy.P$IR?w'     Td5'Iw'     Td5ݶ>I$N      1U`U3Xk'IyY	     $g**uyUoG??I$5oN      9U`U3XMF?=I$535     r3XV:՜k^$Ipc^~w     JEJjN-I$N      9U`U3Xix[$Ilz7'     Tf4D?=I$5xoN      U`U3XiOO$I6     `U*3XUVsrvӓ$IRN}m	     `**u9Mo~z$Ija/9     V2U`5٣wD?=I$5Tv	     `U*2XUVsF;$Ij{     `Td[g'Ixr	     `U*2XUVg'I}OoN     ERRg㯉~v$Ij_f	     `U*2XUV~MN$I;GoN     ERRghÁN$IUv+
9     JEJj>~v$Ij7ߛ      JEJj>O~v$Ij-gߛ      JEJj>ӯ>I$~o     f**u$IP7     v3XV:|D?;I$5~o     f**uɬثg'IoN     JEJj.C_$ITUU/     `7U`U3Xͥˢ$I@	     P0XV:\'b$IRCM6     (JEJj.$IP~*     (JEJj.$IP	7     
RRgD?9I$5wߛ      U`U3Xe|ON$I5įߛ      U`U3XerON$Iؿ7     
RRgt''I{     `**uR$IRMM     Td2{''If	     TdR~r$Ij]?I?     X`U*2XUVY''Iv~	     LRRgGE?7I$5M     %V"U`5ڟ~n$IjU&     RRg㯉~n$Ij
7     0XV:<g!I$vz&     RRgpM$I?M     %V"U`5E~n$Ijޑ?~o     ,a**uy.ps$IRC-{     `	U`U3Xcţ$I5     e**uyLn:5I$'	5     e**uyL~n$Ijك_	5     e**uyL<I$w_~k     ,`U*2XUVwcs$IRMo=/     XTd1{&I|z	     ,U`U3Xͣus$IR[     `YRRgG=G?7I$5?5     e**u9V??I$F{O	     ,U`U3X͡wD?5I$5?7     e**u9$IPOv	     ,U`U3X͡~j$Ij]^	     ,U`U3Xa_~j$Ij7     e**u9>OM$I;&     V"U`59o~j$Ij?~o     ,`U*2XUVs^x@S$IRC-zN	     ,U`U3Xat$Ih6	5     2XV:FWE?5I$5P5N	     0Td0tTS$IRU;5     2XV:&7$I@cwߚ      sJEJj-~j$Ij[oM     V"U`5E?5I$5oM     V"U`5靗E?5I$5Wߚ      sJEJj{7G?5I$5ߚ      sJEJj$I@[5     2XV:~j$IjW
5     2XV:G$IhroM     V"U`5j3I$ų(5    IDATׄߚ      sJEJjt$I@MGߚ      sJEJj+~f$IjՇߛ      JEJj$IP7     1XV:}䇢$IjM     V"U`zG$I$FWߛ      sJEJjyi3$IRC.p	     0Tdv_OG?3I$5ߛ      sJEJjOxU3$IRC.{     `.U`U3X)$IP~o     e**u78W$IjM     V"U`g&I}ߛ      sJEJj?L$I5Z{     `.U`U3X$IP~o     e**u7<mL$I5<&     \RRg}~f$Ij~o     e**u7p`3$IRC~o     e**u7O$Ijx[M     V"U`F~0I$=     `U*2XUVot$Ijx{     ؃JEJj6~f$Ijߛ      sJEJj<8I$F{O	     0Tdvâ$Ij{     `.U`U3X񦣢$IjtM     V"U`ƛD?3I$5?7     2XV:_L$I5C&     \RRg}N~f$Ij7     2XV:tj3$IRC67     2XV:l9#I$_8(     `U*2XUVoOE?3I$5CM     V"U`&|6I$~o     e**u7g&Io:*     `U*2XUVozL$I5{     `.U`U3XmD?3I$5M     V"U`.~f$Ijɍߛ      sJEJjJ$uW7     2XV:3X$InM     V"U`G?3I$5M     V"U`V%I&     \RRg}$Imv{     `.U`U3Xퟋ~f$Ij_7     2XV:3X$InGߛ      sJEJjMo(I$Ƿߛ      sJEJjJ$ujC&     \RRg}$Iݭ~'     `U*2XUVoL$IM5ߛ      sJEJjJ$uߜ      2XV:3X$Iv~s     ,`U*2XUV`U${a	     ,U`U3XL$I;GoN     eJEJjMo;?I$Ǿ,     XTdvd9L$I??ߜ      2XV:g&I     `YRRg}~:I$g>     XTdv+gF?3I$5?9     e**u7'$Ilx7'     V"U`&7$I`K?~s     ,`U*2XUVorL$I6     `YRRg}O~f$Ij57'     V"U`$I`O9     e**uݷ'nI$M9     e**u7G$Ilze7'     V"U`$I`o]~s     ,`U*2XUVo|G$Ilm7'     V"U`W~f$Ij;ߜ      2XV:]"I$     `YRRg}K?$IdUU/;     X`U*2XUVo?~f$Ij?~w     ,a**u7Zg&I#w'     RRg}$Ipߝ      KJEJjys3$IRO     `	U`U3Xg$Ip~w     ,a**u7F?3I$5ܷߝ      KJEJjg&I]     `	U`U3Xi~f$IjUߝ      KJEJjN/I$&7~w     ,a**u?碟$InrgN     %V"U`g&IuE	     Tdv_OF?3I$5-w'     RRg}<I$'	;     0XV:g&IF;N     %V"U`z I$v}'     (JEJj$IJѮ~{     <݊TdPϦOM$I?w'     @`U*2XUVsF;$InpkN     TdP-<$IpO^	     P0XV:ǷG?5I$5wߝ      U`U3XamOM$I7w'     @`U*2XUVsSS$IRÍ9<     (JEJj훢$InrN     Td0&Iv~	     P0XV:v$Ifn;     
RRg䫟~j$Ij걻N     Td0&I-ߝ      U`U3XaOM$I-y'     nRRgã$IZ~{     f**u96~j$Ijɿ~{     f**u9.yS$IR>oO     V"U`5#I$v}ѷ'     nRRg?~j$Ijƕ'     nRRg7D?5I$oO     V"U`5i$IBoO     V"U`5	?$IBoO     V"U`5G?5I$=     v3XV:zG8I$woO     V"U`5G?5I$A~     ,2XV:$VU׳is$IR     `U`U3Xcׯ$IR     `TdQ}&I     `Td1{d[s$IRg	     `U*2XUVwCs$IR.p	     `U*2XUVuEs$IR6     Xd**uyLo I$&[ׅߞ      V"U`5ɖOF?7I$/ߞ      V"U`5]V$Iݯz     `Td1rus$IR&}O      U`U3XctF?7I$Tߟ      RRgwD?7I$T?     V2U`5/M$I-58'     Tf18ע$IZj'     TfJ$)G	?     V2U`51/~n$Ijɗ?~     JeJjPs$IRKM,     0XV:DVSU$IBo?     V"U`5j#I$'     TfR=qo$IRK-~^	     $g**uZ$IRK}Y	     $g**uL_$IR~%     3XV:\G?9I$7ߟ     @rRRgd'$IZjtO      9U`U3XecON$I-?    V"U`5ƕON$I-5ٺ.     3XV:\F{O$IRKR	     $g**u?ߢ$IZz     H`U*2XUVs|7$Ij:V~     JEJj.^$Ib#_~     JEJj.,I$R
     $f**uV??I$ņgA
     $f**uԓa$IRK.`	     $f**uT;~v$IjǇߟ     @bRRg[$IZjzE'     Td3UN$I-?+Eߟ     @bRRgs$IZ?    V"U`5ɍD?;I$X~     IJEJj>~v$Ij_L
     $e**u.y$IRzc
     $e**u{[$IR.zo
     $e**ug'Io:2     2XV:|':I$&|6     2XV:|zGx$IR;u]
     $e**u	g'Iv<     9JEJjNh!I$^A    V"U`5걻$IZ̿A    V"U`5ٷ~z$Ij~     	JEJjNm룟$IZlxoP      !U`U3XiriOO$I-6ڸ*     2XV:՜W$IbOA    V"U`5~z$Ij]Wߠ     @BRRgD?=I$;oP      !U`U3XiW$Ifqr;     H`U*2XUVs'Icw(     Td;%OO$I-78uw(     Td&9u]UO$I-6<w(     TdU~~$IjUߠ     @2RRg[$IZlOߠ     @2RRg+$IZloP      U`U3Xk򕳢$IZZx$     1XV:ռƛ~~$Ij?~     JEJj^4I$3w(    {q;U/Qctm;hl2Z&&1S%Q-MsTcLL,\D.B@JD ʊ;sΐCY9>ߙ5 R`^ߜ~~$Iq_C    JE:z>_O$I3nۯP     "R`^ݣ^~~$IqïC    JE:zuzzI$iƍo0~     1XVUuuz'(I6ٲ1~     1XVUuuk~$I,KC    JJE:պM6$IҌ
     T`U*2XUm|gOP$I3wߡ     @%V"UUj݆_h	J$i??w(     P	U`UUgZkOP$I3nx;     Td3X[?M?AI$͸7?C    JJE:պ>'(I7|u     *a*V=OP$I3y
     T`U*2XU֭s3OP$I:<9~     0XVUu[j:P$I3{/oQ     `JE:UP$I3wkw(     PU`UUg_J?CI$͸Eߡ     @V"UU*o~$IqC    
JE:UH?CI$͸w(     PU`UUgJ?CI$͸'ߏߡ     @V"UU*uoL?CI$ͺ.-
     ,8U`UUgJ/O?CI$-
     ,8U`UUgJ_H?CI$-
     ,8U`UUgOI?EI$͸E    f*V٦lI?EI$͸Oߡ     3XVUul37OQ$I3n|;     XpR`mƷ|.%I4ߡ     3XVUul3(IY4Oߢ     3XVUul3}(I@c_E    f*V٦m(I@3 ~     `U*2XUMW$I[     X`R`mz~)J$)ړ(     V"UU*t4M9J$iƍ!     `U*2XU恻Q$I3Y;~     `U*2XUI?GI$-
     ,(U`UUgʃF7O?GI$~W(     V"UU*~(I@uoߢ     2XVUu<hw$I.YE    e*VyP7$I;%~     `U*2XUq$IM6_E    e*VyP礟$I5-[     XPR`1x~$I
9{     X<R`jޖ~$I
=n-
     , U`UUgCo"$%Im[     X@R`]wJIJ$)(     V"UU*5l$IRэ(     V"UU*?')I@oߢ     2XVUu<TW$Iӥ5ߣ     1XVUu<T禟$IBu?(     `V"UU*ՏNG$IRީG    b*Vyɽ$I.zw     Td3XbYJ$)럈ߢ     1XVUu<kO?KI$-
     ,U`UUg$IRf-
     ,U`UUg׽),%Is3(     @V"UU*=n$IR-~     `U*2XUpC~$I
Q     `JE:UI3x 4%Ihxa[     X R`G2Ӕ$IRoQ     `JE:Ux)I@-(     @V"UU*dOS$I&G    a*Vy$Ͽ+4%IG    a*Vy$_~$I
;Ӌ    IDAT(      V"UU*{KOS$I_=
     ,U`UUg#Ӕ$IRѵ'Q     `AJE:UnM?OI$l:~     `U*2XU=;~$I
~E    a*VٞэS$I:l     Td3Xe{֦$IBNxE     Td3Xe{$IRG    `*Vٞާ~7<%Ij=
     , U`UUgt?oS$IƷ\G    `*VٮN&D%Iw(     0V"UU*y'*IDM3|){     sR`G3|uJ$)Tc/ߣ     3XVUu<$IBy{     Td3X8(D%Ijxa{     sR`G$IB7^G    9g*Vy4O$IRfm{     sR`G9'*ITdt7)     0V"UU*;O?SI$~W(     0V"UU*;23$IRQ     `JE:Uvdtú3$IRᕇQ     `JE:UvdxT$I7G    9f*Vّ$IBM5~     s`U*2XU#CJ$)U3.W&     Td3XeG:?3L%I{K7)     0V"UU*;nM?UI$=
     )U`UUgΘS$IRQ     `NJE:UvOU$I7}6~     s`U*2XU3~$I
5rK     Td3Xeg~sJ$)d<]	     CR`KOU$IǼ8~     s`U*2XU3:>-T%IM     CR`t$IB/? ~     s`U*2XU&N?WI$ݸ>~     s`U*2XUFם~$I
5=
     !U`UUg\s$IRPJߤ     1XVUu7$IuM
     U`UUg~WU$Iga&     Td3Xegu>iOV$II    9c*Vw$IBn<;~     s`U*2XU+߽*d%IjrM{     3R`]1Ɖ'+ITti'oR     `JE:Uv~$I
=%     #R`]?'+I`oߤ     1XVUu1/N?YI$^uX&     Td3Xet4g+IP[>I    a*VUO~$I
ܷ9~     s`U*2XUƛ.K?[I$M
     	U`UUgʮ}$IR'^I    9a*VU:l%I_oR     `NJE:UvUI?[I$~M
     	U`UUgʮ$IRWoR     `NJE:UvLӕ$IR5     `U*2XU;&w^~$I
࿈ߤ     0XVUu$IN~U&     Td3Xew.y_J$)woR     `JE:UvG7$I=9~     s`U*2XU;G0t%Ilr77)     0V"UU*N'$IRQo     h7U`UUgl%|%I{     h9U`UUgtnJ$)XoR     V"UU*kx!+I`KI    3XVUu9oO?_I$ݸ>~     -g*V]}J$)dM
     Td3Xewu>3iӤ$IRMӥߥ     @JE:UD$Iu?+     h1U`UUgʞ',I`sI    3XVUuWN?aI$~M
     Td3XeO/OX$IM
     Td3XeON|e	K$)XoR     V"UU*{sOX$I:?#~     -e*VSMwkK$)XWoR     V"UU*{j3$IRߤ     @KJE:UL?cI$}     h)U`UUgʞ\7g,I`5~     -e*VSS/%Il؝.yl.     Z`U*2XUz~K$)\K    2XVUuՏNGS$IRK    1XVUu,]J?eI$^qP&     Z`U*2XUF7K?eI$o ~     -d*VYK?eI$kI    2XVUu,7$Iu~F.     Z`U*2XUǼ8%IwR     eV"UU*v\LF,I`]
     Td3XeL)%IlOoR     eV"UU*etús$IR_ߤ     @JE:U5,Idtiw)     "R`?u,Ipݣ^K    1XVUu,{$I7~     -b*VY6k;'-I`ëߥ     @{JE:Uo$Io0~     -b*VYNNI?iI$k#~     -b*VYNߓ~Ғ$I
9Y     h	U`UUgr;'-IpOF.     Z`U*2XU:?7%InwR     %V"UU*˭8%Ilt     h	U`UUgroCYK$)7)     R`6$IR`R     V"UU*mp;Z$IG(~     -`*VYn_~֒$I
?-     hU`UUgr$IRߥ     @JE:UVB]-I`[/ߤ     @JE:UVKO[$I7)     R`0O[$I:l.     V"UU*+?I?mI$[     3XVUu/K?mI$\7     3XVUuON&%Ilti     3XVUuǷ$IMv&     V"UU*+e$IRxw)     d*VY)+I?oI$O.     V"UU*+[[$IE.     V"UU*+{/$I9.~     AR`=8&$IRK    U`UUgJsSK$)ٰ;]Z]
     JE:UV膳O\$IG0~     !R`4'.IpK    U`UUgJ$IRᆵ     1XVUu~$I
7]
     JE:UVUӦ3$IRwa6     f`U*2XUrK$)\R      `U*2XU҆_hK$)\R      `U*2XUyK$)w)     `*VYi_~$I
7]
     JE:UVONIK$)Xsw)     0{R`Y{kK$)\gR     `V"UU*0q}K$)\K    3XVUu.IpK    3XVUuB-%InOR     `V"UU*Y/O]$I&w;~     3f*VիMwkK$)d<]     U`UUgʬo2%I{>     !U`UUgʬrtK$)\?ߥ     JE:Uf?I?wI$]s\.     f`U*2XU2+ݏ4%InR     `V"UU*3^d~$IJ6N<.     a*V=7$IuzA.     f`U*2XU2Ko~$I
?     U`UUg,$IRᆵ     U`UUg,N}uK$)Kw)     0#R`Y|O^$IΏw)     0#R`Yk:[^$I:?/~     3`*V^$Iz&~     3`*V?~$I
7l]
     ̀Td3XeQK$)x     U`UUgʬuwg/Ip?ߥ     JE:U"x~$I
99     XYR`7$IN}u.     VTd3X%ati/IpKR     `JE:U'%In|ӹ     XaR`ɯJ?}I$kK    f*VIӗ$IRm
      U`UUgJJ_$Izv.     VTd3X%e|_$I_]
      U`UUgJ_$IF7ߥ     
2XVUux}K$)\w)     V"UU*)#~1%IԂ:?3~     +`U*2XUzմnM$I
;7)     2V"UU*IM?I$\     X!R`#ҟ$InXK    b*VI' Ip{K    b*VI' ItM3m
      U`UUgJԚNN3$IRމߦ     3XVUuMg IpK    `*VI]g IpOߥ     
0XVUug Ip-w)     V"UU*iݏ4H$)]L;>5~     `U*2XUҊd<L
$I
;     X^R`6 Ip*~     `U*2XUNI
$I
7     XfR`6kZ$Iߎߥ     23XVUuAW?I$k&Oߦ     22XVUuA?36Ms$IRc6     Td3X-&ޚ$Inp;w)     V"UU*m1 IpkOߥ     22XVUuM$I
7[     XFR`A$I&Oߦ     21XVUuEg?I$qoS     `JE:Uڤ'!Ip]
     ,U`UUgJ7^$$Inw)     LV"UU*m2'!Ip;ߥ     21XVUuIצ?	I$KM    e`*ViڟO$IjA_M    e`*ViիMg!IpߑM    =g*Vim?I$]{R.     Td3Xm֦?I$uC.     Td3Xmg,$IL;<9~     {`U*2XU6#N$IjAO<~     {`U*2XU:WM}OC$Iu6     Td3Xƛ.O$I
7w)     V"UU*m4ܰ6iH$)d]
     !U`UUgJ7iH$)]L;>-~     {`U*2XUF#N$IjA_M    =`*ViիM!IpߓM    g*Viӟ$InXK    =`*ViᆵC$IᚭR     `JE:Uڪ־C$If9     MR`w$IR[     MR`ZjK"$I
7ߦ     1XVUuxOD$IL.     vTd3X͆֦?I$kK    d*ViY?I$Ρώߦ     n0XVUuYȽӟ$IZPWoS     `7JE:UZmiӻ/H$)oS     `JE:Ung"IpR     `7JE:Unam3$IR恻w)     V"UU*m?kg"IoS     `JE:Uڮ{D$I-woS     `JE:UZoiӻ/H$))     kV"UU*`"Ip[/ߥ     .2XVUu̃ᆵOE$I?m
     U`UUg<蟵oS$IR     R`y=r"I?)     V"UU*saiӻ/H$))     V"UU*b"Ip.ߥ     .0XVUu̋ᆵE$IoS     `'JE:UE}ӟ$IZPȽ)     V"UU*b0A$I)     V"UU*scXI$ߦ     1XVUu̓ӟ$I{U.     vTd3Xe7M2$I
.yl6     vTd3Xe׽1H$u~Q6     vTd3Xet'#Iߦ     N0XVUu̕իMGF$IFM    3XVUu̛?I$ym.     vTd3Xe80H$)x8]m
     Td3XeN{M$IR~)     R`y99F$I-hp_oS     `V"UU*#IpOߥ     JE:Uҟ$IM~     UȽ~_    IDAT`UUg<\#ItM3m
     <
U`UUg<#I.Lߦ     0XVUu̣A%I     xR`ylݔ|$In|y     xR`y5a]$IRR     QJE:Uw?I$ϋߦ     vJE:UU_O>$IjA3M    0XVUu̫26'$Ipëߦ     vJE:U䞛ҟ$I7]K    0XVUu̳u?!I$kO<6~     `U*2XU2#	I$uza6     Td3XeuY$IRG     xR`0I$)oS     g*Vw;MF$I
7w)     V"UU*nӟ$Iҍӥߦ     JE:U]?MF$IjAߦ     JE:U]ؗ?#I$ߦ     JE:UޚMnS$IRuߦ     @`U*2XU&NJ$I
7ٲ1~     c*VYë?$IiM    0XVUu,?%I$I5~   c.;+N 阮uKucmKƮڊuLj;ڎ6vhInI"% FB
4!*)V`!p;k'T:zg^#:I2JY:UAF?%I$P7ߦ     JY:Uʧ/9I$)     b*eV[?$I\w)     0R`i1yFs$IRu)     MR`i{+$I
y	M    o2XVUuLΙω~N$I*GOM    o2XVUuL;$I}     &U)`UUg42II$)?ͭ<"6     Vo`UUg4_{J$IRu}nm
     Jߞ`il>!II$z^~     ҷg3XetR;~V$I
noS     `UVUuL=D?+I$7Oߥ     V6=~V$InOso     g*eV6y$IRu/     g*eV69YI$gm
     3XVUuL3E?-I$7])     `U2XU2%I{~    @V,UU*h󢟖$I
?~    @V,UU*ӨOK$Il)     T`U2XU2>7iI$:6    JY:Uʧ/yI$)?    @V,UU*jk$Ik#oS     e3XeZ{S$IRu}nm
     2XVUuL板$IT@     e*eVVӟ$IT@OnM    ZR`i'&IƷ*.    jJY:Up'&IF4woS     e3Xe>9I$_~    @V,UU*ӬOL$I_ߦ     P%U)`UUg49&(I$)͗ߦ     P%U)`UUgʴus3$IRpߥ     P%U)`UUgʴ~g&I     c*eVv+4I$wvm
     1XVUuL_~f$I*GOM    :R`7(A7I$)їvߦ     PU)`UUgJF~j$I
=V~    @UV,UU*5:;I$tm
     U1XVUuԠwE?5I$P~    @UV,UU*5OM$I4aSm
     U1XVUuTaSS۹'I$)7ߦ     PU)`UUgJ-F@s$IRtQ9&6    jJY:Uj1$I
E)     T`U2XUR/~n$I*'ߦ     PU)`UUgJ-:pJm$IWߦ     PU)`UUgJM{$I\w)     T`U2XURg$IT@3~    @V,UU*5/$I
M    
R`4 I$;M    
R`)N$I     j`*eV=N$I:inQ)     L=U)`UUgJmן$IT@ݷ\m
     S`U2XUR{8I$zW.6    g*eVM~v$I*.M    `JY:U~z$I
n|oS     vR`|]ӓ$IRtm:o     e3XFgD?=I$Pe)     L5U)`UUgJz~Eӓ$IR>     e3XF3$IT@/\~    T3XVUuԪ}'I7#oS     ZR`Z]$IT@M    `jJY:Ujտ'IOoS     ZR`Z54I$7=6    e*eVUg3SjOP$I|66    e*eV[$Ikyߦ     0V,UU*5yG$IR5fm
     S`U2XUR<	J$;foS     JR`u'(I}C)     L%U)`UUg\GѰ%I\ܗV    1XVUun룟$I
aIm
     S`U2XUR'΋~$I*	M    `JY:Ujg(Ixam
     S`U2XURύ~$I*)     LU)`UUgJV>5}OQ$Iѵm}f}
     `U2XUSD?EI$P     e3Xuk$I
cUm
     S`U2XUSRw%IT@`m
     S`U2XUSRo$)J$4     e3X~$I*M    `jJY:Uxˣ$I
wߦ     05V,UU*<~$I*oS     R`\(I     e3Xo:i)OR$IѵY{l}
     `U2XU·$%IT@旄ߦ     0V,UU*|󣟤$I
     e3Xo]')I}~{m
     S`U2XU·t7</IJ$inSS     xR`f}#YJ$m}
     `U2XUBnR$I{ߦ     0V,UU*g)I^~m
     `U2XUByD?KI$ΛoS     xR`ru$IJΚgߧ     0V,UU*|D?MI$Psoߦ     0V,UU*|mOS$IԿ     &e3X~$I*?~    D3XVUu𝚷0iJ$4     &e3XbS$I
y)     L*U)`UUg
Λ$I
׆ߦ     0V,UU*|w6E?OI$ӗߦ     0V,UU*|wI$IRO)     L,U)`UUg
]~$I*
O    `"JY:Ux+HmOT$IԼwS     DR`~$I*օߦ     0V,UU*<I$itoS     HR`Y]5J$C_Eߧ     0qV,UU*<ώ~$I*~    1XVUuo|5J$     &e3XG7T$It.M    `JY:UxtO~$I*v@m
     `U2XU£k.zq3$IR!u     &e3XGYsLJQS$IR:>    b*eV{usS$IR[m
     `U2XU6OU$I43)     LU)`UUg
[}~$I*v:kO    `bJY:U޺oOU$I\)     LU)`UUg
#S0J$95>    Ia*eV}U$I4ҵ)     LU)`UUg
`U$I%ԟKs
O    `"JY:Uxlz~Es$IR!u)     LU)`UUg
MD?WI$R~    D0XVUuصd%IT@Û~    D0XVUu؍>'+Ij~    D0XVUuyC$IR!uxv}
     3XVUu5F$IR!.=1>    JY:Ux:kIG?[I$`9)     `U2XU3>g+I     g*eV~g+IܩOO    hR`ޕl%ITH_~    @V,UU*<>ݷ|$IR!yC}
     E3XVUu8:*\ӕ$IRn*>    JY:UxFwF?]I$PZ[     e*eV|+IBnX~    @V,UU*<~K[ӕ$IR!     e*eVǣ$I
igK}
     2XVUuĴ|%IT@ߦ     P,U)`UUg
Ohl$IR!uxv}
     E2XVUu=%J$z2>    "JY:Uxb'D?_I$ߧ     P$U)`UUg
OLg)',I߱'>    "JY:Uxw~$I*v|74Eߧ     PU)`UUg
Opϖ',IBj,>    JY:Ux'E?aI$ີ)     `U2XUx|$IR!|]}
     1XVUu$,JiЍ~ƒ$I*AЗn7*     `U2XU3g,IBnz~}
     E1XVUuv%ITH:>    JY:Uxrz*K$FfS     (e3X'sqX$IvMs+Q    R`v@S$IR!u7</>    bJY:UxF?)K$zW.>    bJY:Ux׮~ʒ$I*?nO    R`撗F?eI$R{ߗS     (e3X'),IBc7*     `U2XU1,IB]{)     `U2XU1ܳ%9K$xK}
     E0XVUupxgO~Β$I*~    @V,UU*ݷbs$IR)yߨ     `U2XUa2(A7IK$w<F    hR`WvG?iI$7ߧ     `U2XU3uN$IR!,>    pR`e~Ғ$I*a/ͽoT     e*eVu\$IRA5ߨ     `U2XU>xW$IR!>9>    PR`-WE?kI$0>    PR`+$I
ޛV~    @U)`UUg
WsK$I
{Oߨ     `U2XUyԶO[$Iԟ     JY:U8%ITHÛ~    @U)`UUg
pϖ-IBj#>    0R`IO[$I=oT     a*eVn<>iK$zW&F    R`̢-IB~     "JY:U~ޒ$I*[S     a*eVa~v%ITP3~    3XVUu0?z*yK$z7*     ,8U)`UUg
sq[$I5     e3X>xW$IR!%>    g*eVan*K$:ߨ     V,UU*̟D?qI$ToT     XPR`OsK$I
joT     XPR`Og3Sj\$I4     e3X5g.IRj9oT     X0R`pϖg.IjoT     X0R`Wg.I|7*     ,U)`UUg
g.I     e3Xy6(A7K$Y;     e3X7mWS$IRA5[^~    0XVUu0Ή~$I*GOQ    `AJY:U^%ITP>~    0XVUu0:g%ITR~;iw*     ;U)`UUg
}.Ij.zq
     `U2XUrUs$IRAw̄ߨ     0V,UU*,D?wI$K;oT     wR`F.It}I}    2XVUu0:kMG?yI$Tii
     `U2XU߽/K$~}
    0oV>5xR`pϖ'/IoT    ånqj.K3io6DV,UU*,IO^$ILs
S    ΚcRiio_qo:8NFN
`*eVat7%ITXݷb
    V޶ixi|`oJ1}:7(c    IDATXR`̢g/I/T    [zק)'hg3`U2XUݶ+K$FQ   ǩec&ͦhgo$e3X5uv$IRAinՑw*    0:kIͦ}Eْw~"7V,UU*,e~$I*T    `ʬ:*u7,Im󼟎wA,U)`UUg
sq^$I_ߩ    d[zק)RJY:UXxwE?}I$ߨ    dSRLMmTjE/
E0U)`UUg
otUO_$I8sEߩ    @y:Nͦ}EْIy`U2XU_{Jӗ$IRak    aIm[ק7Ԏ${{%e3Xl>!K$Wu
    ,κũٺ,>vzߙҠ3XVUu:k'IS   Yl~II};Pׅ'e3XE?I$T0,
S   'lZW-i|`oJmj߃`R`bE$IJ
    <NJKRo4ؽ>Li4M#bJY:Uџ=)K$~}
    <?z~:'nەҠb[ߌ`R`bt7%ITX/\~    Y{lj6$w̤Ѿ55yfGJY:U2ﴓ$IRޠf/V   ~zj6-M+pϖ4>7pme*eV!ΡB$IzXS   `:2u7,Im`4ڿ3Q?lxe*eV!`$I*5~   [RL}Cۑ/	O0U)`UUg
qz*#@$Iu;    &Yg&'Ѿگꆟ4V,UU*u\G$IJk9]
    afQn<>H=[ޔ6[>=XR`b1 Ij.;    ݰ$-OhΔF=}?ve*eV!薫?$ITXT    Y85[47K3XVUu)$I*,_   PΚgfԿƩʩitۮ_3XVUu|Bǀ$IJkؤ7~
    bfQn<>H=[ޔ6[9So1G,U)`UUg
:kMGH$^~   ݰ$-OhΔߴ9!V,UU*߽/@$I5T    x:f1FfS۽767\`U2XUB/($IRa;    Mg3Riio_7_ZM3XVUu?{RG$IJkOs>-V   Cf%צ-i|`oJ8[4M@܁2XVUuI$Xsoߪ    Thyw'7Ji4LZcXR`
0(A7@$I5*    Snqj.K3io6ݯG5i?c`R`0mWǁ$I
kg
   t9&5igKjr`3XVUuP?$ITZ~[[   	5(u7,I8u|`oJ8[/V;2XVUuPe8$IR5OU   ~"-O=iD%jn@R`9I$ࣧߪ    nqj.K3io6E%=bs3fd*eVwE$H$;   X5Ǥf߾"lIFm%=V?=`U2XUB9F\ IRg3oU    ȪRwÒ۶<o MGK%=:k[1XVUuPD$H$[   Y8.=1vO;S6_GIi?d*eV?$IT`ߪ    qjuYI}|-'iAG U)`UUg
8 <$IkߢoU    Siio_{G2XVUuP?$ITZm{O߈U   xJKRo4ؽ>oT#=YſSJY:U(ӗD,H$z~
   Cޥ'LiЍH*9:`U2XUBY'E,H$(V   Qgf1FfS۹'"i2V,UU*I$X{m*   >:5igK4u@R`
3_"IZ쟊W   ̢CLS?4Nm_ISYw/ĿyJY:U(]$I*ޕU   &Ugl];=Hqxg V,UU*gI$oU   IYl~II};o2XVUuPeh$IRG߫    EYlZW-i|`oJmU=?+c*eV<7xG$I
֟W   ¬:*u7,Im`4ڿ3Q?+IߣAU)`UUg
ej+A$I_ߪ    nqj.K3ikRtnz~	V,UU*io6A$I6oU   Y{lj6-MO>stj.|AgV,UU*)$I*\{   IYƩW-i|`oJm͋y?wc*eVL?$ITh4   `:2u7,Im`4ڿ3Q?+IX`U2XUBIj$I*{   t-Ne}S$\&JY:U(}$I*ߪ    ai6-MON};Չk.+JY:U(ӗDDH$FY}t
   TffQn<>H=[ޔ6IP%a1XVUuPEDH$К-/W  )ݰ$-OhΔD$Mh%/\#e3Xr$Iwk{   uSuYI}mC7W`U2XUBf4FLH$w|:^   &Rg3Riio_7_CҔlO}2XVUuPm?&$ITb8uN*   PS u7=??w׿
kCJY:U(`$I*ޥ'߫   @AV޶i{}ߙҰ$f?#c*eVl^1!IB^~
   {+`iR0
I5fg&V,UU*1!IB;WE߫   yFj6-M+S_MHc៣2XVUuPۣ?*$ITh7x
   f3RwÒ{kpϖ4>7v5$='`U2XUBF"B$Iֻ5*   $<"u7</iɍi|)_9Ha[JY:U(_꿎$IRozW
   <vuSuYI}~=I=@R`\k$I*sϡ?%f   Sg1ٴ4H=[R{_%HRHE/L&e3X	p_$Iu7  @V޶ixi|`oJ8kI*N`U2XUd~cǅ$I
ׇ߫   Pκũwi{}ߙҰ@y?	d*eVa2>I$֏߫   0f1FfSZ4Q5o2XVUu0z$I*Q?uV~  49&5igKjR%ik.|A;V,UU*L?q!Ik   &ΪRwÒ۶<o MG2_ 38R`&G]$I*sU   (]gԻ4ؽ>LiЍ%$UQw e3X17!IBl
   %Լ7Ims/%ںj2XVUu09׼!#C$I9oV   Y}n}EْF2]R2XVUu09=#C$I׻oV   wJKRo4ؽ>o1vrIң?`U2XUYI$w߬   pu-NeihΔ_Kgݷl'2XVUu0Ywcǆ$I
ܓV~  Yl~II}~+I?`U2XUd^~ǆ$I
   Siio_{ѿ$S&JY:U,aǆ$I
ׇ߬   VuOm[ק74E2Zc^;߯p;Vpx,ږvPkXgNui'ۑi2Giw6 	DbkDE"7!\_v]~~c;`~W1HqB*Y3XU3l  Pa/Y%I$Ij/'u.L+Ѷ)_>?*5UfM-HE wIU$IMJݓߝNh=i/}3XUf*կD?  TX~J$I!?Okx"0 >S\PbJV5? t*I$Ij@wMU޺Eiyem۸/{ K>k`JVɚT7  oY%I$I|]p/uIJvW\ d9f
%d`U_{T  *}VI$IRzԿSiu}*Zۣ`_٧V`Jlf sU$ITwOޖLפ-)EWW 2Қ#PqB*Y3X  *lx7$I$)ŻΪ}Soݢ4ؼ2mLiԏ
@ZSF*.U(1X%kR=}寢  *h?$IA24ش{~++) Kg
%d`UgZ @U$I4KNşJS_=១
`JVɚTӦvIE' 
߭$I;#bÁix4޾%	 /̿k*6U(1X%kR}uI @,f$I$:Mu`4ڶ1a/k% LDYV`Jmp' *S
[%I$IG|4xdT	 sx^g
%d`Uoݵ~B  [%I$)KJR_`^3XB*Y3X[פT  6U$IizYo4qMo do03ZB*Y3Xۣ  *xU$IZ{Soݢ4ؼ2mLi؋ 3~lg
%d`Uw3C  Og/߭$ITIݵS4ں>'@-9V`J  *~J$IRj/+uWL[J3E}yg3XUf*ջαE?#  T΋VI$IlӻΪ}S܏f[R*_ 1Fw^yV`J5o?  PenjU$I*P{Soݢ4ؼ2m	 ;?*5U	  x>/^*I$I]{>va_:s,Stz n9;&PpPbJV7O	  7U$IWSÁixT<qwW1 `fzөw3XUf*տCS @O|'n$IxYo[מ۷Tz bxIb3XUf*տE?%  @ӿ~J$IKnj̯޺?OIIiԏ Hk'*5UF  W6n$I|]0/NS~, 0G
`JVɚԌRs @ōn n$I䕩zp`޸&o Lಃog
%d`UjF3-  נZD*I$):Mu7N-ߔ 9?!`JVɚԌ:ǿ=9 /v$IGN+hƝ oRK*5U!M}  (]%I$5r]0/NS~4 PsR`JVɚԜFn~R  񣷇߭$I]Jmiפ-_u 
g3XUf*5#  jsoWI$I5inj[h_l?p]J8k P#>(6U(1X%kRs' U$IR5k/'u.L+Ѷ):_a GB*Y3XS{룟  j`tᷫ$IK_';/NSz$
 @~(8U(1X%kR*/Y :hU$I>Rw4qMo D*5UYo9+Y ''v$I4G--uVzimcJA  S3wI}V`Jͪ'  j`iE*I$i2k˾7Nr  @_*5UYuNxG @v*I$^wԿt:OE  ϫu73XUf*5Li؋~Z  @$IxdԿix˙xr[ wb3XUf*5}ߌ~Z  y-v$I[k7-J+hƔF  S5KV`JkiE @U$Iʵ}RwԿt:$A;+ g.U U(1X%kR :tRW߯$IRk/;uWj+Zۣ  ̋♇o1U U(1X%kRj/{] @Mt׾?~$IsRÁix4޾e ;3g
%d`UjfwG?/  oWI$-5uVzimcJ~ P*5USX    IDATo:5y K$ITIݵS4ں>'Oz JsE
d
%d`Ujf?  Pc~J$IUd]_Sy8t mu@PbJVf9v _$IsRÁix4޾%> joo=g
%d`UjhwME' ߷9~$IŻΪ}Soݢ4ؼ2mLi؋> ixOB*Y3X;_~b  b^~J$IsQ{>va_:F[קD **5U.?$ &z_/$I4KJRCѧ6 @~#B*Y3X[wD?1  p$I=uVz~4o\۷  TGOߍ`JVɚK_  (EԚ#$I7޺EiyemۘҰ}F fsQ
d
%d`Ujvo~f  _%I\Fw_ގs w֟ߕ@PbJVf7g \U$I~s>}" 0Kݵ+UV`Jͮ  P	_%I׿'2  ]]
d
%d`Ujvo~f  g~9$If\vpy ,u>kw**5UM-HE _w7$I43X Yjw**5U  P/_%I7> !?~WB*Y3X_OE?5  xڇ:$IF[G_  x/Fߕ@PbJV~j  ޙ~J$ImWF  B~,TE2XUf*eA{4G?7  SoXI$eᛣOc  fa]7**5U)_  PEZ[+I+/4 `\~S"B*Y3Xhp  5a%IwEoGY ,R`JVɚG3>  P#+߰$IʸŻTg1  0ܲ.T52XUf*Q~n  -7$I}諣Ob  fixIw**5U)'E?9  Hӿ~J$):G) `VߕHPbJV|~' _V$Iy9m0  Կtq]d
%d`Uʧ~r  Ѷ+oXI$YE  RÁw**5U):Ǽ5 Nqj/{]+I[} 0K4TE2XUf*e.>  P#s>J$)~" `k~'TE2XUf*  jdV$I5ѧ0  9w**5U)_g :tR됟c%IWO 7ߕHPbJV  j{XI$h3 Yj/;TE2XUf*e?Ҩ  P#Nc%IU} 0ajM-+UV`J5 ):XI$`  fh=~SBB*Y3XkiE @tOzW+I|*zOG  7**5U)za @t+IL  7wS]ƇUf*WצT  5R<-$IR Ym=/T2XUf*;  js[XI$5αE  JU(U(1X%kRB @/c%I7 `
+UV`Jy_F??  XI$5} 0KR`JVɚg  P7EG|-+If׿F_  RJU(U(1X%kRM-HEk{ @7J$6& `}0T2XUf*_~  w.c%I[E  Rww**5U)] @݌}koYI$5}^  f_+UV`J9O  5[($IRs+7 `K+UV`J7{Jv3 @[V$IljF SkjAmd
%d`Uʻ=߈~  ~+3$IRj/{] ,O~WbB*Y3Xnpš  5=oYI$5αE  JU,U(1X%kRu{  54qM-+I]0 `Fw^~WbB*Y3Xtƣ )O$IUO]  fixJU,U(1X%k PC5~J$Y.;8 `
+UV`J\s\S @;1$IR1 ş
+UV`JgO  5TKŻ߳$IjN;.>s 9	+UV`JjO  5=$IᛣO\  fva]e
%d`ULSF?G  ?~J$9'.  oߕXPbJV%4 *ZYI$տᯍ>o o-UV`Jw  5=]$I_G  VQᷥ**5UI3uV PS?~J$ѧ-  T+UV`JԂTG?I  PC5KM+IZ׿Sѧ-  4~R`JVɚ7'	 ?$IRg-  4R`JVɚ׿O  55{V$IntEg-  4R`JVɚ97$  jxԚZ~J$- `8<T3XUf*--  5oߴ$IgSRvOZ  fR`JVɚnt  55ry=+Iz^s 	R`JVɚ~  ≻wfV$Izs 	~oKU0U(1X%k~~  αߴ$I_, `:G)T3XUf*A{4E?M  CoZI$.	 Zdm
f
%d`Uҏ6ڶ1i Ə~J$~o\} 0KER`JVɚmb i%IT_} 0KGo+UV`JѺk~'i /	i%ITg,  4R`JVɚdƣ	 ?~WjM-k%IT^} 0N	-UV`Jz\< Pc#$IR=+  0bimf
%d`Uҳ5ؼ2y i%ITz~4| `:TE3XUf*	 +/v	k%ITVD  L@ߖhPbJV%=[_RQD?Q  X~J$n} 0c-UV`JzƏl~  ՟i%ITƏ} 03)TE3XUf*^: Ɗ#xV$Inzƣ vSkjA}jf
%d`Us[( ';$IRu 	ѷ**5UIU_~  u'ߵ$In?} 0{-UV`Jz~  FFߵ$IfK 	tjm
g
%d`U5  fva]+Ij6*  0rYm
g
%d`U;  5+H$?tS
 ᷥ**5UIWg団)  j?Z"$IRŚ=a/\ `}0Tu3XUf**v<T Ps3>~J$ZuyK
 t/T3XUf*~
 nY~J$Zg*  >**5UI/T*  nM{߶$INGD_  L@~[B*Y3XBu>O  [($IRuyQ
 %T3XUf*Tx  Fok%ITF  L趯ߖxPbJV%7\ PwAjV$Imu
 96T3XUf*;E?W  4@o[I$¿>M ~_B*Y3Xb|W+  `tV$I/Di
 R`JVɚԂT<p @EV$Io8%2 `B:7**5UI/-gF?Y  4@ᷭ$Ib?xCY
 t}g
%d`Uҋo,  `;}+IҰ} 0	Þ3XUf*YO  9$IbE  L;K U(1X%k^tSRl  ko%IR+} 0!.	/UV`Jz)l  E?o%I4|9
 =!T2XUf*?G?[  4DK~J$i?S 	K U(1X%k^JZ @Cor}+IyW4F  LHcB*Y3XZ &S߸$I'3
 `:Fd
%d`UKm7a $; $IտOP  &}oL U(1X%k^jF?]  4M$I-gF  LH}2TM2XUf*9-O  YW$IS='  2~R5`JVɚԂT~  h7$Iᯍ>= -gߘIPbJV%F| o\I$mݵOO  &hpS5`JVɚS~  h	q%I4.;8 `z~c&B*Y3Xr \s\+Imtǅg'  ==7j*5UI/]Ry<	 !fn˙Z߹$IX	 u~Szd
%d`Umt9O  ;o\I$Ms ISkz;S5`JVɚ[  /q%I47X	 O~cFB*Y3Xr' &)Ʃ}\I$M-gF_  L΋oL(U(1X%k^vSRC  ҿ\I$Mbѧ&  4S5`JVɚ4i  MSbS\I$M7G  LX~gFB*Y3X4zg ;W$I>1 )3UV`JM 0~J$irw  4K{L(U(1X%kf[=O  M2W߹$ILœۢ/L  &iOŻߙQPbJV%Ͷ_~  hy߹$I}#}Z 0aG~gfB*Y3X4zE?e  4k\I$>?; hѷ3UV`Jm寏~  h1ou%I4}> `3UV`JDGo~  hUG߹$I]Go>+ ޹3UV`JDk~  hhjM~J$^OI	 [S5`JVɚI;  ;o]I$z_s 9>goM,U(1X%k&QR1~  hߺ$IzyuZ9	 [5 T2XUf*iR)I iqj[W$I/]Rz$ `\k~B*Y3X4W @K1֕$IKߌ># ÛN5UV`JTݵ4  x;̘$IRH  ̝}kB*Y3X4K^x @ݓ~J$7wS		 [S5`JVɚI6g [W$I/ROH  @gվj*5UIlâ5  h<L#~&ޕ$I7[  hp0T3XUf*iV  K]I$pkWG  ́񣷅ߚiPbJV%M_Ұ @ŎSkzW$I[Խѧ#  s`soM4U(1X%k&+6  ?w%Iu>+'#  sdM4U(1X%k&̟j 0{W$I]G  ̑޺?7UV`JtV @SEo^I$={;/ #ff
%d`Uě#~+y y%IcҨ}. 0GfS5`JVɚhtǅ  UMy%ITw> #7UV`J~"y zgW$I冷}& 0GFw]~oB*Y3X4uyK @~J$:HEoG \utͩf
%d`UҜ4 ;~  hα߽$IYD  ̡W2T3XUf*itj @96$I^ 9ܿ	9UV`Jz_' %{߽$IٷxT> +EK^wB*Y3X4W> z~J$^wE  ̡≻oN<U(1X%k[9  l7$IR6> CߜyPbJV%e͟~  hI.$Iʹ߸ @s84T3XUf*i.] po~J$Z縷E  ̱Y~wB*Y3X42  ɊqW$)W, cc~wB*Y3X4׍] p>~J$oG  ̥p0T3XUf*i_8 ގ^W+IS~= `~wB*Y3X4uNxGS @}%IrjiE	 rfݩd
%d`UҜxTt~  hcw.$IR-5;> cOߞPbJV%Go%  ݵo_I y=oO5 U(1X%k~  Ko_IpJ <hsᷧ*5UIQӿ 1o	%IA{T +OԂS`JVɚx' =!$Ijr3$ `<TC2XUf*i^wb @>5$IRSv~ <l^~{!B*Y3X4_' L$IRkFs y;	?ՐV`Jf~U*  (njM~K$5>  '~=TC2XUf*i>P"    IDAT?p] @&zgI+IԴF^} 0:hS`JVɚlpg L)$IM}/Tg  `-*5UIYwG?{  dd%I%  dxө*5UIA{4D?}  dbt%7$IRZ[*ny <_?oP5'U(1X%k]_~  H縷$Iu{:  QߠjPPbJV%w? g$Iuotǅg  u7*5UI]糿 (uWw$IR]ks;o*  P<T`JVɚ~  co`I6s y4z^e
%d`URD> a7t,ITD_s  ̣w*5UIN ._~K$խ>  gݵP5,U(1X%k"j/}UJa @Fᷰ$IR3 y^Oe
%d`URT{7E?  d`I^Ɣq	 <*y(U3XUf*)ק@  2S<}jM~K$աˢ7  P50U(1X%k' y-,ITwOŎO7  ಃoQ5/U(1X%k%GA  23~ԚZK$Uޙ} {ߢj`PbJV%E6g N[X$ʍ:d  @	EV`JnQ3 @eu{X$uOs  3ߢjhPbJV%E>) uaI*6ں>T  ᷨ*5UIэ.)  CoH$IR%  S+ߣjhPbJV%E7 LuO@=,ITמ} {ߣjhPbJV%E=O!  ?p߲*Ikڔ  ߤjhPbJV%xTt~ TwobI
4  SߣjpPbJV%U_~ UI"GO3  B*Y3XTz~49  c5~K$E_'  }Mg
%d`URj!  uM,IԂ4~dkI @B*Y3XTo~ XĒ$Iuѧ  qj/ye]g
%d`URUlZ$ }obIF6Fb  ?|sMg
%d`URU' uO~O],I4uO0  ;1.U3XUf*2gJv @ԚZK$S{} ww*5UIUjt"  w$I|=ѧ  9vT`JVɚ*?E  27~Z[m,I4׍]}z mIoS5<U(1X%kTg団E  Hs>~K$eS}r P{
MAPbJV%UcwD?  dxuOƒ$Ish 
l<26UB*Y3XTWF?  ~26$Ik~' "za}2XUf*juO~O  h?K%I&O-  *2`JVɚ5G*z;G  H%I&XwFX  TD2`JVɚ*6  RR{Oǒ$IoW R}L2XUf*#  4X$iu׾? BUd
%d`URk/'~"  Q?WY$iVM-H^}Y P!~=NUB*Y3XT\D N~K$ͦY) JZ[L2XUf*.;( )Ʃs~7$IjzT<
 
}Y|2XUf*u{	  ?0w?}'K$|< bW~*V`JlS♇I  %I^BJE3
 ]~*V`JrL OܝZ~'K$W.>  HE2XUf*Ng  J*N$Iz1	 ?z{2XUf*ʵҨT |[Y$rf @;1VUfB*Y3XTFzS	  %kWɒ$IWw;+  ޗ"^UfB*Y3XT|< b:ǽ-V$Iz֦vI^}1 PQoYWPbJV%U7G?  cFw_~+K$=[sk @E;WaPbJV%աcwD?  c}0V$IK^g>  g߬0U(1X%kOG?  cƏߙZ{˒$Iop'  ?c72`JVɚ:=%  <~/K$9-)  6s3F߭0U(1X%kj~2 ک}/̒$)=WD_F  TX}**V`JK[d }+$Iʻ9>  Ve*5UIu %IR}u*ZDC  T\k~*V`JKe?RQD?  'I_~7K^{B) @tW~*V`JS^l s|Y$U;b} Pu^jgL3XUf*N.;(ٻ=MXd.ҙ㠶kvc[{_mN7$PVMd}5;}u}~'_$oq3S{\^/$ آ~'5W-,I2i+R=7   @7U1X%k~l V"5ߝ%I׽lq !ѹd<3XUf*ik  U3<,IF桿2  0c?~UB*Y3X4lu?,	  [U=D*&,IF+  âJcoPcJV%[> mZ~w$IY} `$3XUf*i)Ug  uUZ$I3^R} `tXe*5UIXS  MՆթx$IWE_q  2?UB*Y3X4OT  &{$I:  æ[wYe*5UIX߫Rw  mUZ;$I=^+f ?pq]V2X:Uf*iXr  à|XKZ$ivL7D_i  B?>+B*Y3X4uB#  &{whI4u/_} `H5ﳒ*5UIZ)UUc  &ߣ%Ip:C)  C<;i%U3X%krݍяQ  Sc|{$I^k0  ~&2XUf*i|o,1
  Sҽlq=Z$GN  0:~)N+Md
5d`U0<яQ  ~75w]Z$v32 k{4*5UI^au  |X[]Z$f̓~)UMW  XU<cDPcJV%{k~ u?,.-IH庛*  mg
5d`UҰ:#яR  J~}Z$VU+o)  ٟJ/d
5d`Uз`  Mx2KSK}ڟD_O  7o2XUf*i)  lؼ;$Iy/l P>}Ve
5d`U(>?E?N `uԒ$)򱛣$  ުw\B*Y3X4
H׊~ Sw߫%IRL  0B6OWe
5d`UҨԿG*  lr}$Is[/D_C  %e?K^~ϕjB*Y3X4*\#  {Ϳ߫%I<);W  FH{V`JK*  _&IR&KJճF>  1+J/`jVɚQ\{]c  jmL̓~$INk  #ߊJ?*5UITX i+%5~$ISo  ӘFwd
5d`U(\Oc  fDcג$iߢ  =w`jVɚQ\g  fDτ߯%I:S*{W  FT/y`jVɚQ{G+  ̌^+5W[$M&Ugo  Ao	J/*5UIVwF?Z `Ɣ?A*3-Ibk't  -^iB*Y3X4   (~Z[$mg;ˢ  u}-e
5d`U(ֽ+  ̨΅_
gK)66/n91 @Z'^WRPcJV%b͕~ ̪:wmI4W}   v*~*5UIZG,  ̨)5yG][$mٟ:  J[`jVɚQ{G,  ̸R5mIZ_ݔ^ Lt.RXjPcJV%jͣ? YѿXC[$iD_  H_K[`jVɚml~}41  b(~$I+IUk  }$,m3U1X%kFF?f `ִl[$=_lT=p  V~*5UI\ߌ~ S߻%Iʽ‟OSF  P~*5UI#T=x  fMU<5-IRu7F_	  QwK`jVɚQwQяZ  UO[[Zk꯾,*  @};N,M&U1X%kF	~ +]5$IwN{}   c/&*5UI#Nj> Y׿XC\Qo|Կ 7&*5UI9Ի-  ̉ު#ߒ$tvHO> \4V`JʡI~ \;$I#;V  RʥciB*Y3XE_я\  Uڧi=\QzR)  Z|(,M6U1X%krɯ_  ^;$DvLN> `B0qG'K`jVɚ\jGя\  ["wwqISoF  2U=YJPcJV%eӢR4  0<qISs  i4V`JʩޝgD?v `Ub$ICբRq  +T2XUf*)ڧ*  !gNŗ1N.I0T_}Y  /_}i}YrPcJV%TxG/  (T,+^.I W,ym*^}l \wwfiB*Y3X[Ί~ @R5rI7ۣk  آbҔ3XUf*)ڧi  BkMž{%I+IƵ4  lQfi2XUf*)햪sя_  e*IOjT5> `.
;Kە*5UI9ֻ/  3Z$gR넏)X mj]B*Y3Xc   hUs3?R} 6U>cve
5d`UR-|EZD? ` Jkl^\2} u?4-moPcJV%Z  00V%Iٴ`Ի  uGf
5d`URNx#  J5FU\  15wOK۝*5UIٶ`T5G? `nJ?_$i+9>j `z~*5UI9[udc  N8uIfqG,  liSK`jVɚk0  j<-wvI[ϦD  }X{ZVPcJV%eT=h  R<vI;KS  ]g߭f
5d`URu=8Q  z<߆%IJŒצE  0m3>~*5UI<ף  0Ъ<$MJՆO  ~7K^~ǖ*5UI76/U<8 i~7.IVS[D  0#]~ǖf$U1X%k3{1  g$I/i  FF#*5UIWŽ;q  áR;$I?XT6 USqχ߷`jVɚ$=_Խяd  ݫؼ{$)Z'|,U"  ̸߷`jVɚ$=_Eяd  *[;%I`_NU} ni2XUf*I<яd  :/L=|*_} T4cB*Y3XT>~[c  {P}^4h{" Y_su[V`JO|F? `(Uפ桿~$h_W%>  `u?Lf
5d`U~R>|  vڛR	KF抷򱛣9  UeoK3*5UIW>G3  M^4Ks>R>  `2..tPcJV%^;3  C{C$i8+.Vq  ssҌg
5d`U6  rbj~Ǘ$WS(US  ̽{ɥ`jVɚ$K  0kE4^z7}t @˥Y`jVɚ$Yx Q=hj|=_4NTmZ}d @9K*5UIziž{-  0:z_%I_U ){8Ҭd
5d`U^F? `TU^jKkz	  BҬe
5d`U^~7  #X;$)bS#  (*.ZPcJV%i-ѯ|  ,6I#-/I9KUc  K%K*5UIrkWD? `tکsٯy;S  oK*5UIr͕~L zRj,=/I햺W-KE7  04B*Y3XW>yw  F^\$ijǩڸ& -Rx4B*Y3X~T @Թ <2    IDATD*  0z~f=U1X%k/2q  }v*wI[{\2R}  h}lg
5d`U]eяk  J죩
$My}Ɵjc  tjf;U1X%kg5  䧪Rڃ}y䯦O  JU+Ҝd
5d`U]߫R6  rݍy/H~R󠷤ޝgD  0Z|(n/IPcJV%irF#  KSc|wIʹbWO<S}2  P6Mw|iN2XUf*Iu'  Uy$)wNG  17/UPcJV%i-1U=  Թd<5 I>퓩|?  aKs*5UI|~l  ?R>r}j+	4NT3q  #\W}_V`Jkяm  ^^{p* IRCWD? `du.?~iN3XUf*IS|G7  S։_ayR  0ڪ*~4U1X%k4:~t  [пT,;Anzyяp  BK9`jVɚ$M  LUsC`IZ~xc9  0wҜg
5d`U^+  6ߚZF$Z~3W_ tXG;4B*Y3X>sяo  `65WI
ml^j_sMc  ջw)"U1X%k4^R  &[%RcѮ4ge*$ 쵾[RDPcJV%i~Z#  ꙇR/FSHҬxԹRqM  I<Hj,!]A`jVɚ$m_>  SXW^8U  t//}A
`jVɚ$mgcSяq  `|75w$MJJی~  /b),U1X%ku/]  *Sob1$iJO>11  W)2U1X%km6  0zԽvE*|}$mbWwg6~r  >RhPcJV%iz^  If^sP*.}C^\sRROJ  `zT,ym*5UI^3>(  fCHkb[>퓩w  v~j{*5UIfvMU9  0Ks{R*iNkԽzy  4)<U1X%k4?<q  ̶~'n9qbD"iD[O~Mz  4UצƂ5V`Jk|_  +U+."i4jԻT7E?  Թd<}CV`JT>~k#  KU};pXW\|  0*!DPcJV%if\wяt   Hͩ}RcѮ&EiF?  YwiP2XUf*I3SϦkG? @Uc}^4G4 -!`pTڛS  iiP2XUf*I3WoD? Ak-'	OS_MkW'H  O]K`jVɚ$\?X  L5}_NU,fjG  {!'@e
5d`Ufڸ&  _	<].f!oOKS}я  `@x~*U1X%k4u/7  r}_Ƣa$Myy%U  eno-U1X%k4ߜRUE? !P6G1EHB_Z'~<VLզuя  `uwi2XUf*I3_яw  `TצKSෆHX{jԻĉq9  6uwi2XUf*I3_?~  C>X)6;G  0dz7^#dPcJV%iZkZD? aWSR/‟בFEuɻ  C9 f
5d`Ufުяx  `;}g4_Q)Z Q>~k4B*Y3XiA	  0ճ:B4K_ԻTm\  Qs&GV`Jߤ  UUu7%y{Scl^SK'lS
  \*3}HV`JG? TV+&{ߋٮuS%^C   3
7:U1X%k4{K^R~  4REW5ZjRw  x%i`3XUf*I[   kRcS?M?$MbR'H*(  |&i3XUf*I[D?  ^*SԽ:?j0ZkjԹSSR   }ͅV`JW>~[  `*LU+'~ͲXwFb>ө{!|tUJn  IڛRx+i3XUf*I_  jԻԹyԯ]߯4-15{gjqjRy.q  i^X4B*Y3XٯwO  rݍ#RJC95Υy䯥9kE  0&ދ=LV`J[ud#  `mʵNl%ZGp_ڋ~h<⽩W]gG  `NW_^&KPcJV%injG>  ܨTmx0:+u/]ڧqj+'4Kc>4+ONT  &MPcJV%i*>  ??dwRIs?Z_T,{cZMR`jԽ|Iqz*ݔj   N)]NV`Jܵh   xcz7:Sj/RbScl~;6s*|}j>=rݍF   SԹdA4LB*Y3X9lѮjn~  n3Oޓ]z<QkwbÊ~~?w븏No}^q@|BwA*yW   A)DjPcJV%inQ  YRRXu5RON[}b:y{&~ŵ8XY5bWbm|:OO}gS/KRGmʵץ{'m@
  ~ZFi2XUf*Is[s>)UU  w'ڴ.U|RƟL_?Ɠ/T   LSo.U1X%k4W_      \gj(]PcJV%ik?      0s?QV`JR@;'       `T,#;4B*Y3XW}       н+`jVɚ$T|_T      `k~*94B*Y3X};       wי`jVɚ$:?F      VpwEi3XUf*I-!U<}       /|oҰg
5d`Ub\ (       ^FτO>U1X%k[qSw      EƓpg
5d`Uufq       HE`jVɚ$:      cn*1;4B*Y3X|#      H)n=)42B*Y3X}磏       \d
5d`UEa       Y?tyCi2XUf*ISe      dn(TPcJV%ip*S*{G      d|PV`J`ջ      >o¿J#*5UIZF       ٩OƢ]ÿJ#*5UIu7F      ÿJ#*5UIgu       StHf
5d`UHsOD      G#F5U1X%k4u//      WUyÿJ#*5UI̊ߐR}L      H{~Ai3XUf*I[S	      i>]PV`J<ף	      Y士¿	J#*5UIG}T      Hj`jVɚ$v3<      S>uoj(|PcJV%i)U>}\      Hi2XUf*I_      FiP"U1X%k4BJV      #P&U1X%k4n91      W57bW`jVɚ$G}d      ^o?)V`J_su      ëJҽ¿IYe
5d`Ui}l      ^h7?)V`J`Tm\}t      ){Xo~RnB*Y3Xs?D      0tzO2U1X%k4\      GU!'e*5UIW/>>      `h8=mPcJV%i*R}      ૪<=l3XUf*IYS      x{'e*5UIΚG7     <3XUf*I[      ӓ`jVɚ$o~/     :7¿Ig
5d`Uy\WQ      \{m<ISVɚ$w?}      i¿I2XfJV%i[K{"8     Q>*;3XUf*I_{}      h{$(U1X%k4K^sG
      +ݘc¿IQPcJV%i4^/G
      k}wÿIzQPcJV%i4*R}      @*`PcJV%it|B      aZ'N7;I?*5UI+I*      s7uUi3XUf*IU      sC:I/*5UIGZ      s\{]w:I[`jVɚ$^>^      `δNX7:I[`jVɚ$^>}      (^}NV2XUf*I#ؼT>qG      uoV`Jh_D1      0_]N62XUf*I#Nzc      fMV`J9E3      0+]=N$2XUf*I#]R      fVUV`Jh׹      Q;'iB*Y3Xo*~}      (yI\PcJV%i^(     ѻo*5UI%MU{S      Ao	&i
B*Y3X<^#      jew7IS`jVɚ$Qu)u      l^+&iB*Y3X|^X      ۥ{W¿IڎV`JR>_Ŕ      j=6{`jVɚ$U㣏      ;;`jVɚ$U෦T      jӺX[w6Iۙ*5UIʯm'G?      0)s`jVɚ$WsR#      |Xc5I`jVɚ$YӢ       ت)]M43XUf*Iy<~e     U>]M43XUf*Iֻ      q	&i2XUf*I<~e     ӿ[$PPcJV%)zw}     OTejhf(U1X%kw~e     Aһ$`PcJV%IΊ>       n3_gf0U1X%kJ$      2׽tQ3I3*5UIw}$     >Lg
5d`U+      ioff!U1X%k׿c	     Oޝv^&i2XUf*IqCޑRUFM      du+4KB*Y3X$EM      dodf1U1X%k<)	     Tejodf1U1X%kwI      ocf9U1X%ky/U      fWeo6&i3XUf*Izz7}D     0:ob U1X%kʿN߉>      AƵhob U1X%k-[2     `Ooa(U1X%k-U
     _sMj&i2XUf*IZ>      U+Lf
5d`U{iDW      ލǆ4B*Y3X$mK+      \ޔ_Kg
5d`U^G      Cs?*5UId\OG      Ch-V`J&բRi]     j߻$d
5d`U4:c     !߹$f
5d`U4wJD]      ~'5WKR\PcJV%IS}Ƨ.      DÿoI
`jVɚ$iJOcD_      S߷$f
5d`U4Z'}"     `gߵ$@PcJV%ISˣ0      TRcl^7-I*5UI:G      a6{`jVɚ$i{{~1     ^";`jVɚ$i{k'}     0 TX(U1X%kԻ     >ÿ_IV`JSqR      Gcÿ_IV`J[3      "<]߭$`PcJV%Iӭj>      ҽzy7+I*5UILԹ4      TK~
^%i@3XUf*IwNGk      ̱̳    IDATJf
5d`U4SOT     Q7*I*5UIۻ& uU[mcG;NjNi-O$]E@"
Q 	KH]:Y>:/|>?ÓW͊W      ;CߜF%s
``Ufj     `'h]16%i r
``U;/^o      ̠wGI4 9XgpHs*Iuc(+     8oR$ViV%I3Q%+     ޗߢ$PV2JfbK?      ?š?%ir
``U4S.5     @5/7(I/]W2JfE{W      =P[Q%i*=8Xe9X$dͯ~,{     0]Fԏ~sۓX	}*#yߥ/&IpWm     `Z-I`V#UFZM_L~{"*{     0u+6w7'IY}$i|     dUhO[~ܯfO2+Vi+$i+6]d=      &}w&I]we2+Vi/&Ih!k     	6boLɿ=Π8XeY$IQq     @kKS8`Zqtb$N?      ؁m_MW45dH`II4B͊      PGJ7WX`־$I'+f@      y'ߓ$OkW2:L_Lѫs+     g)$IpվqIh`V>|[b$^!{     𔪹1EMG4\un?'{A_qHn\$IYk~k     4WGrUF[YI4-ݕ	     F2fCf8+Vy_$IY     F[Qn$i8OdO9+Vy#ސ$I[yץ٫     `dEb#UF^q{$ite;{     k66;HpV?~1}*#񕏥/(Ih׾u     0ZE)H8ٓUF^$iOAT^      #3oD֥uw27$Ij     0ج!I]c]/(I6      fP~1]HWqqă`W>zg$iscQW#     j^oBF#Uh7b _;2{3     rQs i'4w=8X-|u$D1o6^      CjnקIKޞ=/9XJ<٫     `4/tѩyg=KVa%/*I~ج(     0ʻ.4R]=/9Xhtj$Տ"     Zx2_#i*Y=/9X7I_T$=+     `57IW5p`6k1>6;}YIy/j[     ` unR{ѫ8UxJKgǲW$     6bKz$^3>=o9X4$I[si     U7_o<FgOA[V)/,IVq#U	     0#it+:{Br
Oܳ<}aIZ5{U     D秿H>7]dB[V)x풿$IZsw      P~u$lޛ=	9X)#}qI?%     @_j}HZ}.{B_s
OӼd%Iu	     wEmUURn|-{B_s
OӾ%I*yYTGW&     @ߨ88FYQeDkVi//IvPOgL     <7T?Ux?$Inc	     3n$DG"=,{$iGՏ}kD6     Tbދm$iscUx$IH^      9I\`-s	>,U}}풾$Iasw٫     `k]9'FyΟdEVa+쓾$IHQuW'     NS.js!*IS/fFVa+ZW/H_d$MKW'     NQ56Dqg$'͎j*lEe&I+8k'     kIzzSߟ=a`8X-|UB$i5     `Fun=#MF]ߏ0064.tB$i2un?7{}     ̈D1oIzFsvj	*lCeKMIT,|UT+     :ͨ/yG[$=~'{B@q
Rvv+$IA     zuߥHtJ`qL_l$MYQ޻<{     Dy-o0>71	*lGgMIV?"E     jÚ(4EVK9{Lq
FK_p$M֥ޢ      SD}\$i[unJ`vyɾNI76;^      SZ{$m␗Et٣U؁rKNT?-F*     򾫶qIV>=*a 9X	(E'ITj-/{     LX(2Eج>zG`&uݑN46;+W)     UhIN>=-a`9X	K_x$M1{Et     `Z5]EvT{gfKXVa~"}I4Z-{     lSyץ[7I^D	*LPo/=Iܜ]M     T␗翧Hj-?{d@s
PW$iՏ;leS     lG}Q$i}{`$=2I4WN     ~uN?Լ/G&<0	UcC=}J4݇n^      Qqqf忟HҎu+&<0I>%IFcidT     `UOłHDj	C*LRwÃ1>PZJ     FUޕ^"Iѷ''0,}J4+     A&D&XdMVa
ʇo>X$M7F^     7IL]04O(Itk-LJ     FDE秿HҤjUeOVa:L_$MYQ޻<{     C򯿥H$*W]=>a8Xi[QV,z͖      fDՍ&"Iq'0W/GIzQkV    !պb,-D&[y5UL4$uVV    !S޹4jcA$i25p`|E)It+2
     F`7ITcЭ#U,%IA>V    aiDw}Hdk^U10$IZ    <<$i.{r
=ҸKS^T>qOj     T#;$i*W,0BtEmދ$I~#vz     Lʨ5C&[s
=Ժ)IRj]97{     z(}E$MK(=Ke;oN_$9Fw     "Kޞ!ISqG(c{/QIzUq/Dܘ^    ~VU<4zATWeOR	Vae*IRj^٫     ckKϐ־1
#*̀ѻb|nU^Yy~z     Py%-CRFtQ
#*̐Uҗ$IXgTdW     TO(C^!ISjn]2{Hq
3lGqU8w#n     @qoK־Q
#*̠r1>g+IRj_sXz     UhwIjleOS9Va5/%+IRϚkt\^    DoK$MEw٣FUifG%Jԣ#Usc     tn?7jc+$i;"{r
;Ag1~vI<O+     u~7j BZߍFUI}.}J:^    ڴ6EIV6==Na9XlGq⯥/_Iz/wdoX     `Q-ieOSyVa'*'j(	Kԣǽ-^     Lh7	INK͞U7%IeK?^    ҾIN@p
	gq2$|ƝK+     c!IS8QmX=N8XU}}.})K۴6{     =]ݨ7Irsvex|;1>yYoEt     LSQ,|eۃ$M),V!Q3җ$IuXz     jn{9Htj
yߦ/iIz(<{     SD7H4|tZD*d+Q?Z^U6>a    Ij-wINa)Vt7=~.}iKԫ}`     4yG[)VOK_ޒ$7%{     P޹4jsvI[)7g(,{;`HsbYK\^46+;.^     vt׭b
47.8X>Ӻ%.IR*yyT^     VTbk$i:8 {`Psgҗ$I~G
     <M%oOG_DTUH&*n7g.IRj-/{     ?VK?<"
LUW"-}KԓfEy
     TՖHv IӨqƇ":
LUcG8z%/IR/*U     FZʹo408X>HG%}Kԋ.+     ͟O+8eV-{S`@wQ;K_^<٫     FNyUQ[;$MɿUsS8*vӗ$I󝓲W+     #G1Ij>Usc8*򱻣U$Mύr
     C`.m@XG0`ʇoڡ?1 It+}Tc٫     VU_c%M@ZGq
U@wFmk?
$In/ND^     0|h Ij&fOS>:oJ8$i[Z    -?Nֺ"*{=`Xw#QwG$IjlV? {    h-L4kfQ`8X׭?I I4*$OܛV    `൮$M_eQ`9X!mG I4wDV    ``un:9~IJafQ`9XaQvyߦ@H4gaDUeoU     8GmήKd6N`Lk?`VǄ$IS     JwQ;KdkZcIjZ
I(\N    ` t /}_&جh-?fQ`'r
C\sc}e$IS{ta:    VmXO]_&Sqˢ
$p
C({$IS~[jn^     ЗGMKdΨߗ=B$Vaص_pH4g}?     R57n9_&SOE#H`FD3b|H4WF    8KD+}9{z}*r-Q;?D$ITc5
     v4po4'zt7{z}*nDԿI&S1}k     Th%iB5ZW΍#VaUU;2>/E	V?QgoQ     HѺT?fnUa#?H4} leP     ةZW$Ѻd߈v={l}*v3c0+E	     Q^qTo󒴣ǽ-kn@s
lѹʨ-zm$I}	     3sQǇ$qL_I&*U}}4.tgH˳W'     ̘k&/Iۨq VѵQW$I۫Xgt+{m    @ϕ?po-^VUѹq
l]ַَ񹻥HGe_    a_Olg/I?ݢ1{T*]cwG#I6jN    i+W/L]]̏D~UU`Ǫ*|:HZ     Q=7wIzzdH`H8X&UDۇF G$jxB    )>r[,vIqcG z*0i'WG㜏x| I>7{gI     cwFKω_M'Gt;BV)+W_IMX$+     &ĽQ,zMT?ꗢs#ehU`:,w<I∟j     UmXoH]]hW?ѹ*S8Xz{S$OxWD    `k8鿧KU*[U^Œw\IFƙ     jQ?G4͎ƙG!03ۍʯEpIFe    'MkM鿟KC^y_w`q7G?]?$IWߏ^     Um]ԏ}kF诩zFD=p
4?EmK?$IӜ]5    jF_\W,zMGOq
tUcCVqoKP$FżݣЭ+    TE+4_<{.c`u=N47i    OD};#4|Υf@h֢}Q?e:IV_     #*to㒆bH*wַx&I}?Q     C*!7qI쨟h-?{G0-V]V,W  %IDATAI<U7{    0ڣQ?~%fŢDk۾/5(;Z>4f5#Q4ص헽     cޖi.Q?<Sѹ[= fU`0ܳ<{DJ    !Q9VfEqoFܔ= v*P(+Z8j_)IfGgyk    W?c%woI}Qq+ߎ%FSǩ Vaݸ6:K9JE    @e_[i.QQ?<u?Fc>r{Tз#UWFk1_Eq{v?d%I}Q`[     4U+D4]Ѽol-s뗢}ߣ=Q5̞: *0*OEOEGmb|lv$iV6>        ;    IENDB`PNG

   IHDR         Rl   	pHYs    {Rk  IDATxwUi`D88#XĖF^,(uT!tanAPRd~Y\`}}=￻+000000000y o1*mfk3H*2.}k{Qo
кJn@1}Yک:%Ylgmp+-|2in[
n'iCZ%w}wD3}Lۏ׀oT;LDp7΄dz$caـ?|>ʬ$7bǌ0bdޜ~>X<EwDQp!ez왈`{=ٿIPxN<;۰cĄ9`3N9/4vlaW'{7<b D#p,E}z ǖ?9(ٳ??HCOc,|܆k	_J'rl;&'aWn~&xVGn̚L?p6Lw&B'}u:m)b75<EO#9ZP,v rHvi@ 9l83*yO`/q|}?h[3''`/ NE!=WF|/X#"c y<0ŵlV`NSKbm@}x;Vps4Fq[u`aԐ~0cߠkAq(gJFQk.g,6g<NEx6aHn,S G Ȫ1޴ɽ^D}_:KCp7sm6	 8+Fc ks'?Y.ѺjiY=D@+1ޙcC:E KpVI(_%Y}₷wc֪H @s?P(um
@vm`w9o7E _|07'mB~VpOkv`1u2`ʊ$9GյRCy0X(9h}t`N;pzPjsaA '?*E%R[cD
?zXeu}8"Q4!?¢Vd/lgTf(׏b _ EmЃrkU(Ms"VƸ4,F r^@UzL:ŎH
y-#Y92 j`fJNy~MRV*aI}F6C;ւxll 5% dBV3n<Sؿ)I Fv'f{9Kk }@	ʿD`p֌C Kc ;ւ.`	u @D:Dʂ
.6`	@l`	u@4Ru%2@	y; ,T:W9
`2j`Xh	P"
]
YB!+@XB= ,41 Ba %̷D K(dBU4z XBpK%Ž
\n"z XB ere; ,ЉJ`	8vXB 5%Ե)Px. B@	gу rܘ@Kc $у
G/P%15ֹ%"!5PC<K{ə`	EDSY9=,NTjQa@B+qeO ֬ 5~%0QakP rޜv0XBHp?}=,dPOX
1"v5qjTKa )?(n,CKc jr^+"VJ ;(,5уj 8JB
K(b ͳ}ۧm +Va	5`#PÜ8z`XB^pj@P1z`XBVC}z6GKa k@..b@{/X(#H6pm|ఄ"ŲvV )$$4DKa a@}b	5`N+P*y=@,@g vj{\
9ȝˀ1N	]pP ւ.@n*"+`N <p`A̼}p`!bb%d7ւ` PBx2"$0F]rVbvhR*=)ȪK;˜UYi׾3KO=QHtS6ٷ/pp:`PK:Iq|ޞJ4?ϸCvBEZN<quh'#6#F${+$8^{{&+"@.m԰닟xQ< ʠTI&DJ>#!ݸg3*^k R$rv%s#Wn
[@u:PX^@O԰d:~4 R75-5,M*st8rxr)\"d dyASEO0*nfo }@al>㧋"nRH9=i3)#>h@.S8#PBh|1H*-*Y5 =q3%oF՚=TP]ώw1PY;>Z.'p-=&T澌	Ĺsc]'q]e-H[)DDs\>lOyb k@q@dNUΆ)4>W@T6_EB9۱aazV@u{<aW'v-e|(!Y3KRFvQr\j=u57u"!!@Ґu6#?#[,[YwmPt}^Z87<0؉,QMmV ʶCq!0hv^:duc1g<lв'|\Z1cLu {8!ƶۉA;'ofnn )oj%Ny~n69k1zJ#7O0K89vr"Ay~UMpG0AW:Wkଟ֔dؿ0r(J"4hЇ\):&#3hr7ix>/Q raRE~e*Q g6d5ra p_/=Q?tO.1a;S`)G9ϽH x
l {|>m[@5\q0ߋ]9+1rlHM]231C	vKTGk1S?DS鄝UG	&(n^u;`_8d;uiL<=fcID/i-zW(GxS{M0Q5e|䯒_k?&;zY#Emfa'w<X0Ƶ(jnnum
ډű@@zX5i ЮǀQInZ9 5qڠ`'mva^#|u Ф?$pnS}䵫J<5J ;CZ߳Z9Rsڀ+ #&$5TڼVT0K;m:z$D}k;|8	zA(&m)y-0ѐV^ps|î.S3000000000P^@¦l    IENDB`PNG

   IHDR         =2   	pHYs    {Rk  IDATxwChb<Gh$FRLxcI1k5{tw]:RP*YY@\,ҋ]da~ܜ;Hp~̻s|c0L:a````````:ܒ{9[AUxS }ZDW+iz%XEm"K/tkoNMz32kBT!XJ}\@XnBKB*y2|1p\H$&ylHB_Ix^Jg&2SiɅˇ%4CsBrOHNW}mj"vFc8wB;zUxDcB;Mm!. >#ߚT)}{_ qj0i&ڻg\V [T܋D;koKX`4;{eoPלI|4gAX~?/~,Z2*[`\f3~.E&;w,TnSrHu8+8Tv-1azcvt-mz\h )	j(3v3tے4ąϏ-4N+d>:ΐ_|9A'=w,So<3Snz	nyd9^
Ng!=Jj>S(e9#޺2`@7LoNBk'AV xx%88׻£֝	s Rr.@g;-
Nv [pS[hqn4Q(vK-dKlx ^ў5`*9`nF@Bϋ!\FMDbSY#j6QQhaO0qB*DlpS	BG$>JPY/Dewܽ$-ڷ$bOoS~unc*#[8B|_#&)f** X3/3:Z6Jh\bcQ  ڂ_pq}S	2u-:<7^%Έ[U,Q_VwWRB^*_נlD{B|vdis7 nA]WCt$F4_tN4q'>P1ZS:ޠ49x<&>")|LyoJxVgد{d^ܦORd"8B-#B?+y9BqņS!/8G!7IgE
.8G!46.8G!td 莲SE9yW7G$$Ѡ;F[jDB ݱz\D^pPD@wW#!;jò/sy9BKAw#{"٢.8G!4O]pPDR#?eEz\I]tAEz1{tWS/;ɋj{NuKhک;E5vF`u8A/4n{fB.G7&/<G( 4޺t#莿y9Bq	7"/<G!?WB]xPChw=`V篒#6NG&6R[Sx)J]|P@hQQ56aNnN]|PChl`V Gm`[и9^ pBΥ;)j,$ PChq00FB&&|8^h97:pAw#/+TRaT%/6`4Jhw`vQz^	`kzS9M >#n*jh>K4Zh|0aΨߐGG6?D>A/4.ѝpk)`pB+Gx)H6#ڛ$=JzmY/G;Awͳ#j;cۈ{fPh|choi
 A|ꄡ_35>y{S|8D{ QZY9ynX;e!>Aݫ3+|0p<rt|p=@mZ6i' UК\b~켷|8&6,kƅ֌p޼\yvE]{IT2B{3fsN٘3PrQ},BϏ	D`3vyAGE9Bڷ &\^fޡ˧#;>t /03/yL /q#y2yޛNi6I%@geo펻 
t6Jn2?+VD@gY/ V%xLh|jdV/Xϒ+u|-Ŀ)&q Ȅ^&JcLhLU2Jk%X5t&޿Ο51)R689@:nN/42P^sz9t~?;ЦL?;Ar9	!7ȅS>ݠ_V;Aw~?TChnG0	?KZx>u ITh{$	]Ib
-^:/- ?謐0;,;P[iP qݬ߁i9M=i
ZCg-A@*ZB2%wm*UBC6EM^h\aG5_:#$pB4Bܷ@/sAk7LӰ{^иؔ#
vs|Ѯ#BUGu☖䷒}4L=Px[w`{,Lh-۷mh`,qܠӍ
]uXW"r]Z뇭¬aXǦ2Bӫ s[o+`[r>LT	w=zm5Jp3N~H!q7X3HgOCZטmA2*4'0_F43-t6\2$pe'TxMȌK_o_ڠg4`TO >Mg9	]TIQzK5dT!p~Bˣtfm
ZK%CL|hf4,޿! ?N4B\'C;KQaգG툙,K5xF]⿁GF*'r<=ŏ%7+oAOR1xdaêU [GY@|N$7 qFI~}4t'%+_>aF%z c'LHk@ۚ0)4/MF%ׄ1`dtD{7׼VЈ;irw\l泌; wڊ;NxFHI)MrJ!7QEl}/?B#e1"n㙨9'pfEr.x <G	+[XEmp~K/TfrFe`iOBi\U
0B3FB3FB3FB3FB3FB3FB3FB3FB3FB3FB3`|ی    IENDB`PNG

   IHDR    
   y[   	pHYs    {Rk    IDATxϫsk=4%KvQ RXq1KBhbIb
!E~䎵dxk{6y    u۸     6    m             @@h           B    6    m             @@h           B    6    m             @@h           B    6    m             @@h           B    6    m             @@h           B    6    m             @@h           B    6    m             @@h           B    6    m             @@h           B    6    m             @@h           B    6    m             @@h           B    6    m             @@h           B    6    m             @@h           B    6    m             @@h           B    6    m             @@h           B    6    m             @@h           B    6    m             @@h           B    6    m             @@h           B    6    m             @@h           B    6    m             @@h           B    6    m             @@h           B    6    m             @@h           B    6    m             @@h           B    6    m             @@h           B    6    m             @@h           B    6    m             @@h           B    6    m             @@h           B    6    m             @@h           B    6    m             @@h           B    6    m             @@h           B    6    m             @@h           B    6    m             @@h           B    6    m             @@h           B    6    m             @@h           B    6    m             @@h           B    6    m             @@h           B    6    m             @@h           B    6    m             @@h           B    6    m             @@h           B    6    m             @@h           B    6    m             @@h           B    6    m             @@h           B    6    m             @@h           B    6    m             @@h           B    6    m             @@h           B    6    m             @@h           B    6    m             @@h           B    6    m             @@h           B    6    m             @@h           B    6    m             @@h           B    6    m             @@h           B    6    m             @@h           B    6    m             @@h           B    6    m             @@h           B    6    m             @@h           B    6    m             @@h           B    6    m             @@h           B    6    m             @@h           B    6    m             @@h           B    6    m             @@h           B    6    m             @@h           B    6    m             @@h           B    6    m             @@h           B    6    m             @@h           B    6    m             @@h           B    6    m             @@h           B    6    m             @@h           B    6    m             @@h           B    6    m             @@h           B    6    m             @@h           B    6    m             @@h           B    6    m             @@h           B    6    m             @@h           B    6    m             @@h           B    6    m             @@h           B    6    m             @@h           B    6    m             @@h           B    6    m             @@h           B    6    m             @@h           B    6    m             @@h           B    6    m             @@h           B    6    m             @@h           B    6    m             @@h           B    6    m             @@h           B    6    m             @@h           B    6    m             @@h           B    6    m             @@h           B    6    m             @@h           B    6    m             @@h           B    6    m             @@h           B    6    m             @@h           B    6    m             @@h           B    6    m             @@h           B    6    m             @@h           B    6    m             @@h           B    6    m             @@h           B    6    m             @@h           B    6    m             @@h           B    6    m             @@h           B    6    m             @@h           B    6    m             @@h           B    -/ܣccvĘ=amc,x  82i_cwy3gOٻc-eWm5mwÃ~1;sj+` #œӛٿMc{cc92z˱scj;?1S   Gwcufyl_Zx1˱V7-ŇN`驟  X	ߌwfGr<|kmrmʷtuGdccW~$  `,82pr,>yr,~?Vj{}cycvػ0K)I**EQP >
$Q 8ٴM={ $i$>kN,[ffϹyuN|ٙD3$Ix3ICZRJ/ڊөyŞMh_K[F=$Iβ̮}~Q[\%mExj-za_Xݶ/H΋~H$I#Q+Rh{ 0wIj\ߩW*6V`N)E󣋢&$IHչr6F>=T5mFj^kʶ{q4XeFS$IsGD֩y~y/w/~U$I$)i |_I;J.ڊڑwym*Vv$I4~G z~R#iPE[Q5u7'_T<w$Ij]]]^MZuazWl@S跌$I<Kw`jG/O?Yn8OQ	NHcEe$I$LS>~w m7EǴ֏?ZI$I_G(E/Vmm~~5#xȷ$IԪa+.Eob=hlі0?GozH$IeeTXuju-ڊ"5.)qT<rc*$IréX,9xmz/DӔT<|}_&$Ibg.G1i?52TGKS~E$I$k<FL}'Rj7kV+R~;_\|$I:w;07oY>狶b#)_Tْ^5$I$`jT4VU{V<P+x{|[H$I|5U;f^E[="´-x^un$IL#vYE[Q{2v6ԾeI/$Iv=yO}HT?R+hk)?/LļԾ9+H$I|y SW`V~_,e@$IR*W(;"nU={8?_$s$ITъIٶ/ c3Ijv`.Z4/I$ijߺ{񎾫 c}/*uumI燿80]>$I֥;WTԟE[?^t'?ʷݘ7$Iq?[g.ڊ"Վx_5ݩoG$I׮
 c}޾廅0]}ߚʍ~H$IgI?~gS瑛cmGo\6*$I$M})|JUOo	wTgoI$I[R61/^M]5.ȷq*eoI$Ij^#eRh<rSa4lȂSgƐ$ITqq/C~VB:E[N97$I$LC{hk]sP$LG3~3H$I*/;"ESQ{7tvze$lHcǻ?-I$Is]Sp{0ޛE[㜯^I$IPk cXy.ڊ?>~S$IfSO߁.K?$I$/vBX4ucnmwlfQ.۾ ^5G$I$v:N^!9YOxw|ǙsqFJ$IҌyV&6o:Oܵqo$    IDATкj߹<#%I$i5/Z~7zqmܢm@Kܯ(I$I,R[~Gz*_U*jOnV+R6{I$I TV|7ߕj^m'H$I U,.e~gzfrbHoaMίNh$I׾{0S]<E[¿h)(I$I]ߟ+?=E[ѰG,$IH'Ch~Ѱ9_q(I$IsRo0ޢCÿXX]TqJ$IҜվeI}
qޢv¿X^o~L$I$UƩ~޶/HmExo<oT<vk?@I$IT7W؜kvm"kbԹ~$Iԓ&`_Y@K0E["aR<$I$<tȆLm7gVS¿HhʲǞ$I$I~T/]ANGy$Iө/߻9Ӿk_5/.c_ʧ8$I$/ˮM-_؜hOk_Վ`[yy9'I$I}u^w0 ͅھo]ˢ(RKÿ8FWʽ8I$IseE=x7MsmGo?$I̟Hί	cse];"b4M>?yI$IRHOļ{0QE[쯄QOGk$IZic4sm$b;<<$ITgجՏsmN-S>yI$IT,6e6cǊS_#ѷ< $IAj,辗ǊGnRg$I$Ve;06+3vcNb>$I$i +Wޓ^~of8ּ|/<$I$tkc3ֹ{xq¿_wiFY$I45X'&a;4O}VI$IR%*)_06mj|$aMK}NI$IRun>~t.ۥ/<FO$ITKX[ÿlI$I*YY*廼6nmPo=0mwFK$IT:w҆4z=;_ç}$I$E?~֫y7ױlÿK㸏FC$I4dBsw=`lϨv/󩬭>$I$i0Nm̽MRGE?$I45|<hg$I$Is_?ůc?Ţ9U;)u$I$u~EsgіX~Gy#I$I#Q:6LoF3$I42 0m̉q>c$I$ijtl}	66ZkSY[}H$IHV?#B`ˢ3IsE$IFrղo!,(+L$IuŞC`̢٫)$I$o'¨kZ1+7MŃWG%$IevjE]mJoD!$I5j"d#̢+$I4U)FFE3/>;$I$I}#&6fyףI$I#d#Ȣi+$ITʧO6ǯJ$IRj]K]GE<￢I$IL*کo'!!mlPm_IU>"$I$I3xo(E+!mMSg$I$i5%6֫yעI$IFTVܝR?XN~eT$I1!mSF,,$I$EE'&76֪yD$I9s)~߄lYS~1g I$IX;'dC̢ҹ/I$IA|VNȆEXMܗ$I$wv{B6,|ǭS==%I$IL~lY$I>ԹwPȆE]>=%I$I}?B6d,>|/I$Ic;RywRȆEuٮ]$IPܯI!"m#ﯧiEvI$IR@ecUw~u!a6&=DuI$IR`kpha?=%I$ITwTȆEۈʷq*W==%I$IPγ祖պ9.I$IGi]hA`I$I~\M)i
h5GoI$I 8V.8s[$I4lіwW*ʢm۽(<=%I$I\+de6BZW=%I$I^|&_~,FDm_Mӊג$I
Ծ{,dd6":w=%I$IU>~b,F@GhI$IRqF}hvwDgI$IR{-WEېk,I$IhCOļ-da6^ڊ,I$Ip>~",چXʽ$I$M>(Y
hRO݈ǒ$I!t{.d`6ڷ,Ò$I!|Eu!pmCv;S*9,I$I\}g6:]=%I$ICVm;/d̢mԏ+I$IҚ|5 h&7~$I$I̗|a|0Yi$I!yт/dʢmX,|~*z zJ$ILwzy=EېhY+I$IZ~l Y|V$IQ]O.?~Ac6͏$Iu~aE[;,$I$i4S/ߋ! m7{$I$E`9,*,)*I$I<,*u^#U$I4MMǐOI$Iv~M=`VQw$I$uk]k=`VA?3sT$Igkf)eȂYUP]G$I$Iϩːh|ǭSX=?%I$IzNy5XfYUL;ENI$IZm͐h?&I$I)%gȂXUH3S$Iּp"YXe*R$IVV|ߣa,*yDJI$IUoߣ!`V6OSDII$IU=m_hɟ$I$ͨ~,ļT<vk|$I$iF+I0?m~_FFI$IfUĿWCGmssQ$IYU<rc7֐E 3Q$I~{אE kzR<$ik7R}ݟvJjԺ|Լh~j8RuɯTWR/i۽;}ߚj=տG;:5n|%.]:w}Mjfѯ$ISאEۀw{]JE'zJ[NŊSO+g:-ڲ5֏grW(ߙRJjfg6&%^t
l_˴TM)[ytQh~jvrw2OCԾ{Ϣm MJY*zJ4Mo{ZW_n~|u<R#]I4?2EE j(IF}nmERؿL?c(5qwx"VY>*d=f6h&6גUtRo']w9~|1ZW]fJTYw:,,K4uZXvm7G>CG䧢6b}AEAn٤g'd=d6`:?0zIuZsũy)ɟh,DWvSFOٶ?~fB#m}ژ$in߲$5n_~N23/un? jI?'!2\I*T<ԼpO~627&<?+IRtŊ'>!/*$ij׻f8)HԾT6VE$px>!$iT*:se[|iM#7F$`?,DMsN4̕˵3-;"cԾ8Z*I_ej%lY7$[S;_/֕{ʣJF5}1о&I&oqTS˻ڲ2$ik)qs9d6 ȦN3zI4O7C,c%ICZܯw!?s=$IUH[?bL%Is^)YYsâ-XmsMTwwا>OK~A6G,yO<$UCK/ws Sщ~KH}m@gԹ;~.X]m^$IjVh/*gg$i+ԹT;-XNFc$I}ds-HF1IҠV.x{y3x~$iv)_7E[ǘ$i*Ծؔs
f:$iV5/? Hmjz$Xlļ<_=&C4URyϞE[֥;G/IҀT<|}	z!󣋢f
8/6E[MlaT>@yM&襉yݿecUNT:\vYYF-IR`eDj-"L~miU[͒E[oVؒ$ET}Q)g>/dRIzk]GcOP`IwTQ[S4'S+fKW~S>="E}	RIҀXgd`GϏU>չ㌔*<-+I:_~FA6m}ꔊN$DEUR;So_IҀUmgd3d֯/E(IRk߲$;,́*wڧJS'fȢOQ>q'֥ҒlJv/?`|, S*%IA/H.?k`L.S$@OXE>?g$ikR/lb^9èvṢtIRpŲ$feF&IV<zB仿>$W;gddc==$IsXʽR`FC"/I
}add=$IsQ':\pԾ) I|ƟG0am=V<rcH$md?L}=L6I'J%I#VYb??`|,zȯJRഔo3xVGIR+W=yK/	?{ ^~-zFIf[Y֥?E} R*)!I3seݟXn,&yKFh!jVVt5֭qgR*:B4:T,6>R?h2>|,z$_**I|TW`'m&IURӻ_?=)gW/韏kV<rSw3~*$)d}Aj^ Տpwzy Y}~$͠Νg|V0s>R=F$itvwR]R|_?  m=0(~AS#R`=6IAE;ݚ7g}_=hOK$UL͋懟ܘɊK$iv+J훎MͳjY@%QNjOg0K>H%icst|ǭg8dCm-<g$iCKf =8S>]V}֕{u[R61/|^C6,X?UScg{=|Cj8Smlsa6Z=V%II! $rղԹԼhAޔmhc;$i]K%?'>=}$iΚ|LQW@/]G8;"~iums(sW:8`}SHf^ezWE\g})zK֬h~F }AE4uWtRM}qI~#e7@)9Թ,IZLS)| ;,=$[佩}ˉyWS?H٢-$06',ʶ/H݈גj^8> /2"z4I&NγSmSy79R?[Zk
?S?㨤j0msu#]4GO> =l SOE)I\nMJͳꇼ'eqX(929`%I|0Z=$Urղ?5/ZG8;4|cǢm;mIRl^`Z&6IN[2u:7.Yy2~n
,@OG4M~C\gP!LţD/I\_=Wm*h훎>$i+D@T֟bXGk<Wmkb^*y$y7&44
U{YƆEFg$t[OGy Ts$UɟN}~j}gT?#)9mDFS݋`H>3ǚV}Gi\5 
Ӫ$)_'} cS'$i*T<Ծ<v;R`EƘ$ǎ$d~ Cg:'tuaOJ,6IRLk?<+cNƪԹԺrXMwC 6EƼxg})\Xqwm~ Clb^q'_?lv=y_ԓ*]jYj߲$5bm3m,fkb^*g$T'?02j+N+zI\p~zj^ Տpw:=hھo>$i*2e7hi^8=l<:\Z)Տ*@6 ,fMFfj{rF&sw4Uo\5uhDy42M~LFW뻟(sպz=W`|,f|3PFћ(q?GCi+yd窹dɢm_}&JhTv>'EOEi֕gRRʽRc6[S h	}NJHԾc?3@R%6@6,fuŞG$}eXwxiX]?OU<Ծ3Mk^>?(Y(&,=ڴo<:zDj+Osvzy{hm_R}JP׹)?"e~T{ڽMv>&0^m3T?[I2~WXB9<jCޓ،X;+G$u[zh|BT+W-KOW@xo7gN0,f}g$o'i2D    IDATE'yK>=9USseu窽"/ c=a6CŊiI>fqENZ,u4.߽#O>vAԮ|_ 3չ	<WhQ>%ihk]GOtHsmb6]j<l5Q9̗ΝgS9 Ha6z%IZW>6RTJŲkSʽRc6~0ļW h$qE;廽.|lJ,\GoNkK>jfwQ`6M-I7>JǪ֨|ԾeIj~J 06,ڦ~Gv;g<\wxi*ǣGV6N.{W@O/~e	 FE۴_oD ICW瞋;\k/utح=W4(,ڦiW$Is[[>&x;t+7g}1yOng e6M;xe4zB퀷`hC:-H?^g
 4XMǢ-}$Is\wj_{hs^g ,YM%IsV/+?wTVD]OK+N>j{s HĢm\$4T.-|C/,Rm}ySIقL  !ih]_)4T~slQs `̢m::\}$M{>qҰU6VsՖn_:@6 ,ڦ^FI>mr)Uيv*5o8*5Nl kg6J榲dʶo~7LU-KR/!I燿~ UEԿGHԺb}ˉi*W=u YYm:ߢϯu(1K<W+ @6D,6uaI0չu}䯀xxYmI6Ʃ>;,s;`2Hg~<l  (!I:2z9_> aѶ/$vۿ>Ƃb]ӚeUh[ASFƉ>IĿaj ΢m='}QIYm>ļԾuijx̳KߝϏ 1,֣uvSI|N   YXG戮TK1|  d}`Ѷ#7FO%  QaѶ.$;ν߉   aѶ.?}?<   uSI|>  >h[ɟJR+~(|  d}dѶFQ%ҵ;<|  d}dѶJRk,x,  Ȣm:]}GV)   #u|$iv>  >h[O,禍TZW?  ˢm-j{)*ItY  EZ;$U|ׅr  ,֢晴TU8  @m/7禍Tڷ>   mkѺj{$Uy_   Y vJ=U*[q  ,EZ^}OjV)q9  h[Tʕp  ,Eۚ&6IhGU%    amk**IyD  ȂXvۣ禍Tu  ȂX~G禍Tj%|  dA,|AN{$U[q  ,EZl}UJV<~{  Y}wUIdN	   Y 5t~xN]U*Y3   dѶ[朗T}6|  d,Pˣ朗TGi  Ynb"*I/q  8mw:*Iլ,Rp9  h[OcHf^3   fѶAJR%wY  ȂY~朗T7>  `miwUId+   Y0_3}WJ<3   fѶqт軪$Uɟ
   Y0մ;*I~g8  @̢m5JR%  h[M3朗Tů
   Y0|/*I,[  h[M軪$UL  Ej|y}U*W    m?61/}_U<zs  g6%%wUId{>  `6%uwUIdۿ>  `6ϯEU%?2|  dmJwDU%7|  dmJ?JR%k]s  E۔QJR%k]0|  dmJJR%k   )>}WJ<3    mS}6*Iq?p  l X8wUId%    h[ㅐ$ͬq>  `6uvwUId?>  `6uwUId>>  `6uwUId#>  `6}wUId8|  dmJ%wUId0|  dmJ3朗T~  E۔=GU%~w  E۔+朗Tjn  E۔k朗T,   ƺ,ڦˮJR%{3    mSJR%3    mSGnJR%p  l XM)%*I~{g8  @6 ,ڦ}WJV?3    mSoJR%   )?JR%   )Ŋ朗T}4|  dmJ軪$UƉ>  `6|軪$U)	    hR>`]U*Yχp  l XM)W-JR%k   )3DU%5/   )ex]U*Yg8  @6 ,ڦwUIdw    hRVDU%?|  dmJ/JR%k_   )>uTfWg8  @6 ,ڦO}WJֹ   )Ŋ朗T:]>  `6x軪$U⑛g8  @6 ,ڦ}WJV'|  dmJwUIdeD  E۔朗T:   )/JRe˶9  hҹ{$U|+8  @̢mJ禍Tj{r  ȂYMyV=U*[	   Y0)}OV?s   f6}{$Uƒq  ,E۔GS%59  hҾ[TIl͋q  ,E۔ES%;|  d,ڦ/*I}s   f6uTIl;   Y0͏JRe+*|  d,~B{$Ub]s   f6qg禍Tڊ9  h8TIner  ,E۔}MJY  hR?}wTIt+|  d,ڦ~wU*]r  ,E۔~oJRkY  hRwTIt+|  d,ڦ_}GJ׺|Y  h/**I}1   dcTTIl/   q,VZy=U*[s   Ej{$U=  @m)W(*Iխ,R6Y  h[MȍTIt?>   msIU*]   Yմo;9*IqGg9  @Ģm5kJRkY  h[M]晴TZ.   YվY  h[M۟JRsq,  ȂXqFQ%   Yԏx_U]3   Yx{U*_9  @m5oJRy  h[MK戮TGi<  XnbNU*]   gѶ"*IuɢY  h[C;$UGr  ,EJRsI,  Xs׹wTIt{g9  @m훎JRR6y  EZW}Eʗy  E:^Iy  EST*_c9  @gmk$U   YYvDO%> |  d}fѶ|ןJRyV<  ̢mMH,晴T?  ˢm-;$Uv=e9  @GmkQ<~{U*_k9  @Gmkѹ;SI|C?|  d}dѶ[NJRk,&|  d}dѶ}?׼hA<  Ȣmm/}?׾y  Omk8戮T:]>  >h[JR+~(|  d}dѶ}?W)gg:  @'mkSIj{9|  d}bѶ6$$i  0mP>hT*_   YXC$U{s  O,֡Ӣ戮T:w>  >h[UFO%   YXFT_t  ,֡q?D_O%i(wCL  maT   YXCm7FM%i(j3   uYEJe}?׺r  0{mQfEO%u<;|  d}`ѶŲ戮Tws  ,֣s戮Tvl>  h[G_O%i(3   1i8?   YYGc6wSIg})|  d=fѶoQTUt  ,֣/EM%i(}AL  z̢m}</JR+z ~  EO?}?W)_UL  zȢm:]}=vot  ,6}÷漣45|<|  d=dѶJPԺxaL  zȢm':n*ICQg:  @CmP?漣4>  hۀ|_JpԪlb  Eۆ4N3z*ICQ:  xoXMC軩$E>>  hDM%i(j  E4=4n*ICQg:  @#my.wSI:\>  hƒGM%i(*W=>  hJДo  E4_}/v:  @m11/V}7qu g-+CKDocĘ(iDc1x7&IΙ H@&UmQ:fv{92̙}ow}_~y3{@k,xͪ軩$e=g:  @1,膓漣Eo%|  m=.5n*IYT>rgL  (Ez軩$QYu  b,S}5ls  0G勒M>>  	h[_ӋRwSIʢ^u  ɲh {JRuZL  (&̢mW}7,*-|  fѶ}7|ytK:  @1Amw?D_M%):+~1|  dѶFTu  b,6@{}/l\s\  (&ȢmǢ漣Eէt  b,6漣E#wt  b,6c漣M |  bѶ_[}/ls  4-y_  PLE+RIʦu  bB,6P{VRIʦ񝗄u  bB,|軩$QH&s   9znTs   9\OT{;:  @1msC[{$eSs   9{RIʦ:  @1msURIʦ
   XQ}$n*IyTS݋:  @,hKM>  d6GëJR6N  Pl${$e=:  @,{EK%)F>  d6GdTl?>  d6W7Mi؋JR6w  05wmafUT{:  @,6pqRIʦ>  `Ѷm}/l^  Pl;毣勒M{	   FhlTiOŒ   Ym%^%Ii/0g;  Xm}GK%)zM\  (Ȣm#;*^*I48  P̑ERIʦS:  @1Gm{;勒M#wu  b,6RgJRVwxYl  (mcMoRJR6u  0,&`|eRIʦʏu  b,&`xRIʦu  b,&JR6z\  (maT?>  Pl 	h{$eUgׇv  bYMH~ ^*I;s  @m2{$e]:  @,&dp>RIʦ-gu  bYMFK%)C^>  `6!}/j  Pl 	i/2JR6u  Pl 	*5^*I48o  Pl 	pbTi  Pl 	4^*IT>vw\  (6EͼOH4;  P'	juT{	   zhE=}/l  `jXM莋勒MUǇu  b=YM}勒MCu  b=YMX}/|*g;  @,&D_K%)nl  (փEۤmqT   SϢmvTixs  Xm`{$exs  XmztTv>  a6YTsv  yX̓n?}'Xl  (E|^΃RIʦv  f6OF}/lsU\  (E<\[TiO-g;  @,IE_K%):9|  mtzCTwg;  @,MSRIʦv  gg6w~=^*I4  P<y4t{$Ӡ=g;  @,,QJRVͼ2z  ¢muVl}'  xmi)RIʦEv  uhg{JR6n=7|  ¢m:$^*ITvI  PE|{$eU{g;  @m{oDI%)zG+|  `6˶L,勒Mw   :X-7EK%)F7>  uh[ 돉JR6B  (C>3RIʪg2|  âmtwRIʪޱ>  aѶ _$i.ll  (E4Fw\>  aѶ@}/|Sx  P<EBA    IDATk$eUg   SX-~;N*IY;g;  @m%){$eg;  @mh{$e+:  @mhxaRIʧ ۾0|  Oh[?5Z*IYg;  @$=wRIʪʏv  Imi4FK%)W?  `Ѷ]}/l!|  Oh[`ë}/|*ǩl  PXxT   E+wRIʪ>  
 K_h}/l^ll  h1{$eSms  h1{$eU{Ǘv  E;$eU>  mb;$eU  o`4EK%)FWv  m1w]}/l*5s  ocxي{$eU{  @Y;$eUȿ  @YwRIʪ;v  ,ڢ,,A'^*I4  &h4RIʦH*7	  @,{$eUgׅv  Xmz_;$eUv  Xm:;$e=g;  j,HӛxTit  HMeltRIʧA'K6  @,ڂ.lTg;  j$`6N*IY;C  h5E[~*N*IY5|  ɢ-TvJR6*~  ,*`tW勒OA*}al  ZcV-JRVu  ǢYT'g;  j
h;$e#g;  j(#^*I4~  Ǣ"}/j  Ţ"g|:N*IY=Og;  jwRIʪot  @Q,ڪb4FK%)F? $m2{$eS{,7  @1,*dxRIʪ> VcXUHEI%)z'Sl  ZaV!.N*IY5  âJoRIʦU  HMaV1۾}/|*^Ul  Z`V1wJRVu  h5E[zWTTl  Z`V1]_}'^> V#XUPRIʦ@*v  =
pRTkg;  ʞE[;$eU︿  @+{m4y5g;  ʞE[4r}/luyl  Zٳh勒OA*}Ql  ZYhUD_K%)5|  YUTFI%)g|:|  YUTg6wRIʪg;  ʚE[U-<A'^*IT>rgl  R,*l|%RIʪ.
  @+[m6d;$eU憎  @+[m;o裸Uw	  @+[m'裸U/  @+[mU6(勒Ö́w   ȢF:=Z*IY-  heɢ.JRVW~,|  ,YU\K}'^  dVq^RYFK%)|;|  ,Y勒Oe<  `j,j`xRIʪGv  wRIʪۆv  wRIʪMgv  :XF{$eS}$ӛw   Ģ&w_}/  bVKJRVN  Ţ&z_;$eg;  ʊE[Mt>wRIʪ׆v  ^RIʧr˷  @ʅE[n9;Z*IY=  heâF_>N*IY58oYl  ZٰhJRVn=7|  lXH{WFI%)T,  `V3#wF_K%):+~1|  ,XpwRIʪ
  @+m5??裸U3= V,j{oEI%)  @+mu݋S勒U=~"~  ,jh|uwRIʪ> VY裸U  @,jw҇裸U5g;  Ъ=;$UY?> VYMSRIʪa? Tgm55;$eg;  Ъ5\kTj/0g;  Ъ5;$հ[w  U[m5Ǣ]5|  ڲh{裸U3>> VmYS裸UN  @,jTTlߟE  hՒE[uwRIʮΞ  @,j);$eUw  UKm57uTjxA  hՒE[>4N*IY5ѳ  hՒE[W~,N*IyUw  U;m5YMT{;;  Ъ[yJNTjp.  Hucі_JRV8|  ڱh=裸W^* |  bіޱJRvu|k|  Zbі[GG%)_  jŢ-e&N*IY5Z2|  ZhhwRIʪP*7	  @6,2?gqT;  ЪLty[}Tw?w  Umh/*JRV:$|  ڰhwRIʪ7v  Um^;$eW{Ww  UmX}Tw;  ЪtVl}^~@|  Z`і%4DI%)+~  ,23;$eW{  @,23d$eWw  UymJ&;  Ъ<̴w:>*I5^{c|  ZgіX}'6  xm>5>*I;=  hUE[gOGG%)> VYe{FG%)k> VYe|2N*IyU+g<  Ъ,LVTwԻ;  Ъ,LR}Tk;  ToLW~,>*I5  !l:%OD^}hYFWLuVl}<Ӷg<  ̫ś^oHߟF_Ұ_GuZ,rd[$]ȿ  0A_Iꟳ$n<%w񝗄o/*Ƣ-c3?6s  檽l=ןǦ{cіşR4k;  {f>z҇^T'?NUE[zǾwb$)ie3  W{j?cі&I|#> hgW|?b,2WkAܛh~| 9^?UT>|[Be?b,27Z}js'I5 @jmԏϞ~$)qjo3 {{պN73,*Ģ-sC0,g3 W@{v/s-*Ģ-s[UJR\{ FU{֔c^g]TE[_IRv"| P7{jǿ?/߿Up]~$:,`x;Iʯh_Gx  b>;ݵ}$EX5@Ǣ;Iʲa> _9Wmu>FEX5@g6ϝ$e]g<  ^eLoGunEX5St=Iʮ]x  6j3yoSޫ6f!TuX5K=Iʯpo=g<  ;=^5 e"uEX5F?{e/Q `K,<nj*Gژm3]TE[C}o'IY=m  }}">4׬Qu?EX5D{=Iʲ=Wx FWm<uy[TuX5HY~$)qj;C U?Ri=E[VIRzW f??gIxJ*ѿi=?;EX5HOlxي P+۽U+_4G3i:,{F?e> ^ُѿiBhk?Ýy$iw{M {f?zY)ѿiW?sEX5Ϡ$eYx ^'>zg|/kZcsXTE[|]4> iͩhkʏE?ebzQ śz֫ޗ?:UmYM3(I6h U\?EX5͒StCIʲ? iNB,h|%ϡ$eƓg< l=R-ѿ2)sTuX5F?eeDy ^a/W$e^?Um;毣CIʶ~>fh;Rѿ
hi,:%IS
 @~;,u}{ꟳ8V^5U&_z*;Y,z^ jnO|ՇU)e9:}TuX5'D?g~jos 	US͛âgG(I=< PM_Iꟳ$n<%u6ޱ\bP݃~3Yl9 k/2u?ix|_S;=ZQ!mMSGIʲ< P-âw_<JRw}u O{j_?zGEXTE[w(I;< 0_U{0W2uxg3ZTE[$i~^wt 6\{KjWʇnBt4-*Ģ:{6yl+bzY <ś=^ߟj~hkE,F?mz iyqI{ßB,nze3)I?< 43ޫ~ W)˺_罨Ϥ$e< 4jD 5>
hkLJRz ʒK~)W~lv6^{Iu0Um77?i<~.%)f>= :ǻDQ!mF?m>.;p4itY>}Kz:{)|vbXK PE3Wx{kVEےPgׅϓB,H>\JRuY o:{!G@w_jR&w}u6Rs?\JRͼ9zBWm=v^5);P)*ĢTL/JegSmY |9KSRپ?蕴|b**ĢYo%ٔ|tRg= l,UK6MEX9KMIʺ!>`߫6Ex?ŢYCxJR.#|W}|JxeUTE}okY ^bmQ)ͼ1zcwJRֵw:|@۽U+cQR~'~MUE5gTwGg= [ޫ6Q?i?ŢgTnt<߫6Л^5I`Q1m|Wo~F%)E*n>>3?{DlgcQ1mśXs*IY== xځ_ixѩ|#LTX4JR.-|P17Kߔz'S^q`{mJa%I[Щjhi.~N%) Tj"x95ZTEOD?}d j}I^_-*Ƣio$s?>K6O}ߒ}">4׬J,I?{Ţgsu*IY7YFZi;ipɞit){G$-hTXoJRލ|y߫6Cѧ$?_sQ1m<CF?}>X-xG@?{$Y}36뫣UIʾwD{ i棠{䟇b,X;WIʺX;~y#BjSEXN뎎~^%):Z_>xYM.*Ƣuy$i~E{ np>ǃ$զΞEXN}JR6|tk>$6wzE.*Ƣu[i*{E?}^?ѷN>$6۾0|ncƳrv3+I?1Ah>
hY6tf|3hZTEY񬺇-R{V3'OIE>
hYmxJR}oW֯ڇh9|#$i~^wt;<H4]TEipϮ$e_<K MgIM+
EYzǽ/ٕF=3_@jvQAm<n~v%/[>wIM3=|nd*++;ӛ|&ǁ$զ	EYJR#3->
$6u]TEϫ'_IjDw M6@jSg_	EY:+~~%>ltәG$զEYoR~%u|}h}GT@.*Ȣ2gX=>}HR=R1(|ndzbXIZw_>iETSdzXS{>@t>_jvQQm4E?˒Ԉg|:|4M=%6n=/|nezsU,Ih|g>@N/Iixs(6F?˒Ԍ2w}uh$ops(6[?~%1Odh5E~IM?>hcq,IhtsIFw\=%6yO.*ʢ2^*yfTS{ MQ>vw䗤=s(66}gIjLS>>a>!IP{gT5YAfy$iaznhΞTm_>hcw~e,Ii<J_>r=Ϣ'$զ`.*̢6~ϵ$5ʏ}q/Ii|us066kIjL}`B4]TEwkIjNeڻX莋$զEYڻhs-I 9+DzIM,ژۣmIjL. jǼ$ժ)>
hcNWlKR G=%VuxG.*̢9϶$5Y>r4/3$I_g6᳻06ٟ~%Qu1l/IgwQamYϷ$5^?>r3.I=>hcΆKR]TT|ʢ,ژ3ﳐmͳ[GvIUO	EY1g3a$-l~-|w_DuIUK>>hc}69F5lED%c]jU    IDATO,(o~99FUvJ-?@FOTG3|vgF\W? 9(5#]jUg7,(}~!95	ڻx8^]TEgzTv~%Y i.I{IwQqmlϻ$5	 u6hQ.Ij|᳻66Z~%q8|G$ժgwQml~KR*g @--,~=%VK=U}mlśh3/Ikpvg @uVl=%vW~<|~5`DVKR*N*o~ M+=%vuy[.jˊ$7-IkwQmLDg_~%?& El?=%^:$~OUE1I*G?ԼFv=%v6|~5a|կ$i3 .+?=%v?6|~5aOh/I0uGGmI]&,ژ~:ٗ- @-^wRْTzm6&|_} KZjYg63	6&jxϿ$5p*}Q9 Peǵ$ղ-gxQmLTE?z'|0 EjI]cF,ژ[G Ijl\~ TU{V)ѣZjgxQ#mL\ms@/E XQђTˆEX1q+=$80 (I*|5b{_/R{KJ$=%uGs|>,ژNH,g$5~ TIFfIm^>ǋhc^6zHRc!Ӌ\GhZVv{Ԇhc^.=zHRg@U=%n0|5cƼy Inx1g@t~SH6t9^ԌEc4EIjnaj@FOdIm?>ǋhcތn9'z&HRcY m|uXj̗Df,ژ.IRLeTl  JgŒT2m>ˋhctVl=$N  ǰ$ն[xQCm̟MRپ?z6HRY+ف.ȝcXjƓgTX1_ `u;Wje᳼!6UGIj|+6+Iw_,ژW<z6Hq3`,}A*GO_Iut<6$5 w_G]Iwn*o>ϋhc.7zDHgBznԕZ7Y^ԔE{;g$i慶~& ̷ΞO,G$պ_EMY1^h='$GS{V|\{;#)6趯E	IRJ	 fX=j%u}KL'6M[}}. ̇ޱ=f%XEL/jʢG$z'~(\ ΏTw]>ϋhcaL/JcDI/Oځ|I.'|5fƂ^}h$=Y? &ixѣUw?,X0ޙ!IiMU.?[%iBu>^ԘEJGIғ`=R%)m;q,XP\=6$IO6~~jlTvE;.
EYn=7$IOicgѣTipgzQsm,=7$IOiT,4| /HwERI&im46MSy0zvHR? 'G$eUgׇ,Xp돉T>|[*n~> lf{*ITM&},Xp3rBT}2| 5ztJRVn:3|hcwq$=}7E Ż$iY?ߧϢ|#zH9K?S#S{"m==C$Ix/G@ŵT>~oȔS{Kg|6Bt}s$%?# G$e+{	6bL/^Iba3:wyUJv򗭭h#g$iV~F âG$eY
E&,=ѳD,u}{9T}~7K<G|	6l┆y"IZG7bfgF_=%)ʇoEF,5"Iz|4 ;]#QmxsȈEKL$=Keegle/I߉mr5Qmj3E80 mpɞѣPυ"#my$ekgL}ߒx=	%)ޣXi/2bFDIs4Z_ ,śWD@IʺѷNSyh#\߈-~^ ?_G$e_O"3m[i*ES{?3F7e'I3ȌE0"IzF:- `z4'IWvs*/mTBwDIz; o3U$UǇ"CmTö/LiЎ3>ڻ* ):ѣNQ"CmTƓ$i=^~f Z}i|5#NSs??cFeN9#IZzǾ7 2`&I|_dʢhƣy#IZϗ)0)/%i^sX/2eF(zHֳm_MUFkY!IZz__dʢJFtG$5n?dʢJy#Iڐ=$q)|hrko;hfn۾( w_T#Lπ"cmTo5ΞKe%Iw_E,ڨ=w$Isw_k=$GE,ڨE|#IІP]K6O=$n0,ʛE4^G4Ǘkse+ǔ$5Y~hV$ͱэ'bzO|[|k;6*izT>vO$ͱזǟ%@e˔qhFW>~쫚τ"smT$ie]:SIʃτ,ڨ zI6A'uVby|<=$I3Իυ,ڨ%@,$mDI]^ SYC^UP4E6O[%Inf_aڻh*=zHltgCmTZ?G	4T,"\_{Wǎ$)CmT-R}$z&I&C|doFIψ!,ڨ5G$I҄c̏ίL3|.9p,ڨ=$Ig`ڻ&)zHωA,ڨm_ѳI42NHLE3zH((ĢZ^Ll$Mrzǽ/|6NgOe&zHX* (ĢZQIʰ(3Ί_LeI"Iz~^cF=,}A*{F(IҼ,>6Hw/'$ygF0mCg$i>*_sX?>1oIRR{ٖF0m%I/NdY<ś7lώh>l= y+%6IR}h 6jexѳJ4?ڻokoN?ChVn$-@s9I_/?Ch^7IcwG,I4wB=D7MsIi?L5E3s3K@n:sPg4I{JK6G'ECYQ;~-zfI]/?	OHRsuyR4E3(=$IRgƟAMf$я$i#럳8\j.6jip.ѳKS_? 7^FK&Tgׅ-EYQK}=$I=O!;é?dK&+ϗ[QW5g$)Lv[YuitO$itt}6G0IR`OI/?nzG;aIҤ+ϙ[QW3$Q&I
lOIP]_F7J5,ڨmG2IRpe;/$śi}V$I?gɢZY&I{۾B!l*[k+IMh<L_~вh˶LiЉi4Υf~GgВtFCkE7&IR"NH*Qn*DI;giE=Og$n:3wyU9bz췉9ѓ$-t^j/*,"ͰhobMh$Up
QK㻯~$IAyBYD,m
7+o}'$yOD,Bg_mW}wo&:{L^{DJ8$WvIŶ/
?h}E߿:zIjy[06ДƣHTfa:|4mdt$ե]XwzEϧ{эJ:j9Ei,F{$i,aK_~~趯E?&6^{cYE,薳g$~'NowkIRs,JؿuW>|ۓM4˫R%lHxڻHE,Pȓ$ռUw5Ǧ4FKj[aɢ.'zI2itũ{;R1IF>;<Od!G\T`,Ng߷D<IRfݒ}"۾(nzm4$ո~Ţ,:zI2lYv}VYG=tzLY$e{oEYW$[n^~@|g<kg1'Ua3>h=+6e){OԀw_1<3gOG\4IIRƍ>̣,cg$I:ixaIsy6(uVB|;OԐfL'$=6=m3P/O8{:w	_.\*3LԴCsh#_ӛ;G$׬JsxJMw:Npx$Ijx"eFm=%InC%{>B$wі}ǟ"D5QSk1MLc]664X1յlc+330UG0J EtP@.(0 e33g?_3\;$˵ϙ}'wjԻXZ`? }R3fhLWxiJ  6Sm3uLj}?r3Z-u8* ~R{Цr__E5|5mL-y÷+`WMdh:r_`zezyjf4Sj~Rw>JSޘ_ Yڐ?7Uik2i[/E `U} Z-R{T.ce3O|2 *:CjP fa5s3ޕ}S_I Wo<'U$O c3؃aЦZTm8 PU@qe&goM/Ne/o%:_w1iSwsZ`o[-T7 R4.w	{AsGFolφ<ue6xU*W,Tϟء/z#Gv4=1k@\{o>/b8|v lY,b26N~Kk$   lq]2>}  g]}@sҶfhS|㹯   G>[u*mw0NR	   Ow)*+Cj   `R5?oUlW6ծo}  -߶:YvghS-s}k'   l?~fVTN   x[Sc*;C~| 5   9J;Ms_C  `joL=UP6ն/Ii}-  Ρ*v8Cj]r_K  Aobgd;Mus_N  O~>VMop   Xe?Ц>   T'g?&--U侶  PCޜ\MڷHo-}m  fw^<"4CoC~9~'5  iaڤr_c  }kRcngaڤ5   Xޓ"<C]Z  6ܞKv~VMz\Sޖz  |e?K6-J{o}  `FU~?*#C?u  ǳ{U-C욪r_{  1UkC*ܫ4m7   s]m7   j=~U1mSΡ   ̈ bڤ<tb   \Uޟe{d?{6i]{R1   SsGoU,H6ijʔAk2   S_='Vłdh.  0:}8Vłeh汯}]  `
UJv~U`ڤr_  2U~Uڤur_  "?M%~UڤN  0%?9Vłgh8u  )0XKs&mC;}  `µ__Ud&mCS,  	6Ԙ["K6i[[w]  j}]reh}  `o<'UEmҶ6Ss}7   dO#~#U)g6i;jr_   +~VU=C=-yu   PuSyUrghZ  ~si3&ȫ[z  @FUT.#Ui2I;Pw徦  Q{ՇMULL6iGtu   d0XKҤdhv4  Zk3&4Xwy;   WEUL\6)։!5  a~U1qڤ?8  нgPM
yTU   Q5>~U1ڤ7  ߳=ULl6)摿R5}  `_ט[bb3I?3  h`AϜ*&:C\W4   㳟7UL|6i>.=    U{c*~a&3^   @b*2Ics   v`RcɮϘ*"C4=U}O   `G ?_*MK6iW~ m  ԽJSMgwN{~   6קr+)C4Zk   ۨ};'UL]6i꯽(=  ԿHSMZGC4  pf    IDATf*W,9RTiT4|A#rkO}   tULmo-=!d0,WOJ2=  0Xk󣊩OKEJ㯻zy   [RUuULu=Wf0ҬW.#U}   IzW}6QSQ?W   <NOG/}^T1׬=	HhnQ߶:}  G2z[f헎VEwf0R]jܷ  ]uL3ipMU^FS+}?  j\g󡊙j>8zn`:UT侯   ԓj؆Uf@R  ׻gB3UzU~H]s;We   MT.^3,:=Ǌ?::,  0ZksG{Is;ePR]wJ֛  @]91PLֻǞg~E%ձ)  `y˨clp5OZ#Z   g?]R굞8u&յ%=?y  YKW?)j#_hh97\קTrw   fEe?ګ>6tO&սG   ̞^;5zM/l>+^Iu\:  q?buC[fpRk  _{Qj-~S1ӕ=ںWJ*R.=  `fTSy>v*fCu"Tu^  0g+NE-xSmCa %s/}  `&=)yNE=ZkZ~hkXsuBޏ   C_2<TZ'y'mgykS  0<uq*jS{{mxoG^+  L~~SmVm÷P,iT?K?]  Tߴ*5e?>NOO|lhݺ:Z')	  `T֥_~nS]mi0HC%G  0e<f?^`[?>\iy  *>չcO6xx])Z'  >+>Mi[߲CPW9{  }.g_/3>?rhrA@ҖB6>  0Eg3ղmhE<IOuSw+  7|g2ճ1۪Sm)5'eA$m^âS   S9>M)W5+w|hKNjOFғ9inW   mpߚT.#YLyk	g|YIڼA?  0<7T?`8^_CIڼ[  :^oްMOg|V4-}vs޲   &Zw.շEipCiJڬ摯N  dr~j̥>}ݺmҵg%my?~  IU=|[*g-շrtEKܢԿm    LN#5zMsj]Omw?IKyAu!   3ߝ|z<F6ms!`I[u[F  0~R[4-{%   ,9Jͥ;<.ui~.xI[hni0   ,7rٞSuc_ҠCP[˲$m῞Rܡ  BRS/~R+nvmi0HϽ1/BҖk_    ƪNސ$~𥐧mímÝq2$msC.   *zOs9aOچzkV}eHڼSa]   PwLRs.~wr7gHzsh   gƜZy>_.^:ϳ$m??u  5Iw=Fh1CpkkmHzן  ]w_~>R[k±<ÆR4Lo  jU{Sj~淳T5'y:_Y#_R  xznjg"CTچzk/NK'igo   [VU}{cehrA_DI  1H|cnAcچz7Lw˔>{,߮  x>z7(u}=:nJX_IUq_  yd}ޏ}hꭽ(5{n_':K   4Xwyj{3jgg,sAM-	-Kh 7Tw[yR˲<lhT~ײ%=RZK  0\ն῞~o`AA<%r^ipߚ   3joLͣ'F};Rޔ`n;V~ ?LU,  `uukT 3L|#4AN  `;?~Q=+W4M6Կ>M:$e  ~j1g7z$>oIz5'*   R{d?~R4&chޚUqIoniܗ  `z5h4NO跒zo'ռj/	  ~si3UWmӤQ[/Ia*?T皟픺e  0AWTԽ4&vhR璃Rc=Ju}'+ zל0z^sj~I!U4gIHs;jX   ?#5|oSK4bh{TޛRw}҂6(=9%   dŻ?hf+:~,UNlG1NWIْ]SE ֻy D3Y⥣`ڛ,ʡQnK?ĐPl4X]?}  `n<Ȧ<+Ny[]fJn%S==jmH>#^"x/N;s  c_ȦqoHOUyU31=^/N*7i|5zMs  c_sUGZԽөxGM_M/&Iq^  ԿiM]W;=yt[{Qj_<7?Y}_TU  jdVWwjѷ_Y5MuWIJTi~nONiZ\$4  ytgMPKvM/Lͣ_ڧE\Խ_4twDжN3:uwBj<ͩ\4xOjiқ[zל  U5z[ UD믽}7:\S    m        m        m        m        m        m        m        m        m        m        m        m        m        m        m        m        m        m        m        m        m        m        m        m        m        m        m        m        m        m        m        m        m        m        m        m        m        m        m        m        m        m        m        m        m        m        m        m        m        m        m        m        m        m        m        m        m        m        m        m        m        m        m        m        m        m        m        m        m        m        m        m        m        m        m        m        m        m        m        m        m        m        m        m        m        m        m        m        m        m        m        m        m        m        m        m        m        m        m        m        m        m        m        m        m        m        m        m        m        m        m        m        m        m        m        m        m        m        m        m        m        m        m        m        m        m        m        m        m        m        m        m        m        m        m        m        m        m        m        m        m        m        m        m        m        m        m        m        m        m        m        m        m        m        m        m        m        m        m        m        m        m        m        m        m        m        m        m        m        m        m        m        m        m        m        m        m        m        m        m        m        m        m        m        m        m        m        m        m        m        m        m        m        m        m        m        m        m        m        m        m        m        m        m        m        m        m        m        m        m        m        m        m        m        m        m        m        m        m        m        m        m        m        m        m        m        m        m        m        m        m        m        m        m        m        m        m        m        m        m        m        m        m        m        m        m        m        m        m        m        m        m        m        m        m        m       oǎ	  `W݉XNm    m    m    m    m    m    m    m    m    m    m    m    m    m    m    m    m    m    m    m    m    m    m    m    m    m    m    m    m    m    m    m    m    m    m    m    m    m    m    m    m    m    m    m    m    m    m    m    m    m    m    m    m    m    m    m    m    m    m    m    m    m    m    m    m    m    m    m    m    m    m    m    m    m    m    m    m    m    m    m    m    m    m    m    m    m    m <  IDAT   m    m    m    m    m    m    m    m    m    m    m    m    m    m    m    m    m    m    m    m    m    m    m    m    m    m    m    m    m    m    m    m    m    m    m    m    m    m    m    m    m    m    m    m    m    m    m    m    m    m    m    m    m    m    m    m    m    m    m    m    m    m    m    m    m    m    m    m    m    m    m    m    m    m    m    m    m    m    m    m    m    m    m    m    m    m    m    m    m    m    m    m    m    m    m    m    m    m    m    m    m    m    m    m    m    m    m    m    m    m    m    m    m    m    m    m    m    m    m    m    m    m    m    m    m    m    m    m    m    m    m    m    m    m    m    m    m    m    m    m    m    m    m    m    m    m    m    m    m    m    m    m    m    m    m    m    m    m    m    m    m    m    m    m    m    m    m    m    m    m    m    m    m    m    m    m    m    m    m    m    m    m    m    m    m    m    m    m    m    m    m    m    m    m    m    m    m    m    m    m    m    m    ҨӅ    IENDB`PNG

   IHDR         \rf   	pHYs    {Rk  IDATxyUՕh8غ8bkt8ᬉit:D,;idJF"$ $2;;^疂XUZ_UwwsI                                       k<9V'oߩli]/DK#
^W6@PP2ǵ<<]/w0?9ۜ[4-CVvgyuؔw
_" 6x/JWoޟ=F4byY4	K!VrO"/iW^(e"G_=?@I/l?R]so*	udCZ+~P=̲ke~;BΚd!׫IkRN2ǿXsǽFo?d< YSדA)2'zJ[h.Sɚё /U矺k+_7Uz+u(O^gD2F~_F7Q"96 pdYw~ܹ]	_jxwBvQO}UWH+C۹@8l
.h׺Sg+oG E7 YNXA>]W j&c@z5brPv:n7ŮИm޿Y:w=3TG6wMG E0?n~Mq@Fxw<v#WF </@؍ ;[@`%96`/ 7kInhZ
Ob7uhwZ Xi\nje^\]" BY5JJ 0nl dr nogmne =e )'ͭD   RܽkbL4 fv ,eew ? BL䟖`] XI);@S4Yw`.Յ{PEv,U1Mޑ]YIΦd,%g$rOX;w*R渽( IgAɭ4W׾]u^#{^O?X]˸N1]| 4$oFNyUcJz(t\Um~v  <?¿l{Ftb]._ЋnI~ d5iݮ`zaSr6`/ smq/ᯝ'e~XIZ xW䕓	Qm\LΚO)h ro쐿?OZ)?kܢᢁL%+q6|8ͩ~w'/ ="p5	N!r<1, ܭsO0s)=E2yE^*'g]9Yڑ1w\^H@~Q3G؋*ISXky%g6'We 昿p#?ya(xnٗ8߾ raʚՕwpkŲIoQ܌v?f_@nL'Xu{T=9Lg,^} 뿚}uQHפ,oqmlw+ r AZfׄ(KK(=52ݦ|> @߿4Ake/y ! 3#/v\0?^`io}Bv(EVl`U"kpS_h WpKK,{>E@Uc}=+u)o1
c C1O6[Nܷq X߉TqӝH.x!5TOJe ^t+{aUT2@#g(ipM9d~B= ڞ5%Q0HAA"  Uy:
zYݔC.((@6K 8D qV^Pܞ~S{q1{A!HD A"8$"	~Skz{B" rM96B" pPe Q! W Ț[-(wA!HD gqM9~J2 t! I a/(H`4n)8B$ 6|7pa/(H`uߔݷ$"Y
o!.(Hv7<y؋
A" ޞnJs9{Q!H^SnB'$g؋
A" 'n)5-{Q!H'f+؋
A"Az^5%{$
A" ڝ5%ne/*HMzx.SA"Ym7%ѻ_^Xai:הt{a!H ^Syn"wa!H n)	ZA",{kJ+g/,x/ה;$ T֡1{q!H "$"'5%1^\ T9%{q!H p{MId$B; =$ƩŅ v 1Hxb{q!H F;,ZA" :3e1D 5%IOx$ gn)5$ R5Ζ v E/2c\-]dafn)ޫ	{!H "4"-؋A" {vȕE v Ks{MI  XܓA" {$ 2?D kJ Ȇ [D.kjP, 	ņ f h%<n)9bC3 $}؋A" Wr{MIܭ؋A" HOn55t<(`jʢw{!H Z"_d/80@Kn)C; %^Sw:C; d;lP5ZEE f gb{$ wTƚY^t|uה4$ knn ({!H 樧,	w!H z},鉯D r+FD O^	ה;$ kj>הEr	{!( 0>ϔ{L@ Z"؋Ao=ה!`/55MmNg P*z wޠjAO (
= [}, JeB *S0$2R2G<I{  pnk,Ib!9W~;TfuU7 {Le!eX;^M,{oYYc]V 0G?5nWY7ymm/T7 w@qݹ}AHu	C<rO/yd/n T&$%J"ݏݷ/-	L 3p]y(_<	ß`P*s\q^ڜE'oWaydՃc~mY_w+F Gu='4DuoW얶NE &#bIo/^4@ rw=N"rOT^#W4+{`r^*{8)l(R޷[8ƚS 0>=N_I}{rZ\Pi ='1&wSz^5C(깳4 tg7Rl^6^2(.# }5{EOc7WTa}6܊{F$6BG 4P=`Kځ`E ~#P5ΖS]osI9>7$ 䂠K]\NLeYzqWI9' ;KP=昿LevX{xnאlG.Z6rw,.Rxߋ m9@8єTNC"KPbNb	 )4s\K~)(ϸK(v`=nJln6e~G$,[ %q߹pIǓL^T5-T1_̭s:;;FܦSE\'GrI<@na5c7v"ـgw2 ؠfd;un"{hr$ { 6&&vw?;1' ?H[\ _	͌$AEPx矫ZXc7!$U`$Ow HyTt݌r6}%q$\ {v3F-T\ Zydݔ){p} {mpg,pw.͚Ձ)íy<V" .ȓn7cHs6ge ^cW5KZx0!2@Ft	-l>Q lVE=R=UcU}l_F H*{eoeS^1{8cnR`T 㜱߻8Kgջm'5f )gZUzWpp̅ loVp{[|넳aJ5P. `QPmČױ&o'2;24 R %kF'n	ɚ_<\|d cxwT3Ӑz&d/O
d ȃ,w'^[9s3u={BX5@vё{AVm7i':ג 6) Z+"yUc(=e?׾>9A%X2L hn_菻{ +>G;c]}`<t {\ZlG/5Ko&c Y+ c# Rܞu  r=2:31 b(6ᏇXbw= :6_X\xo$M HˇqБT@q-@q N|< )б v≯Ip.Dfv #aF aox 0lkJ017%ڟr' H?1i#{6tӐK@Ƥ'7~we7t=,Xω;YSƈ'r_ @Lu?y9ٔQr5q=`R+]K 9IVC$zq)@	kNwvf7͹?PF_f@P+-Ci^}n$JoL}[ wߺU  &<.%Yˆ}!b]76nMT+le@]l~~ o6D鉯q}Gvhʣ[KՄ?hӀUQ HOngٱy@p.PvhL5G	߯]g2+^v?|p pb,PZ+$2'4UM.zpm9 	j;{l{e{DtZ*So<_9#VW渖 d!OI|
.">{Dtn*hԏ7׋
>%(+H5AO5Jbr{2K[l4˞7Z>]                                      ! 6    IENDB`PNG

   IHDR  	  e   ^Q   	pHYs    {Rk    IDATxyeu}T!8š&1m&JFIbL361I'vu'nL"$($XX* R @EPgJ"*CUs>ZΞ؛7P  P@n8z_:$:g~0G)Z{(ZSK?$-h/[/  19>ZSK$ma3szQ|w=/ @~(  ,Q:*Ul^ƻ
  	:4$M@~_}Lߐ}k ` L1*Ϗ|fjhZe_  \}Q4i|xA ` L!WceO(=o`e  lOHZ=)4W;ٷ  A 8뷣I>׌4u}GD}   ۨ}oFFٷ    `Ft?yǩs;g  x뭚NH[    `n4ڟ|g0bϾl  yһgHZG)7Qٷ   A y]G@iK0  YHߐU\0 ` z:_Oښzɾ  4̟!)ꠟ^/ 60 4̨1#V-˾|  4=}}yA ` 0BoQOꦖD}/!  `4utO}oǾ#^}G  ?gUm!Oꦖó/#  `9$r!4p]	 c lp%m`_942  hwI  a  ys4D  $k>(Z3_  A @H'eC/%  `D4j快H|an>? P,0 ԫ/QNlAW  0b^/g4M-^	 8a  dQ|M8i80r  FT}QISu~ @Q  3?Isɞٗ  0↷]OI4Bra	 a  Do_O  3lI#[}P	 a  pOm<Կx+
  3kHI:@İ} ha  tOTl|d  lwM4zO^+ 0  oDkK&GVd_R  wIWuiߟ} Ha  hhj|[5}I  `؏#iɨ7˾K L0 y2hi|ξ  	t7EПMב4zU:ʾM L0 y0+Фwǲ/)  `5jM4zU_
 Ga  s4k9ΤG4Me  Lzڨv{vѫ:nmȾM L0 9n)Z{H3i>{0  &𶋢5C;ѫ:?1  lfS:zİ}Y  \}t{Ѭ}N(    `MQ}g?IQ7F{8  
ӻ߇$fy-
 ` lz;Ø4y]4*  DM3,Hhֻt 2 Jm1i>jh7  J6E_N?4M-ggߥ  ƒA V_sB0i~q4ܖ}I  D~ +_$ivOQKm
 ` l5Za\v{vɾ   CGѫ:uVm
 ` l@`\vR%  ߼ Z˞$i|ٷ( b :_Ҝ!7}9  <NF?} a  O	9l\)  0g}(JU7ݓ} a  h^ҜZξ   ̰ޒ.%ijP  c  u]\_w  U}QSFOfߢ  FA c_uT.i
  8_ծL4?ٺ/ 0  Eh\\B=Ⱦ   354JhoO  #  QtN}o-i.?V  0gwKǒ4bM-gߞ  FA 4Q)ÖU$we_J   i{kIڇ1P  #  aT>U=;k$  o%w.IUkdߝ  FA #:*CM[We_F   y[Qw/I#SߏF ^a  ߎ/I%mSSKbpW  h-.Lٷ& c ozKȾ   E$N/Uٷ& b 0p|A,i[M}  ,)N4:; H1 `Jږ:1g_B   <^N&i4}iĠ}k a  ^~I+ikk  (QGkIמ}[ a @_=6U{(Ⱦ|   RvJѨ}/dߒ  FA PꐟN`%mU+]_ɾt   FBs&i$~ku-	 `$ Era*iZξt   Fǰ#~)}MRz$ 0 u>ٗ  i7_&)O@-	  A Pu_?9CuOywDd_:   #i+5}W}; Hg w-}#Ue  0&)Q5V   (V-<K  `5MtN8IM-۲F   "6㔴%Mo/ξd   FӺ/_>')dߊ  R EM0%mI+Ͼ\   XZ];:G%6   (Ru+?LIOTs}   ުeuZ{oC  i zG)	~  0at~[} Hc w^ǫeѴ˾T   ^x^{ů{f߂   ilS^wue  017%{jEu-  A P)Z˟AJzԦOg_&   wG$-zg~  R EQc[,  L^{C{mpaw a @Q|,ChuN~WDg   JQ?IW} Ha }[?DI_{knʾ<   &OJZڇ.   (ǠOM%}O+}u   {և%-N˶>} Xta @1w]J}i   ׊WJZߺ"  b:2Ⱥg}0   (RhMo^(i|[ 3 ߦ:ξ,   [5n(i] 3 >]od_   e>%-lߕ} Xta @1Z?7ԚZ?}9   0	pSvyz}ٷ Eg lL$;#ٗ   0wEIW۳o3    (B}OR7F{ٗ   ߧspm `Q E\f']syK  GѴj;JZܜ} XTa @zWL𤂛Zo~>2   qoIKo1    (B?Óʭj:   `t?gg^  A PΙIe9W"a%   赢}%%o}w XTa @:'^'W׏D٧?   [a+lwJI#o-    (B跥xRa-.w\}  zc{y~ٷ Ee :TV/si  t}k-%OKȾ  ,*0 A;xR9a?  `;#	ɞٷ Ee :TF.?Oy   AHϔ4}; XTa @Z4Óh  ү}5%ͭ{gM  A P^?I_-T  `o$ZSK9%m{a @i "ihg   ,&SҶg   (A1  kEWJڦ  E0BֻOq   ԚZ*i3 Jc  LU_Oq   AJ  E0ӂӣpS  "iG%mUa @i "i!\s\  "?)Ya @i "i~Ok   t?RI[A P0 aϪ}_M  $3^/L?e 1 `ykjio]}J  lpI晴(0 4a @4_>  9nTIOA P0 a+_og   oFkSW%=~a @i "i^~*˲Oe   FL俳Jz  E0\Oc   FѰ~2Ucg   (AR{T$   ix%њZ*3 Jc  LsKOa   F\3 1 `mwGO_   @S}'=+3 Jc  LRODZ٧/   cbce%`a @i "iS   lαo= 1 `w?d   zMZZI  (A P0mOE6O[   Tn+ 1 `-OE  0WNxE;  E0Ӗ;OW   &Ƴq%m  (A P0mI/S   ̛	+  (A P0mOE~I
  7|#Z;Jg   (A&4  `>w^  E0Uh:f   Li3W*90 4a @xo8+  `֜+A P0 az7  `5MtzK;Tja @i "Ѫv{V4e   ^h-.]X*10 4a @hzL	  @Ag}0]X*10 4a @u~Ov   biDs߉2 Jc  LӊF}7OK   
_}P{TXa @i "/#  T ڇwc  E0ӿ^A7  `;.Ԓwd  E0ӿ7uU   9ߑR2 Jc  L3uOS   fߕ2 Jc  LծόfӺS   C_.}Y*!0 4a @٧!   |}T?'Y  E0+:d   ,Mza @i "Ҩ\}
  teg   (AXu`   kpI$g   (AXU>3>   5M{C{4 1 `Vf+>   `o$=Z  E0+A?1gz   :'N4 1 `V^Û>   `ߩI  (A P٧   l93Z  E0+pS)   ۤin&(0 4a @ʩw?fn   0'wO&)0 4a @ʨt7fn   07vT{8=[  E0+UGdj   0/_94=[  E06dj   0?mi2 Jc  lxNi   jp$d   (Ad9٧   ̿zwL=0 4a @&%Q߹:  1X{z4 1 `6uO   ND-sa @i "Mh;D}-٧   ,M心KcA P0 aYdZ   (:G-=\  E0]~8S   ťq  (A Pɫ
   U_O10 4a @&jEݘ}Z  ]%Ҹe   (Adտ|S
   RtOyw{4n 1 `69U{8_eR   ^6Z˶K?)0 4a @&gN   {KA P0 aQ#	   R߹_	"0 4a @&'eJ   0ti\2 Jc  lkcDSgJ   0k54}]  E0_Ti   #O_!0 4a @ƻ٧   k5$]  E0מ}
  HҨg   (A>   Ts&=Aa @i "o5'd>   0:wi3 Jc  l<k
   @}חQ  (A PlcO   ~5=^  E0_1g:   0w\./ja @i "_|"  9Q  (A Pvi   cexwzi3 Jc  l_{)   cs[Q  (A Pt>e   `,o>?^  E0zc   c}Q  (A P1iٴ.t  6w|i2 Jc  l<S   _=jKA P0 acҨ7ܔ}   D^/Ha @i "~ߕ}   赢9(d   (A7 oG}71_cpi1_VMGq;}c~%ڟ?<MNϼ?g}(z$zS80מo~>{f^6 `"(d   (Ahe" 0Q\?/?=ϢsܯFjg?jgE{嫣sۢٿŻkD}W6d 	Z+3 Jc  ld) ci7;\s_~jg?}_qxN4ݙ} `u縔A P0 a[L <@ohg~~}/_Jgݟc>3_h #c'[˶KfK 1 `6/= lZ7zgV5$y=nUpti[.t- 糔A P0 a#ڊFSm>=  Epf.֨v}FyR[+b}1d~ XTW?  E0ͺg}0 [    IDAT4Q_/<QT,9\r3?=1XsB4 X3gA P0 a#Ԓ1 j ~^=?,w5٧ ,M?w  E0fd (vo0z~8},Ymk毷.X}FkZ)#0 4a @FӳO ;7GkZaoFS `'ӟRFa @i "V/O znyA}ҟZmv'͞ 0~QUZ  E0->% `qYtPT>39ܪݞ=f Mfɳbg   (AIl; Գ#OnaםQX bMk}?%Y*-ba @i "NSߓ}: c*z$}~4ǣ~t7e EgYSZ  E0}1t 1Uˢ}ҟݟ3{.5Ն W禴 1 `61iO 1?ԄӣwG3 S7?3E  (A PѨze @MDDKӟ*{yS ~"e   (A4O ˢ{{5}3Q5}tP4ߛ}) w#yA P0 au?٧ i^4S3hzg_ 0ɞGi12 Jc  ,-f iUQҟңU_WĠ} P@vyzQZ  E0˭M} 06Z+쓶Mf_: {ӟBg   (AXG/}
 0s?ONIRĝyK	BFkjIPZ  E0Klv<tg) Y37IIsmSg4Ku}{PZ  E0˫s;? 88i~Fo8+(-da @i "53ه	<x{tOhM-MI]?}e@)aTDOZ  E0˩9n`5ww?DkӟmbV# Cҟ}Be   (AXNs:0U/+ݞL2hW$ [˟ܓ"0 4a @r\}GMNjOIR7 n'yBd   (A>M}3]_?FY跳/U &ҟuBd   (AXVdv Hy0z~8Z˶KI^F}ײ/[ &T;0 4a @%<pka`L<^/~ID	9i3 Jc  lqCsst4uOyw4/g &Hy(Z<='ga @i "-n> ~;zSwHfIPWD}W6 {ҟo|f   (A"6}49 #suxeJvyz~j%2&ca @i "-^ߙ}E 5;~VI\G+	ϧ?פ  (A PkهSwcgTJ~#ٗ> cnp4i2 Jc  lZh:en FEl<=%Of cMv}f3M  E0[:'+P0"wN6I%W1 cw_?Ϥ  (A PiS5 #`pg%I?7 ۬k2i2 Jc  lZٟ `0z|,ZSKKԒ譚ξC 0GRLca @i "-|Sߛ}HTsN#I]1g. 3kOIs  (A Popiه$%"IO\wFZٷ Fݠ]_I~Is  (A PnSn> $\uDwIڇ!ٷ FH1XsBpt|{~J  E0[:'n!`:_?$m[C_M;	 	Mbx9[5wj?  (A PmpqهE<tg?3Is}OE[
 <[Kj?  E0[=)jC!`߾.}_4/U|g   kg{և}њZF!0 4a @αo> ,-F3ӟ=j;7gb M}7`'%Z;?SQ  (A Pg^ _/ɭ%QK0ωު蜸sT{<7!Sa @i "-PSKxW`W?w$-h3?<p[-xMq?ux~4 1 `0$ D?o$-^^ƻ> ~oM-MHA P0 a1틻fZ ʠ3sDI_{kyi7kO޹OIK%d   (AT߳&]c06¾}7k3Do?[U{</.A P0 a_Kff &Lq;?g$>t7fߕ B۾8;:~qI  (A P{> ,w?c$Nc~y kc?ֲْ;0 4a @濙 ``oOH:'+fߥ 4m>#OK7Kں  E0?9هkE_Hzu
`Q4cx˅[5wj߃%=0 4a @	}H'MwStI_ݳoY j?t~I/7'^~0 1 `6Ѿtp!`>9ҟ+Ƥ%1w.mSgM:"g~ ڇ.Z˶˿JZ  E0ߚn> UD?MHme P}-1);s䛣PIi 1 `6xe`>g9Qo)6C1_WtN9=_~4Z 1 `6ه9牤'6d΀Q:WFEg6(i3 Jc  lpf`_?5ZSKӟ'ƿook$Q_5'Do/0 4a @eO) /Fk'&g<LfӺxNVMG縝s&#0 4a @o> lYIWoqME9Q  (A PyxvC	6h}Iڲbx˿fQ6G^3޷K߿$A P0 aS}C	jgɮl+z1XsBpt|A P0 as Pfc3DRcĠ}Y1}9#I  E0{~'07I=Cٷ>`5ݍ1?x{Iڒ  E0g}
fcCRy>*̇aO?^uDtx_1ZSK1- 1 `6u_> li燤[Fbc{_E?'4O 1 `6f̿  `<tOgkٟFSзb}GE3 1 `6:'v!`$=ٷD`/nEK*00 4a @! [xwT?'!IꣲoPa?kcp=}Bzji@3 Jc  ln> <αHfH)Q{m&V1XsBpt|5~Kf   (AضWz}xOfHң^ho0Mbx9[5wWA%i+2 Jc  l}"iٷJ+Mra/=:'nT{(:q  (A P9|0dtI^H5;&A7껾/3핯ԒkV&)0 4a @¶f> G
Iڒ=f6a$~qpi;9ʧ$-Ba @i "mcGcſD4Vuɾ}¢7U9qxnu(I%f   (Aض> s;ӟ<<	nE?xכ$isa @i "m[W1TsB]o07 kc㯩ח$Q3 Jc  l=#%	I_ٷS2Mo`'/ON$I[A P0 aVCIkɾ£yxNVMGĝy׋$in 1 `UDaQֲ'?'$iέx_]쿺9_WtOywTh!I  E0IaQt}G3Boh[+^wu~>xhM-M$IA P0 alAه3IW}{eB5m>#<WwIRNa @i "m} 4>IV<-ܜ}e5cx˅[5wjے  (A Plٓ"#֞|s[t$[=/eDSվ?~KF;0 4a @¶>d <R=A?|lpՑw[FQ=z9!z~xO?No~J+0 4a @¶Y>d <ҟU=+Mo$97>yi$i3 Jc  l 0"}iAi}e5bx˅[5wj租  (A PCIZ̆|kK~=QsMTNa @i "mE+Q 3:* IXWDw`D}Ϛ\uDt@y]m~nI  (A P-}/f. `Iʨ'Vh6lv֊C$=20 4a @¶#poGRsAR>g߆yMt'+=H 1 `<,p;.K&HRfcߞ}+f؏z_2g/%$I[A P0 a[^}痲 9w噇%1L8Yf&h1cLf
RBBT-,4YDYEEviλ/)8:t}}]USo	T`i՟a3zfyn:GE?$m 4a @l6Mӛ>@w63$jƽg?xՃ	;5}M%IR i aVV
iw)$iR]w~"J4 i aVwT
 xf/)$ibߩ<O~wUӿ{;A$I i a˱V
 ^I:ǿ<Ff-96V3x{I4i i a;T
 xoru4&{Ӛޅ7e;6^V~I!0  A  l?@ ﾸ-I}M34)ݧW6kiUH i a_ki ÿ=InpfAѣ663̢%IZ( i a_{mz$MrRfi7~fyn:G_-A   `u~o ܿ-i=i2^`3cEӻtsNMkߟ)3$)-0  A  l~1vg>o$MC^֌W=LqwU3ʦ!ӏ_]%I <a @oxg5e$MSt7Ͱߌ\WE[H53  g) jtO$MUiFo{oz}ffϟs$IA   `ZD Ɲ
$ino4jzv$i3  _߫>@GϞW6ky~l-پK$m 4a @=sw@4цtGfӏ4vhfm]!Ila @0  AROi<X3xw@Ǯ;fwއQoOJA   `Q}"Hk/$ikʦ鷚񪇚+ޥ{4vjZl6I4 i ao-'Yo$-ZtI4 i aiMoW θ\$I$Ca @0  Aغk Dx\ I$I	 i as[s I$IJ  Hc D0[ws< yff$IA   `_]}py </I$I) i anx $I$d 1 "#T Nʿ$IA   `U2~̢ʿ$IA   `Z pL_$I2  ^[}8U$I 4a @=է:˿$IA   `z|4 QO[$I 4a @7 D|R_$I2  O~I$IJ  Hc D0[{Go>@Q$I 4a @7>]}ff6~I$IJ  Hc D0[>?]}(]Q$I 4a @5k D_}P_$I3  ֬s[{˿$IA   `fsv>@-K$IRba @0  AZ~v>g1=,ަ/I$I i ak6 $I$f 1 ";T ˿$IA   `fU}w/K$IRja @0  Aؚy, 1:'Yw_$IR3  ~4hX}%%I$)40  A  lZ tV%I$)50  A  lڟ:3    IDAT =|Sw_$I3  Vs[Ocpۙ}I$IJ  Hc D0[;W F%}I$IJ  Hc D0[E>	@޹_ݗ$I 4a @%gOsN}I$IJ  Hc D0[uGU F_+K$IRra @0  An=$ 1Z{/I$I i a7 D/K$IRza @0  A$ FR͗$I 4a @ DuQ7_$I3  VT [Ǘ%I$)=0  A  G g$IA   `6WsX}w+K$IRza @0  A\_W}SQݗ$I 4a @:_s }I$IJ  Hc D0s_T F,K$IRza @0  A\ݳ 1ZJw_$I3  ]{9 b~yw_$I3  ~`[}a3h$I$g 1 "5 0n/I$I2  rJ9 "/I$I2  ~s D}|I$IA   `6Km7_$Id 1 "5 X͗$I$ y as +O+K$I <a @F?N9 "n</I$I2  ?s D|o$I$  c D0k~ W-)K$I <a @A S͗$I$ y amOwɧ$I$0  A  l^/>@ޅ%I$Ia @0  AlB) b߭/I$I2  fkS }C}I$IA   `6[O}I$IA   `6[߮>@9%I$Ia @0  Ale;V F%I$Ia @0  AlR}
ݳSݗ$I$ y auN~{) bt?}I$IA   `6[wT Fw%I$Ia @0  AlU}
3/I$I2  f{v 螹sw_$Id 1 "8=ʿ$I$0  A  lY[}
sv-K$I <a @ٺg 1z+>Pݗ$I$ y auR}
|/I$I2  fx) b߭/I$I2  fS ]{w_$Id 1 ";Ow˿$I$0  A  ly>@ޥ˿$I$0  A  lP}
++K$I <a @z^}
.K$I <a @z} 1</I$I2  f]S x\w_$Id 1 "ֻSէ 1Xyjw_$Id 1 "Eէ 1$I$  c D0wէ 1$I$  c D0wS $I$  c D0wǫOc}I$IA   `6[ݫOc˿$I$0  A  ly>@ʿ$I$0  A  lފT Go/I$I2  f._) ,޶/I$I i auܹ QZ/I$I i auOW) o$I$g 1 "=寫O}ʿ$IA   `6[W J+K$IRza @0  Alv>@R$I 4a @ٞ& 0z$IA   `6[?>@]ʿ$IA   `6[gَէ һ~I$IJ  Hc D0է ҿo$I$g 1 ">Oep1~I$IJ  Hc D0}oV sʿ$IA   `6[Oex~I$IJ  Hc D0dS D=v{_$I3  fk}Oe#~I$IJ  Hc D0zi) ̢$IA   `-ڪiƣs Di]_$I3  jz3 Z}_$I3  ?p9 o$I$%g 1 "5~s D霰S_$I3  =rK9 to$I$%g 1 "5s D]o$I$%g 1 "5s D_sh_$I3  ~v9 n9/I$I i asn: Q߽/I$I i as[Z}(n/K$IRra @0  A؏% 2n?Q$I 4a @e{U x$I$f 1 "ջV NkW%I$)50  A  l޹>@[_$IR3  ꞹs9 tNة/I$I i asuN~{9 tٵ/I$I i asuA9 /۫/I$I i ass pt_$IR3  js ua_$IR3  ~OT9 YY$I 4a @k D(K$IRja @0  Aꍟy$ qf>$I$%f 1 "۪O}kʿ$IA   `z>	@β˿$IA   `z;VT Nw%I$)10  A  l:$ qz^$I 4a @%W NCʿ$IA   `zKW 3˿$IA   `z|$ qF^_$I 4a @ /K$IRba @0  AukI "7@$I2  V'>?$IA   `zC~$ :I I$Ii i a']K I$Ii i a?֢fЭ>@Կ$IA   `f>@M'%I$)-0  A  lF^_}8]Q$I 4a @5y^Y ⌟/I$Ii i ak6 ۖ$IA   `_] Dj+o$I$%e 1 "YV Rg$IA   `fY}HݳSH$IRRa @0  Aؚu D_W I$II i ak>תipӉo$I$%e 1 "Yk>@ה$IA   `m4~i ⌟y$I 4a @7^`i "zY I$I) i akoЍէ> I$IJ  Hc D0[{\P}HVH$IRJa @0  Ax\i "߭$I 4a @0$VH$IRJ~ 1 ">@᷿RH$IRJa @0  A~/Oio$I$d 1 "W S,ں$I 4a @էU$I$%d 1 "4hP}HTH$IR@a @0  Aغ D.ߥ$I 4a @u7 D_y@ I$I	 i an D޾$I 4a @B%4z7@$I2  ]ݪimfoSH$IB  Hc D0[wS< Z$IA   `KP}Xc\H$IB  Hc D0[w_U}X($I$ig 1 "4hP}"H$I$ig 1 "T _)$I$ig 1 "_>@w$I3  `i'473-$I$i!g 1 "=/Ů>D w@$Ira @0  A띿[ buNw@$Ira @0  A]$I$- 4a @oU ລ$I$- 4a @秫Ok+I$IZ i a߸d "y$IA   `L ZL; I$I50  A  vf b$IA   `3ꞹs; I$I50  A  3_w@$Ija @0  A?>@g$IP3  >@c$IP3  6OiSd=~-$IA   `ayT ڇj; I$I10  A  lS$I$- 4a @kpէջI$IZ i a˱>@ǔ$I3  6>@gw@$Iba @0  A؆9揪Ok}YU[ I$I-0  A  lj-է:I$IZh i amfث>@qo$I$ie 1 "mx>@$I2  6ϭ>@_*$I$ie 1 "m/Ȯ>\ ]]H$IB  Hc D0z+_}.XE[$I2  6α\}.h_YH$IB  Hc D0ZsD@$IRa @0  AFhtOwGI$IZ@ i a۪Okpw@$IRa @0  A5}y bﻪ$IA   `$rw*$I$i!e 1 "m\>@~-$IA   `qu'9I$IZ( i aWkWV Z／$IP2  6E[5Mol -$IA   `l F$IA   `n=l ƽgI$IZ i a+>@֒I$IZ i a_̝s⟗$I2  6{ .d[ I$I!0  A  lk] n>-$IA   `iW=T}:XGV$I2  6=V װ@$I=0  A  lYvէ>I$I 4a @MwO{;I$I 4a @MsV ZI$I 4a @M_>@+I$I 4a @Moy| O}$Ii  Hc D0F\[}>\q{@$I90  A  lxl -$Ii  Hc D0z}| Ѻw)$I$i3  6Ή^}>hk/$I$i3  6| ц~-$Ii  Hc D0{-ަiwnfmUH$IҔf 1 "F>!@ց.$I$iZ3  ^XU Z礷$I4 i a/f_t	eQ[ I$IӚA   `'6@$I50  A  >lD=qW[ I$IӚA   `[mg55^VH$If 1 "F\}Fho($I$i3  ^xO>#@9$I4 i a/ş>#@7PH$I4f 1 ":'3Dwu[ I$IӘA   `k-پ U̢I$I 4a @Т# P}kI$I 4a @kO	sI$I 4a @eէo$I$M[a @0  AwGO	mxo$I$M[a @0  AsW $I4m i ag])Mkߟ)$I$i2  6_Ǫ	sI$I 4a @U Z,$I$i2  6/Ю= 7XH$I4e 1 "mZ}Nhn/$I$i2  6_~ Fff$I4- i a/o ўV$I4- i awW Z$I4- i amgV eo$I$MKa @0  AwD=tc[ I$IӒA   `y'653{=$Ii  Hc D0ۼl_}Rx/@$I!0  A  l3hfy Ѻg=$I)  Hc D0ｲ |[ I$IӐA   `~vg6@$I!0  A  l]d뷚ۖ$I4 i a ڇPH$IҤg 1 "m>O{I$I 4a @-;OՒ@$I&=0  A  l4XyZi{Y[ I$IA   `e]Dw~,ڪ=$II  Hc D02uNة =$II  Hc D02~/I$I 4a @-׸D_o[ I$IA   `~6o$I$Mra @0  AUKm<h[ I$IA   `k@$I&50  A  l>תsN$I$Mja @KO    IDAT0  Al6MoU Z$I$Mha @0  Aؖm'6@$I&50  A  lR_>1@+$I$iR3  ¶l>1@~?WH$I$f 1 "mGvu}s{ I$IA   `M3W Zտ$I4 i a[7W /$I4 i a[U ;I$I 4a @-_／T xܴޮ=$II  Hc D0uX}fx/~{ I$IA   `{oiƣSD{ok~$I$i2  wU I$I 4a @iSD=-$II  Hc D0z ƣI$I 4a @s[Ol@$I&)0  A  l~jsէ׻I$I 4a @kԽ6o$I$MRa @0  A5sD=qw[ I$IA   `6.DMk-$I$iR2  αo>7@q=$II  Hc D0Z⹿:K>UH$IҤd 1 "o'>9@I$I 4a @mp)'6^P[ I$IA   `6.k}I$I 4a @sOsI$I 4a @vM3U Z}I$I 4a @omxEo$I$MBa @0  A7DhfmUH$IRua @0  A;k@$I3  Η~ 񺧾=$I 4a @>SM3V Z%$I$g 1 "4zD@$I3  jx\[mI$I  Hc D0U ^ו$ITA   `VS{O{{I$I  Hc D0+jϟla B{ I$I i au F߿-$I 4a @/>?@a$I$Ue 1 "[k;$I$Ue 1 "Z($I$*0  A  =^4n @ֿ$ITA   `V -$I 4a @b @i@$I*2  j._ @βI$I  Hc D0R# w?$ITA   `V?4v@-Կ$ITA   `Vk -$I 4a @Qc /$I$i3  xRH$I|g 1 ">׫ $I4 i am7S mx9$I$sa @0  Ad4hg.$I$i3  &5V( k@$I30  A  l2x=$I  Hc D0ڇj@$I4 i ޽G]wn^9vpکՎ;m=2T/=qNiשNM6	AƠ(KbDn0[	D$"bPQr߿LξޏZ[{d҂JQs Hz{ Ik I00  0  Tms Hn?c}$I$Pe dc `֜_Z k/{M=$ICA A AXs|w@z?@$IUa @6a @
aͩu+@z	$It2 1 R0kV[@j~$I$Pe dc `֬w_$ rV{ I$I"0  0  fջ}O y&H$Iҡ    H Yu'^I$I:  )5E/(e8~ U\$I$d dc `ּ?+Y V?[ I$I"0  0  5S ևY=$I    H yuzO H{$I$ua @6a @
aͫ_~ o93H$I\g dc `QJo2i V=|k=$I9    H U[7D?2ys$I$ea @6a @
al* V~$I$i.3 1 R0kfK4 뭛~$I$i.3 1 R0kf3஋$I$ea @6a @
aͭ< Rx0H$I\f dc `ܪ{< k@$I*0  0  [?< |w$I$Ua @6a @
aͭ귣@zI$I l [딗RO $I$Ua @6a @
anO L\xD=$I    H ( >u@$I"0  0  f׻/@zݫK=$I    H ٵWZHopy@$I"0  0  wJ @$I 0  0  7| .%/$I4  )5>L \{ I$IA A AX^G $I$va @6a @
aͯ /I$I l FtSHnL.8,&H$I,f dc `6UT k@$If30  0  ѨiO ~$I$i63 1 R0O W$I4  )F~* w{=$I    H lt^sȭE/$I4[  )N=WD?:@$If+0  0  ѩw@zk:H$Ile dc `6:uSsHo{ I$IA A AZ|t)* V?H=$I    H l>zwHuOI$I l FE?~$I$i62 1 R0W' { I$IA A Ahؿ~2 U[7I$I l FGlm-'=/&H$I3 1 R0o9 ^k@$IfA A ApzHw$I$40  0  ѫ{ [WI$Iia @6a @
aW?l ҫ[?,	$I4 l FG@ze	$I4 l FX+$H$IL2 1 R0z}  7@$IfA A AhֹF??/H$IL2 1 R0Z'z| r:7A$IA A A6vOHsѿ$I4 l F/~> 7|8H$It3 1 R0ݺ;$I$M70  0  ѭ_~> T27A$IA A ARzO Χ~=&H$I42 1 R0@z>~$I$i:  )v[Έ~B U~1H$It2 1 R0=	W(	$It  )v3~&	PJi/mM$I    H l}4׽=@$I60  0  ѯڲ67ش*H$If dc `6g^ă@$I60  0  ѯs[ co$I$La @6a @
a_kKJO	 'I$I: l ƣc[@z[?~$I$`2 1 R0w~J { I$IA A Ax[pPZ	$I4 l ƣ9~J R:9&H$IT3 1 R0&*ߎ~N n`M$I)f dc `6>U ҫ~$I$i  )O[ϊ~N ݧ#o$I$M%0  0  {; ~!&H$IT2 1 R0Zg*9PJ I$IS    H l}4I7{ I$IS    H lBH~rk=$Id dc `6^n`OI$I:Pa @6a @
aU·F?) J)K~$I$@  )W%/)F?+_Y~$I$@  )_ǶD?+߿3H$Iҁ2 1 R0w~V :E7A$IA A A[g@)o$I$/0  0  }룟 MI$I_a @6a @
acQO j I$I    H l<5iPI$IWa @6a @
aYֳ o
	$I l Ƴ~Z RzI$IWa @6a @
aYWE?- o	$I l ƷG VxNM$Ie dc `6U[F?/ J)s5&H$I2 1 R0z7|0yPJ]7A$IA A AֹRJuߺ I$I{    H l|k-yI)0Ww.$Iga @6a @
a-ORJׇI$I30  0  np'@)w_I$I30  0  ORJu7A$I    H l' W~T&~$Ilwd dc `6MUJ (wA$IZ.Ǖ޺eiUnۼwE/  )÷F?3 J)~$Iiᑥ]37.+G(wև~"ކf dc `6o=+PJ}iM$IFO?vVP7Vꟈ: l ƿ~f RmerawA$Ijz%/-Rz'Jem'~6f dc `6xU3`׆I$Q-~a8/MpRzv?u{640  0  > (_o$I#K{f^o\O?V9=7 l r+ oyMM$IUǔv/
=sok l rԻORJQ\px]$If֒΅o9ڲԓ<>_f dc `΅o~j >uwA$IQ_X:++u`Ӫ2ܶ.Mչ5kha @6a @
ay[F?7 JEI$i-<[keںWFIw l 4|lKsRsEM$IUk1Kʨ~]650  0  <\ ($I(O?^RmY[me־7_f dc `O _$IJQ}w	Uems)u]2]W740  0  <.)I$i(ǖyqYn(e-Y440  0  DMUJ (T[>$I46S:O(;c_y550  0  \U (ԝvS$IF/.ӏw_Vg>[S3 1 R0Uֳ y}]$IR[㯫l>~#ճlha @6a @
a^'.I$5GcKwͼ߸T[72F:oC3 1 R0UWE?9 vB]$IR\ǔJoD-u_Qsnja @6a @
a'E?; J)u2 IuJgov}4T_??450  0  |m<s~$I4MO?^2شm.FEC3 1 R0W~v }$I4Zgt+JuC)Na朗  )s[ T~$I4ZK)'xL஋NS3 1 R0WkK
tI$Z'tVWzӏE4yI{jja @6a @
a9>%K·I-<O?n?m_#kXC3 1 R0ΕO]_>5.H$euwjR_CշsM    H ,g~z 2$I8ZzL>OjR~+ ߣaS3 1 R0Y_~z ذ*S^~$Iơ/*Ǖ޺eiUx(=o]lja @6a @
aI8~+K$IFGcwͥ_hkkC3 1 R0[-]_=;.H$~^߸T[7oGǈ>650  0  o93-wA$iJoD-uGѿ1ªnM    H ,oK M
$I]:++u`ӪfQ/f dc `~~ 즻f^m$I&*OΕeRab[~C3 1 R0]O]wA$icJuC)v]$E,450  0  U[>إ~wA$i&N'-kKy2W,wa @6a @
a]'n^~$IRo*k6)S߉U
z🙦f dc `o~ ?$IGcKwͼ߸aLY?G    H ,y_Xpe$)}ǔJJuC)vI0#ׄ\550  0  0g.u29qTm$Iyj-yi\[?Q-kK=XD0Ykja @6a @
a|t>A$i_X:++u`Ӫ2ܶ^     IDAT\uA A A{W3`7/-$iZxDi/?t+vǪuUdC3 1 R0S{k! ~A$^ǔv/ߊcpFA A A&V֏" ?6J딗IZK^O?^RmY[mѿ@6_s l ´꾫" ^|bm$Iiw/MpR:)o^ l ´On?76HQˏ-5JRmPJՋF஋A A AYy|S`7[o$IZK)'R=p})_C`,:罩  )i{_\J=~ 즽쟇I4{d~ڲԓۢ݀4w450  0  0A$MJח޺ei{_?? l wMA$MGcKwͼ߸T[72F*fpoEC3 1 R0ӏ^n3;"A$ҽKMF @s¿M    H L?}~ _$euKgq;ݗG= ˙ߓf dc `قKy*IMK$IYZ^k]G* ̒McA A Avz'	n~$IQˏ-5JRmPʠ}9һaAw  )i_Z$]]i?~$IZK)'RmY[W8z׼/; l ´{O'	k0>H4JN~q8//+?>@< l ´{S^F@sl}$MO?^2شm.FoaW;{ l ´g,M~L.<">HԄZgt+JuC)NF@?~550  0  0Ε=}c}$PZzL>Oj#i^¿iM    H L{F?K п I\:E[7ǟ~x(c
550  0  0Y,𻷅IfGcwͥskha @6a @
a-<Խg& u+o$IӏKVjR
$@-lja @6a @
a[C_~ {$MeY}B魟(Ֆn(9}lja @6a @
a[/(i7VIvuvSwzU~s	WLm7  )iou>O=ԭIRcP]3n?m'FAWGA A AVWD?M 7IR?ؽmqYn(ߎ> ZjS3 1 R0Ӿ>@`$i<_~o:T\_S'`V$[ l ´VE?O 0mA4ڵ]:++uwοO?A A AUD?O TK$MGcKwͼq;n	@&uq3 1 R0Ӿj/m`/Wq$5O?>o>T[7oG-p>790  0  0x`{>#$Iᵖt.|K魟(Ֆn0D4?nra @6a @
a_}WG?Q P-'=7FH]GΊJo2شjǸ~gcw  )i'
^tV~#$Is#K{f^o\VQʰ>= #o{3 1 R0'
^<FHf[K鷣X}Yw  )i-z~)U/o$i֪uUi[;>ora @6a @
a:P}-٩Mg`lo93; l t~$k~#$I߈>+ c~"; l tL؋j7B4;On>+ cw_盜A A ATL؛aUZ;!Iyu0Wqw  )i*O<T؋9FHf#J0ÿ    H LSiO|!IYS^}N Zg&g dc `F?U <U&'~'$Iӯu櫣	Xko}3 1 R0Tj* Y[wB4 ;~6[ l 4B@o;'NH]3}J ZkKÿM    H LS
^<R&~'$Iӫ{GU| l 4z7,~ C~'$Iӫwت~w  )iu.}tJ$M-gD5|g dc `)On'NH`Ӫ30n7=0  0  0LG~ C#?~'$I_uߺ0/7=0  0  0L~ C	I7'`loxw  )`^'>T~'$I_=- ¿M    H LSk+, RK]jo Foo}3 1 R0V?5+~'$ISuDֽÿM    H L஋- Pݷ.NH^_> co}3 1 R0~ K/S^~+$IS{ї`?Kg dc `_~ Gwͼ[!IZu-l և:[ l t-<ݧ. P}[!IRG6g dc `Twu`_:EBtw_}5 V}&;?
  )i:@`?3VH{G5|lKw~2 1 R0tj~6_~+$In0d Q    H LjR[er$im ̝OG!0  0  0MM[ {
}>uѧ`o>-[?
  )iOD?_ cpgo$iu>ѧ`֏Ba @6a @
an|؏L<yB ;݋O֏Ba @6a @
av'=A'	3B_Y}& Z_֏Ba @6a @
aI֛0 1[!I{F	:UQ    H L3Ӓ'lI?~30Lo(d dc `Yy| ~/$I{0#A A AfRkѥTg~6_~/$IkRy ko
֏Ja @6a @
ai؟AN~q$}K} Zuߺod dc `pz3 A$}ѧ`n_ l 4:O~ @u$| 07.
֏Ja @6a @
ai%/-eXE?e )/m c{{¿A A Af7E?e {$ɓ[p} Z·G$0  0  0Fˢ2 P=xC$>'`?sQ    H LQ1)p 2fHRWQE op?1{?*  )i6j}R譛~3$){[ϊ> c~{Q    H Lp=~kBW=> jo(e dc `٪9)h_I\=X) kM֏Ra @6a @
a390N	?} ^EQ    H LUk1)zL.8<nHRƺ-  l 4?I0M͐7} ^7G)0  0  0f;΋~ Lu͐U߾) 
ޏRa @6a @
aͺk0I0u2wCRRw> m8(Pa @6a @
aͶpK~7$)S_{G-0  0  0v[5 SP!I^'џ~W=tc~2 1 R0l7gTuOI_~7Q    H L]?~ LQޏZa @6a @
aZg)>NDRџ}׽mQ    H Ls6 S>wCƽ ^c l 4n_
4zv`2Q    H LsQߏ~ LQ{~;$i=ثv~3 1 R0\:u`{W퐤quvSk [ׄG10  0  0Um7 STm~7$i\\{џy? l 4W<yp!IXGRo(f dc `8O4 Bba @6a @
aZaɉ$S\ ? l 4#p~;$i}/? 9&¿A A Aӣ8 z!ITu? )z7T3 1 R0\YOQץ5CƢ町l ]ha @6a @
aZ.G?s Bֳ$C~3FoDwT3 1 R0\Wm8u2CFWG^f dc `nKܻ$t+S߉ؿha @6a @
a:+~ w~?$ikџr<~xNT3 1 R0ӜRw~ 9C$iDCџq4~3?  )PTm|S TQmط? i(?  )P_D?u V]Z7DFHwÿA A AE|S`z} HҨջo? t>¿A A AUS߉~ GQ7DFߌ|:G90  0  0_ 0K~C$iTj/mg x3 1 R0ӡ{w6I VЗ¿ dc `CUWROihW$53 X+#A A Ae|#0o|&HR5@:ݫK3 1 R0ӡOzwD }c3 1 R0ӡ'4o>-HRc[RwTRKk7`3 1 R0!oG?{ >]ZK^K$űL3|8d dc `C]i]7wDXuC' +¿A A AukGwo$5GE)uHw߅߀q    H Lٯ~ @wIjR,4Yy| l Qw> 4erDѢ痺D .D l > 3%Ԅ{W' od dc `w~K$	mp,Ka @6a @
a䥥<>HRdOO1@Zk:Ka @6a @
az1HRdշ9Mw`\2 1 R0STD? fsoIuKVџaai[0.  ))'[$EԿO0@ZǶ߁q    H La-8ԓۢ o)tkRzџ_>~)0  0  0E6 fz{"Iџ^z߂q    H Lű `tSMC8.Qa @6a @
auVJ=1 `߽L.8,H\׻o? {0N  ))#_1 `t>;7EK=X 
A A A fѻ#$U6SkA A Ak fIwI f^M l ނK?
 ̂ɭeIzO, ֙	A A A`Ӫ fI~W$i6k-yIۏG^ҫAM l Ԅ=GYROn+_~[$i|ZR`0  )	N~q)U?YEf*eЉD{_߅q    H LMzK? ̖Wglm6%_T viwa3 1 R0SS]? ̢ݗIIsXJ]GNخ.	A A AR? ,EՂJ-џQ v16ia @6a @
ajR `g\px}{GBMK'߆q    H LM? ̲~_$`j->O}'	n:~;>ka @6a @
ajRGH 0KC?~c$io=+	ai0  )QRw `#IS_(e8lA A AV+, m?Io(}-	60  0  05c~c;#IſT~?Fsa @6a @
ajZS_Qʰ `3ZK)u$ { l Ī{;QQIFck4{4JJcbb&&65іzf6PQAa (0\"0}}c\f3zk]x~ϓÇs4h  xy{FX}ُH bxuI  (A P0b>}4 X wMHc'FWA P0 aڟ|u `uO}OFT}⧧{! s;A P0 aՆ?9x @ƨxYFRM-YX    IDAT l˰j/&<0 4a @4 	0NH*O0wE	   (AFo> ,IJH*:e?x
KM_A P0 a٦F#jEu9jsb <αogA P0 aW}D X`L9ip} <=wIgA P0 a:ǽ= z$#z|0Է}=QJa @i "i[hf Zݏ~)#ik#' 3лp*QJa @i "iԫo8= IZ}~2G~0Cߒ(%0 4a @4uOOE2αIҨo9?5ZS  E0ӨW  Hg?#i_OYo<3QRa @i "io]}T X,N|cGd=}O5 f{_?J  (A P0C[Q`%4u>n#Y=RRa @i "iiD3>. ,ӣ5$$i<ksѴ~0KKA P0 a;e Yoӿie)-0 4a @4.pq`5MtOw1jQyi9|%e   (AƥꀗO (L#ߔ4-!ן`h-)}RXa @i "iuE Ag!I#>[B
0I 1 `qwG Iw_IIʣS lA P0 aOt Q}WlѪnu	4QwJ 1 `qkxD+NIX`lgSJ  (A P0[?}l HNIʯf >R3 Jc  LV}l 4=$Iy.Xy9-f   (AƱo>: d=OI%ѿ' ֲ1f   (AƱWf FAݏ $iZC' l˳=Spa @i "ik跣N7IZ?3ן`t3g   (AƵ>> ~cߖn@KjkEkgk
  (A P0k V' do~הA P0 al`Խ~Qa2wd?Y X@Sޝ)=0 4a @4*0j(M@~4MO Rݏj9g   (Aƹ} QةMOI[3?1d?I X`-秿sd   (Aƹ#&0ޗ4~z HgMGa @q "iܫ40(I/ ,f8~  (A P0{s60%,I[ߌ{ ,-rWG?  (A P0{~/` TW!ZwJoIzLSK~8ُ Y俇4A P0 a[f% @aMT{=7%Qo8= @I 1 `I{ cbxϷdK*%wd? H2}H?  (A P0MBժ"^q`L4o!?kَѻcD$@zk'2 Jc  LR ci?c~=%R𞫲> #}ЫKqa @i "iR	qoGänji"uEI  (A P0ML+Mos`<*Z˟.&WF}׳8 #wއOz|a @i "i\#Qw4-!z|(GQ:e)=.0 4a @4Iu>{G
1ִg;}&s#8 .JO 1 `jji4>V  z|,&YϏeGSA P0 aVg+ &ຓZ[{MDM= ئ>/oI 1 `I} y|mҨ>_E}7* c-m=0 4a @46h0)&WIIRu˧υ?	LuOA P0 az}`4c~-'eV5zkGGq2Dscza @i "ixXъh-fNZV<+z_Ѵ> ˴  E0ӤVoZ`B1:wM-)f1=?Ӵ  E0Ӥ=	WtvT_Γdv;Ǐ =v-i2ݦmf   (A&ω90z]Hj2Z>20 4a @49>P}F_KIsjswE=G		>9=ea @i "i#@I&OIJ3Z[Muz  E0D7$o>f ຓ> J 1 `Ivy1Tu/W}K7mv ~T(  (A P0MzWD@zc~~{QU]h3$ P߁Ya @i "_>j M_o·l|bp"} 
9C(0 4a @TBݓ,_a2ɪ}Mf? |^2 Jc  LEbhg7 xu9њZXOv G<0 4a @TJ>n M1g35KtOo8}7(iJ80 4a @TJ#ߘ} i5GbpQ9-NX{2Ѧ9G jxL*0 4a @TR{>r 0cGGߡʩE=/y~ c{ߤ?5  E0SI߳ ^݋F?ֲߧZ&zmԷ}=bXg5G'ߥ]a @i "UE: i?4''3[5]s[<|[ [Jj 1 `?1跣~~;V3l>MѻcQoXQ `^fA P0 a*/{Q=Q_yG~8 ]}\)0 4a @T\SKb ,{bp8=[]>ܚ#? wA P0 a*>z ?9Wվ/JOLv!)Gk#a h99e   (AJl?A7@m'N6jnQZ|w۟=WE:m@i=0 4a @Tjk} `4ӣwǣ?ꀗSsh'ѿxU7#_ Ak 1 `R|7 A7ozÚ\yT.Xt{{Th-!}=}䛦L[mϸ?? 3WoZ{]ۗA P0 a*> 0^psԷkEo=9>>5Q9^ntOzWP./G}>!gO &F~e   (AJ}u/MC𞫦oogם'LU|QtlXû]3ז?sV: (Rh-1n  (A P0ܖX"  mMzma @i "W}&  x{QSwzma @i "ڟc   cep  E0{>   06GB]^A P0 a3{_fE   m_Ok2 Jc  LzF%   F^w5o 1 `&egG   iÇn;{A P0 akf}$  `d`]A P0 aҏo>'H  Hj:Zk]A P0 aҏ#	   #ip(ޮ  (A P0_},  `Qwva @i "I{dK   )k~_d   (A%	   #_ɿkA2 Jc  Lzru&   ut-70 0a @¤'W{p}<   ]~Oe   (A7}<   k5$  (A P0iu>   RuO60 4a @¤m߄  e;͵ 1 `&m%  @Ok3 Jc  LzVMc
   tW?3^  (A P0]}L  `Qq-Na @i "IO]jhz*   ,z0ǵ8 1 `&=}o}T  `Q.x=\  (A P0|ep}\  `A5MQzA=\A P0 a?1  c70 4a @¤>M   Nw2 Jc  Lyk,   ,n-~a @i "I3}d  `ZQ{?0 4a @¤5c   r2 Jc  L]Sߓ}l  `4GZ[}[9 1 `&Ͳ;EȝG   Eo2 Jc  L}   ۭlj  (A P0iU{D4퇳/   lޚ=  (A P0in/3  5o 1 `&ͭjGy$  HZ 1 `&ͽ%fa   f}s{3 Jc  L{>?Mos1  YwjFa @i "IW}  `ƚG֊  E0jDG   f{{  E0ee   xZ{F'0 4a @¤:u/8  S|  E0Ggg   ئ  E0#~  'k>wg^a @i "I;>   $~ghf   (A4zUp}  j}ghf   (A4R  _:  (A P0i~k~K   #i?ժ  E0?}   z__wdva @i "I_un  `;b;F;0 4a @¤a  uO|gXA P0 aT~}  (P}ǺhM-Ik3 Jc  LZ|T  `h;#.  E0jl>   aOa @i "I[oc  @!CQ'0 4a @¤Zk4gu   
;߃5^ 1 `&-|>}  p_e;߁5^ 1 `&-B{>;Mwgw   &X糿e   (A8Pq  `B֟~xf   (AH-f4ߖ}  4*կȿj,3 Jc  LZ'+  0azNw5 1 `&-bSKbx  	1|hC|v}WcA P0 a>W#&  0:a=WA P0 aWxF  `rVA P0 a>5u?  0?0 4a @¤}  Sݳ&^  (A P0)jEy$   uEk5 1 `&[G#   q2D~_w@O5 2 `&%bh31   2Ij_zP5 2    fZ{&Gdh ,*0 ջxnji*Q   ;&U XTa @O:ÓTzv   6&5ex ,*0 աO$QtV   tꀗ[5n8-G `Q EO~6b~$   0b;& A PޚI_w#  RoX%UMnߐc  "tNzW'I؞ώfُ   F@WDl?G `Q EO~\?~,   0gUU҈  "t/\Io(   @zH-x/Q Xta @t'I}   "Xuw Eg ap$=ed?   H=wRQf ,:0 K$U{??   ,H-Z˲ A PA/ZSK?@Izr3ޟ   `Z>g*u'e ,:0 _JVZû~D   zg{j?    (FJk#ac  ToXOEjq[sİ Xta @1koG(Ilp1ُ	   HS=/K{G)G  A P?BIvժݢ|  =O*-G  A P[?BIz'y  y6αM R Ei?DIz꛿   `4^Mk̚wd a @Q_$=uՁGZُ   W3g~32xY	  Hc nu(IO_e?.   NL_ܺ7  1 RQfbxߵُ   hxwmc    (p}^AJ/G   kE~T-!    (N?(%iF8"  ,uʮ} @*0 8K(%ifU{=7Mwg?6   Rg Ta @q?LIY/Qc  h{
ojI4o>   "?$͸3   < :G%(    (c?NIr5  IDATyWDݔ   `z|4(m' @:0 HMؼlTf^̿~t   wϋ{ZS4ޛ}$   jTfԒo9?  c4j-2	}$  FA Pg4j7  0wEGշ\}*  FA Pz_J   DDk;(? H0 ֽp*cWxF  hCG/;8X  0 hGvL`%ivӑ   yMwGҏV  02 uN~wG+I{{   	[O H1 W{M4~   wl/h  0 h$ͺ-i=  (B}:\?}4  FA @Dn_Jُ  7|নznPzl]i}?x  0 >m$ͭd?B   &V}4ڇ6'=ޅS `$ oҘVbF0  Bh9ߥ~<}B  FA c?fI[0i#   ъW}<  FA cn˟AK  Ĩo>'ZSKzk:  ,0 '$ͱ;ُ  7|{Q{ĦD}Ǻ# 0  `y4Z4㖤9>uv  `l5>;iku# 0  ͗?nI{s>  OMߙ~VOEy$  <0 mh?rIڎ?q9ُ  ӿd;>"  c  `!Z+"CUh6ߗ(  Gkji}NZS"  0 пS$ͽϝ   Ԇ|;Z+~V)  0 >$ͽe?F   FZQ~EMjv?\}L  ƊA ~^KZ{u  `4hn6_o) ;a  30eMl`VNC   i{٤mM 0;a  3[<#=ُ  һw5宦h1 Ka  35F496I  0)]Yc	 2 aѨymG1Isl1;ُ  TNߏhZSd f 0K7Gkn$ͩ'_MwS   E}qLjSKbpq ` uy?IS8i%   l?~'UU `" `IK?I[K~   ,n]LV>}J  &A v}e򝢾  k=0iP) (a  ۩?I[/@c  `AmK/i[u>&    `.Ox&inu>;:1   V߻m;ӿ e 0OzM2  4'DkjiKZVd e 0zGY64[~   ̛Y--!<4  L40 yֿ곱ٿ}+]>/;!   mx~^=Kzb]# 0  {Dkd4ڇ!~   YV"~%=j𞫲 @  H}5:$ͮ4ُ  YkGПOWIOs[y# P0 4tOTnfW{e?>   f׊Q~XQO @Q  Z3:㛤Y44~z   ̠cߚSb P$0 Eҿؼ.$ͬj1}  ;G>!t    `_oH('ifUh   [{{N?|_P <a  GeyjiG:IO[_{O  'ww&G|cv     K:U$=}s>   xޚ=JҖ+u  0 LNtGl^c;IOʣ   ?$FEG '0 }E_'i-fw|#q  nOGkjIIEo𞫲  ` 0Bם_QO֫}q4~T   \ʔ}7Ro:+(  4  FMK/H'ɵ}]4O
  0ND*:ψh   aws.0Lit  @!J:G%6 3a  #<־/N(uOs Wxf?3=}1    `\z:%M[G  `wh}]_4Ճ?  l'0 q41umtNؼGa)>T   &Ж?7ikk Ga  ci?oէ~96GDȖ_~   doӂ44ڟ]{u:    `B#zVI	U+w=We?  	P\c0k~67Mq  A >z_}ltNzWVdG^۳?  0gv}[H7 H` 0è6z_qRڇvO  VFko=G9'y+ֵT?1 `D hz0FCs_F7GkS<oD  3ްF\WF}n;1  =ɑ    IENDB`PNG

   IHDR   F   F   q.   	pHYs    {Rk  qIDATxklEiU`L4Q	j46b|4>PID#@뵥P(Z<ZRKPHEPZh/ݝ}%|Jo_2I?u۝y$)N8qR_+i(6Lw;miZ}~)}jaP/~x50ڗ/ËZp }$R&W h@	K]^&)?M s"lϾUa$e̎bZ2G1j- )_N멳D`#FDB.$`g@$:r%j_^ ?V<EwYF9w_L=}=(6Z {gjե`|aC(F0= 䬋]gXJ.6vt&+Z2*X?q(gA͛IŘIavGʹxZ:W@-{bRZ+r̈sC:h_y9l[XJvj?415Zȯ`Ex=Ĩq  qu1|Z&m9R(#"%xb$41VnqSHQr0q&ʚ9H!%#:u M8bmѿzMoG~41|fbZ(>6B/1!ܬi)l-Cc4oG&,.pVb;:O3}^qĘ-hb&qhL?^	֌V\bԏnL-_p|ߚ.X');G`S*!;HB{/<`spx$N6DODL{սjcӁv!Vq M
xFXeؠb>gMa@Б܉Qrf%:`mV^q00v-yŤ7t/.Lq7#h1݋}P3aEdwK
`僫KLQݴ gKh]=s?u,Fxa.7RHc	8&,F)c(M ;	[ꬍJR4/#qcٛs|Iߝ<mT`֩&m+1*mG]HEX''@௎kDŨ(9/&șHWw{5:E6*Y??)Zy_Zw=U<kF%RL1r,eGOkZY A$umxlEjOAgJ_H&O)iZ]*;տ#(~8}Ҳf_wJI'N8Ҕ/mP23    IENDB`PNG

   IHDR    p   z    	pHYs    {Rk    IDATxwlwYIBU<JS@PT`,ȫ(GIvz=!H%Nz%dgMY!@)SY\\^zx̺wy4  YiD   ,-  @f,    d   @f,    d   @f,    d   @f,    d   @f,    d   @f,    d   @f,    d   @f,    d   @f,    d   @f,    d   @f,    d   @f,    d   @f,    d   @f,    d   @f,    d   @f,    d   @f,    d   @f,    d   @f,    d   @f,    d   @f,    d   @f,    d   @f,    d   @f,    d   @f,    d   @f,    d   @f,    d   @f,    d   @f,    d   @f,    d   @f,    d   @f,    d   @f,    d   @f,    d   @f,    d   @f,    d   @f,    d   @f,    d   @f,    d   @f,    d   @f,    d   @f,    d   @f,    d   @f,    d   @f,    d   @f,    d   @f,    d   @f,    d   @f,    d   @f,    d   @f,    d   @f,    d   @f,    d   @f,    d   @f,    d   @f,    d   @f,    d   @f,    d   @f,    d   @f,    d   @f,    d   @f,    d   @f,    d   @f,    d   @f,    d   @f,    d   @f,    d   @f,    d   @f,    d   @f,    d   @f,    d   @f,    d&|+.?u\jR|T,khuxJ~S	<ugh5g.;` ɩϤob*^M.guRs_No6o:5᰾kRg_6[:I㿴TO K?cX9qy}}opXYQ?kXږZ_49] 7Z{nYzlXO 7WQk?H[Ϫ8|>oZbԿh~ UAjRHI>3టg}5 cMKYS;jyS]p_U?@um:?zRYZ;FyX 7~6A< TWټ/}}L[Έ] gl͋]ۼd \sKjnI)z[ 9@? +RsşSJ{BMpSV/n?
@n>5+^)E7f_/XSc^̭&~"dAh	< 8Y'.I OW[jD7_{l|_ rU-D" 84V:-v Ƞ{/S#_0p-;Pj\{OY 2TLRyFxͭ_ ;1u;S2 @]TFx?2su[R^@녟oj׻W4k_ʇ@zgl~ƩH	0|o_Ӛ dudYFxkwڶipq9 I])ipus\ ;o%| r7Qsӗ{jmۿū^'i֧Y 9;Rꝺ:T#v9O :2cF (B5jn:<N#w/D5]/kժ#f ~+R٨Qk<=gV-_'/; b	!|T
ig`kwp5{ T瀿
?#it[ G_k>p9 FA5gKO? vUZ۾>"g o	Fj,펲|&˟Y6r`Nzo~n-_'~ 6wyGUW= 070z_٩*E?PQߞ_~t9ۏp?Lk9<,Ucѿʍ˩\ss:|,<UcIs][Sٖ= 0/eUb7y{?LU랸<zf`An>mUE/F?Lk^7{VG6|UcQk}usRЭs
 Lm~1Ucv~~T7ڇcS8t:gRs?ύaaTM XTݣ>~ު(578Am^-Rs׆j,xI[4%1$o/_	띶I,e=l ћsX8V=7>z D}b8zn={ c5$jno;a焟j;_ ɫff|zl=k 0;w-on:9Vc^Y 1 I>V+MIꝱel*u˒Z >AߜҠ=[ 0AHY u{gG ̾~;5~M٭4ig	 *cn5&cKe{M,@3\v_yX@2+?՘sGk 9Sgs8jsSMѳ UF/?ӕptϿ6 <iTџ ^+5|Uٮ?/+ {j<mY/]ߕRYF
 G9L~ƫ ._'n=+zL vW+=U.C.z> ZfYƓjT%z6 +=YY.G ^{j<a-p}$z& 7}ٯCY- F{?{lns)ѳ  se*;g9 tXF`s󗏿 XZ{[eU6` Vj 6|uJn YLؿp w5X [6A/}F_ {} jOw5 67i29^ 'i;;Bw\T>rW5 <o	׬9򟢯o`T>tkzV\Կl;{o'WqoKq	_}wuǦRU)MBq\ ^}yQ>4Կ`= [RsӟYׁZbjƋcmSS^P )_[-~!_^qQ_gg}lmsG>범atSsWVppiї5d<<~{{{!\T/;=)dwV_dZ֎}=Cipv|k*V>uSkwY_I;mv!(2v`＝gy_Ooˢ|Z^j~;iZ}&8|֗W,/7TDwtM^:>@kn;	fZ-n4o9+Y%iX??VdS7N-_>Ujtѽf<UӯG_P9[o;y*mGѳ\dTmE_PeڻV֪?R6~?`sH>u%㯱ssiP,|L8^P=fkѳS]ޞ\Cn(=E&bݔI/H~/|Fmg_=ʇosKeKS斯V<NݩsS|Uc"7E_P	>>EU~5}e9ƎMgS?YeD_!0F=EU~ui
3a4]>zGkJnV>Eͫї)+wWS39voOltc9-j^ީQ5\Y{Ϣ&+}{< A}cq_* ._ǇZ}SsϢo獿{I>?[e[(Aw9b?
fsY};skB5Hi^N$0e{'J}457,j^eE_E>kgY_IC>Zۼ.|ї/,UGb᳧ůwp0J۹ݣ?ڻF\ '|9%;gT,_7|qnpOEkHJݓ6H},5W8|Ԩ88,	>o{ҊRz0?.N0x5 `K~1|?af_n:9oS+>j vd*=᳦h:ףH2T>x>yPz\蹀Eeӏip)ї%5V>Կ=?S{<)ѳwfskA=ߍ<&n8a|ˡ~L.V#uJL?~/z4<8ٰ[tj(/vE,*/"[;kRm7!@ݔknNM~:|T:M%,okt}(5z3>Zۿ)|T}鲄4߂小֯ը|Y G_Rs_ϖ*gF_,Ӳ2`̭TJխk@e{Ϥ.oO
Ȣ,û.UX0{JŪJnٯA5k=Y`s7cM~-|Tzgl}Eipɩwڦ}_o}HEїLC]tO\>SQ<;$4;o'|nO
Ub읺:zaAvRj+,ķ`9K\вUpkt^>Og,Gz^\KE@_o<xFv^e^tJꝾyUϫ,pT]CZZ۾>^+jGv5{_8D?RD8&T/5gIy=ߣ/4Կl=sR9ϕT6`_7`^Ckٿ\פ6}Y"-f~0{Ҋ9R^v~[6N}R-S砏V?KEyEj~I,)zj;/IvM#1Ij U;{9R57~jq[{?JEM{ԧ_`zAjm9RJrFꝾ٣O*jL/Ձ_~P)󖯓7fNH[NO3N?[&L/	!ƿ]L2iu"^sfhxk8|.-s{>//QpPUc>C}n1R'>JjT{l%1fow]S쯦aOҲ6`//aKh&ygd8Hû/Ogk_=iYpPE2|~'jt/Y%5\ 6,nfV7cS}nOZo3 =G9L#IRQpPA:|~$I* v|k9I*.ߢ@Ռ>[=;$U] g9Lwّ$ؿh&gG.N>a2N*V>;$U] }D7>7$U^ S}Dzgl>7$U] _}:}<|v$I* sYk+#IRQ?>a2^*6xVHTTu9Ldxs#IRQ{&ҿt$;o&;yeHTTy9Ls'FSsF+sHk7ύ$IEr9LF`귣s6|f$I** Z?<*~n$IZV+sF`kD0Gύ$IE}D>7$^ @y_{HTTy&;k$xG0,I**L-ݣ5<tbHTTz<9LIJ/'>a"#)|n$I* N4<X %IEmsPTTZ }D:G~*|n$I** ^Wy@IRQfkd&7x9L(I**l-}D,x9L	IJ/W}D{HTTz&=qyHTTy|&;}$xՑ9Lws#IRQ[TMFbF=7$^ /zy\{tHTTzh&2$x.9Ldxǅs#IRQw9Ldxߵs#IRQmsHz |n$I** yy)TxFHTTv<e&6ّ$=g9LgG-,|oHTTug9LsGgG>abݣ5|v$I* &=iّ${rXgG`kE0ώ$IEem}7>;$U] [2,:|v$I* >/,#IҲ.);9L#IRQ|&-#IRQpxUg9Llvk    IDATtّ$8&濄ώ$IEek}zn>;$U] }FmHTTu&6ّ$=qyY]HTTu&ob:#IR%}T4|~$I* v}g9Sik#IRQkqJϏ$IEb8L{GeU\ G}$,/-|v$I* !,$H3 n=+,>;$U] W}a*V>'|~$I* :8G`>a*>>?$U\ ;M9S$8Lw#IRQG0uǆϏ$IEbg4D0Ϗ$I˪ dg9LnOŊgϏ$IEmE0֯I*.nMU$;ss=#IRQ}T>?$U\ i9SrFHTTqlmsR6I*.ŪS*e3$IҲ-{>rw9Si#IRQpsqJ>?$U\ }Tzg5|~$I* N]}T7>?$U\ ;}9S)^HTTqlsSgHj~8ο>C$U[ G퇢qJ簏Ϗ$IEF0iϏ$IE@W>?$U\ {l}T_>?$U\ GJ*gHj`kwF0.!I-{U9gHjۢqJGqSG`mqJz |~$I* vd9Skn$7pZ>C$U[ _SY>C$U[ G}T>?$U\ 7}Tw_>?$U\ {g}%zY3$IRQp
PU~%|$I* w{wSw3$IRQOE0雇ϐ$IEQ;qcGF=?$U\ {g557}YITTm3ϐ$IE@	LuO$腾_qpITTmU>xc9S>p}HTTq8L,Ssϐ$Iͪ-ݓVD0>C$5 @S$Y嫢pZ}gHfQes2$Ypp8Lg8HŪϐ$)* *vyGI`簏G0Q!IRUrlm3ֿ`$]%b3R귣qgHrFqa9tSgHȶ.>aj~%|$IlE0>CFUvl3;g$5`sTq3gHȶ.\}T#X^IYV8LgHȲJ/}!$`{ߏ>ajv
!IR#* 6W8>a*DTUpqAV>;|$Iؿcm3$IjdWq'u$5`{ߍ>aj!IR#* 67zo\>CFvU~5sS_k=CFVb__1Sk3$IjdU-1_>ajc=|$IpZgHȪZ,Ū4D0gHrA2ejn3$IjdSm_>ajAIT>ajwIT뻢p#gHȦ,4E0r3$IJTp w^}Ԛ["|$I,ؿ`3gHȢZ-#1N]>CFjlm36$5V`|Tv>a*egm*V?GT .kMD0ogHԨ}[ {o}:GSIv`E0{ϐ$Qj 6|USseIvr8L/
!IRr\uD1Sk$5j]-	_>ajϐ$Qj z_S\$5j]-F/
lޟϑ$Qj {U9Skm3$IjԶ.>ajC.|$IV{ԧpZgHԨm] [;zS~AI`3S굢qΠUϑ$)ձ.BzV1Sk$5jYY_>ajc>CF-9cg8L!3$IjԲZ/m^}ʇ>CF-8,>aj-^>CF839C3$IjԮ/ݓ6>aj3!IRv~lg8Lmxy3$IjԮ//I,q>GF8j8L{gHԨUY,>ajwI*{pcgHԨUY,]}CX^I)Xss$IJu)p _}:$5jS6`pZ}gHԨM,o|"kn!IR6e }Cs$IjԢlb:l>aj:~$I(pY#nNS락mI(w36$5jQV`{F0a?57zAI/D0/>GFjU%uO |$Iʗؿ36$5*_v`/F06+>GFnl3極oϑ$Q[ U4E0q?GT[ 5΋poϐ$Q\ }CX^I-}üv9$5*[`k7F0/c>GFer,369$7}փXnIO߆K+v%w3e^H$IbG:}<jrFJuw/oџ#Iʽ?7|'^I_{o6;?w`sӟY£໇ϑ$TsnN㿔W➉^{go;;\Q[hW9@IZ6xfj{gS}+S*yn/5hY/+^bsIR-?,kv[-{Ʌϑ$Us{Wd_q<9/߳$O8,ϑ$r͍^ʽT>rwk`=Xܔ,<|$iZ~j{S,^ 5΋v>GT-ͧ?n?}rau9ŮS[H-g9UGϑ$-Ju0ٳ ~}UVv߯*z$i=S0G~}~Kkwϒ$֯͡});.!pY#n<1y鞸<|$iz lx%X wkepis$)GۻdT>xSK}<_FjkgK>K2iSkwhf`xUݣY F_0o}4|$հֶoHo|"!o??A7%٫\ssu;+s$kVû}]@m^X$Us{7FKg繷 ~џ.`~r_ѳ$iF[~uZ]k}Y5,[п%I?;}G뵢_7ٹ>,3׿k$ijv\35k\{mgI5c?7~+Jz\G;skmY;*1۫-_Sf|LJ@Ս~+=KVn|n78;ך16`>K%oꝲQ\|*k_>ʇo[WU%I?_y\?	%)۞s{A3~Y W/F_0o댞%)5_Q~EUW>xS,IuO{ǝ
靻\ǵ9)[k7ϓT6|O~n,G
띱euh'hxyѳ$Us{;j|S=}n;uk,OCPuO
%_vw|n%=fg,?BS^jnyN2=ӳ3'xP6y5s_ϓ3sȣY r	b9SRT{ >I5BՕkLuIZV>;z`{v<IOu$-V>Cvٙ-	,w;|ŪG欹kgY 륲ܟUQZϓH9kn3,O¬*U$-F?=a07A*>3?uOZ1gf[>Ob9Ss2yyltr<I
^>/TΆwO)aOM^>SB;s9rF<64㢹=0:C<I]CGdY 9홅7[$-tr*_k<69,~'57zaLIY]ѓs;uu<6=@[bn,T?hgJZ6xVJ0z`N|!~fpan.̸ϓPy]Huyl9ԿhD}$+>SBwG
欽{gY P33ϔus3,sy~ܟaq>SB4P=TEjyl9V>tk<<s/D4:2z`N,s~s{:~8|6|Q9uY<>ɬݑ^U4DgqY XkY*tSsKJ֎o"췀 NPι?0:GcLI9oG{gY '!san<)|i띶IuX<>u?0JDOYkw NPkن
&n:l==>0g~6~npsa(~	kmсC<>(us%MrQ%{
'8aݣ?}-ꝾY\IԿh豁9\{t<Q	uS>rw*6xflIsmxߵcs;sy,| ΁-i57yiJe=20g,,Y 's>W\jiy,S9&{a֕ejmْ{DOT0,<h[zg*w%=GpP<I)ܯ 1f.oɲ NY＝&
ElIOVU#_O<Y)ɮY_4jx#ɲ N~IJp+fp[&|nBٝ)o ڂ;{ْ_XsΓeG7jY-Rs/鱍>LUR68_E/ϗZ۽1z$`bN8V>'~{f\Y3&m9c葀j<Uy6ɯ
Ρ>_R{TBtd<Ey=?1Xû.B)}0z`*>?OptWT@{1# &o7+Y [:`?>|1o;w8:gLyV[TU .@Orz) 5ї?Lߩ, n R=ї=L/e\783npY3Z~*}T#X^=M{R"fKU*xR%,/Uug*wFs4,XU砿3ջˣ/s;o]50ʇoKņ5ճсTvF_0r26b\}`WTCUP_g
d\6|_?oUߖp}uü	f\F_u7YSZ4s .po}fWT@>oGnE]4|U<5B?[*aѕ8S} umxߵ4IEhx󿒠>o[}Cve\'|ya&ue`M]W0,΁I .Bm_pW̸SsKNժ4G_ps5IEjxUtU_̩b7|^{Gefxŕ;u]YPU[4Ṱgk,Tk߈ai۩ӯϞf޹;D_{?|&X-_'}M*Rhї(,nI .b,a?.?VjAyAE|ou	!zm>{S[oKMp1[^*{M=3Z3G/GX4ͭ~>|Φ/3ڄAT\?
*kDX4{>gf\Y	qG!P}V*E_zgl>kf\V>ǋ Y]nWaJfۻm,KPQ5z;gQiЍ`ѕU;X ޿}Bn{n<jZNꞴAJe}蟿s#R5;U7kP	aO`I7,KTאָD_0z/gRS+w]}UY7,KTkG_0;Kͯ6/d~7,K뢯YoYNlj>?%0a\z'fa/; >[^!طW>'|p	k}na&45~m;s{c-K]IegT?Y瀿JCߋD`&+׿?ukfWY޹{Kx޵\{tU3,MŊgBd\|
<+KUKS|<N3op㉏ǟ9knͥ)I>n\:G\V}N簏m77'W>xSn[ex7~	n:9vyG֩6KM׌~zauO\>0џWgʍ>_ٿG*gw! ]s)orUjn=?ޫ=5+iͧ~HugzZ~4Xyy^,u\5uL婹g;_Mw0oe{M-'^+,ꗤoG_P/0?.upk֯Ios\}X`s0E_P_ΑEBR{޹;E?Pk>:b{mmA8z';ixǅrKb^uC  nIDATukqpw^G}:v}gwoOޙ[5lHA:MHY gѭY
~w~vo= ._'57}Yjm}FU/OP,zGX,3PsӟPf*ܒw]6~;vpYSqSq^eOLw&=, @a?5`1 H?r RJ
;଴|_( Z?
9=ߣy ֳ8C57za*;G_ ΁c V[O  K\sK*V<#|X,3an K{8% ,yjn` `I @V'.?2~?WG dM/?09  Y蝾yY gN;g I_/q{ jw}DY1t zSsWcX gYD Rm,3^sW4E K/Aٯ^c ;m=2`jm󺔆YZ(/?# VE Bz"}CJ0zf zB<4zn :G~*</f `jm~ SwM*V<#</f `|Jjx1#Y +Vk7-  Lhpgx1CY +X .o?XZo9_[]XֿpyWvN~6.f,`Eknz=sgv1Y +\F ̬=M?X᚛45 3bF V=_ 0s~F3|N*=g 03CeuY?EeoFS|4yp=>e]s׌F[	a4}==s kO~&h84:W7G N8,.*R{wF?WsW- ޫ}FͿI+g ߝ~sߏFo0ZVoE X2=bI띾k&>/g ޫlW1~iO}yuip3	 [i=i~?W~)~;z4`tO\~UlhlJh0 녟EkG?|`(-`<+/ E}dNW9CPZZ3r9 :6ͧ8ҴQ׮F( ,Ekn򔆃\ g~7~Q*5  ʇnM/	?W
7pZ}0bV`azӢNj_R+ ,џ?G~q׳&?GZyy}kE|sxwp^_jV0 U2~j;I1Ϛ[:~I+X-NKY۩cii!ꝷ>? [kR`-|W ̺a3,jPsWkm?c}7`f>,'Taj!VEEAѦDj!-ٸiEwRfd:ΨPCfC$)$8TJ)1T>_<',y{y>|9{9+1Ó<n ~n3G.|ƷT'[K0ݟ|x f
~` ɿ(2zsD?|[M߿ 0At~{ckIf=ox3u{Ylk٭ޡ֒Lw盿sKYt[ fͷ%z߸硛Yr;ſnO𥏕fe>S)?8nfje/[xw[_A컮AL_ٍ_KiﾲZ~Is5> 'zҾ,dY>_{絖a\eT:?X6Ϯ+源 ]:~28up9 ;s4>_ֺ/}AJwߵeMo/çrQb`M! ]o-tMy|K2 jؾ'4;_ _-W63.]SĘfgx&. yO{UepPH wJ,;.~LCe<K%Z/gǛKqצ |'KO?ii/ wӽSe[?+mz/Lٟ< ӘWvE7/){/g]-, >TE_. \֎K[Ӵw_Y߼w.< >Vz|v_UD 8{tӾwhk>RM_M+=o@0K}oӾ{3wK\?Pzrumi׾l f~.wm-#J7J782zX_G_=  \    #  @ 0    #  @ 0    #  @ 0    #  @ 0    #  @ 0    #  @ 0    #  @ 0    #  @ 0    #  @ 0    #  @ 0    #  @ 0    #  @ 0    #  @ 0    #  @ 0    #  @ 0    #  @ 0    #  @ 0    #  @ 0    #  @ 0    #  @ 0    #  @ 0    #  @ 0    #  @ 0    #  @ 0    #  @ 0    #  @ 0    #  @ 0    #  @ 0    #  @ 0    #  @ 0    #  @ 0    #  @ 0    #  @ 0    #  @ 0    #  @ 0    #  @ 0    #  @ 0    #  @ 0    #  @ 0    #  @ 0    #  @ 0    #  @ 0    #  @ 0    #  @ 0    #  @ 0    #  @ 0    #  @ 0    #  @ 0    #  @ 0    #  @ 0    #  @ 0    #  @ 0    #  @ 0    #  @ 0    #  @ 0    #  @ 0    #  @ 0    #  @ 0    #  @ 0    #  @ 0    #  @ 0    #  @ 0    #  @ 0    #  @ 0    #  @ 0    #  @ 0    #  @ 0    #  @ 0    #  @ 0    #  @ 0    #  @ 0    #  @ ?[:    IENDB`PNG

   IHDR    	   VAK   	pHYs    {Rk    IDATx]u}Y`-biblZmkڦOhZ55mzM{iZpѦ^i˃J!DEE)`5V EX<?|sE?{9z%;.̙    :?    B    !	      @DH    "$       I    D$    "B    !	      @DH    "$       I    D$    "B    !	      @DH    "$       I    D$    "B    !	      @DH    "$       I    D$    "B    !	      @DH    "$       I    D$    "B    !	      @DH    "$       I    D$    "B    !	      @DH    "$       I    D$    "B    !	      @DH    "$       I    D$    "B    !	      @DH    "$       I    D$    "B    !	      @DH    "$       I    D$    "B    !	      @DH    "$       I    D$    "B    !	      @DH    "$       I    D$    "B    !	      @DH    "$       I    D$    "B    !	      @DH    "$       I    D$    "B    !	      @DH    "$       I    D$    "B    !	      @DH    "$       I    D$    "B    !	      @DH    "$       I    D$    "B    !	      @DH    "$       I    D$    "B    !	      @DH    "$       I    D$    "B    !	      @DH    "$       I    D$    "B    !	      @DH    "$       I    D$    "B    !	      @DH    "$       I    D$    "B    !	      @DH    "$       I    D$    "B    !	      @DH    "$       I    D$    "B    !	      @DH    "$       I    D$    "B    !	      @DH    "$       I    D$    "B    !	      @DH    "$       I    D$    "B    !	      @DH    "$       I    D$    "B    !	      @DH    "$       I    D$    "B    !	      @DH    "$       I    D$    "B    !	      @DH    "$       I    D$    "B    !	      @DH    "$       I    D$    "B    !	      @DH    "$       I    D$    "B    !	      @DH    "$       I    D$    "B    !	      @DH    "$       I    D$    "B    !	      @DH    "$       I    D$    "B    !	      @DH    "$       I    D$    "B    !	      @DH    "$       I    D$    "B    !	      @DH    "$       I    D$    "B    !	      @DH    "$       I    D$    "B    !	      @DH    "$       I    D$    "B    !	      @DH    "$       I    D$    "B    !	      @DH    "$       I    D$    "B    !	      @DH    "$       I    D$    "B    !	      @DH    "$       I    D$    "B    !	      @DH    "$       I    D$    "B    !	      @DH    "$       I    D$    "B    !	      @DH    "$       I    D$    "B    !	      @DH    "$       I    D$    "B    !	      @DH    "$       I    D$    "B    !	      @DH    "$       I    D$    "B    !	      @DH    "$       I    D$    "B    !	      @DH    "$       I    D$    "B    !	      @DH    "$       I    D$    "B    !	      @DH    "$       I    D$    "B    !	      @DH    "$       I    D$    "B    !	      @DH    "$       I    D$    "B    !	      @DH    "$       I    D$    "B    !	      @DH    "$       I    D$    "B    !	      @DH    "$       I    D$    "B    !	      @DH    "$       I    D$    "B    !	      @DH    "$       I    D$    "B    !	      @DH    "$       I    D$    "B    !	      @DH    "$       I    D$    "B    !	      @DH    "$       I    D$    "B    !	      @DH    "$       I    D$    "B    !	      @DH    "$       I    D$    "B    !	      @DH    "$       I    D$    "B    !	      @DH    "$       I    D$    "B    !	      @DH    "$       I    D$    "B    !	      @DH    "$       I    D$    "B    !	      @DH    "$       I    D$    "B    !	      @DH    "$       I    D$    "B    !	      @DH    "$       I    D$    "B    !	      @DH    "$       I    D$    "B    !	      @DH    "$       I    D$    "B    !	      @DH    "$       I    D$    "B    !	      @DH    "$       I    D$    "B    !	      @DH    "$       I    D$    "B    !	      @DH    "$       I    D$    "B    !	      @DH    "$       I    D$    "B    !	      @DH    "$       I    D$    "B    !	      @DH    "$       I    D$    "B    !	      @DH    "$       I    D$    "B    !	      @DH    "$       I    D$    "B    !	      @DH    "$       I    D$    "B    !	      @DH    "$       I    D$    "B    !	      @DH    "$       I    D$    "B    !	      @DH    "$       I    D$    "B    !	      @DH    "$       I    D$    "B    !	      @DH    "$       I    D$    "B    !	      @DH    "$       I    D$    "B    !	      @DH    "$       I    D$    "B    !	      @DH    "$       I    D$    "B    IAM}F?zv?VvT+E]K5i}6 @lVl[n?un`Ckma-EH__zWz=h[zV˭Om  ٴ~_keޓwokح5/=Im~[muZ  |_3-5o=mGZGg?l[WOu  xebB{ћj=5yN|HZ˫6?Il{o?Z{S 7Vk~mfu/=pUMGk۲!icbV}M¶/0 -c<Z:yTsgjr!i{[+v?l)6֧=  QVkj3:amΖ
HWɶ 7pkk3^5~>!i}xrmkGzI  lpzJl3WZj샵6$^~7ןo5>tM   Y]fV];ZkQ-^HkxZ9@[Y   6wSjxBɷ\݋~fI   6ȓ_Yu/ysMZ$+5}ky'ɖtOßhJ  M1=|翶uՏܞ5A4y^[O"=t}  l_'7J[kKwU͟[tC  4ysko~]nf{ޏе{?uBv]   ,OlMv#$~{ћt[Q  +F7gݏbM_I'_fl3O}  Xx;nnf5><I DrN{  :f|_YIo^!ip_7?f$q 4U;_Y͵'mڗpolHNkp_?fv諗l  lpz5\۵_-jDv v3;zZm4V3c{mi  {)ͯͬ3]B6?hfuF  &OVuu˜!i'#mA6嬵_   _ۛYg>F_b@F߳=]  [k|3̿'3$m$[j<XS  j57O&V}McֻתF8 m<5oo~of=pFM/-FHvӚޥoY;   ~Ьb_+`CtRNaֻ5;~A   ?ŧT=u}mC{?Y>  <y5jڄ3\`K_W:  0ѿh~?`fԚ_ܐ4}Vto˽s_}%  8v[j_`f5I5ɓw  ɰWf3y7~	Ioڒo׎?c: 5[yOm`f5Ϻ~߭5s':  q?R_^llH_4[l  `LVv:vXÇ6&$MVl mi׿U񱼧  `7Yg:scBR;?8[>5~X  2:smƏA5;zx  2Vk~afxW5M{h  2=Du?f։7z	Inh`lIggMs=  M6yZٵ}Uޅo3$M=pzc˹  نw<4-w^/  :zQ5{H^-Va  o;Rݿ?}uqw5[3;.3@""^EPT*^.S^GUO$yt2y<'d;}泿wU%`zg??ZuJ׻}jWJl<$I$5xԘ}VuG<c<t6[$I]Od7N?vKs֋੍|_JGo$I!| j5;$uSSfy%I$iRsw @Z|ץM46ەĒ$I4Oݝ/CU~I`1.Y%I$ixl.d>_vHjzh)u2S$II_Il&s0:9$:,/_Y*ǔ$IN=~/|7q֪I[O	 y/J.)%I$i<vK4~GҊtNʪIA2zWWI$I׻VӛW}Hjlyhe>$I$U	UlOݳCR?8F[4E<$I$sFjEZ!?8FWs7d#I$IR<tMj(|w>+>$єo4x䆈g$I
սt~NsZ!5#h|Ի؈g$I
: izI'IӾ$ITC    IDATS)LsԽ=) I$Ilbi.&ug}/b[2K|H$Ipӿ ٤I_CRЏPuS#9$I^n~ց󇤆?eủ|H$I_^@۾g_Y6'VhhЇ$Iѩ{v{:%8Q/,>$I4Jw2%n;-aY? #I$i+?["~wcֽlvSI$Iz.{QcZ`aRQD?W$I$x9|FM:p0kʷ<''$IjPZruBt/u0k?*jFiUI$I5Y~8{ޖ_Y0T)I$Ie>!hLM~eP=?H$Ib4RïEШYߝ0Z7MųG?:$I$ո]K|GR`uR֓$I!~Gv
I$I$h@.wy[C54w}[JfB$I~VSw%hԀCkfދk$ILc!5ҽxg$I$0?٬sHbZ8~6H$IJrRĔ[og~&H$Ijk
#!_g/I$IUO֯ߥ`l8$Z$I5ww)h $VR6$IƵ<|ƈqHbn_=%I$i*;5$~Juϝ=%I$iZu*|qHbnJn̗$I5M7;4FChi^$IfUC{9/I$I3Zߵ1Xug$I$hEo#m$IF޵.6$Òs]$IfA߽QaILj?&I$i<yGj(|FE9$G$I$ժa0VMI9s\$IʫI]AjΏI$Ic;ǠQAIuߒ$IR`ZjsXܖ$ImXCI57S굢$I$64*!M{/ג$I_7`jsWG$I$MӠQI5oTFiI$IZ?|_F8$L$I$]Go;4CRdl$IsW6h9ȷ|e*}$z.K$IV4J֛obI5ѻr,I$IC_7h1h')E<$I^
1FݜkG$I$U=r06F\oF`I$I\?Ac9$|fh==%I$r-5nAc8$GE^I$IlAc8$A$ITc)_I~!4h0%I$Iӫ{V;9{ѳV$IF^+۽!|σƐpH1_IEQ+I$I#SCw=h	31$I$I3X1H=Ac8$61$I$I3[|Ib|4*I$I#[kw?4"}6zJ$IH7xԘ~F@३X`L$I}w@hrH󶌞$IT&1{ 48$U\RѳT$IjSoTq$IToK 48$UXsw4GPI$I]%swBhpHgFNI$IeEٔo%sH$ITnBh|4x)I$IJ#Xy*}DKI$Iw%]g9$USѳR$I4Q~=~Wr8$ULԯEII$Ir>8|WFIdƩx)I$IZA?5wSՂCRt^x$I$ލǄ(CRE_SѳQ$I"5|g!"-$IUԿ!7ME{YL$I$^CBc9$U@;EBI$It|	Y4Eͣg$I$iJ$4fCҐ^C$I$A%1KXիRy6zJ$I֤b=|,pHb$IwfCҐʷeM$Iڠ;fn	4o=$I$IӨwA%4fCH$I4"ߕӛwLh !тq'I$IzWcBc9$"<zI$If~7ۿ1~ׄ4d:3zI$Ife{И!Idx'I$IzofCi&I$I,
91:iѳM$I4gRpƦ!iH&I$I:gW	irH.i$IYxwFИ!=LYh==$&~|{Mw=wѿCR}R#&;Θ<pE<xU*+KMӈ%IZ7n4z7=$IZ<=`sџJ,5w{{ʷ{C|v_2Osw֡M>:+u/~5xTF$I4=k!)_Ӡ=$IYų=UYMCj|Ah+Ss?H>:g}/>(:~',Iq:	k!)Xmg$䏊n:.uI#15/xis7Hߑ~fw*Կg!H6NE&IwMsR|W?PïO&4qh$ij=hO_]l;9$OScϼ*zON4\ßsXIQIo]7?FW34oƍw,M|WoCIҴ*NV9IAZ?=$IU}N/U}쿤ލǤmFɐ$Uޕ?Ϡo?=zfI*&~}/|ׄ?X/|ay&I%IҔSkc06uI;(K_oZijY/~e&sL=og	 UakO;Μ|Av?]~+u/5I"<5m̂9$mS?=$IC+'{%_Y33oɗ:$ikgMCR}.zFI:g~'o\|ͽ0]]JA	STG(IR@Sw')Ypȷc^&IuMИ5zWl$ޣOHC>?N֯|(IRt|3	STޕE&IR	J-HvPM&bV4#,IhПn4V!$,z4Ifs7P]/K%sț$հqH*I_L$F|=7͝a۾fKJjR6AcJ2$I=om1.o|o$uNrT_ %IQxtǎ/P/ޟ% Iߖ?wI%xY$If{Rԯ?WL9EIZ(c+4(sH#ߩ1gg
</wq_Y۩hC,=_jC?gr$t/ +Yֿ$IZγ{/xi3b}]ґ$p݋w	8$͢#IJ^]OʷyMF$I3b_|8$'ԯGIxog$$I>pHE;ռH{80ZG]*OEIKß)xYm3GԽ`Qj(y?(M4͚{~3qH%$i}njbdo$U{?O`9$͆uSF\ŲRO?# @됏h$i-*R%xC,hѳFӊ"u/#7	>@|קWFEJ֢rH+3ҳ⏇?`h{&Il{CL~*EI}MV\!>)_5??4; $U\0Z&IR]u`I3o[S|ßPߔO+IJ<["4wT4/T9&kf *&z4bItfN밿+T&K: yGE9KV౛Sc|fPsEjU'|׆	sKKw$ ՙCLX["I{ɮ1w#swR*/qI/Y6ۤgʷ{}s:I3u_EIGVj}R*_T4xԻw!5|wF?I3w>cGFwP>Ҡe/I#SRԯ>|_]8$̈́uSsHF|W|aR/Ih-M;N%sSk'cfZrH=$i|BjI:jє1 IթH{/L݋wNc?oZ#нhQ%I#o~ :þ3IV^NN㿐FC(;z|IU=cW,{0o9Q;胾cTGID2Iz>g<&~ĿKR*Β9;04Ct?G7I::/;b&iDktA^}jɔoy!4M.y42gSk?\J zdHڿkS}S{`laW6K$w"LM=5$iJyd3!i'I#>ׁ5ӽ`!I?Wz:0u/XZ?_>+1bw1sRF/|}>Ӂ0N]u@T4xԽx>3&Rl搴n)I#pD9?'FA?19$uNZj'1E3!i-x(jm>!4-84zHGzq,8~iCZ^]l6̙xI"'SSkc!i-.zJRe9̼LȪ$F?v>kc䐴ET#X*Yys=?Ҡ=j$Cki9$˹$i]_f_oDIL[NJ%s-_>l9$5FhI\[ON9p;fTqfh:'j#z Y):XPܖJ5x䆔/xi3wԿ#i&KR]R;{`PswDqIܿX6w|Sʗ/T<sOm>Olh8$'oGuIN ,|vq{aJv442|n PsHZCNT:猅m ^G&FSγRuߦ|ׄ 51gTEIDOgzW=z57NZ/oKugUCҚ~k$i9[,|nCdFiI͊wF'%5zWj0H!iM>YgG$Vj任W<@9{uRpo 5H:~=|^ë}'ǔT&{/L݋wNc?܏2ՖC$u;^$`zW={4Eޏ$Ih-Mvo@EޗucK
X`ptORc>V!i(GU>g5P];n=*=4M;g?K5RU9$MQS=494|N3ۥQ<F@UIS1N*'G4_U2N~zW^}{4`a IZq)zNՕoT4eרIswHu4-y%ICYγg4P}?=Τ"HY27<[*!i
zWN͝3|F߷dS4o~I=w~|FG/bѣMuzCW{_Hޞs: hTCjL|j*G$U'Lyh`RI5zIwFE9$F~I:30zW=T&^޿Y2'Hʷ|ekqHZ[E?%is^lFGܞ/zԩ*u^u4FCj:'(ICUs?
hkQalOGoLkIS܏0+@fVe|_)Izލf&w?{ђu`l88$BsD??%ixSs
@=Lf]7GEԿF~tD [!Uhg$M@؈WzX59$B]4;)2P?;ϊNkFC*8+ICQ=g2POߔR=5ŊGJޛ63@6Vf"IsߏZAEDvZ;?,[:
 ٬sHZnloj0)z;5`9I+>_ג45yOLh)EH{(  PpHZE;D?%)c]wDXɊe-'Β)ȆCJ>7.ID<|fh?=+o	&DFw xy$չ㷥`y3ox{&~D}{@6-I+oyc_kyo?vKʊ^# lsHZa I
h>_>Vu_W<}o՜K/@VI+3wI
{ɮ`U&^]Կ=o?xۼ&@V[I+л/HRh7|Jsߜ|ȾCR/z i8$[ྋ0Tt/3{6
@c^h);>~LAξ*Β)? XCI/0ÒT׊ө`Y0U,0u/9Lw 4fCwHRX kdSObF pHzb""I59}Qp!z7S_D$iX<pEX+C{n>a/ͭ>8I/7IkӾ>VL{N{֩uߥ|_ !㐴uS6g`UR04o;uk4#j=F 0zIɷ{-i4Z>oMV#j:g~q 
rHZNIp>g0L]O*}ђ)U 4FCr&)I]%s֋ `lt9$-{uNJ  *!i9$:V]    IDAT3|  Y%8$-g$^s7_   _'g9I*c7_   UCm^IRu/!|  Ye8$={9I*!	  @VIk}NʭI_   u[IRZ>{ R׻NJsg/  UC^IR  d4zScF  *!i,K^$?(|  Y8$eۣw:I*g/  UCXZ(zRk7  *!i,K?IR6  @V9IsƢw:I*bكs  *!i,K$>w ƲԿNJ{  d4WDuTZ^  4֒CX6IKo  @VIIsKiЏ$:_'~  jHʷ}]Z'I5x  dUCRswGuTZk  @VY?$NJs.  UVIO^'I:s  *y[FuTZ>w jH]}p^'I/xi  ʪ!i{$Rx,|  Y4NJipe3  *!ۣw;I*G\   NJ{  dVC)ѻ$R]   UYI$?s  *ևo$ZI  J!iwGuTZ#|  Y:#{$Vcs  *ևџ$  dWCRDvTJ'  @Vy>$-IR),|  YNѻ$R3g.  U^Ik$z |  YԿNJ{ٞ3  *և}GvTJ  @Vy>$=rCn'I93  *އ'$'|1|  YT,{(zRj  dWCRNJ}߇\   ZRIR)  dWC:I*?w Tu=$7${;|  YhNJ.  U^}I;z^'IMs  *o  dWC$m_>w j{HjNJkps  *C?IRi[o>w j{Hj:I*|W]   L^'I/$|  Yt◢:I*|K.  U^mIS#zj,8|  Yt7:I*|]   Nf^'I/|y  ʫ!oGuTZV>w {H:;{$V.  U^}Ig}/zʷym  ʫ!GuTZv  @Vy=$3IRiۿ1|  Ydn^'IMs  *:I*殿>w {H:oa^'Is  *$Zi  ʫ!E{$V]   ..zjs  *v$GS  ʫ!;EuTZc%|  Y9$IRj  dWC҅FuTZӾ>w {H:NJsx  ʫ!{$waF]   :EuTZ  @Vy=$NJws  *ӿIRio=%|  YtDuTZ{  @Vy=$NJk5s  *5z*+|  Ytg:I*"<|  Yt:I*A/5	  @Vi=$k$Zp  dVCRODtTj>{ {HZNJ^   PN'I:  *IRM  dVCRswGtTj>{ {Hm;$Zg  dVCR;$Z]g/  UZ}I[*zR]{X  J!1oNJ  HUVCXҠIRi&|  YT$g  @Vi>$-{(zSc|  dUC;:I*|Mg/  UVI]IR5w{{  ʪ!w:I*ց  @VY>$qfN'I>S  *ևMEtTj3|  Yet͡;$ZE  *ևe{FtTj
  @VY>$]]N'Iֿ  dUCRGtTjGn  @VY>$NJh>>{ j}Hj;$^c  *և$;)|  Y%]$^k?  @VI>$$^O_   Z-_IRu  dTCRc|ݔAN'Iֽx  *!i,UؒTz7>{ jH<ygN'Iɏg/  UCWDtTj?	  @VI?$83zrSc  *GFtTz_   IR{o  qH:oa>'I>  *ߊ$:g?|  Y>s$^}/  UNIC>IRo?=|  Y9I*c7_   m^IRu  dSCRc)NJ/U3  HU4""zk  *!i,KGo$G}  JqHRs9I*  @V)IcY]wD>'I׽l  d4w$> R&>	g}7z<~[  JqHRGsT~NjY/|  Ye8$euG9I
)3  *!i,K=IRH> 2Ʋoѻ$>3  *!iS*}NJ-g0  !yE}NJw  *!y$]> 2׿}NJh<> 2׻b}NBn> ~8g<z{~  JpHz^GrRO`   ]NB3> ѻ$Ի  dS6$)}`   UCr}NJ  @V	I<rC>'I!["|  sHZNӢw9I
׻g0  =7zG*|  sHZdN.'I!u  @6>ѻ$Ի  dC!i9?IRH/  @6巢w9I
h-  @6/xi.'Ia6  @6^$)  @6^`ѻ$93  ȆCn8*z> l9$@Eѻ$Կ  dC!'{.'I!<> l9$@GrVp9  dC!;%z{;|  rHzy/JDrRa   +xO$ձۄ`   ZI+п]NBrR  吴k$)w`   ZI+=w~.'I11o9  dC!i>zN  䐴IRX#)|  PrHZ|ͣ8I
dn  䐴"sKߍ$)Ga   #<q{.'I!.|  PrHZmFrS5s  ȆCJt/9z;F  㐴O_$)⏇a   :I+:C{$90  w=N]u`  㐴2kGrK0  C*9z33  ȆC*o91zm^> l8$B8I
u_a   *I>K{$9+s  ȆC*Lk$յa   *Io=Ns^  ␴*mFrR|2~  i8$w9I
+W0  t|'Iah  ᐴEqVa   I>s{$ջ9  dC!i5{a'Ia>|  pHZ|_$)~75n> l(8$MAUNj9  dC!i
w-$)1  @6{{$ս`9  dC!i*IRXO  @6u8I
X`  46$)|Mg1  sH4zZ?|  Y8)i'IauNz  pISԻ=N]  pISD=N<py  pIS:o8IL9b   4E͝IRh͝> ,CTY/^;z?Y  HIk`{$=w~  PIkw{$տ9  d=N<yg  PIkuFqWQ|_
  @!i4w5NBkG  8$uSy6z'|1~  )CY'Iau/-|  Y5Ի=Ns~  0Ik	;{$U:  B8$$)|ׇb   ᐴm^IRh  @!i-{$9{s  B8$=EqV#0  pHZKw$)㷅a   ᐴ6IR\E򅛄b   +CZh5NBѳ  J琴/yIkS> tIkx=N]}p  9$Dq0  !i-u2zԘY  drHZK#)zК{;|  YRsFpZ/b   +Cښ^J<zz? T&i<py'IaM9  drHޕEqWs7  @V|Nj'I5wG,  8$MCk?$)q  @Vi<$)Żb   +C4K$)a   +C4o91zγ1n,  R8$MSG8I
[g1  !i?NBk  J4M͝IRh	  @V
_w!Tw? T0=N*'0  !it/#z7  @6f@IRh?> l9$̀$)g1  :0wÔ=Nzr,  lsH!$)bكs  fC]u`'I6  @6fyDpZ됿
  @6fHk?$)  @6fH)=Nxl,  Y4IRXSwa   UI3w{$U)  fCL~2N'Ix,  Y4Ze'IuNV,  Y47$)޵b   5I3x=N<~k  Y4IR<|  ٬pHO蒹k$:  fCk-x'IMY  d!i~%zz7> lV8$͂8I
x's  fC,=NBm> l9$'NBk-X,  4Z|$zк  @6fAիw8I
۩  fC,)IRXE9  d3!in<&z7  @6f{ww8I
  @6fIFpZmg1  (Yo"zw> lF9$͢wDqV^b   1Iw8I
[g1  NBkY  d3!ix_'Iu/5|  ٌqHE/KDqKg1  Y6x=NRc  fC,]8zК{^,  4۟ӾIRh> lF8$Ͳ~IRh+  @6#f4Gqkg1  fCR	IR\~j,8|  ٴ9$wk$g1  0}Ie|ONBY  dT>$)޵b   62(~7z? 4]I%ETۊ"_> lZJһr5NBkY  dT'/GpZb   4zW'In:.|  TkGq;._Y! " ̨Eaёqo/Iw;Cξ'=dN[{ߜz#!IwoUϽ>s9g;u Œ$I҆d4_}osX$IRcY$>jg$IƬHc}=wI,$IԘuIcۣp >%I$5fE8s@"$~K$IJ"i8/*MX$IHs>j/\,$IԘUIc?>^K,$IԘUIc.g8P{/Œ$I")q q-,|K$Ij87}}X$IRcY$Eog8P!|K$Ij8Z^ T#g$IgPKR*80wbI$Igq ^>%I$5fERP+>jY,I$1,jg8P	Œ$I3")^>q^,$IԘQIQ-$n3lX$IRZ,}I1 TswbI$IER`Kv>j7X$IRcH
}gp `=%I$5;}5xY,I$Y$WdE Eʗ"|K$IjWIo>5ug$Ize`3@ΊEX$IRcH
u'p >%I$_I˶~F*lj^<$IXgI%hح8P]~)|K$Ij3Ի3@>%I$5֙ER	3@Œ$I"5}_ +g$I:H*C7K׎>R$I,JD BP,$I,JR=p :gs,$IXkI%iE wqX$IRcY$o>*q,$IXkIeij^*+q ?%I$"Do;+}gg$IfT/>^c,$Ix,JT?>}q,$IY$|WG bZ)[i<$Ix,JV]8Pͽ#|K$Ij<gI%w3@Ω_Œ$IϙER3@5bI$I"dP g$IsfT0A/*5X$IR,Jkp ZX$IҳH*a>^c,$IxVI%}_E B,|Kj    IDAT$Ij<+g8X3$I3H*cSS~"u$IY$G BoPѳX$IRY$EG Bo9-|K$Ij<#>F Bǧ?=%I$gI%-g8p>%I$5"O}>og$IY$'F B9,|K$Ij<ER LbX$IR,J\D ۿ>|K$IjLgT/KD BL<$IԘ"1{.X$IғY$UG B"|K$IjLgT:'} ֠-_>%I$5,^sF | zK$IjX$EmF BuV,ǒ$IERsi T3g$IER^3@Dn>%IIcT?}]X$I,*PsD uNj<$I&ER3@޵GcI$iX$U-G B	Œ$IҤױHFp ~>|K$IgTZ|"nX$I&8/">^G<$I	"BQ kg$IMpIwag8X K_>%IlBHPS}:X$I&4
F u2|K$IلfTmR}տ}E<$ILfIkpeg8X,e6	ǒ$IR6Y$UF 5y,I$eERj/| \ǒ$IR6Y$Uo>xB<$I	"jMKEH T|,eSg$I`H`[N>kkX$I&,
Y(s$IMXIu'o z>%Il²H`-R*3@"s$I"Q \scI$),*Zâo :y,I$eERE>d`[>%IlHh}k \=y3Y$I&$hӔz3@n_$IR6,*ˢo :']<$I	"u/5wQX$I&$
^@b$I$-OI>Bs׷dI$կ|J393eY$Uy>k73Y$InF_>{.E);?,*^ӂm w$IUϥa=uV,^n;˥;"_ xX$I-_s濤M'"{hVw"ϒgTZ|bc /dI$-_贯ՇCקTs;VoAlI/_Ŝ] U>+3Y$I{\*Vg^ER<]$ Uѻy,I1?רwNTHEkPF{$I\92%"uNjP
͝>%I4m{w$5SVՂ,jPs߈ J}_dI$FvHԼ,ТMs_g$IFÏ5W*owERM{YXuO<$I^sQny*<&_,jR]%RwzSL$I?v_Fsl,>0^k	})|&K$ծ*?h;9G`I5iME Ի,IT\4\e%oER]	 \3Y$B:cs΂'FkԚ{'YdI5i@);1|&K$UF_*w"Fr@Jc,|&K$75ɥq_J_RZ5}_,jTOD_O л,I\Ǣ-~oERʗm1_.dIQosק?V#W#HYG}MBs_	ɒ$Isڱ_L\`oNk"0ջk
:=%IfQIKwI.J׊Պ:#ᯑ,jV甯F_S 0|.@L$IsGbZ<uERj@)'6z.K$=s?Fdk)2hSo{x,I&35
"^uP
÷GdI456bDZG|*ER^kuP
_g$I=kc>,jX{磯+rRK$In/\#}ԟ.#Ha͝}]Ƥ]$FÏsxſVHcS)_$I*GԺnF1_FfT}mg$I/5TUzF*+MY92Y0(|ׅeI49ǤbѿP#cWk<2:c@iLI4I5Z5>,jZe
ՇeI4ѿj0aG}&:"@JŚ z.Ky렏ΊEɩR;~mDfTzW}}FseI|Qj9w!i)E,#>fT'UP!|.KZs<רeP`I5ۣ/|j\$iҟk4\#*u"HsSSZ}C'K٢Mg$I\GkPo0Z|":"MosYZh뽞kDi^`I5{ޖ@it]>%IlkZ~$z"d5P/	˒$UFÏC);gdI5/_AoѳYog>h̓wm(I\B"%:(>%I
s`YuE49 eeI\ߑe`4Uf,&}$Ic{Qsejï,& J%Yxj9Skc4¬3 *IhF謉 J}g$I3}n'O<h}KE҄Կk4z>%IZ[NoNcw]R}oE҄Խ`k4ٍ͒$=sUk/}y܈"iB~5 g$iʷzWwNGԊ%3-<|Df4!ۼ:Z([fI҄</zAQlj^|	"i*V}WeIRݟkԊs5YpITGD_r Q)YTFـ1(+OE9k@Rl$UF+A'IYpITs߈ JwYTnF>2&|N-"iZ9&/8~>KB?>3\#/k1xg4a8(~͒FE,˂H}Jg$i˷|3k454|sF|˂HG~:($I5h&zW<5F3oAlIVF_w R)Y4u/s]l̂HO?Orl$=w=} &XbEֻkT7>%Ik_o,8	}D_{ Rx,ISs_Mc2̺4G ֪{ 6	ۣ=i,Ius:|iE$65/Ǣ?R^{|/}yj|Qp>c,&-G_ R<~glʷx02Y 6	s΂tϒT_=FIZۿ}NϒT{3zTs,8ImSwAR>5|>KRk{ѣ`"iwy5P.~ʷ~U|>FOrwxC͂Hທ}N/gIj&zTe6"ikktz>%5P[E6I[/C)ګSx-IU{c`ds6+AI^"@ZWI] #S=|f%"i]sxP:>%o:)z٬Y$Mx>Z(b̓>.I#`d>gd45xgPJ}~3|FKR<|SU٬Y$MzSSZ}=Ng$U"{(z|LlV,}=$Uy)`d:g[]ERgr/"zlTįڬY$)HPJ39|FKRUj0R#>>kdmktw_?%"D>kd_}MO1H	ђTe殿>kd-(I>%
y&Pw֯
Y	Ht?}MRg$U 3lF6+AI.ї%@9zI֣M'GOl)GlV,twE_ >3Zk5)|f%"IO׻k>%U`d>gdkW&@9)_E6 u6|EJE_6J}쟅iI*kͽ=F{66+IIzFG_ Կ-Ie}䧣4HuNZJEQڣOrSK$ߌ #5\Gڬ$Y$uN?>%u/#zDTsڬ$Y$5w{[	PZӒT=F*6+IIzfSR=}S/ՒTUwGOh)-4|f%"IϪї)@ibR)027["IϪs?D_ տ9-Ie绢G3H~|UJEUswG_ |WjI*K?=F?$6ETVJ}Wg$ΊEc`z>ke)*@io?'|NKRY]{dXgmV,u*@y)5Z룧2Hy7zY$9k*@uNZoҠ=FuGdnƩh?}Vg$=`;y($=o[ό^ʫ(Rg$E>ϣ1h-4|f%"I[ї,@uY-Iu/9zTY,$=o?}g$Eֿ}E(]ڬdY$iO쵢[Rky-IMKEhՇ"Ik-@u/VmV,ֺ.nJy-I㮽#`})|f%"IkuG[kZ u:6+YIZ{K^R}Z߉ג4w_=~F.6+YIZg{.vʭLҗkI[6} 6ygguֽ`Eqc`䊕w۬Y$iDPz;ג4:|5z\6+aIZ$0@WalICGO]]oJE֫D_ =oy-Ix#`:?6+aIZ:+F_ W/e7
ْ4ʚr֡Y	Hz0@%-I}WG-X4w~KJE֯::(lIa LgnV,o>%R(~'L̖QU<~WC7۬Y$i2@%tN-I[G,Xn8.|f%"I]swD_ 0x-Ih(YIH75/k*omI=^Ƣ}ܗgnV,4z?NP	ْ4-<n=^Ƣrf>3@5t)s[ c/"|f%"I3*磯g|mI=VƢ
YHҌ<v[uP	y9|\ܖh-c`,w]>sg>5@ehܖۢ)./|f%"I3}gk]lܖs΂q
06S>wg7|xl*6@5z)u[6WFOSi𹛕8$*L ΊEs[6V"zolk5$ͪEG_ śnIMӾ=FƦX}oJEfUG_ >[fSG(o9=|f%"IkS굣q~$8|vKҬ>٘^MJEf]qJi[fR c^ٛ<$ͺ9S8@?&|vKL<xmYɳHҬkkZ-ISswEOMwRh<$;:RoIZ|K/0iYHտkR)%[`9<~.(Iڠ:}#ZߒZQ	0v39|f"ITs_*X}K*uN c:oV,*}_oIz_?  &38@Iz}TS65?|KO=wq;oV,t5PI#8|Kҳ]L^P,K_Ҡ}TKg$d0z438HIw]}TRۿ>%?~NX:gpV,4'uw>%iXs_K("Eʗ<|g"IsRsF_ :s\z=B%|g"IsTdE_ Կ}E4ۿ.~'z9U($Y`Z|(|Kܺ=tN9U($YcWPY&|*ziYU($Y6?R1 gɫsֿE?8~ʷ|q,*E}GuQ4YOEp3xYU,$i󶌞 :\9ߣ@UbY$iNk9 Pi&y.[4Ǣ@	_YŲH65?k ^y.uΙw ᚻ5|g"Is^廙g@-e6	[ehw єMYŲHҜ>O@uNy.u/&ztr<*EFyFJ~R3]Rwz1s?䬂Y$i$8/z& T^繤ջP
>>
f93g}nQDO7xvo>
f4|= 	3]RMw_= Ja8jf5! 6\ۿ>%UE3^}\*EFV]g@-an>%U|R4ZGql*EFVEs]Ru^G(H6?>fѵxT 0*WsHiЏc 1xٜU8$Cb*WG/R]|^P,4E a-|KN3= J}gsV,4҆;VjS=eK^>%|7&zlHl*v    IDATEF^G@t/9|K*ySS@6~F/vIyS bZv|T:g{(Y$i5w~K #7lg);c
ZQ*E@t/.|K*Y7OO 4|gjgԽ`P?~j/<u/5z2Y$i,5Poq˷zi_?6" ѳ:AIOSRPK+Bk_RZ= JuGuV,4z=7 j}g缤"1Pn/*Y07Y$ild 2ۿ>|KA ׿y$$ś&z~ VShy/ilOJ9gvV,4z=? j{^xj[)Zc{FjEZ{@Ejy/i;)k8 Pdlj~jEZ'Rs_FSKG@e>$|vg5"Icspzy=%q6M;΍1 msE^?# 	-լ- 2|WFY$i^R=N &B%s_Y(z TNKwV,RGߍ' mo*_ԯEOJ3<YI
}_Em~fW/M/^	YͲHRH֯JiЋ) I]~)|KY#?=| fX@ʦfY$)+
D)Vޞm^>%_s%6@gyV,V俏+ gpR Iku'S굣G@y0$ooп-,> kǖH jO-gzV,ZDxBn~|s$@sgzV,ZoDջ`JT累v692s=iI
-u)0zi뜳 z GQ|YMHRx;Ϗ3 wA)[Q@n= jep}A}HRx.z L޵Gyf4-_7}NYHRx֯PI]Lm~_&|צWD_ s>qI*E[ψ5 SSxT{3ji-s>yI*E"z $it?Rdї9@mu/&|g5"I(_zS5Tn<}~ "I&e)uLvv%P{R65/|g5"IsR<~VJPG_ ~6Y$<m" (2`}BRSR累F_ ߍEJUﺣg ϥۜ~Hp}BBvM}7(EdRΟD Ϡ:|5^!QIEh
0q~&$$ś*z݋w/~OoJceջ: l=C*C?>MA (VݓlBHRj9z(Vݝ{z}C*_E]K`u/1MPI*_SRYSwHlj^j{&'$ˢg 3)[iCu=~-()G~o&,$殿= ץ
H#iSgŢK=wI=bde6LZKէ}<Ledc"Is7g Կ-iCj4	1x{E6Y$ۼ:~7z60KE{uji5w{[|J%:t{F6Y$o>5z6|7SuԻ气Ae/dR>	m9S)[YE!uWJvzua#,To֪<v[j4\ Խt$
jlBHR]]lwxC=FYswuG@UuoI6Y$P`:Yꞿ,K_~dO>D(_ lUS	"IhMѳ
)+Sg"Ѵx>3ip_ ̑,,T* Ud?57۽vzAYDCwlj^}&,T_Ӡ= /<e6	bMK?7X:IJOY Q'? ۇf<vkQ*o܌LzIL#?= P|7ߋT^~1o;ó&Ds?jX$B-t LA/~$Ŵp:ӯmF"1_)Y$Ru/9zvPHӾ_~o҈[Yjwk~hNْߗ,T=z~P&f]sXj{)~R9Σ zRf53*Vù=K۾f7ck <7JE*Wa 맗J~SԽp*z`6 gfdJ~KKѳ(V>|"~_>S>zk{3$UՇD2 *XuO^Gj/{E-xcӾPAEseʖ Y$5{<GzG}&K_~t[h]_3%o:9ǣPo)dIli ɠ\lZGqwxCi_O+H_Ҡ_)=5E*[俋k ]5.~R/>qosu~x#jwqy06 п}E}PgeʖoTm Lr߉9ߦ?=_}oU7K]~99SR|/  ~T,Tz?;zӊ9,u2uNZj/\jm2N<SO<sU]b]@)Ox|LdJ] f4GnN/IN[ϜtW0 ۦ˦4x9=.7y' U7ϙE*E8   ʠ~T9HRk1  ]l9S"IoR|,z  0Z} |Y$u/9z  ]~TcY$ط   T[φ/XkIMWD<   fX}om~TcY$6T  `:gsRuf45?+o}   T7O֯?W*+$ժw)z  0Cv?O~n$թ|SY=  X_E1JI5+$ծ   M'#X,TRJ z  ZsEjY3g!   03"Iu'!   >G5fEԼ4x  <|SʦǟfEj[ԯEE   G??71EZKRZ=  )Ū{Rhs3"I{.  9E5fEj]/4EH   Rdlϋj*$վ='  xJ?'1,T{3   hNҗ՘uI=/  &^C56($MD?=/  &[7O6?AY$i2\=6  &VφJE&1_   |۟?Y$irZq*+z|  LƟ	"$MT1z~  L&LyP9W[$iE   {ޖgA"IWes  `"U)_ssE&|פkES  3~TcNHD  ֆɷziO9"IYRw*  @musE&GU  Z*GR}jyIޜҠ=_  js?IIzW=_  jX}oʖ HHD/4GY  h#"I_ڣ,  @-&eSyj,$M|~5b=o  *uiI҂Fp|  gyI]I{+   TRsyISo>5z  TR廙tj%$驚f  ^+;|Nd$DN   ҽpc"I7  2˶?˩1,wѳ  :cNf$TobJ^<  (7l&g85ƚE<0z&  ZO{IsƔz  PJO?E<u/#z6  O3H3!Y$ISϥͣG4  @t_~^S#,$i-u/>zF  FoaY$Ik)h   ^sY$I먳bQ  ׿M?{FH^KR==  35³H֣=  .7\F)H֧CGn  +GSeJe"IZZQ  _?Q,Կ  06;m"IAÇ2  P{vjs"Ia=  FbQKe$Ͱ|_H׊   #3x䖔-,FHfQ:  ȴHKR6|P#?T/OEHl  s	?sQںl=:i{7ToDw  9U4K6?oQں4ZiV#UE?   s}ZJe{ӯF0Rj9  0'HԼs&F?a*ֿy  a:YwzsJ׿Luܗ5w~KJV  I~Rb5hu_=  fǹ>Ҧ9it.&*ۖ/J{?  5)Mg*JpN{!?TG6   0#SwYJʔOv;/׿Л   _|Mj}w~4)z7  ud_}RRO_B456׽l  tNzIսt_Cxg%U|+R=yO   x^;/HkX$b%~   eQVM?09̤F%+GH\C%բő  gi$j̪|kizԻLKޖRu   x޵GԨl"i^LmIu{Ҩ{  ӊ|g$5*[{={4NM7OGq   xR1H/|T\܋;TT  Խhs.gϹH^<VC"  $[YHJ7|HOkWYq)թ|W"{x  `ک;CjT޵G>"iHnq2  	9 5S?3IA55/o_1  06}	?)U{3Io	A:/k  Lb)U5jQ׽HxW+ձ9q   &ѠZvGzxT_ERm`-$r  `t3R]jOE`iFR3{  0A?nʦ懟wԨMz/~-յ>{  0A5|ׄsԨM?Ҡ?ER?Tn]>{	  0)E:Cg:=osݔm^kޖR=	  0	v>ۨQ0#X$,H5n0<  ߾"e7
?רQ:|u]$<,<!ն  SSDZ03c~4:o Rk+)ZsyO  I}+,Fjz	uִf[Q9suK  j}߆aԨ_6Yw#s4:/@Rw]8  zW~Qcz_\$;YiJs]~)n   ec#kq)_I5o&`  `rC)gճKfz\ER\e[᤺׻[  :Rۿ~VQ=wxÌ?^vJu/X}ln/  @u)okrIKnoCJuuTf|1  w'o#>5ecF/.IkJu{ᶳ z<ÔmYx/ڧ~-,վE}  jp!\ֻY>gHJ<e;)-սoIEY_  @;u#oY~mG0^ܠ  Hc~Q}˷]*GǿHjHPt  =ojR6u:Ei]|  ջؔEkAOm@J\  @h'[s[Lt2|4ԻmEZ3Q_T:9 (Vߛ^~P}kk謙/:#վysq  eRswǟ5TkwN_sHj K_:W-  wGC-i5sҝE̓?%սLۜK  i?[-<o;{$Ɯ> &{'/Lyr./]  `~P[It^sH4Oj^  FwQ)~PM[Q]{H_sHy(J_To?j0  0;Og6M떏u<E`})"/jT1  0G^;9gմ-_1IC54G~:  lb=)gճ|W<E>+չ  )Zno?3R<GHmQ,նgr  SZ|8Zz<H-/ZkW}  <A?L9AsWSwB^[$={aiKuֺ0d]Y@MIA]uSW]t#]t[ADXf(!&Vi%YZSRBzgOk:M|]k_?xׇ5|  &v|lw3_~C!;1f}lww;h  c|xz[?1SӄC}kW=0[m~Sm  8mplŶyG&)önd/يm/O} u㹓9;X$C;/zlv>  pDؾ?j䧎>>h"$7_8N?nf"±CSn  Xiw]93^x⇤?8x\<Uoc{c  +ik=2s-yշƢ[t}?04[m\uG  V}?k>c}[zؾcle!i|>nt}楓_XeN} `e阝ɟmy7;Ecg-/H;$fg|mw  [ϝߖr睰豵>rö7>/R䧌{$   IDAT:ȳ33-Nyظıǲ[v_q`fKǍ1 3f_?n<w?:V҆z`lpoecL}| `i([?uc뇟GhC86X;oE_;v7 y?bn珍glr}V'$=!*dl\o.x;/& `
nX?c㪓^=1;H!_8ظCcvƁN-6
  ÷}dgv{126xؼccK6c_Xmc5`[ן2 sWت+ۡWc>[b!	      @"$   I    $B       @"$   I    $B       @"$   I    $B       @"$   I    $B       @"$   I    $B       @"$   I    $B       @"$   I    $B       @"$   I    $B       @"$   I    $B       @"$   I    $B       @"$   I    $B       @"$   I    $B       @"$   I    $B       @"$   I    $B       @"$   I    $B       @"$   I    $B       @"$   I    $B       @"$   I    $B       @"$   I    $B       @"$   I    $B       @"$   I    $B       @"$   I    $B       @"$   I    $B       @"$   I    $B       @"$   I    $B       @"$   I    $B       @"$   I    $B       @"$   I    $B       @"$   I    $B       @"$   I    $B       @"$   I    $B       @"$   I    $B       @"$   I    $B       @"$   I    $B       @"$   I    $B       @"$   I    $B       @"$   I    $B       @"$   I    $B       @"$   I    $B       @"$   I    $B       @"$   I    $B       @"$   I    $B       @"$   I    $B       @"$   I    $B       @"$   I    $B       @"$   I    $B       @"$   I    $B       @"$   I    $B       @"$   I    $B       @"$   I    $B       @"$   I    $B       @"$   I    $B       @"$   I    $B       @"$   I    $B       @"$   I    $B       @"$   I    $B       @"$   I    $B       @"$   I    $B       @"$   I    $B       @"$   I    $B       @"$   I    $B       @"$   I    $B       @"$   I    $B       @"$   I    $B       @"$   I    $B       @"$   I    $B       @"$   I    $B       @"$   I    $B       @"$   I    $B       @"$   I    $B       @"$   I    $B       @"$   I    $B       @"$   I    $B       @"$   I    $B       @"$   I    $B       @"$   I    $B       @"$   I    $B       @"$   I    $B       @"$   I    $B       @"$   I    $B       @"$   I    $B       @"$   I    $B       @"$   I    $B       @"$   I    $B       @"$   I    $B       @"$   I    $B       @"$   I    $B       @"$   I    $B       @"$   I    $B       @"$   I    $B       @"$   I    $B       @"$   I    $B       @"$   I    $B       @"$   I    $B       @"$   I    $B       @"$   I    $B       @"$   I    $B       @"$   I    $B       @"$   I    $B       @"$   I    $B       @"$   I    $B       @"$   I    $B       @"$   I    $B       @"$   I    $B       @"$   I    $B       @"$   I    $B       @"$   I    $B       @"$   I    $B       @"$   I    $B       @"$   I    $B       @"$   I    $B       @"$   I    $B       @"$   I    $B       @"$   I    $B       @"$   I    $B       @"$   I    $B       @"$   I    $B       @"$   I    $B       @"$   I    $B       @"$   I    $B       @"$   I    $B       @"$   I    $B       @"$   I    $B       @"$   I    $B       @"$   I    $B       @"$   I    $B       @"$   I    $B       @"$   I    $B       @"$   I    $B       @"$   I    $B       @"$   I    $B       @"$   I    $B       @"$   I    $B       @"$   I    $B       @"$   I    $B       @"$   I    $B       @"$   I    $B       @"$   I    $B       @"$   I    $B       @"$   I    $B       @"$   I    $B       @"$   I    $B       @"$   I    $B       @"$   I    $B       @"$   I    $B       @"$   I    $B       @"$   I    $B       @"$   I    $B       @"$   I    $B       @"$   I    $B       @"$   I    $B       @"$   I    $B       @"$   I    $B       @"$   I    $B       @"$   I    $B       @"$   I    $B       @"$   I    $B       @"$   I    $B       @"$   I    $B       @"$   I    $B       @"$   I    $B       @"$   I    $B       @"$   I    $B       @"$   I    $B       @"$   I    $B       @"$   I    $B       @"$   I    $B       @"$   I    $B       @"$   I    $B       @"$   I    $B       @"$   I    $B       @"$   I    $B       @"$   I    $B       @"$   I    $B       @"$   I    $B       @"$   I    $B       @"$   I    $B       @"$   I    $B       @"$   I    $B       @"$   I    $B       @"$   I    $B       @"$   I    $B       @"$   I    $B       @"$   I    $B       @"$   I    $B       @"$   I    $B       @"$   I    $B       @"$   I    $B       @"$   I    >Tp    IENDB`PNG

   IHDR         +   	pHYs    {Rk    IDATxwdgyj@ d6<lcqG{<6p=}:Hne3m%+'2(,Pʹ[RKޕkS\ϳ::]S   5    `Y    @X    @X    @X    @X    @X    @X    @X    @X    @X    @X    @X    @X    @X    @X    @X    @X    @X    @X    @X    @X    @X    @X    @X    @X    @X    @X    @X    @X    @X    @X    @X    @X    @X    @X    @X    @X    @X    @X    @X    @X    @X    @X    @X    @X    @X    @X    @X    @X    @X    @X    @X    @X    @X    @X    @X    @X    @X    @X    @X    @X    @X    @X    @ RCS3TSXm*7yߗֺG! XrfէۦoM-uԻYrL< "o=#u:XBjTu7D?" ZRdk;)e/JC>:g9o;3n3`l 1	(O `o8:KƓFۥAq5V.u?P*&hdG)zQ =uy-:ԻTJd, .M?/9S*S ,>8¯lI_. ArZjKٺ!~ dw>}Ҩݩw7RӨz;ODn'  8OuG*GgPw1_V?FEwɮяX ]S4&5~gtR%# <x+4&~ V&ƨaNKxj>TDSkbԿY  *u&ᣯqj֩sS~+vyC?ƣEO `9׈ҸS ?k/C S_+JcXN!@RS  <Z|545oP{Ѫ}ѿd]<D XZ{=Qǖ u/Z>9hX	 ?5w{s54O^ TO?l/Scx||h 057W_KJcZks0xTz]/QWﲽa	 <T,{Q45Sĝ y^*vxI/OW=!	 x[+m7S|_ƮE+ @%_[J\s++F{пF4~9 {ï1qӏ׌s=+s0 `T>ך8\4xZ 5:MJU5C  FMH!SvyC*3SӏR4vMnSٟ2  *֦֞oƹ^Hek],֦!} +2PkPZ}xg/ <}_7|;  1;>0\Z<:1gRzbVZ  SףR1]㭩Z  Y~]*c\s퇟ŷ ?HۇGkjzm*}FR  2R}ïObks3<- <;<_7'  y:Skw_J9 ?1k˦  owf i,Zuw, S;5-  y^*l*i}ޕR;r+4zW;  w׭R1u/Z5GiOy  F:~&U*Ƶ/NSl>9
  S25:V*ƴ>77uSe  5¯gb*vvr=>OS[  f|T,{auTa- 'EƣWr PC+1m3[ +94h?	  9׸u}_&G :׺Ҹ5(<@_ux|Kv @MUO;4zW*ƬisDѯ{X  0[~yuTS;$' RhtC9Aw>  uI)MMmлV]sLUv!=  uW¯bjީ- Z3aT>  0T5O~"ZX*ƨ7n~P8KA59 `|T,6XZ<u[@Hn찐3  ~H¯bLj3_ @Ѭ}TU9 G?_6ƥ[7 (7h~6U#  ~HuR1u kWp+_'  Qˤ[}7 hG?F+  _^v_R@Yb8V+  e?y5TxDP:~6r UOޛ+^~,#\}xлJS_L߉  0%HĢkh:'~ :h4A9 `Z:}.:Z*F>@swP&-Dn  ^3z{4-}AJҘbv?  3R>t[b<~y%Q|>4$U  W_WK6H˩?bkzm?= `_x¯bDѽtFMlw= `NOܙ;4:[Z<:u_<|~4:gCz= `N:0:[*F5|n4|2QLտRUFg  [UGvTHχI֡
a5wT5  0/bmjnڇ}xh4yWnipwg2  ̫<d=|N4_ha][, 9SR\k8|>4_h  jj?1:\*kQ,qz  jpRXk?=|.4%[0Z7={  D?
[ F93  b`k¯˥" Qu7D\  տks.-6\=k `$td5xa I  [T, j տkuX, jEV  I?~.@n>9z Ȫ~05w|YuT,@ 93  F^}¯ݥb ȴoIUg}, Wu¯b ȱEis(  Rdkyiea6z~ ~¯b ,o nkz, {s  h_K'y	  c}_K<dI  szak|, r[ `N{uxn ȠΩ  Z\Ta c^s7dx tnk~, w=  [4_Z<7Y qS:z @֪@@eSZ=  {w9`Ltb ztSkbY a#?= V?8' `jT=@ iE cV  RĝX3T01}؇R  =a r  jnH]>O?1{޿D:   ԿT 1ۛSs  TUu	R1, ƠE8  9/KĢTL#g  ?~^id0-.Uk  FݞƟS`]SL  6{R1, FoMߎg  fTRsb
Y h[Ne  .Z~~)d0  LU=sTl!Qk6|#  ug0buR  *S'b3Y P͕NUk]  f`pg
L #Tg  0#~=\!`Djy  BթX~d0"n9%zV  s}/b#Y @)S  (ܔR, X]=  99 ο  ̱{RxN -}A*Al  Aş9@`3=  yR(_~g jvz  ̣Y?@Ps=  yV5K_~
;<Uǣg   ,	?H@L=  RJ?H-թ꬏A  ^4,", w=  Z|Rt XsץkF   @~&Q Xz=s   5jB=s  @s~6QY ,Pw5  @Xj}DZf 5W'  Co3`]"z   #H*o~NQvY s͝~,Ug  0Bg]YE`/ѳ  1b+j*lًR  i?()y{g
  0uwb65j|dT>  qvQK T?%  +>/j"y|Y  ?Q, ! DtS|,UJCפ}HOO~\so; s0j"yhp39Vmxt6mLkKo/O6:轩Rsk 3+^)xwj9S{?ww.&!,s`>~U=? ~'oG"?CˇK$.Z0E	-Q#, E j{~-uNg|אթ}Y;o8z `_7:9)u޺?V÷7w{sEt?=|" ջ|5`P{:'Ej}_ơ.oHSf(y z;_6j6zP/UNKLc~~=0ÿBUO/P;ƿ(9g@-Lzpsg:=w^ï%`USKYf0GM~3 c&?پ}Sd_˖l3u6y=s_), G0G2xxMs^?\sǗ_L嚛) Y*ޒE^e0.;zF da@9ycsvMkE?| 2y,3^ m;$U'*:<O t͸ίKWTC
 ۾>.Y6!T L=5q<pWSxJ_g4Y ̲kG(qx!1z~k[]_0_>ϕr`6= Fߠ7G|ձ/[; O͝^?˕r`?z& XKjzMV|wJ[D?4J̿jdL[؈{o󟜓Z#Ws[2
0'~Yd0:'~:z [ۆh~>_~'|nE 3lpυs `$_G5&JS?c6C 3}S9 \sSjU͡^[6Rkwk5>4#~ uNT,:|+G؄Ui5>6(U~,!u/X4-q]	psǗiq`+}5wM;z>y7 Xg0;<y`\C5-i 02Gnju ivj?wUg'kzHhf0:I`~UU_:5W:|Jm(7F?C ="|&1Y Lߊ~̛UA#]s kWd52)6װ4E?^Ue{bg4g~)r=gc 7Փa
tkXZ뢟B !ʵd0w<Sk:zJ)T>sX`
5W&U6Dl/M;Ί~Z,Ǆ`5.)=o91usUӖ ?*\4NY LG?fmg4/M,JF? T/_q`5wyUY:~2|JQ紿@ު2knNk4, |]TZ:?|u/jCipw9xjxeUcl B;ύ~H=GGNJv`ZSipyw>wFjdfjc [Q)exH*\sS_:uNljNJf 0= uO|FLUg&Pwex:`=#ը] ip˩ѣ`z۞g4j% b_Y( i j>ڇ| ~vJ#n~\0dx;o'`D,;Sk>7Q}G}0 0;n**/uNtjܷ4NY l5E-*#5w}c̔ƥ7~ [7g~w-.|I, XR`nK]?31s?๪?{I#~=5wzy9`c= 6_]>4M~&U0="z&lRVi}g3~*W:=Wk 1Q嚛Ssk礔E|䦪RQ~_*(~HG#\#zMsRʪ%ۤmߌ~z3Tmx$n==u_<Wif:qUggcO#7D?́-p߾Ԙu [k>kTmx4lW-6|VHŘguwG;Ws'gTZBJfjZ3o?+8|&HEY <?= ~HχFNuᇈ*֤mgKR{Rs+ßRQ, S甿 e{E.Z|tobQ\*js	04T,}A\jVipYc O9}^ˤb M,~@jéT&ߒ\+zxܷ>ۗ~  );u{gFj_|( <hox>㩹QIigl3>z)>%{2z,@}#ueG?%5$g|@GBI?̐GnHkMS?3|Kd睤Ƽd0ْmokR;5w|Y<T%zLܷKcBe0K8}ѳL5    IDAT>>%m־?R=-`v璤Fh 3Pc>%mi=.`T>tM]Wo~HjT u~jjbXm47=6 rG:~69KJS`֩꬏@Z;砤)\=԰'MOݳ)Pj}sARc,` /__OG:O?s[q߾4~9ss;RE3P]O!ܔW}Ii!`{Z_fѲG	cZwW_:uRjT,{acYRS_ ^_`o8:|I}!=RQSM'9_NJjǬ$ hcX{;!|Iz+}?ؔb#zoF^ 5=g9lnTy]wgËiK*ƤZ/ ,~	jzT,.|IZS}VgG 59/瞤wn#9P(n=}GOlIR1w0(U'_g(ޚ%[>IRĝѣiOޅ+R,R~js=Iae?knsgSkwbbǌ$\m <|@T&`U9`}g|1zo* !IT@_hgR=vjZ߷UI*F. ʇ~j|6o3jV=٪:O]E+SK]-IUS굢_À'ia[M*>z?KRj B5OyL}_S/!0?%iW@?~j{y')߈Cct$A\ .)u]VyFW5Ku7{/IJ?[GGVӢ_.'|Isߦ޷?Vq߾$-j 䬪Rkw:I#V|𪔥JcG=s?REsIRT[ 4w|gi`õG~2<_߭$1j TY9gѪIi۟X{$5fU ?
dl/d:IUs4qo|KIs^ +~26ײ9'i4]w
saRR]`l τ9IYs+RzbAgR~}TĢsK眤{ΗouKۛE)>$x^'.>8uNgSd>IRj h7g1e?5W:|I:۟|+u߾$)ͤZ- g|qRyn4&M,Jmɷ_6g$wx sg}؇^*}j099WRsׅ8IUkwb6?$Qj (}L 24;M$I*P} [oGu'I$-|Y 4wKQU.oq$IRj hc+$ITL, :~6 dM$I*Pm w>' j&I$S6'ETXm|$I)T@g 3[Om$IR1 XR>+ OM$IZ<j hs!o$IR1j hs^+K_>$Ibb9
@f\>$Ibb=
@fz>$IbbлhUYL?m$IR1j _: dg$ITLZ, w}V 2R~hl$IiT@	k$IR1j :OG7|I$I4~a_m$IR1Ͳ_ z{YL>$Ibe PK͝<|I$I4~9O
@FsM$I*fP9_>/ ):|I$I~лlǇ5I$A/ }^ 2һx&I$3(oEtO|\$I|ꏅ5I$A/ # dϻ$IT̠ UW5I$Ay/ &JD\;X?$I/_ JsM$I*fX֞o>/ )"|I$I{p/Fn=-|I$Iz0u] sasM$I*fX}^ 2һd&I$3,@>/ /sM$I*fXDtO|\$Iwע@F&o+k$IR1ò^ >$ d$IT̰ }^ 2>sM$I*fX'Gxw\$IgGOsM$I*fX{/>/ i&I$3,@5 #U	k$IR1^ 9 dsM$I*fX{@F%ۄ5I$ay/ 5 #Ģ&I$3,@wCyEU4I$EY/ R9>2 g$IT̢| ^}\ ro5I$iv\n>$Ib  #U&I$(o>/ O5I$E. ok$IR1] |[yȉ$I.a s J$ix`wDTe\$IY`wEg$IT̰| b6M$I*fXKYL|&I$3,>+ ixEl$I_>+ i&I$3,A>+ i&I$3,}V 2M$I*fX!>+ i&I$3,}V 2>M$I*fX   X6I$a. | 0Gnl$I`>+ &I$3,?}V 2=M$I*fX}V 2=M$I*fXo>+ ]"|I$IwOD7|I$Iw
@f׭m$IR1] |uYSg$IT̰| ;< dfpwg$IT̰l G̔?$I3+m
@fm$I♕`bQJU}^ rk6I$iwRُ>. )o>$Ibe :
@f)|I$I{~?>$Ib XwWYL>$Ibe .9M$I*fP}FtN\l$Is
@f,	m$IR1^ rJYLg$IT̠ 돊>+ tbl$Iઃ
@f^>$Ibe }w;g$IT̠ ! dm$IR1^ tJYPM$I*Y3}N 2'$ITL < du$ITL ~2 ds7I$fY/ ڇ$ do$IR1Ͳ^ sɯo$IR1Ͳ^ 4wK9P$ITL ;4 d&I$,diЋ>+ ~0|I$I4~Pk
@nA*n>$Ibe (- dۛ$ITL _}N 2:M$I*QgFu&I$(@#	@gS|$Iiw> Co$IR1_ |{Y9$ITL 3> d|&I$(@OEU	o$IR1_ W, 䨪R3N$I*X?}L 2g$ITL ]}F 2>C3N$I*Xb6)Ue9P?q$I⩕`q#UǢ	@~5|I$I\sS9P$ITLZ, w]}N 24&I$SDUo$IR1j ]sr/q$IR1j .09Dg$ITLZ, :'eT{o8I$BX ELu?g$ITLZ, Z' dw^3N$I*P- ]}F 25'I$Sb)Ue9P'I$-rX ,nj GN*l>$IbfP>xU1Ts78I$BY o>) d}Gg$ITl, z}F 2933N$I*Pm ݳ9 dw3N$I*Pm 8 dӉ3N$I*Pm C9 d|'I$[6?}F 2Uu78I$BY KM*	@;.~I$I7]} HT8I$LZ ^}F 293N$I*6S O># }{y$IT@}@>$Ib3j=g SE8I$LZ tD
pbQ$IMT@_># k9'I$VD9'I$Vɪ3_
q$IRj (1 dՁ3N$I*6Q [O># sQ$IMT@ﲽ@bm$IMT@[}F 2\9'I$vѿ}> 2>sN$I*6R K Xτ9I$H[ 4w|i X=$ITl- &ZODL8+|I$IF|3{g$ITlZ. 7}F rUUsN$I*W- w>" k9'I$ϫ)}> 29O$IT<Z. ڇ}8| dwNsN$I*W- ]}> 2ֿ9'I$ϫbbQ:@ʵ9I$iWW>|]ՠۆ9I$xN] o<> d;$IT<. z> k{sN$I*Sm "| d{޿9I$xN] @ X#$IT<. ^}> 2V>tM$ITdU3^+Ks$IRl^ ^}D 269`$IT<[ > sN$I*޷E<|I$Iųz9O@>$Ij h cպ$IT<[ Tg WU;,~I$I *'>" kKsN$I*, ipY c>>$Iz}> 2ֻb9'I$ 93 c{.
s$IRaHC9| dj?EN$Ij}\nou$IRɪc c#;|I$I-F{q X7|I$I-F_}p Xc$IԲ hW X9'I$, c ge?^>$IT, &	`D̵Y'Izg0ĢTu> Y'IT, %9I$;g_sh g9I$;g c$I׆:I$5j5w~] \:I$5js coC$IRY <ߎ> sN$Ifz}> 2V>xu$IRY <Ω> 95SdY'IF- x/G̵yg$IRY </K@:'i$IRY <@z=|I$Q, 3@&m$zI$Q, W❣@ƪX>$IԨ] ϫsE5xk$IRvY <;@:A$IRvY <R}> 2ֻpE$IR[ 
s$Ij.ԿX>$IԨ] sF5wyC$IRVY lr@G~<|I$Q, 6T@ƺ,u$IJu`ko> rJ$IRVY l> 7|I$Q, 6QܯF5W:|I$Q, 6Q{Ǣ@G|4|I$Q, 6Qsk@|9|I$Q, 6Ss$Ij&4$I`3.Z}> rVUg$I`3u>$IԨE =l d{g$I`sMlG:I$:d/> +!|I$Q, P@~*(|I$} [s碏@Zb$IR#, :FM.g$IgoR9> _uP$IR=)T%| d|9'IFY LD۩Xm$IR#, P/G̵Y'IFY L7~3l ds_:I$5`
5W6l dwN$I b@
s$IjdzZ ٠e/u$Ijd^$x du/:I$5`EuOB$IR#, Xsk@>$I6iT=u_ X9'IFY L'EUejY'IFY Ly}< 2>CN$I, FoF \>$I2i\ʔ*| du$Ijd4}> 269c$IYf07}> rVUUN$I fs}< 2o:I$5`H \N$I f͝^>n2Y'IFvY ̠ۣ@ƪ9I$5`o8:| dg$IYe0gc \O:I$5`P \N$I AOD<7|I$U 3\ss XZEN$Il aVG̵|[$IR#, fX/EuY'IF6Y w@z>$I&E)z c{/u$IJd0Gn> 95SdY'IFY ̢}< 2?:I$5`uOB \
u$Ijdl~y7l dՁN$I, M^Ҡ}> 2V>tM$IR!Y6yq0o1zI$1Y ̲ޕDMn=$I, fY礿> Y'Ig0_>> _Y'Ig0&d XY'I4Y AΏ> 9\Y'IXg0.Z}< 2^Y'IXg0D \N$I`jg:I$5:9zY'If0Go:1| dg$Ic=g s<|I$1Y QJ \g$Ic\KR* c:I$q`+~ Y9Hu$Ije sXâ@ڇ}8|I$1Y aS?}6 2=kﾣ:˃o,7 /	%|!$	$!%!7@%B!@
Qe\#    IDATdc&7a^
]lI~5c $}]kk3}fgNN$I`;D_ ׽Y'IDf0̦fԪF_ {8~I$)Mb C{E@|C$IRe rK6 
y쟇:I$U&.!b0JK:I$U&.!W@u4|I$2qY l:TM$IRe AN< 
~{g$I*j;+ (_
u$ILT #qG_ ׹N$I`v~yJY/ (l]N$I`D= (nu$ILL #s@5X$IReb Q% (;:I$U&&Q}ckw>$IT, F՜S4˚Rujf$IR, FX+Y'IDd0ڗ}m \φ:I$U&"<ᯣ\sX$IRe" 7o6 
Y'IDd0fHY@eYy'I, F\gE_ 8g$I*`ĵϟ}m \뼩Y'IJ qe6 
{9N$Ig0jtPpYsmNw$I:1; (>$ITu ckZs$IR%Y ֙}m \ƣg$I*`5yPpg$I*`6n; (ڞw$IJy`L6 (u$I61չkW,u$I61<@>|I$, uSm症;I$UrEʚk/k,P$IRc c{y@ϟ>$ITe c}@u:7|I$, X?6 UMթ-$I*`vKKvw$I.1}  (_u$I.1׹k:7>$IT] cuN@e
u$I.18@	m>$ITU c`zk'M$IR%WY [uSPpu$I*:}m \oY'IJ y碯˲T[y'IJn /! (Ʒ0|I$, "k,w$IJy =F_ ׽Y'IJn }@ѵ:gy'IJ. yǣ/y'IJ. 룯hN$I\dXk:>$ITE uo=% (hΞ>$IT	 ֊E_ %PN$I, kZS$IR%<jK׍6 
sqN$I, 뭺) ( H$)Y ׹k-|I$@pS?}] @s$I*Y D }] @g1N$I, ku;I$, rPy'IJX 9}@	4Ol$IR%,<@	tn8*|I$@;IV:e1, rRk{%|I$7e<oSSo)eTu_ I[O. Jy?;IqWgR?KI{/N]/K, rRk| Qo;IQ_7}4Λc\;¿Qf`O} |I$!O3:K~ெF@N-.^wHO[mћg$Itￔ5qo;G@ꭺi^g<N$ic_߾hoK?e 9sa#@t[>$I~ίH#>YSe 9yB@dO>$IRy}</¿? GxJg$I*}9~I=a yjjfZ@	4OT̓$I%o&Is¿ gu01@o;ITI:ÿ g/#1@y'I&/y}Yf|<1Dm7<IæfnpV*# g|}c(/'I<}ީ{%w0/ڭ?k{(q@$Io_KG~J+2ֽ=Pw$iucS׾t a_~%Q[}̓$ICS}# 5@(機y$iӫ3O}ߝMU~ZQ+lG@-.^7@g$Iׯ~
QXy2[uSc(TE̓$I?jVd:Ks攲,)Cit>$10, rZݹơ3ORlwOJsfӚ~.D뜯<IJw~5O	떆?NF@N/' #ѽsE̓$h/xOG?vF@^?PF{Qܓ$iￔϹouVxa 9{υя$G|0|I4)}չ( q~%Ѿp'IdܷxmFsIᏹQf|"Dkg$ITj,Pj;+uo[Df̺8e 9@YdTUsO5wT?מzcw>s	fD$Y̓$i|7Cǆ?VG@o ơs3Oa}6Wƣ 3 D=3OM`8O#S_Lӣ _=$IzΦL>x)k7s {s4>~Ic/Gε?G{s DVߞq~ѿ)5Qf0/7 %פ'I*}Ct:(|2	y'P">$I}Lğf0s Hk$@ѿ`?2	)[HY J{׹3O4?k}>jY LH[O>@Yt:EsO@jSrR>}gmY LHA0.
{|ܷhkܷO)/50	qDD>$IcjEA|T2j?7L0IiދSuPU+$i$v~Ejohȍ9;Qf0A6< %RsO4j_?R\S<_?`&%4!|I6GuѿN`4>,0	?ƥ{'Izk_SZx.l2	FLZTm$ayye =0V}TgY(Q?Fս3H'InjܷߊPZ#`j}D	D5w=I*}]C491, &7/L %E=$ibￔ~t>;FU[]Jn Ju濅>I}sJ%;o&\}wϓf01\ %ҽsEܓ\5e/~gjԹ{䆔zqAo1#`\u` ʤ(zIR.ￔDdFkg( 0Noq쓤qT[_*zcT94, &ڢ7Ed:W>$ioqv\q Z } Ug}ML>x%e}RދS4+#YY5, &'Fdox=$iۯ@ek
]`Bk(֊>IzKֹݷlVZ Lf}>{Q쓤q| ѽY6, &9[ԮELzT['Iϒ#vZ,u \C0N"|Iҳս{#pϲQg0/X}FLV쓤gȍ#p+e`k,HJ&>ekk_k,u \^ܔe(!>$'HtV|=|:	sL=g$mмEF Z}1~8	G =qO쓤G#P c>>F<S($w0]~`sPO@y6, 
PLo'I]e UlY -'G@ԯyG"0,Ul>F@jP뜯?I׿-	`:Y6, 
P_>/@	<|IRεߌ=Y6, МSjףP6Y6(unD&\Kg8 (H{/>3@	N'ILGlY EEw>$3εϳ1dPG}, e.
[mWGOB >Ƒ@A-|eJY/ %<gV_1@쯔cfZ ު(3')51@
g@? eiڂgr:S(a>Ƒ@jg(YG P o5|#U5΍G@Isq#(ϳqdPz}vʚkSu63PRY&\x2|+չTcGgU=zk,W y_G:>%c{y6, 
VmET9(<@纥噛 +[swJy@Iy?D= ,gu;"%7(</=z:_ٸ (`͓?}jRmK砤rԽ@D` (`Eo>C@59(3zP?}l\Y PRۖ@Iů`,zP3m\Y ΍ߎ>G@Yu[択]GO;T=#|+\X砤b\Q@o-lY }}~T:W=y6, )[*<eRm7BI{%ѓ(8 (pO>O@V|=|J*hS[ԪF9 Zg%~1οF'z>%q@A4x@q/!<%W_c,T10,=W (rHYg
(eBIsa(Z>uo[}˪SuVPRZ=ހȚٸ (x3\%XY(84^7z{6, 
7?$zJ*Nk@Ato=%|;Rcg(n+vy(/9zѾh6, JPPr3-|J*F{/i@A4OtLw %G zn

mR4GPC~#~9T-g y(ik;ѣ(.
k$eO}\uP,4ٵΛ=ʀjϴ, JRâPrYTy(irY(
{%3-"<g 5Oy(i2-z1DZD %kRʲs\K硤ɬyG0@Z|5|EdPzVF3T?]Pk4@j_w9H&3RH}߷϶, JTcG@ZSmgɩdIs*< (OۥmG7:3QނH[ZT %\ z>%MNշD-@:+kQY @DIF+`Z*L (W~;o%m|svW@4Xll:V5ޓ碤\׻iLm-*Yg`}.3QR~攲,zT5>Zs|JꏧEIuT
{%-2V?WӚ~6|.JgnQ@\>" (cgh譾/œzox
u=[- YG~\ڗ=j-2-@^t\>%娹x"0|Yj;"~fP}'%Q󸿌I@eO>ߪY }Yyl\w/z$ԹVĵ//^7~Kl[}_L`Z+>35}$l#ڗ=jW{qJF9z()y/JYI 2~͊unQ@=g˿==~G :+g`Cj(i͞z=xt@ɫg>%ƷXsd=y_yxWt|4^=yks, :}}.QxYKۅϺj Pj#	YsWH%{#([\5'Y (v~EJNx{HIdsJ纥ᳮ, 4{ET[}4?3z :ᳮ, 4uNYuf4_yWI zꁰ/EKgfT4w=a˚kSujf$ =]=Yuo=%|FJn?=Z/]5GY W,> ϩq礤!5{{@Y3oV~ 59K<G
PWEϼj 4w۔Z3
𜚧|&~VJ^^''@:6soV~ uo;-<:v~yϟ=J=xU̫, mPs)j_[ymR=Fh_Oܫ, mPmy@u[祤M{(1{՜eg-<{QΞ>/%m|"zt %f, =;GU<o祤ٺP"}fgT?eW
^KGP2}fg6{F=}f^PCgqJ)EdEϿj гֹ3²,5~8|fJz?qo &Rm׆j г8-F_\l>7%=GEz>9@mR\}v6J禤jѣ(՜fsg`oMIOURV<z2 %8cs, 5OѲ.
R2u(z$ e$|g zj;"n+l-'N/;z %ֻ9Xq z޺w}6ION5ǃ[r /X>9@[;}6I\7=??w@j V6Z^>C(ު>PvZ6|&Vs^CDeMֹS*ES3SG uo?=~&w zZ+}6KτP赯?NXy zxkY<F9*֙}Vsfg   IDAT, QDGRmׅQh5)G`ms:Y hj7'LlރWyS i5͔Z{d/GiixtΞ>OIdǔ5> hX, _V0W>KI/lV5Un>#6;GmikS<&ke> нY, ՗;lL_ɟ$U[}ʞ7</dM*[sW^'5}4|JP}_LO-sYY, I/#|G>x'*JY
z_>+6A> CO>[<8ȽyS:AY hӚ=m @dR_Rj,]3:AY hk_K9D*)Iێ> /3:aY h/!]=|Ja͞Z͉> dsdeͪ0|jj|wg4d9 ⾲Y h,Tj{~. $[H"|V', mV}}FGQf74
	@]=u?ZidSJY/lY6֊E{k_b)zJê˫S޸:gyZ, mRE\4Ul>w8lG
`Z:7,	@Ӫ`,wj^>wj}n[[ &]cG@ӪuƗ?)g)՗{{iN tz9 06Y퇩q_7붢t>8~Κ, 4?#z WZgś*|O=tMI77|V'8 M񟌞 !}j;b([pN	@oދS\= BVݔr,V=#5O۔_}$ FѼvdgԹy -[cH{.> #W?gnu³ Pj|@}o*G=~nfX^A.3kY h8"eO= e͵y
[mKS9)wi_0|VVݢ@n?!MYj6u>l?gM~ Z= :w	n6WxPVU+gbd{ ;Loa/>
0z&WZ սT-Z˫R{SV_m.Ղd?i ϡNLEۇl>0ԪF?JrsZ, 4m>­kEjԽ,Q	;eճ^>W 6coX[r֊ $Ue75;l~/9~sW ?g+ Dɔ/\E:0Q3zWFRou/#4u(5x:|k_[}s`""|WFV@!?np{
zjS{qC`5>|WFVOE=xUjEofo//=#Pũ9?xY htݭN#uo995OT[S3$v<Sg1)=( (ޢ}Y hu94z~ _;xy/?>ռ޹&~6 cP_?Y h_	eYyj7'5-o 25}4/{;(@xH =|](v-u\Z+>XV{ypE妃w~P۬7TF^<ȇ.u8;/%5T[ciދR)ڗ\0t #?>3f7 z3@O%{KvOktGijZ<6u>	 [EG@c}y&}^΍N!l=xHN_|_o *_[@c#aR{ԽO-
.w-HsvԿyRv0Ŀ};su==wSKNL1X@dkܺ @qu:7Z, 4]=W  jj	 t  ekH9[_TKmRV}4z   9:+*ʑZ=  ZT[jI X;|  //Z, 4w=g  hY/~KIDY h5}$z   ~mR-Y gcG   Pߎ6U, R/E   HkïI%@!lƓs  <o¯I%@a/'z   c{(Ul~=R-a 
w  ʣuW¯E%@uo?=z   c}R-i 
qG   `L8 [2z  ֪.8 \Q  Xҽï=^@6eG  t۩=J^@yuTH  Fs!X (2es	  ^7տkU, ڗ=  !<&ZCA MEۧD'  `X^/~g*, A  :7~Y (WRE)  `VsG  0M_[A ]U  t_Pe, z_=  Թk
UrY󸿌Y  }M3 P>z=  MԹ	g@yҧg  ):T<k oS[l]#  HPz, 뚧~6z  !kO^~sf|7g=qo,  ^@YJϗr_e  =_~f7w@  yg^( MD#z  Ϣm7fP d4)m  Oh,hduWg  c\~FgiދR  eY	J&w5z  )c¯T٤, 4Y:eku  PnF->@iS <  Zylr f>j  l:%J&񟌞{  PJ"z@@-Rg  JKRu@[=  <zT_Cu*&GA  (K2, 45` ꏧ.ʴ Y  
u??WeY h):3  
ȍ:e~Ud"Թ  œR_P P!)  
}UZ *LEG  (l#+2, Tj_uGI  (1P Pj9	  3۫2mTgbi753V=/ `rkhJîq:g/FFe  0Z^T?W?JuKÿiXu:7zn Zs
>Hj[sU_4RJN B\^8cu{<Tڗ=B `b/%9*#y?Jm{¿i F=z[69*#u~ޕ?ba<g)  [/*#}^yq¿i"2z @n/=y8rg^i;Hdǔ^\ =v{{QsvUR?J#¿iTu=<z @^?WWele'?J¿iTv}v   ~|?J/He3:`  WL5O+_4LU+#,  \iV|mTѫ^o @V|=y*c{). Q׾rI 0{/NթUogz@ga҈-xY>9w `Ɠχ?We}X"F]OD]  <os\ ռJR".  ]g1ϿU	Ywgq8G_  JLs~u}Ҙj3  #ޭJX# M]^EJcijf=t͘0  G{s+EֹY ~>U}):  0r{.Lթ-ßomRx ΏB1־hqb  gv٪8O z25w[}˘1  ]l`i 'Ywmc$ ȴ/9*x=6j[sOZ?kF-1 `$^~=?6w[r3  F">j{\sjxxؤ@spi  0Y,5XsiUrQ~އ˳. jw<\  ϡUGS[wn}Q i:a  3RuϡPϼc9 wiR5  Ó=qOΪ9[lX !R@sgs> 𴪩ϙUM3m:zCڒ1؛^<	  <//+ڮ?CX +T=#%ڞOYah  %{?OV%Wu>d?/ k0  ݻ{sdUrS޿oޓqRDNgN eOޟj&*U7mh }+jK؜9  ׮fӬk?wJ !`GJ| `̛)d [ۭ *m|  `:Aj_z}O k_,,4{Խ{u  `SuOdS:7~{S k7h)" 8t$UnW\:Kz\m vRDeI)M sɞ;+dC~cKy7U* EԾpi<  x6Ys]绪ڢ7li?6{׹iԖiMLݻϟ qjzouGzc
nO=<  ӾW|5%weC{M{:~7F
qo Pb?U%_6u:w, g5$::F  PzVelg菵- R7Jwgmˇy  (ꜭ*/<.FaeyWaҘk	 bZj;<*ws] P/ywJ(  {aUMޘznn$gq<Fu  (T7ecodI/fJ}^<V  Lv-笪IJUo[Ro7U[S3Sgh 0i8⟯*墹^9?N#_ kS?Kc|c `y'=~ñ, ,.7m7[GƓc;b  TNtSU=#N?n#շ_KcCm/  :?ß*oI;X`Js!Hu3  Λ
>n;xv= RߊH#sòȣ @%*3R?O] dYj<.U|cHUsM>m  ICR㛿]&~ڍԺpT]4j6ek>i  X՟~8{) ^c]j}oa.|eOv}ߖ mekj</SSnf5.?9*ơR}  ΍G/QEۧޓIR婾ilIŨy_O  CYy/35j:5OluD~w ?xW^n> :7r޹"n;MZ Hv|WhRk_8( 0Op_fo떦ޚ|_ ?X:g|9|oZ jR->B  l'ꜭSji˩죃w>$ulpmYdX <C]:WKT-}QE `Ssɩ8J;VWkKeU        (    (    (    (    (    (    (    (    (    (    (    (    (    (    (    (    (    (    (    (    (    (    (    (    (    (    (    (    (    (    (    (    (    (    (    (    (    (    (    (    (    (    (    (    (    (    (    (    (    (    (    (    (    (    (    (    (    (    (    (    (    (    (    Hla?    IENDB`PNG

   IHDR          !   	pHYs    {Rk  wIDATxi]E!
%ZP,e\`)(E)qM233$1+$Bod'IHo$3w_X#&d޻}杯=v-aRDÂ11111111jN``t=H.ݫ)rťO9:Q)o D?= L; o<dxaMS(<Y^geFJptR"ѭ-[g5.{%-z "M=j$+m,4dy	i.ju7 N9s}yr=m`voD2wI3l0Ix[unW.V>zokF7\	δGH.mqs4g*y@8JŬ
^`D&H2㮚Ms4;
2y+4umxo%1Uɑ`B\{}4t`[0O;iչbbLLo^.S0kx`pMOs$;F٥z	f4@C$@*v.+@lٝ^y_Bxb'UL9XoUikFg#n0^`erh򥂒gujcQ絟!3!4j".K4ְv`{R_5N%Q oi轨bZ?I@':/=.W
3kMu0BD)c+|H,`i@y@e)VCQʎ`2<,XIKN-eer5⟙^6>ǂY~,XTEUDi+K"/zrVg򯣥;ˇ_s\Eր&ዬ=qߐwW
أ<sh4 {̽`kH]0\RѝZ	=om~f{ʁgSf-
*O®X?n:NL~~SqSYn>W+OϠ`8ë;xgPLO0wAwq]u29D<@w9O+O&'v]18	tzkʓ!	u麣#'X:"`׀`dr蠱}Ny29D\ohv21ۿt~ʓ!	^
L|Py29DLqg^y29D<dz$*(Ku29DL	,SLO0lyjdrx9a"=pր(O(_0QP`Bmj"TTPO0;ᾕ!	-/]0*{rAS0?+O*_0<vDwx[hѺk1Nx]I AGqts^PSyb9Das+pSՉkIlh6<Dg]lRXO0o ٽrM~(`[yr9D6I0EmK <t_?Vyr9D3 #T'C<~y٧Es&< HW`f޲lyJo' 
FaK'lnoAS0wa@t64b]sT'(-$ΐēzU'(-Fxt3<_y"׌
mi$3Q ~NՉ6Q`#݅(,=TV)RQ":IR85`*=j44jxϊιDx+5sk&EpE@kʿ<C0~ʎ.*`։jTQ؁qg=U21l
`&,=@d_Ut~4!F3nJ}?Q.EG:~ު!65wգGuP/DMq9w
d엾g!4%ZU ʥ1o hڍ$^:Pq@}7p>;/1rcí,p]i9FxlLcnv'	$q٭MjsWIWUd']q|W-T>Ge	0
{!]/~q ;pcPAI`,۲'(&;d &[`ALF#Le:QDo\&v/_S X:lO&.hC	}rr
hJS6流 w@uϏ1Ķ@	V,rYn%uh9Ӥ!31F{x O*3T+P*j`:>	gzxȓM5z.Ys6KNfWvT^/5y]cj9`IOS2모ۇDgNKAڧ*؄OuIv"ʚÉ$1J']*:Xظ+%-q_a{
FFI|}㙨C,Z5ƨJmsȔ03gz	L^P p-jo0B!8L0lIa
5-j.޲>S7ɜ	=?`dbf{e.!Oͩ^ުs=H0g=QE['sS #0#Xi 2(]8wiuf&E<<5q4%X\2gZFiľc뎀eC׋!(w%5v$VfR7l8՜+Ut<KA Cp&<Mcm{[!\;2^X)d]\9Gms	1SyN,eVQO;08㼂1L`L`L`L`L`L`L`L`L` -tJ    IENDB`PNG

   IHDR  T  p   [   	pHYs    {Rk    IDATx{u}@QTouT;Y:NviGq\첳tj]msrn*Br	.n"H 	0rTVQ9^k}.>}	     '5      
     @     0      *      
     @     0      *      
     @     0      *      
     @     0      *      
     @     0      *      
     @     0      *      
     @     0      *      
     @     0      *      
     @     0      *      
     @     0      *      
     @     0      *      
     @     0      *      
     @     0      *      
     @     0      *      
     @     0      *      
     @     0      *      
     @     0      *      
     @     0      *      
     @     0      *      
     @     0      *      
     @     0      *      
     @     0      *      
     @     0      *      
     @     0      *      
     @     0      *      
     @     0      *      
     @     0      *      
     @     0      *      
     @     0      *      
     @     0      *      
     @     0      *      
     @     0      *      
     @     0      *      
     @     0      *      
     @     0      *      
     @     0      *      
     @     0      *      
     @     0      *      
     @     0      *      
     @     0      *      
     @     0      *      
     @     0      *      
     @     0      *      
     @     0      *      
     @     0      *      
     @     0      *      
     @     0      *      
     @     0      *      
     @     0      *      
     @     0      *      
     @     0      *      
     @     0      *      
     @     0      *      
     @     0      *      
     @     0      *      
     @     0      *      
     @     0      *      
     @     0      *      
     @     0      *      
     @     0      *      
     @     0      *      
     @     0      *      
     @     0      *      
     @     0      *      
     @     0      *      
     @     0      *      
     @     0      *      
     @     0      *      
     @     0      *      
     @     0      *      
     @     0      *      
     @     0      *      
     @     0      *      
     @     0      *      
     @     0      *      
     @     0      *      
     @     0      *      
     @     0      *      
     @     0      *      
     @     0      *      
     @     0      *      
     @     0      *      
     @     0      *      
     @     0      *      
     @     0      *      
     @     0      *      
     @     0      *      
     @     0      *      
     @     0      *      
     @     0      *      
     @     0      *      
     @     0      *      
     @     0      **H;.KkIsޝZ>^X8!5'~7s_   +z>1v'l)oHs:uwMUm6TfJggyy~sIj}OR/*O{Svj  	$U+_Zi~si͔EԱaP[2o(u.P*OT,ZBF9~;   ޕ+}njT~⵩sߥ.q6*{`ЏRwquS/i|])Uܗ2   7g=-I3ڒ~/X=!U4;R*O\S.pݯߔUK   XZfr+RgT<x[3<j{Q<w2KPwd   I$jR[s?֒Aǵ׼m=J[l   p?kmI_z{qYJw*U`^,{q_Ri=%%   3g8L&knIʣ_WJUtTv}NbӲBJcעR}  3HjhҧOjܠ2쿀X6xvK   fO5H*kpIѢ};i36ߐ_t'kSr_   07YZ\r59/>4)~Pl9."E_  35$lr?f<x[wc;T;y1Hs}  wR3$eojԹc7T@R*=3Y  |zej%-;d>U4njPrA*yY_!˟  僩%.':|U'c1TC}dTTmn   jcT~_KRm7}v_q0JRq1eL  W=T|~TV o:'TR7EVy䡩ڼ!S    Vuu\%n~HhH*MdKM\Tm>S    S%vuXߵ.Te\?pcʖr?   l</dM/Ik~HMddSyoAK\Tm1    w>9̹_KR+?iTĠһ~M*>-Wjb   7u˲ڶ9ei{PRJ\Tm93   :_jTwT[S.Rjh呇   )a|d/Iuwk2xTxRS+=3U    K5H5o_\ߛuTA+ShRǔ~*   k)_\yST7TzLV.}zܳ>S   aPj$֭x^{]*NN?$-9(f   hwrHR[ԿTTWJ?M]    e[n:,~. IunAKRdTW>zA   h-_KŢHR: o:كJ!5`9   zF IuojԻ+T:k' &79?_)    }0Y$¿Tf*k's\   V$-yjߵJå׻  HZT#;ރJog|o亗/   bk*W$+mwX|`o.y   `/: ,W<79$ս򸗧6^SqٿRߏ   WbS'HRk});1T<eٿRy[JU/w   `o<++HRk`PwS7dfJMҠ;:   0;zW~ IPwq=t.@oڧ>^k6/s   `u{O3I*ipTz\J}    0K>5HRQʕ/HFkPܿ!K͓Z?   `X>ZǼ4$5uRGcP:;|rsSm3}i   U[nHg?{u/_<JwgfIMmMUuf   jbpũX_3I*ܢik=o:'7JjjS_K   ޺!$ia6QpT,vo&g   p:g3y$-wJUg87GjjNK   Vj}$$sRK5wZoкk'g2   Fp}\k&$[nYAq*"5Η?   XrP3
I*j\XA/3&̿OiН'   `to<{mmrUHRQ-HwPo<?7Bj`';;	    oc
I*j\O|AI/MV_OÝ   ̰J3<$5w<Jw_Դ#n٧   O:U/$zTbӳRZ4皽  7|TyhsIZXϺWAԿ+{}   1sm*<C֯Sc*7L&꽺  f[<CֹCs3_Ԥ}p.n   YTԱOIM;6}7RCj)U=   T԰%AuRSj[i_    Pm!KCT2;JkRC*zQnwo    :$aKavߒ{   <C֫S[[R19?'}`r   }HzսT'%5c   	wnNf?F*>X_4u{L   <]Wbт TԨ-̠Y;ƽޜR՟"   'ջg!T|vH\븗a%   LD49?UܳoJi+~4D    awgjg#TԤ޺6>_4-Zw{!   V=xk*xF3IZXnP~T,/!kN{!   ֿH$IٻA{4uٸ   cOI*jPݻA\=٨}Stg   `۩uog?3"s4٠2غ1Ʊ藤al   jͩXrPI*27=T:k?hi*=+U2>    {ӲHR%ٳA<Z&=   >|]Q$iaʏ*-7fҸ[lw    ٰ#yYI*2Vmqի?Xij_R   `UOd?S"Sޠ:M4.Vsq   0cz:.$*U{{*`q\~H>W9    3g8~׍+Td<'T7Jc!]49    3jz8qsIZ8U?֓*7ơޕ+   `V:d?kb[J4׼Շ   cnYI*ăJzxmr?Hik𪔺\    ̞aڟ.Ta_{A4TT=p\    ̺a5^E9l}*oS'l`y9g    KÍԤ7J7epҨֽ9c    T~#IսP)=+FiRq   0:c$kJ4zs    ̹jMX2Tr_Je`5}u{   lzW6#IgDӃJe4b}b   |۠>bA};?(iΜ,    q*=39$;'&F:n~   ?<=Y$Xﺓ;hR)    9?S~njoQeA   aT~6TBs4
u7'    u5F}<\7ѿHMYoL    {HR1õN|soIܔ6f!   ^+V,G\<47ѽ|*M   =}Os$#~9nIOM   3u˲HR1SMOiXM?MzG$0   Ujg;TP駷gC#sSޜ   `$U>_~#Imɯ`ީ;    FZ㳟HR1Un~^(W2T~   `y/ImP93    IDATTʏmo7    Ỽ4z]&`ZhAܳ>}   X]stsIZslXFCur_    [}~$Aeٳ?)w3Uܷ    czT,yj3 I*]o_DFYysp    cw@TE6~   `UkIRT{澕    hjˍ: ${AE)Z#    wBTA5S;    ɯ>$Iw/]Uo    ڼax}F$IndPQck   @>ݵω$؍*jdg#w_    `M^H Yr*    s?_R3qu    ~n$IœdPQ*zQ?    ZuKIRTԜ&m5    	n4$-|*jL݋>    @wd?Gq2    ;r!ϓ$*&W    `7;9$-|l}K?    =1Re?W_dPXZܷ     j?$?ϠmтTmN    >$-Ym˧r   `_TLTT4N7)z   ]I
ƲN&    ſ$*zWo<    3h}S*xFs'IΠ[}   ޵g?{*-H}   0RSJRjjM   ,6_??>4*ZO7   YֽϢ$M42FEo[   vv?AE#_;   _f3)Iˠ<%)u   cS ٔFeP69/\o7    T[n\fP{s    ޗJDc2h$+W0ۏ   @FֶTyh*IȠl   u'e?4ш*:_z{    E5H;Ϡ\4q_?    kR19/ٕΠr}   :gU+IcAE#S?Hi8   nߔʥO~%ibl3h4Z|`%e  ?{nYz{CBK(9$! 8p!!!$@%Ȗ䂻-nnrؒgVyk/EgֳҞ&I$nciRY0.ǒ$I$I\wY@c"Y0{vJn8$I$IԿ,1,TmO}WFaI$I$QC?IcH+I$I1x֔(nhLFVl==%I$I4uZИ(*GE]I$I$ie{Uw,hLFRE\I$I$y+B3T<rK$I$IҸWSswiX0r:EZI$I$MH[OBy$I$I5^@cY0R=_%I$I4a\ﾀXPadxl$I$I҄>s_@cY04=W%I$I4+K6ύҸPa$t/\=S%I$I4u{01,T)T$I$I^y"^~4ƒ
Ἀ^$I$Iê{01,T:3T$I$ITO+^h ^=B%I$I4eo>9nHB0ӿ=;%I$I4~rJ+*wT$I$IҊפlf{216,Tѻr)I$I)}gɀذPa{m/I$I$)r)z21,T]GJI$I$iP笯ߗ`P}*zFJ$I$I?l=_~o>gƩ|)I$I$\w;ҨPah:g|-z6J$I$I\ů?#B0GG$I$Iu/#h4{ɷg$I$I)h@cdYP|ץkGDI$I$i]u`]Y*ԮwݲY(I$I$=sE?5w{s}I*ԪϻS*Q(I$I$Q
S#BZX=%I$I5,SsՀȱP6?=$I$Iiwk@cXPyg$I$IN@F
h'I$I$sc#B-$+y$I$IҳukҨPr3=$I$Ig]qS63'h*oTfE:I$I$ZG|<h*Y>?zI$I$IU<tCfw,TLS^=$I$IJk7Bt/)zI$I$IW>vWo~4BYP|_Oیm$I$IR-O2hP+i$I$IRmT`ʕ*<[ίM߉i$I$IR|]c³ֻY&I$I$^)A}a³oTg$I$I4n~'4BX=,zI$I$ICS6o{91t*oHE0I$I$i91t*G.I$I$iݘPYN]^S$I$I4d*Ig$I$IV)~O4B%I$I$:cwu@ch,TXk+U$I$IRxŊ
̝*|WI$I$?j;;1*{G(I$I$id*,h
k,_z%I$I$TWШ
k{.ѳI$I$I\~w4jg0UѳI$I$IZ~Ш
ksLL$I$IFF,Txf[o$I$I$to/.HuPuNr,$I$IFX歟GoE$I$IXmwz@
O}gg$I$I4694NhB63'+A$I$I|j*<a?$I$Iսd=Q9Rg$I$I4~uo=Q)TswFI$I$ilw|@R*<9$ISUy"O7SSSŻR̭~i_I|R~93KR}S>ST>z/$IT>`l~4*c/r,I$=^*W޷z9rI{^FIC?{-廼>_F,Rs7澿Z>s7޻ԿT7
K$|?}P$InMMvcuGSsSf#$łSs7CS1u/`qT<x}Jf$IHT<raPmT65$IQKOwL6/~Em;*HԻeB*?QI>g3Q	~lK$M]n*V\zW:5B ~>(<75}OjԻbT{)u?}IZ+,*Xf^*I4ɕS/h|L~HO2]t*H$U^kğlY3 I4I;<}'}~o13'5w>K$I^SY@z,TDIuN{.IKvMe|+WT#}˱*o$IW?WgB枿=V$I֪r~36x/G63C0:胃l+-$I7zW=S$Ip򯩹ވ>C䍩I;Mߍk*I;~7RE)u#E$+,7P,Pxv/H&o?{G$i^s	h3?'I4
ݝzWGr<w,uNT{y_kI5>8\h-i7Ϟ$IqE*,ufjS-%IR?ub2Zq$IV7'm<<tiԻbOJ$ET>~Om~.kBeo9%zHiZEʷu$[k;$I>!,TXӫS$՗%
cw徃$Ièg ,TXg$Iotʶ4k#ᥩsS]I$i
j?@cXL2{(znH	x9s/zY9R및+$I׻sֆʔj!IƼr}{vۛ6P9uS$I$k~C65e2}/zdHq,RS{)A{Je](I&93,TPsߎ$i*=uFw,,{N]wdJE?R$M@)Qh)ѳB$orjjG>>(ލIkgF,T͂MR|4zNHlL+Mvݩo[I4?L4ֈʔi!IFR/l熟Y`ܴߩxocI45}Oyh<#)$I/ֿxgk3sK$IZz?8",gb2Eg<KԻ]g87J9ǣ%IҸ|+1@z:*S{ IS)gt5&IFu.4ʴA*W=$IRTEWƟK`&XqOI4#)[Ih<%)ΟFIQ'KK|_?TA&InSPN$iu{)!<9ǀI'XqMyh<%)YJE/zHax%HţG?1$I6{N> 'e2:9 I,Ro?{ khMS߿$I?wq =)P<pm$I5ֿg`ݴV$IYKWQ/Pp='zH*9m~ *sRE~[E$,>/Pp/$IU8uNJm~ RȭяI\^};z,T&ټSjE_$UU-N sS}8$)? 鿲P`C8/I*繩o/iT6$IAo==<4~$Iz+Kc?W 1^\($IEwy]yhʄʷyc_$=`mi6~2I!77AYH?e2}.y/Iֱbթ	`CH$i*x0e7
? 	տcy^$ee9+)Y/,|͜%I>~*(_g,J˩w%D#10oԽhǖ$IR?L~ ,	~K5l='n~~ OO{o$IPY?{ IT{yc^$ALN
?; 㫹򱻢g$~ *&u$I+eN/^I&2ql~iWZLΙ[E?%IԿ30ao$I5>grd)*.I:^&}^ &WRē$I5pVY]i29f_N%IF{R?+ ӡuxO$Ps5 b*sg$Iz-Kv/?' e\yo#P$U\=M1	R<tC3]$^{G L|R觡$IBͶyn9)e2!)y.IG|5|X$I6δ3dSBeBt&Y.If_yI)_ /(I*̝N*xg$I]O35e3s dfNꞿ0I)I֥nw_GEwy}N'	\яuIhj332)I?xOrCdlޔ-84,T&@oF?%IڊGnI%o? [TяOI4YOONS및`;,T&@qߕ~I-|_? џIE?F%Iu^y,L 4֊ʘ¯K? ?I׎~J4?}S-Rsx"*cn%IwR? TuNی~J4y	ia2w=2$IOR7|TS^$ilhL-1o{,IҐ*灉5eG$I#CUL|\fshPc?=S$IK>LE?r%Ixo"1ֿ1#I׿ܔos`Z}0^++IP*r/dY4FʘʷyHTs2I`~|w$UZԻ9s{m݅f2ZY$i^_VOx_$il+[gۥKV1,TTG&I&Eg=@T$~Eo{O9$O{OT'q43'W$Mdg=hW)EYՕE*i{ONrj(|^a2{3z|I4uΙ>FM俏~<K(|foL71Y>/zI4Ye3`Tu/\$MxeԿԽ`ů /PC}WD8I&_ #mfN]u@Z4)y	0w<Y|cI*s;X~tBc[4ջ9+{Ssܵg2fM$ib0V~NsI[4V{O^? VBen8&z.J4/zً[㒤lJ;k}'Rs
 8Q*+g$Ic_%s`;f-)M}W{q M#1:G$Ic/g_=]swͣ뒤:*T<rk]{'}ߓ,II~s6o0)f?%E],+[g{	ܧg2F$m.L9zLߌ~K'w-N#?^>K 1a2&f2O~Inߜ/
 w͡яzIғUR|twls S*c}gG$IcY??`0<//IS_v*{oʶ4~F ̝*cwA3YL}7|L|ۢ4=g@6,TD9-IxUupi-l==$idwv/9m_Ȧh[c[sg84)igQ>kFw *sWG$IcUS63'|L[GI~tABeo==zK46_ fK[N	4r~,bREޓ?HkBe-x9$i~/_@0=$)nzyr.}ԧS 4Ν    IDAT_]#0X.%i+zxo;xe6ШʈLIuN/kEI'ݵ 4jg2w}F$itKG$UޓE/a2lR}n$i+%: =DIzԿԽ[߰kg( iTX0O$Rsl YӫS|4zrHVSuw}Ssy	 X0O$yk2z|H~'_\1V,TFXs$l[O1}*Q^'.Ie{	 
*jƃ$I\oyڛa*~Q"iwSw復}[ *##$feZA`;y%i{2<>KEmsTPQޟ"Iғ7sgo#x$i{ e2?E_Ssj~<$Xvfꞷmj}OS) Q4Ôy9Fo/~NP7M7GOI#ޓK 0Y>>H4ru/Z>^sw.V%MpenLN>5~ Ƒ|Fu$IzNsfG
 	e2z7}$it*:ͬw]=q$Ce{U}Q^d]. zXrՊ$I#Sg3 wybVWVCR-4m,TF$iueHʷI|`8'|!zH]t)[Is @*#}gK$Lc2|60\O?Roց< lXKP$Dŝ	 WKS==lL;;OW@6,TFLu*I+2 16DDdK' 0wX|_\ I4u/+|.w1Hlg &iG.I+|2 E/IO]jC=Pʷ{A. dBetϏ>IOSFd FCD%id*;O1׽tIjEjQ ȦrjLʟܑd FGǓ4 (P!F$I
}'1 %qT6QR=|rꜹ e2"_}~$)R63'|&0zu*l==aM= 4ֈʈhg:IBkyѣJZu~^xN^ BeD$Iw>d#KZ>kF; @2*#yG?IjY}4r=讃>7 P3륲2,(IRHΈ yb5ѣKSXz{O d29l(IRX}>s#E$RSS{٧Rk `2}.(IRH/i KG&' @ZS*#{GHIBj}O0 '\"zi+rG]wd  п3$ICx{Ģ0 }ԧG'w_.4- k*BLI^/a ZӣǙFnzyrɮ}_|ׇ B%Xs$S`9xkz豦Qxɂ> g̯K LE5\ԿY>Gwmw @c*Y^CTSg0 b򱻢*l\].Ie| ]B%Xߍ>J4Ժ>,T˓cHߒ9  `GXIW|}`a{O B%.K4M[>L<{O0 @,YjGg\IZsw_ &WGTV6mZ= ҤP	9ss$ICg/ -WRKW䘿LoF; @6$*z}$ih;l6z0}.zMNe'W:']j.}Gog P	T<x}XT揤l&)0^*"zM{O^	 0wtXDAJvyYԽpQ`j42zte{U}:v?7 lYi$Ié,\ 0tS[]'n9oD dcB%HOF%IJ[O L|O̾RSOͽ'  sa{c$IC}䟇] SԽd 	ew1nIj] S_c lXlI&\ [/{O  ҨP0$Ims6obb+T<|`y9Rsw  W*{$IW:|w$R{ 0wXh$I9g. TCa^wZG|<_  N,Tt: /I*)_ ?wUkn*2u/+k= ;Y,T[V!^>on<yWGwUjޔm  4jc`3%I'y 7E.O<=yI  Ce2l3sRyk+IF~'_?sIGw_.IcX]# F(!}$I\- <|?WKC75i_IͥHټs 9*C:n$IB?>o鴏lOg6	 @c,XY/EsIT_nʷ{A   *f2dKv$>k   XYӢ$I>k   XYmw]$SY|WZ   *4^u$ITY   0*C\.Ij|^   jb2DC8Kj.}G   jb2D/$i+GR6^   jb2D݋v$z>g   YQ$I    Y,TXqu}$I9   Be_c]$U^3    ʐ_}%IR-u{   jf2$ͥ$G|"|   d5Pͣ$I|,   @V3!o]$U^X   l,T{;/I*w3    !rj$I>3    !)A$IM3    a}GyITi->c   !Pm}%IRo=-~   !8I&yۆX   lH,TuЇ$I>c   !P񟏾$^>c   !Pw^$UZ?>_   !P}%IRo;#|   dCd2N$MRW   l,Tx{/I*S    "a|F{ITi+|   dCdRT^$UWKقg,   PYӫ$I[+   @6d*5k{/I*	    2X$Iֽ`
   J'}1KJkE|   ȆBf$I    ِYԬw^$UZ3   И:*5tb$IUfV   ,J͊{/$    Y }%IRe?*|   d,Tj:Yݗ$IսpQl   Xi&^$UZ/W   gR|WE{ITi(|   d,Tj\{/I*7+   @BF>}%IRu,+   @BF?}%IReC    bRi}%IRe |   dA,Tj=o/I*ۙ    bRK$IV   ,Jz7}%IReu/\>[    *5߱<K
   PQ/I*}_V   ,$MB?>[    *u~qF}ITY>[    *uRя$_?_   ưPI$Il    bR|WG{ITYe{Ul   YԤoG}ITYV   ,JMZ?K*6|   d,TjΟF}ITY;    Y /I*    dR)}%IRe:0|   d,Tj9w_$UV]g+   @B&󷋾$:V   ,JM.$:g|-|   d,Tjw_$UV/V   ,JMz-$Ml   YԤ˩w_$UV    Y </Kj}Og+   @B&}WF}ITY>>[   @*5)9Kj
   P/I*    dR/I*ۛg+   @B&ی$_>[   @*uRYF}ITYWW   q,T`{/I*-q
   07J}%IR;4|   d,Tj/zY$Io
   PAk$I|W   ,JK}%IR</|   d,Tjw$IlW   ,J;KJo>_   @*5h{/I*-~|   YԠuЇ$IlfN|   YԠu臣$I
   PAE{ITiz    dR}%IRe7    ,Tj>^$UZs+   @Bc>}%IR</|   d,Tj>s^$UZ+   @B}%IR_>_   @*5h{/I*-+   @BS1KJw,|   d,Tj9^$UZ    dR}%IR;6|   d,Tj9ߢ$Io    Y t*KJk
   P$ij.}{|   YԠsף$I~    Y XH&A    Y XH&a    Y tF$I^y|   YBE4i
   P$ije|   YԠs7$Ii>_   @*5P$MZ3
    Y ^:I4Iu]>_   @*5|_$I+   @BӾ}%IRu/#|   d,Tj9$I5W   ,J'|!KJtB|   YԠ}_G{ITi;W   ,JG&KJ+2|   d,Tj^{/I*x
   PA눏G{ITi    dRa$:Y|   YԠuE_{ITyټg,   @B K0|   dA,Tj$I|ׄX   ,J'Kk   PAs;$I~>c    *5hw^$U^및X   ,J%KkE   ȂXԠ߈$:s   ȂX w^$U^mg,   @BWDyITy
    Y;4K]wd   ȂX _;/I*Y3    bRm}%IR_?c   ưPz)e$IV>vW   B&G{ITie{U|   ȂX$X   ,J]_$E/    Y ^}%IR5wK   XԤ;/I*X   ,JMw}%IR嵏D   XԤIw^$U^    Y ~pD$I=wA   XԤw~w^$U^g,   @B&K}%IRo<>|   d,Tj=o;/I*%3    `RY_$Go    Y tN;/I*<>c    *5i;/Ij)s    2}*KZwy]   ȆB&>}%IR-5}O   ȆB&~?KZj9   JM{3KZje   ȆB&}%IR-uΙ	    ِY$U]$R=,   @6d*5(KZx|   ȆB.7L,$I,   P^}%IR+    ِY};/Ils    "+$=|   dCdRˣ$I
    YԨwñ]$R?    YԨw~]$R/Y   l,TjԽp.Ij{9   J:g}=KZ]}p   ȆBF$>g   !PQ{]$RMs    ".Ijl    YԨ$m   ԰PQk$I7Z   lH,Tjo.Ijk-g-   @6$*uRы$}.~   #]$Rg9   J͊Gn$zW>g   !PYqe]$Rs,   @6$*5zz}$ITs    ~px}$IklfN   ȆBf$E/    XԬ{6w]$Vs>k   !PY$6    XԬSw]$V    XԬ$Iv    XԬw]$Vg-   @6*5˷{A]$IU&| y]uyY;Z:-]:ֶ:km0DA  "E aTwѪȔ߳ޟZ!ɻ} `z*	nKJt	    y*)~%z%IReK>k   9$0]$Ig-   @^1Fם${k   +栒D$I    yTsK\w   +栒@D$Iѵ'Z   b*	}WKY   WA%aouIT].    yT|WW]$UZO[   B*	;?+z%IRu~]   +䠒e9E$Iq?o   㠒oG$Is    J"E$Ig-   @^!DFן$F7>k   
9$2\"z%IReM[>k   
9$28]$I5    yETѫ.I*/[   "*{.I*{[-   @^D:fK*
{    IDATJP   +⠒HE$I{[   "*,ڶ,]$I5y   0W;z%IRe:|   qPIh|Ww]$Uװ[	    yT^u\KJ+y   WA%E{G$I-   @^4z%IRV~0|   pPIw;\$U`^    JBC~+z%IR֮
    yT*|^KJߵ6|   pPIiѶe9E$IQ    s堒[W]$UZ-   @>e*}qKJy   OJbësITiS1|   S栒OF$IW	    9$?E$I[   |T=$I6[   |T=$I6g.   @>E*˟$:{8|   S䠒r2sITiQ   _\$UZK>o   )rP	0{.I*mxA    " +sITi    9,z%IRM=|   Sw\$U^3     oqITy^>s   )qP	P$I;3    +0z%IR%~   MJ/ߊsITik>o   )qP	2=$I6y   OJ{.Im13     F$I'1|   Sw_E$I8|   S{w\$U^\   |
T?7z%IR/L   ȧA%e9F$Iѷ.    s[A%\$UڤN   ȧA%3\$U^sg.   @T/90z%IRuy}   ȷJqITy>s   w;w\$U`   o%@_$F}z   ȷJbgG$I}g.   @TzG$Iɤ,>-|   [A%ˣ\$U^ׄ\   |+8^ulK}og.   @T[$>s   w{w\$Ug.   @Tu~]Kʛ{s   ȷJbD$Iɤ,<%|   [A&{\$U^W\   |9Kw\$U{âg.   @Tj`xQ;.I*opn3    B*508g$I7   o!w\$Ug.   @Tjskw\$Ud\K>w   -Rό^qI    pPIqwK   o$I78   o^qdK]>s   -Rw\$U    pPޱqIT}q/yr   7JMtxeK$u|u   7JMKߒ$)I/m   7JL#z%IRV>s   R#o]$Fr   7J$&>s   R#3-z%IR]"|   AF$II   o$II   o:YmY;.I*oxs   `n9w\$UhE3    *53$I7m(.   @TjfpN;.IT,~   7J}w~K$u?   o"-I]   |9͎O((z%IR   0iTj"IR~e   7J?-z%IReqs    *54X<z%IR:   o$II   o$II4|   Aߒ$)IkO    &pPI~gKʛ{s   7JMn>/z%IRM&es    *55$II;s    *5?#-I?.   @Tj{ě[$%ix!s    *5U$IIks    *upA9mqIT}N/6~   =2$>/	    pPâ[$%w;.   @(TjG[$%ip޲   ?
$II]wJ   J?7z%IR&>w   GRs;;.IT   ?|~~K$u{C   J./z%IR}$|   A>ߒ$)I5]   8\߉oI.   @Tj-I4g/   @0Tf[W\$%闆]   a8̀gD$IJR︿    pPˣ[$%ips    *3ſoI_
    pP_ߒ$)I.   @0TfNO*8z%IR]"~   =ʌ$IIs    1*3btI-I?.   @cTfܥ-I4   ;-I4km   ʌk-I4Œ^   G8̊ۗ$)I_?{   ~AeF~K$W}(|   ?Ae$II^zH   $IIzi   $Ii6?,z   2C]2z%IR:,|   2c&ߒ$)I>w   sP1ΌoIE{]   Tf=[$%it9s    >;[$%iҽ.    A$ImX   ;̠Eەߒ$)Iݣ?{   Tf+[$%ipNs    wPMˏoIUs    wPM?ߒ$)I>w   r]C~KdD   8̞bgG$IJV?    4ٰ>z%IRg|,|   LTf/E$IJʣ.   Ae65z%IRw    ;-I4Rߧ    Y(K[$%{^   TfբmrЉoIi?{  Tfxe-I4s   h76\sX~K$:|   2~8z%IRƣ2I   ZAeu$I[   ZAeKRq~K$O   d2w_ߒ$)I5+.   ʌ~$II~e   rPq3?ߒ$)Ma   d2㺇AzKduzM   VrPq.ώmI^    k%wK~K$/;4|   Y+94h$II_>w  T`pΎ-I4   @:*=O[$%sg/   J{>/z%IRz'?|   Y84Ĥ;z%IR>w  uTbͳ[$%i|%s   ZA!ߒ$)M^/>|   Y84DwG$IJVg^    kݖ$I}g/   JS,ܦ6D$IJg/   **2Z:z%IRƷW   VqPiF$IJӠS拶   @*2y$~>{  5Tˣw[$%wg/   J,~\Y{-I4   m0E$IJK.   J/=8z%IRF2   ZAaz'?z%IR::|   Y+84LWE$IJVog/   Jx1$E/L   6pPi /$_   @
*4NO
   @x*69u   A^Ԧ~8|   Y94KZ#g/   P6JCy1$-&|   Y94KZd\K}   drPi(/$g~7|   Y94KT^    k4bzIR^yt   &sPi0/$w;|   Y94KZdR˞>{  T̋%Imb   d`^L/IjS3?>{  T̋%I-jx   (AἘ^Ԗ&>w  T΋%Im'g/   5Jy1$Mu|K   FrPi8/$s   Ao_n~K$֮   @D*-0ע[$%is   Aߒ$)YŞ   @8*-;ow[$%?   @8*-F$IJg/   5J,ܦ6D$IJsg/   P6JKn>?z%IR_&   @(*-1X<z%IR:~i   FqPiޱmIމ>{  QTZ/D$IJk^    kX߉oI^   lpf~K4eg/   5J9z%IR:6|   Yc8HE$IJV^    k)ݖ$I^   d2E$IJs   AeFkWE$IJdR˞>{  TZ$I   d2#ے$)Y/G   FpPibD$IJ/^    k{s~K$M6>w  TZhxq-IU   fJXnKduz[   Bے$)Yw	   @6TZXԲ[$%iͳg/   <qU~K$Mmg/   49,z%IR:$|   LsPiF$IJV^    i*-9ѻ-I5x   d3Ao_N~K$o$~   ,sPiѺ[$i4(>{  lf9OF$IJV   @6TZw_D$IJV   @6TZ/D$IJʣg/   ,6[wG$IJg/   P*]$I*v   d3Aے$)YϽ5|   LrPig(z%IR.   @6TZ9ѻ-I5g/   $6W64W	   @6sT(B~Kdu>   f
eF$IJV^    9*C;z%IR_; |   qPwzbY-I4^&~   qPamWD$IJxXK>{  l8𒃢[$%k.g/   6ݖ$I   f
u}YnKd:.|   LqP{nSNz[$%irߺ   A|^~Kd?7|   pPے$)Yݣ4|   pPz_ݖ$IK   {|nKdnJ   L6ߒ$)Iކ2_m   ֮oIξ>{  l&8 w[$%wg/   {ěw[$%kx!   f
R̲L[$%i|   f
1$Iibg/   ՞
1-I]C   sP!~8z%IRgυ^    =skw[$%ktݩ   ?jǗߒ$)I;epA   :sPao$z%IR:R   ZsPa./z%IRz'7|   Y9z'unKd/90|   Y9:ݖ$I   d[toI,>-~   e]9F<+z%IR+>{  TxDvmIY   @V[*<Qے$)YN	   @V[*<bmIIqwE_    %[[$%_   @VK*<G$IJV   @VK*<mI   @VK*<g~7z%IRƷ]>{  Txt;=,$IibS/   P֍
i|ף[$%{^    Cw[$%   @V;*<ImIU   jAeѻ-I5)./   Պ
m6w~Kdu~q   :qPan:7z%IRzU   ZqPa.-z%IR_?|   Y8IzGݖ$Ivy   ZqPa?7z%IRƣX{#    6[[$%b   d&^sbnKd^>{  6Td3?ے$)Y>=|   Ym8ɺ!z%IR&|Ѷ   jAMV,yƗJԖ:,|   Y-8Yw|#z%IRz+?>{  T,>ے$)Y+   @V*lے$)Y>{  T,~#z%IRҊ~:|   Y86ϢmIݖ$I   TlϏmI{^    f\GnKd]>{  ,
?mIaw|B   P*lbE$IJZׇ_    lXے$)Y3>>{  ,
[dtIѻ-I5?g/   rPaѻ-I5)./   qPatW1z%IR:{8|   YHe9G$IJV_    yMnKd/=8|   Yp͊ݖ$IqU   0*lD$IJdR;?+|   YXgWD$IJZ?   @A-hѻ-I58wI   *lѷ.mIэ_	   @A2X<z%IRE/~\   T*cڒ$)i^>  ,9J{-I?   ȒsPaM6ے$)Yk>{  ,9hݖ$Iɚw   ȒrPaDnKuyI   Tjג$)i>  ,)Ze9G$IJ/   %TZے$)Y>{  ,)bxѻ-IV   d80UkI1   @
S9{-I6>   ȒqPa:o_"z%IR_   LA[ے$)]QY,{z   $T꽢W[$%{ě/   %}W^K)|   Y*LM{-I6   dI80UmIA?.|   YTUѫ-I9+E    IDAT   *TD^KO   dsPa)z%IRFמ>  r*LUe9G$IJ֤.   @V)n|׵ѻ-I/_    
S7轖$II   *W}(z%IR҆W>  R*L]WF$IJ[/   UA[}Yݖ$II+??~   eUTh轖$II   dqP{E$IJC/   UAJyg^K>|   YeTD{-IW   dpP2kI=  *TfvU^K./|   Y%TLOD$IJo_    
轖$IiLb`    :*S,{zYNѫ-I=m3   ȦAJ6z%IR>  lTãZ$%m   dSB>ג$)mƏ   @6U*Ts+Z$%{`    *x{-I68   BFVG$IJhE   .*7XW^Ke3   ȦAygZKuW>  ljT\;-I78g  @ĲsosP!G$IJs/   Qw{W)Gߺ,;}y8h$Ieg0   gZ]UN:<ꏠo[A$g}"J=wg0   V̲{ěs;l?pP!o`M%IR럽0|  P#/;~i;#Wd?~A$eOʃAYjtWg0   uzI?
Ɍﺶ$I{T   Zޓ&spy8Ó=@$IK^  `O-?_THI"I3  hK{OCAd:""IRF7>  ؼ{2͆_\[*hI6NO   <{O-pP!ѺI]  v?ޓՐFם뛷
IVl$)ys`  VLэg5
IygE䍾uA  h{OM]{
I˟l$)}~/yr  h{O.xߗTHn$I  0k%Oi{OkpP!ڕI78oY  txe~4{s\9\~H<g  5`VdM=3o!"IRòX-  eQ{RM}y82?Փ$+|  T{OpP!K$Ij[w   UdGw?~|6A~H/   [qɺF;=1Gp*`E<-|  lbޓ蟪(ZTIBs  !<=Lf4 s4l*X]Yg$I\{  mѶޓ~KʊgkTA-IRzi  ڥEew.GV堈HTsP!`g$I!  tי{O)H*v?y9w;1$=s  hۗ^'Xk6˟$)a  `xbϟs:l*l-9#IRw  @L[WF(W?y9jvesF=~.|  P,}ڃ{?h?y9F?g$I
w_a   :$\9b$I!= {?Y3?l**>,'g$IɛlX> {ҹ'Gξ/Ap;~H  xGw]u(/Ap5+5$_s  tնw5
z+?$)5'a  ࡊ^':&k'o8uEF&{72z @='ߍQAڢ:.)o8-ڮ,yFl  HX#ɽ7GH M57
NJg[ d#TYu7l*`$I!n83| @3{ҍv_JZw_y9Pc$)AQ;>>| ,){)'ͼTbϟ~HV3> `f{砒UAژ<p{3G.  PWvzM?埾ޓ֖d-4uS\9PkO~HhEs  "Əi_y9P3?̑$),>-| @ݟ[vz[98ort{_wRqYT/xIZ> `Z%Oy{Ow^-梿sP>vzƿ+IR\o, -h闖޳/+8[luu~]`TmG?w$I
i|s  'NӒ*&7
2I*za, ?t?ֲhrRmGsßy9P+4T; iHp*J瓿ܑ$)Ǉb  Z{O-sB,\JZۤsO/6~ ؏\H﯅?ksPvFם$)A  ̶b3o{O򻢿͕Χ~%7
?{.#IRXb  fȒ'?'Ig\9P;B6 xƏT:{895l*Ne9E?$Ii<,eO  '?g堈nUR+zas+o8ji|7?$b  ҚK5{"ik*??Y7
4$Ia.7| P!=TA?|k6jſ~Hg1  Sh[=	5
4$Img &=UO?sP.('{A$; ~Gwo#%b?sPF7$)Ǉb  ~NO*vҿo|sck6jkpΎ Ity '^;>!9l*VȷD?$I
sk1 @{2]{k2ip*?QH  MSESDR3vßy8PkF?$I
k|b xsi)WY_ޔ܏~5
6\"Y$IR\ƿA= fHjq?AZ@HzǾ;| {O:D&Ia/y8Pk~=Y$IRhM= KVvy>G&Ij|׵T۔#Iwm3  {O?{OߖIR_k>jotWG$6"y Pb{O~I5ZwQ<ojop#IBy P{O$5[A~G$6Z:| lbSޓ+J4Fם[A+vyNYN&$Ibgd GhKIJg\90߽!$IRhc> HR~!of럋~&Ip͊y C{R|'[#Iҏ5y
3?F?$I
mepAL ޓ$mB!y80:*$IRx_>IjL+slX]Y$I3 dЉF4.	3y803Fߺ $IRh lIjW>>{pPaf.=$IRlaY,{FL XdGwIZUϣTݣ\$),|& o_v|u_#x$Pk>?{Y]zH5F$Il1k,YiM1UIM1rцC R  0i]Hssu}59Mu)_s	 <8|&K9jbMͿLʋSt# TP+~nm=YVW}6@2{ edI4ůz<} &:G|"|eBEjϙK>%I' RmYPQ.\ g/ɒ$i=qj/ykWix)+ c;㟅jU{ۢ& 7,I^VSX;OG_ soYPQ U *˔,IRO~'{=}S _>dUrJ ?>%Ij\^=)k l&srBEwGO 3YnFOޓWw+  <[?7nF*]>}D@5.˒$L3|	 Q>qV :_h\$ij 6|{4kH*eû/>  \}g$IP{Du =Ҭ!Y/-p) |.KT:~8z>KdZ=O) ˒$ս=`ڊNYCPQ-2JsY=# mpա4kH*m#GU ,IR ֿxI,jã* WS+$Iu 4kH*m!JsY:׿tq ;?gi֐,TT{=J,IR\{d8iY5$շSy4pe-4~6KTӊ[=`ں|&|fBEw+ ?>%Ik{. 0m |fBEw T$Iu\}W(ik/}W,j]ߍ> 'zfl$~=`]^>Kdz)3 *ofIߕ Pc-BEϻn+eIo@m:4kP*}> /|.KT'zWҬAYu}*h,IR 6Y5(վ|ǟ> 2zWl$Nuli+n;=|fBEcQg TpsY:;Fo GҬAYh,\ |ǭg$Iu ^4kP*z'}),IR]\wTi5/|fBEcQ{_> 2[>%IKŝ+G7 L/GҬAYh<0 Tàm^?%IAUEOn OҬAYhl*n=-.Tl$~;zluY5(M ~hpYo 34kP*:|((lfY*# f$_y5(O^p}@et,IRq W)I<ƪWFc P͒$U	=`Σ4kX*/> Zk$IZ9=`چnYòPX]s *sgIG5 Lp4kX*&	 EYV~Vix\,Ʈ[2 28e6ϒ$U DҬaYh\yHY gI*׼R*c wӭƮ}@.[>%IZ.?=`Fu<Ʈno> RA$u 39C4kX*> R&EgITFg o	YòPX6nYy ҿd,IRꟽ0z<ۼ8|fBEcY[}@O ehIâ3 L_/YPXG TNђ$UG3 LҬYh<0U TJg$I 0mҬYhl+{R R>~_m>%I.ec fdp4k`*zs *sg$IM N4k`*7\\4|FK] 0#oy50o6Ne *e}iI^ OӬYh+n?3l-IRdwO 0#YPX;k~ 3k3ZȆ=`F]_>Ofs6 Xl>%I
iR* ,71Yh[EJE/|$I|s)i,T4w]}@[>%IhK|Ά?6|fBEc_8 ~E[iIFOa 'ӬYh3 *{̧$Is]qG0 H=i,T4 XsZ9\}W}_i,TԈ+/> z^ʷ9-I\oS)e|gj,TԈm}@%u9-I\9ѣ f;gj,TԈ:}$J*n?+|NK4WN 3635kh*jD-S*g TO9L?>%IW=y`F#4kp*jLÕGw PI+|NK4$z*|fBEbqy 4|9-IҬ7)c fdpq3uf9; >%IK=n`>SgƔo󢔆3 *Z٬wҗ- X[>SgF53 *Hټg$IયE[ YPQꟿS 5zY-Il5|Q 3^585. fkՒ$+am>WgFo┆E o|ۗkIF]FOY ͫ+0Wg5 *{gg$IwEX ݗԦWZi/%*n?+|VK47=b`-MPQ |׆kIFY fbqLmz=* *wD$iTw
 #]J5 k6yA&6ג$	=Z`$:N\mzX? !ג$UFU |j+-T:_ *mpZQ> :+T,TnҠ}@u:)3[
 #1𹪖[qǹ  TZ/kIfR=N`$>WղPQs5?J{E$i&.?zH:|e9  T^{wlIFR OU,ToR/>?%IF[Tѣ F;gZ*jvŭF Pie{Ul>%IZߺT    IDAT}6zhÔ-<|ef;+! T^w٧g$IຣG( DsU,TK}@>%IZm
 #1٪4%H V/mIֱ~ 02۲U,TG Pyg$IZѣ FwҗgZSYN3 *Jق$IpEѣ FsgZSYz{ =3s[+)c F&U,TR" T^q-I]	 ˦_FWPnuGE P~9|nK\Z{elU,T`Z js[6oTGK GWg"McwE Pegum>%IZS_ wU'P~pm# _vFmIT$ T?I*ҏ\4|Z-Iҳ WFI 7Xg"}>@m{O$驵;z<Hǧ~a zƪd*ҏʷE9	 0[?w #Uua|UiYHOix%$ CKWnI~FOG Wn}N@m^>%IǛ" \/X:} (R`-IRyc FsoXog% Fؿߒ7| US=czZ*3*n9%wU$5wGC ;gZBEzFoky	 9[=
`>czV*3j% c$(O z6~*=3Ml>3>Ew}}$5a 0+GyUYYHkhpףL ;oIR\sxY^9ֳPPؿ>3V#)[.IjP^# FoMټg3PPV)e	 ;_g$9uLY19PN S6.IjFώ} 0+W>gZc*Z_[	 _pIM* V5f"a>;v_$i_KYZ֘lR}~@t9.Ioq ,SO[5e"=GŭF P;pIgUZ֚g( R{㒤lrq jpVf"=G=}@-7>%IW{72z Z;>oZk*:  ,S{[$i_{Y9ZkBEz}@-<8|KƨE/Le{UxSSYPΑ}@=Y.Iz'sdY5|ysf"=O[B \,$A6JUE5 UJϕw}@}JeׅrIR.dDY?\3i jkpY.IwÕG3 u>sz,TuϯF PRy.Ig+z+)[yU9P֥R}* V}$7= `*|YHâU A7;&|KU{_LFO1 uj=o*:=* Z$^/7z|f"c/Q 0R$s3crv @٫f"Gû/>[$i]- hA'e7	j=o*z?{a
 6,R{ϷtIRw&}IUkP֣}@?&|Kಥ
 LgZ딅>Ml3 ,S{uIR%w~NQGyUkPֳՇE P{mtIR5\95:e"ge>c`,tP\$US^9S>zgUkPֳ|۟JG P{û/M]T= `N=2|YHӨ9g- Q>%Iը ;K3XuBEFS#0\u[l>%I7= `ε:g"Mo>k`lo][F# se(|YHl7j+;|vIRPWF# sŭaBEfD 06>%I1u.z@ޙsXBEfCg cX^o-_e*/z
@W^Fb+i-4'] gwIҜ?g 1_,jW**nZ}X.I^R?= bxXBEA 5|A$~돉; ўXBEA[T/ i>%I[簏D ]yzg"Ͱ}WE 0^yw}}$RH#GO 5𙬴YH3̗(7>%IS |(=՚V*k3 ROyIhk >՚V*L00 ;^>%Iib4\yqxpw\VN*\yp9 cs^4z'})z @%VmPFP?>`<-^4JeguTj%~fZBEE7OG 0;ϟzML$MRq *aM7YiYH#iyy cwʗg$izNb٬ִPFT>`|$ijT" Pe9ִPFTR2 L6&zKֱyʋ TLPFXqs kc$i5?zl @/^>՚Q*}ߣe o,廾!|KRя P)oQVkFYH#/F 0N/IrHÇn P-"۽4~N+$iM ]9|Kಥc *gx3Zg"yG 0s_|:zB @%W,j8iĵ{o 0|-,|K~X{_+ :~8|V5,TQ7A*'F_k$|іiMc lZ3BE}L@3e|_ip1 *y4,TYh 07'OWIjj[( J5?|^5,Th>}V@c ԰kL HPfF (3;|KR{ _o>I*,_F ,"u;$5ʋO~ ҨPf|ۗw ce@w{$_# js[iTYHUqnm~qG= FkgZ#BEź] _8 Iu7٭HPf|4D <eGE]@ƩAZc X=i*,WvF ow$ijT>V:vWkYH\>%4_n>Vc)9HPf|+Sg8 4Vqׅ)[i@XK+r j<i*8/F\uh}@j- LSJBEz|9wIM6MmG POe[g*ꩃ TͿHR囷Q\L 5y4YHspg9 PR$Ml~#Z럻mLW,T9j5# @:z{@*ip~4 ^ߌJ4G廾>, ~|U@Tݣg Hm>՚,T9lxg: ۾$~ IMl},X\,~+V*;g: Õ|іwI
+>`lt4[YHsX{7E 3$iΛI\t1 cX|WxBE_} PtKjV6: )8/~+f*;k^ CG  I]͋Rs] ;okWkVP} kѿtKIc]OݗF 0]_>՚,T]} ka"i\wY Y2/z֫5YHNJ <XH{=>^`lΜjz*R@ίM,y 9XH:Tv>V`֬g"5\yQ9 <TzKJ"86\ukWkNP" 5GlwIZm/>B+vJsTV~S jiyl~u)_e*nV	 }_9BE
9= [$wzuwu	 Q>Ml~PkNPg> &"ƽYR5TfF (˖Ԛ,T_Rя>0{$=wWR twBE
w} `=ޑ{9!IUzj TvMMjY*Rp>} PI~K= b9<>֜f"o A7u}*>!yu>}
@u;ZsTG t?'$5|ۗE| @E/5YH{̧G  0C;N}1tB6G< kpñw<
-"^= ͔-,n!iZYX<q @5t;\g"UGG `Ϛz%OBx6 )c)[y=A9BEH#0z  #2jܼS̉~ <"P2(z  #RW~/!v廾!w} k9#BP*T 0JA;4ԙ X_{RD*Rj  ̂UlwIխ;pE <~oP+,b9z.  `MwIkS⩿h soP*Vys %e=Qr	 XGN3VX*R2e|  fQ%)[YCRL=ޔN> Կp{ZYH  ̲7޿~4-<ΚҠ} ^Rd*R  ̅~;) !iv'iS [jg"U|4F	 `7
H}~3w]}  3?g{ZYH9 ̡h.|DhjKip1 D{jg"UΑ='  -|WE$M|E{4D' pmCJd"U*z^  =o|Tm^,JE! Nj]CJd"UF  PS{7I$=G6K9G 02廼.ΡT,T
>D  ZOS`𻉤/2Nr*'  fjU&%zn  0|{s&Rӛ|WﴯL c*VeP*^s 3R{[(Rw;k~*;F ){OLUj=Dd"UnozW# ^1ۼ8"{NILG slpAw*T;΍ @كS_$"[ޞW8 soIԪT*R7 r])0"պhzJ m;'JUBECHe9 TR?H5+wWSze1 P3;VPj PÕO}Ez}~lߏ <U9L?~WQrYH5{G	 P3ŝ!
Hj&{̧Sqׅ? @EgQb*Ry SؿJټ3RT%oMS=#	 T\?U,TοG ƆnKSk(q jN1jU2F;"=W +7:;LFy6Kݣ"|;a L}3JUBEYōG `\ip1S}ǑfZ{_OHepO PcרU,T9cs CN}Qw`NMlFꟿa 0n(U9nx5  <{=#=yÿDy `L~q}GYH5 we;K6o`ө\yp*2 qUSw*g"հ8 `N49#S!}/2u4Tv	  `pw *T&c `Mz}Hw"wWSsR*zw"g"մq3 @Õ=]i1@<~z]ɩ @BJ뒅T0ǣ /\_|)[Y]IksS] <WRC*R\~@ x~NH>;n~gRtP5/R/ yʷ{iIZd"ո>9  ϫ|:M)w(NWOSq ߣԪM*Rsy XwEoK{g.">i4Aj/y[.|\ @{OJ.YH5oU  ^u_5tXʷyJ.S?NsSR^/ `Ɔ^~RVYHG LGeK?u	s5/H%oMe᫻n;=$  fERS*ԿxI ="9?&s'b"Vmڻ_Ltr5:{ 4/(e뙅4M <4;S?Kޞ*ѼSR޷1/=7bq 4/(הꖅ4&wC  P|TuA\sDꟻ].baQ_~wq6J[I_LvT^9=  kNtJuBE|&z Ǡ;t87-Oΐi9.:njkS))pw||cr9^i=R/YdpSg2ZS* sßU,TqiG  觲b|'>4V;  F迈T,T1N    *k}瞲if"Q    sVmPƬӢ    TOK[?SYHc    O7gwj:iܚq*'z>   @yg;:g"aD'    g?SYHcXkR    TBO?SYHcZq	s
    ^&6^VPƴ!U    wҗթ5YHcF+    SI-ßө5YHc\wg    韷C3:&i[y*    ̽.Ҹd"yG    ̹6Xe"yN     IDAT  @{O9*nf   9Sܹ"ZcԀ:?z   ,T49    |(yZcԐ}6z   gqje*RSZi*?z   |-<Y8f"59g    ̚iNBEjP[T    \Ym_NBEjXk=    `&MBEjXm    0Z<;L7:$z   /-Zc|:z   hgnj}*RQ*=z   80yRPZu    03"xS65#-"#    mpݲlJMBEjpsy    0m}-ZBEjpHߎ{    ފOVPg    ΁lMFe"5/J0z   :+\\Me")n<.z   :gjj5.I3    Iqjd*3I    AV#P4UODB    xNm?GSYHa7DD    X,T$=Y    F'??SP =   2;RPz}%z<   7L*-T$=|:zF   O:e_	n&*Y1	    S-^&e*TS{"zV   t"|K2)P=.   h5?'e"i_R=3   h_KɤGYHZkK    4ʃßISP_Rы    4MK.>&eOBEs6	   @/#=#IYRg(    QvO.&eBE69
   @CNj0)[C*nҰ    {RpaR,T$S뎊    L֒u)
   >xSmL֒u
   |Ͽ9PεygJe=[   3?BEzU|r|   `ej/}Ws/){,T$W=b   #kK!I]DY    AKo%e됅.    fϺlP4N    Xy4ۿ,9c*U{R*s   g\RYHvk    P)[y-)[,T$MnRя    L?%e뙅5   @?;M#I3*)s   :;iI4P4=   KeI4P4~&ǣ1    VW|?˒if"i$!z&   Pa! I#)R~$z.   PANټaIP4zgNDf    *s]IP4E[2{ z>   P!kn%e#BEH}ߣg4    Uo|f%e#BEh[Y*;zT   P3^%m=,T$_    |<˷ϪlDYH}6Jn    |SI[.IRGl    |JFYkrp   0njgSR6,T$Z}ޙR9    ̡YKI,d"iV\sx   `/W,T$jNIGr    @?YBEҬ_8z   0WJf1I^͋R==   %e{UwxEs(),T$IS=   %.r*/HÇn    Xq) f"i'   Q*zϝl*Wgo"iN* z   0"s$esTS[ٶ/0ƿ~I,g=    3T>zG0yQegԿV+?f4y   uXs&)Ҡ3o#廾>A7z   0M
$es\*S[a$5;G}    <
$esMh{5IjL6/J    _	$esZw Iͪ{_    Oq)ϔ,^A}G?5A*\z	    `ݔ))I[}ɟV$5>Ұ    ]$){ԟ=/HR3\e    VzF#IYP;{Q~:á    ֬>_I럳ɟV}??^    Xυ?;Dko InFikB/    <]q^%mJ]>s*1Ijv~3$    #,廾!Uh^ۦQRxk'    CHʪЂ͞#LRwzu*{OD    ϫ֓i?S|{?$Nj]   ^ڻ1U1yBs_0Ioue    hI_>$m]J]?$MG    U_RY7?$oE    l~gBRVw={2|&I?.uS   `u}2yU|=gej2)P~\   @Zs )`#>JЏ@Izy}W   1Gm^Hں_HJEPZ{Rs}    0u@)h]}2(IϬўs}    {s4}zyzbTR͋Rs|    _{.K?9kB%/}wg9csu    o,=RVnw=JҚ*n<~    cy*[Jeg\-    Nqg<RVůJ,-2KҚst    /e@2Uq֟/TRJ#0K0t    ,S?#m]`IZ[%`    c^t-"'}2|Ml%i-i    caxU)[Yu}9P.IϹ)~ٺg  oc-;"^mk4m\"]Hkih[F?j4FauD` (
"H+e,803<Ϸ9+g;ϹW{N ,OΉ/+#jF[/|P_sB$'ߴTk    ̄,~#RD:*Վ1~I}   цןZFj5J_9u8 IiQow    hꁛw7RAjw   ƪ{;sKH5~fwPzs:_$eob   H-*}W#.zAeB$)}S~b   HO+~O#n=1|ӂ,   `UsSU;orPk_$-    S碳fV~>^R둻w   F2Ru㉞tPA/Z<&I>   B߱}jh;ȃJD:&ImSvw   )v^9^РRܺڇw"    S</*~#M-hP]_$-'[   7Zjj֘;l_$-uP   v+?REj5m_ܭgoXB%i;0pG   i4hޫuNynDJ"Qu<d|   `TmO-~"whP]ſ`I!	   0\tNzE{ຟy=*U{[?.In~Qm    uyk;iUڲX4A/sL   <݊jx?5h~ IԻ}{|h   ,я֚}߫H>9QwT"bˋ4i[   `9#Y>Ejz|fQT:/$MRgDE9@   ̠_U.EjzO٢={4T*H$uxcD5Z   `.|O;Ae/$M    ;;fu[gsl~}F&j{r   ,іK}jyHD]M٠2~%>$I>Qv,1   Ǫo3^{ӣ~EFeP/$MH   J+f-/sh[uhJ&mxًv   Ll؍#fE[Guck|VLO    RuQ~D:^o5cPn,IjG"   .4x-ETz'I6aKq$   J9/Z*~'"5{趋]A%F/$MctKr,   jZw`imղ<K3Ou󊿐4I,   }Su?戺j261v/$MRgk#F<  jЉΩWC:{e.26/$MZ+#   Ut,wn]Gx*Jdu   V^CՃ,3,Jut{GY&iQmsYI   `wJi&Zw@s<h-bK҄   ~I[Cj|kі/{oPHO~u]&w{   fkG}ٷ[/2VI(Ko<kK   o%>95ƷztvGzj>%	782  UNCjzk>ӠȠ2Vm/Z^P!IsK(ul   QvF)~!5Ǵ(6U;~MH~/"	   L |S;芘&EjhIZ`k6>:  iTѻ=.>YQw]LXy$ڛ_W$Ij;1G'   0eW|:_C[bMŠ2׊?Ԑ   ?}gug[LTƪQ.yo$-E{ON   і/ͿE
}{İlG>>VU(IY/C#   (h;>>cM26[w`o$%?	   P=ps|f	}^>xj϶D{ſ>1F?f#   XFն;/KH{hTƪ\IUc>2  ePo7_>BjdkFThTuh̭ާ7[i?   왺`tN|Y{u6({MՌAQ{KջݥJ   `GWXFݟ&kԠ2׊E+͗kcJ   b뷢s;HM1㲘T5h?Zwn1	   ,a/wR>++2?FΊ*cUѽ1WC~EuMI   `OUwR򚨶уcw}+>JҔ(}D   ?ԔGZ=1,Ae^+>sk+C#I=   4O[Ѻ+gPyT?@hSh   &ڪw
Էf]wQ?rw37<foGהUO*},   4w	Tf]+**?8H*bxK   @bpҴ;]Q=%VTSU1h?pVn{)}"   cp	)}S~Od+cPyhT7\Pʬ}ҧ!   Knw4>CcY
+kP_O%RʪEQ~V   5a1EzÞUn$~<ʊT3^1?VL3 b/}  7dc4O_j՝m˩Tݝo9?VFs:K   bo8ݘ]礃Q=tGǱ*W+/s?ВfV>   `E^1E+Iʮu6zqEҒ5   X>O3hez_AhIƕ{i{$Fkm_,}  m4_qYԝK?r3Š?ÛύE\ER[w@   3m3?JkZ_tN|i>|rAT?aD5*4b,)zW|8:ga?C%QzVT?q   3ix')ft>uh}{/\uD}u;~QWɠ?o6ڛ_cY$=n/zOK_   0s-M[1~<X 
     @      0      $*      	
     @      0      $*      	
     @      0      $*      	
     @      0      $*      	
     @      0      $*      	
     @      0      $*      	
     @      0      $*      	
     @      0      $*      	
     @      0      $*      	
     @      0      $*      	
     @      0      $*      	
     @      0      $*      	
     @      0      $*      	
     @      0      $*      	
     @      0      $*      	
     @      0      $*      	
     @      0      $*      	
     @      0      $*      	
     @      0      $*      	
     @      0      $*      	
     @      0      $*      	
     @      0      $*      	
     @      0      $*      	
     @      0      $*      	
     @      0      $*      	
     @      0      $*      	
     @      0      $*      	
     @      0      $*      	
     @      0      $*      	
     @      cP  IDAT0      $*      	
     @      0      $*      	
     @      0      $*      	
     @      0      $*      	
     @      0      $*      	
     @      0      $*      	
     @      0      $*      	
     @      0      $*      	
     @      0      $*      	
     @      0      $*      	
     @      0      $*      	
     @      0      $*      	
     @      0      $*      	
     @      0      $*      	
     @      0      $*      	
     @      0      $*      	
     @      0      $*      	
     @      0      $*      	
     @      0      $*      	
     @      0      $*      	
     @      0      $*      	
     @      0      $*      	
     @      0      $*      	
     @      0      $*      	
     @      0      $*      	
     @      0      $*      	
     @      0      $*      	
     @      0      $*      	
     @      0      $*      	
     @      0      $*      	
     @      0      $*      	
     @      0      $*      	
     @      0      $*      	
     @      0      $*      	
     @      0      $*      	
     @      0      $*      	
     @      0      $*      	
     @      0      $*      	
     @      0      $*      	
     @      0      $*      	
     @      0      $*      	
     @      0      $*      	
     @      0      $*      	
     @      0      $*      	
     @      0      $*      	
     @      0      $*      	
     @      0      $*      	
     @      0      $*      	
     @      0      $*      	
     @      0      $*      	
     @      0      $*      	
     @      0      $*      	
     @      0      $*      	
     @      0      $*      	
     @      0      $*      	
     @      0      $*      	
     @      0      $*      	
     @      0      $*      	
     @      0      $*      	
     @      0      $*      	
     @      0      $*      	
     @      0      $*      	
     @      0      $*      	
     @      0      $*      	
     @A)    IENDB`PNG

   IHDR    	T   >W   	pHYs    {Rk    IDATx{u}]. *TZmPӪMM5ƴUEhjkDjم	Br
DTDº¢+
<sgpja;W̜gg~=3           ]!     B            3     $g     H      A      9     @r!     B            3     $g     H      A      9     @r!     B            3     $g     H      A      9     @r!     B            3     $g     H      A      9     @r!     B            3     $g     H      A      9     @r!     B            3     $g     H      A      9     @r!     B            3     $g     H      A      9     @r!     B            3     $g     H      A      9     @r!     B            3     $g     H      A      9     @r!     B            3     $g     H      A      9     @r!     B            3     $g     H      A      9     @r!     B            3     $g     H      A      9     @r!     B            3     $g     H      A      9     @r!     B            3     $g     H      A      9     @r!     B            3     $g     H      A      9     @r!     B            3     $g     H      A      9     @r!     B            3     $g     H      A      9     @r!     B            3     $g     H      A      9     @r!     B            3     $g     H      A      9     @r!     B            3     $g     H      A      9     @r!     B            3     $g     H      A      9     @r!     B            3     $g     H      A      9     @r!     B            3     $g     H      A      9     @r!     B            3     $g     H      A      9     @r!     B            3     $g     H      A      9     @r!     B            3     $g     H      A      9     @r!     B            3     $g     H      A      9     @r!     B            3     $g     H      A      9     @r!     B            3     $g     H      A      9     @r!     B            3     $g     H      A      9     @r!     B            3     $g     H      A      9     @r!     B            3     $g     H      A      9     @r!     B            3     $g     H      A      9     @r!     B            3     $g     H      A      9     @r!     B            3     $g     H      A      9     @r!     B            3     $g     H      A      9     @r!     B            3     $g     H      A      9     @r!     B            3     $g     H      A      9     @r!     B            3     $g     H      A      9     @r!     B            3     $g     H      A      9     @r!     B            3     $g     H      A      9     @r!     B            3     $g     H      A      9     @r!     B            3     $g     H      A      9     @r!     B            3     $g     H      A      9     @r!     B            3     $g     H      A      9     @r!     B            3     $g     H      A      9     @r!     B            3     $g     H      A      9     @r!     B            3     $g     H      A      9     @r!     B            3     $g     H      A      9     @r!     B            3     $g     H      A      9     @r!     B            3     $g     H      A      9     @r!     B            3     $g     H      A      9     @r!     B            3     $g     H      A      9     @r!     B            3     $g     H      A      9     @r!     B            3     $g     H      A      9     @r!     B            3     $g     H      A      9     @r!     B            3     $g     H      A      9     @r!     B            3     $g     H      A      9     @rPQo\/חDwEWG7Z0Ot->bg/   7zZ%i[[WMtzw^:uf|: 4F{EElO4I-~VOe   -]feEGҏG9Qoe7%OιDu!mSKw_+  S?hO4/:7bԏ]Ahk17RZ˟ו~  تY{/IsުL}*+"җF2=]`9}Q-{ND}ͥ   0DཊbY`nrc~z;VGGRZ;J?  1?IKR)믜:fƖ/]{g0KkP   غQhŞKt~lCKX2_8m_+M@Qpg?   4GknKXhhw1XwYhTR=6BNorzy4AMZ   @7\ղ]חquF[GFZ1&v7?+DIs]KoQwS    1\ETKv._ƶCkz$&B[~[>CZK4uN(})   twjNKXl[cL Tw6EC:h8iBֈ~    0;?onS<RwI귣wQG4u|gİW    ֜튟HR#:y~dz8U/)&9*   '?&:e1Xwidr>t{O I{{#A   L7*~. IMorB*_dT/4/shT    wٿ?Ƶd]4b+0B_#ET݋>1K_   `Fѽ	$ye!h T6FGp~׻#2   ŰV@٢{'>=_ա/,}   ߎΗP@Zȗޛɚ9zѽjqT+ |g   QhݫEhBÇF?\e  7Q/+~ IM}~hFB[Έjٮْ\O   !F?+ZS<A݊bhfB~tWX,)|   (kb
kA@}4   4puQ-}vIjzsU1z{STV_ֻ>&   nQ-ޱ9$5zxB;VG9ZDҗ	   `n9=?oƷrWc9n|T/˓_Gc   $ӿ~U3IPk1Xe:/LuzXJ   ̂Wك$hSc܌ Ts$M[wD   l9 $)EG[G876cy+4mS:b-}    f[_W,BԻzYРm@:eĠSJ   ̑Qp?gchI9MS3   ,kbg&x}%H	QwsK   Pp7ZS3
IRڕ8mΠsSΗ4}c0FE.   9{KUHRΏw0AP]G%Mۖm/   x_y$ivѿ}.iZ(Ft/   ^;չ'%M[ߌ%   hz}$U3T[sBuFhwZG`.   @}1$)KUE\ޛZk;W4-%K   pM}|IJRDP龨V]N4MKv]_    HO)~!II	A/'i;S4-!k/K    pB\A{G߉itl>  7[CxW{ Կwisl=  	ҽ_sHRZ5k>pkTK]Γzr6   $swHRڧ%2;:iZ"Fs1   &Ө1ڟ{isIR[G5c^w9L?   ~xmQCRd>f%IOxmDɧ;   tyT/~"IjAw<z8{$=1m   ֿg!AsIOub鞙z   zQt{o3IJcx-5]V|no3   x/}6"Ij'pLQگ"WZuՌ\$    D}˟HRz77P3$Jf   ]ʟHRk{ԏSvscT+~gHe   Lz^-}^"IU{@A?+~'HeK>   ԻL$P/3o9 uNr1   3Ew?;O| ԫp"    ̦Qwsg(T5m_A{7Zk7nE    `.ԏbg)T5^1 T?PTKw-~%͋ʽc؆z   ̵O}F3I\f^7VҼ>;껿UO|   Rz}`sIZZ^U%z}Q-ݥ&cg   (Fo)"I[fw^7RҼ_w3~   QP۷$UuD3ՏՒHi^y   0V껿g?kB;H*_7F{[   `o|IZ?Φڽ&ѯQmy   0v翿$Umo Ի7JZ?/wnk+   4DW?u|B~Tv%MlKvL]   F$ZUF4EGqB[*Im9{&^W   /:)~#IUogfj7Fz__4    wՂ1T5L}6BGKΈQ=    ۨΩo-~.#IU6uW&qG|9   h3T5ކAh؋ҤZw{_J   4G}ZSsIҒn=u iZswg6^G   4JG?ͩn?4in:i6^?   4h3^F9[1Z&WO    4j,Z^\F&x_qB[,KTԷF|   H=7Lr>n>Bm)Yc^|   hk?Ñmͧ=S_l_&F	   Fwc>ˑj[KDIhv1\w\d   hQPݧ$-d    IDAT|zPaIsZ	    Ꮿju$zW|B/*Jh.^'   堳َ$Uc\Bo+Jku7k$   eC0
Z[^kjdZmr~r2 	a0AA	 ֞${^OHr眽X)zuGx$)j6Oeu/:Jc\>oT<y0H    c\y%Gֿu/|:ƶRsy6   [NČ;IY::BEyۇҸֽt!    [쯆HRk/?vk(k?RYL   0z<w?U|WTk_uJXsюl8   ;w@Ubŭk_N/N_n8   Fڣ$)XƵ.	qwqg    iwAUιP[q89o?    S6Jo	"/\&ƩD    jS61#nH
/\u92ƥ|7rՃQ   Z!Iʪf)Z_/Lfm>I    Z{$if|c7?!<w¿(i^    @JxpwKFrB?EI^ϤTg    C]$){gTS6g/J=ߒC    Qu$)}(VI#-SC7    PԏS+$ifLS3ѻ/H店z   >4HZGF¿ iTki   ~$IY@yY\</F1   e"~$Iِ|F{    FJGMČ{%I9_s:AҨA    }Ɨ$)f3R*3֧ i    RsюKp#J^oKe    Yfm~$Iِ*W?<x5}lĥj   0:&I9'~4x5=HP]*    L^;5}W}$eC]/Fz>Rя>    0E|t&O9x5]_HU.]*/   'Iʆ_T}6   `:t$)Ɗ'<٬-¿uZ   iԿMl*y׈B})Zg    Y̯EIR6MYIjRg    |wR4sQoc    C>:NR,uG?    >/$),TfE=    PW|ϷQIR6YI?ČԿ;    8'JfN]BO9k    *}NwUMQBsj)u    PV|7YIR6YI٬-R    TH$ig!$GKG/    lf6RЏT    TPH$)ۄ,T_'>W    PaǒlR]{dy   +:cwYmdBuc/(   (=esӒl#RmG    ~%IFd!ֻ    NE?~%If!Z:    oIRYv廽>c    FX/sIRYvn95    +y4뒤l=Rj    cw]gBM?S    EY!#KBHhbFqn   1S<zSfo%I3םjQ>    0:s$e/Qq    U7O$)[GB}$    `{0I֑ƺ_>    P?~&Iًd!-Tf+    D#)5b%!mN>    P3+ߋIR,4   @}cDB]_UF~    jҔM'9Yi]{T   '|.Ld!uoT   +W=_~_&Id!i|Y    ߙI5Yil.[=   ک;$)Ҹ<)    ӿ3I,4"_=   `ZG2MR+-4u~0=   E+nM-$;!tE;kEt    Xw!.MR61#|A,   TW|SꚅF_    z~&Q,4M4EZ=   `ej.pݚF-Hֿ    xMl~&Q,4r    }ڟ߱Ij.!VsM{g6    l2{,廾&MRSBK    ɺ~&Q,425{oJn   M梟sԨMB&fEi    2[OwꒅF=   `ʵ7IZd!ʗn=    7צlb;8IBHwAs    M/Ij}Bt?Rя    0mʕl$5:!UR    ]{')sBl=   `(ʔ]f!J   .[~/'1Y=   `wsc*WRя    0tO,T\=w    LЏIj]BT?=o    T)~W'1VY:&+    }IJ㔅*S9s    *|:NRclR%xsJ,z   @et{;IBHw	    *l>ۇIjEB
uGR*
    ӽl;IBHMl    PMvz[=4Y)i=R   z~'1Y)ۤ)    T[O}')rB
ѣ    FB$5F:!TWEQ    e?^ORcdRH=B   `o?;^ORcdk.	    #u$5F2!gDM    I{/ߓ,4ԚK~ey    i{>IBHkbFwy   V<|p~')RBZ8zV   Xh}IjTBNJœwEI    ţ7lb{?IiTP	    c}ҟIjLBnUFG    +œwl(d!is7g#    ~'1YiZw}u*'"    rCO艾Ԩ|Bֺ=   `u{@Ig!i+TWGC    kexwye}FҴսla,   Z`f}FҴ3)us    jl=]_~/(YiZ-_=   V:[FeҔ/|{JN   Z)'KHRz,4?6z   @-uOBHSZswT    R?_~O(Q,4?&z   @u{BIe!);v    +y$es	/ԨTBz=    :kBHSRp    Qz es7ԨLBz=    hWBH\Rw    lVBH\o!ѳ    Xi~(Q,I{o   @EOޕY[#Jjg!Mw3    X);#Jjg!.)    XS6kDI,u/[=    >Yi6s    XŊ[S6YFXBڨ:̊a    h{EI,6ي    lⱛ4Yi    l1_BH֬-R    l1JJYijS    6A~(1,MHE+    `o9-QRvBZ&?_    qe+QRcYi߻4zT    SFIf!3
    *vw{GIe!wӉ#
 S#xT<t=]?;z7n>y?rS|*n3!  {nCBH/Y[S*z	 k;<eR:gujua?wHצl;K6Lj:_S眿M݋wMM[H.,  SV|W?Jj%!dݥ{D& )O-SKSZGNj.~ϚNΊSeDsZ~|S~KxG);$  ci}JBZgί   SoU<<n8.u/9Obj>Xfm~6>~Ek> Vz e?IJӝYE$ Vxw&?*m|K~%廽>7.{-L\0+n9u?r2O `dLQtӞ^|<  <UK>_a.JC?:xg`I= nNČ3ƴf!m, XrC.kSj.~jpz;z˗.=  /c>~^Ԙ,0z TBz:</u/ZGO=ߒ'i]uc  %3IiBHkA  a57jRs|o~~'! >2IiBHkwQ `h&œ#6qb5}ScS&^+
 0^?IJӕ^PS굣 )3ux`jG)_S/UR_|d`} OY_td!F 9-v:NœwE r!}ޒԘ,fmʕD MV<r}^</Xfo51#  SJ7Ɵ$BHϫugG )5c.4fmZG~<;:  {4Yyy Ի۩}|W]^:gM*)[ `<9[$54!=[sw^ Pi<o;+O)e;<%|6s  6H/$54!=[s ॗ@s?7IZ>o9|& R<|mJRcJҚns ۙ}gS6e%i*,TqnJe] NC?~*!j `x9)g$i:kԻ蔊^ Zn>9$1eYiP XԽx^j.1\$|wA)Zߊ  WR[KSRE ":?O\fo~&SZ	 ISRã
 P#Swf|7*n=Rf+] n~F,j^+R^=W ߻to<$D;|>t/ Ps3665>/	 0&|Ij.~OG>; (clbFHRcyWF `O(uZwyeyGoO `ZGVyHRcq=G 1S<tujwM'E 5ӿs&e!T㺗=G qPuG7Rjx'  Pe{#$Yյ9[2"z  IME;Ɵm6k3O &<#)mlB5} 0ʋNͽ.L#iMSw" U^]^~qYմ]G `ک|IxsYFk˩x 0:zGRca·A `Z1#i=ET~z  cxG),#)mhB5{s E/=~~~*n<!I 1
?HjlpBukbF*W=3 *+Ի\cE&7yaS~( 煟q$568:ף Pa;M~f4_緅 S~L9zYլ5GD 1?H& 0~ؠ,mX x2bɗЇU$|v|I Kds^~X,jTG	 *zԽd~wyeERL0ي 0'1L#Yըw  ]gI~jRh ѿwiyFRcInoHE  P>es51cёߍ~L #{3d!T:}l  tsl-i`q !W~X,jRuѳ п"F|я. `S1/Pj.~O\  lL3<(賈^;Q i^*Խt  Qo}45T>}_# ŃW]$5^2qob@MLu?H&˓=	 RbERcYyC>= !tR6!iE^ 1 T\os,Ƽg 0gM~?!ikŔ PQe癔3Ƌf!4MlG `n<!?sHM% IBhk3  e{uj𳆤z3G! PA#7U$5^41wA3  bjޜF?
𳊤,ƵY[2{, LLeR6{s$M61#u.t *wQIimYi#; LrՃuد/$imJJE?Q	 TEy?Hj 1wя~ `
0~u:w7 9'/Bhe*OF?MKlgIZr*y4	 T@FO$5:S| `LuwHG?FhE/5@DRyYak~ xʔ$mlSq) 0DSwލ'w!hv~yDRY[6Oex  6BcS6w$mjsMX Az:]:1N?{HJ듅И:7g ^s$MisN[O~ MCWE}N$,Ƭ &uo!$iZUtR XE?ޘzWg|95)EyBR,Ʃ| ;SsюgIfmz ~BԿԹ`~]AR,ƨ# z|4&f>j QWyG9f31{nѳ Xk|RA] P<vs-_?sE `]2ugI{1 {nY̯恿[{IJf!4&Mn
+z}_$
u/]T?MBhL`f< ^L'Kon>ݻ    IDATyATwOg 1|~KjtBcR3
 X2"5PYA*Č[~Hc JW}S/GR,Ơ|7I  TK}/$Mlz*T<vK]{d7y/y4,Ơ_c O(;w?'HR囵y6 ?R= (V63$R z);|$\Ш7gj(.廽> IR zT<pe^`3h4Yx>= P<Ô.| IZ+Sяs X{Vܚz:g55g$eЈ7 @k-$i
-; 3)I&f!4O=GDI;G ?MCB#p bܐ?HҸ}l~0n^*yo3f3YܓlYpSZGE	$i\k= ,SwݷR;_O̓?9[7Iʂ\=V&Q?~q}/R~'7%){NB#Zk
 {-{#< Iuɧ# }a^ y%IYų6z@-S$n/ T?s~{$ig!4 6S_?HR-eI Zo}3Hn?$ig!4O=^sȣ Tۧ;' Sq̃fQH$ecѳ j󝯇$I\l>= eԿwi.[ڧ씚ߝEd!4ujZ.3|KaR= ؀>m3Dg!4o=#z@mn>k%O:m$5Ш5kT PWz$U}G@-c٩s:wEIR%Z~4z@-No
u4kԿ0:HBh^87  J̓?>%I/]R0ZU^Ԙ,FeG oe'I̗$̓?R=A F?N#??4s]_Rы>+ X^[̗$mx3*z TZH;Y|ݒPZ_g k_Y|IջQPn*{$IYP>N ؚ|D$iu**z Hf_B#TG O8W`K6|Ϸ>	9ӃWD?{%IBhDmRYD9 `,M$e$M]~ǿPOsSO|7?c%IBhDj3 -yI׽d~0fwY^OjRIRc? AihQuS9 `Ej3^4}{9]3RԨ]B#'r :=%I_[RYFFo(v-J>oJYF Sࣄg$i8n`Z`s>IHB# 橹h.IbLWDO `L^y$),F g$iwHe1SSRN=廼2Y&IR	YU|W^z llbF|$>ѣ2~^:%IR6YUџ>xd;g$)ލGO$ ZnNKRRsS6YIlx݋v>&Xs]_kR}c	}E$eYU/>7+O}JuS*LrCYs:)}3G"YUY[LY
 F[?%IlQ6Q^.|?O~[I
g!T~ l #{.I`sNţ7F)`}5>#IBu ~3]T͚@Ŕe*Vܶ?g-5`fo̐$),*\㣏` 0ZG}"|K]=9w}uAlpG `dM^*DrI4YwY؂ژ|Ws3$I3둅PE|k FW/f0}GFXB}m 0咤j򣪀)JZ|$es	ޖ$IgheF `$Lmg$iĚE*:z(W?:{j)5ǒ$)+VE FR/|KFK߉eP9#IRc,bLی>)1e6咤sq{$Ii`1 #u'$i>:C?$5jPkWA 9ᒤySwGLG,~01A|kÿ$IRchYUՇE`4|8|KƧ%E6sq.3O\z[$Ijf!T&  	ߒ1k6xޟG*H$*e!Tn;8 yg$iH-{.ZG~|p"IBbs% oIֻQG͕Sޥ{:)$1YUι}<$i|1㎺d數{^}|$IBb3 Xݒ}WG{$IJBbO}$:[T&6K.{??֡IPwyUJe}FP<zS&foIR=jޔǈIU0
5B i-IWKwTQ7_|>)_CUIl-YUw}PzgKmS}cg7%IftBwG[ 	9|nKY/DA\PvV\0{G.$IRYUkϺ Pye{uw}Mܖ$շFCA^ߖ-J>?wM$),Ҭ-R굢Ͽ PyےZ\Ȧw|%}N?lbF-IlH}wS[$I/$IJYU_>"@?&|fK4Y˫RZx$IRcYU{G?|fKxeԿ{{.u|^H$eB"y)) K$IkbFwy􈬏^+/KevI럅PE*OF'}!|^K5"zLXޟkL:5@fo-IpB(g Pie˟%Iwѣr?WIl̲@#; ֽxy-Iҋ:Ye{`);|%Id!T:]y |ג$la-ޚ~>˩),K$)aBwGt ɏՒ$dsMR{Vܚz:g55*F$Ii2
Tܿ, :3Z}S3?I$5^4&ft9 *|є2~^K>MH?Lx%I6$=}.3|VK!5JJeFH$qB(џ>@e5'|VKn:)LŊRo_K̓?9[7$IRcʳ
>@%M~N$ic=~'UQx{I$1,]sx g~%|NKu?z*0u/]AxsI$5²
x# @;)9-IƖTWqvvS}y$IOf!Z9  ~v$iSXR~hG:#)M^I$5*P`7N? `O9-IҦT>&$uH$)mJB\9-IT9o6hgRޥlQjӚ~I$5F>ڧiIջ-IҔ5kTuCⱛSﺣSoH٬fI$qB(={ #>%IEm&IFm
Wn P-yY$iJy:$I꜅P`Ŋۢ Rz7>%I$I1B(YD߻@Ob$I$I9~Y Z~o>%I$I1B(1vJ}a|$I$I4:} TJ眿ϒ$I$I٘f!TD߻@wϒ$I$I٘f!Ts 2o͒$I$Ig! FY$I$),"R} :$I$IB(|7E߻@u,I$IqB7 fI$Il̳
}{`"|6K$I$ecP@fG߽@e4|8|6K$I$ecP@뎎{jd)El$I$I<&ߕ  $I$IRV,"z0 *{,I$I a7{" *u'g$I$IBhw{j()Y$I$)ABCuدE_@%_>%I$Id!4'1 *{~sY$I$)IBCJhS\$I$IjА7 
˒$I$IYMrώpe癔<|.K$I$e5Bh\} .ɒ$I$IYwp l,I$I(a6w7 _˒$I$I3듅k.7 ~˒$I$IYb#~+ u)E\$I$IjkS +6|&K$I$e5Bhu;8 ׻,I$I,!ֽla 3Y$I$)YBCwqwp }dI$IfYF@
ɒ$I$IYͲbŊ[  V[dI$IfY?vke5 y,I$I0a5ewp w˩3Y$I$ifR^?} ẗ.ɒ$I$IYR%p3*|&K$I$e5BhH;8 :3Y$I$)aBCj'vɒ$I$IYR= be,|&K$I$e5BhHu/' Bǒ$I$IYMR돉P{cI$IYߋP?=%I$If!4G@EcI$IY?{  T̯cI$IYɢ  T;|K$I$5a4w;8 \,I$I4Y|ϷF@|dI$IY恿} 9/ɒ$I$IYMB#?} y,I$I8!>Ꮲ  Ty,I$I8!>p $I$IRV,P{= p\<$I$Ij^</ BuX>%I$Ig!4W} ǒ$I$IYB돍Ps.|K$I$e5BhoN= jy,I$I8!Կ{8 :3X$I$)qBCx{8 :W$I$IRV,yՃp {$I$IRV,: B{%|K$I$e5Bh,Pmg$I$If!4;" bX$I$B[OG_@2|K$I$սBhzk{8 U~(|K$I$սBhzk{8 U<yg<$I$I{:p xy,I$ITJu'  TX$I$B[F@cI$IWZMoS, B8'|K$I$սBhz{8 ջy,I$ITJPǒ$I$Iu޺} zW>%I$I^i!4u} ǒ$I$Iu޺W,Pǒ$I$Iuz˗D@=$I$IR+-i@u/]>%I$I^i!4n:1 Bu/>%I$I^i!4{wli]x63j%1q:LljJ'&fbfhtQM{nYFA@eeZhd2{<9[~IZ   *rZNzkc   ksp$;cy   tx(z'IRhO<   hAhF^$)ީ>   r7F$I
wʧ1   @UBy`IZOc   $)ީ    MW9]$)i	    MW9{8IB띱m<   hAh~(z'IRh5K1   @UBc~{8IB럵]<   hAh~;z'IRhw    MW9W=G$I
g1   @UBUWUN>   rϊI^g2   @UBc|$I/#~&   4\ 4F=/z'IRx    W9$I/d   hG$I
op!3   *1r$\{LL   hAh|Zۿ z'IRxO    M 4FB$3g2   @UBZ$I<?|&   4] 4>B$h3   *q$G_>   r֊I^3   *q$    MW9$Iu]u    MW9OkD$Io    MW9Wp$,l?   Ahm$)E   0\B㴰EMv   0\BcVWUN{rL   ( 4fh$)~o    Ƭwp$9m3   4ИvNG;|&   sI^>   J9;ߋI^Od   `B~wwp$;s!|&   s?voN>   J9+z'IRxK    l-;8I\}DL   ( 4fE$I
ox7g2   @i01<z'IRx;    lt7wp$7   PAh̆>;z'IRxUY>   J9ӣwp$7eaI\   ( 4fO^I/
    lpq7IRs   4И>"z&IRV\   ( 4f+޿I>   JC9Y/D$IJQe   PBc?o$I)   PAhzkE$IJQo   PAhz~:z&IR>   JC9YG$IJC2   @i(1$I)8    IDATtr\   ( 4f#$)E/    Ƭsۢo$s   4Иu$I9t2   @i(1k$Iij   PAhڻ:z&IRڟMl   ( 4f*z&IR:9|6   r֊F$IJS?    ma$I)   0<BP7IR?k   PAhz z&IR>   J9M⑿$I)^   PAhF믋޿I]e   @B0$I)z?s   4o[$)G>   J9Mo$l   PAhW{$)M^>   J8Mwo$g3   @i	蟿kM4u   PAhzgl{$)MS!|6   q	޽I?9=   J8M@F$IJg3   @i	Gѻ7I4   PAhvM4U>   J8M@{WG$IӠ[%   4V8z&IRZ^>   J8Mu]wo$3   |s8M;ߋ޽I!ۄf    B~hITݯ]l   ( 4!uE$IJS   4Єo==z&IR>   J8Mwo$ixI   4Є.'z&IRF^>   J8MHѻ7IT    A&wꧣwo$   4Єt7{7IR3   @i	轛$I|g   BE$IJUg   Bעn$Ϊ   PAhBZ<z&IRW>   JC8MϏ޻Ig   fpzЍ޽Ig3   @iI>wE$IhXe[g    B4՛$Ij}   4oFMTu   PAh)z&IR~0|>   p9n$wƶ   4NDMT./|>   p޻I-g    BG$IJ3   @i 	j{7IroeaI   (3AhZ+_v$)]^>   ʌs%u=E$IJUo    Ah={7IR=C   8	<z&IRzkg   2&lx{7IR5   PfЄ8(z&IRw>   ʌs;F$IJ߯=   ʌsɟ޻Iv    e9MXG$IJW{_
    e9MXF$IJWmg4   @aBWwn$wg4   @aBZ蝛$Iꟿk   (3Ahw$)U?   gPģ?轛$I{u|   (3A(he{7IRU    e9^轛$Ij}'g4   @QB޹I~o    eF9蝛$I   PfP޹Iޚe3   ( s$)]    eF9h蝛$I}q   (3A(uUE$IJU~(~F   &/G$IJWkKg4   @ABAF.޹I~o    e9p|MtuP   (3A(H/D$IJW3     9z&IR>   r
đ$I?he3     /~MtUGg4   @ABAڻ:z&IRZ9   PfP[uUE$IJWo    A([D$IJW+>   ʌq
4Ε;7I?{e   (3A(wn$kp13   @޹I?A=   ʌq
;c蝛$IzeaI   (3A(P?޹IN?>   q
96IRi   2Cv}$I)9   PfPe[hs$)]>?   gP{wD$IJSg4   @!B޹Ig4   @!Bs$)_ը.=/|N    fiMz]   (3A(XE$IJYi   2#usM=)9   PfP?o$)e    eF8E[XR׃NMt]?   gPn޹I^y'4   @B	o95z&IRZ<|N    }m$si   2}$I)9   PfPݣo$)eVi   2h6IR69   PfPU/޷Iꑻ4   @BITGwn$嫪֊i   2wMM9   PPo$)ec?>   ʔsJ6IR?{e   (SA(I޷I?E=   ʔsJs;m$lݛ4   @rBIW6z&IRFú,:|V   ) vϭjr$)e^?   槗P"#wG$IJYi   2޶&z&IRkWi   2\oM9   PP"S>o$)en    e9%96Ir6esg5   @RBu$IikY   PP&˟SףaMuY   0?}$I)럵]   (SA(᭧G$IJc4   @RB/+z&IRF>   ʔrJw'm$lد˲gj   2MMY   PP2Ͽ&z&IRںGY   PP6K|OH'[,~V   OFo$)ek    e
9%4}$I).|N   ) P=m$lد˲gj   2eu$Iik~m   (SA(o޵I1    e8%ѻ6I?{e   (SA(-zЍ޷I'j    m$z9   PPRo$)gUUV0|V   ) Tm$g5   @"BIuѻ6I߆j   2Ej]$Ii_{   (SA(֊{;$Iғ޶&|V   ) X}$I)Zi   2EvfMvY   PPbVG$IJ[?    eJ8%;ѻ6I;j   2%]$Ii\v@   (SA(N/޵Ij   2%E$IYeaY   PPrn$)m]>|V   ) wm$sj   2ѻ6I;cY   PPrk$)mk    e
8%ѻ6I6Z]   (SA(ϪA'z&IRF,:~^    4F]n$)m#|V   ڣwm$տ
    %9)?kyM/=|V   @F$IJg5   @IAh
z]MUg5   @IAh,ߺG}$Iik   `>/)1z]$Ii   $ 4%=z&IRzgK   (9M;D$IJڣg5   @IAhJt~oM!|V   D{kwm$m4v    %)ilm$ok   kwm$    %))2]$Ii_:|V   H]$Iiqn   (I9M޵Ip]k   i]$Ik}߇k   4Yآ{%z&IR:#~^    4eF\k$)m3g5   @IAh8(z&IR>   JBBSwʧwm$m-   $ 4e:QMU5   @IAhʴvU$Ik;   $ 4ѻ6I;#   $ 4wk$)mK    %)Կx]$IisI   (8Mމk$)oN]m>   J"BSs[Wm$   $ 4Z+_g$)uc?>   J"BSz;ѻ6I?Y   PqR[N޵Imkg5   @IAhJ9z&IRڪCuYX>   JBS{wm$Wk   Дj=$Iy   PpVKA7z&IRg-    98Mw޵IǇj   \qpMU>   JBSw'wm$   $ 4:5z&IR:A   (	8M֪D$IJ]Ok   Д'z&IRW>   JBSnxѻ6I6ZY   Pprs>k$)oa]{^   (\F$IJ]{7k   Ahʵ=$Iy   P9MϪ~+z&IR?   c9̀=F$IJg5   @	 4k$)ov]n>   J ;ѫ6IRW5   @	 4:%z&IR}(|^   @B3ÏuUE$IJ[5   @	 4#޵Ij   AhFo8!z&IRڪcuY"|^    B3vEMԵy   P8͈޳I1    %Ќh=$Iy   P8͊%uy8z&IRچ    1fD$IJ[}_    %_]$Iky   P8͐qg$)uݣ,|^    B3Wl$N   p%K~;z&IRچ?   'Ahƌ$z&IRڪCuYX>   ʄ9͘E$IJ]kWk   2aB3{l${5   @0{6IR?gU   ( 4k{n]ѻ6I6y   0?YB3h]$IiZ    efCwm$υk   2AB3w'l$sĻ5   @ E$IJ]y   P&AhvxQ]WUMo:)|^   	r$Izrcj   2AB3jpqѻ6IRg5   @;c=$Iy   P&AhFu&z&IRg-    eBfTkǟ޳I    eBfXؽѻ6IVg5   @6]$Iky   P&Ah׮޳I=|^   	pag$)uWk   2B3?#I-k   2B3z]$IieaI   (c 47k$)u]>|^   1sq+l${{5   @39{6IR?oy   0nB3ˣl$nxY   PTk$)mU,l>   95Swm$/k   2FB_"z&IR~ |^   1rj޳I    eˣl$nxy   PCTe}M[uYe   (c ÛO^I׆k   2&B?{=$I~/5   @=$I_W   (c ]^g$)u/
    eL*wm$mЩ˲5   @|JMԵ   P!z&IR_y   PAA:G+z&IR>   85Hk޳IѺ5   @]$Iy|y   PPo:9z&IR>|^   E 0G$IJ]ďk   sۣl$np5   @YdBl$nt   ,2'z&IRުn   ,"^U$I   ,"/{6IR;5   @YDB9l$nk   =$驫;|^   E Po޵IN?>   "qj5GF$IJ]wk   Hw?D$IJ]   ,{6IR7y   PPSmwm$<\-g6   sjwm$/k   lpA{6IR=   ,=$I_G   (A>z&IRFw}3|^   E d˟S׃nM:uY   0ynU$Ik   l&\OMNH   (A_=$I\~`   (A{ZMԍ_>   frjϪ^޵IjTVX   tB;Ϗ^IΗ~/|^    Dݿ`=$IO   l!1޳Iuǆk   ۻ*z&IRꪇ    e38!ѻ6IRe   l"!0=$Iy   P6O蟵<z&IRkWk   xBml$nx   l"!Z]$Ii:ea   P6O I>   &p_92z&IR_y   P6w'l$   l!Uo޳IѺ5   p[u]ѻ6I6el    }U$Iy   P6?dpɾ{6IR;S   l$!~Hg$)uk	    e#9Cګ_g$)uwk   a[U]$Ik3   `~9$F$IJ]?	    e#8$sw޳I95   @B<IwG$IJ5   l!ˣl$>Z
    e9GE$IJ]{k5   @@B<_޳I&|^    SꝱmM.b   (A9l$nt   l !Rku5޵IѰnm   P6Okѫ6IR9-   l !/G$IJ]
    e8z'~,z&IRJ   (A{6IRW=.|^    [twm$l   g 3}qMΩ    IDATuy   P~!Q{F$IJ]5   @xF>g$)uo>   ʏ 3j{6Iroe3   <!j?j$)u#~f   ?=!~᭧G$IJ]Ŀ    8#!z&IRW>   3pG=$I=xk   (AOE$IJ_kǟ    i8A޳I?Q=   pb;6z&IR
    i8AzSMo_>   pbtxKMJ]n>   SpblWm$_    O wMMNH   (OA6=$I\yH   (OA=F$IJ[5   @y
BlcMUUZ   P!6guD$IJ]?   exy{6IR?{e   (l$nxY   BlQ޳I^-g6   @Bl^f$)}^>   pbU~'z&IR8|^    Fp|M88|^    F띱mMԍ)|^    Fl$宪֪l   }Bl/jj$)uC8|f   sb>z&IRkWk   }Blǿ,[$=}    $>g$)uUѺ,}V   (Bl޿g$)}^>   lVuoG$IJ㟨    BlD$IJC5   dv޳I5   @qbst~oMvzY   T]_c$)}#4|f   TBll$   rbso<1z&IRFw}3|^   TBlޙ{6Ir7el   ,f$)}S   AE$IJ]τl   ln޳IǇk   l+޳I@]l   `l>z&IRڻ   5oE$IJ_>  rb-۪=$I\   M Ģ=$IV   AEѿp=$I3   k$!EG$IJ_mg6   0HB,nޱI;l   `X4UYg$)u׆k   `X4ÛN޳I~.˶
   \8hzkE$IJ_{
   \8h:_/;6I;3   k!Mk뺪l$npQ3   k!7G$IJ]=   k!Cl$υl   `QXTo$I   5wl$g6   0(B,eϮA7z&IRF^?  IXt/޳IjTV8|f   s Ģs5$I3   k!]F$IJ_U3   k!]ޱIl   `1X|K=$It|   M Xo>%z&IR:9|f   s XZc$)}9|f   s Xt&z&IR7~#|f   s XV*z&IR결E   fc3z=$Ikk3   yBãwl$wGg6   07IޱIGl   `n916}c$)}#l   `n91>˟S׃nM>   ԳA}qMu@   fcտhuM.'|f   s3A$Iwm   fckwl$寪֪m   `nf91^K5$I   ԳA|JM)|f   s3A럵<z&IRw^>   u&z&IRl   $!ƮO|Y$Iz:%|n   s3A=xkM,   Lrb"Wc$)}[   Lrb"z'}<z&IR,{v   f+6I~>   d,N];6I;3s   /{fYz{L-B 	!	@B	$@B9Nr4,Y\qMƽ܍qn&˶lkzkqH3Y徯3Ϟ+YBX;/ g$I$Ij.!M;E J>mI$IԪUBX&wl P	~)|nK$IVjmѿ_J-I$IZBHkj^* 7-I$IRDpr )(|nK$IVmD럹(wl P	>%I$IR6YiuV|4k P	%|nK$IVmD˗< C$I$Ij&!Mу7F JX{o̖$I$Id!7߱@%-I$IZBHwW =$I$Ij"!M5 +$I$Ij"!MEMiЍ ^-I$IRRH;/ TB$I$IނM7+!Կ`߯@%tlܖ$I$iZIjqFw_5YY)៉ T`^s[$Io9c4{)Oywx)YòRHo-Wj P=ׇmI$I|kR?NO/ysٳe!"_=ǿBzȷ~}$I$iRgމ_MWѪS*YwBHa?i] =s[$IL?m؛uG]8YY)f :!I$IҤ;catZJ|N=pCsְ,VgG@=xcܖ$I$է|<S?<.٪[<rgaY)| 46oݒ$Ifg61f~RhO< Ϯ{߄mI$IR[gV^󛕅B\qP 0d-I$Ij{fh/kXB
wW -znK$Iޟٖ-|N׬AY)} @e۾)|vK$I&MS{?-_󛓅b[s *{g$I$iӐߙ_~sRx;/>w >%I$Iޟ$DRxv>w oے$IuoHvaX{_􏖥e!&ȷ-I$IzvkޟoNB
[ Qݒ$Iޟ/7'!75/ *a)-I$I{Fg5(!'E= P	wmI$Ij{Q:YR)ougg$I$?{7'!ΊF= Pݣ!|vK$IR˷{O#^uLD֠,TeH( nI$I*{o3S}49~B:J {$I$|ɋ?HCD:?/k'kPB*MO; ͷnI$I
i&Ϧ=zsd!;+ TOQI$IjJVKC??5;__YRij TCg$I$v֯O<Y7#?~1z'}-k.kPB*OҠ}@%٪M͋ߒ$I4ky4G:J  	ݒ$INyOw67'!;FA P^$IReoGE	_YR3 *cx[$I˟΁K3KE:%*w߬AYTk QtMM$I/~37XO%bt֠,T @{oI$Io/fU_󛓅J! ^/I$i?w0gBHkg rV$IT-^:j|^JWgG! a/e_>%I$7&#kPB*]җTg TF?ߒ$IJޟ0xJo=39Y!,蟻U$IT?:럿cP֠,TW}@e?=%I$'? w	JYDE P(^>%I$b_x53xBHǯFE P)݃?>%I$g6~{6EsnrBHlsRt# EoI$I3zn:{h?fBHmt Thu[$Iғ˷xc~;gUPJ[# |7oI$)k{`ip塩xW};9Yuty =o$IԘ6o/oNB*m}@._>%Io_yۥmˢȸDR+}&@e>%IZ`N.7=kPB*u ߒ$IRy-Ni{ş󛓅J]}&@NJ$I*ޟA75xsa~sR;g Tk$IT^:~,XأE_فӿhs"kPB*u4FK P,e>%II/yc~;ipaп`#kPB*}{}.@tP$I洅>cHUWTWq`fy29Y.#\J韽E$If|xPϗAYu| 2-I${bsϜAYw|G RR3\$I{._5Fߦ	ꟻ<<.I$={FWg Pgd!J4	 *ep[$ID_韵8* +3|~K$9y>g.
?e!J9g T=|3\$I+_'[@EN
?Ӳe!JoRϔ.I`sg`̪i/ߜ,TF> RƏꈞߒ$Iޣߺ~{}{YRe\o R3\$IyO@hީ~fBH{> r:|(|K$)|ޟGoc֠,T;'|韽E$IR{Ə~} ;kgd!4Q*DQ P)VpI$]SR{?`4k(:b9:9YRo:-j)F)_.Iz'zs5kPBTDQ P9C?>%I4~fBHsEQ P9K	$Iznڻ/4lǖ?Ԝ0&*U)E9 R<z$IoG_&sYR=pC9 =3\$[4u~Ov:~5(!U3s3\$-~i' Ooğ󛓅*Y o93|K$ծNJ#>أ߆@ew|~sRjs
 gO/	$Iuxn:-~}?۳e!`TFU P9oY$IHxjo>kPBd[ώ> r+$I{ B[>~oNBds> rG$I-{ J"_09Yug Ts\$iy@yB3zNdBH,g TR$IsޟNY}j3zvdBHx
 *gx3\$iVZij>a/~oVBl}d@{)_9.ItoV lH|߬,TƟ  fsqIu~o5W( f&kXBl%J_[$I%/~?G]uX*}]`5ϠaY-4~;)?%IR3 7Z}]\߬,T醷}n@%wx{$I5{ x{U󛕅*]m- I_$i?}Fw\>e!J=/- ፧qIT/K>zO= fhx˙,kXB 0lg$I@6K={8({ `kq󛕅jE L>%IRʷ{O}myYòR\ *ir9.Iޟ( 4D`ְ,TS T<zOʦrI4%/J>أ._n `ƬaYw~O g$Il;ko{ѪS*FW ީ߈󛕅Fh?}~@%>%I? TMYòR-pr 4ke$Iޟ+ XOԬaYN}~@5Eʷ~},$Iޟ~ U7pCjQgߎ> GC,$I@t;YY-~AJA 4Y.IR_sJ^  &/߬aY6߁  ^ErIso 0QvoYòRmꟿC YY.IRwUu  &*_5,!զ> >%Ijr#wF_ `߬aY6[T U<|{,$ ~;|fBHXs[Q =\F`"*  S7~o^BU|;,}?g$IM,_k  Lh7k`BU%,~^,$k5  &jt50!ժ.}@uӟP$5n Do>#|fBHjjTt> G~.~K԰:~  &jxQ7k`B]O> \%I|C?} \v@jW TW?O$5_ D6|fBHFg Pi$|KԤgn=`z7k`B__h}@e.7~KԠ=`GCjˢ4 " e6	$5ՇG η,|fBHg TZg$5gG~ YR-~篣4 4/$irV]=`;=|fBH,g T$IM 0QW߬Y}@w~w<$Mmh=`rF>7/!նDm PisI^嫢G> L/co,Tz9lJݵ2|KT;'zD6|fBH{6 H6?>%Is>=`>f!`Tt> ?_    IDATz)~KTG}!zD92|fBHnxi TsI\q 5Xgj]ͣ7 a?K_>%Ikw 0Q߬Yu *{gg$IumcG= LTYCR˗80J^sTL$4zDulj+8 A'K^>%Ic'= LTgGo,T}@udL$v-$b=`ڻJ,T}:\.IRʷ o54!վ|7Fq PyEom6^\$Nu`HVXBjDŚۢ9 >%ISj@>lX54!5Fu Py+
$թS &j58!51_> )[Y\$../zDo>#|fBH;: ΁$ե-gFv 񓜢o,Ԍ"[}@.?~KT5Fv o,Ԙ}@5)[.IR[IJAh<Y1NZy Y.IR˷ =/gp,Ԙڻ/Z\w\$u Y9-8G< "_=.IR 758!5'Gy P~7|KT/F)-znU}@-V>%Irk 0QEvmzTg߈> C)[.IRUq 5
!5EMiЉ> :.IR[IJ~(^bnxs> +$IUۣ8 L`^3BjZ> )y]9O8 L\E3BjZ>}@mtxl$jN =3BjZ4D P>%IZK 0q?>^a!&6 aIvI'8 L\{WX} =]*U 0q׆WXu ǅvIRG7 Lްp+,/OE Pl$U΁=`F>ղRs{E9 =g$IUwFm MjY!p$i\yH+|e!9ϣA 0_>%I*{ 0q㿐jY^=B 0z9|KTmh=`⺇}*~+YэAY 1.IRkq !{zVBHͮNg! J{wwIZGj /mVBHͮ{ǣB YK$IeG5 L^ysX-!5;UE_ixG5 LkgZY*LZ]ҵ`zY^bVg!׿p3 jer.IRj# B/5|5_>V)y3^2=# BNzVk:!5|WT" JOxI3  ?z54~ЪE $}WFg }sX,{.5\zR53^Rӳ (_Y4BH?OF P;>%I*C}>= D}4|,{ `(|KT/&9֏o j;g$I>"z$@j(!}>@]>%I
mj^*U# B!~+WBu jX{on>%I;1 Y֏/_Q	 9$IQuQ a:^,VGYI?ˢH GxI\qP(0oj(!ꟷm	 3|k$I= F/~^,V%B9I )'|K4= iLѳX'd!$X4G P;d$qu\0+	j=!!'q~Y	 yI&}/ 靱0|,g% bs^I6z a}*|,F PKEoYg$I(gG/ jy~E4D PKݣ>?%I@9z@Hco9+Z9/I$^{L0#wbN>3;3|K4-4GG. |z<V,L ;zI> .X'e!$=U6IEs jIϏ$QsE[ ;+X'e!$=MN>7G}>|K4W,z@>zRB;ߣM ѝzI|kR*Q m>zRB}& xF{If NF3Y'e!$=]6NE jkp^Ynp# B"|YI#O ^-^>%Im	 W}'~&+=UB3;O _$V8z@gZOk	 6ڔM$FK ?j=eBҳT<tK
 7$I
 ?*!Y+Zy/I҆G* K/(|.YIROD Po^ʷz]̗$iCꟿCDp;.j=mBҳ/{EJ(,Z럹y̗$iCq Hip3YgXIKR ;E|I֧n P
>z,uβ j{߅|I֧ˣ( Bge6!i;g) +g$I3nj^*=F/JO.-|NJ,<s_' BsYgBHZǆ7}@92|K4=>ם>z,uwE Paʷ{Kܗ$iZTtDOO ({g3e!$c]~!LF蟷mܗ$i]c J{اgZϘ47\:_/Iҳ4	 YgBHA+>Wz)|KLK_Ҡ=2-4|>YI3{E Kj`/I= JctYgBHA֯>[1~"|Kt zT@i.VlVYfkW h]+$IOU{ P*S>z,? ~I~DH (Ίg5!iuV|4|xj$	mT P*Jϖ46^Jv $I=ѣ JXsk|Vk֣፧D >%IFw^=TW>nYIQ}@sφIڻ|T:e!$G}@/9|KԿh wgZ딅kn>k9JB0G'" KQ|i)!i=3F韽E$5	_ P:ׇh9!i= MW$IliMѣ JgpAsZi]ֳ|ɋS\ hY =# JwZ뜅o='F!_;$Y z@)u`Vk6i}@\~$5/ 0lgZ뜅wc <-^~$5GG> (}Wif!MKţD 8ӧR*Fc Jip~Ze!$m`˿}@5JH4/-z@iY֌6a>{zH[R Jǯkf^ h?-^~$ճu P^~m>՚QB,4# ֒{$+zk KZ3BHg->zYʗ6. IW󶋞p Pjj8!ij3 .wIR} uBVkYIFVE L~joIR-ѓ Jυlf4K.V9 5$  xvE:eSZ3BH ~$U;FO4 (Gl+!iʷx#k NH[R귣 ^>Z,Ylx1 4Zg
H TB{m+!i mte-Iq]~>0z@:)[٭ze!$b}$@uL@T7= >Z,YnM2 4Z])[;$uX蟳eVkf;E x3	$Ih&i 1 EVZ,Yse N6oH]/GO, HWo;!i[TF x˿/$|"_= 2F	jmPB4 (IR9oI 2XWVk1_>'8?eSrRt TJȿjmPBoO% G|6n I*QS3 TNoJ4G, OV|r=sѣ	 *X{_WkYKi qwH˗| 92|YIsT{_>RR{$I.7z"@%N9g!$US"? 7Ҕ-8 I
oz+ >,9lpg5 cz'~5~ I
hsh5c *<u둅4ug5 c#)wId>= ?<6|5+YIsOߎ>3;wIjΔ ;sf%!ior;$i-$8z @w~wLW,9{l 'kMҗ$Is[-G TZJԼ֬d!$qNi4>0[I~4֬e!$ME S|	9h T^?וf+!iNz <ѻSewI6d gZ4ۿ5 }
٫sПD Z4F_} O(RgG
y \_lWkV&T-p iޓ-_~_$m@S'E ?ߕf3!iB3 x_"fSwƂQ o֬f!$M?} W3Hf\gMi4# P_Dwf=!iV} Ϥ3Hֽ|NEvZ_sWkֳ&X?>g1Ҕ-|NA-4o?/zt @txW,IhTF 蟻< IzƟ^ fY1Jҗyf=!i92H M1J7Hw:zZ @-$|Ϋ5'YI{F :(賂;H\{wy OLh6!i^h} `t'$I%+U?e 0:fWkNtZ ;$Ih4ѣ j>|BH
{?E tLAԼ4  64WYI_h} 3\{CHR럽4z @u|WkβzN hu)wIjb_N s(RO},!)މ_>xJl~&5~uG  KZsT맷 @]~h?}@#Z>՚,Fw} {gTߐ5F >>՚,z'[9 A'$յ|WѪkO{ h_f6	5YI۽9 Sӟ^OHRʗ,"F\yH@9BH
nt%= FN/OHRmixw hP,z  [J٢)$m4c |kJs\o>xԼ{$UuG H.(M"!2 6P-Tl<X b\PDBR	ꝱ0 fAWHRZI\qP JBH*A} w:n!IhsãOn h"_JBH*IE lR[~RSOl h&Tg/>o>
_HR0o># Ə>/jM,!$w EETeL/>~{&TF= Y~w{/!Ie(hG3 5,?kI  fYݟ;'!I۾ dG]Af!$ (/$5M#wE }OPkYI%ktU  EjwId~ P.Û'5,;}~<  戥&;)G/ z9ĳJVo \/v;$Y6Iw>nS)wIg!$ݗD `54K^ם} `twBJXG `4[[!<t E~oP+$!ds @۩s=$iCcS X~wP+$!o~l  &aKC?~wW2 F;Tz'~5z>  Rw꿇?$i\yH	
 @ew²JZ)3 ;lj{$=[G͌V]}l 3Wje!$gD `EC$ٔzYq	 P])~P+,!ub  %/{E]DТͦ ;'"JAi؏ @}W|HҸoM{>wjf!$'E
  Hȝ{#]OE#  E*e6	WTG~.z^  9wI+ix1  0<.NT-^Ҡ=3 Hn{=/S> Y³*#g (RMHoҗ} xv?G(*P=7 ^w|ʗ8~"~uw ?w{ZBHB7 GF ۽9"m?wyJ(x @{7ʐT=; )Sg	Hv?n> 92Z}]}Cd!$U @ٌwMm~WT_> 96B	j"!BV_=C |zʷ|u]ERZiTF] w|gC,YIwƂ T+[gJUDW ,V*TϤTѳ (GB,8"<_, ;ڬ?    IDATJT=K zNʷycERp6I㿔Κc	 Ho()!buq T@~(uWwI1u4Z}]Q <>V*Ve)3 U|Wa$M6W @J8^V*𚣢g
 P!E*u;ۧ pJT?  CT^h}  %1;ZBHbѳ " u|ʦi$wYSe
 P2ݣ~WQYImS  ix۹ӻ4fT7 ʨN/U, Aw/͟~̍?{i*:G @.VEf!$UyiM3 ⑻RzT-_zg,LE ξ~QYI3 -g.?~ǑJvoNwK> uQ5eSc*mBR˷{KJE=k :Uo;#.;  4  *ZBHx[Ό5 @?wyʷxI}Gj;BW6 H6NV*^7 @٪;K)[iG[	_IG 7xFg!$U͟Κ \{S`T|_퇢;ZBHA/ Ћj-hjy( 0ڔ/~a}GYI5D aFK#?Qrҳ/MT<tK- PSK	U,4 4P;cPCRiZ9cipa)ߦ @u@G
YI5wעg `EвWߋ{q LR65/V%jR)3 hA7._ڻ|HD֯OF  hi~R2YI5jp3 G7:Iʦ6
'I#vk<o5 FÔoZBHQoa x[R/I[e{gڣS귣  SHjU*!NMmE  Om4LÛNKC?ߝux,ǥ4E <A;~_RRYI5Y 5R{ߟ/捩wJ[ϙ^b Q?EߝԪTBRR%EL X7E?uGrEߥ;#NFu4 P	CU,6 0sn^sT/yQJ5!+JŚۢ f(RoSU,=sc	 `:m%_*ނS{M=Vi؏
 XoLJYIul秢Hl uǧ1_LV?R%ʷ{sip͑謉* 5C"V%j`ѳ	 `Eݵ2Xڻ7eS]*Gvo{7D ̉ѻS`ZBHi]1z> ̹"?:챿w0Mp;k 4FEw1f!$ոѝE( :!uxʷ|u}LSEsLdx譍R  [!nVej\/D) P~nIo
iZ_wI{.Ki4R 7R] S/;~DIWٚO%uPiЍ2 ()U9!1zV 5GS?OvoIԼ{\ZRO9cR*F *a|wʦ6)U9!w|g h4d;?M>8]i[qʷ{swܿONHO? 7Ԁ=ٻhI#5{LF\⒘}cL&$1c4Lb8cow5K""	YdQ"4ր4[S{=9uH/wߪ_^O}V%  ѹԺԼ?jʕhz~;S=5,NM;/LGoOӌ  H~ſTB{k  A'MuQg٩ufIj7SeT?ILŲ}lQ*Wb/kJ/nj|/i{7:w_k곗 @EMdAH&x$ jڸ>u+u!ujjizfjtJj_{}ԺrũFur۩z_  FCطş/*AHz    ~sEMdAHzm>    `t4犚&4Fu(    LCU{"+^~l2IcT?    牚*4N-]    iğ'*AHNF    mhtJ9& $Y    pg9& $agG    -we& $a#    lAj"BҘ}{    }'֥bCMdAH}4    |~nl3ISU>}    zؘʽ_nk!ik]u`}    H)>8PYgƸצmG    `u;\Gy& $ygE    `uF9& $y}   V[焚>}{    ?XdgM}    R?XdeR{    wbJAHT+   XisAMM!IS*N+    cڸ>516$m}A    @MU!I+>    ٫Rb@MU!Iϩ!    dfI9&.8C    Vx:~ $M.LE    K+?TBW+}_   <UBWSU*    Yi]wTٟ&6-ֺzU    !?f_R}   ,o<)OAHVk$    J#~6OAHVsS7+    `:k?*mչ%     $i[?%    ]IAHtꮿ6	    #v̯IAHtjgM    9?ۓg2I~KwG?   `tTU=i2IVѷP    gIe4rC}    _M#!LOZ$Meˣo    0ڷ~'?AHҴ+{YJ"~
    ëI*,O*~ պѷT    ZO
?Ó-d4j~_9     ?NC~"O*AHҌktJ    Nb+$͸{}   irgwRBfU3o    04z}f' $iVՎ*>    T3;F!IsyѷZ    aguRBf]}   X"+_~V' $iNu0    aZ-?id4j5    !T3:F!Issϥ^    w?~6' $iOxw    Uw)lN*AHR_we=    MI2IKV=    EwXCT ]]    ~b$)}/   j=+N*fAHR_>xC=    N*N*fAHR_k'ѷe    uGI,3IoK^}o   Roeq    ys7C!I{4    EU<ʽ8M*AH@7    s?~&s $i`u"^    s}T,1M*AH5    I?g>d4:w^}   YvNT)V/TUn    N35S!I7    H}դ$g~&n'    Rm| +v	?W>f4/o:9>    _IE3Iʃl}W   `u&Kv?O>g4o_}?   v[Ѥb $[JU   AsT(yu͡u    xd*yT(yoT5   s4/xٙT0yu>w    جTL~n& $i+Tmz8>    S33p!I!5    :k?+y $)ɝRw{    YL=ʤŃ $)i   0ƚ*L*):]}   `uu]lǤb2I
v̞)UU   qRuSطI<f^/F    `_~&&AHRxKF     @UnH~I<g4^Z    18󿅟IE@!ICQﮩ*~=    @:.OŒ¤" y'_    v=30)*ira>~wK    2\$KZWqs $i(jgѯ    LSlQٗTVL=&ɝ$õs5ѯ    EU%-?5ش|#IjQ   \ybyTA(yig=;    #*K/?뒊!(UݩDFvOnDf    `5s.&n~^L&I/    ]/3.^1Q$I_bTm|     jlLAB*vn~~LV5I_x    `4pTQ޵1Q;$mνW    `ttYϭq7?G&g}(IV}!   Ukϳbjw'oպ    ƹ	?ǒ!uϓWW? IZ?rC
    &ZƓ6?W&Z7$i[5h
    TH?!sߕ.@͖ uFk    OQϮ[qDwHWm^)UU    Gge*NZ&Tu7?g&z&?0I]   0T#J*aoxfo`ʕT    D_WYTyP$i:5/d    @+>s:J*e˞?5.Ti5S>z{    "5T;gT᯽BN`4'FK    5)ALfR3^w    s۹gRR1"+vI>Jv4(Jt+W"U'^~    0T=LJ*F	~{PJ<$ͤ    ̷J~',J*F[~4JҌZԹ~	   <j]{D9xu֍_4jGlJ|   `t-w?QjRUjP{$͢W"    ZjG%I*FQŧA8UTfwK    A+$-||P?4'{   }JgNR=oj]wt־zM   T'SykϚb[sJ߉4vKUa^    0 /E9ThoϭB=ao
4g͠_    0 [?_u,InA6   ϪO>/?_hKvH?$AKƔڍAF   _T?JR1ՎsOBL/	4N
    \$<I*Fիf8_.Isjra>vPQ    κRtAyx.g>0Kk)Uՠ^    0GrHR1Տ{vo[R}_H\k]w ^    З{ϏbLA<6܏4+    Q3ώ=1A/BPwTu   YsƗrZϻB=ao
B$vx^    0UH*xeyTdR>5<(ucwu    QuSƟIvRBMMÿ IG    .[~F$cHzg| ~պ搹n   `:^swT57oj"Ꮉ~   `|n4|zFB={aԯj5ng_    }7τ"-JjrF'I}uA}	   .;,H*2q·g\ ?JRZCmx	   tuIXB)"%>K)uZ3p   }ՓrπjY='=FS*IuY]<   ؆VjGbُ]Sz%t_$eR[fu   `gua?6ԪWjG[   IX hjyRJWђZ   {E*&w
?ryɧ W%-1u9]P   Y/ʕǟHVjnA':3~W#Us   v#Վ3|Gʵͧi:Av{ÿg~pV   q8:RVRUBޒ6-Y~׾9_\   ƅϝ&}yzio$r.؝}   b٢)ךSߞsoo$ڱoM    7զ>>GʵrՏ*citj7EQҥ   J~~#eےR5}}y꩝GIwK^:.e    +.Fʸ9/P IwKU~\*   к3)ʃ,Usi]wt7IQ?ץ   `uX Fʶ;۷A(UU,I@o~oK   Q}dm*yI9sW9<¦GS0I{+^%   `dTT;g4RՏ{{JhB=;.L'Iv̞)uZl   v=Վ}kٌs/OSSPOI j^A\6   SUƙ?nԹ?2V#G%(InRget   {ǟH׺yy>f}Ƈ|,+W   `(מ5cbk ^մiPIw@?    RS|3)jG9f Ӽo$e}	   wWH9Wڸ~^zg}(+I<{e   `~4T/şHW}yz :T;dIw>O   FMKyuSge!Oy{TlIs   ׼Y[ o9=9>oPOR'%eXs   U몃W[Cjp|\lf  <IDAT|^÷bߗ%ߟ't}I   ͧMVH׺B=nJ> $qY   κSlQsA ӹXKBY7ԪE]Z   ݛSKSl[Cj]2A}5X$ƙ   lWTs)1ka:]/$eWїW   -jOg~:DʶɝRSӰ	z:뿑}$$Ij٢}їW   jS_?;rmS0Am8U?,IS?їW   喙qL\+{YweVC3t+C~U?)u;їW   Լg%R>өzb]fC5tRط$_5/d   s?#r_OU4nҪ?C~5"   ͧb#R5S(AR+aJR_Zs>++   0f:w]Ʌg#Rnx:JwzFSӦ;p%i.UţїU   `LtzFHU;썩ȭi yT$͵	Nێ   SIKBjjlLh$nT??lIk>}I   2}T=Dʩr(AhJUՇM4<1
   dzT)Z/-<	$i-[4>    R=PR.-aj]y@JNHBS:X4mZC/$͢rR񻣯   @vԛ;\픓ѾTz}/$ͦڑ?їR   `j~!746AhJ*mZc/$ʹ)RՍ   ]O~!|KƹIU!*A?[_őּSїP   `tZ~kH^sIޔr 4MN~/%4    QuSK5<Cj!un?/gTROM$iZ-[:_}   ]Uy?ːFr'mq iKLWS/   k^3i+~]j_-gu!վ{pj1Uǣ/   j^iԪgfgc3=ͩ~Ő~;Rj7/   i^3i֗RvCagus]iӒ῔g~p=   *BV(5P>AYݍƚ񿨒5/L   kQH^Z_;G1lB75ŕ-!oB%   m⤭WԼRoE?UGAh:=XK/$SgїF   ` 65/D~>naBmlJ?1NiNƷr]S[/   <iY~!EKڱoMW0́Ahu	N$4v&UG_  }p9֒R79N[Ϝ:?BЭ=Z:{o+w Ʀ?їA   `@Z-?r.~;R+:rC0[><|kj^*NT'ڍK   gĊ>w9Ԏ8R}RsS=nΩ<i'j|)U   '?ofS{]T;zT?S㬿J?ZW8oW?C 4ySo3X$O{PTkV}u   9)(d     ȜA      s!           2g     ȜA      s!           2g     ȜA      s!           2g     ȜA      s!           2g     ȜA      s!           2g     ȜA      s!           2g     ȜA      s!           2g     ȜA      s!           2g     ȜA      s!           2g     ȜA      s!           2g     ȜA      s!           2g     ȜA      s!           2g     ȜA      s!           2g     ȜA      s!           2g     ȜA      s!           2g     ȜA      s!           2g     ȜA      s!           2g     ȜA      s!           2g     ȜA      s!           2g     ȜA      s!           2g     ȜA      s!           2g     ȜA      s!           2g     ȜA      s!           2g     ȜA      s!           2g     ȜA      s!           2g     ȜA      s!           2g     ȜA      s!           2g     ȜA      s!           2g     ȜA      s!           2g     ȜA      s!           2g     ȜA      s!           2g     ȜA      s!           2g     ȜA      s!           2g     ȜA      s!           2g     ȜA      s!           2g     ȜA      s!           2g     ȜA      s!           2g     ȜA      s!           2g     ȜA      s!           2g     ȜA      s!           2g     ȜA      s!           2g     ȜA      s!           2g     ȜA      s!           2g     ȜA      s!           2g     ȜA      s!           2g     ȜA      s!           2g     ȜA      s!           2g     ȜA      s!           2g     ȜA      s!           2g     ȜA      s!           2g     ȜA      s!           2g     ȜA      s!           2g     ȜA      s!           2g     ȜA      s!           2g     ȜA      s!           2g     ȜA      s!           2g     ȜA      s!           2g     ȜA      s!           2g     ȜA      s!           2g     ȜA      s!           2g     ȜA      s!           2g     ȜA      s!           2g     ȜA      s!           2g     ȜA      s!           2g     ȜA      s!           2g     ȜA      s!           2g     ȜA      s!           2g     ȜA      s!           2g     ȜA      s!           2۳ `oSQ
NAy      2      !     8C           3      !     8C           3      !     8C           3      !     8C           3      !     8C           3      !     8C           3      !     8C           3      !     8C           3      !     8C           3      !     8C           3      !     8C           3      !     8C           3      !     8C           3      !     8C           3      !     8C           3      !     8C           3      !     8C           3      !     8C           3      !     8C           3      !     8C           3      !     8C           3      !     8C           3      !     8C           3      !     8C           3      !     8C           3      !     8C           3      !     8C           3      !     8C           3      !     8C           3      !     8C           3      !     8C           3      !     8C           3      !     8C           3      !     8C           3      !     8C           3      !     8C           3      !     8C           3      !     8C           3      !     8C           3      !     8C           3      !     8C           3      !     8C           3      !     8C           3      !     8C           3      !     8C           3      !     8C           3      !     8C           3      "p=    IENDB`PNG

   IHDR  <      F+   	pHYs    {Rk    IDATxwu}4Eƒn4Qר1dkbnxnז&&5kN(RaA.X@:J.T~ S=\=si  _   |1x     -  H  2x     -  H  2x     -  H  2x     -  H  2x     -  H  2x     -  H  2x     -  H  2x     -  H  2x     -  H  2x     -  H  2x     -  H  2x     -  H  2x     -  H  2x     -  H  2x     -  H  2x     -  H  2x     -  H  2x     -  H  2x     -  H  2x     -  H  2x     -  H  2x     -  H  2x     -  H  2x     -  H  2x     -  H  2x     -  H  2x     -  H  2x     -  H  2x     -  H  2x     -  H  2x     -  H  2x     -  H  2x     -  H  2x     -  H  2x     -  H  2x     -  H  2x     -  H  2x     -  H  2x     -  H  2x     -  H  2x     -  H  2x     -  H  2x     -  H  2x     -  H  2x     -  H  2x     -  H  2x     -  H  2x     -  H  2x     -  H  2x     -  H  2x     -  H  2x     -  H  2x     -  H  2x     -  H  2x     -  H  2x     -  H  2x     -  H  2x     -  H  2x     -  H  2x     -  H  2x     -  H  2x     -  H  2x     -  H  2x     -  H  2x     -  H  2x     -  H  2x     -  H  2x     -  H  2x     -  H  2x     -  H  2x     -  H  2x     -  H  2x     -  H  2x     -  H  2x     -  H  2x     -  H  2x     -  H  2x     -  H  2x     -  H  2x     -  H  2x     -  H  2x     -  H  2x     -  H  2x     -  H  2x     -  H  2x     -  H  2x     -  H  2x     -  H  2x     -  H  2x     -  H  2x     -  H  2x     -  H  2x     -  H  2x     -  H  2x     -  H  2x     -  H  2x     -  H  2x     -  H  2x     -  H  2x     -  H  2x     -  H  2x     -  H  2x     -  H  2x     -  H  2x     -  H  2x     -  H  2x     -  H  2x     -  H  2x     -  H  2x     -  H  2x     -  H  2x     -  H  2x     -  H  2x     -  H  2x     -  H  2x     -  H  2x     -  H  2x     -  H  2x     -  H  2x     -  H  2x     -  H  2x     -  H  2x     -  H  2x     -  H  2x     -  H  2x     -  H  2x     -  H  2x     -  H  2x     -  H  2x     -  H  2x     -  H  2x     -  H  2x     -  H  Қ3?*+S(ͽ_SO+բk2 QuWi𻀒|ɝ}Kœ'wY1Ճgxuw>Z?p֞YF ={"NJi6ugp׏Kϖj/AIk2cs~7PM)TwL<=o\;XZ_2j? <j_#5}c鞿w6-g>}[˨& XGSӲmKO7oߛ3:˶F>䝥: {MizLޓ?p}KdxmRa!m M0wlȿT$<MsJ#_~ǶsK,أ}ndƥXmVo'c fӽ@ekz}rt_KP4v `:ΝLْJ紥zל3|u 	/7^!Uu;1s>x6ӴuW @3_HպZ2<sw/fic wZWK)39s䇍 j4G}C⧔{N'ќ9>g tK?wHz`;u34GT ƨyoiZOo~z?gpPڇ 7AsS4 @}4w}A=DS<x[Zo7 0^T~=g<ӗ572jݷ@ >Te[E]zE_kNj};6 ȥwwZ_˶-7gpœ_6M~n u(Rv}a>|agMi_6掿Xw\)  Ti]ES?)e4>qoW7  _gC6ht'9hٶepݩs 50Ywi:ZMz7jG|RW5g  PO6iJ7_69_ +0RzyIm~?5g P#*.#U먹sʰ{O]_6!<q `;ߛ4R:vyV [Jsmjm-ٲFnUUMœ	 `.n8TK
HZj<ZG;<|y @Z~ϑt2|<vV(&a;e< vF9i97l.Xj[E_zBw @MieX䃧oڤ|n: Ɔw]Y?##UO{<"ic L#?RZߴ߄ڄ?=_QF (o{T=[}ׯc;_6N.{	8 (>Ic~oǆqڄY `bxߵIo}Hwn /;$^$Uix~~٪sǢ4 9#zyuUK"4 V)Eߓj>oQڰ+^XFkn<  jxǏJ%W?~hepّ z/7$-~J6SK_ٟ>  Tߛ'O_*e4>  ԨyOiu-ccpy__ZFGI `=i(5j[MKh=-۶o8 hoJ]as?1Zw>  6Q{<>F-kɷa1Z{?}L l?(ՒUjԮ?7ʨ& lӗ߭Ԩ_˷|5{6ex׏& 17߱TjՒ&~=_zP 0w_UeOgQpP.B/uy 0/z%F*vi-#5W  m7߹ԨMC%[gEC  jxZMK{J##uO[}  ,^jԢQ^gj;zg hׇ۪H3-c `A︬TKd< GH\F3  qw25fD?@1 jOV5O<>1| 
o|2nF:e 05w45e\2j}  L񃜢ij	ȏ hT-Fn  kJw65d,`~ uO_~oS#M6w l=^~wS#E9/ 1)2xQ6 >85f>g\u\y 0s]*3ϵ `fuO?95f:g>eϢ	 k~5^2<Xݣ ׿{33O~M)~  BԘhS 4w]Y%[Tf-gߣ t{33~0<  HgԼ4w|V}O| }33 yo{LdQQF}  ׿33G! PQi;?5f"gj|S X}/LdA~ Nw՘ͬV `ain~Tc3x6[MD jO	U9g38 @^ۅ՘Mm6exuѯq ʴflbS1 _y1<PsQ6  Ꞿ4TflBWG xQ_JG՘+J_  <AwE5.g#_qdk KsKjLUFU/e  ֡w>wF5*g#0  3n/715<XK;  3wG5&gѯ]  6ĠW_SV( ]*Tdl@O~ #$} AK$;%
 ~.ϊ'YO/^ ;g;<ipIѯQ  6GY<?^FXz?w{w  f]]je~m 0F݇Ks/YK͕/< -
czg~M 0F]Z{;B~M 0ǺwM5<	u?_ ./.ˏ((3/ݓ>S:t@iͥKs]Z_Go*Qi7>Y|b_vH\22A̔}זjɖM54-ݺ)na=2һ`/iڇzUr}P:G~h2ƃhxzѿ[ ?s*:Gykq?o>;k|j}ߖjٶgtɿuwexixBf<FuLM%}A2whhjdҿ=&ϔ7WhޢUǗҭX\}bƂe<߈~;	xy7-{jiҿRz?1 ѨsOe!2x2GdFR7W?=2dE҃:5$g(G$Oz?d϶,==52wJsqj{ϒ-=짩BjZ֖m[:Gt%0~PL٦2~_k,tKG_|g]8zvӣ?B?LSc^[ѯ5`tO<㭁M9#gZOsKJ_gSKלi>7̠majk<3Eƀio&o>a2`ƴ{KƼUd2z0F5wg6O)c>VFJ_~x٥2_v?O[Yg6+9>%עv>!LѿLMASZ2o3`cyƼT32Ghs<q-۶XϊJe~o_S@#[,<K)9)5Z?~=A?߅C
מ{3(vgxY5K>Q[GZ{*|RcN鞶(u,UǗ%5tN(0Ez~61nqXL{o)o֓W Zjvg\Uuѯ!`nixa٩sGK鵢u)9/$5Z+_?<u.?~h6k2Zs{1lxsV}⧔у7G~y4⿉?o4ue3k#5o~ ~bD5Qs_(kO/7,RcN_:u׏3F	[moq [J҃!gls    IDATkJK?c[޹GhYS7]zQ:|4w{i٣2bV)̱OY;<3|Q=ꝵ"[47=~cgZ-O;G9ԿxR-*lQo}`#VWU']iJg^-+_o\J?STߌ^n-+S>W4w|VT~Q$0Q~HӗF^?Ԙ?lGG'?Gaex녥wޥsKkWLH}13<Ό~;v?w=<hTN<5~D|].iR.FJk%Z[E_	̴њ'ߚhwϋmd+L'0FKk7#z[u\}bf惢FU@1l[kiCjnKUs_<2nFb;xn=q`'6./~\]:ɿ-.lhCڔO~;nTf$~>=,TFUϾ}F asC?KJ}K,/R-25%UY|Rc@UeA/+xR5=H?-.#UP3`&+_?2~.*u"-ZRY+`CZi>jrO%F,"5!UA<ӯsi>M&?t}NϞ6~Sly!-D~KKĿiQMO>'1ɧG҂t23h~M;kGwgin4r~i~SY!-dJ5~1nEs_3GӗRDCcZexǏJKOޯ)Ւ¿G*i;Q1G]/C/?t?K{ߟ<<{QjT>O4`]VkgOQ;yOe?#i}i,F*P3Xw掿~FHӒ$eۆ/Ijh,ޢZGZt`!MS˷+{~i5OU/}GvzvRg#	?i[|Puz}7M;w#-U'K`-5|+_|G.nE(_:`pg4-{jj\r`|ӏ<)rBf?"QiA_6oyNFx)Osg9h2+
?Yâ_3g~=ܡ}wiKSY3~ 0]Z^~6HRs'X:ex&9˽FR?b1ן~.H]xy7OԘR%DcsAlY_Zn$U\3x+}C)ajY/wsJsKjoϒ-K5pQc?.H3aRy$.w_I5gE`:TK	?Yn#]2SF	Mw)otH*>G5L24lǿfIRuX}A,LRd2ew3ѴIZT3 GQ~Hj݌	=<-ﻑh3~V?s)[ϴGB8_>f͒Tq3=x?#;aV(}}^7g</'I4ӃMs`~Wy e١,VW_$UAyR֚+_ϛI*iONwl~H?ȏYﻑEOG^Rz
?5w|ViǥӳÿIf<[/A@$8xFzPk=H>$IlszP{~H$UGRCΑ
?$IsGzPoQiKg$IRq?)3$IRע{Pk	?$Igxy=?$IgI@w^~H$U)ϒ-K|P[û?$I%<͕/Axp9 ITe<}}߃Zs@$:xڇ7>$IRut=$IUN=Q3@$<x~553@$<xם}3@$<xw^}g$IRyDa IT<KAxy9 I(?S-.$I^Am3@$<x_w>??$IԃF?v ITe<o;VUg$IRytOLj{?$IUNw>α~H$UO}|P[E$IUsQw>o?$Ĩgpiw>7$IU3;VkW$IUsO|P[͕/	?$ĨgMw>
?$IԃyOi4*Ւ- I*)*ԭ_$IUxRFk; IEϲF]H$-J<x;?753@$J=x>w>-G$U3L/Am<$fk;Ԗ#Il~oAm&$I2WCj$I6[?Am<$fk;Ԗ#IlAoAm<$fk'w>-G$U3l#eHjs転|P[n?$IԃDƇE IT<_|P_v ITe<cjZU9 IT<G|0$IRw| \s@$:xb$IRvZk׆$IUsG_s@$J;xZ$IU}߃Z|}$IRu{K}jsI*YZ盟?$IgDֺ|.$I^}߃Zs@$J;xvY}j!$IRu4k='$IU{Pk.	?$I=у7ǟ$I[2Es@$iQQJA5F9 ITe<Zs$IUs=־o?$Igx=~H$Ui?AuD9 ITe<OAuOL9 IT<W}߃Z띵"$IeF~H$Uiυ{PkN	?$I{Pkû~H$UYOAus@$:x:Uuj/$IUEZ_zuY ITe<}׃kg$IRq~M]j~H$UO}׃띹CY IT<?#׿@$8xƕA76s@$:xF}߃Z{M9 ITe<ûAZZEY ITe<ϊA5w~^Y ITe<+AymY ITe<A}WY ITe<G@$8x:^g$IRq{O]j1g$IRqV)7g$IR¯EF݇I*੖?-?gğ$IY}׃k}wI*wm]jsI*xv]jwg$IRq/?"׿@$8xz|!7@$8x' >$Isz;=;<$I7EW><$IG񣩏Py ITe<Ւ-KzP{S)<$IZmoA/9 ,$I2MF?~Y ITe<+A5,$I29EѨT˷?$IlǇth@$6xڇ7LM@$6xZ{&Rzg,?$Il/D񣩯8*<$I/u_]joxg$IRqo8ZUy ITe<+'@$6xzg?$Ilɟ?$Il}F.=(<$I֞}Oj@$6xeO-e4A:jg$IҢLgxPJi|Iy ITe<Ό'}I*_{0~Rw6<$II}J)V$IU><ɏF$IUU<`?$IlZm)a]?mƟ	$I2/y@)?$Ilgpݩ<9I*?
;o@$6x'}=<@$6xڇ3ּ'<$I/jxQ ITe<Ւ-Kwy@)}ğ	$I2E2{PJI*_qT=(/;$<$Iˣy@)exǏI*g<`l-mITkyZ_zu IjT˟Vh}J)?&HRr/y@)w֮$IR3{0~'$IO/DR[Its_FG5wzN I.i;o?$IR֥<~(R'] I.1R~HFK9x?N=(o9?<$IZr?ݪT~&HFmK9x:G4<IԨm)OkFGug$IjԶZm)~=(X&HRrE2{PJ\u\y I-_yt=()<$IږvtOٻpK+(R<^# G`E="zD;{J&mH^&tIBH%I2eVoZLZ^|>سwE<g$I*lq}j$|&HR!vg<qg$I*lf[6Z7	$)|ԾsR<y IJ,녧y><M	$T^xcW;g$I*G_		$T^xʋ_R}z. IR{YPJ7Gރ)|HR~ipT9Ryg$I*Ʒ#U IJ*v؇x@_/IT*T/<_}ZW>$IRPeL!y Ƴy IJO3y@Oʋ
	$T
4/.U IJO}'x@_>$IR0b3׼b IJOyjԭ=}RJ.	$)b,<{q9H)ukRyj IJ0O󊽢y@_uwIT*DYxM諟 IJ0Oux@_e3A$
Qa◦nFރ ~&HT,(#7EރjOO?=1z&HRji]x9IT
43W?g$I*e_ꁿ}W>$IR)
o0&_?$IRʽb-<<|C9iVSyV3A$pOڃy@_uITʺ-<1տw3A$pOu_>}k	$u[xʋ^R}RJ	$)\ރV]}zT^ IJVȅu<X3A$[!83A$Ou_>}
	$m\xC ^g$IJV̅}zT3A$O}y@_ITʲ.<S}}-|&HRvg<uI3A$Oyjm><}_L$I)Ǌ,(}FNo	$]^x#Վ IJU腧~x@_E3A$Ou>};
	$]^xSns{pA IRn{=oGʮo	$U_x}+>>$IR)
ԏ3 IJYU˛x@_WLg$I*eUo³y@O	$Mރn;5U}OL$Il,(mx@_/IT&ςRg<ua3A${pmR괣y@Jg$I*e_[y@O*;&|&HRYx~#~?|&HRYxO3׸pQL$I,._k IJYdyE[ԬDxOfsA$I³V/>}=>$IRiU=x@_/IT,<kU?g<y~3A$&>ZUv[<t]L$I³7h9RyWIT,<ԾcW;IT,<Ըpak IJgjG~,n;%|&HDgYMۍ> } IJg=u3Uv}KL$I³Z7}EL$I³gkk^[L$I³zkYL$I³4V=j%sA$I³:>}5|&HDf@+>}>$IRi"l_>}''FIT,<绢x@_ɻg$I*Md5YV>}eo$)MZԾke諯dL$I³->}	$4qYx6R혏G΃WIT,<xT^ IJgSߠ>}C?>$IRil-'Fg$I*MTM8g<}g$I*MTMT;x@_l*/"|.HdTK^R}R\$IiR̠#7F>$IRib̠5F֍ǄIT,<3Ϳ>}ݧ	$41YxfPu_>k IJg&Mmx@_OI&!k3׼b IJg5/Y}:]>$IRi"̰OFuZt IJcg$>$IRi3׸pQL$I3ڷ}w	$4YxfQcg<X$4YxfQET{o\$I3zOJvk IJcguV}Z7>$IRiֵ̲Dޓg$I*uYV?xZ{L\$I3˪'|Ϳ$4Yxf-%$u    IDATGI5 8uy |&Hf楻DTv[\$I3@>k IJcg*9|usA$2Ϡ߸gWEIT,<־3n?>$IRiXc;`->$Iʵ?K^ugj~(|uݡsA,vRMLGoMM3`ۤiGΓwI&[N?W]Rޟ%( ꬾeuUv}k\$i,{cǩqԾ,<su!#=S?ssAq~iWj~Fޢg$C;s׺ IRHJnS̡EM;$Ia? YxxukF~q3WMAQQ[?ÿdc{/sAA{n֬Nq֗ÿ?dcKw> |.H4.y_gW|2y IҌwӪIҸpaq,<s[=`ubWSHKw~Dn^cu,<&>P~g$8Uj-'nyɲ YxPS?`-#IYK^fjԺD(e3+tA\$QeOny7_AڡuTv[l$M	]}*Xi^Ok4HaKIӎ>MGtU_A[A`-1#O>j⴮90 ϐj]{H57SI8c)k	m3zc I|?j]x=H!U= y_oGﻹ}5Һk`,<jY|.} I[}7'~#wuӱ YxXދC`mj*/:|6H6橺ϧ_H+MJ݈):Z7g5/Yu{ATqn<:$g3VyԼx IEnLju YxyC/{cuеA
dua Yx}kX[*;>|6HR[?/n=8$ϐkݼ"Za=$)<=ޙgk3[d2%)v?}7H Yx\_>}olIxMWz}֧y> YxݢԪ"Tv{|1մ%;{Ҽbw,<#z I]eWOُwS~,z3~Mg.`n=)|6Hwsƹ9==zL]ïA񟎾utO-$}77OԺY}KJv%s͋_dA]}=Q=7$}7J5AkXGg$mR[7$ψjzr5	 I/hWnq	8ƹ_]vSeOIm/_Mk7'#XԿ3j̯`O Xﻙմ&^Ŀ3oom`y<iW}7F;q~guV]}]֟ME[IܢRu©o,<#ݽK`=j~0|>H&秅gO_} cy.AxV	IvK.IQY06yvM`~$z>H/|͚	Zuw߷d7M`=z!=$cwsV YxF\~uC8烤y|M=v`Ung5J	G3烤|MWӪOEOSdq%֧YI%/G3YxF-S&2<I鿴 OAC{} io=>p:o35/Z}} iUvySiy?hyvD_T!ivUӾ[Yx~0~}-|FH]C~'zt@n9!4<Y}su
G+烤U_Ӽj{,<TS`}T-3B̫ѓ
%Yxާ=q濄I3r8YxoNh}a4=6p'e?hf?p
O*;.|FHYP8#>~gkzr
l@ԿfVGNuf{
l@3gySYx}Ҫm焤M4YJjĀ)/:0|h؀񟎟6Ze7D
(ncM?,<\Y`Z76^uGNdz`M?KEvܟE
(Ws3p5lD?
6\D	(֭'s3-yyJFul@C焤ּl1Ӽb{.Yxjyul@o(n>'$-'F	(y~%O@͋wn9!iu6zD@O|?,<Վ؈	IijS;w9d	ᆩӊvVLE/	^XuPH=~%OPUD_FԎxj|"z4@!Un~%OPvv!Xmhb~F݂Dg	RkV&ojxtd<~G?,<AUvxmJN5lDυ
I]NosX瑛a`#?'|NHZ	mjXieRO`+RezOh Ԙe	S0	>+$R?PH>~5O`ސR}yY!>z@!UYx<v{ulBRkߵ2z@!UvYxk]s`ulBB*tSnQ (C\MKl\uwE(Σ\e7G_T/|^HE~G Radz`U
=8z@!5+F1y؄nT^y!ߏPH39F130S>/U'o}(a>gl:k؄hՏtUM3`YxƤΪki`BTo{(nc#g0IKvh^gTo{(C3G,<QD_tkO{x4OӺ0,<SjVm`'}.~fHqWow(ƅgQ/h{qPDPX>>gjkn7U!\e6)w;Vu_3FUke)'|66RyKS~C40ǧ{>7Lk||my0,<cV{E_տ3Cʲ/Mѷ8VY3%f|(4NՎD8s`YxƬƁY!Vom(>g>*:f}3CʩW\:V`YxưGE_@A)EW?ooi(n~]3O:0R.nվ90,<cXe7G_lg4U4Z>gL묾%zf45/Y}+C3ϘfdVJ~,|vHۢn[
{iC?}8iR[hVSyV`YxƵE[i0ݧ[!M`/:\>FgkvJuRҤUWo] Լby0,<c\}}T^!MR[OuRχσQd*0g%|~HReiG߶@JχτQd:}]:{E&g~ Ryj0,<c^` >?q[RjգoW Ծ0,<c^ߎt+mg4ε> Vz=Fg[EV|Z&Hォ"i]ߚR}}c>>Fgjr"0ASeׄik]{H-
<M_>Fg]di^{ƭNӊ=c3UvIIi>>GqL`-k3!un /!ҸT;oI`&3!5/Z	LO)E[ΣEߎ:{3~>0τT=7׽6	}FXm[~,63I<5
L)n?R}hvj|u	u1^$iVSe)ωhaYx&O:&H{i[؀	3I-yyJʆW`BOy"Se?WaLu+OsbYx&GukOʮo	'ț,v-l@<dᙰzI&_?Gj[؈_
gªOn&_Q~ШU~_Æ1W;g|dw_} (懍Ue0	T,<XG!ilEin<:6ubL`]ޜR} C8sEV}K3P?bLhOaS툏i;
ؔn7U1|fW	r[nTgg4h[y<Vfu3c>Lh7:y<rGi'v3fy1Yx&8O=[YxԾ[Agk~g>_pԺ[Pn??1W]{v3Վ#mSc`Z7g>uO}BjVfuw	0ɟ!gk^g}Ho@W9#INo#g«[3Lp~k-u*~dnǢ`zOdybh&Wϒ,<ԺzΪkReׄw} sT-I[x2ȯA1t!Uv|}Q>T}%ї?0Gǿ>OǾ*?wTxG<qgeA;;ϔ,<9PH]>ww/ukOG_T'F}&Tv}kQMm{JVeI'6Kݧy}TGTYMjrbY{ϗ,<ռd	gƚT;cG_u_N'}I#P;C3&2OF(v#O	3%f5JFy[Ϛ,<{33P@nj6|iԾUgMtj\0n^۽"|i[}2Fvoϛ,<UWgA<x{_ӣ/S`ޞζy܉a/`v쟄#QJ5uE_<i^kY')AZK^>[:}E<Yx2kRjգ1`LtVߜ'|6i~uI~
ĝ3<&Yx2u)0NԸpQ*/"|>iUv|?_~Aa5$|$OՎCUW>4*K_9N{;|&$O-z"Njp*ʎ<z:^>c'z4O߮7Y:Uq)Lƚ	#3)|>(OUԎD,IkNU|qӪM?*zN(Ou)&D+S-mS?N5`Z7W+O50g|өq'lJ[1S7z,)0#7iʋekRHHӎ	}vX,<u0z8k6$ՎXjpTJrLwve/Ov#n=iz!evܟ֍GnWdn~sme)B'Na͔$V7aUvT?ˣ}<Yx
R`0
ݧN+L>Sϻkߛ%;Cz0ϻ㙅 UY?d>@j~wT;Re6/%/OC~'5.X?87f%e2]H*/*~-,<}(N+unj^cE z.oJc45/}ϛ<P0͋g)P<~LKkN3)U7G}~S=RSe׷㛅H-2u{(x9n915/)տwv~{j۽"UT;qWR󊽦?m_+i~zsxg)X͋/fUO':\1t;tz)j|ɟ~n혏7$U?ߟ.2mW-~RZRg-[~4O0k# |Y,<[|j7 @&O 8ϕ	Sz ֟K_~,O@"6y>uO}
 zO?S.,<qעS  }o?O'$OA YjzrY<AYx
\W  fvϑ	SzU{ ꬺ&Y,<}-  3T?/Ϗ	Sj|" `zO-/2X,<Eojy MgGӟ YK^~n,O`MJoz Os3X,<i  nTYMy<Yx4]e7nF  %ggяjxt Tω	£U=> `4/=X,<zA}_ I£T;ѷ6  ݹda9,<zQ 
X;G/~gq Bk^]I[ΓwE  ԭ=*ۿ:L ,<Zoo] PHς匲h-*u7~ (ἲgdk< @4jYm/MgWE  }T^upA^Yx[ P>~+gGo֩? @:ܘSǟ䗅Gqעg  @j$W46YeKs   KVgь=1 !vRuz匳hf-yY>PH  J놣y£sy  X*)W<fޢRg @+?-?fU/F yy>ەGkg Ds݂bdѬ 0<4Yx46Ko  L=[P,<  ynrh?87zf  Ls
?ÕGW)uZѳ `"ԏ[Yx4Z=;  ^焟£9UYS)53 `|5+<  IDATmfќk^] [s~^+NT*/*VRw#ѳ `t)n~^+RSkMtӿ=O  KF9\)w}k	o> `-F+xeo~-Jh􁔺 =}>+z=5z*6MF XnsJL$bG]ޔ5c  L}d*MW_פT;K_r9 tJ?<^`u)5.#QF-zI<~G _e;#g1kxKSjqv 0W~SuV]3ڔ:O(ڷ=w  Ex*ۂ[v)N'Y/HyU(G |%*GSk5 `.
?sʯQʰ[CE  Gh3Һn>Oÿ(eOv, F9U|gYK7YY'5kǣռbi 0|S&zK/x~𤔪~(S> `Z~Ri5/<Kv	oc$b URe׆T`GnZyfj/P nz/eS=#_ӏnK  CȍJy_x7E*'|v> PӿR*m[G6F%&Uֵn=i tvl_E;ÿXW 0'6Y`gt/Ye|( 9isJvl5|S;ÿh_O  sҾTY0tvOҚ-¿p]e׭e  :ݞ*K_~^RiF_.<=*WՎDJ( @S?'6OUWLgʾUG1  f۝~WH87npi\4xY}0G @.?)ͤ?:'V#U?/Ԭq\ N3E*\Ҍjx̌^׍/<=BRƬ Σ
?4j$Ng8OO/T6K;5y 0+㩲BJ3OsTpʿNoj `v@*ͬSzK3VmjGGU ~>*͸EKgxi^wxRŨyɲY_  Ѽx3J3vRGN?
-S mx"ۂɩS{v׺49V? ]gթ+:*ͨL5~g4zoC~'Nk `mݧ3J3R{XO>MP5Vn; [~,UJ3ӏ[t}8Uo
<w9 (F9UsL}.R;iTL3 N;ՎJ3/γy֨xF^uԬ ~߇cTQ#>:F[v_w?CIk\(Ҧ,5jJЯ-<}HkoMS	 @4'ܢ&Ծ㬑]C_xzګoMSMmZ8K D#}|IGz-dԞKW7QyVYPS uɩpJ9˽25/bFmd󚷜ʻ9<Wح<1K  ʋ^~NQiMm'}.u}hޮ/<T?Қ[UC?R9/1 0]K^~>Qin{_#UH7[yU?Ky cе%*Ma"RmŧI+P5/9R @ReׅGTzA>ڷRz},<k?|S44't\ D-;;6,#g~4.Bu/5]I◦߉yyF3-z[;}$³WY_N~"U5mї1 0bGnׄG![e_OLQNlvSS=S?I_j"өW0 0"7N?~(BeoLC?Cj^[jԩ?&.<tRR#S}קzPҚ[_*wnF `fZWavQu۩b^uMj?ԩ=r09  ,Yx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lYx  lA	 07ݩ(p ߼   -  2<  @    ex  ,  d      Y  2<  @    ex  ,  d      Y  2<  @    ex  ,  d      Y  2<  @    ex  ,  d      Y  2<  @    ex  ,  d      Y  2<  @    ex  ,  d      Y  2<  @    ex  ,  d      Y  2<  @    ex  ,  d      Y  2<  @    ex  ,  d      Y  2<  @    ex  ,  d      Y  2<  @    ex  ,  d      Y  2<  @    ex  ,  d      Y  2<  @    ex  ,  d      Y  2<  @    ex  ,  d      Y  2<  @    ex  ,  d      Y  2<  @    ex  ,  d      Y  2<  @    ex  ,  d      Y  2<  @    ex  ,  d      Y  2<  @    ex  ,  d      Y  2<  @    0UG    IENDB`PNG

   IHDR         ☨m   	pHYs    {Rk    IDATxyeuyobQq1h$NLc줓tmb3N:1Lv{k bE
AA@dRPAF*ϼ۫.1LUg?YY~y9[0}eL]yhh-6Z-}蛣jݗ}   ^Egg%FϏ}syFccxUs; mM5D=sFqDkv/
9mQug   <|hn~!I#ג>蝿W֜kem`3X U>|g>1_PHTg.v    DkvqY$|D#wep)X QQbp?Eqț5(.MY1gO   `.;*Z3[IHصƯD;  QY<K1ֲ;U=   60#IuZ|ѿ(:L= Cѿho?%Ȅf    Q,HR.ao}<κS ,a?|>ګ?%=̢}	   ?IjD33ם1dy `W9Z+wJzlc#   0B_=B&=_ݳg\wkg VڟhlPfUeO   `Yv!IgDeȇd 2F8uPIOޒbpI   a%C&bDE:c& ,޹ˢKIOӲgӳ   0z$,C/p臉` P}dGIO߲bxY٣   US&LCvٳQvg?`Y 0I˟Û͞   ~6$iysD~
X  j؏7֊?$mr;EyǷ'   02'I$M]{$QO+ `n:+ߐY{0ʻ!   +9g4\nZ Ɔ x
qII/򞫳   0)|W<$iZkKݜ4g Hݳ5ZKKI^7dO   `Tu>Mg4-1z1f?`dY 2Q-eQ>xc(   &Tպ76Df?`$Y 鵢-Xr   zhM{8,Dm>׉A' # l5Fk?$q   L+9g"4>w]Xa6G%_|   d(~sF$i[}GD9~4@: L}EqțJjUz  4Û%ۥH'=ʇ~4@* LGFk"I*~eTݜ=R   )7bufH֊3 ӥ߉>_Wɞ*    s~^"If`Y `jF_H]ϫZwkX   x~n"I~c/#ُXP 
5}KFRC   _I+x]n &^۟֒m0W|Q]=V    \UF~"I~; , 0r]*Q{Md   xz~t>S$I?1Ow LntNF*V<?{Ξ,    >C~.\E,ٳُW 8e{]?F*vnw]=Z    6[ȝQzE$uOO$ D)/?8$5S۳[٣   `mIb礟H[4 #wGqj1   P~{:E:~ĠFY `"KPHje;   `R<v]$I};"4 c\wkV2!=#k-    띳$EGwİ X+7?`PKwO-    󣪢{ҟHWwEO
 clO Hjcpq٣   `~oHW?(O
 clз?$5̢\rXh   XUh3Ib+8 }'   Ş/I?$=9K, 0^at>/.͞,    ){bgH~Eѿُ	" +3>?%5VK+    7mi$I?Ԓbl6 >?%5VGTUh   H7I+V</_b0h.N?I    M?$=bF~(1 #ofUkM𒚩za?{    	M?$=wFe6 F[wCt`L9_dO   4F_J?Ñ$=Ww~J& H]R3f   Vm'U/O?ˑ$P3[/g?&iY `d.X?%5RˢZ[X   ]Gkg:V(ׯ~LS HffIW(nX   +O̢Ick01O !^>%5в\{aT   Kgw$Iw^ُxR 9,}pKj%F   Ū*sIc[}<)O #e򇶤l)    ߎ~>G~nFè Ȩ#Z>%կ#   `bTnbH[Ǳ hA-~   fozl~#If~DcX `$lT2t    4opQ?ǶgZb8~D @.Z+_>%իQz   O?~$Izl~< @ޟ>%ի}蛣m'    Fg.AW(ׯ~B 97Z3-UQm;{    L.d$u̱ @rAoJȒbi   0uDC7X  OC-zA(   ZÛmω$Is?ex`Y  E~(ZSmf\sR(   z?+$G+~40, {ڇ-o?,   ݓޟ~^$Izb跳L1 ,5Z] ec   kE7I}L1 ,lJZߋ~   )1ݞ~~$I*;GGS jxњ&}Jڇen   4h,J?G$mo)]rX `Au>GWWʨ6ܓ=B    xsY$i(|o  𞫣5uy>+ʻ!    lQ~$I*z<0 Vf6Mo<3{|    }Qzyْ$MyŪWDُ Dͫ!   -P~qn~$I^	L ,>>`%m^/C    >~$I^_~0e, 0h-VuVQ    5u?gM4^8`X `"}Jڇ9    4aЉoI?si{f?" _~|i`i{4G̞    4zhM~$ISےpO)ay5*iZ(o8{l    07}%ZϠ$iJcGS }.U&4(W=2    GsCIҔ>ُ M~RiL?    &\UFwEIҴ6'S wA*    ,`{X$Mc?`
X `~hzE Ե}sDȞ    ,d)I=^1g?p [>D%=uʝZ6{\    S4ל`Y `^tO@ -(~3{T    soSIҔ;o L8 9}Jzfٓ   dU(|Iy$MQ^/(G  97}xJzz_c   1h.N?i @:'eu͹o    =~n%IӔ?c>Y Ye/N_{DY=%    5UOZ$MKߔ=` h҇W,f\="    QwDX4,j=٣	eF{Дf    #nxsgIY4:>{3, Ш%}`Jzl    6E􏤟gI4=/G> );룵d)ur=    ~{k$Mz>?=P hL;K_{FY=    37E۳Ϸ$iҫݒ=@ hLKJX(NX    `L>!K&Ug{& SA)ih,wN	    O~%I\L  4!ZۤJI[E͞    L~;!K&o˞L  4bpCRVG    (&ZvH?l {3a, Ј޹4^Uq    \rXٗ$Mj=Wey& >z)MuKG    so矁I6τ @#Z{,}@J[    L<Y9L&=0 l?ERֺ'q    `
o8Y$5\dw& j|^pAoc    )J?;Y ޅGi+v}V]=    &Vm٘$MLK(ӝ	b:_(M[3bxo    PhnF&IRК @m#ޞ>iwGo}    XK?#Iixc	bZ^>i}[#[   iV_L?+Ihp1S	bz}_$-`ύjmw>    DQ,f${Vet& j)\>ifQ;%   пs3Izg]8gX MgEiZ/ٷ<    <VUEg.gg4u?GӜ	bZ>i_]5    5#wEygh4uQ @-HҤWܨߖ}   ^s4IڇlgX >nfQ;%V   =i4 @-yY}   &z>>SqXsgX wEiRkֈa?6   M6њ]~&Ic7 RP&bz[    6[~&Ic̢L RCQfSoo    2NKfgT	 Qz}(   ZʵS Y ) r(MRog    P[IҸVfBX MĴl(6   fhs7I6Lh ji-1} JOd    Шm߈go4v`bZZKK$=og    S>~&I^:	aZZ34{2κ    E?~'I bZ4n۾}+   9ISdX a({g     'Ey$j h j89m06   QuGr4Y ) %{JZ۳Zwk-    jxY~
@  4 dCi\\:   ݓޟ~>'I bZ4u[    r
`I(eX a([^/`    =5NF) 4 dCiYȾm   `$tO3;I,  Ԓ=qwGoY    U@+_~n'I bZ4.|}D}   H^{rٝ$B h jXt("v   ̻$)9 4 dCi_*V   U_gIRf h jҨ9W#2V   ƾgy bZ4-1oʾM   `h3=IJ M @-P}   ($Z$)# 4 dCiT|7"*   ;o$)# 4 dCi+v{vTfߞ    0vQ3>IZ,  Ԓ=Qlpٷ&    'IBgX a(Zc~'   9$i! @S, PK0Fbpwm	    cZ[˟~'I bZ4Jmj2    L?󓤅 M @-P'7v   R}ϦIBdX a(Bʝ*Ⱦ   `k/g4Y ) %{JoE    X/3@I,  Ԓ=Am    ꬏bϗJ|fX a(eVx^Tɾ   `<6<P3 4 dC)d߂    05:wI? M @-Pʪs;o?    *պ[|AI,  Ԓ=ݞ÷g~    0u.K? M @-Phpٷ    L~;}^~F(IMgX a(-t#QUٷ    L5'JRY ) %{Jڲ|    ^?/ @S, PK0gr    @D]%ۦJRSY ) %{JUQo9    NH$5 bZ n]gn    G%,  Ԓ=wL    <L??& @S, PK0   QU/#JR|AS, PK0浙E1\sNm    <K5uy$ M @-PϺ_[    牒T' 4 dCi*|qTuٷ    	ֽQsEI,  Ԓ=jxo/    `3O$mi h j|=o-    `shEIڒ,  Ԓ=5awdZ    9;Q$ 4 dC}[    5t}w9$mn h jRu>+U}[    5TeH?o M @-Pjm[
    h@3GIڌ,  Ԓ=}o'    )"UH?wM M @-PjbEې};    \:Q65 4 dC91V    VUϧ?JҦdX a(խsofF    <3HIڔ,  Ԓ=Z->}    sEJdX a(թwΒ[    gdHIz,  Ԓ=-=L   `JN3IIz|fAS, PK0w}     jŮ?~.)IO bZ%u{O    ,WwK?' M @-P÷g:    B뷣egY ) %{J-_    `:.;*R( 4 dCis*y(    LoI?4 dCis\sR-    $,    IDAT|nY$p h jҦ9f.    3KI,  Ԓ=Mjvqw_}     #hnv)I bZ)N[    1ݓ"R bZtUq    uo>+S6fX a(=]ʾM    ?wi$m M @-Pz>bϾM    QoGgdX a(=UÛʾE    7LI @S, PK0gg    r^~)i @S, PK0%Fٷ    0&W)i @S, PK0ޗ>}k     㤪}6%Mo h jW6ܓ}k     cfxi盒7 4 dCmEm    ~)i: @S, PK0~bF    S[/H?4Y ) %{J?ಣo	    `uNIӗ bZ)*o	    `̕w^Eg+ 4 dC{o<3v     &DM?4]Y ) %{J|ײo    `7Z>%MO h jRkf(v     Lޗ)ij @S, PK0'Ym     Lj-Z] M @-PSZ[m     L)*i* @S, PK0t;ٷ     0GֲB%M~ h jՆ{o    `PI bZ}    S*bM?4Y ) %{j:+v{NT퇲/    `JY~.*i @S, PK0tڊK    "UoC{ lTfX akKv}$    L=G%Mn h j<0    QŞ/N?#4Y ) %{j*~eĠ}    S}I%Mf h jd%    L~/L?+4yY ) %{jzjڈr}    S祒&/ 4 dCMOϾ    mbL%MV h j.*/w    9~n*i @S, PK0t4K    ?T݇}SI bZ&~(ٗ:    cY~~*ir @S, PK07bue    8Ug}='UddX aɮOD    	sTI bZ&eGe_     O*bgJ,  Ԓ=5    F^J?O4Y ) %{jr|    iUQ,f M @-PY^    Iz$\UxgX alpٗ6    &6eH?[4Y ) %{j    8竒7 4 dCM^ʾ    6[Z} M @-PUyVe    E_笒3 4 dCMVg_     [Z[l~*i @S, PK0|Ǩ/i    ZVIc bZ&ɾ    j+)ZۤJ,  Ԓ=5!-v     &A査J,  Ԓ=5mJ,    IQ}EfJ,  Ԓ=5,k/e    Fu>篒& 4 dCcߝ}    4nxY篒' 4 dC/c    y>-g# 4 dCw#ߞ}	    ̛UǥJ,  Ԓ=5?-    ? }^~+i @S, PK0>"* `UQzlCkSyuQyu٣G  cA籒F? 4 dCoo}, `UUTP~Scp1ѿ蟿2zg~4zutO~gtx[((v)Z}]#su^:ߣ}~ϵs	ޗ>71łx   dQx~ M @-PYs^z ^Uq\ΈeyFԿg%ۦ66Q91:G#zm_  wΒRI# bZƳW9 `UeTnᚳwG߉IGbG%\:/   ZC{ M @-PcؒmzK T퇢\鹯s_Zc$-~_;%d -񛠲-%n h j6F+  mmߘ95)bDS/c8& P=tsfKJ,  Ԓ=5~})  #ztV/?{_|}fNSW+cx^ ~%f h j6)  #GD瓿MoT3>+:GV5|a (v{̿h jל} LO[K[ퟻlO  MF. 4 dCO>(ٗ, }D俌Ao5zLŞ/WBD} LgJ,  Ԓ=5>o
 0D俈~IԘ};ƟQ=ts 0ڇl; M @-Pc˾\ &w?4>W|}(:2 H+M4ZY ) %{j<x  @aw^W>KKӔ,$oʾ  &G9Nד4:Y ) %{j<*<R [U@.tt(v)NS̢|Wb]  ӿw<I# bZF῜} h.Nגms_]" KU(v{v M @-Pc/S WUQfhw8is*v{NNp7N ;ߣ$F h j=^1f_  #;s'ݤ&ja? պ[|뗤,  Ԓ=5K `_Proݚ} 1&)? 4 dCp wֿF+Ӥlv1鬹  ko bZFgޕ}y âs̢3)ozA	 0r6+eI M @-P/g_  o؋'Dg;9L&~b~ QKOO bZF `_?{/Lƥb勢wΒ:oa |v+&)/ 4 dCfVe_  ߞ:'~%K6t]U@] jRq,  Ԓ=5-.ֽٗ& ib{IT?GY} ֯SbgX aѫ{{/K Ueo:+~fsI\sʹo  6sw2I bZFgd_  â}߳ies_Q  `^&)' 4 dCVŪG ꡛFkXҴ>1  `ڇ%LgX aѪwΒK ˢMikcxyc `.t M @-P#Q5 |U~):G=J==Q_=9  ϠwIZ,  Ԓ=5:u `Te:>!]Jf|ma/{  ̋9\4 4 dCNOȾ 6OKT~gdO U{t-I bZFb澖
 `s'ߟ$5[g;$ 0q'i{ M @-PQ˾ \9eGEϫߛ$  [X, 4 dCFd_  WU1h%IƟ(^=  >߯$-L h jʯ} <Sߕ$%5utOˈ^+{ 2w+I bZ 1_9HF?of& -7G߫$ h jJnv6ܓ} Ds~ߑ$V  s5JҼgX a:N% L^+篌b3ߍ$v}_[=  6[h.N4Y ) %{*'d_ \rx+wN'4F.ޗ 0v:w4w
M @-Py=;ξ)Tyi{k}OGy `b; M @-Py& Fw	h3٣ `Ӕ(~e;y M @-Pyo  /t+$iQugO: ?wY M @-P9xDUe_~ (o8Lɮk G6N' 4 dC;gI L~3?>? 9M% 4 dC%4(o̾ 	6(V"GT̻j?=
 3ߗ$O h jZڇ5 &Tպ7Ij(:{, <^Uνd/Ij> 4 dC-|s_	 а'D:όwN  ?e @S, PK07uTߑ} ꬋ#IO̢ѹ Uqn$,  Ԓ=ux[% LEKq$% QӤ M @-P[/9 `T݇H>ৢ
 0gxWߏ$5 bZQm' \y'm$i*v}VB( >G M @-PW瓿} Fњ&Fj5u/?{ DIj, 4 dC-\K?} cZ6:G-}Fwڇ"2{ Sꬋֲߋ$5 bZ%FU<} chWe>#IP8 RuOz;fobZȾ qSwG5(]Faou_ T!IdX aip/5 `Ts;$-T}_7d_ `J!I @S, PK0tߒ Έba$i+V(;. _Y ) %{j%2 AUE%њ:EZc?-{" l؏oEC{};L,  Ԓ=5}de !n{$DG3 0!G'D=Sk˞#i^ @S, PK0<78}ٗ 0o?"Ib f+ם2jjҔeX as۳/1 `o8#wJglf <7o`}E翿HJ M @-P* _fH/\W Qyi/>4'٣ߢ6u M @-P̢ߖ} FԿW1wG7 G|htZI bZ~> FL}$:wIOqlTTU( Vu𦳢wΒ~g{ CxfX aݲ// `TnAoHGqſ  cm-_{{XI bZk// `Dw~;;H$;  `(,xt?.D.N4Y ) %{j~jK ÛύbM?Iw 3םWEk+ 4 dCOs _I7Iwey ZUg}o:W3=^n I h j/ʾ d%4]=`Z1}Qc DY ) %{/K H`I$iZm Dy1wQW	mZZs3S3vi,Zo23t9cgcgMrAr!"B!A.1(*McKDAN/}V%;<wkZٻY_;s= RY PVÐ0$IQ5M~忇G j37$IfǶ4ٲ~GY{`OY P, (aHyEV$)Y[J3f$Iz=iBW.aP ?YI}t2S" 5YƛVG$͏&4vum\Kޕ5^d@ !e?џ$IMip! \~FA}tw]W6.P}O1 * e=)kODR$i_>#;7%Ijk͎mie}^8`> RY PVÐII}U3Q {E$eJW(ߛǼ$, T U0I$fGkF? xb^1$I&4ݾ9:uvٸԙY~, T* *zR9I}QӤ= xj^7$Im:Mp᩿Yr`	Y P, (aH99I}9 `OkJa!Ixyix_ge.{N	6 T* *zRFJ$Ue v?	.$틚i#S?Hc~). _OI$FT=7D4}cm<1@xU,
 jd@ !esr$IbJ dY׭R$Ix__uH,9(` 1џ$IKѝOo PgO.j$-~?B~'d@ !Zg$IRӟ^ =̓E_1yV3ؑ&[L+`a{, v |?EF$i/ؖǽ4@yMMFt7(J_ -`@ !v0IԾ; 귧4D_9};4px:$u~P d:$IR&? uï[Ge}^8_~ oX P, (aHީo$IRvz7 3I׹Ln8._kߙ{8 T* *zg&$IjO|*}>4+HTMi}soZ|(V:3#  T* *zgr7?!IT+Rg3 {~55"I(S!  ϝ$i<pk qݔ+IqglY?6kM.L    IDAT/ Xx, T U0d׾#$Ij'_  k}-IRk-H+IޝJ, T U0dύ6H `Y4%It4޴zGNԙ?~J T* *zw]HF^ `~.{VIvfǶՏCRg3:  RY PVÐ==)5G$e4wRg3 ?JMJuM4ix_sh.an T* *zgg+ӑ$I5{R) g7yS3ؑ&^FWOs ~ џ$IӚ&W-=7ѷ$&4vMip'_:G>X P, (aȞOG$ao `Xr`ym%I{fǶ4ٲ>_uH,}V=`@ !{Sjџ$IڃvMg' X8zx쏾6H,N5/
 P Yl$IҞ4މK y_-&I߰&[UuʃSgfQLJe@YECvI$-_ G_eMiz44z?Rg' K T* *zw}/$I! X=;Ma&I5;ɖs?gI f@ !{Sjџ$Iڍ={K ,|O.Q7jTYM1= # * e==d$In6C $QwyBoS= X(, T U0dy|'#Ivuk 8Imh:Ix4px:$u?#|Be@ !gzOF$bw =Rӹ;j%v~忥gޜ:˞> M, T U0d7,90 $Iƿ hwD_uqM1=%s Je@YECvlI0hC_sZ'i>4鶫h4XwX<8uf(  W?H]H^v ˞}IڗM'i}soZOUy X P, (aȮlYH]hx	7 PުߞAIٱm	/Y<z^  좙EHhzwSgf U]vT(@M4Eit鲹??% u T* *zkz+~=S$IOU3MSY
-~iqE+g	 Je@YECvF*$)_sZzN|(oNMp᩿Yr`  W, (aȮ
$iJݏr/%|ؖ&[֧%~Q g@ !fzџ$Izk{ :G<ͯq`GlrG;,uY   RY PVÐsK<5M"I[f%  ;>SGiz+?NJE  <H' g.]}=J4޴:7I% _ T* *zGIo[/+ c,~FפjvlK-ũٟ2 X P, (aS|JyXӤީ<   'HWi=  <fǝџ$Iz|; 򣣯K)8MoQ>z+N Je@YEC\_D$I5'^V '4[Sw5M޽e;即#E 
 T* *zg;$I	 +?gPTjc;j_8dq94u 9 ^ T* *zFIaQw GߞRv4zem\Q/ Je@YECK?Is:5  cߊn:ۣPiכt;Rgf   <E?Hm2L_N 4¿Eǯi{kR7Β ] T* *zz':$I? &7_}JqglY,N5 P <N$ͣ&V6  {Wڧ5Çdiq<8 [[ !OlOD$ghC  r/9"JU[ti?[? W, T U0Mn,$I?S	 @Hӻ}5;(~4W:K}  RY PVÐ'0(5?Il (dR;5t/I3~?uz^w 0X P, (aOC$Ls> ?;z|mIWi[y_Tf ; * e=y|iHy9i ({쯤fp54ݾ97N(> " * e=y|KE$no _kVfǶ?Y! @[X P, (aK9o +?#M!^?88&G8 h1 * e=y|̓G$)4|y  *U?߸"z+NE @M, T U0䱺_YH_ 6o]NInߜƛVS!?!;  <'I_sZ  q:75?kvlUK;g3  < <D$)o `_ˊ?88&G8  `X P, (ac7mg!IRMnV  %恭Wp]sIsޗ'";  `Y P, (acM^g!IR@  t7i_uH,90 (Je@YEC~4E$U]ӽgoA  οd_0z^ wY P, (aȣV*$F/ @)oLiU3xhGo\g7uyI9 Y P, (aȣzw'!IR5=o 4ޙ7m2QWK̢3   <⿎$$Iɏ h^l:Iӟ^ל_OHO?  ' * e=yώ$$Iu{  ѥRm5;ɖix_shs  ` RY PVÐG7$IRLMYr`{  慥J̓JWip{S_ Je@YEC~OKi<$$I 0R+t44XwX<8uf v RY PVÐGN|M IR^y& ycf4sSZP5ӹ?4\;Rg , T U0;$Ii `>{i>ؖ&[֧%S͡{7 N T* *zB$4px[  M_O@4c_   * e=ys?Il:Ic^ jOMo Mwii[3(  x" T* *z]E$UοI n|Y{G?wW:K
  Je@YEC̢FA*'o /-g^͡    џ$Iu6Q B0ڸbf#M^9GwOxE  , T U0dN)HTe^ ?t7ipRo3n  , T U0d)HTes d?4px:$u>3?  D RY PVÐ=1$)Q/u=;  goMݏB  G, T U0dƯD
$Ud˗      i9S$0    @;X P, (a~OAj{K     z+_HT]W    h * e=/zWg IRu/H     RY PVÐog IRuVz     RY PVÐD$U     &7}-3$F^~   . T* *z_wSg IRU   v RY PVðzGdHTOq      O@l"   }, T U0]߉$I3?    c@ a0$z    RY PVðvK$I@q@   @X P, (aXuk?IirÅw?    d@ ao$I*   , T U0]O?I7     U[&$&YrP   @+Y P, (aXފ_>~Iir۷~    Je@YEÚOkKTM+>~   ^ T* *zlpD$I?~    Je@YEÚ/>~I{~    Je@YEÚLKTE[}    Je@YEÚM~|QKTE~   n T* *zl/IR/{   v RY PVðf$~   n T* *z֪{s^jKw?    f@ az+_}$UQ>    g@ a}$Ud˗}    Je@YEZG/IR$   , T U0裗$g7   , T U0;>zIׅ     裗$Mǩ{    RY PVðV7F$IozϏ|    `@ ao>zIZ    Je@YEZQ/%Ij}˗    Je@YEu?.IR~   P * e=k;.IR>O}    `@ a%%I     T* *zhp]t    5~/]7vu   @=, T U0c]7|^   @=, T U0Ӣ]7;   zX P, (aXɖ/E$Io|    a@ a&}+%Ij}o    5c$N|u   @=, T U0Qӻ?%IjwM:K~   P * e=s)5c$5w>    U RY PVð6c^}$靛|    b@ amz+_}$ɍ_	    _F$Io||    b@ amOKF/    |?F$Io;   X P, (aXGKg;   X P, (aXѕF$I7    Je@YEڌZ}$'^~   P * e=k3#$u|n   @], T U0_>rIx~   P * e=k3G.IRkv~   P * e=k3#$M    > T* *z֦}$m    IaK&7\~   P * e=-IRo;   X P, (aX0%Ij}'    Je@YEÚV6%Ij}o,    5ϣ[7_    Je@YEÚ$|    c@ aMg+%Ij}    5w-IRw|    c@ aM?}ܒ$gE   @}, T U0𢿌>nIZ_    5}cIqKz'&   > T* *zd㣏[=ew>     RY PVð&}ܒ$/    5$u='   > T* *zd[9;   X P, (aXG$In<    5$5{    d@ aMwn>nIZ]   :Y P, (aX=7D$Iy'=    u RY PVð&F$Iy`k}   @, T U0I]-IRk9   N T* *z֤?}ܒ$7    Je@YEÚ$ݦwo	   ?R, (aXE)5MqK7    TJe@YEj,9(%Ij}ӻ    ~Z7;   :Y P, (aX1/>jIZ|    d@ a-ǿ,%Ij}ӟ]   @, T U0EoūZ7[w>    u RY PVð>jIZo    Je@YEZNzCQK;   N T* *z֢}Ԓ$    裖$M6   N T* *z֢}Ԓ$]ׅ    Je@YEZO{KQK7    Je@YEZOkQKwo	    ~[QK~   P' * e=k_shQKo	    }gQKo    裖$5~   P' * e=k18}G-IRk+   N T* *zbpZt	    GG-IRk;|    d@ a-, H|    d@ a-} %IO      IҾ9>     RY PVð8%I/
      IҾ{ܯ    Je@YEZ}Ԓ$UQoū}    c@ a-, Ho{   X P, (aX $z)   > T* *zbE$IU?->     RY PVð $Icm3S    IDAT7W=   > T* *zbpG$IU?]>     RY PVðs}Ԓ$U?
    oZ*\{   X P, (aX}Ԓ$U𢏄    Je@YEZ׾#%I7    Je@YEZ}Ԓ$U[    ~{QKTE?~   P * e=k?Z*_n   @}, T U0Es}Ԓ$U    Je@YEZO{KQKTE7    Je@YEZ?裖$7    Je@YEZVvQKTE̓    Je@YEZ>OZ*j    Je@YEZNz}QKTG4uf    Je@YEZN|uQKTMe	    裖$~    b@ a-vA$I7V~   P * e=k]裖$ys   @], T U0EF$I_   X P, (aX%F$I48w?    U RY PVð3Rj$}$   * T* *z$M-IR.?:   . T* *z֤>nIh|թ>    u RY PVð&M$ƛׅ    Je@YEÚ4$%I-    Je@YEÚL1%I]ׅ    Je@YEÚL^qKTECw    Je@YEÚLovqKTG~   @], T U0K[j,}f   @=, T U0[j+w?     RY PVð&ω>nIw~    a@ aMמ}ܒ$USs~   P * e=k2-IR5}   @=, T U0G$I4    Je@YEÚ.]}ܒ$U~    a@ aM_-IR5\   @=, T U0p-IR5M~!    T* *zdp[jn:    T* *zdp{[jjI   @=, T U0Iۢ[zSgfQ   @, T U0I!-IRUuz~   @, T U0IG$IU;5?    u RY PVð&^}ܒ$UU    Je@YEÚt0%I96    T* *zVeɁ-IRU7   P * e=k&#$F~   P * e=k>rIi|g~    `@ amn>rIirÅw?    u RY PVð6ӟ~?%I׆    Je@YELn<%I=    T* *zf\zjYr`   @Y P, (aX5>rI{    Je@YEڌyBKTUU~   ~ T* *zfx_G$IU58?    g@ am,%I<   , T U0G$IU5    RY PVð63~?%Iuk    Je@YENycKTU[/   h? * e=k=%I}?   h? * e=k]#$F    RY PVð:GR3>vI{      5jD$IU    Je@YE5}$UU   h7 * e=k4vuKTU?~   n T* *zhrף]^rD   @Y P, (aXD$IU53?    f@ a=%%IM_   h7 * e=k4|yKTU{n   h7 * e=k4/]RgfQ     RY PVðF/iKT]ݣ_    , T U0wG$I?    ^ T* *z֨[]|=o     Je@YENzCKT]ï7     e@ aǽ4%Io     Je@YE*-90>zIj/ƿ    h- * e=k>zIj    RY PVðVӻD$IUt   h/ * e=k5裗$˞    , T U0s^7     d@ aF^}$UW      ~F$I5    N T* *zj?>zIktQo     Je@YEZ裗$׭    N T* *z֪w^7     d@ aǿ,%I      ZrPKTeeω    : T* *z֬<}$UW    > T* *zlz/IRu7     c@ a&[>~Ik?    > T* *zl$FO    > T* *zlw'E$I57     c@ a͆D$I5ݾ9    @X P, (aX>~IkKE     Je@YEÚ׾#%I9    @X P, (aXީo>~Iw     b@ aͺ'<%I     U[$ʆ,    * T* *z֮>	HT]k    . T* *znzџ$I5zE    v RY PVðv[	HT]Cw    h * e=k7޴:$&u    =, T U0貣?Iwk     p' IR    =, T U0]?$I"    @{X P, (aXާ~#$F99    @{X P, (aXF$U䦯    h * e=7(Q/3$ƿ    h * e=/Mqg IR}5Yw     `@ !-F$UYo     Je@YECKMHTe     T* *z_]<3$ʆ}$    @;X P, (a~iϢ?Il|թ     Je@YECK303$&\    , T U0d;7?Iyw     `@ !/$IIe    Y P, (a~3ȥ IRP^    `g=* e=3OA*|=     > * e=3OA*~    ,| T* *z2g5џ$IU6w      ]~t IRM^    ` RY PVÐ9s IR5    ` RY PVÐ9$I    Y P, (aȜɿ)HTm+-    f@ !sG(S$Q[    Je@YECvD$UK    ,l T* *zO$I焿    X, T U0-?Ilz    ,l T* *z?IlK    ,\ T* *z<s$ںZ[    Je@YEC_Aj~[[    Je@YEC;џ$Iն'D    X, T U0#9HTm~:-    e@ !$$I-    pY P, (aȣM]IHTe͎;    ,\ T* *zhE$U[c    `a RY PVÐG]yl'!IRNyc[    Je@YECmџ$I6XwX[    Je@YECџ$I6co    & * e=yމ$$Iuo    & * e=9KJi?Il}s[    Je@YECqgg!IRMs   ?{Uw~Ei&1I413$5mmBm;I&N]Mk5Lts
"DEDH/ "
 /br>˞up;y8g?x~gc V e=?$ۆ'D-    1 P TU2f}UXHmE-    1 P TU2䞦::},$I[     ` U *}rO>$uC/    X? jJ_>$u/    X? jJ_?>$ur{W=    z1 P TU2^9,}4$Ip=    Z1 P TU2-1}4$I+Y-    z1 P TU2ox[hHm~?    ` U *}rW8}4$IO    X/ jJ_ܻɅOOIm      @U/C_KIm9j-    z1 P TU2Oѐ$P=    0 P TU2>9$}<$I˿    X jJ_ܷNImro    ևZe җ!m$I6[    a V e}!IRo,    `} U *}r&$ۖ;o    ևZe җ!mtC      @2 PUː6xNIn_    X jJ_܏IM{    t* U|2}D$I,    `= U *}r׽)}D$I     * U>?}D$I[    ` V e?$I]7x    >  @U/C4}D$II=    3 P TU2GDi      @2 PUː{W)1$fW     * Uy`[>>&$u    X} jJ_<'ސ>&$ur~"O=    j3 P TU2M/;.}L$I~$    ` U *}o|JHuE=    j3 P TU2䁍^Kc"IRM      @2 PUː68c"IR>{    f V eȁYnKImko    VZe җ!f~e"IR'ekC    VZe җ!fGE{    e V eȁ\Q$Ư{    e V eȁ"IRMut=    2 P TU2"IR?y~=    2 P TU2 Ud+}\$I7    ,  @U/CKIIm(gW=    j2 P TU2ͮyuHuS.    `5 U *}r&IHu7>%    `5 U *}rgzHu0    `5 U *}r'LHu     * U9{Zb>2$u    $  @U/CGF<    VZe җ!gGF    VZe җ!g福$I]7      @2 PUː3~o$I]7    VZe җ!gxϥ$I]    VZe җ!gpw\$I6=      @U/C_HInxң    VZe җ!o~;F      @U/C'$I]7}s    VZe җ!orJIn~E      @2 PUː7z?MIn/      @U/Cؿ>6$u    : * U94˭[GG    VZe җ!fGG\{    a V eȡ^qbHu2    `u U *}rhё$_:    `u U *}rh/GGOއ      @U/C臕\$I]7|ߍ	    X jJ_WoJIn|     * U9tO9}|$I     * U9t<7}|$Io    X jJ_9OLInuk=    j0 P TU2OylH}~ &      @2 PUː
G^b>B$u     U *}RgGH    3 P TU2O!Inѳ     * U3doIu[>    g V eHٿ>B$bV:<&      @2 PUː:>B$u    d U *}RiσKH7    Q jJ_[|#c$IRMxQ=    @Ze җ!fW>F$u     * U7y$I]l~PM    @Ze җ!Fg>F$u	    1 P TU2y?>F$u߈	    1 P TU2ݻrQ$~NM    @Ze җ!mo<}$I     U *}ʓGI[~K     9 jJ_1>$IR      @U/C$IR      @U/Cyw\$I]7y    D U *}I}u      jJ_3I7K    0 P TU2;{8IwE    g V eH;>N$u#o    vZe җ!#$IRM    g V eH[#%IR>{    g V eH[Ͻ;}$I?     * UikzŋGJOއ    ,  @U/C$'?&&    `g U *}x    IDATAHI}7vM    2 P TU2/e1K+In    (  @U/C[${w=    2 P TU2N+In9zڽ+&    ` U *}>V$u?    s * UiotƯ$I7>o    vZe җ!$96&    ` U *}=[$I]7m     ; @2 PUː1%IR-      @U/C/H-Io	     jJ_l~;}$Iѫ    a V eђ$::&    `g U *}M>8}$I      @U/CN/In[    vZe җ!g$I78o    Ze җ!g>^$uU2&    ` U *}}bxI}K    l?  @U/Cѳ<}$Iu    l;  @U/C+ץ$I]    Ze җ!kvkGL7     @2 PUː5yM1Iot7     @2 PUː5zů$I7Oo    Ze җ!kYr>f$uo	    ^ jJ_lWoJ3In    l/  @U/C߾ס$I6x    l  @U/C=c&IR^o    Ze җ!o>f$u-&    ` U *}c&IRͮ='&    ` U *}3߼%}$I坟    > jJ_oO5In,c    = * UˎK5Ioto    Ze җ!;cJ5Io?	     jJ_2}$I^    = * U!To$I]    ma V eΙtYIwe<{o    3 P TU2dLxQI}    ОZe җ!;gI7Io?	    h @2 PUː3<累$I7     * UA{+e:L9In՛o    3 P TU2dg-n2}$Is?&    -  @U/Cv$I7:o    2 P TU2dg{rI}w    e V e$׽)&    -  @U/Cv؞JN[~7    M U *}7_>v$u	    h @2 PUː7)c'IR^o    1 P TU2d{rI}K    ЎZe җ!;oxcN_QM    @; jJ_90}$I    f * UX|eI}hM    @ jJ_dL?pJI}=&      @U/C2=9}$I{	    h @2 PUːɏI=Io~;o    0 P TU2$daL'IR-wݻ     U *}$'DM    @=  @U/Cr8%}$ImM    @=  @U/Cr=9}$Iϋ	    g V eHǤ$I7ܻo     U *}R$떓oʿ    b V eH+GPo     U *}5)#(IR}RM    @  @U/C=9}%I'    1 P TU2$kxcGP}7    u * U	sX)aJw]M    8d jJ_-1$<6&     U *}7Ec(IRjM    3 P TU2$o|P}7     @2 PUː?>$u	    8t jJ_ݻrQ$̿    8$ jJ_g/MEIo_	    84 jJ_eǧ$I7y      @U/CVHEIo      @U/CV?>$u      @U/CVrq$    g V e_Q8J}3	    8x jJ_JGIor    g V eq$zKM    3 P TU2duq$[_	    8x jJ_"}$%I~,&     U *}Z8/}$%I~+&     U *}Z&o#)IRM    c V ej${OM    1 P TU2dyx)eXJwAsX]    3 P TU2d,!},%Iɏ	    8p jJ_5IKIoƧ    8  @U/CVg$I7    g V e$IݷGo    Ze җ!+YS)YhJwYzw      @U/CV▏$I7:    c V ej})IRM.    c V ej?$I77     @2 PUː4<gGS[qCM    1 P TU2dE9 }<%I}D]    2 P TU2du?$F7     @2 PUː5}	)IRM.     * UY]$zKM    3 P TU2duO;)IR-ݻ    Ze җ!mukJ}xM    3 P TU2dͯ0}D%I}-OM    3 P TU2dM.ٛ>$uo    Ze җ!mt#*IR-n2&     U *}>2}L%Iٸlux]    }3 P TU2d-LJ}S.&     U *}f;;}L%I[KM    }3 P TU2dM.zfJ}*&     U *}F>$uo    Ze җ!kਿQ|>$rY    {e V ezX|#*IR<2&     U *}fW>$ug    ;  @U/C'$I7m7     @2 PUː0|>$urղ{W]    = U *}&v?,_OWIox     @2 PUː1U    {2 P TU2d}L/;>}\%I'    ܓZe җ!c|o$Iݷo     @2 PUː1x>$i>-[    og V ezY~#+IRO    og V ez$&=3&    k * UY/w$f{mM    3 P TU2dN|J}˯~.&     U *}^<"}l%Iq?    W * UY?>>$uU*&     U *}~fW>$uω	    + jJ_ɛ>$u3      @U/CԟK[Io9F    o1 P TU2dux)qJ}Ó~&.    . jJ_H]Io|ޓo     @2 PUː4+IR>    o1 P TU2d=}RJ}[	      @U/CğJ]I\1    ` v eȚڽ,w$I7:w     jJ_H_Iorɞ       @U/CǤ$I7[o     . UY_W$    zg V e+IJ)/w   @ * UYo˯}>}%Iy     @2 PUː6$f<-&    Ze җ!m?LaIoqo    U *}F/'#,I28w   @ * UYogW)yK}     @2 PUːc,IRM.     @2 PUː7X_aM    3  @U/C$IݷYv    ze V e1$I?     @2 PUːLGYw   N U *}7]>ʒ$uSo   ^ U *}?/}%Iŗ	    ze V ef7GY$-epw    =2 P TU2d3#,IJ)WJ]    #  @U/C6_LgIor    =2 P TU2ds?y~8K}O%&    Ze җ!c/}%I{W]      @U/C6ǾsX$    7 jJ_l+eHiIo|     @2 PUːͲ'GZ]7   @o * U,>Ғ$u	    zc V ef\{#-I28w   @O * U,?#-IJ)     @2 PUː!Lc-IRM.ٛ    t @2 PUː3{Z    ' jJ_lNHkIo9z     jJ_l~+}%IR)exߋ    za V e<o$I*L.     jJ_l7oImIoѳo   ^ U *}zshK};?     @2 PUː4OG[$R?2.    Ze җ!i>ڒ$2>    U *}|O)ExK}>?.    Ze җ!kqۧ[[o    U *}fW>ޒ$i>-[    ` U *}&o-IJ)    ` U *}[$R&o    ` U *}>0}%I'Ͽ    6Ze җ!mOqIo9l    l2  @U/C6G\$R'>*.    d jJ_l$I~'.    d jJ_l	'}%IR)e   Mf V eȆ۽뮿wX$e[    ` U *}_>$i,|o]     * U|K$I*<2.    T jJ_l>$2}1w   2 P TU2dq~$I6w   2 P TU2?>$iU>$.    D jJ_aW$I*     @2 PUː>L_G]$! >#.    D jJ_axϧ$I*̮='.    D jJ_tK][~    ` U *}ҏHwITJw   1 P TU2>$2>w   Mc V eH?<1}%IR)e     @2 PUː~_.IJ)ۮ    6Ze җ!ٽ,$I*    ` U *}җoKyITJ     @2 PUːL/}VKR}'     @2 PUː<2}%IR)e   Mb V eH_>2}%IbV    `S U *}ҟ7$I*^+w   0 P TU2?k^>$2do]    ) * Ug$I*?sq]    ) * U%>$i_!   &0 P TU2CG^l>$2    l   @U/CU/I    l  @U/C4/IJ)O!.     jJ_i|G_$R[_)[w     @2 PUː>O|TKrm     * U]e9=}%IR)eƧ    k @2 PUː~ox[KRï    ֝Ze җ!^$I7     @2 PUː~<2}%I?26    Xg jJ_kp#JY.ITJ   :3 P TU2o;nL$IR)ezŋ   uf V eHf׼:$Iŗ    ֙Ze җ!}\G@$k(c'6    XW jJ_m_H$IFg=!6    XW jJ_tKITJ^   2 P TU2J$IR)eqw   2 P TU2/N$IҾ28a   :2 P TU29OL$IF?>6    XG jJ_0|O?$iw    #  @U/Cڽ,?
$2{o   5d V e?GA$k6.[G    ` U *}>K(H^     @2 PUyd I7xwm    n * Ua(eL$IR)e~;o   uc V eiqǍ鏃$ItP>46    X' jJ_f׼:q$Io   ub V eirI06    X' jJ_𗆧| I7[o   ub V eQ2?$}lyp}    & * U_*$I   0 P TU2^GB$or     @2 PUn|	I'      @U/C቏J$$I]   p/<_wO) @2 PU]e9=$I3   P??\̯,w0χe җ!uO5$I\{   fpwiGɅO/,y~]uj  @U/C릗F    IDATXH>    6ڳO2evͫg=0 P TU2nt鏅$Irֻ    6?^>L8oٸ㯋{a v eG\?$it}    hp#'%{rx|w_+ jJ_powܘhHM.    V.ӎ(^f}Y~;}~; ] *}½Iȏ  fCGO-([-e}wtY 5 @U/C7$i5ZnZv    e/sTWX7]rлF ] *}½鏆$I[Ó~&>   08et䒽e~e9z[>u @2 PUQ2?$i7?->   G?N;⮟JG/lYw @2 PU?$ikύ   ʞGg|IYzm)Eلb 5 @U/C/+_xH-   `~YWX7]8)Hzc v ee|It'?&>   {Gg=L.[]pא jJ_p_/C$ݭ}b}    VFqg|GrYv @2 PU]4%IZ8/>   /{+Ó]>>oarmuxs jJ_p~k#"I	~P}   f(kL8omkpzg V egzQ鏈$I[S   9?:	er2ܖڻi * UGD$ݭEό   X?gWvD\2o(5m> @2 PU9[rHͯ{S}   sX2>Iw(?TrJ_ U *}Yqcc"I}lyp}   (eǕM2v~, @2 PUW?&$n   58{Ǖ%{rp[k7<w jJ_@P$iu   UFqF;WROWJ @2 PUԟOL$Iݚ-   }HeXf~yYRWPD3̟ U *}:RfGE$o9Z  C68etK_7UپZe җ!HT$I?   80c^F?L.[]P[_I64z U *}GE$ݭk}   xwiGɅO/([-eL4~Ϳɟ U *}GE$ݭ   toaexcه^V|<QƯ?gs jJ_p /GE$ݽlux   ГyGλI.~F{g V edܞH5z/   jpÿGe~eukkV}?I7}n{g V ejߏ$Iң  !egL.|z]}FYzm)ek֬~;;g V ej2Hi~  2<e|nUW<m@?ߝ3 P TU25:It28a7  *2:	ero(W洡;  @U/C8P|{%IҊo~#   ]FQ&ooa7oImSG㟁 U *}XqC##IϏ  λ,(P8A+XA_DhEQs@8BUD+2MN:Ŷt
D4miCC:75kZf{?ﵞ\Oxߝʘ$E4gT?ufimX`"T]x  DCi*un?3 ~@5$I$ٻ}RszQ_RG2xcoes @. (%zJSi| HQ!9|G$IgZ+l)j]ogs @. (%zJS~E2 |$|G$IV;pXTlz"Y0-˿=z  DCiJOktb I$IinϤΚamJE/UE/c# rq @)PjGnl {$I$mڑoOeE~JkR779   = B툟$I$v{9ny*DQ	fTkps @. (%zJSyǣ? `*|G$I4:|]j,7.9`ck_5/  JT3џ g$I*ڜR}>yg&amJE/A0px  DCi)? xI$IC_ȷS{]_$}H;W R4߻, P_;$I᪶p8cZ9'u-OE?j:,  Jtj_57 0ooF$IAO>Z+\cTJ#ÿQ 8 a(M?t -t]#H$If)'ކ)?@  Jt-xcJE  ?h<?I$I3ܬRw?OIGnLۊ#
σ 8 a(MSF> 'Z I$gZ+婨=G` è \ PJ0[g BkŗwI$IWj۩Iݻ/HF؆όQ 8 a(M| -t:|G$I4fIeE-)?f Ծjn  Jt Rj_'H$IO7_wׯJ]PBk29   =i7{T6EB -=A$I+|Wo떧T|9   =20 0Xګ$IQnWKMKH5KSo?& 3? rq @)P*SۇDB zׅ$I4{T_Oj.{ݒR @I# rq @)P*S	 [Q;m{$ITo_{h_RugԨ \ PJ0T;џ ?'H$I^7iHsRwTm^ֺssks @. (%zJe+} 3 йA$IKMKH5KSoڔ"ze# rq @)P*[玳?# `E46k=A$IfIeEʿۊ^!?Ϸ 8 a(m <'H$IPmީq~)k:PA>F=  RT\  OkŗI$i8Tm^́Ѽ3ps @. (%zJ[Jz l5{$IKΚamJE#y_ 8 a(uџ n+6|O$I4{T_Oj.?W/J&v^AѼrs @. (%zJ9j_wD ls'H$Iөp}v[R^lW>;G=  R h>:|O$IvTo)+떧blC*0e?>OG=  R m\'H$I/kn~{SRg۰6^Jkg3vs @. (%zJ*8s vI$hwIS{]*N3zE# rq @)PU?' `+u IѨvO9M5̘9	ã rq @)PUGN Vt<'|O$IRWj,wOu^*6=j<9   =\՗F lEQ{:9|W$I7gT?۰6^uJߍ# rq @)PWmER VOx_ Ih.~̻RJNLoK׉^i^k-~x  DC)gGn h]9+|O$I`V[wj_j떧l
0'JL  JRګER Vt>|O$IR|J%n)KŦ'WU9?9   =5X' lMj+H$i[/'5/LYz֦T7Sʪs @. (%zJ9џ s?+H$Վ|{j.WKV;-o# =/>Y [ѹ=A$Iy-;5/VIuSQ&zy~y/>  R=FV Vcv
$I4j.5Z0SųD lؼ=ߌQ 8 a(u?+ `ǽ'|W$Ivk/g;7z֦TH &alȈ \ PJ0r8?+ `Z++H$jG}/۫U`Xu[o  JRRi [1wIp8cZ9'u-OEL  JR?=vk lMjp ITj.5Z:k7A d#  Rԏ7i <Ể$IRk/g;7z֦T> fPH  DC L[O	$I|$W/'Rq]$  Rԏ_}G lCilN$IҰeRk]<9 P5o  JR_S*6F^ 6ԏ}A$imj,7.9 u,S 0	 8 a(wy кỂ$IRhwML3?{얔^>pU& d RԯZW~% 5Ể$IRO=4uׯJ]^ ur @> (%zJqD^ :vI~T;G'rN[S ׽O  DC_|]Jn' lC#|_$I*[mkScɾufimXf0:w& 8 a(ޓwFb 6tnZ I4rj^7s멛|  rr;) d R:7 PHS I_}GjgzQ=``?*ݔ q @)Pg? Q?
$Iƫ8rN[ѫ LZo  JR?Sџ +/HldԺYtOEj ֺ  JR+^x43 Ể$IxwI'~ʿ~UJV Y5/7W  DCu֞ RR$IRu-;5oO߷"v-zk7X  DCߵ. ؎$IpV;/ @ | PJ0]_ ]/H!hRg۰6^e ` OZ  DC +ZwI48%OՋRw ~ 8 a(D h$Ip8cZ9'u[Rk,z=R;s9   =}џ g_ IfyI/R11zW;p7^  DCi&jFj v/HqE P-E/9 q @)Pjab	 W$IRkk TJx>}  JL۰6s u?$5/l R<p9   =sIџ 	$IRk] *e~~ߵ9  R4S5y lOj3H *6 \ PJ0fQ? ;<$un:!z J~]s @. (%zJ3Yџ $IRyv ҹ]s @. (%zJ3YoDr vg]wIԿ/E  Kwm 8 a(d> ;$IR=u *}6 \ PJ0f ;^uX IWou *rv9   =mΫRjף?; `;zO/~g$I}d Һwm 8 a(tFv 3H>4kzU *l7^9   =C?; `Z+3H1z i,7^s @. (%zJ3]?; `z3HՏ~g S?}o6 \ PJ0f) Sv؏$)o3z ʩo6 \ PJ0"m' vowI3z ʩm9   =:|- vwIb @t^ 8 a(E_Fz t۩vI֕7 Gw rq @)PwDz $4X I *]/ \ PJ0*6= ;йA$km ]/ \ PJ0sa @x>yU IԽoEz p~r @. (%zJQ.B LB$)OD P)Nr @. (%zJQO Ǉ$)OE *rvr @. (%zJac Cx46kA$kk TNkſ8 a(E]* &~⯆$\E?R @47^/ \ PJ0"k_{h' LBIT)^) r7^/ \ PJ0"kGџ  0	$\?R @ԏ7^/ \ PJ0"-xSJE P_O I_/F P9{z)  R]F $V$Ik>:z 7^/ \ PJ0zJg LB;I4:kE P)E]/ 8 a(E׼௢?C `~.|w$IӫwW	 3  JRtE? ֿ$iz/<J @!}s @. (%zJPџ" 0	n	$I4{JE/z Jsa \ PJ0?E `Gt I_79   =Auџ" 0I˿;H8+ TNkŗx<  R4Տ{O LR$ij5/l
 Ӽo^ rq @)Pfsџ# 0Ej-~$I} TN  JҠԽ     IDAT֥;H׹ *~̻x<  R4(џ# 0IwI4z> @7^/ 8 a(J%F dT[c$I\ ]  J4U)kџ$ 0Io} Iv= 3ſzE  DCi>xM'	 LRwIǼ;zm Of  DCij_}`'	 LVj9|$Iۯy Ν焿ze  DCij{џ$ 0?H׺++ TN#x2  R4H6^' &I:2 @.o^ rq @)PzY UvIz1 @4_o^ rq @)P:	 >?HmW4^ r'fW \ PJ0YY S{A$m½W Q?9   =AM?' WCHW8k T=y2  R46i SZA$& @xm=  R4un:1 $Ize& @6  J <Ϣ?M `!|$I/ˢW }+xm=  R4{K	 LQwI^ r:k9   =A?O `
z?H-xcz  Ծj^; \ PJ0-'G Տo!I68W 72s @. (%zJZsџ' 0EU$isK? @%5Nym=  R4 جICsѫ TR툟  J 7o	 åCHJn^ zz46{w^[ 8 a(r[OD)jx|!I7{  *xw^ 8 a(re STԟIcsw#$I^	   J W;џ( 08|$iku  *sＶ rq @)PgL)BQ}  TRʯv  DCivZg
 LUjGH4u[ @%5x;m \ PJ0723 ygIFY;\*  Xo[m \ PJ0oLi>t]!I(V?k  TVmᏅv  DCi*[ P_{$IVsٟG  PMFs[m \ PJ0mG 4V	#$I7 @%n; \ PJ0Ti=sĿCKH4J1z J~w^ 8 a(C#*S ~ү$Ls^R@%un:!vs @. (%zJR Ǉ$J5j]^ 8 a(K5 PԟIcsw%$IZ *yΟ~  DCiXj^Wџ+ 0MI.!I(x gvzm?  R4,Վ|{
 LSw	IF} !o  J0U<`' LGjH.!IR *hk9   =as)џ, 0M)|$5Ds {^; 8 a(Sc SMcv
'$IjO~:k9   =apO (7	I +k9   =aq]g LS疓w	IX7TO= TV󜏄q  DCijx\g LSڔj.|$j ?c1׎s @. (%zJVG @	>OHTY@u46o^; 8 a([oX }}B{' *x^ 8 a(cD @	OHTjCy 5  J0־O (}}B<O; TZ{& rq @)Pg %Lcsv)$IB[O~Z.r @. (%zJXץmG @	3(|$
?@5N^ 8 a(k %t-'$IǼ;Iʫo& rq @)P evO$s)EjkY;\  DCiXk (}Ba{9 TZ[{M>  R4} \46gBal)u9 TZ环ǿt΀\ PJ0WG @Iͳ?SH45q 9o& rq @)PZ+gG @I?]SH48k7_ 8 a(s%F @YE~.|$i=s_+ W?=o& rq @)P얊֦ (}Q{$ICTwG? P}Ek9   =a %gؼׄ$KI< o rq @)PZcg d_$K'n~떇Z  DCiث/ Ƞ{$IP툟~`$98r @. (%zJUxO Ƞ~/$z>dHhw_S 8 a(UΚџ2 A%{$I^wO6 _~5  JRjO ȡ]Ko-$Ij9^74]~M-  RTjHJE9 BAyѧj 	o5  JRU=yg dP<BmԽ F?;k9   =Ծ ȤyGwI?RLHh]~M=  RTK s 2>t]n!IҠZO4 k9   =4o:O Ȥ~I9 `f_S 8 a(UWG @&5[H4(Վ"yPԞ
5  JRjr' mao	/$IZW~%eѽ_ 8 a(UI _H46~`d?*r @. (%zJj.?Y cW$V?O2 5  JR]Y 5$I_ ̩+￦ rq @)PZ͋?Y =)|ǐ$)^|<9릱y{ V  DCjՎ|{g dX;$I =uo \ PJ0Xџ6 QI"}A3 #sy￦ rq @)PbN'/|ǐ$i&-;^'	Z9;|s @. (%zJU?:k1$IZ+iG; rq @)PbJێ^{$I3ҬS܃ѯ/ _	4  JRU> ȬsI;$I3Q0Shr9   =Z ȭcHF=E 0r\\  DCՏ $c7 ̼֊/* rq @)PlvJŋG @fET;$I}rvs #q  8 a(UΚџ8 ˿gHԗf~j`$)~P  JRkgџ8 Ŧ'ؼׄ$yGY Ių* rq @)PrE @.9 |א$)wGn~b`$u:7|P  JR=zSg A~@T'V
 #u?* rq @)PzG @Ệ$I[j]@s @. (%zJUd  IJE?런(Ej!|P  JR国K*D @]!IR:7m\(O  DCiu^ Iil$IӭvN]~R`dun?#|P  J(ԼSџ: G͋&|ߐ$iHk]ʓ rq @)Pjeq x46U;$ISnkR1!)XoN,9   =Qџ; G͋>oH4Zc
 Mc	'  R4*W }TXG!IҤ {@r @. (%zJRD @.B!Idk] F^Sw 8 a(LswO5 }TԞN^wH푊MOF? 0Z6~/P  J(սO 5$_ Տ@r @. (%zJTOG @R;$IfL؆ F^|!%~7P  J(U[wJE }־Cmպ⟣J  { \ PJ0FE @u۩~O$"? ֕we 8 a(ZG ~f!IҖ/O$ vn9   =Q~PR_
=$I-xS*E ^gy 8 a(\vNŦ'?} `t_{Ho<.i ]ћw 8 a(b5K?} `4P!IRwmG? k_@s @. (%zJX?{46wC4u$I ~@ʟ rq @)Pj Һs$itkO! ao	?  R4u: fHx.)|$`vNn~
P<@ \ PJ0F_ԾC4z5/t ls; rq @)PG3 fRǼ;|$NMŋG M \ PJ0F3E  `uy!I^ [Q?'  R4ʵW= 8C;$R [(ϥY;
O  DCik  ̰=IRS>pU lEKw-  R4=  0H*[OG?u 6V|9|WPr @. (%zJ^  0ӺT?IR-xS*jOEt 64N}A 8 a(z M]DT: my{_  DCiԫ-"z  "|$Ui~ >t] \ PJ0Cȍѣ  Plz2OỈ$=n lGy; rq @)P֊/E  HwI׾' ؁ɿ39   =%PQ  D)z~ү#~/O  k'~'zoPs @. (%zJ\E  O6{M>"I:+) v{߷=  R͵;2z  H꣣0 `ZA 8 a(is3z  zT?};$ixj" &F#  Ro.== @Ls^"Ij!?t P4 rq @)PKun;=z$  WHΝgG?Y $u(|w \ PJ0RIH  :~{I<ѯ 0K439   =%@L] @k؜W&v[Sx. ~̻wL  DCI/nyX  @{a{$ik>xM LA46k=B3 rq @)Pk^  Nn"I.~ )B3 rq @)P˫z  GSmIR|3?RQD?M 5/=B3 rq @)P+>t}h  DwIRl~&碟$ `jG=| \ PJ0ZWsh  HO':5) xn}. 8 a(տ  X/E4un=5 sỄf6  R۸.z<  Mil;$ij^ (y	l  DCI[}  Ǆ(~{d fEj)4 DCI[7 0~4|O$!oNsF?9 @	ׄ  JѬSc# 0EkS$?}u=: Jj_sp^ 8 a(i۵o86zD  ]ilỊ$)svJ;Ί~f _f<  Rm8# P;H! AQ65| \ PJ0fc P͋>HԼS
 Isw \ PJ0:7/ S
W$Iۊ~U LB19   =%m  +jOڑ?HW蟟` ""C19   =%9L  X5il{$iJ)~3 d{Cq9   =%mG
 `u:/)|o$Mځ{M P- 8 a(i5P  @Y{$i#uv Ak(,  RI4wT4_ +<$i=uE AQ{:%~PX  DCIsY Fj,7|w$mٻL- @57}C9   =%MG  :/E9un?3  y'w \ PJ04Rk,zd  CxT;GwIRStB  SKCw(4  RY{~  HћSmkwI.~ >=rCΡ  J&_܏E `t-7IWϏ~
 Z9'|P|  DCIoKz  Lg҉{:zjN'  !(<  R]wq  PcI_}t fH1ѵ&r @. (%zJZe=6 !վj^.#IosY# ANA49   =%MAoHۊ j]O$U9J=8C{"  R׽ H?HR嚿g޷"z 3hmJc^h r @. (%zJz  ^75DN#IUCGOw  @gỈ'  RW;	  Ij9_= ,|ۓ JW P#e54տ{i D'~	(z' \ PJ04~4z|  U@UIE) ~Sh|    IDATD rq @)P4G*ZG P $iJ5/ E	K4X9   =%MΝgG JG |2|nΩ jh~ 8 a(i5 TIQ֥q$i gsa DwD rq @)PRߜ k_{h#ITmީ  >hr @. (%zJ*WӢ PA $isޓ {/  Rr5~ *}qu#IQ5/q w)  JJ6{Tm% @Eu {M#I3WKG0 0Z++  J׹Q TXڂ7<4տ `[b΢ 8 a(|S=J m'ՎGYs# `ų,  J24kTh8 *xT?wI]SCS*Q wl  DCIyj^=N P6?}$)W~<u>z C7n  DCIy Vj.?|,?_{*z Cx_ca49   =%ejNx Hsw IFJO i_T 8 a()_f% rĿIdk,7/z| C~⯆2  JU?=# A{.Jc߅$i{Mj^4&  SU<{į4  J{ wڑ?IzEJ `9(| \ PJ0ַ%z  #=?|huS궣G$ 0Ǽ+~ \ PJ0oME `Tu۩ygw"I{ T@oFÑ rq @)PR- rrHU^u Ȧ;#  R5/dh HפQ?Ig엊G? bF 8 a()J]/  h|$|?TjG=u$z {]GÓ rq @)PRyvx ج(Rw$Ikr
 M< R?/  /۰6Տyw$5Nym'z UVR=  J]S rZj^]IV;s׹ 	}4\9   =%E# `w_j/Ij!]R= Ѽ;+  RU?WG 6cR3IjCg Smw!U  DCIm dk ^٬R󜏤 0^ir @. (%zJo_3  ;Tlz"5I`8wSۢG 0߉4|9   =%oKE I[j5|S}/w= Qiځ{F  J_G SfGIǼ+ue ` t<'|?p \ PJ0~*z  LYR_
ߥ$	\RQD X{3  R7sU]7  Swmh5c&q3YƩPcF#$2bљdFo@-4 *ʾ4[ /MuC}ϻ󛺷as}{ϧO4UyS}{<n:6eKN%: nּߗ49 * (%zJ}3z  l!EԔ Tߙ49 * (%zJ:a (-_ws;V9sH7D W}ߟ49 * (%zJMŦ# SA>߱$twLo}:=2  ߡ49 * (%zJ/9  )4픔3Y/x) UgmF; T DCIWM} @ә-ik[pxJvT  z,e_N Uq @)P6| 0#γɂ\4=SixŎ6V P =%n:z  ̨)!4eKwM)> Tscis @U PJ04-yz) tE{}]<?e{9LjBqK;NO)D?  )y & 8 a(i>2z  ̞^+W}:=Lj뢟f 1u8Υf 8 a(ikѣ `ifej[T}ޞz~!n~r fVQl{߿Ԍ P =%Ŕ?yg 3|=yԚ}{Tz+2}0 0] 8 a()+z  ˟~}RugRT>G `uOL  R[=  gSSk&xۥ῕W-O3D?~  aZs  Rw=  j'_:u-%}MyoRimc PGĿQ9 * (%zJsǣG @hkѧ=Mڦ:QYG
 v$Ԩ P =%6on*6==  jxԿbſI/פqK>b O 8 a()K (4|=s)[w951'+w- P5]N8Uq @)PRl7 `+4|;)uߒ'7g~  FNћLׇשy9 * (%zJoUѣ `(_R԰:G^_$koLȣ iS#s @U PJ0_E  ?&/]ڇWGiR;;{7  Nƿ9 * (%zJ/[K* @#KG7lۣT:Gv]ϛ^- @cScs @U PJ0T=  B>?~7f]<?%! ,A57T DCI_G  gO՛X|C{/[kꞼG:`T "{f4 T DCIi#	 `僔?|M_o')MI~=X: >޳ P =%է ^uix׷S1ިW֢SU_>py*u f{  R` ފMkM)Rj͛>psRᾔ<_  - P =%իUˣ  b؟O:+?:1kSM~? hΉTs @U PJ0To  hoy׮NOMK{o|C;61'eKޖZǩw秏^GMŦǼ 4\QߘY Uq @)PRwQh `6۩p>tuqZ_{P]4g}.uO9ߦ!"e;e_-%e+9ߤO>z~!XkIûM7p?D  X;WG  JWOE&  ,a7&6xӿ]?ݚipa_bo߿\<y͟q?s   [%l;w P =%հysSimx    (e@5|ߪ Uq @)PR=_8z<    Yw P =%ճa    &Ĝ]' T DCImG    6w;VW  J[縏E(    VL	߱jr @U PJ0T&K3D)    ҿda~Uc  Rz    tS;w P =%ջ4G*    -23 T DCIop7G    iWw P =%տU     hxETo  JF    To  JFiW     /)Ԛ.| Uq @)P҈թ|<zd    Y9~ Uq @)PԿtQ    h; T DCIStה    #? P =%V[N[     Sw  RѪ}ȇ    s77r @U PJ04z_=     4  Rѫ{ʟG.    4|} P =%`wHG    0:/~  RѬwW    0u7Ĝ] P =%fْz    tO#|O*0;s Rmfe    PԚ}Tza  JFa    Qs @U PJ04"z    cHj1|7*x  JFIc    b9 * (%zJMųE2    `'Skkҋ 8 a(i?G    0zr>Tz P =%~ץL8    nLٞ?^* T DCIͨq    4X 8 a(e    03-5|*\vT DCIi    4Pڃ+ 8 a(9xJE=    &S߻+ 8 a(Y:+z    2XsLSڒ P =%5k    @SEj[Sڒ P =%5CWG6    4 T DCIͫs'G    0aj@S P =%59)    M߈uJ[  Rf=    0ʿ 8 a(-xu*6==    4X}dS P =%5w=    Q3l{ 8 a(e{11    6m Uq @)PR_    FŠ}ה% T DCI.[S_    JV4m Uq @)PR||    ꮟlLi[s @U PJ0bJE=    _o.S*  Rhx    ^+eKǔ 8 a(i<j"z    5ԿlT6 T DCI{߉y    @ݍ)MKl  JƧU    jɂݥTE  JƫF=    &3){K P =%W#~;z    5ѻwRU9 * (%zJ\=    `GSkkRU9 * (%zJ:+?=    `> Uq @)Px6|    ݒZۅ)*s @U PJ04u    s(s @U PJ04^=   Y6ݤ49 * (%zJ:'~"z    S& Uq @)P71go}    ap7 8 a(i~Ϣ     0-oNR P =%yۥۣG!    0W.GJ3  R$uOL(    fPy&e{)|)d  JԚ77    =49 * (%zJTo}:z    3xZSR P =%iR    Tl, 8 a(I?{'G"    P|ӿ{f# T DCIz9)    TY Uq @)P^Xݣ"    P]7J  R$x.    @^j]49 * (%zJҏ9#ѣ    (=49 * (%zJҋ5    lb-~}Q P =%j򡔊"zD    [{gRD  JR<#zD    [!xUjM	-J9 * (%zJK>p<zL    [SWr @U PJ0kp	c    G P =%jRG%    2Ɣ-5|(E 8 a(I`ѣ    xsGs @U PJ0W*[Δq	    ;Sk{D): T DCIڒVDK    Et=|(! T DCIڒ%oMEwS    ^`xC.9 * (%zJҖֿda    ~hK>|o(% T DCIҲEbcc    H)/+|g() T DCIښg}.zl   +6>2;BN9 * (%zJV5o?q{   9Bf9 * (%zJ9cѣ    swRs @U PJ0mixw'    ~	Ju Uq @)PLȣG(    y_Ju Uq @)PM߈    06oM; 8 a(IZ_9    ̰"O>  R$1
    ׿]T P =%LץbQ
    ULKٞ?  R$w    XoYPҠ (%zJRMwFS    h=)E#KC8 Ĝ(Ieq
    ol{wH4'q @);EIWDT    hޅ'|'J٢]Y >%__    ȟ/J[Q[ zSPzrX   VsQ*[O. RZ>%=    m3=4je  (OEI%G+    bڔ4jǗq @)Ti_g    0r:=i{K8 a>%'Ix   24uGq @)(|(JL4    #WK?c tN(I3Q{R,    ^ϓFc tRPW,    cxҨ7я2 Rz/	4Se_MEZ    YכxҨ7Ǚq @)4uOQ    9;	O8  (ep%CQf9)q    2ݝԄ&KiЍ~i ox ~0J>C)y   Z(&e?H0 ('ysÇ$tGFO\    IMsoQtd  IDATG?4 Jk(I3]䭩<=r    wuRя5 G^p٨wG.    )ZOltRZh0 (s$J[.    ';:a$Ѧa PZڃÇ$V~7z   zRnNjbETM8 WGI}3z   )6>Vя7 Ԛ>$%i6_ʊ    3SIMsO8 J{w٬    0WZя8 JxYmb?rm   9:~'5F?4 *ѻl!)I]_Ni؏    PA7+;8͛'r @%\?(%)ˢG0    TwwoRkǜr @549a)Iצb}S    *3䭉97Gr @e>>,%)αG`    D=ܤ7ǝr @e})|XJRT[O    PZ?ߵIoTt~i( TfpSy{*G1    lG٤qs俉~i0 TJwU=   `KׅؤqGs @G)IaMI/    uAj4&n~i0 Tw)IW| a/z   _ |&KҟL({ >qW,    EIyswjҸ;E?4 *SB[Sʟ;z   *:Ϥl{i5|Gs @)Iu_   @uOdMe?RG?4 *7|*IuhfeH   _"|&[3 PH|e$e{9'2    RkgҸ?r]p ^CTP=G2    <<_4ny6Y 1|A*Iuip2    L2i_,gL8 `d>L%e=c   1׿k2i,?ˬq ]@=/2    c,_wKj-|MLXf fL~&M.2!I?lxѣ   1T&SǤqmxc1 ֧Ç$եlO!z4   0f'inL_<z0F 0\>X%NuOlh   `;8|'&s ̸$թFf    @ؚZS>LײߒR? ̸$O    4XћLƹ%Gc 3oOT   @Mퟢw`XȞ! ̊eK$լFg    A/iߢGc "lLůTTL    4Sk/i[S*6>=S 5s?p%fuN   @C֦lwＤqwc &|2>t%n=   u~]4-9GOƘ fUT=ߐg    YsIzU}1 YgSkÇ$խʏTc   4Wl7!z$0 0zTVDh    FLؚZݖW5Fp ;SkﷄaI]vJGi    FDz"e+~%)-|= 17>%/N   A,Is~Ti );CXX/EOi    jwcI\ODx <M`(KR.8zL   PS[NaIצbc P4~0KR˖3c   ݒZv_I\c~ B<Zv	ΒTǺ1   @՟[I\_O)F ׻-Iump74    uPs*I?hu xyڇ$~PKR    ]]</z,r @-^a-Ia?zT   dkk)ѣ^ jw^[Z=   0|Zڴ) / 1:~pKR. zR   0l7$=`ѣ^ j%_j-z]:-y[*&Ej    fAݘ|?=9 v7>%u"zT   0Ah.JeL*" R甿TW=   Ao`?zCh- Z;Sg$ձ;G5    3jEIҏ4XsLh- >qgj-z]P~Q   @Z$=_;=`8 &k0%uOdJE=   @)[𝓤񑔆 [ =^W   0ڊυ$=_|<z<Vs @>$ղ;'5    jM+~$鹲ߒ=`8 `$gSv/|Icپ?=}%   w%I/hNiѣ FFZ/I5sTѣ   пtq^I.8-z4@) )թp Ia=   B5+SkbNNI=4 ]gɉ?$n!_=   x{Ο$=_) 07L_q)I?^Rz2zL   2t-%|$=2 YG|(HR{)1   )6ܟ}?|=R i`:ֻG4    /PdOIzw=r y+@HR횘=   o39 3 л|I$լl7Gh   S$yۧEO1 h޵ɯ̉>R굢G4   wD~֓( 4J伹 T   `,/]ls8 43?H$NW    ce3-Oʟ3z,p @#&~k$զysK3   XwqjE5ש|<z,q @c7e/ER䭩x   hj<z$U{_4DU h<[GN$եR?    7e#|$}wLk	 7a#Iuz   RGxGeLëGq pDIC+    QLH^OE  0Vkפ~.0%5]}nX   yEwcj}4͛zO)F gS?$)l7M]:    Q?K#>ƹ_H j (R$}/)z*   a/ufRXsRex pm);?$)qX    [#I
HZixѓ j {Ѽ49XU/EOc   P{߅sl;MFO- H𒤠7=   jw?qqHG Ԟ x~w1Lf;WFOb   ]</~#Y>oOgLa9 1|>?$i~s=   jjEF;F?0R K)_slj-9Ir*0   @mVZs6X41'uOTl/ч  ^I,xM$R>+    ~ɩ5o}4uÔ?zCc# lGR甿L_q)i<ѣ    𮳦<zO#5αkyh nM?&k(I3]ڃ.   @]N;g6]?*qFq  h9S$5yۧgF\   Y5y`݌:uOLʟ#QFr  %׮IHf-%叭    bx9?HM+[Կtq*sh4 P|c{Ѽ'?D%겥هG-   slip))GƂ Xy67{O$UXk1   0#|T]wK+bGƎ AթsJ^a+IU9vw   @eߓz|>2  fAސzV,Ie
   P%.i.P]</(?  fYԻz>7d$mcKES   ҆\ZvߵHR[R=RGx  {S%}GܒMI    lxE~_zޝԿ%"~tW  j<:g]j-{W$bFO   6ZT&l{R?JO~j*6~Tm  jjݩ9oS\Z-%^=2   K_c[t>é{ʟoAUn~48 gளSũs); I([򶔯7zL   br]ǩR#Ꞽ=Sϥwo_<;{Sw4D?,p  MõkRRsgSI8@Ҭ-ٔO>=     <%)    IENDB`PNG

   IHDR         =2   	pHYs    {Rk  IDATxwChb<Gh$FRLxcI1k5{tw]:RP*YY@\,ҋ]da~ܜ;Hp~̻s|c0L:a````````:ܒ{9[AUxS }ZDW+iz%XEm"K/tkoNMz32kBT!XJ}\@XnBKB*y2|1p\H$&ylHB_Ix^Jg&2SiɅˇ%4CsBrOHNW}mj"vFc8wB;zUxDcB;Mm!. >#ߚT)}{_ qj0i&ڻg\V [T܋D;koKX`4;{eoPלI|4gAX~?/~,Z2*[`\f3~.E&;w,TnSrHu8+8Tv-1azcvt-mz\h )	j(3v3tے4ąϏ-4N+d>:ΐ_|9A'=w,So<3Snz	nyd9^
Ng!=Jj>S(e9#޺2`@7LoNBk'AV xx%88׻£֝	s Rr.@g;-
Nv [pS[hqn4Q(vK-dKlx ^ў5`*9`nF@Bϋ!\FMDbSY#j6QQhaO0qB*DlpS	BG$>JPY/Dewܽ$-ڷ$bOoS~unc*#[8B|_#&)f** X3/3:Z6Jh\bcQ  ڂ_pq}S	2u-:<7^%Έ[U,Q_VwWRB^*_נlD{B|vdis7 nA]WCt$F4_tN4q'>P1ZS:ޠ49x<&>")|LyoJxVgد{d^ܦORd"8B-#B?+y9BqņS!/8G!7IgE
.8G!46.8G!td 莲SE9yW7G$$Ѡ;F[jDB ݱz\D^pPD@wW#!;jò/sy9BKAw#{"٢.8G!4O]pPDR#?eEz\I]tAEz1{tWS/;ɋj{NuKhک;E5vF`u8A/4n{fB.G7&/<G( 4޺t#莿y9Bq	7"/<G!?WB]xPChw=`V篒#6NG&6R[Sx)J]|P@hQQ56aNnN]|PChl`V Gm`[и9^ pBΥ;)j,$ PChq00FB&&|8^h97:pAw#/+TRaT%/6`4Jhw`vQz^	`kzS9M >#n*jh>K4Zh|0aΨߐGG6?D>A/4.ѝpk)`pB+Gx)H6#ڛ$=JzmY/G;Awͳ#j;cۈ{fPh|choi
 A|ꄡ_35>y{S|8D{ QZY9ynX;e!>Aݫ3+|0p<rt|p=@mZ6i' UК\b~켷|8&6,kƅ֌p޼\yvE]{IT2B{3fsN٘3PrQ},BϏ	D`3vyAGE9Bڷ &\^fޡ˧#;>t /03/yL /q#y2yޛNi6I%@geo펻 
t6Jn2?+VD@gY/ V%xLh|jdV/Xϒ+u|-Ŀ)&q Ȅ^&JcLhLU2Jk%X5t&޿Ο51)R689@:nN/42P^sz9t~?;ЦL?;Ar9	!7ȅS>ݠ_V;Aw~?TChnG0	?KZx>u ITh{$	]Ib
-^:/- ?謐0;,;P[iP qݬ߁i9M=i
ZCg-A@*ZB2%wm*UBC6EM^h\aG5_:#$pB4Bܷ@/sAk7LӰ{^иؔ#
vs|Ѯ#BUGu☖䷒}4L=Px[w`{,Lh-۷mh`,qܠӍ
]uXW"r]Z뇭¬aXǦ2Bӫ s[o+`[r>LT	w=zm5Jp3N~H!q7X3HgOCZטmA2*4'0_F43-t6\2$pe'TxMȌK_o_ڠg4`TO >Mg9	]TIQzK5dT!p~Bˣtfm
ZK%CL|hf4,޿! ?N4B\'C;KQaգG툙,K5xF]⿁GF*'r<=ŏ%7+oAOR1xdaêU [GY@|N$7 qFI~}4t'%+_>aF%z c'LHk@ۚ0)4/MF%ׄ1`dtD{7׼VЈ;irw\l泌; wڊ;NxFHI)MrJ!7QEl}/?B#e1"n㙨9'pfEr.x <G	+[XEmp~K/TfrFe`iOBi\U
0B3FB3FB3FB3FB3FB3FB3FB3FB3FB3FB3`|ی    IENDB`{
  "api_version": 1,
  "layout": {
    "logo": "yandex-browser-50x50.png",
    "color": "#ffffff",
    "show_title": true
  }
}PNG

   IHDR  h  p   )ñs   	pHYs    {Rk    IDATxyfu}@#\cƸ nIg$$eƩTŊFGb%1$*nYUq(6(EeZdnys~S}Q@{;y^9<OL%      BMs      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h      h":iipiJy*OT<0SRK~  n\wLؒí<p{;gϮao?~3̵~LVYHqJŢ=?Ѥ׿R^   Wf-IբRygOW/s_^ǎf7U4Իé<T,^#Ks?  `X5$iMO?ܗ3÷+SS`vipѹ   0ok?$WL	oL?gѪ*eu4;
WbA񥶷h4l   wK>u$Etįޅ~uL_@L*6XҸd4   S3qI;-hfyTyMobiZ_Os   i.@咔WξeH#ƍcoܳ6uzG*V}#   >l-'u~W"1&{S91\q@!3   FwNܕǿ>yzJ~d9TScg^oDi+Wo  4g3uIjD+LϾ$n[wa'M@Q/Iƻr?  YF۳nƴ٩w?%Mh޶'F&cM~  @3{d.Ijg_I0Ͱ%MP^   @:{e/IkAip)i@3+\}Ho$i~u}?%    ZmK3yIjbq]q5v;R猷eƑ&ΉoLuX    ҝg]/IMsRi]73X074uN>4&^   0W-g}/Im龩Q)Ugbwm*W:74mU캳)    ZxW*W |IjrߐߘA5.@*fM!MjS~'s_   `,Tz*=;}IjtE46k@3T	sʛSۚr    ceT,yVՇCj@SSkF\g  y2Rh%-';6JmӪڴ.9\𺧾%սm/	   0ֆ7@R35UcMZ3(E&=   \yX IjMGhQڢMU='fŕ&<   _gԚ<+nDjF4Ugs_PIO3'r_   `ugԦz~0a?5YcƻSy+%Mɇ5e   &hg̒TD~7UThFOœ4:C;ͽ  tRo~V Im\Tm75Qmb/eI>μ>ܗ   o	gԪVFܔQMcR1G/YT,    ?ro*W@TixץI3^$:Ǿ"۾    <76>CVx4hzka$VSܗ   yQ*,AZբ=3Rh*_IG$՛g,    ;nx)$#MM@SU{_BH<ⅩtwK   k
Ժf4ޥ is]   Qשw/HR+ֳ'k3Rs*{N!ǥ    +nԺw^<MU?ᒞlitї   `9$e˞F_7ϦbfAO4K    `՛ץrՁ$o1zhJŒge$Kzo+o\   O I-<e*fȷS|\IS6O}    w/!$eu>Rtc=^*_[=O{   BX@3ϮM?lpa   чGHR_|E(ɶߐ   o~.!Ikiv4osOz+;   `uo[Զʣ^'i@3zT,/'OTn   \զSԶ:O؎fIԄ:')'i   辯ɞԶWl@ӻ௳$MαHu1~   ~f!Ik4hw\?Y҄WToo.   %ij9$~́zT|AO4OCS   7A{0$hY>́sɑ&ji   |,G,Y$M=ޯ6krVO4-+\<  	P=|[*W4$i=uּ&aMUnͤM    v΋ShT˛1t{oO4/_4'   `><ن$mjɳhM̂i}T׻}1    &T]޹~!IEj5I&~?Q/   vS~!IEqQ?xiTw߭    O<#_CY}pJ~@SRWҤV~R]~   <RdgTOhzMZjހ
   o>#$-\Tu4wb^?hi"[Ow.=   vTDQE1Mwg`lfA~]z   a/uNzSIn~_NUg4G3RW.'8   ??/$-hgYRzg3'8   ,~6"IE+hF~+3{d Iɷ4=   n\yXI*ZP3t~WNʣ_]w   u$T4rRtvߐp$U8 Uݹ;O    snIc^D7hz$%MT+v	   `NUߚ?79s7Tݭ89?(ibY;   DN$ifnGg`I\/   ̋~~"IEs3Д&oj.    hQ$hjNU4W@	s¿M_   =#^<E6	7t4	L>	   `^_E{e?WuN>tܘ%d o>𵹾G   w"Ilm6?>&g   e?_vm)Oys/{|   GSyįf?gauy4ՖS1 ƹ8j4_F    aF^E{f?oau5Ge8YsH}   @e3\$hX+@SZß~    ^5JO5ً$so@Smן7E{=kv    zRyHtsھ@	4=:^    ѝ4rڎ43$Ʊ9q   ]~#IEφrtStV:CJ2     uNg2T4rՁ)Uhw9ƭr޼.    !_~6#IE4K4-+]y   [?|F7~h3ƩuF    4Ng?C󣁦D*/ qwow    h؝}g5Tds+y<ƥ_Ҡ   hobl$̂T~_,ƠrtO{   6TdltW~Gfw/q   xϽ#$MipՊhßIm9m    ZnIQ/~#IEzgjۃQ   Vݳv>ˑ"Ήoفfx%Ϗx4}   @s$n~)O4kxam{   vvS?בɁ{{?(qb   Vf*lGF.Ɂ<?(}O   V\"$o8'bԶ:ǽ2սm9a    ڭRG/~8Uuf@RZOV   qPo^ÞG75zHj[o߬7.    d/e?"o{75Ԧz+   8}}$:'S׽g@R[9$~f   `ţ\uPI*>uݛh$";   0Fw_ρ$izZS׼I-    ̿HjfAJhz7=? y    2u{U I*橺ur79?f0RT5   oJυ$^_Hm/ۘ2<X    IDATrߓ    LΖ4=U~w:7UFjjo^   `2{5χ$㪇nM`&   hՃLŢIR1U:{*VHM<ũ.7   xK!Y$sVcXFjT3{Ѻs{    ԟ:;$$MM#^ަ%`&տ|q    ~LT,3$sPȷgmŜFjJSߒR5}   O_gGT@Ӏ#5rro{    ΠLc^I@#T[}   1}$Ind~2    ;%IRhTT德    `G9׳)IRh-+U}[   N<3-Ig%'    ߟlI]@so4侗    `Խ<%Ϙ$4헪}   nݳ֟:ږFSs?    0z_&I*v"&gޞ   9Rw6rAϜ$4ʕOo    `ols'I*v0&_}    <=IRh4q    IT,/$ &c/Muok    ϡ$h49,H    6ΚCGI3gԿCo    2LJg@<e?    @?KIRh4F}5     ΦT|A)I4_    d2ϧ$x4:_Ұ>    TTToJ7   @fƻRdU44M   @CXJ@`   f~s+I*~Fitu   0{ĴW4mֿY   @C{o+I*4ʣMJ"y    .7e?ǒ@ifA2x    nxϲ$M|FR   @U|h,IFcQyRݒG;    -Qm_d}%ijb3h,}?   hy~%ijb3Шo   BSysoI4juKuh    #qI4ju[>g8    m6ꃳsI4jmOq    =kuI4jgKv   0&y{3/Ii2Ш_g6    c޼.K~%ijb2ШuuN>4jg6    cϾ$MML{r   `T~$I@Vտ|Q.=~   Dr)^QW%^A/x)rpQ%45*ӓL2i&&uȤ'0	LzBzO&I}>ezxI|k}qXff?$I$I4n86hM[Stg$I$I&a~&0{4,I$I)hM)E&;sY$I$ISTͿZ͂k/|U*ڏGdI$I$MQE^15,hGDcI$I$Ma+
Z˂Z)E,$I$I46~#ZɂE=t]$I$I7mE=&W$I$IJ#~+hMjhT$I$I[^ٛߙbAC-n:1zJ$I$I߯wߙbACʨ$I$ITHߝaAC:5zJ$I$IO+?_π4),h9sV$I$Izfޙ5wh@k"XP=ސR=g%I$Igh@k"XPO$I$Is7wߥƳKO(ǫ$I$Io9%>h5foF^=W%I$I{Հd4T$I$IڠF8nh5;"٣T$I$Iz'Qj,B/'zJ$I$IU);6H49*I$I$mt~ɂ0O$I$I~/:h5!G}(zvJ$I$I߷ƱzsLn$I$IҦiK=&r>zdJ$I$IՇ߻FR^GKI$I$i6ξoZaAC=*%I$IRp\j*)sR$I$I*H>h5\="%I$IR{84T՟KEGI$I$:K~jςJ<+z.J$I$I48U{43Q$I$IZfACfoF$I$IR*e7R]YPɟ$I$IRHݣ7~hՖ噻U*;zJ$I$I!q3t@#J(I$I$;t@,h(ǂmS'I$I$6z⎔2HucAC)sfE>I$I$&hՎ\{Wdܓ$I$IjQqЪ6g$I$ITӾ~ojłMۏgN$I$IUEhj/xiЪ6eg$I$IT9hՆL{74E9I$I$?65G8I$I$9hՂDgIi4o$I$IR+>/Z,h$+=$I$IF!>hS~{F$I$IZϊ5,hx=$I$IF{=ʂכ$I$IKܭV^5E2I$I${@+O4̣$I$IȊݓ[4lUKg$I$Iz':haxߞ$I$I^`'Lٜ-V,h(+]$I$ID;V,h`"A/znI$I$IћS6{{?U)6X}g$I$I4Q{?U)6H{Rʳy%I$I$MTGn[40kXаA͏U$I$ID=c@24ۦX$I$I&Ѫ)Y= `AzOb$I$I&JXа~nF'I$I$iE] `Az}Ϣg$I$I4u@U:葛$I$I4o9%NHeyu$I$I$MOE:~/JeA{IH$I$I5RY𜺇z,$I$Iaڻ>~hƂ4Q$I$I$MeX:)9$I4ݍ<'JUצwfpݲԿԿpcO\;ñO#4%Iޝ:ϟG3)ߏ;//>4o^>cTOF$i9sw~y=!*j_%ITRx1ipѩ)?%K9L`3sk7:kݒ?Ni_/u7F\5^.I$is`A3jTk$IR0]7z=7Sg߷N?2]g]^9ҙ͜UKsR$IҳWyp3,hxF3yI$=O|c;NK=Wzsfo~k[ⷧIg~E$Ij>6 mj4<ݜ-R#ITF4zvgs.`j)Ym<u~K{ix7ǟ$IF@0kX40zH$5葛`Ҕ!ul_wL_6?TZ$I*{Gc@kiF]=o$I*N;Hw_w}2eI($IRi86)=k$Iʩ͘wg;,c&L{W?Y:jI*z O$I&o58wMdpqsF$i4}{g/?kQٛ?sfI4o9%MłkE$IRs2I4n<av$Iξo?[M{#IA#?u}$wzYyeSʳ?ƒ$IS@,hXgVXP|$IzΊSix7R~Rg?C|M>~+a?$I7şBY0;ѣE$+wO__[D\텯N^RQDї$Izf7^0Ɔ\=W$IUiU)?gvsөS~T<@IUObAC|EI44#9[1K;[5$VUY	H/ipAD$Mc(:M~&-nh?G$))e7?#fA3;<y"IѪ)?KBQ8NtE_'I4u6͔W=G$ITy0/'ulJ3+#L$7/?fA3foF=G$IҤo/G?e7?@:l\, o$IYeA3ź/zH	l怙cj/|UyMKN_EI4%/;6xB$IR{*<0uxw꠽kSE$IeVtWR],a=?$IR=t}--6|u啩$I*~Z̂fJ)znHVS2k)wH=~>¬池$I[~,/X{!,MipӉ)E_iI4au~06,yO$Ix򮔯!e_~I9szK	jxgA,hâ$Ij@.Kc?D#W=|C_wI4	E_7@kYLN/KE6z\HVix7S~n1gT~H׿b֗͔-9!I꺘.EW`Zw{m\4$iS{? bA3eF_=&$IR*F3;=|$Iӿ~Złft{g|$IuǦξo? `)?K證~ZHU<yw(<cA3E[|$I5h3\x~EKN~lH=w1@yYL9[bѳA$6=%~H4z^4S#sA$5Z2u´w}ߦ$I]g;/@9YL	"'IUy0OÄ4$i}_oh='));3A$UU;,oHNقm-@YYLOJ)(#S{ׇ?jD*:OD?}$IRM}+@YYLGIT{fl~ ixυя!ITF_~VZʂfµ|Ӵ$i2+:O|3n΋R~ܔFǒ$IY~!gbA3&I&bW-I텯?o =}XPJ$ըQ3pn$i7z=ڻX޶"Q%IjRM~$Ƃf|$IԿp:_yK$ՠ)>`+~KMRg߷/f,yO*֬~IFVKXL[X_$,@#.<i&IKXLF?%Ilx%τ+	0o4ǚ$I
lpg  	5g$Iݔc(LLόg%I~'wyeyh}$u*ߋ~Kht[~I;EYLD?%I҆V>)UY|"2'I*no	Âf[$IPOG!)3%ixG$II3oT~KlWş!4E~яBITa3? i̈́g$IZբ$I^в4N~KX}oK}ث߉~DJ
в(M)Ϣ$9rJjs3+h?$I%7zΔ<ndA39z".Ia?}1e7?3 <ⷧ{D?5%IRIOݟ99w{mȂfrn<>.I"{4uj/.))I^`EwuyvꟿK^s>I1oTD?%I5zMg4u/~Jm4bri-b}j͂fBt}8zHjpq)sj4ǩ$Iz5'|d& 6̈́\sxL$Ib3w`2,6:'*IReoI7EH/$T$iA7D `SRH$k\z'}jWET	=7$ImUgR"V~-Q+Id1_8zH4>s@(=2+IR3+4zo}KR@bAt7Kǋ$ISγR{ş 0{4G$IS~WRJ_?ǁT'49DIwNNټm &D?%IME{c,hGW}?40K~Kޘ|s{6MÍ9z$I4}k
 n~*KT{cnK떭[+~HMzs$i*Fwg 1o$I-Y{J]^?k4,hlfk/I*l4L?~ /Iûϋ~JK3{
iaA`;Έc$MO~{^F]$4~O-z~͂lҠ=$Iy_=ZTypWc.~۞s !45sI$I*hM#;|4E{7ޒ)I[s?0=`AP}$Mo4HE觸$i3ҤiٛD$Ie7})OsIR葛`ҔaW*|dMuxwx$iS? M]K%IڠƜ;7ux iY4P~y)IVRO{I;寣쒤Vdm+-c;3 M<zJ4\$FzIǻ$)~{{c.ka^%|6d5`A03&d$Ig%|LٛE?%IU7CRo_W.esE ǂaz'1+IDֿlqhI.~K|oQJ_?s f5M9,zJ4qV~m90ڻ6~K6xvZ7?uߩkg@`4S/zK4Q{~m>Eg;R]$=_~=xu_OYvjiY4 $Iѣ7. ӦwHj/    IDATGnJKSb]1*M+>=%Io *?ѣ@7Ƈ R-Ido΁=|LՇDOIixéۏ?hY4ܭR$5H??H-𞋢'$M{cf쪃1?HĂ!7zK4|r0zڻvU;x.\4ѿ`a̗$o^ 5Y򞔆y7Gß ^=pU9@F7z^3OBTtw>ڋN,h+S*FgI[]:{%|=2$4Կlqǩ[S6{g2 Y4@F$IjnEz~<|8&zrHR&@`A K>;H.
 oJE!I$ {40ZumyBF6)E,`t}xԴyvꟿKuS ZfASs?#IUdz*@&InWI:W m(I6He	  sL.(*x 6%1I6p ^^oe$UYf~oW?hM$I67lg8 Fߋ-&"_\4OO⷇? hMI6~g`<0zH4zԿb;O-cfo5,hjg$Iڰ `6ije-k fՋMy$I$ɔgFRsJJ[+[ ==xuFfg[g7 -LđT7lBXՂmS<$5) Tbx˩cGRyԿwi Ҥ}$A_mY],k?J|o"6?sG M:ϙ}&$z6 .H	*K;NsS *dASSO>'IT5|fcp!cH҆gOo߂`ʍ,hjhOHgo)e ƂmۢǑgj4HGnJKSbu_U6w ̪裔$I(Rg{g6 :"XRl'HIi_ ,hjwgV$պGk 흢ǒ4U#ixR~]^  deASC뎊>oITۊޚ^]&lFOd1 dASCœwG$Imi_ Kgw4G(ٍ eAS3^}$$\[k 1%5ɻcS~R_M=lXLE$ImݯNm=WtWwKݣ>ڻ&, ,hjƧ$Izw;|NPo~i5MT7уW{o ̪?yvQNUs4 ׿h%ž7fzٛdN59@lݿJV4Ԕ;wWs @X45>ITyj9@sA*FLzAS &MN$I3\y`?4,hjd &I~A/w@wAI{c YXK$ժg wF27 V-XŜ-R귣ύ$է~'m?hmEO4MQE4Néۏ  ZeAS}$V/j|{1<k|UU{c63 Â&z裥$Ii4L>=Ѻe̵GϥN-l FF7%IMN
 L9[ѪM~ȍ9 Ҥ}E?%IM%|60Y: ~/<+9u}; T:3$IhxE41Fu_Uri-  )Mt}[U=^Tuɻ˘|d&! @,hjw>JTFS *F;Uޘ
 =_(+IR-4Z2zV֌>wҧR{7 a,hj`xǙg[I+GR6sY򞔊"zi} `db]Iϙ>_}z*x78 Yɂ&X{Ͼ$oWe G{OEwu57 Hʂ&XwÒ$7ObSixy{R{3  	/gdI|g2 Shicp2聫RS? YOgAlpñfIBsQ<`zVMޘW  Z?4 !-IRh>>nOX7{  `Ai)zgkI*GS6oTFXˊ|]z'}jW @6,h%@). f8 z,7#7ʥ)_CyQ? lBY$IqEjy 3ڻX*45z4蔯|+)M? lX^I 3!MjE{ixޘ], 0F4q7}F$)I>?J_=17 ~Mc$I!5)[m,;ƽ7f4~?1  &-SGyIB\}H,g1T׊5-#ޟ/	y (4A:}$)Βb x69^UeyM &cAwD%I
iĝ޼<1{{)g  @T4Af~]i0 <>oߥF;I+|d*3  JY\t9}Ij^gwa Xޘۆo ΂&՛/IR=|C^WmH @,hJ$gk?glwKI>:=k  eAhn$IQ>`CwzY*G1 VcYc$U聫g0 l^{c  HMDߑITy_	    YMX_g$I3    	 [N#$Ҋ}7|   d5bAC{2I*    "a?LJ3   `V}XTOEߑITiEg0   @V#4[d$U/   @V34{2I*    YXTnd$UZ{7_   f,h*6{2I*kح    !\}W&IRe//|   d5dASx]$I]   ՐM;H=$I5g_   jȂB}U&IRe2|   d5eAS1+$>{   P~$Iޱ    YMYT2I*h   ՔM7/+$FO>w   5e$U#.   @Vc4*>}_&IR%&|   d5fASy[Te$URgw^   YeASo+$2|   d5fASa.$F\>w   H?/$W>w   H~W$I
    YYTdĒ$MC>w   oEߗIT~<e    YYT^2L=t]   "ڇ$I*G\   ,h0gF;3IJ/?gV   U4h/z]}$I;s    k 
t2I*s    k 
t;e$߰[]   ,h*_D_ITzGo	    YCXT ?+wf$;'\   !,h*пlq$I׿`a   N3$z   5M^}g&IRu_   GߙITz*|   daAS:LrS6w   5MnRQD_ITj{g.   氠)Y{vwf$\   A,hJg$I*G\   A,hJ=7$I*ܹ3    k;3IJ?    YXД,?o$I*~'|   dbAS9wf$^g    YXД;3IJh   5M}g&IR"|   dbASgF_ITjڇ-   @04e2LRZ>o   )f$-   @04%+G$I*5[   a,hJy$Iֿhy   5Ml}g&IRgK   ,4%j;3IJw_\   a,hJY;3IJw\   a,hJY;3IJ{o\   a,hJDߙITz1|   dcAS	3$:{%|   dcASEߙITz텯    YXД(?s;3Iʭ(R6g   5M͏6$Ԋޚy   5M}o&IRkV[   ,hJ4{3IJmĝ    k ?:LR=|c   ȂD[N7$F_>o   )s$I*w    YYДý{3IJmxi    k 
~$Mj>o   )Q{3IJmpQ    k '$I*UK-   @@4%JN$Iֿty   5MYfoRQDߛITjv    ǂ,󶎾3$?s   f5MI;<L럿s   Ȃ$~<L7?|   ddASo3$s\   ,hJwf$^~Wg.   @@4%|EߙITzY>s   )I}g&IRgc   Ȃ$C-LOR   Ȃ$#;LW|>|   ddASQ3$o}   Ȃ$c>}g&IRY    6MIzA$I   5MIz'|2LOr   Ȃ$$L1|   ddAS<L   5MIz|6Lϙ>s   )IͿ3$    YYД$_;3IJg.   @@4%Or$I׿`a   Ȃ$Y}g&IR/\>s   )I~W$I*{\   ,hJ3+L_o   Ȃ$9$I*\   ,hJbA#I+\   ,hJ;'Lx|   Ȃ$4ihx˩3    k XHg\   ,hJ;7LsQ   Ȃ$4ih3    k XH#7\   ,hJbA#I'
    YYД޼;3IJX`   Ȃ$s$I*d   Ȃ$_3$   5MI9LJl>w   )I~?FߗITI]^>w   )I~$Io    YXД$_2I*φ]   a,hJ$IΒ]   a,hJ2I*s    k&LJs    ke$UR>w   )IOGߗITI_
    YXДwEߗITI]   a,hJ;$I{]   a,hJ=e$UC.   @04%.@}$I4   5MI7LJqf   Ƃ$%GߗITI    YXДs/$'    YXДFߗITIE   5MI:5Ln>{   )I{7EߕITY]_>{   )I{vwe$UVg߷^   A,hJG$I!>{   )˼m$I^   YaAS4FߗITIY   ĂDE2I*)?s    kkVEߗITI]   A,h>~{}$I4   5M?U+$IM']   A,hJ42I*ix.   @ 4%qF}$I4z   5M99LJ*:O]   A,hJ4X4Lj**|   daASD_ITY_>{   )Qݣ$I>{   )Q~2I*    kgC]$I;    k~.L1|   daASI+$>{   )Q}W&IRe?:|   daAS}W&IRe:'|   daAS$I7^   !,hJ]we$UV=>{   )QgDߕIT](es    M`ASn*$ڋ^>   )Q{K$I΁>   )Y$I    YXДlɒ$MK>{   )حwe$UV]g/   @XД2I*kp    k o[}W&IRe<;|   d`ASuˢ$Iѣ7^   ,hJֿlq]$IUtW^   ,hJ?o~]$I^   Pw4%OB=$Ig/   @Vs4%'d$UZ_   ,hJ]{2I*w_   ,hJ]}=$Ic   j΂do'$-    ugASn'$99|   d5gASy[GߓITi    ͂)Ϣ$IbC    9
O}W&IRuEm>   ޝG[Zw!xhLǘ7IM&^\o51PL2	
 (d12h1*Bo{?]Uk8g{PuVghf|5U$I3w   hf`r{2IfZ?_   `430)=$I3mp[   4<*'$i[    hf`tѾ=$I3m|   P́fgKzO&ILtn|   4N}[zO&ILn1>   J9@צd$Ͷɰ.`   P43;5$I333   4tL;   PʁfVPUޓI4kߘ    @3#U=$I3m}   PʁfVܐޓI4F    hfdr=$I3mv֗    IDAT   4͌;1'$iM6>   JC9Əy$UK|   r9K5$I33   4͌N{{zG&I   (@3#_ޑI4')>   J9H#/I$Iy?3=   J9Hwgwd$ͼGg0   @i YYL7   Xjd$ʹ/   @i YbLVMz   (@3C[/J$Iy    ahfh|I$I3+3   4.;$#$iOg|   q9;2If}3   4N{GzG&I3   PƁfǽ&#$iM*>   J8Pwd$ͼjp|   q;wd$E8s   4͌գnzG&I}%   Pāfֿ|##$iN   (@3cM$IyVg0   @i_}lzG&I_   (@3c/I$Iyۯ`    436<M$IyU   Pāfǿ.#$)Rwϧ0   @i~LH#^    !hfl$N9   P&;2If3   4M}L7   P&`ry$I3ozU   P&`|';2If^5|.a    4L$IWs   4Mwc$Es   4M@קc$E   (@;w1I".+>   J8t~LHOa    4	q?#$iM&?   hRnL$I}n]Vm    %́&dry$I=+>   JMʣ1I"?_s   9ЄYJ$I4<9   PhB'9$)s   9Є|yz?&IRM0   @	s	$Ia   @j;2I"uw,   XqIsCz?&IR/a   @4$I'%>   JM1I"&>   JMޏIi|9   PhkߐޏIizu9   Phz~z?&IRɰ.;?:>   JMPwϝ1IbN|   jpz?&IRqa   @~LH3    %ā&l1I"td|   %c$Eza|   N$IT0   @	q	~LX=wb   @;wһ1Ib?Y   Phº=1$)    %=$IF    %߾,$)ss   84+ǧc$E3>   JM%$)Vwg1   @1nLX#_    ehwӻ1IbN{{|   siӻ1Ib.9 >   ʌ94Dս'$)ds   ̘MCLn$$)Rus   ̘MCxz?&IR'g1   @!nLX#^    ehbݘ$I->   94DލIkt   ̐MCtw{b]WUz?&IR7όb   2C4R=xWz?&IR0   @!zaz?&IRkvb   2#42zLX,   (3@ óޟލIkpg1   @ݘ$IF    eFhwwc$Ś_    eFhdiz?&IR   `i6h$I{    ehfryݘ$I,   (3@0/ލIkx;   ̀M|Oz7&IRg1   @nLX[/b   249ݘ$Ij<   (+́iVm_ף^z?&IRc   @@ӻI$Iī   0_6$)    e94]һ1IbD|   @@OUz7&IRWg1   @Ya4;ݘ$Iƃ<   (+ȁV?zLX~3?   VMCM7ܘލIkY   PVMCMn\z7&IRg1   @YA45ݘ$I&_=%>   
ri)oM$I5ݰ>>   
ri/K$IUM   yrz5&IR    e84Xݘ$I6~gz   @`K$I5,   (+āFލIk_THb   BhlލImb   Bh̟wc$E~    ~ߥb$E<   (+ӻ1Ib,   (+߾<$)ڵY   PVMÍ:&$)_b   hnݘ$I<   (́Ǿ2$)Z1   @Yf4௥b$E<   (́fTݘ$IF,   (́fLn($)   ,390nLXU.>   2rݘ$IѺ=+>   2r^Lh_    e9́OI$I6<g)>   2rwwc$_R|   e@3'&7ލIkz7   ,#91dnL\մ<   (āfNN}[z5&IR/c   LhD#/I$I68y   Pͼ	>E6<   XZ4sMݘ$I&]    e8̑?ލI>XU1   @Y4sd=һ1Ix^|   e@3G')$)`   ,9;齘$IF    e8̓][דQz7&IR7c   m@3a$|'>   2p3kצwc$E<   (ȁf@z/&IRc   hLצb$E/y   P͜^LhNc   hPս7$)t,   (ȁfMn>?$)WU5;1   @4shtA՘$I<   (fNykz/&IRW|   m@3z^z/&IRG1   @4hu=wc$ŚyU~   ,m=9$Muy   P͜_sBz5&IRޡ/c   hb$Ey   P͜^LhKc   hTw_M$I6<   ([ɁfU;ݘ$IuY}|   @3&7ލIs   l96C齘$I   l968b$E}q<   ([fyaz/&IR7όc   h.0$)Vս'?   ͜}mz7&IR->   rsދI    e9̹b$Ek|   -@3Yz/&IRc   h\wϧb$E;>   rY N$Iy   P|^Lh^    e8,/G$9>   pY O_齘$I&_;->   pY }=$)1   @4ޓލI1   @L4br齘$IǾ*>   frY>ދImx   l&18{1I<   (ɁfA?{1IU    e39,UnLh=    KvIz/&IR1    e38,eb$E<   (fN}[z/&IRu'1   @4wH$IV}<   (fغӻ1IrUU)   hΫӫ1I<   (͂_yTz/&IR1   @hs3$)O1   @hLȗb$E<   (͂ĺݘ$Iyr|&   G@ܐ^I1   @y4hgK_<   (f׽7$)   <?齘$IѪnc   hPw͎^,IR   P͂nXދI+   <5vmz/&IR9Ky   P͂{_z/&IRNc   0hTWb$E=>   pYP5;uUwc$EL   (fM7O$I?uy   P_6$)y   P{_z/&IRc   hXWb$Ew   <]c]WUz7&IRόd   3ht^Lh">   pYpkצb$E}q<   (?Áf׽/$)d   ?{1IUuY]|&   @kvJ$Iг3   nXދImy   P~M]ދImt   {_z/&IR1   @	4-?{1IUjL   (?@5;uUwc$E3   MKL7O$I68o   MKTz/&IRѥ1   @!齘$I&]    hZ?J$I6eg2   @qiݞPIz5&IRa    K42齘$I<   (42^Lh+c   @.ߙދImzy   Phڥb$euw'g2   ԁEVPAz5&IRs~&   7ui_N$I6\<   :д{1It|   Lhep{1IU    Sv^Lxݽ   @9дΏaI$I?   m@B.N$I6:o<   ́FދImc   hZhpߤb$EzjL   :@BދIs3   贖Mڮb$E|g2   PMKMn:'$)1   i-]Wz/&IRɭ1   i-|/{1Iu   tZɁzz-&IRޡ/d   J4-V=xWz/&IRioc   J4-6s齘$I_:2>  N+9дܝ{1IMJ|   VriL$I6e'g2   i񔺮jLhA|&   qi齘$IцgC|   qi5L$I6vm|   qiN$IVwK|   qi/K$I   tZŁV?'^Lh_   @&4;ދIm=   贊{1IMn:'>  N8P>?{1IUjL   :@Cob$83   贆p5?$)d   n6tnz/&IRc   4l2`^Lh;c   4l28/{1IM'uw'g2   i6~k1I?G   tZ=$)p   贂?2)齘$Iן   @hYދIy   tZ'齘$Iw   t?Iu]M{1IOL   :ρ2{1I.;>  s᧌xz/&IR1   Yx4L$I6,u   t?wb$L   :́czK$I68   ԋ́3ֿb$Ecy   t?gtA齘$IѦw_   @g9s'9$)[5R|&   @ZLx^   @ga9VmWW{{1IL   E@C_ދIm   ,,{1IU   @ga9ǿ.$)^w߈d   hxHݽމIop_g2   YH4<[{1I.=(>  Bra;1$)+   ,$p{{1IMFu   t?J$Ig2   Y84<]_qz/&IR4>  z8w]ދIm1   Y84<?ދIz<   :ǁG48齘$I=+>  Bq}Qz'&IR*>  Bq^LhKd   ^$4B[/L$I6y   tb$eq   t`k1IO   tPwH$I7<=   tz^LhOc   0h,ދIz<   :Á2<齘$I>3>  BpaNLxod   h,5;u5M$I6dL   :6{1IMoy   tm|{1IuYL   :sρ6<鵘$IzG,>  saNLx3!>  sa{1I;1?  z9аE&]ދIz<   :sρ-2^Lx}   @g9аEo靘$IL   :ś-г;1I.=(>  \saU;齘$IѦw|9>  \saMn|z/&IRL   :sˁ-6<gUz-&IRQd   3hbNLxs3   -Xw͓뺪{1IMqF|&   @V^LhU>>  \raDz/&IRއL   :sɁ2L$I78   t[w;1I⍯:&>  \raغ{1IMf~&   <raMo齘$I{?=>  qa.=($)^5>  qaN|Sz'&IRхg2   Й;4lM$I7L   :sǁjޓދIm<s   dM$I;e   tdx.靘$Ig'>  \qa}Uz'&IRW?   @g8аM{<*$)Z   tla}z/&IRωd   37hfމIop[3   wwb$_qx|&   @6}?wb$ś}m|&   @ö[C]O齘$I٪i]c~.   <paYL}yz-&IRes    IDATd   3hXN$I7   tbpқ;1IMn >  \paY|~z'&IR`ӻs   4cvuս7$)^   @t4,u靘$I_L   :@òkz'&IROd   x4,qI$IWWU2   i4Mw_N$IjD;>  N9аݔމIoٿd   h4,5'wb$L   :@òNLx}g2   i4Uwb$5όe   X4,;xމIop_2   P7nz;1I.?4>  Nc9аFމIoz5   tˁe78-靘$Ii)   tɁe;镘$IW2   i$ߪ{oz'&IR{2   P7+b~]z'&IRɭg2   i$V];1IuY\   :@ÊJLF?   tǁsNLxó   @qhX1nJ$I7s   tǁ3NLxU>>  N8аbg;$ya|.   Fqaxiz&IR#\   :@YC]靘$Iן   @$4Wwb$ūwj\   :@Ê]vHz'&IR#   tÁ58-}$Ihٿe   4ށO$IjDk>   @1hXY靘$Ioe   n
VdNLFгs   4+ntޮ}$Ih   @hXq^އIԈW   @hXq=wJ$I7pc|.   Fpa&ݔމIԈ>3>  N31>LF48s   903ޝއIԈW   @'΁>LF\   :q4z<H$IWUuwg3   P'903ۯH$IjDOe|.   (fft}$Iht   thoI$IjD;e   Y[wxJ3;}$Iͨ5Of   kϥcK=uUGpavVmWW{1IQg3   /g_}l=u]U	]jfj~݌_$5E2   hG׽C_TN{G=t?N|SahyKiz  MҰn<Gmyup[O%h'^Lk-I{h   "5;ʾO?|owpa{m(IR   .{f7f9R;80s7CDyht~  @ߪ']z`=#?@ch5'D,$5W2   l}uS{ק37<g$Iͨ=l  `tw~õwMΧ=tfƁ3F?  |7f9]vHqh;x~HԈF   ,{c`9R;81sFF4\  `+^m|x׺N?g$Ij{h|j|6  QeםXWUWOp!b?$I?g3  @N{ܾ7f9|R;8;$IitA  ={Mn>?{TZUUFF4l  h{c6l|o_}+-@CdFfTUuwg3  <7c[?eӻ,-@C]IS   ޘiGhz7K@CLN?k$IjLf  yoL?cV}wi	b{#]$IRo{g3  @xoL|75PZI   ]c?OROvZ]=pGW]p!j|'I`  `7/1Mm<,Q3ޝ~HԘF   Qeoޘyk:픖p!wKӏI_f  eyoLXڪ*TZՏ0ȑ$1m&>  Aw_Gq=<䫧2WVm:+-@C+I7g3  C7fGMƴ񯽥@C貃Iʣ  h{ǫ1I_hFT}l  ޘ{?!],-@C\祟7$5ύg  `tw{b?w㫏߹>\w'ſfK8Аjޛ~HԘ|  1IGQ5O/->a~]#IRc_wb|6  Qe-K=w]pF~HԘ6Ҳj|  gl?~oLnG-`ݽZ/-@C#?3GF;E  oLU\Q@C#l's$I?nx{  Ƚ7fGMMҺ>3gbi97;$575> o̦*u?H?op1|2ܑ$9K]vyl|>  ۮf|TN'44w;$5G > -1Zz>?gii9#^~HԨ6~Az>  `GyoAhh;x~HԘ&^  xoRߎy+-@CLo"$9Muw'3  ƨya`ietg$I+  .{H?w\.->epқI  1z#Wt_jT$gui9(~HԨw^  0Qe勵͗_ߏ--@CڮzIS5{>5? `tiݹ92q֙	gM?$IjTog  h{c>[wxoyasq6IW|$>  ޘz|>
{cw/->̟?$5[  f{cluZ9PZK>o_$ύh  X]Pȗ3U;+z3C%Iҏ| yo+5?/4 Ik3  l]N~K=zrEu=m~~p?g$Iܿog4  l{c6u{VRZFg$Ikrg4  lI?~onN,isʹjߗ~IԨFh  gG1'ZPw_?{5sHF5֥ @;>l#O?J8XwK?$IjVI) 7{o^I/ǟOhh'^~IԸ'E|F ()/vf*,$Q8<> #iyr9hh=H?$IjT}3  sޘQ/9n㿸K?J8h>~IԸz?7> h{cI*i*>>+-@C>g$Ikx;3 ğzo̦*~\WZFH5ک ʾ7fGMHTvyLhhUW#IU5x7  QeI>,-@CMn>?<$q? +uգw'PW勵js7`#I5:ou|F м7F\7ş%hhO?$Ij\o]  <{cm~gR;8xݽ~&IԼSs mz?Mǘmxoz}G[v?$T(EEADQ}@PQ,3wL2iRI	iB {d2{~#!d9/~?ٟ{YШ
}.@t-IT%[ANs፧"{8
0qb߬!YШ9<\\yP$IMx{c"0릗gfdAJƿGK P:ŪR65'|NK$Uy>1;/Ni؋+ȂFoGK PJ~3|NK$|Sn=;~}(]YCQ5 <7o$I*Q-Uegm<}em焟YCQe1 4;/
ђ$Ia8~ oğs*S& ( K
Ӓ$I{c fcȂF{䇢& (=%I&ޘ*묈v4g@֐,hTDM PJ>%IޘUF_ kB֐,hT'> t'OԜ9-IFyo@{ی,hT}>@)|c$IZW' Vcn3Q	 JwiIg7x5	?Q<*U{߷FO PJӒ$Y_LUuxo@MrՂM} Ͱ?rY-Iޘ*;_7zg|1~mF4\}F@)u9-IQk7z|&|eɂFDQ PJӒ$y,Z@	MYCQ3
 Jx9-I]d9=w4Tz 
@ty5$U|ǟ> ڻZ$I%iiKKGn *gfdAJ6 36|NK7}5:=|eɂFlp ΋$I|95$Uީ> FÔ/{I$I+_m?IG8 |WϾ!YШzS9 =cZ$c6J_?UeMOE_/ h|pn3Q5a*+* (5GjI_U=@id7YCQezvY Ttp$
6 y5(Uy+ (Ւ$5|ޘ*+V=>CeA9= Vg$IM|oW PIGns*[)g g$Iu{'RtG? k֠,hTF\}f@iZ:7q c55(Uw> z>|VKT?8#zX||*]> >%Is=`W>_eAJ3 kO-$IumE P'KwYQ+V}n@iuY-IR]+V==`/YQ\wt $M4Fz ޙ_
YQs JNZڵp1 c=3vnsQk Z{ג$խ|Ex 1>ceA7oTVE] PZkIjV{Ex Ρ>ceAZ4 Jk=%I[~?zu5(բ. (ג$թ=`ڻjjQ?> zg~)|^KT'sx˗4|fʂF(_F Jkx%Z:; k4Lټgl֠,hTF^}@yoy-IR]+ ƪYòQm|w3 J{$Iuipѣ j5kX4Mc.Rtj$.ofhyQ|jS0 (A7_>%IC 0V>_eAZU7Ry-IRO fp5kX4U돍> W>%ICӟL:_,|f˂Fw1 ("e7ْ$U|# njjU}@u|W̖$ʵq c=36kX4W7NGe Pjo?%IpC$zu5,ծDe PjwljN̖$uOq c-36kX4]Fe Pz+|fKTz΋ 0vN
YòQgg ^E3[6>ѣ ._5,ծ|V) JmM3[6Q 5׬YШ>Hk-IRe*V>_fAZ6|3 Jog$IUX`U|jY> F\>%I\7 ֳgeAZ3 *k$IU/Eo 5GجYШO}@r̖$Ju c׿x50նGFk Pzْ$UI=`z!|f̂FwʿFk P	]~1|nKT. 0vݣ?>cfA TB/mIw@t50շ9> F\?%IH=`_>cfAZ7 ʯ(R+$IUX`n>cfAZ;Dm P	?>%I*}7 o!
sj]}@%8|nKTڻ.zd؍6|f͂FnF譊> Qʗo?%I*q=`솷>cfA73 *wg$IehPG+YCQ;/J5g$ 0vجYШuGg TCQ|WnI/3 @NLS9 ޙ_ݒ$"{8zTugl,hԈw}+J-IR˗n=`"vQ9 ݒ$~=`"ۄ٬YШu{_9 ;g*|vKT'|2zD)aQd˙ x~oݒ$- @+YQcUy g$IejxI nt36kp4jLKw> 2,ݒ$ۢ3 / DجYШ1u`y 1*>%I*CT Ʈns6kp4jLҭS*Fg TF{oIPgEe _YQ=xm ѿd-IR 9/l,hԨ=(/eSoI|w 7l,hԨGe 9[w]=`"%[٬YШQ^Ŏ >%I
mjN*+G2 ]~<~6> Dn>%I*5 &bts,hԴ}@t-IRT#>=`">gȂFM{ԇ> 'oIꟿ(zD/)|6VO{ a=n3\=`"z~6|6 X3S-|~K4MIEhYF4jb}@,|~K4۵# &gmYШu *믄pIf=~`bE[ڦ7!}    IDATQ˷4.Ilֿt QdY,hF}@+..Il5 &XJD P9>%IoR=z`"?k,hغG4\_$i6jc &vV-5|y "e6$Mީ=v`b':|֪eAf=4 ?=%It_ u9V-5e{F P9[>%ItœE\ |WZ,hG~(,)9.IҤji 3lކV-5|)# *w9.IҤQ 3zYL4j|>r'W6Q 3YL4j|Kv>:q$i+ 01ZfQ3 *ips\q =V,h/Ji؏>z/{i,$iu	 [f4\J9.I8\_xʗl>o՚ɂF~KE ׄqIY &X@U,h *כg$I㨽* LZOeA#M` *\1;c &jݯ[ʂFQϋ>)[Y.I6c &wZOeA#9S# TVOrI
 9ggA#~o>F|'|K>u~o8k3Wyd	 \u]G) Lְ74zT4ҏ5c *kp~\}@ u5zyֳ?,hМI ^%[sIֶ|_ 0q>szZ4ҏ5, y.I6= .j=-Ǜ g% TKsG( L\O\;&Jy.IҚ/{IJAkӲ~I}V@9<|Ku	 7lfsWeA#DN>.چo33]5ixѓ &nz=szF4ҳ4z3 *
$=oHߎ 0q뎎J?,O	 V<qWm>%IZ]#?=2`VsWgdA#=K#2W3]5 fE>wzF4ҳ/*0JyqL$9I*ڏGK ίJ?,k.Iҳ9c fE]9WgdA#=GG Py$=[뎉 0+w]>wz,hs;N a/ۿ,|K_R=%`VwUYV}ĽU' T^s]{?FG 5S>>{z,h4 *Nق$Is# ̚~oj=k4j j{'$I˷Ii4 0;"K
j=k4jjkG( +$IRXYS#|YHkjN*/Z.Ij| 0k7>{z{W}@-L-zK]{7FC U_3ys jovIRs_g(Y=#ŴFz/y W>%ImRY=
`Vw}Vz,h5w)g$yuOdS6osfA#A>N6>%Ikte# fKZXH_k}@}/{i|$5o~ 0JVkYHkS]}@mΙѣ f]؏`Vo8)L(GSh.Ij@w 4R{_J˂FZz|&LZo]T'~*z+:Olj9jְ|WG P+|h$ջWF< uj==łFZF}@tOd|$շAu 9fA#EKw>[VFݚyxIR=Q !G}8|YHkQ?>[v"|KW{7Tc BL!zYHkS귣W $MF8 QKԜYfA#e[Ί>cv}<|KSϦ4D7 1ѳX5ʂFZzg|1=vOHVѣ _>Z,hE PKc?>%I5hR?=  Lc5ɂFZ'>gvFߘyyIR}ߣG wxE<Vk֡E PKc6|K*܂MSq a'JkuPY T<~{o>%IլwgG xr<Vk֡|S[ )>%Ilf>=@ΙJk0~$^Tz}.z@jq4:;?[ _}z Qʗl?4ikkG. Vy"^>%IըwG =puLVk֣cF P[zIRE>=}c /3~.+M4z4} 2|ǟr; J{߄e*i=. $KJEHRw٬ZeA#O6KG P_{g$/!zR@)+	ju4z6 jmx9^T_Ҡ= >Z,h{_ ar5 ;Y΂FZۤTg0 葛R6/I*G}a c{)|>YHchg0 ^υ|IR	w}+z,@iU)QVZ,h1Կ`I9 WO}IRlc?= T~3|>NYHx= 0qKwlwF# (޹gҺdA#y"$,S{~IRH 3ZuʂFS>w\0/I_1 2|Z4G$8/IŦmD (}Wiu͂FS-gv b)_U$N!z @){VkW  ?D$KNEpRVY:gA#ޙ_>9F_4W=q ۄj9iw3 et)a@4:#7 PJojW4Ҙ=|c ;3_4o2	 xvJ4m}6@>/I5 =/Z45l;$i|u{̻ PR3[ʂFwSbG4 4N؏$Iߢ-[
 l͂F@}F@)gkpעG
 ^gZ4:?Fxr=@u@(J's[΂FD6MEs {ԇ.S1 7|gZ4?!F*GRτ$IkSG T΋ZcɂFP?}V@c?6. IZ'K 蟷0|v5,h	/: $kƔy X&k h^ڻ6> Iz/JGn P|3\dA#M_>F^	$IԜ4ѣ *exY3\i\YH,Ug6 4^EwI3띵m ʙ3\eA#MуE l(uwI4}.{g' >o	j-i/X}n@+Lҟ
HZ)_Tz z4 @)a,WklYHnz xmw^= 7?˕ƙ4b7 %)E ɟj5i_g LSw$uO)  yXf( ~XԤ:iJA =x]<WkYHѼS=} ?2 $xC*:OD Piwj=i\o9 ET~;9`'z5,hYs{q 'tO;$ն/H{}@ݕ)IlWw4l5T>7W7 Iukj4S jag$fE O|6IS>6'~*|5,hYss Ybx
T,>>bn]dA#f6H |W9Ip>VF\>՚X4,7s x$Nc jĲf} ;3IZ>R1>v:=|Ϋ5,hnReg; \9wIH#>h}z@'R6YĲ\l F}2zSA^4F PKjM4)>Q<y_wzeAZwoG P[>>՚h4R@ T[RT:Ͽi `"˷	jM4)'G Uʗl~w=of L+gZςF
{G OF$e ޹ZςF
j7qӰ} khx7S`;$E;?fn ojM<)M߈>0)QBfy` hc~f%)q>4XKIijN_S ҿx;ldA#/~qJv uG[H7I+>rq~=@i6\\ T?}@Lwf%)Q>udI#w4z# jZ4Rt_ު XGI4:#G+ 4VԚ,h4 XÛOK>uHJN
 UtV̼.N֬eA#w |MIsTG) 4JTl:! mte3/[HҚp4 H)uP@i6Jg  0I/[H3g Pvm~?PkVJRD `Lwn~s| JdxÉf=,(Cѳ  x;$x6J (qOP,hѳ  A7uHCwxE IAʗ4֬gA# E{f9bՃ'" ,~WP+$LMmF `-OԜf5o?QJ( C"JV[D `B7$5|WD} /&ޠVH4Rjw 0AK]* ֳjeA#9x  Lkg^~T~.o93 PO
˂F*aD `'lCR}TFo Rt;ZaYH%_ ltS{Hv_8 XKOGTF~7zF  N)aCR|Sc Xc6.Vh4RI}ߣg 0~3tDR5~㢏. `]/zaB,h6&ѣ E{SgC$yiKE# XkW(EgA#M߈ lRmS65'."\u4zS
 [TG$zV  A?!^~TO80> 1(:+R`;ZYHenf36 LŪS?HijNTDG Z=CYH%og EۧlIW{O{.> 	ZȂF*ya  J`t婽&&[{_C 졔(ΡV)ԜT#zv  e0޹S6o;/{i_kJAI LP=j&/\=; ڣnHCHMEwe ̂~o(%M	 ۩n8N9 x⮙o	(%"^ Jh൩[*ְR菤ѣ?>> Yֿhy]DLYHwg PVEWe/	HZb7D @_S'*Rza( ZŪRy}wl'XqG {Rٲ*ӣg	 P_.R[ET'H  J{'Je˂FPݣ?=K *}ٕ|0RʗlzgTD @Y)_U=EeA#UxH REw;\_4'\sx]ERfA#Ue{F ;kۙaDg:ip!)? @IuzwERfA#U޿=S 
==oS6AFl7O)*G (≻ܽ+  Fߐ}<e6HU)_M;e 56uwJTz kS>鹚:+o810G H]~1>T,h
/:A'z  52H:Rw;iM? @E0NV*ڣg PCŪf)_4-,upxJJA# Pq!~T,h9=3 wl/X2΍{4Ѧ6Ha\yp*OF 5QV|:Je΂FjSbŝѳ pX/YۦcF 54ZςFpF AF\}<e7IR+S/ݗF8 59wJT^R17 @'}S{IWkRϥT?> @ߞ9 JT񆷝=s =)_{ߵzSꟿ ̦9sCjU"uX HiIIޟyߑԼڻ>ΝF  4h~.nV%S~<z  <xԿdJmv?m\yp*V= `IjU&W xVw~o=Zm{9G.F |:+ޤT,h4U *,s;S6o;_{צީMÛNMEoU_a =6YH5i3 `ꯧI-R*GHݣ?wD5 X+3#>VjRA  fO;.LsWקkSYM @e)_;Rjo 6=өۯ߳4 u3ͧD_5 \yp}KjYH5jp~ѳ `UǥiK~'lԜSNoF\6I) j;RղjT{ߊE  WtWmۥyoI=0w{]Կd4| etUw2*fA#լѽߍI  x4?QW_yIݬn;B'wʃS
    IDAT j{ẐFY1z& C/j鯁sR{_Jټle._M3_O;?\m xOw^~SYHukRY=  k؛'|%W:_gM/w}=g>u44  +~T,hֿt PYE4z44ԿpYOtxGj/&e6w-Sӫf>2x9wSC3g*G _U,h6  ̂~;+MMû.I[NKkONSwֶ'SMiMEg80;&owufQ
  4jU:0zF   @muX3@*TӺM   Z*S`gjU:$Cѳ
    jJUςFqw    Ѡ_OgA#ո|xi,    ʃU,h7    7ßU,h93    jax9ԪM4RݛQ*V=    :/yR]P    6zMmOdA#5|NiЉa    PYS>OZeA#5G0    xmOZeA#5^oc    PI?SvYHjxѳ    eOVTG3    Շ?SYHMjކXqGL   hzJûFjXoWL   JqA<j԰?R/m    Pz?<OfA#5E6    (ѣ?ye@<jڻZJE=    '~*9Z΂Fjh΍q    PJ{S6gxj:M&    LӿNgA#5[g    J?E/~T,h;    JwTs;/NEwe   re)_vj5"/3z   @)/ZNdA#5ME>    5|ßש՘,h$    ßөը,h$>o    g4L]~)9ZʂFL;/    bpաj\4f|ϣ     ̾H=|NeA#MI    07lNYHz	=   `V}ks9ix    bx9䔚;k    s;ǩ,h$=|Sy"z6   Do93YgԿd    éYHzF?Ұ=#   `"7NYHzW='   `"yK7idA#ja    u2ޤ̂F|z   )Fo?w2I?    06k&e?ʂFj	    o4L~5y(IsG'    U?k˂FꛚF^=?   `>=?kO4    ; D4y#7EQ    X{~w~u36iӳFuQ
    kßIٳdA#i͚Q=vk<   57|W?[>3Ik\OET    Xc?SȂFҚ7T#z   *ڏ|ԤϞwʿFV    x^3#Y&IkׂMS
    i[`c?K>w4ֺ_    ~,=O4־/HEP   g=puʦ6&]}4֩YFZ    xAv&ekuk    ͧ?7Y4ֹ9S3    ~^o
f&eku._e*:+G/    ?/ȂFz?oa   ʤl-i?=   hۅ?'̂Fz    4T~<KF&ekoX`,   z>4w4z}.z   0㷥lƤl4owDd    s⟋Is-Ic{?Gd    bx9äl=4mF=    xC0igA#iuXx   %9g4i3   *Rd`˂F9   @MuO_R6,h$M=Ej    jft3KƐ9   :)ϽlLYHXϏ    CßwI4:-zn   PEoUʗoKƘ6   @699Ig    [R`\R6,h$M5GDq    *sßoI4^Ҡ=   %eʂFҬԿxy   @ۯ?ג	eA#iVʗl   @EΝLK&Yw:    0z-,yM0IMDw    ʬ(R,K;,h$jݣ>=   (?ÒYȂFҬ79   @	Rτ?YȂFҬf>
    ?{'ß]I,eA#)E{    JdxE)Jf)I!w   @{ßYI,6z4fE~    JgUR66MmԬe/MEgE    [SpgUR6+hIFRw     ugTRP=<30#䩏   ,k>%͍讜9heK_̺~,.    ,|?Ҡ3ʖoЦ]D	    E?\JMR*Vӫ@[{Ji4    05KϤ,|˟yh{FHR|    &o,JkƧ~&Z["$    duOPR\kDsG@ۻ`㻀$jcGÌM'$jM'	SI]_o1(

 ~-"Y~
=yw(ssι3s~b]%|    ˧wLZ*Z_Ū/$ZcTA   7h=.Űu/H5?    K?-~$UcRß6V3_$=W/}`    `j3iՋrǪ.*$~<>8    U4٫yTQY{/H^X    k_ߊ3I՘5{Y?14^9Q   uET3;?g֌OA{uj{aJ    Fѩq;/I՘8_:'SI׻R    ,Rk?W1uy@?.$J=K    @fҚsͱ/hXI!'    XA{6IR5KWa[s    :ʟ%IkƷAK~x&I۫yK=W    0[)~$Uc\}_r4Co)%i{G   3x恨}S#ZU1h>|   +_+~v$Uc^?дyd(ITg?b    
:W]H&Cl/P^wﷲ3    xojό5]}c]PIzǽ7I~    EsgER55^F-B%\!Q   ѾψjB\e3_$jw[7    xK羊f2<q׫4{)B%i>5OP`   @DOF}ۊIՄ8g{=h~/CXK|~猄    :뷋	I5:4<w`IO=cP?    DDw˩σj~%M4Z   p}닟IՄW̎_$ͫѻ~   Xhlڻ9fj_gxidj|WpIo6   `Ek_j}ᒴڗ[g   {}jxKĠx2f׾yn?xr=    8'7?L^5Py_D"    +O)~#UZ[?tn>    F~yjBk~ζ;Dաv>    ,]<Қɬh]oDZ6   `<uoԇTMh?ѩGhzc$i/[T%    +C>P\G&+4C-$iq_uvݨ%    +F^LGZ31o]sߔ$-q?ml   0zHkFu\uM{Qߘ$-&    o}Q8R5a?mֱߘ$-ξbO    Vߝg8Қɮo^M޽8FtxB   nizw^LB_ڗ|r7H   iֽg6R55OwQ~hTE5Cn    ӦmKTw-f#zw_PSJbkl|wD%   ԏE}ۋH<7}-.h77Òڛ_   `<ChjYnhWRMK(_uv-	   0ɆjiJj#]h٨6YKbxkt   4ݛT\F^g4CO*%i_w#<   &I:pg2ҴԹE4G 4JN&
   0'q^biq^Es{1 $i[7R   5GVFzw\$YSQjlzD$7T   qӾHT_sQc?I%cn    wQͬ.~"MK=bP?:P(4R3;DoKsW   Gnח?w_Zt&h$R}t   (ex1#[iyo.jI'jn? I    ׉^ްgfρfO$i:nZ"   @yT|EfVG/Yu:;X4JdF   ,+"MYl4ï:{ݣ&I"=   ,mG5Csijlz.@3Խcs̎'IԾK}{   Xm7E}kHT}|^K>.گ'I#ݼH   %3xf[GdiZݙeh׉I%i{/m   `dF4Nܧ4mu<4^lmQ?HIg?87:    Z_Xij}]_=v̮۹*I޼r*   }L3ijl;ٴxY'P%ifVG[%   toyE3i~GfJ}j]WF>u[&   v>?ZDCX/e~?g~,I   @	ǷFag$Tu.ѻ"t@3mGUÖjiM   G]FjkwŮUoX.I#Խ['   ҵhg"TvznK;u?PԟJ%ܘ}   V~/_!45Ctsz;?qOTGAYwƠT[(   'Agn89Af֨?IZd3~3b0(u   \u?Z-Ƹ(6=\"Is%o   jfuijZkwas_wVW$-;EJJ  )һksg=iݢ7D}{$iG%åo   ariZmq4Pz4M{aIbj~#ҷR   `=sHRy?4sZU4NH$-,}   &Ԡ~4U|CjZO8fߋEQ'I3JE  IӮqkHR{m77<bvf?HIZPw7   ׉i^LC^[ΎI1PQ{$-ȷŠz-   wo:뷋eHP#$fQp%i!5O   eʟ?Ð)٘4c?]IW?/}   TO?&GcRM@΍jn4ߺ7R	   ?&2Olc[>a?|IWv=,}   Dc˟WHD"t7u}冘]S_IzCǷs   uo:-UH_=d4wmǾ/$Z3o   @!8/;?&?n|`d9vn}̮$J5TK   `azs_^lBfv9#1&yߦi|H+Yv	   $|m3	ij3ͦf3Dg:y$i{uZn	   $oo(~!MRcJ`紪h]6ZI^?{.}   ,!MHo'FڱRL@SߏٿkV咤Vo#o-}   篏xki\iE3+byN[y0Ho   <q܁ssikl|Wt;>ۊjE4/j=CyҾ+   `7QA皟`to9;ߋnE4m9A̮}M_FIjA[#   0wG}O?gƲwyn(}9<CѺlmT/]uo   Hr構/HVcѹfߎ=<UE>JZͬM   4x򞨏z{iL~_OF<Ǟn.޽/ֺwo   <3sו,'f{:rN4]%n)}   ^|Vnv)UE'f>ƚ3?K#_   looW3);E_A{e84mGwѺQqŠd;   ;HY}OEG+UKo*hFlB4_?5_<ɿm   <}4>3%]<W}ǣ{ѻ4*}%6ޱ9ZDQEom   Zd4nƦj/#ZA/Dt8(:nDkb̶җl\wWM}/Du%+}    !e)  IDAT                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        r?;\'R    IENDB`PNG

   IHDR       Ou   	pHYs    {Rk    IDATxyeu}{P)8d\FvLA3'cIwx3<5QE1HA1Y(QfAd
ϼW=$Dg9ZVѫ{u>pgf0}77݋s8gHjPS?b>5    FJߗ~#I/N?݋M÷M)WdU)+Y∟yuz   Tu7D{ٻx$IN{&L^/ޥ}Hz|:O   VuEN$=EYN{.`2*YM)"tSs>
   0bjn>w(~'"~wAt(/f;#O   SF7H7DO`E u e0w^1n-yYI3ܼgSO   |'$I=s`70X`W}^@91   ث6֒4~bxߵٯ`;(;(=YXGZ   01Dq$I3SwQdbm`7NC^W(\}    LUQ!I9/|,DpoޝbT[>/򁛲O    U>|[2H4;ҿ u<h?t_QN1   0ʇnbIf^7煢~ ?Ā`^/ZGK[RmգwdE    EFYlG҅Qv6dv`ɿһ|IzAKZRJCՆ    ?\s}L?$rsYX CwO4,)g~"eH    <r7k{$IRMr~;ˀT+QeJ    <᝗GknI5ѿU
c5qY5+)x8X   `+o=7ZswIW$Wq;cxٯ (,0D?Ԝ:G/	   0j7$I565gd`"lwhvUR#~}:   W~$Ibݣwա0Uc̀fkX9m>    A%ISqog`lL굢ܝ_S{|    `<;'IRR975`f(Z6)Qu>+v   L*=wOϾ%]Fb;jЋ5SRR+    j؋~%IJ5Ng;`veKߞrԸ:
   >=wQڟ{~+3`Կh-|nQRC+N1   @h;)IRr_˳_K0X`9w_Y[Ġ}T   Pj=Q#wSD1d`$6>xkdOR#7
   d*^,J_蟏rٯ&9,b>?'uN_^   pD{dI3k_M0RX^OWNR#k+    L~q~g%Ij@k?ja[oG$5赲O+    dry~w%IjF>1[fOl=#ߓBG'ަ
   \_$=^OS3`'1\h/2Iͭ}Eݘ}\   `Jǒ$51e4Fk/0Iͭ};>    ~%IjNg庻_OH,}$5a?Upq   (okI~C~CA\濰$5!?զ+    FM='$IjbxMo(h7俨$5oj
   UE7sIS1\s}+
À׿zYvJAIjnՆ{+    F\ȪY}%IjNŢ=bW4ʜV#Q;   `L\I$5b0_^Ŋ%/[+    sY{IpW2`a"o>?Hzڵsy    cϦ߁I庻_Qƀ3+њkHR[
   1߅IUqܸ&)X(;/ւ_<gK+    &A9Ή=NLԨegC[
jg>h71
   IoG{ߍIU_RP+&Bz(ސv'eW    Lj(;2IRWʀoGqϥ`$591zYi   +~;E/ȿ+$57>0?MHjv}Z   @or~_&IjPsw-f,%_*]
    7;3IR*=ޚYgڼDlMBzMQ    O;Swgf["zW*Rh-3E"u[f    *s$Iͪsf`V0~zEKߞ:Ǿ?b>    )Uݍ>'$IͪWN?JqHjn#9    t÷Ewj5:ҿ>Qmz    6\uQ~&IjN^X1d(YOaHjfžjݝG    l7>~&IjVݳ:3΀0G/
IͬX(!   =$IjjNn9'3ʀнx*%!--w}-   3Gs&IjLŒF7FயGk/Il.1c
    fDz0~4MԘ:'N	f߉O1HjO]|)    3|(>/MԘb	f#{ѿ$5K(    Õˣ5S$"0F5Y/IͫG    ̪WISOf`0aޝ"Լ:'|0dR    0*Q}$!MûvbH}>"   z>rf>##_F#@= Yz}TG    Ԫڸ&^~?'IjF~5v3`atfU(-x   }Fks$IK^eg}	#eKN9QsU    79uKk	}{|Ij.1	    w?I[[~-63`ado<)Ԩ+fM    U=N_?~+63`a4z:GzIͩwT    SG>]4S)Ā_qx!/1uO?+    <QyZ{<IR}
߉~N?%5tO&    h'I+,7f`x+?%5EZ},   Hwzܺa++vI[O%    ~t=IRܔFbB.)yϊeI    0rkw|I5EkW\sd    #h5OԼgF<-zkq    #ϦI]oٯ"xZ,4VqrIuOHDUfG    0gi$)bK"Wl4釸GLD>    `|Z>w~.M[dB#\R^Ł`Q    c|pe~(Iao~8oԜ\RN^GG    M'Jr<%H?%%5So9'   ;o%I]W<%eЍ/I?%٧    La?:G7NPT/G'eBo:%ЖS?>    `TbT&'eI(c9TKͿ    kw$:jQ>ʗdi+xmTG    LSs~K֒jX(!   V4Q<8O`BcysA-ƦS    `eQ{CIR-uW<0\2To.>z    3?+}w(I;GZ`B#t/CZRmuOHDUe=    ]z| 8MzjΈ~;    L9ٯsoduYR=K^{    `F%YnQu7fvq,]0p4%w\}     [ax%њs$iVz^+gBI?%~>n    mл%I[Oenq,*G!`4u    V GP%ikSox7~(KKog7    v=%IԜ6=i,gYeQmX}     ;`3%IS_50̀<e%/K?%Rû>i    =cwY/_30̀4oI?%^g3    LO;Jfgߒi,X=ϲ    `?Jf;G۔tha,ik/وA7    fAM$|û~ŀyߔ~Kي{F    -U/|(.R4~`XQԜX6w0x    fYU<~ʿ$XS ,<;4(h    j2\uPUƨA~9K?%\>QG    P~7)Ivٯ&)_CXҌT    &̠Ͼ%R43ߐfa8`I3gGyߵG
    \s}=+Rn>53`~M?A} K}     /I$xfRp,nx釯	    Ub$io&8"c->N    ^]J~0X]˟J?|%m=z    huO$m/~0X]~JΦpc    h))I?X]q^IWOg!    @UCQLIWdBZH?x%m{e    ᆫ.5;MIҶ7ٯ&*]I^Q+    FD~)I7
aP}ץ91\<     FɠC2~SMqH	fB+N?t%m[)     FPy5њ;NI׻__L0j1釮]~    e9%I[_K~u0XU}]I[WQ+     FYUF_H$m]3?`PWCWV45'+g    =)Izں|$3`V3?~JzzSq    5G{J~e0XU\D    0f:'|0S:G/u3`Vޗ~JzE{D    CX{PIS^̀ZK:Еn<)     A%IO]f*`,Ԫ8J?t%=y}D     {߇Jҷe&`,Ԫ8M釮'>Q6e    6=E%IO̟"jCW5(\}<     dpÉw'>_L0j釮d    $yɀZ(Е_u@DUe    ZF};_L0j釮*}eTC    07~W*IG33`V,RC)_}$     Dο3$MgB&je"5E}     L6=M%I,2`V,R~e    ;.TdB.je"%Q>     	:z$Mx,d2`V,Rnk>     T(z~=$Mr,d2`V,R^?QU     Sw4ɀZH9K^զ     -w4ɀZH9o9'    *CߍւU%i3`!2`{_g?     ۤw4ɀZH>Q6e?     ۦDw߱JҤeB&je"]\"    .9Z%i2`!2`G    `w4IɀZH>g"G    `(|]$MJ,d2`V,R-|n|/q    [ɿw	ɀL,ʀE+f?     3so߽J$dB&je"ncQUُ:    6b IX4{{s    Y!4ɀZHcq    S^XIXdBX٩sod?     [њs$k,d2`V,W,#o    Z{YIXdBXopIُ6    @m({uݬ$c,d2`V,k    YIXdBXQmz     H9JҸeB&je"\oH    J8eB&je"L(q    H4NɀZH3Zkg    | Kߞ~o+IXn>-Q    hޫ5w[IXdBXsof?     ;J8dB&je"mŢD    q({U=$z,d2`V,7G    7~+IX}u~    sܯJ(gB&je"mGգg?     W>|[+I#XW    NוQ̀L,ʀEڶG'*]    /84ɀZHЂݦ    m3;^IXdBXY    94jɀZH[WFُ,    *~'Z~+IX%~\    F^;WF(2P+]G    `,TݍQ{_IXdBX-W^+Q    NHQɀL,ʀEBSsbx%ُ)    x;`IXdBX{_d?     c\s]~,IMπL,ʀEz}^UG    `luX]$5=2P+鯩g    IDAT|Z	    0֪(~,IM΀L,ʀEzboُ&    D;aIjr,d2`V,V{T~4    &ðC~<nXXW,~,    &%ɀZHUFTec	    0q: XX%o~$    &R5YwŒ԰XdBX}G    ;SwŒԴXdBXgD߫n~    &ZYŒKR2`!2`O~    UKR2`!2`Ѥd?     rDݱ$5%2P+Mtw[C     ;gKRC2`!2`$׻d^#    wȒԄXdBX4z}Ġ    $+55'.Y3`!2`Ѥ6    -wɒX&I    4uwFkwʒX&ϙ     ̿WXdBX4i7    `+UuQeIʀL,ʀET7Dُ     ۠˒X&w~     V^~c$edB&jeIsod?n     lͧ3KRF,d2`V,=+ʇn~     ޛ,I5gB&jeI~     AoFkjN$ՙXƽbK~     ݓ?~,IufB&jeqoc3     fHњkݳ$ՕXƹҷGTec    ϒTW,d2`V,w^    0êQ,3ZȀL,ʀEZ?~     %~-IudB&jelnQ+    `{>ђ4ɀZh_     `nB}$v,d2`V,_og?Z     ̶gߒ~/-IXƭg?V     dry$f,d2`V,ڇuzq    hiIXdBX4NW]H    P᪋%i2`!2`Ѹ9׳'     t}=$F,d2`V,vruُ     I+55'Zf82P+C3?(    s%i3`!2`ȷ`ߓ(    |_N̀L,ʀE^~     h~o-I3XFbKn~     hۢ5wkIXdBX4W,~     hY~-I3XF!o!     Zw~-I3XFw     P/}2[f"2P+싺     j=^Oϖ̀L,ʀEpՅُ     ׻%iG3`!2`Ѩ9     F@Y=%iG2`!2`Ѩ5    {mIڑXdBX4JuNG    QkE%i{3`!2`45'5g?2     qKvfB&jeQ{d?.     A'_~-IۓXFDw     F%i;2`!2`(=cُ
     l؏ץwKҶfB&je7YQ=zG    +,F12P+5     0
̀L,ʀEMX6=     0&
QˀL,ʀEMw     Ɖ_a4bɀZ-|nTُ     cfp;pIXdBXz_    q~4\&2P+5ώj}ُ     cjpwᒴɀZT    8+,F$2P+5W6ܛh     0+ϿɀL,ʀEMw'     &I-eB&jeF5ר6~,     Ϳ-dB&je&;o	     &ɠžHʀL,ʀEi3ZwW#    _o$=E,d2`V,jJݳ:q     `ZQ{rIzXdBXԘ__y    	տtA]$=I,d2`V,jB3?(     0Q{}$p,d2`V,Joj(\(     0zs$P,d2`V,ʮ{f?     Up~o.IߟX+*1     i>\?2P+e9     x\qM?;\32P+e6W     ݳ:\32P+e>U     #ZswIGɀZ(ͧf    IuO{tIڜX2*r    'UcߧKX2\,     [9dB&je+yYD    -;uI2`!2`Q/_    >=&;2P+YQug    `W~.i3`!2`QTG     ^UEПL_4ɀZգwd ن6+(+ওcp͑]Ew?)r{}s6ٿ;7[ϋFy߷%E  &߱KXdBXTWݓ~'  Q=z{!ˢ7ߑ;hSQh-|n-6w($ڇx|wtNWѻdoFވ<  ̜a%Md,d2`V,]_ *Q3w\돟>(eӚh|Kbxףj=s  W=[DfB&je:b `d(\o+őezњڣZhh/?{Կl|ˇn(?  OmbӿKK{62P+?  EՆ1X>1=R)xmo+j?  i9;ˀL,ʀE]߫>(  4AY7-Wsgt_ެ_ݓ?˗<6jn( 0kGߏ%MV,d2`V,1 `BUwΌ~#$fٷLIuEw?n  L>,i2`!2`Ѭ9Qg  գwSw?{(jX{_qxޒ `LkOJ52P+fkH  q"w^+>>/OU1ب6ޗ `lﻒ&'2P+ZSsW  ̈jpbhh%Fao/?  49ɀZh7  #ZO>m5~ݓwsV 0n+i3`!2`l5o  FD+g~`E7w|CZwW  trwYIXf!2 @S1\uQ.cԜ>ѻd^~R  hrŁ?UgB&je٨?  4L;jUzڦDFCj~  hͿUgB&jeon<  ^wA_QҎ>Ot.  mbW%u,d2`V,gy $̃N)bӿJA=\" z_Q%w,d2`V,{X Pj|"Tgo/E  T;74ɀZh&k/{WG :G+G7ZS;C򁛲O  t裸72P+dH 0KVmUl4g?  dxǥC%o,d2`V,_1d AUgGF+6V]<5= `32P+T>q `&(gi>7{4{TN ,|22P+HS;Eg  v@zEDK^RǦvIWg?  ̆~{ӿwJXdBX4uN`G AoKN)MR[>  a9ˀL,ʀE3?  lE?g&ʳ"2d  `TVO	+2P+h(e  FZ+oL)k\
 `tO+2P+hKf ؂kZ[wGI[ͧMR  ix+%W,d2`V,ڡDȪ1  ?l؛?%mseS_  *2;ɀL,ʀE;R TLB^ӿ+J:'fܜ}  7]RdB&jeipa  6oޗ>IN=#Q=z{Q U%%E,d2`V,ފ_1f &?197cCI]w*>z  
K4ɀZh{|q
 @-Dw'TŢ=C"ai TњF?2P+moog| &˰o^]PR~ofL  lA?K(i3`!2`>?  c؋G7԰D?{ hru%|,d2`V,ڞ6  0\({u?IͮXBV :G/΀L,ʀEZyQ6et נ+b4z٧  gpi%v,d2`V,ֺg},c 0Aut&;nj.˨:O5  6+9OeB&jemmx[ R1hzƧbW_>  ?4ɀZh[j􆈪 E{ҿIߺ_~  YU<74ɀZh[_:?# 0~1ɨ1\< h3,{̀L,ʀE[Ԝ(Y iњs;IWD~$( HûL>(i43`!2`9}W /yӿI @BVdB&jemp+ 詪\(}e9IgyTݍ٧$ DX=PeB&jej޳* ru>=$)*(* ~SҶfB&je{?  #j?/}2ZswN'IO]wɼ>> &Bw_{ow]~EG촣cuqZ5iNm;Ctb{ZO۝ !C4\B0*B (ɺZ<ЇVAw|=%,̀EY3`n<J$mY'=?~_#5{wF$$I~h1`Qd,ʚ?J4G?UIw0o7LJ$}#?XfR}$IR;_њ>4n8 +aOXImpw02XfRkT$Ȇw_:~6^sߐGV$i<Sg|h0`Qd,ʚ碟$IRq5ޥ~̵I/HûcW$i,{,̀EY3`hI$K/J~d3}h$IcW[	,̀EY3`Իn~$IEt[W630;?%IƪwP>EfX:ye$I*R u|ujvcY$ill("3`QXx,/<%IBkSwe %~9G$Ix4I(2èR?xG$I
kxU~
cYtXp^jIE3`Qd,ʚ?LOS$)zө5uPMPRܒ$I#]7Skj^mˀE(k,0N~$Ik+uV6%8k$Izu("3`QXSR)IU}3o19}orImpE7P.EfcII=zA0w޵5Ǻ$Ih6R{o:L,̀EY3`_o:-YJ$euk,?*w]]$i$>{("3`QX>SoG?KI,_Z|D0n7]c^$ijkчs@qXf')I4;] cmj^OGė$I~+cX5W+~$IsVm2 jR?%I<l_s\("3`QXS|}$Iۆ]?+0~J*c@$4KiY]G~3`Qd,ʚxMs$I:5MoX{*Y#I4i5ݙ[Vjݱr~j-:,6F"3`QXxTQ$T{S%ߤٯOMI9ٳ#M] <'ƃ"3`QXxTQ$) ڴ!IoU@KeX5ftN(Itݔ' u=ETH$=TښWޚcf_SdX5fTF?EISk+ [gϥoEdH$=olYuǦ	l,̀EY3`aF}ߖ(Ij߰4V hS^$I^gGn[өzAj/yn(2è)/~$IOA/.
Oۣ?E$I҄twWKR7/
 EfP}o$Iғ<g>iM,$7[_Izk
CU,̀EY3`a}c3$IzR5{K2iR]+$iĿ
hp%ZwlꮜZq EfLT$I~7;{
}ʋSI4"cᶵZ??~ %EfLe%I[_M~Kp`jf3$4≩{~`"3`QX&+$I~5.?3`nH4ՃTښ[VeHGA	@4EfLOOߎ~$IO_ZtX|?Iᫀ\uǦ:("3`QX&WS$Iznxj-<$ JMItj7өz,̀EY3`\|$I$=ןFLΊצT?$I~]_HKSc`e    IDAT(2èer5$I~di01aq$Iz][`˪ٯj 3`Qd,ʚdOO$Gpr@ޚRD,IIMUV&~+ ;EfL~z$I[K (Gu?$IixUZ?	 &"3`QX&p'I7~/PuFDI45nߴ,:ˏ
`EfL~/$IR?;L hj^lYQ%IWRkWZxpg= ?"3`QX&O?~v$I?A >4,IFfώ4ܶ6UW]ꮜZL	3`Qd,ʚtA$If
 ODgz]$Yڕ]RwoFn EfLg'I}]Z /LwDI[Jû?zڧ83πE(k,eCJ$kSkw sS}8L<ՃT߷%6HO9`1gX5''I/sj	=RVi$=;pTNߔZ "3`QX&K}$Ilߜ7%I4ܾ17,MRPEfL?ݜa$IJSG eo$=־uoIS_9
@Xf29zM$)~'uV&6`,<xk$I*z][`˪T;6uWOn0RXf29_;+IIS O㟙9N45{v*ө{R|`(2èer4$I҄W}o" [f<Itw*KSw^A Ɠ"3`QX&CC>I	oݣo" &CgRt?$I԰קeY~TjM`2(2èe2Tk"I	nWh
 O?IҨVS4ԻsƫRk!m L.EfL?$I҄Vg[j Wψ$@͞jZ0 ^,̀EY3` >VI5g0`2M7DJ
=7*N/E(k,㯻r~3$IX=H~0K	lOiyE9&uZS? `(2èe(I	/  =S4}cK<u "3`QX̯Ĕ$IƏ@ uF<J`{`T}oS7bX51U3$IT$ep'Q{d7-Kz ɀE(k,{oD?1I4A5=so  G\JaWm^zkIGA! ȀE(k,	OL$MJM OԟNMOMILM]jf\k
 ("3`QX̯֔$IQo x"yvx)I[ȷOʿKs=Vg EfG4$Io͟`7)Ic3iWO}i~ U,̀EY3`_$IT{S/} `Lo}%cTƣz][`˪ԻԚ:(g= 	Ef5G?/I4.}[ OFC?RI=;KR]9?3 ƙ"3`QX̯$I7~4wTt͞pTNR ƀE(k,cj)zK$qwϊ{ )l^*IEe}_Ti t,̀EY3`O$I8WR_	y Xtx*Iy޵5Jޱo2uPd (2èe<9>iI1{ ·_6$i\kH[.IպcSwZ cX54>%Izͩ{ '$cVH͞뗥H#OxvX 3`Qd,ʚZtXJ^Ӓ$IAg:92O[IگjfoZzkU@< Efg$IcZuT si4ȕ^=HieW͎˧
	 -EfE?+I4mI: 0׺)5MGIiRip*+^Z	 gX53ܶ6YIqSgk ȥџ&pqUO} e0`Qd,ʚ˘w$I_P 9-:<;o454ܾ17-K5Ǥf^> H,̀EY3`/^$IҘ'{F uŔUGQz4زj+? aX5F?)I4fu/o R]ŒFfώٯ}cG, F"3`QXs$I\~ @=E$K*+o"UJ%ύ Ef;ۢ$IVj >S,)w1;%.>? `X5>y)5M$IcW&D7 Phz][`˪T;vWM?-g 0Xf2>Ns$IcR 15/yeG9ٳ#M=M;  "3`QXG$IƤm 4S^⫄1NgYZw>?_  "3`QXp$IƠ (UuŻ?%OuoMS_s `(2èeL,<8$IҨWSg6 Pk?%awmM-R]9?s )2`Qd,ʚx|OI$A+ (ophّ֦j:?  "3`QXC?~J$iěq_~ (>7DU@,}a \Xf2WF?%I4 F꫄oƳa?;OMRo1Ԛ= @Ef$Iᚽqi `tN{yJnǸ4T9n87.gZxH  %1`Qd,ʚX?"Id >qijޞ\Ͻ7uU#j 'E(k,uH$p͞ FCR}MR5Gfjk.::, 2`Qd,ʚֽ'IZ YRSGK޵56H5ǤRkj^ߟ  E(k,opH$h{Rka ΊX<tglY5Uݕݔ  sȀE(k,7$Izz{- }fOfpTNR{s $,̀EY3`mRD?#I45oOC .=i+SRIG 0Xf2ںF$I#Z
e `o"#^z޵56H5ǤRk  ~,̀EY3`m$IִH~,q>)ԩukT}  F"3`QXF$I WJٳ#M] <7  Efۣ$Ijojw CS|MPMwwqU_$u/|sj  p(2èet{$Iڟ_P 㮻r~JMqz4ز*.{G,?*
  EfE?I4j
c `n _^S;f*N~9 ˀE(k,/$IfEZ ٯvh͞pTN|#  Xf2WF?I4b 6_T{pߴ,變
x  ǀE(k,#IF Lzg޵uW;6u|ujM> 	,̀EY3`QIiЍ~>$i~o @}(s͞ip%c eX59$IN0 0[/>4G5{KmkS~:uW/H  /,̀EY3`MK8HZ &Y?RՊ>	ki}coZzkIG-  Ɵ"3`QXFS$Iޞ>Y L>?q}ğO  ǀE(k,ixUOG$H3%v Mj-:,}47RYZtx  g#IF] }z@3{;pT]L%	  XXf2z' Hixo :DVnߘޚcRgQ55/  eX5=ף$Iz5v _WgxVRkklY5U@ݕSki SaX5S]g#IFf jpyѧXٱ變OoJGo  "3`QXFk3Hw õ05GυN;7VY Oz~  "3`QXFpg#IJS- c苡ܪ?_wJ]  &"3`QXFOy0Hyu GTښ[VjݱrA aX5>EOF$@K~  ?Z?JVgGn[變Sj->"  ("3`QXF?ؑ$Izn" FԼ44wp߰4uW/H^  F"3`QXFK=OF$` x:+_Ƣ~{XSSⷦ?  Ɓ"3`QXF`'#I
s֯, 4RTښ[Vjݱr~j-:,#  #Ef=_~2$nW Y)ՃTj͞immO*  &"3`QXFK}8H>{ xrfwϤN^  &"3`QXFG䟈~.$&O}i <9_R{?;ixu%:  3`Qd,ʚE$\}{ xj?0ջUZwlꮜZ  <>Ef~.$fET <5㟙;mّ֦jt^K  ,̀EY3`N~.$Ԛz ਜ਼){$oLMRS{=  ÀE(k,cxۧ$I*W* 2}h|}Y~TjM  ,̀EY3`w\$IR>[ 8pz|7ݙ[Vf|  @>,̀EY3`ӇT$I*z'x 8SR_M  eX5YsOE$
    07Xf2NS$I6uѷ
    07Xf2Ͻ7HBk[    ,̀EY3`+$I*    `(2èe46Haq    EffOE$XW)    1`Qd,ʚK=#HkVjMU    cX5uNE3$I6ؼ2N    "3`QX׽D$X    `n(2è|g:HҪw
    0XfRӢ$I*[_Q    gX5o"H_{B    =Efuk3$I=o    `(2èpSR귣$I*ZS    9gX5D$IRaot    aX5uV.Hª>    ÀE(k,e]'"I
57
    "3`QXV]=D$IRI;5    ÀE(k,ep^$I5    ǀE(k,e'"I
    ǀE(k,ef$I~     (2è`SRw$I*I%ύQ    lXfRIϏ~$7'    @^,̀EY3`)W_~$W'    @^,̀EY3`)W7G?ITP~     y(2è\~$:g:>    2`Qd,ʚKF?ITJ*~     y(2è\0yHB16    3`Qd,ʚK7D?ITHM    XfRợ$I*j_&    @~,̀EY3`)A)!I
s/'    @v,̀EY3`)S{OC$R=HOO    XfRΙ~$]&    @EfzAӐ$I4zim    0`Qd,ʚKzYӐ$IԿ    aX52UWOE?ITHK06    b(2èL4$IR!u>    aX52nDӐ$I%ԩ	    ÀE(k,e!I
~    cX5254$IRo".    (2èLߎ~$?~     qXfRϊ~$z    cX5tN{y$I=	    ǀE(k,U$I3Oyqm    1`Qd,ʚKyz5YH    cX5T,$IR5~     XfR5E?IT@;ׇ%    @,Ef3$I*%    @,Efgg!I
     "3`QX3g!I
w     "3`QXS%YH|]]    2`Qd,ʚKy=E?IT@    eX5LKi؏~$)N&    @(Ef9OB$Pwg]    3`Qd,ʚKY:~Y$ITS]    3`Qd,ʚKY:+^$$IR    gX5t/'!I
hpw	    πE(k,e}O$I*O
K    x,̀EY3`)KF?	IT@պ%    @<EfOB$Pⷄ%    @<Efӣ$I*9~  -    IDAT   XfRM$I*βK    x,̀EY3`)p'!I
9w	    πE(k,en$$IRtMZK    x,̀EY3`)K'!Ik$    @XfRfOB$<tWM    E(k,eiz{$I
qCM    E(k,YxpJM$$IRp;%    @XfRF?IT@k    ,̀EY3`)Gԟ~$ן~     e0`Qd,ʚK9:gRs$I    ("3`QX=ע$I*꪿K    2(2è$I*~     e0`Qd,ʚK9z%9H]Gw	    PEf$IRu/    ("3`QXQ{Os$Io%    @XfR~$g>.    `X5rxbs$I9w	    PEfA$PgQw	    PEfcpyA$P%    @XfR-D?IT@/K    2(2è?$IRf]    E(k,n$IR~     e0`Qd,ʚK9n~$)a~     0`Qd,ʚK9n~$);&    aX5r4o~$)f    ("3`QX1/$Id~     0`Qd,ʚK9f2@$Mv{o    ,̀EY3`)G$I
y    ("3`QX
15/~$);    ,̀EY3`)Ģã$I*    ,̀EY3`)CgG?IT@w~     0`Qd,ʚKK~
$ꝷ%    @9XfR)/~
$o
K    r(2èe?$IR;nK    r(2è2)H    ("3`QX9W$I*/%    @9XfRٯ~
$|).    aX52t$I*     {(2èݏfS$IT+w	    PEf$I*ۛ    ,̀EY3`)C7G?IT@}7%    @9XfRsS$ITw	    PEfw[$I*z    ("3`QXлmOA$Pmw	    PEf?~
$~     0`Qd,ʚKzz{S$I<tW]    ÀE(k,e]OA$P    ("3`QXP] I
yw	    PEf_G?IT@    ,̀EY3`)C$IR5    ,̀EY3`)CF?IT@M    ("3`QXP}o$I*~'.    aX52Hٚ&&    @XfRE?ITHE&    @XfRIh~     e0`Qd,ʚK+.)HBj    ("3`QX`"I}Ko    ,̀EY3`)$Izo    ,̀EY3`)CG?ITH3)6    `X52HG뮜~     e0`Qd,ʚKX$IңuSm    E(k,e>E?ITHo    ,̀EY3`)"Iw	    PEf}OA$Ro1	    PEf~
$z#6    `X52T I
߄&    @XfR$IR!Uo    ,̀EY3`)C]OA$RSo    ,̀EY3`)CwF?ITH+o    ,̀EY3`)CSo~
$7_~     e0`Qd,ʚKz$I*	M    2(2è55)HBs]m    E(k,e] I
ysm    E(k,e] I
y    ("3`QX~
$΃	    PEfߋ~
$Am    E(k,e^$IRA~     XfRGcS$I^zd}    3`Qd,ʚKZS$IY	    πE(k,exMS$I5J     "3`QX9$I*yoO    x,̀EY3`)CgG?ITPO    x,̀EY3`)C/~
$z3>    (2è I
     "3`QX^ I
)	    πE(k,eh/yNS$I5    gX5B,>")Hn<>    (2è~
$\     XfRT$I*;o     "3`QXʑVs$IԴv&    @<Efi?$IR)ՃԚ~     XfRf=A$Tw    L:Ef~ I
}K     "3`QXQwcs$I5L     "3`QX1 I
O    X,̀EY3`)G?ITPK0>    b(2èï_$IRAUW;>    b(2è?$IRA8>    b(2è΍~$_;+>    b(2è|$9H~S	    ˀE(k,o@s$IU߻)>    b(2è/,~$O    X,̀EY3`)Gu$I*~     XfRj$I*q?~     qXfRޚc$I*·~&F    (2è79H|]    1`Qd,ʚK919H~o     "3`QX9뗣$I*~     qXfRi{s$IUQ    8,̀EY3`)G?$IRazf    1`Qd,ʚK9'oA$O(    @Efd)5M$I5    cX5$$IRA~3>    (2è,$I*'>    (2è,w$$IRa~     1XfRzOB$V/Q    ,̀EY3`)OB$V7(    @Efep'$I*ޥoQ    ,ٻsᢕffemjS͘t;6ZyXe5;MYmyQ@夐ȡo@DośC"7A>\~?\sgkd,*K]&W~$FMF    2X̀EE3`CoL?	ITYˏ(    @h,u}`$I5ٶ%~     ,Jfe?O?	ITY[.(    @h,u$I5    d(fR祟$I[]S    X̀EE3`g$Iޡ?S    X̀EE3`K?~$|N    3`Q2̀.xIH
l~nN    3`Q2̀.~$g2~     (fR]7$I    8%3`QX3ߕ~$&WQ    X̀EE3`˟I?ITY/(    @y,JfgvˇB$UOo    <%3`QX3$I5(    @y,Jfgr)g!I*ww
    Ph,o=",$IRyZN    2`Q2̀>!,$IRNyNN    2`Q2̀>ó$,$IR#    ,%3`QX3<Eg!I*lCw
    Ph,g!I*l;    (ˀEXT4sg!I*l    ed,*K}zhYH
sKN    2`Q2̀B~$fnuGo    %3`QXԍVOC$UX?S    rX̀EE3`|M!I*lpw
    Ph,uӐ$I6;    (ǀEXT4:M?/!I*lt?    %3`QX4Ӑ$IvS    rX̀EE3`OC$Uw
    Ph,uOC$UK    %3`QX4<E!Ijl܋)    @9,Jfip3OC$UZo    %3`QX?!I*3
    Ph,u}!I*mo    %3`QXՍ!I*lt_    %3`QX5{{yH
_ylN    0`Q2̀^[L?ITa΋)    @,Jfkz9!I*lv;    (ÀEXT4zM>zByHՕ[    X,Jfk|A!I*'o    `(fRѹN?ITiSV    ֟h,$I6<[    X,JfkpC$U
    X̀EE3`WN?ITio*    3`Q2̀^~$f\U    gd,*Kݺ0D$IRͿrGN    ֟h,usKHJ[    X_,JfmvU'"I**    2`Q2̀nM?ITiϋ*    2`Q2̀nOJ?ITi"~     ˀEXT4/98D$IR?|LV    ֗h,u$I6=[    X_,Jfmy'"I*mOo    `}(fROO?ITk~!~     ǀEXT4^'"I*w
    ~X̀EE3`ʆD$Ug    `(fR]M?ITiwqV    ֏h,tqHJ_zhV    ֏h,|g"I*mwo    `(fR_~&$fw|"~     ǀEXT4gg"IjmVW6    `}(fRO?ITq?)~     ÀEXT4{FH{    X,JfԯJ?ITqó$~     ÀEXT4l0T$IR?    %3`QX0S$I6    %3`QX0OE$UK*    0`Q2̀oN?ITkaw    `(f҆񥇦$I~"~     kπEXT46}uH+    3`Q2̀S_~*$F*~     kπEXT46$I#
    |'T2̀C~*$ןW    gd,*K#V6td~.$fwސW    5gd,*K;;nJ?ITkq#
    X̀EE3`it"I*ē
    X̀EE3`iw$I)ω+    2`Q2̀KK?ITq"~     kˀEXT4vyUH|
    X̀EE3`i@$tq^    ֖h,OHw{^    ֖h,ȮOF$U\o    `(fҖZ$
    vX̀EE3`iOF$U̗    `(fҖɵ$I%    `(fҖ%$IɧW    cd,*K[$I7    %3`QX287OF$tԭWf    ֆh,m'OF$U^ȧo    `m(fҘ}$l$IR    X,Jfg~F$U+    0`Q2̀=ӛ.N?ITqW    ad,*K{&W~6$/+    0`Q2̀=$I
    6X̀EE3`ip$I!?Y    =gd,*K{o$IwY    =gd,*K{z=1l$IR    9%3`QX&ӑ$I7    1%3`QX4ӑ$I7    9%3`QX4ӑ$I7    9%3`QX4?$I٤[ݴwf    h,m]7#I*,    1`Q2̀M_~:$g4~     {ƀEXT46E%IEo    `.d,*Kz@Hʛl;3~     {ƀEXT4v;G$U싟+    1`Q2̀]>~>$nuY    gd,*K&מ~>$<-~     πEXT4v/ڔ~>$򆧿8~     πEXT4v,|$IR>_f    vh,G$Ugo    `(fҮߟ~>$fw|2~     πEXT4{_N?!ITsQ^    =,Jfmv'$I*>    =,Jfmr)'$I*oo    `(fҶ_~B$F_,    1`Q2̀m3^~B$&׾#~     ǀEXT4$I7µ    =,JfwOH$dحWn    vh,3$I?    u,Jfo3$I78    u,JforIg$I*oto    `(fҾѿ]Iʛ||sf    vh,{g$I*ov7    X̀EE3`i_?~F$nu-    1`Q2̀e    IDAT]7$IO-    .1`Q2̀e1-$IR    %3`QXOI$Uo    `(f&W5$IRMm,    1`Q2̀e1M)Iʛ}    %3`QX租$Iٴ[Q    y,Jf,1OK?%I@c[    gd,*˂شWZ$    4%3`QXI$U7    X̀EE3`YI?'ITy΋,    3`Q2̀eq/=,$IR5~     ;πEXT41<$Iww    sX̀EE3`Y)$IRNxfn    vh,wcI$5?-    1`Q2̀e=$IR卯<.~     ;ǀEXT42OJ$Ut    9,Jf,Ǧ$InueCn    h,e~R$zXn    h,epo$Ij)ώ-    3`Q2̀e{bII    <<%3`QX|pOYIʛ\sJf    h,gvg%I*ov7    X̀EE3`Y<sYIڛ}-    C3`Q2̀e.$I?z    <4%3`QX`J$5    (fxG=5$IR/?~     ̀EXT4^]7$Iߝ[    dd,*b}q[iIʛ)~     ̀EXT44ٶ%$IR]    (f~Z$o    <8%3`QX~Z$F*~     ΀EXT4?%Ihr    xp,Jf,$I7    <(%3`QXϧ$Ij1~     ̀EXT45%ISw    X̀EE3`Y\O?/I@^[    fd,*$Ij    (f=#$IRM;'~     ̀EXT4n6M?1ITy{n-    2`Q2̀e;$I;w    X̀EE3`YlO+$IRN|Vn    h,m|'&Ihtw    X̀EE3`Yl_~b$&=1~     ɀEXT4?i'&IhvU    N,Jf,}0$IRߕ]    oad,*}3$I?z    |+%3`QXSL$5    [(fFL$5    [(f~f$77~     ʀEXT4{O$Ij    [(fV6t}&Iw    (ff^~j$'zn    EXT40&Iht_    X̀EE3`Y$Iz&    |h,aO9$IRn&~     `d,*rS$I-4u.    (f<_J?7I@c[    1`Q2̀eyLo8$IR    |h,c|śM$5    kX̀EE3`Yó_~n$/-    (f<'jIҭl.    h,ˣwu|~r$G>%~     ,f,=7$Ij/-    h,ez{ON$5    EXT42$I4w    `l,*r$I4_bn    X̀EE3`Y.~r$z>!~    3`Q2̀eɬljI    K΀EXT43$I4w    ,;%3`QX䪷$Ij'[    `(f|F$I4    ΀EXT438WN$|r+   @h,˧wcAJ$    ̀EXT44qSIw    ,3%3`QX~z$&W[    `(f~z$f_[    `(fxaIM{o    XV,Jf,ON?=IHc]    `Y(fV6t'Ihx+    ,)%3`QX'Ihcw    ,+%3`QXO$5te    h,kx+O$5|x_1~    22`Q2̀ey$I?)    h,K,%IROIv   %dd,*ruc	J_zhn   edd,*rl;3%IRM?{an   edd,*r}`$I4VW6o    X6,Jf,O?AIH7Dv   ecd,*rC$I4<    ,%3`QXʆn>;%IR/98    1`Q2̀?~$7[    `(fxg(Ih޻3~    1`Q2̀/O?CIH?)~    21`Q2̀~6%IR#N}Av   ebd,*uA)J_|@v   %bd,*S$I4    ĀEXT47S$I4    h,ox+OQ$5R'o    X,Jfp[~1%IR#    h,|$%IR>_v   %ad,*_7s$I4    EXT4nrQ$5w    ,%3`QXy~$z>!~    20`Q2̀k(Iips    ,%3`QXAuyIJ    h,|ϥ$IjΊ-    X̀EE3`M~$wo-    X̀EE3`ᛍ.$I{o    Xt,Jfo$I4ߊ.    X̀EE3`$I4׿.    X̀EE3`Ϳ$I4ٶ%~    3`Q2̀o7g)Ihs    h,|%$Ij    ̀EXT4K?KIH3~    "3`Q2̀o{O$Ij]    `(fwX;OS$5.    X̀EE3`Lo84%IRw[    `(fo="4%IR#y|v   Eed,*de)Iipʳ    ,*%3`QXx I?MIH6~    2`Q2̀K?OI@O;    2`Q2̀3~iyJ{kn   Eed,*f$I;G    ,"%3`QXx0-/K?OIHύ.    X̀EE3`'<%IR#/]    `(fZ͇$Ijo    X@,JfP/M?QI@/    XD,JfP[H?QIH?)~    1`Q2̀2$I4x.    hX̀EE3`'D%IR#/98~    1`Q2̀K?SI@/.    `X̀EE3`L_~$Օ    h,<#T$5R?]    `(fnyYJF    ĀEXT4N}T$5    ,%3`QXxX+S$I4    ĀEXT4vt*Ih>    EXT4vx*IOo    X,Jf3[^~$ҷ    ,
%3`QXI?UIHGo    X,JfSV6v}*Ih    EXT4vt*IZhV+~    "0`Q2̀5zDJFg    ,%3`QXY-/K?WIHw    EXT4vV}U$57o    X,JfV6v}'+Ihv    h,?~$&nu    Zgd,*b7$Ijqψ.    :%3`QX3^~$Fiv   (f®$I4    3`Q2̀]~$f_ܖ]    q,Jf7^~$泮wc    ̀EXT4vV$5_.    2%3`QXUS_~$FMv   (f®g+IimKv   (fo+Ih~    Zfd,*cz+Iw؏o    hh,WOW$5`s    ʀEXT4vg$Ijo    hh,<|%IRMo<?~    @X̀EE3`awwܔ~$Օ    Zdd,*k3W$5R]    E,JfF&|%IR#    Zdd,*kpү$Ij#    ȀEXT4vWGw|~$7o.    "%3`QX/}:%IR~.    %3`QXkޖ~$>=~    @kX̀EE3`aO}u	KF'    Zcd,*{/$IjGO.    %3`QX#uqK}    1`Q2̀=53$I-4v7~    @KX̀EE3`aOMzkKF    -1`Q2̀=5~ƒ$F?    Zbd,*{X$5o    hh,u~)K)    @CX̀EE3`a-Loޚ~ʒ$z    0`Q2̀0zd)KFw    EXT4𝿟~ʒ$m.    
%3`QXX#~ʒ$77~    @+X̀EE3`aMl;Y$5м    `d,*kezy,IƟ.    %3`QXX+6$Ij;?~    @X̀EE3`a,Ii|Q    Z`d,*kwY$5o    hh,ϥ$Ijɰ[ݴwv   (fZ|$I]    v,JfF$I4:    jgd,*kip¯$Ij7o    h,uqYKucv   (fZ~MYKϻ!.    P3%3`QXXk%%IR#NyNv   (fZZ$5M    jfd,*kM?kIHϼ/~    @X̀EE3`aͭlO[$5|pw!    @X̀EE3`a=L?IiKF    2`Q2̀0Ӗ$I4<o    h,i/J?mIH+]    V,JfzӖ$I4    2`Q2̀2$I-4w?*~    @X̀EE3`aL;;%IR#    52`Q2̀2zk[$5輿.    P#%3`QXX/$I4    jdd,*wcn>K?qI@?]    F,Jffw^~$zpv   (fz\$I4    1`Q2̀4:'.Ii|A    jcd,*_L?qIH^]    6,Jf6uaKVW6    h,mI?sIHc]    &,JfW)%IR#zEv   (fz3$I4[    ĀEXT4[}\$5k    ĀEXT4ʆn>;%IRͦߓ_    ,JfP$Ij	ό.    P%3`QX(a|.Iitk    EXT4JS$I4Y    jad,*%}BKF    0`Q2̀Rܒ~$zo    j`d,*L~$g    50`Q2̀RFmKF_~Tv   (fB)~=%IR#n2~    @X̀EE3`ށ4%IRM/    fd,*%dKFW    (fBIOJ?yIH:~    @h,4<'/Ii    i,JfPRO?yIH-~    @h,#nO?{IHx~    %3`QX(mz$I4<    X̀EE3`#^$5wCv   $%3`QX(mO?{IH[.    dd,*xrKVM/    bd,*ŭl;O_$5R_/    bd,*	ޛ~$F    ),Jf0~/IimKv   %3`QXHӗ$I4    (fBBu|~$zX~   %3`QXH}3/Iix    $(fB_$5Co.    `d,*)s_~$f\]     EXT4Ro$I4v/    Ph,l$Iv񿔿_    0%3`QXHzeG@$5輿.;d    IDAT< 6zhhD		A{L@&!"pMOw	t3ә3 =iUY9^l-Yv"Wy%,7xF>9UR{_շu'     3Efs' I*Rwe    fX5"' I*Rc    fX5"5|[$I8    ɀE(k,ZvX*碟$IH/a    (2èh_$IREzZ    9(2èho.~$"-v   XfBE~$*:ib    ŀE(k,D+NzCJe$IREj    r1`Qd,ʚàPS$I}ݧo    ŀE(k,w6)HԻ    r1`Qd,ʚàD?IT4    r0`Qd,ʚàq޻$IP5,~   XfP8U)A$UW8~   Xf°?=9Hݾ.v   Xf°~vs$I    `X5EkǢ$IJe    "3`QX5<9H
ռ    7Ef04ƾ'!I*RU    3Ef0Lz^$$IRE=    "3`QX&WF?	ITib    "3`QX&$IP?G/    0Xf0)N~c$Iyi    ɀE(k,G$IH{/]    `>(2èa3DI$Mo    O,̀EY3`aشd$I~    |1`Qd,ʚænQ$Iuٿ_    `(2ès«Ru$IH/    0OXf0?qwӐ$I]    Ef0:w4$IRUwS5    Ef0Z_!I*T~    |0`Qd,ʚèG?ITo    Ef0C$UW/    0Xf°=!I*ub    5Ef0:7<$IRj    "3`QXV͋ yH
պ    "3`QXVo~$Bu    "3`QXf勏F?IT}.    0Xf0<H
U    %Ef0~*H
պ߆/    0Xf0k'"I*T綵    %Ef0ԖRL$IRE?    "3`QXv'wD?ITTr   P,̀EY3`auL$IRj    "3`QXv+?L$IRܸ2~   bX5]c;$IPGn
_    `(2èT^~*$*uibo    ,̀EY3`
z3H
8    EfPO~*$B    "3`QX%~*$Bv-~   `X5X H
U6Oa    P(2è(_|,H
X0~   CeX5"I*Tk~    2`Qd,ʚUѾ/$IP/    pXfBU4~.$B/<~    2`Qd,ʚ'#I*T8   C`X5=OF$Ue.~   CaX5'#I*T    8,̀EY3`JZW~"H
5ۢ    8,̀EY3`Jkd$IR*X    fˀE(k,TʲSz)H
\{7    ̒"3`QXC[$IPN_    `XfBtn>9H
{    fˀE(k,TMD?IT4q«o    EfP5F$UE7    ̆"3`QXǢ$IP?~    l(2è*"H
ջ    fÀE(k,TQOE?ITKib    fʀE(k,TQF?IT+   2`Qd,ʚ#I*TO0    0C,̀EY3`O|$IR    fʀE(k,TUwyG$U|Xvx    3aX5u'$IX~    L(2èj}G$I?a    `&XfBe-;<$IP{/a    `XfB$IR*?~    L(2è*|R$I柅0    0],̀EY3`ʚ|$	I
a    `XfBD?!IT;.
a    `XfBՕ/>$IR    .EfPu]WD?#ITi    aX5}$IXKo    EfPu$IRu~    aX5*o)OI$U0    0,̀EY3`O~J$b~    (2è:ynS$IuGo    8EfP+?$IR~v    cX5꠱OI$U;o    8EfPOe$ITY    DYqLʀE(k,E-I$U%	a    ;25.LKRwywW*_|,?eX5sII$Uηa    CzAj]z\l[z{iߍsrp,̀EY3`.|89I   `.*S{xޔH(2è:g$I3K*0   PcS󋿝6{e*_n짉ewb0EfP'勏F?)IT&   ek%S4d'G's	@,̀EY3`N~R$bun==   Թ۳5Ncno~,̀EY3`N~*II   =)oM,,̀E(k,IF?)IT~*NzC   W5nQjo^;֧]iX*N>fX5je)J$U%c   z;25.LKRgۚ⮔45>fdX5g%I*V[g0   @5L}PSRo֔:TZ?C3`Qd,ʚuӽg%I*V{o   `^?Mx&Uƺ`,̀EY3`nZW~<YIU81   YqLj[ڛw!ԭg@,̀EY3`nk$IRk	c    cGڅqIl[sࣀz4
57~?2`Qd,ʚT^~Z$bun[    Y>
RiTk}`0EfPGD?-ITOa   Wz݁3{S*'F5Pպ7b0EfPGO~Z$je*N~S   l^;֧]S?g׺ߍXfB5/pӒ$I̯  
;"5.LKRgۚ۳5^;*W,K2`Qd,ʚuT%I*Xχ1   +V/HS{x=xCJJE>-(2è*_|4yI   xE*VG]۽){ڠ`,̀EY3`;/~^$jorc   `+7/MSﮩѕ'` EfPWk?$IRk];   jkX06.ImkRo֔::3(2èj%I*X/1   Paqjo?Q@}?'yn3`Qd,ʚ'&I*V1   PAcSsݢT:|MgXfB$IR+V%  6~ԁݱ>J,,,(2è:w$I3uc   `hg3GvJNzgXfBMӒ$I3}]   QRs2z7/Guc7c0EfPgP$i~   9+MuR{yy*?c2{?fX5jml$IR+2   0Ə?[W;֧])\l2"3`QXC߈~f$6.	c   `֖~`?N;I'J׉q[CXoye EfPwO~f$u   *V/HS{xޔ?Z"9/(2èk^g&I*Xw   bkSsݢ޼tꣀ}G
{?fX58L$U~   0Ǝ<Q@Rﮔ~̪Qns@,̀EY3`aLԒ$I3?	c   j]z\l[z{mFx?fX5FAwOM$U"  cũe<voJe\O̀E(k,5$IRÉe2   T_򵩹nQjo^;֧rC?JSN`0Ef0
'I
e   #Scڸ$u{wTĕ^?oXfHXz&I*ore   j]z\l[z{iD8+M3(2èQrGs$Iww   5VinX[SoTF*R̀E(k,F?7ITibo   +V&5-JKSw$լrCoXf¨h]&I*Z2   ̳#ScڸdꣀOܕRُTĿ?2`Qd,ʚbI	   Q@[NI=[S4B*_A{d0Ef02ON$Uɿe   bS۽)ų?jJCS'((2èQ{ON$U^gsϣo   nEyiX{wET)uw`,̀EY3`atn:1I\{   ?aȩom\:֤wE)Ux.-3"3`QX%K>$IREzZ-  0RsԹ唩{M"E6(2èQR''I*Z  ()V>5/|joOݛR9LR-+[?fX5FMN$ULoe   ji1nQjo^;֧]S?IP5Xf¨<Iֺ[  ƎHSkٶG?I[uXf¨i_N$U2   USԺKozޚRN߯:`,̀EY3`a4O$I  0+VG]۽){tfX5F򣧎1ITO  a☩a}'SKS$&!4Xf(?qwӓ$Iuo  ƎHSkٶ&l?%ՠN#k(2èQԹOO$U=2   X 57,N->
Bc橲?k(2èQ4o	H$ͦrSiba  \)NzCjc]*'KRK_̀E(k,ƙo~z$5{  `VƏJsޕڛwWJecƾMdX5FҲ[$iֵT=  p0cGڅSmMٚR#!,z@,̀EY3`aT'I*Zo  T^(ݛ~$rbo/3`Qd,ʚ}_E??ITպ4  0ǦE>
htOJ*Z'ÿ1"3`QXU$IRk^{  G(OSﮔ2"I5|sdX5FU){OP$US  ߚZζ5gkJV@j\_̀E(k,F?AITO~   W^۽)ܑ4bZ`,̀EY3`au%IRU+˩hg  (VSTHO6?Xf(k]'(I*g  !5~Tj]ZW?5VݕRُ1F~d Ef0{{$I{  owI=[S6difX5FڲR%IRE+?=uO4  @V'ܰ8Ml<$ͺuXf¨=pm3$Iq3  )V65-JK>
p!4NZ3`Qd,ʚnߒ$Imk?~   sdXpꣀϛG!IZ_ȀE(k,g(I*\  `Ժٶ&lMیCfX5F]-
I447  pJs۽)s?MHP_̀E(k,(I*\3  +^楩c$ln`,̀EY3`WD?EIT:[Og  `dk%S4Q~$Mޣ-g Ef+R㣟$Ip	g  `>
uqScޞ)u?HR=rsv3`Qd,ʚ"5OQ$UL)oi  c:7JOe_jWÿ3"3`QXibl%IRu7  TX5nQjo^;֧]g$D`,̀EY3`z}#9J
qQ=  1vdj]85(wTzIz]}XfLRIV:M,;, (SSRo֔:^սfX58`hIC~  @(un\z\ƾS]4Xf'!~$µlM  Y8&5-JKSw߻߱IR'dX5sߏ~$) y3vdj]Zζ5>
׎>%IX[ga Eftw\$%IRwS} @LU    IDAT=L}v{x=xCJ"$CO`,̀EY3`ioOR$U  fjrݼ*7rZɯ߇̀E(k,#s~-IJݾ. V楩c}ݕRYFҒ}&{(2è#S,%IR+_AXvX]  ƎHSkٶ&lM׎>%IC1(2è~\$Ix~  0Rs)uX4䵮:>(2è~\S$Ixk2 U;Q@}&voJSXTZ?=Xf?yG$Ix4  Qqλ>桻c}ݕRYFԺsdX5qo~$کX ;"5.LKRgۚ۳5n+ʕ$մ@,̀EY3`VHӔ$Iyɇo  X 57,N->
B9+I~ {!(2è~Z;4%IR S<65-:Q@;/OOWI҈<=̀E(k,ڛKӔ$I| `G9:0Vٱ>J,OUI~qDL2`Qd,ʚƹ4%IRj|w  k%mMٚR}Jtg3((2è^Q)uS$U5k  aqjoOݛR}~J4grU3`Qd,ʚޣߊ~$> +Mu|SSS98ÿ2"3`QXun=-yJmbk  f`tc}ݕRُ,%IXf/uqS$ՠ_+}  56.ImkRo֔RM,?:1(2è^^-S$ՠk  8X`j`2z7|(IRxcGf0EfV'*I*^ `^~ oTP(2è~ˢ$IA5< ^Fjݟ=RTg$IC_Y<}2`Qd,ʚlK$IAk" %mMٚR}IT}_Xf?[wE?QITz3 bܰ8M,>$IM'3`Qd,ʚ0vd*$Izn*V> rצEScԿ.I#7XfL%IRj] `kN}PwywWJe?l$if7eX5sg*IjPwEw @G.=.uI=[S4O4IF="3`QX`ߍ~$ @Js2>ovs$Iz:w|>nXf+Mߋ~$5-
m  Z5SwN{ݱGIJԹ[3`Qd,ʚ\{$IAO
k  ؑvajm\2Q@'JGY$ieX58_~$~  检:z{iDT$ikO΀E(k,pp+(JT )N~cj^s{T6_>$I<7[բo΀E(k,ppT%IRMj
m  ^N/GJ$)s3`Qd,ʚLOU$ՠ	k  ^"IF+XfuEs$IuJ׆6  ?ۣ/%I9~pp,̀EY3`i_U$դ%	m  ~REI$)s3~%Xf\%IRMu~m OGI$)soA88Ef4R~$?|2M,;, {&?P$V'2Xf{'+Ij_<D6  寎>$IRi1`Qd,ʚL_$II- W^}I̕τ L"3`QX`}0J|{m 5.>$IR?~0[̀E(k,0}ŉ l%IR*T~K} 0q޻#Iw LV3`Q`,ʚLg+IjRk~  L[g%Iz~0=,̀EY3`n?/JԻ `R}Iv-azXf3g+IRǆ7  <2$I}A(2èfq/G?[ITZ sӉg$I\7cX5OF?]IT߹$ n_}I̵t(2èfݯD?]ITib `jY$I2׺7cX55~$F5/@} ޣFD$)s͋?~0=,̀EY3`kOW$ըg7 h?{I$I287cX5RW$դĲo `dO"IƙoAEf|%IR Q,!IbŀE(k,0;O~$Fun\~  X $Iw6
1`Qd,ʚNs+IjT 0gj)$I2W*a3`QX`vJ9q/8 i^3H$ewW(2èf}OX$ը5~  cg$I\oπE(k,0{ݻΏ~$F~  }>$IR;/A>Ef쵾OX$թSQ gE_A$)s;	A>Ef5|[$I5u'o `{e	$I2׹qE(2èMg,IjTo `pG	$I2޼4aXfwW$ISFXqL Ǣ/ I!aXf}_F?cITZ_ cGF?$)s/N´(2èMcoF?cIT~9 FC-ѧ$I
1aXfWmF?eIT4w P{IFqMȀEY3`C{,IjV󒏄8 @5/p#I/T"3`QXunY%IR޳! ꯽>{$IR:E(2è]s,IjV|1M\ [SI=73cX58tŉ %IRjn; ˢOIc ̌"3`QX`n79Kս wF<$)s]ofƀE(k,07:%IR*| 0ʉgOImkofƀE(k,07Z}49K9 @M8&ԑ$Il(2èFzAs$I5; Y>u$IR@CfX5;~Ғ$fųib; ѧ$I
yfƀE(k,0w߾0IKo9 @ϢIPsoCEfi]'-IjX ~:}Hǆ!̌"3`QX`4'-IjX41vD KWF9$)w3`Qd,ʚ̭OD?kITÚ' ䷣OIsA9Ef,YK֙w P#KeG$ew3fX5[i$I5|) 8IP;!̜"3`QX`n5g-Ij J}H:[OC9Ef[vx*G?mIT:  OIP?C9Ef}O[$հr41vd T_gOIPf΀E(k,0}:iKּ P}>k$IR@uf΀E(k,0;iKֽoo D5$)_C9Ef<?*N%IR+/^  յ)F$,	E1Ef=%yKּC P]e9#I*gfy(0èG'D?oITӺ\~  պ$I
wfǀE(k,0?/yK֞H+	w jjof$IR@CEf<Y~tJv$I5uq PI{/>e$IR@ݻ~0;,̀EY3`{'.IjZ_	u j?s_)#I|sy(2èO$Ikf*VZKF$ԺbX5?/N$I5c P-IF+e<Z~tJv3$I5w{ Wc	#I*N[1`Qd,ʚ̯cۢ$IkN*NzC TGgۚF$E黎#ofǀE(k,0:7%IRk]u| TGoF/$)rwgX5_%IR=|c TGY<}Hzm	C=Ef*VfK$Ke) _q/D_.$)_E=Ef.Ij\' _F-$)7[-(2è_S$Iqgw ׾g$I
u"̞"3`QX`5^S$I5o/2o `uw^}H"̞"3`QX`+_R%IRl\ ='$I
8ofπE(k,G;$Iq3ib No>W$IRTVXvx=(2èl=5Kܰ8 SE*$)"Ef@%IR, Sѧ$I
ƀE(k,Gu){O^$չn3^~  g$IYso"3`QX ۣ$Iy 2Ke\"Ij_{CbX5ȧsiO^$ռ#7< piE$ֺx(0èi^'/I^Y_
{ Ѻ?D_($)ƹ~phXf^R%IRkWw 0<:>}H~phXfy;K{7 0<m>O$IRT4{CcX5ȫs^$@s# WmE&$)]̀E(k,WsG?{I4u<7 5[g$I
#:Ef@^צD?}ITib e<,$IMV{CgX5ȯmO_$@K  VoD$$)UǇ#:Ef@~N~$i=|c ?*DI"IkpXf5/|ӗ$IPY~  1~3$I9&a:f@^R%IԹiU h_SD$V6_G,̀EY3`_$i+_z<M~  }H?#an(2èbE?I4"5/` d6vD*/D!$)o"3`QX FD?I4"uwm} Z	"IkW7	st(0è/$iSq  }HZ_𛄹aX55_$I҈Ծ} |$Ij𛄹aX5Ӿ_$I҈߻+ 29U)uC$EVn9aX5$I9k 0_C$W{8&afƎHec_I4"u  sg$I
no"3`QX VﾯF$I#Rޟǆ? @I4uufM1`Qd,ʚjo^e@$P 0S!ܐ$ICŀE(k,q;Hw `I45w	sǀE(k,laTI4B5{w ̋+OI4~0wXf~9K$I;և? <;"OI\Կ<~0gXfZW@$RV*N~c ̭ƺߌ2$I|{]y,
eΣ-;[J48clCĠ+>DM4&ӭI5ܪ
(Fd'Ayd
ϼYq`w_JzeQ{1`kO 2ӿ~Imx ѵ%XdBV,R=  -RG~$IV' Ps%XdBV,R=]_s  L?$I-ѧ P"6,z,2`!+  hǅ@$ivѧ P]7M4ɀXzTl󒔪2I  ڤbWA$i+Ae :M4ɀXTwu  ߋ-IR>+ (26gB$2` eNA$i U&XdBV,R}' h$IҚ7^rf9 M4ɀXpO	 xw$IZE4F @MDXʀEW a;H$~6  jef?"T5Y  Zhtw$IZ7}F  5Qx 6dB$2`Uwͣ FT,~y-$IVbU {}ɀH,de"լy<4  -48{*$I\E @/1>dB$2`# GB$i~^  H;~hn2`!YHg ~*$I+)Ue  HwoM,D2`!+~ۿ&i  Z[H$_> :)GpEsXʀEg[ [H$={E @~h2`!YHlx R$I3㷢 fF~h?Tz,y  ڪbׅC$^]  o(XdBV,R=+z< 0pq=$IuR]ѧ P3>h2`!YHm|O RUoy*z~=$I~> *v|CˀH,de"շ %$ICO fޣ35/NeB$2`[oD? @Uݓ:6$I6IiXD @͌(NfB$2`jR,  Zgo"I4> ];EsXʀEw~& +ݒ:SD$9y    IDAT|  ~hn3`!YH~& HO {v̀H,de"ջbF? @˕w &$퍮9,$  hK*XdBV,R+)  Z~I֊m^<  ~Yyo},D2`!+/9  Zn|7$ImmpڿF @M[πH,de"տA~* mw$Im|K  w.VgB$2`R r$IjY}  5m{EsXʀEjF[O~. S"I/  ԙnπH,de"5\  {E$b7T?/ ^QXdBV,R3is ?᷑$Imhxџ @/1^QXdBV,Rs-  H~I4[h  <~(O,D2`!+9.V x_~I4O| ;9fQXdBV,RsO _i}I4-0Uq X{4u-ʒXʀEjNVOi<~6  RSk#I&	I xY7eB$2`x w$I?^MݢlɀXf58 FTlHIwG?E2`!YHͪ ~I4Io?7 hbׅ-ʗXʀEjXSR}O ~
v$In';  UEDԼFWt  <ix$IgD 0{wfB$2`W~:  ~f<Lݝ-F$uyw': s.|+ȀXUlq 5H$5񒳢?'᷋fB$2`Yy o$IXoD R,~yɀXf68? _0I&6q !ʟ(vQXdBV,R3y ~'IԤ `u: ~QXdBV,RC~B  ~$Is?gB$2`} 'w$IMO_ VWwMoπH,de"5~B  ԙZ'V$ 4HUd槳G0ʟXʀEjp[nҨ  <Eؿ$Iq? `uo>)QL,D2`!+ٍ|z3 գw$IeK7F\ 38dB$2`{; xZ~+IT< &z'QL,D2`!+;1 xZ`E*{U$IR*mbY4 4~,(QL,D2`!+  <UJ$թ;F< 4;FqɀX7h Ue~w%IPӛf4 ^]-XdBV,R ԼIF7 4Tﰏ2ˀH,de"M@KUoys Gy$IR`}ޝRUE$ MTUoI4;*9 xF#o&IB{.8 \vK=XdBV,d?o g58o&I"a FW~(6"4ۼ$r  <x*u$IR_e @OFɀXɩ' Y?&f$)g [ofB$2`&Y߈~R  VwG&Ir)UUG/ `?ɭ35/Ql,D2`!+irO
 J/IN$i7LC7E 7FɀX	jj^;Y Xy[N$asF `pƿ5πH,de"MV+~V  Vn;%I[w_ X[ݽ~(>"4Yp JK{%IԼ4Y `TGSg3`!YHS<i X%*~$iW `Bo:1Q=2`!YH㢟 UR=~_*m~?I4_bY+ 0!s}zdB$2`&q~Z  V'If'E #"4y[(r  ~CI6O :ԼGȀH,de"Mfϋ~^  VY蝩7$IkRӛR<  qTXdBV,d68_ 2^7$IRyץ wjXʀE̊_  J0$iu=	
 L}>ɀXɭ' `T˗b_	$IZ{#0 _}^ɀXmxޖO j^k%IJ[Q*!c @uTXdBV,O R$=[v &Tؿ	uTXdBV,75/U  ٯZU$IwTU *{UzeB$2`&~f  Co)I~bץX1	 L/"4`3 |2$n{.x &)yTXdBV,҄`TG?5  k=SIIh &\?yTXdBV,7 `(u~SIO SU_~~ɀXɯ_E?5  kep7o*IR{E! 0{{TXdBV,W,Քƃ `͍*IR*zA*I o3"ԎKΌ~n  JTlJԢF -;CjXʀEjG  M'JԎ> -FrG̀H,de"bצTUO ZJ4@J(c h韢}ɀXTsy Qᷕ$ir- Zdp	TXdBV,R{' `VT+Hv$IWKR: ezfB$2`S Y3ԙn%Inʻ. Zz;H΀H,de"k Y3<oJ4!MF7 =o!:"ԮgOE?;  R$Ioxvџj @Kp-zgB$2` (n;K6 hQ/ux^=zgB$2`WMO ߑm_~gIWo4D -5iXʀEj_~z  fx`[KԜ-UG? HπH,de"o~z  o-IR3T=~_G r7I]gB$2`Y `NNb%IwIY @U~ɀXv6pq 07Q{KTϊůHO~i ~ɀXvD??  s?{n~sIUhTwu BXʀEjiSR' `Tߗ_wIjQRyO  OvSgHjF,D2`!+/9	 S7b]xn/=?c	 I[#1ɀX=O / un~{IZAzJ /;IɀH,de"uR ]{̯P$Iy[~x| S;)VRc2`!YHnx @ӿ>1$elFi|w?~  |[IʀH,de"= fpK-7N /QɀX7Tu~  7$i*mʻ. xF?~3YɀX$7) ȧRυ`ٯeџ4  Ϩ-OMjV,D2`!+I> US7$^IC7G  <	ԼXdBV,U  `f~IֺοK?Y  VwğNj^,D2`!+IӍ'9 oOC?~IּD Xa:[n~?yɀX$MG?G  1;$i.?Q hǇOjf,D2`!+I3M~  bHR5pUO U?S7XʀEO^k ǈESϥT?9  Vx_~GɀX$5I e"Inj^  `KɀX$=ԼT-#Y G$yitñџ  kdp)56"oxv @ Dm&IzbWˣ?  LUbׄTjn,D2`!+I?_wwD?K  PSφg{nGT  Xc]XdBV,~r٭O @=TU/$QҰ4  X+3-R3`!YHm4 hԪ毛. 4]wWjt,D2`!+I\wF?M  3R;So5Im_Ʒ ̊+5?"|	 vF?<$u~IҤZ4 5?<R3`!YHzg}#y -K-~IҤ?)< FYj~,D2`!+IOWӛq gP_q}I$Tl+itaO; WjV2`!YHz{~  j|TM\wRO: ^{KXʀE358F?Q  V=vOw$5I+Q/) 3~si22`!YHz^ D<MRco 9U?u~{i22`!YHzw\L _9N~IRT=vw 0熗~{ir2`!YHz') h᥻:7$ծᅋS  >41ɀX$=[b  V躣RgFw$ե~ ߑ:S0MN,D2`!+I+kӣ* F)*;6毗g|-Q?Y jx&*"?SO @Tߛ{?ᷜ$E  DwcXdBV,Vږj" hQ?$O] Z|LXʀEҪ4 @c/a?Ft4u<\ 3?.eB$2`*
 K/Hv$iyixQS [3M\,D2`!+I:z' ѪC3NfޡI;W Z(2>dfB$2`M{  R9N3:S;IZӊ_F7 iXdBV,Vd L񭧤bۗxZ-pfg ^2;6^DfB$2`:_l L̯߈$iUT>xc	 PKkXdBV,V ,4d癟j}IU4 '}!nfB$2`:۽*rt LkRw=IiŢMRH z+G~E4"m `2zipRg7`?3 NXʀE?O D+4uwORT.% hw>dgB$2`mq+/ 槱HXww_> RkfB$2`&94 hno$Mf=7O[O~  k|7&?"5wЇ/ Es@IQ%;2~  ԟvXdBV,֨uR=O @T63$%5b7T4 ƫo<M~,D2`!+Ik❢0 V]sX*{e=(9uw'~l9~  &=<#"5oG?a  UO3-ul~Jo6  ̾QAvdB$2`6\ ZuIO;  ̑o>'"ipW1  RJ[OI]7%65/4^zA 0kdB$2`6_R9~  Vgn;QRl~*_
 x/՚XdBV,ֶߍ~  y"/\E}ONr+ hM'߂jW,D2`!+Ik[E?e  <jipg~:C(i4) @+PʀH,de"i^V w:֏%YK#>KJ ֪:w+eπH,de"i6^}s *Y>?£GIVipf ox7ڗXʀElu UT>[R]zAp\Ja [ZXʀEl5' 0k ,HV/%%='۽j槭L  +oF3"٪碟4  @U,{bȲ͋oJu-04Qs  Q̀H,de"i*z~+5  Ԡ;9&>푪 Xѿ2`!YHFW 25S!:SoLiR*v|"h٭ XM?1/T{3`!YHzo  |?SgߚR+<Sye XC>~[ɀX$vC7G?m  ̲h]O{S{?ZܧR*G| XKՊSgzwڛXʀEl78O  s?ᷧTV  &ڝXʀElWl*_ @[푺{+"48+i|E)?  ̅J]7=XdBV,-'G?o  dT.%Y~JsYwfYID  LߠXʀE\;Ϣ7  "T?_~Jk[RѕNF	  ~J,D2`!+IsR' HxWNr*}i*b?IhR$ d;΂SɀH,de"i^c @]i|)O/
UX?itz?-  oUi:"O  uTSyip΂mU-lށH*O  uSdB02`4w}? eE;~U7&b47hw^x=  57;Vi,D2`!+IsYD?s  4ɠKJ3{3uߴj^V/x'hWX Vi,D2`!+IsMU +?Tl|    IDATVkjmRM~%  kZtùH,de"i^KS (^FW8;9Um^į:waT 	38{πH,de"i$  sz448+b_	5{۽*48g~tb39  &x/πH,de")Gϋ~  hr}|YQ=`3*jx6i|)Zq?M  #c2`!YHQ迌~  h塛躣̯ޡI[;T7RO9cS)J  `Fo/eB$2``  OzSyQEwLMnz|8N4l4z䶙1  35/~)"\/6 T=r{vN]u@3?t}-Crm;Rϧy[IOS |9ޖ&"\;q?  @zT}Y4|_?aM}~7uwyK*yILӌ[}b7~gW,O^K]{8|Tu>  ̍A'6	ͥˀH,de")g[O~   O&)"F3KFW쓆m?Lg|-NO47ԟ?Yށxj?tܧggNי?qx3Udg4k  FW~;s2`!YH     P'ݽLɀX$emZ~G     3{.\zXdBV,r78g~     3ͥgˀH,de")wvLi<~     hjpͥgˀH,de")э߉~     hY\ZY,D2`!+I`    @%ߗK+ˀH,de")yɏ@     Zjt>ߕKXʀERTӿ    FUm=*ɀX$EUlFg    zjwҪfB$2`âA     ZwÿV5"]     T>xCL~\Z"ʻ/~
    h	:ɀX$E?O!     -PuJ/.N,D2`!+I-X?U    0.N\ZXdBV,    I6b+¿V7":TlҔF'    	5j¥5ɀH,de".>0I    `Bux{ҚdB$2`T{n$    0K
\ZXdBV,E     &L-i,D2`!+Iu'E     &HԙZ'oiM3`!YHUKգwF?     Lw)oi-2`!YH[34    0[ZXdBV,VStG     npW¿6":6b    b-m,D2`!+Iu[S'    0ni62`!YHkΎ~"    hA'ۼ${ni62`!YHk>D    @Ëw[XdBV,j:|xI3	    @qKXʀERI     dt>mKXʀER+jG?     4A9Nݝݶ4ɀX$ս;E?     4ÿӖf;"Wlƃ    :sﴥ΀H,de"	~xHs	    @o>)li.2`!YHjBsf=     O{¿˖""4iO&     54ﰥʀH,de")x	    @ﰥʀH,de"Iw_l    P#}WԼﯥʀH,de"Ig    ﮥ̀H,de"Q_7Ut    P7:]KsXʀER    ﬥ΀H,de"qmTˢO     \积ɀX$5[D?     瘟ɀX$5b4D?     (2uW-ȀH,de"W
    @+"Vq3
    @F]?-̀H,de"ɍn86     ݴ3"&D?     d2便ɀX$5R     2拉ɀX$5ޡ~J    c%g-EdB$2`kS     Pww-dB$2`4	    92XdBV,&uRO*     s⿇2`!YH~*I    `o:!g)2"i\vk
    l?KɀX$MR?    0KFXʀED`T-_    qYRp,D2`!+IV3i    `-: fɀX$M\6HգwF?     Q/;.fɀX$MbS    l=TXdBV,&{X     VS}$[0{f&ɀX$Mjӿ    sR2`!YHض8UY     VQpeB$2`4F3    *+KuˀH,de"i+zK    {.Oy+KuˀH,de"iES    JxR3`!YHEhs    3|RwR]3`!YHjC~n    x:8uw{kR]3`!YHjC6/N`E    /]:gB$2`Ԗ    E*uR3`!YHjK6/IUg    4<ogB$2`Ԧm    R:bo,="6U,Tu~z    Zop¿3XʀERO/    @Uܖ:6XjB,D2`!+IkˍS    zGYwRC2`!YHjcS    ÿ#XʀER+[A=	    hrfwR2`!YHjk>    o7,5-"6T.%    h`*mݰ԰XdBV,\OF?     0SXʀERZ'_    LgNXj`,D2`!+ImwF?     Rۿ]XdBV,T}Ys    0FXdBV,;1    ĩ+RÿXʀEh|yO2    DJMπH,de"IO=O2    (^:7Wjz,D2`!+IY,    La#;_i2`!YHΔ*i    h¿&%"$b돉~    k<L]7WXdBV,;1Q?y    hE;+MR,D2`!+IzjK<    4NT,ߞ̀H,de"IO>D    4JO+MZ,D2`!+Iz%    hSgj^wҤeB$2`gh|xI3    P~ifB$2`g_G?     78g~ҤfB$2`gij^*4    r٭ps	̀H,de"I^wwTU5    @TUqI΀H,de"I+o|	5    @팮>([i3`!YH'    6éeJXʀEVe{D?     ?JmȀH,de"IVKS,    7^zALVjC,D2`!+IZg~=    5n_+>SO$F[<7Ut    (ZE{o{Z̀:[(ѕ&?on    ?~Jmwb,dYGW:     !VjYG}Z̀:;>ѕ}7    @VknVjc#?ǟ3`!o	t%o=%	    Ȣ-OW/+1~h1*v{[+IM)8    d?sO -fBVŞt%/!    SIyJmmpףZ̀'ѕVlT=~_S    0'Tb6/ɀ}4ѕ&?O9    ¿Z̀z6ѕF75/^    ̪ARrrs@U?{nR9~    fǠ;Zwʻ"b,d5`q+I򽣟t    Y18K߹Jz'?~h1^_+IPRU$Y    X+;/Nu¿s_Fg3`!M'?4!NB    憅_$ըbWE
Y*ᕤi    `Nr{Z΀#$M1YU;    jy_$լ~h9lᏯ$MRk~ۻ	+Tg:9n´:N[SKgN=v8%aM0,`,%-	$o:Ȗy<y	yy_7    cޑ*uʞԜ\q҇$MRo3=    H/Jz~OԜ\҇$MZWx    xYë1cW>A9`aε/+Iׂ]|    zhO{75?)A9`au,IXOex    չQ%pҷep?*} KҤ%c    yৃu~c݈aIĚG^+{    N#Ǽ#Tҋ׹fA ,TCX&ugy    g/|w٣y~CX&Edz    7SI/[}tIu'G=    PsǢX勒^7e倅bIz=   hN*kf9`!Ex2SӇ$Mrat    j{1og倅4ŲwcI:E    j\{W42}TҖU>~k؀YXHӺX&|#    ^;'7mTU=9`t,Iu'    0':R-uogx7} KR]Z=   	`BgJ7=:YXSU8CYPqz    LTGR[Zg9`!U?IʒTZg~*{    }Jںޕ=:9wYT٣    0[Hu.bpB!fwJΒT^Us}    &DQOI[_'Wex,k,Iu}G?    0	~N7SW{D=E9%Zj    ;%mS${8`!];$խ16W     06'o#<X	űiI[=   1T5Fq8%m[E٣#+$i)n^    8hMI\=I9`a$7}PKRk􁈲    1ѽwMIWkG	 ,kIcݕW     0oȷDq/#-Il+\{g     FXXoϔ]m%UX3C[X    ^XUF)i;)fOxQX)ͳ~'pKRM~5     wIq/#-I)uW    0B^?=R%9`ah%)֩~(    @Xn#MBőo[,2,\\wձ٫     VU:w+%fOxYX9C\jAj     H]$R@*=/#u\\SB    PS)%Ε_+E00}KRpt:     X|*ޚ>)i@-|ET-E0z@:Q[    R:SoVeObXY_>%5O`D^	    \ MR 1'-0*cT    !hL)ipƍFZ]j߂|     I=Qoׂ]Z[G$ռ汿keo    `L4{wֹF^s$i^t     RUE(i-5dOjX}eTwC
    t?<Q|KBozIҼ(U{CZ     SgZV,+#CUEqҿJyѾs[    D%O106yѻ     l^+_7FIy#~m怅Z/Iš{Dk    Ja9}QVf.X+3̢$)Z?1o    x~wEIé#N纃$is^    ?tC4(iBT30~(~{"$͋WD     jfM1=QPݲ<{@8`a,,}H6<Vj     ^HSMG4Z<'VϦ/I:1{-     /~(iH4{8`alEcAѿ     UJZ30PXkM_Kj٫    A]%=g(,9/IZFDUf    r(=Pp*#g50pX{ǣuBe    .{J^50X/Xy_KZ>*{5    @ߒF(ihu.Bqh_r@$mXW    J6(ix5'[d,Ln;ߓ8$Ikf    \&(ix:ʵwe*,L;bfDͧg    x.fs޼<H6wЫ\:%\D  
IDAT{5    *y.-P\}`9စԾ$is79   `Gq %ODqsߍN_(͵/\f    -y$wF\=m`8`aboL_,n9#{5    dhtU,~]?7{rD?*f쒾`$If\{gj    ׹>IknQ>rc9瀅׽9p~$m     cwǊhL4M.5Yyx$e    K]$5ѾGͧe    +ڻ8o{צ:sB}h;Gٛ    B(|K֗GsBth$IeLf    V7DI^K<sB픭QE$Iχr    x1n"Oj_U=m`$8`(\+KHԽ     3wW5gOXd$M^    0R:WU۝վ|
,ZqMޕ$Kj#k    FBwձovW窯dIXx*>$5#z     ?8;INkfYX`Kh%Ius+    >wM4wO30)Kj^    \(}mWϢcFhH_bTfo    3ՆG8-os^q䛣\s[~^UEe&Iu8Q5eo    !'/MNkި6<=f`l8`ѽ餘1}IR]k񈲗    `xw8I}F^B+qk$յ
    `82+>'iM-`8`_sG4;IRMW    VUE?K{4؊VfO[X`<g'IlQ>rS*    \w7IuGxxTUEE13CUf    ݺ+I`;F'e{X`+.K_T|8^    ͺ7&ipGO 9`mP>P4O7})JR\     ۤw-Ծjo-0Q*Β9}AJRxB    _hL&i+;/+0v꯹=5}YJRm1\=   `&wWݵ?ƺBKXTC{?    U8Uio=FPFӗ$աwF\=   k~!Iڎon3{@-8`AwrI,%J҄Z[e/{   sOaO?};	ԊiO_4u.= {   Dq?O7m5sY(ZrTUѽhe+I\fO|    jh2I[_dke?{@m9`)s͂Y[򕤉lzu   ƪh2I[Uuѽ:3cj̡Gugcf$MZ!Gnu   h72I[^qkCjo!?p	ͳ!$bQ5fy    jd|8mLҖU,34{x,hH kn=   N#Z_XyۣjcaX`A4CIPscDUfw    &Xՙ֩IzZfԛ1,0BO>3vI_4uc   >^h8trm
X`3krI4{Cq{Ӊ#   I-f!K55?Z|$z?<rӌߟ&K86S"{   0):h}c^yܻ{¨ߟ=!DѾ⯣x4N:5?    L7.IV5\{Wd ^'w\ͳ?f"$CՆG'8    I-9ZFtW.qNG̢?<H҈_Wٓ   qmF%խb?+j==	9&D[ϊyC_BFMOV   `WV4MKmDX`?|ctY>3S;}U=   OgIׂyF{ŧgoGޘ/X6dƦj_hјYkIJs    ^+Zg|2KۦGquG}Fﶿ#run-֊Dq{bfz34u{D4   `hQ%{Emm֔WmM^As_D]ul~tvrUOkgKƐZ3s}'?GfIJSgK     H g]`n    IENDB`PNG

   IHDR    	   E?   	pHYs    {Rk    IDATx[mwART@P xI`Q!B|PI'bbb1&H{RLLiQkKĢRPlh^zzofD}笙3O{m^Z    J    	      @Fl    #6       ȈM    d&    2b    	      @Fl    #6       ȈM    d&    2b    	      @Fl    #6       ȈM    d&    2b    	      @Fl    #6       ȈM    d&    2b    	      @Fl    #6       ȈM    d&    2b    	      @Fl    #6       ȈM    d&    2b    	      @Fl    #6       ȈM    d&    2b    	      @Fl    #6       ȈM    d&    2b    	      @Fl    #6       ȈM    d&    2b    	      @Fl    #6       ȈM    d&    2b    	      @Fl    #6       ȈM    d&    2b    	      @Fl    #6       ȈM    d&    2b    	      @Fl    #6       ȈM    d&    2b    	      @Fl    #6       ȈM    d&    2b    	      @Fl    #6       ȈM    d&    2b    	      @Fl    #6       ȈM    d&    2b    	      @Fl    #6       ȈM    d&    2b    	      @Fl    #6       ȈM    d&    2b    	      @Fl    #6       ȈM    d&    2b    	      @Fl    #6       ȈM    d&    2b    	      @Fl    #6       ȈM    d&    2b    	      @Fl    #6       ȈM    d&    2b    	      @Fl    #6       ȈM    d&    2b    	      @Fl    #6       ȈM    d&    2b    	      @Fl    #6       ȈM    d&    2b    	      @Fl    #6       ȈM    d&    2b    	      @Fl    #6       ȈM    d&    2b    	      @Fl    #6       ȈM    d&    2b    	      @Fl    #6       ȈM    d&    2b    	      @Fl    #6       ȈM    d&    2b    	      @Fl    #6       ȈM    d&    2b    	      @Fl    #6       ȈM    d&    2b    	      @Fl    #6       ȈM    d&    2b    	      @Fl    #6       ȈM    d&    2b    	      @Fl    #6       ȈM    d&    2b    	      @Fl    #6       ȈM    d&    2b    	      @Fl    #6       ȈM    d&    2b    	      @Fl    #6       ȈM    d&    2b    	      @Fl    #6       ȈM    d&    2b    	      @Fl    #6       ȈM    d&    2b    	      @Fl    #6       ȈM    d&    2b    	      @Fl    #6       ȈM    d&    2b    	      @Fl    #6       ȈM    d&    2b    	      @Fl    #6       ȈM    d&    2b    	      @Fl    #6       ȈM    d&    2b    	      @Fl    #6       ȈM    d&    2b    	      @Fl    #6       ȈM    d&    2b    	      @Fl    #6       ȈM    d&    2b    	      @Fl    #6       ȈM    d&    2b    	      @Fl    #6       ȈM    d&    2b    	      @Fl    #6       ȈM    d&    2b    	      @Fl    #6       ȈM    d&    2b    	      @Fl    #6       ȈM    d&    2b    	      @Fl    #6       ȈM    d&    2b    	      @Fl    #6       ȈM    d&    2b    	      @Fl    #6       ȈM    d&    2b    	      @Fl    #6       ȈM    d&    2b    	      @Fl    #6       ȈM    d&    2b    	      @Fl    #6       ȈM    d&    2b    	      @Fl    #6       ȈM    d&    2b    	      @Fl    #6       ȈM    d&    2b    	      @Fl    #6       ȈM    d&    2b    	      @Fl    #6       ȈM    d&    2b    	      @Fl    #6       ȈM    d&    2b    	      @Fl    #6       ȈM    d&    2b    	      @Fl    #6       ȈM    d&    2b    	      @Fl    #6       ȈM    d&    2b    	      @Fl    #6       ȈM    d&    2b    	      @Fl    #6       ȈM    d&    2b    	      @Fl    #6       ȈM    d&    2b    	      @Fl    #6       ȈM    d&    2b    	      @Fl    #6       ȈM    d&    2b    	      @Fl    #6       ȈM    d&    2b    	      @Fl    #6       ȈM    d&    2b    	      @Fl    #6       ȈM    d&    2b    	      @Fl    #6       ȈM    d&    2b    	      @Fl    #6       ȈM    d&    2b    	      @Fl    #6       ȈM    d&    2b    	      @Fl    #6       ȈM    d&    2b    	      @Fl    #6       ȈM    d&    2b    	      @Fl    #6       ȈM    d&    2b    	      @Fl    #6       ȈM    d&    2b    	      @Fl    #6       ȈM    d&    2b    	      @Fl    #6       ȈM    d&    2b    	      @Fl    #6       ȈM    d&    2b    	      @Fl    #6       ȈM    d&    2b    	      @Fl    #6       ȈM    d&    2b    	      @Fl    #6       ȈM    d&    2b    	      @Fl    #6       ȈM    d&    2b    	      @Fl    #6       ȈM    d&    2b    	      @Fl    #6       ȈM    d&    2b    	      @Fl    #6       ȈM    d&    2b    	      @Fl    #6       ȈM    d&    2b    	      @Fl    #6       ȈM    d&    2b    	      @Fl    #6       ȈM    d&    2b    	   ̡M[oltXUcvŋyO_1{;	cWN}: 6֮}f'𴽮vMo[w,8GlZ,ݟd]ʱzs?[zg7  |gv˦6;ly{opٸ}-{}08icbؼvkϞkG4na  ձ?3aޅkc3׏CdurŦձ~us';紱ٿl %NMmfcr'46?uX=<N&?6-cK7wfO;7{?<Y  KY{h̯zf_;){?MGiv?)Plv3O} 1ۙ?0Wxkl3[_]v+XlT.6-wz3&?lvskN} @fgc~OL~mf+{XwĦc	?8/  ?旿pkn3[;W93}?o|dl~wN2  f瑻-?2;7,fnƦdZ}ӧBPn<zp1  ,k/gL~nf+y?cͱ_شuǍcvnD  8,}f.ݸfe+~rl_KWi`C	ý[Jh PZѽL}Mnf+og=aůc?7i|Oͯzؙ?8  &7#N~mnf+?wl_Lkwf'Wx  Sغ]cS&F7c;6m}馱0  ڼɯl7̱}'cش?L_ccz)  '^79OĦcWN34}D  ظu_RqrǦCw4lw_8vV?/  8xvc_=,/Nش}'EgL~v7L k{c]_ǛR]cWNشuǍc'?f_' #c~&7v'Ï{l{9MPvC%;sO{  8)^Kfؾ6?z'?fG#wS  Nzoۻa̖[_Mfulw?W  ?0V:u,N[_6o;llvwS  O^=,OwM[W}Y4  ɯleYcش}ފ52ݹ=  ~k7CcglZ<űz᳧?Hf;rؾ  |;ۛc?7=e7clش=0f`cN[Yqj  1Xvk׿jbĦ'?(fޚ8  o/Eϙ~V?iĦ~amt~   7sNVO[_ic/ϝul  86[\;,g/ml_cl)  pl6&G07MŦ4پ;e/   k˓+Nllȥ?hݭcl-   3'g0vc;1iOAۡG: ogN~`f+Km~˖8QǦ~k6{#w	  X_/\M}af+KmkolՓ?HOOv  `b3[Yj58>i1p'vwԱ[  0f6{Ħ_7C0nfk  Զ7/Q'nkco{G6>tX  ޝGYV
8o|\h41&f7rsc&^M̍IntṂ  3Ȭ$2u3}wUAl<'+e׳y95ZOuhα#ܔ$I
4Ҕ/2| Y믾`nM/~R>);s\$ITg ٬Z~Zu*[ky&I$Bu|dֿM;6(?*vze*׮$Ik-| Yivlj4KQ&I$bMr%flrAwݚm7y<n8a>e$I*01^:;6uN/f]|<$I$UY 힓xGSsx{&I$Glƺ9cSP}{St&I$M}
u{	Hkߜݱ_4RTK$IRse=+|?ڙ^z{(]$I*^ҽw D4Կ[xfI$I:lgvlYFiS'$I$ɕX}Ȟk6|lyIIsO$Iu}Yn V-sڿ4CkϷ(U$IƬ;.@6OcS;¿HX4|ǣ^*    IDAT|FI$I2ddOmӰxhǦ#LYsIm4ǔ$I1ONeTcS¿8wʈ$I1np۪ߞgl'lQoesI$IR9 z~M7qWkw4F<$I$ա ~-R~4|/Z!xvucI$IR*;K_ y)&7K?y$I$Fn8>~ҺzǦ׾2Og-|I$Ia> ş=6/iUK$IҜSk7<@ڇ|gMb+RؽI$I5npǅ)vȦ?>p> F}F>?#I$uH&-6OF?s$I$5a?ȦeG3xRC}DJeȑ$IԐߐ߅,V7su/3]_CI$Iw:}-=+2#I$ejwɬ}ÿ_/$I\=X띻t1k_F?W$I$)?.|?>!r{ÿWkͣ)$I4]瘿ߓ o_9̊obSLß\,$I,LŲK0<v0+vSx]<9"I$I?K7P/Lf.b?C>R9~H$Izg{MeW1bK?A$IZY<_?A ?Y¿ԯJ$IR&$Iqsԧ(±YkzEB$If\ؽX}
plbvm?AsB$If]oT0QMJ]$IѵT^y961cC>R9~6H$IF7ŒWטc325ˇ~.H$I&׿slbF7<$I,SYהcOݿ~H$IҜ6|G)_}rlbOe$I$yUw.kȱ6Y~N$IiM={D86')zK$IҼ6ܔO.߿ &֫u^>'I$u;5ϛ\=%I$i$ŃNqltOb$Iֿ]pl_>y4zK$Ih+>;59I$In)_enͱ=g$I$=s"|7|961$I$i͛:-;c̱_>w#]$I*ǧi01H>zK$IRj]1pŮ9I$IZ;Rx14O;#zK$IR%략mǱ:}>zvK$IRu뵦?L)zw|865Tl==%I$Vqlj)I$Iz} ||865PՒ$I46>A>&|Y-I$IcU/s	Ǧ]-I$IcWZ͐πcS{WJ0zFK$IXֿ|1]=%I$i|+;;6Ǧ/cY$Iƾ|rAy965@kR},z&K$IR-|<+̱=%I$6koO-w=+ʱڇ^$I?{WcS-~v*=%I$vX&Ǳzgo=%I$.=|jRwg$I$շA7v{cy86ওǮ$I$վ Ǧjy+I$I{@+ın>3)zJ$IRcuI'0QM5=$I$5џ	!Ǧ)v|oJ$IF[涔/2|/jU$I[{^y86D뿖R9$IT,yQ~y0Ǧ~n\$I;gI~y0ǦhGT$I4U7OŲrlwn]=N%I$IOԻhEq\Ŀ$I'7bEȃ86b{Ǩ$I$i>-<zg<c락]$I$ xky Ǧ1U7$I$U5GplSS)I$Ip0slCoNi؏$IipwwHG̱iv$I$Ͱ~#!!Ǧ13+S)I$IKB>BMcfp$I$iP>	86$Ihx%;%#4F=%I$IYcӘhsQ$I	8||4(I$Iڇ|$~Ǆ4G|2zJ$I3Ǧ10y(I$In	<rl7>=%I$IsֳwMcS zJ$I7!'M>O$I4~yTaE?I$I<NcSEPܓ$I$cN
=!M5mUܓ$I$geZ{3||96UPkߊy$I4cSMI$IRC~iw!Ǧi֔a$I$
E!CMӿ9'I$IeAj}9T!ίNiЍs$I׻t9T!G7I$IRDv*"|/|86UDE<=$I$IA>|7|86UDE5IF۰֚ǭ-knß0"zG2%璤VJv	O!DMU|&IkCSGޅ9u柤!N}~#V,jϛbSkwH=__޿4U!IfT0i*F3I6\=}\\ꝷS7}GRkL|31uj۩sR0퇣$g)M7cS4zI4on:9%uNBjTO.^ΧbR?NU_'IRTc"&pl
=sL4O}R%*)vxaj;{4
J4uZsl
ֿ9&I{e]?JZn;G6^P>EV4gLlǦ@Ů$IaSzH?=ŶOz->I4n=3YǱ)aH'/~v3Z+ޒ~5n[$IsRkw? MQ?;g$iL+ܚڇ"勶3%/NcI[Θ~$ISG? MQ*znIƩ~;~=Kßc\ӿuvY7L?GeϒcSݗG-IR+'/^ZUM7K⒤׻`yYrl
G+IRE+[kR?0mgys'WE$UH*~Ypl
JT~˥}|3ßSV5GDQ$UI_^A>M#V,}nH^78&v>X=ka*G$U?Jf*gȱiĺK$6=˩$XǏNŃ\%I}Qϐc(M.HÇnQQ7J~wY<b,L[{G,I@l|F}$iğ&;oY*vgclo&^G$EVK0Fh?%I,S4ß=GEkE)$ջd34"S/T~~g3z+v~u__J~zIҨXgOñiD')z,I~;.;_YZ+%n;;'@4⺧S34"ß\=$IsXy4.Z1[&m%wFHHFTvꓪαiZF<$QSo=R/ퟟz,:IjH#?|FپѳHu[8?/OZ$IU7i-zV*kg$icS}RR{I$gLc|$I1"7xqIqSP)86ͳM'E I,yqjgls_*I߇xy?yE96ͣbǗ4E I+nRKoN{$qS|=QDILSuz[=kaJ0'N4G:?ϱi"zHSk̀QiTFI>l|Mr#I@ekMO~f;b~n$i_q`su86͓޹;FI*ԿT,}iBm;oτ$i/MarA*=r$IT>voj	$i	O4Z+zH֩1XgTQk_MۢL%I!yAݣg$#>f`;YIF>ȟ4&7K#wEI'ݶ*R}.+GW>"9slc=c$IN54iS9I$ͦ~';*i@I|0:G}:^+GZ4~5c<{$5es;,y 5ݩ,і$ͰCxpR86͡A-2`x[*S.IPVqa]";0Ǧӻd#IQ:+"zm$5UM^{|і
ȟıiL.~I{ujg 4KT?*^[n<1uZڇ"K^Li86͑7$uǤ|VdjuI$ն&~|ZꝽ}j,oǦ9;oY\4~ޟ	l41 Iߠ]:nZ+R]86͑7E*I0u3o]4aw}=RkHgsMsWG$տ~'u3xֳ'$,8~n86́ѳLj'|XU~N􈐤ΣiOXˣ$նr[g=~ᒚS3=z,MerA,b6ԧyTCSg=a/ojrNS'勞>s!M<Ojb_K_2J4ܝ7[jCzl|L96mEDI]nNίLܖkWGI,Vn>C!ǦMp!%Iܔ^?き2G$Wo^:,uN㇥%5ش	ڇ|$zlJRrhzh[)u",-~v\a6Aݢ$զ7bg;07G|r	$i>+IpB6ԛJ9]~)|ssDIu{VyRO .Ǧ헣g$բHj̏DIc>KS/kNñi#uO+Iߠڇ|8|hr闸HӽSy%MipqXƻr:G&|#x4#"ip{>.
y86mm3Zƺ)_L}d]ѣG҈+Ss6rO.I@66Bkߎْ4Mg,FokE Iՠ?A_O)vd#شzEqI/`c"zIY*| Y%86mFuIʵbK8wףǑY66"g	gȱi^01ٿgW`n*sS]S?KŮ@'M>G$_e9TG/p]W|-"|F Xslˣ4v1|~)#Jj,M{% ǦYsEAƪwS1%ն2?n>7>/Fpl546ip	J]"u&Vn=3&rl~HX93bɋRvuȒ'LTc,L}$if<(|n}|4Y:? 86͂kU-??|n{D+;Se<g %Ǧ~M4Æ3gFO1itZipwϦno9tM3>E4>|fթl==ʤѼҢ- y4CS˓$i_M9LYZ-|Dfhp۪$UL?>z_}DTf>K$b+ @M33R},&IneekWG69αۤʭo,g Ǧhя4ItekM*v|Y}|@+} &fǱi')'Ina=z.iTߙKjy? rlߊ~IRe} gViGjXygmRLԃcL$i=s7F+Sϥ֊|rAmF+T>f]葧~gıig$Ua`CDO>U{S}'R^شasv~~JR%_O}S**ׇ 9MOcpTI^v*v4ODO@a?npZ+ iC&x01+Iw޲4R%YM헣TZ|/G}n8>u>C cӆ9ÒT.z>7 n=3zj~}_g46wg$U~'^>>sj&bzixewק,dشVE?%R80|6W`eܔW'){Wm,cӆ&.Iթ,E[7GOT>4#_ObK ȱ).y.Ijpwg3ڇ^xeg	|86=~KRj>Nݰ]W|9~gʷ<W zE?%2Mk\x*ޘR=*Ǧ{9i_KߓV I? ;{QY4zl96=rHR%*)[U6>Kz2. ֣ӟ$IJjq\η?>K?A_oa TM1uI?Sk2L.H;.L~
~96r>!Ihp)3`6Z{Cl?,,
 ,86G=!I}g2ln8>M<VzHcI[OV Mش[όk$W>vo>3|&VkśSRRR/OuCp s̱i=,Ijzscջa    IDATd1} HMشbɋ^"Iej3`cK_:G#}Ý,xǦ>#K$U7 {ϐ.-uXV +ıio	;?)1>6٢g;6}&8pޑm شy;ͦ&IZ^>Bm,Mn7 @>fѿ;Ix4Y0g&ݗwޕG9E+RϤb^ M5iIjrSW,KߟҠ\amRkӇ rlz)u=ORs1\>K FűI^IRh> l96=I߉$)> l96=q<Ib+g1  5Ǧ'靳$zՓw^> l96=IoEzV9  dcϱI\IRX> l96=I~8zדڔoy  b_$)uǆa   Ǧ'{w'IaM=0  Ղc|#&zדZ{-|  Y-86=jQ'I!R>Y  ZplzBâ=I
ipI3  jñ	[ϊ$)i_  @VMOC'I!x_  plzBy4zߓ7|V3  jñi"Kϋ^$)O  @V+MYj}OB  d4$))_  @V+MS߄c$)	  @V+M~KR*  @V+MY]2z哤W>|G  qlRD|4?:5|  Y86Mdix;$ޅ_   Ǧ,I  jǱirOF^`   MMŲG{  @V;?6}OF_7O  OM>Iw]  Zjs6;$M'_   |%z瓤׻d  dcSoբOF^ԯ_   %ǦWF|4:G&|  Y-5ԿOF^{_   ?:5z瓤  jǦ]F|4> q'I#<>{ l*[E}4҆>{ }l, z6X}^  R]5T,yq'I#opq  jǦo$i<8|  Ym5ش$i.X> }ljOF^̉  dcS瘿$iuOb  j{?D|4  jǦs'I#}_   fZIk  dcSe;$־> }lxe'I#/  VM+$i> }lOF^+/  VM$i; |  Ym5Ӣw>Iy-/  VMϋ$ie  Zkixϕk$ |  Y5tk$~'|  Y5T]Ih  jǦOFZy4|  Y5ؔy'I#l  @Vk=6M.HF}4  :kiі;$2/~  Κ{l9;$  @I+[_   vxA'I#l?> ֚{lZOF^},|  Y5ش;$~;|  Y5شˢW>I}^  Zki+W>I}0|  Y5شW>I
)\> |l}OBn> {l$Tl  dcG{$D`   Zr'I!Mfg  jiś=I
-3  jǦ=IRH?3  jǦ[G{Rkw`   |{'I!@  jo6Ijh>> {lM$柆`   ]_IRH*|  Ym5ش=I
{Wg0  VsM;,zߓgN`   (zߓz> {l$Կl  dcSh}OB_sT  R]54Y'I!n:9~  {lR*;$/  VMN'I#ox  jǦnI+3|  Ym5TF|4y  j)?z哤E
  @VK>6=zO'I!;*|  Y-5شvu'I!o3  jǦ7E{R`   f2zߓ:G}:|  Y-54X}^'I!u  dcӏN$)i_  @VK>6;&zߓz> }l$!3  jǦޥ_$)  @VK>6s'I!M}g  Zj{}OB*;|  Y-5tW=IiK9  dcKR+$|  Y4t6ѻ$Zu  i}GzVa   fh'Iaus  jǦIRXS> v}lj]OꝻ4|  Y4شw=I
as  jǦbɋw=I
kps  jǦ|S*$49  ii"Ke{m'I!Gg0  ՎcӚ[=I
ys  jǦ=WDzVk[0  JM[N$)  @V+?6V'Iau&|  Y86]O'IauO9  dcSܥѻ$ջxe  ZiIRX> Vlѻ$59  dcS?$)򱟆a   Ǧ~7zד2募> 6ljѫ$M  jǦbDyZb   IRhS> TMYJV'IaV-  @VMY*׮$)	  @VMYui'Ian[> 6&4]O*> 6&Կ]OtS>Y,  ZplRW=I
U  ji"KݓIRh> 	G&zϓ:|.|  Y-86Md}DyZmg1  ՂcDZ+IRh> &T=OB~n,  ZplzB귣w=I
|9  d;w=I,SY  ƞcw_IRh=> l96=apI{$g1  =Ǧ'80zϓк'Y  dcϱ	sDyZg1  =Ǧ'tO=OBp|,  IRh{	  @6ף<I|rA<  b_^$)bWc   kMarAJv'I|<  8slzCDyZ	  @6dp9{$;oY  dcͱIWIRh  @6w{$6  ƚcӓtOb'IZ),|  ˱IGQ'I&|  rlz$)  @6e;$߅c   [MO6 ~'zϓz? 4Q5zϓ7~7|  rlZs<I
mx  Ɩc:WIRl^>3|  XrlZG<I
-  ƒcӺߐ:zǓG~*|  XrlZGFx^  @6Q,C'IF<  شmҰIRhû/  @GMQ]IRheO.  @6vcp{$Wy  dcǱi=WIRxC?> l86GOy  dcǱi}ߔc>IRx  @6v֣}{w<I
op  Ǝcz;:zǓy  dcǱi}&oGy^3  Hı)9zǓ/|  Xqlz
?zǓ:'|!|  Xqlz
$)ޅc   +MOIRxS= l86=$);1  ǦZ+;$W3  ƆcSYeJ0z͓Z{3~&  i\86mG$u\<  ش[ό$)9K1  Ǧ]w'I?.|  plڀ1zǓ> ll86m@ODxߠ[d   MZO*Qkd   MpO  q45Fx^> l,86=N$)5Gc   MOwɞ;$71  Ǧ=;$  qlz>IR%j3  *ϱiv{c~'Isg2  Uc);;$;o  sl}Exc   <Ǧ_wL'Iᕏ> fwv;$UbKg2  UcLIl~'I}d   4Ǧh}ע;IDS> fbV)O_q@L  R96POui<  Jsl+R>YL  rlˣW<ID> f:o;IDoIL  rl$V-
  @VYM3T,}I~'Ihpq3  *˱iO>y  d4ύ$)r> fپ+$U~
  @VIM=+$U	> f}G;IDWd   $ǦY(vze~'Ihp93  *ɱiO+[k1  Uc,Mk$)b_  @V9MԻdN*Q  @V9M=;ID5|&  Y86REwT> rf$UO  @V9M|OSh  dش?:5zœJ3  *űi#%zJ9v  dش1ߴe~'Iw3  *űi#N*g2  UcX씆O+g2  ıi#q'Ig2  UcFp|~'I}g2  UcFꝽ}~'IjqL  ploџ$n:)|&  Ye86m֊7GwTG  @VMkrTv$^? TM`x%$Ua> 6A;ID3=|&  Y%86mI_$;&|&  Y%86m$kn  @V	M)e'Ie*(|.  Y8ǦMT-zœJ>3  96mGwTSL  pMjQ~'I3  96m7OGwT]> ,c&jNp> ,cӦ\#+$U~  @4w\IR%  d@ҽ;ID+  @ʱiNIR%seL  PMs߻;IFnn> ,c\X씆O*Q? űi>zJ9g2  ql#$.+|&  YǦ9=$Ud   4G} zj+Rs  B86͑bT+$Uo  @±ikn$u  d!PDwTz> ,c9IR%ܶ*|&  YǦ9>;IDe{m'e   9Ǧ9TN*Ss  FαiIR%|Og2  cN*Qg2  c띻4zJ4{3  FαiN*QY<> lXk7FwT]_> lT$uL\  (96̓gEwTz> lA＝;ID  @6RMM=Ϣ;IDeєOn> ldA$Uo  @62M&Ń$Uα#~.  iTǧEwTz> ldI%$U]d   ǦNQ[e   	ǦyRK$U޿> l$Qؽ$Uw.|&  H86ͣͧDwTW> l$QoN*kg2  c<j$U ='|.  ټslGŲWDwT'|.  eΣ-bPQmDm$fFI6B:j&*((Gdd'b*:EV{޽y>ҵnU}=βi+y0|P
31|&K$IjyMsSw п,I$1Y6qsG J!,I$1Y6qo~<|PEۿ&|.K$IjiMs\s룏w >sY$IRcNlCSF J{dI$I9Ͳio9!|P
[Nɒ$Ise;R(?|&K$IjiMc}Ǣw \,I$ilC_;& Rj,I$1gY6G Jw3Y$IRcβlS>3g$IƜe4g}=|P
E뉔M˒$IseӘj;h.}k\$IԘ,TsWT;RgsY$IRcNlccwD Jw3Y$IRcNlc>g$IƜd4ƺg~-|P
Ewuo>%I$5f=˦1>;h,I$1Y6/O)D JssY$IRcֳlsʛw лb,I$1Y6߈>B~3Y$IRcֳl
xN4|.K$IjjMcw W$IƬf4oR7>B/eI$Ii6l
hp%;R_,I$1Y6Իdiɒ$IeS_1}(H^>%I$5f-˦K}(7?>%I$5f-˦lezm>%I$5f-˦;|P

ɒ$IeSPsG Jh?M$IƬdTߏ>FkeI$IYɲ)}
 )uN,I$1+Y6?~gW>%I$5f%˦}(g$IƬdXD ʡSs+$IFgXk߈>F-|.K$IjltM-|iJNg[\$I66˦>֓g$IFg\=w Pd+g$IFgpV;h.}k\$Iب,k-{W4:~6|.K$IjlTMMKE@).[?%I$ɲ:+|P
WdI$Iʲ_}(A7e˒$IeS	j@i,I$Y67D J{?eI$I6_    IDATβ$VD JQ3Y$IRcl*I>B,I$Y6}(7eI$Iʲ$P4GQ\$Iؠ,6[w лpq\$I6$˦?|}w>%I$56(˦տz@9t,|.K$Ij8˦9s;hKsY$IRcY6֞>F甿˒$I3βLMo;R_{p\$IfeS>Goɒ$I3βd.Z}(H_>%I$5feS@i,I$1,JVsD J{,I$1,JX̃;RqFL$IԘQM%lpI;R(ګR6=/|.K$IjwM%{E J]sY$IRcl*a?}(Ή;|.K$IjwM%)y>%I$5;˦%|P
cdI$IβwH"5GI$IYEl*iS>xP#?>%I$5+˦Wv ѻx,I$^Y6kE JapsY$IRZ,Jp#:)[E\$IXgM%wn;hsY$IRcY6α>F˒$I̲ĵv}{4>%I$5֙eS+;R(ZOlz,I$,Jӣw sY$IRcY6v 9sY$IRcY6a=lP>%I$5֚eSknڔ"|P
$IZl@wE JsY$IRcY6UGF Jsԧ$Il@!lPKw˒$Ik̲@i_>%I$5֘eSZEJnmel$I^,˦?pu4sY$IRElH+>FSsY$IRElH>3$IƋfTZ;lPE4|6K$Ij ˦4I*OE J/fI$IǳlPD J{߇eI$IdTzl}(GeI$IdTG|2lPŪsY$IRY6U7D Jӛg$IlXŪ{v 9$IlX>F=$IlX3}(k$IlX>}(|^>%I$5˲j-"A/xPC>?%I$eSmgu]>%I$5˲'lP7|.K$Ij<eS뜰u<z͔-xIl$IeTZ'hP*>>%I$5FY6Uyh>F͒$I0˦6X~N4w>%I$5FY6UE JNقg$IeSUk@,I$aT՚}(>%I$5,\@i<3|.K$IjX6UGG ܦfI$iX6U_>Jk_͒$IҤױln>}(w9|6K$I^ǲ-"A/lPۿ?%I	cT>Fy:e7͒$IR6Y6UޕD J﯆fI$),*^焭u =g$I&?ڇ=w+kʂlx}(mfI$մ>%;,+oN(huNfT祢*HP>E)m$I7㽩sVwٲ4XqqJ:}*6˦4X~o Y$Iժ䍩}'Rߖ/ZOn2ϒgTzl74j,I\>ϾcSY^s|YpM5}'g 'fI$9K÷Ý?|ξ~blAo)$|>K$i5ǞݳwgTU(^>%I4,=mh;?%β&o<:z(>%I4{5YT<yw*ޅ;]eY6դp-'fI$m`7{9KoW?YMKwͲ& 6I$U,ͦU}fY6ե[4E_S }Y$IkRT'wgT JJ$V,ͦ3޳,jT})R||l$I*4,jT焭)R)GS6=/|>K$p?,Zளm,jTkD_S $IRk.ySjԻ`4X~N*OEWZ{.ʂlSRz2(_ϒ$I˟Xo{/	7̂lYgG_W ҿ,IT,?xD>gi6]:eS]]uP*Es$IMKeL2.cINk?puTlM5}'+iY$i5w>{4T4l"}/>βf5!(_ϒ$Is,Gᯇ,8˦V'(͒$Is|-?0\Fbla J<gI䍣.1V\Rk?z[k&β.@|$IZW^ڇ|Y63ugTÆ* ,I}T6'ښͲ-"A/(=gI4yYnЍ9PZzͲ^}}ˠ;a|$Iᖟ9Kx_eSM]OP:C?>%IRjngwֿ9K+!PC,8˦9atz-	ϒ$y0\6Nbli}}N5Y$U(Yb_SY6յMR^}K??%IR)k.}kwgK(ZO,j`@tt|$I5wx]j>S=m
57Muw@?@!z>K1`W<g̦eSnx;$I,9s)躔~ LbTlM5km^y3Z$N%oL?n;uT<@ugT Js߆gI4^|ٷtl*V?m@ԽJeSt7>%Iz<gi~H9KTIg*6˦	g$I,Koz-KD $by55eSkK@)-IҤ9Kq6XeSݛi*5~w:~FK4Yz8 S_wYpM5(|>K4Yʣo0V}8eԻpk|~jn-IRk.}ۏ=g}p#7_YpMP? J}g$I}ѷr(¯,8˦	@)+|FKTƚ^,]wX*;?xM5g4!O~?z(;$I,U_,F*ͲiBpdPJͥoђ$MRk58ѷc,&OPJOˉђ$9KǣoP{~gY6MH}5z(-'hIf᧬HoipIx,Lσ,8˦Ii)@G32|NK4<g	J3b*6˦	jk}8|FKuL]{'YpMT❢9R]C$iYz,V	@He9@)]>%IYsۗLӿJ]glɂlK}SQfd$ռypxPTlMVԽ@)uN3ZTϷ.s`_>,&MD_w 43ZTݚ۽:,{Ϥ,8˦	{W;R*ZO=%IsOs*βij[@isZT,7E߲5eӤ);@)y$YjFߞ7,βi<(EhIRsGoE@tg4.-("O*|NKm_}x,BVDu|OgTlMXD_{ 9$i/GnL)Db	>csp*6˦	M@i=%Iᖟ9K@~>,&b=@)S%sZ5{Cg2<>+,&GD_ >#sZHقSk_Iӿ7Tѷ	(|~Nf4uObPZKwӒ4q4xoU],V\Ҡ}K /SY6Mh~1(sZ&9K÷õWER6=/|fY6Mj7=ZY-I5}=X۩ sb8Y	lw}V
ӒT|B0	U+mV,&C}^ڴp0#7ܩ,&-y?5{u:?EOu~AJe$F) ^\?ՒTZ{BHܬY6MxF_ տ9-Iu=ƢQ37+AM^=E*>3zVKR|OG:X?|f%ȲiE5kY-IUsFs]SJeӄ-"@.Y>%uq0s=|f%ȲIxUiIzw c937+AM=5kY-IU7G9X37+AMJӾ}=ZZ֓G9XPJeRkG_ ?xM*7Xqq(Y	lc$@y$U|-ѓ`,;.|f%ȲIω&J{ڗg$Ubc`9gnV,4wԆKY-Il)10c3wY6iTߋ.mK_>%j5wzsgnV,4~Wף7XV\>sd٤.(MǆjIZ#(z|֓gnV,\+6ʭLٶ/גT}9zzEgnV,ñ}m^[>%J.!ztEgnV,\]~&(GkIR=Ƣ{?ܬ$Y6yO}}Zy:e_>%* ztEgnV,}}^OkIJ~	L>sd٤9'@=%-<|=Ƣ]swY6y3(*e^>%v}{Wݬ$Y6<}^?גT$z\E]>se٤Կ>%uN|gnV,􂺧~1:(Xo>%.>z\gnV,Z{|u
P	C>>%o>.zTE#gnV,¦~b> ~fKR)zTEgnV,n=)Z(O55IJv_SɲI/ZF_ >3[XsۢG4t𹛕(&h}~9ZlI*co~<zDMݬDY6śi*ګW+:ϤlےTg~-zDMs	Ylڴ$( LHݬDY6iuz%P	ÏْT. cQd+gnV,Zf5Pvj.zeܖ4I*3X_?wʕe| :eܖc`l7>we٤6X~vuP	ElI*K>=Ʀwюs7+YMZkNG_ ՐSsǟ
ےTzm=Ʀs߅ݬdY6ipuPo-Iehp#`lڇ~,|f%˲IkonWmI*AŪ#`lZ>we٤u6k2Z;|nKRdo S_҈Yɲl:띿mPےY? cS<@JeYF_ 1|H6I얤z/ c3XqqJe6[4F_ >wg$5106Y	lzwy5Pk
ےT4 c3|L*_MZz}TF~*eD얤q#`:'MJe֫a}TJ>%iuN0V7|f%̲Iܦ~':g$G_jٛ0&wE_ Q䩹τnIgˣ/tѳgoV,u]})TpnFnIW%o c?ٛ4&w>}-TJ})iq9c`7>{f٤of<}=TJoIC+ c;oaJefoG_ '^&|-#`:EJefTF_ ߒ45wzs>>f٤}3@tOrsG-xEjn4&ͬyXHeP)7oI7=jƪxٛ8&͸ߊ*ooIoc`n*oMq>}]TNooI|0z]ʽoV,4㚻LuP/vTzo=aƮ{WoV,AO}mTN;7|~Kl?
0vC?|f%βITm.=%ijOd4wDY6ig6@%h٪{W* qjY6ij)y5P9[N4[0z`E7+yM?`3\6|=UƮw>38+yMz}TRg$ml>=NB)38+yMO`)'$mLۿ=NB`Je6mL߉*s$m[Q
0~E^>g٤C!6Lfb"uORQ<yw*e6uj9.IR~e# SgpV,Q@PYN4Z}6I;Q*e6tPMEZ?%iv`u9U &mtO*w^s\fRѣ LkY6i;@uOu咴>Po=
d٤E_ ;oY.ISãG&@kpV,4+O}TVz"5}y,'G?TYElҬԿҺC,=ѣ T/"Y6iVҊOقsIZS[G%@YElҬ)k:o>%j;# 6YElҬ57lzy.I?^cG$@+gqV,4ku;}T^?55|=B3|gʲIVk_*o7I*[뜰u<*efMR ֟tIVIEwuXgrV,4o82z T^u)>%{DDpå{6Ӎ?ej    IDATU(&j*z BOtI♇!@gTlҬR*Y Py&IuNB((ޥbY6i^, L')ɻ @)tl\VMz= j!,|K:](ֲwbY6ikY P>>%Mo5'zB|̣fefxL S͖]=G@in=9|.g̲IsR#g@mt纤	iKRjE(w9~6OU/&I0;-U]R#TYlҜ5) PvIͣ ~D/YlҜ5XqQh A7v{GlTz= JexYElҜ=_g@o9!|Kg]>	> ?Իpq|*e֞?= j}G绤5P:?>f٤9XuO| R6.>P>E;d*e{E.&-<= J'=U,4P;Oj/uzH(Y6in[EJf  Iؚ;TtWG3Rꜰu*emF	):3^Ruqz$(֮%|NgβIs^/D	Zq9/zuL(tV,45qx f_̯yIժݫR̃;4|VgϲIc)yPO_4= Js_Y6i,uyP[OY/#;9|^gϲIc{@uNY/5)ǣ@>d٤?vG nK>%yipѓ
zW?eV❣@IzѺ}9zDTB?Yljs})|K*W=70 ֡SsׅY6i|MoGzG/5"= *!{s;IMkk=? j/䦔-"|K
nz^|\H%zd٤>D͒wo(7?>d٤͖ 0Eڇ~ܗR'@uzG&Y6in=9z LXj/i51<= *e(&	[GwYl>%mLWGo3|>Y6i5{uJn,Kw&ipˉ#Z{bOM
ipwg	Dg_ֻdiG=ǳe٤:'!z L^+/in)PYk
YͲlRHůO)DRZ~4<:G}:|g5˲Ia>/z LlKfP]^jny,&=Kc`"Uq~*ګG
@>?|g5̲Ia5w锊<z L9~ᵖ3% =3=aM
mp%ѳ`2Eꜰu}@kSԽSZ{|\jeBѳ`r}GֿNoNœwGOZ(/|g5ͲI?tE]sMˣ@m?|g5ͲI_=c &Z=Z'~ i͵vw*?z\ JOY6) U<@j.}k=A>u.[=& L6[Y6)ҷy+@	OܕK~_Z| Uv>g٤Rt %Z8Fj{)u PK
YlR)YV֮o7H\Ŀ}b$ s`K_>g٤R4|F*|pk~&y{ Pkgzg٤4(V?Z{\An7|+?eJS/F ~Z{/!ս?(Rs7Y645!=z 1Ehj	T<uo0.d٤R5|, SL?~jx}LY_d٤}
 13^!բm~"FU0qZM*U^{ eV~"(mdeJ#7F_ '{@6!Y6tn;5zKlz{T:E*/a;Q} ,T:zrڣRjnԿz`A6!Y6t5"^+z\0ztC*sC?\&5ƚeJYƣg )=tmԻrѳ =?SeJYOD" f`џ	Heo Ck~o&(&"[= Hl)WeRW$ ?e!,Tz= 8-~C}D/A ~LGdeJ[k_I lb=9}/Qkٻ`9ї /Ss~&,&ۢG *E;}?m~"u]R}ϋ_LM^M*uO HeH&s_bՊuw˲I`:Rң->)+
1?~&0&=F( f3Ssɛ-Lk4X~v%8#MhM*}>= EE=+)i=FZW]~6?|Y sVlBlRkn/ Sgw2:5}y$,T7= E~kri TWoS	βI}F* PzO q֓}0	@MP%,TlG+ X>R6=/ޣ7IjipY/} fQͲIwN312DGsߦ|-/u @Lz&Uֲwv	3> գnHvLE{UKR䩹[9^ǲIUjpѣ g}R[譙5:ޣd٤J9ѳ@џIMI*w=o1~$eu 5,T۾<`Sl-M*O%o. @~*eDH&UG0 JM?~RþlyfJ %	@Uߗe٤>C3gb`{IJME (~~Rce?vG;gijӣo\G/3 J&{e٤J=_g wY.Ͱy/wy`GYtOrKe٤tO5V\<zxts7Ǵ׏
ٿzT<}~TsWx.&UE4 (R~{ֲֿw&/M7.O+W 4!E=MGlRek@+oIKHEչqv?? 585eMSԽs:)Իl\OWsGÿ߫.0ۆ}SY6u]= A7V\zl:G}:55WoZ{\gk3G
 ss_~<&U'iЋo L-`~:~)dr۽*`z &P^m7,T= pE癔?pUxT]觬?4H}r,5wK>7o82]ՏDUs\o*XM|C?= `ͺYaÑ{S/ޖ>ãߌj.~}ʦݫSkw9zHw焭S̯ޅ;sRr1@5O*oM~ӛ<1 TY~sx)\8Z8=o:6o:fu?oFwgt 0ҚlR-Y  C8lR-jy  +V=c0lRm>  zOO5֚ej!   `z}TcY6V=   #v?w,T}9z  0<v}{Suf٤Z\T   ̲-'9X,Tz=  e?~TclRj.}kJ z  0K?kY6n;5z  0K:sejYFB   fÃ)[sej[ȍ3  =ϗj(&ն)=  Ewujn3<[6me*GF   6PϖJ3ͲIwNѳ  7+՘qMu͝sJy?zD  0C?SAY6o>>zF  0 v{GyRʲI}Ї$   3пe&ˣg%   (Rk#,4uL  `=n;%Ɲ-44O=3  X?C*mLM~1zf  ?;Y6irfTdFN   ֠}ş66&MTsDN   ^D~gF5f%&MT_R7   ԨMMzW=C  {/	?+1kY6ij.}kJy?z  oe&MDR   sψjjMZj<  `[M}8Ƭf٤mpy3  `<3lƬg٤}G*  DkgC5f=&MtO<   `~&TcNlDǣ+  )τjIM   qgA5,&M|#(z  LZ',Ɯe$MK7D[  пjs\f$/c<z  _7K%o?1gl&iM|c  z-?)uMU  "[^~ScזMi3z  RԿ?)#&G  P;cwlg>5sl~bՊ9  P+oIyOc˲Iv  <ezj\m$ȳ-z  BƟƙe"ul<  -'ڲIz7IGe  wRkwğƝeG~*z4  TVE:5BlAv   L)eg:5BlRߋ   3|nyN,u49  P{/MaY6Ih1   "O}5FhMz4  Pz?e唊"zn  Vz25wx]M,ӱѳ  %ܦF)lֳҷDo  Wޒ(EM],z  KQA~^S4Y6I3kRz"z  Fڃjj*&iuѳ  㩹>Ae$ʹ/Iˣg:  @	FS*[M9/g:  @R6=/|Fl6y)  cM=6S*cM6  I;QL=I#[/FZN   c?qWn~SuȖ/FZeJiЋ   cbj:z4KHUw>ѳ  `,7~Suϝ?z4HUh==  T|<5w3wNL/1RU  0:EKJԿk:#_To򇯏   sbp۩.4|5GY#URQD   fU^;P15ֻFF/1RxT}   `Vuxk=wa#UNoNE   f)i7K)^?޵AR  V@=Fj.}sFÿ -|iʟ+   :'lRZP#_uo$ե)   l?WQɺ}Q#僴z_T  j|վϽh+_TZ#~'  0c
?OQ^eSEIuw{  o<:Fu$gl^[&ay   X/?G)U֞{kjl꯸8j$_   [.'5*]˦^IuaAw  u]sI׿Y6Z VsץX=  `=$ܤF+VxeS;Ius  5Sk?/QZ/M
6X~θo   k=+$5jQ̯yٔݔm/Rc1  @S6=/Fm˦sd)յwy   x3eK~>R5{uJڗMBڶ%)_y8#   ?T}?)ե	/-챴zz/Vk~#"׭  9w
?QweP됏R]8#   ,e6?Q_R_eS¿`m?q8'   h=lYHBeS~*f/Zso  9MG005f[4>ÿhs.o)   w.g5jWu˦dn\S  	4)E5ePs_⥺>>  uӤlj3k|0:M&ޥŽ  4}:jԲe%eSwSMmes.  ]4Tǚۿ6lJ)u/Z&R>  0wqԨep˦:e;>#MBO   PSbgx5k<˦!$/Mʛg  L~;sR]׹lJfv?4	   s߄gTZ=~gMÇ]oLc  	ӿʙ]9mp3zMײi枿&Mnm  $}~Qmk.)@iRjT  LbéM6w˦QJR?  LA/s޽vtN+`@Ac"Qb"AА5FC&`-`o _i(%*D	,
VEXn^9|欙=ϓ|fY椭9~Z)Ŧw/{XxZ  Xo[Wp[_Vvm_fGfX~u /Mb8_w)ǦZ}uOcuڇ  X/|d<?zoڋ>=شuo'_Ó͎ʶ>3:  p[mX.~lڵs_ #c?vF  8VK~jg[^3_O;6x'fGet?0  $;ck[b[/ƛ|g  +7?}ivϞYl{9E1;*Ǘ5  8?ɟAlgǦ];_v8_#  Xt['7\lڵٷ".|X{{u| fyǿ{>a6,6ںl2r<  W{KobHcӮ+:_Ta  `B]cW?3fX}ylx׳&pfGbȏ1  08J  IDAT7&ΰ˻n[Mq3&fGaoݼ/G  8KV˱ߙ{ibӮۧO~!͎  h
[_ر綳r?_lNW<wjvys8  cWN<aif:kƦ]ؼE_X޸G  :6/;gtO_6N;wl[?y5  p_8yܱsG_!Ŧ];7p!_p5앏z66  pعݓg56Z|1{ Mcv#&nMzlڵܸgl'6/$  ooy^?/9c}/c{6m>MlڳZOzT}?b#  |սw%9o97_5b}wǘq`r|  1gFV7A2ylڳ16~VgO/[~ƩO9  Y{ag[.~X|At0b}_7f?0uGuwO
  pl7=ig[ccĻElڳ[8O@xXL} Xl=mg[[Awb}'16|֙O} hX- xSόƦ-ܘiᚭö?Sk  XgO;gl)cOǦ-~lwE'3ݱsH zZ^0vxw滟5_~V&6oqg;9No ú>x,3  'xۡ?99>V'ݡM[}ЋW<b0n˻n( |?|;\]g~rCb{l1SL71cuSb  X=plvcg3l;?_:oqΙ2;؞O}| p&v1ևt,cluV;-cl{/?Osm_  jl'}f/'d,nXGƦ\ŭ[^4oMy2L}R p^86ݻyxSO\<|h,wp4bc+5;~o.}8yC'aͦ'/h ӝϽ|zkޘ;ll   '6       ȈM    d&    2b    	      @Fl    #6       ȈM    d&    2b    	      @Fl    #6       ȈM    d&    2b    	      @Fl    #6       ȈM    d&    2b    	      @Fl    #6       ȈM    d&    2b    	      @Fl    #6       ȈM    d&    2b    	      @Fl    #6       ȈM    d&    2b    	      @Fl    #6       ȈM    d&    2b    	      @Fl    #6       ȈM    d&    2b    	      @Fl    #6       ȈM    d&    2b    	      @Fl    #6       ȈM    d&    2b    	      @Fl    #6       ȈM    d&    2b    	      @Fl    #6       ȈM    d&    2b    	      @Fl    #6       ȈM    d&    2b    	      @Fl    #6       ȈM    d&    2b    	      @Fl    #6       ȈM    d&    2b    	      @Fl    #6       ȈM    d&    2b    	      @Fl    #6       ȈM    d&    2b    	      @Fl    #6       ȈM    d&    2b    	      @Fl    #6       ȈM    d&    2b    	      @Fl    #6       ȈM    d&    2b    	      @Fl    #6       ȈM    d&    2b    	      @Fl    #6       ȈM    d&    2b    	      @Fl    #6       ȈM    d&    2b    	      @Fl    #6       ȈM    d&    2b    	      @Fl    #6       ȈM    d&    2b    	      @Fl    #6       ȈM    d&    2b    	      @Fl    #6       ȈM    d&    2b    	      @Fl    #6       ȈM    d&    2b    	      @Fl    #6       ȈM    d&    2b    	      @Fl    #6       ȈM    d&    2b    	      @Fl    #6       ȈM    d&    2b    	      @Fl    #6       ȈM    d&    2b    	      @Fl    #6       ȈM    d&    2b    	      @Fl    #6       ȈM    d&    2b    	      @Fl    #6       ȈM    d&    2b    	      @Fl    #6       ȈM    d&    2b    	      @Fl    #6       ȈM    d&    2b    	      @Fl    #6       ȈM    d&    2b    	      @Fl    #6       ȈM    d&    2b    	      @Fl    #6       ȈM    d&    2b    	      @Fl    #6       ȈM    d&    2b    	      @Fl    #6       ȈM    d&    2b    	      @Fl    #6       ȈM    d&    2b    	      @Fl    #6       ȈM    d&    2b    	      @Fl    #6       ȈM    d&    2b    	      @Fl    #6       ȈM    d&    2b    	      @Fl    #6       ȈM    d&    2b    	      @Fl    #6       ȈM    d&    2b    	      @Fl    #6       ȈM    d&    2b    	      @Fl    #6       ȈM    d&    2b    	      @Fl    #6       ȈM    d&    2b    	      @Fl    #6       ȈM    d&    2b    	      @Fl    #6       ȈM    d&    2b    	      @Fl    #6       ȈM    d&    2b    	      @Fl    #6       ȈM    d&    2b    	      @Fl    #6       ȈM    d&    2b    	      @Fl    #6       ȈM    d&    2b    	      @Fl    #6       ȈM    d&    2b    	      @Fl    #6       ȈM    d&    2b    	      @Fl    #6       ȈM    d&    2b    	      @Fl    #6       ȈM    d&    2b    	      @Fl    #6       ȈM    d&    2b    	      @Fl    #6       ȈM    d&    2b    	      @Fl    #6       ȈM    d&    2b    	      @Fl    #6       ȈM    d&    2b    	      @Fl    #6       ȈM    d&    2b    	      @Fl    #6       ȈM    d&    2b    	      @Fl    #6       ȈM    d&    2b    	      @Fl    #6       ȈM    d&    2b    	      @Fl    #6       ȈM    d&    2b    	      @Fl    #6       ȈM    d&    2b    	      @Fl    #6       ȈM    d&    2b    	      @Fl    #6       ȈM    d&    2b    	      @Fl    #6       ȈM    d&    2b    	      @Fl    #6       ȈM    d&    2b    	      @Fl    #6       ȈM    d&    2b    	      @Fl    #6       ȈM    d&    2b    	      @Fl    #6       ȈM    d&    2b    	      @Fl    #6       ȈM    d&    2b    	      @Fl    #6       ȈM    d&    2b    	      @Fl    #6       ȈM    d&    2b    	      @Fl    #6       ȈM    d&    2b    	      @Fl    #6       ȈM    d&    2b    	      @Fl    #6       ȈM    d&    2b    	      @Fl    #6       ȈM    d&    2b    	      @Fl    #6       ȈM    d&    2b    	      @Fl    #6       ȈM    d&    2b    	      @Fl    #6       ȈM    d&    2b    	      @Fl    #6       ȈM    d&    2b    	      @Fl    #6       ȈM    d&    2b    	      @Fl    #6       ȈM    d&    2b    	      @Fl    #6       ȈM    d&    2b    	      @Fl    #6       ȈM    d&    2b    	      @Fl    #6       ȈM    d&    2b    	      @Fl    #6       ȈM     nF     IENDB`PNG

   IHDR   0   0   W   	pHYs    {Rk  IDATx[lQGĽB4'$n *֖F.*QUZBF;q)[3sv/gmjGAPb|8R䴔qS`HA?E[xU1{-"5+)^zydpbjJ.ĬaZ7%hOeHcT!zn%]:;`K_!/nh2 y{> H4  5\Of~{&Jr(E}lRc+hUoſ(bw%9g3 7?AN^12ꢎGϡ+z~-ȁ7pHۆZ rlVT7	0iXIJHH[8+my(%PN.={Q~MP@@@hxl7 ;<qз5 yX9n$e"IU j hW~ (EI g  0M x@d,s3¹0]ЮV@lK ӹ@uH[^֕R-_ tCYbް+}]Nyg\v ,hcn !WLǵXyL9`$/ }[=c=R8n`c$Z")KL^/* ȱsdxsn8Ӻ~nֹ0/V+0q5rb3 ipRfA[wl[x(glxn\yc`mI:
g1uuA5K Jom2k9aeć|B=UImM@! %D+ys&9"3)ZxRN ?n:1;CZMD*ng##ޔ&Jٚ< b|ߡu'    IENDB`PNG

   IHDR  6      Tפ   	pHYs    {Rk  IDATxyp!֪h[[TZUd,ںtQk*nU	$PYAYEPPVYbr}y;c{~y~3Ͽ<-giz+=֨kw'9(-1zB	Ck9NL8շm`۞yjq3(ȱg[{AlJ=J|{}j,r pLX4
>{7Nɼ&rшN4w/`ha1W3&5uY+Kh̡i٨b#c49r3Q}6f~ 8o<TCާS{
R%{#Ԏ^=fFI;;S}0wEA	d8WD	vwد&')h.6gŰ۹`M*#;y6w/ApbZC9| !C~Sh9CEjz=}B0s: ss.wA	!w+^r/@ɢ6A:3i}<Ul !$[MlKẔ'N.w_@C[){Wqdj'%{@s K{Al b3	&[l9UY[W͚tw + 6C<ªL[ 6;9s`&+ 6y7fMGlعb1[^
nED4+:}'9oEђ`76͞r'Ş0$eNwhF֨k]>ßSCboOq%ƌSD3`F3X Nt[7ɞq_5#L4%gc:5K<>Cl@؜=(Vx69˜о]Β<!Bl@rSp`+Ņ|QV o$jlF!6 JlK(.fQpr	oU)I&<oNWvFȈԴ8MjGw\\arcIld߱n3yr͢y`Z$߹edO'dBlFIDK	*FwhgZ/ŧ`:>KΜGy6Bl b&Lqdx!{96L6xL&'*:EI2;yUMΥ.Kdm!6$T@RDu5ȯXF{%dO+%?t[XIEXe\,9bfw{&{)S~Ʊ狩[S/6kLgy.{!S^s1h+6I*D 6E$x `v"It
؀~bSs$Ta/#M[OMc/#MMq{t}$.^Fb:-7GP2"QlN 8rˈ@lX-Ç *-I*jYwh)I*ˈ@l@G7'dtrbbߊ$,2"uSCQKˈ@l@ە{H"eD 6ZH؀bIs:{!mѦY$sD 6F+GTɷ؀bS#Iř4{!d^Hb:7+I{!h(6I*aNB"PlBUQp2{)&6b^JbͯXFRg^JbhIU#H؜MRc/%fM^Jb,$cf/&$b"MljI*D 6ؼգI*.w1h(6g#$`:b"Pl+I,j]Nb-Z3$kUD 6}I*ΜGˉ@l@Cե}<43	.'f=%(84ڴQ	B*VE 6T>#8sc/(歝HRL`/(Ŧz^Pb;L"LlDMR&vc/)Ħ^ YIRq^Rbes){Ih(6$פd{Qh&6sH2ً@l@3%sShUT0QW^ 6y'xLf/*., ջ؋@l@CY㻒d~?d/+f!
C=."Ll*-$ou{YyZt
R7$9	U:Q];@l@9&=;]~7F+>*bMJƞ  bㅳJ;	7<G[2	$M3 1jxuN3#^kHlj%$*
nQh[;[wu؀^bs#ɘ~/҉Kl[I2άGcɞ|Kc1N@ĦK͆\LMtjsKl*jNX<;~)<̑WF$ޮCl@;yN!د_Fi&]Yb͙IhDC1z؀~bSH$_EsT5"	J@l@?%[>zt9$<PMMݱ$Oq˩>t&_|}澛O	&rq=M7͆؀bS,c#uDAl@_%GgvJFT]|$bM=g5}
RQ:z($bZYKұ_{]Tƞ79[lV$ruH$]`[2ьmtvUJBkk9!6'6u~:I'ص]XS$oU)d͞~/kuoΜ ،>>I'ؽB	ϒd̗~	bS+QP2r? <34j;:(8I2cwyQ!6.6u H\+ދekq"دbĦcXdnjG1yb~,߷q-1PHe9RѼ+7j~b"Ŧ@q2>gdMjnV8QC!6؜=(I;2zk -Qs!6IRө+kM)dݸ:؀hR	n'waS|n˜7ugQy!ċ͚t5$B:ZyzD"Gνez?}ߐL8؀VbK&Rxx/w~MD<w 3j!h'h3D'-5Kl*50	h)6Qqw0N؀bVqwd0Bl@W.w@2@]]7%m@l@k}Rh0%Em'ѝ !q-XmZm1cM/@K8ĖoNm03cƞyN !Xc:"6<3Qrw0/#չK^ Ħ}
wA:	uIXْˍ@#.kj;Qx7Q[7eb|ID9}0'vjވ[o ާm_{A56)hoߛ,0#@(4򓍒yސ$F//ό|j35LՋne#
k*{
R tj!gKrQ'4hc20Yt!7sDWP\|C֤[CN4'HrY<$؞|^&N=vl2\Zc:Ws|__~~6J Zuf#    IENDB`PNG

   IHDR       O   	pHYs    {Rk    IDATx{u}/J1#DۨmNMB';4Sɨifڦic8˲/"7V,WerYX`ܿDt/o|~c/|5	    m'     C    0   @ C    0   @ C    0   @ C    0   @ C    0   @ C    0   @ C    0   @ C    0   @ C    0   @ C    0   @ C    0   @ C    0   @ C    0   @ C    0   @ C    0   @ C    0   @ C    0   @ C    0   @ C    0   @ C    0   @ C    0   @ C    0   @ C    0   @ C    0   @ C    0   @ C    0   @ C    0   @ C    0   @ C    0   @ C    0   @ C    0   @ C    0   @ C    0   @ C    0   @ C    0   @ C    0   @ C    0   @ C    0   @ C    0   @ C    0   @ C    0   @ C    0   @ C    0   @ C    0   @ C    0   @ C    0   @ C    0   @ C    0   @ C    0   @ C    0   @ C    0   @ C    0   @ C    0   @ C    0   @ C    0   @ C    0   @ C    0   @ C    0   @ C    0   @ C    0   @ C    0   @ C    0   @ C    0   @ C    0   @ C    0   @ C    0   @ C    0   @ C    0   @ C    0   @ C    0   @ C    0   @ C    0   @ C    0   @ C    0   @ C    0   @ C    0   @ C    0   @ C    0   @ C    0   @ C    0   @ C    0   @ C    0   @ C    0   @ C    0   @ C    0   @ C    0   @ C    0   @ C    0   @ C    0   @ C    0   @ C    0   @ C    0   @ C    0   @ C    0   @ C    0   @ C    0   @ C    0   @ C    0   @ C    0   @ C    0   @ C    0   @ C    0   @ C    0   @ C    0   @ C    0   @ C    0   @ C    0   @ C    0   @ C    0   @ C    0   @ C    0   @ C    0   @ C    0   @ C    0   @ C    0   @ C    0   @ C    0   @ C    0   @ C    0   @ C    0   @ C    0   @ C    0   @ C    0   @ C    0   @ C    0   @ C    0   @ C    0   @ C    0   @ C    0   @ C    0   @ C    0   @ C    0   @ C    0   @ C    0   @ C    0   @ C    0   @ C    0   @ C    0   @ C    0   @ C    0   @ C    0   @ C    0   @ C    0   @ C    0   @ C    0   @ C    0   @ C    0   @ C    0   @ C    0   @ C    0   @ C    0   @ C    0   @ C    0   @ C    0   @ C    0   @ C    0   @ C    0   @ C    0   @ C    0   @ C    0   @ C    0   @ C    0   @ C    0   @ C    0   @ C    0   @ C    0   @ C    0   @ C    0   @ C    0   @ C    0   @ C    0   @ C    0   @ C    0   @ C    0   @ C    0   @ C    0   @ C    0   @ C    0   @ C    0   @ C    0   @ C    0   @ C    0   @ C    0   @ C    0   @ C    0   @ C    0   @ C    0   @ C    0   @ C    0   @ C    0   @ C    0   @ C    0   @ C    0   @ C    0   @ C    0   @ C    0   @ C    0   @ C    0   @ C    0   @ C    0   @ C    0   @ C    0   @ C    0   @ C    0   @ C    0   @ C    0   @ C    0   @ C    0   @ C    0   @ C    0   @ C    0   @ C    0   @ C    0   @ C    0   @ C    0   @ C    0   @ C    0   @ C    0   @ C    0   @ C    0   @ C    0   @ C    0   @ C    0   @ C    0   @ C    0   @ C    0   @ C    0   @ C    0   @ C    0   @ C    0   @ C    0   @ C    0   @ C    0   @ C    0   @ C    0   @ C    0   @ C    0   @ C    0   @ C    0   @ C    0   @ C    0   @ C    0   @ C    0   @ C    0   @ C    0   @ C    0   @ C    0   @ C    0   @ C    0   @ C    0   @ C    0   @ C    0   @ C    0   @ C    0   @ C    0   @ C    0   @ C    0   @ C    0   @ C    0   @ C    0   @ C    0   @ C    0   @ C    0   @ C    0   @ C    0   @ C    0   @ C    0   @ C    0   @ C    0   @ C    0   @ C    0   @ C    0   @ C    0   @ C    0   @ C    0   @ C    0   @ C    0   @ C    0   @ C    0   @ C    0   @ C۬n+;u Tj9,U'+IB
uTr DN-'U':NZ`K73Vҡ.7CW!T.}oTM|k$~??  Ru;^NZoj|éuçSz>M^m#:5T.;7}  XlHq?̞:7=:MٺSy!4u}T  &BT|'eJͫߍn^7ZZDfLug%  `ܗcޜHMGӤN.M~=3{^  T?}wVv=oйk):iV7_J[O,ٿ9l}ܷ  L4c4a֯[8ˡ.KL7F^QoH7E  `*5U+ qTO}wu*W)^fG6 {c47im'rvcSwS  `*Y;.Vڷ}~lۢں֦+ط  ȧU\Wb(U'u_E;[O/V/ߞ-r.  j;+AR1Ԛ/oJ:u֝=]_<igUǾ%=  ^
v4!-6jh=:W]TwH7}   ѾO$CT1-&fh%?ŦZ}p}0-  HZW~2AR1n%i>;Mk#El  :y~T#Nc޳fbHsZ~  0Fj~ײ%$#/zc9X_b_i.UǼ9ܗv  z)5@3b4:(u7S/ͱꘃRޑ*  @SC-$iީ):Լw¥9VT?}Ho   ^\}ƐT~k"55UFu   CVo\OISVM۞+͵R=  ꭿfkeGFCmReJn  dҽIHkS6C[T?\V1?a  "оS8ߤԮshRu/f$Jsn>a  b淪7듦ƚo9VC[x!Ug|0'OsKJ/   ,Vfj~#(k~?֮RuοI{  ͩq?.FY/mu_="'KOO  hVl"i[OYC[?IS%   0RyQ$kf}9ubO4Z_o  `t|p}VTjkh=.ɑZ%~  L~^TT?)\kξor  u~nTE@ޡSca?\}ԩv  &XjbC[8غ7  0/oJ	~Tަmgw465N>t  黽4eUg| ^{C[~1/ͥ|   ӫ{ߥ#FR1Z7-4H3/  h,MUIg0-eKG.   xEZN34_Wzmu7UgJVe3{_  =˩#)wh;;)ͥηf   ؙ?Lꃳw$#Zn0noAJu  {T.}sb$npIy  JwY>Ѵ|To}<vh<k|R9  X~T~/vhk^  6Se?I*ҽR1C[oé\wJQG!O  ߛ#sP34f-dhk~Uy5H  y=|m*g6ҽS76ҽ0vz3  `Zl$z_7rҎjpd  `auj~#HV?Ս6ՖT_B^Ka  [Suһ$C}]8  `1+~fTA=<NIfx';$_8G#  u0IR1Ժ~{~C[wÍ/Z'o3  `'IiX%gh's0   18f?CI*msol-:!  @z#Zg)IPs܆fX5Rų   L˲$Cu65b8݃  G JRQoH·|.K<|c}`@  Xfj|d?_I*>x·]k_4hf[Q>   bf%9KRlw:5/)ޱ|  UN]*'ɇdh\3/Rj]rxJ{   ~ޒTVo}lC[d8qST9y   Co'Bs"]mhkgetWG9w   #Q?ug*>KRRָෳ_eK'n  O"jmuʣ~q:?-#  `~T~KJk30M   L~|1Inͯ:w~Qfhb  @G֦rf2In]wku4-7Oߝ  U;LRڝm#Eiu~  @~fj3Iłk^ۯg(MW+?Q  hOݙe~NT,wr?u)|NA  tg5IZwJzp/{_j~or?   ~_g6IłV.^b4=u(  `Qo},U+ߘ&w?~Ǣ}/FQ  u<7MR1zE#_&ٿR  .9<NR1|yp+>b4UL  js}kbun?sp>b4z]9  0Vzn$Թ[4ɭO   cud?I*T}[T?h.['	  `,/g?I*vYOۢ:/F؊R%  {;IiWo-ޙb4yu:?  `"x3b~-c~1Z,s  `~mz]</FSu;R5s  `:yORmof{[?   u}2ihT   Wϧطd?I*~*CBkz  WHbQfhS\+K7   Suρҫ3)]~   L~9U~TM!.Xg  +σW2i{7~   LE~.T2i3V
  o~    IDATo{*UG|()ڴ[otg
  zJЦ8)u'   Խ8CωҴ6iA-+OޞQ  ߫spV~^Lo6-?  'Emw~e  `q귶g?7Jfhe[r?;   ؁?;JK3CU~f   ͋>(SMsί  OjϑR9e4(  X||d2iNotg   QwSd?OJeh.k:܏   ޸nJϕR9%ڴ}?  j}-%ӑM;}Ñ	   ~ck4ma~e  `2tn?#S* Cv.?9   u/5gMidghvk_r?   {T)M?Uu;Srg    Z)M?Uo7r  06jϝR9Z^}   W=rB3镪cJܯ   S;T*'0C^{E_  |=T*'0C5/ܯ   P~	Цxx   F޼>~&	ЦԹܯ   dоgRmS^~m   ~k[;$T*'$C47G=ܯ   dԽSiddhZW|<9   ս8ϨR9ڦRӹ_  Xz_*mJ~fq   mTy)q?   ?VoA**cmښ3  "ԺϭҒ6eܯ   ,RmOr~ϮR9ڦjRM_  X7-~~16Eun=95   \r}k3Ta)q{Sur^  0~16%.4   ~)YV*,CԼ~  `#yV*,CۤlTo^  1\ϵҒ6ᵯTe   TTl+cmV-_  c?|+cm|ܯ   ?GT.ww]3!!z)"EU
(WQD"*vAL&LzOH!	!3B*!T镄4HL|:'8唽g?~z.=<se*U9wX$ITk	s!C[Eu[=%I$Ix쎙ۋu!8
9E$I$U7>BqmԽ+I$IX{s;/V1E$I$U֙_{!0*Y̧H$I4Cs_Qm<3W$ITZ.!(X\<~w$I$UD=&GC[EB$I$Iw	߃! 
xV.sV$I4.uaH#ơZ.$I1}~0Vr^U$I4nu[+bH#ġ/^$ITLs9ksU$I4yWu9XҽG$I$i̛McH#¡j;OI$IFvyYi8TѣT$I'Cm%TD$I$Z)vzq)C[	/5zJ$I3/1|_̡dj;0͵S$Ii7+zoȡd=;%I$I`ߛ!rh+?&I$IcgHAJ})I$I&k3?C
V+CR$IMVɵG9D=+%I$ISo}9|m$I$ͩ"=ӶψߧarJyEHI$IUOӐ̡mM-ɽ$I$ͫsZe^6yl$I$iA5@^iF\K$I$Iw3[C83Q$IE8]5!qhaWGCIFN39SN̝[.ͭ3>'Cn3|Ssm{.?7?Ss7W9O5֙_wΝ7{wg}4*$L[
߯!Cۈʜ{y(IRlN=r[ܾ|:gjӸGgUEZ̙ٓ-9w[_YIZ}ߌ69$i,ug~
l_gig|>7'/lg@Lm1j3Gs'sQDא$i u966]h<=%I{Ϸ{Jc[?{GEm̼u?ΕG<y|$
:34`m#ugG$Ini7[.ˍc<V*[F]^`WO{_sыO+I҂jg*sh5S[kIRusޫfn73ǡgjEvxAn}3LIJS+ڎ/B 3/$|vs'n6~':?ugsgH4M4	iFLD=Ikv~^no~[!%7SUiF$TsLRW}ژ$i\*7lk?/9ԶM̼ZQuʧġmLF^:gOZl?ߙ:$IuGH6"j+N4nu3f\\Xh'IL4 m#OF9IҸͼ@qm|ն{vnܻ?1{۷mD&zI\Q<y\;sm?-Cߑ;|ͧJWQ>B3VA{:wY/{ܮEѕ$Agm#sqMT߽o?(N/9G8K\k;0FmE7IR~AyVjmܙo@oIREk}_ßwȡ-?_k2iurw?Ө̭%I}xnph{&I*aGn`ʰn~_ǚU3R8jy&I*ᯇ6l_~	Uf{
Խg>qhLTw|;7|wU7f#I[}\mAj+ѳL4EtJ;-ؔO~7FT:W<mA'"zIF7?`^p2o$-N3v~I&ǡ-HGG1IҨUrcsmßSP^I%IuTs"9kK4buowPSKrIҼ*ޓӲ?`r/%z~IF޽WlA|Uf</H6lS[xY$)=δ)&%3֋vԽgL.Cې5xWܒ$Vέ3>ßI0L~M4"rhU_["w:*vzQBvg}2$i/#6L+4%7oţ?)Iъc9mphm$iku2P9sףJF暿VAZ !Y%IRݛO͵_RCdWV4bu$iچF*I>Mq쟅?wLV.+$iĪgyrhE(IҀ\*vxA3ʨ}*$gj_	<9IKg$i/mHJo閹}%I#R\k=;s6~!碈QԽ\ß5P%ӇܮG$@͓1iچED&IRks4$9UT?x钤z|?iچwѳIz_0ʽo+/I
~Iȡm{&z&IXҽrZUC$$)? ͑C۠g{L$v=7O
[εEOIRTZLnCۀ:z$IYL6OJƬȽn΍3Y6@~mT_Ɠsm?S'RX$b38sm?{ ̓C %IZhE<S4g5ɜ^$-DyO,7l.iȋ{%Gf59l\ĿϹ׍m=W̼v4R*I%x\W#5f7IU'wo:eW-m܀4m&Igɵ]_q{g>XWx,wo;;]G/vzQRY'IG[ȵ
~ 8s4ǈ${vn_kn׹+FC L*_cԹ򈜖m αMP{\;W[_=MqhOK$ȭs?7ɊPzܚ;[g|>Ushu$isy??3jO#9TrSgqk;0|C ~[U.GLIlk6DwIZV;/K>ijITAm}8G$iS:`Z~:zHR{*wwpn\9-}J\4&}*IOp:4Mֹrw3/1gnV}(9Ԓܹ#I}k5E3zιqrmZ ˡj+_=w%Iͯes)s	SH_{\j0Y.mbQ,IZ^'7ghg]DO#IxnwM\qhnot	rhgEgIҺEn ^mރ7EO%Ixܹ:q;rZ9	LC[l;y-IZ9`d\MƬӽ>o8ޫ'=%IA`4}4W^ˡ?ڗ=%IMУhj1%*U{ܹ:qrZu&B9$׻;3\ F[]ǕUgZ.ˍߗk;<?|#ǡjlےئ7Lm7=$hEܽ}8Osm- C[4O$}xM3(̽_Fjӿy3
ek~4HxWf>&y O}X4ĊG{՞>ph[%xg$uo}9y j/9D9-R}߈~vHX׹~?zD?r~r7ө۾>7ys;m$moʵ, *7=$͵^]uTn	Uph[$V%Iqj=n PӟZ<&I#V˽o̝+̭S>)e[m1E.jG?v$i, P9|G4?4Lqu C"x?$ Zg~!zIcS\w^ۗkɵ i;s%Izܖk+ *ljIxrж&IC>1y_cwFO=kɝV͍CޖӶO̡mPKƪ9Sߒs=RT7wo:%]G/v|aamzLƪݗt9OOrrrkk|U4";S7IZ)|m{Ƿ4Uo^5ɍsh[D?$ilW|24.Uгj ж@cwD?%i,_5OX8^}WNɡmj,(IQ>u_=W;/K5>;*ȡm_II:=(|OLT-}J!4}ɞяNI|Ez vx~XW?rcgiZ?wrZ+ iL9-@ߍ~JRky!c{^^wC|m$U4$~l@mRjw\6Mrhơ~JR+\?-`S
^3Uk򶜖=5: 6/ؙ_~KR\&|EگGLb={)O
͙? L,C<u=.,Iխ}^>)GONxyQn_{^ph#F?%ux=:5jRyan_rGm014m|$Iȵ^>{TQy ?ˡmGq\*[=<BLCj߫ )mb3lJ6vzQXY=JC{}8S ph$%{xEYe{e8Bs+rҽrs6O~0Ԓ?W qh$^'veXoɹEOUj_;W'"͙Ci &*m?[:~=|KǪ֫xܹnUn}_r͵
sDe9QwG I~ox~\GV4w^䯀~/	3Xqh7HR~^|I^ϝj Q6Gӿ$IoI|軩-rGEU<ܹ:qrZuk Yms{-$Rif P?>aMYSreqrm74ms♾Q><; u84zԖj/o iQ풤U+?@vo?=rGN#Nn_wnHޫ@9h~ߒHRj_{lc[˽nȝ+ȭS>1e[74@msоloS$R0˶ʽ!U	~~-Tw|;|SUh&V* i8A^F*Ss:MJ[{\;W'"yOshKl%Ih<ӶO V?9E.˯v[[67y[N˟Tm;בԾdsy*U_' H%ж/Щ$U>#|D~Y4Gj3:_ HжfHTg:@+^_UshیOǓ$-I j; G;`"9wjn[
 i9mF7B4u[3eL3> ҈phۄӆ)I]ot쩹ȭsE	UphۄA=Sƣ yaj Ρm?2mTV+ڊgt2$w_;WQi{ y16}v$'s  4mйTJ_s߆s  4mлT]  <.6fj{$I{Ƿ9  p8mDmחG戮TZg~1|  !qhۈơO%y  ġm#'|4z?RW   CF[JR|Y  ȡm#:WJRk`,  HCж;/Q%EY  ȡm#-$IZ	;    IDATX   i6dr.z{$r  rhۀ^JRk&|  !shۀJRY  ̡mk6zGV'|   m|9zOֹ~u  H6}پ{$Y_
   )Cto81zO8]s   phۀޏ.S%E9  8m@ETʊGo   )Cȹ׉U%    1v~i*IuT  HAS?{$q>  R4y*I8  @
жS%:9-:|   mi]*IM3   rh[OG朗Tʺ7>  R tpf*I}3   rh[OwUI*e͓?>  R wUI*e#(|  @m"JR)9  0ǡm_JR9+z9-:|  @miI+~  9~oG朗Tʺw^>  R0u4zO*Isq3   sh[GswUI*eK   )Cۺ_>JR)k  98wY*IyGg8  @
ж{G朗TG;|  `m\}t*Ig8  @
жͧE朗Tj;4|  `m]UJYZ  9-ѻ$D  H#mE}UJW    ZsJRm  6wUI*e;.   i8ͪ]UJYop  4fѻ$ΕGp  4f|S*I}پ3    Y~/zWR־p  6q{wUI*ep  4f5]UJY/p  4f5W$zWR:33    Y͓?JR)k  FCOg|>zWR\  FCz_Ij|/g8  @moJR)k  FC۬+wUI*e8|  6}ѻ$>  phչ]UJY   i8\*zWR8g8  @m7JR)k  FC۬E朗T5|  6wѻ$Ao   i8ѻ$26  mz\JR);3    Y{U%5}G  H#mVkwUI*e  FC۬E朗TG+|  6ѻ$Ƒ   i8=xS*Iq{g8  @mz zWR83    YGnU%53    YţG朗Tʚ |  6x]UJYĿ   i8*~]UJYOp  4fkU%B  H#mV}ѻ$>  phUwUI*e   i8*jG朗T>  phUU%/?|  6=JR)|+3    Y>uTVگp  4fJR)rz  H#mVۢwUI*e;/
   i8=xS*Iw53    YU%>  phջ]UJYQ{8|  6ˣwUI*gv  H#mVWUI*miۧq  ̡mVTI*m_>  R0Y۾JRi9  9rz*I~8  @
6{{$Ƒ   )C۬kTI*mU   )C۬εE禍TZ~:|  `m:W}5zO:wY  Hfu8,zO־t9  9j__*Iss   shվp=UJ[38  @
/ĹKTI*m]>  R0~!B*Iȭs   sh<{$H  Hf5W$zOV9-*|  @my*Ig9  @
6qF晴TY  9ͪUJ]?   )C۬~Q%5Oh,  HfxM*Iuֿr  Hmj;$zGR׾xe,  HfV<+zGR׹Y  99E*I{  `2C:rJRim  HQTI*m34z  @m(a*ItY  8wk$n>  Ruto??zGRW?   qh[GwTI*uͯe,  HAѹUJ]τr  ġmvQ%Ե/9|   mbHVg9  @
ж7>JR~^,  HAQ%%|   mh;$V
   )C:!zEW   ph[Gm嫣SI*}5|   mmTJ_?
   )Cۺȹ׍Q%5Ox<  >GwTI*uWr  m=GnQ%u:*|   m;$r  m=[JR+=|   m\U]ҧs  4dmi_W*Iχs  4dmH^㐷s  4dmi$s  4dmiTJ_[_   iS?$s  4dm$-s  4dm[uEJR=xc<  .(F晴T:s  4Dm{UJ_ms  arhۀߎO%5}{<  HCж뎏O%5l>  9m@;D戮TZ.   i6E9?SI*}+   i6yǢSI*};/   i6qSI*}O~>  9m@7E戮T"m>  Ґ8m@mWDT{jL  HCж!˷IIj  09mQ<q~*Iu9  @sE~*I}ɞ   CFto<9z?׽y  ġm#ڗJR=ts<  HCж/̗SI*VNK   i6$UWt  4m8wSID#>  8mD}D漣TZ~:|  !phۘ[\${t  shۄ"=JRrF<  HCж	{JR=rk<  HCж	ݛJRurZUL  Hж	^O%|mL  H6/$iq5'3   C&4lJR%j  ̡m_ygn*I}~3   C&T*Qg:  @0MYԜ^~*Ix  09XmQG$ȵ
   i6{$U>   9mF窯F漣T>>   9mFmwSIDt  4@m<wSIDk>   9mFߋM%:|  rhیnM%9Mm>  Ҁ8mҧmETj2~  LC-z7J8g:  @9vvn*Iug:  @9\qhn*I}3   C\Hg{n*I{y3   C4W}0z7JT7|  qhoM%2ն^\  H6_JRe  m.ܮE漣T'}<~  LC>z7JԾd  m7JR%  mJR%*;|  phɟM%Em  ̡m__ѫ$UAo   樶G勒T'}\  H}6WSKrnT*{/:  d9CkwSID[N   sT*Q3   C</)z7|v   y?DT)|  >rhơK%25Oh\  H}6_JRej_K\  H}6OEsmn*I{i3   C<2z7JT<~wL  H}6O뎏M%2vx~\  H}6OooJRejs   C<MJ$?Nt\  H}6OJRe|  ġmj?/z/Ի  ġm'M%RNS[u  mнT*Sm:  @h_^*Iq쟇u  mT*Sܥs   C4T*Ss   Cv}y^*I-s   CǣwSIFE/   iˣWSIL>  "9-P#RIL͓>>  "9-w֗RILK
   iqRIL>  "9-P}F勒Ts   -CB-}JΝfn*Ig;  9-BRIL#>  "8-B{$U75|  Eph[+RIL>  "8-BD勒Tz]>  "8-B}_K%:u[9-{jl  Hж˶Y%Ii0g;  8-RRILU
   isq{$U;u  @m{$Uͧu  @m8ϢRILwu  @mT5{$Uڎ/   ikj[)z/8wg;  9AߍK%2Nt\  HJRe|  _3JRe  GQ^*Ih=1  ɡj<z/JU뿇v  4Om}RK%25W}0|  yrhD勒T>  <9IRIL>  <9yʧRILEќv  4m}8{$U   isr.T*Sk>  <8Q{$U+:  @>xR^*I{is   ̓C[[JRe*>  <8$IKg;  @#>|uN*Iq{g;  @#~ZORIL#~  L΍C[u$z/Թ~M\  HsgK%2>  9Y_^*Iթ(rmv  4m}V?-k$U>  8ۊg\RIL3?  &7ϡm z z/Թ  m :ׯK%21|  9phTS˵
   i3qRITC~'|  phJRj   mC L-ET*Sg;  9HF勒Tz^>  f8HݣRINVN˷   ik$U>  &8H}E裸T'}<|  MphOɹRIL   6@JRe}i\  H6@K%:k3?-=  F8P^K%RM2z  phoI%R5W$|  ph[mG勒T   6`K%2uo?/|  phΕGF勒T9M-	   i>s{$UWv  m8;$Uq>  8Xm\{$U;v  mC{T*S:  @ !\w|^*I"   iD9|֗RIT=_>  zچqĻwRITU
   i=mCP>AX=g;  @ZCې@I_ݻ.   i=mCҹTS-g;  @ZC۰T*U}ׇv  !i|;$UI   imCR9T*Sv  !=xS^*Iw:  @ZCu>:z/mg;  @6/^K%Rzsl  HچqۣwRITS?>  ,a9:{$UUGv  '9YRILo   iCېu<"z/Trmv  ?k$UW>  C~KN*I   ɡ-mG勒T:׭   m!z^JRe*#|  $+K%Rvzql  h9_I%R5zOl  h9_7F裸TZ.   - ˞sJRe|jl  ^ˡ-FߋK%2  rh{$Un> yǣwRITͯel  ƛC[JRj_Sl  ƛC[[ܮG勒T?<'~  y9T*Sx<-g;  01/7z/JUg;  015OT*Usg;  01T*Uҽg;  01"Mm{$U]v   +`;/K%:9-*|  cɡ-X=RIT~#|  cɡ-XsGwRIT͓>> D裸T:;8|  cɡ-Ԓ\K%22~  y9mߊK%:u9m  Lk$Uo	  qhcJRj  LP;$U5ǆv  `b8RILGn  qhVE勒Tj;$|  cšmD/;$U1> 6"nN*Ijg;  01VFŶȹ׉K%2uxNl  8qh!K%2͵9-}Jl  &ƆC|T*U}_  ph!͓>JRj  m#wRIT+  ph%K{$Uv   ӽ{$Uȵ> 6bJRj  L<wRITs&g;  01FLmWD裸T7> 6D勒T9M-	  D9'G勒T{Rl  &*ϡmT*UsGg;  0Qym#h$I}پ  <T9T*S  D9ރ7F勒T휶}Fl  &*͡mDu<2z-J8  4:S;$U7%|  61z'Jչ~ul  &*͡mT-*v=z/T<~wl  r9ݗF勒Tj<|  6ڗJRjW  ,\T*U]g;  0QYm#kwRIT;/  De9%=JRujg>l&|  F\3RIT> JrhqG裸TZsl  &*ɡm5';$UU_  D%?<ڲ,AB    IDATF1Ҩ
QlvDDDlih@e[UIU$dN@HȜLd ̩ϼp}<k}GV{[3hv/K,Kx{]$IRYՠ[K,S̓$I43,j#oKe.I$Ӹ,j'h9[vI$Iˢu{[=)@o>#|K$I4.:) QKF]$IRjRm5RF.I$Ө,j𒽣I?vI$IFeV_{RF]_l$IiTm5/Fߓ4Jq]$IRQYեE=}_
e[wI$I)YըgEߖ4JwvI$IdVm}O
(svI$IdVz7QƷ>%I$uE[wxU=)@)[#]$IRYլ򱻢oKϯvI$IFdVF}O
(>>%I$uE[{RFFl$IiDm5wDߓ4J.I$ӈ,/NEߗ4Jwן$IRݳhaDߓ4Jؿ$I:Ϣ.? QF>%I$ujE[{RF)V\>%I$ujE[{Rf)˔o]$IRYձ4ȢoKwwI$IYմGߓ4[ۆvI$IZgVӆ}O
($I:΢z=)@)[Y|$Iԩmm5-goI$INmhqEߓ4$I:͢ƍo8)Q>%I$ujE[5}O
(e`fwI$IZfVzA=)@tw{}|$Iԩem5._Ҕ"Q}4|K$I2W<xc=)@.?0|K$I27{RFFl$Iԩem5opI,S$IeV%qz'|K$I.dӔ{RF^c|$IE[*{RFyQl$Iԩ]mhxn 2l$INhk@c>}K
8~+|K$I*e(@]$IRVY52[}O
(O$I:ʢ!o<%Q#)(|K$I&48{q=)@txC|$IԩMmwȻG?wI$Id֐[T 2!]$IR6Y5Ix.I$S,ʯDߓ4Nk$IN-hkP?}?
8}(|K$I"- 3l.I$S,ښԒMSvIx.I$)!Uuq=)@;d|$Iԩ|mkxn ?]$IRY5  5t.I$S,V˖ S!|K$IT>Vf+Is$I$eϓE[xJ(@@|$Iԩtmlpl(@/;|K$IT:;GX.I$S,X|2Y2ۿ2|K$IT6V<xS-)@|_|$IԩlmmtWGg=$IT gVmmpGx.I$dipgCS4kZY5>ohsڶ{E$IoHc?w\Ҩm3ʢ-4a7.GE$IXëR?I'Z7.8g*E[ŻwI$i}˗mzɏ^{L*Wݿdˢ/o-(*|K$Ik\G@OSUKe1+o3T+?Sx xsڶ}Y$I~|-jS}kbY5`z7|K$ݭ\}q𿇬bY52[@M>=%IԞe/sծ<4ޞ?wU,7q>%IjS5}T+78k6hH6?>%IRd7;*E[@#g3^$I5ZPlfʢ˷]g$Ij\GnKMoBY;)<|K$"-4lj?Wm*:Yѕ_ p$IRG@GUU(48S@#/IU~9QV,ZPwD_w 4`/I/<4濧wKD嬼-Pmmhɦ)@\?%IU|t޶<Wm&_r:Y⮋=)Fs=%IU)S;m
e֒}1hW(|K$iKY<of*{FmlGm{gʢ%`H&I[}|qpgCS跈;ᯁBY|-=F*N$IjsՊq[VLuhkQe"hH3T$i^\(3hkQO g$IR˗o11KR~Z}O_;YhkQf?F]O$IU[x窕e:CƿfE[@#}/|K$js1%#256S,Zkg	0}ί$IUzG@o93aVy?_sYhkYŃ7F_ ?3^$i˗ɏ?W͗M
eֲ&}`FW}5|K$k͙dֲ'*hr)]>%I=WG_3ɢeuyK5X7s^$i}\5Wfʢm-4a7:h)$Iϓ1M15U(VuquHN$Ih}.92_3ɢ/buHeﱹDyI\Q?-?ſgE[!@cu}k$I(_;4Ȣ
B>:yFm- ̏>%IRʷ}Y48{qxQ,ZZĽ"@#o;7|Kd'?zCS⺔2mQffE[Kkƃos^$$U&h:YwyIT^zI$o8)Gߺ7UV,ZZwD_ 59/I˗mz=NL]{L*W6¯BY^x}=4R9/I*\"m	̻QfE[+"zh|ׄyI4lCUE#"z*E[~{9/IjGՀk4Pm-n/ ̏5GyI^]yh*-mTZ~fʢuw}]XePf7
$9ZɓU;it~?gE[]le5	X}?%I3>:yp}wU(7kgG$\H z*E[Ivn$U5m FYhky~?h [h$Q-7O-Պ{;sa:Yɿb}]4#+ѳ^F=Wm؍>ށ9U(6Ks^w{m3S{,(Gw7ώBYikC$U\bu6>|dʢMGKFs^o{!G@{/\5h|ϘdѦKF<9zKU<txoU(6lvQ*G_ 5Y/I</"~g$o8)G/&_=
eѦF	\nʶza$iC\5eK6MYhӓ/D_ ;g$I\b}URgLh\C}y4]g$I\<*
]YŲhSU? XyC$Y>*<1zeˢMOU>h|-g$m՟V" wϸjeѦ]qP5
h?>%IoxG@ǃ#hϽjeѦk7>%I|G@o9sՀU<pM*E_Fmlf^T/}#g|U[}-Wsil*E~S":hA?%Ix4T>r[˙jeѦg4)@/9|K*MRw7	FNEY k|ө3tZYY}4Z^T	`>"|fˢMϨwD_ 窭z ѥ٬bY[_Sg>>%IВMSw7I+MŊR*c`!~T+6Vqߕ*@o=+|K6oHc?w\Ҩ} ,Y3xZYi3Zh0˷|#GOpS>>eѦkG?|K\l'6x#3;XmZ|D_ 7yvO$䣠 >eѦ5V>vW
her>^[P~/|ngˢMkltQ+@uy/Izf> j[vV,ڴ&4`~Mn$/+x nYŲhk+@_>%Ilt@mۿ2|ngˢMknƩ?}4^kg$7}4 FvV,o=+hI4U06=kslo|^ߍ> j
Yhӳ;]-@)_E̗$=Y?}2 BM3;`mzeT]/Iz9GLhs6F< 蚣$^}$ vV,/;hr*eK7{1H Y9C.@+}w̗> jcxs;`mz_}}g$Q> jcpYy+'h{S6Q̗678G ?s;`mzF}Bw߷|IjssE ;OvV,Nl
om>%͍8(( ~_*E>o~ZXy}̗67 6.|ng̢MMRd0@+tw/I-xc 6m~,|ng̢MksaV3_Z{4 0evV,ڴVy0,(<|KR+EG @m3̢MkUwG_ eܗ Q<pM*E֪|KS*2@+N/Imߍ 1U46u}߉Z?g$q=jcts;hmZ}1ZhLN	Ԧ<`/)|ng͢Mk]?Zcpg$UE~U46u6?RYD_ 0/Imj|ѣ6G |ng͢MT";dܗT>qo>fѦujx^3@kNdܗVt3 X.[jfѦuj ,m}IjC~>zJgwV,ڴN;*zhb^>%g6s;pmZ犇}]O}Ijz3>=jxU86sZ÷J767>
gѦu쇣k(˔3_΋=@mLq"zng΢M\OG_ 2ƿ~IjrePvV,ڴ^}mFqϥs_ZODyZgwV,ڴ^<4h?>%P+>
gѦZep&ٝU86W/kU|$OK oٝU86wF_ _Vq6s;xmZF}ܭg$5E?=jç,:ϛE;ϳ XX÷FIjJ.[FvZpR*EֻG XX3|KRScV>gѦUleu*KԐg/ 28s;xmڠFzu*e-,|KRxJXYųh589@/IMVDtZٝU<6mPݽ~5:hwT]~6zN;xmڰf7Jek]ƃo3@j\DOs=¤;xm7}NOIsw R{EjE6}΋$չGrZ]wljE6}OY?$-$A=je{Yi[I*G_ 3<w3@jXwDpwV,47}N)[q Iuk ;];AmJެ Gֽ'Dow~mjERw_Zitg$ժE 2lv>S,4f7Je`>AʝᒴuѓvYMhԚ|/ opg IK?=jgt1;ImZ>}aotQcv.YMh>@ku~s9 IxI2zdNk?gEZ=?@+/+75@-uyKjE誯F_ TMV/
?$Κ /<|g5ɢMSǢs@G5@O>eѦe hKIj-R*FѣvƷ>óeѦW>z{ h-_ IkG4@-.'|g5ʢMSotŗ @k.? *6 iYhCs Yʗ4,J5Q*W==j?3ɢMS/)e, h)?$JP[ίYhӼTu, hb)]~HRU^kh3EᅻDV@Rȭcw\>óeѦyw軣@=:,*M#>ǳeѦi4G*F)I
nxV'~"|g5ˢMֳg@]Y I\=jke2s<Ym 1#)$Eѣ26YͲhӼ-c'cy IQ!zVms<amf7Je`l hbu]R{ߋ>vW'eѦymtעg@~gy I]˿=~jmxY06k>= Zo|$-t ?gyV,4ll ,Rwׇ	`-}A*{FO_Z|~Yi+9z> IZGuQ/e7	YhӼ7d^~&HB4PkŽWYi䁶o~&H|S*Pk+>ϳfѦy/_9ze!    IDAT/"\lx.'~"|g5͢M )?$iZ#VFZ>S,ڴ/4 b6sA1=fo<HgzV,ڴ uoѣsAߊ WsY<jEE|y÷vIk1' 6gzV,ڴ`<4z^ }c.\i6
!|g5΢Mgf TG~MRcw)r0%/r\jE|۟H,g ߆4=RaؙˢMZq%c+7Rj_lT 0<6-hs <cg$mH3>=JcxzV,ڴu+OIZ =JãE:Ep i_H IDPF=ymZF=; xStAٞ7z4F<ezgѦo Tφ.N	(Yhӂo"z 4e7EVy6^?gEB*v^~>H48s#qz~|EB5=C Xs9r$U|MG&@/{IEBkc5^{!IܭG%@^>߳dѦfy@$|W4̣'%@ԲhSX% SIZS ?g|֐,VD Ew{o'?>糆dѦ~qJ^<`קl&g$}GFF*=|gʢMo>=z ,'}2I#=kts>kPm
mpʧg
 ϢL/?+$|KR#jgY)|) <ݢG!@uY5(67y UoYw7T'!@cSxy5(67`s(#HZo{/ 6y?Ӭ,^ߎ- <79ԮSh>ﳆeѦole|9U)Ih2oѣ{ZE*芃 c|ө煤4Qzvh3ʢMw{g k߅ ̿uǆYmyyRIRvG@+NdE* ka|gGRqU#5Bo`mL!z |0ܐԬo= Z|546U|WT k\!4z_,UYR0z Ʒ盪$mp
 N>fѦJ58ߢ `pjMoE2w3`YRuw}]`]ׯ@>gѦU>z &s;E燤z?/R*:?gѦ gCIS<ztR
?gѦms?cg/i*V|7zdS1N6?~d΢MkvQ*+z FImɦi|7@k ,ivmd#z םJ9".'zL?gѦJ;w i|É)(,Tg|!z<oygѦJ6Q*/z-?K$URYD&V+W?3!kxmlKC L?~H]S	FW~&d-ȢMwD! 6İzy")~9݇ o?}Bւ,TݖlY(;;:LuwTf+ (˷?dѦJ7V Xq7vRwT>zGƷ+lZE*]?G LsStsEoT<xci!kImvK7Keso^SWψ%YjL`J.\4?;*\=f !ΙˢMwğG% hpI-x.? ZEV/L`Ul`Z2OD"iz.]ѓgYhS-]{tl`"E҆뿥2[=Q xe-}Ay(6"hb_H#i$ <5GY˲hS=ZTQ ˲IT4Ȣ' ϣ_Y˲hSm]yh`>eIk}Sls#kYmM8e۩?k$=G7Io=- XKN?;fڗEӒM=gGy#ie/a>,ZEjg l?o$|-S (o3$kamU~/z\ ,?s$=( !YKhS(O= X +{&T#K|@MN\Y2,T= X Ϙ{6T#|-ߌ G'YKhS3Tsiʷ{E# 5Wwey86կE|*9uw}]$5ٍ澈$48{q,Tˆ= X`egԴ_Ʒ}0%^~d-΢ME. "ꟆCR#]'|<UW6 SR{EmkŊg 2~ngT_7}50e5i{6յ7zh|I)_H[ޟKi+˔3LXMH*Q@b/IRwzM_|e<qAYEoE2 'Rȿ?ʶx483s
 58gEj]E2 ܶ[(DMR;k(۽"QǢM._yJnH"/=6?F77~3Ejcg U2ROlvQ%-xK7K>#W" G Im}iL7_~NI좹o-%`)_EY4ɢMo&VD6 *=_PY%c~?^}d"uʢMh/E6 *ltQ)'+iu|3y h?y*65om T\bUTuS*
`eﱔmIhSc*1zPw;-i}~mt)|t3hSc5= [Xۿ2oON{u{[93hScw~P _0qҥ/?ǤwE_& TTJղhSzVN>mofSqUї 78gѦF?og 5V>znijWN202 qwKղhSZTvy \?ZѵǤT_ S0u֘E𒽢g 1;=)(|Ssʷ{ET>%@MNehS@Ôܚ~&e[(SM[Y'OxsJ٦,Ȋ} 4Y{VYzs2[!GγfѦF6 7^]~<U{]!
@M>}֩Y۾,Q?zŽ>k3w\?y,F=ha7:,)]~j]B%&_~*=WmjlC=h'5&<s/~6nʷP鹲hSs(=
hbuipSi.[	ON{6 D]qPfѦF7<wY O)-/-?EZ|۟HޟF #Iu765|M,! |4d꟥|gf[wzM7i=Sq7 P/_>3Y,FLV>b:-oSYS7vGAGW: Pg96YOLuS΋w;-ٍ֧Rwץ{S<, Xʶ~q٪6Y-ؗ" P{=
$ۿ2H}D=o|O S1=Zu:6M	 4aO;G uyKsm)gR=T>rkJe fѦV깏 @C4Mo:w-,\^cK6M[48iti|7S) ƷF+KmjM R*O-.8/᷶K>79lI}:oL.[|צ|{f;={_2EOIߞ9<; ֬_KNY5yW  Rf+JϖEFxY	   kx6JEZGJ   xnV}:whSʷF	   jtaWmj]o`  Wmj]=3  `Ʒ~߬zgѦVV<pm  {fu;6	   #lwmjg[0C3   28JEZg(   )|lPmjmNIER   HvOVghS]wl,  /D#Y|G8  F~ThS+NL  ź5XdѦ?3  zv}:SˢMZY*W==[  h/VVmL']=[  hKՙjmL';dJA  Ez7~Xf&}GDX   ZXy}f7
VgYIo-/   ~8>Xg&=ߊ   4\؝)[i=:SϢMzZ$z  p>~μd&=EXq]  Ul*Gm?s  ^u-6[i*+z  0eﱔ/i}|e&ɿ0   4^~,ڤ˗m>/   0eє/"~Wy͢Mz=  h&>WyϢMz_x=  20^~μg&=G=  7%VɢMzBJe=  r)E,Hm4  @MNt}:E<u{[\  'MV/Ugh֢mFg   j
UgAh֢A=  ;RGgY,ڤl|s  Xu<6i-9  @ޔśǪYIPqϥ  d&C=  olvQ:!YIT{E  zVRTm:?s  
{VuBhֵٍR  *)ƩY"h֣>=  %{߫E>-x  J%^U):6i=g9   0<gi=:ȢMڐj[y}<   PHߣ*U!6i  @7U2YI_=  P!e77UJmFv   T*6i
w]=  X@N
UrYISwGx   x>^Te&MgGz   [ۅ߃S,ڤ)7R*y  <*Wݟe߃S,ڤ)6  <o=թlm~S*  <|^6(Sf&MѵD~   ,}ϩNh\w_HG   L7թ|m<4l3   ))|~Nh|Wr*,   `
S}:ȢMg/>   @Wlɦ"6iꅩ|3  T,ڤyǢ   {WS,ڤlƩx  uT?˷TSm<;D   QTvYI3   #թemMs  ݔe}:lp˨mFjr}\   <GujesNë;:a}f   ,ץlɦԶ;ͽ:~-R->7   XL~ߨN^˩?e/IF   ѥ3SF8z{FjC}(   iGňEuj^S7Z4s  CԄw^8|#~)b}   }iL^Wa65d  LiLeVL#|OeP  N>26Y?@Rۚ&)   ot4oz|F$ٍRqϥ  @۔ߓ[*5}5?Hjc>+   ,ޡ#^P5ƿ< (B  ]qP=:lCzu&#(;*'"  QeXq\|_%y   4[F~g:l&)z\:ڒMS5  @c/%OuKx-FןImR*s  &Ԑ-,O?h+x 𒽣  Sw_	Sэꋶ|6/|   liSܶE[ؿᤶ?}  @o93eitN?kE@I4>   >_~oNϾh++4و&U}  4Bשӊ=mnCJ7y!!  F}9uђMS{m9+<  C'_2~?Ԇzsg,FJzoN/ԙ  P_A8uZ6϶{E+Ɇ}qN%  7FŢm?K+GSq.  S6(Mw?qE`I?wT}6  N])emjWk^E[*Z^<O   53~_U	GϚ%=_o#
  V{55.ڊGJf7
%ޗGH  v)-xRMh~ _3
  fe3Wy_Ϻh?5}iS   5z.ƷG=~)!|GJe1
  &Ǌ'S;ֵz>-4?^۴)  Z8eSj|hKAvxuFՋRt\  T[/{IZYw7v2WHMK4,  *OoS{kz}Eo?^Y   Vw{z}^Ͽh6-}A*v},  J<KmvQ*m{1(i_F<   i|i)(KvmOrvPҚu  |o{-|KR}h\Tf񍧬    A{0  OIDATJ}Z]N[Ӫ/JZ|Wr5   c}61`IkwȻ澕  ~_GR5^E[Rׯ%M[  ¿`Tjwsn븳^/Jonڠ   ץ|SjuޖR1ZEe\w_Liop   XePsQjw6ދT{;"$  0FO#^Ed=)2$'LeP   L]Yo|zj/ZM?1Y"im"5i  0E	gzvJaumHz9Nqh   luǦl/ZS;u$iNT.u  Um$|K^6Ed{,{1/JҚ]{̴.w  R>~Ow#%ͧk|jѻR悑*YlT<x4/y  VHݽ~5H-ovQ]y{Ou61ڔ-{i_~RӾ  xz+Hüԧhrjtg,d JĢ/巢 4H~r-Sݘmh9U4-7ury>v]z9}9?p]O/'۾퍇q  ˱}&?~C%?v׸pef?'u  <=3loN~hmUNbvCw  OީK]wd}G5Rm,7r؏   `M-cluvGzzh7?wظy=  _1xg.o9kHB۾>96_h3{ގ#  ɷccv'?n׌?жoԿ|/=g^2Q>
  jy19|6=pm/}}k{Q?  d}~lol}g&<[g4`f_;s,7   sc?:tW]:viB۳vx$5[m}[LX   ӟ<cWN{l+-O~ls盧~,   bl&?zn7|eyLlo:df_~*   ngef}˘#cFh{Ƶ3[y{	  
6g[ Th[a\3[ͮ{XbG  v?vf36Ǫ[v?1f7|o:oԏ  `g[{cq;r7l]ׯ_$  ӛ?𾃯M}N54v~Xn8NV;=k/oNd7l~   ?xظ꥓OW;c,/<9c.Z|uǅfGS?~`G   0xܸ&vb7抱so3_ٱ
m-/Qecqo  ?sy`3ͮ7ؖόXؾۮ0[ʱ?O}  Gdm";g?3~x8Iuhhձs;ݯb1;޷O}  lYͺdl}S:	>fvxS  !Y<:a|/[{;S_Gą1G[%<q  X<rfm]c_b-?qrC۹{]owl_c  "Gٵ[7
r#/elNtnoOO}K  ţg^>Vh/^;6o;wؽƱ8c/N}ɮm/9O|j~}c7͛b̮qKV}.n.  WFkD[k{cO{[_<6    m             @@h           B    6    m             @@h           B    6    m             @@h           B    6    m             @@h           B    6    m             @@h           B    6    m             @@h           B    6    m             @@h           B    6    m             @@h           B    6    m             @@h           B    6    m             @@h           B    6    m             @@h           B    6    m             @@h           B    6    m             @@h           B    6    m             @@h           B    6    m             @@h           B    6    m             @@h           B    6    m             @@h           B    6    m             @@h           B    6    m             @@h           B    6    m             @@h           B    6    m             @@h           B    6    m             @@h           B    6    m             @@h           B    6    m             @@h           B    6    m             @@h           B    6    m             @@h           B    6    m             @@h           B    6    m             @@h           B    6    m             @@h           B    6    m             @@h           B    6    m             @@h           B    6    m             @@h           B    6    m             @@h           B    6    m             @@h           B    6    m             @@h           B    6    m             @@h           B    6    m             @@h           B    6    m             @@h           B    6    m             @@h           B    6    m             @@h           B    6    m             @@h           B    6    m             @@h           B    6    m             @@h           B    6    m             @@h           B    6    m             @@h           B    6    m             @@h           B    6    m             @@h           B    6    m             @@h           B    6    m             @@h           B    6    m             @@h           B    6    m             @@h           B    6    m             @@h           B    6    m             @@h           B    6    m             @@h           B    6    m             @@h           B    6    m             @@h           B    6    m             @@h           B    6    m             @@h           B    6    m             @@h           B    6    m             @@h           B    6    m             @@h           B    6    m             @@h           B    6    m             @@h           B    6    m             @@h           B    6    m             @@h           B    6    m             @@h           B    6    m             @@h           B    6    m             @@h           B    6    m             @@h           B    6    m             @@h           B    6    m    0qSKX7=    IENDB`PNG

   IHDR   r   r   ݅}   	pHYs    {Rk  	IDATxwEǟ bÖhb5Jػi$أƊ8)(MrJAHSD"lߟy}7o۷f7H27JR(R(RtLs#+Ʉ
lvѴD1y+'+;8Y`㮭=0H">{$r}(d@ F/j9=[	-SWά` \?֗/DwKiYUYF]hhS\Y|OGx8E#ǯLgXȘ5"=Yjo
Nx^3ކ}o?.nȦ
'sCANz2a!o]SSvQudφ̮lTE37+U<{ЁVOьT 9>k's-Ƀ7/nv6~,Hs|O$m?e@uW'[?wƞta{/=K2x}*d@g~*E!׃\|^RqZaOzFa3w ])xȚ>@"mv^$Be1/;al2\,g&z8qDִGro8t6E@8!g~_ƃ=u0F#ANddrfҜ+0[;os?=OJZhLA sZ>,ixE8E"
9A*mCb3x8*Zb 1B|"+H&S	0]@b/JF10]@R%1Am	G`Zs6 w7rcV s!7r	`6rcV  0@}G Xa?VM&i:MB`2aڤ"3I7@3Kaxx9"|䨻
~)=+
R,L&Rw
()k-TRa-+hqYv #n#7Hrd /te7Vl @ZjXD{?^FZ0A+Vn6=WgBӶ:;qWUdV#Hkd I "vx*%7)Uh+v%QIlQ,p\_qT'?On@2Ocɍb`Uj. LJ=O&7),=Hש|4(BU },HbA%o<r{@ 6~<iHs10;}Z 1p"]eIDyQǚKG:? s=r@K?&mOor(k m|GQE87kQi Z1iڮGћ_=p'5A~7䃮SN	{jP	!G9FON/X@%|PblLC:@bb`(kiZM'p~034߁mG;+ڦ
Oʣ?i{(eL
$<q<x1 L	ҪDpOWTB~瑁t%issE|? (E&im|' ݛhJRw9{rK^"lHK>bAҘ٪JGP
It	g3Q /=G*TV, [
%guD-/bAߛZxu@7ca5sU7ϐɏ(ciTP`9Ph2P!rx K{2Z]ifU_x!2=1;V()<p[Y_<H<L5lXSN]) Z*IrlHPUApWԈ7D;j7nFųkϙɂĵ<N%Oʉ?H@R)/JlF+w$u*>
i
%4{Cתyv$
U̒о[S^YIH^lNB*H"YԞ+wN$ݵ!#
S'ZP)y2kCF\d3rJv&ggHq#ĸ%G~/o]mML㇖}32T)/,mTۊ`cyor5_9a`ݎi`?&w.읓7O60D)HMD)HMD)HM=    IENDB`PNG

   IHDR   L   L   ǗQ+   	pHYs    {Rk  IDATxklTEV$
D;/1#~hԘh$5/B-U D
[bR
OmܹICݻsmwd/{u̙s& q	) &80.%8MM
ho#Ēc_JubD`bPRݿ+X} ġO%mCiW X{()	ޠg=z4d.,9 dhEF!OMA@-| _}d=:M
I`)m eQ&*8+,}.8 ,z<`f͇Q51΀s5YЯlj`VgHS>5sĉ&Z0*_ڽٛ90)t!0~|+'9=0DAZ <;acv^Ώ@J XJ8 [oEaC[q3q|[GA>0)0m=T@ͻ3YMCCfl{ٛf=MheJh
iZL]y+>ш80z=t4:0T3*0ڹMr`uHS؁,a	\`fݵr~Af%706Pe<--0{J?&y;?F-̟?t`֡Mc&*0{Sb`>'agr:p#.0 6<,/0sec-"ͅc-؎6J9-JpX[z{^33k?Vp:0U#/07T`>vLlx`Ksɩ)M;
#90ܣ^%{0 <:0cIMm]`l}EPV3ŚS{#:0\TCjm<4aJŀqƤ{8YI?i@vlHD~~(;0Κā1G-`عƖWŁiDmdf9"9H]b80ogE/b\KfUsdni8&WKSԜ/XȾށƊ_G56ķ1~;|a`,s/k<A1;@F&ƷI~b['%+5ڵ|΂m9<VfI!'b5 (tr+~]ԿlQ`JJ(Y#Ki'̈́ULI>SBM6VHx:}HnYxw)
d_^g>tSp E	? qo|a#tqԧ}T9%AIae\V/\;&v'YbU\ͼfʦZzR&~&80AŁD..1    IENDB`PNG

   IHDR         x   	pHYs    {Rk    IDATxyU}bQcՌڌmӘfjbmژ66I35if.22"(8$EgPgg[X\ݟ~^]+p                                                                                               ( ֶ_8gӿ9ӟtޘԴl
g|ڤa+[ӫr{mŧ=GEvq[pޏ_O$?p[& *k&լĿ3Yv֊.XW9!_Y= 6TIk_5+`q[jEw}ʽ JtKk(^^1\_~x@pYS/"իR_ 'Կ}E_p]9 \x<G- 45տ]yg~|Yߛ`"h`6kV6a6ө~^LA.ja
 ]`'寱Tk/˦-9wʳdQQoQ 6icFZKv'~{col9nց	 ./ͥZ>_9M]rmxN?ozO@nͫk/G?QcZ8\@]oMkOk0-/@0DQc(k1?ҽ;gp`6B Tk֞w~ש?7ruOuw 4A~]Z{s "vg[ 
#Yg[8ۏ><&>k P8uuj|OxmG![l'c PXڹOzMvw>[k__Wd굟m?S 7_ɶWcm'6hEP) pC`gTme_e hH )YMWֺm<|Ï_9+POYG IӚ_ǩ~etoO&+Jްs? _˩qdO	vA%a6|z ΔS5i oez J!7Q}iђ__n"@E(Z[_ TKs`K
F ?`͟  Vt k<^,tc`7g:o6  ?!ZoOk3Vlv RK=f~տ͊}JJ0Z~z_ @%4XOfWּo𪯫 TJpTъ	kf*y?_4ܩ P)EּoU/m5T@rM\ PI9sEwԪxh`J<K~
W㘴~yL<$V} ޠcghٽ*5 xu ~psT 53 0&R@8;u OZ3T ސmoSs nDbUf ^ H~V
U+i_~fTSJ? Rg @eg'?;L* NwZ twRi oQ65[ Yi[ 0 `_XԘ+ \	 pWxw)q ^c-- `6snt@ thq?bJZ I6z tȳ޹'SJ5 橗* 5,?_L	+ Lz >/?gL* кM6ݣ^ n?ri)W ?PM @7.>M~ޘ =̦;VK @7KZaMsǔ$5	 I0Ksǔ$!6 d}\"FwSE @β;S ao6!  gs[S~sv n P]o!xN ް_ PaP и ]Z & %</Z*4 4X  ^y\2 9F^o H6[*0 DR5 @S>+?93 4oS3@*tn{/z?p![,?93 Tƀm~?0FKslxWG7MDK{\6z6ݹQ/?)Xn =mqDvkhqoޠhQo?SI}X3CV@xkk7`ëeoWL>Fl^\pR[INN 㷪ai}e?l?~-pNcc?]5w{.3}|tI`ڙ6~kT'^]YoQF eK
ؽ$n~߼I{;G6=8Px~-/Ƒ= 9ئsLkk~;_Gr.Hb|s(ݾ` Z^lφ3aM?omح5=b@2:lr(@e)^&^D7v ǼGPqɦ{l0_{`78R?eaFK+ 2@~PQ٥vhǝҼ=+P;/	S9 Ѽ98j$|Zldi~6Qq8~V k]ln/KG'yFs$r 8_nPoowCe M)p -u/9|͗86^7OT²;j)h K-[MpX5UZYݓeV76u^{
 Okl࢏׾)h ZUvPKcF+\, t4aGnjt<%9^΍#j &^K(.ޚwF󋥍USnr/R mC%?e4+_=K<ym{;-% J&^;o@;7YJfGר)y R?LZkz(_~-ok^y3[\@_$J$^;PqϥG6yjEoo7ck0@"2EI$OaMCk:Xoq<o7VO4/n_cd; 9yIV`_%[Yo1E:l_|IΧ߳L'?R L>]Qio/`cQGM7k@t@چ~Nh
."?,q4/Ԧ^T+ <\6f)}z9UNCqe>֟kz$_T+ &zaIj|#7tޠs o{)wZo>UV+ϲް7˟[& -#pXv=p&);퟾6V5{W3F- K.ޟƽY/voO>ݚ>ȟ/9v hټ?;iIO{~W۽ꚷ~d>?VP?}GEwoʧ睕R7wFlx׭7-jL: Hȳސ䛇qŶo6ІmQߛjH: 4VMUo?8(u|Py.ům}W?Es{ #\n|׺$XѢ6zl }m^얢MCzhݸC7#j) Oz5IܼazӐ.{z:[>P!2 h71|Ðh\]}m֯&|R7 2. nb/yvKoy]:w^"S塐)X}]}Vܞl lWMo*P=mNtۣ|nO" !wAJS=QYXl`kO4?6P?^"S$@!JX&(TGs7Ipg
R_KF]I퉬3@t@x&(DDdI3H6'$DDI
--$DDI4ܩ>W7	)a o1MBDdJX
l^- DD> ~^}UȔp
j E
\!"2%-qs' DD> U+p@oo""Sr +glG9L} HW-p@n|s U 䛃Ȕ|Ww^M?7Qu >Wp囃Ȕ\ 
\9 "2%. cs&*DD; \9G/DD: W\#'7)q 3>Wo䛃Ȕ\Q+ps|s p
az'DD; K} DD ѭ
 @DT+ pG囃Ȕ|e
 @DT+ |\# j% >W "ZyƊs0o""S P}ހ䛃; 5I}囃Ȕ8 ?]ADdJ> DD+
L|sF8"z|s pPGW%DD; 2@}o""S Q+pD7)q >Whp "2%.U+pDcT "2%. CG]/DD; \#+囃Ȕ\`ڗ
 DD; L>]}/DD: >>VP!"2%-`ߨ86!"*k ޹'8$x| tT!"2%-fm#T+pD7)i Ms' DD> $<>Wx!"2%- ްT}w7)i 8"7)i 
b"$DD> D8y| P?3	.| 7	)a 8$Z2XIL	} ~ ƚMBDdJXiim8"yz| мfG]MBDdJd Ȯt7XF!"*@2 U)pGȔ, XyLC«%(DDdIhQDz7
)Y 3is|% ˾>SBDdJd ǽ_}!MQLɒ ^#g
~|% R9>),DDD3n#,DDD}W8$[BDdJl n>S䛅Ȕ( ^]?%,DDD`3!0DD$ ܿR'p?CDdJl 0zX3	g~[aLI Oܯ>Sh`!"2%I: k8$^;GaLI #g
<|$ V)pI[!"2%H: S>>R7)A6yǄ|OiL	 ~֍LC7)A )ƻg
?PiL	 USg
z[囆Ȕ  Pw3'8DD@p	\CDdO> #NR'pL}/8| h g
X5Eq O߭>SUCDd@g
\i;@yb {c#<DD
1 Ӿ>Op7qB  :Hyb 0[3^ <DD1 4	J}!yFff h}LcsO[""h <cH-q O8Mnf im8$^;Gnf JW)pH	%"2V ~`LcA[""` E	\%"2V v<c7Vnj E}1W-qB Wg
<~W싀-V)pIZuKDdp@tH?!_DDƱ
7 3>O2uKDdp	X5Uncn 0m68$yf~UM6T)pG-qB G
MRnCr g<c7ZnCr ƚuKDdiim8$|S1싀OQ}1ޠc떈8RahXySϐ[""H " :Mn#v ǾW}1k떈8Ra Ӻu>S<_DD-nT 5g
}|* Y_[""@ T'pLd|* ~<cG-qB ~6W)pHh%"j)v />P}1w-)x [8&[uKDd
^/8&Z~|Wr<c+떈 YO$iXP%"2ΉqL}\nLsb yJnLsb &}R}15W-)pN ^ìMb;7-)pN Y3=AnLAsf h>O-)h R'pLtP%"2͙?}&_DD93 D5mѯ]" pm#/| ->O떈0U'pLK떈0 o[	<| ڬ>S4c떈,x\}AnLrn K}1ђuKDd
s@pg	j ^#}| l}P}1[""S 8~ï떈('n@gk-)PN 8&Zӫ| -bw.QK1rs ȾryǄ/_DD 9; d]-)H o8&z <Y}A7.)@ 7SYyԯ]"} ٝ^}1mC떈 hQoy$OQnLrz >O8KDd9= x΀kȈsz J{D}1uKDd9? 4>Ox%"2 Q'pM\!KDd9? ?>N`ҧks~ 0lѢ>KDDgMr }[,_DTZ{Z̻mxl	6ٲ4yupT@|0a6U+oq6,-eY{|Y!W;bo?!_DT>󶾰k$o艹>R {UvȽl
jowswb ΀k>Z6&Ws~gr {#"Q]"*[ђܾ+m Ϻ
.|&6|>}nߕ>뿿4  IDAT w{ Dw&}6\ml~4׿Ii ?~|Q'- _&f ΀贸FzQW~nY)׿[ \9%<c"T@}O>Bvh7=/G3sj '|XAKTg6VNܾ+eo^ygFإO* M!/Q͆W;p~nߕ˿sP "˺	A5dP]R6{+s--_Hy) -~ݗ.Q)j;N])3>W +ڥO!ݹyO	%r_{Oz;;+\ g^ȩ[۶T1t@VqeoY.QQڬޢ`q)ƽG8(^7Ov$95_?r ;[iu큩s{~>]J9 d@\7QGuk@vE1ЮKg?[=ݦ6:\K9[ܙ;Дl}Pv:{ҹ/>Qo!ܿuv n/*y|ҹ|n_jޠcs]S ϼUR~yCOl^,Z2nfTo 'uVx4^^ _T~얷\ǤFW#- l]~JFh/sewNs{(5K= 4]˾(_TqS+#FA%>, };/p7K<<uY^s
G;ee{?x]@UuEz3
qe@/P?pT|R9U/g\eH6_*GܡE ] WnA,~RFկy@ve%[&KY^(pwr_ oӽJC~lݨ2
.\{@n`=AݼGW1L<5Y _&w~N
nyJ =?H݂i_R/a]Zf%GO1\47&7A$ݵI6+3 4xO 'arƊ勂KD_6 [0Y6E5\-Y /X kaocrNzQp#$k2@s#xB<a~-_Vސ_Y M0U0t+&Y ?T?p?uLjJ wIt :&wj^p78 `zKo#Z&'JJdQtqݚ^Igl"_=]tqEc*~ް7*n{LF+7 dtEc:=Hh IzRvENEǪW*6TF6 dW?pwW+ټZLh%]9lO? |6O|-S1?G<%![ A6IRe*f7' ] p}R7靊0kzuCKje%򯨗%-.] K?~Q+g*Nר%
Pwq~QU_g*Fy|@V?S@;e*FT} /ldӽGJ  J"~`|=d)e4Bf+= d`L:@GKIVcEUj ٦]5UPg{B@G>"_ 'أ4y'_Ӕ\W׭}~V} emwwӿKuU +ybz=D/4WtKcev j~sz=Di4خ^rpL8k7S>+_EwS/58b_=li@$>dMk-C Tɝ&=/|]S7իUx\S *,@ɤN9^^/f|SM? һr/tƽkb{Ϳ5 ^RڽVvW|M_'F𻂦 s /)}@	V~|}ӾWwz9akk1 $o1&A	k7[Zկ|4o3#_ߴ=&ϬU/!8?} u?SUq գyv`_67oA/_//򆽹yW7;7?jRsx~eh}I6+K6ޥ^+(
_k^.(_ 9[t|S.ƥ~y v?=]{R_KZ\9kz$Kkzw1 SAA٥Z]]~zw1 . `Y酲j??k{w1 ?]]Jeka7_ %Oүvb C!@W7mCro'=M45^U6~nz|^|Q-|KZ^0LO7J,||)W)~BeoIgoMn+'bT@}a|)W)CBE%Ohe*6EE%_{Uo!-CK\F۸2Ӊ
IWerdFK@[6vETL}a~J (PP~͟Ufw_1W#9ĦNzibAWe-)TXЁ :X㮋k
xQ=k|[7
QCm}tۣk~TWHwlh޳޴#=?
Zoё :Q,PDΧ_:*=ǻ>7kpHc D[@ev.6ںQvS k4y@kcsOps{gem@>3NGc d5IS<y赟|w4_57 ɂI 
ƚwz.m=&> &78ՙ :[6>@Fe٥r/f'|zd߄Ǿ}QDlͳb_3`//zIog7'ʾyոf/7/ݿ&a
.>M~61 7o= H6|wX}61 Tc @xg@e@ @ִF~&1 \( \~1 ʾ- 4|VY  xB ѭj 
o3@XvK 9j(? 
P|z- n P'Y&%	 Av -K ^~tE ]T0T tƽϛ@ Pbqd'Ϛ.zy Ics+c 'PQ @Wk;ӕ1 tq3 Ţ%KW %O.WU @Ipl `ʿ+ o\ xm5 Gb~ϔ
.z Q8b Kk VXk?Y]1 tc 7 9  Dϓ@7P  7uc ȡƚ pF1 7m6B xRkz JF5 `OKwKkzHm`zy -%?+,Z5ūGR^ H=V+Wc5oRZ{dj: T࢏ψ^ysRIR/u KDg_tjR `Myυ>I2\S'Z[7u G~wJQ-?V?U V_Z3h??v:uu7ޥ^ PIi;@VO2ȷE/I P-c#?d&?qS?6W*W|#7²<Zkyq ab71 *!u߈VLHo|q h޼MXpe0 tه|A6ٵy |hUƊ{ ʫn?z#._+ m=~6yR
g~[:"uo7;h{ `)d/G Х;_M
g|#s|֞[;9V (>Pn>ܟ /\>&Q p^o_[EzgO^mjUl +m0sS'YV(	~U> Ϊ;[:nPklwx h~0sau{ >RRKGd9SZ7wUx4W	Nռֽ[ǿm#oܤT5= n|!mS+̆&}83PU_BK?no^;&޳Zk{ֺO2^V]_ PHic-6(	4Z{`+ym͠c7Uk`} G64k)@geo_~նԎpZrs Ő&6MkQmo50}v:9L>ڤv 6d#zm<r&kGjy5Ӽ<T He_Ve=m8gikDk5{v@[Gj;XI a%wk}ڛofWk2w|tz@[-z3m`Q+V{7ꯧ~?&W# "uu?dOZw{QXbeHsz_@5bX_wGf=*Vϴyr_o;ouO>D?tYƼ7N[kƦ}L;<F=]ἳ/>ld                                                                                                 Uw9    IENDB`PNG

   IHDR  	     X   	pHYs    {Rk    IDATxwgu}(bÆ%1bM1Q5Ũ)]ה͵n*i){30Ф7A@E2t a0ao?lY@ܟ[zv|Μ  Q\>svjWEkN?? VzI^}   bpњ[.#PwWGDe߳6} ,?3  hn9;zkF4VQ?;  0M4c~k:Xf    c;wE}C?%#$?l=  &T½k$%)>M;oe}m  ` ¨1|Fkd?ͣdE  럷"FҘss"?    dpۅ_Fk?J[QE~0V  DIc֪D_>    lp/;8_Tچ:)#ٷ  0ezgkZ蝿Gԭ*  &  ZcQi[~;  TK4g1
 	c zA?h-*-@~7b;  i4;$C~5.O.  &  OhpéQB=O"a  ̂g<=HdT|F 3 aoJ)-tED-  PSGIC~%kd^  )?  ex5>5[  U0:A{ɪ};c7O0  ƌ  QWFOI)wƇo3  `{97ߏ$MXK:ݮ<} 0&  fY]G#y/-ū4  yMhߕ$M^^k>} 0  fTZW307V  Mu}E;G D  w>(cKϾ   WmQN&ωW>  Hb 0CDJ_  }/4uW  #f 0#}&Z CT4   FYR&=8<78 `  ݰ/H~dq   [dvM>-Jx蝿GD]gi   	ޔQ*ܢ\vp-  UW߭$Mtuwc @a  SjxWJ(7]z`-  M~,JWK9H  ? )Կh(_[  `A]%i
ZzA @!  Swfo9  ;ߵ$MA==מ} P 4C-  Xx0:ǽ3K4] 3  :'iGDiDOw  @9vy}4	 0U  &ݠޓPU/}]  P\Ӻ/T;} @  &٠cN&i<  >ݟ.&i:o   `KP(w  Ho=?ZKN&i:ꝷ2X ` LgGBiTu{  `>!Zs$MG>    H0(o跳o;  TVI涋U>  J  w>tξ   BԿLO4%-!kdk  l? 	ҿjy  `|ԃ[kjbxM'  [ `Bn(ZKwL(jfٷ  iz{D]=}   &@]Z(xaߘ}  摻$MG폿=6  6 }?IZSȾ   ^}Z8IQ   `uO~H1[  `b;9Zs$M~s_>    cQ)1[  `,4U^볏5   7K'onQzd-  0&|_};O5   8>?I}8  oG_J4/?4T 0 CWؓFQٷ  Th6/Jϓ4U˞dk  <? 13h-1ÞTi}  LEk$M~~3H 	 ۟=u{  |w>IQOdi  <? 1һyR._en   SH4U^u` w1 {򤒵W<  `&2D  O*Y~[  `&4GϥJo{>  6  c`xњ.Tjٳ^wE  0Soj祿J oc 0ڇ)ÝT	~o3  4wCI33  ? dOI`'lpaٷ  LYn(ik   S]Gu?I/w   Mcޖ(i  ? \OLP'{»   CQ}'%MnC^} ` D~;.  ;3JRQ 0  t:D/{o1   c%Mn~# y  I_NZώg^   |S>(ir   K?Icxiٷ   OfЍA4u?O1 f s?Iಃo-   6SV.)iQWdc  3 `GEkS?IX]o-   p֞N)i}e# `f Xe䤅soDԃ[  ?oE{ɫ}/e_  3 `azY9ij~y4퇲,   VDw_Jw_} $? |⤅yQSm  6j:GOϔ4YO L2 Χޟ!NZoÛ}K  @.֒7%ML՞?Q 1 ~;ZwJ'-DKȾ   X`Lߔ4Y, 9  #2अȾ   (is;%MN- 9  #9}m}F{ٷ   4Jl 0s  Fa|5Uh6˾   (lxyZ}{ɨ~ L1 s?I[	  Y.*i"|# ` @KMږW}  0JM#ߒ>*i~eX  3 `^Mz}  y䮨V^*iV8, a PXh-J&mM1gF   $y5$=igW  3 'pj>   Y*i\
 `f ?pO˲o   ^*il}oO* a PXu/pd:   桵QxN}볏) a PR%;p}   06wVIc#c
 `& 4m>U*  `Lu?wWIYG L0 (ڤͭZܨ%  `5Ga%_?}D ? }6i[>}   09.+i_w 0  
j_?ISϾ]    m{>  f @A=Qo   &I}6V97O& ` Pʠۧh_ժG=w   kZC+% ` P?I߷b[  	?oEG L0 (dp٤Wٷ	   sq%G7  e ҿl97   l[Zw]I5ߚ}$ L=? BzMzU/fٷ   Sdpﻒ&8 z  t`bxYٷ   S{{{%VqqQ 0  
ؤ[  )TG%ﾒrfQ 0  
iؤos[":   `lם} L=? BG%U+wf  Kip'  g PH7`[>}K   0#ꁨV8}X\# ` RlҦz};   0c6~߇%>~   @!N&eD};   0';Xh\{R 0  
%feόo   fTQ|Ae P @!վ?Mòo   fߏ%.?   
1Sfߛ}   qLO4  3 (OYU{4ٷ    k6K_T>?   
1SJspٗ?   |׎gT<?   
1SF/c   sߛ% <? B4og_   𸚍ZgI2 ( ?O/{   -X   bQֿpK   \D-L   bQ9M0  R?h-1}Zg P @!EՊD   Hߩ%-|   bQ4ٗ:   la/ھHS @y  tޙ}  Vz~_KZ  3 (O%V Gɾ  `tOwlI @y  dO̾  `5QlI @y  TO~   f#ߵ%-L   bmMk}   is[߹%m{   b;9  WS>-[Ҷe P @!Z躟ٗ5   ;{.[Ҷe P @!Z?{_e   ^wpI[ @y  i!  Y0њ[.i <? BPu   FKں  3 (OQy   FyިV<7\Җg P @!ZW})  wrI[ @y  i[   rԃh撶,?   
1ӶT-)g_   fvM- <? B-/=0  tޓ.i3 ( ?mmC^ٗ0   k6eLWy g P%;D   Fo͒uI @y  ikꟳ[   ߎjKg g Pt/]   ;FD풞<?   
15]o(  9%}  3 (O[R﴿ɾd  `믋֒Kz  3 (O[!  ߧKz  3 (OӲ/W   s/J g P6	ξT  `8<}^g P @!zҖ=3wd_   0Y:6^d P @!z|82  TqqK  3 (O߯~Dٗ)   L~/;3 ( ?=asbs/Q   hDk @y  ٗ'   L6=_ @y  ƻ/O   
MuT+/  3 (OW/M   *HߗX   b_ٗ&   LA'~4_ ( bhnQo   4wI  #` Pߟ}I  jhKҬg P @!V=#g_   0Ն@  3 (OQٗ#   ̄qL r   bMU{hDʾ  `&%OM j   bM	   ;/ӿHoa   b}  iZE|,f P @!3ٗ!   ̤H3 @y  vS>}	  jzFǋҿH @y  nղgEK   fZ#f-?   
1}   NT{Hwi2 ( lӟj/?   `CҿH @y  f;   PY <? Bfٗ   mW@  3 (o   nM^@  3 (oK   x?@  3 (o[]g_r   ih) <? Bf}   ObxYi <? BfG}ٗ   :G%[4 g PlȾ   TyiO5?   
1C̾   -9) <? Bf_f   :ZsۥW1?   
1=3Gɾ   -HS @y  Mw-   R:O* @y  MoՊF~0   Awc-?   
1Ⱦ   mTsUg)?   
1y8   @M MS   b7]}i   ^UOZ  3 (oV<o  )s%?   
1zkd_V   $4- g PtU-)Cٗ   P@H MC   b7]Ξ˾   B9ۃ4 g PT-{V4ٗ   PP_K!Mz   b7=	   (lvM7i3 ( )ig~   0#:1[4 g Pt;/%   `D7)[4 g P<|[   P_&!Mh   b7uO   ፧&5?   
1E}5ٗ   0jM_mB  3 (oٗ   dO&1?   
1솷_}	   YaҤe P @![7e_>   @&-?   
1܆7~>   VB  3 (o2kKDd_>   =B  3 (o2\~H ,a?뢾4k>+ޚ%?Duy[tzw?)?wƇފ_*OE}Mt6d	 `+4ӿWH @y  M^LOٗ 9!]ScpA[x~i>Qzq+=    IDAT[-!:Gft?g?wy~|w^2?(  OԿw4! g P;߳/ G}nڳcp?EMZ;Zh}c𵣣T %ZOw4	 g P߄d $\uȭߏ0.-!2kD~0' 3{{@  3 (o~g_2 01_m#?ݓ8W7fx`jw]ܗ&!?   
1uWd_2 0uC1[dOV{X3ګV$'g~PY}eD=̾ `jt|K^  3 (or/ |MC}-4(9?U??o10 l7l=?   
1}&rQ$9Zs3]Os؛_}ihg4 g PdT2 6S7cp=]Q|As\d_Z 01W9?   
1̾T `l5Gcxé;џNn\}~*zkG}ٗ a<5?   
1>-K J]1geZ#_E 95?   
1~e c^m]~)Zsҟ涋'7ٗ) pT˞0?   
1;.ξL  u[$LWh3;ӟ8f P @!]d_" 0rxl)ږOvA o <? Bƻf_" 0M@/=0ڇJWUOٗ9 ci2 ( Z܈^+rAo85:ȖtO"+ FjxҟҸe P @![˾< 桵;ߣ?o5{U{4}$ޣٷ FD{ӟ8e P @![ N=jҟR?w 3^i2 ( }ȯd_  ѿxuT{,*=^ʝA7vrUT??+K   b78< mR~Ϣt窴9|ξ} 1y+K   b7~U˞Mwc [exۅ9њ[L~?k>}+k5ZOJ @y  _ye [ibx9MQiQc KJ @y  __ɾ, `4uo856)iSw~2 Scsd P @!U{Wd_ 䆽\yLW<)jϗ_ 0**eg P @!Ud_ Ć_TgQߊD &+KJ g Pdh/	 ^MO>?[蟻<dߙ uV *%f P @!S}9 ~h4n?Q{u-
 [w濤?K  3 (o|\wr  R.'7(uK3>1e߲ EGkR))?   
1ݟ1f_ #wF>UQ HNJY g Px_d_
 ̺~؟v[csQȖh 6SRR   b7w\}) 0Æ7?<uٷ5 <z՞/MvJ g P_~}~*i/ fЦQR?i1ٷ8 <ޚ%M)#?   
1˯nٗ DQ-vsPE]#; PȝZ4  3 (/E<62 `o(|3Pֿ kO^Ru   b[7d_ ̈`t?c4kU??} g賟Ҩ3 ( }	 0՞?ܓfGU |#?F @y  %6]4e_ LA'zg|hܓ4_ѯO vOFJ <? B? Sh睤}kyc yh-yj3RU   ba񲃳 LzVҘWvA =GiT g P_RMk})7u9IגbpqG =;((?   
1˩soe2ղg?$mas# "&ګ&( ?   
1K LA7zlmu? D`/;("?   
1KhѴ0Gl`n>Z aM@LJg P @!s۳ L-gFr皤mӈiݗ} 0cbx);S3 @y  %|P?v &YDUZ}3MRګ_͆;O T{4]WGD{]ҟ}Ҩ3 ( x{O}vOxwLR_7g; Lzkcp1;}h5]sN <? BF[7gP뢽gҟeFWKI4QS:q!ӟg8f P @!?r &P}Q99&iU{(껯> CMrV,αEi2 ( 6(g0C"vՊ]Mva/^ݓ>vI>I @y  A`/;Zsۥ?$W-vor(Qj.;(hh->Y$MS   b7`R4M.IU|4`5SwƇs3ҟ9Ҵg P @!7 `Ѝܒ4w' [<[Ίޚ%9Qg4 g Phj5 ܒ4U+wk, D{4j?C$= @y  1GkZ룽ϧ?$MF/zuG F\yLN?ͻd煤 <? BFp?j X=LU{4o> fҦwxlܷ3ҟ6??   
1+_|a/Gj7\JdV}'G t6߲}Kڶ  3 (|ߛc`~?$Mvxy8H~뮈ū{ܢ^f P @!# ;O?$MG#~-b> &K=z1蝾cwg g P_涛S wIZ|_DSgq cٸ.75Ks[g  3 (l_#`_HFI6* "蟳4:Ǿ==^~FK  3 (lsv0FC'I]Uh~QOt?_OŒ;?   
1+[}e?b Šޔl4m?bӫF}1hh-~J+io%   
1+WM#`4utOxOIӣ`5SfIt}GT?/4 g P_|_1;}璤٫F#`5GbxۅѿxutO|oT^~J  3 (+0.O&I^+(^~믍DD{]5(ܔ4 g P_olpձõ:<6W3;!ZK~>J  3 (L/lxZg$mwd7iz_kQ-v9(Iߞ @y  io, `vm-ʝӟGOfjިV$̓' <? B4- YhҟEU˞kOI`C{.њ.|- <? B
 ?$	jh:J`B4Ρo1IZ  3 (o+ I'ߏh#3#wຓwƇsįG|JJe P @!_+ 	kDkSҟC9[}lva/^=yx$I <? B-geXۢZs3H63O`ݨ$??kh-?$)1?   
1[ѯ Ұb3HjEq])
,cp1;}SI  3 (oa) #??$ikz}[xwo85zkDwD$MB   b??R Fhx3#IR)va/^؟oC&5?   
1[؆#`DΆ~YGbcv i)|l7]y!IS @y  -`Kv赲 HHUzq4ޓ}j65F7Dk4 g P9?N Fd~HB9#:l;75Ks;Zs/I @y  -\35	4KHR_h1Sn7ύ{GsI ( bpo|Қ&:G5#IZc>ma2QyuyA,.ItD'Y[2:SSC,&ƘEMܒQnvA6i
(6i-lMsz}hjj&u>s~#){m_uD}ܪ?גE 3 b7v*U uͿ9#ȅƫ6į=cskOM+I-? x  AEخUKkIZz4c<R.,֔	־Ns*I<? x  ASwg?% Ͼ7bͭ*/2xY_qp>[V?e   ߔ$O	@2~ɾ7kÅ2Ʋ;Oj5ON'I   @4|{O	@Bi[#IuO{g0L[·>Wz|zM$I+ @<?  kg Po$e606\Xz)v-}IԌ   1_礷e?# A-~k$)~?W|2xY_qp>e~n??ff   _ wFPKpｾ,\sԖa\WD4; 3 bWd?# |̯%HRS|fvP泞ռǽ?   @ͭ*Ug @soͿ3ԠZTlΦ'~5kK]KkK   1Wf?! ?~g$iu|oG4ۓAﾶ8tO}ǖJV"? x  A=O@αoH1v*=cY4*]gui+e~.?Ӓ2? x  Aտ'`~_$ɵ~I)k|w|V]_ͻ׏J3 g ^G #UUG2HR_g'6Ru-=yOZQI @<?  5Zd	vf$B=^62A?.Olϣ$Icf   ?`^~_$iV|lQَexeawJז~(gO 3 b7y3ߓ| L`EfU(7~-OO$)"? x  Aj|1xuN|KmYKz0#	TJ=J)My$i2 g ow]| LUEfg['~55Jw!/u$I;t    MK鷲)~o$js𮫲?TV_zgtzm)?'$5(? x  A&C5!$լWR?wHJ5s®<H   1ޞt LIJ+=pq۽6^VWW|QK4 3 b7YK~: *}~<HPk甪H'cP߸Wvxe_Β$m 3 b7Y[~: 7Ezg }6U2>[zgo˯H_$i{   @ɪ~: ꪪ>%7EVR};GP7^z|t}Cio'I @<?  ')l0HX7e7JT}w|O$I;z    	}"Ik*;BcYX|>e~nU{H @<?  ;@M'I^kgJʎpOnB9e~$I   @	f]PSDW\q;gޅonǒ$i   1g? uT:DZ{hZYT+m-vO}N%It2 g o#@[O%mBcYX^V$Iq 3 b7^d IaZ2|໥1,\u*P'I 3 b7^'{"I;RޖؽepYwњ9aY>$IR~    Wg? 5,\["I;\s;WWep%~-cvI   1k~2 jDv:Gt?2[Uڇ̯9$I   1K	U,so$n>sw?yX2H   @~2 &Կ;"I;r_RpaU2pa]tNص}v?$Iھ2 g oZ{=3 }įI[ܛ/(C^ZvJ$Iw    ^ӯ~. &4|{wDJk畅,2z&Ie   uM#$Ifd   /# P{ݫ$I$A    IDAT 3 b77\ LϭJ#$Ifd   Y\ L`ڣo$I$9 3 b7bs;Xs0Ήoɿ#$Id   h>7 B;"I$IjN    V{ݫ
	nj$I$5+? x  AFg? "I$IjV    VT L}įI$IR2 g o/yLS0@[~C$I$I   @~qS0o~?$I$I   @Ѫ٘T wJ$Ie   yR)AS0C$I$I   @m:Φ2?*H$I @<?  ۮs볟	1n9'~H$I @<?  ۮ{e? c]OC$I   1v1 ;k$I$53? x  AF#	qTUi!I$Ijf    m-gg? c>pK$I$57? x  Aog? cXIC$I   1vUg`>vH$I @<?  [ӳ1uy}$I$57? x  A^SD JkM$If   '`զ;o$I$ 3 b_'`[K$Ifg   wO~;$I$I   @׿'`3ޝ~;$I$I   @m|w	O:Gv$I$5;? x  A`ÅOZ<+vH$I @<?  [oxOwC$I   1zU'`DûJ$Ig   VZR* I$IR3 g oZ?/y CҵC$I   1[a< {{o$I$ 3 b|ޔ< ~;$I$I   @G|$I$5?? x  Ag? 2So$I$ 3 b|w~ FTH$I   @_yX 0}7I$Ild   V.L$I   @vQ 0~7$I$I @<?  7g} 0eI$Ild   U|?y Q܏I$Ild   UGu!I$I   1[UT`Dޜ;$I$I3 @<?  KG1?C$I4 3 btO0i C?~;$I$I @<?  K>OZ{X$I$F    -]e? 2z!I$I   1[ޚ4 lJ$I   @`D#O$I   @`D{֧I$Id   H 0~7$I$I @<?  K?g? #z^ݐ$I$N    -]k{g? #tzݐ$I$N    -]򃲟-|swC$I4; 3 b̗~׬~ FpwC$I4; 3 b̗~%i QOI$Id   / f]ҵwC$I4;   @rN 0Ek$I$iv2 g o_4 w$I$iv2 g o?:i QܿK$I   @wC 09J$I   @-i Q+~7$I$I @<?  KW=vo 0YK$I   @f? #!I$I   1[2\~ F_I$Id   yR 0ʿ$I   @ŵzf 0~;$I$I @<?  kg`/i$I$N    -3vH$If'? x  A'1tO!I$I   1[\kg? cC$I4; 3 b/~ =C$I4; 3 b'^, I$I   @ŵ|q 0L$I   @ŵg`s?~;$I$I @<?  kg`w$I$N    -_~ лC$I4; 3 b)Y CC$I4; 3 ba, }o$I$iv2 g oq_, AC$I4; 3 b, a#o$I$iv2 g oqO"Y o$I$iv2 g oq#_, aSo$I$iv2 g oq^, apYC$I4; 3 bѿ, a!I$I   1[\~ 0xY$I$N    -ί-ûM$I   @ŵ?!I$I   1[\g? c+vH$If'? x  A>eC$I4; 3 b?, UC$I4 3 bց/~ $I$i62 g oq, !I$I   1[\ks13I$I҈ 3 b?, }+$I$i62 g oq=, sܛ$I$i62 g ov{J 07~H$If"? x  Ah.+~H$If"? x  ATU 09N$I   @+~ 0%{I$Ild   ҕ~+i C#o$I$i62 g oΦ`>9vH$If#? x  Aj=4 a!I$I   1[j=O\~;$I$I @<?  KW=`#o$I$i62 g oߘ4 =~;$I$I @<?  K7`Lk~?$I$I   @~q 0ڟH$Ig   n>+i SI$IR3 g o/uR 0gs$I$5?? x  Ad? c~$I$ 3 bt+~ $I$ 3 bt4 C$I   1[ޅ4 iuC$I   1[~ 4C$I   1[2i M$Ig   uO`L÷I$IR3 g o:'4 J$Ig   uy} 0OO!$Ifg   ҵ`OL$I$5;? x  A}K	zM$I$5;? x  A~ &9m7D$I   1[>?4 Lwo$I$ 3 bLk4 Lo$I$ 3 b|7< i$I$ 3 b|զ;16\~?$I$I   @`LoJ$Ifg   n$y Sٔ~?$I$I   @tz 0OO!$If   V3|$I$57? x  A:Ǽ>H$I @<?  ׻	t7D$I   1[~ &;7D$I   1[< Lŧo$I$ 3 b|ޜ< Lp}C$I$I   @kw]~C$I$I   @k`{o$I$ 3 b|~$y DUݞ~G$I$I   @4  @?G$I$I   @W~" &97D$I   1zÇn~" &=]7D$I   1z\D Ln7D$I   1z[~" &pq7D$I   1ƗD L`pE7D$I   1zKf? >!H$I @<?  [w·Ize~nU$I$5/? x  A^o~" &'$I$y 3 b:Ǿ! P{ݫ$I$y 3 bڇ, P?L#$Ie   k'`B?~G$I$I   @m4S)~30̿#$Ie   ߶6ߓL L`"I$Ij^    m=볟		ڐ~C$I$I   @m7g`Å2z;"I$IjV    㳟		|Q$I$5+? x  A]		u}c$I$5+? x  A]܏d? wD$IԬ   1v/I30I#$Ife   ߶g`B>9H$I @<?  ۮ}/e? ;"I$IjV    m־~& &TH#$Ife   ͭ*e~* &D$IԘ   1ꑍOڇ<H$I @<?  5O';"I$IjN    %O~* &;wD$IԜ   1ed? Z;"I$IjN    Ve? |kwD$IԜ   17 P;"I$IjN    VWf? D$IԌ   1~* jh+D$IԌ   1;2\~. &I$IR#2 g oMwf? ]wD$IԌ   1g? ZwD$IԌ   1N~. &4xY$I$5#? x  AF	Uݗ~G$I$I   @֞H%$I   1ɿ\ >Wo$I$)?? x  AF@ݓ H$I3 g oZ?? w?I$IR~    ]J	-?>H$I3 g oMwf? ue$I$g   x6^d LlJ#$I   1g? 5D-$I$f   x/- so$I$)7? x  Aƫ{;g'H$Ir3 g o:/O@?~K$I$I 3 b7^^d 0["I$I   @1[s)^0o$I$)5? x  AoІg`Rհ["I$I   @l0 }/I$IR^    M5Ge? 5tO["I$I   @]@ΥI$IR^    _?~6 jX["I$I   @k{UPko$I$)/? x  AƯ@2?S=$I$d   d=>`v~-$I$d   d1 sܛo$I$)'? x  A&kݯd? 5`-$I$d   d<4 auD$I @<?  ;O@;~K$I$I9 3 b7Y' j?~K$I$I9 3 b7YOBPSkOI$Ig   ߄yr)APC7I$IҊg   Uߖ| ߦI$Ig   n=/ D$I 3 b7y+~> j|D$I 3 b7y?| PL%$I   @߳Z>'H$IV6? x  A&ɟ~> j{"I$IZ   1]Jzg/H$IV4? x  A5|'I$If   _JPo$I$ie3 g ^~B j/H$IV6? x  A;}O@M}~O$I$I+ @<?  '1K'$I   @z>'ޗ&H$IV.? x  Aj6N3P5$I$i2 g ~o~F jqy-$I$\    o3e~n{"I$IZ   1_ҵ@MOt=$I$L    կ{ڟg?# 5uND$I2 3 bW~F j]{"I$IZ   1_k.?1H$IV&? x  ASJ%$I   @4A̯yr=$I$g   t_yXSPSI$IR|    Mޗߟ =$I$)>? x  AS7d?% 5/3H$I3 g o:wH'$I   1^Uo$I$)>? x  A+:|F=$I$f   (~O$I$I 3 b7z49J'$I}z    IDAT   1^ߒ Կ{"I$I   @>粟/M'$I   1bw.e Pu6o$I$),? x  AZ{"I$I   @iY'ΉoI'$I   1nw~R j}u.H$I2 g ouO'O=$I$e   tk~/H$I2 g oʭޥnPG5,=S$I$I! 3 b7^ ^{"I$I   @/?1Y{{$I$)&? x  A_g?+ 5:"H$Ib2 g ouN5Yip7$I$)&? x  A_/~V jN7E$I4   1hnRu~Z jj"I$Iz    4_:'-H$I @<?  A_^{tPS$I$i 3 bSe?- 5n:=H$I @<?  1u}cPSmD$I4   1O@]UUZ{hM$I$M7? x  A-ys$I$i 3 bz~$H$I @<?  qOH'$If   _\3ߓ 4{"I$In    >5@]Ai7E$I4   13JO@MuN)$Ie   _lÇ6d?1 5{"I$I^    6'k?~O$I$I   @z~b j{"I$I^    [2I$It2 g /ց/~b }I$It2 g /Jٔ _I$IT2 g /˲W~O$=hVۮ33xi5==,{δvӮ鬱=I	AK`DoxJ "(D	8
?}~<zF_$IF2 g /# m|{"I$Ij&? x  A}53 Ten7E$I4y    ׹%3 lX~S$I$Ig   RqGzWS$I$Ig   4~	>{"I$I<? x  AD	{"I$I<? x  AMQ0̭\~S$I$Ie   Խ?j P"I$I,? x  AMh@}*H$I&   @gI$Id 3 bpdFw]~O$I$Ie   5ع>`B$I$i   1[za@uN)$Ic   @f 4yyM$I${    -`N(eP"I$I:   1[ܒ0ѝL'$Ic   @oޘ0z{"I$I:   1[[$#"H$I-? x  AΥ/h@I$Iұe   wJ?v &ԿI$I1e   7wG_y_=$I$[    %]0wI$Iұe   ׿u; R=%H$I>? x  A+cwFM$I$}    -|?vOVI$Ig   _N{?z &4eD$It 3 bd Lh/I$Ig   _NxXxjM$I$]    ݼ<K^~S$I$IG @<?  9U랝Ѐu9H$I.? x  A<0ޓ~O$I$IG @<?  y>`B}wI$Ie   _^OT=.So$I$3 g /{e@'7E$It 3 bWuf 4?O)$I#   @v `Bߟ~O$I$IG @<?  l~ L~D$It 3 b[' @s~2H$I,? x  ArnO t7"H$I,? x  Ar' @[~S$I$IG @<?  ߽/ 0ўD$Itd 3 bd? &TN=$I$Y    ׿/ "I$Iz   1˯ h@WI$Iғg   _~* |7E$I 3 b8FS `B{nJ'$I'   @ -s+I$I 3 b8 @:oy~M$I$͟ @<?  iS ~?H$I   @Qu3J }KM$I$͟ @<?  #_~ LhϤI$I 3 bx~ U[uBM$I$=q    -7.9 Ѐ^~S$I$IO @<?  ;Is "I$Iz   1[<UkN.g?	 &4%7E$I 3 b?tg `BnM'$I'   @p_e?	 &534H$I?? x  AWm$ h@璗I$Ig   ⪻qY 4H$I?? x  AYg>0Y 0M7E$I 3 b?gݙ~O$I$I @<?  .~ Lj)7E$I 3 b_t7E$I 3 b\g@"I$I   1[RF_S$I$I? @<?  we? &T7H$I~8? x  Ag[ޑ4 h@uOI$Ig   wg? "I$I   1[u.@WI$Ig   "mSJ }"I$I   1[us `B$I$3 g o6۳ I$If   wf? лwo$I$o3 g oٰ4y ЀI)$I   @E%~" LhI$I   @۳ -s+K)$I 3 b|Ot6"I$I: @<?  ~" 4~S$I$I3 g oqW;5 Ѐo$I$p    -V3`B~O$I$I3 g o7IR=%H$I   @_o~& 4J)$I$? ` owp @o7E$Id   -O? hўko$I$ `! 1kG}wd? &TK'$I$? ` tYSM)$I4 3 b׎[$ ЀU~S$I$i3 g u.zQSI$I   1kIO,e~. Lh|o$I$x    }; ܙ?~S$I$i3 g =v~. 4o$I$r    U\ h@~S$I$i3 g =u.x^sߟ~S$I$i3 g E\R'{o$I$p    n~2 4Z"I$I @<?  j3 ^"I$I @<?  yyO~S$I$iV3 g ]Ud{?~S$I$iV3 g }Տ}# 0AUV~S$I$i3 g }re"I$I @<?  벟 o"I$I @<?  ~6 4`I$I   1kag>0 0_Ϳ)$I4 3 b߹- 0.<H$IҬe   _;|iMH)$I4k 3 bz o_~S$I$i2 g ௝u@F_!H$IҬe   _K[u| $I$P    ѽ~> 4sᯤI$I   1koe? лo$I$R    ޕ~> 4`ŋo$I$R    M~> 4`]7E$If)? x  A]7~B Lj<*՚o$I$J    ўk 7o$I$J    M=	ЀGߐ~S$I$iV2 g u/{y;?~S$I$iV2 g UkO)g?# &TK)$I4+ 3 bݙ h@濟~S$I$i2 g tY3"I$I @<?  O |"I$I @<?  s?~F 4`|"I$I @<?  SKt I$I   1FLSK_~S$I$i3 g o:|@"I$IӞ @<?  Q:)ЀѝL)$I4 3 b7UBSup[$H$I4g   Tx09Ѐ_J)$I4 3 b7=z]sQM$Ii   @ hwI$I   1? ?"I$IӜ @<?  Su3KO
Iu"I$IӚ @<?  ?
_I$I   16e?) 0q^M$Ii   @~R 4`ϦI$I   1:j	^;wE$I1? x  A'2d?+ }ǯI$I   1~V 47I$I   1;g?+ 0u7E$I1? x  AU h@y̭<.H$IҴe   չ lX~W$I$i2 g o:e?- L)$I4m 3 b7ږ hKI)$I4m 3 b7~Z 4`7E$I-? x  AWd?- R;5H$I4e   tVR:yЀ~W$I$i2 g oz?@9?H$I4e   6ms~S$I$i2 g oz&ȩI$I   1:8yА~3H$IҴd   ){Oo"I$IS @<?  /d?1 0"I$IӒ @<?  s $I$MC    MwO~b 4I$I   1:</А޵~W$I$i2 g o[oۜW$I$i
2 g ou}3{o$I$MC    M hHuϥI$Ij{    MM~f 4wI$Ij{    M* 0H$IR3 g o6?zwSnI)$I   1] hxXOO+$I   1~mS!w"I$Im   @٨sK o_~W$I$ 3 b7##{1H$IR3 g ov@2"I$Im   @it.$I$5? x  Afէe?7 ҿuwE$Iښ @<?  Se?7 2sm]$If   rI ;I$Ija    V~r 4I$Ijc    V _wE$Iژ @<?  Uw+ ~U]$I6f   lUR:Ѐzn_[$H$IR2 g o?zw!~W$I$m 3 b7{o<Аއ^~W$I$m 3 b7{?g@CmN+$IԶ   1:8АO+$IԶ   1V?a/А?[$I$E 3 b7|!k]]$I6e   l6܆@C3H$IR2 g o6]}Z!GN+$IAOВ   1:</Рjݳo$IZsrn\VVMeowڒ @<?  3%~~ 4[$I$Ŵٰ^;חR?#?kK2 g ovu}!/^~W$I$5%J[;/,>Wʰ{D\0q^d   ߾:АC{$I:뙥{4=['}ڒ @<?  [w+ =;H$Iz5'emETv7Û7wlK    n*  ]{E$IߪJgrz\_Rx]߻% Q    IDAT3 b7ۍ;	А͗I$iV֝Z-;JTNЖ   1톷]hI$izf^߾l-Ce1}mڒ @<?  ]ï~ 4:go$I4U9t7.+m+pצ2޷.Ւ   1:8	РէI$:t6,--5_b5lI    xRʰhwI$%UN-j{n*eP6?pk_Ӷd   >АI$i1VÿחўW;:%? x  A4ya3A՛~m$IR[}b\߶wm*}K2Ǿ׾% 3 bէe?C E$IZV_:ޖ`2ڻQ̢w?d   :</РN-$IRTպSKw߾\WEO|ڒ @<?  [Ofm$I:qY2ڳ{Y[2 g Ou}SA՛>H$IGKekS]J]gn-   @?`z>GE$IzV_:o}A}ߗ͗w2f
sghۂ   1^h?%H$I߫Zwjn^~_8<y;eeZ՚?6d   V,&`߽/H$i6֞Rռ_Uf=)YHm   @?}#_~ 4s/I$Myg<t.}Yo2{o@-   @?}mg?G L-$I[z[N/hR쯽ꜟL'm   @?}_h+WI$jݩyyo_]F{hW\@uϤ6d   Wg?G TWǥI$-emETfUl{jC    )~Ϳ/$IZ\>t6,-иoow)8+7ւ   1m|糟$ _o$Irnm9v/;Jv:\2 g O$ ݵ-H$i֝Zegk;f%eu.x^;lC    ֻ'	@C-H$O/ݍJۊC~_?Y:9m!? x  Aw;o0]E$IٰЯ|i]J="t𝤿d   KJ]=,hP"Iռ+_];ח_+i[_~ې @<?  Fw],hOI$?n^^Wў
Iut2 g O?)2ꗹ5'I$R9t7.+m+pצÿԹWy2 g O?Xw+% 知Ik	aim9Я?pK)8!SsK~2 g O?XuJ	@;K/$Iy{WиowG)N@fPg㯥І   15~kO5H$M۸{(OUF|_;~#6d   m& MǥzOI6V9t7.+m+pצ2޷;<o56d   u4hX}w}$IZ:t6,--ռn9/O@[t.}iG-   @?=^5iа/N/$IKJ-/O;<og)n6HՂ   1RUAGο/$IUg=t/{yo_]F{zhиE/J{ 3 b'jU?7H$-HkN*ݍJۊ2ܵ.Aa-   @?=Qe?O ֻ$IR:t6,--ռ;JzA[_d2 g OOT~ 4lx5E$iҪu5=72fmC    iRwpo$IґVҽ}{zTu.oې @<?  ~ 4s$Iݸ(]xR:J-{ 3 b~'
@8E$inaim9v/;J*Au.[ @<?  %а7?~_$IU;t7/?y﹩ARO 3 b\'
@R#I5j__F{zn_7 ՛3 3 by;GJ) ^#I'E/*m+pצ2޷3:g. ? x  Ad\3a/\~_$IR[u|lXZz[N/h,2չ? 3 b'k) ?zO}$Ijݩyyo_}WvgDuOhC    ] M1$iT=t7.;yo? 3 b'zs) zq$IIJR_~o?zwW!Yӂ   1ӑT* qM}$IЪKgrz\_F{w2e̝;-   @?IG! L2#IS{We2,.s+jC    H/* ItUkO9tVWw^ Km   @?IwzS gIt>kpצ2޷zuXDU-   @?Qg<Q?аIU?^;ח.S>v%? x  Atussiu]uIfyyo_]F{hǾ- 3 b#m -~c$IO/ݍJۊC@	Lז   1ӑֻ
@Wޗ~c$IVP:ռÛ/-}KRo)^K2 g OGZus+ cenwFi禃ewG)nf?ے @<?  :f?Y t.}Y$mUN-K2ڳ#'qoOؖ   14sm gIsڧemETǾ}~m?/ے @<?  :, b$iѴٰЯ|i]J=> Ojx5?C[ @<?  :߳, q;#IR֯]2ع(eɾ dLmK    ZsR)a @g$IZq_w߾l-uH	hwmK    h{W ?D4mUkN.ݍJۊ2ܵbϿ-go[2 g OGg?[ enqwFcj	aim9Я?pˡ_Y0Kysd   ޖ?~ \;#IғrIC~2sg kF$? x  Atu.g@L3$`չ?Seg?ȟnK    XO nM1ٮZsrn\VVMeowyhއ^s- 3 bcix5Ou]~.HfU'Ά2ع(V&g{K2 g ORe?] SA$IQUN=y>(ePe=m   @?KK_t2sm$ge//hR=} _- 3 bcj4i5蔹3k$IiIF&m+pצ2޷Я`auВ   1ӱ6@__wFH[u|lXZz[N/jQ?tp{sDK2 g OSd?_ pQ$-]~O`q[і   1ӱݼ<}en[#IZ\>Q <>fߊd   xO 0HWuwy	wM 3 bI?tg HL3E? Xʿ-   @?Mwd?a ۙ~g$Igf& q_̾m   @?MR?~ Dǥ:o$iqTٗ	y|hS    i:oy~ P~k$IQY`oLm   @?M%ۗ2}u$-<زoE2 g O6 u@;F_We% 1]鷢M 3 bI/1 y$׻?e$ 1[Ѧ   1Ӥu6Z3 F_c#$0-V)? x  A4qgH)nS H=̭<.HR0$0(V)? x  ADo~&)}k$I|E9`;V)? x  ADO~ :s>HrsS9`K_~+ڔ @<?  j")hF;e# yoE2 g OMT'J@4@)`YLm   @?5f?g ?[#IJjRFSN-   @?5we?g \$Tgy~+ږ @<?  j}s R]꼟K7s?ξB c鷢m 3 b@޵)H忝} Hm   @?5%~ }{#IZzzM	`kٷm 3 b&ٚ4K7m5ypQh[    7>I$ia<oE2 g OM}ǯg?i \~o$Id g鷢m 3 bF;㩥Hn>=Hg_ ѻ[Ѷ   1SӍ~:YwIUd }oߊe   n`ϱ{#IZs~2 $:Jh[    麗h̭9)H\֞~/ږ @<?  j5'2d?m |u͑$׻wO 8k׳oE3 g O| +WIR|_}r yu}Uu3NZomt]tZu:3vjkm$KKX.BXPvYdG-b	Buޏ_{(o9z>m^ߜw~}Wb   dbu7 ~Ȯ/s$Iyݰ4`3^~Wb   dbNdGh}IR+/n ،ޭ' @~  )G/MG\\2`3W~Wb   db\ Dj,|A#IԂR*{ 9o  ?? Lx0  Α$婹 [>S(f  @& ׻;G} ͣ>~_b   db\{2[Hn/w$Is_oD2 lA[Q  ?? L;? @?	s$Is_oG_1 lNUQ  ?? LGsIW>x]fTwŨf  @&YD~'{<ޑ$mUk}f(  3 O9+}]Gi$i*{}>?  3 O+Isq#IZ'|"j`z7~_j   dbn:&c T{G47u.-\bT3   ?}ƟFι_w$IsSG'G_+ lAτ @~  )wo0 UW;\s{4`}1 g Q~UGAT,~k#IeOߍU ؂bW# @~  in9!t.F#I]5:`K:b3   ?w{G)׮w$I}E_' lA(g  @&Dw0@ͥ{$I3{ݡW	 [(g  @&TՓE5;W!*`.	/F9?   21Ӡݶ,T`G4nR} gp   dbAY; :w$i5`N;c3   ?wGɟ}H__W4{o1 g ļT50(V*xY#IV[NA ֞}g  @&d;ϊ0@<$Mѻ j=~_z   dbA9o? P+I+唪* `ʟ~gz   dbA<=y RxG4Z'nL;c3   ?yj0@w$IS{բk)~;c3   ?EjԘu#Ir }Q  ?? L4:2cG^Rً2 
7F=?   21Ӡk= 6]Ik)*zE1 g "6<`TGu# `
;c2   ?EԻ> 9oI_ueU:  3 Oo} \s{#Izv{QJvUn:&  3 O @s Iҳk;W SԹk8d  @&\wOݰ4$=uF_ LQ7!?   21ST0`UTKw$8 y;q  ?? LU?}$IOW,~k T`c2   ?EUꔪ* 0`÷A)*q1. g "+# y ISW, sH    IDATq  ?? LY%G  ~I~!5nk)^_1& g "k}  T$ս։ w{1. g "+xiJe/ sW!I{ 
;%?   21StD Vļ{HjSX} 0UU_I   db躗} :$յ11 `u @~  )ѿ} 2٢!Ik} 0;)?   21SxIU{CQ  BOETê ߐ}wS   dbabyQ  H!I[54~S   dbas_G Tw$թF?A?)?   210\SQ  Pg_ET&JD?n35oQ   dba`q  Hݛ(w$աֱ)4o?-?   21Ӱ@?~IRtL#i|l1n g 韍> }~]$Ic>4u;d2   ?K>I Q*5D>SO{ fuGq  ?? L4L(H wHƹ]ߍ~0ޯC-?   210սz#@^kO|$i~'I4UC1?   210:cG`+$i\яx fw8f  @&v}aJf  P|<R$IļT[`Wa   dbac@_$ij}뷣 P{.8f  @&&G [auj,.Nqwiяv fX{d3   ?[%;E @/I4&~'Tu~-{]2 g j@rԘ*NQs?F?q  ?? L4n<2h 0Z;IF[{ P=1  ?? L4O(ٯ0Y^G9 /  ?? L4$~7x 0Z'~2^Q|8 Pd\3   ?kUWF @M~ʟ$͠;G?jw8g  @&:|3x 0$Z/$ZΎ~|0% @~  iXkS$iz51~|0K' @~  ihk Cu&Iz7,~l0K~u  ;? L4n9! 0$	$i*ymJfcY*~u2 g 韍>" ։$i5 T_~{   dba)Ue1`HknK'IWD?) @~  i+> 0DڧI$IZ ́E~{   dbascߗ$i*}]Jfc9<ʸg  @&/ 0d:~9~a{3 sN/W=?   2171/UVG Hx$R%IC0>
W @~  itLQ`t.f$IR# ̑+u  ?? L4
NOb׆Q]sN)2 su-u  ?? L4
8^; 0d&U%IW^8`TU*~UR  3 OR æ*SQUOD?Cڻd  @&:Mq`,o5G?C_j @~  iT*}\ R~=%IKя_ X//u  ?? L4J8 0u+Scv$bH9<wL]2   ?Rݫ>2 ΅~OIҠ^$kScb^S  3 OT븏D UHo$)wͥOG?uc;
c @~  iZmZ룏 Cj?څU[򡛣 dйe  @&z}l b>~WIR:|51@&#?~)?   21Ө>Ϣ Cz+IEoJUgcc&ۅ5u  ?? L4j{"}t bw$i8'
@&g @~  iwE`کy+Iv~Q¯5u  ?? L4u.j`ȕ^$iTE?VȨy7u  ?? L4w>: _	$iVMKϋ~Q\[95  ?? L4kn>> n~gILWOR 2E7u  ?? L4u# 0OL45x{: dY; g FD FOȊ$iZ&^` +ީa   dbmb^6>B Nï4Ru/-	 TO>~5?   21(׻ai`Dݔ$iKHJe?	 n9!ީk   dbQG! FH=.I\Ţ76q	BS  3 O#݂R} UZV%IՂmS Pf  @&z} !ՆS/I`~~9?   21Ө>O #w۲Ku8n<2s   dbQe)G	90IdTu6F?]:g  @&\} 5vjkwzWT[D`ަ}9?   218>>J 6m1I5mvяB ~=T  3 OPkR*	ԿԘ*.T&ޭ'F?ҹg  @&&v< Dzս|G  g ƥy} UU>~IGS T=M?5>{   dbq) 3Vu6	$wc+~'@MǄG2 ? L4N\} aUl7Vǣu kw    ?S>H0]$W%NUh#hn*vI$? A0 OT[Z_ fw)11/^45x[|({Y2   ?[C7G+ @=4I_Rя4 D¯Mz*?   21Ӹչ
19ѭU\{W!<߅Oz*?   21Ӹ<
qQROmFbWE? "Oz:?   218V=h0.Ejs&it*y һ;JOg  @&:.>Z >5MWT'j})= @~  ik cjMMnsӯkg/Uz:?   21ӸV]} 3Cb7qaMU CYw @~  i\k}ȡZ*~IK? C}+=3?   21Ӹ<]1U=T,zS]')IRX`w @~  i+50?IRً~0+/
  3 O\>b 1?OiI~0":2ҳ2   ?s?y)UU1`UOܟ~ILn/NKQQu @~  i+.0檍kRyVTG #|Kϝ @~  ic@Tc<M^ E~3   ?{~+t  !H'i:|5~7jc]  ?? LT}?PNjO+vԻ
 #\s[]  ?? LT:˿} JKf^_I底O FX]3=   db:T^qfz7	%MO[D?B q;Mϟ @~  .W^} ޝgƮ/%mb~l 0Myw??   21S]j*nO%=#?~ `LtWݦg  @&K/K׎>r T<ks邔~c1<=w6 @~  N:;Pc5ujT= )~i g T?>r ]K~'Jn6aw &:m1?   21SZ}G; H[OL]1njV~ 0ƚ~i g V# lR>|k*~7Jh_LK~ dU1Ӕ2   ?խ;G; ?:c4εNR~Uq:]e  @&]RG VS1{R-rA	.2~ij g Xݣ <K<4-6u.zJVF}?Ԕ3   ?ձA>z ܺEM?6Fy}M?> PgBM9?   21S]+>sq*{C})Jͣ> PWe/{:>3   ?յι} `}Lik.)n?-Ps\~'jz g Z+Sw  l䘩w4Lޘz?VJU}D Bݨe  @&sDA d\w`S絩{)u -RKHM/?   21Sk/%8w4EoJk2`n=13   ?պ/HUk}1}^J+Я׎>v Z}$3   ?սލGEC z_Wj&>INIG5 x^U1Ug  @&{#?}`VGNS?UiO✔*hu/52   ?RȝG f|^K*M/H3>ʇ} `*5x[=e  @&/΅_> 0gSҢWiKwH+IUXi{y]g  @&/bפFG S{.I~J?__OOKG ~j g TΎ> 0*>/H]zW,zc\T>zw Y:Sc߯y   db'=Uߍ> U}Scj]R^ 9ӻ{V  ?? LmRϢ$ dWm|8u.]=_j,UҽLU; d:zV  ?? L^oRũX;X_sɻSR6 dU[^.?   21y;Rc	 U>ۋcN%;miڻ? 00K~k g _}, LZK?~'kjӯ0T_q+X;Y  ?? Lg>ϣ% rsWRgp:?Gj% X7kN2   ?8UG GwuUm}~J" Cu'iM   db'=EM NUJ#T^Kx_ ϣzԘu  ?? Lg:7& S{K~k:#{|~G	 ^5g g ܕ}<`Tߛz7ڧ6\OW>SS^ FK_~k2   ? FZO7O~TxM'ܑRUE `~tr  ?? Le)u#
 㡪RԽ>ORwV71/5x{j/t^Osqmi4?   21FQ [Ugc꯺*u]g~!5}Oj&濌:7RHIHU{CF {?-7  3 OzK?}D^zT>x}pD:wRsϫs@MjSܿ4쯼(UVGښ9  ?? LW>tS1 *UO<^z7:cj<콩՛~mԮ/|jwo:ߛO兩| DbBs @~  I}L-T5+&mSCS~*OϤַ~;5?5_jT,!!{|S3\荛w[/hjGйS=SR371`  -
/< g v{QZODU `@&yUM <WK(K   db'mɟ   Gu#/?   21\sN)UUq   }P  3 OZUWEW   ` Sc"/?   21VEW   ` :C{  ?? L)pT5FY    n^BY3   ?iuZ}d  A3   ?iwH*-   CU;P  3 O^D[    4  3 O^>}l  ZV{&?   21_.   0&7&慿s`2   ?ib   Pχo2   ?iTE_   `TO,5lA  ?? Lսr   ́%Ϡf  @&*)}  4  3 Oy^  h^$ G  I3uoFa   `T|   db'ͮr   ǅWPL   db'ͮY-   Ud
  ?? LYpTm\}  iqz;e  @&b  IDAT^{Q    @~  Iu)   %(6?   21MDg   `
Zf{1   ?injΔ2H   Q>pm;g  @&_<H   : @~  IsW蝣4   <ʇoMy @~  Is[5   xS?@Ñ @~  Is[?>   );5o@Ñ @~  IsV\{W   i@C @~  Is_>   V>r禿@Ó @~  IZ}6>}  ɟwʧh2   ?)Os  +Y g b_NUgc  Zk4| g 5Gq   Rcb^_   db'-)c   	7  ?? Ln9!  @\N@Û @~  IykcJe?  @h;o   db'w۲   _uU w   db'对)Ueq  Zhh3   ?i0<+  sq;    db'aM<   J@ß @~  IyG   V֓¿k42   ?ip5`  o  ?? Lֿc   c{5: g 4ؚG}8  XZS+¿kt2   ?i~  ѹk5Z g 4Z>   jÿk2   ?)WG   y34;F/?   21bj   #|Ԙ*;F/?   21G    9F3?   21js#    FR¿kt3   ?)=D?   `Tej  3 O)UU    FFc¿k3   ?)я   	UT  3 Oyȿ   \  3 Oz-~   P+ޕ  ?? Ly)G   ַ?] @~  ISc	   0w] @~  ISM)я   .Φ] @~  IUC   0TW}] @~  IUkSя   
Նթ5^ g 4|u7    C}¿k2   ?i*xYǢ   Rcb^t_   db'gx   8U/3?   21ۥrG   ^wHwsm   db'oe~D   UN/^  ?? L!nb^uc   l  3 OG_)UU     3 Ozw   T,!{??   21ؑ   dչU  3 O.~\   @6Sc߿U  3 O^я   {UZGzwoէџz g IqN/$M_m   wQ߹U+/ =? LC%)Z*   s*SÿsV< 0  2)Z6IS}   0gڧ6W5} g I_IF[   0k{.ZV? 3 Ȥyo`4GZJU   Ob7V=x   =? LZ'Q6Iӯwqя   9Z-uG  ` d:/$MbW>   饩11/jn/>  ` IoĿd4:M#   lLo	NV,zS1  ? L:W/&i&kn~   ueiպQ>  ` I֓_Iy>  ){_ڧ6(  Ԃ @&UWd4zw(  4R󀷅:  P  
&iv޸?   d>  ` KU&iv   }WVߝ&?  g Qq;_Ie_8  g|5dUuѧ   2j~_I}^   s__}$  j  懿l47>?   įP: 6  2qF6IsSS굢+   M-{}d_׹ @m dle6IsW{X  ڧ~&W,>  a SY/&iZ]*#  @M~x|wc盘 P  5xK7IsVTя   jzT\S  ? :MֻG   uRS_>,=Wg	 ? z?<㥩z   5J5n[}D  j  N6..śO   j\}Cj,6{:Uu V  yG_I+G?^   g"5zg_U    t?囤XTu6F?b   SW\+>&  c 0 GV|  `MTҖ*QQ ? ip24Tя   HTfjo
 @- H¯T3   ZG]WRv>-  d 0 75E?f   );4G}\  j `"NRv{Q*  `rAjLlWo;     /f8Ij)Ue  TmX_VJ>2_{{w]p<"WT\@28g -K۲-%3s._RTZgqVQ.()9s|^~y=G_ys `\Y rƘ:􁜤~W   *MJjQ5d e `ՆҜnaQn[}   0BZB#T>2  c tCPNRk\1  t߲t+7?}l  ƚ? A봢vs[ٷ   CzŨ_|tVnէg g  AsDpNR<8-Od_7   W~/*͠og g  A95&IIoS"n  j=/*ͤbGTU {  4n='}H'$  `tY߬L<vM  @gc`WM'   D٨_pd{UA  q㟧$EtW   ɪT_@;Ui'n>>   @rObj􁝤׾+  LUJJ=}O   q'ӇvQX  @}KߦRu7>>    ]/!;IX~RD}   0`,L&LJ3y'  a `4.HIL?}   0@MQQiM粏  a `Q[!}[  AhQ\wKe   ^? !~!T訨^~1  Ϛ7MTb{. 0|, b<IQ7   }~SO>B    C}CLM?ԓ4]}   ;^jvN `, }$?̾v   E΍Q7CE؝}    æFJILŲ#Z  YʢTqߚROM̏  o n_EG$歟̾v   _e7לƔz}S 4X RW$Γ̾v   5禿-^k:u*   k\VO`_pdT7e_;   /njt/>&=  d `UΨ-=>}'i05V   #ΨMOSJ=uAt1 `, $9  `ʭO췤k퇮>F  ̐? ~҇Ԃy]wG  ۢ~	Hǚ}  聅? ߧ%oj   oۊƪSߏR593d$  z` `T(@IXN3  u4WF׊>Uk* #  UӇSOg:   FO/JV|Wz) , rjK/;!}8(i0u6  UGV^/=.ݛ   *wmڥǥ	%EGk  `uDꋏr3 Y` `Duw%bIQ  Un/de^_(>}  %  FXOD҇_}   r_|tPe'Dsc1 `Y q-OEw%CWf_9   cob{߃R/?=?>F  2  s@w-=>}(Mo   V-/zXѽ  =  r/{_0QR/=>+  `n+;Ѹ7KΎ4O  }b `Q|XujD}   Y?zug"2 G  N+7epQRk97  wO<~m ` , Q0; (ou^}   )HI3Xvb[>>  ? 9;QmCGI}D{  9ע`^[OA(  Y ]/D}GI~/EscU  0ҺOo<i-<,_}t  H` `T RR_*`D}   6ypNnSܱ!   <-~gPRR'*  )MDmo:iڿw∲}t  Hd `̔Ѹf  QѨ_pd[NN~<  C <yK.96}X)i[p@t9z  zuQw&՗Ǿ}d  "  Y~6K^Jꋎǳo  Uiԗ~Cu?F|9  0d, ?bթLIRDUߖ}   jQ|m6q`4ov}\  R  lJ_>-̾V   FUHIۂyѼOTQ `Y j7ˣNIUQUٷ
  @UJI{'	  #  ӊ+-I#^e&   (trLhv=}D  1  طVVD}ىPI   EŊˤ~Q5_>  (  LOYF5Q>#`8*iMgd"   e?~?勏d     Xw۳\;%>04}}   o|;-maѼf  ` @ﺝ<u[4?;jJgjs7  @_U=Q<%Dk͹}[    ̎VϊڢX%~ؑ}c   qo/G%gG+ܱ>  붣=ѼsQ7cjƗOK  S5_IsinV_rl4h}BG 1e +;hOQ:-&MJ+@U}=   ڲ_ꏥ4M̏cX~R4V͛:w/Σ_|  ?  Fw뺽\ ~"?EGx1ugo  YQߓݦ|n~8GcCŮ/  LkXP)    IENDB`PNG

   IHDR  p     4   	pHYs    {Rk    IDATxygYa!
(
*.6 :*3%}!5YB=!!{g}O:]g?{j[U|9}]ysw%qFip7RR焿L?>M<miĭя ֩j=7|^-}js3{}ss$L (0g_ZYR{w{_ A՚R{j@_>/ip׹)z/_SNS;|w?W~ @KmT_:'40a53cKvN=4~OpzGIH>GZ{;.-Guude_\K 6JoHsQ3X@~fפ:~X+uhJV 6;Rk緆U5^,J&%X@_MS;pU:F8=z}j-]|'EaY@?Ͱ 954l9}'_08LS^>B7 ]g%Z۽&;&ewY):/ WIS6:_zS/m(8 ސZ_~Ww|7 Le{^W}2+vۄXΑ7 L9'|k{k_0,p`n9ְR WU{_bWmN;ώ~uسyҿ4eU/sY 0ن9WgƬe[-DaY<:ְLUoM UթgƬ%[gDalYQ~yoOG< 6.o?3>|7%C.OS۾:|pŵxg$ 3z/vxS>y{Ǝ̑w寏zQ7U ~ZZwQguƊ̅A/AuiȪW ^=Ưq҆bs{eJ /m8m>Z4 `v9#s\նNo~uXM0z2MmZyx|K z"v{{<X:S_x8	:'}&| { mͩkgƫ+_x8^1P/4 r9Z;}O~iCYRkߟzѿh ?Y|x=_h8z?Ro*e Q"{ e5^RW ljy{?D,p`7>/X=vCK ԲW}G^F_H80K~*|iGpHûΉ~9 D\LԻ`yKfapOk\sx &JԿ	Z;oJAKfsx;/ <~wƱBisįw `U=Zۿ!_Dq,pPݤj=R 6ijfZۿ>A7bڇjXM/ `pN\g5mEQ,pDo*M-yEm*  ͠?3]~%CX@I/ ;3{m5~CX@>&RUE u
jpKIwhnk: \Ampy/ahIS_>&ֶ[F?}  7_jfw~CcX@k$6XG =|̯D~P/4d;&|MZo]c fwޒj^#?҅ư>,d>0IfPg	5_X@F>&O3D?r `#k{?SA-yEJaK2B`mM4jT'_8CmG ̅J>Bi#ѯZhȘCmk37 GRk7P3=soK2cPO~я cU+?g}"81t6;: sP>vSK28=Ϣ/ 0m?sލ>
`m\kj?xy6w8P2Xh4G ,Ί߈fe,p #zcD?V `UݟZ۽&36ny2 &P?Y@Ȉh'ëg~ @j\/(cm\y@ !M-"36.u*q zgc+(cm,i]я ~+vG&(cmB 3'O8P2Z: Dzde,p #z5eJ~ @U?Z˷,pdD&׿| X[^Q|8P2ZSQ l4H}EY@Ȉhl+;  ;ϊ,pdD&ֿ` 4H,pdDGSt  s1X@F@kT6K{Ώ~d @]YF!Y@ȈhM{g Tvj3Z,pdDS~:q 6kiY@ȈhMipQя
 C>Fք:rJU 10zՋ|X@F@}KL'n~L q`Y@ȈhuG ꙻԒWde,p #zչ.ߗRo* cw߇de,p #zչuGG? `LUgRk7ge,p #zյOE? `[g8P2Z-[YwI ݠZ#5(cMe 0X"7(cv-yE=}Wc &E5J}HVzg}1  fp@,pdD:ͩ<H ISU}?i~28= 0wYHV{3 q  sG?i28=_  4[៉4Y@Ȉhu7 @-tV|<6(c?&1  =|MZY#]8P2ZtߓR5~  _goFee,p #zE7G  "IsY{ :Zg%M8P2ZdÛO>~ u'(c-~?RUE? zuL,pdD}  4L,pdD{w  9៝iY@Ȉh<0 o?=6-(cmkc ('?Ci28=ˢ `VJ聶-{UZOF90Ty4=z/u΋=xR콩ꭉ4ѰZ@g)mT8P2B;o~{SR+?:Zjij7hV?:_=忧%'ѣY Կ៥qY@Ȉh֢;Ls̿uOl+3KEjRߟ-'6mm(:(cm"5}#]:GNjIS{w	>+Yߋ4,pdDjxG,ຣf~5{g~/=h>j;f՚WhvY@ȈhQ{G30zSix){_O|o'EyVJa{]{f聶:(96zԿl9ij3u[RS'ou8P2|vTuWG30].̡Ί<(cm1cS}S/ΛPkN󗦪T#3WT_}F=|uTZEXS4`U{;=EEY@ȈhY>^`S{n9=9яH+/QQ8P2|6
{gԲ7&vMMUoM {Z28=ONiaFJݯ4e^k緦uGZ3!C,pdD>Z`=]/R9_"@{,E-~+AlzgPsſohY@ȈhQ{D+TZ7+qKG^2w~ge,p #zGv>V`Zoj'9|9q[;K)ѯ&`CR|z28=E{&SSkOМ>g黢_Vz/9}BX@F@:|8HaW0@'֡j=2}BX@F@W}0Q_kZoӿhC?к28=/OG
z9#Z:[7hY@ȈhsY+}0qVmHn~	_~oK28=uGG'LlG^ߋ3#fe,p #zY^ޚㄉ0z^hઃ_.}Y28=z̿t/zI6Kv~yD{ nZzg#[e{^6WV}%(a~Uzg)
c6ûNѿZ;5+6'-~YZOE%_OF;of<F4z/ٵ_Ph;ge,p #zEC9alUJ}~լe3UU7Gީ| M-".kn28={D#︚YXzT?z-I>Z;1j281C黢KSk﷚]~)C\}n_}{M-l8P2ڦǣKRkׄoG?a cKHIݕN~l毴ECfe,p #zmjs%aXh>\y@KW7z}.uPZee,p oG!=m_~5-bOC㿷斓gQ_O-5"(cmSj衫RkۭƷv/14F]:~2vy[Rse,p #zmJݕ>>3wN~5Myk/yx`VU?m~_4>Y@Ȉh#j={+>krjޙ/ޚe[w8P2ڦT=wA[}&Αo՚GSR:G~4.X@F@_裃wY[/E_L[39k:28=6)}thKvǚm}Y׵,pdDmpG54XjmT=sO[ׯT聶Q-,USOD4RMXצ)W<vYsKjmש)Y@ȈhS{}lLU:+~#KYԿDM{km2(cmcԿt+D_hﭙU%I聶1oFALKW_i}:=0FOߕz_fי聶Qz2ؠYFﯔ}3t۾z-IOz6{+ȠqꔚT9FU8P2ltAT?Z˷	RqKLn:[#mr8P2l__At{+Ͷ~?Ұ}}&RkBijWge,p qkcxwVz-Bco;冷/Mfj],pdDYU3_
>V<2&a?HY@Ȉhs/E4কwV{_y4=36~Ҥfe,p #zͦY_>.h0zwGߨf}oQH_$67}\-&JsֲW{UmT3Rek5;9I`8P2lV?}\ЌU:GvHv9R{fVZk7D44o=%ꙻg~wR[MX@F@+sدD4B簏Wi>j)Ҹ5de,p #z;G7'4DUwuw_:RkX@F@+mp!G7wUז"5ڠF|;/+u穽ԢNRX8P23"֪S/CQgSg$^Y@ȈhE-| C[UiyVMg!Y@Ȉh%M9a~WRNU_ޚJ-Y@Ȉh%u6{*-tkK47*TϮ].<Qxde,p #z?i1AMt@=.ߗR5S[~o7.̗#GH,pdD7}LP_Njm{*EԿ`V?zg)uZMoIFGVEFQ)ֶ[G5JR28=J@[~G:G~4uW~:zﭑT,pdD\'T$?(c-WEoQI,pdD\?[τQI,pdD#0Z#Jge,p #z\lA-U=~?%IR>(cx]}DPKk$)聖j?}DPK2~J|8P2چj-&xZ=J|8P2چjZ/~J,pdD9?FকS$ee,p #zm	}<PKOIT聶zK@-ud$IeY@ȈhS$ee,p #zm-'EOo*M-<~J,pdz=xE@,nJ,pdDU~0xvW~7%IRy8P2z[F)I28=Wk>OOIT聶{Xz    IDAT@-uH$IY@Ȉh}/DR{$<(cm}uD@TUZU$IY@Ȉh뫻GSM=~7%I28=W/Dk$I]8P2ꟿ,hv}3nJee,p #zFຣ$I]8P2\l@< nJee,p #zgFN$I]8P2i@]~7%I28QAw]@N|ݔ$IX@FmSwDN~7%I28=W裁~$I]8P2OGNȏMI4,pdD裁)If聶mRUENOI4,pdDuvcZ$yY@Ȉh몵wGԒ$IX@F@[W~0X|$IX@F@[W=},PK8$5/(cm]cZ$yY@Ȉh몽GԒ$IX@F@[W}~"X:b$IX@F@[W}C@-YHԼ,pdDu梨js/OI4,pdDu>gjs$I]8P2ںjOI4,pdDu>碏jS$.(cm]uP@-N)If聶B@-)If聶|[%S$.(cm]3nKv$ivY@Ȉh몽{jS$.(cm]cZZ~?%I28=Uk>M+$I]8P2ںj4)If聶Z;%XF^~?%I28=Uk7FRS$.(cm]o},PKU)If聶Ζm},P[SK$8(cm-,0hZ-J,pdD5"K)Iʳ28=W裁Z)Iʳ28QA]G$<(c͠)IX@F@[_/>$I*X@F@[_ûΎ>UOIT聶}4PKÛO$<(cm};:h]~?%IRy8P2\y`@-M)Iʳ28=WiMS6$,(cm}裁j;*Iʲ28=WDV{QIT聶_裁wT$ee,p #za}4P[o;*Iʲ28=W{>;QIT聶Z@@m?&J,pdDv裁wq$IeY@Ȉh*{T={o$IeY@ȈhZX@={ijwT$28QaMwT$28=6j}$Ige,p #zmFV$)聶}<P[>~G%IR>(cmCb@m/3J|8P2چ5wT$28=6TgǣjkĭwT$28=6T{Gנ,Jge,p #zm.}<Pk~0Jge,p #zm%[TUG9W$I`8P2Zj#;*I6G>";QI,pdD\[O>"'QI,pdD\+>"ѣׅQI,pdD\s%ޚ4h{*I֟聖G-T$?(c-I֯s$IZ8P2Z$ֺ'E=$IX@F@˶l#Z_m=$IX@F@+j=}LP[	$iY@h{dU1Am*Jge,p #z4c%Iw8P2ZIK}LPk]?Juge,p #z;9T$;(cѿ}LPkK{*I֝VR{>&SI,pdDZn}LPk{/
$iY@ȈhU'
jz"Juge,p 1+
jÛ$Izi8P2Zi}TPkC>~O%IK28=J_SQAuOoT$4(c9֯T$4(ca>*gSI,pdDZ|_QAU~O%IK28=Њ[YJv*I^fi{*I^ϰP2lܴ2ֺ_T$8(cm6/1.$Y@Ȉh{_E$Izq8P2l6z{*I^6Z;%ުQwU$6۪#ZkT$/>2I	$,pdD6#Z_W=$I/de,p #zͶޙ}dPk{.$,pdDY#ZOSIB8P2lkG$IZ6m6jwU$de,p C+jw$IZ聶1="ؠ~O%I,pdDw?E$IZ聶1u6짩%$JY@F@ۘZ=ؠ/J$(em ?$
Y@FcCWFZ$IR8=6GF3$IR8=6Y}tPkSId,p #zml~+Z;)J4Y@Ȉh[kwD^_	$Mz8P2FhzS;wU	X@FCWE}GSI&=(cmSZ}|Pkn$Mz8P2ڦ/QAh2J4Y@ȈhRgoD^$Mr8P2ڦ=$I聶Uk>BSI&9(cmSqFB2J4Y@ȈhZmMSK$Mj8P2ڦڟD!^{UI&5(cmSkcG=/$I聶-<U5ֿl*I҄fe,p c,ߎ>F}SI&5(cm.\y@1BMOEUI&1(cm.]wUIX@F@~0b[]$i28=e[4F%Z$IO}Pkû	$Mb8P2\5裄ZZOSI&1(cm裄kwUIX@F@:G~,(:^]$iҲ28=֎o>J$I6U?}Pk۾~O%I,pdDlx	V=p=$iҲ28=E;D'^k$MR8P2\=jsUI&)(cm.k_<J4IY@Ȉhs]5DB<+J4IY@Ȉhs3jj?m~W%I,pdDnCk*IҤde,p #zuc?}P{ݯI]$iR28=֮}P{o~W%I,pdDZhB8J4)Y@ȈhoF+[<J4	Y@ȈhQ
wUIX@F@:GvBuO*I$de,p #zG}P{+$MB8P2|U~(hF]~O%I,pdDjxG6쥩[UI=(cmꝻ(h| J4Y@ȈhUgǣjw߆UI=(cmj装\{D]$iܳ28=jmMTqX@F@7>^jZ۽&J4Y@ȈhY/E/^_
$s8P2|9?F/^~W%I,pdDR#Zp\]$i281;jz{*I8ge,p #zw뎎>bJ~W%I,pdDw碏jwUqX@F@\C_~W%I,pdDyo)6*IҘfe,p c"CWF3Zy6M-<J4Y@ȈhQ}j׻$I聶uW~:'U]$i28=?}P{+$c8P2ڂhT>jѣUI0(cmuvQCwUqX@F@[l}P{>~W%I,pdDsoG5^~W%I,pdD㛣joxIwUqX@F@[Ȫg>nj{*IҸee,p #z-d}P{~W%I,pdDw>n$J4NY@ȈhY_>n_$S8P2ڂU)G6zwU1X@뢏mMSK$K8P2B7#k*IҸde,p #z-tݓkCN|]$i\28=>?}P{$K8P2ڂhTuWG;Z=wU1X@F@hx-wUqX@F@9w$IQ}P{v$C8P2ZD]}P{{$C8P2ZTG=["J,pdD}P{>~W%Ijz8P2ZT}P{>J,pdD:jCnZ~W%Ijz8P2ZT^R5>~jcwUge,p c7G?^{wUI#jwU&ge,p #zE;ojopAwU&ge,p #zE7z*IR28=B[EJv#zUfe,p #zE7G 9$IMX@F@я jwUfe,p #zEڟD?}UI]k~PnZe}$Y@Ȉhuz<1@*IR28=oF?ޙ~W%Ijb8P2Zꝷ81@o9)J,pdD:9cяjj=m~_%IjZ8P2Zj-]JU({+JԴ,pdD4zG=$IMX@F@KU_~P{$5-(c.wяjomwUee,p #zե~PUZ;9JԤ,pdDڴdWIVF|;q@/'JԤ,pdD:տl7z*IR28=T?~ЌMUde,p #zթ?8~}$)Y@Ȉhuz<@/+JԔ,pdD5яjouwUde,p #zխy	_5J~_%IjB8P2ZG9$iB[UjwR?X@F@[寛+;/#J&/Kߓ+?홆]Ҡ<b,pdD:6z7z*IZ;5uDꝷ$o=5Ug689VX߃${m;sipZc9rY@ȈhuX:Gv}$5%[U?V7ǀM5L8P2ZknUTZw|oMg^f3YsY@Ȉhl)яjoUUTyzfsY@Ȉhumh8ۢ$ijmfՊT=sO(z3ee,p #zյ:GV}$S_ઃ{kr$2Y@Ȉhu{F?h%WIhݩ{_CW4쥺=y{e28={@+$iTj_>\8P2Zm[YZOF? {m$mR_KNzee,p #zչE?hѿ~_%IޚT~(3Y@Ȉhuwпl*IPh0$~;Mjͣ V:G~,@#%J$4.[3'K.(cε.~D]~g%ijmu;sij_%*V4%7gg$L*{kRy.e28=`W4ຣ$5W4[3ޚX@F@{oGPy,M-,JR%sįy2-{8V| Ac;+I{M;কz7?\8P2Z[kB>JR֌oœ7Zde,p #z5ߊ~LOp[ӊ~eWx_,pdD&nя	_An~g%iοfwX֣<zee,p #z5W01Act;+IjWJ>V7TUoZOſ2Y@ȈhMF?&hۅYIZo_ﭙUa/MPM=de,p #z5jя
a$}*]ޚ1Ty4uX@F@kJ~Tajm;+ij-fBޚǣY _{,pdD;E?*hαƼ%[?{kHsǿ3Y@ȈhM}/D?*hYIc◧Kݓ>WF^hVGMTde,p #z5%PhwVRckJo힆]Ro*m=qKk6֤F^1{pYX3z׫x    IDATq.(cIMQRDYI50_de,p #z51w~g%e{RwfKRtߚCûύg28=КTkG?.hA7:JZZ;5uDꝷdB~bBof?ִ5F?2hѿ~g%}^{k}o7,pdD5G1;+ifWNﭡO2Y@ȈhMkd efWk54CM.(ciuG'ﭤuS\o0k	K,pdDƵl;ﭤoͪz߯\8P2Z=xEc{a&u~o( ߹L8P2Z_GcRk4Y[Ӊ`;X@F@kb Vm:~2/19?UWBu{X@F@kb'A="JRkD_iQ,pdDV=swƨ{+C<JCt{X@F@kjU_~t(>~oqh_V2ԺuF響4JPߍP+~/sY@ȈhM{44uO/je.(c-,U4J{w]1|&,pdD&7;}65ɒ,pdD&;F?>h[:8*Cm1Nde,p #z5aYQj+5'Fdɒ,pdDFU)я{R=tU5f[(b 3{+5jk1;YYFW-}eJU}6l/28=К^?~8ݕ
RkG/J/˒,pdD-яgKX:jZ$(cm=y{cfԶRWѷjs/˒,pdDqhp!я{]i[}uV{3^de,p #zCຣԴW}uVm~/K28=ơ֮?qγij+Ԥ\}u^s$(cm\7QBt+5jk1z;Y6.V~8RSj+2{Y6.uOяgIۄ_	uHZ\sx,X@F@{pFtPԿP+Y@ȈhTяgxwWjB+P+ݓ?~/K28=Ʃ_~<aj=W{{/P+#c,X@F@zMF}_Tb/H,X@F@{'qB#<Ju[)K5JSKY@ȈhcբR5x#FjIαP+l28=ƭ'D?Rh޹T}EV]~/g6n_{w}w]y$@QTmUVGfZZk֎UӞVU[',YXbY@ 	 %DY 		[.{U"I>w}}9ǜ93|˻ܻG
RcKTԒMw(P(/ȇhU?G
?$&*\@}=BVMaȇhoevcJ)&*X@W}E~7 8zU+ԏ(,m	a"ռ4
ǟN,p|X VkQX
}I~_79X 3ߩ~@iE]wZy/pcpPzFh~!Q_GpʸgpP[~@iEg0Qj_Nvn78@>,p @jFhj[cP=&Rn^@4oV2 8zU5o[̲Lx
{L̛&4Q_Ep?%ÍA=Ъ\CV*&RE6 >Q~? 8zUh,+̟}B}|kȇhU.Z3Hx=+Nu~ 8@>,p @rޤ#̒Hʂ]{D.X|?X~?G 8zUdj#J{L端PH~$8@>,p @z	GZk$D=Sv
)X	A,p|X VS?bK?+D*\
˛fI,p|X Vƛ5Zn]&Q#W(~48@>,p @C׫3Pz2Qku%Mu
)p48@>,p @CUҋr.uMQ_5;gHcpP:>ARg/D]o۟T4JOG 8zեtSG^tLԭŧPhY%#A=R?<RwqLԍǯS02Gta8Z]
~@%D#DΟ}b	طt4a8ZmpY7P~IӼ~S:Xvf$A=T
*!^{>u*oƯy .]M,p|X V}]jH"~*SfFx&8@>,p @S_O %;M4ZQjN@e{hcpPՐ&yN&~pT~WG 8zխh,#*#~r&iޙo+!A=VpQ?r:̂(D#W > A=j!5ԏ􅇭n#އH zgg< 8zձTJs(w}c,ٴZ}mRH6ުA=X?6tN4o1M𪯨PAD,p|X VǼ3ޮ~@}O~\yShY%uJ#Xa8Z]K_|Dܓw@,V<ȼIGm'bpP~@夛F8&WO0+J}o; 8zյ_
 ߒo_͛|e7P*Ѫ۩X e;V?~zs'D\R J'XG۩X Eg?PI1p
/J <D~; 8zչ`ԏ*=7;-vP:Ɇa8Zk# TS?{Nm_A=^v xe~W~
 w28@>,p @{E>@?}cwU󺯫>PZa8Z<Ĳp V?ŧb,9O L%{X ^cCPmYj]˚CZxwӱa8~bsc O~S~ߩygò=ϩ:PnYj޴7scpP4zMKV-GtzԘ7,nW~ 8zOKN}ZH^)M~}{9`t7bpP4i>
@mw7V~yS`s4PUȇhZD}ڈ9G~y_ 5^rA=%ܮ>@4oS9x/?>@kvbpP4E>@4oSghٮgG?nȇh*V	v;?`ɖ5^RYr5nȇhʒnR	X␫/%MQ݊A=蕅WH tg q	/w18@>,p @WM~YP[Zc`g矶&nVKмIG{7cpP4zucd-	r\QnUG'V{cpP4zuF},K߼oy[?_*H럏}cpP4zuיEh hw??nW}z)onȇh/Q %Nǂ&Pk0|j%yA,p|X F.Xrh ,ό6P]K6V2S?A=h?d$OdcԑZ_Tw *͆5&.,E,p|X F/Z=S}< {¥>(k_l6qj-~RAbpP4ܓ~_YŧXm 0O?z 8zc ؏lf/K}Ȓ<DЫX \W ŀ?=zu-ylyGt\C/cpP4:po3R1>ټIG?75\ǖ<{T ؏_ũ?'z 8z@Nݚ7}vԮC-\EC	(?^8>|X F l{k,z-,˂] &u,p|X F9b =o̛rJM8ʒL2Icq,p|X FQ {-Z=˼3CyRǵ<^}fCH@K%X V埫O莸,9XxI RA,p|X F[ש}_#)J7\/,ح~L :$ۻȇh>. $۽ϷO?pǙ?_jM.VMވbpP4ʟ7f>2 y	yg]&n[־?'k}?KxG 8z-R =5λ7VY=̶Ǯ	cpP4^ 9dɳ?j:]k1\h}oik?-ϭyӷ-~K_xe֗ߡa8%`c`[Ze1͚W|onޤ#y[S}ntT\j-zAt Xƻ 8zP_xyX,WP!/(W;cpP4~YQ  |#wRȇh4{窏  ͓3!8@>,p @;  Yfߙ 8zKS}|   )yb](a8Ϫ  >O+%8@>,p @Q?βO  +/<l1wȇh4Z?	  P$U_#)8@>,p @M9,  -ۻߑ 8z?_}   ښ7&7*Z,p|X F?  PM:BnTX :SVQ  518@>,p @,Q  ul7;QcpP4  j*LPQcpP4\/  84o[BEA=ШlM#  j&\{PcpP4lH :Nu;PcpP4pۮ>V  &3?A=ШEwLU+  P_OcpP4|)|  9]SX Sfh 
˚CM{a8u'?	  ѪȇhԽ>^  KM:RSX w͒ i^2ȇhuG  THs5q 8zQwgoc  *"ȇhW3  P{7FnSX wo]8  `Ԃה18@>,p @7O}  @%P>SX z7f>n  Yϔ58@>,p @>n  U1eA=ШwyS,ܫ>r  D=[1p{LcpP4mSG  Hx/eA=Шy_oS}  @	$φw 8@>,p @׼4  E&{KbpP440G  Xf"a8ij{v  }n3oQȇh$oר  (pg*A=HWc  
&yZ;JJ_xXXR`84ɇJZ} @Q4IJwlT?YX IGʇghDc  
y&U,m~@)35>  @,ݺKšpf(j͛td&  @M%My~@iS?H^xWG  4o퓿T5o_r|Qk{  XkhU?b4X o#ͲT}$ @sOTW?e4X ѽs働SnH i6 z]g3P,p xJ`M{e.  ]n]?Aת5P,p tV`b^c	  )̟;GJwoV?m4X 94f'nTZ.  ]\5Fg~@r|Q~YTM  aS7Zo]5q!ZH>xEOQM  Ayӏcԥ+ԏ(8@g
؄,x 	..ɛ.,>,  Rt\{E
}Bȁa/tTK  Bm5S)ޟcx/}M~e{(  9dw'j-=P:,pa矬xTȂ>>  `B~m˾~@)!|Ɵ P.}u,t4ƔCOSS  CA=PZ,paj |T܂  ,e>0*)yz,mIGɇxB1  e,}@*n,۽I}L >D+
u-xw|,MG  k7VP?~@F( b>Y}L Ϥ۟lyt J0RYfD*pYnI gWnPӢ5IM  \IDATG 8($?dC}C?x½
 @}eYOP	,pQ
oF*v/)  ռ[wM9ҝϨ P,pJS"T/QT  j'~`ѫG 8@{_c
鎧G H uyӷG 8@W}8to
 @;67_ׂ, 8@Zo|hRqU1 2s-u-fMO}JbtXiI.^H}L 8h/ԳRo 
܄Zc
 @d~V?kZ믞=[է 48@7d˿&T'XQT  *^ I|'  t\kş;oatYn!NE-} Pj?0ռ͒X}`@֘r|Rkcר(  ޱy&e×?P;,pIwo1./o,}! Tk1p[ZIjKIliC|3g7 #ݺW ]5Cj ?syg~S
},ߑ p K7ܮSS X *Ilճ1HPԼ	 @ae;6.3iO~~ ~ }ނjCɇ4 licC9S@
"ݵkņm?Βǖ$  y ]G6KS#,pI^lqc\&ns#  rޭz~6WF+X Eo͂+lGȇ;>o[,۹Q} .of ɕj`Ed#0,p2h?N3３lo~SOgh]} lTR7xg~ښO`-bPkj˾d޼[c/	ԕ'E SѺEmruӿ[iּ\ТGY6KwlKM    IENDB`PNG

   IHDR  	     .|   	pHYs    {Rk    IDATxie]{+3QreDi
Fۊrm@[
*}[RI%d2#I	!		$L2Ce*gqUOPAB?w-^C]:  aЉ"GJt~Ito!)bt!g  0anb?Hjּ4GjsvD\1(/;  ̰  l-W}2} _[tcO  `BU^v4ocxձQ=rG% b btgwF?"UzVn>m  	WwUH3oD?FϾ 0  dU^~Xt.E)1[>}  )Q(v}VVnݣ}'n[ٗ%  A  Ox<:O~6VyQY  LKXgIЊ{bx'#E	 )` *.g]tv}NOi*v{NT\}*  S(vyz	j3?r׳/Q  L0<  U97␟)5Q=x]  Li8&7ړ"Q
 	c @T1c/3k^շ}Z  3YC	mK߫E    `W𳴚*>  S~>Gۏ,gA}  A <1xMtv^Jlԝ.  `F?%:˷I4\vPĨ}  A pZt~IIź![٧  0FWҟ$M~>?kN̾l   `N^ߜ2RjuC)  ̉e?IGJ# 2 qUo}Os_3Y_vO3  `!ISԊmG"F  K  `nBt>/1;"  S3vN.4]<F~)  ̠HN|OKFi\a}  *?IEG  3  `Ɣw]5/(ozx  QwLN4}*ʵWf_  < Y1DDgaҸ3  |)l1xξ "< P=`tQ7dn   ߣ.^$i:~>}) %y  SntE/q=Mx  DŚ??IΊ2; < )6b8ƨO7  z(x^sXpZ   QUEK+_J{-  :]<%iJ[uz@   ͠ާޕrPsCu3  `~7KjTGTe -` 0E#QҸzߌ  LѕG?[Iz'AD9̾   DU|+ߐ"Pw݃~6[٧  @c/-?cIa7r f0 Ն8g_ JK3{(  hG]G?kI͈A}E ` Lj(}E?iuc<  `\Qoh  l< 	VuE_I㮻ODam)  0u}tzm{;#a%   `BUG8/qW|EQ?r{)  0V{&i}#2 S0 D"ޔOwϏjݍg  ^.OO4s ` 0i*z''Ş4]+8  %U|ftoL&i|  ߇A 7/j(0t  H12Ictiٗ3  A ^~X<iܭ>[>   RH󙤩X(6r a 0!ʻ.Ί_IcmQ^   _]GN4ɨz볯h  |< 	Pm?:{(4-,   6EП^4u{gDUe_  6< l0GwҸ^[  0qFӟ$Mwɾ my  C;iNS  `bUkΪӟ$Mq+ʾ ` ktEYu;iOzODgS   cӟ$Mw~?1(/g  s   I}4:{$E4zGZĨ}  L9I4K 3 H;}/q="S  `zU{G)naYnr ` $}s~Qej   So.NU^ `n ,A':k^bNW?C7gi   S~(x^mpފK 2 Xb3*4V=-ʻ.>   ^yYmslQ1R 0  PYM9i-,7>}  ̌ѕG?Iںٗ1 d G5E4>   f?Oޓ4yve ` ,uƿ   `a>IYF+ \1 X
~<4zǾ=*2  Uw/J4xe ` ,exQE=x<  y=Egvρb/a  A ˿bda   scxفς׎Ⱦ < 1\&vgFu7O/  ?ҟ	%M_>/(ٗ0 ` 0N":?/j+.  4,{k%M]ï"
 0  hp?hZmaY  HU?zGH3{k/_  s  `\*^MjWfY   DDy磳Usjtٗ/ g 0&?MjIS  oϊʾt << 1~-/ؤ}-0  ;UegFISz L3 rݍYXMjbK>   xu(yYipK L3 J&QQ=pm)  S*:)i:~U} Yy  ms_I[u7}F  	F_;,9R4 2 hϤPhx	  ?=ϒi} Yy  -}]/ԤOy  fGwW?SJ=Q/[  3  EUo}tV=-Ԥ;E٧   [Z{EtVnl)i  a ТǥHT;fJ   40cϗ&Yʾ\ $< uO/Ҥ-nӢZ{ei  @Suޑ)i+yy
 `& eԏ.OO&mi+>   hI}$5/I֔4Uߖ} 9y  -zn4iK٧   -+0:˷I4vx
 ` _I[R_F٧   c0<usɭg_  fA @K_M6|Q]<}   0.u~-SdVʾR < TuYXMڬVս_>}   ϡ&[̾L < n85ř>.  `ҟE%M^o} )y  -7/Τi>m   Xbs><*iٗ' b Ђ;86ao(٧   KF_H.4Yxs	 ` 4UjgҦTߓ}   z(V?#TT~f	 ` 4T>xCK3iZ*[>e   H6gTIUٗ& a _I=O   &Dط?JϾ, < }3;u}   0!κ(UIo y  u?;/̤+=}   0a>*i2K 0 h8g_I߷;DuU٧	   *)Iɾ < :L~   Ҡݏ2URn%j 03  _I߯	>E   ]Dgϱ8 y  kLY&}uC)  ӟe%U 0 h`t/ˤiQ2   `Tsϴx  9< _?&Eo]~H  UOKS{42 0  \o2;  )6϶rߓ}	 	y  e?Qg   LoMƕmL  3 hHQ&-bۨ,   `ԏ.O֕U}= 0  }O_I^k   ^vPK L0 hw_I#Q٧   OJsWuW ` @?HQQ?zg   OJsTu7/;  3  9E5'd   ̰%K4   ާޕL[g   ̺,i   <eUO   @YgaI  y  )Duه?   sdx^ÒƚA @;  0SFWg   ̛ῘL,i|   <-u#Qه>   sZwctVl,i<   <-eŮϊ;{   ]ӟ%'< v 4`ly   ]5!oHF~y  0 h OKUe   6YYR   <-E>/>p  18#˒  y  i-&}  wQfIe < 4_   Ty͒  y  iuوr}  ?ϒ  y  il6Wd   bg?GKjA @;  0Ӹ^k   dxAђg < 4.f   i*)yZR  a ЀAZoQ=x]   z6Zg < vËd   Eg}8ZҖg < fwZ   JNk^|-i2 hA @yjj>  3%mQy  0 h Om5p   Z;i3 hA @yj?r}8  @+Eҟ%m^y  0 h O[mT_}(  @-i2 hA @yjه1   Eצ?wK  a ЀA#F   ƢgoIA @;  0Uw]}  X?6)< v 4`-mpև_   ;jpI?8< v 4`-Xg   $_^,.g < %}  ve㒞:< v 4`ͭ[   XrOI&   <mNύ.  OfA @;  04ه,   ۦ?Kz  a ЀA61o>\   ̿JF   <mRpԏܞ}  @>^.{2 hA @yڔ}  ]yd  y  =U}  䨫쒾;< v 4`la<0  SsYt?K  a ЀA>D  `b?5< v 4`WF]|+  U':/  a ЀA_"  78ҟ%=A @;  0ӓ;u}x  ī{Fsӟ%   <}O˷M   Kd < o7ه%   Lrݏ2^  a ЀA/zxa	   SgtҼg < >.  ;<g < u{SD]g   0{):ҟy  y  i    h»9  y  icC   fBY}4   <E   3:y_  a ЀA}  LD?KA @;  0ț"b>  `/^/[y  0 h o+o|!   iԏbKӟy  y  o=  6<e < 洅Z{e   *O$< v 4`7Oy   saty  y  a+w=   u݃_>@  a ЀA5>   `7>@  a ЀA|Uܨ{ev   0wzK{i3 hA @y9   Kf=< v 4`7?<b>   `n>Y  y  OkO>   `U~-:HA @;  0ț>7   {㽋ƕA @;  0țo}   %뢳|w,f < fo>   I_ by  0 h o+ 0   CY];i2 hA @y]eb   Ҭe < feQ2   D!4C   ٭e^   SY  y  h˷jه   Ί#H3A @;  0ț'/   6A?M Jy  0 h oF-   `ԏ[2 hA @yW3%   6C>A  a ЀA~;޺+   `3TW<< v 4`7[OzO!   lx^A  a ЀAUT\}H   [7>4   ٩»'   ~A  a ЀAތG   rՃ/~~{iJ~ y  FOn   A  a ЀAlTC	   hAuU߄A  a ЀAofF   @zǽ3}4   鯼ه   Тj핾%Oڂ  a ЀAt=!   `zҴe < fB   w^A  a ЀAUu}   c=?HӔA @;  0țFW}    c?HӔA @;  0țΊ(d>   8utҴd < E{g:   }Ҵd < b3=}  K*>=vWԝ 0cF(|Ai2 hA @y>l U^oT\bcpGڟE?'+zG965/bDgayQ#Q~=;◢wb~}(o;/|)]{    IDAT#QS 4d < [Gه :^mIy+DطG'fuKފmOD8^w?%!i [uoO4   >d `nݝw6=5YCbE_^ѕGEʈr \?HA @;  0ț;} ̫{-s7ksm^;vLsDށkよa7c~i3 hA @ySe. 0sk^⠬{U}[qp1g 0?>/Mpy  0 h oz] Z}$ʛόyˣwGsV@So> `*U\eviB3 hA @yQ#A S~]yTOSzZ]~k//o>T `{4   hxC &^m1(~q[^wWGy#Q {4   )hvQ?@ gЉscpG{jbD.~QG LaoJgKA @;  0ț'Aa z^[>|[%1Z54   ɯ T(o;/ge,&g *X4i   ɮ{k Xz~74~	kŶ?Q~`/;,MXy  0 h o]~h! K?Y`MG~o+}{F$e < &b3<} uw|%Q{]~x8&%58ai2 hA @y3 /Ck^~Ռ,zǽ#/>`ITnX߃	  y  MnՃe ОQ/Fמ/$ig7~# ̲'~#+MJy  0 h o2}-ه Z{EO@>+{btg"*t (o>#~+MJy  0 h o2]}l [<mx~O?x\̩SZi2 hA @yoa}h f?G_~?_d. ЪWHJA @;  0țه lk?ΊmҦ;Q=x] _U  y  M^}_>, `w]eOiZuOߛ}:@c3**%g < &>$ *(zǾ=)֪cpފr}zcql~_3 hA @y>$ U7C>~)~?-dm xRVy  0 h oZcԽǲ	 n0FW||q~Iz 6[yۗRfy  0 h or U]ړW#ψ%FTe {ϤG  a ЀAT io=MQ=tSi	 lRVy  0 h o2*~qD]e ̹j?ĵr^o`:QA @;  0țC9V'ito~O&aojݍ٧, @A @;  0ț. ޣ18o+^(MMËvc &ZL)!< v 4`_П> C卧GiwDam WRg < ^v`a %z4{</ʛ>IdRZ  a ЀA^r+.0 `18oEtVnfe18cr}wJi	3 hA @y{g! (ort4u5t28Hi)3 hA @yL! 7	~bgGyi٧> ꡛ5)-Uy  0 h /b3> atǣX4w-l/  ,Gi2 hA @yyO~o;II^ߎX% btEi2 hA @yy7}!`Ɣ^W=Nu{UTn̾4 0a{0(-Ey  0 h /bgGY1,'卧e_% s/Di)2 hA @y9?= 3{h1t s~,lOƜA @;  0iO
@#0_,&&iʾz 0zǼ-^(;< v 4`?7e L.zGj=M;]?3 K4  a ЀA?; S(zaLҖ=썋Z XRU/NJ  y  -}_RKΊme~
 sz{4  a ЀA^Ֆ; fЉIIIjbD5W fob-oB[c?~ߓ"< v 4`?߲?r L-=50I9QK ӬFoS,,KI   9 S(v}VKx+V?3;/̾ 0QT_+{tzmto~/&%< v 4`t<=bᤳUKj(o9'7ӟ٣]~8%Mpy  0 h o7 Ӡcpߦ߷$%b]JU$u((cŞ?o,< v 4`ttvw{4׭6Fמ}5`܆Ew]KI?f < v 4`D>	Vwϒct	ٗ% RQ=x]:&gwZ|O~f0< v 4`4	V?r{t{UJb(o<=7][O4'   it5 ({	lQ ?[owyb|g < 򖠅e: /EgοWIVg_ h؍Kbx~?ȿOH  a ЀA	Tq1Mܩ-FW3v;EgIOA @;  0g L򖳣i(IS볢̪+F}&gm>(V?#/i3 hA @yK"˳?f &HͳrQ?zGe`Qy?={Eү  y  䍷bGU(o>OR"ȾLrՃkEFWGga빤d < [0!ʛ0ƓJC~.ٗ5T?r[:&gw/i2 hA @ymtI1 .$ivo}g{bt)18#;WX볤  a ЀA[m1 ;.Kf{Ey1`}?EӯÒ&/< v 4`76| [5Q{mUٗ:QsY/;0'7*:ү&?< v 4`7_# 'Ԋ<~$i[Xo|*Ham=)gw򯯒2< v 4`7kxHRw?~/4'!}]y18oE}{huTd < Ss#* ð#ޜ~/4_{ ʾ|!;/=ӳ:z)i3 hA @y{?Z 2TeC泍CXW(UD?}b|UQ|e < ʣ?Z N`=H|;ꡛbt'cۧ_%  y  䍧?Z C?y˳/7卧;Qk$=Yy  0 h 6, F䴰,Fן}iT=x<;/E>ӳ5I  a ЀA^%T?~}QGb3ZwC%t(U{룳U5L4< v 4`~MXX* z~'{[+EuC7c!Z%Imf < ZnQXX"?wG8lZzn[cM&IҸ3 hA @y=) KdtIڔɾdcV7Dy1Fӯ=A @;  0kYHX+ěiŶQuIhK9j1{,~[{F& < v 4`nMHa^~ϑͩǣ.}@am7s>wΪӯ)4   [uԽG?R Ƭ9}{D]g_F񙲼b-x^C)< v 4`^Cސq0f-gGgaY=GWȾlЉ΋bx~?=!I3 hA @y58' cTE7ԨGK*̟bt118c'~zvvI  a ЀA^{7q0FOnFڨOD_}YVoXӳG5:vL?%i2 hA @y-UG?N dtIj˾̨;뢼Oy[?7y  y  S(ۢIjѵ'e_ba:QyQ/''~,\$ky  0 h YG	>[IGŮώ/02UaΣ;.t2vv=kڊmSx8ԱKv [ZJP ڰ$Tw{9IΙ?[{?{<<xۻeg͡J   < yyS0.c$iu{kYE-4B}k9ܼnWϞr$   < yyu ]HҴcuG.,eeY{XZypEIRzy  y $0Ko`ӻ/IZ|~9z[0=~9zgߴ^~x^}H9;_=IR  0 H`^?># ].^#IKU-o450ٲ^M}(< <  Ig bTEWڊ[ueo_={܋,I2    A^=vkhpo$ _]Kzw$5*< <  %v}F 2ſ/TוhqeoG6]}+|HA @y  	jQoE߲2}P5.;k~ I2    A^Z?}B 2)f_E;ѓG,+o-ו+q/}/I+2    A^Z; ;FwE7A%_?ܲaW^βK  0 H`C?}B 2($g4]qpYeCٙeῗ%INy  y $0ț_kXA+[<XG4V<5|2Ysh9{J  0 H`7ys~+| d0z;煿+ĺQ4QlZ7+{W^SA @y  	&wǣ@݋HRnbG5K<[rqe·~:$IU2    A<| d)Z',z;?Ѡ=y~e{!̲w$MA @y  	&x@޺?O$iOw_GdC1*G`w_3]q@/Ire A @jeY Az=o$-߿m+[Wu^$i a  o:)t $_HҞThnP7*gF   < y+ pNZyp{"I{Z΍gѠ=y~჻w3HA @y  	&kpѧ AIk}'ˢL>ճ.+{|9=$Ijby  y $0ț{FI}+IS9
czuZuA7$iO   < y′O߾"-=?dRv-Uewl}%Iڃ3    A^ڧ&l $UxO$iO(ˢH߳h띻6{*۫Y~KI  0 H`W> m;7/Xo(GO=Xmk$I{{y  y $0ȫ_g`Bݫ>HRėeŎMXv[:$i_   < y>tc @y=E$MrL)z;eӪ{e{!~᷐$Iy   $0ȫ_}k @Ij}Grv}lg͡
u$Ig A @z) LS^HX{[yaٻ7G W$U   < y0#IkYVgC_.{WO_KIA @y  	> ^7D:ͲzpˆiUٽrvf_7I7< <  իPWU7D\U6hPS8^\.?G$M?< <  kPυ/^vZ}k9ܼnWϞrZH  0 H`WbO@Ms~HҾοn=
w$I   < yksPS})%uK˲7C*[6Tv/}w:?Ifg A @sPSӪC_9hXsAٻeg͡]$IҞA @y  	׽?$i_ueE?[uzvae$I{~y  y $0ȫ^E.gg?$i_lr?[V߭<8O$ a  z)\ 'Ig[q@ٽ]e?"I  0 H`WzO|+\ j%I$i   < yYVv ĮC$Id a  ZOL apYo$I$ii3    IDAT    A^:v I$If A @j}* ͖G $I$-my  y $0ȫVÉѧwnH$I>< <  Uk+O@Ek2ݐ$I$-}y  y $0ȫümwG
ڧ|!I$IZ  0 H`WL x7C$IA @y  	:g]熿$I  0 H`7鯍> uOI$IRLy  y $0_wD	Z'<ݐ$I$d A @nx x7C$IA @y  	׿3P[$I  0 H`7w> P!I$I   < yU~wo }kI$IR\y  y $0_30No]!I$I   < yc:'#_3$I$I a  oګ^}" *o:%͐$I$f A @PA$I  0 H`x+}" *h7C$IA @y  	~y *g?/͐$I$f A @qV cح$I$)>< <  -p0sI$IR|y  y $0C> cX{!I$I   < yW<X B$IA @y  	ifO~6͐$I$g A @kPy g)gfH$I3    AµO}uy cB$IԌ  0 H`p} wY{!I$IjFy  y $0[G1>^H$IA @y  	wGuG$Ifd A @߲2< ѹwI$IR32    A:'< >U$I$ a  oᆛ} SQ//$I$I   < y7|dcy XD}[[!I$IjNy  y $0[xO=} 1zB$IԜ  0 H`pE _+$I$I   < yyeY`ό/$I$I   < yZypi $I$9 a  oګ> cy{!I$IjNy  y $0țΚCOG{!I$IjNy  y $0țߏ> cB$IԜ  0 H`7} h$I$9 a  ozWEi u쏅$Id A @}ObFrvfY{!I$IjNy  y $0țOFE$Ife A @ܱ&4 ,b
I$IR2    A,4 ,bo$I$Y a  o߽!4 ,bЍo$I$Y a  ol> wi[!I$IjVy  y $0[w> yv[!I$IjVy  y $0[wO=} ߴ*$I$5+< <  _ѧ`}"$I$5+< <  _ o$I$Y a  o~;4 ,wG
I$IR2    A<,+ˢ> ;"$I$5*< <  /> ct|_{!I$IjTy  y $0ț[K^H$IA @y  	:g`΅o/$I$I   < ysk 0F/$I$I   < ysk 0F/$I$I   < ys 0F7$Ife A @[ h9o
/$I$I   < ys\ 0F_/$I$I   < ys^'g`7$Ife A @uzY }I$IR2    Az_?g`5$I$5+< <  ͭwG9$I$5+< <  ͭwǣ<I$Iҿ   < ysg`/$I$I   < ys}5o/$I$I   < ys4} $I$Y a  on+s^H$IA @y  	ֿ 0F缷$Ife A @zlY sI$IR2    A_;>, $Ife A @oY} |$Ife A @7} ^$I$Y a  on} ӟ$Ife A @7} ^B$IԬ  0 H`77VG1zW($I$5+< <  ͭg?^H$IA @y  	ֿ 0F蓮B$IԬ  0 H`7gE1_=.$I$5+< <  mpg`O$Ife A @:', 1B$IԬ  0 H`7k/$I$I   < ys 0I$IR2    AVE1^^H$IA @y  	pbY cI$IR2    A_;>, 1z[$I$Y a  on> cl	/$I$I   < ys4} (O$Ife A @n 0hXfH$IA @y  	ֻ#g٣_fH$IA @y  	ֻg	/3$I$I   < ys PA{+I$IRs2    AܺW} , T>uo$I$9 a  on+} *7C$IԜ  0 H`7e> t/}w!I$IjNy  y $0ț[wF
z3$I$I   < ys\gM3o$I$9 a  onE
O3$I$I   < ys PI$IRs2    A:), T0ΗI$IRs2    Ag., T0ztS!I$IjNy  y $0ț[{!gS$Id A @N|yY h=fH$IA @y  	:'@a9;,ݐ$I$5#< <  ӑ?} *jwC$IԈ  0 H`7h} *hze!I$IjFy  y $0țli 3$I$I   < yWl} *^7C$IԌ  0 H`z04 TлCo$I$ a  om;4 T1o$I$ a  o[6D
wfH$IA @y  	o> 73$I$I   < y7 PI$IR32    A>?4 TP<%͐$I$5#< <  _ӢO@N!I$IjFy  y $0țOFZh!I$I   < y[<4 T>$I$)>< <  _ﺏD:wC$IA @y  	{O@E$ݐ$I$g A @^ѧ7$I$I a  o:Vi wC$IA @y  	}kO@E.7$I$I a  oZ'<4 T4|dc!I$I   < y: PQ̖wC$IA @y  	@~9;,ݐ$I$f A @+f> >$I$)6< <  -o> OwC$IA @y  	ޣ@E$I  0 H`p|)< TI$IRly  y $0[k@E
7$I$I a  oN> :7ݐ$I$f A @|dy hwC$IA @y  	w_FF?n!I$I   < y׽ PհW,;$I$Iq a  o:k> 5Nxi!I$I   < y^ PC_;$I$Iq a  oڧ|y {I$IR\y  y $0[?} j]C$IA @y  	ifO@E[O;$I$Ia a  o> 77$I$Iq a  o}" *}wC$IA @y  	o'L!I$I   < y7PC;$I$I1 a  o> 5OC$IA @y  	w_G:C$IA @y  	{{O@k*$I$d A @PC)o$I$)&< <  -^{/D߹:$I$d A @kP aI$IRLy  y $0~e9G	]$I$i3    Aۢ@~:$I$-}y  y $0ȫmD	:g1$I$-}y  y $0G	Y!I$IZ  0 H`7=D	zW$I   < yrB apo$I$i3    AzM aeC!I$IZ  0 H`7> 5=vH$I>< <  䍯3PGQG $I$-my  y $0_ėG	ګ	?$I$IKA @y  	*ye9F
:C$I a  Zѧu	;$I$IKA @y  	*0ۢO@;$I$IKA @y  	5ѧI$If A @j7> 5>vH$I6< <  UwǢO@EQC$It a  ZK}* jjC$It a  Z}* j\䍓$I})< <  U}* jC$It a  b+~,Q ap$I$i2    A^ߋ> 5o$I$i2    A^=~{ ؾ5$I$-]y  y $0ȫWF:l#$I$ii2    A^X}. jj濄$I   < ysPSw$I   < y^'M~H$I&< <  UkI$Id A @Nxi i$I$ii2    A^f+~+d PtC$I$IS   < y5'	?~H$IA @y  	5|PS~H$IA @y  	տPSo$I$i a  ^?}2 jo:%$I$M?< <  ի{;O@M~H$IA @y  	>O@M3[I$I3    A^Zǽ$d UeI$It3    A^γgi	?$I$I   < y`PSw$If A @*l ["$I$M7< <  կg.?$I$I   < y]Ph$I$i a  ~ErvfY"I$I^y  y $0ȫ_WG	N7D$I4  0 H`7AG(l L`pH$IA @y  	&}2t ԻoI$I2    Aބ?{tS ip$I$iz a  ov: س=$I$M/< <  MV}: j*z;ٙI$It2    Adu/ѧ`OL"I$INy  y $0ți}: &!$Id A @j}`YE wGI$It2    A;}> jun!I$INy  y $0ț[@Mn?$I$I   < y7PSQH$Ig A @w`_H$Ig A @^G`~'$I$   < y>zM"I$IʟA @y  	:eYO@M;ώC$I$I3    A^ZųFFn
?$I$I3    A^Z9 Tt3!$I a  /gE	>3o$I$)oy  y $0KwGO:kC$I$Iy3    A^Z}B &лI$IR  0 H`V>! |7D$I7< <  %′@M;#M"I$IʚA @y  	2@]ޮQu"I$IʗA @y  	>30_C$I$I2    A^z}" L{I$IR  0 H`^F	rL"I$IʗA @y  	k+g`;r<$I$   < y鵎Ѳ,SPSo$I$)_y  y $0SѧbT>0$I$   < yy>S0_;H$Id A @<: L{I$IR  0 H`޺#O	OC$I$Iy2    A^:V)I$IR  0 H`ʟ>% (v<H$Id A @|	Z+C$I$I a  /}N &9o$I$)=< <  kp9`?H$I3    A^z, L`p7D$IA @y  	Y{X9o    IDAT!$I  0 H`. Lb/gWH$I2    A^Ɩ_VI@Ŀ#$I  0 H`~[>) ^go$I$)-< <  mp'`H$I2    A^z, L`Mo$I$)-< <  sF	I$IRZy  y $0[ėE	Nxi;"I$I<< <  <}V &йwI$I a  /-
z7m"I$I<< <  opg`o^H$I&   < y]0ѓ!$I3    A^:) Lb4(g|~;"I$I,< <  uAg`B_H$I&   < yө0C$I$Ie A @4|0Uo$I$i  0 H`7O>- I$Id a  o:uzi@}YH$Ig A @>ѧ`B_H$Ig A @:,0
G$I$I3    A*0-+I$IR  0 H`7}^ &0o$I$~y  y $0ț^}^ &P5$I$   < yӫ{;Z',$I$   < yӫ}+:=$I$   < ySlfYYvD	o>2$I$   < yS!cF	7C$I$I2    AtqV@co$I$^y  y $0țnuGD	VH$Ig A @YshP#$I a  o,30ލH$Ig A @W<pI$IR  0 H`7߾2 L`I$IR  0 H`77}f &QeG$I$I2    A\g`B޽G}u_qtPPxafQY,,AGː6m^Ҕ4-mCZzK-iK&ҳ{Y'EB9{^k'绥?_$I$2 (   A: Ի/$I$2 (   ATuQP`$I$2 (   A4?j j~C$I$IA @y  gDc4L_~G$I$IϜA @y  G8G@M:H$I9< 2  2-Lsc O$I$3 (   AuC gp9wD$I a  oG?CwI$I3g PA @k𙋢 1ٙI$I3 (   Aջ >'$I$i a  oK?n j~I$I3 (   AZҔ*G@N#$Ig PA @ڵ=G@/~C$I$I  < y?#~+.;$H$I>< 2  2-lF}k$I$3 (   AY8G@M7H$I>< 2  2-l'G@MO
#$I  < y_#?v j޿1H$I>< 2  2-|PCٕf~G$I$I  < y_ :wD$I  0 `u/yK)H$IA @y  )PSc$I$i a  /dtu$I$3< 2  24~Sc7D$I  0 `S֕?z jj;"I$I  0 `S?PS7I$Iҷf PA @ڧ= 57~G$I$IߚA @y  ZzpzOEa'$I$[2 (   A^\훢 Pu{X}G$I$IߜA @y  rjڧ&H$I9< 2  2ս ]wD$I a  /i?mI$I7g PA @ע  5|[$I$}Sy  e d0ȋm'  u:iv9wD$I  0 `[{  5;"I$IFy  e d0ȋ{oG? j~$I$ a  /)~ 4;"I$IFy  e d0nAj? a_I$Iҿd PA @_. Phf H$Id PA @7 zQ$I$  < yu/ zW3H$Id PA @Z'" P3I$IҞ  0 `7UF? j="I$IړA @y  ƣ築~
 QUwD$Id PA @c 5u}$I$ b  o<\ @M]$I$ b  o<jO;"I$I2 (   AT} @Փ_!$I$< R  2O] uwD$I=< 2  2O3:F$Ii  < ySg @MO.#$I4 a  o|j&H$IҴg PA @zOivAwD$I9< 2  2W~$I PSWI$I  0 `7^w %o	#$I4 a  o'@MM#$I4 a  oj; 5!H$I4g PA @` T]vH$Ii  < y`ګ#$I4 a  o}o 5u;"I$IӚA @y  Ư~ Կ}wD$I5< 2  2_c_RUE? j};"I$IӚA @y  ƳE? tQ#$I4 a  o<{q #$I4 a  o<]@MݏI$Ii  < yYܟ~ 4wD$I1< 2  2iG[JA #I$I  0 `7j4L_~G$I$i a  o|uN 9#$I4m a  o|^@Mk2H$IҴe PA @}ƏG? jl4H$IҴe PA @1n!)f 5T_b$I)  < ypMOZ'~O$Ii  < y]擢 5u?[wD$I)< 2  2wKGM'I$I  0 `7޵N~e7I$I  0 `7U;	 u[iv١wD$I%< 2  2C3?~G$I$iZ2 (   A8L I$I  0 `7uJ3=I$I  0 `7V,~* 0zswD$I%< 2  25E? ꨪzwI$I  0 `׌( PSgͯI$I  0 `׌zW3 PSGI$I  0 `׌ګ& Pk$I$MCy  e d0kHG=/a? PCٕfK$I$i3 (   A^s=twsi	#$I4 a  9o?3 PS~G$I$i3 (   A^ss L;~G$I$i3 (   A^sj@M~:H$IҤg PA @Tu~2 1I$I  0 `׬|" PS5H$I$g PA @fտ'@Mm$II  < yͪߊ~2 4G$I$Mry  e d0kV7 PS5#H$I$g PA @U}g@M^~G$I$iR3 (   A^C {oI$I  0 `׼z}-I$I  0 `׼:> PK
#$I4 a  y}IJ( PǠfzn-$II  < yl@M:H$I$f PA @f6@M~G$I$i3 (   A^3]gOP$II  < yͬ}~: T| H$I$f PA @6@M;H$I҄e PA @6m:f$II  < yͭi7'H$IҤe PA @ֽw 5D$II  < yͭ}ʫ ufCo$I$MRy  e d0kpKJU'@MX-$I	  < ynOWG?! j~$I$MRy  e d0kvO ipywD$I&)< 2  25Κ_~B 4zwD$I&)< 2  25֊TU:*V4H$IҤd PA @7zg@M~9H$IҤd PA @7EzI$I  0 `z~F 4cwD$I&%< 2  25? >f~K$I$i2 (   AtsSt 5["I$IA @y  &W~J Ի$I$MBy  e d0ț iI$I  0 `7u-~J T=;"I$IA @y  &~J dho$I$5=< 2  2MHKJU@M~'H$IR3 (   A4@M~G$I$ a  orrysÛ$I$5=< 2  2MN k4Lc_~K$I$ a  orj]	~9H$IR3 (   AdU| IPSGI$Ijry  e d0ț^ ixwD$IA @y  &~R ՛M%$I  0 `7YWL C׆I$Ijjy  e d0țz^J^ކ?%$I  0 `7y+YP`ewD$IA @y  &gD?+ jj$If PA @ɫ{D?+ 2N~e-$I&f PA @ɫ}G?+ 2t/["I$IM  < y҃R ipYD$IA @y  &~Z 4zdK$I&f PA @ɬñO*V,H$IR2 (   Adֹ7 :["I$IM  < yY븗G?- 2oX~K$I$i a  orvm~^ 4|;"I$IM  < y`˥4;["I$IM  < y[wE?/ 2SD$IA @y  &9~^ dVGI$IjRy  e d0ț~~J~?~8H$IR2 (   Ad7z'@M;"I$IM  < y ڧ:H$IRS2 (   Ad׽Osǣo$I$5%< 2  2Mv^ 0["I$IM  < y҃R igo$I$5$< 2  2M~~f UUuwI$IjBy  e d0ț7~f d\["I$IM  < yܐtB-$I&d PA @ɯuˣ _9H$IR2 (   AtT kMG=/H$IҸg PA @h@9%$I4 a  o:]@.H$IҸg PA @hoV&H$IҸg PA @)4G?7 jzOeI$I  0 `7='}
%$I4 a  ozqVs CwI$I  0 `7=uxks WI$I  0 `7=O{Ms C~".=8H$IҸf PA @)jA~r dhD$I4< 2  2MW~r d]["I$IA @y  + [.%$I4 a  o\'@ꩯ
{"I$IA @y  q/~r dj{"I$IA @y  jg@o%$I4 a  ol4aD$I1< 2  2M_k P}KD$I1< 2  2M_s^ :D$I-< 2  2MaG[JA CwI$IVkKS_Nߝw) a  o:=|O !'I$MP3#Rʷ5ickJ_>W36$< 2  2Mg;Ί~z d=q_-$IT]Կ4z讔   < y@N{"I$iN8<u.N3im}O<(GS2 (   At>5OL/H$IFc^:ކ#wlbgg߯	 a  oJ[zP: wO$Iim١{zvݒ44ڱud7_ZǼ8s2 (   A6@jD$I^ԿuenߔҠ[w?&d PA @Ê@I>H$I8]zgpTf PA @s ~?H$IMűRgpdl^oG~8U2 (   A:L{'$IRcZvhj:"u-I;N[SF	gD?d PA @ڵ=	    IDATo$I4_=۽ͩ4ܾ)~;5Uϳ	 a  ol4	u+$I4ũq&OU4I:b?&d PA @wͻ  {"I$-d/LՋRoÑiy͞pZ?&d PA @s뢟  d=$Ie#Rwݒ_=;z讔Q6݋h@y  e d0ț~~J~3 C/I$Wo:>oJߎ=nϦ	 a  O~ djD$Iz9q&OUc?
y5!< 2  2ipYL$IƽE4ؼ&vl(3lBy  e d0SF?C 2>}a=$IRHݏI}^=%0csk2 (   Aڧ&D$I[SgԿ4ܾ)~+#}oM  < y]zP:" +0H$ik9q&OBoBy  e d0\/\I$MX_:\]4rivm; a  OsoX4/H$IܲCR{nIߺrW{s8:4 < 2  2i΅o~ dZ٥I$5	{zvo﷢?Ҳ3M  < yuˣ" c7E$IWؗEImS5#+RQ2 (   Aj@5~O$Ia}kSoÑiyMؚRUET%SӉo a  O`˥L~O$I-;$W떤+p菥̃'ǿd PA @<ss V7DI$OOSo̞\F&d PA @<ss^(zQM$IR~c^]cg|#5	Կ7ل  0 `4G?I 26.)$Izvg66פю)UUGKH3i2 (   Au~ d>xc=$I~ZvHj:"u-5Rt?F2wvA @y  qV װf H$iOOSo̞mH:7-7!< 2  2_׽O:"I4yq^g\ѐ	1݄  0 `]D?I 
o:1H$M|3+ߞפю)U菂Lƿd PA @<}SKJUgW 衻o$I҄:SwݒԿuenߔҠ)2̇4!< 2  2i_.Y{#H$5{/u/~StB>Tu	)7ri&d PA @<]rM$IjBc^:ކ#wlr-yA @y  w#YP@3o$I5sXj:"u|h0/Ӏ  0 `k]F>H$=+ o?#rgJ~4eA @y  FO|!iP@WIuᩳvqmImS~"3?cM  < yWs_@u|[M$IZǼ(uV/JGj`^:7]2 (   AUwD?M 
l,H$e=_=nIyvؚR5jYl@y  e d0Ӿj	@U{g]vH]$Iz_=۽ͩ4ܾ)A'cqV&d PA @<R귢' SwE$i?ũq&OUO0/k2 (   A' wM$IzQm826ճjU&d PA @<=]N~ 0|"Ie#Rwݒ_=;z讔QG#h-n@y  e d0oE?O JRI4_=۽ͻwR귣?D|R&d PA @<_ 0:!HɩuISoLn[cw`7g	 a  Oڵ=P@o$Ijf/LՋRoÑiyMR4!< 2  2i$P
)$-;4WCw4Fy7р  0 `ջOBZ'2Huỿzi}SJvGi?<wF2 (   AW쟎~ ҽmwE$:Sקƙ4ܶ>UF<?ѿGA @y  ߎznJn3$IZZ_:|]WiTQԻ~i&d PA @<=S/L(jL	+$pMUG%=_=;E 
]oA @y  Lo9%PH?~W$IR^S~ u/Կ4)1	 a  OTD?S 
m\~W$Iҁ:%zQ}opT8~'5!< 2  2jE?S 
}SwE$=M_g|4ؼ&vlM?> c{j@y  e d0ӁT=
@	aj;$IS߲CR{nIߺ2oJi؋ oՀ  0 `iu]Se~W$IZ':kƙ4u)[	eM  < y:zUS+$Mrc_g?7im}fwD`toM  < y::.PH5h]zpm$i"9,|mm8r}ckJU}	^3A @y  t@
@!sÁ"IRZvHj:"u-I[WM)g32`2 (   AW~ һwEquᩳvqmճ'bsߋM  < y:Z\(dś$ITE{zvezsMZ'2we2 (   Ae3PhZ+^~[$I
i=_={`4ڱ5 5vl@y  e d0Ӂ:+ u/yKm$i[vȞݺ%4ܾ)A7<k/ڀ  0 `gSW, >/HTAvqmImS}r=ycA @y  l~'@!s#٥I:ũzQm82\\Uf PA @<=z'@A3~<Ht@g|{l^F;TO)t7$< 2  29磟, o$I҃xk~f=tWJ~Sܐ  0 `gOi؋~ 2E4N8<u.N3im}ODHR| wuS2 (   Am/l(e4L|gm$MOc^:ކ#w=9wS2 (   Am[N~ ]$H&euKγh֔Qh7NoHy  e d0ӳ{񛢟- $H&g9o]74D90U㛒A @y  lkaEԼ]g8֧xIXO_{) a  Ouv>t(_-űRgpdl^G.ҿ[Д  0 `:>6PPo$iLZvhj:"u-I;N[SFѧ
`o:>>4$< 2  2NݏIc-ho`Д  0 `:O@aS_~_$I}4$UM  < y҃S|(w_IRxo>I ekģCS2 (   A65_~[$I7$E~A @y  T~ 4ֱ~_$IU_RE`/B}hJy  e d0S` &K7IRlUД  0 `-M	1"Ik١)UU9`/S^#A @y  +wF?a 
ZeIRL/>E C븗߈d PA @<Կueι?~_$I1O}u`fznhJy  e d0SNK()ESg3^I a  O9NOª]IRL} KФ  0 `ܪ]ۣ1 $i^^F_=>4)< 2  2)g.~ ֻ~i}$-|>!>4)< 2  2)?~ 6z"IZ} C2 (   ArkǢ1 u+o$ia_'߇&e PA @<eTu~ ֻ7FX`/]}hRy  e d0S;3uE7 G(>4)< 2  2D3O҆Z#IZt.zc}hRy  e d0S:>)0n$-PG?? s^#A @y  T4D?g 
l,H)?}v ؇
M  < y*衻3 UQ1sF M  < y*Uӣ3 so$i^;'iv7I a  O^y0#Iz׼+ jд  0 `R}yPufzn$oO>9 eд  0 `U~ ̃_1mu]`/7߇e PA @<lOy0#IF}n ދC2 (   AJE?i Aٕfg~g$IW}n KC2 (   AJ>Oyҹ$i~j3>Ѵ  0 `U_(Y0w~c$IS>3 CM  < y*K5 j=f~g$I\3>tѴ  0 `i`t;#I*_꿈>1 CM  < y*]{ՏD?k I3$|O>1 ~#A @y  Tj<p]zp$mxߵ'T a  O?'B$ڵ= #[C3 (   A~ ̓3Qy`/>#A @y  4<OٙIR>>/F41< 2  2i^Zzp:7 Wo$HK}V ؇ǆ߈&f PA @<WC`yԝg]LDQA?9L
=*8QG=N?=ϓI灶6iKP	ZJZҹN)mӉ6S&}Vh!Ó߽zK\+'sR=#ISwlVt;b3   <W!9w$zo} S~+  0  Oêmo }?CHR*} o#&1< <  *0К-q w$ZoG_) lE'&0< <  *008#IҮ:ѷ	 [o{b3   <WOG!Gw$i(X~GLjy  y T`a>? sIҮ׻bsQ1 a PAڒgkEA75FK:?&`+ׯ#&5< <  *0Ӱy!FkF ؊W1  0  Oîw9 C4xFm	 ?  0  Oî}{? SYa	o$I;?֊A @y  i-}nJnG!^Hv%}} _~OLjy  y T`QT|: CT_3IqNtw$g A @yE+0d{7WnZ}u cA @y  iW?;:$ͯ?}m 5A @y  i5R10Dek}j,yv#Iq>}m ~OLry  y T`QU1O
IzW}e 6  0  Oww lpIҎwi6tN@=1 a PAFUsq`%w$i;-=n# `ZG)  0  O)< Cֽw$i۵V}U e{A @y  i]`ȊGoo$Iۮ* ؆rӺ{b3   <G1o	s$I[op 0{b3   <I`~HT7D_ l?GW   < 
4Җ>7~'c$~Svt/D]1 a PAF+? @9gejz_]1 a PAF]w= #0;Gw}= C_~WLzy  y T`Q>{ F,S밟w$IS}; -Nj./&<< <  *0[GJFG]<ޑ$̻ x a PA"> #PnZ;gE_ lG:d A @y{?E!IP7 Ot da PA"jxkG8ޑiyR*+ a PAB]? PuO=4u :d A @yjp Fw$Mso} /
/A @y  )`D擩dGŻ ch}Q  0  OQ|cI'j ,Ky  y T`ʍE Fd5$Mc돉 ؁޵u   < 
YUG j}Ifr#я vg$< <  *0Sd3$ 0BW=4MV`Z+~g%< <  *0Sd^RYF F#{    IDATL~0iwO~ v,Rcu   < 
] ^w$MKwE?؁ɻ:e A @ywa *~05fw$~S#yvVQ  0  OѵW? 0b~7׻= ]8ΨSy  y T`>7~'( 0B$,LƇ CTrf A @y]} 1o	$O< :':e A @ysQ `7
$qRc6~iQ  0  OЖtS󀗇ATOy xF2   <ERZ} ޥK IY <o<.ި[y  y T`qۙ+O>$N <uxQ  0  OR?> /!%)_C~<~0Oϼ;[y  y T` Lrx{HPяu ,Ss;A @y  i*X}$ 9O IfwKuяt X6ay  y T`qwG ţJ$MrS?8`'uZQ  0  OT{ Aڟ{H&=_~𻣎 a PAƪI׊> y=$IZПH, 
?A @y  isQ  Hk$Mb+~3"5~1< <  *0Ӹսo Aw]~IҤ\T7D?	cu   < 
4nx}  Pk["IӿyUQ  0  OX@!If{ *iy  y T`q@1o	$iяl vAkwH]3   <cS?}4 4H&⡯G?YE?5>'ky  y T`ql@1o$ikяj vAwH3   <k> Hƹ]G?CA @y  i\^HeZ+~I8姈nyN0y:E=R  0  OZ7E <>qlpEяh vіH3   <m3R#@$ij;RcwI3   <s>" +an}'IҸ4X{q]'@?< <  *08>w csI4x wwI3   <s}R}L V<qWj~/IRtD?_KA @y  i+ آ?$)	~PEY/OA @y  i1Pn~45~/IRH3SG1 LAy  y T`qy諣	 cwٲ{I"|D?d2   <MBk
 NC~<^QH:g}8N  0  OPC
 c%Ie~AПS!< <  *0$>ᗣ
 ,S_$i5zeJF	S%< <  *0DxTv6F Du1 ~!׿yU#~LKy  y T`Iik Y~7I0kι

^7ʴd A @y:g$ 0FO4n~I7-SA @y  iRjC)E`?&~a]= n#5~LKy  y T`Ix#8)ZIrkS귣 d2e2   <MRݯD L7RcvQ%IYY~5
@F[~i2E a PA&Q?}d C?~GIR:gi#Ǿ#~  0  OV}1Sv6A?~GIR,ǣ dTv7i   < 
4id` *֜( 3F}y  y T`IwG T~OIҮ9яP {߅1ӖA @y  i]G1TN̓^WIN:5l~0O|=3m a PA&͟>: -1y7[*G' CP֧f2   <Mb>}t c3>~WI|ꮞ~d0$g1< <  *0$)1i$~uqm)zяL 5ӘA @y  iRr`¯45Tn?Q	x]}3 a PA&93 0]}%I4G$ CTnZLiy  y T`IyR*#8R똷Y]4ol}3 a PA&_>B ;Rcs,IRT Y쏄9ӚA @y  i^OG	п;KX*OF?
w5< <  *0$:G	9[%{ @Ě{g3   <Mz[^t	$Ma3R[E?5{8< <  *0Ӥ׻|y1`BOޝ
$MW
0]'J3 a PA&o>F L]~0JFj,yv3 a PAP~mQ`t/KRkΔG #4g3   <աUE% &IYɿ~Io#^SO; FsGi   < 
TZ+} 0e:w<e| X=4 a PAĵT>`q`Oݗ$T_Gx @m  r1  Ouw		4X{Ij,=45 ]X HC" b PAR_>N L7Oiw	nsˢg j  21  Oifa*7=} PKe&Ż/G? Tv7ƒgI2   <թD) &XK$MXR[~|lp$e A @yS} dE??	iv_y sg  0  OjvQ*G+ &Yǿ+N4-#o?;hIs a PAVD+ &\~:w1mKU ⑛&  0  Ouk˯u5IUskQ IA @y  v-#G(7>:n45i*F	1:g({y  y T`:ֿ@MO(ORj#xG cX633   <ձ>Z l:5E USzfy  y T`Z6(>^ ԈQ4W/я  TkwA @y  䩮~Tf'_~IM6~ 0IA @y  䩮@m	~.4f Pc,}_y  y T`6 >b Pz*V=/G?f  ~5g A @ys>b T٘ǿ+֧S*Xx`xKߟA @y  εyK9;I')uO &Dυ]zy  y T`W'Pge_N.٩wO &Lajy  y T`׻|c2i,$ͿJCE?> 4Vj{L[   < 
TZGl1`Jo;+5~Iqf*[OE?6 @;	Ǵ  0  OPG)1\O6Z~4 Yϴ  0  OPwlQ`60?IϬ⭩xbM#Io沽4m;< <  *04: SPjswg=R)G ۙA @y  iZ*>0m9#w4͵|c*4 &:~ n3   <MK20z߅T5(u);я  jlL%{qny  y T`iKS SjUyCij}SE{ j88< <  *045Xs^`N{߇R]k.OL PCU  0  OT} vNwTfΙ͏Fp jl>w  0  OSՒ=S}  :?5|E(MxO6^}uGy_y  y T`iq 攛'F(Mb/L+HiЍ> L4  0  OVwE; xͫRsߑDx9zZ Fܴ.5f߁Wy  y T`kfA*/3W5 u>{X60ezWj a PAF= ~ /5~WJT_NźO( SưB?< <  *04:uG XOjz})E:$ SxP;A @y  iZ+!vRjw4ZR3R*c^/v.< <  *0Ӵ= vLՋScɳNiص} BY
s a PA?Ҡ}`^L~Jh˯h<xu1g8g A @yw}`o?;x}*UnvQT)XVuP}   < 
4͵O# ;,R3Rׄߥ\=| TN7 a PARc fKV息S:uw)u' v1wv-< <  *0Ӵ׻c wU,L#^RYF ֊ߣڥ  0  Oޖ uPJճKWMw̓4uRc ;xTA @y  IJ> O7J#^~jZg|/TO Ej3   <Y?> _Y̍'7U%HV) <wv9< <  *0ȓ^ CS<t]|ScvQɯuOeRm j{V2   <_tBq2]$5WU7WgRc isU-< <  *0ȓq}`ޯΙK~k<kS}SџX Dj,#U  0  Of Q٘7J~+s#ũx& TCbU   < 
{?EI U<zk~S듯5<uprr*7?e?5   < 
gT% {SSŵ{ZmiRƹ Lڋhe   < 
g6Xs^Sn?djԘ]~_kjԽip)' ;>~_+Oy  y T`'=)},`S'A=-#V]q?/ `M~l, a PA=.J& Lԯ߼*u<G)}{Sw4X{IJVG &J%e A @y]=}4`2e*-vdj۩yjɳS7ύ7LţT`r}f a PAm{[^ Օwz-KS'5~j>S7ܒҠ jep|   < 
7 jl+L >l,(ns?z_Tܻ:ǣThkP  0  Oz~5x)צ-'ũsʷ?j^ZGiWvԻ4T<v{JN 0kVP  0  OF3^ lLwWguGޥK~kg~)>3y+RcvEyOT-7;~ ugՙp׿̹'֤kF lC a PA &WٔST>uo*ߓu75ҹ_2YsrzO:w~m{   < 
m|귣)   Q9h8 a PA<%   V-}A @y  Iۯ}/FS    Wk2   <i}T  :}0=   < 
_EU   r1[{/< <  *0ȓv\sS6+   PAOcp3   <i~o86   lLe{_p3   <i~|cJe}d  ]лw~y  y T`'Ϳ,   Aj
~y  y T`'Ϳ)}d  Կw
My  y T`'D3S~m   vB7FA @y  I;W¿>   <.A   < 
򤝫lTv6F]   `:a.< <  *0ȓv׏>   O;5A   < 
򤝯צT   ؎f A @yҮ5   lC|25y~6< <  *0ȓvG_   `_	wg A @y.6 }  Qv6/wg A @yҮ=/0   =zW@1 a PA5y~*OGc   <(&< <  *0ȓջc   uG+P\y  y T`'Uy+St2   PRׄ+P\y  y T`'U   Sg(6< <  *0ȓJ,3   L~@ a PA]Dg   Zۿn@ a PAg~)8  j;݀3   <)_7Di   :xd A @yR:#   S4 a PAEXO  1X  0  O[}  `jV5]'< <  *0ȓ2l<}  w|1=*< \2  IDAT<  *0ȓ׻tI  z+:h2   <)~0n#x  @mo==/< <  *0ȓSOGo   bZG!/< <  *0ȓSW4Fq   -'xf A @ytB  t:;3< <  *0ȓWפT9   Ɩ}_A @y  Ií碏9   à:7< <  *0ȓ[7TG   &^5 a PA4}  `ZyЏxg A @ykF?%   *]4?< <  *0ȓFs;   Lxj.+?< <  *0ȓFS7TG   &NK^   < 
5#   xX{wzMFy  y T`'ʷGy   (>}^A @y  Impc   x1 &'< <  *0ȓF[3>   0BxMVy  y T`'WD}   k;]A @y  I};>   bZG!&/< <  *0ȓbsQ  Ի  0  OưS*G    95xyvMfy  y T`'5я    +݋)&7< <  *0ȓjƔ"1    cX65<;&7< <  *0ȓb    ~3{&;< <  *0ȓbk)zя   5X{IwtM~y  y T`'׿G   Rׅ?g A @yR|̓^R8   	nzd A @yxԻ   \x,50{A @y  IQs)    #Nd A @yԻbG   LԘY}\   < 
SX   +ZWy  y T`'WݯCc   ¿~ a PA4f-3~4   Дy+⿃v a PA4~uG   Mzf A @y6 _x   슇oHE߽U  0  Oǿ3    y:M߹U  0  Ow   lz][   < 
uO4E?&   rӺ\ڪwy  y T`'w뎎~L   @eS~;;A @y  I]sJegS   vsÿ_k:*V   *0ȓƿ%   ]Rv7
nxbMG   *h/$IF?.   `u/߫55 ԂA @3(E9#я   )[~}hcߩ5= ԂA @?L<Y   )ZӚџ| Z0 }_(4ǿ+~l   ="{4F j  Η?L   lW~mjК ԆA @K_I̓^G   l]YϚ: Py  t~T2I;W~t   VvdfMgo ԆA @o}>elɳS   <CԽ~Uj_  @m Tпev>/  +eڟ˚޺_X)  < 
LҮ5XG   }ɚzW}  j  n+5f0{MJNS  )Wn?5 {gG 0 q_IڵzW  `U		~,n>  a PQs_IŖ>7O?  `J;:40n#8  ԆA @E38]sƇ#   Lr~UƢ'_}  j  4Tipя   _U1sO @ TԿf:gS*я   D¿K߭w# P+y  	i&z~   0GK,}_>  b Ac8T}G?N   ~'>3߁6 'O @ d:7_I\{'   X	+ZG1X  ԎA @+y&)O[O~   PCs_D 1 ȠU/$ySX  F<G¿J[ @ ͋&)Ov8   9uN50>  c IwǿDiUя   jJ[u[ @- dҽh:Sw-   LRs^q]=}D  j   Dˣ-   LbǾ#o-  ԒA @F~4E-3Oh  `.'{*>&  d QK+eOx   Ҷ^w   2U4I߼*  (A.+mbݍG   r*8Wn5{I*7?  `ܕEjkc:'O
 @ dֹo_I_s5  ]<z}T  j   7T4<%  EjUnrӺ Pky  C_I^sRG   clO̓_UQS~;  ԞA _rMpk  xHU*ͧ]G 3 95y~6Ié   cw~S:  A thK6IéSi]c  `J¿JqG `* I޴yfa6Ié}⯤Tя   yȏ?S󀗥oG ` 0DS~'eտ   "W/{4zW}j  A >e\T>`  ^'[s)  L< !knW_k  /̂|]}h *y  Cn[c5   @Ě=To_R}t  A >/$沽RG   CTv68ZJLlQ4E7%8%˲dj_Le٢vo**P_HWke|V,_UN(R
X9pCRιH}׻Os3OmWe c! `O?!x4Z׼7,   u鳧O[ @y  qY#ݺ*  ` [WϜR{>:  cB <)S$  9T3Gd e! `uJ4Upu  (K5~j~MTe e! `>u?Il}   p:h^S>=  cB <+jC0'iJu  lUURֵ  < ?8'i>s  Y}^\)ʓ|ng {  QG:Iy{"n  @zoĢR?}|   Ơ]   3T>mWƲgIZ7|   "y  ڷX'iM,   :L4ּ)>B  B @n;3N`k\Qe8   N=ޝ>?J}|IOܗ}  5  OHs   *}?ύl KX n<Ile_7   DgEi67.>>  < !Ѿ$K|j[u  z^?+J?赲  Ga! `XE4<IqQ5f8   cx8='JFUE eX "Uh|z[kGTe  0C{1uZ|([ߎG  `! `ȔD}w$=S  XP껕'G;G W`! `O8+O4&Eksu  0^h]P'E X R}V7Fu  `<En@,(%Q) 0C  Xo-Q\'i`ˈ}   ,x[>>J}|Ik >X rn?Is秲  {鳟w+FM >Y R8g   +}(v `, ޣEmū%  `A)vmg>Sor Y 0BzU?
JLu赲  |h~M'Ss  0bo7?JL˲  W5oJ~j}Qe  < T~:W+P`{Q5  0h}[l'SOD  0h~%Q=  9Uͫ<fڪS  0ʪ*:^Eyٷ  赦?=I3y[ܿ=  0, , [>uZ#qQ5~}   W?>I3L#  < <7W(ink}oa	  Q޸,}~fRG7O  d! `!)l=?j'?.J:w[  0:7<}nfR:L `, ,@žmѸ鏌_ξZ   Ng5j9=Gn>.  y  U-%鏎K|7  3?IjvnT yd! `+Y4HI]7F
  @g4X7Qߞ}T  H`! `et_鏑mf*   izĢL:Z>&  $ 0Fv-[3j+^8)i7|(  yW<?ӟ͞ˤ\m>&  $ 0COFƏF4uTU  0Go1饿  y  c<7ڷK<fK#Ye_#   O⿆gEf` o @Ds3%_   XȊG}Lc_FEd  <  ~j={/7?pJaNm  @e<7qB}_.>   y  c[FmrIçc֘zC˾9   T؝Vso]  B  T.ƕ<J:z͵gF<}e   ̉bfxV.[ա'   #B  3V{?r	_k"ʾ*   KkKW:}oh]}Vti  抅<  f=Gk㲨O*is"2   b,i[4W+_Htsq{kg @Y UUx$?B6s4.}J  FMφfTV^4I?;:g7E쎈  @#Q^]?/u/M,ƠWd_   }yW^\rO~?ʧDy`W6t  ~}    IENDB`PNG

   IHDR       o   	pHYs    {Rk    IDATxyfu}.@PA)N$1h:FӭIrH{k̓M\ImO5PŨL2DIeAdg?߻`v3^kꕵ:9{8O? 53w({]V'i:gF   sߎα~ޒ4bms%cpYQv &  >w}9.ogo-_dV   sךg$A˟~7z-Dݐd MAV_w>Z?KsPs0  ySu7D7$Yw_}W~> 43@:Vo<%:QV<'+qݳ:*4  y+GGJ9LsEG%Y x2( |ely;  `T5c&DsOn9#~H1@`5s~^VfE}o9  UXi9/ُ8 	( LA7ִ4]uD  p3}ԯGFzُ: HcT);Gk־/I?Jcpͱٷ  H0B4zat/\e&q  P0_s;ZBxxr-  0R‟?Iܖ?;$ُ֣< X0( LXth-9)-tKv-g߆   #E҂lQ`D*;_<t[  `߻3}_4-5z_]+} 0oP ,e뎟Cҝcxw#  X()4_{|DUe? ` 01/⓿+?;/Ͼ  ʦsԦ$}4=~K6 s WE+Z3ۥ̊Fgߒ   cixWd)jkFwc# 
 cmp9Ei'#  k>HZ:e &
 c,D8FbnQ>  `"<('i
Yݳ&Wd?` 0v}m_
Q  `.XyOtV1|  l Ǡٟ_s|;  `"us)mG#*Q [ Pn|8ڟß4"  yVWe{m 6
 #oˢϋ|ҨT|^]}k  La/:ǿ-(iʿ[ YP i%OK?I#O|0  z_M?Jފώ-gd?
 Dj.1\}y	  0uκhKBI̢]*q O ?P'R'   GKχ(ُD eH)7>O?I#ҝbxٷ'  +q0ωIw cP 冇8x4R-11  ^2{VK?/Jڟ( CP 	oGqOܤjbxٷ'   ?bpͱgFIS__> ?`@᣷Gkߗؤ  'ѻp&(i+>( 0 T5i.7|6  TUtO`R7;Bu<   T?~@FE1֧oO   6ǰޚ4~'3@ E(4j/7  `T>IIjgq  A.@&Z?  S[ž/N?WJR笿~$0P XX ڟ4jP	  6(&eL?_JR L) TM?IV?  m4KZC9SҔ7]nB#)d]q@K7fߞ   ̑H?kJRk.1|G" S 1BH:ǿ=b˾=  c?~攤WF^H` 0uEk.ijzoO   CUF3~# , Wῒ~ВF'^U  yTu7D_L?JR﫫 L	 U+%R~/j[  Pv~4-!}-0@`<?Z3X҈T|^ܒ}k  /֒ϤWFYH` 0/֣E+idZs"   OK%M}32q3@`^O42-yZRm	  @>4,md?`( ̹u'Q:_bm	  @rcK9UTW( L( Tz,Z+~Fedߖ   &UYUt=ُC &
 ssPҨ   ۢXkUx>pU	dy^I:Èr}[  0q? g]%Mo#+ 
 sc؏=N{  ֿ|ُB &
 swL(OGz$  `ts%ݍُB &
 ۬l=}^{oI   Š3W4ϳK L YK?(I-%};  0fuX{VTV,{f~0!P &%)bxٷ#   cjxυZ}VT=#ُA &
 ۤ?M? I[  1)˾

 s 6ޝZX?Ͼ  Uݓޕ~Ε4u/OA &
 [s:'׈r}+  0!κhU]IWYQk 9 Jh-1`$e>d:gߊ   Ltswپُ@ Ɯ
 [{?}^e߆   LM?J_1g?c( l>ZwM?I)-)}  0z]Xտ c -ֻ!)bpٷ    `؋o?K:G%3@`\AHʨٷ   SP8<,i>rk1e{IHʨ{{#*  `8ZwH?KzG c -9 ik"  `J/7l,iz*{Ip` { iܛ1   |Ȓ]_~0P lo~;Ey7o=   6^V4u c o|kfQn8)  (F<-,i+V1g? 3( lrCZ}GZz-ɾ   ",i:{I#1cf}PuOzk  ȩɯwg? 3( l_i}Gݐ}  6~7}^~4T1c@>ZKvL?H]s\sW-   ^%{嚻w  n>=#{3/fn   z_󴤉npQُ: ƈ
 :gyAGʾ   `˔3ɭ` ШK:|==U}  o+e֒&b#2Q0@)wW!G&[   s5(-i2+wgc1aS_wBG6rٷ   l9J?gK7|60@)u4/l;;   `n>ے&ޗ>`L C~>#Ggo/   ScwDgnIU7g? ( <_>Hs]ETe-   snpQnIֲ]"J '5X}yF_UX   {ߒ&d? ( <7K?Hs^OoeZ   0֣Qsixُ6 ƀ
 Os_llpՑٷ   ,EkfQY\dơُ5 ƀ
 O}䯥l{o)   XP3"<.i2G c 'Z{FڇRD}K  zW%ߙH` P1P#EŲgFmw   (*ZK~>4޵}1`@woL?Hso'   Hջp&|.i+}q1`@mgjm{_eJ   DS~N4l7,b@?HP_to%   	cGkuI[G # Z>~b3|   FJ%o>o
 gMFן}  詪s| # Zߛ~Y}   ȪZDwIދa 8 j{mĠ}   H3kxُ/ F
 OrFڢ壷f:   0뷒d? q( *#@#mIξm   `lTcG5sُ. F
 *@#mnݓߝ}   pR^4 # Z^~6bE^}   X &( jzaFjl1   VQ3opY 8 j~^Fjɲ[   F?  P E^D[   &B~֗4  Z(6ijٷ	   LMbŮg~I
 MP eQnp)ٷ   LG%n( 41@Fi}{   d &( 2@(Vko   XպQ,Vg F/  P E#v1[   &^ i2@
 P4jٷ   LWHP hb@-ROa/   Q;ZKwNL@d@ jhdQ>|c-   S>HP hb@-J+ξ   `:>?4  Z(:   r#Z3ۥF )?  P E˟պٷ   L9P hb@-e7    xDgr3@
 PY;   0B7|6I  Z(ʪX[TϾ   dn )/  P EYmU   );v )'  P Eu>ٗ>   ,O@RN( 41@bQm|8   ʰCHAg@ jhtje   lˢ5(I
 MP eϾ  - ia3@
 PP+vjٗ<   (V=?sI
 MP ejpٗ;    &( 2@B9ٗ:   *:F&  P E޲]Z{O   l򑛣x${( 41@7Ͼ  9;o?g4  Z(GZDUf_   kX{7  P Eҝޝٗ8   0:"3I
 MP e   kU#~%sI
 MP e}k#   E?HP hb@-y3E+/m   `uO}g%  P Es]̾  yVmn˟9 &( 2@\Vz/k   `/]Y &( 2@\6ٗ4   Ph3GHP hb@-U?}9   lx9IHP hb@-Eݣj=}9   	:'#	Is
 MP ehpg/e    I;?47  Z(:FDUe_   @ޗ? &( 2@6d(52   UQ*$ms( 41@W5   F?  Z(ڊ_ke_   (>?m  Z(چ}   #fxǗ?m  Z(ښ:'^   oKBg@ jh[STkɾt  U~hl &( 2@іֿdye   33I[
 MP e-WGٗ-   0GkeHP hb@-mIۿ}   cw?ː  Z(:ǽ5r   H>/JLCҖe@ jhZCܜ}   c?אE  Z(ڜzC
   rC~>I
 MP eUϏ.R   ?ߐ  Z(jjpQٗ)   0:Ng6/  P EOUS    ۢ|hlYP hb@-=i3bK/Q   `Bt?!1  P EOV?ʾ<  	R7ZKvLCSg@ j%;F   06sIO
 MP ezC	   LjCZsg<  P E?Zbe_   ?$=y( 41@~d_   _NDR}( 41@c?1f_   _W 3@
 PpR%	   L1U/H,Dҏg@ jkuU}I   S韇HP hb@-{{.̾  i2DK?  Z(Twd_   |E$p( 41@Z3Euٗ"   0h?P hb@-uO}e   Lu'>"d@ jLy۳/C   `Ue{m$f3@
 P}	   ?'D( 41@3z;ٗ    @DUESy$  P ez}ٗ   :?I( 43@tV,{fTξ    ~H_ODP hb@-wǲ/=   3K韛HӞ
 MP e2}+v6   >韟HӜ
 MP e2}"   xRJDP hb@-XkTuٗ   SjQi &( 2@/;    n>-siZ3@
 P쯟f_r    ͪ*ڇ6i3@
 PE/7   6Si &( 2@ώ&r   |UC!si2@
 Pޅ˾    ?W-  P e+=3֣ٗ   +>g?_)  P e}_/3   6Wi &( 2@쯟    m؏EP hb@-ɮwٗ   6\ud,Ҵd@ jLpwjK   `n
EP hb@-ɭ{//   9a韷HӐ
 MP e2,//   3F?w&<  P e2|/-   9׿tU.Ҥg@ jLfȾ    \]Ŋ]?{&9  P eٗ   O響H
 MP e2yo?'   7d`I &( 2@ڇ|DUe_P    IDATV    {?&5  P e\}t% L.u|(:^û/:?7Co=՗ϕ{pT 5 `EH
 MP e29+w跳/) `TGg$;k%ˢwE?ooj/bŮ̒%>엢sۢ/}8_]mg} wߙy4  Z(Se_N (|vv80zݓ~-^{63}in+et ,/DP hb@-	iɎQmx(r ʰcwsOM98Z}&Y,AwE1̨}; ̣oDP hb@-ɨ{/% `l</_;1N+vΧ+z}96Go sdpkH
 MP e2\}) ۪Dٯ]d+f}_{ƤVz՗~u 0~!MJ( 41@97/# `+k9o^Hb+?+:'^w"f_" f\ud$e@ j[Ⱦ &쨡|X!{?7?7U{M <A'}^4)  Z(]q+\ ˣh-9mCoᛲ. Ʀo҄d@ jw+Ⱦ 4L_q`tɄW;| v+O&!  P e[? {1~O%(!{j=ٗ$ Ly4	  Z(ۦ ,r]Oc~skY5(G)84#ٗ* Ljh-!i3@
 PƷ򁫲/ |UߌWe/]d5&-!'+w_0{ {<  P e<kW/ h#7G%6]Cx,0\}Y_P hb@-lpٗ Lw?D4 0ڟ~i3@
 PƯb"K &B}>5xMO#~%7Qٷ  Lǥq &( 2@z$V6OGߌvvMo~&W1e 0Y(V ]/k( 41@ʘ5]Tk;l `lb{_FYt?T]$ٷ	 Lޅ3xi\3@
 PƫoϾd `Tu!>qisjҨko {Նd4  Z(S/ cwD=l{?'ogJ 0ֺui3@
 P_nc ITe :'3Z3ҶV\udD9Ⱦ `l1}.c( 41@;/ IUwC(xEZ&|!o7 ;#ߘ.-  P e|*%rRmx0z_(VMm[ Ҹe@ jG#ߔ} (=_h-1--x3{[ ð?vpi2@
 Pƣ5ξT  ݦ?n[K.Z1eߚ 0_](  P e+=3K ҔeijZ_ h-)-K( 41@=ϳ/ HQ>zktO~WdZ?jٷ- 4-I( 41@W~ T='V|^nl- #ji\2@
 PF'^QUٗ	 ,HPƹg6~7978d@ jvKe_" 0_yP+vMJRb\ud #e_
~GK
 MP e2,j=ٗ ̫mgGq+߻҄9Q V0Egi3@
 PFoɾ< `ޔ\#ߘbbpiٷ= I7K
 MP e2>: 9WF=xw4muO@D~ @rњ.,r( 41@ʈ3˾< `Te;!UJS\=|' w4  Z(Y?ʾ4 `Δ]_~k~4 @M_M>F8  P e4K ]DkɎVI?^{ Lrž?.F5  P e*V bϾ4 ` _^Ե?(9 wҨf@ j^& VuG?KJϊgd?> `AUVGkai3@
 PF/;, `/OJڊfEG	 ,ΉK#
 MP e2Z8f_ enl.mmqU
 ,mg{Q &( 2@z}% [ߡ!{D;/ 0ʡ'd@ jV}I _*ZK4{?'\y׿dY{WP hb@-ѩeU}I @j9NIܒcpُ WՆ &( 2@zS  w}97%-P3G ̫IJ#
 MP e2:^}9 _OoΔu~ mdF)  P e4*|`dU=KIu  &NUENJ
 MP e2K jxI?}j=hmSQ>z[;!z|(ڟd4*  Z(Qy7/ 1Nֲ]ߓFA?Q ٪𶳣wђ(V<LzP hb@-^w -`se#%nrO+ 1UocW_+i!{7q &( 2@ɯwe_ UGI_K| l؏oEvHi3@
 PsQe  DI7JU/g? Նcpө;wh-)](Mb( 41@Jnsx @owX[zc	Smx(DwFrw4-  Z(m mxZs{QV,v߹2qbx%ѿl(YMP hb@-܆}	 0W;%Ŋ]|[ُ5 F]9cp	_>Z}{L &( 2@ɫẌ~; `ZU3~Jy' #_F7GkN+IO
 MP eWwgV^tO}PdVzl`T~blrLt{{?'$i3@
 Pr`AI]ϋ|' m᷿b$M( 41@JR3E?~ q|r%ME~/rO> B9VN޹{>U:KvLHP hb@-G!G鵢JJ~2f?B嚻bpI҇,)"i2@
 Pr_4GԍO~;'i:kQf?	xU}A.ZŪ;$f@ jT>xui/H:FĠD׊ˣA=>dh,JOHP hb@-U`H:rd0Gnu'D=*%;$~( 41@=ϲ LɟRo$ǺgU`bUmg?U:ǽ5ZKwNKP hb@--gtu{/Y{UX87oQ=.ir2@
 P%;Fݐc`ٯHIғ5("/>Ͻ/_,4  Z([ӿ#`PN[{q#`(9םs|綤 &( 2@Y0z-IIV|^k~t6<Ξ=s;X[YP hb@-|9 jpQ9I\TuُPQu?U:WS>/LKR]( 41@Ϩ9 hx9ZCNqQ skt:2} ڇE\IڜP hb@-e@߈ֲ]s-u)+OM;!zl &( 2@Y5q0aMI\ơُUR=~Q,{f3T2  P eN	R6F_HIҜx~ُWRupѿ(yQR9  P eaj5 {$i+yaT~jt:2} ڇҟ  Z(SܿQ0ALI|>n{bp	;whg$B( 41@45 bxZ}M&̦rz|Xg$j( 41@x: LjݷX{M5~cnˣA_SS4IP hb@-} L^+ڇ6&Iҝ|/0(F~ؤ}FkfQ3L8  P e?f &@sKIBWʨ:g?QQQ>zk=>z]xCI &( 2@c`>&}&IYuO~OcHRmx0DwFg  Z(10ƪDY4IJlOe?yVu7pѿٯ=4  Z([ggUc~#}&I(.̕r#7{_F=5]F4
 MP e21 cw$JOz/$ U:N޹{F7GkNIғg@ jo FZw$R?xT=.Zӟ- &( 2@oUg]q/}$ihcxѿl({i3B  Z(W0gu{LFb3\sWO9gG`J}5]3A4  Z(W0w}9Z3c4u~KD9~d䪪(#ן7Fkg &( 2@ǃ0nh30I~jû/EKs;X{=.I &( 2@u ޅ3/I<-膱S6pѿhG,IP hb@-' {w~MDU|\w_s룵x{W4  Z(Sfh3kKƱ޹Qmx0/4:G9ZKwNG%I
 MP e2?- cdp.If𞋲ઍsf¯sEsGIDd@ jOWehUwWe$i+xETُt?VW_+i!{̎=Idf@ jCKwwwt<֊]T:gntRvq.Vg~$A$	D%Ⱦ$YM!BP1ݗ$Ͻ߽'=<|.y~g\%I{AW:LƠ_}ݶ?dY_c
 9( $L鯏~V ;ǥÞ~$ihf߼m9\w&KI3@  $׹=Dk-Iڛj|U5<;|WݿJgeH c@qN<vs5;(nIVgjusսت}UsՁn$i  P&[F?+ {7,IkCgwjmkCv* I2@  $8O
7K۪굢g/6|ꁪj$iR c@dkG?) ɯ	Y׹jq%UUwϷ$I  P&+IZ-ޯ<yW_ijusսت}UsՁ̢ϳ$I5f@
 I(O
@yܫ$-Z~OAlrջmMYH:un%I  P&pv[Pg*IZhn]?ZpOt>OIJ  P&W㘟~N 
<$-G`5}2PaU+{lϢ$I{J(  d2Zg59(X+o$-#0M_s)U܃ٙE;IP 1@  eru^ Jl3WG&a=6uuվ]}?c$E c@ e?%)?cO`2ܱuwUw*@gI= rP H2@\D?' ${'0l?]Xuo8j_f$IZ c@djO	@O?V./VIj|E~ww*[N'$I(  d2Z s$s@O_n[SuRN}]5{?$)
 9( $LΥF?% wT#^~$IjfQWSfw_XuZ\T5>.IF  P&O	@4FI\Ugb0lm]QuHZGW$/ rP H2@L'~J J3T͏%IJ׽Kw7U?W5]?Q&-%Id3@  $	U5E?% {I$}G`5l>}.5T'z:j$I~(  d2g@(Is׹oE1;Vﾰ\x9Љ~I
 9( $̿9 fj(IRVS-43UUcw*Uƿ$I*& rP H2@k~F 
ӹI4Z3ګ;౛WQ5{u5;O$I*7 rP H2@> dЫ+~8>IF˪p֪w9Ug!UUK_+IP 1@  eg /M+hv4_uw:W-ZkG4R$ c@<[U5G?# i$I-T%vm7[=xh&L$ c@jO@AOVOk,?`ȣn5غڊ%    IDATtb>ﯪ檟fg	3$I# rP H2@_yPI4W/	[w*jjv,$I  PW#XѷI4~Q5|扩ފwMZݪ-IP 1@  e~<?	(ɻ$iu.zCg?pl>હjvfQFI  P`۝O@!:W~$Ih_z`ۗmkCv*$I3 rP H2@G3TU yO&IDj[w*W3~]?$I$2@  $X@![7%IYT=?lm]{l%I
 9( $֚̽ߋ~> 
ѹwI4ٚܮ8,$Iuf@
 I(s@!I$Iޒ
 9( $̽M'D? l3&I$I4P 1@  e2 (@#o$I$I  Pp#@6&I$I4P 1@  e-}aU@3W3%I$I&
 9( $̭n]~$I$Id(  d2Zk~: 
$I$I&
 9( $̭ChAX$I$I$3@  $սcO@[$I$I  PVE? -G$I$M: rP H2@['t k~c=$I$i c@wD? zjv#I$I&
 9( $_cE? o
G$I$M# rP H2@ɯ~6 u7G$I$M# rP H2@o~6 ֽ%I$I4P 1@  e:l Dw:{$I$I42@  $p\h]H$Iie@
 I(svy@ޭo$I$I  Po-@΅E$I$M+ rP H2@3G? '&I$I4P 1@  eWUAeЯf$I$IR(  d2^~2 ~$I$If(  d2^_d }[$I$I43@  $j' P"I$I
 9( $W~2 >H$Iif@
 I(ݴ2 X[$I$I43@  $1|mYd 6~$I$Iv(  d2^~2 ~$I$Iv(  d2^'~2 6~$I$Iv(  d2^SO@>I$I4P 1@  e' Hk͛o$I$IS  PFq+@͏T-$I$i c@5Oymse8o$I$I  PF-@ӏ!I$I  PF~. ~$I$I# rP H2@~. n[~$I$I# rP H2@@K$I$Iud@
 I(c|mMs};$I$Iud@
 I(׿ H1I$ITG(  d2zn~. 4;$I$IR c@z  8wH$I:2@  $wD? z$I$IR] c@ʈ-yASdO
C$I$Ք
 9( $VcG? A|!I$ITW(  d2ZUF? Azw~$I$I+ rP H2@橿T tB$I$P 1@  eZkT ^4I$ITW(  d2ZsT $I$P 1@  e:; >/$I$Iue@
 I(չCO@֙~$I$I+ rP H2@O@i~$I$I+ rP H2@K-D? A~6I$ITW(  d2◮/T i;$I$IR] c@h$ 2wH$I2@  $?x]S	A$I$ՙ
 9( $`O@a$I$IR c@h~oS`ck$I$P 1@  ev ,<o~5I$ITg(  d2ZO@[o$I$Iuf@
 I(#4 $I$I5f@
 I(#tg H$I$I5f@
 I(^L sq$I$P 1@  %_c嫢	 ;K;$I$IR c@J	 ׆!I$I  P5Og Hg!I$I  P5Og HowH$I:3@  $|o~& n9%I$ITg(  d/L tb$I$P 1@  %_묷F? A_X~$I$I3 rP H2@>Ϣ	 ?~$I$I3 rP H2@>@c$I$Iuf@
 I(:g HwÊ;$I$IR c@JG? A-C$I$ՙ
 9( $|	 ($I
 9( $\@ƣ$I$Iuf@
 I(:S3ie$I$P 1@  %_E? A7~$I$I3 rP H2@׹G? A7~$I$I3 rP H2@׹g H$I$Iuf@
 I(W/~& n95I$ITg(  d{@ޭ$I$Iuf@
 I(L ݶ&I$ITg(  d{ݲg H3$I$Iuf@
 I(VD? Azw~$I$I3 rP H2@xt3wH$I:3@  $|?L wE$I$P 1@  %_c	 7!I$I  Pu* 2غ9I$ITg(  d{@;$I$Iuf@
 I(#|g $I$Iuf@
 I(#|g p$I$Iuf@
 I(#||Z3dV$I$P 1@  e/\L D$I$Iuf@
 I(7L Dٙ}o$I$Iue@
 I(7L j|EH$I2@  $|MD? G"I$ITW(  d{ݲg PW"I$I  Pu9< <5H$I2@  $|+g	@3~;I$ITW(  ds	@Oq-$I$P 1@  %_C	@~$I$I+ rP H2@Yg ;}$I$I+ rP H2@׹@Ε3H$I2@  $|M3[$I$IR] c@JyL |r-$I$P 1@  %_3L }SH$I2@  $|L wy-$I$P 1@  %_묷F? [7"I$I  PL ~[$I$IR] c@J'7 4lE$I$Օ
 9( $k~S3lv~H$I:2@  $|~# X~@=$I$P 1@  %__~& 5W~$I$I# rP H2@<@i~$I$I# rP H2@8ǣ	`uo	G$I$Ց
 9( $k|	`[=$I$P 1@  e  ֹ{$I$IR c@hU^S{ݲ[$I$IR c@h[ۣ
@[W"I$I  PFkckS[$I$IR c@h~oShus-$I$P 1@  e_bShH$I:2@  $?1 T3$I$I  PFG? {$I$IҴ3@  $QtT k3H$Iig@
 I(#~mMSu$I$I  PF{	O@oG$I$M; rP H2@ƣ
`~$I$Iv(  d2ZG? ~$I$Iv(  d2ZK~* 6~$I$Iv(  d2ZT }a=$I$i c@h?O@H$Iig@
 I(Z{PSlH$Iig@
 I(<ע
hA5x$I$I43@  $j ,&I$I4P 1@  e~* 
<7I$Iif@
 I(#x OqM$I$i c@U Xg!H$Iif@
 I(7HsaE=$I$i c@\ ~f=$I$i c@& D#I$I
 9( $^`~$I$If(  d2ͧG? :H$Iif@
 I(xTsP/I$I$M+ rP H2@~. 
\7I$Iie@
 I(׾]@Zk~$I$IV(  d2z\ ` 1&I$I4P 1@  eZgvsPuG$I$I
 9( $^_~. 
۲.&I$I4P 1@  e+2 (@7I$Iie@
 I(8%@	I$I$M+ rP H2@}jЏ~2 }$I$IS  PkO@Ǽ2&I$I4P 1@  eo~2 
:7I$Iid@
 I(տ' sI$I$M# rP H2@kt_7I$Iid@
 I(xtP-$I$I
 9( $WCziM$I$i c@x=8 (ɻo$I$I  Pƫ߉~2 JkU3$I$I  PƫyE? h$I$IҤ3@  $j,yPi~$I$It(  d2f=g s2.I$I4P 1@  eOF? \8&I$I4P 1@  eOl wۚ$I$IҤ3@  $ePCo$I$I  P3wlI$I$M: rP H2@@	jvwI$IIf@
 I(׹@!K$I$M2 rP H2@y~6 
ZwI$IIf@
 I(Z{@!:/.I$I4P 1@  e'BPK$I$M2 rP H2@ƲE? $I$I$3@  $94z '$I$I`(  d2Ot 3k}$I$IT(  d2^t G$I$I  P%3BNC]$I$iR c@nXt ٿK$I$M* rP H2@[t aE]$I$iR c@j;K$I$M* rP H2@[) (;$I$I  PVcO@)jvf$I$I$2@  $96z,6I$I4P 1@  ez  (Dk$I$I  P^뢟B/wI$IId@
 I("e]Pc$I$I  P^wÊ/K$I$M" rP H2@{| b]wI$IId@
 I(su[R;aM$I$7 rP H2@{͓~9 (HW&I$I
 9( $̽G? i}wo$I$I  P>~ ԹI$Iyf@
 I(kBtox]$I$i c@wEP7!.I$I4P 1@  e_n95	(G$I$I  PWE?! *6I$I4P 1@  e~' )6I$I4P 1@  e~5OymP9oM$I$' rP H2@_D?! ^46I$I4P 1@  eUg;>~$I$IO(  d2~F 
1x|K]$I$i> c@sq3P^=yI$If@
 I({ǣ4V*6I$I4P 1@  eu>@AZk~$I$Ik(  d2gg K66I$I4P 1@  e5Og O
M$I$5 rP H2@#^ 5I$If@
 I(iVSP3%I$I
 9( $L[4xIm$I$i. c@ʄy^SP)~$I$IK(  d2~J 
_&I$I
 9( $LE~J 
ݴ26I$I4P 1@  e2^SPW/M$I$% rP H2@L͏TSPGo$I$Is  P&aϫ~'9(pX5xq}$I$iP 1@  er~osPɯ	M$I$
 9( $L=G?' i$I$IҸ c@^ ݍG&I$I  P&WwG?' ߻>6I$I4n(  d2ZgvsP
M$I$
 9( $L1~N J2V(>I$I4N(  d2f^+I(H_O$I$
 9( $L;{Gm$I$iP 1@  e\PI$Iq2@  $xtP=&I$I  P&[s=I(o$I$Id@
 I(ߌ~R J2T_}$I$iP 1@  e5'0͓~9>I$I4j(  d2fUUg6Y(HO$I$
 9( $L[t7M$I$
 9( $Lڹ
@A_,6<m=    IDATI$I4j(  d2-~V 
2$I$IҨ c@kg0#_~$I$I% rP H2@|S~5Y(L7'I$IF  P&_㈗D?+ \$I$I( c@t>xP'&I$IF  PS>6I$I4J(  d27 dQ,
O$I$2@  $Թ}O@aGx}$I$)
 9( $L $I$IP 1@  e:5zEP~$I$Ie@
 I(k wI$I\(  d2 d$I$IR. rP H2@D?/ %w'I$I+ rP H2@^9y(LsՁI$I  PWk[´?'I$I  PW؟~^ 
ӽ$I$Ise@
 I(SWU EI$I  P`ۗ?~$I$IzP 1@  e_΍~b 
8$I$
 9( $L5~b 
:I$I
 9( $L9o~b 
YH}$I$e@
 I(ӭy/D?1 $I$Iw  PVՠ d-I$I
 9( $L7 תf{~}$I$)
 9( $LG?3 i$I$IR* rP H2@~k~f 
'I$IR c@kg0떅'I$IR c@k:0(LK$I$IP 1@  {~UO@AO?$I$IJd@
 I(4x|KSPƑ/O$I$}g(  dRӗ-뢟´V1>I$I c@J=u.`SP%~$I$IP 1@  ZgaSP?~$I$IP 1@  +_ f/'I$I3 rP H2@Eհ#(I].7FI$IP 1@   ~$I$Izv(  dRͧG?7 i/$I$I  PsE?7 n:&>I$IP 1@  ZgVsPW'I$I
 9( $WcˣOU3o$I$I  Pm8dP1?~$I$Iv(  dRo~r 
ZGI$Iog@
 I(ª'0ݫ'I$I
 9( $[ I$Iog@
 I(<W?~$I$Iv(  dRsK_XU~PƑ/Q$I$ 0 Po@aZ~$I$Iڙ
 9( $|@a:~$I$Iڙ
 9( $_E?; ~f}$I$ig(  dR f$I$IP 1@  GhPA]$I$  Pb6 yk$I$I(  dS´/xW}$I$  Pb^0OO$I$ c@JL fMI$I$ rP H2@y/F?= 6Þ~$I$I; rP H2@	jߍ~~ 
\u`$I$-P 1@  %/G?? i$I$iag@
 I(_䶬~~ 
ݴ2>I$Iv(  dWD?? ?pM}$I$-P 1@  %'7(̰t5;O$I$-P 1@  %Ɗ~~ 
ؿ	Q$I
 9( $6 0OI}$I$-P 1@  %}G (LwQI$Ip3@  $غG (L+$I$if@
 I(5 lS̢%I$IZ c@Jlc:# @+2FI$If(  d>հ#c @aڟ/7J$I 3@  $m PuG'I$I  P~aU zY}$I$-P 1@  % PaI$I03@  $'| 5%I$IZx c@J-޷z i%I$IZp c@JQ 0k>~$I$I/ rP H2@)Ӣ?
 %I$I2@  $2\ nO$I
 9( $Q_( PQQ$I
 9( $jЏ8 P֙)FI$IT(  dRN'8 PK$I$iae@
 I(۲. @aw_~$w{jz#Ng:޵uf8tյ9nu\]vSktYǝ&?$&J0"rT) 4*"F`AD~u}?{7|}/r-J$iIe@
 Y(4~ Ty$I$IZZ Pb@J=> @z~$I$IK' JP 2@qOOi %I$IZ: Pb@J]5?3I P+$I$id@
 Y(u5پ!I P/O$I
 %( d~ Tߟ~$I$IK# JP 2@$ P(I$I  PwSjg@eq$I$-P (1@  f, I$I42@ ,|cLw\~$I$IK# JP 2@s 6^Z\~@$I$u? JP 2@G] B(FI$I
 %( dWo)5@e%I$I~(  eRgn~ Tf|iI$IP (1@  &8/i P׆'I$IR3@ ,:}?F? j3c~$I$I  PlG? *?%I$Iv(  eRgcl< ho$I$ Pb@Jv< g'I$IR3@ ,zl[< l$I$Iv(  eRoMGG? jRoA7J$IP (1@  k'y P_~$I$I  P*=lD Q$If@
 Y(u77 |cI$IP (1@  &_H2'I$IRw3@ ,m|[6Mzǻߒ$I}
 %( d]E? *487J$IP (1@  yRJQ32/]$I$u2 JP 2@=_~& TfzI$IP (1@  &מL L$I$ Pb@J/~k3BU	Q$Ie@
 Y(?	 %I$I^(  e҂Li2~* Tf7J$IԹP (1@  ;{MS2o_~$I$I  PE? *OQ$Ine@
 Y(h# PQ$Ine@
 Y(ꋣ
 ^7J$IԭP (1@  %-?bs2V(I$IR2@ ,4Η 2>I$I
 %( dD? j3(I$IRw2@ ,4@|Q$I$u' JP 2@iOS~. Th?Q$Id@
 Y(-jR3|0 P5(I$IRg2@ ,v5'@efw_~$I$I  POLGi'(I$IR72@ ,v5O
xY$I$u# JP 2@iW0 PƷ(I$IR72@ ,l~l g(I$IR'2@ ,5g ~$I$I  P~6 Ԧފo$I$ Pb@J?2 PG~/FI$Iڟ
 %( d	l %FI$Iڟ
 %( dGwF? *3I$IP (1@  Mn0 Pfqg}$I$? JP 2@igϾ3 PI,FI$Iڝ
 %( dY6 PoQ$Ivg@
 Y(-=l| '(I$IR3@ ,6~$I$I  PڵLi'(I$IR{3@ ,6/ oo$I$ Pb@J{/ mzG$I$7 JP 2@iqO'@e&8?FI$IZ
 %( dWD?! *<pG}$I$7 JP 2@iw-~B Two$I$ Pb@J~~B Thpko$I$ Pb@JϢ _q|$I$3 JP 2@iCF?# *3I$IP (1@  Mo$PbZ\~@$I$/ JP 2@i/,~F To$I$} Pb@Jg@5FI$Iڗ
 %( dqHi |#7J$IԾP (1@  ~@ef;oO$Ie@
 Y(hrG?% j4wo$I$] Pb@J7mzGSBs^~$I$I  PQ1)P7J$IԮP (1@  #䔦@enQ$IVe@
 Y(iv	4o$I$= Pb@Jw_@k~=FI$Iړ
 %( dt49Pᆷ(I$IR{2@ ,?@v	Y7J$IԞP (1@  C-/5E?) *3k7J$IԚP (1@  [Mo l}J$I$# JP 2@V+~R ThpֿQ$Ivd@
 Y(jpE?) *4Q$Ivd@
 Y(ݪ'@&7(I$IR;2@ ,g@e	O$Ivd@
 Y(kz' (I$IR Pb@J}

?%I$I? JP 2@^~BN
Q$I3@ ,[qPJi2\~$I$Ig@
 Y(ls{6AZ\xb$I$՝
 %( dt> Po$I$P (1@  ?O
.y{$I$՝
 %( dtUBׇ(I$IR Pb@JG[J@ef;FI$I  PtǕ
NxV$I$՛
 %( dtU'E?/ *4Xd$I$՛
 %( dt 7J$ITo(  ez'ZB.Q$Iz3@ ,n<'@eO'(I$IR Pb@J'@8FI$I  P;PC$I$ՙ
 %( dtٯ~b Th%I$I3 JP 2@v̢ i=FI$I  P7E?3 *[uh$I$՗
 %( dtώ~f Thxo$I$P (1@  6U3BN
Q$I2@ ,? ݵ5FI$I  P@4E?5 j3R$I$U
 %( d,߹*PY~$I$Iue@
 Y(KO~j Tht~$I$Iue@
 Y(Ko~j Thz7J$ITW(  e4~nSBMﾴl;%I$I' JP 2@Y:5 P/Q$Iz2@ ,K ~Oo$I$P (1@  e4E?7 *4vm$I$Փ
 %( d,*P7J$ITO(  et<$f MӤqS$I:2@ ,[ {M$I$Ց
 %( d,&E?9 *4|E$I$Ց
 %( d,FuB;~$I$Iud@
 Y(K/~r h~$I$I Pb@k)M
))I$IRx(  eݵ5PѦw(I$IR|(  eo] Ю}$I$I Pb@kxћ j7FI$I3@ ,Wo ;%I$I  Pf@%I$I  Pf[7E?= *47J$I
 %( d,FG?= *4%I$I  PfuSFMz';%I$I  Pf㞱d7<uwJ$I
 %( d,f?VB/~$I$Iq Pb@mr@fw5FI$I2@ ,蒷G?? j4ފ$I$)& JP 2@YO?<PٯS$IP (1@  e	Ĕ&'@F$I$)$ JP 2@Y:	P_Q$IP (1@  ei7޺&	PbZ\80NI$I
 %( d,9	P采)I$I3@ ,]G?A *5߆)I$I3@ ,%޲Rӻ/PɍS$Ig@
 Y(޺)PfwJ$I4P (1@  Eˣ! ;%I$Io(  e9~ Tj?S$If@
 Y(<$~ Th;%I$Io(  e]~@~$I$I  P룟" kwJ$I4P (1@  E]@~$I$I  PG?E *5;%I$I_(  e-ҸߊS$Ie@
 Y(i~ T9wJ$I4P (1@  E?muMsR~$I$I  Pӆ99P5
S$Id@
 Y(i$I$i> Pb@~fqgFMz'<+NI$I}(  emzB*    IDAT'	@Q$I$P (1@  E?h'	@_>9NI$I}(  empΫ$ ;%I$I Pb@~CRjg	@fw"VI$Im(  eov߭J;%I$Iڷ Pb@~ɶs% _*NI$IR	Jjf@
 Y(F=YP][$I$:)i4ttl[f;e5?[K3@ ,|~ j:wo$I%SpQiuMؒtۗ+4 JP 2@'4D?M *58o$I%Qos?NV{]W Pb@r:iPV)I$Iݫ=_s捩Y+wjk(  e\S ș~wJ$IR[80O{Im::MKSj.}$gK3@ ,^	@f[qP$IԒ/=*pwoi(  e\4W*I$Iu[uh?26/*!2-ښ
 %( dz߳@w8!NI$Iii=_sEyT魟	P (1@  EMJ;;%I$i-t.~kl[f;4V;.kP (1@  Eh	@fc$IZɆx4ݱ%0쮫:4 JP 2@58ֽ&VI$I;VLizHm7]ۚ
 %( d<?FX+W*I$I]`i4<En	kP (1@  E}F?Q *5wJ$IR|oMmlYZ
'K3@ ,&΍~ j6eE*I$IoKG5icKJAZŝ{5 JP 2@/jtۣ( ѷJ$IZV3hB޼15*ښ
 %( d?'
@W~$IPoAi4ti#o7P (1@  ES) [%I$u)*ɵg)5e-  PTjvZ5;J$IjW?4޺&MwlIi2co3@ ,? {m$IR844}sj?Hiǒ
 %( d7E?S *6J$Iފ`i4ٶ.5}+ Pb@JV?/P*I$))ᆣ3l_YIމώ-  PTl~TU3ZK$iilo4WR?{ƿf@
 Y(z$MoTׇ*I$i_[uh?26/SaGpI~ژ
 %( d4ڼ<P5*I$io;i4ttl[th]_-ژ
 %( d48O5VI$I)*kv$Y3@ ,=z+Ii+ G[K$-_34ݱ%q?c4Xژ
 %( d葶n3~$Iig26/Sӻ/#3P (1@  Eɶs+ u'o$IfckHMGɶuis{c*?ﳍ Pb@iK\X=J$IK)ᆣx4纔fTf[
 %( d?
@|$IvU#tǖƽ菽H6f@
 Y(z-Ҹd蒿W$IjmٯLiz, #.-?߄6f@
 Y(z4:P鍟U$IjI>%FNml&#-_;o Pb@M[ N3QZ\$IRe-?O9,7-*(+K/-  Ph^'@|Ǻ$IzMG*.Ki܋5ȿyhc(  eGSo, ]{%I[yҹ]iz,H
W1 JP 2@ѣ?H[%I}Khim]ܞRD58?7-  Phg@x̓$IgHSe^irYio4DڄGe5?K-  Phm^lY$Ij_MߘWN[R-FmpΫژ
 %( dѶo_"^I$<8F+MovG_P (1@  ECRjfO:^I$_36ߦ7/HG\3>P (1@  E. 5MSg+I%SpQiu͞ҙ?B_sP (1@  Eu~ Tnx$IR:4F|N菁P]Oi3@ ,=@&_=#^I$uފ*MG{?Agvn3@ ,=|Qr͏W$Im=_s[dۺ4۹=?e?-  PZ~|\,I[Ɇx4ݱ%0tB0 JP 2@cmzeʍ6-^I$Voաi4ڼ7oLMmY6f@
 Y(z/?6PMW$IV<-FN.JCߏKJhc(  e?~ T>Y$Isi=_s[dۺ4۹=f_ Pb@k㞑RD?a *78wo$IҾyi4޺&MwlIi2y6f@
 Y(z<5	P~$IoU#hB޼15?f@ͯhc(  eӮ?R ~]W+IGSoAi4tm##O~A6f@
 Y(z<6UvmY$Iٖt&מf;̢?A{Iosϴ0 JP 2@hY$I?*ސ[פ-)M}{ Pb@WOg@&_=#fI%96?26/Sa"`zEm  Pxqy3r͏W$V}E}iz'S󓻣?Om  Px_qB3a͒$Iiai44۹=fqЮqZf@
 Y(z{m3Fu͒$I-l~7vM_`}+)MmX<IZ
 %( d;YrI͒$I[uh?26/Sӻ/cV,wZ[3@ ,퍚n~ nyr͒$I;i4ttl[t q/\[3@ ,&8/) fItI{ +M}-  P7}o2 -0ju͒$I*'-)E%y߅m  P7~xSf?)fI_o!ip+hB޼15?v ~lk(  eW Jz$IcwS`i4ٶ.vnxS̶f@
 Y([#`Y$?4pTo]f\lq;+hK3@ ,[hM,I4Xd_yt	خcѿWۚ
 %( dho56-c~$IZVg26/SO	 {׶5 JP 2@ު9|$IKckHMGɶuis{JM `rIߖf@
 Y(ڛ5?+I-Y$u)ᆣx=_3EpQf@
 Y(ڛMn0I{oY$uުC`{JRO=@&P (1@  E{g6I%IR<xW\4ycjwFtjM]{ Pb@f3;IOyݒ$L^FNml&S4 JP 2@^'4F?k Z`r$I?ŻJ_l}Zm[
 %( dho7kkOvwKz1Z;Li}:geۚ
 %( dho7g@K>%IҾ4X{D]4ycj7,	Mm  PD?k Zb$I{SѦdۺ4۹=> KZ
 %( dho;+ $I)ᆣx4ݱ%0]hi(  e}ߊ~ Do-IIU#h?}Fg2v5 JP 2@Ѿhs6 -1;$I?_o`{J熋Rн'G Pb@EË"i;~$IK|oMmlv_+
Ǟ
 %( dh_#2Co$i[4pTo];4F_C ]_}sښ
 %( dhl~ 7.IR>} c~{ښ
 %( dh_5\>nI`'yMvRѷ Pb@UϿ;yԬ.IRO {
nO[3@ ,~yEgn$u?o9i~tgis(  e}{~)(+N]N79}w Pb@e~%{o[n7E; dP (1@  EU8 -[%In->u Oߝ6g@
 Y(ڗ]Ev}5B$uugE: dN3@ ,z'>;".]LX:&_=#97 P[3-[yH$uG_: d|	w Pb@umF?s Zd~$Il s2;m  P~/9 -2%IfM37%9 JP 2@ѾE?s Z=yr$u4F9 dpߞg@
 Y(-/5: -Kv~%0G3^~{ڜ
 %( dhMoLSE&מ~$Iݪʿ>o QosoO3@ ,ͣe5"CeO_4E7 樷P (1@  E?Kԝ{Ci`^&P (1@  Es=th'/IRg}oO sP (1@  EjvW; -2o$;64̾-= JP 2@Ѽ7$M} mߝg@
 Y(W}seF+~Ig9|P (1@  E9uu$un>k +ߝg@
 Y(gwD?y ڤiR}$~I_3|00'w Pb@~ hKz+} %~{ڞ
 %( dh6Uew^~$I} o=m  P486,N|v$ٯf ࣯=m  P4ז=!5= -O
a6G2 != JP 2@Ѽg@LoB$񗎋>e Q︧ߞg@
 Y(wϾ36i&Ijgo} q?t! JP 2@Ѽg@/&IjgF1 dvmw Pb@S3qe\$G1 dӅP (1@  EM@Lǩw3o$e䔚&0'o^{:
 %( d(h4IU} UoO2@ ,E_;OrI$D/ h~{
 %( d('4E? f2L1IRkm::z0GË~{
 %( d(훣? -4&IjOkN>] /=]  PhB~&Iړ;?ᷧ Pb@|? m4	
cv<xO`}JB(  eyrJA  -4_1IRVRD- ?~{
 %( d(-? /0IROi`f;ߞd@
 Y(l? Q3K;&I?I`߾4t% JP 2@Qds^# @K6#In|
9|ӕP (1@  E}jJq -4;&I鍟>W oOW2@ ,E75? QӤ1IR5} CJ(  e[c @K>_$z+=V`ӕP (1@  Ec @K;-Iꬿw s_+ Pb@<84GrX-$׮a `	ix̓OW2@ ,{_Q Ɨ~$I5C'
9j't) JP 2@QQ ݙ~$Iu5U'
9{?t) JP 2@Q] -6X{D-$UԲR3Iy`&}P(  e 3o$' 40g/?]  PTK7F8 RMx̓o$'ѧ	9~?]  PTKkNq ņ>IhuMY`ӥP (1@  E4 hM2IR} ߟ.e@
 Y(ުC h8f=$p`J~U`fݿoP2@ ,oGH boe40g͏vߟe@
 Y(u fw]~$I#L<t- JP 2@QM7%G{&IkO swZ(  ek? c$)n>E hBZ(  ej=k~	L4z'<tb    IDAT+>E pQ7k Pb@jkrY? W3I^O g,u- JP 2@Qm/zs -7$i~ ԵP (1@  E;cx|;7M4f} {O3@ ,l? ~$IfM"u1 JP 2@Q Znv7$i~}z 0vmb(  e :o4I|_* `wߠ.f@
 Y(qHEx rk>~$IivW v	X7 Pb@jmvע< hf_i}[g,Q_~
 %( d[@/zsM$v`	P3@ ,`k< _i}dۺs@n
A]  P;3E%41Kq-kjM9)h]4:ҤW)
J*#0ϞApq==𹟹~QC˖ |}D h
$IcjfA*z( @~PK3@
 P{/>" }4Ix~D_3 ^[=P c@%5EK -PL]~I' H
ښ
 uP d&;GqZY~ף t{ P J(jt</a7 Wk9-[CJ0 Hwqe@ *w\}L h~I<j Hn=P c@%5>& 5Iܕrz@Cm :( T2@Qc@K)[M4MJN@E- :( T2@QY8cU`.H&Iz'~@:.js( 1@&э'G ZxԙY~I6D_)  P J(_@yg&Iڌm(e:KZ
 uP dI(Go;+n$mz} wg@ *hRZq DY~?~I65E$  P J(W}\ h7$IS}/ Q3@
 P4)N@R$i^  >j{( 1@&l)#@Mq L?~=  P ETq7 -R>yw,"~$mXSv ":30Nj{( 1@&EK -;}$io I4d@ *h#@w]~I6ul #i :( T2@DxT>6 L7qg-)E@~'MC( 1@& -j&Iz_5 zG5NP c@%MZ>6 Mg~6$E[rѷ -)^P c@%MZ~> B$IN|_5@O~'MK( 1@&; m3lqg:' F7~'MK( 1@&ՇD Zhx;N^> `p޿KӒ
 uP dIwG ZIٲs4{iZ2@
 P4eKK)D Zhp'9IҿhT>` @eʖ7MI( 1@& -Ty uvy^='IzN' Q<*^P c@%Mj?}| hY	$IIWF_	 4ǇKӔ
 uP dI_>> Tw$Ms#}  )  P Eww$MqgF_ 4H7MӔ
 uP dInt1G6[u4u"* )<ul~?MS( 1@&)>B X$i]sX @~7M[( 1@&lN ơ\}"I\)W  2i2@
 P4}#b/M]'I%я~ fp?OӖ
 uP dIo] -V>ywNl쭎~0C~GM[( 1@&a} hʏw4/ZiAx@( 1@&E[2^QΣ)[]'I-.[S*k 4Lw4f@ *ubQ.$<Q@?P c@%} hr6e~IRVH*OE?h1  P Em([cJ(8r$/^=_~OMc( 1@R~%	S<IjSn?꧟ P|{jZ3@
 PԖ280F~IR^yP}{jZ3@
 PԖRq`E{OPw_H)F?h~WMk( 1@TG
){y,$io;;@u|M]5 P J(jSë>} q'I\G?h&um~_Mk( 1@Ts} w.$i"Y~`s) :( T2@QuY`Jd'IX+@.T}5 P J(j[mgE+ ǂg8I*[]*>zG-ΚP c@%} "k$i^G7 MSgɶw4g@ *me{,>Z LL~I$=)'7 WU5 P J(jc#7F- HMxOTe#	0|{k3@
 PƆ>Z L9~IRX	[Ӟ
 uP d6;G)SJٞ/%{>{N@L/=  P Elfa*>} 2>҆߁[N~D0!Z{K( 3@躣 Swܻ@IjRh`/
 P d;)T>yOʖn~JRVO&`} z( T2@Qku#^up=(I`yʖ~@= *r`e$E_G?0W_~( 1@\E1 T)[P"TD?0ËWa~( 1@\GR*F)5bP潙)я` &Pwc :( T2@Q$0"P~0Fu{L :( T2@Qc++eK%i>A	uQ=d@ *ucp\}(I.[ 63w~
 uP dix?CI[3SG- {3G( 1@+ SNޯ%i.\`xL? :( T2@4=ע KRg$eߑRG?b`
 uP dhfa*z(m/Ue{<cяV &Oizz( 1@ՇF7 )~Z@(I.MWF?UhAP c@%MK} `Vy4e{x(Î4sяS Z\~i P J(oG f}cn
%i\81
@K="^33@
 P4M[ 4=FIIJe%'aݦgf@ *h# ?P>KzG%Q?	@[Ô->~33@
 P4UTD; a7u~])I5et*;ߍ~j"]_T
 uP dikt |s)I+[S*[e_;N P J('?3w_:'%-6^R=P c@%M]>?A'3;:Ss P{N :( T2@4rzJs?~OJlJgF?hՇuZo( 1@,@JIS4IOD Zw;7  P EXtF ARҔ6 9,I@o3w֛
 uP di- UV	/%M_K~rwzP c@%Mk?} YOܕ=~<Δ4%,0>`^xg :( T2@Ѵ-aG@ޜ&i'W`JtOϚ
 uP di.# NMI-mіiu L;>f@ *hG 6H~婳dSRZurZ#)2tO P J(~4b}`䷝5OI-iɶ)G Sw@f@ *ho?/WL]~Je;d% OGRgfa=P c@%M{?}`"i~E*1Q]}h= :( T2@ѴoQ?(FP$mJCߘʵG? Rc'.Ԇe@ *HIgDE h~Sv] Lڟ]'(  P EzNG 6I~)[TRhJe`yB} :( T2@:KMiЉ> I{.ISIkіit!я) HQ :( T2@S# l⁫S|TRsV(w]x_MV( 1@'aqR<rc;UR|~=~,3Fm\( 1@TVGI ,SAW%Sя# 2~e@ *H?ht碏$ ld{U-.n<9 OW䳿.e@ *H?w{$ ̍Q?O`*i~x' <C~6>  P EO-*% ̍Hs)~4UJn *R
 uP d"=5GK SMw-[c}G _Yl3 P J(c	 snti6worя xV]_3i P J(hT}8hzV4-6>$~ @?wj2@
 PgW @KC~Jz*['8  P Ezf݃5hzo%m`JTO `mgߡP c@%ћ' ;W[\
DQmz( 1@TOFO RK]IO/[S]sXJe 7l6=  P E.'s Bԃ{o߽:3RG lMߩڬP c@%iw^}D`~4ʿWֺ._4 ?Um^( 1@(*"u}e,MSٲ{ B_:n~j2@
 Pa}L`^RַxٳV}$]L :( T2@э'GS :'e{$.Ẑ?xc swZmv( 1@O10e;}Ԗ)^}`,wSgі6?  P Eiі Gg+^/KZ_JG jxw&  P EoxG SMw4)et]wtJE}`zGfݫ :( T2@
 Q<x]L]sXJ((ԙY~kn2@
 Px
 Qitq~-Cuٳ' 0m{Xs
 uP d"mX>  OWvMv;)_uNe^~k2@
 Pk݇ _zG-浙wGA ~^9 :( T2@6DY hKS8˖ T<rcFYs
 uP d"mx?}d`"w\6?G N]	5 P J(FxTfE[ eF726:F xUךP c@%i^ɒʃRO҆-)V~,N	F{[s
 uP d"m\_}l`2Eo=3u\li'70>1 xţK( 1@^}t`K_}K^ʵD ({\ :( T2@6Y> 
wʏή5}b뢏 Lb=^~k< P J(Ɨ-1a7@kcixђ{^-W)_r? .] :( T2@6ѷN> >e{.%ۆ/uOgƗ
 uP d"mZ}|ޓix{}MV?~<^6;j Vn,:2@
 PMlfa*;T(1PYr\T<x] zKv5P c@%i\(t)ι'P\n;,n8.k7 GYlƛ
 uP d"mzٞ/Mȣ1 LHŃצSwsܢ-S^ݯs\g@ *HW~ Xkz(6fIMmg4D+ z'7	{( 1@yO~1 ~H]it꟦lyAЮO#ߚ|joV ?\}o,"{( 1@-2O=}gQ>qg]sX/ROA)m;S~ϥ)  5_t!4? P J(7 lLJ+/D˖nzG]l*[o ,7E P J(<8 G71;m)[C/&lޱJK}T<v[Je LNs/  P EΊ> *'州__' uxu?s4E[lNc?R~쭎 ID
 uP d"M/8 Vx:'/';:</#sY|=赩wO1/7D'\  oIDAT川hI  3 'P c@%iZߔ WCg૟N?zǿ'u~]ɔ->+KMٞ/M_zǼ3ip?%{Ǧ;ћS9X @Bwk( 1@4w.T &A1JeٿM\<xm`n:5=2l^48f~m_]ƺuWĒuw|j `)[c7o( 1@4we   躣ÿh3@
 Pm:   h!֢[( 0@4~G   l=gQL( 1@4,Hc6   fY
 uP d"}s?}   6Yݩho, :( T2@l)   I+?}Eq P J(xp\   heouʖnmEߵP a@%i<u~]   hP c@%i|]}   6\l
P c@%i|O`   `N	P c@%i-2k>    {دOQx( 1@4|*   *:;
 uP d"lŋR:   (jF( 1@4F}   kݯ,*
 uP d"g%   +;
 uP d"OGw   g(kRlo'jN( 1@4??G   __D :( T2@E[򉻢<   sw5*  P Ek   +^e@ *HW|ǔc   R>Lޯ^e@ *HC=   @]wTw53  P Eߺ:>   4+ÿ P J(:'   SltөGP c@%i   L>f@ *H1_}  )'FQ3@
 P'    Sw[¿ P J(RPHG?   )Ro"j|( 1@ଏD?   )Q3@
 Pv}~*Ǣ   (.ufQ3@
 P.~    Sw{¿h22@
 Pز;4D?
   +O?g@ *H<(Q    X :( T2@Q    h¿}h2@
 Pf4   BkwMV( 1@Ԍ>q    L~<4y P J(RsZ#   hޑC
 uP d"5ޱ~$    -oP c@%Y\X    Z{诅df@ *Hͪw{   o=#&7  P EjX3Rя   `Re~Wqhb3@
 PG?   	n<mC
 uP d"5x   0i<uxuMt( 1@i   0k :( T2@ڢ-RتG   0)ݔoP c@%OP#   ËP;2@
 PxT>qWc   hݔ->[Z
 uP d"5    npG¿a= P J('~T    U>qg,:Z
 uP d"5    ?
vve@ *H.KSF?.   )2ufP2@
 Phpǣ   @oj_( 1@4A?eя   ![N^Vf@ *H~d    MP{¿U P J(xT>qgc   6jm( 1@4YO   I/Ff@ *H֢-RoG?:    s?}B :( T2@&~t    }'uvyn	;  P Ef   <j}( 1@4   0[ :( T2@&+!   |υtd@ *H[ߊ~    `xP c@%i01   Q->'  P E캇!~    cte@ *H_~я   `H4] P J(=)E   Ke>/  P EjG~    sht4 P J(R;zYJn#   eɔsMg( 1@Ԟ~    s߅gf@ *H)[]*>X   6Cթ30;7  P EjW>X   6U1JP c@%e-2h   6=-h3@
 P;-   F*Wߛ%/  P J(R;0   l	  :( T2@Y7Tя   `nbg@ *Hm1   @T|iwK3@޲}~*Q?1   <ʏCss g@?B#i|/+1   G൩h.@ P+_h$l̾   ~XY@{/> 4
 \68矢5   ^7⁫ g@WHsL#7F?n   W>ywʖn@x#@ P);/4_wF?n   u2~Gi}ǣO	 g@
4?n9-   Soxhّ < *NIRRt;   0'wv>& L  *hKkp   L9ÿHVWE &
 _5F<6|G   L5j0@_j$o    S\}_ʖnM@kpG &
 FR#i˿sn   F-@ڐ}\  ( Tʿw{K/A   zk mhN>2 L  30F7l'   Z-{a7 iC+> 0P XΞ/4ڇA   Z/mpLiԋ>6 L  ֫{oǿH
_F?   F/mL^}l ( WOH
jfA$1   ;w6# 0!P XǅH{TE   EzG%}_؆>= L +/7b^O   Zaď~ϗ6  [H
lɶ|   LRw6MbLiЉ>B L U7ſH
wܻE   0F=M{O  gʿHotөя#   H3!^~<0AP xVo#)ld#	   &Jje,6_>F L U=~KH  Qv,}^o1@Vvk_v$70^H  ;f;m	c@yّԌRJ0   6wxis^gQ` Pkt/;ˣK   XcRgɶV<rcq` P/β_x$5]IG?   yawwi3sѧ		dIͩw;K   8s?.ED' &
 dti/=G?   1N\T<zs` aY]~:  @r)[S4u|M`B z_IͪʟD?    V>L~#]} P( lѭgHj^x  0K4g-:k>V L( 6\>J=~<%HRVȇ	   Rje,7>V L0 6JOIj^x  yU/eDKsY~G	fF)'!降n|#
   G1J..e}_RYD. &
 {_$5lŏrя(   y.u>Z L8 6趕/CY  W:3,m甆3@`drKf6	я(   r)[woi^$x( luǄIjfRCя)   [ uS{4eK^@ ia#IͬwE?   `Nmi.T%P d>r$n8.1   sbt8ʖG0@`{~
-{a*W  R<t}M{4->b 
 ex!/I[sRYF?   `l_K(mT>f 
 'lY܆W}6I   S	#O -cf~/KܮۤћU   Q~"ZS݃_RYD3 Z 9=-/M[W4F?   `nfK -d.'Imcя*   U<rc,6=ZW/E1P 3:IRvmgE?   `+ߡ1xQ*;F5 Z 9StK/
ܲ_#   Twܻߝq6։'3@`NybKfTя+   x'Yg} h9 \s	W  0weiewJ -g+Vߟ:Kvy^*1q   )rZQ`
 0O	*a7q  +;e,} ( M?g}$Q  *kRWK㬻/4̢ S )kS+_$5)   ӦSߋ/Xx1@`Lkm%eh*z(q  h4f-E5 
 c7.Iw[S*Fя+   #߃q7F5 
 w_tIjv-Q  @w\:Y) o( ̏|9KRY[N~Z  Rcl>n L) M/a[lT>qg
  )g~6Wg?ʵG7 
 *YC˘fM4E?   hQ/]iewJw} r( ̻])gm
  6(?8˖n>m `@፧3_$5~T  0+?~+%ۦK 2@ O/Iv&  `B/3VgNs  B=*~QغTD?   0?:~On?/ npgP$~L  0A;/Ҹʖ} P h5u<S   L⑛RlXi\eد,P h7OLkm'-  YMٞ?+>j ^( 4gl2'ye{,GS   4P}"uxU4zGms h2 '/uW74G?   h|zG#UWjs h: xoHzf/M#
  (JciVix~ѧ 6
 UVѓԸ8   @L/wTie{D,F1@ي":~zAKh˔'   ~"TCߞʵD1 h( Lm+Sgَ/S|T<~{	   ËJsųZ
 &
 x/SWT	  y4bQiT<t}bdGi]ڙ-_
%5	M,N   ̃ǤΌ_լh48) 6
 )杖DIhpK   /wPix޽XY'KEt[T-Jt6- jMf/8dEDQ2\8f^Fǔss	6Es7s~ 
( L^,jE5   'y_oNK?JcP6ܺ$h>Z 0, 0펬䃣͛ű$   Xq?';6璨<ͳS+ P hE􃤤degDt2  )[W'7V] Z ZJDm(uLM>TJJSuZ  Q*FLi4UgFo}  ZR޿/*>	0dJ>6L}  0B@_dnL>_J#|bVOH>pJտ~=  "[tSRIUE ڒ B~t"7H婯   |xFyRVEmQ؝@RP h+龨%JƿK#yM  PdKoM?KJXeٝ1ݻ, `TyAߜ|P4Ϳ"c;R_;   晃-F뢶(nK}l `±@{+h%k^RXIpK}   /g{&tk]>2 0aY@aT>~4Js$l%mfe U  ??3LJ̨oz3C["F  8'zwGeތ"PՏhTS_1   x&RSo==,> 0)Y@SDcƨmx5ew%Z3"  ֚gD3ڰyӇMj_K#?9^N}$ %X@a*ʧڨΎʊ9=,iX{_K}   湣Qy䳡Z"{tՕD碾h\o}N Ƌ "˨}Ϟ(/*-nJ}{   O㻤ubw4(J'KhwLQ    IENDB`PNG

   IHDR       .7   	pHYs    {Rk    IDATxyu}C(ATb	d)23*,30Sq&[tC7;aQDAeQFhVYʶlyoRtyysx9     	     0    @     :          0    @     :          0    @     :          0    @     :          0    @     :          0    @     :          0    @     :          0    @     :          0    @     :          0    @     :          0    @     :          0    @     :          0    @     :          0    @     :          0    @     :          0    @     :          0    @     :          0    @     :          0    @     :          0    @     :          0    @     :          0    @     :          0    @     :          0    @     :          0    @     :          0    @     :          0    @     :          0    @     :          0    @     :          0    @     :          0    @     :          0    @     :          0    @     :          0    @     :          0    @     :          0    @     :          0    @     :          0    @     :          0    @     :          0    @     :          0    @     :          0    @     :          0    @     :          0    @     :          0    @     :          0    @     :          0    @     :          0    @     :          0    @     :          0    @     :          0    @     :          0    @     :          0    @     :          0    @     :          0    @     :          0    @     :          0    @     :          0    @     :          0    @     :          0    @     :          0    @     :          0    @     :          0    @     :          0    @     :          0    @     :          0    @     :          0    @     :          0    @     :          0    @     :          0    @     :          0    @     :          0    @     :          0    @     :          0    @     :          0    @     :          0    @     :          0    @     :          0    @     :          0    @     :          0    @     :          0    @     :          0    @     :          0    @     :          0    @     :          0    @     :          0    @     :          0    @     :          0    @     :          0    @     :          0    @     :          0    @     :          0    @     :          0    @     :          0    @     :          0    @     :          0    @     :          0    @     :          0    @     :          0    @     :          0    @     :          0    @     :          0    @     :          0    @     :          0    @     :          0    @     :          0    @     :          0    @     :          0    @     :          0    @     :          0    @     :          0    @     :          0    @     :          0    @     :          0    @     :          0    @     :          0    @     :          0    @     :          0    @     :          0    @     :          0    @     :          0    @R5sGSy{RXڒݲ%io1  ?Jjvk_;&g6ʙrf?P[S_MBrr   Sw%M^m/hۜ8sPwOWU5l*Э: l  `*6\(i[h^F;s56WKsߗ--bs߆   k8Lݫ<Pr>SSܯcǀ>SR5Gܷ#   3#(i:uVИi{Eq\ya<Toٔ  A^_%Mq˖>;׆NVS7+u_ *}I?>  *u/Hs$kIݍGoi3z]RMڧ={2
  ~~|G:&{@S3Sy۲Òƭa%]
  z~TGd&dUw4Ǽ!?$ik4,S  ͈ϓTcߘz4CdU/Tp1_JsV   f_ι\)IEqoQsTiL̀^e*OP1sRoW   hۙg;R]TG61M-R$Ά   fH)IK`C;םgS/Af}   gHq?)IKrԽoS:9WlLű 5/q   fRϝT򄷦jR5j@˭sşfKMNi}  @gNC?%]IK6II_Z?h!u/9  <|crC%ؓ=,Uޘb^?RC^s  )2tԜ-m}<g@ս#)U  EV}l(Qg'NllR?DI  [ƵϦT̢r4o@wR?V  Hk?*IlZ$|dJuXLs   f{e?JR1V;ϥq26o5IjZH澅  '`VϬT̲r;R4.b@|*|UԴ:>h<   VuR_~vb{X<4JHso羅  c>ϰT̲r!{7X9o_   bT{m$m+Ru9n\ 5Y:u  hoWf?JR1V<uxO4lo_  <1~b-78:5#.5  +~b.-[w_8zDK}Ogv  `B>WϹT̥K's@|B'Xj`o}   ̋aN$sb??YzkJ\To}p1nS   Igbs$s\}P<ydզ
ikIw.-
  [Se?JR1?<X_OődJkՁiy{  @n8k"9XξMu{G3sO7dƵ4xuk  ߹m\Òt)U^ʏOԸV<ظ %   Ju數X$XξW%Iײ}RuqK  noZl,IKв}R˚1n>1&5'   ҽ%C^=z#(r?YR]7y+  T>=ɒT̡r;F/>zޞ~2$5ep8_"   gRy%Cݫb<)#5΅^o	  3~nb.3wV_L_-   ,I,+y}ǀ^oۜ#_ITӰ   Pz_ghI*PSe2&U4|y  `A~bU_w@OԤʣ_-  2LS>ZYVwX{;Ob͏eƴ4x潺a   R'%i~蝋>Kiip{u  @NnJŊW?cKYrOݱzԠ2   EuؒT̲9z]>Jz_9ߠ   0nzgmI*fYu3o;#R39pN7'   J]3$}Rz;85Ԅ:ZJߔ   0ŖTwX$7YՀRjB?gg}C  @S߹-+~b+׽.^0z]|/GAJ^ykRm\{   @T_IFջлNV'n{   h<.IKh@w~7^Icݲ}RO{   hڧ+\Y{qڽy   5X*~u${PyRT4wwC?(i   `6_f?KRl~-'e089S   4ZT馷z]f0Ҹ>i>Oo3   ul`${;݀>g4|[m|   7g?KRWߟAHcي   3wbՁtוNWm@=eK?in?c!_   Ĩ ]Կ낹.KXo   &N?~%9~*ֽ>KcyC   	SuRó%U˖zЫҘ>gҰ}!V   ĩ=e?KR8sghiܾP}~   &V%E;C_46-7}   ֽ%i.>l@&KcT}   LaoQs%q>EǺb   P?sw*V/Iŋ\=:^bq}ڿH_.[   N~旤E|Ǜ>x*CѯN,   K>/IŋW~R,a17   Tvv $i?ֿaKO)   RX;$߯sĀ+hi   x7}G>z_iR   L0u.pM@W?}g<nX\k<}"[   jbK*yCm@T}x@o_eKksG    RJG$M}+$:k~qR_9*   zm@ڧ`C/LQ}   Y]*V i[_Jzua"W4,|k    S웁nWd(iQ[#{    пnk^8w>/JZ̪;^    ؕ0u6|0v izre(i^9    1|TuhAR+M~ؚ@F}Qb>_Tu	    v;s~ZԪ}"IQ|    0޺~=ARkjGo~AbT{Y_   ;Ϧ7e$r~:߹!I]oY   s3xT,7 5=-[R]^Z/}|9   4Xڏe$+;K    IDATO^ZerA޷s   FMSϾ3HjMMMV~1BU}ӹ   XARk*赧>/FZ|9   LW˾7HjMEGnޙb  ֩sίd$&G/;7gi>+|U>W:    mSDW}kNX#g]r.   P֓ZS2uh1p   `1>f!$MÀ/Fޚr
   AobIkMX#u_'n   XD&ό^gZŲ}_oZw6   Aj컄cp19WG0  Soٔg'$&*&r폧O]   dʚDe@D4tu   @nuڧ3N!ٻhDpEvc`̤Lڴm3m4Fӱ;ю5EU1HQS12a y:gu	Ps^Ywo
:<oϳ$I$IzOޞj^W Y%)~>ѷY$I$P7 :5w{,I$IFU.|(~ R)ϱ$I$IzOLy@VjtJ~omGbI$I4µ.PntJ'卩,I$IFN3-JˀNtn><J$I}T3+| R2S*>}w%I$IRjWw{*>}s%I$IR*RhmJǀNe$I$Izun9"| 1S
͓?}g%I$IR+XSdb@gKU+I$IA=TEda@gu:=J$IԺdvda@g5Or]$I$IUL<茬|w|Y$I$IRmάF4gV{*I$I*Z33g}-J$I
W}*@l9wB$I$Is;4:#{YS$I$CE/51|e@g4Ob$I$IcTڼ7 ItFFxTEMI$I4f.v.d#ɀyJ$I$IX;OFl	>}*%I$I׹}FpnoMǢ$I$I,|'b@'\֣$I$IR=2n 0|">J$I$kF8JUGEI$I+Rw`$	Ӿz(I$I^Ml$	Q?Ru$I$I g@g,%J$I$MZSmάH̸E7J$I$j͓? Y(:3Rjף$I$IҫV~,廼1|O0tfΜY%ѷO$I$ik_0~SR:3yWo$I$IkJU,/.O$I$Ik{
03#:+u$I$ISq' qt]TwN$I$i7m ٌ23nzO}$I$I/ 3ʀδj]&I$I4/&|oc@g{TF6I$Iվrqd3ƀδuzM$I$InFfi8L$I$iZv\d3-2?}$I$IH~3~t33tv>c$I$IZǗo0@6U{$I$Iz> ٴ23T~q$I$Izޛj6cl$I$IҌ:M:1w{%I$I4gR M:C:J$I$)廅o303|֩ȟU$I$I1)?LI$I$ֹȆ΀@vH׉Q$I$IT?7· *:>pIy$I$I_ PЙ񟉾K$I$I#Uc7 :S3w{$I$I4R1̊n4tu7$I$IH8,MXT-$I$IzO l fwC$I$I#]υo8@60:I)j7H$I$i=Tyd1tnY}$I$IJQ󌯄o9`l~R}{$I$IJQT[edSf@gu H$I$ֹ_dSf@g4{#I$IT3)MMW7gV=~s$I$I*e i*輪}g$I$IJ[x!	x53nzO}g$I$IJ];^+:y_GI$Iת|v[&t&7oT<@y$I$IDk=@z-Lu7$I$IRuRυo>@l؂R"I$IT:7 ic٠E߉'$I$IիN^	~c@g=noIE}U9$I$IdlYO]$I$IRu4S߀UY/DI$IJ׾v^u/]}?$I$I_%߂w?}>$I$IƢ{A@輬bnݐ$I$Iy#|Iw}s*ꫢφ$I$IXվrq.d2׺B$I$ijRhm6ȀNTԞ>$I$IcY]! mԺ;wB$I$il+Spc@w>:NH$I$uw"`=1:GI$I?]:lx I$IB" $k I$IȟKo
ߌeq5g{ I$Iu?F@71<O$I$I~t-2|;>=r]=$I$IjwPcǣ$I$I&xǩ6w	{Ew@$I$IP?ߐ̀>n0$I$IzzOߑ̀>n:w$I$IFXSc@^?R$I$IFԽ=	]ǀ>>Wܗ$Iv=kJ~zݔ_:w:,Oke'5<?K#=C?Fj;/Orj_WW.NMݻH݇JgME诈$I:M	jc̀>&]ߔƋя}I4ux} ޾vԺ;y^yim%L55</{SSo})u_aIT:f/hs^$U*xsSϥAEۆvs7K??O{nϓ$I_f'8iꭺ?q/I^JRƮ/&ΨZU/7_$dM.sO183yITOiOS|?\S	sf~KRkF$rZ1cяyI4xԽZ1/5Tʗle,*5ݱKM'Y5$k]2'3?$I,ԺRџW؀y!҉	0X%IxWԞN[Nŀ^qD?%IRTEzOvegh7_׹Ty<,IT.ŀ^a:u[vI4S?H_;_#L;_=zCJE/<I4CVe@֊uI4kH[|Ѷ?yRoE$UI1b@btI4:ԽJgFkzZITzjcĀ^Q4y.IT?:+|7Π0#/>$Ir_?76}`E\$Po}՞/Ǒ\29Ƒ:wR$IBw=3
RV`j_45ݱ"?SP=I]$Ru[gz[$I'ͯ=PgR?I/$Wg@$*RSЏIs՗h$5TԟO[Z+yעߒ$iCu{qgRm?3Omڗ-$i#؁?C@{g$Iz896o49$IRF=2%IԪέG@G3Lק_O?$IP? ˀ^![G?%I?m~7S?P_NŋDIԽ0U塭lIƯ_~_.5j*jOGI(R}?+j2WHhNN 3)-}y$Ije@c7F?%IO֊y)_uH}:oKIƾџVA
iI*_S/ڼo?ϋ$iksU&$Iz\|U4L*^x([VTIgUog$I/b[e`+R-,IX+dCg@/ɟ~6KT?45X2ԽogIƮZK%fI*QSco;TI?IG%I"՗ jb@/|$iAjGw*-s$MPz.n3Y6|/Z8itIfVѷja@/3D?%I*_ZN[&ͩs!$I\o}U8Y,IR*z/;q'R#OI*[=*^R~KT&~v}/oލ~qяI*[=*^F^$I#_<hZ$ruV~Vjg$I].Mo
/@=2!IR4Sh;3PӢ$l_K~hS!$Uߊ0%/ܦ'$i݊uΩ6g{-G$IT3+C%<o$\;NL40^?zh$5~ۡVb>tesW%c[}קmF?f$I*}|?2H)$I#ć|g`z5jK)m|7j%e@/yȕ$)tj'w9/IVsDz\$)]|Ѷ7yM~ITʊjs6	P+!zI{'~JS;Oͳ~X.oL;O~"ITGa-Z	Kuᷣ${TWo10"JM$gq]>=~ssV(R}Rmw=z'$II
P+z	ԿяXIf:5OlF[_$I6}V2h]2;*IҌ{G_8]$b6w1@;$H5[u#L>_f6ǀ$IH*/zG=~KLiohuZ175Ô{2օߎ~J4kￂ!}ǚ$I3_].MSvH9o3*>z^$iښ%ۇ[BvyCQMMLGֹ;ơ;ڼ`]M/ygJEX$iZܲ}`z}KTH;NL!5T[UÀ>Z|#-I+Z1/7ocGT4^|U,W.Nc?7\ǀ>\ܖ$iuyo,0&n.$dv=~f@QmRIRQ{:H̜MRãqoO޿I3&`,NGT󴿊~K4L($QŚS.쿊eC M}Du>3Y/IP=
׹~B#QT[>*>= }-*v=/Iu|Yw{Km0oԽG$̵5}>yR{߀4#q>$ߦ}]XǼץύ~DJ~:g}-c@A>$T玓?}S&ϋ~TJFY@f@5sfGo$ISso*+YU>|u#STQ>u /ۥ& -j0!$M08l|6яNIti#׾K>OT}>icGLFITCP:JE?B%ICxYytjsjAGğJT&~(RQ_($ۄ w[7<KT:js6	 ZG$*kR^z˩_L?~?#yo$ImρhzG$iN3>[K?o<)}t81<Iu9+n~?yW4~{Թ:~oڼo@̀>Bn'K~PY+G?f%KݻNOwJo&a@C>}$IڨzOޖ~;͜YsIя[I{#uɜ&Iҫ[u#nL]ސzؕrmޣ7_J}RGğJ4s/ 3!_}*V?XxXjsjc-2P2w}SJvݓ$i8o&L)jOaI
XDsvj~*廿-P8$IWy%@	Rы~KҌU֮  о~(IҤ.~+E*[zݔ7Kcc@~}.%I`;OM9o%@9DI{b[0Ѓ{'vJzOL]~+Fw;,I]ɟzoß 1k{*IzkJ1N:1-I ٴ0~$iz8?HQ<_,I-Թ<˩RmGZ#͙	?IFߊ #}яkIc 1a@4ש$I嗆l}D?%UB񿿷|Ѷ<ˀuף$I/{G),EHŚ'ߒH*gßm d0~\4":~oFiz觸2wʣSܝ_z˼ׅ? ^=KFJ}ǸQ~oīX}-]N .I_om(9D?%V4^L݇J+{l =H쿋$߻Y/EoOF?%DKcKS/@/a*ˀsIR|:     IDAT&TE?L(풆=KFgDi_G]0[+ dK?@4kHo 3o{ǼȟMڗOc>E?C Hƀy I犢{PU}SJz^O8}R  +z#?:HƸco!@յf^6[? Jɀ'$IcZx1K 7gVǾ4~-?S)_u3 T6ى:/IRDͳ6|;S?*U\].M͓>ۅU}5tIҘ{Ti-'8/nWtHjT_CowD_k_8#$i+z~oAq4fI^[@5}$1}ݲ0ޒՏFi*^|8u<%.8c)M߫ P LEJFIҘU}2廽55H#	F2Ϡ!"IÚ@:}HGKkMSK 23Ϡy+$i̚K[bѧA^E/+un=2T?7Smk P"L~81$ij{8SѧArŚSSkżm¿ 63;1o ~|^[~Sυ @-}L|*@q(R_ /mXT^'3uVg~5՗js6	^0ϐQ%#$iqR`r͓>}*4-X:~oڼׅO @mDgH$IRbMKZV"ҽM1swWTFUW P+1SIN#{i]їCe{ xWG+IҘԾvk0w{beШW콩O?j fW}4N[qM{ 6q.[Ś'~o jcʀ>ڗK4u8105>#
j=[ 2πD&$A~305o{ơn;9o805Ok-٣π>ՏEL$U/w yω_rSSm kb@fm?IƠ1y nDUΊ{[ ŀ>Gq{"~v[ 0OօNT90<F^'3uVZҫXm	 to?>$kJw >}bƶ[U @ƀ>zOTZ}'0|:ČEEu[h @6Ri)џ	%IU|3+u&TV-u"+5O4Ө~oGD$U͇: O_OEs!yL~%n Jǀ>g|%c$[ܲ<ܔb9 Hb@Fk)IhGs L|vh>;J+{	 *ˀ>_RTњ~103ZNc[zߜ.߾g dcÀ>ՏEܔ$U"6>0ClIc'o0n 83O|F$UWE9 fVϧJ|U,5 P)i8w?J*Z'F0J݇Nem=뼷|v_S ٯ΀>Mg}-3$%~GR*4yo9 0:Ӥ}[%I/~ MH[Q_r  U}tXQVT@|ȼ|_ 42Obaj%IլsixSW}exo9 ƕ}L$Iîy⟆8 勶RΡ;SC~囄
 Pf@_#I+kRm70
ʣSܝSSm7 F}4OҐI^wyF6ro? @$Ӡ}n<Hƭ1o }ԾviU,^	 VbiJ4Ty}`<u>#[|!՗?̊ `vuЧAۣIRܲ<  @mЇmάy"IP(  c@|wG,*ծ.oo   PC!kS$Bu9;  @mLЇu7IRj?o   Ɣ}HRKo   Ɣ}Ⱥ=H*R   Ƙ}zOH*REw   jc̀>dEkm"IH;5   1HR;O[6   1p"IH~   `u_D-:   }xZs"IH>~   `uCb|X"I@Esu4  Ї%ћ$u0   }z\$Ib^M   2̙RH*PcNw   H!oHP]~   ̀>,#zr$U74    3I?\$Is7   C:wETg~5   Y}HWH*+o   ЇETTEM   >t&zv$㷄3    {}H]$I%sa   ^f@9mG.:7   Hƀ>7IRj{7   ^f@\$I(_37   ^f@Q\$I%h~   l!hѻ$u&   :Cк;ѻ$un>,   :CоfETZ+   :"qb"I*yc>~   l!>xy"I*yg   @7zw$Hg   @IR+<~   l=Aۼ$MW3    4%G.׹{   d1߯D.׾l{   d1|ET{   d1ygwIRk   c@P쿋]$I%l{   d1bn"I*ym   ǀ>uˢwIR4Smά{   d1ET
e   @Au0z{$ޣ72     zHJ\3o   m}@~HJ\ƃo   m}@EETڗ.e   @An+z{$ֹ;2      vyC"I*yS   !KHJ^O3      v]$I%q   6Ȁ>]$I%oc   m} c>HJ^d{   dd@@E.W[e=   2yWwIR4o   Mʀ>y=HJ\[   d2bn"I*q?e   @6) W.^$I%   &e@@IR=vc-   I<:z{$W2    }/]Eo/   &e@@IR[   d25ۋ$un;.   ٤=y{"I*qe   @6) z(z{$uo   Mʀ>GIRk_w-   IPԞ^$I%}   &e@@\HJ\o   Mʀ>mGo/׾l[   d2O՜MwIRk_:?   i2ZU"I*yK3    Mƀ>EmwIRk]   &e@|;wIRk]{   d2OQ{wIRk]   Mʀ>E]$I%u   Mʀ>Ee;D.'   i)ѻ$y:   d#̀>E5zw$~   lR)kѻ$Vg   @6)ETڗ.g   @6)ETڗ~   lR)ETW,
g   @6)h"I*yg   @6)5ETW~   lR)jѻ$䵯7   ٤S8]$I%}Á   &e@G.׹ey=   IЧqD.׹{   d2OQOD.׽{   d2OQOF.׽{   d2OQOE.}{   d2OQOG.{{   d2OQD.{{   d2OQ?]$I%܏   Mʀ>E,zw$b   &e@	HJ^?~   lR)jETy=   IЧq'gIR,   Ч|ET[4     5ћ${;   Ч~G7IR7   6Ȁ>E~3zs$Ui   @A)ETGaM   2OQ}ћ$5O   dd@>\$IyWo   m}H*Po4     {+zs$U֊y7   6Ȁ>EwDo.
Ծz   dd@|ћ$un><   Ч(ћ$u:=   Чjћ$u<   iCS5wETzO    iCHE/zw$b   6Ȁ>mE.m3      R=H*Pm74    [} E\"I@i   @ \$I~o   ǀ>3Do.
X   d1Mћ$5O   d1ћ$zM   ћ$.nM   }?zs$U54    [}/-ˣ7IR~BM   оnY"I@V4    [} +Eo.
{   d1uET   d1u?Do.*T6o   d0yDO./>   :hETZ]   u8IREj   d0{$"5OR]   uP?#{$".   d0/G-Ծz   d0 IREvl]   u/6zo$U5    [}[$Iw   H?ɀ>9R궣7IR*5    $3ћ$"vyC]   {ET/   =r]"IH?~   euxn"IH͓?~   eAH*Rk   @2-[$I}   d/3}ET:w~   e_{$"6   jETk   @2ETTIm   >=H*Tx   d}՗H*T6    3(_}"IP>~   π>[Do-
:   HCy"IHk   @g@b{$"u8)   Y}zOH*R   Ї{$"kk   @g@gD-T_P}   ̀>/-GD-
U/6    3C%[$B5~   ̀>H*T/6    3CGo-
Z1/   }?H*T   PIR>pIm   20䋶Z$I   dIJN"IJf7   spk[$I*_}m  q1G[$Bhm  q1GIRj   c@r[$BVm   0:h_G"IP[m   0:hIR>xEm  q1Ļj%IVGo   }8GA"IREj_~   6CRWIRŪ   jc̀>$wIRj   1f@Fo-
:   f/kZ$I}   jc̀>D'oZ$I{   jc̀>D/Z$Ijfo   Ƙ}_[Z$Ihm   Pc!j_k"IXw7   )5Z"IXC>~   6C8E,</   Ɣ}0zg$U   Ɣ}D,չ   1e@ԪEo-
{   1e@޳?Z$Ih~   6C}`E"IXoo   PCaAo=*zg$U!O}  2}uwƖL 0y CpLBIB2&dĔ00	P#[l&w˲c7rܻpozsL(l~\-g+i;$)!  @!kEY7   H5d@a?H2w   RgXsߌY$I5X*  @!kEYE   CPv[$);)  @-zg$eV7   H5c@]G,j   fAEYwo   jƀ>G,>.  @tNj"Iʬׅ7   H5c@ៈY$IkirV  T#!hEa~9  @0l,EY>   `>CR<`"Iʬ~    Ո}H]H2w~   RЇ{ݑ;$)w]~    Ո}H+Y$IU<   FC^M"IʰƂ׆8   H5a@֒Fo,k_o   0I{H2}o   0-rЏY$I5=6o   Lԃ}'Y$Iջ   &CԿ{E"IʬC77   H5a@KwIRn;e~    Հ}:͍Y$I7   RЇ}7IR~*  @p"IʰY~    Հ}X$I[8  @0ټ,{EY.q   0?-zg$eV~Ls6q   2g@gG,k,|k  9u7zc$eX~    e΀>d3H2s?8   H3Yk駢7IR:   @ʜ}Ț{#zc$eXKo   ЇmKrЋY$IUq   07kY$I7   R#пEaC   @ʘ}H2s:8    IDAT7o   G`j$i]_  1Ea/q   2f@~-zc$eXx4  @ʘ}&geH2ӛ   Lɀ>"GoX$IZ   )SrZ"IʰΩ_q   2e@wX$Iֽb   )S$)wq   2e@֒Eo,+8   H2Hc_X$Iw   R2g쵢7IRM+;   1ᛢ7IRuf  !o>9zc$eXo!7   R#ԽxEa
q   2d@IHrۘ^w   Rf#<$)Ӛ;   )3j,xm"Iʴ֑~    eƀ>bFo,7~    eƀ>b.X$I6uУo   G{ž$)~    eƀ>bӾHrl+Ӷ/s   2b@֒EO,Lkw   RF#XU"Iʴ~    eĀ>js6+$)ú   `" X$Iֿ   )#kX$IV<q_  zDo,Lk,xm  	zW$I:Cw   R&{z"Iʴ)~    earvY$)zW   `" nX$I6   )Go,2<  @ʀ=H$)Ӛ=  @ʀ=HG+Lk;   ) }H2{;   )(۽,EaOs   0Q}@GoX$IV<~O  z'Fo,+χ9   Hg@4ZIQs   *΀}IRuNz  Tq@ͽH2;   &geH2lpw   &̀lu$)Ǻ2M
s   *̀p$)Ӛ{#  @0z9H2}̟9   Hf@Z$)Ӻ+s   *̀/G+LrZ  Tahs6+S$)Ê'   `c`ˣ7IR5vxC  TQ1[yp"Iʴ⏄9   He@31z_$eԍs   *ʀ>ZK>H2wͿ9   He@H2mw   REDx$zc$ؠWm_~    U}L^=H2   
2勢IRm~    U}LOr"Iʴ9   Hd@~;z_$eK   
2y[e1X$I9Iey  j1EO,Lk   1IR;   bcs}Ei݋vs   *ƀ>FZK8z_$eZ   1ƮO"IʴH  T1q2ghX$IX[   a@3/W$I:w   RLIRuΝs   *Ā>f'm"Iʴލ'9   Hb@3H2X{g  T!qrЋX$I9Vecu   0Q14xEi/  @]t"Iʴ~    U}u7z_$eZ   0ֿ}Eios   *>Hrm/Ӽ-o   
0H"Iʴ~    U}L</z_$eZԯ9   H`@S/z_$eZo;   c}IR6  @ j$)2m[   i6'IR5/   &ƛ}2z_$eZ䯄9   Hc΀>zWH2wՁw   Ҙ3(I0Y~    9k_IR;eo   1f@g۽,Ei}+  2CIRm~    1]{x"Iʴޕ9   Hc̀>:g~3z_$e+   1f@sſHr.-o   1e@s-ˢX$I\u  4P+z_$eZ~    )zVH2{;   iL+sοF+LwY  4Hr,[   i+IR5~w  4Q<@"Iʴ	~    !zEo=#z_$eZ   1d@IRF   u2WDF+-o   1c@n=H2o:   Hcƀ^!Ez8z_$eZs   ƌBH2ww   Ҙ1WHwł}Ei5+   1c@֑Hr)Ӷ?~    z4vy["Iʸ~u   ƈbW$I9w   1WLӢIRV-s   ƈboH2muw   1WLk駢IRee  4&IR5@  4&T<y"Iʴs   Ƅ7-W$Iֻ   1a@ιsIR)  @
jG$)׊A٘[   i+IRƵ[   i+x}Ei3)  @>>z_$eZ   1`@F+L<v{  4Z}EkEQ6]  ̀^Q~z$i|4  @
f@cwD+L,N  ̀^a돎W$Iֻ;   ):g}Eiœ?s   +#$);%  @
d@We1W$I:   R z%z_$eZwł;   )z.W$Iֿcy  Ȁ^q31z_$eZzLs6u   +uЇIR5[   ){EY$)U  ZH2{w   RzzWH2mpew   Rz:}=z_$ZU/u   3<wIR5[   )=۾,}EiS   `b<pm"IʴުC    LVH2m;   )=S^TW:   H#f@DsG+k-[   i蹘Ҳ쵣IRuV  2gdfe"Iʴ   3gw$)ӊ's   F̀IH2ӛo   2ghmEq
u   FȀYeI$)Ӻ̋u   01:(z_$eZ   2g{.$)ӊceY  4"̴\"Iʸou   FĀƮH2}~    =CF+L^W  4"o95z_$e+   1gsd"Iʵ~L۾,  @zZ}<z^$e\u   F+ˢW$I9:   H#`@ۢIR;2  @zz.W$IV3  @zy$Iêo   !3gyDo+k[   ieeD+L^0?  p36X2z_$eZw   Ґ3ֽb}EiE2<  @"z'}Eq=~    =cͽH2}߄:   HCd@ٜˢd"IʴW:   zwH2mfU  4Du/1z_$ڠWy[:   HCb@\=H2uЇo   !1gpmEq3)  @zOH2mD  4$xb"Iʴ{   !1@gwIR5v~K  4hۊ$)ZG|:  @z4濪,A"Iʴ;:   HC`@7E+Lu~  4]}h"IʵN*[   iksG+k.:  @ahmEq퓿~    0z]ݢ,}EiS
u   0152}EiGns   fFHr(ou   fFU"Iʸu   fF{z"Iʸo   $z٬,F+Lyn  c@gG+L+OirV  4C5ӽ`^"Iʸ:   H3Ā^3V$I^[   ikӛIR^~    zH2m-w   1PcIRE   0PW$I:o   `@AV$I׽`^  4u˲ߍW$Iֿcy  Mg@W$IV,[   ʀ^S+W$I   &2T/Fo+k/&  @DjmEqUo   Md@9OVa4x[   ƀ^c;ϋW$IVecׅ:   H^cwW$I:   &0XOGo+랿]  	5IR<7  @+/z_$Z'irv  5[}\"Iʸ>u   6:gs"IʸΩ;  2\ߍV$I׻[   i#nWH2x[   ǀN9x}Eq[:   HNٻmEq?~    m:eV$I   F0S6~w"IʸW:   HNl^'IRߴ:  Ć13$)Z^  L^S"Iʸ9~    m :ZGi"Iʸ-:   HȀδoV$IW4Nύ{   ΏOH2;o   `@'_7H2}߅:   HΏuV"IʸުCo   `@Z?z[$e[o   `@'mY^"Iʵ(;{   ǀ<x}"IʸO:   Hɀ<(z[$e\o   d@gmH2E   z23Hr.Ӷ/w   փ59,:OG+k{   /΀s^H2so   :ѽxa"Iʸ-:   HsL"IʸLs6w   ^h,*z[$e^sw;   H/:OV$I>+   ҋ0NNV$I׻vi  "SgwIRO~    :ZmEy]~1  @zt֩1Ue9Go+k{   y^oV$I׽b[   y^UIR>  @ztW{ٗIREu   \u"Iʼw   79,:OGo+^c  u3w_H2   0/V$I9kiۗ;   H`@L"IʼAw   j]Eyw   ΋*ZH2   :yQNV$IW({   Y輨Do+k.:  @z:/#ѻ$):}=  @z:/1Ue9Go+>.  @z:eۊ$)pl~    :륷mEy=~    :륽Kѻ$)'9  @)tKsѻ$)z.w   ~39,:OGo++A  0w_H2ۯ;   H?b@gu/^H2}w   ~Āzk]EyU;   H?b@g5nH2o   ҏ SkIR5vy[  d@gCo:)zW$e^ؿw   lD*]_  d@gC$zW$e   $:1Ue9Go++o   l7DO+k?   lʃwIRu/3  TҶ?W6~wDlmwIR~xu  o.GYٽtekwL`E[G*+ecko  ?YvΛ[o>,TO?ߚ2a@gM*N"I[y   A^SeSE	:CL$I*%;  ]6zW>UVO܍߉ȃҽx-$$U  `$-6gTSoL0QG}fQKo7  `f[H~Km2`@g4n5_蒤z:7  `}5潲ls75=*;>#eFېo\ I  [>*n/MTֿ$)?&  X4dc2`@gu'9 I{wxC  ꥱekGG򙬹o8h~HjP?y  @3Ysc2`@g5濪,g$)~  [:w'π&<xC@yw  @.-ouu$G?$IWec7<  b-Ouuğ$eD?$I5}go  0FmEo]ƪ14Q}t6Is{Խ|Q  LO߉m>?wg@gL*IRMm  ӯbZ|&˔:IRރӛo  0^̫X[P>s7~Sl>o  -?Cnb]ѿȺ9s>Q}t6YD?$I5{ž7  XO[^m&π&k,*y IAoy  zQH03#'~&HjPc緄<  缷uԽp𯕔:3IRj  +ǲwݑ;[{_?g@gFt' IA<  {{h#^kDЙ~&HjP=7  |oԫXk?k~𯱔:31Ue9G?$I5ۯ=  W?*ӿ1=zoyu/+.eΌ<xCsAT˶	y  0n̫X}]sX9xhuYEGy-NT3^ZI]o  zv+L03cF$Iîh<R9=  ?]cZoA_)tfLs{4us  DW:$k8e̙U9  ުpS_G_g@gF^l$ՠ-<  ?f+z.:O03/nf    IDAT~6HjP~joD=  X[z2`@gFLAT~  5'-氲X{WGgմ=ЙQ[E?$I5s @M~uٻ -Xտ_#g@gO|$ՠ}  ߫XGo>9Lʀ7[$~L{  G?KTЙq|$դ֡~  WC߲;1пWo;3VʀZ$&u/9 P1[Կ_og@g(m4X* 0lV6cy./^;c4%3P.!ICŠl ORXKf'P$Q{  N}/ލ'E4ƪM':M03$դޕ=  F{5+\zz;Q}t;T<~w `8b^Sٿ6?vJw1ῖSǜʢXsBT= Q^[|'-OGwݑ῾SM39kw טʲu({VZ]EqRʲ޵Kͧ?9$ioZ~  xOߍ(զ?
LTi	IRM*Oi ΞFD^\H03wؒQ:C .^Ҙ[yp"eP1Y!II{  YKwϏ33TU4 PyNG=IQ)g@g˶~VHҠ_6] {˧_r9[.eTEϘ:C7> `[>*?M^Ws'epټ,ZOD?/$I5;  ~desru{h?$i~  vG3Iu/54Q}t{$F5w{ {˧^z<#1{Uʀk$FuNZ )^_sdٿ4-u/12`@g${$IӲ Q\6Tkg@g$̐$դo>o rICsug@g$\Q:wo Okeϖ݋w)w($e^K03S̐$ը;> _]3bزxGjX/?SDsF?3$I5jko POeٗ~CTB3r,<M4l dۯ<O>G.2`@gd&IҨj T[c7?YvΛ[o>,EđSє:#ӽp$Fn8& јb]g$ij-X5eȴtsCT2M .{W咲uЇ㟷g@gd;1!IYS, \RkoʀO$I{ hGI
ß)tFwݑIRY~ rIztʀP#I*鿅} 09{%ij,|k{TsG?;$I5} }f
IT^,O03ZsG4Ҧ^~ 4y[?S\KU4+ <1?WHf<zɌ03rKv~~HjV POe|{o$~'Lȵl#DTo~ Nb^KR`E2a@g䦾$Ilp ˗q]~vY>U<;2a@'DIR*ec_ PU[.Ij#eN޵K#> *A?K6'y0sW#[}|q咔_;ߗ	:!$լt ^[|7|JYO$iD/1tbټ,ZOD?K$I5c7 Feޖ}oyQDcI:$MNgE?K$I5k= brϼ|U,N$i"ttΛ~HjV 3WqNYvgV4Fu.VL	:%7 6v([bzzFY4>1s?߯<Љ3o˲'9@  SCl2a@'`ͪ$f^~ `C)IXc<~L	սl$necׇ@ X_e_:+eN?$iԵ sO$b5@J0IR]4>tJ*Vsw߯	:'~HjV|Lo  DNIRj2a@'\#):7 G#Ϧ$b5&~L	9kIR^sѿ)IREQ9߯	:7"IaGn	 >~?lJ*T~*vЉ79k$I;  #FLIR~ѷ+eĀX߱<"Ia	 b'STkV߮:csg$,l%IZ&a@g,|,"IcEQ65ik)IXk߯:c1e9E?_$I5}  <梭O$bu/#~^|$հg@ x>%>9w"~E?_$Iu._~`]e$U_	_)#tƆG.tNF$UQ_)#tFc_~HjZ#  KgRTZ?~+E?c$I5h=Q/ lDIIRjWʈһg$|,o?;DJ*Vc7߯:csף16ͬ  <'RTLs_)#tJs$մ4g[ ?h=}"%Ih])3t<$մ~ {yi$Uc߯;;ύ~HjZ  o>52c@gt.Y#Iiڻ  }%I+eƀiߢ5 |Y$Uު+eƀiuYIRMX~`JoEEIR^0~K576x; SW}%Is7Wʌ7 }%I}_߯:cuğD?o$I5s[ Gn>:+eƀXjl,IRM<xC-lVfI$U~5Mŀؚ/$I;o! ѧPTv/a)3tVEIRjS(IXE2d@gl\sGT?:P_c?}
%I˫(_2tVc_(ˢ~HjsοDAIR߱<~k$) S%gPTz	_)CtZ=7X2PO.>]}J23UGT{z=~$IR甿_)CtZcVIR;'P/}$IuħoXʐW+#Iqo KG?IRk2d@g>4#Iyͽ#PeD>IRk,|kK23'$uW, G]O$je~R茽~5$Iy;4g@=o95I*VԚ2e@'~Ij	0*n>{5X2~LЩuGD?$I5{neY'IXOay2S	퓿$ռ9g@ޚvɓ$U{߰):!IA 䭽KNT:gCK2Ss6+PHTWZENTZGIK2SG?$I5HirvM _{.>w
\uK2Sӿ,$l7mS'I`cy2SS&IRtkD Ϝ$͵7,èNuټ,E?$Iu(_NkG_9IRY~RTJ擣I$&&y'NTz7~RTJ~&IT<7&G8IR^kK3S)L$,Amw'I`SwK3S-ˢTsIs" h+ѧMTZ"ЩgE?$I*~G>m?߱1:9_K$M7" y^[Y$UƼW߱1::%I;" y{IY$U}RTܗe|$o# 69,;)I*߱ЩE?$Iu" 6J0I6G߱9:9wNI|``SuNz9$UE;߱9::C'I);!6P]G_3IREkw,e΀N5ݢ,:OG?$InoF ifSCi/߲ЩmgF?$Inwjj3&IpC-K3SY$5i&IhE;jNe5{_sJ׽|Qmzz.>a6;jNuM*g$I'ʴ+# R<qo	ٻp#wN PX,	YB&$Ɇ%!!/TAՒ%066ƽWYlYts܋q0WWs3szw3j3	Թs,,5u8=g4(I}= a=|ecF9> .ѩyE. FX?	ed~ۣ* Oe1|>JFmDO. FXϲl@h7gV*7> KGI; E7ewgF-'DY r)]|$w#= aŚ{gY6&Ykk3 qG$ikga`u>˲1]#_}7EY ,ݻx
,,UʵD[ /Q4_RYDO+ FY6&Yunz Ҿbi|$go1kyIDS>}n1|FJMD) F\,,U^}nFx$YOecm`]X}G }(I>yQL> `#~1|FJM ϳl@Wej 6Ҿ)Il+G #ugg])_kJv ݟ0sR__K T@-|ec*U+0 H$׾r+˔/zQL(tU%s1 Hݓ='%I= qY6fYRH U>'%Iq~g(˿>Ӳ1]j?}F?'%Ia+zPϴl̲@WqzY +T?sRМmRCѓ
h6{@W6 F>'%IߎA T*W}[2 譝|Kg$iu?*zPfn>ײ1]\{ =.B$;6z PŊ]#4 |A1yGG ѹs-,U&P U?Խ@E𹖍ad◦T T<r]$|mE *mf6q_( VN$l-z P!W϶l@Wek_$\MsA$`sf≻ Qfg]q6 جߎ3 THsg[6Y>7 ؤ-'KIҌԹ1@/]>۲1]{ lZM>/%I-_Ҕ:)@4p|4tUY> `>/%Iu it>> `yʗ,|fJ/uϷ*_s 6RԟG0z P1(og׾zY9 U6ץ|	{ci]q| Ծt~̔$m]ߑRYF *qg` 6l<S4un:&z P5e/	qg{ <%sg$iz{:n+z P1ϸqcqu?Gw ڔ/zQܔ$my+# TP֓gܸױ@8T?m L/+_䭸 Z[:ʵDy ELܔ$M=
Li[snXk\\wx SҺ?$i)WD ,RnXk\j L^{8|vJ9 TT9Ƨ|R궣> Kg$i
>_H :7?,5Vu,i)gg$iӵi@Yƫo.QaSV?]N]cUE} 0uE')Iڸy=% !eswYk*}un9!|vJ~;9 3{Ni"t]}ԕe)I־t~Sm2t]?}sA$|KSX= {Sm2t_w 1Ծ @ݔ/5|6ƲgF EǗl3TƹR궣G W>|L˚g|:,-:3TƹoG E<՞]cY& FIYr޻sTƱQ= ͓>>T{&tmţ7F |E {\SqY}+:~[$S6`LO=>T{VZ ҽ9*IRǋS>}=+tosIe*\iiTƠGE Y7|:7~3\i)=ݟ>K%5R*#1R?Ogen[`T;|JReC*V}0F溔6~*dE/Jێ>`_(z/SIbgG =?6]c_KG MٜYTT}7iD _mƾ9>`4Od<*ս1T?gje/# l2"K^>S%
5Oc1T֟tÙ47E Uw>O%i}C*룏t Pj=@fR$ l	>S%idMyQj}gR,Х/	:$ l2ܭ\$i.r1YZ,Х+}VV|\LQ~ȻR궢p T᱔͙>Utk>//I\iNx1ֹy,Хk|wK r)_*IPe6 cy'j]qOecm	 }ѹ*IC@wE    IDAT^TG6 c.3QMf.D>3omla-u̟>sD65OX	 R}nU+~}J@\wD\T\O: fbA!|J0չ &5O7XKϮ{g' UEU[P(˔/}elTmYK?UF _E753VS &>U{,Х*Փ X9+IQ{h_|T9@zT<3 {)]7oԽc ߋJϕԣ_>C`F3|JҠ| lN3R~a.m\G 0325Y+IuᗢO^ HγgjS]DʛR eTVfF YM)ti.})VߙE/4S{OJ<}^>+UR&/-,ս6|JRXJ>fbR)g.mbg* ̨$|K`OTmYKg* ̬Lo}<|JR? \}f53S)g.m!}kS+>w%iZK>pe
 U6קlsSiYKQ f\?9|JҴCunQ
 ϩ{isSiK@{F 0Ś{SW>sa îyN-]z& E𵓷A4l:7}t{6~~*mIs5gV*z0|~R*|K3+u;")+%~~*mij_ վ+ImGE E&n>C4ti
5g, \%3X6jyHjsTiK@ҜmR~E9 ׺$;G .~*mik_spY Wug$wM/>`Z:7|#|6,Х)8g- (<XT<|mi 8#Tie.mm\=}@'U<4vK_n>`ZY>SUVԾj# b>.i/\{ [s)3Uig.mA3 bYKPn*kO= j͓2|6,Х-iάT>s byIDv /zQlUmYK[X%G/ +:粤5gVj]2/s~|Uښ,Х-~/E 0<K5|6KH?/u8#dj5YKӨX}g CcӢѳYhT>8*9Ve.M` *B4_> mu4/-ӹ픔)|NK_/&*rZ%@Ys N|ы紤._Խ# fT}[gj[4Z~)T-{6|VKꇽ'k> `F+o%ti!>`(W!>%W3>R}D蹫Z_@kc Zecmjy-i8nҹc	 ~;j}]ڊZSy íJo}<|fKOGO# bWe.mEJ,e neZے܂]Ren{i]<;~++ti+s FBS6-ikT>c Bs,VoYK[YOF 02?H>ߒf;KS* (.~+3ti+ v=|Qnxlө3\RT-P%|&,Х>Թ FKI>%m}^>u+٬Z_@P?>`$un>>e?/|KrG	 fԏmlU9 #xƔ\Ҕ{% YѪ=tOw`9 #lK3>>%=GvNKiF 0\Nʗ<~V+;t_ l|K纤kǩ\{1 C{Z]cŪۢk yEXEuIA/> `5Oڌd.E_>2:7ݟ>ߥq-s)Eq  íHnf$t "G?|KT%}R9-aVmƲ@\ˢm WL`ɿR_ `'~4~+TRks *\pjg^\vH3?+_ 0r&J3/H]>&̰~g415t*z(e #s3]i&@f ̐n;^.4xݴ\*?JW?gj345p c\Hj/_J.b*k_ P	wlάڌf.DOǢq ݻIK{ i˗2+/U օ>U,Х}8 |s0T?ݩs)W' TOY|xU?G9 vڗE/
? y;>JJunWD }RtEW~Xh@@f韊>`M|ab/|~8}s	)u/5 6,ХlB=s xBSe7E `,98j]:7|#\ ~R:7)}4я.| BJ]G?\ z'o}Q?M5l_{h*OFb R-ThL7gV*;| 6xS6o..T<< ֹ^Af.օ_>)(?ڗ-J>*SMCWT/ n;K^Af.|WTty `"u(5Ohm^B^}JKs ;N@Tw< 0RSw7cH; B<ti@5s Jc_H^	oi.qSe\@S 96Ҡ@ռR>>)VݖZK>CCwkN;Jӈ~ }01T]`>~+}:_R}7˗"5OԹܰ2	 [ϡZH # aSʽR3ߊ/zQj|Sx_ 
 ׹e.O lmH{/Js>}>D+UyG'c^AJe qߏ4|" kIkM͓"{lh~SY X}G̊4 z熯A7gN~%-P6G?- !:Y"@jw Be%n=R^2)y_o;o Mj}>F)2t)) `JᥓnT?=)ygݟ35OXjga~j*;O	 GſQ]
{s  aSMh_{䗔6n393]~د	3.bԽT_ T=g.<Ϣ  PQGSթs}Şu?Wj%{pBx\eWGo}j_`_)_R @uT,Хm?yq Ѣ}m{癓_hށ}Ժ?RI3>mN4qowgwwug'?%޺d5MǦ]Wbܰb *6~w4YK/[=    	_4;g=Xk}   i_}@H]
s   	e1|_d.8揢G    )T,ХlʵG   8"a]Z}9z>    b;"Ն.tiʗ2n;zN    #Rm@έ'E	   T_y;T,Х!qg   Xj]ݐjC4D|?z^    v/	6YKCT󔿎    cwBm05oTnX=7    CYo	)kҐվtA    gT,Х!+U)u[   _]jC4un:6z~    TZح)3+|Pg.aj   i6YKCZ   @%VlNՆ>tiHkѳ   ZsG]nuG   J)kRw?J4ĵ.rL   %sw>L/~iJF\   V/	62YKC^E   Jh_WG]Rl   }F|UG]]=b    FZCw<\83   `tTM;F.tiD*1z    MǄvT,Хy'g   )T?F2tiT}*z0z    guF5tij3   `ԏj#4BwMecm   	.	6YK#V%ѳ   `$4]j#4bK_R=    Z8|3   `oG]vK,   P.?;|Z%@FgF"   S~دnTD҈oD#   ӽj]^=    3|gZe@F=    F5U*tiM*V=    T?*e.x͓*z<   =j]nQ    >_[FjYKy'   @ϨV,Х*4oT?zV   ^}QbREj   =4|/Ze@S   00ekCʗ2~/T,Х
:s   ``ZǨV,Х*5T4zv   ̸2[cTZ[   q3?QYKUk2[=    fL.~T,Х
ֺs   `4HE]`d,   ⡫S6gVE]hKD3   {&t{83   o:sQm@*\Es   ?T_}jcTE/Je}Mx   jk
ߵ6vYKuї   V)[R{.t??٪9   0mgXT,Х1u?E9   i)z(e?/|Xf.Cw6    yGw+J4&5L   "LٜY{6ti\}*=    ߩ(s<ѣ   `JK:5gT9z   lVY_/ߥhXKU=   6ugw(Rf.asfk    @OŪR6w4]GA,   qw'RtҘֽy   ,[NߙHOd.i#3z&   v_3]ώ    Z	ߕHOe.q~!=  1W>`+]:=#  18#;)4K^9	   GlYKJKFJ   `݈m"tI)[s*z(zd   cu?Eٛ]d6zf   cXysnd.G&=;  qP~{!g.G0z|   c R6,%=FP   +R;)BN|ZK~;R*ѳ   	)ֽmmFpԹѳ   Ru>o[`$G^NET   Jy𽇔mA^:e??Hڗ-   @.BCʶWM>k/	0|ᮩܰ2z   P<vKm-Xp-[#ij+   0N+{)F?|}`$Ysf⡫,   0ڗ/qHWxjy\#in   FPΔ)|!ei)sV? ICY#-   0jnŇvU=_ӹ8Hp/~i*O\   `3|!e[Q_|\kOH߇]   `t/wQq̇yNZ/	@ۥb͡   []4(o>!I_g8   {03Z? I_B0   0nYsBPӞyn׊/5lm   *T?wR֧Go|]?ق?(I_/Ec   `OBR4@~g41O9  !2'fo{s|r8Ѩq̇f2   0Lnj]Ix޺7Jzߎ   h_(|G!e}}/;w$N>OEg    XS6o]l@/֯`F5  H<՗~7gTl@(it]*V\1  @3?fq⟇?@IUL~a   0w9wR6譫FzV   luʗ"|!e3Tc7@﮸!J򅻦=  A*8C{)JG6@CT8#    =$| e)@%fO   X}g{u?}aThT6jv   PtR+w{Ͻ@/>@%no7   0 o._^Ox[4&_3   ̰Ofs7Hg)F_F.   `t=]N}},ik_Lq   `ej|K7y	~o
Ffr   3}݂4{05f_=͋%v>RY,   f@+S6w𽂔{o.ik   @)5)PeM޲hCH쒊'   KfwyΗ&k$~#~=   Q%;)dvHej>eHW   IƮIc	?H@wJŪ5  >)O|كx{[@>r}"   }ϏP@\OeQIF+   I=wRPw[wIHvN;v   wV?m}ѷw`Q+խ\    Paezu@|^@opt&:X:   ln;5x_n@ʢOv%U;[9  j옺ů-'>~q?T?]   MǄ,Xҗ  IDATE>z*TRujgZ   +V ew
HYP{/kEPIjxi^   Ԕ)u{ ivLǴ_?[@P`I)S\7C   ،).'ƴa6?<O   6u޿_KY`U-^Oh\RrVf   un=)esf_KYPޯMekE&e{8 :^ʵoՁ   HΔ/|Aֽ~-Mk>s Iժq&   L_X):_k򉾼@OeG~ !Z/ߗ   KC{),_T/'P{҆;B$UۥW  q::ҷV-';"Z!s  |kz)yz*T?1Uď  qн!z^\?dSl$UM  J+_=~&:^"c*ﯯ,'o=9$R_'1   Sפo:#-'4NT/JRޔN?*   n;5@<Y_H	IVף
   yg¯٥,!J]=>/IPsfg  >%/OSk	LnTE/JŚ{g  ҽܔ6Z]"[s*z_o3@к_JU?)u3ul  +Vޜ򅻆_KYds
fl>y*U󌿛c   Vaey]׾栁ft"5_jչ=   `ؔ}M.e.@_{3@Ъ_JPvIc   CNo~4;9oDM!Uͩl<5#   ej7R`Pb_<:    D|"yl>XXʗTW/1   ӹn)yg_O(>T퐊7   fT3R6wniv\rۖbʔ I(R?q  @];_oKYTsf0YO(O+ǐT_nԑ   }Q'K^~-5oԹ4,THDgGi   U+S¯=^_I}R}2GR3+un=)T  -V6קT<~W6.[6?o.x#   kj)10'v	4{6٪#   [M͓>~--4w2ZO讼5%OHomEi   ie*Z(_Խ4n/mgF}  &kg){*=FP.'ej]o0oPI[O3   H[v5C|˖Y?M)?mFۥ}De   ⯗Wʯbi}R!m=+ZT'$  Թ&ZYXvI+N~a(:^}.iT6Gc   m'lҠjǩ\pe#@Ԫ6.	 ij"  `u9?eOcR}n۩
Fo[R~?$V}|  0f\9ykbim_,n;U.'ejt\'iάԹ  1Q>^=,dvN9jF{czj] ed4-%_}r  PqŪSeL5:ܰ2UU5O+֯Lͳ?61#i˗<k>   b)__i&w~jT_R+6J6)$ixTf,   *x׽R˗2.4.*@GRMBԻR}\  PS¯w~8}s1rЩǊԹ'qS*G   #xn<We<өXysgc@FM;Lc>66I(ixjO'   #\U(_<Rγ潌'M˖|7?1%G>   AŚ{R׫ïk/~K3S4_NCgl?my\xƽ9ۤFI   r)״Tm˩uSދ|9X#קES~{҆ٳВۂS"   F@})e͔osRsSx*3R,7O훎K?_d4%/;   װO6l|'?]޹T)ri[X"o=95|ʿ_ӆ($Lޔlu  *aaK=}ߐJj</SMkNgb)/J@EOܛ:Z.H<J,E%i˿ޔZyI  ޵Xs43mX|M*je(X    @     Ѓ:     `     =X    @     Ѓ:     `     =X    @     Ѓ:     `     =X    @     Ѓ:     `     =X    @     Ѓ:     `     =X    @     Ѓ:     `     =X    @     Ѓ:     `     =X    @     Ѓ:     `     =X    @     Ѓ:     `     =X    @     Ѓ:     `     =X    @     Ѓ:     `     =X    @     Ѓ:     `     =X    @     Ѓ:     `     =X    @     Ѓ:     `     =X    @     Ѓ:     `     =X    @     Ѓ:     `     =X    @     Ѓ:     `     =X    @     Ѓ:     `     =X    @;   O!F    O    @     :          A    @     :          A    @     :          A    @     :          A    @     :          A    @     :          A    @     :          A    @     :          A    @     :          A    @     :          A    @     :          A    @     :          A    @     :          A    @     :          A    @     :          A    @     :          A    @     :          A    @     :          A    @     :          A    @     :          A    @     :          A    @     :          A    @     :          A    @     :          A    @     :          A    @     :          A    @     :          A    @     :          A    @     :          A    @     :          A    @     :          A    @     :          A    @     :          A    @     :          A    @     :          A    @     :          A    @     :          A    @     :          A    @     :          A    @     :          A    @     :          A    @     :          A    @     :          A    @     :          A    @     :          A    @     :          A    @     :          A    @     :          A    @     :          A    @     :          A    @     :          A    @     :          A    @     :          A    @     :          A    @     :          A    @     :          A    @     :          A    @     :          A    @     :          A    @     :          A    @     :          A    @     :          A    @     :          A    @     :          A    @     :          A    @     :          A    @     :          A    @     :          A    @     :          A    @     :          A    @     :          A    @     :          A    @     :          A    @     :          A    @     :          A    @     :          A    @     :          A    @     :          A    @     :          A    @     :          A    @     :          A    @     :          A    @     :          A    @     :          A    @     :          A    @     :          A    @     :          A    @     :          A    @     :          A    @     :          A    @     :          A    @     :          A    @     :          A    @     :          A    @     :          A    @     :          A    @     :          A    @     :          A    @     :          A    @     :          A    @     :          A    @     :          A    @      Ӄ6ya    IENDB`PNG

   IHDR   9   9      	pHYs    {Rk  wIDATxklE ŪQ	j|DE+|01&FM^TOPJVB+Ai}PDXBmgwv13kb,t'י\AA>( )[02l6mCUW tr{Ӝy Z˨Z
&ӶLJ{.'pPZw?4Rrv<cǠ_"hhW"̱BeR#wo 8G9膛BrH@}Vzkvz۲G:kA45#z3ِR/TRw`?/<(]$]G4y_&G=9|;e.ڻfW_|}:jG	$_#'z'}Sܡ`wV$u׃NϺ\nby(fAo+]H"Ɲ4$\G 2>d9JH3@^dNǤvWM4Hh #{/@]5H1+HH {7IUBf(!EDL#Hw@:vw%# EiT|*?nG	i6?Rm>P~$X4>Xԛzesyc;354?~R"oa-pSYJH{߆Az=ve>w Ŷe>ޯ<_o^s?f@)-lJ[v&麝CZߔ+!VB<Z!nJnX1*]7?xq%RH1n'2m<AY4ܑ/dOC5V꬐VkR}n2"b)dgCRһe{Dct^°*'pc#ͭa:>1xNw6Vt$R'8ԿuDX5Wn{b14c]vV #Ɉ9(1hp$ʾ|au*ыp'&ݶDBؿBXb~]ܦO`|WGCD̬yP    IENDB`PNG

   IHDR    6   3   	pHYs    {Rk    IDATxyw]_Rڲ* (cU@qAQQdPi}KJ}O%ӖIӜ}}qn%IOn=x?nn7	  yE   8  2` @w  Ȁ  0  ;  dp     2` @w  Ȁ  0  ;  dp     2` @w  Ȁ  0  ;  dp     2` @w  Ȁ  0  ;  dp     2` @w  Ȁ  0  ;  dp     2` @w  Ȁ  0  ;  dp     2` @w  Ȁ  0  ;  dp     2` @w  Ȁ  0  ;  dp     2` @w  Ȁ  0  ;  dp     2` @w  Ȁ  0  ;  dp     2` @w  Ȁ  0  ;  dp     2` @w  Ȁ  0  ;  dp     2` @w  Ȁ  0  ;  dp     2` @w  Ȁ  0  ;  dp     2` @w  Ȁ  0  ;  dp     2` @w  Ȁ  0  ;  dp     2` @w  Ȁ  0  ;  dp     2` @w  Ȁ  0  ;  dp     2` @w  Ȁ  0  ;  dp     2` @w  Ȁ  0  ;  dp     2` @w  Ȁ  0  ;  dp     2` @w  Ȁ  0  ;  dp     2` @w  Ȁ  0  ;  dp     2` @w  Ȁ  0  ;  dp     2` @w  Ȁ  0  ;  dp     2` @w  Ȁ  0  ;  dp     2` @w  Ȁ  0  ;  dp     2` @w  Ȁ  0  ;  dp     2` @w  Ȁ  0  ;  dp     2` @w  Ȁ  0  ;  dp     2` @w  Ȁ  0  ;  dp     2` @w  Ȁ  0  ;  dp     2` @w  Ȁ  0  ;  dp     2` @w  Ȁ  0  ;  dp     2` @w  Ȁ  0  ;  dp     2` @w  Ȁ  0  ;  dp     2` @w  Ȁ  0  ;  dp     2` @w  Ȁ  0  ;  dp     2` @w  Ȁ  0  ;  dp     2` @w  Ȁ  0  ;  dp     2` @w  Ȁ  0  ;  dp     2` @w  Ȁ  0  ;  dp     20ýN:WZg8tT6wT]h/~u?py> lR}ׅ\7wT;R?H399{_RF~/]:W훚GI-ze_hŪ/yC꯸>  Sk*,5ԾhI=tFý-uTg*\}7M &krYeoNSz_Wo=ڗ{j_RcK{#
 0//|y[_}{Z3ý|j?;&gjT~h& 0z_j+MY_;~uRTߟ3 pI[Uuο~c~?u9`cK?S w	ޡNi[saފRc߈Fjl==] 0Һ?
yc~7ϛ͎򿴷c~ FE&kLԾxr{ͣq'aZk>_YY['Fsw9/ն{c7IE	 BY	3Zc?]:Z}~9s~/{yVkyxheh5z_*3 nsfk3+/9py#{7S* G]!gƻY
tZw=_`+՗>gƻ֙ߜ:Zw]~.O U`ڗ43ý}?]}7rI= zjs71nάԽj&] :?%ƼyOڼ!_^1& `-ڧ}ww%OMp7VNoi<<cc As^c]cGSuh	Fc	 x;5J\S3ۗz~y	 XnMm^s_ilYÍH/hu.f* uqwQ{gY#>k~N ֣sɎ?Uu+pyf<) G넿*ƶW6pwφ{' S| |ۚ'~eÆ{}¿hSQ: Q>oGټns_W}+R3t =eUuׇ	bnz<C :,Jc~e?w{Wսz| RyPw$3zO|
 6@z:5v{g^P1ۘu1_"_5䋾? ȍ`ݠb.pýƧPߖ	 =k*ƮI_]p\{P缃̣"w IjBXUu)u?>}"Sjs6INz 6=~K(Sݻzp4Rm_ԹpqS 1_j_'TMý{_:o- sٮB<%EU^M]| tP1iJEUWrսO3 )O-|c]2*&^>w/͙z L&t"|k(^]&SE¿*>;+ 4i"ڧ,;6j>Q`u[範oY<&NEE_L/yC*~8 fnI[o'KEӧ||gG?  3sNC)_>8*K?T? TSooNEf!8^ ZׄoY֯=?T?5 @5u~Qeÿʼs/ `>UUI_u_*>[ Sӣ=qg*{ߟR< 5Y{TDc߂RGE??  #y\V}^ 0ʧOE**p| .ݫ	+*pƼ# 3)>]yG `HH[Qpڧcs  p;-5 NcTltDO PދQmS\ԯE< qgTdV^" l;շ}]Q1rS՜Ywѷ 5oQp'] K?oTTTDt cTYQ12S{΋m `OjQi `L'3}#oT~} \WQ1Qo w^jݣ"<}5o| LDU%}2| 0SZ|!~)EfOyo rCe;HEX;R6o ys÷~so &շS&Rp߀g; {վHEHշyl ÷p%;F) o#3>D6n+F SOo$3>DݛM ?rC$|'#w	 VTX3+*& ֪\u'o&p_O" ֫}߅o&3ᾮlʧE *^jNJӝᾎ͋C b3R}7ԮE  PJŴfΕ{G Z zCT->l	 N^KTL[^ LJ÷ipN~&^;  &LTLKs^wp l%;o*Ӓl]ޞR}k  ]K%V*<ٺ7}f  Ssmb3ھv `afׅo,S>/ )9AR1U~7vwJe?  T\ۼ*|k*?ܻ}W  Ӣ}bʪpϩOI Ux2"|s*=;-' i>KŔTe?}K  Ӫ\`<~{)mlӿ}G  3u_o/]5Rr׮nK{/LKKwGq_J(5xjTg'O^m緥.?7<cu䟤)K+LNJGԩG)̊`JS%{Gn+W\ˎNIej'>։_I+N)`5TSQUr:vTOIKvLc{~9&>uIN'v#*rýyoE0"/s^{3w??Mu<-|@c?7t[O H;S]SO7?hs7x}燻釣* ݛ>Rl~:~7fm]gi=9hdIj۩{%ߛE!T>xw`5{ܢ4<!ܣ43nʧ`e&1`LkԽzQ`թ9*6a}'+q/6?3Nշ{c\w`<O\e{So\ĿG?{A>wv*+ځieD?Ϩؠ*1;/c ?v'>i49jf_S0 P~QAUbw.X}FfR7=5xTVjR 6PKRЭCc5UBc/?#>}q0~Ћ4g>^^OҰp~JM C?xej[ڰۿ)n;9LV_\bz~*'G:K^Þy>'`5dMc=['m- y[Hy/	TͩwϹ-`bz8[#4͙5w׉~yG?*; e Q\}+RsS0G?opo CYeڂ4sշIrmׇ?op?rc	 ;NPPs7K~Ch/J1禣&)9ANJJnCXwy٣X΅Pm3o8|j݄<**4̚8 F;}Sq/FSw1*3| 1ջTU;5;
<_O#l:ýs)}οym6Ú̜X~Jj775=4;n{7aVjgᷯWF?a<kw%o;+o{}>djᷯ|o5e[+OݫK3i}jO|60#Un{x6!(~8n;9ϛͮNc5{w}KP	GvoyOOlwqeGwiόTu"wHN}tTMΗjԟy];OP}緅ߥjl{/Dk(kn	{^?vs^K}'~_h7b޽
׆ߺƿҏL[zw;oMEvpT6WE$vhcWJeЇI)ORO%o)cXG(t}^LKWm>N+[O^qUΕ{Eu_~'**X޽E2^'5VśYyF5PQRw1}7S󀏥߄R//14h;$sek3o8xQYJXýߍu;~sk:`^>x=u雄?Υڸ%;D?Rm-I}d\yץ+CorS~:u5A>SǥYJ+"q+զuF?ki-r??_~ܗuҸpozFߴ4Lc	KRýsŞO#0OmΔU,lNe?%u^jw&>%=q'Ղz!~
giCpX0E-ǧI̓~;2%F|F?@:$idXjp/r`k?,ML,Ouwy]։_tivE{~:^'}ֽzSYc~[?>pzbdw9w,ME.W}R[OHm^Xjc^ý\hs,Sc߱4U5~xHe{^>{j+^g kciJu郗4~ץKG,{/F?AXlʕˣ/,ϗvrjg^`KIil{ݢ [>!U\?>V>"n;)Rr2zd}=K_~A\}jǩTTl,n3ԽoI]KKi߅}4`K3Qiy]TT{G?_Bz_iƚy4檉]h7/5:՗>+)Ep\Ms(dyȧWɚ|l3ҮϙTDoĝ~uo:*W\WZ95eKj~VJw:4RKOL|GRUYW=!Z۽1~U\U    IDATo8Sϼ}]¿j7~xƟ|!weǄ߮Cwd^.i̔po{1<+E7xo)='ފq>IE%jwkjx"RIJ{/io\>e31_}.]R-}u.1nQug{/^.6e5˧㠱߯߭4JuRk.]Rʩ|-R*;Q~^P}緥^M-T>`xI[ITTo7Yi.HJzý}?G =$IXpV0ǆ߬$I*9{w S!f%IRQ^'zA6bJ}KRwd@J4{bw׷KTeYGo!FYITTs-hk7+Ij߈B_~$p\s,3^%IRQ޽=Y|\Jýw{>o^J݇/pG|&^%IRQ:=Yh{$IE5{}kK߬$I*9;zA߫$I*;ܛK? .WITTx=Y.;&^%IRQ:{0{$IEu{oF!BWITTww.\ >~$p^O,4PJ}1{;U${΍CvoWITTwW\ /WITTw+G!}e?
WITTxD0S*IM#\`J={ћFoU$Uy"zA^$)Uv:zAo}$p᧢dwi*I'A/p$F{+{`KT}=P,$cHA ;NWITTxwdp$F{=Y0%I*ƾn $I7?C]o៎C]b:{л{$IEQC}߫$I**<܏|,W\~$p?E!B;U$y,O?~$pb,*I
4zA{$IEu{D!FmKoV$n ů	YITTtwd[oV$vl4v{WJ}GdoV$~=zA6"f%IRQduoV${'zA6ڧ~-f%IRQۻds$IE5{}BU߬$I**:ܷ}mlto>.f%IRQ^El(f%IRp]F!U$eku,U$OCjs7YITTs+zA6K^~$p_q}l4vwJýw[<c7+IΌBQYITTsw 9f%IRQ~վ[.7+IjEKd{7+IjYߊB߬$I*9['ul
YITTt-RmKV$?= +~$po+;7V$=:V$_ +3~$pz-\[Jý\`ln9>f%IRQ-?tuJýwi[Qy$f%IRQ޽-(6$IE{%Sw+I_A[߭$I*7[|!zAVڧSJzýyoG JV$1zAVzw~$poY?qgJzý6gVJV|:6wە$IZ}vʕˣdV${/A[ITTowo<<zAVZ'mJzýs;ҹd$IE{ԯE JV$? +G߭$I*7| zA^:R]ITTk׷{cԷsJZ݇0kە$IZ݇0kWw+Iwd[BJTMYE JSV$F J$IE{/E KO[߮$I*5ܛK?= ;=%v%IRQ^᧢7duoW$ϼ{3zAV:,]I5_wD JcV$ΌAc7߭$I*7ܻW /v,v%IRQ>_gd/߮$I*5ܛG|&zAvQJZý/Eo N߮$I*5k4H`x]I5g|Y?tUJzýwϹ;RL|YJZ[B+Ij߈@]ITTk7:zAvڧ=v%IRQӽە$IE{m);ە$IZ}?qgt6wە$IE{ﶓgd/߮$I*5;m ;>~$poӹ`aJZýFo NoW$[E Jە$IZ}?ywe/zeJZýw37oW$Do N뤿	]ITTkRt3v%IRQӻە$IE{mV)Y)OڜY+IRu"+G N}Ƿ߮$I*5{ ;C]ITTkw.>zAv[JZý ;ݛ]ITTk7@%v%IRQe`TEJTe`R{jJZýw:oW$Kv@{߮$I*5ܽl߮$I*5{/zA~:TiJ:ý6ozi$I:}yiە$IE{Eo NҝoW$9zAvz]ITTk7xU6gVJ:ýOT;SgW$UEo N?]ITTkn=1zAv:n~$po7/zAvzw~$po)k߮$I*5;5zAۿ9~%IRQ>x[2zAv~JT>Do N9+Ij ;[]ITTk~3ە$IE{cFo R}ׅ߯$I*3k6O׎@_IT>C>zAvgKJZý{ӽە$IE{Go N;oW$> ?e_~$p/zEJe?zAv$I6?m>_oW$@*IR1p߮$I*5ܛK? K~$p-*~7zAvAJT>=,zAv:,]ITTkUp;]ITTkO)OڜY+I~ K~$p"^'zAvZGiJT>>zAv:~$p^s@0v%IRQ>SפMW$}{,5v$IEu{m)u[_߯$IJ?Do NʽoW$ݫ@CW߮$I*5['SmKW$= K}>~$p{IJFN5~%IRpA"zAv~$p\{]~$po߯$I*3|,5XJ:ý6gV*ODo No߯$IJԻr|JZýs)^~$pou,w|KJTx%?Q~$*^r\sJTxݛ@?]Ijrý}77J/_Ijrý翇߯$I
W^[eJNOZJ4Uo+@߮$I
W޽j?ywJTp K~2~%IUJ K ~%IUJڜMRZ ;_IfWjE-??zAvz~$*Ze{%SN߯$I
V<3WZpoYj+IRUv*W? ;k߮$I
V޽tYJT` ?e?շyUJTX?= K̓?~$*V{}+R7d}ο߯$IU>xvrJTXk@x͙~$*T{뤿@n_Ijýdu_߯$I
U^YJZt=(~%I]EwI3v%IU(}v: K~$*>գ? K#>~$*>  KKw
_Ijprͣە$Vg~J:`$Vgk;'zA|4~%IU ٚYjo+IRV'R*qZJT@s ;esU$~%Iysph,5$6ϩ}עdu߄߯$I1pN}? K~$<<n+zAvʕWoȃWDo R}
_Ijc: K>~$8b,u.5~%IqjY?tuJT6gV*Go O_Ò$Ի	Yj;+IRmL3Ry9AJT<dwE+IRmL3R}kR*Rm7,IRm3y	Yj[+IRm3Qâdi;"+IRm3QԯERo+IRm3QcFSjaIjcᾮm>vk$ixe>onJTCdGRsWZo<t7S}NJZ^4&}=b<u67,Ivm^fjԻT[돭d.obD}Ò
5%SLIn57ιJei80{KƳN㾔:z]Qo*һ?/Rӧt@U>;~%IcNNece%7p`:UaIR^ץ^Tytd4=L<S`qC7,Iץ^rW6uSߋ!2_ׄ<`$ҧR[?CdMz)}p@U:3~%IT'5Luo8lJPe{aIV_Hsg?3<rR>pp!jd﯅߰$i_O9+k_pƾ~<Ag'%Il&όe\w?|MJN7e4o	M.+IZҟLUP6Wpя)SjaI/z_rTɚ]|u.=1jJ7w|+ҧTw4D>@B:o~ÒTs/`gdYcG? [ׅ߰$Uu'=>lsfx
Tw,Ic􉗼0%np߀zw>5џaI*KQ9H4OPtY~Ò4͙H!F+,q"Pߋ~LAU߰$ҽ7Zmάŋeoȑml/yG߱$t/QW'dOLN䯆߰$o藃~73Dֽd{oX%/{;Z&
,ᾁNʤ@JesU4%i/m	KGzk{ZƾcIz.Z0ڜMRZl;.}%/N%3l>8"}97-??%U]z=`e0s6я/,%U7<3_zw11ڏdO 0y3cIcM3_.;z`S?~pDm_RY@ ~5w,)nץT;CdO]я1V'ފs.)0{;XhVUϼY~kE?e1^&}Od}X4%~^{Q->{jcֻ;4y]:#$}O>ԮE? _V/zE-Kץ^\kջ{&}#g`QK^ץy4)ֽ&}#|0yݫcIhόӿ7Ot{jynܣ*\`͙~˒6uVL{Q}wH=~˒	v	a27я5Z߱ToŸTy$)Bv=ᾑu=(YwqKyK^Ns/ #uY넿~AT_[ƹ^R}0Z~1Np3k[ƹFZЭtmάT~x}-Kc\sFZsGtxBdm?~ks6	ei\미.a5<npl~
ei\+W}0;-NpK?xu.!q-k'#w:LT4>E6Rry-K3
X^;O6ܧyD C)ۿ9aO?~fOQKw~A:eijѧ#ȍw:l<3я;^NOR.5ӆ[~~>E՗!qcχ߳4NrYHtT>'~AgK-KTyg#sŞw:lֽ{я=^oY}0r*}
k{?.,KΊjiS~fOa؃>Y}0ZGI>lOm+=߲4.TX~fOqeǼxQno{rkF^}S\~Xh߳{}024Vp'IPSw,^?>eie;ݐwQ址-qKL\ѓ1YLfh'd,3IL4NNLzMm@dFD1
 
ȪJC@lB^̩}U]u]?~Ub2^_;?|E{ޚIZ9]H	S!̄)>"ӻ1Zo:-|N}u3,9=Pk+J6ӊ^0;c:E3-28>?>ܣ[<2vViqx|>>7    IDATx<WϳHƴ?'Y]H	s?GEC^>"2: xl~,|V}Bi+Tս`ɖu'E.۠_ՅDqTVYJ$a&eI[Gٲ|Y(LDI#_>"YRǣGjᳺ(LܕkfFϴHOxkB:&|V}i5	3cظ;ݹ"Q~葅뜻*|V}YRu	3ϵH^=P{<l+MfFυϴHS}nckK(JuKZiѓ
)T>>4{mDiƍwlDqtVQvb	;c\϶HMӿ1|A.&һfJ룿>"^O+׎QG"O!ms-RǴ>	)txw.&	e+~/ma紎y]L)e\Js-R9z4!2|^}J=VX:oT+vmykr6@qR'5zi}g[.鞷&z$!WbO)~?\pVa?5|EkGR]yt9Wܧfu]Z2A?>"inxy4B>>t/98z]vxlDi2Z>>Ŵ>,+`Z-7DO"Q~YWܧjݳVܕ-摯AHcݕ(~÷\fawl+Oo.;,z!gvWO9FYI2|Eja{{A/>}&L=I.S*z '$|nw%r2^0ZǾ)~EG|Oy}}u3-24{mA*Jcn᳻+Q>Ϣ.̬ѿ>"HOF|VjT7~#~)|E&0,PgwWG}yIc;|E&i᳻Q܃=ou5`/y"/>-Ύ1t^>=(1zLk}-s.2toxA:]᳻Qܣb"&cu`xA:>K=0a\d)ӽh豂:O.E?foƪ=g]d)Rt豂G.|"{`A?z-LYY.O
᥈} \aYٕ4}"oB/UtYa:&|E8;1EqN_^0<]d1im{s/UحwaN+>)y9奊^<:zY\hW.=6˗Ld0yR^̋LZ8Xgy)!Ix0%?"jݳ[k}y)$k>anOxk̋<Vz_=>zL Ay^(5Ian[B="OՆ1y^(5IZkF:EϾwaн`^(5JkJ>"gS`Uc3sQkѭ)4J
}QzW4z"`vZGRGqQ_HLh=2|GfJYs=(5K/Du[D:]:Mzc 3sg{QkBs{_/C^bTW$,Ձ/^0	d~R2~[ʇ37{RQkw}dS2%3{g|RQk9+<75վ?Z23	IEq9@ѯ^g2{h4G`|jO*{M3ssKcT{`3>(5ME}{kO({?ӯ۾auf؊{M<>0*Wn,	7Ձ/+*LpP^>^z_Di|B ϖ[0̅g~Qkg xHOƪ=ɓPJ^07:s?(5NWG ]z}4V=1|ogT F?ٟtgp׵s |JcR=d23FØ~_>~e Je鞿W0(5O/Q<=BIow>;j~iDqOƆz6+~-|T7"Q`Qs?Ft}[	~Z2ܱ-zi2(	Rås<]<}~G=I7	TЎ/dBY[igeXԀJ0(I2)ѩ^!K桯).^^9iFqϒV~5ջ=٥Th]~R}bQwGGX᷾YZO{,<պg_|`%{Ŵ'J#=#BCS}f2^9=cQ3ee9aغtNߥrD'>)sW$jӎ,݋`^]Zv^"NuK\CT=Y^>m:{ʼu䯎?ˠEh}$"{oR KJ_WgWl&`s{ڡ0"zf%6}hbY{isN#0K{%({|LMn,STפ͊J_,/Xn>knxE>=izWn`qog{w/P}	&0{ҴdJեyȫ:K8wl>L?'2{֬ح>z~SiFOl+M=w鞿Wvi)~ h`ƚEQDh4QX4y=mt~)*-[i`o8'^+zRӻ>/KC?_g?Jt>S_w~77^WEGqOѷm -W.S9rg}QAoҽpҿTըAq*`^ܷo<svus?	ov?5zߏ	et]#5OyN}6:uܛuGh~'/j;WQg m_' =!> 0:gkxj$<I`\ ,ns|3ըII#G `IMtj(yȫƷJ [@ըQJG `I7ޭ5>Ci3 $Zfxj,,e'' d6}~}{g `ݩ5>c=N#z  eXNըaLâg `Q:.ըiIn	 d3lUkޥ5>o:-z  swFhZG>z  vڰ}|^tj8g )	NGq?_g uZԨyY=G 1u/\ߛ?ٿE kQLQg=\;E$ ꞷ&/-}9gEL |a[$|磸Au*ѳ	 5'5Eqt/X=  Vj3;R#Q9Is  AwF(sEG( @si~Rx7j$>G}A)*zV9ԟF(sg cWƊ;Q#a9KkG, 0ZއIa= o:-5GqTP)F d/C^ރi_7z|9һH}N3z1  6>?Q8sWF1 0:34f eظ+z6XӘ(s= k}NcF{<= ]{B|Y>;Qܥ?? 5ݪT$4f(;< fH8g+:ף mהƪ=McƢpF u䯆Fq3zq  ջNӘT)Cw  mLcF3~GYXots $>ῇwwe_B>/s $tZxirVQ`PU2H}epϦ (nL0պgeb^i=  H}ûKcS~/Hҿs  PsMwuoe3b~i'J鵣 "lj|Y_3G	 @MOzGxWiIz6~ϗn(H=S2~[  .2+v*9IA#M7  52l]}_QQ_Y6/QR= iyx։oQRߌ.<# ]vxx/iY:gŽ{ձ/Jr\ ̧}Kᝤ1Ƿ(yVQ__  Q<}deʠ}'NC?Wʠe  A:gKxiaZǾ>gEE @glAs>Ž)5O-{o7 )V}(a,x><u/R摯+eП LpPZ;5{#{#_HK LY}c3rcaX*	)epϦi 7qiG=.(#b%G2 gR1+ƽi/Xr{C iwK_}
ђ$\wc[ 0%n1p`ֲcS_HC?_J3} qQH/^s?Mb `'DcoqW#+v/gO`+ &iX[_%<~c12BOSN˰g) `~?wyO.޵>ɓ߲T[	 0a";}V?jnꠟ$Mz[	 0I[:GwYVzlNr5ej,NfSve/ &z2?tv<&<i2X^ LίjwyO))#S:W$ 0YwwyOuK->~*e/A+y(7%y/wyOyȧ/:yoђ$,-/jq Kd[{ZҿEe:Kuυ#:-z `8,=>)[KrQ}dм4oH룿SpK X9+{:%wX.u[u# G{2~]+#~ioIOY ĽW>!>g,]/\zhٱIokj 3QYK~\]W&͒_ڸ{) ֫K憗WM.iqk7JķiR6Aoɗ ̳ѯڣDeV=tzo)=9~Cz-A?&Jm9Z~ 0wm.~/|/$ۮ1XqKuejXɣgt; ko>oi3{S;Γ-kico,,gMcL>47"3}<쵥wI+NTwO?eǚRTkYw~uK fpǝ2ڳ{sxfjqA9oR}eAjj)E,G Hic[iYO_,K.wE[.-]i#qȫ˰=zI@wϯT<g%=J{w˗J.hӴR 5zJWfϊJuݣٿvQz[Y^nt/;Owi~wK,;Vei+ jw~$|X|n<oZ)dS  <Lq w  H@q w  H@q w  H@q w  H@q w  H@q w  H@q w  H@q w  H@q w  H@q w  H@q w  H@q w  H@q w  H@q w  H@q w  H@q w  H@q w  H@q w  H@q w  H@q w  H@q w  H@q w  H@q w  H@q w  H@q w  H@q w  H@q w  H@q w  H@q w  H@q w  H@q w  H@q w  H@q w  H@q w  H@q w  H@q w  H@q w  H@q w  H@q w  H@q w  H@q w  H@q w  H@q w  H@q w  H@q w  H@q w  H@q w  H@q w  H@q w  H@q w  H@q w  H@q w  H@q w  H@q w  H@q w  H@q w  H@q w  H@q w  H@q w  H@q w  H@q w  H@q w  H@q w  H@q w  H@q w  H@q w  H@q w  H@q w  H@q w  H@q w  H@q w  H@q w  H@q w  H@q w  H@q w  H@q w  H@q w  H@q w  H@q w  H@q w  H@q w  H@q w  H@q w  H@q w  H@q w  H@q w  H@q w  H@q w  H@q w  H@q w  H@q w  H@q w  H@q w  H@q w  H@q w  H@q w  H@q w  H@q w  H@q w  H@q w  H@q w  H@q w  H@q w  H@q w  H@q w  H@q w  H@q w  H@q w  H@q w  H@q w  H@q w  H@q w  H@q w  H@q w  H@q w  H@q w  H@q w  H@q w  H@q w  H@q w  H@q w  H@q w  H@q w  H@q w  H@q w  H@q w  H@q w  H@q w  H@q w  H@q w  H@q w  H@q w  H@q w  H@q w  H@q w  H@q w  H@q w  H@q w  H@q w  H@q w  H@q w  H@q w  H@q w  H@q w_&  #IDAT  H@q w  H@q w  H@q w  H@q w  H@q w  H@q w  H@q w  H@q w  H@q w  H@q w  H@q w  H@q w  H@q w  H@q w  H@q w  H@q w  H@q w  H@q w  H@q w  H@q w  H@q w  H@q w  H@q w  H@q w  H@q w  H@q RH4>    IENDB`PNG

   IHDR       }_   	pHYs    {Rk    IDATxwfw]fRP(EDHU;?rQXWTիr$ɤN!R LRgB<{~k$33gS^kkւ>=< &KÇMF9C;+hh}ybr͍o2   LjQcyoޯٻ#yhNY{.e{D?GkѶƴb_m   XSߌbWHRc-6(z->
m Ht|tXOj݃ٯ9   L{w֢m8䧣{Dt/	0V, a?]>š? &a?U7   FQ#w421Xyqm FL~*7/Z?K^wFQ   д[F|It\u5 â([S$ZKw)sD'    L򑛣%w4->ڟtl00
, d)|GZC.MYS>8l   @kXK]$|Kw).>EO+zbҔ="28    EHҸTѻr([e SǢ@C_?ۥ4;#*H    |$mnKΩ᚛qaZOM%EOd
   s{Y-}į`ٳ? >m P1QZҷ_,d    `xyА} IZqOE֓"*7 uh02ŧ^>HKfDe   fl#I[_qgfn EO7ΒgòO   `n?5ZͿ_18bp:İh_ϼ=}P=-&7}D    [apњY IP[vg`WG̿a~p,ln\1   ̃5HҤhٟmO?}-6 kЋ{Fk%}gd   <}_$i%ѿ氈>ƎE0\}cL ,ٗlV}T    󭪢{G$i*~S`X^>k_9+    R= $iZ^O`, lދ%/f   @kw4%_}<6 fЋŋ50}O   hJg~%NB&EFE0Ym ѕQ39,ٜ}d    ǣ}&$iBk(=}$6 ߣwZc+i-!}d    IuFϫ($iR1XyVq0r, ~;:$plû>5   dDew4,|a`?aoX%m:K6   w(6_g!I\wE|`ze/JR%qf   0b^4{o~w!Iܾ᚛|tmֻbh,N%m$   Yn?5ZɿÐInN1XyVʢ0AtX@*in-&}r    #npњY!IܢmwՁG>@6)}o6c   KgH=#2hE`WGq[ӇOIslfan\   ɿא)s#QmQ?_>tJc3bp   `97$i
j"hE`*k־I6%ͱѿ   cUw}{Iڟ}GG?@#, oh!S_W   Lj(yU]$MC#~%vm6|h-5}4W>:   	R)_~!IP韏.E`b'Z+~8}4zk   L=GkѶw4GrD6mT} Z:}4zM   LGHҴ>NP6)7<ŧ^>DJ{>Q   0z_{I:'a?wmROFq҇GIs{(   0*|0>DY};6}^F٧   0MG]o0, ,sڇӇEIs}/GZ٧   0κhIfӳ~yc݋\зF~*    X(Vp=$MEKwWg ¢07>Z3DIs}Л*>:    |hs}$MC^/G~fk57GkNáU6>:    γh{Iڟ}Gİ}l6*'ӇBIsXkߕ}t    |{ߝHҴ=}bO0ڟaP*vA>9    U?OChfAo;5bmԻdI (in->߸8    xnNIeU'?hWdi\YN>6    z(yU$MAao~f+e{myu'in:0    ,*4.]}l66XO   0+4-6~=,mѿOҜWG   V];I6c`, c\:Z>Itݓ0*   SUߵH4=O}9h	-}ȓ:G+b>2    Gޖ~"ISRo>Ģ0+$mAoT   0G߽HҤG>&YFZ^^>Iz^պ   ZZl~#I^e di3"}v[f    pT=$Mz/r#9YFl,L$=G{}\    4Ͽ	sf ɢ0ڟ}G0'9Y>*    SοInfa>xVmԿANsֿbEQ   и6d݌$Mrcޛ}<+6GӇ8I^>)    Ҕ/LInp=3hWo	d   i6{I]40, #lֲoao赲
   ;k$izrQ}, #{'Ӈ6I\+Zp1   0:At|W$Mj>EmQn/H$}/[	   S=_PʾI۩G=wh>Izmû>"    FVUZ]=$M`Smb	eDv9}X9,    yHǑImp_FE`$.-}H   `ltOp}$Mbcޛ}6@~'Z+~8}Hu	   9zٯ8ɾבIlS`E ]Ϧga?;{1   )'eHҤ=G<,6@7g_>j   `l8#Z3y$iZSG<E `՗3Ivr͍G   ]I_/xhLҿ5 },    Lα9G&o>, ycZ}P&{    0Q({Io>ށ)gHӻ|E0&uO|DUe    |p(IXK}S΢,J$=/ڟ~;T    XIIXkĠ}S̢bp郘Eˣڰ:H    x/~]$MJ;>ց)fH=Ӈ0i[G   P6^'$IPdh4FkaT7 }    LZ]ݐ$yF:0, {Q &M{Ke    SŊ!I߸$HEq>>|I\ETUQ    02:F${s&DEY ZwMi}n>	    Zz4~$HƹbWfh4j/iZ+vA>    xWzeZM$sweh4{'Ӈ.i*Yû>    ݗJԿBmF-}蒦e˲_    WUF_M;q>Ɂ)dhL=tIVETU    3?]$i+(b8>ʁ)chL.ij_    s5 .IƱ벏q`X9OӇ-i*xqO~   y;>IƱ>)chLץ[40w}1   `hKJ4fuOP	L6@#c>Tje˲_{    6SQ%IdL6@#+JisFTek   vJ$U3>)bhDZ'j?   gY=$So\}tSĢЈJoQ)u   `+Ug*IƤdh4EC4n8:U   `^Eۤ9I8=fhԮ\{%Mzݳ2U   `.{'I:}GL6@w>`I\зFٯ:    D_HQOl`XjʲKԊ=^S~   I؝ZS=$zU#muN@p%Md3cxٯ8    5_}p]$xWehԮ8mÕ4/]z   Єα~%I֓Ok`JXj%Õ4iuzOD9~   hHau_~/%IZkghԪOIX6~   h3$iT]40%, 9}&1W   $>G%I#X?>)a`Y郕4I/]Z   ꮏbKQs{h`JXj郕4)uyoDUf    $w'gWI(>30%, ^<>XIPeQmXJ   0"z~<JFbWfhԪ{_V70^:   0JhwW4"^}2S¢PI>XI^ҥٯ2    #|h-1JFEfhԪ}V9=0U   `D_$J1dhԪ8C4+^ӏd    gߑ~%IPz,TEV~?>TIĉs~+   ('ZKwʿӒehԪ+҇*i]Oٯ/    cWHIEc`
XjZkP%[1e    WHw[YauiL6@Z0}ƪv_]    {֒$)jÚmZGyn:.   `/3KV1L6@ZIq{g    rO\]$edhEV4.xTٯ,    |lO4Y`U@%Eg    LWv˿h4PJW   0ih/Ij26@, QwDTe
   *9Z~&IMehEV4^պ_S    &XO߃IRSY`U@%r[   0醽h0Ij"6@, Q{_O    DF_!%i*h4PJŊ_U   )һbTwm&Xj=PI#~W   i3F7ߏIRY`U@%Z9   `J]EۤߑIR]Y`U@%RC~j7     K~O&IuehEV42->Gn~%   rUwC{"LjȢ6@*iTu    fn?-LȢ6@*i|0u   ߛI|ghEVn;GW    K(v3I, Mh*{\    Q$i>h4PJʬsETUk    ϬDзߣI|ehEVUlُ   QV>tMfߧI|dhEVc_?    ~&IE	mZeTRF^    sVuG$ikh4PJjbKzW    6/߭IfhEVt[O~    `t5Iښ, Mh*{{_9    bFklY`U@%5Qx    [ewm`U@%5gn    h6Iڒ, Mh*{~    `2Z3$ish4PJbFW    U?O{͢6@*   OF߿IdhEVTgQUٯ    bpwp9Y`U@%ҝ|rU+    hwq4, Mh*{Oe^    P5 >NE	mZeTRňrz   @#}(NNE	mZeTҼd(#   TD$iY`U@%wKdV    и{IҦh4PJ>b~    y^;:Iz, Mh*{歙1|ٯ    {:Iz, Mh*{޹:   @/N-6@, QueN    zZC$=Sm&Xj=PIpYٯ    E7N)6@, {_#    -"}_~w'IߛE	mZeTTC9    <-_H͝>6@*ikxL+    #sԻ$;h4PJ6^DUeB    0Go֢m$߳h4PJڢ哫_    ys&>O-6@, -W    B~*廦I, Mh*{6t_    kKדY`U@%mnû    x)>w{dhEV9uO|+    cix$ɢ6@*i-)g2    0:Ǽ7OTghEV4W    X+9Z3$Mom&Xj=PIs}Л"    ^I, Mh*{6̂~+ٯ
    Ljó_Ӟ~'i*h4PJT?    D]$Mgm&Xj=PIUǋj=    DX?IӗE	mZeTsտW    &RC$M_m&Xj=PIV7FW    &S9˾4]Y`U@%=[Uf    0ц+J4]Y`U@%=S/~    SsJ, Mh*{%GW    Bh,̿4Y`U@%}o5    =    IDAT#6@, Q~-    `T%M~m&Xj=PI_	    J?~?(ih4PJGrDUe    0(~O(ih4PJmfa]:    T_u`]΢6@*ic?*     ~x}͢6@*QmX*     1sw&66@, %_    Ue{CIE	mZeT=(     ;NO;4Y`U@npٯ     *ڇbˢ6@*Mo_Q_    W]~(ih4PJs    9tzw=ʢ6@*Mg#ߙ    0|w&+6@, 4,}    `:Vɢ6@*M_SGc    Q-њY~(i2h4PJS|    ߟ(i"h4PJU    |h-6~QghEVb.QOd?    ;FIE	mZeT.~   -T?ZKOg4Y`U@XkTُ;    z|,QxghEVW~   TmX;7J, Mh*{W~;Q    ANs4Y`U@opُ9    0OSQ,{Q̢6@*Mv~s    `/]~(i<h4PJg?    <XGIE	mZeT9*q    ~)ih4PJpYُ7    P>=^~)ih4PJY?QUُ7    P%"%Wm&Xj=Pi2     jVbGJ, Mh*{>k    !/Kɢ6@*M^ûX    '#6@, 4Yو~   .IIE	mZeTwH    ҝ'%~m&Xj=Pirj3>    TK~G)ih4PJpُ3    ڰ&ZKwL4Y`U@ɨ}#2q    JIE	mZeTw(    ɪuFkvF76@, 4zO    fuh͢6@*N~   Q{Hz, Mh*{x>>    .34RhfhEVƻGg?    )7ZM4zY`U@^#    ~)ih4PJ[e?    *'ZIǔ4ZY`U@%Qu7d?    LIE	mZeTz,~t   W~h,Hϔ4:Y`U@1lNQ~t   1974%Lm&Xj=Pi}[    `LqIɢ6@*Yj}ُ-    0FڇbݦȢ6@*W>    cfpwF#6@, 4F,rMُ,    0nam, Mh*{9W    `L94SR~m&Xj=Pi|0q  S9TTO}cދ;ωm|wûϛ_;gl}n_	 @]({NIY`U@}Л"*q `>TUTO?2,31ѿtI=s{}/DG׏DkAoŊΡݓ(zm/]:Ѓ;NWDʨǳ `6swrh4PJd?  Šwp1_lvAs}/E+強xh;c~1\yfke  o旸%Tm&Xj=Pi+:  a/g.tO)}ufϏ=gzx_Y @z_PR^m&Xj=Pi] `*Uj1~֢mgIXKt>?2ʇt &Zh-6}E	mZeToՆ5ُ) B͚bp1;GDǋgimѶ>M=ѿ(WQ qJ$dhEVFi~D &JY]|ZCܧfw{O J#DkfA', Mh*{h7ۻ  lt_Gt>_U%;Dw~p  lα9xm&Xj=Pit `9C~:ZIPě>哫E 8IghEVFʳO V=\wDtOOwU_6a/Q Yޖ>Ij66@, 4&f?  #|le94'A+^>i<*2n<6 `n=1}^lm&Xj=Pi4_w	 ==$?3&ED3o$! WOiˢ6@*`Kv t*1|kѻdQ٥Lҝ{R _}pl&, Mh*{=ُ% @szqztOH{`,X1~+  /%3fh4PJWُ% @ãߞ4KΊ}~tS6>  Ӣw?aɢ6@*VC& E_u@t>h,HM60:Ǽ_-UUٯ @uDkѶ3ڳh4PJI yS{r&+*~  j=]Ϣ6@*N9G `TǢ}/YtQ>|m 0_?oI=6@, 4: `:1|sDɆ+R Dszh4PJ#(\8 ]Uˣ{GlyJJ}Лbp"A[	 7>_I76@, 4uG `N6^: 9}FbWϾ/_S -7Fe鳕h4PJG E﫡MS˗GY l33h4PJ{ Fk{h$[RmW `TVGkvzh4PJ/ُ! w)W_ݳ>;JҸW,iX1d  s=szh4PJ,{C a/cޛ?#IXϫbp0m }$, Mh*{Rnޝ Sj?˖Ee鳑4~Kb I#~)}v4Y`U@7 SZ{_34m˳ g5IghEV*/A `ʔkni֢m!Iϋպ W͢6@*;o? `g In;G^Q ]6~l$i^h4PJykn~ )0J6Ҙ>u1\ua h-1}N4Y`U@ڇ- a_M{$mI=}  gˢ6@*ԿG 䯈:󎤭I #mњY?I, Mh*{RBKw. &L59y}OG# r#ߕ>I, Mh*{RuO@c Lۣs4-~~/]1g9 qFL$i^h4PJ7Kُ 0{ƟFkfa|#ڇ5Gn>~ iT󐤭Ϣ6@*5[ `_"_>HJhѶѻ^i L%g!I[E	mZeTjy 㪪bp)QFR~O& `T]͞$m]m&Xj=P57f?r EYF҈0 D?Iڪ, Mh*{Rszc G{ڇ5 }4uzwT> )0GehEV^ُ 0.A: _>H/f^ ({M#i˳h4PJha
 ~^"iY)b> 	ֿ|y#ih4PJ9׳5 `U=룾&JVEc PHZGҖehEVip5 `n;%=(}f49m-_> 	=I[E	mZeTjvt j}97I[*) `qI#i˲h4PJ=ُ 0j*_?hv!7{V4u|gTGO> `TUx]#ih4PJ7\yVc j9WgIU+|#  +Iq$m~m&Xj=Pފ_1d?f t\ }F4-!7} */gIE	mZeTi~ P(:Fl"I"a L>Hڼ, Mh*{R>/ 8#/MK$;ΨZf E\#ih4PJUa? 3$=[">-1>sghEVk T~hyD6Uǋcx& 0_?(}4, Mh*{R}( VUڧdYDܒbp'( 0h-)4, Mh*{R={`D9~ U=IڢfDG) 0gY<#iNY`U@zG hPh3$mm/>V1S>tM#inY`U@zwy 4dpqZc!IUE+ 0fڇl#iY`U@X2
 Ӡߎ>{HR?+QOd |_}HtOp|Cf06E	mZeTgec ԬZP?s$UVg 8n;ek&;yO86@, 4W]X 5'eD~of @kbx9ѻdqt(>H, Mh*{V,ecS4h-.}搤&+(' jPeUDE7͢6@*oS>H u(_=kHRV^/;Oc `kQ>?sfh4PJӲ) `U9wIʮ%Q>tM QaOD3o	IYgΣ=[ jqI1I6$Q[31gttI>&;ӉLOڎT]vMQM,,@j)PR"[
R,VΩ[{>z_>GP7Irh#)k3t);џ$IaՓGg ,_;ϒ$釪ݟMs={49T"6P1;s7s$I3lǟ]`4Ӓ$jT{Mm86>{>H*CIY^gGN$iF qlO$)Qn%oh\;SgŞ P_m$ȡE/TȊ秪H$Ifx93W~u4}ے$5jJ5Ρ/@8T"6P1)I4ڸ*u/- {Kt?%IeU4i~.GXlϡ9腊m<)S$I{NPG;t$-톝44ip?>Ávrh#Dm$e-zbFcDJ$iM'i? u]4}$-4}hStZ\w/Ί=5m$ȡE/T,^oџ$IZhQ|	&i?%I*^}ky_uRegFRHZB`g$IҸ;| hz$e|'M~Σs~;uzEm$ȡE/T,k?#I5| hYI/I⛌tiqU;h~u/ FRHZBtx$I5jI3~=| hRKMii|ip韥)oN FRHZB.xo'$IvQ/k$-Ū[v
uѳ6JFR֢*gџ$I& ml WL-躕;jV*|FDqh#Dm$e-zbζOH$~o$MMFi4ڸj೷zY,|,m$ȡE/T,\ﴷG>$iWRw m6i IjbI~+i|˙izyKx~XH*CIY^X|$IsUM7 =xESATǷW/Lë>gzP3m$ȡE/T,[?I@ ?:t4}ѣATޣiͫW2ph#Dm$e-zbavTUџ$Izw ~PwS}#BԚt44XwP?u/[ MFRHZB$i6};ͩ>=*$IQM';jn9+>w[Sgnm$ȡE/T,֏G:$uy3|_ *Ij~ire:r9fm$ȡE/T,p}OG$=MoJ^+ ܆W}0zlHf\5؞&[6U{ ?ȡ9腊;?I4U}+uW*|W `׍oX$-h節SggFRHZB~?ICUGSo? Ms{=#]z4tN^yp9 u'~ H*CIY^}Cg#I(?$-v.NMS ̆CI%rh#)kinF$}_Oy NySJnHVVɖiqs|H*CIY^=Hkt) 1Ǌ$58MmPKߟzO{  qh#Dm$e-zb[Hl?m.z? `vFO/Ԩ[R}ˡ9腊3zK'#IvǾG<|7 `%L$?#^s%ǡ9腊]=ri'#I;m ytW*UO>=m$iIW?Lm\á    IDAT+p >6JFR֢*v]ߋ\$IRJip	 ȫwگ4FIZMimso:gW@/#g5 FRHZBŮ]b"IRvnN @"zHRدR}&m$ȡE/TC?IZ_IC_ PGVm(M,ϥSWH*CIY^5#KF.$a'NzcN @Y^=$i&Uçdˆ4ڸ*z9@8T"6Pk^"IR\} SޔҨ=$it4tYgT ph#Dm$e-zb׌?1S$7_ kxǑ$=k;J5ΡFRHZBŮ>)S$UOܟG,|  kG%I?&w6ϥS	 ʡ9腊jHԾ[  KUoNZV5|*M&6=u?`1H*CIY^xn~/3$=*| `i}SG6i4jn} 0Km$ȡE/T<'F&$鶯! ,=ë:zLIjHire;JC_3 rsh#Dm$e-zMHԮ&;;  KeirgUu]WοIݣ^ 8T"6P캇x$I?w  ?ޣ#KRmI-h4XwPH/g ,m$ȡE/T<YD$IjUӇoKw  =$-r|Ӛ4OS7Ί=FRFRHZBų;%IRi@}o?/zzI*\}kyg?]s@8T"6P&߼:$5?1|P/#^ǷD0IOP׭Lѯ uFRHZBųX#IW=q_@OQ&iMFi4ڸ*zO @8T"6PvNoIT>ev$M=o>#.;ͩ?K H*CIY^xf[!IR+qiy?4oM;/Ks;/ -FRHZB3vn!IRS	 _#o3bMo|:>Σ_ 6JFR֢*e|CƷD| c\T(MޜFWRo|Y 9T"6Px!IR㫞?u{QAV<?M5zIl:Imx9ix_= [H*CIY^xzO~!IR@>/SǜT'KU3= FRHZBm8.Ӑ$M  ѵGE:VU'dˆW} FRHZBӛ{M!IRUK`P`WHz&`AzYG߷ @m$ȡE/T<{\$)O= t=IM<v>d?8m$ȡE/TSտYH&;v}'ھ5M,ϥS> 6JFR֢*B69t47ǟx4?wS= ,ym$ȡE/TS/$$M{g= ?7S)(-8MmPKߟz FRHZB?5}BF69@;o[=ݪzR}> 9腊2wJAg!IRS؟ RH4j44\?k^ ˡ9腊迌$$IjdO ?RO=KkJ~/u7 vqh#Dm$e-z/OB5q?>hSQmj:NmSg/  FRHZBzv'!IRoDz'|JahT4Ν{L ~CI%rh#)k?hD$5G>7aѣQPyYKQ/ vCI%rh#)kjI4&߼*~;򈴫Uçdˆ4ڸ*W@E  FRHZBN}[ IR ?l|8MmNM{  FRHZB.AF5}Y,|G@;J5Ρ  99T"6P=N$IjTC|g='Svǥ
V=Σs=! @im$ȡE/T|ώ߷.IfS3W|g3葩LUçwh4XwP?{ X
H*CIY^G˗jd IRc~; <C^|=zljMimso:'<8N}[3 XH*CIY^ةw?Iӎ/	 +;ztj7o+P9 u}aw Pm$ȡE/T48=џ$Iit1 vˣǧx4\?kLݣ,{ 36JFR֢*v]sD IR3R׆v lJ~m}44p=¿ qh#Dm$e-zb]WD
$5: ,Gv5C?I)uV  4CI%rh#)kX>@ IR#: ,a/JѣM;o4kHCs rh#Dm$e-zy{KROA7|Yl?&[6u+S큩{+ H*CIY^x^@F4s ei#^MFi4ڸ*zwx 9T"6P4Ϣ?Ij_5|jO 0ßzM'imso:'<x節;  um$ȡE/T<oߺ$Ik|Ӛ 2޼.z.Ǿ_9??W;R  FRHZBE$վ~9|tOƃԦieC]2G2  =6JFR֢*v,G$պ#ws цcSct`AzY,9  9T"6P]ȗE$վU 0kbt6sʃSs á9腪Z' IRSwg: 0Huz|KC:(#  KCI%rh#)kU>џ$Inr9 db4iVL-v
ߓ+_ %͡9腪F_Z	HTs iD^wΣ8>  P?m$ȡE/Tm7g}' IRmz Z,MR!;鷿Ʒ5'N}k sh#Dm$e-zjjCџ$Im| JkYgj}kyYK/ @39T"6PYI?Ij[
 Pg2?ie_u{Rw m$ȡE/Tm;m/IRmz8uV>IoLi:޽9i|ii[,#  FRHZBf(%Im'r (m|˙:IMR}3 sh#Dm$e-zj$NY uFYXmߚ&w^6-kL#  š9腪Ʒ$ղRgY Q{ks  B8T"6Pt/IR-}iu   `9T"6PY5x2%Ie>   }m$ȡE/Tm$I_"u    >6JFR֢O/IR-~^   `aH*CIY^jp^Z6s   qh#Dm$e-zjцc^5/	    ,CI%rh#)kU[7~zIj3   sh#Dm$e-zjCF?$Ik	    ,CI%rh#)kU[Uǣ^;3   sh#Dm$e-zjE?$I~7u>   X86JFR֢6g$v   8T"6PD?$Ikpp    ǡ9腪WuKTǽ.|   8m$ȡE/Tm4.IR~   sh#Dm$e-zj7~vIj37    FRHZBFG$ժ>   X<6JFR֢YgJaKTz'1~   hm$ȡE/Tm=O.IRe3   sh#Dm$e-zjio~rIjK7    FRHZB6 %IUë>>   6JFR֢~\Z[   ph#Dm$e-zjUO.IR}S}7    FRHZB6}KT>   6JFR֢>xcKTƷ>   6JFR֢?$զ>   6JFR֢V+j$զio    ̌CI%rh#)kUt}sKT9E   qh#Dm$e-zjܒ$զ   rh#Dm$e-zjܒ$զmkg7    FRHZB&O$6?7   rh#Dm$e-zjцc[?߅n    fˡ9腪Mv
IkN|C   `H*CIY^drg[z4Ίn    fˡ9腪MjsKTJ   `H*CIY^ڤ~7%IE^>   =6JFR֢֘;~nIjn    fΡ9腪-Ǿ6%IM>   =6JFR֢}_E?$Iw[g7    FRHZBs7%IM#_>   =6JFR֢\觖$U'6    y8T"6PsԒ$բ÷m    ph#Dm$e-zjUO-IR-qI    6JFR֢vnSKTF8|n   CI%rh#)kU[LyUSKTW>   á9腪-[o~jIjQwm    ph#Dm$e-zj-O-IR-Ks   <H*CIY^"O-IR-   @m$ȡE/Tp,IR=Rg   @m$ȡE/Tm=u,IR-7|n   CI%rh#)kUN}[3KT)|n   CI%rh#)kU?E?$Ihr%s   |H*CIY^`pE?$Ih|G6    8T"6P~fIjp   @>m$ȡE/Tm0F?$Ihp6    8T"6Phq,IR-   @>m$ȡE/Tm0iM3KTzJ    6JFR֢6o(%IEU?>   ǡ9腪&w&%IEݣ,|n   CI%rh#)kUL1%IE6    8T"6P߈~fI|   @^m$ȡE/TmPu̒$-'    FRHZBi2~fI|o%|f   CI%rh#)kU'$M6~n   CI%rh#)kUuyMKT&w~*|n   CI%rh#)kUV\KTƷ>   ˡ9腪zO,IR-m<)|n   CI%rh#)kU'$=:|n   CI%rh#)kU'$ׯ    FRHZBtĒ$բU    FRHZBtĒ$բ>   ˡ9腪W| %IE;S6    y9T"6P53wKT7|n   CI%rh#)kUӍ9"%IEs7|n   CI%rh#)kUӍ6~bIjQwm    rh#Dm$e-zjgD?$I   @^m$ȡE/TM7'$N}k    /6JFR֢|'$VB    /6JFR֢|'$Nzc    /6JFR֢ܳ>%IE>   ˡ9腪&]Ē$բ	?>   ˡ9腪[o~bIjQ
    FRHZBtm_~bIjQ׆m    rh#Dm$e-zj{XZ=5s   H*CIY^ھ5%IEݣ_>   ˡ9腪wXZ=s   H*CIY^.;O,IR-   @^m$ȡE/TM'$u   @^m$ȡE/T|YJT8~v   CI%rh#)kU$զ??   ʡ9腪}aJTG,~v   CI%rh#)kU7%IҮ=   H*CIY^{~+IRm|u    /6JFR֢&|UJTD    /6JFR֢&%IҮ=u   H*CIY^{OE?$I{On    rh#Dm$e-zjއ6y%IM>   ˡ9腪zyJTz'1|v   CI%rh#)kUN$6VB    /6JFR֢&$6Nys    /6JFR֢&%IҮ;m   H*CIY^D?$I   @^m$ȡE/TMF];g7    y9T"6P5Y#"y%IMn    rh#Dm$e-zj26$z>   ˡ9腪H>   ˡ9腪z5y%IMK>   ˡ9腪H<8|v   CI%rh#)kU9$i^   @^m$ȡE/TM;m+IRm    FRHZBdm$IF׭    FRHZBd~u$IhI   H*CIY^wʛW4   @^m$ȡE/TM;W4mm   _c    IDAT /6JFR֢&+IRmqi    /6JFR֢&$6M   @^m$ȡE/TMF?$Ii   @^m$ȡE/TM=+IRm~   H*CIY^{OF?$Ii=   ˡ9腪ɺxJTF   @^m$ȡE/TM]$Vu    FRHZBdݣ^$ժQ/    FRHZBd#_$ժ    FRHZBd^$ժ)o
    FRHZBhs{E?$I;7    8T"6P5]'$6?;   |H*CIY^.O,IRm\   |H*CIY^?Ē$զ<|v   CI%rh#)kUUD?$Ii7|v   CI%rh#)kUUO>Ē$զO    FRHZBtcD?$Ii|g7    8T"6P5;wD?$Iire   |H*CIY^nmO,IRmw}    6JFR֢>'$6M+|v   CI%rh#)kUM\Ē$զ   @>m$ȡE/TM7O,IR}Sg   @m$ȡE/TM7'$Vuxi    6JFR֢wO,IR3   <H*CIY^n|O,IR}_o    ph#Dm$e-zj'G?$Iο	    FRHZBt뎉~bIj?    FRHZBtsO,IR^   @m$ȡE/TM7XZ5   <H*CIY^nǿ/IvMk7    y8T"6P5?~bIjOo    ph#Dm$e-zjĒ$ժ7o    ph#Dm$e-zjy.%IUo    ph#Dm$e-zjY~bIը>   á9腪z'$vu   9T"6P5]蘭~bIjW7p    fϡ9腪Ǿ6%I]>   =6JFR֢'$v>g8    FRHZBx+LYZ5p    fΡ9腪Ҩ̒$ժ    ̞CI%rh#)kUX%Iڽ7~,|~   0{9腪~3%IU;.	    ̞CI%rh#)kUL5%IU7o    fϡ9腪&^̒$ժoo    fϡ9腪&w]̒$ի u/    ̖CI%rh#)kU7}"%I]ݣ^>   -6JFR֢6m\̒$ծ)o    ̖CI%rh#)kUE?$I	    ̖CI%rh#)kU<8%I]K,|   0[m$ȡE/Tm0?F?$Ikǟ=   -6JFR֢6,IRߴ&|   0[m$ȡE/Tm;,IR|   l9T"6PA7F?$Ikm3   rh#Dm$e-zjѯ~fIjW}$|   0[m$ȡE/T0WJUԒ$իJC    ̌CI%rh#)kU[TO-IR3   qh#Dm$e-zjZ_s@   `vH*CIY^bЦ觖$v   8T"6P[~jIj   8T"6Px觖$vx|   `vH*CIY^b|O-IR   8T"6PcZ5}   8T"6P3Ԓ$ծjC3   qh#Dm$e-zjkSKT*u'|   0m$ȡE/Tm18=O-IR-}q    fá9腪-g+%Ie~+|   0m$ȡE/Tm;O-IR-\9   l8T"6PEG?$Il~.|   0m$ȡE/Tm=GZZ69   l8T"6PI[5g}   `6H*CIY^ڤz|KsKT~3|   0m$ȡE/Tm2}-IRSgs   sh#Dm$e-zjɝE?$I{k8    FRHZB&O~nIjY_	    ,CI%rh#)kU9"%Ie |   xm$ȡE/Tm2-IR-^?8    FRHZB&;m|In89|   xm$ȡE/Tm?7[Z69   9T"6PI7F?$Ilms   `H*CIY^ڤ{K[z6e   qh#Dm$e-zj4D?$I{k8    FRHZB6G?$I9   8T"6P\Z6XwP   `qH*CIY^frO.IR-    ,CI%rh#)kUیo93%Ie[?>   X6JFR֢]{TKT&[    ,CI%rh#)kU?\ZV=@   `qH*CIY^fpF?$IR}g9    FRHZB633%Im>   X86JFR֢O.IRmwg9    FRHZB6#~rIj    ,CI%rh#)kU,_d$ղO    ,CI%rh#)kUUO>$ղq    Ρ9腪)%IeӇo    ,CI%rh#)kU7_$ղjT   `H*CIY^ht.IRmY   8T"6P#%Im>   X6JFR֢6\g$Y   8T"6PQoͯF?$Img9    FRHZBF^$նW    ,CI%rh#)kU+x~JIKT˦[o    ,CI%rh#)kU[U۷F?$Il    ,CI%rh#)kU[MrKTۺ+_>   }m$ȡE/Tm5޼.%Im>   }m$ȡE/Tm5ڸ*%Im>   }m$ȡE/Tm5O/IRm]{T,   `9T"6P?~zIjxE   FRHZBV$ն÷r  cޣv/:!SkjXv0mLS4i*Z45d:SY3gP@9"j 
A!<`H j(>𛅴1~s^׳ߛg mm$ȡu58^667v9    ǡ9TBzD-_6xٷ9    š9TBΖwߖ%Imx|   {HCIEK/Tl?~Izg9    ǡ9TBk$M/}Y|   {HCIEK/Tlz1_vjz   {HCIEK/Tl?J$>    6jFR:+_6v9    [FRH*ZzZg%Iu##>   :6jFR:/IR   sh#Fm$-P}n6N?Izs    ̡9TBwܐ~$g9    [FRH*ZzZw/L?Iz   sh#Fm$-Pه^~$ݷg9    [FRH*ZzZw4$Iu    lCI5rh#hjݍOV	H'p|   5m$ȡu7<)' IR<   `kHCIEK/TnpO@^7<   `kHCIEK/T-'_N?Iz3   qh#Fm$-POg IRogg9    [FRH*Zzbn$Im>6<   `HCIEK/TM/?6$Iu×w|   km$ȡ*&AHF>3>   56jFRt7BH&<   `HCIEK/T{RHf:)>   56jFRtþ1$Iu/s    v͡9TB?,;OA޶,   `HCIEK/Tkq IR   FRH*Zz^kߒ~
$I?    <<6jFRS$׍~~|   HCIEK/Tkro$In   FRH*Zz^S~
$s    CI5rh#h酊{S$-tK|   HCIEK/Twb~$   Crh#Fm$-P˻nN?Izħ9    ͡9TB}7^~$[=>   xhm$ȡ*3s$MwD|   HCIEK/Tgr履$In~y   Csh#Fm$-PqѩH?Iz   FRH*Zz>ã7$Iwe783   FRH*Zz9]7$Inx3   FRH*Zzwܘ~$Yϋs    CI5rh#h酊'!IR^<   9T#6^Ǧ$Inw9    Ρ9TBM'!IR[yS|   HCIEK/T?~$<   9T#6^QK?	Izt    ȡ9TBn>I?Izg:    FRH*Zz",$Iuӿ:<>   x 6jFR4B^7<   HCIEK/T<G$InqǍy   9T#6^xɹ/H?IrmL   HCIEK/T<u?~$	Ot    ϡ9TBg!IR3   sh#Fm$-P 604$Iu<?   6jFRnkOC^7<   HCIEK/T<ߜ~$?    ܟCI5rh#h酊7!IR-   }HCIEK/T<YK?Iz?    ǡ9TBŃߤ$Ioߍt    FRH*ZzӐ$>tR|   p6jFRl}[yH,>   CI5rh#h酊6{C^mnt    FRH*ZzMxUyHG~G|   p/6jFRmI?Izgg:    rh#Fm$-PFC7O3   {9T#6^xh}[yHfyS|   p/6jFRX8Gw$In9    rh#Fm$-P\~"$<3    6FRoׯK?Izt    HCIEK/T<ɻ8D$I}ӟ    8T'6^xx7|H    8T'6^xxW|OHם    8T'6^؅8L$Iu;?    8T%6^ص>~&$   HCIEK/Tcg$IotS3   `9T#6^ص{I?Izg:   sh#Fm$-Pk3~%L$I}    Ρ9TBŮ{RH<>   ֝CI5rh#h酊-8knH?Id7?   ֘CI5rh#h酊-.wޔ~*$+'>   ֙CI5rh#h酊_^H   HCIEK/Tl}~*${t   uFRH*Zzbkg=7T$I}Ήt   uFRH*Zzbk`Hw}*>   ֙CI5rh#h酊-:kn1O?Ir{T~   )6jFR[ߦ$Iot3   `]9T#6^غߚ~.$g|   +6jFR[7}!"IR]ur|   +6jFR[7>E޷L   XWm$ȡ*nxE7v    ȡ9TBn8n6N?Iz:   rh#Fm$-P{HHu   HCIEK/TGޔ~2$%g:   :rh#Fm$-P{&YHx{|   #6jFRgƟO?Iz򋟎t   uFRH*Zzbz\HD|s|   6jFRicGߝ~6$k]~   6jFRoqg#IR{   nHCIEK/TկM?Iz_    ơ9TBg#IR[vM|   6jFRo~6$ܹ|   6jFRooM?Ihxܿu   uFRH*Zzb#IR3   `8T#6^3O]~:$g:   :qh#Fm$-PgW*t$I}    ġ9TBŞ#IR[67u   uFRH*Zzb_##IR_=   .HCIEK/TCuEHƧR~   	6jFR{nq#IRK3   `]8T#6^skL?Iz3   `]8T#6^swo$I    ¡9TBŞG&:   :ph#Fm$-PG~GHDS    9TB^-Gw$Iorџ:   ph#Fm$-Pw7_~B$Έt   uFRH*ZzbLxe	Iw    9TB$-ou   9T#6^;~B$5u   9Gإz    IDATT#6^KM-g$IRws   qm$ȡ*K?#Izg:   @HCIEK/TGOK?#Iz⶿t   9T#6^{,$IIyW:   @HCIEK/TѩH?#Ihxܓs   em$ȡ*Ͽ=$Ij[[|   ̡9TB6-OI7L   hCI5rh#h酊1S$   26jFRcW$Io:6/>   ZFRH*Zzb{z^)IDc    rh#Fm$-P=S$g>'>   ZFRH*Zzbܿs$s   Qm$ȡ*sK?'IzK3   Um$ȡ*SI޷|7>   ZFRH*ZzbLs$G?>>   ZFRH*Zzb^$IRxv|   ȡ9TB]\$Io#s   Em$ȡ*OJ7L   hCI5rh#h酊5-'%IR[mnu   8T#6^^,$Ij˿;>   ZFRH*Zzb{NyzIID~9>   ZFRH*Zzb{tIIDK_    qh#Fm$-PQ`I$o(>   ZFRH*Zzbͯ?/$I}Ǝ\   hCI5rh#h酊7}g%IR\   hCI5rh#h酊7~J?+Ih    -qh#Fm$-P%I7   6jFRl;OK7   6jFReo8$I}   6jFReLTiID#    ph#Fm$-PQ-~Z$5M    ph#Fm$-PQ'$IM4}!   
6jFR_M%IR_^~   4¡9TBE9O_~^$?    ph#Fm$-PQK&:   @HCIEK/T3~H?/Ih    -ph#Fm$-PQJ?/Ihza   6jFR<$oxg~   49TBEY:$I}Ǝ\   ;6jFReͮ:9$IjQ    }FRH*Zz9~b$5_u   sh#Fm$-PQ'$IM4e   wm$ȡ*
۹ͧg&IR=   sm$ȡ*[vMI/v:   @9T#6^(ovg&IR\   36jFR3$g<;>   ̡9TBEy~f$5/u   >sh#Fm$-PQn>M?5IzKs   HCIEK/TԱS$M:   @_9T#6^cvkOM&   Wm$ȡ*ꘜS$g=7>   ʡ9TBE~j$5W:   @_9T#6^d]7$Ios   HCIEK/TԳs$FAu   >rh#Fm$-PQפ$IM4<I   Gm$ȡ*Ꙝs$g??>   ȡ9TBE=8$IjOu   >rh#Fm$-PQn>M?9Iz֫s   HCIEK/TԵ$'_9`Mu   qh#Fm$-PQפ$IM4<   7m$ȡ*ꚜ$   7m$ȡ*''IRͮ~m|   CI5rh#h酊vuiIh~   CI5rh#h酊^~v$żu   'm$ȡ*}$F   'm$ȡ*N&:   @8T#6^oH?;Ihs   OHCIEK/T_M6OO޷\   6jFR@ID    }FRH*Zz"cz'IRN}F|   CI5rh#h酊[~5$Ij;s   /HCIEK/Td~|IDϋu   ph#Fm$-P[J??Izrl   6jFR9O'$IjQu   >ph#Fm$-P3'IRO/   m$ȡ*rO&\   6jFR9#~~$5Ks   HCIEK/Tϧ$Io:6\   Xum$ȡ*ן~$5U?    Ρ9TBE'(IR~~|   :6jFRYS~$5Cu   UFRH*Zz"kpOP&ZvM|   :6jFRy/~:%Iyy#s   `9T#6^ț}3$F'=5>   VCI5rh#h酊Ʌ~$5?u   UFRH*Zz"oL?CIh7:   *sh#Fm$-P78nL?EIzs   `9T#6^XۯO?EIr^   HCIEK/TهOM?EIht:   rh#Fm$-P&0%Ij{u   UFRH*Zzb5O|J)JDO=>   VCI5rh#h酊sQ޷\   XQm$ȡ*V3L?GIhpcs   `9T#6^X+^~$5_u   UFRH*Zzbuzn9JD    ȡ9TBs$\   XEm$ȡ*VƎn9+$%IayWg;   qh#Fm$-PZ|wIJD0>   VCI5rh#h酊2')IRM\   X5m$ȡ*VM~$5Ss   `8T#6^X-}kIJD?    ơ9TBY~$-$>   VCI5rh#h酊3Yg)IR^S   JHCIEK/TɅ~$5=:   *qh#Fm$-PzF$ן    ġ9TB]$Io9B#>   VCI5rh#h酊մ)IR_]   *HCIEK/T~$5g:   ph#Fm$-P& 4%Ije:   ph#Fm$-P`iJD[u   UFRH*ZzbE􈮛S7w;v   FRH*Zzbu)IRO|J|   6jFRkW$IM49   
HCIEK/TN?OIh7:   *ph#Fm$-P/$w    9TB
-_H?QIr^O    ̡9TBj'*IR   FRH*ZzbM/>8D%Ij{fjz   9T#6^XmS~$5w:   @CI5rh#h酊68[OT&Z67v   $6jFRoyMg*IR~||   $9T#6^X}~$5_u   $6jFRorT&^y\|   $9T#6^X}~$5֫s    ɡ9TBE]$Io1|]~   8T#6^mפ$IM4z͏:   @CI5rh#h酊~}*IRM.\   Hqh#Fm$-P㳟~$5o    )m$ȡ*a~$5r   FRH*Zz'ܯ[N~$5g;   @CI5rh#h酊U&:   @CI5rh#h酊s$W2>   HCIEK/T_J?WIhqU   FRH*Zz?G>6\%Ij<k   66jFR$F'?->   jsh#Fm$-P/M?YIh?u   HCIEK/T'+IR\   ͡9TBE^S'+IR-\   ͡9TBE{T-g+IRl   ɡ9TBE,n>l%Ij    59T#6^5oH?[Ihz1   PCI5rh#h酊wV&Z|   PCI5rh#h酊$n்v   ZHCIEK/TA0t%Ij?    8T#6^ŧ/O?]Ih?u   ZHCIEK/TOW&}\   š9TBE?xvJD˻ou   ZHCIEK/Tߕ~$5g;   @m$ȡ*zjcGܞ~$5gg;   @m$ȡ*k~+IRM/;:>   jph#Fm$-P_~$5+s   6jFR5:gW6O͝g;   @im$ȡ*ko2%Ij?    9T#6^7$IM4y:   @im$ȡ*m7$IM4:   @im$ȡ*mrOX&Zn67vg;   @Im$ȡ*mxSOXf   PCI5rh#h酊۹g,IRz^~   FRH*Zz\~ƒ$5C':   @Im$ȡ*ozg,IR->\   (ɡ9TBEg,IR-    8T#6^+'%Ij~6>   Jqh#Fm$-PрrS$    8T#6^hw$IM4\   (š9TBE~ʒ$d<   PCI5rh#h酊6,IR3Ol   (9TBE/[.Y&l   (9TBE;w~2%IjGOu   HCIEK/Tc7$IMgs   6jFR혜,IR3xL|   l76jFRGYfl   nm$ȡ*󀮛OOZ&^~l~   l36jFRmY|C'-IR-n*>   CI5rh#h酊LxUIKFY78   `;9T#6^h_K?iIiڟv   FRH*Zz-ã~Ғ$57>   CI5rh#h酊l;Z&_~~   l#6jFRxaYKD]ƾ   ]HCIEK/TgCZf   ]HCIEK/Tgt3Zf7   `8T#6^hoI?kIiv   `8T#6^hO$IM\   .m$ȡ*4i-IR3xL|   l6jFRm\Ӗ$Ƨ?+>   CI5rh#h酊6NzjiKL+^    9TBEvuiyKD~8?   CI5rh#h酊v-n:%Ijl   [m$ȡ*5	-IR3Nyz|   -6jFR$8>   CI5rh#h酊vyByKLOU|   -6jFR-Gw$Im4w;w   FRH*Zzm/J?qIixҏg;   ph#Fm$-PѶ%$I4yg;   ph#Fm$-PѶ>%Ijug;   ph#Fm$-PѶN?qIi97>   CI5rh#h酊-9%Ij+E|   )6jFR}3$V|   )6jFR\3$f~c|   )6jFR3$   HCIEK/Tt|~$5;   ph#Fm$-P^~$5_v   =FRH*Zzb=>xBKL+v   =FRH*Zzb=z^KL~$>   CI5rh#h酊0<	.IR;-    ˡ9TBŚط[~$5g;   nrh#Fm$-P>7^~$5җg;   rh#Fm$-P>~$5ӗg;   rh#Fm$-P>Fos$nG;   ph#Fm$-P>?:%Ij~2>   vCI5rh#h酊$    á9TBz}$柺$>   vCI5rh#h酊2E'/IR;   `HCIEK/TIOM?yIjt   `HCIEK/Tt|~$5    [FRH*Zzb,n:%Ijv   rh#Fm$-P~W~$5rnG;   V8T#6^X?㳞~$5w   ph#Fm$-P~<!%Ij;0>   ¡9TB-Gw$I4|   6jFRi~E/IR3-G_6/>   vš9TBz^rXKT    FRH*Zzb=s/IRSM{a|   CI5rh#h酊48/IRSͮ=3>   vš9TBZ$mnw   FRH*Zzb}>zZKTc    ǡ9TB\$f|   <6jFRktS_}   hpأ\utˎ֕CI5rh#h酊5󀮛O?$5Kw   H;'vF7n=w:    IDATknwߚs)6jFRmqIjp   j|R3}]7o/וCI5rh#h酊6$IM5~;   2xٷvSMsP7n9c?ozoﲮHCIEK/TYMHTk   ~}7:~W@-i۾?/n"[Wm$ȡ*KHT/   nx+fzu]\5FRH*Zzbm;?$5ߝ   _5>헺eGwuQ΋ۯ3XWm$ȡ*xa@ػw;rZ뤭RږNS;ovҷG\ԶVqtZvvN9H@0FF`8Q	hD1`8p?뼞{ĖS^y>J~7$I$IO?i/;:uWM,9KSshTB%>  @o?/|K$IY1^rd<6.P#z(PJjw J]$IԀfZHl
[R*i'khm ^~ P;E$I}T·l=l\RְgSshTB%MWn V:-|K$I]5Wx8o9rphT*zqaS ZqA|$I$GżCS{ɑ_47KM0;&PJ{ J99MM>%I$I#Sk_5tKJAjh`m ^ZK vZD$I$W@n8!6N׊qud'"OshTB%mmR JwxI$IR/IsJUi~E*t6YshTB%{M_~ P+;/$IwHj/92uWku)ecu9606@mJE/Tҿ׻  27&$I}lY~LY+;^#?϶9rphT*zΧ"9 @d$I$YYm_u5)/k7nbm ^uʏG? e$IW,8<=jQ[;)yM̡CRMcO jny$I$mk!]yl]ץT?:6Vߏ3 98*PIOopO j,ISxI$Ij\HGcRo͢4ظ:A7Ds9i`m ^׻n~ i/I$Iu8թsџލ'o;?Oe&PJzzON |W$I:U,8|W@]4X"Sc/t>WC 6@*@ |33^$IƶɃR7cS4ܼ.Qйo|506@mJE/Tҳ+l~ P+e45$IoY~LY+Hҿ3 98*PIϮǅ juτxI$IR{ѩjrW@DFF!`shTB%=~ P;+)|K$IRd#}ԝl粉y{@mJE/Tҳk-yS }e$IlMZaQڥiy]Je#{{606@mJE/Ts +Ԝ$I$tHGcRo͢4ظ:~'0ƀC 6@*i{74 vgR$I}X8+&`Tq1սynbm ^ջ ӻvn$I=^r䶯T~5g9rphT*zWS4 v>%I$iM+._47KF(EuW͎s 98*PI۫uʏG? a$I4]qSg1fQl\RS7PJnne @?%I$5b^vtꮚL+Rz4#H/M̡CR\< vz7>%I$ջba]y֯*7G!خǇ&PJQG? ჷxI$I5j_տ4ܼ.rPshTB%_% ̰L	/$IƳWo=YWoG{o}ɡCR_< :q$I4gmpUi~E*G5}0ΚC 6@*igf yxI$IU1^rd<6.Mcߌ*҇^shTB%F? a=%I$6Z|֯|fn^R9Qtz{l`m ^սO j8Us^$IR\_3ظ:^+G	Ӈfﳉ9rphT*zvVkɛ R3o$I9i/;:uWM,FVlshTB%/LiЋ~& P;Ϗ$IbSW/T>q0VC 6@*iW7L vʩijb9/I$i7}`j->"u+;rWΉ̡CRz7L Z9/I$i;MZ^:[sJ~)?B@ꨘ 98*PIjo  3]s^$IR%}Qj2֯HepM̡CRZg 4es^$IjZRoNݫޛ떧oEh 	M̡CR&KCO j<&$IR]}`j->bolYnIi8Q ޗNh`m ^io 3}/yI$.gS`zEDo)M̡CR;u?oO jw9/I$cłG4Xod1?KC 6@*iwjO jixMs^$IKLݕǦڥiy]Jew?_C 6@*iw*
A*}^$IfZHǤޚE۾jЍ܁
nX 98*PI;wD? ΅o	$IRTYm_u5)ȤwqAM̡CRo^\ gl$IrT,8|W@]4X"Sq P?C 6@*iw| Rec$IfɃR7cS4ܼ.^һvngUshTB%nS~" @mX$I#Rg1fQl\Ҡf#n+?C 6@*i/Ǣ RwzI$i7+JeGo{I;Rc<kbm ^=ipO ji9/I$mb᩽Խ}i~@̘5|98*PI{R9O j<&
$IjxoHݕǦڥiy]Je.55} 98*PI{R{~2 P[)|K$A> :ˏI5`hY 98*PI{R%)g Իn~$IR}+JeGm_z,z{{?C 6@*iO>g 49/IzTqj/9rW@y
w^613PJ_9' @=xzI$Ym
K6.MR*`}gghshTB%i F·zI$vɯNǤޚEiquJNW+ 98*PI{ZE? -gzI$NIL0V>Γ++KџM̡CRMO jܲ1~K$)bS{ɑԿT~Rӿ+9rphT*z7WE? ֢$IɃRk[C4ܼ.rdcrhTB%M/~: P[9zK$iQͧ2n:-}sJ^	߉n`m ^ 5Y/IX8k;鮚L+Rz4zIs
nbm ^8)ez{I$baȭp+&F_obm ^m j$IzVPˏILR*ѫ#j̡CRo[| zkzI7P߲u7l\R&JkO716@mJE/Tֽ g$IRӎjˎNUi~E*GWBk}5M̡CRN _8J$US1^rd<6.P dWC39rphT*zԝ~B P[o$ISkԿmG50z`?'C 6@*i_l>	@m~Y$Iǯ\[(6N׊^ ؁/
M̡CR/nX Sij^$ijˎNUi~E*78 ᳤9rphT*z >%IFbޡ]yl]+ _nlijm ^}8O jw^$){LGc~p-)T7͡CR[6D?# 毆zI\_ջ4ظ:^+zb9rphT*zD?# ?>%IfbK~=fwd_ʩ- [6ϤPJ׺+ :-|K$MżCS{ɑ_47^ ÇևϩPJZg 6%^$i>0:ˏI5}ԠJ0]͡CRM>?~;)@}uԜg$I*JeG'l;[ cd/ϲPJZ y/I[>]5Wr17 98*PI3QƓ Zo^$5yٿWԿTn
PCVϼPJ:ASZn^>%IR}`jөsߦ-gwHi8^} hPJ^ Z|M̗$I]pVj/;zW@sMJ"z_H\ljm ^j=	 jw{I4>O%GUK+R99z+rhTB%TK +$I&Jߐ+N^_ ` 98*PI3UҷE?' ~'$)#Rg1fQl\Ҡ >͡CR4S> ^$)oY]5+[W gOEmjm ^kbT~R Pk[Ύ$/N%GUvT?PS"I\ 6@*i&uyZ+6g$I&J߰3ku)e YY 98*PI3Y~R P{3k̗$I{Rk[(6N߉^+  L댟͡CR4?' ׻vn̗$IW_Lק FJkяPJ0A7Y@7?%Inսѫ >C 6@*i~
 ,Sq|I \Ss_>C 6@*i}C
 js߆|IzkN^ `39rphT*zf΅o~V P{|IkF 0r 98*PI3] _lK4M T>vonrm ^**l~Z P{V̗$I;o FgtshTB%UQOD?- M|I2 ș>DMΡCRTE ǿ&$iMk _,|F796@mJE/TRN}]Fh/Iv\y"z] ӿ 98*PI4*ۏG?/ s_$mT ψΡCRTU~^ P{M_	$i'<zU Ի9 98*PIUDF(N~Uܗ$Iϭ៊^ `$u/wnrm ^j w}IJ  #9 98*PI5' 7$IzN8zM ^s9rphT*zl+O oOq/$u/{G  #uMΡCRTe/.~b Oyܗ$IϬw FRqtshTB%U_ y}2|Kgֻ FR19 98*PIUVCO ~7MyA$IO5} <K>C 6@*~f e>%IS6\ )?|F7=6@mJE/TRo??@#o9+|Knjz  #gm39rphT*z{?D?3 hrjs}@$I*ۏG 0r\>C 6@*Zt3h-yS$IKS^ `$M9 98*PI7Tv~j ~IZ^ H}qqnzm ^M:P zG$y_^ `$uWMPJQ9O uO~I^ Hx{nzm ^ ѽ_g$IM{?E 0:qnzm ^Ki8~n n$5ޚSW Is~%|N7=6@mJE/TR~n &|KG 0Z.|N7=6@mJE/TRz_:5@ctzo$&z T,>C 6@*)W4@c)|K- ISsMϡCRWD?7 hLI$5ɃR 9e9-6@mJE/TR- 4Fw~IXq  IÇ>áPJYǣ 4g$IM}ίD 0\>áPJY璿~r аzE$iu>-  FR9-6@mJE/TRZ~,@t?/IR]7?z Ի9-6@mJE/TR&@F$5m^ `$ GTB%宿ny(X8+|KԤ}!z 9 y8*PI|WF\w_&U>)zHjr    IDATsZm< ^ܵNg 2/IRc󂭿Q xWj9phT*z7T~z ~*@Zcѓ FS9LSrhTB%E4 [$IM߉ 0ʩsZrhTB%EԽ 4$IM{?E} InږC 6@*)Y YT@׿ #i紶PJ
i)Z ;$I5opߍ# FR3紶PJj 2={$Iu, 0&紾82phT*z]7?@e*Nze IR]+} FV3>-6@mJE/TRTz^@ZQ #
ږC 6@*)bޡ)O exM;$Iu鿊 0Ztֶ 98*PI}si}Gw IXc FVqgPJwO {Ϳ $ձK< A7MM>-6@mJE/TRdOO g;w IXeCTn>šCRY%) ' IT2zHl>|V 98*PIXqz$IS~1zYrhTB%E! 4{w IT 0&gʡCR]ߋ~ HHT7=`du>ZOPJxT" 4NoI{$Iui5ѣ FV>Tm ^QhmO |rS}@ I7*ߍ 0^?9rphT*zFޚS" 4Rܣ Iƽև~4z%ˡCR4
u _4|$i\# F{gC 6@*i*{iJ09@LԼCwIƹuG: 7?> 98*PI;wD?G h',|$i}U8տYgPJz_\w_H4Mq #{Ϳk=#6@mJE/TҨ; H9Lŉ?H46zH\?絞C 6@*iT*{ ׽$cOy:Z̡CR4JsgF>x[ I8[sJV,> 98*PITK~ XS_H4n NSk=36@mJE/T(չ$ 4VoỀ$IcA)Z# FZɡCR4Jǿ,~ H哛Iƥ?=`<|^9rphT*zFu }$K=`n:=|^9rphT*zFޗN~ Xۖ$Ks رUznm ^QsF?K h^$CEOn i(|^k;;C 6@*i*{iJ0i@cu.}[> IҨW #
znm ^Ql	 5]@Q󩿈 0aPJz7~ i@N}}> I(׿q #ܲ!|^k9rphT*zFߎ~ h/|0|$i>q #mpZϡCR4KiЋ~ XeHspN I(V,=`,
~m ^Qm5 s$b$zLPJz_<w]H4n:-zLk+3[ϡCR4M  Rq$Z뢧4 <?Onm ^mR굢( 4Z	$I( 0ںSijbPJ^D/G%IzZϼ5z<nJ֎shTB%rMD?Q hGH4*8z4~^֎shTB%r%o~ x$Ikl==`uWMm06@mJE/TH7Tv~ ln*@Zg1z*X\s[;ΡCR4<@uzoN IRtkDd ~:|nk9rphT*zFLǾ&$IlxG2 LżCvC 6@*ikg
 @?) F^}s[;ϡCR4M֣O oKI\ѣ kvC 6@*i|O R	$I''1 ޗ>> 98*PIP~ 0vn^ IR&Je{K;gvC 6@*ij-zmS RJlѻ$I9kףG0 G9|vk9rphT*zƥrˆ
 :A^ IR_>#z(YshTB%K[Ύ~ @Jip5{$Iٚ?On 0gf.shTB%K$ r:F$u'/ 7um ^qiWrdR
$IQc FoI[ΡCR4N5 ӿԦd*8|7$=v`lt> 98*PI㔿I w$UY9zXi]PJd>45~ IRUuWMF[ ^sp֮shTB%Us^Rli/;:~?$=z~٭ˡCR4n& 3=wI7zX~^PJW7 O:u$I3]o)# J>{9rphT*zƭi% Oӿ@m ߎڭ9@mJE/T5_*~ RqKwIfߌ 0v^>õ{9rphT*zƱF?] ipIR
 clo$gv/6@mJE/T8[. 4NS$sIeѣ `3\C 6@*i+Nze s$kOyHӻϡCR4z f$IG* Υo 98*PIZKF?_ YA8U)q
 cuv?6@mJE/TҸ>w/ ,o~.|G$io]\(S9ϡCR4KiЋ~ =A=nT~1
 cgs\{C 6@*il| ;$I{Z? 0>ǵg9rphT*zƹgRC?'H'&zX^9=ˡCR4εN/O ؎$I݊_R9 0gR,מPJ&KD?c T,+HnX=9`<T?,|krhTB%{[?}~A I.|~*6GM Kg86@mJE/TҸ׹O1 e1Q4u.	 cvi,מPJ( FO$IY=.`lu/{G,מPJCo~ v#~$idkߢG% ֙?>ϵ9rphT*zPڹO ؁U$I^+$ A/M}a<מPJC%o~ éwh Ik-z!}0|yˡCRTf֣ ؁/H7=`o^>ϵw9rphT*zR΋3 ~$i*YJVxֹog.6@mJE/TR]|3 +/H4]9c ^	ڻ 98*PIuX8+~ L/
$Io% Wv|~\^erphT*zۣ4 w Ijvo 0>ӵ9rphT*zToO ؉y6T>q8׻ΡCRTj v{Ϳfֽc j 98*PIj~7Y ;QOq/$Ij6 !??۵9rphT*zkD?k `z7,$Iͪ PvHS 98*PIusD?k `WTAԤf 0ٮ}ʡCRTR* B3IR3^ Fs]C 6@*5i 2)?7Hl= 6J|>PJcG?m `7(|o$ջw P~*>ߵo9rphT*zX̟~ (υzV?H4]PJer Z[}bZ9%|kshTB%յڥ M~/|w$իWD8 ΅o	 98*PIus~ n*fsp IO;/o P;ŉ?>9rphT*zZ' ?HQ7Tѣ j|ɡCRT^TvL	/$Ic~ip Nes^3C 6@*Mx `|n:=|$wOY8Z\ws^3C 6@*εN'  >S;$iLTn= V 98*PIu| {$IYs= ijbYɡCRTz_\=>wwIxkR굢G Wz\m ^oD?s `ߗyip ս_gf.6@mJE/TRsp*;OF?u `n8!~$EgZk^3C 6@*	vIS ԰Z.|$vłS 5襩/
 98*PIMsD?u `/6\&%$I[3 f66@mJE/TR*`Je_ѬM)Q k}C 6@*)M `#8w	I҈54|1 >f46@mJE/TRS^/ K_KHF= 45Es_3C 6@*)ds VYGߎN P{ 98*PIMj7< MżC	IRpsNoK Ugf<6@mJE/TR' >OHb>)z@cٯϡCRԤgb E9:ϣw
IRL/ ;&>59rphT*zR9P O喍c cp_PJjZ[ύ~ >ݰ0|$孿 {?UC 6@*ig rZKWH>' 4N	TMm ^5E)ZO GÇoễ$Ҋ? RMS&6@mJE/TR_{$f7 8u UC 6@*u> ̐y[Hwc {ˡCRĊ   3,NY$if>Le=f Zx.rhTB%5}7F? `:MM_Hfև~4ǣ 4RỀ͡CRԺWS fPwI4i տmY>JshTB%5֢F? `&۩uwIҾ5 8O}@PJjrÇG  3h7R1;$iQ W|GwUC 6@*n8!#  au1$I{^̟O߉# h11z'P9rphT*z\#?  T]{$i+N~U*6G hލ'>6@mJE/TR/1  ̴A/kHvWsG  RJs
T}m ^[(c  @Rq4yPsu  uԜUC 6@* "o\&7$Iۯѣ .	'6@mJE/TR?On(  *һ}CWs  sɡCRMG  |ISu.ax  ʓC 6@*IKs~5  RZC:gSѓ xw/6@mJE/Tf BN;$g/ A'	ʗC 6@*Irv P᦯/
;$>T>)z  wˡCRmf A~ệ$5Wrˆ  lGy"MM/(_m ^$}ɃRz,# Ƞwq$5C_ vOʛC 6@*IO_  e=$^ D33(om ^$=UߍH  rR?$;$1 ؙLŉ?7(km ^$=9/ @CZuwI[s_^) eϡCRgֿ  kwIMs_w_ ʞC 6@*IϬs[? KIC$i+\ Y?(m ^$=yl	 Y?~1m3ts `7-ij;PJs| @ჷbKwIS~q `o[C(&6@mJE/T[  l>M}a>"IRq{?=ԹPJs+G@<MM>?|'QuʏoGl}G{V ذM-DMi&z͊zsMz6C& iRA20w]sLP_e\g=||9fv	黄rrh4PJC7  d,!}'I{ܝ=-0]By9UB%  $_{l#IQﰷE[=-?rh4PJôQg  l#I?YK1dg `K(v~FN Mph*{|  &cI3(g/ VB9UB%}G 0!מFRh    IDAT{[]u\( J͡6@*IВޗ=& 	1(V옿HRm[=PUQB9UB%]zX  &HËi;$5QwD ,rhCVG=& 	S~Y<3}O:zd\ `whCVGivQu ):ݞHB7(g~,gZ `uW2Pzm&8jPIz: {T  hSP-i*V>9FW=^w_kh2rh4PJңod
 `BUw}E~1=V)}dhCVMhn0{\  jԏ{"I[XD Q7 Mph*{i/;{\  bp?,9˟+=Am!ܢCC	mZe/T6A=. )0\je.huW"; @7}hCVMlnQTߔ=2 )CtH_F: hHJ?499UB%is  sXE~b5_ @omMNm&8jPI.{d  S(xA#IQu @Æhrh4PJU}M  H~n#mZˏ @AoNG4Y9UB%i LAg7Id1WGS HR-JI4Y9UB%i*G 0m*mI-hgwv"/hCVo|y٣ R㫿'3fޡ7d; `t{Mnˡ6@*I_=: )VsoI^bfb +n~̡6@*I_In  X5cߗHEDUܓ= 	28{&26@ ^$mY+ ]rptHκ>[d2 `u~I̡6@*I[Vs=> QFT|roD9a *~+}_hCV-lv X8nNh#iΨ֯͞Z |wMn޵&8jPI=B S;=5}ϑ4yuxCo:'{L *9黋&76@ ^$my݃ޜ=B T=pkx{#i2*] ьo:7}dhCV1 ̢%Gb}GRNNOFz	 "?hsh4PJ5\ fX;;[}NhTu# 6a;?=DhCV 6Uo}*ON}$6?> `K?5hCVo|٣ hۢwI_?f `FC	mZe/T ɟR-HV6(zG3ʵe `TYGC	mZe/TbS"Fq ɠ35:KO߅$mf+'	 0CF>4ThCVit h̻w!IВDDyu٣ ACޒh*rh4PJg Ne;hbpGzQ ̨,eޣȡ6@*IԒDչ+{  m6pͪ(v~Fn$);?d  GӓhCVk=G
 @T1`?{?XwUq  AUFw MOm&8jPIZ*{  j忊$i&zG37QUٟ? "N߅4U9UB%ia+ofX 	պH5TxU}M TD Mph*{m|d DFDg;4uW<kVE:ٟ6 bU,}lnʡ6@*IIVuU}p#mnKwMd  : GhCVo#G &IβǧO$U1`ר:wg  ?{w%M_m&8jPIZz 6>X+GIR濋r `w^3i:sh4PJR- fbtFwړ#Q'	 C̡6@*I48 `TUwVzq^%]S4dV  6M9bgQ Mph*{TOύ(# `\7OO߯k;b}Z63 lkOߩ49UB%ן=b  ƨ+o[n455kVE/
 `>+Mmm&8jPI=b  -7gk?/}ߒe$FUo]  ]Y]KSC	mZe/TjlQu3  (V옿{I~\s;c#?  ,;\ Mph*{To3  tb8l<6Ԣ涉oYG_ @}2=.ThCVz1 Шgo?YC>٫g̻ctQ=x[?  _wJ.ϡ6@*IWV HQGE+iJ[}wc gf Mph*{T&{  b3cpG{=rKy HW%:49UB%6v5ؐ=n  &L2p}	;OQvGx LYH49UB%F=n  &tnxt,.}S}mF,FWFTe?  m<bgq Mph*{Lސ=n  ǠGӿeK紅-}ltzsNhbTޖO }N3C	mZe/T\{Q xcfU}tyin\bk?:3QqED9 `]OC	mZe/T9  3Oy+eљ&}kEW>8{I:.{'  jP}Mt Mph*{`?? PA'ʵߊ%+o(v^8ſ_1Y_  w{f+6@ ^$5?w  @(o?}=-Qvtmzuѥ< Laʧ@ ^$5[w+#*{  F?{4]rB}{ЛY=rs+v~Ft}U{[}OB%FCuD Ft^ˡ6@*I7 f:wGyQ_pÜW~8F#݃u.{'iQ.?wU/~)z܍iG3nmkO?)2os@ 0#1-SC	mZe/To     p^̡6@*I	-޿     LmhCV=~    	TFg059UB%)bF    Ly+/59UB%)_A    $yo Mph*{W=    	2g-59UB%)F1    LoLhCVg/C    tn{f?6@ ^$V    ?5^ϡ6@*I{L(    m*59UB%)!oE    @W6Rȡ6@*IQË    ꭋb(Վ Mph*{4@8    /-}Rɡ6@*IҒpGH    TjMm&8jPI,I    @F=:]Rʡ6@*ISDc	    hH_NTrh4PJd5    4`oG}9UB%i~    ЀhCVɫuMh    jTStohCVɫf&    F?vhCV	lvQ_=    l<t,{\;ZC	mZe/T&YO    @sڛC	mZe/T&bgD#
    X@U(VhCVmta#
    X@s;9UB%irS    Btjwm&8jPI7=    0^C	mZe/T&${L    [kԏb禿7Jm&8jPI涉kG    F(9UB%i7٣
    R84QژC	mZe/T;Dq    l_c-6@ ^$MG}2{\    {ϡ6@*IQSlY    f_Esh4PJ4\*{d    w[ϡ6@*IS#    lM禿)J?C	mZe/T[    &Dsh4PJtU=    G07ʡ6@*I{gf.    wDrh4PJW    i!JC	mZe/TK    zzp9UB%i:    JC	mZe/TE    Av(=Bm&8jPI]    ړGˡ6@*IS'DUܛ=    3%6@ ^$MwVf1    hUǧJC	mZe/TbgD5ؐ=    26Pڔ Mph*{4/;{   @kB9UB%i+v}Vİ=    }qtW"P Mph*{4/?{   @.L۠99UB%i6*x~x=    ]fɡ6@*ICG    ۇ	JC	mZe/TfbE    o؝-ohCVj߄    5<@iKrh4PJl%    Gս?(mIm&8jPIF=:{   | -͡6@*IWwWETex   SSt(mim&8jPIFW=    `?ikrh4PJl=U=    `f_mɡ6@*Id8    'O Mph*{4u?K~    ,?Ԗ'-Dm&8jPI7=    `>i!rh4PJl=W    LѷM*6@ ^$~=    `:(vnP9UB%iw    0uLߓ26@ ^$'g;    *UqO+'-dm&8jPIjG~!*G    L)Iד:6@ ^$wy    0{ΒΡ6@*IK#Q   IuhCVv5    m|)xR]9UB%]{0b}    0ƃzy;TWm&8jPIj_Ë}    0~'ՙC	mZe/TW۳#E    X; Mph*{Ά_={   DvR9UB%;?=    %љ&N;6@ ^$9KG     : Mph*{ފOsw   TKKʡ6@*InpƿdA    HSbgIMhCVqQa(   !Nj06@ ^$i    иt9 Mph*{Β    MzG~ۜpm&8jPIǼ;{   @cמ&'ehCV$7([dD    ߨݽ_&'%hCV${݃%"    jOIY9UB%I?"    Ԧ,!Nʡ6@*I^1dF    XxU;N̡6@*IkVgF    XpKO{sh4PJ~bFս/{<   {ooRvm&8jPIC58_#    ,	Ls&!6@ ^$![بݒ="   `o>?:sܤ	ȡ6@*Iz	    [g<WIC	mZe/Tmm    ņ.g&'ZPJާ3{L   )qOgIT0ZPmӗ*Izמ=*   `x{ۚ4iŨi-&Gq	    ltդknQDUe@8jYJfK    $U(v{v4q-!Z¡P_$Q*v٨G&    <JO&bŎٟ'mZuv{nb%I    7mҤIyٟ(mZ{(}MjQ}m   6,Ѥ	벿R% *xCb%IZgM    xHS?~&Mr'3Z¡PH_$is_	    ?a(Qg@K8j{+Iڜ=^0kx   `bd>/M7&'kZ¡PW6}mxβ	    _ˤihph	6@g/I_$i[ݜ=B   h5Ym{4.=,Z¡PE/V%
   @]w2iZh	6@FמXIҖ61
   @KN1i[ʁ8j5JWF٣   )^OFI"QC^Nt/X/;{   &~t}u4M{|Cv`IҖV|rT    ItqhԮ8M$mM>=J   h2JڲSCv,}jnQ~3{   02Uoa63_0"m.=}{#2{   0gk4_	-3,IZF=R   AϏ6_]UI  IDATTx6@_$i*v~zT*    3=Ş/Lqh43-IZyH   `o^4_g@8=鋖$-Hsb*    3`t߻)otٟ22mFd%IUwD٣   )V_NOK뒦?ge pZ%IOdV    UUFN㒦bןrh4쭏sۤ/\`-.;.    LoI3Pwe@9SK!o#    T߉Β߶Yhx~ٟ4BmOp%I⃲+    bԋ~%J}7f@93KbSz   ,iVzY'C1eo}lX]%I]dX    &33(-K]gCQC=}:_{r   `BU=Q7,ixzCQwI_$=_1dY    &P-JO?m ~E%Iu58,    ftVҬ?}ٟ6bmfUUtxA&Ix(o4{   0!;ef'e@9?0Io(٣   lNtW2JOp $}	:Y=j   H?ߩYsh(zq"&IuU,bT?{   dOQIӳ?q )g~<}:ֈ    4,{|4{<?g@9R2}~sq   @~e4Y89}!Z[(!{   А&%jd m<K_$_e
   KKfQ9;YLnx   w]5ۍߡYn|ٟ:<6@I;}1[(:{   PA'*Jẫ^Q_;<6@헧/gDCOH   ̠	L{fe {4Ijw    ,_Hsfbv?wH7%Mi   Ws}+vsf+?wWUQEM{/R    S?}_$|˟Uqo' ax˚$5].    [̻ߘ648c_<Atv{n&IOH   L?D$b哣ޗ'm1ցK$5U7D٣   0עx%]<$6E鋛$5ٓ   MT%$bG_<$6D^vd&Id("{   hP$7C`(V"}    &W#ImK"Fa9&җ8Ij)    <GR_wJg {9IjE1   O?~$Q<*6DyUl6}*vyfTޞ=~   7jݞn$%Gyuٟ>rhLI_$zG^DUe_    F+ER/`8&Vս?:;==}&^O   h+HjSU/?}MhKM_$іg_   }ۻhs?}MlUޖIRu}UİȞ    Sh߇658d š0~/6,}\'IM68   U~ŮJT6C`*G'IM7   
`Ct]{Ժ?u9ٟ?fshLrŁo_$ՃeO`   VMkC`j}?:wL_$z    18߀=MaE Sex˟$5{d_   4̛t'Fyٟ?shLߛJR->.    3e|y.o?R[OC`T/`ݽ_U   0obgHmkpǳ?Jǆ%;/d/e   zUo]tW"Gj[nD9 [͡0JRӍ.L   ^8z7m{0	   S҇ӗCIjO򮫳/   TMYjbœ`8xC=}I&a=   pwu-yLo<#XPmW>xGtxa(I?f_   1,6MGjUsbtٟ?sh̄WGgSFIjѥg_   Wye+#K?Z8fbÒGIje(   UFq?CU= j)?&`~eT   `T/Hm"2{ ơ0s+}&   0YFwm~WD9Ξ  rh̤H_&%ɆkVe^   PUQ#Fj[sh̬YH_*%<&?F   H78judC`ORYQ=x[   H3o4R+x4ơ0"O/HjQOfD9ʞ    ]m>#I;*?F9ZapΊeSjG   hEg2R?6m\t@lSjonOp   AyQ7--67HhGĆmPIbŎL    Z6=#q|ٟ>@*6@n<#:+JRuyiTuc   U}t]Ԗݞmf  4O9Hz    kԏaoK{R_۲|hrQ|˩$̏e\   S{\4F_>ph۠ߛJR-ѕfO\   WU_翷Hmhbt粿z`͚ձacVIO+-   V,R~Ew^L$6 fUQd[   -2<giԆ b&CSn+=}r=n   6pͪwi+v_wJ0 7KvH_j%~4{   lѥGgnQ4>QuC1(}r+Iu41   |9:KKfbg;Gf Sš#sۤ/-yLo:'{   <Eg(,6('~(޺O`8Gk_IZ}7fX   d|Yi`j9TQ.':˞KB]
?   Lˣ&ҬUYQ?s`3}?G~B,IUߋ(    ʻbgH3Ւcp?;`n8-կ_%iwc   h$4M}? lퟓYeOU   o/NfDyٟ6Lrh ,b-I[b|i#   hۣo#,(2im Pٹ7_[;/Ԓ+v˳)   Ն;Dn?Q}M'
m jPn;p#i*+xk   S~E[4=;UU Ԩ=vK_%is~#1
   oY7iZm]u\x)C&1Q|pIzr=A  EI_Q=pk'zm 6/i鋹$=Z&{l   3^!MCψ-_ ˠeGF_K5\*{b   3{ ~qsh0u}{[H涉ѕfJ   `l~!C>6zG=mߎG`C_%icK   {k7	Xa1ޙn'
frh0^y\Wy +WfF   `TŽuRJ˟/U/?ۿQ?K C)2^rhQIԺݟ   #^!ڒDwGAy+c|{UP6 Spw9)_$^>(_,$t^Uo]   &YU9uEw>?}2NoF~C@95N^o,r#i^     &_H'    IENDB`PNG

   IHDR         =2   	pHYs    {Rk  IDATxwChb<Gh$FRLxcI1k5{tw]:RP*YY@\,ҋ]da~ܜ;Hp~̻s|c0L:a````````:ܒ{9[AUxS }ZDW+iz%XEm"K/tkoNMz32kBT!XJ}\@XnBKB*y2|1p\H$&ylHB_Ix^Jg&2SiɅˇ%4CsBrOHNW}mj"vFc8wB;zUxDcB;Mm!. >#ߚT)}{_ qj0i&ڻg\V [T܋D;koKX`4;{eoPלI|4gAX~?/~,Z2*[`\f3~.E&;w,TnSrHu8+8Tv-1azcvt-mz\h )	j(3v3tے4ąϏ-4N+d>:ΐ_|9A'=w,So<3Snz	nyd9^
Ng!=Jj>S(e9#޺2`@7LoNBk'AV xx%88׻£֝	s Rr.@g;-
Nv [pS[hqn4Q(vK-dKlx ^ў5`*9`nF@Bϋ!\FMDbSY#j6QQhaO0qB*DlpS	BG$>JPY/Dewܽ$-ڷ$bOoS~unc*#[8B|_#&)f** X3/3:Z6Jh\bcQ  ڂ_pq}S	2u-:<7^%Έ[U,Q_VwWRB^*_נlD{B|vdis7 nA]WCt$F4_tN4q'>P1ZS:ޠ49x<&>")|LyoJxVgد{d^ܦORd"8B-#B?+y9BqņS!/8G!7IgE
.8G!46.8G!td 莲SE9yW7G$$Ѡ;F[jDB ݱz\D^pPD@wW#!;jò/sy9BKAw#{"٢.8G!4O]pPDR#?eEz\I]tAEz1{tWS/;ɋj{NuKhک;E5vF`u8A/4n{fB.G7&/<G( 4޺t#莿y9Bq	7"/<G!?WB]xPChw=`V篒#6NG&6R[Sx)J]|P@hQQ56aNnN]|PChl`V Gm`[и9^ pBΥ;)j,$ PChq00FB&&|8^h97:pAw#/+TRaT%/6`4Jhw`vQz^	`kzS9M >#n*jh>K4Zh|0aΨߐGG6?D>A/4.ѝpk)`pB+Gx)H6#ڛ$=JzmY/G;Awͳ#j;cۈ{fPh|choi
 A|ꄡ_35>y{S|8D{ QZY9ynX;e!>Aݫ3+|0p<rt|p=@mZ6i' UК\b~켷|8&6,kƅ֌p޼\yvE]{IT2B{3fsN٘3PrQ},BϏ	D`3vyAGE9Bڷ &\^fޡ˧#;>t /03/yL /q#y2yޛNi6I%@geo펻 
t6Jn2?+VD@gY/ V%xLh|jdV/Xϒ+u|-Ŀ)&q Ȅ^&JcLhLU2Jk%X5t&޿Ο51)R689@:nN/42P^sz9t~?;ЦL?;Ar9	!7ȅS>ݠ_V;Aw~?TChnG0	?KZx>u ITh{$	]Ib
-^:/- ?謐0;,;P[iP qݬ߁i9M=i
ZCg-A@*ZB2%wm*UBC6EM^h\aG5_:#$pB4Bܷ@/sAk7LӰ{^иؔ#
vs|Ѯ#BUGu☖䷒}4L=Px[w`{,Lh-۷mh`,qܠӍ
]uXW"r]Z뇭¬aXǦ2Bӫ s[o+`[r>LT	w=zm5Jp3N~H!q7X3HgOCZטmA2*4'0_F43-t6\2$pe'TxMȌK_o_ڠg4`TO >Mg9	]TIQzK5dT!p~Bˣtfm
ZK%CL|hf4,޿! ?N4B\'C;KQaգG툙,K5xF]⿁GF*'r<=ŏ%7+oAOR1xdaêU [GY@|N$7 qFI~}4t'%+_>aF%z c'LHk@ۚ0)4/MF%ׄ1`dtD{7׼VЈ;irw\l泌; wڊ;NxFHI)MrJ!7QEl}/?B#e1"n㙨9'pfEr.x <G	+[XEmp~K/TfrFe`iOBi\U
0B3FB3FB3FB3FB3FB3FB3FB3FB3FB3FB3`|ی    IENDB`PNG

   IHDR  p  T   g   	pHYs    {Rk    IDATxweu}g EPQPc5Y2KILŴko/5F/w
3#]
H^]g|~x/&+'^^>3#~7%HRõ}oTGO   ;oa݊$MTK^?#~/gmk7DG>Р5hP9WE/F縿b4[Fy2    hO$M|^2x:e.+\=πd׊ϊ}Gx/Yߎ跳O   M;Z$ie>fi#zE #0'G+E[au3?y   L)~"ISݢ-gcxo`p8)1_$mPcDUf$    s{ߦ߽H=10-l u0w_S?^җq>4   wK$=I7Ϛ֞h35|/wI̼_k   Prc4>FvyStB5<%"W~9%.i[Y:0d   hN9Q/#IzfEE##7}8`yolҖ47-<}    4o؋?#Izv6}.;p@os'f-kcp	G   @ο$_3ߎʋ 08i0724-zIo99   oGH6bFC#7	LhJ9}=+v:w}    ^+:~0F+~"QUoP}+ޙT_/]g8    9H6?̐,(08FNbwX%[㫢#   `dU'q$I_b_)08Gn!"TFе   ȫǣOH67dV`"p*[EDkf/OIW#Q
   ުbH6[3:ŀ v֒W0%5R뛣|   `씏פH寍_LDCD_o<qG   0Ib+y$IsSKGn~3+{i
ժ;O    7h-2G4G-2._108`#8'ߞ"hk>k#   `bn<޿$'IV_108`C_޸+   8k̼I`螻0b8~X14|(zwORx   FIb_	֗GkV/9Ig   ЌޙO$}mٯ<c>c/6I97(   U>~'$I>~H30|h껳"   R{I=Qrŀ֡C/1I9񨞺/(   Nvt;"IRM-{MFF|a?g~!%)b7   dUh"IRM-<z,~1('濰$UVݕ}   vz4+ޙ~g$I_9028`x;HS]ӏD-    ߧz&HT_?eWKgVIR^N[#    ֡|(n~$Ib_9΀ֿh-~iKIR^Dȍ    cx9ZE]$vyS>8Zk翌$U,}e\}   ywJz^ʁ4L7fy    wނ{%IRgr SwN/IuW^}   *'|*~IT=~@8*sg_8r3    o^tH=$4ցFp05.Hmі1   MTu?$IE[LB=_0r[Yn<.8   `TO.?$I[_;&^ﲽ_,r>    cߊb?IjXMVkjgDpR̼\_q   @MCIjX>rskjetL~Hʭ.    5\=$v}Kk~@m8H[D$;w&8   !O$_{#OgvLrZz|:8   IU<^JT0s΀Rvbw4$=/#2H   i^tH$gmց9g}Ї_r	[   )VwSIAٯSLIIHʭsf-    [(mIm~1`"9<!)~!>    彗FkK$IV(ǳ_;0'8{[$   g\+IRM^`X+'/IyhTWfG    ޙOÒ$__98k'e )bvQ>zsQ   (+oeIjnf1o$$xsIQ   k׻$Ij_qeX>r?~	HJj1   1R+eοے$Z?~F3`zQ_RR3bp'    chxZ;.IR;*ŀ=釾}   0~%Ib+\}O+6cehO?%;߳!    &@H$[gn`p0>(VDa/)QU'    `؏AJ$[8A8s=Sߌ(    j?=~<KT_ί:̀0|h-|q!//    |(n~&I~z3`(]R->    `Nւ$I553?\b]O.eEحG    S0IR}~2`qC]R-~i8   `td$dH\ȐM'd?    LA'|$]~4~2`d9ZH?%5[򽳏    T(v~C$z,Uˀ>c釸f띵}   +,Z_~W&I%/r̓ٯxNN?%5[QU    Dez<'FRJSU-b>z    {e$mef`89[pKjbGz4   kE{wߟI~:p0Z2}ߟ~hKjbm|    ֩|(n~&IW8?5?Āҿ[R3-"w}    rrfߧI;?Ā=4̋5e:    ^zgm&Io?Έ1`dn=5Hsg    XUC#^M4si~#}ЇiI="*   RG[$IsW"W|#|CP} _d9    QE/Ig$]뾚z1`$tYR-#    l7Mk$]ޟj1 ]h-"pT_WF-    ̉~&I\jYo釲[Yo;-   3D{߽IfYeIտl    \ze˶K$mz/&tR,'U1    zjfI65eV\Va,:_a/   ZΝI$mz?JւcIs_{x<   Uet;9I&63?UweUr靿8 4K^#7e1    ИH;>nNi$3 MşL?%q3cx)    4nx7$y}~6u3 `Is_ݳ    H;$IV	S̀ݳ-4uOT    atp]$i_Gۄ)fAbO?|%]/a/h   tՓFl;;IdJb4nxUQy h   1hK$mD3zW	Sʀu@irZe}3X   ;swjp!ٯ+yO+in\u`    i؏?~'Iy[)eAʧ١CWҦ;G
    ;X<I҆(SȀFuH+ikK^    #op1y|WSȀFuVҦN5d'    06'M$i_W)dAsAv6	-2}    xt$I]~{08h+ZI    K#7FkVw|qۈ~}0e8hLwg    k+H$ժ_L9YIW_    {c$O~n8&11ߘ~J^՚    UhxG$SƀFN?`%mD6    (WEk$I/ ѿV҆׿>>    `"/9O;,f2"4{?6    IUFJj՝ohU^ΨOe    0ѪbWJme."45釫9򑛲    
M$=wK~U0E8]op1    L~/(IZwݓ!51vH?X%_3%    SWE%I?\e&"ԮwѮ_    Jõ2̼{BIVWSĀuNU<}\    TOwg53/b~E0%8]1    tOJ~j]o+vCUs?q1    |Gjxٯ*ZCUҺ    o,I;$W~50%8UUҺ+v<}L     V9wg_"0V/H?P%1#    xժ;XDIR>0VJ?P%pe    \y@]$E=o_	L	jջlU9C0x     C?LSi{̟fԪ{UU#Qy0h     Sz4^~(I\gԪJ?P%}1c    @ψ̼;FI:j)aA:i*/>    ߥ1JҴ}ٯjEG#    HU(v{k]$Mc~0%8UTi+:>    M4JE*v}s+)aAޝ~JS̼     #$5M1VŊw4;3     0SQGIޒ}3%8UkҴ]v1     1JEG?SZv~c*Me볏     &>)ISR۲}j-{u*Mc+~   U'G"%i*v{ϔ0V%ۤҴ=ُ>    Ѐ_KiǏeL	jZU]UG    hH~/)IM1VȐ]~   UQ#4pje!5Wُ<    `pq4pje!5S_(ُ<    {')%iR3)ʀCj۳w     QU<WJfAS8To    #`pW+%i3)ʀCΑ    #?HIˀpP+bz$1    FH(v6R&)bA8N~   4;LI8h2wgo    `u{LI8h22~   V=u_%iN2)ʀCnWd?    _g$M@4ŀZpHs[ُ5    0.2_{MI8h2Qk    `|+Z6Kߔq΀pP+iZUߞH    cw8%i3)ʀC8    ׊bsJҸfAS8uHDUe?    tb]$k4ŀZpHVQ^(    syJ8fAS8i:01    &DQ{OI8h26!O     snw4npje!m\WF}ُ0    0iayO$S4ŀZpH#_    `B_߃JҸdAS8uG    pS).T%bA8Xꨞ~8    &\}*]ޘ~'*IM1V҆5    MqȀpP+i;ُ,    0e:<nTF=bA8XMTOݟ    SZ2Z;l~G*IM1V5    RߑJ(gAS8uhDUe?    *gJ%iT3)ʀCz%/B    L{.̼;SI8h27~L    fuOT$b4ŀZpH]_S    Q=pKI;QˀpP+9Z(=    vͿ?ˀpP+i/-    a~w4Jpje!p.f?     44Jpje!=G5ُ&    {4"pje!`sgK    T3ZLSQȀpP+jxGĠX    ޹~*IM1Vw;~$    _noɿ_8h2{~    6W%);bA8E~    6J߳JRf4ŀZpH/M'f?     |h-<U2)ʀC^?~    6YO߷JRV4ŀZph+nSg?     jbk]%)#bA84<     3+Ow8h2д9U    ̝~H3)ʀCS٢-|    `$Z3a%8h24;oa    Pq~+IMfAS8>d?z     ~8
(bA84mo?#    ]c%8h24It    IDAT=ُ    @3(v{K$5M1Voُ    @c7+IdAS8Ef?n     ͪhYI;bA84a?q    hL3)ʀC̼u~    sJRpjeI{§3    TcFkTW4ŀZph+n՚3    t?wTW4ŀZphsG    `$TG$Mh4ŀZphRk~     FF?wL:2)ʀC̼(    -v9W8bA84uG    `$>4W:bA84i;,5d?Z     *r%i.3)ʀCVeُ    H\I8h2$UA'    yV$U4ŀZph|R#    0Goւu%i.2)ʀCRd?N     cOەȀpP+MD6'    Rbx%i3)ʀCPd?J     c;^I8h2иWmTُ    x귣Mw)pjeqُ    X\u`]$mJ4ŀZphkr    rL󕤍̀pP+s~     &|%ic3)ʀCZg?>     {~%ic2)ʀCc(*    ([OɿȀpP+c"    H?~,IM1Vmُ    D0X60bA84n>    hC~=.X6$bA84N;*ُ    D+2Z3%i}3)ʀCTُ    Twpjeqmn#    0GnaIZ8h2и4    `tdݰ$O4ŀZphjsU     Lj]Z;bIz8h284G    `*uO;bIz8h2Ш97    Uy Z_~W,IϗM1VfEy7    ;%y2)ʀC\?~D     ^U<ŒKseAS8FEُ     kܙ{cIz8h2Ш=     <ŎۦKҺ2)ʀC#-Zug    _<X֑M1Vz|:     (vyc$=;bA84r-*5f?     C=%YpjeQw~,     x.N;!.Y?bA84JKDc    _{}$}4ŀZphcI#    Q,m$}7bA84*^UG    пh{eIn4ŀZphT_<q     `}ZQ,Mݲ$̀pP+BŲ~      \~,Ik3)ʀC/     T;*Y8h2PvWFY(     z-Lg$bA8]ُ     <9/e5K8h2Pfmj~     s=YtgAS82[z     x<%/Os4pje%     wΒ7bA8U    0G(vxYݳ̀pP+eK/     L~,i:3)ʀC?     ̱釢wВ/bA8x;l7     &TCK8h2PN\    Tk֢-%MW4ŀZpn{     j?GK8h2PuOy     jV=yo8NZdAS8kf^ܘ    ݓ6^ZdAS8sf    hHh-<nZtdAS8jx%w     =wӒ#bA8D?Q    aCy;jIM1Vjme    H9J4pjek    `xԒ&?bA8Tw    ϧUK8h2P-d    H4jIM1V{e    Vw֒&7bA8TWŎtG    п|{kIM1VY_x z(9\[O5N;w&zgkt==sǢsȯ}ϴ몽Ǐ?:z~&zgm?߳ٞ1rrW^#7~  (&ZdfAS8jiQ=yo  mЍj՝1\ya?*~1zPsǣE뛢߭7bˣD?i+,:?'  @ҿ3K8h2P( ,U(&7wiΑNK(v~Cg5_ˣj?  *K8h2P^ `U',;ߢ{̟>^}x+m/btO_"wgG XJ8h2\  Jqv/#'Ct_Hj8sGwu_"*# V5gJ8h2\75  cꮉKcp嗢wʧj,.b+ftbTO?Q `S~e%MV4ŀZph.+v}sD9X 0y^/?}њ}Vs_w_W:  !Wo4Ypjel<  ~;+/EFODӿي寙Ͼ}|O$  #sȯW49pjeeQuVg HV;}5z}6\n]UU{=  ӿJ8h2\ 0e*ʇo{=;>{ƬE/7/~1'D а>N*i"2)ʀCs(= @#ٞ=X_r fJ*i22)ʀCsQ簏e Ize<_0PK_c,|=b~  C9b4pjehx)e  JDҿkJsό9aS Z7%4ŀZphS+v{T 1W>v[/5:$Z^Sz]35ʇ~t  "eۥϔ4pjeMNc  6TUFU;o_Xf?g?U  l9RxgAS86E/h (7G_]Rf" T=u_nRfAS86 o~o+<DNYGze '%%o4ŀZphS*,# mH43?:Ud \RfAS86> ]~o99GQo]Q+w*i y@wGIM1VW}9 0.)b٫ӿJcFժ;_  ap%e4ŀZphc*2 L{N^Xy?Wf?  |a?]ޘ}QeAS86 .nn86:Zf&𞋳r  /bA8̋۲?  S|q҄91~ ZZ+bA8uP `Z1A/>DTei  0eBIM1V Hժ;wQ,.;E{ϟE  4|+bA8!K_/?  eGZY=I?_}AQ 0u:rwAIM1Vڐz|:# 0_gW3;hf^tQ>zs 05Z@IcM1Vڐl  z蝷0Mn'i#?9ժ W%E4ŀZph}k+ *!'|*Z_N;_j?}  LI8h26b+ (:|/d4;*( Dګ$~4ŀZphZҨ:?  ccx9Ij˳ ߥߓ4pjei} *|=} fGx,4 (#7UCI/M1VZ+/ |f{ӿIʯqgJUfN  sGҿI8h2^ gpl$^/b^}R L-'4pje.S 3![YNLD}l $l4ŀZpy[YTk ˢsЇI;>  Z=ҿI8h29cQ P>tmt[$q3wʧ F:OFkI8h25( @F2Yw3I_  xݓ&̀pP+=WŒWD( @~wNL63ovV>  Jy$d4ŀZpWO UUn86ޒ}LWu~ 0V/{ˀpP+=W.iS{@I73?zgKİ} 4rpjeuUƈx 4j?>;QI'}$ Ο8h2кoM Ue9,eۥK^k> F^MheAS8UM ZW^ߝKUG% *.;ʀpP+=~X ԦR$E/D]}l ~1;ɀpP+=e{f, j1Q߷$i[e/]}| Շ_42pjehQX ̩{sג{G]} ~;M&i42)ʀC_H ̝ubӿgIҦ|'+ HiF#bA8=<#	 0'wGX? 3Go̼i3)ʀCkіQuH l_&Ef;  ":jw4Ipjed 6IUDc$_d  }58h2w\T `>4ۤ&kV> r{Q,mw3IpjeoU# OEOesc TLRn?{wY~8+j=|ZmԶǢZgƩH[ǖ83ve%@ 4C8QH0eH *  F!9~\Y޵U~uWם|OJ*f.}S$Izʍ!{e-n~4o˒$Ia;ˀ0*f.;.~$IO(_/,(iҿД*$IRHݳ~q8T*èIiЉ~$IOSwA7ÔFoג$IqQ-1P85z/J$=F\ ]̷xmI}Ob@ʀCY3`ˣ$Iҏn<J~1S9RK$\0P85fkFg(ICZSw&Y>i%IkZWgRp(kֻ菣$ImkS{Ko&Y>itφo$IY?.Y7PJep4heOP$6ش"~/ix%I&ӠFߐ_x]6pTʚGs{vJN$IԻ?J x4$IO(oIkRCSwAd
:*f\$Ij9Mw@m$IOvQj/{~ʀCY3hmD??I]?%7@#F/I#iϥ=X~@,ʀCY3h}R},I$-4y7@hIԤFݿ
Ro!aiMԇJep4SwD?=Ijv 1h{$IҤ'7I+MU֒o8T*è7~z${w"]q$I᪝h¯BYhʀCY3h=Sw$IjpU+.`A?2$IO]{tUiSw2 pTʚGtON$5#w/׻?u*$v[NX	?W`SˀC2P8gG?;I߽={wɟqHGIkRCw%O ,ʀCY3hoF?;IFBj[m׿$Iڹ-OvQj/{AtpTʚGtN~C$IlZ_-ӿ$iUe{λR藆 fRp(kҿf.I5'Skn;fƕ$I3ذܘ7zI~.- r3P85fuK$j`[$i~ZwA7@ʀCY3hQ/NG?9IԐ/ xv}?$IQ;iuO]G0V *f(IԿ꿅> Lix-$5#ِ_<*u}wjSw3P85c$IVU_= L?e$IoaoߒפޥHܞ7 1P85'UǢ$IsUzy@KFm$i4~kioS3:)Y08T*èg&I7.G<75SG4ں>7̧E}?ȀC2P8apqOM$ոUw (}O?z$Iʪ?jiE;dBo&0P85f#$Iru (k׿:DIx۷5šsSkni2P85%Irտoo btVFJvG$Ie47ֳw5NZc }Jep_~f$6~ _/cIV},:7̧E}ԋ?wwD    IDAT8T*èFw]$IRrFj~ K$=ituiKc_
SgRp(k5):L$ըRkw ScOe$i&x4ܼfWtWZpTʚGu'&Ij= cJ]1%I?ڹ-PVZK ʀCY3਷E?1ITnIß~ 0ڇh$)}aP߰x/|a# pTʚG'&IjP۩}o [W-3Io}`ӊ[wH<0, JepW{KR'&If#uNY){_:5-5šԚ73bRp(k[K$zA~[]lIҏ]s[m]Swt6 JepֵK$x8`6;"cL4Uw*뗧E}O08T*èHF?/I4xdM#8L4Mڻ7z7M aRp(k9OK$p6~ 0ڇ=;&Ih<J[pԿ]uPj-/	2P85z_%IfCwg Ί]zWܖF[קݿ
,*fQO?$IVuI6^+$McBٴ"{Oj/?  8T*è>3A'iIYk4H3 PK/I'IqtKH~eRp(k]}p$I3Xc {i4Gi3R?O) OJep#$IFw^Zs{1 [{R={j4ں>7̧E 2P85#%Il}#݄ 9)Ըގ4oclZz'$3 &ɀC2P8jf)J$JV7 һ菢?%iMO8T*è^~R$i]frfǠ$գj۷WV)oL}¿@i*fQ/뎈~R$iF/΢o g;?%ivnKS|]^= Jep$IƏܕڇ?'v:+>A;cQ3۸W;$un V*fQ#KOiԏ~R$iR7. 7$.@'$MG_ySkn 0+8T*è>$I_- o=;QW=zXšZ 08T*è>$IҔ7Ԛ#n}O,z/IkՎo{օ{{n8T*è>F$IWuOc_~ 9){z;辍iiE;$MX hʀCY3ਉ4G?'I4.|_ ?Bx۷,*ޥHܞO8T*ègVS$ISK ?#ؔ\UC["uNԚ7{' C2P8ap$Ipj/? ^'}ԋSăY7̧E}ÿG ?JepG?%I4{O OEwD|JjXUoG}4Q{S/ ʀCY3ਁ{-LIkU 0iUǨ6-)oL=ÿ OJep̾o~F$i
57Y=+zǩTܶW\]uPj-}f8 `8T*èc/P3$ISX x::FTI3TăSw>E 28T*èco;7I)k~4 0aDݷ16Huÿg q8T*ècU$I45ʟQ `"Io9URtAo%)ww߻ LʀCY3m_$IҔ5xL TܶW\]uPj-?{ 08T*èc{O$ISۇ?'FI_2U=ckRNe/ ʀCY3mM'D?!I4E.	 d1g{]G[FmLM+Ro!Ԛ#{ 08T*èc$IҔ4K7 >~4KGi}Kn^WW 'ʀCY3a=+ 	Iih<J @f?џ~HGNM~xXc3ÿg  aRp(k|$IҔ4S	 U*m_}|B~y]Gd 8T*ècvG$MCNj Jم?Iv56Hu> `pTʚ~~$IS% PZ,ճ(oIkRCw*} pTʚf$IUR=@S_(fj4ں>7̧Sg 1pTʚlj*Hs] Q:+>a/XiϦKRo> &ŀC2P8fSwͿ~:$)]?5O] E$K٠Fߐ_x>5^ r2P85߰8Hz?&p;?ƣ4޾%7I+MU֒| dRp(kiˣ$I
l]x A75jTmiu}oOݵR{ D3P85T=`ӑ$I.|_= dx?,Uit4ش"{Oj/?  42P85>F$6~~ e/HUk{Ǵv*NKuSkn?_  C2P8fO6Hv{ ѮP%LQ4Ի?)Z9 U*f1{l$IRPGkVܖF[ק](=? @pTʚsM$IA? L_ҠWuMJ/g#$ @pTʚG?IP^j[ ]Vx4鴅_uYy`j  i8T*èc}y$IA7,E `&Vokթsz; )aRp(k{;$IJ#_~ Ooՠj4ں>7̧Eo ̀C2P8fK'#IlZ~ ~~Gfx}u\wD>
  <y*f1[Fw\d$IRƣ>5w ̚1/KUOrMcaoߒפޥHܞo Jep̖{$I*p˅7 ̪3\SP_WJ%  LJep̎K$I*\go! 0Mㇿqca>u.J#_ ΀C2P8fGD?ITo
A `uz{G2Uv}`ӊ[w_2o 8T*ècv?"I
;7 hezi}Kn^z~`Xcn t0P851"I
Vx 	A ǿ:A']OZ79Mdw 2P851~"I
ֿ P'kDTNm]Sw>E bRp(k3b~ߔF"IJ5  P'Ko|Uog}4~yoRſ  fJep̆Ή~*$`? zA|x4ܼ&84uNycj  ʀCY3T$IR9 Z#!U;U(W}4uWSO¿  4Jep̆~*$Pw,˥ sگTU3_},:7̧E}¿  4Jep̆G?IT Pwï~:#O}`ӊ[wH<0k  Jep̆_~*$пi }+St? 4'SΉZ
 bRp(k3`~)OE$hx˙ 4eSQs[m]W}4uWZK  SeRp(kӯs룟$I*T7 ÞIM>Fw_Sw>_  ʀCY3~ HU~3= IzImVݷ16Hu  ԖJepL??UfԿcw 4ܞii{o:ma9ux} ʀCY3~;/~&$)w8}y M=i֪vnKw*w H*f1ƏL$IRFw]~s @|֪Sw>' icRp(kSn3S$I\ߏ; :O
o=ָ;} Y`Rp(kӭs$I]Z=+ vN`<LoKÛOOK,uNz}j-;  E*f1z^$Ivn >U){>h0W  P*f1G?I9 VLP_{n  Pg*f1݆D$IRƪcd ح}R}}iGo!Ԛ#  4JepLD$IRƆ7*  _(oIkRCSwAƘ  08T*èc[$uW~o  gjmiu}oP=??  pTʚq%IR}Zo |y  1P85oF?I-g    P*f1zi$I{    C2P8`1C$jIÞ~o    @pTʚm,yHL5    .8T*ècz<$IRzI    uaRp(kSj)C$    	ʀCY3N_4$IR~k    @pTʚt[OC$eaq    ubRp(kөwɟF?Ii~k    @pTʚt\,iHURk    ԉJepLW?4$IRw\~g    @pTʚt?pcӐ$I]    ʀCY3NU!I2HF    P7*f1}ڇ=;YHU~g    @pTʚg!I24iU    udRp(kӧ{λ$IPo!w    ԑJepLg?,$IRǿ:    :2P853tB$Iڹ-    2P853ں>YH	7    ʀC2P8[$Ip+1    8T*ècTG$IpS~9    2P85)t'!I&\"g    @MpTʚt'!I&ko    3ʀCY3.G?	I4_<*    :3P85һOB$My	1    8T*èc7,~$iµM    ufRp(kexOB$MXj~c    @pTʚt}sOB$M=    ;ʀCY3.[$I`Ǆ    Pw*f1]ގ'!I&X    Pw*f1=ڇ?'9H	O    Pw*f1=:'\s$IlN=o    ;ʀCY33$Io%    &0P85ѻ$I`[/    	8T*ècz?A$M/    	8T*ècz6$I    C2P8ֵA$M	?~_    @pTʚ}us$Ij4H}    hʀCY3[$IPw    *f1=$IP-o    h
ʀCY3TUA$M/    !8T*èc:}ES$Iwɟ    *f1:jS$I    C2P8CwD?I4:m}    MaRp(ka׏Y$I5i<J}    h
ʀCY3 I&T    4JepLc$IP{-    I8T*èc:rVS$Ijzm    MbRp(kaD?I4o    hʀCY3o]S$Iw    $*f1Ə$I҄    ĀC2P8C$I҄<0    &1P85)0oJU$I҄j/{A}    bRp(kG4HI5    4Jep@$Mo    hʀCY3=@$M7    4*f$I҄m,    1P85xK,H	5'o    hʀCY3׿#@$M    ƀC2P8;"H	ջo    hʀCY37g I&T~[    @pTʚGgG?I4g%    1P85x}&H	9    4JepC3$I}+o    hʀCY37޾%H	>9    4Jepīv|;HI4    4JepKV3$Ij/    &2P85`D?I4Ə[    @pTʚG/~$iB}Sm    MdRp(kǿ&	H	5    ȀC2P8?LN' I&    D*farگG?I47~[    @pTʚGE?I4N-    8T*è#VwG?I4_<*    &2P85XuD?I4    D*fO@$M	-    8T*è#֮#IQ    D*fkp' I&T    D*fkpqO@$M-    8T*è#˧F?I4g3    &2P85X[ώ~$iBuW~[    mKm    IDAT@pTʚGѝD?I4
-    8T*è#+$IPS~9    &2P85X{~$iBuN|]m    MdRp(k$I҄Oo    h"ʀCY35' I&Tgτ    D*fk' I&Ԯ}[    @pTʚG{$IP^~[    @pTʚG$IPc_~[    @pTʚGX$I}Ko    h"ʀCY3' I&T{    4JepJU$I҄j    ȀC2P8-//I&X{    h ʀCY3>_~I4*    aRp(kqGd_$Ma/    8T*è#NF%Ik    ȀC2P8ⴏ{e_$M0B    bpTʚI4˞~_    @n*fArE%Ik    ȀC2P8?HN/$I`    D*fAr$i~i}    MdRp(k$/$I`c_~_    @pTʚGi$I}    h"ʀCY3=_~I4:m}    MdRp(kqg/$I`?~_    @pTʚGE%I<0    &2P8585$Is    h"ʀCY3](/I&X_
/    8T*è#$Isꯆ    D*f{;$iu?    4Jep/$I`ݳ~_    @pTʚGIUw    D*fǀCz;    4Jept%IR}]    ȀC2P8pHT?~_    @pTʚG9$I~_    @pTʚGIUꏅ    D*fǀCz5    4Jep/$I`/    8T*è#$IjpI    4Jep/$I`[/    8T*è#NwD%Ivn}    MdRp(kqk~'/I&K    h"ʀCY3=_~I4Fl/    8T*è#NߊK	6M    4Jep/$I`ㇿ~_    @pTʚGoK	V=`}    MdRp(k$~#/I&٠~_    @pTʚGɩoK	Zw    McRp(k$/$Ipe1    i8T*è#_K	>7    4Jep~/$Ip>ߣo    hʀCY3 Yy`_$Mo    hʀCY3 OG%I҄    ƀC2P8ⴏ{e_$M~c    @pTʚGD%I҄]g7    4Jepi/{~_$MK    McRp(k$Inp    ƀC2P8-;/I&Ɠo    hʀCY3ƣ' I&s    hʀCY3' I&讫    hʀCY3Uu~$i~_    @pTʚG=	H	V=    ƀC2P8bU+	H	Vv    4*fkO@$M>7    4Jepo$I҄k/?     &1P85Xm7G?I4:'    ĀC2P8b>	H	]uP    MbRp(kFw]$I҄    ĀC2P8b$	H	׻7    4JepvN$I1    I8T*è#ӣ$Ip떅    $*fk' I&˧    $*fkp' I&p˺    ĀC2P8b7G?I4Fm1    I8T*è#VʏD?I4F    MbRp(k(	H	Wv    $*fw$IPk3    h
ʀCY3;$IPW    *f_G?IΩ~g    @SpTʚG~3	Hu~G    MaRp(k&'R$I]w    4JepD6	HX    MaRp(k~$)C[~g    @SpTʚGG?I    *flnƣg I&    hʀCY3Wu~$i~c    @SpTʚGj@$Mh    MaRp(k$IҤZ_    M`Rp(kg I2>ew    4JepsM3$I|    *fot%@$e{    *fo@$e?    *foOD?Iu    hʀCY30$IR_9+    &0P85x~8H:    &0P85x8H3    &0P85xs~7HUw    4Jepg I2>9    ԝJepg I2Y    ԝJepkg I2=    ԝJepkg I2ջ}    ԝJepL=SOA$eGo    9ʀCY3U I24w    ԝJepL{$I    ;ʀCY3mD?I7    Pw*f1Fw>)HU;3    8T*èc: Ir4o    3ʀCY3O~
$)S_~k    @pTʚt\$)HLuN[    ̀C2P8C3$IRz^    ufRp(kӡwD?I	5    8T*èc:t I25[    ̀C2P8C瓿$IRF[ׇ    Pg*f1ǿ:)HL-    :3P85>'$IT~k    @pTʚH~s$Ij[    ʀC2P8GăA$es/    PW*f1=$IRk    PW*f1=Fw>9HL/P    ueRp(kcx I25[    ʀC2P8㢟$I5    8T*èczHs$IkS    ueRp(kӣ$ITs[    ueRp(kӣ{oG?IjZ    PG*f1=:'!9HM    udRp(kӣ%A܉w]IHRVܨVT.:HU,Qkk{@ MY @!;YH!"$$BB%/eNfyx<wyH{    ȀCYp(4ٸw$IgS    2PV
̀]kߨ~$)'.5    8B3h?[$$IRPk-5    8B3h>V$$IRP[/-5    8B3hg~$)}w    GʀCpҷW?	I`'    7ʀCp7T?	I]?S~o    @p(+f.SIHFǾ    1PV
̀]F'!I7    2Ph2<窟$I
lz    2Ph28$I
l3    ee8ZfnM\T?I    ee8g9YHfm.    2PhJ68    2Ph3B$6:W    ee8gv	B$6>    2Ph3g!I||S    }b8GLg!I]st    }b8G?GB$6{    ĀCYp(4kB$r{    }b8Gg!I"[._~s    @_p(+fBi!I    ʀCp;$I
lt܋    ee8iqUOC$69    ee8iӪ$I
lv    2Ph4]OC$6'    ee8ir$I
l{    CYp(4veOC$E\6k{O    }`8G;|NӐ$I7?    >0PV
̀>iH'    >0PV
̀|w$IoC    =`8G{-~$)G    ʀCp⫟~$)-    ʀCpsW?I;    ee8kz!I    ΀CYp(4|$I
nxϕ    uʀCpyH'A    ]g8G{!I    ΀CYp(4F7    ՔB3h=4e$Io    3PV
̀ݖkߨ~"$)?    :ee8mk$I
n'    eʀCpgT?I_,9    8B3h囫$I
n|+o    2ee8mr몟$I
nzo    2ee8m|K$I
nv7    t2Ph6<t'"I[y}    ]f8G'"IO    UʀCprto3$I    ʀCYp(4[|D$7:wo    *ee8o~éD$79u7    t2Ph7g"I]ux    ]e8GM|M3$Io    2PV
̀F<Hk(9    8B3h;QL$IRB}\~w    @p(+f{=i"I    :ȀCYp(4nXYT$IRpS    .2PV
̀]^T$IRpӋ/9    8B3u'T?Is    EʀCpt}$I
nqo    "ee8a|U?Ib֬mڽ    1PV
̀FOE$%4<    ee8IVq/*;    k.MYp(4ش{,E$79w    t2Phݱ֭E$7}7    t2Ph1"I[vy    ]c8Gw̮9H    %ʀCpt㛪$IJh.;    K8B3ɯ~.$)ѿY~w    @p(+f#~H&gm    ]b8GwJs$I	>uD    ]b8G,߮~2$)W.+9    K8B3׮~2$)xKa    CYp(4n}'#I    
ee8ez$IJhT~w    @Wp(+f-S^Yd$IRB    0PV
̀[?HfW    0PV
̀[~_$I	o    0PV
̀{{$I
n9    0PV
̀{_Yl$IRBZ~w    @p(+f=Wl$IRB    CYp(4g$I	M>w    t2Ph3˪$IJhv    ee8gx/V?I    ee8g'U?Irpw    ]`8G7m$I    3PV
̀_dӑ$I	z^    mg8G7>#I    ΀CYp(4n|$IJhzšw    2Ph4>$IJh~w    2Ph4<t#IZ);    8B3>O~:$)[~    63PV
̀}HFGf    mf8GwoH&缾    63PV
̀fWHf]~w    @p(+f]#IZ|    ̀CYp(4{G$e45kS~{    @[p(+f]w>Hd    me8Gmڽi'$I    ZʀCYp(4n['$I||S    me8G?wZ$I	ͮ?    2PV
̀ۦ[$IRBn,;    8B3/~B$)żY    2Ph6|~B$){    FʀCpt`'4rY$IRBS^Y~{    @p(+f}-U?#Iⷖ    FʀCptV?#I    FʀCpt$IJh    ȀCYp(4H$%5    2Ph7:׫$IJjtso    hee8oT?#I̿*=    m8B3$I]    ƀCYp(4~ziS$I	o    1PV
̀f:)Io5kv)=    M8B3ٯ~J$)[    61PV
̀F<)IFN    mb8G?|ZS$IIM{c    mb8GOlصi$I}    }    IDAT2Ph$IZuc    mb8G̮;9Ifo    hee8cMI$%5<o    hee8c|T?'I?+=    -8B3ms$IIM/\~{    @[p(+f#{>i'%Irq    -a8G,'%IZ4kv)=    8B3gO~R$)?V~{    @p(+f/o~R$)q/,=    8B3W$IRR[շ    2Ph2<'$IJjv)    2Ph=1M3V?+I7    ʀCpWW?+Irr    `8G>g%I    p(+f?sYIo    T3PV
̀Fg%I]    p(+f?p$II-rY    8B3%I25kv-=    2Ph4%I    T2PV
̀fWV$IRR    JʀCpT?-Io    d8G?%I    *p(+fO}iI\~{    @%ee8kyK$e\67}o    U8B3MU?/I    PŀCYp(4^%I7    T1PV
̀ƧyIf]~{    @ee8k_~^$))=    2Ph5	M\V?1Ib֬    *p(+fo{\$IRRC(=    2Ph6OL$%5>Oo    `8GM/ܷIo.=    2Ph6>OL$%5    *p(+foÃI    ̀CYp(4$IJjxO    ̀CYp(4[~U3$IIO    p(+fOY$IRR+=     2Ph7k$IJjso    f8G|N3$II-,=     2Ph7x6rY$IRR~    LʀCp彷T?5I~    LʀCpϨ~j$)yo,=     2Pha}$IJjvo    d8j🫟$IJj͛o    d8jǫ$Ijlo    d1PV
̀cElصYN~n$)ёϩ?     2PhcOV?7I#]~{    @ee8Vê$IJjvo    b8ꘜ߫$IJjqǵ    d1PV
̀cu&IO=[~    @ee8V`'6rY$IRRC~    ʀCp=_~r$)*=     2Phe~éON$%5|s    8B3X-o~r$)W.+=     2Phet$Ij:h6V~    @4ee8VU?9I]?S~    @4ee8V̆]xK$IIOye    8B3X=[/~v$)e    ̀CYp(43g'Irq    8B3X=^]$IRR}ǔ    ɀCYp(43<竟$IJlxO    ɀCYp(4黚f>~z$)_V    @ ee8Vk$IJjzɁ    D2PV
̀c5ͮ~oӓ$IIo    HʀCpɇ_[$IRRfmî    D1PV
̀c5'I    b8jY.$IJj|K    b8Zuc$IIM/~K    Q8B3X]N~~$)>^~{    @ee8V7T??Irtoa    "p(+fFGF$I|Z    8B3X]}\$IRb    ʀCp۪$IJjz~    D0PV
̀c?'(I    "p(+fڦY%IRR    D0PV
̀c{a$I    7ee8V?R%IRb_\~    z3PV
̀g(I~b    ֛2Pho:J7U~{    z3PV
̀ET?CIr    ֛2PhOzi3$IC    'ee8P$%6:    'ee8X۰k)JU    :2PV
̀^R%IRR*=    `=p(+fVU%IRR]    'ee8j|ꫪ$IJl-?    `p(+fVϪ~$)	/)?    `p(+fwlܭi(I^_    ĀCYp(4(It^    ŀCYp(47(IZլmإ    `8(I    ee8p󳪟$IJl|K    XʀCpmܭi')I^    ց2Ph<˫$IJj~    ee8xT?IIrr_a    v2Ph<WU?II.?    `gp(+f7?IJ'    e85tX,%IRR?    `'p(+f-nYJ^Z~{    2PV
̀^qH$IYM\    ee8x񩯪~$)g    38B3U,%IRb[Ǜ    ee8lܭi)I^qh    ;CYp(4+$IJjq    ee8x(['$IZfmǖ    8B3ࡌO)I    (ee8x(Ϫ~$)    e8inM3V?OISG    8B3,nyJ_t    ;ʀCYp(4C$Ij1kz|    ;CYp(4?~$){~    a8gxV?OIה    #8B3amڽif'*I]st    ;CYp(4˫$IJjq    ee8x$UD%IRVE3p   AʀCpHƧJFG=    e8dgT?QI7    8B3mصYT?SI    NʀCph7_PL%IRRo}    e8fz[$IJlpS    ʀCph'a3$I}A    ÀCYp(4U?SI    =8B3QmإY~$)ϭ?    `;p(+f*IZg    ʀCYp(4?.IV;~    me8bt$IJl    8B3`[xjS$IM/;    me8jV?WIKo    VʀCp;Jffm    lee8Vcs$Iݣ    ma8jtoV?WICQ~    0PV
̀m5xlJf:    ma8cyϗ$IJjo    ʀCp=fםXd%IRVE3    <ee8s^_d%IRb#S~    1PV
̀1:OV$%uY}    1PV
̀1	MW?[I'    h8B3`{-J\~{    1PV
̀5$IJl    H8B3`{M|M$Iy~    ĀCYp(4_~$){    H8B3`ئ$IJj~Y    <ee8ۯ~$)چ]    x8ʀCp#o~$)O+?    p(+f+I    2Ph?Ut%IRbK,?    p(+fٰk}J\\    0PV
̀5+IM    P8B3`GM/xs$Iݣ    b8;jt܋$IJlr_    P8B3`Gxj$Iͮ9    b8;c',IZ|    <ee8N~$)I    <2Phɹo~$)ѿQ~    p(+f',I|lC    f8;cf1~ƒ$)>\~    p(+fZy}3$II-w7kv)?    8B3`gͮ~o3$I|Z    d8;kr_V?cIT~    p(+fG3$IM/;    2PV
̀i$IJjO     ʀCp^Z%IRVqc    2Ph~ʒ$)aX~    8B3`=?_$IJlז    p?ee8X÷?)Kf[~    8B3`]lإY~Β$)7X    a8egW?gIr    2PV
̀2=,Io    2Ph1ϯ~Β$){    2Ph~9K_<    8B3`=-r$II-G6kv)?    CYp(4$IJlxO    `8ir몟$IJl|    0PV
̀4:W$IJlz    8B3`]MU?kI    V2Ph>]%IRVi    V2PhU~֒$).?    XmʀCpƧYK&g   f8mZ$%6   f8nc-IZ{s   J3PV
̀/~ڒ$)?X~    8B3 T?mI    .ee80>$IJlx    `up(+fA~iK\\~    8B3 _~ޒ$)Y]    ɀCYp(4?F$I    ɀCYp(4L>yK&~m   j2PV
̀(yKf9    `5p(+fAi'.IZ   d8wX%IRbR~    z8B3 c$IJlt܋    V2PhD|䯫$IJlz    ǀCYp(4"O\$%6   c8|l\$e56kvA    X)ʀCpmqU\$%6<    V2PhD^qH3$IM|M   j1PV
̀h_Q%IRbk-?    X-ʀCpmxOU?sI/    ee8af9K?   `ep(+fAM~$)q/,?    XʀCpa}$IJlz~    ÀCYp(42.I|A   0PV
̀K̦fmn7    CYp(4,ｹKĆQ~    8B3 $IJlr_    ee829o$IJlv1    CYp(4.I[|   `8i|\̧O^$%6o    zπCYp(42-zu$I}A   @p(+fAٕ~$)    2PhdO^$%6'    πCYp(42'/I2M     2PhڰK[%IRbwB   @p(+fA>V%IRb   ~3PV
̀l\%IRbN,?    7ee86:^$%r{   @p(+fAO~$)[   8B3[V?}I    2PhT}O_$%6;    ˀCYp(4*Ly}ӗ$I-zu   @p(+fAV%IRfy3	7    d8%Y̪$IJl_    KʀCpPeOW?IcX~    OʀCpPev{$IJl~Y    d8UƧKĖ{     2PhTg$IJn   1PV
̀2vm-՟$IJl|     2PhTO@$%6   1PV
̀J$IRb    8B3W$)O)A    ee848՟$IJnt܋o    ŀCYp(4-VHĦ    _8B3?IK    ŀCYp(4M@$e67k{>   ?8B3V$).A    ee8(4bV)H&缾   78B3_S$Io8    ?8B3f:S$I-,?    ee8hi$IRr[Q]}    ʀCpϬ$IRr_Q~    ʀCp
,'U$)ٕ     2Ph?I    CYp(4bz՟$Il;K    IDATl>   8B3-'s$Iɍ   3PV
̀_W$)   8B3M[n$$IRb[/-?    >ee8hV$)Yo    ̀CYp(4d$$IRr#[~    mʀCp&WIH&罱   8B3M<iB$%6o    ̀CYp(4fq՟$IJl9Ҭm|L   @wp(+fA̮>$I   2PV
̀՟$IJnrko    ˀCYp(4fY՟$IJnv݉7    e8ٻhBRjs&vj,iY̜8f.ᢄ1rR؈\@4 QKP".ٿXNB|o?k=^_ɀCkbQ{ PP#7$I$IF6J1 +5 PXW $I$I8(ŀ8O~ @a~H$I$i432P^O (lpD$I$IpX~ @a~H$I$i432PSy$y  %ujoI$I$^bAVjj]WE? oA$I$I4zpPYp{O  
o>=$I$IeA)deֹ (l/ $I$I8(ŀ8Z'Ұ~" @IU?M;D$I$Ip; PoኾA$I$I4ZpPYprA 
ݰ,$I$IheA)de&׽]O (Ƶ7$I$IF+J1 +5Y~" @auow8"$I$IdA)deF7qDJg >w$I$IF&J1 +5	 PXA$I$I4:pPYp7L ª
A$I$I4:pPYpu/g VHSC$I$I4pPYpN{e3 ;D$I$IpFG
 PXo~H$I$i422(TuUS 
qY"I$IȀR8ʀCPD? z7$I$IF#J1 +BT  d"I$IgA)deQu) ֽ/I$I$5?J1 +J~. @akoI$I$5?J1 +JΏ~. @a $I$Ij~bAVW3  Z_I$I$5;J1 +J^\  KI$I$5;J1 +LRd C$I$I8(ŀ84JUd ~H$I$pPYpho>-  Z+_~H$I$pPYph^O нI$I$57J1 +R^d  [
C$I$I8(ŀ84jO?l ~H$I$pPYphԪ~e J:w$I$IpFu~6 @oC$I$I8(ŀ84ju.xC ?F"I$IffA)deQu) 6|;D$I$-Жګ~*u,gbAVņt ҆Uj;D$I$^:16MjTE15qD>̀R8ʀC -w$I$IZ+^:kMK`4ܹ?1£3kfbAVźW3  7/$I$I#䑩}/'&r}z߿pPYphk ~w$I$IZ+Iuǥͧj9DK332H6(ս (m8kJ%I$I>kԹ荩i2U7z;YzjfbAVժo~> @7!$I$)/L5ǦƥiumܖR]YpPYphT߼2  i"I$I
6(W/NKR˪Rn}/opPYphT^ 0֗I$IcRgq{?
SRt.x}FpFi~> @a3moI$I4Z'xG\{|oHto	M332(W?p tv"I$I#SצƥiumܖR]Qӹm[jFbAV媯_  ͧ!$I$ M,JՋSw߲*U;6T8^jFbAV 5$I$I߫Yw\mQ('Ӹ^53J1 +r^ *NzI-"I$IBuΚcK{KIS)̀R8ʀC\kŋ `|woI$Iƾ#SצƥiumܖR]E322Ш7|g ;D$IjbQj^뗤Uڱ9A7 w?pPYphv~3 }{"I$I(ZyL;.6M(GBƓ8(ŀ84u~g3 ":᷈$I$IPH5(;/OGY~+h332Ш> ҹoI$I{?
wֵis[Juc5#J1 +|R  ӟ~H$I\W%{~NvlNiЍ}ra皙pơ `WI$IJZyL;.6MjT||?pơ+ S딗"$I$uѩ۸tGO>8)ꮫlhfbAV~S Lѷ$I$Isn^8u~מp綔aCu5^4#J1 +C^  /E$I$I:Zg*u/I-RcsJNupPYph\~89 ~H$I\b璷MKMun	3pPYph\~es "uj#᷈$I$IӵN<:uz(z?93φL332иԻ ^[D$I 8"W/Q([MÝR?&[iFbAV:>9 A_:;$I$[Vj	0|?pƥ֊4 `oI$IxZԹRƓSu</1?pƩ+ 0N[D$I4`gͱqil]P`?gV33285' ^g᷈$I$i8"W/NK|R?2BO|#ϱfdA)deq{_E?)  +"$IZyL^=cjaq\kfbAVg:I A
E$I$IcκRodoHuWCSpPYphX3
 O#$I"V(uzֵis[,38(ŀ84nU  Ou-"I$Izq_PܖҰ1XЌ8(ŀ84no^  ;/E$I$IQ(OMՎ)?r4<oD332иս n}7M-;<$I$|^:16MjTO}'K8+hfbAVZ+_ @!$I$/L5ǦƥiumܖR]G(	>4#J1 +cG?-  H3~H$I&HՋSw߲jGTazSK32286?F?-  Hu5᷈$I$-Z+Iu(OߊtߛffA)deqwO oG$I$ikԹ{7zjgOPNpƱ~Z @y~H$IشⅩ۸4MÝR N=pƲ/Li8~^ @g#$I4M,JՋSw߲*U;6T̃ƙZvX{ճ22и6| [D$IFcRgq{?
|,%ܦ&zvbAV (Ajxt="I$IMuҋ~ʵǧjTOF燿i=;J1 +kݫ*y :k~H$IRXG9MK`4ܹ-Q	/zVbAVg\ ?{D$I4(W/NKR˪=+`͟ˀR8ʀCc۲S}: A~5$IV:KM{?
d`NzI=;J1 +s~b @Np="I$IsuKSgSoDTvFL8NzvbAV7~b @e~H$IA7ydj۸4MÝӁizVbAV:- ~H$I>Xgl^4G۷4D։Gѳ22и$ p/$IκRodoHu{WLL_W8(ŀ84O~f @M="I$ia:SoJaXc?ljQ_k8(ŀ84, W+$I4MګcumܖR=Qlj?zVbAVz 4vE="I$i|j]$JՎ):? H΀R8ʀC^# @ӟ+=5(&$I4zV:KM{?
D8@u'̀R8ʀCcY7=I$I$5։GΚcSo=Rz GU,̀R8ʀC7D?5  Pe$I5qDj^P;TtFEՋ:pPYph! qs="I$)P=JՎ~c/07N5̀R8ʀCe HAjD$IRFgqi2U7Hqӛ
ZpPYph!:Ǣ I$I$oN5Ǧƥiumw g¿ifbAVZ(O? @[G$I$͡#R{]$n=7wnKF,@upJm룟 h=$IC(eoO-RcsJv {L4SH̀R8ʀCg. ZgxM"I$icκRodoHu NM̀R8ʀCy~n @
I$I^kŋRgͱqil]P FH穊pLˏJE?9  `7$I8"W/NK|R? I__5#J1 +-9 ΓijbQM"I$Go>5U;6oG 0ꧾV332BO /$$I8:%sSodoHusÿkfbAVZHu/' ݰ,&$IF֊ΚcSo4غ6wn>ԻpPYph!:UO V9&$Izq_[V#4Oy~՚pZG i8H^~H$IMYw\|jvlNߊm_53J1 +-~v @oI$IZޱVkR~"<9#\332Bw{ ˙7$I/L5Ǧƥiu:y-5^322Bs룟 l=7$I4M,JՋSw߲jGT`,U}>fdA)de׊4D?=  XK$I9C{{Ab귢OlF(8~{k u?77$It0NzޏBTmߐ꩝4Vpb/ `O$$IҌ&Ls^zֵis[Ju}>/]B322B/ 7??.$InbQj^뗤Uڱ9})[?=D322Bꧢ  #.$I©Yw\mL}0z	pPYphAT~~ @I$e^:kMkOX<qu̀R8ʀCꞍ 6|D$Ic䑩}kSo4غ6wnK] 2߼2{fdA)deZe h:.$I5(W/NKR˪T؜Ҡ}PP'?Ҍ8(ŀ8P\ 4@w%$IjnǤκRoޏBi>aֻߟ43J1 +-Z'Ұ~ @W%$IjF uP<ջ>Whާ=K332Bns>3ˣI$nȽr`4ܹ->OOM1ȀR8ʀCmE?A :z]"IxU_[Vj3#ffA)de\~ @o>5.$IZyL;.6MjT>9#OI:̀R8ʀC_	 0|kw$IfWH5Ǧƥiphy	\ptKu{W3 uj$I{Jkp綔a5	'jFbAVZU߸6 нw$I]W%eUvlNiЉ> upz.~ @]~H$-Z+IuǥަTmߐ'" S#>ffA)de^g[!  u=;6$IZN<:uz(z  Y^pPYph:%>+ أsޯ&$IczBznb iU?U322xr]"I4ҽeUvlNiЉ> `^N﷚p4 4۷%$ITk+RKNI7TI ٵNyY`̀R8ʀCz^^WO hoF&$IMu΅z׽7U_2O?}@pPYpH9  Ӧѷ$IRxG%ipis[J0TxNi3J1 +yijan?*6$I*o!^߲*U;6oGe HwbAVު)9 MЛJSˏ
M$Ir5:KMھ!խǣ/0 '\΀R8ʀC L}sm"I4V(uzֵ{?
 #@[    IDAT׾329ע# [M$I#R{]dGLTO+ +}fA)de!N^ ~D$ ?
ڱ9~;Wuu}gA)de!}n~ @CD$kԹ荩i2U7z; ,HI}hpPYpH߫3$ ~HYkŋRgͱqH4ܹ->  8(ŀ8ս$ CM$Ih^8u/I-~JՏ> xr}fA)de!}֩/~ @S:e$Izߩz)W pz~GhpPYpHϮu b߄M$Ix6|kѧ 0~GhpPYpHnc h&$i<z( f{wbAVҳ~򯣟% u45yd}"IƯL Bgqwpgl sI4fM,J `:Z-}fA)de!ZvXOD?M !}"Iƪ)/>q Yj[B΀R8ʀCYuϧ& M$Ix. j᷄X2 +if>i O'$i|j ߤ}Kh?7p4Ϻ gO;>$ISߌ>o Y<2о32	/HG?O !7'$il^ 0VgA)de!_~ @ST:%$IW# fhgA)de!U h~Hw>m Y>~OgA)de!eo~ @<>$IQE6 ,uKgA)de!WD?O A4E$~\}  P;BπR8ʀCF?Q A:D$~g 0/
#8(ŀ87ǣ(  [O$I7|ZgA)de!ކ~ @ԻKSQ$IhW? fwwpg& >Q$IhWw>i Y^wptS hͧ($it[s 7~32\k)  ~Hѭu+ `k~%32\oD3 	Q$Ih>E2 ,WT-YbAVҁ\ h޵Ǉ($i4|Mѧ 0K(32\kŋR*  on	Q$IhֽϣO `6UZvx-gA)de!=wGT&E$^ӿ =8J1 +quS {oI4z; MÝ8J1 +~O* 0=oI4z>c Y1Ё32i?TtS--I7}  0=#t8(ŀ8~ heoQ$Ih `4;B΀R8ʀC:w\\|E$POG0 ,o<932ާss >~HѨuˣ `z᷄ptp
 4P~HѨ}kO `Wy-縵8(Ā8lbў _;E$DO `4u>[B΀R8ʀC:~ @ԝ')$u?7ѧ 0KӿI+Ё32gG?Y :k~H܉g 0K[B΀R8ʀC::f hpyw$Ij~>[ Y:᷄pt^ n}7MMHFW= +sgA)de!ZolM]w$Ijv3D, ,wn#pPYpHV h	S$IR[~TJ0d f[Bϙpthu> hzcijbQ"IY{OG+ ,n(A[bAVҡ:3 >u[E$5G}  Կ[Bϝpt# ;E$5'&T f~K32Ύ~ @O?~HտS %o%pPYpH^tj[E$5>S Yj߇z8(ŀ8C 4Tg*$yr RWz8(ŀ85| 4P4[E$53 z&%pPYpHkpE h[E$5)/>O Yw?~K22fWwD?_ "ISE' ,-eA)de!ͮ2 U?4{E$5U}  Tm~K22f_#O hy~Hf|Zi %tppPYpHop'0 P[
U$IR37wԻaY-ˀR8ʀC}O' 4T=45qD"I>~Oi GE:8(ŀ8>5O hE!^$IMRՏ>K Y}K=ʀR8ʀCCOug 4IZC?}  s>22Vu1 Pu4$IsE$ NyY=ˀR8ʀC[? h'^$Iq=> fkMS'tppPYpHs}/G?c _8^$Iq~, f~[Bp4&LuowS jN:7$I
iW `o	|bAVܫ 4X?
W$IR@GTO `_]O32^F?e _{E$}֫ `[~On/
1 +iJS lI^~Hu+ 'tpPYpH+Q{S hY$IRO>A 9\{Bp4?U]t"IV{M	 A'tpPYpHS~ @uꏄ,$\G/ `45qD=πR8ʀC:.9 ۸4f$IejO `''thpPYpHԛ~ @5f$IE\ φ:8(ŀ8' 4\{E$wG ra=CˀR8ʀCz7,~ @o:%f$Iqi G:8(ŀ8sޯF?i JS[$IR]G t{Bp4M~_JV sI)/MO `:.СeA)de!o~ @rA"IoE NBp46MF?k i-$)On  FܠOG0J1 +i~ Oq"ITݳ1  `==J1 +i[ 4\u?-$)KS ׆:8(ŀ8zsO h N}y"I2 9|#7=J1 +ivy F@o	[$IğD {OMCπR8ʀC:!i #`mw$I?#  ?)tpPYpHZ~TJN F@{E$[C_>/ 9jo
zbAVR>|z"I^RՋ>/ 9j_:8(ŀ8<6MD?o `ԻKSG.$iu. tMeA)de!s뢟7 0":5v$Isg 0Go})2225yd{8 0ퟌ]$IҜlY `o
.J1 +)_սD?q `᷋$ICߗR}U  sԻ
*J1 +)_k' ޵Ǉ.$iu}N  {]bAVR' e/$iv{o9 ̃?~WhvpPYpHXg y_$IҬ1 0a:
.J1 +)o]WE?s `Dra"If/pt>% 9w=WhpPYpHyQћJ_$Iҡ#T`<TL]9dbAVRgl3 FH_$IҡջG <oY~WhpPYpH[vXw?Q=E$RՃ7E <mBπR8ʀCK: 0Bګ/$T `t.BπR8ʀC_wF?u `7~HsE <i᷅fp~" #n=~HnG <{|$zmgA)de!~rGs FH?_$IsW?l  
-J1 +L/~ vl_$Iҁk ']~[hpT% 13.$Iqi  ̓ަBsˀR8ʀC*Sk+; 0b~HWݳ1\  I~[hnpPYpH>~w FH}:V($IhQ)[ 0Og|}9eA)de!s< 0bW+$I33 /uV022ս< 0b߾=$I3ܺ&L  IC᷅pT?Ұ~ iw$IM,J 'սsbAVRن9 #fpE7$I^-<  QpTMD?{ `{~W#I `uBsπR8ʀC*[7D?{ `>;F$@i  ̣Y/48(ŀ8-~J e2$-g|Y  ̧oÝfA!de! 71$-[}  h'J1 +|k[ F4$i7|  G~<dA)de!o  Y]m-#IB yֻCupPYpH-;,ջ~ [FZD <Cpe 8dVjC᷌$I1 u+oObAVRL Q]-#IB}G  <ۻofA!de!Z=c p'w#IRͧG  <1eA)de!5/ ^᷌$IeoE Y3[bAVR\-  oIJ3[? Aw8(ŀ8:뎋  1$i!4ʅrˀR8ʀCu)U/ {FoQ<m ouo[bAVRlӿ `V:GIƹe Ƞu̀R8ʀCwò/ {Fqo @ׯ34pPYpHM l'RkŋoIƱ֩/ѧ 0[~kh~32X/ }7$IcXF 2^᷆7J1 +)_ 0[SLSG4$UO WtỳR8ʀCɿR  i$I:}Sw  {X3fA)de!:Ǣ  #n$Iߖ	 z[CpԌ  quǅ4$CS_RՏ d|zπR8ʀCjF/|0 074$C!: Q~oh32Qg훣  cWIFe MCpԐR% q]W5$pov dTHS94pPYpHͩ/	 ~H4M!Uw}<pPYpHͩDI  `FQuƫRV7~s(ObAVRsjg$  `X
m$I] ȬsoɀR8ʀCjV,  c`IF?o @f,P8(ŀ8f5G,  [8>᷍$IR dV~,P8(ŀ8f5  oIFO3ߎ dVC22UģS_ qPSo$Ijz+] (i2P8(ŀ8U=xc `Ln]~H;E 
C22WFi  ƅ!I|췢[ N}y|pPYpHͫ}/Di  	o$IjjU O=~w(obAVR[vXw? U/N7$I}ο. R}Co;
1 +  CUw]- (w=7J1 +u// 8q$Ijoߨ @!CpZ,z% #]~HԔ? (S딗ʛp܆R `>oIk X@O|#PπB8ʀCjnM_" 1SG誻)[2 Pʟp6K 0:!Α$)gm} AT32ܲR_& 131mwF#IR@ӿ
 XXګ ʟpe C~HTo nJSCT32]璷E  ;Ģ[GU^- (oɀR8ʀCjx+^Ҡ C$I\o @u	CT&J1 +U߸6K 0JS'|#IR߾=[/ s"ػf!x'5FMmڦX5&zf]wML]cȚfġDc)E:Cs㺒(eux}l̕ȀpP*ѧ h;#IRH\  tz?=-j2*ʀCA/> @[$IS蟸 @",bA8f?s :$ݣ AƗQupPJe!5eF <|C{G.[F蟴 @QupPJe!5}. 3<$go# R)'#.bA8xT> @O{_ϋ]    IDATGy) Q?*bA84 XoI &QpPJe!5> @ˍ_oIٿU
 <Mj3*ʀCjN_
 mL]=$mm^Jņ5?R`_.QpPJe!5+ rH:<G) LUU1TR]0}6 w$I[Z7O ~)]1TRKg ;Sog}$Im5G j`&<bA85 VG _3#If6:?:|7&>bA85 td^$iSe4Q/'' P^-1}3*ʀCj^}: 񍹿,#IS5uyL &+(&bA8dT7D # #Iғ4<?*b2*ʀCjf[Ό> @GKHe<?D j䯄QU1TR3ߣ !o$GtzH F#haE1pPJe!56 tw$Ig~8G# P3[
(.bA86' b7$Iف/M @͌eAU8(F_X	 :frg@7] @yU[EapPJe!58 $uъݢ 5Tl?fUU1TR)  S+e{$u!Ni2Q 䆓*
~+pPJe!5># @:"$IXKvJ}7F jjxG+
̀pP*|C (೿$ueF jlWGWU1TRÛYG>% @)'C78)y> WWU1TR+ "Lsv[H_y @M9&͢82೿}J !IRK[sW_ nQxTŀRpH-h<}N go"IR\r @Ew3*ʀCjG>}N W_zwI h-GTŀRpHhx	 q	IQ_  6e|o#bA8v씦 tYqoI]׳RneO5 !'+zdAU8(Ԟ}R +zkSE"IRCY9; d_nèpPJe!W.  靗ޢF5:_ MaT82Stה"  $Ijx:. 5:o'bA8vseY OyOHԌG!q hǨ>pPJe!ѹ>+  s#sOGzTl? 0ņ57 -dAU8(Ԯ^}V  ~ _}]-9$Ig^N߉q 4c2WTŀRpH+_s}i ɷ>>$հ;mG jxǿgT82>-  ?dt?$IjrQ? 'sW{FʀpP*}<  "ON$գ 4gT82Y C#$IRlϿ? 4hno/bA8v6hIy xl焿$I1>{)M? wU1TR;} Ro%IR{SJA! GIo/bA86o Jkm c6gTŀRpHm|>' ID{IT~~1u?v G3bA8?◣O +4<o&IRy< t=w	㨞pPJe!Ug MGipܛL/;?b]?i  fAU8(Ɨ}f  R1X&$I/J÷G Zft9oTŀRpHE M*3etI[  -?Uo7bA87 >5  S~nIe$}?G
 B-zgAU8(W}j  6K~U)s$i/{  (;wTŀRpHoߎ>5  m[sJ]*zk  -6yT82:vذ&  l_JEǿ$IR= hb_̀pP*M>2  l'QQ'opܛSd  -7?bA8n48w f$Iop;ST  0Q3*ʀCЯQy &~!I5k4G  `2LٞT82e' `:!I5iT? ~+5#bA8?עO V\sC"[0<4 1ó>R#2*ʀCP3Rg `G&Iٿ|~ T>Mپ/pPJe!u%G m2#I| Ԝ82UG m6[}J^7bg W!=dAU8(Խ}z  /ޒVֆIJ~ :,;gDjNTŀRpHk|ѧ `^Li+Ij[}JE}W_&R2*ʀC^C^}z  w"gFݟ&\i HfFjTTŀRpH, 0o{Nپ/cIR+5Gt 9C!}feAU8(F2  ̫U,IjbޖS 0'_2}eAU8(Ͳ^RQD  yUd1֒4 VRGp _;IˀpP*U  3kIRy~~W qGj[IˀpP*x	 (G>M/U{K3G  SlXz3ۅԼ82[5 @/oD$V2t} #LjdTŀRpHnz%g TK;$#mGe 48-&53bA8n7D! ᆧ'ك )KENjfTŀRpH.)S Pol_Teٞ5GG` 2U1T}  *Q<|{/{EK̯Uѧ `;_PjnTŀRpHS Pbho0I*%;%OO. f+ߕz3RjlTŀRpHxfJ^9 N>M$i);W `/7-fgAU8(&7}  *7$ms 6MFgAU8('- 2eKwI68wRw) VĢTj~TŀRpHkx_I Qdg?M&I[Ps䚣S*3
 MF̄82 (~@ow$miME	 0/^R3*ʀC?◢O @sSfDyU~Q 7XjGTŀRpHzlڛ @{Ii|ف)M' `^ڑU1T>K  */K;$uH" +ڑU1T[vS* Pפ~.&{43 PٷNKɀpP*I?ߧ Ê4⟧̂𷚤n'7h\ hG^jOTŀRpHцg}$4 t効b5&4Zh I7ZU1T~lOi܏>O  T֧YfԢ_Tl/ T:UpPJe!鉚| Pk~%eK_nfK?u+O @g~8=VeAU8('jpۣ @zshaMR. ĘS׳djWTŀRpHzm =WᯋI}ޜw^}  BMnBLˀpP*IOO @s4|Y%'~4]ua  }eAU8('O @ޛg|0f$dqEѧ	 64/bA8$=UF) F?9Il{+ Ɨ^S+3*ʀCS5:g
 i_uDy^NR-1!< SwZU1Tls  [Ks>zKvI=wIsg*'  Z~o77bA8$mω>U  0_[0'ia]xn PqjgTŀRpHT}  Z%_{+'iiR' 9&ڛU1T6S=}  Zgz73ޓ윆g|0^}:  iro::bA8$mN˗E+ ֚yio>IOx|~=}*  mp[vjwTŀRpHڜ&\ t幩ηha49)yi  hb]7];O΀pP*I* /J~O߶=S3  *o跞ڟU1T6>Y  wc[}[PjmKvNޛRQD hHwZU1T6lg4G- ׭xFPjE3ӿ&?  6:U1T'E- *RvK߅RitQ  g@u#bA8$mI}  ȧir˙i
Ju/i|r :mLpPJe!iYuE.  ]ibT}g|0Mo]R>c
 Y;pPJe!iK](t &448-s7TuF  oTpPJe!iKxqJE}  xڛ:(Y+h?](  5379825MW}  ؔ"O;/MóV;.4pqW_' 0:Gu*bA8$mM}  p+'-9s1Tl?  c2woIu+bA8$mUwLE`	 `+uiwߖҏ?Uib4?2  l')ս82/?8 fGkN:7ҍ~ceKwM3?<x_  c{pPJe!ik |giz4</SO7޲=9|ƗצT `T73*ʀCҶ{M 4M$VS7 48i|~?_  hGߟfTŀRpHږ_3 @'J/&W6  :nHIApPJe!i>e  T,_{s_~p)'ߥkN>&7!O  xߧlTŀRpHW}  ?pk\sL~ῥFUI-Z*iOS @M{mÙpP*I\%2  UlX.OH>j[5`_,M4Q/?Z  oƿa824} 'S)irÉit+uifAQz  [dvU3*ʀC|4W( *6ޗ+W%2ZNKvNC!N4:irݱ)T6F  +ޛo^u:bA8$KKvJE`I %#kKAio7jG&W.HC  J3dAU8(j  e+6ޟ{LoƗF?'3zcʖzw{O/L_'-P]0&~:MW8  ]T?fV3*ʀC|5Ho P;\4444sap11+E^67Wd{RyfA~Nɹ3ޔ'oW>PF'  <_mZ̀pP*Ir  hQ/uxx\)_}5izizŏ_k߿TN)F
  J18ߥ824O    @kRoߥ824->VG6     J6pq7i3*ʀC|7    h0eTh?2*ʀC|b    &-ZzlTŀRpH*ˣ     %c3*ʀCR>    Lo;/pPJe!fK÷G8     ~$bA8$OF8     QҏfAU8(ɔ3    <~¿=KOU1Tlrg    yPץ,=QTŀRpH*}     oYz82Tv=WF:     to,bA8$D:     [,=UTŀRpH*;{     [5KOU1ThtL    `+Loz7fiSpPJe!}_d}     BYTTŀRpHG<     @nel}YTTŀRpHᯏ>y     lї6۲9pPJe!ʦw^}     dAU8(*'g    0dofAU8(J[0}     x*aoffAU8(-    W-Yڒ82TuIiԋ>     <|:_GK$bA8$E4    |oҖfAU8(:>     <VQY82tՅ'    ǘrVcik2*ʀCRT}    xѿXښ82v)_w[    `o߸VfAU8(F_3    @Jipܛ¿K[U1TB>     sH    IDATUbi2*ʀCRto}
    :mp;ÿKےU1Ts    I[RofoҶdAU8(:4s    I?X82TU>>     R<*mX82T&}    :emX82TG!$    tF[sai>2*ʀCRyIY    9&,WTŀRpHS0,    ^{ e{<34_pPJe!V,HڛO#    @1bA8$խY>     UlXz?-[4pPJe!v-)VGG    V-hw`i3*ʀCR-<    N.4pPJe!e{x*O$    @22*ʀCR]_v`    h;Ro~22*ʀCR]˖((L    ʀpP*Iun$    @}?mW*+bA8$չRQDJ    F_ÿJefAU8(7O%    @ckoN¿JefAU8(?ѧ    Iw^82Ԅ}.    'u"bA8$51}.    gp;ÿJUdAU8(4'    1צ̂oRpPJe!){s    h	%TUTŀRpHjRӻ}6    jo[j\82Ԥ'-l    +UU1TV~ѧ    9;;TuTŀRpHjZ}:    )!+UU1T̂wC    GÕ2*ʀCR	    P/^RDTŀRpHjd3ۥO(    @m/ZV
ʀpP*IMm}B    jMG΀pP*Im?3
    nJpPJe!H    5/V̀pP*InxS
    fpʻJpPJe!Wѧ     D~7 ;U1TߒR=    rc~=T82ԆF:    TjrfdAU8(VxT<*    T#6+$bA8$>     _yX7YNpPJe!5-Z}V    JU6l&+(bA8$i>     ]0-V[TŀRpHjU3R
    Pb]J5ˀpP*ImkpۣO+    @)'T82Ʀw\}^    tՅ^fAU8(66>     '	*5bA8$O,    _~p7WpPJe!|CJE}f    I_}UsTŀRpHjs[GY    m2*=bA8$	<    l|ͷRooR3*ʀCRۛ|S    UoR2*ʀCR/{yJ$    lɍ_U1T-    g);%VdAU8(.4:i2>     etWU1TãO.    &J%;SU1TRO4E]    48SeAU8(.5pq    xRUGU1T:Hņ5ѧ    ?UQfAU8(5</O/    /?82Թ-Lߎ>     ?P+e{<382'-    ?n*59bA8$umE`    4R3*ʀCRWڔ<    V7lKgAU8(.7g    W.;Ԇ82岥/JiEb    צޢI6dAU8(7ѧ    |GrQ-pPJe!e{Ec    CTQMpPJe!I?F?}   (g_,.*lm:RpHҏ|-'    )&*!MGpPޞ
?T'+$    -7uyP}o:Ry~A4]uaY    j젟	*ѿ'0T_~P%V">    @x7P>J;SƓO3    2N;F1#8(U$թ4Gg    -<zcON|Gt:Re&JR_$<    -1oRߣ*;UjOK#wDh    򇾟z?=F_Xw:RkA:6<O4    dEoRc?t|Utg    h¿qJ]irQJ5߆TIk_t}   )=e{<3ԕ&7Ǟ0TTIs>    @~uo۔Gɧ#8(C$չl]RaM    b|!5->aA7~P%p    NZ0(?aA&w\T%,HWDl    Ί"kLce8O?bAG?ԄG    x"+)ug~+?bA<m\ca&4W    ;R.0.6<C'1tAWa&TdEm    n:峿Rj㋖D_:Ā{sa4Gm    F&WRro}J7⟇VIjLO7    P#w)Rp߉>t]z@a&58wO7    P_r[ÿWJn)k@pPU    mr)?ѧ1t$5l)z'    ͯNjG:ƀJ+IMkt?Go    j$ÿOJ4@pPqo	?Ըmn>    @F4KOcA%|<JR|7S*3    T`z7So~,d}*1#+Imrݱg    (Y1ܐ^=Rҿ?ףdA%YIjjMES    hx֟-,ATVDq    $[
)釛޺<4ATfZIjl3􎋣O9    0ϊSAJ?,HEPy8C㏭$5W4Fs    `Eo~}(*3]sC7xs    ̓7?Q@GpP<O}^~p%[}   me{_7GIkze'2R/i78wjE    &?%=l礔OeA7~t%M;.    [itÿ1Jz↧/DaT*=6l~x%e{?7>    0w%Rm\|8\v$!+`    h.eKw(IZܟSbAF|%%M    lHMQғ78ї3rӵ_IjK/L`}i    6a|A%=uN>t!C^~%-g    x
Wjo%;bh81GXviz7O;    );%=eS}.~%M&    <VQPҦ|F dR!65Z[i    cO7~28dqF~%U-~wi    fP&s8L=\$i^JJ    GRvτ/,HCߏ>0ǀP%e.    :mx{¿Jڼǽ)dpjrۅGYZR    4o6ɷO>*φfIj[~1(   @^zKv
>(iʖ[:bAgIjcv>    `}zYwAIO彇ݟ~%u-1}   q7AI]׳R1|4t1&HKR&3    6oъݢO<[6l~%_g    Z+[Sw@I[Sau167XKR[0w_}   uo}>	pP{	?ֲ֒^S    O೿OV}A	pP+c%wg    Zct'¿I|+8W58ܒfsO=    4澷eT<zo	'eAOx[񖤖-}Q*Gz    h[S珇듴V}B)pP;[8$ĆgY   F*~.-/٩>#8)	?&7}   Y<N|{=I[eW6ɀZK80KR[y~*6>    דu~eJqM2࠶&KR֔"   @Mo]z3ۅӓuMNbAmSotIjs>    PkCO^'i3̀Z]qhQVd甯9   @-ȫIoVFl[>M١?:    @EwF_"xIjss1   @//S'ѧ08CG^Zvis    0]uA-ZNֵh63l]^Z\tTE|    -e</{ot?G*4/{Ij{5=   #χN~9bAN~wї7s    ˧i?>'iZS\}M`p(kRoIjsKvN}7F|    hGIڦƗ}J`p8?T6F|    C¿Iڶ="3ࠑ_gE   MWHEۇe Df4(Kٲa Imor/>    &_{KzVw8IТisƚwSڸx
fx    JopD74(HR)M'    d$m[SޓRQD_74p7:=    ̛MҶ_T>'08hQ?e.$iz    l|$mn9ygA+ܕz<?$lۣO>    l-gv$mCwHӕ+	֘<?m蒤RƔ    [,_s}ol]O(-l,:7\č1$.K0A)Qed.1nqMAK)8Z6HTap:`
@ePz{~~n~ȏ9{^'s9-Ϳ+C^    0'g5Iwd8%倃鏇$5+b{k   鶢xF^M҂|}Ijrԛ>    G{$-7cD?&ʍgF    ^QghV{oE.FIjrq    /w3IFqVMbIjr6g{    _7MgE9=N`Y9鏌$5#    fhM74ʍg|>Z{rc#IM\wJC   1WEoHߗIZϦԝ	ph>)ёFu   `LUDqO$Ϳ?vD'c:7u?>z_    x!ʫNMߏI~/'cz(6IR#8*9{   0N(7znLҼlHD5Ȟ&c.FHX1ubԇ    j0wbѽgU$ဃUDyo?LʍgF٣   lp.L<<.ݚ=F`8`Ѿ#$5οI   ^_;0Ig1C!+S1=$5#   ݗUn<#OeJ8z^鏖$5c{G<    2ֶSKҜg~~^!귧?^ԤK*C{G<    0xh]xlK|}ڜ=B`9SM?ug?dԠOZD    .Is\}8{Hp/D`E&IMsDu   `U}3w\V.f8Uwo'?nԔzdv    FLu(V-}%io|&{|q:DFC'Ih|   ?ڟkIuD#F5_G?zԄj   [Gy/$ͮ7F~J]Q\yj(I^qGڟ=   Rupלǒ4[΋S٣Fn?+_J(׾A/{   0lh=+I]iFq?4unq   0w}ù{+IѪc{f-X<8`!2Z?4vϞ    j[(}_%ko>'͞H8`T?4M=wer    2utn]Wp].,1b)Q䄨    $ڦ=*pR[TIux!{   ̺_ݔ_=puD=&`l8%Rsq$JO'    ,޽;)I?Zmy]-$pKjC_J(Թ    ,5(I?\w7zExI5Ǧ?4    4Wo;(I?f٣ƞXfՑFKdI^=   X>{ƽ7Fg뇢z ׉C7F鏴$e_ʞ    ,;Ic\yumԝ# x8 [UE(7H%i*.yST?=   XN7IXg{_۵pC:/]'?4,kOz   vK3ITQW# %0wF2b   IDATccyIʮxfD=   ?"-O_>hFvr'VڟhMKRVQ2    sqe^IjlDoUQz2X8`T=rsoh]u>    ̂iq+.{koo<xrDܽ2g+?8HrԽ{e   5vJ{kixK?;ƨhB\t(6Ǥ   +=pi6(ם23(cQ?c hn'.ɕScz?Hb4qT-{   cԉQLY.{kWs5kNF=w?rSng"*O28`1`;&-EhM4&'+     @,cu^    IENDB`PNG

   IHDR    
   T-   	pHYs    {Rk    IDATx1 07ݺ    ;     x   C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       c-;˂(OPQQ*"zPxU=gJI:$71	)2$Fzd2-k^{LNəg{^B,   B,   B,   B,   B,   B,   B,   B,   B,   B,'je}y?q~"eKvLXMe;k_  >xyvyq}AZcv:HGozx/Oݝ7gM[ƷVxm*Xr   &ѽ-) i-ڦiԾRUn!Xץm= R/_T<}wK  ؂Oْ樽~05ԾT4֧BDj]wP-6NN},~   Sн뜔-.!i[mԾ~E*]`dEsSjtd?\҄T*7~   Y}_4F}9ẋRcFك#>:5/s+ޕ  0էY
JUhYߜFh,N=a^ƆW  0[RԹ㬔nýlu)?Tj)W  0:7oMMLl8fi5N:W  0:7a)(UoH<н5#R4j_  `'!)|S*4Lf!y)?tkw)EK  GW;u*_JQ4Z|a   /DA$6UjDt,K@:_E  B*<"} @.ONa(Ͱ2  "t[q̇$T{ @VI3ѯ$   R;O9n")|ח>ۂf`ųOW~7JMͳ?3п  ,2v;qR?@,;]_#ֹͦ  h~S]EҀIoN v!XuSx?i5e   }gMH7Y݅`ܔ_?iy0  %c7#}w485ǔNS~¿lk)E  ".fPFT?hlBfUʖ!.Ͷ晟  s):.#603`羋S_</- ik_`\v>/eKw&Ky'B  y~TvMꮹu;Nْ⿹,  f,Rďo$|Ωȵl-&*ͶOK  V|=GRmw{y>vp/xo4|0Ns>_.  @ŔSw$|Ws!ع>R]#Q|T  
+6{`S}õ9[o4#u2  >xKJyK*c!X0e{6&ͶoI5s  >NNV I~/ԮBO?͒f[rs   آe߅$I9-t!mQMf[앩x9{i   LUO߉$֥BysYˋSȵs   |(n$)TI{/`3=@S[K  `zlXw$Ii8G7BΔ-}q7E}is  ⩻R+J cbVW\7CU[΍  0^Eߙ$Ay؅`/־bY   C}LjբmSkb.Ni.^@   yNjU?R^6M?/ͦYN,g  Xfj;@<_v!<slj)p   R?}~T?~,\DhiT66  xbUvyqJRm`}ovy!XtR~τJ3-_Tn|l/  AY}zƷ
[ILWBuLw}i_ _    IDAT  Yҥ+I)5`Q_e
fRgr  L͓?ϒ>?'ʹMG  HeT?w-IhN.lqj]<6s  ` Oߓ^~Tg.gM4q  FQγ}ȈovX,lQ4k:͹8c  VIDs~n2?Fnߖ8[  [I~Tov|W{x  he6~TByGHTGs  `(^A%/JV>`ؘ]}ZS3\  
IJѵo<bfֵtj_|   Cyڟ$BxA⥩;   `I]jzׄҴ-7  J|W$j/[6T-M|?  yvƷ
I).[yʖ8^%;Da  -h|MRlvJ+MMG.	  0T?=7IQ+P8:  ^})e8Iw^`!|6ex1Lf   &׹ݻy-/۫O"-̟^s  `$4;ڂ׺?l7_]_'o_  `tt~;vjZ9[\fEJ6u<*  FNvuʖ(')-XIE}ߌԾlYY	  0r:7~ǓT[кw3Buÿ8i'"8'  FR?I-X0Bq¿8ib6vq>  !}KORmAjk/=_I[+R  `ݘۇ$|<!X<s&=   ̭U_IJQCl/JZ[  PeGFPRm:#aRy$  TF/{e]PRm^k]<`+^F   ,7OJk͓?`_o}=  /AV46?!5  .~aHJ#./]*Rk;  {woE%楲Zu<;Q~c*=   RJ?DIyX{Gu^k]_
x}  i?_}_Ũ?  `b-)[}QRmN:5N/F{?  Ҿ|{ڜ־V?ÿU<͍   Sqԯ%{_޵|υ1XKv9   \`w}Y=RRZ_۵|71V>   .)6'>E/FթqG2   ,S
OJͺyYײ^Ũ(2   \Pw}iRRmVV~eK_Ũo_}  0CO'[JJs\mѯuF]   |0~)6Z+?9ע~Jۊ>   wJPb4-}Q*+  `r]SRIZ:7}V  0"5ڴԼ8)   A=)[SSRmZYj^TOGQ   ̓jBPV{EM   [oTRjZ|!X  `>D2[c=TRmJYj^)ug   }ٲ𻨤ڔܷdT<y[Y  B*:~;裸e!9}c   ݇NRI-f!9qR*3   ͳ?~7Tb]_G=   *R晴jBPsVâ   @g	wTIf!9qox0   8CwUIIũ\wY   )7eKvJJԬph9   jc;e!Y   lV=*,5vyq*/x  `u"e[a%BP3s!
   CyﰒjBP3qU  ))Ϥ|ׄe%Yjy0   ԹBPӮ}   æ,S_	JYjzy0   3U5e	JUe!)   R󜿏Je!־s  !WNWqYjJŔ"   `M}ϕ
g!nX{Gy  (~;X5־tiQ  >|UƷ
JY)u   #yʟ{Yjo   RKXfk\   k_,+eBPT67E   n+{k=X*&{yG   ѽk`)P'},,   b_p}X*WaG   *x->^,eBPϫ}g    Z{U A}?R=  .^~?BP5U>pi  W.#Kc5   )u[[R6Y*廾,D|   |𻲔pJ   ?2h~ϦTtG=   <OR6YVEx   TďߛlpS$z  fOߓۅߟlĲjKwJg;   lQߡB/]=  S)h),+XSje3   }wi),+XSg9   L]/p}ZF$8})e(  iz\ZF$*5u*=  `"46YV=  `ƺw~B*-1   0+CǖƆ;Gl   ߱lȳ@W.zf  h𻶔q}ѳ   LR6Yx>oNӌ   0n[ʆ4   sx򶔍o~!Bp}R*   y'R6Yp/   0oI٢mR6dYhc>=  `5T\ʆ,x   \Pʖ~!Bpky   u?ťlƷNg1   ,2[]^'Ɔ#yڟEa   Xp~'!BpZ]*/z  +}2eK_7?yg/   -9R6YJKg/   )7Iҝ`g!8"5   Z~6.evg.   +7<եBpjy   軺pޢmRoEZ   冇4,晟   0pz;hہO=c  `ܗEݥBpk   V?K f!8o   0z޻`e!85O
   ylҊG   0we}Bpk   F]vwy),}_   04nK e!8dzgJe=K  `m}Bp~J  wz),|7Ttg(   ?~BppH  Yu|^ !)U)	 WMRԝxԽRS'ރ͋oNSTץmESRDM IOU{ysӑ}<SK#~^>?e;l|y=^55ojyߦc}~S_/ 0s~Ǘ, 2[_un9&.yaߘǟ3i?'~4ԾF`(~?_\Bpj% v6έyʟw._^Gzj||tގ G3[z 9v0+5OT?)[my=-.zGjҴ\@# }"[c-d!859	 az} G/Ʊ= los!X:{fpy,eAYxէGH XewL~$ReK3? 0o+e	?, wJE7zFѾry}_~;-ڦ.{ۢR `4OX+-|\ #knM˖Ƒ;Z~8V~.\S sxsVԖѳ f}Io?_5rpͭ?] 0'Gz*e</g" Hݩ}>qRx3UW}ŻR/? URYh_[PЕu?|7
zM{/L,"`z"}Ky*-\ 0芵Syh_g*D`W9Bp rL,IOߓڗ.I2Ԁd#PaP67|חƟd!8`v? EpkKߛJ_zo/A{I)eպ3 R*:{Ǚqol|QQ}ŻSgi3{U$Aj|T<so{.`El~"un>*n+G R YP= wQj-.<Tu~cxXJE7U  }{/?l:N} THX_x{j~jK PZmgsa"@ܗ]S`?{kT<rMKk_"LyBp@j3W<*5OӔ-&ܓTK;硔cR>tejWEwҔ[]j\*[F _?Bp sѳQ^Y'ʹ|R_N TL!P,D: FEYSwo\8w{E'e`tK_Ɔ9>xyM5r|#'+֮`Uwۢ_z T@w{R6Y!Un|,5ۨ:rS궢_ +<il,u>uu-),F% #|חwR6YF~0)Ծ3LoW \kwg46YV<*z0$5a~vI\H5/W FL}Ig!Ti VNJS+5{Er1C!9B0{G3 \|7Y5Uj\JvѹM,#ZM*7== P3Ʊ^IC^_NG_ v^~Ie!PD2 QIo욲%;UҨ}W7 #u?kR6GYԹ9)=GJ%d}S`?"\fBxTߎc έǥ|ğQ҈<Sjף_ ~Id!5(qMRxW*7<`HuV~Id!un96z~0 w=^~.IU,Sc ai|WeR6,%;!z|lnJͳ?&IUoE P/ğc\'~4znxT?瑤hԹ )/e[ǟc̳\:= ;|p4V~. 1?lY.TKwJeB+:6ŚgUJv `ЕE*35Kf8 |8}g8wRjףG XZ_8)畔AT UO2>$M@Їu2/5Og?+rѢmSY&z@ş?fT.z 0T<vCj_wPj|PR\z2.sGVHiMT`OOT}HY`Pg LS8̑4wTn|4z 0MԺdqj3E,n|CH]eT?Is^}߷X
s435)_Cʆ y~/EG QT'IW? N*֮hgﭿ?ilfYs+GL IA?k$-ۇ}"z TJco'm\]3yнgevyq9#iT֟? #.cqo|s_F8y,3yнܔ-!RY_= Zz6u2/5Odݣ绔U,|`uVۅ1ʢpSԹ<S~Ol6\z-{Eѣ9ԹT@I|0n+z,s^>%վ/y*%)uѳ9ҹ-6|485O2z<)Ӻdqj,6,W0z60G:l(izP	7UTQT棢5 ssIX}G*X:un=.V~.>|JYVܴ&z0 2u"iߺ ê\w<OFP}Ż9 }-1L4$-١V:AWfO=+{W>_?C%Bp>_,"/9<4\廿*= Go?IibPK> 3Tn|,{),4T6G2<OԳvyqJfQ ~;IC]LD4`ĕOݻ[Hw{ET,3 Bzj+爤Ѩy֧0BsJWoׅ9IBpk_*
?C$Vkn0jSw%|I\s\i&4-ڶ zߒ痤4Ya>N ޳wIYm}GG0[sTdsXOE/ LC=)燤Ѯ~{|T엚'<{@<;YaU'D9 LQܔ-T}SGynwڟ<|HR,r# SQ>7$UMGFO?`?IiX/-ܐT옊o4~ԺR_O/'46,Y> I{0Խ?6N!I<d!8Gy~ p%?Mgj<SvuxXjT?PRJsT<OIչ1|HR B<'VEFYS%S|+_468YA0ʍ|$}oޚ	C:>tej__>?lzu*'F4Yͳ&zJpR}݁y_?_˒YsPch_W9!I[sѣ׈IRmNe^?}Flg$m|W'G&s<+.8)OIF4Y<5hyV    IDAT& ѻLD4fJe=6agܿoJRV,gY `tyb!Iө}	bԹ[+ޝ_sU8YV<vc
escg$M/JwGP-)%IJߛlZ	ZC!I3~/
EiMuNj]S|W$IBp5z7l6g$ʹ{DRIRmd73U~{IUKv?oMҨd!8w}L=:7~6H\T?S*c
)YuBj|K)[c@T,gQ>oF~S IsU/EOVFTX]Z,N?=^.I-h3,ҏD |U4o~ʰkeܿ%I)2<cG; Q67I#Y_?ܿ5IdYΰˣ{ sA+,x{SE?Pd!8ú^}лO|ח4_f\qKṷ^wMIRmhI[1 ~;pI'"zܲ<O46YΠށ@'RdsA=+.ܿ'V΍YN4YΠ z@q	P_o1um'$eYΠD=V_~&HBֺߢ/l@A/@嵯?<oѶxds˿MS$9Eɳn[@EEKRe4e$SRkRl?$eSBp~ T^K$EWGqOݻZ,~v$)EӬyǢ>PyC!<= ͍x$^_j?oI9BpkQ *{%g$B>`dtϽROo?"(Vlfݻϋk@5@ۧ⩻?Ig!8ʍFU=5PhX冇SgiuƑ]^%IR6 YN|WEzVY IVsSՕu{4N3\$I8iE )_@~?^u$Ie!8o TV#IׯH\w$),Q>PY?$iP|]*Ұ=suS|חo%IF0i}#TRmg$z0-0]oϏ%I*4*PIE4-ݩɺ<ܿ[Kͳ?$f!8=^(jRkIgUSS=OBpa>=i|T<~ӂ/w}-.Y$廿* IҖ7._ xN?$ijyecCqj_{jє/^ITvS',Lo~HҰսgpG=y_o?IF#)ֽ
ixxa}ǬtIT,~b=5zKҰֹrӚ	{u+IjTZSJeW` zl6g$iMesc*[ϦCW5LIZhS~; Ӿ/I^=O$YNTNI$IF0|.TJӅ%I$il~B[}77O$IhSx1@4O/I$Iوf!81@u/I$Iوf!廾4jP)݇
$Ip/PwDߍ*u/I$Ig!5NhRr$Il|o?Eߍ*lnLg$I$e#Ծ1@et<+|K$IR6Y@ݻϋTFﷲ$I$e#T#~PC~>|K$IR6Y@Gߏ{~$I$[(c>piܗ$IYn?}?7v	$IU -8 ʇ$I$eBpKߜs?}?|$IU -Ծb1@%$IU$-wdJuN̗$I"YnCWDߑ*u/I$IYEB 8#3_$Id!ƷJӌ#TB$I$U#͔/{eֳ$IU$T?ৢ P<z}̗$IBYn#TBcg$I$eBp35O;2@%.b̗$IBYns 8g$I$eBp3;P	>%I$)P;2+-!|K$IRV,7S #h$IbYnoFߓF^+$I$eBp3~kչy/I$IYŲLGߓF^%^$Ie!8YKv#TB󌿊$I4V,')wdJh/I$IYŲ?}Go$IU,Ij;2@%v$IU,Ij;24S6U̗$IbYNR̿&r^$I
f!87/DߓF^ȵ^$I
f!8I˖EߓF^γ$I$eBp:7}Oy$IU0I~j=`/#|K$IRV,'{d׺^$I
f!8IŚ[ #yg$I$eBpEߓF^䏇{I$I*$Md8^$I
f!8EۤTdW?g$I$U/	廾4P	},|K$IRV,';2@%m̗$IYN(G /I$IYP#TBh/I$IYP#n;|K$IRV,'8ע #ll$IU4	5{2+}"|K$IRV,'FߓF^y/I$IYEP?'by/I$IYEPDߓF^y/I$IYE7S<vc$IYN\dW<z]$IYN] #^$If!8UDߓF^$I$eBpB'{I$I*:}Oy.
$IU4	un?50^>%I$)hyv=`uy/I$IYEPs #oJ$IR-,	uY}Oy/$IU4	uu~=`uF$IYN{ף #^$If!8 _݇$IU4	u40G$IU4	u<0o
$IU4	u205{I$I*zϵ`~O>%I$)h*60g$IU4	}OyG$I$eBpB0^$If!8b-d$I$eBpB {I$I*z|	o>%I$)`*}G|ח|I$I*#TB|I$I* g$I$eBpBŚ[ P?3_$I
f!8 P?=3_$I
f!8k 8C3_$I
f!8Gߑ*y|I$I*_}G晟
$IU0	uu~Z+?>%I$)`;2@%.$IU0	u8#P	+|I$I*:}G|I$I*:#TB'|I$I*:7}G|I$I*:7}Gkg$I$eBpB#TB3_$I
f!85Eߑ*̟$IU0	;PE7e[}I$I*ڗ}E|s_$Ie!8K Q-s_$Ie!8r Q?$I$U-ߐs?}?q>%I$)XjWchgs_$Ie!8TFk$I$eBpB~'~Pr$IU,	5|_2ׯ$IU,	W;~P;$IU,	1@et*|K$IRV,'/C2g$IU,	vTF>%I$)X[]R/$I4V,')uc/I$IY.~P~1|K$IRV,'h2'Aܗ$IBYNR]ch/I$IY Ѻx<|K$IRV,'ech_wPܗ$IBYNR ѽ/I$IYΪ Q<vCܗ$IBYNR Qnz<|K$IRV,'}1@uݔ-6|K$IRV,'|R?>%I$)H<wcJ_$Id!8I?}7Ɖ$IU$IwcJi/I$IYEoTJg$I$eBp=_}7έǅ~I$I*d->nP)/$I4V,7Sz6~PSw}I$I*f*7<}??D}I$I*f*X}?|+g$I$eBp3uFRl$IYngDߍ*qGg$I$eBp3un:2nP)$IU ԾryRW})|K$IRV,7Gߍ*/I$IYL3:nP)c7~I$I*fjwcJ)}2|K$IRV,7STKYlN_$IBp3}5~o$IxkV`4`$IBpuwcJi7_$IBpO}77v$Ix[ewcJ:!|K$IR6Y?<ܲ< *ILԎLڱvIwbcD3&F<&&&ުQ
EAEbdeZg>g~nPν{yKU}&6mp1wcIʪ/
?  RYnF[{Gߍ%)   ,7YCX?  @j0bIʮ>~  ܌}/   5f{$eW?  RYnFkKRvM}S  Bps>#^,I5?  @YnAy4n,IY5   5!n,IyoirQ  Bp}5j   5.?$^,I9  P[?o{$eW   ,{GŒ]S}  ܂aKRv>&  He!}_}/sy  BpZdX/   Bp~+n,IE?  @j i={$eW7   ,ax9bIʮ
?  RYNCŒ]w?  RYNCŒ]kV   ,C:bIʮѽW   ,sDߋ%)2M.
   a,kŒe   BpZ0N,IY9-3    5tL.*~;^,I=g   DXNᛢŒ]+  04{$eS  04{$e   a,ZCXk4,g   @jibIʲޯ
   A,}',   BpZ(N,IY[3    5tM.*~+^,I5   030z{$e΋   30{$eWy4  Hb!8}/,zk   Ha!8i}',   BpGqX{Gg   @jh;$eYυ   3wbIʲ   !,g謉KRvkn?  RCX+Œ_ŨL˶   ,ghxbIʲ~   ,gz;$eYwg   @j NxX3    5u~{XlxI3    5V<N,IY6z   Bp&*A'^,Iy~ϊ   f!8KR}m   H5g!8Sﱒ$-|ݯe   H5g!8KR9|   KR;!|   AoKR^   H5g!8lXl4,ӎ   ,gcrQYRXW  }WE߉%)˺y   H5f!8KkKR]>   RYR]Ēei  isb!8K>}',M   OY;$Y1*Ӳ   @)Yj+$e[{7  TSsPtE߉%)˺u   H5e!8}',3|   GD߉%)ˆ7>   RMYwDXXwO   H5e!8ݣ8N,Is    ՐoaIʶAo	   ,br4KRND   9=xcXlp3    Ր;1N,IY6   jBp}',+4(|   qKRV,|   oKRu9   jBpZ˟[E}',s    ՌkKR{x   H5c!8ÛWE߉%)F]>   RXA}ĒgAn>   RXxǣĒm}_>   RXA砷F߇%)ۺ}0|   n/KR/l   H5b!8&E;$eg   @1ޱ:N,IYV
   F,dpwbIʶ/	   &,KRu}g   H5a!8&iXs    Մv$eણ   @	1*}',m   H5a!8FÛWE߉%)F29   jBp~.J,Is    ՀuO$e[  TcoF߇%)}>|   ֲgeQD߉%)ˆ>   RXY;$eYYSEs    U?9N,I   @81럿k}XsĻ   @81~/Òms  Tqc«ÒmO
   ,mve9D߉%)ˊw  jKRv9   *Bp>&>,I9   @0!>,I;?   @0y9]aIʶǆ  TaKÒmo
   ,Iz(N,IyVek  TQɓ    IDATdxWbIʶΗ>   REYΓE{E߇%)zd   He!8O(>,I6s    U<i$e辫   @(tĒgav|V,   y4+$e[   ,#Òm?>   RYOG߇%)~)|   
GCw}Xmtes    U<j$۰W%O   b,YKR}M   Hc!8φ}l7s    U<3>,Is    U<@}Xmx9   *BpߣÒmEo}&
   B,mrЉKR?_g  DuX.]F߇%)ۺy   Hb! ~)>,Iֿ3s    UBOX}XmxYs    Uh7ÒmE2M.
   ",* N,IZY   0QdtaIʶ	   ",໇G߇%).   ",}ڿD߇%)ۆ7|=|   \ N}XX_   Ha!@Z;=,"N,IE    U*}l|  ThpqaIʶު   @ a5}l\2|   
\@~?>,IV<rk   H`!Z$>,IVek   )+}%l{s    \`}lzk   H,XÒmO
   )GaIʶ6D  Bpxi}X>   R  XDs    0aIʶy;  B0@aIʶg  B0@?KRG4(|    Z(>,IY/  B0H$e[?   )`u'F߇%)~6|    Q?&Òm/   )`ΡKR[eZM,   H,v$e]{_   )`baIʶ
   )`5+ÒmK   )`KR,|    :=>,I6i3g  @Z`Z;,"J,I>    -0`oKRN9   `UGG߇%)>   pF߇%)F_>   9aIʷbT?7|   d!9.:_~s,   HBF}l9   `{x}Xmp1s    - 
}aIʶ[   @Z@9MaIʺ֮/   iXV*0>,I9  a!XKR^>   G߇%)ۆ7>   )KR   iXVD}kY   `U,}FYaIʶ   BBF\}l럿k   HBB}lrV   HBB'}4>,IVt-V    3
i$e]{W  4,dve9E߇%)ۺ_Y   01,+ft%aIʶE{  4,+>aIʶ  4,+aIʷ~LK   iYVL5:,IY«g  @GU3,:kÒmݓ>~   L
޼*>,I6W   @G?o$e   @G9aIʷ([; |   yb!XA^}Y   扅`E~?>,I;{q   HB׬KRo<5|   yb!XQ3>}l+irQ,   HB:%>,IY    j-{vYaIʶ  4,+ltaIʶ   iXV;E߇%)Fw'|   
$hPeۇ  4fuaIʺΗW,   Hcf!XeK-~+>,I;_g  xYVaIʶ5+   @3_$e[9   By}XKg  @#kuݣ>   YV䢲h=}l^?   &B7~#>,I6Ns    `^}|tʴ    `tÒu=|   1.?YE}lY   B&GnKR{X   Hcb!XKR)|   17>}k    `Mt[waIʺa
   i,b3r؏KR]?   &BFF\}l޼*|   1%D߇%)ۊ2-:|   9	KRֵY   BF.'m,   Hsd!X'.$eg  XsÒm
   i,kݢÒoŨl-n,   Hs`!X3#}|wg  @i軰$e]o    ́`kKR?9|   9G߇%)ۊ@   Hs`!XC3>}kg  @%軰$e]k>   ,YPkٳr4KRw,   Hd!XSKR$|   Ye_KR{e    ͂`MuOHuX7  45«uU>   ,Xˢ>>,I6Y   01s56$e[YSɭg  @!_$e]{_   i,k{ԟD߅%)'},   H3d!Xc=^}\Y   fBuwG߇%)ۊGn   i,knx݉aIʺg~6|   ޙ}Y   fB:_軰$e]g  @k-NY$eKg  @m}Xm4([˞>   4Y6;_KRM!z   ilI}락8|   ilKRo:#|   il۔e/E߇%)ۊ2-:~   Ll`Co >,IY5   `:,zE]Xw?  4=}waIʺG  4Z軰$e]Y   BAF߇%)Z{4|   -l'E߅%)Y,   H[`! U;D߅%)>   X6HE߅%)F\>   X6Hke1KRy   6BaF\}Y   6Ba}럳c,   Ha!0?}rV,   Ha!0^}2-&|   Ml%ۖe}ky   0q4cu]Xw?  	ԿwaIʺǄ  	=Ouźg  @jxy]Xχ  U/.,IY_  5軰$eg  @!.,IY7Y   6B:-.,IyWek   I,˲E_%):~<   HOb!`KR[,   HOb!`KR֍Q,   HOb!`?}˴ly   B.*,I  Md۲췢usv   ?b!p;VG߅%)놷>   X6\waIʻALK>   ,{}>   ,`Iʾު  @z`E߅%)7>   ,30軰$e][ߣ  @ԯIbky   ,9m`Iʾ
   B0W(.,IY7y   ,1z軰$e]yL   =<.?8.,I5   krQew.;3D5YfwǢ}y   MewlxEOzD{]%I?hpy   uZs[.Wk;U`.l[\w%Ih=Tɭg  TmޯzW/ګ}٬,w/d!z+II}~-|  @e=w	*B0#{偒$;ީ>   Jk痝߶*B0#ݣ7o$iz=>|  Bh-{vomKYރKHk$= ma?C.d!b$,_xu<  z_d:S(?)y   ~遲M@v,3[C(I7y   l(:6D5Yffj/I)g  [F+o'B03-bLJR{]L   mߛWUltץ?TQ=p]3)I;  ԯw[*B0C~&%)7>  h%ۖ^߈7&uOh3)IWtA  fgڻ{MT`6$MGp_	  T[k1ZW%e/EME~,sx$U?  {uMSEYfj?)$6y  @d!=KIʾcx  o_+\r@9?6A7D5Yf{KI{3 jsػK#;l4*B0S/~,%IS\CL  `߫-F*?,3V'єzN<  `Ueď<菔LirQKIҰWeۇ  /ݕ/ؗsџ5üie!ު~.%IeYv~{L  SpDt?[,3F?,-|&  䤵9?zŚۢ?j8O(@:Fw]>  ޿/~{2kK_NT`F\lJFòO fiOv~ATA\~p)Iz>  j޿CTZTTAgS4>  j޿Gng
\{F?~  P?/<Q=[MYR)I򙟍  A=?z_LK|
V^wg |?-d/3*BzE)I*	  Zܲ){g{9X{gG.eԷNG?,ϲ%Ik
	  d۲/R{^k⟍dKQ{W oy*t?m,`_H  쟷S9録謉$M+2d5+QIRYN	 @Z˞]v[eDDf]k	RY?J#];s mޯ*+_/ګ}YY⟳d΁Js Lj.U YSIRYs Z;=wrxe#-x,
Fw]JʲyqL  jfO}_QDz'f9Q=P[{G?FòO oc~Khig?c!uTxݣ$|.  z߆_yUY[Uڔn
Z{Bs*Iz_ zن_=ӏ%R&:U ?X_*I*˲Xs{L  I^\OT ?fxIϪ${"|.  cWD5YczgG*Iz)> 1?ZH5,1Jox݉s 2*ڰ~>Ǵ={]_]W%ۆ 	v|c˿o|\uTY<rKGIߊ?3&BsE#+Iz΁o
 oЍx iϑj)J  hxY=}erx'ռbJ(A{YI4|. @?_=ǖǾ17z&U OϬ$τ %>'~\qh9,)/izϟj&EVxS-
 P'Fw_&MT 5Vx+ PU_\v{W;{I9h?=%U>REYQ&[Im ޿{Ǵ
7yU*BVFl G5l,߼T~*z6 |jOz_'zJyS8lKe!&m8IR%yq\ {ѣVR\.U 4gWQg Tks~޿+-Gn2ipTQlR~v%IO{_ ج<޿/~{$ֿD5YI[+IzB~*ozJd(A6mrQYtD?+e*~> Ph?g3U 5W!|6 {|ᠤ:;?TQl6]TzgM f^Nǖ\Q?c'BWFw^> h{&IR	?sSEYY-0$bTv{Q| {0zI҂==p(AhtwaI7 lLkٳOPළͩ,٢~%IOhp @۔_UvWï{$Ixcy=QMlQkKP[_ۅ W{$ize*B-jxy3,IzR> ܼO_D驢,b]ϱ$	MzXl `<:_~s;_5_+G1ԘҲTQLccI*%|6 0K=R$e\OT ;eIғjW sǉ$5H*BiigY~,z> 07^=N$kn?SY2=𭖒4 xc8F63>U 6YFòO fs;$5,ˣgIғQ"IlxTaL[wF?ϒ'5 uOQ"IlpQg|0A˲E?Ӓ'Tt֔iɶ3oѣDTa辫iIғ W#~Ƨ
dF6쒤jտ\qhF'TaHwiIғ*UE31"Ilj}Ƨ
dFZ{B3-IH># ]FIjdS_}Ƨ
dƊuD?ג'?wy| `5GIjd=Of!ȌYM    IDAT\K辫 3W[#DYkTaԋ9%Iի_ ϊZ˞OT 3>ϵ$i#Ny?$Sn*B[_m
6u|S萤FV3Og!Ȭo;/$=Ѱlt!Iltg|8Af.Ϸ$i#uP `zzKؐF6yU*BYϷ$i#?9|F 0=+ǆ$5UG,/(bKܠ[?7|N e;Og!Ȭ6$m># زDIjd,_~%Iipq3-+%zdHR#g|8Af~%I*Ӳ x'$5?'BYkg\|?=*$?TqI\^T=# شΗ=*$V<Og!Ȝ849$m׆w|V `}0zRHR3+2-.Og!ȜtOp.ID#(|N qsF	IjdEz O5`!Ȝ?KϺ$i{x `=&$njB9+K6R]W <Ǆ$5፧,GF?M9]s*="$.rjB9])zN Z˟?wY9jB9k]2YCx=T䢲HG?M==~G$56yڴX2kVF?M49]=${]9jBϼ$iS[ekٳg \}ldgTE{D?=/g wUXf6irs>Հ 1UY~%Ihx2-޺, IX{g9?QeSTцg@{2z"HRc}[|	AƦw}IfY1=$:*O5a!شxc/ILÛ 럷S8?s>Մ x讋~%Ij4k fG	?SMX2VÛN~%Iw'g@Ί5EIjlC~Χdz3$mѝ
\vz~YE(/&,Η~+$mo 9#@[1*Tגe}H6S ˗$ik?SX2v[ω>$IXs{&<2zHRc~A9jB럳4$m΁o
 =|s/ImpWT#]+}H/v	_("IXeg}Aog}H6Syty>3 29G$5~֧d^X}HP\^}KR>Ո .g$i?9|^ bxף}Ijt/?SX2/:^Y IR~3&ES_hPğa!X}Y{G$iNp_}KR+5O5c!ȼ~A IB	 M;cǽ$5N?SX2o}&HQ7&\ydQ/IT3̛Ao>$Ihp3ɊG}KR>Ռ gveoG-TtזigjyIj|~ާd^o9+\$M&#^_kf,WU}.Hg@.?$FWtוirQyjBy>$Iө(6Z[ hEe^Kd~-fû$IկsA_xu.IoTC̻Di4X"'zn 4E>%^~ާdNA4ͺG'|n 4suIj|ݣ~ާd޵}m IfÛ ltuIj|Sg?'B7UY>#$Ir^?; js>%23?Ր bpcB4W{\_>Ք wǣ	I4+Zi3g@mM.*wE7Oԓ _>'$I31,_3?Ք Xs[Y!If;. unǸ$eQ	?SMY`}9$͠o u4z#\TS,>+$I3hpg@ݴ?+Ƿ$h'fB'7|%$&P'U;DޒE?SYFw_}fHfPO:yW5_?SY`YU2-6|~ As}lKR6Κ?B9mg$iu~o ˢlIʦ?SY>c;$IixP}dKR6s?՘ nx$ixc gQ-ITtוirQٟjB;_I|Peo}TKR60O5g!ȂkC4ӆg@%-ٶ,ZFԒMKOԛ orQYIPA ?՜ !W}~HfX][vz^DђU~$D>?$Ih=3JZ{,GY(/?SYۋ6<ĒzULK>G ΎG$e sD4'|8| T;eIʪWg!HK4U9G$eW?SXs[I,Gs ScIʮΗWB8K^ug$i8~ jLDbT?'|$I,9>ǰ$ekD4F߿(| Dh譏>%)>RCXG'99m`V}JRNDHa!Hу7F)Y69nW>~%)FhA/|"ICN,X(>}JRes 5 :3X$͡m1h%I+DsXog}HP砷y9[Iʶeρ T3Ir&z V{ςzd"Ic#>O KDu^>RXR	^}H˴x0/:FosxYR}HXq'ǫ$egAjA*^g$ikn/g
xuǫ$e]`Y,o>c$Icw?qǪ$e_a,ەEw]9#IcEzl0ϧ}JRލeksgDXR)k>j$Icgg
\tq*I7yBJF4_+ ey44_OLHd!Hv{QYEy#ICS;z VE,YLHd!H,$/+ 3h}JʲlBʙ:qIRx0O>>%IS_VgBj(A*}Iw`:Ga)IzUGυPTVesG4^>_ decSxS>?&BJ|+$isPlؒ>.%IOkgCj(A*{G;qVe/ ue9F+뼋zbXRI)A7$}Wiɶ3)o]4$=/x
e!HewZ#Is?>_ w?E';Cj0A*{GIҸ륲χhˢ>t$=)|ڼZd;$Ijx9e\>g VEIғ*Zm8DsYRi.>$IPďYǡ$i#>6|Fzv>$IP][9d^q(IHS,>}I-ga glsIR5kY1lTᛣ"I<=CsO[{GMT3|NXRy?}I橢n7|F IR\qhH:_~sy$IǦ@*-6| Z\)In>>/R,[E3I4Y?o7ˢ;Ij1|?$5b_G9($mу7ϋ	Aj{{%I<W<rk3h/0$U%ό	Aae9DMynx݉e\?wh췣7I4's#eBpJ$IZz*| EecM4F-2p,q}<IѠ܎,GV&If΋6(ITlrpQG$itȇ 23J@o=LK=@/L&Ia/2b!HtOH%<JxܣQq_M4f9Ѹ$ģ'Fo5MI4:=00 (AEAEu A@WSU^ܛ3S{|J^GxZя. f,xa3j*vy^Je/YjIQwއ]sXR,Ʈ^'5x{#ikTX A#2jjg *֧^?$fߜя* NŎO?KeU|AJU`U\?$V}^;Q Qﺳϒz5n^3 ;<545zE5fhI=ګ-@UJ%[Eb+v{q>fj3aAe/M[ \|`Y$),&Qf~qcR4ƶι+"IAxя  ϕz5\`3>~IZ{L	?[f. UUj3I8mj`H}IK=[D? V?$_#ޑt!^qAu#'~<\4Z~ n3)3qAuӆx@U~6I^S?=0V*v|z9S8ƾMߋ~0Bg}!l-*u.>0q<]uJYym&#^~>I[Ŋ_JΎ~ 0Z&A{Tg +(I\6|*{gNzןH`u%4_T ̳熟95?Y 6sS}ɖg4(\Je7q!p X]Jvs[*՗?9?9!*>Q ɩwi5 FXyEޯF)U\h `	?TdD? qצ^?k:G } 51;=3n3-5sKm^W  HcׅE2jG lJ՞N/i%Tw[RvyY5QP3q7.&bN>gjgdlT5~0FK?ä	qr DTsI3j^zD1ӻT|A&ML˞:Rً`7_6)=2&o~0oMC7ƽ(w4[?O=*&-Ru; Q6mW  V)APY]y Oԗ?%<Ƣ%[NUo] FPoǟUJ 룟y R?ӤQqSy߮ ֪?T{\AMl字F? we7uYK
?פQE{ kbvj }ڿF? 6l+vx}6ߖ ޕ']m0&b~ |G?o֩uS5}Gw" c)m(&էE? 0kJ_~IԢ:ÃY,?˔6AP]`u[S}:i^ZY*~Iw cc3ed)ySwKjNVS[?ה6AP_ Lޕ'b<iMm1uk hZ_eG=Y@:OG}Ҍ[:铩  &Hܝ8' ojK. >S}6g]g}>U-gjOAPY>{i#TޔZ'~ܯhjԽO|x~y&3*^Rً~.{>xdjQyL[5ػo 2ş}J l]sFs\G0ER5}G\gj ljG# rթ}S}ٶg&e>ӀWRٍ~eGƟJ3 |ZMG V=nFjk{V_ dy( (U{z04yM9WRϦk_ {('q ae/֮Jc,՗l~fj4k>?RySW- <}sRgTv]'TMߞ:z=_>xލMU=?3UqAeWOE?*`[פ։},׭~	&~:TmV]Ŋ_Jی~^{QJO(ۥqkO}D `V_}_Yڬ2*˺W|-y	 siޕ'	IN?W5l9d=+^'U sY6ve#RRďbXm>N>z?fFr `(|Hm,3*ϦH=E?7`27_:15x_-l֩q[S{=0 N uR/ǟJ lkG' ̯;P+S?NeO
?'bun?@?3X9eT</^;	 ]OkNO>?xbgc;}S#Syͪ:· 7U<潩H}ޯJc?^WW NE\2*뚇a3 FNumwշRŞ{^oWf霷mmFS On94ʻE\69
 4@S;}1O<RJ/IOs~Tu_m}R/SsR RşJs  0$`h+ohSa{gRď?J>8Obq{|Pc?do7n??)KzkOLuWXRUEm D^vT]^Bʽbg)   05.fe.r闢   0[/ëŵ8-T   y>~Wm3JV޺&
   #T_M] (=X  kjC (=XRպ/
   Hw]    IDAT	6#\#   FNC-{*~  訪uwvՆAPzLkN~  ]}Z]]fS?~  hjC (=E\we   wxpO+3ڧ|*   Z;j=+vxZF?w   LU_˶6F|og/   霳<nڼd6RR*{_   Xx"<7nڼdޕ'G?  `k.Nڼe  bU&*oQ   Lwawq5Z'}"Y   >6M)jH  yp (͠ι+   0)ڼgfPR4   0ozW~VmA2J3{ɡf   7~?ڂdfXMUSUF?  `z7~Vm2JvU3   y{ܪ-XAi5g4   Uye>(έڂefYF?  `h_jAPeͯ/Y   CQ޺O./4ۦΟF?  `yZ9Zg6   lתdҲ'ۢ   0g#V (ͱ  9xAZM (ͭbgyo3   fy߫U (mFv~  =3>ZhAi3*V>?N,  k;iB3JY}   0#~V-<0n3   8-h3JCst   xBϪDAi$^;   VRcׇߟUҐ^;   lPߛUҐjn3   jO>ެdXD?  Qg//6R!)Ue   eF*4?>>y   >~OVm2JC    Wҭɪ\Ai]   sc~?Vm$3JP㋿  STZ~?Vm$3J   J6yϫS*g    ;j#APǺ}   ^;5~U}X (c/Mۊ>   D]ª|Ai\|@y   @;R3|Ai+v}aJ"\   `µNHX (-@v>   `ԢjcAPZ}   *Sහ}U9gy  9,ΫXebg+   `X;jcAPZg|6   `OjcAPZȖ?%UӷG   LrT_u]Wi2J\ďG   L	6nɖ   cvUVi\3J5yo  ew[6Tڳ   ƐQ}33JA52  `(mnA)_>K   U-.g+v{   `S:}1Dd뜷K  oON
ê6  :W&^WԢ/Fʵ)>[   QO6QkV_M#eےRnm  4RJT僗W_sc}   0bg|69U.rwùg   #T_u]UW}Z}ÿ)zJe7   ZM~OUm"^ˬV/FR-u.b  @wv6~z:5/FR-+~)Uug   A:Y_mT%Z?b$=PďE?   DA~/Um~r5_"\}  :'U覶Hj3?Iz!oK"   _V}*v{ïZCÿ I{ѡ   *S;h<~պלIztu_  \[T,jj	$=τJ   ̯rUOղ>^'M/*n=x	   &P|S)zW˯?~5G3x  `t.=ΩZVUA
$mON<   '7U˦bgTU$mb  Im~okU#`lu&iOTQ  OtSj`ټ/MOmIHS[+   w황>([kz EѮ_KO  `TT2lVjݿAu'@IOX]#-   6S)gÃ`_	%mOI=-  f9<>l뜳l`9.M/{Ҩ<}v  0G(v|z]RVr
"%m]  (qʷbTO<$銕OU<   Kʻ7vG/B%֪ͬ.  ,n8owG]g7=J_JASRﺳ(  `T{pٝ KY}_R   3Qy{ROleAuM,i|g   P缝R7}w`_¿hI3lɖy  0JPc?ku`_5)uu  	UTsT:{`9}g^u/iWf5   HU~/m}ͯ}0 iMm1t   V]j&_}' iv5yuJbg   4E*]9A8-I}  FT{o(f}A󣯅A$2:  025~OPZ?buTR0fWjO  g}!'Qwă`/>($iϛ{  R}jQO?ԢTr$ͮEw홛y  HS3|ٿwO	^zdLuu\9   jTdKJW>Ju>2ǣ  UUj;TLSi/)5g%ͭ:   sNw;ۥkƗ4*iߢ~@   RS}ɖw;:0]פۄa%;o|H   3WT;TL:xyZg|6,in^:  @:Ejw9ؖn;2ibW%;%[Mߝ   UZ8'-~|sm{`Fn8?M/^4=^潛   tsߤjzZ'c_\   lXR}B6zTj_s:߯EHSˏ  )o]˟~g>?uaiL+v|z*v(  IP{s*v}a}Mok}Qi  0ƪtj{T@0x ԝ4ڧP&   c*SITTkCt*}}_94(֞8G  Xjw3iZe]2,w|f_'  d{Qw2:;/}ݟNK
˒4)ns  ֻTaZ<Wf^C:&inNذ	   #\U*v~v=Loq}I[ˎ  ȨRcW߿jyApë>(i-J*<   Uo~?XA,S?)i5y  (Nj;T@ v}Ao+{yB%;q9  UUkI<jO/طFAi,7  Xh>~ǒH^a)(_KI_  |N7lhτEK]2.  q[{b/2n%sa7>{!iz74N5e  Urq;Td˶M+`_SR}oHij  J	KIGT}*o,#fzyI3sQ  )6Xcޛ=i}e8 fҭSs"   O#5yuIZ`KJsw|ƨ*%M/^$i+KD?9   jޛ)$+½/H&~|PڳS}CIt/Zя  (C~'$uF<2CK~;LҦk~})Uec   ^;5~O=I~*wi ;?7PT  ]BH/:\JFu#9>#&MGcJxSR_~\   7R5zw*i#;>}_+i#Tvy  P).>5zԾT_hI%#I  d}߅w>q4/Rkg'Kzt~;N   2w YKSCSu8A!:?m_1:  }_ޘ=CX)m@S)   Lι+<ʨ[O뿓&X)[ө{!U/Ib  0L~Q5yuꜿr+"Խ_@RMmWD   &D]9lT>Te˶MϏ~   c{j^Z4x_{`,˔w5}Ti:'eTbT2   )&a땩u_>=,ADҹ<Cb4{n?   ̏why{?[ʽ4AQ2nI'u*z AR  h[T7Rw֪ι;ʛ/Le/ᑗ eԻH:Rw>xz6/xik|)  +{5KԻsm*6w_n?l2$A    ȈA    2b       #A    ȈA    2b       #A    ȈA    2b       #A    ȈA    2b       #A    ȈA    2b       #A    ȈA    2b       #A    ȈA    2b       #A    ȈA    2b       #A    ȈA    2b       #A    ȈA    2b       #A    ȈA    2b       #A    ȈA    2b       #A    ȈA    2b       #A    ȈA    2b       #A    ȈA    2b       #A    ȈA    2b       #A    ȈA    2b       #A    ȈA    2b       #A    ȈA    2b       #A    ȈA    2b       #A    ȈA    2b       #A    ȈA    2b       #A    ȈA    2b       #A    ȈA    2b       #A    ȈA    2b       #A    ȈA    2b       #A    ȈA    2b       #A    ȈA    2b       #A    ȈA    2b       #A    ȈA    2b       #A    ȈA    2b       #A    ȈA    2b       #A    ȈA    2b       #A    ȈA    2b       #A    ȈA    2b       #A    ȈA    2b       #A    ȈA    2b       #A    ȈA    2b       #A    ȈA    2b       #A    ȈA    2b       #A    ȈA    2b       #A    ȈA    2b       #A    ȈA    2b       #A    ȈA    2b       #A    ȈA    2b       #A    ȈA    2b       #A    ȈA    2b       #A    ȈA    2b       #A    ȈA    2b       #A    ȈA    2b       #A    ȈA    2b       #A    ȈA    2b       #A    ȈA    2b       #A    ȈA    2b       #A    ȈA    2b       #A    ȈA    2b       #A    ȈA    2b       #A    ȈA    2b       #A    ȈA    2b       #A    ȈA    2b       #A    ȈA    2b       #A    ȈA    2b       #A    ȈA    2b       #A    ȈA    2b       #A    ȈA    2b       #A    ȈA    2b       #A    ȈA    2b       #A    ȈA    2b       #A    ȈA    2b       #A    ȈA    2b       #A    ȈA    2b       #A    ȈA    2b       #A    ȈA    2b       #A    ȈA    2b       #A    ȈA    2b       #A    ȈA    2b       #A    ȈA    2b       #A    ȈA    2b       #A    ȈA    2b       #A    ȈA    2b       #A    ȈA    2b       #A    ȈA    2b       #A    ȈA    2b       #A    ȈA    2b       #A    ȈA    2b       #A    ȈA    2b       #A    ȈA    2b   F  IDAT    #A    ȈA    2b       #A    ȈA    2b       #A    ȈA    2b       #A    ȈA    2b       #A    ȈA    2b       #A    ȈA    2b       #A    ȈA    2b       #A    ȈA    2۱c ` aos$
y    C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    1       C    BA    r\N.    IENDB`PNG

   IHDR       B8   	pHYs    {Rk    IDATx{u}3^(xO՚fi\mL$$M]IlvŦ9seFn" ^P8 \Ao̑9緟~z}yx=      6U      XX!     B            3     $g     H      A      9     @r!     B            3     $g     H      A      9     @r!     B            3     $g     H      A      9     @r!     B            3     $g     H      A      9     @r!     B            3     $g     H      A      9     @r!     B            3     $g     H      A      9     @r!     B            3     $g     H      A      9     @r!     B            3     $g     H      A      9     @r!     B            3     $g     H      A      9     @r!     B            3     $g     H      A      9     @r!     B            3     $g     H      A      9     @r!     B            3     $g     H      A      9     @r!     B            3     $g     H      A      9     @r!     B            3     $g     H      A      9     @r!     B            3     $g     H      A      9     @r!     B            3     $g     H      A      9     @r!     B            3     $g     H      A      9     @r!     B            3     $g     H      A      9     @r!     B            3     $g     H      A      9     @r!     B            3     $g     H      A      9     @r!     B            3     $g     H      A      9     @r!     B            3     $g     H      A      9     @r!     B            3     $g     H      A      9     @r!     B            3     $g     H      A      9     @r!     B            3     $g     H      A      9     @r!     B            3     $g     H      A      9     @r!     B            3     $g     H      A      9     @r!     B            3     $g     H      A      9     @r!     B            3     $g     H      A      9     @r!     B            3     $g     H      A      9     @r!     B            3     $g     H      A      9     @r!     B            3     $g     H      A      9     @r!     B            3     $g     H      A      9     @r!     B            3     $g     H      A      9     @r!     B            3     $g     H      A      9     @r!     B            3     $g     H      A      9     @r!     B            3     $g     H      A      9     @r!     B            3     $g     H      A      9     @r!     B            3     $g     H      A      9     @r!     B            3     $g     H      A      9     @r!     B            3     $g     H      A      9     @r!     B            3     $g     H      A      9     @r!     B            3     $g     H      A      9     @r!     B            3     $g     H      A      9     @r!     B            3     $g     H      A      9     @r!     B            3     $g     H      A      9     @r!     B            3     $g     H      A      9     @r!     B            3     $g     H      Ah1u[7D+s[u/E_D5=%i-'  F/($nkG_3/=3qvgZ mwG3{qjѤ&)1J*  =x[{n%i!Z^xV.}M 4n5EGu[CڭV[>[   NDg]/'Do)vŰ})>÷~YRCJPgJ  ت)Z*7$-z_4\[/wJߎ DՃΧ0UO+/%gJ  ث1ZXoyI*Ϟ61薾-7Aܲ!:3Y\JZk~ҿ   =ߘ}KR> :llL 4Xջr{a>1   kКm/IcӡϙKߢǒA57Eli\ijU  hڿ4V-3ڧl8b4*}~'xziRijU1j=P    7VWo}IZ}Ȉ^+&B{{tTk| u>u   @͗FbKضYѻbubRM 㛽=&Ή!FGJ
    Zw%i[_t7[[cL TwEʵQ~z8iBƈ~    n<7{?ox<" oGCZ?`="w   HopQQ,@!?1GvZ?P҄=mqC  q1ԤZG$.RB-7GXHTt?zP    $i"\Pgղh$ME13   ]W$q;z_X1iw֑ٺYĨ.}k   6E3*~N IMucxՑE5:3%8$_  sꛊHR#[4ʚу`Q?{޻A   0n|5$|I.Р˗G5GI?g  u,~~ Imٞѽ|YD=&j 4ܲ1Z%]    jKzIsIjr^wE4j_ɨVW-.kc   4ۢu賋'HR[s`6_MҌAh؏KکގT   h9$5e{Fʵc?_   4V>$5oU1z}]Tlo]&   n¨UA^#zxB[6DiſvwEҷ	   `?-=7HR[Wc9HT˖Iک   $eu3bG5ut/@o_#a;    zك$hSSb܌ Tsλ$Y7G   B?,Wq256cЧ7HҜuNOn;   hgVŸ(?Hc[ߌtJ)   E2/.~&!IYn`PP!i:'~   &K}h9ل$e{B^OIs>c^   5KQػ$ew	v|fYo+KM[   1F/}V!I)YBus/ivGh    kWHRfA{_%Y;    yVBҴ|ܲ! Կ/9kb   9KR5OV?-ސsl(e{%\gDo.    hQw{}EsIRk~oAhxuQܯ+iVۯZ[   p̾|IJR룯U9z=Q;*iV>з    gm$%s$h_LIsln<oAo   @N͗xIz_;كP,"J%1ą   _g{`?cN-J-ԯ>   0AysIRFȖfB{ojSxvw   D~tNz]IR7DuC~'Z/L   4jo/.~!IY}fB݋WŒs#b؛_y   QCRb{xB[6~X}Kcjj>   cKZ9$e}+#TEǼ|n   ,kHRxB^őZ??F_s   7ES(~&"I)ZWxBMa$=[{|   <qח>wpL#QaEҏ)1yI    <YGa-F"I	]}xBSŐc,   `W|#?+Z 4뚨f(bHQ/ho    apjI^=y	VEzn    Sﲿ+~f"IUwe$=Zߙ   7Qt|kI^_:;|(46u>Ago    icu3I^O/ Խ|y/ZkM    `1?4R$jp#^1. T?%%MEkA1z]   Xlϙg*T55/ ԽſXISQ|jw~m~   J}U$iֿ`ГmDr_4,g<_x   at>+4םP"%MEÞ/;   U[usHRZaa;Zw/R<g   ίF)Z$jho09uޮ<c   )~"IUCk"z~-O/I\Ũ<c   9,~"IUC|;:%MrC~*ꭷγ   xt_*~"IUy{^/JV3    Y^99$M7eK޺y~gImfIn<s>    ̞?f73Oz]/Fz_6S    л|y$UgfmZBuOQ=T    mTG7?a}BS&U8   h}Eg$jP3ߺаg"I=|<?J   4G}Qػ9$UMiQصAhp9 iZOw~m!    գʟHts6uxK&u'.   @F?!uN]zUT+~$ջo	   Fm$jBzܷspz&)o   H]Wr>uʓ)hyy	   W\G6 Tw~}鋖&ό[	   Fgc>ˑj[oD疿`i#.ZG&   U[u˟Hx7|:罻JPCY	    wղu$zß_buNshI    8,}#ITB쵏~Y	    z}3IƵeKc~ޗחP)q5Dub>"   3zsg=TiÍ> >_=b    YRGǯ>8P]G)eC    ޅ)~#I9?ynXuxKhD    >~$Z1מPzIJ<   Wou$UcV}ƹ9,~qRZzM%    &/~$I՘8 :/NK<   L_,H1wUL.B?    g~0Z?$UcRyAhx7_J=    LKYRlH1}<qrZms   D]CTC3{D:|IZtD   A'D4]zM'EIi]    "Z.IS13ZGEIMsDF%u    G/.~^$IU_;TèV]&:y1j=P!   3skIRUޥT    IDAT/Hjt_)|   FO+~$IeǏ߻IM#>    X#I
97N$5Ωs    \/~$IUǼ{T5/Hjb>7   FZwP$I2ս/Hj\>7   Q|6%ϕ$izjTIM   4Ow?Wj1Y1gSOI   4TQ/)~$I"6=2{j#5Ĩ`G    vQ}WZ9$UhgS#-jٞ>7    gg&I^nMU=HMեU    n~Y&IuZ#{_QK?    0OujB:{ߛ~fƹ֚bQ    gWIEVWbqn&    ,~+G$UXu-oZgƵޅ-X   ~Q,)~%I5zTƵG~1b)L   Ϣ$ZBb｡    WEC?WLJ?8=c    hxuȘAH	uNs    
'Ϧ$B>+FՖ    0n+~F%I<fy3Kb    4ϩ$iz2Iޅ-   ~UIR5O}K#    QhgVTC!Zgw}s    cdʟ[Ig~    `uz[+Iv34=ZD=,l   UGaIR4V[K?W    0םXK o͓K?O    0FgYTb!Mt~    Q`ST+.~%I.dĶ}_G[9   ]kIR4    4͠U-Id!Md\   [T=BZk:FՖ    4X?(~%IՓ kp9    h#EkϺ$z4Qu
    $1]T=BZl~N     Q~$U;XWmUoV~[uv9 !2	2"$0aC2֞ܟp<y$g~Yk3&Ώ>"H$I$i=tKf0YQ	ͳ>l I$I1udBj<*6\ I$Iq|` Ӱbuo;;H I$I1߃dOB<gI$I$UȞc+Tdk$I$IH|ߋd`!rj@$I$I}{1l,K,zK$I$~[ _`!~^*=%I$ITѺlbZ=@s,;돋$I$IxS>~O!J?N($I$I*^yV}@Y1>fWFzI$I$_{;3Y16FxI$I$gu~ 2!EwFxI$I$IuxV@f!XC=pCl$I$I6YߡWX1ZMDtI$I$)뭹-e3wGBV_:.I$I$=ms]PmBi%ѳ\$I$IzƊ憔;5 U#y$I$Iu;&NU#i).I$I$m~E~*BY[$I$IzMvk@r,9͓"znK$I$I[]O߱ʱb-kWElI$I$i+SڀT%B$I$I͵80U#mGjI$I$iS}ᯇ߹ʰb4LLKݕGiI$I$i{7 U#yFgI$I$ikGwo@,(|/ړ$I$Iƭקlb;86,(5GeI$I$i`5ODP{BZwFdI$I$i`kN٬]X&Kǒ$I$Ik}4,(yÒ$I$IP*kS>Ewr@mlYQJ>/AI$I$*/jcBR82zJ$I$IíN^~7ƒS?F_I$I$iun==~%!J{%sW$I$I
q{c!D4Ox$I$IBwU&b!Dy5kWE[I$I$))_qb!DiΊ$I$IR)*_Y;a!D)2V=g%I$I:+v@mlXQ
O$I$IR*ꏧ|ww@m,Xq{R**I$I$`!DR$I$IT:͔{< :!B5tH$I$IJ]cȳ"]Sy*I$I$^7~c}FaZM$I$IHԹ<6,T4GQI$I$i4*T?mz@mdY}a#T$I$Iw~FCW_)uS$I$I=6,mgGMI$I$i$뮺,~$!w;$I$Iu5}_=P9BĴԽy)I$I$tW4J,=+%I$I~F1s{9)I$I$EnIv~@BEGHI$I$ij~@mdX1xwM$I$I4V3e3w(bZ|5z6J$I$IcYj#B~^*G$I$I4V}JBj_<'z&J$I$Ic]/ҳb`y/JEsC<$I$Iƺ"${='>Ӿ|A,$I$I*Q@,|_I]$I$IR%*RZiY1g$I$ITZW P+-!\)u[O$I$ITEw	X1:7=$I$IJRbJz}JNܓ$I$I*Y?9'jc!ĔxB̓$I$I*]/ұb|$I$I+x0ew/jb!Ĕ\\$I$I4[B}!S"_$I$IJR9Ss3N$I$I<@4,fIۊo$I$I~b=)S!P+!YgőѳM$I$I&jCV
Bl|W I$I$+e3vGj,&ki$I$I{#pBl|WiF3I$I$IOS;R6cDB־|A,$I$I5OD}"Pe!V0sL$I$If[s[&Wja,*%3g$I$I-yGZ!R_$I$I÷-!^]Bly_]$I$I	_j!,23vHڻ$I$I;F Eb43zfI$I$IچG?@m,|R$I$Imó4lBlJ$I$I"~c}#P*!6[wղQ%I$I$i
823J$I$ITi|ߗ;btn95zDI$ijx{Gھݗ]>ٝO[NeroâX*ꏧԮG/$IfԾt{G64B<|WD'I$bF@?hi/_Z?:RI,5~R`}af0Rﯤ!oMc?%{εGmg=WSEs}WS$r)9@m(,xFeE&IUKNW.J+5TjT_˝eDL</}aR=㔺?Il}Byv'$I4MzHNJL#ޕyKg)?WS?JooCuW^u$IlN= Oug$IhWR;ޙ|ToNyqYo\&5NHj-:?<s?r"O^$id<FY&xI$mVEԻwy\sxjT_yV򽞛G΢({8$IRi=|k&@Y&R$Iذ:uﺰ{7&SXܿ$IjP(!Rw9$ITƺԽ^:+53&_M\sD~$IU{36PBlRߌA$Iaܖ:T_fSJV_CIq	e@m ,ؤEI5y(|&k$,F	ޭؔɿJ$w/À4(B|iFI{Ծ</S>/JnbT?=ts__IUR}_@!~I=z$IVX낯7mZKfcwE͖$I&C:B'}*=w$Iރ7%sS;Ɵ?R۬+/I45u)O8##G$iuSwղ1یSǧ!A$ij/TI?^$IԹ[y_|煟`RsRLn$Iڪ'J٬U@mJYS_q$IRk{yƞ)3<a??9$I[TOڔڗ/3$Iϼ[	T>/M$IUP@mJY]SQ,zH$n;uo?'5Ohf^0]j)Ew$I8' M!g}:zH$=|kj]Ք3RoIO׉$Id[O?3)c!D_E$UbԾdn/|C-_G\sxJF$IғuRK@mJXG+zH*VRS󔏥lg"6[q%3SX)Iڗ?')a!D\wt\$Ix|ej]4="e}A{DJ$;-ԶPs"I*Pwղ4c39Oh$IygF@VB<$I&bq/zsFU>oZcH$E{)~.jBz]=O$I{ǩuRs;0.MOK$i5P&BV[$IzM3X87-EKսsP&B־9"Iơ};5|Oq7DHTRׅVY;"4zHQJkJo?@UؾxƢ6A$U0? ikYUTԏGI4ʋO-Ll=/~!I4Њ憔P*Bս!IFN3uV,N~? V?Sk?-$I<@mXUP~rP$m~Fc0cRX!Iưޣ?Nvg m)
j_<'znHQIG|W_-i|J'$I'|(ԶPLLKڻg$I*sE:vMau'$Iw^~j[BbGA$I%SY{$ISWQ2>z,*s1B$ޚSU>B$i*j_~@m*J'U_>?
0Ί?$i-%l6P4Ox$IeLK|焟Q͓Tdk?$I<g,*d $Iݟ\1l翴RhIjYym6yIJN$IK3? %31mGLIğg9,*uWg$I]O%3=xZo^q,I%z9m=pCl$Iu40yEtIhKٜgc37GI4<3GAEE}\Q&IFY? XU@}g$Ib`m+H$I#Pk.@Yi'IRE|G ryѓ$IT]Ӳs#=$IrZ0;e?$IRXnӱs+EI4'J<L]ؓ$I%h=~fjOBhMlDI4:7yǟ9ʨ/Ɛ$IOY? d!4Ga$IhnHͳ?~ )WR+?
%IR	=xSY=%1ֹ IK|f:7(IJoU)Bj$ISUQ)c9`ĴZ23Q$şS)BcqDK)Xj| <s)$,)3
P%Bcs$i
\/?[ <qL$i_? _b!4fcџ$i[w>lv*x(S$ޚ> 'C>/I 6}_`KHG$I:~;&@I,Pc?%IVֻ杖z.8$ICx|e|Jj}Slγ$@Xۧ"$zHs)ky`[-uAǪ$I@Ec]Zu|K@BcqEI:uW SjΩ{۷?a%IҶmkS{<cT_&Bh̴\=&$I4003wJ[N$ISzݜ:~#5LR6c8uFI3!0H3O뎎ȕ$IPau~nj-os_n  Y#$i3|v>EԌ$IhޟG1d!4Fڗ=[$IfԹc ־xNG$Ix÷Ίg!4Fzkn7$* "/i,IҘ5\1|R~ITz߅ ʠ}OeIF2m`!4&ZMG$je??/ I{џΒ${^>HF(IT?]gҙ:+$uw<f!4^'$I*Wź{R?+ vsqג$z0u?6T?H`!4g&zI_x|e~N (ۧMߊؖ$iyaRYD5Is3H-n>%[mhn{3^?god!4fQ$I*GnH>/?# ;]FKuwU}˟㢽^^B#qG$I:s_~> U^IFK-un8>|3DNlXɟ@$I2`
LeEK*/g3 FB#]Q{F@B=RăM  69$IRloJ M6+pn    IDATc^4n:G5vs EPI*?$'m}& WcߗRq/IՊ"#unfj}狩~ĻR6kaݻ/$UCT y/$*6< ϱQ$I~ﵨ @Ux:$iY4/'E{eJBhD5Ohܕ$u~ UY8zHJޟwꇽ{ o9C$ԮQ~ ;ODOI*6G'ewC GЈ*_=%IVn9g *z=$IS8qR> SB#~g$I/ _OE IڊjYj/_gޔi :[J^g Iڂ6sUvvH$2un=kJ}nړX;.zKTz] %^~pJVd֒qx	 ԞЈi/IR%*6<^>x3vHݕGIZ LB#tv1@H#>xf>/I'$G&Sg= )a!4bz.>H4Ej3W?])uDF?KfƱBh{??^' IX׾tk"I֤q?MvP*>;H4u$e3 lεGEI*Gvꭾ{ H?Bh808!I6|{ SkG$7`!>bH4u\yUHT+?{}AJE/!IX6ѳ8$i,*GSG٩qRK?c,8#gIƲ LG$mYzsyj_qPjT?u៥ ƊЈ Iޠyy `jYϬ?;HBhDx$IS\K0|08~LEHđ_~FP0rɟ$ISsأg< 柦TcGR*^05OX, 2A$Mm{%=4:ٲ9oRׇ@,FH4T_12zI&/ҼlDY $ij}쑊ƺ1$i*ݛ:Z{j)9e m~^ג$i\i?=$6uAj_w/lY\F$IZY@'GO$Iu۩𭩳bqjg/zS&|l,J}c$IcQ ~~*=$g" X\'KM$|S TTI *6NM%3S|9 P!'R$vV/zs\TFO(IXܐ'/xmg d%f!Tb}$ik/>(Y;C7G)I[?7g{ `*w}ܒ$i=rG/zPNCMRI%(RosRwlN 8|rLq9 D+s۷S+y !+}&$idT RˣǖT&ߕ?-s  WPI:&Iix0 ~og/ߕ? Pc!TR>}l$idk/>-4~Ժ૩q{R6{m SB%^~p9NXf>13vHF1id*6<Z~-5c  ={eNy
 !oMۊeR 2cJzyO)},`ďgR| iXPG$I} |0.zIC{ VB%<AIF]p CзmG6i+xh碉s_ ԆB:~#(IU_h_Oh?w_OS>^} BY$I׽;13{{'m{~S Blf?Iͯ~;g8 cgZRdfj]B P+=iJIFm 'G:U.uW-K	N>/	  j#BdZ%)IHU?Y*kǝR+KU~5{  g$m~ݻ. 9yz] 0YL;$L?>R+ǞFm}Sz BD򽞛RQDQ%Izݒij-)uO#  Y	YOIͫyg7 Ҿl27.805Oxw  i}XIFb-*{fw `3*uGGm%IZ{}"zjV֒6 d!T"Eu%I*}EsC~~+FC~ߖ/LS>/ M!CJFW׾@)n;z$j[7>m<ci61- @6@B%Q?aI__>}ASQ  IB%<SGdIJ_g6 Lzn*6<= IB%Ѿ3$I~g6 `_|EԽ}^q⟥|^  d%e!T^J*I7y O21-u"zDVN#]N&{  o>(E%I*u>>^\lj~;R6s?o lY@D%I*uE˟(G1|\ 1c!Tc$-IRk_wZY`{|k 
*_>KTzݔ oh:vygR}ћR6] @VAB%й#$Im1ѳ Rޟ5ǥyO;e3w  M*޽ˣ$Ɖ	 92U?v3  ,MLKEc]9^RV<Pf?`sLLKNx_o  Җ
s$IlY [wR*4y @GB0/IRi/zs-չ42Eꭹ=unfjT?])s ڔ
޿D%I*e܉ 5MJe/E_/  jCa!s$5\վQ]4/'E{e Z`7$IJi Z>/IEsgg;_Wg  ~P@c I҈Խ jlذz.jj5/  R
q I(<4 l|γSă<'{ׅ @B)2$ij9 Su?n,ZOe|ajG  g!=4IFͧh 23vH5mz:s/aHٌ HB(P{~ýa$ij|h J͓?- ZeXvv$Ij19٬]g4 Li)  RYꭹ=MRչ   !(3Oۊw$T5Od   >~,;7IUyh   lYik7IJUw   ) }&IRj}3   @6,>4MR/#|>   dcB(HGG߻ITz>   1f!dK$m}   1R4$I*M,~>   L_B^}&IRyuRs3   @6,47IJSwe    sBgwo$E    sBZKfF߽IT>   1g!swo$V;f   lY|W$IJ2   @VB_G߿ITKge   ,mN)7IJQf   Bh{D߽ITzݔ   UА5o$7e   ",y'$I*E>   #MR<c   UА>,MRT?s    !q^$I'R6c   UА1N𺫖d   B,?}'IRxd   B,ino$晟    ӫBh=MRT[2   @V!BC8揣$I]Oٌ2   @V!BC<c+8I=p}L   *BhZ{$Iun<1|&   dc!4DDI^¯d   b,sIwp$</g2   @V1BC]4N1|&   dc!4D5EI[;d   b,n$)    YYˬ]$I
3g2   _$)eg2   @VABCR_;8Ik   UА4N;8Ik   UАLD$IU3     !i];8Ib+%|&   dd!4$+$)b    (!xB=$IuW-    YEYIGIGDc   ,w{8IBk_W<   *BhX_赫$I
y1   @VQBCZY=$I5?1   @VQB0{;8I«/~wL   ^MBC;8IxML   *Bhꇽ=NYd   ,q$I
h    YYA󔿌$)ޚ1   @VaBC<3p$ɒy   Up$ֹy   U/}'IRh+c   ,}!p$^:;|   df!4O$)_    YYADIZOc   ,{p$8#    0!=|k=$I5y   U0$)>   
!N_>   
R*{8IBf?   WЀs}'IRlv<   Bh}_}'IRhEcm<   Bh>NЊ1   @BU?mp${y   Pu`5zo=$I9|   T]a!4X?}'IRh
    UWXVFIZwy   Pu`5{8IB   
j{8IBzz<   BhZ?{8IBp|<   Bhω$)5Gc   +,l{8IBk/?8|   T]a!4X+EIZ1   @BY8N    UWX䋴%Irc   +,s˩p$־dn<   Bh}'IRhc   +,{p$Z23|   T]a!4Xݻ/$)օ_    UWXVﾫ$I
    UWXV$I
    UWXV;$I
	    UWX,IRUky   PuЀ$)5|   T]a!4/p$ֺ   
5p$ֺk   
GIZkɌy   PuЀp$^:;|   T]a!4X]$)%{c   +,+up$־ty   Pu`$)1   @B4c;8Ik_q`L   Bhf}'IRxd   +,hnwp$׾   Pq YI:+    WXМgEI^od   +,BHԹ   Pqs}'IRx;    UWX$I)urQL   Bhp}'IRx{.    UWX$I)V_>   !IRꭹ-|&   T]a!48^ύ$)3   
$)g2   @Bc!$IRJEc]L   Bhp9ώ$)N3|&   T]a!4@v$ee   e!4H3w$M>F5|.   L.A.MR   0,,E$I)|&   df!4`׍$)wd   ,,u[wp$83    0Kz$I5OhL   *Bh_wp$<d   ,n$)w)|&   df!4/ph$I.    YYăwp$^L   *Bh_uFI^#g2   @VaB{;8ItRL   *Bhz}'IRx;>   
$I
{3    0{e$I>   
ݗDI^=>   
]?$)^'e2   @VQBֽ+8IJQ2   @VQBֹ7IJQs   ,sIo$>   F߿IT} |.   de!4`$5OD\   *Bh$B\   *BhZKfF߿ITZKfe   ,$>   9$un<!|.   de!4`3$ut~\   *Bh'y$Iws    (k7IJQvU\   *BhG'Mrie   ,~oF_IT>   
?wuy3h4&1ƘDi&jDF1=1ǕxPfBoE^E@@@D&R)~߻d%*)سݏyw~iuYM4uxyl   (- :{~GM4   PZAhuvnM4O   PZAh-lWU$)E3?   Ah
a7z&IR>   J9ME<$)E    "s7IR4   PZAh
&n޿I=e   BBS0$I)<2   @i!)yaMJ\   (- 4[Ό^Isg3   @i)}ݛ$Ii   PZAh
F׾?z&IRzMl   (- 4O{$)MS(|6   q޽I>   J8MwD$IJӦ    eʛwo$it   >ѻ7I4   PZAh
tM4U>   J8MAwE$IӨ_e   tVz$)U(׏    IDAT    Eaa&ѻ7I=   `=B{$)Mcw    EBKg3   @i)mM4/Z>   J8Mwo$itg3   @i)xrM4ן>   J8Mâwo$ig3   @i)^*z&IR   PZAhJݛ$I   PZAhJeMTu   PZAhJz'1z&IRzf|   (- 4%BMTx[|   (- 4%C~4z&IR    %ϋn$jt   д轛$I}Y|   o)Gݛ$Ii'|6   p=ѻ7I4e   M&z&IR:$|>   p޻Iޑ?>   J8MD$IJU.   /Yw$)U>   Ahg]MT9"|>   p)o޻I    _޻Iɗn    {E$Iհ[e3   4uVv$)]^>   J9M²n$     4n$[3   @i8)]MT.\>   J9Mx9{7IR53   @i8)}轛$I}i|   ( 4eK޻IM׋    lp?D$IUUeo
    ꛣn${h   `BS;ꗢwn$w3   4Дu蝛$I   PAh:s$)]O>   J9M²n$j|3   `"^Gw$)U/~:|>   s
0轛$Ig   `B7$z&IR:3   4Pkwn${τh   PB;z&IRk>   JC9%z&IR    |mMtn8>|F   r
;7I5   PA(guUE$IJU}(~F   7P_w$)]    L.z&IRGL   ( d|;7I?3   4PU޹Ig4   @i  -z&IRF7>   J9+q$I6   PA(Hs$)]U   PA(HwE$IJY?=|N   qYu]U;7I{i   fq|;F$IJWC>   J8|蝛$I^*|F   q
4蝛$I}   PA(Cwn$kOFh   0B'z&IRcuYX>   J8';7IR;4   @i@~)z&IRz9   PA(Pg޷Io    A"ء'蝛$I~9   0B_;z&IRƷ>   J8ߵ.z&IR
    A;*z&IRI]v}v   ( lp蕛$I)9   PA(XF$IJY?    !}$I)Ss   4P/޷IѧO    !-,Q/z&IR&_?   A(Ƀwn$kPs   4P?r$)e}^>   J8%0}$I)s   4Po$)e>   J8%?m$lx9   PA(a?o$)e;.    ~~MU>   J8%Q޹I;?7|N    Wn${Oi   2}$I)%|N    m$lx9   PfP.z&IR6m   (3A(޷Iɗo    e9%]}$I9Y   0,v&+7IR=   `~v9%R=roMO}s   (3A(F$IJps   0DFWo$)e~(|N    ޷IɃi   2}$I9   (D`MuH   (3A(Ϭ8z&IRQ   MBT_\M/5|N    m$lt9   PfP2+޷IɆφi   2w6Ir6eŎ    dzn$)m݃8|V    LG$IJ[?    e9e|%$IzbWj    d6IR6)s    ώ޷IɆ4   @AB	/?(z&IRú1|V    wF$IJ[w+g5   @1B	>kѻ6I?g5   @1B	u]$Ii^*|V    vu=G$IJ3g5   lqJj[m$z9   PfPR?o$)gUUwvn   (3A({F$IJ[	    e8%ПF$IJ[
    e8%=Uѻ6I6Y   PfPRݿg$H'6Y   PfPbգG$IJYy0|N    ΏG$IJ[gj   2#^&z&IRzGr   (3A(޵I9>   ʌpJw/E$IJ#g5   @BuzaMM*|V    \}(z&IR.ۅj   2sEMuY   PfPr뎊޵I	>   pJn޵I	    e8%;uѻ6I6Y   PfPr_k$)m7j   2[m$l2gk   fm${Oj   }]$Iig5   @IAh/Zk$)m    %9?Mѻ6I6Y   PsC^k$)mUwc   (9͂Ϫ8z&IR:{W   AhFL6k$)m~+|V   fD$IJ    %11x]$Ii}Y   PsSk$)m/>   JbB3ѻ6I6egk   ЬXC]6I=5   |NB3dgwm$_j   xRM\>   JRB3d]$Ii}i   (I9͐	o޵Ip]k   ]$I=   $ 4KA޵I񯏟    8͘}D$IJ   $ 4cF::z&IRF7>   JBB3fp?E$IJd   $ 4cz]$Iy&ugo    %Eѫ6IR=g5   @IAhUݍѻ6I68   $ 4w_k$)mk    %4]$Iiwu   (8͠Yk$)o^]V>   J"B3wkWm$   $ 4:v޳I]5   @IAhFU~!z&IRچ/|V   Dfwm$m|   $ 4k$)mU,,    %	_]$Iy   PpQ5?g$)u>   JBju=G$IJ   `>6ѻ6I6Y   PpaO}0z&IRڪ	    %	68wm$   $ 4zGRMy   Ppaϋ޳I9|^   f\}ѻ6I6Y   PpqD$IJdgg5   @IAh/]$Iy5   @	 4)z&IR꺇:|^   `B3{F$IJ]k   Ah-F];ѻ6I6y   0A&]k$)m{
    %P=2z&IRކݺ,>|^   @B08]ѫ6IR=5   @	  #_g$)u>   J mu]Uѻ6I6y   P95Dwm$m|   rj-gF$IJ[5x.ۅk   A!v޵IA?>   J{6IR?   qj/޳I'    %PS,,ѻ6I6k]     ]k$)mUE   (dwm$5   @	  $z&IRQ   (Gl$nx^   pjk$)m;??   Aa&]k$)mU,,    eftѻ6IR{5   @2=$I   LPtuM/Y>   ʔ95ͮTדQMo?/~^   OPM6k$)mU   LP?6z&IR:|w   (S @s!z&IRz'1|^   )rj~!z&IRv    eǷuUE$IJx   LPb%I{ |V   )rjME$IJ]gk   2%B5={6IR;   LPC9z&IR    eJl$n|G5   @bMUK   LPןk$)u}^>   85p{6IR?w5   @=$I^*|^   )pjMG$=u    e
z]$Ii벰,|^   % pD$IJ]g    e95p{6IR?5   @YbB;{6IR7ly   PPuyqMԍ(|^   % cD$IJ[.ۅk   Z`|۹ѻ6IR=5   @YBB-0\{M׾%|^   % g$)uO>   rj>/޳Iݗk   Z*wm$mة5   @Y"B-1U$IyE   (KA%g$)uY   (KA%z'1z&IRW>   qj>/޳IɽWk   DZ*wm$mԫˊ5   @YB-2U$I5   @YB-2x=$I5   @YB-;{6IR7y   PPt=$I]   (KAe!z&IRú|V   (Aeω^I
    e9pn{6IR78   ,2=$I]L   (Ae:{~GMMtK   (AG޵I;{|[   (A7j$)u~9|^   E B=z&IR[   (AzGjMԍ?y   PPuVǟ I{5   @YDB-5xGMuy   PPKn<)z&IRz'!|^   E Rs1z&IR
    e8Tȟ޳Ik   Hjdk$)mU,l?   淝PM6k$)u?|^   E bOg$)uk   Zlp;l$nxA   ,=$IsE   (AV>G]$Iyb   0mZnrѫ6IR='5   @FB-7=$Iy   PP?{6IR7y   PPu=$Il)|^   m v˟Q׃k$)oդ-3   `~9Q?U$I}5   @BOg$)u5|^   m D?l$nty   PuwF$IJ]5   @Bl޵I^/    e+9l$w5   @JB<nx=$I=|^    zg$)u;    e+9uUE$IJ[{.ۅl   xA$=y݃~ |^    xRM?   l!޳IUk   o\MM.|^    Xwm$m<ˮώ    [A1§Wm$ׄk   ޳I>   rk?{6IR7̩   l!!Fw+l$z   l!!vu$z&IR:{}g   |B<u{6IR;w5   @B<ҽl$nxy   PO?l$n|   l!ϋl$?Z    e39G޵IWk   xR?g$)u2|^    ē\=$I]y   P6OwF$IJ䋟    e39:{|k]W]$Iyn>   fp)M5z&IRzG6|^    S]LMy   P6Oip;l$nk   xJ_g$)uգk   xj+vQ?z&IR:{W   zB<ɽWE$IJ]    pi88z&IRꆗ>   7 =$Iy   P!V޳Ia.˷    i8UU$I3   `98?z&IRgM   (OAohx{6IR7y   PPG$IJd   <!Ξg$)}=_>   SpbT>z&IR6Dm   (OA2imM/Y>   Spb=$Iߵ.|^    f=$I,>|f   ' 9u=E$IJ]??   A6y=$Iy   Pmt{6IR7y   P޳I5   @yBl{,z&IR~~   (_Aͷu=(ѫ6IR;g6   rb,z&IR
    8E7z&IRw]>   qbO=$I,>|f    5$I   P[z{6IR?m   |!3l$nd    IDATk   Ubg$)uׇk   Ub%z&IR~~   (A-[뺚D$IJ]
    8U&_9z&IRv    8U6=,[$=u;?>   qb|{MUG3   8DMuye   (Bl;g$)u~6|f   ;ƟdMԍn8.|^   !G$IJ]]   8-)z&IR:{0|f   TBl~c$)}~/|f   TBll$n5   @ ĶzVMM"|^   TBll$n<ˮ   @9Mz5$Il   &=IM{w   Am6y=$IrF   Am6=$I:eaY   ZAm68ol${   \k9ͺTM?3   k-!݊z؍޳I5   @VB,=WD$IJdg5   0ZB,F$I]U՝U;l   `XSf$)}cw   \+9(4z&IR>  VrbTeCMԍZ>  Vrbьןg$)wn]V>  qb.\f$)}~*|f   s Ģ;6I78]3   k!MgNu]U{6IR7   ̵jۢl$zy   ̵jtq{6Ig6   0*B,G6z&IRq   ZAE=U;6I73   k!׊zԏ޳I??  MXt{޳IjRwV>  pb88z&IRzV   ZAE_KM/Y>  pbuxyM,|f   s [XVW/G$Iݨ_ϊ   @B,mF$IJ_	   \+8$ޱI>  VpbI9z&IRƷ~4|f   s Ē~^]WUMUea   5Kf=$I3   k<!'D$IJwl   `X2c$)}O>  sbtuMU>  sb|f]{6I%s   A%5$I}K   A%5rMM>,|f   s Ē%z&IR&|&|f   s Ē$Iys   k,!²|9z&IRzǿ.~n   uS9Ʒc$)}K
   \c9ޱI?>  rb9z&IRƃMs   k$!\gN?,[$=}#_>  Frb*&ޱIg6   0HBL'D$IJg6   0HBLwE$I߰S;m   `qᯎ^I4u   5ӱu=G$IJwm   n!frU;6I7^v   A^qpMUGs   k!v$I3QП   \815^_$i&s   k!gaY]uc$)}~8~n   u81U΍ޱI.ۅm   `1E+wl$D5   \c81Uc~3z&IL48s   k!j$Ixr   Al=z&IRǾ>  pbF7c$i&   5S78]5If>  Fpb꺇:z&IL4   5ӷu=G$IJ_m   n!BL*z&IL%s    DG$I5|n  6Y}=;zrsͷ!k_$i&]   [q]/ݳ}Y]O;c2B򀕚$Is   JgԽ_Wnܬ]g/- DeuypWh$5/   s~zt1dMu]U[]ws{A0,Lf?s  v?_6,w77ηa\I  0.\Q︠%;mͥe;7E4x{  9:{|]o9ʆ׭7u(- DΪKJԶ:|w  Y6=c>o!Bmϒ$_K   X,jzͷF7#IL4  @M_i!B>;$DO[  Yʊ_"BIfξ/	   L??]goAX+vQ?sG?   ,sZ3=7Ifѧ   ,s6Cu[0Ap+ܑ$i&|  `mh?gӯ~̩u_-S=J8-џ;$L}'|v  >ܟŬ{o!uY$I3S>  ZY̺Gl|{8oaY]u$i&g7  @x/ݖq"s?{$I	   z
6ޱ;}q"MuIyui  hs&_ZSߍ̷)If>  fQg⵺ڷ'J8Bg꺪?$IF7>  ]=]UseiL6#ILT=  Igs?+6M/SZA46kgIyuxy  ||ioG?3̷ǿA4If&
  h^/'4Yq"ᯊ$ifxR  Xl_TN|c=du=º?KKϕq";$ILTuYX?  ?V{"B2 If	   s$>/p"EI43z  `f3FR[{׾%3Hi|Y  `wo׃W[ά΃_4#>>-- D*_$ITˊ7  ݾk~MGti!rYX_Hu  4?~k=Gpnp"s?$Ix=  ؿmx鞞4xUl1AIyZ> ѿ?
m1EHwoDI4;u9  ?{woWYz|yYkTWkW[[;h[Z[mmVoujd y&2̈!dB kks2$'9g?{~>?or~^{UѬQB/O(" (!>%I${A?[`z?=off}H?xSY ѻp-I$iTE6ZCe! Jcѳ[$IR{Ds6K=5BH#Y{_> <<e_>%I$Ma;*>k3듅F־}@td$Iix۠vͬOBfoR}@i.+~~K$I{&vYCm80Y,4w]}@ioݒ$I]6%?}? #!e!w J%[$Ij?(uOԿT<|k?`Ww;>Yid JυoI$6ylU-ϬOBZ5<R_uh$IZۛRؿLvK/Lی' G5Fbg F=[$I{|FӢŁe!n| [$I*Us7>*}//Y,4u3	 JoI$TwP[?f'!t>}&@6z~K$IRkS9[+;K
?'5BH#]6E)s	 ʣL9ۆpI$ie^Nz_{@	~Y,4]}.@p$I[?跓WUץTWq`z?vy2>Yi_o ;~$Il7{TPϗfYs	 J%-I$M{bӤÝϜfZs	 ʥS3\$I{:4knMCԻpQ9ԬQBf& LROpI$iɣ@ϦBHhpg J$Iݳӎ&#wgUFY?3 xţwoI$'6E9WFYh 3.I{W_gie!Rg$u.I7ksgSRT?f'!|	 JeQ[$I{[Oy0[׬QB*M+> \Ԝm$IRI=}j{fRi' ($I/O{ģ uOY,TZK}>@Ο>%IޟG\?H~gd!4E*:FQ P*g$I_;)뒔k(Fb9:>YTn9+r)-|E$Itgu`uNRڬQB*UEQ P:c>>%I4	?k5BH}EQ P:$I@Nߗc_y*CBH*[}JE}N@;l9.Ig?w4)ZFkqFYt}N@鴖;|K$յlKS4~F7kJ3s.ITvxi' 7BHkY n=7|K$UY[w~!uNl]~t~ WBH{) (A/e_>%IޟGrVJ,Pj%
?ۛ5BHk֖讍> tG~"~K$/xjY,T}V@/$I# v~}Y,Tz}V@>%I lsaf}R)kg s\$iyfh(!lWEU PJ%|K$M{v>ޟU/ cWѳY,Tڊo> t?=;|K$MIN? e5ϒBHQG Ϡ^>%I6?N
Pt/3땅J7 ks\$i3+ SlY,TZ?R]w$Iy/~?~T?knA͚e!6{zs JXs[$I{ xB4^Y(Rj9.I* }+gze!R׻hs JoqIT 0;>5BHsG[ PJ$e^ڇ|4u{|? LsYfY> 6A; |K4gZ∔?x ן?f+!U?b `rGi$IWۛޟv
_uhk,!UE] PJqI4jy(@M.Y>5BHs?D] PJc،Y.IS6EU[# XᳱY,TZK}v@iY.IY[w~aoKS꺔< OrfR"/ (ÄrIy e=gfYn:=R^>%If'{0J 9gjfYuϞ}~@9Ev~},$Iޟ?rCm,!U}~@iu\$y >7gze!jRg g$I5wɒk Mk_
͚e!4 `t9gY.IR~a  *MY,Tz}@iX,$_} n>5BHş0 (%{rI\] ofY2e;.*#|KT  O>{5BHXs{Q ZY.IR-UJE} )?g/!UGFe PZ{,$e_} W$|6k*U> w\>%Ic} ^>5BH{2 (|0y.IRj[  fR"G3 (Ή$լ} \>5BHkp K$Iïş  0T+	f!=gVy Rs$Iu{Wo  0Tvf!>w3 (>%ISsF -|6k/H)Gi PZ+$ըޥ{G w>|6k*Y~g V=
$եuG f!JֻdI 7$Iuipѣ oYu3 J>%I^ѣ oYe;>LR%|KTѣ *[}m0!U;5 (֒wsI*) Ó&_Y,T}@uϞ>%Izَ 0T㿌͚f!=g Z~y.IRk-yw>|6k*[kFm PnE]~&|KTڇ|4zPn |6k۬-Sy,|R.IR,b<1|6k*7 (-?$Uc |im4!U޹s7 (A/e^>%Ij 0TfMRk ^	$U'Gz >5BH.A 6X,|KT{ 0T>>5BH/oE olދg$IUX{jY,Tz}@utL$r*" 0T}?g3!Uq}@=6|KT]~&ze)|7k*_8 (65>/|KT(zy$y#,!բb ^?$Uj@l83Y,T+> +$Uc *_}cm8!բI_> c9g.IRU_qPx۬qBE> ڇ<|KT=`Ɵ=5BHhlF*; (uI*R CջpQm8!զ; (&5go>%I*}J)Gv i_3뛅jS߈> ڇ~,|KT].zuܬqBM}@%/?|KTߜ    IDATvHk?gpY>2G< ("[=.IR,bHln8!ժMGy P	~'|KT_ R9gܬqBUݳ3J/_>%I*sO 0TE[
!թ}@%Ss6]?pC8*|ֽBHjζ)g TB?$Y[4Er ON5R~a п.IRk1 C__{Vg TBy,5>/|KTGI;'|׽BHu}G> Q$ߊ 0t>^a!~ п.IR_q`k\
!ձˣ? ~;e^>%I*S;. 0t>^a!: TF縿$P&|׽BHu}F PN	$l7Dn A75ǶuR<">=%I*C(zr>հR}[}@etg$Ie{Dm -?jX.#p$i_st//|a!>ϢA |E$zGOm _F`5,T߲{ L_$tsK)Gl qJBu}WG P]vIF Bw',Ji-~G|$iT,B٢ׄa5,T:G}2,J7/|K4~{RslFVBH{ `jknwї$9Q C?p}Vc"!վkD >%IfmR=`?9-~+g!׻dI __|$ijK# B.+|1j_迈>R#9y3^QsҗG4 9DB}َL(E 1
$R bsX,.\JpJ|$i&z<@jLd!$GҽE E$D;`b6@eJYIr>" TNԯxIF <>x2!i=B! b]xIFi@]>x2!U+G wxI_wBHNj<DK>rz.
$66#U# B.#~+WBu *X{_j:|KUk;1 YƓYIO-xyJE}F@崏9/IRT= Lj<{>#r7|KUѣ d;!|dBS]k	 ՓS5s^G ۜx^,V%B>I /|K4= ӘgOBHzJټ4E P9}3LT:'~>z@5Gb5;/>+Z9/I0_~@0sfb5zϏ>+?$/ YӲQ߉>+ډǳFzIQE^ Xe!$=9ۥoG PIe_$)=v NQlc5}d@%na$i?)z@ѻgBHZGݳǢL wzI[h0?(]G$i:kq z>xVBҺU*:E PIE{Mj}~$i]0z@>xVBs4s *^*Q ڇ~<VYYIQoE PY]zIlѫS*Q ]6|&,稵M Y=%I:'|6z@^+5Ƕj<+!鹚e*ZG PY$Mq뎏 *oE<VcYI멿 L{I9ۥ6z@due!$)}~@uOj$ijѣ uϙ>XgBzj *->%IW=Z \Od5֙o>Cf$iJC| z@l7eue!$mP G{I6=R c[e5֙:|*jtSkg$IS='* qLV96Pp<,J;7|K9y8 Կlz+B<,JBsv3_MG) _	j<gBFԻ`aY
 9g$IREc FBe53!i#j *//IҤ5EQ 	قfBHژfoR}@/I$j[ FBȝsYf!$mdψ>S+O$MGO 	>XoBF=_T |>%Iڨl	 #a=Yi}YIYkD Pv$mL<zl٬z&еE Pyߴvxa$iV. 02ZK>XoB$8"\Z/I,~'zdhtSsYf!$MΉ}@-_R$=W=.`djl0!ie;>l/IsQ	 #aYf!$MW s_u$ jl0!i.#|h/I3]g>cYf!$M}@mn>3|K>/G$ lWhe!$MK׊>c6Z{r$:˾=`knjlTB&4s jQ_* #qYBHڄ, G>H>%IjS FNjlTB&Zs jwɒ/IRҽG" A	jlTB&V=e^R*I
-ᅩ<=`E4|NQYIX jw/Io}-zW$|FYIXOF P+Ewm" IaLCDB 9GiBHĲy/NiЋ>sVz~$կ1 0FVc6mD P+n, IW? 0(|NYIQ>svz	H] :ZBHڌZ{r SI$IhpwG kBHڜf{^ c IRk}m)yԿYƤ6UE P;E{_	Iޥ{G< YS)|V1,ͬs_G PKݳg$I-)q #﯅k5&e_ h=/	HY;G: ]^j.|^1,)(# jw޼{$_+k +BHz}@=u)[$Z.-zH_oVcYISPk` %{$Ii YƤ-R\}@=z[Jѷ' ?>՘tBտs j$u lXNͱs[Ig!$MQc2,*r׻xqD73[MBH/xd cpڔzq #{jlRB6 j}o$Ic Js[MBHºg|3<ZgYK&]k_L)D1 }vj6|vIYISXk;d ~'$gF/ (m569!i%\Z+;5wxA@Tڇ<zt@i.1|vYIS\߉>HJЬR 1EYIS\F @]~/$vS= <"e_>,nζ讍>W/$l"[= 4U+4?)| "`@4~KR//|~kI_>oyqjHF?R= T:']WclO|+ 9wI56#~zNxi}ms\is+h `qU)[$i4 S?|YITy4 e$Ie^>E `r+OjlvB4Z4 _<~ ~ IŁ	 J{?q56;!i"j 	=W-w&j\BHW}V O=IR@Ic Jh?u34Dy <Ey4e;> InݳǢG gS4}~JV <EcZΔ =s5$!iߠ s'!4k}YRk-yWLW,ig6 RI;~R+RslFLWcJlWn W~O$M_o1 LkjLYBqQ CO$I/H7E (I;~+MUB X{RewIֿ| -s])BHB}v ϡwI>OG TBs])BHRG Ej$ij:k `8(|1YICwg8 Mَ/H6-'ߏ) P6~+MeBҐj-3 Xc3M{άQ Ɣf!$-&} _3H&]I)D _Dw5<!i} Rk;/gR| z @.Y>՘,!>r `{Hۄ$IG TNOyBHfsKEwmy l@EI2 0Ŋ<e^>՘,!_yb lH~o$=wc*zZ @%\>՘,!9sg: l{)g/x LOLhT6!ieO)G F	I҈'?  ^jLKBR@[Ί>ԻxqADsK;~= Σ9{4YIuN ~76#W= ?+!)lѫS; 0oɵ;$չ T^ggӖw `7lKT? YQlׅ}5-!)i_>I|Fj2!IujiЍ Py=W}55!)lOlr](!Iuh=}@-Λ>՘,;/>M9oTߐ5E P>>՘,K9 l~;$UlW| jcY[Ԙ,} x잉oG'$je^VD P+k1YI\} (_u]4>!IiF P;>P,? [K9ۆ)$}^zn S)[tg!$ۢ| `*06#^!Imip9 R~ewad!$@D f??N!Il֖u  F9ad!$@sfG {$Y[#o ־'PFBZs 
E:UBJmROn "[c[4"o>0a~n3Ol JBHz/>k_H(49'5 0<nвF޿} S<ZJCFl+R~G4 0ךF@e!$PC7G `cH(.h 0CBHz͋ +֒w3$)lן8 1.PF֒wE `kK!I{SG1 TyQ54b_= iP4WM|#!Iì}&ީ O	'1,{y  LK!Iu{SG/ S~WPcYI#Vo t/|OCY[eD s);ҰFˣ 0Z;$Muټߋ>f,ΠFHB=s nfjIߐ{>]jd!$`?& PqVjGwIX?T 6Bk;jd!$h;~= atSO=$iS~kg 07BHѺ}=z>  R{49: &w;FlkR3 {IP㏚W]}l 5²FOω WsHs9)u% 0Iţw،aYI#\/E	  ۇE$in◌ @9.YPBH?J^  _]~&>"Ivk[}4 })BH?~  ޕZK~T:_<}$ hJY[+BH:'~>z^  >wI+UipI  0<.NM!i$~;zf  93Is_"[} Sjg!$u'D  ZQc96#n"e^W} SxPBH*A#4zn  #bp)>&] TKjDBR5  O:e)"}^]("> iQBH*IK )A	H*w?o> i1d!$D `=gvjm~WT_W} l#pPc$JT'3 A_~WTfo}=ݵG 0(JBR3+z  #Xs{j-ѭ}o|
 +jTBRv"z  *?HY[[$N٢W?x8 Z{#Tw\=K 7킔{fm~%5 0lE]6>4JYI%s?D és_]$>R 2#T/K߉) @I=.e;2#i8_	 6+{#T+E D9/0oX {O ;'j\BRI  0Ykk!be;6/7}  #bpYw5F2!6g PBE`,Bj͈Hy/JvHی>V Y#T& _Z;/}=k>F QklK,jdBRIk ]3m$=_#' 0W~oQcd،?tK *x9#'`َJsfhQ @1YI%w TRk_Hjl7eL `cknKͱ-1jlBRv{sJE=k **vzm]GcH+I)G @Ν~QcJsg PE,.\/	HuyGh&  V[4jtBR *uOJj:#UlދS{_KD %7軍#T"0    IDAT>/53 ;R/欭?Rk}m+ZGi 9w5F>!Ml `H/6-RMNP `Jݵ)QBH@}=w Wߘ:'~ޣ-zuT<|k- PQQ,߷"z  5T/uϙ=.426x_{\J^) Pq>Q*CBRE~ѳ "[bh+ERTxw Ò?xSjQ,->~'z uU֞~?QS !5JTם=  4٩}ğ$i*isM7<O |~7R4YI}F! g)5u)[e^:'|6nJV @|FIRe!$U-Rȝѳ `ArVԜeIڈ2O,n8%A7/ i:e}IRe!$Ug knKso?IO-卩{I.Xb "{05l~wRTYIkCT3	 `E9&}R=k-~G)2wi z~RtYIlp3	 `4X,uL(NHb LNQַ~RtYIs '2lދW*yL7+XA/p M6~	_)1!}~*:F& [xjJQۛR/S^_1 w-5JT˗F& W){y3+zojwi4v{/o/ `Zݓ
{Q,뗢 +=]~_߽ա F9w1f!$UKg P嫮KH>_~Ԕ{Qj~zv*kS ~7SYIc
  T)ggڈfo=kl=S~)  n]MYIUn@ )N}Rp;[s'wJN&  #}GoJeBHxG* 6S٩}ԟl7،{\Mj93w4?tKJE?? @)ߝc[ʜTZ=  J<w(/? ufj'g}fmޔ^O|O&w ʞT=  aЛXp~rZ]W9өﯦlѫ}m&~=>ésgS왩|4?pCJn:  l+JeBHA  `zT<|į+%KRYŉ_HNM9lEEykR?L>7_Wxǻ EF%mR\=  x^GJC7N,a+HK}SE=5Li'oLcL @9`JUBHI     wujT&!&?c>    <cjT&!Fn>#z    h=; 3E5*TG~"z    w'Q,:5kT<rG,    gK.?yRjV    X#?GTrYI5+0     FSk_Qe!$հe3    X~F%jXߍk    :tdjT2!_=    (55gm١BHi=    ըlBR]TdF8    `AGS6*U5!~s    RJvPJg!$ոl7g    [>Hno
PJg!$ռ    Zc?'TYI5}    Zk鯇NF{.y    PKݗ>F-:˾=    :|:A5jԜm*=    VnIY[>T,$M;~   Z|?T6YI(u)z3    jxԜMj&!IOֿ9    7?TVYIzDA    "{0e;0@5jui<   J=9BH    *</Pe!$&=   zR?    lׅF-y/NE    һtԨmBYݢ#    TG>HBH:v~CJn   J_uhg~wBUEI    (H%
OBHsZa    leI5y	    ZBHjy	    5)	    ?ߓB6α=7   t7ٞ|"!In֖)	    Q?ۓf>{WG(    FIͧd!$iTd(    "O=4Ν=J   `9:<,$mtS6)    |ZY|FB&UҽG*    U'5בI-r     !oOj#!I
    #IBHҤj*
    cKno
Nj>GB6uGX    ގNj'!ITkTs    )Id!$ipr   pNjn !I\k_    L٢ׄV'57jp#  ?{wli]y:"Q0I,MJ&K,'1853FSNe1NnhEP6	""fG>:WҰ9w^Uo>wyCߓ  r\:T@!Ir   @Uq*}V3:؁B\֋r   ȵgsR$-    #rS*w~6';AHR-n,{0    Lf?9dTK0{0    Dbji39C!Iտ    0tcޜ,N*AHRm5OOߋ   `7N*AHR~d    ~75gpR1Bjuڟ~[   \ud7g!I6Sw]f    U՞I?V/ks?   @~& $i(nh    EUlN徿M*AHPjߧ   s>M*AHvij    X7bڤb$1o~    e?g2Ij=    wפBZRU~   SWd?_2Iz    sҹtms51ܿK    ;vw*\M*j $i$u9)8    W?<M*j $i$d   8qe*f?O3IYݫ7~?   'WS7d?G!d4Rm    h}&C $iu<4:    <Nܚ~~&C $i#   D3b!I#s    ]%T1W/<    j̤b$e>    wYʤb$izrS{    N/V&~!Ijo    ,b>L*FAHRz_}   Eٿb|L*FAHRGRU~   `1y̛I3I^~    `^!T8>/u[    XrK*3T8s    ,3[0ȐAHXTGr?    Xo%Z,L*2d46dg    6SWd?L$Oӻ~4     Ʃ_Ҋ|UBƢ    `8g?UaI1K#Iڻ    DQUw?Vj><{I,Y[#I8F    	ϻb|bsIzg~V    `U<`g]R1?{],);j    L֙K*ơ]_K^I/Y    \[.g\R1kcIyث I5jY    <Uk[* GcIcÛ I׵    L~%cTwl>4N/Hmf}    `rnOI+~i~,i/H3Y$    ?YR1fɒ7_$IOV#>L    0Z|49TaWoN.'RUn@   %OZ_~,/HֹP   j\WR1nl岤{_$=eS;l   |>J+iVmk/HƆ7TUY0    MSqҊhzהkfufzy&Is{    ,^U{&_J*Ƹaf?塯$*흪ù3    _Ϫbk__$Ho|*s    cwۥ9J*Ƽū?.t&I;.s=o    SHϾ<bp5da5O9    Ȩud?	-z]I\^F    2xN3)5T?^7L/%iG+=/Uͭ?    ؜u{g?	y;w|J)](Is   Qg?	qœBs>JҜ)rԏ     PG?VLVP_%i5zQ?    0oLݲAI$5S? /RQ[Y   auR7d?{	q>>?9-z   `N>O?5O/TSw~     wX,TBB%iu9iT$    Iܚʃ_I*&ջm> zg+IT[Fl   LR15O'~i({u,Iu3	    CҽKR1uZ/XtɰM    Y\KҊ	mjiڴPhIZ@^R5g    qo~$\}2{ T/\R!>    PƩIR1uX?A(ǿ%iAMo3
    5m8+?OVL{Bݛ%i5{[JU5g    zT;9TLxcBI~HB\uU    sGRHAxٸs>zW    Xg@g?;Vh3RxhPwӥIqoO   <nI+}'^:|W    X؜=yTwڗt?   y»I+b8)Uifz_$Qطq    u.^H*_FzAhyATW+?    wۥ>7HZQ_~{=S ti/Jjk3RM}~   `|n~fNBQd$~/~o/    sNgBRUSȽBNIRu.?x0    A}IEZgdB8%ٿ@IU8G    vT|nV.b Rj_$XR3'    Oz{*3Y5ÃPj8dB%:   )Se?5k6Ah𯄮84+Iujywݼn    <֙G
Xku9A(u8ٿ`IƑ    jҹ?,aWRB)ђTsKF
   n4ӻd?"־3></r˲Tk+wN;*   b6庽H+TgF<ߏKRݕ_ֶT   n+5',2 48ٿTw3>+   b:#u5617~v]Z!Iu׽\   ;/-^+=߯Z 43$5?&   Yb9R}m~`*37Dq̛Rwk   DS7Aq_RAhs)ٿ)4N   MǾ5wZ/B,7GnjtII   PZm)p?Ru[ T I[%   @+~f#E<%j><@窣$iN@]J   SrY)l+wN;[ *5NzOo$Nv	   0oHgg?"׹dЮ%fOźeIRyfo[&   Ĩ-ٗ?<-){1to:?͌7Nq>):u6   [Ǽ)ٌRCkZ<IF?3&   x:CdЭ\z7_0y(PRy%vJM	   0n:<F
^CFr=g|ж{}N#	   079?>":#6t7}+ͬ97T   ԿT-ƑO]W*IèsaB   FzTg/Rʃ~#U=Ahy懳s%i('tQF   F]~'rsR#G2^'5Nxwo$՝   ¨y~"nztqK|ds[*xmo$\w<!   `YЭ\ם 4Tۓ޸bS   Zu.?8^#z]/IuM
   `kO=~"#r_z^{dHRޒ
   0/Mb*R:: ,@bTg#_R
   ?6k<E
Թl]Wb3P$Zg|(   iUN/~"}X'YKK!I^!   	URs~~"mzԽ4nB~-IjԿ{o    LޖDgޏMh,Sq$*侽   \OޗDZsSҸAhͩ8hTWޝR
   }"Y^6q6V@x 5yK$U}k   e?#離5fug!JR]   CSS14.^'M*?LIջ?}g   bzg#R<svl$;=s)ifnC^ܷU   `qLDVWӤAhw<ȒКǿ3~7m   nJʵ~"EuRږ&DB#y%l  IDATiD[*   Xr@H>+uސ&B*84L/×	   @@Ry}HjTm=Mu<ⷳHҼ[|   ԥz!Ei3RSR9uRk4bi_
IG{供   Tͭq볟wHQjBzQ*׿</$ͧ_#o   -4'9KaBڍԺifY$i5OӔ~;)   0<7o:磩*bBBG84|:-   4NjҤRgפBBԹTW_"IK   `GT~!Mr^z?>7-GU͇SO]RIjyqE'   0*XiB+׿4uݴ<if~$*+%   c?CC^W3c|?5'$jT5}   P~v!MZ_N٢ӻ<}Őy[Sr2  1Ҿ3,Iy̛SG_M}E7=wUy_e)%jٿ	   о*h3S?}َE;=ڸ2kUU틦s&  Wd?ƽ~7u}bx
~zL-<4&/$moji˹o   @&L䕇8ԿG/Չ`z;gT=/$ӻަKr  /W>w|B5:rBj|]KZ}[   Fq*y4\Ǽ)u.Yw T5J'QYs@Ң<vW!   0d}!ekjij:#{g 4?r "i8Sܚ6   IUQV=5}kjR_KU%eAO+֧~I]wm   5I0_Ze\6n<'UOAhz[~:Cͳ&G>L/~IU+O   5\oiN\6M^ޘ''>sAϘ0Bzd̵6N{h%Mln   @M"MB}0O!     B            3     g           A      8     @p!     B            3     g           A      8     @p!     B            3     g           A      8     @p!     B            3     g           A      8     @p!     B            3     g           A      8     @p!     B            3     g           A      8     @p!     B            3     g           A      8     @p!     B            3     g           A      8     @p!     B            3     g           A      8     @p!     B            3     g           A      8     @p!     B            3     g           A      8     @p!     B            3     g           A      8     @p!     B            3     g           A      8     @p!     B            3     g           A      8     @p!     B            3     g           A      8     @p!     B            3     g           A      8     @p!     B            3     g           A      8     @p!     B            3     g           A      8     @p!     B            3     g           A      8     @p!     B            3     g           A      8     @p!     B            3     g           A      8     @p!     B            3     g           A      8     @p!     B            3     g           A      8     @p!     B            3     g           A      8     @p!     B            3     g           A      8     @p!     B            3     g           A      8     @p!     B            3     g           A      8     @p!     B            3     g           A      8     @p!     B            3     g           A      8     @p!     B            3     g           A      8     @p!     B            3     g           A      8     @p!     B            3     g           A      8     @p!     B            3     g           A      8     @p!     B            3     g           A      8     @p!     B            3     g           A      8     @p!     B            3     g           A      8     @p!     B            3     g           A      8     @p!     B            3     g           A      8     @p!     B            3     g           A      8     @p!     B            3     g           A      8     @p!     B            3     g           A      8     @p!     B            3     g           A      8     @p!     B            3     g           A      8     @p!     B            3     g           A      8     @p!     B            3     g          oh   O=>6!     '           @     B      qB      N     	!     8!     '           @     B      qB      N     	!     8!     '           @     B      qB      N     	!     8!     '      vڞEyC    IENDB`PNG

   IHDR  
     x6   	pHYs    {Rk    IDATxyw]{
 	&LE%*WQQE۠6h;*,(IL&@32dsB*$*U=?:AZ C޿zWZp_rΏ  Lz1]4:~TGB4u}[4'o#  oGJޒ4b-mܮswٲyn뿕 t?   /ugCrt/qoֲ^KX_KDʾ   f_5ewI8v.}Eݘ ye 
 @AV]݋wTG)Zw?fg(bϾ   Lߚ%iZcTG9}<^3s>  %3  ,Vo==:A$Yψξ   \y2G9;LϏF>T  ((  ߎg>5\K4G򱈦ɾ   M^OBZKt>_cpN  f(  ck^gdi.Z+˾   R4>g$Ӳ]s_Fُ8  .  A77o?(棩1Qw  @fc>$W_ͧDzُ:  j  dhg4o-!7}  #PIsʗG騫ُ;  b  z~ZK!4-1}  :$۲GFz<    T%;JqVm  0@%KKw7 0@ )ugCtܖ{}+  ;ߌjWI*eF*  ?  Pѿh|yՒcxEw#  X-}~4[Ndߞѿ񄈦~  nꪨ>RbղpUٷ#  X/)dIǾ-o~ P  [)jQkٷ$  XhM/J4A-q\3  L8P  R:?Z*VC_Ͼ%  S<] ` 0jmtNYiȾ-  п<IԂ*1 2  `~(+koK  .xɬ:pُA  &(  soЋOI߭%Q>  (R'iBѻ~ 0!@ SǢ?|F$  `5ut?&+!    93֕ҨT=Gn̾5  7EwJ?	!  3  `Nvx~*o\}C	  01ަhҿ%Mnղ    U{Wj.1\uU	  0qh߅&ѻbe B 0{}J'  @fCQCI]DG"  1  `Vԛ7J#Ւbٷ'  īuO1'J:'~$ PP  [+ U/dߞ   |fҿ%MtFݍُD  
a 
 v}+~"Tû˾=  f4;    m6|hg4r;>}{  zO;JOrُD  Ɯ(  ۤ^*Z&TSoO   MD?4͌@9x  (  [pRiZo|*  `K9ߒ&qd? S  lzӚQi__	  Vh}ӿ'%} `k 69_H?FSٷ'   ۠Y*^])Is?H ` eAOPi  P!/Le? 3  ly~ *Z38oO   /Fkߙ&1ُD  ƈ(  ϩw҈=}0  `qT$7f?   <}9^	  ,]oNIz]uُD  ƀ(  Ϩ^`V~)RMoS	  \hߞwEuS g 
 w:(OFZ}w  0hsߠԻ|e# g 
 ~pJTѬ_}k  0ߊjKӿE%Mxw_~$ 0@ !o^҈T=5wdߚ   ̣+5(TdW;  (P  Oz<Z"`Sξ5  H03ߥ&98 `D }'N42M?/|1   Q＿>4M-]g? A  |O3Q:X  l :TI]un~" 0b@ Q֊dJR}oK   FD^_*i^!  #  3ޟ~)Js*  `ԏ]ӿY%Mpwe? !  _?F)QoK   F/]%Mn
 1  t~T~p)z}W  0W*ixB a 
 0zW~`)B"֚[  1=ӿc%Mn{Ft7e?
   n=廥XJU<ugߒ   AgHdJz.~ 0@ &XM?[K#v  `4WEbZIYQoz,Q @2P 	U_~P)60w};  0_;JȺ~41 @2P 	PJ[  1׿|y	6~( D3  @|3Z?ٷ"   %h\IY~
   `uI)ΉwD=Ⱦ  (DY_+i򪖽(jmc $  pLJY+Γٷ"   5ZKvN4y/ @P 	?HJYU"'̾  (Sҿ}%M^  $0   ugC~ )dzm  @zm7ُ?   LDJ)M-ge߂   La/G5[XD9mO?   LꐟN?2_<  `4jWKk~ 0@ & /ioA   &KxbIS ` LO?ѯo?   &Tҿ%MN{Fُ>  ( Dk@J}O  @ɿ,ir'    `=2QזCfz   M{]T6[YD=ϳ{  #P 	o<JԂrjm   S?hM?/YRU+{  P wtm   ?ofI˲y  P vx4_uO}ODdv   Ú::ǿ=YR.'    p&a?Mwc-   ϨhT<ZRUx yb 
 P!ZӋ%Q7  4|h-![ZRk~ 0@ 
6FiΛZû}  }cӒnp1ُ:  ( @:gEA4X}  ֩9Wӿ%[ ` {G4M   [yyI2V4u  1P Bso!4}C4ٷ   lGkjA72  s  PNL?`Ϳ!^{_m   ۭwҿ%Sq  1P BuFiNZ{.Ⱦ   `v>%W~ 0@ 
U3\Իx*  YU?qOTK_-:j 9f 
 PoI>`f	h[   fcҿ%]"jgi  %3  (`U,Wh'o/   3ޛ-'h ` #YmG7o-   SM}EwbwQ 9d 
 P9L?XfuGgV   0/RK*~ 0@ 
>W٪{֟dR   0e2G  s  @{,JQ跳o)   WMoS~}wsһi  !P t7*JQQ?~W   )ꇯҿ%w#ߔ8 ` f释l4	   R.J>4U2Q 2  ({o%   W_JN4M-y  P&P vxA'V  P?qw.i|k6~ 0G@ 
ӽҶV-}aԏߕ}  HovI6 r {_(J擲o!   =Mޕ.i<.) 1  (L(JRf>   0֚V,]5|G  s  0~+@QG1bɾ}   `n\7kxyُ/  ( @aObU-9̾u   `,tO_$m][O~t 0G@ 
SW5?6  TOS𒶪m~t 0G@ 
SEiK[   Sӿ%O~l 0G@ 
ҖThko   KSߓm/i<2  (( @aZ+_~(=gwWg.   0MFϏK. 1  (Lk[   ӿ%~  2  (Fαoٷ
   sK@ e 
 PPr4]   ;Zk7  \  1 (7[   3o~I( @@ 
c Q{g   P	L4   0Ū^M{]   j֯jً $^  2  (F1|[   ׿s I#( @@ 
c Qξ-   `r~ i2  (( @a@5J?"   &Fh-9L@d 
 P.P jdQ?vk-   F&P r  TRCo   L~I( @@ 
c Qsh   &Vף50@R~  2  (8o   xs*@R~  2  (\    dTI   0ʬso   0B~^ )7P r  TYUwfCٷ    62  (( @a@(   zZSف@ e 
 PPe9/}   Y/[~~ )'P r  T]bh6=}   f؋a{#H@ e 
 PPwȾ  -0\ue%H@ e 
 PPg'   B~ i~3  (( @a@5_Uwfٗ<   ڨV4\Ae 
 P.P jxB   lǧ+H@ e 
 PPGޙ}   ۪i_O?_4?   0ͺ/u   `;kn$y  2  (Gf_   ,7>P r  TsY_h   M{]T+H?o4   0w}   h$i  2  (+/o   `5uzs  \  1 \>~   ́_ԂIs( @@ 
c Yoja߾&   PAH@ e 
 PPv/ٗ5   0ǚMFf?P r  TYukmʾ  yпbeY  \  1 l6ٗ4   0_hSf7P r  TU?ɾ  y63	I( @@ 
c ٨ZG4ǳ/g    AwMH@ e 
 PPFOξ  $w~>!iv2  (( @a@u>M})   z_3
I( @@ 
c jzQԏߙ}   ɚަ{eY  \  1 ?g_   \lY  \  1 նV^+   FE=?~f!i2  (( @a@<'   F/YHھ@ e 
 PPmKs   	H?   0ͺ/]   `DՏg)P r  T[[eٗ-   0g3Iۖ( @@ 
c t/[   `5֒2$m}  2  (_Ⱦd  1ѻg>P r  T[Zg_   izg.P r  T[^s{
   GkHڪ@ e 
 PPmI/}
   z~&lCҖg 
 P.P 깪V4K   SûK?ߐ   0z}   csoqHڲ@ e 
 PP=[O̟j   #7EkjaY  \  1 36 ߺ"   
?   0zA	   Y@yHz@ e 
 PP=mӋ^{_	   w{Hz@ e 
 PP=]/}	   H~!3  (( @a@UwN	   wG?$=s  2  (~f_   @6ղHz@ e 
 PP۪,b;,  /;Dg 
 P.P 6K    MoST+_~"3  (( @a@?M}I   !~8P r  T/G   `:Q3Iߟ( @@ 
c uNzW   L7J?   0jM-/E   `>'G$}/P r  T3ޟ}   lpӉ#O  2  (脷x;2   &YSG7染H  \  1 e%   L?'T  2  (yٗ    @DDS^"  `  1 z_H   ={/L?/d 
 P2P NfF   tsi3  (( @a@'Ͼ    ~/H( @@ 
c :yUw.   xZޒ~~"Mr  2  (տ|ye   w~~"Mr  2  (dU-5   Y|S94   0U%ٗ   s~f94   0?/9   4>)$f 
 P.P NNKg_n    [lp)$f 
 P.P NFղG^}   l?~"MZ  2  (dԻٗ   V|R4i   0W-}a4ǳ/5   W}OH( @@ 
c Z~se   ,H     IDAT7~"MR  2  (h-o   ۰A?"MH  2  (h.p%   ~"MJ  2  (h-1/1   -6E@ e 
 Pr   `~Dy4	   06 n;    fϠ~?w
  \  1 -ɿ}i   ̺+]3  (( @a@lٗ   kZkًTr  2  (hyu
   `.@ e 
 P}~e   0gGkzQTj  2  (hYɾ    T?I?J  \  1 -f_R @h֯[^}},]{an;ySgW#uGh"Ah g1R   0T#ξ 1дrbn<>- :'3Gu7W:2Ӌh9?˗OscWgܫv IN?J  \  1 -Ͼ Q0E1_}P.ptO{o|m~~-/a{>6ֿ}oA' <~M3  (( @a@izQ4ɾ 2G=13soάz]IVSfw==ѿtI<' P_D*,P r  g~ R c/EE7Dk?Sݢߌ;YY252  (( @a@˨~K	 ^ u%3?gZ3;_oW]1e_ hB*%P r  t|7/# `k'GEDk\1U^s/'^Q/ `;:g	@ e 
 Poxٗ \Qa9wZ!Uhtxn95+ x6NT"@ e 
 P:u~; sUѿlYt{s;Dط۲. ilmf
  \  1 W}	 ߵyؿ«]Q?rSe |W^ղ ( @@ 
c :-ɟ#DMzZt?QgJ}^3Yw%	 O@*!P r  t|<6 Wާ~cςg<jjA~k~x45ٗ* Lfh-1i3  (( @a@Ƿ/ (_Dеf~c_c{{bxE3 07gi3  (( @a@ǳ~)kn%>}wFS=}YD2/{  2  (x6K S>z_xM^d~Og~, 0ڟ~i3  (( @a@ǯjN Eh|0Cߐ>1팈ξ HOK( @@ 
c :~.he cmΧ#ZSڇTtİ}[ @YݨV,]/k  2  (50ud_6 0{_EEtT]2M ѻx*/k  2  (x9ٗ >_;,G1=.=WՊݣho {G5(.c  2  (x5K B=ѻZK[ڪ}^+跳o% k4   0b;d `t5u(:';ZSVg;:d] 0קϥq  \  1 z_ FR~"_oh N_NK( @@ 
c :>kȾ\ `4WG+jnii><`*2w4n   0Qf_* 02'4ZӋҼ7 g~ Mfߊ 03.Q  2  (x43ٗ
 ۰7ZwL7K-%zLG{ٷ& e 
 P.P ~Fݘ} @۾;!,Z#sh'd4.   0_ȾL  E=guX?lz,忳1  \  1 o_} j+gSʪSoa I7q  \  1 ڟɈɾL `^45;Cњ^ƹ)O4;`t>ii2  (( @a@GeK/ {^9$廦{Rξ`lMhi2  (( @a@GѬ?95뼨z]{W*Ifٷ: a//K?K( @@ 
c :u}[ s~h[iV̾`$.hY@ e 
 Pmpٗ ̺.z|8ZwHJVD  ei3  (( @a@G_Mg} cpӉQ|i{Vڇcf?  UQ  \  1 ͺA ~htp\ n?3},p  2  (h6ٗ l~;zLGkzQU=y &S=j.F5P r  tV,bϾ4 `(^^?Q= wҨf 
 P.P ^: mt7D?OJe/gg?> `^5WEkai3  (( @a@GᷮȾ, `IJچDُ 7ޕF0P r  t{eD=̾, `XkjaTyt~ u^W@ e 
 PѪwe_ UꇮOJڇwxW{i2  (( @a@G_;$ `4uX祿?%~>/d?i `/[ޕF-P r  ttxuDd_ MEw;%qӋbpIُ SGGMd 
 P.P N!r 4Q#)iZ+Vd?z `NuO}O;W@ e 
 Pѩ^}}  ϬiZC;SEO" )]+R  2  (hT:t7F/%93 (ND?F%P r  t4}/ xZcG%֚G lbpӉ;CEYiT2  (( @a@Gk/ ![N]ߓF!>e? `5]EV8-P r  4j=w FK=HI[uk^{_
 ~HUWEC{}^Mi2  (( @a@ٗ |Oz<:ZQW;$~ѿ=O}50){  2  (h~/ɾ `FhSFISeQ?zs	l\Έ1%;3  (( @a@sV>gv [е3CwZ[Zc4]EVΓ&%P r  4 <'ZKvN/Jߪe/d? SMwc,WSNI( @@ 
c s/ &cxwZk#Q=78G)ZwHI?   0yUK_og_ LsCI9g? !O)/Sth-)}%3  (( @a@~ &հ3ޟ.Tfʗf7 &O鱧ƞOEwFKK>P r  4 D*:v{PRU"'~0ަ~_u@tOxMGd 
 P.P &50Mf0~+=(i"3e? `;n:1z|?>(]#in2  (( @a@sjz &Mf;PdUcl\`+k-Fyjdw  \  1 ͩz &n&?M{]gt}EV,!)7P r  4z L
SG:OD z*3?Ԃ  \  1 ^4 LOI#TߍOFQ^s{n:1z|?>(} i3  (( @a@)oMIҿ{ j6]=܏{ܗ4   0	w@~$_4)	0sA/;:_ZG]R9   0h(Y=3<Iz _pUEu咊  \  1 : wwM?/\=05w{??-i2  (( @a@+(Xw$miՊݣ^{o Uqu:oIjngI2  (( @a@z jp19Iڇt4ُPyt7<ܯ9$/}_  \  1 pMO@=,"RgyC
S#TdF),9MR&-CKi-6%6%-7zt/$k83;O^d?Çw]\|GkJ?J&kU7/GֺKcnYg$( @^  ή' HhJs: 7{X[.GƊgJB3     G?7 <y7N&QEzkQ]g4PId  y $c :'~n Oև]}uwD_Sek[m_[:~i~a$M9P @ 1 MS^ dRUs$MJCџjU7/GֺKcFIu  y $c :[ $һ&IӪ;z߹t](:d 
 ( @2ip =16If-o|ot/OiJ}	f 
 ( @23蘃K~"Hz<MfPGKTSʽ%i2     :e@FiSwMfg?}w7{xi-%( @^  N~f |o$ͺ)U`.a>vG飥{J_(准VIR@ 2  H t8X;gU)cR]wn)ݫ#K?ÐYd 
 ( @2SK~"Xª+='IR`ό8)]Jo}_7 GHҁ( @^  N/~b jXg2IRx+YLʰ_~wn,OEi;4$   /P d@[wF?1 KXLRvoWot](
L$ e 
 tܹ%XwCo$թ΅oxQƾ.ܽjyio:4Ox~g$i@ 2  H tspOD?1 KQYZk<IR@=TKեsI?!IZ|  y $c :ZLDu>;&Iuywϰ_~e{WNYi I|  y $c :[2yX\^s$չYRpyUU~ҿeWƊgݗ$&P @ 1 Jo=7yXjZc7LBkWEjCU2ҽjyio:4Ox~qIR\  y $c :'vE?/ KLʹ%IK凔C7FtÒSu.]Jo|Ti;<$V e 
 tj`~뫾ZUƬuKK鵢?¡2|+sr?eqw%I   /P d@Sߏ~Z ׅ/IZu##jڳR7Q+wT2     %叇.IZ-+(~t+퍯-Q"P @ 1 NÇn~Z Ti%IK?\Ξtnvm+kKgQ}{ e 
 ZR`^WKԽm0A>߹tܗwLtd 
 ( @2}+%b︣qKR4wP<pMG;m{KJ3}s>I@ 2  H tu/{wD%IjyIOG?j?ܯ[]ڛ,U/{#I( @^  N] ,Çn,ewKxo+;Jo|Ti;$-@ 2  H tUO< ,s^~$)W.cpP~wn,ݭG*}$i e 
 dk'`	%IkR{|~^7}֯Ʊ^Ie 
 ( @2 ]U֙/YUˣ?Ij?YuK{ӑ?ߒ$M3P @ 1 lGf ӿ{%ID-gp۾t6UZ/e%Ia  y $c :w] pPZ4^IҁRWOѯ΍pDixF[I3     V5~R jo$ho>'㟚.;}_~$ e 
 j	@͵N{%IZTǢO 3V]_>w,JT2     >	@2VIҁZ7EiU7/GֺKcnY;Ij  y $c :zW~N juJ斕WG&a8?[v$)Q  y $c :wn~N jjm~$BM,-՞VY$){  y $c :'~N jjWG)Iҿ*DU2ص-4W0ό$Ib  y $c :'|oSPSSCo$_7JRri}l>johmgD$ df 
 djO	@Mu/;%I?2{΍pDixfIOg 
 ( @2{ٻ:{JSܲ2x߲:sK^7Y?/%I e 
 ~(z˦z@$NR3B~9}}i$I   /P d@'#7     IDATۢ~$ItNKϠ[_b|Ti~j[Jf 
 ( @2h3J%Igkj=}.cw΍{J_7I4@ 2  H tNgڛQg:\Fepҽjw >$)&P @ 1 ]|0ɯ1(I<-?yW9Tݧ`׶۾vW;<-$IRm2     ׻gf}o}$Vc]RtKSK7)/-Kf 
 ( @2op':KOsyɢڳot](
+IV  y $c j3P#;&Ix
}w{tdi$ig 
 ( @2l3Ki$IMKUݧ`׶۾t6oL$   /P d@W봟~B jj<V	Ok>lȲ2ܽxz\'KcF$   /P d@W8	ko$i^r?=)Gg$In  y $c zמ }$IGz+{^9W<{sK$@ 2  H tqn(	cw%I^nvm+kKgQҘ[Q$_   /P d@ۣ^uL]$M凔᷾:!ѯ΍_<$Icf 
 ( @2hR'&Zk,6I&R7_ٽܯZ^%I&( @^  .~> jb{G]$Mee9_,{?tdi$IS   /P d@^{k^wI4Z<^$If( @^  .wD? 5%I$IY2     Ѕi@=&I$I4@ 2  H t2 ޵'$I$I&( @^  .hEM$I$iR e 
 [R* V=pi$I$IP  y $c Z~: j97I$IIf 
 ( @2:$I$I$3     Ѕzt$I$I&( @^  .?t 9I$I4@ 2  H taTw{$I$IҤ3     Ѕ5|O@9G$I$M:P @ 1 ]XUgO)G$I$M:P @ 1 ~6 v}=$I$i e 
 |yw݉H$Iid 
 ( @29@G$I$M#P @ 1 e~6 "UUi{$I$I42     m?% 4|[$I$IҴ2      @	E$I$M+P @ 1 C7E? [~$I$IV  y $c :~G? Zg<I$I4@ 2  H t̖ZJ5~6 H$I)e 
 ( @2\' [o$I$I   /P d@ǫ}+@/}$I$I4@ 2  H t:Q{o$I$I   /P d@ǫ{ٻ@j-$I$i e 
 x_d jzA-$I$i e 
 ?' Hv$I$i e 
 x: 2wH$Iig 
 ( @25|' HYwH$Iig 
 ( @2U~2 t/;$I$IҴ3     1ZR* [$I$IҔ3     k P?~$I$Iv  y $c :z~. T}	:I$I4@ 2  H t> R=;$I$I,2     |ϣ ]ׅ!I$If( @^  ^~. wnC$I$"P @ 1 k W!I$If( @^  ϝ ~$I$IE  y $c :z.~. ?kwH$IYd 
 ( @27| H딟C$I$"P @ 1  ~$I$IE  y $c :zUgOsA$I$*P @ 1 ψ~* wH$Ie 
 ( @2<
 ~$I$IU  y $c :ZuG? A_~$I$IU  y $c :ZT };$I$IҬ2     jo|]Sw;$I$IҬ2     \GO@w!I$If( @^  Vw[
 ~$I$IU  y $c :Z+. o!I$If( @^  V
 ~9I$I4@ 2  H tz޴> ZwH$IYe 
 ( @2#G? A'@$I$iV e 
 hLSYwH$IYe 
 ( @25x  ~$I$Ie  y $c :Z7G? 7H$IYf 
 ( @25O@j$I$I,3     ; 3=7H$IYf 
 ( @2Uu~* 5I$I4@ 2  H t斕2D? _!I$I4@ 2  H tV>; 2;$I$I3     kzA3dp%wH$IYf 
 ( @2\g +I$I4@ 2  H tZ~& o~$I$Ie  y $c :. G$I$I   /P d@篵ᗢ	 g!I$If( @^  _WG? A7C$I$2P @ 1 V3$I$I   /P d@}	 /C$I$2P @ 1 L }wH$IYf 
 ( @2׹@'!I$If( @^  _w_F? Azם~$I$Ie  y $c :ݭ~& ]~$I$Ie  y $c :KL 1 $I$h e 
 u/{w3;$I$I,3     ^g H5wH$IYf 
 ( @2׽	 !I$If( @^  _L pj$I$i e 
 u:& ҿ;$I$I,3     ]" ҿiC$I$i e 
 >wl39wH$IYf 
 ( @2׻g H;$I$I,3     ]* ҿcwH$IYf 
 ( @2׻g H$I$I   /P d@篷@[$I$I   /P d@D? A^~$I$Ie  y $c :k	 ]~$I$Ie  y $c :/~& wC$I$2P @ 1 F? A~$I$Ie  y $c :<o<# R=~$I$i e 
 ?i}3;$I$I,3     ~g H~"I$I4@ 2  H tx޴! !I$If( @^  _E? Q4
E$I$*P @ 1 S	@='I$I4@ 2  H tzןL jH$IYe 
 ( @2׻vU3uKo$I$I   /P d@c	@3_~$I$IU  y $c :+碟	@폼&I$I4@ 2  H t}o3E$I$*P @ 1 e~& u.zs-$I$iV e 
 u# D"I$If( @^  _w[	@+o$I$I   /P d@?~& ~$I$IU  y $c :4 Կ[$I$IҬ2     G? _x-$I$iV e 
 uc3hpgo$I$I   /P d@}	@;o$I$I   /P d@篽g PH$IYe 
 ( @2oF? Ξ[$I$IҬ2     k@C$I$I   /P d@}֯D? G$I$"P @ 1 ?L k;<I$I4@ 2  H tZ4 >$I$I   /P d@L k{$I$I,2     kg X~$I$IE  y $c :B+L ^{$I$I2     *~Sw[$I$I,2     ѪOF? 7~$I$IE  y $c :Z՞O@[o$I$I   /P d@Gkͻ
@;o$I$I   /P d@Gk/E? ~$I$IE  y $c :Z]ۢ
Hni-G$I$M;P @ 1 W/~* 5{$I$IҴ3     Q9 :'$I$I   /P d@G΍O@ٯ
G$I$M;P @ 1 O~* uc=$I$i e 
 hT ^{$I$IҴ3     ^< ֻ{$I$IҴ3     ^ XYH$Iig 
 ( @2[
`;#I$I( @^  VsSl{G=$I$i e 
 h7T ~$I$I4@ 2  H tZ~) VKc!7I$Iif 
 ( @2:O@4C7I$Iif 
 ( @2\}XSPI$I$M3P @ 1 F? 5$I$I( @^  ^6`ݭG#I$I( @^  ^@u'#I$I( @^  [`[>~$I$If  y $c :z?\ {$I$I   /P d@GopE@7G$I$M3P @ 1 ;Ύ~. uH$Iif 
 ( @2vRsP~$I$IV  y $c :zϾ7 ֺI$I$M+P @ 1 Χ\ @{o$I$I   /P d@GsI$I$M+P @ 1 G^\ @o$I$I   /P d@GuˢznM$I$iZ e 
 5HsP]o$I$I   /P d@GywG? 5P=`M$I$iZ e 
 Tpd DJc!wI$I)d 
 ( @2U=HP͓_~$I$IF  y $c :^Ço~2 j}+o$I$I   /P d@kpgl>*&I$I4@ 2  H t~޲) #&I$I4@ 2  H tzd @7I$Iid 
 ( @2ս]O@,&I$I4@ 2  H t:~2 j`؝7I$Iid 
 ( @2oD? uoܲ$I$IҤ3     jO@M4O|Q]$I$i e 
 x5W0 Y~$I$It  y $c :f\J5~6 jO$I$I   /P d@ǯj<l @7I$IIg 
 ( @27|g;7$I$I&( @^  +~$I$It  y $c g=o$I$I   /P d@ǯwg4V>;.I$I4@ 2  H tmPu%I$I&( @^  _7E? 5$I$I   /P d@ǯ@Mt/y{]$I$i e 
 Ng&z`]$I$i e 
 5W  
K$I$M2P @ 1 ]@sJ鷣>$I$I3     ЅU=~_Pƾc@]$I$iR e 
 <pMP_~$I$IT  y $c &g*.I$I4@ 2  H ta[t D~$I$IT  y $c UPNK$I$M*P @ 1 ]Xs' %I$I&( @^  ./~: jbmwI$IIe 
 ( @2.zҘ;(6I$I4@ 2  H t-+߉~> jM$I$M P @ 1 ]xG? 5>wI$IId 
 ( @2o@Mt>$I$I   /P d@[ύ~> jwwI$IId 
 ( @2w݉@Mt]$I$i e 
 ^&~$I$ID  y $c ! A4986I$I@ 2  H tF'86I$I@ 2  H t5W0 G#6I$I@ 2  H t+`$I$IZd  y $c ߾7	
K$I$-6P @ 1 ]\{~B jbMK$I$-6P @ 1 ]Co D$I$I   /P d@W~B ꢪJ
M$I$-&P @ 1 ]\0	/M$I$-&P @ 1 ]\~B js&I$I( @^  .â]26I$I@ 2  H tn#mK$I$-&P @ 1 ]|Go~F jbp_    IDATwI$Id 
 ( @2op%@]ۥqI$If 
 ( @2wÇiyIm$I$i e 
 ^gF_~$I$IZh  y $c :n3P#um$I$i e 
 k@o<#6I$I@ 2  H t5{n3P#?~$I$IZh  y $c :O	@MTO?~$I$IZh  y $c :o~J jyw&I$I( @^  N臢_ Hk/&I$I( @^  N'G?% 5䟅&I$I( @^  No~J jw$I$IB2     F\~$I$IZH  y $c :ZF'M$I$-$P @ 1 P\ʠ EUqύO$I$( @^  N7~N juo$I$If 
 ( @2kp%	@t.zsm$I$i@ 2  H tr>Fz~$I$I7P @ 1 \-o~N jdp$I$IҸ e 
 j5	@TO
M$I$( @^  N/~N ꤪJ}	O$I$( @^  NJ鷣iI$I12     6|'F:)6I$I4N  y $c :w|*Iu'&I$I   /P d@'[ouqm$I$i@ 2  H tu>O
@T~$I$I'P @ 1 ljP'հ4$I$IҨ e 
 dkO
@ʹ$I$IҨ e 
 脛[VJ H?O$I$( @^  N÷F?+ 5һ~Mm$I$i@ 2  H t?  o$I$If 
 ( @2wgF=M$I$( @^  NEo~V jy$I$Id 
 ( @2i$I޽G]w$JEWۑ֩Um3.{+-Ӗv:uV֡i.A1r ĈQADcTGξJ20 |~zoď&Iڋ@ 2  H _g+ \$I$Id 
 ( @2S- }$I$Id 
 ( @2K?Z *2$I$Id 
 ( @2ړ?Z */	O$I$=^  y $c 0G TO$I$=^  y $c 0:82~$I$Iz@ 2  H ta#- \7I$I   /P d@n@m$I$2     Ѕkk?^ *2$I$Ie 
 ( @2G d<(K$I$I( @^  .\K&2ݵ$I$I( @^  .\s^PyO$I$=V  y $c pu׼42\~$I$Iz@ 2  H tYRʨP/O$I$=F  y $c MG TI$I   /P d@/K7F Ts+I$I7P @ 1 ]؆L~$I$Iz@ 2  H ta6~$I$Iz@ 2  H ta1 pf}$I$2     -e2$I$I( @^  .|{1PQ,	O$I$=R  y $c o c2wT}$I$2     ЅoxQ3 $I$I#e 
 ( @2_ߏc$I$I( @^  .|ݵˢ?f *3$I$I#e 
 ( @2̒RF4߹3>I$I e 
 4t$I$I3     EKӛΉL}~$I$Izx  y $c 8.yGG@e{[}$I$ e 
 g'I$I( @^  .N/>~$I$Izx  y $c H-ߧ4?n j2٥7J$Id 
 ( @2kL=/O$I$=4P @ 1 ]Ŀ8?'I$I( @^  .^-2ëNO$I$=4P @ 1 ]zgqP-[$I$I   /P d@qϋLӽ/'FI$I`  y $c 5߈L'I$I   /P d@E TwO$I$=( @^  .nkF TfxI$I3     ŭ?xG$I$If 
 ( @2[?r *|$I$I҃ e 
 "w2G Ts(I$I@ R3  H t|cG@ez{U}$I$iW  y $c ;7c2Oe}$I$iW  y $c >; $I$IҮ@ 2  H tmLnO$I$   /P d@Ϗd\|f$I$   /P d@cj:D T{/'I$I@ 2  H 4F T?	O$I$ e 
 hLëPgNO$I$ e 
 hLP׮O$I$ e 
 hLS~.6nY~$I$Iӝ( @^  u3J?~ *],FI$I:P @ 1 k2=2OI$I4 e 
 h_tN@eWO$I   /P d@\? zY}$I$Mw  y $c WC?~ *S?-FI$I7P @ 1 
u%I$I@ 2  H 4f~.	 PyO$I   /P d@c' @eW~$I$Iӛ( @^  6' @eƷ|*>I$I7P @ 1 m׏j(I$Itf 
 ( @2u׼4	 P(I$Itf 
 ( @2-ZiG? *Q$I   /P d@ve3 2ˏ	O$I   /P d@^6 P/O$I   /P d@_g @eνI$I4 e 
 h|ݓ& P;4FI$I/P @ 1 ٥zO>%I$I@ 2  H &w I$I4} e 
 hoS 2O$I   /P d@h-O4sI$I4} e 
 huO @:H$I$MW  y $c ZIG>89 P}$I$MU  y $c ZOo|!9 PG'I$Ite 
 ( @24 @e;6'I$Ite 
 ( @24_F? *W}$I$MW  y $c ZO*9 PΪQ$I   /P d@ssJi'@ez:FI$I'P @ 1 [_~ Tfxي$I$I@ 2  H F7F?	 *3I$I4= e 
 h].yG 2Me~>7J$I4 e 
 h]'@'8FI$I#P @ 1 )i %I$I@ 2  H &J 2ëV'I$Itd 
 ( @25ܹʌo">I$I#P @ 1 '*Y Pa,	Q$I e 
 h}|e B,FI$Ig 
 ( @2YRI 2~$I$I3     :ܳ3i Pᵧ'I$IR@ 2  H F74 $I$)  y $c Zg@mƃ23o$I$)w  y $c Zg3^4 Po$I$)w  y $c ZgUd< `[o$I$)w  y $c Zo }$I$Iʝ( @^  h@e&s$I$)w  y $c Zo͇G? jLJg~7J$I7P @ 1 _~ Tw+o$I$)o  y $c ZqG>( P"FI$If 
 ( @2u7'@eF;7>I$If 
 ( @2u7'@en	O$I e 
 h6% P)coI$Id 
 ( @2u= }H$I$   /P d@+g2D? *3(I$IR@ 2  H &wL 'I$IR@ 2  H FםL Ls?'I$IR@ 2  H 9 PΪQ$I| e 
 huOg@z:FI$Ie 
 ( @2-hvi)^S2\$I$I2     v4ڵOʌ|q}$I$   /P d@ړ
 i,	Q$I\ e 
 h;__
 %I$Iʕ( @^  I/~* To$I$)W  y $c ڒf-e0\ 7J$I*P @ 1 mOۯ~. Tf|I$I+P @ 1 mOí~. f)3Ko$I$)O  y $c ڞ  P{^~$I$Iy2     ], Po
Q$I< e 
 hZ~2 Tfx)7J$I&P @ 1 mW^d $I$)O  y $c ڮW~2 f<(G<#FI$Ird 
 ( @2 7J$I#P @ 1 mWw$ P(I$IR@ 2  H e-ߧ4{ }%I$IJ( @^  >l dn{}$I$   /P d@# i&b%I$Ij  y $c ھz~6 Tw	Q$Ig 
 ( @2sF? *4oo$I$ e 
 h;k@e_H}$I$?P @ 1 mgϟt L3?~$I$I   /P d@t PQ$Ivg 
 ( @2_~: To$I$ e 
 hK;LF>1FI$IZ( @^  7F? *3ck}$I$;P @ 1 moE? j3#~$I$I   /P d@[?~> T{/(I$IR{3     =駣 l%I$Ijo  y $c f-'@eF7}0FI$IZ( @^  W/~B T$I$Ijo  y $c W3	PqQ$Ivf 
 ( @2G?! *;7J$I@ 2  H uN'@~$I$I   /P d@_ף zi}$I$3P @ 1 m/^ `,	Q$Ie 
 ( @2o
uOzy$I$/P @ 1 m~F To$I$} e 
 hR&)Pg(I$IR2     MRS2$I$} e 
 hF7~ )P)~$I$I   /P d@s4O	
%I$IjW  y $c *)P%I$IjW  y $c # 9P7J$IԪ@ 2  H 4O;~N T~/'FI$Iړ( @^  ix	
u׼4FI$Iړ( @^  ?~N To$I$= e 
 hkE?' *}$I$I   /P d@| o$I$5 e 
 hƷl~R f2*G}_$I$#P @ 1 c o$I$ e 
 hz|MBOU$I$#P @ 1 UgO

oQ$Ivd 
 ( @2jsg2w'I$IR;2     |o YP;E$I$՟( @^  kp; %I$I?P @ 1 W} o$I$@ 2  H 4_2G?- *3%I$I?P @ 1 dn{6^}z$I$՝( @^  ltÙO
uO=0FI$I   /P d@s~Z Thp[o$I$@ 2  H 4gݓ&iPэo$I$@ 2  H 4i32~^ Tf/(I$IR e 
 hƷ] P
Q$Iz3     м:!yPކCo$I$@ 2  H 4os_ 7J$ITo  y $c 	/~^ ThO(I$IR e 
 h~b T/Z$I$ՙ( @^  nO
uOzy$I$ՙ( @^  nɿ~b T?	Q$I:3     :8PѶ(I$IR e 
 h:+]J3~f T%I$I3P @ 1 _~f T%I$I/P @ 1 gE?3 *(I$IR} e 
 h4PU'(I$IR} e 
 h\3B;(I$IR} e 
 4a'PwJ$ITU  y $c :o*P{5FI$I   /P d@'F?5 *4o$I$@ 2  H t:@_0FI$I   /P d@F?5 *t)	S$Iz2     oG    IDATy
u%I$I'P @ 1 _(P0FI$I   /P d@.Puo$I$@ 2  H tz
M涇(I$IR= e 
 Y)$P)~$I$Iud 
 ( @2/F?9 *[[7J$ITG  y $c :]~r Thxي%I$I#P @ 1 YB[/Q$I:2     {/D?9 j4/3K$I$)>P @ 1 f^ʨ Ю@$I$g 
 ( @2䎭
6y$I$g 
 ( @2pg@v|7J$I( @^  N_ Po$I$)>P @ 1 :_ TS$I@ 2  H t:k碟 _%I$I   /P d@O
?#FI$Ib3     le&P=;o$I$)6P @ 1 zmFMS:;%I$I   /P d@=w$I$).P @ 1 &~)P'(I$IR\  y $c :n τ(I$IR\  y $c :.zkFQ/NI$Ib2     {J:8NI$Ib2     )n饌zO
)I$IRH  y $c :M&	P-
Q$I@ 2  H tn]`.S$I   /P d@o~ T{wJ$I e 
 t=OJ>;%I$IZ@ 2  H t[Oi:D?C *4wJ$I e 
 ;7G?C *cQ NI$I7P @ 1 `L3R5?~$I$I( @^  w!J?GwJ$I e 
 :+/i" m{$I$-n  y $c ]MRSBͷQ$I   /P d@э" ;%I$IZ@ 2  H T\@ NI$I/P @ 1 ծ)I$Ie 
 ( @2R@&~)NI$I-P @ 1 ՃM&9PΪS$I   /P d@`ík# ;%I$IZ@ 2  H T?J=9NI$I'P @ 1 ՃuO|qsR>NI$I'P @ 1 Ck碟$ 5j9$I$i3     P=OJ>;%I$IZ@ 2  H Tme&IP')I$Ig 
 ( @2zh~ TjrwJ$I e 
 Zg4MF;}$I$I( @^  M,T~$I$I( @^  ፶?YP$I$=^ct~f 
 ( @2zx,䎭wJ$I[wPl>/4M|gki  y $c =g	@j$I4[kp2RƃGy[( @^  k饌zOJ[%I$i*~a2j簳v^uBf 
 ( @2z&w\4W)I$I|~xǦ=?|Nm   /P d@HZ HƷ_~$I$٥{ϗh2^J|W2-   /P d@HCVQ/VI$IjI3e?}_?n:'{K3     P=R_4XCo$I::6Z[f(}!n|A?f 
 ( @2z	@~$I$Y=?息Zw~,O[3     P=Z㝛' |wJ$I"7tϏrem}m/iJƷ^Ϭ e 
 	@&[%I$iwsaeuMve)~isli  y $c Gw!V$Iݩphl-Jӽ5P @ 1 գY?X+V*I$IO]6޺`eK%=_g@ 2  H T䞝OJML$I8./|sm[_&sKi&e4߾=K3     P=Vm~ j2oU$Io/*5e|ەzeZ5sG[3     P=VDXoáJ$I:|ewl*MDJӿ?3jk  y $c Ǫ{O:!VI$IPg~2|wk7nm   /P d@.-e؍~ TjrJ$I̒]lr]wzm/Do],?f 
 ( @2z&w\LU3)~$I(-ík+K9Yo3     P=^ x4s^~$I9GJ)ˏ-[uwO&P @ 1 ?>1VI$I5Y_;6^F֗[Oα?ژ( @^  ~Q3b~$Ife22^J3>:=/m0P @ 1 |t~ Ԫ$IScS&_t)~7sAǿf 
 ( @2ڛ;7G?U **I$i:6Z[fxǦt
^@ 2  H T{`LSbkO	U$IwQ*uh=?ʝ~Qjc  y $c w!OM~$I'̒]lϏrߺLf^Z( @^  joܿ~ T̏V$IR[~+KvFw@ 2  H T{ۮ <K$Ifupl-Jӹ'+3ke[lc  y $c mѷJ$IYg޺`em}mzL%'<}1P @ 1 65~$I4,)ݵJaeuMu})qa*=gl3     PmS~ TW$IUg22R诽H_m   /P d@.-e؍~ Tlpџ+I$Kﬃ`lToDť座Rnc  y $c 'k, |A$IRK:JoAe2ڶL涗4_iIWz3     P=[D?Y *UgW$I}Kwx[ǃ误L-   /P d@D'@座B$IRlUކC(|a'k*Sw+=1P @ 1 EO.~{$IY=?⷗MJ
Gﬃ1P @ 1 c[%Ijvie2ڶL涗4_AQ>$M3     P=_g@͆2+I$=fI?]q]2R&oVf 
 ( @2zD?[ *;J$IOy+ëVmW2Z	OY@ 2  H TO]q exي{%IG٥2ecSi碿BUژ( @^  Y)$Pׄ+I$|枱VFPi%",?e 
 ( @2z2Mn~ l2.~$I}KwxXn]G!LWla  y $c '3. $IR:(=?ʽ{_@ʮm6f 
 ( @2z2?GOʍ>sZ$ITgQ/ϟ_=1P @ 1 ՓE?] *|J$./|sm[_&sKix:~1s3     P=?4oG?_ *=o$IRg2ܺoQ?=0P @ 1 ՓmOF?_ *7{%IT[UކC`lT}_ ?k e 
 lˎ~ Tn+I:+T/ϟ_S{hc  y $c '[|\ӿ.Y$I=?7Ѷe2fZ=/ e 
 l[JD?a *{﯆,IE2ܺoQ/0wTm   /P d@Tܳ3	PG+IZg22[;6Y^yim   /P d@T# L&^I$=:++uwT=Oic  y $c `ӟF?a j7Y$I̒]lr]wzm/DK:_L3     P='L%Ir2ܺoQ/:wژ( @^  )5oiD?c *7i7K$Mس22[;6so"`u~Em   /P d@TzY3rͷ~$IR:+]z{U\2GJ;ߟژ( @^  6g@t%I4t.+uRIBg0P @ 1 SwΫ1 -0o$Ija)5?ػhK2)(nmc8(!m1Wo&+v4jb&L2"T  2I1Lʌ(2g~~j8gݯZ￲:V5c=2Eh/ka  y $c i1 -P|Z͒$I_v{{KETD1hf@ 2  H TsQme &],<fIɩZ=x_C^s`ﹶf 
 ( @2QG~͒$IA-ܴty}^et?`4Z( @^  j.2 -07K$W.ܹw^TʠG`4]@ 2  H TsQ瀷DhY$imUG]TN-M@; [ÿۚ( @^  jNZY)*@T{*nIZ=x_C^sT! OkSwf[3     PU CO,I-ܴty}2XW{e): kewVhK3     PUv8NY$vٮt~o\ ؚնf 
 ( @2z_@6ϔ/[$M{ղJwJ}ө?O	 sڶf 
 ( @2]^q%3nI4U-٢t޾WPUFo(iH 0Omi  y $c y4 -0h%IRnR:NX_^??!; e 
 Gh}ׇ,IT]'~2O=D^f 
 ( @2gmGv%IR۪_~?SK3:Lo5P @ 1 \9mi ZO-I&Eo*;5GJiK.oi  y $c 9mJ? Ư-I&~1/H<~RFsjv~oi  y $c nt5 -fwK=^UzGＰLiHm   /P d@5.-c@KtWݒ$it޾Rtji/Lφ߀f 
 ( @2q\gݒ$iN[Y_C^sT> S߅f 
 ( @2 у-Iֻ>/?V*2EW Uߊf 
 ( @2F?~G%IT]?wʽPYtxwhk  y $c hxm Z$I?[%{O*O(EL Q瀷ߓf 
 ( @2z'eGovݒ$My6{W22Z}C)M}"@~g 
 ( @2S X+am~$ISǫKďJ}E{yP]ik  y $c yiF<%z(vI_cg1YEik  y $c 7 -1wKG< e4oO[3     PW)@K37]u8o	=m   /P d@5_u7 -=o$)wY`L;m   /P d@5oR~G\S$} я;m   /P d@54#@K>nIr?G; Ƥ@ 2  H T;{DhjW.IR} N3     PgcEj%ICO c2@ 2  H TYGhso$)o, cxw͹  y $c ns ڢjVK/ c2`@ 2  H T/Gh>~$I93\is  y $c wʧ? o$)gM@`Lz'yis  y $c GhxYy$%k&3t_oO3     P{6*M: -Jj>o Qߞ6g 
 ( @2G-gDh.IR:Zy`=^~{ڜ( @^  jbGi,8~I=?G7 ƨZeis  y $c q:-~I;ѧqN3     P_XJݏ"w_4OLi`LG~wڞ( @^  j\~xyK5b akN3     Pqe:{.~Ir4g1o='=P @ 1 ո}O? L_շ    IDAT} u_;m   /P d@5]^qeFw_~$I9SY`L~wڞ( @^  j5MTR$XU`L.
;m   /P d@5ΆJG!~I]%17ᷧ e 
 YԿ2/IR c;Cᷧ e 
 Yg߈6ͨT;|$f Qwߞg 
 ( @2k6.M= -'H0IRk}ѧ1@ 2  H T㮾= -S%IjoG2 ƨZ@ 2  H T? ͨ.Nۆ0IR;^{L%`\!P @ 1 ո= -;/o$^} уߝ e 
 MJ}$@?f$G1 Ƥ!P @ 1 UDό6T˷axR&0&{d 
 ( @2?Eh?~$I c4'C  y $c :=@7~$I{F/ ƨͿ=2     P? m3jK$5W} 	=d   /P d@U}۹ Zw⟇0IR{\`nɐ( @^  *? P}7LԞg ӥkoO@ 2  H TQu h4,Nۆ1IR;j7r0F3K=2     PxR' @Nt$M|-Ki4oO@ 2  H Tw^ ho0I9'1!d   /P d@eO 6jF$i}1pVɒ( @^  *~ Tg$i$\0Fë=Y2     PEV-yq)  B/	cɮs.X~{d 
 ( @2nte 6jR;&IܚnV Q
=Y2     PE7hg @KB$Mf-ge G??Y2     PE= ;&I:=L0fCɒ( @^  *jKKO[&I` HӔśߟ, e 
 &я~
 %wL4y.R`=2     PMBU{E? Zy2`[&I껾} 5ѷ'S  y $c Iw -=x[&IlTޣ	1~+'Q  y $c IZM)M h2I5ѧ	1,d   /P d@5)V hPY[&Iz_hi`z)P @ 1 դ4l @[&I>K YwߟL e 
 &~ Xo$i2ݽ*,0f?2     PMJ.E? ڬj6LܢJt 4goP@ 2  H TD?	 Ze:90fwߟl e 
 &ᕇF?	 Zlt%Lۚ R~^ɖ( @^  jO{&Ikxѧ1[}e 
 ( @2_$ hyK$)7E" Ƭ-P @ 1 դ<t[ ŚG*36gWm)M} މA2     PMZ+~ \3I}OO :5e   /P d@5iNH ~$Ioj@jV7([  y $c I~m# j67M4F?&0fߟ e 
 & -?3L4e/-eTG Ƭ1P @ 1 $6t@ˍ.IWF 88e   /P d@5}  ~$Iip.g 3?~2f 
 ( @2Ī[Ҍ -7K7M4F?< `OA3     PMj{~ \}&Iߪ Tgׄߡ e 
 &EE? &I|0~Yiʘ( @^  jRۿ~$I𚣢 F/e   /P d@5UK^\J=~" $wM4O-ب4( ;4P @ 1 $Wuq {4I}f 2`;5P @ 1 $78oi pEwM43@?~f 
 ( @2亇3 8,I98? sP@ 2  H TKt	 	4IjVԃ@jל@ 2  H T^}9$:f]$]Yi H3sʜ( @^  jg@+
k@oߡ e 
 &o~& $/ղ6IKD Vg 
 ( @2l<k `.O&IqI P~2g 
 ( @2jC뎋~* $1Z}CYQm$mXë>) [9P @ 1 U}ODG;I6z  %[ߣ e 
 P+
 7~$I_wF ~[=P @ 1 U[Z 0'tzmm$_+$ pb-ʞ( @^  -.? }o$i=ZT?># ꟻ(%   /P d@Ֆ@"MR-{i}$[ ܂{=P @ 1 U[mUhd H߆7IҺ0:{j=ʞ( @^  M$ Hef&MvUK_Rʠ}> ԟ)36I3     PyK ty_}$]o|2l lͿ}!P @ 1 U;Odokw6 mx!h2     PEX oqgKiF'`?~!P @ 1 U۪o>= ̚}$I;F &@IӐ( @^  mWl fTο'IznZG}-  d 
 ( @2j[^l Hhx7Nuy_ `4~%P @ 1 Uk- ͰW]qVrF `?!&MK  y $c 66@BV8IғvRFu `4- e 
 X?~: $-ղ9IO,< 0!#.MK  y $c 6V-ݲ| H$_[ii74 0	T˶MS( @^  շ| HyefwN;Cg	1z4M e 
 Z/D? 7wN2 ~4M e 
 ZK) Tefo$MsC/ 0A+?~)P @ 1 Uk[Qi7	Tu47}
  ݃MӔ( @^  >"	.z~i(E &Ũ.3KOӔ( @^  p ɟ
u48( 0AF]~-P @ 1 Uo=S  `>4姀JҘvڶA' 0AW~-P @ 1 U}I3 7>~$i$	?ߧi   /P d@^ Hy2NjJ}$	97j2     PAo~F $_Cihp| &M/dd 
 ( @2j}7)M@bR-2IR[hW> ft7j3     Pehx1O	.
wˣ@U{ߨi   /P d@	~J $/Nۆ<IXߕXW= wܟߩi   /P d@jJ .3IR`BUb@ 2  H TY09ݰW~9IR~Oi5~5P @ 1 Ug!90W~$)SKj`B;5 e 
 ף Ӡo{ޯ+D0u@ 2  H Tj#I0..36
{OJ`u}C@ 2  H T\'}O$*`5GMմf 
 ( @2T%I0%n/37}l\F^Uo9#^Mq  y $c TRU`JB퓤;/ps~9P @ 1 UO~V Lѯv~y퓤6U-ݲ48+	=7k3     Pe_G?+ Co$ef7k3     PeJih9OPg72Fs0F\~=P @ 1 UF] "/364-ظ4+\gݚ@ 2  H T\"i0egmI_ D[Ӟ( @^  *c݃~Z LXv(Iؚ5ߓ 𜚦T;<vM{  y $c -ظ48y0eC(IX}I_ @ 23  H TY^uX`
u(ITE5"U{. df 
 ~^ L;Kt;(IPb?us@ 23  H Tig ShpwP&  ɨ.ղp @ 1 U FMSG~zoc ZftϥKOd 
 ( @2\OD?1 TZ[(IU{4Gh+o   /P d@jſ+e4~f Lo$󣿂hc   /P d@ Ӫ!~%iB/ m4앙_~D  y $c |3`5^/	4:@շ~@ 2  H T)7{(I]ew Xo-ei  y $c ih$[6.-gDbo e 
 + S>R_~%i>ꟻ(kkE34P @ 1 49~j P;/,37	4uW):+oY~@ 2  H TSтK؏ EI~4_ \χ4=9P @ 1 մ4 ?%oOˋ-~Asi* 	t{c]ӓ2     PMKݣ0ffuvyEmnFex͗NHyw%I e 
 EPY/MQ֣FHbx!wMO   /P d@5M)E LEFIZz
 ޱmzj  y $c i{ TޒZU)e؋ zP/	ozj  y $c j= M7RjWfoM ov}g 
 ( @2 I,NۆHIz[D]L~ e 
 q~v ElQ. ξ e 
 _TJ&S:<NJޢgF=PwNϘ( @^  jo<);)I-ڬ7@Ruz@ 2  H TXk~z fNEJISނcH{1P @ 1 4V-ݲa7ӫ{;磻)mFexA߄ dVgn&3     PMkͧG?? xFMR5h@ o='3     PMk> Y5^]^~3%MI62`,g~.Y3     PMkղf LJ$aj< Dg>=k  y $c i' iKt))i7-k`J593     PMsS>`w]\fl~;%%kƯG0E e 
 j+e4~ VOkEOIIZEo=')=x   /P d@5?8+ZoYYf ~Jjwղf0 S}efwPϝ( @^  jg 7$PI]+뢿 BZ@ 2  H Tޚ~T O>u|kiqW S{{o.P @ 1 WN~ $PIR2Du0#ڢ@ 2  H Tz^ 륾R-yq-4WPJ3`{   /P d@留%[ҟ~ ^;/,җSIM    /P d@'^Bs6Zu=49U+)E=@)Z߲@ 2  H Tzޱ~ AF]W]^~S%9J_K 0ۨu   /P d@m>$`4[:1J
wJ_G oz_-P @ 1 ~/G?I `M=瘝V-ݲ;.+ lTj6wR( @^  J?{E?I ^*i<ueo xs=P @ 1 mV' F3*3g}4Ro xZ?~+ e 
 W,`N.޳,8J۪/+kg֌J+o=P @ 1 \wE?K s^fv|a47u<zOW <oL_  y $c *L7)?~ 0;/
Zݒ-Ji xN?;^ e 
 \ Ȩy9-VҺ9[F `Q3     Pu	 g-{+i-[Y韻Q k   /P d@o	 jp>ò+\
@+gwT( @^  JO_/D?O w]).ۅ]IOZu^qP)M5 n-җS  y $c *=}ծl0-~{%=,بNXi `?!j2  5    IDAT   P陫o;7xߗ_iZ2o `c~Wa e 
 NDݽt|MjK`^~< )4G̎/ڰ@ 2  H Tz檥/)ePE?S X;,ofoyg sfx7V( @^  J㢟) o9Tl~t-ب`=g s{Zmp  y $c *={ݣ(@ffu{,esK}w6 ̋f2p{   /P d@hᦳ _Y&.K-ﯗO o&P @ 1 * k:).36R[xu^ux):	Ws( @^  J]7G?U {*~+>K\g_-+*e4~ 0|,(kn2     Pi!hFexQ~-3uٷ'~0mwXs( @^  Jkך <Y3q?IS_K}O b4RKXs( @^  Jkך'9si{-)G?A U9   /P d@7, L΋J	|V-yq2' w6P @ 1 ־qd[)~篖;`t)3;0Nkn3     PiZTD?[ hfTןP:{&KkޏxgW gpZs( @^  J` ڥj_	V-ߺW~~ s[>P @ 1 ֭ξo~ Nͨ7Z:-KOMiUʠ~1 0Foߚ@ 2  H TZF^tމEuK}O ZͿ㚟@ 2  H TZMFZ+w(3;(k~{OѽWE? hѰTl~5? e 
 U_Vʠ| z[R_~| `7~5 e 
 ~=&@>ͨw^4gl~۔މ+MR? Fy_  y $c *_| p\vU+J}wfG jf/3~5 e 
 -ظ4`*kFo9_,{@zw@ 2  H TZ.~ 0]~쯈v~yWӶ5GG2`z4R?h~3     PivRFu3Ԍ+KEk\ynᦥf^߻_ 1[Έs=P @ 1 6ֳ1 OA{c4-ظt}Cܡ7^J&# R_Nмg 
 ( @2҆; Cᕇ	).ۅyAkю/*COkD <rWYI4 e 
 -ܴ4g<t[^qPR~Pvڶt~o\sＨa/c <9O  y $c *mxE?e `m5M2X0v~y%W-ݲt_>2zO ꁟ>E e 
 UQuN,t{Gm狶VK{7=f_1 ן/P @ 1 Ӣ3 0,MK?-}~,~A9&jWyz^qPﺸ4Gk IwDc   /P d@{{3 0Fu=xko9GW{U:{,<#sY|OL\go>Y  htMefF>2     PiZO
 W؏Kf}J[\z'}tMWJ%q^YEv{ĻKkVgm\K^}df4ǣW	 L5^{5P @ 1 9_~ @Y=ӴF^Y[ϙO(+-˾Tg^EGgZ9?s[D hAT_w.o  y $c *]?o\   1o3     Pin[S    2kQo e 
 4uW   `=b2     Pi[Q=pK    c[߳($P @ 1 ~    y2pcQL  y $c *}ղJT   `W~6W( @^  J𚣢7   :kj2  H   Pi~   =U( @^  JUO   `RSQl  y $c *_?   >E e 
 4-ܴ4   Jߊg 
 ( @2?   9~xyߣh22     Pi~VlSʰ   U?{MF  y $c *ë~    Ϩy2hCdd 
 ( @2~    ϨͿMN  y $c *;   S4GKl;d 
 ( @2x}   )/{MV  y $c *ۣ<   ORmߛh2     Pi|'   oM^  y $c *jJD?{   RAveߗh2     Pi/?0   U=&3P @ 1 [g_+i>   0͚Q'df 
 ( @2o9#   Slx	?   /P d@=Ow'Nwa+*6qRCڱ,q484$m+b3X-b Y`#H!	s~kOhy?9M   j/~W~D( @ dS   e轈P |9  ȌP)ş~   𽈚P |9  ȌP){j    jw"j|@    3@zW}:z    csG!j~@    3@ǩ.   #&fC ( @fJ=   19=F#  r 
 RlłR굢G   v8  r 
 R|=
   u~(|( @ d_q[R    PnUCP |9  ȌP$z    o ( @fJͨ    LF/  r 
 Rs*!z$    }F/  r 
 Rs    d|deCP |9  ȌPYUO=   O=F3  r 
 R\    ;n@    3@51#UO=   QUש   _@ 2 Tj^݋0z4    #{ѻv@    3@6G?z<    *S{at@    3@fֽ   0b   _@ 2 TjhLsG   `T۩XxpNC#P |9  ȌPu//#   e( ( @fJn^X    n=y2E@    3@f]1   4\O0O@    3@   @C[֦֜w&  r 
 R]ѣ   hE1|wr 
 /  q *@G6/>=.   6ܜZ3w*  r 
 h[yd    so,_@    3@mG   +e@    3@ѩwD   	2P9  ȗP 8 F9{z   ߲8~Ols 
 /  q *V>=6   @uw[*SB   _@ 2 Tfg   @#:  r 
 սѣ   P=Hj݄( @ d4MH;   0:K( ( @fJYF   `.Gh<r 
 /  q *nG   0^jmG@    3@ѭsG   0;6|( @ d4ڕk#   ՓOb޾;O@    3@Ѯ=)u(   ??hr 
 /  q *~WF   `7Č݃+  r 
 ʯTW   JuKw   _@ 2 Tʣ]ˢ	   0ox   _@ 2 TʣCR귣G
   08}3  r 
 R>wlH   @w_49  ȗP 8 TOn+   n5&3h|s 
 /  q *UOG   `WU/hs 
 /  q *e왩z   w ( @fJչG   R1u{( @ dg   :|,| 0  r 
 ROoJu=b   0s 
 /  q *G   US=\,    q *[q[Rt   
z+>Caߊ~  P ̴տ1   SkV>i  0$@ 2:W1TG   *O݁u_  C   3)o_(JnoQ   DSwOz 8  L!7{f67   Wx*>~g k  C   3Œ/%ߍ7   u|wwU7G  ( @f~8|(izY  ׿eq@zf~ @ ds/%MK	kE   [OjtqE?  ( @fW&|(i]?'z   
HT{ѡ/ !r 
 Ǆ/%McJǢG   mgW 9  L3×}  Ro]yWw_G?  ( @fk_*JGVF   e6| HF?  ( @fׄ/%MSߞRُA   gmpO !r 
 A/&_,JN@   zۆTC@ѪwF?  ( @Z_,Jyz   ,;<_fLiЉ~6  P ~(~()eA   Kÿg 9  Pw'=    ?`~i'^  C   C;/%^ΔA(  <Te}ig 9  P墤NE   EKR 9  Ѡ&`}R   FZeϦQl̔z' 9  T/%Yvx(  5iv~A  L  ^%^=   `$ziW<2	 0 dj%/l;/D$   )+RkbFw\  @ 2UQԒQ]#	   FFz6L+՝O	 i   cW~-~()=RnUH  йcn9緢  ( @ƺef>)   6oxiw߸0) 0M dlFIͩD%   h깇Sk>VmZ  &@ rVRk~GIYڼ&z2  @^owi7kmѯ	 i   sK(|(9unX  <2]zߙ~N  L#  wYQR}~h  (:&fKSQ}O
 i   wNj}}QRs*{c碧   Kł¿ե}?~R  L3  c?_>JjVKSh  Xe?T_  ( <xUQR   azosiʚw'7E?+  P qPRK4~	)Q?   0ʇWČosi^g @   c{×WߏO   0mOTV> @   cD<ʯH/Q   0=Aoqi*k֔*u ( ieUOR=t  ]piܺ$i ( <"|)u.w#
   |[5G74R    `jRRR3}A  mHű{KS]s   K×YT1zL  *{}¿TE0  9  7e?:4zJ  .mib  P 1[uJrRRsܵ,zL  liKu{K  P qPI/[1޺>zR  n6ޙZ
ΖQ    `LoY:}$U   Kֳ8¿aTwP/F?3  ( *8×[FO*   yU:^w4  h  cEJIYzQ   ;sҐj/~WJu  h  c}[{a)ѣ
   v`Y71#O|?  @ \iKIѣ
   ^Uiuj';ZVoY3 a :ERR]⡫G   %O~k74cLu @8   UR×[qG   Rg0saK  ]×]缏T
   ~L+Yf~f  4P  ~}LIͮөѣ
   ~dpײoeiHO r 
 T[7ּ}×ѯMզ
   RnUjoei, `@ 1՗/5%5CS귣   c~TwP74̺?  h8  ΥܔzW}:zT  0^tX4ڧ=~  h8  ;&f
  qSsG㿋!V}]/ 0 SoN
_vJjnqoL   c3P_  @ xY[/<%5ٿR5W   gKîwE?5  FP  ^Q_zJjvk=   \u5{f74:RUF?7  FP  ^YO3Ԋ,  IDAT&fˣ   {(X{;Sݛ~n    j:[1ToY=   LޜڧRw4̊!ՓOG?7  FP  vHԚ_2TR":
  \:sÿwaV,8 U>  Q@ aǾ&ܺ?=   A]ΕY1oTm% 0 S/I{/G%5]E*   F\ogÿo6wT>qcS `9  `\&$̎wE*   FTƅ߶0w*VS  @ %IыRI}/-zT  0b/J-}Fk  p 
 .SJzٺ"zL  0BʵoeYiXOD?5  2  2^ֿ1  6ݛJê8MxWS  3@ m/Lg/Q%59{e   ^Qu]*9VRS%U~j  d(  Sb4yeUpH[D)   noIEJêsomw    )S%{SRURj1  @Jê{ٟow    )Umy<I?Y=   hL݋0[UJsJ  @ rugkjE  @Nߨ0*9VE2  ƄP  R;iKWIjTN   PoO!ozrS `8  `H/_%5bڼ&z<  ݹߥҔ7gԻ~NJU  3@ j8_/b%5R}1z<  07=*MuEj 1  QRcĞKYIͨsR  4ܹ4&fJS=So) 1  iU%'5~A+bX  `}s\74U3UO  (  zE^y*iV_=   r55gOi
*.WR5~Z  P  IŒ/n%w̬T=ykH  `Uo~0)n3R⏧zg  ?(  2~pZj-8 ~+)CR=)z"  0EH7oJ[n  M  Fͩ{gK]I1u|Jn8  `7U>)N%NCWG?'  xE@ hهROXJQJu=   E5XKiWk/~g*~   F=;"|+i]  .6?WJRgRJ    4Z퇠~T,?   	OJ;ѯI>~B  K 0פ&4f=   'Rq[%}ꯤOu  (  #|6nZ'|XҐO5z   
-D{5SwRg  S(  S犿LG6|,ixqڼ&z   S[O5b?KWT  L9  |vFjirbŲ_Nu{s  _f~=R{ɻS/SO  (  -KR{eP):g} A'z   ?դfLJIl  i  |i]Tݪ{'R  0Sq/#j;fceNJc7kE?	    QK5O3#M=+~q-i]ߣG	  تmHY2lީϦiH3u/Ի3SSyMJ?  /  U|Կ٩~5o>-zz   VO.^Oߓ-kSTMnJUg[?m  H1H    IENDB`PNG

   IHDR   H   H   UG   	pHYs    {Rk  IDATxylTEEz%FLHT4@#cA Z˶ ,*(*%$"XGҔ}oLڤ۝yݝ7ofJH$lN$!	 O@i!g琉yJ0d'C-yk#_iSܿ L=[ߢm>d6{éxvȩB2,zs3RK&@3}!0qۀYHC8@NH{wx swDӧt@7(9w Y!b}cr=hC|-0è.Vk%wjFǆXmŋӒB7,u u\8\_Ғϑ7ik)[`\ b=Z<.)Sj(nw>Us<heoBwol}u<V8=ApNVs?_A0K? X5)k15aW?ci?.{@0* &_ q5֨=ZKPF	Hʘ{s?k
.~H"зϑi|#)^-#V:H+/WhH]>HX@J@F,CIH!_f9s-d@LG< PF)YI
OHF
d"	R R, >id@cYœ{ɀ;$!b	o۾H])uzS/  PF-%_H {RC
. W_0wܨ^v8Ag,HMCwǈsEd%+#-	'of<7Q5jYCQNv7\M_=`FwL|cȷ;%6[DQh+_&n	 e@ھ]' cנkiY1tؕH-|=H[v瞀d>N5&I.Vc	cdl~i:<ieWZĠG6Ic(HN쮒Ǳ`l\W)+RF[j@)_ EɛVsϦ@g]m!T!vֻc>Ӂ/ z9FS;$@7g!JbuGbǇl?xsGBR>HǦR{֍OLe!.A]:%{D:huo؏/WE1jz}c0|^=qۄV1C%Qh&:_!	I EH(B@$m    IENDB`PNG

   IHDR  
     XV   	pHYs    {Rk    IDATxieu}Tj#>5ơ3h;MMI$ffNg85PE1IQ@22((DyY
(Zcb; 묪so>/{O  0smLht>h{yV)-B;>  hFkfi;fbh{Etyycctu    StG=.zE 1]V>)F7)V  ë̒w=Iog#{el6d?  ` v*Z\w?KX{ctEٷ  D~ƶݓ םE  4-  0蟷g?ZS~vʾ   &u}&e;E_ctMُ=  hC[  P<|{/=0:)P\Ztfm  0M4=zeYo~ @# =o_o)κGyC  0J4}mqU跲  0m 6^S?=~-eY([eߒ   S?JV"F\( ch  E[z4u{CL  ߧJfM  C[  ٰu/O?ƥo9  j3G$~uTİX T  La?|:(ZG5;  (I|a  R 0=Q>&8pZǼ+bɾK  We/EI2ן4| ibh T~hma4u}wİ}  "z'n{$p;.~B 1 `?Z3KqwDٷ*   e41LifItOx_~J 3 `2{?wEV,i e߭   T(D)I?^{Ӣڈ0Q	   3xU}]!4>#[  )FMGctُJ  X  L#G54`Yz_㈲Ⱦc  rW~{$=j˟s1  $  L]_/?LƼ-  @}m$=VC_o~\ 1 ي"8k	Ҹgd  0{ggJcI  0	m hb9R!#[  	2h%}SEws#  v-  4hb	ߍl  &SlNIzk_}3	   _.Z˟~@,5iQٷ-   dxњY)IW{bS  ]m hA7Ca)~  `
.;T*Ysf"
U  4-  PQo?RG[  E?oE%i.uOx_Ġ 93 `u/O? 5fߺ   ,/TR_)	  sbh Xh#WjJϾ7b4Ⱦu  0E跧J\j(ܝ J  GknRS~?KU   WC^*IsjE3  g  wϏ֞O?RS1fߺ   r9朗4=G'  <&C[  /EkŮRCA;  `w#Z{>%U>?7e?: Q 0Vmd+ը_5  `}f*IsjFmُN  	  цK/Hsskl?}  0Ɔ8<UZEec  ~-  cah~FAԔ:k_{o]   ߦJ\k(Zd?: m H7zk\)~7dߺ   4EYDJ\A'	  m H	4VjJo]   f؍oN=}E  C[  :L}`+5G;  *Fgo%iΙ~t -  I"'NAԔ{>5;}  pC\IS3KbpͱُN  -  )H+5so[   &DqeZ]IK+{~t 0m Xt[ωֲh&44\m  "{%ixqMُN  -  ش!Zk~0+5ee߶   LW>WZwGE )dh _H?༕w-   ,{{%i/Y `
 hz_X)O[  )P!I9b{] )ch ~Q+5Qo[   DhG$ͥF{ُN  -  l/H?Pѿ(   `э8Z˟^,Is~l 0Em XpS(UjB1[  )5ƒ4~l 0%m XP΍̒Wik(^-  WȒ4:.b~l 0m X8x0Ukξc   Ew+K\_&  S J?hƾOцKoW   pt|i;$UQ<t[c 	gh }[ZsA4-)F7|!v  P<psW?#Y*G&   J?`ƽdߪ   F5f?KRU/~d 0m w~*{}
   |,ZKE `B 0h}I4>̾[  `Nz'0]Z\w| 	eh _6@U纟|GĨ}  Gsߩ%}qh ` 0zDkgJZWFy8N  ڊOOkp  L C[  M5Ҹ^(%6  6h,IǖǪ%~ ygh (z[YXb(,6  ϖipg  LC[  EX6$<)  Q{oKc9E ` hTi\W
   l-I;_~T 0Am ao~p*cS(  QuyV-IVwe?&    옢A?~p*[ݣ1eߡ   `W-I̒wcc 	ah ~M1eQvξ=  `N`{$=Z3*	 0 `t{O4NW}ʾ5  `q9zfĠ ` ݊DkLiN1ٷ&   ,r^{{$XO~D 0m nWJCoK   H1h,M7{g?    lRi\w%   Kҏl(l~< p  lw?$ƤooK   U{ě%\vP 3 `NRij([gߒ   0wF{u~{ 3 b~@*e^(;   35$]f[Sܗh m mxRv3KctoG   K3*]UGg? h0C[  jQ)oE   _^t}]$m{od? h0C[  jk3RfϾ7,oE   kCD{n^a? @C PE:"ޖ[   ax򒴭цK  4-  /'@Tʪ3g   )N/I~ P  9mRJ3Kc3oA   h~+:2^T=mOC   뷣RFξ  {֊]%Mq+v  4-  s6RB+,oA   hKWf?
 h C[  Pi?q	   	Kח4m @]  Y3~*-fUOo=   ewSxa;?~ @  MQDk~*-Z3Kbx)w   LˢlwISWd? h C[  xCPi1   &VJ4-Bh am _?o(ٷ   LbObx;O@   9韻" TZ<'ʭo9   xCD{ϧHF7 am ~ *-xven   05?4U.? @ 0'u/O? fj   0]2Ǽ3L@;CO>   j(Z+vI? މϾ   `*[7F{g1~ 0  T*ܝ~)-d/9V  5f?  hC[  *o(SZVƫo3   zS0@{  ch @Ǥ~JCo1   `_U?/I?+4,y  4-  ?މϾ   2h,M?34ٕ[~    T}#|Y(o/   $Mv7f?  hC[  *u?|Jڊ]xe   < :cO:   JcOi>\>   GqZ3Iss  4-  ڇMNޗ}K   s0c&Me?  hC[  *xq4?(o)   `.QtIp  4-  ZOi[s6\};   5O?W4Q?1 @ PfOiGg   lE+H<) @ PҎ=-n   hbI-  u PQnސ}   ;h5Ad4k  4-  Z˟~)mo}   `p&#C[  0 ZȾ}   Rs$5?C[  0 XWG:ٷ   0{qV%i3 C[  *j\+vo   `ϙ?{m  JjZKȾm   2Gפ?Hjn  ah @%C[5Qo(   X@=W; P-  K5gDyC-   ,WOYffh @  T2US^B   ,a/:*<BR2 C[  *ڪ	>ٷ
   Ȋ.ֲ%$5+C[  0 ƽϏ)V   Hلfeh @  T2X74F=/6   yg-  u PV\}    Ɇ7~F!9 P-  m5uzEĠ}    c{{*$5#C[  0 Ʋe;Gqٷ   0&S,$}  ah @%C[csfo   `./Bgh @  T2ոYڈQ?    M1ΡK?4 P-  m5V-b^}[    cњY!il3 C[  *j\W-   ~!i|3 C[  *j\     \}~!i<3 C[  *j,Zkߘ};    1Ic-  u PV}o   az :m dh:|h}+    Sn#Z{>%lCxeh @  T2Ujv➫o   !i2 C[  **˳o   Ɋatֿ6Cdh @  T2UVC^1g   @Ín0Z3K:$G  ah @%C[44F.;  	;$E  ah @%C[e?ٗ>   0A-wG{ϧyH :m dhŮsK#K   0J?-  u PV̒~Ae   La/:k_!)5C[  0 i}   ltr3 C[  *jj(;g_   ~A$eh @  T2b5   CDk.g!r2 C[  *j1K   ">~")'C[  0 ݢrw   L5>7\Dgh @  T2B7ٗ9   0|&\Dgh @  T2B=e}   Ө,{[G$-n  ah @%C[-X+v/q   `\e;埓HZm  JZξ   wI$-^  ah @%C[-Du//o   (;E{%'C[  0 mf_    ?0%'C[  0 /   Q(:*Dgh @  T2|^[[7f_    ?atig'>C[  0 m   `\u?I-  u PVUDK   1\(.C[  0 楙QyY   P?K` P-  m5Np   0'喻)&C[  0 vݣl?})   Y+~"ia2 C[  *jG~   9k~"i3 C[  *jGb}   6I-  u PV;/a   3DgW$o  ah @%C[mo}    !NI?c4 P-  m]|RȾ|   vXȷ䟵Hm  Jڞ̾t   EqњY~"i~2 C[  *ڪn&bξt   MM?s4? P-  mU7   )nV~"is~	 @  T2UG5,/[   yߤHm  Js3KK   `Ag0v(C[  0 Z?ʾ\   g0v,C[  0 'EyC
   #g1;C[  0 RȾT   b$m  ah @%C[U{(/U   1F{祟Hھm  Jjp   `Q8,LFeh @  T2YQ?2   X\Hٌ P-  mxo8%   H1I3 C[  *Ke}   (3I2 C[  *m$   HdH-  u PVV;4   et>Is :m dhhfi^}i   -gHs  ah @%C[x?}Y   oO?4m  J?!n;,   h%6攡-  u PV?\?Ͼ$   RwH :m dhb(ܕ}I   54Gfh @  T2տd_    cwoHzm  JV{ϧFٺ/r   kŽFkfIY :m dhm    IDAT]})   4BHzm  Jj=ޖK   ~#3 C[  *jp   QǼ+LGңgh @  T2ګewSe   (ŝ_K?ב P-  my+/A   F~Wv$d  ah @%C魽Qvξ   iI?-  u Pvz럻<   hoO? P-  mݢ<}   4sy$h  ah @%C?e_z    {[z$m  JW{ϧFٺ?   [J?3 C[  *N_}e   0Q:G)G3 C[  *NY+e   `n>#Gl  ah @%Cξ    &RoL?dh @=  T2۳/9   4?m  JSf_n    ,πi :m dh;%,{g_n    mx@Ҕgh @  T2Ǿ;R   |(:k_~$Ms  ah @%Chtٗ   T\>,Hm  J__ʾ    ǰ}m4 P-  m'gd_f    Sepފ3!iZ3 C[  *Nv_Qٗ   T)FkϧIӘ-  u Pv^yT% 0o? 8φi :m dh;#b; iTܺ1N՟GwꇣwDwF7EWG{G{gZY/Aaoo~5fN3usQ>roD1_ Pۣl3"i2 C[  *Nn$  ߊbtf=pފ=7f}:ZvJ.TݣY+-_["F}ui :m dh; =1['}?Qo-)0|xv({[) PsMi2 C[  *Nf  <EE_~K.ӈfFgKwbp|FG
 swi2 C[  *Nf~- 2ʇoDhY&ݣ{obO H6(4eh @  T2G= 2(.W32Gh-;ԶSw1yv $%Ҕdh @  T2F7}Y l?ψOhzZ=N˟#V+ 0Eן=Dm  JUgK"" PuclNPtֽ<v~ϋީM[ d((4 P-  m'e/) `|/a/MlŮ=]1(ܕ} lpdh @  T2V>9ٗ aˣs5${=ͳ!Uٺ? à!Mx  ah @%Ciۯ Tn0gZ|J
Y+vgKyRĠ} ;`pފ҄gh @  T2{; *e9u#Ԝګv[Ϟ f)[G4)I :m dh;m +~Ahj~_K>e w&9C[  0 d4K	 xqG̏D{gЄb- 0{ Mp  ah @%C~ ˣ_E{Wt91Ȉ~+6  GAm  Jͯ?f_F |g.':^@jmG;5 G1ӿ/H-  u Pж-)/# Ze^utt|Kf7~=Qn+v ~X1 M`  ah @%Cfɾ `*w=z~8ګ}@S˟/I|; ŶAm  Jn3/! eoK._M mw3Kw[
 ^y(Z+@m  Jͭ"Q% x;E{3?ykfݒ}TWҿH-  u Pж]} *zvt} 1s_Z?avS>ro] S7y :m dhfF &ϠGg?Ei18oEGB :O#4I P-  mYS)R93^{缔Y{gC"am	 SctI :m dh̆ן} D(5z~8Z+vM|Ʃ!fߢ 0_T1C[  0 mK{1e_: h÷}`lvi(7ߙ}\z`4) P-  mWWe UwCNT=sGٷ0 L5ګvܗ& C[  0 m* xњYY.5e 0_{i2 C[  *6'~1F)7o/J̒({[oo 8I-  u PжY84F([E~KXc/ѭ_;`t?kR3 C[  *6O@% mԏe뢽T퇣m;`bn:-3^jx  ah @%C{/ _e9/S03[_=;)  ~fKM :m dhۜ7} Xm4:j5n{ڟE$  78v P-  mQ{gF{ٗ `HfVK~u/k h{I;-  u Pɡ}3ٗ
 bE{?%=J+vG, X33]jh  ah @%CfOb ;.!NlTݶPy8 4+RS3 C[  *ڎ/k` L9g~$Z3K?%ͽ?;.~ @et|igm  Jٗ	 ~?%mgvkc P}?ǥfh @  T2nɾL  Euct{Og{oFۚh([Ek?åeh @  T2:c% )?%ou/1 kԴm  J/ X_[btُ hwO얚-  u PvY;/ X4o-)W9R2 C[  *ڎo#ޔ}y tG?{%-~~7b~
X\63[jR  ah @%CmpAٗ ,bY]Iyu>|{ُ# [ewSV>93[jJ  ah @%C1mfi[7f_ p2Oܕ^g틣xO& [S0ZjJ  ah @%C{۲/ X0ews[IU{;.~DXm4ZjJ  ah @%Clpaٗ ,b>韵ƴU 0:.Zj@  ah @%C1lNQ˾4 `.;(Z˟Y+iY:  ~5R2 C[  *ڎ_ݣߞ}Y wMԬgmDYf?  EΉ{EMl-  u Pv| M|韯YEE V1ocwꇣs{m  Jc̒(7oȾ, `^n0{?;UR1d? `ޔ[7g~$G9Z+vM&)C[  0 x `.?$ZvNl4Q? 5ԯF{?WI :m dh;^.\}I )F̕*iΈA') ?;.ewsϦ~JӘ-  u Pv*) tSI[ȷDےb}ߊ5f韕m  JSWd_ -wEgk?O%M~9 Ӥ,x^{l9bDI-  u Pv|ٗG}?IA!Pha0duNsL=2<Q؝)N]ISҴiI)RJ	7Mblmzpy>~9+7\}]W ,w9`ۏ- OՁ]i{cX~$?C[  J ehz5 @RH÷xJ^  w7{d4ڹ>~$-.C[  J eh:c! 4IkRowTRw^ʔC ١ϧM_[_zsk   dڮFWf v!iU4UǆS :w◥)O[?C[  J e :#_
 0o[_VU+~!4@Tu}ޘ;֥~$dh @	C[  mWAҤ  2{~ͭWSI V@=~<U_L9'|u;$idh @	C[  m碿 `^&9#nJߏ`ͦiv߾4mip\͑z3 -  YMn(  &7~3%i>M	"G4޽1<6~[$5+C[  J eh_ע o5$ͻ5iK?:zhILRgI   dv;lwK6>1U_hG( ޸Q-is}l=GI   d6F	 hrE۩OM{n(4-MoٖFipRooNdh @	C[  mc%  [)Iwك_Hh᯦Lk?㩷  P ,C۸~7 jS}өwʓo$-E-?C QH՗>&<%s~!^|  0  6{~)௘A$-ewDJ8#yI5MnI`I7&s]m (ah @m7|o8/7yNhFn]M]׼.z<)[J3 -  Yq%/
Mn<7`ըJՁ]i{cXo5Ԛm (ah @mL7o2H÷x}eonm*S`գRupOݒFW:|Vg$-S  0  6ߊ~z YFWbm귧E,jf-iԛ[+I+-  %m 2CO ǌ(I+]祺@G0ͪ4Ɵ/I3.am (ah @І'zh@~E]tJiG1@ȡTؕƻ7u៧2 -  Y+? fߞz>5.JRdq7G4ٻ%|u?7%	 P ,CەoM@ՃM~%)5i'XHizis}l=)NJR3 -  Y+F afU^{(INOgKٱϝJߟ%   d9+ܦS@?PVY-?@KG4޽1wK'IR3 -  Y+pˣyISjᎎOOoNw?oԵm (ah @6:O[(IɍE\M2=K]F;ק&IZ P ,Cە:'(.|qU'{?U>rxk|pɩwʓ?$I%C[  J ehm:	 Vc=JRCTV:+woLRg>I旡-  %m 2]_ tPup\&5z/E|+97LnI`ICgh @	C[  mWɧ tL=|4}^&6rM4wY]5[#IZm (ah @u J߅?Ijl<9BG9HCWk^NNMO|$-k  0  vt|J8$<?q/#}4Wi9"IZm (ah @4|OE?5 R?voo>!IR:WO=~3ٻ%vO'^HVG  0  ve_GO@Wu^/o$OwjfnM.J[ڹՙ-  %m 2]/}4$ߙΨ:6p_4vrmzJ$9 P ,ChnME?5 PM$/c5XZTu}ޘ;Gy$5;C[  J eh.xa3#IR޲-?{d4ڹ>tSlKڕ-  %m 2] `9ֆ=Iju>5RG>4lfץᶓ}B" P ,kgfU%7OCwN4c)^%I   d._~f Z_}$KMn8+BGSui{cXg|gKIo  0  vy'OӞ~$S4;' VƸ{`h4zRͭs(Iߐ-  %m 2]ކWBrJ.6c)ճ3 Kk6M-чC\p\7IJ2 -  Y3o&}S)EJՁ]i{cnym:>ϕ$I   d.oW? ҟ	u6f~9GSupϱXg<3ϐ$Iː-  %m 2]֤zHR>$IiRggjr7OnI`I~$3 P ,CkpF?/ -6Go$[M>wAYfU{4?/NOs!IRT  0  v;>~$ISG}ȡTؕƻ7uw$ieh @	C[  m/
e1`$/6|E_Z={35=Y_$m (ah @5s@Mpi$`$ݚ&{iԛ[u-IR2 -  Y'4F?/ mSMRsߓёkA̪4ƟߙFWF%	_Ò$!C[  J e:i&    IDATh<.ziB~$n`JՁ]i{cX*IR[3 -  YH K8IRǥٽD_ՃSuSJ3u)IR2 -  Y[.~Z ZM4`DMO+?h4zRͭ$ P ,Civ碟ny}$Ϳ-ѧVϾ5%i뿤E/%IZ P ,Rpp\J~"oO57N4o>r_	a#Ru`Wޘ;֥¿$IR>C[  J ehB`)$^}Bzt$UMģS$I   d.}j"cג֤ѧi4?aI$ P ,ÝogE&IZx$Y}N:~+Fk^NNSu!I/C[  J ehUw] D=z,O{Zm$-o>)Q9x4ܱ.OFK   d.}u
@KLn8+I_	?}VZ>|"M>9w$I   d.m;IhY>/Iտ}Y=7.H`ͭ	WI2 -  YK]? Du&IZ6f}^teiNHm7$I   d.m^ W5I6|OEU>r_JpǺ?o%I-  %m 2]o,IhCw&IZ.Ǐ4ٻ%vO'$IjW  0  vi5Ih~$IMߟt:a6M@ץE/$$i3 -  YKڔƽ'q~b]$-[Ͼ9N]_JvG~'.;I%IR2 -  YKW t&IZOՁ]i{cXD$IҪ   d.]_ pǿ
io}mzxI[h4zR??I)C[  J eht?	@GKOih?KN5ICO.J6 6K$i P ,C%m;pV=$\+~1ȡTؕ׽!z"Im (ah @u>b%cͭI؝ƷFKK_Og I P ,C%jnmJ~s`3IҊ7|?[RO>&{I+_>/$IJdh @	C[  m c|$)Ջ;"*O}5Km'o%I-  %m 2]_ 4Y]~$I1f#Ru`Wޘ_z IZ2 -  YKÿ 4Xo$)koD=|4Ugu3J$m (ah @4{~S`N-$?S UoHKr}$I-  %m 2]/_ 4U]Y~$I$IjC  0  vijSP{n
c$I$%C[  J ehfUSP(I$IԒm (ah @\g[_~$I$IjK  0  vgf~$I$IjS  0  v{}3PϾ)I$IԦm (ah @|E?# 5;&I$IR2 -  Y@M)wL$I6eh @	C[  m;.I$IԶm (ah @"p\J8h{$I$e P ,C?yO@C.|q$I$m P ,C5|OF?! T?ԛ[~$I$Ij[  0  vq>'_2I$Im (ah @|O@?7L$I6fh @	C[  mM.~B h𖗄0I$Iژ-  %m 2]\o~B Iǅ0I$Iژ-  %m 2]\wG?! Sy]$I$ P ,CEḔf'aƻ70I$IZ-  %m 2]x; h0I$Iښ-  %m 2]x_| 4M]o$I$Im   d.ѕ& hᯄ/I$Iڜ-  %m 2]xk  h/~I$Im (ah @| 4~$I$Ijs  0  v߰D? 3%I$IR3 -  Yov@O?1~I$Im (ah @«7 h{o$I$Im   d.)UA;_$I$<C[  J ehg<3 h-K$Igh @	C[  mE? 37$I$Im   d.᥯~: f_$I$=C[  J ehFa~$I$Ij{  0  va{C u%I$IR2 -  Yk7E? R~$I$IB  0  v߬{,vI$Iԅm (ah @ªA&<%vI$Iԅm (ah @AFxM$I$ P ,CۅU~: d~$I$IB  0  vͭMiVE? ?K$Idh @	C[  m~b$$6~$I$IB  0  ж?l 4졻o$I$I]   dږ7vr W?~$I$IJ  0  жl 4w.I$I-  %m 2-ot~6 dryK$Idh @	C[  m_G@??o$I$I]   dږw7|v]$I$u%C[  J eho~a{ ]$I$u%C[  J eh[^uU@.xa$I$+ P ,C}: h'.I$I-  %m 2-ov߾g)fUͭ]$I$u%C[  J eh[^ע-I$I-  %m 2->l 4;$I$I]   d66zl 4ޛo$I$I   dږ?;.vI$Iԥm (ah @mYsd 4W.I$I-  %m 2-kpዣ%I$IR2 -  YeϢ|%I$IR2 -  Ye/O@{C$I$K P ,C۲FW: h
]$I$u)C[  J eh[胯~2 dׄ.I$I-  %m 2-k߉~2 dt	]$I$u)C[  J eh[3 h
]$I$u)C[  J eh[ӧE? 2_.I$I-  %m 2-kwK _~$I$IR  0  ж𛴷# h[q$I$K P ,Co~'A[~ vI$Iԥm (ah @mYՁ]O@yN$I$K P ,C۲~2 3o$I$I]   dږUd 4H	K$I.eh @	C[  m˚{s Ӟ~$I$IR  0  ж7d 4Ho]$I$u)C[  J eh[/G? %I$IR2 -  YeՏd 4Ho㷅.I$I-  %m 2-}3 hކo$I$I]   dږU~2 $nI$IԵm (ah @mYG? M1$I$I]   d4& hj$I$IX  0  жO~. .I$I:-  %m 2-hE? MRo$I$I   dtʓͭ_$I$u(C[  J eh[ЩO~. 	K$Ieh @	C[  m_' h)O
_$I$u)C[  J eh;=- hަ$I$I]   dο9У$I$I]   dο'F? %I$IR2 -  Y39CK$I.eh @	C[  m_gG? ?YK$I.eh @	C[  m_~. /I$I-  %m 2s\ 4M ~I$Iԥm (ah @@.xa$I$K P ,C?G? 3x?_$I$u)C[  J eh; Pb_$I$u)C[  J eh;[\ 4ҟ	_$I$u)C[  J eh;Ps0w%I$IR2 -  Yo@ÌK$I.eh @	C[  m\ 4	_$I$u)C[  J eh;8 h~$I$IR  0  v.xas0^$I$K P ,C7a%I$IR2 -  Yo~. f3$I$I]   dο9ύ~. fr[$I$I]   dοYώ~. fzێ%I$IR2 -  Y@Tw\~$I$IR  0  vO{Zs0W?~$I$IR  0  жMG? 3;tk$I$C P ,Cۂ6>1 hك__$I$u(C[  J eh[ܚaǿ$I$IP  0  ж4F? M2.I$I-  %m 2-`
 J$I$\  0  zX0'/I$I-  %m 2-?d 4L_$I$u%C[  J eh[V7\%I$IRW2 -  YeՏd 4ҟ	_$I$u%C[  J eh[VW߆/I$I-  %m 2-k/I$I-  %m 2-kvx0O̅/I$I-  %m 2-kv߾'a&}s$I$+ P ,C۲fwq0}
_$I$u%C[  J eh[VO@T%I$IRW2 -  YeU~2 oC_$I$u%C[  J eh[Mۯ~2 f$I$I]   d~mO@$I$I]   dږ5웣g76I$Iԅm (ah @mYOd 4Po$I$I]   dږ5~2 h7L$I.dh @	C[  mw^7L$I.dh @	C[  m}G? 4z߯0I$I-  %m 2-k_~2 h~$I$IB  0  жd 43g0I$I-  %m 2-kΟ~2 hKo$I$I]   dږ5x?~2 57L$I.dh @	C[  mCO@~$I$IB  0  ж9ύ~2 ~&I$IR2 -  Ye7d 4Q5N5wL$Igh @	C[  m;IO@C7?=I$Im (ah @myD? 48o$I$Im   dږW~6 hΟa$I$=C[  J eh[^ؽ@7L$Igh @	C[  m˛l 4ׇ0I$Iڞ-  %m 2-:xC@[o$I$Im   dږWqU@a$I$=C[  J eho~a{@0I$Iڞ-  %m 2-ory@Տ~=I$Im (ah @myOgIͭc$I$9C[  J eh[5 h
c$I$9C[  J eh[}l 4c$I$9C[  J eh[𲟍~6 jx$I$Im   dږ7xۏD? 57$I$Im   dږ7x?~6 j71I$Iڜ-  %m 2-3~;&I$IR3 -  Yhq)u@՝c$I$8C[  J eh#O@;yG$I$ P ,CۅU?&&I$IR3 -  Ykv?#I$Im (ah @ª> hE?~$I$Ijk  0  v߬}oPw|$I$ P ,C~E? 5w$I$Im   d.gN~: jrywL$Ifh @	C[  m?~: jg$I$ P ,Cۅ5ڹ> hٽ1I$Iښ-  %m 2]X~: c$I$5C[  J eh( hNMǇ2I$Iژ-  %m 2]X3t 4`o$I$Im   d.ǥ4nE-$I$ P ,CۅWG? 5c$I$1C[  J ehfbPO1I$Im (ah @«> hm;$I$Im   d.]| 4Tφ1I$Iژ-  %m 2]xϋ~> ~;&I$IR3 -  Yo|룟t|-$I$m P ,Cۅ7G? 6[&I$IR2 -  YoxF? 6UL$Ieh @	C[  m-/~> l|2I$Iږ-  %m 2]x+ h-L$Ieh @	C[  mц'TϢ슿e$I$,C[  J ehO@Cc$I$-C[  J eh `A&ԛ[~$I$IjS  0  vqU_ 4Xg2I$Iڔ-  %m 2]7mo"	hᶓo$I$Im   d.ɍF?! 6ڹ>I$IԦm (ah @i    IDAT~$I$IjS  0  vqKO@M]~$I$IjS  0  vq.'~$I$IjS  0  vq'[&I$IR2 -  Ylq)ͦ@O{Z=$I$% P ,CW?zw3`^~$I$IjK  0  v 46I$IԖm (ah @ok[&I$IR[Z  J eh&7 4t߻o$I$Im   d. 4?e$I$%C[  J ehFW:h`-$I$- P ,C7e@7~$I$IjC  0  vyN3pH=$I$ P ,C%hq)ͦO	@L$Idh @	C[  m{|[&I$IR2 -  YK?~J lzo$I$Im ?yХe}j\@nC4ĉ5Ac2N2IXAr0$Vq[eSo/4*ȒF7Yd',vGQfdG֦޳<SMS}Ms~uU}ox׮!-  Icӣ?% 6zo$I$I%dh @C[  mSC?% Vu~~$I$I*!C[  r dh;z})SpUog$I$5=C[  r dh;>)hα{3I$I-  9m H2Oc)h~$I$Ijz  0  v<O	@9(I$Im ah @{џvn-$I$  $C5z	@#I$Im ah @	@W3I$I-  9m H2_GDN }nL$I&gh @C[  mW/FN s$I$IM   $ڎ-( K~$I$Ijr  0  v|zw?:1I$Im ah @j%sp~$I$Ijr  0  vUџrGo$I$IM   $ڎIhցog$I$55C[  r dh;_rf':a=$I$  $CֿO
@uL=$I$  $C;GR $I$IM   $ڎ=?) 7{&I$IRS3  -  I};?) W=yw=$I$  $C1b纮
@UgIM$I$  $CW=HgG;I$Im ah @
@uOd=$I$  $C	"DV {&I$IR3  -  IџzN=$I$  $C=c
@Íi=$I$  $C^{gFzqūo$I$IM   $ڎ֪GV 
>wo$I$IM   $N)pg$I$5-C[  r dh;F 4\$I$IM   $N藹7 43$I$IM   $NK?- 7z{&I$IR2  -  I{'?- M7ԋwi$I$5)C[  r dh;O@G+I$IԤm ah @dj%P~$I$IjR  0  vrUF^ Ŋ{&I$IR2  -  Ikxߵџl<=I$IԤm ah @?/ 7z{&I$IR2  -  IwW?/ M7׋^~$I$IjJ  0  vruy(@
i$I$5%C[  r dh;G@yM$I$)  $C	uUEb &I$IRC2  -  IzO@o;7I$IԔm ah @dsU''g$I$5%C[  r dh;_[џo$I$IM   $N_ }{o$I$IM   $N=?1 &I$IR2  -  ImџFM$I$	  $C	C][џ&I$IR2  -  IoџZ3I$I-  9m H2/voџ5I$I4  $C׻|Yg 8I$I4  $C]@z]M$I$i3  -  I}Ļ?3 &I$IҬgh @C[  mz4 47M$I   $NѦ;?5 M[vi$I$r  0  v:o??SP귅4I$If9C[  r dh;(@䏆4I$If9C[  r dh;gU KWM$I$i3  -  IөfO@7i$I$r  0  v:V&SPc4I$If9C[  r dh; 4hX/9I$I4  $C5@7M$IY   $N?7 &I$IҬfh @C[  mW(@4I$If5C[  r dh;:'I {i$I$j  0  vz@zqaI]$I$i3  -  Iӭj=(@됷4I$If1C[  r dh;݆\(@䏆4I$If1C[  r dh;돌 wBM$I$i3  -  Iӭw `&I$I,fh @C[  m[[(艟4I$If1C[  r dh;Z6PjT}u]$I$i2  -  Iӯџ~$I$Im ah @yqg s?~$I$Im ah @_spg G4I$If-C[  r dh;g~*P}׆4I$If-C[  r dh;@S&I$I,eh @C[  mZs]WO@Z$I$Im ah @mLMwFz 
9c7M$IY   $4O@W,i$I$R  0  6Ez 
0&I$I,eh @C[  mcgџTi$I$R  0  6 wM$IY   $u=E~ 
9wM$I   $5z@z})I$I4+  $C_tJ ׆4I$If%C[  r dhWD~ 
0ztcM$I$iV2  -  IquO?? %;5I$If!C[  r dhW렷D~ 
>$I$I-  9m H2j= (@i$I$B  0  6WD? 
0o4I$If!C[  r dh[C  &I$I,dh @C[  mc' @	zq$I$I  $CG;	 Pa5I$I3  -  I-߱g @$I$I
   $7z' 9(I$I-  9m H2opw uiM$I$):C[  r dh_{ (@z"I$I-  9m H2s h&I$IRd  0  6ցo~ sG$I$I  $C٨z @z/i$I$Efh @C[  mg]D? 
0&I$IRd  0  v6_spS  {o$I$I  $C٨{>OBV!I$I-  9m H2GvS >~$I$I   $H^Q^s  K!I$I-  9m H2F (}$I$I   $N (h]7M$Im ah @ԻTUuwM$Im ah @9 &I$IRD  0  vvj/[`{.r]$I$)"C[  r dh;[6$ (So$I$I  $Cj'@F~$I$I   $VK$ (AUխ5I$I-  9m H2:'}(I Pqk$I$M;C[  r dh;[5I Pޅ_k$I$M;C[  r dh;{UO<Y Pko$I$I   $^ۿ, ([o$I$I   $^+~ խ}_~$I$If  0  v_ G]$I$i  $C٫ף ]&I$I43  -  I3jo~ `$I$IS   $fû~ `7M$Iifh @C[  mg %;5I$I-  9m H2ͺ2i P$I$I   $f4 (Dφ5I$I-  9m H2і@7$I$IR  0  vv=>y P#74I$I-  9m H2~ `4&I$I42  -  I[OG? 
9v&I$I42  -  I[wG? 
ѻ$I$I   $p^Qv 5I$I-  9m H2F~" `m7M$Iidh @C[  mg# %r&I$IҤ3  -  I]~" ?
k$I$M:C[  r dh;۵xW~$I$It  0  v[-F? 
0y]]$I$i  $Coxߵ6~$I$It  0  v_g@	nz}]$I$i  $Cٯ{>BtN@]$I$i  $Cٯ}nB.J]$I$i  $CC]uT (3$I$I   $6=WE? 
P&I$I$3  -  Iͨ!OB5I$I4m ah @m3@!:wM$IIeh @C[  mQзG? 
ѻ|i]$I$iR  $Cۆڛ vn]$I$iB  $C4eTO?~$I$IT  0  ж9@!Z9I$I4m ah @ms+ Pws]$I$i  $CZB/I$I4m ah @m~2 `x7M$IIdh @C[  mՖa l^\X~$I$Iw  0  жYZd (D~$I$Iw  0  жYuNXk$I$;C[  r dh۬ZZk$I$;C[  r dhۼ~6 `xu7M$Iqgh @C[  mF? Jo$I2  -  I6ͫg@!G;I$I4m ah @mg@!~&I$I4m ah @mjg@!?<.I$I4m ah @m3~` o
i$I$3C[  r dh̆t (hX}u]$I$i\  $Cfֻl! Pqk$I$+C[  r dh:'}( P_k$I$+C[  r dhZt ('5I$Iƕ-  9m H2mn{ ;I$I4m ah @msl<# P5I$IƑ-  9m H2mnK| (DgwM$Iqdh @C[  m[D? 
ѿby]$I$i  $Cu]UO I$I4m ah @mm+	PD$I$I  $Cf7y]ok$I$mo  0  ж.RS<I$I  $CfD?! 
ѿvu]$I$i{3  -  Iou=D?# 
0$I$Iۙ-  9m H2m~o~F X/.}y]$I$i{2  -  Io5B&I$Idh @C[  m_OG?# 
=o$I$Iۓ-  9m H2m~#;Pk$I$mO  0  жzOG?% 
0ztc]$I$i;2  -  Ie4@	QZK]$I$fh @C[  m˨O	Bt&I$IK   $ږQw^O	B.j]$I$fh @C[  m˨u[ vn]$I$fh @C[  m˩z@Go$I$I/5C[  r dh[N΋~N bߔ}$I$Iz)  $Cr] (Dw$I$I/%C[  r dh[N? (DwM$I-  9m H2-uUE?) 
0&I$IK   $ږ艟F?) J0ԋ^~$I$I   $ږƵO
B&I$IRn  0  жz|.IPyk$I$fh @C[  m˪f'@!?>)I$I-  9m H2-; ($I$I  $C=g@	n&I$IRN  0  ж~V s$I$I9  $C
B._~$I$I   $ږWݢ qA]$I$)'C[  r dh[`Kꪳ9iP3w%I$I  $C2@!_wM$Im   $ږYUOBtO;I$I  $C2@!~$I$Im ah @mzs65I$I5C[  r dh[n/~^ `دWl    IDAT*I$I-  $CrrVck$I$mK  0  жzC~$I$Iږm ah @mug5I$I%C[  r dh[nE]W'@
k$I$mK  0  жF (D~$I$IJeh @C[  mn x]$I$)-  9m H2-y~b ݡwM$IT  0  жGnև5I$IR  $C[ %;6I$I-  9m H2-G?3 
^&I$I2  -  I׿B.b]$I$ik  $C랶w35I$I-  9m H2-#Pꩇ$I$I[   $AKxS$I$Izm ah @|4@!
k$I$X  0  v>],P$I$I/-  9m H2:'}(Pׇ5I$I^,C[  r dh;]]WUsn|&I$Ieh @C[  mѦ; h=I$IB  $CipB.B]$I$2  -  ISE?7 
1ɩwM$I   $Oc (D$I$I/-  9m H2X׃n$I$Iz^  0  v=!P$I$I   $WGD?9 
ѿ&I$I3  -  IUOF?9 
oIk$I$=?C[  r dh;_}{~b&I$Is3  -  Isj= (D6I$I-  9m H2w^ (D5I$I-  9m H2W~v bxwM$Ifh @C[  m= ZOԋKo$I$Ifh @C[  m֪uUE?= 
>7o$I$Ifh @C[  mɟE?= 
=$I$Ifh @C[  mMD?= 
1qwM$Ig3  -  IYG?= 
1z&I$Iҳ  $CORTUZ&I$IҖm ah @휶| pm$I$ L  $o (DUwM$I-  $C@!\~$I$Iڒ-  9m H2ߺgEvM$I$C[  r dh; iM$I$C[  r dh;-,OB.|m$I$}  0  vuI[Cf]$I$   $w+~ z&I$I-  9m H2:k?(H됷6I$I|gh @C[  m*	Pi{6I$I|gh @C[  mU=yw3G5I$I|gh @C[  m5y]38I$I;C[  r dhޅ_~ խ	m$I   $ڪstNPm$I$o  0  Vwa?)PU+o$I$in3  -  I" su]$I$o  0  V[o8:)PA^\cm$I$g  0  V[@A&I$Im ah @>l@Az&I$Im ah @ia"9P6I$I\fh @C[  mlû.~ j?#I$I/C[  r dhg_29Pm$I   $:'49P5I$I/C[  r dhgkks Om$I   $U~ bMk$I   $~rj -I$I+C[  r dhֻOtODm$I$W  0  VϭsO7~$I$I-  9m H2z؏~ bMM$I4W  $C[=C7D?K JQm$I   $7,(HgM$I4?  $C[=~ &I$Im ah @_ݢ% {Mm$I$O  0  V_Kꪳ9iPA^\&I$Im ah @^]F?M 
6I$I|dh @C[  mBZ4(HM$I4  $C[P?4(g6I$I|dh @C[  mB5iP~^\&I$I*?C[  r dh|O 5m$I3  -  Iz?95yPgm$I$-  9m H2Ջջ I$I   $G Uҗ7I$IR  $C[hwa?P!I$I   $jk!Pޅ_m$I3  -  IZGG?Q 
2&I$I*;C[  r dh=/( ڛŅ$I$m ah @Vݢ( i[M$ITn  0  V[maI]u6G?S 
;M$ITl  0  Vw]L(uM$ITn  0  VW~ z&I$I*7C[  r dhT?L(Lз7I$IR  $C[jtt}$IYrsԽKZ9(SB  0  VR
@A?>)I$I[};ԃGnjV=zKm ah @뢟* 6~$I$i-,ۇf=/#zJO. C[  r dhmw* io$I$Tw~]v^]9z%dh @C[  m-u#P
o$IRjg~_ֻs'գG7礪9m ah @;\(Ȗ~$I$)җQwا_zMn?o  $C[mkn~ M$I_kozfT;-  9m H2նpts0oo$I{TYwzxyuz<Ǥzqū4=C[?݋_u}r8Z{FcisR{sz㴢Nzjk@MP $H@ 1=\~JdZ/	  Rz}4qazy}$IԎLiieʷmN(;ꞡ-  U PVZ礷E? 4UM$IRo,;4RG%oWm  R않G)~0I$I}ْCRwլ44ں!A'U7{  Tah @)C[Uitя, 9-M$IR}*uO_ꯟF[֦b$eϸ P-  mUF? 4L~$I$iHiieʷmN(Ru5 *m (eh*uG~+M$I4wYvh9<6.MRStO5 *m (eh*e_07I$I3_]5+K/KiEd,tOnꞡ-  U PVU+7a:KY}$I4}eN̨vTL<ǐ5}=C[  0 6muc@.D}$I4E-8 uWfᦕ)߶9cGmV0a3 
C[  Jڪj~lhɿ}$I$FsIeޚ`4ں!Q?[5 *m (ehuV;amib^7N$IK-9$uWJRdhޅ\m  RS] f`8I$Iϖ3~fT{TdEf{  Tah @)C[N7E? 4L_7I${Y#ᦕ)߶9cB+/:"yy  Tah @)C[NN~th}$IV4wQ4ظ4nHi؋#C<C[  0 vy~thb41g'I$5k`\4zuJ%
fꞡ-  U PVS礷E? 4P~$I:-<(uWf;OE.9{  Tah @)C[VsJEg{@/:"I$IuiR男?3ݴ26T_C?[5 *m (ehmtя/ 3M$I:M5ƥiuCJ^Wx#㟷gh @  26)zOn"I$Ol!jVꯟF[B-2ܢgh @  2f6?{ `uV;I$I3Y]qXꯛs Xx8k9WL=C[  0 vlk_ 'I$M[^:M>V|攊<k8cdp P-  m'O0{o$IT[sxl\F[74Ffls[m  Rړ~hQ?M,8 I$IU˖fyiem*:ODמ,=C[  0 EGD? 4P
q$IK-<0uWfᦕ~Ohbpݲ P-  m'uV;q$Iҳ7uzkO|攊<k35g P-  mG;7 Lo$IZ[vvj)_i!{  Tah @)C[i7E? 4M	q$Ij~ْCRwլ_?/MExaZnxөE3 
C[  JjOuv 0zga$IR+KupTlA^xͧ+u *m (eh=wGc hp)7N$I5n[sx޸<6	0&GO3 
C[  JjO3I$>eKIHKh놔说[>=C[  0 9{=Q;'IvWJhTdGu)3YX3 
C[  Jj*uI@'Iز~3/tT诩0=C[  0 e `$IjYsMeޚ`Ҕ?xSJEfŚgh @  2T]oe x41g;'Iih^w`I)ﺔ诠nxϚgh @  2T-zUJE8@J$IҞ]5+K-kS=Uk3 
C[  Jj#q'Ije^+Kupʔojc/u *m (ehjxя3 47o$I^βCSoiqi)|5jkpu3 
C[  Jj]&t$I)[rHꮚWF[74Ȣ1B[=C[  0 E@CuO{o$Ijc٢WKhTL<op~3 
C[  JjʚO*;i h򧥅9I]qXꯛV|攊" ?j-  U PVS+i ('IԨ:M5ƥiuCJ~>`rhψgh @  2T6G&*;'ITײ%Y~^}YJ,"W-̨{  Tah @)C[Me37zI$IC٢SwaɧhTLl*T0ϑgh @  2T-~]#@Co9#I$]xfTnvnZmw6 ZRm  R'~hbib^wN$)βCSoiqimݐҨ5b?oj-  U PVS3k _	s$I3U]5knte)'3ϟgh @  2T_E? 4T~$IlԿSiem*&E/Ϥgh @  2T;k jo9I=nR男iieʷmN(jc?j-  U PVS޼4D? 4Ѡ&['I'u>S?OM)oU_Ϯgh @  2t4zu@CuO_$Iz%Y~^mYO@_?ꞡ-  U PV`ñя6 5zI$I,[xP8,9*v<U	h1 P-  m5я6 ?|k$I-lRg١wpʔoۜRQD5w?j-  U PV2`ZEʎ['I}ծ9<6.MR-;?k-  U PVUo ?s$YYjVꯟF[֦=bGџu *m (ehjxn>7Iz-<(uWfb;jYYm  RxPEGH,uz|,7L)yW4??k-  U PHEUg;o {ꯇ:I4^eǿ))_Y *Ӻgh @  2մuSq jpQN$-9$uWJhTtz0%&wgl3 
C[  Jj:.os$ifWNM+S" fsG=C[  0 'F? 4UQIvѷN$Mqs{kO|攊<ɖ! P-  m5wя8 ;N$YqiqimݐҰ Tvԫ?랡-  U PVYvq lxN$UvWJhTdG ;{  Tah @)C[Mwŏ~h=M'I-<0uWfᦕ 01ggh @  2t7,W$7uzkO|攊<k@{ *m (eh's lp['IRʖz?):_	 >߄m nW    IDAT R'1~$IjjVꯟF[֦"{,4V&dh @  2մ7FG*-~]$eL/f_4TK*œ߂&dh @  2L4`~$I]^:_xG4o}_` Nm P-  m5=1Qu${ْCRwլ44ں!A'~xMhB  Tah @)C[D(QSHe^/K-kS=};ׅߐ&dh @  2JLG~7$Ie^+Kupʔo}M+M *m (eh~O@l$iڛo,;4RGg)2qyi@  Tah @)C[T[WE? 4XN.[rHꮚWF[74ȢO. hӄm  Rz~"q:'%Ie^/K-kS1hi`/{Ԅm  R:_tD$iZp@8,NM+SmsJE}J6yoT2 
C[  Jjƚw*OE? 4;I^%J#& cwޟߪ&dh @  2L6G&v{'Iҋw]`uᷪ	 P-  m5/pw$XcwDJ Xߪ&dh @  2L=_E? 43$I/VS	|UM *m (ehm)+&Msy$@i؋> ҷߪ&dh @  2L?xSc@u+I}"s1W *m (ehn\(I˖}"s_~-  U PV3]o{ .;N\_> |~-  U PV3]vG? @_y$d> DjJ  Tah @)C[ET<5f;I~;<0Ɗߪdh @  2UD|%F\~$Iziy`|;V5%C[  0 "?G? 4]>J?~$I/yQjJ  Tah @)C[E9ע} Z#7O`qѧ16[Քm  R
i>>pϋy$}ckUM *m (ehFw_t,ME͓$iѝ/# c߅ߪdh @  2UT Z{<I&vY`.XjJ  Tah @)C[E=}я? -07OɊ'> W~?V5%C[  0 R>~ hbb[wݓ$> #V5%C[  0 "
 S=I]sK) P-  mG `q7O&S RůWM *m (ehz_ѯ  -?qW͓$i> "Os	WM *m (ehȲ
 e~$I#ѧ1Vdߪ&eh @  2Utŏ~ he~$I駣O! c,[դm  Rnx 9IGB h[դm  R ~$Il  clNDߪ&eh @  2UtS _'Ijgߎ> Mߪ&eh @  2UxsMEG @_$Ig16[դm  RFw]* E~$I-ȗTW1_߫eh @  28Կ3ѯ -ѿ'IjWo> 9.^5)C[  0 ơ~ h	{v=> 6}-  U PVcT6(-yC$ޅ~ 7߫&eh @  2ո4[ѯ -_=IR{\80&~-  U PVѯ -1;$=o;;0Ɗᷪi P-  m5.uO{o @[yʖ~$I(-V5-C[  0 ƦHiԏ~% hޅ}VTLl>{ ]ߪeh @  285ѯ -1'Ij~S*rzjZ  Tah @)C[SG E>L׆>IR|17rQjZ  Tah @)C[Sݕ& Ez~"I]?>w ~-  U PVckUak@K2I[ c{߫eh @  2ո?pck@[yʎ'Ijn> |i  Tah @)C[[k~- hEG>IRsN`eK~-  U PV}$59{4D: Y>JsY *m (ehq+;;7 ̔	~$I+;F8 \ P-  m5 ̤~$Iͫ>q U3 
C[  Jj\, E&G$5ş>q іU3 
C[  Jj@@tr$5gF7 `I P-  m5e_RQD OԬGn>o E-^51C[  0 Ƶ-ѯ -?qw$5y4G7 \߬fh @  2ո6qy@tNy{$5EY&Ejb  Tah @)C[ks$ e|6IQoG 5-:8f51C[  0 Ƶ؟~= hb#ib7PT>k =^55C[  0 ƹb_ Z{o?IRuII`~-  U PVӢ_ ZfxOTGO cnxy P-  m5_ fl7PT߲} 5YM *m (ehq BoGo$P)_m  R~M hݗ?IR}\{B)mjj  Tah @)C[{ 6Ec>JD_2 jm  Rz~<5M$հԟ>c ĂVC3 
C[  Jjʷ~%Is} bb[jr  Tah @)C[}sJŎG_ ZsAIR9 ׇ߬&gh @  2U0(IWÛ} moV  RC B?Qw%IRǿ} UoV3 
C[  JuNW;(IGْC 5ڟ߭&gh @  2U]*~@@z;Cgxwjr  Tah @)C[եgF. Q>Lْ7AI7@MdG&n59C[  0 R?~] h/'(:O߬gh @  2U]>ѯ -?vgW-$oQNȣO 50w P-  mUD2 TAI=ѧ
m  RSÛ R[Nmp	ѧ
_m  RSs$)[xP-$g#ߍT D[M *m (eh:)Ek@K[(IcΟS e~-  U PVu+v{k@Km?>Q E>L]M *m (eh5ѯ -?ʘ]?vgjCn3  U PVu?~m h'BI5wTt>O hՂm  R[QNȣ_ Z=CIxY@6~ڐ-  U PVu,W][(IW} ~ڐ-  U PVul @MP4]} 	]m *m (eh:oG: \g;$)קT'	.~!C[  0 X)ѯ -6{(IwǢ 5Rt߮dh @  2U]{U@:);5P讋 52Ֆm  Rk>{(I)[t߲@%?~ڒ-  U PVuѯ -?qWWM$|qfz|,~%C[  0 j}R}2座(Ix ]-  Tah @)C[չ_~ hȗt	N"ea- *m (eh:__! ڮSķDI]5+ P3߯6eh @  2Uѯ uo$izff&+SjS  Tah @)C[սb=ѯ -7óEDITwD jfp֢m  R{WDF ~%I_G jw߰6eh @  2U`k x41w(IFf:K~ڔ-  U PVu/;5)y {EI-~]J0 P77 P-  mՄo~  "&J}j o߰eh @  2U\8U:(Io>3 oX2 
C[  Jڪ	uOWѯ 4ܴ2.JҷF jcm *m (ehFtSODN hBm$MiD_ jj/G߱eh @  2USuq ;=1.Jybb[yůe- *m (ehԿ	 v*;Rvԫo$ij`i=~ژ-  U PVM	 տ|Nm$MM>+ {߱6fh @  2U*a+ ;ibQguNxsJE}V e	em *m (eh&5qE+ (Iڳ>' X
em *m (eh&;_) xV41w(I헊m*{m  RjR٢Sʇѯ <w·$i}G 1C[  0 hѯ <+߶9M;>J}Ɔ='5C[  0 VDV 0>Jҿ> \O߳fh @  2U|ѯ <GwT[IY;}> ɿ}ښ-  U PVkީjstz$R,"> YQl7 P-  mĆ~ 969{HIRyWD j.tK=ks  Tah @)C[5޹~ ygn$tץ4D jn7 P-  mĲů^;C4}. h7 P-  mo~ yfHI-xe*ǢO ]qX]ks  Tah @)C[5_/ x契9{II_g&Gibw P-  mԺ';CwR?v@~ڞ-  U PVm>w0I}&< Û~ڞ-  U PCMns_1 xA?~'%Iϔ-<('O ;Oo[3 
C[  Jڪ|$T<P[)IԿ|NY A:'%=C[  0 \vϤ_3 xAK?~+%el2EXW}k{  Tah @)C[5ѯ =eG[)Im~^9 AF;? jm (eh׿3ѯ Ko$קt) A&C[  1 ^_~ ōs/KIjcÛN 4Lg;m  RjCS?~ EMO[)Im_M)E  dIq2 C[  Jڪo\K~7$]D0W7=-  U PVm{Fj nIsԆfE@qz&C[  0 Zw> g)IMo)߶9#wN;3 
C[  Jڪ-(uTx$e
_{ (Rvԫ *m (eh~ ʣo$5lkS=Q@nsq  Tah @)C[7Fn PnO~7%7}9S޸"'n-   PVm*߶9R/Դ_wZo >~m  RjSDr Kz|(nJRc:)tKG; 9Nfh @  2U~7_9 %lS 4X[fh @  2UO*Ǣ_; %'NIyoMi؍H9+ P-  mնVFv k<uTF?Xi@dh @  2U}_; eNsTz~<cȎSs3 
C[  JڪuEJ,]ֿo$լ	oNEGG8 W<5 P-  mFw|=]7βC$զ?hM_{z^  Tah @)C[@%PIC?hW8 P-  mƲůKȣ_? 7Tƽ)oOi4"eK	}z~  Tah @)C[ѯ T3RķPI"i@K6>`  Tah @)C[%~ ѽW9{QI71@\gh @  2U[ vKҿ4nuz_ 3zm  Rjs~, S;*IR_LEOg $~ P-  mW/~`OܕRI
ȟNCD,27@h  Tah @)C[ΊwG ۆ7.ӣ?hǄ@C[  *0 ZݜS v[o$ջ T
zm  Rj{Ûn+Sv$tSޞҰ1@ibP/-  U PVm{D GO4SeG:O@KV-Kgh @  2U뛿*;_E #TIF^@/{ *m    IDAT (eh+Ms_E cs?~S%iZWnZq@u>+7Q/-  U PV[W OhKwU \wŏ蛨 *m (eh+T2A'u=?ݝw-JTT 7Q P-  mg} {9{VIzJ^+ Y~U-  U PVz޹~` JTTL<
 ))[x`mTy  Tah @)C[陲E& Ez?~_%iOʎٔ?OT iov-C[  0 Fw~%`:wWIڝEJCDv-C[  0 z_W TS7V-<(
 YvhԮeh @  2~\vkRʇѯ% LlwVv=ߊ(7Fj3 
C[  JJmteѯ% L=WyYIzFw|## gpwR-  U PVzn?ZzfWl>is?*uW͊m  RsˎٔQ	 bpőV^pd{H xanXp@.gh @  2ޫ_M 6l3`8^R[  P-  m_7;S䩷{+IO;E*K7S2 
C[  JJ/;R* O>JZ܂ˢ?Tv?-  U PVz6F 0=}7WRʎ~Mv  %nz  Tah @)C[酛 x==wWR{ʎy}n sogh @  2^lR*W ]al+iFwE.|W離gh @  2^=ߊ~E`fo^IͭH ɿ}?{ P-  mw'_Q 9ƶҠ) ^~C{ P-  m/[ڔak
 3H/,!+/RQD@eڭm  RK7 fְg?K{wt]y:+!IXG (ʨ딈
"%0ðL3HYHȞ:,$!+$:dOȾ['N~u}1\^U}~|]bx Ih-!T۔-  u PVzzgY1wڇ?%5bte7 lGj3 C[  *J/^{s fN1'ٟŒUF=7 lNLնgh @  T2~nQeobIͨw" Kʹ P-  <Kﲏ* \uh,iB[k:$y1VmW  ah @%C[i+Z҈~+@mgGkn˒&o⑫( 7ݯ| Uۗ-  u PVں?8-@E{W.K'? ScЉ֊?c} P-  mko3 "nOlؒbpŁe}%~N笶;C[  0 -5sG &BKϒ^7+! X?Y :m dh+m}fY esta糤1xQdD} ?s P-  m=G &˨3?-iak j~2 C[  *J5ZS> 0qJiJ(; Xpݓߟ :m d!kp! &ˣOVK&F} XݍZk'C[  0 TQ> 01L-^>e+ fx`[  ah @%C[~œd] \^T絤u;F^} ua_  ah @%C[~?}t`o<1ZwKܖ-i/]1g_ 0vek}yy :m dh+կ}#"+6:)[?_+򹇳 H3ǚm  JҶ5z; aЉEߒ_u~ :z7C[  0 m 2hpik|yjn |!!l
3 C[  *J>P0N zqi&[sd̾
 `by :m dh+m{[N> H[?˥h('j{  ah @%C[i# gzkޕy.Ms/(&D*3Z-  u PVڎec 6hui meZm  J5a ߊKtvu޸6ej leޘ٭ :m dh+m_/J1Q<qstwiuJ2@#N.C[  0 > 0=r7r}Mg4m8/@x.C[  0 /lQSv6DxQtOz_/@#Z{g,C[  0 Ⴔ?S(8T*;z_wZCgڲ]~^M mxu-h  ah @%C[i~uAqV<ukNoܗY{FҥQgC 
~3]-  u PVz~08L(^tnguzGo\1d; ŭ :m dh+SKw[ `F^/lٮ;Q<qSԿ? P-  mkpG fKYs{o mO+egCU>uZm  J9G fVs	d	z=xy0'C[  0 4^}`EW\ ݓh}\ `NpK  ah @%C[i~ 2=*s[bn([볏 ̤\3Ɠ-  u PVګt6 F޸6:z	:Gr.[wf ykƗ-  u PV7}P#}&*MawQKx? ?+hl P-  mw6 b=d5GF? (%g5C[  0  -^7 #ߖ3Q{ˢ{ʟ5Q# Tfh @  T2K7 PSԭѿtit{K>{/ [oW<fh @  T2(# l?1/t+2zgYpZ8 hx?Wh P-  mktυG bã{t14W<'7W493 C[  *JWfq `ct?/sпHyCc#xbG g#OC9 P-  mlQnz< p=&zh?O[ct|{bxW|?6 D!J :m dh+-lVfs `g_YAoLYdk{ce1¹B ̖!ZwKD9 P-  mgS 01g?Nd~S!{GpTz* \yP*J :m dh+-|;> )?%;2-1__tR1f DeC~6geh @  T2> X{n?'c#6g%9M=?~ίGs  l}lm  JZC> @SQ#Fw3|1_;c=sۢk&Esukt׼+zg|$sCgFQn~"?a `N`@J :m dh+ş> 4XOύkbpŁѿsѿ;si	oQxy?vO޹9e/L<;,78[hG]SEb 0CS  ah @%xjc   4lE3 C[  *JkxG   `:hgh @  T2Wwfy   /8gh22 C[  *Jxc   0u:Ǽ3G-  u PVo&   Lk|49 P-  m^GĠ}   F :m dh+'d}   Pn|0ZKvJdh @  T2__>    Sߦh2 C[  *J9|?   4ZU{h2 C[  *J9H   hUh2 C[  *JI-9;    ,sx4q P-  m.ɾ    it9o;m  JR^}_1f_    oh23 C[  *Jo8!    ht4 P-  m:GR5    (3> :m dh+7z    MEk.9m  JR~>}    4B#-G-  u PVsg_    </Dgh @  T2&Wu    0.Mgh @  T2&=#+   `2[Uo8m  J4+   `".? F :m dh+MN~>,   2E{'F :m dh+MV.;    &clԜm  Jd=   (F9Mo6jN  ah @%C[iZ('nʾ    &kԨm  J;W   @oKQ2 C[  *Jҝ|    莯Өq P-  mɬf_    :z-  u PV+_ewc   btߥ3jf  ah @%C[ir?    H]53C[  0 4a7    у˨ P-  mnxk   `_o2jn  ah @%C[ise}U    Kcm  J7W   Xt5;C[  0 4uW   uA;-  u PVjFWe_    s P-  mf;O   3MG  ah @%C[!-1gξ2    _YFȷ翿h*2 C[  *Jͩw̾2    ݖad'C[  0 Ԡ   S9]45 P-  mf?/   y3MW  ah @%C[a-5;:    _1Ρ?ޢ :m dh+5}u    lǧh2 C[  *JlnQn~2    v^wM]  ah @%C[/t   W :m dh+5GZ}    Vv7F{W濯h*3 C[  *Jͭ粯   wMo  ah @%C[W<Άk   `?廥hz3 C[  *Jnpيk   `h{;C[  0 ګ)*   T<qS :m dh+5   Jߝ :m dh+5>9:   g0E-  u PVW|!:   xae#ߞ~ :m dh+MG}_eoS   Oo8!D-  u PV'J   ǆhwN  ah @%C[izj#Άk   f :m dh+MW.Z   S%m  JҔb(7?}    DO濕h2 C[  *JWɾZ   W<~CN :m dh+Ma^sg_/   *~H4 P-  mȾ^   5n  ah @%C[iJ[sޛ}    fЎfh @  T2ޙ;b   ӿo"m  Jd(-   fDh-{If:C[  0 4Nk   S$-D2 C[  *JSEQ<ruU   Lѽ翃H  dh @%C[i}OU   Lbߚ"m :m dh+F}    SjpAogh @  T2fΑQW   0eS^Gۇ P-  mixW   `7G3 C[  *JS   `J\ŋ< :m dh+VȾv   i0G簷uHw  ah @%C[ij#3W   pVsH/-  u PVM   4X=Z[B P-  ml.Q<sw   4ToHL  ah @%C[i6   hͧkH/-  u PV/e_A   @ݍ'5 :m dh+ncQ   E{Ts
  bh @]>%5k   h᫢x]g   J4SR^/LĨ}   FȷcH[KO  bh @֪=>%6   `u_H[˳  bh @־?))>1:   &Ph=BڊG>6  4-  Z]ç*:   &MYFw[Hu*;     TjOIВxW   0Af!լ<}t  hC[  *~gçɨ{o   Gj
VKv( @ Ps?~J}-   =R&  0  TOISE[W   hx7
i[ @ P)i_	   HRnz,ګL	}  hC[  *)iZ(7z   tO	i}/  cwE  IDATh @NK4yuO~   $inc @ Pi鏟&]g_Q   =#ixG	 1 Ry}㧤ɬs~5   A?Nk  ch ViPI`W   7M;D[	 1 `x{#ǢX5   ,r^Wu~Sq m *3>*irk
   X ݓ8Aziq m *H4-^e_U   <^{L4O<H @  l=J4uQ?   I]Z{4_Z m *鏠&wVe_W   |(9yk([O  dh Vk}u&eF
   NK> cޒ}  h(C[  Z?J_̾   m4zh-1Az~2h P  lOԌ7;   mP7G7-H*  -  [mM鏡Q{WFZ}m   5x=}  h(C[  ^1ʗ?JjF[9   9|5=AZ:5x `  =鏢ދ-   `+?:/d%HQOg1   Z(*9u~Sİ}u   /,=B5S @ PKcZ(aTRs_   x+J?WD 3 ῐ8*A-%n;   P<qS~ -P3?}  h8C[  j]QIͪ{oDE   ):n -d>j  4-  #qTR^{L   ޙM/"F @ Mڇ|#f^GϾ   ^{l[G )`h 6{E#=}   ̼≛|wi=. 0m &N$̆7}  *sϥH]7g7  -  ۬so?Jj^U򹇳0   I3?6 e7  -  lpRIͬ{#2  27i,-%# 0 `;ZgF6Kٷ   ̌[8# 1 `GSIͬQ>P5   ӯߊaoIU٧ )bh v36nQéf=#2*  ;co Ҹ{G )ch vSImx   L_N/ѽ>v  LC[  +O%5ʗE   NZҸvz   y>_?Jjn5  yTv6D7s  S y1GTInpW   LחY狿/r  m 7/jcb('*  _Ҙsa `J 0ow31UR~w~   mFŋҿK{oe=  -  so?Jjv+}  @#ʗx 3 `^X*-5o̾   QަҘ 3 `uOP㪤fA;:  f(Ҹk|Y>  L9C[  ]ؼlGVIͮȾ   Y=^hn 0 `A.Y*oju   mt﷢dҸ  0m XvxCcfQ>h   p_W]{Kvk   3 3WI]e}  ds/o2_' bh GWIon   &GYD?M.e9sCs  C[  T^*-9G}  D_RFKv᫲   3 7XIsV   7ŋҿK* 0m +O   =te\ʨ{oEc 2 `<zhwc7   Ʈ@}Mr)>򹇳!  3 =z}l^sf^G=}  ؔM9mɥ} a  Uʃf%5~?  l(F=ť>  8C[  Ʈ{'g%5wu   _~e} q  _#ޞH+-^;}  ^sto)Qes1  C[  rk%5=p   nt%Zswo)or   fy鏶]_t4   7wRF/≛!  C[  R~pzlܢ[Iͮ}  ([OE][Jiٮ1c  -  7}  s̿J-tS  -  w_?Jjv+v[3   60'Qk)%;fB  xA  Lt%5!{G{>F  ocRJO!  m E3>+Npm   /]}ZJiN1qm eh d)F=?Jjt}  V<GK)-5F} -  9=z%5;+o3   xQΟߣq1#  [ TƧ|%5Lm   /xh=4&G} ` 0z,Nܺkpd  $)':{4:9gA   7˱?'i_k   A~::}Yw51 @m  4𞋢𦓲1   跢_I,kh} ` 'ooH$Gɾ   e~tO8[{o:9 v1 Q39%5G1   fQ1i&4:)'}  ` b⿋X,Yua7  `eDwbim3_6e>    4Gk՞ƒȔe__   ̐J.,bx  敡-  V<htּ+YR\~@  _8;4ǿ;>v  0m he?&KjHwѝȾ   b+=g 42 `j%GeIͨj(3  `
=6Z!#   RZ{#ɯsFݘ}s  0E?85ZKvL+-d{/>n  0  LbC9Β&̍  `{F]WZ:WQ  -  Smxף}В&}]  p/ҿJݢ/ 0m ~A<8Z4_}[  P#WG{ҿJ2=D1 4  ̌l.tl^jIҝctﷲ*   xh5e-iT>b   S%Koۇo̾   h-!24_}M/]e   Ulzr7ܶV"[OF#W   xh+{4u^&b>Z  0qm yEos=&ڇlɨsGݘ}=  0'nlګ^s?ce)  h  Qo;':'76/![Rn/b4Ⱦ   0Fjt^S$7%b>N    e+u-)Y(+	  	Q<qsyUUVwM'E{> @ @ѓF%?K{Kf_C   Lb'ҿJ[Ӗ޹-_)  @ *>xE.hrIkxo    O}_Tz#~1Uo:9>2  0Um `5DDk^;螋   O}_TҊݣsF}  m `>e#}9goݼxwIV{ˣx  1*-xwRF/?/JtaD,7o-F  f-  ,~'ǮG?h/ij'|  1)77#kO:gkW(F xa9Xl    IENDB`PNG

   IHDR         6   	pHYs    {Rk    IDATxyu}K4[tt4u3Q$Ѩ9ٜNb&椪7@E
() 
`444<wͩ>OF     iD      `            2      @B      H       	       !      $d                  2      @B      H       	       !      $d                  2      @B      H       	       !      $d                  2      @B      H       	       !      $d                  2      @B      H       	       !      $d                  2      @B      H       	       !      $d                  2      @B      H       	       !      $d                  2      @B      H       	       !      $d                  2      @B      H       	       !      $d                  2      @B      H       	       !      $d                  2      @B      H       	       !      $d                  2      @B      H       	       !      $d                  2      @B      H       	       !      $d                  2      @B      H       	       !      $d                  2      @B      H       	       !      $d                  2      @B      H       	       !      $d                  2      @B      H       	       !      $d                  2      @B      H       	       !      $d                  2      @B      H       	       !      $d                  2      @B      H       	       !      $d                  2      @B      H       	       !      $d                  2      @B      H       	       !      $d                  2      @B      H       	       !      $d                  2      @B      H       	       !      $d                  2      @B      H       	       !      $d                  2      @B      H       	       !      $d                  2      @B      H       	       !      $d                  2      @B      H       	       !      $d                  2      @B      H       	       !      $d                  2      @B      H       	       !      $d                  2      @B      H       	       !      $d                  2      @B      H       	       !      $d                  2      @B      H       	       !      $d                  2      @B      H       	       !      $d                  2      @B      H       	       !      $d                  2      @B      H       	       !      $d                  2      @B      H       	       !      $d                  2      @B      H       	       !      $d                  2      @B      H       	       !      $d                  2      @B      H       	       !      $d                  2      @B      H       	       !      $d                  2      @B      H       	       !      $d                  2      @B      H       	       !      $d                  2      @B      H       	       !      $d JJ-c^__iHj+٭ї   #6wJsS;%%n=K76ڿRo=G`*n*O+_j_4+pK  1R=S2lֱ]:_ҿR?|Oĩe Fsz??F5~IE :e|   `?Tkv/-9}?uҹp4|TW(   KdpyZ2yTivEiҽxuyY. st.Z]j_dijJ鵢/S   @Dws·KK? 0w{?e&i+G_   _jV|*IOǷw.-ۢlN; ;w)7xIR  `kO*ժßS%I]QZǿ?~,Wn ='P|,  `pL)i﹥{e˃ 0xρN  XWT;?Jvfei2Ʋ\ w]]Z_7%i;]v@  }S[$Mg+J,{/٥ %Mfw(  +IPJ7 v)v/-ձї1   Sͽg%i1ک`U3 tҹhڪKG_   LŶnҹhU)Vb.N)/"Mkw)O  Va[IEYzIT n-Ͼ1/4ͭޥn<3r  `ՃΕ:|{f9 z;Kf@D_   dkg~'yWFպ=J[Ώh]W1^֬,gG_   $3l?TZG:WfFW7i3=@]fe_  }u%ifmzL PoTZ'5XJsVe  @rÇ(_,I3}-u2&~ pf?T)Ekv-[}Y  L4q#)a~zytȟo[R|?   ;W\,I3#nʉH Dߋ2[/  X7W;?KkRz2&n }]zq3o>7  `_{OzQ]f.,^OÒҴz2+ї6   ]qd$͌6/dbU_Qjᗣ/m   xE3̒43~yǗI1@RjҿK   ~pX:Y$͌5+K$ t? Rfw(zi  J7?CK̘ݡt{2 ~i?)S;"   LagKigiIC 0w%e\   -w{?OKR5ƺ]FMջt%  `껮*uO	ju/;h u]g|0-e{̒^   0J+ժ%Gw_O_du%  `\?&[q6=9 9duN)R]   0V]GzpnwX)Ydwj   @a?ß%cͽZ &qo)   Ko-Ͼ1[1K= 6^U{3LR8/]   5l>PZ<\1<K<<@uS{^7QTהag˸.[   ~T>;Y\1;K) :<)SO2l?K   &Q}wKfgrIXO 9¿iR<7>   &Z/?KR5VT}k:5'äD5~zfԗ*   L>j5{nl`pMZJ#kQ^   0}ui%if|{~4zm7IJsGv  4vᯊ^ս9 t_5C_Q]   pm%ifLٵn_PP1#%Fqi  @:/-]%S#s)d ugk|Q7ER  zW.I^n29fHY|ݥ#   Y
j\YY; FTo  ~iMTg~ +¿	RZۛu1  r3lzIToc7	5|ankQ2   ,W7^Oj5n?@R{j/M{ͽ^껯]   2|S-)m>@Էz2Ex  ѻtg}ICkv-- 0RͮinvE]   c?%if ZǼ>޷^   <ajP pn*MyP  mS?p܋~jĵO ͣ^EJ\RB   যks IF r<@@i/Cy   l?jĵO~._IZsCw,-   AiMgTlZ?W0iZ[[b޲    0l>P8l@fFWv h;_4ͮ(X{   `Q^fe$͌ջz ߏ)G^   XGHR5º ҟ149x   @HR5>^kqpR)qo.}
   fi}?HR5zל{/Bj6[   `o/O<+@>- A|a!MSͽV{   `T.3IRos iZc|8ޛ    #Խh6Af_,l h'/^zrI   Q֥7%HRZl`Vis   ~?SjzU	Ҵ>Kt   } ʴ7f5 {KA/.q   ƨ{G$ZD_@]W;hikR{߇    4%AE4m zWbov2ጥx   pm3$ifa.;`0J^UK   X"N?oj{6 N=%J\R   TgsIҚ]K鵞x *Mp^VK   X*NiT-O@缿Ҥ  @~̟DCHRu/yy_4Ư,    H	g4}y uRͮ$ֽxR    uN{_y$U{  ΍>K5    åu%$ڎM{ |_4i5   Jv	I~qDvR}M   `Bwx$l[31_u{8i?   27	o?jj8 )ITE    &̰4}Ny$UOֺ=G Na҄וD    &3,$چ[6>z \8I3pm'   	9gT=I_u()ep#   	6>\ZZ$<~+x K*o   /-ժ1$z#?j./J}K֡o    2$z:#?柆 ){a7   J׆iHRG~\5}+Iai   lKvIytC^ϪFo/H}C,    ӫC6$ϩF{ſ )    ,pXǽ9Ck2c9_   `[6>?됤_5iNiI   o8=Cf?b   l%LNlj4|M	o   ۛ?r8CF?̓5HKQsauo    熟HR57 l8gRy/F{;<   `\:y9e`giu/h   XJ營HZ9jS_4ZGF)n   X&?|ϣFfeUsSJ}}   `|"˶-_YԨfWi\>~   ,CsF$5 0/FG/{=   nJƲ ԵyIvD  ewHj, K;   @V'My2 (mo}o   xDړK$5U uoR    >&&nR?pK   n*}~", JWF   WǇHj, JU?   <3sI ~-o   '5rgiI `9n   mާT$ }   >úsI 4{Y)f-   `՛֗jN+)3 h]Q_}   X>ERɘ@S]G   ,NYJ9F Z{    IDATѷh   E|^YF VTWFߛ   F};\$L 4.Y}O   M]$5d :եzd   }I4 4]YY{   G=(##FRɐ@SUo    cUuUV~#1 45u+8   @vs:,FRc3 h:ZKa   `I;[K=d$i w.   _ZTg :U\   %>f$56&U;z    !o/պ=h$i {Ǣ    z+FRc*3 hbkRz{,   @~}iYe d6n4
   07~%FR Ⱥ|8
   0Q'=FRc2 hj2l   L[Jfeٍd 5S   =#g7S@U   LOMh3I gauo}   `p|9Td _B   `}r$5&>&g8   w]]g:@ݽ?Q}   `tsIe3 (޷_   Lߥg;@xu)u?~	   0z~#1 תJi}}   `z:<$f PXݯ]-   `~|q9Df PH[퇢    )tI ?<%   pmZkDe В>-D   t$GRc2 hi[K}?   Hg\xV2) u/^}/   HC$5&&A/*׌   5֡/?Ԙ ZΎ   ׿s I %};}    FׇIjg [{>   Qqyfw?T"3 h.   ts!I k_   >RY~>$@cm    {߄Ije jR   5l=X<3HR#$ӪK}58   ewفgEJD Y   0g-C^~^$ 4R6   מ~f$ 4z2   61~n$ 4ZzE)^-   3#I% 6{    ??X Y}   	w_[HK@ivE7    |]gIRd H{    ۠R)<IRc V}   `uN2 Zt1   vnTkV+Ij5UsgagK=   =/ϖ$5ƚ@OG߫    XMZ{2 h{Y)^
   ^3&Ie ЂpF=
   E,ͽ~$1 ZP3   .Y~$1 ZP\}o   `݇Ks焟7Ij<}_   `z~$1 ;}O   `<`s'If v>ѷ#    ƠwőgO# movE&^   8zuKϠ$Qe 69ѷ!    ƨgP# mkΥُA    S=(^%"Y    ?8>,JRc$ ٵ}   `/?T@OZ    W}&LJRc ]    ҠW8lJRYL =a&v   @GMIj,*7Fk    0A/?T@[Gf    Ϩ$5@ݚe{ ?<ڲ<.TEcsl$c؉ƶc:Ai;vDFPŤ2 3HA	@1XXEAQg!s}|իW:}}O$IX^VY"I$I
Խp* {J, y󟕊n-$I$IB<_f'>cE$I$I{3+ {, pkL$I$IR4RgW@z2, x'$I$I`?'뮍%$I$I`E3, m. >$I$I*\gX@, x3D$I$IhmL~dց$I$I:g}=,6 C!I$I	hK[g  5~kJE=;$I$I4!O\=! R꣣g$I$I&b-1Z@, j.)z3C$I$IVm ޥF
I$I$M`m |KS6g$I$I&ց?_:gDIT<6.~|q|f]sOZz=R%?r~xu泆7ݸߒ$I7~d@]-xv*;zFH$Ӡa/IOJKCOaZ)u)ᅩ13'+UR?Mc?:}9u8.?(_>\}џ$IW[ϺX, j}$I]ژkWGyRϦLͥHN3[_)/ÿ2˂ٿ(]vH$UޕdPS$Ih?86wѩ{}ߦ~oQSVj>c{)ÿ~$I
M.Oϲ /g$I
z/VOu|ߑ&]KR:o*A?mIT}#}~@ދ+I4Կ}E}x=wGƢOs]H$N#;8H?fxCJ z$H)tg_{|:)_w~Ƃ_9{ntz*ڛH)sw, j=g$I4fw:廼&=`3߳0]#J$=݊A;ɷTt$iRSvi'}6o89nN$M`4@ I&~wx?{w|8撝[ַ,u/YF$I2@eP3s`3@$Ub-j>c)/T+|}?UITG}$H, jb$IU/O>^X:éë$I~
g,_R_$U..; Xw&[SOgTyK
\*@fPMiЏ~K},I>VF&WΊƽ%IR]}t	Y A;F?%IҘ+}x_>Br=J($IRT^wyu	\`-xO%IWl\_KsR}S!ItkE?%I+ցuΩ'$Icק­EQc Sg$I*A?o8%ɻO$IҘjw 0, XsF?%IRx%πef:l4?V$iwR8 Sw~xItwR?L!&IFX?FMY LE	,I&ٻ;g~-_^cI5FIԿwhԔ[U$M^;/Kc?>Z?2GQ$Y1HnπFY L+$isRoղ-P	}*DtJ^k;̭)R*$Iz]{wzET-SϤ{\%IӬh=EĿ_z BD?%ITl%uNBj,|N{L|Sw|%IӨШi3T4E?%Ic4^o Rs%ISlp13'5b0eG}4Y.I~=W?žö $MhC>. 2O~Kh:~	F y/t-$IU{4j`仼:A?9.IR
7:hԿ{IEjwhԄ=$)Djl^ 23'Ol*ڛ$i3^W̭i13'Q[ZVlsxؘw|צ-gG?$I4Ϸ{~4j`J4W[S%ûȣk?$Ix s^4-IR}*ԻoG  7$IW/@, -SѼ?-IR->o3iD?:$Ic4{E̝n S}_E?%I=~rx=']WF?F$IԻhL9)п$I[+w%e0l5YK$Un3;(=N/	ǵ$IS=~=|lz "Ii7 S`uNBsZhnH?R.N5F?j$I{n;: npӒ$MU/{f^$bؑ$xO̝N |$ij*6ܚZ| |:Ch?$>* S`uΞ~>K4E?=/|11.i$IR}wReИB lnuYtWjmL.םX$uhL!	ף˒$MtkI/@I32 I4ފ0wX L˒$MdE~xw,}S4W$ծ! )c0o~&K4qo>+;"|xGcKZտw hL	mcI&A/uΙO'%W+`$էA/;2 S`u8q,ID%w70?!I4:gτhL	4g$IQ|/{fZH$^טsi$Iq_I93sWI:N	]K3XPswl`:OQ$^+XṁƔ 0KǮ)_yLa($IhOuSRg?ҷgyhL	緣͒$UުScIE{SOtg_|x2=E5`0A.~VKTs澿OAI*쒼]{jɔ  ~~KTƽ3
|}Pz4=S15fh  o!q.IRqQ9[s_OŃk$]yhgV~!	9ߣ$USK3I)C6, &DE|I*Q|/PIME?&%IzJY{u_|WV {, &@)9 IRxO|XHߠViM1EY LGIb+?d+$IJsw1퇹c07='$IN?>ߤ,뢟	sS_>,@=/~'zvHRyh-h[~J`rN~qjdbPq>=K$I
? OGsNEG$i퟽ʧ FIojÿh$i+4XC9勩Ƃg4 8 U63ǗIjW=k30@Zo&$=VŦRs:l۔dSN$ig0()IwE{Sz^^SjW)3
Ȧ@u]=$I[Ec]j0J$E?jkWE)IRѸ750D?v%I#j*U>g|%;5n>wz |y$|/P/3sRc7{4~ }4jE1Iris c7YяaIfVtJW|Ozm$^;z_/&2i,Iz{".oë*̝L U4hmw$A?XT<6,I{g99Q
j.'I*oRE[hΔ觳$բ.o8%uΙZ9 !
ꞻ zJ4:gτZiA#ZN#o_+wOc?{iE|Y T#RԻ9PURISlOuSCS/ֲw-ß ` oK/$izx<3sRE?%i"ro?@Y, *u䇣g$I7皔o9PyJ5E?%RԿɭoYw|I`d ޥFUIJKo0)%F?%)~7̽ saP1o$WZq|4?^;).I㿷ß )bP!n=z%I*I яqIݽm;g-@cY T!$IRg+]qp\5Ns>|ؿeTFY THow$I41
0lkWE?%so?@*ƺ-Inv;*~L|פqo]ν iX TDs7GpI~~j
0mfXIw5:[j/&@, *sg$IOsg*3/1/i+RSR|ß} dO@E9&zKv~j{FLZ3[gE?%MӽW"Y@*@U/ISnn|WT)/T<twc_Vlg*@6r IDWu)@]@J /L뗧9SmSË] d!, *$=+ uӽ`I_RE*Zgۧ~%@V IҤ6Xu,yL5FIn{+M?~  IҤ6~ 5TEOI#g@) 7'$IzJyQJxpm_{|:}) g}?DcHԘe K+dE{S߾"uW~2廽>Y@6, 88C'נK>CxXh4 ~ Ʊ 6Gѯ"$=+v	 <ZI ڲ "DͮxoFP ~^%cB]ŦRs:lG? S, wITa=??+^=*<{WDgbI6GN _s7kEiw`Խd>S M*ͅѯ4$m^Fw~UuNrԐ&H7ScV? (@9sg' gfԿ!U@|{Hu`73=    IDAT<$mVo[p S6G{@$If:s'sEiyy]ojwb4=#g , V7H'3qWl3_:g|eWωbظ&]Iǯ(Rs	 <u=~wi:_/ hL  /*$U <}=R'W	Y :ϣ_$Izz	@	=3,zHݠw]zO.5z{`ny, t]%Iֽxy	@y{R?{wo? -Ӣ߹$IZ)Uru/5z¨f_se? Ш Ec]{$IE bícFZ;jʽ Uާ,IRe)_y	hTʽw0.Vj[5 ~x$I0wLcǍ&Ew d`̺+v~w$So V+S~0zꨢu]Zy4, =e o9;}NǬs豣*~ H`fB*$ c2iѣq6=WeI}~۽ 0wY Qk_$Iz_>'wTGqoaۦ|  ~$1QsZ=TBп}W/[ @V	 c9g^{$I?`1E`^Q'{oթj X Q_%I'C N/D"=Nņ[RCS/ֲwƂg a0Fņ[%IzTEc]j,:|Fhf_\{_ H`L힟RQDOJ:g k.~o  Ա ~)Iң6Sg$ 0{͌FTw uW 8X }$UG c7g+]Obϧ澿/ Ւ.; 5TGw# 9i*q]{\:׿F  c2瞒$U]WF *hipcM?O|_ `/f03sR*I#t|G<zLUA/֭~7BϤoJ- h<	 cWWIhnH[G *jfN꯹0{wNBj_Co 0 ֡=uVG`@5yP|Z+6ݕ/Osaۦ|   ~+I#DF w4?ʧ/ @c, Ơw２$su\`2;2N#MT H?`k/~$iX>sVi_*tNbj{ @B, FmfON%I
IF &FhT<tw/	|  g0b~O$iX" s?빩{>R˫?  a>eIQ	 LJo݀wR}ܧRs7 `n9, F݋$IY~05n>L?^LtWZn	 `X XJ{Q$ֻwIϟ@|O]4  i, Fzq$Izrdkǝ5EԿ}E=dj    ?o$)"_?9z&07p`Ի9K_c   |6)E쩏$V>Me~ `K}#I   `n=Y P}#Iy17l>  l, FssIR]sL<    #ԻsIRko!    U>:7|C    a0BEsCя$o=/|   YɷA$uZ<   0 #\sIRk.}G<   0 #>#>W   X H>$ոGB    e0"KFHj\   @`$I廾6|   Y(1GTӊA    g0
3[kEHjZoB    E |WEHj\φB    g0oIRk   Y @ODHjZ0.z   Y8IRMpr   J {EHjZ笯A    Q|ן}#Ii>  , F`p?9   d`0E>GTÊn   @V e[UJE}$IaA    U@ɚ?  O (YEHjZA    ?/~Y   ʰ (Y̯FHjXX>  R, J]{$o;?|   YX wg@ֽdi   J (g@93   *d7FIjX@    π$I5,3   *L}#Ia̜9   * (Qπ$I5l   dcPֲwGIjX@    H$u/X>  r, J>sg@6;g    U@:̋>$հ!   @V9 %#HTÚ1|   YX wՑg@U`   dcPy@U<6|   Y%Y hp@5ce   J (Qs IR>6|   Y%Y (u@սx   ddP|6g@9{n   J (Iπ$I5}߇@    $4#HTZm>  , J:g@6   @VI %i3 IRwzE   J (I>$խH
   @VI %@U   @VY %鞷]9$fn   @VY %^W9$f<|   YeY âρ$I5   *򆓣ρ$I5   dePys IR]   deP=DIjVw   *$5@9   *$E~_9$fu>|   YeY $;@>   *>$հQ   @*;(HTZ   deP|DIjX@    ,4|S$5   deP~>$հ^o	   @VY %h3 IRk~?@    ,P$;"|   YeY >$հ|@    ,t$5l>  , JYg@֘   dePi_>$հ̜   dePΙ_>$խ   @Vi %螻 HT   dfPK$Iu   @Vi %^c IR   *K>$լ)|   YY w@U47?    4>*HT|}   J (Aρ$I5h   @Vi e|ן}$IY    h<2>O>$,    4@gFIjV~0|   YY !zn9$nu   *$Iu
   @Vi %ܱ2HT   dfPK$Iu(   U@	w]}$Ia93   *{>$հƼg@    ,.HT
   @VY %{}$勶	   @VY %!HT_>  , J0Xc$;*|   YeY @Qo   @VY % $E-3   *~}$Ia>  , J` Iu@    ,)HTZ| |   YeY @Q눿   @VY % $E_@    , IRD?>  , J03 IR,   dePWEIjX   @VY %yY$u]>  , J0g@ֽ3   *g@ֻ   dePƇxg@[   dePƇxg@6;g    U@DIj3   *π$I5lnu   ʲ (Acπ$I5xG   ʲ (A#π$I5hm   @VY %]yh$Ԙ"|   Y%Y wG@o9   ddP%K$I5-Us   *}#Iiͽ+|   Y%Y {n?:s   *DHjZA    $t.GT'C   J (A?9s   *}#Ii;A    $tNIRM]~`   J (Ag$I5	s   *6GT_>  , J>?6Xwm   J (A?>$մ⡻    U@	ZIR]wScfN,   ʱ (AsEHj\g!   U@	1GT^>  r, JIRkY   dcP|DHj\눿   @V9 eIRkY    (I굣$I5s9   dcPy$u/Y>  r, JRl\}#Iik   @V9 %{]$\>  r, J2X*GT>  r,  o=/GTӊ9   dcPy)?XY   dbPGGHj\g!   U@Iz}#Iq~/|   YX rIRkY   dbPw>$ոI   @V) %IR랷(|   YX }g~$I5nhg!   U@IG,GT7>  R, J:g?7Y   dbPҷGHj\>  R, JIRk,zn<   ʰ (I}$I57C    IiЋ>$ո   @
IRkY   daP}?>$ո>  2, J4g?׽   *`$I9&|   YeX wg?_sQ,   ʰ (Q⽣~$I5xY   daPy~$IuMy   @V	 %IRw~U<   J (QOEHj^kٻ!   U@Z(GT|"|   Y%X ?>$ռΙ_   @V	 %jsIR]o<   J (Q+}$I5   *L>$ռ   HU`P)GTC   *d~}#Iy/
   @>!    (Yo>:/!    (Y}}$I5s!    (Yy>׽py   d, J>>׻y   d, J:/}$I5oy   d, J]>W!    (Y}$IJv   @l}#IRj   H #Pt>$ռ֑   @`}#IyK<   P P\}#Iy݋   @`GHj^!    ޥFHj`   BY @>k3   X @g?FH]^>  ,3IR?
   @`Z}#IRj   da, F7DH.   @`=7G3   HQ, Fhn>$ռ!    =WGHj^   X ꃽsIR+/&|&   Y?G3   BX Hyg>$Q   @`D:G9k3   BX H}#IR]~PL    #7|$IJWD    a0"m|$IJCD    a0BEkc$I)3   `\}#IRj.}{L    Ç+IRd   dcg0B˾}#IR=7|&   Y Pg>$ޕD    ;jwg>$+g"   3IR   @6v #Mg>$wxa\    |EH4E    ++FH|"|&   XY `3IR3   `MGHzW>  l, FjY$Iip3   `:g~-G:Ԙ>  ll, F}>$iX˫"   5I~\    |/GH4s?E    1wY>  ll, `3IRg"   8>N>$)   @66 c0{$IEm>  l,, Ơ>$iXs"   py$I|"|.   XX AsEH4{   dca0/>$iXE    1)ZDHw_>  l,, dpg>$kƼgE    91]{\$I~5|.   Y I]{$I:O"   tNBy$I:   d#g0&oYy$Iz>  l, ƤoDH4   d#g0.N(|$IJEsC\   ҨY Qg>$w   d#e0{ͅ=$k   d#e0F+>$iX/E    )1Iu/Y>  l, ƨ}Ǣ{$Iֿ   d#e0Fͽ}#IҰ"_>  l, isS*3I_?  4* cVl3Ga>  ld, v~y$I:?>  ld, Ƭwٷ{$Iֽx   d#c0f3=Ga[   @62 c:=$+'|.   X Ysߌ>$_>  l$, m)I   Q Pl\}#IҰI   @6 -gGH4r   d#a{I."   @9GaCwE    	 ?}#I#_>  t {zY$I:g#    -S{$I9K   He Rl%GaU"    ꃿIp    IDATA\   Y #GaE{Sj	   @V* >}#I#廾.|6   Y, xOY$I:   Je$_Isg#    P}#IҰUGE    +@䇿I:|.   Y, .; GwSc   Jc>ٻx'MQSiu|,V֪:?3Te.ZGֶj&!a_4!  d-,|=x5sx>\vg#   P1 P]$Ig|*|6   czoFHԫu   Hy}#I҆:w?  |X >zK}$I֭   @eX kzj}$I/eyuKg#   P ϋ$WwF   2#, 5ND]$Iul   *3 X7GHԫuݒ   Tf@;y}#I҆:0~6   L  ݧ~}#I҆3y>  ʴY GHԫzkg#   P6кjIzOhl   *f0 g.G^F   2m v;z$Iվ   T` T4ϳ,Gr   T`@d<}#Ieݼ%   LIzՖ3|6   i }#IRy   @eZ, DDHԫjil   *b0 jK}#IRϮ	   @eZ, łێ$iCYc}FG    *}IzU~]l   *Sf0@w}#IR)>  ʔY z$I56g#   P28Ϣz$Iչ   T`yC]$IuF   2e d<oբ{$Iz,˫^?  |*, L[{$IU?   LiIz5/bl   *Sb0`+}#IRg#   PS?w=$Y>  ʔX A$icZm>  ʤY 9yV6G^%o   @>Y kz$I83   L jpT]$IZ>  ʤY E}#IRF   2i ~GH+=>  ʤY .G   T&`@eϭ$WF   2) sz$IպbAl   *b0ZW}#IR]F   2) qGH+{g   LI   T&`P͛j]$Iǽ?~>   DY ?$W>  ʄY GGHԫg#   P0ּw=$ꮽ3|6   	 `}#Iƺ<   T&`U5ϳ,G^# |>   	 p3FHԫqg#   P׹Iz|Dl   *b0Z+FHԫ   T&`5Nx]$IkU4on|   *[e0jz$I꫶M   l.ϚGHԫ|   [c0?6G^kF   U C#z$Iy   T`4/b]$Iƞ{.z>   - v$!o   @e, ]ۉ$WOG    !}Iz98|6   - [O$Wg   T`H4/Z]$Is~0   6!Q?w=$U#   P,!QW<ˢz$I8   lɞy(G^   @e, Hsz$Iy   li^>/G^Ym]FG   I C~Gz$Iz#   P$!R=<$8#   P$!=x]$IZ?'|6   M 2VDHkl.EF   I C}z$IU
   @e, L?$!|>   q, L;$-|>   q, <k<}#IRE   <tU]$I:^>  8 Cu!w=$ʞ<|6   q, PEHWׄG   `{I  2p, ݈$Wʽ#   "!}w=$ܷ"|6   > CIze4:'|>   !8z$Iz#   P R~$ij   X ysU$W#   !w=$ꬾ"|6   !ֺnI]$Isy.|>   , X}#IR_ŻG   -yS=$I}5t|   *X >G^}'~>   !yIzu:|6   , \Gߎ$icjm>  {kYAv#   P vŻEHWυG   b0FYIz?,~>   @tV_}#IRg#   P (DHv=Ow   Pv8W=$U[   eױ ~oV=$I}5   eױ (/>}#IR#   \:_}#IR#7F   (@1~O]$I`   , 
qǣz$Iv;#    (A$_   J@6G^[N   J@:^}#IRwF   H%fP z$IXս^>   @OXU$I}Տ{|  TR R=7y$Iy7#    (lw=$yNl  TR ӹIz-g#    (z$I꫺G   H%dP0>}#IR_S4|>  @*!DHWʽ#    (5w=$Yl  TB ԹIzeg4]|  T2 H]$I}>   @O/<$X   d, 
+y$Iuݒ   d, 
*{Izu\>   @A8+GyZS|  T" ռz$IvG   H%bPP?}#IR_w|  T" Uk<ϲIzo>>|>  @*>}_]$Ik   Jڷ}#IƲn^]   $, 
yWz$I~G   H%aP`v$oG   H%aPdvN+G^;G   )>rS]$Ig>   @|D]$I}U   , 
q_FHW?   JjK}#IR_>   @эngz$IY}E|   (I>OG   HgP$ڡo   
}<GU|  Tp %P=5<$վ   , J"[H]$I>   @It:7Gu;yu#    (eߊ$>   @Iԏ@=$I}5W|#|>  @*0kgIzu<'|>  @*0>qw]$IF   HfP"[N$   
D~)G}<|>  @*({Ij]}@|  TP e2<o7z$Iy   Fdk$icjm>   @ɴ[}#IR_o	   
dg}&G!|>  @* -{Ijt\|  T@ e3:'ϪOEHԫ   #cPBVDH,˫{<|>  @*j\}#IR_>   @	Oh=$I}5/   `, JEHW#    (왇z$Iꕥ   RX T3z$Iz#    (%_$Y   
a=$I}?4|>  @*ZKww=$>rc|   (cFHn{Â:z>  @*kxtU$I}Տy_|  T %8<$\    , J-<$չ    , l<oIzeim|  b (CWGHW   
Z}#IR_3"|>  @* k{Ij]$|>  @* {fAA   RX g?}#I:<   iY w0GG'|>  @r FHW󒯅G   HC~DHWs#   !g@^yuz$I5i#   !g'$A    o91Gg|*|>  @b lмK<$պ   iY Aߏ$U    wV-GuZyE3   F =ݟ_}#IR_>   ) zZ.$%>   ) zgE=$I}<;|>  @R Ծ[<$=x|  4, htNU$   02|, ӹ{Ij,l|  4, Ӽ|~=$I}|D|  4, S?DHW[#   !d@.ϳ,Geݼ׮3   Ґ `S?$	    rr=$I}X>    i~DHW#   !c8#}#IR_Y<>|F  @" `<o7z$I꫶-3   F ]*G~)|>  @" lR%<$վ   iX I>}#IR_3G   HCM}<$zg$   !aɳS<$83   F [$iPj;   Ґ `ZW}#IR_5#   !afտ{Ig$   !`fU<ϲI3    `O}#IR_K>    }<$չ   iX E͋.Gں<	    [T[{IU;3   Ҁ `F=$I}5	   #>|C=$I}o>!|>  @p lUây$I   Ҁ `$i\=|F  @` lUmnw<$q'g$   f֍ɳں{Ij]{H  et[}#IR_Gn
    Z(G׮3   Ҁ `B'}$GqO`  4, 꾯$i\g$   eeVGHWg   i@Y 0aN$V-Ow    ּ<$3     `jG}#IҸS  4, ;y}#IR_΋   02x, #7FHWV}2Osg$   cV-$i\%o    XG$Ij	   iX 0)C}#IҸڷ|7|F  @0 L<$l	   #Ii=$I	   iX 0ix$IWOH   HI;Iպ	   iX 0i}_}#IҸ$|F  @  L/[$iʺyu_    SҾkIU?H   H)i^;Iպ	   i@X 0%v$i\݇>#    fyiFH_W4~N  H< ȍ<$~g$   `V-$i\+    SXG$I<tu  4 , ݢx$I_=_>'    `FYm]5$IGs   FbY 0-VDH4g$   ` LKk;Iy3   R0 ~Gx$I_;I   H, 꾯$iՎ=|N  @
deVGH4>#    `ڷ}#IҸ:^>#    `ښ}$Ii9	   ) V[;I6YI   HA, ;y}#IҸ9	  1y/[N̫:HX 0#}#IҸ:w>#  xAu7ND޺vqy<o;SX 0#Z]HSy.|N  Mu_|,o]w޹<?~ w* fDcGW;w$  @U$yW6<]{ǔ/`, Żu$I39	  PkKޘ7vS>Ϻ3[) f<$d;ω   Cn䭫3ؓASX 0c:$M   0^ᲿysyV}r~8S`, 1 ID-}K  (3Yυ `ƌm%IĚ5|N  ԻN>h5/bHX 0c2$iu>?|N  Ľ_͇!. 3*[:$i\Y<͛>'  fZu?D>5/Vg* fTӢ	I6YI  iYw,/Jcc4xX, Q͋>$i5s  `{S>f^ZW>R, ̨ڲwE$m=I  ۿ)/wgwHcZs7,kӼg%  Pzսv})wF4o<&M* f\
I6Y툷I  dw})F׺BM\9	  X	wpX, q{D$mνI  7S=C*3W[[Y!I&˚oY	  puV_9 3otNE$mڲwJ  `y?ϯo?R, ̊}+I6YoI  `?wƹoXw%ϻo]JYFYZ0$iu$|N  nS>^$# ~҇I6];J  `UwǞLxoIcB6@  f؞/kG7/})y$>qwHX 0kuD$mF$  0=Ճ_76o]8<tujhuiU* fMӢI6Y+$  0q/Gc8k- yG$mN3Ow	  D,;mg
Kc-{W!If'  Joymy۷wޑY7XF    IDAT=&krX, =v/,%IZW?+ `ף5 4k4 $Iȍs  nhT0 ̪E$mWyE ".zwo91֭į!,>
Y5#]$jS{ 3o_ټ}2k} xsCZ4|V 0<8׬5և `vɳںCM}Y	  n*Sj߁T0 ̺}+I6[ׄJ  w7<#EnHck\}tHgY	  λ+#bC־  fV-,N* f]uWF$ml#  f'?fKSnwFJb6{ $iyC .|wUƞ{
m}g$Iyg%  3v_7~`{#a6ѼI6[sg%  S>nJ[cT  le>;$IlYm]  GuW?V.;]3$O f`<o7I6[ߏ  ,,d~	peFY t~]!Ifk^Y	 @A_ּq훎ͻߞN]i8ʲ#b6wI6[g "_h+ovT0 l33>}H:?=/ \սv o^>?}A'?JŪ{
mzkIX
  x_ֵjGm*{cD6\]  ymkOT*]Y`X, ئw}Hٺk  lw7<sel
m$I[zk%  3nS>+)i3eugF* >G$IbsW `w!-> ֞/N+,$io=5~^ u
O脟-#b6}D-%  [x)3%pGϚT0 ls>K$Ibc?6=/ ʬe?xGDI۠5O* Y>K$IbK>/ JûٟşI#b6WoE%$m+% @io7?Iuϩb  ݓ$tf^]y	 Pwk?IO~n  З$iC `({3Ǣ?IO~  DoE'$mI  kymٻErr}$wşo#b@q)<$iu>/ Ey_Ҭ}']* b,%ϻ3E-V=53  ?I*I5ׇ`, 3ѓ$ik `6Uzy^??%}~4#ys1 a?>2L$io?#|^ ̘;%o}>orb]{Gg\k:) 4\"Ij4o	 03ף?^Iunٙ
0C}HG;|f LS$iҵo=5<Mc@9~$ik\?3 ~AuK7#E_OnuG&I7~Ʀ `  %IԺ>//l޾aw%֪ݑb  ؏&J4eن @9}hjџ$iѷT0 '$I[|	 w%֕{ͩ`, UkW?(I"* `_n|$I}5/~^  \wg$I[l֧ysg& 0|=3;7IzK 7}Hj>3~ʧu~헤i	?SX qD-$m{L  ^uWһOFL4vO}Χ  \7G-$mU3 ض/I۶Y	?SX ot<?}Hn^& v?HRjg`X, />_$Ij>>3~I
Z(|$irr &nz"c$iՏ{Hc@E6vY0t] n1˛S޾<{	V?=s$ ϯyE1$mڑ>7_x[_7wͻ4Ֆ%~ ]g$I[uł	 eS>cKUh IfIchxt#IV>rc2k^?ys7$I+!' qI^~#|n@,o91﮽3TgHX 00jy}#I҄j7s ּymk睇N3zKkgHX 08FNIPԹ	 C»=XJd@u^Y#Ieʞ/ 0h/Ij'c, (K}H4PPwkͻmx, (v>k$IPUK& nDcIR<py) ˂]>o$Ijٳ? t5zJ
^s]*  NgD7$Ma>7`[Ō$fOw, 8>o$IP˾>7`[ڒٮuݒy
S?F7$M~>7`<*I,׺r7R< >,>s$IzY7k fSuWEO\IR	jzKd@>yO#I҄j,#|nlq+I*A6| ` o:6̑$iBo?#|nl-{g$ƙ>RY 0e#I҄i fK?zJJPϼT@ $?b*I |vliQ+I*A>RY 0FYsG	պ	 yG$
չsG	=uм|~$>RY 0+}H4j-|vlh]X$`
U?=$Iraо1+I*xYc}KeZS$Im fAg1+I*xٺ]*( ZF?$M 0Ӻk]*|ޥ `>0$i5/j#VT:^>RAY 0i#I҄<xe5]w#VT7?FVyeg$Iɫ2|~~O&I,׺
}g$Iqg' ̔!1zJJPoϼTP GA$M]N )sh$ƹ>RAY 0 IV-Ow	 0~MnFϼTP <?r*I|,|~Lh^/cUTG'|楂 `ɳS$I}q f@k*I*AŻϼTP =FC$Mdm>?`~$I]uWϼTP .I0U? #UT<n>RAY 0Ǽ/($iRV>?`FTIR. ay}I4Ӽ3 j*S٬]3o, ݟ_}I4aQ*I*A
y, >$IT떄O ԾcyKfШHI5n_fj,#zJJP3/ Cy֍>$ITv 0EQIR	jzKfP>~[$IҤj]sph||$Y	y, *UK$I&U4:'|duVT?g^*0 JOEI$Mo 0Y3EPIR	--| `Tg$Iu~3 &eymGPIR	.zi). N%I&Unuɨ)I*AYc}Kg$IXm[g( LTDNIR	>yOKgi&I&]ʽg( LT/ENIR	ꬾ"|楂 `ԾII{ Os( LD%ѣSTڷ|7|楂 `(e>$It#>C`":_=6%I%u~3/ C}$IuA3 &"{gcST}%|楂 `(5/r$IҤ	4]-yuǦ$5Nx)6 Rߋ>$IRc>G`KjK=.%I%]s/ it<=}FI4ZQ ؂T=s/ Cs(I&]Ӽ( lNRT,Ov
{, Z_>$IR$|o?#zTJ` `hՎsJ)վ9
 }Q)I*AGoy, ^ϳJI5ӂg) =_N$gϽ _$[S>>GՎx{$5ϽT }VI4ڷ>G5)I*I>R	X 0j}VI4)Ow	 Z.T?#s/ $q3"~/^=%I%Ms/ CsߊJ)5A,z/ʪOEGIRI.|IK%`k^J^>K`LDOFIRIJW;j3K)?R S?ccQTkVϽT ;lE$cGo 0+z,JJR^*	 
s$ISvR }$i[s/ м_-I\g) %7:'jG$$5B) 
~{-I\<͛>O(ݢǡ$DO`K%a@1$u?O(FBIR-ٗJ<K)׾Y
@y[=
%Ie)`ٗJh`4$i5S^]y
@9u\=	%I%){J¨Ki8>ڮGAIRI7R ǂU>$IrVS Jv#PT?99| P:_}I4n^=ri^PTZW>RX P(K}I4 Kދǟ$D5/ R;g$I*{<n>S(ysl$_) 
sLiU?3RcOT,.|IK%b@t ($iZo=%|PCؓ$5/ Ӽg$Iӫ]ϫ{JL:w=$I%g_* 
vEe$M;|Ppsdȓ$֪o\, (Dy&IҴ>rSLjn$E_	d, (gFg$MҷT yעG$dO`K%c@!5Li׺
@q,IҶzk_* 
3I]V{:Ov ]݈u2ժit8R. VܚcMi83⩟'I*Yn, (-'Fk$MCWT u#NT~ggK%d@a5\&IҌT;w* }MTZ+ϿTB VDk$HUK* Q=7G$y޴B>}_&IҴE/ C/F6IR	JBk߰,l$iFj
@1t8zIJXug`*! 
qGm$HGo	 ˗݈k$| Ъjg3N8D3IR	wIL%e@u1$iFj|B\`o?3zIJXg`*) 
}8IfVmOEV Ԃ>zIJXcsp, (q)$ij~g+ é~҇ǘ$Ֆ5| j9'IҌ=P͍ MF1IR7ETR BG$I3V>[2Yz"zIJXwsp, (%}I4cu2|0\Q$mTb Bm[:If=_]ּ[s0 0:'Ϟ,$ijt\|`8,9D.IRIY8R^;._QfQ@QDp/ 
*\@}E>=ݙ<O$9$d"sBDI:k*BLLzj֗XO:NU@Rc; N3;,|Jƿ= bngy_Gw 0Pf$i|J`J=)@SS+< r)U$o5 K.^@TЭ TOWIG S}~pZ hjps *Iߺ\= bӾ>78k{3V4~BJe= bC~;|N{] MSmG} 0P't3V4~/\= feۅiki# P)eJ$QsH媥
)V>$~*Y hj7}uV$Oc>= rݛO	Y h o{ѓ	):kP5 Ma32[}w$b "5𙨚uߌ>`y$|Jbk_0z"0z E3Q5 Mg͓>}PΟ>g%I_ @3Q|Tg! \?>k%I15Q s3Q~ ڊWG 0>g%I1u~:3Q>7 д}1r)m$A 8sQ~ /,iV4:7=~ j, 4x<H(W/Km$i$廿.=~  o='G 04Y+IM=v s7jOfE 04$MA:z @"* Mu>`ZC$ֹ=n IGlT, 4ޗ \y_m>o%ICjs c-e{D 0T~@[3 buQeqE 0Te<>s%ICx <s!QY HR;>`Z~-~JZ/F x>U{Z RpwG x(|JW0JTzj R3}!|k_s̕$֙=V iʔ<|F, ٵ3 ϼ+IW-* 4;ΎJ= 鉊o>'`:W>s%IV/E xy33Rgd =Q$ _I=>w%IWRi 8sRgd =Qߎ>'`$:7>w%IW <S/j@Ys6OeHq	 #8}WA廼2v=B =k S\ Fxl>{%I_纣 <=k Sj Fy_^IUWS* ϪygjϚ/g LއHu]rI 5M]TٟCX HO3 F}юWY 5*W>+U[c >7`t:WnG~=- `zQ>/֔ߪs F
    IDATsqW쵾c ֪ujk@z>;` |J^kSje# ֪gjk@zڗ}vHߞy[`Iս ֪l<gjk~>a =>?`Z~-|K~Z󄿌 N5 ٚMJz
 ծ|aI_ˢ S5 iuo=-Dis  KM֚3 B4Xi~oTѣ  ֩lN-gjk@ZCN/T>Y,ISܭRc  K3gҺ RˢR ѾsX%;G Zg}9|v, :+g) (8X{(}z: Ro>K Lno$I#w}z+GR6YUmY Hx3 ´/#|KR\sdq sӉS@ZGއ4otocIjo?'= li_W :[g* 6\6,IU+_Tfˣy `=>GU[, u5Y*W?}@wɒTffgD ʕQ@Z:W}@Lo,IU>`tFUm ֣>[ \ji(|.KҤ8wS*:: lɟw 4oT6WE {˷$MpN?_w{m<Um ֳͧD 0,Iٜ-Rw%8 lS@Zz ZY,IV=Op $+mP z{c	 ?U,>e	ϒ4)5'TI<3U@ڀ\}\yPlI[Sese _ =WU۠, uD 0V'}:|>K8׻(_2 L'?mp j Oծ~ђ4*u h7?[64 i+"{ek`-Ic̬Թ# ҆f m`s}p\+zNKҸԾ`^ S~0e3W68 iw} cӒ45o
@t92|QY HQs OY7?>%)!R}"@5Fe mD= lJ>%)^oMe |sV@ڈ{%U>vO$|^K(w}M*[}u\>gU, x VS6wy-I(x ugj/!ֹ
ْ4E/N򛣏\ ~mt FVW_ {y̖asXzUQ CSzzfOv &T<|{9 cu߇lIxM%D 0TJ	/)WtS[>%i`ʚYUڔ, M~a ekunFnI+]0݅^M@ڔff%1 L2$~[,y{y) Dgj/#<QZ_>%iC(_}ȴ&g mb}D)7廾&|KT,>&g mj3rg2 Lb)_9.I(R& T3Xd  o x[jDqIZS=ߒ}\ȵ/>UH  s &R/|a,^}w2[}L@~>UH Ҁ*3l7$[c>R;> D=)>UH Ҁj_8|e	 i\jŔ"X0>UX Ҁ &|0n:W}@!?47G 0ъnM.
钦|S3@ lYe i {xC\4廿y 	+ͪ4 is *\y.5}_*< >>Uh Ҁ+]}V@e~~vIlfVj󕔊NQ clLټ  \{}^@u8#]Rul:7}\LVmY HCxTg6 TGMS?>%M~~5}XjY Pqg6 TNo=%Mf͓>R}x4SZg Y_>:[zImRâ/ kNJ@B.J,n g|{I_}_KCD[ 0'UVm(Y HC{g7 TVy/iLEjՔ
 &v4, !:o rݩ[g*#
 &FSjC@R◤mG PieHj{s_43+' y'Ұ XT !+:w}Mu~i lrՆ4zT `4:W[I#lfVjשl> `"uV<Wf 0T6>`jt,廼*9W뭩{ L	5 iu>,,RƑ@ҐMj?7N3VW@r~7<S}N),{b=' T-4`6, a7Y*[}Tynw~EITkSS = i/^}*|@F4w:㋩l>J RR6gY4, Tu z+HmßHZffo>: ?+~+" iDK>`+JC@Қ *7ogj#@Q3)l z2u<(e;<7[SO gU~.z6, N <xT??Guw:$}, Th_8|6, ֽ3 xHO/ M[R)  J}_	Ȳ FX󄿌>gQ^'}:4-s} :Ń7?PmY Hll>5=9RE}.l~}FesF4:} kmJ9yT]_Ly m|K6, 8{ `=H͓??HX}7U/ xO~ȳ F̬T; S8CHR}wǤTt S4Ty R@D yn#lVy `L-3(: )}PSYD *Թh,=QSy\,	 E]ß7Ts~ `S7_Ss
)m~<(N# >ZH RP>} i}7?mRJҫy (<yRT RTsJep  ,RR߈!G ~>jaY HW  {٩qgHRS\qWC
 Fw|As²  PMŲR;KmßsHS`<ө{)eC Ǆ?P-4 )bѳ  2{(/\_CzFsLoԹ[) `Ga, ZC,  F_Y<)EsMqG$u<(G 0$S6gJY H 0=If|W?t/x~js	l~  #оh g Ac PYK$Mz߻O, L=|D, 1qG  X\:Яjk:_SR*: @g?/Qm, ơY\qWl  D?:~>i-_JD c͏?OQm, Ƥsg 0zڹxks7w8RũXzum   Q, 1)~ ֮ͧ)/4gT]u?m{/ `Z?Q, 1l  ,Rq}+³y[?Ѧ0K;Mekuw 0I4M ֟D	 `R	Zg}9+ǣh;"5Dj`OэN &Xߨ6VY HԜ}x 0Ww8+Cߗ?י[Χsѩ\qw	 P1?G@Zω @T,.u:$5R}w-!q9_IM÷' `oK̬AU xt 4RԹ{%/|aI*_8uRSR?/ L֙H@:7=3 )Vz u0u80RjT)eE/BOsSoSY_O SznI@GA  xǖ=εHGQ/~ijf[yGjyg{g[ 0:Ji ƱYx T
guLPyq{S}woH.jg	__/OO}8DOZ|5/)u<(un<!u:/ސ˼'? P4Y HcZ    kT, 1@   4Xm y    x6eє;,6 iks   1վhajc4>    N.
Rm Ƽ=N    3k
Rm Ƽ|S\=S    #~og M@)    =W6Y HP}Tѳ   1֟W6Y HRo   t+Wܝ9U6Y HR7z    u?S61Y HҜ^    Sx,;</JiR &=g    Ҿt)&* iw|AJ,z    0jE'廾&~J@:W=n    ǆK6qY HV}_J,g    #T?=RM\ ֽ   t,>J@   T, IlfV*=z    0dS6Y}$f Mh39z    0d>~f Mh秲2z   0$劻R6g{(&6 ikp9   4'&: iƔ"z   0`e)'&: i~F<   `Zg}9I@0z   0@e?F;6Y HXzU\   `@ZoRY Hy_D%    |ыTD Ry*3z<   -I*Y H=    fwye=j@JMep   `#u80IJY H}s
   QtSo
_RRY H*_Ҕq   \{Tݒj@X+W    l|sj@X    &CCTd RtR   `}t)uIU2 xw   `=/?.If U=G/    ֦H.
GRY HqGG    kwHU: J    kzίCRr RkWѣ   gѾt#*TnwG3    |KT~>z   6Y HUoV|   @Jl</3R, )ug    w9n]jS4{N*W-o    Sl<_W4-Y HSRq    SuWT, ii2{(z   Lr)m4e MQs=    Rφ6uY HST`TWD;   R,>e36uY HSVy3   `4;!զ2 iw'   0|ݻ/Rmj ŋg   @E զ6 i
(#   :~@=z   TW_~@~>v=z   TR]4/z,   "_~#u- -_T6WED   Ji{) ԾxQL   {R6o;)    '~*Gʞ@Rj7;z6   LbU),Gʞ@Rwx^*3   `re{){J R   Xkߑ69\y_   8esUw~y4Y Hz機    uHٳd 鿚e*3zf   L;R6o{i3 '}&zn   LQ
ϑ5d <=;   ^rk@3j	   0޺T8R, $=Yx1
   0ڗ#^{     c\`l~#e@.4z   I	@)eL   O~{)[, $΍GU   P~Hzf i廿.N3z   kh)ۀ, $e{DW   Pe)4RY HZgS?=g   4xm` ֫Y_    !w~7#ekVxy   0Zzw}݌4{ó 5   0Rs~'#eofV{Y   bM)e4{ A5   0|e7.F6WX HZﺷ|;z   Uʃ`l}alH{%n;z   E-OH&󮭞u#irjhY   0?~"eXzu{/F/~I*Gc   sQff߽H *}]84YjL   N#տ;)P#?kײ_Hno    :+-Uo=HG}(z6   lS6g)Ts6O,ߵA&mGh   iocG}84xC=    &Q{~"e[5NL$irk_0tP   l+R6g)pyy¿ ImSؒЁ   oUكy_>^k]845Й   !Zg}Zcÿ I_C7   (&esK!չ'k{I{-:   ֪J}~"eC{O~׊UAQ{p   i7~"eCx'kY=/J/>Cs   Y\*mR*O_ {-TY   o/ߛHِO/ y&"l    :N4{5Og. ZIئ,f:   z/T?ʦ|s_jչꐨ   WV~O"e#{\ IVrQ   Yw$R6lg. z%U	1   RoߍHx< /PRQw E  IDAT  `ʕ{)a3@E_ڔZ٨<   025bgM__s%_j:+   jp)\tns
"%U9[kF<  iS<tKo"m}񬏉Z >YT   }"eu/ Z.B%U   L->,{н/TRulʕj   S䒔<C<0\ >!;ÿ`IխqF4  iP6K	󐲠O_ '6T|gس   <Cx/ :7KvNesհ?   Pq+琲R;_@j7R`/\RkOC~
    TY)M<k}<s{w.<]>    @Y7VϺ zz.:a=    *{)._:_ N+e;nTZ|eHO   *\yp}AKm[! i
,u\:   @ޘgH+߼ oI]s   JZYR65}z=lָ ?u֗t    扟
1sћ h_uXD=9   P!fG.L@j>XȪM)=5    x&BƤ㧶_@֙   RzjRx|pbղz0IS   <wunch)_LT?   0?7BƩۤr/ oMgϊJZ>?    &\lR6F?k8@IS̬Խ>   V^]^7!l ݇Vl4=B*6`   &TNYfoCj =**ij:   :wR6f^c_ +sЭn   LεGCHǯoj =~1,i   @5_y	1/TtG (+RpIU?L,7   S?_~ ecX7%M_I   0fNj;)Ú}|b HE~-/@Ҕ5oT<p&|   xhis\y\V_骾/7   bun86AƴUqw./B<r    1eקl1H{[A}&- ʔIWo   F̖|_[qlx=6iӹISWpT>~`NB   `48
R6u<hM^ 4NT_qS*Ac   ejQP㘏a7@x<e~mGR@Kw1   YR6廼2# ,,</JҔ5wT,jPG   0NL̬{i6gԽ¡< i?7/KU㍩lq   H)ڗ<@ !4}5Og   +Wޗ_~o ecZ?>d, z;S+$M_k   lv=xw}iޚʡ> zVۦq   ,R㘏Hǳ|SȏP}7%M_iS   `Z;)nw? =1/S<<   \Rf6Kq   <Sw%)u4/e. zZyXISܭR   ~X~sn' i4em$S%MWNe(9   jSkquR*j. zMC@҈kۑ   Q6W~ƵII,B#[ t=e_.ij_0G   Ln+5@Ҹ</C_:@OR񒦨RG}  @e?KcZOTtB#_ t^E/4=_ʕEy   PI-}i?{֔IS5   49_Z|5@ObIxc?uD{   0񺷞9/]s/IX@~{?hfVx|   䒔{NҘԽ4n =Esu$ISmRqG   Lb)_1+u8@_?X|פ2[}  D(WY:yijcZVϞ'5m
   P揤>[ʞ̬Tt8@OS%*_Fy   0T??KT`Թ4	rSX=SRkp#   On8U?R4)vnw>*"u:/  m]n0o3Y'o<1e>a\(}  @EҸTͩ4&bSz0ՏP?V뭩l<}  @LM!~sH3R+Kjb }eZV&_R%k|)Ei   !Zg}9gsiT,>MZ <xT?¿	$Uֹ}  <gr)|SGT ǧlK¿)$UYs1G   LG<.E6g_CJ&zS䏦iVlM":6K>   `:1\RP?nMU4.%Տ,SSzY   Cӹ餔ZMg~/u\2oIը~O'  tonn4?u(M-  ^$ikn   ӽ:gnidlhsq&\ LQǦ|ϷI蚧~>D  ~MOߞQ O[NMC'ibk_84  MY)🱥aWm}Il: Oѽ8i-ÿ	%MX3Rc1   (;qJ/x~j~oSF?- ~H+J>)iUu^   {R6A77vF*[jcgj OYrYj7)߰ƾ|X~s   {.U/MwtRJzClY <U:'}2@Zw{m*W=}j  Zu:!?GKܭRES"51, ֶY/o&4v5Z  }Md7?ڗ씺K.Mӈ~8M,T'/? 5qԇR*:G   <M]km+y~z|OX lbŒԾ[yߧwTijk~sG   <{E)?/kl|KRoJ~35pj:_RSSq̖G?TE>rgtrj]0?5Nd[X=>Iíuѧ    <      T      T      T      T      T      T      T      T      T      T      T      T      T      T      T      T      T      T      T      T      T      T      T      T      T      T      T      T      T      T      T      T      T      T      T      T      T      T      T      T      T      T      T      T      T      T      T      T      T      T      T      T      T      T      T      T      T      T      T      T      T      T      T      T      T      T      T      T      T      T      T      T      T      T      T      T      T      T   {v@  0jA  @             A            	            $       H      @             A            	            $       H      @             A            	            $       H      @             A            	            $       H      @             A            	            $       H      @             A            	            $       H      @             A            	            $       H      @             A            	            $       H      @             A            	            $       H      @             A            	            $       H      @             A            	            $       H      @             A            	            $       H      @             A            	            $       H      @             A            	            $       H      @             A            	            $       H      @             A            	            $       H      @             A            	            $       H      @             A            	            $       H      @             A            	            $       H      @             A            	            $       H      @             A            	            $       H      @             A            	            $       H      @             A            	            $       H      @             A            	            $       H      @             A            	            $       H      @             A            	            $       H      @             A            	            $       H      @             A            	            $       H      @             A            	            $       H      @             A            	            $       H      @             A            	            $       H      @             A            	            $       H      @             A            	            $       H      @             A            	            $       H      @             A      sdn?`    IENDB`PNG

   IHDR  	T     Q   	pHYs    {Rk    IDATxyee}kPD"&1FMnbnOIkcsM<ɍ7ͮ*D! H'J#
HH_PPtխ5w&7ߵggs//_~Z 0>azo:#Dߋ7EkDߟ&AuOa/   P9:Ǽ=nG_0:;,QGnS ?`S+'2#:Z˟u~   AuwcW9G-쿧W9܁̍AU1]<'3Z{=7,i]~    ?~#IzV1z\ l;*=z{Z=Z)fEsdV    &Q$Բݢ}/EU1ZO@T|a?߸0mTpVxZs>*   0qֺhIvU~qh9h*0w}nZ117   d>c@k9Ocp9|  *`\.Z$*i~Z   ī7[%iek?- 2lU:RIZb   Ԩ7ՁL$Ǩz40ç1Z{m   `=?~H4Ɩ=;:g_Ugs-MIVϋco    5z䶨}Y=$i~~kU#2&Ψ?w*%-lվ/Ѻe    [%EyW9赲?9  
[~s֊=WF؝ٯ"    FylD1l A0whCڇ&k_G    |Zg$i[gt/YlXL*\ͳJEDIi?cQo?   rT{~$IZXu~;0'U@yF_u!hJ    <]GknIjGEu'`TEyYT>()oz$   6z^~$IZ#{l7*F?̢􃟤:Ǽ=ꮿ   P'Ekf%I6h6l3*],ZKؓԈ:ǽ#_e    A+Jc$-|^GKFٟ"dP4k:;IͩsGۜz   `zk]$)ꨟ_lA<Vt?ZsNRsξ    O?IԒ-F~qE!NR|#W    4FK{$U}u1/0aЋ%K5SMR+T    j؋	~%IJmU,4AnCaMRT    _E跦EIrk1x_W	`AZ    M$%1Ac7P&uEٯ*    Pި)IRr3?M3[:cY_    oDϋ$Im~ L)*`Ah-f9]~3   wuT{G$=-Z`:L!*`aѽ/IsS   0kx%Zk$-}fh	2U뷣sʻ[[瘷GZo+    dxZKݕ$u/q XUQoM?`Ijnuos
   \w| IfS~o9 7*`}-ZPJRskQw7e    he{cIS_Q0y1h#@%|Sԝٯ+    
=$Iͩkc0z~~ڇD#ٯ+    J1Fc~%IjP<=L(*`7$5!?_W    ߎQ?~%IjP^nBȠ
'Ek.'I}Dim
   B>5\TzQ^&A0VGkf>Qo/u   @F>/ϳ$IͩZG|)L*`LcE%IͭpO
   	1KZ{/IRsV>oƠ
u7SIjժ[_W    LEk._f;ẛ?Q0vX3êAFܐ   `B;0IRjhٟ(pUh-5@$-{V|
   	߅IUubim'
(Aw]e$5ό~]   0F$I:1lJ2oDk$5%O-f    &vWLݘ$QՈa?+Ƞ
fQ􃏤7Sn89u   7j̿#$5'2Ƞ
6vTGlGRYVg    bu_js$IeTO􃎤fo+    m]$Ij1OP*)>$#.~U   7:2LԬvCfBT[eݚ)#W    |H;$5_keTOjh3`#u>[    EwߡIU?B0X7h$5qtV    hwifտOpUIͭ}f/    FߩI]cO`U_s\!FRck7?   m6h-%nMԜ*FqITaZ}IͬeQ+U    ۭ߯IU<eP|˰귤\$5jsco*    as:MԠfs?O@TԽd&"--w>5    s3G#&IjLժh_(aY;X$5Ż_S    0u롨{7IRc;ٟ'a~'C~4"R    0Vojs$IiՏg1{P$5嫲_Q    0/7$Iͨ1j<aPSnZ=ٯ(    WϮH$54aPl4j[&WwEo)    _u8>NԐfv=_:`PS%WDW    ,~;G)^NԌGTtΠ
hkf>UQe    `A՛FIQ?M@2*R􃈤fU=r[	    R&Z˞~O'IʯZu6dDU0[pf􃈤Y1Kٯ'    H5h,ʿ$׽_?K@"*6uߖ~ Ԡ[~;   @#.;;IR~v{?K@*2N?|HjT+~5   @sԣkvgYW	HbPdЋ?~Ԝzd    qꑨܧKfv7fU0EWԘ    룵Yx`Tw8$51otL    hOJ˓$5TݐIAL6$5WFZZ   ";=IRn(s,0**Z,!)j1z    c؏α?~'I-U7fdPS[yY+	    SoZվ/Ϳ$=O?G2I7EkH?`HopQo$    (/Ek|<=FĠ
&\]oٯ#    (^N$ջ߳?E1	WIuO}wD=~   Dgw~U/跳?E0	6ƅ
I~:   kEצIr\/ `O_uW    LC7G9w}?C0	5|h,J?PHʩkj    &S%I9BggU0􃄤fv-f    `@I҂=ٟ `T$tr~    La?:G-NP)$z0`o<5!)
   Ro7U#gI7	ALq~m/:    `aqafvJ#$-\%#*0GomV[_A    0z̤J;hýٟ`T], iA?'F\   V/HHTտ0O`TzmA6(7    l6?>/ɿ7$-Hc>* u7$-lϮ~     fx祳*P -9ֺO0`t/C{#:    |~(IZ_96* I?0HZG)~     Od43Psguy`PbuISEQo7    lEV0>Q4-50fU0!z.?,H;/~     `xgx{EIҼ6O0fU0!G5 i    zK$i~]0fU0Fգ& i~gٯ    `{>-I\ cfP)I[7Dٯ    `jyjfQԛ cdPs$[>/zW    0~(I7Ƞ
J7EkՋ%Oݟ~     c_9JȠ

7|Áٯ    `\U?c벿2TA_96p i~ٯ    `Fe?J❣m cbPÁ^3n+    /8R4w.A:5IZg~     󥮣L$ cbP̢􃁤1x~Q    guHT}$iluO0&UP
$gWdZ    2b$MP^iĠ

ֽdI@zj    PH$"U*(Xc(4^1+   )3FïK$gY10Up@ZM+    H2Z{]<#R47Y
J<+#(    @*%IsO
0UP=W$ͽ~     MP_H$ͭE

տÀ>'#	    kKIҎ>ٟ`PO} 0 iǫVcwfJ    \KIҎWO	0UP~;0 iYÛ~     =1%I;P3BUdA@Ҏջٯ    }i]$iWJ|UP֊=7Gٯ    ᆷ_44%I/dF92j^w+    (D~)I7	Ƞ

4ClfQo>;    dЉ?)Iڮ_<$̑Ahp9 IW~u     wu<=S.0GUPWM?Hګ1g:    B/[~)Iz|#*(P}j^wk    (Y=α?~)Iڶg'̑A7 iYÛ~e     ~쎨{OIS=ٟ`@ޓ~.    0AW~)Iz:'3̑A}o$mo_    OI0GUPoO?Hz{DW    0MGy'}?TA* prk    `OL$=y^ Ƞ

T$=qݳ*    Lɿ~*Izڇdg#*(Puk?uos+    Zg${'|UPH?He    )2QI>⧲?TAZ4 ;Cٯ    `
Լ|UP$}	W    0CQzQ=$[xc#*(Pk$=^ˢ~-     Slpwo>Mٟ`@URC)w|&     ;T4AϠ

dP%5:     Uo~ {ߛJ`TAګ1g     ipw$*UP *)ώ_~     |	*ISAϠ

dP%6     7^ߗ~*IӜAϠ

dP%9u     xR/8.U9*(AȠJʩZ¨7?
     غzc~.NU5*(AȠJix˹ُ?    6=h--^U1*(AȠJZM    ]~*IӘAϠ

dP%-l^uos    }Fh;VI|UP *i[K\    f9Z%i2TAG    `NzVI|UP *iaj~#    07*_~*IӒAϠ

dP%-@˟G    s]%iJ2TAُ:    XuNWI|UP *i~~    ƪ޴6$wUP>*(A4U{{s    y!4TA@U5G    `ԣh~s]$MrUP>*(A4?uN    `ލJ~'+IAϠ

dP%jQo\x    ,'ߟ~/+IAϠ

dP%'g?     njHI̠
gP2[cX    ,>~?+IAϠ

dP%jD     E~O+IAϠ

dP%W~    jsj%i2TA=g    t~_+IAϠ

dP%Oe?     Fh{[I|UP *in:=Q    h}WEkw4	TA@Uُ1    @4	TA@UҎWxn~    njOǕ3TAopُ0    @cn<5WJϠ
gP2vQُ0    @u\I*9*(AȠJځ?;~|    omZk$AϠ

dP%m+~t    ѻTjUP>*(A}~kD=~t    ѯ:TbUP>*(A-mS    }7+IfP3TI^e?     {^I*-*(AȠJڶڇ>b~d    5Zh-yz}$AϠ

dP%mCwd?     }JRATA@US׻ُ*    DeTm    IDATJUP>*(A_ke?     cpwTJUP>*(Afd?     s%|UP *~/Q    4Z{m~,IMϠ
gP2jD~,    XOe]$5=*(AȠJz7x    L.{KR3TA-    
/~',IMΠ
gP2jݣpo	    0hwÒ|UP *;_yxc	    0U~7,IM͠
gP2UEԣ    `tNxg$51*(AȠJ~$    oDk3%aTA@U>ُ#    T]bIjZUP>*(AG    VwGwƒԤ|UP *i1G    ;cIjRUP>*(AG91    ࿌ЏKRS2TA4-5Fߚ    m_;+XAϠ

dPi%ُ      Osϥ!KR2TA4zUĠ    Fk̢dIΠ
gP2Ҵ6    wɒAϠ

dPi{d?z     <z]Zk$efP3TiZ    z{eIJ̠
gP2Ҵُܾ     ۨj-KRVUP>*(AAt;     C%)+*(AȠJd?r     la/H$edP3TiZُ     ;hp̒AϠ

dPh3bُ     s9m͒TA@UzG    9rf9KBfP3TiҫV(ΆG    1{ΒTA@U_961    `L]%i2TA4ɵCD=~     ~,IAϠ

dPInxُ     cVjwВTA@UԺQ    <~{hIZ|UP *Mdvzُ     e؋AʿyΠ
gP2$ֿtY    <hI|UP *MZ/跳-     [=_~/-IAϠ

dPIkp	ُ     dxҒ4TA@Uڇ~H    `zzK$WUP>*(A&e?R     ,OK|eP3TiRkُ     I:ǽ#Z#*(AȠJN1Z{m    @њ+5(ZƜAϠ

dPI{{%     uN|W}$;*(AȠJŷl7ܛ(    l ZƘAϠ

dP]ُ     =%iTA@U*jn~     h#Ek.ג4|UP *\ó!     HqeP3Tڇ&b~     hz=Zk=$#*(AȠJ6ǳ     cK82TAT     n=^ߗ~-Is͠
gP2Ro(    zK}$5*(AȠJ9     
PwGr{mIKUP>*(AJkxُ     vE$%*(AȠJ%97     JkEϋ%iG3TATL3bG    88[v0*(AȠJ=     J4D%iG2TATDw_~\     (%i2TATBOe    @Ɇ|e}$moUP>*(AߒgD؝ُ
     [$AϠ

dP׻     &R%|UP *5js`c    [$AϠ

dP&׻ُ     oTXUP>*(AgGZ     0aWοm̠
gP2RS}     &TC-TA@UjdK     &#%i2TAz|      `-U
ɠ
gP2R#;     &\#%)2TAԴz/     `Q{qIZUP>*(A]޸&     `Jthݸ$m%*(AȠJMwf?     LA'}_~?.IOAϠ

dPƴQ;     `?o$=IUP>*(AR~     FVT{ \(*(AȠJTݙ8     0.˿+'Ƞ
gP2RG    )Vj%3TAN1zG    )׻_%2TA]~      ꑨ?'\=*(AȠJٍRc      zC$}{UP>*(A2Kُ      |Sim>3\+*(AȠJG      CI?ʠ
gP2RV^Qُ      |;x{tIڒAϠ

dP7     O{ߣKҖ|UP *eTA?     <7DkfQ}$TA@Uhp}     ت	LO$*(AȠJ]ϋ#}     ت]MS$*(AȠJ]U?     MG5^]tgP3Ti!=Ά{     &Û?~.i3TA.@<     l?~.iz3TA`-9 f@9F]/gSbpQ]G>S߽Noo?Awn:-;/_=M  LͿc4TA@UZ'N;  ,~cw+F]:.y;{F|}ODˣxV0ڇhzKtN̒wo9'Fk"Q ٳ䒦2*(AȠJg xQ+w^N-Os&:'=i-yFzUt>Kcxn=9  n+?gK|UP *-Dz  _h1ܾ_<=]jՊ=gfLa;zֈ0  V>/,-i٠|UP *-DOQ 7DãwfGS̢Tth>1ۏfx  Ef4uTA@U @ԝzpՑ;F瘟mIf=?W{ѿ|#%  Pi}>4]TA@Uc ïK=:'zT`Xcjfhuqp1z?n  LY?K|UP *k˞uH9  S~tZ.o矇U^S?Wn `B}͟TA@U϶  0v*w]fT$U'1渨7ݟS pϻ'*(AȠJ"U8  cQo\Oy#ŻwU\^9w|&b `;/M?J|UP *Wޙ @'"*lɫZ?guy  
4{4l+i3TA4_oT7  7Pi[Kt>!Q;q  O?J|UP *G[%Xԣo  ߎG>_u,J?JUF3KbO
  M6Fu_%M~UP>*(A aF4{N+Z[UzfEEKFZ @[~iUgP3Ti--?  dbwjSYNt.  mjUIAϠ

dPq=dX d˰~p=Q{T95Wf?r  4@S;*i3TA4F]c 73o>JY7+FG $cwDkgSIAϠ

dPq^i  rDuۢ5S9Tnod=xc	 @~3L*ir3TA4ם# <1Vmga? `4*ir3TA4_1dH 0Fug3FTvV]23;F `3̠
gP2Ҹ]g  a4G?g3[ikO7  hcϞ&2*(AȠJcif# 92z/U/?_JN9ctUُ;  ߞKNIAϠ

dPq9]?  hgJirn+  1]/gMIAϠ

dPq4e  U]ˢ{ƟDk3ϒ4^31(  sʠ
gP2\yh S[}}!%}gC_?[ Li~4YTA@Uk,1 `+F_ݳe%m~,7>  (+ϕ&+*(AȠJsjfQ= 6͎2:ό7iN  ʴO;g)%MNUP>*(AR磿# 7>/I?+J{~#Fޔj `;?1,)ir2TA47# ?mY?i);~  Ƞ
gP2ҎVA7G `m`}O1g%sKwz8 6_4)i"2TAm  A=-F	%-|Պ=C"F  [QEk3ϏϠ
gP2Ҏ6Z_ 2+FW%>1Z7  [=ύϠ
gP2Ҏ>gt ǰNAN?JjX3{  g33TA#m  ,= .VmmJi4vJt:k휜kP `T.Q!bPT-oK[Qy{?k=w+g==YP$DfP%ϠJJA{J;t%I񠌮}S>:K)&Ih|%w"A?*)aU^l%If\7[oHl2K8$Ij<I1gP%%̠5g+I4]M[0=2}sO8I$RF[W߇@^URT?zoR6J$MM_zg(=UI$vT:~9TI3fP}te$I]7y?~2ˢI$t~9TI3fP64d%IRUtV3gpq=P$i&}m=dP%ϠJJAWܟ~$Iyuh=w0*I|;DTI3fP5ۢ$IRڶotO{+K;SR$i};ǠJʟA0**IޛJoKo9=?.%IfA\/*)URx<*IPn>tV~|C++-MOIhp߀@*URTxLv\T%Ir|߶{7o ϗv?I%ImA?*)aU|#SSdT%Iu܊ 뿽Lvn*I4aP%ϠJJAL%Im[w}_LJ$Mm΍4TI	3ig*ITe*5~~~!G$It6TI	3'*IT]mepoj []+I4{JʟA0*ůy$Iҿ4=9w?>uV_I[HJʟA0*fg$IRV*`-,^cI;A?*)aU<[8yJ$Uͥ{g zgcY$ijoA?*)aU<O~$IGׄe 5Y6|"G$It4i~u3gP%%̠<xG$I
krǕ~+cYyDx~jIho}T͠JʟA0*$IRL͸̗!7@~_rK$y3,eP%ϠJJA_3$IҒ>;o1LWJ$?g:^URTo-+;$IҒ6޶tO|Z-P-?TGQ.I-t@TI	3_[$IR;x. Civo.IɰtW?/dP%ϠJJA7G?KI%[{L0-'?L>$I)~uP'*)UR*s/D?KI%Ϊ/i32$Ij⿣TI3fPW3OR$6^~wLeee>'$IR1cP%ϠJJA_iɷF?IIV`	7q)$ǿ$IRյ>vbA?*)aUeO$Mmۮ(ݓs̘~0c@$F22nM\[׀TI3fPŗyIs$I:mm]]:s[ jkP$ij/'cKgA?*)aU|hQ$=ߕ?Y$IvϮ2ٱ̗{ʳo0`:TI3fPŗ5%Io, ?"$ItCΫ}uEǕo-`zTI3fPł[~0)J${+Ӟ~coS=FTH$=&^ןS_g|<TI	3bpˊ(It@zqzj}c>Imp	Yyd6*)URXܻ-)J$=ڶ.e X;?=$IҌU&;6߰tOyvTI3fPED?CI'xPv]Kџ"$iFjWU;_^K=xTI3fP%Ipm?'o* o$I4d}-eůTI	3bg(Ij[zo{
'(CX$Iɿo|%e_wl<28PTI	3m+D?CInᷙ] F/$)xjcSn/Ko
e &*)URfߏ~$I]O	 8{_ǌ$s    IDATIH2_Y`TI3fP5&]%I=w Q$I3\3.em}\[{L~ D3gP%%̠jzj)n$Iz-|Cgw U/EH%񭗔Jݱ:A?*)aU%I$=ƷtV~C4zg?~$Is_n/};~0gP%%̠jv>'Ipy As~a'cH$g`O|euuJ~W dfP%ϠJJAj+I$}F:ۘ
`R&#IX5^/~u_ 0*)URfS-?$IaM lR6cI$mioްo<uKJg3gP%%̠j6?'Iu]	z?M$\m222_		 fA?*)aUi'I{s@}Fל%I.{uk`~ 1gP%%̠jtOyK$sKgnY@斕U$fů;ťz &*)URfߊ~v$I_! ?L>,IRU&;6[:Lq3gP%%̠jo0I$f1 Gf]$UY]&]Q+џ <9URT͘g'IUMv\^:+ Hyy0Ibv䮏o(+3gP%ϠJJAlYuΒ$I55Yyd@>7iGI45ܻ??J-?h?8TI	3-~r$IRs? ȫ.e2H$U&;6ҿe] bTI3fP5[{>$Ik5EG [:$I\Lv^]F[W{s?_A?*)aUc?f$IJ= ctݚ7I_ξ5gů(3_9
@TI	3w&ITʨWz$6`ʬ8tk$IfRx2|B;t	@*URT͎$IҬ6_	 Nݓ^1N4õ{v-|[KΉ>TI	3CwF?7I4g7 ӭ{K<I}[W奻yៃ L'*)URfC$IҌ7[R>I45fetݚ2x|=t斅0TI	3M$ICo" f=-OfRo)^zQ8,eP%ϠJJAl$Iњ/(ݓݜ ,ѧΊ$%ݳk/S _ɠJʟA0~j$ik{.~p=l?Lvn8$UT;xLv^.:tW?/
 *)UR_ݱL$b͸[]}o$`Qivo/)ǗcJgnYg /*)UR+$IWI Kfo<uep?
? @0gP%%̠j-
kIl|;o  J'D<J`#e*~tOzzg ,URTMUG2F?3I4C5߲xA o cRj.uk53 A?*)aUӭG?1I4C= kZydivq)IzMFs`ҙ;$3 TI3fP5FW$IҬԶ_ =)IZmJ3Ap3xg ƠJʟA0%Io} C`I>2{CSl JʟA0)R&'&If7Hetݛ?>%i|/{[}3_ 2gP%%̠jz/xY$I3P;[zo '?F%i:jƥٽ/^Szk)C0gP%%̠jz>vR$I3W= D]?Q*Ij*[/)'cKg?`TI3fP5~$Il|;o x2q*IULvl*-ayM?`TI3fP5VUx$I<xG DJR=Istݚ2x4 :*)URSE?-I45{ۏ< p@<4ntf2޶.{;!?àJʟA04IOK$MqN	w @{3$Mk]e|%e_wlzj^ 1gP%%̠j:-jnIQs-{ {~7cVH{.++/=?c'ΠJʟA0)Rƃ%I~q ?m%ij{r5e}_WS 1gP%%̠jg%IGo 8~K=kƥٽ_ſ0wHN 2gP%%̠j?J$MaͽJga lwR6WҬ׶y2}s~tV3 XzURTMɎMJ$M[mSz$2O_I3VL̗{7, `P%ϠJJAՔ[V$IF׾1KG)-Wuk` A?*)aUӥ~R$ijtO|Z Kw֏2FK^3.emW[: 0gP%%̠j{OJ$MY bIj*Co<e @nURTMo~R$izq} VZ&w_,22ܲb[ 1gP%%̠j4_$IҴ4#h3=џ̒v䮏5gEQg<? 0TI	3SSJF?)I4%-|Q} \͒fRx2|¾J" `6TI3fP5=rs$ISR 1L>hIvϮ2ٱ̗/+UG ?TI	3$I~)txHzߥ7,/Ӟ 1gP%%̠jzLvn~N$i
ܾ9ZjIӨo<u͙ep+K _URTM2D?'IfRzk ZR&w]-kLJ{{o[_O(uǖSn  <IURTM[8)I)h|9w n7ܴýU&;6}_w3>  URTMe$IR`{5 -T}_ݷu  X*URTM뢟$IJ쏾i  W:[&캡[S/ǔܲ TI3fP5{o~J$)qJħ4 I_ʸ1.宙[?(^T:+ &URTMUO]{$IOo HhEKjYƷ^RO <URT[g$Iٵ8Ўi  澛?Υ*k.~5W]t\>:Y TI	3oH$%n Ȭ+m?ҥ&^ןS/ǔܲ> A?*)aUo0I]:+g  .-iCw__w  2gP%%̠*K$IR{u- Ӡ{3FWdǦ22_)g `TI3fP[gҶH$%}xg~ \wI.~:/]}t?[  ΠJʟA0|$IIo 6ۮQivo/)ǗcJg  jURT6뢟$IJX}tN L/,eԍmmSݟ)QxR TI	3m|OH$%leE _~R{vɎMee7,/S  OA?*)aU5$IR= Z[?5CG+SJ//ӿ5  *)UR_.I?}c ӮR6c_X3.em}\[{L 8xTI	3ʫG$ek2*7|G `|џ^۔;S+Jg)o eP%ϠJJAU^+$Hd-n ůbo{dǦ22_f  TI3fPuG$%kTp ~?Uipo켺[S}Y  cP%ϠJJAU^~>$)Q[ 9++Df}_ݷ;ť3wH  *)URZqX)~$IWo A.UƷ^8;tV=5 A?*)aU9OG$%}Yqh js@vϽecSn/K焿7  A?*)aU9.#I5 fYQʰ}IΫ5e[{L `TI3fP7D?IvtOzF nxEڟ&캡>uvwKo! cP%ϠJJAUN;~:$)I}  tVQ>j|p	wΏ#  TISA0$IJR-?~  kѧS{/#{ʳ  <*)URg#I4 &w~$D2yu]6_zk)e   /*)URF$%ip+o zQ)m}&Lg͸4__wl?%s  x2TI	3gxşF?Iv}  *5Sa*j}[KΪ ͠JʟA0|ƟF$%h k~^iFjWOmX^}s  TI	3gsk$I6{ ?/zv3p  0TI	3ʧ=l$IRMH |ZڇwF5^֗Jݱ  A?*)aUtO'#I4Uw .2k{vɎMΪw  TI3fP¿h$IzG$ d1LL]2yum]]iύ  1gP%%̠*F?ITy	Y ǯe*u9.~e 40gP%%̠*뢟$I~,f 3-j&ٽ/'cKg= 42gP%%̠*F?ITq+ RqvϮ2ٱ꾓  
*)URriG?ITq.^ 2eUJw  ̠JʟA0<ks$I5׶{o -;K{?zer5et,7~W  W3gP%%̠*y?\$IR5\~  Oc'caRx2|B;tV  TI	3cpD?ITq0}  ONv6h*p|oX^<+?  TI	3ct͙E$Z,~=p <y#>Ϋ5epq  aP%ϠJJAU\$IRMH  ~Ѿ2x|=t  8(TI	3ʣ?G?ITi:V %/CwYyd}  1gP%%̠*KiE$X3.S)^ e*ݓ  ʠJʟA0zk/HJܹ%V    *)URr_OE$UD*    aP%ϠJJAUeS$I=
    ppTI3fPuOE$UXsw
    pTI3fP䮫$IGW)    cP%ϠJJAU$I/S    ǠJʟA0uO|Z3$I>ҙ[~     A?*)aU凢$I    2gP%%̠~w<H
\t\    \URTo?~&$I;    8TI	37G?ITY?~     A?*)aUvE3$I5    8TI	3_3D$UV?~     A?*)aU[VʨL$IRM;;    8TI	3[wOD$U(    0gP%%̠nu/~"$    XURTmp髢$I9/	Q    aP%ϠJJAU݆~"$FҙJ    ,*)UR6'"I*jrU	    tTI	3s~"$FW~     KǠJʟA05~6H	O    cP%ϠJJAU斕2E?ITKm[<;F    A?*)aUC$UTs-	    TI	3W~$ׯO    eP%ϠJJAU|y$I55	    TI	3?~$zg8>    A?*)aUm]<$IR-M    XZURTk~${o
M    gP%ϠJJAU&;F?ITIM    gP%ϠJJAUڇ~$(6    A?*)aU;0yHJ?'    3gP%%̠NGG?ITK͸tV=5>    A?*)aUu!I*    aP%ϠJJAUG?ITI헆&    @*)UR4$INM    URTi!I*ipo&    @*)UR4YOC$UR?~     1TI	33~$ڦtV=56    bTI3fPUF?ITA̓w%    @*)UR>!I*hrw	    ǠJʟA0:Q7iH
]    cP%ϠJJAU}'=#YHJo     A?*)aU$Iy?~     qTI	3J$-=	    ǠJʟA0.~e$I5ԌKga	    ǠJʟA076YH
j3.    bTI3fPUN~$&wn	K    XURl    IDATTg$IoK    XURTgg!I*hx߅%    @,*)UR3Ǣ$I
K    XURTէg!I*w	    ˠJʟA0{~$    eP%ϠJJAUe斕2E?I]۔Ίo     A?*)aUu'!I*{]    3gP%%̠.7}O$Iws]    3gP%%̠.s~<IH
?%    @<*)URҿ𗣟$IM%    @<*)UR2xE?	ITA~     TI	3$$IR76.    TI3fPUN~$".    TI3fPU'$$IRSw	    ϠJʟA0o$$IR|o]    3gP%%̠.$I)
K    xURTesk$IѵM84.    TI3fPU[$I
?~     u0gP%%̠.#D?	I\o    URTե~$)f׍7	    P*)UR*R6IH&wnK    *TI3fPU)ώ~$7%    @TI	3G~$7~     u0gP%%̠49H
]    A?*)aU$I~     u0gP%%̠ˣ$I~     u0gP%%̠_$IR.    A?*)aUD?ITAwJ]    JʟA0z769H
    URTcxE?ITAs2.    `P%ϠJJAU=F?59H
    A?*)aU}bms$I[{L]    JʟA0zo<?9H
    A?*)aUzIs$I]    A?*)aU I*{    URTcsks$IYqX]    JʟA0z4$IRtaM    àJʟA0z4$IRpm    A?*)aUh$IRpo    URTcP%Il~     0gP%%̠_#If{o    URTգA$>|WM    àJʟA0J-+m$I
y    A?*)aUXydS$I<p{]    TàJʟA0:tO~fS$I|    URTա I*    A?*)aUu I*    A?*)aUu I*uc]    àJʟA0:OA$UPO%    @=TI	3Cm?$IR5|".    aP%ϠJJAUdS$I4    A?*)aUuG?ITAU    W2gP%%̠wBS$I|w	    P*)URKOA$UP    URTաΗG?ITAͽ7%    @=TI	35)H
j    A?*)aUu\ I*ٽ=.    aP%ϠJJAU*)H
j-.    aP%ϠJJAU I*yw	    P*)UR0x߫$Iυ%    @=TI	3?~
$GK    zTI3fPU$IR~!.    aP%ϠJJAU I*{_]    àJʟA0:F?ITAm    A?*)aUu~/$IP]    àJʟA0:?WOA$Ш~     0gP%%̠U$i-e	    P*)UR0_G?ITIG&    @TI	3A$Irݓ~     u0gP%%̠MS$I=[o    URTJ$}/M    :TI3fPU*Izk	M    :TI3fPU_$IR%    A?*)aUu0$I_    A?*)aUu0$I_o    URTa/)HJoX~     u0gP%%̠~C$IrM    :TI3fPU:)HJl<>6    `P%ϠJJAU?$Ie	M    :TI3fPU<)HJ~/o    URTa?~
$[o    URTa鏣$I5g&    @TI	3?~
$ׯM    :TI3fPU^$IR%o(6    `P%ϠJJAUOA$U&    @TI	3`D?ITI	M    :TI3fPU~
$o	M    :TI3fPUů~
$ڇ
M    :TI3fPU=)HJj{&    @TI	3C]$IR-5    A?*)aUuoX$IREuV~     TI	3C9)H>:>    TI3fPU:)H    gP%ϠJJAUz$)HZ$	    ϠJʟA0: I*υ'    @<*)UR[OA$U     A?*)aUu{$I~     TI	3C!)H^	    ϠJʟA0:tW?/)H]sF}    3gP%%̠S$IREo >    TI3fPUUGE?ITQ'    @8*)UR* I*jr5	    ΠJʟA0zf$IR%5_~     TI	3Gv$I;6   gΟvP\PQ)2LdjmUK[QZu:"c[E''IHY!Ȣl$@Bd焄B +1 	9IoP$gy]9>?333jǴ@s$I4͖֕'    @-*)?*)0vL9Hlt   333j۪$Ij?Z~     1A$5ԣ(O    ZUR~UR`U IO>    jTITITc~$gN}    233jV?IP>    jTITITc3$Ij'    @-*)?*)0v?9H}	    PˠJϠJ
̠kR$IRCoyO}    233jë$IjW'    @-*)?*)0v/P$IRCMY~     1A$`>    jTITITcpk$IjF    TITITW?IX#S~     u;eA$5VF    TITITw/W?IXF    TITIT֟~$羦F    TITIT{̿~$_~     u9$IjǗ(    @*)?*)0vt6>9H|N    133j'fi$I57
    PƠJϠJ
̠-r$I5y    cP%gP%fPՖ?[$$IRCM    AAAU[&_t$I|(    @*)?*)0L'!I{so    AAAU[w^R$$IRcNzQ    033js$Ijo    AAAU[FןT$$IRc.~}    033jGT?	IXë.Q    UR~UR`Um\IHݴF    jTITITe?~$&w_]~     5?OB$5o    AAAU[zIHgK{)    333jKV?	I`CN    ֞AAAU[o'!I{O)    333jK?\$$IRN}I    =*)?*)0tzZ$I?5w
    n6$Ije)    333jϴ`$I5    X{UR~UR`U|B$5o    `TITITgrG$Ij>U~     kϠJϠJ
̠=.~$m7
    3g!Isw)    233jpB$5X)    233jW,$IRNyq    -*)?*)0g!IN    ֖AAAU{gYH^qH    -*)?*)0Ng!IlS    `mTITIT~$[*S    eP%gP%fP՞?X,$IRMN    ֖AAAU6|K$I-6ϖr    *)?*)06OC$5XM?R~     kǠJϠJ
̠Mm[$Ijމ/,S    cP%gP%fPզ~$~N    ֎AAAUƷiH|    `TITITit۪$IjGo;    X;UR~UR`Um^v`Ӑ$I6;    X;UR~UR`UmOC$5[    `TITIT+$IjaN    ֎AAAUz'BӐ$I9
    6=yOC$5Z*    033jSgӫ$Ij//U    aP%gP%fPծٰ[<$IR.;    XUR~UR`U>yH^{\    *)?*)0vMyH~a    *)?*)0vo=yH<p[    *)?*)0v>vB$I-6ϖ*U    gP%gP%fPծ$Ij]~     ϠJϠJ
̠]^W<$IRNO
    ?C$5ZP~     ϠJϠJ
̠]_X<$IR/;V    VAAAUGx$I6ĩ
    C$5o    `TITITm6W?I`/~N    VAAAUۦ]D$IRu[    X]UR~UR`Um{]$I}O*    233j$Ijީ/-U    eP%gP%fPն'U?IhV    VAAAUۆ\D$IR?rl    .*)?*)0{m$I6[    X]UR~UR`Um'"Imo    `uTITIT{ܾOD$ڰ;[^ZW~     ǠJϠJ
̠m7|o$I9Y
    zn6$Ijމ/W    UcP%gP%fPվɃ\L$IRG
    z7rY3$I6[    X=UR~UR`U}D$5so    `TITITox$Ij>Y~     ǠJϠJ
̠}HVvgK{+    033j_ߨ~&$:o|v    *)?*)0uA3$I;    `uTITIT~&$q    *)?*)0 KfQHF~M
    *2LYT$IRo=V    VAAAUg~*$&R~     àJϠJ
̠*V?Ijly    `TITITe^yhS$Iyӏ+    3330uOE$5\s    <*)?*)0^VT$IR{m    <*)?*)0%ID7U~     +wB)?*)0CYT$IRÍo^    VAAAUu٨_\$IRM^    VAAAU-E$x8[
    r^Y\$IRu|N    ,*)?*)0O~.$z^    VAAAUᕇU?Ip^    VAAAUy~.$F{    XYUR~UR`U97>$Ixe
    rt٧Hn^    VAAAU2MOF$5\gw,    133/OH$=^ݷL    *)?*)0,~2$g^    VAAAUэU?Ip.W    cP%gP%fPex'#Int9
    rGOF$57+    133;$Ij`~    XUR~UR`UY:Gh$I=7    2¬{6$Ij;f    VAAAUC~6$e    *)?*)0<-U?IpP~     +àJϠJ
̠*$Ij֫    `eTITIT|hH._~     +àJϠJ
̠*OU?IxCf    AAAUH{^Y    =gP%gP%fPsس$Ijf    AAAUu٨Wt$IR<f    AAAUU?Ip[-W    =gP%gP%fPi|EOG$5    `TITITe}$Ijh)7    g2.~}ӑ$I}O,    133?󷫟$Ij^U~     {ƠJϠJ
̠*I$,    ]PϠJ
̠*S~:$F7]~     {}l    IDATƠJϠJ
̠*״H|{    3UR~UR`U&~Hg    }UR~UR`UF7V|$IRu}~    >*)?*)0\K7T?Ix3f    vAAAU$Ij%,    333}T?IxOf    vAAAUU|$IRM>    }UR~UR`U٦/T?!Irly7    {M	IO    *)?*)0lN~B$f    vAAAU	I|hf    vAAAU^U$IRn<f    vAAAU?]$IRM>{c    *)?*)0l	Ig.[    ]gP%gP%fPoU?#IxݣW~     ΠJϠJ
̠*xUH$5^ﴗ,    3337g$Io-Y    ]gP%gP%fPo~F$F8f    vAAAUU$IRMx    :*)?*)0|ݷT3$I7Ζ?n    vAAA8[g)I    %UR~UR`UaȽOI$5^,    133-U?%IxK֗,    133^$IRnT~     ƠJϠJ
̠j>.$Ior7    kCߨ~J$&O-[    gP%gP%fP5>)I[~     ;ϠJϠJ
̠jNlxʗ~uB$    iUR~UR`UcI$5o    `TITIT͏U?'Ix/,Y    gP%gP%fP5?WV$IRMf    vAAA$I
sw-    133ݷls$IN    9UR~UR`U;$I
hpޟ-    133/U?)Ixk/Y    cP%gP%fP5_w^R$IR㍷^Y~     ;ǠJϠJ
̠j=IIƛ-/+[    333/II:P    AAA|OJ$;W    `KgU?)Iࢿ*[    333?J$5So    `k$Ij}/Y    333?S$I7ϖ]~     O̠JϠJ
̠j.g%IO    <1*)?*)0;J$?w    OU?+I    TITIT͡{f~Ӓ$I7=w    7U?-Ixm[o    TITITͧM$Ijt9iw    $I
+[    gP%gP%fP5gnӒ$I{m    <>*)?*)0=n%I]    x|UR~UR`Usoͦ%Ior5w    T?/Iz^w    U?/IP-    c333_ë~^$)([    fP%gP%fP5%I^vP    <6*)?*)0=K$4    xlUR~UR`Us쀧fq$I7}    xLUR~UR`UmOW?1IP*[    ofP%gP%fP5F7S$IR@_X~     ̠JϠJ
̠j/=In    AAA|'&I}    fUR~UR`U{󫟘$I
hruw    gQIvgT     _ǠJϠJ
̠jM>{c3$Iu٧n    AAAxZ3$I    zUR~UR`Uo[$IR@+)[    gP%gP%fP5zIƷn    AAAL$4}    zUR~UR`U`il^$IR@CQ     AAAbsMS$IN    **)?*)00؉OM$4/    ãG%IvX~     _eP%gP%fPz+OM$4    **)?*)09OM$%4̖7<v    ̠JϠJ
̠jqL~n$)q-    TITIT-˪$I
?,[    /333Zk\$IR@Ï[~     _fP%gP%fP8羦I[*[    /333Z~I/Ζ*]     *i23ZOͦ''I    0!*)02}''I    0!*)02''I^qH    TIAAb^IƟ~    TIAAbON$4]|    TIAAb''IB    AAAՂYk6,W?;IP.    k$I
h-[    `TITIT-uo~v$)ѧ*[    `TITIT-Z$IR@([    `TITIT-	?_$IRB鬳ѭ    O砧}$IҎ    ,2*)?*)04ݶI    AAAb'I]r    ̠JϠJ
̠j1/=I&P~    "333ZL_^$IRBlySo    XTUR~UR`U{s$I
{ܾ    ,**)?*)0n6?R$IR@wA    ʠJϠJ
̠jq\$IR@Ï[~    233Z\k~~$)֫    XTUR~UR`Uk$I
h>[^ګv   EdP%gP%fPoO$=    ,"*)?*)0vfI$I|e    ȠJϠJ
̠jM	JWZ~    "233Zlή~$)?n   EdP%gP%fP~$)iwlyi]    ƠJϠJ
̠jN'(IBGo    X4UR~UR`U$I;S*]    `TITIT-uig(I^~p    ƠJϠJ
̠g~$)-    hn>J    X4UR~UR`U~u3$I!u    AAA7d3$I!N{Y    ĠJϠJ
̠{f^S$I/;v   bP%gP%fPţ&~)JƷ]P~    "133QV%IR@/~n   EbP%gP%fPţ羦)J:=v   EaP%gP%fPţoOQ${篗.    (:MFQ$4d    AAA_1MQ$4    AAA_1Q$4}    AAA_1U?GIRg.    I/~$))/.]    `TITITOͦ')I|o    XUR~UR`U|;$I
h|    XUR~UR`U|MgW?IIw    ,*)?*)0*W$%IRH7|o    ΠJϠJ
̠{ǯU?IIRK    ΠJϠJ
̠9$I
i)]    `TITIT_l$InT~    333o_$IMY~    333/X,%IRBsw.    0F3~YJz'r    ̠JϠJ
̠o9Ǫ$I
ip_.    0&Kf)I}    AAAe)InR~    <3337Y4%IRHCQ~    2337W4%IRHS~v   yeP%gP%fPcOӔ$I!>    +*)?*)0*^i{$IoyO    sʠJϠJ
̠3ze$IMn   yeP%gP%fPn>yJ:@    ȠJϠJ
̠ߴ_$I!N}I    ȠJϠJ
̠=f)IB^v   ydP%gP%fPZk6o~$)m.    0x"WV?QIt    AAAOd'*IB    *)?*)0*H~OT$;7o    7UR~UR`U<1T?QIo    7UR~UR`U<fg*Iqq    sƠJϠJ
̠oJgKo    'UR~UR`UpT$9o    'UR~UR`UH~T$?    *)?*)0*v{>T$4    AAA;l^T%IR@-.    0GWV?UIдȗշ    *)?*)0*vpOU$=o    UR~UR`U$I
ѻv   yaP%gP%fPOS$I!7U~    033b,5W?WIxU    	*)?*)0*vxU$%4̖]~    <033bg7Y\%IRH7D    JϠJ
̠ߴ_s$I!    *)?*)0*vV}$I
ix[o    UR~UR`U촥f'+IsM    sJϠJ
̠]1OV$%4ϖ7<v   tUR~UR`UTd%IRH_P~    @:*)?*)0*vE]~$)yR~    @:*)?*)0*vET?YIo    HgP%gP%fP.YZ7vPl%IR@T    @8*)?*)0*v$IJh:uzZ    U7V?[IR.    ̠JϠJ
̠];eV$4    $333bWug+IBݴv   dUR~UR`U~$)w-    ̠JϠJ
̠1+IB    233bw>Tt%IRHS_R~    @**)?*)0*vG_~$)e.    ʠJϠJ
̠9gJw\T~    @**)?*)0*vtۖ+Iv-/+]     AAAkwU?_IRS~    @"*)?*)0*vࢿ~$)Y[~    @"*)?*)0*vWU?_IpQ    $233bwul:~$)]o    HdP%gP%fPŞK$I	\~    @*)?*)0*wT?aIR}o    HcP%gP%fPŞ\',IB    133bOtOX$4؉    133bll<~ƒ$)go]     AAA{jrX$%4:~{    IS^%IRH_X~    @*)?*)0*TK?    $133bOu۷KF<v   $UR~UR`U<OY$4ݶv    UR~UR`U]$I
+]     AAA+a,IB.     JϠJ
̠?w$I
ix    RTITITG>)KƷv   UR~UR`Uui,Ivۡ~    UR~UR`UV?gIR+]     AAA+ex,IB;    $033bkY$4    TITITR:<9K&wv   UR~UR`U;$IJhԟ-oxJ    333b%>yF$I!uߕ.    :*)?*)0*VIKv   TITITz'|$I!>qj    333bEl<~֒$)Ƀw.    8*)?*)0*V$IJh:uyF    -333b>g-IB    ZfP%gP%fPJ珪$I
ix    ZfP%gP%fPJ'$I
i.    2*)?*)0*V^i{Ӗ$IM{͖/    (*)?*)0*V3W?mIR.    **)?*)0*Vë$I
.    **)?*)0*VCWT?mI𚷔.    **)?*)0*VC?\%IRH{+]    UUR~UR`Ucޣ[Z4鐤	k&CfMHT	X3dԔ@HW+[/*dc,Ȳ/±6 |"c	&"ߍϾ:G!:G:g?{`爏u$IJP[O}I    ȠJʟA0*KUoI7.    0TI	3bt_?ޒ$)I/    ƑA?*)aU,֧'-IԻ    ƑA?*)aU,ƺWR?$)A3.    0TI	3b1vG\$%qχ.    0nTI	3b1\$IIj]    *)URXLϿ'#.IԽ~]    ƠJʟA0*S߈K$R    ƠJʟA0*)/.׎KUc    #URT߻5c.Iܸ4v   qbP%ϠJJA{YsI]    `TI3fPbko{G\$%w    *)URXl͏sI#{o    !    IDAT'URTVS3uIAL91~   1aP%ϠJJAпKuIyo
]    `\TI3fP(t?-.IԹ    *)URoK$yE     JʟA0*Fq櫢?$)I.    0.TI	3bTgK$5>K    *)UR޾mwI~    80gP%%̠Q\菻$IJRw    ƁA?*)aUJSq$II<tK    JʟA0*FyI~L    TI3fP($IIjm^~    @4*)URK$uy_    TI	3bW_yI޾m    D3gP%%̠QjyI.    ͠JʟA0*FjR菽$IJRC    @ *)UR_K$/}{    TI	3bԺ_X^$%in]     A?*)aUZ$II<ts    TI	3bԚ菽$IR]O    TI3fPȭ:T'?$)IMo_     A?*)aUDgGG_$%s{o    bP%ϠJJA:;?$)I}.    ŠJʟA0*"nG_$%    D1gP%%̠~)U$IIj|    `P%ϠJJAQO~7/IԾ    "TI3fPEޝE%IR7}$v   URTD%IR]     A?*)aUDiI^L    F͠JʟA0*sT$i.57/    A?*)aUD<tK$II|?.    0jURTO@$%    F͠JʟA0*"/' IT=`    fP%ϠJJA' I//    0JURTj1j<$IRڟ    FȠJʟA0*{u3$II    FɠJʟA0*urj3$II<    FɠJʟA0*.g IS_~    TI3fPE,$IJR_    `TTI	3bTO$IR:U    bP%ϠJJA~
$)Io]~    TI3fP8OA$%j<QW~    (TI3fP8hnzcS$Ijn'    A?*)aUS~~'9H$?    A?*)aUn~$)I6.    0
URT1.7$IR~    (TI3fPŸho{Gs$IY8/    TI	3b\47 Iպ    XlURT16VSOB$%{    A?*)aU=_~$)I~    b3gP%%̠qҽnm$IYL    XLURT1NZ[G?	I?L_    `1TI3fP8iOB$%ce    ɠJʟA0*MB$%w%    ,&*)UR73Ǩ$I\^    ɠJʟA0*MF?IƇ~1~   bP%ϠJJA㦵yY$Ij_    ,*)UR;t)nӐ$II~mc    ĠJʟA0*;$IJo    X,URT14$IRX    A?*)aUg4iHD    ,*)URG͏6iHDu_    XURT1VS3C$%//    TI	3b\r$IIbO:6~   fP%ϠJJA{iC$%y    XhURT1Za$Ij_    A?*)aU?<$IRz_t    ͠JʟA0*YOD$%z    A?*)aUˢ$IJTヿ~    B2gP%%̠qֹ}OD$%}ɿ	_    `!TI3fP8k'"I    A?*)aUS_ZʠL$IR|=~   dP%ϠJJAnȞg"I4:-    aP%ϠJJAwۦg"I    ,*)URw+L$IR׭_    `TI3fPŸkn|]3$I}    ŠJʟA0*ުcK~.H,uezo    X URTAD?I7/    TI	3"gD?I5_    `!TI3fPET$IR
_    `!TI3fPEK$IJT|L:6   eP%ϠJJAYT>\$IR/    pTI	3"޾ˣ$IJT?_    hTI3fPEk\$IRz{._    hTI3fPEF?I    8ZURTƩ/-eЋ~2$)Q    A?*)aUd2x'#Iվ    8URTIMOF$%{    *)URȤ}Ż$IJn}    0gP%%̠L_d$IRAi{E    GʠJʟA0*RYulE?I֖ߋa    TI3fPE6{wF?I/    pTI	3"gD?I7/    pTI	3"o~6$)Sv>o    8URTMcg#Iڼ,   #aP%ϠJJAU>t$IR:_    A?*)aUdwyӑ$I    	*)URȨs$IJT~L>.   2gP%%̠Z)Hd5yC    eP%ϠJJA)R#Iչ7    ̓A?*)aUd5x#I߆/    0_URTUMG$%j>UW~    |TI3fPEV+|$IRg>   0gP%%̠_|$IR:    àJʟA0*ZulE?!I]0    0URTYޝOH$%z    àJʟA0*2pz$Ijn'7    ̕A?*)aUdֺmOH$%G    seP%ϠJJA5/~B$)Y=0    0WURT]H$%jv_    `TI	3"޾ˣ$IJVÿ~    \TI3fPEvk$IRV0    0URT]7E?#I0    0URTީ/-eЋ~J$)Q'    TI3fPE$IR_~    TI3fPEn=7)Id/}{    cP%ϠJJAuо]OI$%{7    A?*)aUAs뢟$IJ౽7    A?*)aUªcK~.9ILUUi   (kNaTI3fPE]$IRZ-   ǗƥmEݶ+ճTI	3.7$IR_h   뗔%'`W)H|*?'gP%ϠJJAuѺI$%k7   BZ[Ω߿T'#FvϠJʟA0*Â$IҼKc{   ȣoyE{lUǄwb8*)UR$IJ̿}    Ǘƥm۶gFP)/PURTQ'}G?)IM	a    xfUJ6oURTQ'k$IR~    qfSS{OgP%ϠJJAu:MOJ$ec   jyYim^V:;Vޞ-epp_|ΠJʟA0*jԗ2E?+Ioc   zX}|in\ZVee\k~ʠJʟA0*fȞg%Io    %{㙥`W)fT_gpURTQ7[ύ~V$)YGa   XҺͥso/%{<+TI3fPEݴxg$I٪81   Ysbim^V:;Vޞ-epp!ԭϚTI	3n_$IR    Js޶two82	eP%ϠJJAR~Z$)Yݯmc   h_RZ[}|nLjQgP%ϠJJAuԿwgӒ$I<7   ^c}~o/?ڗIFgP%ϠJJAuԽ%IUUqυ1   QXsԎgK73~r+ʠJʟA0*u[$IJ   Y}\in\ZV`W)N/oPURTQG3_$IRº|"   ^XcںtvN=_*3G	s_opURTQWճD?/Io0   Jc}~o/?6mf8*)URˢ$IVUMw   LJ7ΎgK73FS3?eP%ϠJJAuչ}K$%}   ǕƥmEPvkGqD?eP%ϠJJAu:MK$%w'   %uy:OGw3gP%%̠:zOL$%kķ   HڼЯ{Y,|͡?a8*)UR#{$IJXc   kS'}Wl)Ju^yb(*)URV$i/ww   ǕY/+Yz~z)nZ1A?*)aUw$Iw;   4/)KgT^?kgGgTI	3faI6xw   BcIyYXYz{/+FX׿!TI3fPE:Tg$IJXC   B:a_Dn_۳+D|)PURTQw{$IRV1   pV{h<?-[)o/ߍq[cX^ʠJʟA0*{L$%ww   UcںtvNj>Կ/TI3fPEݵ.~k3$I	}   Xڼtv}E)3pURTQw3_$IRҚ[  	CoۊһmSWJ5Y5j?eP%ϠJJA`o$Io,  `~u_Kw?^+cռn3A?*)aULˢ$IJ}   PTk9UdΠJʟA0*&A꿌~j$)a3=[  k_^ZΎgK7^igP%ϠJJAuoF?5I'Y-  @2/͍KK{ۊһmSWJ5Wzf>oTI	3b"R&I67]2   k_rrPvmF8+͹TI3fPŤ<'I;  O./S{OD*U'ΠJʟA0*&Es$IXgLOT-  5ּ6/++KoϖCOY53gP%%̠IѾM$%uޛo   Ks޶bWj#UeP%ϠJJAbaI#So   Wuo<*یS
zpURT11VS3ON$%lo   Xc+J7Ω߿T'ԔƦQ3gP%%̠IҿON$e-5/e   8ZΎgKS4U-TI3fP$^Z$IIkm[  ܸ(KRU5eP%ϠJJAu[$IJZ2   ~Iim]^79K㢔Lf8*)UR$3~.I~   LƺWo.S{PeUTI	3bT>$IRƪ4[  ֜XZΎgK7sm`(*)UR4E?;I%'2   >47.-m+JwC߉OeP%ϠJJAs_F?;Iޭ2   4>ҾߖW?ZTJ㝤۠uTI	3bҴg'I6x[  `5̡_wJRMQN¿v0A?*)aULS_:Á$Iґ/3   `͉k]dt$cϠJʟA0*&;$IJZw2   #ܸ(Jma(*)URD[>$IRzw^~   ,%uy:ZD8&i:χa8*)URD3$IґT=h^uL=  PޡԷ?_ǣ4ªs_ΠJʟA0*&Qc$IRgZ=  pDN(sP:;Vޞ-epp_)Uc_ʠJʟA0*&Ҫc[V$\{  pVWJRz$YUWeP%ϠJJAE??I׆2   ?~Iim]~W>H᪦b8*)URT/'IkS_~   ڼЯ{Y,'%IIH43gP%%̠I:$IJ\낷3  :ЯݥgKWJUEX$&U}/CTI3fPŤj}y)~$II`=  S#)m+Jw?^;G I5z{gP%ϠJJAl]OP$%m  _cںtvNj>㎤	zgP%ϠJJAwۦ'(IVUG=  X{Rim^V:;V2xgP%ϠJJA};$IJ̯g  15uBin\ZW{v<58jc$X'5TI	3b5?A{    IDAT'(Isa=  G^3/]two(J鵢d95x[_CΠJʟA0*&ڪcJ|:JU?6{O4  H女so/UO$鈛2A?*)aULD?CIٿ~   奵yYX91DZpURT1f-2I#s  `>47.}6-D!I=_ʠJʟA0*&]2J6  W/9two(J鵢Đ7xgP%ϠJJA-3ItZeԗ4  Sgj<ӄ$En	pURToE?EIo	g  hyYim^V:;Vޞ-~u$<gP%ϠJJA8?)Juw}0 ܸ}3H/IsM_ʠJʟA0*xQi_(I7x{  &W/9yv<?n3GIJ]¿3A?*)aU<~$)sUUg* :Za^bZD_T]TI	3Uǖ\s$I"7  $Xڼtv,=[3_&׆`8*)UR_~$)q=3  Ks1aWj}KD֕ʠJʟA0*8d$I:Ҫ+ӫ	i  `lu{㙥`W)f	/IuI	3gP%%̠
I~  @ƙ?_ZA^ﾦTͧOuIҐz_t3gP%%̠
iR*IJu7  ԚKkٱl)$%w'㿟0A?*)aU'$%IR_~  Y}|in\ZV~u_}KW?=TI	30IJz} @=4/)KgTR[uo8#{TI3fP?$IJ^ouM  5/.x~<$߇ΠJʟA0*9$%IRzmi  `5'eceRRUѧ$)εPURT߱Ru~$)qsU5  0cqqiio[Q7];g$i؆b(*)UR>YJ5z}M dj_RZ[}|n#<$y+TI	3ֽg)I׹7  X3~uߵ(K5}0$%ΠJʟA0*a,%IRi  J7Zޞ-epp_)U}JjP1A?*)aUg\$IwJc  Z}\in\ZV`W)v+Ii {CTI3fP?z)I׺7  94/)Kgԡ_z&$MPTI	3D?MIޭi  ?'e~uJcѧ$ikΠJʟA0*q!iJU>~  l<S{}TU*I53	PURTk?G?MITm] >47.-m+Jw?^;$$5z}Q2gP%%̠
^	tS$%s{  EcںtvNj>}~JtD5?WΠJʟA0*xa<%IR|1 5֞TZ}{/+F$-XgP%ϠJJAM~$){viyY] <LpW]۳+D_$-Z_TI	3־)Ij̯k  yMio[Q7]Z'$I#mԗ?f8*)UR5ֿ:yJԽw  4/wvNj>}.J¿G3A?*)aUU=D%IRi  &Qc+J낷Ηs￪T$4$iw¿gsxURTO{i$I5ំ5  vʋK(ϿZO|>%I9,*)UR'XD%IR\w @4>޶two(J鵢O>IRV=}ouϠJʟA0*ɚ!JԿ+w @VKJk9Udy'IRm<A?*)aU0Ky>Jz k}yim^6l[3$IտA?*)aU0\ޝT$ՠok  Ks_׻mSWJ5>$If2gP%%̠
^&Jsa] ڗ\7]t'$I_΋oϠJʟA0*w$IAU2 `T女sjoOFc$3gP%%̠
k=A?Jڼ, Xh5/s:;Vޞ-~u$IJQ3o	ϠJʟA0*8cwE?UIT7~  Ǘƥm<|{) ̒$IGX)TI	3*Ij౽w g]t'$IZ:{3gP%%̠
}D?UIT iuukKkKz&t$I:}pxURT5>E?UIT:o һ3ѧ$Iq3c3gP%%̠
z{U$ՠwk  ^̝"I&֧3gP%%̠
榷*IP]k_~  C7G_J$i53gP%%̠
󅿈~$&.~[m O|;L$I#_	A8<*)UR`n$IIm  ~Tcg$Iq3~6TI	39:n#JT}2 Ē$i>7gP%ϠJJA]뢟$II3}  N}Iy$IF]0'URTu?-J9~  7K#I4oƠJʟA0*օd%IRM| in\}I7x9jURT5N{Tg+IPUW7  3}I7x9jURT~$& `[ɫu7scP%ϠJJAOMV$դw~  h_O#I4
A*)UR`~l%IR]KcI @}I׻1gP%%̠
_~$F/7 @Ӣ"I47A*)UR`?t%IRM} wH$ε~07URT+IjRzLOT} L6,$I#}ŻoƠJʟA0*~$F.xK} L7ED$iĵ.1gP%%̠
yoD?]IT7~  mwO"I4⚛~07URT:n#JT=2 XUH$~5anTI	3#?pc$I5jƢ `ű>$I҈k{ETI3fPG{W$ըuk `25/>$IҨmىTI3fPGuy$I5j Lͳ-$I#zykURTiJ$IZК <;$I#npp_TI3fPGn$IQ2 &O{; I4]~0wURT~^$I5 </3H$oΠJʟA0*8ri$Iuƙ?~  {YW$Iq[	A;*)UR5?OX$լ
q '$Iqք ̝A?*)aUpt~ƒ$F_~  e-'$Iq+oΠJʟA0*8:om3$Iu,kNq Q=`$IF\=aTI	3ӹX$լg( &JI4Z;93gP%%̠
Ns?~ƒ$fL LWG>$)';3gP%%̠
)/.׊~ʒ$FU/s I45>l$eP%%̠
^$IY~  ׺g$I
ȿȕA?*)aUp7~ʒ$f~  G=$iu7cP%ϠJJAOY$լl; gF=$iUA*)UR5N{T,IjVk
s z4$I#noǠJʟA0*X~Β$f8? m[OI4z ̏A?*)aU07%IRͪO >y$I҈~mcTI3fP}ۣ$IaON ԚOIP0/URTh_%IRݶ) yOIP{;yTI3fPg=OZ$լD^}| OkSG$:ǠJʟA0*X8_%IRk} ~:O#Ij~wcP%ϠJJA,~Ғ$uo>; {GIPcIwcP%ϠJJA,G%IKV=h^}\ KWD9$iuoϠJʟA0*XX~֒$; #_>q$I҈<3gP%%̠
VoZ$հW?~  5R>q$I҈w]¼TI3fP?~֒$U>8|F: @=4>IP!̟A?*)aUgZ$I5ͯ J}H>~0URT[ulOE?mITú7  OIP~0URTsO[$հj2[ ȯѧ$I
}wgP%ϠJJA,ε%IRMk][ ȯ5g$I
yYTI3fPO[$մ5 9}HٻhKV@dRDDD]" N"(*2V*IB2bB22d"I a{?ϯ9Ȑ~k~W߾朗! ?*HȠJC+-eЎ PXZ+w$IRV=>k IZ}-Π
34o `Ju[G$孳  @~hAgP	TIipo `J;6֑$Iy ;Dˠ
3=iow$IR/f  ug!Z\UA$dP%U(eԏ Tߍw$IRʆ7}  ~hqTA~UA4F_,G RÛ>~HU}  
C ?*HȠJ_v հ[;%IfTK ;}AgP	TI{F Sw;$)We ̮aoE䆃YeP	TIcl3J)5ZwF#IR;' o-.*Ϡ
2[u? J{;$)O` հo~hqTA~UA4c Liw$IRFw\}  C ?*HȠJoݣc L;$)Ou{C ~~gPTABUxk `,꺴|E#I_{K/  o->*Ϡ
2_u? $Ij~ݣ}  A[-gPTABU\:G bՆu$Ij~s9l NzO-gPTABUk? b-$Inx' {țo->*Ϡ
2_{gR)6|G$5z]' %᷈AgP	TIw `խKkŶ7$Ijf]_}  QҚ*3 !*i2.] L1~Hf=7O  Ha]--ˠ
3=]? xB#IO  Kg"ڲ ?*HȠJL흾j# LawzN#IH fʃomYUA$dP%Mޫ);7$IjXsJj (*Ϡ
2&=)7G$5οp 3 !*iruy `uiG$5I}  :1іePTABUj=T{ `H#I}  P{#ڲ ?*HȠJl}D Spk#ISu	 *e,*Ϡ
2&=9迅=$zz)^i ֯GTA~UA4ٺǼ+ +
{$IR|}  F~h3 !*iw|V)A> 0å᷏$I 4W3myUA$dP%ME 3w{IO  P# ?*HȠJ|v fI؊mK鷢O  Pз$ ?*HȠJ|# ̂.^~H:\5 kDKpTAzUAKv0hG$?矣O  P}8dPTABURL `G-[>$i֝}  {>~hi2 !*)ˣ=᷏$Ip˷.uwc ~DKAgP	TI1u?? =9$IsOE  @	IDAgP	TIAضǢ  `I4g] ;7&*Ϡ
2}3O  0#g}#I& ~I4TA~UAW~ Q_~H	rR TW7A]%ɠ
3 $uzc#I__>; `Cw$Z$Ϡ
2[u;E? ^up#I=  ItTA~UAS `FJ{g?$i_ `>7.*Ϡ
2b7  0Cz_$I_5/>7 +*Ϡ
2bg  !ׇ?$i|N@ 4@_KtTA~UAܲR?vS  ̐o$IX=)  ۋ-]UA$dP%7  !/~H1|Rw}j  ޣ1wm%ˠ
3z}0)  fɰWڻ $IK[琟2 *.yUA$dP%뇢 `P$IE;E @x]͠
3fTo+9  fH/$MYO /A6    IDATKTA~UAԌW  3{į@$ii h~ho=*HϠ
2Q?~ 3\{r$I9}Z  5᷉6*Ϡ
2Q{RWO 0KaiyI$IG_ @:|DKAgP	TIͩʵO 0c/$IҖ5?.u}V  PwumϠ
34d' 1#m IUI 4o-}UA$dP%5o~ oA$in;'  MTA~UAԠVn &itEw$IZT흞Sh}N  =-}UA$dP%5+U) a;H$m~8  -}UA$dP%5Y,  3hxw$IF7}F  Q?@mdPTABURg E^i~Q-$I6.eЉ" ƓAgP	TIknY[룟 `ϛ$I&;  O4 ?*HȠJj^~ 4?n.$I AzDɠ
3;Ϣ `FNzO-$IRWѧ  ~h<TA~UAԼk^4  3[H$=u?}6  MRKk7ƓAgP	TIͬpk  ̨!?~I'z hjMƗAgP	TIlp 07~I'OD @o8>F?*HϠ
2Y~ YUK{$I7dk h	Q4 ?*HȠJjf/3 ".Y~IinR?|w  4LߌS4 ?*HȠJjn/_D  3n,~Io{[ {<N2 !*.XD  3և!I;&D  >\Zs/*Ϡ
2[7G? V<-&$I_sJO aFw]~hTA~UAoS# 0z/&$I  hS4 ?*HȠJjvN~& Vm
$Iwj  hi~hTA~UAzg qݏ;&$i' P~2Vx3 !*ٵwY3 ̸χD$z뎍>	 &vKkŶ᷊ƛAgP	TIͯz qݏ|M$IҬy Uw.V3 !*>WS ̸ѭD$jC)  4s*UA$dP%5o~* YWץ"IfjMї  POIgPTABURVn_ʠ\  3nxw$I3VF  @u}mgPTABURFΌ~. Y7?~I4Kמ}  U+[+UA$dP%E?  exAw$IR{WR?yqdPTABUR:&  ᷑$I?\GdPTABURn~2  E$M{흿w  <	~h2TA~UA~2  JK{$I['> p^~h2TA~UAG `OEF$Mm++_ >\ZsM$*Ϡ
2Y @)^iyi}$I4;џ @Ín;7f2 !*)W;/~6  >om$I5TF 7xEˠ
3\g ^Hi{̻?zEˠ
3\uxC $IFw\ $M.*Ϡ
25ԏ~%  Rۋo$I? $P[4;Ѡ
3|=2  G$MC/ $0?M6*Ϡ
2;F?  e4(~(F$)s $1`e	ߊUA$dP%嫽JF 7;&F$)s΍8 ᷋&AgP	TI9\ _tIuys'9 H{M6*Ϡ
2r?ߢ o1In?/c HoM>*Ϡ
2r9 w;ILT ^sxgPTABUR斕{ o1;ID  HwM>*Ϡ
26' ;t;IT FϠ
3u?' ;T__Zs[J$5ѝEl .FϠ
3Rg ;N[I7 6O0ɠ
3܍tV3 .U$Ijd˷)?dgS ?*HȠJ]?w3 ~$V$ btys ?*HȠJ]{WD?#  ?Vڻ8^$IwzN?lZ}- ?*HȠJ_O	 ^sx$IR\G3 ˟cAgP	TI\&) x|uU:{I&] `s.-Q\UA$dP%{[ 'h疅L$E7\{r2 TeAgP	TISmJ  <3IX7R @Fu]ڻ Q-iPTABUt4 	QZ+$I
inY2 Hpk= ?*HȠJz'qs s$IRDS1 $6{FTA~UA4wy~)(I xBu^II!c HwofPTABUT}y 7~3I4Ɇ $7b3 !*iz' )uyW$I$R: Hl7]斅5͠
3sOF?)  OmrIrR=xs. gPTABU5ԏ  <;N$+?n)?gPTABUt5g {o'IQgY R~(>*Ϡ
2~V  6΋~f$IҒ6n??c uZu} ?*HȠJVnWޣO &$IKXE Sbti᷍AgP	TIpO &JiIEnox DoԌ ?*HȠJz'7i dë$IZF|:c "^~ߨTA~UA4}wRa ɺG#$iK}/?N)R֗ܲGȠ
3ltǅ &riJ=q
 Lǅ8jNUA$dP%Mg3.y ,~CI-ߦTw_1
 Li1TA~UA4 `u+w$ISOP `
;Gɠ
3魺' `,;$iSS rfePTABU6p' `.'$)[}֯ o5**Ϡ
2΁?  l*ݏ[J'kp~џ G᷎AgP	TISܲR?rO3 ?"Ijfݣ~ T{;jVUA$dP%Mw  ,co)I?PI `JU~yTA~UA4ug `z'a=%I7Z]2 bV8Q2 !*i[m E/$I*+h \~yTA~UA4o8. X]o*Il7[ ƪJ{{Լ ?*HȠJz'AS E~$$n^Wʠq L꾫53*Ϡ
2NSʨ  ,hP:1$^]?	0tMffPTABUl4 `*]~WIfee@ `Ft|{FfPTABUl? -6}[IfgOG 0+AgP	TIQ{RO ᷕ$iRa 0#DfPTABUT{e aᷕ$izn fH̿ ?*HȠJg8 Xcn~_I./n fLg	 ?*HȠJ{" X2;.([X)j8 `TA~UA4[U_  ,;W)in2\{RG 0WTA~UA4[ϛ~v  N]~cI7dO5 `Fu~g-fgPTABUl5w ʠS:t%I[?4 fհ[Z~TA~UA4{U  ,z],IRQ? Q/~&R3 !*i\C Fw^\Z+$IyRw fX	 ?*HȠJ:> 5ZuzUJG 0oHϠ
3٬ڰ. ~kI]{KK, `~)GUA$dP%fKVG??  QKȷ[f^}?  }o#Ƞ
3٬џ~~  Ʀ=Z:!$5N)W X?ҦfPTABUҌ6~  Ʀ~+]F٥' tJko$Ƞ
3mٽ  T;?7$etEK  0?o$ɠ
3٭{ț  yqi.$ie# o?$ɠ
3nnR?z_3 0v?'/Id[mtJ wh[Ii2 !*i\3 08$Mۗ- ՃJJAgP	TI]_~  &K4vxf} 5l{I2 !*i[u[F?E  ?oo0IjR}y I2 !*Ië~  &K`K/D  <Vl~7)WUA$dP%{ۣ" ɪFw~I[?a  GMʗAgP	TIaW# ᷘ$iCxg' S~o'ˠ
3$7 `=]ᷘ$iuR?ro'
 SKkgOʗAgP	TI{/F?G  1=m$iFq Hct)rfPTABU۪ԏ$ 0tֺh' &J93 !*I}$ 8FUީ(Fr  lѠw~nTA~UAsE?I  $-+WDZ  lmRJAgP	TIFsJg	  ~Tu;o3IҷeO	 E/)͠
3$}sKv~  wfťO ũ^Jy3 !*I\~  )~IҬ9~O E\MTA~UAoڰ.i h.3.>Yw2hG  l~W)wUA$dP%\C (?~IL|2d°  ޯ:*Ϡ
2u	 q~knY&I^{E?  KZ6R ?*HȠJU=pC 8/]Z+$iZSxgs d"DTA~UAǫG' F$M[>Xʰ ,xTA~UAǫ+K'
 {>'o6I;|w^wl wZ ?*HȠJU{U XՃ?~IR:TF?  c1쿇[ ?*HȠJ~  ~9'6IX)nS 06C~si:2 !*IOT{  O=ZGZ&IYj2 `/[^ ?*HȠJғ5g
 Q/o7Ijzԏj }o/MOUA$dP% @.o8Ij\++KVRWO5 Dt~Sɠ
3$=Y/Z  lǗ8IjJ~T_< LLҚ[~iz2 !*IOKgE?U  T]Sڻ,ЖoSga/Y Żb ?*HȠJS;=O @:A-:X2) +*Ϡ
2R~  JIҤ[ W=xKMˠ
3$mJ/\ 5tAM'IsJuUO. @2M_UA$dP%iS+ @j;/.ݾ?%o3եT  \gWg ?*HȠJ&5U' Hn=0T$iRo+y h꾫3MgUA$dP%iSS5  ljTKi-$i׼מ 4Ji ?*HȠJҦ', 1ZwFiO6-BK 4K]/4TA~UAͩg `jԭ.+ƓM{/jMO' @#8^fPTABU6_Y 2^%֓ǫ+Ӣ_K F/6MoUA$dP%isjRQ 0u+}_~I9ep{O$ @UC]c͠
3$mn΍~  Ӱ[go~IVl[z}pϒ F_LΠ
3$mnt LKg	$^ݏTn~ R}O8MwUA$dP%iᙥ?| L7J2  aw4 ?*HȠJb^wL 0F_tOt9e  Mt ?*HȠJb `vepNw?\7WJ]Ep  NӟAgP	TIZTs[{0 R?t°=(ë.F?i  ՝o<MUA$dP%i.3	 I-ݾ???^0 1b;OAgP	TIZl~2	 Yu?JkBIͭkFT  Ko~}i62 !*I[R L;wBIͪsO2 jOAgP	TIڒgc3 @)e5斕QVFw^$ Lg!dPTABU+F?e  ̫exA7Z(ixZR}+ 0F^;P3AgP	TIF|*) epޓS~u T42    IDAT foAVUA$dP%iK~O  ~?~{M(i2c: L~߄ ?*HȠJ|R?vs 7Uzyi6voSz2R:Y YuAJϠ
3$-EKD?g  lҰÌQҦ^}~~ 7^7f/*Ϡ
2uyMs &6t2\{r)A 7f.*Ϡ
2T' 0g(~KJj~ @T]~3j63 !*IKUD?i  ,Ba.)kv{̯'R  D5TA~UAJ,Y `2|Uᷥ4u2bRw G(
ˠ
3$-ek~  RuUF[sZsoLiZj_~E h=͠
3$-eݏ| NZ[SX{J?w" -=ᷥf7*Ϡ
2U exM)-[>]J5 `Տ_Z˷	35TA~UAοD?m  QuեwKkgߞRS2 ^KVߛ ?*HȠJR K7ߠRD^Ug}j#	 8uSAgP	TIG[O~  jíᷨ4:v qa*TA~UAqoE?o  D;J{ߥҖ٥.ë?VG	 `z'~M*TA~UA|R?v @jgMiU?-eԏI  wܭOO%*Ϡ
24 ~;>ߪ7^;J=?-  4࢝oUi>*Ϡ
24:& Q_Q:6n{,  iꪴxy*TT0$E?s  4\a]\{?}jj=a`J F~JAgP	TIgS IUF[gtҚ[~*_@5҅?9	  {;Z?3 !*IcmKy(  JYk^ߪymU:N@^sxٟ `\3o]ePTABU򽣟:  D#~jgWߺ|]?w2٥>%  S߽7gPTABU]g_ 0'Y*CwWKW{1^//O+_G i77gPTABU&;  fA5*7~~-|Z}=hJg/iŻѺ3J4 07KߖAgP	TID~? `GV\7_Ke7;wJeR=xK)0  X=-wmTA~UAin~  R2Q.|:xi.~܊mKt~gepeJ6  h5,-*Ϡ
24 SR?tG~~^sx響N~o~7[-:mgξ-ݣQz}.ܱptymS  d?omq2 !*I+  6{Juet˧ʃ|]SQfK{V9n[{t>3w~kO,7P x[sos2 !*Ilg  &>𛛪{*)O\Në.K,.Oo|Gw~]G;QB'wga;lO.+.=  J^ϥ'ʠ
3$M     M9ÿ?(*Ϡ
24іo]wE?}     Υ'ɠ
3$Mˣ>     X䟄o.=YUA$dP%iҵwRF    W?@i>{s2 !*Iod    ˥ʠ
3$E=W?     f٠Sڻ<?r2 !*I!-+W    0W]	TA~UAgc    ,ߓKAgP	TIJvA     fhݙߑKAgP	TIlxݱ      3{䯆?.mjUA$dP%)2#     I֯-eߏKTABU")    `FN}dPTABUO!     3n=XZ+^\ڜ ?*HȠJRx+-#D?     L+63*Ϡ
2ԄE?     LaW_fPTABUP{2F?     L5.-&*Ϡ
2Ԕ$    0:>{pi1TA~UA9O"     Sht۹߁K͠
3$5]D?     L[ZlUA$dP%Ig    )RmXWZs[--6*Ϡ
2ԨoSꇿ4    0%zﾥ-Ƞ
3$5~    c֪-mIUA$dP%iw~n)V    @r>TA~UA&6    J{g-miUA$dP%uR:     +ÿ떖"*Ϡ
2FD    QUڻ<?{ni)2 !*IM{oF?     $4l︥ʠ
3$5JۢI     2J{K㖖(*Ϡ
2g}3	    @"ën[Z ?*HȠJRk==T    A5*^ݶTA~UA7l    <;mi3 !*IM楥%     MVץs¿Ӗ:*Ϡ
2~.    h-.[GUA$dP%)C~|.    =eKȠ
3$eiD?     4¿ÖƕAgP	TIR_~2    h4 ?*HȠJR{~6    h+זܲﯥqePTABU2;M     ZgUA$dP%)U˷.CG?     4@~mimݵ4 ?*HȠJRu	    @ﬥqgPTABUҵno~>    T=pNȠ
3$elp    @c3jiTA~UAwy^)V
    @꾫KknYw$2 !*IY|'     ݣ~-;jiRTA~UA|e)(    `/~ZdUA$dP%)sõ'E?     LP_nZdUA$dP%)sL3
    4{iiTA~UA()    `%;iiTA~UAuyWS
    n;'h)"*Ϡ
2e    1 ?*HȠJ4;S     d ?*HȠJT4U1I    `:1{h)(*Ϡ
24-NzO
    |jmN'eTqiZj2ӺԎSsjLVnNӞũ&.3
AA(" E@YA=|$Z$<uOˇOm%
AT*IivQ5{    0.e_sP
*A:=g
    n<+},e
AT*IjQ>zWh    `Fh_YJAT* UV     4
AT*IkQ>vwx    `g:QzYYTA9
rP%.px    `'׬H3KӒ*>UPA$ղ%{E    *XoYTA9
rP%.H    `.?eirP
*AvQ6dY     Sh-yF~YTA9
rP%Oc    =Ҵ
AT*IuX(G-     Oct750},M[TA9T=j    xߚO1UP}TI{Ų}<=n    xK5UP}TIjB5+-     Od4I#KӚ*>UPA$5bODٛ     oC9UP}TIjJ+We\     ~!/MKӜ*>UPA$5bn     KwҴ
AT*IMc    ([X49sPJR*=7#٣    z|(}g,U!UP}TIjZ1{    4Zh-3}_,U!UP}TIj\    X^XHTA9z~8{    4KwRrP
*AFx(7ޙ=    e4Q#**>UPA$5=    aaj9sPJRc]o     Pb>ab9sPJR~_    h-5 {',U1UP}TIjt3hwG1    @v>6}',U0UP}TIjzߝ=    ,swRUsP
*A$-ѽWgc    Z|3;`9sPJDԷgc    ){sQTTA9
rP%IyyH    *>UPA$i[ߘ=    jcZݯTTA9
rP%I?jxۗ2    @-tN{gWCTA9Deh    _IJuAT* Un\=    k؏NJuAT* U"b     ԿrUWSTA9׿    P9܃Q,q
AT*Iz|}l?=    *{RrP
*A$=q>=    *cxW50}+-UP}TIғx=r{    ~nxu^WaTA9'c    `.MJuAT* U,=kG5    =|k앿ϕj*>UPA$ke=    OYF䷦q:
AT*Iz     Sgp[9sPJᯊG6    (ۏD[9sPJGgl    =gԄTA9
rP%IWQv7em    tûDkfaVjBTA9wG6    @a/GRAT*Iځxfݓ=    ,W+5ΉoATPkT    b=Ԥ:=G'UPA^J5[v    :~GVjXޙ̓*֪?$juN    KlnVjb3~?'UPAaJHRza    %ΣQĺߗ=yrPTTG:b     _d=ϳG 0Oc~9 IU1    0Q;.}z4{ 
*}TՊώr٣    `"\]n>UPAޕ*er    מ=
yrP9gG$U1kM8    ᝗S4q ̓*E>aH    ^+ڟݫ1'UPA5?$    0>sn	<9
G$աb,~=    exע5[U҂v3 ̓*/?$&    ?'MQ/ɞ
8
wMC@jNh    )?g:ǿ1{, c
*loLHR,;    }?'MYݳߟ=1pPZǀ$թ     ;{enUҏ׻d&{: c
*8TC^eo.{    l&}*9){< c
*}Tzcx    xZ{FkvQNU*ڵx=|K    xrn/*,9{J c
*O?$u>    z}$}*+*kT׆=?{    <?i1*n+>0Q Iut'=    Z>SIO^ٓUPa[~ed@Zc    쟾7n:;{T c
*}Txf={    L%=mwe`LTAu/MHRQ    4\(VDTSWq*T7=   *˭3{O*#UPaњY8:W(;f|    W#}>*{d c
*8Tz|({    3zhkuc#UPqsOHR-F|={    M1FF%mWDٓ#UPqo@&/!    `}owgk ATԔk    @ZgC%m9+hG$5b鳣|    T~$C~2}*i*7ޑ=>1sP5?$)u>    T?L߁Jڱڇ| &A
Ԥ7    @=5})i}o0FM17{cARqЋlo    @Mbswvg`TAMOxscATG?    PatNxSSҎW,'b͞"8}ueAyY    *NI;U=B	qP51|$5a跳?    @EmGENI;/e`BTAGhջ    P$})i*V<?b%8=F_	     EԷ7%tW$&Ajh     *5QL*ק?$׬     0kMf4%|ŪE UP35? $-yF)3     L!C^ϔ49TA͌7fvKDHRkE
    QtN/{LIlv(7ݗ=Q	sP5?$$\     P_'.
jh$5OmX)     Wl6KInx  IDAT?g`pPu4F`[𦭿    lmFCŪm@9^2&_{D     V9JIC
8=zOvQn#s     $Y4eDݔ=V]AX?,$uN|?    5њ=}O)i<c؅TAVB^Od    ]l?_4<#g`rP5>7xf6     J9Χߑ4Ydv1UPs^>"FO    .]4f[G9+(/!I_    `=?Z3#%/
A4@S$     2z(=7)i|-3ʍwf *h0_>"    0feo.G&})i@x8_FC z_O    0Ne3GQҘ[W͞0@UQG6!IMovQZW    %ޗ6{ TAn>7!IZš)     K#읣V|aGGA4IYFqHHD?*     P>zW+~"}(iu|9޽6"IZ,     ;cЉ'%}(iy}h=ed:ߗ$-bQ>vOg    A[~}~QYûd`
8=v_$):md    #&Sw{G0%TAC._ $maٟ    `;*ZL)JŲF1L	UTn$iA<#F2     O[/'JHkO3qP6$i[#_1d    '2G7%Mo(ILUpߟ@$mſ,     OHJP;0eTAÍZ?֊?T$IњY[i     #w&Vò0Tѿ$i[DO    /}h74:'fh=j)
ت},muNri    FmXŲ}&S|(;{ SAhZ$i[+4    @cQ=5\wn*\sSx$-kG4    @[|PIL9U$i[š?ewS    ?NJ\#٣rFqk2mu|O    fENP*>;Fݜ=j
pP<p1d$i[kN4    @o>'Z3%M1\wn*Aל$mca]    jkt5[p@IwǲGP!'=6m|    Pn~ U?4:-b47@8ܰސ$m{Οe    ^Eݟ>UQ7fObTOih$i[kO4    @=etW7}'ir+ܖ=m
rP<kcnI҂hw)     ׻c>IgޫGPQҿᬘ$iۯ'n4    @en\Cm3gTۭǏ$ikqg    *i+d٣8U$i[kN,    @9KI\['|9vhNCH/    P	Xf&T;WD7?$I}<e    Vv7Eץ$MQ	UNu6Eq쯥?$IsڻG"    <a?:-}'iru?'({ 5
ie{c5$ME+,    )~_N~"FiԌ*`^F8b$5b/g    `.HN~30ym^?`W|a,    T="}g'ir.hjA0($5cĠY    TE:Iْ1Ԝ*`lFG}Pz|0     i߿"ZKJI@[eT+}SמE    ]nQ,^~N+w114*`|?$=p]    vr}QzYnN+VT_=fqPLFYFǕ$5/!     Wv7E_JI_{0ؘYВ9A     &gۺI3keOT7Z$5:S     Q;8IcnvЭ *`1ZEK)    *7I81kMAˌ:}aȖ{)    }nZ7G
2zs3?$i~*ʹ    0o5+m}"F* ˣ3IjX1e    `qLM*>r:4GoJIRO     u!զ$8\a2fHIR_}t     vpݹњ=}&i+_+ OA0o_LIRc][=   `4ZK߫Iw3ekCXxJkG<$	÷fO    xJ{FiW?8
TSgpוQG$5ᯊ1{   NIߣIGWoD=R *`:[2ȓ9#F    ?f8E3I?){ 0UT{>=I{>=   MFNߛIڹGBo0{ 4U+_hǟ$չ7>=    ʹ}+evbcOE٣`^T+w;YAIeK=    V7F$PŊGepPTscn
TehúQ   @M>wdbQv7grPT}ڻVIҘ+}E<    }wcb[!APy7DwX%Ic}F   @Z9-;1IO_?
ߌJTQ;    5VswaI)\`g4*vs{?.%.   @ޜ?>{\ r=5+uЋT8&{   P7bo}I7,ogFsP_oq*6{wQ4   .z>5ѿlIȞ SA(D֊?L%JK    7S}-GTE1z 0uT4EƳ}g?X%
d͞    T?'x[_pP+b;YYIT7fOn    ߎ9}%5WDWGy4{ T*e>3 Z˟ȕis["   @NTfE_G*Acxѻ(>17[CX(Gٓ   JS-}%ծ{D_n~ۿewsO<@m8N[Ֆ??D7ܒ˒Xgf    ٠Sߞǒ*(~Itctѻc11za?'TaoڡY(zm]XC1    h4Y}%|aֶV'ek[ޥ|~q5bIh,U >z_Ft/htN(y}~ Iifa?={     @Eg/;    IENDB`PNG

   IHDR         <q   	pHYs    {Rk  fIDATxyCD"QH<SXDH0*LJBeyT'7,\rA9DYT@ݙy3=Ǘf]޼73}1     +zN~n1)_+W˭ZK=
} 3σQ.6J6Ѕ~\IsNiڒ&%
=spMD)%S`/.-Sj
7w>{55ODW5n_ƤG.˘إ<?}#N%q)ݠA\ERsO
{ǌ%5"_oCpИRH__XZQvLm0?ؚbKĈAbB䲖̌1?p8Gԁg}wc˜>faz;$o8S,cu6Ir냳I`-z5VQ?rY_뱆 } nNqpIM{=!	?!eѹ"?zK
 EH _U(XsD9%Ԅo)XNѹ!ȧ$1[e rew8ׂ{؛K<S9s_AN
!wx.(k֊\H+869iw	}*JZ߰TX+NK$9YL>581YXrA+hIQqAEܣ[Ċe'~PM_E^DgʪqVaSAbO;;cFIYAX~ Ns1mIenJ-#vu&dE\kZJp0<(L&Ug|oKϟX8I8 :~5dgVs`5u{Ћn)V%Ȏ{bhOjun/q.r79XqoT,cg'ҰhETG<E"\,ss ;^Qz+:{l7q֯AIw[,a.5Nfmk]/sWeG7A
L,f}yk,z<$PN$(VAc{kDR`baݒXH
L,/;X":,X%?1=/<,XX$;8+:,Ś'ቤ`0ȎI	dZDRb>H
L,cԏAvQI5.iIuBZ/<,XCvlyщ`)T7S&
XIAvɤ`R	,L
L,{d}g
nPL,ܨ :,9/L
L,B})<,Xxqx轿%<,y0T8{V	`e1UxB)X0-@vC'dٷ\xB)X0S~iǅ'/QYOӲ,-Hb'0#9YZE  ;ޥJ7\N*&1P(o`ዥ֓LgAxb,!z#N,a0ȎwjYCePW-C#Xx
meqt=0r`jY)eq\-#%tk|[x,ÆYt,d)<ZFb`-K#e/xy,G1T1d-#e\ׁ>ֈ7١BXz_3g?÷6.;ci7@9jDx9^/?+G&ԩ ^ 4	QX g|*%SV
oDMt6hsʩqItbaxq߰9EjNъec'@+l"s	<bx?./^J-8 z5I[Od\&4Rҟ
؛B X^{ghy*ׄ˒\[8dZZbaMFI;hnPPP3NyieNTfpadRG/F.0/NN݁%z0c;@,C RXWXCɋb\3&Vb
I]ˣ 3NĪڹ89S<7Ƚ ;|݀ӾJ:`KD* ٹVb5}@ͥ%.R-Ԇ1xRzQ25|J∨P?(j=mˤUG5J\_\'Xi(Ab/KZ& +1+ip;HBH\p!X&%D,Jy_&MwWg^CAb~=A5Duh3@]I٢˜482Cq;+q$B²8*_Pz͞R{6,u=}¦	=.5;F&1n?Lrz<?P*鈑_2`/s8vwmoS"s!9=#Hl=Gwf=R]X;xOXzV.dBaK%OJG.XȾㄨL$rT' *6RϬRUk':WD >$.ky6B8Ub4\,՗y/G˴q[d?"XB['&=VɌG|osGPMk.xi3g>36.3ڞm؄|7YEY-2ܭ\rc1-xMOZ[]EmAcg>T\*y8ׂVpm8m[5}VHU#ȇ;ytl{|7}ZӞMZs9 4LK8pLe+&6,{İ%CŘN-]KQ<:1cWruL=;Samc\ܿ|7       :OWUz    IENDB`{
  "name": "Contao Manager",
  "short_name": "Contao Manager",
  "description": "The official tool to manage a Contao Open Source CMS installation.",
  "dir": "auto",
  "display": "standalone",
  "orientation": "any",
  "start_url": "/",
  "background_color": "#ffffff",
  "theme_color": "#ffffff",
  "icons": [
    {
      "src": "android-chrome-36x36.png",
      "sizes": "36x36",
      "type": "image/png",
      "purpose": "any"
    },
    {
      "src": "android-chrome-48x48.png",
      "sizes": "48x48",
      "type": "image/png",
      "purpose": "any"
    },
    {
      "src": "android-chrome-72x72.png",
      "sizes": "72x72",
      "type": "image/png",
      "purpose": "any"
    },
    {
      "src": "android-chrome-96x96.png",
      "sizes": "96x96",
      "type": "image/png",
      "purpose": "any"
    },
    {
      "src": "android-chrome-144x144.png",
      "sizes": "144x144",
      "type": "image/png",
      "purpose": "any"
    },
    {
      "src": "android-chrome-192x192.png",
      "sizes": "192x192",
      "type": "image/png",
      "purpose": "any"
    },
    {
      "src": "android-chrome-256x256.png",
      "sizes": "256x256",
      "type": "image/png",
      "purpose": "any"
    },
    {
      "src": "android-chrome-384x384.png",
      "sizes": "384x384",
      "type": "image/png",
      "purpose": "any"
    },
    {
      "src": "android-chrome-512x512.png",
      "sizes": "512x512",
      "type": "image/png",
      "purpose": "any"
    }
  ]
}PNG

   IHDR  
  
   YŨ   	pHYs    {Rk    IDATxyeu}} 58<IbC;&Fh:vLLhغb{F}ϊo2  QP@dy
ϼYuӝv`=kY+k%+{~'  ʇяNkQy|	Rw8  =WEs$]3;1ή1ѷ&   0[xf!YtvzVAU}  LˢylgGO)F71(u  0v `r^OL.:+?e1<{;  `w (i:[U>^[Qُ=  :   C1}/3إjny.?  	mGS%M;=+zGU/;2p  .  5(btq;Rb]|H  0S[N(ivZMt^rHُA  h-]  Lύ޺6lI1ٷ#  Lx{YkD[~ @ &(=URri|ٷ%  L_^f#J݊}_eG"  .  <rM֧SIQ[  U[+JJ(ߜX f  `|ۅ;=YE4!;?;;/ξ=  	㫏ʭ%i㳨1G#  L$]  	.Qܲni*<7ʻ/ϾE  x+EgŖ4ܲ~1#  L]  8Խ-?Ж&bGyUٷ)   atRjn#6	  ` Vv~o~%=J/oU   6#%ZUoQv~L @*]  fh>`-Mh=_Ce߭   lY;OJ#3de?*  .  3gtQ|W	+z  '}"Rb.~T 3 `fǢ3<PZ{<wf߲   UUMGmnyoQ7d?1 ` 0WΚDK^wWEչ'  0z-=Sbog?1 `I 0CԐ},^Ỳo[   ʰ/MIze  v Z[Ϗb_?pZ.  tE)IW+c|ُM  X4  LrWEgŖRQu;s  X$fsQI1&  ,
]  J{0=`YjI}_U[  EV=pC>?=T6GG'  ,(]  vu˾u  X"]EG%iS*(ߒ c T^zDtVo~,ޯso  ?9^*IώMgg?: `A z>RK~Wpg  @FgO%iZu/=<	   ^A_Kz  dܲTIڤ5ُN  h` V*{K-EQ=xK  :]U6q#g?> ]  Z>O?T_o_   &IUEzv;a  6.  RE
KmX(:  `;-ﮒ9zwh b @k^H?Tsu  xLUﰒ9uQ/
  ` V(;F+6U(8  wD/J=  m` +kVI1;ٷ/   -R}?Lͨw"q#  .  ptC_U|bV  @trtVln+IQd?> q 0F~{Vr_s|  @.:(V6g?> 1 02z>~+1  )08s%is[K Ge D2WjSsbtٷ.   Ӣﻒ9&F7 Gd +Ǉ釻RG  7JT]_ c D_A>ԕٷ.   S>ݽ^+IS#E#  ~.  ,/J?̕Tgߺ   LjMX,ISo  Sv 8_yK!ԦzGs  6|b$mN1	  ` ?o6;~  ^_$mVd?> `.  F7[J-﫣Ͼu  AG{$mNݽ_1(  ` @@tv{AԖ{iTߝ}  0QcIڜ'C  v ;釵R[*vZSm  dIӳ  8]  /=<VjINψ˳o[   Wse;<5}Y6bDߐ ` ~H+Uso[   )kOfI'~"	 3  Eog+f߲   wMm1G'  3` %7Y%|-   ߦ?KҦw"ƣG'  3` 5(e648X   x|^tx]{$mj ` gN?Pk[   6I]QӒ)lew} c =:?90Vz  @w^OJMOe?6 1  ,J^wWDս?v  ZFn-I'  ]  3,V]oW   hdpߧcKҦ[G&  3` %=O_nQvA
   ͍;ڒx"^ `F F7*Mrsc|ٷ*   ,L;$=Nu~d 0#v Xt/)U}.6  72[Wv~d 0v XT?p&qξM  `5[7K ` 釭Ҥ;O"Qm
   Ի%1[u~b 0v X4{ܲViʨzoS   XtwqIz~\ 0v X4M!4koQ   X2可bKңUa/q	 3 `QlaX!4q6/̾E  `ɍ.Z{$=FË~T 0v X3O?\&e1   ND$=J/$  S` WWIkp   rA\;$=bsb|uOJ  .  nÓV	"2  twG_LWG? ` zGE4Iu[N	   c|9Ye;$l/+r  v XPe*PU5ϋ[oM   8óvLoGjtYُH  .  jx釩Ĵj(o^m	   *?ip'  L!]  T)0UF}K  D:D%'+vaDYf?" 2  ,r]YEa4	N[   Za|)љ[./I?  L]  }QIwYO   `lG#  S` [Q=^Uq_   R7Kk  L]  ƠmQ̊Wdߍ   JՃF%i[DYܟh `  F~3 UlnYX}+  @=a;=_>_}lc )b 釧Rfoe߆   0'|4=_6y  ` Q|WOz5*oC   ~t[UOD  .  J?8zoC   *ES%xsˣ=H `J ʯJ	;B^}  T]zX$o<3q 0 ~h*-ysbt   Z ik )a @cK?4ɟ̾   `:$nޝ$ `J hU[JKYߏ>   	FgVf^ `J LXܨ6ܑ}  L:L@ҌbQ?1 0 %JKՊ-c|ٷ   ̞r/l@LVsUS )` @#ocaT#  U=pC;Bk|7  L]  釥R?U}  L}3I읳  L]  RikQ7dn   @DIU_{ )` @}(:+J?,UDy%w   T{X3I3Sﰷe?    V>pSA؍.:(V   ~$N^ `
 P3JŬ_ff   wgfbg?    6WJŪˣ<}   b{{s~ iZED9~ r  68kRi1ZMw^}   CIS_}  @ P[OJ袃o/   `I_-ُ;  Z` z:TZGe   lr~7LAtWsU 3 aoK?$^/jp   lkzI[yُ:  Z` ڊ/TZVm]fV   @Ms?_4ovc 3 bL?$ξ   &2z1At6  -g @mŞ/O?$ޡQUٷ   PkNYk|ُ8  Z` ڊ=^~H*5Xܨ;v   ]$M_O~ r  /J[   M9?w4Uov 3 .I?$48fF   "(<:+~ iz2 )]  jCRni'   X$3O?4= Д.  쪭?%~}   EwN?4 Д.  쪭.;"   @yYUYg @S  f6_[   XBo&<BR3 )]  j3U*>KQuϾu   4DwH?v h` vժӳo    AyYUf @S  f65?f2   @)N?v h` vՖ{*b˾e   L~t~e9vf @S  fVj(<v   &3<BR2 )]  j3U[    >~^!} Д.  j截̾U   	RGyڕ.  M P&bF-ٷ	   0F~v!] Д.  j[   `ޚ~~!= Д.  jR   p1$#]  2 6]MbŎO۲o   g~! Д.  j]vd   E9N?ϐ4 Д.  j   h߉ܲsI.  M P&bgGٷ   Bc6lCdg @S  fIjt1ٷ   RU(vyN` v `WRo   F|5Cf @S  fIQuɾ   );g&3]  2 6]MB+ξ   )Q&Ce @S  fzym    L<$M^  4e @mʬQm36    ͨ=-Cde @S  fF%    >$MV  4e @mʪw#*    XwHv h` vO/   `m<&,DDd @S  f}   3bI.  M PK   n0LDR~  4e @mZV>1{ʾ  3sI Д.  j):   fT)lDRn  4e @mZ{<bϾ  UsetVl~F")/]  2 6]-Isc|˹ٗ;   0'|4DRZ  4e @mZ'~<R   @l~V")']  2 6]-vn/!R   7%r2 )]  j3b7   3IK.  M Pڿʾ   ~Nyw3,Df @S  fŪQuɾ   QO$-m  4e @mZF}y   <ợg(.]  2 6]-F_Qٗ7   c&Ee @S  fony]}i   < IK.  M P	;   6#S$-M  4e @mZȊ5ύ>   tU/\Eg @S  fltW/i   6sI.  M PA?4    m;+7]  2 6]-H+˲/g   _[埳HZv h` vNT   HZv h` vմb?})   4VubǧHZv h` vմ%_;   [$-N  4e @mjRGTUe   pF(v{A` v `W[mg_    ntɡg/<]  2 6]խɾ|   GUFwN? Д.  NOjٗ/   xf` v `Wu&   Xtޚ~#i2 )]  j3VQ?   XtDgŖ1&]  2 6]mn㫏;l   L_{y` v `WS7g_    Kz6\FRv h` v-򎋲/Y   %78g3g @S  fMٗ+   @q;<5|FRv h` vI&7g_    i?(]  2 6]mJS>}   zFi$` v `WW3ޟ}   &FRv h` vxWe
   0(>5e @S  fǪ%~e
   01~f#^  4e @mzFW;D   &x8m$m~  4e @mz./Q   3I.  M Pgd_    GwWHڼv h` vHyK	   0FWM?Ñy Д.  *o;?   lU^~#i3 )]  j3?]ٗ%   @+xbYM` v `W?(,   hޗ LG&e @S  fCٗ +g    IDAT$   @oNM` v `WʭzK   uz_I.  M Pw?}9   v$=~  4e @mo6Q=t[   Z/A` v `We_    63I.  M P]wÝٗ"   @zcYG` v `W?}   LNN? Д.  x{Ge   05nG` v `wf_    Se|	g>9]  2 6nQ=t{%   0uNُ` v `wv   `*Fُ` v `wF[UToξ    SUEw?S Д.  f>}   LGIv h` vguoʾ    [UFw_? Д.  ^o   `&.=<,H` v `wƚ[=We_v    Gw_?4.  M Pl?]ٗ   L]|H` v `w*on%   0{_M?d @s  f;;   `&`ِ$]  3 6i|ݷ/7   4GχY` v `w6ꈪʾ    fψY` v `w6]~T   0ӪރQs"i3 )]  j3؝=^Q/5   78gE,g @S  f;/Be   _}*Hv h` vbgF:ٗ >=t{TS({s_ UόY` v `wOٗ 06h˻/O9kbp?F݇w;wFwߎ~%]ΪPӢQ~3zI@ND)F?r9.[Eߐ2 `mnԙ[~n$b  4e @mSʭzK VU5'7KٻďG/Q.y}~=zG#'C'?<)_;˿  M<f @S  f;U Lc|17j;)-bDo"E *{4 Д.  Nof_^ @~-b|7bp}_=KiZӊ-+{cxΚ6ܙY `umwi2 )]  j3؝z1 &x=WCcpǣ?wEX=1QqQDUf_ ]yLwi2 )]  j3؝6>  1bxή_2,WG]Q  K9^Dv h` vb> )Q.jHt[ƹ-);1p5  GY` v `wkm (2']=D1< f{ Д.  N/U/+ `?6.ۥ"_]qtĠ} dx;Y` v `wK
 X@_ZNx([m{[X1d_ #d @S  f;]w]}I m<+k/:+H~-FTU% ,@+;4 Д.  NO/!r b|1Ǣ)Ԯ6^3Sg?6J (>:sӿ[HӞ.  M P4	 Tnz~o;>-{e;1r]D9ʾz=;4 Д.  NG.Eٗ XF_s|}0~!bbpʧz #i` v `w:/ٗ HQfUtrwX+ETU  <>Bv h` v[DK	 	=W_:M }	%Ώ5i` v `xge lA9k+ҿHVǋcx~^- <aNL Mk  4e @mo|ٗ ̮r#":+J^ mjy?} ?c_j Mk  4e @m%U}̩-b_N> 518_ޟ}[ K-Yei3 )]  j3mwóv̾ `w\uk2k~UCm DDkI~ Mc  4e @m-nQ=xk% oԏ%FwWK\v1<gMx}L4f @S  fz-V=|WN(vzf羴u|Y<&oE Y^@v h` vc/ JDؿΪ?67}[L]|Hwi2 )]  j3mgŚEٗ L-E?ziި6ܑ}lX4e @S  fS Sc|ww?ߥo'Am 3cp e @S  f6n `9s]j[=_Nɾ`&T{jiZ2 )]  j3m_/Ae 6}R[jٷ4 L1엦$]  2 65 Zri*vxjňʾ`fKӒ.  M Pn*JĠ} @\#5ٟҴq_=xK S{?i` v `]}(֨bpǣbpiv~m@ `t!4d @S  fۮן} b=i,v`Qy Д.  춧⳿Qٗ LeGF?Yo`~tї
 0U'}"3^j{  4e @mipʧ/ XD+y-Ψg?" `jv斥Km` v `=w_} ĩzcpǣbjI_rn BoJlڜ.  M Pn;K &KUC9Ӓ6[]] _\Z.  M Pn;K &F>Kz9wf?F hMj.  M PnZeTߝ} @0g>K]c|O h)N<ښ.  M P;O/ HW~ateIԊ-bxُ h_-<Z.  M P7 rU5YUg{#E ZwȟKm` v `w[uTٗ	 (<&XҢjMُ hUHژ.  M Pd;ٗ ,r3Utv ڣE_Lږ.  M Pd7K T-;ZeY"[jY  4e @mmoȾD `l*ŎO(ُ$ xՃFgR2 )]  j3؝G _^ISwD LoOܖڔ.  M P6 ]y韻&U LL̖ڔ.  M P# CI&bDkW 02_-%]  2 6ɬ{/ X<"_[Ie(o^ &?d @S  f;\}i (>FgI1_a }~tWc͏EEgRK2 )]  j3؝Vo1d_ 75K韵ي-bt!ُ2 XRՆ;c|18}e{[F Д.  N^#ޙ}Y }2sVR˛[~{F+?{)` v `wa LQ/Ǽ?UҔv| ^_7Uљ[9+My  4e @mʭޟ}Y wJ|:1 pG9~7Dg韥,f @S  f;YGٗ ,뢻?[%MwS>Sbp(v.3Sҿe @S  f;Y/B% o8gΣ>:e+΀2=+2 (J(ȓ47h%m蒒-	v)mhZZP4uad}]|{yO{=>$}s瘝f_8iti;RȗFI;]  J `w5[z ~Z*Qu M0-iyծ0]+,]  J `w/G8 @V̢*/A Ls{m]뗦ֲ=v (e @6݅`? R4rY'" 5Uvm%}` R  d3]8w|9 &7y~G%4pX'# ]F6JߞGx4? P` lG~"G ƺko ߌGicKn^ʽSkov (e @6݅Q3+G &3o
]-;1 Ճ_MÛJ6uOzMj-3.IZ0 P` lF( 7hi}Y	Ѷi]oj#iAg @)]  .xzJn <ɿ?%鉴S?9$>g$.]  J `7o1 'fOO1vJ$|fwc'( xǖ4ܼ*-Nݕ{O	).  v f uW~7%)/JCwG=T;ֵ~>Ctf @)]  7[7   uO)IuTD4^V~q\,uWvj!9 P` lu{e  |Uzk4uNŔOVtϧ5G9H4Hjv  2  nl~8G  e~/%i6攪q+ON߻7)/Io  2  n6D 4[)IsQF^s{m]뗦}SK` R  d3؍}3R ԚY~/%i^ZڨzѶiiy>㒔.  v fW7E?? |WJ~+%iN[4\g4H[vƆޚRg^~#` R  d3؍k/~~ w߸%zv}s[_U=4ܼ*-Nݕ{O|` R  d3؍k ߡz}o$gc^΃ ڹ=MKSw~B$g  2  nL~,;TuNJ|=u)G >Fw^W)Q$Eg @)]  Իϣ J~/>JRd) x;Uw{X3?[%ie @)]  43(IQ=]ũr񟣒Tv (e @6݀잪η vqٮ~%i>v	 Is{m]뗦}S^JR]3 .  v	~v e;RgFIZHu/>kL6=ͩ}\i` R  d3؝~  UGSc?~%i!=wSj`ڍTUw{Rg^5(3P9]  J `7K> 4]Uo|Ok`T;-ũrZ:IjZ  2  <d]% Dl8,&JBoitU@ǹ[/H+>=+sMd @1]  o~!h=EDIC~8U,pU4ڶ16-O5Ί?$I=]  J `w~_'9ePTwRџB1-iyU[:ǿ*fVIX  2  <!|gP`@j4ں6/`;=-3I.  v f;-=U݇zA-d4r`U8w]ojD.]  J `w֎>o$չ/NU[,Ѷiiy/uV9#Iv (e @6G?7 MTU$MC}53-iyU[:ǿj߂"Iv (e @6y2x@=.J45v+ix驿S㿜Z?5C02 .  v穙R~ h7ֲ=$MS<}XGF[צggRקύ$-v (e @6sˣ=o$Mc_hIoѶiiy/uV7F&H.  v f;?a7~$i\G=L(wlIͫR]wj-}r}IR3 .  vO~j |;}Ani/DԨvnOkS=uZgsIe @)]  On~j w>IjBTvFCT݇h4pXo4$[  2  >?TUO@C.f?IjJ"~q婷fYWjkWv (e @6ݹ{D?3 M1α}ԨfvK;. 0i|Mix;ݩsϦ֒=J P` ls`@Chݓ&>GR}(vnOkS=u:%I~ P` l%@Tܛ>#IRS]S sj?F_W|cj_w$M.  v f;-}RJN3 $IR-,xiiy/uVg<י$I P` ls[~b `md'IM}ԏ3,dƣ4ޱ%7JuSwީS=I4 P` ls;-7Ox2,UܞF[צz>9n$Iv (e @6ݹmx')7zE$-fWGإ=F6wR5"IR`  2  6'`uO'IG_Ҡ}"hA'q90ׂ$I-]  J `w[gJa0Fw^$Iߵg?}&fQؒWũrpo    IDAT)?$-v (e @6ݹ{үD?/ ӬR_
w'/G_Ds{m]뗦}SKTv (e @6ݹ)6rn$}'foITGh4ش<~[jeI%]  J `w~`tc_~$I?'E_a74tLY5[ϭ$IӚ.  v f;w}G0Fw\~$IOMUkG`!iix㩩}s«SkF%IjR  2  >[ L}o$؟JT;ֵ~iwx;gQg @)]  MOj0~$I7zڇ(gN$v (e @6ݹD?- Sw9Iu~YJ^a6icKn^z'uVZ3$I` R  d3؝7 Lꑯ'9IR^G2T;-ũr?K$)/]  J `wn߷9iBK~$IT=ro9sG[צz>y?7$i2 .  v砥ONiԏ~Z L{$zV$;'UvѶiiy/uV!I6]  J `wg`
=רG8I4<aؒWy|;(gA$o  2  ;Oi3/q٩w}3wsR]wj-{ZKv (e @6op
tz}$naT;K[/H+9uO>+If  2  |{U
oM4zVZߌ>1Sv]WR̷?$> P` l_~ Y"o
mw_Dm<L[p_8uUj,
7ITv (e @6٭})ӻ=M4G-=qsY0hԿ샩rZ7$IS.  v f;uO'`o{kSU݇+R]ojoSI4 P` lcM+ ̖~$IsuiUG`w/	w.I.  v f;x0E:ǽ2I1/Oi4HSa<L[p]rZǒ$Ie @)]  \ L7nkkhԿ샏sR${e @)]  nU'`Ju]$_C{jH.JKRwR{$I$]  J `wj#	S6Iֿih4ش<:+JI$d @)]  ^^ L5wMOMixS?KZ{IY` R  d3؝ms0%g9Ib}]s~g7a+Ne{sK$G  2  5`
T݇Rk5IRP3viwWNm`az>$IA P` le]WE?' S`œo$)'ߘwDF4~ClZzkK{n<$I%]  J `wvn~N @iIƣ4ޱ%7JuSwީ%Ir  2  >)UUsPsU뛩d&Is/|c<G[צz>%I.  v f;;u`
=.IN$uWvj-$IӐ.  v f;;yGS0FM$I$iZ3 .  vgZZ (QuNOi$I$Mk  2  4O	@=vK$I$IӜ.  v f;; \S~$I$Iv (e @6٩= ٨=+I$I4 P` l}~3Ps;g$I$M{  2  ny)g$I$M{  2  nyOA3Psc_~$I$Iv (e @6W|(#fvg$I$M{  2  nyN~F jlxL$I&d @)]  XO+I$IԄ| @)]  W=gGh-$I$	 P` l-# ~G-$I$! P` le?O@7
e$I$5%]  J `)~B jw{o$I$IM` R  d3-?~B jo$I$IM` R  d3-ٙ'΃5(I$IԔv (e @6ݲׯ~B jjtEwL$I&e @)]  ~{O@M?;&I$IR2 .  v Two1I$I.  v f[V{$	a/c$I$5)]  J `7ψ~> jz;&I$IR2 .  vF[/c$I$5-]  J `77D? 5_4I$IԴv (e @6z; o
c$I$5-]  J `7tD >$I$IM` R  d3op@ک5(I$IԴv (e @6݂/wo=? /0I$I.  v fk_~> jhx7L$I&f @)]  W=twPC+9I$Iv (e @6Ҡ| P~$I$Ijb  2  n^탟t T瘗1I$I.  v fcc+ xZK~$I$Ijb  2  n^S^t P=7L$If @)]  ;O@:I$Iv (e @6ݼMPCOa$I$55]  J `7UF? 5_$I$Iv (e @6ݼםt Poa$I$55]  J `75O@uO&I$IRS3 .  v3ؽG8I$Iv (e @6ݼ;D? uSSk7L$If @)]  U=fK$I&g @)]  f4[JaP360I$I.  v f;y탟l +0I$I.  v f;y_l o$I$IM` R  d3؝Ήl s0I$I.  v f;y^l P&I$IR3 .  v'ߏ~6 jwo$I$IM` R  d3؝ޅ~6 j{0I$I.  v f;y>l P縟a$I$59]  J `w;$ Q?~$I$Ijr  2  => a$I$59]  J `w_:3 (fva$I$59]  J `7K/~6 jj+~I$Iv (e @6mSP3o~$I$Ijz  2  䍿qKP3{_$I$5=]  J `w~6 jftK$Ig @)]  N^~  ѭ/I$I.  v f;yi؍~6 jf3$I$IM` R  d3؝%{D? 547L$Ig @)]  NVgG? 54&I$IR3 .  v'}ďF? 54pX$I$ P` l9O@/a$I$5=]  J `w:': e~$I$Ijz  2  duO'U$I$ P` lg7L$Ig @)]  NV̷D? 5;7L$Ig @)]  NV?~2 jw;o$I$IM` R  d3؝yd P췇0I$I.  v f;Y~2 jw[o$I$IM` R  d3؝%~2 j{ƛo$I$IM` R  d3؝~2 j{0I$I.  v f;Y+E? 5o$I$IM` R  d3؝â&I$IR3 .  v'kiyPCS	a$I$5=]  J `wםd P׆0I$I.  v f;Y?d Ԑ$I$I P` l5O@uO{]$I$ P` l5)O@uWV$I$ P` l5'a$I$5=]  J `w7~2 j{0I$I.  v f;Y/d P﬷0I$I.  v f;YÛϊ~2 jwo$I$IM` R  d3؝-D? 5;7L$Ig @)]  Np˚'z3I$Iv (e @6	yO@>&I$IR3 .  v'B&I$IR3 .  v'B_W7L$Ig @)]  N뢟_&I$IR3 .  v'B+D? 5_$I$Iv (e @6	н';$I$Iv (e @6]_0|4I$I| @)]  N]WF? 54&I$IR3 .  v'BE? 54&I$IR3 .  v'Bw'7~$I$Ijz  2  _'F[/a$I$5=]  J `w/tm~2 jhte7L$Ig @)]  B7ڶ1I$I| @)]  NF? 54os$I$ P` l~{EO@U~5I$Iv (e @6	yO@Uo$I$IM` R  d3؝-~2 ha$I$5=]  J `w7d Tk1I$I.  v f;YO~2 j}$I$IM` R  d3؝'E? 5K$I$IM` R  d3؝G? 59$I$IM` R  d3؝ckwL$I&g @)]  NGE? 5=MwL$I&g @)]  NsF? 5;wL$I&g @)]  NeO@M׾/I$Iv (e @6v& nH$I$ P` lտ\st$I$ P` lտn^~$I$Ijr  2  d-~2 jjtg$I$IM` R  d3؝d k$I$IM` R  d3؝d $I$IM` R  d3؝ޚ1I$I.  v f;Y3d xZ3o$I$IM` R  d3؝i~2 j}so$I$IM` R  d3؝I~2 jї2I$I.  v f;Y~. Ή~$I$Ijj  2  du~YPcU~$I$Ijj  2  dQPc52I$I.  v f;Yd Xҿe$I$55]  J `wd `L$If @)]  N^vnd$I$ P` lWl $I$IM` R  d3؝{S$I$ P` l7gGc$I$55]  J `w^l xZ3o$I$IM` R  d3R+k[&I$IR3 .  v3Խg:[&I$IR3 .  v'ox@uO[&I$IR3 .  v'ox'L$I&f @)]  N`1@/[&I$IR3 .  v'op@6~$I$Ijb  2  PPcÛV2I$I.  v f;y2 ]W2I$I.  v f;ysl o$I$IM` R  d3؝7D? uo2I$I.  v f;y1 A
g$I$5-]  J `w:G, Ί$I$IM` R  d3؝!ϋ~6 j{>L$Ie @)]  fdqPcO+I$I԰v (e @6ݼCO@P-$I$i P` lyUt o$I$IM` R  d3kF^~$I$IjZ  2  nw^t o$I$IM` R  d3kx˧v~$I$IjZ  2  n^N~: l<J%{3I$I.  v fsD? 5>%L$I&e @)]  տO@uOzM=$I$I P` lywPss(I$IԤv (e @6ݼzg% ~$I$IjR  2  n^ݓ= u'3I$I.  v fWWD? 57{&I$IR2 .  vj;~$I$IjR  2  n^~( ~+I$IԤv (e @6Z@g$I$5%]  J `7{&I$IRS2 .  v@uxs=$I$) P` l_zAPsu$I$IM` R  d3ox݉@>T=$I$) P` l\| p˹L$Id @)]  _^~$I$IjJ  2  n~| \f=$I$) P` luOzM0>#I$IԄv (e @6:G, c6I$IԄv (e @6>3 3~$I$IjB  2  nYiЉ~B j$I$IM` R  d3-zh[PsX=$I$	 P` le~mPsׅ3I$I.  v f[{&I$IR2 .  D    IDATv^2	a7f4I$I=]  J `UF?! S}ď4I$I=]  J `E LI~$I$Iv (e @6ݲzg-	O+I$I4 P` leu?O\M$I$i3 .  v,'`
oZ~$I$Iv (e @6 L=i$I$My  2  nyU@U;g$I$M{  2  ny ]UOi$I$Ms  2  ,|{g)9go$I$IӜ.  v f[);7M$Ii` R  d3-G?# S?4I$I9]  J `ާ8/~$I$Iv (e @6 LѶ7M$Ii` R  d3-)P=zM$I$i3 .  vg Lψk$I$Mi  2  Tu~J @W4I$I5]  J `wv`
~{M$I$iZ3 .  vgE?% S?4I$I5]  J `wv^w}gA&4RئcicV3Nj[.iש&:K[6&Zg~@n,7(r1aE`a(9>}|?3m o$I$IY3 .  v'SKџ_~$I$Iʚ.  v (f;O	@o$I$IY3 .  v'SȷEJ h&I$IRv e @1>џ$ڇ6I$I1]  j P`w2x~ )I$I1]  j P`wr;EN 蝻&I$I1]  j P`wr&so$I$I3 .  v'cgDN uyM$I$)c  2 _t@ r*I$I-]  j P`wrߣ?' I&I$IRv e @19Ϣ?' It|[]$I$)[  2 j	@|*I$I-]  j P`wr־ sD$I$I2 .  v'۸`' m1I$I-]  j P`w,;o$I$I2 .  v'`)џ㦵v&I$IRv e @1ֿ`O
@C^~$I$Iʔ.  v (f;zg|2D5I$I2e @-]  NIH=$I$I2 .  v'[ߌ $1&I$IRv e @1	sf< $0&I$IRv e @17zwg AY^c]$I$)K  2 ~
@}U]$I$)K  2 \
@c~$I$Iʒ.  v (f;?\YHw$I$IY2 .  v'_DV \~D]$I$)K  2 lxsg 5I$Id @-]  NEV wiV6I$I2d @-]  NfЉ $o$I$I	2 .  v?- It&I$IRv e @1){æO@~6I$I!]  j P`w:7 $1&I$IRv e @1O@/k$I$e` Z  3؝N#iHbyY^Z~$I$Iv e @1%џDZ{8I$I4 P` bSjiU?/ It|[m$I$i3 .  vk?/ IL]$I$i3 .  vӢ?/ I.Z]$I$i3 .  vW?/ Io I$I4 P` bӫ{G?/ I?k$I${  2 |џDZv	m$I$s  2 j@"o	m$I$s  2 twFb &I$I<g @-]  NWDb \&I$I<g @-]  N'Eb ~a]$I$i3 .  v[G{Fb w6Ko$I$I.  v (f;ݺ}8HkM$Iy` Z  3؝n!Hw6I$I5]  j P`wϢ?1 M$Iy` Z  3؝~џ$W}3I$I4 P` b+#mDf su]$I$i^3 .  vүGf 5m$I$c  2 }џD2I$I4 P` bӯsDf &I$I<f @-]  NEf pmm$I$i3 .  vWHbx&I$If @-]  L $1z&I$I<f @-]  L d15=~$I$Iv e @1ݕO@"^~$I$Iv e @1ݕ{{?5 tOHm$I$i2 .  vWH߇6I$I-]  j P`wZSӌџ$7$I$Iv e @1ݕkMџ$ƿ7I$I4o P` b+c?7 &I$I<e @-]  \ $9mM$Iy` Z  3]}8sHυ6I$I)]  j P`wj@"m$I$S  2 Zsӌџ$F\~$I$Iv e @1ݕmO?9 Yo$I$I.  v (f?|N' A
m$I$K  2 ֿhO@"S?~$I$Iv e @1ݕ{G?9 7~$I$Iv e @1ݕߋ $2&I$IҼd @-]  l=4qg M$Iy` Z  3]Hn&I$I<d @-]  (|㷣?; t&I$I<d @-]  |%Hm$I$C  2 =/?; >.I$I4 P` b+_WEv ݷ%I$I4 P` b?= Ynύo$I$x  2 nL $>wo$I$I.  v (fړ?= tWM$IY` Z  3؍wO@">I$I4 P` b1uOxw -6I$If=]  j P`7/ $2n?~$I$Iv e @1ݠV4v >/o$I$p  2 n\. $9o$I$I.  v (fʣ?? ]~$I$Iv e @1ݸz@"76I$If9]  j P`71o $2~&I$I,g @-]  џdZ$I$IO.  v (fҪfy  Ά77I$If4]  j P`7[ H	m$I$j  2 nl~ $2&I$IҬf @-]  =#O DFm	m$I$j  2 nlC_ d4lw^}$I$i3 .  v4h H}$I$I3.  v (f룟 t7~,I$I4 P` b9! m$I$b  2 n| HdtM$IY` Z  3؍sۣ [$I$I.  v (f_kG? i&I$IҬe @-]  FOD' I$I4k P` b HM$IY` Z  3؝ Hdx9M$IY` Z  3؝}8) ȸ&I$IҬe @-]  F') Lk7I$If)]  j P`wFZS{D:M$I` Z  3؝F^ HnM$IY` Z  3؝W}39 o6I$If)]  j P`wvD[
m$I$R  2 9 ɴ~$I$Iv e @1٩ׯE? &I$IҬd @-]  VwG?	 `)I$I4+ P` bD?	 ^1I$I4+ P` bUk #I$I4+ P` bUwE?	 i}埇7I$If!]  j P`wj/ t&I$I,d @-]  XKqg@"s$I$Iv e @1kxyD[Nm$I$B  2 ߼o  C6I$If!]  j P`wdZ$I$I  T3 >d:G5I$I.  v (f;ޱi@">I$I.  v (f;$i ړo$I$I P` bY'D? =xsm$I$):]  j P`w6n@&q/7I$I"3 .  vg~ $9MM$Iv e @1m4Ͱ< Hw$I$I P` b螫 >>I$I.  v (f;8*y o$I$I P` b[D? 2֞/o$I$Ee @-]  no1y LgÛ$I$IQ P` b[kM3E? }M$Iv e @1nMOD[Nm$I$Ee @-]  v~" $2~&I$IRT  2 l~" $EM$Iv e @1ٮ7F? &I$IRD  2 lM3F? 韷[}$I$)"]  j P`ww]3 Mg6I$I"2 .  vgGG? /~$I$I` Z  3؝zg~: LkM$I` Z  3؝_C3 		o$I$t  2 f4~* $?]}$I$i3 .  vѽD? r^m$I$i3 .  v
 [$I$I+.  v (f;_
 ɴ&I$IJf @-]  G^T H{_7I$IV2]  j P`wNM3G? _|`}$I$i3 .  vWD? qqm$I$i%3 .  v_~. d24k~$I$IZv e @1d:I$IR P` bSD? nX}$I$i2 .  v5 0)o$I$P  2 |5?D? sUm$I$i2 .  vO~2 d26{R}$I$i%2 .  v~2 $$I$I+.  v (f;_zU ޙ	o$I$D  2 zǦ鷢 f}$I$i2 .  vE? =pSm$I$i%2 .  vF? 2֞/o$I$M;]  j P`wg@2o	o$I$M;]  j P`wj[dzg!I$I4v e @19lift HdpiM$I)g @-]  gΏ~: $2~&I$IҴ3 .  vE? i%I$I4v e @1{ t&I$I43 .  v& L$I$I` Z  3؝ӖV5CD7}7I$I4v e @1mxyDƭo$I$I` Z  3؝| HeM$Iie @-]  oݓ| H{{$I$I` Z  3؝F mM$Iie @-]  qKqgOD0I$I4v e @1nxODݭM$Iid @-]  w9	LW7I$I.  v (f;uOxw 
o$I$M#]  j P`wk5	L7I$I.  v (f;qo3 ѝ6I$I.  v (f;o8#ɠ,)I$I4v e @1g@2C~7I$I4v e @1sE?# nx}$I$i P` b_K4qS G7I$I&.  v (f7E?% ݷ%I$I4v e @1:6)xԴ~$I$Id  2 nzg~:)Lg[$I$I` Z  3Qk Hw$I$I` Z  3MniA79MM$I	f @-]  iK m$I$M2]  j P`7O H~&I$IҤ2 .  v=	d'/I$I4v e @1<xEs }$I$I` Z  3MҪfy(IM$I	e @-]   LT,)I$I4~
 @-]  /G?) i&I$I$2 .  vs9O
dzg&I$I$2 .  vsZK G7I$I&.  v (f#wF?+ =pcm$I$i P` b\wZ i}$I$I P` bg@20I$IT.  v (fΆ7G?+ 靻:I$IT.  v (f4h $p    IDATHdxәM$Iv e @1ݜ HdY*I$IT.  v (f ɴ&I$IRM  2 nzg|2iL7I$Ij2 .  vs>5Od~$I$I` Z  3Mښg7M Hdt%M$Iv e @1ݼ(yɠ,&I$IRi  2 n H}$I$I P` by@23?~$I$I*` Z  3[{ Hfp͉M$Iv e @1-jƭE?1 ?|{}$I$0]  j P`7w^ /o$I$d @-]  Odǿ+I$IT.  v (fα~b $ӿ`&I$IRI  2 nZ_'@277I$IJ2 .  v7-LfyNM$Ig.  v (f5'F?3 i$I$I4]  j P`7M3 ޙo$I$=v e @1ug@2kNo$I$=v e @1h5h HdЭM$Ig.  v (f2Lk.M$Ig.  v (f.ZS ~$I$Iz& P` bQ[9L$I$I$]  j P`w1jF?5 v~}$I$d @-]  .HK;4#LfyN7N$I` Z  3] H}k$I$Iۛ.  v (f8@2|*I$I P` bS?~n $3&I$If @-]  .NuD?7 &I$If @-]  .VG~r $EM$I` Z  3][N~r $9M$I` Z  3]z'@2ׅ7I$I']  j P`w| oq}$I$i{2 .  v=~iFg@&vf'I$Id @-]  .^{~v $>M$I` Z  3] Hφ7I$I.]  j P`wg@2-7I$I.]  j P`wjd[
o$I$=]  2 zf He7N$I` Z  3]̆(L7I$I*]  j P`w1럿.L$I$IO.  v (fuOxw W7I$I*]  j P`w1k@6aZs$I$2 .  v#?~~ $9M$I'` Z  3]܆}+LM$I'` Z  3]zg!~$I$Izv e @1ŭsě Ɍ4˫wq$I$=Q  2 Z  ɴ'I$Ie @-]  .vD?A nD}$I$2 .  vGD?A \yL}$I$2 .  vƏE?A =xs}$I$2 .  vHn'I$I3 .  v;6Mo9Lw8I$I.  v (fmG?C _O}$I$ P` b6IqQ}$I$ P` bg@6nso$I$I` Z  3UkF?C 7N$If @-]  j[wE?E &I$Ic3 .  v" oN}$I$ P` bV/F?E wjvq$I$=.  v (fmu6%)P.I$Ih  2 Z# d$I$v e @1]=룟# >.I$Ih  2 mpődƏ~$I$Iz4]  j P`W@B8I$Ie @-]  :9P8I$Ie @-]  YMoE?I 'I$I.  ` @1]=훣$ Ɍ6I$I-]  j P`Wy'	@6qү8I$Iv e @1]=~ $9Oo$I$I  2 [kO~$I$I2 .  v[~ $3}s}$I$` Z  3ް)Y͠,'I$IZv e @1]=9_~ $9?8I$Ibg @-]  u|k mAH$I$-v  2 _kM3E?M tf$I$-v  2 G?M wnW~$I$I.  v (f'jpőO*I$I7]  j P`WOTw'& 	o$I$iq3 .  vD~u '8I$If @-]  	[-G?O 'I$IZv e @1]=Y.~ $7N$I P` bzG?O n'I$IZv e @1]=Y<Hhp17N$I P` bzZw~ $4~'I$IZv e @1]=UwG?Q jY$I$-^  2 ( 	uOP$I$-^  2 9_~ $4'I$IZv e @1]=Uo~ $4?8I$Ie @-]  j}AӌGZE$I$-V  2 }E?S 'I$IZv e @1]=]7D?S 'I$IZv e @1]=]M~ $4'I$IZv e @1]=]_Lh<nZ_;'I$IZv e @1]=m4
@B$I$I.  v (fixO~$I$I.  v (fy}S ]8I$Id @-]  j{
@Fa9I$IV5_tO`ӿftEMd @-]  j{j
@Rc~$I$)֞/l:G靻pF3^S93d @-]  j{
@B
q$IRx~4l9?|vݩO3d @-]  j{^1Ko$I$MjMm4Ͱ_wm P`޽UwoY jGشSvic֦ꜣL9Ӟ1홶zM6$! BbDD@
!"% ~;S$dk>;{'vT
@)[th$IeKg9;q ?:	 P.  jO~G? 4Tss$I7e_;M|TL>6n\wT&d @U  f=-[tHJ(s$I+fyiqem۔RQ?7xb?d @U  fiG='I$I;[,ze)ߺ>Ǧ46` v (`W{F? 4(O$I-wUJ,7	gՄv ` v7.h#@C?ȣ$If-~eꮘW|"פbr[kB  Te @iڛ:R#@Cn8!I$IjPiyiqem۔RQ$i2 *]  J3^`я- 4z;'I$-?uJs`òo]ROM` v (`W{[&*F);UwN$I-o^Ͻ	 P.  jop|c@Cu?wN$Ix-:4uWN+>8GS%E2 *]  J3ֻя- 5;'I$)SS4ܸ2mJ(2F P.  joˎ};'I$i`Y>+VMRu}J^Ko;k@  Te @i*S#я. MT)D$IjdҙjNꯛH5lHO?	 P.  LݗD? 4T9I$I+fyixEx?j^}?k2 *]  J3UW~2<I$Iڋ&LRƕimߞOn@  Te @i*S~thѣw9I$IiRFܖR>cD;.  U Pʔ-:$QDEc^~$I$XʖLUsRD7IE?1WQ?M` v (`We`.x$I+fyiqe*| 3g @U  fo;;7~$IFwďgsW	ɉ㟝g @U  f.h@C'I$IM*;᭩znlXSvS/.  U P9_ ,;MN$IcҙjNꯛH5<)2 P.  tO?P%I$Ic^]1;KÍ+S}KWyQg P.  Ja j I$IcՂRg[=74ڶ)b՝}(;Ua3 *]  J3U돋~hG$IYtf]4ذ,[ק4FM'XV` v (`WU]G,['I$qnw՜_7kR}?8c([g P.  Jqo~hu$IT-:$uWNp4ڶ)75-}C[v ` vU /9I$RHRo4ذ,5bUßg @U  fw_PE4`['I$iҙwvsStV o	.  U Pֿя1 9o$Iqnw՜_7kR= P.  jϾ+1W|"I$IW٩v^n\F6EU:~6]{  Te @iZ萔Fy@C]~$IԲ:giaY=rkJ(1?~<]  2 4]ME~ f#^~$Iܲ3Sw՜4~IʷOiЉ9ߗg @U  fhxя2 =o$IQ=ݩn"פb读:R;Tv ` v5.H@]~$ITHS4ܸT_oiWu` v (`WSю e['I1o|Vꭞ|AWYR3 *]  J3Քя3 M5lѡN$IcSğN>7ܘҠ]w{u` v (`WSUuя3 ]5'I$)l+Swo^ǢB).  U PKg lǯ5u$I-<8uߤ_HœD9њg @U  f?~hѶo$IYzοo]Rޏ	csۚg @U  f*;я3 {'IeKg9n"] 	Yq3 *]  J3TVlH`?~$Ige_+fH5ujsg @U  fli lxN$Ih9_;/7LmR*诏8ok.  U P L"{<M/I$YznlXS_~*3 P.  j*+я4 'E;I6-o^_	cPv ` v5MҠX`+?$IZ]1;sgO%{  Te @iX`ko$IR#8po/话WѶM)E=EdǼ6 P.  jp|c@-|E$IUORo4ذ,[ק4ERvk?Oj.  U P~h~$Iƹl]5'M|TtG@ϗg @U  f.[xR$IE٩v^yQ*^5`xߣ?s.  U P釢m l['Iā|V]4ܸ2mJE=Ʌ<]  2 4]MG;~ L7;I.;᭩znlXS&|yR3 *]  J3tD? 4\;I,[:3uWIu)߼&'rcfrϪg @U  f騳עm nxN$lRW}7_g
~=]  2 4]MKG̯`Zir~7O$饚80uJK>WѶM)S@݌g` v (`W衛o sN$GNxkꭞ|M@g?ߚ.  U Po է$IjwٱoJ8~L__*&kB  Te @iz}0ׇ;IԞE٩v^n\[-R<``2 *]  J3t);7O$5Yzn~3imSJ(bll@  Te @iΊgp~$IR˖L?|9 3޷?+.  U P/G? 4ֳ$I8jNꯛH5Ⱦ%9	 P.  j:_G+n?#I,[]1;KÍ+hۦ/ \ڄv ` v5uG|	y$iZp@,zeiȭ)* S"` v (`Wڑ?hp;~{͓$IlԻ;ǹ):_K M~%៻M` v (`Wۢs .rm$I?&RyM*ǣ S;.,nB  Te @i    IDAT7t e_~$IԔ-|EꮘkƕimSpo܄v ` v5Vύ~h~$IR:g`ò4z֔FyW3d @U  fsD? 	y$˖LUs%)ߺ>A'k@-n<)3	 P.  jڛ?#E? 4\C7O$=la{λSD7gC
_?:s	 P.  j_G,'IRk[xpꮘkƕimSJE 1vd @U  f}Q~h~$IjEHRo4ذ,[ק
 4Z7 ]  2 4]틺я: -߿.I:'t]4熔:;~y=hB  Te @ieIiG? 4]ys$Iu.;浩#SO_KE@JwoD2 *]  J3վjoF? @<IjSw?qqem۔RQDs vwߍd @U  f}Sw Z`x7Ol|Vꭞ|?z; P.  j_49'IRtҙjNꯛH}W4Ȣ4 t҄v ` vʎ}c@Kt'IҾ,[]1;D7X ho7M` v (`Wy Z`p͑7Oik9_;/7LmR*4˖!5 ]  2 4]ˆw\Gny$MIORo4ذ,[ק4EZ d_.  U Pe>Ec~$I۲3Sw՜_7kR}20Fy?#N5!]  2 4]:G]'IK6_ \m1/p߬d @U  f}ڂS{&vT'IK	@OnYM` v (`W:Q}bIGDݓ$NxkF~6	 @U  f}#{ Z$I/V}.|Քv ` v{ ZbpiwOwEK j wmjJ  Te @ieMiG? @ԃir'Is	@ f5%]  2 4]E4я> -~$I]?}*-g߬d @U  f7>I_S	@~.  U P"}?G? {$5GFJ jՔv ` vQv[} ڢl'IҮtJk߬d @U  f~hޥ{$FI j`oYM` v (`WQ(%{~$IUk$ 5==7) P.  *ڿ~ha/e}$hG @oVS2 *]  J3UT9Ez'IҏV<h~*f5%]  2 4]T~ h>$I?#0DPGDjH  Te @i,rM+ @KݧAO.;:toV2 *]  J3UdkE H	}$se?}߬&e @U  fȺ+7 E7}:Iu@-f5)]  2 4]E->,b 3$I;]'ѧ2f5)]  2 4]E7z O΋> oV2 *]  J3Ut[Έ~ ho$I;\4,PoV2 *]  J3Uts_ ZdO RWYM` v (`We'55 e:'t$)]Ik"f5)]  2 4]C3ߍ~ h}$7$P~.  U Pơѯ -2z'IR6$Pݳ+f5)]  2 4]Cѯ mR);_?IR{2PS~1n5)]  2 4]C3~%U e_'Ijo>Pׇْ߭&e @U  fhѯ -'Ijmݕ}
͢V2 *]  J3ոwU @-}C$ @7i P.  j\_=?u e_oO/> YM` v (`WR: 2k$(P=߬e @U  f鈗4F I1Jْ@IR=|KLjZ  Te @iJ 2K?~$I> @DjZ  Te @i.~% h+$]e> D?[M` v (`WTwG hcE$)~ Ds[M` v (`WcSѯ -ӻ7PԚ@MtN}gjZ  Te @iFn~- hޯ?IR{_wѧȎymjZ  Te @i/~- h|_~%Ihxї:irմv ` v5nu?](IjGwn>{ @v ` v5neMiG L~(IjGEx~.  U PƱ#E M1J7@IRˎzu&~.  U PƱ'F P(Ijv} ew P.  j~_ Zh(Ijv?} [M` v (`WXvkvjr ا"eǿ%J%譞~.  U PƵѣwF b%I{.>u D
[M` v (`WOG V<`&:'Ljb  Te @iz,~%I+;'(Fi򈗅߮&f @U  fq-[ꯛ=O 5Q<Pjj  Te @iF B	_;/PVS3 *]  J387ƊW;(IjV[ό>o pVS3 *]  J38F" $Y%Pk[M` v (`W\v웢_ Zx4[(IjHOiE7 jw]` v (`W^}Kk@Ku}O$5o>k H]M` v (`WF& $V@dǿ%v55]  2 4]{? V,e	7WoWS3 *]  J3ո9mѯ	 -'"FBIR=|KI&[V3 *]  J3U*z0U
wRO 5߿.v58]  2 4]աΏ~U hbc~%IsƯF_3 jdxᷫ P.  ._ Z߅BIR}_S@v ` vU:'|@m
6S@ᷫ P.  ͟mѯ -9$} ~.  U Pp_ ZlpPT2>c HvW3 *]  J3U]+&KCIR':tW3 *]  J3U]{(IWO>_ {
]M` v (`WuxW]~%Ijmv ` vU~e hb~%I([ʔFyF._M` v (`Wuw_ Zէ$uW~fz_ P.  NeT+@۷3o$i\$lP39~5=]  2 4]խbѯ -=7$i=!dP3٢CW3 *]  J3Uzfk@7~.Jƻl!)@<~ڐ.  U PVE6 ݠŇDIF_+ j&rMjC  Te @i[ْץTѯ -׻7Q4n>-TP3[N_m` v (`WulW=|K=$oO 5_߯6d @U  f:6W Ro$i,@uW^kC  Te @ic @zfM$_>} ~ڐ.  U PXvԫS*Fѯ m7Rvԫ$i,BP7^\kC  Te @ik~31jT>O ;oXK2 *]  J3U]?.4vWM$Os~'4PCMoX[2 *]  J3U] vwQ4n>5,PC
am` v (`Wm)W [EIR|g釣 5߱d @U  f:?p]+ ;IuwQ[3&"PSS~ڒ.  U P\~ `_]$6~i9A8(%]  2 4]չ
N-ir~Q{ 54z֦v ` vU쟊ѯ =?FIRH} X2 *]  J3U v_~%I13@MxkS  Te @i{K?tNyGm$F} ~ڔ.  U P^ķEF [
}[G j,;ᷬM P.  	~ 9^ʎymm$-> Ty"-]  2 4]57>*Tm$H-ѧʷ\Z.  U PPDJ 3ɉ$igl89-]  2 4]5W4ʣ_' Eox'}
em` v (`WMi7_' w)6JR}? Pc3~5,]  2 4]5uGEN <(IS@-|E=k[  Te @ijJݳ;u8>Jѧ=q_-kc  Te @ijLԟ~ "uϊ)/[AƆw})1]  2 4]5ޯFR <[
'O 57{v ` vդ_W
 oK7HI6F=@uv ` vդ:'=\4FJ>- 4@tfMkc  Te @ijZ_+ xt~#%IS/E jx{v ` vմZx$U/[AY~ښ.  U PVZ>&;)IV>) 4{}ښ.  U PV?
Ի$BHœ[	 ]w P.  쪉\jyMN~'%I]S@Cdv ` vW~2]];)I*衛 Pl~ڜ.  U PXwFZ KwJ[)Iڻgv	!w~!9]  2 4]53Rw_/ إޗ,VJˢ ѿZ3 *]  J3US~ vi}~ʮ$ըβKE bOmmm` v (`WMw_/ حRgo=3l EŇ߶6g @U  f~
 ckirReK^Ұ}6 h߶g @U  f&7zW v?ops@o?/=]  2 4]55GFb [-ir{)Io(F [3 *]  J3UW ^T_KIҮp| a+f߷g @U  fF`Tdߏ~ `g&3%I+[Y IA<'o\3 *]  J3U~^k /է$n8!< 0n
o2 :]  J3U] ^T}*eG&fJ+[z?])/D8 P.  eG*0U5~i͔$=Ɠ ;}7N  Tg @ijC_5 xqNʎ}c͔xg2 L?=` v (`Wm'_5 xI[
<7 @'qz.]  2 4])K+FswSZw,/D9=.  U PRѯ |˵7Sښ ӥwɟ9  L]  J3U[ HMIj[;>{`t
uz.]  2 4]ߋ~ `OG,vJRk8(O 4Tٞ&3]  2 4]#~<A_)I-@|% P.  MDr GS);S^vkRy"c_{f @U  f6ջѯ 7VNIjz[όg{f @U  f6-}CJE)F~?%uu> `z4yo~.  U P{Gv Fޑ&~?%qMFFnyz^  Te @ij[뎊~ `Uտ?ho.  U PVgůEv W);7TRğNiЉxg @U  f5T<W /PIjH}WF<e{  Td @ijc[ϊ~ `u}O׻C 衛^.  U PX?~ `OTײ3S=q@K~L3 *]  J3U+;)'_? k$ձ3R~e H߉zA  Te @ijk]G~ QwTV+O'8 mv1` v (`Wm?~ iѷTRķl7 -o6i P.  쪭eG&0RTF@v ` v
@9(uW492]}|3 *]  J3UG P豻/4uUU}?&'k[{
    IDATu  Te @ijs
@%>~O%iˎzU*1@~5j P.  35"u{*Ic)Oh ZB6]  2 4]u_C |,eK^~S%i\_=?[g @U  f9~ۗwU~])e Z<&~v ` vHG PYUI
,;M;8 DnZ~ P.  J?*@u^vx]&Lwn$k2&E3 *]  J3ؕ~,uWn S~~[%i_7` H~&&3 *]  J3ؕ~,MTt~`Jw_&ψ ~ P.  J5 L~[h iaY]Kg @U  f+=W?~`ꌆ{oWI:o `lt}OmKg @U  f+T~%`<o4|+z0 3?~ P.  J?lxEѯ$ L#K)7V#_F ?=` v (`Wa/ѯ$ LυXI
 _7R{.  U PòHiЉ~-`/;+I?#n>5# ^ ;_IQ  Te @i$WRw՜;+IU|OS xcwHy  Te @i뭞Z(O)T1
 4;=` v (`Wz~W_M 37[Iڛ}, v{λo<]  2 4]~5i3ڶ)e'g)EG' Z2M{=` v (`Wza/ѯ& L|˵ƾ($^j2 *]  J3ؕ^XvO4F 0W3$K)DT]𛩽` v (`Wu= m07W~E2e P.  J/_O '&$={x1h4z𻩽` v (`Wuْץ4ʣ_Q 'm핤O(?`]~; P.  J/ѯ( {״{g 5V)BmLMbj㎩IZchbkպ5ɶScq3  QA(i rN9ڀ3{?u=V0Uݯ| Wֿb vH7~j3 )]  j3ؕ}D`tat|o篤knI;,R=qϰQp  4e @mW"A1vߓ,iFZKn>!֡.  M P4GgIgXG(Z:ǽ5T2 )]  j3ؕ> 0zFWE؆ jǣlS` v `WzϏ* ѮEs̯l:t\g @S  f+w\}T GUEKAD}@#ޙ Д.  J?Y}T w{'?%MpsKwɧ' 0ɪ|V٪ Д.  J?b~ 3͕ɒ&bscpiW ,3?[,]  2 6]i|
 e;.Kڇc. X03(U2 )]  j3ؕi> 0΋־Il4um6 ƠŪ=?c,]  2 6]i;[kT-G BQgI׊gG[f_S w^9 Д.  J֓, rk?%OgA? LJUv h` vsdY +>Mђ|Dޜ}-(Q+V3 )]  j3ؕvDޔ}l`Z9Ӓrw_&*o# X4[G韹Zv h` vkpq O9yN4_?| ]ja2 )]  j3ؕvΗޞ}l`<UU.ܒkI܊gGyp z^_` v `WF ckhlIR7D Ffx響Zv h` vg. r-QlI]A7a-X  4e @mҎ>糏. jkے>Q] /Xb-\  4e @mRʇo> 0A._7sfvKݷo H1c-h  4e @mRz2qA-i;Q=y :+3Y.  M PTbK#aQn;ڟgᒞ^û/;2  ]y2Z+vMlf @S  f+ox׳0 LrDk?%X˗G:7 w|ւg @S  f+կ{> 0oקK?5$6 j 9Zv h` v=|14DOEknig4cxٷ XY` v `Wj/gc hûŁ?.R[` V#?8 Д.  Jfui+|Yn:.f{ kc-s[.  M P԰e;E SaxQwi*{^?_ds {ՓGkni']  2 6]yk> 0=]<Z˟/MzŪ=wɧjo> 01WNe @S  f+5}/fe :÷SR͊5{EQu> 0Y*ڇ.\.  M P0ܞ}`* ^Y/MBgquhD> 0]y` v `WZzeqkE}wK̗Ʊ!ME{٧ &Zkq3 )]  j3ؕbK"AV=PtH/CϿ%Q' L^+U{kq3 )]  j3ؕ X|FGkN[n `n91s^.  M PpuN# 3|o[sKbOGOE Sŷk3 )]  j3ؕe;G5pS>p}tE}/m1g5 ZDkni?]  2 6]ia_c 3kV(7ޒ} `&"_` v `WZڇ\W>|۶ckŮ?HmmM>F 0;*_F.  M P_}ۋGw(V j{ۿ{ ̤.Oy@` v `WZ =Uo>7~!ڇ.iko-{> 0g/g.]  2 6]i+V8*1XFt{k斤̠cx~i  [r4v h` vip	 xwFOEqnVmF tlm  4e @m7 `ЍEߊֲW]{UDUf AF.  M PH-G> koYBU}w駣|ƈ l3 )]  j3ؕ `r梽?Sh*atOt\T[
 лO3 )]  j3ؕbK#a1 j{>?_(e;G_7WE >Ū=3 )]  j3ؕ& tW=$:m#5xyM.h7UwK?= `n8:gd @S  f+-nSޕ}ERuG+/OCZs]|ژ XD#ޘR2 )]  j3ؕe;G @ѿ|wӶO`wNxGopyD }צ,v h` vůw ZUFŚ&F{{{Qn%f t~_'J` v `WZ_Q; twn?-z}":j}N)S]}GoK&| EkŮ?(-]  2 6]i47}qS|zr.dtM۲}{Gﲹ?#G1g
 ՟9F Д.  Js;; 0!֣17bp/:'hm#iF(zEt_sP8?6D1 }kQj  4e @m҈[` 6myb`pqѻ3=Os[Q#gmQ}IxctNzgtOrR"?r5.  M P4ze ]r]1n879~o}m ֶh(~U(a[[׶[olۢsoF?O.TZgn Fs勵)?]  2 6]itm    U=1ZwIR~  4e @mhvj   )˗	i<2 )]  j3ؕF[縷f{   1F%oBv h` vW>>   ̄_Jd @S  f+ޅ>    3}/i|2 )]  j3ؕF_"z   0Ն?<H.  M P;_>    Ss錄i2 )]  j3ؕrj   07 W  4e @mR^e_    SwG~4~ Д.  Jyu|O    0uh=G.  M P]@5    0UW` v `Wʭwg   1Gٗh<3 )]  j3ؕr+xqĠ}    L_Nf @S  f+7W   Th-o=v h` vGBU    0^Σ` v `W\}    LΩƣ` v `W~u    0MwGkNo<v h` v1iNQma    0~0}Gc.  M P4>.+   `T[gh3 )]  j3ؕƧb#zk   `.:v h` vjp糯   Q?bst4 Д.  JU}"*j    >` v `Ww=j    {UwK` v `W:'3j    {֦h2 )]  j3ؕư%Q>|k    0(־$G.  M P4u   _D&/]  2 6]iL[KTOޗ}E    rAe @S  f+oK   0vn` v `WߊU{Dy"    Uߐn` v `WW;&    o^` v `W/
   Gb{&7]  2 6]i|    gh3 )]  j3ؕƿGTeu   *}ϧh3 )]  j3ؕ&}]    vj&?]  2 6]i2    G9g4 Д.  JSy   |B#]  2 6]irW   h>2v h` v	jni?~   02d @S  f+MV>}m    ƠAHd @S  f+MXw{   E׿MU  4e @mg_    kЉIte @S  f+M`+vꩇ   Eӿ7M]  4e @md_d_    ׊b^/v h` v	mQ˾B    \5o/v h` vɭw駳   U7G.v h` vɭXgTM   ]7Mo  4e @md׻|y5    '֊ghz3 )]  j3ؕ&bEy"*   h{{Z4 Д.  J_W	   @#[54Eӝ.  M P40|u   P[Hcg @S  f+MGkʾN    j~oV4 Д.  JQf~;J   10ڇ!mE.  M P4=;,J   !|1ME.  M P4=k_   ߎISd @S  f+MWkʾV    Ko)v h` vEQud_-    Ϩ*b祿h2 )]  j3ؕ7Wf_-    ϨwP4{ Д.  JNS7e_/    ZKf/]  2 6]i:]W   ?soh63 )]  j3ؕG5p   n87D3.  M P4.X   ?kL4 Д.  JSgE   6+/Lg @S  f+Mws?}    D(V>7D.  M P4-)ǿ}    3{{I4 Д.  J_f_5   wM斤H  4e @m44ʇo;n   YT>#.  ` v٨sʻ   `n8:]D Д.  J3ܒ(v   ̐9
v h` v٩s[   `!` v `Ww}    3|d}"v h` v٪}EW   0ͪ*:_ ҏg @S  f+^o}    Slpӱ?.  M P4{8   BU(9jL3 )]  j3ؕf:   P{HO.  M P4[TOޗ}   Sdxњ[!=M  4e @m=W   0-h{}{L Д.  J3()   @oO` v `W:_z{5   L;Ojod  &.  JyQU   L!mO>.  L8U]_S  3IDAT]  jkI%^wD9Ⱦ   	4i{+1  0v uI%7   0U{S~!&۳  ` ڊ_H*)b^Quʾ   	=oҎT>c 3 b鏤ƣesW   0!^%ҎT=y_ ` P[qI%I+叾}-   _Dsːv赲O  ` j#sʿ;   1׻ob 0 )(4V(j   TyliG+ 0 W>P*ijA7z   ͠u{]Huj' )` @mK>P*i_}`   "B[>B  L]  j]}`CXGTO=}E   c[ZSTy>F  L]  jRIYe_Q   8t}>oRW}    6RIcܒse5   $]w
agd%  .  O=P*i|k0   \e;QHM+!8 0v b~Ů鏥ƷGgT   @A7ڇ6!-DU{s `
 HqK%o/)   Fw_KHQٗg'  .  tNL%w4   F|h-9MBZ:'3H 0%v hwSIc޲xKu    ߐ!-PK?}    42ۯ?J:JDUf_Y   "}!lp)
 )a @#?J7~!   𮋣5$BZMwg-  .  TUVh*i+ξ   EPb^B4  ,]  kSIQ?̾   EIwi>Z  L]  ]<T4k   X@> -Fk?}  "  46&WFZW    Ũ|# 1 n+vJ<49.d   4U -F/S 1 `AG%Ul(7ޒ}u   .LHu# 1 `At/[*ij0   jwm[~9 0ev XO@4y;,   vP՛^ -ZsKj=}  2  ,?JU{D   sޟ -fcE1 `
 `:g7!U9]    -vo>j  L!]  LY&s0   '(7Ū=EmniTO=}  B  ,~'Z+P4qk_U[   x:n7iO  S` 9&;   =#o( 2 `A6*iB[û.ξ   3Xf4-# 2 `aZUIYq+>}   M(Vf 9>r  L1]  \?Jܺ}8   t}ԛ
Q5S 3 `c۟~\4-}  ]҈j; 0v Xc~5UV|Qu̾   `f֟> >v  L9]  EX%Mvs?}  L*7~KFU"E ` 8h}YCnxٷ   ̖A7GR4X}    ,ޕ?J습/9:  ꟧H#mDU<}    ,DV>7UD=?d_g   0 #u  ]  UO?J   ZmZ{4VՖ  3` EU>`/vëXҨڛ4   JU{syui./ b ^^%M~ݳ$:  S9QW|nTGO   3` EW?}9=In8/J  _ߗ2]6}  1  DJ486f_i   0w%QWzG c HTZXI_wDTU   |(V=_hp뗳   3` ]dC!W   LY}>樓_  0 `taYISЊgG[   &OUEn/el(1 0v =W|n~}  D__wz)E>  0]  Fs?J$J  1h-M>/eTV1 ` 0rZZIpy   rQxӬ6$w_} q  |b#EQ=P   c<u{~  v >wj%MG~=*5   ?0:'vww)!%$ .  y'~?`+i:_}`   c?K.|(! 6  ?+V0|;Z  1RbdC  v H9??Jڇ\D}  @]Dkե:'fDUfE  v mEץ?J~(V  TcwDOG*zETG    [c~n35   HuXRZƛ"  ov [O̕4+c5   a?:_|[r)_>  2 `t/D}"E   #=ǥz|* 2 `[@$-Pݳߗ}  HZ=\ʬ{{"*( 2 `TQ;Wt4   ,s54;U_t"  <#]  Rh^ISЊ]|;   ,룵sKI'~	  ;]  Dk|%M~AQ   twkJ-e>5Q=PQ b X|__I_QU   ,hyum)WFG  .  co_sɯ+   z>߳_dE  !  Lwω%Mxv=Wf_i   P_9WdҿcKI"MweD  a  L-'aI]%Q?}  ~߭ڇՖO"  b Dl8??;aXd⿌(W   esߩG)c  j3 `_[ɮw駳3   nI.-e9n>  Ј.  ipZbIܒqAu   ?{_ֲKK	u T0 `b~&XV#Gg_g   oӿCK#onI._} ` 0ʧ?Kڇ:   7妻8ߝQW~~7G  .  ׎iND4uvZ  Rmy06;4G)?>  v Uk?vNP4.XM   T>lҨ~} `Q 0U?2Zk~:aYd6   3noN,b՞e  z  LrC>W%M`˟ɾ   U":Zciu/ 3 `:}su/9YdUI  {9_/F֊]ڈ>}  0  L7F?>KGBD}  0+atҨ6d<  )]  _1?4!Z="*  `UUt(*V??7 d (Ғ&7We_]   LEO+-zsK{$ @]  f˰+?RKpy7   Sw"ۢxKq t  ̤s<XKU{Dk  )ӿb>ln87 0 `.ߒx-i+٨Zf_Y   LMEknI]i1j{}n;%*  ]  ~FN̖4~}c  07)ZsKӿJ]{1r}  `, W1p~|㶤soG
  	5h-)u?P  ~]  q0őoJ4~gٷ   hpIƺ}Ntyo>Z  01v ::;BIf_O   L3lRڇDޔ}  ` v>~/%AsKcpW   `p)~&%÷e'  h  #?+'ߺ+z+vWeJ   mj"+~U.dސ}  `j @MeGѿh1?xfb|  14YZswWiw|ѿjMݔ}|  `* (luGw]%BVd_C   3u50:'N?\1d  z  |^({CfIŭ}#z  10XlFOUUQ c  <]ݯ&_|[VH/i[if_9   $|h-%;fϊbK}sܯGwGOD[bxQ>r{Tc  7  |Oj8 :gQG9Z(_Rz|4z   QmQ>tm%?V(MQvds  bWl8\    IENDB`PNG

   IHDR   $   $       	pHYs    {Rk  IDATx[HaG.RQC=DDcK뚮HQhI(a,]TcK3v\O̠Ks6p^rw|90̲DۉM8WBΨVoWZB19WEIWi!C}gBA|u^eg>ϐ_T	I u[!Ϥ.? 8֝sxJ${e~ ql</(|<7݋v&;C{kH^;p0Z!(MLǝ |y܋k@[xʔa7[Yfq
qICiHH@?ƂIa)[ك\@@`i:
D UQUzjbԨ!mZbg 	H0JKQGf"Co@)4pBT RQH@A$C'RvoPD05Rq2'{7R}D{WN .RrCHX)Q{gL`k} %``%Nu6PO MG/~Cyk?[!x$(h^c"Vd:mRO${u4"t(gժ
rS[oͲM B    IENDB`PNG

   IHDR   `   `   w8   	pHYs    {Rk  IDATxylUEA-Pq'FK4JP#QYbP\HEbFCdIwB	-
R
J[R.t;AZf޼9o{̝9yɓ'O<b*r=+!-@Ң,b#U1sIi}fC^\7!kp7vBke\~=i-CfĿ qɛaaeJO:^?ϰ3vmSP7i;2Җo	iG@J`J76⻂~z/tBWq1Y{3!#gyO`Ό$``Ԗ3[f=@OLJ+]> 2	WN. 0rcQ}{>h2@;lЎ2 1w (;uʨ?Jsv
Ƙ@S.Qkvd b;p3F]gw'(MAAZ|BT!SPҚC@;KqoVA?U`NĤA] 6!3r9o^S,}¼'6|G^凬 ѵ(f ~Mo -$1k{z;b]`:Nl%?ğ \5 Z!ļRxs.=AZ1PKV POrdxBl[ 3( ČM`x ܛ	L@Y4t&a u)u@0dH`H@;]yCP  ]q pVE H&0	h8@4uW@ eK&׶hy-x)
 e\&0	@GF&HkƠ 0Q7I ^ԍ` ?4 bԍ` B-yXF0	laH-Ln g$ ih  m3 y @Ӂ'a
 92@Z	u3@քv PS$ `ĉa 9EC@ݱk iX3P79 dQ ['P7= A\@+ͥn BSbI uS@`IZuS@+]U=K1wڝf捒7͠%@-A`4o2!	$1P=Ȥ6h  Km5b;m$TJӭ:`kBM䫂K76Ƃ̝ i
6EҎmf65kF0!3 ycy4ӓ{zh9u']IuĒ-4 W Hˆ?2 =$e :@i!֛ ʮ(}Ӣ u$-@؎aX6n>?fl R+P\ 0xaӣ0#H;3`y VR\ڃҏ@ `fϘ5?տmy
T{b".NH0PR6hP lBg~b4$v&( 'o~7	;Av0_U)h O[Fs#ͭ=ÂO-0̗edRדHu>zhЖQ[a֑GנoC;Ԛ 3-%pnt 	j~2+͡) {䩹gȪ ޒ,n|ŖK%!ވjBKAePcᵏ_=(I9q
tgi7;MM1a;5r-\|Za"̇P8ɨ>=H ЩٗŜc2.%v׃	~.5T@y2\rZ3Sg
})EzO<yɓ'_D}    IENDB`PNG

   IHDR         tL   	pHYs    {Rk  IDATxyp/kV[j-mmGҩ]֥t鴝ֶ$1!,dQ!Q\(HHoso(Z{=̗?y|{ 1=XNXXNXXNXXNXXNXXNXXNXXNs '[t>!|uJiEgUg7'}OV>n)ʳ=_VSceG@7dKsN^ߩ//g|`8/&ʎhݜ,k@>
[S}֮okxiw`O wDw- lF,=r+ 9X<0O]NLX~D$-/ͽL>D8.5l5@AD-/ j=c&.^
nX c9؎]gDUUN鿂#T# ڸuaUNTʤo3xrD;*$I6>ƥ`tősғӮ<QL3󞪜:2HfΠ+[s0HT?	޷$IԼ599eZAyysY5cё3\3^L;ׂU|9fͼ|9yPqZ|tGP$ޖxq\oŠ/Z7;ZpV1jaWqZWPjfiWHKyw](Tq=͓W[^VWǴG lPhkj͓3~%(=oG:,^-C3FN/CA XGkU
`Q9r@9v'LVO^I{9r{3$NpF|GC p ڴeClȨNy)wQO(U(YFGwwe`	%W{+%Ԡ]:HJmR#ng9_]Iy\և]⎽"'m|3j T.{]D^>~(hy^1Z-p_I-9S!+n7!ر-"2߃7"jSޯ]A۹",/+DMu6E><s]NyL$\=|lq)/S?sߣr+' k,rKp5+;9d
z夸FrvSpkF/0Go3ONg@8R,zt/j$v#2џ 5
r~97s@xWzq9"9gԐ!9W@"m@h3nr$r^9e&NA/0Ghs"<qD6rʦVQ[[(2Ghs@s^96RzNQ9K-oԈZ^`/'^CusQٙ9'g|P~ErO	($N!PğO"s^9e+&#ʩ:	=$a#4)vr/M3u6^S
xSo@/4G蕓vWNK"Yrʣ(.4.4GhSw?^l+'ճI?F/6G/@Aobs^9q="ѺrR=,ӈSF0=ts^9f/b#)HR_P^p+'Յrv9B>z唉w)Mb"o/ыz夺Sʋ]t+'ss^9}r9c唃cD/<GS޿Qğz9B^@i.z9tI]`tA/>GS=ba#4)vb#)WP$l|WNw"=v-ΐsQ{~9>$1P{(	m+OwU/,NB?L|~9eO1<޽6Nj0K*c3l	_n@͒?ƥ WNFNoo"<)y7&i138Έ*ȋ0%v	-?}Nmu)[r'^3PRhp/W\S!vuS&P$zY|Q'Ifu$s@)|x!ڸ4eCӭMm7G?>1MEg'ۅ%rn[N]\ԐsIyp!}_wPCTN*nw%hE@lf,.Y/
@g׳S>MZDlx@9FTN@٠[S tgK]pDJ|3bF	GNo@Qϗ˫sBmEe9C.D5)"4Ʌ,t!)^^-xr'q'_.^.LQ^@
[\om rVOȩpMi4rs|V.y>ϨGNyTwt	R]?-P_"n%*MNK8mw6@ IB/ƽ\O3'Ki/TZQB@¾}egn7D?VQ(b:#VMQ'߶ZQ;
9"OL̒.-o_RTGoj<jPBG.BG|BI+:3zI񣵏&I'Sj"w:u%5Jub=eGꒅTȽ<ެ;y[U-JQ[ԖdSCM\9U/Pt$^H0Ffǈi{3Cv3)`Q$~~x9eC@rQc
kߩt,i%ӓrճIlXzrg$1䌕SNDb5;S;EW'Ɛ&*i9	rnrʵrS8po+[@85S.zv=6-Kt0`E52ᚙiՇA"qВ%޳Dl{';C$R9M>hWOI*}'JB9MP~NNKrkCm,Aˏ*ؕH!	Ɲu'@ShEPu?'޳AutI_[m%?9`UfP}ܴ^߼85@6_OFfVMwڍ`l0hNzt*;v𗏂0{ڕaa9ca9ca9ca9ca9ca9ca9ca9ca9ca90 {w    IENDB`PNG

   IHDR   H   H   UG   	pHYs    {Rk  IDATxylUǧ-V@[Ĉ1^A$i0D%x$^1*11.-Ki҃ZA-`mDkKHZhQv~IvM~&~ﳳ
+1$'G*URA܀KŅ`1Tk*3ro5FˈRAW/dLb LkX$	K˗'  BP^-gW &FIU7Mwq.ԝHZyWS&~2T +r)Z*zAr4]@LZt
HO~ M <HW [<Jۓ< 1Wb/o@ۛzk%P/wǕmF#bκ" ALXb$(a֢ t$Sf qԋ@?Xn8Z8 Rt+I(
jlxڞ k[vi1bp	`go0gh?R1ZKw$@Ƒ/ɡMC#~izS)([ QYu'.>Y ]
 )}2`J۝$+ |* e\  !op_҇PE39Q\@kYq'* e+|rG.:	X@eu, d3 * 0%L+i )/RHY~;* /@,iN4@#bYŎhR+ a)r 7ԚDroA/@Ei4@@l0EU$0ly/@gP@HZt5* 1 Ι_d+gVϷ`ČzBb1|USiuV ) y* %a$EɟJU<<+1 z>* kJFpŚAu9D
gcך-QsLGPa>7u%~)i5* ̀v`g)k
lKR뒜"90H(uϺ?HdTGs$"Mo,li{sn{teg<lx!PHL2uPk?W:L25]P X5y$6k7'\z| EI=@>HMGDrx.[@r:?bFE -mE3}&BQFo*H˦=7/3v$ԥn1>yNIWP)#rԥd	 dVSHd}ցPxY\_} D(/KČRfhyӗI7r>5i_VXa`S 5~9-    IENDB`PNG

   IHDR   <   <   :r   	pHYs    {Rk  IDATxkhEǷ*E|~Q[QQRXEUPQ~
޼$j&6ij5HT1MmD4єVMmؙ_f}@ͽwdmwvfqY&&&,q`3aZpoET$ӷ5ٖqȱ^	7ς[hYrt )Fa{2^tV#rXl&*ai/>"+AlS7-ϛzT_<?yfzw .4`>I=r;b!Hޟ|z8`-ykK`5W,u|Mp{'(X܁*wn[
([w's"z48\߅8	P[E`՗Rך`5k3S?е NZX-O6$!.?>6Q7fYឧl-%z?FkTȞlֽtO&0e1&N$`o`Wb^K
,惪Qيb69ti7	q{(bEbP^0>b=65w6qtCw#^6q	iE,#,Ҁg,>-gf­ٟ<*\+<{O)An}.;2yrxJ*f{Vr_|&05`iy[~Y=`kPVOxv6X>\GVAV{|mx&`e*A5:ݷ+<|WΥ9I/<+RUh`g_%ɷ%am}XޝUCFmmn`طߪ˪.<zW4-X}-d-lRu0Y*s|ݍ`IxQ NGnSg7nz#%IR)95@,$]קK']
^\QW5#0B,9ԓ1|AO]Z윢(b#s	~(ʊGpao\W+|+̟<
I
LL7`jTwC߉    IENDB`PNG

   IHDR  p  h   v   	pHYs    {Rk    IDATxww]{f	ʽ
6xT"r^+Rr7%3I&2RI@zH$Lzfw<w߻<k=c~/
`֯gD]EEcܢhˋ$%U(3    ᛢe;Iφ?AWE3\& ,-0SߎGGka;a5?c*   YR>t};a7rٯ`p8+|}hu_ $`&'   @rUQ|i$|>Z3ko(W8`̔Ǣ{:ϣ5/wIjK1h>J    R=ۥH]vֱݫ釲_01\<~.K6KڤZGvD}    Gcw6gifQ~Ot.\Go~e eI'埋濤%ծ}EG   X}^4o~w#Iz}F۳_08`g%G;_Ē&b0>b    R[e[H6‟e{Gx,3ǀGγXc/]I[%٧   vZ4n~#IвuD#2U36.\=ߔ-{d5    wXy$ro%T2X`ǿM4o24d7    wW8$i*WG5SɀHKkRl4Gò   ջ;{IҦ78_P4SŀjqfLR[yyt   0zW<SN{$IkѻWL7RKQ҈Zi   `aqHt\^Cɀ*wY4{KP[uoZ   0u#IZ6jfb`"pF*v?,¥Ykѿ#   `ju_$IZEߋ_30Q8yK~NhѿS   `u I·Ӌ}ޒn3UKYF#/7I#y(2$   2'a$i8{9zgϢ</3I9+_嚫"   FK~7$I^/zO};cˀWwR٧   l6uϧIWb\ցc(WKKRM1    H5h?~W$In۲_;0V8׉9ƒ_T*v1ʵ7dH    lq<`{)H4o_=08iwG=/'I"ʵ>    wEwG<W\&8Y돌$x$    ņ{6I4v1zT̜x"G8%$)bWo    $I[MD̔rQ7    &Gӣd;%Ih*WOݗ3`fto8:;)mqS   @%Ig~`8~ZJH]_#dL    le{/IF-_?02LX4Qf   @s)I4Z'}"~p0'soMH/rUG    u>/$IybZ2`*,;<E"i<*Vl>    X(e?n$i_Q?-Cch,&"iLZm(h   `u<OѶSs>ј[4>{.>    Ah{(Ivyc\kBtqF   ;]_%Im˷޷~2`*oHmgM    H~/%ImK-'g`p02gmAdt|   nJ4OIF-{	ٯ!XL֩)H7    fZ=$IoѽfjinQ>8h    YkW%I}Km_~A-L4Vm    e?ZG8Jmwo"dLe{ƪ;eM    n3ߝ~o%I}Ŋo"$LK?%W!h   `YŞoL$bGᛳ_EPwXY/i|j x   `L;cIF߆_WTbD?pU4vzqA/i|jg
    ϧXU}$iTD*f+724>[n   x\4kIF_!aX+OEO?%O?keO    LE+$I9lk6EƧwǠL   jgw\7dj\1h>}4   0^w]vzq)MˀԻdPu1Xw   _-I3YsFZ*d?z[4v. 4壷eM    L;e}IF_ODYfYp0V6,ފϽ54+rUG    S׹Xy$iu.;5ʀ:ῧؒƤ[Dγ%    X}$I9ٯ!M_?%Gswq    3}'$I##:Ekc\w4V,4u'X   `V:wb>o!>+<hIQ٧    3fP<ͽ$nL4E3_CpsYX>/$    fTQ.L4ڊ_e3 UᛣlYR~co'    @Fcnq]$iNW3 WYR~C1>     ~_&Iqswߥٯ 0 O}cI5?c1    AO{3Ihk~#z3΀SEcĒr+v<u_    ߯׊A?~&ImWfqhk܊G    <5)M4o~18-'r[E<;8   U>xm4o&IYc~'3`z(~K+)Eѻ    6J$I#wyٯf#չxU+)ŻdE    PIJW$(ٯf#S>6;m~Jʫ}_fE    PݠQJ_$_~08IH?h%_peE    I߳IFSk#:3ƀ?|s4l~JʩyFt    j)>˷Io$e{ez1D똏r*|cy8   ѻwnTzuD_Pet8oFcnq+i+!    XP*M4:ap0tͣ~3`Вͣ9G    ,~7Z/N4^p02U1(`4W}   ?ŮH$?aFp0T/z*iu    yXY}$i{>~08ik}   Ht/5NN4<&0`hZ'}< 4ښ+>~    `th9Ipk~w`POƲRI    f͠t4}{$iz+)gPl*it+rG    )m,N4'Q)gk?;FԒ͢Ǚ'    }:IZEdnb,ՇFVe;    06:g|*N4ap64'}<   F_H$~4,6L)T7MIuG    3k$IéWSʀ>LIï1h<}    h,2.OOdk)eXSp+Vl7e8    0~'IZ/QXh,G    &`>'IZz7a
p`_Rp^{Q    e|"=ސ~'IZ}42`A~4OXQ    XY$i*vzIDap W~HJ^̓kg5    0,K$-l~<̀<WHIiÏw<p1    GIvapP[x4K6O? %e[Gc    (Uzu$iA*vyyDzapP[CGIéw    *;Όܢ?IԿWSĀZn(iw    LY~'IZ,~0E8ߍƊ({'    L̓ߛ~(I__~0E8wE釢1h<}    T?S}$fK4_+L	jikQ:h   л;AIRwJaJpPK~ JZz}    LWzuL)a&+FcnQ(iaw
    ̞^+_AIҦ<&L	6YSCISQ    IߊbvMlVv)`&kPR=#    fZ#
%I^5ٯXPR͖m    g(IڤWa
pi?>%իw͡٧	    o:h{CIR'"-0`4T}     AuXe$Zޑ
a
pI:~J3>J    gѽx;DIRŖlkgBpl։o!(i*v!Oޝ}     ePF_JK$U|7΀MRP&4(}     /`=Q>NQo993࠺~7˶N? %Us    HkOS$m|~aAeoN?$Uu(G    PA-J6I~m08c?I*x}ǲ    znIc$p~m08}\'B˶+    `83s%I[+_L8*k}c釟{    PSJk$@s"W̀ʚ|'i1   )-Ns$=u~c08k>I/\sAk]    ,ktGIsW̀jzh-N?$@˶9    `t/X(Izz`pPIoz^d    0h~O$~o
&:/ГoG    0DwFcEJ~ysٯ	&tyL'ke    ^~)I:gm+	fA%~Izmf    [}ʟf`T>oi'^y@    Рh^~7)I~	fA%:Г􃵏h     $vZ$kW̀JZA'kg    @~O)INC13ࠒL?$}OKrG    hZ˿$Ewe`T<}釞{    0w~_)IzQ4W̀J&ГZGjĠ>    1>c45g	fA%~"Г(v}e~(H     ȠT6Rf9B:8釞4-_>    1Կ;LIT	fA%^oN?Y}     c}cJҬ<_L0*iCOjw    `ǣXLI8ÀJ^~IZK|[     0z7~)IX~08ĀCʫwݑG     0A~$^Sf-0)q-    &̠h"~Sf)0i{)ُ?    0z7~)IupP4Gދ}    `p]$HaA%hُ=    0O?;wJ,dATb!w{    `
=<Sf!0iD-:ʇo~   )}JҔgATb!7    Sf~M+_~)IӜupP4ZGj`    SwAw4pPpHíe<P    L`/e߅JҴfATb!-'g?    <yw4o~*IӘupP4ڧi#    ̈%߉J4fATb!b7Št#    ̊ߙ~7*IӖupP4Gދo    `ƔkƒH%i2*1Yh    3sƧH%i2*1o6m    `VuQRI8ÀJ8lQ>pec    ̸gߗJҔdATb!-\%    >#w4pPpHS?d?     ϬbN%i3*1[F    t< T&<0~݋Vf?     ?hPFs{P%i3*1<]n    ʇoƒR%iR3*1jl(91    x^3>*IupPu/3    xA(vm$MbaA%Ҧ<"~#    Qz7~*IupP	)    j}7W%i2*1׽hG    ;l;VI8ÀJ8j5n    I,KgIʀ:8ĀCВͣ|    `;m4!pPpH_    ֿVI8ÀJ8k"=zG    `A{WI8ÀJ8hnq}Y
    `m_%i3*1^Ι    ,K_%i3*1b7ŠL
    (|c=$saA%4(\    Mb%i3*1    ]~+IupP^ُ(    Е[J8fATb!={~l     {YI8ÀJ8uԇM    dYI8ÀJ8X}?h    \Ch%i2*1Uf?     9e4{ZI8ÀJ8=    05WGcnq}$KaA%w[UܒH    k;[I8ÀJ8ԽpE    0<ʗJ8dATb!(#~    F=n%i2*178߾<Q    /eo/JRraA%:g|*1    K;NÕ8ÀJ84^b    IDATֺ    `lp]$efATbYwqُ     X<yw4m~+IYpPphVk    `"t;]Iʀ:8ĀC3-|    `":D?O4pPph7    LUJRFaA%=8~     &Kُ~H㕤QgATbYW;    Կkw48ÀJ84Kp#    0ZGJ]$20L˷d?r     \{C4J҈2*1ЬԽx    `*O;_IUaA%5~     `z}+IȀ:8ĀCP5    9w48ÀJ84    `OGUw48ÀJ84-&Oݗ    L7,IC΀:8ĀC\ُ    *{K03*1дVN#    j[OMafATbiwqُ    Lh;aIVaA%Z/b0~     fBuј[~7,IȀ:8ĀCS(\h    ̔	?,ICȀ:8ĀCVԿ~     f{l;bIZ8ÀJ84M+3k+    93ĒpPph^w#    0ebIZ8ÀJ84-5}[DH    ̴KBfATbiǙُ     N{1X*0MC/Z    w;"X*0M|s|G	    S%i2*1Ф>ُ     A%i!2*1D|?1    ?y%faA%:s#    sqF=$̀:8ĀCZ+b^    <ZR}$ɀ:8ĀCZ_~|     x.MO:pPphkֈ~7    `#{eI8ÀJ84o99    `#^Ew˒)pPphj~w`     PAM_Mɀ:8ĀCVۗe?6     TT>rs4l~,IU3*1$>     6Qď3KR8ÀJ841-<n~d     D'-%BaA%ڧi    @M2YdATbh1x    O?;KFfATbIsƧ     H_>Y660};8<     @cQ>Y6"0{s91    `u_~,IupPƹbb|"1    `ZВBpPph^s#    t/-Z^(0kŪWEtُ     -ђ|pPph\^o    u/Y~-IϗupPƱb7Dُ     iD+%2*18ֻG    ^"^Z+0[ͽQ     Fd^;OKҳeATbqwُ     #9i$=[aA%o     ̠Ak]+_~O-I10Sk~$     H9SK̀:8ĀCR"G    $(Vl~_-IߛupPƥի     u_ՒpPph*x    @Ǣ%֒opPph^y@     w֒opPp(bDZُ     cbh,&Z6dATb/1     `t_K҆8ÀJ87     13X@4m~-IaA%ʬ{>ُ      c}'%ɀ:8ĀCY^o     O[gK8ÀJ8U]?     ~-i3*1PFŊbz*    ++K6Oז4pPp(+    hڒf70e[?     L;dmI3upPF]?    0a'à:8ĀC#mnq+c    )1s%\aA%e>    `Bܒf/0ry     &Tދ%^aA%U#>q    `µ~_}ʀ:8ĀCyw     &\%VaA%E2b0    0h{oIupPFQ?     L_L4;pPph{pD    0-oIupP]=?  0S1x(&wի{^ѽhet?}'}G߈2_?5mghw|p}ǣտ^Kt'z[O}D-1xfmD.  {žߒf#0bv1h &4kWwaѽpEtThKQc4O^hǆ뎌]F"z  :|֒;0  0O}^>8:sOhaCcߩӛ[n̏V:|6zo_  ̸3K8ÀJ84G]q  f]ً;iѽth_7Gt^<uK=1X&:  3bè|Œ;0ѿ `tQ*z1ZG8H#q:󵿙,7EO	  SsL+i3*1а{Q iNys:w[\w`@˷Ψ/  |h,,̀:8ĀCè;?  L~'5DUۤUhѽl(b~  UHw[IӛupPQ/f 4rl>8ڧY4xW4nV%G%_ 0.+iz3*10݆)	  g|2wDFb/59k3k?  K*i:3*1B׽pE 14XwROhh-J	knQ4蜿45WGk  HSJ8ÀJ8-:G?  ojɟb7WUz wI1h?  ۠>oM*i2*1B>i  Ǣwl)f[* Mn*i2*1BV*# (&%[grO9  fLŪW'4UpPph ~kwA:wX}wP>Ꮲ"G ^,{ʟQph]wD !(;?eEcnQNiS+v!'~,w1d?Z  ɠh4mSdATbf Dγտb7הQ{<6 `'}<;ɀ:8ĀCQd מ3>.;F֒͢uo  S|&0nnQ+ 6n;}WJ+_RJ[]РD	 h1%MGaA%[닿1 `cqц|hQ>t} @RTdATboj P::g|:UJ(MRM'D ^{!;π:8ĀCu*ሲ1 Y?+?Q<<Eh PAҿKJ8ÀJ8TŻf ^Vn8*Zr4_bEEtO;  a|"˷M)i3*1&l4 '?zkt(v1{4<:/  [O4pPphSk_ 6<kA?PՊ^<`  s(9sҿ;J8ÀJ8>? 0GnŊҿJn˶A# g:W3J8ÀJ8){)bPf| fǠ]F7Ǥqn:A{} &60mJ݋v ̄Ak]tg~@PWct/Ykg#  l0DsO4pPprK65] V>vGOd4oO&Gw`  @&30U Lk}Ǣd}~M'd1  3m~:/Mn(i2*1P .2zI'i`ޖ}  ̬JN(i2*1P^Q?  ӡߍ5Fs?=O[etǈN# 9ߊ&*0Usg?  ߉_oI~')b?  QJ.(i2*1F7h~ @իu$M#7gP  39%MVaA%Zr `2uѽ|(V:;1*_ 0
A4?c%MLaA%z7q ,n:0_]NdT|b 06Zw?IupP6bK(  aPΏ_ޜ=Nd>#1h<} LN#wH'i22*1>ϲ?  o0Dsw4>  VH'i22*1Կ* X+"ߝMq  G]ј[}OgATb6)  ?hhh-J&iz{W>  Nד4pPp71 ;39i4m}M:7cG  |bw<IupP^;?  G$fΟM'd  ӡEǓ4pPp{ rU<gӿI҆64F Pg4pPpK f>/18$}o}I 6Xw4lNfATbl1( ){ѽb(V4$=W˶?  t~3{̀:8ĀCUx wi4?$icke  ҿI8ÀJ8\n9)	 0rsƧIY˳R 3(ӿI8ÀJ8l;kg< FQbT%G ^Sw9IcupPih `h`[~
 @-ҿI8ÀJ8l(	 0|A9$ۧamQ>v{i 01~$;{|?\u*Vk;ƩYGGNit9Vό]3]U/񴝢r!1TFE`D@4A  d/YXBo{s
~Mx%ՎJ2PVi" iJ$kGR [\]Ihd8a//YJ$k.KS^~wA{	)U$IRCb8?lW$IҼT~4/y[}[Ry&Ǳ$IRtZԋJ2PVS3~nva,I4iң-hJ/ǲ$IRm6>8T2^OR$kΕ ꤹiВ$Isl@}p$ee?5q{$I:`wnNs^~cCR֏E$Ieo׀0PIʀi(It`ԿXrTPwkNU$IRkūo58T2{}09J$W5ګ''$A/G$IRm\~`83|(ITRWU #UK$զ?e8{>o$IRQ_
`>oS?%IjӞ?,Fp$ee/-~$I?VUgW\hSi$IhW3 J2PV1ܹ9)J$e+ZgB-0i'D|?%IF߰ߑ:?fg8b3$Inemj[
`b-:,<ǽ$IҼV1R7ƒ0v8T2{$IܫԻiYj~GLU?%IHU4vޱcSԗ[X0PIʀCF?CI9Uuvo nq$Iyui}Cm\:kKRc
K*ɀCYpL?3X%I{S&~J3WWDH$={~>Կme|OS̎Po(`bp$ee1ݺOP$i95~;LޗG$H$j׎4زvW\XrTL6d8_~$Iǅ	ל IޯBiYj>65O{>*ɀCYpLҗr$If7(?OFRHIkK婳Z`8\'O$S3 xn+5;$IoZjj,|^l8T2^-WF??Ij?[	~FlH1zԿ3ſ|'>?+d8SVI:Uz8>k s?>$IRͪ:Ϥ{
ҷ沗, %8T2NK?I$@'ٯ
 ȷwJ)mKk9.V,HɀC%p(+OO$~k	_'EHn8HGJ"u|Wj}ߥ! ̀C%p(+)T~z$I];n7 zNX$IRgSѿSˀC%p(+oD?;I|>5~pqH4Ug`_rSs+
0PIʀcnZ$IRϤƢCo# RkFH}5ͩZ 5f# jʀC%p(+3|g'IZy2spIjwqǅ=uk2p$ee1]g\$ISޞwvLE֫?v$I];`](W$. s*ɀCYpL?~r$ir}0͓yzǏ$I[~*]z7njJ2PVep$I_?y`
5O}Y>~oǐ$I߰P6J+ޙZ+w!    IDAT,1PIʀc,92^3I)lw-E<S#IƪfuǧcRc ʀC%p(+Ѿ-M$Ma>	 :5̻$IѪ];`](WK_p$ee1=z_;7I)种7 GߔҠ$IRhU4Իqij_<?7d8G&IkSca7 ;RS$a?wn*L|$2PIʀczZIQ5ؾ!5~POk&J_Uc[RߥUM^J2PV/IQ5|< ֿ,Iv=[֦E\W J2PVa&IR4% s4?$ISUw4۸<uP?Kd8#S귣$IݏY? 06N[?$I4|GS?;֘98s8*ɀCYpL~;IIJ_~ 0~Z)U'?$IS\kޯB^yo|^8T2|ό~f$i}[o W74FIMw/JǦң??d8&;$Iw iG$iª`۸<uPj1PIʀc5"~f$iB|V$Ipߴjvd:6 &J2PVmϲ\$i>|Ԙ98`,<$^'IũNoH%G08T2lo~b$i><E yʋmuUJmץE<eW Ld8&Ap$IVz"~Ujz<IRDFl0Z{t֊t3PIʀcr%I&A/?w sFI wnNMRwXtXg 0d8&W$I҄չ7 ӣ}XkGlYP.|Sj,9* C%p(+5zu$IT7 LE1j<|~Xc՛Ss+ c2PIʀcB-|^:$I|#5 0u^g($A/wܞzΚRkłԘ9(3 d8&Sk$ISyχ7 LOiЍH$i8HÝSӪ]w|j<&5Y ɀC%p(+ԽOK$MBU%U(ISYSKS8	 0j*ɀCYpLk$Iz7~ qQG$MtU4ؾ!nZګ P*ɀCYpLKUgWӒ$Icޞ_sW6 k4|HI4q{m\:kKRc PG*ɀCYpL7D?+I4UR~ kڔJI4ܹ97JuǧcRc?`\p$ee1y}0YI1w4 \_x_G$պj׎4ز6u/U(8g7 3d8&`5J$qV3 O3>)I<3_rSsN1PIʀc,|^:$Iӆ<7 ǞM^=uG$AoWv~9.V,ELIg8di|C$Iڰ?/ ULIԪ'KMRwX|x^ F*ɀCYpLu~R$iLѷ ^PI: Uvwy{yK {p$ee1Y[~R$i>|Gj,:4l3k?J%)|Rj_?Od8YxH:$Iȯ2 cj/Rn'$={^ܜ:kKfg?;3PIʀcr$Iư5'1 P}[?R%iRӪ]w|j<&53 (c8^$IƬg; h4eU|'|voI/Y x*ɀCYpL~N$ig /H'FJ|u`۸|Pg2 0*ɀCYpL$Iz7~ 
p1+ipٯB\Z 5f 0PIʀc24O$IƨS0 0z7-4fUv]g`G, ÀC%p(+;$Iڟ? 7MÇnTӪ]~Qj>654 Pk*ɀCYpLWWD?%I4&yI ):Ϥ}SSS)? c8dzS$IcP//W(tg-ZԘ98g 08T2_Ұ$IԽ Ff4_ITkGuY;>WK L$d8_7E?#I4ؚ] `g2n#cXRaծ`](WK Ld8ߞq$I_w D~/?%e~`۸<uZ+ J2PVo_~F$*f0I7FKz4q{}ԹORkūg( ?a8ǘ9(UF?#IT熃} @_J׊Tj׎_r	Xrd 1PIʀc'$Ij^o =XOf<e?  ~*ɀCYpe$IRͿ?y{ T5Yػs}Cm\:kKf  d8[+gG?!IT+ P'rJvG4issoZU( `p$ee1o~B$UM~ @tƪ[SޗZ+ߐK `8T2cIۈ~B${ hoDTKj?ۮKR{y f8j#IjZa3 uRRlFlߐzΚRkłԘ9(O 1PIʀc|u>G$մUU - wnNMRwXtX?  C%p(+$IҳU=`j,><VkT-K{`ڽ_rRcQ +d8pG$հΕS `\t>nxܻnXsj.=:- Ib8ǘZ|DJ^$I5~ pizqy9.V,H9 d*ɀCYp~:$u; MR1.hAܜVS{1*  J2PV{_D?IT3y GkQ.j׎4زvW>65O6  0PYʀc<oxӑ$I5w Û?5e{
ҷ沗s  2PIʀc<5H:oW( 0Z+ߐRUEkS+J  p$ee1>o?H$}Q `TǺƽ wnNMRwX|x g8ixu$Iu~ $5UOwQϦ15O|A; 2PIʀctl$IRl2>IVuIRoԹ `Jp$ee1~z7l$IRj?' 0Q>/fG~mf֊1sp `8T2?~6$&35f
O `Ҵ?TUaՓU^yLj,>" P*ɀCYpx$I5o T;?Qyڵ#MR{yK  e8xisOF$դj &UNUwwG
:`۸|Pg2m 0^8T2/d$IRM^	 L5'D+~'sK}uE|_us  3PIʀct~2$	 LED٪iطRO?EƢC  ǀC%p(+߼&HԿw	 L߉מ3׾??[y  C%p(+2|'#IjP~ 4l::`۸<ug|  `zp$ee1FҰd$IRpÝw.w ֊|pߴ*ux_ {8T2Zs$I5=w	 LEQkGuY;>WK{  b8|E?IT?N@/KUs`v=[֦E\  ˀC%p(+ѻ"I Y>j[y&ԻԾmyτ C%p(+1res$I ڢ'A|~ܜV~Jצ  `p$ee1>Ol~.$)=$ Y|iڵcW\sBj<&5  FŀC%p(+1䨔as$IuW7	 0kpiRv?w~Qj>65  "p$ee1ZzS$Iz7	 Wc>J^ٕrtZ|?  ƀC%p(+YGOE$6 w~:UW7JuǧֹMu 3PIʀc<0$izk_{ g2~'յj׎_r	ٯgk  ȀC%p(+0"IƢC G"աjvн~&?۩yK  0PIʀc<TOT$IRP[E g<e<3۠NoLgΥoO3e_  d*ɀCYpŇ4D?IT7# s^wissoZU(  ĀC%p(+kxu3$I]XxH= Ò#Swg`](/|Sj,9*  L9d8}ۢ$I
wY +ߕ9_NRe<'   ?ʀC%p(+^g"I/ѷ 0IÝw?;nOSgqbAj  /d8OD?IP} 㟠9ͩiU;>W  x8T2ਿ=$Iz7~  yZ>5N|~  1PIʀcD$:C    `p$eeQoS^D$IR@GSc[    J2PV:uOD$Կ;    0PYʀ:k(Hګ~     *ˀCYp[$IqUwwj,>"    8T2਷]E?I4ׄ     ^*ɀCYppף$Iq{B-    2PIʀުSOD$JeA    8T2ਯ)/~$i~     g8G}}m$I#wi7    }*ɀCYpW5yH׾M7    }*ɀCYpW~$i۩    >d8Ǣ$Iaׄ    2PIʀ[~$iu    A*ɀCYp{$IaZ     d8jj!IFT~j?    ~J2PV<g$Ia{ׅ    2PIʀ1iHֽ    8T2ਧ4$I3ތ?    e8G=u/~$iTz    Q*ɀCYpSG?I4n=    gg8G=^4$I҈m8#     J2PV4ܹ9iHվm    8T2ਧLӐ$I#y{    ʀC%p(+ig!IFT    xn*ɀCYpO#6YH5    8T2ਟ7G?I4z_Z~{     ̀C%p(+\g!IFT=    f8G|R$I#yτ    s3PIʀ~w|*YHT5v    p$eeQ?G?I4~!     ̀C%p(+>%YHԻ    7d8<,$I\w    o*ɀCYp̒$IQ    'd8u$IE05N|~    J2PV^yL$I#zw    *ɀCYpK%IH4w]    J2PVҽOB$g    p$eeQ/N~$iu>w    *ɀCYpK$IAC    J2PV2'!IFP    p$eeQ/_~$i9    1PIʀ^];$I;n9    1PIʀFfNi؏~$iol    ̉J2PV\zts$I#    d8ꣵbAs$I#    `n8T2ਏ19H^    d8s$Ij}    `n8T2ਏ~$iXrT    ̍J2PVѽA$sGo    `8T2ਏgE?I4sK    ̝J2PVwA$s/9    3PIʀ>~!9Hy    p$eeQÇn~$i^?~s     sg8G}TO$I<׹o    `8T2ਏ;9Hy    ;d8jbOA$}    ̙J2PV<$IA:     ΀C%p(+zhX$I|WU    ;d8꡵OA$sU    c8G=W9)Hyn]7    ǀC%p(+z\OA$so)     p$eeQݵ~
$i}y    1PIʀ~ )Hy7    ǀC%p(+zݴ,)Hy    c8G=o=/)Hy{o     J2PVп I    @d8a Ig~s     y8T2ਇwn~
$iko     J2PV0|lKS$I\*A    IDATׇ    @d8z I~s     y8T2ਇtS$I\ԗ    @d8!OA$sG    @d8j`ɑ@$w05f;    ,*ɀCYpǩK	9    |*ɀCYpkg I湪x    3PIʀ#^#$I<W=@    3PIʀ#^G?I4'     p$ee}ᛢ$I~s     8T2׾@$sn9    |*ɀCYp|G?I4]~s     8T2׹@$s-W    @>d8uW@$s;/9    |*ɀCYp^@$s;.9    |*ɀCYppr3$I\7    πC%p(+xό~$i    g8G-~$irN    3PIʀ#^G?I46~8     p$ee@$s~s     8T2g Iކ3o     J2PV\$I<׻    g8G뢟$Iz7~s     8T27ؾ!Hy%7    πC%p(+xÇn~$i_~s     8T27|g Iuo    3PIʀ#$I<׽7    πC%p(+xSG?I4u}    3PIʀ#^w$I}0     p$eeh3$I\    g8Gg Iޗ    @>d8U$Iz_>)     p$ee/u@$sO9    |*ɀCYpKN3$I\o7    πC%p(+xi8~$i|V    3PIʀ#AO@$w    ̀C%p(+`~$in9'     p$eelQO@$;    l*ɀCYpj' IFPw    πC%p(+XS^$Iw    πC%p(+XS^$IoZ~w     8T2\' IFPK     J2PV8$I[;    |*ɀCYpj.=:	H4vm    3PIʀ#$I`Mw    πC%p(+XS_$I>t[    3PIʀ#$Ip    g8G,I     J2PVd$I#ڵ#     p$eeˀCj=~w     8T2\' IFQ~w     8T2e!IҔTU1sP    1PIʀ#$IScɑ    ǀC%p(+XͥGG?I4'D    1PIʀ#VG?I4T    1PIʀ#VF?I4Z    c8G$I҈j    b8GGD?I4ڟ    b8GEF?I4^    d1PIʀ#O@$Κo     J2PVRUE?I4WE    1PIʀ#^$IAk~w     y8T2g IFPS     J2PVR$I    c8G+Hߴ*     p$eej=$I|    c8G3H4o}    1PIʀ#^@$C    @d8$I>~o    1PIʀ#p@$jw    ǀC%p(+xÇ~$i;w    ǀC%p(+x$I҈j,9*     ΀C%p(+xo~$iD5    ;d8]$I҈j}o    `8T27g IFT~{     sg8GݗG?I4:=     ΀C%p(+xo^$I҈\    ;d80Hս    0w*ɀCYpz^3$I#w    0w*ɀCYp}C@$=V    ̝J2PVz7.~$iD\~{     sg8G3@$7    p$eeſ~$iD~{     sg8GD?I4    ;d8u.g IFհ3    p$eesG?I4'(     ƀC%p(+xտ$Ik    d8?[@$7    p$eeu~$i/y[    ̍J2PVZj3$I#s    `n8T2/F?I4º    p$eeyOG?I4z_;7     ƀC%p(+x͓_$I}y    ̍J2PV5𐔪*)H5x    d8!OA$[o    `n8T2ਇjOA$+     ƀC%p(+z;q%IXrT    J2PV0| IFX~     g8G=1)H:u    *ɀCYp$Ia~7     πC%p(+z IFX??    3PIʀ$I^    *ɀCYpC3$Ia[>~     g8G=t/~
$i76     πC%p(+z~/$Ia7    p$eeQOA$    `8T2ਇ%o~
$iz1sp    J2PVоOA$沗     p$eeQJS$I#u     p$eeQ&)H׾-7    o*ɀCYpĒ$Iq+     d8G}~'9H    o*ɀCYpG IFX?    }3PIʀ>;~$i^~     f8G}99H6|    7d8cems$I#j=~     f8G}7~$i5~     ̀C%p(+}CA$ٿ~     ̀C%p(+_$I҈k_o    p$eeQݫ$I҈\7    8T2ਏg[s$I#{_     s3PIʀ>ګ$I҈m\~     ̀C%p(+h IF\?:ixf5+˜˲i53ZL3eSMciZM4rQ䦨 "Eᠢrܿm s>{=k=w7k{A    g8TG;s$IOo    p&eюOJ?IMWA    g8TGC~l6$IV{l    vȀC5p(Lw$IງT    v̀C5p(Lݔ~$iW7    cɀCEperۧOB$mp$~     ;f8TG[_8?$$I7ܺ%~     ;f8TG[FW;$$I7    1d82$Io    `8T2h'!I67    cɀCEpepKOB$mtluG    8T2hK祟$I
9w    @ɀCEpwԳOB$;    x d8}ݏ$I
?w    @ɀCEp'!I    <j2PQ;g!I6%o     p&eўB$mpώ     p&eў͟H?IMn:~     d8TG{ל~$ivf+w    p_ɀCEpgt[B$w    p_ɀCEpgu$IG=3~     e8TG{gyYH@w(~     e8TG{'^YH@    8T2hO_J?Ihtq;    /d8=t$I7^C    2PM*ʀ=-OH?Ihw    p_ɀCEpi6즟$I覓꾏!    p&eѦ鶛OC$'w    mɀCEpiOC$;    6d84Ӑ$Igy    ̀C5p(6.=*4$IRE    8T2hpӐ$IWC    o3PM*ʀM^~$)˟!    p&eѦ~?4$IRi    |j2PQmgiHPE    o1PM*ʀMXiHP#}    ŀC5p(Fl:M?I^[    ɀCEpkz{yH@^C    o1PM*ʀ][/K?Ihtٱ;    d85$I7~8~     b8TG~$)w    -ɀCEpkp?$I
-    p.eѮ/N?I{o    Cup(v$I-    p.eѮ~<<$IRy"    2PQ1t~"$)So"    2PQmv~"$)    Cup(Mn<D$IR;    0P]*ʀmJ?I    ,;d86M'"IBu    ,;d868OD$-    ΀C5p(G'"IB>E    `p&eѶq9D$IRo"    8T2h[?~"$)Oo    XvɀCEp4n'"IBM;wo    XrɀCEpoڽ3L$IRΫ'~    23PM*ʀ}/_~&$)T_"    8T2h$I
    ,3d873$IE    `p&eѾVD$]qB   ef8TG3$I&~2~    23PM*ʀ}㞝~&$)ԴlueS   ee8TG:3$I:P   ee8TQd~*$)W   %e8T|n)T$IR/"    8T2$I
5a[    j2PQa$I
59[    j2PQap"IBM-    ʀC5p(?"IRM~#    8T21T$IRψ#    8T2(T$IR){    XFɀCEp̉M٨~.$)}    ,!d8kק$I
5-    ȀC5p(19"IBMn<~    22PM*ʀc~.92\$IRaw[   ec8Ts$I:?%~    1PM*ʀc~s$Izo=    ƀC5p(ᇃ$I'~    ;:d8Gߗ~.$)#    ,d8˴wHP/E    `p&e1_&_2d$IRݷo    X6ɀCEp̗g$I
=    ĀC5p(2a'#Im=    ĀC5p(2x_$I
?    ,d8KN?Il    ,d8KOO?Il|{    j2PQ'#IM|   eb8TvH?Ij:n=~    0PM*ʀcLtqH`#G    `Yp&e1F~gH`w(~    0PM*ʀc'l$IRᅯ#    ,8T2?S l$IR5#    ,8T2?~HHMl   ewsɀCEp̟OL?Il2nM    C5p(4|-t$IRM   e`8T|ӑ$IG    `p&e1Fz[H`í[    ,d8J?Ilt{    ,d8S]O?Il    ,d8Sg$IJ6V}t&   Eg8T|l:M?I{o    XtɀCEp̯7~>$)X    XtɀCEp̯MI?Ilx=    ΀C5p(5$IFWG    `p&e1"|$IRW#    8T2_~>$)d4[    j2PQ{Ϧ$I
}7	    ,2d8g4$IRI    `p&e1ߦw})$IR    ,2d8OH$_}Z   Ef8T|]$I&w~.~    "3PM*ʀc>w'$IM'I    `Qp&e1z'v	Ip7|&   Ee8T|'$IO{I&   Ee8Tǜѳd~F$)C7	    ,(d8_H?#Ils    ,*d8$I
6=    ʀC5p(7Ag$IuxR&   Ed8T?H$    j2PQ{3H$M    ȀC5p(H$]M    ȀC5p(0WOI$c{    j2PQa|S$Ig+7	    ,d870    IDAT$I
9)    j2PQaH?%Iߌ$    h8T2XS$I"~    1PM*ʀc1t|r)IpO3~    1PM*ʀcAlMw$I
6    j2PQcr%$I}#~    "1PM*ʀcq.?>$IRI    `p&e8"$IR/$    H8T2X~'$IR-    j2PQL?'In|    j2PQdGfAII`ӯ!    1PM*ʀcLn:$IRtM    C5p(2$IzG=+~    0PM*ʀcnI?)InpK7	    ,
d8K/J?)Int[7	    ,
d8KM6$IR͟$    (8T2X0wͦ$IՕw	    , d8tMg%Iu#~    "0PM*ʀc?;$IRII    `p&ex~V$)p~    j2PQKJ$_{F&   E`8TCD$MI    `ݛj2PQht~Z$)t:w	    9d8ϥ$I
;fM    ΀C5p(4%IzY&   yg8Tbnݒ~Z$)Go    wɀCEp,/L?-Inr%    j2PQ{Ϥ$IJ7V~D.   yf8TǂQx~^$)\%    08T2X\|&$IRI    `p&eFW~^$)Wo    gɀCEp,y~^$)o    gɀCEp,	~^$)7o    gɀCEp,~,$IRu^    j2PQlel~b$)\_%    08T2Xl[.I?1In$    08T2XlˎK?1In=I    `^p&e$I&~2~    2PM*ʀck'&Iҍ}K    `p&e:PI    j2PQoڹ#$IR{(~    <2PM*ʀcopIpÏI    `p&e~f$)7	    #d8̗$I
75[]K    `p&ez~f$:<5~    1PM*ʀcu^g&Isw	    d8/$I
7ܺ%~    1PM*ʀc9IpΊ$    0o8T2X:$IR]o    7ɀCEp,/H?5I@@.   yb8TrS&I_%    0O8T2X{?b6vM$    j2PQcr%&I<)~    <1PM*ʀcy>ytIp^I    `p&e<s$I馓Yg    ɀCEp,1{$Ij[c.   ya8T]t~r$)̗    ɀCEp,鶛ON$]zT&   ya8Tr_{FIp[.$    0/8T2X.í$IJ7VyT.   y`8Tr$I=gw	    d8Ku?~r$8~    <0PM*ʀcɬ6~v$)c%    08T2X>?~v$)    j2PQgtɑg'IM{f+w	    ΀C5p(38N$5P%    :d8Og$IjމK    uɀCEp,ΖfIIp%    :d8ϧ$I
7M    3PM*ʀc9~OIp7	    ΀C5p(48ӓ$I9    Zf8Tr;'IK    eɀCEp,!OM?=I@%    2d8ʦٴ$IםK    aɀCEp,$I
7M    -3PM*ʀcy?vhI=    ƀC5p(?O$5PK    UɀCEp,?~~$Z%    *d8ޏ͆$IלK    QɀCEp,ɗ.N?AIn7	    ʀC5p(6$I9w	    ȀC5p(?OOP$5P    hj2PQ˭{/$Ijy%    "d8ܾ3$IFWK    AɀCEp0gP$n1~    @8T2`tP$5PK    5ɀCEp08P$5P%~    @k8T2wJ?CI@s^K    5ɀCEpl:M?EInw	    ƀC5p(~(IM|&   p&evޝ~$)t:w	    ĀC5p(S$I;Ww	    ĀC5p((Ih%    d8خH?EI@+N%    d8Q$|M    -1PM*ʀ{9Jt鬳w	    C5p(1ps$I;f]    0PM*ʀ{O|n9J|ow	    C5p(9(Ihtŉ    Za8Tʦٴ$I&w|6    @#8T27\~$)t:]    Z`8T6$I;    Z`8T?e$I48    Z`8T=t$I4    Z`8Ti6mK?KIn]    0PM*ʀ߰5,%IRuxR.   4d8E$Ijω%    f8T?e$I4%    f8T=t$I4]    iɀCEp +f޶Ӕ$IwݒK     ̀C5p(vd|Ӕ$Iy[   f8T;2Ӕ$I{o    H2PM*ʀ韲WiJ^9~    @j2PQH=OS$5    H2PM*ʀZ4$I
7]j.    d8x0$IjA?K     ŀC5p($IjIϋ%    b8TS$5ï%    b8T{)Ihsw	    p&eZ4$I
7~_m    ɀCEpP7lM?QI@X.   d8x(Ï~$'0~    @j2PQ<$I>L%    `8T{'*IhUK%    `8Tielۖ~$)ܴluem    ̀C5p(q+I=w	    l4d8x8$IR    hɀCEpp'0L%IR?]    ̀C5p(N=T$5%    8T2alMw$IJ7VyT6   d8T;cOU$5Pg    HɀCEp3> T%IR]    ɀC5p(vF禟$Ij'%    8T2`gtS$I4    6j2PQ7~$)d<]    ŀC5p(v$Ij1{    (ɀCEp~$]    ŀC5p(vV~$FW+~    F1PM*ʀ9I*Ihw	    ld8(1OV$5P%    8T2SOV$5P-~    F0PM*ʀs_~$K    `#p&eAqN?YI@K    `#p&eAOͦ$Iᦝ;f+	    7d8(5g+IsSw	    7d8(5$I?    ֛j2PQWg+Ihx    ֛j2PQ$I4#    ֛j2PQۼl6$IJ7V~d6   ud8Tb+OW$5PO%    8T2`W.;6t%IRw	    'd83,t%IR.}K.   d8TO?]I@.%    8T2`٨~$)d4[    ։j2PQ-$IjQϊ%    ^8T2`W/~SJ    ֋j2PQi/I?_I@+N%    ^8T2`Wu$I4s    ֋j2PQ첕f]',IMΫ7    :0PM*ʀ/~$z?'~    z0PM*ʀ~$Z%    8T2F禟$Ijug    XɀCEpPsOX$5t]    C5p(jM5%IRuyj.   f8T׼7%IRO~a.   f8TcK~]    k̀C5p(j{vK]    k̀C5p(jul6$IJ7V}t6   d8TkakOY$5P?K    `-p&eZ}m,Ihpw	    %d8X<%IR>]    kɀC5p(ւ\$i{;>K    `-=j2PQ}5,IMΫ7    1PM*ʀ2,Iwsw	    d8X+Ï~Β$K    `p&eZ$Ijg    X+ɀCEpVs$I49[]M    `-p&eY4vH?iI@C&    8T2`-?wNIKw	    d8XKí$Ij?K    `-p&eZOZ$5Kw	    d8XK?%IRM    j2PQ鶛Z$5P-!~    @-d8XkϜ~֒$gU.   ZɀCEp$I4]    8T2`3%IRM~C.   ZɀCEp6>MF-I&    PC5p(W$Ij;~3~    @d8XO~ڒ$[    a8TN?mI@ϟK    j2PQ?~ڒ$oVWv&    8T2`]l~ޒ$t6   ]d8Te|G[$5P=K    `Wp&ez^tpyK]]    ʀC5p(K$Ijm%    8T2`tyjyKfw&    +8T2`=MWoO?qI@c%    +8T2`={_K]    C5p(}O\$5w	    
d8XO㟓~$Y]    C5p(SU3Mg.IsS	    2PM*ʀ6sg.I    (e8Tmt	g.Ihχ    (e8Tmp_$Ij-    (e8T{3\$x8[ݼ{6   ɀCEp}̿F$w/o    (`8Tare.Ihp?    (a8TaxO]$5w	    0PM*ʀ?%.Ihͯ    (a8T$Ij?M    `gp&eXm6ߕ~$앿M    `'p&eFpAK~    vj2PQlG^~$&\K    `gp&eF.IZh<n=~    0PM*ʀyJ?wIH1~    0PM*ʀ4K'/Ih%    38T2`#~OK~    ɀCEpCK}[.   a8Tw/$IjO&    p8T2`Cl2J?{I@_M    ap&eF|$I4w	    <d8hO~$&_8~    1PM*ʀ?O^$x8[    j2PQl~$zG=+~    C1PM*ʀ#f7O_$5M    !p&eAO_$5Sw	    <d8H~/Ihz    j2PQ$Oz^KFm    ƀC5p(:>9%IR#O+~    1PM*ʀtI?K    p&eA$Ijɭ    x0ɀCEp28/IZh2u<>~    p&eAJ_I?IHM    `G8T2 e/n%IZ&    #ɀCEp4' Ih    d8H]vl$I45[]-~    p&eAR?M$L6   3PM*ʀ?$IR#mvo    ?d8`5H]~|6   1PM*ʀMI$&w~.~    p&eA?IH`6   {3PM*ʀ~?HF;    ̀C5p(:H3$I4    ̀C5p(Z0 IhNl    IDATŏ    7d8h3ҟ$IjQc	    ÀC5p(Z08OA$5Rgo    j2PQwܳӟ$Ij.~    =8T2-ͦ Ihػx"DB3N8ziت}L;MڜQL3Zϱ2cNM6Dn!JD FA0KD	T.QŀEI"^ߺ籓I?xWwdD$I$I_pPY8T{~ @{I$I$eAd1P]}is  jyΏ&$I$I\TaAեb; PM96$I$I2
p.5/|ms  j&$I$I\TaAզE)uO &$I$IpŀCuحO D$I$I2
pNun=;I  5D$I$I2
pN' DU᷉$I$IdAd1Pj' DoI$I$ɀ*8bU~ @4D$I$IӝUpŀCuu ~&6$I$ItgAd1P*nzw  j&$I$I8,[K, ~H$I$i3
pn5V44 (?~H$I$i3
p=4 h᷉$I$I70 Xwǆ D~H$I$iz3
p(i  5ѽ᷉$I$I70 X?4 {06$I$IfAd1P-YR< hqJ$I$)&0 Z ~H$I$i:3
pun;7y  51wD&$I$I8,k DM$I$I4pPY8Tg*y  ui''$I$I8,s' Dׇ&$I$I8,s>D |D$I$IӗUpŀCuiE jM᷉$I$I/0 \7F? .4;(>$I$IteAd1Pk>1L h~߄'$I$I8,{}D? &em"I$Iʀ*8bݱ!  5ѻ᷉$I$I+0 ^qG? &ƾ4D$I$IӓUpŀCu~& @4X}"I$Iɀ*8b7(N3  5ѾI$I$MMTaACǷG? &w_~H$I$iz2
phvnS jC᷉$I$I'0 ơo~* @4ּ<>$I$ItdAd188O ''$I$I8,ٽ oI$I$MGTaAK~. @M#6$I$ItdAd1иTܴ"  uQSc$I$I&?0 ƥeo~. @6.O$I$I4pPY84.)۹?m 0}$I$I&?0 Ʃ P~H$I$i3
phd wSI$I$MvTaAS?~2 @.}C}"I$I΀*8bqy뢟 P#OO$I$I4pPY84V,Jӌ~6 @MD$I$IUpŀCV n;͞D$I$IUpŀCVs P#)>$I$IfAd1иվ- $I$I&70 ƭٯ~6 @1>$I$IfAd18V2  uiٙ'$I$I8,z\t i^s$I$I&30 ƱwG? F*>$I$IdfAd18ֺO 
O$I$I4pPY845VRُ~> @MgcoI$I$M^TaAk}D? F&>$I$IeAd1иݱ!  5R|I$I$M^TaAk?~> @t:>$I$IeAd1иּu /ͮ8&F$I$IdeAd16(N3	 5\oI$I$MTTaAsn~B @~H$I$O~"~k~~|M70 ƹmD?! F\~H$I$}g5'ƥ:z6o=׆opPY84ε|K j|k$I$IZ뗤bݱ!O?r=t}n͟UpŀC\WF?! fh"I$IM*cS*ٿ}K͛UpŀC^g H?O$I$I~JSg۽-Ns(/pPY84. 5I$I4cƥ:z6od?0 ƽwG?# F~H$IZ$[(=;3O=@gAd1и׺ Q$I$IRM[y\j[ڛ(wTC/?sѼpPY845V4 7F$I$I(-gm)un79i8,{wE?% F\~H$IԺ:z6/N#π*8bI{eO	 rvO]qL"I$IFWc~I*,OR4~?O͟UpŀCP P3~"F$I$ICjqnqjoZ:צwI2;UpŀCPE?% f7$I$I:kNJKS3Ro12_]3
ph"YR {U"I$I[cuSu&vmN4gUpŀCRۢ P#s3E$I$V$/IŖ婻cCٙRYF6B-4zE̀*8bIs9	 2F$I$ij[ylj[ڛ?
WDvAm5gUpŀCR߉~N @I"I$IҴXsRjm\zP1N#Jׄ;8,j1 {7$I$IXcK~J]S9'^sχ{8,OF?) FSivoI$IƺEyReyؐ{vT?O%Z3
ph[ c_~H$I46<65-NMRg۽-^ThmUpŀCTqӻ P3Ŗ?Q$I$Ik5'ƥ:sPZD(?ڗv΀*8bIu P3	Q$I$IC/MKRq5|,y?F480 &Le?Y 5R6J+~H$I,J_-Swǆ߳31Ch__7UpŀCVg Lׄ($I$ǦũiYl_zmG8NSkI3
ph}Y j_($I$Y?W:L|!pPY84i \E$Iq%?
ޫRM3
phj^g Lz_'}H$Itf(kߞ;6)e,ƿ5pPY84q,Jӌ~Z @4/|]"I$I?qR{Ӳپ6voKێ@֕&580 &cF?- fE$I45ԾS5ͩl?25ӹyUS΀*8bIs9O ރQ$I$IQRkTlY~Pgc1c8,WN ꦘM3/S$I$I̢\8}FΔ~O-gz8,g"i 5/)$IqR{Ӳپ6voKۊq	vfo΀*8bId j:~H$IƧƚRk?OvmNem`sk^3
phR; [oI$IR=kvBj_-|J?2e:UpŀCZqD?/ nzEj:>N$I$\Gt(LGʔ~~8,Z>y 5;E$IҾپ6voKۊK+UpŀCZcK-vf"I$IXqi*EtX~480 &]O Q$I$Iic2[뗤bݱG7pPY84u, uS~H$I2[y\j[ڛ(w[(sM#i`TaAMrwD?1 >8N$I$P~~kvoKӌqFN3
phk^' PS$I$I>hm\3ks*t׽pPY84,Jӈ~f @z(N$I)Z$[ggP{
UpŀC^[ PC^~H$Iķ\87-;Q('Lߋj{oV3
phzv3 jS$I$iR?
s{[Jf06z_580 & ~w$I$s'֥O֙۵9{ԃ{wpPY84  ߩd]qL"I$IcѪ%ز<uwlH=;S*`t[8, w;E$Ij޴,u=Q("G8xUpŀC_ Oi"I$I5֜Z(oLӈqR¿hpTaAMCō d"I$IYߟZ=u>wꁏk(߈z5B3
phj] Pz6ͮ<6V$I%~I*,ORΔ2G1`fAd14XҔ~s jU$I$r+K*ԽC/Ed=|C̀*8bi ;7u"I$I5֜ZbL=|cJFW@EL΀*8bi{ #[I$I:T_Zyƃ[R0>F3
phZj_ Q}soI$I:̢Լuز<uwl87eONd ̀*8bi~n @M6)V$I4<65-NMRg۽NpPY845x~*[F?9 :H$IkNJK~ʮͩl=P#ݝ¿NipTaAMSo~r @7N$I4Y5NZG{U*?Pss_+vipTaAMSWE?9 [E$IҘ6G\ݱ!L,L㿞i`TaAMS9 5վ᷊$I1h{[Jv4~_400 {; 0$$I4ƚRkTlI]S|:`Buw|$kgAd1д` jlK+~H$Iq%ز<u*
0Ew_uP3
ph}Y jykoI$I̢rSwǆ߳3c	0źw^Q3
ph*6# 5U\[E$Ihj޴,uMR궢6;և8,t jM᷊$I5֜ZbLڜS?n VpPY84u<6 QfW$^$It5N;!/IŖ>
|, JÿjpTaAMcGo~z @M6)V$I4O+Ku|JRΔ~ Cu_g500  zv"I$[Ҿپ6voKۊ`d:uW3
phk}7 PS'U$Iik6.M֙۵9oDx fAd14xG?= {E$IZ뗤bݱ!O?c @ζ}8,P ̧}[oI$ibZy\j[ڛ)v>=kfAd1дǢ PS/}4V$IPW:צm)u'>X|=_580 S *+$I85ZbL|tn^u]3
phZ 8	W$I:Xu|j_-Swǆ7ZoJTaAMm3R4  PSW$IVe>
ĝ)3`}g̀*8bigp {[E$IZBr34OrS\'480 ζ3  PWv]{E$Iv3~ >sil>}}Rj_UpŀC\ߎ~ @	{E$IRc~I*,OR3y?7480 ƚG?A :~H$IGRs޴,uM'Lߋ>8Bs4{fAd1дW>x3 j|[E$Iƚq[HR4Oh *hm-UpŀC^ޫ! Pc͵2^$IOLK_3ks*gF Y_~pPY84g XI$MY^Z뗤bݱ!L,Oc Fi`TaAM{͋m3 j	W$I4<65-NMRgڃ+` 4/|m%̀*8bmG?E 4{oI$MD5'ƥ?
S4/^ jbn}J3
pHKkm{E$IWcK~J]S9'g2{gAd1w௧ Ogy$Ij̢Լuز<uwlH=;S*S124?8,RʷD?E {E$I5je`PozE
ki`TaAyqG?E H"IDtkTlIoL>O@({gAd1V>Ds jOI$ꗦ%]ks*?}02ͮ8&gAd1ֻ 
W$I4f慯KŖ婻cCy?/j8,*9 uiS'f$IQ\87-KkSo+ ([ԼpPY8Ԗ5    IDAT. \7,$I:kNJKSuG4>'`^s_ީ3
pHS'^'I 5ֹE$IUMK~ʽWrѧ# d)~4π*8b!}wE?I {w+$IS̢rSwǆ߳3>j8,ҷ~~ jqoIijjoZ:צm)u'! 03
pHߪߍ~ @~H$Mj5'ƥ:z6T m߇5TaA[5'	 HY$I&S7wޮOrףO= {͚?0 ~ @i,$Ic)/J͋~.[6S* j{߯5oTaAۛ;  M7$IRk޴,uMR궢O8 ]pPY8o~ @un"ITkNJKSu͕ͧ5 ;s?0 u  R>X"IQRkcC*~44йyUy͟UpŀCfiD?M E$i<.5->Q(;.J=;S*g L5{̀*8b!}wݷD?M ["I4Bi_q½{[JV S}o͟UpŀC:_xo jn?jD,$IUKSu&vmNe Lo	4TaA黛 CR-$IZ$[?
 ֆ_4TaAk|+ pXs}H$}[+Ku)sN c`nl~Gh8,{~ @u"f$IG8Xc#R}" G~Wh8,w~(y 5WI3I4]5X=|Á[ ~8!/*0 4տ<1/-$ij}7O  `O14TaAips4y csYw$IW5 ,co͟UpŀCǤrvO jE$MUŖ?> !*UpŀCF?Q `]w$I3 0DsO:tTaAiϾ3 c_-$izvn QUpŀC~ =rS"IݗF? z{}CgAd1)/Lۊ~ @:E$ME~ !=|C}CgAd1][) 0W~Hѧ 0Dݝ:0 t:~ ~Hѧ 0Dݻ>~_pPY8CoD?S `}iv᷋$Iʧ>} !l_~_pPY8C8e)eS @_]$IW>{ !|B΀*8b!* 0:~H	of?h _:dTaA} |%n$I]cˣO `C΀*8b!5T1|]$I< `Z~c07pŀC:|~< ciE"I&֥>w !k^C΀*8b!A+I
 w.$ibk_ `gpCgAd1ޮ egP"I&b˟E_; ͮzICgAd1wE?W `LI"I&WG: 0uUpŀC:Z
 7.$i2qQ QUpŀC:NyaJv AE$M\>}  CBπ*8b!yǷG?Y `L?oI4yvo>s !=t}}gAd1ζ3, 0&^~Hɫ3 G}gAd1~+ c,S^~Hɪl?}  Cپ63
pHG^T 9~$IS `ȊV:|TaA)7> c{E᷋$Ixy Y_#8,R^ݻ/~ (?fW<?~$IQ_>o !k_:|TaA)l1Ҽ߆/$i2joѧ 0dCπ*8b!\8 cs$I}  C|O:|TaA)ǤT D#$I:? q?1t8,R~>t1<I4u: ,̢Cπ*8b!WO #W/$i t}#ˀ*8b!׺. 0F_$IW~g 0Do}}#ˀ*8b!E~OJ" cnq#IƷO׉>i !?=eAd1
 H[W/$i|kC 0d]oYTaAܲ& c//$i|q 0y_`#ˀ*8b!]K/ 0fx#IƳo>e !uOTaAjR*O #ō=$IYu& }:8,7W w/$i<}Y) Ykï:8,׹' 9g#IƯW>}  C<7,0 t' a$IU>X Y:8,80 0f_=$Ic̢3 ^fWg2
pH?P3 IYY?~Hi# R>CpŀCVK1 0fOy#IƧ%}  C{CGUpŀCVߋ~ ~H}ۢ `Ⱥ;?~c3
pHט ~jyy#IƣζE_/ un;7БgAd1W>DS L?a$Ix 
1tpPY8u") cgJ# S#π*8b!U2 0n25zE#Ij̢z և9gAd1<O CTItx @s3qpPY8!T6~ ?qW#Ij]c}  #Xu|#π*8b!ޮ C~"$I]
 0de72
pHé;3 0+ITߺw]}  C{8,pj^s CITz}  C{CypPY8!5(b6I cyoIT7O `Ⱥ;6ˀ*8b!, @Nc$IRjE) tn9#P^TaAix7~ *~$ͮ8&$IuɯD) [ˀ*8b!ſ1φ2$^ ~3P^TaAi:g m2$Vu4D FyOˀ*8b!ޣ7G?k `}-ͮ<6$IO `_~g(/0 4܊3 S)$I5iq)u[	 0de;CpPY8~ ݅᷌$IGu*4 Fĝw63pHC2 Q)gٙE$I
}[O `;7π*8b!W>1ڸ4$Iu ζ3gAd1_sF?m `Lu2$I}  #P\w3
pHïuɯD?m `\u[{F$V~W	 09P~TaAi=)u SkHs ᷆3
pH W>~Hd. 02͞[CpPY8ԹyU UYٯg$IRL֙k rw.0 4Zj Xqg$IRLD" ;CGUpŀCQ8n; c{F$T>E syˀ*8b!mO cs9}HqO `D:_8=eAd1FW󫣟8 0:.$I[ʷD  }{ˀ*8b!֥o~ +gٙE7$IZ:}  #2o]TaAizE3 XkF$-X> &W5ttpPY8{g W3$iZylJl BO0QeAd1F[~ 8Rc7$I}~:  FWoU8,hk]g 5oi$I+6#  FdcҢo}TaAiĝzES G4$iu<  F#᷆>0 4zo~ k7$ImsOD 7;gAd1F_sD?u `u/$IyΏD 89P[̀
8b!ſ1W2,
k$Ihj_ 0B_~o3
pHR*f; 0ZF$ݗE 4{}TaAia=|Cs \o'oI4ʧ>5 )~kZTaAia*n ~75ּ<$Ií2 ={C2
pHS?	P\F$7  F{C2
pHcSz& c4F$E (P8,۵9 _k$I{   FuUˀ*8b!-\ŧ" {%w$IN`i C2
pHW~ $(fSoITo, Q*f}dAd1Ǥrvo &@?m$IR]}V  #{C3
pH[ޫ= 0ok$IRVֳg 0B{.9T90 	ѼoIt> 0b֙C3
pH[sE?{ `BtF$}O>' k_C3
pH_ͯF?} `RoItts 	9T=0 uw|$ }oI_TO	 `25V~wzTaAik> 0!_Rm#Ik_ `g948,8~ i^s$IʫcC	 Xo'0 S? 0!w_~HVٽ' 0bϏ;48,RL;.~ 4S~H#u/F_ (,;48,RL+N~ )>$I::}:  u'0 ܟMe?K  0!O=fW~HW>h  ,{?p2
pHq/ i]$I:t_}2  ~wh7pŀCӣ  $I:tO> {Cˀ*8b!/G	  &Ik^~H?yO  ,m^TaA)TF  &Hs8$i`s~$T  H=4;΀
8b!{_ IS^~H﮸O `4/|meAd1b+>_  }[oI3 X^={o/0 [WG  &Lkw8$k_T `
=48,Rp+IG)  &LC.Α$I> ҽC̀*8b!Ǣ  sS#IU_> R7᷇UpŀC}E)  &Mg2Α$IKu/ `>|pPY8|. u~H}  q+70 T{r  LLj:>Α$i[qL*JY  ,܁7UpŀCGE9  &Pw$I\_> {Cπ*8b!գG/ {0ͮx~#IҴֽc}9  ,]~hpPY8z8턔z/	 jmxS#IT6T6> o8,R}%K 0z]~H4> пA48,R}*  L	u$Iz}"  RYo?0 T>K 0\~H4M5
 S|fwdAd1jRz6 08U$ISRqD Xo&0 T]e Pu$IV<?|%[? :_h$pPY8zվ_ ImܣI&G] o!MTaA^5/ ܼ*ޑ$id|  @}"h2
pH/ *OƪI&ƚRw ;Dˀ*8b!կmDi  &XI&bLz  @o;Dˀ*8<JxYFccxnf1cLuh4T/44웲-
B wAAi~oNшl}V^3s΄/]28;}ѧ hbݩoIZגMR @YK"8R8lYy  Z<$# h2
J1F OEoID d; -ˀ*8(ŀCgS!<  -?<$Nȣ Z[D3J1YwD pH4G @wh~3
J1[ \?H4EX 70 \~UI*6<gEt  PwG4pPpHwF `w$ImVq D)m750e+Ni<> @^o$iN @#8R8z73 LHԸᛣ F&ѼgAb!ջ_> !IRGQp  υI4pPpH 0!z?#IRyQo  XI4pPpH5ojQ*6> 4#IRC5 )YTaA)R]uh  &D}$IjBΎ NDUpPT~4T  "ԙZ$xkl FW.    IDATdAb!տl6)y  &D$IsΉq ha2
J1Q~% [SgfIXwD j&Z8R8f4> _Ičo?74 P0ApPpHͨ 0A)[uH:;]?vvDUpPԐb'  3$Fo?/3 PsVMppPpHit'  E|^H:;=?;-\TaA)Rs' 0V$IC]GX Ss'Z8R83S 0IݔzI;HG @_>fAb!5ߌ> ]uhH># e_hA3
J1?>l  (Rw7$Ih qha3
J1Uˣ 0.NEo!IlIE @d,̀*8(ŀCj^O 0_H;Hlx?~)7π*8(ŀCj^VE `ܕ:˷
IuxuJa_ fFNQЀ
8(ŀCj^ L_
Iwr] -|TaA)R[i*z 0$IXwD j_h3
J1_ ato!I歩) @:3e{EUpP<|  G68?ib2
J1Yrq	 &T~e3rH,~e) g/(&0w]}B 	?!IFx jw{+ɀ*8(ŀCjn3}B 	VtNI4 @m7b2
J1[w_>! ]ypH-*ko
 X~UoeAb!5EXw &YQށoIT;ED jnx>oeAb!5ѷ># >un.$i6uՔ @8R8f;g  O"IJ78(( PwEĿ]UpPmѧ t,e|HNtOP {(60?6  Ie,G| 0pb3
J1_E c?6$i~umgG bW_UpP힓x}N  R=[Hjpd MRbb3
J1ֳ	 '$Iz{6Q/% ;/(>0NL9 >$q-<嫯1	 4ogAb!lT' `F=^F$^sH azogAb!|5' GF>$|[J8# $lo~(>0=^}R  wԇH$e=; 431GTaA)R{~ףO
 cVl燿$Iâ$ 48_1GTaA)R*}V  cSSgjQ;I4XB 1-zdAb!{G Iɫf~w= @YEYI{FȀ*8(ŀCjWC}V  o	+I&l)_scO@ 7Q}2
J1ZR]}Z  'Y$M-J h)Ө6pPpHktQѧ 	1$Ijӿ# h޿Q}2
J1W>-  OSw$I{[R Vt5OTaA)RVtJAy xBSr7$}e;l*6Q 4躣5WTaA)R; *o&IRZi~^8 '~2mZeAb!I}^  %o&IR{^k6 %_Q2
J1Y3c <ywI'~* ׇmT8R86 ΚiIz= G w
ߨ~pPpHmpO $u>#$Ij^ݽ~9u? FqT8R8)E xZv;IUS-? )Sgf/0\}f  ^Q1v$5[oG ZfݯſsT8R8v78_ vg>D$I5oj̿\ k*ZfAb!>3  xޔ7$M- 9W)[UpPF 6YyJT?? W_Q}3
J1%ѧ Շ$IwԇRG? 2fAb!^>5  Nw$}oJ~& z-ͣfAb!MF @98{;J[w4FT ZK%{T8R8hxv af[JπhO# F5ݣzgAb!MF}}n  fI^$-l}~5݇ ?pPpHS-' `V57l	OILņ?~ IP)E;0irS β-T-XwG `B^Q3
J1&w 4cRgjqJ4?e^F &@TaA)5(}v  *^{J4/F?f 	=- ?0i  M78kiJ4we, 0Ewm,$-gAb!MV+  ̉$UǫR+ ]{T[HȀ*8(ŀCO @uE_$iuz ?OCjFTaA)5l 07q$|~3C?I I5lo"5#0i 0wƃ;wXw{R1 `&Rs2
J1&ר'  ̝Q?`;KÙ  R.Rs2
J1&{D 5ޡgI7z_ )o#5'0i2 0OZhjQ4 mĿԨ8R8	mjQ*}  $իHk  #S>FR2
J1&;F  a!I(i|?  #$5+0ir 0]#I
+R  {E;Iˀ*8(ŀC57D! R$i[謉)  83VR2
J1&ˢ ǩ_$iRɔ {r{Iˀ*8(ŀC{& ̿HS?Vd4< n3pPpHW_}  X~{IRVnƷ} MjfTaA)g|1 ,ᅻԢ7$oJ; o'530Iٮ0׊ L5Ga'~*  <b=uTaA), ,ͧlg$-*:4 leƿ8R8$M78 `\^&5)_}m	 (wQjnTaA)V$">I  .覙_)&_4̢O7 @)Ew_JpPpHa;Ώ>I  !~oIR]S=\ SjvTaA)~OG$ 8,7$cu4 `J΀*8(ŀCvx~J(, )48eT)Ii<  }3VjtTaA)~-gD% pËH%$)lEc FR3
J1g	 7m>HE} R3
J1e+~z R~u)o4IZ_7}z L}vEITaA)~uD& ([Z_p SËvgpPpHz 4 x'M;MlՋD_Y yM-#0Ikf<}  jgtŁl$Umjqw诏>  X{[L-wpPpHz}  j)5Im}~5w]}N ]jOTaA)( '7_7$jipҔƃ3
 0{.ߙPpHz57F( *4`_?nbї `A|'veAb! P{=I5}?%T ,o0+0IOVR*3 P{E?S7IQ˷KO$ 3\gAb!~^ huGl焿$MpSSkG>  !{&S2
J1TOD hbw;q&ۓwU 582/0IOUݳSvO @E]Vl{*?6 +zqLˀ*8(ŀCC  koMvixٗS @-LJ7ڙUpPwE* *4dmwvm4<oY 7:vfAb!i[Y* @ܕzG~NRs[U/讍>i  3l6o620Iҽ @+uYRo|6}  jk|I660ISwߌ>W  QMS>:K6	I߸qSau QpPpH}  Z%_sCw3gF^ SdβqjmTaA)6O @E]wtvزf*/ @/#-vgAb!icv}̿`  `:i:˶IZزU/IËvK`C% h>өpPpH* @H?:S~FWx}z  +wڟUpP2M  _wS$}ޚ7o8 ڟUpPR-2GO rfwj-*O8 92lzj}TaA)6WO d)4q%+eixTdE_ ֙ߓ{8R8$O d*_oBIO;it) Z&"0I) 0q]sDw*[MT5J  ^}d7&#0Iip  E_Jm4F  01dAb!i6e+$ @ `L-
+JP%ip?bm &Rw_
jr2
J14F9> {.O~$un^Vb?S*?  +&+0I}  xņipҔ&(5%!NK`Cm  RJ?NDeAb!i-$>c  <a7.? uԔoJKNEgMb  ~ܰfDeAb!Js>c  lqKe[#Z6{c^s* '1&.0IUv a޺4|uI)^<n	 FvoHM^TaA)6_r LKmw -4~W^i aGLoJM\TaA)6 cS74-jy< Y&20I[U*  sx4`U4˺"RX Px;-dAb!i.]~@9 `nOËH攞[>;F `MoNMlTaA)o>g  ̳9+GSfY?[6?"  ̣jb3
J14W  &G4|;l&2̇g+  2=&FG5pPpH}> ?F9>S=e|柫ѕ[Q  υM5pPpHKiԋ>k  +:7$LM	يߩjNٮۢQ ݔm3oUMvTaA)5G5  dK[Lӿ)ulfU=ʶ}V48KiS=O+  54E]%0IsYF5  l%wSgoX-@K6Iݽ^Y^唯&|O#  YM|TaA)O  M1=RLEoZUhfﯥ2/giE @^8ȀR8$u>}  h6o>=YzG}(eQGMvzQ48sitŁ)F  hJpPpH? @i|3~ylKߙ'm}{4  ̗HldAEb!i>]~@y `ޛƷ=3*[ z?uwYIq#U/I>_9)za7  L{ǿ̀*8(ŀC|G7  &xgѕRށ5It>#ͼe>+u;'itai|93ƃ ctzm;ZaTaA)ˢO  <&_ƷFW{^*N=@5)dZivx~wR']߆7)Tߠ @o?/-XTaA)" )gKWͧmOËLw[cMw3w=*s\ṙ57⑻R1  0~4pPpHo3    @CكlҏeAb!i>    `c!pPpHϦgx*S    @壔OfAb!i     TF=[z8R8$wc?}     o
-=QTaA)潥HEs    @M([$pPpHZ}Y@    IDAT     [z8R8$-Dٮ/OȣO     5S#ul[z8R8$-TN>y     χ*0IUߏ>y     H4e=;TpPpHZ[     51hodAb!i!    @ÿ[KOUpP,[u*O     FZ7kic2
J1/'    wo6&0I]wWT     W660Io:-    GÿSKUpPz?    XO,,;pPpH
ijQ}    X`9T"0IQN    Bf)[R8R8$EmT>     ,efAb!)EEA     B>N_]Z*UpPȲ]~~    @=248R8$E7ѧ    T¿GKɀ*8(ŀCRt}
    G!_hipPpHCk!     {[¿CK̀*8(ŀCRs    <zV7hJTaA)j-S=}    cCZUpP4<    vgjTaA)RKSGg    9;CߞpPpHS뎎>     ́|38T50IuS*    @E?Y8R8$խߊ>     TP<rg,,{4pPpH[C}    `pҧÿ5KsUpP:wUy    `-ÿ3KsUpP:?EG     fap¿1KsUpPZdT#D    PB{$e=;4pPpHkS?}"    (axζߖ΀*8(ŀCR]˶}V*k$     lHm¿-KsUpP:7<w3	    F24pPpHs/Hiԋ>     <>eL7ei>2
J1TF}*    x
óK+0IuǫR*s	    (zRsÿ%KUpP&4s	    ߐ̀*8(ŀCRs	    O(Sbo|fAb!)0d    co|gAb!)	    *6N[;;0IijQn    `o8ߍȀ*8(ŀCR	    0GK[3"0IjXw    h&{@pPpHjZ-     1GKUpPƵl    ?KUpP&6?EO    ?|K,,pPpHjd>35'    `gAb!R	    C7ΒMÿKUpPTtFQ    Ᶎ"2
J1g/>     wuL-&,EdAb!e='GO)    @yw`)*0IMoxѧ    ?5;UpP|^*)    @yRdTaA)])    @댮<8UpP6
    ^v~i_):0Imix'    5+!0Im)[F
    xE`ʶ{vw_pPpHjS>     78{dAb!MM>4FV    *ޖ:6+%0Imktաѧ    _Hw^NpPpHj[=^R>>     ԙZWSTaA)â+    @~g]npPpHjc.?x}b    c|Iv:fAb!    8uzmw]pPpHjkN?0>     7oR]3
J1}f    mIN/
+50Im.[M*FZ    oR3
J1笈>     T5umWsTaA)^ݳS}8    N?+=0I/F[    ZoR2
J14mTl?    C>Jݽ_Vj@TaA)&)>     0hoRS2
J141-<}v    BRsJɀ*8(ŀC$?g     TOUpPj&){ѧ     D~U3IÿJʀ*8(ŀCҤ?cѧ    `EoR2
J14qM-Nk/    ]sxYpPpHzG}(    ,b!e^mVjbTaA)&KO0    oRS3
J14}o	    w÷βÿJM̀*8(ŀC$73    0zG~XpPpHjJ8    ̋-gUpPIot!ѧ    `ǫÿJMπ*8(ŀCҤzqJN9    SóڐUpP$T]9    3C7β-¿JmȀ*8(ŀC~*e>+VGd    9;]dAb!I?hpDd    FUjSTaA)-$|',    Z]^UjQTaA)_    0k?Uj[TaA)Ʒ~+4    }iL-*-0Izl}ߐRGg    Rwׇ_ژUpP$=ѵGFg    6<oR[3
J1Ǘ)z'    iHm]Ujkǜ3Iz>     OwÿJmwۣ`Y'Iu,9>     OjtWÿJmw`GOFi    'TקlՋÿJmwEq8(%5GOjRMѧ    q'}:4?4d>IR0    &ԙZT?4d_GOjԢ4s    akN	'`=GO^wצO6    @,4Ib{̀R'IR^w    &\Y$5`?4GOPsSY}   IR+TFW3ࠔ~$)OT    &HIl`28kiѓ48w_}   	!umT.>4.+IR攊"|    S{QiR9
`2'IMkta    s&*MlSS fA)[Ό?|԰_    \wSgDI-[3@pP$5i}   6+=-BIwۢ/gA9_}$q-4_}   cwPigѧ3࠴N/
?~z+    -?Ye7Pi4p=$5w}   6ǩÿ}J4@pPZ~$e;4a}   ^*{EI8('IMnxS    @.-Ie6(IMnXw{9    S4SwD_Z7 JRG    h;_pY8(o<Jn~%o93    &uw5Rmi8l7AIjz=^Ҩ}   &Rw_	)鱍oFu8<JR    _auy8AIjE˶H7Gu    7:SkJzL^}h	fetEPRDu    ڔs3%="Dΰ6,<JR[]wte    j̟ǔčAKp0k~%-e;0uѧ    ѕÔkn>$I>    @ߒ[e+I(O-anFAV58w]}   G]Jz~4R"Z=:S$o_     g/f)]}XE8$GQ];    ,YYJIOTl?\"T?_$[^K    `B:ǫUJzʺ_kApP$AH(<    '¿QJzg->Qژߛ    g|	&%m\]DZƀz|$8JRV>/5g    X ţl6&%=}/7i38lxaRZ}   g~r7IIuigIIjkO>    <$[/Ap0'0HJRb!    d|9do6nק0/8ë?|6    ذ:e;0opFZʀ9Mm~,%M-N;/>    \*;]%*;׃2`c)ImǫRv=    0Gg/(\}:h1$7)    s`|٩do5Ap0w;$i~T    )E%*)Bp0Bᔤ5)z'    "OCQR'm8SnNjp<%    %ͮ|5'3`uzgַdӔsy    J~^,$z{	ap0~@%i)g    EgMV85)g	`RgQIg-    );}%ͮ^M(/	y18C*IT, ۻgAE[-"XeZSZ2ESK]tpԩt֎S%Y0"(2
RD0H
F!r!ْ{}9k'<  <%q#ԄfDKT'*    oabe%Y/u̘UOT:W}.{    S%yݛ=J̘rǯcjCUjĳG?    hzkPVtiB8`F.h`T,Ө;G?    >34=J̨r!IXG?    ^o]U,=4'Ԍf\OXIS{    P[僷Gc޾{BIӫwr+S>d%.ǿ$    S5bwWWDB9`V/A+Iud~    !}7(i_=Q)̊rC15oa+Iu    fGϥ%MGfjWTqDȆ    c}4w,{Pc8=v^?x%FVyG7    3ܼ.OJ~+?=R9̪IT/    0hWqX|PTG
5瀃Y<Xjo%{   xh~wO@FT̾;bjb!,Iu?4     3}'i0}OH]p}$խe    0/ĜW,x~T;6f9:E|'$js     FZݻ~᛾4.+;8Hӻژ,IuXt`T;7e?    0bk4OҸZֈ-;8HպYV댷E'     FK3>}'i0rgOpj/IВT    Hi_׳
{1u̜!-Ijr?pS     #{;=I}G
<!KԒT/-	    ֿhLϓ4eE~4{rpuX-Iu}_     Zk@OҀ:9QOCC$z5+     :(4=Z)9`t׬JܒT喻     f4OSNjcٓN;KTED~     _UE$iGZOũrI[>    @ε:IXGQmEhgC|dc4(}KR='	    4uEcbNNҀO7\=Zs򦘚;KR[~    `֕nƼwtĜ]=Z`8`un>)KRjN#	    YSx %$G6IT~4{   :SwrW-Gp02Z?}KR     fVsޕ4Z7eO#8V4W>%V}n~    `fTU/DNj|g9`dDq+$թI3	    \34+H0p0RG6F HRj}v5    ޚ{7IQ5g6@Te    ј;}&i05OymTဃ߲>^ HRm;n    0-nƼmRsj<=Z``p0?T%/_g    #X|PM`j۲GFZ>Cf֪D    vK5PK߯IL٣#=K
IK+?=   \7{5IEZٓfB}C^`HR]q~   Fw$w-gO18FqkICrW   'WUѾ4Ihr3c,Es[IA_U    OsDM _=R`V8`:Q$ՠYqu    ޚ3Iӯ8(7ݖ=R`8`<UUtnXSIX$i|S    ~ј;}o&izV%G
*?04M̉g|    rͻn!}g&iZ/9:)0p0(_ziC#Icܼ.{   Pc}B2I{\yѻ8ʩyIeEUl    P(#5Oym'Q}dL3'qwD   @T;b1I{Ĝ~eJȘ}]  IDAT'ӻh$i>=   j]g_wu(ဃZ*wn(IҸֻmU   `Uoykwa7?kqpP_U5+bj$]>;Ϟ    h4O;<&i+dJ8CwFץ?V4nr}c   qmF댷$fs}Q>uxLg?^4F5QwfOy    EN{Iڽ'*1{s4#1IZ__DUfx    F]ُJwIzDFxD?j4.u   (h_rtK3lYFx壛NƤggv    FTϦ$=Z_{{eI8i7ŊM$i䛻O){   0b?ے5O;<^=2`9g*?~4jS   	;-IO]7Fe~LVtn\E?45OzeT   !јϒ5>w_pv#:?<1_8J(:"zi   YxCZ+7`8rXJҨվ#~   8ސcek8` Ttn>)e?4Bu=   "xCWQM==p e4_{G*I#Ĝ]=   ΈĳwVRݛO`ڧ(,s3h}oC+I}6    |mĜh<"Us{Hr3l=5+Wbͽ#   7'::GfWFOGc$[,ƖQ   ,r!rGFDcc d(m=8$!yQu4    wY7YXvX/9:z?VT]Q,{y#.IٵV;eOg    fi;1::z)0bpo/:,ƼzIJ}'"*{$   0zkq!XWGGѿZp#^'z!:/DcYsD   `zkWGcrݓ4Jok#9QRUrwt׬ I3UǧgO^    (HlQ,;lW寏3Kݛ+\;#E?]`9QWUQn?zw]D낏c*Inr]     1?u
    IENDB`PNG

   IHDR     
   K   	pHYs    {Rk    IDATxOgARPHA`aBPbpa a0*bL	3Ni,TXP$%T
d)Z
)Ri9{=fμ~y~缿}K       p]2        <}                @                                            @                         @                                            @                         @                                            @                         @                                            @                         @                                            @                         @                                            @                         @                                            @                         @                                            @                         @                                            @                         @                                            @                         @                                            @                         @                                            @                         @                                            @                         @                                            @                         @                                            @                         @                                            @                         @                                            @                         @                                            @                         @                                            @                         @                                            @                         @                                            @                         @                                            @                         @                                            @                         @                                            @                         @                                            @                         @                                            @                         @                                            @                         @                                            @                         @                                            @                         @                                            @                         @                                            @                         @                                            @                         @                                            @                         @                                            @                         @                                            @                         @                                            @                         @                                            @                         @                                            @                         @                                            @                         @                                            @                         @                                            @                         @                                            @                         @                                            @                         @                                            @                         @                                            @                         @                                            @                         @                                            @                         @                                            @                         @                                            @                         @                                            @                         @                                            @                         @                                            @                         @                                            @                         @                                            @                         @                                            @                         @                                            @                         @                                            @                         @                                            @                         @                                    ͷacS[~w,5cqx%fw>q    lcy˦ߍyS\}MϾ{x #O<:۱ɱ? ny͋;_}   p>cL#33~qnw߸}lxt㈧@ pm_ޙ67r.׾tlw   =l󒱺c}cnf?	 G{?vcqf6u;q#&    ?pK쪟;ƱCSLӇ7΍2S
    _\bݙ]_5߻ֱ]=1uQ \`'o;cqfv׍㳏+    o=3_8̎N]6VwX/f?.:aog?ɱcqn׏fZ     w겱{gncA p?[7s7f=   ˧ߩ1ڻfn|ُ43l|l~X_"3;6۽cl70    8gG0pffԷv燳g9g7??VX|/88}   Sycqecuͷ8! x:'C0c}   ӲyNgffO{?w16mǚ aػCcy/M"    TlqX\wnffu/{cx; Ob3_0ofw'5n    Ϩ}t,N\:;}Xugs jk7go}   yށM33ՎrcX o֋ßX\l3;c5d   jřYΆ {;uG {_X\?fؕ_    .'gff/3c; ßuG|b    w̿33|ُ#G kn{vyc8    oGgffݝxXw;z1v|KP3kOß}   }[v3 "ʕ+(*6ՋkA~zw3-mRI#ɄTRH!4@:4ˤ6֮k树d9{)Sf'<*aY$i+{a_1E5z`pyQ~濤BJևf_     _Տ;N4{){/&kxtNٷ%4y    ߭ߎ~9N4-4_D5n`pӗx_;   ة;OF{?Ó$5~<}%1 _4IS[Q}A    Vhh^IҨYS>_FS4b`p__}   W?qwH$9{!&A/,bfa/)nVQ+    L7FI-wN*. Tk}ߒ$i+{aT\}   3(=?OԬڇ'i5 뎞_I˾   Īnr7?$5ꞋcM@ՏbfA/E1W=    xkt/I}7GLY y(3E?    ̭IY焿tbZL@uףy_I_S0    wI?$5r4GyвGuW/{    0:'E9$uT_n zs$[Fuٗ=    nU?:7<Pw|jL 'U/tn==    +}%Il&ѻtߘT 0쮎?IjfQtr    .?>(Ijl/cİI3Q 5EKaKjH77Ͼ   @#-ʝ~8P:8$?dIi&1K    4ˣXUy$u^LX >~WDWRCY+̾    QwL?7$5;ߎI0 #7G6?TIifA//    |~v(Ijtwc P=x};")A/'     [$)51vz(V2(9/X}    I]G#J]_wG돦$5ٟξ    ϥGw'J]ޓ- On?CԜz~,    dyS$uaf krmXSٗ?    `=eEIR~b܌d,    <eO?g$5931Nc`ЋJHjNC3b;    Q,$QfDb\@KԘ+!Wd_    9пh3GIR[Yn?'A@k@$5?uK    0z~,Q~(Gni@cYÐԌ{dkʼ    aXEAJ]bf. T~=[$5[^u    Y]=gf>UY F6|IͨQ?~g    IR+h@՟zKjF/׌R    >pu˷J?$5ѿf, tOofyQ}/s    @'D10R^7M@ӿђMf|    _[N)Ijt}+szFo#i4,U    q?$5Ή9 N%+/y$6    `:^3KIR_t- to:    IDATf;c    ^`h٥$;<O_bfa7U=O"|_    	3|( Sڇ+b8aX&)i?"|^    	Vt?X$EfK?; ~?(ikr>/g    蟿Sy$-*Go%M}u    S{܇5%Iͭs; e`X~+^͓4ݕ;:'    0hs盒ֿZ |#4I]݋bq	    \zesJYbX qn3ҿi%EuW    4KXEy$uO	X Qo)nfA9|N/]    @3>,Sg^= ݳ>4/X1-    zC$6۽Uy=W,    os竮JY@MH:G/bX%    iuh砒Uc$Mo+r    .[JWOp>oNH{dsr    x6bfA$a-<o6 H[Gsr    X35lTԼ~p zE;m͐4-*_1':    u6D?#$5Q=pm@I¨n:i/p     n??V*IjT/A:8 i_F_     6kXRIRr z_]4uuO덺    ̕GJU~`~<_K:k    )~v*IjGe?xh g:4Uysݧ6b    0/^3TI=hN>4(i-iz*W2'    |<.ۤJMc{wg`IӲ7    0*Fd3UIR#, Q_)ifan<a.^     ֿhsUIR#*wx@ӿPIS]    ?H?[$5+wm_{_     [[M?c$M1ӿ@IQߌ2[    >x]˞~*IϞ1L$M~|tCfj    1VI=~`X<-ӿ8I]݋b76t    +ݓ&U4-2cs лh/Ldxn=mcfi    2F{柿J@׶_ɮ7f    KwG`%I[{n`p_ɮ{G7v    [-F1 ,VԚچ<7 ?H:jD՟    `ldy$5os +XU#i2+wGh|    cAt|G$56z_ɬ1|膹    ^}QYIRk*>x- t@!iYͧ    0[ObfA9$)޹K6|`]Ų&E    01zg~"VԚy H'|dge    Rk%Ik >w_ɪoǸ    0Q'rǗJZSU7`WDt/ir*WlSӨ    0y[NbfA$55u_ |j4A-,Λ    `b3\IRLMK6Z /\Կt    &WՏʷJZSSuۙ P-i2~s4    xDKs%Iw'}z,i2j3|     opqg<[şIƿrQ?u|     S{_JZ¨Gm}{_nQ}(a    +OJbx:, Ql+i\a    2|(n~+IjMt> ժ_{GF5    L%{JZ]_{ޥPI[{#Q     өs|%I :Q4;,'    0(w~uٯ$5 ]^"%a3Qξ     S(o,IIlpϼ 0|(i<럷è^    F}π%IwǞy`_sg?
    yP[ς%I_~9K_Ǣn?6q    Q	KZU+y}勵@Ic-cQϹ     ԿlsaIRLZǼO/ .IW1    4ڏd>$&_ 5Q,Lqƣ6i    hx$L?#$&Շ}@u/Lx"ݬ    ѪΌbfAY$5@/LR~/Z     "w?KZQ|@O0I,,     Yߐn,Iq~@$;g&k    {&%KZc]/LR^1X     ~;KZM9@0I);"ի2gX     ~z8\ȒXW~[Gky*IJjfaT:    r'Kb\Fz$)޹SW     ϓ%Iͧ Is~     0::7\YW-տ$i;"իRU     w.w|Y$5v/Ew$i,궳RU     _ug̒_]=/HꝻ8u@    `uP9$5VVĿLAFSwF    Wwrפ7KZcSK}>/HWWJL    xgG1 YV_JA湙QvV@
    ~=Kb{OZoLAF     L:~,YJsػ?"I5     ̽ί( IR|@k_\>zk 
    wgђVj~B/H4    y+w{&9=OZ/IA,u    `4|$5}*o$mk=S'     ;Ϧ%I:b/Hdwi	    h3jIR. 4w/%u     GuyQ,L?$FZ4Eu{wD=L0    ?UKZ#4+z̓%     zE.ZY ikfAT<#u    `<Tw3{n~v-IQd@z$     {_]KZ#4E6N$    /u(w3lIRk޳  MKK6     Sϱ%I1Y ;     L?˖$5 /E    VFiKZ i+qOܕ:4    0~-Ij[ 	o     s϶%Iy4u@    WrqKZs iB+w&cC"     gϹ%I94,SC     &X=΁?$\f@zs\    >tCK6O?$, ҄NP    tsoIRkβ  MR7     LA7{T$)" ;wI    :/gFg@ڟ}KDO    N>~.Ijmt Ih1|    UߊrW䟇Kbc  M@V~     L5O?$6* Ҙ^a:    Cߕ~..Ijmp qn1|a    樟+[埏KbC  qKL     hyۧKZ iLz:    @U/{m~N.Ijw qlV1|    :?咤X, Hc     trIRk  YCQשC     krKZ iZUԏߑ:    __ٹ$)5 տtA     K=_H??$) ҘvZ;H    8>x]7M?G$3 8t>rS      Ϥw%I\Y Ơn     l(w&<]z, Hɵو up    23uIRY  ex>pu     so埭K♲  %A     XY$  %kۈA7uP    ;_%I )śS4     uwu;:]ߛ )YL     `c=2], H##     6J]G_I?s$+ (Ygd     0#%埽K?  I:    \wIR, H#\ʨۏb     0SQ3xIRk6 ҈|!     C%I, H#sS/     7uoO?$, H]݋~     pUQ,L?ױ  oK     `'y$5 iZGQS.     zCQnyIjr <t>|c     Կ`E$5 i~my     #WOKR, HP{tSg,     Ptr9$4,ꞋR+     9=yY ީK      Xi$4+DP     w%hX 9lp푩     x;<^e@:jD]S     0N}6^e@l>yF     wVMY W-u~    qUzZ9$&ޚ	     YJ?ϗY 6ꦓR&     wk?FXi$S i#Z     <M?חbʳ  mh˞wK     0)({Q$-, HXkS%     4vH?ߗb  m@=^1I     0q(w{m9$S in==u>    I5s~I*4 z=S#     huޖ~/If@Z=/'N     `Uw_/I/ z;wI@     Ӣs寧KR1eY ֱr     L᣷DdI*( :6A     MK~/Ie@ZbD]A     0m({as I*$ s50_:     Ꝼ$Y$-, HQ䏦>     0ޚ(W2y$S Y*{QkL|     `//$S Y_G     0D{mӟHR1Y ^?QS     h'?b³  =Cխ:     4ߑ|@	0     Ѩ($ {[Y5u    ;
$idf@z}<u    &>tC3ӟHR1Y rF]<:     @ugTL` ԁ     +[?7b²  {.Dԁ     ީKv Ińe@:      .TLP Eh0u     [O?Cb  -jEuWR     ՝'e$ 5I^     gֿ`g	TLH fS     Y:Qg
h F=/Sg     XLA	۲G}     ~x}IZ4Y PcY     XwkO IŘg@釣>:      aXE{mӟ1HR1Y P#_     XM Ig@e~;u@     6@]GoI IŘf@kpRg     `U7A1U3%b8HL     >ӟ9HR1Y P\ԁ     x7H If@ϛ#a@     ̍AA1Su)     0w/H IŘe@}":u     V_O!Ie@     {=?b so     gTI 4z     ̟ὗ?bL s     gTA 4,צ     . Ԛ:l      97ӟMHR Mg3b     0:=?EY T=S     `:F3
I* M0     . ^H.     <C~=Y$IY W     @ꞋWHҢ, hC     s?"! _ue@     ZsIZ4, hja     RI*F MM.K$     QzzI*F MEߛ:D      㧽ϥ?ÐbY TT}a      ӟaHR1, h     Su}ޜ,Ce@_u     0,Ce@]O     17O?ӐbY DW|J      U?ӐbY kۈz:0      Gۏ?ېb mpSg     `r/lI*9 ]_QR     `QgTc 4/3uF      &O]ӟqHR1Y U{kR     `:$, huYl      L9ҟuHR1OY d|GS     `rf7?Es MT9u(      &_ԏ?b ifQ?yO@      L{g;?Es ML<u      G?M!Ig@̂>A      Ç}D] 4uo      LʲHR1Y DTvV    $跣^*fW]]E3bpq1_o/X1[>>ݓ?^TG{.WGQߊ  0/H"If@c_{7:\ I7^`.Ό5EG	#ryS;:eKoᇢ}ۢs{{DE#>|cǲ  b opŁ7~  9Ts/g>S?6PDb(fEjK5:;'MDuQ?u_O  fEs u/}O   W{I;juĿArx?-*ڟ}Kt_;1wiݧ  0z݈@m| 4Yz Ftgߢ>?CQ.A4rF>9UW  3_9Ʒ%G>  L}>\.w䟤lw8鯢~12K  1(w~    IDATU/I6. ۺ_{=  LoE1+{mM}Rީk;  `1E mk"	  XGunFOEwEz/G UWFT  [uq&)&= :3&  neU735:jۿ8}Wn_>xmD=U ;s$ eM' `Twi/3q6}ft]"~4C^*7  ҭ(-&, hj
 F(n>,?={W  h̟%iцe@cW}Ro  0r"ώ޹KsoFd\*o#kd  W㒴hò QwJ QzzhsQ,$}[D^P   wޙ?KҢƪީzC R?~GX9_ُ_gk  [ 4V!  s.uGEDgmi^Zit{w:  0]:{m?sKҢƦAz/ v>gJ:{ƖFڲE?"U?G  h+??gKҢƦǤ `QqnN(w]L-KWFÇW
  ߎrN%X, h,ZQS  NzEn86}(^>KKw\y  4sԒTG 4]z goGu)⇣\Y^ݓ?UWf uVGtyZu[iOݗz 㡿4o{kX9  .̞%X, (Hq |Q,{^,M{劭g^@~  xFUWΒTc ^u97n  ٷ&/I|,5%E?=X q9WfIZY Pj~j  F~_"{>}.u|ooE  IuI鳲$ ֿd6  RwD{gaI^{7#~  "U.}N9 =?k  ao֫r%{F:ٗ  n\=KRY PZݓ:F toED{7Ͼ6r跳//  4T]/N%x, (}ި N]E?b3\_E   RNXgRj4  S_E{ߟNu%rmbpU?
 @ԏMaI*! Ji `#իWE%QWRNn+#U%	 s$ϐ [~+  ls}.${ͧd_  hfϿT<C 4~+  ?>J+!{.ξb 09}d@#ԛ2  rMe%MH3{Fٗ0  T^IZY H+wzzS `2O>/Nc%MhK93v% )SDKg^IZY Hmy 77{_DdU,W7) O鳮$ߓ Q?yO '4śϮ!Gnξ 0%>#{Ε; _6  Ç/~8śϬВͣw#zE )oϸ? UxbM 2|Q,HU%5rEu˩ٗB  &\3g[I*# I劭#~M Ƣ   u=k\+Iſg@#w'R  䫟+'|[K=/1/  L%{ϴY H>tC <uHTKLK%j1|&  rϳTX (j37^  rԝ'gRIZn   XoS>E 4z `Ć\2ʝ^>J҆   XkgbfA+I oSo  NuMs$ջ\»  N:VRX Ш~  ^ÇoM?%i>j|w  9;:}v gI 0־SĿbfa)IڲE"a qU\u*u, h*{QDz `ѿd(q)IsȯG0  cwMY%5 Wݓ:& :/9}ޔʝ^7Ⱦ 0'b&3f@Vu7Y  ڿx~Q,H5%);U? yUR45 ~,So  _K_>gJҸ9  9URs yw΢ԛ+  sc5gKI_ɾd 0.:{>}Njd 4/9
 F;S>P֣	  VϧZ?zS `TnM+%ik-1|K9  (n>Jj5. _;
 {܇II^mgf_ H=OgSIe@s¨WJ [ίʟ'%iZZ۾W  TR4- :z SwM#%iZ~}  I{7ϤZ+So  gD63$M{}:̾ V k񦳟 x;OIq/so  X]~+[ϣZaz `>GgGIjdK6d
  ?Jd@sCRo  < z,b&s$51f  gPId@sӒͣn?z ;:#f$=]{/D]>}  `D{!}jD 4'u'  ?%$k  ӯnV# 9ip7N  [[3%i*w~U: <[O-OI6[F}*	 >rsyS(IZo-_ξ}  0Ϻq))= _7L  >Hʞ%IMbpٷ  QuWNI1Y Fse H6Dﴏφw֧": ػx;Aζ:ztPi{ڢX/jOڣm=jj{y!BP Q d
8@4 	f7Wv[kz!=kg'.|Fj 搟˹
}XJ$5ჷI?[t9ǋ$IvseY/zFj %Ib+6^[>'|.`\~H$igso7O<?K3&0 %$Ijle_?*3! {Fs1Sb$I<ܲ!/|epyi$ 켱h3U$mmob
'!G$IM͹ظ2VYύ  Y$IR>|gngA F?$IY}<Ź{޻s먗χ i iu>t%IVqUu@ m3|tSH$:yx}}k@ sFgCÒ$IMjpi㿂)| LؗჷG?$IjS]y~y;i3@E )P$IjLe9;? fQ/o~:I$Ur\l\9sްr N3jIFK>0? 觔$IҌnŦ5_bnn % )#w>%I	} LÞ#q%Iߠ;~֒ܽ?4:+|^HA '>Y.IT?e<G} lC|+%I*y3soGrs248 `;$.ITB| TM {E?$I+soXu  6ܲ!/IT׶-5Ңg{ TKc$ITݚMkr]17u* ;}kB I6X<O ֑/r/Ip0>l,ܽCdNNg*T !+>:H$ձG4:+|ZG,acM$ɕe>qK?ۧfNcN  C$IjUY>Pc_G~IWnݜ\{Wk:3@j L۶t.$IRGg< uG$I=Mkr]1wg<d LW$IiX2|ڟ񟾓$ImyeWKitvȓ8 `ڶ=%I=v ߶+G?$IR+<|<Ywri~ #Sr e:oH$UA7wg; }oKO@I4+?W9:s #; >CIo><h$I*[squs?ͭc_> 08 `Z_;,t $ItEo'(g: {_+Ip[6ުy> 08 `Z/tF$I7~g< 觢$IÕ[7oʝe3 #{ :$I4,r? _8(IvSe\yu\ s m#IToY dtvzASR$hMkƏ+99Ί- 3 Tl$t$I\0w/s <k$i<o}|_g% *p ?~Y(I[9 &:yx$i3n>'.x,;(E , LBIջf4|hܺ9)IR*[=;ߑ[G |& `V 07O$IT'o #K$z)Źbnn/? # I|?t>$IJ vTw\$Ua[6幷jW`q 0 %I4u^ߘ<-|~ջ_$Uss;)E@r d_J$
7ߘ[<+|v]5XǪ$I3W9:m Hp 7:TI$ͭc~1|nbl\}]U؊~n!.ss{ɜFg?`8 ੍e:gI$}үm xA>|GcVӰ-`[5/w v R{C.I]ϝ3>>u<$iWnݜ+soW~@s n Ի򓡃$IҌ,sw_k 'uAASWl?~5]G8
 i/p S*&t8$I?2|Vw?G?v%I^Eם+96Y
 ) Eȹ$IfbW`y Yypя_IܰsoռYvPNn O?I$=sj 7yVǰ$[7b[=U|49 ЁN$i&		  ¶g`y4q,Ij@e\lZkyέ^T1 w\K$E,G :gQ0,ISEם+99@8 <ɶ\s$IL>Lпǲ$<<[^z`NcO@! <I?%IfRKr>0:;~<K*Pus.6̽csuc 0 $:J$͔0{n| 3I;ӒTݚMkrWU
  kmâ$IҌ>L>Ws֒<ܲ!/݋?K挿!&  ~ur.Q$i&] d/ q-Iӕ<|]ilg 02) LΓ$I3es ToISEwտoɭC Fv ~fSBLI[Ӣge P	OJWݚMkr]17us Ȼ ~fmC$IRhnn _ιߎ~K&k8-ҽCdNNß!  q_:J$E׻3 TQ~KMypj^,;(EV  #{ u/СT$)s>@UnR\Y\l\{r笃s? P 7)$IROXi<|Ǻ$պ5w__?*wyWn_ :J$EYY _ϹE?%yeC_>*s  [G,t$IjY w?F?%o&ʝe_Jr @V$)֡ VFgb%яyIѕOܿϝ3ߖ[ u ЁW$iW㋶9 us觽$͈ش&.ss{ɜ H9  9t$I$|:vhNp[6幷j^n/=0M F@õ}N"t.$Iڛܕ!?>@y㠤7|<Kr{_{ : sCdIW^ymя~I-Gsqչz,w:8|QY _(tp$Iڛm{g M׹G cR.6sw^2'Y_S 48 hkBgiIUzO @c$Mܰ-Ə{βr7k' @I l>n%IV?@-xZQ@+nƕ_[]II ka[$ioUqE M>5ԖYmmfw/z 0 ֻc$I^3|^@R+y_8wW%sr  e lp˹3$Iިs ]qۥѣ:47' f  V>vO.I+In خur~$zDTʭsqW֜g  ir Pc~!th$IuO <Y="HriM9:%_  R8 h%Itۖ~' LG
fBE?7ߐkd `q Po-	%Ih"?+3 ZǾ<ǣ'I{a?%n|^>9-xZ# T3 j$I{[ M iVnݜ+soW~@   hlߜ $I{~; \qE i7~{wn1  @?$Idk[ {E.[I;R-`ݩbnn/3~ q á$ITeڒ[>;| ##I*+/ϽUrgA9-/  #r @O I^Y ؉_pcmߺ9W9:_#  ;@zk	I=i ڟ9[ԨΣܿ9uKÿ  0 4Lg<,B?\H$s    IDAT/| v^OER}+yeC;5wW%sr @t>~֐$I=Z .X<o}X!բ`[5/w  ӻ>$ID>g }o\GR[7b[=;g[??2  #a 4C?H$K>Y=^H35o  ( f$IT? ݧussCO7'6YF  4H~f$IzzA;i  Y1$I?>c {Fqۥѣb[=;g[G   # Az׌~$Iڝݓg, `hʜC㹸ku_d'u/ ` 4H~ؑ$Iڝ.x| Y+?=rH;p[6o/=Я  M |?$IPn
 <-9zo˃_̽>ۧ F8 haP"IT. w44#*ޗ+soXupn   4D%$In߲lެn׏sޕ[Ǿ<  ip ~G$IR
 ػZG$Ǣյ lȃsoռ^z`N @	 bp$IvKe'6| W)zQM*n*+?;i3~ @M 4$IvGmU @Oß=bGsqչz,w:8|Qe  8 h}s.z$IvG?[ a:y@SKش&.ss{ɜFg 9 ho%I; ̈́<ܲ!/ϽUl  9 hW*$IU @1ѣr͹ظrxkNw   L$ʕO4U л`eڒ.ͽrg/;  " 4@C?I$jkT 2o>x[Q/bӚ`鮘KO  09 Y<9N$i_>W 3J=hGe{s_i>   Ոku$IZT TqEI*+n97.9M9-zf  H5 \K9g* `fj*W|eQsu~  @j  5׻C?I$JÇ;`I4zdi^E?7ߐkd   jnpә%Iv ury4zlo"lȃsoռYvPN  <% 57w]gDIέß>O 3_ODO.ܺ9W?y} is Pgs$I;) =TP.n<]4$l  @ juC?DJ$J>O =]̮r]17itV7  `dr Pc(s$IV>r4 ÊcfF"lȃsoռYv[   #{]Ϛ$I;[ ianZ͹ظ2VY   FB8 /~$IکEnY
 Mg:WWuuK @)$Iδm=G :sr-*_]17itv1  02c9 9ۡQ%Iv J_db#w幷j^,;(Y  # ڟ$I;J[n `W{^.[\=yaE]֡s  F*@Muǡb%IvQ @=OyTvŝW˝ߙ[G,  % 5ջӡl%Ivo	 w{ l9㿪1  M 7?J$B`9
 3#wj^,;ȯ3  r$ 5U{$Ivq <|nWʭsqe˝έ#^  `@Mwۇ[IQ
 M\lZ3~]17U  4 5:ݸ$InitV SqՓ#An0*%s     5$IT#g( 'ZIzA;i  n +"hu/IsO~} [oͭÞ   ! jB$I;R'    T jh%$IҎ	    @ 54%$IҎO      %$It+i3    s P3^ė$Iڑ>?    p P33~?t/I#u    @	 5ӻC$InͭC>?    p P3oǗ$In>;    q P3.
]K$Mު     R8 ]K$M9    @ 5Sv]K$M{&    T3 juC$Imp    @ 5o.%I[>;    q P#ȗ$IVe[G4|v    H5 FzW}:t/I4     R9 SC$Iө&    TC je$It,	     Ր>|g2_$iʆEn	     ՐXOE?t/I4UM     @M{e2_$i:	     Ք|wC$Iө{M      D]K$Mֱ/     RM9 5C$ISU>)|f    H5 &N]K$M{gL      Dq}Ip    j@M9t/I4Uo     R9 XB_$iҊ^NcL      @g%Ijx	     ՜hЅ$IT{J    j@t|[B_$i(|f    H5 }0t/I4UL      @څ}II+z9-/|f    H5 7~!t/I4Yn
     R8 ΫB$I5y	     5n~R_$iz+?>/    p PeХ$Idu>_%      n}Ij	    `~9 q]K$MVz(|^    H ڧvR_$iM_     RC8 9ԗ$IS%     *#K}I]y	     5_(t/I4Y3>/    p PquB$I:    @j Wl\ԗ$IDN%     *nxwC$I5w]    @ŕ$t/I4Q[     R8 Y9ž$ID?2~^     *uC$Iսo%      *?.%I&s%      *ԗ$I		     R8 y]K$MX9i~    @j [н$ID$|V    H z.%I&ش&|V    H kO]K$M`g%    0 *lp9}I_(|V    H ;]K$MTJ     a TB$IYY	     5
+'t/I4Q>+    q Pa]K$MT먗J     a TTg.%I&lX`y	     5jн$IDO>+    r PQzb_$i>+    r PQ3ؗ$I_     R9 ]K$Mg%    @ *{߅.%I&g%    @ *wէC$Iջc    @j  տž$IDuY	     5|s}I{    @j  5ž$ID1|V    H /]K$MTWJ      T𞵡}IjY	     5>ž$ISVs>+    r PQBw$IOU~$|N    H rܗ$IzG
     RC9 }C$I5|c    0 TP먗.%I&Y	     5
jž$ID6     RC9 7.%I&jnY    @uN{sb_$ik	     RC9 w.%I&z,|V    H ;t/I4Q+9|V    H _ž$ID.h    @.Xb_$i_Y	     5
]/}IY	     5
ž$IDu    @j( 	}I    @j( 4ž$IDuN{S    @n97t/I4Qo     RC9 KC$I>    @j( T}]b_$iZǽ"|V    H ?Nb_$iZG8|V    H ?%t/I4QC>+    r PAÇ~ؗ$IpY	     5
*'t/I4Qi    @j( TB$IFgJ      TPؗ$I9	    : 'ž$IS6,$    &8 ١{}I	+z    @u T̢g%I&ߎ      ZZ??t/I4QeY	    : uχ.%I&<>+    4Y@ub_$i    @u TK{ɜž$IDY	    : }B$IU>q    d >B$IU>~o    d 9͡}I*I    d 9-}I*>+    4Y@t|[b_$iʴ%|V    hj|C$IU
      Z:g3t/I4QeY	    : {λB$IU      Z't/I4av    d ҽ}{}I	+z    @u TKK$Mذ      Z}0t/I4Yѳ    @u TK]K$MVZO    @.hR_$iؾ    @j( ӻK}IJ>/    r P1Х$Id}v    @DR_$iZ=/|^    H bzWsR_$iZG$|^    H b H\WK      TLO.%I&}k%    P *$IɵO~}    @8 $I3>/    r P1+?ԗ$Io	     RC9  $i&K      T I4    @j( ӻӡK}I^y	     5q  Ifr݋g    @Х$Id.X    @8 $I3ޕ     RC9 @$z%    P *wB$Iտy	     5]Х$IdyB    @.xR_$i떅K      TLﲏ.%I&kp˹    @j( [Х$Id
     RC9 %ԗ$IbӚy	     5^?C$I5{    @j( _.%I&|y	     5Х$Id%    P *{B$IV%    P *{{Cw$IS=#|f    H b;t/I4U^>3    r P1sЗ$I		     R9 ]K$MU{3    @j  .%I>3    r P1/t/I4U/q    @tN{SB_$i+L      TL]K$MUҿ     R9 IЗ$IU>3    r P1_З$Icg&    @ *uC$IS53    @j  :B$ISU	     5iЅ$IT?>|f    H bZ>'t/I4U-g&    @ f}I*?~f    < ftVB_$iʊ^    0y TP.;}Ij	     5
*{O.%Iu+g&    0 *l=З$Io     R8 {B$IS93    @j 4|Ѕ$ITuO    @)t/I4U     R8 ]K$MU3    @j TyuB_$iL    @/	]K$M`	     5
rnB_$i.     R8 _]K$MoL     a TP'.%I|	     5
9&t/I4eV    @]ϗ$INC>7    q PA+?̗$IN	     5
ꭚ̗$INe>7    q PA݋>̗$INs$|n    H Y2_$i:u/	     5
,G2_$i:VM     A TP7.%IS;K&      *}ү.%I_     R8 ]K$M     R8 ֑/
]K$MwM     A TC$Iөn     7E?t/I4ҢgM     ! TT~$t/I4Zǽ2|n    H ~̗$INSs    @Ezk2_$i:u~g    @EY̗$IN݋&|n    H ;]K$M5s    @j 5ذ"t/I4=%|n    H 7|>t/I4.     RC8 7]K$M}7M     ! TԶߧ+I4+Ӗ	     5]e$IҴ*˜>;    p PQsCw$Iӭu+g'      *s.%I[{N      TT7.%I[wN      TTȗ$In?>;    p PQc_ȗ$In5ǆN      TTg.%I/N      TXB$Iө&      *l=̗$INÇ     R8 mtI_>7    p Pa{ׅ%I[g'    Ts *E$Itkg'    Ts *lpy|I9    @9 ɡ|I_N     +Ȟ    IDAT TXCB$Iӭwh    j@VC"_$i֝>;    s Paȗ$InWNfޟ-+/8FGIbXN/X&Qk4*3IbbtTcrhshrmA.\[
@m}{6#r;{g?ߪ?pᩧZo   fs Pcȗ$IZh7N      XgB$In     R9 !Ǘ$IO      X{.%I&s䯄O      C$I{{'    r PsE?t/I~4|v    H ȗ$IZh+	     R9 ].%I3g'    ` jni}"_$i6|v    H ȗ$IZhE?|v    H ]K$MRZ	     5%$I$u{e    @N%$I$u?    @j( 5=K|IIP    @uxm_$i>?    r Ps_ė$I'O      ʧe1]K$-і    \39 h-t/IЊ[g'    P `||I7i    @j  0ri_$i4|~    H 7ė$Iq>?    r  ]K$MRO      4=C$I4ظO    @K|IIpr    @tOyO_$iw5|~    H :G)t/I4IE/|~    H %$IҤ~v    @,%$I$uxM    0, |?t/I4Iݓ>?    q 7.%I&'    0 btǆ%$I$T    @Co89t/I4Io~)|~    H !ė$IO     a 4Dė$IaLP     A 4D%I&}Kg(      .%I&{g(      sC$I;3    @j B$I6x
     5).%I&ix    @j 2~`s_$iFw]>?    q  ;.
]K$MRw'      dφ.%I&(ʴ3    @j 2d$IҤuxM    @|II=|    H LI:Կ3    @j 9ⵡ|II^w\    @W?/t/I4i;>C    p 0ė$I{'     fo.%I&g(      ftǆ$IҤu>g(      fx	|II}P      4`㾡|II_O3    @j  _.%I&mφP      4Lw.%I&mt3    @j  B$IVg(      |I*yN    j@N_$i:Gj    j@$Iީ>C    s @o_$I3    @9 4$IҤ/3    @9 4tu_$i[
     R9 h*t/I4iE3    @9 =]|I*}n    j@u$IR:k>G    s @5/]K$Uw(    Tc h~EY|II\*~    / 5v[_$i҆7>C    s P/]K$Mg(    Tc jcB$I7is    @) տB$IUj9
     Ք{I*uOx[    j@Cu~S^$Js?>G    r P^$I(    TS $IҤ}I    j@%t/I4iP      4h9|I*yN    j@T^$Jo     R9 hy]K$UwQ      4X.%I4ظo    j@u>$IR>G    r `}~6ty/IT}Q      4\$IQL+>G    q p|=t/IT')|    H5 v+IT'3|    H5 $IR>G    f 4\.%I49
     Ռ$IRFw^>G    q p^$IR^    j@,$IRګ?K    ՇP<|o^$Jc~#|    H5 `2ty/ITY>G    q 07$I(    T# f`㾡{I*u^    j\IU<xw    j~-{IJEgg)    T f@%IYY
     ՄYrײC$IUY
    ` ̈C$IU\v`    jm>;ty/IT7>G    p 0#W$IR}K    j/C$I*g)    T fD3o	K$Usg)    T fD.%I;    @ b~tB$IU|eY
    `n9 !n]K$Ui9
     Հ2tV^$J     R8 !]K$Ui3g)    4 ̐%I9Wg)    4 ̐q$IZ?	     Ҕs 0C8tq/ITg)    4 ̒e8ty/ITѭ_     榛3{I*>G    ) `o>-ty/ITb\>K    ) `|?W$u>Y
     M1 3wB$IU    @b fL]K$UmqY
     M1 3C$IUm:+|    HS*.%I4޷(    4 ̠=ׅ.%I*U˴    @R fυ%I9Wg)    4 ̠%B$IUY
     M) 3w.%I6Y
     M) 3sB$IUv~,    ^Ž$IRՊ>K    ) `Fm{IW??|    HS}e^$j~+|    HS^w\^$j:|    HSB$IU^6|    HS]K$Umt    @B fT_]K$U=T    @2 f.e9.%I>e    tq 0$I!6z    HSŽ$IR|"|    HS\g^$jo>K    ) `>{I|(z    HSŽ$IRF2S    @" fٞ?]Q^$jS<    07= ̸C$IUQ,    7|N^$jK     q 0$IhY
     M 3wC$IUQ,    9B$I+e{ճ)    4% ̸>	K$Yy
     M	 ]K$UmsFѳ    @ (G߾$tq/IT     Ҕp @9Ž$IRFwl     Ҕp @?#{IR     iJ8 Ž$IRN^>O    ) }KB$I9uO|G<     4,z;B$IU_y
    `. ~`ׄ.%I6q],     ~`x	{I>K    ) \IZ6igS     ) pC$I9uy
     s t}E^$)ޙ     R0 $I)    X =ׅ.%I6ڲ1|    H #O]K$Un/y
     r Ž$IRN_>O    @ ?$Iʩ{;)     ?>߇.%Ir_O    @
 G~$IRtj,    9 Fw]$IoR     ) axŽ$IRq^y
     q #H^$)7S     ) 8C$I9(|    HA ]K$4y
     q 7tq/ITѝR     ) etE{Ie_>O      x.%Irjy
     p Х$IRNݓ>O      xo
]K$߰2|    H (U*ˢ]K$Umx    @
 Tl$Ix    @
 4|v^$rŸly
     -3 <kB$I9uy
     -3 <i]K$?)     :G6ti/I     2s cie9.%I6y
    `ny9 q$Iܨ_=>O    e 5н$IRN;4     2r o#ti/IS?     2r =ti/IC)     :"ti/Ih˥    @ZF x|e?.%IVvi~EL    0< []K$>?S     i8 	vL^$)޺)    L g8ti/I`>    @Z& xBc$Iiy
     - <?SE$IZ=    @Z& xR-{I0|    H Oji}^$)g/|    H Ojp^K{I<|    H Ow{C$I9o\<     T_]K$4~    @Z xr+ʢ#tq/ITb\W=+~    [Z XW%Ir    @Zb X5G.%Iry
     -1 ,H$Iix    @Zb Xѿ$Ii|ϵ    @Zb XU,b$IܰW=~*~    [: XC$I9uxM<     lxK{Izg?|    HK ߰2ti/IOS     i	9 `'~^$)і    @ZB X/]K$Tti~EL     n~$Ius/T     sK yY^$)G<     &2Х$IRNKׄS     i8 `"
]K$4y
     - LK{Iζ2ͯ     p dzzYG{I,~    [| ͡K{Iz7|    HK Х$IRNS     i	8 `b!ti/I[S     i	8 `b^^$)@<     &^[^$)/	     "s @%Ŏ]K$=)     Ph١K{I>O    E J
]K$1z    H tOyO^$){)     PI.%Irk
     -" TVt.%Ir9GS     i9 B$I97     "r @e]K$4ڴ>|    H NХ$IRNŎ    @ZD sثB$I{aL     ߥ,.%Ir
    `nq8  +C$I9/y
     - d\Х$IRN[     "q @Y$Iʩؾ%|    H Y:Gr^$)T     i8  O-Q?ti/IS߉     9  ;ׇ.%Ir_y
     - d^Х$IRNÛN     "p @9	]K$4v{<     uХ$IRVEQ}nL    29  [{ճʲ%Ir~濆T     ) o.%Iro)     bxB$I9o\>O    L X?$Iiy
     er ;K{Il~^L    28 `Q\K$չ3    @ ES<xw^$)     R ,ѦB$I9o>=|    H hͅ.%Ir*>O     X4$Iʭf
     U E^Ѕ$IRn>S     [C$I97     RE XTMg.%Iry
     U Eտh.ti/IS    @ {C$I
     U E^Ѕ$IRnݓ>S    
 [C$I9.Y>O    
 Fև.%Ir}y
     U E׿h>ti/IS~ |    H8 `uOx{^$)A/     ҄ k^$Iʭn
     M Kر5ti/I5    @ hХ$IRN/     ҄ $͇.%Ir*i~EL    & %=K{I:bL    & %^[^$)WL    & %S$IipA    @ hХ$IRN-)    4 ,EK{Ie%|    H %=K{I:*|    H %^[^$)>S    r *vl]K$4y
     - hХ$IRN     9 `I/]K$e5hiSg*      XR$Iʭskg*      XR^$Iʭwg*      XrŎK{IW>O    p rf^$)~-|    H %׿C$IYe3    @z Xr'tg/I[gg*    $ \YE^$)9	     ғp o-ti/I)    $ ,7]K$4~`s<     E.%I*sg*     ,Ǿ9tg/I[T     	8 `yB$I9/
    `9 `ٌ9ti/IhY    @z X6ï4    IDAT$Iʩx;    @z X6/U^$)/     p Ѕ$IRnS>S     Sr]K$4tuL    0 \$IitE    @z XVk
]K$Tt,.3    @z XV3?$Iʭs+g*     :G&ta/I[?     cp ZkYS^$)U      ntK{I[
     cp \Х$IRV^|ZL    ~ ]?K$93    @	 XvC_$Iʭſ
     Op _QK{I_?>~    {$ qQ^$)}S     '8  5K{Iqgg*    c nН$IRn~;|    H? !4ta/I[T     8  LwC$I9o>=|    H? aF	]K$T<xw<    ~ 7$Iʭg*    C ={Iܺ'+|    H? 0}[E$Iip3    @! o=ti/I)    C 5Х$IRNEw{WT      ~4ti/I[瓿>S    $ D{IzqL     nϟ. ti/IેT     s {]K$4zu<     0$Ij/ӞO      ;;{I:G)|    :  ZW.%Irog*     RK{I7?S    3 i0šK{I>O    t 0_/ti/I[{n3    0ۺ u.%Ir9XGT    l: `xI^$)%g*    `u 0-	]K$4y
    m] LѦB$I9e%|    f F]K$93    0 05ǿ5ta/I[T    r heYC$I9>2|    f [C$I9.|    f ]K$e5igT    @k&9 `p^$)1>S     9{I},|    Z3 e$Iixg*    E :W.%Ir*+|    Z3 SgC$I
    h Li]K$=g*    5s 0u:"ta/I3    К9 >+ʢХ$IRN;6T    @9k 0F$Iʩ=TT    @k8 `*.;ti/I[WT    @k8 `*uOzg^$)Y;|    Z3 SfЅ$IRnï>S     Ul3ti/I)    5S 07$Ij<*۫>S     ߅%Ir	    p ڹ0$Is>|    Z3 k3r<]K$4
    (g 7.%Ir*'|    Z3 Smx?.%Irk
    h L$IʭT    @k&8 `u>Ѕ$IRn    Lp t[kYS^$)]WT    @9 0Fw^$Ij+ӞO    V9 `l$IR}cL     S?]K$?3    j< L/]K$6s3    j< B]K$T<xW<     0|N^$)/    V9 ]K$[{L     =m{I>S    Fs @-}nYE^$)]T    @ Pm.%Iv˴Sg*    X '%Ir}CL     ?{I_
    h5 js̯.%Ir޸.|    Z r4]K$Tl3~    ʦr @.ti/I[{T    @ P+]K$;3    j$ J?]K$6
    h5 jsثB$I,|    Z z_QK{I2
    ( 3Н$IRn^>S    q @6$IʭGg*    8 I
]K$6
    h5 jfЅ$IRn-3    j RХ$IRn]L     4Ѕ$IRnݓ>S    Fq @-{I_?|    Z ZЅ$IRn-T    @Q PO{=,Х$IRVN
    ( 5;{I:GJL     5fm^$)>S    p @m`^$)7N
    Vc8 ::ta/I[oT    @1 P_EoG^$)/    	 Pk;6.%Ir=|    Z Z\&ta/Ig*     ]K$63    j Z{.%Iʴ3*    U{ bН$IRnc>S    s @o>=ta/I[T    @ P{/]^$)ѭ_   {ow]jWڎNѫNGN[Զx3:͜i[$ bCE.B40^ }#;#rYx%o^  bҹ k/%I*U*    h. 0NxJD^$i~&W    1\ `*t{IAk7    PL4 
ݫ7$I5oNT    @1\ `*7/%IM     B社$Ig*    X. 0VU%I8OU    @L* /}4$IҠu>vb     Scm{IA;p1{S    rѺOR_K$\ߕ    b" (O$Iux/*    H. 0Uo|5$IҠM     Jw$Io*    H. 0U|M{IA-}S    Dr|o$Ig*    8. 0UGD{/%IuKw    PL :ݐ^$i:W    b ^s^{IAvm     SuS_K$\	OMU    @1Q\ `4$IIU    @1Q\ `^H}a/I4hU    @L J};R_K$ZsOT    @1Q\ `*uv^$iЪ7baա
    (& L;,$IR5]     Ry3S_K$QW*    . 0oK}a/I4h7o*    . 0z7]^$iЪ    bb j_~\{I:*Ow
    (& L$I/MU    @1\ `j/%Isw    PL j7$INT    @1\ `uݘ^$i~'>#}W    sֺ앩%I?HU    @1\ `5znzI:|]    c ܲB{IAۑ    w. 0z\^$iX8I
    (ƚ L$I
    (ƚ Lօ/I}Y/ITGs     S<Y/%Iw{w    P5 	w$Iqo,:4}W    r{Y{I:j]    c fB^$[[     3y1/%Iw*    [. 05GFT$IV}+
    (Ɩ ̌7$Ig*    K. 03ם^$ZE     3u+S_K$Q窳w    P% ^$_L     cnYDL}a/I4pUV    @ )[H}_/ITG+w    P )+NO}Y/ITG>}W    qҺ%/%Ie*    ;. 0SӞ^$X8
    (Ɗ ̜SK$QͿ    b ,e$IR/?.}W    Xqse$IҤw    P 9I}Y/ITGUX[    bl )W?-ꧾ$IKV    @16\ `&)e$IR
    (Ɔ ̤u秾$IM*    . 0Z2e$IRU{baա
    (Ƃ ̤YM}Y/ITW3    b, l[^H}Y/ITG]    b ۙ^$7\    b, \qZzI:#}W    Xpպ%/%Iꪱӷ    PsU$Iuպoӷ    PsV{zI:~[    t. 0z{/K}Y/ITGoMU    @ fZR_K$Uyڏo+    H 3/%Iꪵe
    (R L+WQS_K$Qҷ    Pr׿ԗ$IuԿs
    (R ^w~zI*H    4. 0Z2E$IR].O
    (Ҹ k$Iuչm    i\ eԗ$Iu
    ,. kۙ^$*`    . k\qZzIj^m    )\ Ѻ%/%I7o+    H g$Imצo+    &wEG, \ o=e$IR-{>   ʵGEGg׺m.Z:p	 b . 7^^$om   ashoޭQw?{~#b . 7/?nD%I[g
   +Oxj47,ݽ)<Jͷ  !~$I}[?    ã_WEFUJwq1 G|(J$En    [8:EoΈNJ<ߓb . X%I457~   `ܼ"磷wkT]#yN1 [t8S$iuvMV    |g	O޶27EwJ-@\ oѺi$IRm   [GGk˱_߿횈~/ƥ11 [4zn*IT[^k    f*ΎogD\Q Vs"$IR]
   `F1iu>zBG  f$IԹm   0NxJ47,ݽ)DTULz% |/%I?C.{[   LeXt]e^;Εg& |օ/N=X%IjߋMW    \{T478U_<SƬԽq My3SVI:k   *9{F?fߑb . #=p$I'ސ    	O޶27E~}3VuoO \ G{Y*ITWwo+   ;,돎֖ck]赳_Ռ}Ͼ/1 /?.p$IIߗ    \{T478U_<Sfz_HK  񅩇$IR5
   .#~_[Z؟ejq Aſ-'I4uv    dhho[ݛODUenw\ (oL=`%Iǧӷ   w4wX4-Fg׺meZwݜ (nL=`%Ij<   *+}W7~2U_%@\ GѺ$IR
   ]Es_Q=%zV( <YM=`%Is
   Gݛ7jZ! <eCV$|NW   ;,돎֖ck]趲_h:A  a!%I4UU'P   &[hn^ۻ5ƽo=Tsl3%s CRXI:k]}   LrӢa#FPySQ, Z8$IUg+   `LhۣQPWyz$ xL=`%IM
   ώ֖ckmfИT}R, TߖzJ$YG   0ZڣyEGo֨dWf) z7]zJ$Y?OW   𔫏RMX)?b\ }q$IRu>7}_   59I8WE#*&g& _zJ$Yϧ+   `iӟ-Fg׺mfjvYu%s WDO=h%I<7   ʵGEshoޭQwgRЌןJOd. cA+ITgwu   G{ս_~}qϦX2 q^1$IoOW   0Ecы_߽㛈5V5|b\ ǡu+RZI:Z,:$}c  |Gg׺id1Œ  C_J=h%I4X   0ܼ"磷wkTٯ '\^X2 ;,zJ$Y   `'<5G{t)3Œ  SoߎV$z7]   `b-[6֖cʿ5U?4J9b\ ǩsi$IRUͯ/~Q  q*ΎogDQ^Y{b\ ǩuS[Ik   5OD{|n+#ZͿb\ ǩ<$IRݵ?/   F<ܰ<VFwߓ\o߫K <$Iu   ܲh?:Z[ήuѿ횈~/4570/T. лW$ֺXxwo,   Chn^'GoΈN[ȚoK <&W$ir  ITyz4?&磷wkTwfĖO=Nd. ;$IRu>~R  tSayM߿'?RKSہoH}O, $IRrU  GGk˱ٵW??r v    IDATS]IZ<{7   \{6^*/\)?)K3_~6P, uݘzJ$]   ~#~_[Z؟X#Ժ%Œ  OPW$Iu  ?<g?/VFwQU%=Z4! xgR+ITw~Q  `GGk˱ٵ.zvFw%-%K <QsER^I+O  D(+}>z_;sij~P, };R^Is  GRFpgGXICN?{( XSS^I^1}c  lhho[ݛODUed4Z[^K ,AzJ$][7   #4wX4|N_{ѿ}wDT" ,AGR^IaxO,   \{T478U{Fո7c1uџYK ,Q$Iu׺  '>#~/^쏜&օ/I?( XKR_Iْ   xuˣ{S쏘&;4l# X)$IyπY   <gGk˱ٵ.zvFt['%MY^~Q, DS_Ia8Ww   k>[jܛQ|K ,OS`IkoY   3\ſx޶27\wdD43b\ rU,ITw>2{c  Lãh]{"~GBIZIb\ tvz K$^#w  4)Ov]/^GO[7ܤX2 ` _z K$;(}g  LrQܼ"磷wkT{?Ig)Œ  (OX$iu|c  #ay\*/ekW%s T=pG!,ITw?   ܲh?zW{"~G8IyK wӻSaIatSf,  o]Z};#j4|ILd. |M!,I4Z"}g  WD{|n;c$82Œ  j$I0ْ   \}nmo[ݛ~$<?X2 `P~7 $Iy_,   1,돎֖c{g䒤qob\ o. $IFs5}g  <ѯo]Z};#:V4q5znyNd. @:WzK$  Xܼ"磷wkT]$i*jx%s jԃX$i2;  Fsho[ݛ~$i(5sb\ 4RbIF  ̘eXtUۮٟ$ifjsb\ ::KI?Z  L|gɋDFG!I~:@d. @Mz770$IFJY  (<=ۻ_1L^P, P_zK$ݟKY  d*Oxj47,ݽ)dđ$="Bd. @M_zK$go-  `^k7Fk7D{g$IK<Yb\ 0h%ITֺ[  /ڣyEtv};#:eGIRM8㳟3K ԨϤȒ$IègK  kD{|nj)!Vyzb\ uސz K$y_,-KZ  hnXm+{S%pGR  5j뿤Ȓ$Iêqҷ  Pe8뗢uˣ{yԏ9ٮba!(b\ 5z&K$G^  +~.5$IV PUDո7\$IF~*k  [ȃ_Do֨g$M@+F1 f `$IJU?`  8y޶27Eůp$V{s PGO=%IU뒿LZ  0[Q-Fg׺kg\$MIս_p j{$IҰ^  \{T47_߼/$i1G1 f嚧/~E$IҴUwªC  LrӢay?ײ?Hfmצ?) Aν$IҰj  Sahho[ݛODUeO~IҌ׻Hb. tݘz8K$  gh?:Z[ήu۷3ʞ$=?$ AҗΒ$Iê'ӷ  rQܼ"~)/Iw{ӟq _L=%IVIߗ  `\~G٫]%ݳ%J1 `VU$IҰj]{  2~/}ytwo=U=%I \ !}q{-I4Z  0
ώ֖ck]趲$IC{͛ӟq 5$IҰ\ƣ  u*+}>z{Fո'{zK4:WL 0$>,H$Mk  `GDsho[W}_Ξؒ$E?) Iy_$ijk_?  <.GcѺ߿'gOjIƲGOvp SiIaջ  <rltv޾f|$ibj_~\b . uߜzHK$~/  mڣg{|nqOR$ikӟq K=%IY-  fGhnXm+ʿKٓXU|  C8?Ғ$Iì{ [G/~sODϞ$M}wu  ܲBA-I4Uo.  [8:EoΈn3{J4.~i. 0d/<$If~)}o 0yܼ"磷wkTٳV$}/J
q cmA-I4 *W?-'	+I[c~ 0dwQA-I4zv-  x/G{뫢{[MU?{J'Po
b. '}DU֒$ICߋK\  |Gg׺idSI4`Go  #пs$I0k]{ ashoޭQwePI4S~,}wP _y&I4u?}A >	O޶27E)IFTi[b . .{Ea-I4̪ƽ0,}s s귵ůvy$I3XՏUb. 4|Ny-I4f g۷3Ȟ$iL_O*s Faա3N$iZ<%s 嚧Gc}>z{Fpgl$Ic\[\ }$I0yS i'<%G{{"*{&J	~H4Ġ\ ioK=%I]?  fܲh?:Z[ήuʿΞ$iߺ+r F׭I$Msm=}s LrQܼWN=$Iv۬w\ )OxjDzpK$>  &]ſH{Fpg̓$I3Rҷ\ ߾;$Ijv  &́u{uߗ$I׼9}Q Ugܒ$Iî?K\  qf8I\qZ. 0BK*$IvO\  qf8IA( PySnIawg.:4}w L˞q$I~(ߖ. hUߞzxK$-{s LE=$I( XK=%I]磫7 $i]	'IwY. 0bS-I4N\  ɞp$I|"  #8$I(*O{V 'g7Ih+黈b`. n3 $Iv6}w Lɞo$I8w\ [H=%I]o. I̅M$)S~4}Q HyJ.I4:Xx. Iכ$IR'<5}Q HмE$I(jw $&IfIEs 'P.I4׾%}w L]7gO7I4U7E-\ ${>zK$jX;,}w ;{I雈. @u$I_O]  cmnYDUe6I4]D Hzߤ$Isi `'pd$Igߗ(j $i$I( 0g>'{I$EwwE-\ ,Y$I^_^  cw$IRt8=}QԳ/] <.M=%IFQïM]  uʞk$IѾ]DQ  QN=%IFQW. q~g5Ih]]DQ  Q$I#<ߥo/ qך$IR4/xQ. i":e.I4 0:W=$I_OEp ]$i 0{.ɞj$I8wE-\ dzK$^'7}{ 9D$C }Q H|$Iu_o/ qcL$I^ՏwE-\ d嚧/$I^ҷ e4I4U]雈6. 3$I(ON^  cuߓ=$I]D N=%IFUso/ qןʞg$I۷3}Q K2`$IUO  E-=$IwӻwE} W$IҨZ,:4} )D$Cݫ7"ڸ  c$IҨj `?i&I(j gޙzK$Ύӷ 8|_$IRO黈6. hRwIQU 0{.ɞf$I]DQ `L4zn.I4gR ֻٳL$)o]DQ `\U$IҨ|tu HVݷ/{I$E"ڸ  c$I  ժC"Y&IFD]\ 1>zK$O_  Y`$IZ\mDQ `4۩$I(;p1{ di闳$IRD(j }A+I4 uK$IRTKEr L]$I(k  C_$I-HEr Lgɩ$I(k_~\ ԛ$IRt\(j oJIi۵  CsϞb$IuF. 0f5GF{$I(kߧo0 Qus$I_(j ק$IW/ ZuHD=$Iu_o#N. \yfa/I4_2} RG'$Ib͍(j օ/I=%IFZUEyڳ7 46Z$IZgҷE\ 1Té$IҨko0 Qi]K$irۈV. _$in"} Jï͞_$IQOEs Tڷ$I#/, 0
k^_$Iѿ]DQ; `L?$IO`  ۷#{zI$EwE\ 1UC_$i 0
%Iߞ(j _I=%IFc N 0L^]$Iuv(j g.L=%IF]}#} SdO.IVo#ڹ  cK=%IF]+Wo0 aj믳'$IbwY6 0g>'$IʨLa  rv%IơL(j UDUޝzK$% Iwg-IӞ(j ޭ$IҨq} 7e-I㟔(j ^zK$eX; vs"z%ImD 0J@$)G^  X3K$iӷP  nnYTR$Iw @͚og$IbnKFٜ. }éIg P'?Q$Kkޜ(  sI:;֦0 :uߜ=$I|mD1. hIIb  u%IX5}Q 0	RD $Iʨ @赳$Ib͍/G0  >$I2|r} C㍿=$I<b(\ 	> $IʨzX;,} u_eO+I{N( ͷV@$)+_I LSg$Ib}ҷи  'EtIWob  }ٳJ$iޗ?(  dIYjܻx2{ Y%IXo#q &H#ǧ>$Ij]'[ `@$Iz}D14. iS$IYnzw Xd)IkmyY>t &O6S
$I)Q{ `	5%I`~#}Q 0az_xCA$)Wo1 ޔ=$I<bh\ 		IJb  Kѿso$I:Xs#q &LsS$I5t x"5GFT%IXϧ#r &;J}8H$e{ 	hL$Iz.OGݟ. ۙp$Iʪ˱= x/?.{BI$=Xb\ 	ؚԇ$IRf ջI$\NGC LWA$)Ic  WumI$Z4}Q 0^=vB$)qo,M Xt$IzHs_( P[>$Iʬu1 f$Iʓ8}#Q 0:;1!Iف  Ύg$IӈUo$r &T󭿛$IJ׎Od  d&IyS>: `R{_|K$jd  fաQ=$Io$b\ 	ֿuWB$)Lc  _̞K$Isb\ 	ؚ$IRvGo2 G~gO%I7й  y1
I:;OMd  {SI$!5b\ Iv#ԇ$IRfX?< |۳$ICjsb\ 	GS$Iٹ ƺɞH$Iߍ㟔( psIz{o2 oպI$!\F	 `57,O}`H$FGw ҽ~sB$IzHߓ(F tsˢjݟА$Iʮe  T}y$I:W(F Ͼ/!I]ªCw @yڏgO#IպowH  SW>4$Iơ=} ,{I$=y(F А$Iם  ל=$IVy$p Cjܛ$IJ#<rj    IDAT 0|>{I$=y_F `Jn|WC$ijow 0"{I$=WLI# L{!!I4oݕ 9$I7$q Dcϧ><$Iƥӷ 0z{/˞B$I}q;bd\ iꐨ#"I4uv 3xTodO!Izo%bT\ )IqZ3R6 fK̞A$IX_HJۥ. h]IquKӷ 0[:}$IzxU?rV `4S!$IRoߎm ̖eO IUD1R. rD$i\v 'PDUeIҷH  S{$IҸԹm ֖̆eOIGMJ# L֖cS$$IRպ?G3 `u?#I.{eV) `ʔhD$ij] rj#I5{% `
9a"I4.oߝ kٓG$Q+(F BJ}H$Ss yJܑ$IzD1R. j^$I8սvc> WgIG.䆍S$@eH20I&$+$fH@WͶ,a^p6*K{Žwɖ>u{׽ullIJgs>e%9]IY4۾<*  o|Wh$ijM `/59 ދC
 @NL$_3E9  ;Z iH럽MP |$I^s  VsߗԚ HCZg u&I|7TU+ j_359 T` h$ih! V/ i+nYp Ho	$IpTu^v Z-Kj @z'Sp yKw4I[N U%;Z!9 n	.  uSWl{$Ijv>z X1ߙ
4UO:`  {Ww4I[O^i  ֨w&Br  y	0  uS>zKi$ۿ&r  ^OM&Br  yc*t  QIf;埣W 5*6|gR+, Ґ/*
4  uSrr&IYyeѫ >,|gR+, 4~ TUj/{g&IU  UMj @:h  {$IjVE0  k9{Za9 F_  ~^IT> `7 iZa PGSIFW ڏMj @;8  uT+e6$IR_g Vσ&Bs  H8  u9Ow5ITo `;)E @?ϡ {/	$IR `R)|wR+vwu  H6  G5IT  LJ{Nj @:t  ꪸ]M$ճ|kS*
 Ue$|R+4 =ˡs *w{O&IWo7 I)-|wR+<  Pg+$IR U+^S  &epO' H#VM ~w|c&ISOFo(  ;_'s  X:|  .$IOōG'  9Z9 F!:|  j|w6I_u U^C iZiJ<t Yow6I^yk	 "|R9 FB @U)[Y&I U+^K  &mp;Rr  `S:  wWw6IW?^G  ww(j ik/{g R6oM$Ttb: 0%?CU H#ZA Pwݣw&If.oM,W ɫʔo=JZ @:  |Ɖ$Iֿx5 `JʇߡԪM sğ# &6I4{۽2^  Lʃ(j iD(TC @ݕS $Iz?~  LY勞Qj& WyN@ h$I,EZ@ 0e7~RK wƿ$ |O$i `~nKU H#\{
I  M=w7I4͙ )2~RS Qnl |
$I#") @.'|RV9 FU& M$LgE  {w)j i	 Q76'|$IӛH )j ioRU' $Ib  A'e7ߧԪU $KB @S_S $IޙRYD  dN>Vr  )Z:  {g7I4=y? dwߧԪ] $:  |(|$IW{ٻ|-" hݟMNVr  )e6LU{E hq_$Iz5 `woNVr  iG) &Vݟ/$IҺ 4Z}r{Z~!tP 4Mp$i\wt* ^[OߩԪe $Moʔ"tX 4W(۽"|$IS{ h*j ITsQ hۄp$ij?6z  Xo߫Ԫe $=SoC @/ym'I&W{z? | ^[U HzW  MԿx=N$M↟F  뭼J @s;th 4NO]I5wS `/5|R9 :  hp{$IZCcsRq+ + @sС HU:}4|$I/\-  L|7Wj6 R硃 /O$Izn7IE
  ӢZqG~T Hz^-/ WỜ$Iznӿ"  LՇWj: W勞/ /e6$Iۿ:U'W i=+;Z d3s$  L߱Ԫu $`ׇ0 '*9IFwT7 i3F{Z! d~I4  LSw,j I/Xg1 F#;$IZGo  Ӯ{ZnFjd  MV}au$Z7I7D  ӮsRs  i9"t 4]
$Iz˿  LEZj> V  ꩇR+:IF.oKߎ^  ]y%ỖZՖoʔ"t 4]=:IF▓G? _KV#r  iw-  *S{u${c>= fLoՈ HZc7 `_yv$k[j# `K_sՈ HZc=:  Eg$I= fLZV#t dʗ>|$ij_ 0s՘ HZk6 a1NjF| 0?K)9 :~<t !$Iz˿= fVU|V{Z7TW7 aQ>-,~Ǔ$w{wJNh QC׆]j5* &B 0響c~'IRq*4z ̸?߽ I{B P#;$IMi 0+:}:|RQ9 4E/z  Ө|䦔-4|ϓ$iѥ  3,R/ Iũs `،{1zǓ$Q-<= fEyRr  iuOJ : <I7 音]Vr  iK_RU; aS>rc(|ד$u 0:}"|Sq9 4{/	v  èւ=O:oT=P =nnո HRw  C$IkM'FOk YUqvV#s  iJw{O VCץl$Iu{4 |,|S9 4~:  U]w=IT{ϣG4 k{ỘZ)׿`С 0ji$Ih| 0S)q> Hr?:  Y=%[|$E7Gc  DqỘZ7oTe? aVrJ}$=  L	jl $S+
~  î{Ww>I"jQ f|jl $S?:  ޠڻ7|$i6˷{eV= Tc) |/S9 n-5> +"e^I40=~ B?&~/Sjr $sM'A QпxO٨c  \įej5: ֹq: FEI4u*z k7w3 I\d2t Tj/{g'IL}ꮊ  oj| $WŝC QQ>zsʷyi'It/2=f jѲL @z; `9"|$iښI*<'z F?є IU|G ,PhpՏ* @})[YVs  i+Й 0Rw@I֧EOT Z)nYP @z;;C `T+=Pu{_4A _;k{ZC I]ӛ `w?ѻ$ISRt( @wykP @ҴTE` E+%Ilޝ	 P;#7jjM $MK  F%IZ[ץj]c 549 4-w}Gp YE?u:|$iu۾<^=1 js Hʇ  j?ڻ-|$y-,w=* ꫗l6aiւ	 0Ə1m^JL7N-'GH Z+n:!~oS Hڻ/tH SR6oPll4 P{!~wS HGo	  np~;$i= !M0 @Ҵ?wq  BI?oi( hEnj] $Mk~;tX R߆ѫvS 15t9 4U+n  ~ỡ$itꟽ(z 4J瀭w8. ;L  VuL=>JG= =I @ҴáC P=y_w~K(Izg΋w  S=NolN'tp oK1 H˩59 4#}	 s]ů
%IC؜Կ` LU)c $H	 ]m^+JEˢ @})k $L6LSP  -4~_$5yG3 F-^^49 4c.a  7`TtB hwvJÚ I3  GM3zg$5|-Rq9 Gn
 H6HՓR  Vop1 $Ik-5| 0lߩ59 4/5t fkLټFIR=kT>q 04{OχB)  k7h Iz^/NWc
 `hjr66'|Sks  ifwT  $uLJ<z< 59 4[:P G z'3K  CsỞZC I3^{T  &op1)I)I
hކѲQ 01GJ IRȍ +n9%e7!%IWKSqӉ# `h<(|Sk$r  iVꟵ t 05ŝ|[Sѣ `uOY읡 +,_KJf~5U## `-|qH @ҬU>xu| `IwII;)Q 0529 4k )%;)|$MS_W=^  FFJ IVoTUC uSz O;$iw|W  0K~ʷ{E @ҬV{I `UwJIҺѧR^=N  FJqi{Z# IZoZ  Ӡ:Gi^)IB6LI* }Pir  iV˗  MW^/*=9  FSU|wBF* fB-  ӣւR:|2U# `dw_5r9 4NЁ \q`ocJռR)UU  iӾ*Z $zI]  OqoE)Ij.oKG  *;%|?Tkr  )$? 0\ʇONo
3%iT	  ;ދCF2 B Wz ]SF|񖩸1  NVH @RHvH_  ;O;?T)IRO 㯇jd $	  C,R4ۼ,.ge  ꥸ}Q Iau \sDnwJҰ9{ 3jts  )*,t 0Lo=%i ʔ/}}: yժS{=%u~) h⎳wGv "A ,tSoԴ%M- $uOJѮ @RhcsRa )niʷ"~76'u hH%5u Hy *1w{w*IuRyEѿ 3wI @Rtf@ `URχTm^Rя5 :owJ @R*8t( cp)$QKDZ `]:N9 Tz'}-t. ZygT"jTu~b  =z2 Rx˔^p  POKټwSI_RYD `tL)e $թB3  ;INoM%iZiSy"W.  ӤjHق\ j @wwS6A*IY?JՊۣ 0kJ/s  >-4UC (n==;1~OGSyѿV !99 T: d唍	U%iw{w\wtJU R?e6=9 T:,tP PO7UIL㿯WRUF `1|g @Rwk  jMVIzKKLG ``*e?ga @]|8|o|פyK&  FR+9 Tڻ#t`  Um_JOoGV  @IWr  ]: hx͔0|4:K;= YE?ۿ:|7_Z7B'    IDAT6  RE=Vpip~)ѿ  VT^  j  LZUՇ|7ﳒ'?fG  `\?Sr  7: h^g-Hﴒ]Oѿ  ꩇR6}U^  j[Op  LįlFử5=Sѿ  ;6oT?t |壷QK؜WRwwSѿ  _l59 T-	  S瀭w\Ij4D .al9 Tڻ=
  Ru%QKm )4w9 T_ VuOF|}?  |Z)[C $վO.t 0܊[OO?Jm:?T*n:1 @=*~9 ߢS]: ~W_H;.ן~;  0$:A+ekF4С (C؂MSϥ)UU  H}.Jsל IGB;  ZyW)e546'uipپ> !?wq+]{ $5C;  iڻ;|'+Μo5 h/{g,e4ݍ  *'>VsM8z?F|So#  0B/߅l9 Ԙ%My  7T)۽2|OF߂1wRYD 0}1|/I @R*n:!t sipѩs'|*4_~!7 Xvʷ}y,eF9OB<  SNVo7KM,ox?  2GỲM! ռRԃ  ֨,Rqw/g_CK5ۻSS^  xߛl
9 Ը: `^χh8ux_kV#
  kT>r{SjZ $5w|  XcHߩ,S/↟*G  &mkޢi)b $5B>  jZm{v9?_ hA7勷߯SF=s  #%g/J~GKI7▓S{*
  Cwmis  ^E%  N=WG}nb޻Օ/ye{t  `uh-e ImpŁ  fT/Kōǥq߿5;Fo&V>~kO  ̨wp)[ Hjl}>   lV>nOv}\#/<wF Y;;c $5+C   QRq9χS6\m&:l=TF 8vʷ{E.e I{?  P<zgO?/UoOc:/+^RYD \uH.] Hj;U   NO=;MoмS{w12U违  Pk_?Ks= V  5z07z?K ۽2|4ũIݟ]_{*0^  ^~9 {?t!  VݟۖE_xƣw|?>7N  ;4wr  i(xw  y*$./NNLcL|mCO!/)7GoND TWL|V IC  T'@?C9?}E&hZ/4I_KwLō=nA7m  9vwMC $G6MUXr   #:/HKsK:Ijs$0o/}}jRGJݟMoipSq&WU  V=!] H?  m#R=REwʷ&G'>R+&c&N#t;A{Kꟽğp̧᩸gG  X/N!eӔ ICG  2e1}Փj	?M^m-'?sz*4U  l9MS $U?]     Vޕy?ߐi{gC     9z7نMc $W6JժC     /~Ui @?{}     e?Ӑi+S*Х     !eӜ ICYqIK     P_mßeH @r     xΡ,Cf  R     ['#?ːN $m]      0lr  ih˗6D      QuW|?Ðnp     Pvv!e3 IC]{.     @MTejgR69 4^O      7$p $}c>P      ^3) Ho']*     8}?| $D3.     @V!e I#QStB     `U+LټUH, @4     }Bf) F]0     UW|KQH, @HUu~     ̞ۇ?Y{B     `k&ls  iQ't      fCKHsg7 Fp      3R{?Y+)н     9M'? Hx      3GEHY@ $d3?     p):/9 @V~f     L ,( F      ӫ|ڔ	!eA9 4m."     ܸ Hz~;t     G=)q).e>      wß;HYp $|w]H     Selß9HYp $|oI.&     9 4     X7U牔oE)A $in+@JU      S?kAs)I $      SRxgRV H/;
     05?_ @UU
     0INʗ.ق( ~!tW     &Ѳ
RV Hҳq;ta     ֢|7?W+ +Nv     }ß'HYs  IڢS?      kxo ͭ_ $ꟻ8tw     ^}#HYMs  I/Pd     /5 @VBw     @j IZM]ߑRU.2     ӛßHYs  Ik]     xZHYs  IkGB     `== /i     `/3y5  :&t    67?/ @|     FUHs ID     HSHYCr  IiZu     g @&Yo.9     0JS)A9 ɶũ]v     `TΜl@۬ He     FA?m^\@ IJ6OUh     îw& m^ $iΜ     0V=09 )oE:+C     V,@ IZgo     0Vޙ? @֡|R]     9 uK     R6AR H:/*~    9 Ѯ     S_!$Gץ4.E     hU{~05) Hz6{     4_뗲!$goL.G     HѯKِ @G     Ds/eC Iڻ5r$    @T)vlr  ICC%     hھY $ij/{gJU,    @T+Hق/eC I8ta    &_ӗ!$McߗRU.M     Pg}llNkR69 inpѡ     Y/eC Iڻ=r<    @7:q $i\yp     S{_×!$@NoJQ     P'^ʆ< 4C/+t    Sïv/eC IKS     P3燿n/e# IP    @{Shlr  I3XxTu]      RzH $i럽(t    (=llNkR6"9 .vT]     `Uej__$B35t    6lr  IѢSԃ     ̖Tʗ.yih @f]     `2nR69 j&ZqG     3Zq{l4wr  IX/.]     0:&x) Hl6oT>zs     3 @f|    (z;_F I6HW`     0-^: $i#     S|.z Syš     L;uwI- UO.c     0;I؜% HRdŭ.e     ^"@Z9 {?     `]/ZZ39 W    V=m_:39 ސR    TuᯱKj=' T    Tںr  I5h#e     &N]ںr  I5wwB5      @҂MSХ     ֤|$5uIr  I5{_.n     ZU:%V ISc+C7     x!]RZS $f_O    @Tc)_ekZk$հB9     x_\Rk9 )e     9ᯝKj5 T-]      ᯙKjM̏ IQW"t    `Μz֤/me6
Iީ    0~V.5?g~[O-,$IzV7X     `u%=KmI[    0zW֔g~[	I_qy     j?rne;ZH?2t    `4twᯋKjS{g I7Ѕ    W	M\Rk_3?ϭ|ٻ@._UO.~     *;)pIunp!L}>$i	]     ^!upIgLڇ~:$IZC7I7.     3}4^uI\7t	    `Kjw=?$i    0<z'~5uoIi|g;w?$iw}GJE?t!    ;!iRg~[CI&UCB     .o[RkZj7$M|-R=    l}#nIis<gUeJػh;;DTUbJΨu.v:V;]gUU۩S@ 	\\(
å P(7"BQI$!|g8ܒs޿;9ϳ/OSnҟ&{c    5|}4J~-1:~UJM-r     0)rw?<$ikrm"     L$?ۖy; 8Lgn:5D     6,N~-1ʇn~ }K$I{V|R_    `>赢u'?Ӗ}Sj| s_p=}2    0t?V 7If^QnF     `sgْb?{O< ]'I]SMD9H    :ꃒaKjU= l $ivo>-G     j{_%?k;PW&U,?b?    PC{_+} L %Is!~	    @YXg֒}# :W~<$;E1W'^    ϫ%Ÿk?<5 ;O %Is~g%    7?ZRc"uS GAJ^'~    vőK~F-1.Ps˒?PI;bߙ7z     ,e?Zkޔ|ZRLj=I`%IsߞJ     ^4jKOz=@wI$i4`+    H|h.;^ [JFSQuvM%     	Thђy7 reM%I{G&    :ޗZRc-YU DD3AKFӒ3    @^w)t׆ AKFW_>    	Gq􋓟?KjL׏ڳ{?hIh]{8k    0)UߑYR#I[l 0<$io;     LHҟ9KGh ?KF[̷=M    *kR7Kj$s!O{x@?xIq    `hϙ%55t ig&V,/'     YR#Ġ;@D־3$};    w.Ԣ˒\ݺ^< s?	Ixs({    0&գXseIjn?pĳ?I+V4#|
    zZgʒI+V(q A'#IOK>4     A$?KH^u) ;/Hd$IcjjQQ    `/9M~,)RW>th kGs?!Ix*{UT    `TG7GgȒk|]?z 03 _OJ4\އ    0Jn>gǒi >$bp5sy;
    t/ύ%E-Z:F; *>?9I*?0ۜQ     F`hN-J~f,Q:޷ב t7I[3     @(XR6[1@Ӈ	J n6K    A/Z99K~mV /xo')IoE۳     0;/4F IJ_wfuC    `sI4%?ԨMF Zk|$-?pn*     +    IDAT-Q8 SOue %,˪o.     <ߒ<XRV+_kMf eŉIK_ҿ    GKjԮWӵe ѻyM'-I@Sbps     xo>[Q/d Ds勓?yI+yYTs     |;˞WRv~Ԝ1Y}$5?yId\xȜo6     /\NxMs_IUxaT ۊ/I"H&S|    XЪ2g#yF-]H.5 7 NJ"H&SEQ5ɍ    `!^gX^v N4yyC4:{$7    fpϺhN-J~+Qz7: kڑ݀     r(z~]IZ#~= 1Eqk(4|Zd7!    UǢu/&?ەԨm{׏3S  "I\QFs    UUigw3P3ő$M5+Fq     VG%?˕ԨoՎs 01=8$ILK7    w%LRI^uX?# u.PI4Z     dq_O~+Qۊ^m{ PvDLTK>4    kE7$?Ԩu{ehd$$IljQ6^:[	    ?us!ct eߒE$Mb勢Ho'     Mo	k%5j]Q  "Kœ$M߉QR     }WGs3JjԺ_hWLI&[oÉ㸥     Z}SK~F+޵&e ~JQ4V߿m,    :ZDk/?T늕? `z{LIZPNxmTuk    A/gFsYI5ojQ6]6K C+KJ&ZCyk    L~+u?6u 0 ּ)*Ilo}n    zNH~+N}CĠ  "ʝ[yU,{n7    0qr4,N~+-{N7N5Pӿ:W'j    ợ8_%տ&NMd 0Ծ_dId?tR    :5]%տ&ٵjbXJbK&^1Ij     ƣߎoN*?"~M<g蒤U|QT    `t*:>ZaO_q+jnKzɚ `1}آ/$ir?     f#JOݜ5PʏH&Z+    0k._lxEs ,u;!$IkjQsq    *eI*=:ꢑ%bH&WQz0խ    `TbKJul 0T?+_"I\5.bKy    xrV>g_wDNő$MCS~     DsURkfMPe1=8I4R~     ~JҿL~*Vj1 tZ/$ir+ͩo?     3z_;2:Q=56USɿ`5;Z菉     \3g>4zWvuVPgǒ$Is񟧾     `\g]qˢq_] CK"P4}6    XʇnbsJwŪD}c DUE$BJ&D>    R^G8ZW(7z 2_ɿT`T>    P5EğO~.*޵Nz]Tru+ILQ>    @zh硒]7̌z *:4X4z_[    j˧~sPI}[j?Q ?ѽfe/$iMM     ^@%պι0I!ռ u?1kE$bQ| m    GS}Jwݯ'gj 0Ի^w/$iN^    d맣9(tD `\     O6<#yzV,/]Q`oIx]wl[    0OŲ&?TZx}7FN `ln֚7'Ɛ$%cݯ     L}S+6Z9NGn `FgoI*ՎRq    yztsǾ"٦tݰ:r5 ?ѿeML/;7$i,NŨ:Rn    ۢu뒟iJ_1/#g [n1*7$i<u}wDU     5UvD䃓eJ_U]Vh}?'$ח     u+}[aJYG_ ` `F9US1=Wo(Ih+>    ~'ڟ痒jU_rXH D<ɿ$I8g|Է    ~疒jԒѽ^,4Y c^dVRf    *:_畒S䃣|X ]Fsɿ$I}ƯGo1    @":9tľѽz9 *w}?ڟWo>IԷ     |RR=jvޟTj w檗%F$ކSZ    	]*Ǿ"wT+r 0[DCczjߘ9dq6^    L@39(tXTԗYl1NM*ISQϏr=o+    }N4rp+:c[S_jk fen9#+_V4Z'&G*    sI4RRgF[RT{ B~,:oL/}Vo`Ij?Fo)    :QRsפ Oq}OLZ?    `Q,{nsGI}[c𽯦; Oah}!$z_[6    `(|^FI}bpU/?n|>݆ 4ZN}    frCGLFIo9=Q>xcKϼg [ng!$͗V6    CoiT,/?ծR_va 0/IL/}f
ISW8 C[    \gWo-kNd `釣sՒh.? $+?0éo    ()J}Q/Ed `En:-N#IzgzD    <g0Y>ѿ㼈~'efA0 F:MjW?Է
    3`/eҒ>-ѻaOM `
pY:1LOuw    _(~3%?;4x3j= L@pbּ@jPR    =$?3>;Uw:償0 r^w| %cpϺԷ    X|4*ut.xoo9=G$ *E<J҂}buo     ?ܒgDo~VT;O}`7 E9{?SKN-I7\I}    K8>]hvOsĠR, U5\?cq걭    yH}hsGѿ(|#ԗF `lFCuۣy_0$)ZrT]/    \?g~SlZ9=?nf>{ɇcѽm81MEQ>r_ 湲sz7?Ͽ+S'5IO>~'e     `                         Ȁ        d         2`         0                @                         Ȁ        d         2`         0                @                         Ȁ        d         2`         0                @                         Ȁ        d         2`         0                @                         Ȁ        d         2`         0                @                         Ȁ        d         2`         0                @                         Ȁ        d         2`         0                @                         Ȁ        d         2`         0                @                         Ȁ        d         2`         0                @                         Ȁ        d         2`         0                @                         Ȁ        d         2`         0                @                         Ȁ        d         2`         0                @                         Ȁ        d         2`         0                @                         Ȁ        d         2`         0                @                         Ȁ        d         2`         0                @                         Ȁ        d         2`         0                @                         Ȁ        d         2`         0                @                         Ȁ        d         2`         0                @                         Ȁ        d         2`         0                @                         Ȁ        d         2`         0                @                         Ȁ        d         2`         0                @                         Ȁ        d         2`         0                @                         Ȁ        d         2`         0                @                         Ȁ        d         2`         0                @                         Ȁ        d         2`         0                @                         Ȁ        d         2`         0                @                         Ȁ        d         2`         0                @                         Ȁ        d         2`         0                @                         Ȁ        d         2`         0                @                         Ȁ        d         2`         0                @                         Ȁ        d         2`         0                @                         Ȁ        d         2`         0                @                         Ȁ        d         2`         0                @                         Ȁ        d         2`         0                @                         Ȁ        d         2`         0                @                         Ȁ        d         2`         0                @                         Ȁ        d         2`   ڵ  AU:ހ     	                 @                                  @                                  @                                  @                                  @                                  @                                  @                                  @                                  @                                  @                                  @                                  @                                  @                                  @                                  @                                  @                                  @   \e  ~IDAT                               @                                  @                                  @                                  @                                  @                                  @                                  @                                  @                                  @                                  @                                  @                                  @                                  @                                  @                                  @                                  @                                  @                                  @                                  @                                  @                                  @                                  @                                  @                                  @                                  @                                  @                                  @                                  ;U    IENDB`PNG

   IHDR         F   	pHYs    {Rk  IDATxi[@5eĄĔ@UMԄ+$U-gaA`aA=(þ[0^=M߯קn{I  ,H$I!B
$	H)$R IY0k6#
G0Uvf9%q4we5$ b2`}5l$ML蓟W@PfH6%2W\ Z`7sA}o5n%]fђpV"V)]Vమ>Z c$V*TryPAW;~9@T{A1|cE-eT"	PoM kXP]oXp$k'&6+mD- jx?GNm/xg +}Wv	ee~YS6@E9{N$	4'=K(๠:1
oVѩ5@0<wIG Zapmps#pv_¯ 7
*镝!xZ=ۧ1{Xqˌz/w!/J,ڀ/Ȯٳ .YjZ7_U3P@j
$C%̤iCڃ{7>:@ƜW )xχ~5Fik7a<oC!	׃iS}g8U|W@/ξj~uCߖΑVcگHݯ@ƔuUUv!5v\ܺV*w V|s'_3O3Fa3p.vϟX>j7Wӻ2O>v}Z֍c[ ۧG9/:B6upk`0^9GO@ze'>ɚshE90QO+i%7G*o@R;[޹c`7g }do `I$kI4	P{#wVoRrHX{Pr,(~WxY#@mv	d)>T7@*jQ^?RxY#@8(ڡRmU3@xY#[[XmGv=
Tr	d)xE'<"GD:R-ց*Be/@DWqt5P>N"KqH>Pct@6a'DId)E_4^Id)z?TsU@j2j'4Mm.lFz,(G2W@RW9"kY+z D'4/05w@K]E'0|D2ц~Ux2Y
"-Iv+dFN'6UsdFN`ŀdFNs[O(KY$V8PF5	e)ܚ&hĘEz(PȽq@9OL/iH,Q^l	%\pQKM̅Tȯ.i>8DtRY"/U褲E^d>`щe)є1ĲD^4O"+{U'$T+q,P
O.KA->@}RyD䲤EQsІm;q9
̥D}{bR@;!v.\Gke¥U:. 1"wl·}ZT( 	dz	(O~Nc"5_\:['[/@\,`m 0_6#WyՓpA<U?/	ΡDCkUK2эr\WY˻eYOp\Iyk<RٿX"WHYgJo.~@2KR}yBDK2>#$uo(1n.
AX:P#PǘpQu2ȮM0pO8W
]/wu;"6'vP&UѲ+B PŮ@C}oUo'.^BAaǝ¥aM=YT'(>0suee¥a	x}[-TEo u<_-E;5Dya]Jpu(co@n~Hنd?^Ԅd$੧APtzۍ?#^*^~ФegBRpOnW=Lz\ȢW)CKE"OQs0!0?"V <ca	/
JlTuW$g$Q_/޹NxUK"?ȘkshKC8?Jۀ^+;17Uw $K"2jy߄°7T!I.CH36$8u#Rx&Wg[Jhc\ ~ڻPt$ñr8"6;Y(V'쮑
$MΗ3kb,~+l+>ZnDq[Ι1S:PĊ[{j}FMYuWuAjO"7s#ciPMI.}(ևӘZjWo$x⑨8>Tbz`79~LR,}ص$f[Y[wκlۗ~$;"#ɄX-טsW	ZeFwa$.(G흆W{,5X@$k
$E
$	H)$R I @@H$I!B
$ 8dgd    IENDB`PNG

   IHDR   2   2   ?   	pHYs    {Rk  
IDATx}hVUoRA%¬H-JA)e(	gnTr,7f@^tK02)/根{^˹8=>ov}}{{ε![>\B;Yc:N{Y7wս{{.}C*sEwa]<vJ
rrBʼxxkQ"T?`_))ewg[&ZvɈdX77f!	(Udd}:Lǈ w@\9ꉼx}13<C@k$sc6' lKx096؎YYMɾ~xZ{
Dt`;oa{j2Օda BGiAHχ_`^(vt tsZ q^I.M7sQSBv^@lx0z ava&Aa;@xfZ ΁f-6@옅D恈xF0+4;Z7oz,99f-@CKF ._>dHzv]fG6-U0+
`ݓ~~|<N쀸֩I7>DgdX2g,REqtsfYi<۪*e7v*
9Dޓi[>HU)D6d^Y.4 R)VzdK;B:-YW:BWw3yh=~3<<K2Uiwo=+^]EVMYs8:$l 쫗`m뺬 ~=
$ahBԾc$<d?E6LHy<z myꁩzjߋe+5"*f_ґpKy"Z3-N֍gvC<Uo
!c <čsЪɽr"INs!osA    IENDB`<?xml version="1.0" encoding="utf-8"?>
<browserconfig>
  <msapplication>
    <tile>
      <square70x70logo src="mstile-70x70.png"/>
      <square150x150logo src="mstile-150x150.png"/>
      <wide310x150logo src="mstile-310x150.png"/>
      <square310x310logo src="mstile-310x310.png"/>
      <TileColor>#ffffff</TileColor>
    </tile>
  </msapplication>
</browserconfig>PNG

   IHDR   0   0   W   	pHYs    {Rk  IDATx[lQGĽB4'$n *֖F.*QUZBF;q)[3sv/gmjGAPb|8R䴔qS`HA?E[xU1{-"5+)^zydpbjJ.ĬaZ7%hOeHcT!zn%]:;`K_!/nh2 y{> H4  5\Of~{&Jr(E}lRc+hUoſ(bw%9g3 7?AN^12ꢎGϡ+z~-ȁ7pHۆZ rlVT7	0iXIJHH[8+my(%PN.={Q~MP@@@hxl7 ;<qз5 yX9n$e"IU j hW~ (EI g  0M x@d,s3¹0]ЮV@lK ӹ@uH[^֕R-_ tCYbް+}]Nyg\v ,hcn !WLǵXyL9`$/ }[=c=R8n`c$Z")KL^/* ȱsdxsn8Ӻ~nֹ0/V+0q5rb3 ipRfA[wl[x(glxn\yc`mI:
g1uuA5K Jom2k9aeć|B=UImM@! %D+ys&9"3)ZxRN ?n:1;CZMD*ng##ޔ&Jٚ< b|ߡu'    IENDB`PNG

   IHDR           szz   	pHYs    {Rk  IDATx]HQ"z"1{H(衇
xz6wYME"sl[2/!]2(J$Ŋҵ̝{⎥c3w|ef9{W{;%Pe\1S(fǶ48/KGZofZJg-z"CC:;N @  D3ԍJG	H[P}BT! Ɨ>n +PRz$G-E%v P?OQe4[WP}GҴ! Ҹ-us'He'> H@8>X1]'	HG޻P{= c Z"]vw ʽ\ uw qӿ7Z+rh|Q/D\4@di}
\:p.;P}\M?խh/nRوv?@J;|c/@kv *MwekP탡\zٱ@0t_AZ69{gW'&v I} K>ߖ ~Q3D7<^IlDQpbF*d<9XS_H^|]mUEF16UȦAZP?WәOlB    IENDB`PNG

   IHDR         F   	pHYs    {Rk  IDATxwibh1p4&@$DHǒĔWw,R-"%,eiW!]|73}7wgw'I@ @ @
:szW
;_`m)Aʑ) #o(Պز{Glm/? );K}Lq@l8]ڂ&_WPxo_Ƕ@-{2\2%Pz &H-j_dl@Wa(u]"mnWɣWܗe5YW 0AzWe7}MS)E]}s~_-z`BHZWcū}Z\X7$Q(h|I-vp*Z-T5#%׆?,;
\:[CH[\}_&pN2f͌ZFI)t>D)` :'!	oSz \I`7X;. QO[ e#;eL+uw	0wN):G.c2+j]S#-17FG -p```_QY厰zn4R((u` mA2<֡enWd-PF}@fLJ(Lc!V16+<n\|gҔq>[QQ/>;@!*8OkV`n
QC[?k!
ا<Cp\җ!
}x6#{wrwtC߆ɍ`lZ3 ݳ@ڬuQUqjص{KTY	XMgI@'	WFVXǪ=KgYe,zygo eY?Ly||ϱ j;漏/er_Qd:O``ƦN^F@jc@ɮFS/@|	IےoT }_*xioU
;57p4BȬTZIdOIyh{@8B@ ,I $)y"'<(i@H(\YcGBpR*7'<މbl=,X.@c(	d1H$.aR.a*bPx'<4~
.p@H<4N"0bJ9Xۻ0Spr. `$rS*wY[E޹@}ܓbܶ	;!N"qx+Tebޖv8E(I\ y@ybޖ6ge
ő)IQv/PE_wd1sT}udb7[ !]y'0<D2Q?=,}͜[;;,.@|;,@@LHJ }t3	e1R&>
Q?=,f\VhrO(Y$ݭroc	e1=(ub}HHZeqfhDH
ZRn:/EjMw	/$b)	mx'(RQN,I$/'$R8@f^".8X	TOWsO,I,Fb \HY u@;DQoil=,jqݶ8Uc `>	ɤ?ch(ȣ 8pkȃn~+6>
p><K7~(~kn/;XUZZ,`m'33?_g&ځP'LC~h?wk?4Ɔ
GVepo,idї.-b8W`?8c<>R:Q"?+<6F_kl]XnlU*X0	eO$31jyBxK	u }}Hk @pwQu'OT(:adN4x!} P:(z#<2iǽY-&U̚	O:ԡg^_OP|;wia@9:FU>wiX@W:z-yw
5D^W.%
x9:~1w/]w@) C~7ٗ5.GCp󠌺?|yBz?QWYx/lNhRb`e`rAQ<@zdȂȭRQ©?n<MA_kD _9,wr.Fb;E	L86x\<^ܙڟgJOբ4 6:US?Z<.Pm`n/DCI"0n)߄7H$=P%Y=1\2#-_bCЀu`qj*A
D}+<OQWjKm̽sR>BΑzXFR\R"J7<	$v@O@o4rڒJjYa`c\ԙ=>칒VLI}es&sT,[HƜ>]4 V&ZR@GBqՅ!7_s#c(U_Υ\y\*z&QآG V+G +Ѵ'V"QVXGe0ڽ?&6-rywÐHff2?omXWP!5V6DkS!=ư/"5Q=KPgl%vNŒ6^G)ꪪs06@ @ @A嫟(]=    IENDB`<?php

declare (strict_types=1);
/*
 * This file is part of Contao Manager.
 *
 * (c) Contao Association
 *
 * @license LGPL-3.0-or-later
 */
namespace _ContaoManager\Contao\ManagerApi\HttpKernel;

use _ContaoManager\Contao\ManagerApi\Exception\ApiProblemException;
use _ContaoManager\Contao\ManagerApi\Exception\ProcessOutputException;
use _ContaoManager\Crell\ApiProblem\ApiProblem;
use _ContaoManager\Crell\ApiProblem\JsonException;
use _ContaoManager\Symfony\Component\HttpFoundation\Response;
use _ContaoManager\Symfony\Component\HttpKernel\Exception\HttpExceptionInterface;
use _ContaoManager\Symfony\Component\Process\Exception\ProcessFailedException;
class ApiProblemResponse extends Response
{
    public function __construct(ApiProblem $problem, array $headers = [])
    {
        if (0 === $problem->getStatus()) {
            $problem->setStatus(500);
        }
        if ('' === $problem->getTitle()) {
            $code = $problem->getStatus();
            $problem->setTitle(Response::$statusTexts[$code] ?? 'unknown status');
        }
        try {
            $content = $problem->asJson();
        } catch (JsonException $exception) {
            $problem = new ApiProblem($exception->getMessage());
            $content = $problem->asJson();
        }
        parent::__construct($content, $problem->getStatus(), array_merge($headers, ['Content-Type' => 'application/problem+json']));
    }
    /**
     * Creates a ApiProblemResponse from exception.
     */
    public static function createFromException(\Throwable $exception, bool $debug = \false): self
    {
        $headers = [];
        if ($exception instanceof ApiProblemException) {
            $problem = $exception->getApiProblem();
        } else {
            $problem = new ApiProblem($exception->getMessage());
            if ($exception instanceof HttpExceptionInterface) {
                $problem->setStatus($exception->getStatusCode());
            }
            if ($exception instanceof ProcessOutputException || $exception instanceof ProcessFailedException) {
                $problem->setStatus(Response::HTTP_BAD_GATEWAY);
                $problem->setDetail($exception->getProcess()->getErrorOutput() ?: $exception->getProcess()->getOutput());
            }
            if ($debug) {
                $problem['debug'] = $exception->getTraceAsString();
            }
        }
        if ($exception instanceof HttpExceptionInterface) {
            $headers = $exception->getHeaders();
        }
        return new self($problem, $headers);
    }
}
<?php

namespace _ContaoManager;

/*
 * This file is part of Contao Manager.
 *
 * Copyright (c) 2016-2017 Contao Association
 *
 * @license LGPL-3.0+
 */
\setlocale(\LC_ALL, 'C');
require __DIR__ . '/../vendor/autoload.php';
use Composer\Console\Application as ComposerApplication;
use Composer\Util\Platform;
use Composer\XdebugHandler\XdebugHandler;
use _ContaoManager\Contao\ManagerApi\ApiApplication;
use _ContaoManager\Contao\ManagerApi\ApiKernel;
use _ContaoManager\Symfony\Component\Console\Input\ArgvInput;
\error_reporting(-1);
\set_time_limit(0);
$xdebug = new XdebugHandler('ContaoManager');
$xdebug->check();
unset($xdebug);
if (\function_exists('ini_set')) {
    @\ini_set('display_errors', 1);
    @\ini_set('zlib.output_compression', 0);
    // Set user defined memory limit
    if ($memoryLimit = \getenv('COMPOSER_MEMORY_LIMIT')) {
        @\ini_set('memory_limit', $memoryLimit);
    } else {
        $memoryInBytes = static function ($value) {
            $unit = \strtolower(\substr($value, -1, 1));
            $value = (int) $value;
            switch ($unit) {
                /** @noinspection PhpMissingBreakStatementInspection */
                case 'g':
                    $value *= 1024;
                // no break (cumulative multiplier)
                /** @noinspection PhpMissingBreakStatementInspection */
                case 'm':
                    $value *= 1024;
                // no break (cumulative multiplier)
                case 'k':
                    $value *= 1024;
            }
            return $value;
        };
        $memoryLimit = \trim(\ini_get('memory_limit'));
        // Increase memory_limit if it is lower than 1.5GB
        if ($memoryLimit != -1 && $memoryInBytes($memoryLimit) < 1024 * 1024 * 1536) {
            @\ini_set('memory_limit', '1536M');
        }
        unset($memoryInBytes);
    }
    unset($memoryLimit);
}
// Workaround PHP bug on Windows where env vars containing Unicode chars are mangled in $_SERVER
// see https://github.com/php/php-src/issues/7896
if (\PHP_VERSION_ID >= 70113 && (\PHP_VERSION_ID < 80016 || \PHP_VERSION_ID >= 80100 && \PHP_VERSION_ID < 80103) && Platform::isWindows()) {
    foreach ($_SERVER as $serverVar => $serverVal) {
        if (($serverVal = \getenv($serverVar)) !== \false) {
            $_SERVER[$serverVar] = $serverVal;
        }
    }
}
Platform::putEnv('COMPOSER_BINARY', \realpath($_SERVER['argv'][0]));
// Always create kernel to initialize the application
$kernel = new ApiKernel('@symfony_env@' === 'prod' ? 'prod' : 'dev');
$input = new ArgvInput();
switch ($input->getFirstArgument()) {
    // This "test" command is only for the dev version, if the Phar is compiled this is done in the stub.php
    case 'test':
        die(\json_encode(['version' => \PHP_VERSION, 'version_id' => \PHP_VERSION_ID, 'sapi' => \PHP_SAPI]));
    case 'composer':
        $application = new ComposerApplication();
        $argv = $_SERVER['argv'];
        \array_shift($argv);
        $input = new ArgvInput($argv);
        break;
    default:
        $application = new ApiApplication($kernel);
}
$application->run($input);
<?php

declare (strict_types=1);
/*
 * This file is part of Contao Manager.
 *
 * (c) Contao Association
 *
 * @license LGPL-3.0-or-later
 */
namespace _ContaoManager\Contao\ManagerApi\Config;

use _ContaoManager\Contao\ManagerApi\ApiKernel;
use _ContaoManager\Symfony\Component\Filesystem\Filesystem;
class UploadsConfig extends AbstractConfig
{
    public function __construct(ApiKernel $kernel, Filesystem $filesystem)
    {
        parent::__construct($kernel->getConfigDir() . \DIRECTORY_SEPARATOR . 'uploads.json', $filesystem, $kernel->getTranslator());
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Contao Manager.
 *
 * (c) Contao Association
 *
 * @license LGPL-3.0-or-later
 */
namespace _ContaoManager\Contao\ManagerApi\Config;

use _ContaoManager\Contao\ManagerApi\ApiKernel;
use _ContaoManager\Contao\ManagerApi\Security\User;
use _ContaoManager\Symfony\Component\Filesystem\Filesystem;
use _ContaoManager\Symfony\Component\PasswordHasher\Hasher\PasswordHasherFactoryInterface;
class UserConfig extends AbstractConfig
{
    public function __construct(private readonly PasswordHasherFactoryInterface $passwordHasherFactory, ApiKernel $kernel, Filesystem $filesystem)
    {
        parent::__construct($kernel->getConfigDir() . \DIRECTORY_SEPARATOR . 'users.json', $filesystem, $kernel->getTranslator());
    }
    /**
     * Gets the application secret.
     */
    public function getSecret(): string
    {
        $this->initialize();
        if (!isset($this->data['secret'])) {
            $this->setSecret(bin2hex(random_bytes(40)));
        }
        return $this->data['secret'];
    }
    /**
     * Sets the application secret.
     *
     * @param string $secret
     */
    public function setSecret($secret): void
    {
        $this->initialize();
        if (empty($secret)) {
            throw new \InvalidArgumentException('Secret cannot be empty.');
        }
        $this->data['secret'] = (string) $secret;
        $this->save();
    }
    public function hasUsers(): bool
    {
        $this->initialize();
        return isset($this->data['users']) && \is_array($this->data['users']) && [] !== $this->data['users'];
    }
    /**
     * Gets all users.
     *
     * @return array<User>
     */
    public function getUsers(): array
    {
        $this->initialize();
        if (!$this->hasUsers()) {
            return [];
        }
        $users = [];
        foreach (array_keys($this->data['users']) as $username) {
            $users[] = $this->getUser($username);
        }
        return $users;
    }
    /**
     * Returns whether a user with the given username exists.
     */
    public function hasUser(string $username): bool
    {
        $this->initialize();
        return isset($this->data['users'][$username]);
    }
    /**
     * Gets the user by username or null if it does not exist.
     */
    public function getUser(string $username, string|null $scope = null): User|null
    {
        $this->initialize();
        if (!isset($this->data['users'][$username])) {
            return null;
        }
        $data = $this->data['users'][$username];
        $user = new User($data['username'], $data['password'] ?? null, $scope ?? $data['scope'] ?? null);
        if ($data['totp_secret'] ?? null) {
            $user->setTotpSecret($data['totp_secret']);
        }
        if ($data['passkey'] ?? null) {
            $user->setPasskey($data['passkey']);
        }
        return $user;
    }
    /**
     * Creates user from given username and plaintext password but does not add it.
     */
    public function createUser(string $username, string $password, string|null $scope = null): User
    {
        $this->initialize();
        $encodedPassword = $this->passwordHasherFactory->getPasswordHasher(new User($username, null))->hash($password);
        return new User($username, $encodedPassword, $scope);
    }
    /**
     * Adds a user to the configuration file.
     */
    public function addUser(User $user): void
    {
        $this->initialize();
        $username = $user->getUserIdentifier();
        if (isset($this->data['users'][$username])) {
            throw new \RuntimeException(\sprintf('Username "%s" already exists.', $username));
        }
        $this->data['users'][$username] = $user->jsonSerialize();
        $this->save();
    }
    /**
     * Replaces a user in the configuration file.
     */
    public function replaceUser(User $user): void
    {
        $this->initialize();
        unset($this->data['users'][$user->getUserIdentifier()]);
        $this->addUser($user);
    }
    /**
     * Update properties of a user in the configuration file.
     */
    public function updateUser(string $username, array $data): void
    {
        $this->initialize();
        if (!isset($this->data['users'][$username])) {
            throw new \RuntimeException(\sprintf('Username "%s" does not exist.', $username));
        }
        if (isset($data['password'])) {
            $data['password'] = $this->passwordHasherFactory->getPasswordHasher(new User($username, null))->hash($data['password']);
        }
        $this->data['users'][$username] = array_merge($this->data['users'][$username], $data);
        $this->save();
    }
    /**
     * Deletes a user from the configuration file.
     */
    public function deleteUser(string $username): void
    {
        $this->initialize();
        unset($this->data['users'][$username]);
        $this->save();
    }
    public function getWebauthnOptions(string $key): string|null
    {
        $this->initialize();
        if (($this->data['webauthn'][$key]['expires'] ?? 0) < time()) {
            return null;
        }
        return $this->data['webauthn'][$key]['options'] ?? null;
    }
    public function setWebauthnOptions(string $key, string $value): void
    {
        $this->initialize();
        $this->data['webauthn'][$key] = ['options' => $value, 'expires' => strtotime('+5 minutes')];
        $this->save();
    }
    public function deleteWebauthnOptions(string $key): void
    {
        $this->initialize();
        unset($this->data['webauthn'][$key]);
        $this->save();
    }
    /**
     * Gets tokens from the configuration file.
     */
    public function getTokens(): array
    {
        $this->initialize();
        if (!isset($this->data['tokens']) || !\is_array($this->data['tokens'])) {
            return [];
        }
        $data = [];
        foreach ($this->data['tokens'] as $id => $payload) {
            $data[] = array_merge(['id' => $id], $payload);
        }
        return $data;
    }
    /**
     * Gets token payload by ID (hashed token value).
     */
    public function getToken(string $id): array|null
    {
        $this->initialize();
        if (!isset($this->data['tokens'][$id])) {
            return null;
        }
        return array_merge(['id' => $id], $this->data['tokens'][$id]);
    }
    /**
     * Finds token payload by unhashed token value.
     */
    public function findToken(string $token): array|null
    {
        $this->initialize();
        return $this->getToken(hash('sha256', $token));
    }
    /**
     * Creates a token for given username.
     */
    public function createToken(string $username, string $clientId, string $scope = 'admin', bool $oneTime = \false): array
    {
        $this->initialize();
        if (!$this->hasUser($username)) {
            throw new \RuntimeException(\sprintf('Username "%s" does not exist.', $username));
        }
        if (!$oneTime) {
            foreach ($this->getTokens() as $payload) {
                if ($payload['username'] === $username && $payload['client_id'] === $clientId) {
                    $this->deleteToken($payload['id']);
                }
            }
        }
        $token = bin2hex(random_bytes(16));
        $id = hash('sha256', $token);
        if (isset($this->data['tokens'][$id])) {
            throw new \RuntimeException(\sprintf('Token with ID "%s" already exist.', $id));
        }
        $data = ['username' => $username, 'client_id' => $clientId, 'scope' => $scope];
        if ($oneTime) {
            $data['grant_type'] = 'one-time';
            $data['expires'] = strtotime('+30 seconds');
        }
        $this->data['tokens'][$id] = $data;
        $this->save();
        return array_merge(['id' => $id, 'token' => $token], $this->data['tokens'][$id]);
    }
    /**
     * Deletes a token from the configuration file.
     */
    public function deleteToken(string $id): void
    {
        $this->initialize();
        unset($this->data['tokens'][$id]);
        $this->save();
    }
    public function createInvitation(string $scope = 'admin'): array
    {
        $this->initialize();
        $token = bin2hex(random_bytes(16));
        $id = hash('sha256', $token);
        if (isset($this->data['tokens'][$id])) {
            throw new \RuntimeException(\sprintf('Token with ID "%s" already exist.', $id));
        }
        $data = ['scope' => $scope, 'grant_type' => 'invitation', 'expires' => strtotime('+1 week')];
        $this->data['tokens'][$id] = $data;
        $this->save();
        return array_merge(['id' => $id, 'token' => $token], $this->data['tokens'][$id]);
    }
    protected function initialize(): void
    {
        parent::initialize();
        $hasChanges = \false;
        if ([] !== $this->data && (!isset($this->data['version']) || (int) $this->data['version'] < 2)) {
            throw new \RuntimeException('Unsupported user.json version');
        }
        if (!isset($this->data['version'])) {
            $this->data['version'] = 2;
            $hasChanges = \true;
        }
        foreach ($this->data['tokens'] ?? [] as $id => $token) {
            if (isset($token['expires']) && $token['expires'] < time()) {
                unset($this->data['tokens'][$id]);
                $hasChanges = \true;
            }
        }
        foreach ($this->data['webauthn'] ?? [] as $key => $data) {
            if (($data['expires'] ?? 0) < time()) {
                unset($this->data['webauthn'][$key]);
                $hasChanges = \true;
            }
        }
        if ($hasChanges) {
            $this->save();
        }
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Contao Manager.
 *
 * (c) Contao Association
 *
 * @license LGPL-3.0-or-later
 */
namespace _ContaoManager\Contao\ManagerApi\Config;

use _ContaoManager\Contao\ManagerApi\ApiKernel;
use _ContaoManager\Symfony\Component\Filesystem\Filesystem;
class ManagerConfig extends AbstractConfig
{
    public function __construct(ApiKernel $kernel, Filesystem $filesystem)
    {
        parent::__construct($kernel->getConfigDir() . \DIRECTORY_SEPARATOR . 'manager.json', $filesystem, $kernel->getTranslator());
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Contao Manager.
 *
 * (c) Contao Association
 *
 * @license LGPL-3.0-or-later
 */
namespace _ContaoManager\Contao\ManagerApi\Config;

use _ContaoManager\Contao\ManagerApi\Exception\ApiProblemException;
use _ContaoManager\Contao\ManagerApi\I18n\Translator;
use _ContaoManager\Crell\ApiProblem\ApiProblem;
use _ContaoManager\Symfony\Component\Filesystem\Exception\IOException;
use _ContaoManager\Symfony\Component\Filesystem\Filesystem;
/**
 * @implements \IteratorAggregate<string, array|string|int|float|bool>
 */
abstract class AbstractConfig implements \IteratorAggregate, \Countable
{
    /**
     * @var array<string, array|string|int|float|bool>|null
     */
    protected array|null $data = null;
    private bool $deleted = \false;
    public function __construct(private readonly string $file, private readonly Filesystem $filesystem, private readonly Translator $translator)
    {
    }
    /**
     * Returns the config.
     */
    public function all(): array
    {
        $this->initialize();
        return $this->data;
    }
    /**
     * Returns the config keys.
     */
    public function keys(): array
    {
        $this->initialize();
        return array_keys($this->data);
    }
    /**
     * Replaces the current config by a new set.
     */
    public function replace(array $data = []): void
    {
        $this->initialize();
        $this->data = $data;
        $this->save();
    }
    /**
     * Adds config options.
     */
    public function add(array $data = []): void
    {
        $this->initialize();
        $this->data = array_replace($this->data, $data);
        $this->save();
    }
    /**
     * Returns a config option by name.
     */
    public function get(string $key, array|bool|float|int|string|null $default = null): array|bool|float|int|string|null
    {
        $this->initialize();
        return \array_key_exists($key, $this->data) ? $this->data[$key] : $default;
    }
    /**
     * Sets a config option by name.
     */
    public function set(string $key, array|bool|float|int|string $value): void
    {
        $this->initialize();
        $this->data[$key] = $value;
        $this->save();
    }
    /**
     * Returns true if the config option is defined.
     */
    public function has(string $key): bool
    {
        $this->initialize();
        return \array_key_exists($key, $this->data);
    }
    /**
     * Removes a config option.
     */
    public function remove(string $key): void
    {
        $this->initialize();
        unset($this->data[$key]);
        $this->save();
    }
    /**
     * @return \ArrayIterator<string, array|string|int|float|bool>
     */
    public function getIterator(): \ArrayIterator
    {
        $this->initialize();
        return new \ArrayIterator($this->data);
    }
    public function count(): int
    {
        $this->initialize();
        return \count($this->data);
    }
    /**
     * Saves current data to the JSON config file.
     */
    public function save(): void
    {
        if ($this->deleted || null === $this->data) {
            return;
        }
        try {
            $this->filesystem->dumpFile($this->file, json_encode($this->data, \JSON_PRETTY_PRINT));
        } catch (IOException $exception) {
            $this->throwNotWritable($exception);
        }
    }
    public function delete(): void
    {
        $this->deleted = \true;
        try {
            $this->filesystem->remove($this->file);
        } catch (IOException $exception) {
            $this->throwNotWritable($exception);
        }
    }
    protected function initialize(): void
    {
        if (null !== $this->data) {
            return;
        }
        if (!$this->filesystem->exists($this->file)) {
            $this->data = [];
            return;
        }
        $data = json_decode(file_get_contents($this->file), \true);
        if (!\is_array($data)) {
            throw new \InvalidArgumentException('The config file does not contain valid JSON data.');
        }
        $this->data = $data;
    }
    private function throwNotWritable(\Throwable $throwable): void
    {
        $problem = (new ApiProblem($this->translator->trans('error.writable.config-file', ['file' => $this->file]), 'https://php.net/is_writable'))->setDetail($this->translator->trans('error.writable.detail'));
        throw new ApiProblemException($problem, $throwable);
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Contao Manager.
 *
 * (c) Contao Association
 *
 * @license LGPL-3.0-or-later
 */
namespace _ContaoManager\Contao\ManagerApi\Config;

use _ContaoManager\Contao\ManagerApi\ApiKernel;
use _ContaoManager\Symfony\Component\Filesystem\Filesystem;
class ComposerConfig extends AbstractConfig
{
    public function __construct(ApiKernel $kernel, Filesystem $filesystem)
    {
        parent::__construct($kernel->getConfigDir() . \DIRECTORY_SEPARATOR . 'config.json', $filesystem, $kernel->getTranslator());
    }
    public function config(): PartialConfig
    {
        return new PartialConfig($this, 'config');
    }
    public function repositories(): PartialConfig
    {
        return new PartialConfig($this, 'repositories');
    }
    public function allowPlugins(): void
    {
        $config = $this->config();
        if ([] === $config->all() || ['allow-plugins' => \true] === $config->all()) {
            $config->replace(['preferred-install' => 'dist', 'store-auths' => \false, 'optimize-autoloader' => \true, 'sort-packages' => \true, 'discard-changes' => \true]);
        }
        if (\true !== $config->get('allow-plugins')) {
            $config->set('allow-plugins', \true);
        }
        if (null === $config->get('audit')) {
            $config->set('audit', ['block-insecure' => \false]);
        }
    }
    protected function initialize(): void
    {
        if (null !== $this->data) {
            return;
        }
        parent::initialize();
        // Make sure the config is in the correct subkey
        if (!$this->has('config') || [] === $this->get('config')) {
            $config = $this->all();
            unset($config['config']);
            $this->replace(['config' => $config]);
        }
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Contao Manager.
 *
 * (c) Contao Association
 *
 * @license LGPL-3.0-or-later
 */
namespace _ContaoManager\Contao\ManagerApi\Config;

/**
 * @implements \IteratorAggregate<string, array|string|int|float|bool>
 */
class PartialConfig implements \IteratorAggregate, \Countable
{
    public function __construct(private readonly AbstractConfig $parent, private readonly string $key)
    {
    }
    /**
     * Returns the config.
     */
    public function all(): array
    {
        return $this->parent->get($this->key, []);
    }
    /**
     * Returns the config keys.
     */
    public function keys(): array
    {
        return array_keys($this->parent->get($this->key, []));
    }
    /**
     * Replaces the current config by a new set.
     */
    public function replace(array $data = []): void
    {
        $this->parent->set($this->key, $data);
    }
    /**
     * Adds config options.
     */
    public function add(array $data = []): void
    {
        $this->replace(array_replace($this->all(), $data));
    }
    /**
     * Returns a config option by name.
     */
    public function get(string $key, array|bool|float|int|string|null $default = null): array|bool|float|int|string|null
    {
        $data = $this->all();
        return \array_key_exists($key, $data) ? $data[$key] : $default;
    }
    /**
     * Sets a config option by name.
     */
    public function set(string $key, array|bool|float|int|string $value): void
    {
        $this->add([$key => $value]);
    }
    /**
     * Returns true if the config option is defined.
     */
    public function has(string $key): bool
    {
        $data = $this->all();
        return \array_key_exists($key, $data);
    }
    /**
     * Removes a config option.
     */
    public function remove(string $key): void
    {
        $data = $this->all();
        unset($data[$key]);
        $this->replace($data);
    }
    /**
     * @return \ArrayIterator<string, array|string|int|float|bool>
     */
    public function getIterator(): \ArrayIterator
    {
        return new \ArrayIterator($this->all());
    }
    public function count(): int
    {
        return \count($this->all());
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Contao Manager.
 *
 * (c) Contao Association
 *
 * @license LGPL-3.0-or-later
 */
namespace _ContaoManager\Contao\ManagerApi\Config;

use _ContaoManager\Contao\ManagerApi\ApiKernel;
use _ContaoManager\Symfony\Component\Filesystem\Filesystem;
class AuthConfig extends AbstractConfig
{
    public function __construct(ApiKernel $kernel, Filesystem $filesystem)
    {
        parent::__construct($kernel->getConfigDir() . \DIRECTORY_SEPARATOR . 'auth.json', $filesystem, $kernel->getTranslator());
    }
    /**
     * Returns the GitHub OAuth token from the config file.
     */
    public function getGithubToken(): string|null
    {
        $this->initialize();
        if (!isset($this->data['github-oauth']['github.com'])) {
            return null;
        }
        return (string) $this->data['github-oauth']['github.com'];
    }
    /**
     * Stores the GitHub OAuth token in the config file.
     */
    public function setGithubToken(string $token): void
    {
        $this->initialize();
        $this->data['github-oauth'] = ['github.com' => $token];
        $this->save();
    }
    /**
     * Adds basic authentication info for given domain.
     */
    public function setBasicAuth(string $domain, string $username, string $password): void
    {
        $this->initialize();
        $this->data['http-basic'][$domain] = ['username' => $username, 'password' => $password];
        $this->save();
    }
    /**
     * Deletes basic authentication for given domain.
     */
    public function deleteBasicAuth(string $domain): void
    {
        $this->initialize();
        if (!isset($this->data['http-basic'][$domain])) {
            return;
        }
        unset($this->data['http-basic'][$domain]);
        $this->save();
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Contao Manager.
 *
 * (c) Contao Association
 *
 * @license LGPL-3.0-or-later
 */
namespace _ContaoManager\Contao\ManagerApi\Security;

use _ContaoManager\Contao\ManagerApi\ApiKernel;
use _ContaoManager\Contao\ManagerApi\Config\UserConfig;
use _ContaoManager\Symfony\Component\Filesystem\Filesystem;
use _ContaoManager\Symfony\Component\HttpFoundation\Request;
use _ContaoManager\Symfony\Component\HttpFoundation\Response;
use _ContaoManager\Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use _ContaoManager\Symfony\Component\Security\Core\Exception\AuthenticationCredentialsNotFoundException;
use _ContaoManager\Symfony\Component\Security\Core\User\UserProviderInterface;
use _ContaoManager\Symfony\Component\Security\Http\Authenticator\Passport\Badge\UserBadge;
use _ContaoManager\Symfony\Component\Security\Http\Authenticator\Passport\SelfValidatingPassport;
class PasswordlessAuthenticator extends AbstractBrowserAuthenticator
{
    private string $tokenId;
    /**
     * @param UserProviderInterface<User> $userProvider
     */
    public function __construct(private readonly UserProviderInterface $userProvider, private readonly UserConfig $userConfig, JwtManager $jwtManager, Filesystem $filesystem, ApiKernel $kernel)
    {
        parent::__construct($jwtManager, $this->userConfig, $filesystem, $kernel);
    }
    public function supports(Request $request): bool
    {
        if (!parent::supports($request) || !$request->request->has('token')) {
            return \false;
        }
        $token = $this->userConfig->findToken($request->request->get('token'));
        return $token && 'one-time' === ($token['grant_type'] ?? null);
    }
    public function authenticate(Request $request): SelfValidatingPassport
    {
        $token = $this->userConfig->findToken($request->request->get('token'));
        if (null === $token || 'one-time' !== ($token['grant_type'] ?? null)) {
            throw new AuthenticationCredentialsNotFoundException();
        }
        $this->tokenId = $token['id'];
        $userBadge = new UserBadge($token['username'], $this->userProvider->loadUserByIdentifier(...), ['scope' => $token['scope']]);
        return new SelfValidatingPassport($userBadge);
    }
    public function onAuthenticationSuccess(Request $request, TokenInterface $token, string $firewallName): Response
    {
        $this->userConfig->deleteToken($this->tokenId);
        return parent::onAuthenticationSuccess($request, $token, $firewallName);
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Contao Manager.
 *
 * (c) Contao Association
 *
 * @license LGPL-3.0-or-later
 */
namespace _ContaoManager\Contao\ManagerApi\Security;

use _ContaoManager\Contao\ManagerApi\ApiKernel;
use _ContaoManager\Contao\ManagerApi\Config\UserConfig;
use _ContaoManager\Contao\ManagerApi\Exception\InvalidTotpException;
use _ContaoManager\Cose\Algorithms;
use _ContaoManager\Symfony\Component\DependencyInjection\Attribute\Autoconfigure;
use _ContaoManager\Symfony\Component\Filesystem\Filesystem;
use _ContaoManager\Symfony\Component\HttpFoundation\Exception\BadRequestException;
use _ContaoManager\Symfony\Component\HttpFoundation\JsonResponse;
use _ContaoManager\Symfony\Component\HttpFoundation\Request;
use _ContaoManager\Symfony\Component\HttpFoundation\Response;
use _ContaoManager\Symfony\Component\HttpKernel\Exception\UnprocessableEntityHttpException;
use _ContaoManager\Symfony\Component\Security\Core\Exception\AccessDeniedException;
use _ContaoManager\Symfony\Component\Security\Core\Exception\AuthenticationCredentialsNotFoundException;
use _ContaoManager\Symfony\Component\Security\Core\Exception\AuthenticationException;
use _ContaoManager\Symfony\Component\Security\Core\Exception\BadCredentialsException;
use _ContaoManager\Symfony\Component\Security\Core\User\UserProviderInterface;
use _ContaoManager\Symfony\Component\Security\Http\Authenticator\Passport\Badge\UserBadge;
use _ContaoManager\Symfony\Component\Security\Http\Authenticator\Passport\Credentials\CustomCredentials;
use _ContaoManager\Symfony\Component\Security\Http\Authenticator\Passport\Passport;
use _ContaoManager\Symfony\Component\Security\Http\Authenticator\Passport\SelfValidatingPassport;
use _ContaoManager\Symfony\Component\Serializer\Encoder\JsonEncode;
use _ContaoManager\Symfony\Component\Serializer\Normalizer\AbstractObjectNormalizer;
use _ContaoManager\Symfony\Component\Serializer\SerializerInterface;
use _ContaoManager\Webauthn\AuthenticatorAssertionResponse;
use _ContaoManager\Webauthn\AuthenticatorAssertionResponseValidator;
use _ContaoManager\Webauthn\AuthenticatorAttestationResponse;
use _ContaoManager\Webauthn\AuthenticatorAttestationResponseValidator;
use _ContaoManager\Webauthn\AuthenticatorSelectionCriteria;
use _ContaoManager\Webauthn\PublicKeyCredential;
use _ContaoManager\Webauthn\PublicKeyCredentialCreationOptions;
use _ContaoManager\Webauthn\PublicKeyCredentialParameters;
use _ContaoManager\Webauthn\PublicKeyCredentialRequestOptions;
use _ContaoManager\Webauthn\PublicKeyCredentialRpEntity;
use _ContaoManager\Webauthn\PublicKeyCredentialSource;
use _ContaoManager\Webauthn\PublicKeyCredentialUserEntity;
#[Autoconfigure(bind: ['$serializer' => '@contao_manager.webauthn.serializer', '$authenticatorAttestationResponseValidator' => '@contao_manager.webauthn.authenticator_attestation_response_validator', '$authenticatorAssertionResponseValidator' => '@contao_manager.webauthn.authenticator_assertion_response_validator'])]
class WebauthnAuthenticator extends AbstractBrowserAuthenticator
{
    /**
     * @param UserProviderInterface<User> $userProvider
     */
    public function __construct(private readonly SerializerInterface $serializer, private readonly AuthenticatorAttestationResponseValidator $authenticatorAttestationResponseValidator, private readonly AuthenticatorAssertionResponseValidator $authenticatorAssertionResponseValidator, private readonly UserProviderInterface $userProvider, private readonly UserConfig $userConfig, JwtManager $jwtManager, Filesystem $filesystem, ApiKernel $kernel)
    {
        parent::__construct($jwtManager, $this->userConfig, $filesystem, $kernel);
    }
    public function supports(Request $request): bool
    {
        return parent::supports($request) && $request->request->has('passkey');
    }
    public function authenticate(Request $request): Passport
    {
        $rpEntity = $this->createRpEntity($request->getHost());
        if ($request->request->has('username') && (!$this->userConfig->hasUsers() || $request->request->has('invitation'))) {
            if ($this->userConfig->hasUser($request->request->get('username'))) {
                throw new UnprocessableEntityHttpException('Username exists.');
            }
            $user = $this->createUser($rpEntity, $request->request->get('username'), $request->request->get('passkey'), $request->request->get('invitation'));
            $userBadge = new UserBadge($user->getUserIdentifier(), $this->userProvider->loadUserByIdentifier(...));
            return new SelfValidatingPassport($userBadge);
        }
        $authenticatorAssertionResponse = $this->serializer->deserialize($request->request->get('passkey'), PublicKeyCredential::class, 'json')->response;
        if (!$authenticatorAssertionResponse instanceof AuthenticatorAssertionResponse) {
            throw new BadRequestException();
        }
        $username = $authenticatorAssertionResponse->userHandle;
        $userBadge = new UserBadge($username, $this->userProvider->loadUserByIdentifier(...));
        $credentials = new CustomCredentials(function (AuthenticatorAssertionResponse $response, User $user) use ($rpEntity): bool {
            $passkey = $user->getPasskey();
            $challenge = bin2hex($response->clientDataJSON->challenge);
            $requestOptions = $this->userConfig->getWebauthnOptions($challenge);
            if (!$passkey || !$requestOptions) {
                throw new AuthenticationCredentialsNotFoundException();
            }
            $this->userConfig->deleteWebauthnOptions($challenge);
            try {
                $publicKeyCredentialSource = $this->serializer->deserialize($passkey, PublicKeyCredentialSource::class, 'json');
                $publicKeyCredentialRequestOptions = $this->serializer->deserialize($requestOptions, PublicKeyCredentialRequestOptions::class, 'json');
                $this->authenticatorAssertionResponseValidator->check($publicKeyCredentialSource, $response, $publicKeyCredentialRequestOptions, $rpEntity->id, $user->getUserIdentifier());
                return \true;
            } catch (\Exception $e) {
                throw new AuthenticationException($e->getMessage(), $e->getCode(), $e);
            }
        }, $authenticatorAssertionResponse);
        return new Passport($userBadge, $credentials);
    }
    public function onAuthenticationFailure(Request $request, AuthenticationException $exception): Response
    {
        if ($exception instanceof InvalidTotpException) {
            return new JsonResponse(['username' => $exception->getUser()?->getUserIdentifier(), 'totp_enabled' => \true], Response::HTTP_UNAUTHORIZED);
        }
        return parent::onAuthenticationFailure($request, $exception);
    }
    public function getCredentialOptions(string $host, string|null $username): string
    {
        $challenge = random_bytes(32);
        $rpEntity = $this->createRpEntity($host);
        if (null === $username) {
            $options = new PublicKeyCredentialRequestOptions($challenge, $rpEntity->id, userVerification: PublicKeyCredentialRequestOptions::USER_VERIFICATION_REQUIREMENT_REQUIRED);
        } else {
            $options = new PublicKeyCredentialCreationOptions($rpEntity, new PublicKeyCredentialUserEntity($username, $username, $username), $challenge, [
                PublicKeyCredentialParameters::create('public-key', Algorithms::COSE_ALGORITHM_ES256K),
                // More interesting algorithm
                PublicKeyCredentialParameters::create('public-key', Algorithms::COSE_ALGORITHM_ES256),
                //      ||
                PublicKeyCredentialParameters::create('public-key', Algorithms::COSE_ALGORITHM_RS256),
                //      ||
                PublicKeyCredentialParameters::create('public-key', Algorithms::COSE_ALGORITHM_PS256),
                //      \/
                PublicKeyCredentialParameters::create('public-key', Algorithms::COSE_ALGORITHM_ED256),
            ], new AuthenticatorSelectionCriteria(userVerification: AuthenticatorSelectionCriteria::USER_VERIFICATION_REQUIREMENT_REQUIRED));
        }
        $serialized = $this->serializer->serialize($options, 'json', [AbstractObjectNormalizer::SKIP_NULL_VALUES => \true, JsonEncode::OPTIONS => \JSON_THROW_ON_ERROR]);
        $this->userConfig->setWebauthnOptions(bin2hex($challenge), $serialized);
        return $serialized;
    }
    private function createUser(PublicKeyCredentialRpEntity $rpEntity, string $username, string $data, string|null $invitation = null): User
    {
        $scope = null;
        if ($invitation) {
            $token = $this->userConfig->findToken($invitation);
            if (null === $token || 'invitation' !== ($token['grant_type'] ?? null)) {
                throw new AuthenticationCredentialsNotFoundException('Invitation not found.');
            }
            $scope = $token['scope'];
        } elseif ($this->userConfig->hasUsers()) {
            throw new AccessDeniedException();
        }
        $authenticatorAttestationResponse = $this->serializer->deserialize($data, PublicKeyCredential::class, 'json')->response;
        if (!$authenticatorAttestationResponse instanceof AuthenticatorAttestationResponse) {
            throw new BadCredentialsException();
        }
        $challenge = bin2hex($authenticatorAttestationResponse->clientDataJSON->challenge);
        $creationOptions = $this->userConfig->getWebauthnOptions($challenge);
        if (!$creationOptions) {
            throw new BadCredentialsException();
        }
        $this->userConfig->deleteWebauthnOptions($challenge);
        $publicKeyCredentialCreationOptions = $this->serializer->deserialize($creationOptions, PublicKeyCredentialCreationOptions::class, 'json');
        $publicKeyCredentialSource = $this->authenticatorAttestationResponseValidator->check($authenticatorAttestationResponse, $publicKeyCredentialCreationOptions, $rpEntity->id);
        $user = new User($username, null, $scope);
        $user->setPasskey($this->serializer->serialize($publicKeyCredentialSource, 'json'));
        $this->userConfig->addUser($user);
        if ($invitation) {
            $this->userConfig->deleteToken($token['id']);
        }
        return $user;
    }
    private function createRpEntity(string $host): PublicKeyCredentialRpEntity
    {
        if ('127.0.0.1' === $host) {
            $host = 'localhost';
        }
        return new PublicKeyCredentialRpEntity('Contao Manager ' . ApiKernel::MANAGER_VERSION, $host);
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Contao Manager.
 *
 * (c) Contao Association
 *
 * @license LGPL-3.0-or-later
 */
namespace _ContaoManager\Contao\ManagerApi\Security;

use _ContaoManager\Contao\ManagerApi\Config\UserConfig;
use _ContaoManager\Symfony\Component\HttpFoundation\Request;
use _ContaoManager\Symfony\Component\HttpFoundation\Response;
use _ContaoManager\Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use _ContaoManager\Symfony\Component\Security\Core\Exception\AuthenticationCredentialsNotFoundException;
use _ContaoManager\Symfony\Component\Security\Core\Exception\AuthenticationException;
use _ContaoManager\Symfony\Component\Security\Core\User\UserProviderInterface;
use _ContaoManager\Symfony\Component\Security\Http\Authenticator\AbstractAuthenticator;
use _ContaoManager\Symfony\Component\Security\Http\Authenticator\Passport\Badge\UserBadge;
use _ContaoManager\Symfony\Component\Security\Http\Authenticator\Passport\SelfValidatingPassport;
class TokenAuthenticator extends AbstractAuthenticator
{
    private string $tokenId;
    /**
     * @param UserProviderInterface<User> $userProvider
     */
    public function __construct(private readonly UserProviderInterface $userProvider, private readonly UserConfig $config)
    {
    }
    public function supports(Request $request): bool
    {
        if ($request->headers->has('Contao-Manager-Auth')) {
            return \true;
        }
        $authentication = $this->getAuthenticationHeader($request);
        return \is_string($authentication) && 0 === stripos($authentication, 'bearer ');
    }
    public function authenticate(Request $request): SelfValidatingPassport
    {
        $token = $this->config->findToken($this->getToken($request));
        if (null === $token || 'one-time' === ($token['grant_type'] ?? null)) {
            throw new AuthenticationCredentialsNotFoundException();
        }
        $this->tokenId = $token['id'];
        $userBadge = new UserBadge($token['username'], $this->userProvider->loadUserByIdentifier(...), ['scope' => $token['scope']]);
        return new SelfValidatingPassport($userBadge);
    }
    public function onAuthenticationFailure(Request $request, AuthenticationException $exception): Response|null
    {
        return null;
    }
    public function onAuthenticationSuccess(Request $request, TokenInterface $token, string $firewallName): Response|null
    {
        $token->setAttribute('authenticator', static::class);
        $token->setAttribute('token_id', $this->tokenId);
        return null;
    }
    /**
     * Gets the authentication header from request or HTTP headers.
     */
    private function getAuthenticationHeader(Request $request): string|null
    {
        if ($request->server->has('HTTP_AUTHORIZATION')) {
            return $request->server->get('HTTP_AUTHORIZATION');
        }
        if ($request->server->has('REDIRECT_HTTP_AUTHORIZATION')) {
            return $request->server->get('REDIRECT_HTTP_AUTHORIZATION');
        }
        if (\function_exists('getallheaders')) {
            $headers = getallheaders();
            if (isset($headers['authorization'])) {
                return $headers['authorization'];
            }
        }
        return null;
    }
    private function getToken(Request $request): string
    {
        if ($request->headers->has('Contao-Manager-Auth')) {
            return $request->headers->get('Contao-Manager-Auth');
        }
        $authentication = $this->getAuthenticationHeader($request);
        if (\is_string($authentication) && 0 === stripos($authentication, 'bearer ')) {
            return substr($authentication, 7);
        }
        throw new AuthenticationCredentialsNotFoundException();
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\Contao\ManagerApi\Security;

use _ContaoManager\Contao\ManagerApi\Config\UserConfig;
use _ContaoManager\Symfony\Component\Security\Core\Authentication\AuthenticationTrustResolverInterface;
use _ContaoManager\Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
class AuthenticationTrustResolver implements AuthenticationTrustResolverInterface
{
    public function __construct(private readonly AuthenticationTrustResolverInterface $inner, private readonly UserConfig $config)
    {
    }
    public function isAuthenticated(TokenInterface|null $token = null): bool
    {
        return $this->inner->isAuthenticated($token);
    }
    public function isRememberMe(TokenInterface|null $token = null): bool
    {
        return $this->inner->isRememberMe($token);
    }
    public function isFullFledged(TokenInterface|null $token = null): bool
    {
        if (!$this->inner->isFullFledged($token) || !$token?->getUserIdentifier()) {
            return \false;
        }
        return User::scopeFromRoles($token->getRoleNames()) === User::scopeFromRoles($this->config->getUser($token->getUserIdentifier())?->getRoles());
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Contao Manager.
 *
 * (c) Contao Association
 *
 * @license LGPL-3.0-or-later
 */
namespace _ContaoManager\Contao\ManagerApi\Security;

use _ContaoManager\Contao\ManagerApi\Config\UserConfig;
use _ContaoManager\Symfony\Component\Security\Core\Exception\UnsupportedUserException;
use _ContaoManager\Symfony\Component\Security\Core\Exception\UserNotFoundException;
use _ContaoManager\Symfony\Component\Security\Core\User\PasswordAuthenticatedUserInterface;
use _ContaoManager\Symfony\Component\Security\Core\User\PasswordUpgraderInterface;
use _ContaoManager\Symfony\Component\Security\Core\User\UserInterface;
use _ContaoManager\Symfony\Component\Security\Core\User\UserProviderInterface;
/**
 * @implements UserProviderInterface<User>
 */
class UserProvider implements UserProviderInterface, PasswordUpgraderInterface
{
    public function __construct(private readonly UserConfig $config)
    {
    }
    public function loadUserByIdentifier(string $identifier, array $attributes = []): UserInterface
    {
        $user = $this->config->getUser($identifier, $attributes['scope'] ?? null);
        if (null === $user) {
            $ex = new UserNotFoundException(\sprintf('Username "%s" does not exist.', $identifier));
            $ex->setUserIdentifier($identifier);
            throw $ex;
        }
        return $user;
    }
    public function refreshUser(UserInterface $user): UserInterface
    {
        if (!$user instanceof User) {
            throw new UnsupportedUserException(\sprintf('Instances of "%s" are not supported.', $user::class));
        }
        return $this->loadUserByIdentifier($user->getUserIdentifier());
    }
    public function supportsClass(string $class): bool
    {
        return User::class === $class;
    }
    public function upgradePassword(PasswordAuthenticatedUserInterface $user, string $newHashedPassword): void
    {
        if (!$user instanceof User) {
            throw new UnsupportedUserException(\sprintf('Instances of "%s" are not supported.', $user::class));
        }
        $this->config->replaceUser(new User($user->getUserIdentifier(), $newHashedPassword, $user->getScope()));
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Contao Manager.
 *
 * (c) Contao Association
 *
 * @license LGPL-3.0-or-later
 */
namespace _ContaoManager\Contao\ManagerApi\Security;

use _ContaoManager\Symfony\Component\Security\Core\User\PasswordAuthenticatedUserInterface;
use _ContaoManager\Symfony\Component\Security\Core\User\UserInterface;
class User implements UserInterface, PasswordAuthenticatedUserInterface, \JsonSerializable
{
    public const SCOPES = ['admin', 'install', 'update', 'read'];
    private string|null $totp_secret = null;
    private string|null $passkey = null;
    public function __construct(private readonly string $username, private string|null $password, private string|null $scope = null)
    {
        $this->scope ??= 'admin';
        if (!\in_array($this->scope, self::SCOPES, \true)) {
            throw new \InvalidArgumentException('Invalid scope');
        }
    }
    public function getUserIdentifier(): string
    {
        return $this->username;
    }
    public function getPassword(): string|null
    {
        return $this->password;
    }
    public function eraseCredentials(): void
    {
        $this->password = null;
    }
    public function getPasskey(): string|null
    {
        return $this->passkey;
    }
    public function setPasskey(string|null $passkey): void
    {
        $this->passkey = $passkey;
    }
    public function getScope(): string
    {
        return $this->scope;
    }
    public function getRoles(): array
    {
        return self::rolesFromScope($this->scope) ?? [];
    }
    public function getTotpSecret(): string|null
    {
        return $this->totp_secret;
    }
    public function setTotpSecret(string|null $secret): void
    {
        $this->totp_secret = $secret;
    }
    public function jsonSerialize(): array
    {
        return ['username' => $this->username, 'password' => $this->password, 'passkey' => $this->passkey, 'scope' => $this->scope, 'totp_secret' => $this->totp_secret];
    }
    public static function rolesFromScope(string|null $scope): array|null
    {
        if (null === $scope || !\in_array($scope, self::SCOPES, \true)) {
            return null;
        }
        return ['ROLE_' . strtoupper($scope)];
    }
    public static function scopeFromRoles(array $roles): string|null
    {
        $scopes = array_map(static fn(string $role) => strtolower(substr($role, 5)), $roles);
        $scopes = array_values(array_intersect(self::SCOPES, $scopes));
        if ([] === $scopes) {
            return null;
        }
        return $scopes[0];
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Contao Manager.
 *
 * (c) Contao Association
 *
 * @license LGPL-3.0-or-later
 */
namespace _ContaoManager\Contao\ManagerApi\Security;

use _ContaoManager\Symfony\Component\HttpFoundation\Request;
use _ContaoManager\Symfony\Component\HttpFoundation\Response;
use _ContaoManager\Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use _ContaoManager\Symfony\Component\Security\Core\Exception\AuthenticationCredentialsNotFoundException;
use _ContaoManager\Symfony\Component\Security\Core\Exception\AuthenticationException;
use _ContaoManager\Symfony\Component\Security\Core\User\UserProviderInterface;
use _ContaoManager\Symfony\Component\Security\Http\Authenticator\AbstractAuthenticator;
use _ContaoManager\Symfony\Component\Security\Http\Authenticator\Passport\Badge\UserBadge;
use _ContaoManager\Symfony\Component\Security\Http\Authenticator\Passport\Passport;
use _ContaoManager\Symfony\Component\Security\Http\Authenticator\Passport\SelfValidatingPassport;
class JwtAuthenticator extends AbstractAuthenticator
{
    /**
     * @param UserProviderInterface<User> $userProvider
     */
    public function __construct(private readonly UserProviderInterface $userProvider, private readonly JwtManager $jwtManager)
    {
    }
    public function supports(Request $request): bool
    {
        return $this->jwtManager->hasRequestToken($request) && null !== $this->jwtManager->getPayload($request);
    }
    public function authenticate(Request $request): Passport
    {
        $credentials = $this->jwtManager->getPayload($request);
        if (null === $credentials) {
            throw new AuthenticationCredentialsNotFoundException();
        }
        $userBadge = new UserBadge($credentials->username, $this->userProvider->loadUserByIdentifier(...), ['scope' => $credentials->scope ?? null]);
        return new SelfValidatingPassport($userBadge);
    }
    public function onAuthenticationSuccess(Request $request, TokenInterface $token, string $firewallName): Response|null
    {
        $token->setAttribute('authenticator', static::class);
        return null;
    }
    public function onAuthenticationFailure(Request $request, AuthenticationException $exception): Response|null
    {
        return null;
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Contao Manager.
 *
 * (c) Contao Association
 *
 * @license LGPL-3.0-or-later
 */
namespace _ContaoManager\Contao\ManagerApi\Security;

use _ContaoManager\Contao\ManagerApi\ApiKernel;
use _ContaoManager\Contao\ManagerApi\Config\UserConfig;
use _ContaoManager\Contao\ManagerApi\HttpKernel\ApiProblemResponse;
use _ContaoManager\Crell\ApiProblem\ApiProblem;
use _ContaoManager\Symfony\Component\Filesystem\Filesystem;
use _ContaoManager\Symfony\Component\HttpFoundation\JsonResponse;
use _ContaoManager\Symfony\Component\HttpFoundation\Request;
use _ContaoManager\Symfony\Component\HttpFoundation\Response;
use _ContaoManager\Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use _ContaoManager\Symfony\Component\Security\Core\Exception\AuthenticationException;
use _ContaoManager\Symfony\Component\Security\Http\Authenticator\AbstractAuthenticator;
abstract class AbstractBrowserAuthenticator extends AbstractAuthenticator
{
    private const LOCK_FILE = 'login.lock';
    public function __construct(private readonly JwtManager $jwtManager, private readonly UserConfig $userConfig, private readonly Filesystem $filesystem, private readonly ApiKernel $kernel)
    {
    }
    public function supports(Request $request): bool
    {
        // Manager login is locked
        if (self::isLocked($this->kernel->getConfigDir())) {
            return \false;
        }
        return '/api/session' === $request->getPathInfo() && $request->isMethod(Request::METHOD_POST);
    }
    public function onAuthenticationSuccess(Request $request, TokenInterface $token, string $firewallName): Response
    {
        // Reset lock counter
        $this->filesystem->dumpFile($this->kernel->getConfigDir() . \DIRECTORY_SEPARATOR . self::LOCK_FILE, '0');
        $token->setAttribute('authenticator', static::class);
        $user = $this->userConfig->getUser($token->getUserIdentifier());
        $scope = User::scopeFromRoles($token->getRoleNames());
        $json = ['username' => $token->getUserIdentifier(), 'scope' => $scope, 'limited' => $scope !== User::scopeFromRoles($user?->getRoles())];
        if ($user?->getPasskey()) {
            $json['passkey'] = \true;
        } else {
            $json['totp_enabled'] = (bool) $user?->getTotpSecret();
        }
        $response = new JsonResponse($json, Response::HTTP_CREATED);
        $this->jwtManager->addToken($request, $response, $token);
        return $response;
    }
    public function onAuthenticationFailure(Request $request, AuthenticationException $exception): Response
    {
        // Increase lock counter
        $this->filesystem->dumpFile($this->kernel->getConfigDir() . \DIRECTORY_SEPARATOR . self::LOCK_FILE, (string) (self::getLockCount($this->kernel->getConfigDir()) + 1));
        return new ApiProblemResponse((new ApiProblem())->setStatus(Response::HTTP_UNAUTHORIZED));
    }
    public static function isLocked(string $configDir): bool
    {
        return self::getLockCount($configDir) >= 3;
    }
    private static function getLockCount(string $configDir): int
    {
        return (int) @file_get_contents($configDir . \DIRECTORY_SEPARATOR . self::LOCK_FILE);
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Contao Manager.
 *
 * (c) Contao Association
 *
 * @license LGPL-3.0-or-later
 */
namespace _ContaoManager\Contao\ManagerApi\Security;

use _ContaoManager\Contao\ManagerApi\Exception\InvalidTotpException;
use _ContaoManager\OTPHP\TOTP;
use _ContaoManager\Symfony\Component\Security\Http\Authenticator\Passport\Badge\BadgeInterface;
class TotpBadge implements BadgeInterface
{
    private bool $resolved = \false;
    public function __construct(private readonly string $code)
    {
    }
    public function verify(User $user): bool
    {
        $this->resolved = \true;
        if (null === $user->getTotpSecret()) {
            return $this->resolved = \true;
        }
        if (!TOTP::createFromSecret($user->getTotpSecret())->verify($this->code)) {
            $exception = new InvalidTotpException();
            $exception->setUser($user);
            throw $exception;
        }
        return $this->resolved = \true;
    }
    public function isResolved(): bool
    {
        return $this->resolved;
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Contao Manager.
 *
 * (c) Contao Association
 *
 * @license LGPL-3.0-or-later
 */
namespace _ContaoManager\Contao\ManagerApi\Security;

use _ContaoManager\Contao\ManagerApi\ApiKernel;
use _ContaoManager\Contao\ManagerApi\Config\UserConfig;
use _ContaoManager\Contao\ManagerApi\Exception\InvalidTotpException;
use _ContaoManager\Symfony\Component\Filesystem\Filesystem;
use _ContaoManager\Symfony\Component\HttpFoundation\JsonResponse;
use _ContaoManager\Symfony\Component\HttpFoundation\Request;
use _ContaoManager\Symfony\Component\HttpFoundation\Response;
use _ContaoManager\Symfony\Component\HttpKernel\Exception\UnprocessableEntityHttpException;
use _ContaoManager\Symfony\Component\Security\Core\Exception\AuthenticationCredentialsNotFoundException;
use _ContaoManager\Symfony\Component\Security\Core\Exception\AuthenticationException;
use _ContaoManager\Symfony\Component\Security\Core\User\PasswordUpgraderInterface;
use _ContaoManager\Symfony\Component\Security\Core\User\UserProviderInterface;
use _ContaoManager\Symfony\Component\Security\Http\Authenticator\Passport\Badge\PasswordUpgradeBadge;
use _ContaoManager\Symfony\Component\Security\Http\Authenticator\Passport\Badge\UserBadge;
use _ContaoManager\Symfony\Component\Security\Http\Authenticator\Passport\Credentials\PasswordCredentials;
use _ContaoManager\Symfony\Component\Security\Http\Authenticator\Passport\Passport;
class LoginAuthenticator extends AbstractBrowserAuthenticator
{
    /**
     * @param UserProviderInterface<User> $userProvider
     */
    public function __construct(private readonly UserProviderInterface $userProvider, private readonly UserConfig $userConfig, JwtManager $jwtManager, Filesystem $filesystem, ApiKernel $kernel)
    {
        parent::__construct($jwtManager, $this->userConfig, $filesystem, $kernel);
    }
    public function supports(Request $request): bool
    {
        return parent::supports($request) && $request->request->has('username') && $request->request->has('password');
    }
    public function authenticate(Request $request): Passport
    {
        if (!$this->userConfig->hasUsers()) {
            $user = $this->userConfig->createUser($request->request->get('username'), $request->request->get('password'));
            $this->userConfig->addUser($user);
        } elseif ($request->request->has('invitation')) {
            $token = $this->userConfig->findToken($request->request->get('invitation'));
            if (null === $token || 'invitation' !== ($token['grant_type'] ?? null)) {
                throw new AuthenticationCredentialsNotFoundException();
            }
            $user = $this->userConfig->createUser($request->request->get('username'), $request->request->get('password'), $token['scope']);
            if ($this->userConfig->hasUser($user->getUserIdentifier())) {
                throw new UnprocessableEntityHttpException('Username exists.');
            }
            $this->userConfig->addUser($user);
            $this->userConfig->deleteToken($token['id']);
        }
        $userBadge = new UserBadge($request->request->get('username'), $this->userProvider->loadUserByIdentifier(...));
        $passport = new Passport($userBadge, new PasswordCredentials($request->request->get('password')));
        if ($this->userProvider instanceof PasswordUpgraderInterface) {
            $passport->addBadge(new PasswordUpgradeBadge($request->request->get('password'), $this->userProvider));
        }
        $passport->addBadge(new TotpBadge($request->request->getString('totp')));
        return $passport;
    }
    public function onAuthenticationFailure(Request $request, AuthenticationException $exception): Response
    {
        if ($exception instanceof InvalidTotpException) {
            return new JsonResponse(['username' => $exception->getUser()?->getUserIdentifier(), 'totp_enabled' => \true], Response::HTTP_UNAUTHORIZED);
        }
        return parent::onAuthenticationFailure($request, $exception);
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Contao Manager.
 *
 * (c) Contao Association
 *
 * @license LGPL-3.0-or-later
 */
namespace _ContaoManager\Contao\ManagerApi\Security;

use _ContaoManager\Contao\ManagerApi\ApiKernel;
use _ContaoManager\Contao\ManagerApi\Config\UserConfig;
use _ContaoManager\Firebase\JWT\JWT;
use _ContaoManager\Firebase\JWT\Key;
use _ContaoManager\Symfony\Component\HttpFoundation\Cookie;
use _ContaoManager\Symfony\Component\HttpFoundation\Request;
use _ContaoManager\Symfony\Component\HttpFoundation\Response;
use _ContaoManager\Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
class JwtManager
{
    public const COOKIE_AUTH = 'contao_manager_auth';
    public function __construct(private readonly UserConfig $users)
    {
    }
    /**
     * Gets payload data from JWT token cookie in the request.
     */
    public function getPayload(Request $request): \stdClass|null
    {
        if (!$request->cookies->has(self::COOKIE_AUTH)) {
            return null;
        }
        try {
            return JWT::decode($request->cookies->get(self::COOKIE_AUTH), new Key($this->users->getSecret(), 'HS256'));
        } catch (\Exception) {
            return null;
        }
    }
    /**
     * Checks if the request has a JWT cookie.
     */
    public function hasRequestToken(Request $request): bool
    {
        return $request->cookies->has(self::COOKIE_AUTH);
    }
    /**
     * Checks if the response has a JWT cookie.
     */
    public function hasResponseToken(Response $response): bool
    {
        return $this->hasCookie($response);
    }
    /**
     * Adds JWT auth cookies to the given response.
     */
    public function addToken(Request $request, Response $response, TokenInterface $token): void
    {
        $payload = ['iat' => time(), 'exp' => strtotime('+30 minutes'), 'username' => $token->getUserIdentifier(), 'scope' => User::scopeFromRoles($token->getRoleNames())];
        $response->headers->setCookie($this->createCookie(JWT::encode($payload, $this->users->getSecret(), 'HS256'), $request));
    }
    /**
     * Clears the JWT cookie in the response.
     */
    public function removeToken(Request $request, Response $response): void
    {
        if (!$request->cookies->has(self::COOKIE_AUTH)) {
            return;
        }
        $response->headers->clearCookie(self::COOKIE_AUTH, ApiKernel::isPhar() ? $request->getBaseUrl() . '/' : '/', null, $request->isSecure());
    }
    /**
     * Returns whether the response has a cookie with that name.
     */
    private function hasCookie(Response $response): bool
    {
        $cookies = $response->headers->getCookies();
        foreach ($cookies as $cookie) {
            if (self::COOKIE_AUTH === $cookie->getName()) {
                return \true;
            }
        }
        return \false;
    }
    /**
     * Creates a cookie configured for Contao Manager.
     */
    private function createCookie(string $value, Request $request): Cookie
    {
        return Cookie::create(self::COOKIE_AUTH, $value, 0, ApiKernel::isPhar() ? $request->getBaseUrl() . '/' : '/', null, $request->isSecure(), \true, \false, Cookie::SAMESITE_STRICT);
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Contao Manager.
 *
 * (c) Contao Association
 *
 * @license LGPL-3.0-or-later
 */
namespace _ContaoManager\Contao\ManagerApi\TaskOperation\Composer;

use _ContaoManager\Contao\ManagerApi\Process\ConsoleProcessFactory;
use _ContaoManager\Contao\ManagerApi\TaskOperation\AbstractProcessOperation;
use _ContaoManager\Symfony\Component\Security\Http\Attribute\IsGranted;
#[IsGranted('ROLE_INSTALL')]
class RemoveOperation extends AbstractProcessOperation
{
    public function __construct(ConsoleProcessFactory $processFactory, private readonly array $removed)
    {
        try {
            $process = $processFactory->restoreBackgroundProcess('composer-remove');
            parent::__construct($process);
        } catch (\Exception) {
            $arguments = array_merge(['composer', 'remove'], $this->removed, ['--no-update', '--no-scripts', '--no-ansi', '--no-interaction']);
            $process = $processFactory->createManagerConsoleBackgroundProcess($arguments, 'composer-remove');
            parent::__construct($process);
        }
    }
    public function getSummary(): string
    {
        return 'composer remove ' . implode(' ', $this->removed) . ' --no-update';
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Contao Manager.
 *
 * (c) Contao Association
 *
 * @license LGPL-3.0-or-later
 */
namespace _ContaoManager\Contao\ManagerApi\TaskOperation\Composer;

use _ContaoManager\Contao\ManagerApi\Process\ConsoleProcessFactory;
use _ContaoManager\Contao\ManagerApi\TaskOperation\AbstractProcessOperation;
use _ContaoManager\Symfony\Component\Security\Http\Attribute\IsGranted;
#[IsGranted('ROLE_UPDATE')]
class ClearCacheOperation extends AbstractProcessOperation
{
    public function __construct(ConsoleProcessFactory $processFactory)
    {
        try {
            parent::__construct($processFactory->restoreBackgroundProcess('clear-cache'));
        } catch (\Exception) {
            parent::__construct($processFactory->createManagerConsoleBackgroundProcess(['composer', 'clear-cache', '--no-interaction'], 'clear-cache'));
        }
    }
    public function getSummary(): string
    {
        return 'composer clear-cache';
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Contao Manager.
 *
 * (c) Contao Association
 *
 * @license LGPL-3.0-or-later
 */
namespace _ContaoManager\Contao\ManagerApi\TaskOperation\Composer;

use _ContaoManager\Contao\ManagerApi\I18n\Translator;
use _ContaoManager\Contao\ManagerApi\Process\ConsoleProcessFactory;
use _ContaoManager\Contao\ManagerApi\TaskOperation\AbstractProcessOperation;
use _ContaoManager\Symfony\Component\Security\Http\Attribute\IsGranted;
#[IsGranted('ROLE_UPDATE')]
class DumpAutoloadOperation extends AbstractProcessOperation
{
    public function __construct(ConsoleProcessFactory $processFactory, private readonly Translator $translator)
    {
        try {
            parent::__construct($processFactory->restoreBackgroundProcess('dump-autoload'));
        } catch (\Exception) {
            parent::__construct($processFactory->createManagerConsoleBackgroundProcess(['composer', 'dump-autoload', '--no-dev', '--optimize'], 'dump-autoload'));
        }
    }
    public function getSummary(): string
    {
        return 'composer dump-autoload';
    }
    public function getDetails(): string|null
    {
        $total = $this->getTotalClasses($this->process->getOutput());
        if (null !== $total) {
            return $this->translator->trans('taskoperation.dump-autoload.result', ['count' => $total]);
        }
        return '';
    }
    private function getTotalClasses(string $output): string|null
    {
        $lines = explode("\n", $output);
        foreach ($lines as $line) {
            if (preg_match('{Generated optimized autoload files containing ([\d.]+) classes}', $line, $match)) {
                return $match[1];
            }
        }
        return null;
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Contao Manager.
 *
 * (c) Contao Association
 *
 * @license LGPL-3.0-or-later
 */
namespace _ContaoManager\Contao\ManagerApi\TaskOperation\Composer;

use _ContaoManager\Contao\ManagerApi\Composer\Environment;
use _ContaoManager\Contao\ManagerApi\I18n\Translator;
use _ContaoManager\Contao\ManagerApi\Process\ConsoleProcessFactory;
use _ContaoManager\Contao\ManagerApi\Task\TaskConfig;
use _ContaoManager\Contao\ManagerApi\TaskOperation\AbstractProcessOperation;
use _ContaoManager\Symfony\Component\Security\Http\Attribute\IsGranted;
#[IsGranted('ROLE_UPDATE')]
class InstallOperation extends AbstractProcessOperation
{
    public function __construct(ConsoleProcessFactory $processFactory, private readonly TaskConfig $taskConfig, Environment $environment, private readonly Translator $translator, private readonly bool $dryRun = \false, bool $retry = \true)
    {
        try {
            $process = $processFactory->restoreBackgroundProcess('composer-install');
            $retries = (int) $this->taskConfig->getState('install-retry', 0);
            if ($retry && $retries < 4 && $process->isTerminated() && !$process->isSuccessful()) {
                $process->delete();
                $this->taskConfig->setState('install-retry', ++$retries);
                throw new \RuntimeException('Install process failed, restarting');
            }
            parent::__construct($process);
        } catch (\Exception) {
            $arguments = ['composer', 'install', '--no-dev', '--no-progress', '--no-ansi', '--no-interaction', '--optimize-autoloader'];
            if ($this->dryRun) {
                $arguments[] = '--dry-run';
                $arguments[] = '--no-scripts';
                $arguments[] = '--no-plugins';
            }
            if ($environment->isDebug()) {
                $arguments[] = '--profile';
                $arguments[] = '-vvv';
            }
            $process = $processFactory->createManagerConsoleBackgroundProcess($arguments, 'composer-install');
            // An install task should never need 5min to install
            $process->setTimeout(60 * 5);
            parent::__construct($process);
        }
    }
    public function getSummary(): string
    {
        $summary = 'composer install';
        if ($this->dryRun) {
            $summary .= ' --dry-run';
        }
        return $summary;
    }
    public function getDetails(): string|null
    {
        if (!$this->isStarted()) {
            return null;
        }
        if ($this->isRunning() && ($attempt = (int) $this->taskConfig->getState('install-retry', 0)) > 0) {
            return $this->translator->trans('taskoperation.composer-install.retry', ['current' => $attempt + 1, 'max' => 5]);
        }
        if ($this->isSuccessful()) {
            $output = $this->process->getOutput();
            if (str_contains($output, 'Nothing to install or update')) {
                return $this->translator->trans('taskoperation.composer-install.nothing');
            }
            $operations = $this->getPackageOperations($output);
            if (null !== $operations) {
                return $this->translator->trans('taskoperation.composer-install.result', $operations);
            }
        }
        return '';
    }
    private function getPackageOperations(string $output): array|null
    {
        // Package operations: 6 installs, 85 updates, 0 removals
        $lines = explode("\n", $output);
        foreach ($lines as $line) {
            if (\false !== $pos = strpos($line, 'Package operations:')) {
                $operations = substr($line, $pos);
                if (preg_match('{Package operations: (\d+) installs, (\d+) updates, (\d+) removals}', $operations, $match)) {
                    return ['installs' => $match[1], 'updates' => $match[2], 'removals' => $match[3]];
                }
            }
        }
        return null;
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Contao Manager.
 *
 * (c) Contao Association
 *
 * @license LGPL-3.0-or-later
 */
namespace _ContaoManager\Contao\ManagerApi\TaskOperation\Composer;

use _ContaoManager\Contao\ManagerApi\Composer\Environment;
use _ContaoManager\Contao\ManagerApi\Process\ConsoleProcessFactory;
use _ContaoManager\Contao\ManagerApi\TaskOperation\AbstractProcessOperation;
use _ContaoManager\Symfony\Component\Security\Http\Attribute\IsGranted;
#[IsGranted('ROLE_UPDATE')]
class UpdateOperation extends AbstractProcessOperation
{
    public function __construct(ConsoleProcessFactory $processFactory, Environment $environment, private readonly array $packages = [], private readonly bool $dryRun = \false)
    {
        try {
            parent::__construct($processFactory->restoreBackgroundProcess('composer-update'));
        } catch (\Exception) {
            $arguments = array_merge(['composer', 'update'], $this->packages, ['--with-dependencies', '--no-install', '--no-scripts', '--no-dev', '--no-progress', '--no-ansi', '--no-interaction', '--optimize-autoloader']);
            if ($this->dryRun) {
                $arguments[] = '--dry-run';
                $arguments[] = '--no-scripts';
                $arguments[] = '--no-plugins';
            }
            if ($environment->isDebug()) {
                $arguments[] = '--profile';
                $arguments[] = '-vvv';
            }
            parent::__construct($processFactory->createManagerConsoleBackgroundProcess($arguments, 'composer-update'));
        }
    }
    public function getSummary(): string
    {
        $summary = 'composer update';
        if ([] !== $this->packages) {
            $summary .= ' ' . implode(' ', $this->packages);
        }
        $summary .= ' --no-install';
        if ($this->dryRun) {
            $summary .= ' --dry-run';
        }
        return $summary;
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Contao Manager.
 *
 * (c) Contao Association
 *
 * @license LGPL-3.0-or-later
 */
namespace _ContaoManager\Contao\ManagerApi\TaskOperation\Composer;

use _ContaoManager\Contao\ManagerApi\Process\ConsoleProcessFactory;
use _ContaoManager\Contao\ManagerApi\TaskOperation\AbstractProcessOperation;
use _ContaoManager\Symfony\Component\Security\Http\Attribute\IsGranted;
#[IsGranted('ROLE_INSTALL')]
class RequireOperation extends AbstractProcessOperation
{
    public function __construct(ConsoleProcessFactory $processFactory, private readonly array $required)
    {
        try {
            $process = $processFactory->restoreBackgroundProcess('composer-require');
            parent::__construct($process);
        } catch (\Exception) {
            $arguments = array_merge(['composer', 'require'], $this->required, ['--no-update', '--no-scripts', '--prefer-stable', '--sort-packages', '--no-ansi', '--no-interaction']);
            $process = $processFactory->createManagerConsoleBackgroundProcess($arguments, 'composer-require');
            parent::__construct($process);
        }
    }
    public function getSummary(): string
    {
        return 'composer require ' . implode(' ', $this->required) . ' --no-update';
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Contao Manager.
 *
 * (c) Contao Association
 *
 * @license LGPL-3.0-or-later
 */
namespace _ContaoManager\Contao\ManagerApi\TaskOperation\Composer;

use Composer\Util\Filesystem;
use _ContaoManager\Contao\ManagerApi\ApiKernel;
use _ContaoManager\Contao\ManagerApi\Composer\Environment;
use _ContaoManager\Contao\ManagerApi\Process\ConsoleProcessFactory;
use _ContaoManager\Contao\ManagerApi\Task\TaskConfig;
use _ContaoManager\Contao\ManagerApi\TaskOperation\AbstractProcessOperation;
use _ContaoManager\Symfony\Component\Finder\Finder;
use _ContaoManager\Symfony\Component\Security\Http\Attribute\IsGranted;
#[IsGranted('ROLE_INSTALL')]
class CreateProjectOperation extends AbstractProcessOperation
{
    private string|null $publicDir;
    public function __construct(TaskConfig $taskConfig, ConsoleProcessFactory $processFactory, ApiKernel $kernel, private readonly Environment $environment, private readonly string $package, private readonly string|null $version = null, bool $isUpload = \false)
    {
        try {
            parent::__construct($processFactory->restoreBackgroundProcess('composer-create-project'));
        } catch (\Exception) {
            $folder = uniqid('contao-');
            $arguments = ['composer', 'create-project', $this->package . ($this->version ? ':' . $this->version : ''), $folder, '--no-install', '--no-scripts', '--no-dev', '--no-progress', '--no-ansi', '--no-interaction'];
            if ($isUpload) {
                $arguments[] = '--repository=' . json_encode(['type' => 'artifact', 'url' => $this->environment->getArtifactDir()]);
            }
            if ($this->environment->isDebug()) {
                $arguments[] = '--profile';
                $arguments[] = '-vvv';
            }
            $process = $processFactory->createManagerConsoleBackgroundProcess($arguments, 'composer-create-project');
            $process->setMeta(['folder' => $folder]);
            parent::__construct($process);
        }
        $this->publicDir = $taskConfig->getState('public-dir');
        if (null !== $this->publicDir) {
            return;
        }
        if ($kernel->getProjectDir() === $kernel->getPublicDir()) {
            throw new \RuntimeException('Cannot install without a public directory.');
        }
        $taskConfig->setState('public-dir', $this->publicDir = $kernel->getPublicDir());
    }
    public function getSummary(): string
    {
        return 'composer create-project ' . $this->package . ($this->version ? ':' . $this->version : '');
    }
    public function run(): void
    {
        parent::run();
        if ($this->process->isSuccessful() && !$this->isInstalled()) {
            $folder = $this->process->getMeta()['folder'] ?? null;
            if ($folder) {
                $fs = new Filesystem();
                $files = Finder::create()->exclude(['__MACOSX'])->notName(['theme.xml', '.DS_Store'])->ignoreVCS(\true)->ignoreDotFiles(\true)->depth(0)->in($folder);
                foreach ($files as $file) {
                    $fs->copy($file->getPathname(), \dirname($file->getPath()) . \DIRECTORY_SEPARATOR . $file->getFilename());
                }
                $fs->removeDirectory($folder);
                // write public-dir in composer.json
                try {
                    $file = $this->environment->getComposerJsonFile();
                    $json = $file->read();
                    $json['extra']['public-dir'] = basename((string) $this->publicDir);
                    $file->write($json);
                } catch (\RuntimeException) {
                    // ignore
                }
                $this->process->setMeta(['installed' => \true]);
            }
        }
    }
    public function isRunning(): bool
    {
        return parent::isRunning() || $this->isStarted() && !$this->hasError() && !$this->isInstalled();
    }
    public function isSuccessful(): bool
    {
        return parent::isSuccessful() && $this->isInstalled();
    }
    private function isInstalled(): bool
    {
        return (bool) ($this->process->getMeta()['installed'] ?? \false);
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Contao Manager.
 *
 * (c) Contao Association
 *
 * @license LGPL-3.0-or-later
 */
namespace _ContaoManager\Contao\ManagerApi\TaskOperation\Composer;

use Composer\Json\JsonFile;
use _ContaoManager\Contao\ManagerApi\Composer\CloudChanges;
use _ContaoManager\Contao\ManagerApi\Composer\CloudException;
use _ContaoManager\Contao\ManagerApi\Composer\CloudJob;
use _ContaoManager\Contao\ManagerApi\Composer\CloudResolver;
use _ContaoManager\Contao\ManagerApi\Composer\Environment;
use _ContaoManager\Contao\ManagerApi\Exception\RequestException;
use _ContaoManager\Contao\ManagerApi\I18n\Translator;
use _ContaoManager\Contao\ManagerApi\Task\TaskConfig;
use _ContaoManager\Contao\ManagerApi\TaskOperation\ConsoleOutput;
use _ContaoManager\Contao\ManagerApi\TaskOperation\SponsoredOperationInterface;
use _ContaoManager\Contao\ManagerApi\TaskOperation\TaskOperationInterface;
use _ContaoManager\Psr\Log\LoggerInterface;
use _ContaoManager\Symfony\Component\Filesystem\Filesystem;
use _ContaoManager\Symfony\Component\Security\Http\Attribute\IsGranted;
use _ContaoManager\Terminal42\ComposerLockValidator\ValidationException;
use _ContaoManager\Terminal42\ComposerLockValidator\Validator;
#[IsGranted('ROLE_UPDATE')]
class CloudOperation implements TaskOperationInterface, SponsoredOperationInterface
{
    private const CLOUD_ERROR = 'Error handling the Composer Resolver Cloud. Please try again later.';
    private CloudJob|null $job = null;
    private \Throwable|null $exception = null;
    private string|null $output = null;
    public function __construct(private readonly CloudResolver $cloud, private readonly CloudChanges $changes, private readonly TaskConfig $taskConfig, private readonly Environment $environment, private readonly Translator $translator, private readonly Filesystem $filesystem, private readonly LoggerInterface|null $logger = null)
    {
    }
    public function getSummary(): string
    {
        $summary = 'composer update ';
        if ([] !== $this->changes->getUpdates()) {
            $summary .= implode(' ', $this->changes->getUpdates());
        }
        $summary .= ' --no-install';
        if ($this->changes->getDryRun()) {
            $summary .= ' --dry-run';
        }
        return $summary;
    }
    public function getDetails(): string|null
    {
        $job = $this->getCurrentJob();
        if (!$job instanceof CloudJob) {
            return '';
        }
        switch ($job->getStatus()) {
            case CloudJob::STATUS_QUEUED:
                return $this->translator->trans('taskoperation.cloud.queued', ['seconds' => $job->getWaitingTime(), 'jobs' => $job->getJobsInQueue() + $job->getWorkers(), 'workers' => $job->getWorkers()]);
            case CloudJob::STATUS_PROCESSING:
                $seconds = $this->taskConfig->getState('cloud-job-processing');
                if (!$seconds) {
                    return '';
                }
                $seconds = time() - $seconds;
                return $this->translator->trans('taskoperation.cloud.processing', ['seconds' => $seconds]);
            case CloudJob::STATUS_ERROR:
                return '';
            case CloudJob::STATUS_FINISHED:
                $seconds = $this->taskConfig->getState('cloud-job-finished', time()) - $this->taskConfig->getState('cloud-job-processing', time());
                $profile = $this->getFinalProfile($this->getOutput());
                preg_match('{Memory usage: ([^ ]+) \(peak: ([^)]+)\), time: ([0-9.]+s)\.}', $profile, $match);
                return $this->translator->trans('taskoperation.cloud.finished', ['job' => $job->getId(), 'memory' => $match[1] ?? '', 'peak' => $match[2] ?? '', 'time' => $match[3] ?? '', 'seconds' => $seconds]);
        }
        return '';
    }
    public function getConsole(): ConsoleOutput
    {
        $console = new ConsoleOutput();
        $job = $this->getCurrentJob();
        if ($this->exception instanceof CloudException) {
            return $console->add(\sprintf("> The Composer Resolver Cloud failed with status code %s\n\n  %s", $this->exception->getStatusCode(), $this->exception->getErrorMessage()));
        }
        if ($this->exception instanceof RequestException && 404 === $this->exception->getStatusCode()) {
            return $console->add(self::CLOUD_ERROR);
        }
        if ($this->exception instanceof \Exception) {
            return $console->add($this->exception->getMessage());
        }
        if (!$job instanceof CloudJob) {
            if ($this->hasError()) {
                $console->add(self::CLOUD_ERROR);
            }
            return $console;
        }
        $title = '> Resolving dependencies using Composer Cloud ' . $job->getVersion();
        switch ($job->getStatus()) {
            case CloudJob::STATUS_QUEUED:
                break;
            case CloudJob::STATUS_PROCESSING:
                if ($this->environment->isDebug()) {
                    $console->add($this->getOutput(), $title);
                } else {
                    $console->add($title);
                }
                break;
            case CloudJob::STATUS_ERROR:
                $console->add(\sprintf("%s\n\n# Cloud Job ID %s failed", $this->getOutput(), $job->getId()), $title);
                break;
            case CloudJob::STATUS_FINISHED:
                $output = $this->getOutput();
                $seconds = $this->taskConfig->getState('cloud-job-finished', time()) - $this->taskConfig->getState('cloud-job-processing', time());
                $profile = $this->getFinalProfile($output);
                $console->add($output, $title);
                $console->add("# Job ID {$job->getId()} completed in {$seconds} seconds\n# " . $profile);
                break;
            default:
                throw new \RuntimeException(\sprintf('Unknown cloud status "%s"', $job->getStatus()));
        }
        return $console;
    }
    public function isStarted(): bool
    {
        try {
            return null !== $this->taskConfig->getState('cloud-job');
        } catch (\Exception $exception) {
            $this->exception = $exception;
            return \true;
        }
    }
    public function isRunning(): bool
    {
        try {
            return $this->isStarted() && null === $this->taskConfig->getState('cloud-job-successful');
        } catch (\Exception $exception) {
            $this->exception = $exception;
            return \false;
        }
    }
    public function isSuccessful(): bool
    {
        return (bool) $this->taskConfig->getState('cloud-job-successful', \false);
    }
    public function hasError(): bool
    {
        return \false === $this->taskConfig->getState('cloud-job-successful');
    }
    public function continueOnError(): bool
    {
        return \false;
    }
    public function run(): void
    {
        try {
            if (null === $this->taskConfig->getState('cloud-job')) {
                // Retry to create Cloud job, the first request always fails on XAMPP for
                // unknown reason
                $attempts = (int) $this->taskConfig->getState('cloud-job-attempts', 0);
                if ($attempts >= 5) {
                    $this->taskConfig->setState('cloud-job-successful', \false);
                    $this->output = self::CLOUD_ERROR;
                    return;
                }
                $this->taskConfig->setState('cloud-job-attempts', $attempts + 1);
                $this->job = $this->cloud->createJob($this->changes, $this->environment);
                $this->taskConfig->setState('cloud-job', $this->job->getId());
                return;
            }
            if (null !== $this->taskConfig->getState('cloud-job-successful')) {
                return;
            }
            $job = $this->getCurrentJob();
            if (!$job instanceof CloudJob) {
                return;
            }
            if ($job->isSuccessful()) {
                try {
                    $lockJson = $this->validateComposerFiles($job);
                    $this->filesystem->dumpFile($this->environment->getLockFile(), $lockJson);
                    $this->taskConfig->setState('cloud-job-successful', \true);
                } catch (\Exception $e) {
                    $this->taskConfig->setState('cloud-job-validation-error', $e->getMessage());
                    $this->taskConfig->setState('cloud-job-successful', \false);
                }
            } elseif ($job->isFailed()) {
                $this->taskConfig->setState('cloud-job-successful', \false);
            }
        } catch (\Exception $exception) {
            $this->exception = $exception;
            $this->output = self::CLOUD_ERROR;
        }
    }
    public function abort(): void
    {
        $this->taskConfig->setState('cloud-job-successful', \false);
    }
    public function delete(): void
    {
        try {
            $this->output = $this->taskConfig->getState('cloud-job-output', '');
            $this->cloud->deleteJob((string) $this->taskConfig->getState('cloud-job'));
        } catch (\Exception $exception) {
            $this->exception = $exception;
        }
    }
    public function getSponsor(): array|null
    {
        if (!$this->job instanceof CloudJob) {
            return null;
        }
        return $this->job->getSponsor();
    }
    private function getCurrentJob(): CloudJob|null
    {
        if ($this->job instanceof CloudJob) {
            return $this->job;
        }
        if (null === $this->taskConfig->getState('cloud-job')) {
            return null;
        }
        try {
            if (\is_array($content = $this->taskConfig->getState('cloud-job-status'))) {
                $this->job = new CloudJob($content);
                if (null !== $this->taskConfig->getState('cloud-job-successful')) {
                    $this->output = $this->taskConfig->getState('cloud-job-output', '');
                    return $this->job;
                }
                $lastUpdated = time() - (int) $this->taskConfig->getState('cloud-job-updated', time());
                $isProcessing = (int) $this->taskConfig->getState('cloud-job-processing', 0) > 0;
                if ($isProcessing && $lastUpdated <= 5 || $lastUpdated <= 10) {
                    $this->output = $this->taskConfig->getState('cloud-job-output', '');
                    return $this->job;
                }
            }
        } catch (\Exception $exception) {
            // do nothing
        }
        try {
            $this->job = $this->cloud->getJob((string) $this->taskConfig->getState('cloud-job'));
        } catch (\Exception $exception) {
            $this->exception = $exception;
            if ($exception instanceof CloudException && $exception->isClientError()) {
                $this->taskConfig->setState('cloud-job-successful', \false);
            }
            return $this->job;
        }
        if (!$this->job instanceof CloudJob) {
            return null;
        }
        $this->taskConfig->setState('cloud-job-status', $this->job->jsonSerialize());
        $this->taskConfig->setState('cloud-job-updated', time());
        if ($this->job->isProcessing() && !$this->taskConfig->getState('cloud-job-processing')) {
            $this->taskConfig->setState('cloud-job-processing', time());
        }
        if (!$this->taskConfig->getState('cloud-job-finished') && ($this->job->isSuccessful() || $this->job->isFailed())) {
            $this->taskConfig->setState('cloud-job-finished', time());
        }
        return $this->job;
    }
    private function getFinalProfile(string $output): string
    {
        // Memory usage: 353.94MB (peak: 1327.09MB), time: 160.17s
        $lines = array_reverse(explode("\n", $output));
        foreach ($lines as $line) {
            if (\false !== $pos = strpos($line, 'Memory usage:')) {
                return substr($line, $pos);
            }
        }
        return '';
    }
    private function getOutput(): string
    {
        if (null !== $this->output) {
            return $this->output;
        }
        $job = $this->getCurrentJob();
        if (null === $job) {
            return $this->output = self::CLOUD_ERROR;
        }
        try {
            $this->output = $this->cloud->getOutput($job);
            if (null === $this->output) {
                $this->output = self::CLOUD_ERROR;
            } else {
                if ($validationError = $this->taskConfig->getState('cloud-job-validation-error')) {
                    $this->output .= "\n–––––––––––––––––––––––––––––––––––––––––\n\n";
                    $this->output .= $validationError;
                }
                $this->taskConfig->setState('cloud-job-output', $this->output);
            }
            return $this->output;
        } catch (\Exception) {
            return $this->output = self::CLOUD_ERROR;
        }
    }
    /**
     * The composer.json of a cloud job must be identical to the local file. If that
     * is not the case, either an incorrect job is trying to be installed, or the
     * local composer.json was modified after the cloud job was started. Both cases
     * are not valid and unsupported.
     */
    private function validateComposerFiles(CloudJob $job): string
    {
        try {
            $remoteJson = JsonFile::parseJson($this->cloud->getComposerJson($job));
            $localJson = $this->environment->getComposerJsonWithConfig();
            if ($remoteJson !== $localJson) {
                $this->logger?->error('The composer.json file of the cloud job does not match the local composer.json', ['local' => $localJson, 'remote' => $remoteJson]);
                throw new \RuntimeException('The composer.json file of the cloud job does not match the local composer.json');
            }
            $remoteLock = $this->cloud->getComposerLock($job);
            $lockContent = JsonFile::parseJson($remoteLock);
            Validator::createFromComposer($this->environment->getComposer(\true))->validate($lockContent, $this->environment->getComposerLock());
        } catch (ValidationException $throwable) {
            $this->logger?->error('Failed validating composer.lock from cloud job: ' . $throwable->getMessage(), ['composerJson' => $remoteJson, 'composerLock' => $remoteLock]);
            throw $throwable;
        }
        return $remoteLock;
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Contao Manager.
 *
 * (c) Contao Association
 *
 * @license LGPL-3.0-or-later
 */
namespace _ContaoManager\Contao\ManagerApi\TaskOperation\Filesystem;

use _ContaoManager\Contao\ManagerApi\Composer\Environment;
use _ContaoManager\Contao\ManagerApi\I18n\Translator;
use _ContaoManager\Contao\ManagerApi\Task\TaskConfig;
use _ContaoManager\Contao\ManagerApi\TaskOperation\AbstractInlineOperation;
use _ContaoManager\Contao\ManagerApi\TaskOperation\ConsoleOutput;
use _ContaoManager\Symfony\Component\Filesystem\Filesystem;
use _ContaoManager\Symfony\Component\Security\Http\Attribute\IsGranted;
#[IsGranted('ROLE_INSTALL')]
class InstallUploadsOperation extends AbstractInlineOperation
{
    public function __construct(private readonly array $uploads, TaskConfig $config, private readonly Environment $environment, private readonly Translator $translator, private readonly Filesystem $filesystem)
    {
        parent::__construct($config);
    }
    public function getSummary(): string
    {
        return $this->translator->trans('taskoperation.install-uploads.summary');
    }
    public function getDetails(): string|null
    {
        $files = array_map(static fn($config) => $config['name'], $this->uploads);
        return implode(', ', $files);
    }
    public function getConsole(): ConsoleOutput
    {
        $console = new ConsoleOutput();
        if (!$this->isSuccessful()) {
            return $console;
        }
        $installed = $this->taskConfig->getState($this->getName() . '.files');
        if (!empty($installed)) {
            $console->add(implode('', array_map(fn($upload): string => '- ' . $this->translator->trans('taskoperation.install-uploads.console', $upload), $installed)));
        }
        return $this->addConsoleOutput($console);
    }
    protected function doRun(): bool
    {
        $installed = [];
        foreach ($this->uploads as $config) {
            $target = basename((string) $config['package']['dist']['url']);
            // Ignore if a file is already installed, so it's not deleted on failed operation
            if ($this->filesystem->exists($this->environment->getArtifactDir() . '/' . $target)) {
                continue;
            }
            $this->filesystem->copy($this->environment->getUploadDir() . '/' . $config['id'], $this->environment->getArtifactDir() . '/' . $target);
            $installed[$target] = ['name' => $target, 'package' => $config['package']['name'], 'version' => $config['package']['version']];
        }
        $this->taskConfig->setState($this->getName() . '.files', $installed);
        return \true;
    }
    protected function getName(): string
    {
        return 'install-uploads';
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Contao Manager.
 *
 * (c) Contao Association
 *
 * @license LGPL-3.0-or-later
 */
namespace _ContaoManager\Contao\ManagerApi\TaskOperation\Filesystem;

use _ContaoManager\Contao\ManagerApi\Composer\Environment;
use _ContaoManager\Contao\ManagerApi\I18n\Translator;
use _ContaoManager\Contao\ManagerApi\Task\TaskConfig;
use _ContaoManager\Contao\ManagerApi\TaskOperation\AbstractInlineOperation;
use _ContaoManager\Symfony\Component\Filesystem\Exception\IOException;
use _ContaoManager\Symfony\Component\Filesystem\Filesystem;
use _ContaoManager\Symfony\Component\Security\Http\Attribute\IsGranted;
#[IsGranted('ROLE_INSTALL')]
class RemoveArtifactsOperation extends AbstractInlineOperation
{
    public function __construct(private readonly array $files, TaskConfig $taskConfig, private readonly Environment $environment, private readonly Translator $translator, private readonly Filesystem $filesystem)
    {
        parent::__construct($taskConfig);
    }
    public function getSummary(): string
    {
        return $this->translator->trans('taskoperation.remove-artifacts.summary');
    }
    public function getDetails(): string|null
    {
        return implode(', ', $this->files);
    }
    protected function doRun(): bool
    {
        foreach ($this->files as $file) {
            try {
                $this->filesystem->remove($this->environment->getArtifactDir() . '/' . $file);
            } catch (IOException) {
                // Ignore if file could not be deleted
            }
        }
        return \true;
    }
    protected function getName(): string
    {
        return 'remove-artifacts';
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Contao Manager.
 *
 * (c) Contao Association
 *
 * @license LGPL-3.0-or-later
 */
namespace _ContaoManager\Contao\ManagerApi\TaskOperation\Filesystem;

use _ContaoManager\Contao\ManagerApi\Composer\Environment;
use _ContaoManager\Contao\ManagerApi\Task\TaskConfig;
use _ContaoManager\Contao\ManagerApi\TaskOperation\AbstractInlineOperation;
use _ContaoManager\Symfony\Component\Filesystem\Filesystem;
use _ContaoManager\Symfony\Component\Security\Http\Attribute\IsGranted;
#[IsGranted('ROLE_UPDATE')]
class RemoveVendorOperation extends AbstractInlineOperation
{
    public function __construct(TaskConfig $taskConfig, private readonly Environment $environment, private readonly Filesystem $filesystem)
    {
        parent::__construct($taskConfig);
    }
    public function getSummary(): string
    {
        return 'rm -rf vendor';
    }
    protected function doRun(): bool
    {
        $this->filesystem->remove($this->environment->getVendorDir());
        return \true;
    }
    protected function getName(): string
    {
        return 'remove-vendor';
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Contao Manager.
 *
 * (c) Contao Association
 *
 * @license LGPL-3.0-or-later
 */
namespace _ContaoManager\Contao\ManagerApi\TaskOperation\Filesystem;

use _ContaoManager\Contao\ManagerApi\Composer\Environment;
use _ContaoManager\Contao\ManagerApi\Config\UploadsConfig;
use _ContaoManager\Contao\ManagerApi\I18n\Translator;
use _ContaoManager\Contao\ManagerApi\Task\TaskConfig;
use _ContaoManager\Contao\ManagerApi\TaskOperation\AbstractInlineOperation;
use _ContaoManager\Symfony\Component\Filesystem\Exception\IOException;
use _ContaoManager\Symfony\Component\Filesystem\Filesystem;
use _ContaoManager\Symfony\Component\Security\Http\Attribute\IsGranted;
#[IsGranted('ROLE_INSTALL')]
class RemoveUploadsOperation extends AbstractInlineOperation
{
    public function __construct(private readonly array $uploads, private readonly UploadsConfig $uploadsConfig, TaskConfig $taskConfig, private readonly Environment $environment, private readonly Translator $translator, private readonly Filesystem $filesystem)
    {
        parent::__construct($taskConfig);
    }
    public function getSummary(): string
    {
        return $this->translator->trans('taskoperation.remove-uploads.summary');
    }
    public function getDetails(): string|null
    {
        $files = array_map(static fn($config) => $config['name'], $this->uploads);
        return implode(', ', $files);
    }
    protected function doRun(): bool
    {
        foreach ($this->uploads as $config) {
            $this->uploadsConfig->remove($config['id']);
            try {
                $this->filesystem->remove($this->environment->getUploadDir() . '/' . $config['id']);
            } catch (IOException) {
                // Ignore if file could not be deleted
            }
        }
        return \true;
    }
    protected function getName(): string
    {
        return 'remove-uploads';
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Contao Manager.
 *
 * (c) Contao Association
 *
 * @license LGPL-3.0-or-later
 */
namespace _ContaoManager\Contao\ManagerApi\TaskOperation\Filesystem;

use _ContaoManager\Contao\ManagerApi\ApiKernel;
use _ContaoManager\Contao\ManagerApi\Task\TaskConfig;
use _ContaoManager\Contao\ManagerApi\TaskOperation\AbstractInlineOperation;
use _ContaoManager\Symfony\Component\Filesystem\Filesystem;
use _ContaoManager\Symfony\Component\Security\Http\Attribute\IsGranted;
#[IsGranted('ROLE_UPDATE')]
class RemoveCacheOperation extends AbstractInlineOperation
{
    public function __construct(private readonly string $environment, private readonly ApiKernel $kernel, TaskConfig $taskConfig, private readonly Filesystem $filesystem, private readonly string $name = 'remove-cache')
    {
        parent::__construct($taskConfig);
    }
    public function getSummary(): string
    {
        return 'rm -rf var/cache/' . $this->environment;
    }
    protected function doRun(): bool
    {
        $this->filesystem->remove($this->getCacheDir());
        return \true;
    }
    protected function getName(): string
    {
        return $this->name . '@' . $this->getCacheDir();
    }
    /**
     * Gets the Contao cache directory for current environment.
     */
    private function getCacheDir(): string
    {
        return $this->kernel->getProjectDir() . '/var/cache/' . $this->environment;
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Contao Manager.
 *
 * (c) Contao Association
 *
 * @license LGPL-3.0-or-later
 */
namespace _ContaoManager\Contao\ManagerApi\TaskOperation\Manager;

use _ContaoManager\Contao\ManagerApi\I18n\Translator;
use _ContaoManager\Contao\ManagerApi\System\SelfUpdate;
use _ContaoManager\Contao\ManagerApi\Task\TaskConfig;
use _ContaoManager\Contao\ManagerApi\TaskOperation\AbstractInlineOperation;
use _ContaoManager\Symfony\Component\Security\Http\Attribute\IsGranted;
#[IsGranted('ROLE_UPDATE')]
class SelfUpdateOperation extends AbstractInlineOperation
{
    public function __construct(private readonly SelfUpdate $updater, TaskConfig $taskConfig, private readonly Translator $translator)
    {
        parent::__construct($taskConfig);
    }
    public function getSummary(): string
    {
        return basename(\Phar::running()) . ' self-update';
    }
    public function getDetails(): string|null
    {
        if ($this->isSuccessful()) {
            return $this->translator->trans('taskoperation.self-update.success', ['new' => $this->updater->getOldVersion()]);
        }
        return $this->translator->trans('taskoperation.self-update.detail', ['old' => $this->updater->getOldVersion(), 'new' => $this->updater->getNewVersion()]);
    }
    protected function doRun(): bool
    {
        return $this->updater->update();
    }
    protected function getName(): string
    {
        return 'self-update';
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Contao Manager.
 *
 * (c) Contao Association
 *
 * @license LGPL-3.0-or-later
 */
namespace _ContaoManager\Contao\ManagerApi\TaskOperation;

use _ContaoManager\Contao\ManagerApi\Task\TaskConfig;
use _ContaoManager\Contao\ManagerApi\Task\TaskStatus;
use _ContaoManager\Psr\Log\LoggerAwareInterface;
use _ContaoManager\Psr\Log\LoggerAwareTrait;
abstract class AbstractInlineOperation implements TaskOperationInterface, LoggerAwareInterface
{
    use LoggerAwareTrait;
    public function __construct(protected TaskConfig $taskConfig)
    {
    }
    public function getDetails(): string|null
    {
        return '';
    }
    public function getConsole(): ConsoleOutput
    {
        return $this->addConsoleOutput(new ConsoleOutput());
    }
    public function isStarted(): bool
    {
        return null !== $this->taskConfig->getState($this->getName());
    }
    public function isRunning(): bool
    {
        return TaskStatus::STATUS_ACTIVE === $this->taskConfig->getState($this->getName());
    }
    public function isSuccessful(): bool
    {
        return TaskStatus::STATUS_COMPLETE === $this->taskConfig->getState($this->getName());
    }
    public function hasError(): bool
    {
        return TaskStatus::STATUS_ERROR === $this->taskConfig->getState($this->getName());
    }
    public function continueOnError(): bool
    {
        return \false;
    }
    public function run(): void
    {
        // Inline task should never need more than 60secs to complete. Assume something
        // went wrong.
        $started = (int) $this->taskConfig->getState($this->getName() . '.started', 0);
        if ($started > 0 && $started + 60 < time()) {
            $this->taskConfig->setState($this->getName(), TaskStatus::STATUS_ERROR);
            $this->taskConfig->setState($this->getName() . '.error', 'Inline operation did not complete within 60 seconds.');
            return;
        }
        // Do not start the inline task again if it has been started
        if ($this->isStarted()) {
            return;
        }
        $this->taskConfig->setState($this->getName(), TaskStatus::STATUS_ACTIVE);
        $this->taskConfig->setState($this->getName() . '.started', time());
        $success = null;
        register_shutdown_function(function () use (&$success): void {
            if (null === $success) {
                $this->taskConfig->setState($this->getName(), TaskStatus::STATUS_ERROR);
            }
        });
        try {
            $success = $this->doRun();
        } catch (\Throwable $throwable) {
            $this->taskConfig->setState($this->getName() . '.error', $throwable->getMessage());
            $success = \false;
        }
        if ($success) {
            $this->taskConfig->setState($this->getName(), TaskStatus::STATUS_COMPLETE);
        } else {
            $this->taskConfig->setState($this->getName(), TaskStatus::STATUS_ERROR);
        }
    }
    public function abort(): void
    {
        if ($this->isRunning()) {
            $this->taskConfig->setState($this->getName(), TaskStatus::STATUS_ERROR);
        }
    }
    public function delete(): void
    {
        // Do nothing
    }
    /**
     * Adds the exception message to the console output.
     */
    protected function addConsoleOutput(ConsoleOutput $console): ConsoleOutput
    {
        if ($error = $this->taskConfig->getState($this->getName() . '.error')) {
            $console->add((string) $error);
        }
        return $console;
    }
    /**
     * Gets the name to store this operation state in the config file.
     */
    abstract protected function getName(): string;
    /**
     * Executes the operation and returns whether it was successful.
     *
     * @throws \Exception
     */
    abstract protected function doRun(): bool;
}
<?php

declare (strict_types=1);
/*
 * This file is part of Contao Manager.
 *
 * (c) Contao Association
 *
 * @license LGPL-3.0-or-later
 */
namespace _ContaoManager\Contao\ManagerApi\TaskOperation;

interface SponsoredOperationInterface
{
    public function getSponsor(): array|null;
}
<?php

declare (strict_types=1);
/*
 * This file is part of Contao Manager.
 *
 * (c) Contao Association
 *
 * @license LGPL-3.0-or-later
 */
namespace _ContaoManager\Contao\ManagerApi\TaskOperation;

class ConsoleOutput implements \Stringable
{
    private string $output = '';
    public function __toString(): string
    {
        return $this->output;
    }
    /**
     * Adds output to the console log.
     */
    public function add(string $output, string|null $title = null): self
    {
        if (null !== $title) {
            $output = \sprintf("%s\n\n%s", $title, $output);
        }
        if ('' === $output) {
            return $this;
        }
        if ('' !== $this->output) {
            $output = $this->output . "\n\n" . $output;
        }
        $this->output = $output;
        return $this;
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Contao Manager.
 *
 * (c) Contao Association
 *
 * @license LGPL-3.0-or-later
 */
namespace _ContaoManager\Contao\ManagerApi\TaskOperation;

use _ContaoManager\Contao\ManagerApi\Process\Forker\InlineForker;
use _ContaoManager\Contao\ManagerApi\Process\ProcessController;
use _ContaoManager\Psr\Log\LoggerAwareInterface;
use _ContaoManager\Psr\Log\LoggerAwareTrait;
use _ContaoManager\Symfony\Component\Process\Process;
abstract class AbstractProcessOperation implements TaskOperationInterface, LoggerAwareInterface
{
    use LoggerAwareTrait;
    private const SIGNALS = [1 => 'SIGHUP', 2 => 'SIGINT', 3 => 'SIGQUIT', 9 => 'SIGKILL', 15 => 'SIGTERM'];
    private bool $abort = \false;
    public function __construct(protected readonly Process|ProcessController $process)
    {
    }
    public function getDetails(): string|null
    {
        return '';
    }
    public function getConsole(): ConsoleOutput
    {
        $console = new ConsoleOutput();
        if (!$this->process->isStarted()) {
            return $console;
        }
        $console->add($this->process->getOutput() . $this->getProcessError(), '$ ' . $this->process->getCommandLine());
        return $console;
    }
    public function isStarted(): bool
    {
        return $this->process->isStarted();
    }
    public function isRunning(): bool
    {
        return $this->process->isRunning();
    }
    public function isSuccessful(): bool
    {
        return $this->process->isSuccessful();
    }
    public function hasError(): bool
    {
        return $this->abort || $this->process->isTerminated() && $this->process->getExitCode() > 0;
    }
    public function continueOnError(): bool
    {
        return \false;
    }
    public function run(): void
    {
        if (!$this->process->isStarted()) {
            $this->process->start();
        }
    }
    public function abort(): void
    {
        $this->abort = \true;
        if ($this->isRunning()) {
            $this->process->stop();
        }
    }
    public function delete(): void
    {
        $this->process->delete();
    }
    protected function getProcessError(): string
    {
        $output = '';
        if ($this->process->isTerminated()) {
            $signal = '';
            if ($this->process->hasBeenSignaled()) {
                $signal = $this->getSignalText($this->process->getTermSignal());
            } elseif ($this->process->hasBeenStopped()) {
                $signal = $this->getSignalText($this->process->getStopSignal());
            }
            if ($this->process instanceof ProcessController && $this->process->getForker() instanceof InlineForker) {
                $output = <<<'OUTPUT'

# WARNING: INLINE PROCESS EXECUTION
# Background processes are not support by your server/shell.
# The operation might have be affected by script runtime (e.g. stop after 30 seconds).
#
OUTPUT;
            }
            $output .= \sprintf("\n# Process terminated with exit code %s\n# Result: %s%s\n", $this->process->getExitCode(), $this->process->getExitCodeText(), $signal);
        }
        return $output;
    }
    private function getSignalText(int|null $signal): string
    {
        if (isset(self::SIGNALS[$signal])) {
            return \sprintf(' [%s]', self::SIGNALS[$signal]);
        }
        return \sprintf(' [signal %s]', $signal);
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Contao Manager.
 *
 * (c) Contao Association
 *
 * @license LGPL-3.0-or-later
 */
namespace _ContaoManager\Contao\ManagerApi\TaskOperation\Contao;

use _ContaoManager\Contao\ManagerApi\Process\ConsoleProcessFactory;
use _ContaoManager\Contao\ManagerApi\Task\TaskConfig;
use _ContaoManager\Contao\ManagerApi\TaskOperation\AbstractInlineOperation;
use _ContaoManager\Symfony\Component\Security\Http\Attribute\IsGranted;
#[IsGranted('ROLE_UPDATE')]
class MaintenanceModeOperation extends AbstractInlineOperation
{
    public function __construct(TaskConfig $taskConfig, private readonly ConsoleProcessFactory $processFactory, private readonly string $state)
    {
        parent::__construct($taskConfig);
    }
    public function getSummary(): string
    {
        return 'vendor/bin/contao-console contao:maintenance-mode ' . $this->state;
    }
    public function continueOnError(): bool
    {
        return \true;
    }
    protected function getName(): string
    {
        return 'maintenance-' . $this->state;
    }
    protected function doRun(): bool
    {
        $process = $this->processFactory->createContaoConsoleProcess(['contao:maintenance-mode', $this->state, '--no-interaction']);
        $process->run();
        return $process->isSuccessful();
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Contao Manager.
 *
 * (c) Contao Association
 *
 * @license LGPL-3.0-or-later
 */
namespace _ContaoManager\Contao\ManagerApi\TaskOperation\Contao;

use _ContaoManager\Contao\ManagerApi\Process\ConsoleProcessFactory;
use _ContaoManager\Contao\ManagerApi\TaskOperation\AbstractProcessOperation;
use _ContaoManager\Symfony\Component\Security\Http\Attribute\IsGranted;
#[IsGranted('ROLE_UPDATE')]
class BackupCreateOperation extends AbstractProcessOperation
{
    public function __construct(ConsoleProcessFactory $processFactory, string $processId = 'backup-create')
    {
        try {
            parent::__construct($processFactory->restoreBackgroundProcess($processId));
        } catch (\Exception) {
            parent::__construct($processFactory->createContaoConsoleBackgroundProcess(['contao:backup:create'], $processId));
        }
    }
    public function getSummary(): string
    {
        return 'vendor/bin/contao-console contao:backup:create';
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Contao Manager.
 *
 * (c) Contao Association
 *
 * @license LGPL-3.0-or-later
 */
namespace _ContaoManager\Contao\ManagerApi\TaskOperation\Contao;

use _ContaoManager\Contao\ManagerApi\Process\ConsoleProcessFactory;
use _ContaoManager\Contao\ManagerApi\TaskOperation\AbstractProcessOperation;
use _ContaoManager\Symfony\Component\Security\Http\Attribute\IsGranted;
#[IsGranted('ROLE_UPDATE')]
class CacheWarmupOperation extends AbstractProcessOperation
{
    public function __construct(ConsoleProcessFactory $processFactory, string $environment, string $processId = 'cache-warmup')
    {
        try {
            parent::__construct($processFactory->restoreBackgroundProcess($processId));
        } catch (\Exception) {
            parent::__construct($processFactory->createContaoConsoleBackgroundProcess(['cache:warmup', '--env=' . $environment], $processId));
        }
    }
    public function getSummary(): string
    {
        return 'vendor/bin/contao-console cache:warmup';
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Contao Manager.
 *
 * (c) Contao Association
 *
 * @license LGPL-3.0-or-later
 */
namespace _ContaoManager\Contao\ManagerApi\TaskOperation\Contao;

use _ContaoManager\Contao\ManagerApi\ApiKernel;
use _ContaoManager\Contao\ManagerApi\Composer\Environment;
use _ContaoManager\Contao\ManagerApi\Task\TaskConfig;
use _ContaoManager\Contao\ManagerApi\TaskOperation\AbstractInlineOperation;
use _ContaoManager\Symfony\Component\Filesystem\Filesystem;
use _ContaoManager\Symfony\Component\Security\Http\Attribute\IsGranted;
#[IsGranted('ROLE_INSTALL')]
class CreateContaoOperation extends AbstractInlineOperation
{
    private const SUPPORTED_VERSIONS = ['4.13', '5.3', '5.7'];
    private readonly string|null $version;
    private string|null $publicDir;
    public function __construct(TaskConfig $taskConfig, private readonly Environment $environment, ApiKernel $kernel, private readonly Filesystem $filesystem)
    {
        parent::__construct($taskConfig);
        $this->version = $taskConfig->getOption('version');
        $this->publicDir = $taskConfig->getState('public-dir');
        if (!\in_array($this->version, self::SUPPORTED_VERSIONS, \true)) {
            throw new \InvalidArgumentException('Unsupported Contao version');
        }
        if (null !== $this->publicDir) {
            return;
        }
        // We must use the kernel at runtime here because the parameter is not dynamic
        // @noinspection ProjectDirParameter */
        if ($kernel->getProjectDir() === $kernel->getPublicDir()) {
            throw new \RuntimeException('Cannot install without a public directory.');
        }
        $taskConfig->setState('public-dir', $this->publicDir = $kernel->getPublicDir());
    }
    public function getSummary(): string
    {
        return 'composer create-project contao/managed-edition:' . $this->version . ' --no-install';
    }
    protected function getName(): string
    {
        return 'create-project';
    }
    protected function doRun(): bool
    {
        $protected = [$this->environment->getJsonFile(), $this->environment->getLockFile(), $this->environment->getVendorDir()];
        if ($this->filesystem->exists($protected)) {
            throw new \RuntimeException('Cannot install into existing application');
        }
        $this->filesystem->dumpFile($this->environment->getJsonFile(), $this->generateComposerJson($this->taskConfig->getOption('version'), (bool) $this->taskConfig->getOption('core-only', \false)));
        return \true;
    }
    private function generateComposerJson(string $version, bool $coreOnly = \false): string
    {
        $coreBundle = '';
        if ($this->isDevVersion($version)) {
            $version .= '.x-dev';
            $coreBundle = ',
        "contao/core-bundle": "' . $version . '"';
        } else {
            $version .= '.*';
        }
        if ($coreOnly) {
            $require = <<<JSON
        "contao/conflicts": "*@dev",
        "contao/manager-bundle": "{$version}"{$coreBundle}
JSON;
        } else {
            $require = <<<JSON
        "contao/conflicts": "*@dev",
        "contao/manager-bundle": "{$version}"{$coreBundle},
        "contao/calendar-bundle": "{$version}",
        "contao/comments-bundle": "{$version}",
        "contao/faq-bundle": "{$version}",
        "contao/listing-bundle": "{$version}",
        "contao/news-bundle": "{$version}",
        "contao/newsletter-bundle": "{$version}"
JSON;
        }
        // https://github.com/contao/contao-manager/issues/627 Still needed since we
        // allow Contao 4.9 for PHP < 7.4
        if (version_compare($version, '4.12', '>=')) {
            $publicDir = basename((string) $this->publicDir);
            $script = '@php vendor/bin/contao-setup';
        } else {
            $publicDir = 'web';
            $script = 'Contao\\\\ManagerBundle\\\\Composer\\\\ScriptHandler::initializeApplication';
        }
        return <<<JSON
{
    "type": "project",
    "require": {
{$require}
    },
    "extra": {
        "public-dir": "{$publicDir}",
        "contao-component-dir": "assets"
    },
    "scripts": {
        "post-install-cmd": [
            "{$script}"
        ],
        "post-update-cmd": [
            "{$script}"
        ]
    }
}
JSON;
    }
    private function isDevVersion(string $version): bool
    {
        return \false;
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Contao Manager.
 *
 * (c) Contao Association
 *
 * @license LGPL-3.0-or-later
 */
namespace _ContaoManager\Contao\ManagerApi\TaskOperation\Contao;

use _ContaoManager\Contao\ManagerApi\Process\ConsoleProcessFactory;
use _ContaoManager\Contao\ManagerApi\TaskOperation\AbstractProcessOperation;
use _ContaoManager\Symfony\Component\Security\Http\Attribute\IsGranted;
#[IsGranted('ROLE_UPDATE')]
class BackupRestoreOperation extends AbstractProcessOperation
{
    public function __construct(ConsoleProcessFactory $processFactory, private readonly string $file, string $processId = 'backup-restore')
    {
        try {
            parent::__construct($processFactory->restoreBackgroundProcess($processId));
        } catch (\Exception) {
            parent::__construct($processFactory->createContaoConsoleBackgroundProcess(['contao:backup:restore', $this->file], $processId));
        }
    }
    public function getSummary(): string
    {
        return 'vendor/bin/contao-console contao:backup:restore ' . $this->file;
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Contao Manager.
 *
 * (c) Contao Association
 *
 * @license LGPL-3.0-or-later
 */
namespace _ContaoManager\Contao\ManagerApi\TaskOperation\Contao;

use _ContaoManager\Contao\ManagerApi\Process\ConsoleProcessFactory;
use _ContaoManager\Contao\ManagerApi\TaskOperation\AbstractProcessOperation;
use _ContaoManager\Symfony\Component\Security\Http\Attribute\IsGranted;
#[IsGranted('ROLE_UPDATE')]
class CacheClearOperation extends AbstractProcessOperation
{
    public function __construct(ConsoleProcessFactory $processFactory, string $environment, string $processId = 'cache-clear')
    {
        try {
            parent::__construct($processFactory->restoreBackgroundProcess($processId));
        } catch (\Exception) {
            parent::__construct($processFactory->createContaoConsoleBackgroundProcess(['cache:clear', '--env=' . $environment, '--no-warmup'], $processId));
        }
    }
    public function getSummary(): string
    {
        return 'vendor/bin/contao-console cache:clear --no-warmup';
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Contao Manager.
 *
 * (c) Contao Association
 *
 * @license LGPL-3.0-or-later
 */
namespace _ContaoManager\Contao\ManagerApi\TaskOperation;

interface TaskOperationInterface
{
    public function getSummary(): string;
    public function getDetails(): string|null;
    public function getConsole(): ConsoleOutput;
    public function isStarted(): bool;
    public function isRunning(): bool;
    public function isSuccessful(): bool;
    public function hasError(): bool;
    public function continueOnError(): bool;
    public function run(): void;
    public function abort(): void;
    public function delete(): void;
}
<?php

declare (strict_types=1);
/*
 * This file is part of Contao Manager.
 *
 * (c) Contao Association
 *
 * @license LGPL-3.0-or-later
 */
namespace _ContaoManager\Contao\ManagerApi\Composer;

use Composer\Json\JsonFile;
use _ContaoManager\Contao\ManagerApi\System\Request;
use _ContaoManager\Psr\Log\LoggerAwareInterface;
use _ContaoManager\Psr\Log\LoggerAwareTrait;
use _ContaoManager\Symfony\Component\DependencyInjection\Attribute\AutoconfigureTag;
#[AutoconfigureTag('monolog.logger', ['channel' => 'tasks'])]
class CloudResolver implements LoggerAwareInterface
{
    use LoggerAwareTrait;
    private const API_URL = 'https://www.composer-resolver.cloud';
    public function __construct(private Request $request)
    {
    }
    /**
     * Creates a Cloud job for given composer changes.
     */
    public function createJob(CloudChanges $changes, Environment $environment): CloudJob
    {
        $environment->reset();
        $data = ['composerJson' => $environment->getComposerJsonWithConfig(), 'composerLock' => $environment->getComposerLock(), 'platform' => $environment->getPlatformPackages(), 'localPackages' => $environment->getLocalPackages()];
        $command = $changes->getUpdates();
        $command[] = '--with-dependencies';
        $command[] = '--profile';
        if ($environment->isDebug()) {
            $command[] = '-vvv';
        }
        $body = json_encode($data);
        $headers = ['Composer-Resolver-Client: contao', 'Composer-Resolver-Command: ' . implode(' ', $command)];
        if (null !== $this->logger) {
            $this->logger->info('Creating Composer Cloud job', ['headers' => $headers, 'body' => $body]);
        }
        $content = $this->request->postJson(self::API_URL . '/jobs', $body, $headers, $statusCode);
        switch ($statusCode) {
            case 200:
            case 201:
            case 202:
                // Location redirect to fetch the job content
                return new CloudJob(JsonFile::parseJson($content));
            case 400:
                throw new CloudException('Composer Resolver did not accept the API call', $statusCode, $content, $body);
            case 503:
                throw new CloudException('Too many jobs on the Composer Resolver queue.', $statusCode, $content, $body);
            default:
                throw $this->createUnknownResponseException($statusCode, $content, $body);
        }
    }
    /**
     * Gets job information from the Composer Cloud.
     */
    public function getJob(string $jobId): CloudJob|null
    {
        if ('' === $jobId) {
            return null;
        }
        $content = $this->request->getJson(self::API_URL . '/jobs/' . $jobId, ['Composer-Resolver-Client: contao'], $statusCode);
        return match ($statusCode) {
            200, 202 => new CloudJob(JsonFile::parseJson($content)),
            default => throw $this->createUnknownResponseException($statusCode, $content),
        };
    }
    /**
     * Deletes a cloud job and returns whether it was successful.
     */
    public function deleteJob(string $jobId): bool
    {
        if ('' === $jobId) {
            return \false;
        }
        $content = $this->request->deleteJson(self::API_URL . '/jobs/' . $jobId, ['Composer-Resolver-Client: contao'], $statusCode);
        if (204 === $statusCode) {
            return \true;
        }
        throw $this->createUnknownResponseException($statusCode, $content);
    }
    /**
     * Gets the composer.json file.
     */
    public function getComposerJson(CloudJob $job): string
    {
        return $this->getContent($job->getLink(CloudJob::LINK_JSON));
    }
    /**
     * Gets the composer.lock file or null if the cloud job was not successful.
     */
    public function getComposerLock(CloudJob $job): string|null
    {
        if (!$job->isSuccessful()) {
            return null;
        }
        return $this->getContent($job->getLink(CloudJob::LINK_LOCK));
    }
    /**
     * Gets the console output for a cloud job.
     */
    public function getOutput(CloudJob $job): string|null
    {
        if ($job->isQueued()) {
            return null;
        }
        return $this->getContent($job->getLink(CloudJob::LINK_OUTPUT));
    }
    private function getContent(string $link): string
    {
        $content = $this->request->getJson(self::API_URL . $link, ['Composer-Resolver-Client: contao'], $statusCode, \true);
        if (200 === $statusCode) {
            return $content;
        }
        throw $this->createUnknownResponseException($statusCode, $content);
    }
    private function createUnknownResponseException(int|null $statusCode, string|null $responseBody, string|null $requestBody = null): CloudException
    {
        return new CloudException('Composer Resolver returned an unexpected status code', (int) $statusCode, (string) $responseBody, $requestBody);
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Contao Manager.
 *
 * (c) Contao Association
 *
 * @license LGPL-3.0-or-later
 */
namespace _ContaoManager\Contao\ManagerApi\Composer;

class CloudChanges
{
    private array $require = [];
    private array $remove = [];
    private array $updates = [];
    private bool $dryRun = \false;
    public function requirePackage(string $packageName, string|null $version = null): void
    {
        unset($this->remove[$packageName]);
        $this->require[$packageName] = $version ? $packageName . '=' . $version : $packageName;
        $this->addUpdate($packageName);
    }
    public function getRequiredPackages(): array
    {
        return $this->require;
    }
    public function removePackage(string $packageName): void
    {
        unset($this->require[$packageName]);
        $this->remove[$packageName] = $packageName;
        $this->addUpdate($packageName);
    }
    public function getRemovedPackages(): array
    {
        return $this->remove;
    }
    public function setUpdates(array $updates): void
    {
        $this->updates = [];
        foreach ($updates as $packageName) {
            $this->updates[$packageName] = $packageName;
        }
    }
    public function addUpdate(string $packageName): void
    {
        $this->updates[$packageName] = $packageName;
    }
    public function getUpdates(): array
    {
        return array_values($this->updates);
    }
    public function setDryRun(bool $dryRun): void
    {
        $this->dryRun = $dryRun;
    }
    public function getDryRun(): bool
    {
        return $this->dryRun;
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Contao Manager.
 *
 * (c) Contao Association
 *
 * @license LGPL-3.0-or-later
 */
namespace _ContaoManager\Contao\ManagerApi\Composer;

class CloudJob implements \JsonSerializable
{
    public const STATUS_QUEUED = 'queued';
    public const STATUS_PROCESSING = 'processing';
    public const STATUS_FINISHED = 'finished';
    public const STATUS_ERROR = 'finished_with_errors';
    public const LINK_JSON = 'composerJson';
    public const LINK_LOCK = 'composerLock';
    public const LINK_OUTPUT = 'composerOutput';
    public function __construct(private readonly array $result)
    {
    }
    public function getId(): string
    {
        return $this->result['jobId'];
    }
    public function getStatus(): string
    {
        return $this->result['status'];
    }
    public function getLink(string $name): string|null
    {
        return $this->result['links'][$name] ?? null;
    }
    public function getSponsor(): array
    {
        return $this->result['sponsoredBy'];
    }
    public function getWaitingTime(): int
    {
        if (self::STATUS_QUEUED !== $this->result['status']) {
            return 0;
        }
        $currentPos = $this->result['queuePosition'] ?: $this->result['stats']['numberOfJobsInQueue'];
        return (int) round($currentPos * $this->result['stats']['averageProcessingTimeInMs'] / 1000 / max($this->result['stats']['numberOfWorkers'], 1));
    }
    public function getJobsInQueue(): int
    {
        return (int) $this->result['queuePosition'] ?: $this->result['stats']['numberOfJobsInQueue'];
    }
    public function getWorkers(): int
    {
        return (int) $this->result['stats']['numberOfWorkers'];
    }
    public function getVersion(): string
    {
        return isset($this->result['stats']['appVersion']) ? 'v' . $this->result['stats']['appVersion'] : '';
    }
    public function isQueued(): bool
    {
        return self::STATUS_QUEUED === $this->getStatus();
    }
    public function isProcessing(): bool
    {
        return self::STATUS_PROCESSING === $this->getStatus();
    }
    public function isSuccessful(): bool
    {
        return self::STATUS_FINISHED === $this->getStatus();
    }
    public function isFailed(): bool
    {
        return self::STATUS_ERROR === $this->getStatus();
    }
    public function jsonSerialize(): array
    {
        return $this->result;
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Contao Manager.
 *
 * (c) Contao Association
 *
 * @license LGPL-3.0-or-later
 */
namespace _ContaoManager\Contao\ManagerApi\Composer;

class CloudException extends \RuntimeException
{
    public function __construct(string $message, int $code, private readonly string $responseBody, private readonly string|null $requestBody = null)
    {
        parent::__construct($message, $code);
    }
    /**
     * Returns the response status code or general error 500.
     */
    public function getStatusCode(): int
    {
        return $this->getCode();
    }
    /**
     * Returns the Cloud error message or the exception message as fallback.
     */
    public function getErrorMessage(): string
    {
        $message = $this->getMessage() . "\n\nResponse:\n" . $this->responseBody;
        if ($this->requestBody) {
            $message .= "\n\nRequest:\n" . $this->requestBody;
        }
        return $message;
    }
    public function isInvalid(): bool
    {
        return $this->getStatusCode() < 100 || $this->getStatusCode() >= 600;
    }
    public function isInformational(): bool
    {
        return $this->getStatusCode() >= 100 && $this->getStatusCode() < 200;
    }
    public function isSuccessful(): bool
    {
        return $this->getStatusCode() >= 200 && $this->getStatusCode() < 300;
    }
    public function isRedirection(): bool
    {
        return $this->getStatusCode() >= 300 && $this->getStatusCode() < 400;
    }
    public function isClientError(): bool
    {
        return $this->getStatusCode() >= 400 && $this->getStatusCode() < 500;
    }
    public function isServerError(): bool
    {
        return $this->getStatusCode() >= 500 && $this->getStatusCode() < 600;
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Contao Manager.
 *
 * (c) Contao Association
 *
 * @license LGPL-3.0-or-later
 */
namespace _ContaoManager\Contao\ManagerApi\Composer;

use Composer\Composer;
use Composer\Factory;
use Composer\IO\NullIO;
use Composer\Json\JsonFile;
use Composer\Package\Dumper\ArrayDumper;
use Composer\Repository\ArtifactRepository;
use Composer\Repository\PathRepository;
use Composer\Repository\PlatformRepository;
use Composer\Repository\RepositoryInterface;
use Composer\Repository\RepositoryUtils;
use _ContaoManager\Contao\ManagerApi\ApiKernel;
use _ContaoManager\Contao\ManagerApi\Config\ComposerConfig;
use _ContaoManager\Contao\ManagerApi\Config\ManagerConfig;
use _ContaoManager\Contao\ManagerApi\System\Request;
use _ContaoManager\Psr\Log\LoggerInterface;
use _ContaoManager\Symfony\Component\Filesystem\Filesystem;
use _ContaoManager\Symfony\Component\Finder\Finder;
class Environment
{
    private Composer|null $composer = null;
    private \Composer\Util\Filesystem|null $composerFs = null;
    public function __construct(private readonly ApiKernel $kernel, private readonly ManagerConfig $managerConfig, private readonly ComposerConfig $composerConfig, private readonly Filesystem $filesystem, private readonly Request $request, private readonly LoggerInterface|null $logger = null)
    {
    }
    /**
     * Resets the Composer object (necessary after modifying Composer files).
     */
    public function reset(): void
    {
        $this->composer = null;
    }
    /**
     * Returns whether debug mode is activated.
     */
    public function isDebug(): bool
    {
        return $this->kernel->isDebug();
    }
    /**
     * Gets path to the directory where all Contao Manager related information is stored.
     */
    public function getBackupDir(): string
    {
        return $this->kernel->getConfigDir();
    }
    public function getBackupPaths(): array
    {
        return [$this->getJsonFile() => \sprintf('%s/%s~', $this->getBackupDir(), basename($this->getJsonFile())), $this->getLockFile() => \sprintf('%s/%s~', $this->getBackupDir(), basename($this->getLockFile()))];
    }
    public function createBackup(): bool
    {
        if (!$this->filesystem->exists($this->getJsonFile())) {
            if (null !== $this->logger) {
                $this->logger->info('Cannot create composer file backup, source JSON does not exist', ['file' => $this->getJsonFile()]);
            }
            return \false;
        }
        if (null !== $this->logger) {
            $this->logger->info('Creating backup of composer files');
        }
        foreach ($this->getBackupPaths() as $source => $target) {
            if ($this->filesystem->exists($source)) {
                $this->filesystem->copy($source, $target, \true);
                if (null !== $this->logger) {
                    $this->logger->info(\sprintf('Copied "%s" to "%s"', $source, $target));
                }
            } elseif (null !== $this->logger) {
                $this->logger->info(\sprintf('File "%s" does not exist', $source));
            }
        }
        return \true;
    }
    public function restoreBackup(): bool
    {
        if (null !== $this->logger) {
            $this->logger->info('Restoring backup of composer files');
        }
        foreach (array_flip($this->getBackupPaths()) as $source => $target) {
            if ($this->filesystem->exists($source)) {
                $this->filesystem->copy($source, $target, \true);
                $this->filesystem->remove($source);
                if (null !== $this->logger) {
                    $this->logger->info(\sprintf('Copied "%s" to "%s"', $source, $target));
                }
            } elseif (null !== $this->logger) {
                $this->logger->info(\sprintf('File "%s" does not exist', $source));
            }
        }
        return \true;
    }
    /**
     * Gets path to the composer.json file in the Contao root.
     */
    public function getJsonFile(): string
    {
        return $this->kernel->getProjectDir() . \DIRECTORY_SEPARATOR . 'composer.json';
    }
    /**
     * Gets path to the composer.lock file in the Contao root.
     */
    public function getLockFile(): string
    {
        return $this->kernel->getProjectDir() . \DIRECTORY_SEPARATOR . 'composer.lock';
    }
    /**
     * Gets the directory where Composer installs its packages to.
     */
    public function getVendorDir(): string
    {
        return $this->kernel->getProjectDir() . \DIRECTORY_SEPARATOR . 'vendor';
    }
    /**
     * Gets the directory where uploads are stored to. These are temporary and only
     * until they are installed as artifact or provider.
     */
    public function getUploadDir(): string
    {
        $dir = $this->kernel->getConfigDir() . '/uploads';
        $this->filesystem->mkdir($dir);
        return $dir;
    }
    /**
     * Gets the path where artifacts are installed to. Artifacts are ZIP files that
     * contain Composer packages.
     *
     * @see https://getcomposer.org/doc/05-repositories.md#artifact
     */
    public function getArtifactDir(): string
    {
        $dir = $this->kernel->getConfigDir() . '/packages';
        $this->filesystem->mkdir($dir);
        return $dir;
    }
    /**
     * Gets list of file names in the artifacts directory.
     */
    public function getArtifacts(): array
    {
        $files = [];
        $finder = (new Finder())->files()->depth(0)->in($this->getArtifactDir());
        foreach ($finder->getIterator() as $file) {
            $files[] = $file->getFilename();
        }
        return $files;
    }
    /**
     * Gets the Composer instance.
     */
    public function getComposer(bool $reload = \false): Composer
    {
        $this->composerConfig->allowPlugins();
        if (null === $this->composer || $reload) {
            $this->composer = Factory::create(new NullIO(), $this->getJsonFile());
            $this->fixManagerPlugin();
        }
        return $this->composer;
    }
    /**
     * Gets whether the Cloud resolver is enabled in the Manager configuration.
     */
    public function useCloudResolver(): bool
    {
        return !$this->managerConfig->get('disable_cloud', \false);
    }
    public function getComposerJsonFile(): JsonFile
    {
        $file = $this->getComposer()->getConfig()->getConfigSource()->getName();
        return new JsonFile($file);
    }
    public function getComposerJson(): array
    {
        $json = $this->getComposerJsonFile()->read();
        $repositories = $this->getComposer()->getConfig()->getRepositories();
        unset($repositories['packagist.org']);
        if ([] !== $repositories || !empty($json['repositories'])) {
            $json['repositories'] = [];
            foreach ($repositories as $repository) {
                if (isset($repository['url'])) {
                    $repository['url'] = $this->normalizeRepositoryPath($repository['url']);
                }
                $json['repositories'][] = $repository;
            }
        }
        return $json;
    }
    public function getComposerJsonWithConfig(): array
    {
        $composerJson = $this->getComposerJson();
        if (\is_array($composerJson['config'] ?? null)) {
            $composerJson['config'] = array_replace_recursive($this->composerConfig->config()->all(), $composerJson['config']);
        } else {
            $composerJson['config'] = $this->composerConfig->config()->all();
        }
        return $composerJson;
    }
    public function getComposerLockFile(): JsonFile
    {
        return new JsonFile($this->getLockFile());
    }
    public function getComposerLock(): array
    {
        $locker = $this->getComposer()->getLocker();
        if (!$locker->isLocked()) {
            return [];
        }
        return $locker->getLockData();
    }
    public function getPlatformPackages(): array
    {
        $platformOverrides = $this->getComposer()->getConfig()->get('platform');
        $platform = [];
        foreach ((new PlatformRepository([], $platformOverrides))->getPackages() as $package) {
            if (\in_array($package->getName(), ['composer-plugin-api', 'composer-runtime-api'], \true)) {
                continue;
            }
            $platform[$package->getName()] = $package->getVersion();
        }
        return $platform;
    }
    public function getLocalPackages(): array
    {
        $packages = [];
        $repositories = $this->getComposer()->getRepositoryManager()->getRepositories();
        $dumper = new ArrayDumper();
        foreach ($repositories as $repo) {
            foreach (RepositoryUtils::flattenRepositories($repo) as $repository) {
                if ($repository instanceof ArtifactRepository || $repository instanceof PathRepository) {
                    foreach ($repository->getPackages() as $package) {
                        $dump = $dumper->dump($package);
                        if (isset($dump['dist']['path'])) {
                            $dump['dist']['path'] = $this->normalizeRepositoryPath($dump['dist']['path']);
                        }
                        // see https://github.com/composer/composer/issues/7955
                        unset($dump['dist']['reference']);
                        $packages[] = $dump;
                    }
                }
            }
        }
        return $packages;
    }
    public function mergeMetadata(array $package, string|null $language = null): array
    {
        if (isset($package['source']) || preg_match('{https?://}', $package['dist']['url'] ?? '') || empty($package['extra']['contao-metadata-url'])) {
            return $package;
        }
        try {
            $headers = [];
            if ($language) {
                $headers[] = 'Accept-Language: ' . $language;
            }
            if ($package['version'] ?? null) {
                $headers[] = 'Contao-Package-Version: ' . $package['version'];
            }
            $metadata = JsonFile::parseJson($this->request->getJson($package['extra']['contao-metadata-url'], $headers), $package['extra']['contao-metadata-url']);
            if (\is_array($metadata)) {
                // Make sure only allowed keys are preserved in metadata
                $metadata = array_intersect_key($metadata, array_flip(['title', 'description', 'homepage', 'suggest', 'support', 'funding', 'abandoned', 'logo']));
                // Do not allow custom logo URLs since they could track the Contao Manager user/browser
                if (isset($metadata['logo']) && preg_match('{https?://}i', (string) $metadata['logo'])) {
                    unset($metadata['logo']);
                }
                return array_merge($package, $metadata, ['private' => \true]);
            }
        } catch (\Exception) {
        }
        return $package;
    }
    private function normalizeRepositoryPath(string $path): string
    {
        if (null === $this->composerFs) {
            $this->composerFs = new \Composer\Util\Filesystem();
        }
        $normalizedPath = $this->composerFs->normalizePath($path);
        if (str_starts_with($path, './')) {
            return './' . $normalizedPath;
        }
        return $normalizedPath;
    }
    /**
     * Fix order of repositories if the latest manager-plugin is not installed.
     *
     * @see https://github.com/contao/manager-plugin/pull/59
     */
    private function fixManagerPlugin(): void
    {
        $repoManager = $this->composer->getRepositoryManager();
        // Skip if contao/manager-plugin was found in a version newer than 2.13.3 (the
        // last before the bugfix)
        if ($repoManager->getLocalRepository()->findPackage('contao/manager-plugin', '> 2.13.3')) {
            return;
        }
        $ref = new \ReflectionProperty($repoManager, 'repositories');
        /** @var array<RepositoryInterface> $repositories */
        $repositories = $ref->getValue($repoManager);
        $changed = \false;
        foreach ($repositories as $k => $repo) {
            if ('composer repo (https://repo.packagist.org)' === $repo->getRepoName()) {
                unset($repositories[$k]);
                $repositories[] = $repo;
                $changed = \true;
                break;
            }
        }
        if ($changed) {
            $ref->setValue($repoManager, $repositories);
        }
    }
}
a:35:{i:0;O:51:"Symfony\Component\Config\Resource\DirectoryResource":2:{s:61:" Symfony\Component\Config\Resource\DirectoryResource resource";s:84:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/Controller";s:60:" Symfony\Component\Config\Resource\DirectoryResource pattern";s:8:"/\.php$/";}i:1;O:46:"Symfony\Component\Config\Resource\FileResource":1:{s:56:" Symfony\Component\Config\Resource\FileResource resource";s:110:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/Controller/Config/AuthController.php";}i:2;O:46:"Symfony\Component\Config\Resource\FileResource":1:{s:56:" Symfony\Component\Config\Resource\FileResource resource";s:114:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/Controller/Config/ComposerController.php";}i:3;O:46:"Symfony\Component\Config\Resource\FileResource":1:{s:56:" Symfony\Component\Config\Resource\FileResource resource";s:113:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/Controller/Config/ManagerController.php";}i:4;O:46:"Symfony\Component\Config\Resource\FileResource":1:{s:56:" Symfony\Component\Config\Resource\FileResource resource";s:109:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/Controller/ConstraintController.php";}i:5;O:46:"Symfony\Component\Config\Resource\FileResource":1:{s:56:" Symfony\Component\Config\Resource\FileResource resource";s:115:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/Controller/Contao/AccessKeyController.php";}i:6;O:46:"Symfony\Component\Config\Resource\FileResource":1:{s:56:" Symfony\Component\Config\Resource\FileResource resource";s:112:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/Controller/Contao/BackupController.php";}i:7;O:46:"Symfony\Component\Config\Resource\FileResource":1:{s:56:" Symfony\Component\Config\Resource\FileResource resource";s:123:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/Controller/Contao/DatabaseMigrationController.php";}i:8;O:46:"Symfony\Component\Config\Resource\FileResource":1:{s:56:" Symfony\Component\Config\Resource\FileResource resource";s:121:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/Controller/Contao/InstallToolLockController.php";}i:9;O:46:"Symfony\Component\Config\Resource\FileResource":1:{s:56:" Symfony\Component\Config\Resource\FileResource resource";s:115:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/Controller/Contao/JwtCookieController.php";}i:10;O:46:"Symfony\Component\Config\Resource\FileResource":1:{s:56:" Symfony\Component\Config\Resource\FileResource resource";s:121:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/Controller/Contao/MaintenanceModeController.php";}i:11;O:46:"Symfony\Component\Config\Resource\FileResource":1:{s:56:" Symfony\Component\Config\Resource\FileResource resource";s:103:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/Controller/FileController.php";}i:12;O:46:"Symfony\Component\Config\Resource\FileResource":1:{s:56:" Symfony\Component\Config\Resource\FileResource resource";s:102:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/Controller/LogController.php";}i:13;O:46:"Symfony\Component\Config\Resource\FileResource":1:{s:56:" Symfony\Component\Config\Resource\FileResource resource";s:113:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/Controller/Packages/CloudController.php";}i:14;O:46:"Symfony\Component\Config\Resource\FileResource":1:{s:56:" Symfony\Component\Config\Resource\FileResource resource";s:121:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/Controller/Packages/LocalPackagesController.php";}i:15;O:46:"Symfony\Component\Config\Resource\FileResource":1:{s:56:" Symfony\Component\Config\Resource\FileResource resource";s:123:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/Controller/Packages/MissingPackagesController.php";}i:16;O:46:"Symfony\Component\Config\Resource\FileResource":1:{s:56:" Symfony\Component\Config\Resource\FileResource resource";s:119:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/Controller/Packages/RootPackageController.php";}i:17;O:46:"Symfony\Component\Config\Resource\FileResource":1:{s:56:" Symfony\Component\Config\Resource\FileResource resource";s:122:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/Controller/Packages/UploadPackagesController.php";}i:18;O:46:"Symfony\Component\Config\Resource\FileResource":1:{s:56:" Symfony\Component\Config\Resource\FileResource resource";s:115:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/Controller/Server/AdminUserController.php";}i:19;O:46:"Symfony\Component\Config\Resource\FileResource":1:{s:56:" Symfony\Component\Config\Resource\FileResource resource";s:114:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/Controller/Server/ComposerController.php";}i:20;O:46:"Symfony\Component\Config\Resource\FileResource":1:{s:56:" Symfony\Component\Config\Resource\FileResource resource";s:112:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/Controller/Server/ConfigController.php";}i:21;O:46:"Symfony\Component\Config\Resource\FileResource":1:{s:56:" Symfony\Component\Config\Resource\FileResource resource";s:112:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/Controller/Server/ContaoController.php";}i:22;O:46:"Symfony\Component\Config\Resource\FileResource":1:{s:56:" Symfony\Component\Config\Resource\FileResource resource";s:114:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/Controller/Server/DatabaseController.php";}i:23;O:46:"Symfony\Component\Config\Resource\FileResource":1:{s:56:" Symfony\Component\Config\Resource\FileResource resource";s:113:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/Controller/Server/OpcacheController.php";}i:24;O:46:"Symfony\Component\Config\Resource\FileResource":1:{s:56:" Symfony\Component\Config\Resource\FileResource resource";s:112:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/Controller/Server/PhpCliController.php";}i:25;O:46:"Symfony\Component\Config\Resource\FileResource":1:{s:56:" Symfony\Component\Config\Resource\FileResource resource";s:112:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/Controller/Server/PhpWebController.php";}i:26;O:46:"Symfony\Component\Config\Resource\FileResource":1:{s:56:" Symfony\Component\Config\Resource\FileResource resource";s:113:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/Controller/Server/PhpinfoController.php";}i:27;O:46:"Symfony\Component\Config\Resource\FileResource":1:{s:56:" Symfony\Component\Config\Resource\FileResource resource";s:116:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/Controller/Server/SelfUpdateController.php";}i:28;O:46:"Symfony\Component\Config\Resource\FileResource":1:{s:56:" Symfony\Component\Config\Resource\FileResource resource";s:106:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/Controller/SessionController.php";}i:29;O:46:"Symfony\Component\Config\Resource\FileResource":1:{s:56:" Symfony\Component\Config\Resource\FileResource resource";s:103:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/Controller/TaskController.php";}i:30;O:46:"Symfony\Component\Config\Resource\FileResource":1:{s:56:" Symfony\Component\Config\Resource\FileResource resource";s:103:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/Controller/UserController.php";}i:31;O:46:"Symfony\Component\Config\Resource\FileResource":1:{s:56:" Symfony\Component\Config\Resource\FileResource resource";s:87:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/ApiKernel.php";}i:32;O:46:"Symfony\Component\Config\Resource\FileResource":1:{s:56:" Symfony\Component\Config\Resource\FileResource resource";s:107:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/vendor/symfony/http-kernel/Kernel.php";}i:33;O:72:"Symfony\Component\DependencyInjection\Config\ContainerParametersResource":1:{s:84:" Symfony\Component\DependencyInjection\Config\ContainerParametersResource parameters";a:0:{}}i:34;O:46:"Symfony\Component\Config\Resource\FileResource":1:{s:56:" Symfony\Component\Config\Resource\FileResource resource";s:134:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/Resources/cache/Contao_ManagerApi_ApiKernelProdContainer.php";}}<?php

namespace _ContaoManager;

// This file has been auto-generated by the Symfony Dependency Injection Component for internal use.
if (\class_exists(\_ContaoManager\ContainerLiF9Qbu\Contao_ManagerApi_ApiKernelProdContainer::class, \false)) {
    // no-op
} elseif (!include __DIR__ . '/ContainerLiF9Qbu/Contao_ManagerApi_ApiKernelProdContainer.php') {
    \touch(__DIR__ . '/ContainerLiF9Qbu.legacy');
    return;
}
if (!\class_exists(Contao_ManagerApi_ApiKernelProdContainer::class, \false)) {
    \class_alias(\_ContaoManager\ContainerLiF9Qbu\Contao_ManagerApi_ApiKernelProdContainer::class, Contao_ManagerApi_ApiKernelProdContainer::class, \false);
}
return new \_ContaoManager\ContainerLiF9Qbu\Contao_ManagerApi_ApiKernelProdContainer(['container.build_hash' => 'LiF9Qbu', 'container.build_id' => 'c13f7905', 'container.build_time' => 1776251943, 'container.runtime_mode' => \in_array(\PHP_SAPI, ['cli', 'phpdbg', 'embed'], \true) ? 'web=0' : 'web=1'], __DIR__ . \DIRECTORY_SEPARATOR . 'ContainerLiF9Qbu');
<?php

namespace _ContaoManager;

// This file has been auto-generated by the Symfony Cache Component.
return [[], []];
a:172:{i:0;O:46:"Symfony\Component\Config\Resource\FileResource":1:{s:56:" Symfony\Component\Config\Resource\FileResource resource";s:100:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/vendor/composer/installed.json";}i:1;O:46:"Symfony\Component\Config\Resource\FileResource":1:{s:56:" Symfony\Component\Config\Resource\FileResource resource";s:87:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/ApiKernel.php";}i:2;O:56:"Symfony\Component\Config\Resource\ClassExistenceResource":2:{s:8:"resource";s:77:"Symfony\Component\Translation\DependencyInjection\DataCollectorTranslatorPass";s:6:"exists";a:2:{i:0;b:0;i:1;N;}}i:3;O:56:"Symfony\Component\Config\Resource\ClassExistenceResource":2:{s:8:"resource";s:75:"Symfony\Component\Validator\DependencyInjection\AddConstraintValidatorsPass";s:6:"exists";a:2:{i:0;b:0;i:1;N;}}i:4;O:56:"Symfony\Component\Config\Resource\ClassExistenceResource":2:{s:8:"resource";s:76:"Symfony\Component\Validator\DependencyInjection\AddValidatorInitializersPass";s:6:"exists";a:2:{i:0;b:0;i:1;N;}}i:5;O:56:"Symfony\Component\Config\Resource\ClassExistenceResource":2:{s:8:"resource";s:67:"Symfony\Component\Console\DependencyInjection\AddConsoleCommandPass";s:6:"exists";a:2:{i:0;b:1;i:1;N;}}i:6;O:56:"Symfony\Component\Config\Resource\ClassExistenceResource":2:{s:8:"resource";s:64:"Symfony\Component\Translation\DependencyInjection\TranslatorPass";s:6:"exists";a:2:{i:0;b:0;i:1;N;}}i:7;O:56:"Symfony\Component\Config\Resource\ClassExistenceResource":2:{s:8:"resource";s:69:"Symfony\Component\Translation\DependencyInjection\TranslatorPathsPass";s:6:"exists";a:2:{i:0;b:0;i:1;N;}}i:8;O:56:"Symfony\Component\Config\Resource\ClassExistenceResource":2:{s:8:"resource";s:71:"Symfony\Component\Translation\DependencyInjection\LoggingTranslatorPass";s:6:"exists";a:2:{i:0;b:0;i:1;N;}}i:9;O:56:"Symfony\Component\Config\Resource\ClassExistenceResource":2:{s:8:"resource";s:74:"Symfony\Component\Translation\DependencyInjection\TranslationExtractorPass";s:6:"exists";a:2:{i:0;b:0;i:1;N;}}i:10;O:56:"Symfony\Component\Config\Resource\ClassExistenceResource":2:{s:8:"resource";s:71:"Symfony\Component\Translation\DependencyInjection\TranslationDumperPass";s:6:"exists";a:2:{i:0;b:0;i:1;N;}}i:11;O:56:"Symfony\Component\Config\Resource\ClassExistenceResource":2:{s:8:"resource";s:63:"Symfony\Component\Serializer\DependencyInjection\SerializerPass";s:6:"exists";a:2:{i:0;b:1;i:1;N;}}i:12;O:56:"Symfony\Component\Config\Resource\ClassExistenceResource":2:{s:8:"resource";s:67:"Symfony\Component\PropertyInfo\DependencyInjection\PropertyInfoPass";s:6:"exists";a:2:{i:0;b:1;i:1;N;}}i:13;O:56:"Symfony\Component\Config\Resource\ClassExistenceResource":2:{s:8:"resource";s:51:"Symfony\Component\Form\DependencyInjection\FormPass";s:6:"exists";a:2:{i:0;b:0;i:1;N;}}i:14;O:56:"Symfony\Component\Config\Resource\ClassExistenceResource":2:{s:8:"resource";s:72:"Symfony\Component\Workflow\DependencyInjection\WorkflowGuardListenerPass";s:6:"exists";a:2:{i:0;b:0;i:1;N;}}i:15;O:56:"Symfony\Component\Config\Resource\ClassExistenceResource":2:{s:8:"resource";s:65:"Symfony\Component\Mime\DependencyInjection\AddMimeTypeGuesserPass";s:6:"exists";a:2:{i:0;b:0;i:1;N;}}i:16;O:56:"Symfony\Component\Config\Resource\ClassExistenceResource":2:{s:8:"resource";s:72:"Symfony\Component\Scheduler\DependencyInjection\AddScheduleMessengerPass";s:6:"exists";a:2:{i:0;b:0;i:1;N;}}i:17;O:56:"Symfony\Component\Config\Resource\ClassExistenceResource":2:{s:8:"resource";s:61:"Symfony\Component\Messenger\DependencyInjection\MessengerPass";s:6:"exists";a:2:{i:0;b:0;i:1;N;}}i:18;O:56:"Symfony\Component\Config\Resource\ClassExistenceResource":2:{s:8:"resource";s:63:"Symfony\Component\HttpClient\DependencyInjection\HttpClientPass";s:6:"exists";a:2:{i:0;b:0;i:1;N;}}i:19;O:56:"Symfony\Component\Config\Resource\ClassExistenceResource":2:{s:8:"resource";s:79:"Symfony\Component\Validator\DependencyInjection\AddAutoMappingConfigurationPass";s:6:"exists";a:2:{i:0;b:0;i:1;N;}}i:20;O:46:"Symfony\Component\Config\Resource\FileResource":1:{s:56:" Symfony\Component\Config\Resource\FileResource resource";s:107:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/Resources/config/config_prod.yaml";}i:21;O:46:"Symfony\Component\Config\Resource\FileResource":1:{s:56:" Symfony\Component\Config\Resource\FileResource resource";s:102:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/Resources/config/config.yaml";}i:22;O:46:"Symfony\Component\Config\Resource\FileResource":1:{s:56:" Symfony\Component\Config\Resource\FileResource resource";s:104:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/Resources/config/services.yaml";}i:23;O:57:"Symfony\Component\Config\Resource\ReflectionClassResource":4:{s:5:"files";a:1:{s:92:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/ApiApplication.php";N;}s:9:"className";s:32:"Contao\ManagerApi\ApiApplication";s:15:"excludedVendors";a:1:{i:0;s:76:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/vendor";}s:4:"hash";s:32:"193a88e26025615e73f401d764124b08";}i:24;O:57:"Symfony\Component\Config\Resource\ReflectionClassResource":4:{s:5:"files";a:1:{s:87:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/ApiKernel.php";N;}s:9:"className";s:27:"Contao\ManagerApi\ApiKernel";s:15:"excludedVendors";a:1:{i:0;s:76:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/vendor";}s:4:"hash";s:32:"d1ad8a78082ab0f987b8b2a6a10c5f8c";}i:25;O:57:"Symfony\Component\Config\Resource\ReflectionClassResource":4:{s:5:"files";a:1:{s:99:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/Composer/CloudChanges.php";N;}s:9:"className";s:39:"Contao\ManagerApi\Composer\CloudChanges";s:15:"excludedVendors";a:1:{i:0;s:76:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/vendor";}s:4:"hash";s:32:"802189b4ae492e246a7ba50aa057c63a";}i:26;O:57:"Symfony\Component\Config\Resource\ReflectionClassResource":4:{s:5:"files";a:1:{s:101:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/Composer/CloudException.php";N;}s:9:"className";s:41:"Contao\ManagerApi\Composer\CloudException";s:15:"excludedVendors";a:1:{i:0;s:76:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/vendor";}s:4:"hash";s:32:"d3df1cb8e32278c3196fae3652c6f507";}i:27;O:57:"Symfony\Component\Config\Resource\ReflectionClassResource":4:{s:5:"files";a:1:{s:95:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/Composer/CloudJob.php";N;}s:9:"className";s:35:"Contao\ManagerApi\Composer\CloudJob";s:15:"excludedVendors";a:1:{i:0;s:76:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/vendor";}s:4:"hash";s:32:"6974d5289dac3e4d3d450f45479a9ef9";}i:28;O:57:"Symfony\Component\Config\Resource\ReflectionClassResource":4:{s:5:"files";a:1:{s:100:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/Composer/CloudResolver.php";N;}s:9:"className";s:40:"Contao\ManagerApi\Composer\CloudResolver";s:15:"excludedVendors";a:1:{i:0;s:76:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/vendor";}s:4:"hash";s:32:"a858842e40881562136c1c1571aefdfb";}i:29;O:57:"Symfony\Component\Config\Resource\ReflectionClassResource":4:{s:5:"files";a:1:{s:98:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/Composer/Environment.php";N;}s:9:"className";s:38:"Contao\ManagerApi\Composer\Environment";s:15:"excludedVendors";a:1:{i:0;s:76:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/vendor";}s:4:"hash";s:32:"8e4b1c0461f99b0870317601725dbd52";}i:30;O:57:"Symfony\Component\Config\Resource\ReflectionClassResource":4:{s:5:"files";a:1:{s:99:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/Config/AbstractConfig.php";N;}s:9:"className";s:39:"Contao\ManagerApi\Config\AbstractConfig";s:15:"excludedVendors";a:1:{i:0;s:76:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/vendor";}s:4:"hash";s:32:"adac4dc403372246e807938aa1e1c99c";}i:31;O:57:"Symfony\Component\Config\Resource\ReflectionClassResource":4:{s:5:"files";a:2:{s:95:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/Config/AuthConfig.php";N;s:99:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/Config/AbstractConfig.php";N;}s:9:"className";s:35:"Contao\ManagerApi\Config\AuthConfig";s:15:"excludedVendors";a:1:{i:0;s:76:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/vendor";}s:4:"hash";s:32:"7540db6e6a47cc874ecbf4562d7e7559";}i:32;O:57:"Symfony\Component\Config\Resource\ReflectionClassResource":4:{s:5:"files";a:2:{s:99:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/Config/ComposerConfig.php";N;s:99:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/Config/AbstractConfig.php";N;}s:9:"className";s:39:"Contao\ManagerApi\Config\ComposerConfig";s:15:"excludedVendors";a:1:{i:0;s:76:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/vendor";}s:4:"hash";s:32:"32cc8997f8dfac743ca431dd13320fc6";}i:33;O:57:"Symfony\Component\Config\Resource\ReflectionClassResource":4:{s:5:"files";a:2:{s:98:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/Config/ManagerConfig.php";N;s:99:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/Config/AbstractConfig.php";N;}s:9:"className";s:38:"Contao\ManagerApi\Config\ManagerConfig";s:15:"excludedVendors";a:1:{i:0;s:76:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/vendor";}s:4:"hash";s:32:"1038d3d80334d990ae456308c1941da8";}i:34;O:57:"Symfony\Component\Config\Resource\ReflectionClassResource":4:{s:5:"files";a:1:{s:98:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/Config/PartialConfig.php";N;}s:9:"className";s:38:"Contao\ManagerApi\Config\PartialConfig";s:15:"excludedVendors";a:1:{i:0;s:76:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/vendor";}s:4:"hash";s:32:"814953650eed381e59727556eb97cf85";}i:35;O:57:"Symfony\Component\Config\Resource\ReflectionClassResource":4:{s:5:"files";a:2:{s:98:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/Config/UploadsConfig.php";N;s:99:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/Config/AbstractConfig.php";N;}s:9:"className";s:38:"Contao\ManagerApi\Config\UploadsConfig";s:15:"excludedVendors";a:1:{i:0;s:76:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/vendor";}s:4:"hash";s:32:"1038d3d80334d990ae456308c1941da8";}i:36;O:57:"Symfony\Component\Config\Resource\ReflectionClassResource":4:{s:5:"files";a:2:{s:95:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/Config/UserConfig.php";N;s:99:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/Config/AbstractConfig.php";N;}s:9:"className";s:35:"Contao\ManagerApi\Config\UserConfig";s:15:"excludedVendors";a:1:{i:0;s:76:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/vendor";}s:4:"hash";s:32:"cfc468ac2d2db33b39e5919e2437a867";}i:37;O:57:"Symfony\Component\Config\Resource\ReflectionClassResource":4:{s:5:"files";a:1:{s:109:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/EventListener/CheckTotpListener.php";N;}s:9:"className";s:49:"Contao\ManagerApi\EventListener\CheckTotpListener";s:15:"excludedVendors";a:1:{i:0;s:76:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/vendor";}s:4:"hash";s:32:"ca7229c01844cf15e195b0fe9a97d382";}i:38;O:57:"Symfony\Component\Config\Resource\ReflectionClassResource":4:{s:5:"files";a:1:{s:109:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/EventListener/ExceptionListener.php";N;}s:9:"className";s:49:"Contao\ManagerApi\EventListener\ExceptionListener";s:15:"excludedVendors";a:1:{i:0;s:76:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/vendor";}s:4:"hash";s:32:"c72e9bfe37476d4902e36cca05ee9ee6";}i:39;O:57:"Symfony\Component\Config\Resource\ReflectionClassResource":4:{s:5:"files";a:1:{s:111:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/EventListener/JsonRequestListener.php";N;}s:9:"className";s:51:"Contao\ManagerApi\EventListener\JsonRequestListener";s:15:"excludedVendors";a:1:{i:0;s:76:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/vendor";}s:4:"hash";s:32:"57b83051c651a782b765f540ea4d2c98";}i:40;O:57:"Symfony\Component\Config\Resource\ReflectionClassResource":4:{s:5:"files";a:1:{s:106:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/EventListener/LocaleListener.php";N;}s:9:"className";s:46:"Contao\ManagerApi\EventListener\LocaleListener";s:15:"excludedVendors";a:1:{i:0;s:76:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/vendor";}s:4:"hash";s:32:"71e8c1eec1c1a4808c7770a749a1b357";}i:41;O:57:"Symfony\Component\Config\Resource\ReflectionClassResource":4:{s:5:"files";a:1:{s:108:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/EventListener/SecurityListener.php";N;}s:9:"className";s:48:"Contao\ManagerApi\EventListener\SecurityListener";s:15:"excludedVendors";a:1:{i:0;s:76:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/vendor";}s:4:"hash";s:32:"659ee92d053cc6be8a25a6d8a3945abf";}i:42;O:57:"Symfony\Component\Config\Resource\ReflectionClassResource":4:{s:5:"files";a:1:{s:107:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/Exception/ApiProblemException.php";N;}s:9:"className";s:47:"Contao\ManagerApi\Exception\ApiProblemException";s:15:"excludedVendors";a:1:{i:0;s:76:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/vendor";}s:4:"hash";s:32:"443c9296e634cb5393fe715da8ef2d53";}i:43;O:57:"Symfony\Component\Config\Resource\ReflectionClassResource":4:{s:5:"files";a:1:{s:108:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/Exception/InvalidJsonException.php";N;}s:9:"className";s:48:"Contao\ManagerApi\Exception\InvalidJsonException";s:15:"excludedVendors";a:1:{i:0;s:76:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/vendor";}s:4:"hash";s:32:"008fb4fb9d04abf2d6db75d98a7e9d6c";}i:44;O:57:"Symfony\Component\Config\Resource\ReflectionClassResource":4:{s:5:"files";a:1:{s:108:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/Exception/InvalidTotpException.php";N;}s:9:"className";s:48:"Contao\ManagerApi\Exception\InvalidTotpException";s:15:"excludedVendors";a:1:{i:0;s:76:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/vendor";}s:4:"hash";s:32:"b363d5878a26b662e27dc89a7c79800a";}i:45;O:57:"Symfony\Component\Config\Resource\ReflectionClassResource":4:{s:5:"files";a:1:{s:110:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/Exception/ProcessOutputException.php";N;}s:9:"className";s:50:"Contao\ManagerApi\Exception\ProcessOutputException";s:15:"excludedVendors";a:1:{i:0;s:76:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/vendor";}s:4:"hash";s:32:"d25cfd06f62a23f9b2ba8c60bcd14387";}i:46;O:57:"Symfony\Component\Config\Resource\ReflectionClassResource":4:{s:5:"files";a:1:{s:104:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/Exception/RequestException.php";N;}s:9:"className";s:44:"Contao\ManagerApi\Exception\RequestException";s:15:"excludedVendors";a:1:{i:0;s:76:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/vendor";}s:4:"hash";s:32:"8fc5a2749e42df03199e51fd2c0ded6e";}i:47;O:57:"Symfony\Component\Config\Resource\ReflectionClassResource":4:{s:5:"files";a:1:{s:107:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/HttpKernel/ApiProblemResponse.php";N;}s:9:"className";s:47:"Contao\ManagerApi\HttpKernel\ApiProblemResponse";s:15:"excludedVendors";a:1:{i:0;s:76:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/vendor";}s:4:"hash";s:32:"f5e8faf72b00e0942ed1ba87bc0a4465";}i:48;O:57:"Symfony\Component\Config\Resource\ReflectionClassResource":4:{s:5:"files";a:1:{s:93:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/I18n/Translator.php";N;}s:9:"className";s:33:"Contao\ManagerApi\I18n\Translator";s:15:"excludedVendors";a:1:{i:0;s:76:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/vendor";}s:4:"hash";s:32:"70b5cd8de2f9e822b54cd58bc907b379";}i:49;O:57:"Symfony\Component\Config\Resource\ReflectionClassResource":4:{s:5:"files";a:2:{s:116:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/IntegrityCheck/IntegrityCheckInterface.php";N;s:115:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/IntegrityCheck/AbstractIntegrityCheck.php";N;}s:9:"className";s:55:"Contao\ManagerApi\IntegrityCheck\AbstractIntegrityCheck";s:15:"excludedVendors";a:1:{i:0;s:76:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/vendor";}s:4:"hash";s:32:"f9a584f206f16f163fbd86410371ee5d";}i:50;O:57:"Symfony\Component\Config\Resource\ReflectionClassResource":4:{s:5:"files";a:3:{s:116:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/IntegrityCheck/IntegrityCheckInterface.php";N;s:111:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/IntegrityCheck/AllowUrlFopenCheck.php";N;s:115:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/IntegrityCheck/AbstractIntegrityCheck.php";N;}s:9:"className";s:51:"Contao\ManagerApi\IntegrityCheck\AllowUrlFopenCheck";s:15:"excludedVendors";a:1:{i:0;s:76:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/vendor";}s:4:"hash";s:32:"6b068f6c871b2992e483e008e4222975";}i:51;O:57:"Symfony\Component\Config\Resource\ReflectionClassResource":4:{s:5:"files";a:3:{s:116:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/IntegrityCheck/IntegrityCheckInterface.php";N;s:109:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/IntegrityCheck/GraphicsLibCheck.php";N;s:115:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/IntegrityCheck/AbstractIntegrityCheck.php";N;}s:9:"className";s:49:"Contao\ManagerApi\IntegrityCheck\GraphicsLibCheck";s:15:"excludedVendors";a:1:{i:0;s:76:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/vendor";}s:4:"hash";s:32:"6b068f6c871b2992e483e008e4222975";}i:52;O:57:"Symfony\Component\Config\Resource\ReflectionClassResource":4:{s:5:"files";a:1:{s:114:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/IntegrityCheck/IntegrityCheckFactory.php";N;}s:9:"className";s:54:"Contao\ManagerApi\IntegrityCheck\IntegrityCheckFactory";s:15:"excludedVendors";a:1:{i:0;s:76:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/vendor";}s:4:"hash";s:32:"4b15bbd10e8bcbf401b0c2678ec0c47b";}i:53;O:57:"Symfony\Component\Config\Resource\ReflectionClassResource":4:{s:5:"files";a:1:{s:116:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/IntegrityCheck/IntegrityCheckInterface.php";N;}s:9:"className";s:56:"Contao\ManagerApi\IntegrityCheck\IntegrityCheckInterface";s:15:"excludedVendors";a:1:{i:0;s:76:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/vendor";}s:4:"hash";s:32:"2c98b6607b114205618fd339b060a79d";}i:54;O:57:"Symfony\Component\Config\Resource\ReflectionClassResource":4:{s:5:"files";a:3:{s:116:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/IntegrityCheck/IntegrityCheckInterface.php";N;s:109:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/IntegrityCheck/MemoryLimitCheck.php";N;s:115:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/IntegrityCheck/AbstractIntegrityCheck.php";N;}s:9:"className";s:49:"Contao\ManagerApi\IntegrityCheck\MemoryLimitCheck";s:15:"excludedVendors";a:1:{i:0;s:76:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/vendor";}s:4:"hash";s:32:"6b068f6c871b2992e483e008e4222975";}i:55;O:57:"Symfony\Component\Config\Resource\ReflectionClassResource":4:{s:5:"files";a:3:{s:116:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/IntegrityCheck/IntegrityCheckInterface.php";N;s:111:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/IntegrityCheck/PhpExtensionsCheck.php";N;s:115:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/IntegrityCheck/AbstractIntegrityCheck.php";N;}s:9:"className";s:51:"Contao\ManagerApi\IntegrityCheck\PhpExtensionsCheck";s:15:"excludedVendors";a:1:{i:0;s:76:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/vendor";}s:4:"hash";s:32:"6b068f6c871b2992e483e008e4222975";}i:56;O:57:"Symfony\Component\Config\Resource\ReflectionClassResource":4:{s:5:"files";a:3:{s:116:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/IntegrityCheck/IntegrityCheckInterface.php";N;s:105:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/IntegrityCheck/ProcessCheck.php";N;s:115:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/IntegrityCheck/AbstractIntegrityCheck.php";N;}s:9:"className";s:45:"Contao\ManagerApi\IntegrityCheck\ProcessCheck";s:15:"excludedVendors";a:1:{i:0;s:76:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/vendor";}s:4:"hash";s:32:"6b068f6c871b2992e483e008e4222975";}i:57;O:57:"Symfony\Component\Config\Resource\ReflectionClassResource":4:{s:5:"files";a:3:{s:116:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/IntegrityCheck/IntegrityCheckInterface.php";N;s:105:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/IntegrityCheck/SessionCheck.php";N;s:115:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/IntegrityCheck/AbstractIntegrityCheck.php";N;}s:9:"className";s:45:"Contao\ManagerApi\IntegrityCheck\SessionCheck";s:15:"excludedVendors";a:1:{i:0;s:76:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/vendor";}s:4:"hash";s:32:"6b068f6c871b2992e483e008e4222975";}i:58;O:57:"Symfony\Component\Config\Resource\ReflectionClassResource":4:{s:5:"files";a:3:{s:116:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/IntegrityCheck/IntegrityCheckInterface.php";N;s:105:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/IntegrityCheck/SymlinkCheck.php";N;s:115:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/IntegrityCheck/AbstractIntegrityCheck.php";N;}s:9:"className";s:45:"Contao\ManagerApi\IntegrityCheck\SymlinkCheck";s:15:"excludedVendors";a:1:{i:0;s:76:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/vendor";}s:4:"hash";s:32:"6ab79c32ddf8e9615d5477c45a091d45";}i:59;O:57:"Symfony\Component\Config\Resource\ReflectionClassResource":4:{s:5:"files";a:3:{s:116:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/IntegrityCheck/IntegrityCheckInterface.php";N;s:108:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/IntegrityCheck/SysTempDirCheck.php";N;s:115:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/IntegrityCheck/AbstractIntegrityCheck.php";N;}s:9:"className";s:48:"Contao\ManagerApi\IntegrityCheck\SysTempDirCheck";s:15:"excludedVendors";a:1:{i:0;s:76:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/vendor";}s:4:"hash";s:32:"0168e79ea119ea48b5e8ac5d8e49e6cf";}i:60;O:57:"Symfony\Component\Config\Resource\ReflectionClassResource":4:{s:5:"files";a:3:{s:116:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/IntegrityCheck/IntegrityCheckInterface.php";N;s:101:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/IntegrityCheck/ZipCheck.php";N;s:115:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/IntegrityCheck/AbstractIntegrityCheck.php";N;}s:9:"className";s:41:"Contao\ManagerApi\IntegrityCheck\ZipCheck";s:15:"excludedVendors";a:1:{i:0;s:76:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/vendor";}s:4:"hash";s:32:"6b068f6c871b2992e483e008e4222975";}i:61;O:57:"Symfony\Component\Config\Resource\ReflectionClassResource":4:{s:5:"files";a:1:{s:101:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/Process/AbstractProcess.php";N;}s:9:"className";s:41:"Contao\ManagerApi\Process\AbstractProcess";s:15:"excludedVendors";a:1:{i:0;s:76:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/vendor";}s:4:"hash";s:32:"63a1eb5cabe55a8cbeef6eaf39ca6ef4";}i:62;O:57:"Symfony\Component\Config\Resource\ReflectionClassResource":4:{s:5:"files";a:1:{s:107:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/Process/ConsoleProcessFactory.php";N;}s:9:"className";s:47:"Contao\ManagerApi\Process\ConsoleProcessFactory";s:15:"excludedVendors";a:1:{i:0;s:76:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/vendor";}s:4:"hash";s:32:"1505cbe6553eeedf3992fbc1978e1798";}i:63;O:57:"Symfony\Component\Config\Resource\ReflectionClassResource":4:{s:5:"files";a:1:{s:95:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/Process/ContaoApi.php";N;}s:9:"className";s:35:"Contao\ManagerApi\Process\ContaoApi";s:15:"excludedVendors";a:1:{i:0;s:76:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/vendor";}s:4:"hash";s:32:"2567f665fb8660aa2bc5d5b2ef9739ad";}i:64;O:57:"Symfony\Component\Config\Resource\ReflectionClassResource":4:{s:5:"files";a:1:{s:99:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/Process/ContaoConsole.php";N;}s:9:"className";s:39:"Contao\ManagerApi\Process\ContaoConsole";s:15:"excludedVendors";a:1:{i:0;s:76:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/vendor";}s:4:"hash";s:32:"4defe2281d967e763e9544412d2f93dc";}i:65;O:57:"Symfony\Component\Config\Resource\ReflectionClassResource":4:{s:5:"files";a:2:{s:108:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/Process/Forker/ForkerInterface.php";N;s:107:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/Process/Forker/AbstractForker.php";N;}s:9:"className";s:47:"Contao\ManagerApi\Process\Forker\AbstractForker";s:15:"excludedVendors";a:1:{i:0;s:76:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/vendor";}s:4:"hash";s:32:"daf43de8e57b62e31cf07562b054a0f1";}i:66;O:57:"Symfony\Component\Config\Resource\ReflectionClassResource":4:{s:5:"files";a:3:{s:108:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/Process/Forker/ForkerInterface.php";N;s:105:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/Process/Forker/DisownForker.php";N;s:107:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/Process/Forker/AbstractForker.php";N;}s:9:"className";s:45:"Contao\ManagerApi\Process\Forker\DisownForker";s:15:"excludedVendors";a:1:{i:0;s:76:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/vendor";}s:4:"hash";s:32:"77fa478201da42d17368f626fa78401d";}i:67;O:57:"Symfony\Component\Config\Resource\ReflectionClassResource":4:{s:5:"files";a:1:{s:108:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/Process/Forker/ForkerInterface.php";N;}s:9:"className";s:48:"Contao\ManagerApi\Process\Forker\ForkerInterface";s:15:"excludedVendors";a:1:{i:0;s:76:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/vendor";}s:4:"hash";s:32:"a2d8b36440a52efd0e80b9c62995216f";}i:68;O:57:"Symfony\Component\Config\Resource\ReflectionClassResource":4:{s:5:"files";a:3:{s:108:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/Process/Forker/ForkerInterface.php";N;s:105:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/Process/Forker/InlineForker.php";N;s:107:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/Process/Forker/AbstractForker.php";N;}s:9:"className";s:45:"Contao\ManagerApi\Process\Forker\InlineForker";s:15:"excludedVendors";a:1:{i:0;s:76:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/vendor";}s:4:"hash";s:32:"77fa478201da42d17368f626fa78401d";}i:69;O:57:"Symfony\Component\Config\Resource\ReflectionClassResource":4:{s:5:"files";a:3:{s:108:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/Process/Forker/ForkerInterface.php";N;s:104:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/Process/Forker/NohupForker.php";N;s:107:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/Process/Forker/AbstractForker.php";N;}s:9:"className";s:44:"Contao\ManagerApi\Process\Forker\NohupForker";s:15:"excludedVendors";a:1:{i:0;s:76:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/vendor";}s:4:"hash";s:32:"77fa478201da42d17368f626fa78401d";}i:70;O:57:"Symfony\Component\Config\Resource\ReflectionClassResource":4:{s:5:"files";a:3:{s:108:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/Process/Forker/ForkerInterface.php";N;s:111:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/Process/Forker/WindowsStartForker.php";N;s:107:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/Process/Forker/AbstractForker.php";N;}s:9:"className";s:51:"Contao\ManagerApi\Process\Forker\WindowsStartForker";s:15:"excludedVendors";a:1:{i:0;s:76:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/vendor";}s:4:"hash";s:32:"77fa478201da42d17368f626fa78401d";}i:71;O:57:"Symfony\Component\Config\Resource\ReflectionClassResource":4:{s:5:"files";a:1:{s:105:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/Process/PhpExecutableFinder.php";N;}s:9:"className";s:45:"Contao\ManagerApi\Process\PhpExecutableFinder";s:15:"excludedVendors";a:1:{i:0;s:76:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/vendor";}s:4:"hash";s:32:"e814c25e410aaa09b12fba143cd51809";}i:72;O:57:"Symfony\Component\Config\Resource\ReflectionClassResource":4:{s:5:"files";a:2:{s:103:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/Process/ProcessController.php";N;s:101:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/Process/AbstractProcess.php";N;}s:9:"className";s:43:"Contao\ManagerApi\Process\ProcessController";s:15:"excludedVendors";a:1:{i:0;s:76:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/vendor";}s:4:"hash";s:32:"752b982973fefd95c53c968c62f0e8f2";}i:73;O:57:"Symfony\Component\Config\Resource\ReflectionClassResource":4:{s:5:"files";a:2:{s:99:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/Process/ProcessRunner.php";N;s:101:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/Process/AbstractProcess.php";N;}s:9:"className";s:39:"Contao\ManagerApi\Process\ProcessRunner";s:15:"excludedVendors";a:1:{i:0;s:76:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/vendor";}s:4:"hash";s:32:"993a9ca20c1b534abd0cb3c5394a0f73";}i:74;O:57:"Symfony\Component\Config\Resource\ReflectionClassResource":4:{s:5:"files";a:1:{s:97:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/Process/Utf8Process.php";N;}s:9:"className";s:37:"Contao\ManagerApi\Process\Utf8Process";s:15:"excludedVendors";a:1:{i:0;s:76:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/vendor";}s:4:"hash";s:32:"e146e6f76470d46af93ca1146991bb68";}i:75;O:57:"Symfony\Component\Config\Resource\ReflectionClassResource":4:{s:5:"files";a:1:{s:115:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/Security/AbstractBrowserAuthenticator.php";N;}s:9:"className";s:55:"Contao\ManagerApi\Security\AbstractBrowserAuthenticator";s:15:"excludedVendors";a:1:{i:0;s:76:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/vendor";}s:4:"hash";s:32:"17077d7b25a25c3afbd0a9ca8c79d873";}i:76;O:57:"Symfony\Component\Config\Resource\ReflectionClassResource":4:{s:5:"files";a:1:{s:114:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/Security/AuthenticationTrustResolver.php";N;}s:9:"className";s:54:"Contao\ManagerApi\Security\AuthenticationTrustResolver";s:15:"excludedVendors";a:1:{i:0;s:76:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/vendor";}s:4:"hash";s:32:"62446b610f4ec5f6ea175293e172c53f";}i:77;O:57:"Symfony\Component\Config\Resource\ReflectionClassResource":4:{s:5:"files";a:1:{s:103:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/Security/JwtAuthenticator.php";N;}s:9:"className";s:43:"Contao\ManagerApi\Security\JwtAuthenticator";s:15:"excludedVendors";a:1:{i:0;s:76:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/vendor";}s:4:"hash";s:32:"2763c61aa35ff740b8e8af5ddc84ec30";}i:78;O:57:"Symfony\Component\Config\Resource\ReflectionClassResource":4:{s:5:"files";a:1:{s:97:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/Security/JwtManager.php";N;}s:9:"className";s:37:"Contao\ManagerApi\Security\JwtManager";s:15:"excludedVendors";a:1:{i:0;s:76:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/vendor";}s:4:"hash";s:32:"4c8d774bffd9945e5860b90ff02e4d77";}i:79;O:57:"Symfony\Component\Config\Resource\ReflectionClassResource":4:{s:5:"files";a:2:{s:105:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/Security/LoginAuthenticator.php";N;s:115:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/Security/AbstractBrowserAuthenticator.php";N;}s:9:"className";s:45:"Contao\ManagerApi\Security\LoginAuthenticator";s:15:"excludedVendors";a:1:{i:0;s:76:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/vendor";}s:4:"hash";s:32:"77294d260c556ddb5ca6611b493c708f";}i:80;O:57:"Symfony\Component\Config\Resource\ReflectionClassResource":4:{s:5:"files";a:2:{s:112:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/Security/PasswordlessAuthenticator.php";N;s:115:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/Security/AbstractBrowserAuthenticator.php";N;}s:9:"className";s:52:"Contao\ManagerApi\Security\PasswordlessAuthenticator";s:15:"excludedVendors";a:1:{i:0;s:76:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/vendor";}s:4:"hash";s:32:"bdd08d3a6b938f957af7bcb514cd815b";}i:81;O:57:"Symfony\Component\Config\Resource\ReflectionClassResource":4:{s:5:"files";a:1:{s:105:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/Security/TokenAuthenticator.php";N;}s:9:"className";s:45:"Contao\ManagerApi\Security\TokenAuthenticator";s:15:"excludedVendors";a:1:{i:0;s:76:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/vendor";}s:4:"hash";s:32:"33f4a96e7a2877d2034252f3f04ec750";}i:82;O:57:"Symfony\Component\Config\Resource\ReflectionClassResource":4:{s:5:"files";a:1:{s:96:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/Security/TotpBadge.php";N;}s:9:"className";s:36:"Contao\ManagerApi\Security\TotpBadge";s:15:"excludedVendors";a:1:{i:0;s:76:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/vendor";}s:4:"hash";s:32:"93b9ecb5685dd2dd8818f3a428fc8dbf";}i:83;O:57:"Symfony\Component\Config\Resource\ReflectionClassResource":4:{s:5:"files";a:1:{s:91:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/Security/User.php";N;}s:9:"className";s:31:"Contao\ManagerApi\Security\User";s:15:"excludedVendors";a:1:{i:0;s:76:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/vendor";}s:4:"hash";s:32:"2b4795db330f4952031098cbf2ee9711";}i:84;O:57:"Symfony\Component\Config\Resource\ReflectionClassResource":4:{s:5:"files";a:1:{s:99:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/Security/UserProvider.php";N;}s:9:"className";s:39:"Contao\ManagerApi\Security\UserProvider";s:15:"excludedVendors";a:1:{i:0;s:76:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/vendor";}s:4:"hash";s:32:"8eb5e636f623b939de67e52fcf4e2ac8";}i:85;O:57:"Symfony\Component\Config\Resource\ReflectionClassResource":4:{s:5:"files";a:2:{s:108:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/Security/WebauthnAuthenticator.php";N;s:115:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/Security/AbstractBrowserAuthenticator.php";N;}s:9:"className";s:48:"Contao\ManagerApi\Security\WebauthnAuthenticator";s:15:"excludedVendors";a:1:{i:0;s:76:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/vendor";}s:4:"hash";s:32:"01b5965be0abb7dfc6f0c5ef1b841ed0";}i:86;O:57:"Symfony\Component\Config\Resource\ReflectionClassResource":4:{s:5:"files";a:1:{s:92:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/System/Request.php";N;}s:9:"className";s:32:"Contao\ManagerApi\System\Request";s:15:"excludedVendors";a:1:{i:0;s:76:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/vendor";}s:4:"hash";s:32:"1cd828726b3c106a2490a7662a8db68b";}i:87;O:57:"Symfony\Component\Config\Resource\ReflectionClassResource":4:{s:5:"files";a:1:{s:95:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/System/SelfUpdate.php";N;}s:9:"className";s:35:"Contao\ManagerApi\System\SelfUpdate";s:15:"excludedVendors";a:1:{i:0;s:76:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/vendor";}s:4:"hash";s:32:"debf89a738fbe47f02da054abb17e707";}i:88;O:57:"Symfony\Component\Config\Resource\ReflectionClassResource":4:{s:5:"files";a:1:{s:95:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/System/ServerInfo.php";N;}s:9:"className";s:35:"Contao\ManagerApi\System\ServerInfo";s:15:"excludedVendors";a:1:{i:0;s:76:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/vendor";}s:4:"hash";s:32:"03c6387426aa00eb70eb7335365e35fc";}i:89;O:57:"Symfony\Component\Config\Resource\ReflectionClassResource":4:{s:5:"files";a:2:{s:96:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/Task/TaskInterface.php";N;s:95:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/Task/AbstractTask.php";N;}s:9:"className";s:35:"Contao\ManagerApi\Task\AbstractTask";s:15:"excludedVendors";a:1:{i:0;s:76:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/vendor";}s:4:"hash";s:32:"04fba86beab94bd34b46348e0da0d396";}i:90;O:57:"Symfony\Component\Config\Resource\ReflectionClassResource":4:{s:5:"files";a:3:{s:96:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/Task/TaskInterface.php";N;s:106:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/Task/Composer/ClearCacheTask.php";N;s:95:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/Task/AbstractTask.php";N;}s:9:"className";s:46:"Contao\ManagerApi\Task\Composer\ClearCacheTask";s:15:"excludedVendors";a:1:{i:0;s:76:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/vendor";}s:4:"hash";s:32:"537f314baba2de5c70467d59934e9de8";}i:91;O:57:"Symfony\Component\Config\Resource\ReflectionClassResource":4:{s:5:"files";a:3:{s:96:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/Task/TaskInterface.php";N;s:108:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/Task/Composer/DumpAutoloadTask.php";N;s:95:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/Task/AbstractTask.php";N;}s:9:"className";s:48:"Contao\ManagerApi\Task\Composer\DumpAutoloadTask";s:15:"excludedVendors";a:1:{i:0;s:76:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/vendor";}s:4:"hash";s:32:"537f314baba2de5c70467d59934e9de8";}i:92;O:57:"Symfony\Component\Config\Resource\ReflectionClassResource":4:{s:5:"files";a:3:{s:96:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/Task/TaskInterface.php";N;s:106:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/Task/Contao/BackupCreateTask.php";N;s:95:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/Task/AbstractTask.php";N;}s:9:"className";s:46:"Contao\ManagerApi\Task\Contao\BackupCreateTask";s:15:"excludedVendors";a:1:{i:0;s:76:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/vendor";}s:4:"hash";s:32:"537f314baba2de5c70467d59934e9de8";}i:93;O:57:"Symfony\Component\Config\Resource\ReflectionClassResource":4:{s:5:"files";a:3:{s:96:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/Task/TaskInterface.php";N;s:107:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/Task/Contao/BackupRestoreTask.php";N;s:95:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/Task/AbstractTask.php";N;}s:9:"className";s:47:"Contao\ManagerApi\Task\Contao\BackupRestoreTask";s:15:"excludedVendors";a:1:{i:0;s:76:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/vendor";}s:4:"hash";s:32:"537f314baba2de5c70467d59934e9de8";}i:94;O:57:"Symfony\Component\Config\Resource\ReflectionClassResource":4:{s:5:"files";a:3:{s:96:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/Task/TaskInterface.php";N;s:106:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/Task/Contao/RebuildCacheTask.php";N;s:95:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/Task/AbstractTask.php";N;}s:9:"className";s:46:"Contao\ManagerApi\Task\Contao\RebuildCacheTask";s:15:"excludedVendors";a:1:{i:0;s:76:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/vendor";}s:4:"hash";s:32:"4449bbb861540ced464e781c08da66d3";}i:95;O:57:"Symfony\Component\Config\Resource\ReflectionClassResource":4:{s:5:"files";a:3:{s:96:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/Task/TaskInterface.php";N;s:105:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/Task/Manager/SelfUpdateTask.php";N;s:95:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/Task/AbstractTask.php";N;}s:9:"className";s:45:"Contao\ManagerApi\Task\Manager\SelfUpdateTask";s:15:"excludedVendors";a:1:{i:0;s:76:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/vendor";}s:4:"hash";s:32:"005f162b6b00b85f187f4db2c3050294";}i:96;O:57:"Symfony\Component\Config\Resource\ReflectionClassResource":4:{s:5:"files";a:3:{s:96:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/Task/TaskInterface.php";N;s:112:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/Task/Packages/AbstractPackagesTask.php";N;s:95:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/Task/AbstractTask.php";N;}s:9:"className";s:52:"Contao\ManagerApi\Task\Packages\AbstractPackagesTask";s:15:"excludedVendors";a:1:{i:0;s:76:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/vendor";}s:4:"hash";s:32:"9b54a603f49ebad56a5079aea4d81462";}i:97;O:57:"Symfony\Component\Config\Resource\ReflectionClassResource":4:{s:5:"files";a:4:{s:96:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/Task/TaskInterface.php";N;s:103:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/Task/Packages/InstallTask.php";N;s:112:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/Task/Packages/AbstractPackagesTask.php";N;s:95:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/Task/AbstractTask.php";N;}s:9:"className";s:43:"Contao\ManagerApi\Task\Packages\InstallTask";s:15:"excludedVendors";a:1:{i:0;s:76:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/vendor";}s:4:"hash";s:32:"525027ce79c078df965f95e6a1c4f991";}i:98;O:57:"Symfony\Component\Config\Resource\ReflectionClassResource":4:{s:5:"files";a:4:{s:96:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/Task/TaskInterface.php";N;s:101:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/Task/Packages/SetupTask.php";N;s:112:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/Task/Packages/AbstractPackagesTask.php";N;s:95:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/Task/AbstractTask.php";N;}s:9:"className";s:41:"Contao\ManagerApi\Task\Packages\SetupTask";s:15:"excludedVendors";a:1:{i:0;s:76:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/vendor";}s:4:"hash";s:32:"74c47faa6d840e69a71bfb721d087221";}i:99;O:57:"Symfony\Component\Config\Resource\ReflectionClassResource":4:{s:5:"files";a:4:{s:96:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/Task/TaskInterface.php";N;s:102:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/Task/Packages/UpdateTask.php";N;s:112:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/Task/Packages/AbstractPackagesTask.php";N;s:95:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/Task/AbstractTask.php";N;}s:9:"className";s:42:"Contao\ManagerApi\Task\Packages\UpdateTask";s:15:"excludedVendors";a:1:{i:0;s:76:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/vendor";}s:4:"hash";s:32:"e506ac23199452c50108bfebb4a6e7ac";}i:100;O:57:"Symfony\Component\Config\Resource\ReflectionClassResource":4:{s:5:"files";a:2:{s:93:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/Task/TaskConfig.php";N;s:99:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/Config/AbstractConfig.php";N;}s:9:"className";s:33:"Contao\ManagerApi\Task\TaskConfig";s:15:"excludedVendors";a:1:{i:0;s:76:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/vendor";}s:4:"hash";s:32:"3052a263becadac589dbc8b5e7f56dea";}i:101;O:57:"Symfony\Component\Config\Resource\ReflectionClassResource":4:{s:5:"files";a:1:{s:96:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/Task/TaskInterface.php";N;}s:9:"className";s:36:"Contao\ManagerApi\Task\TaskInterface";s:15:"excludedVendors";a:1:{i:0;s:76:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/vendor";}s:4:"hash";s:32:"f23470e5366514ca2817b71036e55f11";}i:102;O:57:"Symfony\Component\Config\Resource\ReflectionClassResource":4:{s:5:"files";a:1:{s:94:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/Task/TaskManager.php";N;}s:9:"className";s:34:"Contao\ManagerApi\Task\TaskManager";s:15:"excludedVendors";a:1:{i:0;s:76:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/vendor";}s:4:"hash";s:32:"9d9610a64651505108adbe39e8a07c3b";}i:103;O:57:"Symfony\Component\Config\Resource\ReflectionClassResource":4:{s:5:"files";a:1:{s:93:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/Task/TaskStatus.php";N;}s:9:"className";s:33:"Contao\ManagerApi\Task\TaskStatus";s:15:"excludedVendors";a:1:{i:0;s:76:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/vendor";}s:4:"hash";s:32:"6f3f9e8fa6d26d87b07fdcd3389b6946";}i:104;O:57:"Symfony\Component\Config\Resource\ReflectionClassResource":4:{s:5:"files";a:2:{s:114:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/TaskOperation/TaskOperationInterface.php";N;s:115:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/TaskOperation/AbstractInlineOperation.php";N;}s:9:"className";s:55:"Contao\ManagerApi\TaskOperation\AbstractInlineOperation";s:15:"excludedVendors";a:1:{i:0;s:76:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/vendor";}s:4:"hash";s:32:"ff78eaaedbce480bdfde65f7cef7fc04";}i:105;O:57:"Symfony\Component\Config\Resource\ReflectionClassResource":4:{s:5:"files";a:2:{s:114:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/TaskOperation/TaskOperationInterface.php";N;s:116:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/TaskOperation/AbstractProcessOperation.php";N;}s:9:"className";s:56:"Contao\ManagerApi\TaskOperation\AbstractProcessOperation";s:15:"excludedVendors";a:1:{i:0;s:76:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/vendor";}s:4:"hash";s:32:"c898b4e7b994126a469e15b0b03bbf16";}i:106;O:57:"Symfony\Component\Config\Resource\ReflectionClassResource":4:{s:5:"files";a:3:{s:114:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/TaskOperation/TaskOperationInterface.php";N;s:120:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/TaskOperation/Composer/ClearCacheOperation.php";N;s:116:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/TaskOperation/AbstractProcessOperation.php";N;}s:9:"className";s:60:"Contao\ManagerApi\TaskOperation\Composer\ClearCacheOperation";s:15:"excludedVendors";a:1:{i:0;s:76:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/vendor";}s:4:"hash";s:32:"1ae836570084f6cf2de88232ee6fd369";}i:107;O:57:"Symfony\Component\Config\Resource\ReflectionClassResource":4:{s:5:"files";a:3:{s:114:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/TaskOperation/TaskOperationInterface.php";N;s:119:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/TaskOperation/SponsoredOperationInterface.php";N;s:115:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/TaskOperation/Composer/CloudOperation.php";N;}s:9:"className";s:55:"Contao\ManagerApi\TaskOperation\Composer\CloudOperation";s:15:"excludedVendors";a:1:{i:0;s:76:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/vendor";}s:4:"hash";s:32:"5f0698b50d7d2e198c97c6235020c700";}i:108;O:57:"Symfony\Component\Config\Resource\ReflectionClassResource":4:{s:5:"files";a:3:{s:114:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/TaskOperation/TaskOperationInterface.php";N;s:123:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/TaskOperation/Composer/CreateProjectOperation.php";N;s:116:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/TaskOperation/AbstractProcessOperation.php";N;}s:9:"className";s:63:"Contao\ManagerApi\TaskOperation\Composer\CreateProjectOperation";s:15:"excludedVendors";a:1:{i:0;s:76:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/vendor";}s:4:"hash";s:32:"db92387d3def30a20a68e005a3a5cc73";}i:109;O:57:"Symfony\Component\Config\Resource\ReflectionClassResource":4:{s:5:"files";a:3:{s:114:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/TaskOperation/TaskOperationInterface.php";N;s:122:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/TaskOperation/Composer/DumpAutoloadOperation.php";N;s:116:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/TaskOperation/AbstractProcessOperation.php";N;}s:9:"className";s:62:"Contao\ManagerApi\TaskOperation\Composer\DumpAutoloadOperation";s:15:"excludedVendors";a:1:{i:0;s:76:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/vendor";}s:4:"hash";s:32:"53077e5527cb3482468e7595061785b9";}i:110;O:57:"Symfony\Component\Config\Resource\ReflectionClassResource":4:{s:5:"files";a:3:{s:114:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/TaskOperation/TaskOperationInterface.php";N;s:117:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/TaskOperation/Composer/InstallOperation.php";N;s:116:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/TaskOperation/AbstractProcessOperation.php";N;}s:9:"className";s:57:"Contao\ManagerApi\TaskOperation\Composer\InstallOperation";s:15:"excludedVendors";a:1:{i:0;s:76:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/vendor";}s:4:"hash";s:32:"063dbada03b59e7f059abc85cdd2baee";}i:111;O:57:"Symfony\Component\Config\Resource\ReflectionClassResource":4:{s:5:"files";a:3:{s:114:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/TaskOperation/TaskOperationInterface.php";N;s:116:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/TaskOperation/Composer/RemoveOperation.php";N;s:116:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/TaskOperation/AbstractProcessOperation.php";N;}s:9:"className";s:56:"Contao\ManagerApi\TaskOperation\Composer\RemoveOperation";s:15:"excludedVendors";a:1:{i:0;s:76:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/vendor";}s:4:"hash";s:32:"ed277ed60b7da13ebe8fa036e2f428e1";}i:112;O:57:"Symfony\Component\Config\Resource\ReflectionClassResource":4:{s:5:"files";a:3:{s:114:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/TaskOperation/TaskOperationInterface.php";N;s:117:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/TaskOperation/Composer/RequireOperation.php";N;s:116:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/TaskOperation/AbstractProcessOperation.php";N;}s:9:"className";s:57:"Contao\ManagerApi\TaskOperation\Composer\RequireOperation";s:15:"excludedVendors";a:1:{i:0;s:76:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/vendor";}s:4:"hash";s:32:"799ed00f2fef87d0953be8c3d02b20b1";}i:113;O:57:"Symfony\Component\Config\Resource\ReflectionClassResource":4:{s:5:"files";a:3:{s:114:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/TaskOperation/TaskOperationInterface.php";N;s:116:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/TaskOperation/Composer/UpdateOperation.php";N;s:116:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/TaskOperation/AbstractProcessOperation.php";N;}s:9:"className";s:56:"Contao\ManagerApi\TaskOperation\Composer\UpdateOperation";s:15:"excludedVendors";a:1:{i:0;s:76:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/vendor";}s:4:"hash";s:32:"9dd9184b7b75e9086994aa27477efeb4";}i:114;O:57:"Symfony\Component\Config\Resource\ReflectionClassResource":4:{s:5:"files";a:1:{s:105:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/TaskOperation/ConsoleOutput.php";N;}s:9:"className";s:45:"Contao\ManagerApi\TaskOperation\ConsoleOutput";s:15:"excludedVendors";a:1:{i:0;s:76:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/vendor";}s:4:"hash";s:32:"28c20f40abd9d183db04dc4eb929742e";}i:115;O:57:"Symfony\Component\Config\Resource\ReflectionClassResource":4:{s:5:"files";a:3:{s:114:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/TaskOperation/TaskOperationInterface.php";N;s:120:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/TaskOperation/Contao/BackupCreateOperation.php";N;s:116:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/TaskOperation/AbstractProcessOperation.php";N;}s:9:"className";s:60:"Contao\ManagerApi\TaskOperation\Contao\BackupCreateOperation";s:15:"excludedVendors";a:1:{i:0;s:76:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/vendor";}s:4:"hash";s:32:"395ae9a3e8a139b9fd4909d368edbceb";}i:116;O:57:"Symfony\Component\Config\Resource\ReflectionClassResource":4:{s:5:"files";a:3:{s:114:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/TaskOperation/TaskOperationInterface.php";N;s:121:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/TaskOperation/Contao/BackupRestoreOperation.php";N;s:116:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/TaskOperation/AbstractProcessOperation.php";N;}s:9:"className";s:61:"Contao\ManagerApi\TaskOperation\Contao\BackupRestoreOperation";s:15:"excludedVendors";a:1:{i:0;s:76:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/vendor";}s:4:"hash";s:32:"727321d8f86eaa64fe2198aa2f2d6bd6";}i:117;O:57:"Symfony\Component\Config\Resource\ReflectionClassResource":4:{s:5:"files";a:3:{s:114:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/TaskOperation/TaskOperationInterface.php";N;s:118:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/TaskOperation/Contao/CacheClearOperation.php";N;s:116:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/TaskOperation/AbstractProcessOperation.php";N;}s:9:"className";s:58:"Contao\ManagerApi\TaskOperation\Contao\CacheClearOperation";s:15:"excludedVendors";a:1:{i:0;s:76:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/vendor";}s:4:"hash";s:32:"9571f2342ebb6d65dec2e36a62b7ebf6";}i:118;O:57:"Symfony\Component\Config\Resource\ReflectionClassResource":4:{s:5:"files";a:3:{s:114:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/TaskOperation/TaskOperationInterface.php";N;s:119:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/TaskOperation/Contao/CacheWarmupOperation.php";N;s:116:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/TaskOperation/AbstractProcessOperation.php";N;}s:9:"className";s:59:"Contao\ManagerApi\TaskOperation\Contao\CacheWarmupOperation";s:15:"excludedVendors";a:1:{i:0;s:76:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/vendor";}s:4:"hash";s:32:"c96dd354b83fab9e57c1fe03faa8780a";}i:119;O:57:"Symfony\Component\Config\Resource\ReflectionClassResource":4:{s:5:"files";a:3:{s:114:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/TaskOperation/TaskOperationInterface.php";N;s:120:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/TaskOperation/Contao/CreateContaoOperation.php";N;s:115:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/TaskOperation/AbstractInlineOperation.php";N;}s:9:"className";s:60:"Contao\ManagerApi\TaskOperation\Contao\CreateContaoOperation";s:15:"excludedVendors";a:1:{i:0;s:76:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/vendor";}s:4:"hash";s:32:"93b9dcca548760039661a97790fc5db6";}i:120;O:57:"Symfony\Component\Config\Resource\ReflectionClassResource":4:{s:5:"files";a:3:{s:114:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/TaskOperation/TaskOperationInterface.php";N;s:123:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/TaskOperation/Contao/MaintenanceModeOperation.php";N;s:115:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/TaskOperation/AbstractInlineOperation.php";N;}s:9:"className";s:63:"Contao\ManagerApi\TaskOperation\Contao\MaintenanceModeOperation";s:15:"excludedVendors";a:1:{i:0;s:76:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/vendor";}s:4:"hash";s:32:"1a20fc5bff17d426ea81825ce6b090cf";}i:121;O:57:"Symfony\Component\Config\Resource\ReflectionClassResource":4:{s:5:"files";a:3:{s:114:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/TaskOperation/TaskOperationInterface.php";N;s:126:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/TaskOperation/Filesystem/InstallUploadsOperation.php";N;s:115:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/TaskOperation/AbstractInlineOperation.php";N;}s:9:"className";s:66:"Contao\ManagerApi\TaskOperation\Filesystem\InstallUploadsOperation";s:15:"excludedVendors";a:1:{i:0;s:76:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/vendor";}s:4:"hash";s:32:"63104c3bb603a4e313f08ba872f6669b";}i:122;O:57:"Symfony\Component\Config\Resource\ReflectionClassResource":4:{s:5:"files";a:3:{s:114:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/TaskOperation/TaskOperationInterface.php";N;s:127:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/TaskOperation/Filesystem/RemoveArtifactsOperation.php";N;s:115:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/TaskOperation/AbstractInlineOperation.php";N;}s:9:"className";s:67:"Contao\ManagerApi\TaskOperation\Filesystem\RemoveArtifactsOperation";s:15:"excludedVendors";a:1:{i:0;s:76:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/vendor";}s:4:"hash";s:32:"ad368b1b23700e52b2ffc9c627b2d8a1";}i:123;O:57:"Symfony\Component\Config\Resource\ReflectionClassResource":4:{s:5:"files";a:3:{s:114:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/TaskOperation/TaskOperationInterface.php";N;s:123:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/TaskOperation/Filesystem/RemoveCacheOperation.php";N;s:115:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/TaskOperation/AbstractInlineOperation.php";N;}s:9:"className";s:63:"Contao\ManagerApi\TaskOperation\Filesystem\RemoveCacheOperation";s:15:"excludedVendors";a:1:{i:0;s:76:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/vendor";}s:4:"hash";s:32:"fe5a7d3a0d4f403743ce37723b70b776";}i:124;O:57:"Symfony\Component\Config\Resource\ReflectionClassResource":4:{s:5:"files";a:3:{s:114:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/TaskOperation/TaskOperationInterface.php";N;s:125:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/TaskOperation/Filesystem/RemoveUploadsOperation.php";N;s:115:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/TaskOperation/AbstractInlineOperation.php";N;}s:9:"className";s:65:"Contao\ManagerApi\TaskOperation\Filesystem\RemoveUploadsOperation";s:15:"excludedVendors";a:1:{i:0;s:76:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/vendor";}s:4:"hash";s:32:"b337f30b803423b886d35c68cf24ccdc";}i:125;O:57:"Symfony\Component\Config\Resource\ReflectionClassResource":4:{s:5:"files";a:3:{s:114:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/TaskOperation/TaskOperationInterface.php";N;s:124:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/TaskOperation/Filesystem/RemoveVendorOperation.php";N;s:115:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/TaskOperation/AbstractInlineOperation.php";N;}s:9:"className";s:64:"Contao\ManagerApi\TaskOperation\Filesystem\RemoveVendorOperation";s:15:"excludedVendors";a:1:{i:0;s:76:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/vendor";}s:4:"hash";s:32:"cc97f2b289f3560ea993b1b1fce79e11";}i:126;O:57:"Symfony\Component\Config\Resource\ReflectionClassResource":4:{s:5:"files";a:3:{s:114:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/TaskOperation/TaskOperationInterface.php";N;s:119:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/TaskOperation/Manager/SelfUpdateOperation.php";N;s:115:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/TaskOperation/AbstractInlineOperation.php";N;}s:9:"className";s:59:"Contao\ManagerApi\TaskOperation\Manager\SelfUpdateOperation";s:15:"excludedVendors";a:1:{i:0;s:76:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/vendor";}s:4:"hash";s:32:"634873be60ea4af391b0a083d98ab1af";}i:127;O:57:"Symfony\Component\Config\Resource\ReflectionClassResource":4:{s:5:"files";a:1:{s:119:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/TaskOperation/SponsoredOperationInterface.php";N;}s:9:"className";s:59:"Contao\ManagerApi\TaskOperation\SponsoredOperationInterface";s:15:"excludedVendors";a:1:{i:0;s:76:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/vendor";}s:4:"hash";s:32:"6697582dd04056e43a2bb1861101a7c2";}i:128;O:57:"Symfony\Component\Config\Resource\ReflectionClassResource":4:{s:5:"files";a:1:{s:114:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/TaskOperation/TaskOperationInterface.php";N;}s:9:"className";s:54:"Contao\ManagerApi\TaskOperation\TaskOperationInterface";s:15:"excludedVendors";a:1:{i:0;s:76:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/vendor";}s:4:"hash";s:32:"c2d47e9db093c49382867e14d8330c46";}i:129;O:46:"Symfony\Component\Config\Resource\GlobResource":6:{s:6:"prefix";s:73:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api";s:7:"pattern";s:2:"/*";s:9:"recursive";b:1;s:4:"hash";s:32:"d6e0d46bf26c084044caeabd056317bd";s:12:"forExclusion";b:0;s:16:"excludedPrefixes";a:4:{s:81:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/Command";b:1;s:84:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/Controller";b:1;s:83:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/Resources";b:1;s:79:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/Tests";b:1;}}i:130;O:57:"Symfony\Component\Config\Resource\ReflectionClassResource":4:{s:5:"files";a:1:{s:98:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/Command/AboutCommand.php";N;}s:9:"className";s:38:"Contao\ManagerApi\Command\AboutCommand";s:15:"excludedVendors";a:1:{i:0;s:76:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/vendor";}s:4:"hash";s:32:"cb18779f4e894c4f425ee74424b52092";}i:131;O:57:"Symfony\Component\Config\Resource\ReflectionClassResource":4:{s:5:"files";a:1:{s:107:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/Command/IntegrityCheckCommand.php";N;}s:9:"className";s:47:"Contao\ManagerApi\Command\IntegrityCheckCommand";s:15:"excludedVendors";a:1:{i:0;s:76:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/vendor";}s:4:"hash";s:32:"32b2749d6da87988aedf77141320c9ee";}i:132;O:57:"Symfony\Component\Config\Resource\ReflectionClassResource":4:{s:5:"files";a:1:{s:106:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/Command/ProcessRunnerCommand.php";N;}s:9:"className";s:46:"Contao\ManagerApi\Command\ProcessRunnerCommand";s:15:"excludedVendors";a:1:{i:0;s:76:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/vendor";}s:4:"hash";s:32:"09af8d08347783627ca18994348a6c3a";}i:133;O:57:"Symfony\Component\Config\Resource\ReflectionClassResource":4:{s:5:"files";a:2:{s:102:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/Command/TaskAbortCommand.php";N;s:103:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/Command/TaskUpdateCommand.php";N;}s:9:"className";s:42:"Contao\ManagerApi\Command\TaskAbortCommand";s:15:"excludedVendors";a:1:{i:0;s:76:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/vendor";}s:4:"hash";s:32:"3458a5370defbe816b4607f2b4aa5c98";}i:134;O:57:"Symfony\Component\Config\Resource\ReflectionClassResource":4:{s:5:"files";a:1:{s:103:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/Command/TaskDeleteCommand.php";N;}s:9:"className";s:43:"Contao\ManagerApi\Command\TaskDeleteCommand";s:15:"excludedVendors";a:1:{i:0;s:76:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/vendor";}s:4:"hash";s:32:"7b0df25fcbdba13a3df41f5cf13651c7";}i:135;O:57:"Symfony\Component\Config\Resource\ReflectionClassResource":4:{s:5:"files";a:1:{s:103:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/Command/TaskUpdateCommand.php";N;}s:9:"className";s:43:"Contao\ManagerApi\Command\TaskUpdateCommand";s:15:"excludedVendors";a:1:{i:0;s:76:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/vendor";}s:4:"hash";s:32:"89e00594ae5099bb1ffef53f7246888a";}i:136;O:57:"Symfony\Component\Config\Resource\ReflectionClassResource":4:{s:5:"files";a:1:{s:99:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/Command/UpdateCommand.php";N;}s:9:"className";s:39:"Contao\ManagerApi\Command\UpdateCommand";s:15:"excludedVendors";a:1:{i:0;s:76:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/vendor";}s:4:"hash";s:32:"6059406eaeac989e4a67ff6cd31b4944";}i:137;O:46:"Symfony\Component\Config\Resource\GlobResource":6:{s:6:"prefix";s:81:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/Command";s:7:"pattern";s:0:"";s:9:"recursive";b:1;s:4:"hash";s:32:"62718f0ac8c20e019ee010a26285c4f5";s:12:"forExclusion";b:0;s:16:"excludedPrefixes";a:0:{}}i:138;O:57:"Symfony\Component\Config\Resource\ReflectionClassResource":4:{s:5:"files";a:1:{s:120:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/Controller/Config/AbstractConfigController.php";N;}s:9:"className";s:60:"Contao\ManagerApi\Controller\Config\AbstractConfigController";s:15:"excludedVendors";a:1:{i:0;s:76:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/vendor";}s:4:"hash";s:32:"a7dc0ea79d9b3e3db82ded4657a3e59f";}i:139;O:57:"Symfony\Component\Config\Resource\ReflectionClassResource":4:{s:5:"files";a:2:{s:110:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/Controller/Config/AuthController.php";N;s:120:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/Controller/Config/AbstractConfigController.php";N;}s:9:"className";s:50:"Contao\ManagerApi\Controller\Config\AuthController";s:15:"excludedVendors";a:1:{i:0;s:76:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/vendor";}s:4:"hash";s:32:"e953d71b75c914d414f24e7f217b0d00";}i:140;O:57:"Symfony\Component\Config\Resource\ReflectionClassResource":4:{s:5:"files";a:2:{s:114:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/Controller/Config/ComposerController.php";N;s:120:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/Controller/Config/AbstractConfigController.php";N;}s:9:"className";s:54:"Contao\ManagerApi\Controller\Config\ComposerController";s:15:"excludedVendors";a:1:{i:0;s:76:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/vendor";}s:4:"hash";s:32:"72d59d38ddb8b8152e3cab477516cc38";}i:141;O:57:"Symfony\Component\Config\Resource\ReflectionClassResource":4:{s:5:"files";a:2:{s:113:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/Controller/Config/ManagerController.php";N;s:120:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/Controller/Config/AbstractConfigController.php";N;}s:9:"className";s:53:"Contao\ManagerApi\Controller\Config\ManagerController";s:15:"excludedVendors";a:1:{i:0;s:76:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/vendor";}s:4:"hash";s:32:"53703263771a0123a685fcaee9a0dc25";}i:142;O:57:"Symfony\Component\Config\Resource\ReflectionClassResource":4:{s:5:"files";a:1:{s:109:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/Controller/ConstraintController.php";N;}s:9:"className";s:49:"Contao\ManagerApi\Controller\ConstraintController";s:15:"excludedVendors";a:1:{i:0;s:76:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/vendor";}s:4:"hash";s:32:"1a95017f69b840b834b2d5b78cb6c98d";}i:143;O:57:"Symfony\Component\Config\Resource\ReflectionClassResource":4:{s:5:"files";a:1:{s:115:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/Controller/Contao/AccessKeyController.php";N;}s:9:"className";s:55:"Contao\ManagerApi\Controller\Contao\AccessKeyController";s:15:"excludedVendors";a:1:{i:0;s:76:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/vendor";}s:4:"hash";s:32:"23eba1f8b7b6e992495300d0352d7f04";}i:144;O:57:"Symfony\Component\Config\Resource\ReflectionClassResource":4:{s:5:"files";a:1:{s:112:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/Controller/Contao/BackupController.php";N;}s:9:"className";s:52:"Contao\ManagerApi\Controller\Contao\BackupController";s:15:"excludedVendors";a:1:{i:0;s:76:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/vendor";}s:4:"hash";s:32:"b9789dba64c637020bde13405834e11b";}i:145;O:57:"Symfony\Component\Config\Resource\ReflectionClassResource":4:{s:5:"files";a:1:{s:123:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/Controller/Contao/DatabaseMigrationController.php";N;}s:9:"className";s:63:"Contao\ManagerApi\Controller\Contao\DatabaseMigrationController";s:15:"excludedVendors";a:1:{i:0;s:76:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/vendor";}s:4:"hash";s:32:"a8253ebc01eb8dc12cf06ce08f3bdc61";}i:146;O:57:"Symfony\Component\Config\Resource\ReflectionClassResource":4:{s:5:"files";a:1:{s:121:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/Controller/Contao/InstallToolLockController.php";N;}s:9:"className";s:61:"Contao\ManagerApi\Controller\Contao\InstallToolLockController";s:15:"excludedVendors";a:1:{i:0;s:76:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/vendor";}s:4:"hash";s:32:"c0893acfe9aab439e1afdbb83077c881";}i:147;O:57:"Symfony\Component\Config\Resource\ReflectionClassResource":4:{s:5:"files";a:1:{s:115:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/Controller/Contao/JwtCookieController.php";N;}s:9:"className";s:55:"Contao\ManagerApi\Controller\Contao\JwtCookieController";s:15:"excludedVendors";a:1:{i:0;s:76:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/vendor";}s:4:"hash";s:32:"5a76629af45161bb728addcbbbde3ff3";}i:148;O:57:"Symfony\Component\Config\Resource\ReflectionClassResource":4:{s:5:"files";a:1:{s:121:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/Controller/Contao/MaintenanceModeController.php";N;}s:9:"className";s:61:"Contao\ManagerApi\Controller\Contao\MaintenanceModeController";s:15:"excludedVendors";a:1:{i:0;s:76:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/vendor";}s:4:"hash";s:32:"d9a064db93d41a4f6568762906885814";}i:149;O:57:"Symfony\Component\Config\Resource\ReflectionClassResource":4:{s:5:"files";a:1:{s:103:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/Controller/FileController.php";N;}s:9:"className";s:43:"Contao\ManagerApi\Controller\FileController";s:15:"excludedVendors";a:1:{i:0;s:76:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/vendor";}s:4:"hash";s:32:"acb3dccb3377576072b1de1fa88bb402";}i:150;O:57:"Symfony\Component\Config\Resource\ReflectionClassResource":4:{s:5:"files";a:1:{s:102:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/Controller/LogController.php";N;}s:9:"className";s:42:"Contao\ManagerApi\Controller\LogController";s:15:"excludedVendors";a:1:{i:0;s:76:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/vendor";}s:4:"hash";s:32:"e86dc3fa0f3789afc0556afa5f1ece24";}i:151;O:57:"Symfony\Component\Config\Resource\ReflectionClassResource":4:{s:5:"files";a:1:{s:113:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/Controller/Packages/CloudController.php";N;}s:9:"className";s:53:"Contao\ManagerApi\Controller\Packages\CloudController";s:15:"excludedVendors";a:1:{i:0;s:76:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/vendor";}s:4:"hash";s:32:"1e75c637e4047564e260d648c9ca7170";}i:152;O:57:"Symfony\Component\Config\Resource\ReflectionClassResource":4:{s:5:"files";a:1:{s:121:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/Controller/Packages/LocalPackagesController.php";N;}s:9:"className";s:61:"Contao\ManagerApi\Controller\Packages\LocalPackagesController";s:15:"excludedVendors";a:1:{i:0;s:76:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/vendor";}s:4:"hash";s:32:"af00ff0eecee91a8340393620aaf0e50";}i:153;O:57:"Symfony\Component\Config\Resource\ReflectionClassResource":4:{s:5:"files";a:1:{s:123:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/Controller/Packages/MissingPackagesController.php";N;}s:9:"className";s:63:"Contao\ManagerApi\Controller\Packages\MissingPackagesController";s:15:"excludedVendors";a:1:{i:0;s:76:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/vendor";}s:4:"hash";s:32:"a4822ae795aeb2e2731ec760135a5141";}i:154;O:57:"Symfony\Component\Config\Resource\ReflectionClassResource":4:{s:5:"files";a:1:{s:119:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/Controller/Packages/RootPackageController.php";N;}s:9:"className";s:59:"Contao\ManagerApi\Controller\Packages\RootPackageController";s:15:"excludedVendors";a:1:{i:0;s:76:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/vendor";}s:4:"hash";s:32:"2a892a0b85b8dff61b4a99136e14c851";}i:155;O:57:"Symfony\Component\Config\Resource\ReflectionClassResource":4:{s:5:"files";a:1:{s:122:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/Controller/Packages/UploadPackagesController.php";N;}s:9:"className";s:62:"Contao\ManagerApi\Controller\Packages\UploadPackagesController";s:15:"excludedVendors";a:1:{i:0;s:76:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/vendor";}s:4:"hash";s:32:"17f12ec24e54aced8d087895f86f3d94";}i:156;O:57:"Symfony\Component\Config\Resource\ReflectionClassResource":4:{s:5:"files";a:1:{s:115:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/Controller/Server/AdminUserController.php";N;}s:9:"className";s:55:"Contao\ManagerApi\Controller\Server\AdminUserController";s:15:"excludedVendors";a:1:{i:0;s:76:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/vendor";}s:4:"hash";s:32:"a9c3275d003c6a9aa82aa00b026ca50c";}i:157;O:57:"Symfony\Component\Config\Resource\ReflectionClassResource":4:{s:5:"files";a:1:{s:114:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/Controller/Server/ComposerController.php";N;}s:9:"className";s:54:"Contao\ManagerApi\Controller\Server\ComposerController";s:15:"excludedVendors";a:1:{i:0;s:76:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/vendor";}s:4:"hash";s:32:"93e9b3894f8ef2a93a88edd6d351ee94";}i:158;O:57:"Symfony\Component\Config\Resource\ReflectionClassResource":4:{s:5:"files";a:1:{s:112:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/Controller/Server/ConfigController.php";N;}s:9:"className";s:52:"Contao\ManagerApi\Controller\Server\ConfigController";s:15:"excludedVendors";a:1:{i:0;s:76:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/vendor";}s:4:"hash";s:32:"fdc329d9b756c832fab41c9b1a33e3a1";}i:159;O:57:"Symfony\Component\Config\Resource\ReflectionClassResource":4:{s:5:"files";a:1:{s:112:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/Controller/Server/ContaoController.php";N;}s:9:"className";s:52:"Contao\ManagerApi\Controller\Server\ContaoController";s:15:"excludedVendors";a:1:{i:0;s:76:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/vendor";}s:4:"hash";s:32:"b5b18740fa43cd6e838206ea6ca8f336";}i:160;O:57:"Symfony\Component\Config\Resource\ReflectionClassResource":4:{s:5:"files";a:1:{s:114:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/Controller/Server/DatabaseController.php";N;}s:9:"className";s:54:"Contao\ManagerApi\Controller\Server\DatabaseController";s:15:"excludedVendors";a:1:{i:0;s:76:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/vendor";}s:4:"hash";s:32:"a3bc13c4e29bd00824bc8a14ff7181be";}i:161;O:57:"Symfony\Component\Config\Resource\ReflectionClassResource":4:{s:5:"files";a:1:{s:113:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/Controller/Server/OpcacheController.php";N;}s:9:"className";s:53:"Contao\ManagerApi\Controller\Server\OpcacheController";s:15:"excludedVendors";a:1:{i:0;s:76:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/vendor";}s:4:"hash";s:32:"ec8059db7f31cb7d3ab82cf9040d70d5";}i:162;O:57:"Symfony\Component\Config\Resource\ReflectionClassResource":4:{s:5:"files";a:1:{s:112:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/Controller/Server/PhpCliController.php";N;}s:9:"className";s:52:"Contao\ManagerApi\Controller\Server\PhpCliController";s:15:"excludedVendors";a:1:{i:0;s:76:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/vendor";}s:4:"hash";s:32:"afb1ffcf2d53c8cfb66cc630e9d3d00a";}i:163;O:57:"Symfony\Component\Config\Resource\ReflectionClassResource":4:{s:5:"files";a:1:{s:112:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/Controller/Server/PhpWebController.php";N;}s:9:"className";s:52:"Contao\ManagerApi\Controller\Server\PhpWebController";s:15:"excludedVendors";a:1:{i:0;s:76:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/vendor";}s:4:"hash";s:32:"bd681d076edb4d93ef97f0b025e6e42c";}i:164;O:57:"Symfony\Component\Config\Resource\ReflectionClassResource":4:{s:5:"files";a:1:{s:113:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/Controller/Server/PhpinfoController.php";N;}s:9:"className";s:53:"Contao\ManagerApi\Controller\Server\PhpinfoController";s:15:"excludedVendors";a:1:{i:0;s:76:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/vendor";}s:4:"hash";s:32:"b18132712651baa79cdf21707a1534b6";}i:165;O:57:"Symfony\Component\Config\Resource\ReflectionClassResource":4:{s:5:"files";a:1:{s:116:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/Controller/Server/SelfUpdateController.php";N;}s:9:"className";s:56:"Contao\ManagerApi\Controller\Server\SelfUpdateController";s:15:"excludedVendors";a:1:{i:0;s:76:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/vendor";}s:4:"hash";s:32:"5db625c5dc9eb2013f08651df1169f5f";}i:166;O:57:"Symfony\Component\Config\Resource\ReflectionClassResource":4:{s:5:"files";a:1:{s:106:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/Controller/SessionController.php";N;}s:9:"className";s:46:"Contao\ManagerApi\Controller\SessionController";s:15:"excludedVendors";a:1:{i:0;s:76:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/vendor";}s:4:"hash";s:32:"6bbfa92f6155ec0b11d252aadeccd883";}i:167;O:57:"Symfony\Component\Config\Resource\ReflectionClassResource":4:{s:5:"files";a:1:{s:103:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/Controller/TaskController.php";N;}s:9:"className";s:43:"Contao\ManagerApi\Controller\TaskController";s:15:"excludedVendors";a:1:{i:0;s:76:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/vendor";}s:4:"hash";s:32:"973e0764dc25e0eda47e04254bf58169";}i:168;O:57:"Symfony\Component\Config\Resource\ReflectionClassResource":4:{s:5:"files";a:1:{s:103:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/Controller/UserController.php";N;}s:9:"className";s:43:"Contao\ManagerApi\Controller\UserController";s:15:"excludedVendors";a:1:{i:0;s:76:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/vendor";}s:4:"hash";s:32:"8f12ee01923fbe4f4cb07eacc408b231";}i:169;O:46:"Symfony\Component\Config\Resource\GlobResource":6:{s:6:"prefix";s:84:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/Controller";s:7:"pattern";s:0:"";s:9:"recursive";b:1;s:4:"hash";s:32:"44ff259308c9e1ec994dccfbe57a45e4";s:12:"forExclusion";b:0;s:16:"excludedPrefixes";a:0:{}}i:170;O:55:"Symfony\Component\Config\Resource\FileExistenceResource":2:{s:65:" Symfony\Component\Config\Resource\FileExistenceResource resource";s:96:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/test-dir/config/serializer";s:63:" Symfony\Component\Config\Resource\FileExistenceResource exists";b:0;}i:171;O:46:"Symfony\Component\Config\Resource\FileResource":1:{s:56:" Symfony\Component\Config\Resource\FileResource resource";s:156:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/vendor/symfony/http-kernel/Controller/ArgumentResolver/RequestPayloadValueResolver.php";}}<?php

namespace _ContaoManager;

// This file has been auto-generated by the Symfony Routing Component.
return ['contao_managerapi_config_auth_putgithubtoken' => [[], ['_controller' => '_ContaoManager\Contao\ManagerApi\Controller\Config\AuthController::putGithubToken'], [], [['text', '/api/config/auth/config/auth/github-oauth']], [], [], []], 'contao_managerapi_config_composer__invoke' => [[], ['_controller' => '_ContaoManager\Contao\ManagerApi\Controller\Config\ComposerController'], [], [['text', '/api/config/composer']], [], [], []], 'contao_managerapi_config_manager__invoke' => [[], ['_controller' => '_ContaoManager\Contao\ManagerApi\Controller\Config\ManagerController'], [], [['text', '/api/config/manager']], [], [], []], 'contao_managerapi_constraint__invoke' => [[], ['_controller' => '_ContaoManager\Contao\ManagerApi\Controller\ConstraintController'], [], [['text', '/api/constraint']], [], [], []], 'contao_managerapi_contao_accesskey__invoke' => [[], ['_controller' => '_ContaoManager\Contao\ManagerApi\Controller\Contao\AccessKeyController'], [], [['text', '/api/contao/access-key']], [], [], []], 'contao_managerapi_contao_backup__invoke' => [[], ['_controller' => '_ContaoManager\Contao\ManagerApi\Controller\Contao\BackupController'], [], [['text', '/api/contao/backup']], [], [], []], 'contao_managerapi_contao_databasemigration__invoke' => [[], ['_controller' => '_ContaoManager\Contao\ManagerApi\Controller\Contao\DatabaseMigrationController'], [], [['text', '/api/contao/database-migration']], [], [], []], 'contao_managerapi_contao_installtoollock__invoke' => [[], ['_controller' => '_ContaoManager\Contao\ManagerApi\Controller\Contao\InstallToolLockController'], [], [['text', '/api/contao/install-tool/lock']], [], [], []], 'contao_managerapi_contao_jwtcookie__invoke' => [[], ['_controller' => '_ContaoManager\Contao\ManagerApi\Controller\Contao\JwtCookieController'], [], [['text', '/api/contao/jwt-cookie']], [], [], []], 'contao_managerapi_contao_maintenancemode__invoke' => [[], ['_controller' => '_ContaoManager\Contao\ManagerApi\Controller\Contao\MaintenanceModeController'], [], [['text', '/api/contao/maintenance-mode']], [], [], []], 'contao_managerapi_file__invoke' => [['file'], ['_controller' => '_ContaoManager\Contao\ManagerApi\Controller\FileController'], [], [['variable', '/', '[^/]++', 'file', \true], ['text', '/api/files']], [], [], []], 'contao_managerapi_log_listfiles' => [[], ['_controller' => '_ContaoManager\Contao\ManagerApi\Controller\LogController::listFiles'], [], [['text', '/api/logs']], [], [], []], 'contao_managerapi_log_retrievefile' => [['filename'], ['_controller' => '_ContaoManager\Contao\ManagerApi\Controller\LogController::retrieveFile'], [], [['variable', '/', '[^/]++', 'filename', \true], ['text', '/api/logs']], [], [], []], 'contao_managerapi_log_deletefile' => [['filename'], ['_controller' => '_ContaoManager\Contao\ManagerApi\Controller\LogController::deleteFile'], [], [['variable', '/', '[^/]++', 'filename', \true], ['text', '/api/logs']], [], [], []], 'contao_managerapi_packages_cloud_getclouddata' => [[], ['_controller' => '_ContaoManager\Contao\ManagerApi\Controller\Packages\CloudController::getCloudData'], [], [['text', '/api/packages/cloud']], [], [], []], 'contao_managerapi_packages_cloud_writeandinstall' => [[], ['_controller' => '_ContaoManager\Contao\ManagerApi\Controller\Packages\CloudController::writeAndInstall'], [], [['text', '/api/packages/cloud']], [], [], []], 'contao_managerapi_packages_localpackages__invoke' => [[], ['_controller' => '_ContaoManager\Contao\ManagerApi\Controller\Packages\LocalPackagesController'], [], [['text', '/api/packages/local']], [], [], []], 'contao_managerapi_packages_localpackages__invoke_1' => [['name'], ['name' => null, '_controller' => '_ContaoManager\Contao\ManagerApi\Controller\Packages\LocalPackagesController'], ['name' => '.+'], [['variable', '/', '.+', 'name', \true], ['text', '/api/packages/local']], [], [], []], 'contao_managerapi_packages_missingpackages__invoke' => [[], ['_controller' => '_ContaoManager\Contao\ManagerApi\Controller\Packages\MissingPackagesController'], [], [['text', '/api/packages/missing']], [], [], []], 'contao_managerapi_packages_rootpackage__invoke' => [[], ['_controller' => '_ContaoManager\Contao\ManagerApi\Controller\Packages\RootPackageController'], [], [['text', '/api/packages/root']], [], [], []], 'contao_managerapi_packages_uploadpackages_read' => [[], ['_controller' => '_ContaoManager\Contao\ManagerApi\Controller\Packages\UploadPackagesController::read'], [], [['text', '/api/packages/uploads']], [], [], []], 'contao_managerapi_packages_uploadpackages_upload' => [[], ['form-data' => \true, '_controller' => '_ContaoManager\Contao\ManagerApi\Controller\Packages\UploadPackagesController::upload'], [], [['text', '/api/packages/uploads']], [], [], []], 'contao_managerapi_packages_uploadpackages_delete' => [['id'], ['_controller' => '_ContaoManager\Contao\ManagerApi\Controller\Packages\UploadPackagesController::delete'], [], [['variable', '/', '[^/]++', 'id', \true], ['text', '/api/packages/uploads']], [], [], []], 'contao_managerapi_server_adminuser__invoke' => [[], ['_controller' => '_ContaoManager\Contao\ManagerApi\Controller\Server\AdminUserController'], [], [['text', '/api/server/admin-user']], [], [], []], 'contao_managerapi_server_composer__invoke' => [[], ['_controller' => '_ContaoManager\Contao\ManagerApi\Controller\Server\ComposerController'], [], [['text', '/api/server/composer']], [], [], []], 'contao_managerapi_server_config_getconfig' => [[], ['_controller' => '_ContaoManager\Contao\ManagerApi\Controller\Server\ConfigController::getConfig'], [], [['text', '/api/server/config']], [], [], []], 'contao_managerapi_server_config_setconfig' => [[], ['_controller' => '_ContaoManager\Contao\ManagerApi\Controller\Server\ConfigController::setConfig'], [], [['text', '/api/server/config']], [], [], []], 'contao_managerapi_server_contao_handle' => [[], ['_controller' => '_ContaoManager\Contao\ManagerApi\Controller\Server\ContaoController::handle'], [], [['text', '/api/server/contao']], [], [], []], 'contao_managerapi_server_contao_update' => [[], ['_controller' => '_ContaoManager\Contao\ManagerApi\Controller\Server\ContaoController::update'], [], [['text', '/api/server/contao']], [], [], []], 'contao_managerapi_server_database_handle' => [[], ['_controller' => '_ContaoManager\Contao\ManagerApi\Controller\Server\DatabaseController::handle'], [], [['text', '/api/server/database']], [], [], []], 'contao_managerapi_server_database_write' => [[], ['_controller' => '_ContaoManager\Contao\ManagerApi\Controller\Server\DatabaseController::write'], [], [['text', '/api/server/database']], [], [], []], 'contao_managerapi_server_opcache_getopcache' => [[], ['_controller' => '_ContaoManager\Contao\ManagerApi\Controller\Server\OpcacheController::getOpcache'], [], [['text', '/api/server/opcache']], [], [], []], 'contao_managerapi_server_opcache_deleteopcache' => [[], ['_controller' => '_ContaoManager\Contao\ManagerApi\Controller\Server\OpcacheController::deleteOpcache'], [], [['text', '/api/server/opcache']], [], [], []], 'contao_managerapi_server_phpcli__invoke' => [[], ['_controller' => '_ContaoManager\Contao\ManagerApi\Controller\Server\PhpCliController'], [], [['text', '/api/server/php-cli']], [], [], []], 'contao_managerapi_server_phpweb__invoke' => [[], ['_controller' => '_ContaoManager\Contao\ManagerApi\Controller\Server\PhpWebController'], [], [['text', '/api/server/php-web']], [], [], []], 'contao_managerapi_server_phpinfo__invoke' => [[], ['_controller' => '_ContaoManager\Contao\ManagerApi\Controller\Server\PhpinfoController'], [], [['text', '/api/server/phpinfo']], [], [], []], 'contao_managerapi_server_selfupdate__invoke' => [[], ['_controller' => '_ContaoManager\Contao\ManagerApi\Controller\Server\SelfUpdateController'], [], [['text', '/api/server/self-update']], [], [], []], 'contao_managerapi_session_getsession' => [[], ['_controller' => '_ContaoManager\Contao\ManagerApi\Controller\SessionController::getSession'], [], [['text', '/api/session']], [], [], []], 'contao_managerapi_session_getwebauthnoptions' => [[], ['_controller' => '_ContaoManager\Contao\ManagerApi\Controller\SessionController::getWebauthnOptions'], [], [['text', '/api/session/options']], [], [], []], 'contao_managerapi_task__invoke' => [[], ['_controller' => '_ContaoManager\Contao\ManagerApi\Controller\TaskController'], [], [['text', '/api/task']], [], [], []], 'contao_managerapi_user_listusers' => [[], ['_controller' => '_ContaoManager\Contao\ManagerApi\Controller\UserController::listUsers'], [], [['text', '/api/users']], [], [], []], 'contao_managerapi_user_createuser' => [[], ['_controller' => '_ContaoManager\Contao\ManagerApi\Controller\UserController::createUser'], [], [['text', '/api/users']], [], [], []], 'user_get' => [['username'], ['_controller' => '_ContaoManager\Contao\ManagerApi\Controller\UserController::retrieveUser'], [], [['variable', '/', '[^/]++', 'username', \true], ['text', '/api/users']], [], [], []], 'contao_managerapi_user_replaceuser' => [['username'], ['_controller' => '_ContaoManager\Contao\ManagerApi\Controller\UserController::replaceUser'], [], [['variable', '/', '[^/]++', 'username', \true], ['text', '/api/users']], [], [], []], 'contao_managerapi_user_deleteuser' => [['username'], ['_controller' => '_ContaoManager\Contao\ManagerApi\Controller\UserController::deleteUser'], [], [['variable', '/', '[^/]++', 'username', \true], ['text', '/api/users']], [], [], []], 'contao_managerapi_user_setpassword' => [['username'], ['_controller' => '_ContaoManager\Contao\ManagerApi\Controller\UserController::setPassword'], [], [['text', '/password'], ['variable', '/', '[^/]++', 'username', \true], ['text', '/api/users']], [], [], []], 'contao_managerapi_user_gettotp' => [['username'], ['_controller' => '_ContaoManager\Contao\ManagerApi\Controller\UserController::getTOTP'], [], [['text', '/totp'], ['variable', '/', '[^/]++', 'username', \true], ['text', '/api/users']], [], [], []], 'contao_managerapi_user_setuptotp' => [['username'], ['_controller' => '_ContaoManager\Contao\ManagerApi\Controller\UserController::setupTotp'], [], [['text', '/totp'], ['variable', '/', '[^/]++', 'username', \true], ['text', '/api/users']], [], [], []], 'contao_managerapi_user_deletetotp' => [['username'], ['_controller' => '_ContaoManager\Contao\ManagerApi\Controller\UserController::deleteTotp'], [], [['text', '/totp'], ['variable', '/', '[^/]++', 'username', \true], ['text', '/api/users']], [], [], []], 'contao_managerapi_user_listtokens' => [['username'], ['_controller' => '_ContaoManager\Contao\ManagerApi\Controller\UserController::listTokens'], [], [['text', '/tokens'], ['variable', '/', '[^/]++', 'username', \true], ['text', '/api/users']], [], [], []], 'contao_managerapi_user_createtoken' => [['username'], ['_controller' => '_ContaoManager\Contao\ManagerApi\Controller\UserController::createToken'], [], [['text', '/tokens'], ['variable', '/', '[^/]++', 'username', \true], ['text', '/api/users']], [], [], []], 'contao_managerapi_user_retrievetoken' => [['username', 'id'], ['_controller' => '_ContaoManager\Contao\ManagerApi\Controller\UserController::retrieveToken'], [], [['variable', '/', '[^/]++', 'id', \true], ['text', '/tokens'], ['variable', '/', '[^/]++', 'username', \true], ['text', '/api/users']], [], [], []], 'contao_managerapi_user_deletetoken' => [['username', 'id'], ['_controller' => '_ContaoManager\Contao\ManagerApi\Controller\UserController::deleteToken'], [], [['variable', '/', '[^/]++', 'id', \true], ['text', '/tokens'], ['variable', '/', '[^/]++', 'username', \true], ['text', '/api/users']], [], [], []], 'contao_managerapi_user_inviteuser' => [[], ['_controller' => '_ContaoManager\Contao\ManagerApi\Controller\UserController::inviteUser'], [], [['text', '/api/invitations']], [], [], []], '_ContaoManager\Contao\ManagerApi\Controller\Config\AuthController::putGithubToken' => [[], ['_controller' => '_ContaoManager\Contao\ManagerApi\Controller\Config\AuthController::putGithubToken'], [], [['text', '/api/config/auth/config/auth/github-oauth']], [], [], []], '_ContaoManager\Contao\ManagerApi\Controller\Config\ComposerController' => [[], ['_controller' => '_ContaoManager\Contao\ManagerApi\Controller\Config\ComposerController'], [], [['text', '/api/config/composer']], [], [], []], '_ContaoManager\Contao\ManagerApi\Controller\Config\ComposerController::__invoke' => [[], ['_controller' => '_ContaoManager\Contao\ManagerApi\Controller\Config\ComposerController'], [], [['text', '/api/config/composer']], [], [], []], '_ContaoManager\Contao\ManagerApi\Controller\Config\ManagerController' => [[], ['_controller' => '_ContaoManager\Contao\ManagerApi\Controller\Config\ManagerController'], [], [['text', '/api/config/manager']], [], [], []], '_ContaoManager\Contao\ManagerApi\Controller\Config\ManagerController::__invoke' => [[], ['_controller' => '_ContaoManager\Contao\ManagerApi\Controller\Config\ManagerController'], [], [['text', '/api/config/manager']], [], [], []], '_ContaoManager\Contao\ManagerApi\Controller\ConstraintController' => [[], ['_controller' => '_ContaoManager\Contao\ManagerApi\Controller\ConstraintController'], [], [['text', '/api/constraint']], [], [], []], '_ContaoManager\Contao\ManagerApi\Controller\ConstraintController::__invoke' => [[], ['_controller' => '_ContaoManager\Contao\ManagerApi\Controller\ConstraintController'], [], [['text', '/api/constraint']], [], [], []], '_ContaoManager\Contao\ManagerApi\Controller\Contao\AccessKeyController' => [[], ['_controller' => '_ContaoManager\Contao\ManagerApi\Controller\Contao\AccessKeyController'], [], [['text', '/api/contao/access-key']], [], [], []], '_ContaoManager\Contao\ManagerApi\Controller\Contao\AccessKeyController::__invoke' => [[], ['_controller' => '_ContaoManager\Contao\ManagerApi\Controller\Contao\AccessKeyController'], [], [['text', '/api/contao/access-key']], [], [], []], '_ContaoManager\Contao\ManagerApi\Controller\Contao\BackupController' => [[], ['_controller' => '_ContaoManager\Contao\ManagerApi\Controller\Contao\BackupController'], [], [['text', '/api/contao/backup']], [], [], []], '_ContaoManager\Contao\ManagerApi\Controller\Contao\BackupController::__invoke' => [[], ['_controller' => '_ContaoManager\Contao\ManagerApi\Controller\Contao\BackupController'], [], [['text', '/api/contao/backup']], [], [], []], '_ContaoManager\Contao\ManagerApi\Controller\Contao\DatabaseMigrationController' => [[], ['_controller' => '_ContaoManager\Contao\ManagerApi\Controller\Contao\DatabaseMigrationController'], [], [['text', '/api/contao/database-migration']], [], [], []], '_ContaoManager\Contao\ManagerApi\Controller\Contao\DatabaseMigrationController::__invoke' => [[], ['_controller' => '_ContaoManager\Contao\ManagerApi\Controller\Contao\DatabaseMigrationController'], [], [['text', '/api/contao/database-migration']], [], [], []], '_ContaoManager\Contao\ManagerApi\Controller\Contao\InstallToolLockController' => [[], ['_controller' => '_ContaoManager\Contao\ManagerApi\Controller\Contao\InstallToolLockController'], [], [['text', '/api/contao/install-tool/lock']], [], [], []], '_ContaoManager\Contao\ManagerApi\Controller\Contao\InstallToolLockController::__invoke' => [[], ['_controller' => '_ContaoManager\Contao\ManagerApi\Controller\Contao\InstallToolLockController'], [], [['text', '/api/contao/install-tool/lock']], [], [], []], '_ContaoManager\Contao\ManagerApi\Controller\Contao\JwtCookieController' => [[], ['_controller' => '_ContaoManager\Contao\ManagerApi\Controller\Contao\JwtCookieController'], [], [['text', '/api/contao/jwt-cookie']], [], [], []], '_ContaoManager\Contao\ManagerApi\Controller\Contao\JwtCookieController::__invoke' => [[], ['_controller' => '_ContaoManager\Contao\ManagerApi\Controller\Contao\JwtCookieController'], [], [['text', '/api/contao/jwt-cookie']], [], [], []], '_ContaoManager\Contao\ManagerApi\Controller\Contao\MaintenanceModeController' => [[], ['_controller' => '_ContaoManager\Contao\ManagerApi\Controller\Contao\MaintenanceModeController'], [], [['text', '/api/contao/maintenance-mode']], [], [], []], '_ContaoManager\Contao\ManagerApi\Controller\Contao\MaintenanceModeController::__invoke' => [[], ['_controller' => '_ContaoManager\Contao\ManagerApi\Controller\Contao\MaintenanceModeController'], [], [['text', '/api/contao/maintenance-mode']], [], [], []], '_ContaoManager\Contao\ManagerApi\Controller\FileController' => [['file'], ['_controller' => '_ContaoManager\Contao\ManagerApi\Controller\FileController'], [], [['variable', '/', '[^/]++', 'file', \true], ['text', '/api/files']], [], [], []], '_ContaoManager\Contao\ManagerApi\Controller\FileController::__invoke' => [['file'], ['_controller' => '_ContaoManager\Contao\ManagerApi\Controller\FileController'], [], [['variable', '/', '[^/]++', 'file', \true], ['text', '/api/files']], [], [], []], '_ContaoManager\Contao\ManagerApi\Controller\LogController::listFiles' => [[], ['_controller' => '_ContaoManager\Contao\ManagerApi\Controller\LogController::listFiles'], [], [['text', '/api/logs']], [], [], []], '_ContaoManager\Contao\ManagerApi\Controller\LogController::retrieveFile' => [['filename'], ['_controller' => '_ContaoManager\Contao\ManagerApi\Controller\LogController::retrieveFile'], [], [['variable', '/', '[^/]++', 'filename', \true], ['text', '/api/logs']], [], [], []], '_ContaoManager\Contao\ManagerApi\Controller\LogController::deleteFile' => [['filename'], ['_controller' => '_ContaoManager\Contao\ManagerApi\Controller\LogController::deleteFile'], [], [['variable', '/', '[^/]++', 'filename', \true], ['text', '/api/logs']], [], [], []], '_ContaoManager\Contao\ManagerApi\Controller\Packages\CloudController::getCloudData' => [[], ['_controller' => '_ContaoManager\Contao\ManagerApi\Controller\Packages\CloudController::getCloudData'], [], [['text', '/api/packages/cloud']], [], [], []], '_ContaoManager\Contao\ManagerApi\Controller\Packages\CloudController::writeAndInstall' => [[], ['_controller' => '_ContaoManager\Contao\ManagerApi\Controller\Packages\CloudController::writeAndInstall'], [], [['text', '/api/packages/cloud']], [], [], []], '_ContaoManager\Contao\ManagerApi\Controller\Packages\MissingPackagesController' => [[], ['_controller' => '_ContaoManager\Contao\ManagerApi\Controller\Packages\MissingPackagesController'], [], [['text', '/api/packages/missing']], [], [], []], '_ContaoManager\Contao\ManagerApi\Controller\Packages\MissingPackagesController::__invoke' => [[], ['_controller' => '_ContaoManager\Contao\ManagerApi\Controller\Packages\MissingPackagesController'], [], [['text', '/api/packages/missing']], [], [], []], '_ContaoManager\Contao\ManagerApi\Controller\Packages\RootPackageController' => [[], ['_controller' => '_ContaoManager\Contao\ManagerApi\Controller\Packages\RootPackageController'], [], [['text', '/api/packages/root']], [], [], []], '_ContaoManager\Contao\ManagerApi\Controller\Packages\RootPackageController::__invoke' => [[], ['_controller' => '_ContaoManager\Contao\ManagerApi\Controller\Packages\RootPackageController'], [], [['text', '/api/packages/root']], [], [], []], '_ContaoManager\Contao\ManagerApi\Controller\Packages\UploadPackagesController::read' => [[], ['_controller' => '_ContaoManager\Contao\ManagerApi\Controller\Packages\UploadPackagesController::read'], [], [['text', '/api/packages/uploads']], [], [], []], '_ContaoManager\Contao\ManagerApi\Controller\Packages\UploadPackagesController::upload' => [[], ['form-data' => \true, '_controller' => '_ContaoManager\Contao\ManagerApi\Controller\Packages\UploadPackagesController::upload'], [], [['text', '/api/packages/uploads']], [], [], []], '_ContaoManager\Contao\ManagerApi\Controller\Packages\UploadPackagesController::delete' => [['id'], ['_controller' => '_ContaoManager\Contao\ManagerApi\Controller\Packages\UploadPackagesController::delete'], [], [['variable', '/', '[^/]++', 'id', \true], ['text', '/api/packages/uploads']], [], [], []], '_ContaoManager\Contao\ManagerApi\Controller\Server\AdminUserController' => [[], ['_controller' => '_ContaoManager\Contao\ManagerApi\Controller\Server\AdminUserController'], [], [['text', '/api/server/admin-user']], [], [], []], '_ContaoManager\Contao\ManagerApi\Controller\Server\AdminUserController::__invoke' => [[], ['_controller' => '_ContaoManager\Contao\ManagerApi\Controller\Server\AdminUserController'], [], [['text', '/api/server/admin-user']], [], [], []], '_ContaoManager\Contao\ManagerApi\Controller\Server\ComposerController' => [[], ['_controller' => '_ContaoManager\Contao\ManagerApi\Controller\Server\ComposerController'], [], [['text', '/api/server/composer']], [], [], []], '_ContaoManager\Contao\ManagerApi\Controller\Server\ComposerController::__invoke' => [[], ['_controller' => '_ContaoManager\Contao\ManagerApi\Controller\Server\ComposerController'], [], [['text', '/api/server/composer']], [], [], []], '_ContaoManager\Contao\ManagerApi\Controller\Server\ConfigController::getConfig' => [[], ['_controller' => '_ContaoManager\Contao\ManagerApi\Controller\Server\ConfigController::getConfig'], [], [['text', '/api/server/config']], [], [], []], '_ContaoManager\Contao\ManagerApi\Controller\Server\ConfigController::setConfig' => [[], ['_controller' => '_ContaoManager\Contao\ManagerApi\Controller\Server\ConfigController::setConfig'], [], [['text', '/api/server/config']], [], [], []], '_ContaoManager\Contao\ManagerApi\Controller\Server\ContaoController::handle' => [[], ['_controller' => '_ContaoManager\Contao\ManagerApi\Controller\Server\ContaoController::handle'], [], [['text', '/api/server/contao']], [], [], []], '_ContaoManager\Contao\ManagerApi\Controller\Server\ContaoController::update' => [[], ['_controller' => '_ContaoManager\Contao\ManagerApi\Controller\Server\ContaoController::update'], [], [['text', '/api/server/contao']], [], [], []], '_ContaoManager\Contao\ManagerApi\Controller\Server\DatabaseController::handle' => [[], ['_controller' => '_ContaoManager\Contao\ManagerApi\Controller\Server\DatabaseController::handle'], [], [['text', '/api/server/database']], [], [], []], '_ContaoManager\Contao\ManagerApi\Controller\Server\DatabaseController::write' => [[], ['_controller' => '_ContaoManager\Contao\ManagerApi\Controller\Server\DatabaseController::write'], [], [['text', '/api/server/database']], [], [], []], '_ContaoManager\Contao\ManagerApi\Controller\Server\OpcacheController::getOpcache' => [[], ['_controller' => '_ContaoManager\Contao\ManagerApi\Controller\Server\OpcacheController::getOpcache'], [], [['text', '/api/server/opcache']], [], [], []], '_ContaoManager\Contao\ManagerApi\Controller\Server\OpcacheController::deleteOpcache' => [[], ['_controller' => '_ContaoManager\Contao\ManagerApi\Controller\Server\OpcacheController::deleteOpcache'], [], [['text', '/api/server/opcache']], [], [], []], '_ContaoManager\Contao\ManagerApi\Controller\Server\PhpCliController' => [[], ['_controller' => '_ContaoManager\Contao\ManagerApi\Controller\Server\PhpCliController'], [], [['text', '/api/server/php-cli']], [], [], []], '_ContaoManager\Contao\ManagerApi\Controller\Server\PhpCliController::__invoke' => [[], ['_controller' => '_ContaoManager\Contao\ManagerApi\Controller\Server\PhpCliController'], [], [['text', '/api/server/php-cli']], [], [], []], '_ContaoManager\Contao\ManagerApi\Controller\Server\PhpWebController' => [[], ['_controller' => '_ContaoManager\Contao\ManagerApi\Controller\Server\PhpWebController'], [], [['text', '/api/server/php-web']], [], [], []], '_ContaoManager\Contao\ManagerApi\Controller\Server\PhpWebController::__invoke' => [[], ['_controller' => '_ContaoManager\Contao\ManagerApi\Controller\Server\PhpWebController'], [], [['text', '/api/server/php-web']], [], [], []], '_ContaoManager\Contao\ManagerApi\Controller\Server\PhpinfoController' => [[], ['_controller' => '_ContaoManager\Contao\ManagerApi\Controller\Server\PhpinfoController'], [], [['text', '/api/server/phpinfo']], [], [], []], '_ContaoManager\Contao\ManagerApi\Controller\Server\PhpinfoController::__invoke' => [[], ['_controller' => '_ContaoManager\Contao\ManagerApi\Controller\Server\PhpinfoController'], [], [['text', '/api/server/phpinfo']], [], [], []], '_ContaoManager\Contao\ManagerApi\Controller\Server\SelfUpdateController' => [[], ['_controller' => '_ContaoManager\Contao\ManagerApi\Controller\Server\SelfUpdateController'], [], [['text', '/api/server/self-update']], [], [], []], '_ContaoManager\Contao\ManagerApi\Controller\Server\SelfUpdateController::__invoke' => [[], ['_controller' => '_ContaoManager\Contao\ManagerApi\Controller\Server\SelfUpdateController'], [], [['text', '/api/server/self-update']], [], [], []], '_ContaoManager\Contao\ManagerApi\Controller\SessionController::getSession' => [[], ['_controller' => '_ContaoManager\Contao\ManagerApi\Controller\SessionController::getSession'], [], [['text', '/api/session']], [], [], []], '_ContaoManager\Contao\ManagerApi\Controller\SessionController::getWebauthnOptions' => [[], ['_controller' => '_ContaoManager\Contao\ManagerApi\Controller\SessionController::getWebauthnOptions'], [], [['text', '/api/session/options']], [], [], []], '_ContaoManager\Contao\ManagerApi\Controller\TaskController' => [[], ['_controller' => '_ContaoManager\Contao\ManagerApi\Controller\TaskController'], [], [['text', '/api/task']], [], [], []], '_ContaoManager\Contao\ManagerApi\Controller\TaskController::__invoke' => [[], ['_controller' => '_ContaoManager\Contao\ManagerApi\Controller\TaskController'], [], [['text', '/api/task']], [], [], []], '_ContaoManager\Contao\ManagerApi\Controller\UserController::listUsers' => [[], ['_controller' => '_ContaoManager\Contao\ManagerApi\Controller\UserController::listUsers'], [], [['text', '/api/users']], [], [], []], '_ContaoManager\Contao\ManagerApi\Controller\UserController::createUser' => [[], ['_controller' => '_ContaoManager\Contao\ManagerApi\Controller\UserController::createUser'], [], [['text', '/api/users']], [], [], []], '_ContaoManager\Contao\ManagerApi\Controller\UserController::retrieveUser' => [['username'], ['_controller' => '_ContaoManager\Contao\ManagerApi\Controller\UserController::retrieveUser'], [], [['variable', '/', '[^/]++', 'username', \true], ['text', '/api/users']], [], [], []], '_ContaoManager\Contao\ManagerApi\Controller\UserController::replaceUser' => [['username'], ['_controller' => '_ContaoManager\Contao\ManagerApi\Controller\UserController::replaceUser'], [], [['variable', '/', '[^/]++', 'username', \true], ['text', '/api/users']], [], [], []], '_ContaoManager\Contao\ManagerApi\Controller\UserController::deleteUser' => [['username'], ['_controller' => '_ContaoManager\Contao\ManagerApi\Controller\UserController::deleteUser'], [], [['variable', '/', '[^/]++', 'username', \true], ['text', '/api/users']], [], [], []], '_ContaoManager\Contao\ManagerApi\Controller\UserController::setPassword' => [['username'], ['_controller' => '_ContaoManager\Contao\ManagerApi\Controller\UserController::setPassword'], [], [['text', '/password'], ['variable', '/', '[^/]++', 'username', \true], ['text', '/api/users']], [], [], []], '_ContaoManager\Contao\ManagerApi\Controller\UserController::getTOTP' => [['username'], ['_controller' => '_ContaoManager\Contao\ManagerApi\Controller\UserController::getTOTP'], [], [['text', '/totp'], ['variable', '/', '[^/]++', 'username', \true], ['text', '/api/users']], [], [], []], '_ContaoManager\Contao\ManagerApi\Controller\UserController::setupTotp' => [['username'], ['_controller' => '_ContaoManager\Contao\ManagerApi\Controller\UserController::setupTotp'], [], [['text', '/totp'], ['variable', '/', '[^/]++', 'username', \true], ['text', '/api/users']], [], [], []], '_ContaoManager\Contao\ManagerApi\Controller\UserController::deleteTotp' => [['username'], ['_controller' => '_ContaoManager\Contao\ManagerApi\Controller\UserController::deleteTotp'], [], [['text', '/totp'], ['variable', '/', '[^/]++', 'username', \true], ['text', '/api/users']], [], [], []], '_ContaoManager\Contao\ManagerApi\Controller\UserController::listTokens' => [['username'], ['_controller' => '_ContaoManager\Contao\ManagerApi\Controller\UserController::listTokens'], [], [['text', '/tokens'], ['variable', '/', '[^/]++', 'username', \true], ['text', '/api/users']], [], [], []], '_ContaoManager\Contao\ManagerApi\Controller\UserController::createToken' => [['username'], ['_controller' => '_ContaoManager\Contao\ManagerApi\Controller\UserController::createToken'], [], [['text', '/tokens'], ['variable', '/', '[^/]++', 'username', \true], ['text', '/api/users']], [], [], []], '_ContaoManager\Contao\ManagerApi\Controller\UserController::retrieveToken' => [['username', 'id'], ['_controller' => '_ContaoManager\Contao\ManagerApi\Controller\UserController::retrieveToken'], [], [['variable', '/', '[^/]++', 'id', \true], ['text', '/tokens'], ['variable', '/', '[^/]++', 'username', \true], ['text', '/api/users']], [], [], []], '_ContaoManager\Contao\ManagerApi\Controller\UserController::deleteToken' => [['username', 'id'], ['_controller' => '_ContaoManager\Contao\ManagerApi\Controller\UserController::deleteToken'], [], [['variable', '/', '[^/]++', 'id', \true], ['text', '/tokens'], ['variable', '/', '[^/]++', 'username', \true], ['text', '/api/users']], [], [], []], '_ContaoManager\Contao\ManagerApi\Controller\UserController::inviteUser' => [[], ['_controller' => '_ContaoManager\Contao\ManagerApi\Controller\UserController::inviteUser'], [], [['text', '/api/invitations']], [], [], []]];
<?php

namespace _ContaoManager;

/**
 * This file has been auto-generated
 * by the Symfony Routing Component.
 */
return [
    \false,
    // $matchHost
    [
        // $staticRoutes
        '/api/config/auth/config/auth/github-oauth' => [[['_route' => 'contao_managerapi_config_auth_putgithubtoken', '_controller' => '_ContaoManager\Contao\ManagerApi\Controller\Config\AuthController::putGithubToken'], null, ['GET' => 0, 'PUT' => 1, 'PATCH' => 2], null, \false, \false, null]],
        '/api/config/composer' => [[['_route' => 'contao_managerapi_config_composer__invoke', '_controller' => '_ContaoManager\Contao\ManagerApi\Controller\Config\ComposerController'], null, ['GET' => 0, 'PUT' => 1, 'PATCH' => 2], null, \false, \false, null]],
        '/api/config/manager' => [[['_route' => 'contao_managerapi_config_manager__invoke', '_controller' => '_ContaoManager\Contao\ManagerApi\Controller\Config\ManagerController'], null, ['GET' => 0, 'PUT' => 1, 'PATCH' => 2], null, \false, \false, null]],
        '/api/constraint' => [[['_route' => 'contao_managerapi_constraint__invoke', '_controller' => '_ContaoManager\Contao\ManagerApi\Controller\ConstraintController'], null, ['POST' => 0], null, \false, \false, null]],
        '/api/contao/access-key' => [[['_route' => 'contao_managerapi_contao_accesskey__invoke', '_controller' => '_ContaoManager\Contao\ManagerApi\Controller\Contao\AccessKeyController'], null, ['GET' => 0, 'PUT' => 1, 'DELETE' => 2], null, \false, \false, null]],
        '/api/contao/backup' => [[['_route' => 'contao_managerapi_contao_backup__invoke', '_controller' => '_ContaoManager\Contao\ManagerApi\Controller\Contao\BackupController'], null, ['GET' => 0], null, \false, \false, null]],
        '/api/contao/database-migration' => [[['_route' => 'contao_managerapi_contao_databasemigration__invoke', '_controller' => '_ContaoManager\Contao\ManagerApi\Controller\Contao\DatabaseMigrationController'], null, ['GET' => 0, 'PUT' => 1, 'DELETE' => 2], null, \false, \false, null]],
        '/api/contao/install-tool/lock' => [[['_route' => 'contao_managerapi_contao_installtoollock__invoke', '_controller' => '_ContaoManager\Contao\ManagerApi\Controller\Contao\InstallToolLockController'], null, ['GET' => 0, 'PUT' => 1, 'DELETE' => 2], null, \false, \false, null]],
        '/api/contao/jwt-cookie' => [[['_route' => 'contao_managerapi_contao_jwtcookie__invoke', '_controller' => '_ContaoManager\Contao\ManagerApi\Controller\Contao\JwtCookieController'], null, ['GET' => 0, 'PUT' => 1, 'DELETE' => 2], null, \false, \false, null]],
        '/api/contao/maintenance-mode' => [[['_route' => 'contao_managerapi_contao_maintenancemode__invoke', '_controller' => '_ContaoManager\Contao\ManagerApi\Controller\Contao\MaintenanceModeController'], null, ['GET' => 0, 'PUT' => 1, 'DELETE' => 2], null, \false, \false, null]],
        '/api/logs' => [[['_route' => 'contao_managerapi_log_listfiles', '_controller' => '_ContaoManager\Contao\ManagerApi\Controller\LogController::listFiles'], null, ['GET' => 0], null, \false, \false, null]],
        '/api/packages/cloud' => [[['_route' => 'contao_managerapi_packages_cloud_getclouddata', '_controller' => '_ContaoManager\Contao\ManagerApi\Controller\Packages\CloudController::getCloudData'], null, ['GET' => 0], null, \false, \false, null], [['_route' => 'contao_managerapi_packages_cloud_writeandinstall', '_controller' => '_ContaoManager\Contao\ManagerApi\Controller\Packages\CloudController::writeAndInstall'], null, ['PUT' => 0], null, \false, \false, null]],
        '/api/packages/local' => [[['_route' => 'contao_managerapi_packages_localpackages__invoke', '_controller' => '_ContaoManager\Contao\ManagerApi\Controller\Packages\LocalPackagesController'], null, ['GET' => 0], null, \false, \false, null]],
        '/api/packages/missing' => [[['_route' => 'contao_managerapi_packages_missingpackages__invoke', '_controller' => '_ContaoManager\Contao\ManagerApi\Controller\Packages\MissingPackagesController'], null, ['GET' => 0], null, \false, \false, null]],
        '/api/packages/root' => [[['_route' => 'contao_managerapi_packages_rootpackage__invoke', '_controller' => '_ContaoManager\Contao\ManagerApi\Controller\Packages\RootPackageController'], null, ['GET' => 0], null, \false, \false, null]],
        '/api/packages/uploads' => [[['_route' => 'contao_managerapi_packages_uploadpackages_read', '_controller' => '_ContaoManager\Contao\ManagerApi\Controller\Packages\UploadPackagesController::read'], null, ['GET' => 0], null, \false, \false, null], [['_route' => 'contao_managerapi_packages_uploadpackages_upload', 'form-data' => \true, '_controller' => '_ContaoManager\Contao\ManagerApi\Controller\Packages\UploadPackagesController::upload'], null, ['POST' => 0], null, \false, \false, null]],
        '/api/server/admin-user' => [[['_route' => 'contao_managerapi_server_adminuser__invoke', '_controller' => '_ContaoManager\Contao\ManagerApi\Controller\Server\AdminUserController'], null, ['GET' => 0, 'POST' => 1], null, \false, \false, null]],
        '/api/server/composer' => [[['_route' => 'contao_managerapi_server_composer__invoke', '_controller' => '_ContaoManager\Contao\ManagerApi\Controller\Server\ComposerController'], null, ['GET' => 0], null, \false, \false, null]],
        '/api/server/config' => [[['_route' => 'contao_managerapi_server_config_getconfig', '_controller' => '_ContaoManager\Contao\ManagerApi\Controller\Server\ConfigController::getConfig'], null, ['GET' => 0], null, \false, \false, null], [['_route' => 'contao_managerapi_server_config_setconfig', '_controller' => '_ContaoManager\Contao\ManagerApi\Controller\Server\ConfigController::setConfig'], null, ['PUT' => 0], null, \false, \false, null]],
        '/api/server/contao' => [[['_route' => 'contao_managerapi_server_contao_handle', '_controller' => '_ContaoManager\Contao\ManagerApi\Controller\Server\ContaoController::handle'], null, ['GET' => 0], null, \false, \false, null], [['_route' => 'contao_managerapi_server_contao_update', '_controller' => '_ContaoManager\Contao\ManagerApi\Controller\Server\ContaoController::update'], null, ['POST' => 0], null, \false, \false, null]],
        '/api/server/database' => [[['_route' => 'contao_managerapi_server_database_handle', '_controller' => '_ContaoManager\Contao\ManagerApi\Controller\Server\DatabaseController::handle'], null, ['GET' => 0], null, \false, \false, null], [['_route' => 'contao_managerapi_server_database_write', '_controller' => '_ContaoManager\Contao\ManagerApi\Controller\Server\DatabaseController::write'], null, ['POST' => 0], null, \false, \false, null]],
        '/api/server/opcache' => [[['_route' => 'contao_managerapi_server_opcache_getopcache', '_controller' => '_ContaoManager\Contao\ManagerApi\Controller\Server\OpcacheController::getOpcache'], null, ['GET' => 0], null, \false, \false, null], [['_route' => 'contao_managerapi_server_opcache_deleteopcache', '_controller' => '_ContaoManager\Contao\ManagerApi\Controller\Server\OpcacheController::deleteOpcache'], null, ['DELETE' => 0], null, \false, \false, null]],
        '/api/server/php-cli' => [[['_route' => 'contao_managerapi_server_phpcli__invoke', '_controller' => '_ContaoManager\Contao\ManagerApi\Controller\Server\PhpCliController'], null, ['GET' => 0], null, \false, \false, null]],
        '/api/server/php-web' => [[['_route' => 'contao_managerapi_server_phpweb__invoke', '_controller' => '_ContaoManager\Contao\ManagerApi\Controller\Server\PhpWebController'], null, ['GET' => 0], null, \false, \false, null]],
        '/api/server/phpinfo' => [[['_route' => 'contao_managerapi_server_phpinfo__invoke', '_controller' => '_ContaoManager\Contao\ManagerApi\Controller\Server\PhpinfoController'], null, ['GET' => 0], null, \false, \false, null]],
        '/api/server/self-update' => [[['_route' => 'contao_managerapi_server_selfupdate__invoke', '_controller' => '_ContaoManager\Contao\ManagerApi\Controller\Server\SelfUpdateController'], null, ['GET' => 0], null, \false, \false, null]],
        '/api/session' => [[['_route' => 'contao_managerapi_session_getsession', '_controller' => '_ContaoManager\Contao\ManagerApi\Controller\SessionController::getSession'], null, ['GET' => 0, 'POST' => 1, 'DELETE' => 2], null, \false, \false, null]],
        '/api/session/options' => [[['_route' => 'contao_managerapi_session_getwebauthnoptions', '_controller' => '_ContaoManager\Contao\ManagerApi\Controller\SessionController::getWebauthnOptions'], null, ['GET' => 0, 'POST' => 1], null, \false, \false, null]],
        '/api/task' => [[['_route' => 'contao_managerapi_task__invoke', '_controller' => '_ContaoManager\Contao\ManagerApi\Controller\TaskController'], null, ['GET' => 0, 'PUT' => 1, 'PATCH' => 2, 'DELETE' => 3], null, \false, \false, null]],
        '/api/users' => [[['_route' => 'contao_managerapi_user_listusers', '_controller' => '_ContaoManager\Contao\ManagerApi\Controller\UserController::listUsers'], null, ['GET' => 0], null, \false, \false, null], [['_route' => 'contao_managerapi_user_createuser', '_controller' => '_ContaoManager\Contao\ManagerApi\Controller\UserController::createUser'], null, ['POST' => 0], null, \false, \false, null]],
        '/api/invitations' => [[['_route' => 'contao_managerapi_user_inviteuser', '_controller' => '_ContaoManager\Contao\ManagerApi\Controller\UserController::inviteUser'], null, ['POST' => 0], null, \false, \false, null]],
    ],
    [
        // $regexpList
        0 => '{^(?' . '|/api/(?' . '|files/([^/]++)(*:29)' . '|logs/([^/]++)(?' . '|(*:52)' . ')' . '|packages/(?' . '|local(?:/(.+))?(*:87)' . '|uploads/([^/]++)(*:110)' . ')' . '|users/([^/]++)(?' . '|(*:136)' . '|/(?' . '|password(*:156)' . '|to(?' . '|tp(?' . '|(*:174)' . ')' . '|kens(?' . '|(*:190)' . '|/([^/]++)(?' . '|(*:210)' . ')' . ')' . ')' . ')' . ')' . ')' . ')/?$}sDu',
    ],
    [
        // $dynamicRoutes
        29 => [[['_route' => 'contao_managerapi_file__invoke', '_controller' => '_ContaoManager\Contao\ManagerApi\Controller\FileController'], ['file'], ['GET' => 0, 'PUT' => 1], null, \false, \true, null]],
        52 => [[['_route' => 'contao_managerapi_log_retrievefile', '_controller' => '_ContaoManager\Contao\ManagerApi\Controller\LogController::retrieveFile'], ['filename'], ['GET' => 0], null, \false, \true, null], [['_route' => 'contao_managerapi_log_deletefile', '_controller' => '_ContaoManager\Contao\ManagerApi\Controller\LogController::deleteFile'], ['filename'], ['DELETE' => 0], null, \false, \true, null]],
        87 => [[['_route' => 'contao_managerapi_packages_localpackages__invoke_1', 'name' => null, '_controller' => '_ContaoManager\Contao\ManagerApi\Controller\Packages\LocalPackagesController'], ['name'], ['GET' => 0], null, \false, \true, null]],
        110 => [[['_route' => 'contao_managerapi_packages_uploadpackages_delete', '_controller' => '_ContaoManager\Contao\ManagerApi\Controller\Packages\UploadPackagesController::delete'], ['id'], ['DELETE' => 0], null, \false, \true, null]],
        136 => [[['_route' => 'user_get', '_controller' => '_ContaoManager\Contao\ManagerApi\Controller\UserController::retrieveUser'], ['username'], ['GET' => 0], null, \false, \true, null], [['_route' => 'contao_managerapi_user_replaceuser', '_controller' => '_ContaoManager\Contao\ManagerApi\Controller\UserController::replaceUser'], ['username'], ['PUT' => 0], null, \false, \true, null], [['_route' => 'contao_managerapi_user_deleteuser', '_controller' => '_ContaoManager\Contao\ManagerApi\Controller\UserController::deleteUser'], ['username'], ['DELETE' => 0], null, \false, \true, null]],
        156 => [[['_route' => 'contao_managerapi_user_setpassword', '_controller' => '_ContaoManager\Contao\ManagerApi\Controller\UserController::setPassword'], ['username'], ['PUT' => 0], null, \false, \false, null]],
        174 => [[['_route' => 'contao_managerapi_user_gettotp', '_controller' => '_ContaoManager\Contao\ManagerApi\Controller\UserController::getTOTP'], ['username'], ['GET' => 0], null, \false, \false, null], [['_route' => 'contao_managerapi_user_setuptotp', '_controller' => '_ContaoManager\Contao\ManagerApi\Controller\UserController::setupTotp'], ['username'], ['PUT' => 0], null, \false, \false, null], [['_route' => 'contao_managerapi_user_deletetotp', '_controller' => '_ContaoManager\Contao\ManagerApi\Controller\UserController::deleteTotp'], ['username'], ['DELETE' => 0], null, \false, \false, null]],
        190 => [[['_route' => 'contao_managerapi_user_listtokens', '_controller' => '_ContaoManager\Contao\ManagerApi\Controller\UserController::listTokens'], ['username'], ['GET' => 0], null, \false, \false, null], [['_route' => 'contao_managerapi_user_createtoken', '_controller' => '_ContaoManager\Contao\ManagerApi\Controller\UserController::createToken'], ['username'], ['POST' => 0], null, \false, \false, null]],
        210 => [[['_route' => 'contao_managerapi_user_retrievetoken', '_controller' => '_ContaoManager\Contao\ManagerApi\Controller\UserController::retrieveToken'], ['username', 'id'], ['GET' => 0], null, \false, \true, null], [['_route' => 'contao_managerapi_user_deletetoken', '_controller' => '_ContaoManager\Contao\ManagerApi\Controller\UserController::deleteToken'], ['username', 'id'], ['DELETE' => 0], null, \false, \true, null], [null, null, null, null, \false, \false, 0]],
    ],
    null,
];
a:35:{i:0;O:51:"Symfony\Component\Config\Resource\DirectoryResource":2:{s:61:" Symfony\Component\Config\Resource\DirectoryResource resource";s:84:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/Controller";s:60:" Symfony\Component\Config\Resource\DirectoryResource pattern";s:8:"/\.php$/";}i:1;O:46:"Symfony\Component\Config\Resource\FileResource":1:{s:56:" Symfony\Component\Config\Resource\FileResource resource";s:110:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/Controller/Config/AuthController.php";}i:2;O:46:"Symfony\Component\Config\Resource\FileResource":1:{s:56:" Symfony\Component\Config\Resource\FileResource resource";s:114:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/Controller/Config/ComposerController.php";}i:3;O:46:"Symfony\Component\Config\Resource\FileResource":1:{s:56:" Symfony\Component\Config\Resource\FileResource resource";s:113:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/Controller/Config/ManagerController.php";}i:4;O:46:"Symfony\Component\Config\Resource\FileResource":1:{s:56:" Symfony\Component\Config\Resource\FileResource resource";s:109:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/Controller/ConstraintController.php";}i:5;O:46:"Symfony\Component\Config\Resource\FileResource":1:{s:56:" Symfony\Component\Config\Resource\FileResource resource";s:115:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/Controller/Contao/AccessKeyController.php";}i:6;O:46:"Symfony\Component\Config\Resource\FileResource":1:{s:56:" Symfony\Component\Config\Resource\FileResource resource";s:112:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/Controller/Contao/BackupController.php";}i:7;O:46:"Symfony\Component\Config\Resource\FileResource":1:{s:56:" Symfony\Component\Config\Resource\FileResource resource";s:123:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/Controller/Contao/DatabaseMigrationController.php";}i:8;O:46:"Symfony\Component\Config\Resource\FileResource":1:{s:56:" Symfony\Component\Config\Resource\FileResource resource";s:121:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/Controller/Contao/InstallToolLockController.php";}i:9;O:46:"Symfony\Component\Config\Resource\FileResource":1:{s:56:" Symfony\Component\Config\Resource\FileResource resource";s:115:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/Controller/Contao/JwtCookieController.php";}i:10;O:46:"Symfony\Component\Config\Resource\FileResource":1:{s:56:" Symfony\Component\Config\Resource\FileResource resource";s:121:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/Controller/Contao/MaintenanceModeController.php";}i:11;O:46:"Symfony\Component\Config\Resource\FileResource":1:{s:56:" Symfony\Component\Config\Resource\FileResource resource";s:103:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/Controller/FileController.php";}i:12;O:46:"Symfony\Component\Config\Resource\FileResource":1:{s:56:" Symfony\Component\Config\Resource\FileResource resource";s:102:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/Controller/LogController.php";}i:13;O:46:"Symfony\Component\Config\Resource\FileResource":1:{s:56:" Symfony\Component\Config\Resource\FileResource resource";s:113:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/Controller/Packages/CloudController.php";}i:14;O:46:"Symfony\Component\Config\Resource\FileResource":1:{s:56:" Symfony\Component\Config\Resource\FileResource resource";s:121:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/Controller/Packages/LocalPackagesController.php";}i:15;O:46:"Symfony\Component\Config\Resource\FileResource":1:{s:56:" Symfony\Component\Config\Resource\FileResource resource";s:123:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/Controller/Packages/MissingPackagesController.php";}i:16;O:46:"Symfony\Component\Config\Resource\FileResource":1:{s:56:" Symfony\Component\Config\Resource\FileResource resource";s:119:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/Controller/Packages/RootPackageController.php";}i:17;O:46:"Symfony\Component\Config\Resource\FileResource":1:{s:56:" Symfony\Component\Config\Resource\FileResource resource";s:122:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/Controller/Packages/UploadPackagesController.php";}i:18;O:46:"Symfony\Component\Config\Resource\FileResource":1:{s:56:" Symfony\Component\Config\Resource\FileResource resource";s:115:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/Controller/Server/AdminUserController.php";}i:19;O:46:"Symfony\Component\Config\Resource\FileResource":1:{s:56:" Symfony\Component\Config\Resource\FileResource resource";s:114:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/Controller/Server/ComposerController.php";}i:20;O:46:"Symfony\Component\Config\Resource\FileResource":1:{s:56:" Symfony\Component\Config\Resource\FileResource resource";s:112:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/Controller/Server/ConfigController.php";}i:21;O:46:"Symfony\Component\Config\Resource\FileResource":1:{s:56:" Symfony\Component\Config\Resource\FileResource resource";s:112:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/Controller/Server/ContaoController.php";}i:22;O:46:"Symfony\Component\Config\Resource\FileResource":1:{s:56:" Symfony\Component\Config\Resource\FileResource resource";s:114:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/Controller/Server/DatabaseController.php";}i:23;O:46:"Symfony\Component\Config\Resource\FileResource":1:{s:56:" Symfony\Component\Config\Resource\FileResource resource";s:113:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/Controller/Server/OpcacheController.php";}i:24;O:46:"Symfony\Component\Config\Resource\FileResource":1:{s:56:" Symfony\Component\Config\Resource\FileResource resource";s:112:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/Controller/Server/PhpCliController.php";}i:25;O:46:"Symfony\Component\Config\Resource\FileResource":1:{s:56:" Symfony\Component\Config\Resource\FileResource resource";s:112:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/Controller/Server/PhpWebController.php";}i:26;O:46:"Symfony\Component\Config\Resource\FileResource":1:{s:56:" Symfony\Component\Config\Resource\FileResource resource";s:113:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/Controller/Server/PhpinfoController.php";}i:27;O:46:"Symfony\Component\Config\Resource\FileResource":1:{s:56:" Symfony\Component\Config\Resource\FileResource resource";s:116:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/Controller/Server/SelfUpdateController.php";}i:28;O:46:"Symfony\Component\Config\Resource\FileResource":1:{s:56:" Symfony\Component\Config\Resource\FileResource resource";s:106:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/Controller/SessionController.php";}i:29;O:46:"Symfony\Component\Config\Resource\FileResource":1:{s:56:" Symfony\Component\Config\Resource\FileResource resource";s:103:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/Controller/TaskController.php";}i:30;O:46:"Symfony\Component\Config\Resource\FileResource":1:{s:56:" Symfony\Component\Config\Resource\FileResource resource";s:103:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/Controller/UserController.php";}i:31;O:46:"Symfony\Component\Config\Resource\FileResource":1:{s:56:" Symfony\Component\Config\Resource\FileResource resource";s:87:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/ApiKernel.php";}i:32;O:46:"Symfony\Component\Config\Resource\FileResource":1:{s:56:" Symfony\Component\Config\Resource\FileResource resource";s:107:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/vendor/symfony/http-kernel/Kernel.php";}i:33;O:72:"Symfony\Component\DependencyInjection\Config\ContainerParametersResource":1:{s:84:" Symfony\Component\DependencyInjection\Config\ContainerParametersResource parameters";a:0:{}}i:34;O:46:"Symfony\Component\Config\Resource\FileResource":1:{s:56:" Symfony\Component\Config\Resource\FileResource resource";s:134:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.10.13/api/Resources/cache/Contao_ManagerApi_ApiKernelProdContainer.php";}}<?php

namespace _ContaoManager;

// This file has been auto-generated by the Symfony Dependency Injection Component
// You can reference it in the "opcache.preload" php.ini setting on PHP >= 7.4 when preloading is desired
use _ContaoManager\Symfony\Component\DependencyInjection\Dumper\Preloader;
if (\in_array(\PHP_SAPI, ['cli', 'phpdbg', 'embed'], \true)) {
    return;
}
require \dirname(__DIR__, 3) . '/vendor/autoload.php';
(require __DIR__ . '/Contao_ManagerApi_ApiKernelProdContainer.php')->set(\_ContaoManager\ContainerLiF9Qbu\Contao_ManagerApi_ApiKernelProdContainer::class, null);
require __DIR__ . '/ContainerLiF9Qbu/RequestPayloadValueResolverGhost8d82153.php';
require __DIR__ . '/ContainerLiF9Qbu/getServicesResetterService.php';
require __DIR__ . '/ContainerLiF9Qbu/getSecurity_UserValueResolverService.php';
require __DIR__ . '/ContainerLiF9Qbu/getSecurity_UserCheckerLocatorService.php';
require __DIR__ . '/ContainerLiF9Qbu/getSecurity_SecurityTokenValueResolverService.php';
require __DIR__ . '/ContainerLiF9Qbu/getSecurity_RouteLoader_LogoutService.php';
require __DIR__ . '/ContainerLiF9Qbu/getSecurity_Listener_UserProviderService.php';
require __DIR__ . '/ContainerLiF9Qbu/getSecurity_Listener_UserChecker_ApiService.php';
require __DIR__ . '/ContainerLiF9Qbu/getSecurity_Listener_PasswordMigratingService.php';
require __DIR__ . '/ContainerLiF9Qbu/getSecurity_Listener_CheckAuthenticatorCredentialsService.php';
require __DIR__ . '/ContainerLiF9Qbu/getSecurity_Listener_Api_UserProviderService.php';
require __DIR__ . '/ContainerLiF9Qbu/getSecurity_HelperService.php';
require __DIR__ . '/ContainerLiF9Qbu/getSecurity_Firewall_Map_Context_ApiService.php';
require __DIR__ . '/ContainerLiF9Qbu/getSecurity_Firewall_EventDispatcherLocatorService.php';
require __DIR__ . '/ContainerLiF9Qbu/getSecurity_Firewall_Authenticator_ApiService.php';
require __DIR__ . '/ContainerLiF9Qbu/getSecurity_EventDispatcher_ApiService.php';
require __DIR__ . '/ContainerLiF9Qbu/getSecurity_ChannelListenerService.php';
require __DIR__ . '/ContainerLiF9Qbu/getSecurity_Authenticator_ManagersLocatorService.php';
require __DIR__ . '/ContainerLiF9Qbu/getSecurity_Authenticator_Manager_ApiService.php';
require __DIR__ . '/ContainerLiF9Qbu/getSecurity_AccessMapService.php';
require __DIR__ . '/ContainerLiF9Qbu/getSecurity_AccessListenerService.php';
require __DIR__ . '/ContainerLiF9Qbu/getSecurity_Access_RoleHierarchyVoterService.php';
require __DIR__ . '/ContainerLiF9Qbu/getSecurity_Access_AuthenticatedVoterService.php';
require __DIR__ . '/ContainerLiF9Qbu/getSecrets_VaultService.php';
require __DIR__ . '/ContainerLiF9Qbu/getRouting_LoaderService.php';
require __DIR__ . '/ContainerLiF9Qbu/getPropertyInfo_SerializerExtractorService.php';
require __DIR__ . '/ContainerLiF9Qbu/getMonolog_Logger_TasksService.php';
require __DIR__ . '/ContainerLiF9Qbu/getMonolog_Logger_SecurityService.php';
require __DIR__ . '/ContainerLiF9Qbu/getMonolog_LoggerService.php';
require __DIR__ . '/ContainerLiF9Qbu/getErrorControllerService.php';
require __DIR__ . '/ContainerLiF9Qbu/getDebug_ErrorHandlerConfiguratorService.php';
require __DIR__ . '/ContainerLiF9Qbu/getContaoManager_Security_AuthenticationTrustResolverService.php';
require __DIR__ . '/ContainerLiF9Qbu/getContainer_GetRoutingConditionServiceService.php';
require __DIR__ . '/ContainerLiF9Qbu/getContainer_EnvVarProcessorsLocatorService.php';
require __DIR__ . '/ContainerLiF9Qbu/getContainer_EnvVarProcessorService.php';
require __DIR__ . '/ContainerLiF9Qbu/getCache_SystemClearerService.php';
require __DIR__ . '/ContainerLiF9Qbu/getCache_SystemService.php';
require __DIR__ . '/ContainerLiF9Qbu/getCache_SecurityIsGrantedAttributeExpressionLanguageService.php';
require __DIR__ . '/ContainerLiF9Qbu/getCache_GlobalClearerService.php';
require __DIR__ . '/ContainerLiF9Qbu/getCache_AppClearerService.php';
require __DIR__ . '/ContainerLiF9Qbu/getCache_AppService.php';
require __DIR__ . '/ContainerLiF9Qbu/getArgumentResolver_VariadicService.php';
require __DIR__ . '/ContainerLiF9Qbu/getArgumentResolver_UidService.php';
require __DIR__ . '/ContainerLiF9Qbu/getArgumentResolver_SessionService.php';
require __DIR__ . '/ContainerLiF9Qbu/getArgumentResolver_ServiceService.php';
require __DIR__ . '/ContainerLiF9Qbu/getArgumentResolver_RequestAttributeService.php';
require __DIR__ . '/ContainerLiF9Qbu/getArgumentResolver_RequestService.php';
require __DIR__ . '/ContainerLiF9Qbu/getArgumentResolver_QueryParameterValueResolverService.php';
require __DIR__ . '/ContainerLiF9Qbu/getArgumentResolver_DefaultService.php';
require __DIR__ . '/ContainerLiF9Qbu/getArgumentResolver_DatetimeService.php';
require __DIR__ . '/ContainerLiF9Qbu/getArgumentResolver_BackedEnumResolverService.php';
require __DIR__ . '/ContainerLiF9Qbu/getTemplateControllerService.php';
require __DIR__ . '/ContainerLiF9Qbu/getRedirectControllerService.php';
require __DIR__ . '/ContainerLiF9Qbu/getTaskManagerService.php';
require __DIR__ . '/ContainerLiF9Qbu/getUpdateTaskService.php';
require __DIR__ . '/ContainerLiF9Qbu/getSetupTaskService.php';
require __DIR__ . '/ContainerLiF9Qbu/getInstallTaskService.php';
require __DIR__ . '/ContainerLiF9Qbu/getSelfUpdateTaskService.php';
require __DIR__ . '/ContainerLiF9Qbu/getRebuildCacheTaskService.php';
require __DIR__ . '/ContainerLiF9Qbu/getBackupRestoreTaskService.php';
require __DIR__ . '/ContainerLiF9Qbu/getBackupCreateTaskService.php';
require __DIR__ . '/ContainerLiF9Qbu/getDumpAutoloadTaskService.php';
require __DIR__ . '/ContainerLiF9Qbu/getClearCacheTaskService.php';
require __DIR__ . '/ContainerLiF9Qbu/getServerInfoService.php';
require __DIR__ . '/ContainerLiF9Qbu/getSelfUpdateService.php';
require __DIR__ . '/ContainerLiF9Qbu/getRequestService.php';
require __DIR__ . '/ContainerLiF9Qbu/getWebauthnAuthenticatorService.php';
require __DIR__ . '/ContainerLiF9Qbu/getUserProviderService.php';
require __DIR__ . '/ContainerLiF9Qbu/getTokenAuthenticatorService.php';
require __DIR__ . '/ContainerLiF9Qbu/getPasswordlessAuthenticatorService.php';
require __DIR__ . '/ContainerLiF9Qbu/getLoginAuthenticatorService.php';
require __DIR__ . '/ContainerLiF9Qbu/getJwtAuthenticatorService.php';
require __DIR__ . '/ContainerLiF9Qbu/getContaoConsoleService.php';
require __DIR__ . '/ContainerLiF9Qbu/getContaoApiService.php';
require __DIR__ . '/ContainerLiF9Qbu/getConsoleProcessFactoryService.php';
require __DIR__ . '/ContainerLiF9Qbu/getSysTempDirCheckService.php';
require __DIR__ . '/ContainerLiF9Qbu/getSymlinkCheckService.php';
require __DIR__ . '/ContainerLiF9Qbu/getSessionCheckService.php';
require __DIR__ . '/ContainerLiF9Qbu/getProcessCheckService.php';
require __DIR__ . '/ContainerLiF9Qbu/getPhpExtensionsCheckService.php';
require __DIR__ . '/ContainerLiF9Qbu/getMemoryLimitCheckService.php';
require __DIR__ . '/ContainerLiF9Qbu/getIntegrityCheckFactoryService.php';
require __DIR__ . '/ContainerLiF9Qbu/getGraphicsLibCheckService.php';
require __DIR__ . '/ContainerLiF9Qbu/getAllowUrlFopenCheckService.php';
require __DIR__ . '/ContainerLiF9Qbu/getTranslatorService.php';
require __DIR__ . '/ContainerLiF9Qbu/getExceptionListenerService.php';
require __DIR__ . '/ContainerLiF9Qbu/getUserControllerService.php';
require __DIR__ . '/ContainerLiF9Qbu/getTaskControllerService.php';
require __DIR__ . '/ContainerLiF9Qbu/getSessionControllerService.php';
require __DIR__ . '/ContainerLiF9Qbu/getSelfUpdateControllerService.php';
require __DIR__ . '/ContainerLiF9Qbu/getPhpinfoControllerService.php';
require __DIR__ . '/ContainerLiF9Qbu/getPhpWebControllerService.php';
require __DIR__ . '/ContainerLiF9Qbu/getPhpCliControllerService.php';
require __DIR__ . '/ContainerLiF9Qbu/getOpcacheControllerService.php';
require __DIR__ . '/ContainerLiF9Qbu/getDatabaseControllerService.php';
require __DIR__ . '/ContainerLiF9Qbu/getContaoControllerService.php';
require __DIR__ . '/ContainerLiF9Qbu/getConfigControllerService.php';
require __DIR__ . '/ContainerLiF9Qbu/getComposerController2Service.php';
require __DIR__ . '/ContainerLiF9Qbu/getAdminUserControllerService.php';
require __DIR__ . '/ContainerLiF9Qbu/getUploadPackagesControllerService.php';
require __DIR__ . '/ContainerLiF9Qbu/getRootPackageControllerService.php';
require __DIR__ . '/ContainerLiF9Qbu/getMissingPackagesControllerService.php';
require __DIR__ . '/ContainerLiF9Qbu/getLocalPackagesControllerService.php';
require __DIR__ . '/ContainerLiF9Qbu/getCloudControllerService.php';
require __DIR__ . '/ContainerLiF9Qbu/getLogControllerService.php';
require __DIR__ . '/ContainerLiF9Qbu/getFileControllerService.php';
require __DIR__ . '/ContainerLiF9Qbu/getMaintenanceModeControllerService.php';
require __DIR__ . '/ContainerLiF9Qbu/getJwtCookieControllerService.php';
require __DIR__ . '/ContainerLiF9Qbu/getInstallToolLockControllerService.php';
require __DIR__ . '/ContainerLiF9Qbu/getDatabaseMigrationControllerService.php';
require __DIR__ . '/ContainerLiF9Qbu/getBackupControllerService.php';
require __DIR__ . '/ContainerLiF9Qbu/getAccessKeyControllerService.php';
require __DIR__ . '/ContainerLiF9Qbu/getConstraintControllerService.php';
require __DIR__ . '/ContainerLiF9Qbu/getManagerControllerService.php';
require __DIR__ . '/ContainerLiF9Qbu/getComposerControllerService.php';
require __DIR__ . '/ContainerLiF9Qbu/getAuthControllerService.php';
require __DIR__ . '/ContainerLiF9Qbu/getUploadsConfigService.php';
require __DIR__ . '/ContainerLiF9Qbu/getManagerConfigService.php';
require __DIR__ . '/ContainerLiF9Qbu/getComposerConfigService.php';
require __DIR__ . '/ContainerLiF9Qbu/getEnvironmentService.php';
require __DIR__ . '/ContainerLiF9Qbu/getCloudResolverService.php';
require __DIR__ . '/ContainerLiF9Qbu/get_ServiceLocator_Y_Xs7MwService.php';
require __DIR__ . '/ContainerLiF9Qbu/get_ServiceLocator_AH5O6SdService.php';
require __DIR__ . '/ContainerLiF9Qbu/get_ServiceLocator_EZsc_DOService.php';
$classes = [];
$classes[] = '_ContaoManager\Symfony\Bundle\FrameworkBundle\FrameworkBundle';
$classes[] = '_ContaoManager\Symfony\Bundle\SecurityBundle\SecurityBundle';
$classes[] = '_ContaoManager\Symfony\Bundle\MonologBundle\MonologBundle';
$classes[] = '_ContaoManager\Symfony\Component\DependencyInjection\ServiceLocator';
$classes[] = '_ContaoManager\Contao\ManagerApi\Composer\CloudResolver';
$classes[] = '_ContaoManager\Contao\ManagerApi\Composer\Environment';
$classes[] = '_ContaoManager\Contao\ManagerApi\Config\ComposerConfig';
$classes[] = '_ContaoManager\Contao\ManagerApi\Config\ManagerConfig';
$classes[] = '_ContaoManager\Contao\ManagerApi\Config\UploadsConfig';
$classes[] = '_ContaoManager\Contao\ManagerApi\Config\UserConfig';
$classes[] = '_ContaoManager\Contao\ManagerApi\Controller\Config\AuthController';
$classes[] = '_ContaoManager\Contao\ManagerApi\Config\AuthConfig';
$classes[] = '_ContaoManager\Contao\ManagerApi\Controller\Config\ComposerController';
$classes[] = '_ContaoManager\Contao\ManagerApi\Controller\Config\ManagerController';
$classes[] = '_ContaoManager\Contao\ManagerApi\Controller\ConstraintController';
$classes[] = '_ContaoManager\Contao\ManagerApi\Controller\Contao\AccessKeyController';
$classes[] = '_ContaoManager\Contao\ManagerApi\Controller\Contao\BackupController';
$classes[] = '_ContaoManager\Contao\ManagerApi\Controller\Contao\DatabaseMigrationController';
$classes[] = '_ContaoManager\Contao\ManagerApi\Controller\Contao\InstallToolLockController';
$classes[] = '_ContaoManager\Contao\ManagerApi\Controller\Contao\JwtCookieController';
$classes[] = '_ContaoManager\Contao\ManagerApi\Controller\Contao\MaintenanceModeController';
$classes[] = '_ContaoManager\Contao\ManagerApi\Controller\FileController';
$classes[] = '_ContaoManager\Contao\ManagerApi\Controller\LogController';
$classes[] = '_ContaoManager\Contao\ManagerApi\Controller\Packages\CloudController';
$classes[] = '_ContaoManager\Contao\ManagerApi\Controller\Packages\LocalPackagesController';
$classes[] = '_ContaoManager\Contao\ManagerApi\Controller\Packages\MissingPackagesController';
$classes[] = '_ContaoManager\Contao\ManagerApi\Controller\Packages\RootPackageController';
$classes[] = '_ContaoManager\Contao\ManagerApi\Controller\Packages\UploadPackagesController';
$classes[] = '_ContaoManager\Contao\ManagerApi\Controller\Server\AdminUserController';
$classes[] = '_ContaoManager\Contao\ManagerApi\Controller\Server\ComposerController';
$classes[] = '_ContaoManager\Contao\ManagerApi\Controller\Server\ConfigController';
$classes[] = '_ContaoManager\Contao\ManagerApi\Controller\Server\ContaoController';
$classes[] = '_ContaoManager\Contao\ManagerApi\Controller\Server\DatabaseController';
$classes[] = '_ContaoManager\Contao\ManagerApi\Controller\Server\OpcacheController';
$classes[] = '_ContaoManager\Contao\ManagerApi\Controller\Server\PhpCliController';
$classes[] = '_ContaoManager\Contao\ManagerApi\Controller\Server\PhpWebController';
$classes[] = '_ContaoManager\Contao\ManagerApi\Controller\Server\PhpinfoController';
$classes[] = '_ContaoManager\Contao\ManagerApi\Controller\Server\SelfUpdateController';
$classes[] = '_ContaoManager\Contao\ManagerApi\Controller\SessionController';
$classes[] = '_ContaoManager\Contao\ManagerApi\Controller\TaskController';
$classes[] = '_ContaoManager\Contao\ManagerApi\Controller\UserController';
$classes[] = '_ContaoManager\Contao\ManagerApi\EventListener\CheckTotpListener';
$classes[] = '_ContaoManager\Contao\ManagerApi\EventListener\ExceptionListener';
$classes[] = '_ContaoManager\Contao\ManagerApi\EventListener\JsonRequestListener';
$classes[] = '_ContaoManager\Contao\ManagerApi\EventListener\LocaleListener';
$classes[] = '_ContaoManager\Symfony\Component\HttpKernel\EventListener\LocaleListener';
$classes[] = '_ContaoManager\Contao\ManagerApi\EventListener\SecurityListener';
$classes[] = '_ContaoManager\Contao\ManagerApi\I18n\Translator';
$classes[] = '_ContaoManager\Contao\ManagerApi\IntegrityCheck\AllowUrlFopenCheck';
$classes[] = '_ContaoManager\Contao\ManagerApi\IntegrityCheck\GraphicsLibCheck';
$classes[] = '_ContaoManager\Contao\ManagerApi\IntegrityCheck\IntegrityCheckFactory';
$classes[] = '_ContaoManager\Contao\ManagerApi\IntegrityCheck\MemoryLimitCheck';
$classes[] = '_ContaoManager\Contao\ManagerApi\IntegrityCheck\PhpExtensionsCheck';
$classes[] = '_ContaoManager\Contao\ManagerApi\IntegrityCheck\ProcessCheck';
$classes[] = '_ContaoManager\Contao\ManagerApi\IntegrityCheck\SessionCheck';
$classes[] = '_ContaoManager\Contao\ManagerApi\IntegrityCheck\SymlinkCheck';
$classes[] = '_ContaoManager\Contao\ManagerApi\IntegrityCheck\SysTempDirCheck';
$classes[] = '_ContaoManager\Contao\ManagerApi\Process\ConsoleProcessFactory';
$classes[] = '_ContaoManager\Contao\ManagerApi\Process\ContaoApi';
$classes[] = '_ContaoManager\Contao\ManagerApi\Process\ContaoConsole';
$classes[] = '_ContaoManager\Contao\ManagerApi\Security\JwtAuthenticator';
$classes[] = '_ContaoManager\Contao\ManagerApi\Security\JwtManager';
$classes[] = '_ContaoManager\Contao\ManagerApi\Security\LoginAuthenticator';
$classes[] = '_ContaoManager\Contao\ManagerApi\Security\PasswordlessAuthenticator';
$classes[] = '_ContaoManager\Contao\ManagerApi\Security\TokenAuthenticator';
$classes[] = '_ContaoManager\Contao\ManagerApi\Security\UserProvider';
$classes[] = '_ContaoManager\Contao\ManagerApi\Security\WebauthnAuthenticator';
$classes[] = '_ContaoManager\Symfony\Component\Serializer\SerializerInterface';
$classes[] = '_ContaoManager\Webauthn\Denormalizer\WebauthnSerializerFactory';
$classes[] = '_ContaoManager\Webauthn\AttestationStatement\AttestationStatementSupportManager';
$classes[] = '_ContaoManager\Webauthn\AuthenticatorAttestationResponseValidator';
$classes[] = '_ContaoManager\Webauthn\CeremonyStep\CeremonyStepManager';
$classes[] = '_ContaoManager\Webauthn\CeremonyStep\CeremonyStepManagerFactory';
$classes[] = '_ContaoManager\Webauthn\AuthenticatorAssertionResponseValidator';
$classes[] = '_ContaoManager\Contao\ManagerApi\System\Request';
$classes[] = '_ContaoManager\Contao\ManagerApi\System\SelfUpdate';
$classes[] = '_ContaoManager\Contao\ManagerApi\System\ServerInfo';
$classes[] = '_ContaoManager\Contao\ManagerApi\Process\PhpExecutableFinder';
$classes[] = '_ContaoManager\Contao\ManagerApi\Task\Composer\ClearCacheTask';
$classes[] = '_ContaoManager\Contao\ManagerApi\Task\Composer\DumpAutoloadTask';
$classes[] = '_ContaoManager\Contao\ManagerApi\Task\Contao\BackupCreateTask';
$classes[] = '_ContaoManager\Contao\ManagerApi\Task\Contao\BackupRestoreTask';
$classes[] = '_ContaoManager\Contao\ManagerApi\Task\Contao\RebuildCacheTask';
$classes[] = '_ContaoManager\Contao\ManagerApi\Task\Manager\SelfUpdateTask';
$classes[] = '_ContaoManager\Contao\ManagerApi\Task\Packages\InstallTask';
$classes[] = '_ContaoManager\Contao\ManagerApi\Task\Packages\SetupTask';
$classes[] = '_ContaoManager\Contao\ManagerApi\Task\Packages\UpdateTask';
$classes[] = '_ContaoManager\Contao\ManagerApi\Task\TaskManager';
$classes[] = '_ContaoManager\Symfony\Bundle\FrameworkBundle\Controller\RedirectController';
$classes[] = '_ContaoManager\Symfony\Bundle\FrameworkBundle\Controller\TemplateController';
$classes[] = '_ContaoManager\Symfony\Component\HttpKernel\Controller\ArgumentResolver\BackedEnumValueResolver';
$classes[] = '_ContaoManager\Symfony\Component\HttpKernel\Controller\ArgumentResolver\DateTimeValueResolver';
$classes[] = '_ContaoManager\Symfony\Component\Clock\Clock';
$classes[] = '_ContaoManager\Symfony\Component\HttpKernel\Controller\ArgumentResolver\DefaultValueResolver';
$classes[] = '_ContaoManager\Symfony\Component\HttpKernel\Controller\ArgumentResolver\QueryParameterValueResolver';
$classes[] = '_ContaoManager\Symfony\Component\HttpKernel\Controller\ArgumentResolver\RequestValueResolver';
$classes[] = '_ContaoManager\Symfony\Component\HttpKernel\Controller\ArgumentResolver\RequestAttributeValueResolver';
$classes[] = '_ContaoManager\Symfony\Component\HttpKernel\Controller\ArgumentResolver\RequestPayloadValueResolver';
$classes[] = '_ContaoManager\Symfony\Component\HttpKernel\Controller\ArgumentResolver\ServiceValueResolver';
$classes[] = '_ContaoManager\Symfony\Component\HttpKernel\Controller\ArgumentResolver\SessionValueResolver';
$classes[] = '_ContaoManager\Symfony\Component\HttpKernel\Controller\ArgumentResolver\UidValueResolver';
$classes[] = '_ContaoManager\Symfony\Component\HttpKernel\Controller\ArgumentResolver\VariadicValueResolver';
$classes[] = '_ContaoManager\Symfony\Component\Cache\Adapter\FilesystemAdapter';
$classes[] = '_ContaoManager\Symfony\Component\Cache\Marshaller\DefaultMarshaller';
$classes[] = '_ContaoManager\Symfony\Component\HttpKernel\CacheClearer\Psr6CacheClearer';
$classes[] = '_ContaoManager\Symfony\Component\Cache\Adapter\AdapterInterface';
$classes[] = '_ContaoManager\Symfony\Component\PropertyAccess\PropertyAccessor';
$classes[] = '_ContaoManager\Symfony\Component\Cache\Adapter\AbstractAdapter';
$classes[] = '_ContaoManager\Symfony\Component\DependencyInjection\EnvVarProcessor';
$classes[] = '_ContaoManager\Contao\ManagerApi\Security\AuthenticationTrustResolver';
$classes[] = '_ContaoManager\Symfony\Component\Security\Core\Authentication\AuthenticationTrustResolver';
$classes[] = '_ContaoManager\Symfony\Component\HttpKernel\EventListener\CacheAttributeListener';
$classes[] = '_ContaoManager\Symfony\Component\Security\Http\EventListener\IsGrantedAttributeListener';
$classes[] = '_ContaoManager\Symfony\Component\HttpKernel\EventListener\DebugHandlersListener';
$classes[] = '_ContaoManager\Symfony\Component\HttpKernel\Debug\ErrorHandlerConfigurator';
$classes[] = '_ContaoManager\Monolog\Logger';
$classes[] = '_ContaoManager\Symfony\Component\ErrorHandler\ErrorRenderer\FileLinkFormatter';
$classes[] = '_ContaoManager\Symfony\Component\HttpKernel\Controller\ErrorController';
$classes[] = '_ContaoManager\Symfony\Component\ErrorHandler\ErrorRenderer\SerializerErrorRenderer';
$classes[] = '_ContaoManager\Symfony\Component\ErrorHandler\ErrorRenderer\HtmlErrorRenderer';
$classes[] = '_ContaoManager\Symfony\Component\EventDispatcher\EventDispatcher';
$classes[] = '_ContaoManager\Symfony\Component\HttpKernel\EventListener\ErrorListener';
$classes[] = '_ContaoManager\Symfony\Component\Filesystem\Filesystem';
$classes[] = '_ContaoManager\Symfony\Component\Runtime\Runner\Symfony\HttpKernelRunner';
$classes[] = '_ContaoManager\Symfony\Component\Runtime\Runner\Symfony\ResponseRunner';
$classes[] = '_ContaoManager\Symfony\Component\Runtime\SymfonyRuntime';
$classes[] = '_ContaoManager\Symfony\Component\HttpKernel\HttpKernel';
$classes[] = '_ContaoManager\Symfony\Bundle\FrameworkBundle\Controller\ControllerResolver';
$classes[] = '_ContaoManager\Symfony\Component\HttpKernel\Controller\ArgumentResolver';
$classes[] = '_ContaoManager\Symfony\Component\HttpKernel\ControllerMetadata\ArgumentMetadataFactory';
$classes[] = '_ContaoManager\Monolog\Handler\FingersCrossedHandler';
$classes[] = '_ContaoManager\Monolog\Handler\ErrorLogHandler';
$classes[] = '_ContaoManager\Monolog\Processor\PsrLogMessageProcessor';
$classes[] = '_ContaoManager\Monolog\Handler\FingersCrossed\ErrorLevelActivationStrategy';
$classes[] = '_ContaoManager\Symfony\Component\DependencyInjection\ParameterBag\ContainerBag';
$classes[] = '_ContaoManager\Symfony\Component\PropertyInfo\Extractor\PhpDocExtractor';
$classes[] = '_ContaoManager\Symfony\Component\PropertyInfo\Extractor\PhpStanExtractor';
$classes[] = '_ContaoManager\Symfony\Component\PropertyInfo\Extractor\ReflectionExtractor';
$classes[] = '_ContaoManager\Symfony\Component\PropertyInfo\Extractor\SerializerExtractor';
$classes[] = '_ContaoManager\Symfony\Component\HttpFoundation\RequestStack';
$classes[] = '_ContaoManager\Symfony\Component\HttpKernel\EventListener\ResponseListener';
$classes[] = '_ContaoManager\Symfony\Bundle\FrameworkBundle\Routing\Router';
$classes[] = '_ContaoManager\Symfony\Component\Config\ResourceCheckerConfigCacheFactory';
$classes[] = '_ContaoManager\Symfony\Component\Routing\RequestContext';
$classes[] = '_ContaoManager\Symfony\Component\HttpKernel\EventListener\RouterListener';
$classes[] = '_ContaoManager\Symfony\Bundle\FrameworkBundle\Routing\DelegatingLoader';
$classes[] = '_ContaoManager\Symfony\Component\Config\Loader\LoaderResolver';
$classes[] = '_ContaoManager\Symfony\Component\Routing\Loader\XmlFileLoader';
$classes[] = '_ContaoManager\Symfony\Component\HttpKernel\Config\FileLocator';
$classes[] = '_ContaoManager\Symfony\Component\Routing\Loader\YamlFileLoader';
$classes[] = '_ContaoManager\Symfony\Component\Routing\Loader\PhpFileLoader';
$classes[] = '_ContaoManager\Symfony\Component\Routing\Loader\GlobFileLoader';
$classes[] = '_ContaoManager\Symfony\Component\Routing\Loader\DirectoryLoader';
$classes[] = '_ContaoManager\Symfony\Component\Routing\Loader\ContainerLoader';
$classes[] = '_ContaoManager\Symfony\Bundle\FrameworkBundle\Routing\AttributeRouteControllerLoader';
$classes[] = '_ContaoManager\Symfony\Component\Routing\Loader\AttributeDirectoryLoader';
$classes[] = '_ContaoManager\Symfony\Component\Routing\Loader\AttributeFileLoader';
$classes[] = '_ContaoManager\Symfony\Component\Routing\Loader\Psr4DirectoryLoader';
$classes[] = '_ContaoManager\Symfony\Bundle\FrameworkBundle\Secrets\SodiumVault';
$classes[] = '_ContaoManager\Symfony\Component\String\LazyString';
$classes[] = '_ContaoManager\Symfony\Component\Security\Core\Authorization\Voter\AuthenticatedVoter';
$classes[] = '_ContaoManager\Symfony\Component\Security\Core\Authorization\AccessDecisionManager';
$classes[] = '_ContaoManager\Symfony\Component\Security\Core\Authorization\Strategy\AffirmativeStrategy';
$classes[] = '_ContaoManager\Symfony\Component\Security\Core\Authorization\Voter\RoleHierarchyVoter';
$classes[] = '_ContaoManager\Symfony\Component\Security\Core\Role\RoleHierarchy';
$classes[] = '_ContaoManager\Symfony\Component\Security\Http\Firewall\AccessListener';
$classes[] = '_ContaoManager\Symfony\Component\Security\Http\AccessMap';
$classes[] = '_ContaoManager\Symfony\Component\HttpFoundation\ChainRequestMatcher';
$classes[] = '_ContaoManager\Symfony\Component\HttpFoundation\RequestMatcher\PathRequestMatcher';
$classes[] = '_ContaoManager\Symfony\Component\Security\Http\Authentication\AuthenticatorManager';
$classes[] = '_ContaoManager\Symfony\Component\Security\Core\Authorization\AuthorizationChecker';
$classes[] = '_ContaoManager\Symfony\Component\Security\Http\Firewall\ChannelListener';
$classes[] = '_ContaoManager\Symfony\Bundle\SecurityBundle\EventListener\FirewallListener';
$classes[] = '_ContaoManager\Symfony\Component\Security\Http\Logout\LogoutUrlGenerator';
$classes[] = '_ContaoManager\Symfony\Component\Security\Http\Firewall\AuthenticatorManagerListener';
$classes[] = '_ContaoManager\Symfony\Bundle\SecurityBundle\Security\FirewallMap';
$classes[] = '_ContaoManager\Symfony\Bundle\SecurityBundle\Security\FirewallContext';
$classes[] = '_ContaoManager\Symfony\Component\Security\Http\Firewall\ExceptionListener';
$classes[] = '_ContaoManager\Symfony\Component\Security\Http\HttpUtils';
$classes[] = '_ContaoManager\Symfony\Bundle\SecurityBundle\Security\FirewallConfig';
$classes[] = '_ContaoManager\Symfony\Bundle\SecurityBundle\Security';
$classes[] = '_ContaoManager\Symfony\Component\Security\Http\EventListener\UserProviderListener';
$classes[] = '_ContaoManager\Symfony\Component\Security\Http\EventListener\CheckCredentialsListener';
$classes[] = '_ContaoManager\Symfony\Component\Security\Http\EventListener\PasswordMigratingListener';
$classes[] = '_ContaoManager\Symfony\Component\Security\Http\EventListener\UserCheckerListener';
$classes[] = '_ContaoManager\Symfony\Component\PasswordHasher\Hasher\PasswordHasherFactory';
$classes[] = '_ContaoManager\Symfony\Bundle\SecurityBundle\Routing\LogoutRouteLoader';
$classes[] = '_ContaoManager\Symfony\Component\Security\Http\Controller\SecurityTokenValueResolver';
$classes[] = '_ContaoManager\Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorage';
$classes[] = '_ContaoManager\Symfony\Component\Security\Core\User\InMemoryUserChecker';
$classes[] = '_ContaoManager\Symfony\Component\Security\Http\Controller\UserValueResolver';
$classes[] = '_ContaoManager\Symfony\Component\Serializer\Serializer';
$classes[] = '_ContaoManager\Symfony\Component\Serializer\Normalizer\UnwrappingDenormalizer';
$classes[] = '_ContaoManager\Symfony\Component\Serializer\Normalizer\ProblemNormalizer';
$classes[] = '_ContaoManager\Symfony\Component\Serializer\Normalizer\UidNormalizer';
$classes[] = '_ContaoManager\Symfony\Component\Serializer\Normalizer\DateTimeNormalizer';
$classes[] = '_ContaoManager\Symfony\Component\Serializer\Normalizer\ConstraintViolationListNormalizer';
$classes[] = '_ContaoManager\Symfony\Component\Serializer\NameConverter\MetadataAwareNameConverter';
$classes[] = '_ContaoManager\Symfony\Component\Serializer\Normalizer\DateTimeZoneNormalizer';
$classes[] = '_ContaoManager\Symfony\Component\Serializer\Normalizer\DateIntervalNormalizer';
$classes[] = '_ContaoManager\Symfony\Component\Serializer\Normalizer\FormErrorNormalizer';
$classes[] = '_ContaoManager\Symfony\Component\Serializer\Normalizer\BackedEnumNormalizer';
$classes[] = '_ContaoManager\Symfony\Component\Serializer\Normalizer\DataUriNormalizer';
$classes[] = '_ContaoManager\Symfony\Component\Serializer\Normalizer\JsonSerializableNormalizer';
$classes[] = '_ContaoManager\Symfony\Component\Serializer\Normalizer\ArrayDenormalizer';
$classes[] = '_ContaoManager\Symfony\Component\Serializer\Normalizer\ObjectNormalizer';
$classes[] = '_ContaoManager\Symfony\Component\PropertyInfo\PropertyInfoCacheExtractor';
$classes[] = '_ContaoManager\Symfony\Component\PropertyInfo\PropertyInfoExtractor';
$classes[] = '_ContaoManager\Symfony\Component\Serializer\Mapping\ClassDiscriminatorFromClassMetadata';
$classes[] = '_ContaoManager\Symfony\Component\Serializer\Encoder\XmlEncoder';
$classes[] = '_ContaoManager\Symfony\Component\Serializer\Encoder\JsonEncoder';
$classes[] = '_ContaoManager\Symfony\Component\Serializer\Encoder\YamlEncoder';
$classes[] = '_ContaoManager\Symfony\Component\Serializer\Encoder\CsvEncoder';
$classes[] = '_ContaoManager\Symfony\Component\Serializer\Mapping\Factory\CacheClassMetadataFactory';
$classes[] = '_ContaoManager\Symfony\Component\Serializer\Mapping\Factory\ClassMetadataFactory';
$classes[] = '_ContaoManager\Symfony\Component\Serializer\Mapping\Loader\LoaderChain';
$classes[] = '_ContaoManager\Symfony\Component\Serializer\Mapping\Loader\AttributeLoader';
$classes[] = '_ContaoManager\Psr\Cache\CacheItemPoolInterface';
$classes[] = '_ContaoManager\Symfony\Component\Cache\Adapter\PhpArrayAdapter';
$classes[] = '_ContaoManager\Symfony\Component\DependencyInjection\ContainerInterface';
$classes[] = '_ContaoManager\Symfony\Component\HttpKernel\DependencyInjection\ServicesResetter';
$classes[] = '_ContaoManager\Symfony\Component\HttpKernel\EventListener\ValidateRequestListener';
$preloaded = Preloader::preload($classes);
$classes = [];
$classes[] = '_ContaoManager\Symfony\Component\Routing\Generator\CompiledUrlGenerator';
$classes[] = '_ContaoManager\Symfony\Bundle\FrameworkBundle\Routing\RedirectableCompiledUrlMatcher';
$preloaded = Preloader::preload($classes, $preloaded);
<?php

namespace _ContaoManager\Symfony\Config\Framework;

use _ContaoManager\Symfony\Component\Config\Loader\ParamConfigurator;
use _ContaoManager\Symfony\Component\Config\Definition\Exception\InvalidConfigurationException;
/**
 * This class is automatically generated to help in creating a config.
 */
class HttpCacheConfig
{
    private $enabled;
    private $debug;
    private $traceLevel;
    private $traceHeader;
    private $defaultTtl;
    private $privateHeaders;
    private $skipResponseHeaders;
    private $allowReload;
    private $allowRevalidate;
    private $staleWhileRevalidate;
    private $staleIfError;
    private $terminateOnCacheHit;
    private $_usedProperties = [];
    /**
     * @default false
     * @param ParamConfigurator|bool $value
     * @return $this
     */
    public function enabled($value): static
    {
        $this->_usedProperties['enabled'] = \true;
        $this->enabled = $value;
        return $this;
    }
    /**
     * @default '%kernel.debug%'
     * @param ParamConfigurator|bool $value
     * @return $this
     */
    public function debug($value): static
    {
        $this->_usedProperties['debug'] = \true;
        $this->debug = $value;
        return $this;
    }
    /**
     * @default null
     * @param ParamConfigurator|'none'|'short'|'full' $value
     * @return $this
     */
    public function traceLevel($value): static
    {
        $this->_usedProperties['traceLevel'] = \true;
        $this->traceLevel = $value;
        return $this;
    }
    /**
     * @default null
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function traceHeader($value): static
    {
        $this->_usedProperties['traceHeader'] = \true;
        $this->traceHeader = $value;
        return $this;
    }
    /**
     * @default null
     * @param ParamConfigurator|int $value
     * @return $this
     */
    public function defaultTtl($value): static
    {
        $this->_usedProperties['defaultTtl'] = \true;
        $this->defaultTtl = $value;
        return $this;
    }
    /**
     * @param ParamConfigurator|list<ParamConfigurator|mixed> $value
     *
     * @return $this
     */
    public function privateHeaders(ParamConfigurator|array $value): static
    {
        $this->_usedProperties['privateHeaders'] = \true;
        $this->privateHeaders = $value;
        return $this;
    }
    /**
     * @param ParamConfigurator|list<ParamConfigurator|mixed> $value
     *
     * @return $this
     */
    public function skipResponseHeaders(ParamConfigurator|array $value): static
    {
        $this->_usedProperties['skipResponseHeaders'] = \true;
        $this->skipResponseHeaders = $value;
        return $this;
    }
    /**
     * @default null
     * @param ParamConfigurator|bool $value
     * @return $this
     */
    public function allowReload($value): static
    {
        $this->_usedProperties['allowReload'] = \true;
        $this->allowReload = $value;
        return $this;
    }
    /**
     * @default null
     * @param ParamConfigurator|bool $value
     * @return $this
     */
    public function allowRevalidate($value): static
    {
        $this->_usedProperties['allowRevalidate'] = \true;
        $this->allowRevalidate = $value;
        return $this;
    }
    /**
     * @default null
     * @param ParamConfigurator|int $value
     * @return $this
     */
    public function staleWhileRevalidate($value): static
    {
        $this->_usedProperties['staleWhileRevalidate'] = \true;
        $this->staleWhileRevalidate = $value;
        return $this;
    }
    /**
     * @default null
     * @param ParamConfigurator|int $value
     * @return $this
     */
    public function staleIfError($value): static
    {
        $this->_usedProperties['staleIfError'] = \true;
        $this->staleIfError = $value;
        return $this;
    }
    /**
     * @default null
     * @param ParamConfigurator|bool $value
     * @return $this
     */
    public function terminateOnCacheHit($value): static
    {
        $this->_usedProperties['terminateOnCacheHit'] = \true;
        $this->terminateOnCacheHit = $value;
        return $this;
    }
    public function __construct(array $value = [])
    {
        if (array_key_exists('enabled', $value)) {
            $this->_usedProperties['enabled'] = \true;
            $this->enabled = $value['enabled'];
            unset($value['enabled']);
        }
        if (array_key_exists('debug', $value)) {
            $this->_usedProperties['debug'] = \true;
            $this->debug = $value['debug'];
            unset($value['debug']);
        }
        if (array_key_exists('trace_level', $value)) {
            $this->_usedProperties['traceLevel'] = \true;
            $this->traceLevel = $value['trace_level'];
            unset($value['trace_level']);
        }
        if (array_key_exists('trace_header', $value)) {
            $this->_usedProperties['traceHeader'] = \true;
            $this->traceHeader = $value['trace_header'];
            unset($value['trace_header']);
        }
        if (array_key_exists('default_ttl', $value)) {
            $this->_usedProperties['defaultTtl'] = \true;
            $this->defaultTtl = $value['default_ttl'];
            unset($value['default_ttl']);
        }
        if (array_key_exists('private_headers', $value)) {
            $this->_usedProperties['privateHeaders'] = \true;
            $this->privateHeaders = $value['private_headers'];
            unset($value['private_headers']);
        }
        if (array_key_exists('skip_response_headers', $value)) {
            $this->_usedProperties['skipResponseHeaders'] = \true;
            $this->skipResponseHeaders = $value['skip_response_headers'];
            unset($value['skip_response_headers']);
        }
        if (array_key_exists('allow_reload', $value)) {
            $this->_usedProperties['allowReload'] = \true;
            $this->allowReload = $value['allow_reload'];
            unset($value['allow_reload']);
        }
        if (array_key_exists('allow_revalidate', $value)) {
            $this->_usedProperties['allowRevalidate'] = \true;
            $this->allowRevalidate = $value['allow_revalidate'];
            unset($value['allow_revalidate']);
        }
        if (array_key_exists('stale_while_revalidate', $value)) {
            $this->_usedProperties['staleWhileRevalidate'] = \true;
            $this->staleWhileRevalidate = $value['stale_while_revalidate'];
            unset($value['stale_while_revalidate']);
        }
        if (array_key_exists('stale_if_error', $value)) {
            $this->_usedProperties['staleIfError'] = \true;
            $this->staleIfError = $value['stale_if_error'];
            unset($value['stale_if_error']);
        }
        if (array_key_exists('terminate_on_cache_hit', $value)) {
            $this->_usedProperties['terminateOnCacheHit'] = \true;
            $this->terminateOnCacheHit = $value['terminate_on_cache_hit'];
            unset($value['terminate_on_cache_hit']);
        }
        if ([] !== $value) {
            throw new InvalidConfigurationException(sprintf('The following keys are not supported by "%s": ', __CLASS__) . implode(', ', array_keys($value)));
        }
    }
    public function toArray(): array
    {
        $output = [];
        if (isset($this->_usedProperties['enabled'])) {
            $output['enabled'] = $this->enabled;
        }
        if (isset($this->_usedProperties['debug'])) {
            $output['debug'] = $this->debug;
        }
        if (isset($this->_usedProperties['traceLevel'])) {
            $output['trace_level'] = $this->traceLevel;
        }
        if (isset($this->_usedProperties['traceHeader'])) {
            $output['trace_header'] = $this->traceHeader;
        }
        if (isset($this->_usedProperties['defaultTtl'])) {
            $output['default_ttl'] = $this->defaultTtl;
        }
        if (isset($this->_usedProperties['privateHeaders'])) {
            $output['private_headers'] = $this->privateHeaders;
        }
        if (isset($this->_usedProperties['skipResponseHeaders'])) {
            $output['skip_response_headers'] = $this->skipResponseHeaders;
        }
        if (isset($this->_usedProperties['allowReload'])) {
            $output['allow_reload'] = $this->allowReload;
        }
        if (isset($this->_usedProperties['allowRevalidate'])) {
            $output['allow_revalidate'] = $this->allowRevalidate;
        }
        if (isset($this->_usedProperties['staleWhileRevalidate'])) {
            $output['stale_while_revalidate'] = $this->staleWhileRevalidate;
        }
        if (isset($this->_usedProperties['staleIfError'])) {
            $output['stale_if_error'] = $this->staleIfError;
        }
        if (isset($this->_usedProperties['terminateOnCacheHit'])) {
            $output['terminate_on_cache_hit'] = $this->terminateOnCacheHit;
        }
        return $output;
    }
}
<?php

namespace _ContaoManager\Symfony\Config\Framework\Webhook;

use _ContaoManager\Symfony\Component\Config\Loader\ParamConfigurator;
use _ContaoManager\Symfony\Component\Config\Definition\Exception\InvalidConfigurationException;
/**
 * This class is automatically generated to help in creating a config.
 */
class RoutingConfig
{
    private $service;
    private $secret;
    private $_usedProperties = [];
    /**
     * @default null
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function service($value): static
    {
        $this->_usedProperties['service'] = \true;
        $this->service = $value;
        return $this;
    }
    /**
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function secret($value): static
    {
        $this->_usedProperties['secret'] = \true;
        $this->secret = $value;
        return $this;
    }
    public function __construct(array $value = [])
    {
        if (array_key_exists('service', $value)) {
            $this->_usedProperties['service'] = \true;
            $this->service = $value['service'];
            unset($value['service']);
        }
        if (array_key_exists('secret', $value)) {
            $this->_usedProperties['secret'] = \true;
            $this->secret = $value['secret'];
            unset($value['secret']);
        }
        if ([] !== $value) {
            throw new InvalidConfigurationException(sprintf('The following keys are not supported by "%s": ', __CLASS__) . implode(', ', array_keys($value)));
        }
    }
    public function toArray(): array
    {
        $output = [];
        if (isset($this->_usedProperties['service'])) {
            $output['service'] = $this->service;
        }
        if (isset($this->_usedProperties['secret'])) {
            $output['secret'] = $this->secret;
        }
        return $output;
    }
}
<?php

namespace _ContaoManager\Symfony\Config\Framework;

require_once __DIR__ . \DIRECTORY_SEPARATOR . 'Cache' . \DIRECTORY_SEPARATOR . 'PoolConfig.php';
use _ContaoManager\Symfony\Component\Config\Loader\ParamConfigurator;
use _ContaoManager\Symfony\Component\Config\Definition\Exception\InvalidConfigurationException;
/**
 * This class is automatically generated to help in creating a config.
 */
class CacheConfig
{
    private $prefixSeed;
    private $app;
    private $system;
    private $directory;
    private $defaultPsr6Provider;
    private $defaultRedisProvider;
    private $defaultMemcachedProvider;
    private $defaultDoctrineDbalProvider;
    private $defaultPdoProvider;
    private $pools;
    private $_usedProperties = [];
    /**
     * Used to namespace cache keys when using several apps with the same shared backend
     * @example my-application-name/%kernel.environment%
     * @default '_%kernel.project_dir%.%kernel.container_class%'
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function prefixSeed($value): static
    {
        $this->_usedProperties['prefixSeed'] = \true;
        $this->prefixSeed = $value;
        return $this;
    }
    /**
     * App related cache pools configuration
     * @default 'cache.adapter.filesystem'
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function app($value): static
    {
        $this->_usedProperties['app'] = \true;
        $this->app = $value;
        return $this;
    }
    /**
     * System related cache pools configuration
     * @default 'cache.adapter.system'
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function system($value): static
    {
        $this->_usedProperties['system'] = \true;
        $this->system = $value;
        return $this;
    }
    /**
     * @default '%kernel.cache_dir%/pools/app'
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function directory($value): static
    {
        $this->_usedProperties['directory'] = \true;
        $this->directory = $value;
        return $this;
    }
    /**
     * @default null
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function defaultPsr6Provider($value): static
    {
        $this->_usedProperties['defaultPsr6Provider'] = \true;
        $this->defaultPsr6Provider = $value;
        return $this;
    }
    /**
     * @default 'redis://localhost'
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function defaultRedisProvider($value): static
    {
        $this->_usedProperties['defaultRedisProvider'] = \true;
        $this->defaultRedisProvider = $value;
        return $this;
    }
    /**
     * @default 'memcached://localhost'
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function defaultMemcachedProvider($value): static
    {
        $this->_usedProperties['defaultMemcachedProvider'] = \true;
        $this->defaultMemcachedProvider = $value;
        return $this;
    }
    /**
     * @default 'database_connection'
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function defaultDoctrineDbalProvider($value): static
    {
        $this->_usedProperties['defaultDoctrineDbalProvider'] = \true;
        $this->defaultDoctrineDbalProvider = $value;
        return $this;
    }
    /**
     * @default null
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function defaultPdoProvider($value): static
    {
        $this->_usedProperties['defaultPdoProvider'] = \true;
        $this->defaultPdoProvider = $value;
        return $this;
    }
    /**
     * @template TValue of mixed
     * @param TValue $value
     * @return \Symfony\Config\Framework\Cache\PoolConfig|$this
     * @psalm-return (TValue is array ? \Symfony\Config\Framework\Cache\PoolConfig : static)
     */
    public function pool(string $name, mixed $value = []): \_ContaoManager\Symfony\Config\Framework\Cache\PoolConfig|static
    {
        if (!\is_array($value)) {
            $this->_usedProperties['pools'] = \true;
            $this->pools[$name] = $value;
            return $this;
        }
        if (!isset($this->pools[$name]) || !$this->pools[$name] instanceof \_ContaoManager\Symfony\Config\Framework\Cache\PoolConfig) {
            $this->_usedProperties['pools'] = \true;
            $this->pools[$name] = new \_ContaoManager\Symfony\Config\Framework\Cache\PoolConfig($value);
        } elseif (1 < \func_num_args()) {
            throw new InvalidConfigurationException('The node created by "pool()" has already been initialized. You cannot pass values the second time you call pool().');
        }
        return $this->pools[$name];
    }
    public function __construct(array $value = [])
    {
        if (array_key_exists('prefix_seed', $value)) {
            $this->_usedProperties['prefixSeed'] = \true;
            $this->prefixSeed = $value['prefix_seed'];
            unset($value['prefix_seed']);
        }
        if (array_key_exists('app', $value)) {
            $this->_usedProperties['app'] = \true;
            $this->app = $value['app'];
            unset($value['app']);
        }
        if (array_key_exists('system', $value)) {
            $this->_usedProperties['system'] = \true;
            $this->system = $value['system'];
            unset($value['system']);
        }
        if (array_key_exists('directory', $value)) {
            $this->_usedProperties['directory'] = \true;
            $this->directory = $value['directory'];
            unset($value['directory']);
        }
        if (array_key_exists('default_psr6_provider', $value)) {
            $this->_usedProperties['defaultPsr6Provider'] = \true;
            $this->defaultPsr6Provider = $value['default_psr6_provider'];
            unset($value['default_psr6_provider']);
        }
        if (array_key_exists('default_redis_provider', $value)) {
            $this->_usedProperties['defaultRedisProvider'] = \true;
            $this->defaultRedisProvider = $value['default_redis_provider'];
            unset($value['default_redis_provider']);
        }
        if (array_key_exists('default_memcached_provider', $value)) {
            $this->_usedProperties['defaultMemcachedProvider'] = \true;
            $this->defaultMemcachedProvider = $value['default_memcached_provider'];
            unset($value['default_memcached_provider']);
        }
        if (array_key_exists('default_doctrine_dbal_provider', $value)) {
            $this->_usedProperties['defaultDoctrineDbalProvider'] = \true;
            $this->defaultDoctrineDbalProvider = $value['default_doctrine_dbal_provider'];
            unset($value['default_doctrine_dbal_provider']);
        }
        if (array_key_exists('default_pdo_provider', $value)) {
            $this->_usedProperties['defaultPdoProvider'] = \true;
            $this->defaultPdoProvider = $value['default_pdo_provider'];
            unset($value['default_pdo_provider']);
        }
        if (array_key_exists('pools', $value)) {
            $this->_usedProperties['pools'] = \true;
            $this->pools = array_map(fn($v) => \is_array($v) ? new \_ContaoManager\Symfony\Config\Framework\Cache\PoolConfig($v) : $v, $value['pools']);
            unset($value['pools']);
        }
        if ([] !== $value) {
            throw new InvalidConfigurationException(sprintf('The following keys are not supported by "%s": ', __CLASS__) . implode(', ', array_keys($value)));
        }
    }
    public function toArray(): array
    {
        $output = [];
        if (isset($this->_usedProperties['prefixSeed'])) {
            $output['prefix_seed'] = $this->prefixSeed;
        }
        if (isset($this->_usedProperties['app'])) {
            $output['app'] = $this->app;
        }
        if (isset($this->_usedProperties['system'])) {
            $output['system'] = $this->system;
        }
        if (isset($this->_usedProperties['directory'])) {
            $output['directory'] = $this->directory;
        }
        if (isset($this->_usedProperties['defaultPsr6Provider'])) {
            $output['default_psr6_provider'] = $this->defaultPsr6Provider;
        }
        if (isset($this->_usedProperties['defaultRedisProvider'])) {
            $output['default_redis_provider'] = $this->defaultRedisProvider;
        }
        if (isset($this->_usedProperties['defaultMemcachedProvider'])) {
            $output['default_memcached_provider'] = $this->defaultMemcachedProvider;
        }
        if (isset($this->_usedProperties['defaultDoctrineDbalProvider'])) {
            $output['default_doctrine_dbal_provider'] = $this->defaultDoctrineDbalProvider;
        }
        if (isset($this->_usedProperties['defaultPdoProvider'])) {
            $output['default_pdo_provider'] = $this->defaultPdoProvider;
        }
        if (isset($this->_usedProperties['pools'])) {
            $output['pools'] = array_map(fn($v) => $v instanceof \_ContaoManager\Symfony\Config\Framework\Cache\PoolConfig ? $v->toArray() : $v, $this->pools);
        }
        return $output;
    }
}
<?php

namespace _ContaoManager\Symfony\Config\Framework;

use _ContaoManager\Symfony\Component\Config\Loader\ParamConfigurator;
use _ContaoManager\Symfony\Component\Config\Definition\Exception\InvalidConfigurationException;
/**
 * This class is automatically generated to help in creating a config.
 */
class FragmentsConfig
{
    private $enabled;
    private $hincludeDefaultTemplate;
    private $path;
    private $_usedProperties = [];
    /**
     * @default false
     * @param ParamConfigurator|bool $value
     * @return $this
     */
    public function enabled($value): static
    {
        $this->_usedProperties['enabled'] = \true;
        $this->enabled = $value;
        return $this;
    }
    /**
     * @default null
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function hincludeDefaultTemplate($value): static
    {
        $this->_usedProperties['hincludeDefaultTemplate'] = \true;
        $this->hincludeDefaultTemplate = $value;
        return $this;
    }
    /**
     * @default '/_fragment'
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function path($value): static
    {
        $this->_usedProperties['path'] = \true;
        $this->path = $value;
        return $this;
    }
    public function __construct(array $value = [])
    {
        if (array_key_exists('enabled', $value)) {
            $this->_usedProperties['enabled'] = \true;
            $this->enabled = $value['enabled'];
            unset($value['enabled']);
        }
        if (array_key_exists('hinclude_default_template', $value)) {
            $this->_usedProperties['hincludeDefaultTemplate'] = \true;
            $this->hincludeDefaultTemplate = $value['hinclude_default_template'];
            unset($value['hinclude_default_template']);
        }
        if (array_key_exists('path', $value)) {
            $this->_usedProperties['path'] = \true;
            $this->path = $value['path'];
            unset($value['path']);
        }
        if ([] !== $value) {
            throw new InvalidConfigurationException(sprintf('The following keys are not supported by "%s": ', __CLASS__) . implode(', ', array_keys($value)));
        }
    }
    public function toArray(): array
    {
        $output = [];
        if (isset($this->_usedProperties['enabled'])) {
            $output['enabled'] = $this->enabled;
        }
        if (isset($this->_usedProperties['hincludeDefaultTemplate'])) {
            $output['hinclude_default_template'] = $this->hincludeDefaultTemplate;
        }
        if (isset($this->_usedProperties['path'])) {
            $output['path'] = $this->path;
        }
        return $output;
    }
}
<?php

namespace _ContaoManager\Symfony\Config\Framework\Form;

use _ContaoManager\Symfony\Component\Config\Loader\ParamConfigurator;
use _ContaoManager\Symfony\Component\Config\Definition\Exception\InvalidConfigurationException;
/**
 * This class is automatically generated to help in creating a config.
 */
class CsrfProtectionConfig
{
    private $enabled;
    private $fieldName;
    private $_usedProperties = [];
    /**
     * @default null
     * @param ParamConfigurator|bool $value
     * @return $this
     */
    public function enabled($value): static
    {
        $this->_usedProperties['enabled'] = \true;
        $this->enabled = $value;
        return $this;
    }
    /**
     * @default '_token'
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function fieldName($value): static
    {
        $this->_usedProperties['fieldName'] = \true;
        $this->fieldName = $value;
        return $this;
    }
    public function __construct(array $value = [])
    {
        if (array_key_exists('enabled', $value)) {
            $this->_usedProperties['enabled'] = \true;
            $this->enabled = $value['enabled'];
            unset($value['enabled']);
        }
        if (array_key_exists('field_name', $value)) {
            $this->_usedProperties['fieldName'] = \true;
            $this->fieldName = $value['field_name'];
            unset($value['field_name']);
        }
        if ([] !== $value) {
            throw new InvalidConfigurationException(sprintf('The following keys are not supported by "%s": ', __CLASS__) . implode(', ', array_keys($value)));
        }
    }
    public function toArray(): array
    {
        $output = [];
        if (isset($this->_usedProperties['enabled'])) {
            $output['enabled'] = $this->enabled;
        }
        if (isset($this->_usedProperties['fieldName'])) {
            $output['field_name'] = $this->fieldName;
        }
        return $output;
    }
}
<?php

namespace _ContaoManager\Symfony\Config\Framework\HttpClient;

require_once __DIR__ . \DIRECTORY_SEPARATOR . 'DefaultOptions' . \DIRECTORY_SEPARATOR . 'PeerFingerprintConfig.php';
require_once __DIR__ . \DIRECTORY_SEPARATOR . 'DefaultOptions' . \DIRECTORY_SEPARATOR . 'RetryFailedConfig.php';
use _ContaoManager\Symfony\Component\Config\Loader\ParamConfigurator;
use _ContaoManager\Symfony\Component\Config\Definition\Exception\InvalidConfigurationException;
/**
 * This class is automatically generated to help in creating a config.
 */
class DefaultOptionsConfig
{
    private $headers;
    private $vars;
    private $maxRedirects;
    private $httpVersion;
    private $resolve;
    private $proxy;
    private $noProxy;
    private $timeout;
    private $maxDuration;
    private $bindto;
    private $verifyPeer;
    private $verifyHost;
    private $cafile;
    private $capath;
    private $localCert;
    private $localPk;
    private $passphrase;
    private $ciphers;
    private $peerFingerprint;
    private $cryptoMethod;
    private $extra;
    private $retryFailed;
    private $_usedProperties = [];
    /**
     * @return $this
     */
    public function header(string $name, mixed $value): static
    {
        $this->_usedProperties['headers'] = \true;
        $this->headers[$name] = $value;
        return $this;
    }
    /**
     * @return $this
     */
    public function vars(string $name, mixed $value): static
    {
        $this->_usedProperties['vars'] = \true;
        $this->vars[$name] = $value;
        return $this;
    }
    /**
     * The maximum number of redirects to follow.
     * @default null
     * @param ParamConfigurator|int $value
     * @return $this
     */
    public function maxRedirects($value): static
    {
        $this->_usedProperties['maxRedirects'] = \true;
        $this->maxRedirects = $value;
        return $this;
    }
    /**
     * The default HTTP version, typically 1.1 or 2.0, leave to null for the best version.
     * @default null
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function httpVersion($value): static
    {
        $this->_usedProperties['httpVersion'] = \true;
        $this->httpVersion = $value;
        return $this;
    }
    /**
     * @return $this
     */
    public function resolve(string $host, mixed $value): static
    {
        $this->_usedProperties['resolve'] = \true;
        $this->resolve[$host] = $value;
        return $this;
    }
    /**
     * The URL of the proxy to pass requests through or null for automatic detection.
     * @default null
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function proxy($value): static
    {
        $this->_usedProperties['proxy'] = \true;
        $this->proxy = $value;
        return $this;
    }
    /**
     * A comma separated list of hosts that do not require a proxy to be reached.
     * @default null
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function noProxy($value): static
    {
        $this->_usedProperties['noProxy'] = \true;
        $this->noProxy = $value;
        return $this;
    }
    /**
     * The idle timeout, defaults to the "default_socket_timeout" ini parameter.
     * @default null
     * @param ParamConfigurator|float $value
     * @return $this
     */
    public function timeout($value): static
    {
        $this->_usedProperties['timeout'] = \true;
        $this->timeout = $value;
        return $this;
    }
    /**
     * The maximum execution time for the request+response as a whole.
     * @default null
     * @param ParamConfigurator|float $value
     * @return $this
     */
    public function maxDuration($value): static
    {
        $this->_usedProperties['maxDuration'] = \true;
        $this->maxDuration = $value;
        return $this;
    }
    /**
     * A network interface name, IP address, a host name or a UNIX socket to bind to.
     * @default null
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function bindto($value): static
    {
        $this->_usedProperties['bindto'] = \true;
        $this->bindto = $value;
        return $this;
    }
    /**
     * Indicates if the peer should be verified in a TLS context.
     * @default null
     * @param ParamConfigurator|bool $value
     * @return $this
     */
    public function verifyPeer($value): static
    {
        $this->_usedProperties['verifyPeer'] = \true;
        $this->verifyPeer = $value;
        return $this;
    }
    /**
     * Indicates if the host should exist as a certificate common name.
     * @default null
     * @param ParamConfigurator|bool $value
     * @return $this
     */
    public function verifyHost($value): static
    {
        $this->_usedProperties['verifyHost'] = \true;
        $this->verifyHost = $value;
        return $this;
    }
    /**
     * A certificate authority file.
     * @default null
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function cafile($value): static
    {
        $this->_usedProperties['cafile'] = \true;
        $this->cafile = $value;
        return $this;
    }
    /**
     * A directory that contains multiple certificate authority files.
     * @default null
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function capath($value): static
    {
        $this->_usedProperties['capath'] = \true;
        $this->capath = $value;
        return $this;
    }
    /**
     * A PEM formatted certificate file.
     * @default null
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function localCert($value): static
    {
        $this->_usedProperties['localCert'] = \true;
        $this->localCert = $value;
        return $this;
    }
    /**
     * A private key file.
     * @default null
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function localPk($value): static
    {
        $this->_usedProperties['localPk'] = \true;
        $this->localPk = $value;
        return $this;
    }
    /**
     * The passphrase used to encrypt the "local_pk" file.
     * @default null
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function passphrase($value): static
    {
        $this->_usedProperties['passphrase'] = \true;
        $this->passphrase = $value;
        return $this;
    }
    /**
     * A list of TLS ciphers separated by colons, commas or spaces (e.g. "RC3-SHA:TLS13-AES-128-GCM-SHA256"...)
     * @default null
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function ciphers($value): static
    {
        $this->_usedProperties['ciphers'] = \true;
        $this->ciphers = $value;
        return $this;
    }
    /**
     * Associative array: hashing algorithm => hash(es).
     */
    public function peerFingerprint(array $value = []): \_ContaoManager\Symfony\Config\Framework\HttpClient\DefaultOptions\PeerFingerprintConfig
    {
        if (null === $this->peerFingerprint) {
            $this->_usedProperties['peerFingerprint'] = \true;
            $this->peerFingerprint = new \_ContaoManager\Symfony\Config\Framework\HttpClient\DefaultOptions\PeerFingerprintConfig($value);
        } elseif (0 < \func_num_args()) {
            throw new InvalidConfigurationException('The node created by "peerFingerprint()" has already been initialized. You cannot pass values the second time you call peerFingerprint().');
        }
        return $this->peerFingerprint;
    }
    /**
     * The minimum version of TLS to accept; must be one of STREAM_CRYPTO_METHOD_TLSv*_CLIENT constants.
     * @default null
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function cryptoMethod($value): static
    {
        $this->_usedProperties['cryptoMethod'] = \true;
        $this->cryptoMethod = $value;
        return $this;
    }
    /**
     * @return $this
     */
    public function extra(string $name, mixed $value): static
    {
        $this->_usedProperties['extra'] = \true;
        $this->extra[$name] = $value;
        return $this;
    }
    /**
     * @template TValue of mixed
     * @param TValue $value
     * @default {"enabled":false,"retry_strategy":null,"http_codes":[],"max_retries":3,"delay":1000,"multiplier":2,"max_delay":0,"jitter":0.1}
     * @return \Symfony\Config\Framework\HttpClient\DefaultOptions\RetryFailedConfig|$this
     * @psalm-return (TValue is array ? \Symfony\Config\Framework\HttpClient\DefaultOptions\RetryFailedConfig : static)
     */
    public function retryFailed(mixed $value = []): \_ContaoManager\Symfony\Config\Framework\HttpClient\DefaultOptions\RetryFailedConfig|static
    {
        if (!\is_array($value)) {
            $this->_usedProperties['retryFailed'] = \true;
            $this->retryFailed = $value;
            return $this;
        }
        if (!$this->retryFailed instanceof \_ContaoManager\Symfony\Config\Framework\HttpClient\DefaultOptions\RetryFailedConfig) {
            $this->_usedProperties['retryFailed'] = \true;
            $this->retryFailed = new \_ContaoManager\Symfony\Config\Framework\HttpClient\DefaultOptions\RetryFailedConfig($value);
        } elseif (0 < \func_num_args()) {
            throw new InvalidConfigurationException('The node created by "retryFailed()" has already been initialized. You cannot pass values the second time you call retryFailed().');
        }
        return $this->retryFailed;
    }
    public function __construct(array $value = [])
    {
        if (array_key_exists('headers', $value)) {
            $this->_usedProperties['headers'] = \true;
            $this->headers = $value['headers'];
            unset($value['headers']);
        }
        if (array_key_exists('vars', $value)) {
            $this->_usedProperties['vars'] = \true;
            $this->vars = $value['vars'];
            unset($value['vars']);
        }
        if (array_key_exists('max_redirects', $value)) {
            $this->_usedProperties['maxRedirects'] = \true;
            $this->maxRedirects = $value['max_redirects'];
            unset($value['max_redirects']);
        }
        if (array_key_exists('http_version', $value)) {
            $this->_usedProperties['httpVersion'] = \true;
            $this->httpVersion = $value['http_version'];
            unset($value['http_version']);
        }
        if (array_key_exists('resolve', $value)) {
            $this->_usedProperties['resolve'] = \true;
            $this->resolve = $value['resolve'];
            unset($value['resolve']);
        }
        if (array_key_exists('proxy', $value)) {
            $this->_usedProperties['proxy'] = \true;
            $this->proxy = $value['proxy'];
            unset($value['proxy']);
        }
        if (array_key_exists('no_proxy', $value)) {
            $this->_usedProperties['noProxy'] = \true;
            $this->noProxy = $value['no_proxy'];
            unset($value['no_proxy']);
        }
        if (array_key_exists('timeout', $value)) {
            $this->_usedProperties['timeout'] = \true;
            $this->timeout = $value['timeout'];
            unset($value['timeout']);
        }
        if (array_key_exists('max_duration', $value)) {
            $this->_usedProperties['maxDuration'] = \true;
            $this->maxDuration = $value['max_duration'];
            unset($value['max_duration']);
        }
        if (array_key_exists('bindto', $value)) {
            $this->_usedProperties['bindto'] = \true;
            $this->bindto = $value['bindto'];
            unset($value['bindto']);
        }
        if (array_key_exists('verify_peer', $value)) {
            $this->_usedProperties['verifyPeer'] = \true;
            $this->verifyPeer = $value['verify_peer'];
            unset($value['verify_peer']);
        }
        if (array_key_exists('verify_host', $value)) {
            $this->_usedProperties['verifyHost'] = \true;
            $this->verifyHost = $value['verify_host'];
            unset($value['verify_host']);
        }
        if (array_key_exists('cafile', $value)) {
            $this->_usedProperties['cafile'] = \true;
            $this->cafile = $value['cafile'];
            unset($value['cafile']);
        }
        if (array_key_exists('capath', $value)) {
            $this->_usedProperties['capath'] = \true;
            $this->capath = $value['capath'];
            unset($value['capath']);
        }
        if (array_key_exists('local_cert', $value)) {
            $this->_usedProperties['localCert'] = \true;
            $this->localCert = $value['local_cert'];
            unset($value['local_cert']);
        }
        if (array_key_exists('local_pk', $value)) {
            $this->_usedProperties['localPk'] = \true;
            $this->localPk = $value['local_pk'];
            unset($value['local_pk']);
        }
        if (array_key_exists('passphrase', $value)) {
            $this->_usedProperties['passphrase'] = \true;
            $this->passphrase = $value['passphrase'];
            unset($value['passphrase']);
        }
        if (array_key_exists('ciphers', $value)) {
            $this->_usedProperties['ciphers'] = \true;
            $this->ciphers = $value['ciphers'];
            unset($value['ciphers']);
        }
        if (array_key_exists('peer_fingerprint', $value)) {
            $this->_usedProperties['peerFingerprint'] = \true;
            $this->peerFingerprint = new \_ContaoManager\Symfony\Config\Framework\HttpClient\DefaultOptions\PeerFingerprintConfig($value['peer_fingerprint']);
            unset($value['peer_fingerprint']);
        }
        if (array_key_exists('crypto_method', $value)) {
            $this->_usedProperties['cryptoMethod'] = \true;
            $this->cryptoMethod = $value['crypto_method'];
            unset($value['crypto_method']);
        }
        if (array_key_exists('extra', $value)) {
            $this->_usedProperties['extra'] = \true;
            $this->extra = $value['extra'];
            unset($value['extra']);
        }
        if (array_key_exists('retry_failed', $value)) {
            $this->_usedProperties['retryFailed'] = \true;
            $this->retryFailed = \is_array($value['retry_failed']) ? new \_ContaoManager\Symfony\Config\Framework\HttpClient\DefaultOptions\RetryFailedConfig($value['retry_failed']) : $value['retry_failed'];
            unset($value['retry_failed']);
        }
        if ([] !== $value) {
            throw new InvalidConfigurationException(sprintf('The following keys are not supported by "%s": ', __CLASS__) . implode(', ', array_keys($value)));
        }
    }
    public function toArray(): array
    {
        $output = [];
        if (isset($this->_usedProperties['headers'])) {
            $output['headers'] = $this->headers;
        }
        if (isset($this->_usedProperties['vars'])) {
            $output['vars'] = $this->vars;
        }
        if (isset($this->_usedProperties['maxRedirects'])) {
            $output['max_redirects'] = $this->maxRedirects;
        }
        if (isset($this->_usedProperties['httpVersion'])) {
            $output['http_version'] = $this->httpVersion;
        }
        if (isset($this->_usedProperties['resolve'])) {
            $output['resolve'] = $this->resolve;
        }
        if (isset($this->_usedProperties['proxy'])) {
            $output['proxy'] = $this->proxy;
        }
        if (isset($this->_usedProperties['noProxy'])) {
            $output['no_proxy'] = $this->noProxy;
        }
        if (isset($this->_usedProperties['timeout'])) {
            $output['timeout'] = $this->timeout;
        }
        if (isset($this->_usedProperties['maxDuration'])) {
            $output['max_duration'] = $this->maxDuration;
        }
        if (isset($this->_usedProperties['bindto'])) {
            $output['bindto'] = $this->bindto;
        }
        if (isset($this->_usedProperties['verifyPeer'])) {
            $output['verify_peer'] = $this->verifyPeer;
        }
        if (isset($this->_usedProperties['verifyHost'])) {
            $output['verify_host'] = $this->verifyHost;
        }
        if (isset($this->_usedProperties['cafile'])) {
            $output['cafile'] = $this->cafile;
        }
        if (isset($this->_usedProperties['capath'])) {
            $output['capath'] = $this->capath;
        }
        if (isset($this->_usedProperties['localCert'])) {
            $output['local_cert'] = $this->localCert;
        }
        if (isset($this->_usedProperties['localPk'])) {
            $output['local_pk'] = $this->localPk;
        }
        if (isset($this->_usedProperties['passphrase'])) {
            $output['passphrase'] = $this->passphrase;
        }
        if (isset($this->_usedProperties['ciphers'])) {
            $output['ciphers'] = $this->ciphers;
        }
        if (isset($this->_usedProperties['peerFingerprint'])) {
            $output['peer_fingerprint'] = $this->peerFingerprint->toArray();
        }
        if (isset($this->_usedProperties['cryptoMethod'])) {
            $output['crypto_method'] = $this->cryptoMethod;
        }
        if (isset($this->_usedProperties['extra'])) {
            $output['extra'] = $this->extra;
        }
        if (isset($this->_usedProperties['retryFailed'])) {
            $output['retry_failed'] = $this->retryFailed instanceof \_ContaoManager\Symfony\Config\Framework\HttpClient\DefaultOptions\RetryFailedConfig ? $this->retryFailed->toArray() : $this->retryFailed;
        }
        return $output;
    }
}
<?php

namespace _ContaoManager\Symfony\Config\Framework\HttpClient\ScopedClientConfig\RetryFailed;

use _ContaoManager\Symfony\Component\Config\Loader\ParamConfigurator;
use _ContaoManager\Symfony\Component\Config\Definition\Exception\InvalidConfigurationException;
/**
 * This class is automatically generated to help in creating a config.
 */
class HttpCodeConfig
{
    private $code;
    private $methods;
    private $_usedProperties = [];
    /**
     * @default null
     * @param ParamConfigurator|int $value
     * @return $this
     */
    public function code($value): static
    {
        $this->_usedProperties['code'] = \true;
        $this->code = $value;
        return $this;
    }
    /**
     * @param ParamConfigurator|list<ParamConfigurator|mixed> $value
     *
     * @return $this
     */
    public function methods(ParamConfigurator|array $value): static
    {
        $this->_usedProperties['methods'] = \true;
        $this->methods = $value;
        return $this;
    }
    public function __construct(array $value = [])
    {
        if (array_key_exists('code', $value)) {
            $this->_usedProperties['code'] = \true;
            $this->code = $value['code'];
            unset($value['code']);
        }
        if (array_key_exists('methods', $value)) {
            $this->_usedProperties['methods'] = \true;
            $this->methods = $value['methods'];
            unset($value['methods']);
        }
        if ([] !== $value) {
            throw new InvalidConfigurationException(sprintf('The following keys are not supported by "%s": ', __CLASS__) . implode(', ', array_keys($value)));
        }
    }
    public function toArray(): array
    {
        $output = [];
        if (isset($this->_usedProperties['code'])) {
            $output['code'] = $this->code;
        }
        if (isset($this->_usedProperties['methods'])) {
            $output['methods'] = $this->methods;
        }
        return $output;
    }
}
<?php

namespace _ContaoManager\Symfony\Config\Framework\HttpClient\ScopedClientConfig;

use _ContaoManager\Symfony\Component\Config\Loader\ParamConfigurator;
use _ContaoManager\Symfony\Component\Config\Definition\Exception\InvalidConfigurationException;
/**
 * This class is automatically generated to help in creating a config.
 */
class PeerFingerprintConfig
{
    private $sha1;
    private $pinsha256;
    private $md5;
    private $_usedProperties = [];
    /**
     * @default null
     * @param ParamConfigurator|mixed $value
     *
     * @return $this
     */
    public function sha1(mixed $value): static
    {
        $this->_usedProperties['sha1'] = \true;
        $this->sha1 = $value;
        return $this;
    }
    /**
     * @default null
     * @param ParamConfigurator|mixed $value
     *
     * @return $this
     */
    public function pinsha256(mixed $value): static
    {
        $this->_usedProperties['pinsha256'] = \true;
        $this->pinsha256 = $value;
        return $this;
    }
    /**
     * @default null
     * @param ParamConfigurator|mixed $value
     *
     * @return $this
     */
    public function md5(mixed $value): static
    {
        $this->_usedProperties['md5'] = \true;
        $this->md5 = $value;
        return $this;
    }
    public function __construct(array $value = [])
    {
        if (array_key_exists('sha1', $value)) {
            $this->_usedProperties['sha1'] = \true;
            $this->sha1 = $value['sha1'];
            unset($value['sha1']);
        }
        if (array_key_exists('pin-sha256', $value)) {
            $this->_usedProperties['pinsha256'] = \true;
            $this->pinsha256 = $value['pin-sha256'];
            unset($value['pin-sha256']);
        }
        if (array_key_exists('md5', $value)) {
            $this->_usedProperties['md5'] = \true;
            $this->md5 = $value['md5'];
            unset($value['md5']);
        }
        if ([] !== $value) {
            throw new InvalidConfigurationException(sprintf('The following keys are not supported by "%s": ', __CLASS__) . implode(', ', array_keys($value)));
        }
    }
    public function toArray(): array
    {
        $output = [];
        if (isset($this->_usedProperties['sha1'])) {
            $output['sha1'] = $this->sha1;
        }
        if (isset($this->_usedProperties['pinsha256'])) {
            $output['pin-sha256'] = $this->pinsha256;
        }
        if (isset($this->_usedProperties['md5'])) {
            $output['md5'] = $this->md5;
        }
        return $output;
    }
}
<?php

namespace _ContaoManager\Symfony\Config\Framework\HttpClient\ScopedClientConfig;

require_once __DIR__ . \DIRECTORY_SEPARATOR . 'RetryFailed' . \DIRECTORY_SEPARATOR . 'HttpCodeConfig.php';
use _ContaoManager\Symfony\Component\Config\Loader\ParamConfigurator;
use _ContaoManager\Symfony\Component\Config\Definition\Exception\InvalidConfigurationException;
/**
 * This class is automatically generated to help in creating a config.
 */
class RetryFailedConfig
{
    private $enabled;
    private $retryStrategy;
    private $httpCodes;
    private $maxRetries;
    private $delay;
    private $multiplier;
    private $maxDelay;
    private $jitter;
    private $_usedProperties = [];
    /**
     * @default false
     * @param ParamConfigurator|bool $value
     * @return $this
     */
    public function enabled($value): static
    {
        $this->_usedProperties['enabled'] = \true;
        $this->enabled = $value;
        return $this;
    }
    /**
     * service id to override the retry strategy
     * @default null
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function retryStrategy($value): static
    {
        $this->_usedProperties['retryStrategy'] = \true;
        $this->retryStrategy = $value;
        return $this;
    }
    /**
     * A list of HTTP status code that triggers a retry
     */
    public function httpCode(string $code, array $value = []): \_ContaoManager\Symfony\Config\Framework\HttpClient\ScopedClientConfig\RetryFailed\HttpCodeConfig
    {
        if (!isset($this->httpCodes[$code])) {
            $this->_usedProperties['httpCodes'] = \true;
            $this->httpCodes[$code] = new \_ContaoManager\Symfony\Config\Framework\HttpClient\ScopedClientConfig\RetryFailed\HttpCodeConfig($value);
        } elseif (1 < \func_num_args()) {
            throw new InvalidConfigurationException('The node created by "httpCode()" has already been initialized. You cannot pass values the second time you call httpCode().');
        }
        return $this->httpCodes[$code];
    }
    /**
     * @default 3
     * @param ParamConfigurator|int $value
     * @return $this
     */
    public function maxRetries($value): static
    {
        $this->_usedProperties['maxRetries'] = \true;
        $this->maxRetries = $value;
        return $this;
    }
    /**
     * Time in ms to delay (or the initial value when multiplier is used)
     * @default 1000
     * @param ParamConfigurator|int $value
     * @return $this
     */
    public function delay($value): static
    {
        $this->_usedProperties['delay'] = \true;
        $this->delay = $value;
        return $this;
    }
    /**
     * If greater than 1, delay will grow exponentially for each retry: delay * (multiple ^ retries)
     * @default 2
     * @param ParamConfigurator|float $value
     * @return $this
     */
    public function multiplier($value): static
    {
        $this->_usedProperties['multiplier'] = \true;
        $this->multiplier = $value;
        return $this;
    }
    /**
     * Max time in ms that a retry should ever be delayed (0 = infinite)
     * @default 0
     * @param ParamConfigurator|int $value
     * @return $this
     */
    public function maxDelay($value): static
    {
        $this->_usedProperties['maxDelay'] = \true;
        $this->maxDelay = $value;
        return $this;
    }
    /**
     * Randomness in percent (between 0 and 1) to apply to the delay
     * @default 0.1
     * @param ParamConfigurator|float $value
     * @return $this
     */
    public function jitter($value): static
    {
        $this->_usedProperties['jitter'] = \true;
        $this->jitter = $value;
        return $this;
    }
    public function __construct(array $value = [])
    {
        if (array_key_exists('enabled', $value)) {
            $this->_usedProperties['enabled'] = \true;
            $this->enabled = $value['enabled'];
            unset($value['enabled']);
        }
        if (array_key_exists('retry_strategy', $value)) {
            $this->_usedProperties['retryStrategy'] = \true;
            $this->retryStrategy = $value['retry_strategy'];
            unset($value['retry_strategy']);
        }
        if (array_key_exists('http_codes', $value)) {
            $this->_usedProperties['httpCodes'] = \true;
            $this->httpCodes = array_map(fn($v) => \is_array($v) ? new \_ContaoManager\Symfony\Config\Framework\HttpClient\ScopedClientConfig\RetryFailed\HttpCodeConfig($v) : $v, $value['http_codes']);
            unset($value['http_codes']);
        }
        if (array_key_exists('max_retries', $value)) {
            $this->_usedProperties['maxRetries'] = \true;
            $this->maxRetries = $value['max_retries'];
            unset($value['max_retries']);
        }
        if (array_key_exists('delay', $value)) {
            $this->_usedProperties['delay'] = \true;
            $this->delay = $value['delay'];
            unset($value['delay']);
        }
        if (array_key_exists('multiplier', $value)) {
            $this->_usedProperties['multiplier'] = \true;
            $this->multiplier = $value['multiplier'];
            unset($value['multiplier']);
        }
        if (array_key_exists('max_delay', $value)) {
            $this->_usedProperties['maxDelay'] = \true;
            $this->maxDelay = $value['max_delay'];
            unset($value['max_delay']);
        }
        if (array_key_exists('jitter', $value)) {
            $this->_usedProperties['jitter'] = \true;
            $this->jitter = $value['jitter'];
            unset($value['jitter']);
        }
        if ([] !== $value) {
            throw new InvalidConfigurationException(sprintf('The following keys are not supported by "%s": ', __CLASS__) . implode(', ', array_keys($value)));
        }
    }
    public function toArray(): array
    {
        $output = [];
        if (isset($this->_usedProperties['enabled'])) {
            $output['enabled'] = $this->enabled;
        }
        if (isset($this->_usedProperties['retryStrategy'])) {
            $output['retry_strategy'] = $this->retryStrategy;
        }
        if (isset($this->_usedProperties['httpCodes'])) {
            $output['http_codes'] = array_map(fn($v) => $v instanceof \_ContaoManager\Symfony\Config\Framework\HttpClient\ScopedClientConfig\RetryFailed\HttpCodeConfig ? $v->toArray() : $v, $this->httpCodes);
        }
        if (isset($this->_usedProperties['maxRetries'])) {
            $output['max_retries'] = $this->maxRetries;
        }
        if (isset($this->_usedProperties['delay'])) {
            $output['delay'] = $this->delay;
        }
        if (isset($this->_usedProperties['multiplier'])) {
            $output['multiplier'] = $this->multiplier;
        }
        if (isset($this->_usedProperties['maxDelay'])) {
            $output['max_delay'] = $this->maxDelay;
        }
        if (isset($this->_usedProperties['jitter'])) {
            $output['jitter'] = $this->jitter;
        }
        return $output;
    }
}
<?php

namespace _ContaoManager\Symfony\Config\Framework\HttpClient;

require_once __DIR__ . \DIRECTORY_SEPARATOR . 'ScopedClientConfig' . \DIRECTORY_SEPARATOR . 'PeerFingerprintConfig.php';
require_once __DIR__ . \DIRECTORY_SEPARATOR . 'ScopedClientConfig' . \DIRECTORY_SEPARATOR . 'RetryFailedConfig.php';
use _ContaoManager\Symfony\Component\Config\Loader\ParamConfigurator;
use _ContaoManager\Symfony\Component\Config\Definition\Exception\InvalidConfigurationException;
/**
 * This class is automatically generated to help in creating a config.
 */
class ScopedClientConfig
{
    private $scope;
    private $baseUri;
    private $authBasic;
    private $authBearer;
    private $authNtlm;
    private $query;
    private $headers;
    private $maxRedirects;
    private $httpVersion;
    private $resolve;
    private $proxy;
    private $noProxy;
    private $timeout;
    private $maxDuration;
    private $bindto;
    private $verifyPeer;
    private $verifyHost;
    private $cafile;
    private $capath;
    private $localCert;
    private $localPk;
    private $passphrase;
    private $ciphers;
    private $peerFingerprint;
    private $cryptoMethod;
    private $extra;
    private $retryFailed;
    private $_usedProperties = [];
    /**
     * The regular expression that the request URL must match before adding the other options. When none is provided, the base URI is used instead.
     * @default null
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function scope($value): static
    {
        $this->_usedProperties['scope'] = \true;
        $this->scope = $value;
        return $this;
    }
    /**
     * The URI to resolve relative URLs, following rules in RFC 3985, section 2.
     * @default null
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function baseUri($value): static
    {
        $this->_usedProperties['baseUri'] = \true;
        $this->baseUri = $value;
        return $this;
    }
    /**
     * An HTTP Basic authentication "username:password".
     * @default null
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function authBasic($value): static
    {
        $this->_usedProperties['authBasic'] = \true;
        $this->authBasic = $value;
        return $this;
    }
    /**
     * A token enabling HTTP Bearer authorization.
     * @default null
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function authBearer($value): static
    {
        $this->_usedProperties['authBearer'] = \true;
        $this->authBearer = $value;
        return $this;
    }
    /**
     * A "username:password" pair to use Microsoft NTLM authentication (requires the cURL extension).
     * @default null
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function authNtlm($value): static
    {
        $this->_usedProperties['authNtlm'] = \true;
        $this->authNtlm = $value;
        return $this;
    }
    /**
     * @return $this
     */
    public function query(string $key, mixed $value): static
    {
        $this->_usedProperties['query'] = \true;
        $this->query[$key] = $value;
        return $this;
    }
    /**
     * @return $this
     */
    public function header(string $name, mixed $value): static
    {
        $this->_usedProperties['headers'] = \true;
        $this->headers[$name] = $value;
        return $this;
    }
    /**
     * The maximum number of redirects to follow.
     * @default null
     * @param ParamConfigurator|int $value
     * @return $this
     */
    public function maxRedirects($value): static
    {
        $this->_usedProperties['maxRedirects'] = \true;
        $this->maxRedirects = $value;
        return $this;
    }
    /**
     * The default HTTP version, typically 1.1 or 2.0, leave to null for the best version.
     * @default null
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function httpVersion($value): static
    {
        $this->_usedProperties['httpVersion'] = \true;
        $this->httpVersion = $value;
        return $this;
    }
    /**
     * @return $this
     */
    public function resolve(string $host, mixed $value): static
    {
        $this->_usedProperties['resolve'] = \true;
        $this->resolve[$host] = $value;
        return $this;
    }
    /**
     * The URL of the proxy to pass requests through or null for automatic detection.
     * @default null
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function proxy($value): static
    {
        $this->_usedProperties['proxy'] = \true;
        $this->proxy = $value;
        return $this;
    }
    /**
     * A comma separated list of hosts that do not require a proxy to be reached.
     * @default null
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function noProxy($value): static
    {
        $this->_usedProperties['noProxy'] = \true;
        $this->noProxy = $value;
        return $this;
    }
    /**
     * The idle timeout, defaults to the "default_socket_timeout" ini parameter.
     * @default null
     * @param ParamConfigurator|float $value
     * @return $this
     */
    public function timeout($value): static
    {
        $this->_usedProperties['timeout'] = \true;
        $this->timeout = $value;
        return $this;
    }
    /**
     * The maximum execution time for the request+response as a whole.
     * @default null
     * @param ParamConfigurator|float $value
     * @return $this
     */
    public function maxDuration($value): static
    {
        $this->_usedProperties['maxDuration'] = \true;
        $this->maxDuration = $value;
        return $this;
    }
    /**
     * A network interface name, IP address, a host name or a UNIX socket to bind to.
     * @default null
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function bindto($value): static
    {
        $this->_usedProperties['bindto'] = \true;
        $this->bindto = $value;
        return $this;
    }
    /**
     * Indicates if the peer should be verified in a TLS context.
     * @default null
     * @param ParamConfigurator|bool $value
     * @return $this
     */
    public function verifyPeer($value): static
    {
        $this->_usedProperties['verifyPeer'] = \true;
        $this->verifyPeer = $value;
        return $this;
    }
    /**
     * Indicates if the host should exist as a certificate common name.
     * @default null
     * @param ParamConfigurator|bool $value
     * @return $this
     */
    public function verifyHost($value): static
    {
        $this->_usedProperties['verifyHost'] = \true;
        $this->verifyHost = $value;
        return $this;
    }
    /**
     * A certificate authority file.
     * @default null
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function cafile($value): static
    {
        $this->_usedProperties['cafile'] = \true;
        $this->cafile = $value;
        return $this;
    }
    /**
     * A directory that contains multiple certificate authority files.
     * @default null
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function capath($value): static
    {
        $this->_usedProperties['capath'] = \true;
        $this->capath = $value;
        return $this;
    }
    /**
     * A PEM formatted certificate file.
     * @default null
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function localCert($value): static
    {
        $this->_usedProperties['localCert'] = \true;
        $this->localCert = $value;
        return $this;
    }
    /**
     * A private key file.
     * @default null
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function localPk($value): static
    {
        $this->_usedProperties['localPk'] = \true;
        $this->localPk = $value;
        return $this;
    }
    /**
     * The passphrase used to encrypt the "local_pk" file.
     * @default null
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function passphrase($value): static
    {
        $this->_usedProperties['passphrase'] = \true;
        $this->passphrase = $value;
        return $this;
    }
    /**
     * A list of TLS ciphers separated by colons, commas or spaces (e.g. "RC3-SHA:TLS13-AES-128-GCM-SHA256"...)
     * @default null
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function ciphers($value): static
    {
        $this->_usedProperties['ciphers'] = \true;
        $this->ciphers = $value;
        return $this;
    }
    /**
     * Associative array: hashing algorithm => hash(es).
     */
    public function peerFingerprint(array $value = []): \_ContaoManager\Symfony\Config\Framework\HttpClient\ScopedClientConfig\PeerFingerprintConfig
    {
        if (null === $this->peerFingerprint) {
            $this->_usedProperties['peerFingerprint'] = \true;
            $this->peerFingerprint = new \_ContaoManager\Symfony\Config\Framework\HttpClient\ScopedClientConfig\PeerFingerprintConfig($value);
        } elseif (0 < \func_num_args()) {
            throw new InvalidConfigurationException('The node created by "peerFingerprint()" has already been initialized. You cannot pass values the second time you call peerFingerprint().');
        }
        return $this->peerFingerprint;
    }
    /**
     * The minimum version of TLS to accept; must be one of STREAM_CRYPTO_METHOD_TLSv*_CLIENT constants.
     * @default null
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function cryptoMethod($value): static
    {
        $this->_usedProperties['cryptoMethod'] = \true;
        $this->cryptoMethod = $value;
        return $this;
    }
    /**
     * @return $this
     */
    public function extra(string $name, mixed $value): static
    {
        $this->_usedProperties['extra'] = \true;
        $this->extra[$name] = $value;
        return $this;
    }
    /**
     * @template TValue of mixed
     * @param TValue $value
     * @default {"enabled":false,"retry_strategy":null,"http_codes":[],"max_retries":3,"delay":1000,"multiplier":2,"max_delay":0,"jitter":0.1}
     * @return \Symfony\Config\Framework\HttpClient\ScopedClientConfig\RetryFailedConfig|$this
     * @psalm-return (TValue is array ? \Symfony\Config\Framework\HttpClient\ScopedClientConfig\RetryFailedConfig : static)
     */
    public function retryFailed(mixed $value = []): \_ContaoManager\Symfony\Config\Framework\HttpClient\ScopedClientConfig\RetryFailedConfig|static
    {
        if (!\is_array($value)) {
            $this->_usedProperties['retryFailed'] = \true;
            $this->retryFailed = $value;
            return $this;
        }
        if (!$this->retryFailed instanceof \_ContaoManager\Symfony\Config\Framework\HttpClient\ScopedClientConfig\RetryFailedConfig) {
            $this->_usedProperties['retryFailed'] = \true;
            $this->retryFailed = new \_ContaoManager\Symfony\Config\Framework\HttpClient\ScopedClientConfig\RetryFailedConfig($value);
        } elseif (0 < \func_num_args()) {
            throw new InvalidConfigurationException('The node created by "retryFailed()" has already been initialized. You cannot pass values the second time you call retryFailed().');
        }
        return $this->retryFailed;
    }
    public function __construct(array $value = [])
    {
        if (array_key_exists('scope', $value)) {
            $this->_usedProperties['scope'] = \true;
            $this->scope = $value['scope'];
            unset($value['scope']);
        }
        if (array_key_exists('base_uri', $value)) {
            $this->_usedProperties['baseUri'] = \true;
            $this->baseUri = $value['base_uri'];
            unset($value['base_uri']);
        }
        if (array_key_exists('auth_basic', $value)) {
            $this->_usedProperties['authBasic'] = \true;
            $this->authBasic = $value['auth_basic'];
            unset($value['auth_basic']);
        }
        if (array_key_exists('auth_bearer', $value)) {
            $this->_usedProperties['authBearer'] = \true;
            $this->authBearer = $value['auth_bearer'];
            unset($value['auth_bearer']);
        }
        if (array_key_exists('auth_ntlm', $value)) {
            $this->_usedProperties['authNtlm'] = \true;
            $this->authNtlm = $value['auth_ntlm'];
            unset($value['auth_ntlm']);
        }
        if (array_key_exists('query', $value)) {
            $this->_usedProperties['query'] = \true;
            $this->query = $value['query'];
            unset($value['query']);
        }
        if (array_key_exists('headers', $value)) {
            $this->_usedProperties['headers'] = \true;
            $this->headers = $value['headers'];
            unset($value['headers']);
        }
        if (array_key_exists('max_redirects', $value)) {
            $this->_usedProperties['maxRedirects'] = \true;
            $this->maxRedirects = $value['max_redirects'];
            unset($value['max_redirects']);
        }
        if (array_key_exists('http_version', $value)) {
            $this->_usedProperties['httpVersion'] = \true;
            $this->httpVersion = $value['http_version'];
            unset($value['http_version']);
        }
        if (array_key_exists('resolve', $value)) {
            $this->_usedProperties['resolve'] = \true;
            $this->resolve = $value['resolve'];
            unset($value['resolve']);
        }
        if (array_key_exists('proxy', $value)) {
            $this->_usedProperties['proxy'] = \true;
            $this->proxy = $value['proxy'];
            unset($value['proxy']);
        }
        if (array_key_exists('no_proxy', $value)) {
            $this->_usedProperties['noProxy'] = \true;
            $this->noProxy = $value['no_proxy'];
            unset($value['no_proxy']);
        }
        if (array_key_exists('timeout', $value)) {
            $this->_usedProperties['timeout'] = \true;
            $this->timeout = $value['timeout'];
            unset($value['timeout']);
        }
        if (array_key_exists('max_duration', $value)) {
            $this->_usedProperties['maxDuration'] = \true;
            $this->maxDuration = $value['max_duration'];
            unset($value['max_duration']);
        }
        if (array_key_exists('bindto', $value)) {
            $this->_usedProperties['bindto'] = \true;
            $this->bindto = $value['bindto'];
            unset($value['bindto']);
        }
        if (array_key_exists('verify_peer', $value)) {
            $this->_usedProperties['verifyPeer'] = \true;
            $this->verifyPeer = $value['verify_peer'];
            unset($value['verify_peer']);
        }
        if (array_key_exists('verify_host', $value)) {
            $this->_usedProperties['verifyHost'] = \true;
            $this->verifyHost = $value['verify_host'];
            unset($value['verify_host']);
        }
        if (array_key_exists('cafile', $value)) {
            $this->_usedProperties['cafile'] = \true;
            $this->cafile = $value['cafile'];
            unset($value['cafile']);
        }
        if (array_key_exists('capath', $value)) {
            $this->_usedProperties['capath'] = \true;
            $this->capath = $value['capath'];
            unset($value['capath']);
        }
        if (array_key_exists('local_cert', $value)) {
            $this->_usedProperties['localCert'] = \true;
            $this->localCert = $value['local_cert'];
            unset($value['local_cert']);
        }
        if (array_key_exists('local_pk', $value)) {
            $this->_usedProperties['localPk'] = \true;
            $this->localPk = $value['local_pk'];
            unset($value['local_pk']);
        }
        if (array_key_exists('passphrase', $value)) {
            $this->_usedProperties['passphrase'] = \true;
            $this->passphrase = $value['passphrase'];
            unset($value['passphrase']);
        }
        if (array_key_exists('ciphers', $value)) {
            $this->_usedProperties['ciphers'] = \true;
            $this->ciphers = $value['ciphers'];
            unset($value['ciphers']);
        }
        if (array_key_exists('peer_fingerprint', $value)) {
            $this->_usedProperties['peerFingerprint'] = \true;
            $this->peerFingerprint = new \_ContaoManager\Symfony\Config\Framework\HttpClient\ScopedClientConfig\PeerFingerprintConfig($value['peer_fingerprint']);
            unset($value['peer_fingerprint']);
        }
        if (array_key_exists('crypto_method', $value)) {
            $this->_usedProperties['cryptoMethod'] = \true;
            $this->cryptoMethod = $value['crypto_method'];
            unset($value['crypto_method']);
        }
        if (array_key_exists('extra', $value)) {
            $this->_usedProperties['extra'] = \true;
            $this->extra = $value['extra'];
            unset($value['extra']);
        }
        if (array_key_exists('retry_failed', $value)) {
            $this->_usedProperties['retryFailed'] = \true;
            $this->retryFailed = \is_array($value['retry_failed']) ? new \_ContaoManager\Symfony\Config\Framework\HttpClient\ScopedClientConfig\RetryFailedConfig($value['retry_failed']) : $value['retry_failed'];
            unset($value['retry_failed']);
        }
        if ([] !== $value) {
            throw new InvalidConfigurationException(sprintf('The following keys are not supported by "%s": ', __CLASS__) . implode(', ', array_keys($value)));
        }
    }
    public function toArray(): array
    {
        $output = [];
        if (isset($this->_usedProperties['scope'])) {
            $output['scope'] = $this->scope;
        }
        if (isset($this->_usedProperties['baseUri'])) {
            $output['base_uri'] = $this->baseUri;
        }
        if (isset($this->_usedProperties['authBasic'])) {
            $output['auth_basic'] = $this->authBasic;
        }
        if (isset($this->_usedProperties['authBearer'])) {
            $output['auth_bearer'] = $this->authBearer;
        }
        if (isset($this->_usedProperties['authNtlm'])) {
            $output['auth_ntlm'] = $this->authNtlm;
        }
        if (isset($this->_usedProperties['query'])) {
            $output['query'] = $this->query;
        }
        if (isset($this->_usedProperties['headers'])) {
            $output['headers'] = $this->headers;
        }
        if (isset($this->_usedProperties['maxRedirects'])) {
            $output['max_redirects'] = $this->maxRedirects;
        }
        if (isset($this->_usedProperties['httpVersion'])) {
            $output['http_version'] = $this->httpVersion;
        }
        if (isset($this->_usedProperties['resolve'])) {
            $output['resolve'] = $this->resolve;
        }
        if (isset($this->_usedProperties['proxy'])) {
            $output['proxy'] = $this->proxy;
        }
        if (isset($this->_usedProperties['noProxy'])) {
            $output['no_proxy'] = $this->noProxy;
        }
        if (isset($this->_usedProperties['timeout'])) {
            $output['timeout'] = $this->timeout;
        }
        if (isset($this->_usedProperties['maxDuration'])) {
            $output['max_duration'] = $this->maxDuration;
        }
        if (isset($this->_usedProperties['bindto'])) {
            $output['bindto'] = $this->bindto;
        }
        if (isset($this->_usedProperties['verifyPeer'])) {
            $output['verify_peer'] = $this->verifyPeer;
        }
        if (isset($this->_usedProperties['verifyHost'])) {
            $output['verify_host'] = $this->verifyHost;
        }
        if (isset($this->_usedProperties['cafile'])) {
            $output['cafile'] = $this->cafile;
        }
        if (isset($this->_usedProperties['capath'])) {
            $output['capath'] = $this->capath;
        }
        if (isset($this->_usedProperties['localCert'])) {
            $output['local_cert'] = $this->localCert;
        }
        if (isset($this->_usedProperties['localPk'])) {
            $output['local_pk'] = $this->localPk;
        }
        if (isset($this->_usedProperties['passphrase'])) {
            $output['passphrase'] = $this->passphrase;
        }
        if (isset($this->_usedProperties['ciphers'])) {
            $output['ciphers'] = $this->ciphers;
        }
        if (isset($this->_usedProperties['peerFingerprint'])) {
            $output['peer_fingerprint'] = $this->peerFingerprint->toArray();
        }
        if (isset($this->_usedProperties['cryptoMethod'])) {
            $output['crypto_method'] = $this->cryptoMethod;
        }
        if (isset($this->_usedProperties['extra'])) {
            $output['extra'] = $this->extra;
        }
        if (isset($this->_usedProperties['retryFailed'])) {
            $output['retry_failed'] = $this->retryFailed instanceof \_ContaoManager\Symfony\Config\Framework\HttpClient\ScopedClientConfig\RetryFailedConfig ? $this->retryFailed->toArray() : $this->retryFailed;
        }
        return $output;
    }
}
<?php

namespace _ContaoManager\Symfony\Config\Framework\HttpClient\DefaultOptions\RetryFailed;

use _ContaoManager\Symfony\Component\Config\Loader\ParamConfigurator;
use _ContaoManager\Symfony\Component\Config\Definition\Exception\InvalidConfigurationException;
/**
 * This class is automatically generated to help in creating a config.
 */
class HttpCodeConfig
{
    private $code;
    private $methods;
    private $_usedProperties = [];
    /**
     * @default null
     * @param ParamConfigurator|int $value
     * @return $this
     */
    public function code($value): static
    {
        $this->_usedProperties['code'] = \true;
        $this->code = $value;
        return $this;
    }
    /**
     * @param ParamConfigurator|list<ParamConfigurator|mixed> $value
     *
     * @return $this
     */
    public function methods(ParamConfigurator|array $value): static
    {
        $this->_usedProperties['methods'] = \true;
        $this->methods = $value;
        return $this;
    }
    public function __construct(array $value = [])
    {
        if (array_key_exists('code', $value)) {
            $this->_usedProperties['code'] = \true;
            $this->code = $value['code'];
            unset($value['code']);
        }
        if (array_key_exists('methods', $value)) {
            $this->_usedProperties['methods'] = \true;
            $this->methods = $value['methods'];
            unset($value['methods']);
        }
        if ([] !== $value) {
            throw new InvalidConfigurationException(sprintf('The following keys are not supported by "%s": ', __CLASS__) . implode(', ', array_keys($value)));
        }
    }
    public function toArray(): array
    {
        $output = [];
        if (isset($this->_usedProperties['code'])) {
            $output['code'] = $this->code;
        }
        if (isset($this->_usedProperties['methods'])) {
            $output['methods'] = $this->methods;
        }
        return $output;
    }
}
<?php

namespace _ContaoManager\Symfony\Config\Framework\HttpClient\DefaultOptions;

use _ContaoManager\Symfony\Component\Config\Loader\ParamConfigurator;
use _ContaoManager\Symfony\Component\Config\Definition\Exception\InvalidConfigurationException;
/**
 * This class is automatically generated to help in creating a config.
 */
class PeerFingerprintConfig
{
    private $sha1;
    private $pinsha256;
    private $md5;
    private $_usedProperties = [];
    /**
     * @default null
     * @param ParamConfigurator|mixed $value
     *
     * @return $this
     */
    public function sha1(mixed $value): static
    {
        $this->_usedProperties['sha1'] = \true;
        $this->sha1 = $value;
        return $this;
    }
    /**
     * @default null
     * @param ParamConfigurator|mixed $value
     *
     * @return $this
     */
    public function pinsha256(mixed $value): static
    {
        $this->_usedProperties['pinsha256'] = \true;
        $this->pinsha256 = $value;
        return $this;
    }
    /**
     * @default null
     * @param ParamConfigurator|mixed $value
     *
     * @return $this
     */
    public function md5(mixed $value): static
    {
        $this->_usedProperties['md5'] = \true;
        $this->md5 = $value;
        return $this;
    }
    public function __construct(array $value = [])
    {
        if (array_key_exists('sha1', $value)) {
            $this->_usedProperties['sha1'] = \true;
            $this->sha1 = $value['sha1'];
            unset($value['sha1']);
        }
        if (array_key_exists('pin-sha256', $value)) {
            $this->_usedProperties['pinsha256'] = \true;
            $this->pinsha256 = $value['pin-sha256'];
            unset($value['pin-sha256']);
        }
        if (array_key_exists('md5', $value)) {
            $this->_usedProperties['md5'] = \true;
            $this->md5 = $value['md5'];
            unset($value['md5']);
        }
        if ([] !== $value) {
            throw new InvalidConfigurationException(sprintf('The following keys are not supported by "%s": ', __CLASS__) . implode(', ', array_keys($value)));
        }
    }
    public function toArray(): array
    {
        $output = [];
        if (isset($this->_usedProperties['sha1'])) {
            $output['sha1'] = $this->sha1;
        }
        if (isset($this->_usedProperties['pinsha256'])) {
            $output['pin-sha256'] = $this->pinsha256;
        }
        if (isset($this->_usedProperties['md5'])) {
            $output['md5'] = $this->md5;
        }
        return $output;
    }
}
<?php

namespace _ContaoManager\Symfony\Config\Framework\HttpClient\DefaultOptions;

require_once __DIR__ . \DIRECTORY_SEPARATOR . 'RetryFailed' . \DIRECTORY_SEPARATOR . 'HttpCodeConfig.php';
use _ContaoManager\Symfony\Component\Config\Loader\ParamConfigurator;
use _ContaoManager\Symfony\Component\Config\Definition\Exception\InvalidConfigurationException;
/**
 * This class is automatically generated to help in creating a config.
 */
class RetryFailedConfig
{
    private $enabled;
    private $retryStrategy;
    private $httpCodes;
    private $maxRetries;
    private $delay;
    private $multiplier;
    private $maxDelay;
    private $jitter;
    private $_usedProperties = [];
    /**
     * @default false
     * @param ParamConfigurator|bool $value
     * @return $this
     */
    public function enabled($value): static
    {
        $this->_usedProperties['enabled'] = \true;
        $this->enabled = $value;
        return $this;
    }
    /**
     * service id to override the retry strategy
     * @default null
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function retryStrategy($value): static
    {
        $this->_usedProperties['retryStrategy'] = \true;
        $this->retryStrategy = $value;
        return $this;
    }
    /**
     * A list of HTTP status code that triggers a retry
     */
    public function httpCode(string $code, array $value = []): \_ContaoManager\Symfony\Config\Framework\HttpClient\DefaultOptions\RetryFailed\HttpCodeConfig
    {
        if (!isset($this->httpCodes[$code])) {
            $this->_usedProperties['httpCodes'] = \true;
            $this->httpCodes[$code] = new \_ContaoManager\Symfony\Config\Framework\HttpClient\DefaultOptions\RetryFailed\HttpCodeConfig($value);
        } elseif (1 < \func_num_args()) {
            throw new InvalidConfigurationException('The node created by "httpCode()" has already been initialized. You cannot pass values the second time you call httpCode().');
        }
        return $this->httpCodes[$code];
    }
    /**
     * @default 3
     * @param ParamConfigurator|int $value
     * @return $this
     */
    public function maxRetries($value): static
    {
        $this->_usedProperties['maxRetries'] = \true;
        $this->maxRetries = $value;
        return $this;
    }
    /**
     * Time in ms to delay (or the initial value when multiplier is used)
     * @default 1000
     * @param ParamConfigurator|int $value
     * @return $this
     */
    public function delay($value): static
    {
        $this->_usedProperties['delay'] = \true;
        $this->delay = $value;
        return $this;
    }
    /**
     * If greater than 1, delay will grow exponentially for each retry: delay * (multiple ^ retries)
     * @default 2
     * @param ParamConfigurator|float $value
     * @return $this
     */
    public function multiplier($value): static
    {
        $this->_usedProperties['multiplier'] = \true;
        $this->multiplier = $value;
        return $this;
    }
    /**
     * Max time in ms that a retry should ever be delayed (0 = infinite)
     * @default 0
     * @param ParamConfigurator|int $value
     * @return $this
     */
    public function maxDelay($value): static
    {
        $this->_usedProperties['maxDelay'] = \true;
        $this->maxDelay = $value;
        return $this;
    }
    /**
     * Randomness in percent (between 0 and 1) to apply to the delay
     * @default 0.1
     * @param ParamConfigurator|float $value
     * @return $this
     */
    public function jitter($value): static
    {
        $this->_usedProperties['jitter'] = \true;
        $this->jitter = $value;
        return $this;
    }
    public function __construct(array $value = [])
    {
        if (array_key_exists('enabled', $value)) {
            $this->_usedProperties['enabled'] = \true;
            $this->enabled = $value['enabled'];
            unset($value['enabled']);
        }
        if (array_key_exists('retry_strategy', $value)) {
            $this->_usedProperties['retryStrategy'] = \true;
            $this->retryStrategy = $value['retry_strategy'];
            unset($value['retry_strategy']);
        }
        if (array_key_exists('http_codes', $value)) {
            $this->_usedProperties['httpCodes'] = \true;
            $this->httpCodes = array_map(fn($v) => \is_array($v) ? new \_ContaoManager\Symfony\Config\Framework\HttpClient\DefaultOptions\RetryFailed\HttpCodeConfig($v) : $v, $value['http_codes']);
            unset($value['http_codes']);
        }
        if (array_key_exists('max_retries', $value)) {
            $this->_usedProperties['maxRetries'] = \true;
            $this->maxRetries = $value['max_retries'];
            unset($value['max_retries']);
        }
        if (array_key_exists('delay', $value)) {
            $this->_usedProperties['delay'] = \true;
            $this->delay = $value['delay'];
            unset($value['delay']);
        }
        if (array_key_exists('multiplier', $value)) {
            $this->_usedProperties['multiplier'] = \true;
            $this->multiplier = $value['multiplier'];
            unset($value['multiplier']);
        }
        if (array_key_exists('max_delay', $value)) {
            $this->_usedProperties['maxDelay'] = \true;
            $this->maxDelay = $value['max_delay'];
            unset($value['max_delay']);
        }
        if (array_key_exists('jitter', $value)) {
            $this->_usedProperties['jitter'] = \true;
            $this->jitter = $value['jitter'];
            unset($value['jitter']);
        }
        if ([] !== $value) {
            throw new InvalidConfigurationException(sprintf('The following keys are not supported by "%s": ', __CLASS__) . implode(', ', array_keys($value)));
        }
    }
    public function toArray(): array
    {
        $output = [];
        if (isset($this->_usedProperties['enabled'])) {
            $output['enabled'] = $this->enabled;
        }
        if (isset($this->_usedProperties['retryStrategy'])) {
            $output['retry_strategy'] = $this->retryStrategy;
        }
        if (isset($this->_usedProperties['httpCodes'])) {
            $output['http_codes'] = array_map(fn($v) => $v instanceof \_ContaoManager\Symfony\Config\Framework\HttpClient\DefaultOptions\RetryFailed\HttpCodeConfig ? $v->toArray() : $v, $this->httpCodes);
        }
        if (isset($this->_usedProperties['maxRetries'])) {
            $output['max_retries'] = $this->maxRetries;
        }
        if (isset($this->_usedProperties['delay'])) {
            $output['delay'] = $this->delay;
        }
        if (isset($this->_usedProperties['multiplier'])) {
            $output['multiplier'] = $this->multiplier;
        }
        if (isset($this->_usedProperties['maxDelay'])) {
            $output['max_delay'] = $this->maxDelay;
        }
        if (isset($this->_usedProperties['jitter'])) {
            $output['jitter'] = $this->jitter;
        }
        return $output;
    }
}
<?php

namespace _ContaoManager\Symfony\Config\Framework\Serializer;

use _ContaoManager\Symfony\Component\Config\Loader\ParamConfigurator;
use _ContaoManager\Symfony\Component\Config\Definition\Exception\InvalidConfigurationException;
/**
 * This class is automatically generated to help in creating a config.
 */
class MappingConfig
{
    private $paths;
    private $_usedProperties = [];
    /**
     * @param ParamConfigurator|list<ParamConfigurator|mixed> $value
     *
     * @return $this
     */
    public function paths(ParamConfigurator|array $value): static
    {
        $this->_usedProperties['paths'] = \true;
        $this->paths = $value;
        return $this;
    }
    public function __construct(array $value = [])
    {
        if (array_key_exists('paths', $value)) {
            $this->_usedProperties['paths'] = \true;
            $this->paths = $value['paths'];
            unset($value['paths']);
        }
        if ([] !== $value) {
            throw new InvalidConfigurationException(sprintf('The following keys are not supported by "%s": ', __CLASS__) . implode(', ', array_keys($value)));
        }
    }
    public function toArray(): array
    {
        $output = [];
        if (isset($this->_usedProperties['paths'])) {
            $output['paths'] = $this->paths;
        }
        return $output;
    }
}
<?php

namespace _ContaoManager\Symfony\Config\Framework;

require_once __DIR__ . \DIRECTORY_SEPARATOR . 'Validation' . \DIRECTORY_SEPARATOR . 'MappingConfig.php';
require_once __DIR__ . \DIRECTORY_SEPARATOR . 'Validation' . \DIRECTORY_SEPARATOR . 'NotCompromisedPasswordConfig.php';
require_once __DIR__ . \DIRECTORY_SEPARATOR . 'Validation' . \DIRECTORY_SEPARATOR . 'AutoMappingConfig.php';
use _ContaoManager\Symfony\Component\Config\Loader\ParamConfigurator;
use _ContaoManager\Symfony\Component\Config\Definition\Exception\InvalidConfigurationException;
/**
 * This class is automatically generated to help in creating a config.
 */
class ValidationConfig
{
    private $enabled;
    private $cache;
    private $enableAnnotations;
    private $enableAttributes;
    private $staticMethod;
    private $translationDomain;
    private $emailValidationMode;
    private $mapping;
    private $notCompromisedPassword;
    private $autoMapping;
    private $_usedProperties = [];
    /**
     * @default false
     * @param ParamConfigurator|bool $value
     * @return $this
     */
    public function enabled($value): static
    {
        $this->_usedProperties['enabled'] = \true;
        $this->enabled = $value;
        return $this;
    }
    /**
     * @default null
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function cache($value): static
    {
        $this->_usedProperties['cache'] = \true;
        $this->cache = $value;
        return $this;
    }
    /**
     * @default null
     * @param ParamConfigurator|bool $value
     * @return $this
     */
    public function enableAnnotations($value): static
    {
        $this->_usedProperties['enableAnnotations'] = \true;
        $this->enableAnnotations = $value;
        return $this;
    }
    /**
     * @default true
     * @param ParamConfigurator|bool $value
     * @return $this
     */
    public function enableAttributes($value): static
    {
        $this->_usedProperties['enableAttributes'] = \true;
        $this->enableAttributes = $value;
        return $this;
    }
    /**
     * @param ParamConfigurator|list<ParamConfigurator|mixed> $value
     *
     * @return $this
     */
    public function staticMethod(ParamConfigurator|array $value): static
    {
        $this->_usedProperties['staticMethod'] = \true;
        $this->staticMethod = $value;
        return $this;
    }
    /**
     * @default 'validators'
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function translationDomain($value): static
    {
        $this->_usedProperties['translationDomain'] = \true;
        $this->translationDomain = $value;
        return $this;
    }
    /**
     * @default null
     * @param ParamConfigurator|'html5'|'html5-allow-no-tld'|'strict'|'loose' $value
     * @return $this
     */
    public function emailValidationMode($value): static
    {
        $this->_usedProperties['emailValidationMode'] = \true;
        $this->emailValidationMode = $value;
        return $this;
    }
    /**
     * @default {"paths":[]}
     */
    public function mapping(array $value = []): \_ContaoManager\Symfony\Config\Framework\Validation\MappingConfig
    {
        if (null === $this->mapping) {
            $this->_usedProperties['mapping'] = \true;
            $this->mapping = new \_ContaoManager\Symfony\Config\Framework\Validation\MappingConfig($value);
        } elseif (0 < \func_num_args()) {
            throw new InvalidConfigurationException('The node created by "mapping()" has already been initialized. You cannot pass values the second time you call mapping().');
        }
        return $this->mapping;
    }
    /**
     * @default {"enabled":true,"endpoint":null}
     */
    public function notCompromisedPassword(array $value = []): \_ContaoManager\Symfony\Config\Framework\Validation\NotCompromisedPasswordConfig
    {
        if (null === $this->notCompromisedPassword) {
            $this->_usedProperties['notCompromisedPassword'] = \true;
            $this->notCompromisedPassword = new \_ContaoManager\Symfony\Config\Framework\Validation\NotCompromisedPasswordConfig($value);
        } elseif (0 < \func_num_args()) {
            throw new InvalidConfigurationException('The node created by "notCompromisedPassword()" has already been initialized. You cannot pass values the second time you call notCompromisedPassword().');
        }
        return $this->notCompromisedPassword;
    }
    /**
     * A collection of namespaces for which auto-mapping will be enabled by default, or null to opt-in with the EnableAutoMapping constraint.
     * @example []
     * @example ["validator.property_info_loader"]
     */
    public function autoMapping(string $namespace, array $value = []): \_ContaoManager\Symfony\Config\Framework\Validation\AutoMappingConfig
    {
        if (!isset($this->autoMapping[$namespace])) {
            $this->_usedProperties['autoMapping'] = \true;
            $this->autoMapping[$namespace] = new \_ContaoManager\Symfony\Config\Framework\Validation\AutoMappingConfig($value);
        } elseif (1 < \func_num_args()) {
            throw new InvalidConfigurationException('The node created by "autoMapping()" has already been initialized. You cannot pass values the second time you call autoMapping().');
        }
        return $this->autoMapping[$namespace];
    }
    public function __construct(array $value = [])
    {
        if (array_key_exists('enabled', $value)) {
            $this->_usedProperties['enabled'] = \true;
            $this->enabled = $value['enabled'];
            unset($value['enabled']);
        }
        if (array_key_exists('cache', $value)) {
            $this->_usedProperties['cache'] = \true;
            $this->cache = $value['cache'];
            unset($value['cache']);
        }
        if (array_key_exists('enable_annotations', $value)) {
            $this->_usedProperties['enableAnnotations'] = \true;
            $this->enableAnnotations = $value['enable_annotations'];
            unset($value['enable_annotations']);
        }
        if (array_key_exists('enable_attributes', $value)) {
            $this->_usedProperties['enableAttributes'] = \true;
            $this->enableAttributes = $value['enable_attributes'];
            unset($value['enable_attributes']);
        }
        if (array_key_exists('static_method', $value)) {
            $this->_usedProperties['staticMethod'] = \true;
            $this->staticMethod = $value['static_method'];
            unset($value['static_method']);
        }
        if (array_key_exists('translation_domain', $value)) {
            $this->_usedProperties['translationDomain'] = \true;
            $this->translationDomain = $value['translation_domain'];
            unset($value['translation_domain']);
        }
        if (array_key_exists('email_validation_mode', $value)) {
            $this->_usedProperties['emailValidationMode'] = \true;
            $this->emailValidationMode = $value['email_validation_mode'];
            unset($value['email_validation_mode']);
        }
        if (array_key_exists('mapping', $value)) {
            $this->_usedProperties['mapping'] = \true;
            $this->mapping = new \_ContaoManager\Symfony\Config\Framework\Validation\MappingConfig($value['mapping']);
            unset($value['mapping']);
        }
        if (array_key_exists('not_compromised_password', $value)) {
            $this->_usedProperties['notCompromisedPassword'] = \true;
            $this->notCompromisedPassword = new \_ContaoManager\Symfony\Config\Framework\Validation\NotCompromisedPasswordConfig($value['not_compromised_password']);
            unset($value['not_compromised_password']);
        }
        if (array_key_exists('auto_mapping', $value)) {
            $this->_usedProperties['autoMapping'] = \true;
            $this->autoMapping = array_map(fn($v) => \is_array($v) ? new \_ContaoManager\Symfony\Config\Framework\Validation\AutoMappingConfig($v) : $v, $value['auto_mapping']);
            unset($value['auto_mapping']);
        }
        if ([] !== $value) {
            throw new InvalidConfigurationException(sprintf('The following keys are not supported by "%s": ', __CLASS__) . implode(', ', array_keys($value)));
        }
    }
    public function toArray(): array
    {
        $output = [];
        if (isset($this->_usedProperties['enabled'])) {
            $output['enabled'] = $this->enabled;
        }
        if (isset($this->_usedProperties['cache'])) {
            $output['cache'] = $this->cache;
        }
        if (isset($this->_usedProperties['enableAnnotations'])) {
            $output['enable_annotations'] = $this->enableAnnotations;
        }
        if (isset($this->_usedProperties['enableAttributes'])) {
            $output['enable_attributes'] = $this->enableAttributes;
        }
        if (isset($this->_usedProperties['staticMethod'])) {
            $output['static_method'] = $this->staticMethod;
        }
        if (isset($this->_usedProperties['translationDomain'])) {
            $output['translation_domain'] = $this->translationDomain;
        }
        if (isset($this->_usedProperties['emailValidationMode'])) {
            $output['email_validation_mode'] = $this->emailValidationMode;
        }
        if (isset($this->_usedProperties['mapping'])) {
            $output['mapping'] = $this->mapping->toArray();
        }
        if (isset($this->_usedProperties['notCompromisedPassword'])) {
            $output['not_compromised_password'] = $this->notCompromisedPassword->toArray();
        }
        if (isset($this->_usedProperties['autoMapping'])) {
            $output['auto_mapping'] = array_map(fn($v) => $v instanceof \_ContaoManager\Symfony\Config\Framework\Validation\AutoMappingConfig ? $v->toArray() : $v, $this->autoMapping);
        }
        return $output;
    }
}
<?php

namespace _ContaoManager\Symfony\Config\Framework;

require_once __DIR__ . \DIRECTORY_SEPARATOR . 'RateLimiter' . \DIRECTORY_SEPARATOR . 'LimiterConfig.php';
use _ContaoManager\Symfony\Component\Config\Loader\ParamConfigurator;
use _ContaoManager\Symfony\Component\Config\Definition\Exception\InvalidConfigurationException;
/**
 * This class is automatically generated to help in creating a config.
 */
class RateLimiterConfig
{
    private $enabled;
    private $limiters;
    private $_usedProperties = [];
    /**
     * @default false
     * @param ParamConfigurator|bool $value
     * @return $this
     */
    public function enabled($value): static
    {
        $this->_usedProperties['enabled'] = \true;
        $this->enabled = $value;
        return $this;
    }
    public function limiter(string $name, array $value = []): \_ContaoManager\Symfony\Config\Framework\RateLimiter\LimiterConfig
    {
        if (!isset($this->limiters[$name])) {
            $this->_usedProperties['limiters'] = \true;
            $this->limiters[$name] = new \_ContaoManager\Symfony\Config\Framework\RateLimiter\LimiterConfig($value);
        } elseif (1 < \func_num_args()) {
            throw new InvalidConfigurationException('The node created by "limiter()" has already been initialized. You cannot pass values the second time you call limiter().');
        }
        return $this->limiters[$name];
    }
    public function __construct(array $value = [])
    {
        if (array_key_exists('enabled', $value)) {
            $this->_usedProperties['enabled'] = \true;
            $this->enabled = $value['enabled'];
            unset($value['enabled']);
        }
        if (array_key_exists('limiters', $value)) {
            $this->_usedProperties['limiters'] = \true;
            $this->limiters = array_map(fn($v) => new \_ContaoManager\Symfony\Config\Framework\RateLimiter\LimiterConfig($v), $value['limiters']);
            unset($value['limiters']);
        }
        if ([] !== $value) {
            throw new InvalidConfigurationException(sprintf('The following keys are not supported by "%s": ', __CLASS__) . implode(', ', array_keys($value)));
        }
    }
    public function toArray(): array
    {
        $output = [];
        if (isset($this->_usedProperties['enabled'])) {
            $output['enabled'] = $this->enabled;
        }
        if (isset($this->_usedProperties['limiters'])) {
            $output['limiters'] = array_map(fn($v) => $v->toArray(), $this->limiters);
        }
        return $output;
    }
}
<?php

namespace _ContaoManager\Symfony\Config\Framework\RateLimiter\LimiterConfig;

use _ContaoManager\Symfony\Component\Config\Loader\ParamConfigurator;
use _ContaoManager\Symfony\Component\Config\Definition\Exception\InvalidConfigurationException;
/**
 * This class is automatically generated to help in creating a config.
 */
class RateConfig
{
    private $interval;
    private $amount;
    private $_usedProperties = [];
    /**
     * Configures the rate interval. The value must be a number followed by "second", "minute", "hour", "day", "week" or "month" (or their plural equivalent).
     * @default null
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function interval($value): static
    {
        $this->_usedProperties['interval'] = \true;
        $this->interval = $value;
        return $this;
    }
    /**
     * Amount of tokens to add each interval
     * @default 1
     * @param ParamConfigurator|int $value
     * @return $this
     */
    public function amount($value): static
    {
        $this->_usedProperties['amount'] = \true;
        $this->amount = $value;
        return $this;
    }
    public function __construct(array $value = [])
    {
        if (array_key_exists('interval', $value)) {
            $this->_usedProperties['interval'] = \true;
            $this->interval = $value['interval'];
            unset($value['interval']);
        }
        if (array_key_exists('amount', $value)) {
            $this->_usedProperties['amount'] = \true;
            $this->amount = $value['amount'];
            unset($value['amount']);
        }
        if ([] !== $value) {
            throw new InvalidConfigurationException(sprintf('The following keys are not supported by "%s": ', __CLASS__) . implode(', ', array_keys($value)));
        }
    }
    public function toArray(): array
    {
        $output = [];
        if (isset($this->_usedProperties['interval'])) {
            $output['interval'] = $this->interval;
        }
        if (isset($this->_usedProperties['amount'])) {
            $output['amount'] = $this->amount;
        }
        return $output;
    }
}
<?php

namespace _ContaoManager\Symfony\Config\Framework\RateLimiter;

require_once __DIR__ . \DIRECTORY_SEPARATOR . 'LimiterConfig' . \DIRECTORY_SEPARATOR . 'RateConfig.php';
use _ContaoManager\Symfony\Component\Config\Loader\ParamConfigurator;
use _ContaoManager\Symfony\Component\Config\Definition\Exception\InvalidConfigurationException;
/**
 * This class is automatically generated to help in creating a config.
 */
class LimiterConfig
{
    private $lockFactory;
    private $cachePool;
    private $storageService;
    private $policy;
    private $limit;
    private $interval;
    private $rate;
    private $_usedProperties = [];
    /**
     * The service ID of the lock factory used by this limiter (or null to disable locking)
     * @default 'lock.factory'
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function lockFactory($value): static
    {
        $this->_usedProperties['lockFactory'] = \true;
        $this->lockFactory = $value;
        return $this;
    }
    /**
     * The cache pool to use for storing the current limiter state
     * @default 'cache.rate_limiter'
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function cachePool($value): static
    {
        $this->_usedProperties['cachePool'] = \true;
        $this->cachePool = $value;
        return $this;
    }
    /**
     * The service ID of a custom storage implementation, this precedes any configured "cache_pool"
     * @default null
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function storageService($value): static
    {
        $this->_usedProperties['storageService'] = \true;
        $this->storageService = $value;
        return $this;
    }
    /**
     * The algorithm to be used by this limiter
     * @default null
     * @param ParamConfigurator|'fixed_window'|'token_bucket'|'sliding_window'|'no_limit' $value
     * @return $this
     */
    public function policy($value): static
    {
        $this->_usedProperties['policy'] = \true;
        $this->policy = $value;
        return $this;
    }
    /**
     * The maximum allowed hits in a fixed interval or burst
     * @default null
     * @param ParamConfigurator|int $value
     * @return $this
     */
    public function limit($value): static
    {
        $this->_usedProperties['limit'] = \true;
        $this->limit = $value;
        return $this;
    }
    /**
     * Configures the fixed interval if "policy" is set to "fixed_window" or "sliding_window". The value must be a number followed by "second", "minute", "hour", "day", "week" or "month" (or their plural equivalent).
     * @default null
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function interval($value): static
    {
        $this->_usedProperties['interval'] = \true;
        $this->interval = $value;
        return $this;
    }
    /**
     * Configures the fill rate if "policy" is set to "token_bucket"
     */
    public function rate(array $value = []): \_ContaoManager\Symfony\Config\Framework\RateLimiter\LimiterConfig\RateConfig
    {
        if (null === $this->rate) {
            $this->_usedProperties['rate'] = \true;
            $this->rate = new \_ContaoManager\Symfony\Config\Framework\RateLimiter\LimiterConfig\RateConfig($value);
        } elseif (0 < \func_num_args()) {
            throw new InvalidConfigurationException('The node created by "rate()" has already been initialized. You cannot pass values the second time you call rate().');
        }
        return $this->rate;
    }
    public function __construct(array $value = [])
    {
        if (array_key_exists('lock_factory', $value)) {
            $this->_usedProperties['lockFactory'] = \true;
            $this->lockFactory = $value['lock_factory'];
            unset($value['lock_factory']);
        }
        if (array_key_exists('cache_pool', $value)) {
            $this->_usedProperties['cachePool'] = \true;
            $this->cachePool = $value['cache_pool'];
            unset($value['cache_pool']);
        }
        if (array_key_exists('storage_service', $value)) {
            $this->_usedProperties['storageService'] = \true;
            $this->storageService = $value['storage_service'];
            unset($value['storage_service']);
        }
        if (array_key_exists('policy', $value)) {
            $this->_usedProperties['policy'] = \true;
            $this->policy = $value['policy'];
            unset($value['policy']);
        }
        if (array_key_exists('limit', $value)) {
            $this->_usedProperties['limit'] = \true;
            $this->limit = $value['limit'];
            unset($value['limit']);
        }
        if (array_key_exists('interval', $value)) {
            $this->_usedProperties['interval'] = \true;
            $this->interval = $value['interval'];
            unset($value['interval']);
        }
        if (array_key_exists('rate', $value)) {
            $this->_usedProperties['rate'] = \true;
            $this->rate = new \_ContaoManager\Symfony\Config\Framework\RateLimiter\LimiterConfig\RateConfig($value['rate']);
            unset($value['rate']);
        }
        if ([] !== $value) {
            throw new InvalidConfigurationException(sprintf('The following keys are not supported by "%s": ', __CLASS__) . implode(', ', array_keys($value)));
        }
    }
    public function toArray(): array
    {
        $output = [];
        if (isset($this->_usedProperties['lockFactory'])) {
            $output['lock_factory'] = $this->lockFactory;
        }
        if (isset($this->_usedProperties['cachePool'])) {
            $output['cache_pool'] = $this->cachePool;
        }
        if (isset($this->_usedProperties['storageService'])) {
            $output['storage_service'] = $this->storageService;
        }
        if (isset($this->_usedProperties['policy'])) {
            $output['policy'] = $this->policy;
        }
        if (isset($this->_usedProperties['limit'])) {
            $output['limit'] = $this->limit;
        }
        if (isset($this->_usedProperties['interval'])) {
            $output['interval'] = $this->interval;
        }
        if (isset($this->_usedProperties['rate'])) {
            $output['rate'] = $this->rate->toArray();
        }
        return $output;
    }
}
<?php

namespace _ContaoManager\Symfony\Config\Framework\Cache;

use _ContaoManager\Symfony\Component\Config\Loader\ParamConfigurator;
use _ContaoManager\Symfony\Component\Config\Definition\Exception\InvalidConfigurationException;
/**
 * This class is automatically generated to help in creating a config.
 */
class PoolConfig
{
    private $adapters;
    private $tags;
    private $public;
    private $defaultLifetime;
    private $provider;
    private $earlyExpirationMessageBus;
    private $clearer;
    private $_usedProperties = [];
    /**
     * @param ParamConfigurator|list<ParamConfigurator|mixed>|mixed $value
     *
     * @return $this
     */
    public function adapters(mixed $value): static
    {
        $this->_usedProperties['adapters'] = \true;
        $this->adapters = $value;
        return $this;
    }
    /**
     * @default null
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function tags($value): static
    {
        $this->_usedProperties['tags'] = \true;
        $this->tags = $value;
        return $this;
    }
    /**
     * @default false
     * @param ParamConfigurator|bool $value
     * @return $this
     */
    public function public($value): static
    {
        $this->_usedProperties['public'] = \true;
        $this->public = $value;
        return $this;
    }
    /**
     * Default lifetime of the pool
     * @example "300" for 5 minutes expressed in seconds, "PT5M" for five minutes expressed as ISO 8601 time interval, or "5 minutes" as a date expression
     * @default null
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function defaultLifetime($value): static
    {
        $this->_usedProperties['defaultLifetime'] = \true;
        $this->defaultLifetime = $value;
        return $this;
    }
    /**
     * Overwrite the setting from the default provider for this adapter.
     * @default null
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function provider($value): static
    {
        $this->_usedProperties['provider'] = \true;
        $this->provider = $value;
        return $this;
    }
    /**
     * @example "messenger.default_bus" to send early expiration events to the default Messenger bus.
     * @default null
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function earlyExpirationMessageBus($value): static
    {
        $this->_usedProperties['earlyExpirationMessageBus'] = \true;
        $this->earlyExpirationMessageBus = $value;
        return $this;
    }
    /**
     * @default null
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function clearer($value): static
    {
        $this->_usedProperties['clearer'] = \true;
        $this->clearer = $value;
        return $this;
    }
    public function __construct(array $value = [])
    {
        if (array_key_exists('adapters', $value)) {
            $this->_usedProperties['adapters'] = \true;
            $this->adapters = $value['adapters'];
            unset($value['adapters']);
        }
        if (array_key_exists('tags', $value)) {
            $this->_usedProperties['tags'] = \true;
            $this->tags = $value['tags'];
            unset($value['tags']);
        }
        if (array_key_exists('public', $value)) {
            $this->_usedProperties['public'] = \true;
            $this->public = $value['public'];
            unset($value['public']);
        }
        if (array_key_exists('default_lifetime', $value)) {
            $this->_usedProperties['defaultLifetime'] = \true;
            $this->defaultLifetime = $value['default_lifetime'];
            unset($value['default_lifetime']);
        }
        if (array_key_exists('provider', $value)) {
            $this->_usedProperties['provider'] = \true;
            $this->provider = $value['provider'];
            unset($value['provider']);
        }
        if (array_key_exists('early_expiration_message_bus', $value)) {
            $this->_usedProperties['earlyExpirationMessageBus'] = \true;
            $this->earlyExpirationMessageBus = $value['early_expiration_message_bus'];
            unset($value['early_expiration_message_bus']);
        }
        if (array_key_exists('clearer', $value)) {
            $this->_usedProperties['clearer'] = \true;
            $this->clearer = $value['clearer'];
            unset($value['clearer']);
        }
        if ([] !== $value) {
            throw new InvalidConfigurationException(sprintf('The following keys are not supported by "%s": ', __CLASS__) . implode(', ', array_keys($value)));
        }
    }
    public function toArray(): array
    {
        $output = [];
        if (isset($this->_usedProperties['adapters'])) {
            $output['adapters'] = $this->adapters;
        }
        if (isset($this->_usedProperties['tags'])) {
            $output['tags'] = $this->tags;
        }
        if (isset($this->_usedProperties['public'])) {
            $output['public'] = $this->public;
        }
        if (isset($this->_usedProperties['defaultLifetime'])) {
            $output['default_lifetime'] = $this->defaultLifetime;
        }
        if (isset($this->_usedProperties['provider'])) {
            $output['provider'] = $this->provider;
        }
        if (isset($this->_usedProperties['earlyExpirationMessageBus'])) {
            $output['early_expiration_message_bus'] = $this->earlyExpirationMessageBus;
        }
        if (isset($this->_usedProperties['clearer'])) {
            $output['clearer'] = $this->clearer;
        }
        return $output;
    }
}
<?php

namespace _ContaoManager\Symfony\Config\Framework;

require_once __DIR__ . \DIRECTORY_SEPARATOR . 'Serializer' . \DIRECTORY_SEPARATOR . 'MappingConfig.php';
use _ContaoManager\Symfony\Component\Config\Loader\ParamConfigurator;
use _ContaoManager\Symfony\Component\Config\Definition\Exception\InvalidConfigurationException;
/**
 * This class is automatically generated to help in creating a config.
 */
class SerializerConfig
{
    private $enabled;
    private $enableAnnotations;
    private $enableAttributes;
    private $nameConverter;
    private $circularReferenceHandler;
    private $maxDepthHandler;
    private $mapping;
    private $defaultContext;
    private $_usedProperties = [];
    /**
     * @default true
     * @param ParamConfigurator|bool $value
     * @return $this
     */
    public function enabled($value): static
    {
        $this->_usedProperties['enabled'] = \true;
        $this->enabled = $value;
        return $this;
    }
    /**
     * @default null
     * @param ParamConfigurator|bool $value
     * @return $this
     */
    public function enableAnnotations($value): static
    {
        $this->_usedProperties['enableAnnotations'] = \true;
        $this->enableAnnotations = $value;
        return $this;
    }
    /**
     * @default true
     * @param ParamConfigurator|bool $value
     * @return $this
     */
    public function enableAttributes($value): static
    {
        $this->_usedProperties['enableAttributes'] = \true;
        $this->enableAttributes = $value;
        return $this;
    }
    /**
     * @default null
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function nameConverter($value): static
    {
        $this->_usedProperties['nameConverter'] = \true;
        $this->nameConverter = $value;
        return $this;
    }
    /**
     * @default null
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function circularReferenceHandler($value): static
    {
        $this->_usedProperties['circularReferenceHandler'] = \true;
        $this->circularReferenceHandler = $value;
        return $this;
    }
    /**
     * @default null
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function maxDepthHandler($value): static
    {
        $this->_usedProperties['maxDepthHandler'] = \true;
        $this->maxDepthHandler = $value;
        return $this;
    }
    /**
     * @default {"paths":[]}
     */
    public function mapping(array $value = []): \_ContaoManager\Symfony\Config\Framework\Serializer\MappingConfig
    {
        if (null === $this->mapping) {
            $this->_usedProperties['mapping'] = \true;
            $this->mapping = new \_ContaoManager\Symfony\Config\Framework\Serializer\MappingConfig($value);
        } elseif (0 < \func_num_args()) {
            throw new InvalidConfigurationException('The node created by "mapping()" has already been initialized. You cannot pass values the second time you call mapping().');
        }
        return $this->mapping;
    }
    /**
     * @return $this
     */
    public function defaultContext(string $key, mixed $value): static
    {
        $this->_usedProperties['defaultContext'] = \true;
        $this->defaultContext[$key] = $value;
        return $this;
    }
    public function __construct(array $value = [])
    {
        if (array_key_exists('enabled', $value)) {
            $this->_usedProperties['enabled'] = \true;
            $this->enabled = $value['enabled'];
            unset($value['enabled']);
        }
        if (array_key_exists('enable_annotations', $value)) {
            $this->_usedProperties['enableAnnotations'] = \true;
            $this->enableAnnotations = $value['enable_annotations'];
            unset($value['enable_annotations']);
        }
        if (array_key_exists('enable_attributes', $value)) {
            $this->_usedProperties['enableAttributes'] = \true;
            $this->enableAttributes = $value['enable_attributes'];
            unset($value['enable_attributes']);
        }
        if (array_key_exists('name_converter', $value)) {
            $this->_usedProperties['nameConverter'] = \true;
            $this->nameConverter = $value['name_converter'];
            unset($value['name_converter']);
        }
        if (array_key_exists('circular_reference_handler', $value)) {
            $this->_usedProperties['circularReferenceHandler'] = \true;
            $this->circularReferenceHandler = $value['circular_reference_handler'];
            unset($value['circular_reference_handler']);
        }
        if (array_key_exists('max_depth_handler', $value)) {
            $this->_usedProperties['maxDepthHandler'] = \true;
            $this->maxDepthHandler = $value['max_depth_handler'];
            unset($value['max_depth_handler']);
        }
        if (array_key_exists('mapping', $value)) {
            $this->_usedProperties['mapping'] = \true;
            $this->mapping = new \_ContaoManager\Symfony\Config\Framework\Serializer\MappingConfig($value['mapping']);
            unset($value['mapping']);
        }
        if (array_key_exists('default_context', $value)) {
            $this->_usedProperties['defaultContext'] = \true;
            $this->defaultContext = $value['default_context'];
            unset($value['default_context']);
        }
        if ([] !== $value) {
            throw new InvalidConfigurationException(sprintf('The following keys are not supported by "%s": ', __CLASS__) . implode(', ', array_keys($value)));
        }
    }
    public function toArray(): array
    {
        $output = [];
        if (isset($this->_usedProperties['enabled'])) {
            $output['enabled'] = $this->enabled;
        }
        if (isset($this->_usedProperties['enableAnnotations'])) {
            $output['enable_annotations'] = $this->enableAnnotations;
        }
        if (isset($this->_usedProperties['enableAttributes'])) {
            $output['enable_attributes'] = $this->enableAttributes;
        }
        if (isset($this->_usedProperties['nameConverter'])) {
            $output['name_converter'] = $this->nameConverter;
        }
        if (isset($this->_usedProperties['circularReferenceHandler'])) {
            $output['circular_reference_handler'] = $this->circularReferenceHandler;
        }
        if (isset($this->_usedProperties['maxDepthHandler'])) {
            $output['max_depth_handler'] = $this->maxDepthHandler;
        }
        if (isset($this->_usedProperties['mapping'])) {
            $output['mapping'] = $this->mapping->toArray();
        }
        if (isset($this->_usedProperties['defaultContext'])) {
            $output['default_context'] = $this->defaultContext;
        }
        return $output;
    }
}
<?php

namespace _ContaoManager\Symfony\Config\Framework;

use _ContaoManager\Symfony\Component\Config\Loader\ParamConfigurator;
use _ContaoManager\Symfony\Component\Config\Definition\Exception\InvalidConfigurationException;
/**
 * This class is automatically generated to help in creating a config.
 */
class CsrfProtectionConfig
{
    private $enabled;
    private $_usedProperties = [];
    /**
     * @default null
     * @param ParamConfigurator|bool $value
     * @return $this
     */
    public function enabled($value): static
    {
        $this->_usedProperties['enabled'] = \true;
        $this->enabled = $value;
        return $this;
    }
    public function __construct(array $value = [])
    {
        if (array_key_exists('enabled', $value)) {
            $this->_usedProperties['enabled'] = \true;
            $this->enabled = $value['enabled'];
            unset($value['enabled']);
        }
        if ([] !== $value) {
            throw new InvalidConfigurationException(sprintf('The following keys are not supported by "%s": ', __CLASS__) . implode(', ', array_keys($value)));
        }
    }
    public function toArray(): array
    {
        $output = [];
        if (isset($this->_usedProperties['enabled'])) {
            $output['enabled'] = $this->enabled;
        }
        return $output;
    }
}
<?php

namespace _ContaoManager\Symfony\Config\Framework;

require_once __DIR__ . \DIRECTORY_SEPARATOR . 'Assets' . \DIRECTORY_SEPARATOR . 'PackageConfig.php';
use _ContaoManager\Symfony\Component\Config\Loader\ParamConfigurator;
use _ContaoManager\Symfony\Component\Config\Definition\Exception\InvalidConfigurationException;
/**
 * This class is automatically generated to help in creating a config.
 */
class AssetsConfig
{
    private $enabled;
    private $strictMode;
    private $versionStrategy;
    private $version;
    private $versionFormat;
    private $jsonManifestPath;
    private $basePath;
    private $baseUrls;
    private $packages;
    private $_usedProperties = [];
    /**
     * @default false
     * @param ParamConfigurator|bool $value
     * @return $this
     */
    public function enabled($value): static
    {
        $this->_usedProperties['enabled'] = \true;
        $this->enabled = $value;
        return $this;
    }
    /**
     * Throw an exception if an entry is missing from the manifest.json
     * @default false
     * @param ParamConfigurator|bool $value
     * @return $this
     */
    public function strictMode($value): static
    {
        $this->_usedProperties['strictMode'] = \true;
        $this->strictMode = $value;
        return $this;
    }
    /**
     * @default null
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function versionStrategy($value): static
    {
        $this->_usedProperties['versionStrategy'] = \true;
        $this->versionStrategy = $value;
        return $this;
    }
    /**
     * @default null
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function version($value): static
    {
        $this->_usedProperties['version'] = \true;
        $this->version = $value;
        return $this;
    }
    /**
     * @default '%%s?%%s'
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function versionFormat($value): static
    {
        $this->_usedProperties['versionFormat'] = \true;
        $this->versionFormat = $value;
        return $this;
    }
    /**
     * @default null
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function jsonManifestPath($value): static
    {
        $this->_usedProperties['jsonManifestPath'] = \true;
        $this->jsonManifestPath = $value;
        return $this;
    }
    /**
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function basePath($value): static
    {
        $this->_usedProperties['basePath'] = \true;
        $this->basePath = $value;
        return $this;
    }
    /**
     * @param ParamConfigurator|list<ParamConfigurator|mixed>|mixed $value
     *
     * @return $this
     */
    public function baseUrls(mixed $value): static
    {
        $this->_usedProperties['baseUrls'] = \true;
        $this->baseUrls = $value;
        return $this;
    }
    public function package(string $name, array $value = []): \_ContaoManager\Symfony\Config\Framework\Assets\PackageConfig
    {
        if (!isset($this->packages[$name])) {
            $this->_usedProperties['packages'] = \true;
            $this->packages[$name] = new \_ContaoManager\Symfony\Config\Framework\Assets\PackageConfig($value);
        } elseif (1 < \func_num_args()) {
            throw new InvalidConfigurationException('The node created by "package()" has already been initialized. You cannot pass values the second time you call package().');
        }
        return $this->packages[$name];
    }
    public function __construct(array $value = [])
    {
        if (array_key_exists('enabled', $value)) {
            $this->_usedProperties['enabled'] = \true;
            $this->enabled = $value['enabled'];
            unset($value['enabled']);
        }
        if (array_key_exists('strict_mode', $value)) {
            $this->_usedProperties['strictMode'] = \true;
            $this->strictMode = $value['strict_mode'];
            unset($value['strict_mode']);
        }
        if (array_key_exists('version_strategy', $value)) {
            $this->_usedProperties['versionStrategy'] = \true;
            $this->versionStrategy = $value['version_strategy'];
            unset($value['version_strategy']);
        }
        if (array_key_exists('version', $value)) {
            $this->_usedProperties['version'] = \true;
            $this->version = $value['version'];
            unset($value['version']);
        }
        if (array_key_exists('version_format', $value)) {
            $this->_usedProperties['versionFormat'] = \true;
            $this->versionFormat = $value['version_format'];
            unset($value['version_format']);
        }
        if (array_key_exists('json_manifest_path', $value)) {
            $this->_usedProperties['jsonManifestPath'] = \true;
            $this->jsonManifestPath = $value['json_manifest_path'];
            unset($value['json_manifest_path']);
        }
        if (array_key_exists('base_path', $value)) {
            $this->_usedProperties['basePath'] = \true;
            $this->basePath = $value['base_path'];
            unset($value['base_path']);
        }
        if (array_key_exists('base_urls', $value)) {
            $this->_usedProperties['baseUrls'] = \true;
            $this->baseUrls = $value['base_urls'];
            unset($value['base_urls']);
        }
        if (array_key_exists('packages', $value)) {
            $this->_usedProperties['packages'] = \true;
            $this->packages = array_map(fn($v) => new \_ContaoManager\Symfony\Config\Framework\Assets\PackageConfig($v), $value['packages']);
            unset($value['packages']);
        }
        if ([] !== $value) {
            throw new InvalidConfigurationException(sprintf('The following keys are not supported by "%s": ', __CLASS__) . implode(', ', array_keys($value)));
        }
    }
    public function toArray(): array
    {
        $output = [];
        if (isset($this->_usedProperties['enabled'])) {
            $output['enabled'] = $this->enabled;
        }
        if (isset($this->_usedProperties['strictMode'])) {
            $output['strict_mode'] = $this->strictMode;
        }
        if (isset($this->_usedProperties['versionStrategy'])) {
            $output['version_strategy'] = $this->versionStrategy;
        }
        if (isset($this->_usedProperties['version'])) {
            $output['version'] = $this->version;
        }
        if (isset($this->_usedProperties['versionFormat'])) {
            $output['version_format'] = $this->versionFormat;
        }
        if (isset($this->_usedProperties['jsonManifestPath'])) {
            $output['json_manifest_path'] = $this->jsonManifestPath;
        }
        if (isset($this->_usedProperties['basePath'])) {
            $output['base_path'] = $this->basePath;
        }
        if (isset($this->_usedProperties['baseUrls'])) {
            $output['base_urls'] = $this->baseUrls;
        }
        if (isset($this->_usedProperties['packages'])) {
            $output['packages'] = array_map(fn($v) => $v->toArray(), $this->packages);
        }
        return $output;
    }
}
<?php

namespace _ContaoManager\Symfony\Config\Framework\Notifier;

use _ContaoManager\Symfony\Component\Config\Loader\ParamConfigurator;
use _ContaoManager\Symfony\Component\Config\Definition\Exception\InvalidConfigurationException;
/**
 * This class is automatically generated to help in creating a config.
 */
class AdminRecipientConfig
{
    private $email;
    private $phone;
    private $_usedProperties = [];
    /**
     * @default null
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function email($value): static
    {
        $this->_usedProperties['email'] = \true;
        $this->email = $value;
        return $this;
    }
    /**
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function phone($value): static
    {
        $this->_usedProperties['phone'] = \true;
        $this->phone = $value;
        return $this;
    }
    public function __construct(array $value = [])
    {
        if (array_key_exists('email', $value)) {
            $this->_usedProperties['email'] = \true;
            $this->email = $value['email'];
            unset($value['email']);
        }
        if (array_key_exists('phone', $value)) {
            $this->_usedProperties['phone'] = \true;
            $this->phone = $value['phone'];
            unset($value['phone']);
        }
        if ([] !== $value) {
            throw new InvalidConfigurationException(sprintf('The following keys are not supported by "%s": ', __CLASS__) . implode(', ', array_keys($value)));
        }
    }
    public function toArray(): array
    {
        $output = [];
        if (isset($this->_usedProperties['email'])) {
            $output['email'] = $this->email;
        }
        if (isset($this->_usedProperties['phone'])) {
            $output['phone'] = $this->phone;
        }
        return $output;
    }
}
<?php

namespace _ContaoManager\Symfony\Config\Framework;

require_once __DIR__ . \DIRECTORY_SEPARATOR . 'Messenger' . \DIRECTORY_SEPARATOR . 'RoutingConfig.php';
require_once __DIR__ . \DIRECTORY_SEPARATOR . 'Messenger' . \DIRECTORY_SEPARATOR . 'SerializerConfig.php';
require_once __DIR__ . \DIRECTORY_SEPARATOR . 'Messenger' . \DIRECTORY_SEPARATOR . 'TransportConfig.php';
require_once __DIR__ . \DIRECTORY_SEPARATOR . 'Messenger' . \DIRECTORY_SEPARATOR . 'BusConfig.php';
use _ContaoManager\Symfony\Component\Config\Loader\ParamConfigurator;
use _ContaoManager\Symfony\Component\Config\Definition\Exception\InvalidConfigurationException;
/**
 * This class is automatically generated to help in creating a config.
 */
class MessengerConfig
{
    private $enabled;
    private $routing;
    private $serializer;
    private $transports;
    private $failureTransport;
    private $resetOnMessage;
    private $stopWorkerOnSignals;
    private $defaultBus;
    private $buses;
    private $_usedProperties = [];
    /**
     * @default false
     * @param ParamConfigurator|bool $value
     * @return $this
     */
    public function enabled($value): static
    {
        $this->_usedProperties['enabled'] = \true;
        $this->enabled = $value;
        return $this;
    }
    public function routing(string $message_class, array $value = []): \_ContaoManager\Symfony\Config\Framework\Messenger\RoutingConfig
    {
        if (!isset($this->routing[$message_class])) {
            $this->_usedProperties['routing'] = \true;
            $this->routing[$message_class] = new \_ContaoManager\Symfony\Config\Framework\Messenger\RoutingConfig($value);
        } elseif (1 < \func_num_args()) {
            throw new InvalidConfigurationException('The node created by "routing()" has already been initialized. You cannot pass values the second time you call routing().');
        }
        return $this->routing[$message_class];
    }
    /**
     * @default {"default_serializer":"messenger.transport.native_php_serializer","symfony_serializer":{"format":"json","context":[]}}
     */
    public function serializer(array $value = []): \_ContaoManager\Symfony\Config\Framework\Messenger\SerializerConfig
    {
        if (null === $this->serializer) {
            $this->_usedProperties['serializer'] = \true;
            $this->serializer = new \_ContaoManager\Symfony\Config\Framework\Messenger\SerializerConfig($value);
        } elseif (0 < \func_num_args()) {
            throw new InvalidConfigurationException('The node created by "serializer()" has already been initialized. You cannot pass values the second time you call serializer().');
        }
        return $this->serializer;
    }
    /**
     * @template TValue of string|array
     * @param TValue $value
     * @return \Symfony\Config\Framework\Messenger\TransportConfig|$this
     * @psalm-return (TValue is array ? \Symfony\Config\Framework\Messenger\TransportConfig : static)
     */
    public function transport(string $name, string|array $value = []): \_ContaoManager\Symfony\Config\Framework\Messenger\TransportConfig|static
    {
        if (!\is_array($value)) {
            $this->_usedProperties['transports'] = \true;
            $this->transports[$name] = $value;
            return $this;
        }
        if (!isset($this->transports[$name]) || !$this->transports[$name] instanceof \_ContaoManager\Symfony\Config\Framework\Messenger\TransportConfig) {
            $this->_usedProperties['transports'] = \true;
            $this->transports[$name] = new \_ContaoManager\Symfony\Config\Framework\Messenger\TransportConfig($value);
        } elseif (1 < \func_num_args()) {
            throw new InvalidConfigurationException('The node created by "transport()" has already been initialized. You cannot pass values the second time you call transport().');
        }
        return $this->transports[$name];
    }
    /**
     * Transport name to send failed messages to (after all retries have failed).
     * @default null
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function failureTransport($value): static
    {
        $this->_usedProperties['failureTransport'] = \true;
        $this->failureTransport = $value;
        return $this;
    }
    /**
     * Reset container services after each message.
     * @default true
     * @param ParamConfigurator|bool $value
     * @deprecated Option "reset_on_message" at "messenger" is deprecated. It does nothing and will be removed in version 7.0.
     * @return $this
     */
    public function resetOnMessage($value): static
    {
        $this->_usedProperties['resetOnMessage'] = \true;
        $this->resetOnMessage = $value;
        return $this;
    }
    /**
     * @param ParamConfigurator|list<ParamConfigurator|int> $value
     *
     * @return $this
     */
    public function stopWorkerOnSignals(ParamConfigurator|array $value): static
    {
        $this->_usedProperties['stopWorkerOnSignals'] = \true;
        $this->stopWorkerOnSignals = $value;
        return $this;
    }
    /**
     * @default null
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function defaultBus($value): static
    {
        $this->_usedProperties['defaultBus'] = \true;
        $this->defaultBus = $value;
        return $this;
    }
    /**
     * @default {"messenger.bus.default":{"default_middleware":{"enabled":true,"allow_no_handlers":false,"allow_no_senders":true},"middleware":[]}}
     */
    public function bus(string $name, array $value = []): \_ContaoManager\Symfony\Config\Framework\Messenger\BusConfig
    {
        if (!isset($this->buses[$name])) {
            $this->_usedProperties['buses'] = \true;
            $this->buses[$name] = new \_ContaoManager\Symfony\Config\Framework\Messenger\BusConfig($value);
        } elseif (1 < \func_num_args()) {
            throw new InvalidConfigurationException('The node created by "bus()" has already been initialized. You cannot pass values the second time you call bus().');
        }
        return $this->buses[$name];
    }
    public function __construct(array $value = [])
    {
        if (array_key_exists('enabled', $value)) {
            $this->_usedProperties['enabled'] = \true;
            $this->enabled = $value['enabled'];
            unset($value['enabled']);
        }
        if (array_key_exists('routing', $value)) {
            $this->_usedProperties['routing'] = \true;
            $this->routing = array_map(fn($v) => \is_array($v) ? new \_ContaoManager\Symfony\Config\Framework\Messenger\RoutingConfig($v) : $v, $value['routing']);
            unset($value['routing']);
        }
        if (array_key_exists('serializer', $value)) {
            $this->_usedProperties['serializer'] = \true;
            $this->serializer = new \_ContaoManager\Symfony\Config\Framework\Messenger\SerializerConfig($value['serializer']);
            unset($value['serializer']);
        }
        if (array_key_exists('transports', $value)) {
            $this->_usedProperties['transports'] = \true;
            $this->transports = array_map(fn($v) => \is_array($v) ? new \_ContaoManager\Symfony\Config\Framework\Messenger\TransportConfig($v) : $v, $value['transports']);
            unset($value['transports']);
        }
        if (array_key_exists('failure_transport', $value)) {
            $this->_usedProperties['failureTransport'] = \true;
            $this->failureTransport = $value['failure_transport'];
            unset($value['failure_transport']);
        }
        if (array_key_exists('reset_on_message', $value)) {
            $this->_usedProperties['resetOnMessage'] = \true;
            $this->resetOnMessage = $value['reset_on_message'];
            unset($value['reset_on_message']);
        }
        if (array_key_exists('stop_worker_on_signals', $value)) {
            $this->_usedProperties['stopWorkerOnSignals'] = \true;
            $this->stopWorkerOnSignals = $value['stop_worker_on_signals'];
            unset($value['stop_worker_on_signals']);
        }
        if (array_key_exists('default_bus', $value)) {
            $this->_usedProperties['defaultBus'] = \true;
            $this->defaultBus = $value['default_bus'];
            unset($value['default_bus']);
        }
        if (array_key_exists('buses', $value)) {
            $this->_usedProperties['buses'] = \true;
            $this->buses = array_map(fn($v) => new \_ContaoManager\Symfony\Config\Framework\Messenger\BusConfig($v), $value['buses']);
            unset($value['buses']);
        }
        if ([] !== $value) {
            throw new InvalidConfigurationException(sprintf('The following keys are not supported by "%s": ', __CLASS__) . implode(', ', array_keys($value)));
        }
    }
    public function toArray(): array
    {
        $output = [];
        if (isset($this->_usedProperties['enabled'])) {
            $output['enabled'] = $this->enabled;
        }
        if (isset($this->_usedProperties['routing'])) {
            $output['routing'] = array_map(fn($v) => $v instanceof \_ContaoManager\Symfony\Config\Framework\Messenger\RoutingConfig ? $v->toArray() : $v, $this->routing);
        }
        if (isset($this->_usedProperties['serializer'])) {
            $output['serializer'] = $this->serializer->toArray();
        }
        if (isset($this->_usedProperties['transports'])) {
            $output['transports'] = array_map(fn($v) => $v instanceof \_ContaoManager\Symfony\Config\Framework\Messenger\TransportConfig ? $v->toArray() : $v, $this->transports);
        }
        if (isset($this->_usedProperties['failureTransport'])) {
            $output['failure_transport'] = $this->failureTransport;
        }
        if (isset($this->_usedProperties['resetOnMessage'])) {
            $output['reset_on_message'] = $this->resetOnMessage;
        }
        if (isset($this->_usedProperties['stopWorkerOnSignals'])) {
            $output['stop_worker_on_signals'] = $this->stopWorkerOnSignals;
        }
        if (isset($this->_usedProperties['defaultBus'])) {
            $output['default_bus'] = $this->defaultBus;
        }
        if (isset($this->_usedProperties['buses'])) {
            $output['buses'] = array_map(fn($v) => $v->toArray(), $this->buses);
        }
        return $output;
    }
}
<?php

namespace _ContaoManager\Symfony\Config\Framework;

require_once __DIR__ . \DIRECTORY_SEPARATOR . 'Webhook' . \DIRECTORY_SEPARATOR . 'RoutingConfig.php';
use _ContaoManager\Symfony\Component\Config\Loader\ParamConfigurator;
use _ContaoManager\Symfony\Component\Config\Definition\Exception\InvalidConfigurationException;
/**
 * This class is automatically generated to help in creating a config.
 */
class WebhookConfig
{
    private $enabled;
    private $messageBus;
    private $routing;
    private $_usedProperties = [];
    /**
     * @default false
     * @param ParamConfigurator|bool $value
     * @return $this
     */
    public function enabled($value): static
    {
        $this->_usedProperties['enabled'] = \true;
        $this->enabled = $value;
        return $this;
    }
    /**
     * The message bus to use.
     * @default 'messenger.default_bus'
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function messageBus($value): static
    {
        $this->_usedProperties['messageBus'] = \true;
        $this->messageBus = $value;
        return $this;
    }
    public function routing(string $type, array $value = []): \_ContaoManager\Symfony\Config\Framework\Webhook\RoutingConfig
    {
        if (!isset($this->routing[$type])) {
            $this->_usedProperties['routing'] = \true;
            $this->routing[$type] = new \_ContaoManager\Symfony\Config\Framework\Webhook\RoutingConfig($value);
        } elseif (1 < \func_num_args()) {
            throw new InvalidConfigurationException('The node created by "routing()" has already been initialized. You cannot pass values the second time you call routing().');
        }
        return $this->routing[$type];
    }
    public function __construct(array $value = [])
    {
        if (array_key_exists('enabled', $value)) {
            $this->_usedProperties['enabled'] = \true;
            $this->enabled = $value['enabled'];
            unset($value['enabled']);
        }
        if (array_key_exists('message_bus', $value)) {
            $this->_usedProperties['messageBus'] = \true;
            $this->messageBus = $value['message_bus'];
            unset($value['message_bus']);
        }
        if (array_key_exists('routing', $value)) {
            $this->_usedProperties['routing'] = \true;
            $this->routing = array_map(fn($v) => new \_ContaoManager\Symfony\Config\Framework\Webhook\RoutingConfig($v), $value['routing']);
            unset($value['routing']);
        }
        if ([] !== $value) {
            throw new InvalidConfigurationException(sprintf('The following keys are not supported by "%s": ', __CLASS__) . implode(', ', array_keys($value)));
        }
    }
    public function toArray(): array
    {
        $output = [];
        if (isset($this->_usedProperties['enabled'])) {
            $output['enabled'] = $this->enabled;
        }
        if (isset($this->_usedProperties['messageBus'])) {
            $output['message_bus'] = $this->messageBus;
        }
        if (isset($this->_usedProperties['routing'])) {
            $output['routing'] = array_map(fn($v) => $v->toArray(), $this->routing);
        }
        return $output;
    }
}
<?php

namespace _ContaoManager\Symfony\Config\Framework;

use _ContaoManager\Symfony\Component\Config\Loader\ParamConfigurator;
use _ContaoManager\Symfony\Component\Config\Definition\Exception\InvalidConfigurationException;
/**
 * This class is automatically generated to help in creating a config.
 */
class RouterConfig
{
    private $enabled;
    private $resource;
    private $type;
    private $cacheDir;
    private $defaultUri;
    private $httpPort;
    private $httpsPort;
    private $strictRequirements;
    private $utf8;
    private $_usedProperties = [];
    /**
     * @default false
     * @param ParamConfigurator|bool $value
     * @return $this
     */
    public function enabled($value): static
    {
        $this->_usedProperties['enabled'] = \true;
        $this->enabled = $value;
        return $this;
    }
    /**
     * @default null
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function resource($value): static
    {
        $this->_usedProperties['resource'] = \true;
        $this->resource = $value;
        return $this;
    }
    /**
     * @default null
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function type($value): static
    {
        $this->_usedProperties['type'] = \true;
        $this->type = $value;
        return $this;
    }
    /**
     * @default '%kernel.cache_dir%'
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function cacheDir($value): static
    {
        $this->_usedProperties['cacheDir'] = \true;
        $this->cacheDir = $value;
        return $this;
    }
    /**
     * The default URI used to generate URLs in a non-HTTP context
     * @default null
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function defaultUri($value): static
    {
        $this->_usedProperties['defaultUri'] = \true;
        $this->defaultUri = $value;
        return $this;
    }
    /**
     * @default 80
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function httpPort($value): static
    {
        $this->_usedProperties['httpPort'] = \true;
        $this->httpPort = $value;
        return $this;
    }
    /**
     * @default 443
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function httpsPort($value): static
    {
        $this->_usedProperties['httpsPort'] = \true;
        $this->httpsPort = $value;
        return $this;
    }
    /**
     * set to true to throw an exception when a parameter does not match the requirements
     * set to false to disable exceptions when a parameter does not match the requirements (and return null instead)
     * set to null to disable parameter checks against requirements
     * 'true' is the preferred configuration in development mode, while 'false' or 'null' might be preferred in production
     * @default true
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function strictRequirements($value): static
    {
        $this->_usedProperties['strictRequirements'] = \true;
        $this->strictRequirements = $value;
        return $this;
    }
    /**
     * @default true
     * @param ParamConfigurator|bool $value
     * @return $this
     */
    public function utf8($value): static
    {
        $this->_usedProperties['utf8'] = \true;
        $this->utf8 = $value;
        return $this;
    }
    public function __construct(array $value = [])
    {
        if (array_key_exists('enabled', $value)) {
            $this->_usedProperties['enabled'] = \true;
            $this->enabled = $value['enabled'];
            unset($value['enabled']);
        }
        if (array_key_exists('resource', $value)) {
            $this->_usedProperties['resource'] = \true;
            $this->resource = $value['resource'];
            unset($value['resource']);
        }
        if (array_key_exists('type', $value)) {
            $this->_usedProperties['type'] = \true;
            $this->type = $value['type'];
            unset($value['type']);
        }
        if (array_key_exists('cache_dir', $value)) {
            $this->_usedProperties['cacheDir'] = \true;
            $this->cacheDir = $value['cache_dir'];
            unset($value['cache_dir']);
        }
        if (array_key_exists('default_uri', $value)) {
            $this->_usedProperties['defaultUri'] = \true;
            $this->defaultUri = $value['default_uri'];
            unset($value['default_uri']);
        }
        if (array_key_exists('http_port', $value)) {
            $this->_usedProperties['httpPort'] = \true;
            $this->httpPort = $value['http_port'];
            unset($value['http_port']);
        }
        if (array_key_exists('https_port', $value)) {
            $this->_usedProperties['httpsPort'] = \true;
            $this->httpsPort = $value['https_port'];
            unset($value['https_port']);
        }
        if (array_key_exists('strict_requirements', $value)) {
            $this->_usedProperties['strictRequirements'] = \true;
            $this->strictRequirements = $value['strict_requirements'];
            unset($value['strict_requirements']);
        }
        if (array_key_exists('utf8', $value)) {
            $this->_usedProperties['utf8'] = \true;
            $this->utf8 = $value['utf8'];
            unset($value['utf8']);
        }
        if ([] !== $value) {
            throw new InvalidConfigurationException(sprintf('The following keys are not supported by "%s": ', __CLASS__) . implode(', ', array_keys($value)));
        }
    }
    public function toArray(): array
    {
        $output = [];
        if (isset($this->_usedProperties['enabled'])) {
            $output['enabled'] = $this->enabled;
        }
        if (isset($this->_usedProperties['resource'])) {
            $output['resource'] = $this->resource;
        }
        if (isset($this->_usedProperties['type'])) {
            $output['type'] = $this->type;
        }
        if (isset($this->_usedProperties['cacheDir'])) {
            $output['cache_dir'] = $this->cacheDir;
        }
        if (isset($this->_usedProperties['defaultUri'])) {
            $output['default_uri'] = $this->defaultUri;
        }
        if (isset($this->_usedProperties['httpPort'])) {
            $output['http_port'] = $this->httpPort;
        }
        if (isset($this->_usedProperties['httpsPort'])) {
            $output['https_port'] = $this->httpsPort;
        }
        if (isset($this->_usedProperties['strictRequirements'])) {
            $output['strict_requirements'] = $this->strictRequirements;
        }
        if (isset($this->_usedProperties['utf8'])) {
            $output['utf8'] = $this->utf8;
        }
        return $output;
    }
}
<?php

namespace _ContaoManager\Symfony\Config\Framework;

require_once __DIR__ . \DIRECTORY_SEPARATOR . 'Translator' . \DIRECTORY_SEPARATOR . 'PseudoLocalizationConfig.php';
require_once __DIR__ . \DIRECTORY_SEPARATOR . 'Translator' . \DIRECTORY_SEPARATOR . 'ProviderConfig.php';
use _ContaoManager\Symfony\Component\Config\Loader\ParamConfigurator;
use _ContaoManager\Symfony\Component\Config\Definition\Exception\InvalidConfigurationException;
/**
 * This class is automatically generated to help in creating a config.
 */
class TranslatorConfig
{
    private $enabled;
    private $fallbacks;
    private $logging;
    private $formatter;
    private $cacheDir;
    private $defaultPath;
    private $paths;
    private $pseudoLocalization;
    private $providers;
    private $_usedProperties = [];
    /**
     * @default false
     * @param ParamConfigurator|bool $value
     * @return $this
     */
    public function enabled($value): static
    {
        $this->_usedProperties['enabled'] = \true;
        $this->enabled = $value;
        return $this;
    }
    /**
     * @param ParamConfigurator|list<ParamConfigurator|mixed>|string $value
     *
     * @return $this
     */
    public function fallbacks(ParamConfigurator|string|array $value): static
    {
        $this->_usedProperties['fallbacks'] = \true;
        $this->fallbacks = $value;
        return $this;
    }
    /**
     * @default false
     * @param ParamConfigurator|bool $value
     * @return $this
     */
    public function logging($value): static
    {
        $this->_usedProperties['logging'] = \true;
        $this->logging = $value;
        return $this;
    }
    /**
     * @default 'translator.formatter.default'
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function formatter($value): static
    {
        $this->_usedProperties['formatter'] = \true;
        $this->formatter = $value;
        return $this;
    }
    /**
     * @default '%kernel.cache_dir%/translations'
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function cacheDir($value): static
    {
        $this->_usedProperties['cacheDir'] = \true;
        $this->cacheDir = $value;
        return $this;
    }
    /**
     * The default path used to load translations
     * @default '%kernel.project_dir%/translations'
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function defaultPath($value): static
    {
        $this->_usedProperties['defaultPath'] = \true;
        $this->defaultPath = $value;
        return $this;
    }
    /**
     * @param ParamConfigurator|list<ParamConfigurator|mixed> $value
     *
     * @return $this
     */
    public function paths(ParamConfigurator|array $value): static
    {
        $this->_usedProperties['paths'] = \true;
        $this->paths = $value;
        return $this;
    }
    /**
     * @default {"enabled":false,"accents":true,"expansion_factor":1,"brackets":true,"parse_html":false,"localizable_html_attributes":[]}
     */
    public function pseudoLocalization(array $value = []): \_ContaoManager\Symfony\Config\Framework\Translator\PseudoLocalizationConfig
    {
        if (null === $this->pseudoLocalization) {
            $this->_usedProperties['pseudoLocalization'] = \true;
            $this->pseudoLocalization = new \_ContaoManager\Symfony\Config\Framework\Translator\PseudoLocalizationConfig($value);
        } elseif (0 < \func_num_args()) {
            throw new InvalidConfigurationException('The node created by "pseudoLocalization()" has already been initialized. You cannot pass values the second time you call pseudoLocalization().');
        }
        return $this->pseudoLocalization;
    }
    /**
     * Translation providers you can read/write your translations from
     */
    public function provider(string $name, array $value = []): \_ContaoManager\Symfony\Config\Framework\Translator\ProviderConfig
    {
        if (!isset($this->providers[$name])) {
            $this->_usedProperties['providers'] = \true;
            $this->providers[$name] = new \_ContaoManager\Symfony\Config\Framework\Translator\ProviderConfig($value);
        } elseif (1 < \func_num_args()) {
            throw new InvalidConfigurationException('The node created by "provider()" has already been initialized. You cannot pass values the second time you call provider().');
        }
        return $this->providers[$name];
    }
    public function __construct(array $value = [])
    {
        if (array_key_exists('enabled', $value)) {
            $this->_usedProperties['enabled'] = \true;
            $this->enabled = $value['enabled'];
            unset($value['enabled']);
        }
        if (array_key_exists('fallbacks', $value)) {
            $this->_usedProperties['fallbacks'] = \true;
            $this->fallbacks = $value['fallbacks'];
            unset($value['fallbacks']);
        }
        if (array_key_exists('logging', $value)) {
            $this->_usedProperties['logging'] = \true;
            $this->logging = $value['logging'];
            unset($value['logging']);
        }
        if (array_key_exists('formatter', $value)) {
            $this->_usedProperties['formatter'] = \true;
            $this->formatter = $value['formatter'];
            unset($value['formatter']);
        }
        if (array_key_exists('cache_dir', $value)) {
            $this->_usedProperties['cacheDir'] = \true;
            $this->cacheDir = $value['cache_dir'];
            unset($value['cache_dir']);
        }
        if (array_key_exists('default_path', $value)) {
            $this->_usedProperties['defaultPath'] = \true;
            $this->defaultPath = $value['default_path'];
            unset($value['default_path']);
        }
        if (array_key_exists('paths', $value)) {
            $this->_usedProperties['paths'] = \true;
            $this->paths = $value['paths'];
            unset($value['paths']);
        }
        if (array_key_exists('pseudo_localization', $value)) {
            $this->_usedProperties['pseudoLocalization'] = \true;
            $this->pseudoLocalization = \is_array($value['pseudo_localization']) ? new \_ContaoManager\Symfony\Config\Framework\Translator\PseudoLocalizationConfig($value['pseudo_localization']) : $value['pseudo_localization'];
            unset($value['pseudo_localization']);
        }
        if (array_key_exists('providers', $value)) {
            $this->_usedProperties['providers'] = \true;
            $this->providers = array_map(fn($v) => new \_ContaoManager\Symfony\Config\Framework\Translator\ProviderConfig($v), $value['providers']);
            unset($value['providers']);
        }
        if ([] !== $value) {
            throw new InvalidConfigurationException(sprintf('The following keys are not supported by "%s": ', __CLASS__) . implode(', ', array_keys($value)));
        }
    }
    public function toArray(): array
    {
        $output = [];
        if (isset($this->_usedProperties['enabled'])) {
            $output['enabled'] = $this->enabled;
        }
        if (isset($this->_usedProperties['fallbacks'])) {
            $output['fallbacks'] = $this->fallbacks;
        }
        if (isset($this->_usedProperties['logging'])) {
            $output['logging'] = $this->logging;
        }
        if (isset($this->_usedProperties['formatter'])) {
            $output['formatter'] = $this->formatter;
        }
        if (isset($this->_usedProperties['cacheDir'])) {
            $output['cache_dir'] = $this->cacheDir;
        }
        if (isset($this->_usedProperties['defaultPath'])) {
            $output['default_path'] = $this->defaultPath;
        }
        if (isset($this->_usedProperties['paths'])) {
            $output['paths'] = $this->paths;
        }
        if (isset($this->_usedProperties['pseudoLocalization'])) {
            $output['pseudo_localization'] = $this->pseudoLocalization instanceof \_ContaoManager\Symfony\Config\Framework\Translator\PseudoLocalizationConfig ? $this->pseudoLocalization->toArray() : $this->pseudoLocalization;
        }
        if (isset($this->_usedProperties['providers'])) {
            $output['providers'] = array_map(fn($v) => $v->toArray(), $this->providers);
        }
        return $output;
    }
}
<?php

namespace _ContaoManager\Symfony\Config\Framework;

require_once __DIR__ . \DIRECTORY_SEPARATOR . 'Workflows' . \DIRECTORY_SEPARATOR . 'WorkflowsConfig.php';
use _ContaoManager\Symfony\Component\Config\Loader\ParamConfigurator;
use _ContaoManager\Symfony\Component\Config\Definition\Exception\InvalidConfigurationException;
/**
 * This class is automatically generated to help in creating a config.
 */
class WorkflowsConfig
{
    private $enabled;
    private $workflows;
    private $_usedProperties = [];
    /**
     * @default false
     * @param ParamConfigurator|bool $value
     * @return $this
     */
    public function enabled($value): static
    {
        $this->_usedProperties['enabled'] = \true;
        $this->enabled = $value;
        return $this;
    }
    /**
     * @template TValue of mixed
     * @param TValue $value
     * @return \Symfony\Config\Framework\Workflows\WorkflowsConfig|$this
     * @psalm-return (TValue is array ? \Symfony\Config\Framework\Workflows\WorkflowsConfig : static)
     */
    public function workflows(string $name, mixed $value = []): \_ContaoManager\Symfony\Config\Framework\Workflows\WorkflowsConfig|static
    {
        if (!\is_array($value)) {
            $this->_usedProperties['workflows'] = \true;
            $this->workflows[$name] = $value;
            return $this;
        }
        if (!isset($this->workflows[$name]) || !$this->workflows[$name] instanceof \_ContaoManager\Symfony\Config\Framework\Workflows\WorkflowsConfig) {
            $this->_usedProperties['workflows'] = \true;
            $this->workflows[$name] = new \_ContaoManager\Symfony\Config\Framework\Workflows\WorkflowsConfig($value);
        } elseif (1 < \func_num_args()) {
            throw new InvalidConfigurationException('The node created by "workflows()" has already been initialized. You cannot pass values the second time you call workflows().');
        }
        return $this->workflows[$name];
    }
    public function __construct(array $value = [])
    {
        if (array_key_exists('enabled', $value)) {
            $this->_usedProperties['enabled'] = \true;
            $this->enabled = $value['enabled'];
            unset($value['enabled']);
        }
        if (array_key_exists('workflows', $value)) {
            $this->_usedProperties['workflows'] = \true;
            $this->workflows = array_map(fn($v) => \is_array($v) ? new \_ContaoManager\Symfony\Config\Framework\Workflows\WorkflowsConfig($v) : $v, $value['workflows']);
            unset($value['workflows']);
        }
        if ([] !== $value) {
            throw new InvalidConfigurationException(sprintf('The following keys are not supported by "%s": ', __CLASS__) . implode(', ', array_keys($value)));
        }
    }
    public function toArray(): array
    {
        $output = [];
        if (isset($this->_usedProperties['enabled'])) {
            $output['enabled'] = $this->enabled;
        }
        if (isset($this->_usedProperties['workflows'])) {
            $output['workflows'] = array_map(fn($v) => $v instanceof \_ContaoManager\Symfony\Config\Framework\Workflows\WorkflowsConfig ? $v->toArray() : $v, $this->workflows);
        }
        return $output;
    }
}
<?php

namespace _ContaoManager\Symfony\Config\Framework\Workflows;

require_once __DIR__ . \DIRECTORY_SEPARATOR . 'WorkflowsConfig' . \DIRECTORY_SEPARATOR . 'AuditTrailConfig.php';
require_once __DIR__ . \DIRECTORY_SEPARATOR . 'WorkflowsConfig' . \DIRECTORY_SEPARATOR . 'MarkingStoreConfig.php';
require_once __DIR__ . \DIRECTORY_SEPARATOR . 'WorkflowsConfig' . \DIRECTORY_SEPARATOR . 'PlaceConfig.php';
require_once __DIR__ . \DIRECTORY_SEPARATOR . 'WorkflowsConfig' . \DIRECTORY_SEPARATOR . 'TransitionConfig.php';
use _ContaoManager\Symfony\Component\Config\Definition\Exception\InvalidConfigurationException;
use _ContaoManager\Symfony\Component\Config\Loader\ParamConfigurator;
/**
 * This class is automatically generated to help in creating a config.
 */
class WorkflowsConfig
{
    private $auditTrail;
    private $type;
    private $markingStore;
    private $supports;
    private $supportStrategy;
    private $initialMarking;
    private $eventsToDispatch;
    private $places;
    private $transitions;
    private $metadata;
    private $_usedProperties = [];
    /**
     * @default {"enabled":false}
     */
    public function auditTrail(array $value = []): \_ContaoManager\Symfony\Config\Framework\Workflows\WorkflowsConfig\AuditTrailConfig
    {
        if (null === $this->auditTrail) {
            $this->_usedProperties['auditTrail'] = \true;
            $this->auditTrail = new \_ContaoManager\Symfony\Config\Framework\Workflows\WorkflowsConfig\AuditTrailConfig($value);
        } elseif (0 < \func_num_args()) {
            throw new InvalidConfigurationException('The node created by "auditTrail()" has already been initialized. You cannot pass values the second time you call auditTrail().');
        }
        return $this->auditTrail;
    }
    /**
     * @default 'state_machine'
     * @param ParamConfigurator|'workflow'|'state_machine' $value
     * @return $this
     */
    public function type($value): static
    {
        $this->_usedProperties['type'] = \true;
        $this->type = $value;
        return $this;
    }
    public function markingStore(array $value = []): \_ContaoManager\Symfony\Config\Framework\Workflows\WorkflowsConfig\MarkingStoreConfig
    {
        if (null === $this->markingStore) {
            $this->_usedProperties['markingStore'] = \true;
            $this->markingStore = new \_ContaoManager\Symfony\Config\Framework\Workflows\WorkflowsConfig\MarkingStoreConfig($value);
        } elseif (0 < \func_num_args()) {
            throw new InvalidConfigurationException('The node created by "markingStore()" has already been initialized. You cannot pass values the second time you call markingStore().');
        }
        return $this->markingStore;
    }
    /**
     * @param ParamConfigurator|list<ParamConfigurator|mixed>|string $value
     *
     * @return $this
     */
    public function supports(ParamConfigurator|string|array $value): static
    {
        $this->_usedProperties['supports'] = \true;
        $this->supports = $value;
        return $this;
    }
    /**
     * @default null
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function supportStrategy($value): static
    {
        $this->_usedProperties['supportStrategy'] = \true;
        $this->supportStrategy = $value;
        return $this;
    }
    /**
     * @param ParamConfigurator|list<ParamConfigurator|mixed>|mixed $value
     *
     * @return $this
     */
    public function initialMarking(mixed $value): static
    {
        $this->_usedProperties['initialMarking'] = \true;
        $this->initialMarking = $value;
        return $this;
    }
    /**
     * Select which Transition events should be dispatched for this Workflow
     * @example workflow.enter
     * @example workflow.transition
     * @default null
     * @param ParamConfigurator|mixed $value
     *
     * @return $this
     */
    public function eventsToDispatch(mixed $value = NULL): static
    {
        $this->_usedProperties['eventsToDispatch'] = \true;
        $this->eventsToDispatch = $value;
        return $this;
    }
    /**
     * @template TValue of mixed
     * @param TValue $value
     * @return \Symfony\Config\Framework\Workflows\WorkflowsConfig\PlaceConfig|$this
     * @psalm-return (TValue is array ? \Symfony\Config\Framework\Workflows\WorkflowsConfig\PlaceConfig : static)
     */
    public function place(mixed $value = []): \_ContaoManager\Symfony\Config\Framework\Workflows\WorkflowsConfig\PlaceConfig|static
    {
        $this->_usedProperties['places'] = \true;
        if (!\is_array($value)) {
            $this->places[] = $value;
            return $this;
        }
        return $this->places[] = new \_ContaoManager\Symfony\Config\Framework\Workflows\WorkflowsConfig\PlaceConfig($value);
    }
    /**
     * @template TValue of mixed
     * @param TValue $value
     * @return \Symfony\Config\Framework\Workflows\WorkflowsConfig\TransitionConfig|$this
     * @psalm-return (TValue is array ? \Symfony\Config\Framework\Workflows\WorkflowsConfig\TransitionConfig : static)
     */
    public function transition(mixed $value = []): \_ContaoManager\Symfony\Config\Framework\Workflows\WorkflowsConfig\TransitionConfig|static
    {
        $this->_usedProperties['transitions'] = \true;
        if (!\is_array($value)) {
            $this->transitions[] = $value;
            return $this;
        }
        return $this->transitions[] = new \_ContaoManager\Symfony\Config\Framework\Workflows\WorkflowsConfig\TransitionConfig($value);
    }
    /**
     * @return $this
     */
    public function metadata(string $key, mixed $value): static
    {
        $this->_usedProperties['metadata'] = \true;
        $this->metadata[$key] = $value;
        return $this;
    }
    public function __construct(array $value = [])
    {
        if (array_key_exists('audit_trail', $value)) {
            $this->_usedProperties['auditTrail'] = \true;
            $this->auditTrail = \is_array($value['audit_trail']) ? new \_ContaoManager\Symfony\Config\Framework\Workflows\WorkflowsConfig\AuditTrailConfig($value['audit_trail']) : $value['audit_trail'];
            unset($value['audit_trail']);
        }
        if (array_key_exists('type', $value)) {
            $this->_usedProperties['type'] = \true;
            $this->type = $value['type'];
            unset($value['type']);
        }
        if (array_key_exists('marking_store', $value)) {
            $this->_usedProperties['markingStore'] = \true;
            $this->markingStore = new \_ContaoManager\Symfony\Config\Framework\Workflows\WorkflowsConfig\MarkingStoreConfig($value['marking_store']);
            unset($value['marking_store']);
        }
        if (array_key_exists('supports', $value)) {
            $this->_usedProperties['supports'] = \true;
            $this->supports = $value['supports'];
            unset($value['supports']);
        }
        if (array_key_exists('support_strategy', $value)) {
            $this->_usedProperties['supportStrategy'] = \true;
            $this->supportStrategy = $value['support_strategy'];
            unset($value['support_strategy']);
        }
        if (array_key_exists('initial_marking', $value)) {
            $this->_usedProperties['initialMarking'] = \true;
            $this->initialMarking = $value['initial_marking'];
            unset($value['initial_marking']);
        }
        if (array_key_exists('events_to_dispatch', $value)) {
            $this->_usedProperties['eventsToDispatch'] = \true;
            $this->eventsToDispatch = $value['events_to_dispatch'];
            unset($value['events_to_dispatch']);
        }
        if (array_key_exists('places', $value)) {
            $this->_usedProperties['places'] = \true;
            $this->places = array_map(fn($v) => \is_array($v) ? new \_ContaoManager\Symfony\Config\Framework\Workflows\WorkflowsConfig\PlaceConfig($v) : $v, $value['places']);
            unset($value['places']);
        }
        if (array_key_exists('transitions', $value)) {
            $this->_usedProperties['transitions'] = \true;
            $this->transitions = array_map(fn($v) => \is_array($v) ? new \_ContaoManager\Symfony\Config\Framework\Workflows\WorkflowsConfig\TransitionConfig($v) : $v, $value['transitions']);
            unset($value['transitions']);
        }
        if (array_key_exists('metadata', $value)) {
            $this->_usedProperties['metadata'] = \true;
            $this->metadata = $value['metadata'];
            unset($value['metadata']);
        }
        if ([] !== $value) {
            throw new InvalidConfigurationException(sprintf('The following keys are not supported by "%s": ', __CLASS__) . implode(', ', array_keys($value)));
        }
    }
    public function toArray(): array
    {
        $output = [];
        if (isset($this->_usedProperties['auditTrail'])) {
            $output['audit_trail'] = $this->auditTrail instanceof \_ContaoManager\Symfony\Config\Framework\Workflows\WorkflowsConfig\AuditTrailConfig ? $this->auditTrail->toArray() : $this->auditTrail;
        }
        if (isset($this->_usedProperties['type'])) {
            $output['type'] = $this->type;
        }
        if (isset($this->_usedProperties['markingStore'])) {
            $output['marking_store'] = $this->markingStore->toArray();
        }
        if (isset($this->_usedProperties['supports'])) {
            $output['supports'] = $this->supports;
        }
        if (isset($this->_usedProperties['supportStrategy'])) {
            $output['support_strategy'] = $this->supportStrategy;
        }
        if (isset($this->_usedProperties['initialMarking'])) {
            $output['initial_marking'] = $this->initialMarking;
        }
        if (isset($this->_usedProperties['eventsToDispatch'])) {
            $output['events_to_dispatch'] = $this->eventsToDispatch;
        }
        if (isset($this->_usedProperties['places'])) {
            $output['places'] = array_map(fn($v) => $v instanceof \_ContaoManager\Symfony\Config\Framework\Workflows\WorkflowsConfig\PlaceConfig ? $v->toArray() : $v, $this->places);
        }
        if (isset($this->_usedProperties['transitions'])) {
            $output['transitions'] = array_map(fn($v) => $v instanceof \_ContaoManager\Symfony\Config\Framework\Workflows\WorkflowsConfig\TransitionConfig ? $v->toArray() : $v, $this->transitions);
        }
        if (isset($this->_usedProperties['metadata'])) {
            $output['metadata'] = $this->metadata;
        }
        return $output;
    }
}
<?php

namespace _ContaoManager\Symfony\Config\Framework\Workflows\WorkflowsConfig;

use _ContaoManager\Symfony\Component\Config\Loader\ParamConfigurator;
use _ContaoManager\Symfony\Component\Config\Definition\Exception\InvalidConfigurationException;
/**
 * This class is automatically generated to help in creating a config.
 */
class AuditTrailConfig
{
    private $enabled;
    private $_usedProperties = [];
    /**
     * @default false
     * @param ParamConfigurator|bool $value
     * @return $this
     */
    public function enabled($value): static
    {
        $this->_usedProperties['enabled'] = \true;
        $this->enabled = $value;
        return $this;
    }
    public function __construct(array $value = [])
    {
        if (array_key_exists('enabled', $value)) {
            $this->_usedProperties['enabled'] = \true;
            $this->enabled = $value['enabled'];
            unset($value['enabled']);
        }
        if ([] !== $value) {
            throw new InvalidConfigurationException(sprintf('The following keys are not supported by "%s": ', __CLASS__) . implode(', ', array_keys($value)));
        }
    }
    public function toArray(): array
    {
        $output = [];
        if (isset($this->_usedProperties['enabled'])) {
            $output['enabled'] = $this->enabled;
        }
        return $output;
    }
}
<?php

namespace _ContaoManager\Symfony\Config\Framework\Workflows\WorkflowsConfig;

use _ContaoManager\Symfony\Component\Config\Loader\ParamConfigurator;
use _ContaoManager\Symfony\Component\Config\Definition\Exception\InvalidConfigurationException;
/**
 * This class is automatically generated to help in creating a config.
 */
class MarkingStoreConfig
{
    private $type;
    private $property;
    private $service;
    private $_usedProperties = [];
    /**
     * @default null
     * @param ParamConfigurator|'method' $value
     * @return $this
     */
    public function type($value): static
    {
        $this->_usedProperties['type'] = \true;
        $this->type = $value;
        return $this;
    }
    /**
     * @default null
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function property($value): static
    {
        $this->_usedProperties['property'] = \true;
        $this->property = $value;
        return $this;
    }
    /**
     * @default null
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function service($value): static
    {
        $this->_usedProperties['service'] = \true;
        $this->service = $value;
        return $this;
    }
    public function __construct(array $value = [])
    {
        if (array_key_exists('type', $value)) {
            $this->_usedProperties['type'] = \true;
            $this->type = $value['type'];
            unset($value['type']);
        }
        if (array_key_exists('property', $value)) {
            $this->_usedProperties['property'] = \true;
            $this->property = $value['property'];
            unset($value['property']);
        }
        if (array_key_exists('service', $value)) {
            $this->_usedProperties['service'] = \true;
            $this->service = $value['service'];
            unset($value['service']);
        }
        if ([] !== $value) {
            throw new InvalidConfigurationException(sprintf('The following keys are not supported by "%s": ', __CLASS__) . implode(', ', array_keys($value)));
        }
    }
    public function toArray(): array
    {
        $output = [];
        if (isset($this->_usedProperties['type'])) {
            $output['type'] = $this->type;
        }
        if (isset($this->_usedProperties['property'])) {
            $output['property'] = $this->property;
        }
        if (isset($this->_usedProperties['service'])) {
            $output['service'] = $this->service;
        }
        return $output;
    }
}
<?php

namespace _ContaoManager\Symfony\Config\Framework\Workflows\WorkflowsConfig;

use _ContaoManager\Symfony\Component\Config\Loader\ParamConfigurator;
use _ContaoManager\Symfony\Component\Config\Definition\Exception\InvalidConfigurationException;
/**
 * This class is automatically generated to help in creating a config.
 */
class TransitionConfig
{
    private $name;
    private $guard;
    private $from;
    private $to;
    private $metadata;
    private $_usedProperties = [];
    /**
     * @default null
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function name($value): static
    {
        $this->_usedProperties['name'] = \true;
        $this->name = $value;
        return $this;
    }
    /**
     * An expression to block the transition
     * @example is_fully_authenticated() and is_granted('ROLE_JOURNALIST') and subject.getTitle() == 'My first article'
     * @default null
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function guard($value): static
    {
        $this->_usedProperties['guard'] = \true;
        $this->guard = $value;
        return $this;
    }
    /**
     * @param ParamConfigurator|list<ParamConfigurator|mixed>|string $value
     *
     * @return $this
     */
    public function from(ParamConfigurator|string|array $value): static
    {
        $this->_usedProperties['from'] = \true;
        $this->from = $value;
        return $this;
    }
    /**
     * @param ParamConfigurator|list<ParamConfigurator|mixed>|string $value
     *
     * @return $this
     */
    public function to(ParamConfigurator|string|array $value): static
    {
        $this->_usedProperties['to'] = \true;
        $this->to = $value;
        return $this;
    }
    /**
     * @return $this
     */
    public function metadata(string $key, mixed $value): static
    {
        $this->_usedProperties['metadata'] = \true;
        $this->metadata[$key] = $value;
        return $this;
    }
    public function __construct(array $value = [])
    {
        if (array_key_exists('name', $value)) {
            $this->_usedProperties['name'] = \true;
            $this->name = $value['name'];
            unset($value['name']);
        }
        if (array_key_exists('guard', $value)) {
            $this->_usedProperties['guard'] = \true;
            $this->guard = $value['guard'];
            unset($value['guard']);
        }
        if (array_key_exists('from', $value)) {
            $this->_usedProperties['from'] = \true;
            $this->from = $value['from'];
            unset($value['from']);
        }
        if (array_key_exists('to', $value)) {
            $this->_usedProperties['to'] = \true;
            $this->to = $value['to'];
            unset($value['to']);
        }
        if (array_key_exists('metadata', $value)) {
            $this->_usedProperties['metadata'] = \true;
            $this->metadata = $value['metadata'];
            unset($value['metadata']);
        }
        if ([] !== $value) {
            throw new InvalidConfigurationException(sprintf('The following keys are not supported by "%s": ', __CLASS__) . implode(', ', array_keys($value)));
        }
    }
    public function toArray(): array
    {
        $output = [];
        if (isset($this->_usedProperties['name'])) {
            $output['name'] = $this->name;
        }
        if (isset($this->_usedProperties['guard'])) {
            $output['guard'] = $this->guard;
        }
        if (isset($this->_usedProperties['from'])) {
            $output['from'] = $this->from;
        }
        if (isset($this->_usedProperties['to'])) {
            $output['to'] = $this->to;
        }
        if (isset($this->_usedProperties['metadata'])) {
            $output['metadata'] = $this->metadata;
        }
        return $output;
    }
}
<?php

namespace _ContaoManager\Symfony\Config\Framework\Workflows\WorkflowsConfig;

use _ContaoManager\Symfony\Component\Config\Loader\ParamConfigurator;
use _ContaoManager\Symfony\Component\Config\Definition\Exception\InvalidConfigurationException;
/**
 * This class is automatically generated to help in creating a config.
 */
class PlaceConfig
{
    private $name;
    private $metadata;
    private $_usedProperties = [];
    /**
     * @default null
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function name($value): static
    {
        $this->_usedProperties['name'] = \true;
        $this->name = $value;
        return $this;
    }
    /**
     * @return $this
     */
    public function metadata(string $key, mixed $value): static
    {
        $this->_usedProperties['metadata'] = \true;
        $this->metadata[$key] = $value;
        return $this;
    }
    public function __construct(array $value = [])
    {
        if (array_key_exists('name', $value)) {
            $this->_usedProperties['name'] = \true;
            $this->name = $value['name'];
            unset($value['name']);
        }
        if (array_key_exists('metadata', $value)) {
            $this->_usedProperties['metadata'] = \true;
            $this->metadata = $value['metadata'];
            unset($value['metadata']);
        }
        if ([] !== $value) {
            throw new InvalidConfigurationException(sprintf('The following keys are not supported by "%s": ', __CLASS__) . implode(', ', array_keys($value)));
        }
    }
    public function toArray(): array
    {
        $output = [];
        if (isset($this->_usedProperties['name'])) {
            $output['name'] = $this->name;
        }
        if (isset($this->_usedProperties['metadata'])) {
            $output['metadata'] = $this->metadata;
        }
        return $output;
    }
}
<?php

namespace _ContaoManager\Symfony\Config\Framework;

use _ContaoManager\Symfony\Component\Config\Loader\ParamConfigurator;
use _ContaoManager\Symfony\Component\Config\Definition\Exception\InvalidConfigurationException;
/**
 * This class is automatically generated to help in creating a config.
 */
class EsiConfig
{
    private $enabled;
    private $_usedProperties = [];
    /**
     * @default false
     * @param ParamConfigurator|bool $value
     * @return $this
     */
    public function enabled($value): static
    {
        $this->_usedProperties['enabled'] = \true;
        $this->enabled = $value;
        return $this;
    }
    public function __construct(array $value = [])
    {
        if (array_key_exists('enabled', $value)) {
            $this->_usedProperties['enabled'] = \true;
            $this->enabled = $value['enabled'];
            unset($value['enabled']);
        }
        if ([] !== $value) {
            throw new InvalidConfigurationException(sprintf('The following keys are not supported by "%s": ', __CLASS__) . implode(', ', array_keys($value)));
        }
    }
    public function toArray(): array
    {
        $output = [];
        if (isset($this->_usedProperties['enabled'])) {
            $output['enabled'] = $this->enabled;
        }
        return $output;
    }
}
<?php

namespace _ContaoManager\Symfony\Config\Framework;

use _ContaoManager\Symfony\Component\Config\Loader\ParamConfigurator;
use _ContaoManager\Symfony\Component\Config\Definition\Exception\InvalidConfigurationException;
/**
 * This class is automatically generated to help in creating a config.
 */
class WebLinkConfig
{
    private $enabled;
    private $_usedProperties = [];
    /**
     * @default false
     * @param ParamConfigurator|bool $value
     * @return $this
     */
    public function enabled($value): static
    {
        $this->_usedProperties['enabled'] = \true;
        $this->enabled = $value;
        return $this;
    }
    public function __construct(array $value = [])
    {
        if (array_key_exists('enabled', $value)) {
            $this->_usedProperties['enabled'] = \true;
            $this->enabled = $value['enabled'];
            unset($value['enabled']);
        }
        if ([] !== $value) {
            throw new InvalidConfigurationException(sprintf('The following keys are not supported by "%s": ', __CLASS__) . implode(', ', array_keys($value)));
        }
    }
    public function toArray(): array
    {
        $output = [];
        if (isset($this->_usedProperties['enabled'])) {
            $output['enabled'] = $this->enabled;
        }
        return $output;
    }
}
<?php

namespace _ContaoManager\Symfony\Config\Framework\Mailer;

use _ContaoManager\Symfony\Component\Config\Loader\ParamConfigurator;
use _ContaoManager\Symfony\Component\Config\Definition\Exception\InvalidConfigurationException;
/**
 * This class is automatically generated to help in creating a config.
 */
class EnvelopeConfig
{
    private $sender;
    private $recipients;
    private $_usedProperties = [];
    /**
     * @default null
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function sender($value): static
    {
        $this->_usedProperties['sender'] = \true;
        $this->sender = $value;
        return $this;
    }
    /**
     * @param ParamConfigurator|list<ParamConfigurator|mixed> $value
     *
     * @return $this
     */
    public function recipients(ParamConfigurator|array $value): static
    {
        $this->_usedProperties['recipients'] = \true;
        $this->recipients = $value;
        return $this;
    }
    public function __construct(array $value = [])
    {
        if (array_key_exists('sender', $value)) {
            $this->_usedProperties['sender'] = \true;
            $this->sender = $value['sender'];
            unset($value['sender']);
        }
        if (array_key_exists('recipients', $value)) {
            $this->_usedProperties['recipients'] = \true;
            $this->recipients = $value['recipients'];
            unset($value['recipients']);
        }
        if ([] !== $value) {
            throw new InvalidConfigurationException(sprintf('The following keys are not supported by "%s": ', __CLASS__) . implode(', ', array_keys($value)));
        }
    }
    public function toArray(): array
    {
        $output = [];
        if (isset($this->_usedProperties['sender'])) {
            $output['sender'] = $this->sender;
        }
        if (isset($this->_usedProperties['recipients'])) {
            $output['recipients'] = $this->recipients;
        }
        return $output;
    }
}
<?php

namespace _ContaoManager\Symfony\Config\Framework\Mailer;

use _ContaoManager\Symfony\Component\Config\Loader\ParamConfigurator;
use _ContaoManager\Symfony\Component\Config\Definition\Exception\InvalidConfigurationException;
/**
 * This class is automatically generated to help in creating a config.
 */
class HeaderConfig
{
    private $value;
    private $_usedProperties = [];
    /**
     * @default null
     * @param ParamConfigurator|mixed $value
     *
     * @return $this
     */
    public function value(mixed $value): static
    {
        $this->_usedProperties['value'] = \true;
        $this->value = $value;
        return $this;
    }
    public function __construct(array $value = [])
    {
        if (array_key_exists('value', $value)) {
            $this->_usedProperties['value'] = \true;
            $this->value = $value['value'];
            unset($value['value']);
        }
        if ([] !== $value) {
            throw new InvalidConfigurationException(sprintf('The following keys are not supported by "%s": ', __CLASS__) . implode(', ', array_keys($value)));
        }
    }
    public function toArray(): array
    {
        $output = [];
        if (isset($this->_usedProperties['value'])) {
            $output['value'] = $this->value;
        }
        return $output;
    }
}
<?php

namespace _ContaoManager\Symfony\Config\Framework;

use _ContaoManager\Symfony\Component\Config\Loader\ParamConfigurator;
use _ContaoManager\Symfony\Component\Config\Definition\Exception\InvalidConfigurationException;
/**
 * This class is automatically generated to help in creating a config.
 */
class SsiConfig
{
    private $enabled;
    private $_usedProperties = [];
    /**
     * @default false
     * @param ParamConfigurator|bool $value
     * @return $this
     */
    public function enabled($value): static
    {
        $this->_usedProperties['enabled'] = \true;
        $this->enabled = $value;
        return $this;
    }
    public function __construct(array $value = [])
    {
        if (array_key_exists('enabled', $value)) {
            $this->_usedProperties['enabled'] = \true;
            $this->enabled = $value['enabled'];
            unset($value['enabled']);
        }
        if ([] !== $value) {
            throw new InvalidConfigurationException(sprintf('The following keys are not supported by "%s": ', __CLASS__) . implode(', ', array_keys($value)));
        }
    }
    public function toArray(): array
    {
        $output = [];
        if (isset($this->_usedProperties['enabled'])) {
            $output['enabled'] = $this->enabled;
        }
        return $output;
    }
}
<?php

namespace _ContaoManager\Symfony\Config\Framework\Translator;

use _ContaoManager\Symfony\Component\Config\Loader\ParamConfigurator;
use _ContaoManager\Symfony\Component\Config\Definition\Exception\InvalidConfigurationException;
/**
 * This class is automatically generated to help in creating a config.
 */
class PseudoLocalizationConfig
{
    private $enabled;
    private $accents;
    private $expansionFactor;
    private $brackets;
    private $parseHtml;
    private $localizableHtmlAttributes;
    private $_usedProperties = [];
    /**
     * @default false
     * @param ParamConfigurator|bool $value
     * @return $this
     */
    public function enabled($value): static
    {
        $this->_usedProperties['enabled'] = \true;
        $this->enabled = $value;
        return $this;
    }
    /**
     * @default true
     * @param ParamConfigurator|bool $value
     * @return $this
     */
    public function accents($value): static
    {
        $this->_usedProperties['accents'] = \true;
        $this->accents = $value;
        return $this;
    }
    /**
     * @default 1.0
     * @param ParamConfigurator|float $value
     * @return $this
     */
    public function expansionFactor($value): static
    {
        $this->_usedProperties['expansionFactor'] = \true;
        $this->expansionFactor = $value;
        return $this;
    }
    /**
     * @default true
     * @param ParamConfigurator|bool $value
     * @return $this
     */
    public function brackets($value): static
    {
        $this->_usedProperties['brackets'] = \true;
        $this->brackets = $value;
        return $this;
    }
    /**
     * @default false
     * @param ParamConfigurator|bool $value
     * @return $this
     */
    public function parseHtml($value): static
    {
        $this->_usedProperties['parseHtml'] = \true;
        $this->parseHtml = $value;
        return $this;
    }
    /**
     * @param ParamConfigurator|list<ParamConfigurator|mixed> $value
     *
     * @return $this
     */
    public function localizableHtmlAttributes(ParamConfigurator|array $value): static
    {
        $this->_usedProperties['localizableHtmlAttributes'] = \true;
        $this->localizableHtmlAttributes = $value;
        return $this;
    }
    public function __construct(array $value = [])
    {
        if (array_key_exists('enabled', $value)) {
            $this->_usedProperties['enabled'] = \true;
            $this->enabled = $value['enabled'];
            unset($value['enabled']);
        }
        if (array_key_exists('accents', $value)) {
            $this->_usedProperties['accents'] = \true;
            $this->accents = $value['accents'];
            unset($value['accents']);
        }
        if (array_key_exists('expansion_factor', $value)) {
            $this->_usedProperties['expansionFactor'] = \true;
            $this->expansionFactor = $value['expansion_factor'];
            unset($value['expansion_factor']);
        }
        if (array_key_exists('brackets', $value)) {
            $this->_usedProperties['brackets'] = \true;
            $this->brackets = $value['brackets'];
            unset($value['brackets']);
        }
        if (array_key_exists('parse_html', $value)) {
            $this->_usedProperties['parseHtml'] = \true;
            $this->parseHtml = $value['parse_html'];
            unset($value['parse_html']);
        }
        if (array_key_exists('localizable_html_attributes', $value)) {
            $this->_usedProperties['localizableHtmlAttributes'] = \true;
            $this->localizableHtmlAttributes = $value['localizable_html_attributes'];
            unset($value['localizable_html_attributes']);
        }
        if ([] !== $value) {
            throw new InvalidConfigurationException(sprintf('The following keys are not supported by "%s": ', __CLASS__) . implode(', ', array_keys($value)));
        }
    }
    public function toArray(): array
    {
        $output = [];
        if (isset($this->_usedProperties['enabled'])) {
            $output['enabled'] = $this->enabled;
        }
        if (isset($this->_usedProperties['accents'])) {
            $output['accents'] = $this->accents;
        }
        if (isset($this->_usedProperties['expansionFactor'])) {
            $output['expansion_factor'] = $this->expansionFactor;
        }
        if (isset($this->_usedProperties['brackets'])) {
            $output['brackets'] = $this->brackets;
        }
        if (isset($this->_usedProperties['parseHtml'])) {
            $output['parse_html'] = $this->parseHtml;
        }
        if (isset($this->_usedProperties['localizableHtmlAttributes'])) {
            $output['localizable_html_attributes'] = $this->localizableHtmlAttributes;
        }
        return $output;
    }
}
<?php

namespace _ContaoManager\Symfony\Config\Framework\Translator;

use _ContaoManager\Symfony\Component\Config\Loader\ParamConfigurator;
use _ContaoManager\Symfony\Component\Config\Definition\Exception\InvalidConfigurationException;
/**
 * This class is automatically generated to help in creating a config.
 */
class ProviderConfig
{
    private $dsn;
    private $domains;
    private $locales;
    private $_usedProperties = [];
    /**
     * @default null
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function dsn($value): static
    {
        $this->_usedProperties['dsn'] = \true;
        $this->dsn = $value;
        return $this;
    }
    /**
     * @param ParamConfigurator|list<ParamConfigurator|mixed> $value
     *
     * @return $this
     */
    public function domains(ParamConfigurator|array $value): static
    {
        $this->_usedProperties['domains'] = \true;
        $this->domains = $value;
        return $this;
    }
    /**
     * @param ParamConfigurator|list<ParamConfigurator|mixed> $value
     *
     * @return $this
     */
    public function locales(ParamConfigurator|array $value): static
    {
        $this->_usedProperties['locales'] = \true;
        $this->locales = $value;
        return $this;
    }
    public function __construct(array $value = [])
    {
        if (array_key_exists('dsn', $value)) {
            $this->_usedProperties['dsn'] = \true;
            $this->dsn = $value['dsn'];
            unset($value['dsn']);
        }
        if (array_key_exists('domains', $value)) {
            $this->_usedProperties['domains'] = \true;
            $this->domains = $value['domains'];
            unset($value['domains']);
        }
        if (array_key_exists('locales', $value)) {
            $this->_usedProperties['locales'] = \true;
            $this->locales = $value['locales'];
            unset($value['locales']);
        }
        if ([] !== $value) {
            throw new InvalidConfigurationException(sprintf('The following keys are not supported by "%s": ', __CLASS__) . implode(', ', array_keys($value)));
        }
    }
    public function toArray(): array
    {
        $output = [];
        if (isset($this->_usedProperties['dsn'])) {
            $output['dsn'] = $this->dsn;
        }
        if (isset($this->_usedProperties['domains'])) {
            $output['domains'] = $this->domains;
        }
        if (isset($this->_usedProperties['locales'])) {
            $output['locales'] = $this->locales;
        }
        return $output;
    }
}
<?php

namespace _ContaoManager\Symfony\Config\Framework;

use _ContaoManager\Symfony\Component\Config\Loader\ParamConfigurator;
use _ContaoManager\Symfony\Component\Config\Definition\Exception\InvalidConfigurationException;
/**
 * This class is automatically generated to help in creating a config.
 */
class ProfilerConfig
{
    private $enabled;
    private $collect;
    private $collectParameter;
    private $onlyExceptions;
    private $onlyMainRequests;
    private $dsn;
    private $collectSerializerData;
    private $_usedProperties = [];
    /**
     * @default false
     * @param ParamConfigurator|bool $value
     * @return $this
     */
    public function enabled($value): static
    {
        $this->_usedProperties['enabled'] = \true;
        $this->enabled = $value;
        return $this;
    }
    /**
     * @default true
     * @param ParamConfigurator|bool $value
     * @return $this
     */
    public function collect($value): static
    {
        $this->_usedProperties['collect'] = \true;
        $this->collect = $value;
        return $this;
    }
    /**
     * The name of the parameter to use to enable or disable collection on a per request basis
     * @default null
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function collectParameter($value): static
    {
        $this->_usedProperties['collectParameter'] = \true;
        $this->collectParameter = $value;
        return $this;
    }
    /**
     * @default false
     * @param ParamConfigurator|bool $value
     * @return $this
     */
    public function onlyExceptions($value): static
    {
        $this->_usedProperties['onlyExceptions'] = \true;
        $this->onlyExceptions = $value;
        return $this;
    }
    /**
     * @default false
     * @param ParamConfigurator|bool $value
     * @return $this
     */
    public function onlyMainRequests($value): static
    {
        $this->_usedProperties['onlyMainRequests'] = \true;
        $this->onlyMainRequests = $value;
        return $this;
    }
    /**
     * @default 'file:%kernel.cache_dir%/profiler'
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function dsn($value): static
    {
        $this->_usedProperties['dsn'] = \true;
        $this->dsn = $value;
        return $this;
    }
    /**
     * Enables the serializer data collector and profiler panel
     * @default false
     * @param ParamConfigurator|bool $value
     * @return $this
     */
    public function collectSerializerData($value): static
    {
        $this->_usedProperties['collectSerializerData'] = \true;
        $this->collectSerializerData = $value;
        return $this;
    }
    public function __construct(array $value = [])
    {
        if (array_key_exists('enabled', $value)) {
            $this->_usedProperties['enabled'] = \true;
            $this->enabled = $value['enabled'];
            unset($value['enabled']);
        }
        if (array_key_exists('collect', $value)) {
            $this->_usedProperties['collect'] = \true;
            $this->collect = $value['collect'];
            unset($value['collect']);
        }
        if (array_key_exists('collect_parameter', $value)) {
            $this->_usedProperties['collectParameter'] = \true;
            $this->collectParameter = $value['collect_parameter'];
            unset($value['collect_parameter']);
        }
        if (array_key_exists('only_exceptions', $value)) {
            $this->_usedProperties['onlyExceptions'] = \true;
            $this->onlyExceptions = $value['only_exceptions'];
            unset($value['only_exceptions']);
        }
        if (array_key_exists('only_main_requests', $value)) {
            $this->_usedProperties['onlyMainRequests'] = \true;
            $this->onlyMainRequests = $value['only_main_requests'];
            unset($value['only_main_requests']);
        }
        if (array_key_exists('dsn', $value)) {
            $this->_usedProperties['dsn'] = \true;
            $this->dsn = $value['dsn'];
            unset($value['dsn']);
        }
        if (array_key_exists('collect_serializer_data', $value)) {
            $this->_usedProperties['collectSerializerData'] = \true;
            $this->collectSerializerData = $value['collect_serializer_data'];
            unset($value['collect_serializer_data']);
        }
        if ([] !== $value) {
            throw new InvalidConfigurationException(sprintf('The following keys are not supported by "%s": ', __CLASS__) . implode(', ', array_keys($value)));
        }
    }
    public function toArray(): array
    {
        $output = [];
        if (isset($this->_usedProperties['enabled'])) {
            $output['enabled'] = $this->enabled;
        }
        if (isset($this->_usedProperties['collect'])) {
            $output['collect'] = $this->collect;
        }
        if (isset($this->_usedProperties['collectParameter'])) {
            $output['collect_parameter'] = $this->collectParameter;
        }
        if (isset($this->_usedProperties['onlyExceptions'])) {
            $output['only_exceptions'] = $this->onlyExceptions;
        }
        if (isset($this->_usedProperties['onlyMainRequests'])) {
            $output['only_main_requests'] = $this->onlyMainRequests;
        }
        if (isset($this->_usedProperties['dsn'])) {
            $output['dsn'] = $this->dsn;
        }
        if (isset($this->_usedProperties['collectSerializerData'])) {
            $output['collect_serializer_data'] = $this->collectSerializerData;
        }
        return $output;
    }
}
<?php

namespace _ContaoManager\Symfony\Config\Framework;

use _ContaoManager\Symfony\Component\Config\Loader\ParamConfigurator;
use _ContaoManager\Symfony\Component\Config\Definition\Exception\InvalidConfigurationException;
/**
 * This class is automatically generated to help in creating a config.
 */
class SemaphoreConfig
{
    private $enabled;
    private $resources;
    private $_usedProperties = [];
    /**
     * @default false
     * @param ParamConfigurator|bool $value
     * @return $this
     */
    public function enabled($value): static
    {
        $this->_usedProperties['enabled'] = \true;
        $this->enabled = $value;
        return $this;
    }
    /**
     * @return $this
     */
    public function resource(string $name, mixed $value): static
    {
        $this->_usedProperties['resources'] = \true;
        $this->resources[$name] = $value;
        return $this;
    }
    public function __construct(array $value = [])
    {
        if (array_key_exists('enabled', $value)) {
            $this->_usedProperties['enabled'] = \true;
            $this->enabled = $value['enabled'];
            unset($value['enabled']);
        }
        if (array_key_exists('resources', $value)) {
            $this->_usedProperties['resources'] = \true;
            $this->resources = $value['resources'];
            unset($value['resources']);
        }
        if ([] !== $value) {
            throw new InvalidConfigurationException(sprintf('The following keys are not supported by "%s": ', __CLASS__) . implode(', ', array_keys($value)));
        }
    }
    public function toArray(): array
    {
        $output = [];
        if (isset($this->_usedProperties['enabled'])) {
            $output['enabled'] = $this->enabled;
        }
        if (isset($this->_usedProperties['resources'])) {
            $output['resources'] = $this->resources;
        }
        return $output;
    }
}
<?php

namespace _ContaoManager\Symfony\Config\Framework;

use _ContaoManager\Symfony\Component\Config\Loader\ParamConfigurator;
use _ContaoManager\Symfony\Component\Config\Definition\Exception\InvalidConfigurationException;
/**
 * This class is automatically generated to help in creating a config.
 */
class SecretsConfig
{
    private $enabled;
    private $vaultDirectory;
    private $localDotenvFile;
    private $decryptionEnvVar;
    private $_usedProperties = [];
    /**
     * @default true
     * @param ParamConfigurator|bool $value
     * @return $this
     */
    public function enabled($value): static
    {
        $this->_usedProperties['enabled'] = \true;
        $this->enabled = $value;
        return $this;
    }
    /**
     * @default '%kernel.project_dir%/config/secrets/%kernel.runtime_environment%'
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function vaultDirectory($value): static
    {
        $this->_usedProperties['vaultDirectory'] = \true;
        $this->vaultDirectory = $value;
        return $this;
    }
    /**
     * @default '%kernel.project_dir%/.env.%kernel.environment%.local'
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function localDotenvFile($value): static
    {
        $this->_usedProperties['localDotenvFile'] = \true;
        $this->localDotenvFile = $value;
        return $this;
    }
    /**
     * @default 'base64:default::SYMFONY_DECRYPTION_SECRET'
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function decryptionEnvVar($value): static
    {
        $this->_usedProperties['decryptionEnvVar'] = \true;
        $this->decryptionEnvVar = $value;
        return $this;
    }
    public function __construct(array $value = [])
    {
        if (array_key_exists('enabled', $value)) {
            $this->_usedProperties['enabled'] = \true;
            $this->enabled = $value['enabled'];
            unset($value['enabled']);
        }
        if (array_key_exists('vault_directory', $value)) {
            $this->_usedProperties['vaultDirectory'] = \true;
            $this->vaultDirectory = $value['vault_directory'];
            unset($value['vault_directory']);
        }
        if (array_key_exists('local_dotenv_file', $value)) {
            $this->_usedProperties['localDotenvFile'] = \true;
            $this->localDotenvFile = $value['local_dotenv_file'];
            unset($value['local_dotenv_file']);
        }
        if (array_key_exists('decryption_env_var', $value)) {
            $this->_usedProperties['decryptionEnvVar'] = \true;
            $this->decryptionEnvVar = $value['decryption_env_var'];
            unset($value['decryption_env_var']);
        }
        if ([] !== $value) {
            throw new InvalidConfigurationException(sprintf('The following keys are not supported by "%s": ', __CLASS__) . implode(', ', array_keys($value)));
        }
    }
    public function toArray(): array
    {
        $output = [];
        if (isset($this->_usedProperties['enabled'])) {
            $output['enabled'] = $this->enabled;
        }
        if (isset($this->_usedProperties['vaultDirectory'])) {
            $output['vault_directory'] = $this->vaultDirectory;
        }
        if (isset($this->_usedProperties['localDotenvFile'])) {
            $output['local_dotenv_file'] = $this->localDotenvFile;
        }
        if (isset($this->_usedProperties['decryptionEnvVar'])) {
            $output['decryption_env_var'] = $this->decryptionEnvVar;
        }
        return $output;
    }
}
<?php

namespace _ContaoManager\Symfony\Config\Framework;

use _ContaoManager\Symfony\Component\Config\Loader\ParamConfigurator;
use _ContaoManager\Symfony\Component\Config\Definition\Exception\InvalidConfigurationException;
/**
 * This class is automatically generated to help in creating a config.
 */
class PropertyAccessConfig
{
    private $enabled;
    private $magicCall;
    private $magicGet;
    private $magicSet;
    private $throwExceptionOnInvalidIndex;
    private $throwExceptionOnInvalidPropertyPath;
    private $_usedProperties = [];
    /**
     * @default true
     * @param ParamConfigurator|bool $value
     * @return $this
     */
    public function enabled($value): static
    {
        $this->_usedProperties['enabled'] = \true;
        $this->enabled = $value;
        return $this;
    }
    /**
     * @default false
     * @param ParamConfigurator|bool $value
     * @return $this
     */
    public function magicCall($value): static
    {
        $this->_usedProperties['magicCall'] = \true;
        $this->magicCall = $value;
        return $this;
    }
    /**
     * @default true
     * @param ParamConfigurator|bool $value
     * @return $this
     */
    public function magicGet($value): static
    {
        $this->_usedProperties['magicGet'] = \true;
        $this->magicGet = $value;
        return $this;
    }
    /**
     * @default true
     * @param ParamConfigurator|bool $value
     * @return $this
     */
    public function magicSet($value): static
    {
        $this->_usedProperties['magicSet'] = \true;
        $this->magicSet = $value;
        return $this;
    }
    /**
     * @default false
     * @param ParamConfigurator|bool $value
     * @return $this
     */
    public function throwExceptionOnInvalidIndex($value): static
    {
        $this->_usedProperties['throwExceptionOnInvalidIndex'] = \true;
        $this->throwExceptionOnInvalidIndex = $value;
        return $this;
    }
    /**
     * @default true
     * @param ParamConfigurator|bool $value
     * @return $this
     */
    public function throwExceptionOnInvalidPropertyPath($value): static
    {
        $this->_usedProperties['throwExceptionOnInvalidPropertyPath'] = \true;
        $this->throwExceptionOnInvalidPropertyPath = $value;
        return $this;
    }
    public function __construct(array $value = [])
    {
        if (array_key_exists('enabled', $value)) {
            $this->_usedProperties['enabled'] = \true;
            $this->enabled = $value['enabled'];
            unset($value['enabled']);
        }
        if (array_key_exists('magic_call', $value)) {
            $this->_usedProperties['magicCall'] = \true;
            $this->magicCall = $value['magic_call'];
            unset($value['magic_call']);
        }
        if (array_key_exists('magic_get', $value)) {
            $this->_usedProperties['magicGet'] = \true;
            $this->magicGet = $value['magic_get'];
            unset($value['magic_get']);
        }
        if (array_key_exists('magic_set', $value)) {
            $this->_usedProperties['magicSet'] = \true;
            $this->magicSet = $value['magic_set'];
            unset($value['magic_set']);
        }
        if (array_key_exists('throw_exception_on_invalid_index', $value)) {
            $this->_usedProperties['throwExceptionOnInvalidIndex'] = \true;
            $this->throwExceptionOnInvalidIndex = $value['throw_exception_on_invalid_index'];
            unset($value['throw_exception_on_invalid_index']);
        }
        if (array_key_exists('throw_exception_on_invalid_property_path', $value)) {
            $this->_usedProperties['throwExceptionOnInvalidPropertyPath'] = \true;
            $this->throwExceptionOnInvalidPropertyPath = $value['throw_exception_on_invalid_property_path'];
            unset($value['throw_exception_on_invalid_property_path']);
        }
        if ([] !== $value) {
            throw new InvalidConfigurationException(sprintf('The following keys are not supported by "%s": ', __CLASS__) . implode(', ', array_keys($value)));
        }
    }
    public function toArray(): array
    {
        $output = [];
        if (isset($this->_usedProperties['enabled'])) {
            $output['enabled'] = $this->enabled;
        }
        if (isset($this->_usedProperties['magicCall'])) {
            $output['magic_call'] = $this->magicCall;
        }
        if (isset($this->_usedProperties['magicGet'])) {
            $output['magic_get'] = $this->magicGet;
        }
        if (isset($this->_usedProperties['magicSet'])) {
            $output['magic_set'] = $this->magicSet;
        }
        if (isset($this->_usedProperties['throwExceptionOnInvalidIndex'])) {
            $output['throw_exception_on_invalid_index'] = $this->throwExceptionOnInvalidIndex;
        }
        if (isset($this->_usedProperties['throwExceptionOnInvalidPropertyPath'])) {
            $output['throw_exception_on_invalid_property_path'] = $this->throwExceptionOnInvalidPropertyPath;
        }
        return $output;
    }
}
<?php

namespace _ContaoManager\Symfony\Config\Framework\Messenger;

require_once __DIR__ . \DIRECTORY_SEPARATOR . 'TransportConfig' . \DIRECTORY_SEPARATOR . 'RetryStrategyConfig.php';
use _ContaoManager\Symfony\Component\Config\Loader\ParamConfigurator;
use _ContaoManager\Symfony\Component\Config\Definition\Exception\InvalidConfigurationException;
/**
 * This class is automatically generated to help in creating a config.
 */
class TransportConfig
{
    private $dsn;
    private $serializer;
    private $options;
    private $failureTransport;
    private $retryStrategy;
    private $rateLimiter;
    private $_usedProperties = [];
    /**
     * @default null
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function dsn($value): static
    {
        $this->_usedProperties['dsn'] = \true;
        $this->dsn = $value;
        return $this;
    }
    /**
     * Service id of a custom serializer to use.
     * @default null
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function serializer($value): static
    {
        $this->_usedProperties['serializer'] = \true;
        $this->serializer = $value;
        return $this;
    }
    /**
     * @return $this
     */
    public function option(string $key, mixed $value): static
    {
        $this->_usedProperties['options'] = \true;
        $this->options[$key] = $value;
        return $this;
    }
    /**
     * Transport name to send failed messages to (after all retries have failed).
     * @default null
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function failureTransport($value): static
    {
        $this->_usedProperties['failureTransport'] = \true;
        $this->failureTransport = $value;
        return $this;
    }
    /**
     * @template TValue of mixed
     * @param TValue $value
     * @default {"service":null,"max_retries":3,"delay":1000,"multiplier":2,"max_delay":0}
     * @return \Symfony\Config\Framework\Messenger\TransportConfig\RetryStrategyConfig|$this
     * @psalm-return (TValue is array ? \Symfony\Config\Framework\Messenger\TransportConfig\RetryStrategyConfig : static)
     */
    public function retryStrategy(mixed $value = []): \_ContaoManager\Symfony\Config\Framework\Messenger\TransportConfig\RetryStrategyConfig|static
    {
        if (!\is_array($value)) {
            $this->_usedProperties['retryStrategy'] = \true;
            $this->retryStrategy = $value;
            return $this;
        }
        if (!$this->retryStrategy instanceof \_ContaoManager\Symfony\Config\Framework\Messenger\TransportConfig\RetryStrategyConfig) {
            $this->_usedProperties['retryStrategy'] = \true;
            $this->retryStrategy = new \_ContaoManager\Symfony\Config\Framework\Messenger\TransportConfig\RetryStrategyConfig($value);
        } elseif (0 < \func_num_args()) {
            throw new InvalidConfigurationException('The node created by "retryStrategy()" has already been initialized. You cannot pass values the second time you call retryStrategy().');
        }
        return $this->retryStrategy;
    }
    /**
     * Rate limiter name to use when processing messages
     * @default null
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function rateLimiter($value): static
    {
        $this->_usedProperties['rateLimiter'] = \true;
        $this->rateLimiter = $value;
        return $this;
    }
    public function __construct(array $value = [])
    {
        if (array_key_exists('dsn', $value)) {
            $this->_usedProperties['dsn'] = \true;
            $this->dsn = $value['dsn'];
            unset($value['dsn']);
        }
        if (array_key_exists('serializer', $value)) {
            $this->_usedProperties['serializer'] = \true;
            $this->serializer = $value['serializer'];
            unset($value['serializer']);
        }
        if (array_key_exists('options', $value)) {
            $this->_usedProperties['options'] = \true;
            $this->options = $value['options'];
            unset($value['options']);
        }
        if (array_key_exists('failure_transport', $value)) {
            $this->_usedProperties['failureTransport'] = \true;
            $this->failureTransport = $value['failure_transport'];
            unset($value['failure_transport']);
        }
        if (array_key_exists('retry_strategy', $value)) {
            $this->_usedProperties['retryStrategy'] = \true;
            $this->retryStrategy = \is_array($value['retry_strategy']) ? new \_ContaoManager\Symfony\Config\Framework\Messenger\TransportConfig\RetryStrategyConfig($value['retry_strategy']) : $value['retry_strategy'];
            unset($value['retry_strategy']);
        }
        if (array_key_exists('rate_limiter', $value)) {
            $this->_usedProperties['rateLimiter'] = \true;
            $this->rateLimiter = $value['rate_limiter'];
            unset($value['rate_limiter']);
        }
        if ([] !== $value) {
            throw new InvalidConfigurationException(sprintf('The following keys are not supported by "%s": ', __CLASS__) . implode(', ', array_keys($value)));
        }
    }
    public function toArray(): array
    {
        $output = [];
        if (isset($this->_usedProperties['dsn'])) {
            $output['dsn'] = $this->dsn;
        }
        if (isset($this->_usedProperties['serializer'])) {
            $output['serializer'] = $this->serializer;
        }
        if (isset($this->_usedProperties['options'])) {
            $output['options'] = $this->options;
        }
        if (isset($this->_usedProperties['failureTransport'])) {
            $output['failure_transport'] = $this->failureTransport;
        }
        if (isset($this->_usedProperties['retryStrategy'])) {
            $output['retry_strategy'] = $this->retryStrategy instanceof \_ContaoManager\Symfony\Config\Framework\Messenger\TransportConfig\RetryStrategyConfig ? $this->retryStrategy->toArray() : $this->retryStrategy;
        }
        if (isset($this->_usedProperties['rateLimiter'])) {
            $output['rate_limiter'] = $this->rateLimiter;
        }
        return $output;
    }
}
<?php

namespace _ContaoManager\Symfony\Config\Framework\Messenger\Serializer;

use _ContaoManager\Symfony\Component\Config\Loader\ParamConfigurator;
use _ContaoManager\Symfony\Component\Config\Definition\Exception\InvalidConfigurationException;
/**
 * This class is automatically generated to help in creating a config.
 */
class SymfonySerializerConfig
{
    private $format;
    private $context;
    private $_usedProperties = [];
    /**
     * Serialization format for the messenger.transport.symfony_serializer service (which is not the serializer used by default).
     * @default 'json'
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function format($value): static
    {
        $this->_usedProperties['format'] = \true;
        $this->format = $value;
        return $this;
    }
    /**
     * @return $this
     */
    public function context(string $name, mixed $value): static
    {
        $this->_usedProperties['context'] = \true;
        $this->context[$name] = $value;
        return $this;
    }
    public function __construct(array $value = [])
    {
        if (array_key_exists('format', $value)) {
            $this->_usedProperties['format'] = \true;
            $this->format = $value['format'];
            unset($value['format']);
        }
        if (array_key_exists('context', $value)) {
            $this->_usedProperties['context'] = \true;
            $this->context = $value['context'];
            unset($value['context']);
        }
        if ([] !== $value) {
            throw new InvalidConfigurationException(sprintf('The following keys are not supported by "%s": ', __CLASS__) . implode(', ', array_keys($value)));
        }
    }
    public function toArray(): array
    {
        $output = [];
        if (isset($this->_usedProperties['format'])) {
            $output['format'] = $this->format;
        }
        if (isset($this->_usedProperties['context'])) {
            $output['context'] = $this->context;
        }
        return $output;
    }
}
<?php

namespace _ContaoManager\Symfony\Config\Framework\Messenger;

require_once __DIR__ . \DIRECTORY_SEPARATOR . 'Serializer' . \DIRECTORY_SEPARATOR . 'SymfonySerializerConfig.php';
use _ContaoManager\Symfony\Component\Config\Loader\ParamConfigurator;
use _ContaoManager\Symfony\Component\Config\Definition\Exception\InvalidConfigurationException;
/**
 * This class is automatically generated to help in creating a config.
 */
class SerializerConfig
{
    private $defaultSerializer;
    private $symfonySerializer;
    private $_usedProperties = [];
    /**
     * Service id to use as the default serializer for the transports.
     * @default 'messenger.transport.native_php_serializer'
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function defaultSerializer($value): static
    {
        $this->_usedProperties['defaultSerializer'] = \true;
        $this->defaultSerializer = $value;
        return $this;
    }
    /**
     * @default {"format":"json","context":[]}
     */
    public function symfonySerializer(array $value = []): \_ContaoManager\Symfony\Config\Framework\Messenger\Serializer\SymfonySerializerConfig
    {
        if (null === $this->symfonySerializer) {
            $this->_usedProperties['symfonySerializer'] = \true;
            $this->symfonySerializer = new \_ContaoManager\Symfony\Config\Framework\Messenger\Serializer\SymfonySerializerConfig($value);
        } elseif (0 < \func_num_args()) {
            throw new InvalidConfigurationException('The node created by "symfonySerializer()" has already been initialized. You cannot pass values the second time you call symfonySerializer().');
        }
        return $this->symfonySerializer;
    }
    public function __construct(array $value = [])
    {
        if (array_key_exists('default_serializer', $value)) {
            $this->_usedProperties['defaultSerializer'] = \true;
            $this->defaultSerializer = $value['default_serializer'];
            unset($value['default_serializer']);
        }
        if (array_key_exists('symfony_serializer', $value)) {
            $this->_usedProperties['symfonySerializer'] = \true;
            $this->symfonySerializer = new \_ContaoManager\Symfony\Config\Framework\Messenger\Serializer\SymfonySerializerConfig($value['symfony_serializer']);
            unset($value['symfony_serializer']);
        }
        if ([] !== $value) {
            throw new InvalidConfigurationException(sprintf('The following keys are not supported by "%s": ', __CLASS__) . implode(', ', array_keys($value)));
        }
    }
    public function toArray(): array
    {
        $output = [];
        if (isset($this->_usedProperties['defaultSerializer'])) {
            $output['default_serializer'] = $this->defaultSerializer;
        }
        if (isset($this->_usedProperties['symfonySerializer'])) {
            $output['symfony_serializer'] = $this->symfonySerializer->toArray();
        }
        return $output;
    }
}
<?php

namespace _ContaoManager\Symfony\Config\Framework\Messenger\TransportConfig;

use _ContaoManager\Symfony\Component\Config\Loader\ParamConfigurator;
use _ContaoManager\Symfony\Component\Config\Definition\Exception\InvalidConfigurationException;
/**
 * This class is automatically generated to help in creating a config.
 */
class RetryStrategyConfig
{
    private $service;
    private $maxRetries;
    private $delay;
    private $multiplier;
    private $maxDelay;
    private $_usedProperties = [];
    /**
     * Service id to override the retry strategy entirely
     * @default null
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function service($value): static
    {
        $this->_usedProperties['service'] = \true;
        $this->service = $value;
        return $this;
    }
    /**
     * @default 3
     * @param ParamConfigurator|int $value
     * @return $this
     */
    public function maxRetries($value): static
    {
        $this->_usedProperties['maxRetries'] = \true;
        $this->maxRetries = $value;
        return $this;
    }
    /**
     * Time in ms to delay (or the initial value when multiplier is used)
     * @default 1000
     * @param ParamConfigurator|int $value
     * @return $this
     */
    public function delay($value): static
    {
        $this->_usedProperties['delay'] = \true;
        $this->delay = $value;
        return $this;
    }
    /**
     * If greater than 1, delay will grow exponentially for each retry: this delay = (delay * (multiple ^ retries))
     * @default 2
     * @param ParamConfigurator|float $value
     * @return $this
     */
    public function multiplier($value): static
    {
        $this->_usedProperties['multiplier'] = \true;
        $this->multiplier = $value;
        return $this;
    }
    /**
     * Max time in ms that a retry should ever be delayed (0 = infinite)
     * @default 0
     * @param ParamConfigurator|int $value
     * @return $this
     */
    public function maxDelay($value): static
    {
        $this->_usedProperties['maxDelay'] = \true;
        $this->maxDelay = $value;
        return $this;
    }
    public function __construct(array $value = [])
    {
        if (array_key_exists('service', $value)) {
            $this->_usedProperties['service'] = \true;
            $this->service = $value['service'];
            unset($value['service']);
        }
        if (array_key_exists('max_retries', $value)) {
            $this->_usedProperties['maxRetries'] = \true;
            $this->maxRetries = $value['max_retries'];
            unset($value['max_retries']);
        }
        if (array_key_exists('delay', $value)) {
            $this->_usedProperties['delay'] = \true;
            $this->delay = $value['delay'];
            unset($value['delay']);
        }
        if (array_key_exists('multiplier', $value)) {
            $this->_usedProperties['multiplier'] = \true;
            $this->multiplier = $value['multiplier'];
            unset($value['multiplier']);
        }
        if (array_key_exists('max_delay', $value)) {
            $this->_usedProperties['maxDelay'] = \true;
            $this->maxDelay = $value['max_delay'];
            unset($value['max_delay']);
        }
        if ([] !== $value) {
            throw new InvalidConfigurationException(sprintf('The following keys are not supported by "%s": ', __CLASS__) . implode(', ', array_keys($value)));
        }
    }
    public function toArray(): array
    {
        $output = [];
        if (isset($this->_usedProperties['service'])) {
            $output['service'] = $this->service;
        }
        if (isset($this->_usedProperties['maxRetries'])) {
            $output['max_retries'] = $this->maxRetries;
        }
        if (isset($this->_usedProperties['delay'])) {
            $output['delay'] = $this->delay;
        }
        if (isset($this->_usedProperties['multiplier'])) {
            $output['multiplier'] = $this->multiplier;
        }
        if (isset($this->_usedProperties['maxDelay'])) {
            $output['max_delay'] = $this->maxDelay;
        }
        return $output;
    }
}
<?php

namespace _ContaoManager\Symfony\Config\Framework\Messenger;

use _ContaoManager\Symfony\Component\Config\Loader\ParamConfigurator;
use _ContaoManager\Symfony\Component\Config\Definition\Exception\InvalidConfigurationException;
/**
 * This class is automatically generated to help in creating a config.
 */
class RoutingConfig
{
    private $senders;
    private $_usedProperties = [];
    /**
     * @param ParamConfigurator|list<ParamConfigurator|mixed> $value
     *
     * @return $this
     */
    public function senders(ParamConfigurator|array $value): static
    {
        $this->_usedProperties['senders'] = \true;
        $this->senders = $value;
        return $this;
    }
    public function __construct(array $value = [])
    {
        if (array_key_exists('senders', $value)) {
            $this->_usedProperties['senders'] = \true;
            $this->senders = $value['senders'];
            unset($value['senders']);
        }
        if ([] !== $value) {
            throw new InvalidConfigurationException(sprintf('The following keys are not supported by "%s": ', __CLASS__) . implode(', ', array_keys($value)));
        }
    }
    public function toArray(): array
    {
        $output = [];
        if (isset($this->_usedProperties['senders'])) {
            $output['senders'] = $this->senders;
        }
        return $output;
    }
}
<?php

namespace _ContaoManager\Symfony\Config\Framework\Messenger\BusConfig;

use _ContaoManager\Symfony\Component\Config\Loader\ParamConfigurator;
use _ContaoManager\Symfony\Component\Config\Definition\Exception\InvalidConfigurationException;
/**
 * This class is automatically generated to help in creating a config.
 */
class MiddlewareConfig
{
    private $id;
    private $arguments;
    private $_usedProperties = [];
    /**
     * @default null
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function id($value): static
    {
        $this->_usedProperties['id'] = \true;
        $this->id = $value;
        return $this;
    }
    /**
     * @param ParamConfigurator|list<ParamConfigurator|mixed> $value
     *
     * @return $this
     */
    public function arguments(ParamConfigurator|array $value): static
    {
        $this->_usedProperties['arguments'] = \true;
        $this->arguments = $value;
        return $this;
    }
    public function __construct(array $value = [])
    {
        if (array_key_exists('id', $value)) {
            $this->_usedProperties['id'] = \true;
            $this->id = $value['id'];
            unset($value['id']);
        }
        if (array_key_exists('arguments', $value)) {
            $this->_usedProperties['arguments'] = \true;
            $this->arguments = $value['arguments'];
            unset($value['arguments']);
        }
        if ([] !== $value) {
            throw new InvalidConfigurationException(sprintf('The following keys are not supported by "%s": ', __CLASS__) . implode(', ', array_keys($value)));
        }
    }
    public function toArray(): array
    {
        $output = [];
        if (isset($this->_usedProperties['id'])) {
            $output['id'] = $this->id;
        }
        if (isset($this->_usedProperties['arguments'])) {
            $output['arguments'] = $this->arguments;
        }
        return $output;
    }
}
<?php

namespace _ContaoManager\Symfony\Config\Framework\Messenger\BusConfig;

use _ContaoManager\Symfony\Component\Config\Loader\ParamConfigurator;
use _ContaoManager\Symfony\Component\Config\Definition\Exception\InvalidConfigurationException;
/**
 * This class is automatically generated to help in creating a config.
 */
class DefaultMiddlewareConfig
{
    private $enabled;
    private $allowNoHandlers;
    private $allowNoSenders;
    private $_usedProperties = [];
    /**
     * @default true
     * @param ParamConfigurator|bool $value
     * @return $this
     */
    public function enabled($value): static
    {
        $this->_usedProperties['enabled'] = \true;
        $this->enabled = $value;
        return $this;
    }
    /**
     * @default false
     * @param ParamConfigurator|bool $value
     * @return $this
     */
    public function allowNoHandlers($value): static
    {
        $this->_usedProperties['allowNoHandlers'] = \true;
        $this->allowNoHandlers = $value;
        return $this;
    }
    /**
     * @default true
     * @param ParamConfigurator|bool $value
     * @return $this
     */
    public function allowNoSenders($value): static
    {
        $this->_usedProperties['allowNoSenders'] = \true;
        $this->allowNoSenders = $value;
        return $this;
    }
    public function __construct(array $value = [])
    {
        if (array_key_exists('enabled', $value)) {
            $this->_usedProperties['enabled'] = \true;
            $this->enabled = $value['enabled'];
            unset($value['enabled']);
        }
        if (array_key_exists('allow_no_handlers', $value)) {
            $this->_usedProperties['allowNoHandlers'] = \true;
            $this->allowNoHandlers = $value['allow_no_handlers'];
            unset($value['allow_no_handlers']);
        }
        if (array_key_exists('allow_no_senders', $value)) {
            $this->_usedProperties['allowNoSenders'] = \true;
            $this->allowNoSenders = $value['allow_no_senders'];
            unset($value['allow_no_senders']);
        }
        if ([] !== $value) {
            throw new InvalidConfigurationException(sprintf('The following keys are not supported by "%s": ', __CLASS__) . implode(', ', array_keys($value)));
        }
    }
    public function toArray(): array
    {
        $output = [];
        if (isset($this->_usedProperties['enabled'])) {
            $output['enabled'] = $this->enabled;
        }
        if (isset($this->_usedProperties['allowNoHandlers'])) {
            $output['allow_no_handlers'] = $this->allowNoHandlers;
        }
        if (isset($this->_usedProperties['allowNoSenders'])) {
            $output['allow_no_senders'] = $this->allowNoSenders;
        }
        return $output;
    }
}
<?php

namespace _ContaoManager\Symfony\Config\Framework\Messenger;

require_once __DIR__ . \DIRECTORY_SEPARATOR . 'BusConfig' . \DIRECTORY_SEPARATOR . 'DefaultMiddlewareConfig.php';
require_once __DIR__ . \DIRECTORY_SEPARATOR . 'BusConfig' . \DIRECTORY_SEPARATOR . 'MiddlewareConfig.php';
use _ContaoManager\Symfony\Component\Config\Definition\Exception\InvalidConfigurationException;
/**
 * This class is automatically generated to help in creating a config.
 */
class BusConfig
{
    private $defaultMiddleware;
    private $middleware;
    private $_usedProperties = [];
    /**
     * @template TValue of mixed
     * @param TValue $value
     * @default {"enabled":true,"allow_no_handlers":false,"allow_no_senders":true}
     * @return \Symfony\Config\Framework\Messenger\BusConfig\DefaultMiddlewareConfig|$this
     * @psalm-return (TValue is array ? \Symfony\Config\Framework\Messenger\BusConfig\DefaultMiddlewareConfig : static)
     */
    public function defaultMiddleware(mixed $value = []): \_ContaoManager\Symfony\Config\Framework\Messenger\BusConfig\DefaultMiddlewareConfig|static
    {
        if (!\is_array($value)) {
            $this->_usedProperties['defaultMiddleware'] = \true;
            $this->defaultMiddleware = $value;
            return $this;
        }
        if (!$this->defaultMiddleware instanceof \_ContaoManager\Symfony\Config\Framework\Messenger\BusConfig\DefaultMiddlewareConfig) {
            $this->_usedProperties['defaultMiddleware'] = \true;
            $this->defaultMiddleware = new \_ContaoManager\Symfony\Config\Framework\Messenger\BusConfig\DefaultMiddlewareConfig($value);
        } elseif (0 < \func_num_args()) {
            throw new InvalidConfigurationException('The node created by "defaultMiddleware()" has already been initialized. You cannot pass values the second time you call defaultMiddleware().');
        }
        return $this->defaultMiddleware;
    }
    /**
     * @template TValue of mixed
     * @param TValue $value
     * @return \Symfony\Config\Framework\Messenger\BusConfig\MiddlewareConfig|$this
     * @psalm-return (TValue is array ? \Symfony\Config\Framework\Messenger\BusConfig\MiddlewareConfig : static)
     */
    public function middleware(mixed $value = []): \_ContaoManager\Symfony\Config\Framework\Messenger\BusConfig\MiddlewareConfig|static
    {
        $this->_usedProperties['middleware'] = \true;
        if (!\is_array($value)) {
            $this->middleware[] = $value;
            return $this;
        }
        return $this->middleware[] = new \_ContaoManager\Symfony\Config\Framework\Messenger\BusConfig\MiddlewareConfig($value);
    }
    public function __construct(array $value = [])
    {
        if (array_key_exists('default_middleware', $value)) {
            $this->_usedProperties['defaultMiddleware'] = \true;
            $this->defaultMiddleware = \is_array($value['default_middleware']) ? new \_ContaoManager\Symfony\Config\Framework\Messenger\BusConfig\DefaultMiddlewareConfig($value['default_middleware']) : $value['default_middleware'];
            unset($value['default_middleware']);
        }
        if (array_key_exists('middleware', $value)) {
            $this->_usedProperties['middleware'] = \true;
            $this->middleware = array_map(fn($v) => \is_array($v) ? new \_ContaoManager\Symfony\Config\Framework\Messenger\BusConfig\MiddlewareConfig($v) : $v, $value['middleware']);
            unset($value['middleware']);
        }
        if ([] !== $value) {
            throw new InvalidConfigurationException(sprintf('The following keys are not supported by "%s": ', __CLASS__) . implode(', ', array_keys($value)));
        }
    }
    public function toArray(): array
    {
        $output = [];
        if (isset($this->_usedProperties['defaultMiddleware'])) {
            $output['default_middleware'] = $this->defaultMiddleware instanceof \_ContaoManager\Symfony\Config\Framework\Messenger\BusConfig\DefaultMiddlewareConfig ? $this->defaultMiddleware->toArray() : $this->defaultMiddleware;
        }
        if (isset($this->_usedProperties['middleware'])) {
            $output['middleware'] = array_map(fn($v) => $v instanceof \_ContaoManager\Symfony\Config\Framework\Messenger\BusConfig\MiddlewareConfig ? $v->toArray() : $v, $this->middleware);
        }
        return $output;
    }
}
<?php

namespace _ContaoManager\Symfony\Config\Framework;

use _ContaoManager\Symfony\Component\Config\Loader\ParamConfigurator;
use _ContaoManager\Symfony\Component\Config\Definition\Exception\InvalidConfigurationException;
/**
 * This class is automatically generated to help in creating a config.
 */
class PropertyInfoConfig
{
    private $enabled;
    private $_usedProperties = [];
    /**
     * @default true
     * @param ParamConfigurator|bool $value
     * @return $this
     */
    public function enabled($value): static
    {
        $this->_usedProperties['enabled'] = \true;
        $this->enabled = $value;
        return $this;
    }
    public function __construct(array $value = [])
    {
        if (array_key_exists('enabled', $value)) {
            $this->_usedProperties['enabled'] = \true;
            $this->enabled = $value['enabled'];
            unset($value['enabled']);
        }
        if ([] !== $value) {
            throw new InvalidConfigurationException(sprintf('The following keys are not supported by "%s": ', __CLASS__) . implode(', ', array_keys($value)));
        }
    }
    public function toArray(): array
    {
        $output = [];
        if (isset($this->_usedProperties['enabled'])) {
            $output['enabled'] = $this->enabled;
        }
        return $output;
    }
}
<?php

namespace _ContaoManager\Symfony\Config\Framework;

require_once __DIR__ . \DIRECTORY_SEPARATOR . 'Mailer' . \DIRECTORY_SEPARATOR . 'EnvelopeConfig.php';
require_once __DIR__ . \DIRECTORY_SEPARATOR . 'Mailer' . \DIRECTORY_SEPARATOR . 'HeaderConfig.php';
use _ContaoManager\Symfony\Component\Config\Loader\ParamConfigurator;
use _ContaoManager\Symfony\Component\Config\Definition\Exception\InvalidConfigurationException;
/**
 * This class is automatically generated to help in creating a config.
 */
class MailerConfig
{
    private $enabled;
    private $messageBus;
    private $dsn;
    private $transports;
    private $envelope;
    private $headers;
    private $_usedProperties = [];
    /**
     * @default false
     * @param ParamConfigurator|bool $value
     * @return $this
     */
    public function enabled($value): static
    {
        $this->_usedProperties['enabled'] = \true;
        $this->enabled = $value;
        return $this;
    }
    /**
     * The message bus to use. Defaults to the default bus if the Messenger component is installed.
     * @default null
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function messageBus($value): static
    {
        $this->_usedProperties['messageBus'] = \true;
        $this->messageBus = $value;
        return $this;
    }
    /**
     * @default null
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function dsn($value): static
    {
        $this->_usedProperties['dsn'] = \true;
        $this->dsn = $value;
        return $this;
    }
    /**
     * @return $this
     */
    public function transport(string $name, mixed $value): static
    {
        $this->_usedProperties['transports'] = \true;
        $this->transports[$name] = $value;
        return $this;
    }
    /**
     * Mailer Envelope configuration
     */
    public function envelope(array $value = []): \_ContaoManager\Symfony\Config\Framework\Mailer\EnvelopeConfig
    {
        if (null === $this->envelope) {
            $this->_usedProperties['envelope'] = \true;
            $this->envelope = new \_ContaoManager\Symfony\Config\Framework\Mailer\EnvelopeConfig($value);
        } elseif (0 < \func_num_args()) {
            throw new InvalidConfigurationException('The node created by "envelope()" has already been initialized. You cannot pass values the second time you call envelope().');
        }
        return $this->envelope;
    }
    /**
     * @template TValue of mixed
     * @param TValue $value
     * @return \Symfony\Config\Framework\Mailer\HeaderConfig|$this
     * @psalm-return (TValue is array ? \Symfony\Config\Framework\Mailer\HeaderConfig : static)
     */
    public function header(string $name, mixed $value = []): \_ContaoManager\Symfony\Config\Framework\Mailer\HeaderConfig|static
    {
        if (!\is_array($value)) {
            $this->_usedProperties['headers'] = \true;
            $this->headers[$name] = $value;
            return $this;
        }
        if (!isset($this->headers[$name]) || !$this->headers[$name] instanceof \_ContaoManager\Symfony\Config\Framework\Mailer\HeaderConfig) {
            $this->_usedProperties['headers'] = \true;
            $this->headers[$name] = new \_ContaoManager\Symfony\Config\Framework\Mailer\HeaderConfig($value);
        } elseif (1 < \func_num_args()) {
            throw new InvalidConfigurationException('The node created by "header()" has already been initialized. You cannot pass values the second time you call header().');
        }
        return $this->headers[$name];
    }
    public function __construct(array $value = [])
    {
        if (array_key_exists('enabled', $value)) {
            $this->_usedProperties['enabled'] = \true;
            $this->enabled = $value['enabled'];
            unset($value['enabled']);
        }
        if (array_key_exists('message_bus', $value)) {
            $this->_usedProperties['messageBus'] = \true;
            $this->messageBus = $value['message_bus'];
            unset($value['message_bus']);
        }
        if (array_key_exists('dsn', $value)) {
            $this->_usedProperties['dsn'] = \true;
            $this->dsn = $value['dsn'];
            unset($value['dsn']);
        }
        if (array_key_exists('transports', $value)) {
            $this->_usedProperties['transports'] = \true;
            $this->transports = $value['transports'];
            unset($value['transports']);
        }
        if (array_key_exists('envelope', $value)) {
            $this->_usedProperties['envelope'] = \true;
            $this->envelope = new \_ContaoManager\Symfony\Config\Framework\Mailer\EnvelopeConfig($value['envelope']);
            unset($value['envelope']);
        }
        if (array_key_exists('headers', $value)) {
            $this->_usedProperties['headers'] = \true;
            $this->headers = array_map(fn($v) => \is_array($v) ? new \_ContaoManager\Symfony\Config\Framework\Mailer\HeaderConfig($v) : $v, $value['headers']);
            unset($value['headers']);
        }
        if ([] !== $value) {
            throw new InvalidConfigurationException(sprintf('The following keys are not supported by "%s": ', __CLASS__) . implode(', ', array_keys($value)));
        }
    }
    public function toArray(): array
    {
        $output = [];
        if (isset($this->_usedProperties['enabled'])) {
            $output['enabled'] = $this->enabled;
        }
        if (isset($this->_usedProperties['messageBus'])) {
            $output['message_bus'] = $this->messageBus;
        }
        if (isset($this->_usedProperties['dsn'])) {
            $output['dsn'] = $this->dsn;
        }
        if (isset($this->_usedProperties['transports'])) {
            $output['transports'] = $this->transports;
        }
        if (isset($this->_usedProperties['envelope'])) {
            $output['envelope'] = $this->envelope->toArray();
        }
        if (isset($this->_usedProperties['headers'])) {
            $output['headers'] = array_map(fn($v) => $v instanceof \_ContaoManager\Symfony\Config\Framework\Mailer\HeaderConfig ? $v->toArray() : $v, $this->headers);
        }
        return $output;
    }
}
<?php

namespace _ContaoManager\Symfony\Config\Framework;

use _ContaoManager\Symfony\Component\Config\Loader\ParamConfigurator;
use _ContaoManager\Symfony\Component\Config\Definition\Exception\InvalidConfigurationException;
/**
 * This class is automatically generated to help in creating a config.
 */
class UidConfig
{
    private $enabled;
    private $defaultUuidVersion;
    private $nameBasedUuidVersion;
    private $nameBasedUuidNamespace;
    private $timeBasedUuidVersion;
    private $timeBasedUuidNode;
    private $_usedProperties = [];
    /**
     * @default true
     * @param ParamConfigurator|bool $value
     * @return $this
     */
    public function enabled($value): static
    {
        $this->_usedProperties['enabled'] = \true;
        $this->enabled = $value;
        return $this;
    }
    /**
     * @default null
     * @param ParamConfigurator|7|6|4|1 $value
     * @return $this
     */
    public function defaultUuidVersion($value): static
    {
        $this->_usedProperties['defaultUuidVersion'] = \true;
        $this->defaultUuidVersion = $value;
        return $this;
    }
    /**
     * @default 5
     * @param ParamConfigurator|5|3 $value
     * @return $this
     */
    public function nameBasedUuidVersion($value): static
    {
        $this->_usedProperties['nameBasedUuidVersion'] = \true;
        $this->nameBasedUuidVersion = $value;
        return $this;
    }
    /**
     * @default null
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function nameBasedUuidNamespace($value): static
    {
        $this->_usedProperties['nameBasedUuidNamespace'] = \true;
        $this->nameBasedUuidNamespace = $value;
        return $this;
    }
    /**
     * @default null
     * @param ParamConfigurator|7|6|1 $value
     * @return $this
     */
    public function timeBasedUuidVersion($value): static
    {
        $this->_usedProperties['timeBasedUuidVersion'] = \true;
        $this->timeBasedUuidVersion = $value;
        return $this;
    }
    /**
     * @default null
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function timeBasedUuidNode($value): static
    {
        $this->_usedProperties['timeBasedUuidNode'] = \true;
        $this->timeBasedUuidNode = $value;
        return $this;
    }
    public function __construct(array $value = [])
    {
        if (array_key_exists('enabled', $value)) {
            $this->_usedProperties['enabled'] = \true;
            $this->enabled = $value['enabled'];
            unset($value['enabled']);
        }
        if (array_key_exists('default_uuid_version', $value)) {
            $this->_usedProperties['defaultUuidVersion'] = \true;
            $this->defaultUuidVersion = $value['default_uuid_version'];
            unset($value['default_uuid_version']);
        }
        if (array_key_exists('name_based_uuid_version', $value)) {
            $this->_usedProperties['nameBasedUuidVersion'] = \true;
            $this->nameBasedUuidVersion = $value['name_based_uuid_version'];
            unset($value['name_based_uuid_version']);
        }
        if (array_key_exists('name_based_uuid_namespace', $value)) {
            $this->_usedProperties['nameBasedUuidNamespace'] = \true;
            $this->nameBasedUuidNamespace = $value['name_based_uuid_namespace'];
            unset($value['name_based_uuid_namespace']);
        }
        if (array_key_exists('time_based_uuid_version', $value)) {
            $this->_usedProperties['timeBasedUuidVersion'] = \true;
            $this->timeBasedUuidVersion = $value['time_based_uuid_version'];
            unset($value['time_based_uuid_version']);
        }
        if (array_key_exists('time_based_uuid_node', $value)) {
            $this->_usedProperties['timeBasedUuidNode'] = \true;
            $this->timeBasedUuidNode = $value['time_based_uuid_node'];
            unset($value['time_based_uuid_node']);
        }
        if ([] !== $value) {
            throw new InvalidConfigurationException(sprintf('The following keys are not supported by "%s": ', __CLASS__) . implode(', ', array_keys($value)));
        }
    }
    public function toArray(): array
    {
        $output = [];
        if (isset($this->_usedProperties['enabled'])) {
            $output['enabled'] = $this->enabled;
        }
        if (isset($this->_usedProperties['defaultUuidVersion'])) {
            $output['default_uuid_version'] = $this->defaultUuidVersion;
        }
        if (isset($this->_usedProperties['nameBasedUuidVersion'])) {
            $output['name_based_uuid_version'] = $this->nameBasedUuidVersion;
        }
        if (isset($this->_usedProperties['nameBasedUuidNamespace'])) {
            $output['name_based_uuid_namespace'] = $this->nameBasedUuidNamespace;
        }
        if (isset($this->_usedProperties['timeBasedUuidVersion'])) {
            $output['time_based_uuid_version'] = $this->timeBasedUuidVersion;
        }
        if (isset($this->_usedProperties['timeBasedUuidNode'])) {
            $output['time_based_uuid_node'] = $this->timeBasedUuidNode;
        }
        return $output;
    }
}
<?php

namespace _ContaoManager\Symfony\Config\Framework;

use _ContaoManager\Symfony\Component\Config\Loader\ParamConfigurator;
use _ContaoManager\Symfony\Component\Config\Definition\Exception\InvalidConfigurationException;
/**
 * This class is automatically generated to help in creating a config.
 */
class RemoteeventConfig
{
    private $enabled;
    private $_usedProperties = [];
    /**
     * @default false
     * @param ParamConfigurator|bool $value
     * @return $this
     */
    public function enabled($value): static
    {
        $this->_usedProperties['enabled'] = \true;
        $this->enabled = $value;
        return $this;
    }
    public function __construct(array $value = [])
    {
        if (array_key_exists('enabled', $value)) {
            $this->_usedProperties['enabled'] = \true;
            $this->enabled = $value['enabled'];
            unset($value['enabled']);
        }
        if ([] !== $value) {
            throw new InvalidConfigurationException(sprintf('The following keys are not supported by "%s": ', __CLASS__) . implode(', ', array_keys($value)));
        }
    }
    public function toArray(): array
    {
        $output = [];
        if (isset($this->_usedProperties['enabled'])) {
            $output['enabled'] = $this->enabled;
        }
        return $output;
    }
}
<?php

namespace _ContaoManager\Symfony\Config\Framework;

use _ContaoManager\Symfony\Component\Config\Loader\ParamConfigurator;
use _ContaoManager\Symfony\Component\Config\Definition\Exception\InvalidConfigurationException;
/**
 * This class is automatically generated to help in creating a config.
 */
class AssetMapperConfig
{
    private $enabled;
    private $paths;
    private $excludedPatterns;
    private $excludeDotfiles;
    private $server;
    private $publicPrefix;
    private $missingImportMode;
    private $extensions;
    private $importmapPath;
    private $importmapPolyfill;
    private $importmapScriptAttributes;
    private $vendorDir;
    private $provider;
    private $_usedProperties = [];
    /**
     * @default false
     * @param ParamConfigurator|bool $value
     * @return $this
     */
    public function enabled($value): static
    {
        $this->_usedProperties['enabled'] = \true;
        $this->enabled = $value;
        return $this;
    }
    /**
     * @return $this
     */
    public function path(string $namespace, mixed $value): static
    {
        $this->_usedProperties['paths'] = \true;
        $this->paths[$namespace] = $value;
        return $this;
    }
    /**
     * @param ParamConfigurator|list<ParamConfigurator|mixed> $value
     *
     * @return $this
     */
    public function excludedPatterns(ParamConfigurator|array $value): static
    {
        $this->_usedProperties['excludedPatterns'] = \true;
        $this->excludedPatterns = $value;
        return $this;
    }
    /**
     * If true, any files starting with "." will be excluded from the asset mapper
     * @default true
     * @param ParamConfigurator|bool $value
     * @return $this
     */
    public function excludeDotfiles($value): static
    {
        $this->_usedProperties['excludeDotfiles'] = \true;
        $this->excludeDotfiles = $value;
        return $this;
    }
    /**
     * If true, a "dev server" will return the assets from the public directory (true in "debug" mode only by default)
     * @default false
     * @param ParamConfigurator|bool $value
     * @return $this
     */
    public function server($value): static
    {
        $this->_usedProperties['server'] = \true;
        $this->server = $value;
        return $this;
    }
    /**
     * The public path where the assets will be written to (and served from when "server" is true)
     * @default '/assets/'
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function publicPrefix($value): static
    {
        $this->_usedProperties['publicPrefix'] = \true;
        $this->publicPrefix = $value;
        return $this;
    }
    /**
     * Behavior if an asset cannot be found when imported from JavaScript or CSS files - e.g. "import './non-existent.js'". "strict" means an exception is thrown, "warn" means a warning is logged, "ignore" means the import is left as-is.
     * @default 'warn'
     * @param ParamConfigurator|'strict'|'warn'|'ignore' $value
     * @return $this
     */
    public function missingImportMode($value): static
    {
        $this->_usedProperties['missingImportMode'] = \true;
        $this->missingImportMode = $value;
        return $this;
    }
    /**
     * @return $this
     */
    public function extension(string $extension, mixed $value): static
    {
        $this->_usedProperties['extensions'] = \true;
        $this->extensions[$extension] = $value;
        return $this;
    }
    /**
     * The path of the importmap.php file.
     * @default '%kernel.project_dir%/importmap.php'
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function importmapPath($value): static
    {
        $this->_usedProperties['importmapPath'] = \true;
        $this->importmapPath = $value;
        return $this;
    }
    /**
     * The importmap name that will be used to load the polyfill. Set to false to disable.
     * @default 'es-module-shims'
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function importmapPolyfill($value): static
    {
        $this->_usedProperties['importmapPolyfill'] = \true;
        $this->importmapPolyfill = $value;
        return $this;
    }
    /**
     * @return $this
     */
    public function importmapScriptAttribute(string $key, mixed $value): static
    {
        $this->_usedProperties['importmapScriptAttributes'] = \true;
        $this->importmapScriptAttributes[$key] = $value;
        return $this;
    }
    /**
     * The directory to store JavaScript vendors.
     * @default '%kernel.project_dir%/assets/vendor'
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function vendorDir($value): static
    {
        $this->_usedProperties['vendorDir'] = \true;
        $this->vendorDir = $value;
        return $this;
    }
    /**
     * @default null
     * @param ParamConfigurator|mixed $value
     * @deprecated Option "provider" at "asset_mapper" is deprecated and does nothing. Remove it.
     * @return $this
     */
    public function provider($value): static
    {
        $this->_usedProperties['provider'] = \true;
        $this->provider = $value;
        return $this;
    }
    public function __construct(array $value = [])
    {
        if (array_key_exists('enabled', $value)) {
            $this->_usedProperties['enabled'] = \true;
            $this->enabled = $value['enabled'];
            unset($value['enabled']);
        }
        if (array_key_exists('paths', $value)) {
            $this->_usedProperties['paths'] = \true;
            $this->paths = $value['paths'];
            unset($value['paths']);
        }
        if (array_key_exists('excluded_patterns', $value)) {
            $this->_usedProperties['excludedPatterns'] = \true;
            $this->excludedPatterns = $value['excluded_patterns'];
            unset($value['excluded_patterns']);
        }
        if (array_key_exists('exclude_dotfiles', $value)) {
            $this->_usedProperties['excludeDotfiles'] = \true;
            $this->excludeDotfiles = $value['exclude_dotfiles'];
            unset($value['exclude_dotfiles']);
        }
        if (array_key_exists('server', $value)) {
            $this->_usedProperties['server'] = \true;
            $this->server = $value['server'];
            unset($value['server']);
        }
        if (array_key_exists('public_prefix', $value)) {
            $this->_usedProperties['publicPrefix'] = \true;
            $this->publicPrefix = $value['public_prefix'];
            unset($value['public_prefix']);
        }
        if (array_key_exists('missing_import_mode', $value)) {
            $this->_usedProperties['missingImportMode'] = \true;
            $this->missingImportMode = $value['missing_import_mode'];
            unset($value['missing_import_mode']);
        }
        if (array_key_exists('extensions', $value)) {
            $this->_usedProperties['extensions'] = \true;
            $this->extensions = $value['extensions'];
            unset($value['extensions']);
        }
        if (array_key_exists('importmap_path', $value)) {
            $this->_usedProperties['importmapPath'] = \true;
            $this->importmapPath = $value['importmap_path'];
            unset($value['importmap_path']);
        }
        if (array_key_exists('importmap_polyfill', $value)) {
            $this->_usedProperties['importmapPolyfill'] = \true;
            $this->importmapPolyfill = $value['importmap_polyfill'];
            unset($value['importmap_polyfill']);
        }
        if (array_key_exists('importmap_script_attributes', $value)) {
            $this->_usedProperties['importmapScriptAttributes'] = \true;
            $this->importmapScriptAttributes = $value['importmap_script_attributes'];
            unset($value['importmap_script_attributes']);
        }
        if (array_key_exists('vendor_dir', $value)) {
            $this->_usedProperties['vendorDir'] = \true;
            $this->vendorDir = $value['vendor_dir'];
            unset($value['vendor_dir']);
        }
        if (array_key_exists('provider', $value)) {
            $this->_usedProperties['provider'] = \true;
            $this->provider = $value['provider'];
            unset($value['provider']);
        }
        if ([] !== $value) {
            throw new InvalidConfigurationException(sprintf('The following keys are not supported by "%s": ', __CLASS__) . implode(', ', array_keys($value)));
        }
    }
    public function toArray(): array
    {
        $output = [];
        if (isset($this->_usedProperties['enabled'])) {
            $output['enabled'] = $this->enabled;
        }
        if (isset($this->_usedProperties['paths'])) {
            $output['paths'] = $this->paths;
        }
        if (isset($this->_usedProperties['excludedPatterns'])) {
            $output['excluded_patterns'] = $this->excludedPatterns;
        }
        if (isset($this->_usedProperties['excludeDotfiles'])) {
            $output['exclude_dotfiles'] = $this->excludeDotfiles;
        }
        if (isset($this->_usedProperties['server'])) {
            $output['server'] = $this->server;
        }
        if (isset($this->_usedProperties['publicPrefix'])) {
            $output['public_prefix'] = $this->publicPrefix;
        }
        if (isset($this->_usedProperties['missingImportMode'])) {
            $output['missing_import_mode'] = $this->missingImportMode;
        }
        if (isset($this->_usedProperties['extensions'])) {
            $output['extensions'] = $this->extensions;
        }
        if (isset($this->_usedProperties['importmapPath'])) {
            $output['importmap_path'] = $this->importmapPath;
        }
        if (isset($this->_usedProperties['importmapPolyfill'])) {
            $output['importmap_polyfill'] = $this->importmapPolyfill;
        }
        if (isset($this->_usedProperties['importmapScriptAttributes'])) {
            $output['importmap_script_attributes'] = $this->importmapScriptAttributes;
        }
        if (isset($this->_usedProperties['vendorDir'])) {
            $output['vendor_dir'] = $this->vendorDir;
        }
        if (isset($this->_usedProperties['provider'])) {
            $output['provider'] = $this->provider;
        }
        return $output;
    }
}
<?php

namespace _ContaoManager\Symfony\Config\Framework;

require_once __DIR__ . \DIRECTORY_SEPARATOR . 'HtmlSanitizer' . \DIRECTORY_SEPARATOR . 'SanitizerConfig.php';
use _ContaoManager\Symfony\Component\Config\Loader\ParamConfigurator;
use _ContaoManager\Symfony\Component\Config\Definition\Exception\InvalidConfigurationException;
/**
 * This class is automatically generated to help in creating a config.
 */
class HtmlSanitizerConfig
{
    private $enabled;
    private $sanitizers;
    private $_usedProperties = [];
    /**
     * @default false
     * @param ParamConfigurator|bool $value
     * @return $this
     */
    public function enabled($value): static
    {
        $this->_usedProperties['enabled'] = \true;
        $this->enabled = $value;
        return $this;
    }
    public function sanitizer(string $name, array $value = []): \_ContaoManager\Symfony\Config\Framework\HtmlSanitizer\SanitizerConfig
    {
        if (!isset($this->sanitizers[$name])) {
            $this->_usedProperties['sanitizers'] = \true;
            $this->sanitizers[$name] = new \_ContaoManager\Symfony\Config\Framework\HtmlSanitizer\SanitizerConfig($value);
        } elseif (1 < \func_num_args()) {
            throw new InvalidConfigurationException('The node created by "sanitizer()" has already been initialized. You cannot pass values the second time you call sanitizer().');
        }
        return $this->sanitizers[$name];
    }
    public function __construct(array $value = [])
    {
        if (array_key_exists('enabled', $value)) {
            $this->_usedProperties['enabled'] = \true;
            $this->enabled = $value['enabled'];
            unset($value['enabled']);
        }
        if (array_key_exists('sanitizers', $value)) {
            $this->_usedProperties['sanitizers'] = \true;
            $this->sanitizers = array_map(fn($v) => new \_ContaoManager\Symfony\Config\Framework\HtmlSanitizer\SanitizerConfig($v), $value['sanitizers']);
            unset($value['sanitizers']);
        }
        if ([] !== $value) {
            throw new InvalidConfigurationException(sprintf('The following keys are not supported by "%s": ', __CLASS__) . implode(', ', array_keys($value)));
        }
    }
    public function toArray(): array
    {
        $output = [];
        if (isset($this->_usedProperties['enabled'])) {
            $output['enabled'] = $this->enabled;
        }
        if (isset($this->_usedProperties['sanitizers'])) {
            $output['sanitizers'] = array_map(fn($v) => $v->toArray(), $this->sanitizers);
        }
        return $output;
    }
}
<?php

namespace _ContaoManager\Symfony\Config\Framework;

use _ContaoManager\Symfony\Component\Config\Loader\ParamConfigurator;
use _ContaoManager\Symfony\Component\Config\Definition\Exception\InvalidConfigurationException;
/**
 * This class is automatically generated to help in creating a config.
 */
class ExceptionConfig
{
    private $logLevel;
    private $statusCode;
    private $_usedProperties = [];
    /**
     * The level of log message. Null to let Symfony decide.
     * @default null
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function logLevel($value): static
    {
        $this->_usedProperties['logLevel'] = \true;
        $this->logLevel = $value;
        return $this;
    }
    /**
     * The status code of the response. Null or 0 to let Symfony decide.
     * @default null
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function statusCode($value): static
    {
        $this->_usedProperties['statusCode'] = \true;
        $this->statusCode = $value;
        return $this;
    }
    public function __construct(array $value = [])
    {
        if (array_key_exists('log_level', $value)) {
            $this->_usedProperties['logLevel'] = \true;
            $this->logLevel = $value['log_level'];
            unset($value['log_level']);
        }
        if (array_key_exists('status_code', $value)) {
            $this->_usedProperties['statusCode'] = \true;
            $this->statusCode = $value['status_code'];
            unset($value['status_code']);
        }
        if ([] !== $value) {
            throw new InvalidConfigurationException(sprintf('The following keys are not supported by "%s": ', __CLASS__) . implode(', ', array_keys($value)));
        }
    }
    public function toArray(): array
    {
        $output = [];
        if (isset($this->_usedProperties['logLevel'])) {
            $output['log_level'] = $this->logLevel;
        }
        if (isset($this->_usedProperties['statusCode'])) {
            $output['status_code'] = $this->statusCode;
        }
        return $output;
    }
}
<?php

namespace _ContaoManager\Symfony\Config\Framework;

use _ContaoManager\Symfony\Component\Config\Loader\ParamConfigurator;
use _ContaoManager\Symfony\Component\Config\Definition\Exception\InvalidConfigurationException;
/**
 * This class is automatically generated to help in creating a config.
 */
class SessionConfig
{
    private $enabled;
    private $storageFactoryId;
    private $handlerId;
    private $name;
    private $cookieLifetime;
    private $cookiePath;
    private $cookieDomain;
    private $cookieSecure;
    private $cookieHttponly;
    private $cookieSamesite;
    private $useCookies;
    private $gcDivisor;
    private $gcProbability;
    private $gcMaxlifetime;
    private $savePath;
    private $metadataUpdateThreshold;
    private $sidLength;
    private $sidBitsPerCharacter;
    private $_usedProperties = [];
    /**
     * @default false
     * @param ParamConfigurator|bool $value
     * @return $this
     */
    public function enabled($value): static
    {
        $this->_usedProperties['enabled'] = \true;
        $this->enabled = $value;
        return $this;
    }
    /**
     * @default 'session.storage.factory.native'
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function storageFactoryId($value): static
    {
        $this->_usedProperties['storageFactoryId'] = \true;
        $this->storageFactoryId = $value;
        return $this;
    }
    /**
     * @default null
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function handlerId($value): static
    {
        $this->_usedProperties['handlerId'] = \true;
        $this->handlerId = $value;
        return $this;
    }
    /**
     * @default null
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function name($value): static
    {
        $this->_usedProperties['name'] = \true;
        $this->name = $value;
        return $this;
    }
    /**
     * @default null
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function cookieLifetime($value): static
    {
        $this->_usedProperties['cookieLifetime'] = \true;
        $this->cookieLifetime = $value;
        return $this;
    }
    /**
     * @default null
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function cookiePath($value): static
    {
        $this->_usedProperties['cookiePath'] = \true;
        $this->cookiePath = $value;
        return $this;
    }
    /**
     * @default null
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function cookieDomain($value): static
    {
        $this->_usedProperties['cookieDomain'] = \true;
        $this->cookieDomain = $value;
        return $this;
    }
    /**
     * @default null
     * @param ParamConfigurator|true|false|'auto' $value
     * @return $this
     */
    public function cookieSecure($value): static
    {
        $this->_usedProperties['cookieSecure'] = \true;
        $this->cookieSecure = $value;
        return $this;
    }
    /**
     * @default true
     * @param ParamConfigurator|bool $value
     * @return $this
     */
    public function cookieHttponly($value): static
    {
        $this->_usedProperties['cookieHttponly'] = \true;
        $this->cookieHttponly = $value;
        return $this;
    }
    /**
     * @default null
     * @param ParamConfigurator|NULL|'lax'|'strict'|'none' $value
     * @return $this
     */
    public function cookieSamesite($value): static
    {
        $this->_usedProperties['cookieSamesite'] = \true;
        $this->cookieSamesite = $value;
        return $this;
    }
    /**
     * @default null
     * @param ParamConfigurator|bool $value
     * @return $this
     */
    public function useCookies($value): static
    {
        $this->_usedProperties['useCookies'] = \true;
        $this->useCookies = $value;
        return $this;
    }
    /**
     * @default null
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function gcDivisor($value): static
    {
        $this->_usedProperties['gcDivisor'] = \true;
        $this->gcDivisor = $value;
        return $this;
    }
    /**
     * @default 1
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function gcProbability($value): static
    {
        $this->_usedProperties['gcProbability'] = \true;
        $this->gcProbability = $value;
        return $this;
    }
    /**
     * @default null
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function gcMaxlifetime($value): static
    {
        $this->_usedProperties['gcMaxlifetime'] = \true;
        $this->gcMaxlifetime = $value;
        return $this;
    }
    /**
     * @default null
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function savePath($value): static
    {
        $this->_usedProperties['savePath'] = \true;
        $this->savePath = $value;
        return $this;
    }
    /**
     * seconds to wait between 2 session metadata updates
     * @default 0
     * @param ParamConfigurator|int $value
     * @return $this
     */
    public function metadataUpdateThreshold($value): static
    {
        $this->_usedProperties['metadataUpdateThreshold'] = \true;
        $this->metadataUpdateThreshold = $value;
        return $this;
    }
    /**
     * @default null
     * @param ParamConfigurator|int $value
     * @return $this
     */
    public function sidLength($value): static
    {
        $this->_usedProperties['sidLength'] = \true;
        $this->sidLength = $value;
        return $this;
    }
    /**
     * @default null
     * @param ParamConfigurator|int $value
     * @return $this
     */
    public function sidBitsPerCharacter($value): static
    {
        $this->_usedProperties['sidBitsPerCharacter'] = \true;
        $this->sidBitsPerCharacter = $value;
        return $this;
    }
    public function __construct(array $value = [])
    {
        if (array_key_exists('enabled', $value)) {
            $this->_usedProperties['enabled'] = \true;
            $this->enabled = $value['enabled'];
            unset($value['enabled']);
        }
        if (array_key_exists('storage_factory_id', $value)) {
            $this->_usedProperties['storageFactoryId'] = \true;
            $this->storageFactoryId = $value['storage_factory_id'];
            unset($value['storage_factory_id']);
        }
        if (array_key_exists('handler_id', $value)) {
            $this->_usedProperties['handlerId'] = \true;
            $this->handlerId = $value['handler_id'];
            unset($value['handler_id']);
        }
        if (array_key_exists('name', $value)) {
            $this->_usedProperties['name'] = \true;
            $this->name = $value['name'];
            unset($value['name']);
        }
        if (array_key_exists('cookie_lifetime', $value)) {
            $this->_usedProperties['cookieLifetime'] = \true;
            $this->cookieLifetime = $value['cookie_lifetime'];
            unset($value['cookie_lifetime']);
        }
        if (array_key_exists('cookie_path', $value)) {
            $this->_usedProperties['cookiePath'] = \true;
            $this->cookiePath = $value['cookie_path'];
            unset($value['cookie_path']);
        }
        if (array_key_exists('cookie_domain', $value)) {
            $this->_usedProperties['cookieDomain'] = \true;
            $this->cookieDomain = $value['cookie_domain'];
            unset($value['cookie_domain']);
        }
        if (array_key_exists('cookie_secure', $value)) {
            $this->_usedProperties['cookieSecure'] = \true;
            $this->cookieSecure = $value['cookie_secure'];
            unset($value['cookie_secure']);
        }
        if (array_key_exists('cookie_httponly', $value)) {
            $this->_usedProperties['cookieHttponly'] = \true;
            $this->cookieHttponly = $value['cookie_httponly'];
            unset($value['cookie_httponly']);
        }
        if (array_key_exists('cookie_samesite', $value)) {
            $this->_usedProperties['cookieSamesite'] = \true;
            $this->cookieSamesite = $value['cookie_samesite'];
            unset($value['cookie_samesite']);
        }
        if (array_key_exists('use_cookies', $value)) {
            $this->_usedProperties['useCookies'] = \true;
            $this->useCookies = $value['use_cookies'];
            unset($value['use_cookies']);
        }
        if (array_key_exists('gc_divisor', $value)) {
            $this->_usedProperties['gcDivisor'] = \true;
            $this->gcDivisor = $value['gc_divisor'];
            unset($value['gc_divisor']);
        }
        if (array_key_exists('gc_probability', $value)) {
            $this->_usedProperties['gcProbability'] = \true;
            $this->gcProbability = $value['gc_probability'];
            unset($value['gc_probability']);
        }
        if (array_key_exists('gc_maxlifetime', $value)) {
            $this->_usedProperties['gcMaxlifetime'] = \true;
            $this->gcMaxlifetime = $value['gc_maxlifetime'];
            unset($value['gc_maxlifetime']);
        }
        if (array_key_exists('save_path', $value)) {
            $this->_usedProperties['savePath'] = \true;
            $this->savePath = $value['save_path'];
            unset($value['save_path']);
        }
        if (array_key_exists('metadata_update_threshold', $value)) {
            $this->_usedProperties['metadataUpdateThreshold'] = \true;
            $this->metadataUpdateThreshold = $value['metadata_update_threshold'];
            unset($value['metadata_update_threshold']);
        }
        if (array_key_exists('sid_length', $value)) {
            $this->_usedProperties['sidLength'] = \true;
            $this->sidLength = $value['sid_length'];
            unset($value['sid_length']);
        }
        if (array_key_exists('sid_bits_per_character', $value)) {
            $this->_usedProperties['sidBitsPerCharacter'] = \true;
            $this->sidBitsPerCharacter = $value['sid_bits_per_character'];
            unset($value['sid_bits_per_character']);
        }
        if ([] !== $value) {
            throw new InvalidConfigurationException(sprintf('The following keys are not supported by "%s": ', __CLASS__) . implode(', ', array_keys($value)));
        }
    }
    public function toArray(): array
    {
        $output = [];
        if (isset($this->_usedProperties['enabled'])) {
            $output['enabled'] = $this->enabled;
        }
        if (isset($this->_usedProperties['storageFactoryId'])) {
            $output['storage_factory_id'] = $this->storageFactoryId;
        }
        if (isset($this->_usedProperties['handlerId'])) {
            $output['handler_id'] = $this->handlerId;
        }
        if (isset($this->_usedProperties['name'])) {
            $output['name'] = $this->name;
        }
        if (isset($this->_usedProperties['cookieLifetime'])) {
            $output['cookie_lifetime'] = $this->cookieLifetime;
        }
        if (isset($this->_usedProperties['cookiePath'])) {
            $output['cookie_path'] = $this->cookiePath;
        }
        if (isset($this->_usedProperties['cookieDomain'])) {
            $output['cookie_domain'] = $this->cookieDomain;
        }
        if (isset($this->_usedProperties['cookieSecure'])) {
            $output['cookie_secure'] = $this->cookieSecure;
        }
        if (isset($this->_usedProperties['cookieHttponly'])) {
            $output['cookie_httponly'] = $this->cookieHttponly;
        }
        if (isset($this->_usedProperties['cookieSamesite'])) {
            $output['cookie_samesite'] = $this->cookieSamesite;
        }
        if (isset($this->_usedProperties['useCookies'])) {
            $output['use_cookies'] = $this->useCookies;
        }
        if (isset($this->_usedProperties['gcDivisor'])) {
            $output['gc_divisor'] = $this->gcDivisor;
        }
        if (isset($this->_usedProperties['gcProbability'])) {
            $output['gc_probability'] = $this->gcProbability;
        }
        if (isset($this->_usedProperties['gcMaxlifetime'])) {
            $output['gc_maxlifetime'] = $this->gcMaxlifetime;
        }
        if (isset($this->_usedProperties['savePath'])) {
            $output['save_path'] = $this->savePath;
        }
        if (isset($this->_usedProperties['metadataUpdateThreshold'])) {
            $output['metadata_update_threshold'] = $this->metadataUpdateThreshold;
        }
        if (isset($this->_usedProperties['sidLength'])) {
            $output['sid_length'] = $this->sidLength;
        }
        if (isset($this->_usedProperties['sidBitsPerCharacter'])) {
            $output['sid_bits_per_character'] = $this->sidBitsPerCharacter;
        }
        return $output;
    }
}
<?php

namespace _ContaoManager\Symfony\Config\Framework\HtmlSanitizer;

use _ContaoManager\Symfony\Component\Config\Loader\ParamConfigurator;
use _ContaoManager\Symfony\Component\Config\Definition\Exception\InvalidConfigurationException;
/**
 * This class is automatically generated to help in creating a config.
 */
class SanitizerConfig
{
    private $allowSafeElements;
    private $allowStaticElements;
    private $allowElements;
    private $blockElements;
    private $dropElements;
    private $allowAttributes;
    private $dropAttributes;
    private $forceAttributes;
    private $forceHttpsUrls;
    private $allowedLinkSchemes;
    private $allowedLinkHosts;
    private $allowRelativeLinks;
    private $allowedMediaSchemes;
    private $allowedMediaHosts;
    private $allowRelativeMedias;
    private $withAttributeSanitizers;
    private $withoutAttributeSanitizers;
    private $maxInputLength;
    private $_usedProperties = [];
    /**
     * Allows "safe" elements and attributes.
     * @default false
     * @param ParamConfigurator|bool $value
     * @return $this
     */
    public function allowSafeElements($value): static
    {
        $this->_usedProperties['allowSafeElements'] = \true;
        $this->allowSafeElements = $value;
        return $this;
    }
    /**
     * Allows all static elements and attributes from the W3C Sanitizer API standard.
     * @default false
     * @param ParamConfigurator|bool $value
     * @return $this
     */
    public function allowStaticElements($value): static
    {
        $this->_usedProperties['allowStaticElements'] = \true;
        $this->allowStaticElements = $value;
        return $this;
    }
    /**
     * @return $this
     */
    public function allowElement(string $name, mixed $value): static
    {
        $this->_usedProperties['allowElements'] = \true;
        $this->allowElements[$name] = $value;
        return $this;
    }
    /**
     * @param ParamConfigurator|list<ParamConfigurator|mixed>|string $value
     *
     * @return $this
     */
    public function blockElements(ParamConfigurator|string|array $value): static
    {
        $this->_usedProperties['blockElements'] = \true;
        $this->blockElements = $value;
        return $this;
    }
    /**
     * @param ParamConfigurator|list<ParamConfigurator|mixed>|string $value
     *
     * @return $this
     */
    public function dropElements(ParamConfigurator|string|array $value): static
    {
        $this->_usedProperties['dropElements'] = \true;
        $this->dropElements = $value;
        return $this;
    }
    /**
     * @return $this
     */
    public function allowAttribute(string $name, mixed $value): static
    {
        $this->_usedProperties['allowAttributes'] = \true;
        $this->allowAttributes[$name] = $value;
        return $this;
    }
    /**
     * @return $this
     */
    public function dropAttribute(string $name, mixed $value): static
    {
        $this->_usedProperties['dropAttributes'] = \true;
        $this->dropAttributes[$name] = $value;
        return $this;
    }
    /**
     * @return $this
     */
    public function forceAttribute(string $name, ParamConfigurator|array $value): static
    {
        $this->_usedProperties['forceAttributes'] = \true;
        $this->forceAttributes[$name] = $value;
        return $this;
    }
    /**
     * Transforms URLs using the HTTP scheme to use the HTTPS scheme instead.
     * @default false
     * @param ParamConfigurator|bool $value
     * @return $this
     */
    public function forceHttpsUrls($value): static
    {
        $this->_usedProperties['forceHttpsUrls'] = \true;
        $this->forceHttpsUrls = $value;
        return $this;
    }
    /**
     * @param ParamConfigurator|list<ParamConfigurator|mixed> $value
     *
     * @return $this
     */
    public function allowedLinkSchemes(ParamConfigurator|array $value): static
    {
        $this->_usedProperties['allowedLinkSchemes'] = \true;
        $this->allowedLinkSchemes = $value;
        return $this;
    }
    /**
     * Allows only a given list of hosts to be used in links href attributes.
     * @default null
     * @param ParamConfigurator|mixed $value
     *
     * @return $this
     */
    public function allowedLinkHosts(mixed $value = NULL): static
    {
        $this->_usedProperties['allowedLinkHosts'] = \true;
        $this->allowedLinkHosts = $value;
        return $this;
    }
    /**
     * Allows relative URLs to be used in links href attributes.
     * @default false
     * @param ParamConfigurator|bool $value
     * @return $this
     */
    public function allowRelativeLinks($value): static
    {
        $this->_usedProperties['allowRelativeLinks'] = \true;
        $this->allowRelativeLinks = $value;
        return $this;
    }
    /**
     * @param ParamConfigurator|list<ParamConfigurator|mixed> $value
     *
     * @return $this
     */
    public function allowedMediaSchemes(ParamConfigurator|array $value): static
    {
        $this->_usedProperties['allowedMediaSchemes'] = \true;
        $this->allowedMediaSchemes = $value;
        return $this;
    }
    /**
     * Allows only a given list of hosts to be used in media source attributes (img, audio, video, ...).
     * @default null
     * @param ParamConfigurator|mixed $value
     *
     * @return $this
     */
    public function allowedMediaHosts(mixed $value = NULL): static
    {
        $this->_usedProperties['allowedMediaHosts'] = \true;
        $this->allowedMediaHosts = $value;
        return $this;
    }
    /**
     * Allows relative URLs to be used in media source attributes (img, audio, video, ...).
     * @default false
     * @param ParamConfigurator|bool $value
     * @return $this
     */
    public function allowRelativeMedias($value): static
    {
        $this->_usedProperties['allowRelativeMedias'] = \true;
        $this->allowRelativeMedias = $value;
        return $this;
    }
    /**
     * @param ParamConfigurator|list<ParamConfigurator|mixed> $value
     *
     * @return $this
     */
    public function withAttributeSanitizers(ParamConfigurator|array $value): static
    {
        $this->_usedProperties['withAttributeSanitizers'] = \true;
        $this->withAttributeSanitizers = $value;
        return $this;
    }
    /**
     * @param ParamConfigurator|list<ParamConfigurator|mixed> $value
     *
     * @return $this
     */
    public function withoutAttributeSanitizers(ParamConfigurator|array $value): static
    {
        $this->_usedProperties['withoutAttributeSanitizers'] = \true;
        $this->withoutAttributeSanitizers = $value;
        return $this;
    }
    /**
     * The maximum length allowed for the sanitized input.
     * @default 0
     * @param ParamConfigurator|int $value
     * @return $this
     */
    public function maxInputLength($value): static
    {
        $this->_usedProperties['maxInputLength'] = \true;
        $this->maxInputLength = $value;
        return $this;
    }
    public function __construct(array $value = [])
    {
        if (array_key_exists('allow_safe_elements', $value)) {
            $this->_usedProperties['allowSafeElements'] = \true;
            $this->allowSafeElements = $value['allow_safe_elements'];
            unset($value['allow_safe_elements']);
        }
        if (array_key_exists('allow_static_elements', $value)) {
            $this->_usedProperties['allowStaticElements'] = \true;
            $this->allowStaticElements = $value['allow_static_elements'];
            unset($value['allow_static_elements']);
        }
        if (array_key_exists('allow_elements', $value)) {
            $this->_usedProperties['allowElements'] = \true;
            $this->allowElements = $value['allow_elements'];
            unset($value['allow_elements']);
        }
        if (array_key_exists('block_elements', $value)) {
            $this->_usedProperties['blockElements'] = \true;
            $this->blockElements = $value['block_elements'];
            unset($value['block_elements']);
        }
        if (array_key_exists('drop_elements', $value)) {
            $this->_usedProperties['dropElements'] = \true;
            $this->dropElements = $value['drop_elements'];
            unset($value['drop_elements']);
        }
        if (array_key_exists('allow_attributes', $value)) {
            $this->_usedProperties['allowAttributes'] = \true;
            $this->allowAttributes = $value['allow_attributes'];
            unset($value['allow_attributes']);
        }
        if (array_key_exists('drop_attributes', $value)) {
            $this->_usedProperties['dropAttributes'] = \true;
            $this->dropAttributes = $value['drop_attributes'];
            unset($value['drop_attributes']);
        }
        if (array_key_exists('force_attributes', $value)) {
            $this->_usedProperties['forceAttributes'] = \true;
            $this->forceAttributes = $value['force_attributes'];
            unset($value['force_attributes']);
        }
        if (array_key_exists('force_https_urls', $value)) {
            $this->_usedProperties['forceHttpsUrls'] = \true;
            $this->forceHttpsUrls = $value['force_https_urls'];
            unset($value['force_https_urls']);
        }
        if (array_key_exists('allowed_link_schemes', $value)) {
            $this->_usedProperties['allowedLinkSchemes'] = \true;
            $this->allowedLinkSchemes = $value['allowed_link_schemes'];
            unset($value['allowed_link_schemes']);
        }
        if (array_key_exists('allowed_link_hosts', $value)) {
            $this->_usedProperties['allowedLinkHosts'] = \true;
            $this->allowedLinkHosts = $value['allowed_link_hosts'];
            unset($value['allowed_link_hosts']);
        }
        if (array_key_exists('allow_relative_links', $value)) {
            $this->_usedProperties['allowRelativeLinks'] = \true;
            $this->allowRelativeLinks = $value['allow_relative_links'];
            unset($value['allow_relative_links']);
        }
        if (array_key_exists('allowed_media_schemes', $value)) {
            $this->_usedProperties['allowedMediaSchemes'] = \true;
            $this->allowedMediaSchemes = $value['allowed_media_schemes'];
            unset($value['allowed_media_schemes']);
        }
        if (array_key_exists('allowed_media_hosts', $value)) {
            $this->_usedProperties['allowedMediaHosts'] = \true;
            $this->allowedMediaHosts = $value['allowed_media_hosts'];
            unset($value['allowed_media_hosts']);
        }
        if (array_key_exists('allow_relative_medias', $value)) {
            $this->_usedProperties['allowRelativeMedias'] = \true;
            $this->allowRelativeMedias = $value['allow_relative_medias'];
            unset($value['allow_relative_medias']);
        }
        if (array_key_exists('with_attribute_sanitizers', $value)) {
            $this->_usedProperties['withAttributeSanitizers'] = \true;
            $this->withAttributeSanitizers = $value['with_attribute_sanitizers'];
            unset($value['with_attribute_sanitizers']);
        }
        if (array_key_exists('without_attribute_sanitizers', $value)) {
            $this->_usedProperties['withoutAttributeSanitizers'] = \true;
            $this->withoutAttributeSanitizers = $value['without_attribute_sanitizers'];
            unset($value['without_attribute_sanitizers']);
        }
        if (array_key_exists('max_input_length', $value)) {
            $this->_usedProperties['maxInputLength'] = \true;
            $this->maxInputLength = $value['max_input_length'];
            unset($value['max_input_length']);
        }
        if ([] !== $value) {
            throw new InvalidConfigurationException(sprintf('The following keys are not supported by "%s": ', __CLASS__) . implode(', ', array_keys($value)));
        }
    }
    public function toArray(): array
    {
        $output = [];
        if (isset($this->_usedProperties['allowSafeElements'])) {
            $output['allow_safe_elements'] = $this->allowSafeElements;
        }
        if (isset($this->_usedProperties['allowStaticElements'])) {
            $output['allow_static_elements'] = $this->allowStaticElements;
        }
        if (isset($this->_usedProperties['allowElements'])) {
            $output['allow_elements'] = $this->allowElements;
        }
        if (isset($this->_usedProperties['blockElements'])) {
            $output['block_elements'] = $this->blockElements;
        }
        if (isset($this->_usedProperties['dropElements'])) {
            $output['drop_elements'] = $this->dropElements;
        }
        if (isset($this->_usedProperties['allowAttributes'])) {
            $output['allow_attributes'] = $this->allowAttributes;
        }
        if (isset($this->_usedProperties['dropAttributes'])) {
            $output['drop_attributes'] = $this->dropAttributes;
        }
        if (isset($this->_usedProperties['forceAttributes'])) {
            $output['force_attributes'] = $this->forceAttributes;
        }
        if (isset($this->_usedProperties['forceHttpsUrls'])) {
            $output['force_https_urls'] = $this->forceHttpsUrls;
        }
        if (isset($this->_usedProperties['allowedLinkSchemes'])) {
            $output['allowed_link_schemes'] = $this->allowedLinkSchemes;
        }
        if (isset($this->_usedProperties['allowedLinkHosts'])) {
            $output['allowed_link_hosts'] = $this->allowedLinkHosts;
        }
        if (isset($this->_usedProperties['allowRelativeLinks'])) {
            $output['allow_relative_links'] = $this->allowRelativeLinks;
        }
        if (isset($this->_usedProperties['allowedMediaSchemes'])) {
            $output['allowed_media_schemes'] = $this->allowedMediaSchemes;
        }
        if (isset($this->_usedProperties['allowedMediaHosts'])) {
            $output['allowed_media_hosts'] = $this->allowedMediaHosts;
        }
        if (isset($this->_usedProperties['allowRelativeMedias'])) {
            $output['allow_relative_medias'] = $this->allowRelativeMedias;
        }
        if (isset($this->_usedProperties['withAttributeSanitizers'])) {
            $output['with_attribute_sanitizers'] = $this->withAttributeSanitizers;
        }
        if (isset($this->_usedProperties['withoutAttributeSanitizers'])) {
            $output['without_attribute_sanitizers'] = $this->withoutAttributeSanitizers;
        }
        if (isset($this->_usedProperties['maxInputLength'])) {
            $output['max_input_length'] = $this->maxInputLength;
        }
        return $output;
    }
}
<?php

namespace _ContaoManager\Symfony\Config\Framework;

require_once __DIR__ . \DIRECTORY_SEPARATOR . 'HttpClient' . \DIRECTORY_SEPARATOR . 'DefaultOptionsConfig.php';
require_once __DIR__ . \DIRECTORY_SEPARATOR . 'HttpClient' . \DIRECTORY_SEPARATOR . 'ScopedClientConfig.php';
use _ContaoManager\Symfony\Component\Config\Loader\ParamConfigurator;
use _ContaoManager\Symfony\Component\Config\Definition\Exception\InvalidConfigurationException;
/**
 * This class is automatically generated to help in creating a config.
 */
class HttpClientConfig
{
    private $enabled;
    private $maxHostConnections;
    private $defaultOptions;
    private $mockResponseFactory;
    private $scopedClients;
    private $_usedProperties = [];
    /**
     * @default false
     * @param ParamConfigurator|bool $value
     * @return $this
     */
    public function enabled($value): static
    {
        $this->_usedProperties['enabled'] = \true;
        $this->enabled = $value;
        return $this;
    }
    /**
     * The maximum number of connections to a single host.
     * @default null
     * @param ParamConfigurator|int $value
     * @return $this
     */
    public function maxHostConnections($value): static
    {
        $this->_usedProperties['maxHostConnections'] = \true;
        $this->maxHostConnections = $value;
        return $this;
    }
    public function defaultOptions(array $value = []): \_ContaoManager\Symfony\Config\Framework\HttpClient\DefaultOptionsConfig
    {
        if (null === $this->defaultOptions) {
            $this->_usedProperties['defaultOptions'] = \true;
            $this->defaultOptions = new \_ContaoManager\Symfony\Config\Framework\HttpClient\DefaultOptionsConfig($value);
        } elseif (0 < \func_num_args()) {
            throw new InvalidConfigurationException('The node created by "defaultOptions()" has already been initialized. You cannot pass values the second time you call defaultOptions().');
        }
        return $this->defaultOptions;
    }
    /**
     * The id of the service that should generate mock responses. It should be either an invokable or an iterable.
     * @default null
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function mockResponseFactory($value): static
    {
        $this->_usedProperties['mockResponseFactory'] = \true;
        $this->mockResponseFactory = $value;
        return $this;
    }
    /**
     * @template TValue of mixed
     * @param TValue $value
     * @return \Symfony\Config\Framework\HttpClient\ScopedClientConfig|$this
     * @psalm-return (TValue is array ? \Symfony\Config\Framework\HttpClient\ScopedClientConfig : static)
     */
    public function scopedClient(string $name, mixed $value = []): \_ContaoManager\Symfony\Config\Framework\HttpClient\ScopedClientConfig|static
    {
        if (!\is_array($value)) {
            $this->_usedProperties['scopedClients'] = \true;
            $this->scopedClients[$name] = $value;
            return $this;
        }
        if (!isset($this->scopedClients[$name]) || !$this->scopedClients[$name] instanceof \_ContaoManager\Symfony\Config\Framework\HttpClient\ScopedClientConfig) {
            $this->_usedProperties['scopedClients'] = \true;
            $this->scopedClients[$name] = new \_ContaoManager\Symfony\Config\Framework\HttpClient\ScopedClientConfig($value);
        } elseif (1 < \func_num_args()) {
            throw new InvalidConfigurationException('The node created by "scopedClient()" has already been initialized. You cannot pass values the second time you call scopedClient().');
        }
        return $this->scopedClients[$name];
    }
    public function __construct(array $value = [])
    {
        if (array_key_exists('enabled', $value)) {
            $this->_usedProperties['enabled'] = \true;
            $this->enabled = $value['enabled'];
            unset($value['enabled']);
        }
        if (array_key_exists('max_host_connections', $value)) {
            $this->_usedProperties['maxHostConnections'] = \true;
            $this->maxHostConnections = $value['max_host_connections'];
            unset($value['max_host_connections']);
        }
        if (array_key_exists('default_options', $value)) {
            $this->_usedProperties['defaultOptions'] = \true;
            $this->defaultOptions = new \_ContaoManager\Symfony\Config\Framework\HttpClient\DefaultOptionsConfig($value['default_options']);
            unset($value['default_options']);
        }
        if (array_key_exists('mock_response_factory', $value)) {
            $this->_usedProperties['mockResponseFactory'] = \true;
            $this->mockResponseFactory = $value['mock_response_factory'];
            unset($value['mock_response_factory']);
        }
        if (array_key_exists('scoped_clients', $value)) {
            $this->_usedProperties['scopedClients'] = \true;
            $this->scopedClients = array_map(fn($v) => \is_array($v) ? new \_ContaoManager\Symfony\Config\Framework\HttpClient\ScopedClientConfig($v) : $v, $value['scoped_clients']);
            unset($value['scoped_clients']);
        }
        if ([] !== $value) {
            throw new InvalidConfigurationException(sprintf('The following keys are not supported by "%s": ', __CLASS__) . implode(', ', array_keys($value)));
        }
    }
    public function toArray(): array
    {
        $output = [];
        if (isset($this->_usedProperties['enabled'])) {
            $output['enabled'] = $this->enabled;
        }
        if (isset($this->_usedProperties['maxHostConnections'])) {
            $output['max_host_connections'] = $this->maxHostConnections;
        }
        if (isset($this->_usedProperties['defaultOptions'])) {
            $output['default_options'] = $this->defaultOptions->toArray();
        }
        if (isset($this->_usedProperties['mockResponseFactory'])) {
            $output['mock_response_factory'] = $this->mockResponseFactory;
        }
        if (isset($this->_usedProperties['scopedClients'])) {
            $output['scoped_clients'] = array_map(fn($v) => $v instanceof \_ContaoManager\Symfony\Config\Framework\HttpClient\ScopedClientConfig ? $v->toArray() : $v, $this->scopedClients);
        }
        return $output;
    }
}
<?php

namespace _ContaoManager\Symfony\Config\Framework;

use _ContaoManager\Symfony\Component\Config\Loader\ParamConfigurator;
use _ContaoManager\Symfony\Component\Config\Definition\Exception\InvalidConfigurationException;
/**
 * This class is automatically generated to help in creating a config.
 */
class PhpErrorsConfig
{
    private $log;
    private $throw;
    private $_usedProperties = [];
    /**
     * Use the application logger instead of the PHP logger for logging PHP errors.
     * @example "true" to use the default configuration: log all errors. "false" to disable. An integer bit field of E_* constants, or an array mapping E_* constants to log levels.
     * @default null
     * @param ParamConfigurator|mixed $value
     *
     * @return $this
     */
    public function log(mixed $value): static
    {
        $this->_usedProperties['log'] = \true;
        $this->log = $value;
        return $this;
    }
    /**
     * Throw PHP errors as \ErrorException instances.
     * @default false
     * @param ParamConfigurator|bool $value
     * @return $this
     */
    public function throw($value): static
    {
        $this->_usedProperties['throw'] = \true;
        $this->throw = $value;
        return $this;
    }
    public function __construct(array $value = [])
    {
        if (array_key_exists('log', $value)) {
            $this->_usedProperties['log'] = \true;
            $this->log = $value['log'];
            unset($value['log']);
        }
        if (array_key_exists('throw', $value)) {
            $this->_usedProperties['throw'] = \true;
            $this->throw = $value['throw'];
            unset($value['throw']);
        }
        if ([] !== $value) {
            throw new InvalidConfigurationException(sprintf('The following keys are not supported by "%s": ', __CLASS__) . implode(', ', array_keys($value)));
        }
    }
    public function toArray(): array
    {
        $output = [];
        if (isset($this->_usedProperties['log'])) {
            $output['log'] = $this->log;
        }
        if (isset($this->_usedProperties['throw'])) {
            $output['throw'] = $this->throw;
        }
        return $output;
    }
}
<?php

namespace _ContaoManager\Symfony\Config\Framework;

require_once __DIR__ . \DIRECTORY_SEPARATOR . 'Notifier' . \DIRECTORY_SEPARATOR . 'AdminRecipientConfig.php';
use _ContaoManager\Symfony\Component\Config\Loader\ParamConfigurator;
use _ContaoManager\Symfony\Component\Config\Definition\Exception\InvalidConfigurationException;
/**
 * This class is automatically generated to help in creating a config.
 */
class NotifierConfig
{
    private $enabled;
    private $messageBus;
    private $chatterTransports;
    private $texterTransports;
    private $notificationOnFailedMessages;
    private $channelPolicy;
    private $adminRecipients;
    private $_usedProperties = [];
    /**
     * @default false
     * @param ParamConfigurator|bool $value
     * @return $this
     */
    public function enabled($value): static
    {
        $this->_usedProperties['enabled'] = \true;
        $this->enabled = $value;
        return $this;
    }
    /**
     * The message bus to use. Defaults to the default bus if the Messenger component is installed.
     * @default null
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function messageBus($value): static
    {
        $this->_usedProperties['messageBus'] = \true;
        $this->messageBus = $value;
        return $this;
    }
    /**
     * @return $this
     */
    public function chatterTransport(string $name, mixed $value): static
    {
        $this->_usedProperties['chatterTransports'] = \true;
        $this->chatterTransports[$name] = $value;
        return $this;
    }
    /**
     * @return $this
     */
    public function texterTransport(string $name, mixed $value): static
    {
        $this->_usedProperties['texterTransports'] = \true;
        $this->texterTransports[$name] = $value;
        return $this;
    }
    /**
     * @default false
     * @param ParamConfigurator|bool $value
     * @return $this
     */
    public function notificationOnFailedMessages($value): static
    {
        $this->_usedProperties['notificationOnFailedMessages'] = \true;
        $this->notificationOnFailedMessages = $value;
        return $this;
    }
    /**
     * @return $this
     */
    public function channelPolicy(string $name, ParamConfigurator|string|array $value): static
    {
        $this->_usedProperties['channelPolicy'] = \true;
        $this->channelPolicy[$name] = $value;
        return $this;
    }
    public function adminRecipient(array $value = []): \_ContaoManager\Symfony\Config\Framework\Notifier\AdminRecipientConfig
    {
        $this->_usedProperties['adminRecipients'] = \true;
        return $this->adminRecipients[] = new \_ContaoManager\Symfony\Config\Framework\Notifier\AdminRecipientConfig($value);
    }
    public function __construct(array $value = [])
    {
        if (array_key_exists('enabled', $value)) {
            $this->_usedProperties['enabled'] = \true;
            $this->enabled = $value['enabled'];
            unset($value['enabled']);
        }
        if (array_key_exists('message_bus', $value)) {
            $this->_usedProperties['messageBus'] = \true;
            $this->messageBus = $value['message_bus'];
            unset($value['message_bus']);
        }
        if (array_key_exists('chatter_transports', $value)) {
            $this->_usedProperties['chatterTransports'] = \true;
            $this->chatterTransports = $value['chatter_transports'];
            unset($value['chatter_transports']);
        }
        if (array_key_exists('texter_transports', $value)) {
            $this->_usedProperties['texterTransports'] = \true;
            $this->texterTransports = $value['texter_transports'];
            unset($value['texter_transports']);
        }
        if (array_key_exists('notification_on_failed_messages', $value)) {
            $this->_usedProperties['notificationOnFailedMessages'] = \true;
            $this->notificationOnFailedMessages = $value['notification_on_failed_messages'];
            unset($value['notification_on_failed_messages']);
        }
        if (array_key_exists('channel_policy', $value)) {
            $this->_usedProperties['channelPolicy'] = \true;
            $this->channelPolicy = $value['channel_policy'];
            unset($value['channel_policy']);
        }
        if (array_key_exists('admin_recipients', $value)) {
            $this->_usedProperties['adminRecipients'] = \true;
            $this->adminRecipients = array_map(fn($v) => new \_ContaoManager\Symfony\Config\Framework\Notifier\AdminRecipientConfig($v), $value['admin_recipients']);
            unset($value['admin_recipients']);
        }
        if ([] !== $value) {
            throw new InvalidConfigurationException(sprintf('The following keys are not supported by "%s": ', __CLASS__) . implode(', ', array_keys($value)));
        }
    }
    public function toArray(): array
    {
        $output = [];
        if (isset($this->_usedProperties['enabled'])) {
            $output['enabled'] = $this->enabled;
        }
        if (isset($this->_usedProperties['messageBus'])) {
            $output['message_bus'] = $this->messageBus;
        }
        if (isset($this->_usedProperties['chatterTransports'])) {
            $output['chatter_transports'] = $this->chatterTransports;
        }
        if (isset($this->_usedProperties['texterTransports'])) {
            $output['texter_transports'] = $this->texterTransports;
        }
        if (isset($this->_usedProperties['notificationOnFailedMessages'])) {
            $output['notification_on_failed_messages'] = $this->notificationOnFailedMessages;
        }
        if (isset($this->_usedProperties['channelPolicy'])) {
            $output['channel_policy'] = $this->channelPolicy;
        }
        if (isset($this->_usedProperties['adminRecipients'])) {
            $output['admin_recipients'] = array_map(fn($v) => $v->toArray(), $this->adminRecipients);
        }
        return $output;
    }
}
<?php

namespace _ContaoManager\Symfony\Config\Framework;

use _ContaoManager\Symfony\Component\Config\Loader\ParamConfigurator;
use _ContaoManager\Symfony\Component\Config\Definition\Exception\InvalidConfigurationException;
/**
 * This class is automatically generated to help in creating a config.
 */
class RequestConfig
{
    private $enabled;
    private $formats;
    private $_usedProperties = [];
    /**
     * @default false
     * @param ParamConfigurator|bool $value
     * @return $this
     */
    public function enabled($value): static
    {
        $this->_usedProperties['enabled'] = \true;
        $this->enabled = $value;
        return $this;
    }
    /**
     * @return $this
     */
    public function format(string $name, mixed $value): static
    {
        $this->_usedProperties['formats'] = \true;
        $this->formats[$name] = $value;
        return $this;
    }
    public function __construct(array $value = [])
    {
        if (array_key_exists('enabled', $value)) {
            $this->_usedProperties['enabled'] = \true;
            $this->enabled = $value['enabled'];
            unset($value['enabled']);
        }
        if (array_key_exists('formats', $value)) {
            $this->_usedProperties['formats'] = \true;
            $this->formats = $value['formats'];
            unset($value['formats']);
        }
        if ([] !== $value) {
            throw new InvalidConfigurationException(sprintf('The following keys are not supported by "%s": ', __CLASS__) . implode(', ', array_keys($value)));
        }
    }
    public function toArray(): array
    {
        $output = [];
        if (isset($this->_usedProperties['enabled'])) {
            $output['enabled'] = $this->enabled;
        }
        if (isset($this->_usedProperties['formats'])) {
            $output['formats'] = $this->formats;
        }
        return $output;
    }
}
<?php

namespace _ContaoManager\Symfony\Config\Framework;

use _ContaoManager\Symfony\Component\Config\Loader\ParamConfigurator;
use _ContaoManager\Symfony\Component\Config\Definition\Exception\InvalidConfigurationException;
/**
 * This class is automatically generated to help in creating a config.
 */
class AnnotationsConfig
{
    private $enabled;
    private $cache;
    private $fileCacheDir;
    private $debug;
    private $_usedProperties = [];
    /**
     * @default false
     * @param ParamConfigurator|bool $value
     * @return $this
     */
    public function enabled($value): static
    {
        $this->_usedProperties['enabled'] = \true;
        $this->enabled = $value;
        return $this;
    }
    /**
     * @default 'php_array'
     * @param ParamConfigurator|'none'|'php_array'|'file' $value
     * @return $this
     */
    public function cache($value): static
    {
        $this->_usedProperties['cache'] = \true;
        $this->cache = $value;
        return $this;
    }
    /**
     * @default '%kernel.cache_dir%/annotations'
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function fileCacheDir($value): static
    {
        $this->_usedProperties['fileCacheDir'] = \true;
        $this->fileCacheDir = $value;
        return $this;
    }
    /**
     * @default false
     * @param ParamConfigurator|bool $value
     * @return $this
     */
    public function debug($value): static
    {
        $this->_usedProperties['debug'] = \true;
        $this->debug = $value;
        return $this;
    }
    public function __construct(array $value = [])
    {
        if (array_key_exists('enabled', $value)) {
            $this->_usedProperties['enabled'] = \true;
            $this->enabled = $value['enabled'];
            unset($value['enabled']);
        }
        if (array_key_exists('cache', $value)) {
            $this->_usedProperties['cache'] = \true;
            $this->cache = $value['cache'];
            unset($value['cache']);
        }
        if (array_key_exists('file_cache_dir', $value)) {
            $this->_usedProperties['fileCacheDir'] = \true;
            $this->fileCacheDir = $value['file_cache_dir'];
            unset($value['file_cache_dir']);
        }
        if (array_key_exists('debug', $value)) {
            $this->_usedProperties['debug'] = \true;
            $this->debug = $value['debug'];
            unset($value['debug']);
        }
        if ([] !== $value) {
            throw new InvalidConfigurationException(sprintf('The following keys are not supported by "%s": ', __CLASS__) . implode(', ', array_keys($value)));
        }
    }
    public function toArray(): array
    {
        $output = [];
        if (isset($this->_usedProperties['enabled'])) {
            $output['enabled'] = $this->enabled;
        }
        if (isset($this->_usedProperties['cache'])) {
            $output['cache'] = $this->cache;
        }
        if (isset($this->_usedProperties['fileCacheDir'])) {
            $output['file_cache_dir'] = $this->fileCacheDir;
        }
        if (isset($this->_usedProperties['debug'])) {
            $output['debug'] = $this->debug;
        }
        return $output;
    }
}
<?php

namespace _ContaoManager\Symfony\Config\Framework\Assets;

use _ContaoManager\Symfony\Component\Config\Loader\ParamConfigurator;
use _ContaoManager\Symfony\Component\Config\Definition\Exception\InvalidConfigurationException;
/**
 * This class is automatically generated to help in creating a config.
 */
class PackageConfig
{
    private $strictMode;
    private $versionStrategy;
    private $version;
    private $versionFormat;
    private $jsonManifestPath;
    private $basePath;
    private $baseUrls;
    private $_usedProperties = [];
    /**
     * Throw an exception if an entry is missing from the manifest.json
     * @default false
     * @param ParamConfigurator|bool $value
     * @return $this
     */
    public function strictMode($value): static
    {
        $this->_usedProperties['strictMode'] = \true;
        $this->strictMode = $value;
        return $this;
    }
    /**
     * @default null
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function versionStrategy($value): static
    {
        $this->_usedProperties['versionStrategy'] = \true;
        $this->versionStrategy = $value;
        return $this;
    }
    /**
     * @default null
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function version($value): static
    {
        $this->_usedProperties['version'] = \true;
        $this->version = $value;
        return $this;
    }
    /**
     * @default null
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function versionFormat($value): static
    {
        $this->_usedProperties['versionFormat'] = \true;
        $this->versionFormat = $value;
        return $this;
    }
    /**
     * @default null
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function jsonManifestPath($value): static
    {
        $this->_usedProperties['jsonManifestPath'] = \true;
        $this->jsonManifestPath = $value;
        return $this;
    }
    /**
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function basePath($value): static
    {
        $this->_usedProperties['basePath'] = \true;
        $this->basePath = $value;
        return $this;
    }
    /**
     * @param ParamConfigurator|list<ParamConfigurator|mixed>|mixed $value
     *
     * @return $this
     */
    public function baseUrls(mixed $value): static
    {
        $this->_usedProperties['baseUrls'] = \true;
        $this->baseUrls = $value;
        return $this;
    }
    public function __construct(array $value = [])
    {
        if (array_key_exists('strict_mode', $value)) {
            $this->_usedProperties['strictMode'] = \true;
            $this->strictMode = $value['strict_mode'];
            unset($value['strict_mode']);
        }
        if (array_key_exists('version_strategy', $value)) {
            $this->_usedProperties['versionStrategy'] = \true;
            $this->versionStrategy = $value['version_strategy'];
            unset($value['version_strategy']);
        }
        if (array_key_exists('version', $value)) {
            $this->_usedProperties['version'] = \true;
            $this->version = $value['version'];
            unset($value['version']);
        }
        if (array_key_exists('version_format', $value)) {
            $this->_usedProperties['versionFormat'] = \true;
            $this->versionFormat = $value['version_format'];
            unset($value['version_format']);
        }
        if (array_key_exists('json_manifest_path', $value)) {
            $this->_usedProperties['jsonManifestPath'] = \true;
            $this->jsonManifestPath = $value['json_manifest_path'];
            unset($value['json_manifest_path']);
        }
        if (array_key_exists('base_path', $value)) {
            $this->_usedProperties['basePath'] = \true;
            $this->basePath = $value['base_path'];
            unset($value['base_path']);
        }
        if (array_key_exists('base_urls', $value)) {
            $this->_usedProperties['baseUrls'] = \true;
            $this->baseUrls = $value['base_urls'];
            unset($value['base_urls']);
        }
        if ([] !== $value) {
            throw new InvalidConfigurationException(sprintf('The following keys are not supported by "%s": ', __CLASS__) . implode(', ', array_keys($value)));
        }
    }
    public function toArray(): array
    {
        $output = [];
        if (isset($this->_usedProperties['strictMode'])) {
            $output['strict_mode'] = $this->strictMode;
        }
        if (isset($this->_usedProperties['versionStrategy'])) {
            $output['version_strategy'] = $this->versionStrategy;
        }
        if (isset($this->_usedProperties['version'])) {
            $output['version'] = $this->version;
        }
        if (isset($this->_usedProperties['versionFormat'])) {
            $output['version_format'] = $this->versionFormat;
        }
        if (isset($this->_usedProperties['jsonManifestPath'])) {
            $output['json_manifest_path'] = $this->jsonManifestPath;
        }
        if (isset($this->_usedProperties['basePath'])) {
            $output['base_path'] = $this->basePath;
        }
        if (isset($this->_usedProperties['baseUrls'])) {
            $output['base_urls'] = $this->baseUrls;
        }
        return $output;
    }
}
<?php

namespace _ContaoManager\Symfony\Config\Framework\Validation;

use _ContaoManager\Symfony\Component\Config\Loader\ParamConfigurator;
use _ContaoManager\Symfony\Component\Config\Definition\Exception\InvalidConfigurationException;
/**
 * This class is automatically generated to help in creating a config.
 */
class NotCompromisedPasswordConfig
{
    private $enabled;
    private $endpoint;
    private $_usedProperties = [];
    /**
     * When disabled, compromised passwords will be accepted as valid.
     * @default true
     * @param ParamConfigurator|bool $value
     * @return $this
     */
    public function enabled($value): static
    {
        $this->_usedProperties['enabled'] = \true;
        $this->enabled = $value;
        return $this;
    }
    /**
     * API endpoint for the NotCompromisedPassword Validator.
     * @default null
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function endpoint($value): static
    {
        $this->_usedProperties['endpoint'] = \true;
        $this->endpoint = $value;
        return $this;
    }
    public function __construct(array $value = [])
    {
        if (array_key_exists('enabled', $value)) {
            $this->_usedProperties['enabled'] = \true;
            $this->enabled = $value['enabled'];
            unset($value['enabled']);
        }
        if (array_key_exists('endpoint', $value)) {
            $this->_usedProperties['endpoint'] = \true;
            $this->endpoint = $value['endpoint'];
            unset($value['endpoint']);
        }
        if ([] !== $value) {
            throw new InvalidConfigurationException(sprintf('The following keys are not supported by "%s": ', __CLASS__) . implode(', ', array_keys($value)));
        }
    }
    public function toArray(): array
    {
        $output = [];
        if (isset($this->_usedProperties['enabled'])) {
            $output['enabled'] = $this->enabled;
        }
        if (isset($this->_usedProperties['endpoint'])) {
            $output['endpoint'] = $this->endpoint;
        }
        return $output;
    }
}
<?php

namespace _ContaoManager\Symfony\Config\Framework\Validation;

use _ContaoManager\Symfony\Component\Config\Loader\ParamConfigurator;
use _ContaoManager\Symfony\Component\Config\Definition\Exception\InvalidConfigurationException;
/**
 * This class is automatically generated to help in creating a config.
 */
class MappingConfig
{
    private $paths;
    private $_usedProperties = [];
    /**
     * @param ParamConfigurator|list<ParamConfigurator|mixed> $value
     *
     * @return $this
     */
    public function paths(ParamConfigurator|array $value): static
    {
        $this->_usedProperties['paths'] = \true;
        $this->paths = $value;
        return $this;
    }
    public function __construct(array $value = [])
    {
        if (array_key_exists('paths', $value)) {
            $this->_usedProperties['paths'] = \true;
            $this->paths = $value['paths'];
            unset($value['paths']);
        }
        if ([] !== $value) {
            throw new InvalidConfigurationException(sprintf('The following keys are not supported by "%s": ', __CLASS__) . implode(', ', array_keys($value)));
        }
    }
    public function toArray(): array
    {
        $output = [];
        if (isset($this->_usedProperties['paths'])) {
            $output['paths'] = $this->paths;
        }
        return $output;
    }
}
<?php

namespace _ContaoManager\Symfony\Config\Framework\Validation;

use _ContaoManager\Symfony\Component\Config\Loader\ParamConfigurator;
use _ContaoManager\Symfony\Component\Config\Definition\Exception\InvalidConfigurationException;
/**
 * This class is automatically generated to help in creating a config.
 */
class AutoMappingConfig
{
    private $services;
    private $_usedProperties = [];
    /**
     * @param ParamConfigurator|list<ParamConfigurator|mixed> $value
     *
     * @return $this
     */
    public function services(ParamConfigurator|array $value): static
    {
        $this->_usedProperties['services'] = \true;
        $this->services = $value;
        return $this;
    }
    public function __construct(array $value = [])
    {
        if (array_key_exists('services', $value)) {
            $this->_usedProperties['services'] = \true;
            $this->services = $value['services'];
            unset($value['services']);
        }
        if ([] !== $value) {
            throw new InvalidConfigurationException(sprintf('The following keys are not supported by "%s": ', __CLASS__) . implode(', ', array_keys($value)));
        }
    }
    public function toArray(): array
    {
        $output = [];
        if (isset($this->_usedProperties['services'])) {
            $output['services'] = $this->services;
        }
        return $output;
    }
}
<?php

namespace _ContaoManager\Symfony\Config\Framework;

use _ContaoManager\Symfony\Component\Config\Loader\ParamConfigurator;
use _ContaoManager\Symfony\Component\Config\Definition\Exception\InvalidConfigurationException;
/**
 * This class is automatically generated to help in creating a config.
 */
class LockConfig
{
    private $enabled;
    private $resources;
    private $_usedProperties = [];
    /**
     * @default false
     * @param ParamConfigurator|bool $value
     * @return $this
     */
    public function enabled($value): static
    {
        $this->_usedProperties['enabled'] = \true;
        $this->enabled = $value;
        return $this;
    }
    /**
     * @return $this
     */
    public function resource(string $name, ParamConfigurator|string|array $value): static
    {
        $this->_usedProperties['resources'] = \true;
        $this->resources[$name] = $value;
        return $this;
    }
    public function __construct(array $value = [])
    {
        if (array_key_exists('enabled', $value)) {
            $this->_usedProperties['enabled'] = \true;
            $this->enabled = $value['enabled'];
            unset($value['enabled']);
        }
        if (array_key_exists('resources', $value)) {
            $this->_usedProperties['resources'] = \true;
            $this->resources = $value['resources'];
            unset($value['resources']);
        }
        if ([] !== $value) {
            throw new InvalidConfigurationException(sprintf('The following keys are not supported by "%s": ', __CLASS__) . implode(', ', array_keys($value)));
        }
    }
    public function toArray(): array
    {
        $output = [];
        if (isset($this->_usedProperties['enabled'])) {
            $output['enabled'] = $this->enabled;
        }
        if (isset($this->_usedProperties['resources'])) {
            $output['resources'] = $this->resources;
        }
        return $output;
    }
}
<?php

namespace _ContaoManager\Symfony\Config\Framework;

use _ContaoManager\Symfony\Component\Config\Loader\ParamConfigurator;
use _ContaoManager\Symfony\Component\Config\Definition\Exception\InvalidConfigurationException;
/**
 * This class is automatically generated to help in creating a config.
 */
class SchedulerConfig
{
    private $enabled;
    private $_usedProperties = [];
    /**
     * @default false
     * @param ParamConfigurator|bool $value
     * @return $this
     */
    public function enabled($value): static
    {
        $this->_usedProperties['enabled'] = \true;
        $this->enabled = $value;
        return $this;
    }
    public function __construct(array $value = [])
    {
        if (array_key_exists('enabled', $value)) {
            $this->_usedProperties['enabled'] = \true;
            $this->enabled = $value['enabled'];
            unset($value['enabled']);
        }
        if ([] !== $value) {
            throw new InvalidConfigurationException(sprintf('The following keys are not supported by "%s": ', __CLASS__) . implode(', ', array_keys($value)));
        }
    }
    public function toArray(): array
    {
        $output = [];
        if (isset($this->_usedProperties['enabled'])) {
            $output['enabled'] = $this->enabled;
        }
        return $output;
    }
}
<?php

namespace _ContaoManager\Symfony\Config\Framework;

require_once __DIR__ . \DIRECTORY_SEPARATOR . 'Form' . \DIRECTORY_SEPARATOR . 'CsrfProtectionConfig.php';
use _ContaoManager\Symfony\Component\Config\Loader\ParamConfigurator;
use _ContaoManager\Symfony\Component\Config\Definition\Exception\InvalidConfigurationException;
/**
 * This class is automatically generated to help in creating a config.
 */
class FormConfig
{
    private $enabled;
    private $csrfProtection;
    private $legacyErrorMessages;
    private $_usedProperties = [];
    /**
     * @default false
     * @param ParamConfigurator|bool $value
     * @return $this
     */
    public function enabled($value): static
    {
        $this->_usedProperties['enabled'] = \true;
        $this->enabled = $value;
        return $this;
    }
    /**
     * @default {"enabled":null,"field_name":"_token"}
     */
    public function csrfProtection(array $value = []): \_ContaoManager\Symfony\Config\Framework\Form\CsrfProtectionConfig
    {
        if (null === $this->csrfProtection) {
            $this->_usedProperties['csrfProtection'] = \true;
            $this->csrfProtection = new \_ContaoManager\Symfony\Config\Framework\Form\CsrfProtectionConfig($value);
        } elseif (0 < \func_num_args()) {
            throw new InvalidConfigurationException('The node created by "csrfProtection()" has already been initialized. You cannot pass values the second time you call csrfProtection().');
        }
        return $this->csrfProtection;
    }
    /**
     * @default null
     * @param ParamConfigurator|bool $value
     * @deprecated The child node "legacy_error_messages" at path "form" is deprecated.
     * @return $this
     */
    public function legacyErrorMessages($value): static
    {
        $this->_usedProperties['legacyErrorMessages'] = \true;
        $this->legacyErrorMessages = $value;
        return $this;
    }
    public function __construct(array $value = [])
    {
        if (array_key_exists('enabled', $value)) {
            $this->_usedProperties['enabled'] = \true;
            $this->enabled = $value['enabled'];
            unset($value['enabled']);
        }
        if (array_key_exists('csrf_protection', $value)) {
            $this->_usedProperties['csrfProtection'] = \true;
            $this->csrfProtection = new \_ContaoManager\Symfony\Config\Framework\Form\CsrfProtectionConfig($value['csrf_protection']);
            unset($value['csrf_protection']);
        }
        if (array_key_exists('legacy_error_messages', $value)) {
            $this->_usedProperties['legacyErrorMessages'] = \true;
            $this->legacyErrorMessages = $value['legacy_error_messages'];
            unset($value['legacy_error_messages']);
        }
        if ([] !== $value) {
            throw new InvalidConfigurationException(sprintf('The following keys are not supported by "%s": ', __CLASS__) . implode(', ', array_keys($value)));
        }
    }
    public function toArray(): array
    {
        $output = [];
        if (isset($this->_usedProperties['enabled'])) {
            $output['enabled'] = $this->enabled;
        }
        if (isset($this->_usedProperties['csrfProtection'])) {
            $output['csrf_protection'] = $this->csrfProtection->toArray();
        }
        if (isset($this->_usedProperties['legacyErrorMessages'])) {
            $output['legacy_error_messages'] = $this->legacyErrorMessages;
        }
        return $output;
    }
}
<?php

namespace _ContaoManager\Symfony\Config\Security\ProviderConfig\Memory;

use _ContaoManager\Symfony\Component\Config\Loader\ParamConfigurator;
use _ContaoManager\Symfony\Component\Config\Definition\Exception\InvalidConfigurationException;
/**
 * This class is automatically generated to help in creating a config.
 */
class UserConfig
{
    private $password;
    private $roles;
    private $_usedProperties = [];
    /**
     * @default null
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function password($value): static
    {
        $this->_usedProperties['password'] = \true;
        $this->password = $value;
        return $this;
    }
    /**
     * @param ParamConfigurator|list<ParamConfigurator|mixed>|string $value
     *
     * @return $this
     */
    public function roles(ParamConfigurator|string|array $value): static
    {
        $this->_usedProperties['roles'] = \true;
        $this->roles = $value;
        return $this;
    }
    public function __construct(array $value = [])
    {
        if (array_key_exists('password', $value)) {
            $this->_usedProperties['password'] = \true;
            $this->password = $value['password'];
            unset($value['password']);
        }
        if (array_key_exists('roles', $value)) {
            $this->_usedProperties['roles'] = \true;
            $this->roles = $value['roles'];
            unset($value['roles']);
        }
        if ([] !== $value) {
            throw new InvalidConfigurationException(sprintf('The following keys are not supported by "%s": ', __CLASS__) . implode(', ', array_keys($value)));
        }
    }
    public function toArray(): array
    {
        $output = [];
        if (isset($this->_usedProperties['password'])) {
            $output['password'] = $this->password;
        }
        if (isset($this->_usedProperties['roles'])) {
            $output['roles'] = $this->roles;
        }
        return $output;
    }
}
<?php

namespace _ContaoManager\Symfony\Config\Security\ProviderConfig;

use _ContaoManager\Symfony\Component\Config\Loader\ParamConfigurator;
use _ContaoManager\Symfony\Component\Config\Definition\Exception\InvalidConfigurationException;
/**
 * This class is automatically generated to help in creating a config.
 */
class LdapConfig
{
    private $service;
    private $baseDn;
    private $searchDn;
    private $searchPassword;
    private $extraFields;
    private $defaultRoles;
    private $uidKey;
    private $filter;
    private $passwordAttribute;
    private $_usedProperties = [];
    /**
     * @default 'ldap'
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function service($value): static
    {
        $this->_usedProperties['service'] = \true;
        $this->service = $value;
        return $this;
    }
    /**
     * @default null
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function baseDn($value): static
    {
        $this->_usedProperties['baseDn'] = \true;
        $this->baseDn = $value;
        return $this;
    }
    /**
     * @default null
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function searchDn($value): static
    {
        $this->_usedProperties['searchDn'] = \true;
        $this->searchDn = $value;
        return $this;
    }
    /**
     * @default null
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function searchPassword($value): static
    {
        $this->_usedProperties['searchPassword'] = \true;
        $this->searchPassword = $value;
        return $this;
    }
    /**
     * @param ParamConfigurator|list<ParamConfigurator|mixed> $value
     *
     * @return $this
     */
    public function extraFields(ParamConfigurator|array $value): static
    {
        $this->_usedProperties['extraFields'] = \true;
        $this->extraFields = $value;
        return $this;
    }
    /**
     * @param ParamConfigurator|list<ParamConfigurator|mixed>|string $value
     *
     * @return $this
     */
    public function defaultRoles(ParamConfigurator|string|array $value): static
    {
        $this->_usedProperties['defaultRoles'] = \true;
        $this->defaultRoles = $value;
        return $this;
    }
    /**
     * @default 'sAMAccountName'
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function uidKey($value): static
    {
        $this->_usedProperties['uidKey'] = \true;
        $this->uidKey = $value;
        return $this;
    }
    /**
     * @default '({uid_key}={username})'
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function filter($value): static
    {
        $this->_usedProperties['filter'] = \true;
        $this->filter = $value;
        return $this;
    }
    /**
     * @default null
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function passwordAttribute($value): static
    {
        $this->_usedProperties['passwordAttribute'] = \true;
        $this->passwordAttribute = $value;
        return $this;
    }
    public function __construct(array $value = [])
    {
        if (array_key_exists('service', $value)) {
            $this->_usedProperties['service'] = \true;
            $this->service = $value['service'];
            unset($value['service']);
        }
        if (array_key_exists('base_dn', $value)) {
            $this->_usedProperties['baseDn'] = \true;
            $this->baseDn = $value['base_dn'];
            unset($value['base_dn']);
        }
        if (array_key_exists('search_dn', $value)) {
            $this->_usedProperties['searchDn'] = \true;
            $this->searchDn = $value['search_dn'];
            unset($value['search_dn']);
        }
        if (array_key_exists('search_password', $value)) {
            $this->_usedProperties['searchPassword'] = \true;
            $this->searchPassword = $value['search_password'];
            unset($value['search_password']);
        }
        if (array_key_exists('extra_fields', $value)) {
            $this->_usedProperties['extraFields'] = \true;
            $this->extraFields = $value['extra_fields'];
            unset($value['extra_fields']);
        }
        if (array_key_exists('default_roles', $value)) {
            $this->_usedProperties['defaultRoles'] = \true;
            $this->defaultRoles = $value['default_roles'];
            unset($value['default_roles']);
        }
        if (array_key_exists('uid_key', $value)) {
            $this->_usedProperties['uidKey'] = \true;
            $this->uidKey = $value['uid_key'];
            unset($value['uid_key']);
        }
        if (array_key_exists('filter', $value)) {
            $this->_usedProperties['filter'] = \true;
            $this->filter = $value['filter'];
            unset($value['filter']);
        }
        if (array_key_exists('password_attribute', $value)) {
            $this->_usedProperties['passwordAttribute'] = \true;
            $this->passwordAttribute = $value['password_attribute'];
            unset($value['password_attribute']);
        }
        if ([] !== $value) {
            throw new InvalidConfigurationException(sprintf('The following keys are not supported by "%s": ', __CLASS__) . implode(', ', array_keys($value)));
        }
    }
    public function toArray(): array
    {
        $output = [];
        if (isset($this->_usedProperties['service'])) {
            $output['service'] = $this->service;
        }
        if (isset($this->_usedProperties['baseDn'])) {
            $output['base_dn'] = $this->baseDn;
        }
        if (isset($this->_usedProperties['searchDn'])) {
            $output['search_dn'] = $this->searchDn;
        }
        if (isset($this->_usedProperties['searchPassword'])) {
            $output['search_password'] = $this->searchPassword;
        }
        if (isset($this->_usedProperties['extraFields'])) {
            $output['extra_fields'] = $this->extraFields;
        }
        if (isset($this->_usedProperties['defaultRoles'])) {
            $output['default_roles'] = $this->defaultRoles;
        }
        if (isset($this->_usedProperties['uidKey'])) {
            $output['uid_key'] = $this->uidKey;
        }
        if (isset($this->_usedProperties['filter'])) {
            $output['filter'] = $this->filter;
        }
        if (isset($this->_usedProperties['passwordAttribute'])) {
            $output['password_attribute'] = $this->passwordAttribute;
        }
        return $output;
    }
}
<?php

namespace _ContaoManager\Symfony\Config\Security\ProviderConfig;

require_once __DIR__ . \DIRECTORY_SEPARATOR . 'Memory' . \DIRECTORY_SEPARATOR . 'UserConfig.php';
use _ContaoManager\Symfony\Component\Config\Definition\Exception\InvalidConfigurationException;
/**
 * This class is automatically generated to help in creating a config.
 */
class MemoryConfig
{
    private $users;
    private $_usedProperties = [];
    public function user(string $identifier, array $value = []): \_ContaoManager\Symfony\Config\Security\ProviderConfig\Memory\UserConfig
    {
        if (!isset($this->users[$identifier])) {
            $this->_usedProperties['users'] = \true;
            $this->users[$identifier] = new \_ContaoManager\Symfony\Config\Security\ProviderConfig\Memory\UserConfig($value);
        } elseif (1 < \func_num_args()) {
            throw new InvalidConfigurationException('The node created by "user()" has already been initialized. You cannot pass values the second time you call user().');
        }
        return $this->users[$identifier];
    }
    public function __construct(array $value = [])
    {
        if (array_key_exists('users', $value)) {
            $this->_usedProperties['users'] = \true;
            $this->users = array_map(fn($v) => new \_ContaoManager\Symfony\Config\Security\ProviderConfig\Memory\UserConfig($v), $value['users']);
            unset($value['users']);
        }
        if ([] !== $value) {
            throw new InvalidConfigurationException(sprintf('The following keys are not supported by "%s": ', __CLASS__) . implode(', ', array_keys($value)));
        }
    }
    public function toArray(): array
    {
        $output = [];
        if (isset($this->_usedProperties['users'])) {
            $output['users'] = array_map(fn($v) => $v->toArray(), $this->users);
        }
        return $output;
    }
}
<?php

namespace _ContaoManager\Symfony\Config\Security\ProviderConfig;

use _ContaoManager\Symfony\Component\Config\Loader\ParamConfigurator;
use _ContaoManager\Symfony\Component\Config\Definition\Exception\InvalidConfigurationException;
/**
 * This class is automatically generated to help in creating a config.
 */
class ChainConfig
{
    private $providers;
    private $_usedProperties = [];
    /**
     * @param ParamConfigurator|list<ParamConfigurator|mixed>|string $value
     *
     * @return $this
     */
    public function providers(ParamConfigurator|string|array $value): static
    {
        $this->_usedProperties['providers'] = \true;
        $this->providers = $value;
        return $this;
    }
    public function __construct(array $value = [])
    {
        if (array_key_exists('providers', $value)) {
            $this->_usedProperties['providers'] = \true;
            $this->providers = $value['providers'];
            unset($value['providers']);
        }
        if ([] !== $value) {
            throw new InvalidConfigurationException(sprintf('The following keys are not supported by "%s": ', __CLASS__) . implode(', ', array_keys($value)));
        }
    }
    public function toArray(): array
    {
        $output = [];
        if (isset($this->_usedProperties['providers'])) {
            $output['providers'] = $this->providers;
        }
        return $output;
    }
}
<?php

namespace _ContaoManager\Symfony\Config\Security;

use _ContaoManager\Symfony\Component\Config\Loader\ParamConfigurator;
use _ContaoManager\Symfony\Component\Config\Definition\Exception\InvalidConfigurationException;
/**
 * This class is automatically generated to help in creating a config.
 */
class PasswordHasherConfig
{
    private $algorithm;
    private $migrateFrom;
    private $hashAlgorithm;
    private $keyLength;
    private $ignoreCase;
    private $encodeAsBase64;
    private $iterations;
    private $cost;
    private $memoryCost;
    private $timeCost;
    private $id;
    private $_usedProperties = [];
    /**
     * @default null
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function algorithm($value): static
    {
        $this->_usedProperties['algorithm'] = \true;
        $this->algorithm = $value;
        return $this;
    }
    /**
     * @param ParamConfigurator|list<ParamConfigurator|mixed>|mixed $value
     *
     * @return $this
     */
    public function migrateFrom(mixed $value): static
    {
        $this->_usedProperties['migrateFrom'] = \true;
        $this->migrateFrom = $value;
        return $this;
    }
    /**
     * Name of hashing algorithm for PBKDF2 (i.e. sha256, sha512, etc..) See hash_algos() for a list of supported algorithms.
     * @default 'sha512'
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function hashAlgorithm($value): static
    {
        $this->_usedProperties['hashAlgorithm'] = \true;
        $this->hashAlgorithm = $value;
        return $this;
    }
    /**
     * @default 40
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function keyLength($value): static
    {
        $this->_usedProperties['keyLength'] = \true;
        $this->keyLength = $value;
        return $this;
    }
    /**
     * @default false
     * @param ParamConfigurator|bool $value
     * @return $this
     */
    public function ignoreCase($value): static
    {
        $this->_usedProperties['ignoreCase'] = \true;
        $this->ignoreCase = $value;
        return $this;
    }
    /**
     * @default true
     * @param ParamConfigurator|bool $value
     * @return $this
     */
    public function encodeAsBase64($value): static
    {
        $this->_usedProperties['encodeAsBase64'] = \true;
        $this->encodeAsBase64 = $value;
        return $this;
    }
    /**
     * @default 5000
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function iterations($value): static
    {
        $this->_usedProperties['iterations'] = \true;
        $this->iterations = $value;
        return $this;
    }
    /**
     * @default null
     * @param ParamConfigurator|int $value
     * @return $this
     */
    public function cost($value): static
    {
        $this->_usedProperties['cost'] = \true;
        $this->cost = $value;
        return $this;
    }
    /**
     * @default null
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function memoryCost($value): static
    {
        $this->_usedProperties['memoryCost'] = \true;
        $this->memoryCost = $value;
        return $this;
    }
    /**
     * @default null
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function timeCost($value): static
    {
        $this->_usedProperties['timeCost'] = \true;
        $this->timeCost = $value;
        return $this;
    }
    /**
     * @default null
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function id($value): static
    {
        $this->_usedProperties['id'] = \true;
        $this->id = $value;
        return $this;
    }
    public function __construct(array $value = [])
    {
        if (array_key_exists('algorithm', $value)) {
            $this->_usedProperties['algorithm'] = \true;
            $this->algorithm = $value['algorithm'];
            unset($value['algorithm']);
        }
        if (array_key_exists('migrate_from', $value)) {
            $this->_usedProperties['migrateFrom'] = \true;
            $this->migrateFrom = $value['migrate_from'];
            unset($value['migrate_from']);
        }
        if (array_key_exists('hash_algorithm', $value)) {
            $this->_usedProperties['hashAlgorithm'] = \true;
            $this->hashAlgorithm = $value['hash_algorithm'];
            unset($value['hash_algorithm']);
        }
        if (array_key_exists('key_length', $value)) {
            $this->_usedProperties['keyLength'] = \true;
            $this->keyLength = $value['key_length'];
            unset($value['key_length']);
        }
        if (array_key_exists('ignore_case', $value)) {
            $this->_usedProperties['ignoreCase'] = \true;
            $this->ignoreCase = $value['ignore_case'];
            unset($value['ignore_case']);
        }
        if (array_key_exists('encode_as_base64', $value)) {
            $this->_usedProperties['encodeAsBase64'] = \true;
            $this->encodeAsBase64 = $value['encode_as_base64'];
            unset($value['encode_as_base64']);
        }
        if (array_key_exists('iterations', $value)) {
            $this->_usedProperties['iterations'] = \true;
            $this->iterations = $value['iterations'];
            unset($value['iterations']);
        }
        if (array_key_exists('cost', $value)) {
            $this->_usedProperties['cost'] = \true;
            $this->cost = $value['cost'];
            unset($value['cost']);
        }
        if (array_key_exists('memory_cost', $value)) {
            $this->_usedProperties['memoryCost'] = \true;
            $this->memoryCost = $value['memory_cost'];
            unset($value['memory_cost']);
        }
        if (array_key_exists('time_cost', $value)) {
            $this->_usedProperties['timeCost'] = \true;
            $this->timeCost = $value['time_cost'];
            unset($value['time_cost']);
        }
        if (array_key_exists('id', $value)) {
            $this->_usedProperties['id'] = \true;
            $this->id = $value['id'];
            unset($value['id']);
        }
        if ([] !== $value) {
            throw new InvalidConfigurationException(sprintf('The following keys are not supported by "%s": ', __CLASS__) . implode(', ', array_keys($value)));
        }
    }
    public function toArray(): array
    {
        $output = [];
        if (isset($this->_usedProperties['algorithm'])) {
            $output['algorithm'] = $this->algorithm;
        }
        if (isset($this->_usedProperties['migrateFrom'])) {
            $output['migrate_from'] = $this->migrateFrom;
        }
        if (isset($this->_usedProperties['hashAlgorithm'])) {
            $output['hash_algorithm'] = $this->hashAlgorithm;
        }
        if (isset($this->_usedProperties['keyLength'])) {
            $output['key_length'] = $this->keyLength;
        }
        if (isset($this->_usedProperties['ignoreCase'])) {
            $output['ignore_case'] = $this->ignoreCase;
        }
        if (isset($this->_usedProperties['encodeAsBase64'])) {
            $output['encode_as_base64'] = $this->encodeAsBase64;
        }
        if (isset($this->_usedProperties['iterations'])) {
            $output['iterations'] = $this->iterations;
        }
        if (isset($this->_usedProperties['cost'])) {
            $output['cost'] = $this->cost;
        }
        if (isset($this->_usedProperties['memoryCost'])) {
            $output['memory_cost'] = $this->memoryCost;
        }
        if (isset($this->_usedProperties['timeCost'])) {
            $output['time_cost'] = $this->timeCost;
        }
        if (isset($this->_usedProperties['id'])) {
            $output['id'] = $this->id;
        }
        return $output;
    }
}
<?php

namespace _ContaoManager\Symfony\Config\Security;

require_once __DIR__ . \DIRECTORY_SEPARATOR . 'ProviderConfig' . \DIRECTORY_SEPARATOR . 'ChainConfig.php';
require_once __DIR__ . \DIRECTORY_SEPARATOR . 'ProviderConfig' . \DIRECTORY_SEPARATOR . 'MemoryConfig.php';
require_once __DIR__ . \DIRECTORY_SEPARATOR . 'ProviderConfig' . \DIRECTORY_SEPARATOR . 'LdapConfig.php';
use _ContaoManager\Symfony\Component\Config\Loader\ParamConfigurator;
use _ContaoManager\Symfony\Component\Config\Definition\Exception\InvalidConfigurationException;
/**
 * This class is automatically generated to help in creating a config.
 */
class ProviderConfig
{
    private $id;
    private $chain;
    private $memory;
    private $ldap;
    private $_usedProperties = [];
    /**
     * @default null
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function id($value): static
    {
        $this->_usedProperties['id'] = \true;
        $this->id = $value;
        return $this;
    }
    public function chain(array $value = []): \_ContaoManager\Symfony\Config\Security\ProviderConfig\ChainConfig
    {
        if (null === $this->chain) {
            $this->_usedProperties['chain'] = \true;
            $this->chain = new \_ContaoManager\Symfony\Config\Security\ProviderConfig\ChainConfig($value);
        } elseif (0 < \func_num_args()) {
            throw new InvalidConfigurationException('The node created by "chain()" has already been initialized. You cannot pass values the second time you call chain().');
        }
        return $this->chain;
    }
    public function memory(array $value = []): \_ContaoManager\Symfony\Config\Security\ProviderConfig\MemoryConfig
    {
        if (null === $this->memory) {
            $this->_usedProperties['memory'] = \true;
            $this->memory = new \_ContaoManager\Symfony\Config\Security\ProviderConfig\MemoryConfig($value);
        } elseif (0 < \func_num_args()) {
            throw new InvalidConfigurationException('The node created by "memory()" has already been initialized. You cannot pass values the second time you call memory().');
        }
        return $this->memory;
    }
    public function ldap(array $value = []): \_ContaoManager\Symfony\Config\Security\ProviderConfig\LdapConfig
    {
        if (null === $this->ldap) {
            $this->_usedProperties['ldap'] = \true;
            $this->ldap = new \_ContaoManager\Symfony\Config\Security\ProviderConfig\LdapConfig($value);
        } elseif (0 < \func_num_args()) {
            throw new InvalidConfigurationException('The node created by "ldap()" has already been initialized. You cannot pass values the second time you call ldap().');
        }
        return $this->ldap;
    }
    public function __construct(array $value = [])
    {
        if (array_key_exists('id', $value)) {
            $this->_usedProperties['id'] = \true;
            $this->id = $value['id'];
            unset($value['id']);
        }
        if (array_key_exists('chain', $value)) {
            $this->_usedProperties['chain'] = \true;
            $this->chain = new \_ContaoManager\Symfony\Config\Security\ProviderConfig\ChainConfig($value['chain']);
            unset($value['chain']);
        }
        if (array_key_exists('memory', $value)) {
            $this->_usedProperties['memory'] = \true;
            $this->memory = new \_ContaoManager\Symfony\Config\Security\ProviderConfig\MemoryConfig($value['memory']);
            unset($value['memory']);
        }
        if (array_key_exists('ldap', $value)) {
            $this->_usedProperties['ldap'] = \true;
            $this->ldap = new \_ContaoManager\Symfony\Config\Security\ProviderConfig\LdapConfig($value['ldap']);
            unset($value['ldap']);
        }
        if ([] !== $value) {
            throw new InvalidConfigurationException(sprintf('The following keys are not supported by "%s": ', __CLASS__) . implode(', ', array_keys($value)));
        }
    }
    public function toArray(): array
    {
        $output = [];
        if (isset($this->_usedProperties['id'])) {
            $output['id'] = $this->id;
        }
        if (isset($this->_usedProperties['chain'])) {
            $output['chain'] = $this->chain->toArray();
        }
        if (isset($this->_usedProperties['memory'])) {
            $output['memory'] = $this->memory->toArray();
        }
        if (isset($this->_usedProperties['ldap'])) {
            $output['ldap'] = $this->ldap->toArray();
        }
        return $output;
    }
}
<?php

namespace _ContaoManager\Symfony\Config\Security;

require_once __DIR__ . \DIRECTORY_SEPARATOR . 'FirewallConfig' . \DIRECTORY_SEPARATOR . 'LogoutConfig.php';
require_once __DIR__ . \DIRECTORY_SEPARATOR . 'FirewallConfig' . \DIRECTORY_SEPARATOR . 'SwitchUserConfig.php';
require_once __DIR__ . \DIRECTORY_SEPARATOR . 'FirewallConfig' . \DIRECTORY_SEPARATOR . 'LoginThrottlingConfig.php';
require_once __DIR__ . \DIRECTORY_SEPARATOR . 'FirewallConfig' . \DIRECTORY_SEPARATOR . 'X509Config.php';
require_once __DIR__ . \DIRECTORY_SEPARATOR . 'FirewallConfig' . \DIRECTORY_SEPARATOR . 'RemoteUserConfig.php';
require_once __DIR__ . \DIRECTORY_SEPARATOR . 'FirewallConfig' . \DIRECTORY_SEPARATOR . 'LoginLinkConfig.php';
require_once __DIR__ . \DIRECTORY_SEPARATOR . 'FirewallConfig' . \DIRECTORY_SEPARATOR . 'FormLoginConfig.php';
require_once __DIR__ . \DIRECTORY_SEPARATOR . 'FirewallConfig' . \DIRECTORY_SEPARATOR . 'FormLoginLdapConfig.php';
require_once __DIR__ . \DIRECTORY_SEPARATOR . 'FirewallConfig' . \DIRECTORY_SEPARATOR . 'JsonLoginConfig.php';
require_once __DIR__ . \DIRECTORY_SEPARATOR . 'FirewallConfig' . \DIRECTORY_SEPARATOR . 'JsonLoginLdapConfig.php';
require_once __DIR__ . \DIRECTORY_SEPARATOR . 'FirewallConfig' . \DIRECTORY_SEPARATOR . 'AccessTokenConfig.php';
require_once __DIR__ . \DIRECTORY_SEPARATOR . 'FirewallConfig' . \DIRECTORY_SEPARATOR . 'HttpBasicConfig.php';
require_once __DIR__ . \DIRECTORY_SEPARATOR . 'FirewallConfig' . \DIRECTORY_SEPARATOR . 'HttpBasicLdapConfig.php';
require_once __DIR__ . \DIRECTORY_SEPARATOR . 'FirewallConfig' . \DIRECTORY_SEPARATOR . 'RememberMeConfig.php';
use _ContaoManager\Symfony\Component\Config\Loader\ParamConfigurator;
use _ContaoManager\Symfony\Component\Config\Definition\Exception\InvalidConfigurationException;
/**
 * This class is automatically generated to help in creating a config.
 */
class FirewallConfig
{
    private $pattern;
    private $host;
    private $methods;
    private $security;
    private $userChecker;
    private $requestMatcher;
    private $accessDeniedUrl;
    private $accessDeniedHandler;
    private $entryPoint;
    private $provider;
    private $stateless;
    private $lazy;
    private $context;
    private $logout;
    private $switchUser;
    private $requiredBadges;
    private $customAuthenticators;
    private $loginThrottling;
    private $x509;
    private $remoteUser;
    private $loginLink;
    private $formLogin;
    private $formLoginLdap;
    private $jsonLogin;
    private $jsonLoginLdap;
    private $accessToken;
    private $httpBasic;
    private $httpBasicLdap;
    private $rememberMe;
    private $_usedProperties = [];
    /**
     * @default null
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function pattern($value): static
    {
        $this->_usedProperties['pattern'] = \true;
        $this->pattern = $value;
        return $this;
    }
    /**
     * @default null
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function host($value): static
    {
        $this->_usedProperties['host'] = \true;
        $this->host = $value;
        return $this;
    }
    /**
     * @param ParamConfigurator|list<ParamConfigurator|mixed>|string $value
     *
     * @return $this
     */
    public function methods(ParamConfigurator|string|array $value): static
    {
        $this->_usedProperties['methods'] = \true;
        $this->methods = $value;
        return $this;
    }
    /**
     * @default true
     * @param ParamConfigurator|bool $value
     * @return $this
     */
    public function security($value): static
    {
        $this->_usedProperties['security'] = \true;
        $this->security = $value;
        return $this;
    }
    /**
     * The UserChecker to use when authenticating users in this firewall.
     * @default 'security.user_checker'
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function userChecker($value): static
    {
        $this->_usedProperties['userChecker'] = \true;
        $this->userChecker = $value;
        return $this;
    }
    /**
     * @default null
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function requestMatcher($value): static
    {
        $this->_usedProperties['requestMatcher'] = \true;
        $this->requestMatcher = $value;
        return $this;
    }
    /**
     * @default null
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function accessDeniedUrl($value): static
    {
        $this->_usedProperties['accessDeniedUrl'] = \true;
        $this->accessDeniedUrl = $value;
        return $this;
    }
    /**
     * @default null
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function accessDeniedHandler($value): static
    {
        $this->_usedProperties['accessDeniedHandler'] = \true;
        $this->accessDeniedHandler = $value;
        return $this;
    }
    /**
     * An enabled authenticator name or a service id that implements "Symfony\Component\Security\Http\EntryPoint\AuthenticationEntryPointInterface"
     * @default null
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function entryPoint($value): static
    {
        $this->_usedProperties['entryPoint'] = \true;
        $this->entryPoint = $value;
        return $this;
    }
    /**
     * @default null
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function provider($value): static
    {
        $this->_usedProperties['provider'] = \true;
        $this->provider = $value;
        return $this;
    }
    /**
     * @default false
     * @param ParamConfigurator|bool $value
     * @return $this
     */
    public function stateless($value): static
    {
        $this->_usedProperties['stateless'] = \true;
        $this->stateless = $value;
        return $this;
    }
    /**
     * @default false
     * @param ParamConfigurator|bool $value
     * @return $this
     */
    public function lazy($value): static
    {
        $this->_usedProperties['lazy'] = \true;
        $this->lazy = $value;
        return $this;
    }
    /**
     * @default null
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function context($value): static
    {
        $this->_usedProperties['context'] = \true;
        $this->context = $value;
        return $this;
    }
    /**
     * @template TValue of mixed
     * @param TValue $value
     * @return \Symfony\Config\Security\FirewallConfig\LogoutConfig|$this
     * @psalm-return (TValue is array ? \Symfony\Config\Security\FirewallConfig\LogoutConfig : static)
     */
    public function logout(mixed $value = []): \_ContaoManager\Symfony\Config\Security\FirewallConfig\LogoutConfig|static
    {
        if (!\is_array($value)) {
            $this->_usedProperties['logout'] = \true;
            $this->logout = $value;
            return $this;
        }
        if (!$this->logout instanceof \_ContaoManager\Symfony\Config\Security\FirewallConfig\LogoutConfig) {
            $this->_usedProperties['logout'] = \true;
            $this->logout = new \_ContaoManager\Symfony\Config\Security\FirewallConfig\LogoutConfig($value);
        } elseif (0 < \func_num_args()) {
            throw new InvalidConfigurationException('The node created by "logout()" has already been initialized. You cannot pass values the second time you call logout().');
        }
        return $this->logout;
    }
    public function switchUser(array $value = []): \_ContaoManager\Symfony\Config\Security\FirewallConfig\SwitchUserConfig
    {
        if (null === $this->switchUser) {
            $this->_usedProperties['switchUser'] = \true;
            $this->switchUser = new \_ContaoManager\Symfony\Config\Security\FirewallConfig\SwitchUserConfig($value);
        } elseif (0 < \func_num_args()) {
            throw new InvalidConfigurationException('The node created by "switchUser()" has already been initialized. You cannot pass values the second time you call switchUser().');
        }
        return $this->switchUser;
    }
    /**
     * @param ParamConfigurator|list<ParamConfigurator|mixed> $value
     *
     * @return $this
     */
    public function requiredBadges(ParamConfigurator|array $value): static
    {
        $this->_usedProperties['requiredBadges'] = \true;
        $this->requiredBadges = $value;
        return $this;
    }
    /**
     * @param ParamConfigurator|list<ParamConfigurator|mixed> $value
     *
     * @return $this
     */
    public function customAuthenticators(ParamConfigurator|array $value): static
    {
        $this->_usedProperties['customAuthenticators'] = \true;
        $this->customAuthenticators = $value;
        return $this;
    }
    public function loginThrottling(array $value = []): \_ContaoManager\Symfony\Config\Security\FirewallConfig\LoginThrottlingConfig
    {
        if (null === $this->loginThrottling) {
            $this->_usedProperties['loginThrottling'] = \true;
            $this->loginThrottling = new \_ContaoManager\Symfony\Config\Security\FirewallConfig\LoginThrottlingConfig($value);
        } elseif (0 < \func_num_args()) {
            throw new InvalidConfigurationException('The node created by "loginThrottling()" has already been initialized. You cannot pass values the second time you call loginThrottling().');
        }
        return $this->loginThrottling;
    }
    public function x509(array $value = []): \_ContaoManager\Symfony\Config\Security\FirewallConfig\X509Config
    {
        if (null === $this->x509) {
            $this->_usedProperties['x509'] = \true;
            $this->x509 = new \_ContaoManager\Symfony\Config\Security\FirewallConfig\X509Config($value);
        } elseif (0 < \func_num_args()) {
            throw new InvalidConfigurationException('The node created by "x509()" has already been initialized. You cannot pass values the second time you call x509().');
        }
        return $this->x509;
    }
    public function remoteUser(array $value = []): \_ContaoManager\Symfony\Config\Security\FirewallConfig\RemoteUserConfig
    {
        if (null === $this->remoteUser) {
            $this->_usedProperties['remoteUser'] = \true;
            $this->remoteUser = new \_ContaoManager\Symfony\Config\Security\FirewallConfig\RemoteUserConfig($value);
        } elseif (0 < \func_num_args()) {
            throw new InvalidConfigurationException('The node created by "remoteUser()" has already been initialized. You cannot pass values the second time you call remoteUser().');
        }
        return $this->remoteUser;
    }
    public function loginLink(array $value = []): \_ContaoManager\Symfony\Config\Security\FirewallConfig\LoginLinkConfig
    {
        if (null === $this->loginLink) {
            $this->_usedProperties['loginLink'] = \true;
            $this->loginLink = new \_ContaoManager\Symfony\Config\Security\FirewallConfig\LoginLinkConfig($value);
        } elseif (0 < \func_num_args()) {
            throw new InvalidConfigurationException('The node created by "loginLink()" has already been initialized. You cannot pass values the second time you call loginLink().');
        }
        return $this->loginLink;
    }
    public function formLogin(array $value = []): \_ContaoManager\Symfony\Config\Security\FirewallConfig\FormLoginConfig
    {
        if (null === $this->formLogin) {
            $this->_usedProperties['formLogin'] = \true;
            $this->formLogin = new \_ContaoManager\Symfony\Config\Security\FirewallConfig\FormLoginConfig($value);
        } elseif (0 < \func_num_args()) {
            throw new InvalidConfigurationException('The node created by "formLogin()" has already been initialized. You cannot pass values the second time you call formLogin().');
        }
        return $this->formLogin;
    }
    public function formLoginLdap(array $value = []): \_ContaoManager\Symfony\Config\Security\FirewallConfig\FormLoginLdapConfig
    {
        if (null === $this->formLoginLdap) {
            $this->_usedProperties['formLoginLdap'] = \true;
            $this->formLoginLdap = new \_ContaoManager\Symfony\Config\Security\FirewallConfig\FormLoginLdapConfig($value);
        } elseif (0 < \func_num_args()) {
            throw new InvalidConfigurationException('The node created by "formLoginLdap()" has already been initialized. You cannot pass values the second time you call formLoginLdap().');
        }
        return $this->formLoginLdap;
    }
    public function jsonLogin(array $value = []): \_ContaoManager\Symfony\Config\Security\FirewallConfig\JsonLoginConfig
    {
        if (null === $this->jsonLogin) {
            $this->_usedProperties['jsonLogin'] = \true;
            $this->jsonLogin = new \_ContaoManager\Symfony\Config\Security\FirewallConfig\JsonLoginConfig($value);
        } elseif (0 < \func_num_args()) {
            throw new InvalidConfigurationException('The node created by "jsonLogin()" has already been initialized. You cannot pass values the second time you call jsonLogin().');
        }
        return $this->jsonLogin;
    }
    public function jsonLoginLdap(array $value = []): \_ContaoManager\Symfony\Config\Security\FirewallConfig\JsonLoginLdapConfig
    {
        if (null === $this->jsonLoginLdap) {
            $this->_usedProperties['jsonLoginLdap'] = \true;
            $this->jsonLoginLdap = new \_ContaoManager\Symfony\Config\Security\FirewallConfig\JsonLoginLdapConfig($value);
        } elseif (0 < \func_num_args()) {
            throw new InvalidConfigurationException('The node created by "jsonLoginLdap()" has already been initialized. You cannot pass values the second time you call jsonLoginLdap().');
        }
        return $this->jsonLoginLdap;
    }
    public function accessToken(array $value = []): \_ContaoManager\Symfony\Config\Security\FirewallConfig\AccessTokenConfig
    {
        if (null === $this->accessToken) {
            $this->_usedProperties['accessToken'] = \true;
            $this->accessToken = new \_ContaoManager\Symfony\Config\Security\FirewallConfig\AccessTokenConfig($value);
        } elseif (0 < \func_num_args()) {
            throw new InvalidConfigurationException('The node created by "accessToken()" has already been initialized. You cannot pass values the second time you call accessToken().');
        }
        return $this->accessToken;
    }
    public function httpBasic(array $value = []): \_ContaoManager\Symfony\Config\Security\FirewallConfig\HttpBasicConfig
    {
        if (null === $this->httpBasic) {
            $this->_usedProperties['httpBasic'] = \true;
            $this->httpBasic = new \_ContaoManager\Symfony\Config\Security\FirewallConfig\HttpBasicConfig($value);
        } elseif (0 < \func_num_args()) {
            throw new InvalidConfigurationException('The node created by "httpBasic()" has already been initialized. You cannot pass values the second time you call httpBasic().');
        }
        return $this->httpBasic;
    }
    public function httpBasicLdap(array $value = []): \_ContaoManager\Symfony\Config\Security\FirewallConfig\HttpBasicLdapConfig
    {
        if (null === $this->httpBasicLdap) {
            $this->_usedProperties['httpBasicLdap'] = \true;
            $this->httpBasicLdap = new \_ContaoManager\Symfony\Config\Security\FirewallConfig\HttpBasicLdapConfig($value);
        } elseif (0 < \func_num_args()) {
            throw new InvalidConfigurationException('The node created by "httpBasicLdap()" has already been initialized. You cannot pass values the second time you call httpBasicLdap().');
        }
        return $this->httpBasicLdap;
    }
    public function rememberMe(array $value = []): \_ContaoManager\Symfony\Config\Security\FirewallConfig\RememberMeConfig
    {
        if (null === $this->rememberMe) {
            $this->_usedProperties['rememberMe'] = \true;
            $this->rememberMe = new \_ContaoManager\Symfony\Config\Security\FirewallConfig\RememberMeConfig($value);
        } elseif (0 < \func_num_args()) {
            throw new InvalidConfigurationException('The node created by "rememberMe()" has already been initialized. You cannot pass values the second time you call rememberMe().');
        }
        return $this->rememberMe;
    }
    public function __construct(array $value = [])
    {
        if (array_key_exists('pattern', $value)) {
            $this->_usedProperties['pattern'] = \true;
            $this->pattern = $value['pattern'];
            unset($value['pattern']);
        }
        if (array_key_exists('host', $value)) {
            $this->_usedProperties['host'] = \true;
            $this->host = $value['host'];
            unset($value['host']);
        }
        if (array_key_exists('methods', $value)) {
            $this->_usedProperties['methods'] = \true;
            $this->methods = $value['methods'];
            unset($value['methods']);
        }
        if (array_key_exists('security', $value)) {
            $this->_usedProperties['security'] = \true;
            $this->security = $value['security'];
            unset($value['security']);
        }
        if (array_key_exists('user_checker', $value)) {
            $this->_usedProperties['userChecker'] = \true;
            $this->userChecker = $value['user_checker'];
            unset($value['user_checker']);
        }
        if (array_key_exists('request_matcher', $value)) {
            $this->_usedProperties['requestMatcher'] = \true;
            $this->requestMatcher = $value['request_matcher'];
            unset($value['request_matcher']);
        }
        if (array_key_exists('access_denied_url', $value)) {
            $this->_usedProperties['accessDeniedUrl'] = \true;
            $this->accessDeniedUrl = $value['access_denied_url'];
            unset($value['access_denied_url']);
        }
        if (array_key_exists('access_denied_handler', $value)) {
            $this->_usedProperties['accessDeniedHandler'] = \true;
            $this->accessDeniedHandler = $value['access_denied_handler'];
            unset($value['access_denied_handler']);
        }
        if (array_key_exists('entry_point', $value)) {
            $this->_usedProperties['entryPoint'] = \true;
            $this->entryPoint = $value['entry_point'];
            unset($value['entry_point']);
        }
        if (array_key_exists('provider', $value)) {
            $this->_usedProperties['provider'] = \true;
            $this->provider = $value['provider'];
            unset($value['provider']);
        }
        if (array_key_exists('stateless', $value)) {
            $this->_usedProperties['stateless'] = \true;
            $this->stateless = $value['stateless'];
            unset($value['stateless']);
        }
        if (array_key_exists('lazy', $value)) {
            $this->_usedProperties['lazy'] = \true;
            $this->lazy = $value['lazy'];
            unset($value['lazy']);
        }
        if (array_key_exists('context', $value)) {
            $this->_usedProperties['context'] = \true;
            $this->context = $value['context'];
            unset($value['context']);
        }
        if (array_key_exists('logout', $value)) {
            $this->_usedProperties['logout'] = \true;
            $this->logout = \is_array($value['logout']) ? new \_ContaoManager\Symfony\Config\Security\FirewallConfig\LogoutConfig($value['logout']) : $value['logout'];
            unset($value['logout']);
        }
        if (array_key_exists('switch_user', $value)) {
            $this->_usedProperties['switchUser'] = \true;
            $this->switchUser = new \_ContaoManager\Symfony\Config\Security\FirewallConfig\SwitchUserConfig($value['switch_user']);
            unset($value['switch_user']);
        }
        if (array_key_exists('required_badges', $value)) {
            $this->_usedProperties['requiredBadges'] = \true;
            $this->requiredBadges = $value['required_badges'];
            unset($value['required_badges']);
        }
        if (array_key_exists('custom_authenticators', $value)) {
            $this->_usedProperties['customAuthenticators'] = \true;
            $this->customAuthenticators = $value['custom_authenticators'];
            unset($value['custom_authenticators']);
        }
        if (array_key_exists('login_throttling', $value)) {
            $this->_usedProperties['loginThrottling'] = \true;
            $this->loginThrottling = new \_ContaoManager\Symfony\Config\Security\FirewallConfig\LoginThrottlingConfig($value['login_throttling']);
            unset($value['login_throttling']);
        }
        if (array_key_exists('x509', $value)) {
            $this->_usedProperties['x509'] = \true;
            $this->x509 = new \_ContaoManager\Symfony\Config\Security\FirewallConfig\X509Config($value['x509']);
            unset($value['x509']);
        }
        if (array_key_exists('remote_user', $value)) {
            $this->_usedProperties['remoteUser'] = \true;
            $this->remoteUser = new \_ContaoManager\Symfony\Config\Security\FirewallConfig\RemoteUserConfig($value['remote_user']);
            unset($value['remote_user']);
        }
        if (array_key_exists('login_link', $value)) {
            $this->_usedProperties['loginLink'] = \true;
            $this->loginLink = new \_ContaoManager\Symfony\Config\Security\FirewallConfig\LoginLinkConfig($value['login_link']);
            unset($value['login_link']);
        }
        if (array_key_exists('form_login', $value)) {
            $this->_usedProperties['formLogin'] = \true;
            $this->formLogin = new \_ContaoManager\Symfony\Config\Security\FirewallConfig\FormLoginConfig($value['form_login']);
            unset($value['form_login']);
        }
        if (array_key_exists('form_login_ldap', $value)) {
            $this->_usedProperties['formLoginLdap'] = \true;
            $this->formLoginLdap = new \_ContaoManager\Symfony\Config\Security\FirewallConfig\FormLoginLdapConfig($value['form_login_ldap']);
            unset($value['form_login_ldap']);
        }
        if (array_key_exists('json_login', $value)) {
            $this->_usedProperties['jsonLogin'] = \true;
            $this->jsonLogin = new \_ContaoManager\Symfony\Config\Security\FirewallConfig\JsonLoginConfig($value['json_login']);
            unset($value['json_login']);
        }
        if (array_key_exists('json_login_ldap', $value)) {
            $this->_usedProperties['jsonLoginLdap'] = \true;
            $this->jsonLoginLdap = new \_ContaoManager\Symfony\Config\Security\FirewallConfig\JsonLoginLdapConfig($value['json_login_ldap']);
            unset($value['json_login_ldap']);
        }
        if (array_key_exists('access_token', $value)) {
            $this->_usedProperties['accessToken'] = \true;
            $this->accessToken = new \_ContaoManager\Symfony\Config\Security\FirewallConfig\AccessTokenConfig($value['access_token']);
            unset($value['access_token']);
        }
        if (array_key_exists('http_basic', $value)) {
            $this->_usedProperties['httpBasic'] = \true;
            $this->httpBasic = new \_ContaoManager\Symfony\Config\Security\FirewallConfig\HttpBasicConfig($value['http_basic']);
            unset($value['http_basic']);
        }
        if (array_key_exists('http_basic_ldap', $value)) {
            $this->_usedProperties['httpBasicLdap'] = \true;
            $this->httpBasicLdap = new \_ContaoManager\Symfony\Config\Security\FirewallConfig\HttpBasicLdapConfig($value['http_basic_ldap']);
            unset($value['http_basic_ldap']);
        }
        if (array_key_exists('remember_me', $value)) {
            $this->_usedProperties['rememberMe'] = \true;
            $this->rememberMe = new \_ContaoManager\Symfony\Config\Security\FirewallConfig\RememberMeConfig($value['remember_me']);
            unset($value['remember_me']);
        }
        if ([] !== $value) {
            throw new InvalidConfigurationException(sprintf('The following keys are not supported by "%s": ', __CLASS__) . implode(', ', array_keys($value)));
        }
    }
    public function toArray(): array
    {
        $output = [];
        if (isset($this->_usedProperties['pattern'])) {
            $output['pattern'] = $this->pattern;
        }
        if (isset($this->_usedProperties['host'])) {
            $output['host'] = $this->host;
        }
        if (isset($this->_usedProperties['methods'])) {
            $output['methods'] = $this->methods;
        }
        if (isset($this->_usedProperties['security'])) {
            $output['security'] = $this->security;
        }
        if (isset($this->_usedProperties['userChecker'])) {
            $output['user_checker'] = $this->userChecker;
        }
        if (isset($this->_usedProperties['requestMatcher'])) {
            $output['request_matcher'] = $this->requestMatcher;
        }
        if (isset($this->_usedProperties['accessDeniedUrl'])) {
            $output['access_denied_url'] = $this->accessDeniedUrl;
        }
        if (isset($this->_usedProperties['accessDeniedHandler'])) {
            $output['access_denied_handler'] = $this->accessDeniedHandler;
        }
        if (isset($this->_usedProperties['entryPoint'])) {
            $output['entry_point'] = $this->entryPoint;
        }
        if (isset($this->_usedProperties['provider'])) {
            $output['provider'] = $this->provider;
        }
        if (isset($this->_usedProperties['stateless'])) {
            $output['stateless'] = $this->stateless;
        }
        if (isset($this->_usedProperties['lazy'])) {
            $output['lazy'] = $this->lazy;
        }
        if (isset($this->_usedProperties['context'])) {
            $output['context'] = $this->context;
        }
        if (isset($this->_usedProperties['logout'])) {
            $output['logout'] = $this->logout instanceof \_ContaoManager\Symfony\Config\Security\FirewallConfig\LogoutConfig ? $this->logout->toArray() : $this->logout;
        }
        if (isset($this->_usedProperties['switchUser'])) {
            $output['switch_user'] = $this->switchUser->toArray();
        }
        if (isset($this->_usedProperties['requiredBadges'])) {
            $output['required_badges'] = $this->requiredBadges;
        }
        if (isset($this->_usedProperties['customAuthenticators'])) {
            $output['custom_authenticators'] = $this->customAuthenticators;
        }
        if (isset($this->_usedProperties['loginThrottling'])) {
            $output['login_throttling'] = $this->loginThrottling->toArray();
        }
        if (isset($this->_usedProperties['x509'])) {
            $output['x509'] = $this->x509->toArray();
        }
        if (isset($this->_usedProperties['remoteUser'])) {
            $output['remote_user'] = $this->remoteUser->toArray();
        }
        if (isset($this->_usedProperties['loginLink'])) {
            $output['login_link'] = $this->loginLink->toArray();
        }
        if (isset($this->_usedProperties['formLogin'])) {
            $output['form_login'] = $this->formLogin->toArray();
        }
        if (isset($this->_usedProperties['formLoginLdap'])) {
            $output['form_login_ldap'] = $this->formLoginLdap->toArray();
        }
        if (isset($this->_usedProperties['jsonLogin'])) {
            $output['json_login'] = $this->jsonLogin->toArray();
        }
        if (isset($this->_usedProperties['jsonLoginLdap'])) {
            $output['json_login_ldap'] = $this->jsonLoginLdap->toArray();
        }
        if (isset($this->_usedProperties['accessToken'])) {
            $output['access_token'] = $this->accessToken->toArray();
        }
        if (isset($this->_usedProperties['httpBasic'])) {
            $output['http_basic'] = $this->httpBasic->toArray();
        }
        if (isset($this->_usedProperties['httpBasicLdap'])) {
            $output['http_basic_ldap'] = $this->httpBasicLdap->toArray();
        }
        if (isset($this->_usedProperties['rememberMe'])) {
            $output['remember_me'] = $this->rememberMe->toArray();
        }
        return $output;
    }
}
<?php

namespace _ContaoManager\Symfony\Config\Security\FirewallConfig;

require_once __DIR__ . \DIRECTORY_SEPARATOR . 'AccessToken' . \DIRECTORY_SEPARATOR . 'TokenHandlerConfig.php';
use _ContaoManager\Symfony\Component\Config\Loader\ParamConfigurator;
use _ContaoManager\Symfony\Component\Config\Definition\Exception\InvalidConfigurationException;
/**
 * This class is automatically generated to help in creating a config.
 */
class AccessTokenConfig
{
    private $provider;
    private $rememberMe;
    private $successHandler;
    private $failureHandler;
    private $realm;
    private $tokenExtractors;
    private $tokenHandler;
    private $_usedProperties = [];
    /**
     * @default null
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function provider($value): static
    {
        $this->_usedProperties['provider'] = \true;
        $this->provider = $value;
        return $this;
    }
    /**
     * @default true
     * @param ParamConfigurator|bool $value
     * @return $this
     */
    public function rememberMe($value): static
    {
        $this->_usedProperties['rememberMe'] = \true;
        $this->rememberMe = $value;
        return $this;
    }
    /**
     * @default null
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function successHandler($value): static
    {
        $this->_usedProperties['successHandler'] = \true;
        $this->successHandler = $value;
        return $this;
    }
    /**
     * @default null
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function failureHandler($value): static
    {
        $this->_usedProperties['failureHandler'] = \true;
        $this->failureHandler = $value;
        return $this;
    }
    /**
     * @default null
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function realm($value): static
    {
        $this->_usedProperties['realm'] = \true;
        $this->realm = $value;
        return $this;
    }
    /**
     * @param ParamConfigurator|list<ParamConfigurator|mixed>|string $value
     *
     * @return $this
     */
    public function tokenExtractors(ParamConfigurator|string|array $value): static
    {
        $this->_usedProperties['tokenExtractors'] = \true;
        $this->tokenExtractors = $value;
        return $this;
    }
    /**
     * @template TValue of mixed
     * @param TValue $value
     * @example "App\\Security\\CustomTokenHandler"
     * @return \Symfony\Config\Security\FirewallConfig\AccessToken\TokenHandlerConfig|$this
     * @psalm-return (TValue is array ? \Symfony\Config\Security\FirewallConfig\AccessToken\TokenHandlerConfig : static)
     */
    public function tokenHandler(mixed $value = []): \_ContaoManager\Symfony\Config\Security\FirewallConfig\AccessToken\TokenHandlerConfig|static
    {
        if (!\is_array($value)) {
            $this->_usedProperties['tokenHandler'] = \true;
            $this->tokenHandler = $value;
            return $this;
        }
        if (!$this->tokenHandler instanceof \_ContaoManager\Symfony\Config\Security\FirewallConfig\AccessToken\TokenHandlerConfig) {
            $this->_usedProperties['tokenHandler'] = \true;
            $this->tokenHandler = new \_ContaoManager\Symfony\Config\Security\FirewallConfig\AccessToken\TokenHandlerConfig($value);
        } elseif (0 < \func_num_args()) {
            throw new InvalidConfigurationException('The node created by "tokenHandler()" has already been initialized. You cannot pass values the second time you call tokenHandler().');
        }
        return $this->tokenHandler;
    }
    public function __construct(array $value = [])
    {
        if (array_key_exists('provider', $value)) {
            $this->_usedProperties['provider'] = \true;
            $this->provider = $value['provider'];
            unset($value['provider']);
        }
        if (array_key_exists('remember_me', $value)) {
            $this->_usedProperties['rememberMe'] = \true;
            $this->rememberMe = $value['remember_me'];
            unset($value['remember_me']);
        }
        if (array_key_exists('success_handler', $value)) {
            $this->_usedProperties['successHandler'] = \true;
            $this->successHandler = $value['success_handler'];
            unset($value['success_handler']);
        }
        if (array_key_exists('failure_handler', $value)) {
            $this->_usedProperties['failureHandler'] = \true;
            $this->failureHandler = $value['failure_handler'];
            unset($value['failure_handler']);
        }
        if (array_key_exists('realm', $value)) {
            $this->_usedProperties['realm'] = \true;
            $this->realm = $value['realm'];
            unset($value['realm']);
        }
        if (array_key_exists('token_extractors', $value)) {
            $this->_usedProperties['tokenExtractors'] = \true;
            $this->tokenExtractors = $value['token_extractors'];
            unset($value['token_extractors']);
        }
        if (array_key_exists('token_handler', $value)) {
            $this->_usedProperties['tokenHandler'] = \true;
            $this->tokenHandler = \is_array($value['token_handler']) ? new \_ContaoManager\Symfony\Config\Security\FirewallConfig\AccessToken\TokenHandlerConfig($value['token_handler']) : $value['token_handler'];
            unset($value['token_handler']);
        }
        if ([] !== $value) {
            throw new InvalidConfigurationException(sprintf('The following keys are not supported by "%s": ', __CLASS__) . implode(', ', array_keys($value)));
        }
    }
    public function toArray(): array
    {
        $output = [];
        if (isset($this->_usedProperties['provider'])) {
            $output['provider'] = $this->provider;
        }
        if (isset($this->_usedProperties['rememberMe'])) {
            $output['remember_me'] = $this->rememberMe;
        }
        if (isset($this->_usedProperties['successHandler'])) {
            $output['success_handler'] = $this->successHandler;
        }
        if (isset($this->_usedProperties['failureHandler'])) {
            $output['failure_handler'] = $this->failureHandler;
        }
        if (isset($this->_usedProperties['realm'])) {
            $output['realm'] = $this->realm;
        }
        if (isset($this->_usedProperties['tokenExtractors'])) {
            $output['token_extractors'] = $this->tokenExtractors;
        }
        if (isset($this->_usedProperties['tokenHandler'])) {
            $output['token_handler'] = $this->tokenHandler instanceof \_ContaoManager\Symfony\Config\Security\FirewallConfig\AccessToken\TokenHandlerConfig ? $this->tokenHandler->toArray() : $this->tokenHandler;
        }
        return $output;
    }
}
<?php

namespace _ContaoManager\Symfony\Config\Security\FirewallConfig;

require_once __DIR__ . \DIRECTORY_SEPARATOR . 'RememberMe' . \DIRECTORY_SEPARATOR . 'TokenProviderConfig.php';
use _ContaoManager\Symfony\Component\Config\Loader\ParamConfigurator;
use _ContaoManager\Symfony\Component\Config\Definition\Exception\InvalidConfigurationException;
/**
 * This class is automatically generated to help in creating a config.
 */
class RememberMeConfig
{
    private $secret;
    private $service;
    private $userProviders;
    private $catchExceptions;
    private $signatureProperties;
    private $tokenProvider;
    private $tokenVerifier;
    private $name;
    private $lifetime;
    private $path;
    private $domain;
    private $secure;
    private $httponly;
    private $samesite;
    private $alwaysRememberMe;
    private $rememberMeParameter;
    private $_usedProperties = [];
    /**
     * @default '%kernel.secret%'
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function secret($value): static
    {
        $this->_usedProperties['secret'] = \true;
        $this->secret = $value;
        return $this;
    }
    /**
     * @default null
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function service($value): static
    {
        $this->_usedProperties['service'] = \true;
        $this->service = $value;
        return $this;
    }
    /**
     * @param ParamConfigurator|list<ParamConfigurator|mixed>|string $value
     *
     * @return $this
     */
    public function userProviders(ParamConfigurator|string|array $value): static
    {
        $this->_usedProperties['userProviders'] = \true;
        $this->userProviders = $value;
        return $this;
    }
    /**
     * @default true
     * @param ParamConfigurator|bool $value
     * @return $this
     */
    public function catchExceptions($value): static
    {
        $this->_usedProperties['catchExceptions'] = \true;
        $this->catchExceptions = $value;
        return $this;
    }
    /**
     * @param ParamConfigurator|list<ParamConfigurator|mixed> $value
     *
     * @return $this
     */
    public function signatureProperties(ParamConfigurator|array $value): static
    {
        $this->_usedProperties['signatureProperties'] = \true;
        $this->signatureProperties = $value;
        return $this;
    }
    /**
     * @template TValue of string|array
     * @param TValue $value
     * @return \Symfony\Config\Security\FirewallConfig\RememberMe\TokenProviderConfig|$this
     * @psalm-return (TValue is array ? \Symfony\Config\Security\FirewallConfig\RememberMe\TokenProviderConfig : static)
     */
    public function tokenProvider(string|array $value = []): \_ContaoManager\Symfony\Config\Security\FirewallConfig\RememberMe\TokenProviderConfig|static
    {
        if (!\is_array($value)) {
            $this->_usedProperties['tokenProvider'] = \true;
            $this->tokenProvider = $value;
            return $this;
        }
        if (!$this->tokenProvider instanceof \_ContaoManager\Symfony\Config\Security\FirewallConfig\RememberMe\TokenProviderConfig) {
            $this->_usedProperties['tokenProvider'] = \true;
            $this->tokenProvider = new \_ContaoManager\Symfony\Config\Security\FirewallConfig\RememberMe\TokenProviderConfig($value);
        } elseif (0 < \func_num_args()) {
            throw new InvalidConfigurationException('The node created by "tokenProvider()" has already been initialized. You cannot pass values the second time you call tokenProvider().');
        }
        return $this->tokenProvider;
    }
    /**
     * The service ID of a custom rememberme token verifier.
     * @default null
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function tokenVerifier($value): static
    {
        $this->_usedProperties['tokenVerifier'] = \true;
        $this->tokenVerifier = $value;
        return $this;
    }
    /**
     * @default 'REMEMBERME'
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function name($value): static
    {
        $this->_usedProperties['name'] = \true;
        $this->name = $value;
        return $this;
    }
    /**
     * @default 31536000
     * @param ParamConfigurator|int $value
     * @return $this
     */
    public function lifetime($value): static
    {
        $this->_usedProperties['lifetime'] = \true;
        $this->lifetime = $value;
        return $this;
    }
    /**
     * @default '/'
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function path($value): static
    {
        $this->_usedProperties['path'] = \true;
        $this->path = $value;
        return $this;
    }
    /**
     * @default null
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function domain($value): static
    {
        $this->_usedProperties['domain'] = \true;
        $this->domain = $value;
        return $this;
    }
    /**
     * @default false
     * @param ParamConfigurator|true|false|'auto' $value
     * @return $this
     */
    public function secure($value): static
    {
        $this->_usedProperties['secure'] = \true;
        $this->secure = $value;
        return $this;
    }
    /**
     * @default true
     * @param ParamConfigurator|bool $value
     * @return $this
     */
    public function httponly($value): static
    {
        $this->_usedProperties['httponly'] = \true;
        $this->httponly = $value;
        return $this;
    }
    /**
     * @default null
     * @param ParamConfigurator|NULL|'lax'|'strict'|'none' $value
     * @return $this
     */
    public function samesite($value): static
    {
        $this->_usedProperties['samesite'] = \true;
        $this->samesite = $value;
        return $this;
    }
    /**
     * @default false
     * @param ParamConfigurator|bool $value
     * @return $this
     */
    public function alwaysRememberMe($value): static
    {
        $this->_usedProperties['alwaysRememberMe'] = \true;
        $this->alwaysRememberMe = $value;
        return $this;
    }
    /**
     * @default '_remember_me'
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function rememberMeParameter($value): static
    {
        $this->_usedProperties['rememberMeParameter'] = \true;
        $this->rememberMeParameter = $value;
        return $this;
    }
    public function __construct(array $value = [])
    {
        if (array_key_exists('secret', $value)) {
            $this->_usedProperties['secret'] = \true;
            $this->secret = $value['secret'];
            unset($value['secret']);
        }
        if (array_key_exists('service', $value)) {
            $this->_usedProperties['service'] = \true;
            $this->service = $value['service'];
            unset($value['service']);
        }
        if (array_key_exists('user_providers', $value)) {
            $this->_usedProperties['userProviders'] = \true;
            $this->userProviders = $value['user_providers'];
            unset($value['user_providers']);
        }
        if (array_key_exists('catch_exceptions', $value)) {
            $this->_usedProperties['catchExceptions'] = \true;
            $this->catchExceptions = $value['catch_exceptions'];
            unset($value['catch_exceptions']);
        }
        if (array_key_exists('signature_properties', $value)) {
            $this->_usedProperties['signatureProperties'] = \true;
            $this->signatureProperties = $value['signature_properties'];
            unset($value['signature_properties']);
        }
        if (array_key_exists('token_provider', $value)) {
            $this->_usedProperties['tokenProvider'] = \true;
            $this->tokenProvider = \is_array($value['token_provider']) ? new \_ContaoManager\Symfony\Config\Security\FirewallConfig\RememberMe\TokenProviderConfig($value['token_provider']) : $value['token_provider'];
            unset($value['token_provider']);
        }
        if (array_key_exists('token_verifier', $value)) {
            $this->_usedProperties['tokenVerifier'] = \true;
            $this->tokenVerifier = $value['token_verifier'];
            unset($value['token_verifier']);
        }
        if (array_key_exists('name', $value)) {
            $this->_usedProperties['name'] = \true;
            $this->name = $value['name'];
            unset($value['name']);
        }
        if (array_key_exists('lifetime', $value)) {
            $this->_usedProperties['lifetime'] = \true;
            $this->lifetime = $value['lifetime'];
            unset($value['lifetime']);
        }
        if (array_key_exists('path', $value)) {
            $this->_usedProperties['path'] = \true;
            $this->path = $value['path'];
            unset($value['path']);
        }
        if (array_key_exists('domain', $value)) {
            $this->_usedProperties['domain'] = \true;
            $this->domain = $value['domain'];
            unset($value['domain']);
        }
        if (array_key_exists('secure', $value)) {
            $this->_usedProperties['secure'] = \true;
            $this->secure = $value['secure'];
            unset($value['secure']);
        }
        if (array_key_exists('httponly', $value)) {
            $this->_usedProperties['httponly'] = \true;
            $this->httponly = $value['httponly'];
            unset($value['httponly']);
        }
        if (array_key_exists('samesite', $value)) {
            $this->_usedProperties['samesite'] = \true;
            $this->samesite = $value['samesite'];
            unset($value['samesite']);
        }
        if (array_key_exists('always_remember_me', $value)) {
            $this->_usedProperties['alwaysRememberMe'] = \true;
            $this->alwaysRememberMe = $value['always_remember_me'];
            unset($value['always_remember_me']);
        }
        if (array_key_exists('remember_me_parameter', $value)) {
            $this->_usedProperties['rememberMeParameter'] = \true;
            $this->rememberMeParameter = $value['remember_me_parameter'];
            unset($value['remember_me_parameter']);
        }
        if ([] !== $value) {
            throw new InvalidConfigurationException(sprintf('The following keys are not supported by "%s": ', __CLASS__) . implode(', ', array_keys($value)));
        }
    }
    public function toArray(): array
    {
        $output = [];
        if (isset($this->_usedProperties['secret'])) {
            $output['secret'] = $this->secret;
        }
        if (isset($this->_usedProperties['service'])) {
            $output['service'] = $this->service;
        }
        if (isset($this->_usedProperties['userProviders'])) {
            $output['user_providers'] = $this->userProviders;
        }
        if (isset($this->_usedProperties['catchExceptions'])) {
            $output['catch_exceptions'] = $this->catchExceptions;
        }
        if (isset($this->_usedProperties['signatureProperties'])) {
            $output['signature_properties'] = $this->signatureProperties;
        }
        if (isset($this->_usedProperties['tokenProvider'])) {
            $output['token_provider'] = $this->tokenProvider instanceof \_ContaoManager\Symfony\Config\Security\FirewallConfig\RememberMe\TokenProviderConfig ? $this->tokenProvider->toArray() : $this->tokenProvider;
        }
        if (isset($this->_usedProperties['tokenVerifier'])) {
            $output['token_verifier'] = $this->tokenVerifier;
        }
        if (isset($this->_usedProperties['name'])) {
            $output['name'] = $this->name;
        }
        if (isset($this->_usedProperties['lifetime'])) {
            $output['lifetime'] = $this->lifetime;
        }
        if (isset($this->_usedProperties['path'])) {
            $output['path'] = $this->path;
        }
        if (isset($this->_usedProperties['domain'])) {
            $output['domain'] = $this->domain;
        }
        if (isset($this->_usedProperties['secure'])) {
            $output['secure'] = $this->secure;
        }
        if (isset($this->_usedProperties['httponly'])) {
            $output['httponly'] = $this->httponly;
        }
        if (isset($this->_usedProperties['samesite'])) {
            $output['samesite'] = $this->samesite;
        }
        if (isset($this->_usedProperties['alwaysRememberMe'])) {
            $output['always_remember_me'] = $this->alwaysRememberMe;
        }
        if (isset($this->_usedProperties['rememberMeParameter'])) {
            $output['remember_me_parameter'] = $this->rememberMeParameter;
        }
        return $output;
    }
}
<?php

namespace _ContaoManager\Symfony\Config\Security\FirewallConfig;

use _ContaoManager\Symfony\Component\Config\Loader\ParamConfigurator;
use _ContaoManager\Symfony\Component\Config\Definition\Exception\InvalidConfigurationException;
/**
 * This class is automatically generated to help in creating a config.
 */
class FormLoginConfig
{
    private $provider;
    private $rememberMe;
    private $successHandler;
    private $failureHandler;
    private $checkPath;
    private $useForward;
    private $requirePreviousSession;
    private $loginPath;
    private $usernameParameter;
    private $passwordParameter;
    private $csrfParameter;
    private $csrfTokenId;
    private $enableCsrf;
    private $postOnly;
    private $formOnly;
    private $alwaysUseDefaultTargetPath;
    private $defaultTargetPath;
    private $targetPathParameter;
    private $useReferer;
    private $failurePath;
    private $failureForward;
    private $failurePathParameter;
    private $csrfTokenGenerator;
    private $_usedProperties = [];
    /**
     * @default null
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function provider($value): static
    {
        $this->_usedProperties['provider'] = \true;
        $this->provider = $value;
        return $this;
    }
    /**
     * @default true
     * @param ParamConfigurator|bool $value
     * @return $this
     */
    public function rememberMe($value): static
    {
        $this->_usedProperties['rememberMe'] = \true;
        $this->rememberMe = $value;
        return $this;
    }
    /**
     * @default null
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function successHandler($value): static
    {
        $this->_usedProperties['successHandler'] = \true;
        $this->successHandler = $value;
        return $this;
    }
    /**
     * @default null
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function failureHandler($value): static
    {
        $this->_usedProperties['failureHandler'] = \true;
        $this->failureHandler = $value;
        return $this;
    }
    /**
     * @default '/login_check'
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function checkPath($value): static
    {
        $this->_usedProperties['checkPath'] = \true;
        $this->checkPath = $value;
        return $this;
    }
    /**
     * @default false
     * @param ParamConfigurator|bool $value
     * @return $this
     */
    public function useForward($value): static
    {
        $this->_usedProperties['useForward'] = \true;
        $this->useForward = $value;
        return $this;
    }
    /**
     * @default false
     * @param ParamConfigurator|bool $value
     * @deprecated Option "require_previous_session" at "form_login" is deprecated, it will be removed in version 7.0. Setting it has no effect anymore.
     * @return $this
     */
    public function requirePreviousSession($value): static
    {
        $this->_usedProperties['requirePreviousSession'] = \true;
        $this->requirePreviousSession = $value;
        return $this;
    }
    /**
     * @default '/login'
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function loginPath($value): static
    {
        $this->_usedProperties['loginPath'] = \true;
        $this->loginPath = $value;
        return $this;
    }
    /**
     * @default '_username'
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function usernameParameter($value): static
    {
        $this->_usedProperties['usernameParameter'] = \true;
        $this->usernameParameter = $value;
        return $this;
    }
    /**
     * @default '_password'
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function passwordParameter($value): static
    {
        $this->_usedProperties['passwordParameter'] = \true;
        $this->passwordParameter = $value;
        return $this;
    }
    /**
     * @default '_csrf_token'
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function csrfParameter($value): static
    {
        $this->_usedProperties['csrfParameter'] = \true;
        $this->csrfParameter = $value;
        return $this;
    }
    /**
     * @default 'authenticate'
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function csrfTokenId($value): static
    {
        $this->_usedProperties['csrfTokenId'] = \true;
        $this->csrfTokenId = $value;
        return $this;
    }
    /**
     * @default false
     * @param ParamConfigurator|bool $value
     * @return $this
     */
    public function enableCsrf($value): static
    {
        $this->_usedProperties['enableCsrf'] = \true;
        $this->enableCsrf = $value;
        return $this;
    }
    /**
     * @default true
     * @param ParamConfigurator|bool $value
     * @return $this
     */
    public function postOnly($value): static
    {
        $this->_usedProperties['postOnly'] = \true;
        $this->postOnly = $value;
        return $this;
    }
    /**
     * @default false
     * @param ParamConfigurator|bool $value
     * @return $this
     */
    public function formOnly($value): static
    {
        $this->_usedProperties['formOnly'] = \true;
        $this->formOnly = $value;
        return $this;
    }
    /**
     * @default false
     * @param ParamConfigurator|bool $value
     * @return $this
     */
    public function alwaysUseDefaultTargetPath($value): static
    {
        $this->_usedProperties['alwaysUseDefaultTargetPath'] = \true;
        $this->alwaysUseDefaultTargetPath = $value;
        return $this;
    }
    /**
     * @default '/'
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function defaultTargetPath($value): static
    {
        $this->_usedProperties['defaultTargetPath'] = \true;
        $this->defaultTargetPath = $value;
        return $this;
    }
    /**
     * @default '_target_path'
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function targetPathParameter($value): static
    {
        $this->_usedProperties['targetPathParameter'] = \true;
        $this->targetPathParameter = $value;
        return $this;
    }
    /**
     * @default false
     * @param ParamConfigurator|bool $value
     * @return $this
     */
    public function useReferer($value): static
    {
        $this->_usedProperties['useReferer'] = \true;
        $this->useReferer = $value;
        return $this;
    }
    /**
     * @default null
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function failurePath($value): static
    {
        $this->_usedProperties['failurePath'] = \true;
        $this->failurePath = $value;
        return $this;
    }
    /**
     * @default false
     * @param ParamConfigurator|bool $value
     * @return $this
     */
    public function failureForward($value): static
    {
        $this->_usedProperties['failureForward'] = \true;
        $this->failureForward = $value;
        return $this;
    }
    /**
     * @default '_failure_path'
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function failurePathParameter($value): static
    {
        $this->_usedProperties['failurePathParameter'] = \true;
        $this->failurePathParameter = $value;
        return $this;
    }
    /**
     * @default null
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function csrfTokenGenerator($value): static
    {
        $this->_usedProperties['csrfTokenGenerator'] = \true;
        $this->csrfTokenGenerator = $value;
        return $this;
    }
    public function __construct(array $value = [])
    {
        if (array_key_exists('provider', $value)) {
            $this->_usedProperties['provider'] = \true;
            $this->provider = $value['provider'];
            unset($value['provider']);
        }
        if (array_key_exists('remember_me', $value)) {
            $this->_usedProperties['rememberMe'] = \true;
            $this->rememberMe = $value['remember_me'];
            unset($value['remember_me']);
        }
        if (array_key_exists('success_handler', $value)) {
            $this->_usedProperties['successHandler'] = \true;
            $this->successHandler = $value['success_handler'];
            unset($value['success_handler']);
        }
        if (array_key_exists('failure_handler', $value)) {
            $this->_usedProperties['failureHandler'] = \true;
            $this->failureHandler = $value['failure_handler'];
            unset($value['failure_handler']);
        }
        if (array_key_exists('check_path', $value)) {
            $this->_usedProperties['checkPath'] = \true;
            $this->checkPath = $value['check_path'];
            unset($value['check_path']);
        }
        if (array_key_exists('use_forward', $value)) {
            $this->_usedProperties['useForward'] = \true;
            $this->useForward = $value['use_forward'];
            unset($value['use_forward']);
        }
        if (array_key_exists('require_previous_session', $value)) {
            $this->_usedProperties['requirePreviousSession'] = \true;
            $this->requirePreviousSession = $value['require_previous_session'];
            unset($value['require_previous_session']);
        }
        if (array_key_exists('login_path', $value)) {
            $this->_usedProperties['loginPath'] = \true;
            $this->loginPath = $value['login_path'];
            unset($value['login_path']);
        }
        if (array_key_exists('username_parameter', $value)) {
            $this->_usedProperties['usernameParameter'] = \true;
            $this->usernameParameter = $value['username_parameter'];
            unset($value['username_parameter']);
        }
        if (array_key_exists('password_parameter', $value)) {
            $this->_usedProperties['passwordParameter'] = \true;
            $this->passwordParameter = $value['password_parameter'];
            unset($value['password_parameter']);
        }
        if (array_key_exists('csrf_parameter', $value)) {
            $this->_usedProperties['csrfParameter'] = \true;
            $this->csrfParameter = $value['csrf_parameter'];
            unset($value['csrf_parameter']);
        }
        if (array_key_exists('csrf_token_id', $value)) {
            $this->_usedProperties['csrfTokenId'] = \true;
            $this->csrfTokenId = $value['csrf_token_id'];
            unset($value['csrf_token_id']);
        }
        if (array_key_exists('enable_csrf', $value)) {
            $this->_usedProperties['enableCsrf'] = \true;
            $this->enableCsrf = $value['enable_csrf'];
            unset($value['enable_csrf']);
        }
        if (array_key_exists('post_only', $value)) {
            $this->_usedProperties['postOnly'] = \true;
            $this->postOnly = $value['post_only'];
            unset($value['post_only']);
        }
        if (array_key_exists('form_only', $value)) {
            $this->_usedProperties['formOnly'] = \true;
            $this->formOnly = $value['form_only'];
            unset($value['form_only']);
        }
        if (array_key_exists('always_use_default_target_path', $value)) {
            $this->_usedProperties['alwaysUseDefaultTargetPath'] = \true;
            $this->alwaysUseDefaultTargetPath = $value['always_use_default_target_path'];
            unset($value['always_use_default_target_path']);
        }
        if (array_key_exists('default_target_path', $value)) {
            $this->_usedProperties['defaultTargetPath'] = \true;
            $this->defaultTargetPath = $value['default_target_path'];
            unset($value['default_target_path']);
        }
        if (array_key_exists('target_path_parameter', $value)) {
            $this->_usedProperties['targetPathParameter'] = \true;
            $this->targetPathParameter = $value['target_path_parameter'];
            unset($value['target_path_parameter']);
        }
        if (array_key_exists('use_referer', $value)) {
            $this->_usedProperties['useReferer'] = \true;
            $this->useReferer = $value['use_referer'];
            unset($value['use_referer']);
        }
        if (array_key_exists('failure_path', $value)) {
            $this->_usedProperties['failurePath'] = \true;
            $this->failurePath = $value['failure_path'];
            unset($value['failure_path']);
        }
        if (array_key_exists('failure_forward', $value)) {
            $this->_usedProperties['failureForward'] = \true;
            $this->failureForward = $value['failure_forward'];
            unset($value['failure_forward']);
        }
        if (array_key_exists('failure_path_parameter', $value)) {
            $this->_usedProperties['failurePathParameter'] = \true;
            $this->failurePathParameter = $value['failure_path_parameter'];
            unset($value['failure_path_parameter']);
        }
        if (array_key_exists('csrf_token_generator', $value)) {
            $this->_usedProperties['csrfTokenGenerator'] = \true;
            $this->csrfTokenGenerator = $value['csrf_token_generator'];
            unset($value['csrf_token_generator']);
        }
        if ([] !== $value) {
            throw new InvalidConfigurationException(sprintf('The following keys are not supported by "%s": ', __CLASS__) . implode(', ', array_keys($value)));
        }
    }
    public function toArray(): array
    {
        $output = [];
        if (isset($this->_usedProperties['provider'])) {
            $output['provider'] = $this->provider;
        }
        if (isset($this->_usedProperties['rememberMe'])) {
            $output['remember_me'] = $this->rememberMe;
        }
        if (isset($this->_usedProperties['successHandler'])) {
            $output['success_handler'] = $this->successHandler;
        }
        if (isset($this->_usedProperties['failureHandler'])) {
            $output['failure_handler'] = $this->failureHandler;
        }
        if (isset($this->_usedProperties['checkPath'])) {
            $output['check_path'] = $this->checkPath;
        }
        if (isset($this->_usedProperties['useForward'])) {
            $output['use_forward'] = $this->useForward;
        }
        if (isset($this->_usedProperties['requirePreviousSession'])) {
            $output['require_previous_session'] = $this->requirePreviousSession;
        }
        if (isset($this->_usedProperties['loginPath'])) {
            $output['login_path'] = $this->loginPath;
        }
        if (isset($this->_usedProperties['usernameParameter'])) {
            $output['username_parameter'] = $this->usernameParameter;
        }
        if (isset($this->_usedProperties['passwordParameter'])) {
            $output['password_parameter'] = $this->passwordParameter;
        }
        if (isset($this->_usedProperties['csrfParameter'])) {
            $output['csrf_parameter'] = $this->csrfParameter;
        }
        if (isset($this->_usedProperties['csrfTokenId'])) {
            $output['csrf_token_id'] = $this->csrfTokenId;
        }
        if (isset($this->_usedProperties['enableCsrf'])) {
            $output['enable_csrf'] = $this->enableCsrf;
        }
        if (isset($this->_usedProperties['postOnly'])) {
            $output['post_only'] = $this->postOnly;
        }
        if (isset($this->_usedProperties['formOnly'])) {
            $output['form_only'] = $this->formOnly;
        }
        if (isset($this->_usedProperties['alwaysUseDefaultTargetPath'])) {
            $output['always_use_default_target_path'] = $this->alwaysUseDefaultTargetPath;
        }
        if (isset($this->_usedProperties['defaultTargetPath'])) {
            $output['default_target_path'] = $this->defaultTargetPath;
        }
        if (isset($this->_usedProperties['targetPathParameter'])) {
            $output['target_path_parameter'] = $this->targetPathParameter;
        }
        if (isset($this->_usedProperties['useReferer'])) {
            $output['use_referer'] = $this->useReferer;
        }
        if (isset($this->_usedProperties['failurePath'])) {
            $output['failure_path'] = $this->failurePath;
        }
        if (isset($this->_usedProperties['failureForward'])) {
            $output['failure_forward'] = $this->failureForward;
        }
        if (isset($this->_usedProperties['failurePathParameter'])) {
            $output['failure_path_parameter'] = $this->failurePathParameter;
        }
        if (isset($this->_usedProperties['csrfTokenGenerator'])) {
            $output['csrf_token_generator'] = $this->csrfTokenGenerator;
        }
        return $output;
    }
}
<?php

namespace _ContaoManager\Symfony\Config\Security\FirewallConfig;

use _ContaoManager\Symfony\Component\Config\Loader\ParamConfigurator;
use _ContaoManager\Symfony\Component\Config\Definition\Exception\InvalidConfigurationException;
/**
 * This class is automatically generated to help in creating a config.
 */
class JsonLoginLdapConfig
{
    private $provider;
    private $rememberMe;
    private $successHandler;
    private $failureHandler;
    private $checkPath;
    private $useForward;
    private $requirePreviousSession;
    private $loginPath;
    private $usernamePath;
    private $passwordPath;
    private $service;
    private $dnString;
    private $queryString;
    private $searchDn;
    private $searchPassword;
    private $_usedProperties = [];
    /**
     * @default null
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function provider($value): static
    {
        $this->_usedProperties['provider'] = \true;
        $this->provider = $value;
        return $this;
    }
    /**
     * @default true
     * @param ParamConfigurator|bool $value
     * @return $this
     */
    public function rememberMe($value): static
    {
        $this->_usedProperties['rememberMe'] = \true;
        $this->rememberMe = $value;
        return $this;
    }
    /**
     * @default null
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function successHandler($value): static
    {
        $this->_usedProperties['successHandler'] = \true;
        $this->successHandler = $value;
        return $this;
    }
    /**
     * @default null
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function failureHandler($value): static
    {
        $this->_usedProperties['failureHandler'] = \true;
        $this->failureHandler = $value;
        return $this;
    }
    /**
     * @default '/login_check'
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function checkPath($value): static
    {
        $this->_usedProperties['checkPath'] = \true;
        $this->checkPath = $value;
        return $this;
    }
    /**
     * @default false
     * @param ParamConfigurator|bool $value
     * @return $this
     */
    public function useForward($value): static
    {
        $this->_usedProperties['useForward'] = \true;
        $this->useForward = $value;
        return $this;
    }
    /**
     * @default false
     * @param ParamConfigurator|bool $value
     * @deprecated Option "require_previous_session" at "json_login_ldap" is deprecated, it will be removed in version 7.0. Setting it has no effect anymore.
     * @return $this
     */
    public function requirePreviousSession($value): static
    {
        $this->_usedProperties['requirePreviousSession'] = \true;
        $this->requirePreviousSession = $value;
        return $this;
    }
    /**
     * @default '/login'
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function loginPath($value): static
    {
        $this->_usedProperties['loginPath'] = \true;
        $this->loginPath = $value;
        return $this;
    }
    /**
     * @default 'username'
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function usernamePath($value): static
    {
        $this->_usedProperties['usernamePath'] = \true;
        $this->usernamePath = $value;
        return $this;
    }
    /**
     * @default 'password'
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function passwordPath($value): static
    {
        $this->_usedProperties['passwordPath'] = \true;
        $this->passwordPath = $value;
        return $this;
    }
    /**
     * @default 'ldap'
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function service($value): static
    {
        $this->_usedProperties['service'] = \true;
        $this->service = $value;
        return $this;
    }
    /**
     * @default '{username}'
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function dnString($value): static
    {
        $this->_usedProperties['dnString'] = \true;
        $this->dnString = $value;
        return $this;
    }
    /**
     * @default null
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function queryString($value): static
    {
        $this->_usedProperties['queryString'] = \true;
        $this->queryString = $value;
        return $this;
    }
    /**
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function searchDn($value): static
    {
        $this->_usedProperties['searchDn'] = \true;
        $this->searchDn = $value;
        return $this;
    }
    /**
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function searchPassword($value): static
    {
        $this->_usedProperties['searchPassword'] = \true;
        $this->searchPassword = $value;
        return $this;
    }
    public function __construct(array $value = [])
    {
        if (array_key_exists('provider', $value)) {
            $this->_usedProperties['provider'] = \true;
            $this->provider = $value['provider'];
            unset($value['provider']);
        }
        if (array_key_exists('remember_me', $value)) {
            $this->_usedProperties['rememberMe'] = \true;
            $this->rememberMe = $value['remember_me'];
            unset($value['remember_me']);
        }
        if (array_key_exists('success_handler', $value)) {
            $this->_usedProperties['successHandler'] = \true;
            $this->successHandler = $value['success_handler'];
            unset($value['success_handler']);
        }
        if (array_key_exists('failure_handler', $value)) {
            $this->_usedProperties['failureHandler'] = \true;
            $this->failureHandler = $value['failure_handler'];
            unset($value['failure_handler']);
        }
        if (array_key_exists('check_path', $value)) {
            $this->_usedProperties['checkPath'] = \true;
            $this->checkPath = $value['check_path'];
            unset($value['check_path']);
        }
        if (array_key_exists('use_forward', $value)) {
            $this->_usedProperties['useForward'] = \true;
            $this->useForward = $value['use_forward'];
            unset($value['use_forward']);
        }
        if (array_key_exists('require_previous_session', $value)) {
            $this->_usedProperties['requirePreviousSession'] = \true;
            $this->requirePreviousSession = $value['require_previous_session'];
            unset($value['require_previous_session']);
        }
        if (array_key_exists('login_path', $value)) {
            $this->_usedProperties['loginPath'] = \true;
            $this->loginPath = $value['login_path'];
            unset($value['login_path']);
        }
        if (array_key_exists('username_path', $value)) {
            $this->_usedProperties['usernamePath'] = \true;
            $this->usernamePath = $value['username_path'];
            unset($value['username_path']);
        }
        if (array_key_exists('password_path', $value)) {
            $this->_usedProperties['passwordPath'] = \true;
            $this->passwordPath = $value['password_path'];
            unset($value['password_path']);
        }
        if (array_key_exists('service', $value)) {
            $this->_usedProperties['service'] = \true;
            $this->service = $value['service'];
            unset($value['service']);
        }
        if (array_key_exists('dn_string', $value)) {
            $this->_usedProperties['dnString'] = \true;
            $this->dnString = $value['dn_string'];
            unset($value['dn_string']);
        }
        if (array_key_exists('query_string', $value)) {
            $this->_usedProperties['queryString'] = \true;
            $this->queryString = $value['query_string'];
            unset($value['query_string']);
        }
        if (array_key_exists('search_dn', $value)) {
            $this->_usedProperties['searchDn'] = \true;
            $this->searchDn = $value['search_dn'];
            unset($value['search_dn']);
        }
        if (array_key_exists('search_password', $value)) {
            $this->_usedProperties['searchPassword'] = \true;
            $this->searchPassword = $value['search_password'];
            unset($value['search_password']);
        }
        if ([] !== $value) {
            throw new InvalidConfigurationException(sprintf('The following keys are not supported by "%s": ', __CLASS__) . implode(', ', array_keys($value)));
        }
    }
    public function toArray(): array
    {
        $output = [];
        if (isset($this->_usedProperties['provider'])) {
            $output['provider'] = $this->provider;
        }
        if (isset($this->_usedProperties['rememberMe'])) {
            $output['remember_me'] = $this->rememberMe;
        }
        if (isset($this->_usedProperties['successHandler'])) {
            $output['success_handler'] = $this->successHandler;
        }
        if (isset($this->_usedProperties['failureHandler'])) {
            $output['failure_handler'] = $this->failureHandler;
        }
        if (isset($this->_usedProperties['checkPath'])) {
            $output['check_path'] = $this->checkPath;
        }
        if (isset($this->_usedProperties['useForward'])) {
            $output['use_forward'] = $this->useForward;
        }
        if (isset($this->_usedProperties['requirePreviousSession'])) {
            $output['require_previous_session'] = $this->requirePreviousSession;
        }
        if (isset($this->_usedProperties['loginPath'])) {
            $output['login_path'] = $this->loginPath;
        }
        if (isset($this->_usedProperties['usernamePath'])) {
            $output['username_path'] = $this->usernamePath;
        }
        if (isset($this->_usedProperties['passwordPath'])) {
            $output['password_path'] = $this->passwordPath;
        }
        if (isset($this->_usedProperties['service'])) {
            $output['service'] = $this->service;
        }
        if (isset($this->_usedProperties['dnString'])) {
            $output['dn_string'] = $this->dnString;
        }
        if (isset($this->_usedProperties['queryString'])) {
            $output['query_string'] = $this->queryString;
        }
        if (isset($this->_usedProperties['searchDn'])) {
            $output['search_dn'] = $this->searchDn;
        }
        if (isset($this->_usedProperties['searchPassword'])) {
            $output['search_password'] = $this->searchPassword;
        }
        return $output;
    }
}
<?php

namespace _ContaoManager\Symfony\Config\Security\FirewallConfig;

use _ContaoManager\Symfony\Component\Config\Loader\ParamConfigurator;
use _ContaoManager\Symfony\Component\Config\Definition\Exception\InvalidConfigurationException;
/**
 * This class is automatically generated to help in creating a config.
 */
class HttpBasicConfig
{
    private $provider;
    private $realm;
    private $_usedProperties = [];
    /**
     * @default null
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function provider($value): static
    {
        $this->_usedProperties['provider'] = \true;
        $this->provider = $value;
        return $this;
    }
    /**
     * @default 'Secured Area'
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function realm($value): static
    {
        $this->_usedProperties['realm'] = \true;
        $this->realm = $value;
        return $this;
    }
    public function __construct(array $value = [])
    {
        if (array_key_exists('provider', $value)) {
            $this->_usedProperties['provider'] = \true;
            $this->provider = $value['provider'];
            unset($value['provider']);
        }
        if (array_key_exists('realm', $value)) {
            $this->_usedProperties['realm'] = \true;
            $this->realm = $value['realm'];
            unset($value['realm']);
        }
        if ([] !== $value) {
            throw new InvalidConfigurationException(sprintf('The following keys are not supported by "%s": ', __CLASS__) . implode(', ', array_keys($value)));
        }
    }
    public function toArray(): array
    {
        $output = [];
        if (isset($this->_usedProperties['provider'])) {
            $output['provider'] = $this->provider;
        }
        if (isset($this->_usedProperties['realm'])) {
            $output['realm'] = $this->realm;
        }
        return $output;
    }
}
<?php

namespace _ContaoManager\Symfony\Config\Security\FirewallConfig\AccessToken;

require_once __DIR__ . \DIRECTORY_SEPARATOR . 'TokenHandler' . \DIRECTORY_SEPARATOR . 'OidcUserInfoConfig.php';
require_once __DIR__ . \DIRECTORY_SEPARATOR . 'TokenHandler' . \DIRECTORY_SEPARATOR . 'OidcConfig.php';
use _ContaoManager\Symfony\Component\Config\Loader\ParamConfigurator;
use _ContaoManager\Symfony\Component\Config\Definition\Exception\InvalidConfigurationException;
/**
 * This class is automatically generated to help in creating a config.
 */
class TokenHandlerConfig
{
    private $id;
    private $oidcUserInfo;
    private $oidc;
    private $_usedProperties = [];
    /**
     * @default null
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function id($value): static
    {
        $this->_usedProperties['id'] = \true;
        $this->id = $value;
        return $this;
    }
    /**
     * @template TValue of string|array
     * @param TValue $value
     * @return \Symfony\Config\Security\FirewallConfig\AccessToken\TokenHandler\OidcUserInfoConfig|$this
     * @psalm-return (TValue is array ? \Symfony\Config\Security\FirewallConfig\AccessToken\TokenHandler\OidcUserInfoConfig : static)
     */
    public function oidcUserInfo(string|array $value = []): \_ContaoManager\Symfony\Config\Security\FirewallConfig\AccessToken\TokenHandler\OidcUserInfoConfig|static
    {
        if (!\is_array($value)) {
            $this->_usedProperties['oidcUserInfo'] = \true;
            $this->oidcUserInfo = $value;
            return $this;
        }
        if (!$this->oidcUserInfo instanceof \_ContaoManager\Symfony\Config\Security\FirewallConfig\AccessToken\TokenHandler\OidcUserInfoConfig) {
            $this->_usedProperties['oidcUserInfo'] = \true;
            $this->oidcUserInfo = new \_ContaoManager\Symfony\Config\Security\FirewallConfig\AccessToken\TokenHandler\OidcUserInfoConfig($value);
        } elseif (0 < \func_num_args()) {
            throw new InvalidConfigurationException('The node created by "oidcUserInfo()" has already been initialized. You cannot pass values the second time you call oidcUserInfo().');
        }
        return $this->oidcUserInfo;
    }
    public function oidc(array $value = []): \_ContaoManager\Symfony\Config\Security\FirewallConfig\AccessToken\TokenHandler\OidcConfig
    {
        if (null === $this->oidc) {
            $this->_usedProperties['oidc'] = \true;
            $this->oidc = new \_ContaoManager\Symfony\Config\Security\FirewallConfig\AccessToken\TokenHandler\OidcConfig($value);
        } elseif (0 < \func_num_args()) {
            throw new InvalidConfigurationException('The node created by "oidc()" has already been initialized. You cannot pass values the second time you call oidc().');
        }
        return $this->oidc;
    }
    public function __construct(array $value = [])
    {
        if (array_key_exists('id', $value)) {
            $this->_usedProperties['id'] = \true;
            $this->id = $value['id'];
            unset($value['id']);
        }
        if (array_key_exists('oidc_user_info', $value)) {
            $this->_usedProperties['oidcUserInfo'] = \true;
            $this->oidcUserInfo = \is_array($value['oidc_user_info']) ? new \_ContaoManager\Symfony\Config\Security\FirewallConfig\AccessToken\TokenHandler\OidcUserInfoConfig($value['oidc_user_info']) : $value['oidc_user_info'];
            unset($value['oidc_user_info']);
        }
        if (array_key_exists('oidc', $value)) {
            $this->_usedProperties['oidc'] = \true;
            $this->oidc = new \_ContaoManager\Symfony\Config\Security\FirewallConfig\AccessToken\TokenHandler\OidcConfig($value['oidc']);
            unset($value['oidc']);
        }
        if ([] !== $value) {
            throw new InvalidConfigurationException(sprintf('The following keys are not supported by "%s": ', __CLASS__) . implode(', ', array_keys($value)));
        }
    }
    public function toArray(): array
    {
        $output = [];
        if (isset($this->_usedProperties['id'])) {
            $output['id'] = $this->id;
        }
        if (isset($this->_usedProperties['oidcUserInfo'])) {
            $output['oidc_user_info'] = $this->oidcUserInfo instanceof \_ContaoManager\Symfony\Config\Security\FirewallConfig\AccessToken\TokenHandler\OidcUserInfoConfig ? $this->oidcUserInfo->toArray() : $this->oidcUserInfo;
        }
        if (isset($this->_usedProperties['oidc'])) {
            $output['oidc'] = $this->oidc->toArray();
        }
        return $output;
    }
}
<?php

namespace _ContaoManager\Symfony\Config\Security\FirewallConfig\AccessToken\TokenHandler;

use _ContaoManager\Symfony\Component\Config\Loader\ParamConfigurator;
use _ContaoManager\Symfony\Component\Config\Definition\Exception\InvalidConfigurationException;
/**
 * This class is automatically generated to help in creating a config.
 */
class OidcUserInfoConfig
{
    private $baseUri;
    private $claim;
    private $client;
    private $_usedProperties = [];
    /**
     * Base URI of the userinfo endpoint on the OIDC server.
     * @default null
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function baseUri($value): static
    {
        $this->_usedProperties['baseUri'] = \true;
        $this->baseUri = $value;
        return $this;
    }
    /**
     * Claim which contains the user identifier (e.g. sub, email, etc.).
     * @default 'sub'
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function claim($value): static
    {
        $this->_usedProperties['claim'] = \true;
        $this->claim = $value;
        return $this;
    }
    /**
     * HttpClient service id to use to call the OIDC server.
     * @default null
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function client($value): static
    {
        $this->_usedProperties['client'] = \true;
        $this->client = $value;
        return $this;
    }
    public function __construct(array $value = [])
    {
        if (array_key_exists('base_uri', $value)) {
            $this->_usedProperties['baseUri'] = \true;
            $this->baseUri = $value['base_uri'];
            unset($value['base_uri']);
        }
        if (array_key_exists('claim', $value)) {
            $this->_usedProperties['claim'] = \true;
            $this->claim = $value['claim'];
            unset($value['claim']);
        }
        if (array_key_exists('client', $value)) {
            $this->_usedProperties['client'] = \true;
            $this->client = $value['client'];
            unset($value['client']);
        }
        if ([] !== $value) {
            throw new InvalidConfigurationException(sprintf('The following keys are not supported by "%s": ', __CLASS__) . implode(', ', array_keys($value)));
        }
    }
    public function toArray(): array
    {
        $output = [];
        if (isset($this->_usedProperties['baseUri'])) {
            $output['base_uri'] = $this->baseUri;
        }
        if (isset($this->_usedProperties['claim'])) {
            $output['claim'] = $this->claim;
        }
        if (isset($this->_usedProperties['client'])) {
            $output['client'] = $this->client;
        }
        return $output;
    }
}
<?php

namespace _ContaoManager\Symfony\Config\Security\FirewallConfig\AccessToken\TokenHandler;

use _ContaoManager\Symfony\Component\Config\Loader\ParamConfigurator;
use _ContaoManager\Symfony\Component\Config\Definition\Exception\InvalidConfigurationException;
/**
 * This class is automatically generated to help in creating a config.
 */
class OidcConfig
{
    private $claim;
    private $audience;
    private $issuers;
    private $algorithm;
    private $key;
    private $_usedProperties = [];
    /**
     * Claim which contains the user identifier (e.g.: sub, email..).
     * @default 'sub'
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function claim($value): static
    {
        $this->_usedProperties['claim'] = \true;
        $this->claim = $value;
        return $this;
    }
    /**
     * Audience set in the token, for validation purpose.
     * @default null
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function audience($value): static
    {
        $this->_usedProperties['audience'] = \true;
        $this->audience = $value;
        return $this;
    }
    /**
     * @param ParamConfigurator|list<ParamConfigurator|mixed> $value
     *
     * @return $this
     */
    public function issuers(ParamConfigurator|array $value): static
    {
        $this->_usedProperties['issuers'] = \true;
        $this->issuers = $value;
        return $this;
    }
    /**
     * Algorithm used to sign the token.
     * @default null
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function algorithm($value): static
    {
        $this->_usedProperties['algorithm'] = \true;
        $this->algorithm = $value;
        return $this;
    }
    /**
     * JSON-encoded JWK used to sign the token (must contain a "kty" key).
     * @default null
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function key($value): static
    {
        $this->_usedProperties['key'] = \true;
        $this->key = $value;
        return $this;
    }
    public function __construct(array $value = [])
    {
        if (array_key_exists('claim', $value)) {
            $this->_usedProperties['claim'] = \true;
            $this->claim = $value['claim'];
            unset($value['claim']);
        }
        if (array_key_exists('audience', $value)) {
            $this->_usedProperties['audience'] = \true;
            $this->audience = $value['audience'];
            unset($value['audience']);
        }
        if (array_key_exists('issuers', $value)) {
            $this->_usedProperties['issuers'] = \true;
            $this->issuers = $value['issuers'];
            unset($value['issuers']);
        }
        if (array_key_exists('algorithm', $value)) {
            $this->_usedProperties['algorithm'] = \true;
            $this->algorithm = $value['algorithm'];
            unset($value['algorithm']);
        }
        if (array_key_exists('key', $value)) {
            $this->_usedProperties['key'] = \true;
            $this->key = $value['key'];
            unset($value['key']);
        }
        if ([] !== $value) {
            throw new InvalidConfigurationException(sprintf('The following keys are not supported by "%s": ', __CLASS__) . implode(', ', array_keys($value)));
        }
    }
    public function toArray(): array
    {
        $output = [];
        if (isset($this->_usedProperties['claim'])) {
            $output['claim'] = $this->claim;
        }
        if (isset($this->_usedProperties['audience'])) {
            $output['audience'] = $this->audience;
        }
        if (isset($this->_usedProperties['issuers'])) {
            $output['issuers'] = $this->issuers;
        }
        if (isset($this->_usedProperties['algorithm'])) {
            $output['algorithm'] = $this->algorithm;
        }
        if (isset($this->_usedProperties['key'])) {
            $output['key'] = $this->key;
        }
        return $output;
    }
}
<?php

namespace _ContaoManager\Symfony\Config\Security\FirewallConfig;

use _ContaoManager\Symfony\Component\Config\Loader\ParamConfigurator;
use _ContaoManager\Symfony\Component\Config\Definition\Exception\InvalidConfigurationException;
/**
 * This class is automatically generated to help in creating a config.
 */
class JsonLoginConfig
{
    private $provider;
    private $rememberMe;
    private $successHandler;
    private $failureHandler;
    private $checkPath;
    private $useForward;
    private $requirePreviousSession;
    private $loginPath;
    private $usernamePath;
    private $passwordPath;
    private $_usedProperties = [];
    /**
     * @default null
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function provider($value): static
    {
        $this->_usedProperties['provider'] = \true;
        $this->provider = $value;
        return $this;
    }
    /**
     * @default true
     * @param ParamConfigurator|bool $value
     * @return $this
     */
    public function rememberMe($value): static
    {
        $this->_usedProperties['rememberMe'] = \true;
        $this->rememberMe = $value;
        return $this;
    }
    /**
     * @default null
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function successHandler($value): static
    {
        $this->_usedProperties['successHandler'] = \true;
        $this->successHandler = $value;
        return $this;
    }
    /**
     * @default null
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function failureHandler($value): static
    {
        $this->_usedProperties['failureHandler'] = \true;
        $this->failureHandler = $value;
        return $this;
    }
    /**
     * @default '/login_check'
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function checkPath($value): static
    {
        $this->_usedProperties['checkPath'] = \true;
        $this->checkPath = $value;
        return $this;
    }
    /**
     * @default false
     * @param ParamConfigurator|bool $value
     * @return $this
     */
    public function useForward($value): static
    {
        $this->_usedProperties['useForward'] = \true;
        $this->useForward = $value;
        return $this;
    }
    /**
     * @default false
     * @param ParamConfigurator|bool $value
     * @deprecated Option "require_previous_session" at "json_login" is deprecated, it will be removed in version 7.0. Setting it has no effect anymore.
     * @return $this
     */
    public function requirePreviousSession($value): static
    {
        $this->_usedProperties['requirePreviousSession'] = \true;
        $this->requirePreviousSession = $value;
        return $this;
    }
    /**
     * @default '/login'
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function loginPath($value): static
    {
        $this->_usedProperties['loginPath'] = \true;
        $this->loginPath = $value;
        return $this;
    }
    /**
     * @default 'username'
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function usernamePath($value): static
    {
        $this->_usedProperties['usernamePath'] = \true;
        $this->usernamePath = $value;
        return $this;
    }
    /**
     * @default 'password'
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function passwordPath($value): static
    {
        $this->_usedProperties['passwordPath'] = \true;
        $this->passwordPath = $value;
        return $this;
    }
    public function __construct(array $value = [])
    {
        if (array_key_exists('provider', $value)) {
            $this->_usedProperties['provider'] = \true;
            $this->provider = $value['provider'];
            unset($value['provider']);
        }
        if (array_key_exists('remember_me', $value)) {
            $this->_usedProperties['rememberMe'] = \true;
            $this->rememberMe = $value['remember_me'];
            unset($value['remember_me']);
        }
        if (array_key_exists('success_handler', $value)) {
            $this->_usedProperties['successHandler'] = \true;
            $this->successHandler = $value['success_handler'];
            unset($value['success_handler']);
        }
        if (array_key_exists('failure_handler', $value)) {
            $this->_usedProperties['failureHandler'] = \true;
            $this->failureHandler = $value['failure_handler'];
            unset($value['failure_handler']);
        }
        if (array_key_exists('check_path', $value)) {
            $this->_usedProperties['checkPath'] = \true;
            $this->checkPath = $value['check_path'];
            unset($value['check_path']);
        }
        if (array_key_exists('use_forward', $value)) {
            $this->_usedProperties['useForward'] = \true;
            $this->useForward = $value['use_forward'];
            unset($value['use_forward']);
        }
        if (array_key_exists('require_previous_session', $value)) {
            $this->_usedProperties['requirePreviousSession'] = \true;
            $this->requirePreviousSession = $value['require_previous_session'];
            unset($value['require_previous_session']);
        }
        if (array_key_exists('login_path', $value)) {
            $this->_usedProperties['loginPath'] = \true;
            $this->loginPath = $value['login_path'];
            unset($value['login_path']);
        }
        if (array_key_exists('username_path', $value)) {
            $this->_usedProperties['usernamePath'] = \true;
            $this->usernamePath = $value['username_path'];
            unset($value['username_path']);
        }
        if (array_key_exists('password_path', $value)) {
            $this->_usedProperties['passwordPath'] = \true;
            $this->passwordPath = $value['password_path'];
            unset($value['password_path']);
        }
        if ([] !== $value) {
            throw new InvalidConfigurationException(sprintf('The following keys are not supported by "%s": ', __CLASS__) . implode(', ', array_keys($value)));
        }
    }
    public function toArray(): array
    {
        $output = [];
        if (isset($this->_usedProperties['provider'])) {
            $output['provider'] = $this->provider;
        }
        if (isset($this->_usedProperties['rememberMe'])) {
            $output['remember_me'] = $this->rememberMe;
        }
        if (isset($this->_usedProperties['successHandler'])) {
            $output['success_handler'] = $this->successHandler;
        }
        if (isset($this->_usedProperties['failureHandler'])) {
            $output['failure_handler'] = $this->failureHandler;
        }
        if (isset($this->_usedProperties['checkPath'])) {
            $output['check_path'] = $this->checkPath;
        }
        if (isset($this->_usedProperties['useForward'])) {
            $output['use_forward'] = $this->useForward;
        }
        if (isset($this->_usedProperties['requirePreviousSession'])) {
            $output['require_previous_session'] = $this->requirePreviousSession;
        }
        if (isset($this->_usedProperties['loginPath'])) {
            $output['login_path'] = $this->loginPath;
        }
        if (isset($this->_usedProperties['usernamePath'])) {
            $output['username_path'] = $this->usernamePath;
        }
        if (isset($this->_usedProperties['passwordPath'])) {
            $output['password_path'] = $this->passwordPath;
        }
        return $output;
    }
}
<?php

namespace _ContaoManager\Symfony\Config\Security\FirewallConfig\Logout;

use _ContaoManager\Symfony\Component\Config\Loader\ParamConfigurator;
use _ContaoManager\Symfony\Component\Config\Definition\Exception\InvalidConfigurationException;
/**
 * This class is automatically generated to help in creating a config.
 */
class DeleteCookieConfig
{
    private $path;
    private $domain;
    private $secure;
    private $samesite;
    private $partitioned;
    private $_usedProperties = [];
    /**
     * @default null
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function path($value): static
    {
        $this->_usedProperties['path'] = \true;
        $this->path = $value;
        return $this;
    }
    /**
     * @default null
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function domain($value): static
    {
        $this->_usedProperties['domain'] = \true;
        $this->domain = $value;
        return $this;
    }
    /**
     * @default false
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function secure($value): static
    {
        $this->_usedProperties['secure'] = \true;
        $this->secure = $value;
        return $this;
    }
    /**
     * @default null
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function samesite($value): static
    {
        $this->_usedProperties['samesite'] = \true;
        $this->samesite = $value;
        return $this;
    }
    /**
     * @default false
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function partitioned($value): static
    {
        $this->_usedProperties['partitioned'] = \true;
        $this->partitioned = $value;
        return $this;
    }
    public function __construct(array $value = [])
    {
        if (array_key_exists('path', $value)) {
            $this->_usedProperties['path'] = \true;
            $this->path = $value['path'];
            unset($value['path']);
        }
        if (array_key_exists('domain', $value)) {
            $this->_usedProperties['domain'] = \true;
            $this->domain = $value['domain'];
            unset($value['domain']);
        }
        if (array_key_exists('secure', $value)) {
            $this->_usedProperties['secure'] = \true;
            $this->secure = $value['secure'];
            unset($value['secure']);
        }
        if (array_key_exists('samesite', $value)) {
            $this->_usedProperties['samesite'] = \true;
            $this->samesite = $value['samesite'];
            unset($value['samesite']);
        }
        if (array_key_exists('partitioned', $value)) {
            $this->_usedProperties['partitioned'] = \true;
            $this->partitioned = $value['partitioned'];
            unset($value['partitioned']);
        }
        if ([] !== $value) {
            throw new InvalidConfigurationException(sprintf('The following keys are not supported by "%s": ', __CLASS__) . implode(', ', array_keys($value)));
        }
    }
    public function toArray(): array
    {
        $output = [];
        if (isset($this->_usedProperties['path'])) {
            $output['path'] = $this->path;
        }
        if (isset($this->_usedProperties['domain'])) {
            $output['domain'] = $this->domain;
        }
        if (isset($this->_usedProperties['secure'])) {
            $output['secure'] = $this->secure;
        }
        if (isset($this->_usedProperties['samesite'])) {
            $output['samesite'] = $this->samesite;
        }
        if (isset($this->_usedProperties['partitioned'])) {
            $output['partitioned'] = $this->partitioned;
        }
        return $output;
    }
}
<?php

namespace _ContaoManager\Symfony\Config\Security\FirewallConfig;

use _ContaoManager\Symfony\Component\Config\Loader\ParamConfigurator;
use _ContaoManager\Symfony\Component\Config\Definition\Exception\InvalidConfigurationException;
/**
 * This class is automatically generated to help in creating a config.
 */
class SwitchUserConfig
{
    private $provider;
    private $parameter;
    private $role;
    private $targetRoute;
    private $_usedProperties = [];
    /**
     * @default null
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function provider($value): static
    {
        $this->_usedProperties['provider'] = \true;
        $this->provider = $value;
        return $this;
    }
    /**
     * @default '_switch_user'
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function parameter($value): static
    {
        $this->_usedProperties['parameter'] = \true;
        $this->parameter = $value;
        return $this;
    }
    /**
     * @default 'ROLE_ALLOWED_TO_SWITCH'
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function role($value): static
    {
        $this->_usedProperties['role'] = \true;
        $this->role = $value;
        return $this;
    }
    /**
     * @default null
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function targetRoute($value): static
    {
        $this->_usedProperties['targetRoute'] = \true;
        $this->targetRoute = $value;
        return $this;
    }
    public function __construct(array $value = [])
    {
        if (array_key_exists('provider', $value)) {
            $this->_usedProperties['provider'] = \true;
            $this->provider = $value['provider'];
            unset($value['provider']);
        }
        if (array_key_exists('parameter', $value)) {
            $this->_usedProperties['parameter'] = \true;
            $this->parameter = $value['parameter'];
            unset($value['parameter']);
        }
        if (array_key_exists('role', $value)) {
            $this->_usedProperties['role'] = \true;
            $this->role = $value['role'];
            unset($value['role']);
        }
        if (array_key_exists('target_route', $value)) {
            $this->_usedProperties['targetRoute'] = \true;
            $this->targetRoute = $value['target_route'];
            unset($value['target_route']);
        }
        if ([] !== $value) {
            throw new InvalidConfigurationException(sprintf('The following keys are not supported by "%s": ', __CLASS__) . implode(', ', array_keys($value)));
        }
    }
    public function toArray(): array
    {
        $output = [];
        if (isset($this->_usedProperties['provider'])) {
            $output['provider'] = $this->provider;
        }
        if (isset($this->_usedProperties['parameter'])) {
            $output['parameter'] = $this->parameter;
        }
        if (isset($this->_usedProperties['role'])) {
            $output['role'] = $this->role;
        }
        if (isset($this->_usedProperties['targetRoute'])) {
            $output['target_route'] = $this->targetRoute;
        }
        return $output;
    }
}
<?php

namespace _ContaoManager\Symfony\Config\Security\FirewallConfig;

use _ContaoManager\Symfony\Component\Config\Loader\ParamConfigurator;
use _ContaoManager\Symfony\Component\Config\Definition\Exception\InvalidConfigurationException;
/**
 * This class is automatically generated to help in creating a config.
 */
class LoginThrottlingConfig
{
    private $limiter;
    private $maxAttempts;
    private $interval;
    private $lockFactory;
    private $_usedProperties = [];
    /**
     * A service id implementing "Symfony\Component\HttpFoundation\RateLimiter\RequestRateLimiterInterface".
     * @default null
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function limiter($value): static
    {
        $this->_usedProperties['limiter'] = \true;
        $this->limiter = $value;
        return $this;
    }
    /**
     * @default 5
     * @param ParamConfigurator|int $value
     * @return $this
     */
    public function maxAttempts($value): static
    {
        $this->_usedProperties['maxAttempts'] = \true;
        $this->maxAttempts = $value;
        return $this;
    }
    /**
     * @default '1 minute'
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function interval($value): static
    {
        $this->_usedProperties['interval'] = \true;
        $this->interval = $value;
        return $this;
    }
    /**
     * The service ID of the lock factory used by the login rate limiter (or null to disable locking)
     * @default null
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function lockFactory($value): static
    {
        $this->_usedProperties['lockFactory'] = \true;
        $this->lockFactory = $value;
        return $this;
    }
    public function __construct(array $value = [])
    {
        if (array_key_exists('limiter', $value)) {
            $this->_usedProperties['limiter'] = \true;
            $this->limiter = $value['limiter'];
            unset($value['limiter']);
        }
        if (array_key_exists('max_attempts', $value)) {
            $this->_usedProperties['maxAttempts'] = \true;
            $this->maxAttempts = $value['max_attempts'];
            unset($value['max_attempts']);
        }
        if (array_key_exists('interval', $value)) {
            $this->_usedProperties['interval'] = \true;
            $this->interval = $value['interval'];
            unset($value['interval']);
        }
        if (array_key_exists('lock_factory', $value)) {
            $this->_usedProperties['lockFactory'] = \true;
            $this->lockFactory = $value['lock_factory'];
            unset($value['lock_factory']);
        }
        if ([] !== $value) {
            throw new InvalidConfigurationException(sprintf('The following keys are not supported by "%s": ', __CLASS__) . implode(', ', array_keys($value)));
        }
    }
    public function toArray(): array
    {
        $output = [];
        if (isset($this->_usedProperties['limiter'])) {
            $output['limiter'] = $this->limiter;
        }
        if (isset($this->_usedProperties['maxAttempts'])) {
            $output['max_attempts'] = $this->maxAttempts;
        }
        if (isset($this->_usedProperties['interval'])) {
            $output['interval'] = $this->interval;
        }
        if (isset($this->_usedProperties['lockFactory'])) {
            $output['lock_factory'] = $this->lockFactory;
        }
        return $output;
    }
}
<?php

namespace _ContaoManager\Symfony\Config\Security\FirewallConfig;

use _ContaoManager\Symfony\Component\Config\Loader\ParamConfigurator;
use _ContaoManager\Symfony\Component\Config\Definition\Exception\InvalidConfigurationException;
/**
 * This class is automatically generated to help in creating a config.
 */
class LoginLinkConfig
{
    private $checkRoute;
    private $checkPostOnly;
    private $signatureProperties;
    private $lifetime;
    private $maxUses;
    private $usedLinkCache;
    private $successHandler;
    private $failureHandler;
    private $provider;
    private $alwaysUseDefaultTargetPath;
    private $defaultTargetPath;
    private $loginPath;
    private $targetPathParameter;
    private $useReferer;
    private $failurePath;
    private $failureForward;
    private $failurePathParameter;
    private $_usedProperties = [];
    /**
     * Route that will validate the login link - e.g. "app_login_link_verify".
     * @default null
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function checkRoute($value): static
    {
        $this->_usedProperties['checkRoute'] = \true;
        $this->checkRoute = $value;
        return $this;
    }
    /**
     * If true, only HTTP POST requests to "check_route" will be handled by the authenticator.
     * @default false
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function checkPostOnly($value): static
    {
        $this->_usedProperties['checkPostOnly'] = \true;
        $this->checkPostOnly = $value;
        return $this;
    }
    /**
     * @param ParamConfigurator|list<ParamConfigurator|mixed> $value
     *
     * @return $this
     */
    public function signatureProperties(ParamConfigurator|array $value): static
    {
        $this->_usedProperties['signatureProperties'] = \true;
        $this->signatureProperties = $value;
        return $this;
    }
    /**
     * The lifetime of the login link in seconds.
     * @default 600
     * @param ParamConfigurator|int $value
     * @return $this
     */
    public function lifetime($value): static
    {
        $this->_usedProperties['lifetime'] = \true;
        $this->lifetime = $value;
        return $this;
    }
    /**
     * Max number of times a login link can be used - null means unlimited within lifetime.
     * @default null
     * @param ParamConfigurator|int $value
     * @return $this
     */
    public function maxUses($value): static
    {
        $this->_usedProperties['maxUses'] = \true;
        $this->maxUses = $value;
        return $this;
    }
    /**
     * Cache service id used to expired links of max_uses is set.
     * @default null
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function usedLinkCache($value): static
    {
        $this->_usedProperties['usedLinkCache'] = \true;
        $this->usedLinkCache = $value;
        return $this;
    }
    /**
     * A service id that implements Symfony\Component\Security\Http\Authentication\AuthenticationSuccessHandlerInterface.
     * @default null
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function successHandler($value): static
    {
        $this->_usedProperties['successHandler'] = \true;
        $this->successHandler = $value;
        return $this;
    }
    /**
     * A service id that implements Symfony\Component\Security\Http\Authentication\AuthenticationFailureHandlerInterface.
     * @default null
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function failureHandler($value): static
    {
        $this->_usedProperties['failureHandler'] = \true;
        $this->failureHandler = $value;
        return $this;
    }
    /**
     * The user provider to load users from.
     * @default null
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function provider($value): static
    {
        $this->_usedProperties['provider'] = \true;
        $this->provider = $value;
        return $this;
    }
    /**
     * @default false
     * @param ParamConfigurator|bool $value
     * @return $this
     */
    public function alwaysUseDefaultTargetPath($value): static
    {
        $this->_usedProperties['alwaysUseDefaultTargetPath'] = \true;
        $this->alwaysUseDefaultTargetPath = $value;
        return $this;
    }
    /**
     * @default '/'
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function defaultTargetPath($value): static
    {
        $this->_usedProperties['defaultTargetPath'] = \true;
        $this->defaultTargetPath = $value;
        return $this;
    }
    /**
     * @default '/login'
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function loginPath($value): static
    {
        $this->_usedProperties['loginPath'] = \true;
        $this->loginPath = $value;
        return $this;
    }
    /**
     * @default '_target_path'
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function targetPathParameter($value): static
    {
        $this->_usedProperties['targetPathParameter'] = \true;
        $this->targetPathParameter = $value;
        return $this;
    }
    /**
     * @default false
     * @param ParamConfigurator|bool $value
     * @return $this
     */
    public function useReferer($value): static
    {
        $this->_usedProperties['useReferer'] = \true;
        $this->useReferer = $value;
        return $this;
    }
    /**
     * @default null
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function failurePath($value): static
    {
        $this->_usedProperties['failurePath'] = \true;
        $this->failurePath = $value;
        return $this;
    }
    /**
     * @default false
     * @param ParamConfigurator|bool $value
     * @return $this
     */
    public function failureForward($value): static
    {
        $this->_usedProperties['failureForward'] = \true;
        $this->failureForward = $value;
        return $this;
    }
    /**
     * @default '_failure_path'
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function failurePathParameter($value): static
    {
        $this->_usedProperties['failurePathParameter'] = \true;
        $this->failurePathParameter = $value;
        return $this;
    }
    public function __construct(array $value = [])
    {
        if (array_key_exists('check_route', $value)) {
            $this->_usedProperties['checkRoute'] = \true;
            $this->checkRoute = $value['check_route'];
            unset($value['check_route']);
        }
        if (array_key_exists('check_post_only', $value)) {
            $this->_usedProperties['checkPostOnly'] = \true;
            $this->checkPostOnly = $value['check_post_only'];
            unset($value['check_post_only']);
        }
        if (array_key_exists('signature_properties', $value)) {
            $this->_usedProperties['signatureProperties'] = \true;
            $this->signatureProperties = $value['signature_properties'];
            unset($value['signature_properties']);
        }
        if (array_key_exists('lifetime', $value)) {
            $this->_usedProperties['lifetime'] = \true;
            $this->lifetime = $value['lifetime'];
            unset($value['lifetime']);
        }
        if (array_key_exists('max_uses', $value)) {
            $this->_usedProperties['maxUses'] = \true;
            $this->maxUses = $value['max_uses'];
            unset($value['max_uses']);
        }
        if (array_key_exists('used_link_cache', $value)) {
            $this->_usedProperties['usedLinkCache'] = \true;
            $this->usedLinkCache = $value['used_link_cache'];
            unset($value['used_link_cache']);
        }
        if (array_key_exists('success_handler', $value)) {
            $this->_usedProperties['successHandler'] = \true;
            $this->successHandler = $value['success_handler'];
            unset($value['success_handler']);
        }
        if (array_key_exists('failure_handler', $value)) {
            $this->_usedProperties['failureHandler'] = \true;
            $this->failureHandler = $value['failure_handler'];
            unset($value['failure_handler']);
        }
        if (array_key_exists('provider', $value)) {
            $this->_usedProperties['provider'] = \true;
            $this->provider = $value['provider'];
            unset($value['provider']);
        }
        if (array_key_exists('always_use_default_target_path', $value)) {
            $this->_usedProperties['alwaysUseDefaultTargetPath'] = \true;
            $this->alwaysUseDefaultTargetPath = $value['always_use_default_target_path'];
            unset($value['always_use_default_target_path']);
        }
        if (array_key_exists('default_target_path', $value)) {
            $this->_usedProperties['defaultTargetPath'] = \true;
            $this->defaultTargetPath = $value['default_target_path'];
            unset($value['default_target_path']);
        }
        if (array_key_exists('login_path', $value)) {
            $this->_usedProperties['loginPath'] = \true;
            $this->loginPath = $value['login_path'];
            unset($value['login_path']);
        }
        if (array_key_exists('target_path_parameter', $value)) {
            $this->_usedProperties['targetPathParameter'] = \true;
            $this->targetPathParameter = $value['target_path_parameter'];
            unset($value['target_path_parameter']);
        }
        if (array_key_exists('use_referer', $value)) {
            $this->_usedProperties['useReferer'] = \true;
            $this->useReferer = $value['use_referer'];
            unset($value['use_referer']);
        }
        if (array_key_exists('failure_path', $value)) {
            $this->_usedProperties['failurePath'] = \true;
            $this->failurePath = $value['failure_path'];
            unset($value['failure_path']);
        }
        if (array_key_exists('failure_forward', $value)) {
            $this->_usedProperties['failureForward'] = \true;
            $this->failureForward = $value['failure_forward'];
            unset($value['failure_forward']);
        }
        if (array_key_exists('failure_path_parameter', $value)) {
            $this->_usedProperties['failurePathParameter'] = \true;
            $this->failurePathParameter = $value['failure_path_parameter'];
            unset($value['failure_path_parameter']);
        }
        if ([] !== $value) {
            throw new InvalidConfigurationException(sprintf('The following keys are not supported by "%s": ', __CLASS__) . implode(', ', array_keys($value)));
        }
    }
    public function toArray(): array
    {
        $output = [];
        if (isset($this->_usedProperties['checkRoute'])) {
            $output['check_route'] = $this->checkRoute;
        }
        if (isset($this->_usedProperties['checkPostOnly'])) {
            $output['check_post_only'] = $this->checkPostOnly;
        }
        if (isset($this->_usedProperties['signatureProperties'])) {
            $output['signature_properties'] = $this->signatureProperties;
        }
        if (isset($this->_usedProperties['lifetime'])) {
            $output['lifetime'] = $this->lifetime;
        }
        if (isset($this->_usedProperties['maxUses'])) {
            $output['max_uses'] = $this->maxUses;
        }
        if (isset($this->_usedProperties['usedLinkCache'])) {
            $output['used_link_cache'] = $this->usedLinkCache;
        }
        if (isset($this->_usedProperties['successHandler'])) {
            $output['success_handler'] = $this->successHandler;
        }
        if (isset($this->_usedProperties['failureHandler'])) {
            $output['failure_handler'] = $this->failureHandler;
        }
        if (isset($this->_usedProperties['provider'])) {
            $output['provider'] = $this->provider;
        }
        if (isset($this->_usedProperties['alwaysUseDefaultTargetPath'])) {
            $output['always_use_default_target_path'] = $this->alwaysUseDefaultTargetPath;
        }
        if (isset($this->_usedProperties['defaultTargetPath'])) {
            $output['default_target_path'] = $this->defaultTargetPath;
        }
        if (isset($this->_usedProperties['loginPath'])) {
            $output['login_path'] = $this->loginPath;
        }
        if (isset($this->_usedProperties['targetPathParameter'])) {
            $output['target_path_parameter'] = $this->targetPathParameter;
        }
        if (isset($this->_usedProperties['useReferer'])) {
            $output['use_referer'] = $this->useReferer;
        }
        if (isset($this->_usedProperties['failurePath'])) {
            $output['failure_path'] = $this->failurePath;
        }
        if (isset($this->_usedProperties['failureForward'])) {
            $output['failure_forward'] = $this->failureForward;
        }
        if (isset($this->_usedProperties['failurePathParameter'])) {
            $output['failure_path_parameter'] = $this->failurePathParameter;
        }
        return $output;
    }
}
<?php

namespace _ContaoManager\Symfony\Config\Security\FirewallConfig\RememberMe\TokenProvider;

use _ContaoManager\Symfony\Component\Config\Loader\ParamConfigurator;
use _ContaoManager\Symfony\Component\Config\Definition\Exception\InvalidConfigurationException;
/**
 * This class is automatically generated to help in creating a config.
 */
class DoctrineConfig
{
    private $enabled;
    private $connection;
    private $_usedProperties = [];
    /**
     * @default false
     * @param ParamConfigurator|bool $value
     * @return $this
     */
    public function enabled($value): static
    {
        $this->_usedProperties['enabled'] = \true;
        $this->enabled = $value;
        return $this;
    }
    /**
     * @default null
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function connection($value): static
    {
        $this->_usedProperties['connection'] = \true;
        $this->connection = $value;
        return $this;
    }
    public function __construct(array $value = [])
    {
        if (array_key_exists('enabled', $value)) {
            $this->_usedProperties['enabled'] = \true;
            $this->enabled = $value['enabled'];
            unset($value['enabled']);
        }
        if (array_key_exists('connection', $value)) {
            $this->_usedProperties['connection'] = \true;
            $this->connection = $value['connection'];
            unset($value['connection']);
        }
        if ([] !== $value) {
            throw new InvalidConfigurationException(sprintf('The following keys are not supported by "%s": ', __CLASS__) . implode(', ', array_keys($value)));
        }
    }
    public function toArray(): array
    {
        $output = [];
        if (isset($this->_usedProperties['enabled'])) {
            $output['enabled'] = $this->enabled;
        }
        if (isset($this->_usedProperties['connection'])) {
            $output['connection'] = $this->connection;
        }
        return $output;
    }
}
<?php

namespace _ContaoManager\Symfony\Config\Security\FirewallConfig\RememberMe;

require_once __DIR__ . \DIRECTORY_SEPARATOR . 'TokenProvider' . \DIRECTORY_SEPARATOR . 'DoctrineConfig.php';
use _ContaoManager\Symfony\Component\Config\Loader\ParamConfigurator;
use _ContaoManager\Symfony\Component\Config\Definition\Exception\InvalidConfigurationException;
/**
 * This class is automatically generated to help in creating a config.
 */
class TokenProviderConfig
{
    private $service;
    private $doctrine;
    private $_usedProperties = [];
    /**
     * The service ID of a custom rememberme token provider.
     * @default null
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function service($value): static
    {
        $this->_usedProperties['service'] = \true;
        $this->service = $value;
        return $this;
    }
    /**
     * @default {"enabled":false,"connection":null}
     */
    public function doctrine(array $value = []): \_ContaoManager\Symfony\Config\Security\FirewallConfig\RememberMe\TokenProvider\DoctrineConfig
    {
        if (null === $this->doctrine) {
            $this->_usedProperties['doctrine'] = \true;
            $this->doctrine = new \_ContaoManager\Symfony\Config\Security\FirewallConfig\RememberMe\TokenProvider\DoctrineConfig($value);
        } elseif (0 < \func_num_args()) {
            throw new InvalidConfigurationException('The node created by "doctrine()" has already been initialized. You cannot pass values the second time you call doctrine().');
        }
        return $this->doctrine;
    }
    public function __construct(array $value = [])
    {
        if (array_key_exists('service', $value)) {
            $this->_usedProperties['service'] = \true;
            $this->service = $value['service'];
            unset($value['service']);
        }
        if (array_key_exists('doctrine', $value)) {
            $this->_usedProperties['doctrine'] = \true;
            $this->doctrine = \is_array($value['doctrine']) ? new \_ContaoManager\Symfony\Config\Security\FirewallConfig\RememberMe\TokenProvider\DoctrineConfig($value['doctrine']) : $value['doctrine'];
            unset($value['doctrine']);
        }
        if ([] !== $value) {
            throw new InvalidConfigurationException(sprintf('The following keys are not supported by "%s": ', __CLASS__) . implode(', ', array_keys($value)));
        }
    }
    public function toArray(): array
    {
        $output = [];
        if (isset($this->_usedProperties['service'])) {
            $output['service'] = $this->service;
        }
        if (isset($this->_usedProperties['doctrine'])) {
            $output['doctrine'] = $this->doctrine instanceof \_ContaoManager\Symfony\Config\Security\FirewallConfig\RememberMe\TokenProvider\DoctrineConfig ? $this->doctrine->toArray() : $this->doctrine;
        }
        return $output;
    }
}
<?php

namespace _ContaoManager\Symfony\Config\Security\FirewallConfig;

use _ContaoManager\Symfony\Component\Config\Loader\ParamConfigurator;
use _ContaoManager\Symfony\Component\Config\Definition\Exception\InvalidConfigurationException;
/**
 * This class is automatically generated to help in creating a config.
 */
class FormLoginLdapConfig
{
    private $provider;
    private $rememberMe;
    private $successHandler;
    private $failureHandler;
    private $checkPath;
    private $useForward;
    private $requirePreviousSession;
    private $loginPath;
    private $usernameParameter;
    private $passwordParameter;
    private $csrfParameter;
    private $csrfTokenId;
    private $enableCsrf;
    private $postOnly;
    private $formOnly;
    private $alwaysUseDefaultTargetPath;
    private $defaultTargetPath;
    private $targetPathParameter;
    private $useReferer;
    private $failurePath;
    private $failureForward;
    private $failurePathParameter;
    private $csrfTokenGenerator;
    private $service;
    private $dnString;
    private $queryString;
    private $searchDn;
    private $searchPassword;
    private $_usedProperties = [];
    /**
     * @default null
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function provider($value): static
    {
        $this->_usedProperties['provider'] = \true;
        $this->provider = $value;
        return $this;
    }
    /**
     * @default true
     * @param ParamConfigurator|bool $value
     * @return $this
     */
    public function rememberMe($value): static
    {
        $this->_usedProperties['rememberMe'] = \true;
        $this->rememberMe = $value;
        return $this;
    }
    /**
     * @default null
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function successHandler($value): static
    {
        $this->_usedProperties['successHandler'] = \true;
        $this->successHandler = $value;
        return $this;
    }
    /**
     * @default null
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function failureHandler($value): static
    {
        $this->_usedProperties['failureHandler'] = \true;
        $this->failureHandler = $value;
        return $this;
    }
    /**
     * @default '/login_check'
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function checkPath($value): static
    {
        $this->_usedProperties['checkPath'] = \true;
        $this->checkPath = $value;
        return $this;
    }
    /**
     * @default false
     * @param ParamConfigurator|bool $value
     * @return $this
     */
    public function useForward($value): static
    {
        $this->_usedProperties['useForward'] = \true;
        $this->useForward = $value;
        return $this;
    }
    /**
     * @default false
     * @param ParamConfigurator|bool $value
     * @deprecated Option "require_previous_session" at "form_login_ldap" is deprecated, it will be removed in version 7.0. Setting it has no effect anymore.
     * @return $this
     */
    public function requirePreviousSession($value): static
    {
        $this->_usedProperties['requirePreviousSession'] = \true;
        $this->requirePreviousSession = $value;
        return $this;
    }
    /**
     * @default '/login'
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function loginPath($value): static
    {
        $this->_usedProperties['loginPath'] = \true;
        $this->loginPath = $value;
        return $this;
    }
    /**
     * @default '_username'
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function usernameParameter($value): static
    {
        $this->_usedProperties['usernameParameter'] = \true;
        $this->usernameParameter = $value;
        return $this;
    }
    /**
     * @default '_password'
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function passwordParameter($value): static
    {
        $this->_usedProperties['passwordParameter'] = \true;
        $this->passwordParameter = $value;
        return $this;
    }
    /**
     * @default '_csrf_token'
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function csrfParameter($value): static
    {
        $this->_usedProperties['csrfParameter'] = \true;
        $this->csrfParameter = $value;
        return $this;
    }
    /**
     * @default 'authenticate'
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function csrfTokenId($value): static
    {
        $this->_usedProperties['csrfTokenId'] = \true;
        $this->csrfTokenId = $value;
        return $this;
    }
    /**
     * @default false
     * @param ParamConfigurator|bool $value
     * @return $this
     */
    public function enableCsrf($value): static
    {
        $this->_usedProperties['enableCsrf'] = \true;
        $this->enableCsrf = $value;
        return $this;
    }
    /**
     * @default true
     * @param ParamConfigurator|bool $value
     * @return $this
     */
    public function postOnly($value): static
    {
        $this->_usedProperties['postOnly'] = \true;
        $this->postOnly = $value;
        return $this;
    }
    /**
     * @default false
     * @param ParamConfigurator|bool $value
     * @return $this
     */
    public function formOnly($value): static
    {
        $this->_usedProperties['formOnly'] = \true;
        $this->formOnly = $value;
        return $this;
    }
    /**
     * @default false
     * @param ParamConfigurator|bool $value
     * @return $this
     */
    public function alwaysUseDefaultTargetPath($value): static
    {
        $this->_usedProperties['alwaysUseDefaultTargetPath'] = \true;
        $this->alwaysUseDefaultTargetPath = $value;
        return $this;
    }
    /**
     * @default '/'
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function defaultTargetPath($value): static
    {
        $this->_usedProperties['defaultTargetPath'] = \true;
        $this->defaultTargetPath = $value;
        return $this;
    }
    /**
     * @default '_target_path'
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function targetPathParameter($value): static
    {
        $this->_usedProperties['targetPathParameter'] = \true;
        $this->targetPathParameter = $value;
        return $this;
    }
    /**
     * @default false
     * @param ParamConfigurator|bool $value
     * @return $this
     */
    public function useReferer($value): static
    {
        $this->_usedProperties['useReferer'] = \true;
        $this->useReferer = $value;
        return $this;
    }
    /**
     * @default null
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function failurePath($value): static
    {
        $this->_usedProperties['failurePath'] = \true;
        $this->failurePath = $value;
        return $this;
    }
    /**
     * @default false
     * @param ParamConfigurator|bool $value
     * @return $this
     */
    public function failureForward($value): static
    {
        $this->_usedProperties['failureForward'] = \true;
        $this->failureForward = $value;
        return $this;
    }
    /**
     * @default '_failure_path'
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function failurePathParameter($value): static
    {
        $this->_usedProperties['failurePathParameter'] = \true;
        $this->failurePathParameter = $value;
        return $this;
    }
    /**
     * @default null
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function csrfTokenGenerator($value): static
    {
        $this->_usedProperties['csrfTokenGenerator'] = \true;
        $this->csrfTokenGenerator = $value;
        return $this;
    }
    /**
     * @default 'ldap'
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function service($value): static
    {
        $this->_usedProperties['service'] = \true;
        $this->service = $value;
        return $this;
    }
    /**
     * @default '{username}'
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function dnString($value): static
    {
        $this->_usedProperties['dnString'] = \true;
        $this->dnString = $value;
        return $this;
    }
    /**
     * @default null
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function queryString($value): static
    {
        $this->_usedProperties['queryString'] = \true;
        $this->queryString = $value;
        return $this;
    }
    /**
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function searchDn($value): static
    {
        $this->_usedProperties['searchDn'] = \true;
        $this->searchDn = $value;
        return $this;
    }
    /**
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function searchPassword($value): static
    {
        $this->_usedProperties['searchPassword'] = \true;
        $this->searchPassword = $value;
        return $this;
    }
    public function __construct(array $value = [])
    {
        if (array_key_exists('provider', $value)) {
            $this->_usedProperties['provider'] = \true;
            $this->provider = $value['provider'];
            unset($value['provider']);
        }
        if (array_key_exists('remember_me', $value)) {
            $this->_usedProperties['rememberMe'] = \true;
            $this->rememberMe = $value['remember_me'];
            unset($value['remember_me']);
        }
        if (array_key_exists('success_handler', $value)) {
            $this->_usedProperties['successHandler'] = \true;
            $this->successHandler = $value['success_handler'];
            unset($value['success_handler']);
        }
        if (array_key_exists('failure_handler', $value)) {
            $this->_usedProperties['failureHandler'] = \true;
            $this->failureHandler = $value['failure_handler'];
            unset($value['failure_handler']);
        }
        if (array_key_exists('check_path', $value)) {
            $this->_usedProperties['checkPath'] = \true;
            $this->checkPath = $value['check_path'];
            unset($value['check_path']);
        }
        if (array_key_exists('use_forward', $value)) {
            $this->_usedProperties['useForward'] = \true;
            $this->useForward = $value['use_forward'];
            unset($value['use_forward']);
        }
        if (array_key_exists('require_previous_session', $value)) {
            $this->_usedProperties['requirePreviousSession'] = \true;
            $this->requirePreviousSession = $value['require_previous_session'];
            unset($value['require_previous_session']);
        }
        if (array_key_exists('login_path', $value)) {
            $this->_usedProperties['loginPath'] = \true;
            $this->loginPath = $value['login_path'];
            unset($value['login_path']);
        }
        if (array_key_exists('username_parameter', $value)) {
            $this->_usedProperties['usernameParameter'] = \true;
            $this->usernameParameter = $value['username_parameter'];
            unset($value['username_parameter']);
        }
        if (array_key_exists('password_parameter', $value)) {
            $this->_usedProperties['passwordParameter'] = \true;
            $this->passwordParameter = $value['password_parameter'];
            unset($value['password_parameter']);
        }
        if (array_key_exists('csrf_parameter', $value)) {
            $this->_usedProperties['csrfParameter'] = \true;
            $this->csrfParameter = $value['csrf_parameter'];
            unset($value['csrf_parameter']);
        }
        if (array_key_exists('csrf_token_id', $value)) {
            $this->_usedProperties['csrfTokenId'] = \true;
            $this->csrfTokenId = $value['csrf_token_id'];
            unset($value['csrf_token_id']);
        }
        if (array_key_exists('enable_csrf', $value)) {
            $this->_usedProperties['enableCsrf'] = \true;
            $this->enableCsrf = $value['enable_csrf'];
            unset($value['enable_csrf']);
        }
        if (array_key_exists('post_only', $value)) {
            $this->_usedProperties['postOnly'] = \true;
            $this->postOnly = $value['post_only'];
            unset($value['post_only']);
        }
        if (array_key_exists('form_only', $value)) {
            $this->_usedProperties['formOnly'] = \true;
            $this->formOnly = $value['form_only'];
            unset($value['form_only']);
        }
        if (array_key_exists('always_use_default_target_path', $value)) {
            $this->_usedProperties['alwaysUseDefaultTargetPath'] = \true;
            $this->alwaysUseDefaultTargetPath = $value['always_use_default_target_path'];
            unset($value['always_use_default_target_path']);
        }
        if (array_key_exists('default_target_path', $value)) {
            $this->_usedProperties['defaultTargetPath'] = \true;
            $this->defaultTargetPath = $value['default_target_path'];
            unset($value['default_target_path']);
        }
        if (array_key_exists('target_path_parameter', $value)) {
            $this->_usedProperties['targetPathParameter'] = \true;
            $this->targetPathParameter = $value['target_path_parameter'];
            unset($value['target_path_parameter']);
        }
        if (array_key_exists('use_referer', $value)) {
            $this->_usedProperties['useReferer'] = \true;
            $this->useReferer = $value['use_referer'];
            unset($value['use_referer']);
        }
        if (array_key_exists('failure_path', $value)) {
            $this->_usedProperties['failurePath'] = \true;
            $this->failurePath = $value['failure_path'];
            unset($value['failure_path']);
        }
        if (array_key_exists('failure_forward', $value)) {
            $this->_usedProperties['failureForward'] = \true;
            $this->failureForward = $value['failure_forward'];
            unset($value['failure_forward']);
        }
        if (array_key_exists('failure_path_parameter', $value)) {
            $this->_usedProperties['failurePathParameter'] = \true;
            $this->failurePathParameter = $value['failure_path_parameter'];
            unset($value['failure_path_parameter']);
        }
        if (array_key_exists('csrf_token_generator', $value)) {
            $this->_usedProperties['csrfTokenGenerator'] = \true;
            $this->csrfTokenGenerator = $value['csrf_token_generator'];
            unset($value['csrf_token_generator']);
        }
        if (array_key_exists('service', $value)) {
            $this->_usedProperties['service'] = \true;
            $this->service = $value['service'];
            unset($value['service']);
        }
        if (array_key_exists('dn_string', $value)) {
            $this->_usedProperties['dnString'] = \true;
            $this->dnString = $value['dn_string'];
            unset($value['dn_string']);
        }
        if (array_key_exists('query_string', $value)) {
            $this->_usedProperties['queryString'] = \true;
            $this->queryString = $value['query_string'];
            unset($value['query_string']);
        }
        if (array_key_exists('search_dn', $value)) {
            $this->_usedProperties['searchDn'] = \true;
            $this->searchDn = $value['search_dn'];
            unset($value['search_dn']);
        }
        if (array_key_exists('search_password', $value)) {
            $this->_usedProperties['searchPassword'] = \true;
            $this->searchPassword = $value['search_password'];
            unset($value['search_password']);
        }
        if ([] !== $value) {
            throw new InvalidConfigurationException(sprintf('The following keys are not supported by "%s": ', __CLASS__) . implode(', ', array_keys($value)));
        }
    }
    public function toArray(): array
    {
        $output = [];
        if (isset($this->_usedProperties['provider'])) {
            $output['provider'] = $this->provider;
        }
        if (isset($this->_usedProperties['rememberMe'])) {
            $output['remember_me'] = $this->rememberMe;
        }
        if (isset($this->_usedProperties['successHandler'])) {
            $output['success_handler'] = $this->successHandler;
        }
        if (isset($this->_usedProperties['failureHandler'])) {
            $output['failure_handler'] = $this->failureHandler;
        }
        if (isset($this->_usedProperties['checkPath'])) {
            $output['check_path'] = $this->checkPath;
        }
        if (isset($this->_usedProperties['useForward'])) {
            $output['use_forward'] = $this->useForward;
        }
        if (isset($this->_usedProperties['requirePreviousSession'])) {
            $output['require_previous_session'] = $this->requirePreviousSession;
        }
        if (isset($this->_usedProperties['loginPath'])) {
            $output['login_path'] = $this->loginPath;
        }
        if (isset($this->_usedProperties['usernameParameter'])) {
            $output['username_parameter'] = $this->usernameParameter;
        }
        if (isset($this->_usedProperties['passwordParameter'])) {
            $output['password_parameter'] = $this->passwordParameter;
        }
        if (isset($this->_usedProperties['csrfParameter'])) {
            $output['csrf_parameter'] = $this->csrfParameter;
        }
        if (isset($this->_usedProperties['csrfTokenId'])) {
            $output['csrf_token_id'] = $this->csrfTokenId;
        }
        if (isset($this->_usedProperties['enableCsrf'])) {
            $output['enable_csrf'] = $this->enableCsrf;
        }
        if (isset($this->_usedProperties['postOnly'])) {
            $output['post_only'] = $this->postOnly;
        }
        if (isset($this->_usedProperties['formOnly'])) {
            $output['form_only'] = $this->formOnly;
        }
        if (isset($this->_usedProperties['alwaysUseDefaultTargetPath'])) {
            $output['always_use_default_target_path'] = $this->alwaysUseDefaultTargetPath;
        }
        if (isset($this->_usedProperties['defaultTargetPath'])) {
            $output['default_target_path'] = $this->defaultTargetPath;
        }
        if (isset($this->_usedProperties['targetPathParameter'])) {
            $output['target_path_parameter'] = $this->targetPathParameter;
        }
        if (isset($this->_usedProperties['useReferer'])) {
            $output['use_referer'] = $this->useReferer;
        }
        if (isset($this->_usedProperties['failurePath'])) {
            $output['failure_path'] = $this->failurePath;
        }
        if (isset($this->_usedProperties['failureForward'])) {
            $output['failure_forward'] = $this->failureForward;
        }
        if (isset($this->_usedProperties['failurePathParameter'])) {
            $output['failure_path_parameter'] = $this->failurePathParameter;
        }
        if (isset($this->_usedProperties['csrfTokenGenerator'])) {
            $output['csrf_token_generator'] = $this->csrfTokenGenerator;
        }
        if (isset($this->_usedProperties['service'])) {
            $output['service'] = $this->service;
        }
        if (isset($this->_usedProperties['dnString'])) {
            $output['dn_string'] = $this->dnString;
        }
        if (isset($this->_usedProperties['queryString'])) {
            $output['query_string'] = $this->queryString;
        }
        if (isset($this->_usedProperties['searchDn'])) {
            $output['search_dn'] = $this->searchDn;
        }
        if (isset($this->_usedProperties['searchPassword'])) {
            $output['search_password'] = $this->searchPassword;
        }
        return $output;
    }
}
<?php

namespace _ContaoManager\Symfony\Config\Security\FirewallConfig;

use _ContaoManager\Symfony\Component\Config\Loader\ParamConfigurator;
use _ContaoManager\Symfony\Component\Config\Definition\Exception\InvalidConfigurationException;
/**
 * This class is automatically generated to help in creating a config.
 */
class HttpBasicLdapConfig
{
    private $provider;
    private $realm;
    private $service;
    private $dnString;
    private $queryString;
    private $searchDn;
    private $searchPassword;
    private $_usedProperties = [];
    /**
     * @default null
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function provider($value): static
    {
        $this->_usedProperties['provider'] = \true;
        $this->provider = $value;
        return $this;
    }
    /**
     * @default 'Secured Area'
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function realm($value): static
    {
        $this->_usedProperties['realm'] = \true;
        $this->realm = $value;
        return $this;
    }
    /**
     * @default 'ldap'
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function service($value): static
    {
        $this->_usedProperties['service'] = \true;
        $this->service = $value;
        return $this;
    }
    /**
     * @default '{username}'
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function dnString($value): static
    {
        $this->_usedProperties['dnString'] = \true;
        $this->dnString = $value;
        return $this;
    }
    /**
     * @default null
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function queryString($value): static
    {
        $this->_usedProperties['queryString'] = \true;
        $this->queryString = $value;
        return $this;
    }
    /**
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function searchDn($value): static
    {
        $this->_usedProperties['searchDn'] = \true;
        $this->searchDn = $value;
        return $this;
    }
    /**
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function searchPassword($value): static
    {
        $this->_usedProperties['searchPassword'] = \true;
        $this->searchPassword = $value;
        return $this;
    }
    public function __construct(array $value = [])
    {
        if (array_key_exists('provider', $value)) {
            $this->_usedProperties['provider'] = \true;
            $this->provider = $value['provider'];
            unset($value['provider']);
        }
        if (array_key_exists('realm', $value)) {
            $this->_usedProperties['realm'] = \true;
            $this->realm = $value['realm'];
            unset($value['realm']);
        }
        if (array_key_exists('service', $value)) {
            $this->_usedProperties['service'] = \true;
            $this->service = $value['service'];
            unset($value['service']);
        }
        if (array_key_exists('dn_string', $value)) {
            $this->_usedProperties['dnString'] = \true;
            $this->dnString = $value['dn_string'];
            unset($value['dn_string']);
        }
        if (array_key_exists('query_string', $value)) {
            $this->_usedProperties['queryString'] = \true;
            $this->queryString = $value['query_string'];
            unset($value['query_string']);
        }
        if (array_key_exists('search_dn', $value)) {
            $this->_usedProperties['searchDn'] = \true;
            $this->searchDn = $value['search_dn'];
            unset($value['search_dn']);
        }
        if (array_key_exists('search_password', $value)) {
            $this->_usedProperties['searchPassword'] = \true;
            $this->searchPassword = $value['search_password'];
            unset($value['search_password']);
        }
        if ([] !== $value) {
            throw new InvalidConfigurationException(sprintf('The following keys are not supported by "%s": ', __CLASS__) . implode(', ', array_keys($value)));
        }
    }
    public function toArray(): array
    {
        $output = [];
        if (isset($this->_usedProperties['provider'])) {
            $output['provider'] = $this->provider;
        }
        if (isset($this->_usedProperties['realm'])) {
            $output['realm'] = $this->realm;
        }
        if (isset($this->_usedProperties['service'])) {
            $output['service'] = $this->service;
        }
        if (isset($this->_usedProperties['dnString'])) {
            $output['dn_string'] = $this->dnString;
        }
        if (isset($this->_usedProperties['queryString'])) {
            $output['query_string'] = $this->queryString;
        }
        if (isset($this->_usedProperties['searchDn'])) {
            $output['search_dn'] = $this->searchDn;
        }
        if (isset($this->_usedProperties['searchPassword'])) {
            $output['search_password'] = $this->searchPassword;
        }
        return $output;
    }
}
<?php

namespace _ContaoManager\Symfony\Config\Security\FirewallConfig;

use _ContaoManager\Symfony\Component\Config\Loader\ParamConfigurator;
use _ContaoManager\Symfony\Component\Config\Definition\Exception\InvalidConfigurationException;
/**
 * This class is automatically generated to help in creating a config.
 */
class X509Config
{
    private $provider;
    private $user;
    private $credentials;
    private $userIdentifier;
    private $_usedProperties = [];
    /**
     * @default null
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function provider($value): static
    {
        $this->_usedProperties['provider'] = \true;
        $this->provider = $value;
        return $this;
    }
    /**
     * @default 'SSL_CLIENT_S_DN_Email'
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function user($value): static
    {
        $this->_usedProperties['user'] = \true;
        $this->user = $value;
        return $this;
    }
    /**
     * @default 'SSL_CLIENT_S_DN'
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function credentials($value): static
    {
        $this->_usedProperties['credentials'] = \true;
        $this->credentials = $value;
        return $this;
    }
    /**
     * @default 'emailAddress'
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function userIdentifier($value): static
    {
        $this->_usedProperties['userIdentifier'] = \true;
        $this->userIdentifier = $value;
        return $this;
    }
    public function __construct(array $value = [])
    {
        if (array_key_exists('provider', $value)) {
            $this->_usedProperties['provider'] = \true;
            $this->provider = $value['provider'];
            unset($value['provider']);
        }
        if (array_key_exists('user', $value)) {
            $this->_usedProperties['user'] = \true;
            $this->user = $value['user'];
            unset($value['user']);
        }
        if (array_key_exists('credentials', $value)) {
            $this->_usedProperties['credentials'] = \true;
            $this->credentials = $value['credentials'];
            unset($value['credentials']);
        }
        if (array_key_exists('user_identifier', $value)) {
            $this->_usedProperties['userIdentifier'] = \true;
            $this->userIdentifier = $value['user_identifier'];
            unset($value['user_identifier']);
        }
        if ([] !== $value) {
            throw new InvalidConfigurationException(sprintf('The following keys are not supported by "%s": ', __CLASS__) . implode(', ', array_keys($value)));
        }
    }
    public function toArray(): array
    {
        $output = [];
        if (isset($this->_usedProperties['provider'])) {
            $output['provider'] = $this->provider;
        }
        if (isset($this->_usedProperties['user'])) {
            $output['user'] = $this->user;
        }
        if (isset($this->_usedProperties['credentials'])) {
            $output['credentials'] = $this->credentials;
        }
        if (isset($this->_usedProperties['userIdentifier'])) {
            $output['user_identifier'] = $this->userIdentifier;
        }
        return $output;
    }
}
<?php

namespace _ContaoManager\Symfony\Config\Security\FirewallConfig;

use _ContaoManager\Symfony\Component\Config\Loader\ParamConfigurator;
use _ContaoManager\Symfony\Component\Config\Definition\Exception\InvalidConfigurationException;
/**
 * This class is automatically generated to help in creating a config.
 */
class RemoteUserConfig
{
    private $provider;
    private $user;
    private $_usedProperties = [];
    /**
     * @default null
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function provider($value): static
    {
        $this->_usedProperties['provider'] = \true;
        $this->provider = $value;
        return $this;
    }
    /**
     * @default 'REMOTE_USER'
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function user($value): static
    {
        $this->_usedProperties['user'] = \true;
        $this->user = $value;
        return $this;
    }
    public function __construct(array $value = [])
    {
        if (array_key_exists('provider', $value)) {
            $this->_usedProperties['provider'] = \true;
            $this->provider = $value['provider'];
            unset($value['provider']);
        }
        if (array_key_exists('user', $value)) {
            $this->_usedProperties['user'] = \true;
            $this->user = $value['user'];
            unset($value['user']);
        }
        if ([] !== $value) {
            throw new InvalidConfigurationException(sprintf('The following keys are not supported by "%s": ', __CLASS__) . implode(', ', array_keys($value)));
        }
    }
    public function toArray(): array
    {
        $output = [];
        if (isset($this->_usedProperties['provider'])) {
            $output['provider'] = $this->provider;
        }
        if (isset($this->_usedProperties['user'])) {
            $output['user'] = $this->user;
        }
        return $output;
    }
}
<?php

namespace _ContaoManager\Symfony\Config\Security\FirewallConfig;

require_once __DIR__ . \DIRECTORY_SEPARATOR . 'Logout' . \DIRECTORY_SEPARATOR . 'DeleteCookieConfig.php';
use _ContaoManager\Symfony\Component\Config\Loader\ParamConfigurator;
use _ContaoManager\Symfony\Component\Config\Definition\Exception\InvalidConfigurationException;
/**
 * This class is automatically generated to help in creating a config.
 */
class LogoutConfig
{
    private $enableCsrf;
    private $csrfTokenId;
    private $csrfParameter;
    private $csrfTokenGenerator;
    private $csrfTokenManager;
    private $path;
    private $target;
    private $invalidateSession;
    private $clearSiteData;
    private $deleteCookies;
    private $_usedProperties = [];
    /**
     * @default null
     * @param ParamConfigurator|bool $value
     * @return $this
     */
    public function enableCsrf($value): static
    {
        $this->_usedProperties['enableCsrf'] = \true;
        $this->enableCsrf = $value;
        return $this;
    }
    /**
     * @default 'logout'
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function csrfTokenId($value): static
    {
        $this->_usedProperties['csrfTokenId'] = \true;
        $this->csrfTokenId = $value;
        return $this;
    }
    /**
     * @default '_csrf_token'
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function csrfParameter($value): static
    {
        $this->_usedProperties['csrfParameter'] = \true;
        $this->csrfParameter = $value;
        return $this;
    }
    /**
     * @default null
     * @param ParamConfigurator|mixed $value
     * @deprecated The "csrf_token_generator" option is deprecated. Use "csrf_token_manager" instead.
     * @return $this
     */
    public function csrfTokenGenerator($value): static
    {
        $this->_usedProperties['csrfTokenGenerator'] = \true;
        $this->csrfTokenGenerator = $value;
        return $this;
    }
    /**
     * @default null
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function csrfTokenManager($value): static
    {
        $this->_usedProperties['csrfTokenManager'] = \true;
        $this->csrfTokenManager = $value;
        return $this;
    }
    /**
     * @default '/logout'
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function path($value): static
    {
        $this->_usedProperties['path'] = \true;
        $this->path = $value;
        return $this;
    }
    /**
     * @default '/'
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function target($value): static
    {
        $this->_usedProperties['target'] = \true;
        $this->target = $value;
        return $this;
    }
    /**
     * @default true
     * @param ParamConfigurator|bool $value
     * @return $this
     */
    public function invalidateSession($value): static
    {
        $this->_usedProperties['invalidateSession'] = \true;
        $this->invalidateSession = $value;
        return $this;
    }
    /**
     * @param ParamConfigurator|list<ParamConfigurator|mixed>|string $value
     *
     * @return $this
     */
    public function clearSiteData(ParamConfigurator|string|array $value): static
    {
        $this->_usedProperties['clearSiteData'] = \true;
        $this->clearSiteData = $value;
        return $this;
    }
    public function deleteCookie(string $name, array $value = []): \_ContaoManager\Symfony\Config\Security\FirewallConfig\Logout\DeleteCookieConfig
    {
        if (!isset($this->deleteCookies[$name])) {
            $this->_usedProperties['deleteCookies'] = \true;
            $this->deleteCookies[$name] = new \_ContaoManager\Symfony\Config\Security\FirewallConfig\Logout\DeleteCookieConfig($value);
        } elseif (1 < \func_num_args()) {
            throw new InvalidConfigurationException('The node created by "deleteCookie()" has already been initialized. You cannot pass values the second time you call deleteCookie().');
        }
        return $this->deleteCookies[$name];
    }
    public function __construct(array $value = [])
    {
        if (array_key_exists('enable_csrf', $value)) {
            $this->_usedProperties['enableCsrf'] = \true;
            $this->enableCsrf = $value['enable_csrf'];
            unset($value['enable_csrf']);
        }
        if (array_key_exists('csrf_token_id', $value)) {
            $this->_usedProperties['csrfTokenId'] = \true;
            $this->csrfTokenId = $value['csrf_token_id'];
            unset($value['csrf_token_id']);
        }
        if (array_key_exists('csrf_parameter', $value)) {
            $this->_usedProperties['csrfParameter'] = \true;
            $this->csrfParameter = $value['csrf_parameter'];
            unset($value['csrf_parameter']);
        }
        if (array_key_exists('csrf_token_generator', $value)) {
            $this->_usedProperties['csrfTokenGenerator'] = \true;
            $this->csrfTokenGenerator = $value['csrf_token_generator'];
            unset($value['csrf_token_generator']);
        }
        if (array_key_exists('csrf_token_manager', $value)) {
            $this->_usedProperties['csrfTokenManager'] = \true;
            $this->csrfTokenManager = $value['csrf_token_manager'];
            unset($value['csrf_token_manager']);
        }
        if (array_key_exists('path', $value)) {
            $this->_usedProperties['path'] = \true;
            $this->path = $value['path'];
            unset($value['path']);
        }
        if (array_key_exists('target', $value)) {
            $this->_usedProperties['target'] = \true;
            $this->target = $value['target'];
            unset($value['target']);
        }
        if (array_key_exists('invalidate_session', $value)) {
            $this->_usedProperties['invalidateSession'] = \true;
            $this->invalidateSession = $value['invalidate_session'];
            unset($value['invalidate_session']);
        }
        if (array_key_exists('clear_site_data', $value)) {
            $this->_usedProperties['clearSiteData'] = \true;
            $this->clearSiteData = $value['clear_site_data'];
            unset($value['clear_site_data']);
        }
        if (array_key_exists('delete_cookies', $value)) {
            $this->_usedProperties['deleteCookies'] = \true;
            $this->deleteCookies = array_map(fn($v) => \is_array($v) ? new \_ContaoManager\Symfony\Config\Security\FirewallConfig\Logout\DeleteCookieConfig($v) : $v, $value['delete_cookies']);
            unset($value['delete_cookies']);
        }
        if ([] !== $value) {
            throw new InvalidConfigurationException(sprintf('The following keys are not supported by "%s": ', __CLASS__) . implode(', ', array_keys($value)));
        }
    }
    public function toArray(): array
    {
        $output = [];
        if (isset($this->_usedProperties['enableCsrf'])) {
            $output['enable_csrf'] = $this->enableCsrf;
        }
        if (isset($this->_usedProperties['csrfTokenId'])) {
            $output['csrf_token_id'] = $this->csrfTokenId;
        }
        if (isset($this->_usedProperties['csrfParameter'])) {
            $output['csrf_parameter'] = $this->csrfParameter;
        }
        if (isset($this->_usedProperties['csrfTokenGenerator'])) {
            $output['csrf_token_generator'] = $this->csrfTokenGenerator;
        }
        if (isset($this->_usedProperties['csrfTokenManager'])) {
            $output['csrf_token_manager'] = $this->csrfTokenManager;
        }
        if (isset($this->_usedProperties['path'])) {
            $output['path'] = $this->path;
        }
        if (isset($this->_usedProperties['target'])) {
            $output['target'] = $this->target;
        }
        if (isset($this->_usedProperties['invalidateSession'])) {
            $output['invalidate_session'] = $this->invalidateSession;
        }
        if (isset($this->_usedProperties['clearSiteData'])) {
            $output['clear_site_data'] = $this->clearSiteData;
        }
        if (isset($this->_usedProperties['deleteCookies'])) {
            $output['delete_cookies'] = array_map(fn($v) => $v instanceof \_ContaoManager\Symfony\Config\Security\FirewallConfig\Logout\DeleteCookieConfig ? $v->toArray() : $v, $this->deleteCookies);
        }
        return $output;
    }
}
<?php

namespace _ContaoManager\Symfony\Config\Security;

use _ContaoManager\Symfony\Component\Config\Loader\ParamConfigurator;
use _ContaoManager\Symfony\Component\Config\Definition\Exception\InvalidConfigurationException;
/**
 * This class is automatically generated to help in creating a config.
 */
class AccessDecisionManagerConfig
{
    private $strategy;
    private $service;
    private $strategyService;
    private $allowIfAllAbstain;
    private $allowIfEqualGrantedDenied;
    private $_usedProperties = [];
    /**
     * @default null
     * @param ParamConfigurator|'affirmative'|'consensus'|'unanimous'|'priority' $value
     * @return $this
     */
    public function strategy($value): static
    {
        $this->_usedProperties['strategy'] = \true;
        $this->strategy = $value;
        return $this;
    }
    /**
     * @default null
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function service($value): static
    {
        $this->_usedProperties['service'] = \true;
        $this->service = $value;
        return $this;
    }
    /**
     * @default null
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function strategyService($value): static
    {
        $this->_usedProperties['strategyService'] = \true;
        $this->strategyService = $value;
        return $this;
    }
    /**
     * @default false
     * @param ParamConfigurator|bool $value
     * @return $this
     */
    public function allowIfAllAbstain($value): static
    {
        $this->_usedProperties['allowIfAllAbstain'] = \true;
        $this->allowIfAllAbstain = $value;
        return $this;
    }
    /**
     * @default true
     * @param ParamConfigurator|bool $value
     * @return $this
     */
    public function allowIfEqualGrantedDenied($value): static
    {
        $this->_usedProperties['allowIfEqualGrantedDenied'] = \true;
        $this->allowIfEqualGrantedDenied = $value;
        return $this;
    }
    public function __construct(array $value = [])
    {
        if (array_key_exists('strategy', $value)) {
            $this->_usedProperties['strategy'] = \true;
            $this->strategy = $value['strategy'];
            unset($value['strategy']);
        }
        if (array_key_exists('service', $value)) {
            $this->_usedProperties['service'] = \true;
            $this->service = $value['service'];
            unset($value['service']);
        }
        if (array_key_exists('strategy_service', $value)) {
            $this->_usedProperties['strategyService'] = \true;
            $this->strategyService = $value['strategy_service'];
            unset($value['strategy_service']);
        }
        if (array_key_exists('allow_if_all_abstain', $value)) {
            $this->_usedProperties['allowIfAllAbstain'] = \true;
            $this->allowIfAllAbstain = $value['allow_if_all_abstain'];
            unset($value['allow_if_all_abstain']);
        }
        if (array_key_exists('allow_if_equal_granted_denied', $value)) {
            $this->_usedProperties['allowIfEqualGrantedDenied'] = \true;
            $this->allowIfEqualGrantedDenied = $value['allow_if_equal_granted_denied'];
            unset($value['allow_if_equal_granted_denied']);
        }
        if ([] !== $value) {
            throw new InvalidConfigurationException(sprintf('The following keys are not supported by "%s": ', __CLASS__) . implode(', ', array_keys($value)));
        }
    }
    public function toArray(): array
    {
        $output = [];
        if (isset($this->_usedProperties['strategy'])) {
            $output['strategy'] = $this->strategy;
        }
        if (isset($this->_usedProperties['service'])) {
            $output['service'] = $this->service;
        }
        if (isset($this->_usedProperties['strategyService'])) {
            $output['strategy_service'] = $this->strategyService;
        }
        if (isset($this->_usedProperties['allowIfAllAbstain'])) {
            $output['allow_if_all_abstain'] = $this->allowIfAllAbstain;
        }
        if (isset($this->_usedProperties['allowIfEqualGrantedDenied'])) {
            $output['allow_if_equal_granted_denied'] = $this->allowIfEqualGrantedDenied;
        }
        return $output;
    }
}
<?php

namespace _ContaoManager\Symfony\Config\Security;

use _ContaoManager\Symfony\Component\Config\Loader\ParamConfigurator;
use _ContaoManager\Symfony\Component\Config\Definition\Exception\InvalidConfigurationException;
/**
 * This class is automatically generated to help in creating a config.
 */
class AccessControlConfig
{
    private $requestMatcher;
    private $requiresChannel;
    private $path;
    private $host;
    private $port;
    private $ips;
    private $attributes;
    private $route;
    private $methods;
    private $allowIf;
    private $roles;
    private $_usedProperties = [];
    /**
     * @default null
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function requestMatcher($value): static
    {
        $this->_usedProperties['requestMatcher'] = \true;
        $this->requestMatcher = $value;
        return $this;
    }
    /**
     * @default null
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function requiresChannel($value): static
    {
        $this->_usedProperties['requiresChannel'] = \true;
        $this->requiresChannel = $value;
        return $this;
    }
    /**
     * use the urldecoded format
     * @example ^/path to resource/
     * @default null
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function path($value): static
    {
        $this->_usedProperties['path'] = \true;
        $this->path = $value;
        return $this;
    }
    /**
     * @default null
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function host($value): static
    {
        $this->_usedProperties['host'] = \true;
        $this->host = $value;
        return $this;
    }
    /**
     * @default null
     * @param ParamConfigurator|int $value
     * @return $this
     */
    public function port($value): static
    {
        $this->_usedProperties['port'] = \true;
        $this->port = $value;
        return $this;
    }
    /**
     * @param ParamConfigurator|list<ParamConfigurator|mixed>|string $value
     *
     * @return $this
     */
    public function ips(ParamConfigurator|string|array $value): static
    {
        $this->_usedProperties['ips'] = \true;
        $this->ips = $value;
        return $this;
    }
    /**
     * @return $this
     */
    public function attribute(string $key, mixed $value): static
    {
        $this->_usedProperties['attributes'] = \true;
        $this->attributes[$key] = $value;
        return $this;
    }
    /**
     * @default null
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function route($value): static
    {
        $this->_usedProperties['route'] = \true;
        $this->route = $value;
        return $this;
    }
    /**
     * @param ParamConfigurator|list<ParamConfigurator|mixed>|string $value
     *
     * @return $this
     */
    public function methods(ParamConfigurator|string|array $value): static
    {
        $this->_usedProperties['methods'] = \true;
        $this->methods = $value;
        return $this;
    }
    /**
     * @default null
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function allowIf($value): static
    {
        $this->_usedProperties['allowIf'] = \true;
        $this->allowIf = $value;
        return $this;
    }
    /**
     * @param ParamConfigurator|list<ParamConfigurator|mixed>|string $value
     *
     * @return $this
     */
    public function roles(ParamConfigurator|string|array $value): static
    {
        $this->_usedProperties['roles'] = \true;
        $this->roles = $value;
        return $this;
    }
    public function __construct(array $value = [])
    {
        if (array_key_exists('request_matcher', $value)) {
            $this->_usedProperties['requestMatcher'] = \true;
            $this->requestMatcher = $value['request_matcher'];
            unset($value['request_matcher']);
        }
        if (array_key_exists('requires_channel', $value)) {
            $this->_usedProperties['requiresChannel'] = \true;
            $this->requiresChannel = $value['requires_channel'];
            unset($value['requires_channel']);
        }
        if (array_key_exists('path', $value)) {
            $this->_usedProperties['path'] = \true;
            $this->path = $value['path'];
            unset($value['path']);
        }
        if (array_key_exists('host', $value)) {
            $this->_usedProperties['host'] = \true;
            $this->host = $value['host'];
            unset($value['host']);
        }
        if (array_key_exists('port', $value)) {
            $this->_usedProperties['port'] = \true;
            $this->port = $value['port'];
            unset($value['port']);
        }
        if (array_key_exists('ips', $value)) {
            $this->_usedProperties['ips'] = \true;
            $this->ips = $value['ips'];
            unset($value['ips']);
        }
        if (array_key_exists('attributes', $value)) {
            $this->_usedProperties['attributes'] = \true;
            $this->attributes = $value['attributes'];
            unset($value['attributes']);
        }
        if (array_key_exists('route', $value)) {
            $this->_usedProperties['route'] = \true;
            $this->route = $value['route'];
            unset($value['route']);
        }
        if (array_key_exists('methods', $value)) {
            $this->_usedProperties['methods'] = \true;
            $this->methods = $value['methods'];
            unset($value['methods']);
        }
        if (array_key_exists('allow_if', $value)) {
            $this->_usedProperties['allowIf'] = \true;
            $this->allowIf = $value['allow_if'];
            unset($value['allow_if']);
        }
        if (array_key_exists('roles', $value)) {
            $this->_usedProperties['roles'] = \true;
            $this->roles = $value['roles'];
            unset($value['roles']);
        }
        if ([] !== $value) {
            throw new InvalidConfigurationException(sprintf('The following keys are not supported by "%s": ', __CLASS__) . implode(', ', array_keys($value)));
        }
    }
    public function toArray(): array
    {
        $output = [];
        if (isset($this->_usedProperties['requestMatcher'])) {
            $output['request_matcher'] = $this->requestMatcher;
        }
        if (isset($this->_usedProperties['requiresChannel'])) {
            $output['requires_channel'] = $this->requiresChannel;
        }
        if (isset($this->_usedProperties['path'])) {
            $output['path'] = $this->path;
        }
        if (isset($this->_usedProperties['host'])) {
            $output['host'] = $this->host;
        }
        if (isset($this->_usedProperties['port'])) {
            $output['port'] = $this->port;
        }
        if (isset($this->_usedProperties['ips'])) {
            $output['ips'] = $this->ips;
        }
        if (isset($this->_usedProperties['attributes'])) {
            $output['attributes'] = $this->attributes;
        }
        if (isset($this->_usedProperties['route'])) {
            $output['route'] = $this->route;
        }
        if (isset($this->_usedProperties['methods'])) {
            $output['methods'] = $this->methods;
        }
        if (isset($this->_usedProperties['allowIf'])) {
            $output['allow_if'] = $this->allowIf;
        }
        if (isset($this->_usedProperties['roles'])) {
            $output['roles'] = $this->roles;
        }
        return $output;
    }
}
<?php

namespace _ContaoManager\Symfony\Config;

require_once __DIR__ . \DIRECTORY_SEPARATOR . 'Security' . \DIRECTORY_SEPARATOR . 'AccessDecisionManagerConfig.php';
require_once __DIR__ . \DIRECTORY_SEPARATOR . 'Security' . \DIRECTORY_SEPARATOR . 'PasswordHasherConfig.php';
require_once __DIR__ . \DIRECTORY_SEPARATOR . 'Security' . \DIRECTORY_SEPARATOR . 'ProviderConfig.php';
require_once __DIR__ . \DIRECTORY_SEPARATOR . 'Security' . \DIRECTORY_SEPARATOR . 'FirewallConfig.php';
require_once __DIR__ . \DIRECTORY_SEPARATOR . 'Security' . \DIRECTORY_SEPARATOR . 'AccessControlConfig.php';
use _ContaoManager\Symfony\Component\Config\Loader\ParamConfigurator;
use _ContaoManager\Symfony\Component\Config\Definition\Exception\InvalidConfigurationException;
/**
 * This class is automatically generated to help in creating a config.
 */
class SecurityConfig implements \_ContaoManager\Symfony\Component\Config\Builder\ConfigBuilderInterface
{
    private $accessDeniedUrl;
    private $sessionFixationStrategy;
    private $hideUserNotFound;
    private $eraseCredentials;
    private $enableAuthenticatorManager;
    private $accessDecisionManager;
    private $passwordHashers;
    private $providers;
    private $firewalls;
    private $accessControl;
    private $roleHierarchy;
    private $_usedProperties = [];
    /**
     * @example /foo/error403
     * @default null
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function accessDeniedUrl($value): static
    {
        $this->_usedProperties['accessDeniedUrl'] = \true;
        $this->accessDeniedUrl = $value;
        return $this;
    }
    /**
     * @default 'migrate'
     * @param ParamConfigurator|'none'|'migrate'|'invalidate' $value
     * @return $this
     */
    public function sessionFixationStrategy($value): static
    {
        $this->_usedProperties['sessionFixationStrategy'] = \true;
        $this->sessionFixationStrategy = $value;
        return $this;
    }
    /**
     * @default true
     * @param ParamConfigurator|bool $value
     * @return $this
     */
    public function hideUserNotFound($value): static
    {
        $this->_usedProperties['hideUserNotFound'] = \true;
        $this->hideUserNotFound = $value;
        return $this;
    }
    /**
     * @default true
     * @param ParamConfigurator|bool $value
     * @return $this
     */
    public function eraseCredentials($value): static
    {
        $this->_usedProperties['eraseCredentials'] = \true;
        $this->eraseCredentials = $value;
        return $this;
    }
    /**
     * @default true
     * @param ParamConfigurator|bool $value
     * @deprecated The "enable_authenticator_manager" option at "security" is deprecated.
     * @return $this
     */
    public function enableAuthenticatorManager($value): static
    {
        $this->_usedProperties['enableAuthenticatorManager'] = \true;
        $this->enableAuthenticatorManager = $value;
        return $this;
    }
    /**
     * @default {"allow_if_all_abstain":false,"allow_if_equal_granted_denied":true}
     */
    public function accessDecisionManager(array $value = []): \_ContaoManager\Symfony\Config\Security\AccessDecisionManagerConfig
    {
        if (null === $this->accessDecisionManager) {
            $this->_usedProperties['accessDecisionManager'] = \true;
            $this->accessDecisionManager = new \_ContaoManager\Symfony\Config\Security\AccessDecisionManagerConfig($value);
        } elseif (0 < \func_num_args()) {
            throw new InvalidConfigurationException('The node created by "accessDecisionManager()" has already been initialized. You cannot pass values the second time you call accessDecisionManager().');
        }
        return $this->accessDecisionManager;
    }
    /**
     * @template TValue of string|array
     * @param TValue $value
     * @example "auto"
     * @example {"algorithm":"auto","time_cost":8,"cost":13}
     * @return \Symfony\Config\Security\PasswordHasherConfig|$this
     * @psalm-return (TValue is array ? \Symfony\Config\Security\PasswordHasherConfig : static)
     */
    public function passwordHasher(string $class, string|array $value = []): \_ContaoManager\Symfony\Config\Security\PasswordHasherConfig|static
    {
        if (!\is_array($value)) {
            $this->_usedProperties['passwordHashers'] = \true;
            $this->passwordHashers[$class] = $value;
            return $this;
        }
        if (!isset($this->passwordHashers[$class]) || !$this->passwordHashers[$class] instanceof \_ContaoManager\Symfony\Config\Security\PasswordHasherConfig) {
            $this->_usedProperties['passwordHashers'] = \true;
            $this->passwordHashers[$class] = new \_ContaoManager\Symfony\Config\Security\PasswordHasherConfig($value);
        } elseif (1 < \func_num_args()) {
            throw new InvalidConfigurationException('The node created by "passwordHasher()" has already been initialized. You cannot pass values the second time you call passwordHasher().');
        }
        return $this->passwordHashers[$class];
    }
    /**
     * @example {"memory":{"users":{"foo":{"password":"foo","roles":"ROLE_USER"},"bar":{"password":"bar","roles":"[ROLE_USER, ROLE_ADMIN]"}}}}
     * @example {"entity":{"class":"SecurityBundle:User","property":"username"}}
     */
    public function provider(string $name, array $value = []): \_ContaoManager\Symfony\Config\Security\ProviderConfig
    {
        if (!isset($this->providers[$name])) {
            $this->_usedProperties['providers'] = \true;
            $this->providers[$name] = new \_ContaoManager\Symfony\Config\Security\ProviderConfig($value);
        } elseif (1 < \func_num_args()) {
            throw new InvalidConfigurationException('The node created by "provider()" has already been initialized. You cannot pass values the second time you call provider().');
        }
        return $this->providers[$name];
    }
    public function firewall(string $name, array $value = []): \_ContaoManager\Symfony\Config\Security\FirewallConfig
    {
        if (!isset($this->firewalls[$name])) {
            $this->_usedProperties['firewalls'] = \true;
            $this->firewalls[$name] = new \_ContaoManager\Symfony\Config\Security\FirewallConfig($value);
        } elseif (1 < \func_num_args()) {
            throw new InvalidConfigurationException('The node created by "firewall()" has already been initialized. You cannot pass values the second time you call firewall().');
        }
        return $this->firewalls[$name];
    }
    public function accessControl(array $value = []): \_ContaoManager\Symfony\Config\Security\AccessControlConfig
    {
        $this->_usedProperties['accessControl'] = \true;
        return $this->accessControl[] = new \_ContaoManager\Symfony\Config\Security\AccessControlConfig($value);
    }
    /**
     * @return $this
     */
    public function roleHierarchy(string $id, mixed $value): static
    {
        $this->_usedProperties['roleHierarchy'] = \true;
        $this->roleHierarchy[$id] = $value;
        return $this;
    }
    public function getExtensionAlias(): string
    {
        return 'security';
    }
    public function __construct(array $value = [])
    {
        if (array_key_exists('access_denied_url', $value)) {
            $this->_usedProperties['accessDeniedUrl'] = \true;
            $this->accessDeniedUrl = $value['access_denied_url'];
            unset($value['access_denied_url']);
        }
        if (array_key_exists('session_fixation_strategy', $value)) {
            $this->_usedProperties['sessionFixationStrategy'] = \true;
            $this->sessionFixationStrategy = $value['session_fixation_strategy'];
            unset($value['session_fixation_strategy']);
        }
        if (array_key_exists('hide_user_not_found', $value)) {
            $this->_usedProperties['hideUserNotFound'] = \true;
            $this->hideUserNotFound = $value['hide_user_not_found'];
            unset($value['hide_user_not_found']);
        }
        if (array_key_exists('erase_credentials', $value)) {
            $this->_usedProperties['eraseCredentials'] = \true;
            $this->eraseCredentials = $value['erase_credentials'];
            unset($value['erase_credentials']);
        }
        if (array_key_exists('enable_authenticator_manager', $value)) {
            $this->_usedProperties['enableAuthenticatorManager'] = \true;
            $this->enableAuthenticatorManager = $value['enable_authenticator_manager'];
            unset($value['enable_authenticator_manager']);
        }
        if (array_key_exists('access_decision_manager', $value)) {
            $this->_usedProperties['accessDecisionManager'] = \true;
            $this->accessDecisionManager = new \_ContaoManager\Symfony\Config\Security\AccessDecisionManagerConfig($value['access_decision_manager']);
            unset($value['access_decision_manager']);
        }
        if (array_key_exists('password_hashers', $value)) {
            $this->_usedProperties['passwordHashers'] = \true;
            $this->passwordHashers = array_map(fn($v) => \is_array($v) ? new \_ContaoManager\Symfony\Config\Security\PasswordHasherConfig($v) : $v, $value['password_hashers']);
            unset($value['password_hashers']);
        }
        if (array_key_exists('providers', $value)) {
            $this->_usedProperties['providers'] = \true;
            $this->providers = array_map(fn($v) => new \_ContaoManager\Symfony\Config\Security\ProviderConfig($v), $value['providers']);
            unset($value['providers']);
        }
        if (array_key_exists('firewalls', $value)) {
            $this->_usedProperties['firewalls'] = \true;
            $this->firewalls = array_map(fn($v) => new \_ContaoManager\Symfony\Config\Security\FirewallConfig($v), $value['firewalls']);
            unset($value['firewalls']);
        }
        if (array_key_exists('access_control', $value)) {
            $this->_usedProperties['accessControl'] = \true;
            $this->accessControl = array_map(fn($v) => new \_ContaoManager\Symfony\Config\Security\AccessControlConfig($v), $value['access_control']);
            unset($value['access_control']);
        }
        if (array_key_exists('role_hierarchy', $value)) {
            $this->_usedProperties['roleHierarchy'] = \true;
            $this->roleHierarchy = $value['role_hierarchy'];
            unset($value['role_hierarchy']);
        }
        if ([] !== $value) {
            throw new InvalidConfigurationException(sprintf('The following keys are not supported by "%s": ', __CLASS__) . implode(', ', array_keys($value)));
        }
    }
    public function toArray(): array
    {
        $output = [];
        if (isset($this->_usedProperties['accessDeniedUrl'])) {
            $output['access_denied_url'] = $this->accessDeniedUrl;
        }
        if (isset($this->_usedProperties['sessionFixationStrategy'])) {
            $output['session_fixation_strategy'] = $this->sessionFixationStrategy;
        }
        if (isset($this->_usedProperties['hideUserNotFound'])) {
            $output['hide_user_not_found'] = $this->hideUserNotFound;
        }
        if (isset($this->_usedProperties['eraseCredentials'])) {
            $output['erase_credentials'] = $this->eraseCredentials;
        }
        if (isset($this->_usedProperties['enableAuthenticatorManager'])) {
            $output['enable_authenticator_manager'] = $this->enableAuthenticatorManager;
        }
        if (isset($this->_usedProperties['accessDecisionManager'])) {
            $output['access_decision_manager'] = $this->accessDecisionManager->toArray();
        }
        if (isset($this->_usedProperties['passwordHashers'])) {
            $output['password_hashers'] = array_map(fn($v) => $v instanceof \_ContaoManager\Symfony\Config\Security\PasswordHasherConfig ? $v->toArray() : $v, $this->passwordHashers);
        }
        if (isset($this->_usedProperties['providers'])) {
            $output['providers'] = array_map(fn($v) => $v->toArray(), $this->providers);
        }
        if (isset($this->_usedProperties['firewalls'])) {
            $output['firewalls'] = array_map(fn($v) => $v->toArray(), $this->firewalls);
        }
        if (isset($this->_usedProperties['accessControl'])) {
            $output['access_control'] = array_map(fn($v) => $v->toArray(), $this->accessControl);
        }
        if (isset($this->_usedProperties['roleHierarchy'])) {
            $output['role_hierarchy'] = $this->roleHierarchy;
        }
        return $output;
    }
}
<?php

namespace _ContaoManager\Symfony\Config;

require_once __DIR__ . \DIRECTORY_SEPARATOR . 'Monolog' . \DIRECTORY_SEPARATOR . 'HandlerConfig.php';
use _ContaoManager\Symfony\Component\Config\Loader\ParamConfigurator;
use _ContaoManager\Symfony\Component\Config\Definition\Exception\InvalidConfigurationException;
/**
 * This class is automatically generated to help in creating a config.
 */
class MonologConfig implements \_ContaoManager\Symfony\Component\Config\Builder\ConfigBuilderInterface
{
    private $useMicroseconds;
    private $channels;
    private $handlers;
    private $_usedProperties = [];
    /**
     * @default true
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function useMicroseconds($value): static
    {
        $this->_usedProperties['useMicroseconds'] = \true;
        $this->useMicroseconds = $value;
        return $this;
    }
    /**
     * @param ParamConfigurator|list<ParamConfigurator|mixed> $value
     *
     * @return $this
     */
    public function channels(ParamConfigurator|array $value): static
    {
        $this->_usedProperties['channels'] = \true;
        $this->channels = $value;
        return $this;
    }
    /**
     * @template TValue of mixed
     * @param TValue $value
     * @example {"type":"stream","path":"\/var\/log\/symfony.log","level":"ERROR","bubble":"false","formatter":"my_formatter"}
     * @example {"type":"fingers_crossed","action_level":"WARNING","buffer_size":30,"handler":"custom"}
     * @example {"type":"service","id":"my_handler"}
     * @return \Symfony\Config\Monolog\HandlerConfig|$this
     * @psalm-return (TValue is array ? \Symfony\Config\Monolog\HandlerConfig : static)
     */
    public function handler(string $name, mixed $value = []): \_ContaoManager\Symfony\Config\Monolog\HandlerConfig|static
    {
        if (!\is_array($value)) {
            $this->_usedProperties['handlers'] = \true;
            $this->handlers[$name] = $value;
            return $this;
        }
        if (!isset($this->handlers[$name]) || !$this->handlers[$name] instanceof \_ContaoManager\Symfony\Config\Monolog\HandlerConfig) {
            $this->_usedProperties['handlers'] = \true;
            $this->handlers[$name] = new \_ContaoManager\Symfony\Config\Monolog\HandlerConfig($value);
        } elseif (1 < \func_num_args()) {
            throw new InvalidConfigurationException('The node created by "handler()" has already been initialized. You cannot pass values the second time you call handler().');
        }
        return $this->handlers[$name];
    }
    public function getExtensionAlias(): string
    {
        return 'monolog';
    }
    public function __construct(array $value = [])
    {
        if (array_key_exists('use_microseconds', $value)) {
            $this->_usedProperties['useMicroseconds'] = \true;
            $this->useMicroseconds = $value['use_microseconds'];
            unset($value['use_microseconds']);
        }
        if (array_key_exists('channels', $value)) {
            $this->_usedProperties['channels'] = \true;
            $this->channels = $value['channels'];
            unset($value['channels']);
        }
        if (array_key_exists('handlers', $value)) {
            $this->_usedProperties['handlers'] = \true;
            $this->handlers = array_map(fn($v) => \is_array($v) ? new \_ContaoManager\Symfony\Config\Monolog\HandlerConfig($v) : $v, $value['handlers']);
            unset($value['handlers']);
        }
        if ([] !== $value) {
            throw new InvalidConfigurationException(sprintf('The following keys are not supported by "%s": ', __CLASS__) . implode(', ', array_keys($value)));
        }
    }
    public function toArray(): array
    {
        $output = [];
        if (isset($this->_usedProperties['useMicroseconds'])) {
            $output['use_microseconds'] = $this->useMicroseconds;
        }
        if (isset($this->_usedProperties['channels'])) {
            $output['channels'] = $this->channels;
        }
        if (isset($this->_usedProperties['handlers'])) {
            $output['handlers'] = array_map(fn($v) => $v instanceof \_ContaoManager\Symfony\Config\Monolog\HandlerConfig ? $v->toArray() : $v, $this->handlers);
        }
        return $output;
    }
}
<?php

namespace _ContaoManager\Symfony\Config\Monolog;

require_once __DIR__ . \DIRECTORY_SEPARATOR . 'HandlerConfig' . \DIRECTORY_SEPARATOR . 'ProcessPsr3MessagesConfig.php';
require_once __DIR__ . \DIRECTORY_SEPARATOR . 'HandlerConfig' . \DIRECTORY_SEPARATOR . 'ExcludedHttpCodeConfig.php';
require_once __DIR__ . \DIRECTORY_SEPARATOR . 'HandlerConfig' . \DIRECTORY_SEPARATOR . 'PublisherConfig.php';
require_once __DIR__ . \DIRECTORY_SEPARATOR . 'HandlerConfig' . \DIRECTORY_SEPARATOR . 'MongoConfig.php';
require_once __DIR__ . \DIRECTORY_SEPARATOR . 'HandlerConfig' . \DIRECTORY_SEPARATOR . 'MongodbConfig.php';
require_once __DIR__ . \DIRECTORY_SEPARATOR . 'HandlerConfig' . \DIRECTORY_SEPARATOR . 'ElasticsearchConfig.php';
require_once __DIR__ . \DIRECTORY_SEPARATOR . 'HandlerConfig' . \DIRECTORY_SEPARATOR . 'RedisConfig.php';
require_once __DIR__ . \DIRECTORY_SEPARATOR . 'HandlerConfig' . \DIRECTORY_SEPARATOR . 'PredisConfig.php';
require_once __DIR__ . \DIRECTORY_SEPARATOR . 'HandlerConfig' . \DIRECTORY_SEPARATOR . 'EmailPrototypeConfig.php';
require_once __DIR__ . \DIRECTORY_SEPARATOR . 'HandlerConfig' . \DIRECTORY_SEPARATOR . 'VerbosityLevelsConfig.php';
require_once __DIR__ . \DIRECTORY_SEPARATOR . 'HandlerConfig' . \DIRECTORY_SEPARATOR . 'ChannelsConfig.php';
use _ContaoManager\Symfony\Component\Config\Loader\ParamConfigurator;
use _ContaoManager\Symfony\Component\Config\Definition\Exception\InvalidConfigurationException;
/**
 * This class is automatically generated to help in creating a config.
 */
class HandlerConfig
{
    private $type;
    private $id;
    private $enabled;
    private $priority;
    private $level;
    private $bubble;
    private $interactiveOnly;
    private $appName;
    private $fillExtraContext;
    private $includeStacktraces;
    private $processPsr3Messages;
    private $path;
    private $filePermission;
    private $useLocking;
    private $filenameFormat;
    private $dateFormat;
    private $ident;
    private $logopts;
    private $facility;
    private $maxFiles;
    private $actionLevel;
    private $activationStrategy;
    private $stopBuffering;
    private $passthruLevel;
    private $excluded404s;
    private $excludedHttpCodes;
    private $acceptedLevels;
    private $minLevel;
    private $maxLevel;
    private $bufferSize;
    private $flushOnOverflow;
    private $handler;
    private $url;
    private $exchange;
    private $exchangeName;
    private $room;
    private $messageFormat;
    private $apiVersion;
    private $channel;
    private $botName;
    private $useAttachment;
    private $useShortAttachment;
    private $includeExtra;
    private $iconEmoji;
    private $webhookUrl;
    private $excludeFields;
    private $team;
    private $notify;
    private $nickname;
    private $token;
    private $region;
    private $source;
    private $useSsl;
    private $user;
    private $title;
    private $host;
    private $port;
    private $config;
    private $members;
    private $connectionString;
    private $timeout;
    private $time;
    private $deduplicationLevel;
    private $store;
    private $connectionTimeout;
    private $persistent;
    private $dsn;
    private $hubId;
    private $clientId;
    private $autoLogStacks;
    private $release;
    private $environment;
    private $messageType;
    private $parseMode;
    private $disableWebpagePreview;
    private $disableNotification;
    private $splitLongMessages;
    private $delayBetweenMessages;
    private $topic;
    private $factor;
    private $tags;
    private $consoleFormaterOptions;
    private $consoleFormatterOptions;
    private $formatter;
    private $nested;
    private $publisher;
    private $mongo;
    private $mongodb;
    private $elasticsearch;
    private $index;
    private $documentType;
    private $ignoreError;
    private $redis;
    private $predis;
    private $fromEmail;
    private $toEmail;
    private $subject;
    private $contentType;
    private $headers;
    private $mailer;
    private $emailPrototype;
    private $lazy;
    private $verbosityLevels;
    private $channels;
    private $_usedProperties = [];
    /**
     * @default null
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function type($value): static
    {
        $this->_usedProperties['type'] = \true;
        $this->type = $value;
        return $this;
    }
    /**
     * @default null
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function id($value): static
    {
        $this->_usedProperties['id'] = \true;
        $this->id = $value;
        return $this;
    }
    /**
     * @default true
     * @param ParamConfigurator|bool $value
     * @return $this
     */
    public function enabled($value): static
    {
        $this->_usedProperties['enabled'] = \true;
        $this->enabled = $value;
        return $this;
    }
    /**
     * @default 0
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function priority($value): static
    {
        $this->_usedProperties['priority'] = \true;
        $this->priority = $value;
        return $this;
    }
    /**
     * @default 'DEBUG'
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function level($value): static
    {
        $this->_usedProperties['level'] = \true;
        $this->level = $value;
        return $this;
    }
    /**
     * @default true
     * @param ParamConfigurator|bool $value
     * @return $this
     */
    public function bubble($value): static
    {
        $this->_usedProperties['bubble'] = \true;
        $this->bubble = $value;
        return $this;
    }
    /**
     * @default false
     * @param ParamConfigurator|bool $value
     * @return $this
     */
    public function interactiveOnly($value): static
    {
        $this->_usedProperties['interactiveOnly'] = \true;
        $this->interactiveOnly = $value;
        return $this;
    }
    /**
     * @default null
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function appName($value): static
    {
        $this->_usedProperties['appName'] = \true;
        $this->appName = $value;
        return $this;
    }
    /**
     * @default false
     * @param ParamConfigurator|bool $value
     * @return $this
     */
    public function fillExtraContext($value): static
    {
        $this->_usedProperties['fillExtraContext'] = \true;
        $this->fillExtraContext = $value;
        return $this;
    }
    /**
     * @default false
     * @param ParamConfigurator|bool $value
     * @return $this
     */
    public function includeStacktraces($value): static
    {
        $this->_usedProperties['includeStacktraces'] = \true;
        $this->includeStacktraces = $value;
        return $this;
    }
    /**
     * @template TValue of mixed
     * @param TValue $value
     * @default {"enabled":null}
     * @return \Symfony\Config\Monolog\HandlerConfig\ProcessPsr3MessagesConfig|$this
     * @psalm-return (TValue is array ? \Symfony\Config\Monolog\HandlerConfig\ProcessPsr3MessagesConfig : static)
     */
    public function processPsr3Messages(mixed $value = []): \_ContaoManager\Symfony\Config\Monolog\HandlerConfig\ProcessPsr3MessagesConfig|static
    {
        if (!\is_array($value)) {
            $this->_usedProperties['processPsr3Messages'] = \true;
            $this->processPsr3Messages = $value;
            return $this;
        }
        if (!$this->processPsr3Messages instanceof \_ContaoManager\Symfony\Config\Monolog\HandlerConfig\ProcessPsr3MessagesConfig) {
            $this->_usedProperties['processPsr3Messages'] = \true;
            $this->processPsr3Messages = new \_ContaoManager\Symfony\Config\Monolog\HandlerConfig\ProcessPsr3MessagesConfig($value);
        } elseif (0 < \func_num_args()) {
            throw new InvalidConfigurationException('The node created by "processPsr3Messages()" has already been initialized. You cannot pass values the second time you call processPsr3Messages().');
        }
        return $this->processPsr3Messages;
    }
    /**
     * @default '%kernel.logs_dir%/%kernel.environment%.log'
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function path($value): static
    {
        $this->_usedProperties['path'] = \true;
        $this->path = $value;
        return $this;
    }
    /**
     * @default null
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function filePermission($value): static
    {
        $this->_usedProperties['filePermission'] = \true;
        $this->filePermission = $value;
        return $this;
    }
    /**
     * @default false
     * @param ParamConfigurator|bool $value
     * @return $this
     */
    public function useLocking($value): static
    {
        $this->_usedProperties['useLocking'] = \true;
        $this->useLocking = $value;
        return $this;
    }
    /**
     * @default '{filename}-{date}'
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function filenameFormat($value): static
    {
        $this->_usedProperties['filenameFormat'] = \true;
        $this->filenameFormat = $value;
        return $this;
    }
    /**
     * @default 'Y-m-d'
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function dateFormat($value): static
    {
        $this->_usedProperties['dateFormat'] = \true;
        $this->dateFormat = $value;
        return $this;
    }
    /**
     * @default false
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function ident($value): static
    {
        $this->_usedProperties['ident'] = \true;
        $this->ident = $value;
        return $this;
    }
    /**
     * @default 1
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function logopts($value): static
    {
        $this->_usedProperties['logopts'] = \true;
        $this->logopts = $value;
        return $this;
    }
    /**
     * @default 'user'
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function facility($value): static
    {
        $this->_usedProperties['facility'] = \true;
        $this->facility = $value;
        return $this;
    }
    /**
     * @default 0
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function maxFiles($value): static
    {
        $this->_usedProperties['maxFiles'] = \true;
        $this->maxFiles = $value;
        return $this;
    }
    /**
     * @default 'WARNING'
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function actionLevel($value): static
    {
        $this->_usedProperties['actionLevel'] = \true;
        $this->actionLevel = $value;
        return $this;
    }
    /**
     * @default null
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function activationStrategy($value): static
    {
        $this->_usedProperties['activationStrategy'] = \true;
        $this->activationStrategy = $value;
        return $this;
    }
    /**
     * @default true
     * @param ParamConfigurator|bool $value
     * @return $this
     */
    public function stopBuffering($value): static
    {
        $this->_usedProperties['stopBuffering'] = \true;
        $this->stopBuffering = $value;
        return $this;
    }
    /**
     * @default null
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function passthruLevel($value): static
    {
        $this->_usedProperties['passthruLevel'] = \true;
        $this->passthruLevel = $value;
        return $this;
    }
    /**
     * @param ParamConfigurator|list<ParamConfigurator|mixed> $value
     *
     * @return $this
     */
    public function excluded404s(ParamConfigurator|array $value): static
    {
        $this->_usedProperties['excluded404s'] = \true;
        $this->excluded404s = $value;
        return $this;
    }
    /**
     * @template TValue of mixed
     * @param TValue $value
     * Only for "fingers_crossed" handler type
     * @example 403
     * @example 404
     * @example {"400":["^\/foo","^\/bar"]}
     * @return \Symfony\Config\Monolog\HandlerConfig\ExcludedHttpCodeConfig|$this
     * @psalm-return (TValue is array ? \Symfony\Config\Monolog\HandlerConfig\ExcludedHttpCodeConfig : static)
     */
    public function excludedHttpCode(mixed $value = []): \_ContaoManager\Symfony\Config\Monolog\HandlerConfig\ExcludedHttpCodeConfig|static
    {
        $this->_usedProperties['excludedHttpCodes'] = \true;
        if (!\is_array($value)) {
            $this->excludedHttpCodes[] = $value;
            return $this;
        }
        return $this->excludedHttpCodes[] = new \_ContaoManager\Symfony\Config\Monolog\HandlerConfig\ExcludedHttpCodeConfig($value);
    }
    /**
     * @param ParamConfigurator|list<ParamConfigurator|mixed> $value
     *
     * @return $this
     */
    public function acceptedLevels(ParamConfigurator|array $value): static
    {
        $this->_usedProperties['acceptedLevels'] = \true;
        $this->acceptedLevels = $value;
        return $this;
    }
    /**
     * @default 'DEBUG'
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function minLevel($value): static
    {
        $this->_usedProperties['minLevel'] = \true;
        $this->minLevel = $value;
        return $this;
    }
    /**
     * @default 'EMERGENCY'
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function maxLevel($value): static
    {
        $this->_usedProperties['maxLevel'] = \true;
        $this->maxLevel = $value;
        return $this;
    }
    /**
     * @default 0
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function bufferSize($value): static
    {
        $this->_usedProperties['bufferSize'] = \true;
        $this->bufferSize = $value;
        return $this;
    }
    /**
     * @default false
     * @param ParamConfigurator|bool $value
     * @return $this
     */
    public function flushOnOverflow($value): static
    {
        $this->_usedProperties['flushOnOverflow'] = \true;
        $this->flushOnOverflow = $value;
        return $this;
    }
    /**
     * @default null
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function handler($value): static
    {
        $this->_usedProperties['handler'] = \true;
        $this->handler = $value;
        return $this;
    }
    /**
     * @default null
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function url($value): static
    {
        $this->_usedProperties['url'] = \true;
        $this->url = $value;
        return $this;
    }
    /**
     * @default null
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function exchange($value): static
    {
        $this->_usedProperties['exchange'] = \true;
        $this->exchange = $value;
        return $this;
    }
    /**
     * @default 'log'
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function exchangeName($value): static
    {
        $this->_usedProperties['exchangeName'] = \true;
        $this->exchangeName = $value;
        return $this;
    }
    /**
     * @default null
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function room($value): static
    {
        $this->_usedProperties['room'] = \true;
        $this->room = $value;
        return $this;
    }
    /**
     * @default 'text'
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function messageFormat($value): static
    {
        $this->_usedProperties['messageFormat'] = \true;
        $this->messageFormat = $value;
        return $this;
    }
    /**
     * @default null
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function apiVersion($value): static
    {
        $this->_usedProperties['apiVersion'] = \true;
        $this->apiVersion = $value;
        return $this;
    }
    /**
     * @default null
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function channel($value): static
    {
        $this->_usedProperties['channel'] = \true;
        $this->channel = $value;
        return $this;
    }
    /**
     * @default 'Monolog'
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function botName($value): static
    {
        $this->_usedProperties['botName'] = \true;
        $this->botName = $value;
        return $this;
    }
    /**
     * @default true
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function useAttachment($value): static
    {
        $this->_usedProperties['useAttachment'] = \true;
        $this->useAttachment = $value;
        return $this;
    }
    /**
     * @default false
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function useShortAttachment($value): static
    {
        $this->_usedProperties['useShortAttachment'] = \true;
        $this->useShortAttachment = $value;
        return $this;
    }
    /**
     * @default false
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function includeExtra($value): static
    {
        $this->_usedProperties['includeExtra'] = \true;
        $this->includeExtra = $value;
        return $this;
    }
    /**
     * @default null
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function iconEmoji($value): static
    {
        $this->_usedProperties['iconEmoji'] = \true;
        $this->iconEmoji = $value;
        return $this;
    }
    /**
     * @default null
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function webhookUrl($value): static
    {
        $this->_usedProperties['webhookUrl'] = \true;
        $this->webhookUrl = $value;
        return $this;
    }
    /**
     * @param ParamConfigurator|list<ParamConfigurator|mixed> $value
     *
     * @return $this
     */
    public function excludeFields(ParamConfigurator|array $value): static
    {
        $this->_usedProperties['excludeFields'] = \true;
        $this->excludeFields = $value;
        return $this;
    }
    /**
     * @default null
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function team($value): static
    {
        $this->_usedProperties['team'] = \true;
        $this->team = $value;
        return $this;
    }
    /**
     * @default false
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function notify($value): static
    {
        $this->_usedProperties['notify'] = \true;
        $this->notify = $value;
        return $this;
    }
    /**
     * @default 'Monolog'
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function nickname($value): static
    {
        $this->_usedProperties['nickname'] = \true;
        $this->nickname = $value;
        return $this;
    }
    /**
     * @default null
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function token($value): static
    {
        $this->_usedProperties['token'] = \true;
        $this->token = $value;
        return $this;
    }
    /**
     * @default null
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function region($value): static
    {
        $this->_usedProperties['region'] = \true;
        $this->region = $value;
        return $this;
    }
    /**
     * @default null
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function source($value): static
    {
        $this->_usedProperties['source'] = \true;
        $this->source = $value;
        return $this;
    }
    /**
     * @default true
     * @param ParamConfigurator|bool $value
     * @return $this
     */
    public function useSsl($value): static
    {
        $this->_usedProperties['useSsl'] = \true;
        $this->useSsl = $value;
        return $this;
    }
    /**
     * @default null
     * @param ParamConfigurator|mixed $value
     *
     * @return $this
     */
    public function user(mixed $value): static
    {
        $this->_usedProperties['user'] = \true;
        $this->user = $value;
        return $this;
    }
    /**
     * @default null
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function title($value): static
    {
        $this->_usedProperties['title'] = \true;
        $this->title = $value;
        return $this;
    }
    /**
     * @default null
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function host($value): static
    {
        $this->_usedProperties['host'] = \true;
        $this->host = $value;
        return $this;
    }
    /**
     * @default 514
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function port($value): static
    {
        $this->_usedProperties['port'] = \true;
        $this->port = $value;
        return $this;
    }
    /**
     * @param ParamConfigurator|list<ParamConfigurator|mixed> $value
     *
     * @return $this
     */
    public function config(ParamConfigurator|array $value): static
    {
        $this->_usedProperties['config'] = \true;
        $this->config = $value;
        return $this;
    }
    /**
     * @param ParamConfigurator|list<ParamConfigurator|mixed> $value
     *
     * @return $this
     */
    public function members(ParamConfigurator|array $value): static
    {
        $this->_usedProperties['members'] = \true;
        $this->members = $value;
        return $this;
    }
    /**
     * @default null
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function connectionString($value): static
    {
        $this->_usedProperties['connectionString'] = \true;
        $this->connectionString = $value;
        return $this;
    }
    /**
     * @default null
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function timeout($value): static
    {
        $this->_usedProperties['timeout'] = \true;
        $this->timeout = $value;
        return $this;
    }
    /**
     * @default 60
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function time($value): static
    {
        $this->_usedProperties['time'] = \true;
        $this->time = $value;
        return $this;
    }
    /**
     * @default 400
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function deduplicationLevel($value): static
    {
        $this->_usedProperties['deduplicationLevel'] = \true;
        $this->deduplicationLevel = $value;
        return $this;
    }
    /**
     * @default null
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function store($value): static
    {
        $this->_usedProperties['store'] = \true;
        $this->store = $value;
        return $this;
    }
    /**
     * @default null
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function connectionTimeout($value): static
    {
        $this->_usedProperties['connectionTimeout'] = \true;
        $this->connectionTimeout = $value;
        return $this;
    }
    /**
     * @default null
     * @param ParamConfigurator|bool $value
     * @return $this
     */
    public function persistent($value): static
    {
        $this->_usedProperties['persistent'] = \true;
        $this->persistent = $value;
        return $this;
    }
    /**
     * @default null
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function dsn($value): static
    {
        $this->_usedProperties['dsn'] = \true;
        $this->dsn = $value;
        return $this;
    }
    /**
     * @default null
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function hubId($value): static
    {
        $this->_usedProperties['hubId'] = \true;
        $this->hubId = $value;
        return $this;
    }
    /**
     * @default null
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function clientId($value): static
    {
        $this->_usedProperties['clientId'] = \true;
        $this->clientId = $value;
        return $this;
    }
    /**
     * @default false
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function autoLogStacks($value): static
    {
        $this->_usedProperties['autoLogStacks'] = \true;
        $this->autoLogStacks = $value;
        return $this;
    }
    /**
     * @default null
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function release($value): static
    {
        $this->_usedProperties['release'] = \true;
        $this->release = $value;
        return $this;
    }
    /**
     * @default null
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function environment($value): static
    {
        $this->_usedProperties['environment'] = \true;
        $this->environment = $value;
        return $this;
    }
    /**
     * @default 0
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function messageType($value): static
    {
        $this->_usedProperties['messageType'] = \true;
        $this->messageType = $value;
        return $this;
    }
    /**
     * @default null
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function parseMode($value): static
    {
        $this->_usedProperties['parseMode'] = \true;
        $this->parseMode = $value;
        return $this;
    }
    /**
     * @default null
     * @param ParamConfigurator|bool $value
     * @return $this
     */
    public function disableWebpagePreview($value): static
    {
        $this->_usedProperties['disableWebpagePreview'] = \true;
        $this->disableWebpagePreview = $value;
        return $this;
    }
    /**
     * @default null
     * @param ParamConfigurator|bool $value
     * @return $this
     */
    public function disableNotification($value): static
    {
        $this->_usedProperties['disableNotification'] = \true;
        $this->disableNotification = $value;
        return $this;
    }
    /**
     * @default false
     * @param ParamConfigurator|bool $value
     * @return $this
     */
    public function splitLongMessages($value): static
    {
        $this->_usedProperties['splitLongMessages'] = \true;
        $this->splitLongMessages = $value;
        return $this;
    }
    /**
     * @default false
     * @param ParamConfigurator|bool $value
     * @return $this
     */
    public function delayBetweenMessages($value): static
    {
        $this->_usedProperties['delayBetweenMessages'] = \true;
        $this->delayBetweenMessages = $value;
        return $this;
    }
    /**
     * @default null
     * @param ParamConfigurator|int $value
     * @return $this
     */
    public function topic($value): static
    {
        $this->_usedProperties['topic'] = \true;
        $this->topic = $value;
        return $this;
    }
    /**
     * @default 1
     * @param ParamConfigurator|int $value
     * @return $this
     */
    public function factor($value): static
    {
        $this->_usedProperties['factor'] = \true;
        $this->factor = $value;
        return $this;
    }
    /**
     * @param ParamConfigurator|list<ParamConfigurator|mixed>|string $value
     *
     * @return $this
     */
    public function tags(ParamConfigurator|string|array $value): static
    {
        $this->_usedProperties['tags'] = \true;
        $this->tags = $value;
        return $this;
    }
    /**
     * @default null
     * @param ParamConfigurator|mixed $value
     * @deprecated ".console_formater_options" is deprecated, use ".console_formatter_options" instead.
     *
     * @return $this
     */
    public function consoleFormaterOptions(mixed $value): static
    {
        $this->_usedProperties['consoleFormaterOptions'] = \true;
        $this->consoleFormaterOptions = $value;
        return $this;
    }
    /**
     * @default array (
     * )
     * @param ParamConfigurator|mixed $value
     *
     * @return $this
     */
    public function consoleFormatterOptions(mixed $value = array()): static
    {
        $this->_usedProperties['consoleFormatterOptions'] = \true;
        $this->consoleFormatterOptions = $value;
        return $this;
    }
    /**
     * @default null
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function formatter($value): static
    {
        $this->_usedProperties['formatter'] = \true;
        $this->formatter = $value;
        return $this;
    }
    /**
     * @default false
     * @param ParamConfigurator|bool $value
     * @return $this
     */
    public function nested($value): static
    {
        $this->_usedProperties['nested'] = \true;
        $this->nested = $value;
        return $this;
    }
    /**
     * @template TValue of string|array
     * @param TValue $value
     * @return \Symfony\Config\Monolog\HandlerConfig\PublisherConfig|$this
     * @psalm-return (TValue is array ? \Symfony\Config\Monolog\HandlerConfig\PublisherConfig : static)
     */
    public function publisher(string|array $value = []): \_ContaoManager\Symfony\Config\Monolog\HandlerConfig\PublisherConfig|static
    {
        if (!\is_array($value)) {
            $this->_usedProperties['publisher'] = \true;
            $this->publisher = $value;
            return $this;
        }
        if (!$this->publisher instanceof \_ContaoManager\Symfony\Config\Monolog\HandlerConfig\PublisherConfig) {
            $this->_usedProperties['publisher'] = \true;
            $this->publisher = new \_ContaoManager\Symfony\Config\Monolog\HandlerConfig\PublisherConfig($value);
        } elseif (0 < \func_num_args()) {
            throw new InvalidConfigurationException('The node created by "publisher()" has already been initialized. You cannot pass values the second time you call publisher().');
        }
        return $this->publisher;
    }
    /**
     * @template TValue of string|array
     * @param TValue $value
     * @return \Symfony\Config\Monolog\HandlerConfig\MongoConfig|$this
     * @psalm-return (TValue is array ? \Symfony\Config\Monolog\HandlerConfig\MongoConfig : static)
     */
    public function mongo(string|array $value = []): \_ContaoManager\Symfony\Config\Monolog\HandlerConfig\MongoConfig|static
    {
        if (!\is_array($value)) {
            $this->_usedProperties['mongo'] = \true;
            $this->mongo = $value;
            return $this;
        }
        if (!$this->mongo instanceof \_ContaoManager\Symfony\Config\Monolog\HandlerConfig\MongoConfig) {
            $this->_usedProperties['mongo'] = \true;
            $this->mongo = new \_ContaoManager\Symfony\Config\Monolog\HandlerConfig\MongoConfig($value);
        } elseif (0 < \func_num_args()) {
            throw new InvalidConfigurationException('The node created by "mongo()" has already been initialized. You cannot pass values the second time you call mongo().');
        }
        return $this->mongo;
    }
    /**
     * @template TValue of string|array
     * @param TValue $value
     * @return \Symfony\Config\Monolog\HandlerConfig\MongodbConfig|$this
     * @psalm-return (TValue is array ? \Symfony\Config\Monolog\HandlerConfig\MongodbConfig : static)
     */
    public function mongodb(string|array $value = []): \_ContaoManager\Symfony\Config\Monolog\HandlerConfig\MongodbConfig|static
    {
        if (!\is_array($value)) {
            $this->_usedProperties['mongodb'] = \true;
            $this->mongodb = $value;
            return $this;
        }
        if (!$this->mongodb instanceof \_ContaoManager\Symfony\Config\Monolog\HandlerConfig\MongodbConfig) {
            $this->_usedProperties['mongodb'] = \true;
            $this->mongodb = new \_ContaoManager\Symfony\Config\Monolog\HandlerConfig\MongodbConfig($value);
        } elseif (0 < \func_num_args()) {
            throw new InvalidConfigurationException('The node created by "mongodb()" has already been initialized. You cannot pass values the second time you call mongodb().');
        }
        return $this->mongodb;
    }
    /**
     * @template TValue of string|array
     * @param TValue $value
     * @return \Symfony\Config\Monolog\HandlerConfig\ElasticsearchConfig|$this
     * @psalm-return (TValue is array ? \Symfony\Config\Monolog\HandlerConfig\ElasticsearchConfig : static)
     */
    public function elasticsearch(string|array $value = []): \_ContaoManager\Symfony\Config\Monolog\HandlerConfig\ElasticsearchConfig|static
    {
        if (!\is_array($value)) {
            $this->_usedProperties['elasticsearch'] = \true;
            $this->elasticsearch = $value;
            return $this;
        }
        if (!$this->elasticsearch instanceof \_ContaoManager\Symfony\Config\Monolog\HandlerConfig\ElasticsearchConfig) {
            $this->_usedProperties['elasticsearch'] = \true;
            $this->elasticsearch = new \_ContaoManager\Symfony\Config\Monolog\HandlerConfig\ElasticsearchConfig($value);
        } elseif (0 < \func_num_args()) {
            throw new InvalidConfigurationException('The node created by "elasticsearch()" has already been initialized. You cannot pass values the second time you call elasticsearch().');
        }
        return $this->elasticsearch;
    }
    /**
     * @default 'monolog'
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function index($value): static
    {
        $this->_usedProperties['index'] = \true;
        $this->index = $value;
        return $this;
    }
    /**
     * @default 'logs'
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function documentType($value): static
    {
        $this->_usedProperties['documentType'] = \true;
        $this->documentType = $value;
        return $this;
    }
    /**
     * @default false
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function ignoreError($value): static
    {
        $this->_usedProperties['ignoreError'] = \true;
        $this->ignoreError = $value;
        return $this;
    }
    /**
     * @template TValue of string|array
     * @param TValue $value
     * @return \Symfony\Config\Monolog\HandlerConfig\RedisConfig|$this
     * @psalm-return (TValue is array ? \Symfony\Config\Monolog\HandlerConfig\RedisConfig : static)
     */
    public function redis(string|array $value = []): \_ContaoManager\Symfony\Config\Monolog\HandlerConfig\RedisConfig|static
    {
        if (!\is_array($value)) {
            $this->_usedProperties['redis'] = \true;
            $this->redis = $value;
            return $this;
        }
        if (!$this->redis instanceof \_ContaoManager\Symfony\Config\Monolog\HandlerConfig\RedisConfig) {
            $this->_usedProperties['redis'] = \true;
            $this->redis = new \_ContaoManager\Symfony\Config\Monolog\HandlerConfig\RedisConfig($value);
        } elseif (0 < \func_num_args()) {
            throw new InvalidConfigurationException('The node created by "redis()" has already been initialized. You cannot pass values the second time you call redis().');
        }
        return $this->redis;
    }
    /**
     * @template TValue of string|array
     * @param TValue $value
     * @return \Symfony\Config\Monolog\HandlerConfig\PredisConfig|$this
     * @psalm-return (TValue is array ? \Symfony\Config\Monolog\HandlerConfig\PredisConfig : static)
     */
    public function predis(string|array $value = []): \_ContaoManager\Symfony\Config\Monolog\HandlerConfig\PredisConfig|static
    {
        if (!\is_array($value)) {
            $this->_usedProperties['predis'] = \true;
            $this->predis = $value;
            return $this;
        }
        if (!$this->predis instanceof \_ContaoManager\Symfony\Config\Monolog\HandlerConfig\PredisConfig) {
            $this->_usedProperties['predis'] = \true;
            $this->predis = new \_ContaoManager\Symfony\Config\Monolog\HandlerConfig\PredisConfig($value);
        } elseif (0 < \func_num_args()) {
            throw new InvalidConfigurationException('The node created by "predis()" has already been initialized. You cannot pass values the second time you call predis().');
        }
        return $this->predis;
    }
    /**
     * @default null
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function fromEmail($value): static
    {
        $this->_usedProperties['fromEmail'] = \true;
        $this->fromEmail = $value;
        return $this;
    }
    /**
     * @param ParamConfigurator|list<ParamConfigurator|mixed>|string $value
     *
     * @return $this
     */
    public function toEmail(ParamConfigurator|string|array $value): static
    {
        $this->_usedProperties['toEmail'] = \true;
        $this->toEmail = $value;
        return $this;
    }
    /**
     * @default null
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function subject($value): static
    {
        $this->_usedProperties['subject'] = \true;
        $this->subject = $value;
        return $this;
    }
    /**
     * @default null
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function contentType($value): static
    {
        $this->_usedProperties['contentType'] = \true;
        $this->contentType = $value;
        return $this;
    }
    /**
     * @param ParamConfigurator|list<ParamConfigurator|mixed> $value
     *
     * @return $this
     */
    public function headers(ParamConfigurator|array $value): static
    {
        $this->_usedProperties['headers'] = \true;
        $this->headers = $value;
        return $this;
    }
    /**
     * @default null
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function mailer($value): static
    {
        $this->_usedProperties['mailer'] = \true;
        $this->mailer = $value;
        return $this;
    }
    /**
     * @template TValue of string|array
     * @param TValue $value
     * @return \Symfony\Config\Monolog\HandlerConfig\EmailPrototypeConfig|$this
     * @psalm-return (TValue is array ? \Symfony\Config\Monolog\HandlerConfig\EmailPrototypeConfig : static)
     */
    public function emailPrototype(string|array $value = []): \_ContaoManager\Symfony\Config\Monolog\HandlerConfig\EmailPrototypeConfig|static
    {
        if (!\is_array($value)) {
            $this->_usedProperties['emailPrototype'] = \true;
            $this->emailPrototype = $value;
            return $this;
        }
        if (!$this->emailPrototype instanceof \_ContaoManager\Symfony\Config\Monolog\HandlerConfig\EmailPrototypeConfig) {
            $this->_usedProperties['emailPrototype'] = \true;
            $this->emailPrototype = new \_ContaoManager\Symfony\Config\Monolog\HandlerConfig\EmailPrototypeConfig($value);
        } elseif (0 < \func_num_args()) {
            throw new InvalidConfigurationException('The node created by "emailPrototype()" has already been initialized. You cannot pass values the second time you call emailPrototype().');
        }
        return $this->emailPrototype;
    }
    /**
     * @default true
     * @param ParamConfigurator|bool $value
     * @return $this
     */
    public function lazy($value): static
    {
        $this->_usedProperties['lazy'] = \true;
        $this->lazy = $value;
        return $this;
    }
    public function verbosityLevels(array $value = []): \_ContaoManager\Symfony\Config\Monolog\HandlerConfig\VerbosityLevelsConfig
    {
        if (null === $this->verbosityLevels) {
            $this->_usedProperties['verbosityLevels'] = \true;
            $this->verbosityLevels = new \_ContaoManager\Symfony\Config\Monolog\HandlerConfig\VerbosityLevelsConfig($value);
        } elseif (0 < \func_num_args()) {
            throw new InvalidConfigurationException('The node created by "verbosityLevels()" has already been initialized. You cannot pass values the second time you call verbosityLevels().');
        }
        return $this->verbosityLevels;
    }
    /**
     * @template TValue of mixed
     * @param TValue $value
     * @return \Symfony\Config\Monolog\HandlerConfig\ChannelsConfig|$this
     * @psalm-return (TValue is array ? \Symfony\Config\Monolog\HandlerConfig\ChannelsConfig : static)
     */
    public function channels(mixed $value = []): \_ContaoManager\Symfony\Config\Monolog\HandlerConfig\ChannelsConfig|static
    {
        if (!\is_array($value)) {
            $this->_usedProperties['channels'] = \true;
            $this->channels = $value;
            return $this;
        }
        if (!$this->channels instanceof \_ContaoManager\Symfony\Config\Monolog\HandlerConfig\ChannelsConfig) {
            $this->_usedProperties['channels'] = \true;
            $this->channels = new \_ContaoManager\Symfony\Config\Monolog\HandlerConfig\ChannelsConfig($value);
        } elseif (0 < \func_num_args()) {
            throw new InvalidConfigurationException('The node created by "channels()" has already been initialized. You cannot pass values the second time you call channels().');
        }
        return $this->channels;
    }
    public function __construct(array $value = [])
    {
        if (array_key_exists('type', $value)) {
            $this->_usedProperties['type'] = \true;
            $this->type = $value['type'];
            unset($value['type']);
        }
        if (array_key_exists('id', $value)) {
            $this->_usedProperties['id'] = \true;
            $this->id = $value['id'];
            unset($value['id']);
        }
        if (array_key_exists('enabled', $value)) {
            $this->_usedProperties['enabled'] = \true;
            $this->enabled = $value['enabled'];
            unset($value['enabled']);
        }
        if (array_key_exists('priority', $value)) {
            $this->_usedProperties['priority'] = \true;
            $this->priority = $value['priority'];
            unset($value['priority']);
        }
        if (array_key_exists('level', $value)) {
            $this->_usedProperties['level'] = \true;
            $this->level = $value['level'];
            unset($value['level']);
        }
        if (array_key_exists('bubble', $value)) {
            $this->_usedProperties['bubble'] = \true;
            $this->bubble = $value['bubble'];
            unset($value['bubble']);
        }
        if (array_key_exists('interactive_only', $value)) {
            $this->_usedProperties['interactiveOnly'] = \true;
            $this->interactiveOnly = $value['interactive_only'];
            unset($value['interactive_only']);
        }
        if (array_key_exists('app_name', $value)) {
            $this->_usedProperties['appName'] = \true;
            $this->appName = $value['app_name'];
            unset($value['app_name']);
        }
        if (array_key_exists('fill_extra_context', $value)) {
            $this->_usedProperties['fillExtraContext'] = \true;
            $this->fillExtraContext = $value['fill_extra_context'];
            unset($value['fill_extra_context']);
        }
        if (array_key_exists('include_stacktraces', $value)) {
            $this->_usedProperties['includeStacktraces'] = \true;
            $this->includeStacktraces = $value['include_stacktraces'];
            unset($value['include_stacktraces']);
        }
        if (array_key_exists('process_psr_3_messages', $value)) {
            $this->_usedProperties['processPsr3Messages'] = \true;
            $this->processPsr3Messages = \is_array($value['process_psr_3_messages']) ? new \_ContaoManager\Symfony\Config\Monolog\HandlerConfig\ProcessPsr3MessagesConfig($value['process_psr_3_messages']) : $value['process_psr_3_messages'];
            unset($value['process_psr_3_messages']);
        }
        if (array_key_exists('path', $value)) {
            $this->_usedProperties['path'] = \true;
            $this->path = $value['path'];
            unset($value['path']);
        }
        if (array_key_exists('file_permission', $value)) {
            $this->_usedProperties['filePermission'] = \true;
            $this->filePermission = $value['file_permission'];
            unset($value['file_permission']);
        }
        if (array_key_exists('use_locking', $value)) {
            $this->_usedProperties['useLocking'] = \true;
            $this->useLocking = $value['use_locking'];
            unset($value['use_locking']);
        }
        if (array_key_exists('filename_format', $value)) {
            $this->_usedProperties['filenameFormat'] = \true;
            $this->filenameFormat = $value['filename_format'];
            unset($value['filename_format']);
        }
        if (array_key_exists('date_format', $value)) {
            $this->_usedProperties['dateFormat'] = \true;
            $this->dateFormat = $value['date_format'];
            unset($value['date_format']);
        }
        if (array_key_exists('ident', $value)) {
            $this->_usedProperties['ident'] = \true;
            $this->ident = $value['ident'];
            unset($value['ident']);
        }
        if (array_key_exists('logopts', $value)) {
            $this->_usedProperties['logopts'] = \true;
            $this->logopts = $value['logopts'];
            unset($value['logopts']);
        }
        if (array_key_exists('facility', $value)) {
            $this->_usedProperties['facility'] = \true;
            $this->facility = $value['facility'];
            unset($value['facility']);
        }
        if (array_key_exists('max_files', $value)) {
            $this->_usedProperties['maxFiles'] = \true;
            $this->maxFiles = $value['max_files'];
            unset($value['max_files']);
        }
        if (array_key_exists('action_level', $value)) {
            $this->_usedProperties['actionLevel'] = \true;
            $this->actionLevel = $value['action_level'];
            unset($value['action_level']);
        }
        if (array_key_exists('activation_strategy', $value)) {
            $this->_usedProperties['activationStrategy'] = \true;
            $this->activationStrategy = $value['activation_strategy'];
            unset($value['activation_strategy']);
        }
        if (array_key_exists('stop_buffering', $value)) {
            $this->_usedProperties['stopBuffering'] = \true;
            $this->stopBuffering = $value['stop_buffering'];
            unset($value['stop_buffering']);
        }
        if (array_key_exists('passthru_level', $value)) {
            $this->_usedProperties['passthruLevel'] = \true;
            $this->passthruLevel = $value['passthru_level'];
            unset($value['passthru_level']);
        }
        if (array_key_exists('excluded_404s', $value)) {
            $this->_usedProperties['excluded404s'] = \true;
            $this->excluded404s = $value['excluded_404s'];
            unset($value['excluded_404s']);
        }
        if (array_key_exists('excluded_http_codes', $value)) {
            $this->_usedProperties['excludedHttpCodes'] = \true;
            $this->excludedHttpCodes = array_map(fn($v) => \is_array($v) ? new \_ContaoManager\Symfony\Config\Monolog\HandlerConfig\ExcludedHttpCodeConfig($v) : $v, $value['excluded_http_codes']);
            unset($value['excluded_http_codes']);
        }
        if (array_key_exists('accepted_levels', $value)) {
            $this->_usedProperties['acceptedLevels'] = \true;
            $this->acceptedLevels = $value['accepted_levels'];
            unset($value['accepted_levels']);
        }
        if (array_key_exists('min_level', $value)) {
            $this->_usedProperties['minLevel'] = \true;
            $this->minLevel = $value['min_level'];
            unset($value['min_level']);
        }
        if (array_key_exists('max_level', $value)) {
            $this->_usedProperties['maxLevel'] = \true;
            $this->maxLevel = $value['max_level'];
            unset($value['max_level']);
        }
        if (array_key_exists('buffer_size', $value)) {
            $this->_usedProperties['bufferSize'] = \true;
            $this->bufferSize = $value['buffer_size'];
            unset($value['buffer_size']);
        }
        if (array_key_exists('flush_on_overflow', $value)) {
            $this->_usedProperties['flushOnOverflow'] = \true;
            $this->flushOnOverflow = $value['flush_on_overflow'];
            unset($value['flush_on_overflow']);
        }
        if (array_key_exists('handler', $value)) {
            $this->_usedProperties['handler'] = \true;
            $this->handler = $value['handler'];
            unset($value['handler']);
        }
        if (array_key_exists('url', $value)) {
            $this->_usedProperties['url'] = \true;
            $this->url = $value['url'];
            unset($value['url']);
        }
        if (array_key_exists('exchange', $value)) {
            $this->_usedProperties['exchange'] = \true;
            $this->exchange = $value['exchange'];
            unset($value['exchange']);
        }
        if (array_key_exists('exchange_name', $value)) {
            $this->_usedProperties['exchangeName'] = \true;
            $this->exchangeName = $value['exchange_name'];
            unset($value['exchange_name']);
        }
        if (array_key_exists('room', $value)) {
            $this->_usedProperties['room'] = \true;
            $this->room = $value['room'];
            unset($value['room']);
        }
        if (array_key_exists('message_format', $value)) {
            $this->_usedProperties['messageFormat'] = \true;
            $this->messageFormat = $value['message_format'];
            unset($value['message_format']);
        }
        if (array_key_exists('api_version', $value)) {
            $this->_usedProperties['apiVersion'] = \true;
            $this->apiVersion = $value['api_version'];
            unset($value['api_version']);
        }
        if (array_key_exists('channel', $value)) {
            $this->_usedProperties['channel'] = \true;
            $this->channel = $value['channel'];
            unset($value['channel']);
        }
        if (array_key_exists('bot_name', $value)) {
            $this->_usedProperties['botName'] = \true;
            $this->botName = $value['bot_name'];
            unset($value['bot_name']);
        }
        if (array_key_exists('use_attachment', $value)) {
            $this->_usedProperties['useAttachment'] = \true;
            $this->useAttachment = $value['use_attachment'];
            unset($value['use_attachment']);
        }
        if (array_key_exists('use_short_attachment', $value)) {
            $this->_usedProperties['useShortAttachment'] = \true;
            $this->useShortAttachment = $value['use_short_attachment'];
            unset($value['use_short_attachment']);
        }
        if (array_key_exists('include_extra', $value)) {
            $this->_usedProperties['includeExtra'] = \true;
            $this->includeExtra = $value['include_extra'];
            unset($value['include_extra']);
        }
        if (array_key_exists('icon_emoji', $value)) {
            $this->_usedProperties['iconEmoji'] = \true;
            $this->iconEmoji = $value['icon_emoji'];
            unset($value['icon_emoji']);
        }
        if (array_key_exists('webhook_url', $value)) {
            $this->_usedProperties['webhookUrl'] = \true;
            $this->webhookUrl = $value['webhook_url'];
            unset($value['webhook_url']);
        }
        if (array_key_exists('exclude_fields', $value)) {
            $this->_usedProperties['excludeFields'] = \true;
            $this->excludeFields = $value['exclude_fields'];
            unset($value['exclude_fields']);
        }
        if (array_key_exists('team', $value)) {
            $this->_usedProperties['team'] = \true;
            $this->team = $value['team'];
            unset($value['team']);
        }
        if (array_key_exists('notify', $value)) {
            $this->_usedProperties['notify'] = \true;
            $this->notify = $value['notify'];
            unset($value['notify']);
        }
        if (array_key_exists('nickname', $value)) {
            $this->_usedProperties['nickname'] = \true;
            $this->nickname = $value['nickname'];
            unset($value['nickname']);
        }
        if (array_key_exists('token', $value)) {
            $this->_usedProperties['token'] = \true;
            $this->token = $value['token'];
            unset($value['token']);
        }
        if (array_key_exists('region', $value)) {
            $this->_usedProperties['region'] = \true;
            $this->region = $value['region'];
            unset($value['region']);
        }
        if (array_key_exists('source', $value)) {
            $this->_usedProperties['source'] = \true;
            $this->source = $value['source'];
            unset($value['source']);
        }
        if (array_key_exists('use_ssl', $value)) {
            $this->_usedProperties['useSsl'] = \true;
            $this->useSsl = $value['use_ssl'];
            unset($value['use_ssl']);
        }
        if (array_key_exists('user', $value)) {
            $this->_usedProperties['user'] = \true;
            $this->user = $value['user'];
            unset($value['user']);
        }
        if (array_key_exists('title', $value)) {
            $this->_usedProperties['title'] = \true;
            $this->title = $value['title'];
            unset($value['title']);
        }
        if (array_key_exists('host', $value)) {
            $this->_usedProperties['host'] = \true;
            $this->host = $value['host'];
            unset($value['host']);
        }
        if (array_key_exists('port', $value)) {
            $this->_usedProperties['port'] = \true;
            $this->port = $value['port'];
            unset($value['port']);
        }
        if (array_key_exists('config', $value)) {
            $this->_usedProperties['config'] = \true;
            $this->config = $value['config'];
            unset($value['config']);
        }
        if (array_key_exists('members', $value)) {
            $this->_usedProperties['members'] = \true;
            $this->members = $value['members'];
            unset($value['members']);
        }
        if (array_key_exists('connection_string', $value)) {
            $this->_usedProperties['connectionString'] = \true;
            $this->connectionString = $value['connection_string'];
            unset($value['connection_string']);
        }
        if (array_key_exists('timeout', $value)) {
            $this->_usedProperties['timeout'] = \true;
            $this->timeout = $value['timeout'];
            unset($value['timeout']);
        }
        if (array_key_exists('time', $value)) {
            $this->_usedProperties['time'] = \true;
            $this->time = $value['time'];
            unset($value['time']);
        }
        if (array_key_exists('deduplication_level', $value)) {
            $this->_usedProperties['deduplicationLevel'] = \true;
            $this->deduplicationLevel = $value['deduplication_level'];
            unset($value['deduplication_level']);
        }
        if (array_key_exists('store', $value)) {
            $this->_usedProperties['store'] = \true;
            $this->store = $value['store'];
            unset($value['store']);
        }
        if (array_key_exists('connection_timeout', $value)) {
            $this->_usedProperties['connectionTimeout'] = \true;
            $this->connectionTimeout = $value['connection_timeout'];
            unset($value['connection_timeout']);
        }
        if (array_key_exists('persistent', $value)) {
            $this->_usedProperties['persistent'] = \true;
            $this->persistent = $value['persistent'];
            unset($value['persistent']);
        }
        if (array_key_exists('dsn', $value)) {
            $this->_usedProperties['dsn'] = \true;
            $this->dsn = $value['dsn'];
            unset($value['dsn']);
        }
        if (array_key_exists('hub_id', $value)) {
            $this->_usedProperties['hubId'] = \true;
            $this->hubId = $value['hub_id'];
            unset($value['hub_id']);
        }
        if (array_key_exists('client_id', $value)) {
            $this->_usedProperties['clientId'] = \true;
            $this->clientId = $value['client_id'];
            unset($value['client_id']);
        }
        if (array_key_exists('auto_log_stacks', $value)) {
            $this->_usedProperties['autoLogStacks'] = \true;
            $this->autoLogStacks = $value['auto_log_stacks'];
            unset($value['auto_log_stacks']);
        }
        if (array_key_exists('release', $value)) {
            $this->_usedProperties['release'] = \true;
            $this->release = $value['release'];
            unset($value['release']);
        }
        if (array_key_exists('environment', $value)) {
            $this->_usedProperties['environment'] = \true;
            $this->environment = $value['environment'];
            unset($value['environment']);
        }
        if (array_key_exists('message_type', $value)) {
            $this->_usedProperties['messageType'] = \true;
            $this->messageType = $value['message_type'];
            unset($value['message_type']);
        }
        if (array_key_exists('parse_mode', $value)) {
            $this->_usedProperties['parseMode'] = \true;
            $this->parseMode = $value['parse_mode'];
            unset($value['parse_mode']);
        }
        if (array_key_exists('disable_webpage_preview', $value)) {
            $this->_usedProperties['disableWebpagePreview'] = \true;
            $this->disableWebpagePreview = $value['disable_webpage_preview'];
            unset($value['disable_webpage_preview']);
        }
        if (array_key_exists('disable_notification', $value)) {
            $this->_usedProperties['disableNotification'] = \true;
            $this->disableNotification = $value['disable_notification'];
            unset($value['disable_notification']);
        }
        if (array_key_exists('split_long_messages', $value)) {
            $this->_usedProperties['splitLongMessages'] = \true;
            $this->splitLongMessages = $value['split_long_messages'];
            unset($value['split_long_messages']);
        }
        if (array_key_exists('delay_between_messages', $value)) {
            $this->_usedProperties['delayBetweenMessages'] = \true;
            $this->delayBetweenMessages = $value['delay_between_messages'];
            unset($value['delay_between_messages']);
        }
        if (array_key_exists('topic', $value)) {
            $this->_usedProperties['topic'] = \true;
            $this->topic = $value['topic'];
            unset($value['topic']);
        }
        if (array_key_exists('factor', $value)) {
            $this->_usedProperties['factor'] = \true;
            $this->factor = $value['factor'];
            unset($value['factor']);
        }
        if (array_key_exists('tags', $value)) {
            $this->_usedProperties['tags'] = \true;
            $this->tags = $value['tags'];
            unset($value['tags']);
        }
        if (array_key_exists('console_formater_options', $value)) {
            $this->_usedProperties['consoleFormaterOptions'] = \true;
            $this->consoleFormaterOptions = $value['console_formater_options'];
            unset($value['console_formater_options']);
        }
        if (array_key_exists('console_formatter_options', $value)) {
            $this->_usedProperties['consoleFormatterOptions'] = \true;
            $this->consoleFormatterOptions = $value['console_formatter_options'];
            unset($value['console_formatter_options']);
        }
        if (array_key_exists('formatter', $value)) {
            $this->_usedProperties['formatter'] = \true;
            $this->formatter = $value['formatter'];
            unset($value['formatter']);
        }
        if (array_key_exists('nested', $value)) {
            $this->_usedProperties['nested'] = \true;
            $this->nested = $value['nested'];
            unset($value['nested']);
        }
        if (array_key_exists('publisher', $value)) {
            $this->_usedProperties['publisher'] = \true;
            $this->publisher = \is_array($value['publisher']) ? new \_ContaoManager\Symfony\Config\Monolog\HandlerConfig\PublisherConfig($value['publisher']) : $value['publisher'];
            unset($value['publisher']);
        }
        if (array_key_exists('mongo', $value)) {
            $this->_usedProperties['mongo'] = \true;
            $this->mongo = \is_array($value['mongo']) ? new \_ContaoManager\Symfony\Config\Monolog\HandlerConfig\MongoConfig($value['mongo']) : $value['mongo'];
            unset($value['mongo']);
        }
        if (array_key_exists('mongodb', $value)) {
            $this->_usedProperties['mongodb'] = \true;
            $this->mongodb = \is_array($value['mongodb']) ? new \_ContaoManager\Symfony\Config\Monolog\HandlerConfig\MongodbConfig($value['mongodb']) : $value['mongodb'];
            unset($value['mongodb']);
        }
        if (array_key_exists('elasticsearch', $value)) {
            $this->_usedProperties['elasticsearch'] = \true;
            $this->elasticsearch = \is_array($value['elasticsearch']) ? new \_ContaoManager\Symfony\Config\Monolog\HandlerConfig\ElasticsearchConfig($value['elasticsearch']) : $value['elasticsearch'];
            unset($value['elasticsearch']);
        }
        if (array_key_exists('index', $value)) {
            $this->_usedProperties['index'] = \true;
            $this->index = $value['index'];
            unset($value['index']);
        }
        if (array_key_exists('document_type', $value)) {
            $this->_usedProperties['documentType'] = \true;
            $this->documentType = $value['document_type'];
            unset($value['document_type']);
        }
        if (array_key_exists('ignore_error', $value)) {
            $this->_usedProperties['ignoreError'] = \true;
            $this->ignoreError = $value['ignore_error'];
            unset($value['ignore_error']);
        }
        if (array_key_exists('redis', $value)) {
            $this->_usedProperties['redis'] = \true;
            $this->redis = \is_array($value['redis']) ? new \_ContaoManager\Symfony\Config\Monolog\HandlerConfig\RedisConfig($value['redis']) : $value['redis'];
            unset($value['redis']);
        }
        if (array_key_exists('predis', $value)) {
            $this->_usedProperties['predis'] = \true;
            $this->predis = \is_array($value['predis']) ? new \_ContaoManager\Symfony\Config\Monolog\HandlerConfig\PredisConfig($value['predis']) : $value['predis'];
            unset($value['predis']);
        }
        if (array_key_exists('from_email', $value)) {
            $this->_usedProperties['fromEmail'] = \true;
            $this->fromEmail = $value['from_email'];
            unset($value['from_email']);
        }
        if (array_key_exists('to_email', $value)) {
            $this->_usedProperties['toEmail'] = \true;
            $this->toEmail = $value['to_email'];
            unset($value['to_email']);
        }
        if (array_key_exists('subject', $value)) {
            $this->_usedProperties['subject'] = \true;
            $this->subject = $value['subject'];
            unset($value['subject']);
        }
        if (array_key_exists('content_type', $value)) {
            $this->_usedProperties['contentType'] = \true;
            $this->contentType = $value['content_type'];
            unset($value['content_type']);
        }
        if (array_key_exists('headers', $value)) {
            $this->_usedProperties['headers'] = \true;
            $this->headers = $value['headers'];
            unset($value['headers']);
        }
        if (array_key_exists('mailer', $value)) {
            $this->_usedProperties['mailer'] = \true;
            $this->mailer = $value['mailer'];
            unset($value['mailer']);
        }
        if (array_key_exists('email_prototype', $value)) {
            $this->_usedProperties['emailPrototype'] = \true;
            $this->emailPrototype = \is_array($value['email_prototype']) ? new \_ContaoManager\Symfony\Config\Monolog\HandlerConfig\EmailPrototypeConfig($value['email_prototype']) : $value['email_prototype'];
            unset($value['email_prototype']);
        }
        if (array_key_exists('lazy', $value)) {
            $this->_usedProperties['lazy'] = \true;
            $this->lazy = $value['lazy'];
            unset($value['lazy']);
        }
        if (array_key_exists('verbosity_levels', $value)) {
            $this->_usedProperties['verbosityLevels'] = \true;
            $this->verbosityLevels = \is_array($value['verbosity_levels']) ? new \_ContaoManager\Symfony\Config\Monolog\HandlerConfig\VerbosityLevelsConfig($value['verbosity_levels']) : $value['verbosity_levels'];
            unset($value['verbosity_levels']);
        }
        if (array_key_exists('channels', $value)) {
            $this->_usedProperties['channels'] = \true;
            $this->channels = \is_array($value['channels']) ? new \_ContaoManager\Symfony\Config\Monolog\HandlerConfig\ChannelsConfig($value['channels']) : $value['channels'];
            unset($value['channels']);
        }
        if ([] !== $value) {
            throw new InvalidConfigurationException(sprintf('The following keys are not supported by "%s": ', __CLASS__) . implode(', ', array_keys($value)));
        }
    }
    public function toArray(): array
    {
        $output = [];
        if (isset($this->_usedProperties['type'])) {
            $output['type'] = $this->type;
        }
        if (isset($this->_usedProperties['id'])) {
            $output['id'] = $this->id;
        }
        if (isset($this->_usedProperties['enabled'])) {
            $output['enabled'] = $this->enabled;
        }
        if (isset($this->_usedProperties['priority'])) {
            $output['priority'] = $this->priority;
        }
        if (isset($this->_usedProperties['level'])) {
            $output['level'] = $this->level;
        }
        if (isset($this->_usedProperties['bubble'])) {
            $output['bubble'] = $this->bubble;
        }
        if (isset($this->_usedProperties['interactiveOnly'])) {
            $output['interactive_only'] = $this->interactiveOnly;
        }
        if (isset($this->_usedProperties['appName'])) {
            $output['app_name'] = $this->appName;
        }
        if (isset($this->_usedProperties['fillExtraContext'])) {
            $output['fill_extra_context'] = $this->fillExtraContext;
        }
        if (isset($this->_usedProperties['includeStacktraces'])) {
            $output['include_stacktraces'] = $this->includeStacktraces;
        }
        if (isset($this->_usedProperties['processPsr3Messages'])) {
            $output['process_psr_3_messages'] = $this->processPsr3Messages instanceof \_ContaoManager\Symfony\Config\Monolog\HandlerConfig\ProcessPsr3MessagesConfig ? $this->processPsr3Messages->toArray() : $this->processPsr3Messages;
        }
        if (isset($this->_usedProperties['path'])) {
            $output['path'] = $this->path;
        }
        if (isset($this->_usedProperties['filePermission'])) {
            $output['file_permission'] = $this->filePermission;
        }
        if (isset($this->_usedProperties['useLocking'])) {
            $output['use_locking'] = $this->useLocking;
        }
        if (isset($this->_usedProperties['filenameFormat'])) {
            $output['filename_format'] = $this->filenameFormat;
        }
        if (isset($this->_usedProperties['dateFormat'])) {
            $output['date_format'] = $this->dateFormat;
        }
        if (isset($this->_usedProperties['ident'])) {
            $output['ident'] = $this->ident;
        }
        if (isset($this->_usedProperties['logopts'])) {
            $output['logopts'] = $this->logopts;
        }
        if (isset($this->_usedProperties['facility'])) {
            $output['facility'] = $this->facility;
        }
        if (isset($this->_usedProperties['maxFiles'])) {
            $output['max_files'] = $this->maxFiles;
        }
        if (isset($this->_usedProperties['actionLevel'])) {
            $output['action_level'] = $this->actionLevel;
        }
        if (isset($this->_usedProperties['activationStrategy'])) {
            $output['activation_strategy'] = $this->activationStrategy;
        }
        if (isset($this->_usedProperties['stopBuffering'])) {
            $output['stop_buffering'] = $this->stopBuffering;
        }
        if (isset($this->_usedProperties['passthruLevel'])) {
            $output['passthru_level'] = $this->passthruLevel;
        }
        if (isset($this->_usedProperties['excluded404s'])) {
            $output['excluded_404s'] = $this->excluded404s;
        }
        if (isset($this->_usedProperties['excludedHttpCodes'])) {
            $output['excluded_http_codes'] = array_map(fn($v) => $v instanceof \_ContaoManager\Symfony\Config\Monolog\HandlerConfig\ExcludedHttpCodeConfig ? $v->toArray() : $v, $this->excludedHttpCodes);
        }
        if (isset($this->_usedProperties['acceptedLevels'])) {
            $output['accepted_levels'] = $this->acceptedLevels;
        }
        if (isset($this->_usedProperties['minLevel'])) {
            $output['min_level'] = $this->minLevel;
        }
        if (isset($this->_usedProperties['maxLevel'])) {
            $output['max_level'] = $this->maxLevel;
        }
        if (isset($this->_usedProperties['bufferSize'])) {
            $output['buffer_size'] = $this->bufferSize;
        }
        if (isset($this->_usedProperties['flushOnOverflow'])) {
            $output['flush_on_overflow'] = $this->flushOnOverflow;
        }
        if (isset($this->_usedProperties['handler'])) {
            $output['handler'] = $this->handler;
        }
        if (isset($this->_usedProperties['url'])) {
            $output['url'] = $this->url;
        }
        if (isset($this->_usedProperties['exchange'])) {
            $output['exchange'] = $this->exchange;
        }
        if (isset($this->_usedProperties['exchangeName'])) {
            $output['exchange_name'] = $this->exchangeName;
        }
        if (isset($this->_usedProperties['room'])) {
            $output['room'] = $this->room;
        }
        if (isset($this->_usedProperties['messageFormat'])) {
            $output['message_format'] = $this->messageFormat;
        }
        if (isset($this->_usedProperties['apiVersion'])) {
            $output['api_version'] = $this->apiVersion;
        }
        if (isset($this->_usedProperties['channel'])) {
            $output['channel'] = $this->channel;
        }
        if (isset($this->_usedProperties['botName'])) {
            $output['bot_name'] = $this->botName;
        }
        if (isset($this->_usedProperties['useAttachment'])) {
            $output['use_attachment'] = $this->useAttachment;
        }
        if (isset($this->_usedProperties['useShortAttachment'])) {
            $output['use_short_attachment'] = $this->useShortAttachment;
        }
        if (isset($this->_usedProperties['includeExtra'])) {
            $output['include_extra'] = $this->includeExtra;
        }
        if (isset($this->_usedProperties['iconEmoji'])) {
            $output['icon_emoji'] = $this->iconEmoji;
        }
        if (isset($this->_usedProperties['webhookUrl'])) {
            $output['webhook_url'] = $this->webhookUrl;
        }
        if (isset($this->_usedProperties['excludeFields'])) {
            $output['exclude_fields'] = $this->excludeFields;
        }
        if (isset($this->_usedProperties['team'])) {
            $output['team'] = $this->team;
        }
        if (isset($this->_usedProperties['notify'])) {
            $output['notify'] = $this->notify;
        }
        if (isset($this->_usedProperties['nickname'])) {
            $output['nickname'] = $this->nickname;
        }
        if (isset($this->_usedProperties['token'])) {
            $output['token'] = $this->token;
        }
        if (isset($this->_usedProperties['region'])) {
            $output['region'] = $this->region;
        }
        if (isset($this->_usedProperties['source'])) {
            $output['source'] = $this->source;
        }
        if (isset($this->_usedProperties['useSsl'])) {
            $output['use_ssl'] = $this->useSsl;
        }
        if (isset($this->_usedProperties['user'])) {
            $output['user'] = $this->user;
        }
        if (isset($this->_usedProperties['title'])) {
            $output['title'] = $this->title;
        }
        if (isset($this->_usedProperties['host'])) {
            $output['host'] = $this->host;
        }
        if (isset($this->_usedProperties['port'])) {
            $output['port'] = $this->port;
        }
        if (isset($this->_usedProperties['config'])) {
            $output['config'] = $this->config;
        }
        if (isset($this->_usedProperties['members'])) {
            $output['members'] = $this->members;
        }
        if (isset($this->_usedProperties['connectionString'])) {
            $output['connection_string'] = $this->connectionString;
        }
        if (isset($this->_usedProperties['timeout'])) {
            $output['timeout'] = $this->timeout;
        }
        if (isset($this->_usedProperties['time'])) {
            $output['time'] = $this->time;
        }
        if (isset($this->_usedProperties['deduplicationLevel'])) {
            $output['deduplication_level'] = $this->deduplicationLevel;
        }
        if (isset($this->_usedProperties['store'])) {
            $output['store'] = $this->store;
        }
        if (isset($this->_usedProperties['connectionTimeout'])) {
            $output['connection_timeout'] = $this->connectionTimeout;
        }
        if (isset($this->_usedProperties['persistent'])) {
            $output['persistent'] = $this->persistent;
        }
        if (isset($this->_usedProperties['dsn'])) {
            $output['dsn'] = $this->dsn;
        }
        if (isset($this->_usedProperties['hubId'])) {
            $output['hub_id'] = $this->hubId;
        }
        if (isset($this->_usedProperties['clientId'])) {
            $output['client_id'] = $this->clientId;
        }
        if (isset($this->_usedProperties['autoLogStacks'])) {
            $output['auto_log_stacks'] = $this->autoLogStacks;
        }
        if (isset($this->_usedProperties['release'])) {
            $output['release'] = $this->release;
        }
        if (isset($this->_usedProperties['environment'])) {
            $output['environment'] = $this->environment;
        }
        if (isset($this->_usedProperties['messageType'])) {
            $output['message_type'] = $this->messageType;
        }
        if (isset($this->_usedProperties['parseMode'])) {
            $output['parse_mode'] = $this->parseMode;
        }
        if (isset($this->_usedProperties['disableWebpagePreview'])) {
            $output['disable_webpage_preview'] = $this->disableWebpagePreview;
        }
        if (isset($this->_usedProperties['disableNotification'])) {
            $output['disable_notification'] = $this->disableNotification;
        }
        if (isset($this->_usedProperties['splitLongMessages'])) {
            $output['split_long_messages'] = $this->splitLongMessages;
        }
        if (isset($this->_usedProperties['delayBetweenMessages'])) {
            $output['delay_between_messages'] = $this->delayBetweenMessages;
        }
        if (isset($this->_usedProperties['topic'])) {
            $output['topic'] = $this->topic;
        }
        if (isset($this->_usedProperties['factor'])) {
            $output['factor'] = $this->factor;
        }
        if (isset($this->_usedProperties['tags'])) {
            $output['tags'] = $this->tags;
        }
        if (isset($this->_usedProperties['consoleFormaterOptions'])) {
            $output['console_formater_options'] = $this->consoleFormaterOptions;
        }
        if (isset($this->_usedProperties['consoleFormatterOptions'])) {
            $output['console_formatter_options'] = $this->consoleFormatterOptions;
        }
        if (isset($this->_usedProperties['formatter'])) {
            $output['formatter'] = $this->formatter;
        }
        if (isset($this->_usedProperties['nested'])) {
            $output['nested'] = $this->nested;
        }
        if (isset($this->_usedProperties['publisher'])) {
            $output['publisher'] = $this->publisher instanceof \_ContaoManager\Symfony\Config\Monolog\HandlerConfig\PublisherConfig ? $this->publisher->toArray() : $this->publisher;
        }
        if (isset($this->_usedProperties['mongo'])) {
            $output['mongo'] = $this->mongo instanceof \_ContaoManager\Symfony\Config\Monolog\HandlerConfig\MongoConfig ? $this->mongo->toArray() : $this->mongo;
        }
        if (isset($this->_usedProperties['mongodb'])) {
            $output['mongodb'] = $this->mongodb instanceof \_ContaoManager\Symfony\Config\Monolog\HandlerConfig\MongodbConfig ? $this->mongodb->toArray() : $this->mongodb;
        }
        if (isset($this->_usedProperties['elasticsearch'])) {
            $output['elasticsearch'] = $this->elasticsearch instanceof \_ContaoManager\Symfony\Config\Monolog\HandlerConfig\ElasticsearchConfig ? $this->elasticsearch->toArray() : $this->elasticsearch;
        }
        if (isset($this->_usedProperties['index'])) {
            $output['index'] = $this->index;
        }
        if (isset($this->_usedProperties['documentType'])) {
            $output['document_type'] = $this->documentType;
        }
        if (isset($this->_usedProperties['ignoreError'])) {
            $output['ignore_error'] = $this->ignoreError;
        }
        if (isset($this->_usedProperties['redis'])) {
            $output['redis'] = $this->redis instanceof \_ContaoManager\Symfony\Config\Monolog\HandlerConfig\RedisConfig ? $this->redis->toArray() : $this->redis;
        }
        if (isset($this->_usedProperties['predis'])) {
            $output['predis'] = $this->predis instanceof \_ContaoManager\Symfony\Config\Monolog\HandlerConfig\PredisConfig ? $this->predis->toArray() : $this->predis;
        }
        if (isset($this->_usedProperties['fromEmail'])) {
            $output['from_email'] = $this->fromEmail;
        }
        if (isset($this->_usedProperties['toEmail'])) {
            $output['to_email'] = $this->toEmail;
        }
        if (isset($this->_usedProperties['subject'])) {
            $output['subject'] = $this->subject;
        }
        if (isset($this->_usedProperties['contentType'])) {
            $output['content_type'] = $this->contentType;
        }
        if (isset($this->_usedProperties['headers'])) {
            $output['headers'] = $this->headers;
        }
        if (isset($this->_usedProperties['mailer'])) {
            $output['mailer'] = $this->mailer;
        }
        if (isset($this->_usedProperties['emailPrototype'])) {
            $output['email_prototype'] = $this->emailPrototype instanceof \_ContaoManager\Symfony\Config\Monolog\HandlerConfig\EmailPrototypeConfig ? $this->emailPrototype->toArray() : $this->emailPrototype;
        }
        if (isset($this->_usedProperties['lazy'])) {
            $output['lazy'] = $this->lazy;
        }
        if (isset($this->_usedProperties['verbosityLevels'])) {
            $output['verbosity_levels'] = $this->verbosityLevels instanceof \_ContaoManager\Symfony\Config\Monolog\HandlerConfig\VerbosityLevelsConfig ? $this->verbosityLevels->toArray() : $this->verbosityLevels;
        }
        if (isset($this->_usedProperties['channels'])) {
            $output['channels'] = $this->channels instanceof \_ContaoManager\Symfony\Config\Monolog\HandlerConfig\ChannelsConfig ? $this->channels->toArray() : $this->channels;
        }
        return $output;
    }
}
<?php

namespace _ContaoManager\Symfony\Config\Monolog\HandlerConfig;

use _ContaoManager\Symfony\Component\Config\Loader\ParamConfigurator;
use _ContaoManager\Symfony\Component\Config\Definition\Exception\InvalidConfigurationException;
/**
 * This class is automatically generated to help in creating a config.
 */
class ProcessPsr3MessagesConfig
{
    private $enabled;
    private $dateFormat;
    private $removeUsedContextFields;
    private $_usedProperties = [];
    /**
     * @default null
     * @param ParamConfigurator|bool $value
     * @return $this
     */
    public function enabled($value): static
    {
        $this->_usedProperties['enabled'] = \true;
        $this->enabled = $value;
        return $this;
    }
    /**
     * @default null
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function dateFormat($value): static
    {
        $this->_usedProperties['dateFormat'] = \true;
        $this->dateFormat = $value;
        return $this;
    }
    /**
     * @default null
     * @param ParamConfigurator|bool $value
     * @return $this
     */
    public function removeUsedContextFields($value): static
    {
        $this->_usedProperties['removeUsedContextFields'] = \true;
        $this->removeUsedContextFields = $value;
        return $this;
    }
    public function __construct(array $value = [])
    {
        if (array_key_exists('enabled', $value)) {
            $this->_usedProperties['enabled'] = \true;
            $this->enabled = $value['enabled'];
            unset($value['enabled']);
        }
        if (array_key_exists('date_format', $value)) {
            $this->_usedProperties['dateFormat'] = \true;
            $this->dateFormat = $value['date_format'];
            unset($value['date_format']);
        }
        if (array_key_exists('remove_used_context_fields', $value)) {
            $this->_usedProperties['removeUsedContextFields'] = \true;
            $this->removeUsedContextFields = $value['remove_used_context_fields'];
            unset($value['remove_used_context_fields']);
        }
        if ([] !== $value) {
            throw new InvalidConfigurationException(sprintf('The following keys are not supported by "%s": ', __CLASS__) . implode(', ', array_keys($value)));
        }
    }
    public function toArray(): array
    {
        $output = [];
        if (isset($this->_usedProperties['enabled'])) {
            $output['enabled'] = $this->enabled;
        }
        if (isset($this->_usedProperties['dateFormat'])) {
            $output['date_format'] = $this->dateFormat;
        }
        if (isset($this->_usedProperties['removeUsedContextFields'])) {
            $output['remove_used_context_fields'] = $this->removeUsedContextFields;
        }
        return $output;
    }
}
<?php

namespace _ContaoManager\Symfony\Config\Monolog\HandlerConfig;

use _ContaoManager\Symfony\Component\Config\Loader\ParamConfigurator;
use _ContaoManager\Symfony\Component\Config\Definition\Exception\InvalidConfigurationException;
/**
 * This class is automatically generated to help in creating a config.
 */
class PublisherConfig
{
    private $id;
    private $hostname;
    private $port;
    private $chunkSize;
    private $encoder;
    private $_usedProperties = [];
    /**
     * @default null
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function id($value): static
    {
        $this->_usedProperties['id'] = \true;
        $this->id = $value;
        return $this;
    }
    /**
     * @default null
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function hostname($value): static
    {
        $this->_usedProperties['hostname'] = \true;
        $this->hostname = $value;
        return $this;
    }
    /**
     * @default 12201
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function port($value): static
    {
        $this->_usedProperties['port'] = \true;
        $this->port = $value;
        return $this;
    }
    /**
     * @default 1420
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function chunkSize($value): static
    {
        $this->_usedProperties['chunkSize'] = \true;
        $this->chunkSize = $value;
        return $this;
    }
    /**
     * @default null
     * @param ParamConfigurator|'json'|'compressed_json' $value
     * @return $this
     */
    public function encoder($value): static
    {
        $this->_usedProperties['encoder'] = \true;
        $this->encoder = $value;
        return $this;
    }
    public function __construct(array $value = [])
    {
        if (array_key_exists('id', $value)) {
            $this->_usedProperties['id'] = \true;
            $this->id = $value['id'];
            unset($value['id']);
        }
        if (array_key_exists('hostname', $value)) {
            $this->_usedProperties['hostname'] = \true;
            $this->hostname = $value['hostname'];
            unset($value['hostname']);
        }
        if (array_key_exists('port', $value)) {
            $this->_usedProperties['port'] = \true;
            $this->port = $value['port'];
            unset($value['port']);
        }
        if (array_key_exists('chunk_size', $value)) {
            $this->_usedProperties['chunkSize'] = \true;
            $this->chunkSize = $value['chunk_size'];
            unset($value['chunk_size']);
        }
        if (array_key_exists('encoder', $value)) {
            $this->_usedProperties['encoder'] = \true;
            $this->encoder = $value['encoder'];
            unset($value['encoder']);
        }
        if ([] !== $value) {
            throw new InvalidConfigurationException(sprintf('The following keys are not supported by "%s": ', __CLASS__) . implode(', ', array_keys($value)));
        }
    }
    public function toArray(): array
    {
        $output = [];
        if (isset($this->_usedProperties['id'])) {
            $output['id'] = $this->id;
        }
        if (isset($this->_usedProperties['hostname'])) {
            $output['hostname'] = $this->hostname;
        }
        if (isset($this->_usedProperties['port'])) {
            $output['port'] = $this->port;
        }
        if (isset($this->_usedProperties['chunkSize'])) {
            $output['chunk_size'] = $this->chunkSize;
        }
        if (isset($this->_usedProperties['encoder'])) {
            $output['encoder'] = $this->encoder;
        }
        return $output;
    }
}
<?php

namespace _ContaoManager\Symfony\Config\Monolog\HandlerConfig;

use _ContaoManager\Symfony\Component\Config\Loader\ParamConfigurator;
use _ContaoManager\Symfony\Component\Config\Definition\Exception\InvalidConfigurationException;
/**
 * This class is automatically generated to help in creating a config.
 */
class RedisConfig
{
    private $id;
    private $host;
    private $password;
    private $port;
    private $database;
    private $keyName;
    private $_usedProperties = [];
    /**
     * @default null
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function id($value): static
    {
        $this->_usedProperties['id'] = \true;
        $this->id = $value;
        return $this;
    }
    /**
     * @default null
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function host($value): static
    {
        $this->_usedProperties['host'] = \true;
        $this->host = $value;
        return $this;
    }
    /**
     * @default null
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function password($value): static
    {
        $this->_usedProperties['password'] = \true;
        $this->password = $value;
        return $this;
    }
    /**
     * @default 6379
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function port($value): static
    {
        $this->_usedProperties['port'] = \true;
        $this->port = $value;
        return $this;
    }
    /**
     * @default 0
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function database($value): static
    {
        $this->_usedProperties['database'] = \true;
        $this->database = $value;
        return $this;
    }
    /**
     * @default 'monolog_redis'
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function keyName($value): static
    {
        $this->_usedProperties['keyName'] = \true;
        $this->keyName = $value;
        return $this;
    }
    public function __construct(array $value = [])
    {
        if (array_key_exists('id', $value)) {
            $this->_usedProperties['id'] = \true;
            $this->id = $value['id'];
            unset($value['id']);
        }
        if (array_key_exists('host', $value)) {
            $this->_usedProperties['host'] = \true;
            $this->host = $value['host'];
            unset($value['host']);
        }
        if (array_key_exists('password', $value)) {
            $this->_usedProperties['password'] = \true;
            $this->password = $value['password'];
            unset($value['password']);
        }
        if (array_key_exists('port', $value)) {
            $this->_usedProperties['port'] = \true;
            $this->port = $value['port'];
            unset($value['port']);
        }
        if (array_key_exists('database', $value)) {
            $this->_usedProperties['database'] = \true;
            $this->database = $value['database'];
            unset($value['database']);
        }
        if (array_key_exists('key_name', $value)) {
            $this->_usedProperties['keyName'] = \true;
            $this->keyName = $value['key_name'];
            unset($value['key_name']);
        }
        if ([] !== $value) {
            throw new InvalidConfigurationException(sprintf('The following keys are not supported by "%s": ', __CLASS__) . implode(', ', array_keys($value)));
        }
    }
    public function toArray(): array
    {
        $output = [];
        if (isset($this->_usedProperties['id'])) {
            $output['id'] = $this->id;
        }
        if (isset($this->_usedProperties['host'])) {
            $output['host'] = $this->host;
        }
        if (isset($this->_usedProperties['password'])) {
            $output['password'] = $this->password;
        }
        if (isset($this->_usedProperties['port'])) {
            $output['port'] = $this->port;
        }
        if (isset($this->_usedProperties['database'])) {
            $output['database'] = $this->database;
        }
        if (isset($this->_usedProperties['keyName'])) {
            $output['key_name'] = $this->keyName;
        }
        return $output;
    }
}
<?php

namespace _ContaoManager\Symfony\Config\Monolog\HandlerConfig;

use _ContaoManager\Symfony\Component\Config\Loader\ParamConfigurator;
use _ContaoManager\Symfony\Component\Config\Definition\Exception\InvalidConfigurationException;
/**
 * This class is automatically generated to help in creating a config.
 */
class ElasticsearchConfig
{
    private $id;
    private $hosts;
    private $host;
    private $port;
    private $transport;
    private $user;
    private $password;
    private $_usedProperties = [];
    /**
     * @default null
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function id($value): static
    {
        $this->_usedProperties['id'] = \true;
        $this->id = $value;
        return $this;
    }
    /**
     * @param ParamConfigurator|list<ParamConfigurator|mixed> $value
     *
     * @return $this
     */
    public function hosts(ParamConfigurator|array $value): static
    {
        $this->_usedProperties['hosts'] = \true;
        $this->hosts = $value;
        return $this;
    }
    /**
     * @default null
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function host($value): static
    {
        $this->_usedProperties['host'] = \true;
        $this->host = $value;
        return $this;
    }
    /**
     * @default 9200
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function port($value): static
    {
        $this->_usedProperties['port'] = \true;
        $this->port = $value;
        return $this;
    }
    /**
     * @default 'Http'
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function transport($value): static
    {
        $this->_usedProperties['transport'] = \true;
        $this->transport = $value;
        return $this;
    }
    /**
     * @default null
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function user($value): static
    {
        $this->_usedProperties['user'] = \true;
        $this->user = $value;
        return $this;
    }
    /**
     * @default null
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function password($value): static
    {
        $this->_usedProperties['password'] = \true;
        $this->password = $value;
        return $this;
    }
    public function __construct(array $value = [])
    {
        if (array_key_exists('id', $value)) {
            $this->_usedProperties['id'] = \true;
            $this->id = $value['id'];
            unset($value['id']);
        }
        if (array_key_exists('hosts', $value)) {
            $this->_usedProperties['hosts'] = \true;
            $this->hosts = $value['hosts'];
            unset($value['hosts']);
        }
        if (array_key_exists('host', $value)) {
            $this->_usedProperties['host'] = \true;
            $this->host = $value['host'];
            unset($value['host']);
        }
        if (array_key_exists('port', $value)) {
            $this->_usedProperties['port'] = \true;
            $this->port = $value['port'];
            unset($value['port']);
        }
        if (array_key_exists('transport', $value)) {
            $this->_usedProperties['transport'] = \true;
            $this->transport = $value['transport'];
            unset($value['transport']);
        }
        if (array_key_exists('user', $value)) {
            $this->_usedProperties['user'] = \true;
            $this->user = $value['user'];
            unset($value['user']);
        }
        if (array_key_exists('password', $value)) {
            $this->_usedProperties['password'] = \true;
            $this->password = $value['password'];
            unset($value['password']);
        }
        if ([] !== $value) {
            throw new InvalidConfigurationException(sprintf('The following keys are not supported by "%s": ', __CLASS__) . implode(', ', array_keys($value)));
        }
    }
    public function toArray(): array
    {
        $output = [];
        if (isset($this->_usedProperties['id'])) {
            $output['id'] = $this->id;
        }
        if (isset($this->_usedProperties['hosts'])) {
            $output['hosts'] = $this->hosts;
        }
        if (isset($this->_usedProperties['host'])) {
            $output['host'] = $this->host;
        }
        if (isset($this->_usedProperties['port'])) {
            $output['port'] = $this->port;
        }
        if (isset($this->_usedProperties['transport'])) {
            $output['transport'] = $this->transport;
        }
        if (isset($this->_usedProperties['user'])) {
            $output['user'] = $this->user;
        }
        if (isset($this->_usedProperties['password'])) {
            $output['password'] = $this->password;
        }
        return $output;
    }
}
<?php

namespace _ContaoManager\Symfony\Config\Monolog\HandlerConfig;

use _ContaoManager\Symfony\Component\Config\Loader\ParamConfigurator;
use _ContaoManager\Symfony\Component\Config\Definition\Exception\InvalidConfigurationException;
/**
 * This class is automatically generated to help in creating a config.
 */
class EmailPrototypeConfig
{
    private $id;
    private $method;
    private $_usedProperties = [];
    /**
     * @default null
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function id($value): static
    {
        $this->_usedProperties['id'] = \true;
        $this->id = $value;
        return $this;
    }
    /**
     * @default null
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function method($value): static
    {
        $this->_usedProperties['method'] = \true;
        $this->method = $value;
        return $this;
    }
    public function __construct(array $value = [])
    {
        if (array_key_exists('id', $value)) {
            $this->_usedProperties['id'] = \true;
            $this->id = $value['id'];
            unset($value['id']);
        }
        if (array_key_exists('method', $value)) {
            $this->_usedProperties['method'] = \true;
            $this->method = $value['method'];
            unset($value['method']);
        }
        if ([] !== $value) {
            throw new InvalidConfigurationException(sprintf('The following keys are not supported by "%s": ', __CLASS__) . implode(', ', array_keys($value)));
        }
    }
    public function toArray(): array
    {
        $output = [];
        if (isset($this->_usedProperties['id'])) {
            $output['id'] = $this->id;
        }
        if (isset($this->_usedProperties['method'])) {
            $output['method'] = $this->method;
        }
        return $output;
    }
}
<?php

namespace _ContaoManager\Symfony\Config\Monolog\HandlerConfig;

use _ContaoManager\Symfony\Component\Config\Loader\ParamConfigurator;
use _ContaoManager\Symfony\Component\Config\Definition\Exception\InvalidConfigurationException;
/**
 * This class is automatically generated to help in creating a config.
 */
class MongodbConfig
{
    private $id;
    private $uri;
    private $username;
    private $password;
    private $database;
    private $collection;
    private $_usedProperties = [];
    /**
     * ID of a MongoDB\Client service
     * @example doctrine_mongodb.odm.logs_connection
     * @default null
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function id($value): static
    {
        $this->_usedProperties['id'] = \true;
        $this->id = $value;
        return $this;
    }
    /**
     * @default null
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function uri($value): static
    {
        $this->_usedProperties['uri'] = \true;
        $this->uri = $value;
        return $this;
    }
    /**
     * @default null
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function username($value): static
    {
        $this->_usedProperties['username'] = \true;
        $this->username = $value;
        return $this;
    }
    /**
     * @default null
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function password($value): static
    {
        $this->_usedProperties['password'] = \true;
        $this->password = $value;
        return $this;
    }
    /**
     * @default 'monolog'
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function database($value): static
    {
        $this->_usedProperties['database'] = \true;
        $this->database = $value;
        return $this;
    }
    /**
     * @default 'logs'
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function collection($value): static
    {
        $this->_usedProperties['collection'] = \true;
        $this->collection = $value;
        return $this;
    }
    public function __construct(array $value = [])
    {
        if (array_key_exists('id', $value)) {
            $this->_usedProperties['id'] = \true;
            $this->id = $value['id'];
            unset($value['id']);
        }
        if (array_key_exists('uri', $value)) {
            $this->_usedProperties['uri'] = \true;
            $this->uri = $value['uri'];
            unset($value['uri']);
        }
        if (array_key_exists('username', $value)) {
            $this->_usedProperties['username'] = \true;
            $this->username = $value['username'];
            unset($value['username']);
        }
        if (array_key_exists('password', $value)) {
            $this->_usedProperties['password'] = \true;
            $this->password = $value['password'];
            unset($value['password']);
        }
        if (array_key_exists('database', $value)) {
            $this->_usedProperties['database'] = \true;
            $this->database = $value['database'];
            unset($value['database']);
        }
        if (array_key_exists('collection', $value)) {
            $this->_usedProperties['collection'] = \true;
            $this->collection = $value['collection'];
            unset($value['collection']);
        }
        if ([] !== $value) {
            throw new InvalidConfigurationException(sprintf('The following keys are not supported by "%s": ', __CLASS__) . implode(', ', array_keys($value)));
        }
    }
    public function toArray(): array
    {
        $output = [];
        if (isset($this->_usedProperties['id'])) {
            $output['id'] = $this->id;
        }
        if (isset($this->_usedProperties['uri'])) {
            $output['uri'] = $this->uri;
        }
        if (isset($this->_usedProperties['username'])) {
            $output['username'] = $this->username;
        }
        if (isset($this->_usedProperties['password'])) {
            $output['password'] = $this->password;
        }
        if (isset($this->_usedProperties['database'])) {
            $output['database'] = $this->database;
        }
        if (isset($this->_usedProperties['collection'])) {
            $output['collection'] = $this->collection;
        }
        return $output;
    }
}
<?php

namespace _ContaoManager\Symfony\Config\Monolog\HandlerConfig;

use _ContaoManager\Symfony\Component\Config\Loader\ParamConfigurator;
use _ContaoManager\Symfony\Component\Config\Definition\Exception\InvalidConfigurationException;
/**
 * This class is automatically generated to help in creating a config.
 */
class MongoConfig
{
    private $id;
    private $host;
    private $port;
    private $user;
    private $pass;
    private $database;
    private $collection;
    private $_usedProperties = [];
    /**
     * @default null
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function id($value): static
    {
        $this->_usedProperties['id'] = \true;
        $this->id = $value;
        return $this;
    }
    /**
     * @default null
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function host($value): static
    {
        $this->_usedProperties['host'] = \true;
        $this->host = $value;
        return $this;
    }
    /**
     * @default 27017
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function port($value): static
    {
        $this->_usedProperties['port'] = \true;
        $this->port = $value;
        return $this;
    }
    /**
     * @default null
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function user($value): static
    {
        $this->_usedProperties['user'] = \true;
        $this->user = $value;
        return $this;
    }
    /**
     * @default null
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function pass($value): static
    {
        $this->_usedProperties['pass'] = \true;
        $this->pass = $value;
        return $this;
    }
    /**
     * @default 'monolog'
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function database($value): static
    {
        $this->_usedProperties['database'] = \true;
        $this->database = $value;
        return $this;
    }
    /**
     * @default 'logs'
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function collection($value): static
    {
        $this->_usedProperties['collection'] = \true;
        $this->collection = $value;
        return $this;
    }
    public function __construct(array $value = [])
    {
        if (array_key_exists('id', $value)) {
            $this->_usedProperties['id'] = \true;
            $this->id = $value['id'];
            unset($value['id']);
        }
        if (array_key_exists('host', $value)) {
            $this->_usedProperties['host'] = \true;
            $this->host = $value['host'];
            unset($value['host']);
        }
        if (array_key_exists('port', $value)) {
            $this->_usedProperties['port'] = \true;
            $this->port = $value['port'];
            unset($value['port']);
        }
        if (array_key_exists('user', $value)) {
            $this->_usedProperties['user'] = \true;
            $this->user = $value['user'];
            unset($value['user']);
        }
        if (array_key_exists('pass', $value)) {
            $this->_usedProperties['pass'] = \true;
            $this->pass = $value['pass'];
            unset($value['pass']);
        }
        if (array_key_exists('database', $value)) {
            $this->_usedProperties['database'] = \true;
            $this->database = $value['database'];
            unset($value['database']);
        }
        if (array_key_exists('collection', $value)) {
            $this->_usedProperties['collection'] = \true;
            $this->collection = $value['collection'];
            unset($value['collection']);
        }
        if ([] !== $value) {
            throw new InvalidConfigurationException(sprintf('The following keys are not supported by "%s": ', __CLASS__) . implode(', ', array_keys($value)));
        }
    }
    public function toArray(): array
    {
        $output = [];
        if (isset($this->_usedProperties['id'])) {
            $output['id'] = $this->id;
        }
        if (isset($this->_usedProperties['host'])) {
            $output['host'] = $this->host;
        }
        if (isset($this->_usedProperties['port'])) {
            $output['port'] = $this->port;
        }
        if (isset($this->_usedProperties['user'])) {
            $output['user'] = $this->user;
        }
        if (isset($this->_usedProperties['pass'])) {
            $output['pass'] = $this->pass;
        }
        if (isset($this->_usedProperties['database'])) {
            $output['database'] = $this->database;
        }
        if (isset($this->_usedProperties['collection'])) {
            $output['collection'] = $this->collection;
        }
        return $output;
    }
}
<?php

namespace _ContaoManager\Symfony\Config\Monolog\HandlerConfig;

use _ContaoManager\Symfony\Component\Config\Loader\ParamConfigurator;
use _ContaoManager\Symfony\Component\Config\Definition\Exception\InvalidConfigurationException;
/**
 * This class is automatically generated to help in creating a config.
 */
class VerbosityLevelsConfig
{
    private $vERBOSITYQUIET;
    private $vERBOSITYNORMAL;
    private $vERBOSITYVERBOSE;
    private $vERBOSITYVERYVERBOSE;
    private $vERBOSITYDEBUG;
    private $_usedProperties = [];
    /**
     * @default 'ERROR'
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function vERBOSITYQUIET($value): static
    {
        $this->_usedProperties['vERBOSITYQUIET'] = \true;
        $this->vERBOSITYQUIET = $value;
        return $this;
    }
    /**
     * @default 'WARNING'
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function vERBOSITYNORMAL($value): static
    {
        $this->_usedProperties['vERBOSITYNORMAL'] = \true;
        $this->vERBOSITYNORMAL = $value;
        return $this;
    }
    /**
     * @default 'NOTICE'
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function vERBOSITYVERBOSE($value): static
    {
        $this->_usedProperties['vERBOSITYVERBOSE'] = \true;
        $this->vERBOSITYVERBOSE = $value;
        return $this;
    }
    /**
     * @default 'INFO'
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function vERBOSITYVERYVERBOSE($value): static
    {
        $this->_usedProperties['vERBOSITYVERYVERBOSE'] = \true;
        $this->vERBOSITYVERYVERBOSE = $value;
        return $this;
    }
    /**
     * @default 'DEBUG'
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function vERBOSITYDEBUG($value): static
    {
        $this->_usedProperties['vERBOSITYDEBUG'] = \true;
        $this->vERBOSITYDEBUG = $value;
        return $this;
    }
    public function __construct(array $value = [])
    {
        if (array_key_exists('VERBOSITY_QUIET', $value)) {
            $this->_usedProperties['vERBOSITYQUIET'] = \true;
            $this->vERBOSITYQUIET = $value['VERBOSITY_QUIET'];
            unset($value['VERBOSITY_QUIET']);
        }
        if (array_key_exists('VERBOSITY_NORMAL', $value)) {
            $this->_usedProperties['vERBOSITYNORMAL'] = \true;
            $this->vERBOSITYNORMAL = $value['VERBOSITY_NORMAL'];
            unset($value['VERBOSITY_NORMAL']);
        }
        if (array_key_exists('VERBOSITY_VERBOSE', $value)) {
            $this->_usedProperties['vERBOSITYVERBOSE'] = \true;
            $this->vERBOSITYVERBOSE = $value['VERBOSITY_VERBOSE'];
            unset($value['VERBOSITY_VERBOSE']);
        }
        if (array_key_exists('VERBOSITY_VERY_VERBOSE', $value)) {
            $this->_usedProperties['vERBOSITYVERYVERBOSE'] = \true;
            $this->vERBOSITYVERYVERBOSE = $value['VERBOSITY_VERY_VERBOSE'];
            unset($value['VERBOSITY_VERY_VERBOSE']);
        }
        if (array_key_exists('VERBOSITY_DEBUG', $value)) {
            $this->_usedProperties['vERBOSITYDEBUG'] = \true;
            $this->vERBOSITYDEBUG = $value['VERBOSITY_DEBUG'];
            unset($value['VERBOSITY_DEBUG']);
        }
        if ([] !== $value) {
            throw new InvalidConfigurationException(sprintf('The following keys are not supported by "%s": ', __CLASS__) . implode(', ', array_keys($value)));
        }
    }
    public function toArray(): array
    {
        $output = [];
        if (isset($this->_usedProperties['vERBOSITYQUIET'])) {
            $output['VERBOSITY_QUIET'] = $this->vERBOSITYQUIET;
        }
        if (isset($this->_usedProperties['vERBOSITYNORMAL'])) {
            $output['VERBOSITY_NORMAL'] = $this->vERBOSITYNORMAL;
        }
        if (isset($this->_usedProperties['vERBOSITYVERBOSE'])) {
            $output['VERBOSITY_VERBOSE'] = $this->vERBOSITYVERBOSE;
        }
        if (isset($this->_usedProperties['vERBOSITYVERYVERBOSE'])) {
            $output['VERBOSITY_VERY_VERBOSE'] = $this->vERBOSITYVERYVERBOSE;
        }
        if (isset($this->_usedProperties['vERBOSITYDEBUG'])) {
            $output['VERBOSITY_DEBUG'] = $this->vERBOSITYDEBUG;
        }
        return $output;
    }
}
<?php

namespace _ContaoManager\Symfony\Config\Monolog\HandlerConfig;

use _ContaoManager\Symfony\Component\Config\Loader\ParamConfigurator;
use _ContaoManager\Symfony\Component\Config\Definition\Exception\InvalidConfigurationException;
/**
 * This class is automatically generated to help in creating a config.
 */
class PredisConfig
{
    private $id;
    private $host;
    private $_usedProperties = [];
    /**
     * @default null
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function id($value): static
    {
        $this->_usedProperties['id'] = \true;
        $this->id = $value;
        return $this;
    }
    /**
     * @default null
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function host($value): static
    {
        $this->_usedProperties['host'] = \true;
        $this->host = $value;
        return $this;
    }
    public function __construct(array $value = [])
    {
        if (array_key_exists('id', $value)) {
            $this->_usedProperties['id'] = \true;
            $this->id = $value['id'];
            unset($value['id']);
        }
        if (array_key_exists('host', $value)) {
            $this->_usedProperties['host'] = \true;
            $this->host = $value['host'];
            unset($value['host']);
        }
        if ([] !== $value) {
            throw new InvalidConfigurationException(sprintf('The following keys are not supported by "%s": ', __CLASS__) . implode(', ', array_keys($value)));
        }
    }
    public function toArray(): array
    {
        $output = [];
        if (isset($this->_usedProperties['id'])) {
            $output['id'] = $this->id;
        }
        if (isset($this->_usedProperties['host'])) {
            $output['host'] = $this->host;
        }
        return $output;
    }
}
<?php

namespace _ContaoManager\Symfony\Config\Monolog\HandlerConfig;

use _ContaoManager\Symfony\Component\Config\Loader\ParamConfigurator;
use _ContaoManager\Symfony\Component\Config\Definition\Exception\InvalidConfigurationException;
/**
 * This class is automatically generated to help in creating a config.
 */
class ExcludedHttpCodeConfig
{
    private $code;
    private $urls;
    private $_usedProperties = [];
    /**
     * @default null
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function code($value): static
    {
        $this->_usedProperties['code'] = \true;
        $this->code = $value;
        return $this;
    }
    /**
     * @param ParamConfigurator|list<ParamConfigurator|mixed> $value
     *
     * @return $this
     */
    public function urls(ParamConfigurator|array $value): static
    {
        $this->_usedProperties['urls'] = \true;
        $this->urls = $value;
        return $this;
    }
    public function __construct(array $value = [])
    {
        if (array_key_exists('code', $value)) {
            $this->_usedProperties['code'] = \true;
            $this->code = $value['code'];
            unset($value['code']);
        }
        if (array_key_exists('urls', $value)) {
            $this->_usedProperties['urls'] = \true;
            $this->urls = $value['urls'];
            unset($value['urls']);
        }
        if ([] !== $value) {
            throw new InvalidConfigurationException(sprintf('The following keys are not supported by "%s": ', __CLASS__) . implode(', ', array_keys($value)));
        }
    }
    public function toArray(): array
    {
        $output = [];
        if (isset($this->_usedProperties['code'])) {
            $output['code'] = $this->code;
        }
        if (isset($this->_usedProperties['urls'])) {
            $output['urls'] = $this->urls;
        }
        return $output;
    }
}
<?php

namespace _ContaoManager\Symfony\Config\Monolog\HandlerConfig;

use _ContaoManager\Symfony\Component\Config\Loader\ParamConfigurator;
use _ContaoManager\Symfony\Component\Config\Definition\Exception\InvalidConfigurationException;
/**
 * This class is automatically generated to help in creating a config.
 */
class ChannelsConfig
{
    private $type;
    private $elements;
    private $_usedProperties = [];
    /**
     * @default null
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function type($value): static
    {
        $this->_usedProperties['type'] = \true;
        $this->type = $value;
        return $this;
    }
    /**
     * @param ParamConfigurator|list<ParamConfigurator|mixed> $value
     *
     * @return $this
     */
    public function elements(ParamConfigurator|array $value): static
    {
        $this->_usedProperties['elements'] = \true;
        $this->elements = $value;
        return $this;
    }
    public function __construct(array $value = [])
    {
        if (array_key_exists('type', $value)) {
            $this->_usedProperties['type'] = \true;
            $this->type = $value['type'];
            unset($value['type']);
        }
        if (array_key_exists('elements', $value)) {
            $this->_usedProperties['elements'] = \true;
            $this->elements = $value['elements'];
            unset($value['elements']);
        }
        if ([] !== $value) {
            throw new InvalidConfigurationException(sprintf('The following keys are not supported by "%s": ', __CLASS__) . implode(', ', array_keys($value)));
        }
    }
    public function toArray(): array
    {
        $output = [];
        if (isset($this->_usedProperties['type'])) {
            $output['type'] = $this->type;
        }
        if (isset($this->_usedProperties['elements'])) {
            $output['elements'] = $this->elements;
        }
        return $output;
    }
}
<?php

namespace _ContaoManager\Symfony\Config;

require_once __DIR__ . \DIRECTORY_SEPARATOR . 'Framework' . \DIRECTORY_SEPARATOR . 'CsrfProtectionConfig.php';
require_once __DIR__ . \DIRECTORY_SEPARATOR . 'Framework' . \DIRECTORY_SEPARATOR . 'FormConfig.php';
require_once __DIR__ . \DIRECTORY_SEPARATOR . 'Framework' . \DIRECTORY_SEPARATOR . 'HttpCacheConfig.php';
require_once __DIR__ . \DIRECTORY_SEPARATOR . 'Framework' . \DIRECTORY_SEPARATOR . 'EsiConfig.php';
require_once __DIR__ . \DIRECTORY_SEPARATOR . 'Framework' . \DIRECTORY_SEPARATOR . 'SsiConfig.php';
require_once __DIR__ . \DIRECTORY_SEPARATOR . 'Framework' . \DIRECTORY_SEPARATOR . 'FragmentsConfig.php';
require_once __DIR__ . \DIRECTORY_SEPARATOR . 'Framework' . \DIRECTORY_SEPARATOR . 'ProfilerConfig.php';
require_once __DIR__ . \DIRECTORY_SEPARATOR . 'Framework' . \DIRECTORY_SEPARATOR . 'WorkflowsConfig.php';
require_once __DIR__ . \DIRECTORY_SEPARATOR . 'Framework' . \DIRECTORY_SEPARATOR . 'RouterConfig.php';
require_once __DIR__ . \DIRECTORY_SEPARATOR . 'Framework' . \DIRECTORY_SEPARATOR . 'SessionConfig.php';
require_once __DIR__ . \DIRECTORY_SEPARATOR . 'Framework' . \DIRECTORY_SEPARATOR . 'RequestConfig.php';
require_once __DIR__ . \DIRECTORY_SEPARATOR . 'Framework' . \DIRECTORY_SEPARATOR . 'AssetsConfig.php';
require_once __DIR__ . \DIRECTORY_SEPARATOR . 'Framework' . \DIRECTORY_SEPARATOR . 'AssetMapperConfig.php';
require_once __DIR__ . \DIRECTORY_SEPARATOR . 'Framework' . \DIRECTORY_SEPARATOR . 'TranslatorConfig.php';
require_once __DIR__ . \DIRECTORY_SEPARATOR . 'Framework' . \DIRECTORY_SEPARATOR . 'ValidationConfig.php';
require_once __DIR__ . \DIRECTORY_SEPARATOR . 'Framework' . \DIRECTORY_SEPARATOR . 'AnnotationsConfig.php';
require_once __DIR__ . \DIRECTORY_SEPARATOR . 'Framework' . \DIRECTORY_SEPARATOR . 'SerializerConfig.php';
require_once __DIR__ . \DIRECTORY_SEPARATOR . 'Framework' . \DIRECTORY_SEPARATOR . 'PropertyAccessConfig.php';
require_once __DIR__ . \DIRECTORY_SEPARATOR . 'Framework' . \DIRECTORY_SEPARATOR . 'PropertyInfoConfig.php';
require_once __DIR__ . \DIRECTORY_SEPARATOR . 'Framework' . \DIRECTORY_SEPARATOR . 'CacheConfig.php';
require_once __DIR__ . \DIRECTORY_SEPARATOR . 'Framework' . \DIRECTORY_SEPARATOR . 'PhpErrorsConfig.php';
require_once __DIR__ . \DIRECTORY_SEPARATOR . 'Framework' . \DIRECTORY_SEPARATOR . 'ExceptionConfig.php';
require_once __DIR__ . \DIRECTORY_SEPARATOR . 'Framework' . \DIRECTORY_SEPARATOR . 'WebLinkConfig.php';
require_once __DIR__ . \DIRECTORY_SEPARATOR . 'Framework' . \DIRECTORY_SEPARATOR . 'LockConfig.php';
require_once __DIR__ . \DIRECTORY_SEPARATOR . 'Framework' . \DIRECTORY_SEPARATOR . 'SemaphoreConfig.php';
require_once __DIR__ . \DIRECTORY_SEPARATOR . 'Framework' . \DIRECTORY_SEPARATOR . 'MessengerConfig.php';
require_once __DIR__ . \DIRECTORY_SEPARATOR . 'Framework' . \DIRECTORY_SEPARATOR . 'SchedulerConfig.php';
require_once __DIR__ . \DIRECTORY_SEPARATOR . 'Framework' . \DIRECTORY_SEPARATOR . 'HttpClientConfig.php';
require_once __DIR__ . \DIRECTORY_SEPARATOR . 'Framework' . \DIRECTORY_SEPARATOR . 'MailerConfig.php';
require_once __DIR__ . \DIRECTORY_SEPARATOR . 'Framework' . \DIRECTORY_SEPARATOR . 'SecretsConfig.php';
require_once __DIR__ . \DIRECTORY_SEPARATOR . 'Framework' . \DIRECTORY_SEPARATOR . 'NotifierConfig.php';
require_once __DIR__ . \DIRECTORY_SEPARATOR . 'Framework' . \DIRECTORY_SEPARATOR . 'RateLimiterConfig.php';
require_once __DIR__ . \DIRECTORY_SEPARATOR . 'Framework' . \DIRECTORY_SEPARATOR . 'UidConfig.php';
require_once __DIR__ . \DIRECTORY_SEPARATOR . 'Framework' . \DIRECTORY_SEPARATOR . 'HtmlSanitizerConfig.php';
require_once __DIR__ . \DIRECTORY_SEPARATOR . 'Framework' . \DIRECTORY_SEPARATOR . 'WebhookConfig.php';
require_once __DIR__ . \DIRECTORY_SEPARATOR . 'Framework' . \DIRECTORY_SEPARATOR . 'RemoteeventConfig.php';
use _ContaoManager\Symfony\Component\Config\Loader\ParamConfigurator;
use _ContaoManager\Symfony\Component\Config\Definition\Exception\InvalidConfigurationException;
/**
 * This class is automatically generated to help in creating a config.
 */
class FrameworkConfig implements \_ContaoManager\Symfony\Component\Config\Builder\ConfigBuilderInterface
{
    private $secret;
    private $httpMethodOverride;
    private $trustXSendfileTypeHeader;
    private $ide;
    private $test;
    private $defaultLocale;
    private $setLocaleFromAcceptLanguage;
    private $setContentLanguageFromLocale;
    private $enabledLocales;
    private $trustedHosts;
    private $trustedProxies;
    private $trustedHeaders;
    private $errorController;
    private $handleAllThrowables;
    private $csrfProtection;
    private $form;
    private $httpCache;
    private $esi;
    private $ssi;
    private $fragments;
    private $profiler;
    private $workflows;
    private $router;
    private $session;
    private $request;
    private $assets;
    private $assetMapper;
    private $translator;
    private $validation;
    private $annotations;
    private $serializer;
    private $propertyAccess;
    private $propertyInfo;
    private $cache;
    private $phpErrors;
    private $exceptions;
    private $webLink;
    private $lock;
    private $semaphore;
    private $messenger;
    private $scheduler;
    private $disallowSearchEngineIndex;
    private $httpClient;
    private $mailer;
    private $secrets;
    private $notifier;
    private $rateLimiter;
    private $uid;
    private $htmlSanitizer;
    private $webhook;
    private $remoteevent;
    private $_usedProperties = [];
    /**
     * @default null
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function secret($value): static
    {
        $this->_usedProperties['secret'] = \true;
        $this->secret = $value;
        return $this;
    }
    /**
     * Set true to enable support for the '_method' request parameter to determine the intended HTTP method on POST requests. Note: When using the HttpCache, you need to call the method in your front controller instead
     * @default null
     * @param ParamConfigurator|bool $value
     * @return $this
     */
    public function httpMethodOverride($value): static
    {
        $this->_usedProperties['httpMethodOverride'] = \true;
        $this->httpMethodOverride = $value;
        return $this;
    }
    /**
     * Set true to enable support for xsendfile in binary file responses.
     * @default false
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function trustXSendfileTypeHeader($value): static
    {
        $this->_usedProperties['trustXSendfileTypeHeader'] = \true;
        $this->trustXSendfileTypeHeader = $value;
        return $this;
    }
    /**
     * @default null
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function ide($value): static
    {
        $this->_usedProperties['ide'] = \true;
        $this->ide = $value;
        return $this;
    }
    /**
     * @default null
     * @param ParamConfigurator|bool $value
     * @return $this
     */
    public function test($value): static
    {
        $this->_usedProperties['test'] = \true;
        $this->test = $value;
        return $this;
    }
    /**
     * @default 'en'
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function defaultLocale($value): static
    {
        $this->_usedProperties['defaultLocale'] = \true;
        $this->defaultLocale = $value;
        return $this;
    }
    /**
     * Whether to use the Accept-Language HTTP header to set the Request locale (only when the "_locale" request attribute is not passed).
     * @default false
     * @param ParamConfigurator|bool $value
     * @return $this
     */
    public function setLocaleFromAcceptLanguage($value): static
    {
        $this->_usedProperties['setLocaleFromAcceptLanguage'] = \true;
        $this->setLocaleFromAcceptLanguage = $value;
        return $this;
    }
    /**
     * Whether to set the Content-Language HTTP header on the Response using the Request locale.
     * @default false
     * @param ParamConfigurator|bool $value
     * @return $this
     */
    public function setContentLanguageFromLocale($value): static
    {
        $this->_usedProperties['setContentLanguageFromLocale'] = \true;
        $this->setContentLanguageFromLocale = $value;
        return $this;
    }
    /**
     * @param ParamConfigurator|list<ParamConfigurator|mixed> $value
     *
     * @return $this
     */
    public function enabledLocales(ParamConfigurator|array $value): static
    {
        $this->_usedProperties['enabledLocales'] = \true;
        $this->enabledLocales = $value;
        return $this;
    }
    /**
     * @param ParamConfigurator|list<ParamConfigurator|mixed>|string $value
     *
     * @return $this
     */
    public function trustedHosts(ParamConfigurator|string|array $value): static
    {
        $this->_usedProperties['trustedHosts'] = \true;
        $this->trustedHosts = $value;
        return $this;
    }
    /**
     * @default null
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function trustedProxies($value): static
    {
        $this->_usedProperties['trustedProxies'] = \true;
        $this->trustedProxies = $value;
        return $this;
    }
    /**
     * @param ParamConfigurator|list<ParamConfigurator|mixed>|string $value
     *
     * @return $this
     */
    public function trustedHeaders(ParamConfigurator|string|array $value): static
    {
        $this->_usedProperties['trustedHeaders'] = \true;
        $this->trustedHeaders = $value;
        return $this;
    }
    /**
     * @default 'error_controller'
     * @param ParamConfigurator|mixed $value
     * @return $this
     */
    public function errorController($value): static
    {
        $this->_usedProperties['errorController'] = \true;
        $this->errorController = $value;
        return $this;
    }
    /**
     * HttpKernel will handle all kinds of \Throwable
     * @default null
     * @param ParamConfigurator|bool $value
     * @return $this
     */
    public function handleAllThrowables($value): static
    {
        $this->_usedProperties['handleAllThrowables'] = \true;
        $this->handleAllThrowables = $value;
        return $this;
    }
    /**
     * @default {"enabled":null}
     */
    public function csrfProtection(array $value = []): \_ContaoManager\Symfony\Config\Framework\CsrfProtectionConfig
    {
        if (null === $this->csrfProtection) {
            $this->_usedProperties['csrfProtection'] = \true;
            $this->csrfProtection = new \_ContaoManager\Symfony\Config\Framework\CsrfProtectionConfig($value);
        } elseif (0 < \func_num_args()) {
            throw new InvalidConfigurationException('The node created by "csrfProtection()" has already been initialized. You cannot pass values the second time you call csrfProtection().');
        }
        return $this->csrfProtection;
    }
    /**
     * form configuration
     * @default {"enabled":false,"csrf_protection":{"enabled":null,"field_name":"_token"}}
     */
    public function form(array $value = []): \_ContaoManager\Symfony\Config\Framework\FormConfig
    {
        if (null === $this->form) {
            $this->_usedProperties['form'] = \true;
            $this->form = new \_ContaoManager\Symfony\Config\Framework\FormConfig($value);
        } elseif (0 < \func_num_args()) {
            throw new InvalidConfigurationException('The node created by "form()" has already been initialized. You cannot pass values the second time you call form().');
        }
        return $this->form;
    }
    /**
     * HTTP cache configuration
     * @default {"enabled":false,"debug":"%kernel.debug%","private_headers":[],"skip_response_headers":[]}
     */
    public function httpCache(array $value = []): \_ContaoManager\Symfony\Config\Framework\HttpCacheConfig
    {
        if (null === $this->httpCache) {
            $this->_usedProperties['httpCache'] = \true;
            $this->httpCache = new \_ContaoManager\Symfony\Config\Framework\HttpCacheConfig($value);
        } elseif (0 < \func_num_args()) {
            throw new InvalidConfigurationException('The node created by "httpCache()" has already been initialized. You cannot pass values the second time you call httpCache().');
        }
        return $this->httpCache;
    }
    /**
     * esi configuration
     * @default {"enabled":false}
     */
    public function esi(array $value = []): \_ContaoManager\Symfony\Config\Framework\EsiConfig
    {
        if (null === $this->esi) {
            $this->_usedProperties['esi'] = \true;
            $this->esi = new \_ContaoManager\Symfony\Config\Framework\EsiConfig($value);
        } elseif (0 < \func_num_args()) {
            throw new InvalidConfigurationException('The node created by "esi()" has already been initialized. You cannot pass values the second time you call esi().');
        }
        return $this->esi;
    }
    /**
     * ssi configuration
     * @default {"enabled":false}
     */
    public function ssi(array $value = []): \_ContaoManager\Symfony\Config\Framework\SsiConfig
    {
        if (null === $this->ssi) {
            $this->_usedProperties['ssi'] = \true;
            $this->ssi = new \_ContaoManager\Symfony\Config\Framework\SsiConfig($value);
        } elseif (0 < \func_num_args()) {
            throw new InvalidConfigurationException('The node created by "ssi()" has already been initialized. You cannot pass values the second time you call ssi().');
        }
        return $this->ssi;
    }
    /**
     * fragments configuration
     * @default {"enabled":false,"hinclude_default_template":null,"path":"\/_fragment"}
     */
    public function fragments(array $value = []): \_ContaoManager\Symfony\Config\Framework\FragmentsConfig
    {
        if (null === $this->fragments) {
            $this->_usedProperties['fragments'] = \true;
            $this->fragments = new \_ContaoManager\Symfony\Config\Framework\FragmentsConfig($value);
        } elseif (0 < \func_num_args()) {
            throw new InvalidConfigurationException('The node created by "fragments()" has already been initialized. You cannot pass values the second time you call fragments().');
        }
        return $this->fragments;
    }
    /**
     * profiler configuration
     * @default {"enabled":false,"collect":true,"collect_parameter":null,"only_exceptions":false,"only_main_requests":false,"dsn":"file:%kernel.cache_dir%\/profiler","collect_serializer_data":false}
     */
    public function profiler(array $value = []): \_ContaoManager\Symfony\Config\Framework\ProfilerConfig
    {
        if (null === $this->profiler) {
            $this->_usedProperties['profiler'] = \true;
            $this->profiler = new \_ContaoManager\Symfony\Config\Framework\ProfilerConfig($value);
        } elseif (0 < \func_num_args()) {
            throw new InvalidConfigurationException('The node created by "profiler()" has already been initialized. You cannot pass values the second time you call profiler().');
        }
        return $this->profiler;
    }
    /**
     * @template TValue of mixed
     * @param TValue $value
     * @default {"enabled":false,"workflows":[]}
     * @return \Symfony\Config\Framework\WorkflowsConfig|$this
     * @psalm-return (TValue is array ? \Symfony\Config\Framework\WorkflowsConfig : static)
     */
    public function workflows(mixed $value = []): \_ContaoManager\Symfony\Config\Framework\WorkflowsConfig|static
    {
        if (!\is_array($value)) {
            $this->_usedProperties['workflows'] = \true;
            $this->workflows = $value;
            return $this;
        }
        if (!$this->workflows instanceof \_ContaoManager\Symfony\Config\Framework\WorkflowsConfig) {
            $this->_usedProperties['workflows'] = \true;
            $this->workflows = new \_ContaoManager\Symfony\Config\Framework\WorkflowsConfig($value);
        } elseif (0 < \func_num_args()) {
            throw new InvalidConfigurationException('The node created by "workflows()" has already been initialized. You cannot pass values the second time you call workflows().');
        }
        return $this->workflows;
    }
    /**
     * router configuration
     * @default {"enabled":false,"cache_dir":"%kernel.cache_dir%","default_uri":null,"http_port":80,"https_port":443,"strict_requirements":true,"utf8":true}
     */
    public function router(array $value = []): \_ContaoManager\Symfony\Config\Framework\RouterConfig
    {
        if (null === $this->router) {
            $this->_usedProperties['router'] = \true;
            $this->router = new \_ContaoManager\Symfony\Config\Framework\RouterConfig($value);
        } elseif (0 < \func_num_args()) {
            throw new InvalidConfigurationException('The node created by "router()" has already been initialized. You cannot pass values the second time you call router().');
        }
        return $this->router;
    }
    /**
     * session configuration
     * @default {"enabled":false,"storage_factory_id":"session.storage.factory.native","cookie_httponly":true,"gc_probability":1,"metadata_update_threshold":0}
     */
    public function session(array $value = []): \_ContaoManager\Symfony\Config\Framework\SessionConfig
    {
        if (null === $this->session) {
            $this->_usedProperties['session'] = \true;
            $this->session = new \_ContaoManager\Symfony\Config\Framework\SessionConfig($value);
        } elseif (0 < \func_num_args()) {
            throw new InvalidConfigurationException('The node created by "session()" has already been initialized. You cannot pass values the second time you call session().');
        }
        return $this->session;
    }
    /**
     * request configuration
     * @default {"enabled":false,"formats":[]}
     */
    public function request(array $value = []): \_ContaoManager\Symfony\Config\Framework\RequestConfig
    {
        if (null === $this->request) {
            $this->_usedProperties['request'] = \true;
            $this->request = new \_ContaoManager\Symfony\Config\Framework\RequestConfig($value);
        } elseif (0 < \func_num_args()) {
            throw new InvalidConfigurationException('The node created by "request()" has already been initialized. You cannot pass values the second time you call request().');
        }
        return $this->request;
    }
    /**
     * assets configuration
     * @default {"enabled":false,"strict_mode":false,"version_strategy":null,"version":null,"version_format":"%%s?%%s","json_manifest_path":null,"base_path":"","base_urls":[],"packages":[]}
     */
    public function assets(array $value = []): \_ContaoManager\Symfony\Config\Framework\AssetsConfig
    {
        if (null === $this->assets) {
            $this->_usedProperties['assets'] = \true;
            $this->assets = new \_ContaoManager\Symfony\Config\Framework\AssetsConfig($value);
        } elseif (0 < \func_num_args()) {
            throw new InvalidConfigurationException('The node created by "assets()" has already been initialized. You cannot pass values the second time you call assets().');
        }
        return $this->assets;
    }
    /**
     * Asset Mapper configuration
     * @default {"enabled":false,"paths":[],"excluded_patterns":[],"exclude_dotfiles":true,"server":false,"public_prefix":"\/assets\/","missing_import_mode":"warn","extensions":[],"importmap_path":"%kernel.project_dir%\/importmap.php","importmap_polyfill":"es-module-shims","importmap_script_attributes":[],"vendor_dir":"%kernel.project_dir%\/assets\/vendor"}
     */
    public function assetMapper(array $value = []): \_ContaoManager\Symfony\Config\Framework\AssetMapperConfig
    {
        if (null === $this->assetMapper) {
            $this->_usedProperties['assetMapper'] = \true;
            $this->assetMapper = new \_ContaoManager\Symfony\Config\Framework\AssetMapperConfig($value);
        } elseif (0 < \func_num_args()) {
            throw new InvalidConfigurationException('The node created by "assetMapper()" has already been initialized. You cannot pass values the second time you call assetMapper().');
        }
        return $this->assetMapper;
    }
    /**
     * translator configuration
     * @default {"enabled":false,"fallbacks":[],"logging":false,"formatter":"translator.formatter.default","cache_dir":"%kernel.cache_dir%\/translations","default_path":"%kernel.project_dir%\/translations","paths":[],"pseudo_localization":{"enabled":false,"accents":true,"expansion_factor":1,"brackets":true,"parse_html":false,"localizable_html_attributes":[]},"providers":[]}
     */
    public function translator(array $value = []): \_ContaoManager\Symfony\Config\Framework\TranslatorConfig
    {
        if (null === $this->translator) {
            $this->_usedProperties['translator'] = \true;
            $this->translator = new \_ContaoManager\Symfony\Config\Framework\TranslatorConfig($value);
        } elseif (0 < \func_num_args()) {
            throw new InvalidConfigurationException('The node created by "translator()" has already been initialized. You cannot pass values the second time you call translator().');
        }
        return $this->translator;
    }
    /**
     * @template TValue of mixed
     * @param TValue $value
     * validation configuration
     * @default {"enabled":false,"enable_attributes":true,"static_method":["loadValidatorMetadata"],"translation_domain":"validators","mapping":{"paths":[]},"not_compromised_password":{"enabled":true,"endpoint":null},"auto_mapping":[]}
     * @return \Symfony\Config\Framework\ValidationConfig|$this
     * @psalm-return (TValue is array ? \Symfony\Config\Framework\ValidationConfig : static)
     */
    public function validation(mixed $value = []): \_ContaoManager\Symfony\Config\Framework\ValidationConfig|static
    {
        if (!\is_array($value)) {
            $this->_usedProperties['validation'] = \true;
            $this->validation = $value;
            return $this;
        }
        if (!$this->validation instanceof \_ContaoManager\Symfony\Config\Framework\ValidationConfig) {
            $this->_usedProperties['validation'] = \true;
            $this->validation = new \_ContaoManager\Symfony\Config\Framework\ValidationConfig($value);
        } elseif (0 < \func_num_args()) {
            throw new InvalidConfigurationException('The node created by "validation()" has already been initialized. You cannot pass values the second time you call validation().');
        }
        return $this->validation;
    }
    /**
     * annotation configuration
     * @default {"enabled":false,"cache":"php_array","file_cache_dir":"%kernel.cache_dir%\/annotations","debug":false}
     */
    public function annotations(array $value = []): \_ContaoManager\Symfony\Config\Framework\AnnotationsConfig
    {
        if (null === $this->annotations) {
            $this->_usedProperties['annotations'] = \true;
            $this->annotations = new \_ContaoManager\Symfony\Config\Framework\AnnotationsConfig($value);
        } elseif (0 < \func_num_args()) {
            throw new InvalidConfigurationException('The node created by "annotations()" has already been initialized. You cannot pass values the second time you call annotations().');
        }
        return $this->annotations;
    }
    /**
     * @template TValue of mixed
     * @param TValue $value
     * serializer configuration
     * @default {"enabled":true,"enable_attributes":true,"mapping":{"paths":[]},"default_context":[]}
     * @return \Symfony\Config\Framework\SerializerConfig|$this
     * @psalm-return (TValue is array ? \Symfony\Config\Framework\SerializerConfig : static)
     */
    public function serializer(mixed $value = []): \_ContaoManager\Symfony\Config\Framework\SerializerConfig|static
    {
        if (!\is_array($value)) {
            $this->_usedProperties['serializer'] = \true;
            $this->serializer = $value;
            return $this;
        }
        if (!$this->serializer instanceof \_ContaoManager\Symfony\Config\Framework\SerializerConfig) {
            $this->_usedProperties['serializer'] = \true;
            $this->serializer = new \_ContaoManager\Symfony\Config\Framework\SerializerConfig($value);
        } elseif (0 < \func_num_args()) {
            throw new InvalidConfigurationException('The node created by "serializer()" has already been initialized. You cannot pass values the second time you call serializer().');
        }
        return $this->serializer;
    }
    /**
     * Property access configuration
     * @default {"enabled":true,"magic_call":false,"magic_get":true,"magic_set":true,"throw_exception_on_invalid_index":false,"throw_exception_on_invalid_property_path":true}
     */
    public function propertyAccess(array $value = []): \_ContaoManager\Symfony\Config\Framework\PropertyAccessConfig
    {
        if (null === $this->propertyAccess) {
            $this->_usedProperties['propertyAccess'] = \true;
            $this->propertyAccess = new \_ContaoManager\Symfony\Config\Framework\PropertyAccessConfig($value);
        } elseif (0 < \func_num_args()) {
            throw new InvalidConfigurationException('The node created by "propertyAccess()" has already been initialized. You cannot pass values the second time you call propertyAccess().');
        }
        return $this->propertyAccess;
    }
    /**
     * Property info configuration
     * @default {"enabled":true}
     */
    public function propertyInfo(array $value = []): \_ContaoManager\Symfony\Config\Framework\PropertyInfoConfig
    {
        if (null === $this->propertyInfo) {
            $this->_usedProperties['propertyInfo'] = \true;
            $this->propertyInfo = new \_ContaoManager\Symfony\Config\Framework\PropertyInfoConfig($value);
        } elseif (0 < \func_num_args()) {
            throw new InvalidConfigurationException('The node created by "propertyInfo()" has already been initialized. You cannot pass values the second time you call propertyInfo().');
        }
        return $this->propertyInfo;
    }
    /**
     * Cache configuration
     * @default {"prefix_seed":"_%kernel.project_dir%.%kernel.container_class%","app":"cache.adapter.filesystem","system":"cache.adapter.system","directory":"%kernel.cache_dir%\/pools\/app","default_redis_provider":"redis:\/\/localhost","default_memcached_provider":"memcached:\/\/localhost","default_doctrine_dbal_provider":"database_connection","default_pdo_provider":null,"pools":[]}
     */
    public function cache(array $value = []): \_ContaoManager\Symfony\Config\Framework\CacheConfig
    {
        if (null === $this->cache) {
            $this->_usedProperties['cache'] = \true;
            $this->cache = new \_ContaoManager\Symfony\Config\Framework\CacheConfig($value);
        } elseif (0 < \func_num_args()) {
            throw new InvalidConfigurationException('The node created by "cache()" has already been initialized. You cannot pass values the second time you call cache().');
        }
        return $this->cache;
    }
    /**
     * PHP errors handling configuration
     * @default {"throw":false}
     */
    public function phpErrors(array $value = []): \_ContaoManager\Symfony\Config\Framework\PhpErrorsConfig
    {
        if (null === $this->phpErrors) {
            $this->_usedProperties['phpErrors'] = \true;
            $this->phpErrors = new \_ContaoManager\Symfony\Config\Framework\PhpErrorsConfig($value);
        } elseif (0 < \func_num_args()) {
            throw new InvalidConfigurationException('The node created by "phpErrors()" has already been initialized. You cannot pass values the second time you call phpErrors().');
        }
        return $this->phpErrors;
    }
    /**
     * Exception handling configuration
     */
    public function exception(string $class, array $value = []): \_ContaoManager\Symfony\Config\Framework\ExceptionConfig
    {
        if (!isset($this->exceptions[$class])) {
            $this->_usedProperties['exceptions'] = \true;
            $this->exceptions[$class] = new \_ContaoManager\Symfony\Config\Framework\ExceptionConfig($value);
        } elseif (1 < \func_num_args()) {
            throw new InvalidConfigurationException('The node created by "exception()" has already been initialized. You cannot pass values the second time you call exception().');
        }
        return $this->exceptions[$class];
    }
    /**
     * web links configuration
     * @default {"enabled":false}
     */
    public function webLink(array $value = []): \_ContaoManager\Symfony\Config\Framework\WebLinkConfig
    {
        if (null === $this->webLink) {
            $this->_usedProperties['webLink'] = \true;
            $this->webLink = new \_ContaoManager\Symfony\Config\Framework\WebLinkConfig($value);
        } elseif (0 < \func_num_args()) {
            throw new InvalidConfigurationException('The node created by "webLink()" has already been initialized. You cannot pass values the second time you call webLink().');
        }
        return $this->webLink;
    }
    /**
     * @template TValue of mixed
     * @param TValue $value
     * Lock configuration
     * @default {"enabled":false,"resources":{"default":["flock"]}}
     * @return \Symfony\Config\Framework\LockConfig|$this
     * @psalm-return (TValue is array ? \Symfony\Config\Framework\LockConfig : static)
     */
    public function lock(mixed $value = []): \_ContaoManager\Symfony\Config\Framework\LockConfig|static
    {
        if (!\is_array($value)) {
            $this->_usedProperties['lock'] = \true;
            $this->lock = $value;
            return $this;
        }
        if (!$this->lock instanceof \_ContaoManager\Symfony\Config\Framework\LockConfig) {
            $this->_usedProperties['lock'] = \true;
            $this->lock = new \_ContaoManager\Symfony\Config\Framework\LockConfig($value);
        } elseif (0 < \func_num_args()) {
            throw new InvalidConfigurationException('The node created by "lock()" has already been initialized. You cannot pass values the second time you call lock().');
        }
        return $this->lock;
    }
    /**
     * @template TValue of mixed
     * @param TValue $value
     * Semaphore configuration
     * @default {"enabled":false,"resources":[]}
     * @return \Symfony\Config\Framework\SemaphoreConfig|$this
     * @psalm-return (TValue is array ? \Symfony\Config\Framework\SemaphoreConfig : static)
     */
    public function semaphore(mixed $value = []): \_ContaoManager\Symfony\Config\Framework\SemaphoreConfig|static
    {
        if (!\is_array($value)) {
            $this->_usedProperties['semaphore'] = \true;
            $this->semaphore = $value;
            return $this;
        }
        if (!$this->semaphore instanceof \_ContaoManager\Symfony\Config\Framework\SemaphoreConfig) {
            $this->_usedProperties['semaphore'] = \true;
            $this->semaphore = new \_ContaoManager\Symfony\Config\Framework\SemaphoreConfig($value);
        } elseif (0 < \func_num_args()) {
            throw new InvalidConfigurationException('The node created by "semaphore()" has already been initialized. You cannot pass values the second time you call semaphore().');
        }
        return $this->semaphore;
    }
    /**
     * Messenger configuration
     * @default {"enabled":false,"routing":[],"serializer":{"default_serializer":"messenger.transport.native_php_serializer","symfony_serializer":{"format":"json","context":[]}},"transports":[],"failure_transport":null,"reset_on_message":true,"stop_worker_on_signals":[],"default_bus":null,"buses":{"messenger.bus.default":{"default_middleware":{"enabled":true,"allow_no_handlers":false,"allow_no_senders":true},"middleware":[]}}}
     */
    public function messenger(array $value = []): \_ContaoManager\Symfony\Config\Framework\MessengerConfig
    {
        if (null === $this->messenger) {
            $this->_usedProperties['messenger'] = \true;
            $this->messenger = new \_ContaoManager\Symfony\Config\Framework\MessengerConfig($value);
        } elseif (0 < \func_num_args()) {
            throw new InvalidConfigurationException('The node created by "messenger()" has already been initialized. You cannot pass values the second time you call messenger().');
        }
        return $this->messenger;
    }
    /**
     * Scheduler configuration
     * @default {"enabled":false}
     */
    public function scheduler(array $value = []): \_ContaoManager\Symfony\Config\Framework\SchedulerConfig
    {
        if (null === $this->scheduler) {
            $this->_usedProperties['scheduler'] = \true;
            $this->scheduler = new \_ContaoManager\Symfony\Config\Framework\SchedulerConfig($value);
        } elseif (0 < \func_num_args()) {
            throw new InvalidConfigurationException('The node created by "scheduler()" has already been initialized. You cannot pass values the second time you call scheduler().');
        }
        return $this->scheduler;
    }
    /**
     * Enabled by default when debug is enabled.
     * @default false
     * @param ParamConfigurator|bool $value
     * @return $this
     */
    public function disallowSearchEngineIndex($value): static
    {
        $this->_usedProperties['disallowSearchEngineIndex'] = \true;
        $this->disallowSearchEngineIndex = $value;
        return $this;
    }
    /**
     * @template TValue of mixed
     * @param TValue $value
     * HTTP Client configuration
     * @default {"enabled":false,"scoped_clients":[]}
     * @return \Symfony\Config\Framework\HttpClientConfig|$this
     * @psalm-return (TValue is array ? \Symfony\Config\Framework\HttpClientConfig : static)
     */
    public function httpClient(mixed $value = []): \_ContaoManager\Symfony\Config\Framework\HttpClientConfig|static
    {
        if (!\is_array($value)) {
            $this->_usedProperties['httpClient'] = \true;
            $this->httpClient = $value;
            return $this;
        }
        if (!$this->httpClient instanceof \_ContaoManager\Symfony\Config\Framework\HttpClientConfig) {
            $this->_usedProperties['httpClient'] = \true;
            $this->httpClient = new \_ContaoManager\Symfony\Config\Framework\HttpClientConfig($value);
        } elseif (0 < \func_num_args()) {
            throw new InvalidConfigurationException('The node created by "httpClient()" has already been initialized. You cannot pass values the second time you call httpClient().');
        }
        return $this->httpClient;
    }
    /**
     * Mailer configuration
     * @default {"enabled":false,"message_bus":null,"dsn":null,"transports":[],"headers":[]}
     */
    public function mailer(array $value = []): \_ContaoManager\Symfony\Config\Framework\MailerConfig
    {
        if (null === $this->mailer) {
            $this->_usedProperties['mailer'] = \true;
            $this->mailer = new \_ContaoManager\Symfony\Config\Framework\MailerConfig($value);
        } elseif (0 < \func_num_args()) {
            throw new InvalidConfigurationException('The node created by "mailer()" has already been initialized. You cannot pass values the second time you call mailer().');
        }
        return $this->mailer;
    }
    /**
     * @default {"enabled":true,"vault_directory":"%kernel.project_dir%\/config\/secrets\/%kernel.runtime_environment%","local_dotenv_file":"%kernel.project_dir%\/.env.%kernel.environment%.local","decryption_env_var":"base64:default::SYMFONY_DECRYPTION_SECRET"}
     */
    public function secrets(array $value = []): \_ContaoManager\Symfony\Config\Framework\SecretsConfig
    {
        if (null === $this->secrets) {
            $this->_usedProperties['secrets'] = \true;
            $this->secrets = new \_ContaoManager\Symfony\Config\Framework\SecretsConfig($value);
        } elseif (0 < \func_num_args()) {
            throw new InvalidConfigurationException('The node created by "secrets()" has already been initialized. You cannot pass values the second time you call secrets().');
        }
        return $this->secrets;
    }
    /**
     * Notifier configuration
     * @default {"enabled":false,"message_bus":null,"chatter_transports":[],"texter_transports":[],"notification_on_failed_messages":false,"channel_policy":[],"admin_recipients":[]}
     */
    public function notifier(array $value = []): \_ContaoManager\Symfony\Config\Framework\NotifierConfig
    {
        if (null === $this->notifier) {
            $this->_usedProperties['notifier'] = \true;
            $this->notifier = new \_ContaoManager\Symfony\Config\Framework\NotifierConfig($value);
        } elseif (0 < \func_num_args()) {
            throw new InvalidConfigurationException('The node created by "notifier()" has already been initialized. You cannot pass values the second time you call notifier().');
        }
        return $this->notifier;
    }
    /**
     * @template TValue of mixed
     * @param TValue $value
     * Rate limiter configuration
     * @default {"enabled":false,"limiters":[]}
     * @return \Symfony\Config\Framework\RateLimiterConfig|$this
     * @psalm-return (TValue is array ? \Symfony\Config\Framework\RateLimiterConfig : static)
     */
    public function rateLimiter(mixed $value = []): \_ContaoManager\Symfony\Config\Framework\RateLimiterConfig|static
    {
        if (!\is_array($value)) {
            $this->_usedProperties['rateLimiter'] = \true;
            $this->rateLimiter = $value;
            return $this;
        }
        if (!$this->rateLimiter instanceof \_ContaoManager\Symfony\Config\Framework\RateLimiterConfig) {
            $this->_usedProperties['rateLimiter'] = \true;
            $this->rateLimiter = new \_ContaoManager\Symfony\Config\Framework\RateLimiterConfig($value);
        } elseif (0 < \func_num_args()) {
            throw new InvalidConfigurationException('The node created by "rateLimiter()" has already been initialized. You cannot pass values the second time you call rateLimiter().');
        }
        return $this->rateLimiter;
    }
    /**
     * Uid configuration
     * @default {"enabled":true,"name_based_uuid_version":5}
     */
    public function uid(array $value = []): \_ContaoManager\Symfony\Config\Framework\UidConfig
    {
        if (null === $this->uid) {
            $this->_usedProperties['uid'] = \true;
            $this->uid = new \_ContaoManager\Symfony\Config\Framework\UidConfig($value);
        } elseif (0 < \func_num_args()) {
            throw new InvalidConfigurationException('The node created by "uid()" has already been initialized. You cannot pass values the second time you call uid().');
        }
        return $this->uid;
    }
    /**
     * HtmlSanitizer configuration
     * @default {"enabled":false,"sanitizers":[]}
     */
    public function htmlSanitizer(array $value = []): \_ContaoManager\Symfony\Config\Framework\HtmlSanitizerConfig
    {
        if (null === $this->htmlSanitizer) {
            $this->_usedProperties['htmlSanitizer'] = \true;
            $this->htmlSanitizer = new \_ContaoManager\Symfony\Config\Framework\HtmlSanitizerConfig($value);
        } elseif (0 < \func_num_args()) {
            throw new InvalidConfigurationException('The node created by "htmlSanitizer()" has already been initialized. You cannot pass values the second time you call htmlSanitizer().');
        }
        return $this->htmlSanitizer;
    }
    /**
     * Webhook configuration
     * @default {"enabled":false,"message_bus":"messenger.default_bus","routing":[]}
     */
    public function webhook(array $value = []): \_ContaoManager\Symfony\Config\Framework\WebhookConfig
    {
        if (null === $this->webhook) {
            $this->_usedProperties['webhook'] = \true;
            $this->webhook = new \_ContaoManager\Symfony\Config\Framework\WebhookConfig($value);
        } elseif (0 < \func_num_args()) {
            throw new InvalidConfigurationException('The node created by "webhook()" has already been initialized. You cannot pass values the second time you call webhook().');
        }
        return $this->webhook;
    }
    /**
     * RemoteEvent configuration
     * @default {"enabled":false}
     */
    public function remoteevent(array $value = []): \_ContaoManager\Symfony\Config\Framework\RemoteeventConfig
    {
        if (null === $this->remoteevent) {
            $this->_usedProperties['remoteevent'] = \true;
            $this->remoteevent = new \_ContaoManager\Symfony\Config\Framework\RemoteeventConfig($value);
        } elseif (0 < \func_num_args()) {
            throw new InvalidConfigurationException('The node created by "remoteevent()" has already been initialized. You cannot pass values the second time you call remoteevent().');
        }
        return $this->remoteevent;
    }
    public function getExtensionAlias(): string
    {
        return 'framework';
    }
    public function __construct(array $value = [])
    {
        if (array_key_exists('secret', $value)) {
            $this->_usedProperties['secret'] = \true;
            $this->secret = $value['secret'];
            unset($value['secret']);
        }
        if (array_key_exists('http_method_override', $value)) {
            $this->_usedProperties['httpMethodOverride'] = \true;
            $this->httpMethodOverride = $value['http_method_override'];
            unset($value['http_method_override']);
        }
        if (array_key_exists('trust_x_sendfile_type_header', $value)) {
            $this->_usedProperties['trustXSendfileTypeHeader'] = \true;
            $this->trustXSendfileTypeHeader = $value['trust_x_sendfile_type_header'];
            unset($value['trust_x_sendfile_type_header']);
        }
        if (array_key_exists('ide', $value)) {
            $this->_usedProperties['ide'] = \true;
            $this->ide = $value['ide'];
            unset($value['ide']);
        }
        if (array_key_exists('test', $value)) {
            $this->_usedProperties['test'] = \true;
            $this->test = $value['test'];
            unset($value['test']);
        }
        if (array_key_exists('default_locale', $value)) {
            $this->_usedProperties['defaultLocale'] = \true;
            $this->defaultLocale = $value['default_locale'];
            unset($value['default_locale']);
        }
        if (array_key_exists('set_locale_from_accept_language', $value)) {
            $this->_usedProperties['setLocaleFromAcceptLanguage'] = \true;
            $this->setLocaleFromAcceptLanguage = $value['set_locale_from_accept_language'];
            unset($value['set_locale_from_accept_language']);
        }
        if (array_key_exists('set_content_language_from_locale', $value)) {
            $this->_usedProperties['setContentLanguageFromLocale'] = \true;
            $this->setContentLanguageFromLocale = $value['set_content_language_from_locale'];
            unset($value['set_content_language_from_locale']);
        }
        if (array_key_exists('enabled_locales', $value)) {
            $this->_usedProperties['enabledLocales'] = \true;
            $this->enabledLocales = $value['enabled_locales'];
            unset($value['enabled_locales']);
        }
        if (array_key_exists('trusted_hosts', $value)) {
            $this->_usedProperties['trustedHosts'] = \true;
            $this->trustedHosts = $value['trusted_hosts'];
            unset($value['trusted_hosts']);
        }
        if (array_key_exists('trusted_proxies', $value)) {
            $this->_usedProperties['trustedProxies'] = \true;
            $this->trustedProxies = $value['trusted_proxies'];
            unset($value['trusted_proxies']);
        }
        if (array_key_exists('trusted_headers', $value)) {
            $this->_usedProperties['trustedHeaders'] = \true;
            $this->trustedHeaders = $value['trusted_headers'];
            unset($value['trusted_headers']);
        }
        if (array_key_exists('error_controller', $value)) {
            $this->_usedProperties['errorController'] = \true;
            $this->errorController = $value['error_controller'];
            unset($value['error_controller']);
        }
        if (array_key_exists('handle_all_throwables', $value)) {
            $this->_usedProperties['handleAllThrowables'] = \true;
            $this->handleAllThrowables = $value['handle_all_throwables'];
            unset($value['handle_all_throwables']);
        }
        if (array_key_exists('csrf_protection', $value)) {
            $this->_usedProperties['csrfProtection'] = \true;
            $this->csrfProtection = new \_ContaoManager\Symfony\Config\Framework\CsrfProtectionConfig($value['csrf_protection']);
            unset($value['csrf_protection']);
        }
        if (array_key_exists('form', $value)) {
            $this->_usedProperties['form'] = \true;
            $this->form = \is_array($value['form']) ? new \_ContaoManager\Symfony\Config\Framework\FormConfig($value['form']) : $value['form'];
            unset($value['form']);
        }
        if (array_key_exists('http_cache', $value)) {
            $this->_usedProperties['httpCache'] = \true;
            $this->httpCache = \is_array($value['http_cache']) ? new \_ContaoManager\Symfony\Config\Framework\HttpCacheConfig($value['http_cache']) : $value['http_cache'];
            unset($value['http_cache']);
        }
        if (array_key_exists('esi', $value)) {
            $this->_usedProperties['esi'] = \true;
            $this->esi = \is_array($value['esi']) ? new \_ContaoManager\Symfony\Config\Framework\EsiConfig($value['esi']) : $value['esi'];
            unset($value['esi']);
        }
        if (array_key_exists('ssi', $value)) {
            $this->_usedProperties['ssi'] = \true;
            $this->ssi = \is_array($value['ssi']) ? new \_ContaoManager\Symfony\Config\Framework\SsiConfig($value['ssi']) : $value['ssi'];
            unset($value['ssi']);
        }
        if (array_key_exists('fragments', $value)) {
            $this->_usedProperties['fragments'] = \true;
            $this->fragments = \is_array($value['fragments']) ? new \_ContaoManager\Symfony\Config\Framework\FragmentsConfig($value['fragments']) : $value['fragments'];
            unset($value['fragments']);
        }
        if (array_key_exists('profiler', $value)) {
            $this->_usedProperties['profiler'] = \true;
            $this->profiler = \is_array($value['profiler']) ? new \_ContaoManager\Symfony\Config\Framework\ProfilerConfig($value['profiler']) : $value['profiler'];
            unset($value['profiler']);
        }
        if (array_key_exists('workflows', $value)) {
            $this->_usedProperties['workflows'] = \true;
            $this->workflows = \is_array($value['workflows']) ? new \_ContaoManager\Symfony\Config\Framework\WorkflowsConfig($value['workflows']) : $value['workflows'];
            unset($value['workflows']);
        }
        if (array_key_exists('router', $value)) {
            $this->_usedProperties['router'] = \true;
            $this->router = \is_array($value['router']) ? new \_ContaoManager\Symfony\Config\Framework\RouterConfig($value['router']) : $value['router'];
            unset($value['router']);
        }
        if (array_key_exists('session', $value)) {
            $this->_usedProperties['session'] = \true;
            $this->session = \is_array($value['session']) ? new \_ContaoManager\Symfony\Config\Framework\SessionConfig($value['session']) : $value['session'];
            unset($value['session']);
        }
        if (array_key_exists('request', $value)) {
            $this->_usedProperties['request'] = \true;
            $this->request = \is_array($value['request']) ? new \_ContaoManager\Symfony\Config\Framework\RequestConfig($value['request']) : $value['request'];
            unset($value['request']);
        }
        if (array_key_exists('assets', $value)) {
            $this->_usedProperties['assets'] = \true;
            $this->assets = \is_array($value['assets']) ? new \_ContaoManager\Symfony\Config\Framework\AssetsConfig($value['assets']) : $value['assets'];
            unset($value['assets']);
        }
        if (array_key_exists('asset_mapper', $value)) {
            $this->_usedProperties['assetMapper'] = \true;
            $this->assetMapper = \is_array($value['asset_mapper']) ? new \_ContaoManager\Symfony\Config\Framework\AssetMapperConfig($value['asset_mapper']) : $value['asset_mapper'];
            unset($value['asset_mapper']);
        }
        if (array_key_exists('translator', $value)) {
            $this->_usedProperties['translator'] = \true;
            $this->translator = \is_array($value['translator']) ? new \_ContaoManager\Symfony\Config\Framework\TranslatorConfig($value['translator']) : $value['translator'];
            unset($value['translator']);
        }
        if (array_key_exists('validation', $value)) {
            $this->_usedProperties['validation'] = \true;
            $this->validation = \is_array($value['validation']) ? new \_ContaoManager\Symfony\Config\Framework\ValidationConfig($value['validation']) : $value['validation'];
            unset($value['validation']);
        }
        if (array_key_exists('annotations', $value)) {
            $this->_usedProperties['annotations'] = \true;
            $this->annotations = \is_array($value['annotations']) ? new \_ContaoManager\Symfony\Config\Framework\AnnotationsConfig($value['annotations']) : $value['annotations'];
            unset($value['annotations']);
        }
        if (array_key_exists('serializer', $value)) {
            $this->_usedProperties['serializer'] = \true;
            $this->serializer = \is_array($value['serializer']) ? new \_ContaoManager\Symfony\Config\Framework\SerializerConfig($value['serializer']) : $value['serializer'];
            unset($value['serializer']);
        }
        if (array_key_exists('property_access', $value)) {
            $this->_usedProperties['propertyAccess'] = \true;
            $this->propertyAccess = new \_ContaoManager\Symfony\Config\Framework\PropertyAccessConfig($value['property_access']);
            unset($value['property_access']);
        }
        if (array_key_exists('property_info', $value)) {
            $this->_usedProperties['propertyInfo'] = \true;
            $this->propertyInfo = new \_ContaoManager\Symfony\Config\Framework\PropertyInfoConfig($value['property_info']);
            unset($value['property_info']);
        }
        if (array_key_exists('cache', $value)) {
            $this->_usedProperties['cache'] = \true;
            $this->cache = new \_ContaoManager\Symfony\Config\Framework\CacheConfig($value['cache']);
            unset($value['cache']);
        }
        if (array_key_exists('php_errors', $value)) {
            $this->_usedProperties['phpErrors'] = \true;
            $this->phpErrors = new \_ContaoManager\Symfony\Config\Framework\PhpErrorsConfig($value['php_errors']);
            unset($value['php_errors']);
        }
        if (array_key_exists('exceptions', $value)) {
            $this->_usedProperties['exceptions'] = \true;
            $this->exceptions = array_map(fn($v) => \is_array($v) ? new \_ContaoManager\Symfony\Config\Framework\ExceptionConfig($v) : $v, $value['exceptions']);
            unset($value['exceptions']);
        }
        if (array_key_exists('web_link', $value)) {
            $this->_usedProperties['webLink'] = \true;
            $this->webLink = \is_array($value['web_link']) ? new \_ContaoManager\Symfony\Config\Framework\WebLinkConfig($value['web_link']) : $value['web_link'];
            unset($value['web_link']);
        }
        if (array_key_exists('lock', $value)) {
            $this->_usedProperties['lock'] = \true;
            $this->lock = \is_array($value['lock']) ? new \_ContaoManager\Symfony\Config\Framework\LockConfig($value['lock']) : $value['lock'];
            unset($value['lock']);
        }
        if (array_key_exists('semaphore', $value)) {
            $this->_usedProperties['semaphore'] = \true;
            $this->semaphore = \is_array($value['semaphore']) ? new \_ContaoManager\Symfony\Config\Framework\SemaphoreConfig($value['semaphore']) : $value['semaphore'];
            unset($value['semaphore']);
        }
        if (array_key_exists('messenger', $value)) {
            $this->_usedProperties['messenger'] = \true;
            $this->messenger = \is_array($value['messenger']) ? new \_ContaoManager\Symfony\Config\Framework\MessengerConfig($value['messenger']) : $value['messenger'];
            unset($value['messenger']);
        }
        if (array_key_exists('scheduler', $value)) {
            $this->_usedProperties['scheduler'] = \true;
            $this->scheduler = \is_array($value['scheduler']) ? new \_ContaoManager\Symfony\Config\Framework\SchedulerConfig($value['scheduler']) : $value['scheduler'];
            unset($value['scheduler']);
        }
        if (array_key_exists('disallow_search_engine_index', $value)) {
            $this->_usedProperties['disallowSearchEngineIndex'] = \true;
            $this->disallowSearchEngineIndex = $value['disallow_search_engine_index'];
            unset($value['disallow_search_engine_index']);
        }
        if (array_key_exists('http_client', $value)) {
            $this->_usedProperties['httpClient'] = \true;
            $this->httpClient = \is_array($value['http_client']) ? new \_ContaoManager\Symfony\Config\Framework\HttpClientConfig($value['http_client']) : $value['http_client'];
            unset($value['http_client']);
        }
        if (array_key_exists('mailer', $value)) {
            $this->_usedProperties['mailer'] = \true;
            $this->mailer = \is_array($value['mailer']) ? new \_ContaoManager\Symfony\Config\Framework\MailerConfig($value['mailer']) : $value['mailer'];
            unset($value['mailer']);
        }
        if (array_key_exists('secrets', $value)) {
            $this->_usedProperties['secrets'] = \true;
            $this->secrets = new \_ContaoManager\Symfony\Config\Framework\SecretsConfig($value['secrets']);
            unset($value['secrets']);
        }
        if (array_key_exists('notifier', $value)) {
            $this->_usedProperties['notifier'] = \true;
            $this->notifier = \is_array($value['notifier']) ? new \_ContaoManager\Symfony\Config\Framework\NotifierConfig($value['notifier']) : $value['notifier'];
            unset($value['notifier']);
        }
        if (array_key_exists('rate_limiter', $value)) {
            $this->_usedProperties['rateLimiter'] = \true;
            $this->rateLimiter = \is_array($value['rate_limiter']) ? new \_ContaoManager\Symfony\Config\Framework\RateLimiterConfig($value['rate_limiter']) : $value['rate_limiter'];
            unset($value['rate_limiter']);
        }
        if (array_key_exists('uid', $value)) {
            $this->_usedProperties['uid'] = \true;
            $this->uid = new \_ContaoManager\Symfony\Config\Framework\UidConfig($value['uid']);
            unset($value['uid']);
        }
        if (array_key_exists('html_sanitizer', $value)) {
            $this->_usedProperties['htmlSanitizer'] = \true;
            $this->htmlSanitizer = \is_array($value['html_sanitizer']) ? new \_ContaoManager\Symfony\Config\Framework\HtmlSanitizerConfig($value['html_sanitizer']) : $value['html_sanitizer'];
            unset($value['html_sanitizer']);
        }
        if (array_key_exists('webhook', $value)) {
            $this->_usedProperties['webhook'] = \true;
            $this->webhook = \is_array($value['webhook']) ? new \_ContaoManager\Symfony\Config\Framework\WebhookConfig($value['webhook']) : $value['webhook'];
            unset($value['webhook']);
        }
        if (array_key_exists('remote-event', $value)) {
            $this->_usedProperties['remoteevent'] = \true;
            $this->remoteevent = \is_array($value['remote-event']) ? new \_ContaoManager\Symfony\Config\Framework\RemoteeventConfig($value['remote-event']) : $value['remote-event'];
            unset($value['remote-event']);
        }
        if ([] !== $value) {
            throw new InvalidConfigurationException(sprintf('The following keys are not supported by "%s": ', __CLASS__) . implode(', ', array_keys($value)));
        }
    }
    public function toArray(): array
    {
        $output = [];
        if (isset($this->_usedProperties['secret'])) {
            $output['secret'] = $this->secret;
        }
        if (isset($this->_usedProperties['httpMethodOverride'])) {
            $output['http_method_override'] = $this->httpMethodOverride;
        }
        if (isset($this->_usedProperties['trustXSendfileTypeHeader'])) {
            $output['trust_x_sendfile_type_header'] = $this->trustXSendfileTypeHeader;
        }
        if (isset($this->_usedProperties['ide'])) {
            $output['ide'] = $this->ide;
        }
        if (isset($this->_usedProperties['test'])) {
            $output['test'] = $this->test;
        }
        if (isset($this->_usedProperties['defaultLocale'])) {
            $output['default_locale'] = $this->defaultLocale;
        }
        if (isset($this->_usedProperties['setLocaleFromAcceptLanguage'])) {
            $output['set_locale_from_accept_language'] = $this->setLocaleFromAcceptLanguage;
        }
        if (isset($this->_usedProperties['setContentLanguageFromLocale'])) {
            $output['set_content_language_from_locale'] = $this->setContentLanguageFromLocale;
        }
        if (isset($this->_usedProperties['enabledLocales'])) {
            $output['enabled_locales'] = $this->enabledLocales;
        }
        if (isset($this->_usedProperties['trustedHosts'])) {
            $output['trusted_hosts'] = $this->trustedHosts;
        }
        if (isset($this->_usedProperties['trustedProxies'])) {
            $output['trusted_proxies'] = $this->trustedProxies;
        }
        if (isset($this->_usedProperties['trustedHeaders'])) {
            $output['trusted_headers'] = $this->trustedHeaders;
        }
        if (isset($this->_usedProperties['errorController'])) {
            $output['error_controller'] = $this->errorController;
        }
        if (isset($this->_usedProperties['handleAllThrowables'])) {
            $output['handle_all_throwables'] = $this->handleAllThrowables;
        }
        if (isset($this->_usedProperties['csrfProtection'])) {
            $output['csrf_protection'] = $this->csrfProtection->toArray();
        }
        if (isset($this->_usedProperties['form'])) {
            $output['form'] = $this->form instanceof \_ContaoManager\Symfony\Config\Framework\FormConfig ? $this->form->toArray() : $this->form;
        }
        if (isset($this->_usedProperties['httpCache'])) {
            $output['http_cache'] = $this->httpCache instanceof \_ContaoManager\Symfony\Config\Framework\HttpCacheConfig ? $this->httpCache->toArray() : $this->httpCache;
        }
        if (isset($this->_usedProperties['esi'])) {
            $output['esi'] = $this->esi instanceof \_ContaoManager\Symfony\Config\Framework\EsiConfig ? $this->esi->toArray() : $this->esi;
        }
        if (isset($this->_usedProperties['ssi'])) {
            $output['ssi'] = $this->ssi instanceof \_ContaoManager\Symfony\Config\Framework\SsiConfig ? $this->ssi->toArray() : $this->ssi;
        }
        if (isset($this->_usedProperties['fragments'])) {
            $output['fragments'] = $this->fragments instanceof \_ContaoManager\Symfony\Config\Framework\FragmentsConfig ? $this->fragments->toArray() : $this->fragments;
        }
        if (isset($this->_usedProperties['profiler'])) {
            $output['profiler'] = $this->profiler instanceof \_ContaoManager\Symfony\Config\Framework\ProfilerConfig ? $this->profiler->toArray() : $this->profiler;
        }
        if (isset($this->_usedProperties['workflows'])) {
            $output['workflows'] = $this->workflows instanceof \_ContaoManager\Symfony\Config\Framework\WorkflowsConfig ? $this->workflows->toArray() : $this->workflows;
        }
        if (isset($this->_usedProperties['router'])) {
            $output['router'] = $this->router instanceof \_ContaoManager\Symfony\Config\Framework\RouterConfig ? $this->router->toArray() : $this->router;
        }
        if (isset($this->_usedProperties['session'])) {
            $output['session'] = $this->session instanceof \_ContaoManager\Symfony\Config\Framework\SessionConfig ? $this->session->toArray() : $this->session;
        }
        if (isset($this->_usedProperties['request'])) {
            $output['request'] = $this->request instanceof \_ContaoManager\Symfony\Config\Framework\RequestConfig ? $this->request->toArray() : $this->request;
        }
        if (isset($this->_usedProperties['assets'])) {
            $output['assets'] = $this->assets instanceof \_ContaoManager\Symfony\Config\Framework\AssetsConfig ? $this->assets->toArray() : $this->assets;
        }
        if (isset($this->_usedProperties['assetMapper'])) {
            $output['asset_mapper'] = $this->assetMapper instanceof \_ContaoManager\Symfony\Config\Framework\AssetMapperConfig ? $this->assetMapper->toArray() : $this->assetMapper;
        }
        if (isset($this->_usedProperties['translator'])) {
            $output['translator'] = $this->translator instanceof \_ContaoManager\Symfony\Config\Framework\TranslatorConfig ? $this->translator->toArray() : $this->translator;
        }
        if (isset($this->_usedProperties['validation'])) {
            $output['validation'] = $this->validation instanceof \_ContaoManager\Symfony\Config\Framework\ValidationConfig ? $this->validation->toArray() : $this->validation;
        }
        if (isset($this->_usedProperties['annotations'])) {
            $output['annotations'] = $this->annotations instanceof \_ContaoManager\Symfony\Config\Framework\AnnotationsConfig ? $this->annotations->toArray() : $this->annotations;
        }
        if (isset($this->_usedProperties['serializer'])) {
            $output['serializer'] = $this->serializer instanceof \_ContaoManager\Symfony\Config\Framework\SerializerConfig ? $this->serializer->toArray() : $this->serializer;
        }
        if (isset($this->_usedProperties['propertyAccess'])) {
            $output['property_access'] = $this->propertyAccess->toArray();
        }
        if (isset($this->_usedProperties['propertyInfo'])) {
            $output['property_info'] = $this->propertyInfo->toArray();
        }
        if (isset($this->_usedProperties['cache'])) {
            $output['cache'] = $this->cache->toArray();
        }
        if (isset($this->_usedProperties['phpErrors'])) {
            $output['php_errors'] = $this->phpErrors->toArray();
        }
        if (isset($this->_usedProperties['exceptions'])) {
            $output['exceptions'] = array_map(fn($v) => $v instanceof \_ContaoManager\Symfony\Config\Framework\ExceptionConfig ? $v->toArray() : $v, $this->exceptions);
        }
        if (isset($this->_usedProperties['webLink'])) {
            $output['web_link'] = $this->webLink instanceof \_ContaoManager\Symfony\Config\Framework\WebLinkConfig ? $this->webLink->toArray() : $this->webLink;
        }
        if (isset($this->_usedProperties['lock'])) {
            $output['lock'] = $this->lock instanceof \_ContaoManager\Symfony\Config\Framework\LockConfig ? $this->lock->toArray() : $this->lock;
        }
        if (isset($this->_usedProperties['semaphore'])) {
            $output['semaphore'] = $this->semaphore instanceof \_ContaoManager\Symfony\Config\Framework\SemaphoreConfig ? $this->semaphore->toArray() : $this->semaphore;
        }
        if (isset($this->_usedProperties['messenger'])) {
            $output['messenger'] = $this->messenger instanceof \_ContaoManager\Symfony\Config\Framework\MessengerConfig ? $this->messenger->toArray() : $this->messenger;
        }
        if (isset($this->_usedProperties['scheduler'])) {
            $output['scheduler'] = $this->scheduler instanceof \_ContaoManager\Symfony\Config\Framework\SchedulerConfig ? $this->scheduler->toArray() : $this->scheduler;
        }
        if (isset($this->_usedProperties['disallowSearchEngineIndex'])) {
            $output['disallow_search_engine_index'] = $this->disallowSearchEngineIndex;
        }
        if (isset($this->_usedProperties['httpClient'])) {
            $output['http_client'] = $this->httpClient instanceof \_ContaoManager\Symfony\Config\Framework\HttpClientConfig ? $this->httpClient->toArray() : $this->httpClient;
        }
        if (isset($this->_usedProperties['mailer'])) {
            $output['mailer'] = $this->mailer instanceof \_ContaoManager\Symfony\Config\Framework\MailerConfig ? $this->mailer->toArray() : $this->mailer;
        }
        if (isset($this->_usedProperties['secrets'])) {
            $output['secrets'] = $this->secrets->toArray();
        }
        if (isset($this->_usedProperties['notifier'])) {
            $output['notifier'] = $this->notifier instanceof \_ContaoManager\Symfony\Config\Framework\NotifierConfig ? $this->notifier->toArray() : $this->notifier;
        }
        if (isset($this->_usedProperties['rateLimiter'])) {
            $output['rate_limiter'] = $this->rateLimiter instanceof \_ContaoManager\Symfony\Config\Framework\RateLimiterConfig ? $this->rateLimiter->toArray() : $this->rateLimiter;
        }
        if (isset($this->_usedProperties['uid'])) {
            $output['uid'] = $this->uid->toArray();
        }
        if (isset($this->_usedProperties['htmlSanitizer'])) {
            $output['html_sanitizer'] = $this->htmlSanitizer instanceof \_ContaoManager\Symfony\Config\Framework\HtmlSanitizerConfig ? $this->htmlSanitizer->toArray() : $this->htmlSanitizer;
        }
        if (isset($this->_usedProperties['webhook'])) {
            $output['webhook'] = $this->webhook instanceof \_ContaoManager\Symfony\Config\Framework\WebhookConfig ? $this->webhook->toArray() : $this->webhook;
        }
        if (isset($this->_usedProperties['remoteevent'])) {
            $output['remote-event'] = $this->remoteevent instanceof \_ContaoManager\Symfony\Config\Framework\RemoteeventConfig ? $this->remoteevent->toArray() : $this->remoteevent;
        }
        return $output;
    }
}
<?php

namespace _ContaoManager\ContainerLiF9Qbu;

use _ContaoManager\Symfony\Component\DependencyInjection\Argument\RewindableGenerator;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\RuntimeException;
/*
 * @internal This class has been auto-generated by the Symfony Dependency Injection Component.
 */
class getSecurity_Firewall_Map_Context_ApiService extends Contao_ManagerApi_ApiKernelProdContainer
{
    /*
     * Gets the private 'security.firewall.map.context.api' shared service.
     *
     * @return \Symfony\Bundle\SecurityBundle\Security\FirewallContext
     */
    public static function do($container, $lazyLoad = \true)
    {
        $a = $container->services['router'] ?? self::getRouterService($container);
        $instance = new \_ContaoManager\Symfony\Bundle\SecurityBundle\Security\FirewallContext(new RewindableGenerator(function () use ($container) {
            yield 0 => $container->privates['security.channel_listener'] ?? $container->load('getSecurity_ChannelListenerService');
            yield 1 => $container->privates['security.firewall.authenticator.api'] ?? $container->load('getSecurity_Firewall_Authenticator_ApiService');
            yield 2 => $container->privates['security.access_listener'] ?? $container->load('getSecurity_AccessListenerService');
        }, 3), new \_ContaoManager\Symfony\Component\Security\Http\Firewall\ExceptionListener($container->services['security.token_storage'] ??= new \_ContaoManager\Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorage(), $container->privates['contao_manager.security.authentication_trust_resolver'] ?? $container->load('getContaoManager_Security_AuthenticationTrustResolverService'), new \_ContaoManager\Symfony\Component\Security\Http\HttpUtils($a, $a), 'api', NULL, NULL, NULL, $container->privates['monolog.logger.security'] ?? $container->load('getMonolog_Logger_SecurityService'), \true), NULL, new \_ContaoManager\Symfony\Bundle\SecurityBundle\Security\FirewallConfig('api', 'security.user_checker', NULL, \true, \true, '_ContaoManager\Contao\ManagerApi\Security\UserProvider', NULL, NULL, NULL, NULL, ['_ContaoManager\Contao\ManagerApi\Security\LoginAuthenticator', '_ContaoManager\Contao\ManagerApi\Security\WebauthnAuthenticator', '_ContaoManager\Contao\ManagerApi\Security\PasswordlessAuthenticator', '_ContaoManager\Contao\ManagerApi\Security\JwtAuthenticator', '_ContaoManager\Contao\ManagerApi\Security\TokenAuthenticator'], NULL, NULL));
        if (isset($container->privates['security.firewall.map.context.api'])) {
            return $container->privates['security.firewall.map.context.api'];
        }
        return $container->privates['security.firewall.map.context.api'] = $instance;
    }
}
<?php

namespace _ContaoManager\ContainerLiF9Qbu;

use _ContaoManager\Symfony\Component\DependencyInjection\Argument\RewindableGenerator;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\RuntimeException;
/*
 * @internal This class has been auto-generated by the Symfony Dependency Injection Component.
 */
class getContainer_GetRoutingConditionServiceService extends Contao_ManagerApi_ApiKernelProdContainer
{
    /*
     * Gets the public 'container.get_routing_condition_service' shared service.
     *
     * @return \Closure
     */
    public static function do($container, $lazyLoad = \true)
    {
        return $container->services['container.get_routing_condition_service'] = (new \_ContaoManager\Symfony\Component\DependencyInjection\Argument\ServiceLocator($container->getService ??= $container->getService(...), [], []))->get(...);
    }
}
<?php

namespace _ContaoManager\ContainerLiF9Qbu;

use _ContaoManager\Symfony\Component\DependencyInjection\Argument\RewindableGenerator;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\RuntimeException;
/*
 * @internal This class has been auto-generated by the Symfony Dependency Injection Component.
 */
class getComposerController2Service extends Contao_ManagerApi_ApiKernelProdContainer
{
    /*
     * Gets the public 'Contao\ManagerApi\Controller\Server\ComposerController' shared autowired service.
     *
     * @return \Contao\ManagerApi\Controller\Server\ComposerController
     */
    public static function do($container, $lazyLoad = \true)
    {
        return $container->services['Contao\ManagerApi\Controller\Server\ComposerController'] = new \_ContaoManager\Contao\ManagerApi\Controller\Server\ComposerController($container->privates['Contao\ManagerApi\Composer\Environment'] ?? $container->load('getEnvironmentService'), $container->services['Contao\ManagerApi\I18n\Translator'] ?? $container->load('getTranslatorService'), $container->privates['filesystem'] ??= new \_ContaoManager\Symfony\Component\Filesystem\Filesystem());
    }
}
<?php

namespace _ContaoManager\ContainerLiF9Qbu;

use _ContaoManager\Symfony\Component\DependencyInjection\Argument\RewindableGenerator;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\RuntimeException;
/*
 * @internal This class has been auto-generated by the Symfony Dependency Injection Component.
 */
class getSecurity_UserCheckerLocatorService extends Contao_ManagerApi_ApiKernelProdContainer
{
    /*
     * Gets the private 'security.user_checker_locator' shared service.
     *
     * @return \Symfony\Component\DependencyInjection\ServiceLocator
     */
    public static function do($container, $lazyLoad = \true)
    {
        return $container->privates['security.user_checker_locator'] = new \_ContaoManager\Symfony\Component\DependencyInjection\ServiceLocator(['api' => #[\Closure(name: 'security.user_checker', class: '_ContaoManager\Symfony\Component\Security\Core\User\InMemoryUserChecker')] fn() => $container->privates['security.user_checker'] ??= new \_ContaoManager\Symfony\Component\Security\Core\User\InMemoryUserChecker()]);
    }
}
<?php

namespace _ContaoManager\ContainerLiF9Qbu;

use _ContaoManager\Symfony\Component\DependencyInjection\Argument\RewindableGenerator;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\RuntimeException;
/*
 * @internal This class has been auto-generated by the Symfony Dependency Injection Component.
 */
class getConsole_Command_SecretsListService extends Contao_ManagerApi_ApiKernelProdContainer
{
    /*
     * Gets the private 'console.command.secrets_list' shared service.
     *
     * @return \Symfony\Bundle\FrameworkBundle\Command\SecretsListCommand
     */
    public static function do($container, $lazyLoad = \true)
    {
        $container->privates['console.command.secrets_list'] = $instance = new \_ContaoManager\Symfony\Bundle\FrameworkBundle\Command\SecretsListCommand($container->privates['secrets.vault'] ?? $container->load('getSecrets_VaultService'), $container->privates['secrets.local_vault'] ??= new \_ContaoManager\Symfony\Bundle\FrameworkBundle\Secrets\DotenvVault(\dirname(__DIR__, 4) . '/test-dir/.env.prod.local'));
        $instance->setName('secrets:list');
        $instance->setDescription('List all secrets');
        return $instance;
    }
}
<?php

namespace _ContaoManager\ContainerLiF9Qbu;

use _ContaoManager\Symfony\Component\DependencyInjection\Argument\RewindableGenerator;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\RuntimeException;
/*
 * @internal This class has been auto-generated by the Symfony Dependency Injection Component.
 */
class getConsole_Command_SecretsRemoveService extends Contao_ManagerApi_ApiKernelProdContainer
{
    /*
     * Gets the private 'console.command.secrets_remove' shared service.
     *
     * @return \Symfony\Bundle\FrameworkBundle\Command\SecretsRemoveCommand
     */
    public static function do($container, $lazyLoad = \true)
    {
        $container->privates['console.command.secrets_remove'] = $instance = new \_ContaoManager\Symfony\Bundle\FrameworkBundle\Command\SecretsRemoveCommand($container->privates['secrets.vault'] ?? $container->load('getSecrets_VaultService'), $container->privates['secrets.local_vault'] ??= new \_ContaoManager\Symfony\Bundle\FrameworkBundle\Secrets\DotenvVault(\dirname(__DIR__, 4) . '/test-dir/.env.prod.local'));
        $instance->setName('secrets:remove');
        $instance->setDescription('Remove a secret from the vault');
        return $instance;
    }
}
<?php

namespace _ContaoManager\ContainerLiF9Qbu;

use _ContaoManager\Symfony\Component\DependencyInjection\Argument\RewindableGenerator;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\RuntimeException;
/*
 * @internal This class has been auto-generated by the Symfony Dependency Injection Component.
 */
class getGraphicsLibCheckService extends Contao_ManagerApi_ApiKernelProdContainer
{
    /*
     * Gets the private 'Contao\ManagerApi\IntegrityCheck\GraphicsLibCheck' shared autowired service.
     *
     * @return \Contao\ManagerApi\IntegrityCheck\GraphicsLibCheck
     */
    public static function do($container, $lazyLoad = \true)
    {
        return $container->privates['Contao\ManagerApi\IntegrityCheck\GraphicsLibCheck'] = new \_ContaoManager\Contao\ManagerApi\IntegrityCheck\GraphicsLibCheck($container->services['Contao\ManagerApi\I18n\Translator'] ?? $container->load('getTranslatorService'));
    }
}
<?php

namespace _ContaoManager\ContainerLiF9Qbu;

use _ContaoManager\Symfony\Component\DependencyInjection\Argument\RewindableGenerator;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\RuntimeException;
/*
 * @internal This class has been auto-generated by the Symfony Dependency Injection Component.
 */
class getPhpCliControllerService extends Contao_ManagerApi_ApiKernelProdContainer
{
    /*
     * Gets the public 'Contao\ManagerApi\Controller\Server\PhpCliController' shared autowired service.
     *
     * @return \Contao\ManagerApi\Controller\Server\PhpCliController
     */
    public static function do($container, $lazyLoad = \true)
    {
        return $container->services['Contao\ManagerApi\Controller\Server\PhpCliController'] = new \_ContaoManager\Contao\ManagerApi\Controller\Server\PhpCliController();
    }
}
<?php

namespace _ContaoManager\ContainerLiF9Qbu;

use _ContaoManager\Symfony\Component\DependencyInjection\Argument\RewindableGenerator;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\RuntimeException;
/*
 * @internal This class has been auto-generated by the Symfony Dependency Injection Component.
 */
class getSecurity_Authenticator_ManagersLocatorService extends Contao_ManagerApi_ApiKernelProdContainer
{
    /*
     * Gets the private 'security.authenticator.managers_locator' shared service.
     *
     * @return \Symfony\Component\DependencyInjection\ServiceLocator
     */
    public static function do($container, $lazyLoad = \true)
    {
        return $container->privates['security.authenticator.managers_locator'] = new \_ContaoManager\Symfony\Component\DependencyInjection\ServiceLocator(['api' => #[\Closure(name: 'security.authenticator.manager.api', class: '_ContaoManager\Symfony\Component\Security\Http\Authentication\AuthenticatorManager')] fn() => $container->privates['security.authenticator.manager.api'] ?? $container->load('getSecurity_Authenticator_Manager_ApiService')]);
    }
}
<?php

namespace _ContaoManager\ContainerLiF9Qbu;

use _ContaoManager\Symfony\Component\DependencyInjection\Argument\RewindableGenerator;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\RuntimeException;
/*
 * @internal This class has been auto-generated by the Symfony Dependency Injection Component.
 */
class getTaskDeleteCommandService extends Contao_ManagerApi_ApiKernelProdContainer
{
    /*
     * Gets the public 'Contao\ManagerApi\Command\TaskDeleteCommand' shared autowired service.
     *
     * @return \Contao\ManagerApi\Command\TaskDeleteCommand
     */
    public static function do($container, $lazyLoad = \true)
    {
        $container->services['Contao\ManagerApi\Command\TaskDeleteCommand'] = $instance = new \_ContaoManager\Contao\ManagerApi\Command\TaskDeleteCommand($container->privates['Contao\ManagerApi\Task\TaskManager'] ?? $container->load('getTaskManagerService'));
        $instance->setName('task:delete');
        $instance->setDescription('Deletes the current task if it is not active.');
        return $instance;
    }
}
<?php

namespace _ContaoManager\ContainerLiF9Qbu;

use _ContaoManager\Symfony\Component\DependencyInjection\Argument\RewindableGenerator;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\RuntimeException;
/*
 * @internal This class has been auto-generated by the Symfony Dependency Injection Component.
 */
class get_Console_Command_SecretsEncryptFromLocal_LazyService extends Contao_ManagerApi_ApiKernelProdContainer
{
    /*
     * Gets the private '.console.command.secrets_encrypt_from_local.lazy' shared service.
     *
     * @return \Symfony\Component\Console\Command\LazyCommand
     */
    public static function do($container, $lazyLoad = \true)
    {
        return $container->privates['.console.command.secrets_encrypt_from_local.lazy'] = new \_ContaoManager\Symfony\Component\Console\Command\LazyCommand('secrets:encrypt-from-local', [], 'Encrypt all local secrets to the vault', \false, #[\Closure(name: 'console.command.secrets_encrypt_from_local', class: '_ContaoManager\Symfony\Bundle\FrameworkBundle\Command\SecretsEncryptFromLocalCommand')] fn(): \_ContaoManager\Symfony\Bundle\FrameworkBundle\Command\SecretsEncryptFromLocalCommand => $container->privates['console.command.secrets_encrypt_from_local'] ?? $container->load('getConsole_Command_SecretsEncryptFromLocalService'));
    }
}
<?php

namespace _ContaoManager\ContainerLiF9Qbu;

use _ContaoManager\Symfony\Component\DependencyInjection\Argument\RewindableGenerator;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\RuntimeException;
/*
 * @internal This class has been auto-generated by the Symfony Dependency Injection Component.
 */
class getConstraintControllerService extends Contao_ManagerApi_ApiKernelProdContainer
{
    /*
     * Gets the public 'Contao\ManagerApi\Controller\ConstraintController' shared autowired service.
     *
     * @return \Contao\ManagerApi\Controller\ConstraintController
     */
    public static function do($container, $lazyLoad = \true)
    {
        return $container->services['Contao\ManagerApi\Controller\ConstraintController'] = new \_ContaoManager\Contao\ManagerApi\Controller\ConstraintController();
    }
}
<?php

namespace _ContaoManager\ContainerLiF9Qbu;

use _ContaoManager\Symfony\Component\DependencyInjection\Argument\RewindableGenerator;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\RuntimeException;
/*
 * @internal This class has been auto-generated by the Symfony Dependency Injection Component.
 */
class getArgumentResolver_BackedEnumResolverService extends Contao_ManagerApi_ApiKernelProdContainer
{
    /*
     * Gets the private 'argument_resolver.backed_enum_resolver' shared service.
     *
     * @return \Symfony\Component\HttpKernel\Controller\ArgumentResolver\BackedEnumValueResolver
     */
    public static function do($container, $lazyLoad = \true)
    {
        return $container->privates['argument_resolver.backed_enum_resolver'] = new \_ContaoManager\Symfony\Component\HttpKernel\Controller\ArgumentResolver\BackedEnumValueResolver();
    }
}
<?php

namespace _ContaoManager\ContainerLiF9Qbu;

return ['.1_AttestationStatementSupportManager~XHmS4ar' => \true, '.Contao\ManagerApi\Command\AboutCommand.lazy' => \true, '.Contao\ManagerApi\Command\IntegrityCheckCommand.lazy' => \true, '.Contao\ManagerApi\Command\ProcessRunnerCommand.lazy' => \true, '.Contao\ManagerApi\Command\TaskAbortCommand.lazy' => \true, '.Contao\ManagerApi\Command\TaskDeleteCommand.lazy' => \true, '.Contao\ManagerApi\Command\TaskUpdateCommand.lazy' => \true, '.Contao\ManagerApi\Command\UpdateCommand.lazy' => \true, '.Psr\Container\ContainerInterface $parameter_bag' => \true, '.Psr\Log\LoggerInterface $cache.logger' => \true, '.Psr\Log\LoggerInterface $console.logger' => \true, '.Psr\Log\LoggerInterface $php.logger' => \true, '.Psr\Log\LoggerInterface $request.logger' => \true, '.Psr\Log\LoggerInterface $router.logger' => \true, '.Psr\Log\LoggerInterface $security.logger' => \true, '.Psr\Log\LoggerInterface $tasks.logger' => \true, '.abstract.instanceof.Contao\ManagerApi\ApiApplication' => \true, '.abstract.instanceof.Contao\ManagerApi\Command\AboutCommand' => \true, '.abstract.instanceof.Contao\ManagerApi\Command\IntegrityCheckCommand' => \true, '.abstract.instanceof.Contao\ManagerApi\Command\ProcessRunnerCommand' => \true, '.abstract.instanceof.Contao\ManagerApi\Command\TaskAbortCommand' => \true, '.abstract.instanceof.Contao\ManagerApi\Command\TaskDeleteCommand' => \true, '.abstract.instanceof.Contao\ManagerApi\Command\TaskUpdateCommand' => \true, '.abstract.instanceof.Contao\ManagerApi\Command\UpdateCommand' => \true, '.abstract.instanceof.Contao\ManagerApi\Composer\CloudResolver' => \true, '.abstract.instanceof.Contao\ManagerApi\Controller\Packages\CloudController' => \true, '.abstract.instanceof.Contao\ManagerApi\EventListener\CheckTotpListener' => \true, '.abstract.instanceof.Contao\ManagerApi\EventListener\ExceptionListener' => \true, '.abstract.instanceof.Contao\ManagerApi\EventListener\JsonRequestListener' => \true, '.abstract.instanceof.Contao\ManagerApi\EventListener\LocaleListener' => \true, '.abstract.instanceof.Contao\ManagerApi\EventListener\SecurityListener' => \true, '.abstract.instanceof.Contao\ManagerApi\IntegrityCheck\IntegrityCheckFactory' => \true, '.abstract.instanceof.Contao\ManagerApi\Process\ConsoleProcessFactory' => \true, '.abstract.instanceof.Contao\ManagerApi\Security\WebauthnAuthenticator' => \true, '.abstract.instanceof.Contao\ManagerApi\TaskOperation\Composer\ClearCacheOperation' => \true, '.abstract.instanceof.Contao\ManagerApi\TaskOperation\Composer\CreateProjectOperation' => \true, '.abstract.instanceof.Contao\ManagerApi\TaskOperation\Composer\DumpAutoloadOperation' => \true, '.abstract.instanceof.Contao\ManagerApi\TaskOperation\Composer\InstallOperation' => \true, '.abstract.instanceof.Contao\ManagerApi\TaskOperation\Composer\RemoveOperation' => \true, '.abstract.instanceof.Contao\ManagerApi\TaskOperation\Composer\RequireOperation' => \true, '.abstract.instanceof.Contao\ManagerApi\TaskOperation\Composer\UpdateOperation' => \true, '.abstract.instanceof.Contao\ManagerApi\TaskOperation\Contao\BackupCreateOperation' => \true, '.abstract.instanceof.Contao\ManagerApi\TaskOperation\Contao\BackupRestoreOperation' => \true, '.abstract.instanceof.Contao\ManagerApi\TaskOperation\Contao\CacheClearOperation' => \true, '.abstract.instanceof.Contao\ManagerApi\TaskOperation\Contao\CacheWarmupOperation' => \true, '.abstract.instanceof.Contao\ManagerApi\TaskOperation\Contao\CreateContaoOperation' => \true, '.abstract.instanceof.Contao\ManagerApi\TaskOperation\Contao\MaintenanceModeOperation' => \true, '.abstract.instanceof.Contao\ManagerApi\TaskOperation\Filesystem\InstallUploadsOperation' => \true, '.abstract.instanceof.Contao\ManagerApi\TaskOperation\Filesystem\RemoveArtifactsOperation' => \true, '.abstract.instanceof.Contao\ManagerApi\TaskOperation\Filesystem\RemoveCacheOperation' => \true, '.abstract.instanceof.Contao\ManagerApi\TaskOperation\Filesystem\RemoveUploadsOperation' => \true, '.abstract.instanceof.Contao\ManagerApi\TaskOperation\Filesystem\RemoveVendorOperation' => \true, '.abstract.instanceof.Contao\ManagerApi\TaskOperation\Manager\SelfUpdateOperation' => \true, '.abstract.instanceof.Contao\ManagerApi\Task\Composer\ClearCacheTask' => \true, '.abstract.instanceof.Contao\ManagerApi\Task\Composer\DumpAutoloadTask' => \true, '.abstract.instanceof.Contao\ManagerApi\Task\Contao\BackupCreateTask' => \true, '.abstract.instanceof.Contao\ManagerApi\Task\Contao\BackupRestoreTask' => \true, '.abstract.instanceof.Contao\ManagerApi\Task\Contao\RebuildCacheTask' => \true, '.abstract.instanceof.Contao\ManagerApi\Task\Manager\SelfUpdateTask' => \true, '.abstract.instanceof.Contao\ManagerApi\Task\Packages\InstallTask' => \true, '.abstract.instanceof.Contao\ManagerApi\Task\Packages\SetupTask' => \true, '.abstract.instanceof.Contao\ManagerApi\Task\Packages\UpdateTask' => \true, '.abstract.instanceof.Contao\ManagerApi\Task\TaskManager' => \true, '.cache_connection.GD_MSZC' => \true, '.cache_connection.JKE6keX' => \true, '.console.command.about.lazy' => \true, '.console.command.assets_install.lazy' => \true, '.console.command.cache_clear.lazy' => \true, '.console.command.cache_pool_clear.lazy' => \true, '.console.command.cache_pool_delete.lazy' => \true, '.console.command.cache_pool_invalidate_tags.lazy' => \true, '.console.command.cache_pool_list.lazy' => \true, '.console.command.cache_pool_prune.lazy' => \true, '.console.command.cache_warmup.lazy' => \true, '.console.command.config_debug.lazy' => \true, '.console.command.config_dump_reference.lazy' => \true, '.console.command.container_debug.lazy' => \true, '.console.command.container_lint.lazy' => \true, '.console.command.debug_autowiring.lazy' => \true, '.console.command.event_dispatcher_debug.lazy' => \true, '.console.command.router_debug.lazy' => \true, '.console.command.router_match.lazy' => \true, '.console.command.secrets_decrypt_to_local.lazy' => \true, '.console.command.secrets_encrypt_from_local.lazy' => \true, '.console.command.secrets_generate_key.lazy' => \true, '.console.command.secrets_list.lazy' => \true, '.console.command.secrets_remove.lazy' => \true, '.console.command.secrets_set.lazy' => \true, '.console.command.serializer_debug.lazy' => \true, '.console.command.yaml_lint.lazy' => \true, '.instanceof.Contao\ManagerApi\Composer\CloudResolver.0.Contao\ManagerApi\Composer\CloudResolver' => \true, '.instanceof.Contao\ManagerApi\EventListener\CheckTotpListener.0.Contao\ManagerApi\EventListener\CheckTotpListener' => \true, '.instanceof.Contao\ManagerApi\EventListener\ExceptionListener.0.Contao\ManagerApi\EventListener\ExceptionListener' => \true, '.instanceof.Contao\ManagerApi\EventListener\JsonRequestListener.0.Contao\ManagerApi\EventListener\JsonRequestListener' => \true, '.instanceof.Contao\ManagerApi\EventListener\SecurityListener.0.Contao\ManagerApi\EventListener\SecurityListener' => \true, '.instanceof.Contao\ManagerApi\Process\ConsoleProcessFactory.0.Contao\ManagerApi\Process\ConsoleProcessFactory' => \true, '.instanceof.Contao\ManagerApi\Security\WebauthnAuthenticator.0.Contao\ManagerApi\Security\WebauthnAuthenticator' => \true, '.instanceof.Contao\ManagerApi\Task\TaskInterface.0.Contao\ManagerApi\Task\Composer\ClearCacheTask' => \true, '.instanceof.Contao\ManagerApi\Task\TaskInterface.0.Contao\ManagerApi\Task\Composer\DumpAutoloadTask' => \true, '.instanceof.Contao\ManagerApi\Task\TaskInterface.0.Contao\ManagerApi\Task\Contao\BackupCreateTask' => \true, '.instanceof.Contao\ManagerApi\Task\TaskInterface.0.Contao\ManagerApi\Task\Contao\BackupRestoreTask' => \true, '.instanceof.Contao\ManagerApi\Task\TaskInterface.0.Contao\ManagerApi\Task\Contao\RebuildCacheTask' => \true, '.instanceof.Contao\ManagerApi\Task\TaskInterface.0.Contao\ManagerApi\Task\Manager\SelfUpdateTask' => \true, '.instanceof.Contao\ManagerApi\Task\TaskInterface.0.Contao\ManagerApi\Task\Packages\InstallTask' => \true, '.instanceof.Contao\ManagerApi\Task\TaskInterface.0.Contao\ManagerApi\Task\Packages\SetupTask' => \true, '.instanceof.Contao\ManagerApi\Task\TaskInterface.0.Contao\ManagerApi\Task\Packages\UpdateTask' => \true, '.instanceof.Contao\ManagerApi\Task\TaskManager.0.Contao\ManagerApi\Task\TaskManager' => \true, '.instanceof.Psr\Log\LoggerAwareInterface.0.Contao\ManagerApi\Composer\CloudResolver' => \true, '.instanceof.Psr\Log\LoggerAwareInterface.0.Contao\ManagerApi\Process\ConsoleProcessFactory' => \true, '.instanceof.Psr\Log\LoggerAwareInterface.0.Contao\ManagerApi\TaskOperation\Composer\ClearCacheOperation' => \true, '.instanceof.Psr\Log\LoggerAwareInterface.0.Contao\ManagerApi\TaskOperation\Composer\CreateProjectOperation' => \true, '.instanceof.Psr\Log\LoggerAwareInterface.0.Contao\ManagerApi\TaskOperation\Composer\DumpAutoloadOperation' => \true, '.instanceof.Psr\Log\LoggerAwareInterface.0.Contao\ManagerApi\TaskOperation\Composer\InstallOperation' => \true, '.instanceof.Psr\Log\LoggerAwareInterface.0.Contao\ManagerApi\TaskOperation\Composer\RemoveOperation' => \true, '.instanceof.Psr\Log\LoggerAwareInterface.0.Contao\ManagerApi\TaskOperation\Composer\RequireOperation' => \true, '.instanceof.Psr\Log\LoggerAwareInterface.0.Contao\ManagerApi\TaskOperation\Composer\UpdateOperation' => \true, '.instanceof.Psr\Log\LoggerAwareInterface.0.Contao\ManagerApi\TaskOperation\Contao\BackupCreateOperation' => \true, '.instanceof.Psr\Log\LoggerAwareInterface.0.Contao\ManagerApi\TaskOperation\Contao\BackupRestoreOperation' => \true, '.instanceof.Psr\Log\LoggerAwareInterface.0.Contao\ManagerApi\TaskOperation\Contao\CacheClearOperation' => \true, '.instanceof.Psr\Log\LoggerAwareInterface.0.Contao\ManagerApi\TaskOperation\Contao\CacheWarmupOperation' => \true, '.instanceof.Psr\Log\LoggerAwareInterface.0.Contao\ManagerApi\TaskOperation\Contao\CreateContaoOperation' => \true, '.instanceof.Psr\Log\LoggerAwareInterface.0.Contao\ManagerApi\TaskOperation\Contao\MaintenanceModeOperation' => \true, '.instanceof.Psr\Log\LoggerAwareInterface.0.Contao\ManagerApi\TaskOperation\Filesystem\InstallUploadsOperation' => \true, '.instanceof.Psr\Log\LoggerAwareInterface.0.Contao\ManagerApi\TaskOperation\Filesystem\RemoveArtifactsOperation' => \true, '.instanceof.Psr\Log\LoggerAwareInterface.0.Contao\ManagerApi\TaskOperation\Filesystem\RemoveCacheOperation' => \true, '.instanceof.Psr\Log\LoggerAwareInterface.0.Contao\ManagerApi\TaskOperation\Filesystem\RemoveUploadsOperation' => \true, '.instanceof.Psr\Log\LoggerAwareInterface.0.Contao\ManagerApi\TaskOperation\Filesystem\RemoveVendorOperation' => \true, '.instanceof.Psr\Log\LoggerAwareInterface.0.Contao\ManagerApi\TaskOperation\Manager\SelfUpdateOperation' => \true, '.instanceof.Psr\Log\LoggerAwareInterface.0.Contao\ManagerApi\Task\Composer\ClearCacheTask' => \true, '.instanceof.Psr\Log\LoggerAwareInterface.0.Contao\ManagerApi\Task\Composer\DumpAutoloadTask' => \true, '.instanceof.Psr\Log\LoggerAwareInterface.0.Contao\ManagerApi\Task\Contao\BackupCreateTask' => \true, '.instanceof.Psr\Log\LoggerAwareInterface.0.Contao\ManagerApi\Task\Contao\BackupRestoreTask' => \true, '.instanceof.Psr\Log\LoggerAwareInterface.0.Contao\ManagerApi\Task\Contao\RebuildCacheTask' => \true, '.instanceof.Psr\Log\LoggerAwareInterface.0.Contao\ManagerApi\Task\Manager\SelfUpdateTask' => \true, '.instanceof.Psr\Log\LoggerAwareInterface.0.Contao\ManagerApi\Task\Packages\InstallTask' => \true, '.instanceof.Psr\Log\LoggerAwareInterface.0.Contao\ManagerApi\Task\Packages\SetupTask' => \true, '.instanceof.Psr\Log\LoggerAwareInterface.0.Contao\ManagerApi\Task\Packages\UpdateTask' => \true, '.instanceof.Psr\Log\LoggerAwareInterface.0.Contao\ManagerApi\Task\TaskManager' => \true, '.instanceof.Symfony\Bundle\FrameworkBundle\Controller\AbstractController.0.Contao\ManagerApi\Controller\Packages\CloudController' => \true, '.instanceof.Symfony\Component\Console\Command\Command.0.Contao\ManagerApi\Command\AboutCommand' => \true, '.instanceof.Symfony\Component\Console\Command\Command.0.Contao\ManagerApi\Command\IntegrityCheckCommand' => \true, '.instanceof.Symfony\Component\Console\Command\Command.0.Contao\ManagerApi\Command\ProcessRunnerCommand' => \true, '.instanceof.Symfony\Component\Console\Command\Command.0.Contao\ManagerApi\Command\TaskAbortCommand' => \true, '.instanceof.Symfony\Component\Console\Command\Command.0.Contao\ManagerApi\Command\TaskDeleteCommand' => \true, '.instanceof.Symfony\Component\Console\Command\Command.0.Contao\ManagerApi\Command\TaskUpdateCommand' => \true, '.instanceof.Symfony\Component\Console\Command\Command.0.Contao\ManagerApi\Command\UpdateCommand' => \true, '.instanceof.Symfony\Component\EventDispatcher\EventSubscriberInterface.0.Contao\ManagerApi\EventListener\LocaleListener' => \true, '.instanceof.Symfony\Contracts\Service\ResetInterface.0.Contao\ManagerApi\ApiApplication' => \true, '.instanceof.Symfony\Contracts\Service\ServiceSubscriberInterface.0.Contao\ManagerApi\Controller\Packages\CloudController' => \true, '.instanceof.Symfony\Contracts\Service\ServiceSubscriberInterface.0.Contao\ManagerApi\IntegrityCheck\IntegrityCheckFactory' => \true, '.security.command.debug_firewall.lazy' => \true, '.security.command.user_password_hash.lazy' => \true, '.security.request_matcher.AMZT15Y' => \true, '.security.request_matcher.LBzTDsp' => \true, '.security.request_matcher.gjnNpJn' => \true, '.security.request_matcher.j_9S1dW' => \true, '.service_locator..Fs8Kd7' => \true, '.service_locator..sxWFEb' => \true, '.service_locator.5hkYuXt' => \true, '.service_locator.5hkYuXt.Contao\ManagerApi\IntegrityCheck\IntegrityCheckFactory' => \true, '.service_locator.7ILhJfy' => \true, '.service_locator.9gXQpqd' => \true, '.service_locator.9gXQpqd.router.default' => \true, '.service_locator.BvkMlPl' => \true, '.service_locator.Ct6lrWe' => \true, '.service_locator.EZsc.DO' => \true, '.service_locator.GMhTiCF' => \true, '.service_locator.H.Zsu_s' => \true, '.service_locator.IMte7nJ' => \true, '.service_locator.JkQTEiI' => \true, '.service_locator.MlbgBlB' => \true, '.service_locator.NBUFN6A' => \true, '.service_locator.QRKZpFh' => \true, '.service_locator.VdCFd8p' => \true, '.service_locator.WxpRori' => \true, '.service_locator.XXv1IfR' => \true, '.service_locator.Xbsa8iG' => \true, '.service_locator.aH5O6Sd' => \true, '.service_locator.bJ.4HC5' => \true, '.service_locator.cUcW89y' => \true, '.service_locator.cUcW89y.router.cache_warmer' => \true, '.service_locator.e_.xxAP' => \true, '.service_locator.gcBfhm4' => \true, '.service_locator.lLv4pWF' => \true, '.service_locator.s6F2uGJ' => \true, '.service_locator.s6F2uGJ.Contao\ManagerApi\Controller\Packages\CloudController' => \true, '.service_locator.tpD_zef' => \true, '.service_locator.uPlitoC' => \true, '.service_locator.vMArKF_' => \true, '.service_locator.w7.f4fT' => \true, '.service_locator.y.Xs7Mw' => \true, '_ContaoManager\Contao\ManagerApi\ApiApplication' => \true, '_ContaoManager\Contao\ManagerApi\ApiKernel' => \true, '_ContaoManager\Contao\ManagerApi\Command' => \true, '_ContaoManager\Contao\ManagerApi\Composer\CloudChanges' => \true, '_ContaoManager\Contao\ManagerApi\Composer\CloudException' => \true, '_ContaoManager\Contao\ManagerApi\Composer\CloudJob' => \true, '_ContaoManager\Contao\ManagerApi\Composer\CloudResolver' => \true, '_ContaoManager\Contao\ManagerApi\Composer\Environment' => \true, '_ContaoManager\Contao\ManagerApi\Config\AuthConfig' => \true, '_ContaoManager\Contao\ManagerApi\Config\ComposerConfig' => \true, '_ContaoManager\Contao\ManagerApi\Config\ManagerConfig' => \true, '_ContaoManager\Contao\ManagerApi\Config\PartialConfig' => \true, '_ContaoManager\Contao\ManagerApi\Config\UploadsConfig' => \true, '_ContaoManager\Contao\ManagerApi\Config\UserConfig' => \true, '_ContaoManager\Contao\ManagerApi\Controller' => \true, '_ContaoManager\Contao\ManagerApi\EventListener\CheckTotpListener' => \true, '_ContaoManager\Contao\ManagerApi\EventListener\ExceptionListener' => \true, '_ContaoManager\Contao\ManagerApi\EventListener\JsonRequestListener' => \true, '_ContaoManager\Contao\ManagerApi\EventListener\LocaleListener' => \true, 'Contao\ManagerApi\EventListener\LocaleListener.inner' => \true, '_ContaoManager\Contao\ManagerApi\EventListener\SecurityListener' => \true, '_ContaoManager\Contao\ManagerApi\Exception\ApiProblemException' => \true, '_ContaoManager\Contao\ManagerApi\Exception\InvalidJsonException' => \true, '_ContaoManager\Contao\ManagerApi\Exception\InvalidTotpException' => \true, '_ContaoManager\Contao\ManagerApi\Exception\ProcessOutputException' => \true, '_ContaoManager\Contao\ManagerApi\Exception\RequestException' => \true, '_ContaoManager\Contao\ManagerApi\HttpKernel\ApiProblemResponse' => \true, '_ContaoManager\Contao\ManagerApi\IntegrityCheck\AllowUrlFopenCheck' => \true, '_ContaoManager\Contao\ManagerApi\IntegrityCheck\GraphicsLibCheck' => \true, '_ContaoManager\Contao\ManagerApi\IntegrityCheck\IntegrityCheckFactory' => \true, '_ContaoManager\Contao\ManagerApi\IntegrityCheck\MemoryLimitCheck' => \true, '_ContaoManager\Contao\ManagerApi\IntegrityCheck\PhpExtensionsCheck' => \true, '_ContaoManager\Contao\ManagerApi\IntegrityCheck\ProcessCheck' => \true, '_ContaoManager\Contao\ManagerApi\IntegrityCheck\SessionCheck' => \true, '_ContaoManager\Contao\ManagerApi\IntegrityCheck\SymlinkCheck' => \true, '_ContaoManager\Contao\ManagerApi\IntegrityCheck\SysTempDirCheck' => \true, '_ContaoManager\Contao\ManagerApi\IntegrityCheck\ZipCheck' => \true, '_ContaoManager\Contao\ManagerApi\Process\ConsoleProcessFactory' => \true, '_ContaoManager\Contao\ManagerApi\Process\ContaoApi' => \true, '_ContaoManager\Contao\ManagerApi\Process\ContaoConsole' => \true, '_ContaoManager\Contao\ManagerApi\Process\Forker\DisownForker' => \true, '_ContaoManager\Contao\ManagerApi\Process\Forker\InlineForker' => \true, '_ContaoManager\Contao\ManagerApi\Process\Forker\NohupForker' => \true, '_ContaoManager\Contao\ManagerApi\Process\Forker\WindowsStartForker' => \true, '_ContaoManager\Contao\ManagerApi\Process\PhpExecutableFinder' => \true, '_ContaoManager\Contao\ManagerApi\Process\ProcessController' => \true, '_ContaoManager\Contao\ManagerApi\Process\ProcessRunner' => \true, '_ContaoManager\Contao\ManagerApi\Process\Utf8Process' => \true, '_ContaoManager\Contao\ManagerApi\Resources' => \true, '_ContaoManager\Contao\ManagerApi\Security\AuthenticationTrustResolver' => \true, '_ContaoManager\Contao\ManagerApi\Security\JwtAuthenticator' => \true, '_ContaoManager\Contao\ManagerApi\Security\JwtManager' => \true, '_ContaoManager\Contao\ManagerApi\Security\LoginAuthenticator' => \true, '_ContaoManager\Contao\ManagerApi\Security\PasswordlessAuthenticator' => \true, '_ContaoManager\Contao\ManagerApi\Security\TokenAuthenticator' => \true, '_ContaoManager\Contao\ManagerApi\Security\TotpBadge' => \true, '_ContaoManager\Contao\ManagerApi\Security\User' => \true, '_ContaoManager\Contao\ManagerApi\Security\UserProvider' => \true, '_ContaoManager\Contao\ManagerApi\Security\WebauthnAuthenticator' => \true, '_ContaoManager\Contao\ManagerApi\System\Request' => \true, '_ContaoManager\Contao\ManagerApi\System\SelfUpdate' => \true, '_ContaoManager\Contao\ManagerApi\System\ServerInfo' => \true, '_ContaoManager\Contao\ManagerApi\TaskOperation\Composer\ClearCacheOperation' => \true, '_ContaoManager\Contao\ManagerApi\TaskOperation\Composer\CloudOperation' => \true, '_ContaoManager\Contao\ManagerApi\TaskOperation\Composer\CreateProjectOperation' => \true, '_ContaoManager\Contao\ManagerApi\TaskOperation\Composer\DumpAutoloadOperation' => \true, '_ContaoManager\Contao\ManagerApi\TaskOperation\Composer\InstallOperation' => \true, '_ContaoManager\Contao\ManagerApi\TaskOperation\Composer\RemoveOperation' => \true, '_ContaoManager\Contao\ManagerApi\TaskOperation\Composer\RequireOperation' => \true, '_ContaoManager\Contao\ManagerApi\TaskOperation\Composer\UpdateOperation' => \true, '_ContaoManager\Contao\ManagerApi\TaskOperation\ConsoleOutput' => \true, '_ContaoManager\Contao\ManagerApi\TaskOperation\Contao\BackupCreateOperation' => \true, '_ContaoManager\Contao\ManagerApi\TaskOperation\Contao\BackupRestoreOperation' => \true, '_ContaoManager\Contao\ManagerApi\TaskOperation\Contao\CacheClearOperation' => \true, '_ContaoManager\Contao\ManagerApi\TaskOperation\Contao\CacheWarmupOperation' => \true, '_ContaoManager\Contao\ManagerApi\TaskOperation\Contao\CreateContaoOperation' => \true, '_ContaoManager\Contao\ManagerApi\TaskOperation\Contao\MaintenanceModeOperation' => \true, '_ContaoManager\Contao\ManagerApi\TaskOperation\Filesystem\InstallUploadsOperation' => \true, '_ContaoManager\Contao\ManagerApi\TaskOperation\Filesystem\RemoveArtifactsOperation' => \true, '_ContaoManager\Contao\ManagerApi\TaskOperation\Filesystem\RemoveCacheOperation' => \true, '_ContaoManager\Contao\ManagerApi\TaskOperation\Filesystem\RemoveUploadsOperation' => \true, '_ContaoManager\Contao\ManagerApi\TaskOperation\Filesystem\RemoveVendorOperation' => \true, '_ContaoManager\Contao\ManagerApi\TaskOperation\Manager\SelfUpdateOperation' => \true, '_ContaoManager\Contao\ManagerApi\TaskOperation\SponsoredOperationInterface' => \true, '_ContaoManager\Contao\ManagerApi\Task\Composer\ClearCacheTask' => \true, '_ContaoManager\Contao\ManagerApi\Task\Composer\DumpAutoloadTask' => \true, '_ContaoManager\Contao\ManagerApi\Task\Contao\BackupCreateTask' => \true, '_ContaoManager\Contao\ManagerApi\Task\Contao\BackupRestoreTask' => \true, '_ContaoManager\Contao\ManagerApi\Task\Contao\RebuildCacheTask' => \true, '_ContaoManager\Contao\ManagerApi\Task\Manager\SelfUpdateTask' => \true, '_ContaoManager\Contao\ManagerApi\Task\Packages\InstallTask' => \true, '_ContaoManager\Contao\ManagerApi\Task\Packages\SetupTask' => \true, '_ContaoManager\Contao\ManagerApi\Task\Packages\UpdateTask' => \true, '_ContaoManager\Contao\ManagerApi\Task\TaskConfig' => \true, '_ContaoManager\Contao\ManagerApi\Task\TaskManager' => \true, '_ContaoManager\Contao\ManagerApi\Task\TaskStatus' => \true, '_ContaoManager\Contao\ManagerApi\Tests' => \true, '_ContaoManager\Psr\Cache\CacheItemPoolInterface' => \true, '_ContaoManager\Psr\Clock\ClockInterface' => \true, 'Psr\Container\ContainerInterface $parameterBag' => \true, '_ContaoManager\Psr\EventDispatcher\EventDispatcherInterface' => \true, '_ContaoManager\Psr\Log\LoggerInterface' => \true, 'Psr\Log\LoggerInterface $cacheLogger' => \true, 'Psr\Log\LoggerInterface $consoleLogger' => \true, 'Psr\Log\LoggerInterface $phpLogger' => \true, 'Psr\Log\LoggerInterface $requestLogger' => \true, 'Psr\Log\LoggerInterface $routerLogger' => \true, 'Psr\Log\LoggerInterface $securityLogger' => \true, 'Psr\Log\LoggerInterface $tasksLogger' => \true, '_ContaoManager\Symfony\Bundle\SecurityBundle\Security' => \true, '_ContaoManager\Symfony\Component\Clock\ClockInterface' => \true, '_ContaoManager\Symfony\Component\Config\Loader\LoaderInterface' => \true, '_ContaoManager\Symfony\Component\DependencyInjection\ParameterBag\ContainerBagInterface' => \true, '_ContaoManager\Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface' => \true, '_ContaoManager\Symfony\Component\DependencyInjection\ReverseContainer' => \true, '_ContaoManager\Symfony\Component\ErrorHandler\ErrorRenderer\FileLinkFormatter' => \true, '_ContaoManager\Symfony\Component\EventDispatcher\EventDispatcherInterface' => \true, '_ContaoManager\Symfony\Component\Filesystem\Filesystem' => \true, '_ContaoManager\Symfony\Component\HttpFoundation\Request' => \true, '_ContaoManager\Symfony\Component\HttpFoundation\RequestStack' => \true, '_ContaoManager\Symfony\Component\HttpFoundation\Response' => \true, '_ContaoManager\Symfony\Component\HttpFoundation\Session\SessionInterface' => \true, '_ContaoManager\Symfony\Component\HttpFoundation\UriSigner' => \true, '_ContaoManager\Symfony\Component\HttpFoundation\UrlHelper' => \true, '_ContaoManager\Symfony\Component\HttpKernel\Config\FileLocator' => \true, '_ContaoManager\Symfony\Component\HttpKernel\Fragment\FragmentUriGeneratorInterface' => \true, '_ContaoManager\Symfony\Component\HttpKernel\HttpCache\StoreInterface' => \true, '_ContaoManager\Symfony\Component\HttpKernel\HttpKernelInterface' => \true, '_ContaoManager\Symfony\Component\HttpKernel\KernelInterface' => \true, '_ContaoManager\Symfony\Component\HttpKernel\UriSigner' => \true, '_ContaoManager\Symfony\Component\PasswordHasher\Hasher\PasswordHasherFactoryInterface' => \true, '_ContaoManager\Symfony\Component\PasswordHasher\Hasher\UserPasswordHasherInterface' => \true, '_ContaoManager\Symfony\Component\PropertyAccess\PropertyAccessorInterface' => \true, '_ContaoManager\Symfony\Component\PropertyInfo\PropertyAccessExtractorInterface' => \true, '_ContaoManager\Symfony\Component\PropertyInfo\PropertyDescriptionExtractorInterface' => \true, '_ContaoManager\Symfony\Component\PropertyInfo\PropertyInfoExtractorInterface' => \true, '_ContaoManager\Symfony\Component\PropertyInfo\PropertyInitializableExtractorInterface' => \true, '_ContaoManager\Symfony\Component\PropertyInfo\PropertyListExtractorInterface' => \true, '_ContaoManager\Symfony\Component\PropertyInfo\PropertyReadInfoExtractorInterface' => \true, '_ContaoManager\Symfony\Component\PropertyInfo\PropertyTypeExtractorInterface' => \true, '_ContaoManager\Symfony\Component\PropertyInfo\PropertyWriteInfoExtractorInterface' => \true, '_ContaoManager\Symfony\Component\Routing\Generator\UrlGeneratorInterface' => \true, '_ContaoManager\Symfony\Component\Routing\Matcher\UrlMatcherInterface' => \true, '_ContaoManager\Symfony\Component\Routing\RequestContext' => \true, '_ContaoManager\Symfony\Component\Routing\RequestContextAwareInterface' => \true, '_ContaoManager\Symfony\Component\Routing\RouterInterface' => \true, '_ContaoManager\Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface' => \true, '_ContaoManager\Symfony\Component\Security\Core\Authorization\AccessDecisionManagerInterface' => \true, '_ContaoManager\Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface' => \true, '_ContaoManager\Symfony\Component\Security\Core\Role\RoleHierarchyInterface' => \true, '_ContaoManager\Symfony\Component\Security\Core\Security' => \true, '_ContaoManager\Symfony\Component\Security\Core\User\UserCheckerInterface' => \true, '_ContaoManager\Symfony\Component\Security\Core\User\UserProviderInterface' => \true, '_ContaoManager\Symfony\Component\Security\Http\Authentication\AuthenticationUtils' => \true, '_ContaoManager\Symfony\Component\Security\Http\Authentication\UserAuthenticatorInterface' => \true, '_ContaoManager\Symfony\Component\Security\Http\Firewall' => \true, '_ContaoManager\Symfony\Component\Security\Http\FirewallMapInterface' => \true, '_ContaoManager\Symfony\Component\Security\Http\HttpUtils' => \true, '_ContaoManager\Symfony\Component\Security\Http\Session\SessionAuthenticationStrategyInterface' => \true, '_ContaoManager\Symfony\Component\Serializer\Encoder\DecoderInterface' => \true, '_ContaoManager\Symfony\Component\Serializer\Encoder\EncoderInterface' => \true, '_ContaoManager\Symfony\Component\Serializer\Mapping\ClassDiscriminatorResolverInterface' => \true, '_ContaoManager\Symfony\Component\Serializer\Mapping\Factory\ClassMetadataFactoryInterface' => \true, '_ContaoManager\Symfony\Component\Serializer\Normalizer\DenormalizerInterface' => \true, '_ContaoManager\Symfony\Component\Serializer\Normalizer\NormalizerInterface' => \true, '_ContaoManager\Symfony\Component\Serializer\Normalizer\ObjectNormalizer' => \true, '_ContaoManager\Symfony\Component\Serializer\Normalizer\PropertyNormalizer' => \true, '_ContaoManager\Symfony\Component\Serializer\SerializerInterface' => \true, '_ContaoManager\Symfony\Component\String\Slugger\SluggerInterface' => \true, '_ContaoManager\Symfony\Component\Uid\Factory\NameBasedUuidFactory' => \true, '_ContaoManager\Symfony\Component\Uid\Factory\RandomBasedUuidFactory' => \true, '_ContaoManager\Symfony\Component\Uid\Factory\TimeBasedUuidFactory' => \true, '_ContaoManager\Symfony\Component\Uid\Factory\UlidFactory' => \true, '_ContaoManager\Symfony\Component\Uid\Factory\UuidFactory' => \true, '_ContaoManager\Symfony\Contracts\Cache\CacheInterface' => \true, '_ContaoManager\Symfony\Contracts\Cache\TagAwareCacheInterface' => \true, '_ContaoManager\Symfony\Contracts\EventDispatcher\EventDispatcherInterface' => \true, 'argument_metadata_factory' => \true, 'argument_resolver' => \true, 'argument_resolver.backed_enum_resolver' => \true, 'argument_resolver.controller_locator' => \true, 'argument_resolver.datetime' => \true, 'argument_resolver.default' => \true, 'argument_resolver.query_parameter_value_resolver' => \true, 'argument_resolver.request' => \true, 'argument_resolver.request_attribute' => \true, 'argument_resolver.request_payload' => \true, 'argument_resolver.service' => \true, 'argument_resolver.session' => \true, 'argument_resolver.uid' => \true, 'argument_resolver.variadic' => \true, 'cache.adapter.apcu' => \true, 'cache.adapter.array' => \true, 'cache.adapter.doctrine_dbal' => \true, 'cache.adapter.filesystem' => \true, 'cache.adapter.memcached' => \true, 'cache.adapter.pdo' => \true, 'cache.adapter.psr6' => \true, 'cache.adapter.redis' => \true, 'cache.adapter.redis_tag_aware' => \true, 'cache.adapter.system' => \true, 'cache.annotations' => \true, 'cache.app.taggable' => \true, 'cache.default_clearer' => \true, 'cache.default_doctrine_dbal_provider' => \true, 'cache.default_marshaller' => \true, 'cache.default_memcached_provider' => \true, 'cache.default_redis_provider' => \true, 'cache.early_expiration_handler' => \true, 'cache.property_access' => \true, 'cache.property_info' => \true, 'cache.security_expression_language' => \true, 'cache.serializer' => \true, 'cache.validator' => \true, 'cache_clearer' => \true, 'clock' => \true, 'config.resource.self_checking_resource_checker' => \true, 'config_builder.warmer' => \true, 'config_cache_factory' => \true, 'console.command.about' => \true, 'console.command.assets_install' => \true, 'console.command.cache_clear' => \true, 'console.command.cache_pool_clear' => \true, 'console.command.cache_pool_delete' => \true, 'console.command.cache_pool_invalidate_tags' => \true, 'console.command.cache_pool_list' => \true, 'console.command.cache_pool_prune' => \true, 'console.command.cache_warmup' => \true, 'console.command.config_debug' => \true, 'console.command.config_dump_reference' => \true, 'console.command.container_debug' => \true, 'console.command.container_lint' => \true, 'console.command.debug_autowiring' => \true, 'console.command.event_dispatcher_debug' => \true, 'console.command.router_debug' => \true, 'console.command.router_match' => \true, 'console.command.secrets_decrypt_to_local' => \true, 'console.command.secrets_encrypt_from_local' => \true, 'console.command.secrets_generate_key' => \true, 'console.command.secrets_list' => \true, 'console.command.secrets_remove' => \true, 'console.command.secrets_set' => \true, 'console.command.serializer_debug' => \true, 'console.command.yaml_lint' => \true, 'console.error_listener' => \true, 'console.messenger.application' => \true, 'console.messenger.execute_command_handler' => \true, 'console.suggest_missing_package_subscriber' => \true, 'container.env' => \true, 'container.env_var_processor' => \true, 'container.getenv' => \true, 'contao_manager.security.authentication_trust_resolver' => \true, 'contao_manager.security.authentication_trust_resolver.inner' => \true, 'contao_manager.webauthn.authenticator_assertion_response_validator' => \true, 'contao_manager.webauthn.authenticator_attestation_response_validator' => \true, 'contao_manager.webauthn.ceremony_step_manager_factory' => \true, 'contao_manager.webauthn.creation_ceremony' => \true, 'contao_manager.webauthn.request_ceremony' => \true, 'contao_manager.webauthn.serializer' => \true, 'contao_manager.webauthn.serializer_factory' => \true, 'controller.cache_attribute_listener' => \true, 'controller.is_granted_attribute_listener' => \true, 'controller_resolver' => \true, 'data_collector.security' => \true, 'debug.debug_handlers_listener' => \true, 'debug.file_link_formatter' => \true, 'dependency_injection.config.container_parameters_resource_checker' => \true, 'error_handler.error_renderer.html' => \true, 'error_handler.error_renderer.serializer' => \true, 'error_renderer' => \true, 'error_renderer.html' => \true, 'error_renderer.serializer' => \true, 'exception_listener' => \true, 'file_locator' => \true, 'filesystem' => \true, 'fragment.handler' => \true, 'fragment.renderer.inline' => \true, 'fragment.uri_generator' => \true, 'http_cache' => \true, 'http_cache.store' => \true, 'locale_aware_listener' => \true, 'locale_listener' => \true, 'logger' => \true, 'monolog.activation_strategy.not_found' => \true, 'monolog.formatter.chrome_php' => \true, 'monolog.formatter.gelf_message' => \true, 'monolog.formatter.html' => \true, 'monolog.formatter.json' => \true, 'monolog.formatter.line' => \true, 'monolog.formatter.loggly' => \true, 'monolog.formatter.logstash' => \true, 'monolog.formatter.normalizer' => \true, 'monolog.formatter.scalar' => \true, 'monolog.formatter.syslog' => \true, 'monolog.formatter.wildfire' => \true, 'monolog.handler.file' => \true, 'monolog.handler.fingers_crossed.error_level_activation_strategy' => \true, 'monolog.handler.main' => \true, 'monolog.handler.null_internal' => \true, 'monolog.http_client' => \true, 'monolog.logger' => \true, 'monolog.logger.cache' => \true, 'monolog.logger.console' => \true, 'monolog.logger.php' => \true, 'monolog.logger.request' => \true, 'monolog.logger.router' => \true, 'monolog.logger.security' => \true, 'monolog.logger.tasks' => \true, 'monolog.logger_prototype' => \true, 'monolog.processor.psr_log_message' => \true, 'name_based_uuid.factory' => \true, 'parameter_bag' => \true, 'process.messenger.process_message_handler' => \true, 'property_accessor' => \true, 'property_info' => \true, 'property_info.cache' => \true, 'property_info.cache.inner' => \true, 'property_info.php_doc_extractor' => \true, 'property_info.phpstan_extractor' => \true, 'property_info.reflection_extractor' => \true, 'property_info.serializer_extractor' => \true, 'random_based_uuid.factory' => \true, 'response_listener' => \true, 'reverse_container' => \true, 'router.cache_warmer' => \true, 'router.default' => \true, 'router.request_context' => \true, 'router_listener' => \true, 'routing.loader.annotation' => \true, 'routing.loader.annotation.directory' => \true, 'routing.loader.annotation.file' => \true, 'routing.loader.attribute' => \true, 'routing.loader.attribute.directory' => \true, 'routing.loader.attribute.file' => \true, 'routing.loader.container' => \true, 'routing.loader.directory' => \true, 'routing.loader.glob' => \true, 'routing.loader.php' => \true, 'routing.loader.psr4' => \true, 'routing.loader.xml' => \true, 'routing.loader.yml' => \true, 'routing.resolver' => \true, 'secrets.decryption_key' => \true, 'secrets.local_vault' => \true, 'secrets.vault' => \true, 'security.access.authenticated_voter' => \true, 'security.access.decision_manager' => \true, 'security.access.role_hierarchy_voter' => \true, 'security.access_listener' => \true, 'security.access_map' => \true, 'security.access_token_extractor.header' => \true, 'security.access_token_extractor.query_string' => \true, 'security.access_token_extractor.request_body' => \true, 'security.access_token_handler.oidc' => \true, 'security.access_token_handler.oidc.jwk' => \true, 'security.access_token_handler.oidc.signature' => \true, 'security.access_token_handler.oidc.signature.ES256' => \true, 'security.access_token_handler.oidc.signature.ES384' => \true, 'security.access_token_handler.oidc.signature.ES512' => \true, 'security.access_token_handler.oidc_user_info' => \true, 'security.access_token_handler.oidc_user_info.http_client' => \true, 'security.authentication.custom_failure_handler' => \true, 'security.authentication.custom_success_handler' => \true, 'security.authentication.failure_handler' => \true, 'security.authentication.listener.abstract' => \true, 'security.authentication.session_strategy' => \true, 'security.authentication.session_strategy.api' => \true, 'security.authentication.session_strategy_noop' => \true, 'security.authentication.success_handler' => \true, 'security.authentication.switchuser_listener' => \true, 'security.authentication.trust_resolver' => \true, 'security.authentication_utils' => \true, 'security.authenticator.access_token' => \true, 'security.authenticator.access_token.chain_extractor' => \true, 'security.authenticator.form_login' => \true, 'security.authenticator.http_basic' => \true, 'security.authenticator.json_login' => \true, 'security.authenticator.manager' => \true, 'security.authenticator.manager.api' => \true, 'security.authenticator.managers_locator' => \true, 'security.authenticator.remote_user' => \true, 'security.authenticator.x509' => \true, 'security.authorization_checker' => \true, 'security.channel_listener' => \true, 'security.command.debug_firewall' => \true, 'security.command.user_password_hash' => \true, 'security.context_listener' => \true, 'security.event_dispatcher.api' => \true, 'security.exception_listener' => \true, 'security.exception_listener.api' => \true, 'security.firewall' => \true, 'security.firewall.authenticator' => \true, 'security.firewall.authenticator.api' => \true, 'security.firewall.config' => \true, 'security.firewall.context' => \true, 'security.firewall.context_locator' => \true, 'security.firewall.event_dispatcher_locator' => \true, 'security.firewall.lazy_context' => \true, 'security.firewall.map' => \true, 'security.firewall.map.config.api' => \true, 'security.firewall.map.context.api' => \true, 'security.helper' => \true, 'security.http_utils' => \true, 'security.impersonate_url_generator' => \true, 'security.ldap_locator' => \true, 'security.listener.api.user_provider' => \true, 'security.listener.check_authenticator_credentials' => \true, 'security.listener.login_throttling' => \true, 'security.listener.password_migrating' => \true, 'security.listener.session' => \true, 'security.listener.user_checker' => \true, 'security.listener.user_checker.api' => \true, 'security.listener.user_provider' => \true, 'security.listener.user_provider.abstract' => \true, 'security.logout.listener.clear_site_data' => \true, 'security.logout.listener.cookie_clearing' => \true, 'security.logout.listener.default' => \true, 'security.logout.listener.session' => \true, 'security.logout_listener' => \true, 'security.logout_url_generator' => \true, 'security.password_hasher' => \true, 'security.password_hasher_factory' => \true, 'security.role_hierarchy' => \true, 'security.route_loader.logout' => \true, 'security.security_token_value_resolver' => \true, 'security.untracked_token_storage' => \true, 'security.user.provider.chain' => \true, 'security.user.provider.concrete.contao_manager_user_provider' => \true, 'security.user.provider.in_memory' => \true, 'security.user.provider.ldap' => \true, 'security.user.provider.missing' => \true, 'security.user_authenticator' => \true, 'security.user_checker' => \true, 'security.user_checker.api' => \true, 'security.user_checker.chain.api' => \true, 'security.user_checker_locator' => \true, 'security.user_password_hasher' => \true, 'security.user_providers' => \true, 'security.user_value_resolver' => \true, 'security.validator.user_password' => \true, 'serializer' => \true, 'serializer.denormalizer.array' => \true, 'serializer.denormalizer.unwrapping' => \true, 'serializer.encoder.csv' => \true, 'serializer.encoder.json' => \true, 'serializer.encoder.xml' => \true, 'serializer.encoder.yaml' => \true, 'serializer.mapping.cache.symfony' => \true, 'serializer.mapping.cache_class_metadata_factory' => \true, 'serializer.mapping.cache_class_metadata_factory.inner' => \true, 'serializer.mapping.cache_warmer' => \true, 'serializer.mapping.chain_loader' => \true, 'serializer.mapping.class_discriminator_resolver' => \true, 'serializer.mapping.class_metadata_factory' => \true, 'serializer.name_converter.camel_case_to_snake_case' => \true, 'serializer.name_converter.metadata_aware' => \true, 'serializer.normalizer.backed_enum' => \true, 'serializer.normalizer.constraint_violation_list' => \true, 'serializer.normalizer.data_uri' => \true, 'serializer.normalizer.dateinterval' => \true, 'serializer.normalizer.datetime' => \true, 'serializer.normalizer.datetimezone' => \true, 'serializer.normalizer.form_error' => \true, 'serializer.normalizer.json_serializable' => \true, 'serializer.normalizer.object' => \true, 'serializer.normalizer.problem' => \true, 'serializer.normalizer.property' => \true, 'serializer.normalizer.uid' => \true, 'serializer.property_accessor' => \true, 'slugger' => \true, 'time_based_uuid.factory' => \true, 'ulid.factory' => \true, 'uri_signer' => \true, 'url_helper' => \true, 'uuid.factory' => \true, 'validate_request_listener' => \true];
<?php

namespace _ContaoManager\ContainerLiF9Qbu;

use _ContaoManager\Symfony\Component\DependencyInjection\Argument\RewindableGenerator;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\RuntimeException;
/*
 * @internal This class has been auto-generated by the Symfony Dependency Injection Component.
 */
class getProcessRunnerCommandService extends Contao_ManagerApi_ApiKernelProdContainer
{
    /*
     * Gets the public 'Contao\ManagerApi\Command\ProcessRunnerCommand' shared autowired service.
     *
     * @return \Contao\ManagerApi\Command\ProcessRunnerCommand
     */
    public static function do($container, $lazyLoad = \true)
    {
        $container->services['Contao\ManagerApi\Command\ProcessRunnerCommand'] = $instance = new \_ContaoManager\Contao\ManagerApi\Command\ProcessRunnerCommand();
        $instance->setName('background-task:run');
        $instance->setDescription('Execute a background task');
        return $instance;
    }
}
<?php

namespace _ContaoManager\ContainerLiF9Qbu;

use _ContaoManager\Symfony\Component\DependencyInjection\Argument\RewindableGenerator;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\RuntimeException;
/*
 * @internal This class has been auto-generated by the Symfony Dependency Injection Component.
 */
class getJwtAuthenticatorService extends Contao_ManagerApi_ApiKernelProdContainer
{
    /*
     * Gets the private 'Contao\ManagerApi\Security\JwtAuthenticator' shared autowired service.
     *
     * @return \Contao\ManagerApi\Security\JwtAuthenticator
     */
    public static function do($container, $lazyLoad = \true)
    {
        return $container->privates['Contao\ManagerApi\Security\JwtAuthenticator'] = new \_ContaoManager\Contao\ManagerApi\Security\JwtAuthenticator($container->privates['Contao\ManagerApi\Security\UserProvider'] ?? $container->load('getUserProviderService'), $container->privates['Contao\ManagerApi\Security\JwtManager'] ?? self::getJwtManagerService($container));
    }
}
<?php

namespace _ContaoManager\ContainerLiF9Qbu;

use _ContaoManager\Symfony\Component\DependencyInjection\Argument\RewindableGenerator;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\RuntimeException;
/*
 * @internal This class has been auto-generated by the Symfony Dependency Injection Component.
 */
class getContaoControllerService extends Contao_ManagerApi_ApiKernelProdContainer
{
    /*
     * Gets the public 'Contao\ManagerApi\Controller\Server\ContaoController' shared autowired service.
     *
     * @return \Contao\ManagerApi\Controller\Server\ContaoController
     */
    public static function do($container, $lazyLoad = \true)
    {
        return $container->services['Contao\ManagerApi\Controller\Server\ContaoController'] = new \_ContaoManager\Contao\ManagerApi\Controller\Server\ContaoController($container->services['kernel'] ?? $container->get('kernel', 1), $container->privates['Contao\ManagerApi\Process\ContaoApi'] ?? $container->load('getContaoApiService'), $container->privates['Contao\ManagerApi\Process\ContaoConsole'] ?? $container->load('getContaoConsoleService'), $container->privates['Contao\ManagerApi\Process\ConsoleProcessFactory'] ?? $container->load('getConsoleProcessFactoryService'), $container->privates['monolog.logger'] ?? $container->load('getMonolog_LoggerService'), $container->privates['filesystem'] ??= new \_ContaoManager\Symfony\Component\Filesystem\Filesystem());
    }
}
<?php

namespace _ContaoManager\ContainerLiF9Qbu;

use _ContaoManager\Symfony\Component\DependencyInjection\Argument\RewindableGenerator;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\RuntimeException;
/*
 * @internal This class has been auto-generated by the Symfony Dependency Injection Component.
 */
class getSecurity_AccessMapService extends Contao_ManagerApi_ApiKernelProdContainer
{
    /*
     * Gets the private 'security.access_map' shared service.
     *
     * @return \Symfony\Component\Security\Http\AccessMap
     */
    public static function do($container, $lazyLoad = \true)
    {
        $container->privates['security.access_map'] = $instance = new \_ContaoManager\Symfony\Component\Security\Http\AccessMap();
        $instance->add(new \_ContaoManager\Symfony\Component\HttpFoundation\ChainRequestMatcher([new \_ContaoManager\Symfony\Component\HttpFoundation\RequestMatcher\PathRequestMatcher('^/api/session(/options)?$')]), ['PUBLIC_ACCESS'], NULL);
        $instance->add(new \_ContaoManager\Symfony\Component\HttpFoundation\ChainRequestMatcher([new \_ContaoManager\Symfony\Component\HttpFoundation\RequestMatcher\PathRequestMatcher('^/api')]), ['ROLE_USER'], NULL);
        return $instance;
    }
}
<?php

namespace _ContaoManager\ContainerLiF9Qbu;

use _ContaoManager\Symfony\Component\DependencyInjection\Argument\RewindableGenerator;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\RuntimeException;
/*
 * @internal This class has been auto-generated by the Symfony Dependency Injection Component.
 */
class getIntegrityCheckFactoryService extends Contao_ManagerApi_ApiKernelProdContainer
{
    /*
     * Gets the private 'Contao\ManagerApi\IntegrityCheck\IntegrityCheckFactory' shared autowired service.
     *
     * @return \Contao\ManagerApi\IntegrityCheck\IntegrityCheckFactory
     */
    public static function do($container, $lazyLoad = \true)
    {
        return $container->privates['Contao\ManagerApi\IntegrityCheck\IntegrityCheckFactory'] = new \_ContaoManager\Contao\ManagerApi\IntegrityCheck\IntegrityCheckFactory((new \_ContaoManager\Symfony\Component\DependencyInjection\Argument\ServiceLocator($container->getService ??= $container->getService(...), ['_ContaoManager\Contao\ManagerApi\IntegrityCheck\AllowUrlFopenCheck' => ['privates', '_ContaoManager\Contao\ManagerApi\IntegrityCheck\AllowUrlFopenCheck', 'getAllowUrlFopenCheckService', \true], '_ContaoManager\Contao\ManagerApi\IntegrityCheck\GraphicsLibCheck' => ['privates', '_ContaoManager\Contao\ManagerApi\IntegrityCheck\GraphicsLibCheck', 'getGraphicsLibCheckService', \true], '_ContaoManager\Contao\ManagerApi\IntegrityCheck\MemoryLimitCheck' => ['privates', '_ContaoManager\Contao\ManagerApi\IntegrityCheck\MemoryLimitCheck', 'getMemoryLimitCheckService', \true], '_ContaoManager\Contao\ManagerApi\IntegrityCheck\PhpExtensionsCheck' => ['privates', '_ContaoManager\Contao\ManagerApi\IntegrityCheck\PhpExtensionsCheck', 'getPhpExtensionsCheckService', \true], '_ContaoManager\Contao\ManagerApi\IntegrityCheck\ProcessCheck' => ['privates', '_ContaoManager\Contao\ManagerApi\IntegrityCheck\ProcessCheck', 'getProcessCheckService', \true], '_ContaoManager\Contao\ManagerApi\IntegrityCheck\SessionCheck' => ['privates', '_ContaoManager\Contao\ManagerApi\IntegrityCheck\SessionCheck', 'getSessionCheckService', \true], '_ContaoManager\Contao\ManagerApi\IntegrityCheck\SymlinkCheck' => ['privates', '_ContaoManager\Contao\ManagerApi\IntegrityCheck\SymlinkCheck', 'getSymlinkCheckService', \true], '_ContaoManager\Contao\ManagerApi\IntegrityCheck\SysTempDirCheck' => ['privates', '_ContaoManager\Contao\ManagerApi\IntegrityCheck\SysTempDirCheck', 'getSysTempDirCheckService', \true]], ['_ContaoManager\Contao\ManagerApi\IntegrityCheck\AllowUrlFopenCheck' => '_ContaoManager\Contao\ManagerApi\IntegrityCheck\AllowUrlFopenCheck', '_ContaoManager\Contao\ManagerApi\IntegrityCheck\GraphicsLibCheck' => '_ContaoManager\Contao\ManagerApi\IntegrityCheck\GraphicsLibCheck', '_ContaoManager\Contao\ManagerApi\IntegrityCheck\MemoryLimitCheck' => '_ContaoManager\Contao\ManagerApi\IntegrityCheck\MemoryLimitCheck', '_ContaoManager\Contao\ManagerApi\IntegrityCheck\PhpExtensionsCheck' => '_ContaoManager\Contao\ManagerApi\IntegrityCheck\PhpExtensionsCheck', '_ContaoManager\Contao\ManagerApi\IntegrityCheck\ProcessCheck' => '_ContaoManager\Contao\ManagerApi\IntegrityCheck\ProcessCheck', '_ContaoManager\Contao\ManagerApi\IntegrityCheck\SessionCheck' => '_ContaoManager\Contao\ManagerApi\IntegrityCheck\SessionCheck', '_ContaoManager\Contao\ManagerApi\IntegrityCheck\SymlinkCheck' => '_ContaoManager\Contao\ManagerApi\IntegrityCheck\SymlinkCheck', '_ContaoManager\Contao\ManagerApi\IntegrityCheck\SysTempDirCheck' => '_ContaoManager\Contao\ManagerApi\IntegrityCheck\SysTempDirCheck']))->withContext('_ContaoManager\Contao\ManagerApi\IntegrityCheck\IntegrityCheckFactory', $container));
    }
}
<?php

namespace _ContaoManager\ContainerLiF9Qbu;

use _ContaoManager\Symfony\Component\DependencyInjection\Argument\RewindableGenerator;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\RuntimeException;
/*
 * @internal This class has been auto-generated by the Symfony Dependency Injection Component.
 */
class getConsole_Command_ContainerDebugService extends Contao_ManagerApi_ApiKernelProdContainer
{
    /*
     * Gets the private 'console.command.container_debug' shared service.
     *
     * @return \Symfony\Bundle\FrameworkBundle\Command\ContainerDebugCommand
     */
    public static function do($container, $lazyLoad = \true)
    {
        $container->privates['console.command.container_debug'] = $instance = new \_ContaoManager\Symfony\Bundle\FrameworkBundle\Command\ContainerDebugCommand();
        $instance->setName('debug:container');
        $instance->setDescription('Display current services for an application');
        return $instance;
    }
}
<?php

namespace _ContaoManager\ContainerLiF9Qbu;

use _ContaoManager\Symfony\Component\DependencyInjection\Argument\RewindableGenerator;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\RuntimeException;
/*
 * @internal This class has been auto-generated by the Symfony Dependency Injection Component.
 */
class get_Console_Command_ContainerDebug_LazyService extends Contao_ManagerApi_ApiKernelProdContainer
{
    /*
     * Gets the private '.console.command.container_debug.lazy' shared service.
     *
     * @return \Symfony\Component\Console\Command\LazyCommand
     */
    public static function do($container, $lazyLoad = \true)
    {
        return $container->privates['.console.command.container_debug.lazy'] = new \_ContaoManager\Symfony\Component\Console\Command\LazyCommand('debug:container', [], 'Display current services for an application', \false, #[\Closure(name: 'console.command.container_debug', class: '_ContaoManager\Symfony\Bundle\FrameworkBundle\Command\ContainerDebugCommand')] fn(): \_ContaoManager\Symfony\Bundle\FrameworkBundle\Command\ContainerDebugCommand => $container->privates['console.command.container_debug'] ?? $container->load('getConsole_Command_ContainerDebugService'));
    }
}
<?php

namespace _ContaoManager\ContainerLiF9Qbu;

use _ContaoManager\Symfony\Component\DependencyInjection\Argument\RewindableGenerator;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\RuntimeException;
/*
 * @internal This class has been auto-generated by the Symfony Dependency Injection Component.
 */
class getWebauthnAuthenticatorService extends Contao_ManagerApi_ApiKernelProdContainer
{
    /*
     * Gets the private 'Contao\ManagerApi\Security\WebauthnAuthenticator' shared autowired service.
     *
     * @return \Contao\ManagerApi\Security\WebauthnAuthenticator
     */
    public static function do($container, $lazyLoad = \true)
    {
        $a = $container->services['event_dispatcher'] ?? self::getEventDispatcherService($container);
        if (isset($container->privates['Contao\ManagerApi\Security\WebauthnAuthenticator'])) {
            return $container->privates['Contao\ManagerApi\Security\WebauthnAuthenticator'];
        }
        $b = new \_ContaoManager\Webauthn\CeremonyStep\CeremonyStepManagerFactory();
        $c = new \_ContaoManager\Webauthn\AuthenticatorAttestationResponseValidator(NULL, NULL, NULL, NULL, $a, $b->creationCeremony());
        $d = $container->privates['monolog.logger'] ?? $container->load('getMonolog_LoggerService');
        $c->setLogger($d);
        $e = new \_ContaoManager\Webauthn\AuthenticatorAssertionResponseValidator(NULL, NULL, NULL, NULL, $a, $b->requestCeremony());
        $e->setLogger($d);
        $instance = new \_ContaoManager\Contao\ManagerApi\Security\WebauthnAuthenticator((new \_ContaoManager\Webauthn\Denormalizer\WebauthnSerializerFactory(new \_ContaoManager\Webauthn\AttestationStatement\AttestationStatementSupportManager()))->create(), $c, $e, $container->privates['Contao\ManagerApi\Security\UserProvider'] ?? $container->load('getUserProviderService'), $container->privates['Contao\ManagerApi\Config\UserConfig'] ?? self::getUserConfigService($container), $container->privates['Contao\ManagerApi\Security\JwtManager'] ?? self::getJwtManagerService($container), $container->privates['filesystem'] ??= new \_ContaoManager\Symfony\Component\Filesystem\Filesystem(), $container->services['kernel'] ?? $container->get('kernel', 1));
        if (isset($container->privates['Contao\ManagerApi\Security\WebauthnAuthenticator'])) {
            return $container->privates['Contao\ManagerApi\Security\WebauthnAuthenticator'];
        }
        return $container->privates['Contao\ManagerApi\Security\WebauthnAuthenticator'] = $instance;
    }
}
<?php

namespace _ContaoManager\ContainerLiF9Qbu;

use _ContaoManager\Symfony\Component\DependencyInjection\Argument\RewindableGenerator;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\RuntimeException;
/*
 * @internal This class has been auto-generated by the Symfony Dependency Injection Component.
 */
class getJwtCookieControllerService extends Contao_ManagerApi_ApiKernelProdContainer
{
    /*
     * Gets the public 'Contao\ManagerApi\Controller\Contao\JwtCookieController' shared autowired service.
     *
     * @return \Contao\ManagerApi\Controller\Contao\JwtCookieController
     */
    public static function do($container, $lazyLoad = \true)
    {
        return $container->services['Contao\ManagerApi\Controller\Contao\JwtCookieController'] = new \_ContaoManager\Contao\ManagerApi\Controller\Contao\JwtCookieController($container->privates['Contao\ManagerApi\Process\ContaoApi'] ?? $container->load('getContaoApiService'));
    }
}
<?php

namespace _ContaoManager\ContainerLiF9Qbu;

use _ContaoManager\Symfony\Component\DependencyInjection\Argument\RewindableGenerator;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\RuntimeException;
/*
 * @internal This class has been auto-generated by the Symfony Dependency Injection Component.
 */
class getRouter_CacheWarmerService extends Contao_ManagerApi_ApiKernelProdContainer
{
    /*
     * Gets the private 'router.cache_warmer' shared service.
     *
     * @return \Symfony\Bundle\FrameworkBundle\CacheWarmer\RouterCacheWarmer
     */
    public static function do($container, $lazyLoad = \true)
    {
        return $container->privates['router.cache_warmer'] = new \_ContaoManager\Symfony\Bundle\FrameworkBundle\CacheWarmer\RouterCacheWarmer((new \_ContaoManager\Symfony\Component\DependencyInjection\Argument\ServiceLocator($container->getService ??= $container->getService(...), ['router' => ['services', 'router', 'getRouterService', \false]], ['router' => '?']))->withContext('router.cache_warmer', $container));
    }
}
<?php

namespace _ContaoManager\ContainerLiF9Qbu;

use _ContaoManager\Symfony\Component\DependencyInjection\Argument\RewindableGenerator;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\RuntimeException;
/*
 * @internal This class has been auto-generated by the Symfony Dependency Injection Component.
 */
class getBackupRestoreTaskService extends Contao_ManagerApi_ApiKernelProdContainer
{
    /*
     * Gets the private 'Contao\ManagerApi\Task\Contao\BackupRestoreTask' shared autowired service.
     *
     * @return \Contao\ManagerApi\Task\Contao\BackupRestoreTask
     */
    public static function do($container, $lazyLoad = \true)
    {
        $container->privates['Contao\ManagerApi\Task\Contao\BackupRestoreTask'] = $instance = new \_ContaoManager\Contao\ManagerApi\Task\Contao\BackupRestoreTask($container->privates['Contao\ManagerApi\Process\ConsoleProcessFactory'] ?? $container->load('getConsoleProcessFactoryService'), $container->services['Contao\ManagerApi\I18n\Translator'] ?? $container->load('getTranslatorService'));
        $instance->setLogger($container->privates['monolog.logger.tasks'] ?? $container->load('getMonolog_Logger_TasksService'));
        return $instance;
    }
}
<?php

namespace _ContaoManager\ContainerLiF9Qbu;

use _ContaoManager\Symfony\Component\DependencyInjection\Argument\RewindableGenerator;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\RuntimeException;
/*
 * @internal This class has been auto-generated by the Symfony Dependency Injection Component.
 */
class getConsole_CommandLoaderService extends Contao_ManagerApi_ApiKernelProdContainer
{
    /*
     * Gets the public 'console.command_loader' shared service.
     *
     * @return \Symfony\Component\Console\CommandLoader\ContainerCommandLoader
     */
    public static function do($container, $lazyLoad = \true)
    {
        return $container->services['console.command_loader'] = new \_ContaoManager\Symfony\Component\Console\CommandLoader\ContainerCommandLoader(new \_ContaoManager\Symfony\Component\DependencyInjection\Argument\ServiceLocator($container->getService ??= $container->getService(...), ['_ContaoManager\Contao\ManagerApi\Command\AboutCommand' => ['privates', '.Contao\ManagerApi\Command\AboutCommand.lazy', 'getAboutCommand_LazyService', \true], '_ContaoManager\Contao\ManagerApi\Command\IntegrityCheckCommand' => ['privates', '.Contao\ManagerApi\Command\IntegrityCheckCommand.lazy', 'getIntegrityCheckCommand_LazyService', \true], '_ContaoManager\Contao\ManagerApi\Command\ProcessRunnerCommand' => ['privates', '.Contao\ManagerApi\Command\ProcessRunnerCommand.lazy', 'getProcessRunnerCommand_LazyService', \true], '_ContaoManager\Contao\ManagerApi\Command\TaskAbortCommand' => ['privates', '.Contao\ManagerApi\Command\TaskAbortCommand.lazy', 'getTaskAbortCommand_LazyService', \true], '_ContaoManager\Contao\ManagerApi\Command\TaskDeleteCommand' => ['privates', '.Contao\ManagerApi\Command\TaskDeleteCommand.lazy', 'getTaskDeleteCommand_LazyService', \true], '_ContaoManager\Contao\ManagerApi\Command\TaskUpdateCommand' => ['privates', '.Contao\ManagerApi\Command\TaskUpdateCommand.lazy', 'getTaskUpdateCommand_LazyService', \true], '_ContaoManager\Contao\ManagerApi\Command\UpdateCommand' => ['privates', '.Contao\ManagerApi\Command\UpdateCommand.lazy', 'getUpdateCommand_LazyService', \true], 'console.command.about' => ['privates', '.console.command.about.lazy', 'get_Console_Command_About_LazyService', \true], 'console.command.assets_install' => ['privates', '.console.command.assets_install.lazy', 'get_Console_Command_AssetsInstall_LazyService', \true], 'console.command.cache_clear' => ['privates', '.console.command.cache_clear.lazy', 'get_Console_Command_CacheClear_LazyService', \true], 'console.command.cache_pool_clear' => ['privates', '.console.command.cache_pool_clear.lazy', 'get_Console_Command_CachePoolClear_LazyService', \true], 'console.command.cache_pool_prune' => ['privates', '.console.command.cache_pool_prune.lazy', 'get_Console_Command_CachePoolPrune_LazyService', \true], 'console.command.cache_pool_invalidate_tags' => ['privates', '.console.command.cache_pool_invalidate_tags.lazy', 'get_Console_Command_CachePoolInvalidateTags_LazyService', \true], 'console.command.cache_pool_delete' => ['privates', '.console.command.cache_pool_delete.lazy', 'get_Console_Command_CachePoolDelete_LazyService', \true], 'console.command.cache_pool_list' => ['privates', '.console.command.cache_pool_list.lazy', 'get_Console_Command_CachePoolList_LazyService', \true], 'console.command.cache_warmup' => ['privates', '.console.command.cache_warmup.lazy', 'get_Console_Command_CacheWarmup_LazyService', \true], 'console.command.config_debug' => ['privates', '.console.command.config_debug.lazy', 'get_Console_Command_ConfigDebug_LazyService', \true], 'console.command.config_dump_reference' => ['privates', '.console.command.config_dump_reference.lazy', 'get_Console_Command_ConfigDumpReference_LazyService', \true], 'console.command.container_debug' => ['privates', '.console.command.container_debug.lazy', 'get_Console_Command_ContainerDebug_LazyService', \true], 'console.command.container_lint' => ['privates', '.console.command.container_lint.lazy', 'get_Console_Command_ContainerLint_LazyService', \true], 'console.command.debug_autowiring' => ['privates', '.console.command.debug_autowiring.lazy', 'get_Console_Command_DebugAutowiring_LazyService', \true], 'console.command.event_dispatcher_debug' => ['privates', '.console.command.event_dispatcher_debug.lazy', 'get_Console_Command_EventDispatcherDebug_LazyService', \true], 'console.command.router_debug' => ['privates', '.console.command.router_debug.lazy', 'get_Console_Command_RouterDebug_LazyService', \true], 'console.command.router_match' => ['privates', '.console.command.router_match.lazy', 'get_Console_Command_RouterMatch_LazyService', \true], 'console.command.serializer_debug' => ['privates', '.console.command.serializer_debug.lazy', 'get_Console_Command_SerializerDebug_LazyService', \true], 'console.command.yaml_lint' => ['privates', '.console.command.yaml_lint.lazy', 'get_Console_Command_YamlLint_LazyService', \true], 'console.command.secrets_set' => ['privates', '.console.command.secrets_set.lazy', 'get_Console_Command_SecretsSet_LazyService', \true], 'console.command.secrets_remove' => ['privates', '.console.command.secrets_remove.lazy', 'get_Console_Command_SecretsRemove_LazyService', \true], 'console.command.secrets_generate_key' => ['privates', '.console.command.secrets_generate_key.lazy', 'get_Console_Command_SecretsGenerateKey_LazyService', \true], 'console.command.secrets_list' => ['privates', '.console.command.secrets_list.lazy', 'get_Console_Command_SecretsList_LazyService', \true], 'console.command.secrets_decrypt_to_local' => ['privates', '.console.command.secrets_decrypt_to_local.lazy', 'get_Console_Command_SecretsDecryptToLocal_LazyService', \true], 'console.command.secrets_encrypt_from_local' => ['privates', '.console.command.secrets_encrypt_from_local.lazy', 'get_Console_Command_SecretsEncryptFromLocal_LazyService', \true], 'security.command.debug_firewall' => ['privates', '.security.command.debug_firewall.lazy', 'get_Security_Command_DebugFirewall_LazyService', \true], 'security.command.user_password_hash' => ['privates', '.security.command.user_password_hash.lazy', 'get_Security_Command_UserPasswordHash_LazyService', \true]], ['_ContaoManager\Contao\ManagerApi\Command\AboutCommand' => '?', '_ContaoManager\Contao\ManagerApi\Command\IntegrityCheckCommand' => '?', '_ContaoManager\Contao\ManagerApi\Command\ProcessRunnerCommand' => '?', '_ContaoManager\Contao\ManagerApi\Command\TaskAbortCommand' => '?', '_ContaoManager\Contao\ManagerApi\Command\TaskDeleteCommand' => '?', '_ContaoManager\Contao\ManagerApi\Command\TaskUpdateCommand' => '?', '_ContaoManager\Contao\ManagerApi\Command\UpdateCommand' => '?', 'console.command.about' => '?', 'console.command.assets_install' => '?', 'console.command.cache_clear' => '?', 'console.command.cache_pool_clear' => '?', 'console.command.cache_pool_prune' => '?', 'console.command.cache_pool_invalidate_tags' => '?', 'console.command.cache_pool_delete' => '?', 'console.command.cache_pool_list' => '?', 'console.command.cache_warmup' => '?', 'console.command.config_debug' => '?', 'console.command.config_dump_reference' => '?', 'console.command.container_debug' => '?', 'console.command.container_lint' => '?', 'console.command.debug_autowiring' => '?', 'console.command.event_dispatcher_debug' => '?', 'console.command.router_debug' => '?', 'console.command.router_match' => '?', 'console.command.serializer_debug' => '?', 'console.command.yaml_lint' => '?', 'console.command.secrets_set' => '?', 'console.command.secrets_remove' => '?', 'console.command.secrets_generate_key' => '?', 'console.command.secrets_list' => '?', 'console.command.secrets_decrypt_to_local' => '?', 'console.command.secrets_encrypt_from_local' => '?', 'security.command.debug_firewall' => '?', 'security.command.user_password_hash' => '?']), ['about' => 'console.command.about', 'integrity-check' => '_ContaoManager\Contao\ManagerApi\Command\IntegrityCheckCommand', 'background-task:run' => '_ContaoManager\Contao\ManagerApi\Command\ProcessRunnerCommand', 'task:abort' => '_ContaoManager\Contao\ManagerApi\Command\TaskAbortCommand', 'task:delete' => '_ContaoManager\Contao\ManagerApi\Command\TaskDeleteCommand', 'task:update' => '_ContaoManager\Contao\ManagerApi\Command\TaskUpdateCommand', 'self-update' => '_ContaoManager\Contao\ManagerApi\Command\UpdateCommand', 'assets:install' => 'console.command.assets_install', 'cache:clear' => 'console.command.cache_clear', 'cache:pool:clear' => 'console.command.cache_pool_clear', 'cache:pool:prune' => 'console.command.cache_pool_prune', 'cache:pool:invalidate-tags' => 'console.command.cache_pool_invalidate_tags', 'cache:pool:delete' => 'console.command.cache_pool_delete', 'cache:pool:list' => 'console.command.cache_pool_list', 'cache:warmup' => 'console.command.cache_warmup', 'debug:config' => 'console.command.config_debug', 'config:dump-reference' => 'console.command.config_dump_reference', 'debug:container' => 'console.command.container_debug', 'lint:container' => 'console.command.container_lint', 'debug:autowiring' => 'console.command.debug_autowiring', 'debug:event-dispatcher' => 'console.command.event_dispatcher_debug', 'debug:router' => 'console.command.router_debug', 'router:match' => 'console.command.router_match', 'debug:serializer' => 'console.command.serializer_debug', 'lint:yaml' => 'console.command.yaml_lint', 'secrets:set' => 'console.command.secrets_set', 'secrets:remove' => 'console.command.secrets_remove', 'secrets:generate-keys' => 'console.command.secrets_generate_key', 'secrets:list' => 'console.command.secrets_list', 'secrets:decrypt-to-local' => 'console.command.secrets_decrypt_to_local', 'secrets:encrypt-from-local' => 'console.command.secrets_encrypt_from_local', 'debug:firewall' => 'security.command.debug_firewall', 'security:hash-password' => 'security.command.user_password_hash']);
    }
}
<?php

namespace _ContaoManager\ContainerLiF9Qbu;

use _ContaoManager\Symfony\Component\DependencyInjection\Argument\RewindableGenerator;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\RuntimeException;
/*
 * @internal This class has been auto-generated by the Symfony Dependency Injection Component.
 */
class getCache_AppService extends Contao_ManagerApi_ApiKernelProdContainer
{
    /*
     * Gets the public 'cache.app' shared service.
     *
     * @return \Symfony\Component\Cache\Adapter\FilesystemAdapter
     */
    public static function do($container, $lazyLoad = \true)
    {
        $container->services['cache.app'] = $instance = new \_ContaoManager\Symfony\Component\Cache\Adapter\FilesystemAdapter('YbTXgffVaS', 0, $container->targetDir . '' . '/pools/app', new \_ContaoManager\Symfony\Component\Cache\Marshaller\DefaultMarshaller(NULL, \false));
        $instance->setLogger($container->privates['monolog.logger.cache'] ?? self::getMonolog_Logger_CacheService($container));
        return $instance;
    }
}
<?php

namespace _ContaoManager\ContainerLiF9Qbu;

use _ContaoManager\Symfony\Component\DependencyInjection\Argument\RewindableGenerator;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\RuntimeException;
/*
 * @internal This class has been auto-generated by the Symfony Dependency Injection Component.
 */
class getConsole_Command_SecretsSetService extends Contao_ManagerApi_ApiKernelProdContainer
{
    /*
     * Gets the private 'console.command.secrets_set' shared service.
     *
     * @return \Symfony\Bundle\FrameworkBundle\Command\SecretsSetCommand
     */
    public static function do($container, $lazyLoad = \true)
    {
        $container->privates['console.command.secrets_set'] = $instance = new \_ContaoManager\Symfony\Bundle\FrameworkBundle\Command\SecretsSetCommand($container->privates['secrets.vault'] ?? $container->load('getSecrets_VaultService'), $container->privates['secrets.local_vault'] ??= new \_ContaoManager\Symfony\Bundle\FrameworkBundle\Secrets\DotenvVault(\dirname(__DIR__, 4) . '/test-dir/.env.prod.local'));
        $instance->setName('secrets:set');
        $instance->setDescription('Set a secret in the vault');
        return $instance;
    }
}
<?php

namespace _ContaoManager\ContainerLiF9Qbu;

use _ContaoManager\Symfony\Component\DependencyInjection\Argument\RewindableGenerator;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\RuntimeException;
/*
 * @internal This class has been auto-generated by the Symfony Dependency Injection Component.
 */
class getSecurity_Command_UserPasswordHashService extends Contao_ManagerApi_ApiKernelProdContainer
{
    /*
     * Gets the private 'security.command.user_password_hash' shared service.
     *
     * @return \Symfony\Component\PasswordHasher\Command\UserPasswordHashCommand
     */
    public static function do($container, $lazyLoad = \true)
    {
        $container->privates['security.command.user_password_hash'] = $instance = new \_ContaoManager\Symfony\Component\PasswordHasher\Command\UserPasswordHashCommand($container->privates['security.password_hasher_factory'] ?? self::getSecurity_PasswordHasherFactoryService($container), ['_ContaoManager\Symfony\Component\Security\Core\User\PasswordAuthenticatedUserInterface']);
        $instance->setName('security:hash-password');
        $instance->setDescription('Hash a user password');
        return $instance;
    }
}
<?php

namespace _ContaoManager\ContainerLiF9Qbu;

use _ContaoManager\Symfony\Component\DependencyInjection\Argument\RewindableGenerator;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\RuntimeException;
/*
 * @internal This class has been auto-generated by the Symfony Dependency Injection Component.
 */
class getConsoleProcessFactoryService extends Contao_ManagerApi_ApiKernelProdContainer
{
    /*
     * Gets the private 'Contao\ManagerApi\Process\ConsoleProcessFactory' shared autowired service.
     *
     * @return \Contao\ManagerApi\Process\ConsoleProcessFactory
     */
    public static function do($container, $lazyLoad = \true)
    {
        $container->privates['Contao\ManagerApi\Process\ConsoleProcessFactory'] = $instance = new \_ContaoManager\Contao\ManagerApi\Process\ConsoleProcessFactory($container->services['kernel'] ?? $container->get('kernel', 1), $container->privates['Contao\ManagerApi\System\ServerInfo'] ?? $container->load('getServerInfoService'), $container->privates['filesystem'] ??= new \_ContaoManager\Symfony\Component\Filesystem\Filesystem());
        $instance->setLogger($container->privates['monolog.logger.tasks'] ?? $container->load('getMonolog_Logger_TasksService'));
        return $instance;
    }
}
<?php

namespace _ContaoManager\ContainerLiF9Qbu;

use _ContaoManager\Symfony\Component\DependencyInjection\Argument\RewindableGenerator;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\RuntimeException;
/*
 * @internal This class has been auto-generated by the Symfony Dependency Injection Component.
 */
class get_Console_Command_ConfigDumpReference_LazyService extends Contao_ManagerApi_ApiKernelProdContainer
{
    /*
     * Gets the private '.console.command.config_dump_reference.lazy' shared service.
     *
     * @return \Symfony\Component\Console\Command\LazyCommand
     */
    public static function do($container, $lazyLoad = \true)
    {
        return $container->privates['.console.command.config_dump_reference.lazy'] = new \_ContaoManager\Symfony\Component\Console\Command\LazyCommand('config:dump-reference', [], 'Dump the default configuration for an extension', \false, #[\Closure(name: 'console.command.config_dump_reference', class: '_ContaoManager\Symfony\Bundle\FrameworkBundle\Command\ConfigDumpReferenceCommand')] fn(): \_ContaoManager\Symfony\Bundle\FrameworkBundle\Command\ConfigDumpReferenceCommand => $container->privates['console.command.config_dump_reference'] ?? $container->load('getConsole_Command_ConfigDumpReferenceService'));
    }
}
<?php

namespace _ContaoManager\ContainerLiF9Qbu;

use _ContaoManager\Symfony\Component\DependencyInjection\Argument\RewindableGenerator;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\RuntimeException;
/*
 * @internal This class has been auto-generated by the Symfony Dependency Injection Component.
 */
class getCache_AppClearerService extends Contao_ManagerApi_ApiKernelProdContainer
{
    /*
     * Gets the public 'cache.app_clearer' shared service.
     *
     * @return \Symfony\Component\HttpKernel\CacheClearer\Psr6CacheClearer
     */
    public static function do($container, $lazyLoad = \true)
    {
        return $container->services['cache.app_clearer'] = new \_ContaoManager\Symfony\Component\HttpKernel\CacheClearer\Psr6CacheClearer(['cache.app' => $container->services['cache.app'] ?? $container->load('getCache_AppService')]);
    }
}
<?php

namespace _ContaoManager\ContainerLiF9Qbu;

use _ContaoManager\Symfony\Component\DependencyInjection\Argument\RewindableGenerator;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\RuntimeException;
/*
 * @internal This class has been auto-generated by the Symfony Dependency Injection Component.
 */
class getUserControllerService extends Contao_ManagerApi_ApiKernelProdContainer
{
    /*
     * Gets the public 'Contao\ManagerApi\Controller\UserController' shared autowired service.
     *
     * @return \Contao\ManagerApi\Controller\UserController
     */
    public static function do($container, $lazyLoad = \true)
    {
        return $container->services['Contao\ManagerApi\Controller\UserController'] = new \_ContaoManager\Contao\ManagerApi\Controller\UserController($container->privates['Contao\ManagerApi\Config\UserConfig'] ?? self::getUserConfigService($container), $container->services['router'] ?? self::getRouterService($container), $container->privates['security.helper'] ?? $container->load('getSecurity_HelperService'), $container->privates['security.password_hasher_factory'] ?? self::getSecurity_PasswordHasherFactoryService($container));
    }
}
<?php

namespace _ContaoManager\ContainerLiF9Qbu;

use _ContaoManager\Symfony\Component\DependencyInjection\Argument\RewindableGenerator;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\RuntimeException;
/*
 * @internal This class has been auto-generated by the Symfony Dependency Injection Component.
 */
class getConsole_Command_RouterDebugService extends Contao_ManagerApi_ApiKernelProdContainer
{
    /*
     * Gets the private 'console.command.router_debug' shared service.
     *
     * @return \Symfony\Bundle\FrameworkBundle\Command\RouterDebugCommand
     */
    public static function do($container, $lazyLoad = \true)
    {
        $container->privates['console.command.router_debug'] = $instance = new \_ContaoManager\Symfony\Bundle\FrameworkBundle\Command\RouterDebugCommand($container->services['router'] ?? self::getRouterService($container), $container->privates['debug.file_link_formatter'] ??= new \_ContaoManager\Symfony\Component\ErrorHandler\ErrorRenderer\FileLinkFormatter(NULL));
        $instance->setName('debug:router');
        $instance->setDescription('Display current routes for an application');
        return $instance;
    }
}
<?php

namespace _ContaoManager\ContainerLiF9Qbu;

use _ContaoManager\Symfony\Component\DependencyInjection\Argument\RewindableGenerator;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Container;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\LogicException;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\ParameterNotFoundException;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\RuntimeException;
use _ContaoManager\Symfony\Component\DependencyInjection\ParameterBag\FrozenParameterBag;
use _ContaoManager\Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface;
/*
 * @internal This class has been auto-generated by the Symfony Dependency Injection Component.
 */
class Contao_ManagerApi_ApiKernelProdContainer extends Container
{
    protected $targetDir;
    protected $parameters = [];
    protected \Closure $getService;
    public function __construct(private array $buildParameters = [], protected string $containerDir = __DIR__)
    {
        $this->targetDir = \dirname($containerDir);
        $this->parameters = $this->getDefaultParameters();
        $this->services = $this->privates = [];
        $this->syntheticIds = ['kernel' => \true];
        $this->methodMap = ['event_dispatcher' => 'getEventDispatcherService', 'http_kernel' => 'getHttpKernelService', 'request_stack' => 'getRequestStackService', 'router' => 'getRouterService', 'security.token_storage' => 'getSecurity_TokenStorageService'];
        $this->fileMap = ['_ContaoManager\Contao\ManagerApi\Command\AboutCommand' => 'getAboutCommandService', '_ContaoManager\Contao\ManagerApi\Command\IntegrityCheckCommand' => 'getIntegrityCheckCommandService', '_ContaoManager\Contao\ManagerApi\Command\ProcessRunnerCommand' => 'getProcessRunnerCommandService', '_ContaoManager\Contao\ManagerApi\Command\TaskAbortCommand' => 'getTaskAbortCommandService', '_ContaoManager\Contao\ManagerApi\Command\TaskDeleteCommand' => 'getTaskDeleteCommandService', '_ContaoManager\Contao\ManagerApi\Command\TaskUpdateCommand' => 'getTaskUpdateCommandService', '_ContaoManager\Contao\ManagerApi\Command\UpdateCommand' => 'getUpdateCommandService', '_ContaoManager\Contao\ManagerApi\Controller\Config\AuthController' => 'getAuthControllerService', '_ContaoManager\Contao\ManagerApi\Controller\Config\ComposerController' => 'getComposerControllerService', '_ContaoManager\Contao\ManagerApi\Controller\Config\ManagerController' => 'getManagerControllerService', '_ContaoManager\Contao\ManagerApi\Controller\ConstraintController' => 'getConstraintControllerService', '_ContaoManager\Contao\ManagerApi\Controller\Contao\AccessKeyController' => 'getAccessKeyControllerService', '_ContaoManager\Contao\ManagerApi\Controller\Contao\BackupController' => 'getBackupControllerService', '_ContaoManager\Contao\ManagerApi\Controller\Contao\DatabaseMigrationController' => 'getDatabaseMigrationControllerService', '_ContaoManager\Contao\ManagerApi\Controller\Contao\InstallToolLockController' => 'getInstallToolLockControllerService', '_ContaoManager\Contao\ManagerApi\Controller\Contao\JwtCookieController' => 'getJwtCookieControllerService', '_ContaoManager\Contao\ManagerApi\Controller\Contao\MaintenanceModeController' => 'getMaintenanceModeControllerService', '_ContaoManager\Contao\ManagerApi\Controller\FileController' => 'getFileControllerService', '_ContaoManager\Contao\ManagerApi\Controller\LogController' => 'getLogControllerService', '_ContaoManager\Contao\ManagerApi\Controller\Packages\CloudController' => 'getCloudControllerService', '_ContaoManager\Contao\ManagerApi\Controller\Packages\LocalPackagesController' => 'getLocalPackagesControllerService', '_ContaoManager\Contao\ManagerApi\Controller\Packages\MissingPackagesController' => 'getMissingPackagesControllerService', '_ContaoManager\Contao\ManagerApi\Controller\Packages\RootPackageController' => 'getRootPackageControllerService', '_ContaoManager\Contao\ManagerApi\Controller\Packages\UploadPackagesController' => 'getUploadPackagesControllerService', '_ContaoManager\Contao\ManagerApi\Controller\Server\AdminUserController' => 'getAdminUserControllerService', '_ContaoManager\Contao\ManagerApi\Controller\Server\ComposerController' => 'getComposerController2Service', '_ContaoManager\Contao\ManagerApi\Controller\Server\ConfigController' => 'getConfigControllerService', '_ContaoManager\Contao\ManagerApi\Controller\Server\ContaoController' => 'getContaoControllerService', '_ContaoManager\Contao\ManagerApi\Controller\Server\DatabaseController' => 'getDatabaseControllerService', '_ContaoManager\Contao\ManagerApi\Controller\Server\OpcacheController' => 'getOpcacheControllerService', '_ContaoManager\Contao\ManagerApi\Controller\Server\PhpCliController' => 'getPhpCliControllerService', '_ContaoManager\Contao\ManagerApi\Controller\Server\PhpWebController' => 'getPhpWebControllerService', '_ContaoManager\Contao\ManagerApi\Controller\Server\PhpinfoController' => 'getPhpinfoControllerService', '_ContaoManager\Contao\ManagerApi\Controller\Server\SelfUpdateController' => 'getSelfUpdateControllerService', '_ContaoManager\Contao\ManagerApi\Controller\SessionController' => 'getSessionControllerService', '_ContaoManager\Contao\ManagerApi\Controller\TaskController' => 'getTaskControllerService', '_ContaoManager\Contao\ManagerApi\Controller\UserController' => 'getUserControllerService', '_ContaoManager\Contao\ManagerApi\I18n\Translator' => 'getTranslatorService', '_ContaoManager\Symfony\Bundle\FrameworkBundle\Controller\RedirectController' => 'getRedirectControllerService', '_ContaoManager\Symfony\Bundle\FrameworkBundle\Controller\TemplateController' => 'getTemplateControllerService', 'cache.app' => 'getCache_AppService', 'cache.app_clearer' => 'getCache_AppClearerService', 'cache.global_clearer' => 'getCache_GlobalClearerService', 'cache.security_is_granted_attribute_expression_language' => 'getCache_SecurityIsGrantedAttributeExpressionLanguageService', 'cache.system' => 'getCache_SystemService', 'cache.system_clearer' => 'getCache_SystemClearerService', 'cache_warmer' => 'getCacheWarmerService', 'console.command_loader' => 'getConsole_CommandLoaderService', 'container.env_var_processors_locator' => 'getContainer_EnvVarProcessorsLocatorService', 'container.get_routing_condition_service' => 'getContainer_GetRoutingConditionServiceService', 'debug.error_handler_configurator' => 'getDebug_ErrorHandlerConfiguratorService', 'error_controller' => 'getErrorControllerService', 'routing.loader' => 'getRouting_LoaderService', 'services_resetter' => 'getServicesResetterService'];
        $this->aliases = [];
    }
    public function compile(): void
    {
        throw new LogicException('You cannot compile a dumped container that was already compiled.');
    }
    public function isCompiled(): bool
    {
        return \true;
    }
    public function getRemovedIds(): array
    {
        return require $this->containerDir . \DIRECTORY_SEPARATOR . 'removed-ids.php';
    }
    protected function load($file, $lazyLoad = \true): mixed
    {
        if (class_exists($class = __NAMESPACE__ . '\\' . $file, \false)) {
            return $class::do($this, $lazyLoad);
        }
        if ('.' === $file[-4]) {
            $class = substr($class, 0, -4);
        } else {
            $file .= '.php';
        }
        $service = require $this->containerDir . \DIRECTORY_SEPARATOR . $file;
        return class_exists($class, \false) ? $class::do($this, $lazyLoad) : $service;
    }
    protected function createProxy($class, \Closure $factory)
    {
        class_exists($class, \false) || require __DIR__ . '/' . $class . '.php';
        return $factory();
    }
    /*
     * Gets the public 'event_dispatcher' shared service.
     *
     * @return \Symfony\Component\EventDispatcher\EventDispatcher
     */
    protected static function getEventDispatcherService($container)
    {
        $instance = new \_ContaoManager\Symfony\Component\EventDispatcher\EventDispatcher();
        if (isset($container->services['event_dispatcher'])) {
            return $container->services['event_dispatcher'];
        }
        $container->services['event_dispatcher'] = $instance;
        $instance->addListener('_ContaoManager\Symfony\Component\Security\Http\Event\CheckPassportEvent', [#[\Closure(name: '_ContaoManager\Contao\ManagerApi\EventListener\CheckTotpListener')] fn() => $container->privates['Contao\ManagerApi\EventListener\CheckTotpListener'] ??= new \_ContaoManager\Contao\ManagerApi\EventListener\CheckTotpListener(), '__invoke'], 0);
        $instance->addListener('kernel.exception', [#[\Closure(name: '_ContaoManager\Contao\ManagerApi\EventListener\ExceptionListener')] fn() => $container->privates['Contao\ManagerApi\EventListener\ExceptionListener'] ?? $container->load('getExceptionListenerService'), '__invoke'], 10);
        $instance->addListener('kernel.request', [#[\Closure(name: '_ContaoManager\Contao\ManagerApi\EventListener\JsonRequestListener')] fn() => $container->privates['Contao\ManagerApi\EventListener\JsonRequestListener'] ??= new \_ContaoManager\Contao\ManagerApi\EventListener\JsonRequestListener(), '__invoke'], 20);
        $instance->addListener('kernel.response', [#[\Closure(name: '_ContaoManager\Contao\ManagerApi\EventListener\SecurityListener')] fn() => $container->privates['Contao\ManagerApi\EventListener\SecurityListener'] ?? self::getSecurityListenerService($container), '__invoke'], 0);
        $instance->addListener('_ContaoManager\Symfony\Component\Security\Http\Event\CheckPassportEvent', [#[\Closure(name: 'security.listener.user_provider', class: '_ContaoManager\Symfony\Component\Security\Http\EventListener\UserProviderListener')] fn() => $container->privates['security.listener.user_provider'] ?? $container->load('getSecurity_Listener_UserProviderService'), 'checkPassport'], 1024);
        $instance->addListener('kernel.request', [#[\Closure(name: '_ContaoManager\Contao\ManagerApi\EventListener\LocaleListener')] fn() => $container->privates['Contao\ManagerApi\EventListener\LocaleListener'] ?? self::getLocaleListenerService($container), 'setDefaultLocale'], 100);
        $instance->addListener('kernel.request', [#[\Closure(name: '_ContaoManager\Contao\ManagerApi\EventListener\LocaleListener')] fn() => $container->privates['Contao\ManagerApi\EventListener\LocaleListener'] ?? self::getLocaleListenerService($container), 'onKernelRequest'], 16);
        $instance->addListener('kernel.finish_request', [#[\Closure(name: '_ContaoManager\Contao\ManagerApi\EventListener\LocaleListener')] fn() => $container->privates['Contao\ManagerApi\EventListener\LocaleListener'] ?? self::getLocaleListenerService($container), 'onKernelFinishRequest'], 0);
        $instance->addListener('kernel.controller_arguments', [#[\Closure(name: 'argument_resolver.request_payload', class: '_ContaoManager\Symfony\Component\HttpKernel\Controller\ArgumentResolver\RequestPayloadValueResolver')] fn() => $container->privates['argument_resolver.request_payload'] ?? self::getArgumentResolver_RequestPayloadService($container), 'onKernelControllerArguments'], 0);
        $instance->addListener('kernel.response', [#[\Closure(name: 'response_listener', class: '_ContaoManager\Symfony\Component\HttpKernel\EventListener\ResponseListener')] fn() => $container->privates['response_listener'] ??= new \_ContaoManager\Symfony\Component\HttpKernel\EventListener\ResponseListener('UTF-8', \false), 'onKernelResponse'], 0);
        $instance->addListener('kernel.request', [#[\Closure(name: 'validate_request_listener', class: '_ContaoManager\Symfony\Component\HttpKernel\EventListener\ValidateRequestListener')] fn() => $container->privates['validate_request_listener'] ??= new \_ContaoManager\Symfony\Component\HttpKernel\EventListener\ValidateRequestListener(), 'onKernelRequest'], 256);
        $instance->addListener('kernel.controller_arguments', [#[\Closure(name: 'exception_listener', class: '_ContaoManager\Symfony\Component\HttpKernel\EventListener\ErrorListener')] fn() => $container->privates['exception_listener'] ?? self::getExceptionListener2Service($container), 'onControllerArguments'], 0);
        $instance->addListener('kernel.exception', [#[\Closure(name: 'exception_listener', class: '_ContaoManager\Symfony\Component\HttpKernel\EventListener\ErrorListener')] fn() => $container->privates['exception_listener'] ?? self::getExceptionListener2Service($container), 'logKernelException'], 0);
        $instance->addListener('kernel.exception', [#[\Closure(name: 'exception_listener', class: '_ContaoManager\Symfony\Component\HttpKernel\EventListener\ErrorListener')] fn() => $container->privates['exception_listener'] ?? self::getExceptionListener2Service($container), 'onKernelException'], -128);
        $instance->addListener('kernel.response', [#[\Closure(name: 'exception_listener', class: '_ContaoManager\Symfony\Component\HttpKernel\EventListener\ErrorListener')] fn() => $container->privates['exception_listener'] ?? self::getExceptionListener2Service($container), 'removeCspHeader'], -128);
        $instance->addListener('kernel.controller_arguments', [#[\Closure(name: 'controller.cache_attribute_listener', class: '_ContaoManager\Symfony\Component\HttpKernel\EventListener\CacheAttributeListener')] fn() => $container->privates['controller.cache_attribute_listener'] ??= new \_ContaoManager\Symfony\Component\HttpKernel\EventListener\CacheAttributeListener(), 'onKernelControllerArguments'], 10);
        $instance->addListener('kernel.response', [#[\Closure(name: 'controller.cache_attribute_listener', class: '_ContaoManager\Symfony\Component\HttpKernel\EventListener\CacheAttributeListener')] fn() => $container->privates['controller.cache_attribute_listener'] ??= new \_ContaoManager\Symfony\Component\HttpKernel\EventListener\CacheAttributeListener(), 'onKernelResponse'], -10);
        $instance->addListener('console.error', [#[\Closure(name: 'console.error_listener', class: '_ContaoManager\Symfony\Component\Console\EventListener\ErrorListener')] fn() => $container->privates['console.error_listener'] ?? $container->load('getConsole_ErrorListenerService'), 'onConsoleError'], -128);
        $instance->addListener('console.terminate', [#[\Closure(name: 'console.error_listener', class: '_ContaoManager\Symfony\Component\Console\EventListener\ErrorListener')] fn() => $container->privates['console.error_listener'] ?? $container->load('getConsole_ErrorListenerService'), 'onConsoleTerminate'], -128);
        $instance->addListener('console.error', [#[\Closure(name: 'console.suggest_missing_package_subscriber', class: '_ContaoManager\Symfony\Bundle\FrameworkBundle\EventListener\SuggestMissingPackageSubscriber')] fn() => $container->privates['console.suggest_missing_package_subscriber'] ??= new \_ContaoManager\Symfony\Bundle\FrameworkBundle\EventListener\SuggestMissingPackageSubscriber(), 'onConsoleError'], 0);
        $instance->addListener('kernel.request', [#[\Closure(name: 'debug.debug_handlers_listener', class: '_ContaoManager\Symfony\Component\HttpKernel\EventListener\DebugHandlersListener')] fn() => $container->privates['debug.debug_handlers_listener'] ??= new \_ContaoManager\Symfony\Component\HttpKernel\EventListener\DebugHandlersListener(NULL, $container->getEnv('bool:default::key:web:default:kernel.runtime_mode:')), 'configure'], 2048);
        $instance->addListener('console.command', [#[\Closure(name: 'debug.debug_handlers_listener', class: '_ContaoManager\Symfony\Component\HttpKernel\EventListener\DebugHandlersListener')] fn() => $container->privates['debug.debug_handlers_listener'] ??= new \_ContaoManager\Symfony\Component\HttpKernel\EventListener\DebugHandlersListener(NULL, $container->getEnv('bool:default::key:web:default:kernel.runtime_mode:')), 'configure'], 2048);
        $instance->addListener('kernel.request', [#[\Closure(name: 'router_listener', class: '_ContaoManager\Symfony\Component\HttpKernel\EventListener\RouterListener')] fn() => $container->privates['router_listener'] ?? self::getRouterListenerService($container), 'onKernelRequest'], 32);
        $instance->addListener('kernel.finish_request', [#[\Closure(name: 'router_listener', class: '_ContaoManager\Symfony\Component\HttpKernel\EventListener\RouterListener')] fn() => $container->privates['router_listener'] ?? self::getRouterListenerService($container), 'onKernelFinishRequest'], 0);
        $instance->addListener('kernel.exception', [#[\Closure(name: 'router_listener', class: '_ContaoManager\Symfony\Component\HttpKernel\EventListener\RouterListener')] fn() => $container->privates['router_listener'] ?? self::getRouterListenerService($container), 'onKernelException'], -64);
        $instance->addListener('kernel.request', [#[\Closure(name: 'security.firewall', class: '_ContaoManager\Symfony\Bundle\SecurityBundle\EventListener\FirewallListener')] fn() => $container->privates['security.firewall'] ?? self::getSecurity_FirewallService($container), 'configureLogoutUrlGenerator'], 8);
        $instance->addListener('kernel.request', [#[\Closure(name: 'security.firewall', class: '_ContaoManager\Symfony\Bundle\SecurityBundle\EventListener\FirewallListener')] fn() => $container->privates['security.firewall'] ?? self::getSecurity_FirewallService($container), 'onKernelRequest'], 8);
        $instance->addListener('kernel.finish_request', [#[\Closure(name: 'security.firewall', class: '_ContaoManager\Symfony\Bundle\SecurityBundle\EventListener\FirewallListener')] fn() => $container->privates['security.firewall'] ?? self::getSecurity_FirewallService($container), 'onKernelFinishRequest'], 0);
        $instance->addListener('kernel.controller_arguments', [#[\Closure(name: 'controller.is_granted_attribute_listener', class: '_ContaoManager\Symfony\Component\Security\Http\EventListener\IsGrantedAttributeListener')] fn() => $container->privates['controller.is_granted_attribute_listener'] ?? self::getController_IsGrantedAttributeListenerService($container), 'onKernelControllerArguments'], 20);
        $instance->addListener('_ContaoManager\Symfony\Component\Security\Http\Event\CheckPassportEvent', [#[\Closure(name: 'security.listener.check_authenticator_credentials', class: '_ContaoManager\Symfony\Component\Security\Http\EventListener\CheckCredentialsListener')] fn() => $container->privates['security.listener.check_authenticator_credentials'] ?? $container->load('getSecurity_Listener_CheckAuthenticatorCredentialsService'), 'checkPassport'], 0);
        $instance->addListener('_ContaoManager\Symfony\Component\Security\Http\Event\LoginSuccessEvent', [#[\Closure(name: 'security.listener.password_migrating', class: '_ContaoManager\Symfony\Component\Security\Http\EventListener\PasswordMigratingListener')] fn() => $container->privates['security.listener.password_migrating'] ?? $container->load('getSecurity_Listener_PasswordMigratingService'), 'onLoginSuccess'], 0);
        return $instance;
    }
    /*
     * Gets the public 'http_kernel' shared service.
     *
     * @return \Symfony\Component\HttpKernel\HttpKernel
     */
    protected static function getHttpKernelService($container)
    {
        $a = new \_ContaoManager\Symfony\Bundle\FrameworkBundle\Controller\ControllerResolver($container, $container->privates['monolog.logger.request'] ?? self::getMonolog_Logger_RequestService($container));
        $a->allowControllers(['_ContaoManager\Symfony\Bundle\FrameworkBundle\Controller\AbstractController', '_ContaoManager\Symfony\Bundle\FrameworkBundle\Controller\TemplateController']);
        $a->allowControllers(['_ContaoManager\Contao\ManagerApi\Controller\Config\AuthController', '_ContaoManager\Contao\ManagerApi\Controller\Config\ComposerController', '_ContaoManager\Contao\ManagerApi\Controller\Config\ManagerController', '_ContaoManager\Contao\ManagerApi\Controller\ConstraintController', '_ContaoManager\Contao\ManagerApi\Controller\Contao\AccessKeyController', '_ContaoManager\Contao\ManagerApi\Controller\Contao\BackupController', '_ContaoManager\Contao\ManagerApi\Controller\Contao\DatabaseMigrationController', '_ContaoManager\Contao\ManagerApi\Controller\Contao\InstallToolLockController', '_ContaoManager\Contao\ManagerApi\Controller\Contao\JwtCookieController', '_ContaoManager\Contao\ManagerApi\Controller\Contao\MaintenanceModeController', '_ContaoManager\Contao\ManagerApi\Controller\FileController', '_ContaoManager\Contao\ManagerApi\Controller\LogController', '_ContaoManager\Contao\ManagerApi\Controller\Packages\CloudController', '_ContaoManager\Contao\ManagerApi\Controller\Packages\LocalPackagesController', '_ContaoManager\Contao\ManagerApi\Controller\Packages\MissingPackagesController', '_ContaoManager\Contao\ManagerApi\Controller\Packages\RootPackageController', '_ContaoManager\Contao\ManagerApi\Controller\Packages\UploadPackagesController', '_ContaoManager\Contao\ManagerApi\Controller\Server\AdminUserController', '_ContaoManager\Contao\ManagerApi\Controller\Server\ComposerController', '_ContaoManager\Contao\ManagerApi\Controller\Server\ConfigController', '_ContaoManager\Contao\ManagerApi\Controller\Server\ContaoController', '_ContaoManager\Contao\ManagerApi\Controller\Server\DatabaseController', '_ContaoManager\Contao\ManagerApi\Controller\Server\OpcacheController', '_ContaoManager\Contao\ManagerApi\Controller\Server\PhpCliController', '_ContaoManager\Contao\ManagerApi\Controller\Server\PhpWebController', '_ContaoManager\Contao\ManagerApi\Controller\Server\PhpinfoController', '_ContaoManager\Contao\ManagerApi\Controller\Server\SelfUpdateController', '_ContaoManager\Contao\ManagerApi\Controller\SessionController', '_ContaoManager\Contao\ManagerApi\Controller\TaskController', '_ContaoManager\Contao\ManagerApi\Controller\UserController']);
        return $container->services['http_kernel'] = new \_ContaoManager\Symfony\Component\HttpKernel\HttpKernel($container->services['event_dispatcher'] ?? self::getEventDispatcherService($container), $a, $container->services['request_stack'] ??= new \_ContaoManager\Symfony\Component\HttpFoundation\RequestStack(), new \_ContaoManager\Symfony\Component\HttpKernel\Controller\ArgumentResolver(new \_ContaoManager\Symfony\Component\HttpKernel\ControllerMetadata\ArgumentMetadataFactory(), new RewindableGenerator(function () use ($container) {
            yield 0 => $container->privates['security.user_value_resolver'] ?? $container->load('getSecurity_UserValueResolverService');
            yield 1 => $container->privates['security.security_token_value_resolver'] ?? $container->load('getSecurity_SecurityTokenValueResolverService');
            yield 2 => $container->privates['argument_resolver.backed_enum_resolver'] ??= new \_ContaoManager\Symfony\Component\HttpKernel\Controller\ArgumentResolver\BackedEnumValueResolver();
            yield 3 => $container->privates['argument_resolver.uid'] ??= new \_ContaoManager\Symfony\Component\HttpKernel\Controller\ArgumentResolver\UidValueResolver();
            yield 4 => $container->privates['argument_resolver.datetime'] ?? $container->load('getArgumentResolver_DatetimeService');
            yield 5 => $container->privates['argument_resolver.request_attribute'] ??= new \_ContaoManager\Symfony\Component\HttpKernel\Controller\ArgumentResolver\RequestAttributeValueResolver();
            yield 6 => $container->privates['argument_resolver.request'] ??= new \_ContaoManager\Symfony\Component\HttpKernel\Controller\ArgumentResolver\RequestValueResolver();
            yield 7 => $container->privates['argument_resolver.session'] ??= new \_ContaoManager\Symfony\Component\HttpKernel\Controller\ArgumentResolver\SessionValueResolver();
            yield 8 => $container->privates['argument_resolver.service'] ?? $container->load('getArgumentResolver_ServiceService');
            yield 9 => $container->privates['argument_resolver.default'] ??= new \_ContaoManager\Symfony\Component\HttpKernel\Controller\ArgumentResolver\DefaultValueResolver();
            yield 10 => $container->privates['argument_resolver.variadic'] ??= new \_ContaoManager\Symfony\Component\HttpKernel\Controller\ArgumentResolver\VariadicValueResolver();
        }, 11), new \_ContaoManager\Symfony\Component\DependencyInjection\Argument\ServiceLocator($container->getService ??= $container->getService(...), ['_ContaoManager\Symfony\Component\HttpKernel\Controller\ArgumentResolver\BackedEnumValueResolver' => ['privates', 'argument_resolver.backed_enum_resolver', 'getArgumentResolver_BackedEnumResolverService', \true], '_ContaoManager\Symfony\Component\HttpKernel\Controller\ArgumentResolver\DateTimeValueResolver' => ['privates', 'argument_resolver.datetime', 'getArgumentResolver_DatetimeService', \true], '_ContaoManager\Symfony\Component\HttpKernel\Controller\ArgumentResolver\DefaultValueResolver' => ['privates', 'argument_resolver.default', 'getArgumentResolver_DefaultService', \true], '_ContaoManager\Symfony\Component\HttpKernel\Controller\ArgumentResolver\QueryParameterValueResolver' => ['privates', 'argument_resolver.query_parameter_value_resolver', 'getArgumentResolver_QueryParameterValueResolverService', \true], '_ContaoManager\Symfony\Component\HttpKernel\Controller\ArgumentResolver\RequestAttributeValueResolver' => ['privates', 'argument_resolver.request_attribute', 'getArgumentResolver_RequestAttributeService', \true], '_ContaoManager\Symfony\Component\HttpKernel\Controller\ArgumentResolver\RequestPayloadValueResolver' => ['privates', 'argument_resolver.request_payload', 'getArgumentResolver_RequestPayloadService', \false], '_ContaoManager\Symfony\Component\HttpKernel\Controller\ArgumentResolver\RequestValueResolver' => ['privates', 'argument_resolver.request', 'getArgumentResolver_RequestService', \true], '_ContaoManager\Symfony\Component\HttpKernel\Controller\ArgumentResolver\ServiceValueResolver' => ['privates', 'argument_resolver.service', 'getArgumentResolver_ServiceService', \true], '_ContaoManager\Symfony\Component\HttpKernel\Controller\ArgumentResolver\SessionValueResolver' => ['privates', 'argument_resolver.session', 'getArgumentResolver_SessionService', \true], '_ContaoManager\Symfony\Component\HttpKernel\Controller\ArgumentResolver\UidValueResolver' => ['privates', 'argument_resolver.uid', 'getArgumentResolver_UidService', \true], '_ContaoManager\Symfony\Component\HttpKernel\Controller\ArgumentResolver\VariadicValueResolver' => ['privates', 'argument_resolver.variadic', 'getArgumentResolver_VariadicService', \true], '_ContaoManager\Symfony\Component\Security\Http\Controller\SecurityTokenValueResolver' => ['privates', 'security.security_token_value_resolver', 'getSecurity_SecurityTokenValueResolverService', \true], '_ContaoManager\Symfony\Component\Security\Http\Controller\UserValueResolver' => ['privates', 'security.user_value_resolver', 'getSecurity_UserValueResolverService', \true]], ['_ContaoManager\Symfony\Component\HttpKernel\Controller\ArgumentResolver\BackedEnumValueResolver' => '_ContaoManager\Symfony\Component\HttpKernel\Controller\ArgumentResolver\BackedEnumValueResolver', '_ContaoManager\Symfony\Component\HttpKernel\Controller\ArgumentResolver\DateTimeValueResolver' => '_ContaoManager\Symfony\Component\HttpKernel\Controller\ArgumentResolver\DateTimeValueResolver', '_ContaoManager\Symfony\Component\HttpKernel\Controller\ArgumentResolver\DefaultValueResolver' => '_ContaoManager\Symfony\Component\HttpKernel\Controller\ArgumentResolver\DefaultValueResolver', '_ContaoManager\Symfony\Component\HttpKernel\Controller\ArgumentResolver\QueryParameterValueResolver' => '_ContaoManager\Symfony\Component\HttpKernel\Controller\ArgumentResolver\QueryParameterValueResolver', '_ContaoManager\Symfony\Component\HttpKernel\Controller\ArgumentResolver\RequestAttributeValueResolver' => '_ContaoManager\Symfony\Component\HttpKernel\Controller\ArgumentResolver\RequestAttributeValueResolver', '_ContaoManager\Symfony\Component\HttpKernel\Controller\ArgumentResolver\RequestPayloadValueResolver' => '_ContaoManager\Symfony\Component\HttpKernel\Controller\ArgumentResolver\RequestPayloadValueResolver', '_ContaoManager\Symfony\Component\HttpKernel\Controller\ArgumentResolver\RequestValueResolver' => '_ContaoManager\Symfony\Component\HttpKernel\Controller\ArgumentResolver\RequestValueResolver', '_ContaoManager\Symfony\Component\HttpKernel\Controller\ArgumentResolver\ServiceValueResolver' => '_ContaoManager\Symfony\Component\HttpKernel\Controller\ArgumentResolver\ServiceValueResolver', '_ContaoManager\Symfony\Component\HttpKernel\Controller\ArgumentResolver\SessionValueResolver' => '_ContaoManager\Symfony\Component\HttpKernel\Controller\ArgumentResolver\SessionValueResolver', '_ContaoManager\Symfony\Component\HttpKernel\Controller\ArgumentResolver\UidValueResolver' => '_ContaoManager\Symfony\Component\HttpKernel\Controller\ArgumentResolver\UidValueResolver', '_ContaoManager\Symfony\Component\HttpKernel\Controller\ArgumentResolver\VariadicValueResolver' => '_ContaoManager\Symfony\Component\HttpKernel\Controller\ArgumentResolver\VariadicValueResolver', '_ContaoManager\Symfony\Component\Security\Http\Controller\SecurityTokenValueResolver' => '_ContaoManager\Symfony\Component\Security\Http\Controller\SecurityTokenValueResolver', '_ContaoManager\Symfony\Component\Security\Http\Controller\UserValueResolver' => '_ContaoManager\Symfony\Component\Security\Http\Controller\UserValueResolver'])), \false);
    }
    /*
     * Gets the public 'request_stack' shared service.
     *
     * @return \Symfony\Component\HttpFoundation\RequestStack
     */
    protected static function getRequestStackService($container)
    {
        return $container->services['request_stack'] = new \_ContaoManager\Symfony\Component\HttpFoundation\RequestStack();
    }
    /*
     * Gets the public 'router' shared service.
     *
     * @return \Symfony\Bundle\FrameworkBundle\Routing\Router
     */
    protected static function getRouterService($container)
    {
        $a = new \_ContaoManager\Monolog\Logger('router');
        $a->pushHandler($container->privates['monolog.handler.main'] ?? self::getMonolog_Handler_MainService($container));
        $container->services['router'] = $instance = new \_ContaoManager\Symfony\Bundle\FrameworkBundle\Routing\Router((new \_ContaoManager\Symfony\Component\DependencyInjection\Argument\ServiceLocator($container->getService ??= $container->getService(...), ['routing.loader' => ['services', 'routing.loader', 'getRouting_LoaderService', \true]], ['routing.loader' => '_ContaoManager\Symfony\Component\Config\Loader\LoaderInterface']))->withContext('router.default', $container), 'kernel::loadRoutes', ['cache_dir' => $container->targetDir . '', 'debug' => \false, 'generator_class' => '_ContaoManager\Symfony\Component\Routing\Generator\CompiledUrlGenerator', 'generator_dumper_class' => '_ContaoManager\Symfony\Component\Routing\Generator\Dumper\CompiledUrlGeneratorDumper', 'matcher_class' => '_ContaoManager\Symfony\Bundle\FrameworkBundle\Routing\RedirectableCompiledUrlMatcher', 'matcher_dumper_class' => '_ContaoManager\Symfony\Component\Routing\Matcher\Dumper\CompiledUrlMatcherDumper', 'strict_requirements' => \true, 'resource_type' => 'service'], $container->privates['router.request_context'] ?? self::getRouter_RequestContextService($container), $container->privates['parameter_bag'] ??= new \_ContaoManager\Symfony\Component\DependencyInjection\ParameterBag\ContainerBag($container), $a, 'en');
        $instance->setConfigCacheFactory(new \_ContaoManager\Symfony\Component\Config\ResourceCheckerConfigCacheFactory());
        return $instance;
    }
    /*
     * Gets the public 'security.token_storage' shared service.
     *
     * @return \Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorage
     */
    protected static function getSecurity_TokenStorageService($container)
    {
        return $container->services['security.token_storage'] = new \_ContaoManager\Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorage();
    }
    /*
     * Gets the private '.service_locator.tpD_zef' shared service.
     *
     * @return \Symfony\Component\DependencyInjection\ServiceLocator
     */
    protected static function get_ServiceLocator_TpDZefService($container)
    {
        $instance = new \_ContaoManager\Symfony\Component\DependencyInjection\Argument\ServiceLocator($container->getService ??= $container->getService(...), ['security.firewall.map.context.api' => ['privates', 'security.firewall.map.context.api', 'getSecurity_Firewall_Map_Context_ApiService', \true]], ['security.firewall.map.context.api' => '?']);
        if (isset($container->privates['.service_locator.tpD_zef'])) {
            return $container->privates['.service_locator.tpD_zef'];
        }
        return $container->privates['.service_locator.tpD_zef'] = $instance;
    }
    /*
     * Gets the private 'Contao\ManagerApi\Config\UserConfig' shared autowired service.
     *
     * @return \Contao\ManagerApi\Config\UserConfig
     */
    protected static function getUserConfigService($container)
    {
        return $container->privates['Contao\ManagerApi\Config\UserConfig'] = new \_ContaoManager\Contao\ManagerApi\Config\UserConfig($container->privates['security.password_hasher_factory'] ?? self::getSecurity_PasswordHasherFactoryService($container), $container->services['kernel'] ?? $container->get('kernel', 1), $container->privates['filesystem'] ??= new \_ContaoManager\Symfony\Component\Filesystem\Filesystem());
    }
    /*
     * Gets the private 'Contao\ManagerApi\EventListener\LocaleListener' shared autowired service.
     *
     * @return \Contao\ManagerApi\EventListener\LocaleListener
     */
    protected static function getLocaleListenerService($container)
    {
        return $container->privates['Contao\ManagerApi\EventListener\LocaleListener'] = new \_ContaoManager\Contao\ManagerApi\EventListener\LocaleListener(new \_ContaoManager\Symfony\Component\HttpKernel\EventListener\LocaleListener($container->services['request_stack'] ??= new \_ContaoManager\Symfony\Component\HttpFoundation\RequestStack(), 'en', $container->services['router'] ?? self::getRouterService($container), \false, []));
    }
    /*
     * Gets the private 'Contao\ManagerApi\EventListener\SecurityListener' shared autowired service.
     *
     * @return \Contao\ManagerApi\EventListener\SecurityListener
     */
    protected static function getSecurityListenerService($container)
    {
        return $container->privates['Contao\ManagerApi\EventListener\SecurityListener'] = new \_ContaoManager\Contao\ManagerApi\EventListener\SecurityListener($container->privates['Contao\ManagerApi\Security\JwtManager'] ?? self::getJwtManagerService($container), $container->services['security.token_storage'] ??= new \_ContaoManager\Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorage(), $container->privates['security.authorization_checker'] ?? self::getSecurity_AuthorizationCheckerService($container));
    }
    /*
     * Gets the private 'Contao\ManagerApi\Security\JwtManager' shared autowired service.
     *
     * @return \Contao\ManagerApi\Security\JwtManager
     */
    protected static function getJwtManagerService($container)
    {
        return $container->privates['Contao\ManagerApi\Security\JwtManager'] = new \_ContaoManager\Contao\ManagerApi\Security\JwtManager($container->privates['Contao\ManagerApi\Config\UserConfig'] ?? self::getUserConfigService($container));
    }
    /*
     * Gets the private 'argument_resolver.request_payload' shared service.
     *
     * @return \Symfony\Component\HttpKernel\Controller\ArgumentResolver\RequestPayloadValueResolver
     */
    protected static function getArgumentResolver_RequestPayloadService($container, $lazyLoad = \true)
    {
        if (\true === $lazyLoad) {
            return $container->privates['argument_resolver.request_payload'] = $container->createProxy('RequestPayloadValueResolverGhost8d82153', static fn() => \_ContaoManager\RequestPayloadValueResolverGhost8d82153::createLazyGhost(static fn($proxy) => self::getArgumentResolver_RequestPayloadService($container, $proxy)));
        }
        return $lazyLoad->__construct($container->privates['serializer'] ?? self::getSerializerService($container), NULL, NULL) && \false ?: $lazyLoad;
    }
    /*
     * Gets the private 'cache.property_access' shared service.
     *
     * @return \Symfony\Component\Cache\Adapter\AdapterInterface
     */
    protected static function getCache_PropertyAccessService($container)
    {
        return $container->privates['cache.property_access'] = \_ContaoManager\Symfony\Component\PropertyAccess\PropertyAccessor::createCache('5s2XBuUwnY', 0, $container->getParameter('container.build_id'), $container->privates['monolog.logger.cache'] ?? self::getMonolog_Logger_CacheService($container));
    }
    /*
     * Gets the private 'cache.property_info' shared service.
     *
     * @return \Symfony\Component\Cache\Adapter\AdapterInterface
     */
    protected static function getCache_PropertyInfoService($container)
    {
        return $container->privates['cache.property_info'] = \_ContaoManager\Symfony\Component\Cache\Adapter\AbstractAdapter::createSystemCache('X-aN5AGBzy', 0, $container->getParameter('container.build_id'), $container->targetDir . '' . '/pools/system', $container->privates['monolog.logger.cache'] ?? self::getMonolog_Logger_CacheService($container));
    }
    /*
     * Gets the private 'cache.serializer' shared service.
     *
     * @return \Symfony\Component\Cache\Adapter\AdapterInterface
     */
    protected static function getCache_SerializerService($container)
    {
        return $container->privates['cache.serializer'] = \_ContaoManager\Symfony\Component\Cache\Adapter\AbstractAdapter::createSystemCache('yfVW0XFe3F', 0, $container->getParameter('container.build_id'), $container->targetDir . '' . '/pools/system', $container->privates['monolog.logger.cache'] ?? self::getMonolog_Logger_CacheService($container));
    }
    /*
     * Gets the private 'controller.is_granted_attribute_listener' shared service.
     *
     * @return \Symfony\Component\Security\Http\EventListener\IsGrantedAttributeListener
     */
    protected static function getController_IsGrantedAttributeListenerService($container)
    {
        return $container->privates['controller.is_granted_attribute_listener'] = new \_ContaoManager\Symfony\Component\Security\Http\EventListener\IsGrantedAttributeListener($container->privates['security.authorization_checker'] ?? self::getSecurity_AuthorizationCheckerService($container), NULL);
    }
    /*
     * Gets the private 'exception_listener' shared service.
     *
     * @return \Symfony\Component\HttpKernel\EventListener\ErrorListener
     */
    protected static function getExceptionListener2Service($container)
    {
        return $container->privates['exception_listener'] = new \_ContaoManager\Symfony\Component\HttpKernel\EventListener\ErrorListener('error_controller', $container->privates['monolog.logger.request'] ?? self::getMonolog_Logger_RequestService($container), \false, []);
    }
    /*
     * Gets the private 'monolog.handler.main' shared service.
     *
     * @return \Monolog\Handler\FingersCrossedHandler
     */
    protected static function getMonolog_Handler_MainService($container)
    {
        $a = new \_ContaoManager\Monolog\Handler\ErrorLogHandler(0, 'DEBUG', \true);
        $a->pushProcessor(new \_ContaoManager\Monolog\Processor\PsrLogMessageProcessor());
        return $container->privates['monolog.handler.main'] = new \_ContaoManager\Monolog\Handler\FingersCrossedHandler($a, new \_ContaoManager\Monolog\Handler\FingersCrossed\ErrorLevelActivationStrategy('error'), 0, \true, \true, NULL);
    }
    /*
     * Gets the private 'monolog.logger.cache' shared service.
     *
     * @return \Monolog\Logger
     */
    protected static function getMonolog_Logger_CacheService($container)
    {
        $container->privates['monolog.logger.cache'] = $instance = new \_ContaoManager\Monolog\Logger('cache');
        $instance->pushHandler($container->privates['monolog.handler.main'] ?? self::getMonolog_Handler_MainService($container));
        return $instance;
    }
    /*
     * Gets the private 'monolog.logger.request' shared service.
     *
     * @return \Monolog\Logger
     */
    protected static function getMonolog_Logger_RequestService($container)
    {
        $container->privates['monolog.logger.request'] = $instance = new \_ContaoManager\Monolog\Logger('request');
        $instance->pushHandler($container->privates['monolog.handler.main'] ?? self::getMonolog_Handler_MainService($container));
        return $instance;
    }
    /*
     * Gets the private 'parameter_bag' shared service.
     *
     * @return \Symfony\Component\DependencyInjection\ParameterBag\ContainerBag
     */
    protected static function getParameterBagService($container)
    {
        return $container->privates['parameter_bag'] = new \_ContaoManager\Symfony\Component\DependencyInjection\ParameterBag\ContainerBag($container);
    }
    /*
     * Gets the private 'router.request_context' shared service.
     *
     * @return \Symfony\Component\Routing\RequestContext
     */
    protected static function getRouter_RequestContextService($container)
    {
        return $container->privates['router.request_context'] = \_ContaoManager\Symfony\Component\Routing\RequestContext::fromUri('', 'localhost', 'http', 80, 443);
    }
    /*
     * Gets the private 'router_listener' shared service.
     *
     * @return \Symfony\Component\HttpKernel\EventListener\RouterListener
     */
    protected static function getRouterListenerService($container)
    {
        return $container->privates['router_listener'] = new \_ContaoManager\Symfony\Component\HttpKernel\EventListener\RouterListener($container->services['router'] ?? self::getRouterService($container), $container->services['request_stack'] ??= new \_ContaoManager\Symfony\Component\HttpFoundation\RequestStack(), $container->privates['router.request_context'] ?? self::getRouter_RequestContextService($container), $container->privates['monolog.logger.request'] ?? self::getMonolog_Logger_RequestService($container), \dirname(__DIR__, 4) . '/test-dir', \false);
    }
    /*
     * Gets the private 'security.access.decision_manager' shared service.
     *
     * @return \Symfony\Component\Security\Core\Authorization\AccessDecisionManager
     */
    protected static function getSecurity_Access_DecisionManagerService($container)
    {
        return $container->privates['security.access.decision_manager'] = new \_ContaoManager\Symfony\Component\Security\Core\Authorization\AccessDecisionManager(new RewindableGenerator(function () use ($container) {
            yield 0 => $container->privates['security.access.authenticated_voter'] ?? $container->load('getSecurity_Access_AuthenticatedVoterService');
            yield 1 => $container->privates['security.access.role_hierarchy_voter'] ?? $container->load('getSecurity_Access_RoleHierarchyVoterService');
        }, 2), new \_ContaoManager\Symfony\Component\Security\Core\Authorization\Strategy\AffirmativeStrategy(\false));
    }
    /*
     * Gets the private 'security.authorization_checker' shared service.
     *
     * @return \Symfony\Component\Security\Core\Authorization\AuthorizationChecker
     */
    protected static function getSecurity_AuthorizationCheckerService($container)
    {
        return $container->privates['security.authorization_checker'] = new \_ContaoManager\Symfony\Component\Security\Core\Authorization\AuthorizationChecker($container->services['security.token_storage'] ??= new \_ContaoManager\Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorage(), $container->privates['security.access.decision_manager'] ?? self::getSecurity_Access_DecisionManagerService($container), \false, \false);
    }
    /*
     * Gets the private 'security.firewall' shared service.
     *
     * @return \Symfony\Bundle\SecurityBundle\EventListener\FirewallListener
     */
    protected static function getSecurity_FirewallService($container)
    {
        $a = $container->privates['security.firewall.map'] ?? self::getSecurity_Firewall_MapService($container);
        if (isset($container->privates['security.firewall'])) {
            return $container->privates['security.firewall'];
        }
        $b = $container->services['event_dispatcher'] ?? self::getEventDispatcherService($container);
        if (isset($container->privates['security.firewall'])) {
            return $container->privates['security.firewall'];
        }
        $instance = new \_ContaoManager\Symfony\Bundle\SecurityBundle\EventListener\FirewallListener($a, $b, new \_ContaoManager\Symfony\Component\Security\Http\Logout\LogoutUrlGenerator($container->services['request_stack'] ??= new \_ContaoManager\Symfony\Component\HttpFoundation\RequestStack(), $container->services['router'] ?? self::getRouterService($container), $container->services['security.token_storage'] ??= new \_ContaoManager\Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorage()));
        if (isset($container->privates['security.firewall'])) {
            return $container->privates['security.firewall'];
        }
        return $container->privates['security.firewall'] = $instance;
    }
    /*
     * Gets the private 'security.firewall.map' shared service.
     *
     * @return \Symfony\Bundle\SecurityBundle\Security\FirewallMap
     */
    protected static function getSecurity_Firewall_MapService($container)
    {
        $a = $container->privates['.service_locator.tpD_zef'] ?? self::get_ServiceLocator_TpDZefService($container);
        if (isset($container->privates['security.firewall.map'])) {
            return $container->privates['security.firewall.map'];
        }
        $instance = new \_ContaoManager\Symfony\Bundle\SecurityBundle\Security\FirewallMap($a, new RewindableGenerator(function () use ($container) {
            yield 'security.firewall.map.context.api' => NULL;
        }, 1));
        if (isset($container->privates['security.firewall.map'])) {
            return $container->privates['security.firewall.map'];
        }
        return $container->privates['security.firewall.map'] = $instance;
    }
    /*
     * Gets the private 'security.password_hasher_factory' shared service.
     *
     * @return \Symfony\Component\PasswordHasher\Hasher\PasswordHasherFactory
     */
    protected static function getSecurity_PasswordHasherFactoryService($container)
    {
        return $container->privates['security.password_hasher_factory'] = new \_ContaoManager\Symfony\Component\PasswordHasher\Hasher\PasswordHasherFactory(['_ContaoManager\Symfony\Component\Security\Core\User\PasswordAuthenticatedUserInterface' => ['algorithm' => 'auto', 'migrate_from' => [], 'hash_algorithm' => 'sha512', 'key_length' => 40, 'ignore_case' => \false, 'encode_as_base64' => \true, 'iterations' => 5000, 'cost' => NULL, 'memory_cost' => NULL, 'time_cost' => NULL]]);
    }
    /*
     * Gets the private 'serializer' shared service.
     *
     * @return \Symfony\Component\Serializer\Serializer
     */
    protected static function getSerializerService($container)
    {
        $a = $container->privates['property_info.reflection_extractor'] ??= new \_ContaoManager\Symfony\Component\PropertyInfo\Extractor\ReflectionExtractor();
        $b = new \_ContaoManager\Symfony\Component\PropertyAccess\PropertyAccessor(3, 2, $container->privates['cache.property_access'] ?? self::getCache_PropertyAccessService($container), $a, $a);
        $c = $container->privates['serializer.mapping.cache_class_metadata_factory'] ?? self::getSerializer_Mapping_CacheClassMetadataFactoryService($container);
        $d = new \_ContaoManager\Symfony\Component\Serializer\NameConverter\MetadataAwareNameConverter($c);
        $e = new \_ContaoManager\Symfony\Component\PropertyInfo\PropertyInfoCacheExtractor(new \_ContaoManager\Symfony\Component\PropertyInfo\PropertyInfoExtractor(new RewindableGenerator(function () use ($container) {
            yield 0 => $container->privates['property_info.serializer_extractor'] ?? $container->load('getPropertyInfo_SerializerExtractorService');
            yield 1 => $container->privates['property_info.reflection_extractor'] ??= new \_ContaoManager\Symfony\Component\PropertyInfo\Extractor\ReflectionExtractor();
        }, 2), new RewindableGenerator(function () use ($container) {
            yield 0 => $container->privates['property_info.phpstan_extractor'] ??= new \_ContaoManager\Symfony\Component\PropertyInfo\Extractor\PhpStanExtractor();
            yield 1 => $container->privates['property_info.php_doc_extractor'] ??= new \_ContaoManager\Symfony\Component\PropertyInfo\Extractor\PhpDocExtractor();
            yield 2 => $container->privates['property_info.reflection_extractor'] ??= new \_ContaoManager\Symfony\Component\PropertyInfo\Extractor\ReflectionExtractor();
        }, 3), new RewindableGenerator(function () use ($container) {
            yield 0 => $container->privates['property_info.php_doc_extractor'] ??= new \_ContaoManager\Symfony\Component\PropertyInfo\Extractor\PhpDocExtractor();
        }, 1), new RewindableGenerator(function () use ($container) {
            yield 0 => $container->privates['property_info.reflection_extractor'] ??= new \_ContaoManager\Symfony\Component\PropertyInfo\Extractor\ReflectionExtractor();
        }, 1), new RewindableGenerator(function () use ($container) {
            yield 0 => $container->privates['property_info.reflection_extractor'] ??= new \_ContaoManager\Symfony\Component\PropertyInfo\Extractor\ReflectionExtractor();
        }, 1)), $container->privates['cache.property_info'] ?? self::getCache_PropertyInfoService($container));
        return $container->privates['serializer'] = new \_ContaoManager\Symfony\Component\Serializer\Serializer([new \_ContaoManager\Symfony\Component\Serializer\Normalizer\UnwrappingDenormalizer($b), new \_ContaoManager\Symfony\Component\Serializer\Normalizer\ProblemNormalizer(\false, translator: NULL), new \_ContaoManager\Symfony\Component\Serializer\Normalizer\UidNormalizer(), new \_ContaoManager\Symfony\Component\Serializer\Normalizer\DateTimeNormalizer(), new \_ContaoManager\Symfony\Component\Serializer\Normalizer\ConstraintViolationListNormalizer([], $d), new \_ContaoManager\Symfony\Component\Serializer\Normalizer\DateTimeZoneNormalizer(), new \_ContaoManager\Symfony\Component\Serializer\Normalizer\DateIntervalNormalizer(), new \_ContaoManager\Symfony\Component\Serializer\Normalizer\FormErrorNormalizer(), new \_ContaoManager\Symfony\Component\Serializer\Normalizer\BackedEnumNormalizer(), new \_ContaoManager\Symfony\Component\Serializer\Normalizer\DataUriNormalizer(NULL), new \_ContaoManager\Symfony\Component\Serializer\Normalizer\JsonSerializableNormalizer(NULL, NULL), new \_ContaoManager\Symfony\Component\Serializer\Normalizer\ArrayDenormalizer(), new \_ContaoManager\Symfony\Component\Serializer\Normalizer\ObjectNormalizer($c, $d, $b, $e, new \_ContaoManager\Symfony\Component\Serializer\Mapping\ClassDiscriminatorFromClassMetadata($c), NULL, [], $e)], [new \_ContaoManager\Symfony\Component\Serializer\Encoder\XmlEncoder(), new \_ContaoManager\Symfony\Component\Serializer\Encoder\JsonEncoder(NULL, NULL), new \_ContaoManager\Symfony\Component\Serializer\Encoder\YamlEncoder(NULL, NULL), new \_ContaoManager\Symfony\Component\Serializer\Encoder\CsvEncoder()], []);
    }
    /*
     * Gets the private 'serializer.mapping.cache_class_metadata_factory' shared service.
     *
     * @return \Symfony\Component\Serializer\Mapping\Factory\CacheClassMetadataFactory
     */
    protected static function getSerializer_Mapping_CacheClassMetadataFactoryService($container)
    {
        return $container->privates['serializer.mapping.cache_class_metadata_factory'] = new \_ContaoManager\Symfony\Component\Serializer\Mapping\Factory\CacheClassMetadataFactory(new \_ContaoManager\Symfony\Component\Serializer\Mapping\Factory\ClassMetadataFactory(new \_ContaoManager\Symfony\Component\Serializer\Mapping\Loader\LoaderChain([new \_ContaoManager\Symfony\Component\Serializer\Mapping\Loader\AttributeLoader(NULL)])), \_ContaoManager\Symfony\Component\Cache\Adapter\PhpArrayAdapter::create($container->targetDir . '' . '/serialization.php', $container->privates['cache.serializer'] ?? self::getCache_SerializerService($container)));
    }
    public function getParameter(string $name): array|bool|string|int|float|\UnitEnum|null
    {
        if (\array_key_exists($name, $this->buildParameters)) {
            return $this->buildParameters[$name];
        }
        if (isset($this->loadedDynamicParameters[$name])) {
            return $this->loadedDynamicParameters[$name] ? $this->dynamicParameters[$name] : $this->getDynamicParameter($name);
        }
        if (!\array_key_exists($name, $this->parameters) || '.' === ($name[0] ?? '')) {
            throw new ParameterNotFoundException($name);
        }
        return $this->parameters[$name];
    }
    public function hasParameter(string $name): bool
    {
        if (\array_key_exists($name, $this->buildParameters)) {
            return \true;
        }
        return \array_key_exists($name, $this->parameters) || isset($this->loadedDynamicParameters[$name]);
    }
    public function setParameter(string $name, $value): void
    {
        throw new LogicException('Impossible to call set() on a frozen ParameterBag.');
    }
    public function getParameterBag(): ParameterBagInterface
    {
        if (!isset($this->parameterBag)) {
            $parameters = $this->parameters;
            foreach ($this->loadedDynamicParameters as $name => $loaded) {
                $parameters[$name] = $loaded ? $this->dynamicParameters[$name] : $this->getDynamicParameter($name);
            }
            foreach ($this->buildParameters as $name => $value) {
                $parameters[$name] = $value;
            }
            $this->parameterBag = new FrozenParameterBag($parameters);
        }
        return $this->parameterBag;
    }
    private $loadedDynamicParameters = ['kernel.runtime_environment' => \false, 'kernel.runtime_mode' => \false, 'kernel.runtime_mode.web' => \false, 'kernel.runtime_mode.cli' => \false, 'kernel.runtime_mode.worker' => \false, 'kernel.build_dir' => \false, 'kernel.cache_dir' => \false, 'router.cache_dir' => \false, 'serializer.mapping.cache.file' => \false];
    private $dynamicParameters = [];
    private function getDynamicParameter(string $name)
    {
        $container = $this;
        $value = match ($name) {
            'kernel.runtime_environment' => $container->getEnv('default:kernel.environment:APP_RUNTIME_ENV'),
            'kernel.runtime_mode' => $container->getEnv('query_string:default:container.runtime_mode:APP_RUNTIME_MODE'),
            'kernel.runtime_mode.web' => $container->getEnv('bool:default::key:web:default:kernel.runtime_mode:'),
            'kernel.runtime_mode.cli' => $container->getEnv('not:default:kernel.runtime_mode.web:'),
            'kernel.runtime_mode.worker' => $container->getEnv('bool:default::key:worker:default:kernel.runtime_mode:'),
            'kernel.build_dir' => $container->targetDir . '',
            'kernel.cache_dir' => $container->targetDir . '',
            'router.cache_dir' => $container->targetDir . '',
            'serializer.mapping.cache.file' => $container->targetDir . '' . '/serialization.php',
            default => throw new ParameterNotFoundException($name),
        };
        $this->loadedDynamicParameters[$name] = \true;
        return $this->dynamicParameters[$name] = $value;
    }
    protected function getDefaultParameters(): array
    {
        return ['kernel.project_dir' => \dirname(__DIR__, 4) . '/test-dir', 'kernel.environment' => 'prod', 'kernel.debug' => \false, 'kernel.logs_dir' => \dirname(__DIR__, 4) . '/test-dir/contao-manager/logs', 'kernel.bundles' => ['FrameworkBundle' => '_ContaoManager\Symfony\Bundle\FrameworkBundle\FrameworkBundle', 'SecurityBundle' => '_ContaoManager\Symfony\Bundle\SecurityBundle\SecurityBundle', 'MonologBundle' => '_ContaoManager\Symfony\Bundle\MonologBundle\MonologBundle'], 'kernel.bundles_metadata' => ['FrameworkBundle' => ['path' => \dirname(__DIR__, 4) . '/vendor/symfony/framework-bundle', 'namespace' => '_ContaoManager\Symfony\Bundle\FrameworkBundle'], 'SecurityBundle' => ['path' => \dirname(__DIR__, 4) . '/vendor/symfony/security-bundle', 'namespace' => '_ContaoManager\Symfony\Bundle\SecurityBundle'], 'MonologBundle' => ['path' => \dirname(__DIR__, 4) . '/vendor/symfony/monolog-bundle/src', 'namespace' => '_ContaoManager\Symfony\Bundle\MonologBundle']], 'kernel.charset' => 'UTF-8', 'kernel.container_class' => 'Contao_ManagerApi_ApiKernelProdContainer', 'event_dispatcher.event_aliases' => ['_ContaoManager\Symfony\Component\Console\Event\ConsoleCommandEvent' => 'console.command', '_ContaoManager\Symfony\Component\Console\Event\ConsoleErrorEvent' => 'console.error', '_ContaoManager\Symfony\Component\Console\Event\ConsoleSignalEvent' => 'console.signal', '_ContaoManager\Symfony\Component\Console\Event\ConsoleTerminateEvent' => 'console.terminate', '_ContaoManager\Symfony\Component\HttpKernel\Event\ControllerArgumentsEvent' => 'kernel.controller_arguments', '_ContaoManager\Symfony\Component\HttpKernel\Event\ControllerEvent' => 'kernel.controller', '_ContaoManager\Symfony\Component\HttpKernel\Event\ResponseEvent' => 'kernel.response', '_ContaoManager\Symfony\Component\HttpKernel\Event\FinishRequestEvent' => 'kernel.finish_request', '_ContaoManager\Symfony\Component\HttpKernel\Event\RequestEvent' => 'kernel.request', '_ContaoManager\Symfony\Component\HttpKernel\Event\ViewEvent' => 'kernel.view', '_ContaoManager\Symfony\Component\HttpKernel\Event\ExceptionEvent' => 'kernel.exception', '_ContaoManager\Symfony\Component\HttpKernel\Event\TerminateEvent' => 'kernel.terminate', '_ContaoManager\Symfony\Component\Security\Core\Event\AuthenticationSuccessEvent' => 'security.authentication.success', '_ContaoManager\Symfony\Component\Security\Http\Event\InteractiveLoginEvent' => 'security.interactive_login', '_ContaoManager\Symfony\Component\Security\Http\Event\SwitchUserEvent' => 'security.switch_user'], 'fragment.renderer.hinclude.global_template' => NULL, 'fragment.path' => '/_fragment', 'kernel.secret' => '', 'kernel.http_method_override' => \true, 'kernel.trust_x_sendfile_type_header' => \false, 'kernel.trusted_hosts' => [], 'kernel.default_locale' => 'en', 'kernel.enabled_locales' => [], 'kernel.error_controller' => 'error_controller', 'debug.file_link_format' => NULL, 'debug.error_handler.throw_at' => 0, 'router.request_context.host' => 'localhost', 'router.request_context.scheme' => 'http', 'router.request_context.base_url' => '', 'router.resource' => 'kernel::loadRoutes', 'request_listener.http_port' => 80, 'request_listener.https_port' => 443, 'data_collector.templates' => [], 'security.role_hierarchy.roles' => ['ROLE_ADMIN' => [0 => 'ROLE_INSTALL'], 'ROLE_INSTALL' => [0 => 'ROLE_UPDATE'], 'ROLE_UPDATE' => [0 => 'ROLE_READ'], 'ROLE_READ' => [0 => 'ROLE_USER']], 'security.access.denied_url' => NULL, 'security.authentication.manager.erase_credentials' => \true, 'security.authentication.session_strategy.strategy' => 'migrate', 'security.authentication.hide_user_not_found' => \true, 'security.firewalls' => [0 => 'api'], 'security.logout_uris' => [], 'monolog.use_microseconds' => \true, 'monolog.swift_mailer.handlers' => [], 'monolog.handlers_to_channels' => ['monolog.handler.main' => NULL], 'console.command.ids' => []];
    }
}
<?php

namespace _ContaoManager\ContainerLiF9Qbu;

use _ContaoManager\Symfony\Component\DependencyInjection\Argument\RewindableGenerator;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\RuntimeException;
/*
 * @internal This class has been auto-generated by the Symfony Dependency Injection Component.
 */
class get_Console_Command_CachePoolPrune_LazyService extends Contao_ManagerApi_ApiKernelProdContainer
{
    /*
     * Gets the private '.console.command.cache_pool_prune.lazy' shared service.
     *
     * @return \Symfony\Component\Console\Command\LazyCommand
     */
    public static function do($container, $lazyLoad = \true)
    {
        return $container->privates['.console.command.cache_pool_prune.lazy'] = new \_ContaoManager\Symfony\Component\Console\Command\LazyCommand('cache:pool:prune', [], 'Prune cache pools', \false, #[\Closure(name: 'console.command.cache_pool_prune', class: '_ContaoManager\Symfony\Bundle\FrameworkBundle\Command\CachePoolPruneCommand')] fn(): \_ContaoManager\Symfony\Bundle\FrameworkBundle\Command\CachePoolPruneCommand => $container->privates['console.command.cache_pool_prune'] ?? $container->load('getConsole_Command_CachePoolPruneService'));
    }
}
<?php

namespace _ContaoManager\ContainerLiF9Qbu;

use _ContaoManager\Symfony\Component\DependencyInjection\Argument\RewindableGenerator;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\RuntimeException;
/*
 * @internal This class has been auto-generated by the Symfony Dependency Injection Component.
 */
class getTaskUpdateCommandService extends Contao_ManagerApi_ApiKernelProdContainer
{
    /*
     * Gets the public 'Contao\ManagerApi\Command\TaskUpdateCommand' shared autowired service.
     *
     * @return \Contao\ManagerApi\Command\TaskUpdateCommand
     */
    public static function do($container, $lazyLoad = \true)
    {
        $container->services['Contao\ManagerApi\Command\TaskUpdateCommand'] = $instance = new \_ContaoManager\Contao\ManagerApi\Command\TaskUpdateCommand($container->privates['Contao\ManagerApi\Task\TaskManager'] ?? $container->load('getTaskManagerService'));
        $instance->setName('task:update');
        $instance->setDescription('Updates the current task and returns the status information.');
        return $instance;
    }
}
<?php

namespace _ContaoManager\ContainerLiF9Qbu;

use _ContaoManager\Symfony\Component\DependencyInjection\Argument\RewindableGenerator;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\RuntimeException;
/*
 * @internal This class has been auto-generated by the Symfony Dependency Injection Component.
 */
class getTaskControllerService extends Contao_ManagerApi_ApiKernelProdContainer
{
    /*
     * Gets the public 'Contao\ManagerApi\Controller\TaskController' shared autowired service.
     *
     * @return \Contao\ManagerApi\Controller\TaskController
     */
    public static function do($container, $lazyLoad = \true)
    {
        return $container->services['Contao\ManagerApi\Controller\TaskController'] = new \_ContaoManager\Contao\ManagerApi\Controller\TaskController($container->privates['Contao\ManagerApi\Task\TaskManager'] ?? $container->load('getTaskManagerService'));
    }
}
<?php

namespace _ContaoManager\ContainerLiF9Qbu;

use _ContaoManager\Symfony\Component\DependencyInjection\Argument\RewindableGenerator;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\RuntimeException;
/*
 * @internal This class has been auto-generated by the Symfony Dependency Injection Component.
 */
class getMaintenanceModeControllerService extends Contao_ManagerApi_ApiKernelProdContainer
{
    /*
     * Gets the public 'Contao\ManagerApi\Controller\Contao\MaintenanceModeController' shared autowired service.
     *
     * @return \Contao\ManagerApi\Controller\Contao\MaintenanceModeController
     */
    public static function do($container, $lazyLoad = \true)
    {
        return $container->services['Contao\ManagerApi\Controller\Contao\MaintenanceModeController'] = new \_ContaoManager\Contao\ManagerApi\Controller\Contao\MaintenanceModeController($container->privates['Contao\ManagerApi\Process\ContaoConsole'] ?? $container->load('getContaoConsoleService'), $container->privates['Contao\ManagerApi\Process\ConsoleProcessFactory'] ?? $container->load('getConsoleProcessFactoryService'), $container->services['kernel'] ?? $container->get('kernel', 1), $container->privates['filesystem'] ??= new \_ContaoManager\Symfony\Component\Filesystem\Filesystem());
    }
}
<?php

namespace _ContaoManager\ContainerLiF9Qbu;

use _ContaoManager\Symfony\Component\DependencyInjection\Argument\RewindableGenerator;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\RuntimeException;
/*
 * @internal This class has been auto-generated by the Symfony Dependency Injection Component.
 */
class getFileControllerService extends Contao_ManagerApi_ApiKernelProdContainer
{
    /*
     * Gets the public 'Contao\ManagerApi\Controller\FileController' shared autowired service.
     *
     * @return \Contao\ManagerApi\Controller\FileController
     */
    public static function do($container, $lazyLoad = \true)
    {
        return $container->services['Contao\ManagerApi\Controller\FileController'] = new \_ContaoManager\Contao\ManagerApi\Controller\FileController($container->services['kernel'] ?? $container->get('kernel', 1), $container->privates['filesystem'] ??= new \_ContaoManager\Symfony\Component\Filesystem\Filesystem());
    }
}
<?php

namespace _ContaoManager\ContainerLiF9Qbu;

use _ContaoManager\Symfony\Component\DependencyInjection\Argument\RewindableGenerator;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\RuntimeException;
/*
 * @internal This class has been auto-generated by the Symfony Dependency Injection Component.
 */
class get_ServiceLocator_Y_Xs7MwService extends Contao_ManagerApi_ApiKernelProdContainer
{
    /*
     * Gets the private '.service_locator.y.Xs7Mw' shared service.
     *
     * @return \Symfony\Component\DependencyInjection\ServiceLocator
     */
    public static function do($container, $lazyLoad = \true)
    {
        return $container->privates['.service_locator.y.Xs7Mw'] = new \_ContaoManager\Symfony\Component\DependencyInjection\Argument\ServiceLocator($container->getService ??= $container->getService(...), ['processFactory' => ['privates', '_ContaoManager\Contao\ManagerApi\Process\ConsoleProcessFactory', 'getConsoleProcessFactoryService', \true], 'serverInfo' => ['privates', '_ContaoManager\Contao\ManagerApi\System\ServerInfo', 'getServerInfoService', \true]], ['processFactory' => '_ContaoManager\Contao\ManagerApi\Process\ConsoleProcessFactory', 'serverInfo' => '_ContaoManager\Contao\ManagerApi\System\ServerInfo']);
    }
}
<?php

namespace _ContaoManager\ContainerLiF9Qbu;

use _ContaoManager\Symfony\Component\DependencyInjection\Argument\RewindableGenerator;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\RuntimeException;
/*
 * @internal This class has been auto-generated by the Symfony Dependency Injection Component.
 */
class getRouting_LoaderService extends Contao_ManagerApi_ApiKernelProdContainer
{
    /*
     * Gets the public 'routing.loader' shared service.
     *
     * @return \Symfony\Bundle\FrameworkBundle\Routing\DelegatingLoader
     */
    public static function do($container, $lazyLoad = \true)
    {
        $a = new \_ContaoManager\Symfony\Component\Config\Loader\LoaderResolver();
        $b = new \_ContaoManager\Symfony\Component\HttpKernel\Config\FileLocator($container->services['kernel'] ?? $container->get('kernel', 1));
        $c = new \_ContaoManager\Symfony\Bundle\FrameworkBundle\Routing\AttributeRouteControllerLoader('prod');
        $a->addLoader(new \_ContaoManager\Symfony\Component\Routing\Loader\XmlFileLoader($b, 'prod'));
        $a->addLoader(new \_ContaoManager\Symfony\Component\Routing\Loader\YamlFileLoader($b, 'prod'));
        $a->addLoader(new \_ContaoManager\Symfony\Component\Routing\Loader\PhpFileLoader($b, 'prod'));
        $a->addLoader(new \_ContaoManager\Symfony\Component\Routing\Loader\GlobFileLoader($b, 'prod'));
        $a->addLoader(new \_ContaoManager\Symfony\Component\Routing\Loader\DirectoryLoader($b, 'prod'));
        $a->addLoader(new \_ContaoManager\Symfony\Component\Routing\Loader\ContainerLoader(new \_ContaoManager\Symfony\Component\DependencyInjection\Argument\ServiceLocator($container->getService ??= $container->getService(...), ['kernel' => ['services', 'kernel', 'getKernelService', \false], 'security.route_loader.logout' => ['privates', 'security.route_loader.logout', 'getSecurity_RouteLoader_LogoutService', \true]], ['kernel' => '?', 'security.route_loader.logout' => '_ContaoManager\Symfony\Bundle\SecurityBundle\Routing\LogoutRouteLoader']), 'prod'));
        $a->addLoader($c);
        $a->addLoader(new \_ContaoManager\Symfony\Component\Routing\Loader\AttributeDirectoryLoader($b, $c));
        $a->addLoader(new \_ContaoManager\Symfony\Component\Routing\Loader\AttributeFileLoader($b, $c));
        $a->addLoader(new \_ContaoManager\Symfony\Component\Routing\Loader\Psr4DirectoryLoader($b));
        return $container->services['routing.loader'] = new \_ContaoManager\Symfony\Bundle\FrameworkBundle\Routing\DelegatingLoader($a, ['utf8' => \true], []);
    }
}
<?php

namespace _ContaoManager\ContainerLiF9Qbu;

use _ContaoManager\Symfony\Component\DependencyInjection\Argument\RewindableGenerator;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\RuntimeException;
/*
 * @internal This class has been auto-generated by the Symfony Dependency Injection Component.
 */
class getEnvironmentService extends Contao_ManagerApi_ApiKernelProdContainer
{
    /*
     * Gets the private 'Contao\ManagerApi\Composer\Environment' shared autowired service.
     *
     * @return \Contao\ManagerApi\Composer\Environment
     */
    public static function do($container, $lazyLoad = \true)
    {
        return $container->privates['Contao\ManagerApi\Composer\Environment'] = new \_ContaoManager\Contao\ManagerApi\Composer\Environment($container->services['kernel'] ?? $container->get('kernel', 1), $container->privates['Contao\ManagerApi\Config\ManagerConfig'] ?? $container->load('getManagerConfigService'), $container->privates['Contao\ManagerApi\Config\ComposerConfig'] ?? $container->load('getComposerConfigService'), $container->privates['filesystem'] ??= new \_ContaoManager\Symfony\Component\Filesystem\Filesystem(), $container->privates['Contao\ManagerApi\System\Request'] ?? $container->load('getRequestService'), $container->privates['monolog.logger'] ?? $container->load('getMonolog_LoggerService'));
    }
}
<?php

namespace _ContaoManager\ContainerLiF9Qbu;

use _ContaoManager\Symfony\Component\DependencyInjection\Argument\RewindableGenerator;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\RuntimeException;
/*
 * @internal This class has been auto-generated by the Symfony Dependency Injection Component.
 */
class getSecurity_Listener_UserChecker_ApiService extends Contao_ManagerApi_ApiKernelProdContainer
{
    /*
     * Gets the private 'security.listener.user_checker.api' shared service.
     *
     * @return \Symfony\Component\Security\Http\EventListener\UserCheckerListener
     */
    public static function do($container, $lazyLoad = \true)
    {
        return $container->privates['security.listener.user_checker.api'] = new \_ContaoManager\Symfony\Component\Security\Http\EventListener\UserCheckerListener($container->privates['security.user_checker'] ??= new \_ContaoManager\Symfony\Component\Security\Core\User\InMemoryUserChecker());
    }
}
<?php

namespace _ContaoManager\ContainerLiF9Qbu;

use _ContaoManager\Symfony\Component\DependencyInjection\Argument\RewindableGenerator;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\RuntimeException;
/*
 * @internal This class has been auto-generated by the Symfony Dependency Injection Component.
 */
class getServicesResetterService extends Contao_ManagerApi_ApiKernelProdContainer
{
    /*
     * Gets the public 'services_resetter' shared service.
     *
     * @return \Symfony\Component\HttpKernel\DependencyInjection\ServicesResetter
     */
    public static function do($container, $lazyLoad = \true)
    {
        return $container->services['services_resetter'] = new \_ContaoManager\Symfony\Component\HttpKernel\DependencyInjection\ServicesResetter(new RewindableGenerator(function () use ($container) {
            if (\false) {
                yield 'Contao\ManagerApi\ApiApplication' => null;
            }
            if (isset($container->services['request_stack'])) {
                yield 'request_stack' => $container->services['request_stack'] ?? null;
            }
            if (isset($container->services['cache.app'])) {
                yield 'cache.app' => $container->services['cache.app'] ?? null;
            }
            if (isset($container->services['cache.system'])) {
                yield 'cache.system' => $container->services['cache.system'] ?? null;
            }
            if (\false) {
                yield 'cache.validator' => null;
            }
            if (isset($container->privates['cache.serializer'])) {
                yield 'cache.serializer' => $container->privates['cache.serializer'] ?? null;
            }
            if (\false) {
                yield 'cache.annotations' => null;
            }
            if (isset($container->privates['cache.property_info'])) {
                yield 'cache.property_info' => $container->privates['cache.property_info'] ?? null;
            }
            if (isset($container->services['security.token_storage'])) {
                yield 'security.untracked_token_storage' => $container->services['security.token_storage'] ?? null;
            }
            if (\false) {
                yield 'cache.security_expression_language' => null;
            }
            if (isset($container->services['cache.security_is_granted_attribute_expression_language'])) {
                yield 'cache.security_is_granted_attribute_expression_language' => $container->services['cache.security_is_granted_attribute_expression_language'] ?? null;
            }
            if (isset($container->privates['monolog.handler.main'])) {
                yield 'monolog.handler.main' => $container->privates['monolog.handler.main'] ?? null;
            }
        }, fn() => 0 + (int) \false + (int) isset($container->services['request_stack']) + (int) isset($container->services['cache.app']) + (int) isset($container->services['cache.system']) + (int) \false + (int) isset($container->privates['cache.serializer']) + (int) \false + (int) isset($container->privates['cache.property_info']) + (int) isset($container->services['security.token_storage']) + (int) \false + (int) isset($container->services['cache.security_is_granted_attribute_expression_language']) + (int) isset($container->privates['monolog.handler.main'])), ['_ContaoManager\Contao\ManagerApi\ApiApplication' => ['reset'], 'request_stack' => ['?resetRequestFormats'], 'cache.app' => ['reset'], 'cache.system' => ['reset'], 'cache.validator' => ['reset'], 'cache.serializer' => ['reset'], 'cache.annotations' => ['reset'], 'cache.property_info' => ['reset'], 'security.untracked_token_storage' => ['reset'], 'cache.security_expression_language' => ['reset'], 'cache.security_is_granted_attribute_expression_language' => ['reset'], 'monolog.handler.main' => ['reset']]);
    }
}
<?php

namespace _ContaoManager\ContainerLiF9Qbu;

use _ContaoManager\Symfony\Component\DependencyInjection\Argument\RewindableGenerator;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\RuntimeException;
/*
 * @internal This class has been auto-generated by the Symfony Dependency Injection Component.
 */
class getCache_SecurityIsGrantedAttributeExpressionLanguageService extends Contao_ManagerApi_ApiKernelProdContainer
{
    /*
     * Gets the public 'cache.security_is_granted_attribute_expression_language' shared service.
     *
     * @return \Symfony\Component\Cache\Adapter\AdapterInterface
     */
    public static function do($container, $lazyLoad = \true)
    {
        return $container->services['cache.security_is_granted_attribute_expression_language'] = \_ContaoManager\Symfony\Component\Cache\Adapter\AbstractAdapter::createSystemCache('Pmt1LPgjC3', 0, $container->getParameter('container.build_id'), $container->targetDir . '' . '/pools/system', $container->privates['monolog.logger.cache'] ?? self::getMonolog_Logger_CacheService($container));
    }
}
<?php

namespace _ContaoManager\ContainerLiF9Qbu;

use _ContaoManager\Symfony\Component\DependencyInjection\Argument\RewindableGenerator;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\RuntimeException;
/*
 * @internal This class has been auto-generated by the Symfony Dependency Injection Component.
 */
class getOpcacheControllerService extends Contao_ManagerApi_ApiKernelProdContainer
{
    /*
     * Gets the public 'Contao\ManagerApi\Controller\Server\OpcacheController' shared autowired service.
     *
     * @return \Contao\ManagerApi\Controller\Server\OpcacheController
     */
    public static function do($container, $lazyLoad = \true)
    {
        return $container->services['Contao\ManagerApi\Controller\Server\OpcacheController'] = new \_ContaoManager\Contao\ManagerApi\Controller\Server\OpcacheController();
    }
}
<?php

namespace _ContaoManager\ContainerLiF9Qbu;

use _ContaoManager\Symfony\Component\DependencyInjection\Argument\RewindableGenerator;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\RuntimeException;
/*
 * @internal This class has been auto-generated by the Symfony Dependency Injection Component.
 */
class getConsole_Command_AssetsInstallService extends Contao_ManagerApi_ApiKernelProdContainer
{
    /*
     * Gets the private 'console.command.assets_install' shared service.
     *
     * @return \Symfony\Bundle\FrameworkBundle\Command\AssetsInstallCommand
     */
    public static function do($container, $lazyLoad = \true)
    {
        $container->privates['console.command.assets_install'] = $instance = new \_ContaoManager\Symfony\Bundle\FrameworkBundle\Command\AssetsInstallCommand($container->privates['filesystem'] ??= new \_ContaoManager\Symfony\Component\Filesystem\Filesystem(), \dirname(__DIR__, 4) . '/test-dir');
        $instance->setName('assets:install');
        $instance->setDescription('Install bundle\'s web assets under a public directory');
        return $instance;
    }
}
<?php

namespace _ContaoManager\ContainerLiF9Qbu;

use _ContaoManager\Symfony\Component\DependencyInjection\Argument\RewindableGenerator;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\RuntimeException;
/*
 * @internal This class has been auto-generated by the Symfony Dependency Injection Component.
 */
class getSerializer_Mapping_CacheWarmerService extends Contao_ManagerApi_ApiKernelProdContainer
{
    /*
     * Gets the private 'serializer.mapping.cache_warmer' shared service.
     *
     * @return \Symfony\Bundle\FrameworkBundle\CacheWarmer\SerializerCacheWarmer
     */
    public static function do($container, $lazyLoad = \true)
    {
        return $container->privates['serializer.mapping.cache_warmer'] = new \_ContaoManager\Symfony\Bundle\FrameworkBundle\CacheWarmer\SerializerCacheWarmer([new \_ContaoManager\Symfony\Component\Serializer\Mapping\Loader\AttributeLoader(NULL)], $container->targetDir . '' . '/serialization.php');
    }
}
<?php

namespace _ContaoManager\ContainerLiF9Qbu;

use _ContaoManager\Symfony\Component\DependencyInjection\Argument\RewindableGenerator;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\RuntimeException;
/*
 * @internal This class has been auto-generated by the Symfony Dependency Injection Component.
 */
class getLoginAuthenticatorService extends Contao_ManagerApi_ApiKernelProdContainer
{
    /*
     * Gets the private 'Contao\ManagerApi\Security\LoginAuthenticator' shared autowired service.
     *
     * @return \Contao\ManagerApi\Security\LoginAuthenticator
     */
    public static function do($container, $lazyLoad = \true)
    {
        return $container->privates['Contao\ManagerApi\Security\LoginAuthenticator'] = new \_ContaoManager\Contao\ManagerApi\Security\LoginAuthenticator($container->privates['Contao\ManagerApi\Security\UserProvider'] ?? $container->load('getUserProviderService'), $container->privates['Contao\ManagerApi\Config\UserConfig'] ?? self::getUserConfigService($container), $container->privates['Contao\ManagerApi\Security\JwtManager'] ?? self::getJwtManagerService($container), $container->privates['filesystem'] ??= new \_ContaoManager\Symfony\Component\Filesystem\Filesystem(), $container->services['kernel'] ?? $container->get('kernel', 1));
    }
}
<?php

namespace _ContaoManager\ContainerLiF9Qbu;

use _ContaoManager\Symfony\Component\DependencyInjection\Argument\RewindableGenerator;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\RuntimeException;
/*
 * @internal This class has been auto-generated by the Symfony Dependency Injection Component.
 */
class getSecurity_EventDispatcher_ApiService extends Contao_ManagerApi_ApiKernelProdContainer
{
    /*
     * Gets the private 'security.event_dispatcher.api' shared service.
     *
     * @return \Symfony\Component\EventDispatcher\EventDispatcher
     */
    public static function do($container, $lazyLoad = \true)
    {
        $container->privates['security.event_dispatcher.api'] = $instance = new \_ContaoManager\Symfony\Component\EventDispatcher\EventDispatcher();
        $instance->addListener('_ContaoManager\Symfony\Component\Security\Http\Event\CheckPassportEvent', [#[\Closure(name: 'security.listener.api.user_provider', class: '_ContaoManager\Symfony\Component\Security\Http\EventListener\UserProviderListener')] fn() => $container->privates['security.listener.api.user_provider'] ?? $container->load('getSecurity_Listener_Api_UserProviderService'), 'checkPassport'], 2048);
        $instance->addListener('_ContaoManager\Symfony\Component\Security\Http\Event\CheckPassportEvent', [#[\Closure(name: 'security.listener.user_checker.api', class: '_ContaoManager\Symfony\Component\Security\Http\EventListener\UserCheckerListener')] fn() => $container->privates['security.listener.user_checker.api'] ?? $container->load('getSecurity_Listener_UserChecker_ApiService'), 'preCheckCredentials'], 256);
        $instance->addListener('security.authentication.success', [#[\Closure(name: 'security.listener.user_checker.api', class: '_ContaoManager\Symfony\Component\Security\Http\EventListener\UserCheckerListener')] fn() => $container->privates['security.listener.user_checker.api'] ?? $container->load('getSecurity_Listener_UserChecker_ApiService'), 'postCheckCredentials'], 256);
        $instance->addListener('_ContaoManager\Symfony\Component\Security\Http\Event\CheckPassportEvent', [#[\Closure(name: '_ContaoManager\Contao\ManagerApi\EventListener\CheckTotpListener')] fn() => $container->privates['Contao\ManagerApi\EventListener\CheckTotpListener'] ??= new \_ContaoManager\Contao\ManagerApi\EventListener\CheckTotpListener(), '__invoke'], 0);
        $instance->addListener('_ContaoManager\Symfony\Component\Security\Http\Event\CheckPassportEvent', [#[\Closure(name: 'security.listener.user_provider', class: '_ContaoManager\Symfony\Component\Security\Http\EventListener\UserProviderListener')] fn() => $container->privates['security.listener.user_provider'] ?? $container->load('getSecurity_Listener_UserProviderService'), 'checkPassport'], 1024);
        $instance->addListener('_ContaoManager\Symfony\Component\Security\Http\Event\CheckPassportEvent', [#[\Closure(name: 'security.listener.check_authenticator_credentials', class: '_ContaoManager\Symfony\Component\Security\Http\EventListener\CheckCredentialsListener')] fn() => $container->privates['security.listener.check_authenticator_credentials'] ?? $container->load('getSecurity_Listener_CheckAuthenticatorCredentialsService'), 'checkPassport'], 0);
        $instance->addListener('_ContaoManager\Symfony\Component\Security\Http\Event\LoginSuccessEvent', [#[\Closure(name: 'security.listener.password_migrating', class: '_ContaoManager\Symfony\Component\Security\Http\EventListener\PasswordMigratingListener')] fn() => $container->privates['security.listener.password_migrating'] ?? $container->load('getSecurity_Listener_PasswordMigratingService'), 'onLoginSuccess'], 0);
        return $instance;
    }
}
<?php

namespace _ContaoManager\ContainerLiF9Qbu;

use _ContaoManager\Symfony\Component\DependencyInjection\Argument\RewindableGenerator;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\RuntimeException;
/*
 * @internal This class has been auto-generated by the Symfony Dependency Injection Component.
 */
class getCache_SystemService extends Contao_ManagerApi_ApiKernelProdContainer
{
    /*
     * Gets the public 'cache.system' shared service.
     *
     * @return \Symfony\Component\Cache\Adapter\AdapterInterface
     */
    public static function do($container, $lazyLoad = \true)
    {
        return $container->services['cache.system'] = \_ContaoManager\Symfony\Component\Cache\Adapter\AbstractAdapter::createSystemCache('agLTqXcWDt', 0, $container->getParameter('container.build_id'), $container->targetDir . '' . '/pools/system', $container->privates['monolog.logger.cache'] ?? self::getMonolog_Logger_CacheService($container));
    }
}
<?php

namespace _ContaoManager\ContainerLiF9Qbu;

use _ContaoManager\Symfony\Component\DependencyInjection\Argument\RewindableGenerator;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\RuntimeException;
/*
 * @internal This class has been auto-generated by the Symfony Dependency Injection Component.
 */
class getMonolog_LoggerService extends Contao_ManagerApi_ApiKernelProdContainer
{
    /*
     * Gets the private 'monolog.logger' shared service.
     *
     * @return \Monolog\Logger
     */
    public static function do($container, $lazyLoad = \true)
    {
        $container->privates['monolog.logger'] = $instance = new \_ContaoManager\Monolog\Logger('app');
        $instance->useMicrosecondTimestamps(\true);
        $instance->pushHandler($container->privates['monolog.handler.main'] ?? self::getMonolog_Handler_MainService($container));
        return $instance;
    }
}
<?php

namespace _ContaoManager\ContainerLiF9Qbu;

use _ContaoManager\Symfony\Component\DependencyInjection\Argument\RewindableGenerator;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\RuntimeException;
/*
 * @internal This class has been auto-generated by the Symfony Dependency Injection Component.
 */
class get_Console_Command_CachePoolDelete_LazyService extends Contao_ManagerApi_ApiKernelProdContainer
{
    /*
     * Gets the private '.console.command.cache_pool_delete.lazy' shared service.
     *
     * @return \Symfony\Component\Console\Command\LazyCommand
     */
    public static function do($container, $lazyLoad = \true)
    {
        return $container->privates['.console.command.cache_pool_delete.lazy'] = new \_ContaoManager\Symfony\Component\Console\Command\LazyCommand('cache:pool:delete', [], 'Delete an item from a cache pool', \false, #[\Closure(name: 'console.command.cache_pool_delete', class: '_ContaoManager\Symfony\Bundle\FrameworkBundle\Command\CachePoolDeleteCommand')] fn(): \_ContaoManager\Symfony\Bundle\FrameworkBundle\Command\CachePoolDeleteCommand => $container->privates['console.command.cache_pool_delete'] ?? $container->load('getConsole_Command_CachePoolDeleteService'));
    }
}
<?php

namespace _ContaoManager\ContainerLiF9Qbu;

use _ContaoManager\Symfony\Component\DependencyInjection\Argument\RewindableGenerator;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\RuntimeException;
/*
 * @internal This class has been auto-generated by the Symfony Dependency Injection Component.
 */
class getMonolog_Logger_SecurityService extends Contao_ManagerApi_ApiKernelProdContainer
{
    /*
     * Gets the private 'monolog.logger.security' shared service.
     *
     * @return \Monolog\Logger
     */
    public static function do($container, $lazyLoad = \true)
    {
        $container->privates['monolog.logger.security'] = $instance = new \_ContaoManager\Monolog\Logger('security');
        $instance->pushHandler($container->privates['monolog.handler.main'] ?? self::getMonolog_Handler_MainService($container));
        return $instance;
    }
}
<?php

namespace _ContaoManager\ContainerLiF9Qbu;

use _ContaoManager\Symfony\Component\DependencyInjection\Argument\RewindableGenerator;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\RuntimeException;
/*
 * @internal This class has been auto-generated by the Symfony Dependency Injection Component.
 */
class getUpdateCommandService extends Contao_ManagerApi_ApiKernelProdContainer
{
    /*
     * Gets the public 'Contao\ManagerApi\Command\UpdateCommand' shared autowired service.
     *
     * @return \Contao\ManagerApi\Command\UpdateCommand
     */
    public static function do($container, $lazyLoad = \true)
    {
        $container->services['Contao\ManagerApi\Command\UpdateCommand'] = $instance = new \_ContaoManager\Contao\ManagerApi\Command\UpdateCommand($container->privates['Contao\ManagerApi\System\SelfUpdate'] ?? $container->load('getSelfUpdateService'));
        $instance->setName('self-update');
        $instance->setDescription('Updates Contao Manager to the latest version');
        return $instance;
    }
}
<?php

namespace _ContaoManager\ContainerLiF9Qbu;

use _ContaoManager\Symfony\Component\DependencyInjection\Argument\RewindableGenerator;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\RuntimeException;
/*
 * @internal This class has been auto-generated by the Symfony Dependency Injection Component.
 */
class getDebug_ErrorHandlerConfiguratorService extends Contao_ManagerApi_ApiKernelProdContainer
{
    /*
     * Gets the public 'debug.error_handler_configurator' shared service.
     *
     * @return \Symfony\Component\HttpKernel\Debug\ErrorHandlerConfigurator
     */
    public static function do($container, $lazyLoad = \true)
    {
        $a = new \_ContaoManager\Monolog\Logger('php');
        $a->pushHandler($container->privates['monolog.handler.main'] ?? self::getMonolog_Handler_MainService($container));
        return $container->services['debug.error_handler_configurator'] = new \_ContaoManager\Symfony\Component\HttpKernel\Debug\ErrorHandlerConfigurator($a, NULL, 0, \false, \false, NULL);
    }
}
<?php

namespace _ContaoManager\ContainerLiF9Qbu;

use _ContaoManager\Symfony\Component\DependencyInjection\Argument\RewindableGenerator;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\RuntimeException;
/*
 * @internal This class has been auto-generated by the Symfony Dependency Injection Component.
 */
class getTaskDeleteCommand_LazyService extends Contao_ManagerApi_ApiKernelProdContainer
{
    /*
     * Gets the private '.Contao\ManagerApi\Command\TaskDeleteCommand.lazy' shared service.
     *
     * @return \Symfony\Component\Console\Command\LazyCommand
     */
    public static function do($container, $lazyLoad = \true)
    {
        return $container->privates['.Contao\ManagerApi\Command\TaskDeleteCommand.lazy'] = new \_ContaoManager\Symfony\Component\Console\Command\LazyCommand('task:delete', [], 'Deletes the current task if it is not active.', \false, #[\Closure(name: '_ContaoManager\Contao\ManagerApi\Command\TaskDeleteCommand')] fn(): \_ContaoManager\Contao\ManagerApi\Command\TaskDeleteCommand => $container->services['Contao\ManagerApi\Command\TaskDeleteCommand'] ?? $container->load('getTaskDeleteCommandService'));
    }
}
<?php

namespace _ContaoManager\ContainerLiF9Qbu;

use _ContaoManager\Symfony\Component\DependencyInjection\Argument\RewindableGenerator;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\RuntimeException;
/*
 * @internal This class has been auto-generated by the Symfony Dependency Injection Component.
 */
class getSecurity_Access_AuthenticatedVoterService extends Contao_ManagerApi_ApiKernelProdContainer
{
    /*
     * Gets the private 'security.access.authenticated_voter' shared service.
     *
     * @return \Symfony\Component\Security\Core\Authorization\Voter\AuthenticatedVoter
     */
    public static function do($container, $lazyLoad = \true)
    {
        return $container->privates['security.access.authenticated_voter'] = new \_ContaoManager\Symfony\Component\Security\Core\Authorization\Voter\AuthenticatedVoter($container->privates['contao_manager.security.authentication_trust_resolver'] ?? $container->load('getContaoManager_Security_AuthenticationTrustResolverService'));
    }
}
<?php

namespace _ContaoManager\ContainerLiF9Qbu;

use _ContaoManager\Symfony\Component\DependencyInjection\Argument\RewindableGenerator;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\RuntimeException;
/*
 * @internal This class has been auto-generated by the Symfony Dependency Injection Component.
 */
class getProcessCheckService extends Contao_ManagerApi_ApiKernelProdContainer
{
    /*
     * Gets the private 'Contao\ManagerApi\IntegrityCheck\ProcessCheck' shared autowired service.
     *
     * @return \Contao\ManagerApi\IntegrityCheck\ProcessCheck
     */
    public static function do($container, $lazyLoad = \true)
    {
        return $container->privates['Contao\ManagerApi\IntegrityCheck\ProcessCheck'] = new \_ContaoManager\Contao\ManagerApi\IntegrityCheck\ProcessCheck($container->services['Contao\ManagerApi\I18n\Translator'] ?? $container->load('getTranslatorService'));
    }
}
<?php

namespace _ContaoManager\ContainerLiF9Qbu;

use _ContaoManager\Symfony\Component\DependencyInjection\Argument\RewindableGenerator;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\RuntimeException;
/*
 * @internal This class has been auto-generated by the Symfony Dependency Injection Component.
 */
class getSessionControllerService extends Contao_ManagerApi_ApiKernelProdContainer
{
    /*
     * Gets the public 'Contao\ManagerApi\Controller\SessionController' shared autowired service.
     *
     * @return \Contao\ManagerApi\Controller\SessionController
     */
    public static function do($container, $lazyLoad = \true)
    {
        return $container->services['Contao\ManagerApi\Controller\SessionController'] = new \_ContaoManager\Contao\ManagerApi\Controller\SessionController($container->privates['Contao\ManagerApi\Config\UserConfig'] ?? self::getUserConfigService($container), $container->privates['security.helper'] ?? $container->load('getSecurity_HelperService'), $container->privates['Contao\ManagerApi\Security\JwtManager'] ?? self::getJwtManagerService($container), $container->services['kernel'] ?? $container->get('kernel', 1), $container->privates['Contao\ManagerApi\Security\WebauthnAuthenticator'] ?? $container->load('getWebauthnAuthenticatorService'));
    }
}
<?php

namespace _ContaoManager\ContainerLiF9Qbu;

use _ContaoManager\Symfony\Component\DependencyInjection\Argument\RewindableGenerator;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\RuntimeException;
/*
 * @internal This class has been auto-generated by the Symfony Dependency Injection Component.
 */
class getSecurity_Listener_PasswordMigratingService extends Contao_ManagerApi_ApiKernelProdContainer
{
    /*
     * Gets the private 'security.listener.password_migrating' shared service.
     *
     * @return \Symfony\Component\Security\Http\EventListener\PasswordMigratingListener
     */
    public static function do($container, $lazyLoad = \true)
    {
        return $container->privates['security.listener.password_migrating'] = new \_ContaoManager\Symfony\Component\Security\Http\EventListener\PasswordMigratingListener($container->privates['security.password_hasher_factory'] ?? self::getSecurity_PasswordHasherFactoryService($container));
    }
}
<?php

namespace _ContaoManager\ContainerLiF9Qbu;

use _ContaoManager\Symfony\Component\DependencyInjection\Argument\RewindableGenerator;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\RuntimeException;
/*
 * @internal This class has been auto-generated by the Symfony Dependency Injection Component.
 */
class getSelfUpdateTaskService extends Contao_ManagerApi_ApiKernelProdContainer
{
    /*
     * Gets the private 'Contao\ManagerApi\Task\Manager\SelfUpdateTask' shared autowired service.
     *
     * @return \Contao\ManagerApi\Task\Manager\SelfUpdateTask
     */
    public static function do($container, $lazyLoad = \true)
    {
        $container->privates['Contao\ManagerApi\Task\Manager\SelfUpdateTask'] = $instance = new \_ContaoManager\Contao\ManagerApi\Task\Manager\SelfUpdateTask($container->privates['Contao\ManagerApi\System\SelfUpdate'] ?? $container->load('getSelfUpdateService'), $container->services['Contao\ManagerApi\I18n\Translator'] ?? $container->load('getTranslatorService'));
        $instance->setLogger($container->privates['monolog.logger.tasks'] ?? $container->load('getMonolog_Logger_TasksService'));
        return $instance;
    }
}
<?php

namespace _ContaoManager\ContainerLiF9Qbu;

use _ContaoManager\Symfony\Component\DependencyInjection\Argument\RewindableGenerator;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\RuntimeException;
/*
 * @internal This class has been auto-generated by the Symfony Dependency Injection Component.
 */
class get_Console_Command_SerializerDebug_LazyService extends Contao_ManagerApi_ApiKernelProdContainer
{
    /*
     * Gets the private '.console.command.serializer_debug.lazy' shared service.
     *
     * @return \Symfony\Component\Console\Command\LazyCommand
     */
    public static function do($container, $lazyLoad = \true)
    {
        return $container->privates['.console.command.serializer_debug.lazy'] = new \_ContaoManager\Symfony\Component\Console\Command\LazyCommand('debug:serializer', [], 'Display serialization information for classes', \false, #[\Closure(name: 'console.command.serializer_debug', class: '_ContaoManager\Symfony\Component\Serializer\Command\DebugCommand')] fn(): \_ContaoManager\Symfony\Component\Serializer\Command\DebugCommand => $container->privates['console.command.serializer_debug'] ?? $container->load('getConsole_Command_SerializerDebugService'));
    }
}
<?php

namespace _ContaoManager\ContainerLiF9Qbu;

use _ContaoManager\Symfony\Component\DependencyInjection\Argument\RewindableGenerator;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\RuntimeException;
/*
 * @internal This class has been auto-generated by the Symfony Dependency Injection Component.
 */
class getCache_GlobalClearerService extends Contao_ManagerApi_ApiKernelProdContainer
{
    /*
     * Gets the public 'cache.global_clearer' shared service.
     *
     * @return \Symfony\Component\HttpKernel\CacheClearer\Psr6CacheClearer
     */
    public static function do($container, $lazyLoad = \true)
    {
        return $container->services['cache.global_clearer'] = new \_ContaoManager\Symfony\Component\HttpKernel\CacheClearer\Psr6CacheClearer(['cache.app' => $container->services['cache.app'] ?? $container->load('getCache_AppService'), 'cache.system' => $container->services['cache.system'] ?? $container->load('getCache_SystemService'), 'cache.serializer' => $container->privates['cache.serializer'] ?? self::getCache_SerializerService($container), 'cache.property_info' => $container->privates['cache.property_info'] ?? self::getCache_PropertyInfoService($container), 'cache.property_access' => $container->privates['cache.property_access'] ?? self::getCache_PropertyAccessService($container), 'cache.security_is_granted_attribute_expression_language' => $container->services['cache.security_is_granted_attribute_expression_language'] ?? $container->load('getCache_SecurityIsGrantedAttributeExpressionLanguageService')]);
    }
}
<?php

namespace _ContaoManager\ContainerLiF9Qbu;

use _ContaoManager\Symfony\Component\DependencyInjection\Argument\RewindableGenerator;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\RuntimeException;
/*
 * @internal This class has been auto-generated by the Symfony Dependency Injection Component.
 */
class getTaskManagerService extends Contao_ManagerApi_ApiKernelProdContainer
{
    /*
     * Gets the private 'Contao\ManagerApi\Task\TaskManager' shared autowired service.
     *
     * @return \Contao\ManagerApi\Task\TaskManager
     */
    public static function do($container, $lazyLoad = \true)
    {
        $container->privates['Contao\ManagerApi\Task\TaskManager'] = $instance = new \_ContaoManager\Contao\ManagerApi\Task\TaskManager(new RewindableGenerator(function () use ($container) {
            yield 0 => $container->privates['Contao\ManagerApi\Task\Composer\ClearCacheTask'] ?? $container->load('getClearCacheTaskService');
            yield 1 => $container->privates['Contao\ManagerApi\Task\Composer\DumpAutoloadTask'] ?? $container->load('getDumpAutoloadTaskService');
            yield 2 => $container->privates['Contao\ManagerApi\Task\Contao\BackupCreateTask'] ?? $container->load('getBackupCreateTaskService');
            yield 3 => $container->privates['Contao\ManagerApi\Task\Contao\BackupRestoreTask'] ?? $container->load('getBackupRestoreTaskService');
            yield 4 => $container->privates['Contao\ManagerApi\Task\Contao\RebuildCacheTask'] ?? $container->load('getRebuildCacheTaskService');
            yield 5 => $container->privates['Contao\ManagerApi\Task\Manager\SelfUpdateTask'] ?? $container->load('getSelfUpdateTaskService');
            yield 6 => $container->privates['Contao\ManagerApi\Task\Packages\InstallTask'] ?? $container->load('getInstallTaskService');
            yield 7 => $container->privates['Contao\ManagerApi\Task\Packages\SetupTask'] ?? $container->load('getSetupTaskService');
            yield 8 => $container->privates['Contao\ManagerApi\Task\Packages\UpdateTask'] ?? $container->load('getUpdateTaskService');
        }, 9), $container->services['kernel'] ?? $container->get('kernel', 1), $container->privates['Contao\ManagerApi\Process\ConsoleProcessFactory'] ?? $container->load('getConsoleProcessFactoryService'), $container->privates['security.authorization_checker'] ?? self::getSecurity_AuthorizationCheckerService($container), $container->privates['filesystem'] ??= new \_ContaoManager\Symfony\Component\Filesystem\Filesystem());
        $instance->setLogger($container->privates['monolog.logger.tasks'] ?? $container->load('getMonolog_Logger_TasksService'));
        return $instance;
    }
}
<?php

namespace _ContaoManager\ContainerLiF9Qbu;

use _ContaoManager\Symfony\Component\DependencyInjection\Argument\RewindableGenerator;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\RuntimeException;
/*
 * @internal This class has been auto-generated by the Symfony Dependency Injection Component.
 */
class getConsole_ErrorListenerService extends Contao_ManagerApi_ApiKernelProdContainer
{
    /*
     * Gets the private 'console.error_listener' shared service.
     *
     * @return \Symfony\Component\Console\EventListener\ErrorListener
     */
    public static function do($container, $lazyLoad = \true)
    {
        $a = new \_ContaoManager\Monolog\Logger('console');
        $a->pushHandler($container->privates['monolog.handler.main'] ?? self::getMonolog_Handler_MainService($container));
        return $container->privates['console.error_listener'] = new \_ContaoManager\Symfony\Component\Console\EventListener\ErrorListener($a);
    }
}
<?php

namespace _ContaoManager\ContainerLiF9Qbu;

use _ContaoManager\Symfony\Component\DependencyInjection\Argument\RewindableGenerator;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\RuntimeException;
/*
 * @internal This class has been auto-generated by the Symfony Dependency Injection Component.
 */
class getUploadPackagesControllerService extends Contao_ManagerApi_ApiKernelProdContainer
{
    /*
     * Gets the public 'Contao\ManagerApi\Controller\Packages\UploadPackagesController' shared autowired service.
     *
     * @return \Contao\ManagerApi\Controller\Packages\UploadPackagesController
     */
    public static function do($container, $lazyLoad = \true)
    {
        return $container->services['Contao\ManagerApi\Controller\Packages\UploadPackagesController'] = new \_ContaoManager\Contao\ManagerApi\Controller\Packages\UploadPackagesController($container->privates['Contao\ManagerApi\Config\UploadsConfig'] ?? $container->load('getUploadsConfigService'), $container->privates['Contao\ManagerApi\Composer\Environment'] ?? $container->load('getEnvironmentService'), $container->services['Contao\ManagerApi\I18n\Translator'] ?? $container->load('getTranslatorService'), $container->privates['filesystem'] ??= new \_ContaoManager\Symfony\Component\Filesystem\Filesystem());
    }
}
<?php

namespace _ContaoManager\ContainerLiF9Qbu;

use _ContaoManager\Symfony\Component\DependencyInjection\Argument\RewindableGenerator;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\RuntimeException;
/*
 * @internal This class has been auto-generated by the Symfony Dependency Injection Component.
 */
class getContaoApiService extends Contao_ManagerApi_ApiKernelProdContainer
{
    /*
     * Gets the private 'Contao\ManagerApi\Process\ContaoApi' shared autowired service.
     *
     * @return \Contao\ManagerApi\Process\ContaoApi
     */
    public static function do($container, $lazyLoad = \true)
    {
        return $container->privates['Contao\ManagerApi\Process\ContaoApi'] = new \_ContaoManager\Contao\ManagerApi\Process\ContaoApi($container->privates['Contao\ManagerApi\Process\ConsoleProcessFactory'] ?? $container->load('getConsoleProcessFactoryService'), $container->privates['filesystem'] ??= new \_ContaoManager\Symfony\Component\Filesystem\Filesystem());
    }
}
<?php

namespace _ContaoManager\ContainerLiF9Qbu;

use _ContaoManager\Symfony\Component\DependencyInjection\Argument\RewindableGenerator;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\RuntimeException;
/*
 * @internal This class has been auto-generated by the Symfony Dependency Injection Component.
 */
class getMemoryLimitCheckService extends Contao_ManagerApi_ApiKernelProdContainer
{
    /*
     * Gets the private 'Contao\ManagerApi\IntegrityCheck\MemoryLimitCheck' shared autowired service.
     *
     * @return \Contao\ManagerApi\IntegrityCheck\MemoryLimitCheck
     */
    public static function do($container, $lazyLoad = \true)
    {
        return $container->privates['Contao\ManagerApi\IntegrityCheck\MemoryLimitCheck'] = new \_ContaoManager\Contao\ManagerApi\IntegrityCheck\MemoryLimitCheck($container->services['Contao\ManagerApi\I18n\Translator'] ?? $container->load('getTranslatorService'));
    }
}
<?php

namespace _ContaoManager\ContainerLiF9Qbu;

use _ContaoManager\Symfony\Component\DependencyInjection\Argument\RewindableGenerator;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\RuntimeException;
/*
 * @internal This class has been auto-generated by the Symfony Dependency Injection Component.
 */
class get_Security_Command_DebugFirewall_LazyService extends Contao_ManagerApi_ApiKernelProdContainer
{
    /*
     * Gets the private '.security.command.debug_firewall.lazy' shared service.
     *
     * @return \Symfony\Component\Console\Command\LazyCommand
     */
    public static function do($container, $lazyLoad = \true)
    {
        return $container->privates['.security.command.debug_firewall.lazy'] = new \_ContaoManager\Symfony\Component\Console\Command\LazyCommand('debug:firewall', [], 'Display information about your security firewall(s)', \false, #[\Closure(name: 'security.command.debug_firewall', class: '_ContaoManager\Symfony\Bundle\SecurityBundle\Command\DebugFirewallCommand')] fn(): \_ContaoManager\Symfony\Bundle\SecurityBundle\Command\DebugFirewallCommand => $container->privates['security.command.debug_firewall'] ?? $container->load('getSecurity_Command_DebugFirewallService'));
    }
}
<?php

namespace _ContaoManager\ContainerLiF9Qbu;

use _ContaoManager\Symfony\Component\DependencyInjection\Argument\RewindableGenerator;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\RuntimeException;
/*
 * @internal This class has been auto-generated by the Symfony Dependency Injection Component.
 */
class getSysTempDirCheckService extends Contao_ManagerApi_ApiKernelProdContainer
{
    /*
     * Gets the private 'Contao\ManagerApi\IntegrityCheck\SysTempDirCheck' shared autowired service.
     *
     * @return \Contao\ManagerApi\IntegrityCheck\SysTempDirCheck
     */
    public static function do($container, $lazyLoad = \true)
    {
        return $container->privates['Contao\ManagerApi\IntegrityCheck\SysTempDirCheck'] = new \_ContaoManager\Contao\ManagerApi\IntegrityCheck\SysTempDirCheck($container->privates['filesystem'] ??= new \_ContaoManager\Symfony\Component\Filesystem\Filesystem(), $container->services['Contao\ManagerApi\I18n\Translator'] ?? $container->load('getTranslatorService'));
    }
}
<?php

namespace _ContaoManager\ContainerLiF9Qbu;

use _ContaoManager\Symfony\Component\DependencyInjection\Argument\RewindableGenerator;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\RuntimeException;
/*
 * @internal This class has been auto-generated by the Symfony Dependency Injection Component.
 */
class get_Console_Command_SecretsRemove_LazyService extends Contao_ManagerApi_ApiKernelProdContainer
{
    /*
     * Gets the private '.console.command.secrets_remove.lazy' shared service.
     *
     * @return \Symfony\Component\Console\Command\LazyCommand
     */
    public static function do($container, $lazyLoad = \true)
    {
        return $container->privates['.console.command.secrets_remove.lazy'] = new \_ContaoManager\Symfony\Component\Console\Command\LazyCommand('secrets:remove', [], 'Remove a secret from the vault', \false, #[\Closure(name: 'console.command.secrets_remove', class: '_ContaoManager\Symfony\Bundle\FrameworkBundle\Command\SecretsRemoveCommand')] fn(): \_ContaoManager\Symfony\Bundle\FrameworkBundle\Command\SecretsRemoveCommand => $container->privates['console.command.secrets_remove'] ?? $container->load('getConsole_Command_SecretsRemoveService'));
    }
}
<?php

namespace _ContaoManager\ContainerLiF9Qbu;

use _ContaoManager\Symfony\Component\DependencyInjection\Argument\RewindableGenerator;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\RuntimeException;
/*
 * @internal This class has been auto-generated by the Symfony Dependency Injection Component.
 */
class getArgumentResolver_QueryParameterValueResolverService extends Contao_ManagerApi_ApiKernelProdContainer
{
    /*
     * Gets the private 'argument_resolver.query_parameter_value_resolver' shared service.
     *
     * @return \Symfony\Component\HttpKernel\Controller\ArgumentResolver\QueryParameterValueResolver
     */
    public static function do($container, $lazyLoad = \true)
    {
        return $container->privates['argument_resolver.query_parameter_value_resolver'] = new \_ContaoManager\Symfony\Component\HttpKernel\Controller\ArgumentResolver\QueryParameterValueResolver();
    }
}
<?php

namespace _ContaoManager\ContainerLiF9Qbu;

use _ContaoManager\Symfony\Component\DependencyInjection\Argument\RewindableGenerator;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\RuntimeException;
/*
 * @internal This class has been auto-generated by the Symfony Dependency Injection Component.
 */
class getTaskUpdateCommand_LazyService extends Contao_ManagerApi_ApiKernelProdContainer
{
    /*
     * Gets the private '.Contao\ManagerApi\Command\TaskUpdateCommand.lazy' shared service.
     *
     * @return \Symfony\Component\Console\Command\LazyCommand
     */
    public static function do($container, $lazyLoad = \true)
    {
        return $container->privates['.Contao\ManagerApi\Command\TaskUpdateCommand.lazy'] = new \_ContaoManager\Symfony\Component\Console\Command\LazyCommand('task:update', [], 'Updates the current task and returns the status information.', \false, #[\Closure(name: '_ContaoManager\Contao\ManagerApi\Command\TaskUpdateCommand')] fn(): \_ContaoManager\Contao\ManagerApi\Command\TaskUpdateCommand => $container->services['Contao\ManagerApi\Command\TaskUpdateCommand'] ?? $container->load('getTaskUpdateCommandService'));
    }
}
<?php

namespace _ContaoManager\ContainerLiF9Qbu;

use _ContaoManager\Symfony\Component\DependencyInjection\Argument\RewindableGenerator;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\RuntimeException;
/*
 * @internal This class has been auto-generated by the Symfony Dependency Injection Component.
 */
class getConfigControllerService extends Contao_ManagerApi_ApiKernelProdContainer
{
    /*
     * Gets the public 'Contao\ManagerApi\Controller\Server\ConfigController' shared autowired service.
     *
     * @return \Contao\ManagerApi\Controller\Server\ConfigController
     */
    public static function do($container, $lazyLoad = \true)
    {
        return $container->services['Contao\ManagerApi\Controller\Server\ConfigController'] = new \_ContaoManager\Contao\ManagerApi\Controller\Server\ConfigController($container->privates['Contao\ManagerApi\Config\ManagerConfig'] ?? $container->load('getManagerConfigService'), $container->privates['Contao\ManagerApi\System\ServerInfo'] ?? $container->load('getServerInfoService'), $container->privates['Contao\ManagerApi\Composer\Environment'] ?? $container->load('getEnvironmentService'), $container->services['Contao\ManagerApi\I18n\Translator'] ?? $container->load('getTranslatorService'));
    }
}
<?php

namespace _ContaoManager\ContainerLiF9Qbu;

use _ContaoManager\Symfony\Component\DependencyInjection\Argument\RewindableGenerator;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\RuntimeException;
/*
 * @internal This class has been auto-generated by the Symfony Dependency Injection Component.
 */
class getSelfUpdateService extends Contao_ManagerApi_ApiKernelProdContainer
{
    /*
     * Gets the private 'Contao\ManagerApi\System\SelfUpdate' shared autowired service.
     *
     * @return \Contao\ManagerApi\System\SelfUpdate
     */
    public static function do($container, $lazyLoad = \true)
    {
        return $container->privates['Contao\ManagerApi\System\SelfUpdate'] = new \_ContaoManager\Contao\ManagerApi\System\SelfUpdate($container->services['kernel'] ?? $container->get('kernel', 1), $container->privates['Contao\ManagerApi\Config\ManagerConfig'] ?? $container->load('getManagerConfigService'), $container->privates['Contao\ManagerApi\System\Request'] ?? $container->load('getRequestService'), $container->privates['filesystem'] ??= new \_ContaoManager\Symfony\Component\Filesystem\Filesystem());
    }
}
<?php

namespace _ContaoManager\ContainerLiF9Qbu;

use _ContaoManager\Symfony\Component\DependencyInjection\Argument\RewindableGenerator;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\RuntimeException;
/*
 * @internal This class has been auto-generated by the Symfony Dependency Injection Component.
 */
class getTaskAbortCommandService extends Contao_ManagerApi_ApiKernelProdContainer
{
    /*
     * Gets the public 'Contao\ManagerApi\Command\TaskAbortCommand' shared autowired service.
     *
     * @return \Contao\ManagerApi\Command\TaskAbortCommand
     */
    public static function do($container, $lazyLoad = \true)
    {
        $container->services['Contao\ManagerApi\Command\TaskAbortCommand'] = $instance = new \_ContaoManager\Contao\ManagerApi\Command\TaskAbortCommand($container->privates['Contao\ManagerApi\Task\TaskManager'] ?? $container->load('getTaskManagerService'));
        $instance->setName('task:abort');
        $instance->setDescription('Aborts the current task and returns the status information.');
        return $instance;
    }
}
<?php

namespace _ContaoManager\ContainerLiF9Qbu;

use _ContaoManager\Symfony\Component\DependencyInjection\Argument\RewindableGenerator;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\RuntimeException;
/*
 * @internal This class has been auto-generated by the Symfony Dependency Injection Component.
 */
class getCloudResolverService extends Contao_ManagerApi_ApiKernelProdContainer
{
    /*
     * Gets the private 'Contao\ManagerApi\Composer\CloudResolver' shared autowired service.
     *
     * @return \Contao\ManagerApi\Composer\CloudResolver
     */
    public static function do($container, $lazyLoad = \true)
    {
        $container->privates['Contao\ManagerApi\Composer\CloudResolver'] = $instance = new \_ContaoManager\Contao\ManagerApi\Composer\CloudResolver($container->privates['Contao\ManagerApi\System\Request'] ?? $container->load('getRequestService'));
        $instance->setLogger($container->privates['monolog.logger.tasks'] ?? $container->load('getMonolog_Logger_TasksService'));
        return $instance;
    }
}
<?php

namespace _ContaoManager\ContainerLiF9Qbu;

use _ContaoManager\Symfony\Component\DependencyInjection\Argument\RewindableGenerator;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\RuntimeException;
/*
 * @internal This class has been auto-generated by the Symfony Dependency Injection Component.
 */
class get_Console_Command_SecretsDecryptToLocal_LazyService extends Contao_ManagerApi_ApiKernelProdContainer
{
    /*
     * Gets the private '.console.command.secrets_decrypt_to_local.lazy' shared service.
     *
     * @return \Symfony\Component\Console\Command\LazyCommand
     */
    public static function do($container, $lazyLoad = \true)
    {
        return $container->privates['.console.command.secrets_decrypt_to_local.lazy'] = new \_ContaoManager\Symfony\Component\Console\Command\LazyCommand('secrets:decrypt-to-local', [], 'Decrypt all secrets and stores them in the local vault', \false, #[\Closure(name: 'console.command.secrets_decrypt_to_local', class: '_ContaoManager\Symfony\Bundle\FrameworkBundle\Command\SecretsDecryptToLocalCommand')] fn(): \_ContaoManager\Symfony\Bundle\FrameworkBundle\Command\SecretsDecryptToLocalCommand => $container->privates['console.command.secrets_decrypt_to_local'] ?? $container->load('getConsole_Command_SecretsDecryptToLocalService'));
    }
}
<?php

namespace _ContaoManager\ContainerLiF9Qbu;

use _ContaoManager\Symfony\Component\DependencyInjection\Argument\RewindableGenerator;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\RuntimeException;
/*
 * @internal This class has been auto-generated by the Symfony Dependency Injection Component.
 */
class getAccessKeyControllerService extends Contao_ManagerApi_ApiKernelProdContainer
{
    /*
     * Gets the public 'Contao\ManagerApi\Controller\Contao\AccessKeyController' shared autowired service.
     *
     * @return \Contao\ManagerApi\Controller\Contao\AccessKeyController
     */
    public static function do($container, $lazyLoad = \true)
    {
        return $container->services['Contao\ManagerApi\Controller\Contao\AccessKeyController'] = new \_ContaoManager\Contao\ManagerApi\Controller\Contao\AccessKeyController($container->privates['Contao\ManagerApi\Process\ContaoApi'] ?? $container->load('getContaoApiService'));
    }
}
<?php

namespace _ContaoManager\ContainerLiF9Qbu;

use _ContaoManager\Symfony\Component\DependencyInjection\Argument\RewindableGenerator;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\RuntimeException;
/*
 * @internal This class has been auto-generated by the Symfony Dependency Injection Component.
 */
class getPropertyInfo_SerializerExtractorService extends Contao_ManagerApi_ApiKernelProdContainer
{
    /*
     * Gets the private 'property_info.serializer_extractor' shared service.
     *
     * @return \Symfony\Component\PropertyInfo\Extractor\SerializerExtractor
     */
    public static function do($container, $lazyLoad = \true)
    {
        return $container->privates['property_info.serializer_extractor'] = new \_ContaoManager\Symfony\Component\PropertyInfo\Extractor\SerializerExtractor($container->privates['serializer.mapping.cache_class_metadata_factory'] ?? self::getSerializer_Mapping_CacheClassMetadataFactoryService($container));
    }
}
<?php

namespace _ContaoManager\ContainerLiF9Qbu;

use _ContaoManager\Symfony\Component\DependencyInjection\Argument\RewindableGenerator;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\RuntimeException;
/*
 * @internal This class has been auto-generated by the Symfony Dependency Injection Component.
 */
class getUserProviderService extends Contao_ManagerApi_ApiKernelProdContainer
{
    /*
     * Gets the private 'Contao\ManagerApi\Security\UserProvider' shared autowired service.
     *
     * @return \Contao\ManagerApi\Security\UserProvider
     */
    public static function do($container, $lazyLoad = \true)
    {
        return $container->privates['Contao\ManagerApi\Security\UserProvider'] = new \_ContaoManager\Contao\ManagerApi\Security\UserProvider($container->privates['Contao\ManagerApi\Config\UserConfig'] ?? self::getUserConfigService($container));
    }
}
<?php

namespace _ContaoManager\ContainerLiF9Qbu;

use _ContaoManager\Symfony\Component\DependencyInjection\Argument\RewindableGenerator;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\RuntimeException;
/*
 * @internal This class has been auto-generated by the Symfony Dependency Injection Component.
 */
class getPhpWebControllerService extends Contao_ManagerApi_ApiKernelProdContainer
{
    /*
     * Gets the public 'Contao\ManagerApi\Controller\Server\PhpWebController' shared autowired service.
     *
     * @return \Contao\ManagerApi\Controller\Server\PhpWebController
     */
    public static function do($container, $lazyLoad = \true)
    {
        return $container->services['Contao\ManagerApi\Controller\Server\PhpWebController'] = new \_ContaoManager\Contao\ManagerApi\Controller\Server\PhpWebController($container->privates['Contao\ManagerApi\IntegrityCheck\IntegrityCheckFactory'] ?? $container->load('getIntegrityCheckFactoryService'));
    }
}
<?php

namespace _ContaoManager\ContainerLiF9Qbu;

use _ContaoManager\Symfony\Component\DependencyInjection\Argument\RewindableGenerator;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\RuntimeException;
/*
 * @internal This class has been auto-generated by the Symfony Dependency Injection Component.
 */
class getAboutCommand_LazyService extends Contao_ManagerApi_ApiKernelProdContainer
{
    /*
     * Gets the private '.Contao\ManagerApi\Command\AboutCommand.lazy' shared service.
     *
     * @return \Symfony\Component\Console\Command\LazyCommand
     */
    public static function do($container, $lazyLoad = \true)
    {
        return $container->privates['.Contao\ManagerApi\Command\AboutCommand.lazy'] = new \_ContaoManager\Symfony\Component\Console\Command\LazyCommand('about', [], 'Displays information about Contao Manager and the current server', \false, #[\Closure(name: '_ContaoManager\Contao\ManagerApi\Command\AboutCommand')] fn(): \_ContaoManager\Contao\ManagerApi\Command\AboutCommand => $container->services['Contao\ManagerApi\Command\AboutCommand'] ?? $container->load('getAboutCommandService'));
    }
}
<?php

namespace _ContaoManager\ContainerLiF9Qbu;

use _ContaoManager\Symfony\Component\DependencyInjection\Argument\RewindableGenerator;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\RuntimeException;
/*
 * @internal This class has been auto-generated by the Symfony Dependency Injection Component.
 */
class getConsole_Command_ContainerLintService extends Contao_ManagerApi_ApiKernelProdContainer
{
    /*
     * Gets the private 'console.command.container_lint' shared service.
     *
     * @return \Symfony\Bundle\FrameworkBundle\Command\ContainerLintCommand
     */
    public static function do($container, $lazyLoad = \true)
    {
        $container->privates['console.command.container_lint'] = $instance = new \_ContaoManager\Symfony\Bundle\FrameworkBundle\Command\ContainerLintCommand();
        $instance->setName('lint:container');
        $instance->setDescription('Ensure that arguments injected into services match type declarations');
        return $instance;
    }
}
<?php

namespace _ContaoManager\ContainerLiF9Qbu;

use _ContaoManager\Symfony\Component\DependencyInjection\Argument\RewindableGenerator;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\RuntimeException;
/*
 * @internal This class has been auto-generated by the Symfony Dependency Injection Component.
 */
class get_Console_Command_About_LazyService extends Contao_ManagerApi_ApiKernelProdContainer
{
    /*
     * Gets the private '.console.command.about.lazy' shared service.
     *
     * @return \Symfony\Component\Console\Command\LazyCommand
     */
    public static function do($container, $lazyLoad = \true)
    {
        return $container->privates['.console.command.about.lazy'] = new \_ContaoManager\Symfony\Component\Console\Command\LazyCommand('about', [], 'Display information about the current project', \false, #[\Closure(name: 'console.command.about', class: '_ContaoManager\Symfony\Bundle\FrameworkBundle\Command\AboutCommand')] fn(): \_ContaoManager\Symfony\Bundle\FrameworkBundle\Command\AboutCommand => $container->privates['console.command.about'] ?? $container->load('getConsole_Command_AboutService'));
    }
}
<?php

namespace _ContaoManager\ContainerLiF9Qbu;

use _ContaoManager\Symfony\Component\DependencyInjection\Argument\RewindableGenerator;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\RuntimeException;
/*
 * @internal This class has been auto-generated by the Symfony Dependency Injection Component.
 */
class get_Console_Command_RouterMatch_LazyService extends Contao_ManagerApi_ApiKernelProdContainer
{
    /*
     * Gets the private '.console.command.router_match.lazy' shared service.
     *
     * @return \Symfony\Component\Console\Command\LazyCommand
     */
    public static function do($container, $lazyLoad = \true)
    {
        return $container->privates['.console.command.router_match.lazy'] = new \_ContaoManager\Symfony\Component\Console\Command\LazyCommand('router:match', [], 'Help debug routes by simulating a path info match', \false, #[\Closure(name: 'console.command.router_match', class: '_ContaoManager\Symfony\Bundle\FrameworkBundle\Command\RouterMatchCommand')] fn(): \_ContaoManager\Symfony\Bundle\FrameworkBundle\Command\RouterMatchCommand => $container->privates['console.command.router_match'] ?? $container->load('getConsole_Command_RouterMatchService'));
    }
}
<?php

namespace _ContaoManager\ContainerLiF9Qbu;

use _ContaoManager\Symfony\Component\DependencyInjection\Argument\RewindableGenerator;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\RuntimeException;
/*
 * @internal This class has been auto-generated by the Symfony Dependency Injection Component.
 */
class getTranslatorService extends Contao_ManagerApi_ApiKernelProdContainer
{
    /*
     * Gets the public 'Contao\ManagerApi\I18n\Translator' shared autowired service.
     *
     * @return \Contao\ManagerApi\I18n\Translator
     */
    public static function do($container, $lazyLoad = \true)
    {
        return $container->services['Contao\ManagerApi\I18n\Translator'] = new \_ContaoManager\Contao\ManagerApi\I18n\Translator($container->services['request_stack'] ??= new \_ContaoManager\Symfony\Component\HttpFoundation\RequestStack());
    }
}
<?php

namespace _ContaoManager\ContainerLiF9Qbu;

use _ContaoManager\Symfony\Component\DependencyInjection\Argument\RewindableGenerator;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\RuntimeException;
/*
 * @internal This class has been auto-generated by the Symfony Dependency Injection Component.
 */
class getSelfUpdateControllerService extends Contao_ManagerApi_ApiKernelProdContainer
{
    /*
     * Gets the public 'Contao\ManagerApi\Controller\Server\SelfUpdateController' shared autowired service.
     *
     * @return \Contao\ManagerApi\Controller\Server\SelfUpdateController
     */
    public static function do($container, $lazyLoad = \true)
    {
        return $container->services['Contao\ManagerApi\Controller\Server\SelfUpdateController'] = new \_ContaoManager\Contao\ManagerApi\Controller\Server\SelfUpdateController();
    }
}
<?php

namespace _ContaoManager\ContainerLiF9Qbu;

use _ContaoManager\Symfony\Component\DependencyInjection\Argument\RewindableGenerator;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\RuntimeException;
/*
 * @internal This class has been auto-generated by the Symfony Dependency Injection Component.
 */
class getSecurity_ChannelListenerService extends Contao_ManagerApi_ApiKernelProdContainer
{
    /*
     * Gets the private 'security.channel_listener' shared service.
     *
     * @return \Symfony\Component\Security\Http\Firewall\ChannelListener
     */
    public static function do($container, $lazyLoad = \true)
    {
        $a = $container->privates['router.request_context'] ?? self::getRouter_RequestContextService($container);
        return $container->privates['security.channel_listener'] = new \_ContaoManager\Symfony\Component\Security\Http\Firewall\ChannelListener($container->privates['security.access_map'] ?? $container->load('getSecurity_AccessMapService'), $container->privates['monolog.logger.security'] ?? $container->load('getMonolog_Logger_SecurityService'), $a->getHttpPort(), $a->getHttpsPort());
    }
}
<?php

namespace _ContaoManager\ContainerLiF9Qbu;

use _ContaoManager\Symfony\Component\DependencyInjection\Argument\RewindableGenerator;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\RuntimeException;
/*
 * @internal This class has been auto-generated by the Symfony Dependency Injection Component.
 */
class getArgumentResolver_VariadicService extends Contao_ManagerApi_ApiKernelProdContainer
{
    /*
     * Gets the private 'argument_resolver.variadic' shared service.
     *
     * @return \Symfony\Component\HttpKernel\Controller\ArgumentResolver\VariadicValueResolver
     */
    public static function do($container, $lazyLoad = \true)
    {
        return $container->privates['argument_resolver.variadic'] = new \_ContaoManager\Symfony\Component\HttpKernel\Controller\ArgumentResolver\VariadicValueResolver();
    }
}
<?php

namespace _ContaoManager\ContainerLiF9Qbu;

use _ContaoManager\Symfony\Component\DependencyInjection\Argument\RewindableGenerator;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\RuntimeException;
/*
 * @internal This class has been auto-generated by the Symfony Dependency Injection Component.
 */
class getManagerControllerService extends Contao_ManagerApi_ApiKernelProdContainer
{
    /*
     * Gets the public 'Contao\ManagerApi\Controller\Config\ManagerController' shared autowired service.
     *
     * @return \Contao\ManagerApi\Controller\Config\ManagerController
     */
    public static function do($container, $lazyLoad = \true)
    {
        return $container->services['Contao\ManagerApi\Controller\Config\ManagerController'] = new \_ContaoManager\Contao\ManagerApi\Controller\Config\ManagerController($container->privates['Contao\ManagerApi\Config\ManagerConfig'] ?? $container->load('getManagerConfigService'));
    }
}
<?php

namespace _ContaoManager\ContainerLiF9Qbu;

use _ContaoManager\Symfony\Component\DependencyInjection\Argument\RewindableGenerator;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\RuntimeException;
/*
 * @internal This class has been auto-generated by the Symfony Dependency Injection Component.
 */
class getBackupControllerService extends Contao_ManagerApi_ApiKernelProdContainer
{
    /*
     * Gets the public 'Contao\ManagerApi\Controller\Contao\BackupController' shared autowired service.
     *
     * @return \Contao\ManagerApi\Controller\Contao\BackupController
     */
    public static function do($container, $lazyLoad = \true)
    {
        return $container->services['Contao\ManagerApi\Controller\Contao\BackupController'] = new \_ContaoManager\Contao\ManagerApi\Controller\Contao\BackupController($container->privates['Contao\ManagerApi\Process\ContaoConsole'] ?? $container->load('getContaoConsoleService'), $container->privates['Contao\ManagerApi\Process\ConsoleProcessFactory'] ?? $container->load('getConsoleProcessFactoryService'));
    }
}
<?php

namespace _ContaoManager\ContainerLiF9Qbu;

use _ContaoManager\Symfony\Component\DependencyInjection\Argument\RewindableGenerator;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\RuntimeException;
/*
 * @internal This class has been auto-generated by the Symfony Dependency Injection Component.
 */
class getSecurity_HelperService extends Contao_ManagerApi_ApiKernelProdContainer
{
    /*
     * Gets the private 'security.helper' shared service.
     *
     * @return \Symfony\Bundle\SecurityBundle\Security
     */
    public static function do($container, $lazyLoad = \true)
    {
        return $container->privates['security.helper'] = new \_ContaoManager\Symfony\Bundle\SecurityBundle\Security(new \_ContaoManager\Symfony\Component\DependencyInjection\Argument\ServiceLocator($container->getService ??= $container->getService(...), ['request_stack' => ['services', 'request_stack', 'getRequestStackService', \false], 'security.authenticator.managers_locator' => ['privates', 'security.authenticator.managers_locator', 'getSecurity_Authenticator_ManagersLocatorService', \true], 'security.authorization_checker' => ['privates', 'security.authorization_checker', 'getSecurity_AuthorizationCheckerService', \false], 'security.firewall.event_dispatcher_locator' => ['privates', 'security.firewall.event_dispatcher_locator', 'getSecurity_Firewall_EventDispatcherLocatorService', \true], 'security.firewall.map' => ['privates', 'security.firewall.map', 'getSecurity_Firewall_MapService', \false], 'security.token_storage' => ['services', 'security.token_storage', 'getSecurity_TokenStorageService', \false], 'security.user_checker_locator' => ['privates', 'security.user_checker_locator', 'getSecurity_UserCheckerLocatorService', \true]], ['request_stack' => '?', 'security.authenticator.managers_locator' => '?', 'security.authorization_checker' => '?', 'security.firewall.event_dispatcher_locator' => '?', 'security.firewall.map' => '?', 'security.token_storage' => '?', 'security.user_checker_locator' => '?']), ['api' => new \_ContaoManager\Symfony\Component\DependencyInjection\Argument\ServiceLocator($container->getService ??= $container->getService(...), ['_ContaoManager\Contao\ManagerApi\Security\JwtAuthenticator' => ['privates', '_ContaoManager\Contao\ManagerApi\Security\JwtAuthenticator', 'getJwtAuthenticatorService', \true], '_ContaoManager\Contao\ManagerApi\Security\LoginAuthenticator' => ['privates', '_ContaoManager\Contao\ManagerApi\Security\LoginAuthenticator', 'getLoginAuthenticatorService', \true], '_ContaoManager\Contao\ManagerApi\Security\PasswordlessAuthenticator' => ['privates', '_ContaoManager\Contao\ManagerApi\Security\PasswordlessAuthenticator', 'getPasswordlessAuthenticatorService', \true], '_ContaoManager\Contao\ManagerApi\Security\TokenAuthenticator' => ['privates', '_ContaoManager\Contao\ManagerApi\Security\TokenAuthenticator', 'getTokenAuthenticatorService', \true], '_ContaoManager\Contao\ManagerApi\Security\WebauthnAuthenticator' => ['privates', '_ContaoManager\Contao\ManagerApi\Security\WebauthnAuthenticator', 'getWebauthnAuthenticatorService', \true]], ['_ContaoManager\Contao\ManagerApi\Security\JwtAuthenticator' => '?', '_ContaoManager\Contao\ManagerApi\Security\LoginAuthenticator' => '?', '_ContaoManager\Contao\ManagerApi\Security\PasswordlessAuthenticator' => '?', '_ContaoManager\Contao\ManagerApi\Security\TokenAuthenticator' => '?', '_ContaoManager\Contao\ManagerApi\Security\WebauthnAuthenticator' => '?'])]);
    }
}
<?php

namespace _ContaoManager\ContainerLiF9Qbu;

use _ContaoManager\Symfony\Component\DependencyInjection\Argument\RewindableGenerator;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\RuntimeException;
/*
 * @internal This class has been auto-generated by the Symfony Dependency Injection Component.
 */
class getSecurity_Listener_UserProviderService extends Contao_ManagerApi_ApiKernelProdContainer
{
    /*
     * Gets the private 'security.listener.user_provider' shared service.
     *
     * @return \Symfony\Component\Security\Http\EventListener\UserProviderListener
     */
    public static function do($container, $lazyLoad = \true)
    {
        return $container->privates['security.listener.user_provider'] = new \_ContaoManager\Symfony\Component\Security\Http\EventListener\UserProviderListener($container->privates['Contao\ManagerApi\Security\UserProvider'] ?? $container->load('getUserProviderService'));
    }
}
<?php

namespace _ContaoManager\ContainerLiF9Qbu;

use _ContaoManager\Symfony\Component\DependencyInjection\Argument\RewindableGenerator;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\RuntimeException;
/*
 * @internal This class has been auto-generated by the Symfony Dependency Injection Component.
 */
class get_Console_Command_YamlLint_LazyService extends Contao_ManagerApi_ApiKernelProdContainer
{
    /*
     * Gets the private '.console.command.yaml_lint.lazy' shared service.
     *
     * @return \Symfony\Component\Console\Command\LazyCommand
     */
    public static function do($container, $lazyLoad = \true)
    {
        return $container->privates['.console.command.yaml_lint.lazy'] = new \_ContaoManager\Symfony\Component\Console\Command\LazyCommand('lint:yaml', [], 'Lint a YAML file and outputs encountered errors', \false, #[\Closure(name: 'console.command.yaml_lint', class: '_ContaoManager\Symfony\Bundle\FrameworkBundle\Command\YamlLintCommand')] fn(): \_ContaoManager\Symfony\Bundle\FrameworkBundle\Command\YamlLintCommand => $container->privates['console.command.yaml_lint'] ?? $container->load('getConsole_Command_YamlLintService'));
    }
}
<?php

namespace _ContaoManager\ContainerLiF9Qbu;

use _ContaoManager\Symfony\Component\DependencyInjection\Argument\RewindableGenerator;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\RuntimeException;
/*
 * @internal This class has been auto-generated by the Symfony Dependency Injection Component.
 */
class getSecrets_VaultService extends Contao_ManagerApi_ApiKernelProdContainer
{
    /*
     * Gets the private 'secrets.vault' shared service.
     *
     * @return \Symfony\Bundle\FrameworkBundle\Secrets\SodiumVault
     */
    public static function do($container, $lazyLoad = \true)
    {
        return $container->privates['secrets.vault'] = new \_ContaoManager\Symfony\Bundle\FrameworkBundle\Secrets\SodiumVault(\dirname(__DIR__, 4) . '/test-dir/config/secrets/' . $container->getEnv('string:default:kernel.environment:APP_RUNTIME_ENV'), \_ContaoManager\Symfony\Component\String\LazyString::fromCallable($container->getEnv(...), 'base64:default::SYMFONY_DECRYPTION_SECRET'));
    }
}
<?php

namespace _ContaoManager\ContainerLiF9Qbu;

use _ContaoManager\Symfony\Component\DependencyInjection\Argument\RewindableGenerator;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\RuntimeException;
/*
 * @internal This class has been auto-generated by the Symfony Dependency Injection Component.
 */
class getConsole_Command_ConfigDumpReferenceService extends Contao_ManagerApi_ApiKernelProdContainer
{
    /*
     * Gets the private 'console.command.config_dump_reference' shared service.
     *
     * @return \Symfony\Bundle\FrameworkBundle\Command\ConfigDumpReferenceCommand
     */
    public static function do($container, $lazyLoad = \true)
    {
        $container->privates['console.command.config_dump_reference'] = $instance = new \_ContaoManager\Symfony\Bundle\FrameworkBundle\Command\ConfigDumpReferenceCommand();
        $instance->setName('config:dump-reference');
        $instance->setDescription('Dump the default configuration for an extension');
        return $instance;
    }
}
<?php

namespace _ContaoManager\ContainerLiF9Qbu;

use _ContaoManager\Symfony\Component\DependencyInjection\Argument\RewindableGenerator;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\RuntimeException;
/*
 * @internal This class has been auto-generated by the Symfony Dependency Injection Component.
 */
class getConsole_Command_CacheWarmupService extends Contao_ManagerApi_ApiKernelProdContainer
{
    /*
     * Gets the private 'console.command.cache_warmup' shared service.
     *
     * @return \Symfony\Bundle\FrameworkBundle\Command\CacheWarmupCommand
     */
    public static function do($container, $lazyLoad = \true)
    {
        $container->privates['console.command.cache_warmup'] = $instance = new \_ContaoManager\Symfony\Bundle\FrameworkBundle\Command\CacheWarmupCommand($container->services['cache_warmer'] ?? $container->load('getCacheWarmerService'));
        $instance->setName('cache:warmup');
        $instance->setDescription('Warm up an empty cache');
        return $instance;
    }
}
<?php

namespace _ContaoManager\ContainerLiF9Qbu;

use _ContaoManager\Symfony\Component\DependencyInjection\Argument\RewindableGenerator;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\RuntimeException;
/*
 * @internal This class has been auto-generated by the Symfony Dependency Injection Component.
 */
class getSecurity_Access_RoleHierarchyVoterService extends Contao_ManagerApi_ApiKernelProdContainer
{
    /*
     * Gets the private 'security.access.role_hierarchy_voter' shared service.
     *
     * @return \Symfony\Component\Security\Core\Authorization\Voter\RoleHierarchyVoter
     */
    public static function do($container, $lazyLoad = \true)
    {
        return $container->privates['security.access.role_hierarchy_voter'] = new \_ContaoManager\Symfony\Component\Security\Core\Authorization\Voter\RoleHierarchyVoter(new \_ContaoManager\Symfony\Component\Security\Core\Role\RoleHierarchy($container->parameters['security.role_hierarchy.roles']));
    }
}
<?php

namespace _ContaoManager\ContainerLiF9Qbu;

use _ContaoManager\Symfony\Component\DependencyInjection\Argument\RewindableGenerator;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\RuntimeException;
/*
 * @internal This class has been auto-generated by the Symfony Dependency Injection Component.
 */
class getArgumentResolver_RequestAttributeService extends Contao_ManagerApi_ApiKernelProdContainer
{
    /*
     * Gets the private 'argument_resolver.request_attribute' shared service.
     *
     * @return \Symfony\Component\HttpKernel\Controller\ArgumentResolver\RequestAttributeValueResolver
     */
    public static function do($container, $lazyLoad = \true)
    {
        return $container->privates['argument_resolver.request_attribute'] = new \_ContaoManager\Symfony\Component\HttpKernel\Controller\ArgumentResolver\RequestAttributeValueResolver();
    }
}
<?php

namespace _ContaoManager\ContainerLiF9Qbu;

use _ContaoManager\Symfony\Component\DependencyInjection\Argument\RewindableGenerator;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\RuntimeException;
/*
 * @internal This class has been auto-generated by the Symfony Dependency Injection Component.
 */
class getBackupCreateTaskService extends Contao_ManagerApi_ApiKernelProdContainer
{
    /*
     * Gets the private 'Contao\ManagerApi\Task\Contao\BackupCreateTask' shared autowired service.
     *
     * @return \Contao\ManagerApi\Task\Contao\BackupCreateTask
     */
    public static function do($container, $lazyLoad = \true)
    {
        $container->privates['Contao\ManagerApi\Task\Contao\BackupCreateTask'] = $instance = new \_ContaoManager\Contao\ManagerApi\Task\Contao\BackupCreateTask($container->privates['Contao\ManagerApi\Process\ConsoleProcessFactory'] ?? $container->load('getConsoleProcessFactoryService'), $container->services['Contao\ManagerApi\I18n\Translator'] ?? $container->load('getTranslatorService'));
        $instance->setLogger($container->privates['monolog.logger.tasks'] ?? $container->load('getMonolog_Logger_TasksService'));
        return $instance;
    }
}
<?php

namespace _ContaoManager\ContainerLiF9Qbu;

use _ContaoManager\Symfony\Component\DependencyInjection\Argument\RewindableGenerator;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\RuntimeException;
/*
 * @internal This class has been auto-generated by the Symfony Dependency Injection Component.
 */
class getProcessRunnerCommand_LazyService extends Contao_ManagerApi_ApiKernelProdContainer
{
    /*
     * Gets the private '.Contao\ManagerApi\Command\ProcessRunnerCommand.lazy' shared service.
     *
     * @return \Symfony\Component\Console\Command\LazyCommand
     */
    public static function do($container, $lazyLoad = \true)
    {
        return $container->privates['.Contao\ManagerApi\Command\ProcessRunnerCommand.lazy'] = new \_ContaoManager\Symfony\Component\Console\Command\LazyCommand('background-task:run', [], 'Execute a background task', \false, #[\Closure(name: '_ContaoManager\Contao\ManagerApi\Command\ProcessRunnerCommand')] fn(): \_ContaoManager\Contao\ManagerApi\Command\ProcessRunnerCommand => $container->services['Contao\ManagerApi\Command\ProcessRunnerCommand'] ?? $container->load('getProcessRunnerCommandService'));
    }
}
<?php

namespace _ContaoManager\ContainerLiF9Qbu;

use _ContaoManager\Symfony\Component\DependencyInjection\Argument\RewindableGenerator;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\RuntimeException;
/*
 * @internal This class has been auto-generated by the Symfony Dependency Injection Component.
 */
class getConsole_Command_CachePoolDeleteService extends Contao_ManagerApi_ApiKernelProdContainer
{
    /*
     * Gets the private 'console.command.cache_pool_delete' shared service.
     *
     * @return \Symfony\Bundle\FrameworkBundle\Command\CachePoolDeleteCommand
     */
    public static function do($container, $lazyLoad = \true)
    {
        $container->privates['console.command.cache_pool_delete'] = $instance = new \_ContaoManager\Symfony\Bundle\FrameworkBundle\Command\CachePoolDeleteCommand($container->services['cache.global_clearer'] ?? $container->load('getCache_GlobalClearerService'), ['cache.app', 'cache.system', 'cache.validator', 'cache.serializer', 'cache.annotations', 'cache.property_info', 'cache.property_access', 'cache.security_expression_language', 'cache.security_is_granted_attribute_expression_language']);
        $instance->setName('cache:pool:delete');
        $instance->setDescription('Delete an item from a cache pool');
        return $instance;
    }
}
<?php

namespace _ContaoManager\ContainerLiF9Qbu;

use _ContaoManager\Symfony\Component\DependencyInjection\Argument\RewindableGenerator;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\RuntimeException;
/*
 * @internal This class has been auto-generated by the Symfony Dependency Injection Component.
 */
class getCloudControllerService extends Contao_ManagerApi_ApiKernelProdContainer
{
    /*
     * Gets the public 'Contao\ManagerApi\Controller\Packages\CloudController' shared autowired service.
     *
     * @return \Contao\ManagerApi\Controller\Packages\CloudController
     */
    public static function do($container, $lazyLoad = \true)
    {
        $container->services['Contao\ManagerApi\Controller\Packages\CloudController'] = $instance = new \_ContaoManager\Contao\ManagerApi\Controller\Packages\CloudController($container->privates['Contao\ManagerApi\Composer\Environment'] ?? $container->load('getEnvironmentService'), $container->privates['Contao\ManagerApi\Task\TaskManager'] ?? $container->load('getTaskManagerService'), $container->privates['filesystem'] ??= new \_ContaoManager\Symfony\Component\Filesystem\Filesystem(), $container->privates['monolog.logger'] ?? $container->load('getMonolog_LoggerService'));
        $instance->setContainer((new \_ContaoManager\Symfony\Component\DependencyInjection\Argument\ServiceLocator($container->getService ??= $container->getService(...), ['http_kernel' => ['services', 'http_kernel', 'getHttpKernelService', \false], 'parameter_bag' => ['privates', 'parameter_bag', 'getParameterBagService', \false], 'request_stack' => ['services', 'request_stack', 'getRequestStackService', \false], 'router' => ['services', 'router', 'getRouterService', \false], 'security.authorization_checker' => ['privates', 'security.authorization_checker', 'getSecurity_AuthorizationCheckerService', \false], 'security.token_storage' => ['services', 'security.token_storage', 'getSecurity_TokenStorageService', \false], 'serializer' => ['privates', 'serializer', 'getSerializerService', \false]], ['http_kernel' => '?', 'parameter_bag' => '?', 'request_stack' => '?', 'router' => '?', 'security.authorization_checker' => '?', 'security.token_storage' => '?', 'serializer' => '?']))->withContext('_ContaoManager\Contao\ManagerApi\Controller\Packages\CloudController', $container));
        return $instance;
    }
}
<?php

namespace _ContaoManager\ContainerLiF9Qbu;

use _ContaoManager\Symfony\Component\DependencyInjection\Argument\RewindableGenerator;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\RuntimeException;
/*
 * @internal This class has been auto-generated by the Symfony Dependency Injection Component.
 */
class getSetupTaskService extends Contao_ManagerApi_ApiKernelProdContainer
{
    /*
     * Gets the private 'Contao\ManagerApi\Task\Packages\SetupTask' shared autowired service.
     *
     * @return \Contao\ManagerApi\Task\Packages\SetupTask
     */
    public static function do($container, $lazyLoad = \true)
    {
        $container->privates['Contao\ManagerApi\Task\Packages\SetupTask'] = $instance = new \_ContaoManager\Contao\ManagerApi\Task\Packages\SetupTask($container->privates['Contao\ManagerApi\Process\ConsoleProcessFactory'] ?? $container->load('getConsoleProcessFactoryService'), $container->privates['Contao\ManagerApi\Composer\CloudResolver'] ?? $container->load('getCloudResolverService'), $container->services['kernel'] ?? $container->get('kernel', 1), $container->privates['Contao\ManagerApi\Config\UploadsConfig'] ?? $container->load('getUploadsConfigService'), $container->privates['Contao\ManagerApi\Composer\Environment'] ?? $container->load('getEnvironmentService'), $container->privates['filesystem'] ??= new \_ContaoManager\Symfony\Component\Filesystem\Filesystem(), $container->services['Contao\ManagerApi\I18n\Translator'] ?? $container->load('getTranslatorService'));
        $instance->setLogger($container->privates['monolog.logger.tasks'] ?? $container->load('getMonolog_Logger_TasksService'));
        return $instance;
    }
}
<?php

namespace _ContaoManager\ContainerLiF9Qbu;

use _ContaoManager\Symfony\Component\DependencyInjection\Argument\RewindableGenerator;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\RuntimeException;
/*
 * @internal This class has been auto-generated by the Symfony Dependency Injection Component.
 */
class get_Console_Command_SecretsSet_LazyService extends Contao_ManagerApi_ApiKernelProdContainer
{
    /*
     * Gets the private '.console.command.secrets_set.lazy' shared service.
     *
     * @return \Symfony\Component\Console\Command\LazyCommand
     */
    public static function do($container, $lazyLoad = \true)
    {
        return $container->privates['.console.command.secrets_set.lazy'] = new \_ContaoManager\Symfony\Component\Console\Command\LazyCommand('secrets:set', [], 'Set a secret in the vault', \false, #[\Closure(name: 'console.command.secrets_set', class: '_ContaoManager\Symfony\Bundle\FrameworkBundle\Command\SecretsSetCommand')] fn(): \_ContaoManager\Symfony\Bundle\FrameworkBundle\Command\SecretsSetCommand => $container->privates['console.command.secrets_set'] ?? $container->load('getConsole_Command_SecretsSetService'));
    }
}
<?php

namespace _ContaoManager\ContainerLiF9Qbu;

use _ContaoManager\Symfony\Component\DependencyInjection\Argument\RewindableGenerator;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\RuntimeException;
/*
 * @internal This class has been auto-generated by the Symfony Dependency Injection Component.
 */
class getTemplateControllerService extends Contao_ManagerApi_ApiKernelProdContainer
{
    /*
     * Gets the public 'Symfony\Bundle\FrameworkBundle\Controller\TemplateController' shared service.
     *
     * @return \Symfony\Bundle\FrameworkBundle\Controller\TemplateController
     */
    public static function do($container, $lazyLoad = \true)
    {
        return $container->services['Symfony\Bundle\FrameworkBundle\Controller\TemplateController'] = new \_ContaoManager\Symfony\Bundle\FrameworkBundle\Controller\TemplateController(NULL);
    }
}
<?php

namespace _ContaoManager\ContainerLiF9Qbu;

use _ContaoManager\Symfony\Component\DependencyInjection\Argument\RewindableGenerator;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\RuntimeException;
/*
 * @internal This class has been auto-generated by the Symfony Dependency Injection Component.
 */
class getConsole_Command_CachePoolInvalidateTagsService extends Contao_ManagerApi_ApiKernelProdContainer
{
    /*
     * Gets the private 'console.command.cache_pool_invalidate_tags' shared service.
     *
     * @return \Symfony\Bundle\FrameworkBundle\Command\CachePoolInvalidateTagsCommand
     */
    public static function do($container, $lazyLoad = \true)
    {
        $container->privates['console.command.cache_pool_invalidate_tags'] = $instance = new \_ContaoManager\Symfony\Bundle\FrameworkBundle\Command\CachePoolInvalidateTagsCommand(new \_ContaoManager\Symfony\Component\DependencyInjection\Argument\ServiceLocator($container->getService ??= $container->getService(...), ['cache.app' => ['privates', 'cache.app.taggable', 'getCache_App_TaggableService', \true]], ['cache.app' => '_ContaoManager\Symfony\Component\Cache\Adapter\TagAwareAdapter']));
        $instance->setName('cache:pool:invalidate-tags');
        $instance->setDescription('Invalidate cache tags for all or a specific pool');
        return $instance;
    }
}
<?php

namespace _ContaoManager\ContainerLiF9Qbu;

use _ContaoManager\Symfony\Component\DependencyInjection\Argument\RewindableGenerator;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\RuntimeException;
/*
 * @internal This class has been auto-generated by the Symfony Dependency Injection Component.
 */
class get_Console_Command_EventDispatcherDebug_LazyService extends Contao_ManagerApi_ApiKernelProdContainer
{
    /*
     * Gets the private '.console.command.event_dispatcher_debug.lazy' shared service.
     *
     * @return \Symfony\Component\Console\Command\LazyCommand
     */
    public static function do($container, $lazyLoad = \true)
    {
        return $container->privates['.console.command.event_dispatcher_debug.lazy'] = new \_ContaoManager\Symfony\Component\Console\Command\LazyCommand('debug:event-dispatcher', [], 'Display configured listeners for an application', \false, #[\Closure(name: 'console.command.event_dispatcher_debug', class: '_ContaoManager\Symfony\Bundle\FrameworkBundle\Command\EventDispatcherDebugCommand')] fn(): \_ContaoManager\Symfony\Bundle\FrameworkBundle\Command\EventDispatcherDebugCommand => $container->privates['console.command.event_dispatcher_debug'] ?? $container->load('getConsole_Command_EventDispatcherDebugService'));
    }
}
<?php

namespace _ContaoManager\ContainerLiF9Qbu;

use _ContaoManager\Symfony\Component\DependencyInjection\Argument\RewindableGenerator;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\RuntimeException;
/*
 * @internal This class has been auto-generated by the Symfony Dependency Injection Component.
 */
class get_Console_Command_CachePoolList_LazyService extends Contao_ManagerApi_ApiKernelProdContainer
{
    /*
     * Gets the private '.console.command.cache_pool_list.lazy' shared service.
     *
     * @return \Symfony\Component\Console\Command\LazyCommand
     */
    public static function do($container, $lazyLoad = \true)
    {
        return $container->privates['.console.command.cache_pool_list.lazy'] = new \_ContaoManager\Symfony\Component\Console\Command\LazyCommand('cache:pool:list', [], 'List available cache pools', \false, #[\Closure(name: 'console.command.cache_pool_list', class: '_ContaoManager\Symfony\Bundle\FrameworkBundle\Command\CachePoolListCommand')] fn(): \_ContaoManager\Symfony\Bundle\FrameworkBundle\Command\CachePoolListCommand => $container->privates['console.command.cache_pool_list'] ?? $container->load('getConsole_Command_CachePoolListService'));
    }
}
<?php

namespace _ContaoManager\ContainerLiF9Qbu;

use _ContaoManager\Symfony\Component\DependencyInjection\Argument\RewindableGenerator;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\RuntimeException;
/*
 * @internal This class has been auto-generated by the Symfony Dependency Injection Component.
 */
class getConsole_Command_EventDispatcherDebugService extends Contao_ManagerApi_ApiKernelProdContainer
{
    /*
     * Gets the private 'console.command.event_dispatcher_debug' shared service.
     *
     * @return \Symfony\Bundle\FrameworkBundle\Command\EventDispatcherDebugCommand
     */
    public static function do($container, $lazyLoad = \true)
    {
        $container->privates['console.command.event_dispatcher_debug'] = $instance = new \_ContaoManager\Symfony\Bundle\FrameworkBundle\Command\EventDispatcherDebugCommand($container->privates['.service_locator.BvkMlPl'] ?? $container->load('get_ServiceLocator_BvkMlPlService'));
        $instance->setName('debug:event-dispatcher');
        $instance->setDescription('Display configured listeners for an application');
        return $instance;
    }
}
<?php

namespace _ContaoManager\ContainerLiF9Qbu;

use _ContaoManager\Symfony\Component\DependencyInjection\Argument\RewindableGenerator;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\RuntimeException;
/*
 * @internal This class has been auto-generated by the Symfony Dependency Injection Component.
 */
class getArgumentResolver_ServiceService extends Contao_ManagerApi_ApiKernelProdContainer
{
    /*
     * Gets the private 'argument_resolver.service' shared service.
     *
     * @return \Symfony\Component\HttpKernel\Controller\ArgumentResolver\ServiceValueResolver
     */
    public static function do($container, $lazyLoad = \true)
    {
        return $container->privates['argument_resolver.service'] = new \_ContaoManager\Symfony\Component\HttpKernel\Controller\ArgumentResolver\ServiceValueResolver(new \_ContaoManager\Symfony\Component\DependencyInjection\Argument\ServiceLocator($container->getService ??= $container->getService(...), ['_ContaoManager\Contao\ManagerApi\Controller\Server\AdminUserController::__invoke' => ['privates', '.service_locator.aH5O6Sd', 'get_ServiceLocator_AH5O6SdService', \true], '_ContaoManager\Contao\ManagerApi\Controller\Server\ComposerController::__invoke' => ['privates', '.service_locator.aH5O6Sd', 'get_ServiceLocator_AH5O6SdService', \true], '_ContaoManager\Contao\ManagerApi\Controller\Server\ContaoController::handle' => ['privates', '.service_locator.aH5O6Sd', 'get_ServiceLocator_AH5O6SdService', \true], '_ContaoManager\Contao\ManagerApi\Controller\Server\ContaoController::update' => ['privates', '.service_locator.aH5O6Sd', 'get_ServiceLocator_AH5O6SdService', \true], '_ContaoManager\Contao\ManagerApi\Controller\Server\DatabaseController::handle' => ['privates', '.service_locator.aH5O6Sd', 'get_ServiceLocator_AH5O6SdService', \true], '_ContaoManager\Contao\ManagerApi\Controller\Server\DatabaseController::write' => ['privates', '.service_locator.aH5O6Sd', 'get_ServiceLocator_AH5O6SdService', \true], '_ContaoManager\Contao\ManagerApi\Controller\Server\PhpCliController::__invoke' => ['privates', '.service_locator.y.Xs7Mw', 'get_ServiceLocator_Y_Xs7MwService', \true], '_ContaoManager\Contao\ManagerApi\Controller\Server\PhpWebController::__invoke' => ['privates', '.service_locator.aH5O6Sd', 'get_ServiceLocator_AH5O6SdService', \true], '_ContaoManager\Contao\ManagerApi\Controller\Server\SelfUpdateController::__invoke' => ['privates', '.service_locator.EZsc.DO', 'get_ServiceLocator_EZsc_DOService', \true], 'Contao\ManagerApi\Controller\Server\AdminUserController:__invoke' => ['privates', '.service_locator.aH5O6Sd', 'get_ServiceLocator_AH5O6SdService', \true], '_ContaoManager\Contao\ManagerApi\Controller\Server\AdminUserController' => ['privates', '.service_locator.aH5O6Sd', 'get_ServiceLocator_AH5O6SdService', \true], 'Contao\ManagerApi\Controller\Server\ComposerController:__invoke' => ['privates', '.service_locator.aH5O6Sd', 'get_ServiceLocator_AH5O6SdService', \true], '_ContaoManager\Contao\ManagerApi\Controller\Server\ComposerController' => ['privates', '.service_locator.aH5O6Sd', 'get_ServiceLocator_AH5O6SdService', \true], 'Contao\ManagerApi\Controller\Server\ContaoController:handle' => ['privates', '.service_locator.aH5O6Sd', 'get_ServiceLocator_AH5O6SdService', \true], 'Contao\ManagerApi\Controller\Server\ContaoController:update' => ['privates', '.service_locator.aH5O6Sd', 'get_ServiceLocator_AH5O6SdService', \true], 'Contao\ManagerApi\Controller\Server\DatabaseController:handle' => ['privates', '.service_locator.aH5O6Sd', 'get_ServiceLocator_AH5O6SdService', \true], 'Contao\ManagerApi\Controller\Server\DatabaseController:write' => ['privates', '.service_locator.aH5O6Sd', 'get_ServiceLocator_AH5O6SdService', \true], 'Contao\ManagerApi\Controller\Server\PhpCliController:__invoke' => ['privates', '.service_locator.y.Xs7Mw', 'get_ServiceLocator_Y_Xs7MwService', \true], '_ContaoManager\Contao\ManagerApi\Controller\Server\PhpCliController' => ['privates', '.service_locator.y.Xs7Mw', 'get_ServiceLocator_Y_Xs7MwService', \true], 'Contao\ManagerApi\Controller\Server\PhpWebController:__invoke' => ['privates', '.service_locator.aH5O6Sd', 'get_ServiceLocator_AH5O6SdService', \true], '_ContaoManager\Contao\ManagerApi\Controller\Server\PhpWebController' => ['privates', '.service_locator.aH5O6Sd', 'get_ServiceLocator_AH5O6SdService', \true], 'Contao\ManagerApi\Controller\Server\SelfUpdateController:__invoke' => ['privates', '.service_locator.EZsc.DO', 'get_ServiceLocator_EZsc_DOService', \true], '_ContaoManager\Contao\ManagerApi\Controller\Server\SelfUpdateController' => ['privates', '.service_locator.EZsc.DO', 'get_ServiceLocator_EZsc_DOService', \true]], ['_ContaoManager\Contao\ManagerApi\Controller\Server\AdminUserController::__invoke' => '?', '_ContaoManager\Contao\ManagerApi\Controller\Server\ComposerController::__invoke' => '?', '_ContaoManager\Contao\ManagerApi\Controller\Server\ContaoController::handle' => '?', '_ContaoManager\Contao\ManagerApi\Controller\Server\ContaoController::update' => '?', '_ContaoManager\Contao\ManagerApi\Controller\Server\DatabaseController::handle' => '?', '_ContaoManager\Contao\ManagerApi\Controller\Server\DatabaseController::write' => '?', '_ContaoManager\Contao\ManagerApi\Controller\Server\PhpCliController::__invoke' => '?', '_ContaoManager\Contao\ManagerApi\Controller\Server\PhpWebController::__invoke' => '?', '_ContaoManager\Contao\ManagerApi\Controller\Server\SelfUpdateController::__invoke' => '?', 'Contao\ManagerApi\Controller\Server\AdminUserController:__invoke' => '?', '_ContaoManager\Contao\ManagerApi\Controller\Server\AdminUserController' => '?', 'Contao\ManagerApi\Controller\Server\ComposerController:__invoke' => '?', '_ContaoManager\Contao\ManagerApi\Controller\Server\ComposerController' => '?', 'Contao\ManagerApi\Controller\Server\ContaoController:handle' => '?', 'Contao\ManagerApi\Controller\Server\ContaoController:update' => '?', 'Contao\ManagerApi\Controller\Server\DatabaseController:handle' => '?', 'Contao\ManagerApi\Controller\Server\DatabaseController:write' => '?', 'Contao\ManagerApi\Controller\Server\PhpCliController:__invoke' => '?', '_ContaoManager\Contao\ManagerApi\Controller\Server\PhpCliController' => '?', 'Contao\ManagerApi\Controller\Server\PhpWebController:__invoke' => '?', '_ContaoManager\Contao\ManagerApi\Controller\Server\PhpWebController' => '?', 'Contao\ManagerApi\Controller\Server\SelfUpdateController:__invoke' => '?', '_ContaoManager\Contao\ManagerApi\Controller\Server\SelfUpdateController' => '?']));
    }
}
<?php

namespace _ContaoManager\ContainerLiF9Qbu;

use _ContaoManager\Symfony\Component\DependencyInjection\Argument\RewindableGenerator;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\RuntimeException;
/*
 * @internal This class has been auto-generated by the Symfony Dependency Injection Component.
 */
class get_Console_Command_CachePoolInvalidateTags_LazyService extends Contao_ManagerApi_ApiKernelProdContainer
{
    /*
     * Gets the private '.console.command.cache_pool_invalidate_tags.lazy' shared service.
     *
     * @return \Symfony\Component\Console\Command\LazyCommand
     */
    public static function do($container, $lazyLoad = \true)
    {
        return $container->privates['.console.command.cache_pool_invalidate_tags.lazy'] = new \_ContaoManager\Symfony\Component\Console\Command\LazyCommand('cache:pool:invalidate-tags', [], 'Invalidate cache tags for all or a specific pool', \false, #[\Closure(name: 'console.command.cache_pool_invalidate_tags', class: '_ContaoManager\Symfony\Bundle\FrameworkBundle\Command\CachePoolInvalidateTagsCommand')] fn(): \_ContaoManager\Symfony\Bundle\FrameworkBundle\Command\CachePoolInvalidateTagsCommand => $container->privates['console.command.cache_pool_invalidate_tags'] ?? $container->load('getConsole_Command_CachePoolInvalidateTagsService'));
    }
}
<?php

namespace _ContaoManager\ContainerLiF9Qbu;

use _ContaoManager\Symfony\Component\DependencyInjection\Argument\RewindableGenerator;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\RuntimeException;
/*
 * @internal This class has been auto-generated by the Symfony Dependency Injection Component.
 */
class get_Console_Command_CacheWarmup_LazyService extends Contao_ManagerApi_ApiKernelProdContainer
{
    /*
     * Gets the private '.console.command.cache_warmup.lazy' shared service.
     *
     * @return \Symfony\Component\Console\Command\LazyCommand
     */
    public static function do($container, $lazyLoad = \true)
    {
        return $container->privates['.console.command.cache_warmup.lazy'] = new \_ContaoManager\Symfony\Component\Console\Command\LazyCommand('cache:warmup', [], 'Warm up an empty cache', \false, #[\Closure(name: 'console.command.cache_warmup', class: '_ContaoManager\Symfony\Bundle\FrameworkBundle\Command\CacheWarmupCommand')] fn(): \_ContaoManager\Symfony\Bundle\FrameworkBundle\Command\CacheWarmupCommand => $container->privates['console.command.cache_warmup'] ?? $container->load('getConsole_Command_CacheWarmupService'));
    }
}
<?php

namespace _ContaoManager\ContainerLiF9Qbu;

use _ContaoManager\Symfony\Component\DependencyInjection\Argument\RewindableGenerator;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\RuntimeException;
/*
 * @internal This class has been auto-generated by the Symfony Dependency Injection Component.
 */
class getCache_SystemClearerService extends Contao_ManagerApi_ApiKernelProdContainer
{
    /*
     * Gets the public 'cache.system_clearer' shared service.
     *
     * @return \Symfony\Component\HttpKernel\CacheClearer\Psr6CacheClearer
     */
    public static function do($container, $lazyLoad = \true)
    {
        return $container->services['cache.system_clearer'] = new \_ContaoManager\Symfony\Component\HttpKernel\CacheClearer\Psr6CacheClearer(['cache.system' => $container->services['cache.system'] ?? $container->load('getCache_SystemService'), 'cache.serializer' => $container->privates['cache.serializer'] ?? self::getCache_SerializerService($container), 'cache.property_info' => $container->privates['cache.property_info'] ?? self::getCache_PropertyInfoService($container), 'cache.property_access' => $container->privates['cache.property_access'] ?? self::getCache_PropertyAccessService($container), 'cache.security_is_granted_attribute_expression_language' => $container->services['cache.security_is_granted_attribute_expression_language'] ?? $container->load('getCache_SecurityIsGrantedAttributeExpressionLanguageService')]);
    }
}
<?php

namespace _ContaoManager\ContainerLiF9Qbu;

use _ContaoManager\Symfony\Component\DependencyInjection\Argument\RewindableGenerator;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\RuntimeException;
/*
 * @internal This class has been auto-generated by the Symfony Dependency Injection Component.
 */
class get_ServiceLocator_BvkMlPlService extends Contao_ManagerApi_ApiKernelProdContainer
{
    /*
     * Gets the private '.service_locator.BvkMlPl' shared service.
     *
     * @return \Symfony\Component\DependencyInjection\ServiceLocator
     */
    public static function do($container, $lazyLoad = \true)
    {
        return $container->privates['.service_locator.BvkMlPl'] = new \_ContaoManager\Symfony\Component\DependencyInjection\Argument\ServiceLocator($container->getService ??= $container->getService(...), ['event_dispatcher' => ['services', 'event_dispatcher', 'getEventDispatcherService', \false], 'security.event_dispatcher.api' => ['privates', 'security.event_dispatcher.api', 'getSecurity_EventDispatcher_ApiService', \true]], ['event_dispatcher' => '_ContaoManager\Symfony\Component\EventDispatcher\EventDispatcher', 'security.event_dispatcher.api' => '_ContaoManager\Symfony\Component\EventDispatcher\EventDispatcher']);
    }
}
<?php

namespace _ContaoManager\ContainerLiF9Qbu;

use _ContaoManager\Symfony\Component\DependencyInjection\Argument\RewindableGenerator;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\RuntimeException;
/*
 * @internal This class has been auto-generated by the Symfony Dependency Injection Component.
 */
class getMonolog_Logger_TasksService extends Contao_ManagerApi_ApiKernelProdContainer
{
    /*
     * Gets the private 'monolog.logger.tasks' shared service.
     *
     * @return \Monolog\Logger
     */
    public static function do($container, $lazyLoad = \true)
    {
        $container->privates['monolog.logger.tasks'] = $instance = new \_ContaoManager\Monolog\Logger('tasks');
        $instance->pushHandler($container->privates['monolog.handler.main'] ?? self::getMonolog_Handler_MainService($container));
        return $instance;
    }
}
<?php

namespace _ContaoManager\ContainerLiF9Qbu;

use _ContaoManager\Symfony\Component\DependencyInjection\Argument\RewindableGenerator;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\RuntimeException;
/*
 * @internal This class has been auto-generated by the Symfony Dependency Injection Component.
 */
class getAdminUserControllerService extends Contao_ManagerApi_ApiKernelProdContainer
{
    /*
     * Gets the public 'Contao\ManagerApi\Controller\Server\AdminUserController' shared autowired service.
     *
     * @return \Contao\ManagerApi\Controller\Server\AdminUserController
     */
    public static function do($container, $lazyLoad = \true)
    {
        return $container->services['Contao\ManagerApi\Controller\Server\AdminUserController'] = new \_ContaoManager\Contao\ManagerApi\Controller\Server\AdminUserController($container->privates['Contao\ManagerApi\Process\ContaoConsole'] ?? $container->load('getContaoConsoleService'));
    }
}
<?php

namespace _ContaoManager\ContainerLiF9Qbu;

use _ContaoManager\Symfony\Component\DependencyInjection\Argument\RewindableGenerator;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\RuntimeException;
/*
 * @internal This class has been auto-generated by the Symfony Dependency Injection Component.
 */
class getIntegrityCheckCommandService extends Contao_ManagerApi_ApiKernelProdContainer
{
    /*
     * Gets the public 'Contao\ManagerApi\Command\IntegrityCheckCommand' shared autowired service.
     *
     * @return \Contao\ManagerApi\Command\IntegrityCheckCommand
     */
    public static function do($container, $lazyLoad = \true)
    {
        $container->services['Contao\ManagerApi\Command\IntegrityCheckCommand'] = $instance = new \_ContaoManager\Contao\ManagerApi\Command\IntegrityCheckCommand($container->privates['Contao\ManagerApi\IntegrityCheck\IntegrityCheckFactory'] ?? $container->load('getIntegrityCheckFactoryService'));
        $instance->setName('integrity-check');
        $instance->setDescription('Performs integrity check for the Contao Manager');
        return $instance;
    }
}
<?php

namespace _ContaoManager\ContainerLiF9Qbu;

use _ContaoManager\Symfony\Component\DependencyInjection\Argument\RewindableGenerator;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\RuntimeException;
/*
 * @internal This class has been auto-generated by the Symfony Dependency Injection Component.
 */
class get_Console_Command_AssetsInstall_LazyService extends Contao_ManagerApi_ApiKernelProdContainer
{
    /*
     * Gets the private '.console.command.assets_install.lazy' shared service.
     *
     * @return \Symfony\Component\Console\Command\LazyCommand
     */
    public static function do($container, $lazyLoad = \true)
    {
        return $container->privates['.console.command.assets_install.lazy'] = new \_ContaoManager\Symfony\Component\Console\Command\LazyCommand('assets:install', [], 'Install bundle\'s web assets under a public directory', \false, #[\Closure(name: 'console.command.assets_install', class: '_ContaoManager\Symfony\Bundle\FrameworkBundle\Command\AssetsInstallCommand')] fn(): \_ContaoManager\Symfony\Bundle\FrameworkBundle\Command\AssetsInstallCommand => $container->privates['console.command.assets_install'] ?? $container->load('getConsole_Command_AssetsInstallService'));
    }
}
<?php

namespace _ContaoManager\ContainerLiF9Qbu;

use _ContaoManager\Symfony\Component\DependencyInjection\Argument\RewindableGenerator;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\RuntimeException;
/*
 * @internal This class has been auto-generated by the Symfony Dependency Injection Component.
 */
class getSecurity_Firewall_EventDispatcherLocatorService extends Contao_ManagerApi_ApiKernelProdContainer
{
    /*
     * Gets the private 'security.firewall.event_dispatcher_locator' shared service.
     *
     * @return \Symfony\Component\DependencyInjection\ServiceLocator
     */
    public static function do($container, $lazyLoad = \true)
    {
        return $container->privates['security.firewall.event_dispatcher_locator'] = new \_ContaoManager\Symfony\Component\DependencyInjection\ServiceLocator(['api' => #[\Closure(name: 'security.event_dispatcher.api', class: '_ContaoManager\Symfony\Component\EventDispatcher\EventDispatcher')] fn() => $container->privates['security.event_dispatcher.api'] ?? $container->load('getSecurity_EventDispatcher_ApiService')]);
    }
}
<?php

namespace _ContaoManager\ContainerLiF9Qbu;

use _ContaoManager\Symfony\Component\DependencyInjection\Argument\RewindableGenerator;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\RuntimeException;
/*
 * @internal This class has been auto-generated by the Symfony Dependency Injection Component.
 */
class getConsole_Command_SerializerDebugService extends Contao_ManagerApi_ApiKernelProdContainer
{
    /*
     * Gets the private 'console.command.serializer_debug' shared service.
     *
     * @return \Symfony\Component\Serializer\Command\DebugCommand
     */
    public static function do($container, $lazyLoad = \true)
    {
        $container->privates['console.command.serializer_debug'] = $instance = new \_ContaoManager\Symfony\Component\Serializer\Command\DebugCommand($container->privates['serializer.mapping.cache_class_metadata_factory'] ?? self::getSerializer_Mapping_CacheClassMetadataFactoryService($container));
        $instance->setName('debug:serializer');
        $instance->setDescription('Display serialization information for classes');
        return $instance;
    }
}
<?php

namespace _ContaoManager\ContainerLiF9Qbu;

use _ContaoManager\Symfony\Component\DependencyInjection\Argument\RewindableGenerator;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\RuntimeException;
/*
 * @internal This class has been auto-generated by the Symfony Dependency Injection Component.
 */
class getPhpExtensionsCheckService extends Contao_ManagerApi_ApiKernelProdContainer
{
    /*
     * Gets the private 'Contao\ManagerApi\IntegrityCheck\PhpExtensionsCheck' shared autowired service.
     *
     * @return \Contao\ManagerApi\IntegrityCheck\PhpExtensionsCheck
     */
    public static function do($container, $lazyLoad = \true)
    {
        return $container->privates['Contao\ManagerApi\IntegrityCheck\PhpExtensionsCheck'] = new \_ContaoManager\Contao\ManagerApi\IntegrityCheck\PhpExtensionsCheck($container->services['Contao\ManagerApi\I18n\Translator'] ?? $container->load('getTranslatorService'));
    }
}
<?php

namespace _ContaoManager\ContainerLiF9Qbu;

use _ContaoManager\Symfony\Component\DependencyInjection\Argument\RewindableGenerator;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\RuntimeException;
/*
 * @internal This class has been auto-generated by the Symfony Dependency Injection Component.
 */
class getArgumentResolver_DefaultService extends Contao_ManagerApi_ApiKernelProdContainer
{
    /*
     * Gets the private 'argument_resolver.default' shared service.
     *
     * @return \Symfony\Component\HttpKernel\Controller\ArgumentResolver\DefaultValueResolver
     */
    public static function do($container, $lazyLoad = \true)
    {
        return $container->privates['argument_resolver.default'] = new \_ContaoManager\Symfony\Component\HttpKernel\Controller\ArgumentResolver\DefaultValueResolver();
    }
}
<?php

namespace _ContaoManager\ContainerLiF9Qbu;

use _ContaoManager\Symfony\Component\DependencyInjection\Argument\RewindableGenerator;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\RuntimeException;
/*
 * @internal This class has been auto-generated by the Symfony Dependency Injection Component.
 */
class getAuthControllerService extends Contao_ManagerApi_ApiKernelProdContainer
{
    /*
     * Gets the public 'Contao\ManagerApi\Controller\Config\AuthController' shared autowired service.
     *
     * @return \Contao\ManagerApi\Controller\Config\AuthController
     */
    public static function do($container, $lazyLoad = \true)
    {
        return $container->services['Contao\ManagerApi\Controller\Config\AuthController'] = new \_ContaoManager\Contao\ManagerApi\Controller\Config\AuthController(new \_ContaoManager\Contao\ManagerApi\Config\AuthConfig($container->services['kernel'] ?? $container->get('kernel', 1), $container->privates['filesystem'] ??= new \_ContaoManager\Symfony\Component\Filesystem\Filesystem()));
    }
}
<?php

namespace _ContaoManager\ContainerLiF9Qbu;

use _ContaoManager\Symfony\Component\DependencyInjection\Argument\RewindableGenerator;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\RuntimeException;
/*
 * @internal This class has been auto-generated by the Symfony Dependency Injection Component.
 */
class getArgumentResolver_DatetimeService extends Contao_ManagerApi_ApiKernelProdContainer
{
    /*
     * Gets the private 'argument_resolver.datetime' shared service.
     *
     * @return \Symfony\Component\HttpKernel\Controller\ArgumentResolver\DateTimeValueResolver
     */
    public static function do($container, $lazyLoad = \true)
    {
        return $container->privates['argument_resolver.datetime'] = new \_ContaoManager\Symfony\Component\HttpKernel\Controller\ArgumentResolver\DateTimeValueResolver(new \_ContaoManager\Symfony\Component\Clock\Clock());
    }
}
<?php

namespace _ContaoManager\ContainerLiF9Qbu;

use _ContaoManager\Symfony\Component\DependencyInjection\Argument\RewindableGenerator;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\RuntimeException;
/*
 * @internal This class has been auto-generated by the Symfony Dependency Injection Component.
 */
class getArgumentResolver_UidService extends Contao_ManagerApi_ApiKernelProdContainer
{
    /*
     * Gets the private 'argument_resolver.uid' shared service.
     *
     * @return \Symfony\Component\HttpKernel\Controller\ArgumentResolver\UidValueResolver
     */
    public static function do($container, $lazyLoad = \true)
    {
        return $container->privates['argument_resolver.uid'] = new \_ContaoManager\Symfony\Component\HttpKernel\Controller\ArgumentResolver\UidValueResolver();
    }
}
<?php

namespace _ContaoManager\ContainerLiF9Qbu;

use _ContaoManager\Symfony\Component\DependencyInjection\Argument\RewindableGenerator;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\RuntimeException;
/*
 * @internal This class has been auto-generated by the Symfony Dependency Injection Component.
 */
class getInstallToolLockControllerService extends Contao_ManagerApi_ApiKernelProdContainer
{
    /*
     * Gets the public 'Contao\ManagerApi\Controller\Contao\InstallToolLockController' shared autowired service.
     *
     * @return \Contao\ManagerApi\Controller\Contao\InstallToolLockController
     */
    public static function do($container, $lazyLoad = \true)
    {
        return $container->services['Contao\ManagerApi\Controller\Contao\InstallToolLockController'] = new \_ContaoManager\Contao\ManagerApi\Controller\Contao\InstallToolLockController($container->privates['Contao\ManagerApi\Process\ContaoConsole'] ?? $container->load('getContaoConsoleService'), $container->services['kernel'] ?? $container->get('kernel', 1), $container->privates['filesystem'] ??= new \_ContaoManager\Symfony\Component\Filesystem\Filesystem());
    }
}
<?php

namespace _ContaoManager\ContainerLiF9Qbu;

use _ContaoManager\Symfony\Component\DependencyInjection\Argument\RewindableGenerator;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\RuntimeException;
/*
 * @internal This class has been auto-generated by the Symfony Dependency Injection Component.
 */
class getUpdateCommand_LazyService extends Contao_ManagerApi_ApiKernelProdContainer
{
    /*
     * Gets the private '.Contao\ManagerApi\Command\UpdateCommand.lazy' shared service.
     *
     * @return \Symfony\Component\Console\Command\LazyCommand
     */
    public static function do($container, $lazyLoad = \true)
    {
        return $container->privates['.Contao\ManagerApi\Command\UpdateCommand.lazy'] = new \_ContaoManager\Symfony\Component\Console\Command\LazyCommand('self-update', [], 'Updates Contao Manager to the latest version', \false, #[\Closure(name: '_ContaoManager\Contao\ManagerApi\Command\UpdateCommand')] fn(): \_ContaoManager\Contao\ManagerApi\Command\UpdateCommand => $container->services['Contao\ManagerApi\Command\UpdateCommand'] ?? $container->load('getUpdateCommandService'));
    }
}
<?php

namespace _ContaoManager\ContainerLiF9Qbu;

use _ContaoManager\Symfony\Component\DependencyInjection\Argument\RewindableGenerator;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\RuntimeException;
/*
 * @internal This class has been auto-generated by the Symfony Dependency Injection Component.
 */
class getComposerControllerService extends Contao_ManagerApi_ApiKernelProdContainer
{
    /*
     * Gets the public 'Contao\ManagerApi\Controller\Config\ComposerController' shared autowired service.
     *
     * @return \Contao\ManagerApi\Controller\Config\ComposerController
     */
    public static function do($container, $lazyLoad = \true)
    {
        return $container->services['Contao\ManagerApi\Controller\Config\ComposerController'] = new \_ContaoManager\Contao\ManagerApi\Controller\Config\ComposerController($container->privates['Contao\ManagerApi\Config\ComposerConfig'] ?? $container->load('getComposerConfigService'));
    }
}
<?php

namespace _ContaoManager\ContainerLiF9Qbu;

use _ContaoManager\Symfony\Component\DependencyInjection\Argument\RewindableGenerator;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\RuntimeException;
/*
 * @internal This class has been auto-generated by the Symfony Dependency Injection Component.
 */
class getArgumentResolver_SessionService extends Contao_ManagerApi_ApiKernelProdContainer
{
    /*
     * Gets the private 'argument_resolver.session' shared service.
     *
     * @return \Symfony\Component\HttpKernel\Controller\ArgumentResolver\SessionValueResolver
     */
    public static function do($container, $lazyLoad = \true)
    {
        return $container->privates['argument_resolver.session'] = new \_ContaoManager\Symfony\Component\HttpKernel\Controller\ArgumentResolver\SessionValueResolver();
    }
}
<?php

namespace _ContaoManager\ContainerLiF9Qbu;

use _ContaoManager\Symfony\Component\DependencyInjection\Argument\RewindableGenerator;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\RuntimeException;
/*
 * @internal This class has been auto-generated by the Symfony Dependency Injection Component.
 */
class getCacheWarmerService extends Contao_ManagerApi_ApiKernelProdContainer
{
    /*
     * Gets the public 'cache_warmer' shared service.
     *
     * @return \Symfony\Component\HttpKernel\CacheWarmer\CacheWarmerAggregate
     */
    public static function do($container, $lazyLoad = \true)
    {
        return $container->services['cache_warmer'] = new \_ContaoManager\Symfony\Component\HttpKernel\CacheWarmer\CacheWarmerAggregate(new RewindableGenerator(function () use ($container) {
            yield 0 => $container->privates['config_builder.warmer'] ?? $container->load('getConfigBuilder_WarmerService');
            yield 1 => $container->privates['router.cache_warmer'] ?? $container->load('getRouter_CacheWarmerService');
            yield 2 => $container->privates['serializer.mapping.cache_warmer'] ?? $container->load('getSerializer_Mapping_CacheWarmerService');
        }, 3), \false, $container->targetDir . '' . '/Contao_ManagerApi_ApiKernelProdContainerDeprecations.log');
    }
}
<?php

namespace _ContaoManager\ContainerLiF9Qbu;

use _ContaoManager\Symfony\Component\DependencyInjection\Argument\RewindableGenerator;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\RuntimeException;
/*
 * @internal This class has been auto-generated by the Symfony Dependency Injection Component.
 */
class getRedirectControllerService extends Contao_ManagerApi_ApiKernelProdContainer
{
    /*
     * Gets the public 'Symfony\Bundle\FrameworkBundle\Controller\RedirectController' shared service.
     *
     * @return \Symfony\Bundle\FrameworkBundle\Controller\RedirectController
     */
    public static function do($container, $lazyLoad = \true)
    {
        $a = $container->privates['router.request_context'] ?? self::getRouter_RequestContextService($container);
        return $container->services['Symfony\Bundle\FrameworkBundle\Controller\RedirectController'] = new \_ContaoManager\Symfony\Bundle\FrameworkBundle\Controller\RedirectController($container->services['router'] ?? self::getRouterService($container), $a->getHttpPort(), $a->getHttpsPort());
    }
}
<?php

namespace _ContaoManager\ContainerLiF9Qbu;

use _ContaoManager\Symfony\Component\DependencyInjection\Argument\RewindableGenerator;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\RuntimeException;
/*
 * @internal This class has been auto-generated by the Symfony Dependency Injection Component.
 */
class getUploadsConfigService extends Contao_ManagerApi_ApiKernelProdContainer
{
    /*
     * Gets the private 'Contao\ManagerApi\Config\UploadsConfig' shared autowired service.
     *
     * @return \Contao\ManagerApi\Config\UploadsConfig
     */
    public static function do($container, $lazyLoad = \true)
    {
        return $container->privates['Contao\ManagerApi\Config\UploadsConfig'] = new \_ContaoManager\Contao\ManagerApi\Config\UploadsConfig($container->services['kernel'] ?? $container->get('kernel', 1), $container->privates['filesystem'] ??= new \_ContaoManager\Symfony\Component\Filesystem\Filesystem());
    }
}
<?php

namespace _ContaoManager\ContainerLiF9Qbu;

use _ContaoManager\Symfony\Component\DependencyInjection\Argument\RewindableGenerator;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\RuntimeException;
/*
 * @internal This class has been auto-generated by the Symfony Dependency Injection Component.
 */
class getDatabaseMigrationControllerService extends Contao_ManagerApi_ApiKernelProdContainer
{
    /*
     * Gets the public 'Contao\ManagerApi\Controller\Contao\DatabaseMigrationController' shared autowired service.
     *
     * @return \Contao\ManagerApi\Controller\Contao\DatabaseMigrationController
     */
    public static function do($container, $lazyLoad = \true)
    {
        return $container->services['Contao\ManagerApi\Controller\Contao\DatabaseMigrationController'] = new \_ContaoManager\Contao\ManagerApi\Controller\Contao\DatabaseMigrationController($container->privates['Contao\ManagerApi\Process\ContaoConsole'] ?? $container->load('getContaoConsoleService'), $container->privates['Contao\ManagerApi\Process\ConsoleProcessFactory'] ?? $container->load('getConsoleProcessFactoryService'), $container->services['kernel'] ?? $container->get('kernel', 1));
    }
}
<?php

namespace _ContaoManager\ContainerLiF9Qbu;

use _ContaoManager\Symfony\Component\DependencyInjection\Argument\RewindableGenerator;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\RuntimeException;
/*
 * @internal This class has been auto-generated by the Symfony Dependency Injection Component.
 */
class getConsole_Command_YamlLintService extends Contao_ManagerApi_ApiKernelProdContainer
{
    /*
     * Gets the private 'console.command.yaml_lint' shared service.
     *
     * @return \Symfony\Bundle\FrameworkBundle\Command\YamlLintCommand
     */
    public static function do($container, $lazyLoad = \true)
    {
        $container->privates['console.command.yaml_lint'] = $instance = new \_ContaoManager\Symfony\Bundle\FrameworkBundle\Command\YamlLintCommand();
        $instance->setName('lint:yaml');
        $instance->setDescription('Lint a YAML file and outputs encountered errors');
        return $instance;
    }
}
<?php

namespace _ContaoManager\ContainerLiF9Qbu;

use _ContaoManager\Symfony\Component\DependencyInjection\Argument\RewindableGenerator;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\RuntimeException;
/*
 * @internal This class has been auto-generated by the Symfony Dependency Injection Component.
 */
class getConfigBuilder_WarmerService extends Contao_ManagerApi_ApiKernelProdContainer
{
    /*
     * Gets the private 'config_builder.warmer' shared service.
     *
     * @return \Symfony\Bundle\FrameworkBundle\CacheWarmer\ConfigBuilderCacheWarmer
     */
    public static function do($container, $lazyLoad = \true)
    {
        return $container->privates['config_builder.warmer'] = new \_ContaoManager\Symfony\Bundle\FrameworkBundle\CacheWarmer\ConfigBuilderCacheWarmer($container->services['kernel'] ?? $container->get('kernel', 1), $container->privates['monolog.logger'] ?? $container->load('getMonolog_LoggerService'));
    }
}
<?php

namespace _ContaoManager\ContainerLiF9Qbu;

use _ContaoManager\Symfony\Component\DependencyInjection\Argument\RewindableGenerator;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\RuntimeException;
/*
 * @internal This class has been auto-generated by the Symfony Dependency Injection Component.
 */
class getPasswordlessAuthenticatorService extends Contao_ManagerApi_ApiKernelProdContainer
{
    /*
     * Gets the private 'Contao\ManagerApi\Security\PasswordlessAuthenticator' shared autowired service.
     *
     * @return \Contao\ManagerApi\Security\PasswordlessAuthenticator
     */
    public static function do($container, $lazyLoad = \true)
    {
        return $container->privates['Contao\ManagerApi\Security\PasswordlessAuthenticator'] = new \_ContaoManager\Contao\ManagerApi\Security\PasswordlessAuthenticator($container->privates['Contao\ManagerApi\Security\UserProvider'] ?? $container->load('getUserProviderService'), $container->privates['Contao\ManagerApi\Config\UserConfig'] ?? self::getUserConfigService($container), $container->privates['Contao\ManagerApi\Security\JwtManager'] ?? self::getJwtManagerService($container), $container->privates['filesystem'] ??= new \_ContaoManager\Symfony\Component\Filesystem\Filesystem(), $container->services['kernel'] ?? $container->get('kernel', 1));
    }
}
<?php

namespace _ContaoManager\ContainerLiF9Qbu;

use _ContaoManager\Symfony\Component\DependencyInjection\Argument\RewindableGenerator;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\RuntimeException;
/*
 * @internal This class has been auto-generated by the Symfony Dependency Injection Component.
 */
class getClearCacheTaskService extends Contao_ManagerApi_ApiKernelProdContainer
{
    /*
     * Gets the private 'Contao\ManagerApi\Task\Composer\ClearCacheTask' shared autowired service.
     *
     * @return \Contao\ManagerApi\Task\Composer\ClearCacheTask
     */
    public static function do($container, $lazyLoad = \true)
    {
        $container->privates['Contao\ManagerApi\Task\Composer\ClearCacheTask'] = $instance = new \_ContaoManager\Contao\ManagerApi\Task\Composer\ClearCacheTask($container->privates['Contao\ManagerApi\Process\ConsoleProcessFactory'] ?? $container->load('getConsoleProcessFactoryService'), $container->services['Contao\ManagerApi\I18n\Translator'] ?? $container->load('getTranslatorService'));
        $instance->setLogger($container->privates['monolog.logger.tasks'] ?? $container->load('getMonolog_Logger_TasksService'));
        return $instance;
    }
}
<?php

namespace _ContaoManager\ContainerLiF9Qbu;

use _ContaoManager\Symfony\Component\DependencyInjection\Argument\RewindableGenerator;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\RuntimeException;
/*
 * @internal This class has been auto-generated by the Symfony Dependency Injection Component.
 */
class getRootPackageControllerService extends Contao_ManagerApi_ApiKernelProdContainer
{
    /*
     * Gets the public 'Contao\ManagerApi\Controller\Packages\RootPackageController' shared autowired service.
     *
     * @return \Contao\ManagerApi\Controller\Packages\RootPackageController
     */
    public static function do($container, $lazyLoad = \true)
    {
        return $container->services['Contao\ManagerApi\Controller\Packages\RootPackageController'] = new \_ContaoManager\Contao\ManagerApi\Controller\Packages\RootPackageController($container->privates['Contao\ManagerApi\Composer\Environment'] ?? $container->load('getEnvironmentService'));
    }
}
<?php

namespace _ContaoManager\ContainerLiF9Qbu;

use _ContaoManager\Symfony\Component\DependencyInjection\Argument\RewindableGenerator;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\RuntimeException;
/*
 * @internal This class has been auto-generated by the Symfony Dependency Injection Component.
 */
class getCache_App_TaggableService extends Contao_ManagerApi_ApiKernelProdContainer
{
    /*
     * Gets the private 'cache.app.taggable' shared service.
     *
     * @return \Symfony\Component\Cache\Adapter\TagAwareAdapter
     */
    public static function do($container, $lazyLoad = \true)
    {
        return $container->privates['cache.app.taggable'] = new \_ContaoManager\Symfony\Component\Cache\Adapter\TagAwareAdapter($container->services['cache.app'] ?? $container->load('getCache_AppService'));
    }
}
<?php

namespace _ContaoManager\ContainerLiF9Qbu;

use _ContaoManager\Symfony\Component\DependencyInjection\Argument\RewindableGenerator;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\RuntimeException;
/*
 * @internal This class has been auto-generated by the Symfony Dependency Injection Component.
 */
class getContaoConsoleService extends Contao_ManagerApi_ApiKernelProdContainer
{
    /*
     * Gets the private 'Contao\ManagerApi\Process\ContaoConsole' shared autowired service.
     *
     * @return \Contao\ManagerApi\Process\ContaoConsole
     */
    public static function do($container, $lazyLoad = \true)
    {
        return $container->privates['Contao\ManagerApi\Process\ContaoConsole'] = new \_ContaoManager\Contao\ManagerApi\Process\ContaoConsole($container->privates['Contao\ManagerApi\Process\ConsoleProcessFactory'] ?? $container->load('getConsoleProcessFactoryService'));
    }
}
<?php

namespace _ContaoManager\ContainerLiF9Qbu;

use _ContaoManager\Symfony\Component\DependencyInjection\Argument\RewindableGenerator;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\RuntimeException;
/*
 * @internal This class has been auto-generated by the Symfony Dependency Injection Component.
 */
class getManagerConfigService extends Contao_ManagerApi_ApiKernelProdContainer
{
    /*
     * Gets the private 'Contao\ManagerApi\Config\ManagerConfig' shared autowired service.
     *
     * @return \Contao\ManagerApi\Config\ManagerConfig
     */
    public static function do($container, $lazyLoad = \true)
    {
        return $container->privates['Contao\ManagerApi\Config\ManagerConfig'] = new \_ContaoManager\Contao\ManagerApi\Config\ManagerConfig($container->services['kernel'] ?? $container->get('kernel', 1), $container->privates['filesystem'] ??= new \_ContaoManager\Symfony\Component\Filesystem\Filesystem());
    }
}
<?php

namespace _ContaoManager\ContainerLiF9Qbu;

use _ContaoManager\Symfony\Component\DependencyInjection\Argument\RewindableGenerator;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\RuntimeException;
/*
 * @internal This class has been auto-generated by the Symfony Dependency Injection Component.
 */
class getSecurity_UserValueResolverService extends Contao_ManagerApi_ApiKernelProdContainer
{
    /*
     * Gets the private 'security.user_value_resolver' shared service.
     *
     * @return \Symfony\Component\Security\Http\Controller\UserValueResolver
     */
    public static function do($container, $lazyLoad = \true)
    {
        return $container->privates['security.user_value_resolver'] = new \_ContaoManager\Symfony\Component\Security\Http\Controller\UserValueResolver($container->services['security.token_storage'] ??= new \_ContaoManager\Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorage());
    }
}
<?php

namespace _ContaoManager\ContainerLiF9Qbu;

use _ContaoManager\Symfony\Component\DependencyInjection\Argument\RewindableGenerator;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\RuntimeException;
/*
 * @internal This class has been auto-generated by the Symfony Dependency Injection Component.
 */
class get_Console_Command_DebugAutowiring_LazyService extends Contao_ManagerApi_ApiKernelProdContainer
{
    /*
     * Gets the private '.console.command.debug_autowiring.lazy' shared service.
     *
     * @return \Symfony\Component\Console\Command\LazyCommand
     */
    public static function do($container, $lazyLoad = \true)
    {
        return $container->privates['.console.command.debug_autowiring.lazy'] = new \_ContaoManager\Symfony\Component\Console\Command\LazyCommand('debug:autowiring', [], 'List classes/interfaces you can use for autowiring', \false, #[\Closure(name: 'console.command.debug_autowiring', class: '_ContaoManager\Symfony\Bundle\FrameworkBundle\Command\DebugAutowiringCommand')] fn(): \_ContaoManager\Symfony\Bundle\FrameworkBundle\Command\DebugAutowiringCommand => $container->privates['console.command.debug_autowiring'] ?? $container->load('getConsole_Command_DebugAutowiringService'));
    }
}
<?php

namespace _ContaoManager\ContainerLiF9Qbu;

use _ContaoManager\Symfony\Component\DependencyInjection\Argument\RewindableGenerator;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\RuntimeException;
/*
 * @internal This class has been auto-generated by the Symfony Dependency Injection Component.
 */
class getSecurity_Command_DebugFirewallService extends Contao_ManagerApi_ApiKernelProdContainer
{
    /*
     * Gets the private 'security.command.debug_firewall' shared service.
     *
     * @return \Symfony\Bundle\SecurityBundle\Command\DebugFirewallCommand
     */
    public static function do($container, $lazyLoad = \true)
    {
        $container->privates['security.command.debug_firewall'] = $instance = new \_ContaoManager\Symfony\Bundle\SecurityBundle\Command\DebugFirewallCommand($container->parameters['security.firewalls'], $container->privates['.service_locator.tpD_zef'] ?? self::get_ServiceLocator_TpDZefService($container), $container->privates['.service_locator.BvkMlPl'] ?? $container->load('get_ServiceLocator_BvkMlPlService'), ['api' => [$container->privates['Contao\ManagerApi\Security\LoginAuthenticator'] ?? $container->load('getLoginAuthenticatorService'), $container->privates['Contao\ManagerApi\Security\WebauthnAuthenticator'] ?? $container->load('getWebauthnAuthenticatorService'), $container->privates['Contao\ManagerApi\Security\PasswordlessAuthenticator'] ?? $container->load('getPasswordlessAuthenticatorService'), $container->privates['Contao\ManagerApi\Security\JwtAuthenticator'] ?? $container->load('getJwtAuthenticatorService'), $container->privates['Contao\ManagerApi\Security\TokenAuthenticator'] ?? $container->load('getTokenAuthenticatorService')]], \false);
        $instance->setName('debug:firewall');
        $instance->setDescription('Display information about your security firewall(s)');
        return $instance;
    }
}
<?php

namespace _ContaoManager\ContainerLiF9Qbu;

use _ContaoManager\Symfony\Component\DependencyInjection\Argument\RewindableGenerator;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\RuntimeException;
/*
 * @internal This class has been auto-generated by the Symfony Dependency Injection Component.
 */
class getSecurity_Listener_CheckAuthenticatorCredentialsService extends Contao_ManagerApi_ApiKernelProdContainer
{
    /*
     * Gets the private 'security.listener.check_authenticator_credentials' shared service.
     *
     * @return \Symfony\Component\Security\Http\EventListener\CheckCredentialsListener
     */
    public static function do($container, $lazyLoad = \true)
    {
        return $container->privates['security.listener.check_authenticator_credentials'] = new \_ContaoManager\Symfony\Component\Security\Http\EventListener\CheckCredentialsListener($container->privates['security.password_hasher_factory'] ?? self::getSecurity_PasswordHasherFactoryService($container));
    }
}
<?php

namespace _ContaoManager\ContainerLiF9Qbu;

use _ContaoManager\Symfony\Component\DependencyInjection\Argument\RewindableGenerator;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\RuntimeException;
/*
 * @internal This class has been auto-generated by the Symfony Dependency Injection Component.
 */
class get_Console_Command_CachePoolClear_LazyService extends Contao_ManagerApi_ApiKernelProdContainer
{
    /*
     * Gets the private '.console.command.cache_pool_clear.lazy' shared service.
     *
     * @return \Symfony\Component\Console\Command\LazyCommand
     */
    public static function do($container, $lazyLoad = \true)
    {
        return $container->privates['.console.command.cache_pool_clear.lazy'] = new \_ContaoManager\Symfony\Component\Console\Command\LazyCommand('cache:pool:clear', [], 'Clear cache pools', \false, #[\Closure(name: 'console.command.cache_pool_clear', class: '_ContaoManager\Symfony\Bundle\FrameworkBundle\Command\CachePoolClearCommand')] fn(): \_ContaoManager\Symfony\Bundle\FrameworkBundle\Command\CachePoolClearCommand => $container->privates['console.command.cache_pool_clear'] ?? $container->load('getConsole_Command_CachePoolClearService'));
    }
}
<?php

namespace _ContaoManager\ContainerLiF9Qbu;

use _ContaoManager\Symfony\Component\DependencyInjection\Argument\RewindableGenerator;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\RuntimeException;
/*
 * @internal This class has been auto-generated by the Symfony Dependency Injection Component.
 */
class getConsole_Command_CacheClearService extends Contao_ManagerApi_ApiKernelProdContainer
{
    /*
     * Gets the private 'console.command.cache_clear' shared service.
     *
     * @return \Symfony\Bundle\FrameworkBundle\Command\CacheClearCommand
     */
    public static function do($container, $lazyLoad = \true)
    {
        $container->privates['console.command.cache_clear'] = $instance = new \_ContaoManager\Symfony\Bundle\FrameworkBundle\Command\CacheClearCommand(new \_ContaoManager\Symfony\Component\HttpKernel\CacheClearer\ChainCacheClearer(new RewindableGenerator(fn() => new \EmptyIterator(), 0)), $container->privates['filesystem'] ??= new \_ContaoManager\Symfony\Component\Filesystem\Filesystem());
        $instance->setName('cache:clear');
        $instance->setDescription('Clear the cache');
        return $instance;
    }
}
<?php

namespace _ContaoManager\ContainerLiF9Qbu;

use _ContaoManager\Symfony\Component\DependencyInjection\Argument\RewindableGenerator;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\RuntimeException;
/*
 * @internal This class has been auto-generated by the Symfony Dependency Injection Component.
 */
class getPhpinfoControllerService extends Contao_ManagerApi_ApiKernelProdContainer
{
    /*
     * Gets the public 'Contao\ManagerApi\Controller\Server\PhpinfoController' shared autowired service.
     *
     * @return \Contao\ManagerApi\Controller\Server\PhpinfoController
     */
    public static function do($container, $lazyLoad = \true)
    {
        return $container->services['Contao\ManagerApi\Controller\Server\PhpinfoController'] = new \_ContaoManager\Contao\ManagerApi\Controller\Server\PhpinfoController();
    }
}
<?php

namespace _ContaoManager\ContainerLiF9Qbu;

use _ContaoManager\Symfony\Component\DependencyInjection\Argument\RewindableGenerator;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\RuntimeException;
/*
 * @internal This class has been auto-generated by the Symfony Dependency Injection Component.
 */
class getConsole_Command_CachePoolListService extends Contao_ManagerApi_ApiKernelProdContainer
{
    /*
     * Gets the private 'console.command.cache_pool_list' shared service.
     *
     * @return \Symfony\Bundle\FrameworkBundle\Command\CachePoolListCommand
     */
    public static function do($container, $lazyLoad = \true)
    {
        $container->privates['console.command.cache_pool_list'] = $instance = new \_ContaoManager\Symfony\Bundle\FrameworkBundle\Command\CachePoolListCommand(['cache.app', 'cache.system', 'cache.validator', 'cache.serializer', 'cache.annotations', 'cache.property_info', 'cache.property_access', 'cache.security_expression_language', 'cache.security_is_granted_attribute_expression_language']);
        $instance->setName('cache:pool:list');
        $instance->setDescription('List available cache pools');
        return $instance;
    }
}
<?php

namespace _ContaoManager\ContainerLiF9Qbu;

use _ContaoManager\Symfony\Component\DependencyInjection\Argument\RewindableGenerator;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\RuntimeException;
/*
 * @internal This class has been auto-generated by the Symfony Dependency Injection Component.
 */
class getSecurity_Authenticator_Manager_ApiService extends Contao_ManagerApi_ApiKernelProdContainer
{
    /*
     * Gets the private 'security.authenticator.manager.api' shared service.
     *
     * @return \Symfony\Component\Security\Http\Authentication\AuthenticatorManager
     */
    public static function do($container, $lazyLoad = \true)
    {
        $a = $container->privates['Contao\ManagerApi\Security\WebauthnAuthenticator'] ?? $container->load('getWebauthnAuthenticatorService');
        if (isset($container->privates['security.authenticator.manager.api'])) {
            return $container->privates['security.authenticator.manager.api'];
        }
        $instance = new \_ContaoManager\Symfony\Component\Security\Http\Authentication\AuthenticatorManager([$container->privates['Contao\ManagerApi\Security\LoginAuthenticator'] ?? $container->load('getLoginAuthenticatorService'), $a, $container->privates['Contao\ManagerApi\Security\PasswordlessAuthenticator'] ?? $container->load('getPasswordlessAuthenticatorService'), $container->privates['Contao\ManagerApi\Security\JwtAuthenticator'] ?? $container->load('getJwtAuthenticatorService'), $container->privates['Contao\ManagerApi\Security\TokenAuthenticator'] ?? $container->load('getTokenAuthenticatorService')], $container->services['security.token_storage'] ??= new \_ContaoManager\Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorage(), $container->privates['security.event_dispatcher.api'] ?? $container->load('getSecurity_EventDispatcher_ApiService'), 'api', $container->privates['monolog.logger.security'] ?? $container->load('getMonolog_Logger_SecurityService'), \true, \true, []);
        if (isset($container->privates['security.authenticator.manager.api'])) {
            return $container->privates['security.authenticator.manager.api'];
        }
        return $container->privates['security.authenticator.manager.api'] = $instance;
    }
}
<?php

namespace _ContaoManager\ContainerLiF9Qbu;

use _ContaoManager\Symfony\Component\DependencyInjection\Argument\RewindableGenerator;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\RuntimeException;
/*
 * @internal This class has been auto-generated by the Symfony Dependency Injection Component.
 */
class getAllowUrlFopenCheckService extends Contao_ManagerApi_ApiKernelProdContainer
{
    /*
     * Gets the private 'Contao\ManagerApi\IntegrityCheck\AllowUrlFopenCheck' shared autowired service.
     *
     * @return \Contao\ManagerApi\IntegrityCheck\AllowUrlFopenCheck
     */
    public static function do($container, $lazyLoad = \true)
    {
        return $container->privates['Contao\ManagerApi\IntegrityCheck\AllowUrlFopenCheck'] = new \_ContaoManager\Contao\ManagerApi\IntegrityCheck\AllowUrlFopenCheck($container->services['Contao\ManagerApi\I18n\Translator'] ?? $container->load('getTranslatorService'));
    }
}
<?php

namespace _ContaoManager\ContainerLiF9Qbu;

use _ContaoManager\Symfony\Component\DependencyInjection\Argument\RewindableGenerator;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\RuntimeException;
/*
 * @internal This class has been auto-generated by the Symfony Dependency Injection Component.
 */
class getRebuildCacheTaskService extends Contao_ManagerApi_ApiKernelProdContainer
{
    /*
     * Gets the private 'Contao\ManagerApi\Task\Contao\RebuildCacheTask' shared autowired service.
     *
     * @return \Contao\ManagerApi\Task\Contao\RebuildCacheTask
     */
    public static function do($container, $lazyLoad = \true)
    {
        $container->privates['Contao\ManagerApi\Task\Contao\RebuildCacheTask'] = $instance = new \_ContaoManager\Contao\ManagerApi\Task\Contao\RebuildCacheTask($container->services['kernel'] ?? $container->get('kernel', 1), $container->privates['Contao\ManagerApi\Process\ConsoleProcessFactory'] ?? $container->load('getConsoleProcessFactoryService'), $container->privates['Contao\ManagerApi\Process\ContaoConsole'] ?? $container->load('getContaoConsoleService'), $container->services['Contao\ManagerApi\I18n\Translator'] ?? $container->load('getTranslatorService'), $container->privates['filesystem'] ??= new \_ContaoManager\Symfony\Component\Filesystem\Filesystem());
        $instance->setLogger($container->privates['monolog.logger.tasks'] ?? $container->load('getMonolog_Logger_TasksService'));
        return $instance;
    }
}
<?php

namespace _ContaoManager\ContainerLiF9Qbu;

use _ContaoManager\Symfony\Component\DependencyInjection\Argument\RewindableGenerator;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\RuntimeException;
/*
 * @internal This class has been auto-generated by the Symfony Dependency Injection Component.
 */
class getSecurity_Firewall_Authenticator_ApiService extends Contao_ManagerApi_ApiKernelProdContainer
{
    /*
     * Gets the private 'security.firewall.authenticator.api' shared service.
     *
     * @return \Symfony\Component\Security\Http\Firewall\AuthenticatorManagerListener
     */
    public static function do($container, $lazyLoad = \true)
    {
        $a = $container->privates['security.authenticator.manager.api'] ?? $container->load('getSecurity_Authenticator_Manager_ApiService');
        if (isset($container->privates['security.firewall.authenticator.api'])) {
            return $container->privates['security.firewall.authenticator.api'];
        }
        $instance = new \_ContaoManager\Symfony\Component\Security\Http\Firewall\AuthenticatorManagerListener($a);
        if (isset($container->privates['security.firewall.authenticator.api'])) {
            return $container->privates['security.firewall.authenticator.api'];
        }
        return $container->privates['security.firewall.authenticator.api'] = $instance;
    }
}
<?php

namespace _ContaoManager\ContainerLiF9Qbu;

use _ContaoManager\Symfony\Component\DependencyInjection\Argument\RewindableGenerator;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\RuntimeException;
/*
 * @internal This class has been auto-generated by the Symfony Dependency Injection Component.
 */
class get_Console_Command_SecretsGenerateKey_LazyService extends Contao_ManagerApi_ApiKernelProdContainer
{
    /*
     * Gets the private '.console.command.secrets_generate_key.lazy' shared service.
     *
     * @return \Symfony\Component\Console\Command\LazyCommand
     */
    public static function do($container, $lazyLoad = \true)
    {
        return $container->privates['.console.command.secrets_generate_key.lazy'] = new \_ContaoManager\Symfony\Component\Console\Command\LazyCommand('secrets:generate-keys', [], 'Generate new encryption keys', \false, #[\Closure(name: 'console.command.secrets_generate_key', class: '_ContaoManager\Symfony\Bundle\FrameworkBundle\Command\SecretsGenerateKeysCommand')] fn(): \_ContaoManager\Symfony\Bundle\FrameworkBundle\Command\SecretsGenerateKeysCommand => $container->privates['console.command.secrets_generate_key'] ?? $container->load('getConsole_Command_SecretsGenerateKeyService'));
    }
}
<?php

namespace _ContaoManager\ContainerLiF9Qbu;

use _ContaoManager\Symfony\Component\DependencyInjection\Argument\RewindableGenerator;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\RuntimeException;
/*
 * @internal This class has been auto-generated by the Symfony Dependency Injection Component.
 */
class get_Console_Command_RouterDebug_LazyService extends Contao_ManagerApi_ApiKernelProdContainer
{
    /*
     * Gets the private '.console.command.router_debug.lazy' shared service.
     *
     * @return \Symfony\Component\Console\Command\LazyCommand
     */
    public static function do($container, $lazyLoad = \true)
    {
        return $container->privates['.console.command.router_debug.lazy'] = new \_ContaoManager\Symfony\Component\Console\Command\LazyCommand('debug:router', [], 'Display current routes for an application', \false, #[\Closure(name: 'console.command.router_debug', class: '_ContaoManager\Symfony\Bundle\FrameworkBundle\Command\RouterDebugCommand')] fn(): \_ContaoManager\Symfony\Bundle\FrameworkBundle\Command\RouterDebugCommand => $container->privates['console.command.router_debug'] ?? $container->load('getConsole_Command_RouterDebugService'));
    }
}
<?php

namespace _ContaoManager\ContainerLiF9Qbu;

use _ContaoManager\Symfony\Component\DependencyInjection\Argument\RewindableGenerator;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\RuntimeException;
/*
 * @internal This class has been auto-generated by the Symfony Dependency Injection Component.
 */
class getConsole_Command_CachePoolClearService extends Contao_ManagerApi_ApiKernelProdContainer
{
    /*
     * Gets the private 'console.command.cache_pool_clear' shared service.
     *
     * @return \Symfony\Bundle\FrameworkBundle\Command\CachePoolClearCommand
     */
    public static function do($container, $lazyLoad = \true)
    {
        $container->privates['console.command.cache_pool_clear'] = $instance = new \_ContaoManager\Symfony\Bundle\FrameworkBundle\Command\CachePoolClearCommand($container->services['cache.global_clearer'] ?? $container->load('getCache_GlobalClearerService'), ['cache.app', 'cache.system', 'cache.validator', 'cache.serializer', 'cache.annotations', 'cache.property_info', 'cache.property_access', 'cache.security_expression_language', 'cache.security_is_granted_attribute_expression_language']);
        $instance->setName('cache:pool:clear');
        $instance->setDescription('Clear cache pools');
        return $instance;
    }
}
<?php

namespace _ContaoManager\ContainerLiF9Qbu;

use _ContaoManager\Symfony\Component\DependencyInjection\Argument\RewindableGenerator;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\RuntimeException;
/*
 * @internal This class has been auto-generated by the Symfony Dependency Injection Component.
 */
class getLogControllerService extends Contao_ManagerApi_ApiKernelProdContainer
{
    /*
     * Gets the public 'Contao\ManagerApi\Controller\LogController' shared autowired service.
     *
     * @return \Contao\ManagerApi\Controller\LogController
     */
    public static function do($container, $lazyLoad = \true)
    {
        return $container->services['Contao\ManagerApi\Controller\LogController'] = new \_ContaoManager\Contao\ManagerApi\Controller\LogController($container->services['kernel'] ?? $container->get('kernel', 1), $container->privates['filesystem'] ??= new \_ContaoManager\Symfony\Component\Filesystem\Filesystem());
    }
}
<?php

namespace _ContaoManager\ContainerLiF9Qbu;

use _ContaoManager\Symfony\Component\DependencyInjection\Argument\RewindableGenerator;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\RuntimeException;
/*
 * @internal This class has been auto-generated by the Symfony Dependency Injection Component.
 */
class getContainer_EnvVarProcessorService extends Contao_ManagerApi_ApiKernelProdContainer
{
    /*
     * Gets the private 'container.env_var_processor' shared service.
     *
     * @return \Symfony\Component\DependencyInjection\EnvVarProcessor
     */
    public static function do($container, $lazyLoad = \true)
    {
        return $container->privates['container.env_var_processor'] = new \_ContaoManager\Symfony\Component\DependencyInjection\EnvVarProcessor($container, new RewindableGenerator(function () use ($container) {
            yield 0 => $container->privates['secrets.vault'] ?? $container->load('getSecrets_VaultService');
        }, 1));
    }
}
<?php

namespace _ContaoManager\ContainerLiF9Qbu;

use _ContaoManager\Symfony\Component\DependencyInjection\Argument\RewindableGenerator;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\RuntimeException;
/*
 * @internal This class has been auto-generated by the Symfony Dependency Injection Component.
 */
class getSecurity_Listener_Api_UserProviderService extends Contao_ManagerApi_ApiKernelProdContainer
{
    /*
     * Gets the private 'security.listener.api.user_provider' shared service.
     *
     * @return \Symfony\Component\Security\Http\EventListener\UserProviderListener
     */
    public static function do($container, $lazyLoad = \true)
    {
        return $container->privates['security.listener.api.user_provider'] = new \_ContaoManager\Symfony\Component\Security\Http\EventListener\UserProviderListener($container->privates['Contao\ManagerApi\Security\UserProvider'] ?? $container->load('getUserProviderService'));
    }
}
<?php

namespace _ContaoManager\ContainerLiF9Qbu;

use _ContaoManager\Symfony\Component\DependencyInjection\Argument\RewindableGenerator;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\RuntimeException;
/*
 * @internal This class has been auto-generated by the Symfony Dependency Injection Component.
 */
class getInstallTaskService extends Contao_ManagerApi_ApiKernelProdContainer
{
    /*
     * Gets the private 'Contao\ManagerApi\Task\Packages\InstallTask' shared autowired service.
     *
     * @return \Contao\ManagerApi\Task\Packages\InstallTask
     */
    public static function do($container, $lazyLoad = \true)
    {
        $container->privates['Contao\ManagerApi\Task\Packages\InstallTask'] = $instance = new \_ContaoManager\Contao\ManagerApi\Task\Packages\InstallTask($container->privates['Contao\ManagerApi\Process\ContaoConsole'] ?? $container->load('getContaoConsoleService'), $container->privates['Contao\ManagerApi\Process\ConsoleProcessFactory'] ?? $container->load('getConsoleProcessFactoryService'), $container->privates['Contao\ManagerApi\Composer\CloudResolver'] ?? $container->load('getCloudResolverService'), $container->privates['Contao\ManagerApi\Composer\Environment'] ?? $container->load('getEnvironmentService'), $container->privates['filesystem'] ??= new \_ContaoManager\Symfony\Component\Filesystem\Filesystem(), $container->services['Contao\ManagerApi\I18n\Translator'] ?? $container->load('getTranslatorService'));
        $instance->setLogger($container->privates['monolog.logger.tasks'] ?? $container->load('getMonolog_Logger_TasksService'));
        return $instance;
    }
}
<?php

namespace _ContaoManager\ContainerLiF9Qbu;

use _ContaoManager\Symfony\Component\DependencyInjection\Argument\RewindableGenerator;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\RuntimeException;
/*
 * @internal This class has been auto-generated by the Symfony Dependency Injection Component.
 */
class getContainer_EnvVarProcessorsLocatorService extends Contao_ManagerApi_ApiKernelProdContainer
{
    /*
     * Gets the public 'container.env_var_processors_locator' shared service.
     *
     * @return \Symfony\Component\DependencyInjection\ServiceLocator
     */
    public static function do($container, $lazyLoad = \true)
    {
        return $container->services['container.env_var_processors_locator'] = new \_ContaoManager\Symfony\Component\DependencyInjection\Argument\ServiceLocator($container->getService ??= $container->getService(...), ['base64' => ['privates', 'container.env_var_processor', 'getContainer_EnvVarProcessorService', \true], 'bool' => ['privates', 'container.env_var_processor', 'getContainer_EnvVarProcessorService', \true], 'const' => ['privates', 'container.env_var_processor', 'getContainer_EnvVarProcessorService', \true], 'csv' => ['privates', 'container.env_var_processor', 'getContainer_EnvVarProcessorService', \true], 'default' => ['privates', 'container.env_var_processor', 'getContainer_EnvVarProcessorService', \true], 'defined' => ['privates', 'container.env_var_processor', 'getContainer_EnvVarProcessorService', \true], 'enum' => ['privates', 'container.env_var_processor', 'getContainer_EnvVarProcessorService', \true], 'file' => ['privates', 'container.env_var_processor', 'getContainer_EnvVarProcessorService', \true], 'float' => ['privates', 'container.env_var_processor', 'getContainer_EnvVarProcessorService', \true], 'int' => ['privates', 'container.env_var_processor', 'getContainer_EnvVarProcessorService', \true], 'json' => ['privates', 'container.env_var_processor', 'getContainer_EnvVarProcessorService', \true], 'key' => ['privates', 'container.env_var_processor', 'getContainer_EnvVarProcessorService', \true], 'not' => ['privates', 'container.env_var_processor', 'getContainer_EnvVarProcessorService', \true], 'query_string' => ['privates', 'container.env_var_processor', 'getContainer_EnvVarProcessorService', \true], 'require' => ['privates', 'container.env_var_processor', 'getContainer_EnvVarProcessorService', \true], 'resolve' => ['privates', 'container.env_var_processor', 'getContainer_EnvVarProcessorService', \true], 'shuffle' => ['privates', 'container.env_var_processor', 'getContainer_EnvVarProcessorService', \true], 'string' => ['privates', 'container.env_var_processor', 'getContainer_EnvVarProcessorService', \true], 'trim' => ['privates', 'container.env_var_processor', 'getContainer_EnvVarProcessorService', \true], 'url' => ['privates', 'container.env_var_processor', 'getContainer_EnvVarProcessorService', \true]], ['base64' => '?', 'bool' => '?', 'const' => '?', 'csv' => '?', 'default' => '?', 'defined' => '?', 'enum' => '?', 'file' => '?', 'float' => '?', 'int' => '?', 'json' => '?', 'key' => '?', 'not' => '?', 'query_string' => '?', 'require' => '?', 'resolve' => '?', 'shuffle' => '?', 'string' => '?', 'trim' => '?', 'url' => '?']);
    }
}
<?php

namespace _ContaoManager\ContainerLiF9Qbu;

use _ContaoManager\Symfony\Component\DependencyInjection\Argument\RewindableGenerator;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\RuntimeException;
/*
 * @internal This class has been auto-generated by the Symfony Dependency Injection Component.
 */
class getExceptionListenerService extends Contao_ManagerApi_ApiKernelProdContainer
{
    /*
     * Gets the private 'Contao\ManagerApi\EventListener\ExceptionListener' shared autowired service.
     *
     * @return \Contao\ManagerApi\EventListener\ExceptionListener
     */
    public static function do($container, $lazyLoad = \true)
    {
        return $container->privates['Contao\ManagerApi\EventListener\ExceptionListener'] = new \_ContaoManager\Contao\ManagerApi\EventListener\ExceptionListener($container->privates['monolog.logger'] ?? $container->load('getMonolog_LoggerService'), \false);
    }
}
<?php

namespace _ContaoManager\ContainerLiF9Qbu;

use _ContaoManager\Symfony\Component\DependencyInjection\Argument\RewindableGenerator;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\RuntimeException;
/*
 * @internal This class has been auto-generated by the Symfony Dependency Injection Component.
 */
class getSymlinkCheckService extends Contao_ManagerApi_ApiKernelProdContainer
{
    /*
     * Gets the private 'Contao\ManagerApi\IntegrityCheck\SymlinkCheck' shared autowired service.
     *
     * @return \Contao\ManagerApi\IntegrityCheck\SymlinkCheck
     */
    public static function do($container, $lazyLoad = \true)
    {
        return $container->privates['Contao\ManagerApi\IntegrityCheck\SymlinkCheck'] = new \_ContaoManager\Contao\ManagerApi\IntegrityCheck\SymlinkCheck($container->services['kernel'] ?? $container->get('kernel', 1), $container->privates['filesystem'] ??= new \_ContaoManager\Symfony\Component\Filesystem\Filesystem(), $container->services['Contao\ManagerApi\I18n\Translator'] ?? $container->load('getTranslatorService'));
    }
}
<?php

namespace _ContaoManager\ContainerLiF9Qbu;

use _ContaoManager\Symfony\Component\DependencyInjection\Argument\RewindableGenerator;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\RuntimeException;
/*
 * @internal This class has been auto-generated by the Symfony Dependency Injection Component.
 */
class getRequestService extends Contao_ManagerApi_ApiKernelProdContainer
{
    /*
     * Gets the private 'Contao\ManagerApi\System\Request' shared autowired service.
     *
     * @return \Contao\ManagerApi\System\Request
     */
    public static function do($container, $lazyLoad = \true)
    {
        return $container->privates['Contao\ManagerApi\System\Request'] = new \_ContaoManager\Contao\ManagerApi\System\Request($container->privates['monolog.logger'] ?? $container->load('getMonolog_LoggerService'));
    }
}
<?php

namespace _ContaoManager\ContainerLiF9Qbu;

use _ContaoManager\Symfony\Component\DependencyInjection\Argument\RewindableGenerator;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\RuntimeException;
/*
 * @internal This class has been auto-generated by the Symfony Dependency Injection Component.
 */
class getSessionCheckService extends Contao_ManagerApi_ApiKernelProdContainer
{
    /*
     * Gets the private 'Contao\ManagerApi\IntegrityCheck\SessionCheck' shared autowired service.
     *
     * @return \Contao\ManagerApi\IntegrityCheck\SessionCheck
     */
    public static function do($container, $lazyLoad = \true)
    {
        return $container->privates['Contao\ManagerApi\IntegrityCheck\SessionCheck'] = new \_ContaoManager\Contao\ManagerApi\IntegrityCheck\SessionCheck($container->services['Contao\ManagerApi\I18n\Translator'] ?? $container->load('getTranslatorService'));
    }
}
<?php

namespace _ContaoManager\ContainerLiF9Qbu;

use _ContaoManager\Symfony\Component\DependencyInjection\Argument\RewindableGenerator;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\RuntimeException;
/*
 * @internal This class has been auto-generated by the Symfony Dependency Injection Component.
 */
class getMissingPackagesControllerService extends Contao_ManagerApi_ApiKernelProdContainer
{
    /*
     * Gets the public 'Contao\ManagerApi\Controller\Packages\MissingPackagesController' shared autowired service.
     *
     * @return \Contao\ManagerApi\Controller\Packages\MissingPackagesController
     */
    public static function do($container, $lazyLoad = \true)
    {
        return $container->services['Contao\ManagerApi\Controller\Packages\MissingPackagesController'] = new \_ContaoManager\Contao\ManagerApi\Controller\Packages\MissingPackagesController($container->privates['Contao\ManagerApi\Composer\Environment'] ?? $container->load('getEnvironmentService'));
    }
}
<?php

namespace _ContaoManager\ContainerLiF9Qbu;

use _ContaoManager\Symfony\Component\DependencyInjection\Argument\RewindableGenerator;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\RuntimeException;
/*
 * @internal This class has been auto-generated by the Symfony Dependency Injection Component.
 */
class getConsole_Command_SecretsGenerateKeyService extends Contao_ManagerApi_ApiKernelProdContainer
{
    /*
     * Gets the private 'console.command.secrets_generate_key' shared service.
     *
     * @return \Symfony\Bundle\FrameworkBundle\Command\SecretsGenerateKeysCommand
     */
    public static function do($container, $lazyLoad = \true)
    {
        $container->privates['console.command.secrets_generate_key'] = $instance = new \_ContaoManager\Symfony\Bundle\FrameworkBundle\Command\SecretsGenerateKeysCommand($container->privates['secrets.vault'] ?? $container->load('getSecrets_VaultService'), $container->privates['secrets.local_vault'] ??= new \_ContaoManager\Symfony\Bundle\FrameworkBundle\Secrets\DotenvVault(\dirname(__DIR__, 4) . '/test-dir/.env.prod.local'));
        $instance->setName('secrets:generate-keys');
        $instance->setDescription('Generate new encryption keys');
        return $instance;
    }
}
<?php

namespace _ContaoManager\ContainerLiF9Qbu;

use _ContaoManager\Symfony\Component\DependencyInjection\Argument\RewindableGenerator;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\RuntimeException;
/*
 * @internal This class has been auto-generated by the Symfony Dependency Injection Component.
 */
class getUpdateTaskService extends Contao_ManagerApi_ApiKernelProdContainer
{
    /*
     * Gets the private 'Contao\ManagerApi\Task\Packages\UpdateTask' shared autowired service.
     *
     * @return \Contao\ManagerApi\Task\Packages\UpdateTask
     */
    public static function do($container, $lazyLoad = \true)
    {
        $container->privates['Contao\ManagerApi\Task\Packages\UpdateTask'] = $instance = new \_ContaoManager\Contao\ManagerApi\Task\Packages\UpdateTask($container->privates['Contao\ManagerApi\Process\ContaoConsole'] ?? $container->load('getContaoConsoleService'), $container->privates['Contao\ManagerApi\Process\ConsoleProcessFactory'] ?? $container->load('getConsoleProcessFactoryService'), $container->privates['Contao\ManagerApi\Composer\CloudResolver'] ?? $container->load('getCloudResolverService'), $container->privates['Contao\ManagerApi\Config\UploadsConfig'] ?? $container->load('getUploadsConfigService'), $container->services['kernel'] ?? $container->get('kernel', 1), $container->privates['Contao\ManagerApi\Composer\Environment'] ?? $container->load('getEnvironmentService'), $container->privates['filesystem'] ??= new \_ContaoManager\Symfony\Component\Filesystem\Filesystem(), $container->services['Contao\ManagerApi\I18n\Translator'] ?? $container->load('getTranslatorService'));
        $instance->setLogger($container->privates['monolog.logger.tasks'] ?? $container->load('getMonolog_Logger_TasksService'));
        return $instance;
    }
}
<?php

namespace _ContaoManager\ContainerLiF9Qbu;

use _ContaoManager\Symfony\Component\DependencyInjection\Argument\RewindableGenerator;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\RuntimeException;
/*
 * @internal This class has been auto-generated by the Symfony Dependency Injection Component.
 */
class get_Console_Command_SecretsList_LazyService extends Contao_ManagerApi_ApiKernelProdContainer
{
    /*
     * Gets the private '.console.command.secrets_list.lazy' shared service.
     *
     * @return \Symfony\Component\Console\Command\LazyCommand
     */
    public static function do($container, $lazyLoad = \true)
    {
        return $container->privates['.console.command.secrets_list.lazy'] = new \_ContaoManager\Symfony\Component\Console\Command\LazyCommand('secrets:list', [], 'List all secrets', \false, #[\Closure(name: 'console.command.secrets_list', class: '_ContaoManager\Symfony\Bundle\FrameworkBundle\Command\SecretsListCommand')] fn(): \_ContaoManager\Symfony\Bundle\FrameworkBundle\Command\SecretsListCommand => $container->privates['console.command.secrets_list'] ?? $container->load('getConsole_Command_SecretsListService'));
    }
}
<?php

namespace _ContaoManager\ContainerLiF9Qbu;

use _ContaoManager\Symfony\Component\DependencyInjection\Argument\RewindableGenerator;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\RuntimeException;
/*
 * @internal This class has been auto-generated by the Symfony Dependency Injection Component.
 */
class getComposerConfigService extends Contao_ManagerApi_ApiKernelProdContainer
{
    /*
     * Gets the private 'Contao\ManagerApi\Config\ComposerConfig' shared autowired service.
     *
     * @return \Contao\ManagerApi\Config\ComposerConfig
     */
    public static function do($container, $lazyLoad = \true)
    {
        return $container->privates['Contao\ManagerApi\Config\ComposerConfig'] = new \_ContaoManager\Contao\ManagerApi\Config\ComposerConfig($container->services['kernel'] ?? $container->get('kernel', 1), $container->privates['filesystem'] ??= new \_ContaoManager\Symfony\Component\Filesystem\Filesystem());
    }
}
<?php

namespace _ContaoManager\ContainerLiF9Qbu;

use _ContaoManager\Symfony\Component\DependencyInjection\Argument\RewindableGenerator;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\RuntimeException;
/*
 * @internal This class has been auto-generated by the Symfony Dependency Injection Component.
 */
class getConsole_Command_SecretsEncryptFromLocalService extends Contao_ManagerApi_ApiKernelProdContainer
{
    /*
     * Gets the private 'console.command.secrets_encrypt_from_local' shared service.
     *
     * @return \Symfony\Bundle\FrameworkBundle\Command\SecretsEncryptFromLocalCommand
     */
    public static function do($container, $lazyLoad = \true)
    {
        $container->privates['console.command.secrets_encrypt_from_local'] = $instance = new \_ContaoManager\Symfony\Bundle\FrameworkBundle\Command\SecretsEncryptFromLocalCommand($container->privates['secrets.vault'] ?? $container->load('getSecrets_VaultService'), $container->privates['secrets.local_vault'] ??= new \_ContaoManager\Symfony\Bundle\FrameworkBundle\Secrets\DotenvVault(\dirname(__DIR__, 4) . '/test-dir/.env.prod.local'));
        $instance->setName('secrets:encrypt-from-local');
        $instance->setDescription('Encrypt all local secrets to the vault');
        return $instance;
    }
}
<?php

namespace _ContaoManager\ContainerLiF9Qbu;

use _ContaoManager\Symfony\Component\DependencyInjection\Argument\RewindableGenerator;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\RuntimeException;
/*
 * @internal This class has been auto-generated by the Symfony Dependency Injection Component.
 */
class getSecurity_AccessListenerService extends Contao_ManagerApi_ApiKernelProdContainer
{
    /*
     * Gets the private 'security.access_listener' shared service.
     *
     * @return \Symfony\Component\Security\Http\Firewall\AccessListener
     */
    public static function do($container, $lazyLoad = \true)
    {
        return $container->privates['security.access_listener'] = new \_ContaoManager\Symfony\Component\Security\Http\Firewall\AccessListener($container->services['security.token_storage'] ??= new \_ContaoManager\Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorage(), $container->privates['security.access.decision_manager'] ?? self::getSecurity_Access_DecisionManagerService($container), $container->privates['security.access_map'] ?? $container->load('getSecurity_AccessMapService'), \false);
    }
}
<?php

namespace _ContaoManager\ContainerLiF9Qbu;

use _ContaoManager\Symfony\Component\DependencyInjection\Argument\RewindableGenerator;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\RuntimeException;
/*
 * @internal This class has been auto-generated by the Symfony Dependency Injection Component.
 */
class getConsole_Command_CachePoolPruneService extends Contao_ManagerApi_ApiKernelProdContainer
{
    /*
     * Gets the private 'console.command.cache_pool_prune' shared service.
     *
     * @return \Symfony\Bundle\FrameworkBundle\Command\CachePoolPruneCommand
     */
    public static function do($container, $lazyLoad = \true)
    {
        $container->privates['console.command.cache_pool_prune'] = $instance = new \_ContaoManager\Symfony\Bundle\FrameworkBundle\Command\CachePoolPruneCommand(new RewindableGenerator(function () use ($container) {
            yield 'cache.app' => $container->services['cache.app'] ?? $container->load('getCache_AppService');
        }, 1));
        $instance->setName('cache:pool:prune');
        $instance->setDescription('Prune cache pools');
        return $instance;
    }
}
<?php

namespace _ContaoManager\ContainerLiF9Qbu;

use _ContaoManager\Symfony\Component\DependencyInjection\Argument\RewindableGenerator;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\RuntimeException;
/*
 * @internal This class has been auto-generated by the Symfony Dependency Injection Component.
 */
class get_Security_Command_UserPasswordHash_LazyService extends Contao_ManagerApi_ApiKernelProdContainer
{
    /*
     * Gets the private '.security.command.user_password_hash.lazy' shared service.
     *
     * @return \Symfony\Component\Console\Command\LazyCommand
     */
    public static function do($container, $lazyLoad = \true)
    {
        return $container->privates['.security.command.user_password_hash.lazy'] = new \_ContaoManager\Symfony\Component\Console\Command\LazyCommand('security:hash-password', [], 'Hash a user password', \false, #[\Closure(name: 'security.command.user_password_hash', class: '_ContaoManager\Symfony\Component\PasswordHasher\Command\UserPasswordHashCommand')] fn(): \_ContaoManager\Symfony\Component\PasswordHasher\Command\UserPasswordHashCommand => $container->privates['security.command.user_password_hash'] ?? $container->load('getSecurity_Command_UserPasswordHashService'));
    }
}
<?php

namespace _ContaoManager\ContainerLiF9Qbu;

use _ContaoManager\Symfony\Component\DependencyInjection\Argument\RewindableGenerator;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\RuntimeException;
/*
 * @internal This class has been auto-generated by the Symfony Dependency Injection Component.
 */
class getSecurity_RouteLoader_LogoutService extends Contao_ManagerApi_ApiKernelProdContainer
{
    /*
     * Gets the private 'security.route_loader.logout' shared service.
     *
     * @return \Symfony\Bundle\SecurityBundle\Routing\LogoutRouteLoader
     */
    public static function do($container, $lazyLoad = \true)
    {
        return $container->privates['security.route_loader.logout'] = new \_ContaoManager\Symfony\Bundle\SecurityBundle\Routing\LogoutRouteLoader([], 'security.logout_uris');
    }
}
<?php

namespace _ContaoManager\ContainerLiF9Qbu;

use _ContaoManager\Symfony\Component\DependencyInjection\Argument\RewindableGenerator;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\RuntimeException;
/*
 * @internal This class has been auto-generated by the Symfony Dependency Injection Component.
 */
class get_Console_Command_ConfigDebug_LazyService extends Contao_ManagerApi_ApiKernelProdContainer
{
    /*
     * Gets the private '.console.command.config_debug.lazy' shared service.
     *
     * @return \Symfony\Component\Console\Command\LazyCommand
     */
    public static function do($container, $lazyLoad = \true)
    {
        return $container->privates['.console.command.config_debug.lazy'] = new \_ContaoManager\Symfony\Component\Console\Command\LazyCommand('debug:config', [], 'Dump the current configuration for an extension', \false, #[\Closure(name: 'console.command.config_debug', class: '_ContaoManager\Symfony\Bundle\FrameworkBundle\Command\ConfigDebugCommand')] fn(): \_ContaoManager\Symfony\Bundle\FrameworkBundle\Command\ConfigDebugCommand => $container->privates['console.command.config_debug'] ?? $container->load('getConsole_Command_ConfigDebugService'));
    }
}
<?php

namespace _ContaoManager\ContainerLiF9Qbu;

use _ContaoManager\Symfony\Component\DependencyInjection\Argument\RewindableGenerator;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\RuntimeException;
/*
 * @internal This class has been auto-generated by the Symfony Dependency Injection Component.
 */
class getContaoManager_Security_AuthenticationTrustResolverService extends Contao_ManagerApi_ApiKernelProdContainer
{
    /*
     * Gets the private 'contao_manager.security.authentication_trust_resolver' shared autowired service.
     *
     * @return \Contao\ManagerApi\Security\AuthenticationTrustResolver
     */
    public static function do($container, $lazyLoad = \true)
    {
        return $container->privates['contao_manager.security.authentication_trust_resolver'] = new \_ContaoManager\Contao\ManagerApi\Security\AuthenticationTrustResolver(new \_ContaoManager\Symfony\Component\Security\Core\Authentication\AuthenticationTrustResolver(), $container->privates['Contao\ManagerApi\Config\UserConfig'] ?? self::getUserConfigService($container));
    }
}
<?php

namespace _ContaoManager\ContainerLiF9Qbu;

use _ContaoManager\Symfony\Component\DependencyInjection\Argument\RewindableGenerator;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\RuntimeException;
/*
 * @internal This class has been auto-generated by the Symfony Dependency Injection Component.
 */
class getDatabaseControllerService extends Contao_ManagerApi_ApiKernelProdContainer
{
    /*
     * Gets the public 'Contao\ManagerApi\Controller\Server\DatabaseController' shared autowired service.
     *
     * @return \Contao\ManagerApi\Controller\Server\DatabaseController
     */
    public static function do($container, $lazyLoad = \true)
    {
        return $container->services['Contao\ManagerApi\Controller\Server\DatabaseController'] = new \_ContaoManager\Contao\ManagerApi\Controller\Server\DatabaseController($container->privates['Contao\ManagerApi\Process\ContaoApi'] ?? $container->load('getContaoApiService'), $container->privates['Contao\ManagerApi\Process\ContaoConsole'] ?? $container->load('getContaoConsoleService'));
    }
}
<?php

namespace _ContaoManager\ContainerLiF9Qbu;

use _ContaoManager\Symfony\Component\DependencyInjection\Argument\RewindableGenerator;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\RuntimeException;
/*
 * @internal This class has been auto-generated by the Symfony Dependency Injection Component.
 */
class getConsole_Command_SecretsDecryptToLocalService extends Contao_ManagerApi_ApiKernelProdContainer
{
    /*
     * Gets the private 'console.command.secrets_decrypt_to_local' shared service.
     *
     * @return \Symfony\Bundle\FrameworkBundle\Command\SecretsDecryptToLocalCommand
     */
    public static function do($container, $lazyLoad = \true)
    {
        $container->privates['console.command.secrets_decrypt_to_local'] = $instance = new \_ContaoManager\Symfony\Bundle\FrameworkBundle\Command\SecretsDecryptToLocalCommand($container->privates['secrets.vault'] ?? $container->load('getSecrets_VaultService'), $container->privates['secrets.local_vault'] ??= new \_ContaoManager\Symfony\Bundle\FrameworkBundle\Secrets\DotenvVault(\dirname(__DIR__, 4) . '/test-dir/.env.prod.local'));
        $instance->setName('secrets:decrypt-to-local');
        $instance->setDescription('Decrypt all secrets and stores them in the local vault');
        return $instance;
    }
}
<?php

namespace _ContaoManager\ContainerLiF9Qbu;

use _ContaoManager\Symfony\Component\DependencyInjection\Argument\RewindableGenerator;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\RuntimeException;
/*
 * @internal This class has been auto-generated by the Symfony Dependency Injection Component.
 */
class getLocalPackagesControllerService extends Contao_ManagerApi_ApiKernelProdContainer
{
    /*
     * Gets the public 'Contao\ManagerApi\Controller\Packages\LocalPackagesController' shared autowired service.
     *
     * @return \Contao\ManagerApi\Controller\Packages\LocalPackagesController
     */
    public static function do($container, $lazyLoad = \true)
    {
        return $container->services['Contao\ManagerApi\Controller\Packages\LocalPackagesController'] = new \_ContaoManager\Contao\ManagerApi\Controller\Packages\LocalPackagesController($container->privates['Contao\ManagerApi\Composer\Environment'] ?? $container->load('getEnvironmentService'));
    }
}
<?php

namespace _ContaoManager\ContainerLiF9Qbu;

use _ContaoManager\Symfony\Component\DependencyInjection\Argument\RewindableGenerator;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\RuntimeException;
/*
 * @internal This class has been auto-generated by the Symfony Dependency Injection Component.
 */
class getAboutCommandService extends Contao_ManagerApi_ApiKernelProdContainer
{
    /*
     * Gets the public 'Contao\ManagerApi\Command\AboutCommand' shared autowired service.
     *
     * @return \Contao\ManagerApi\Command\AboutCommand
     */
    public static function do($container, $lazyLoad = \true)
    {
        $container->services['Contao\ManagerApi\Command\AboutCommand'] = $instance = new \_ContaoManager\Contao\ManagerApi\Command\AboutCommand($container->services['kernel'] ?? $container->get('kernel', 1), $container->privates['Contao\ManagerApi\System\ServerInfo'] ?? $container->load('getServerInfoService'));
        $instance->setName('about');
        $instance->setDescription('Displays information about Contao Manager and the current server');
        return $instance;
    }
}
<?php

namespace _ContaoManager\ContainerLiF9Qbu;

use _ContaoManager\Symfony\Component\DependencyInjection\Argument\RewindableGenerator;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\RuntimeException;
/*
 * @internal This class has been auto-generated by the Symfony Dependency Injection Component.
 */
class getTaskAbortCommand_LazyService extends Contao_ManagerApi_ApiKernelProdContainer
{
    /*
     * Gets the private '.Contao\ManagerApi\Command\TaskAbortCommand.lazy' shared service.
     *
     * @return \Symfony\Component\Console\Command\LazyCommand
     */
    public static function do($container, $lazyLoad = \true)
    {
        return $container->privates['.Contao\ManagerApi\Command\TaskAbortCommand.lazy'] = new \_ContaoManager\Symfony\Component\Console\Command\LazyCommand('task:abort', [], 'Aborts the current task and returns the status information.', \false, #[\Closure(name: '_ContaoManager\Contao\ManagerApi\Command\TaskAbortCommand')] fn(): \_ContaoManager\Contao\ManagerApi\Command\TaskAbortCommand => $container->services['Contao\ManagerApi\Command\TaskAbortCommand'] ?? $container->load('getTaskAbortCommandService'));
    }
}
<?php

namespace _ContaoManager\ContainerLiF9Qbu;

use _ContaoManager\Symfony\Component\DependencyInjection\Argument\RewindableGenerator;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\RuntimeException;
/*
 * @internal This class has been auto-generated by the Symfony Dependency Injection Component.
 */
class getSecurity_SecurityTokenValueResolverService extends Contao_ManagerApi_ApiKernelProdContainer
{
    /*
     * Gets the private 'security.security_token_value_resolver' shared service.
     *
     * @return \Symfony\Component\Security\Http\Controller\SecurityTokenValueResolver
     */
    public static function do($container, $lazyLoad = \true)
    {
        return $container->privates['security.security_token_value_resolver'] = new \_ContaoManager\Symfony\Component\Security\Http\Controller\SecurityTokenValueResolver($container->services['security.token_storage'] ??= new \_ContaoManager\Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorage());
    }
}
<?php

namespace _ContaoManager\ContainerLiF9Qbu;

use _ContaoManager\Symfony\Component\DependencyInjection\Argument\RewindableGenerator;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\RuntimeException;
/*
 * @internal This class has been auto-generated by the Symfony Dependency Injection Component.
 */
class getTokenAuthenticatorService extends Contao_ManagerApi_ApiKernelProdContainer
{
    /*
     * Gets the private 'Contao\ManagerApi\Security\TokenAuthenticator' shared autowired service.
     *
     * @return \Contao\ManagerApi\Security\TokenAuthenticator
     */
    public static function do($container, $lazyLoad = \true)
    {
        return $container->privates['Contao\ManagerApi\Security\TokenAuthenticator'] = new \_ContaoManager\Contao\ManagerApi\Security\TokenAuthenticator($container->privates['Contao\ManagerApi\Security\UserProvider'] ?? $container->load('getUserProviderService'), $container->privates['Contao\ManagerApi\Config\UserConfig'] ?? self::getUserConfigService($container));
    }
}
<?php

namespace _ContaoManager\ContainerLiF9Qbu;

use _ContaoManager\Symfony\Component\DependencyInjection\Argument\RewindableGenerator;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\RuntimeException;
/*
 * @internal This class has been auto-generated by the Symfony Dependency Injection Component.
 */
class getConsole_Command_DebugAutowiringService extends Contao_ManagerApi_ApiKernelProdContainer
{
    /*
     * Gets the private 'console.command.debug_autowiring' shared service.
     *
     * @return \Symfony\Bundle\FrameworkBundle\Command\DebugAutowiringCommand
     */
    public static function do($container, $lazyLoad = \true)
    {
        $container->privates['console.command.debug_autowiring'] = $instance = new \_ContaoManager\Symfony\Bundle\FrameworkBundle\Command\DebugAutowiringCommand(NULL, $container->privates['debug.file_link_formatter'] ??= new \_ContaoManager\Symfony\Component\ErrorHandler\ErrorRenderer\FileLinkFormatter(NULL));
        $instance->setName('debug:autowiring');
        $instance->setDescription('List classes/interfaces you can use for autowiring');
        return $instance;
    }
}
<?php

namespace _ContaoManager\ContainerLiF9Qbu;

use _ContaoManager\Symfony\Component\DependencyInjection\Argument\RewindableGenerator;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\RuntimeException;
/*
 * @internal This class has been auto-generated by the Symfony Dependency Injection Component.
 */
class getServerInfoService extends Contao_ManagerApi_ApiKernelProdContainer
{
    /*
     * Gets the private 'Contao\ManagerApi\System\ServerInfo' shared autowired service.
     *
     * @return \Contao\ManagerApi\System\ServerInfo
     */
    public static function do($container, $lazyLoad = \true)
    {
        return $container->privates['Contao\ManagerApi\System\ServerInfo'] = new \_ContaoManager\Contao\ManagerApi\System\ServerInfo(new \_ContaoManager\Contao\ManagerApi\Process\PhpExecutableFinder($container->privates['monolog.logger'] ?? $container->load('getMonolog_LoggerService')), $container->privates['Contao\ManagerApi\Config\ManagerConfig'] ?? $container->load('getManagerConfigService'));
    }
}
<?php

namespace _ContaoManager\ContainerLiF9Qbu;

use _ContaoManager\Symfony\Component\DependencyInjection\Argument\RewindableGenerator;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\RuntimeException;
/*
 * @internal This class has been auto-generated by the Symfony Dependency Injection Component.
 */
class getConsole_Command_RouterMatchService extends Contao_ManagerApi_ApiKernelProdContainer
{
    /*
     * Gets the private 'console.command.router_match' shared service.
     *
     * @return \Symfony\Bundle\FrameworkBundle\Command\RouterMatchCommand
     */
    public static function do($container, $lazyLoad = \true)
    {
        $container->privates['console.command.router_match'] = $instance = new \_ContaoManager\Symfony\Bundle\FrameworkBundle\Command\RouterMatchCommand($container->services['router'] ?? self::getRouterService($container), new RewindableGenerator(fn() => new \EmptyIterator(), 0));
        $instance->setName('router:match');
        $instance->setDescription('Help debug routes by simulating a path info match');
        return $instance;
    }
}
<?php

namespace _ContaoManager\ContainerLiF9Qbu;

use _ContaoManager\Symfony\Component\DependencyInjection\Argument\RewindableGenerator;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\RuntimeException;
/*
 * @internal This class has been auto-generated by the Symfony Dependency Injection Component.
 */
class getIntegrityCheckCommand_LazyService extends Contao_ManagerApi_ApiKernelProdContainer
{
    /*
     * Gets the private '.Contao\ManagerApi\Command\IntegrityCheckCommand.lazy' shared service.
     *
     * @return \Symfony\Component\Console\Command\LazyCommand
     */
    public static function do($container, $lazyLoad = \true)
    {
        return $container->privates['.Contao\ManagerApi\Command\IntegrityCheckCommand.lazy'] = new \_ContaoManager\Symfony\Component\Console\Command\LazyCommand('integrity-check', [], 'Performs integrity check for the Contao Manager', \false, #[\Closure(name: '_ContaoManager\Contao\ManagerApi\Command\IntegrityCheckCommand')] fn(): \_ContaoManager\Contao\ManagerApi\Command\IntegrityCheckCommand => $container->services['Contao\ManagerApi\Command\IntegrityCheckCommand'] ?? $container->load('getIntegrityCheckCommandService'));
    }
}
<?php

namespace _ContaoManager\ContainerLiF9Qbu;

use _ContaoManager\Symfony\Component\DependencyInjection\Argument\RewindableGenerator;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\RuntimeException;
/*
 * @internal This class has been auto-generated by the Symfony Dependency Injection Component.
 */
class get_ServiceLocator_AH5O6SdService extends Contao_ManagerApi_ApiKernelProdContainer
{
    /*
     * Gets the private '.service_locator.aH5O6Sd' shared service.
     *
     * @return \Symfony\Component\DependencyInjection\ServiceLocator
     */
    public static function do($container, $lazyLoad = \true)
    {
        return $container->privates['.service_locator.aH5O6Sd'] = new \_ContaoManager\Symfony\Component\DependencyInjection\Argument\ServiceLocator($container->getService ??= $container->getService(...), ['serverInfo' => ['privates', '_ContaoManager\Contao\ManagerApi\System\ServerInfo', 'getServerInfoService', \true]], ['serverInfo' => '_ContaoManager\Contao\ManagerApi\System\ServerInfo']);
    }
}
<?php

namespace _ContaoManager\ContainerLiF9Qbu;

use _ContaoManager\Symfony\Component\DependencyInjection\Argument\RewindableGenerator;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\RuntimeException;
/*
 * @internal This class has been auto-generated by the Symfony Dependency Injection Component.
 */
class getErrorControllerService extends Contao_ManagerApi_ApiKernelProdContainer
{
    /*
     * Gets the public 'error_controller' shared service.
     *
     * @return \Symfony\Component\HttpKernel\Controller\ErrorController
     */
    public static function do($container, $lazyLoad = \true)
    {
        $a = $container->services['request_stack'] ??= new \_ContaoManager\Symfony\Component\HttpFoundation\RequestStack();
        return $container->services['error_controller'] = new \_ContaoManager\Symfony\Component\HttpKernel\Controller\ErrorController($container->services['http_kernel'] ?? self::getHttpKernelService($container), 'error_controller', new \_ContaoManager\Symfony\Component\ErrorHandler\ErrorRenderer\SerializerErrorRenderer($container->privates['serializer'] ?? self::getSerializerService($container), \_ContaoManager\Symfony\Component\ErrorHandler\ErrorRenderer\SerializerErrorRenderer::getPreferredFormat($a), new \_ContaoManager\Symfony\Component\ErrorHandler\ErrorRenderer\HtmlErrorRenderer(\_ContaoManager\Symfony\Component\ErrorHandler\ErrorRenderer\HtmlErrorRenderer::isDebug($a, \false), 'UTF-8', $container->privates['debug.file_link_formatter'] ??= new \_ContaoManager\Symfony\Component\ErrorHandler\ErrorRenderer\FileLinkFormatter(NULL), \dirname(__DIR__, 4) . '/test-dir', \_ContaoManager\Symfony\Component\ErrorHandler\ErrorRenderer\HtmlErrorRenderer::getAndCleanOutputBuffer($a), $container->privates['monolog.logger'] ?? $container->load('getMonolog_LoggerService')), \_ContaoManager\Symfony\Component\ErrorHandler\ErrorRenderer\HtmlErrorRenderer::isDebug($a, \false)));
    }
}
<?php

namespace _ContaoManager\ContainerLiF9Qbu;

use _ContaoManager\Symfony\Component\DependencyInjection\Argument\RewindableGenerator;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\RuntimeException;
/*
 * @internal This class has been auto-generated by the Symfony Dependency Injection Component.
 */
class get_ServiceLocator_EZsc_DOService extends Contao_ManagerApi_ApiKernelProdContainer
{
    /*
     * Gets the private '.service_locator.EZsc.DO' shared service.
     *
     * @return \Symfony\Component\DependencyInjection\ServiceLocator
     */
    public static function do($container, $lazyLoad = \true)
    {
        return $container->privates['.service_locator.EZsc.DO'] = new \_ContaoManager\Symfony\Component\DependencyInjection\Argument\ServiceLocator($container->getService ??= $container->getService(...), ['updater' => ['privates', '_ContaoManager\Contao\ManagerApi\System\SelfUpdate', 'getSelfUpdateService', \true]], ['updater' => '_ContaoManager\Contao\ManagerApi\System\SelfUpdate']);
    }
}
<?php

namespace _ContaoManager\ContainerLiF9Qbu;

use _ContaoManager\Symfony\Component\DependencyInjection\Argument\RewindableGenerator;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\RuntimeException;
/*
 * @internal This class has been auto-generated by the Symfony Dependency Injection Component.
 */
class get_Console_Command_CacheClear_LazyService extends Contao_ManagerApi_ApiKernelProdContainer
{
    /*
     * Gets the private '.console.command.cache_clear.lazy' shared service.
     *
     * @return \Symfony\Component\Console\Command\LazyCommand
     */
    public static function do($container, $lazyLoad = \true)
    {
        return $container->privates['.console.command.cache_clear.lazy'] = new \_ContaoManager\Symfony\Component\Console\Command\LazyCommand('cache:clear', [], 'Clear the cache', \false, #[\Closure(name: 'console.command.cache_clear', class: '_ContaoManager\Symfony\Bundle\FrameworkBundle\Command\CacheClearCommand')] fn(): \_ContaoManager\Symfony\Bundle\FrameworkBundle\Command\CacheClearCommand => $container->privates['console.command.cache_clear'] ?? $container->load('getConsole_Command_CacheClearService'));
    }
}
<?php

namespace _ContaoManager\ContainerLiF9Qbu;

use _ContaoManager\Symfony\Component\DependencyInjection\Argument\RewindableGenerator;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\RuntimeException;
/*
 * @internal This class has been auto-generated by the Symfony Dependency Injection Component.
 */
class getArgumentResolver_RequestService extends Contao_ManagerApi_ApiKernelProdContainer
{
    /*
     * Gets the private 'argument_resolver.request' shared service.
     *
     * @return \Symfony\Component\HttpKernel\Controller\ArgumentResolver\RequestValueResolver
     */
    public static function do($container, $lazyLoad = \true)
    {
        return $container->privates['argument_resolver.request'] = new \_ContaoManager\Symfony\Component\HttpKernel\Controller\ArgumentResolver\RequestValueResolver();
    }
}
<?php

namespace _ContaoManager\ContainerLiF9Qbu;

class RequestPayloadValueResolverGhost8d82153 extends \_ContaoManager\Symfony\Component\HttpKernel\Controller\ArgumentResolver\RequestPayloadValueResolver implements \_ContaoManager\Symfony\Component\VarExporter\LazyObjectInterface
{
    use \_ContaoManager\Symfony\Component\VarExporter\LazyGhostTrait;
    private const LAZY_OBJECT_PROPERTY_SCOPES = ["\x00" . parent::class . "\x00" . 'serializer' => [parent::class, 'serializer', null, 530], "\x00" . parent::class . "\x00" . 'translator' => [parent::class, 'translator', null, 530], "\x00" . parent::class . "\x00" . 'validator' => [parent::class, 'validator', null, 530], 'serializer' => [parent::class, 'serializer', null, 530], 'translator' => [parent::class, 'translator', null, 530], 'validator' => [parent::class, 'validator', null, 530]];
}
class_exists(\_ContaoManager\Symfony\Component\VarExporter\Internal\Hydrator::class);
class_exists(\_ContaoManager\Symfony\Component\VarExporter\Internal\LazyObjectRegistry::class);
class_exists(\_ContaoManager\Symfony\Component\VarExporter\Internal\LazyObjectState::class);
if (!\class_exists('_ContaoManager\RequestPayloadValueResolverGhost8d82153', \false)) {
    \class_alias(__NAMESPACE__ . '\RequestPayloadValueResolverGhost8d82153', '_ContaoManager\RequestPayloadValueResolverGhost8d82153', \false);
}
<?php

namespace _ContaoManager\ContainerLiF9Qbu;

use _ContaoManager\Symfony\Component\DependencyInjection\Argument\RewindableGenerator;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\RuntimeException;
/*
 * @internal This class has been auto-generated by the Symfony Dependency Injection Component.
 */
class getConsole_Command_AboutService extends Contao_ManagerApi_ApiKernelProdContainer
{
    /*
     * Gets the private 'console.command.about' shared service.
     *
     * @return \Symfony\Bundle\FrameworkBundle\Command\AboutCommand
     */
    public static function do($container, $lazyLoad = \true)
    {
        $container->privates['console.command.about'] = $instance = new \_ContaoManager\Symfony\Bundle\FrameworkBundle\Command\AboutCommand();
        $instance->setName('about');
        $instance->setDescription('Display information about the current project');
        return $instance;
    }
}
<?php

namespace _ContaoManager\ContainerLiF9Qbu;

use _ContaoManager\Symfony\Component\DependencyInjection\Argument\RewindableGenerator;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\RuntimeException;
/*
 * @internal This class has been auto-generated by the Symfony Dependency Injection Component.
 */
class getDumpAutoloadTaskService extends Contao_ManagerApi_ApiKernelProdContainer
{
    /*
     * Gets the private 'Contao\ManagerApi\Task\Composer\DumpAutoloadTask' shared autowired service.
     *
     * @return \Contao\ManagerApi\Task\Composer\DumpAutoloadTask
     */
    public static function do($container, $lazyLoad = \true)
    {
        $container->privates['Contao\ManagerApi\Task\Composer\DumpAutoloadTask'] = $instance = new \_ContaoManager\Contao\ManagerApi\Task\Composer\DumpAutoloadTask($container->privates['Contao\ManagerApi\Process\ConsoleProcessFactory'] ?? $container->load('getConsoleProcessFactoryService'), $container->services['Contao\ManagerApi\I18n\Translator'] ?? $container->load('getTranslatorService'));
        $instance->setLogger($container->privates['monolog.logger.tasks'] ?? $container->load('getMonolog_Logger_TasksService'));
        return $instance;
    }
}
<?php

namespace _ContaoManager\ContainerLiF9Qbu;

use _ContaoManager\Symfony\Component\DependencyInjection\Argument\RewindableGenerator;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\RuntimeException;
/*
 * @internal This class has been auto-generated by the Symfony Dependency Injection Component.
 */
class get_Console_Command_ContainerLint_LazyService extends Contao_ManagerApi_ApiKernelProdContainer
{
    /*
     * Gets the private '.console.command.container_lint.lazy' shared service.
     *
     * @return \Symfony\Component\Console\Command\LazyCommand
     */
    public static function do($container, $lazyLoad = \true)
    {
        return $container->privates['.console.command.container_lint.lazy'] = new \_ContaoManager\Symfony\Component\Console\Command\LazyCommand('lint:container', [], 'Ensure that arguments injected into services match type declarations', \false, #[\Closure(name: 'console.command.container_lint', class: '_ContaoManager\Symfony\Bundle\FrameworkBundle\Command\ContainerLintCommand')] fn(): \_ContaoManager\Symfony\Bundle\FrameworkBundle\Command\ContainerLintCommand => $container->privates['console.command.container_lint'] ?? $container->load('getConsole_Command_ContainerLintService'));
    }
}
<?php

namespace _ContaoManager\ContainerLiF9Qbu;

use _ContaoManager\Symfony\Component\DependencyInjection\Argument\RewindableGenerator;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\RuntimeException;
/*
 * @internal This class has been auto-generated by the Symfony Dependency Injection Component.
 */
class getConsole_Command_ConfigDebugService extends Contao_ManagerApi_ApiKernelProdContainer
{
    /*
     * Gets the private 'console.command.config_debug' shared service.
     *
     * @return \Symfony\Bundle\FrameworkBundle\Command\ConfigDebugCommand
     */
    public static function do($container, $lazyLoad = \true)
    {
        $container->privates['console.command.config_debug'] = $instance = new \_ContaoManager\Symfony\Bundle\FrameworkBundle\Command\ConfigDebugCommand($container->services['container.env_var_processors_locator'] ?? $container->load('getContainer_EnvVarProcessorsLocatorService'));
        $instance->setName('debug:config');
        $instance->setDescription('Dump the current configuration for an extension');
        return $instance;
    }
}
<?php return array (
  0 => 'Symfony\\Bundle\\FrameworkBundle\\Controller\\AbstractController',
  1 => '_ContaoManager\\Contao\\ManagerApi\\Controller\\Config\\AbstractConfigController',
  2 => '_ContaoManager\\Contao\\ManagerApi\\Controller\\Config\\AuthController',
  3 => '_ContaoManager\\Contao\\ManagerApi\\Controller\\Config\\ComposerController',
  4 => '_ContaoManager\\Contao\\ManagerApi\\Controller\\Config\\ManagerController',
  5 => '_ContaoManager\\Contao\\ManagerApi\\Controller\\ConstraintController',
  6 => '_ContaoManager\\Contao\\ManagerApi\\Controller\\Contao\\AccessKeyController',
  7 => '_ContaoManager\\Contao\\ManagerApi\\Controller\\Contao\\BackupController',
  8 => '_ContaoManager\\Contao\\ManagerApi\\Controller\\Contao\\DatabaseMigrationController',
  9 => '_ContaoManager\\Contao\\ManagerApi\\Controller\\Contao\\InstallToolLockController',
  10 => '_ContaoManager\\Contao\\ManagerApi\\Controller\\Contao\\JwtCookieController',
  11 => '_ContaoManager\\Contao\\ManagerApi\\Controller\\Contao\\MaintenanceModeController',
  12 => '_ContaoManager\\Contao\\ManagerApi\\Controller\\FileController',
  13 => '_ContaoManager\\Contao\\ManagerApi\\Controller\\LogController',
  14 => '_ContaoManager\\Contao\\ManagerApi\\Controller\\Packages\\CloudController',
  15 => '_ContaoManager\\Contao\\ManagerApi\\Controller\\Packages\\LocalPackagesController',
  16 => '_ContaoManager\\Contao\\ManagerApi\\Controller\\Packages\\MissingPackagesController',
  17 => '_ContaoManager\\Contao\\ManagerApi\\Controller\\Packages\\RootPackageController',
  18 => '_ContaoManager\\Contao\\ManagerApi\\Controller\\Packages\\UploadPackagesController',
  19 => '_ContaoManager\\Contao\\ManagerApi\\Controller\\Server\\AdminUserController',
  20 => '_ContaoManager\\Contao\\ManagerApi\\Controller\\Server\\ComposerController',
  21 => '_ContaoManager\\Contao\\ManagerApi\\Controller\\Server\\ConfigController',
  22 => '_ContaoManager\\Contao\\ManagerApi\\Controller\\Server\\ContaoController',
  23 => '_ContaoManager\\Contao\\ManagerApi\\Controller\\Server\\DatabaseController',
  24 => '_ContaoManager\\Contao\\ManagerApi\\Controller\\Server\\OpcacheController',
  25 => '_ContaoManager\\Contao\\ManagerApi\\Controller\\Server\\PhpCliController',
  26 => '_ContaoManager\\Contao\\ManagerApi\\Controller\\Server\\PhpWebController',
  27 => '_ContaoManager\\Contao\\ManagerApi\\Controller\\Server\\PhpinfoController',
  28 => '_ContaoManager\\Contao\\ManagerApi\\Controller\\Server\\SelfUpdateController',
  29 => '_ContaoManager\\Contao\\ManagerApi\\Controller\\SessionController',
  30 => '_ContaoManager\\Contao\\ManagerApi\\Controller\\TaskController',
  31 => '_ContaoManager\\Contao\\ManagerApi\\Controller\\UserController',
  32 => 'JsonSchema\\Entity\\ErrorBag',
  33 => 'JsonSchema\\Entity\\ErrorBagProxy',
  34 => 'JsonSchema\\Entity\\JsonPointer',
  36 => 'Symfony\\Bundle\\FrameworkBundle\\Controller\\ControllerResolver',
  37 => 'Symfony\\Bundle\\FrameworkBundle\\Controller\\RedirectController',
  38 => 'Symfony\\Bundle\\FrameworkBundle\\Controller\\TemplateController',
  39 => 'Symfony\\Component\\HttpKernel\\Controller\\ArgumentResolver',
  40 => 'Symfony\\Component\\HttpKernel\\Controller\\ArgumentResolverInterface',
  41 => 'Symfony\\Component\\HttpKernel\\Controller\\ArgumentResolver\\BackedEnumValueResolver',
  42 => 'Symfony\\Component\\HttpKernel\\Controller\\ArgumentResolver\\DateTimeValueResolver',
  43 => 'Symfony\\Component\\HttpKernel\\Controller\\ArgumentResolver\\DefaultValueResolver',
  44 => 'Symfony\\Component\\HttpKernel\\Controller\\ArgumentResolver\\NotTaggedControllerValueResolver',
  45 => 'Symfony\\Component\\HttpKernel\\Controller\\ArgumentResolver\\QueryParameterValueResolver',
  46 => 'Symfony\\Component\\HttpKernel\\Controller\\ArgumentResolver\\RequestAttributeValueResolver',
  47 => 'Symfony\\Component\\HttpKernel\\Controller\\ArgumentResolver\\RequestPayloadValueResolver',
  48 => 'Symfony\\Component\\HttpKernel\\Controller\\ArgumentResolver\\RequestValueResolver',
  49 => 'Symfony\\Component\\HttpKernel\\Controller\\ArgumentResolver\\ServiceValueResolver',
  50 => 'Symfony\\Component\\HttpKernel\\Controller\\ArgumentResolver\\SessionValueResolver',
  51 => 'Symfony\\Component\\HttpKernel\\Controller\\ArgumentResolver\\TraceableValueResolver',
  52 => 'Symfony\\Component\\HttpKernel\\Controller\\ArgumentResolver\\UidValueResolver',
  53 => 'Symfony\\Component\\HttpKernel\\Controller\\ArgumentResolver\\VariadicValueResolver',
  54 => 'Symfony\\Component\\HttpKernel\\Controller\\ArgumentValueResolverInterface',
  55 => 'Symfony\\Component\\HttpKernel\\Controller\\ContainerControllerResolver',
  56 => 'Symfony\\Component\\HttpKernel\\Controller\\ControllerReference',
  57 => 'Symfony\\Component\\HttpKernel\\Controller\\ControllerResolver',
  58 => 'Symfony\\Component\\HttpKernel\\Controller\\ControllerResolverInterface',
  59 => 'Symfony\\Component\\HttpKernel\\Controller\\ErrorController',
  60 => 'Symfony\\Component\\HttpKernel\\Controller\\TraceableArgumentResolver',
  61 => 'Symfony\\Component\\HttpKernel\\Controller\\TraceableControllerResolver',
  62 => 'Symfony\\Component\\HttpKernel\\Controller\\ValueResolverInterface',
  63 => 'Symfony\\Component\\Security\\Http\\Controller\\SecurityTokenValueResolver',
  64 => 'Symfony\\Component\\Security\\Http\\Controller\\UserValueResolver',
);services:
    _defaults:
        autoconfigure: true
        autowire: true
        public: false
        bind:
            $debug: '%kernel.debug%'

    kernel:
        synthetic: true
        public: true
        tags:
            - routing.route_loader

    _ContaoManager\Contao\ManagerApi\:
        resource: '../../*'
        exclude: '../../{Command,Controller,Resources,Tests}'

    _ContaoManager\Contao\ManagerApi\Command\:
        resource: '../../Command'
        public: true

    _ContaoManager\Contao\ManagerApi\Controller\:
        resource: '../../Controller'
        public: true
        tags: ['controller.service_arguments']


    ##############################
    #  Additional configuration  #
    ##############################

    _ContaoManager\Contao\ManagerApi\ApiKernel: '@kernel'

    # Service is public for ApiKernel::getTranslator()
    _ContaoManager\Contao\ManagerApi\I18n\Translator:
        public: true

    _ContaoManager\Contao\ManagerApi\Task\TaskManager:
        arguments:
            - !tagged app.task

    contao_manager.webauthn.serializer_factory:
        class: _ContaoManager\Webauthn\Denormalizer\WebauthnSerializerFactory
        arguments:
            - !service { class: _ContaoManager\Webauthn\AttestationStatement\AttestationStatementSupportManager }

    contao_manager.webauthn.serializer:
        class:  _ContaoManager\Symfony\Component\Serializer\SerializerInterface
        factory: ['@contao_manager.webauthn.serializer_factory', 'create']

    contao_manager.webauthn.ceremony_step_manager_factory:
        class: _ContaoManager\Webauthn\CeremonyStep\CeremonyStepManagerFactory

    contao_manager.webauthn.creation_ceremony:
        class: _ContaoManager\Webauthn\CeremonyStep\CeremonyStepManager
        factory: ['@contao_manager.webauthn.ceremony_step_manager_factory', 'creationCeremony']

    contao_manager.webauthn.request_ceremony:
        class: _ContaoManager\Webauthn\CeremonyStep\CeremonyStepManager
        factory: ['@contao_manager.webauthn.ceremony_step_manager_factory', 'requestCeremony']

    contao_manager.webauthn.authenticator_attestation_response_validator:
        class: _ContaoManager\Webauthn\AuthenticatorAttestationResponseValidator
        arguments:
            $ceremonyStepManager: '@contao_manager.webauthn.creation_ceremony'
        calls:
            - setLogger: ['@logger']

    contao_manager.webauthn.authenticator_assertion_response_validator:
        class: _ContaoManager\Webauthn\AuthenticatorAssertionResponseValidator
        arguments:
            $ceremonyStepManager: '@contao_manager.webauthn.request_ceremony'
        calls:
            - setLogger: ['@logger']

    # Override the AuthenticationTrustResolver to deny IS_AUTHENTICATED_FULLY if token has limited permissions
    contao_manager.security.authentication_trust_resolver:
        class: _ContaoManager\Contao\ManagerApi\Security\AuthenticationTrustResolver
        decorates: 'security.authentication.trust_resolver'
        arguments: ['@.inner']
imports:
    - { resource: config.yaml }

monolog:
    handlers:
        main:
            type: rotating_file
            path: "%kernel.logs_dir%/api.log"
            level: INFO
            channels: ['!event', '!security', '!request']
            max_files: 10

services:
    contao_manager.webauthn.ceremony_step_manager_factory:
        class: _ContaoManager\Webauthn\CeremonyStep\CeremonyStepManagerFactory
        calls:
            - setSecuredRelyingPartyId: [ [ 'localhost' ] ]
imports:
    - { resource: config.yaml }

monolog:
    handlers:
        main:
            type: fingers_crossed
            action_level: error
            handler: file

        file:
            type: error_log
imports:
    - { resource: services.yaml }

# The secret is only required to sign fragment URLs which is not used
framework:
    secret: ''
    default_locale: en
    router:
        resource: kernel::loadRoutes
        type: service

security:
    password_hashers:
        _ContaoManager\Symfony\Component\Security\Core\User\PasswordAuthenticatedUserInterface: 'auto'

    providers:
        contao_manager_user_provider:
            id: _ContaoManager\Contao\ManagerApi\Security\UserProvider

    firewalls:
        api:
            stateless: true
            provider: contao_manager_user_provider
            custom_authenticators:
                - _ContaoManager\Contao\ManagerApi\Security\LoginAuthenticator
                - _ContaoManager\Contao\ManagerApi\Security\WebauthnAuthenticator
                - _ContaoManager\Contao\ManagerApi\Security\PasswordlessAuthenticator
                - _ContaoManager\Contao\ManagerApi\Security\JwtAuthenticator
                - _ContaoManager\Contao\ManagerApi\Security\TokenAuthenticator

    role_hierarchy:
        ROLE_ADMIN: ROLE_INSTALL
        ROLE_INSTALL: ROLE_UPDATE
        ROLE_UPDATE: ROLE_READ
        ROLE_READ: ROLE_USER

    access_control:
        - { path: ^/api/session(/options)?$, roles: PUBLIC_ACCESS }
        - { path: ^/api, roles: ROLE_USER }
cs:
    integrity:
        allow_url_fopen:
            title: 'Služba PHP "allow_url_fopen" není na tomto serveru spuštěna.'
        process:
            title: 'Funkce PHP  "proc_*" není k dispozici na tomto serveru.'
            detail: 'Funkce "proc_open" a "proc_close" jsou nezbytné pro spouštění příkazů na pozadí. Dotázejte se Vašeho poskytovatele, proč není daná k dispozici. Správce Contaa nebude moct bez toho fungovat správně.'
        intl:
            title: 'Rozšíření PHP Intl není na tomto serveru spuštěno.'
            detail: 'Contao 4 vyžaduje rozšíření PHP Intl pro mezinárodní záležitosti.'
        openssl:
            title: 'Rozšíření PHP OpenSSL není na tomto serveru spuštěno.'
            detail: 'Správce Contaa vyžaduje rozšíření OpenSSL, aby mohl stahovat soubory přes zabezpečené připojení (https).'
        dom:
            title: 'Rozšíření PHP DOM není na tomto serveru spuštěno.'
            detail: 'Contao 4 vyžaduje rozšíření PHP DOM pro zpracování dokumentů XML.'
        xmlreader:
            title: 'Rozšíření PHP XMLReader není na tomto serveru spuštěno.'
            detail: 'Contao 4 vyžaduje rozšíření PHP XMLReader pro zpracování dokumentů XML.'
        graphics_lib:
            title: 'Není dostupná žádná knihovna PHP na zpracování obrázků.'
            detail: 'Contao 4 vyžaduje pro zpracování obrázku jedno z následujících rozšíření: GD, Imagick nebo Gmagick.'
        symlink:
            title: 'Metoda pro vytvoření symlinků buď není dostupná nebo nefunguje správně.'
        session:
            title: 'Sezení PHP nelze zahájit.'
        memory_limit:
            title: 'Nedostatečné množství paměti pro PHP.'
            detail: 'Vaše nastavení PHP dovoluje (na příkazovém řádku) jen omezené akce kvůli omezení paměti {limit}. Ta není dostatečná pro chod Composeru a nešlo automaticky zvýšit paměť. Kontaktujte prosím Vaše poskytovatele služeb.'
        systempdir:
            title: 'Nelze zapisovat do dočasné složky systému.'
            detail: 'Nejspíš jde o problém s Vaším nastavením služeb. Ujistěte se, že open_basedir dovoluje přístup k dočasné složce nebo zda je sys_temp_dir správně nastavená.'
        zip:
            title: 'Rozšíření zip a příkazy unzip/7z chybějí.'

    boot:
        composer:
            invalid: 'Schéma ověření composer.json: {exception}'

    config:
        php_cli:
            not_found: 'Tato cesta neobsahuje platné binární PHP.'
            incompatible: 'Tato verze je verze PHP {cli}, ale Váš server je ve verzi {web}.'
            error: 'Chyba při validaci binární PHP.'
        cloud:
            platform: 'Platforma nemusí být nastavená v composer.json.'
            cache: 'Položky meziúložiště nemusí být nastavené v composer.json.'

    task:
        setup_packages:
            title: 'Instalování aplikací Contaa'
        install_packages:
            title: 'Nainstalovat věci závislé na Composerovi'
        update_packages:
            title: 'Aktualizují se balíčky'
        dump_autoload:
            title: 'Vyčistit Autoloadera Composeru'
        clear_cache:
            title: 'Vyprazdňování meziúložiště Composeru'
        rebuild_cache:
            title: 'Přetváří se meziúložiště Contaa.'
        self_update:
            title: 'Spustit samoaktualizaci Správce Contaa'
        backup_create:
            title: 'Vytváření uložení databáze'
        backup_restore:
            title: 'Obnovení uložené databáze'

    taskoperation:
        self-update:
            detail: 'Aktualizování {old} na {new}'
            success: 'Aktualizovat na {new}'
        install-uploads:
            summary: 'Instalují se nahrané soubory'
            console: 'Nainstalovaný artefakt pro {package} (verze {version}) [do balíčků/{name}]'
        remove-uploads:
            summary: 'Smazat nahrané soubory'
        remove-artifacts:
            summary: 'Mazání nahraných balíčků'
        composer-install:
            retry: 'Nový pokus {current}/{max}'
            nothing: 'Neexistuje nic k nainstalování či aktualizování'
            result: 'nainstalováno: {installs}, zaktualizováno: {updates}, smazáno: {removals}'
        dump-autoload:
            result: 'Vygenerované optiomalizované autoload soubory obsahují počet tříd: {count}'
        cloud:
            queued: 'Proces začne za {seconds} s. (současný {jobs} proces - počet uživatelů: {workers})'
            processing: 'Doba aktivity: {seconds} s'
            error: 'Vyřešení závislostí nevyšlo'
            finished: 'Dokončení:  {seconds} s. Využití paměti: {memory} (vrchol: {peak}), doba: {time}.'

    upload:
        error:
            file: 'Tento soubor není platný nebo neobsahuje žádnou composer.json.'
            json: 'Soubor composer.json neobsahuje žádná platná data JSON,'
            schema: 'Ověření schématu composer.json selhalo,'
            partial: 'Nahrání souborů nebylo dokončeno.'

    error:
        writable:
            root: 'Správce Contaa nemůže zapisovat do kořenového adresáře na "{path}".'
            directory: 'Správce Contaa nemůže vytvořit adresář "{path}".'
            config-file: 'Správce Contaa nemůže zapisovat do konfiguračního souboru v "{path}".'
            detail: 'Vypadá to, že Váš webový server není správně nastavený. Pokud chcete nainstalovat Contao, nastavte prosím kořenový dokument na Vašem webovém serveru. Jinak se jistěte, že jsou přístupová práva nastavená správně. Pokud si nejste jistí, obraťte se na správce webových služeb.'
br:
    integrity:
        allow_url_fopen:
            title: 'An arventennoù PHP "allow_url_fopen" n''eo ket gweredekaet war ar servijer.'
        process:
            title: ''
            detail: ''
        intl:
            title: 'N''eo ket hegerz an astenn PHP Intl.'
            detail: 'Contao 4 a c''houlenn an astenn PHP Intl evit ma vo etrebroadel.'
        openssl:
            title: 'N''eo ket hegerz an astenn PHP OpenSSL.'
            detail: 'Manager contao a c''houl an amzer openssl evit pellgargañ restroù dre ur gevreadenn dirinegañ (https).'
        dom:
            title: ''
            detail: ''
        xmlreader:
            title: ''
            detail: ''
        graphics_lib:
            title: ''
            detail: ''
        symlink:
            title: ''
        session:
            title: 'N''hall ket bezañ kroget an dalc''h PHP.'
        memory_limit:
            title: ''
            detail: ''
        systempdir:
            title: ''
            detail: ''

    boot:
        composer:
            invalid: ''

    config:
        php_cli:
            not_found: ''
            incompatible: ''
        cloud:
            platform: ''
            cache: ''

    task:
        setup_packages:
            title: ''
        install_packages:
            title: ''
        update_packages:
            title: 'Oc''h hizivaat ar pakadoù'
        dump_autoload:
            title: ''
        clear_cache:
            title: ''
        rebuild_cache:
            title: 'Oc''h adsevel krubuilh Contao'
        self_update:
            title: ''

    taskoperation:
        self-update:
            detail: ''
            success: ''
        install-uploads:
            summary: ''
            console: ''
        remove-uploads:
            summary: ''
        composer-install:
            retry: ''
            nothing: ''
            result: ''
        dump-autoload:
            result: ''
        cloud:
            queued: ''
            processing: ''
            error: ''
            finished: ''

    upload:
        error:
            file: ''
            json: ''
            schema: ''
            partial: ''

    error:
        writable:
            root: ''
            directory: ''
            config-file: ''
            detail: ''
es:
    integrity:
        allow_url_fopen:
            title: 'La configuración de PHP "allow_url_fopen" no está habilitada en el servidor.'
        process:
            title: 'Las funciones PHP "proc_ *" no están disponibles en el servidor. '
            detail: 'Las funciones "proc_open", "proc_close", "proc_get_status" y "proc_terminate" son necesarias para ejecutar tareas de línea de comandos en segundo plano. Consulte con su proveedor de alojamiento por qué este método no está disponible; el Contao Manager no se ejecutará correctamente sin él. '
        intl:
            title: 'La extensión PHP Intl no está disponible.'
            detail: 'Contao 4 requiere la extensión PHP Intl para fines de internacionalización.'
        openssl:
            title: 'La extensión PHP OpenSSL no está disponible.'
            detail: 'El Contao Manager requiere la extensión OpenSSL para descargar archivos a través de una conexión cifrada (https).'
        dom:
            title: 'La extensión PHP DOM no está disponible. '
            detail: 'Contao 4 requiere la extensión DOM de PHP para analizar documentos XML.'
        xmlreader:
            title: 'La extensión PHP XMLReader no está disponible.'
            detail: 'Contao 4 requiere la extensión XMLReader de PHP para analizar documentos XML.'
        graphics_lib:
            title: 'No hay biblioteca de procesamiento de imágenes PHP disponible.'
            detail: 'Contao 4 requiere la extensión GD, Imagick o Gmagick para procesar imágenes.'
        symlink:
            title: 'El método de enlace simbólico PHP no está disponible o no funciona correctamente.'
        session:
            title: 'La sesión de PHP no se pudo iniciar.'
        memory_limit:
            title: 'Límite insuficiente de memoria de PHP.'
            detail: 'Su configuración PHP solo permite {limit} memoria (en la línea de comando). Esto no es suficiente para ejecutar Composer y no fue posible aumentar este límite automáticamente. Por favor, póngase en contacto con su proveedor de hosting para obtener asistencia.'
        systempdir:
            title: 'No se puede escribir en el directorio temporal del sistema.'
            detail: 'Probablemente esto sea un problema con su configuración de alojamiento. Asegúrese de que open_basedir permita el acceso al directorio temporal o que el sys_temp_dir esté configurado correctamente.'
        zip:
            title: 'Faltan la extensión zip y los comandos unzip/7z.'

    boot:
        composer:
            invalid: 'validación del esquema composer.json: {exception}'

    config:
        php_cli:
            not_found: 'Esta ruta no contiene un binario PHP válido.'
            incompatible: 'Este binario es una versión de PHP {cli}, pero su servidor web es la versión {web}.'
            error: 'Error al validar el binario PHP.'
        cloud:
            platform: 'La plataforma no debe configurarse en composer.json.'
            cache: 'Las propiedades de caché no deben configurarse en composer.json.'

    task:
        setup_packages:
            title: 'Instalación de la aplicación Contao'
        install_packages:
            title: 'Instalando dependencias del Composer'
        update_packages:
            title: 'Actualizando paquetes'
        dump_autoload:
            title: 'Autocargador de clases de dumping Composer'
        clear_cache:
            title: 'Limpiar el caché del Composer'
        rebuild_cache:
            title: 'Reconstruyendo de caché de Contao'
        self_update:
            title: 'Autoactualización de Contao Manager '
        backup_create:
            title: 'Creando una copia de seguridad de la base de datos'
        backup_restore:
            title: 'Restaurar la copia de seguridad de la base de datos'

    taskoperation:
        self-update:
            detail: 'Actualización de {old} a {new}'
            success: 'Actualizado a {new}'
        install-uploads:
            summary: 'Instalación de cargas'
            console: 'Artefacto instalado para {package} (versión {version}) [a paquetes / {name}]'
        remove-uploads:
            summary: 'Eliminando cargas'
        remove-artifacts:
            summary: 'Eliminar paquetes cargados'
        composer-install:
            retry: 'volviendo a intentar {current}/{max}'
            nothing: 'Nada que instalar o actualizar'
            result: '{installs} instalado, {updates} actualizado, {removals} eliminado'
        dump-autoload:
            result: 'Archivos de carga automática optimizados generados que contienen {count} clases'
        cloud:
            queued: 'En cola, comenzando en aprox. {seconds} segundos (actualmente {jobs} trabajos en {workers} trabajadores)'
            processing: 'Activo durante {seconds} segundos.'
            error: 'No se pudieron resolver las dependencias'
            finished: 'Completado en {seconds} segundos. Uso de memoria: {memory} (pico: {peak}), tiempo: {time}.'

    upload:
        error:
            file: 'El archivo no es válido o no contiene un composer.json.'
            json: 'El composer.json no contiene datos JSON válidos.'
            schema: 'La validación del esquema composer.json ha fallado.'
            partial: 'La carga del archivo no se completó.'

    error:
        writable:
            root: 'El Contao Manager no pudo escribir en el directorio raíz en "{path}". '
            directory: 'Contao Manager no pudo crear el directorio "{path}".'
            config-file: 'Contao Manager no pudo escribir un archivo de configuración en "{file}".'
            detail: 'Parece que su servidor no está configurado correctamente. Si está a punto de instalar Contao, configure el DocumentRoot de su servidor web. De lo contrario, asegúrese de que los permisos de acceso a archivos sean correctos. Si no está seguro de cómo solucionar este problema, comuníquese con su proveedor de alojamiento para obtener asistencia.'
pt:
    integrity:
        allow_url_fopen:
            title: 'A função PHP "allow_url_fopen" não está ativada no servidor. '
        process:
            title: 'As funções "proc_*" do PHP não estão disponíveis no servidor.'
            detail: 'As funções "proc_open", "proc_close", "proc_get_status" e "proc_terminate" são necessárias para executar tarefas de linha de comando em segundo plano. Verifique com o seu fornecedor de alojamento porque é que este método não está disponível; o Gestor de Contacto não funcionará correctamente sem ele.'
        intl:
            title: 'A extensão PHP Intl não está disponível.'
            detail: 'O Contao 4 necessita da extensão PHP Intl para propósitos de internacionalização.'
        openssl:
            title: 'A extensão PHP OpenSSL não se encontra disponível.'
            detail: 'O Contao Manager necessita da extensão OpenSSL para receber ficheiros através de uma ligação encriptada (https).'
        dom:
            title: 'A extensão PHP DOM não se encontra disponivel.'
            detail: 'O contao 4 necessita da extensão PHP DOM para reconhecer documentos XML.'
        xmlreader:
            title: 'A extensão PHP XMLReader não está disponível.'
            detail: 'O contao 4 necessita da extensão PHP XMLReader para reconhecer documentos XML.'
        graphics_lib:
            title: 'Nenhuma biblioteca de processamento de imagens PHP está disponível. '
            detail: 'O Contacto 4 requer ou a extensão GD, Imagick ou Gmagick para processar imagens.'
        symlink:
            title: 'O método PHP symlink não está disponível ou não funciona correctamente.'
        session:
            title: 'A sessão PHP falhou ao iniciar.'
        memory_limit:
            title: 'Memória limite PHP insuficiente.'
            detail: 'A configuração PHP atual apenas permite {limit} de memória (na linha de comandos). Estes recursos não são suficientes para executar o Composer e não é possível aumentar este limite automaticamente. Por favor contacte o seu fornecedor de conteúdo  para assistência.'
        systempdir:
            title: 'Impossível escrever no directório de memória de sistema temporário.'
            detail: 'Isto é muito provavelmente um problema com a configuração do seu alojamento. Certifique-se de que o open_basedir permite o acesso ao directório temporário ou de que o sys_temp_dir está correctamente configurado.'
        zip:
            title: ''

    boot:
        composer:
            invalid: 'composer.json schema validation: {exception}'

    config:
        php_cli:
            not_found: 'Este caminho não contém um binário PHP válido. '
            incompatible: 'Este binário é uma versão PHP {cli} mas o seu servidor web é versão {web}.'
            error: ''
        cloud:
            platform: 'A plataforma não pode estar configurada em composer.json .'
            cache: 'Propriedades de cache não podem estar configuradas em composer.json .'

    task:
        setup_packages:
            title: 'A instalar aplicação Contao'
        install_packages:
            title: 'A instalar dependências composer'
        update_packages:
            title: 'A atualizar pacotes'
        dump_autoload:
            title: 'Compressor de descarga classe Autoloader'
        clear_cache:
            title: 'A limpar Cache Composer'
        rebuild_cache:
            title: 'A reconstruir Cache Composer'
        self_update:
            title: 'Contao Manager Auto-atualização'
        backup_create:
            title: ''
        backup_restore:
            title: ''

    taskoperation:
        self-update:
            detail: 'A atualizar de {old} para {new}'
            success: 'Actualizado para {new}'
        install-uploads:
            summary: 'Instalação de uploads'
            console: 'Artifact instalado de {package} (versão {version}) [para packages/{name}]'
        remove-uploads:
            summary: 'Remoção de uploads'
        remove-artifacts:
            summary: ''
        composer-install:
            retry: 'tentando de novo {current}/{max}'
            nothing: 'Nada para instalar ou actualizar'
            result: '{installs} instalado, {updates} actualizado, {removals} retirado'
        dump-autoload:
            result: 'Geração de ficheiros de carga automática optimizados contendo classes {count}.'
        cloud:
            queued: 'Em fila de espera, começando em aproximadamente. {seconds} secundos (actualmente {jobs} empregos em {workers} trabalhadores)'
            processing: 'Activo durante {seconds} segundos.'
            error: 'Falha na resolução de dependências'
            finished: 'Concluído em {seconds} segundos. Utilização de memória: {memory} (pico: {peak}), hora: {time}.'

    upload:
        error:
            file: 'O ficheiro é inválido ou não contém um composer.json .'
            json: 'O composer.json não contém dados JSON válidos .'
            schema: 'O composer.json não passou a validação de schemas.'
            partial: 'O upload de ficheiros não completou com sucesso.'

    error:
        writable:
            root: 'O Gestor de Contacto não pôde escrever para o directório raiz em "{path}".'
            directory: 'O Contao Manager não pôde criar o directório "{path}".'
            config-file: 'O Contao Manager não pôde escrever um ficheiro de configuração para "{file}".'
            detail: 'Parece que o seu servidor não está configurado correctamente. Se está prestes a instalar o Contao, por favor configure o DocumentRoot do seu servidor web. Caso contrário, certifique-se de que as permissões de acesso ao ficheiro estão correctas. Se não tiver a certeza de como corrigir isto, contacte o seu fornecedor de alojamento para obter apoio.'
de:
    integrity:
        allow_url_fopen:
            title: 'Die PHP-Einstellung "allow_url_fopen" ist auf dem Server deaktiviert.'
        process:
            title: 'Die PHP "proc_*" Funktionen ist auf dem Server nicht verfügbar.'
            detail: 'Die Funktionen "proc_open", "proc_close", "proc_get_status" und "proc_terminate" sind notwendig, um Kommandozeilentasks im Hintergrund auszuführen. Bitte frage bei deinem Hosting-Anbieter nach, warum die Funktionen nicht verfügbar sind; der Contao Manager läuft nicht ohne sie.'
        intl:
            title: 'Die PHP Intl-Erweiterung ist nicht verfügbar.'
            detail: 'Contao 4 benötigt die PHP Intl-Erweiterung für die Internationalisierung der Anwendung.'
        openssl:
            title: 'Die PHP OpenSSL-Erweiterung ist nicht verfügbar.'
            detail: 'Der Contao Manager benötigt die OpenSSL-Erweiterung, um Dateien über eine verschlüsselte Verbindung (https) herunterzuladen.'
        dom:
            title: 'Die PHP DOM-Erweiterung ist nicht verfügbar.'
            detail: 'Contao 4 benötigt die PHP DOM-Erweiterung, um XML-Dokumente zu parsen.'
        xmlreader:
            title: 'Die PHP XMLReader-Erweiterung ist nicht verfügbar.'
            detail: 'Contao 4 benötigt die PHP XMLReader-Erweiterung, um XML-Dokumente zu parsen.'
        graphics_lib:
            title: 'Keine PHP Bild-Bibliothek verfügbar.'
            detail: 'Contao 4 benötigt entweder die GD-, Imagick- oder Gmagick-Erweiterung, um Bilder zu verarbeiten.'
        symlink:
            title: 'Die PHP Symlink-Methode ist nicht verfügbar oder funktioniert nicht korrekt.'
        session:
            title: 'Die PHP-Session konnte nicht gestartet werden.'
        memory_limit:
            title: 'Ungenügendes PHP Memory-Limit.'
            detail: 'Deine PHP-Konfiguration erlaubt nur {limit} RAM (auf der Kommandozeile). Das ist nicht genug, um Composer auszuführen, und das Limit konnte auch nicht automatisch erhöht werden. Bitte kontaktiere deinen Hosting-Anbieter.'
        systempdir:
            title: 'Konnte nicht in den temporären Systemordner schreiben.'
            detail: 'Dies ist höchstwahrscheinlich ein Problem mit deiner Serverkonfiguration. Stelle sicher, dass entweder open_basedir den Zugriff auf den temporären Ordner erlaubt oder dass sys_temp_dir korrekt gesetzt ist.'
        zip:
            title: 'Die PHP ZIP-Erweiterung und die unzip/7z-Commands sind beide nicht verfügbar.'

    boot:
        composer:
            invalid: 'composer.json Schema-Validierung: {exception}'

    config:
        php_cli:
            not_found: 'Der Pfad enthält kein gültiges PHP-Binary.'
            incompatible: 'Dieses Binary beinhaltet PHP {cli}, der Webprozess verwendet jedoch PHP {web}.'
            error: 'Fehler beim Validieren des PHP-Binary.'
        cloud:
            platform: 'Die Plattform darf in der composer.json nicht konfiguriert sein.'
            cache: 'Cache-Einstellungen dürfen in der composer.json nicht konfiguriert sein.'

    task:
        setup_packages:
            title: 'Contao wird installiert'
        install_packages:
            title: 'Installieren von Composer-Abhängigkeiten'
        update_packages:
            title: 'Pakete werden aktualisiert'
        dump_autoload:
            title: 'Schreibe Composer-Autoloader'
        clear_cache:
            title: 'Leeren des Composer-Caches'
        rebuild_cache:
            title: 'Neuerstellung des Contao-Caches'
        self_update:
            title: 'Aktualisiere Contao Manager'
        backup_create:
            title: 'Erstelle Datenbank-Backup'
        backup_restore:
            title: 'Datenbank-Backup wird wiederhergestellt'

    taskoperation:
        self-update:
            detail: 'Aktualisiere von {old} nach {new}'
            success: 'Aktualisiert auf {new}'
        install-uploads:
            summary: 'Installiere hochgeladene Pakete'
            console: 'Artefakt für {package} (Version {version}) [nach packages/{name}] installiert'
        remove-uploads:
            summary: 'Entferne hochgeladene Dateien'
        remove-artifacts:
            summary: 'Entferne hochgeladene Pakete'
        composer-install:
            retry: 'Versuch {current}/{max}'
            nothing: 'Keine Aktualisierungen'
            result: '{installs} installiert, {updates} aktualisiert, {removals} entfernt'
        dump-autoload:
            result: 'Autoload-Dateien für {count} Klassen generiert'
        cloud:
            queued: 'Berechnung startet in ca. {seconds} Sekunden (aktuell {jobs} Aufgaben auf {workers} Servern)'
            processing: 'Aktiv seit {seconds} Sekunden.'
            error: 'Abhängigkeits-Auflösung fehlgeschlagen'
            finished: 'Erfolgreich nach {seconds} Sekunden. RAM-Verbrauch: {memory} (Spitze: {peak}), Dauer: {time}.'

    upload:
        error:
            file: 'Die Datei ist ungültig oder enthält keine composer.json.'
            json: 'Die composer.json enthält keine validen JSON-Daten.'
            schema: 'Die composer.json Schema-Validierung ist fehlgeschlagen.'
            partial: 'Der Upload wurde nicht abgeschlossen.'

    error:
        writable:
            root: 'Der Contao Manager kann das Wurzelverzeichnis unter "{path}" nicht beschreiben.'
            directory: 'Das Verzeichnis "{path}" konnte nicht angelegt werden.'
            config-file: 'Die Konfigurations-Datei unter "{file}" konnte nicht geschrieben werden.'
            detail: 'Es scheint als wäre dein Webserver nicht korrekt konfiguriert. Falls du gerade Contao installierst, stelle sicher, dass der DocumentRoot richtig konfiguriert ist. Andernfalls stelle sicher, dass die Dateiberechtigungen korrekt sind. Falls du dies nicht selber reparieren kannst, frage am besten bei deinem Hosting-Anbieter.'
it:
    integrity:
        allow_url_fopen:
            title: 'L''impostazione PHP "allow_url_fopen" non è abilitata sul server.'
        process:
            title: 'Le funzioni PHP "proc_*" non sono disponibili sul server.'
            detail: 'Le funzioni "proc_open", "proc_close", "proc_get_status" e "proc_terminate" sono necessarie per eseguire compiti da linea di comando in background. Verifica con il tuo fornitore di hosting perché questo metodo non è disponibile; il Contao Manager non funzionerà correttamente senza di esso.'
        intl:
            title: 'L''estensione PHP Intl non è disponibile.'
            detail: 'Contao 4 richiede l''estensione PHP Intl per l''internazionalizzazione.'
        openssl:
            title: 'L''estensione PHP OpenSSL non è disponibile.'
            detail: 'Il Contao Manager richiede l''estensione OpenSSL per scaricare i file su una connessione criptata (https).'
        dom:
            title: 'L''estensione PHP DOM non è disponibile. '
            detail: 'Contao 4 richiede l''estensione PHP DOM per analizzare i documenti XML. '
        xmlreader:
            title: 'L''estensione PHP XMLReader non è disponibile.'
            detail: 'Contao 4 richiede l''estensione PHP XMLReader per analizzare i documenti XML. '
        graphics_lib:
            title: 'Non è disponibile una libreria di elaborazione delle immagini PHP.'
            detail: 'Contao 4 richiede l''estensione GD, Imagick o Gmagick per elaborare le immagini.'
        symlink:
            title: 'Il metodo PHP symlink non è disponibile o non funziona correttamente.'
        session:
            title: 'Non è stato possibile avviare la sessione PHP.'
        memory_limit:
            title: 'Limite della memoria PHP non sufficiente.'
            detail: 'La configurazione PHP consente solo la memoria {limit} (sulla riga di comando). Questo non è sufficiente per eseguire Composer e non è stato possibile aumentare automaticamente questo limite. Si prega di contattare il proprio fornitore di webhosting per il supporto.'
        systempdir:
            title: 'Impossibile scrivere sulla cartella temporanea di sistema.'
            detail: 'Questo è molto probabilmente un problema con la vostra configurazione di hosting. Assicurarsi che open_basedir permetta l''accesso alla directory temporanea o che sys_temp_dir sia configurato correttamente.'
        zip:
            title: ''

    boot:
        composer:
            invalid: 'Convalida dello schema composer.json: {exception}'

    config:
        php_cli:
            not_found: 'Questo percorso non contiene un PHP valido.'
            incompatible: 'Il PHP è una versione {cli} ma il tuo server web è una versione {web}.'
            error: 'Errore durante la convalida del PHP binary.'
        cloud:
            platform: 'La piattaforma non deve essere configurata in composer.json.'
            cache: 'Le proprietà della cache non devono essere configurate in composer.json.'

    task:
        setup_packages:
            title: 'Installazione dell''applicazione Contao'
        install_packages:
            title: 'Installazione delle dipendenze del composer'
        update_packages:
            title: 'Aggiornamento pacchetti'
        dump_autoload:
            title: 'Dumping Composer Class Autoloader'
        clear_cache:
            title: 'Cancellazione della cache del compositore'
        rebuild_cache:
            title: 'Ricostruzione di Contao Cache'
        self_update:
            title: 'Auto-aggiornamento del Contao Manager'
        backup_create:
            title: 'Creazione del backup del database'
        backup_restore:
            title: 'Ripristino del backup del database'

    taskoperation:
        self-update:
            detail: 'Aggiornamento da {old} a {new}'
            success: 'Aggiornato a {nuovo}'
        install-uploads:
            summary: 'Installazione uploads'
            console: 'Installate modifiche per {package} (versione {version}) [su pacchetti / {name}]'
        remove-uploads:
            summary: 'Rimuovi uploads'
        remove-artifacts:
            summary: ''
        composer-install:
            retry: 'riprova {current}/{max}'
            nothing: 'Niente da installare o aggiornare'
            result: '{installs} installato, {updates} aggiornato, {removals} rimosso'
        dump-autoload:
            result: 'Generati file di caricamento automatico ottimizzati contenenti {count} classi'
        cloud:
            queued: 'In coda, a partire da circa {seconds} secondi (attualmente {jobs} jobs  {workers} attivi)'
            processing: 'Attivo per {secondi} secondi.'
            error: 'Verifica delle dipendenze non riuscita'
            finished: 'Completatio in {seconds} secondi. Utilizzo della memoria: {memory} (peak: {peak}), tempo: {time}.'

    upload:
        error:
            file: 'Il file non è valido o non contiene un composer.json.'
            json: 'Composer.json non contiene dati JSON validi.'
            schema: 'La convalida dello schema composer.json non è riuscita.'
            partial: 'Il caricamento del file non è stato completato.'

    error:
        writable:
            root: 'Il Contao Manager non poteva scrivere nella directory principale in "{path}".'
            directory: 'Contao Manager non è stato in grado di creare la directory "{path}".'
            config-file: 'Contao Manager non ha potuto scrivere un file di configurazione "{file}".'
            detail: 'Sembra che il tuo server non sia configurato correttamente. Se stai per installare Contao, configura la document root del tuo server web. In caso contrario, assicurarsi che le autorizzazioni di accesso al file siano corrette. Se non sei sicuro di come risolvere questo problema, contatta il tuo provider di hosting per supporto.'
pl:
    integrity:
        allow_url_fopen:
            title: 'Ustawienie PHP "allow_url_fopen" nie jest włączone na serwerze.'
        process:
            title: 'Funkcje PHP "proc_*" są niedostępne na serwerze.'
            detail: 'Funkcje "proc_open", "proc_close", "proc_get_status" i "proc_terminate" są konieczne do wykonywania zadań w linii komend w tle. Skonsultuj z administratorem serwera, dlaczego te funkcje są niedostępne; Contao Manager nie będzie działał bez nich prawidłowo.'
        intl:
            title: 'Rozszerzenie PHP Intl jest niedostępne.'
            detail: 'Contao 4 wymaga rozszerzenia PHP Intl w celach umiędzynarodowienia.'
        openssl:
            title: 'Rozszerzenie PHP OpenSSL jest niedostępne.'
            detail: 'Contao Manager wymaga rozszerzenia OpenSSL w celu pobierania plików przez szyfrowane połączenie (https).'
        dom:
            title: 'Rozszerzenie PHP DOM jest niedostępne.'
            detail: 'Contao 4 wymaga rozszerzenia PHP DOM do czytania dokumentów XML.'
        xmlreader:
            title: 'Rozszerzenie PHP XMLReader jest niedostępne.'
            detail: 'Contao 4 wymaga rozszerzenia PHP XMLReader do czytania dokumentów XML.'
        graphics_lib:
            title: 'Nie ma dostępnej biblioteki PHP do przetwarzania obrazków.'
            detail: 'Contao 4 wymaga rozszerzenia GD, Imagick lub Gmgick do przetwarzania obrazków.'
        symlink:
            title: 'Metoda PHP symlink jest niedostępna lub nie działa prawidłowo.'
        session:
            title: 'Sesja PHP nie mogła zostać uruchomiona.'
        memory_limit:
            title: 'Niewystarczający limit pamięci.'
            detail: 'Twoja konfiguracja PHP pozwala tylko na {limit} pamięci (w linii komend). To nie wystarczy na uruchomienie Composera i automatycznie podniesienie limitu nie było możliwe. Skontaktuj się z hostingodawcą.'
        systempdir:
            title: 'Nie udało się zapisać do tymczasowego katalogu systemowego.'
            detail: 'To jest prawdopodobnie problem z konfiguracją hostingu. Upewnij się, że open_basedir pozwala na dostęp do tymczasowego katalogu lub, że sys_temp_dir jest poprawnie skonfigurowane.'
        zip:
            title: 'Brakuje zarówno rozszerzenia ZIP, jak i poleceń unzip/7z.'

    boot:
        composer:
            invalid: 'walidacja composer.json: {exception}'

    config:
        php_cli:
            not_found: 'Ta ścieżka nie zawiera prawidłowego PHP binary.'
            incompatible: 'Ta wersja PHP binary to {cli}, ale wersja na serwerze to {web}.'
            error: 'Błąd podczas sprawdzania poprawności pliku wykonywalnego PHP.'
        cloud:
            platform: 'Platforma nie może być skonfigurowana w composer.json.'
            cache: 'Właściwości cache nie mogą być skonfigurowane w composer.json.'

    task:
        setup_packages:
            title: 'Instalowanie Aplikacji Contao'
        install_packages:
            title: 'Instalowanie Pakietów Composera'
        update_packages:
            title: 'Aktualizowanie pakietów'
        dump_autoload:
            title: 'Generowanie Klas Autoloader Composer''a'
        clear_cache:
            title: 'Czyszczenie Cache Composera'
        rebuild_cache:
            title: 'Przebudowywanie Contao cache'
        self_update:
            title: 'Auto-Aktualizacja Contao Manager'
        backup_create:
            title: 'Tworzenie kopii zapasowej bazy danych'
        backup_restore:
            title: 'Przywracanie kopii zapasowej bazy danych'

    taskoperation:
        self-update:
            detail: 'Aktualizowanie z {old} do {new}'
            success: 'Aktualizuj do {new}'
        install-uploads:
            summary: 'Instalowanie załadowanych plików'
            console: 'Zainstalowano artifact dla {package} (wersja {version}) [w packages/{name}]'
        remove-uploads:
            summary: 'Usuwanie załadowanych plików'
        remove-artifacts:
            summary: 'Usuwanie przesłanych pakietów'
        composer-install:
            retry: 'ponawianie {current}/{max}'
            nothing: 'Nic od instalacji lub aktualizacji'
            result: '{installs} zainstalowane, {updates} zaktualizowane, {removals} usunięte'
        dump-autoload:
            result: 'Wygenerowano zoptymalizowane pliki autoload zawierające {count} klas'
        cloud:
            queued: 'Dodane do kolejki, startuje za około {seconds} sekund (aktualnie {jobs} zadań w {workers} kolejkach)'
            processing: 'Aktywne od {seconds} sekund.'
            error: 'Nie udało się rozwiązać zależności'
            finished: 'Ukończone w {seconds} sekund. Użycie pamięci: {memory} (szczyt: {peak}), czas:{time}.'

    upload:
        error:
            file: 'Plik jest nieprawidłowy lub nie zawiera composer.json.'
            json: 'Plik composer.json nie zawiera poprawnych danych JSON.'
            schema: 'Walidacja struktury composer.json nie powiodła się.'
            partial: 'Wgrywanie pliku nie zostało zakończone.'

    error:
        writable:
            root: 'Contao Manager nie mógł wykonać zapisu w głównym katalogu w "{path}".'
            directory: 'Contao Manager nie mógł stworzyć katalogu "{path}".'
            config-file: 'Contao Manager nie mógł zapisać pliku konfiguracyjnego w "{file}".'
            detail: 'Wygląda na to, że twój serwer nie jest poprawnie skonfigurowany. Jeśli zamierzasz teraz instalować Contao, skonfiguruj katalog główny serwera www - document root. Sprawdź również, czy uprawnienia do zapisu plików są prawidłowe. Jeśli nie wiesz jak to naprawić, skontaktuj się z administratorem serwera, aby uzyskać wsparcie.'
fa:
    integrity:
        allow_url_fopen:
            title: 'تنظیم PHP "allow_url_fopen" در سرور فعال نیست.'
        process:
            title: ''
            detail: ''
        intl:
            title: 'افزونه PHP Intl موجود نیست.'
            detail: ''
        openssl:
            title: 'افزونه‌ی PHP OpenSSL موجود نیست.'
            detail: ''
        dom:
            title: ''
            detail: ''
        xmlreader:
            title: ''
            detail: ''
        graphics_lib:
            title: ''
            detail: ''
        symlink:
            title: ''
        session:
            title: ''
        memory_limit:
            title: 'محدویت حافظه‌ی PHP ناکافی'
            detail: ''
        systempdir:
            title: 'قادر به نوشتن دایرکتوری سیستم موقت نیست.'
            detail: ''

    boot:
        composer:
            invalid: ''

    config:
        php_cli:
            not_found: 'این مسیر شما یک باینری PHP معتبر نیست.'
            incompatible: 'این باینری PHP نسخه‌ی {cli} است اما وب سرورتان  نسخه‌ی {web} است.'
        cloud:
            platform: ''
            cache: ''

    task:
        setup_packages:
            title: ''
        install_packages:
            title: ''
        update_packages:
            title: 'بروزرسانی بسته‌ها'
        dump_autoload:
            title: ''
        clear_cache:
            title: ''
        rebuild_cache:
            title: ''
        self_update:
            title: ''

    taskoperation:
        self-update:
            detail: ''
            success: ''
        install-uploads:
            summary: ''
            console: ''
        remove-uploads:
            summary: ''
        composer-install:
            retry: ''
            nothing: ''
            result: ''
        dump-autoload:
            result: ''
        cloud:
            queued: ''
            processing: ''
            error: ''
            finished: ''

    upload:
        error:
            file: ''
            json: ''
            schema: ''
            partial: ''

    error:
        writable:
            root: ''
            directory: ''
            config-file: ''
            detail: ''
sv:
    integrity:
        allow_url_fopen:
            title: 'PHP-inställningen "allow_url_fopen" är inte aktiverad på servern.'
        process:
            title: 'PHP "proc_*"-funktionerna är inte tillgängliga på servern.'
            detail: 'Funktionerna "proc_open", "proc_close", "proc_get_status" och "proc_terminate" är nödvändiga för att köra kommandoradsuppgifter i bakgrunden. Kontrollera med din värdleverantör varför den här metoden inte är tillgänglig; Contao Manager kommer inte att fungera korrekt utan den.'
        intl:
            title: 'PHP Intl-tillägget är inte tillgängligt.'
            detail: 'Contao 4 kräver PHP Intl-tillägget för internationaliseringsändamål.'
        openssl:
            title: 'PHP OpenSSL-tillägget är inte tillgängligt.'
            detail: 'Contao Manager kräver OpenSSL-tillägget för att ladda ner filer över en krypterad anslutning (https).'
        dom:
            title: 'PHP DOM-tillägget är inte tillgängligt.'
            detail: 'Contao 4 kräver PHP DOM-tillägget för att tolka XML-dokument.'
        xmlreader:
            title: 'PHP XMLReader-tillägget är inte tillgängligt.'
            detail: 'Contao 4 kräver PHP XMLReader-tillägget för att tolka XML-dokument.'
        graphics_lib:
            title: 'Inget PHP-bildbehandlingsbibliotek är tillgängligt.'
            detail: 'Contao 4 kräver antingen tillägget GD, Imagick eller Gmagick för att bearbeta bilder.'
        symlink:
            title: 'PHP symlink-metoden är inte tillgänglig eller fungerar inte korrekt.'
        session:
            title: 'PHP-sessionen kunde inte startas.'
        memory_limit:
            title: 'Otillräcklig gräns för PHP-minne.'
            detail: 'Din PHP-konfiguration tillåter endast {limit}-minne (på kommandoraden). Detta räcker inte för att köra Composer och det var inte möjligt att automatiskt öka denna gräns. Kontakta din värdleverantör för support.'
        systempdir:
            title: 'Det går inte att skriva till den tillfälliga systemkatalogen.'
            detail: 'Detta är troligen ett problem med din värdkonfiguration. Se till att antingen open_basedir tillåter åtkomst till den temporära katalogen eller att sys_temp_dir är korrekt konfigurerad.'
        zip:
            title: 'Både zip-tillägget och kommandona unzip/7z saknas.'

    boot:
        composer:
            invalid: 'composer.json schemavalidering: {exception}'

    config:
        php_cli:
            not_found: 'Den här sökvägen innehåller inte en giltig PHP-binär.'
            incompatible: 'Den här binära filen är en PHP-version {cli} men din webbserver är version {web}.'
            error: 'Fel vid validering av PHP-binären.'
        cloud:
            platform: 'Plattform får inte konfigureras i composer.json.'
            cache: 'Cacheegenskaper får inte konfigureras i composer.json.'

    task:
        setup_packages:
            title: 'Installerar Contao-applikationen'
        install_packages:
            title: 'Installera Composer Dependens'
        update_packages:
            title: 'Uppdaterar paket'
        dump_autoload:
            title: 'Dumping Composer Class Autoloader'
        clear_cache:
            title: 'Rensa Composer Cache'
        rebuild_cache:
            title: 'Bygger om Contao Cache'
        self_update:
            title: 'Självuppdatering för Contao Manager'
        backup_create:
            title: 'Skapar säkerhetskopiering av databas'
        backup_restore:
            title: 'Återställer säkerhetskopiering av databas'

    taskoperation:
        self-update:
            detail: 'Uppdaterar från {old} till {new}'
            success: 'Uppdaterad till {new}'
        install-uploads:
            summary: 'Installerar uppladdningar'
            console: 'Installerad artefakt för {package} (version {version}) [till package/{name}]'
        remove-uploads:
            summary: 'Tar bort uppladdningar'
        remove-artifacts:
            summary: 'Ta bort uppladdade paket'
        composer-install:
            retry: 'försöker igen {current}/{max}'
            nothing: 'Inget att installera eller uppdatera'
            result: '{installs} installerat, {updates} uppdaterat, {removals} borttaget'
        dump-autoload:
            result: 'Genererade optimerade autoload-filer som innehåller {count} klasser'
        cloud:
            queued: 'Kö, med start om ca. {seconds} sekunder (för närvarande {jobs} jobb på {workers} arbetare)'
            processing: 'Aktiv i {seconds} sekunder.'
            error: 'Det gick inte att lösa beroenden'
            finished: 'Klart på {seconds} sekunder. Minnesanvändning: {memory} (peak: {peak}), tid: {time}.'

    upload:
        error:
            file: 'Filen är ogiltig eller innehåller inte en composer.json.'
            json: 'Composer.json innehåller inte giltig JSON-data.'
            schema: 'Composer.json-schemavalideringen misslyckades.'
            partial: 'Filuppladdningen slutfördes inte.'

    error:
        writable:
            root: 'Contao Manager kunde inte skriva till rotkatalogen på "{path}".'
            directory: 'Contao Manager kunde inte skapa katalogen "{path}".'
            config-file: 'Contao Manager kunde inte skriva en konfigurationsfil till "{file}".'
            detail: 'Det verkar som om din server inte är korrekt konfigurerad. Om du är på väg att installera Contao, vänligen konfigurera DocumentRoot för din webbserver. Se annars till att filåtkomstbehörigheterna är korrekta. Om du är osäker på hur du åtgärdar detta, kontakta din värdleverantör för support.'
en:
    integrity:
        allow_url_fopen:
            title: 'The PHP setting "allow_url_fopen" is not enabled on the server.'
        process:
            title: 'The PHP "proc_*" functions are not available on the server.'
            detail: 'The "proc_open", "proc_close", "proc_get_status" and "proc_terminate" functions are necessary to run command line tasks in the background. Check with your hosting provider why this method is not available; the Contao Manager will not run correctly without it.'
        intl:
            title: 'The PHP Intl extension is not available.'
            detail: 'Contao 4 requires the PHP Intl extension for internationalization purposes.'
        openssl:
            title: 'The PHP OpenSSL extension is not available.'
            detail: 'The Contao Manager requires the OpenSSL extension to download files over an encrypted connection (https).'
        dom:
            title: 'The PHP DOM extension is not available.'
            detail: 'Contao 4 requires the PHP DOM extension to parse XML documents.'
        xmlreader:
            title: 'The PHP XMLReader extension is not available.'
            detail: 'Contao 4 requires the PHP XMLReader extension to parse XML documents.'
        graphics_lib:
            title: 'No PHP image processing library is available.'
            detail: 'Contao 4 requires either the GD, Imagick or Gmagick extension to process images.'
        symlink:
            title: 'The PHP symlink method is unavailable or does not work correctly.'
        session:
            title: 'The PHP session could not be started.'
        memory_limit:
            title: 'Insufficient PHP memory limit.'
            detail: 'Your PHP configuration only allows for {limit} memory (on the command line). This is not enough to run Composer and it was not possible to automatically increase this limit. Please contact your hosting provider for support.'
        systempdir:
            title: 'Unable to write to the temporary system directory.'
            detail: 'This is most likely a problem with your hosting configuration. Make sure that either open_basedir does allow access to the temporary directory or that the sys_temp_dir is correctly configured.'
        zip:
            title: 'The zip extension and unzip/7z commands are both missing.'

    boot:
        composer:
            invalid: 'composer.json schema validation: {exception}'

    config:
        php_cli:
            not_found: 'This path does not contain a valid PHP binary.'
            incompatible: 'This binary is a PHP version {cli} but your web server is version {web}.'
            error: 'Error validating the PHP binary.'
        cloud:
            platform: 'Platform must not be configured in composer.json.'
            cache: 'Cache properties must not be configured in composer.json.'

    task:
        setup_packages:
            title: 'Installing Contao Application'
        install_packages:
            title: 'Installing Composer Dependencies'
        update_packages:
            title: 'Updating Packages'
        dump_autoload:
            title: 'Dumping Composer Class Autoloader'
        clear_cache:
            title: 'Clearing Composer Cache'
        rebuild_cache:
            title: 'Rebuilding Contao Cache'
        self_update:
            title: 'Contao Manager Self-Update'
        backup_create:
            title: 'Creating database backup'
        backup_restore:
            title: 'Restoring database backup'

    taskoperation:
        self-update:
            detail: 'Updating from {old} to {new}'
            success: 'Updated to {new}'
        install-uploads:
            summary: 'Installing uploads'
            console: 'Installed artifact for {package} (version {version}) [to packages/{name}]'
        remove-uploads:
            summary: 'Removing uploads'
        remove-artifacts:
            summary: 'Removing uploaded packages'
        composer-install:
            retry: 'retrying {current}/{max}'
            nothing: 'Nothing to install or update'
            result: '{installs} installed, {updates} updated, {removals} removed'
        dump-autoload:
            result: 'Generated optimized autoload files containing {count} classes'
        cloud:
            queued: 'Queued, starting in approx. {seconds} seconds (currently {jobs} jobs on {workers} workers)'
            processing: 'Active for {seconds} seconds.'
            error: 'Failed resolving dependencies'
            finished: 'Completed in {seconds} seconds. Memory usage: {memory} (peak: {peak}), time: {time}.'

    upload:
        error:
            file: 'The file is invalid or does not contain a composer.json.'
            json: 'The composer.json does not contain valid JSON data.'
            schema: 'The composer.json schema validation failed.'
            partial: 'The file upload was not completed.'

    error:
        writable:
            root: 'The Contao Manager could not write to the root directory at "{path}".'
            directory: 'The Contao Manager could not create the directory "{path}".'
            config-file: 'The Contao Manager could not write a config file to "{file}".'
            detail: 'It looks like your server is not configured correctly. If you are about to install Contao, please setup the DocumentRoot of your web server. Otherwise make sure the file access permissions are correct. If you are unsure how to fix this, contact your hosting provider for support.'
ja:
    integrity:
        allow_url_fopen:
            title: 'サーバーのPHPの設定で"allow_url_fopen"が有効ではありません。'
        process:
            title: 'PHPの"proc_"関数が有効ではありません。'
            detail: 'バックグラウンドでコマンド行のタスクを実行するために"proc_open"、"proc_close"、"proc_get_status"、"proc_terminate"といった関数が必要です。これらのメソッドが何故利用できないかをホスティングサービスの提供者に確認してください、これらなしではContao Managerは正しく動作しません。'
        intl:
            title: 'PHPのIntl拡張を利用できません。'
            detail: 'Contao 4は国際化の目的のためにPHPのIntl拡張を必要とします。'
        openssl:
            title: 'PHPのOpenSSL拡張を利用できません。'
            detail: 'Contao Managerは暗号化した接続(https)でファイルをダウンロードするためにOpenSSL拡張が必要です。'
        dom:
            title: 'PHPのDOM拡張を利用できません。'
            detail: 'Contao 4はXMLドキュメントの解析のためにPHPのDOM拡張を必要とします。'
        xmlreader:
            title: 'PHPのXMLReader拡張を利用できません。'
            detail: 'Contao 4はXMLドキュメントの解析のためにPHPのXMLReader拡張を必要とします。'
        graphics_lib:
            title: 'PHPの画像処理のライブラリが何も利用できません。'
            detail: 'Contao 4は画像を処理するためにGD、IMagick、Gmagickの拡張のいずれかを必要とします。'
        symlink:
            title: 'PHPのsymlinkメソッドを利用できないか、正しく動作しません。'
        session:
            title: 'PHPのセッションを開始できませんでした。'
        memory_limit:
            title: 'PHPのメモリの制限が不足しています。'
            detail: 'PHPの設定は(コマンド行では){limit}のメモリだけを許可しています。こではComposerを動作させるのに十分ではなく、制限を自動的に増やすこともできませんでした。ホスティングの提供者に連絡してサポートを求めてください。'
        systempdir:
            title: 'システムの一時ディレクトリに書き込みできませんでした。'
            detail: 'ホスティングの設定に問題の可能性がもっとも高いです。open_basedirが一時ディクトリへのアクセスを許可しているか、sys_temp_dirが正しく設定されているか確認してください。'
        zip:
            title: 'zip拡張とunzip/7zコマンドの両方がありません。'

    boot:
        composer:
            invalid: 'composer.jsonスキームの検証: {exception}'

    config:
        php_cli:
            not_found: 'このパスに有効なPHPの実行ファイルがありません。'
            incompatible: 'この実行ファイルはPHPのバージョンは{cli}ですが、ウェブサーバーでのバージョンは{web}です。'
            error: 'PHPの実行ファイルの有効性確認にエラーがあります。'
        cloud:
            platform: 'プラットフォームはcomposer.jsonに構成してはなりません。'
            cache: 'キャッシュの属性をcomposer.jsonに構成してはなりません。'

    task:
        setup_packages:
            title: 'Contaoアプリケーションをインストール中'
        install_packages:
            title: 'Composerの依存関係をインストール中'
        update_packages:
            title: 'パッケージを更新'
        dump_autoload:
            title: 'Composerのクラスのオートローダーを書き出し中'
        clear_cache:
            title: 'Composerのキャッシュを消去中'
        rebuild_cache:
            title: 'Contaoのキャッシュを再作成'
        self_update:
            title: 'Contao Managerの自己更新'
        backup_create:
            title: 'データベースのバックアップを作成中'
        backup_restore:
            title: 'データベースのバックアップを復元中'

    taskoperation:
        self-update:
            detail: '{old}から{new}に更新中'
            success: '{new}に更新完了'
        install-uploads:
            summary: 'アップロードしたファイルをインストール中'
            console: '{package} (バージョン {version})のインストール過程[packages/{name}に存在]'
        remove-uploads:
            summary: 'アップロードしたファイルを削除中'
        remove-artifacts:
            summary: 'アップロードしたパッケージを削除中'
        composer-install:
            retry: '再試行中 {current}/{max}'
            nothing: 'インストールやアップデートはなし'
            result: '{installs}個をインストール、{updates}個をアップデート、{removals}個を削除'
        dump-autoload:
            result: '{count}個のクラスを含む最適化した自動読み込みのファイルを生成'
        cloud:
            queued: 'キューに追加し約{seconds}秒で開始予定 (現在{workers}個のワーカーに{jobs}個のジョブ)'
            processing: '{seconds}秒動作中'
            error: '依存関係の解決に失敗'
            finished: '{seconds}秒で完了。メモリの使用: {memory} (最大: {peak})、時間: {time}。'

    upload:
        error:
            file: 'ファイルが無効、またはcomposer.jsonを含んでいません。'
            json: 'composer.jsonが正しいJSONのデータを含んでいません。'
            schema: 'composer.jsonスキーマの検証に失敗しました。'
            partial: 'アップロードしたファイルは完全ではありませんでした。'

    error:
        writable:
            root: 'Contao Managerは"{path}"のルートディレクトリに書き込みできませんでした。'
            directory: 'Contao Managerは"{path}"のディレクトリを作成できませんでした。'
            config-file: 'Contao Managerは構成ファイルを"{file}"に書き込めませんでした。'
            detail: 'サーバーを正しく構成できていない様です。Contaoをインストールしようとしている場合は、WebサーバーのDocumentRootを設定してください。そうでない場合はファイルのアクセス権限が正しいことを確認してください。これを修正する方法がわからない場合は、ホスティング提供者に連絡してサポートを求めてください。'
ru:
    integrity:
        allow_url_fopen:
            title: 'Настройка PHP "allow_url_fopen" отключена на сервере.'
        process:
            title: 'Функции PHP "proc_*" недоступны на сервере.'
            detail: 'Функции "proc_open", "proc_close", "proc_get_status" и "proc_terminate" необходимы для выполнения задач командной строки в фоновом режиме. Узнайте у вашего хостинг-провайдера, почему этот метод недоступен, Contao Manager не будет корректно работать без него.'
        intl:
            title: 'Расширение PHP Intl недоступно.'
            detail: 'Contao 4 необходимо расширение PHP Intl в целях интернационализации.'
        openssl:
            title: 'Расширение PHP OpenSSL недоступно.'
            detail: 'Contao Manager необходимо расширение OpenSSL для передачи файлов по зашифрованному соединению (https).'
        dom:
            title: 'Расширение PHP DOM недоступно.'
            detail: 'Contao 4 необходимо расширение PHP DOM для анализа XML-документов.'
        xmlreader:
            title: 'Расширение PHP XMLReader недоступно.'
            detail: 'Contao 4 необходимо расширение PHP XMLReader для анализа XML-документов.'
        graphics_lib:
            title: 'Библиотека обработки изображений PHP не доступна.'
            detail: 'Для обработки изображений Contao 4 требует расширения GD, Imagick или Gmagick.'
        symlink:
            title: 'Метод PHP symlink недоступен или работает неправильно.'
        session:
            title: 'Не удалось запустить сессию PHP.'
        memory_limit:
            title: 'Недостаточный предел памяти PHP.'
            detail: 'Конфигурация PHP позволяет использовать только {limit} памяти (в командной строке). Этого недостаточно для запуска Composer и автоматическое увеличение этого предела невозможно. Для получения поддержки обратитесь к вашему хостинг-провайдеру.'
        systempdir:
            title: 'Не удается записать во временный системный каталог.'
            detail: 'Вероятно, это проблема с настройкой вашего хостинга. Убедитесь, что open_basedir разрешает доступ к временному каталогу или sys_temp_dir настроен правильно.'
        zip:
            title: 'Расширение zip и команды unzip/7z отсутствуют.'

    boot:
        composer:
            invalid: 'composer.json проверка схемы: {exception}'

    config:
        php_cli:
            not_found: 'Путь не содержит верный бинарный файл PHP.'
            incompatible: 'Двоичный файл PHP версии {cli}, а веб-сервер версии {web}.'
            error: 'Ошибка проверки двоичного файла PHP.'
        cloud:
            platform: 'Платформа не должна быть настроена в composer.json.'
            cache: 'Свойства кеша не должны быть настроены в composer.json.'

    task:
        setup_packages:
            title: 'Установка приложения Contao'
        install_packages:
            title: 'Установка зависимостей Composer'
        update_packages:
            title: 'Обновление пакетов'
        dump_autoload:
            title: 'Дампинг автозагрузчика класса Composer'
        clear_cache:
            title: 'Очистка кеша Composer'
        rebuild_cache:
            title: 'Перестроение кеша Contao'
        self_update:
            title: 'Автоматическое обновление Contao Manager'
        backup_create:
            title: 'Создание резервной копии базы данных'
        backup_restore:
            title: 'Восстановление резервной копии базы данных'

    taskoperation:
        self-update:
            detail: 'Обновление с {old} до {new}'
            success: 'Обновлено до {new}'
        install-uploads:
            summary: 'Установка загрузок'
            console: 'Установлен артефакт для {package} (версии {version}) [к пакетам/{name}]'
        remove-uploads:
            summary: 'Удаление загрузок'
        remove-artifacts:
            summary: 'Удаление загруженных пакетов'
        composer-install:
            retry: 'повторная попытка {current}/{max}'
            nothing: 'Нечего устанавливать или обновлять'
            result: '{installs} установлено, {updates} обновлено, {removals} удалено'
        dump-autoload:
            result: 'Созданы оптимизированные файлы автозагрузки, содержащие классы {count}'
        cloud:
            queued: 'В очереди, начиная приблизительно с {seconds} сек. (сейчас {jobs} задач в {workers} воркерах (workers))'
            processing: 'Активен в течение {seconds} сек.'
            error: 'Ошибка разрешения зависимостей'
            finished: 'Завершено за {seconds} сек. Использование памяти: {memory} (пик: {peak}), время: {time}.'

    upload:
        error:
            file: 'Ошибка файла или отсутствует composer.json.'
            json: 'Файл composer.json не содержит допустимых данных JSON.'
            schema: 'Ошибка проверки схемы composer.json.'
            partial: 'Загрузка файла не была завершена.'

    error:
        writable:
            root: 'Contao Manager не смог записать в корневой каталог "{path}".'
            directory: 'Contao Manager не смог создать каталог "{path}".'
            config-file: 'Contao Manager не смог записать файл конфигурации "{file}".'
            detail: 'Вероятно, сервер настроен неправильно. Если вы собираетесь установить Contao, установите корневой каталог документов веб-сервера. В противном случае убедитесь, что права доступа к файлам указаны правильно. Если вы не знаете, как это исправить, обратитесь за помощью к своему хостинг-провайдеру.'
sr:
    integrity:
        allow_url_fopen:
            title: 'Опција PHP "allow_url_fopen" није омогућена на серверу.'
        process:
            title: 'Функције PHP "proc_*" нису доступне на серверу.'
            detail: 'Функције "proc_open", "proc_close", "proc_get_status" and "proc_terminate"  су неопходне за извршавање задатака командне линије у позадини. Проверите са својим провајдером хостинга зашто нису доступне; Contao Manager без њих неће радити исправно.'
        intl:
            title: 'Екстензија PHP Intl није доступна.'
            detail: 'Contao 4 захтева Intl екстензију ради потреба интернационализације.'
        openssl:
            title: 'Екстензија PHP OpenSSL није доступна.'
            detail: 'Contao Менаџер захтева OpenSSL екстензију ради преузимања фајлова преко заштићене конекције (https). '
        dom:
            title: 'Екстензија PHP DOM није доступна.'
            detail: 'Contao 4 треба екстензију PHP DOM да би могао да обрађује XML документе.'
        xmlreader:
            title: 'Екстензија PHP XMLReader није доступна.'
            detail: 'Contao 4 треба екстензију PHP XMLReader да би могао да обрађује XML документе.'
        graphics_lib:
            title: 'Није доступна нити једна PHP библиотека за обраду слика.'
            detail: 'Contao 4 треба GD, Imagick или Gmagick да би могао да обрађује слике.'
        symlink:
            title: 'Метода PHP symlink није доступна или не ради исправно.'
        session:
            title: 'PHP сесија није покренута.'
        memory_limit:
            title: 'Недовољан лимит меморије за PHP.'
            detail: 'Ваша конфигурација PHP дозвољава употребу {limit} меморије (у командној линији). То није довољно да би Композер радио, а није успело ни аутоматско повећање лимита. Контактирајте вашег провајдера ради подршке.'
        systempdir:
            title: 'Неуспешан упис у привремени системски директоријум.'
            detail: 'Ово је вероватно узроковано конфигурацијом хостинга. Проверите да ли open_basedir  дозвољава приступ привременом директоријуму, и да ли је sys_temp_dir исправно конфигурисан.'
        zip:
            title: ''

    boot:
        composer:
            invalid: 'composer.json schema validation: {exception}'

    config:
        php_cli:
            not_found: 'Ова путања не садржи валидан PHP binary.'
            incompatible: 'Овај binary је намењен верзији PHP {cli} док је на вашем веб серверу верзија {web}.'
            error: 'Грешка приликом валидације PHP binary.'
        cloud:
            platform: 'Платформа не сме бити конфигурисана у composer.json.'
            cache: 'Подешавања Cache-а не смеју бити конфигурисана у composer.json.'

    task:
        setup_packages:
            title: 'Инсталирање Contao апликације'
        install_packages:
            title: 'Инсталирање Композер зависности'
        update_packages:
            title: 'Ажурирање Пакета'
        dump_autoload:
            title: 'Пражњење Composer Class Autoloader-а'
        clear_cache:
            title: 'Пражњење Композер Cache-а'
        rebuild_cache:
            title: 'Поновно креирање кеша'
        self_update:
            title: 'Contao Manager аутоматско ажурирање'
        backup_create:
            title: 'Креирање резервне копије базе података'
        backup_restore:
            title: 'Обнављање копије базе података'

    taskoperation:
        self-update:
            detail: 'Надоградња са  {old} на {new}'
            success: 'Ажурирано на {new}'
        install-uploads:
            summary: 'Инсталирање преузетих фајлова'
            console: 'Инсталисани артифакти за {package} (верзија {version}) [to packages/{name}]'
        remove-uploads:
            summary: 'Уклањање преузетих фајлова'
        remove-artifacts:
            summary: ''
        composer-install:
            retry: 'покушај {current}/{max}'
            nothing: 'Нема ништа за инсталацију или преузимање'
            result: '{installs} инсталирано, {updates} ажурирано, {removals} уклоњено'
        dump-autoload:
            result: 'Generated optimized autoload files containing {count} classes'
        cloud:
            queued: 'Убачено у редослед, почиње за око  {seconds} секунди (тренутно {jobs} задатака у {workers} послова)'
            processing: 'Активно {seconds} секунди.'
            error: 'Неуспешно разрешавање зависности'
            finished: 'Завршено за {seconds} секунди. Употреба меморије: {memory} (peak: {peak}), time: {time}.'

    upload:
        error:
            file: 'Фајл је неисправан или не садржи composer.json.'
            json: 'Composer.json не садржи исправне JSON податке.'
            schema: 'Валидација composer.json schema није успела.'
            partial: 'Преузимање фајла није завршено.'

    error:
        writable:
            root: 'Contao Manager не може да пише у root directory на путањи "{path}".'
            directory: 'Contao Manager не може да креира директоријум "{path}".'
            config-file: 'Contao Manager не може да пише у конфигурациони фајл "{file}".'
            detail: 'Чини се да Ваш сервер није исправно конфигурисан. Ако планирате да инсталирате Contao, подесите DocumentRoot на Вашем мрежном серверу. У супротном будите сигурни да су дозволе за приступ фајловима исправне. Ако нисте сигурни како то да урадите, контактирајте Вашег хостинг провајдера.'
fr:
    integrity:
        allow_url_fopen:
            title: 'Le paramètre PHP "allow_url_fopen" n''est pas activé sur le serveur.'
        process:
            title: 'Les fonctions PHP "proc_*" ne sont pas disponibles sur le serveur.'
            detail: 'Les fonctions "proc_open", "proc_close", "proc_get_status" et "proc_terminate" sont nécessaires pour exécuter des tâches en ligne de commande en arrière-plan. Vérifiez auprès de votre hébergeur pourquoi cette méthode n''est pas disponible ; le Contao Manager ne fonctionnera pas correctement sans elle.'
        intl:
            title: 'L''extension PHP Intl n''est pas disponible.'
            detail: 'Contao 4 nécessite l''extension PHP Intl à des fins d''internationalisation.'
        openssl:
            title: 'L''extension PHP OpenSSL n''est pas disponible.'
            detail: 'Le Contao Manager nécessite l''extension OpenSSL pour télécharger des fichiers via une connexion sécurisée (https).'
        dom:
            title: 'L''extension PHP DOM n''est pas disponible.'
            detail: 'Contao 4 nécessite l''extension PHP DOM pour analyser les documents XML.'
        xmlreader:
            title: 'L''extension PHP XMLReader n''est pas disponible.'
            detail: 'Contao 4 nécessite l''extension PHP XMLReader pour analyser les documents XML.'
        graphics_lib:
            title: 'Aucune bibliothèque de traitement d''image PHP n''est disponible.'
            detail: 'Contao 4 nécessite l''extension GD, Imagick ou Gmagick pour traiter les images.'
        symlink:
            title: 'La méthode PHP symlink est indisponible ou ne fonctionne pas correctement.'
        session:
            title: 'La session PHP n''a pas pu être démarrée.'
        memory_limit:
            title: 'Limite de mémoire PHP insuffisante.'
            detail: 'Votre configuration PHP n''autorise que {limit} de mémoire (en ligne de commande). Ce n''est pas suffisant pour exécuter Composer et il n''a pas été possible d''augmenter automatiquement cette limite. Veuillez contacter votre hébergeur pour obtenir de l''aide.'
        systempdir:
            title: 'Impossible d''écrire dans le répertoire système temporaire.'
            detail: 'Il s''agit très probablement d''un problème avec votre configuration d''hébergement. Assurez-vous que open_basedir autorise l''accès au répertoire temporaire ou que sys_temp_dir est correctement configuré.'
        zip:
            title: 'L''extension zip et les commandes unzip/7z sont toutes manquantes.'

    boot:
        composer:
            invalid: 'Validation du schéma de composer.json : {exception}'

    config:
        php_cli:
            not_found: 'Ce chemin ne contient pas de binaire PHP valide.'
            incompatible: 'Ce binaire est une version PHP {cli} mais votre serveur web est en version {web}.'
            error: 'Erreur lors de la validation du binaire PHP.'
        cloud:
            platform: 'La plateforme ne doit pas être configurée dans composer.json.'
            cache: 'Les propriétés du cache ne doivent pas être configurées dans composer.json.'

    task:
        setup_packages:
            title: 'Installation de l''application Contao'
        install_packages:
            title: 'Installation des dépendances Composer'
        update_packages:
            title: 'Mise à jour des paquets'
        dump_autoload:
            title: 'Génération de l''autoloader de classes Composer'
        clear_cache:
            title: 'Vidage du cache Composer'
        rebuild_cache:
            title: 'Reconstruction du cache Contao'
        self_update:
            title: 'Mise à jour automatique du Contao Manager'
        backup_create:
            title: 'Création de la sauvegarde de la base de données'
        backup_restore:
            title: 'Restauration de la sauvegarde de la base de données'

    taskoperation:
        self-update:
            detail: 'Mise à jour de {old} vers {new}'
            success: 'Mis à jour vers {new}'
        install-uploads:
            summary: 'Installation des téléchargements'
            console: 'Artéfact installé pour {package} (version {version}) [dans packages/{name}]'
        remove-uploads:
            summary: 'Suppression des téléchargements'
        remove-artifacts:
            summary: 'Suppression des paquets téléchargés'
        composer-install:
            retry: 'nouvelle tentative {current}/{max}'
            nothing: 'Rien à installer ou à mettre à jour'
            result: '{installs} installé(s), {updates} mis à jour, {removals} supprimé(s)'
        dump-autoload:
            result: 'Fichiers autoload optimisés générés contenant {count} classes'
        cloud:
            queued: 'En attente, démarrage dans environ {seconds} secondes (actuellement {jobs} tâches sur {workers} workers)'
            processing: 'Actif depuis {seconds} secondes.'
            error: 'Échec de la résolution des dépendances'
            finished: 'Terminé en {seconds} secondes. Utilisation mémoire : {memory} (pic : {peak}), temps : {time}.'

    upload:
        error:
            file: 'Le fichier est invalide ou ne contient pas de composer.json.'
            json: 'Le fichier composer.json ne contient pas de données JSON valides.'
            schema: 'La validation du schéma de composer.json a échoué.'
            partial: 'Le téléchargement du fichier n''a pas été terminé.'

    error:
        writable:
            root: 'Le Contao Manager n''a pas pu écrire dans le répertoire racine à l''adresse "{path}".'
            directory: 'Le Contao Manager n''a pas pu créer le répertoire "{path}".'
            config-file: 'Le Contao Manager n''a pas pu écrire un fichier de configuration dans "{file}".'
            detail: 'Il semble que votre serveur ne soit pas configuré correctement. Si vous êtes sur le point d''installer Contao, veuillez configurer le DocumentRoot de votre serveur web. Sinon, assurez-vous que les permissions d''accès aux fichiers sont correctes. Si vous ne savez pas comment résoudre ce problème, contactez votre hébergeur pour obtenir de l''aide.'
lv:
    integrity:
        allow_url_fopen:
            title: 'PHP iestatījums "allow_url_fopen" serverī nav iespējots.'
        process:
            title: 'Serverī nav pieejamas PHP "proc_*" funkcijas.'
            detail: 'Funkcijas "proc_open", "proc_close", "proc_get_status" un "proc_terminate" ir nepieciešamas, lai fona režīmā palaistu komandrindas uzdevumus. Noskaidrojiet pie sava hostinga pakalpojumu sniedzēja, kāpēc šī metode nav pieejama; bez tās Contao Manager nedarbosies pareizi.'
        intl:
            title: 'PHP Intl paplašinājums nav pieejams.'
            detail: 'Contao 4 ir nepieciešams PHP Intl paplašinājums internacionalizācijas vajadzībām.'
        openssl:
            title: 'PHP OpenSSL paplašinājums nav pieejams.'
            detail: 'Contao Manager ir nepieciešams OpenSSL paplašinājums, lai failus lejupielādētu šifrētā savienojumā (https).'
        dom:
            title: 'PHP DOM paplašinājums nav pieejams.'
            detail: 'Contao 4 ir nepieciešams PHP DOM paplašinājums, lai analizētu XML dokumentus.'
        xmlreader:
            title: 'PHP XMLReader paplašinājums nav pieejams.'
            detail: 'Contao 4 ir nepieciešams PHP XMLReader paplašinājums, lai analizētu XML dokumentus.'
        graphics_lib:
            title: 'Nav pieejama neviena PHP attēlu apstrādes bibliotēka.'
            detail: 'Lai apstrādātu attēlus, Contao 4 nepieciešams paplašinājums GD, Imagick vai Gmagick.'
        symlink:
            title: 'PHP simbolu metode nav pieejama vai nedarbojas pareizi.'
        session:
            title: 'Nevarēja uzsākt PHP sesiju.'
        memory_limit:
            title: 'Nepietiekams PHP atmiņas ierobežojums.'
            detail: 'Jūsu PHP konfigurācija atļauj tikai {limit} atmiņu (komandrindā). Ar to nepietiek, lai palaistu Composer, un nebija iespējams automātiski palielināt šo limitu. Lūdzu, sazinieties ar savu hostinga pakalpojumu sniedzēju, lai saņemtu atbalstu.'
        systempdir:
            title: 'Nevar rakstīt sistēmas pagaidu direktorijā.'
            detail: 'Visticamāk, tā ir problēma ar jūsu hostinga konfigurāciju. Pārliecinieties, vai open_basedir ļauj piekļūt pagaidu direktorijai, vai arī sys_temp_dir ir pareizi konfigurēta.'
        zip:
            title: ''

    boot:
        composer:
            invalid: 'composer.json shēmas validācija: {exception}'

    config:
        php_cli:
            not_found: 'Šis ceļš nesatur derīgu PHP bināru.'
            incompatible: 'Šis binārs ir PHP versija {cli}, bet jūsu tīmekļa serveris ir versija {web}.'
            error: ''
        cloud:
            platform: 'Platforma nedrīkst būt konfigurēta composer.json.'
            cache: 'Kešatmiņas rekvizīti nedrīkst būt konfigurēti composer.json.'

    task:
        setup_packages:
            title: 'Instalē Contao lietotni'
        install_packages:
            title: 'Composer atkarību instalēšana'
        update_packages:
            title: 'Atjaunina pakotnes'
        dump_autoload:
            title: ''
        clear_cache:
            title: 'Iztīra Composer kešatmiņu'
        rebuild_cache:
            title: 'Pārbūvē Contao kešatmiņu'
        self_update:
            title: 'Contao Manager pašatjaunināšana'
        backup_create:
            title: ''
        backup_restore:
            title: ''

    taskoperation:
        self-update:
            detail: 'Atjaunina no {old} uz {new}'
            success: 'Atjaunināts uz {new}'
        install-uploads:
            summary: 'Augšupielādes instalēšana'
            console: 'Instalēts artefakts {package} (versija {version}) [uz packages/{name}]'
        remove-uploads:
            summary: 'Augšupielādes noņemšana'
        remove-artifacts:
            summary: ''
        composer-install:
            retry: 'atkārtots mēģinājums {current}/{max}'
            nothing: 'Nekas nav jāinstalē vai jāatjaunina'
            result: '{installs} instalēts, {updates} atjaunināts, {removals} noņemts'
        dump-autoload:
            result: 'Izveidoti optimizēti autoload faili, kas satur {count} klases'
        cloud:
            queued: 'Ierindots, sāks aptuveni pēc {seconds} sekundēm (pašlaik {jobs} darbi uz {workers} darbiniekiem).'
            processing: 'Aktīvs {seconds} sekundes.'
            error: 'Neizdevās atrisināt atkarības'
            finished: 'Pabeigts {seconds} sekundēs. Atmiņas izmantošana: {memory} (maksimums: {peak}), laiks: {time}.'

    upload:
        error:
            file: 'Datne ir nederīga vai nesatur composer.json.'
            json: 'Composer.json nesatur derīgus JSON datus.'
            schema: 'Composer.json shēmas validācija neizdevās.'
            partial: 'Failu augšupielāde netika pabeigta.'

    error:
        writable:
            root: 'Contao Manager nevarēja rakstīt uz saknes direktoriju adresē "{path}".'
            directory: 'Contao Manager nevarēja izveidot direktoriju "{path}".'
            config-file: 'Contao Manager nevarēja uzrakstīt konfigurācijas failu uz "{file}".'
            detail: 'Izskatās, ka jūsu serveris nav pareizi konfigurēts. Ja gatavojaties instalēt Contao, lūdzu, iestatiet sava tīmekļa servera DocumentRoot. Pretējā gadījumā pārliecinieties, ka failu piekļuves atļaujas ir pareizas. Ja neesat pārliecināts, kā to novērst, sazinieties ar savu hostinga pakalpojumu sniedzēju, lai saņemtu atbalstu.'
tr:
    integrity:
        allow_url_fopen:
            title: 'Sunucuda "allow_url_fopen" PHP ayarı etkinleştirilmemiş.'
        process:
            title: 'Sunucuda "proc_*" işlevleri kullanılamıyor.'
            detail: '"proc_open", "proc_close", "proc_get_status" ve "proc_terminate" işlevleri arka planda komut satırı işlemlerini yapmak için gereklidir. Barındırma hizmeti sağlayıcınıza bu yöntemlerin neden kullanılamadığını sorun. Bunlar olmadan Contao Manager düzgün şekilde çalışmaz.'
        intl:
            title: 'PHP Intl eklentisi kullanılamıyor.'
            detail: 'Contao 4 uluslararası özelliklerinin çalışabilmesi için PHP Intl eklentisi gereklidir.'
        openssl:
            title: 'PHP OpenSSL eklentisi kullanılamıyor.'
            detail: 'Contao Manager, şifrelenmiş bir bağlantı (https) üzerinden  dosyaları indirebilmek için OpenSSL eklentisine gerek duyar.'
        dom:
            title: 'PHP DOM eklentisi kullanılamıyor.'
            detail: 'Contao 4, XML dosyalarını okuyabilmek için PHP XML Reader eklentisine gerek duyar.'
        xmlreader:
            title: 'PHP XML Reader eklentisi kullanılamıyor.'
            detail: 'Contao 4, XML dosyalarını okuyabilmek için PHP XMLReader eklentisine gerek duyar.'
        graphics_lib:
            title: 'Kullanılabilecek bir PHP görsel işleme kitaplığı bulunamadı.'
            detail: 'Contao 4, görselleri işlemek için GD, Imagick ya da Gmagick eklentisine gerek duyar.'
        symlink:
            title: 'PHP symlink yöntemi kullanılamıyor ya da düzgün şekilde çalışmıyor.'
        session:
            title: 'PHP oturumu başlatılamadı.'
        memory_limit:
            title: 'PHP bellek sınırı yetersiz.'
            detail: 'PHP yapılandırmanız yalnızca {limit} bellek kullanımına (komut satırında) izin veriyor. Bu değer, Composer çalıştırmak için yetersiz ve bu sınır otomatik olarak artırılamadı. Destek almak için barındırma hizmeti sağlayıcınızla görüşün.'
        systempdir:
            title: 'Geçici sistem klasörüne yazılamadı.'
            detail: 'Bu sorun büyük olasılıkla barındırma hizmeti yapılandırmanızla ilgilidir. open_basedir tarafından geçici klasöre erişme izin verildiğinden ya da sys_temp_dir parametresinin doğru yapılandırıldığından emin olun.'
        zip:
            title: 'zip eklentisi ile unzip/7z komutlarının ikisi de eksik.'

    boot:
        composer:
            invalid: 'composer.json şema doğrulaması: {exception}'

    config:
        php_cli:
            not_found: 'Bu yolda geçerli bir PHP binary dosyası bulunamadı.'
            incompatible: 'Bu binary dosyası bir PHP {cli} sürümü. Ancak site sunucunuzun sürümü {web}.'
            error: 'PHP binary dosyası doğrulanırken sorun çıktı.'
        cloud:
            platform: 'Platform, composer.json içinden yapılandırılmamalıdır.'
            cache: 'Ön bellek özellikleri composer.json içinde yapılandırılmamalıdır.'

    task:
        setup_packages:
            title: 'Contao uygulaması kuruluyor'
        install_packages:
            title: 'Composer bağımlılıkları kuruluyor'
        update_packages:
            title: 'Paketler güncelleniyor'
        dump_autoload:
            title: 'Composer sınıf otomatik yükleyicisi indiriliyor'
        clear_cache:
            title: 'Composer ön belleği temizleniyor'
        rebuild_cache:
            title: 'Contao ön belleği yeniden oluşturuluyor'
        self_update:
            title: 'Contao Manager kendi kendine güncelleme'
        backup_create:
            title: 'Veri tabanı yedeği oluşturuluyor'
        backup_restore:
            title: 'Veri tabanı yedeği geri yükleniyor'

    taskoperation:
        self-update:
            detail: '{old} sürümünden {new} sürümüne güncelleniyor'
            success: '{new} sürümüne güncellendi'
        install-uploads:
            summary: 'Yüklemeler kuruluyor'
            console: '{package} ({version} sürümü) için [to packages/{name}] artifaktı kuruldu'
        remove-uploads:
            summary: 'Yüklemeler kaldırılıyor'
        remove-artifacts:
            summary: 'Yüklenmiş paketler kaldırılıyor'
        composer-install:
            retry: 'yeniden deneniyor {current}/{max}'
            nothing: 'Kurulacak ya da güncellenecek bir şey yok'
            result: '{installs} kuruldu, {updates} güncellendi, {removals} kaldırıldı'
        dump-autoload:
            result: '{count} sınıf içeren iyileştirilmiş otomatik yükleme dosyası üretildi'
        cloud:
            queued: 'Kuyrukta, yaklaşık {seconds} saniye içinde başlayacak (şu anda {workers} işlem üzerinde {jobs} görev yapılıyor)'
            processing: '{seconds} saniyedir işleniyor.'
            error: 'Bağımlılıklar çözümlenemedi'
            finished: '{seconds} saniyede tamamlandı. Bellek kullanımı: {memory} (en fazla: {peak}), süre: {time}.'

    upload:
        error:
            file: 'Dosya geçersiz ya da composer.json dosyasını içermiyor.'
            json: 'composer.json dosyasında geçerli bir JSON verisi bulunamadı.'
            schema: 'composer.json şeması doğrulanamadı.'
            partial: 'Dosya yüklemesi tamamlanamadı.'

    error:
        writable:
            root: 'Contao Manager "{path}" yolundaki kök klasöre yazamadı.'
            directory: 'Contao Manager "{path}" klasörünü oluşturamadı.'
            config-file: 'Contao Manager "{file}" dosyasına yapılandırmayı yazamadı.'
            detail: 'Sunucunuz doğru yapılandırılmamış gibi görünüyor. Contao kuracaksanız, lütfen site sunucunuzun kök belge klasörüne kurun. Yoksa dosya erişim izinlerinin doğru olduğundan emin olun. Bu sorunu nasıl düzelteceğinizden emin değilseniz, destek almak için barındırma hizmeti sağlayıcınızla görüşün.'
nl:
    integrity:
        allow_url_fopen:
            title: 'De PHP instelling "allow_url_fopen" is niet ingeschakeld op de server.'
        process:
            title: 'De PHP "proc_*" functies zijn niet beschikbaar op de server.'
            detail: 'De functies "proc_open", "proc_close", "proc_get_status" en "proc_terminate" zijn nodig om opdrachtregeltaken op de achtergrond uit te voeren. Neem contact op met uw hostingprovider waarom deze methode niet beschikbaar is; De Contao Manager wordt niet correct uitgevoerd zonder deze methode.'
        intl:
            title: 'De PHP Intl extensie is niet beschikbaar.'
            detail: 'Contao 4 vereist de Intl extension voor internationalisering.'
        openssl:
            title: 'De PHP OpenSSL extensie is niet beschikbaar.'
            detail: 'Contao Manager vereist de OpenSSL extensie om bestanden over versleutelde verbindingen (https) te downloaden.'
        dom:
            title: 'De PHP DOM extensie is niet beschikbaar.'
            detail: 'Contao 4 vereist de PHP DOM extensie om XML-documenten te parsen.'
        xmlreader:
            title: 'De PHP XML Reader extensie is niet beschikbaar.'
            detail: 'Contao 4 vereist de PHP XMLReader extensie om XML-documenten te parsen.'
        graphics_lib:
            title: 'Er is geen bibliotheek voor PHP-beeldverwerking beschikbaar.'
            detail: 'Contao 4 vereist ofwel de GD, Imagick of Gmagick-extensie om afbeeldingen te verwerken.'
        symlink:
            title: 'PHP-symlink methode is niet beschikbaar of werkt niet correct.'
        session:
            title: 'PHP-sessie kan niet worden gestart.'
        memory_limit:
            title: 'Limiet PHP-geheugen onvoldoende.'
            detail: 'Uw PHP-configuratie staat alleen {limit} geheugen toe (op de opdrachtregel). Dit is niet genoeg om Composer uit te voeren, het was niet mogelijk om deze limiet automatisch te verhogen. Neem contact op met uw hostingprovider voor ondersteuning.'
        systempdir:
            title: 'Tijdelijke systeem directory niet beschrijfbaar.'
            detail: 'Er is waarschijnlijk een probleem met uw hostingconfiguratie. Zorg ervoor dat open_basedir toegang geeft tot de tijdelijke directory, of dat sys_temp_dir correct is geconfigureerd.'
        zip:
            title: 'De commando''s voor de zip-extensie en unzip/7z ontbreken.'

    boot:
        composer:
            invalid: 'composer.json schema validatie: {exception}'

    config:
        php_cli:
            not_found: 'Dit pad bevat geen geldige PHP binary.'
            incompatible: 'Dit binary is een PHP versie {cli} maar uw webserver is versie {web}.'
            error: 'Fout bij het valideren van het PHP-binaire bestand.'
        cloud:
            platform: 'Platform mag niet geconfigureerd zijn in composer.json.'
            cache: 'Cache instellingen mogen niet geconfigureerd zijn in composer.json.'

    task:
        setup_packages:
            title: 'Contao-applicatie installeren'
        install_packages:
            title: 'Composer Afhankelijkheden Installeren'
        update_packages:
            title: 'Pakketten bijwerken'
        dump_autoload:
            title: 'Dumping Composer Class Autoloader'
        clear_cache:
            title: 'Composer Cache Wissen'
        rebuild_cache:
            title: 'Contao Cache opnieuw opbouwen'
        self_update:
            title: 'Contao Manager Zelf-update'
        backup_create:
            title: 'Databaseback-up maken'
        backup_restore:
            title: 'Databaseback-up herstellen'

    taskoperation:
        self-update:
            detail: 'Bijwerken van {old} naar {new}'
            success: 'Update naar {new}'
        install-uploads:
            summary: 'Uploads installeren'
            console: 'Artefact geïnstalleerd voor {package} (version {version}) [to packages/{name}]'
        remove-uploads:
            summary: 'Uploads verwijderen'
        remove-artifacts:
            summary: 'Geüploade pakketten verwijderen'
        composer-install:
            retry: '{current} / {max} opnieuw proberen'
            nothing: 'Niets om te installeren of bij te werken'
            result: '{installs} geïnstalleerd, {updates} bijgewerkt, {removals} verwijderd'
        dump-autoload:
            result: 'Gegenereerde geoptimaliseerde autoload-bestanden met {count} classes'
        cloud:
            queued: 'In de wachtrij, beginnend over ca. {seconds} seconden (momenteel {jobs} banen voor {workers} workers)'
            processing: 'Actief gedurende {seconds} seconden.'
            error: 'Het oplossen van afhankelijkheden is mislukt'
            finished: 'Voltooid in {seconds} seconden. Geheugengebruik: {memory} (piek: {peak}), tijd: {time}.'

    upload:
        error:
            file: 'Het bestand is ongeldig of bevat geen composer.json.'
            json: 'De composer.json bevat geen geldige JSON-gegevens.'
            schema: 'De validatie van het componer.json-schema is mislukt.'
            partial: 'Het uploaden van het bestand is niet voltooid.'

    error:
        writable:
            root: 'Contao Manager kon niet schrijven naar de hoofdmap op "{path}".'
            directory: 'Contao Manager kon de directory "{path}" niet aanmaken.'
            config-file: 'Contao Manager kon geen configuratiebestand naar "{file}" schrijven.'
            detail: 'Het lijkt erop dat uw server niet correct is geconfigureerd. Als u op het punt staat Contao te installeren, stel dan de DocumentRoot van uw webserver in. Zorg er anders voor dat de toegangsrechten voor bestanden correct zijn. Als u niet zeker weet hoe dit op te lossen neem dan contact op met uw hostingprovider voor ondersteuning.'
zh:
    integrity:
        allow_url_fopen:
            title: '服务器未启用PHP设置"allow_url_fopen"'
        process:
            title: ''
            detail: ''
        intl:
            title: 'PHP扩展Intl不可用'
            detail: 'Contao 4 系统需要使用PHP Intl扩展来进行国际化'
        openssl:
            title: 'PHP扩展OpenSSL不可用'
            detail: 'Contao Manager需要使用OpenSSL扩展来通过加密链接(https)下载文件。'
        dom:
            title: 'PHP DOM扩展不可用。'
            detail: 'Contao 4 需要 PHP DOM 扩展来解析XML文档。'
        xmlreader:
            title: 'The PHP XMLReader 扩展不可用。'
            detail: ''
        graphics_lib:
            title: '没有有效的PHP图片处理库，'
            detail: 'Contao 4 需要 GD, Imagick 或 Gmagick 扩展来处理图片。'
        symlink:
            title: 'PHP符号链接方法不可用或无法正常工作。'
        session:
            title: 'PHP session无法启动。'
        memory_limit:
            title: 'PHP内存限制不足'
            detail: '当前PHP配置仅允许 {limit} 内存 (在命令行中)。该内存设置无法满足运行Composer，该设置无法自动调整增加限制。请联系主机提供商提供相关支持。'
        systempdir:
            title: '系统临时目录无法写入'
            detail: '很有可能是主机的配置问题。请确保open_basedir允许访问临时目录，或者sys_temp_dir已正确配置。'
        zip:
            title: ''

    boot:
        composer:
            invalid: 'composer.json schema验证: {exception}'

    config:
        php_cli:
            not_found: '该路径没有包含有效的PHP二进制文件'
            incompatible: 'PHP二进制文件版本 {cli} 但是当前服务器版本为 {web}'
            error: ''
        cloud:
            platform: '不得在composer.json中配置平台。'
            cache: '不得在composer.json中配置缓存属性。'

    task:
        setup_packages:
            title: '安装Contao应用'
        install_packages:
            title: '正在安装Composer依赖'
        update_packages:
            title: '包更新中'
        dump_autoload:
            title: ''
        clear_cache:
            title: '正在清理Composer缓存'
        rebuild_cache:
            title: 'Contao 缓存重建中'
        self_update:
            title: ''
        backup_create:
            title: ''
        backup_restore:
            title: ''

    taskoperation:
        self-update:
            detail: '从 {old} 更新到 {new}'
            success: ''
        install-uploads:
            summary: ''
            console: '已安装的artifact类型 for {package} (版本 {version}) [to packages/{name}]'
        remove-uploads:
            summary: ''
        remove-artifacts:
            summary: ''
        composer-install:
            retry: ''
            nothing: ''
            result: ''
        dump-autoload:
            result: ''
        cloud:
            queued: ''
            processing: ''
            error: ''
            finished: ''

    upload:
        error:
            file: '文件无效或者没有包含composer.json。'
            json: 'composer.json没有包含有效的JSON数据。'
            schema: 'composer.json schema验证失败。'
            partial: '上传文件未完成。'

    error:
        writable:
            root: ''
            directory: ''
            config-file: ''
            detail: ''
<?php

declare (strict_types=1);
/*
 * This file is part of Contao Manager.
 *
 * (c) Contao Association
 *
 * @license LGPL-3.0-or-later
 */
namespace _ContaoManager\Contao\ManagerApi;

use _ContaoManager\Contao\ManagerApi\Command\AboutCommand;
use _ContaoManager\Contao\ManagerApi\Command\IntegrityCheckCommand;
use _ContaoManager\Contao\ManagerApi\Command\ProcessRunnerCommand;
use _ContaoManager\Contao\ManagerApi\Command\TaskAbortCommand;
use _ContaoManager\Contao\ManagerApi\Command\TaskDeleteCommand;
use _ContaoManager\Contao\ManagerApi\Command\TaskUpdateCommand;
use _ContaoManager\Contao\ManagerApi\Command\UpdateCommand;
use _ContaoManager\Symfony\Component\Console\Application;
use _ContaoManager\Symfony\Component\Console\Command\Command;
use _ContaoManager\Symfony\Component\Console\Input\InputInterface;
use _ContaoManager\Symfony\Component\Console\Input\InputOption;
use _ContaoManager\Symfony\Component\Console\Output\OutputInterface;
class ApiApplication extends Application
{
    private bool $commandsRegistered = \false;
    public function __construct(private readonly ApiKernel $kernel)
    {
        parent::__construct('Contao Manager', ApiKernel::MANAGER_VERSION);
        $this->getDefinition()->addOption(new InputOption('disable-events', null, InputOption::VALUE_NONE, 'Disables the event dispatcher.'));
    }
    /**
     * Gets the Kernel associated with this Console.
     */
    public function getKernel(): ApiKernel
    {
        return $this->kernel;
    }
    public function doRun(InputInterface $input, OutputInterface $output): int
    {
        $this->registerCommands();
        if ('self-update' !== $this->getCommandName($input) && !$input->hasParameterOption(['--disable-events'], \true)) {
            $this->setDispatcher($this->kernel->getContainer()->get('event_dispatcher'));
        }
        return (int) parent::doRun($input, $output);
    }
    protected function getDefaultCommands(): array
    {
        $commands = parent::getDefaultCommands();
        $commands[] = (new Command('composer'))->setDescription('Run Composer within Contao Manager');
        return $commands;
    }
    private function registerCommands(): void
    {
        if ($this->commandsRegistered) {
            return;
        }
        $this->commandsRegistered = \true;
        $this->kernel->boot();
        $container = $this->kernel->getContainer();
        $this->add($container->get(ProcessRunnerCommand::class)->setName('run'));
        $this->add($container->get(AboutCommand::class));
        $this->add($container->get(IntegrityCheckCommand::class));
        $this->add($container->get(TaskAbortCommand::class));
        $this->add($container->get(TaskDeleteCommand::class));
        $this->add($container->get(TaskUpdateCommand::class));
        $this->add($container->get(UpdateCommand::class));
        if ((!\Phar::running(\false) || $this->kernel->isDebug()) && $container->has('console.command_loader')) {
            $this->setCommandLoader($container->get('console.command_loader'));
        }
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Contao Manager.
 *
 * (c) Contao Association
 *
 * @license LGPL-3.0-or-later
 */
namespace _ContaoManager\Contao\ManagerApi\Tests\Composer;

use _ContaoManager\Contao\ManagerApi\Composer\CloudJob;
use _ContaoManager\PHPUnit\Framework\TestCase;
class CloudJobTest extends TestCase
{
    /**
     * @dataProvider waitingTime
     */
    public function testCalculatesTheWaitingTime(int $queuePosition, int $avgTime, int $workers, int $expected): void
    {
        $job = new CloudJob(['status' => CloudJob::STATUS_QUEUED, 'queuePosition' => $queuePosition, 'stats' => ['averageProcessingTimeInMs' => $avgTime * 1000, 'numberOfJobsInQueue' => $queuePosition, 'numberOfWorkers' => $workers]]);
        $this->assertSame($expected, $job->getWaitingTime());
    }
    public static function waitingTime(): iterable
    {
        yield [12, 30, 6, 60];
        yield [10, 10, 5, 20];
        yield [3, 25, 8, 9];
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Contao Manager.
 *
 * (c) Contao Association
 *
 * @license LGPL-3.0-or-later
 */
namespace _ContaoManager\Contao\ManagerApi\Tests\Controller;

use _ContaoManager\Contao\ManagerApi\Controller\LogController;
use _ContaoManager\PHPUnit\Framework\TestCase;
class LogPatternTest extends TestCase
{
    /**
     * @dataProvider logMessages
     */
    public function testLogPattern(string $line, string $datetime, string $channel, string $level, string $message, string $context, string $extra): void
    {
        $result = preg_match(LogController::MONOLOG_PATTERN, $line, $matches);
        $this->assertSame(1, $result);
        $this->assertSame($line, $matches[0]);
        $this->assertSame($datetime, $matches['datetime'], 'DateTime does not match');
        $this->assertSame($channel, $matches['channel'], 'Channel does not match');
        $this->assertSame($level, $matches['level'], 'Level does not match');
        $this->assertSame($message, $matches['message'], 'Message does not match');
        $this->assertSame($context, $matches['context'], 'Context does not match');
        $this->assertSame($extra, $matches['extra'], 'Extra does not match');
    }
    public static function logMessages(): iterable
    {
        yield ['[2024-08-20T00:41:04.411801+02:00] request.INFO: Matched route "tl_page.32". {"route":"tl_page.32","route_parameters":{"_controller":"Contao\FrontendIndex::renderPage","_scope":"frontend","_locale":"de","_format":"html","_canonical_route":"tl_page.32","pageModel":{"Contao\PageModel":[]},"_route":"tl_page.32","_route_object":{"Contao\CoreBundle\Routing\Page\PageRoute":[]}}} []', '2024-08-20T00:41:04.411801+02:00', 'request', 'INFO', 'Matched route "tl_page.32".', '{"route":"tl_page.32","route_parameters":{"_controller":"Contao\FrontendIndex::renderPage","_scope":"frontend","_locale":"de","_format":"html","_canonical_route":"tl_page.32","pageModel":{"Contao\PageModel":[]},"_route":"tl_page.32","_route_object":{"Contao\CoreBundle\Routing\Page\PageRoute":[]}}}', '[]'];
        yield ['[2024-08-20T00:00:05.476105+02:00] app.ERROR: Github\Exception\RuntimeException: Bad credentials in vendor/knplabs/github-api/lib/Github/HttpClient/Plugin/GithubExceptionThrower.php:137 Stack trace: #0 vendor/php-http/httplug/src/Promise/HttpFulfilledPromise.php(31): Github\HttpClient\Plugin\GithubExceptionThrower->Github\HttpClient\Plugin\{closure}(Object(Nyholm\Psr7\Response)) #1 vendor/knplabs/github-api/lib/Github/HttpClient/Plugin/GithubExceptionThrower.php(28): Http\Client\Promise\HttpFulfilledPromise->then(Object(Closure)) #2 vendor/php-http/client-common/src/PluginChain.php(44): Github\HttpClient\Plugin\GithubExceptionThrower->handleRequest(Object(Nyholm\Psr7\Request), Object(Closure), Object(Http\Client\Common\PluginChain)) #3 vendor/php-http/client-common/src/PluginChain.php(59): Http\Client\Common\PluginChain->Http\Client\Common\{closure}(Object(Nyholm\Psr7\Request)) #4 vendor/php-http/client-common/src/PluginClient.php(87): Http\Client\Common\PluginChain->__invoke(Object(Nyholm\Psr7\Request)) #5 vendor/php-http/client-common/src/HttpMethodsClient.php(148): Http\Client\Common\PluginClient->sendRequest(Object(Nyholm\Psr7\Request)) #6 vendor/php-http/client-common/src/HttpMethodsClient.php(107): Http\Client\Common\HttpMethodsClient->sendRequest(Object(Nyholm\Psr7\Request)) #7 vendor/php-http/client-common/src/HttpMethodsClient.php(55): Http\Client\Common\HttpMethodsClient->send(\'GET\', \'...\', Array, NULL) #8 vendor/knplabs/github-api/lib/Github/Api/AbstractApi.php(92): Http\Client\Common\HttpMethodsClient->get(\'...\', Array) #9 vendor/knplabs/github-api/lib/Github/Api/AcceptHeaderTrait.php(19): Github\Api\AbstractApi->get(\'...\', Array, Array) #10 vendor/knplabs/github-api/lib/Github/Api/Repo.php(150): Github\Api\Repo->get(\'...\') #11 src/Cron/GithubUpdater.php(34): Github\Api\Repo->show(\'foo\', \'core\') #12 src/Cron/GithubUpdater.php(24): App\Cron\GithubUpdater->addRepositoryData(Array) #13 vendor/contao/core-bundle/src/Cron/CronJob.php(44): App\Cron\GithubUpdater->__invoke(\'cli\') #14 vendor/contao/core-bundle/src/Cron/Cron.php(197): Contao\CoreBundle\Cron\CronJob->__invoke(\'cli\') #15 vendor/contao/core-bundle/src/Cron/Cron.php(182): Contao\CoreBundle\Cron\Cron->executeCrons(Array, \'cli\', Object(Closure)) #16 vendor/contao/core-bundle/src/Cron/Cron.php(97): Contao\CoreBundle\Cron\Cron->doRun(Array, \'cli\', false) #17 vendor/contao/core-bundle/src/Command/CronCommand.php(53): Contao\CoreBundle\Cron\Cron->run(\'cli\', false) #18 vendor/symfony/console/Command/Command.php(326): Contao\CoreBundle\Command\CronCommand->execute(Object(Symfony\Component\Console\Input\ArgvInput), Object(Symfony\Component\Console\Output\ConsoleOutput)) #19 vendor/symfony/console/Application.php(1096): Symfony\Component\Console\Command\Command->run(Object(Symfony\Component\Console\Input\ArgvInput), Object(Symfony\Component\Console\Output\ConsoleOutput)) #20 vendor/symfony/framework-bundle/Console/Application.php(126): Symfony\Component\Console\Application->doRunCommand(Object(Contao\CoreBundle\Command\CronCommand), Object(Symfony\Component\Console\Input\ArgvInput), Object(Symfony\Component\Console\Output\ConsoleOutput)) #21 vendor/symfony/console/Application.php(324): Symfony\Bundle\FrameworkBundle\Console\Application->doRunCommand(Object(Contao\CoreBundle\Command\CronCommand), Object(Symfony\Component\Console\Input\ArgvInput), Object(Symfony\Component\Console\Output\ConsoleOutput)) #22 vendor/symfony/framework-bundle/Console/Application.php(80): Symfony\Component\Console\Application->doRun(Object(Symfony\Component\Console\Input\ArgvInput), Object(Symfony\Component\Console\Output\ConsoleOutput)) #23 vendor/symfony/console/Application.php(175): Symfony\Bundle\FrameworkBundle\Console\Application->doRun(Object(Symfony\Component\Console\Input\ArgvInput), Object(Symfony\Component\Console\Output\ConsoleOutput)) #24 vendor/contao/manager-bundle/bin/contao-console(40): Symfony\Component\Console\Application->run(Object(Symfony\Component\Console\Input\ArgvInput)) #25 vendor/bin/contao-console(119): include(\'...\') #26 {main} [] []', '2024-08-20T00:00:05.476105+02:00', 'app', 'ERROR', 'Github\Exception\RuntimeException: Bad credentials in vendor/knplabs/github-api/lib/Github/HttpClient/Plugin/GithubExceptionThrower.php:137 Stack trace: #0 vendor/php-http/httplug/src/Promise/HttpFulfilledPromise.php(31): Github\HttpClient\Plugin\GithubExceptionThrower->Github\HttpClient\Plugin\{closure}(Object(Nyholm\Psr7\Response)) #1 vendor/knplabs/github-api/lib/Github/HttpClient/Plugin/GithubExceptionThrower.php(28): Http\Client\Promise\HttpFulfilledPromise->then(Object(Closure)) #2 vendor/php-http/client-common/src/PluginChain.php(44): Github\HttpClient\Plugin\GithubExceptionThrower->handleRequest(Object(Nyholm\Psr7\Request), Object(Closure), Object(Http\Client\Common\PluginChain)) #3 vendor/php-http/client-common/src/PluginChain.php(59): Http\Client\Common\PluginChain->Http\Client\Common\{closure}(Object(Nyholm\Psr7\Request)) #4 vendor/php-http/client-common/src/PluginClient.php(87): Http\Client\Common\PluginChain->__invoke(Object(Nyholm\Psr7\Request)) #5 vendor/php-http/client-common/src/HttpMethodsClient.php(148): Http\Client\Common\PluginClient->sendRequest(Object(Nyholm\Psr7\Request)) #6 vendor/php-http/client-common/src/HttpMethodsClient.php(107): Http\Client\Common\HttpMethodsClient->sendRequest(Object(Nyholm\Psr7\Request)) #7 vendor/php-http/client-common/src/HttpMethodsClient.php(55): Http\Client\Common\HttpMethodsClient->send(\'GET\', \'...\', Array, NULL) #8 vendor/knplabs/github-api/lib/Github/Api/AbstractApi.php(92): Http\Client\Common\HttpMethodsClient->get(\'...\', Array) #9 vendor/knplabs/github-api/lib/Github/Api/AcceptHeaderTrait.php(19): Github\Api\AbstractApi->get(\'...\', Array, Array) #10 vendor/knplabs/github-api/lib/Github/Api/Repo.php(150): Github\Api\Repo->get(\'...\') #11 src/Cron/GithubUpdater.php(34): Github\Api\Repo->show(\'foo\', \'core\') #12 src/Cron/GithubUpdater.php(24): App\Cron\GithubUpdater->addRepositoryData(Array) #13 vendor/contao/core-bundle/src/Cron/CronJob.php(44): App\Cron\GithubUpdater->__invoke(\'cli\') #14 vendor/contao/core-bundle/src/Cron/Cron.php(197): Contao\CoreBundle\Cron\CronJob->__invoke(\'cli\') #15 vendor/contao/core-bundle/src/Cron/Cron.php(182): Contao\CoreBundle\Cron\Cron->executeCrons(Array, \'cli\', Object(Closure)) #16 vendor/contao/core-bundle/src/Cron/Cron.php(97): Contao\CoreBundle\Cron\Cron->doRun(Array, \'cli\', false) #17 vendor/contao/core-bundle/src/Command/CronCommand.php(53): Contao\CoreBundle\Cron\Cron->run(\'cli\', false) #18 vendor/symfony/console/Command/Command.php(326): Contao\CoreBundle\Command\CronCommand->execute(Object(Symfony\Component\Console\Input\ArgvInput), Object(Symfony\Component\Console\Output\ConsoleOutput)) #19 vendor/symfony/console/Application.php(1096): Symfony\Component\Console\Command\Command->run(Object(Symfony\Component\Console\Input\ArgvInput), Object(Symfony\Component\Console\Output\ConsoleOutput)) #20 vendor/symfony/framework-bundle/Console/Application.php(126): Symfony\Component\Console\Application->doRunCommand(Object(Contao\CoreBundle\Command\CronCommand), Object(Symfony\Component\Console\Input\ArgvInput), Object(Symfony\Component\Console\Output\ConsoleOutput)) #21 vendor/symfony/console/Application.php(324): Symfony\Bundle\FrameworkBundle\Console\Application->doRunCommand(Object(Contao\CoreBundle\Command\CronCommand), Object(Symfony\Component\Console\Input\ArgvInput), Object(Symfony\Component\Console\Output\ConsoleOutput)) #22 vendor/symfony/framework-bundle/Console/Application.php(80): Symfony\Component\Console\Application->doRun(Object(Symfony\Component\Console\Input\ArgvInput), Object(Symfony\Component\Console\Output\ConsoleOutput)) #23 vendor/symfony/console/Application.php(175): Symfony\Bundle\FrameworkBundle\Console\Application->doRun(Object(Symfony\Component\Console\Input\ArgvInput), Object(Symfony\Component\Console\Output\ConsoleOutput)) #24 vendor/contao/manager-bundle/bin/contao-console(40): Symfony\Component\Console\Application->run(Object(Symfony\Component\Console\Input\ArgvInput)) #25 vendor/bin/contao-console(119): include(\'...\') #26 {main}', '[]', '[]'];
        yield ['[2024-08-20T06:22:09.276738+02:00] php.WARNING: Warning: Undefined array key "MSC" {"exception":"[object] (ErrorException(code: 0): Warning: Undefined array key \"MSC\" at vendor/contao/newsletter-bundle/contao/modules/ModuleSubscribe.php:95)"} {"request_uri":"https://www.example.org/","request_method":"GET"}', '2024-08-20T06:22:09.276738+02:00', 'php', 'WARNING', 'Warning: Undefined array key "MSC"', '{"exception":"[object] (ErrorException(code: 0): Warning: Undefined array key \"MSC\" at vendor/contao/newsletter-bundle/contao/modules/ModuleSubscribe.php:95)"}', '{"request_uri":"https://www.example.org/","request_method":"GET"}'];
        yield 'Insert tag in log message' => ['[2024-08-20T00:41:04.809596+02:00] contao.error.ERROR: Unknown insert tag {{foo::bar}} on page https://www.example.org/ [] {"request_uri":"https://www.example.org/","request_method":"GET","contao":{"Contao\CoreBundle\Monolog\ContaoContext":"{\"func\":\"Contao\\\\InsertTags::executeReplace\",\"action\":\"ERROR\",\"username\":\"N\/A\",\"browser\":\"Mozilla\/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit\/537.36 (KHTML, like Gecko) Chrome\/120.0.0.0 Safari\/537.36\",\"uri\":\"https:\/\/www.example.org\/\",\"pageId\":32}"}}', '2024-08-20T00:41:04.809596+02:00', 'contao.error', 'ERROR', 'Unknown insert tag {{foo::bar}} on page https://www.example.org/', '[]', '{"request_uri":"https://www.example.org/","request_method":"GET","contao":{"Contao\CoreBundle\Monolog\ContaoContext":"{\"func\":\"Contao\\\\InsertTags::executeReplace\",\"action\":\"ERROR\",\"username\":\"N\/A\",\"browser\":\"Mozilla\/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit\/537.36 (KHTML, like Gecko) Chrome\/120.0.0.0 Safari\/537.36\",\"uri\":\"https:\/\/www.example.org\/\",\"pageId\":32}"}}'];
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Contao Manager.
 *
 * (c) Contao Association
 *
 * @license LGPL-3.0-or-later
 */
namespace _ContaoManager\Contao\ManagerApi\Controller;

use _ContaoManager\Contao\ManagerApi\HttpKernel\ApiProblemResponse;
use _ContaoManager\Crell\ApiProblem\ApiProblem;
use _ContaoManager\Symfony\Component\Filesystem\Filesystem;
use _ContaoManager\Symfony\Component\HttpFoundation\Request;
use _ContaoManager\Symfony\Component\HttpFoundation\Response;
use _ContaoManager\Symfony\Component\HttpKernel\KernelInterface;
use _ContaoManager\Symfony\Component\Routing\Attribute\Route;
use _ContaoManager\Symfony\Component\Security\Http\Attribute\IsGranted;
#[Route(path: '/files/{file}', methods: ['GET', 'PUT'])]
#[IsGranted('ROLE_ADMIN')]
class FileController
{
    private const ALLOWED_FILES = ['composer.json', 'composer.lock'];
    public function __construct(private readonly KernelInterface $kernel, private readonly Filesystem $filesystem)
    {
    }
    public function __invoke(Request $request): Response
    {
        if (!\in_array($request->attributes->get('file'), self::ALLOWED_FILES, \true)) {
            return new ApiProblemResponse((new ApiProblem())->setStatus(Response::HTTP_FORBIDDEN));
        }
        $file = $this->kernel->getProjectDir() . '/' . $request->attributes->get('file');
        if ($request->isMethod('PUT')) {
            $this->filesystem->dumpFile($file, $request->getContent());
        } elseif (!$this->filesystem->exists($file)) {
            return new Response('', Response::HTTP_NO_CONTENT);
        }
        return new Response(file_get_contents($file));
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Contao Manager.
 *
 * (c) Contao Association
 *
 * @license LGPL-3.0-or-later
 */
namespace _ContaoManager\Contao\ManagerApi\Controller;

use _ContaoManager\Contao\ManagerApi\Config\UserConfig;
use _ContaoManager\Contao\ManagerApi\Security\User;
use _ContaoManager\OTPHP\Factory;
use _ContaoManager\OTPHP\TOTP;
use _ContaoManager\Symfony\Bundle\SecurityBundle\Security;
use _ContaoManager\Symfony\Component\HttpFoundation\Exception\BadRequestException;
use _ContaoManager\Symfony\Component\HttpFoundation\JsonResponse;
use _ContaoManager\Symfony\Component\HttpFoundation\Request;
use _ContaoManager\Symfony\Component\HttpFoundation\Response;
use _ContaoManager\Symfony\Component\HttpKernel\Exception\BadRequestHttpException;
use _ContaoManager\Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
use _ContaoManager\Symfony\Component\HttpKernel\Exception\ServiceUnavailableHttpException;
use _ContaoManager\Symfony\Component\HttpKernel\Exception\UnprocessableEntityHttpException;
use _ContaoManager\Symfony\Component\PasswordHasher\Hasher\PasswordHasherFactoryInterface;
use _ContaoManager\Symfony\Component\Routing\Attribute\Route;
use _ContaoManager\Symfony\Component\Routing\Generator\UrlGeneratorInterface;
use _ContaoManager\Symfony\Component\Security\Core\Exception\AccessDeniedException;
use _ContaoManager\Symfony\Component\Security\Http\Attribute\IsGranted;
/**
 * Controller to handle users.
 */
class UserController
{
    public function __construct(private readonly UserConfig $config, private readonly UrlGeneratorInterface $urlGenerator, private readonly Security $security, private readonly PasswordHasherFactoryInterface $passwordHasherFactory)
    {
    }
    /**
     * Returns a list of users in the configuration file.
     */
    #[Route(path: '/users', methods: ['GET'])]
    #[IsGranted('IS_AUTHENTICATED_FULLY')]
    public function listUsers(): Response
    {
        if (!$this->security->isGranted('ROLE_ADMIN')) {
            $username = $this->security->getUser()?->getUserIdentifier();
            $user = $this->config->getUser($username);
            return $this->getUserResponse([$user]);
        }
        return $this->getUserResponse($this->config->getUsers());
    }
    /**
     * Adds a new user to the configuration file.
     */
    #[Route(path: '/users', methods: ['POST'])]
    #[IsGranted('ROLE_ADMIN')]
    public function createUser(Request $request): Response
    {
        $user = $this->createUserFromRequest($request);
        if ($this->config->hasUser($user->getUserIdentifier())) {
            throw new BadRequestHttpException(\sprintf('User "%s" already exists.', $user->getUserIdentifier()));
        }
        $this->config->addUser($user);
        return $this->getUserResponse($user, Response::HTTP_CREATED, \true);
    }
    /**
     * Returns user data from the configuration file.
     */
    #[Route(path: '/users/{username}', name: 'user_get', methods: ['GET'])]
    #[IsGranted('IS_AUTHENTICATED_FULLY')]
    public function retrieveUser(string $username): Response
    {
        $this->denyAccessUnlessUserOrAdmin($username);
        $user = $this->config->getUser($username);
        if (null === $user) {
            throw new NotFoundHttpException(\sprintf('User "%s" was not found.', $username));
        }
        return $this->getUserResponse($user);
    }
    /**
     * Replaces user data in the configuration file.
     */
    #[Route(path: '/users/{username}', methods: ['PUT'])]
    #[IsGranted('IS_AUTHENTICATED_FULLY')]
    public function replaceUser(string $username, Request $request): Response
    {
        $this->denyAccessUnlessUserOrAdmin($username);
        $user = $this->createUserFromRequest($request);
        if (!$this->config->hasUser($user->getUserIdentifier())) {
            throw new NotFoundHttpException(\sprintf('User "%s" does not exist.', $user->getUserIdentifier()));
        }
        $this->config->replaceUser($user);
        return $this->getUserResponse($user, Response::HTTP_OK, \true);
    }
    /**
     * Deletes a user from the configuration file.
     */
    #[Route(path: '/users/{username}', methods: ['DELETE'])]
    #[IsGranted('ROLE_ADMIN')]
    public function deleteUser(string $username): Response
    {
        $user = $this->config->getUser($username);
        if (null === $user) {
            throw new NotFoundHttpException(\sprintf('User "%s" was not found.', $username));
        }
        $this->config->deleteUser($username);
        return $this->getUserResponse($user);
    }
    #[Route(path: '/users/{username}/password', methods: ['PUT'])]
    #[IsGranted('IS_AUTHENTICATED_FULLY')]
    public function setPassword(string $username, Request $request): Response
    {
        $this->denyAccessUnlessUser($username);
        $user = $this->config->getUser($username);
        if (null === $user) {
            throw new NotFoundHttpException(\sprintf('User "%s" does not exist.', $username));
        }
        if ($user->getPasskey()) {
            throw new ServiceUnavailableHttpException('Cannot change password of a user with a Passkey.');
        }
        $currentPassword = $request->request->get('current_password');
        $newPassword = $request->request->get('new_password');
        if (!$currentPassword || !$newPassword) {
            throw new BadRequestHttpException('Invalid payload.');
        }
        $isPasswordValid = $this->passwordHasherFactory->getPasswordHasher($user)->verify($user->getPassword(), $currentPassword);
        if (!$isPasswordValid) {
            throw new UnprocessableEntityHttpException('Current password is not valid.');
        }
        $this->config->updateUser($username, ['password' => $newPassword]);
        return new JsonResponse();
    }
    #[Route(path: '/users/{username}/totp', methods: ['GET'])]
    #[IsGranted('IS_AUTHENTICATED_FULLY')]
    public function getTOTP(string $username): Response
    {
        $this->denyAccessUnlessUser($username);
        $user = $this->config->getUser($username);
        if (null === $user) {
            throw new NotFoundHttpException(\sprintf('User "%s" does not exist.', $username));
        }
        if ($user->getPasskey()) {
            throw new ServiceUnavailableHttpException('Cannot configure TOTP of a user with a Passkey.');
        }
        if (null !== $user->getTotpSecret()) {
            throw new BadRequestException('TOTP already configured.');
        }
        $totp = TOTP::generate();
        $totp->setLabel($username);
        return new JsonResponse(['provisioning_uri' => $totp->getProvisioningUri()]);
    }
    #[Route(path: '/users/{username}/totp', methods: ['PUT'])]
    #[IsGranted('IS_AUTHENTICATED_FULLY')]
    public function setupTotp(string $username, Request $request): Response
    {
        $this->denyAccessUnlessUser($username);
        $user = $this->config->getUser($username);
        if (null === $user) {
            throw new NotFoundHttpException(\sprintf('User "%s" does not exist.', $username));
        }
        if ($user->getPasskey()) {
            throw new ServiceUnavailableHttpException('Cannot configure TOTP of a user with a Passkey.');
        }
        if (null !== $user->getTotpSecret()) {
            throw new AccessDeniedException('TOTP already configured.');
        }
        try {
            $totp = Factory::loadFromProvisioningUri($request->request->get('provisioning_uri'));
        } catch (\Exception) {
            throw new BadRequestHttpException('Invalid provisioning_uri');
        }
        if (!$totp instanceof TOTP) {
            throw new BadRequestHttpException('Invalid provisioning_uri');
        }
        if (!$totp->verify($request->request->get('totp'))) {
            throw new UnprocessableEntityHttpException('Invalid TOTP');
        }
        $this->config->updateUser($username, ['totp_secret' => $totp->getSecret()]);
        return new JsonResponse(null, Response::HTTP_CREATED);
    }
    #[Route(path: '/users/{username}/totp', methods: ['DELETE'])]
    #[IsGranted('IS_AUTHENTICATED_FULLY')]
    public function deleteTotp(string $username, Request $request): Response
    {
        $this->denyAccessUnlessUser($username);
        $user = $this->config->getUser($username);
        if (null === $user) {
            throw new NotFoundHttpException(\sprintf('User "%s" does not exist.', $username));
        }
        if ($user->getPasskey()) {
            throw new ServiceUnavailableHttpException('Cannot configure TOTP of a user with a Passkey.');
        }
        if (null === $user->getTotpSecret()) {
            throw new NotFoundHttpException('TOTP not configured.');
        }
        try {
            $totp = TOTP::createFromSecret($user->getTotpSecret());
        } catch (\Exception) {
            throw new \RuntimeException('TOTP error.');
        }
        if (!$totp->verify($request->request->getString('totp'))) {
            throw new UnprocessableEntityHttpException('Invalid TOTP');
        }
        $this->config->updateUser($username, ['totp_secret' => null]);
        return new JsonResponse();
    }
    /**
     * Returns a list of tokens of a user in the configuration file.
     */
    #[Route(path: '/users/{username}/tokens', methods: ['GET'])]
    #[IsGranted('IS_AUTHENTICATED_FULLY')]
    public function listTokens(string $username): Response
    {
        $this->denyAccessUnlessUserOrAdmin($username);
        $tokens = array_filter($this->config->getTokens(), static fn($token): bool => ($token['username'] ?? null) === $username);
        return new JsonResponse($tokens);
    }
    /**
     * Adds a new token for a user to the configuration file.
     *
     * For adding a new token, a user does not have to be fully authenticated. We
     * allow creating a token if
     *  - the user is admin or the current user
     *  - the requested scope is allowed for the current user
     * This essentially means the current user can create a new token for itself with less
     * or the same privileges, but never with higher privileges or for another user.
     */
    #[Route(path: '/users/{username}/tokens', methods: ['POST'])]
    public function createToken(string $username, Request $request): Response
    {
        $this->denyAccessUnlessUserOrAdmin($username);
        if (!$this->config->hasUser($username)) {
            throw new BadRequestHttpException(\sprintf('User "%s" does not exists.', $username));
        }
        $clientId = $request->request->get('client_id');
        $scope = $request->request->get('scope');
        $oneTimeToken = 'one-time' === $request->request->get('grant_type');
        if (!$clientId || !$scope) {
            throw new BadRequestHttpException('Invalid payload for OAuth token.');
        }
        $this->denyAccessUnlessGranted('ROLE_' . strtoupper($scope));
        $token = $this->config->createToken($username, $clientId, $scope, $oneTimeToken);
        if ($oneTimeToken) {
            $token['url'] = $request->getUriForPath('/#?token=' . $token['token']);
        }
        return new JsonResponse($token, Response::HTTP_CREATED);
    }
    /**
     * Returns token data of a user from the configuration file.
     */
    #[Route(path: '/users/{username}/tokens/{id}', methods: ['GET'])]
    #[IsGranted('IS_AUTHENTICATED_FULLY')]
    public function retrieveToken(string $username, string $id): Response
    {
        $this->denyAccessUnlessUserOrAdmin($username);
        $payload = $this->config->getToken($id);
        if (null === $payload || $payload['username'] !== $username) {
            throw new NotFoundHttpException(\sprintf('Token with ID "%s" was not found.', $id));
        }
        return new JsonResponse($payload);
    }
    /**
     * Deletes a token from the configuration file.
     */
    #[Route(path: '/users/{username}/tokens/{id}', methods: ['DELETE'])]
    #[IsGranted('IS_AUTHENTICATED_FULLY')]
    public function deleteToken(string $username, string $id): Response
    {
        $this->denyAccessUnlessUserOrAdmin($username);
        $payload = $this->config->getToken($id);
        if (null === $payload || $payload['username'] !== $username) {
            throw new NotFoundHttpException(\sprintf('Token "%s" was not found.', $id));
        }
        $this->config->deleteToken($id);
        return new JsonResponse($payload);
    }
    /**
     * Adds an invitation to the configuration file.
     */
    #[Route(path: '/invitations', methods: ['POST'])]
    #[IsGranted('ROLE_ADMIN')]
    public function inviteUser(Request $request): Response
    {
        $token = $this->config->createInvitation($request->request->get('scope'));
        $token['url'] = $request->getUriForPath('/#?invitation=' . $token['token']);
        return new JsonResponse($token, Response::HTTP_CREATED);
    }
    /**
     * Creates a response for given user information.
     *
     * @param User|array<User> $user
     */
    private function getUserResponse(User|array $user, int $status = Response::HTTP_OK, bool $addLocation = \false): Response
    {
        $response = new JsonResponse($this->convertToJson($user), $status);
        if ($addLocation && $user instanceof User) {
            $response->headers->set('Location', $this->urlGenerator->generate('user_get', ['username' => $user->getUserIdentifier()]));
        }
        return $response;
    }
    /**
     * Converts a user to JSON representation.
     *
     * @param array<User>|User $user
     */
    private function convertToJson(User|array $user): array
    {
        if ($user instanceof User) {
            $json = ['username' => $user->getUserIdentifier(), 'scope' => $user->getScope(), 'passkey' => $user->getPasskey()];
            if ($user->getPasskey()) {
                $json['passkey'] = \true;
            } else {
                $json['totp_enabled'] = (bool) $user->getTotpSecret();
            }
            return $json;
        }
        foreach ($user as $k => $item) {
            $user[$k] = $this->convertToJson($item);
        }
        return $user;
    }
    /**
     * Creates and returns a new user from request data.
     *
     * @throws BadRequestHttpException
     */
    private function createUserFromRequest(Request $request): User
    {
        $username = $request->request->get('username', '');
        $password = $request->request->get('password', '');
        $scope = $request->request->get('scope');
        if ('' === $username || \strlen($password) < 8) {
            throw new BadRequestHttpException('Username or password invalid.');
        }
        if (!\in_array($scope, User::SCOPES, \true)) {
            throw new BadRequestHttpException('Only the following "scope" is required: ' . implode(', ', User::SCOPES));
        }
        return $this->config->createUser($username, $password, $scope);
    }
    private function denyAccessUnlessUser(string $username, string $message = 'Access Denied.'): void
    {
        if ($username !== $this->security->getUser()?->getUserIdentifier()) {
            throw new AccessDeniedException($message);
        }
    }
    private function denyAccessUnlessUserOrAdmin(string $username, string $message = 'Access Denied.'): void
    {
        if ($username !== $this->security->getUser()?->getUserIdentifier()) {
            $this->denyAccessUnlessGranted('ROLE_ADMIN', null, $message);
        }
    }
    private function denyAccessUnlessGranted(mixed $attribute, mixed $subject = null, string $message = 'Access Denied.'): void
    {
        if (!$this->security->isGranted($attribute, $subject)) {
            $exception = new AccessDeniedException($message);
            $exception->setAttributes([$attribute]);
            $exception->setSubject($subject);
            throw $exception;
        }
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Contao Manager.
 *
 * (c) Contao Association
 *
 * @license LGPL-3.0-or-later
 */
namespace _ContaoManager\Contao\ManagerApi\Controller;

use _ContaoManager\Contao\ManagerApi\ApiKernel;
use _ContaoManager\Symfony\Component\Filesystem\Filesystem;
use _ContaoManager\Symfony\Component\Finder\Finder;
use _ContaoManager\Symfony\Component\Finder\SplFileInfo;
use _ContaoManager\Symfony\Component\HttpFoundation\BinaryFileResponse;
use _ContaoManager\Symfony\Component\HttpFoundation\JsonResponse;
use _ContaoManager\Symfony\Component\HttpFoundation\Request;
use _ContaoManager\Symfony\Component\HttpFoundation\Response;
use _ContaoManager\Symfony\Component\HttpKernel\Exception\BadRequestHttpException;
use _ContaoManager\Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
use _ContaoManager\Symfony\Component\Routing\Attribute\Route;
use _ContaoManager\Symfony\Component\Security\Http\Attribute\IsGranted;
/**
 * Controller to handle log files.
 */
class LogController
{
    public const MONOLOG_PATTERN = '/^\[(?<datetime>\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d+.*)\] (?<channel>[\w-]+(?:\.[\w-]+)?)\.(?<level>\w+): (?<message>.+)(?: (?<context>(?:\[.*?\]|\{.*?\})))(?: (?<extra>(?:\[.*\]|\{.*\})))\s{0,2}$/';
    public function __construct(private readonly ApiKernel $kernel, private readonly Filesystem $filesystem)
    {
    }
    #[Route(path: '/logs', methods: ['GET'])]
    #[IsGranted('ROLE_READ')]
    public function listFiles(): Response
    {
        if (!$this->filesystem->exists($this->kernel->getProjectDir() . '/var/logs')) {
            return new JsonResponse([]);
        }
        /** @var Finder $finder */
        $finder = Finder::create()->depth(0)->files()->ignoreDotFiles(\true)->name('*.log')->sortByName(\true)->in($this->kernel->getProjectDir() . '/var/logs');
        $files = [];
        foreach ($finder as $file) {
            $files[] = ['name' => $this->getFilenameWithoutExtension($file), 'mtime' => \DateTime::createFromFormat('U', (string) $file->getMTime())->format(\DateTime::ATOM), 'size' => $file->getSize(), 'lines' => $this->countLines(new \SplFileObject((string) $file))];
        }
        // Reverse files order to sort by date descending
        return new JsonResponse(array_reverse($files));
    }
    #[Route(path: '/logs/{filename}', methods: ['GET'])]
    #[IsGranted('ROLE_READ')]
    public function retrieveFile(string $filename, Request $request): Response
    {
        $file = $this->getFile($filename);
        if ('json' === $request->getPreferredFormat()) {
            return $this->parseJson($file, $request);
        }
        $response = new BinaryFileResponse($file);
        $response->headers->set('Content-Type', 'text/plain');
        return $response;
    }
    #[Route(path: '/logs/{filename}', methods: ['DELETE'])]
    #[IsGranted('ROLE_ADMIN')]
    public function deleteFile(string $filename): Response
    {
        $file = $this->getFile($filename);
        $this->filesystem->remove($file->getPathname());
        return new Response('', Response::HTTP_NO_CONTENT);
    }
    /**
     * Gets absolute path for filename and checks for security and if file exists.
     */
    private function getFile(string $filename): \SplFileObject
    {
        if (str_contains($filename, '/')) {
            throw new BadRequestHttpException(\sprintf('"%s" is not a valid file name.', $filename));
        }
        $path = $this->kernel->getProjectDir() . '/var/logs/' . $filename . '.log';
        if (!is_file($path)) {
            throw new NotFoundHttpException(\sprintf('Log file "%s" does not exist.', $filename));
        }
        return new \SplFileObject($path);
    }
    private function parseJson(\SplFileObject $file, Request $request): JsonResponse
    {
        $file->setFlags(\SplFileObject::DROP_NEW_LINE);
        $content = [];
        $skipLastLine = \false;
        $total = $this->countLines($file, $skipLastLine);
        $limit = $request->query->getInt('limit', $total);
        $offset = $request->query->getInt('offset');
        $channels = $request->query->has('channels') ? explode(',', $request->query->get('channel')) : null;
        $levels = $request->query->has('levels') ? explode(',', $request->query->get('levels')) : null;
        if ($offset) {
            $file->seek($offset);
        }
        while (!$file->eof() && $limit > 0) {
            if ($skipLastLine && $file->key() === $total) {
                break;
            }
            if (null !== $line = $this->parseJsonLine($file->fgets(), $channels, $levels)) {
                $content[] = $line;
            }
            --$limit;
        }
        return new JsonResponse(['name' => $this->getFilenameWithoutExtension($file), 'mtime' => \DateTime::createFromFormat('U', (string) $file->getMTime())->format(\DateTime::ATOM), 'size' => $file->getSize(), 'lines' => $total, 'content' => $content]);
    }
    private function parseJsonLine(string $line, array|null $channels = null, array|null $levels = null): array|string|null
    {
        if (!preg_match(self::MONOLOG_PATTERN, $line, $matches)) {
            return $line;
        }
        if ($channels && !\in_array($matches['channel'], $channels, \true)) {
            return null;
        }
        if ($levels && !\in_array($matches['level'], $levels, \true)) {
            return null;
        }
        $matches['context'] = json_decode(trim($matches['context']), \true);
        $matches['extra'] = json_decode(trim($matches['extra']), \true);
        return array_intersect_key($matches, array_flip(['datetime', 'channel', 'level', 'message', 'context', 'extra']));
    }
    private function countLines(\SplFileObject $file, bool &$skipLastLine = \false): int
    {
        $skipLastLine = \false;
        $file->seek(\PHP_INT_MAX);
        $lines = $file->key() + 1;
        $file->seek($file->key());
        if (empty($file->current())) {
            $skipLastLine = \true;
            --$lines;
        }
        $file->rewind();
        return $lines;
    }
    /**
     * We use the file name without extension as REST object name, because some
     * hosters block *.log files for security reasons.
     *
     * @param SplFileInfo|\SplFileObject $file
     */
    private function getFilenameWithoutExtension($file): string
    {
        return pathinfo($file->getFilename(), \PATHINFO_FILENAME);
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Contao Manager.
 *
 * (c) Contao Association
 *
 * @license LGPL-3.0-or-later
 */
namespace _ContaoManager\Contao\ManagerApi\Controller\Config;

use _ContaoManager\Contao\ManagerApi\Config\AuthConfig;
use _ContaoManager\Symfony\Component\HttpFoundation\JsonResponse;
use _ContaoManager\Symfony\Component\HttpFoundation\Request;
use _ContaoManager\Symfony\Component\HttpFoundation\Response;
use _ContaoManager\Symfony\Component\HttpKernel\Exception\BadRequestHttpException;
use _ContaoManager\Symfony\Component\Routing\Attribute\Route;
use _ContaoManager\Symfony\Component\Security\Http\Attribute\IsGranted;
#[Route(path: '/config/auth', methods: ['GET', 'PUT', 'PATCH'])]
#[IsGranted('ROLE_INSTALL')]
class AuthController extends AbstractConfigController
{
    public function __construct(AuthConfig $config)
    {
        parent::__construct($config);
    }
    #[Route(path: '/config/auth/github-oauth', methods: ['PUT'])]
    #[IsGranted('ROLE_INSTALL')]
    public function putGithubToken(Request $request): Response
    {
        if (!$this->config instanceof AuthConfig || !$request->request->has('token')) {
            throw new BadRequestHttpException('GitHub token could not be stored.');
        }
        $this->config->setGithubToken($request->request->get('token'));
        return new JsonResponse($this->config->get('github-oauth'));
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Contao Manager.
 *
 * (c) Contao Association
 *
 * @license LGPL-3.0-or-later
 */
namespace _ContaoManager\Contao\ManagerApi\Controller\Config;

use _ContaoManager\Contao\ManagerApi\Config\AbstractConfig;
use _ContaoManager\Symfony\Component\HttpFoundation\JsonResponse;
use _ContaoManager\Symfony\Component\HttpFoundation\Request;
use _ContaoManager\Symfony\Component\HttpFoundation\Response;
abstract class AbstractConfigController
{
    public function __construct(protected AbstractConfig $config)
    {
    }
    public function __invoke(Request $request): Response
    {
        match ($request->getMethod()) {
            'PUT' => $this->config->replace($request->request->all()),
            'PATCH' => $this->config->add($request->request->all()),
            default => new JsonResponse($this->config->all()),
        };
        return new JsonResponse($this->config->all());
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Contao Manager.
 *
 * (c) Contao Association
 *
 * @license LGPL-3.0-or-later
 */
namespace _ContaoManager\Contao\ManagerApi\Controller\Config;

use _ContaoManager\Contao\ManagerApi\Config\ComposerConfig;
use _ContaoManager\Symfony\Component\Routing\Attribute\Route;
use _ContaoManager\Symfony\Component\Security\Http\Attribute\IsGranted;
#[Route(path: '/config/composer', methods: ['GET', 'PUT', 'PATCH'])]
#[IsGranted('ROLE_INSTALL')]
class ComposerController extends AbstractConfigController
{
    public function __construct(ComposerConfig $config)
    {
        parent::__construct($config);
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Contao Manager.
 *
 * (c) Contao Association
 *
 * @license LGPL-3.0-or-later
 */
namespace _ContaoManager\Contao\ManagerApi\Controller\Config;

use _ContaoManager\Contao\ManagerApi\Config\ManagerConfig;
use _ContaoManager\Symfony\Component\Routing\Attribute\Route;
use _ContaoManager\Symfony\Component\Security\Http\Attribute\IsGranted;
#[Route(path: '/config/manager', methods: ['GET', 'PUT', 'PATCH'])]
#[IsGranted('ROLE_INSTALL')]
class ManagerController extends AbstractConfigController
{
    public function __construct(ManagerConfig $config)
    {
        parent::__construct($config);
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Contao Manager.
 *
 * (c) Contao Association
 *
 * @license LGPL-3.0-or-later
 */
namespace _ContaoManager\Contao\ManagerApi\Controller;

use _ContaoManager\Contao\ManagerApi\HttpKernel\ApiProblemResponse;
use _ContaoManager\Contao\ManagerApi\Task\TaskManager;
use _ContaoManager\Contao\ManagerApi\Task\TaskStatus;
use _ContaoManager\Crell\ApiProblem\ApiProblem;
use _ContaoManager\Symfony\Component\HttpFoundation\JsonResponse;
use _ContaoManager\Symfony\Component\HttpFoundation\Request;
use _ContaoManager\Symfony\Component\HttpFoundation\Response;
use _ContaoManager\Symfony\Component\HttpKernel\Exception\BadRequestHttpException;
use _ContaoManager\Symfony\Component\Routing\Attribute\Route;
use _ContaoManager\Symfony\Component\Security\Http\Attribute\IsGranted;
#[Route(path: '/task', methods: ['GET', 'PUT', 'PATCH', 'DELETE'])]
#[IsGranted('ROLE_UPDATE')]
class TaskController
{
    public function __construct(private readonly TaskManager $taskManager)
    {
    }
    public function __invoke(Request $request): Response
    {
        return match ($request->getMethod()) {
            'GET' => $this->getTask(),
            'PUT' => $this->putTask($request),
            'PATCH' => $this->patchTask($request),
            'DELETE' => $this->deleteTask(),
            default => new Response('', Response::HTTP_METHOD_NOT_ALLOWED),
        };
    }
    private function getTask(): Response
    {
        return $this->getResponse($this->taskManager->updateTask());
    }
    private function putTask(Request $request): Response
    {
        if ($this->taskManager->hasTask()) {
            throw new BadRequestHttpException('A task is already active');
        }
        $name = $request->request->get('name');
        $config = $request->request->all('config');
        if (empty($name) || !\is_array($config)) {
            throw new BadRequestHttpException('Invalid task data');
        }
        return $this->getResponse($this->taskManager->createTask($name, $config));
    }
    private function patchTask(Request $request): Response
    {
        if (!$this->taskManager->hasTask()) {
            throw new BadRequestHttpException('No active task found.');
        }
        if (TaskStatus::STATUS_ABORTING === $request->request->get('status')) {
            return $this->getResponse($this->taskManager->abortTask());
        }
        if (TaskStatus::STATUS_ACTIVE === $request->request->get('status')) {
            return $this->getResponse($this->taskManager->updateTask(\true));
        }
        throw new BadRequestHttpException('Unsupported task status');
    }
    private function deleteTask(): Response
    {
        if (!$this->taskManager->hasTask()) {
            return $this->getResponse();
        }
        try {
            return $this->getResponse($this->taskManager->deleteTask());
        } catch (\RuntimeException $e) {
            return new ApiProblemResponse((new ApiProblem($e->getMessage()))->setStatus(Response::HTTP_FORBIDDEN));
        }
    }
    private function getResponse(TaskStatus|null $status = null): Response
    {
        if (!$status instanceof TaskStatus) {
            return new Response('', Response::HTTP_NO_CONTENT);
        }
        $json = $status->jsonSerialize();
        try {
            return new JsonResponse($json);
        } catch (\InvalidArgumentException) {
            $json['console'] = utf8_encode((string) $json['console']);
            foreach ($json['operations'] as &$operation) {
                try {
                    new JsonResponse($operation);
                } catch (\InvalidArgumentException) {
                    $operation['console'] = utf8_encode((string) $operation['console']);
                }
            }
            return new JsonResponse($json);
        }
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Contao Manager.
 *
 * (c) Contao Association
 *
 * @license LGPL-3.0-or-later
 */
namespace _ContaoManager\Contao\ManagerApi\Controller\Server;

use _ContaoManager\Contao\ManagerApi\IntegrityCheck\IntegrityCheckFactory;
use _ContaoManager\Contao\ManagerApi\System\ServerInfo;
use _ContaoManager\Crell\ApiProblem\ApiProblem;
use _ContaoManager\Symfony\Component\HttpFoundation\JsonResponse;
use _ContaoManager\Symfony\Component\HttpFoundation\Response;
use _ContaoManager\Symfony\Component\Routing\Attribute\Route;
use _ContaoManager\Symfony\Component\Security\Http\Attribute\IsGranted;
#[Route(path: '/server/php-web', methods: ['GET'])]
#[IsGranted('ROLE_READ')]
class PhpWebController
{
    public function __construct(private readonly IntegrityCheckFactory $integrity)
    {
    }
    /**
     * Gets response about PHP web process version and issues.
     */
    public function __invoke(ServerInfo $serverInfo): Response
    {
        return new JsonResponse(['version' => \PHP_VERSION, 'version_id' => \PHP_VERSION_ID, 'platform' => $serverInfo->getPlatform(), 'problem' => $this->runIntegrityChecks()]);
    }
    /**
     * Checks system integrity and returns problem if found.
     */
    private function runIntegrityChecks(): array|null
    {
        $problem = $this->integrity->runWebChecks();
        if ($problem instanceof ApiProblem) {
            return $problem->asArray();
        }
        return null;
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Contao Manager.
 *
 * (c) Contao Association
 *
 * @license LGPL-3.0-or-later
 */
namespace _ContaoManager\Contao\ManagerApi\Controller\Server;

use _ContaoManager\Contao\ManagerApi\ApiKernel;
use _ContaoManager\Contao\ManagerApi\Exception\ProcessOutputException;
use _ContaoManager\Contao\ManagerApi\HttpKernel\ApiProblemResponse;
use _ContaoManager\Contao\ManagerApi\Process\ConsoleProcessFactory;
use _ContaoManager\Contao\ManagerApi\Process\ContaoApi;
use _ContaoManager\Contao\ManagerApi\Process\ContaoConsole;
use _ContaoManager\Contao\ManagerApi\System\ServerInfo;
use _ContaoManager\Crell\ApiProblem\ApiProblem;
use _ContaoManager\Psr\Log\LoggerInterface;
use _ContaoManager\Symfony\Component\Filesystem\Filesystem;
use _ContaoManager\Symfony\Component\HttpFoundation\JsonResponse;
use _ContaoManager\Symfony\Component\HttpFoundation\Request;
use _ContaoManager\Symfony\Component\HttpFoundation\Response;
use _ContaoManager\Symfony\Component\Process\Exception\ProcessFailedException;
use _ContaoManager\Symfony\Component\Routing\Attribute\Route;
use _ContaoManager\Symfony\Component\Security\Http\Attribute\IsGranted;
class ContaoController
{
    public function __construct(private readonly ApiKernel $kernel, private readonly ContaoApi $contaoApi, private readonly ContaoConsole $contaoConsole, private readonly ConsoleProcessFactory $processFactory, private readonly LoggerInterface $logger, private readonly Filesystem $filesystem)
    {
    }
    #[Route(path: '/server/contao', methods: ['GET'])]
    #[IsGranted('ROLE_READ')]
    public function handle(Request $request, ServerInfo $serverInfo): Response
    {
        if (!$serverInfo->getPhpExecutable()) {
            return new ApiProblemResponse((new ApiProblem('Missing hosting configuration.', '/api/server/config'))->setStatus(Response::HTTP_SERVICE_UNAVAILABLE));
        }
        try {
            $contaoVersion = $this->getContaoVersion();
        } catch (\RuntimeException $e) {
            if ($request->isMethod('POST')) {
                return new Response('', Response::HTTP_BAD_REQUEST);
            }
            if ($e instanceof ProcessFailedException) {
                return $this->createResponse(['supported' => \false, 'error' => $e->getMessage()], Response::HTTP_BAD_GATEWAY);
            }
            if ($e instanceof ProcessOutputException) {
                return $this->createResponse(['supported' => \false, 'error' => $e->getProcess()->getErrorOutput() ?: $e->getProcess()->getOutput()], Response::HTTP_BAD_GATEWAY);
            }
            $contaoVersion = null;
        }
        if (null === $contaoVersion) {
            $files = $this->getProjectFiles();
            if ($request->isMethod('POST')) {
                return $this->createDirectories($request->request->get('directory'), $request->request->getBoolean('usePublicDir'));
            }
            return $this->createResponse(['conflicts' => $files]);
        }
        return $this->createResponse(['version' => $contaoVersion, 'cli' => ['commands' => (object) $this->contaoConsole->getCommandList()], 'api' => ['version' => $this->contaoApi->getVersion(), 'features' => $this->contaoApi->getFeatures(), 'commands' => $this->contaoApi->getCommands()], 'config' => (object) $this->contaoConsole->getConfig(), 'supported' => version_compare($contaoVersion, '4.0.0', '>=') || str_starts_with($contaoVersion, 'dev-')]);
    }
    #[Route(path: '/server/contao', methods: ['POST'])]
    #[IsGranted('ROLE_INSTALL')]
    public function update(Request $request, ServerInfo $serverInfo): Response
    {
        return $this->handle($request, $serverInfo);
    }
    private function createDirectories(string|null $directory, bool $usePublicDir): Response
    {
        if (!ApiKernel::isPhar()) {
            return new Response('', Response::HTTP_SERVICE_UNAVAILABLE);
        }
        $currentRoot = $this->kernel->getProjectDir();
        $targetRoot = $currentRoot;
        $publicDir = $currentRoot . '/' . ($usePublicDir ? 'public' : 'web');
        if (null !== $directory) {
            if (str_contains($directory, '..')) {
                return new Response('', Response::HTTP_BAD_REQUEST);
            }
            if ($this->filesystem->exists($currentRoot . '/' . $directory)) {
                return new ApiProblemResponse((new ApiProblem('Target directory exists'))->setStatus(Response::HTTP_FORBIDDEN));
            }
            $targetRoot = $currentRoot . '/' . $directory;
            $publicDir = $targetRoot . '/' . ($usePublicDir ? 'public' : 'web');
            $this->filesystem->mkdir($targetRoot);
            $this->filesystem->mirror($this->kernel->getConfigDir(), $targetRoot . '/contao-manager');
            $this->filesystem->remove($this->kernel->getConfigDir());
        }
        $this->filesystem->mkdir($publicDir);
        // Create response before moving Phar, otherwise the JsonResponse class
        // cannot be autoloaded
        $response = $this->createResponse(['project_dir' => $targetRoot, 'public_dir' => $usePublicDir ? 'public' : 'web', 'conflicts' => []], Response::HTTP_CREATED);
        $phar = \Phar::running(\false);
        $this->filesystem->rename($phar, $publicDir . '/' . basename($phar));
        if ($this->filesystem->exists(\dirname($phar) . '/.htaccess')) {
            $this->filesystem->rename(\dirname($phar) . '/.htaccess', $publicDir . '/.htaccess');
        }
        if ([] === array_diff(scandir(\dirname($phar), \SCANDIR_SORT_NONE), ['.', '..'])) {
            $this->filesystem->remove(\dirname($phar));
        }
        return $response;
    }
    /**
     * Gets a list of files in the project root directory, excluding what is allowed
     * to install Contao.
     */
    private function getProjectFiles(): array
    {
        $content = scandir($this->kernel->getProjectDir());
        if (\false === $content) {
            return [];
        }
        return array_values(array_diff($content, [
            '.',
            '..',
            '.env',
            '.env.local',
            '.git',
            '.idea',
            '.ddev',
            '.well-known',
            'cgi-bin',
            'contao-manager',
            'plesk-stat',
            'public',
            'web',
            '.bash_profile',
            '.bash_logout',
            '.bashrc',
            '.DS_Store',
            '.ftpquota',
            '.htaccess',
            'user.ini',
            basename(\dirname(\Phar::running())),
            // Allow parent directory of the PHAR file (public dir)
            basename(\Phar::running()),
        ]));
    }
    /**
     * Tries to detect the Contao 4/3/2 version by analyzing the filesystem.
     */
    private function getContaoVersion(): string|null
    {
        if ($this->filesystem->exists($this->processFactory->getContaoConsolePath())) {
            return $this->contaoConsole->getVersion();
        }
        // Required for Contao 2.11
        \define('TL_ROOT', $this->kernel->getProjectDir());
        $files = [$this->kernel->getProjectDir() . '/system/constants.php', $this->kernel->getProjectDir() . '/system/config/constants.php'];
        // Test if the Phar was placed in the Contao 2/3 root
        if ('' !== $phar = \Phar::running(\false)) {
            $files[] = \dirname($phar) . '/system/constants.php';
            $files[] = \dirname($phar) . '/system/config/constants.php';
        }
        $this->logger->info('Searching for Contao 2/3', ['files' => $files]);
        foreach ($files as $file) {
            if ($this->filesystem->exists($file)) {
                try {
                    @include $file;
                } catch (\Throwable) {
                    // do nothing on error or exception
                }
                if (\defined('VERSION') && \defined('BUILD')) {
                    /** @noinspection PhpUndefinedConstantInspection */
                    return VERSION . '.' . BUILD;
                }
                break;
            }
        }
        return null;
    }
    private function createResponse(array $data, int $status = Response::HTTP_OK): JsonResponse
    {
        return new JsonResponse(array_merge(['version' => null, 'cli' => ['commands' => []], 'api' => ['version' => 0, 'features' => [], 'commands' => []], 'config' => new \stdClass(), 'supported' => \false, 'conflicts' => [], 'project_dir' => $this->kernel->getProjectDir(), 'public_dir' => basename($this->kernel->getPublicDir()), 'directory_separator' => \DIRECTORY_SEPARATOR], $data), $status);
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Contao Manager.
 *
 * (c) Contao Association
 *
 * @license LGPL-3.0-or-later
 */
namespace _ContaoManager\Contao\ManagerApi\Controller\Server;

use _ContaoManager\Contao\ManagerApi\HttpKernel\ApiProblemResponse;
use _ContaoManager\Contao\ManagerApi\Process\ContaoApi;
use _ContaoManager\Contao\ManagerApi\Process\ContaoConsole;
use _ContaoManager\Contao\ManagerApi\System\ServerInfo;
use _ContaoManager\Crell\ApiProblem\ApiProblem;
use _ContaoManager\Symfony\Component\HttpFoundation\JsonResponse;
use _ContaoManager\Symfony\Component\HttpFoundation\Request;
use _ContaoManager\Symfony\Component\HttpFoundation\Response;
use _ContaoManager\Symfony\Component\Routing\Attribute\Route;
use _ContaoManager\Symfony\Component\Security\Http\Attribute\IsGranted;
class DatabaseController
{
    // double escaping is necessary for JavaScript validation
    private const URL_PATTERN = '^([^:]+)://(([^:@]+)(:([^@]+))?@)?([^:\/]+(:[0-9]+)?)/([^?]+)(\?.+)?$';
    public function __construct(private readonly ContaoApi $contaoApi, private readonly ContaoConsole $contaoConsole)
    {
    }
    #[Route(path: '/server/database', methods: ['GET'])]
    #[IsGranted('ROLE_READ')]
    public function handle(Request $request, ServerInfo $serverInfo): Response
    {
        if (!$serverInfo->getPhpExecutable()) {
            return new ApiProblemResponse((new ApiProblem('Missing hosting configuration.', '/api/server/config'))->setStatus(Response::HTTP_SERVICE_UNAVAILABLE));
        }
        $commands = $this->contaoConsole->getCommandList();
        $features = $this->contaoApi->getFeatures();
        if (!isset($commands['contao:migrate']['options'], $features['contao/manager-bundle']['dot-env']) || !\in_array('format', $commands['contao:migrate']['options'], \true) || !\in_array('dry-run', $commands['contao:migrate']['options'], \true) || !\in_array('hash', $commands['contao:migrate']['options'], \true) || !\in_array('DATABASE_URL', $features['contao/manager-bundle']['dot-env'], \true)) {
            return new ApiProblemResponse((new ApiProblem('Contao console does not support the necessary contao:migrate command/arguments or CLI API features.'))->setStatus(Response::HTTP_NOT_IMPLEMENTED));
        }
        if ($request->isMethod('POST')) {
            $url = $request->request->get('url');
            if (empty($url) || !preg_match('{' . self::URL_PATTERN . '}i', $url)) {
                return new ApiProblemResponse((new ApiProblem('Invalid URL'))->setStatus(Response::HTTP_BAD_REQUEST));
            }
            $this->contaoApi->runCommand(['dot-env:set', 'DATABASE_URL', $url]);
        } else {
            $url = $this->contaoApi->runCommand(['dot-env:get', 'DATABASE_URL']);
        }
        return new JsonResponse(['url' => $url, 'pattern' => self::URL_PATTERN, 'status' => $this->contaoConsole->checkDatabaseMigrations()]);
    }
    #[Route(path: '/server/database', methods: ['POST'])]
    #[IsGranted('ROLE_INSTALL')]
    public function write(Request $request, ServerInfo $serverInfo): Response
    {
        return $this->handle($request, $serverInfo);
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Contao Manager.
 *
 * (c) Contao Association
 *
 * @license LGPL-3.0-or-later
 */
namespace _ContaoManager\Contao\ManagerApi\Controller\Server;

use _ContaoManager\Contao\ManagerApi\HttpKernel\ApiProblemResponse;
use _ContaoManager\Contao\ManagerApi\Process\ContaoConsole;
use _ContaoManager\Contao\ManagerApi\System\ServerInfo;
use _ContaoManager\Crell\ApiProblem\ApiProblem;
use _ContaoManager\Symfony\Component\HttpFoundation\JsonResponse;
use _ContaoManager\Symfony\Component\HttpFoundation\Request;
use _ContaoManager\Symfony\Component\HttpFoundation\Response;
use _ContaoManager\Symfony\Component\Process\Exception\ProcessFailedException;
use _ContaoManager\Symfony\Component\Routing\Attribute\Route;
use _ContaoManager\Symfony\Component\Security\Http\Attribute\IsGranted;
#[Route(path: '/server/admin-user', methods: ['GET', 'POST'])]
#[IsGranted('ROLE_INSTALL')]
class AdminUserController
{
    public function __construct(private readonly ContaoConsole $contaoConsole)
    {
    }
    public function __invoke(Request $request, ServerInfo $serverInfo): Response
    {
        if (!$serverInfo->getPhpExecutable()) {
            return new ApiProblemResponse((new ApiProblem('Missing hosting configuration.', '/api/server/config'))->setStatus(Response::HTTP_SERVICE_UNAVAILABLE));
        }
        $commands = $this->contaoConsole->getCommandList();
        if (!isset($commands['contao:user:list']['options'], $commands['contao:user:create']['options']) || !\in_array('format', $commands['contao:user:list']['options'], \true) || !\in_array('column', $commands['contao:user:list']['options'], \true)) {
            return new ApiProblemResponse((new ApiProblem('Contao console does not support the necessary contao:user:list and/or contao:user:create commands/options.'))->setStatus(Response::HTTP_NOT_IMPLEMENTED));
        }
        if ($request->isMethod('POST')) {
            if ($this->hasAdminUser()) {
                return new ApiProblemResponse((new ApiProblem('An admin user already exists.'))->setStatus(Response::HTTP_METHOD_NOT_ALLOWED));
            }
            try {
                $this->contaoConsole->createBackendUser(['username' => $request->request->get('username'), 'name' => $request->request->get('name'), 'email' => $request->request->get('email'), 'language' => $request->getPreferredLanguage()], $request->request->get('password'));
                return $this->getUserResponse(Response::HTTP_CREATED);
            } catch (ProcessFailedException $exception) {
                $problem = new ApiProblem('Unable to create back end account.');
                $problem->setStatus(Response::HTTP_INTERNAL_SERVER_ERROR);
                $problem['debug'] = $exception->getProcess()->getOutput() . $exception->getProcess()->getErrorOutput();
                return new ApiProblemResponse($problem);
            }
        }
        return $this->getUserResponse();
    }
    private function getUserResponse(int $status = Response::HTTP_OK): JsonResponse
    {
        return new JsonResponse(['hasUser' => $this->hasAdminUser(\true)], $status);
    }
    private function hasAdminUser(bool $throw = \false): bool
    {
        $users = $this->contaoConsole->getUsers($throw);
        foreach ($users as $user) {
            if ($user['admin']) {
                return \true;
            }
        }
        return \false;
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Contao Manager.
 *
 * (c) Contao Association
 *
 * @license LGPL-3.0-or-later
 */
namespace _ContaoManager\Contao\ManagerApi\Controller\Server;

use _ContaoManager\Symfony\Component\HttpFoundation\Response;
use _ContaoManager\Symfony\Component\Routing\Attribute\Route;
use _ContaoManager\Symfony\Component\Security\Http\Attribute\IsGranted;
#[Route(path: '/server/phpinfo', methods: ['GET'])]
#[IsGranted('ROLE_READ')]
class PhpinfoController
{
    /**
     * Gets response with phpinfo().
     */
    public function __invoke(): Response
    {
        ob_start();
        phpinfo(\INFO_GENERAL | \INFO_CONFIGURATION | \INFO_MODULES | \INFO_ENVIRONMENT);
        return new Response(ob_get_clean());
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Contao Manager.
 *
 * (c) Contao Association
 *
 * @license LGPL-3.0-or-later
 */
namespace _ContaoManager\Contao\ManagerApi\Controller\Server;

use _ContaoManager\Symfony\Component\HttpFoundation\JsonResponse;
use _ContaoManager\Symfony\Component\HttpFoundation\Response;
use _ContaoManager\Symfony\Component\Routing\Attribute\Route;
use _ContaoManager\Symfony\Component\Security\Http\Attribute\IsGranted;
class OpcacheController
{
    #[Route(path: '/server/opcache', methods: ['GET'])]
    #[IsGranted('ROLE_READ')]
    public function getOpcache(): Response
    {
        if (!\function_exists('opcache_reset') && !\function_exists('_ContaoManager\opcache_reset')) {
            return new JsonResponse(null, Response::HTTP_NOT_IMPLEMENTED);
        }
        global $opcacheEnabled;
        $status = ['opcache_enabled' => $opcacheEnabled, 'reset_token' => md5(\Phar::running(\false))];
        return new JsonResponse($status);
    }
    #[Route(path: '/server/opcache', methods: ['DELETE'])]
    #[IsGranted('ROLE_UPDATE')]
    public function deleteOpcache(): Response
    {
        if (!\function_exists('opcache_reset') && !\function_exists('_ContaoManager\opcache_reset')) {
            return new JsonResponse(null, Response::HTTP_NOT_IMPLEMENTED);
        }
        opcache_reset();
        return $this->getOpcache();
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Contao Manager.
 *
 * (c) Contao Association
 *
 * @license LGPL-3.0-or-later
 */
namespace _ContaoManager\Contao\ManagerApi\Controller\Server;

use Composer\Json\JsonFile;
use _ContaoManager\Contao\ManagerApi\Composer\Environment;
use _ContaoManager\Contao\ManagerApi\Config\ManagerConfig;
use _ContaoManager\Contao\ManagerApi\HttpKernel\ApiProblemResponse;
use _ContaoManager\Contao\ManagerApi\I18n\Translator;
use _ContaoManager\Contao\ManagerApi\System\ServerInfo;
use _ContaoManager\Crell\ApiProblem\ApiProblem;
use _ContaoManager\Symfony\Component\HttpFoundation\JsonResponse;
use _ContaoManager\Symfony\Component\HttpFoundation\Request;
use _ContaoManager\Symfony\Component\HttpFoundation\Response;
use _ContaoManager\Symfony\Component\Process\Exception\RuntimeException;
use _ContaoManager\Symfony\Component\Routing\Attribute\Route;
use _ContaoManager\Symfony\Component\Security\Http\Attribute\IsGranted;
class ConfigController
{
    public function __construct(private readonly ManagerConfig $config, private readonly ServerInfo $serverInfo, private readonly Environment $environment, private readonly Translator $translator)
    {
    }
    #[Route(path: '/server/config', methods: ['GET'])]
    #[IsGranted('ROLE_READ')]
    public function getConfig(): Response
    {
        return new JsonResponse(['php_cli' => (string) $this->serverInfo->getPhpExecutable(), 'cloud' => $this->getCloudConfig()]);
    }
    #[Route(path: '/server/config', methods: ['PUT'])]
    #[IsGranted('ROLE_INSTALL')]
    public function setConfig(Request $request): Response
    {
        $phpCli = $request->request->get('php_cli');
        if (null !== $error = $this->validatePhpCli($phpCli)) {
            $problem = (new ApiProblem('Bad Request'))->setStatus(400);
            $problem->setDetail($error);
            return new ApiProblemResponse($problem);
        }
        $this->config->set('php_cli', $phpCli);
        if ($request->request->getBoolean('cloud', \true)) {
            $this->config->remove('disable_cloud');
        } else {
            $this->config->set('disable_cloud', \true);
        }
        return $this->getConfig();
    }
    private function validatePhpCli(string $phpCli): string|null
    {
        try {
            $info = $this->serverInfo->getPhpExecutableFinder()->getServerInfo($phpCli);
        } catch (RuntimeException $e) {
            return $this->translator->trans('config.php_cli.error') . "\n\n" . $e->getMessage();
        }
        if (null === $info) {
            return $this->translator->trans('config.php_cli.not_found');
        }
        $vWeb = \PHP_MAJOR_VERSION . '.' . \PHP_MINOR_VERSION;
        $vCli = vsprintf('%s.%s', explode('.', (string) $info['version']));
        if (version_compare($vWeb, $vCli, '<>')) {
            return $this->translator->trans('config.php_cli.incompatible', ['cli' => $vCli, 'web' => $vWeb]);
        }
        return null;
    }
    private function getCloudConfig(): array
    {
        $issues = $this->checkCloudIssues();
        return ['enabled' => !$this->config->get('disable_cloud', \false), 'issues' => $issues];
    }
    private function checkCloudIssues(): array
    {
        $json = new JsonFile($this->environment->getJsonFile());
        if (!$json->exists()) {
            return [];
        }
        try {
            $data = $json->read();
        } catch (\RuntimeException $e) {
            return [$e->getMessage()];
        }
        $issues = [];
        if (isset($data['config']['platform'])) {
            $issues[] = $this->translator->trans('config.cloud.platform');
        }
        if (isset($data['config']['cache-dir']) || isset($data['config']['cache-files-dir']) || isset($data['config']['cache-repo-dir']) || isset($data['config']['cache-vcs-dir']) || isset($data['config']['cache-files-ttl']) || isset($data['config']['cache-files-maxsize'])) {
            $issues[] = $this->translator->trans('config.cloud.cache');
        }
        return array_unique($issues);
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Contao Manager.
 *
 * (c) Contao Association
 *
 * @license LGPL-3.0-or-later
 */
namespace _ContaoManager\Contao\ManagerApi\Controller\Server;

use _ContaoManager\Contao\ManagerApi\Composer\Environment;
use _ContaoManager\Contao\ManagerApi\HttpKernel\ApiProblemResponse;
use _ContaoManager\Contao\ManagerApi\I18n\Translator;
use _ContaoManager\Contao\ManagerApi\System\ServerInfo;
use _ContaoManager\Crell\ApiProblem\ApiProblem;
use _ContaoManager\JsonSchema\Exception\ValidationException;
use _ContaoManager\JsonSchema\Validator;
use _ContaoManager\Seld\JsonLint\ParsingException;
use _ContaoManager\Symfony\Component\Filesystem\Filesystem;
use _ContaoManager\Symfony\Component\HttpFoundation\JsonResponse;
use _ContaoManager\Symfony\Component\HttpFoundation\Response;
use _ContaoManager\Symfony\Component\Routing\Attribute\Route;
use _ContaoManager\Symfony\Component\Security\Http\Attribute\IsGranted;
#[Route(path: '/server/composer', methods: ['GET'])]
#[IsGranted('ROLE_READ')]
class ComposerController
{
    public function __construct(private readonly Environment $environment, private readonly Translator $translator, private readonly Filesystem $filesystem)
    {
    }
    public function __invoke(ServerInfo $serverInfo): Response
    {
        if (!$serverInfo->getPhpExecutable()) {
            return new ApiProblemResponse((new ApiProblem('Missing hosting configuration.', '/api/server/config'))->setStatus(Response::HTTP_SERVICE_UNAVAILABLE));
        }
        $result = ['json' => ['found' => \false, 'valid' => \false, 'error' => null], 'lock' => ['found' => \false, 'fresh' => \false], 'vendor' => ['found' => \false]];
        if ($this->filesystem->exists($this->environment->getJsonFile())) {
            $result['json']['found'] = \true;
            $result['json']['valid'] = \true;
            $result['vendor']['found'] = is_dir($this->environment->getVendorDir());
            if ($this->validateSchema($result)) {
                // If schema is valid but does not contain contao/manager-bundle, mark as "not
                // found" so the install screen will conflict with the file.
                try {
                    $json = $this->environment->getComposerJson();
                    if (!isset($json['require']['contao/manager-bundle'])) {
                        $result['json']['found'] = \false;
                        $result['json']['valid'] = \false;
                    } else {
                        $this->validateLockFile($result);
                    }
                } catch (\Exception $exception) {
                    $result['json']['valid'] = \false;
                    $result['json']['error'] = $this->translator->trans('boot.composer.invalid', ['exception' => $exception->getMessage()]);
                }
            }
        }
        return new JsonResponse($result);
    }
    private function validateSchema(array &$result): bool
    {
        try {
            $schemaFile = __DIR__ . '/../../../vendor/composer/composer/res/composer-schema.json';
            // Prepend with file:// only when not using a special schema already (e.g. in the phar)
            if (!str_contains($schemaFile, '://')) {
                $schemaFile = 'file://' . $schemaFile;
            }
            $schema = (object) ['$ref' => $schemaFile];
            $schema->required = [];
            $value = json_decode(file_get_contents($this->environment->getJsonFile()), \false);
            $validator = new Validator();
            $validator->validate($value, $schema);
            if (!$validator->isValid()) {
                $errors = [];
                foreach ($validator->getErrors() as $error) {
                    $errors[] = ($error['property'] ? $error['property'] . ' : ' : '') . $error['message'];
                }
                throw new ValidationException(implode(', ', $errors));
            }
            return \true;
        } catch (ValidationException $exception) {
            $result['json']['valid'] = \false;
            $result['json']['error'] = $this->translator->trans('boot.composer.invalid', ['exception' => $exception->getMessage()]);
            return \false;
        }
    }
    private function validateLockFile(array &$result): void
    {
        try {
            $locker = $this->environment->getComposer()->getLocker();
            if ($locker->isLocked()) {
                $result['lock']['found'] = \true;
                if ($locker->isFresh()) {
                    $result['lock']['fresh'] = \true;
                }
            }
        } catch (ParsingException $e) {
            $result['json']['valid'] = \false;
            $result['json']['error'] = $this->translator->trans('boot.composer.invalid', ['exception' => $e->getMessage() . ' ' . $e->getDetails()['text']]);
        } catch (\Exception $e) {
            $result['json']['valid'] = \false;
            $result['json']['error'] = $this->translator->trans('boot.composer.invalid', ['exception' => $e->getMessage()]);
        }
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Contao Manager.
 *
 * (c) Contao Association
 *
 * @license LGPL-3.0-or-later
 */
namespace _ContaoManager\Contao\ManagerApi\Controller\Server;

use _ContaoManager\Contao\ManagerApi\HttpKernel\ApiProblemResponse;
use _ContaoManager\Contao\ManagerApi\Process\ConsoleProcessFactory;
use _ContaoManager\Contao\ManagerApi\System\ServerInfo;
use _ContaoManager\Crell\ApiProblem\ApiProblem;
use _ContaoManager\Symfony\Component\HttpFoundation\JsonResponse;
use _ContaoManager\Symfony\Component\HttpFoundation\Response;
use _ContaoManager\Symfony\Component\Routing\Attribute\Route;
use _ContaoManager\Symfony\Component\Security\Http\Attribute\IsGranted;
#[Route(path: '/server/php-cli', methods: ['GET'])]
#[IsGranted('ROLE_READ')]
class PhpCliController
{
    public function __invoke(ServerInfo $serverInfo, ConsoleProcessFactory $processFactory): Response
    {
        if (!$serverInfo->getPhpExecutable()) {
            return new ApiProblemResponse((new ApiProblem('Missing hosting configuration.', '/api/server/config'))->setStatus(Response::HTTP_SERVICE_UNAVAILABLE));
        }
        return new JsonResponse($this->runIntegrityChecks($processFactory));
    }
    private function runIntegrityChecks(ConsoleProcessFactory $processFactory): array
    {
        $process = $processFactory->createManagerConsoleProcess(['integrity-check', '--format=json']);
        $process->run();
        $output = $process->getOutput();
        $result = json_decode($output, \true);
        if (!\is_array($result)) {
            return ['version' => \PHP_VERSION, 'version_id' => \PHP_VERSION_ID, 'problem' => ['title' => 'Received invalid JSON output from the command line', 'type' => 'https://php.net/json_decode', 'detail' => $output]];
        }
        return $result;
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Contao Manager.
 *
 * (c) Contao Association
 *
 * @license LGPL-3.0-or-later
 */
namespace _ContaoManager\Contao\ManagerApi\Controller\Server;

use _ContaoManager\Contao\ManagerApi\HttpKernel\ApiProblemResponse;
use _ContaoManager\Contao\ManagerApi\System\SelfUpdate;
use _ContaoManager\Crell\ApiProblem\ApiProblem;
use _ContaoManager\Symfony\Component\HttpFoundation\JsonResponse;
use _ContaoManager\Symfony\Component\HttpFoundation\Response;
use _ContaoManager\Symfony\Component\Routing\Attribute\Route;
use _ContaoManager\Symfony\Component\Security\Http\Attribute\IsGranted;
#[Route(path: '/server/self-update', methods: ['GET'])]
#[IsGranted('ROLE_UPDATE')]
class SelfUpdateController
{
    /**
     * Gets response about update status of the Contao Manager.
     */
    public function __invoke(SelfUpdate $updater): Response
    {
        if (!$updater->canUpdate()) {
            return new ApiProblemResponse((new ApiProblem('This version cannot be updated.'))->setStatus(Response::HTTP_NOT_IMPLEMENTED));
        }
        try {
            $error = null;
            $supportsUpdate = $updater->supportsUpdate();
            $latestVersion = $updater->getNewVersion();
        } catch (\Throwable $throwable) {
            $error = $throwable->getMessage();
            $supportsUpdate = \true;
            $latestVersion = $updater->getOldVersion();
        }
        return new JsonResponse(['current_version' => $updater->getOldVersion(), 'latest_version' => $latestVersion, 'channel' => $updater->getChannel(), 'supported' => $supportsUpdate, 'error' => $error]);
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Contao Manager.
 *
 * (c) Contao Association
 *
 * @license LGPL-3.0-or-later
 */
namespace _ContaoManager\Contao\ManagerApi\Controller;

use _ContaoManager\Contao\ManagerApi\ApiKernel;
use _ContaoManager\Contao\ManagerApi\Config\UserConfig;
use _ContaoManager\Contao\ManagerApi\HttpKernel\ApiProblemResponse;
use _ContaoManager\Contao\ManagerApi\Security\JwtManager;
use _ContaoManager\Contao\ManagerApi\Security\LoginAuthenticator;
use _ContaoManager\Contao\ManagerApi\Security\TokenAuthenticator;
use _ContaoManager\Contao\ManagerApi\Security\User;
use _ContaoManager\Contao\ManagerApi\Security\WebauthnAuthenticator;
use _ContaoManager\Crell\ApiProblem\ApiProblem;
use _ContaoManager\Symfony\Bundle\SecurityBundle\Security;
use _ContaoManager\Symfony\Component\HttpFoundation\JsonResponse;
use _ContaoManager\Symfony\Component\HttpFoundation\Request;
use _ContaoManager\Symfony\Component\HttpFoundation\Response;
use _ContaoManager\Symfony\Component\Routing\Attribute\Route;
class SessionController
{
    public function __construct(private readonly UserConfig $config, private readonly Security $security, private readonly JwtManager $jwtManager, private readonly ApiKernel $kernel, private readonly WebauthnAuthenticator $webauthn)
    {
    }
    #[Route(path: '/session', methods: ['GET', 'POST', 'DELETE'])]
    public function getSession(Request $request): Response
    {
        switch ($request->getMethod()) {
            case 'GET':
                return $this->getStatus();
            case 'POST':
                if (LoginAuthenticator::isLocked($this->kernel->getConfigDir())) {
                    return new ApiProblemResponse((new ApiProblem())->setStatus(Response::HTTP_FORBIDDEN));
                }
                // Login should have been handled by the firewall
                return new Response('Bad Request', Response::HTTP_BAD_REQUEST);
            case 'DELETE':
                return $this->handleLogout($request);
        }
        return new Response(null, Response::HTTP_METHOD_NOT_ALLOWED);
    }
    #[Route(path: '/session/options', methods: ['GET', 'POST'])]
    public function getWebauthnOptions(Request $request): Response
    {
        $username = $request->isMethod('POST') ? $request->request->get('username') : null;
        return new JsonResponse($this->webauthn->getCredentialOptions($request->getHost(), $username), json: \true);
    }
    /**
     * Returns the login status of the user.
     */
    private function getStatus(): Response
    {
        if ($this->security->isGranted('ROLE_USER')) {
            $token = $this->security->getToken();
            if (null !== $token && TokenAuthenticator::class === $token->getAttribute('authenticator') && null !== $payload = $this->config->getToken($token->getAttribute('token_id'))) {
                return new JsonResponse($payload);
            }
            $user = $this->config->getUser($token->getUserIdentifier());
            $scope = User::scopeFromRoles($token?->getRoleNames());
            $json = ['username' => $token?->getUserIdentifier(), 'scope' => $scope, 'limited' => $scope !== User::scopeFromRoles($user?->getRoles())];
            if ($user?->getPasskey()) {
                $json['passkey'] = \true;
            } else {
                $json['totp_enabled'] = (bool) $user?->getTotpSecret();
            }
            return new JsonResponse($json);
        }
        if (LoginAuthenticator::isLocked($this->kernel->getConfigDir())) {
            return new ApiProblemResponse((new ApiProblem())->setStatus(Response::HTTP_FORBIDDEN));
        }
        if (!$this->config->hasUsers()) {
            return new Response('', Response::HTTP_NO_CONTENT);
        }
        return new ApiProblemResponse((new ApiProblem())->setStatus(Response::HTTP_UNAUTHORIZED));
    }
    /**
     * Logs the user out by removing cookies from the browser.
     */
    private function handleLogout(Request $request): Response
    {
        if (!$this->security->isGranted('ROLE_USER')) {
            return new ApiProblemResponse((new ApiProblem('User is not logged in'))->setStatus(Response::HTTP_UNAUTHORIZED));
        }
        $response = new Response('', Response::HTTP_NO_CONTENT);
        $this->jwtManager->removeToken($request, $response);
        return $response;
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Contao Manager.
 *
 * (c) Contao Association
 *
 * @license LGPL-3.0-or-later
 */
namespace _ContaoManager\Contao\ManagerApi\Controller\Packages;

use Composer\Package\Link;
use Composer\Repository\InstalledRepository;
use Composer\Repository\InstalledRepositoryInterface;
use Composer\Repository\PlatformRepository;
use Composer\Repository\RootPackageRepository;
use _ContaoManager\Contao\ManagerApi\Composer\Environment;
use _ContaoManager\Symfony\Component\HttpFoundation\JsonResponse;
use _ContaoManager\Symfony\Component\HttpFoundation\Response;
use _ContaoManager\Symfony\Component\Routing\Attribute\Route;
use _ContaoManager\Symfony\Component\Security\Http\Attribute\IsGranted;
#[Route(path: '/packages/missing', methods: ['GET'])]
#[IsGranted('ROLE_READ')]
class MissingPackagesController
{
    private readonly InstalledRepositoryInterface $localRepository;
    private readonly InstalledRepository $compositeRepository;
    public function __construct(Environment $environment)
    {
        $composer = $environment->getComposer();
        $this->localRepository = $composer->getRepositoryManager()->getLocalRepository();
        $this->compositeRepository = new InstalledRepository([new RootPackageRepository($composer->getPackage()), $this->localRepository, new PlatformRepository([], $composer->getConfig()->get('platform') ?: [])]);
    }
    public function __invoke(): Response
    {
        $missing = [];
        foreach ($this->localRepository->getPackages() as $package) {
            if ($this->hasDependents([$package->getName()])) {
                continue;
            }
            $replaces = array_keys($package->getReplaces());
            if ([] !== $replaces && $this->hasDependents($replaces)) {
                continue;
            }
            $missing[] = $package->getName();
        }
        if ([] === $missing) {
            return new Response('', Response::HTTP_NO_CONTENT);
        }
        return new JsonResponse($missing);
    }
    private function hasDependents(array $names): bool
    {
        $dependents = $this->compositeRepository->getDependents($names, null, \false, \false);
        foreach ($dependents as $dependent) {
            /** @var Link $link */
            [, $link] = $dependent;
            if ('requires' === $link->getDescription()) {
                return \true;
            }
        }
        return \false;
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Contao Manager.
 *
 * (c) Contao Association
 *
 * @license LGPL-3.0-or-later
 */
namespace _ContaoManager\Contao\ManagerApi\Controller\Packages;

use Composer\Json\JsonFile;
use Composer\Semver\Constraint\Constraint;
use Composer\Semver\Constraint\MultiConstraint;
use Composer\Semver\VersionParser;
use Composer\Util\Zip;
use _ContaoManager\Contao\ManagerApi\Composer\Environment;
use _ContaoManager\Contao\ManagerApi\Config\UploadsConfig;
use _ContaoManager\Contao\ManagerApi\Exception\ApiProblemException;
use _ContaoManager\Contao\ManagerApi\I18n\Translator;
use _ContaoManager\Crell\ApiProblem\ApiProblem;
use _ContaoManager\JsonSchema\Constraints\Constraint as JsonConstraint;
use _ContaoManager\JsonSchema\Exception\ValidationException;
use _ContaoManager\JsonSchema\Validator;
use _ContaoManager\Seld\JsonLint\ParsingException;
use _ContaoManager\Symfony\Component\Filesystem\Exception\IOException;
use _ContaoManager\Symfony\Component\Filesystem\Filesystem;
use _ContaoManager\Symfony\Component\HttpFoundation\File\UploadedFile;
use _ContaoManager\Symfony\Component\HttpFoundation\JsonResponse;
use _ContaoManager\Symfony\Component\HttpFoundation\Request;
use _ContaoManager\Symfony\Component\HttpFoundation\Response;
use _ContaoManager\Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
use _ContaoManager\Symfony\Component\Routing\Attribute\Route;
use _ContaoManager\Symfony\Component\Security\Http\Attribute\IsGranted;
class UploadPackagesController
{
    public const CHUNK_SIZE = 1048576;
    public function __construct(private readonly UploadsConfig $config, private readonly Environment $environment, private readonly Translator $translator, private readonly Filesystem $filesystem)
    {
    }
    #[Route(path: '/packages/uploads', methods: ['GET'])]
    #[IsGranted('ROLE_READ')]
    public function read(): JsonResponse
    {
        $this->validateUploadSupport();
        $uploads = $this->config->all();
        foreach ($uploads as $id => &$upload) {
            if (!$this->filesystem->exists($this->uploadPath($id))) {
                unset($uploads[$id]);
                $this->config->remove($id);
                continue;
            }
            $upload['filesize'] = filesize($this->uploadPath($id));
            if ($upload['error']) {
                $upload['error'] = $this->translator->trans('upload.error.' . $upload['error']);
            } elseif (!$upload['success']) {
                $upload['error'] = $this->translator->trans('upload.error.partial');
            }
        }
        return new JsonResponse(array_reverse($uploads));
    }
    #[Route(path: '/packages/uploads', methods: ['POST'], defaults: ['form-data' => \true])]
    #[IsGranted('ROLE_INSTALL')]
    public function upload(Request $request): JsonResponse
    {
        $this->validateUploadSupport();
        // Must be a HTML5 upload
        if ($request->files->has('package')) {
            /** @var UploadedFile $file */
            $file = $request->files->get('package');
            $id = $this->createUpload($file->getClientOriginalName(), $file->getSize());
            $file->move($this->environment->getUploadDir(), $id);
            return $this->finishUpload($id, $request->getPreferredLanguage());
        }
        switch ($request->request->get('phase')) {
            case 'start':
                $id = $this->createUpload($request->request->get('name'), $request->request->getInt('size'));
                return new JsonResponse(['status' => 'success', 'data' => ['session_id' => $id, 'end_offset' => self::CHUNK_SIZE]], Response::HTTP_CREATED);
            case 'upload':
                $this->addChunk($request->request->get('session_id'), $request->request->getInt('start_offset'), $request->files->get('chunk'));
                return new JsonResponse(['status' => 'success']);
            case 'finish':
                $id = $request->request->get('session_id');
                return $this->finishUpload($id, $request->getPreferredLanguage());
        }
        throw new \RuntimeException(\sprintf('Invalid chunk phase "%s"', $request->request->get('phase')));
    }
    #[Route(path: '/packages/uploads/{id}', methods: ['DELETE'])]
    #[IsGranted('ROLE_INSTALL')]
    public function delete(string $id): JsonResponse
    {
        $this->validateUploadSupport();
        if (!$this->config->has($id)) {
            throw new NotFoundHttpException(\sprintf('Unknown file ID "%s"', $id));
        }
        try {
            $this->filesystem->remove($this->uploadPath($id));
        } catch (IOException) {
            // Ignore if file could not be deleted
        }
        $this->config->remove($id);
        return new JsonResponse(['status' => 'success']);
    }
    private function createUpload(string $name, int $size): string
    {
        /** @noinspection PhpUnhandledExceptionInspection */
        $id = bin2hex(random_bytes(8));
        $this->filesystem->touch($this->uploadPath($id));
        $this->config->set($id, ['id' => $id, 'name' => $name, 'size' => $size, 'success' => \false, 'error' => null, 'package' => null]);
        return $id;
    }
    private function addChunk(string $id, int $offset, UploadedFile $file): void
    {
        if (!$this->config->has($id)) {
            throw new NotFoundHttpException(\sprintf('Unknown file ID "%s"', $id));
        }
        $fp = fopen($this->uploadPath($id), 'cb+');
        flock($fp, \LOCK_EX);
        fseek($fp, $offset);
        fwrite($fp, file_get_contents($file->getPathname()), self::CHUNK_SIZE);
        flock($fp, \LOCK_UN);
        fclose($fp);
    }
    private function finishUpload(string $id, string|null $language = null): JsonResponse
    {
        $uploadFile = $this->uploadPath($id);
        $config = $this->config->get($id);
        if (null === $config || !$this->filesystem->exists($uploadFile)) {
            throw new NotFoundHttpException(\sprintf('Unknown file ID "%s"', $id));
        }
        $size = filesize($uploadFile);
        if ($config['success'] || $config['error']) {
            throw new \RuntimeException('File has already be uploaded completely.');
        }
        if ($size !== $config['size']) {
            throw new \RuntimeException(\sprintf('Incomplete upload ID "%s": %s instead of %s bytes', $id, $size, $config['size']));
        }
        try {
            $json = Zip::getComposerJson($uploadFile);
            if (null === $json) {
                return $this->installError($id, 'file');
            }
        } catch (\RuntimeException $e) {
            return $this->installError($id, 'file', $e);
        }
        try {
            $data = JsonFile::parseJson($json, $uploadFile . '#composer.json');
        } catch (ParsingException $exception) {
            return $this->installError($id, 'json', $exception);
        }
        try {
            $this->validateJsonSchema($data);
        } catch (ValidationException $exception) {
            return $this->installError($id, 'schema', $exception);
        }
        [$vendor, $package] = explode('/', (string) $data['name']);
        $config['success'] = \true;
        $config['hash'] = sha1_file($uploadFile);
        $config['package'] = array_merge($this->environment->mergeMetadata($data, $language), ['installation-source' => 'dist', 'dist' => ['shasum' => $config['hash'], 'type' => 'zip', 'url' => \sprintf('/contao-manager/packages/%s__%s__%s__%s.zip', $vendor, $package, (new VersionParser())->normalize($data['version']), substr(sha1_file($uploadFile), 0, 8))]]);
        $this->config->set($id, $config);
        return new JsonResponse(['status' => 'success', 'data' => $this->config->get($id)]);
    }
    private function uploadPath(string $id): string
    {
        return $this->environment->getUploadDir() . '/' . $id;
    }
    private function installError(string $id, string $error, \Exception|null $e = null): JsonResponse
    {
        $config = $this->config->get($id);
        $config['success'] = \false;
        $config['error'] = $error;
        if ($e instanceof \Exception) {
            $config['exception'] = $e->getMessage();
        }
        $this->config->set($id, $config);
        return new JsonResponse($config);
    }
    private function validateUploadSupport(): void
    {
        if (!$this->filesystem->exists($this->environment->getJsonFile())) {
            return;
        }
        if (!\extension_loaded('zip')) {
            throw new ApiProblemException((new ApiProblem("The artifact repository requires PHP's zip extension"))->setStatus(Response::HTTP_NOT_IMPLEMENTED));
        }
        $packages = $this->environment->getComposer()->getRepositoryManager()->getLocalRepository()->getPackages();
        foreach ($packages as $package) {
            if ('contao/manager-plugin' === $package->getName()) {
                $require = new MultiConstraint([new Constraint('>=', '2.7'), new Constraint('=', 'dev-main')], \false);
                if ($require->matches(new Constraint('=', $package->getVersion()))) {
                    return;
                }
            }
        }
        throw new ApiProblemException((new ApiProblem('Must install contao/manager-plugin 2.7 or later to support artifacts.'))->setStatus(Response::HTTP_NOT_IMPLEMENTED));
    }
    private function validateJsonSchema(mixed $data): void
    {
        $schemaFile = __DIR__ . '/../../../vendor/composer/composer/res/composer-schema.json';
        // Prepend with file:// only when not using a special schema already (e.g. in the phar)
        if (!str_contains($schemaFile, '://')) {
            $schemaFile = 'file://' . $schemaFile;
        }
        $schema = (object) ['$ref' => $schemaFile];
        $schema->required = ['name', 'version'];
        $value = json_decode(json_encode($data), \false);
        $validator = new Validator();
        $validator->validate($value, $schema, JsonConstraint::CHECK_MODE_EXCEPTIONS);
        if ($validator->isValid()) {
            return;
        }
        $errors = [];
        foreach ($validator->getErrors() as $error) {
            $errors[] = ($error['property'] ? $error['property'] . ' : ' : '') . $error['message'];
        }
        throw new ValidationException(implode(', ', $errors));
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Contao Manager.
 *
 * (c) Contao Association
 *
 * @license LGPL-3.0-or-later
 */
namespace _ContaoManager\Contao\ManagerApi\Controller\Packages;

use Composer\Package\Dumper\ArrayDumper;
use _ContaoManager\Contao\ManagerApi\Composer\Environment;
use _ContaoManager\Symfony\Component\HttpFoundation\JsonResponse;
use _ContaoManager\Symfony\Component\HttpFoundation\Response;
use _ContaoManager\Symfony\Component\Routing\Attribute\Route;
use _ContaoManager\Symfony\Component\Security\Http\Attribute\IsGranted;
#[Route(path: '/packages/root', methods: ['GET'])]
#[IsGranted('ROLE_READ')]
class RootPackageController
{
    public function __construct(private readonly Environment $environment)
    {
    }
    public function __invoke(): Response
    {
        $dumper = new ArrayDumper();
        return new JsonResponse($dumper->dump($this->environment->getComposer()->getPackage()));
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Contao Manager.
 *
 * (c) Contao Association
 *
 * @license LGPL-3.0-or-later
 */
namespace _ContaoManager\Contao\ManagerApi\Controller\Packages;

use Composer\Json\JsonFile;
use _ContaoManager\Contao\ManagerApi\Composer\Environment;
use _ContaoManager\Contao\ManagerApi\Task\TaskManager;
use _ContaoManager\Psr\Log\LoggerInterface;
use _ContaoManager\Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use _ContaoManager\Symfony\Component\Filesystem\Filesystem;
use _ContaoManager\Symfony\Component\HttpFoundation\JsonResponse;
use _ContaoManager\Symfony\Component\HttpFoundation\Request;
use _ContaoManager\Symfony\Component\HttpFoundation\Response;
use _ContaoManager\Symfony\Component\HttpKernel\Exception\BadRequestHttpException;
use _ContaoManager\Symfony\Component\HttpKernel\Exception\HttpException;
use _ContaoManager\Symfony\Component\HttpKernel\Exception\HttpExceptionInterface;
use _ContaoManager\Symfony\Component\Routing\Attribute\Route;
use _ContaoManager\Symfony\Component\Security\Http\Attribute\IsGranted;
use _ContaoManager\Terminal42\ComposerLockValidator\Validator;
class CloudController extends AbstractController
{
    public function __construct(private readonly Environment $environment, private readonly TaskManager $taskManager, private readonly Filesystem $filesystem, private readonly LoggerInterface $logger)
    {
    }
    #[Route(path: '/packages/cloud', methods: ['GET'])]
    #[IsGranted('ROLE_READ')]
    public function getCloudData(): Response
    {
        return new JsonResponse(['composerJson' => $this->environment->getComposerJsonWithConfig(), 'composerLock' => $this->environment->getComposerLock(), 'platform' => $this->environment->getPlatformPackages(), 'localPackages' => $this->environment->getLocalPackages()]);
    }
    #[Route(path: '/packages/cloud', methods: ['PUT'])]
    #[IsGranted('ROLE_UPDATE')]
    public function writeAndInstall(Request $request): Response
    {
        if ($this->taskManager->hasTask()) {
            throw new BadRequestHttpException('A task is already active');
        }
        $backupCreated = \false;
        $lock = $request->request->all('composerLock');
        if ([] === $lock) {
            return new Response('composerLock is missing', Response::HTTP_BAD_REQUEST);
        }
        try {
            $lockFile = new JsonFile($this->filesystem->tempnam(sys_get_temp_dir(), md5(\Phar::running())));
            $lockFile->write($lock);
            $lockContent = $lockFile->read();
            // Validates the JSON
        } catch (\Throwable $throwable) {
            $this->logger->error('Invalid composerLock for /api/packages/cloud.', ['composerLock' => $lock]);
            throw new BadRequestHttpException($throwable->getMessage(), $throwable);
        }
        try {
            if ($request->request->has('composerJson') && [] !== $json = $request->request->all('composerJson')) {
                $jsonFile = new JsonFile($this->filesystem->tempnam(sys_get_temp_dir(), md5(\Phar::running())));
                $jsonFile->write($json);
                $jsonFile->validateSchema(JsonFile::LAX_SCHEMA);
                if (!$this->isGranted('ROLE_INSTALL') && $jsonFile->read() !== $this->environment->getComposerJsonFile()->read()) {
                    throw $this->createAccessDeniedException('No permission to change the composer.json');
                }
                if (!$this->environment->createBackup()) {
                    $this->logger->error('Unable to create backup of composer files.', ['composerJson' => $json ?? null, 'composerLock' => $lock]);
                    throw new HttpException(Response::HTTP_INTERNAL_SERVER_ERROR, 'Unable to create backup of composer files.');
                }
                $backupCreated = \true;
                $this->environment->getComposerJsonFile()->write($jsonFile->read());
            }
        } catch (\Throwable $throwable) {
            $this->logger->error('Invalid composerJson for /api/packages/cloud: ' . $throwable->getMessage(), ['composerJson' => $json ?? null, 'composerLock' => $lock]);
            if ($throwable instanceof HttpExceptionInterface) {
                throw $throwable;
            }
            throw new BadRequestHttpException($throwable->getMessage(), $throwable);
        }
        try {
            Validator::createFromComposer($this->environment->getComposer(\true))->validate($lockContent, $this->environment->getComposerLock());
        } catch (\Throwable $throwable) {
            $this->logger->error('Invalid composerLock for /api/packages/cloud: ' . $throwable->getMessage(), ['composerJson' => $json ?? null, 'composerLock' => $lock]);
            if ($backupCreated) {
                $this->environment->restoreBackup();
            }
            throw new BadRequestHttpException($throwable->getMessage(), $throwable);
        }
        // Only write after composer.json was validated
        $this->environment->getComposerLockFile()->write($lockContent);
        return new JsonResponse($this->taskManager->createTask('composer/install', []));
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Contao Manager.
 *
 * (c) Contao Association
 *
 * @license LGPL-3.0-or-later
 */
namespace _ContaoManager\Contao\ManagerApi\Controller\Packages;

use Composer\Package\Dumper\ArrayDumper;
use Composer\Package\Link;
use Composer\Package\PackageInterface;
use Composer\Repository\InstalledRepository;
use Composer\Repository\InstalledRepositoryInterface;
use Composer\Repository\PlatformRepository;
use Composer\Repository\RootPackageRepository;
use _ContaoManager\Contao\ManagerApi\Composer\Environment;
use _ContaoManager\Symfony\Component\HttpFoundation\JsonResponse;
use _ContaoManager\Symfony\Component\HttpFoundation\Request;
use _ContaoManager\Symfony\Component\HttpFoundation\Response;
use _ContaoManager\Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
use _ContaoManager\Symfony\Component\Routing\Attribute\Route;
use _ContaoManager\Symfony\Component\Security\Http\Attribute\IsGranted;
#[Route(path: '/packages/local', methods: ['GET'])]
#[Route(path: '/packages/local/{name}', methods: ['GET'], requirements: ['name' => '.+'])]
#[IsGranted('ROLE_READ')]
class LocalPackagesController
{
    private readonly InstalledRepositoryInterface $localRepository;
    private readonly InstalledRepository $compositeRepository;
    public function __construct(private readonly Environment $environment)
    {
        $composer = $this->environment->getComposer();
        $this->localRepository = $composer->getRepositoryManager()->getLocalRepository();
        $this->compositeRepository = new InstalledRepository([new RootPackageRepository($composer->getPackage()), $this->localRepository, new PlatformRepository([], $composer->getConfig()->get('platform') ?: [])]);
    }
    public function __invoke(Request $request, string|null $name = null): Response
    {
        if (null !== $name) {
            return $this->getOnePackage($name, $request->getPreferredLanguage());
        }
        $dumper = new ArrayDumper();
        $packages = [];
        foreach ($this->localRepository->getPackages() as $package) {
            $packages[$package->getName()] = $this->environment->mergeMetadata($dumper->dump($package), $request->getPreferredLanguage());
            $packages[$package->getName()]['dependents'] = $this->getDependents($package);
        }
        return new JsonResponse($packages);
    }
    private function getOnePackage(string $name, string|null $language = null): Response
    {
        [$package] = array_values($this->localRepository->findPackages($name));
        if (!$package instanceof PackageInterface) {
            throw new NotFoundHttpException('Package "' . $name . '" is not installed');
        }
        $dumper = new ArrayDumper();
        $data = $this->environment->mergeMetadata($dumper->dump($package), $language);
        $data['dependents'] = $this->getDependents($package);
        return new JsonResponse($data);
    }
    private function getDependents(PackageInterface $package): array
    {
        $dependents = $this->parseDependents([$package->getName()]);
        if ([] === $dependents && [] !== $replaces = array_keys($package->getReplaces())) {
            return $this->parseDependents($replaces, \true);
        }
        return $dependents;
    }
    private function parseDependents(array $packageNames, bool $withReplaces = \false): array
    {
        $links = [];
        $dependents = $this->compositeRepository->getDependents($packageNames, null, \false, \false);
        foreach ($dependents as $dependent) {
            /** @var Link $link */
            [, $link] = $dependent;
            if (!$withReplaces && 'replaces' === $link->getDescription()) {
                continue;
            }
            $constraint = $link->getConstraint();
            $links[] = ['description' => $link->getDescription(), 'source' => $link->getSource(), 'target' => $link->getTarget(), 'constraint' => $constraint->getPrettyString()];
        }
        return $links;
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Contao Manager.
 *
 * (c) Contao Association
 *
 * @license LGPL-3.0-or-later
 */
namespace _ContaoManager\Contao\ManagerApi\Controller;

use Composer\Semver\VersionParser;
use _ContaoManager\Symfony\Component\HttpFoundation\JsonResponse;
use _ContaoManager\Symfony\Component\HttpFoundation\Request;
use _ContaoManager\Symfony\Component\HttpFoundation\Response;
use _ContaoManager\Symfony\Component\Routing\Attribute\Route;
use _ContaoManager\Symfony\Component\Security\Http\Attribute\IsGranted;
#[Route(path: '/constraint', methods: ['POST'])]
#[IsGranted('ROLE_UPDATE')]
class ConstraintController
{
    public function __invoke(Request $request): Response
    {
        if (!$request->request->has('constraint')) {
            return new Response('Missing constraint in POST data.', Response::HTTP_BAD_REQUEST);
        }
        try {
            $versionParser = new VersionParser();
            $versionParser->parseConstraints($request->request->get('constraint'));
        } catch (\Exception $exception) {
            return new JsonResponse(['valid' => \false, 'error' => $exception->getMessage()]);
        }
        return new JsonResponse(['valid' => \true, 'error' => null]);
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Contao Manager.
 *
 * (c) Contao Association
 *
 * @license LGPL-3.0-or-later
 */
namespace _ContaoManager\Contao\ManagerApi\Controller\Contao;

use Composer\Semver\Constraint\Constraint;
use Composer\Semver\Constraint\MultiConstraint;
use _ContaoManager\Contao\ManagerApi\ApiKernel;
use _ContaoManager\Contao\ManagerApi\HttpKernel\ApiProblemResponse;
use _ContaoManager\Contao\ManagerApi\Process\ContaoConsole;
use _ContaoManager\Crell\ApiProblem\ApiProblem;
use _ContaoManager\Symfony\Component\Filesystem\Filesystem;
use _ContaoManager\Symfony\Component\HttpFoundation\JsonResponse;
use _ContaoManager\Symfony\Component\HttpFoundation\Request;
use _ContaoManager\Symfony\Component\HttpFoundation\Response;
use _ContaoManager\Symfony\Component\Routing\Attribute\Route;
use _ContaoManager\Symfony\Component\Security\Http\Attribute\IsGranted;
#[Route(path: '/contao/install-tool/lock', methods: ['GET', 'PUT', 'DELETE'])]
#[IsGranted('ROLE_UPDATE')]
class InstallToolLockController
{
    private readonly string $lockFile;
    public function __construct(private readonly ContaoConsole $console, ApiKernel $kernel, private readonly Filesystem $filesystem)
    {
        $this->lockFile = $kernel->getProjectDir() . '/var/install_lock';
    }
    public function __invoke(Request $request): Response
    {
        try {
            $contaoVersion = $this->console->getVersion();
        } catch (\RuntimeException) {
            $contaoVersion = null;
        }
        if (null === $contaoVersion || (new MultiConstraint([new Constraint('<', '4.4.9'), new Constraint('>', '4.13.9999')], \false))->matches(new Constraint('=', $contaoVersion))) {
            return new ApiProblemResponse((new ApiProblem('Contao does not support locking the install tool.'))->setStatus(Response::HTTP_NOT_IMPLEMENTED));
        }
        return match ($request->getMethod()) {
            'GET' => $this->getLockStatus(),
            'PUT' => $this->lockInstallTool(),
            'DELETE' => $this->unlockInstallTool(),
            default => new Response(null, Response::HTTP_METHOD_NOT_ALLOWED),
        };
    }
    private function getLockStatus(): Response
    {
        return new JsonResponse(['locked' => $this->isLocked()]);
    }
    private function lockInstallTool(): Response
    {
        $this->filesystem->dumpFile($this->lockFile, '3');
        return $this->getLockStatus();
    }
    private function unlockInstallTool(): Response
    {
        $this->filesystem->remove($this->lockFile);
        return $this->getLockStatus();
    }
    private function isLocked(): bool
    {
        return $this->filesystem->exists($this->lockFile) && @file_get_contents($this->lockFile) >= 3;
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Contao Manager.
 *
 * (c) Contao Association
 *
 * @license LGPL-3.0-or-later
 */
namespace _ContaoManager\Contao\ManagerApi\Controller\Contao;

use _ContaoManager\Contao\ManagerApi\ApiKernel;
use _ContaoManager\Contao\ManagerApi\HttpKernel\ApiProblemResponse;
use _ContaoManager\Contao\ManagerApi\Process\ConsoleProcessFactory;
use _ContaoManager\Contao\ManagerApi\Process\ContaoConsole;
use _ContaoManager\Contao\ManagerApi\Process\ProcessController;
use _ContaoManager\Contao\ManagerApi\Task\TaskStatus;
use _ContaoManager\Crell\ApiProblem\ApiProblem;
use _ContaoManager\Symfony\Component\HttpFoundation\JsonResponse;
use _ContaoManager\Symfony\Component\HttpFoundation\Request;
use _ContaoManager\Symfony\Component\HttpFoundation\Response;
use _ContaoManager\Symfony\Component\HttpKernel\Exception\BadRequestHttpException;
use _ContaoManager\Symfony\Component\Routing\Attribute\Route;
use _ContaoManager\Symfony\Component\Security\Http\Attribute\IsGranted;
#[Route(path: '/contao/database-migration', methods: ['GET', 'PUT', 'DELETE'])]
#[IsGranted('ROLE_UPDATE')]
class DatabaseMigrationController
{
    public function __construct(private readonly ContaoConsole $console, private readonly ConsoleProcessFactory $processFactory, private readonly ApiKernel $kernel)
    {
    }
    public function __invoke(Request $request): Response
    {
        $commands = $this->console->getCommandList();
        if (!isset($commands['contao:migrate']['options']) || !\in_array('hash', $commands['contao:migrate']['options'], \true) || !\in_array('format', $commands['contao:migrate']['options'], \true) || !\in_array('dry-run', $commands['contao:migrate']['options'], \true)) {
            return new ApiProblemResponse((new ApiProblem('Contao does not support database migrations.'))->setStatus(Response::HTTP_NOT_IMPLEMENTED));
        }
        switch ($request->getMethod()) {
            case 'GET':
                return $this->getStatus();
            case 'PUT':
                if (null !== $this->getBackgroundProcess()) {
                    throw new BadRequestHttpException('A migration is already active');
                }
                $process = $this->createProcess($request->request->get('hash'), $request->request->get('type'), $request->request->getBoolean('withDeletes'));
                $process->setMeta(['skip_warnings' => $request->request->getBoolean('skipWarnings')]);
                $process->start();
                return new Response('', Response::HTTP_CREATED);
            case 'DELETE':
                if (null === $process = $this->getBackgroundProcess()) {
                    return new Response();
                }
                $process->delete();
                return new Response();
        }
        return new Response(null, Response::HTTP_METHOD_NOT_ALLOWED);
    }
    private function getStatus(): Response
    {
        $process = $this->getBackgroundProcess();
        if (null === $process) {
            return new Response('', Response::HTTP_NO_CONTENT);
        }
        $skipWarnings = (bool) ($process->getMeta()['skip_warnings'] ?? \false);
        $output = trim($process->getOutput());
        if ('' !== $output) {
            $lines = explode("\n", $output);
            while ($line = array_shift($lines)) {
                $data = json_decode($line, \true);
                $type = $data['type'] ?? null;
                if ('warning' === $type && $skipWarnings) {
                    continue;
                }
                if (\in_array($type, ['error', 'problem', 'warning'], \true)) {
                    array_unshift($lines, $line);
                    return $this->handleProblems($lines, $process);
                }
                if ('migration-pending' === $type && !empty($data['names'])) {
                    return $this->handleMigrations($data, $lines, $process);
                }
                if ('schema-pending' === $type && !empty($data['commands'])) {
                    return $this->handleSchema($data, $lines, $process);
                }
            }
        }
        return new JsonResponse(['type' => $this->getProcessType($process), 'status' => $this->getProcessStatus($process), 'operations' => [], 'hash' => null]);
    }
    private function createProcess(string|null $hash, string|null $type, bool $withDeletes): ProcessController
    {
        $args = ['contao:migrate', '--no-interaction', '--format=ndjson', null === $hash ? '--dry-run' : '--hash=' . $hash];
        switch ($type) {
            case 'migrations-only':
                $args[] = '--migrations-only';
                break;
            case 'schema-only':
                $args[] = '--schema-only';
                break;
        }
        if ($withDeletes && 'migrations-only' !== $type && null !== $hash) {
            $args[] = '--with-deletes';
        }
        return $this->processFactory->createContaoConsoleBackgroundProcess($args, 'database-migration');
    }
    private function getBackgroundProcess(): ProcessController|null
    {
        try {
            return $this->processFactory->restoreBackgroundProcess('database-migration');
        } catch (\Exception) {
            return null;
        }
    }
    private function handleProblems(array $lines, ProcessController $process): Response
    {
        $responseType = 'warning';
        $operations = [];
        foreach ($lines as $line) {
            $data = json_decode((string) $line, \true);
            $type = $data['type'] ?? null;
            if (!\in_array($type, ['error', 'problem', 'warning'], \true)) {
                continue;
            }
            if ('warning' !== $type) {
                $responseType = 'problem';
            }
            if ('error' === $type && isset($data['message'], $data['file'], $data['line'], $data['trace'])) {
                $operations[] = ['status' => 'error', 'name' => \sprintf('Exception in file %s on line %s', str_replace($this->kernel->getProjectDir() . '/', '', $data['file']), $data['line']), 'message' => $data['message'], 'trace' => str_replace($this->kernel->getProjectDir() . '/', '', $data['trace'])];
            } else {
                $message = explode("\n", $data['message'] ?? '', 2) + ['', ''];
                $operations[] = ['status' => 'error', 'name' => $message[0], 'message' => $message[1]];
            }
        }
        return new JsonResponse(['type' => $responseType, 'status' => $this->getProcessStatus($process), 'operations' => $operations]);
    }
    private function handleMigrations(array $pending, array $lines, ProcessController $process): Response
    {
        $operations = [];
        foreach ($pending['names'] as $name) {
            $operations[] = ['name' => $name, 'status' => 'pending', 'message' => ''];
        }
        $c = 0;
        foreach ($lines as $line) {
            $data = json_decode((string) $line, \true);
            if ('migration-result' === ($data['type'] ?? '')) {
                $operations[$c]['message'] = $data['message'];
                $operations[$c]['status'] = $data['isSuccessful'] ? TaskStatus::STATUS_COMPLETE : TaskStatus::STATUS_ERROR;
                ++$c;
            }
        }
        return new JsonResponse(['type' => $this->getProcessType($process, 'migrations'), 'status' => $this->getProcessStatus($process), 'operations' => array_values($operations), 'hash' => $pending['hash']]);
    }
    private function handleSchema(array $pending, array $lines, ProcessController $process): Response
    {
        $operations = [];
        foreach ($pending['commands'] as $name) {
            $operations[$name] = ['name' => $name, 'status' => !$process->isRunning() && !$process->isSuccessful() ? TaskStatus::STATUS_ERROR : 'pending', 'message' => ''];
        }
        foreach ($lines as $line) {
            $data = json_decode((string) $line, \true);
            $type = $data['type'] ?? '';
            $name = $data['command'] ?? '';
            if ('schema-execute' === $type) {
                $operations[$name]['status'] = TaskStatus::STATUS_ACTIVE;
                continue;
            }
            if ('schema-result' === $type) {
                $operations[$name]['status'] = $data['isSuccessful'] ? TaskStatus::STATUS_COMPLETE : TaskStatus::STATUS_ERROR;
                $operations[$name]['message'] = $data['message'] ?? '';
            }
        }
        return new JsonResponse(['type' => $this->getProcessType($process, 'schema'), 'status' => $this->getProcessStatus($process), 'operations' => array_values($operations), 'hash' => $pending['hash']]);
    }
    private function getProcessStatus(ProcessController $process): string
    {
        if (!$process->isStarted()) {
            $process->start();
            return TaskStatus::STATUS_ACTIVE;
        }
        if ($process->isRunning()) {
            return TaskStatus::STATUS_ACTIVE;
        }
        if ($process->isSuccessful()) {
            if (str_contains($process->getCommandLine(), '--dry-run')) {
                return 'pending';
            }
            return TaskStatus::STATUS_COMPLETE;
        }
        return TaskStatus::STATUS_ERROR;
    }
    private function getProcessType(ProcessController $process, string $default = ''): string
    {
        if (str_contains($process->getCommandLine(), '--schema-only')) {
            return 'schema-only';
        }
        if (str_contains($process->getCommandLine(), '--migrations-only')) {
            return 'migrations-only';
        }
        return $default;
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Contao Manager.
 *
 * (c) Contao Association
 *
 * @license LGPL-3.0-or-later
 */
namespace _ContaoManager\Contao\ManagerApi\Controller\Contao;

use _ContaoManager\Contao\ManagerApi\HttpKernel\ApiProblemResponse;
use _ContaoManager\Contao\ManagerApi\Process\ContaoApi;
use _ContaoManager\Crell\ApiProblem\ApiProblem;
use _ContaoManager\Seld\JsonLint\ParsingException;
use _ContaoManager\Symfony\Component\HttpFoundation\JsonResponse;
use _ContaoManager\Symfony\Component\HttpFoundation\Request;
use _ContaoManager\Symfony\Component\HttpFoundation\Response;
use _ContaoManager\Symfony\Component\Routing\Attribute\Route;
use _ContaoManager\Symfony\Component\Security\Http\Attribute\IsGranted;
#[Route(path: '/contao/access-key', methods: ['GET', 'PUT', 'DELETE'])]
#[IsGranted('ROLE_UPDATE')]
class AccessKeyController
{
    public function __construct(private readonly ContaoApi $api)
    {
    }
    /**
     * Handles the controller action.
     *
     * @throws ParsingException
     */
    public function __invoke(Request $request): Response
    {
        return match ($request->getMethod()) {
            'GET' => $this->getAccessKey(),
            'PUT' => $this->setAccessKey($request),
            'DELETE' => $this->removeAccessKey(),
            default => new Response(null, Response::HTTP_METHOD_NOT_ALLOWED),
        };
    }
    /**
     * @throws ParsingException
     */
    private function getAccessKey(): Response
    {
        if (!$this->isSupported('get')) {
            return new ApiProblemResponse((new ApiProblem('Contao does not support the access-key API.'))->setStatus(Response::HTTP_NOT_IMPLEMENTED));
        }
        return new JsonResponse(['access-key' => $this->api->runCommand($this->getAccessKeyArguments('get'))]);
    }
    /**
     * @throws ParsingException
     */
    private function setAccessKey(Request $request): Response
    {
        if (!$this->isSupported('set')) {
            return new Response(null, Response::HTTP_NOT_IMPLEMENTED);
        }
        if (!$request->request->has('user') || !$request->request->has('password')) {
            return new Response(null, Response::HTTP_BAD_REQUEST);
        }
        $user = $request->request->get('user');
        $password = $request->request->get('password');
        $accessKey = password_hash($user . ':' . $password, \PASSWORD_DEFAULT);
        $this->api->runCommand(array_merge($this->getAccessKeyArguments('set'), [$accessKey]));
        return new JsonResponse(['access-key' => $accessKey]);
    }
    /**
     * @throws ParsingException
     */
    private function removeAccessKey(): Response
    {
        if (!$this->isSupported('remove')) {
            return new Response(null, Response::HTTP_NOT_IMPLEMENTED);
        }
        $this->api->runCommand($this->getAccessKeyArguments('remove'));
        return new JsonResponse(['access-key' => '']);
    }
    private function getAccessKeyArguments(string $action): array
    {
        if (1 === $this->api->getVersion()) {
            return ['access-key:' . $action];
        }
        return ['dot-env:' . $action, 'APP_DEV_ACCESSKEY'];
    }
    /**
     * Returns whether access key command is supported.
     */
    private function isSupported(string $action): bool
    {
        return 1 === $this->api->getVersion() || $this->api->hasCommand('dot-env:' . $action) && \in_array('APP_DEV_ACCESSKEY', $this->api->getFeatures()['contao/manager-bundle']['dot-env'], \true);
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Contao Manager.
 *
 * (c) Contao Association
 *
 * @license LGPL-3.0-or-later
 */
namespace _ContaoManager\Contao\ManagerApi\Controller\Contao;

use _ContaoManager\Contao\ManagerApi\Exception\ProcessOutputException;
use _ContaoManager\Contao\ManagerApi\HttpKernel\ApiProblemResponse;
use _ContaoManager\Contao\ManagerApi\Process\ConsoleProcessFactory;
use _ContaoManager\Contao\ManagerApi\Process\ContaoConsole;
use _ContaoManager\Crell\ApiProblem\ApiProblem;
use _ContaoManager\Symfony\Component\HttpFoundation\JsonResponse;
use _ContaoManager\Symfony\Component\HttpFoundation\Request;
use _ContaoManager\Symfony\Component\HttpFoundation\Response;
use _ContaoManager\Symfony\Component\Routing\Attribute\Route;
use _ContaoManager\Symfony\Component\Security\Http\Attribute\IsGranted;
#[Route(path: '/contao/backup', methods: ['GET'])]
#[IsGranted('ROLE_UPDATE')]
class BackupController
{
    public function __construct(private readonly ContaoConsole $console, private readonly ConsoleProcessFactory $processFactory)
    {
    }
    public function __invoke(Request $request): Response
    {
        $commands = $this->console->getCommandList();
        if (!\array_key_exists('contao:backup:list', $commands) || !\array_key_exists('contao:backup:create', $commands) || !\array_key_exists('contao:backup:restore', $commands)) {
            return new ApiProblemResponse((new ApiProblem('Contao does not support backups.'))->setStatus(Response::HTTP_NOT_IMPLEMENTED));
        }
        $arguments = ['contao:backup:list', '--format=json', '--no-interaction'];
        $process = $this->processFactory->createContaoConsoleProcess($arguments);
        $process->run();
        $data = json_decode(trim($process->getOutput()), \true);
        if (!\is_array($data)) {
            throw new ProcessOutputException('Invalid response for listing backups.', $process);
        }
        return new JsonResponse($data);
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Contao Manager.
 *
 * (c) Contao Association
 *
 * @license LGPL-3.0-or-later
 */
namespace _ContaoManager\Contao\ManagerApi\Controller\Contao;

use _ContaoManager\Contao\ManagerApi\ApiKernel;
use _ContaoManager\Contao\ManagerApi\HttpKernel\ApiProblemResponse;
use _ContaoManager\Contao\ManagerApi\Process\ConsoleProcessFactory;
use _ContaoManager\Contao\ManagerApi\Process\ContaoConsole;
use _ContaoManager\Crell\ApiProblem\ApiProblem;
use _ContaoManager\Symfony\Component\Filesystem\Filesystem;
use _ContaoManager\Symfony\Component\HttpFoundation\JsonResponse;
use _ContaoManager\Symfony\Component\HttpFoundation\Request;
use _ContaoManager\Symfony\Component\HttpFoundation\Response;
use _ContaoManager\Symfony\Component\Routing\Attribute\Route;
use _ContaoManager\Symfony\Component\Security\Http\Attribute\IsGranted;
#[Route(path: '/contao/maintenance-mode', methods: ['GET', 'PUT', 'DELETE'])]
#[IsGranted('ROLE_UPDATE')]
class MaintenanceModeController
{
    public function __construct(private readonly ContaoConsole $console, private readonly ConsoleProcessFactory $processFactory, private readonly ApiKernel $kernel, private readonly Filesystem $filesystem)
    {
    }
    public function __invoke(Request $request): Response
    {
        try {
            $commands = $this->console->getCommandList();
        } catch (\RuntimeException) {
            $commands = [];
        }
        $hasLexik = \array_key_exists('lexik:maintenance:lock', $commands) && \array_key_exists('lexik:maintenance:unlock', $commands);
        if (!$hasLexik && !\array_key_exists('contao:maintenance-mode', $commands)) {
            return new ApiProblemResponse((new ApiProblem('Contao does not support maintenance mode.'))->setStatus(Response::HTTP_NOT_IMPLEMENTED));
        }
        return match ($request->getMethod()) {
            'GET' => $this->getStatus($hasLexik),
            'PUT' => $this->enable($hasLexik),
            'DELETE' => $this->disable($hasLexik),
            default => new Response(null, Response::HTTP_METHOD_NOT_ALLOWED),
        };
    }
    private function getStatus(bool $lexik): Response
    {
        if ($lexik) {
            return new JsonResponse(['enabled' => $this->filesystem->exists($this->kernel->getProjectDir() . '/var/maintenance_lock')]);
        }
        return new JsonResponse($this->runContaoCommand());
    }
    private function enable(bool $lexik): Response
    {
        if ($lexik) {
            return new JsonResponse(['enabled' => $this->runLexikCommand('lock')]);
        }
        return new JsonResponse($this->runContaoCommand('enable'));
    }
    private function disable(bool $lexik): Response
    {
        if ($lexik) {
            return new JsonResponse(['enabled' => !$this->runLexikCommand('unlock')]);
        }
        return new JsonResponse($this->runContaoCommand('disable'));
    }
    private function runContaoCommand(string|null $state = null): array
    {
        $arguments = ['contao:maintenance'];
        if (null !== $state) {
            $arguments[] = $state;
        }
        $arguments[] = '--format=json';
        $arguments[] = '--no-interaction';
        $process = $this->processFactory->createContaoConsoleProcess($arguments);
        $process->run();
        $data = json_decode(trim($process->getOutput()), \true);
        if (!\is_array($data)) {
            return ['enabled' => \false];
        }
        return $data;
    }
    private function runLexikCommand(string $command): bool
    {
        $process = $this->processFactory->createContaoConsoleProcess(['lexik:maintenance:' . $command, '--no-interaction']);
        $process->run();
        return $process->isSuccessful();
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Contao Manager.
 *
 * (c) Contao Association
 *
 * @license LGPL-3.0-or-later
 */
namespace _ContaoManager\Contao\ManagerApi\Controller\Contao;

use _ContaoManager\Contao\ManagerApi\HttpKernel\ApiProblemResponse;
use _ContaoManager\Contao\ManagerApi\Process\ContaoApi;
use _ContaoManager\Crell\ApiProblem\ApiProblem;
use _ContaoManager\Seld\JsonLint\ParsingException;
use _ContaoManager\Symfony\Component\HttpFoundation\Cookie;
use _ContaoManager\Symfony\Component\HttpFoundation\JsonResponse;
use _ContaoManager\Symfony\Component\HttpFoundation\Request;
use _ContaoManager\Symfony\Component\HttpFoundation\Response;
use _ContaoManager\Symfony\Component\Routing\Attribute\Route;
use _ContaoManager\Symfony\Component\Security\Http\Attribute\IsGranted;
#[Route(path: '/contao/jwt-cookie', methods: ['GET', 'PUT', 'DELETE'])]
#[IsGranted('ROLE_UPDATE')]
class JwtCookieController
{
    public const COOKIE_NAME = 'contao_settings';
    public function __construct(private readonly ContaoApi $api)
    {
    }
    /**
     * Handles the controller action.
     *
     * @throws ParsingException
     */
    public function __invoke(Request $request): ApiProblemResponse|Response
    {
        if (!$this->isSupported()) {
            return new ApiProblemResponse((new ApiProblem('Contao does not support the jwt-token API.'))->setStatus(Response::HTTP_NOT_IMPLEMENTED));
        }
        return match ($request->getMethod()) {
            'GET' => $this->getJwtPayload($request),
            'PUT' => $this->setJwtToken($request),
            'DELETE' => $this->removeJwtToken(),
            default => new Response(null, Response::HTTP_METHOD_NOT_ALLOWED),
        };
    }
    /**
     * @throws ParsingException
     */
    private function getJwtPayload(Request $request): Response
    {
        if (!$request->cookies->has(self::COOKIE_NAME)) {
            return new Response('', Response::HTTP_NO_CONTENT);
        }
        $payload = $this->api->runJsonCommand(['jwt-cookie:parse', $request->cookies->get(self::COOKIE_NAME)]);
        return new JsonResponse($payload);
    }
    /**
     * @throws ParsingException
     */
    private function setJwtToken(Request $request): Response
    {
        $arguments = ['jwt-cookie:generate'];
        if ($request->request->getBoolean('debug')) {
            $arguments[] = '--debug';
        }
        $cookie = Cookie::fromString($this->api->runCommand($arguments));
        $response = new JsonResponse(['debug' => $request->request->getBoolean('debug')]);
        $response->headers->setCookie($cookie);
        return $response;
    }
    private function removeJwtToken(): Response
    {
        $response = new Response('', Response::HTTP_NO_CONTENT);
        $response->headers->clearCookie(self::COOKIE_NAME);
        return $response;
    }
    private function isSupported(): bool
    {
        $features = $this->api->getFeatures();
        return isset($features['contao/manager-bundle']['jwt-cookie']) && \in_array('debug', $features['contao/manager-bundle']['jwt-cookie'], \true);
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Contao Manager.
 *
 * (c) Contao Association
 *
 * @license LGPL-3.0-or-later
 */
namespace _ContaoManager\Contao\ManagerApi;

use Composer\Util\ErrorHandler;
use _ContaoManager\Contao\ManagerApi\Exception\ApiProblemException;
use _ContaoManager\Contao\ManagerApi\I18n\Translator;
use _ContaoManager\Crell\ApiProblem\ApiProblem;
use _ContaoManager\Symfony\Bundle\FrameworkBundle\FrameworkBundle;
use _ContaoManager\Symfony\Bundle\MonologBundle\MonologBundle;
use _ContaoManager\Symfony\Bundle\SecurityBundle\SecurityBundle;
use _ContaoManager\Symfony\Component\Config\Loader\LoaderInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerInterface;
use _ContaoManager\Symfony\Component\Filesystem\Exception\IOException;
use _ContaoManager\Symfony\Component\Filesystem\Filesystem;
use _ContaoManager\Symfony\Component\HttpFoundation\Request;
use _ContaoManager\Symfony\Component\HttpFoundation\RequestStack;
use _ContaoManager\Symfony\Component\HttpKernel\Kernel;
use _ContaoManager\Symfony\Component\Routing\RouteCollection;
/**
 * @property ContainerInterface $container
 */
class ApiKernel extends Kernel
{
    public const MANAGER_VERSION = '1.10.13';
    public const VERSION_KEY = '@manager_version' . '@';
    private string|null $projectDir = null;
    private string|null $configDir = null;
    private string|null $publicDir = null;
    private readonly Filesystem $filesystem;
    public function __construct(string $environment)
    {
        $this->filesystem = new Filesystem();
        $debug = 'dev' === $environment;
        ErrorHandler::register();
        error_reporting($debug ? \E_ALL : \E_ERROR | \E_PARSE | \E_CORE_ERROR | \E_COMPILE_ERROR);
        ini_set('display_errors', $debug ? '1' : '0');
        ini_set('error_log', $this->getLogDir() . \DIRECTORY_SEPARATOR . 'error-' . date('Y-m-d') . '.log');
        parent::__construct($environment, $debug);
        $this->configureComposerEnvironment();
    }
    public function isWebDir(): bool
    {
        $publicDir = $this->getPublicDir();
        return 'web' === \dirname($publicDir) && $publicDir !== $this->getProjectDir();
    }
    public function getRootDir(): string
    {
        return __DIR__;
    }
    public function getProjectDir(): string
    {
        if (null === $this->projectDir) {
            $this->findProjectDir();
        }
        return $this->projectDir;
    }
    public function getPublicDir(): string
    {
        $this->getProjectDir();
        return $this->publicDir;
    }
    public function getCacheDir(): string
    {
        $cacheDir = $this->debug ? $this->getConfigDir() . '/appcache' : __DIR__ . '/Resources/cache';
        $this->ensureDirectoryExists($cacheDir);
        return $cacheDir;
    }
    public function getLogDir(): string
    {
        $logDir = $this->getConfigDir() . '/logs';
        $this->ensureDirectoryExists($logDir);
        return $logDir;
    }
    /**
     * Gets the directory where to place manager files like config and logs.
     */
    public function getConfigDir(): string
    {
        if (null !== $this->configDir) {
            return $this->configDir;
        }
        $this->configDir = $this->getProjectDir() . \DIRECTORY_SEPARATOR . 'contao-manager';
        if (!self::isPhar()) {
            return $this->configDir;
        }
        // Try to find a config directory in the parent from previous version
        if (!$this->filesystem->exists($this->configDir)) {
            $parentDir = \dirname($this->getProjectDir()) . \DIRECTORY_SEPARATOR . 'contao-manager';
            if ($this->filesystem->exists($parentDir . '/manager.json')) {
                $this->filesystem->mirror($parentDir, $this->configDir);
            }
            $this->ensureDirectoryExists($this->configDir);
        }
        // Make sure the config directory contains a .htaccess file
        if (!$this->filesystem->exists($this->configDir . \DIRECTORY_SEPARATOR . '.htaccess')) {
            $this->filesystem->dumpFile($this->configDir . \DIRECTORY_SEPARATOR . '.htaccess', <<<'CODE'
<IfModule !mod_authz_core.c>
    Order deny,allow
    Deny from all
</IfModule>
<IfModule mod_authz_core.c>
    Require all denied
</IfModule>
CODE
);
        }
        return $this->configDir;
    }
    public function getTranslator(): Translator
    {
        if ($this->container) {
            return $this->container->get(Translator::class);
        }
        // The kernel has not been bootet successfully, manually create a translator
        $requestStack = new RequestStack();
        $requestStack->push(Request::createFromGlobals());
        return new Translator($requestStack);
    }
    public function registerBundles(): array
    {
        return [new FrameworkBundle(), new SecurityBundle(), new MonologBundle()];
    }
    public function registerContainerConfiguration(LoaderInterface $loader): void
    {
        $loader->load(__DIR__ . '/Resources/config/config_' . $this->environment . '.yaml');
    }
    /**
     * Loads the routes using framework.router config. We must use a loader method not
     * e.g. a routes.yaml because of dynamic path to the Phar.
     */
    public function loadRoutes(LoaderInterface $loader): RouteCollection
    {
        $resolver = $loader->getResolver()->resolve(__DIR__ . '/Controller', 'attribute');
        $routes = $resolver->load(__DIR__ . '/Controller', 'attribute');
        $routes->addPrefix('api');
        return $routes;
    }
    public static function isPhar(): bool
    {
        return '' !== \Phar::running(\false);
    }
    /**
     * Configures the Composer environment variables to match the current setup.
     */
    private function configureComposerEnvironment(): void
    {
        $root = $this->getProjectDir();
        putenv('COMPOSER=' . $root . \DIRECTORY_SEPARATOR . 'composer.json');
        putenv('COMPOSER_HOME=' . $this->getConfigDir());
        putenv('COMPOSER_HTACCESS_PROTECT=0');
        chdir($root);
    }
    /**
     * Finds the Contao installation directory depending on the Phar file or
     * development mode.
     */
    private function findProjectDir(): void
    {
        // @see https://getcomposer.org/doc/03-cli.md#composer
        if (\false !== $composer = getenv('COMPOSER')) {
            // We don't know the public dir when running on command line, but it shouldn't matter
            $this->projectDir = \dirname($composer);
            $this->publicDir = $this->projectDir;
            return;
        }
        // Not a phar file, use test directory in local development
        if (!self::isPhar()) {
            $this->projectDir = \dirname(__DIR__) . \DIRECTORY_SEPARATOR . 'test-dir';
            $this->publicDir = $this->projectDir . '/web';
            $this->ensureDirectoryExists($this->publicDir);
            return;
        }
        // Use the current working directory in CLI mode
        if (('cli' === \PHP_SAPI || !isset($_SERVER['REQUEST_URI'])) && !empty($_SERVER['PWD'])) {
            // We don't know the public dir when running on command line, but it shouldn't matter
            $this->projectDir = $_SERVER['PWD'];
            $this->publicDir = $_SERVER['PWD'];
            return;
        }
        $current = getcwd();
        if (!$current) {
            $current = \dirname(\Phar::running(\false));
        }
        // Always use current folder if it is not named "web" or "public"
        if ('web' !== basename($current) && 'public' !== basename($current)) {
            $this->projectDir = $current;
            $this->publicDir = $current;
            return;
        }
        $contaoFiles = ['/vendor/contao/manager-bundle/bin/contao-console', '/system/constants.php', '/system/config/constants.php'];
        if ($this->debug) {
            $contaoFiles[] = '/vendor/contao/contao/manager-bundle/bin/contao-console';
        }
        // Use current folder if it looks like Contao
        foreach ($contaoFiles as $file) {
            if ($this->filesystem->exists($current . $file)) {
                $this->projectDir = $current;
                $this->publicDir = $current;
                return;
            }
        }
        // Throw exception if parent folder looks like Contao but is not writeable
        if (!is_writable(\dirname($current))) {
            $files = [\dirname($current) . '/vendor/contao/manager-bundle/bin/contao-console', \dirname($current) . '/system/constants.php', \dirname($current) . '/system/config/constants.php'];
            if ($this->debug) {
                $files[] = \dirname($current) . '/vendor/contao/contao/manager-bundle/bin/contao-console';
            }
            foreach ($files as $file) {
                if ($this->filesystem->exists($file)) {
                    $translator = $this->getTranslator();
                    $problem = (new ApiProblem($translator->trans('error.writable.root', ['path' => \dirname($current)]), 'https://php.net/is_writable'))->setDetail($translator->trans('error.writable.detail'));
                    throw new ApiProblemException($problem);
                }
            }
        }
        $this->publicDir = $current;
        $this->projectDir = \dirname($current);
    }
    private function ensureDirectoryExists(string $directory): void
    {
        try {
            $this->filesystem->mkdir($directory);
        } catch (IOException $exception) {
            $translator = $this->getTranslator();
            $problem = new ApiProblem($translator->trans('error.writable.directory', ['path' => $exception->getPath()]));
            $problem->setDetail($translator->trans('error.writable.detail'));
            throw new ApiProblemException($problem, $exception);
        }
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Contao Manager.
 *
 * (c) Contao Association
 *
 * @license LGPL-3.0-or-later
 */
namespace _ContaoManager\Contao\ManagerApi\System;

use _ContaoManager\Contao\ManagerApi\Config\ManagerConfig;
use _ContaoManager\Contao\ManagerApi\Process\Forker\DisownForker;
use _ContaoManager\Contao\ManagerApi\Process\Forker\ForkerInterface;
use _ContaoManager\Contao\ManagerApi\Process\Forker\InlineForker;
use _ContaoManager\Contao\ManagerApi\Process\Forker\NohupForker;
use _ContaoManager\Contao\ManagerApi\Process\Forker\WindowsStartForker;
use _ContaoManager\Contao\ManagerApi\Process\PhpExecutableFinder;
class ServerInfo
{
    public const PLATFORM_WINDOWS = 'windows';
    public const PLATFORM_UNIX = 'unix';
    private const PHP_BINARIES = ['/opt/plesk/php/{major}.{minor}/bin/php', '/bin/php{major}{minor}', '/opt/RZphp{major}{minor}/bin/php-cli', '/opt/alt/php{major}{minor}/usr/bin/php', '/opt/php-{major}.{minor}.{release}/bin/php', '/opt/php-{major}.{minor}/bin/php', '/opt/php{major}.{minor}/bin/php', '/opt/php{major}{minor}/bin/php', '/opt/php{major}/bin/php', '/usr/bin/php{major}.{minor}-cli', '/usr/bin/php{major}.{minor}', '/usr/bin/php{major}{minor}', '/usr/bin/php{major}{minor}/php{major}', '/usr/bin/php{major}', '/usr/bin/php', '/usr/iports/php{major}{minor}/bin/php', '/usr/lib/cgi-bin/php{major}.{minor}', '/usr/lib64/php{major}.{minor}/bin/php', '/usr/local/bin/edis-php-cli-{major}{minor}-stable-openssl', '/usr/local/bin/edis-php-cli-{major}{minor}', '/usr/local/bin/php_cli', '/usr/local/bin/php', '/usr/local/bin/php{major}-{major}{minor}LATEST-CLI', '/usr/local/bin/php{major}.{minor}.{release}-cli', '/usr/local/php-{major}.{minor}/bin/php', '/usr/local/php{major}{minor}/bin/php', '/usr/local/phpfarm/inst/php-{major}.{minor}/bin/php', '/usr/local/php{major}{minor}/bin/php', '/opt/phpbrew/php/php-{major}.{minor}/bin/php', '/opt/phpfarm/inst/php-{major}.{minor}/bin/php-cgi', '/vrmd/webserver/php{major}{minor}/bin/php', '/package/host/localhost/php-{major}.{minor}/bin/php', '/Applications/MAMP/bin/php/php{major}.{minor}.{release}/bin/php', 'C:\XAMPP\php\php.exe', 'D:\XAMPP\php\php.exe', 'C:\MAMP\bin\php\php{major}.{minor}.{release}\php.exe', 'D:\MAMP\bin\php\php{major}.{minor}.{release}\php.exe', 'D:\laragon\bin\php\php-{major}.{minor}.{release}-Win32-VC15-x64\php.EXE', 'C:\laragon\bin\php\php-{major}.{minor}.{release}-Win32-VC15-x64\php.EXE'];
    public function __construct(private readonly PhpExecutableFinder $phpExecutableFinder, private readonly ManagerConfig $managerConfig)
    {
    }
    public function getPhpExecutableFinder(): PhpExecutableFinder
    {
        return $this->phpExecutableFinder;
    }
    /**
     * Gets PHP executable by detecting known server paths.
     */
    public function getPhpExecutable(): string|null
    {
        $paths = [];
        if ($php_cli = $this->managerConfig->get('php_cli')) {
            $paths[] = $php_cli;
        }
        foreach (self::PHP_BINARIES as $path) {
            $paths[] = $this->getPhpVersionPath($path);
        }
        $found = $this->phpExecutableFinder->find($paths);
        if ($php_cli && $found !== $php_cli) {
            $this->managerConfig->set('php_cli', $found);
        }
        return $found;
    }
    /**
     * Gets environment variables for the PHP command line process.
     */
    public function getPhpEnv(): array
    {
        return ['PHP_PATH' => $this->getPhpExecutable()];
    }
    /**
     * Returns the background process forker classes for the current server.
     *
     * @return array<class-string<ForkerInterface>>
     */
    public function getProcessForkers(): array
    {
        if (self::PLATFORM_WINDOWS === $this->getPlatform()) {
            return [WindowsStartForker::class, InlineForker::class];
        }
        return [DisownForker::class, NohupForker::class, InlineForker::class];
    }
    /**
     * Returns the server platform (Windows or UNIX).
     */
    public function getPlatform(): string
    {
        return '\\' === \DIRECTORY_SEPARATOR ? self::PLATFORM_WINDOWS : self::PLATFORM_UNIX;
    }
    /**
     * Gets versionised path to PHP binary.
     */
    private function getPhpVersionPath(string $path): string
    {
        return str_replace(['{major}', '{minor}', '{release}', '{extra}'], [\PHP_MAJOR_VERSION, \PHP_MINOR_VERSION, \PHP_RELEASE_VERSION, \PHP_EXTRA_VERSION], $path);
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Contao Manager.
 *
 * (c) Contao Association
 *
 * @license LGPL-3.0-or-later
 */
namespace _ContaoManager\Contao\ManagerApi\System;

use Composer\CaBundle\CaBundle;
use Composer\Util\Platform;
use Composer\Util\StreamContextFactory;
use _ContaoManager\Contao\ManagerApi\ApiKernel;
use _ContaoManager\Contao\ManagerApi\Exception\RequestException;
use _ContaoManager\Psr\Log\LoggerInterface;
class Request
{
    private const DEFAULT_TIMEOUT = 5;
    public function __construct(private readonly LoggerInterface|null $logger = null)
    {
    }
    public function get(string $url, ?int &$statusCode = null, bool $catch = \false, int $timeout = self::DEFAULT_TIMEOUT): string|null
    {
        return $this->getContent($url, $statusCode, [], $catch, $timeout);
    }
    /**
     * @return resource|false
     */
    public function getStream(string $url, ?int &$statusCode = null, bool $catch = \false)
    {
        $context = $this->createStreamContext($url, 0);
        try {
            $stream = fopen($url, 'r', \false, $context);
            $statusCode = $this->getLastStatusCode($http_response_header);
        } catch (\Throwable $throwable) {
            if ($catch) {
                return \false;
            }
            throw new RequestException($url, $this->getLastStatusCode($http_response_header ?? null), $throwable);
        }
        return $stream;
    }
    public function getJson(string $url, array $headers = [], ?int &$statusCode = null, bool $catch = \false): string|null
    {
        $headers[] = 'Accept: application/json';
        return $this->getContent($url, $statusCode, ['http' => ['header' => $headers]], $catch);
    }
    public function postJson(string $url, string $content, array $headers = [], ?int &$statusCode = null, bool $catch = \false): string|null
    {
        $headers[] = 'Accept: application/json';
        $headers[] = 'Content-Type: application/json';
        $options = ['http' => ['method' => 'POST', 'header' => $headers, 'content' => $content]];
        return $this->getContent($url, $statusCode, $options, $catch);
    }
    public function deleteJson(string $url, array $headers = [], ?int &$statusCode = null, bool $catch = \false): string|null
    {
        $headers[] = 'Accept: application/json';
        $options = ['http' => ['method' => 'DELETE', 'header' => $headers]];
        return $this->getContent($url, $statusCode, $options, $catch);
    }
    private function getContent(string $url, ?int &$statusCode, array $options, bool $catch, int $timeout = self::DEFAULT_TIMEOUT): string|null
    {
        $context = $this->createStreamContext($url, $timeout, $options);
        try {
            if (\false === $content = file_get_contents($url, \false, $context)) {
                throw new \RuntimeException();
            }
            $statusCode = $this->getLastStatusCode($http_response_header);
        } catch (\Throwable $throwable) {
            if ($catch) {
                return null;
            }
            throw new RequestException($url, $this->getLastStatusCode($http_response_header ?? null), $throwable);
        }
        return $content;
    }
    /**
     * @return resource
     */
    private function createStreamContext(string $url, int $timeout = self::DEFAULT_TIMEOUT, array $options = [])
    {
        $tlsDefaults = $this->getTlsDefaults($options);
        $options = array_replace_recursive($tlsDefaults, $options);
        if ($timeout > 0) {
            $options['http']['timeout'] ??= $timeout;
        }
        $options['http']['ignore_errors'] ??= \true;
        if (isset($options['http']['header']) && !\is_array($options['http']['header'])) {
            $options['http']['header'] = [$options['http']['header']];
        }
        $options['http']['header'][] = \sprintf('User-Agent: Contao Manager/%s (%s; %s; %s%s)', ApiKernel::VERSION_KEY === ApiKernel::MANAGER_VERSION ? 'source' : ApiKernel::MANAGER_VERSION, \function_exists('php_uname') ? php_uname('s') : 'Unknown', \function_exists('php_uname') ? php_uname('r') : 'Unknown', 'PHP ' . \PHP_MAJOR_VERSION . '.' . \PHP_MINOR_VERSION . '.' . \PHP_RELEASE_VERSION, Platform::getEnv('CI') ? '; CI' : '');
        return StreamContextFactory::getContext($url, $options);
    }
    /**
     * @see \Composer\Util\RemoteFilesystem::getTlsDefaults()
     */
    private function getTlsDefaults(array $options): array
    {
        $ciphers = implode(':', ['ECDHE-RSA-AES128-GCM-SHA256', 'ECDHE-ECDSA-AES128-GCM-SHA256', 'ECDHE-RSA-AES256-GCM-SHA384', 'ECDHE-ECDSA-AES256-GCM-SHA384', 'DHE-RSA-AES128-GCM-SHA256', 'DHE-DSS-AES128-GCM-SHA256', 'kEDH+AESGCM', 'ECDHE-RSA-AES128-SHA256', 'ECDHE-ECDSA-AES128-SHA256', 'ECDHE-RSA-AES128-SHA', 'ECDHE-ECDSA-AES128-SHA', 'ECDHE-RSA-AES256-SHA384', 'ECDHE-ECDSA-AES256-SHA384', 'ECDHE-RSA-AES256-SHA', 'ECDHE-ECDSA-AES256-SHA', 'DHE-RSA-AES128-SHA256', 'DHE-RSA-AES128-SHA', 'DHE-DSS-AES128-SHA256', 'DHE-RSA-AES256-SHA256', 'DHE-DSS-AES256-SHA', 'DHE-RSA-AES256-SHA', 'AES128-GCM-SHA256', 'AES256-GCM-SHA384', 'AES128-SHA256', 'AES256-SHA256', 'AES128-SHA', 'AES256-SHA', 'AES', 'CAMELLIA', 'DES-CBC3-SHA', '!aNULL', '!eNULL', '!EXPORT', '!DES', '!RC4', '!MD5', '!PSK', '!aECDH', '!EDH-DSS-DES-CBC3-SHA', '!EDH-RSA-DES-CBC3-SHA', '!KRB5-DES-CBC3-SHA']);
        /**
         * CN_match and SNI_server_name are only known once a URL is passed. They will be
         * set in the getOptionsForUrl() method which receives a URL.
         *
         * cafile or capath can be overridden by passing in those options to constructor.
         */
        $defaults = ['ssl' => ['ciphers' => $ciphers, 'verify_peer' => \true, 'verify_depth' => 7, 'SNI_enabled' => \true]];
        if (isset($options['ssl'])) {
            $defaults['ssl'] = array_replace_recursive($defaults['ssl'], $options['ssl']);
        }
        /*
         * Attempt to find a local cafile or throw an exception if none pre-set
         * The user may go download one if this occurs.
         */
        if (!isset($defaults['ssl']['cafile']) && !isset($defaults['ssl']['capath'])) {
            $result = CaBundle::getSystemCaRootBundlePath($this->logger);
            if (is_dir($result)) {
                $defaults['ssl']['capath'] = $result;
            } else {
                $defaults['ssl']['cafile'] = $result;
            }
        }
        /*
         * Disable TLS compression to prevent CRIME attacks where supported.
         */
        $defaults['ssl']['disable_compression'] = \true;
        return $defaults;
    }
    private function getLastStatusCode(array|null $http_response_header): int
    {
        if (!\is_array($http_response_header)) {
            return 500;
        }
        // Reverse the headers so we find the last HTTP status code if the request
        // was redirected See
        // http://php.net/manual/en/reserved.variables.httpresponseheader.php#122362
        $http_response_header = array_reverse($http_response_header);
        foreach ($http_response_header as $header) {
            if (preg_match('{^HTTP/.+ (\d{3}) }i', (string) $header, $matches)) {
                return (int) $matches[1];
            }
        }
        return 500;
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Contao Manager.
 *
 * (c) Contao Association
 *
 * @license LGPL-3.0-or-later
 */
namespace _ContaoManager\Contao\ManagerApi\System;

use Composer\Repository\PlatformRepository;
use _ContaoManager\Contao\ManagerApi\ApiKernel;
use _ContaoManager\Contao\ManagerApi\Config\ManagerConfig;
use _ContaoManager\Symfony\Component\Filesystem\Filesystem;
class SelfUpdate
{
    private const DOWNLOAD_URL = 'https://download.contao.org/contao-manager/%s/contao-manager.phar';
    private const VERSION_URL = 'https://download.contao.org/contao-manager/%s/contao-manager.version';
    private array|null $remote = null;
    private bool $checkedForUpdates = \false;
    public function __construct(private readonly ApiKernel $kernel, private readonly ManagerConfig $managerConfig, private readonly Request $request, private readonly Filesystem $filesystem)
    {
    }
    /**
     * Returns whether the current application can be updated.
     */
    public function canUpdate(): bool
    {
        return ApiKernel::isPhar();
    }
    /**
     * Returns whether the current environments supports the new requirements.
     */
    public function supportsUpdate(): bool
    {
        $this->checkForUpdate();
        $requires = $this->managerConfig->get('latest_requires', []);
        $repository = new PlatformRepository();
        foreach ($requires as $name => $constraint) {
            if (null === $repository->findPackage($name, $constraint)) {
                return \false;
            }
        }
        return \true;
    }
    /**
     * Returns whether this is a development build.
     */
    public function isDev(): bool
    {
        // @phpstan-ignore-next-line
        return ApiKernel::VERSION_KEY === ApiKernel::MANAGER_VERSION || 'prod' !== $this->kernel->getEnvironment() || $this->kernel->isDebug();
    }
    /**
     * Gets the release channel for the current version.
     */
    public function getChannel(): string
    {
        return $this->isDev() ? 'dev' : 'stable';
    }
    /**
     * Returns whether there is an update available.
     */
    public function hasUpdate(): bool
    {
        return $this->getOldVersion() !== $this->getNewVersion();
    }
    /**
     * Returns version of currently installed Phar.
     */
    public function getOldVersion(): string
    {
        return ApiKernel::MANAGER_VERSION;
    }
    /**
     * Returns version of remotely available Phar.
     */
    public function getNewVersion(): string|null
    {
        $this->checkForUpdate();
        return $this->managerConfig->has('latest_version') ? (string) $this->managerConfig->get('latest_version') : null;
    }
    /**
     * Returns the requirements for the remotely available Phar.
     */
    public function getNewRequires(): array
    {
        $this->checkForUpdate();
        return $this->managerConfig->get('latest_requires', []);
    }
    /**
     * Updates the current Phar to the latest version available.
     *
     * @throws \Throwable
     */
    public function update(): bool
    {
        if (!$this->hasUpdate() || !$this->canUpdate() || !$this->supportsUpdate()) {
            return \false;
        }
        $remote = $this->getRemoteInfo();
        $phar = \Phar::running(\false);
        [$filename, $extension] = $this->splitFilename($phar);
        $backupFile = $this->kernel->getConfigDir() . '/' . $filename . '-old' . $extension;
        $tempFile = \dirname($phar) . '/' . $filename . '.temp';
        $this->backup($phar, $backupFile);
        try {
            $this->download($tempFile);
            $this->validate($tempFile, $remote['sha1']);
            $this->install($tempFile, $phar);
        } catch (\Throwable $throwable) {
            $this->filesystem->remove($tempFile);
            throw $throwable;
        }
        // Check the update server after update. This might be necessary if an updated
        // version contains a new update URL, which will be the case one the PHP version
        // is no longer supported.
        $this->managerConfig->remove('last_update');
        return \true;
    }
    /**
     * Loads latest information from the update server if the local cache has expired.
     */
    private function checkForUpdate(): void
    {
        if ($this->checkedForUpdates) {
            return;
        }
        $lastUpdate = $this->managerConfig->get('last_update');
        $latestVersion = $this->managerConfig->get('latest_version');
        if (null !== $latestVersion && null !== $lastUpdate && \false !== ($lastUpdate = strtotime((string) $lastUpdate)) && !$this->isDev() && $lastUpdate <= time() && $lastUpdate > strtotime('-1 hour')) {
            return;
        }
        $remote = $this->getRemoteInfo();
        $this->checkedForUpdates = \true;
        $this->managerConfig->set('last_update', (new \DateTime())->format('c'));
        $this->managerConfig->set('latest_version', $remote['version']);
        $this->managerConfig->set('latest_requires', $remote['requires'] ?? []);
    }
    /**
     * Gets remote information about available updates.
     */
    private function getRemoteInfo(): array
    {
        if (null === $this->remote) {
            $url = \sprintf(self::VERSION_URL, $this->getChannel());
            $content = trim((string) $this->request->get($url, $statusCode, \false, 0));
            $data = json_decode($content, \true);
            if (!isset($data['version'], $data['sha1']) || !preg_match('@^\d+\.\d+\.\d+(-[a-z0-9\-]+)?$@', (string) $data['version']) || !preg_match('%^[a-z0-9]{40}%', (string) $data['sha1'])) {
                throw new \RuntimeException('Version request returned incorrectly formatted response.');
            }
            $this->remote = $data;
        }
        return $this->remote;
    }
    /**
     * Creates a backup of the current Phar to the given target.
     */
    private function backup(string $current, string $target): void
    {
        $this->filesystem->copy($current, $target, \true);
    }
    /**
     * Downloads the latest remote version to the given target.
     */
    private function download(string $target): void
    {
        $url = \sprintf(self::DOWNLOAD_URL, $this->getChannel());
        $result = $this->request->getStream($url);
        if (null === $result) {
            throw new \RuntimeException(\sprintf('Request to URL failed: %s', $url));
        }
        $this->filesystem->dumpFile($target, $result);
    }
    /**
     * Validates temporary file if it matches the given SHA1 hash.
     */
    private function validate(string $tempFile, string $sha1): void
    {
        $tmpVersion = sha1_file($tempFile);
        if ($tmpVersion !== $sha1) {
            throw new \RuntimeException(\sprintf('Download file appears to be corrupted or outdated. The file received does not have the expected SHA-1 hash: %s.', $sha1));
        }
    }
    /**
     * Installs the temporary Phar to the target location.
     */
    private function install(string $tempFile, string $phar): void
    {
        if (\defined('PHP_WINDOWS_VERSION_BUILD')) {
            $this->filesystem->copy($tempFile, $phar, \true);
            $this->filesystem->remove($tempFile);
            return;
        }
        $this->filesystem->rename($tempFile, $phar, \true);
    }
    /**
     * Gets filename and extension from current Phar file.
     */
    private function splitFilename(string $phar): array
    {
        $extension = '.phar.php';
        $filename = basename($phar, $extension);
        if ($filename === $phar) {
            $extension = '.phar';
            $filename = basename($phar, $extension);
        }
        return [$filename, $extension];
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Contao Manager.
 *
 * (c) Contao Association
 *
 * @license LGPL-3.0-or-later
 */
namespace _ContaoManager\Contao\ManagerApi\Task;

use _ContaoManager\Contao\ManagerApi\TaskOperation\ConsoleOutput;
use _ContaoManager\Contao\ManagerApi\TaskOperation\SponsoredOperationInterface;
use _ContaoManager\Contao\ManagerApi\TaskOperation\TaskOperationInterface;
final class TaskStatus implements \JsonSerializable
{
    public const STATUS_ACTIVE = 'active';
    public const STATUS_COMPLETE = 'complete';
    public const STATUS_ERROR = 'error';
    public const STATUS_PAUSED = 'paused';
    public const STATUS_ABORTING = 'aborting';
    public const STATUS_STOPPED = 'stopped';
    private bool $cancellable = \false;
    private bool $autoClose = \false;
    private bool $audit = \false;
    private bool $abort = \false;
    public function __construct(
        private readonly string $id,
        private readonly string $title,
        /**
         * @var array<TaskOperationInterface>
         */
        private readonly array $operations
    )
    {
    }
    public function getTitle(): string
    {
        return $this->title;
    }
    public function getConsole(): string
    {
        $console = new ConsoleOutput();
        foreach ($this->operations as $operation) {
            $console->add((string) $operation->getConsole());
        }
        return (string) $console;
    }
    /**
     * @return array<TaskOperationInterface>
     */
    public function getOperations(): array
    {
        return $this->operations;
    }
    public function isCancellable(): bool
    {
        return $this->cancellable;
    }
    public function setCancellable(bool $stoppable): self
    {
        $this->cancellable = $stoppable;
        return $this;
    }
    public function canAutoClose(): bool
    {
        return $this->autoClose;
    }
    public function setAutoClose(bool $autoClose): self
    {
        $this->autoClose = $autoClose;
        return $this;
    }
    public function hasAudit(): bool
    {
        return $this->audit;
    }
    public function setAudit(bool $audit): self
    {
        $this->audit = $audit;
        return $this;
    }
    public function getStatus(): string
    {
        foreach ($this->operations as $i => $operation) {
            if ($this->abort) {
                if ($operation->isRunning()) {
                    return self::STATUS_ABORTING;
                }
                continue;
            }
            if ($operation->hasError()) {
                if ($operation->continueOnError()) {
                    if (isset($this->operations[$i + 1]) && ($this->operations[$i + 1]->isRunning() || $this->operations[$i + 1]->isSuccessful())) {
                        continue;
                    }
                    return self::STATUS_PAUSED;
                }
                return self::STATUS_ERROR;
            }
            if (!$operation->isStarted() || $operation->isRunning()) {
                return self::STATUS_ACTIVE;
            }
        }
        if ($this->abort) {
            return self::STATUS_STOPPED;
        }
        return self::STATUS_COMPLETE;
    }
    public function setAborted(): self
    {
        $this->abort = \true;
        return $this;
    }
    public function isActive(): bool
    {
        return self::STATUS_ACTIVE === $this->getStatus();
    }
    public function isComplete(): bool
    {
        return self::STATUS_COMPLETE === $this->getStatus();
    }
    public function isStopped(): bool
    {
        return self::STATUS_STOPPED === $this->getStatus();
    }
    public function hasError(): bool
    {
        return self::STATUS_ERROR === $this->getStatus();
    }
    public function jsonSerialize(): array
    {
        $operations = [];
        $sponsor = null;
        $isNext = !$this->abort;
        $hasError = \false;
        $canContinue = \false;
        foreach ($this->operations as $operation) {
            $status = $this->getOperationStatus($operation, $isNext);
            $operations[] = ['summary' => $operation->getSummary(), 'details' => $operation->getDetails(), 'console' => (string) $operation->getConsole(), 'status' => $hasError && !$canContinue ? self::STATUS_STOPPED : $status];
            if ($operation instanceof SponsoredOperationInterface) {
                $sponsor = $operation->getSponsor();
            }
            $isNext = $operation->isSuccessful();
            $canContinue = $canContinue || !$hasError && $operation->hasError() && $operation->continueOnError();
            $hasError = $hasError || $operation->hasError();
        }
        return ['id' => $this->id, 'title' => $this->title, 'console' => $this->getConsole(), 'cancellable' => $this->cancellable, 'continuable' => $canContinue, 'autoclose' => $this->autoClose, 'audit' => $this->audit, 'status' => $this->getStatus(), 'operations' => $operations, 'sponsor' => $sponsor];
    }
    private function getOperationStatus(TaskOperationInterface $operation, bool $isNext = \false): string
    {
        return match (\true) {
            $operation->isRunning() => self::STATUS_ACTIVE,
            $operation->isSuccessful() => self::STATUS_COMPLETE,
            $operation->hasError() => self::STATUS_ERROR,
            $isNext || $operation->isStarted() => self::STATUS_ACTIVE,
            default => 'pending',
        };
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Contao Manager.
 *
 * (c) Contao Association
 *
 * @license LGPL-3.0-or-later
 */
namespace _ContaoManager\Contao\ManagerApi\Task\Composer;

use _ContaoManager\Contao\ManagerApi\I18n\Translator;
use _ContaoManager\Contao\ManagerApi\Process\ConsoleProcessFactory;
use _ContaoManager\Contao\ManagerApi\Task\AbstractTask;
use _ContaoManager\Contao\ManagerApi\Task\TaskConfig;
use _ContaoManager\Contao\ManagerApi\Task\TaskStatus;
use _ContaoManager\Contao\ManagerApi\TaskOperation\Composer\DumpAutoloadOperation;
class DumpAutoloadTask extends AbstractTask
{
    public function __construct(private readonly ConsoleProcessFactory $processFactory, Translator $translator)
    {
        parent::__construct($translator);
    }
    public function getName(): string
    {
        return 'composer/dump-autoload';
    }
    public function create(TaskConfig $config): TaskStatus
    {
        return parent::create($config)->setAutoClose(\true);
    }
    protected function getTitle(): string
    {
        return $this->translator->trans('task.dump_autoload.title');
    }
    protected function buildOperations(TaskConfig $config): array
    {
        return [new DumpAutoloadOperation($this->processFactory, $this->translator)];
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Contao Manager.
 *
 * (c) Contao Association
 *
 * @license LGPL-3.0-or-later
 */
namespace _ContaoManager\Contao\ManagerApi\Task\Composer;

use _ContaoManager\Contao\ManagerApi\I18n\Translator;
use _ContaoManager\Contao\ManagerApi\Process\ConsoleProcessFactory;
use _ContaoManager\Contao\ManagerApi\Task\AbstractTask;
use _ContaoManager\Contao\ManagerApi\Task\TaskConfig;
use _ContaoManager\Contao\ManagerApi\Task\TaskStatus;
use _ContaoManager\Contao\ManagerApi\TaskOperation\Composer\ClearCacheOperation;
class ClearCacheTask extends AbstractTask
{
    public function __construct(private readonly ConsoleProcessFactory $processFactory, Translator $translator)
    {
        parent::__construct($translator);
    }
    public function getName(): string
    {
        return 'composer/clear-cache';
    }
    public function create(TaskConfig $config): TaskStatus
    {
        return parent::create($config)->setAutoClose(\true);
    }
    protected function getTitle(): string
    {
        return $this->translator->trans('task.clear_cache.title');
    }
    protected function buildOperations(TaskConfig $config): array
    {
        return [new ClearCacheOperation($this->processFactory)];
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Contao Manager.
 *
 * (c) Contao Association
 *
 * @license LGPL-3.0-or-later
 */
namespace _ContaoManager\Contao\ManagerApi\Task\Manager;

use _ContaoManager\Contao\ManagerApi\I18n\Translator;
use _ContaoManager\Contao\ManagerApi\System\SelfUpdate;
use _ContaoManager\Contao\ManagerApi\Task\AbstractTask;
use _ContaoManager\Contao\ManagerApi\Task\TaskConfig;
use _ContaoManager\Contao\ManagerApi\TaskOperation\Manager\SelfUpdateOperation;
use _ContaoManager\Contao\ManagerApi\TaskOperation\TaskOperationInterface;
class SelfUpdateTask extends AbstractTask
{
    public function __construct(private readonly SelfUpdate $updater, Translator $translator)
    {
        parent::__construct($translator);
    }
    public function getName(): string
    {
        return 'manager/self-update';
    }
    protected function getTitle(): string
    {
        return $this->translator->trans('task.self_update.title');
    }
    /**
     * @return array<TaskOperationInterface>
     */
    protected function buildOperations(TaskConfig $config): array
    {
        return [new SelfUpdateOperation($this->updater, $config, $this->translator)];
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Contao Manager.
 *
 * (c) Contao Association
 *
 * @license LGPL-3.0-or-later
 */
namespace _ContaoManager\Contao\ManagerApi\Task;

use _ContaoManager\Contao\ManagerApi\I18n\Translator;
use _ContaoManager\Contao\ManagerApi\TaskOperation\TaskOperationInterface;
use _ContaoManager\Psr\Log\LoggerAwareInterface;
use _ContaoManager\Psr\Log\LoggerAwareTrait;
abstract class AbstractTask implements TaskInterface, LoggerAwareInterface
{
    use LoggerAwareTrait;
    public function __construct(protected Translator $translator)
    {
    }
    public function create(TaskConfig $config): TaskStatus
    {
        $operations = $this->buildOperations($config);
        foreach ($operations as $operation) {
            if (null !== $this->logger && $operation instanceof LoggerAwareInterface) {
                $operation->setLogger($this->logger);
            }
        }
        return new TaskStatus($config->getId(), $this->getTitle(), $operations);
    }
    public function update(TaskConfig $config, bool $continue = \false): TaskStatus
    {
        if ($config->isCancelled()) {
            return $this->abort($config);
        }
        $status = $this->create($config);
        $operations = $status->getOperations();
        foreach ($operations as $i => $operation) {
            if (!$operation->isStarted() || $operation->isRunning()) {
                if (null !== $this->logger) {
                    $this->logger->info('Current operation: ' . $operation::class);
                }
                $operation->run();
                if (null !== $this->logger && $operation->hasError()) {
                    $this->logger->info('Failed operation: ' . $operation::class);
                }
                return $status;
            }
            if ($operation->isSuccessful()) {
                if (null !== $this->logger) {
                    $this->logger->info('Completed operation: ' . $operation::class);
                }
                continue;
            }
            if ($operation->hasError() && $operation->continueOnError()) {
                if ($continue) {
                    if (null !== $this->logger) {
                        $this->logger->info('Continuing after failed operation: ' . $operation::class);
                    }
                    continue;
                }
                if (!isset($operations[$i + 1]) || $operations[$i + 1]->isRunning() || $operations[$i + 1]->isSuccessful()) {
                    continue;
                }
            }
            return $status;
        }
        return $status;
    }
    public function abort(TaskConfig $config): TaskStatus
    {
        $config->setCancelled();
        $status = $this->create($config)->setAborted();
        foreach ($status->getOperations() as $operation) {
            $operation->abort();
            if ($operation->isRunning()) {
                if (null !== $this->logger) {
                    $this->logger->info('Task operation is active, aborting', ['class' => $operation::class]);
                }
                break;
            }
        }
        return $status;
    }
    public function delete(TaskConfig $config): bool
    {
        $status = $this->create($config);
        $operations = $status->getOperations();
        foreach ($operations as $operation) {
            if ($operation->isRunning()) {
                if (null !== $this->logger) {
                    $this->logger->info('Cannot delete active operation', ['class' => $operation::class]);
                }
                return \false;
            }
        }
        foreach ($operations as $operation) {
            if (null !== $this->logger) {
                $this->logger->info('Deleting operation', ['class' => $operation::class]);
            }
            $operation->delete();
        }
        $config->delete();
        return \true;
    }
    abstract protected function getTitle(): string;
    /**
     * @return array<TaskOperationInterface>
     */
    abstract protected function buildOperations(TaskConfig $config): array;
}
<?php

declare (strict_types=1);
/*
 * This file is part of Contao Manager.
 *
 * (c) Contao Association
 *
 * @license LGPL-3.0-or-later
 */
namespace _ContaoManager\Contao\ManagerApi\Task\Packages;

use _ContaoManager\Contao\ManagerApi\ApiKernel;
use _ContaoManager\Contao\ManagerApi\Composer\CloudChanges;
use _ContaoManager\Contao\ManagerApi\Composer\CloudResolver;
use _ContaoManager\Contao\ManagerApi\Composer\Environment;
use _ContaoManager\Contao\ManagerApi\Config\UploadsConfig;
use _ContaoManager\Contao\ManagerApi\I18n\Translator;
use _ContaoManager\Contao\ManagerApi\Process\ConsoleProcessFactory;
use _ContaoManager\Contao\ManagerApi\Task\TaskConfig;
use _ContaoManager\Contao\ManagerApi\TaskOperation\Composer\CloudOperation;
use _ContaoManager\Contao\ManagerApi\TaskOperation\Composer\CreateProjectOperation;
use _ContaoManager\Contao\ManagerApi\TaskOperation\Composer\InstallOperation;
use _ContaoManager\Contao\ManagerApi\TaskOperation\Contao\CreateContaoOperation;
use _ContaoManager\Contao\ManagerApi\TaskOperation\Filesystem\InstallUploadsOperation;
use _ContaoManager\Contao\ManagerApi\TaskOperation\Filesystem\RemoveUploadsOperation;
use _ContaoManager\Symfony\Component\Filesystem\Filesystem;
class SetupTask extends AbstractPackagesTask
{
    public function __construct(private readonly ConsoleProcessFactory $processFactory, private readonly CloudResolver $cloudResolver, private readonly ApiKernel $kernel, private readonly UploadsConfig $uploads, Environment $environment, Filesystem $filesystem, Translator $translator)
    {
        parent::__construct($environment, $filesystem, $translator);
    }
    public function getName(): string
    {
        return 'contao/install';
    }
    protected function getTitle(): string
    {
        return $this->translator->trans('task.setup_packages.title');
    }
    protected function buildOperations(TaskConfig $config): array
    {
        $upload = null;
        if ($uploadId = $config->getOption('upload')) {
            $upload = $config->getState('upload');
            if (!$upload) {
                $upload = $this->uploads->get($uploadId);
                $config->setState('upload', $upload);
            }
            $operations = [new InstallUploadsOperation([$upload], $config, $this->environment, $this->translator, $this->filesystem), new CreateProjectOperation($config, $this->processFactory, $this->kernel, $this->environment, $upload['package']['name'], null, \true)];
        } elseif ($package = $config->getOption('package')) {
            $operations = [new CreateProjectOperation($config, $this->processFactory, $this->kernel, $this->environment, $package, $config->getOption('version'))];
        } else {
            $operations = [new CreateContaoOperation($config, $this->environment, $this->kernel, $this->filesystem)];
        }
        if ($config->getOption('no-update')) {
            return $operations;
        }
        if ($this->environment->useCloudResolver()) {
            $operations[] = new CloudOperation($this->cloudResolver, new CloudChanges(), $config, $this->environment, $this->translator, $this->filesystem, $this->logger);
        }
        $operations[] = new InstallOperation($this->processFactory, $config, $this->environment, $this->translator, \false, !$config->isCancelled());
        if ($upload) {
            $operations[] = new RemoveUploadsOperation([$upload], $this->uploads, $config, $this->environment, $this->translator, $this->filesystem);
        }
        return $operations;
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Contao Manager.
 *
 * (c) Contao Association
 *
 * @license LGPL-3.0-or-later
 */
namespace _ContaoManager\Contao\ManagerApi\Task\Packages;

use Composer\Semver\Constraint\Constraint;
use Composer\Semver\VersionParser;
use _ContaoManager\Contao\ManagerApi\ApiKernel;
use _ContaoManager\Contao\ManagerApi\Composer\CloudChanges;
use _ContaoManager\Contao\ManagerApi\Composer\CloudResolver;
use _ContaoManager\Contao\ManagerApi\Composer\Environment;
use _ContaoManager\Contao\ManagerApi\Config\UploadsConfig;
use _ContaoManager\Contao\ManagerApi\I18n\Translator;
use _ContaoManager\Contao\ManagerApi\Process\ConsoleProcessFactory;
use _ContaoManager\Contao\ManagerApi\Process\ContaoConsole;
use _ContaoManager\Contao\ManagerApi\Task\TaskConfig;
use _ContaoManager\Contao\ManagerApi\Task\TaskStatus;
use _ContaoManager\Contao\ManagerApi\TaskOperation\Composer\CloudOperation;
use _ContaoManager\Contao\ManagerApi\TaskOperation\Composer\InstallOperation;
use _ContaoManager\Contao\ManagerApi\TaskOperation\Composer\RemoveOperation;
use _ContaoManager\Contao\ManagerApi\TaskOperation\Composer\RequireOperation;
use _ContaoManager\Contao\ManagerApi\TaskOperation\Composer\UpdateOperation;
use _ContaoManager\Contao\ManagerApi\TaskOperation\Contao\MaintenanceModeOperation;
use _ContaoManager\Contao\ManagerApi\TaskOperation\Filesystem\InstallUploadsOperation;
use _ContaoManager\Contao\ManagerApi\TaskOperation\Filesystem\RemoveArtifactsOperation;
use _ContaoManager\Contao\ManagerApi\TaskOperation\Filesystem\RemoveUploadsOperation;
use _ContaoManager\Symfony\Component\Filesystem\Filesystem;
class UpdateTask extends AbstractPackagesTask
{
    public function __construct(private readonly ContaoConsole $contaoConsole, private readonly ConsoleProcessFactory $processFactory, private readonly CloudResolver $cloudResolver, private readonly UploadsConfig $uploads, private readonly ApiKernel $kernel, Environment $environment, Filesystem $filesystem, Translator $translator)
    {
        parent::__construct($environment, $filesystem, $translator);
    }
    public function getName(): string
    {
        return 'composer/update';
    }
    public function update(TaskConfig $config, bool $continue = \false): TaskStatus
    {
        $status = parent::update($config, $continue);
        if ($status->isComplete() && $config->getOption('dry_run', \false)) {
            $this->restoreState($config);
        }
        return $status;
    }
    protected function getTitle(): string
    {
        return $this->translator->trans('task.update_packages.title');
    }
    protected function buildOperations(TaskConfig $config): array
    {
        $changes = $this->getComposerDefinition($config);
        $toggleMaintenance = !$changes->getDryRun() && \array_key_exists('contao:maintenance-mode', $this->contaoConsole->getCommandList());
        $operations = [];
        if (($required = $changes->getRequiredPackages()) && [] !== $required) {
            $operations[] = new RequireOperation($this->processFactory, $required);
        }
        if (($removed = $changes->getRemovedPackages()) && [] !== $removed) {
            $operations[] = new RemoveOperation($this->processFactory, $removed);
        }
        if ($this->environment->useCloudResolver()) {
            $operations[] = new CloudOperation($this->cloudResolver, $changes, $config, $this->environment, $this->translator, $this->filesystem, $this->logger);
        } else {
            $operations[] = new UpdateOperation($this->processFactory, $this->environment, $changes->getUpdates(), $changes->getDryRun());
        }
        if ($toggleMaintenance) {
            $operations[] = new MaintenanceModeOperation($config, $this->processFactory, 'enable');
        }
        if (!$changes->getDryRun() || $this->environment->useCloudResolver()) {
            $operations[] = new InstallOperation($this->processFactory, $config, $this->environment, $this->translator, $changes->getDryRun(), !$config->isCancelled());
        }
        if ($toggleMaintenance) {
            $operations[] = new MaintenanceModeOperation($config, $this->processFactory, 'disable');
        }
        if ($config->getOption('uploads', \false) && \count($this->uploads)) {
            $uploads = array_filter($this->uploads->all(), static fn($upload): bool => $upload['success'] && isset($upload['package']['name']) && ([] === $changes->getUpdates() || \in_array($upload['package']['name'], $changes->getUpdates(), \true)));
            array_unshift($operations, new InstallUploadsOperation($uploads, $config, $this->environment, $this->translator, $this->filesystem));
            if (!$config->getOption('dry_run', \false)) {
                $operations[] = new RemoveUploadsOperation($uploads, $this->uploads, $config, $this->environment, $this->translator, $this->filesystem);
            }
        }
        if ([] !== $removed) {
            $artifacts = array_filter($this->environment->getArtifacts(), static function (string $file) use ($removed): bool {
                foreach ($removed as $packageName) {
                    if (str_starts_with($file, str_replace('/', '__', $packageName))) {
                        return \true;
                    }
                }
                return \false;
            });
            if ([] !== $artifacts) {
                $operations[] = new RemoveArtifactsOperation($artifacts, $config, $this->environment, $this->translator, $this->filesystem);
            }
        }
        return $operations;
    }
    protected function getComposerDefinition(TaskConfig $config): CloudChanges
    {
        $updates = $config->getOption('update', []);
        $definition = new CloudChanges();
        $definition->setUpdates($updates);
        $definition->setDryRun($config->getOption('dry_run', \false));
        foreach ($config->getOption('require', []) as $name => $version) {
            $definition->requirePackage($name, $version);
        }
        foreach ($config->getOption('remove', []) as $name) {
            $definition->removePackage($name);
        }
        $this->addContaoConflictsRequirement($definition);
        $this->handleContaoRequirement($definition);
        // Update all packages if none are set
        if (empty($updates)) {
            $definition->setUpdates([]);
        }
        return $definition;
    }
    private function addContaoConflictsRequirement(CloudChanges $definition): void
    {
        $rootRequires = $this->environment->getComposer()->getPackage()->getRequires();
        if (isset($rootRequires['contao/conflicts']) && '*@dev' === $rootRequires['contao/conflicts']->getPrettyConstraint()) {
            if ([] !== $definition->getUpdates()) {
                $definition->addUpdate('contao/conflicts');
            }
            return;
        }
        $definition->requirePackage('contao/conflicts', '*@dev');
    }
    private function handleContaoRequirement(CloudChanges $definition): void
    {
        foreach ($definition->getRequiredPackages() as $require) {
            $require = explode('=', (string) $require, 2);
            $packageName = $require[0];
            $version = $require[1] ?? null;
            // Automatically require core-bundle and installation-bundle if the
            // manager-bundle is not stable otherwise the dependency would not be resolved
            // because we don't set minimum-stability
            if ('contao/manager-bundle' === $packageName && null !== $version) {
                $rootRequires = $this->environment->getComposer()->getPackage()->getRequires();
                $versionParser = new VersionParser();
                $constraint = $versionParser->parseConstraints($version);
                $isContao5 = $constraint->matches(new Constraint('>=', '5@dev'));
                // Patch composer.json to make sure we have a valid public-dir and install scripts
                if ($isContao5) {
                    try {
                        $jsonFile = $this->environment->getComposerJsonFile();
                        $json = $jsonFile->read();
                        if (!isset($json['extra']['public-dir'])) {
                            $json['extra']['public-dir'] = basename($this->kernel->getPublicDir());
                        }
                        foreach (['post-install-cmd', 'post-update-cmd'] as $group) {
                            if (isset($json['scripts'][$group]) && \is_array($json['scripts'][$group])) {
                                foreach ($json['scripts'][$group] as $k => $script) {
                                    if ('Contao\ManagerBundle\Composer\ScriptHandler::initializeApplication' === $script) {
                                        $json['scripts'][$group][$k] = '@php vendor/bin/contao-setup';
                                        break;
                                    }
                                }
                            } elseif (isset($json['scripts'][$group]) && 'Contao\ManagerBundle\Composer\ScriptHandler::initializeApplication' === $json['scripts'][$group]) {
                                $json['scripts'][$group] = '@php vendor/bin/contao-setup';
                            }
                        }
                        $jsonFile->write($json);
                    } catch (\Exception) {
                        // Ignore
                    }
                }
                if ('stable' !== VersionParser::parseStability($version)) {
                    $definition->requirePackage('contao/core-bundle', $version);
                    if (!$isContao5) {
                        $definition->requirePackage('contao/installation-bundle', $version);
                    } elseif (isset($rootRequires['contao/installation-bundle'])) {
                        $definition->removePackage('contao/installation-bundle');
                    }
                } else {
                    if (isset($rootRequires['contao/core-bundle'])) {
                        $definition->removePackage('contao/core-bundle');
                    }
                    if (isset($rootRequires['contao/installation-bundle'])) {
                        $definition->removePackage('contao/installation-bundle');
                    }
                }
                return;
            }
        }
        // Automatically update the core-bundle and installation-bundle when updating Contao
        // (but only if they are actually installed, like not on the initial installation)
        foreach ($definition->getUpdates() as $packageName) {
            if ('contao/manager-bundle' === $packageName) {
                $localRepository = $this->environment->getComposer()->getRepositoryManager()->getLocalRepository();
                if (!empty($localRepository->findPackages('contao/core-bundle'))) {
                    $definition->addUpdate('contao/core-bundle');
                }
                if (!empty($localRepository->findPackages('contao/installation-bundle'))) {
                    $definition->addUpdate('contao/installation-bundle');
                }
            }
        }
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Contao Manager.
 *
 * (c) Contao Association
 *
 * @license LGPL-3.0-or-later
 */
namespace _ContaoManager\Contao\ManagerApi\Task\Packages;

use _ContaoManager\Contao\ManagerApi\Composer\CloudChanges;
use _ContaoManager\Contao\ManagerApi\Composer\CloudResolver;
use _ContaoManager\Contao\ManagerApi\Composer\Environment;
use _ContaoManager\Contao\ManagerApi\I18n\Translator;
use _ContaoManager\Contao\ManagerApi\Process\ConsoleProcessFactory;
use _ContaoManager\Contao\ManagerApi\Process\ContaoConsole;
use _ContaoManager\Contao\ManagerApi\Task\TaskConfig;
use _ContaoManager\Contao\ManagerApi\TaskOperation\Composer\CloudOperation;
use _ContaoManager\Contao\ManagerApi\TaskOperation\Composer\InstallOperation;
use _ContaoManager\Contao\ManagerApi\TaskOperation\Contao\MaintenanceModeOperation;
use _ContaoManager\Contao\ManagerApi\TaskOperation\Filesystem\RemoveVendorOperation;
use _ContaoManager\Symfony\Component\Filesystem\Filesystem;
class InstallTask extends AbstractPackagesTask
{
    public function __construct(private readonly ContaoConsole $contaoConsole, private readonly ConsoleProcessFactory $processFactory, private readonly CloudResolver $cloudResolver, Environment $environment, Filesystem $filesystem, Translator $translator)
    {
        parent::__construct($environment, $filesystem, $translator);
    }
    public function getName(): string
    {
        return 'composer/install';
    }
    protected function getTitle(): string
    {
        return $this->translator->trans('task.install_packages.title');
    }
    protected function buildOperations(TaskConfig $config): array
    {
        $operations = [];
        $dryRun = (bool) $config->getOption('dry_run', \false);
        $supportsMaintenance = $config->getState('supports-maintenance');
        if (null === $supportsMaintenance) {
            $supportsMaintenance = \array_key_exists('contao:maintenance-mode', $this->contaoConsole->getCommandList());
            $config->setState('supports-maintenance', $supportsMaintenance);
        }
        if ($config->getOption('remove-vendor', \false)) {
            $operations[] = new RemoveVendorOperation($config, $this->environment, $this->filesystem);
        }
        if ($this->environment->useCloudResolver() && !$this->filesystem->exists($this->environment->getLockFile())) {
            $changes = new CloudChanges();
            $changes->setDryRun($dryRun);
            $operations[] = new CloudOperation($this->cloudResolver, $changes, $config, $this->environment, $this->translator, $this->filesystem, $this->logger);
        }
        if ($supportsMaintenance) {
            $operations[] = new MaintenanceModeOperation($config, $this->processFactory, 'enable');
        }
        $operations[] = new InstallOperation($this->processFactory, $config, $this->environment, $this->translator, $dryRun, !$config->isCancelled());
        if ($supportsMaintenance) {
            $operations[] = new MaintenanceModeOperation($config, $this->processFactory, 'disable');
        }
        return $operations;
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Contao Manager.
 *
 * (c) Contao Association
 *
 * @license LGPL-3.0-or-later
 */
namespace _ContaoManager\Contao\ManagerApi\Task\Packages;

use _ContaoManager\Contao\ManagerApi\Composer\Environment;
use _ContaoManager\Contao\ManagerApi\I18n\Translator;
use _ContaoManager\Contao\ManagerApi\Task\AbstractTask;
use _ContaoManager\Contao\ManagerApi\Task\TaskConfig;
use _ContaoManager\Contao\ManagerApi\Task\TaskStatus;
use _ContaoManager\Symfony\Component\Filesystem\Filesystem;
abstract class AbstractPackagesTask extends AbstractTask
{
    public function __construct(protected Environment $environment, protected Filesystem $filesystem, Translator $translator)
    {
        parent::__construct($translator);
    }
    public function create(TaskConfig $config): TaskStatus
    {
        return parent::create($config)->setAudit(!$config->getOption('dry_run', \false))->setCancellable(\true);
    }
    public function update(TaskConfig $config, bool $continue = \false): TaskStatus
    {
        $this->createBackup($config);
        $status = parent::update($config, $continue);
        if ($status->hasError() || $status->isStopped()) {
            $this->restoreState($config);
        }
        return $status;
    }
    public function abort(TaskConfig $config): TaskStatus
    {
        $status = parent::abort($config);
        if ($status->hasError() || $status->isStopped()) {
            $this->restoreState($config);
        }
        return $status;
    }
    /**
     * Creates a backup of the composer.json and composer.lock file and stores the
     * currently installed artifacts.
     */
    protected function createBackup(TaskConfig $config): void
    {
        if ($config->getState('backup-created', \false)) {
            return;
        }
        if (!$this->environment->createBackup()) {
            return;
        }
        $config->setState('backup-artifacts', $this->environment->getArtifacts());
        $config->setState('backup-created', \true);
    }
    /**
     * Restores the backup files if a backup was created within this task.
     */
    protected function restoreState(TaskConfig $config): void
    {
        if ($config->getState('backup-created', \false) && !$config->getState('backup-restored', \false)) {
            if (!$this->environment->restoreBackup()) {
                return;
            }
            if (null !== $previous = $config->getState('backup-artifacts')) {
                foreach (array_diff($this->environment->getArtifacts(), $previous) as $delete) {
                    $this->filesystem->remove($this->environment->getArtifactDir() . '/' . $delete);
                }
            }
            $config->setState('backup-restored', \true);
        }
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Contao Manager.
 *
 * (c) Contao Association
 *
 * @license LGPL-3.0-or-later
 */
namespace _ContaoManager\Contao\ManagerApi\Task\Contao;

use _ContaoManager\Contao\ManagerApi\I18n\Translator;
use _ContaoManager\Contao\ManagerApi\Process\ConsoleProcessFactory;
use _ContaoManager\Contao\ManagerApi\Task\AbstractTask;
use _ContaoManager\Contao\ManagerApi\Task\TaskConfig;
use _ContaoManager\Contao\ManagerApi\Task\TaskStatus;
use _ContaoManager\Contao\ManagerApi\TaskOperation\Contao\BackupCreateOperation;
class BackupCreateTask extends AbstractTask
{
    public function __construct(private readonly ConsoleProcessFactory $processFactory, Translator $translator)
    {
        parent::__construct($translator);
    }
    public function getName(): string
    {
        return 'contao/backup-create';
    }
    public function create(TaskConfig $config): TaskStatus
    {
        return parent::create($config)->setAutoClose(\true);
    }
    protected function getTitle(): string
    {
        return $this->translator->trans('task.backup_create.title');
    }
    protected function buildOperations(TaskConfig $config): array
    {
        return [new BackupCreateOperation($this->processFactory)];
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Contao Manager.
 *
 * (c) Contao Association
 *
 * @license LGPL-3.0-or-later
 */
namespace _ContaoManager\Contao\ManagerApi\Task\Contao;

use _ContaoManager\Contao\ManagerApi\I18n\Translator;
use _ContaoManager\Contao\ManagerApi\Process\ConsoleProcessFactory;
use _ContaoManager\Contao\ManagerApi\Task\AbstractTask;
use _ContaoManager\Contao\ManagerApi\Task\TaskConfig;
use _ContaoManager\Contao\ManagerApi\Task\TaskStatus;
use _ContaoManager\Contao\ManagerApi\TaskOperation\Contao\BackupCreateOperation;
use _ContaoManager\Contao\ManagerApi\TaskOperation\Contao\BackupRestoreOperation;
use _ContaoManager\Symfony\Component\HttpFoundation\Exception\BadRequestException;
class BackupRestoreTask extends AbstractTask
{
    public function __construct(private readonly ConsoleProcessFactory $processFactory, Translator $translator)
    {
        parent::__construct($translator);
    }
    public function getName(): string
    {
        return 'contao/backup-restore';
    }
    public function create(TaskConfig $config): TaskStatus
    {
        return parent::create($config);
    }
    protected function getTitle(): string
    {
        return $this->translator->trans('task.backup_restore.title');
    }
    protected function buildOperations(TaskConfig $config): array
    {
        $file = $config->getOption('file');
        $backup = $config->getOption('backup', \false);
        if (!$file) {
            throw new BadRequestException();
        }
        $operations = [new BackupRestoreOperation($this->processFactory, $file)];
        if ($backup) {
            array_unshift($operations, new BackupCreateOperation($this->processFactory));
        }
        return $operations;
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Contao Manager.
 *
 * (c) Contao Association
 *
 * @license LGPL-3.0-or-later
 */
namespace _ContaoManager\Contao\ManagerApi\Task\Contao;

use _ContaoManager\Contao\ManagerApi\ApiKernel;
use _ContaoManager\Contao\ManagerApi\I18n\Translator;
use _ContaoManager\Contao\ManagerApi\Process\ConsoleProcessFactory;
use _ContaoManager\Contao\ManagerApi\Process\ContaoConsole;
use _ContaoManager\Contao\ManagerApi\Task\AbstractTask;
use _ContaoManager\Contao\ManagerApi\Task\TaskConfig;
use _ContaoManager\Contao\ManagerApi\Task\TaskStatus;
use _ContaoManager\Contao\ManagerApi\TaskOperation\Contao\CacheClearOperation;
use _ContaoManager\Contao\ManagerApi\TaskOperation\Contao\CacheWarmupOperation;
use _ContaoManager\Contao\ManagerApi\TaskOperation\Contao\MaintenanceModeOperation;
use _ContaoManager\Contao\ManagerApi\TaskOperation\Filesystem\RemoveCacheOperation;
use _ContaoManager\Symfony\Component\Filesystem\Filesystem;
class RebuildCacheTask extends AbstractTask
{
    public function __construct(private readonly ApiKernel $kernel, private readonly ConsoleProcessFactory $processFactory, private readonly ContaoConsole $contaoConsole, Translator $translator, private readonly Filesystem $filesystem)
    {
        parent::__construct($translator);
    }
    public function getName(): string
    {
        return 'contao/rebuild-cache';
    }
    public function create(TaskConfig $config): TaskStatus
    {
        return parent::create($config)->setAutoClose(\true);
    }
    protected function getTitle(): string
    {
        return $this->translator->trans('task.rebuild_cache.title');
    }
    protected function buildOperations(TaskConfig $config): array
    {
        $supportsMaintenance = $config->getState('supports-maintenance');
        $environment = $config->getOption('environment', 'prod');
        if (null === $supportsMaintenance) {
            $supportsMaintenance = \array_key_exists('contao:maintenance-mode', $this->contaoConsole->getCommandList());
            $config->setState('supports-maintenance', $supportsMaintenance);
        }
        $operations = [new RemoveCacheOperation($environment, $this->kernel, $config, $this->filesystem), new CacheClearOperation($this->processFactory, $environment)];
        if (\false !== $config->getOption('warmup', \true)) {
            $operations[] = new CacheWarmupOperation($this->processFactory, $environment);
        } else {
            // Remove cache directory again (contao/contao-manager#655)
            $operations[] = new RemoveCacheOperation($environment, $this->kernel, $config, $this->filesystem, 'remove-cache-again');
        }
        if ($supportsMaintenance && 'dev' !== $environment) {
            array_unshift($operations, new MaintenanceModeOperation($config, $this->processFactory, 'enable'));
            $operations[] = new MaintenanceModeOperation($config, $this->processFactory, 'disable');
        }
        return $operations;
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Contao Manager.
 *
 * (c) Contao Association
 *
 * @license LGPL-3.0-or-later
 */
namespace _ContaoManager\Contao\ManagerApi\Task;

use _ContaoManager\Contao\ManagerApi\ApiKernel;
use _ContaoManager\Contao\ManagerApi\Process\ConsoleProcessFactory;
use _ContaoManager\Psr\Log\LoggerAwareInterface;
use _ContaoManager\Psr\Log\LoggerAwareTrait;
use _ContaoManager\studio24\Rotate\Rotate;
use _ContaoManager\Symfony\Component\DependencyInjection\Attribute\AutoconfigureTag;
use _ContaoManager\Symfony\Component\Filesystem\Filesystem;
use _ContaoManager\Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;
use _ContaoManager\Symfony\Component\HttpKernel\Exception\HttpException;
use _ContaoManager\Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface;
use _ContaoManager\Symfony\Component\Security\Http\Attribute\IsGranted;
#[AutoconfigureTag('monolog.logger', ['channel' => 'tasks'])]
class TaskManager implements LoggerAwareInterface
{
    use LoggerAwareTrait;
    private string $configFile;
    private string $logFile;
    /**
     * @var array<TaskInterface>
     */
    private array $tasks = [];
    /**
     * @param iterable<TaskInterface> $tasks
     */
    public function __construct(iterable $tasks, private readonly ApiKernel $kernel, private readonly ConsoleProcessFactory $processFactory, private readonly AuthorizationCheckerInterface $authorizationChecker, private readonly Filesystem $filesystem)
    {
        $this->configFile = $this->kernel->getConfigDir() . \DIRECTORY_SEPARATOR . 'task.json';
        $this->logFile = $this->kernel->getLogDir() . '/task-output.log';
        foreach ($tasks as $task) {
            $this->tasks[$task->getName()] = $task;
        }
    }
    public function supportsTask(string $name): bool
    {
        return isset($this->tasks[$name]);
    }
    public function hasTask(): bool
    {
        return $this->filesystem->exists($this->configFile);
    }
    public function createTask(string $name, array $options): TaskStatus
    {
        if ($this->hasTask()) {
            throw new \RuntimeException('A task already exists.');
        }
        $config = new TaskConfig($this->configFile, $this->filesystem, $this->kernel->getTranslator(), $name, $options);
        $config->save();
        $task = $this->loadTask($config);
        $status = $task->create($config);
        foreach ($status->getOperations() as $operation) {
            foreach ((new \ReflectionClass($operation))->getAttributes(IsGranted::class) as $attribute) {
                /** @var IsGranted $isGranted */
                $isGranted = $attribute->newInstance();
                if (!$this->authorizationChecker->isGranted($isGranted->attribute, $isGranted->subject)) {
                    $task->delete($config);
                    if ($isGranted->statusCode) {
                        throw new HttpException($isGranted->statusCode, $isGranted->message ?? '', null, [], $isGranted->exceptionCode ?? 0);
                    }
                    throw new AccessDeniedHttpException($isGranted->message ?? '', null, $isGranted->exceptionCode ?? 0);
                }
            }
        }
        if (null !== $this->logger) {
            $this->logger->info('Created new task', ['name' => $name, 'options' => $options, 'class' => $task::class]);
        }
        $this->processFactory->createManagerConsoleBackgroundProcess(['task:update', '--poll']);
        return $status;
    }
    public function updateTask(bool $continue = \false): TaskStatus|null
    {
        $config = $this->getTaskConfig();
        if (null === $config) {
            return null;
        }
        $task = $this->loadTask($config);
        if (null !== $this->logger) {
            $this->logger->info('Updating task status', ['name' => $task->getName(), 'class' => $task::class]);
        }
        $status = $task->update($config, $continue);
        if (null !== $this->logger && $status->isComplete()) {
            $this->logger->info('Task has been completed', ['name' => $task->getName(), 'class' => $task::class]);
        }
        return $status;
    }
    public function abortTask(): TaskStatus|null
    {
        $config = $this->getTaskConfig();
        if (null === $config) {
            return null;
        }
        $task = $this->loadTask($config);
        if (null !== $this->logger) {
            $this->logger->info('Aborting task', ['name' => $task->getName(), 'class' => $task::class]);
        }
        return $task->abort($config);
    }
    public function deleteTask(): TaskStatus|null
    {
        $config = $this->getTaskConfig();
        if (null === $config) {
            return null;
        }
        $task = $this->loadTask($config);
        if (null !== $this->logger) {
            $this->logger->info('Deleting task', ['name' => $task->getName(), 'class' => $task::class]);
        }
        $status = $config->isCancelled() ? $task->abort($config) : $task->create($config);
        if ($status->isActive() || !$task->delete($config)) {
            throw new \RuntimeException('Active task cannot be deleted');
        }
        $this->saveConsoleOutput($status->getConsole());
        return $status;
    }
    private function loadTask(TaskConfig $config): TaskInterface
    {
        $name = $config->getName();
        if (!isset($this->tasks[$name])) {
            throw new \InvalidArgumentException(\sprintf('Unable to get task "%s".', $name));
        }
        $task = $this->tasks[$name];
        if (!$task instanceof TaskInterface) {
            throw new \RuntimeException(\sprintf('"%s" is not an instance of "%s"', $task::class, TaskInterface::class));
        }
        return $task;
    }
    private function getTaskConfig(): TaskConfig|null
    {
        if ($this->filesystem->exists($this->configFile)) {
            try {
                return new TaskConfig($this->configFile, $this->filesystem, $this->kernel->getTranslator());
            } catch (\Exception) {
                $this->filesystem->remove($this->configFile);
            }
        }
        return null;
    }
    private function saveConsoleOutput(string $output): void
    {
        $rotate = new Rotate($this->logFile);
        $rotate->keep(50);
        $rotate->run();
        $this->filesystem->dumpFile($this->logFile, $output);
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Contao Manager.
 *
 * (c) Contao Association
 *
 * @license LGPL-3.0-or-later
 */
namespace _ContaoManager\Contao\ManagerApi\Task;

use _ContaoManager\Symfony\Component\DependencyInjection\Attribute\AutoconfigureTag;
#[AutoconfigureTag('app.task')]
#[AutoconfigureTag('monolog.logger', ['channel' => 'tasks'])]
interface TaskInterface
{
    /**
     * Gets the task name.
     */
    public function getName(): string;
    /**
     * Creates a task.
     */
    public function create(TaskConfig $config): TaskStatus;
    /**
     * Updates the task.
     */
    public function update(TaskConfig $config, bool $continue = \false): TaskStatus;
    /**
     * Cancels a task.
     */
    public function abort(TaskConfig $config): TaskStatus;
    /**
     * Deletes a task.
     */
    public function delete(TaskConfig $config): bool;
}
<?php

declare (strict_types=1);
/*
 * This file is part of Contao Manager.
 *
 * (c) Contao Association
 *
 * @license LGPL-3.0-or-later
 */
namespace _ContaoManager\Contao\ManagerApi\Task;

use _ContaoManager\Contao\ManagerApi\Config\AbstractConfig;
use _ContaoManager\Contao\ManagerApi\I18n\Translator;
use _ContaoManager\Ramsey\Uuid\Uuid;
use _ContaoManager\Symfony\Component\Filesystem\Filesystem;
class TaskConfig extends AbstractConfig
{
    public function __construct(string $file, Filesystem $filesystem, Translator $translator, string|null $name = null, array|null $options = null)
    {
        parent::__construct($file, $filesystem, $translator);
        $this->initialize();
        if (null === $name && null === $options) {
            return;
        }
        $this->data = ['id' => Uuid::uuid4()->toString(), 'name' => $name, 'options' => $options, 'state' => [], 'cancelled' => \false];
    }
    public function getId(): string
    {
        $this->initialize();
        return $this->data['id'] ?? '--unknown--';
    }
    public function getName(): string
    {
        $this->initialize();
        return $this->data['name'] ?? '--unknown--';
    }
    public function getOptions(): array
    {
        $this->initialize();
        return $this->data['options'] ?? [];
    }
    public function getOption(string $name, array|bool|float|int|string|null $default = null): array|bool|float|int|string|null
    {
        $this->initialize();
        return \array_key_exists($name, $this->data['options']) ? $this->data['options'][$name] : $default;
    }
    public function getState(string $name, array|bool|float|int|string|null $default = null): array|bool|float|int|string|null
    {
        $this->initialize();
        return \array_key_exists($name, $this->data['state']) ? $this->data['state'][$name] : $default;
    }
    public function setState(string $name, array|bool|float|int|string|null $value): void
    {
        $this->initialize();
        $this->data['state'][$name] = $value;
        $this->save();
    }
    public function clearState(string $name): void
    {
        $this->initialize();
        unset($this->data['state'][$name]);
    }
    public function isCancelled(): bool
    {
        $this->initialize();
        return (bool) $this->data['cancelled'];
    }
    /**
     * Mark task as cancelled.
     */
    public function setCancelled(): void
    {
        $this->initialize();
        $this->data['cancelled'] = \true;
        $this->save();
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Contao Manager.
 *
 * (c) Contao Association
 *
 * @license LGPL-3.0-or-later
 */
namespace _ContaoManager\Contao\ManagerApi\Command;

use _ContaoManager\Contao\ManagerApi\IntegrityCheck\IntegrityCheckFactory;
use _ContaoManager\Crell\ApiProblem\ApiProblem;
use _ContaoManager\Symfony\Component\Console\Attribute\AsCommand;
use _ContaoManager\Symfony\Component\Console\Command\Command;
use _ContaoManager\Symfony\Component\Console\Input\InputInterface;
use _ContaoManager\Symfony\Component\Console\Input\InputOption;
use _ContaoManager\Symfony\Component\Console\Output\OutputInterface;
#[AsCommand(name: 'integrity-check', description: 'Performs integrity check for the Contao Manager')]
class IntegrityCheckCommand extends Command
{
    public function __construct(private readonly IntegrityCheckFactory $integrity)
    {
        parent::__construct();
    }
    protected function configure(): void
    {
        $this->addOption('format', null, InputOption::VALUE_REQUIRED, 'Use "text" or "json" to output the check results accordingly.', 'text');
    }
    protected function execute(InputInterface $input, OutputInterface $output): int
    {
        $problem = $this->integrity->runCliCheck();
        $format = $input->getOption('format');
        if ('json' === $format) {
            return $this->writeJson($output, $problem);
        }
        if ('text' !== $format) {
            throw new \InvalidArgumentException(\sprintf('Unknown output format "%s"', $format));
        }
        if (null !== $problem) {
            $output->writeln('Running PHP ' . \PHP_VERSION);
            $output->writeln($problem->getTitle());
            if ('' !== $detail = $problem->getDetail()) {
                $output->writeln('');
                $output->writeln($detail);
            }
            return Command::FAILURE;
        }
        $output->writeln('<info>Running PHP ' . \PHP_VERSION . ', all checks successful.</info>');
        return Command::SUCCESS;
    }
    private function writeJson(OutputInterface $output, ApiProblem|null $problem = null): int
    {
        $output->write(json_encode(['version' => \PHP_VERSION, 'version_id' => \PHP_VERSION_ID, 'problem' => $problem?->asArray()], \JSON_UNESCAPED_SLASHES | \JSON_PRETTY_PRINT));
        return null === $problem ? Command::SUCCESS : Command::FAILURE;
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Contao Manager.
 *
 * (c) Contao Association
 *
 * @license LGPL-3.0-or-later
 */
namespace _ContaoManager\Contao\ManagerApi\Command;

use _ContaoManager\Contao\ManagerApi\ApiKernel;
use _ContaoManager\Contao\ManagerApi\System\SelfUpdate;
use _ContaoManager\Symfony\Component\Console\Attribute\AsCommand;
use _ContaoManager\Symfony\Component\Console\Command\Command;
use _ContaoManager\Symfony\Component\Console\Input\InputInterface;
use _ContaoManager\Symfony\Component\Console\Output\OutputInterface;
#[AsCommand(name: 'self-update', description: 'Updates Contao Manager to the latest version')]
class UpdateCommand extends Command
{
    public function __construct(private readonly SelfUpdate $updater)
    {
        parent::__construct();
    }
    public function isEnabled(): bool
    {
        return ApiKernel::isPhar() && parent::isEnabled();
    }
    protected function execute(InputInterface $input, OutputInterface $output): int
    {
        if (!$this->updater->supportsUpdate()) {
            throw new \RuntimeException('Your server does not meet the requirements of the next Contao Manager version.');
        }
        if (!$this->updater->canUpdate()) {
            throw new \RuntimeException('This build of Contao Manager cannot be automatically updated.');
        }
        return $this->update($output);
    }
    protected function configure(): void
    {
    }
    private function update(OutputInterface $output): int
    {
        $result = $this->updater->update();
        if (\false === $result) {
            $output->writeln('<info>Already up-to-date.</info>');
        } else {
            $output->writeln(\sprintf('Updated from version %s to version %s.', $this->updater->getOldVersion(), $this->updater->getNewVersion()));
        }
        return Command::SUCCESS;
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Contao Manager.
 *
 * (c) Contao Association
 *
 * @license LGPL-3.0-or-later
 */
namespace _ContaoManager\Contao\ManagerApi\Command;

use _ContaoManager\Symfony\Component\Console\Attribute\AsCommand;
use _ContaoManager\Symfony\Component\Console\Command\Command;
use _ContaoManager\Symfony\Component\Console\Input\InputInterface;
use _ContaoManager\Symfony\Component\Console\Output\OutputInterface;
#[AsCommand(name: 'task:abort', description: 'Aborts the current task and returns the status information.')]
class TaskAbortCommand extends TaskUpdateCommand
{
    protected function configure(): void
    {
        parent::configure();
    }
    protected function execute(InputInterface $input, OutputInterface $output): int
    {
        if (!$this->taskManager->hasTask()) {
            $output->writeln('No task is currently active.');
            return Command::FAILURE;
        }
        $this->taskManager->abortTask();
        return parent::execute($input, $output);
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Contao Manager.
 *
 * (c) Contao Association
 *
 * @license LGPL-3.0-or-later
 */
namespace _ContaoManager\Contao\ManagerApi\Command;

use _ContaoManager\Contao\ManagerApi\Task\TaskManager;
use _ContaoManager\Contao\ManagerApi\Task\TaskStatus;
use _ContaoManager\Contao\ManagerApi\TaskOperation\TaskOperationInterface;
use _ContaoManager\Symfony\Component\Console\Attribute\AsCommand;
use _ContaoManager\Symfony\Component\Console\Command\Command;
use _ContaoManager\Symfony\Component\Console\Helper\ProgressIndicator;
use _ContaoManager\Symfony\Component\Console\Input\InputInterface;
use _ContaoManager\Symfony\Component\Console\Input\InputOption;
use _ContaoManager\Symfony\Component\Console\Output\ConsoleOutput;
use _ContaoManager\Symfony\Component\Console\Output\ConsoleSectionOutput;
use _ContaoManager\Symfony\Component\Console\Output\OutputInterface;
use _ContaoManager\Symfony\Component\Console\Style\SymfonyStyle;
#[AsCommand(name: 'task:update', description: 'Updates the current task and returns the status information.')]
class TaskUpdateCommand extends Command
{
    public function __construct(protected TaskManager $taskManager)
    {
        parent::__construct();
    }
    protected function configure(): void
    {
        $this->addOption('poll', null, InputOption::VALUE_NONE, 'Poll for updates until the task is completed.')->addOption('interval', null, InputOption::VALUE_REQUIRED, 'Poll interval in seconds.', 1);
    }
    protected function execute(InputInterface $input, OutputInterface $output): int
    {
        if (!$this->taskManager->hasTask()) {
            $output->writeln('No task is currently active.');
            return Command::FAILURE;
        }
        $status = $this->taskManager->updateTask();
        if (null === $status) {
            return Command::FAILURE;
        }
        if (!$output instanceof ConsoleOutput) {
            return Command::FAILURE;
        }
        $style = new SymfonyStyle($input, $output);
        $style->title($status->getTitle());
        $sections = [];
        $progresses = [];
        $operations = $status->getOperations();
        foreach ($operations as $i => $operation) {
            $section = $output->section();
            $section->writeln(($operation->isRunning() ? ' > ' : ' - ') . $operation->getSummary());
            $section->writeln('');
            $sections[$i] = $section;
        }
        $this->updateOperations($status->getOperations(), $sections, $progresses);
        if ($input->getOption('poll')) {
            while ($status->isActive()) {
                sleep((int) $input->getOption('interval'));
                $newStatus = $this->taskManager->updateTask();
                if (null === $newStatus) {
                    return Command::FAILURE;
                }
                if ($this->updateOperations($newStatus->getOperations(), $sections, $progresses)) {
                    break;
                }
            }
        }
        match ($status->getStatus()) {
            TaskStatus::STATUS_COMPLETE => $style->success('Operations completed successfully'),
            TaskStatus::STATUS_ERROR => $style->error('Task terminated unexpectedly'),
            TaskStatus::STATUS_STOPPED => $style->warning('Task has been stopped'),
            default => Command::SUCCESS,
        };
        return Command::SUCCESS;
    }
    /**
     * @param array<TaskOperationInterface> $operations
     * @param array<ConsoleSectionOutput>   $sections
     * @param array<ProgressIndicator>      $progresses
     */
    private function updateOperations(array $operations, array $sections, array &$progresses): bool
    {
        foreach ($operations as $i => $operation) {
            $section = $sections[$i];
            $progress = $progresses[$i] ?? null;
            $this->updateOperation($operation, $section, $progress);
            if ($progress) {
                $progresses[$i] = $progress;
            }
            if (!$operation->isStarted() || $operation->isRunning()) {
                return \false;
            }
        }
        return \true;
    }
    private function updateOperation(TaskOperationInterface $operation, ConsoleSectionOutput $section, ProgressIndicator|null &$progress): void
    {
        if (!$operation->isStarted()) {
            return;
        }
        $section->clear();
        if ($operation->isRunning()) {
            if (null === $progress) {
                $progress = new ProgressIndicator($section);
                $progress->start($operation->getSummary());
            }
            $progress->advance();
            $section->writeln('   ' . $operation->getDetails());
            $section->writeln('');
            return;
        }
        if (null !== $progress) {
            $progress->finish($operation->getSummary());
            $section->clear();
            $progress = null;
        }
        $icon = '';
        if ($operation->isSuccessful()) {
            $icon = \sprintf('<fg=green;options=bold>%s</>', '\\' === \DIRECTORY_SEPARATOR ? 'OK' : "✔");
        } elseif ($operation->hasError()) {
            $icon = \sprintf('<fg=red;options=bold>%s</>', '\\' === \DIRECTORY_SEPARATOR ? 'ERROR' : "✘");
        }
        $section->writeln(' ' . $icon . ' ' . $operation->getSummary());
        $section->writeln('   ' . $operation->getDetails());
        $section->writeln('');
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Contao Manager.
 *
 * (c) Contao Association
 *
 * @license LGPL-3.0-or-later
 */
namespace _ContaoManager\Contao\ManagerApi\Command;

use _ContaoManager\Contao\ManagerApi\Process\ProcessRunner;
use _ContaoManager\Symfony\Component\Console\Attribute\AsCommand;
use _ContaoManager\Symfony\Component\Console\Command\Command;
use _ContaoManager\Symfony\Component\Console\Input\InputArgument;
use _ContaoManager\Symfony\Component\Console\Input\InputInterface;
use _ContaoManager\Symfony\Component\Console\Output\OutputInterface;
#[AsCommand(name: 'background-task:run', description: 'Execute a background task')]
class ProcessRunnerCommand extends Command
{
    protected function configure(): void
    {
        $this->addArgument('path', InputArgument::REQUIRED, 'Absolute path to the task config file.');
    }
    protected function execute(InputInterface $input, OutputInterface $output): int
    {
        set_time_limit(0);
        ignore_user_abort(\true);
        $process = new ProcessRunner($input->getArgument('path'));
        try {
            $process->run();
        } catch (\Exception $exception) {
            $process->addOutput((string) $exception);
            $process->stop();
            return Command::FAILURE;
        }
        return Command::SUCCESS;
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Contao Manager.
 *
 * (c) Contao Association
 *
 * @license LGPL-3.0-or-later
 */
namespace _ContaoManager\Contao\ManagerApi\Command;

use _ContaoManager\Contao\ManagerApi\ApiKernel;
use _ContaoManager\Contao\ManagerApi\System\ServerInfo;
use _ContaoManager\Symfony\Component\Console\Attribute\AsCommand;
use _ContaoManager\Symfony\Component\Console\Command\Command;
use _ContaoManager\Symfony\Component\Console\Helper\TableSeparator;
use _ContaoManager\Symfony\Component\Console\Input\InputInterface;
use _ContaoManager\Symfony\Component\Console\Output\OutputInterface;
use _ContaoManager\Symfony\Component\Console\Style\SymfonyStyle;
use _ContaoManager\Symfony\Component\Process\Exception\ProcessFailedException;
use _ContaoManager\Symfony\Component\Process\Process;
#[AsCommand(name: 'about', description: 'Displays information about Contao Manager and the current server')]
class AboutCommand extends Command
{
    public function __construct(private readonly ApiKernel $kernel, private readonly ServerInfo $serverInfo)
    {
        parent::__construct();
    }
    protected function configure(): void
    {
    }
    protected function execute(InputInterface $input, OutputInterface $output): int
    {
        $data = $this->collectData();
        $this->outputTable($input, $output, $data);
        return Command::SUCCESS;
    }
    private function outputTable(InputInterface $input, OutputInterface $output, array $data): void
    {
        $io = new SymfonyStyle($input, $output);
        $osVersion = $data['server']['os_version'] ? ' (' . $data['server']['os_version'] . ')' : '';
        $rows = [['<info>Contao Manager</info>'], new TableSeparator(), ['Version', $data['app']['version']], ['Environment', $data['app']['env']], ['Debug', $data['app']['debug'] ? 'true' : 'false'], ['Cache directory', $data['app']['cache_dir']], ['Contao directory', $data['app']['project_dir']], ['Data directory', $data['app']['config_dir']], new TableSeparator(), ['<info>PHP</info>'], new TableSeparator(), ['Version', $data['php']['version']], ['Architecture', $data['php']['arch'] . ' bits'], ['Server API', $data['php']['sapi']], ['Intl locale', $data['php']['locale']], ['Timezone', $data['php']['timezone']], ['Binary Path', $data['php']['binary'] ?: '-- NOT FOUND --'], new TableSeparator(), ['<info>Server</info>'], new TableSeparator(), ['Operating System', $data['server']['os_name'] . $osVersion]];
        if (!empty($data['server']['arch'])) {
            $rows[] = ['Architecture', $data['server']['arch']];
        }
        $rows[] = new TableSeparator();
        $rows[] = ['<info>Background Forkers</info>'];
        $rows[] = new TableSeparator();
        foreach ($data['forkers'] as $class => $supported) {
            $rows[] = [substr(strrchr((string) $class, '\\'), 1), $supported ? 'supported' : 'not supported'];
        }
        $io->table([], $rows);
    }
    private function collectData(): array
    {
        $version = $this->getManagerVersion();
        $forkers = [];
        foreach ($this->serverInfo->getProcessForkers() as $class) {
            $forker = new $class([], $this->serverInfo->getPhpEnv());
            $forkers[$class] = $forker->isSupported();
        }
        $data = ['app' => ['version' => $version, 'env' => $this->kernel->getEnvironment(), 'debug' => $this->kernel->isDebug(), 'cache_dir' => $this->kernel->getCacheDir(), 'log_dir' => $this->kernel->getLogDir(), 'project_dir' => $this->kernel->getProjectDir(), 'config_dir' => $this->kernel->getConfigDir()], 'php' => ['version' => \PHP_VERSION, 'version_id' => \PHP_VERSION_ID, 'arch' => \PHP_INT_SIZE * 8, 'sapi' => \PHP_SAPI, 'locale' => class_exists('Locale', \false) && \Locale::getDefault() ? \Locale::getDefault() : '', 'timezone' => date_default_timezone_get(), 'binary' => $this->serverInfo->getPhpExecutable()], 'server' => ['os_name' => php_uname('s'), 'os_version' => php_uname('r'), 'arch' => php_uname('m')], 'forkers' => $forkers];
        if ($data['server']['os_name'] === $data['server']['os_version']) {
            $data['server']['os_version'] = '';
            $data['server']['arch'] = '';
        }
        return $data;
    }
    private function getManagerVersion(): string
    {
        $version = ApiKernel::MANAGER_VERSION;
        if (ApiKernel::VERSION_KEY === $version) {
            $git = new Process(['git', 'describe', '--tags', '--always']);
            try {
                $git->mustRun();
                $version = trim($git->getOutput());
            } catch (ProcessFailedException) {
                return 'n/a';
            }
        }
        return $version;
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Contao Manager.
 *
 * (c) Contao Association
 *
 * @license LGPL-3.0-or-later
 */
namespace _ContaoManager\Contao\ManagerApi\Command;

use _ContaoManager\Contao\ManagerApi\Task\TaskManager;
use _ContaoManager\Symfony\Component\Console\Attribute\AsCommand;
use _ContaoManager\Symfony\Component\Console\Command\Command;
use _ContaoManager\Symfony\Component\Console\Input\InputInterface;
use _ContaoManager\Symfony\Component\Console\Output\OutputInterface;
#[AsCommand(name: 'task:delete', description: 'Deletes the current task if it is not active.')]
class TaskDeleteCommand extends Command
{
    public function __construct(private readonly TaskManager $taskManager)
    {
        parent::__construct();
    }
    protected function configure(): void
    {
    }
    protected function execute(InputInterface $input, OutputInterface $output): int
    {
        if (!$this->taskManager->hasTask()) {
            $output->writeln('No task is currently active.');
            return Command::FAILURE;
        }
        $status = $this->taskManager->deleteTask();
        if (null === $status || $status->isActive()) {
            $output->writeln('Task could not be deleted.');
            return Command::FAILURE;
        }
        return Command::SUCCESS;
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Contao Manager.
 *
 * (c) Contao Association
 *
 * @license LGPL-3.0-or-later
 */
namespace _ContaoManager\Contao\ManagerApi\I18n;

use _ContaoManager\Symfony\Component\HttpFoundation\RequestStack;
use _ContaoManager\Symfony\Component\Yaml\Yaml;
class Translator
{
    private array $labels = [];
    public function __construct(private readonly RequestStack $requestStack)
    {
    }
    /**
     * Gets label for given ID from translation files.
     */
    public function trans(string $id, array $params = []): string
    {
        $locales = ['en'];
        if (null !== $request = $this->requestStack->getCurrentRequest()) {
            $locale = $request->getLocale();
            if (5 === \strlen($locale)) {
                array_unshift($locales, substr($locale, 0, 2));
            }
            array_unshift($locales, $locale);
        }
        return $this->replaceParameters($this->findLabel($id, $locales), $params);
    }
    /**
     * Searches for label by ID in the given locales.
     */
    private function findLabel(string $id, array $locales): string
    {
        foreach ($locales as $locale) {
            $this->load($locale);
            if (isset($this->labels[$locale][$id]) && ('' !== $this->labels[$locale][$id] || 'en' === $locale)) {
                return $this->labels[$locale][$id];
            }
        }
        return $id;
    }
    /**
     * Replaces parameters in label.
     */
    private function replaceParameters(string $label, array $params): string
    {
        if ([] === $params) {
            return $label;
        }
        $replace = [];
        foreach ($params as $k => $v) {
            $replace['{' . $k . '}'] = $v;
        }
        return strtr($label, $replace);
    }
    /**
     * Loads labels from file for given locale if it exists.
     */
    private function load(string $locale): void
    {
        if (isset($this->labels[$locale])) {
            return;
        }
        $file = __DIR__ . '/../Resources/i18n/' . $locale . '.yml';
        if (!is_file($file)) {
            return;
        }
        $data = Yaml::parse(file_get_contents($file));
        if (empty($data[$locale]) || !\is_array($data[$locale])) {
            return;
        }
        $this->store($locale, $data[$locale]);
    }
    /**
     * Adds new labels to the label store by flattening array keys.
     */
    private function store(string $locale, array $data, string $prefix = ''): void
    {
        foreach ($data as $k => $v) {
            if (\is_array($v)) {
                $this->store($locale, $v, $prefix . $k . '.');
            } else {
                $this->labels[$locale][$prefix . $k] = $v;
            }
        }
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Contao Manager.
 *
 * (c) Contao Association
 *
 * @license LGPL-3.0-or-later
 */
namespace _ContaoManager\Contao\ManagerApi\Exception;

use _ContaoManager\Crell\ApiProblem\ApiProblem;
use _ContaoManager\Symfony\Component\HttpKernel\Exception\HttpException;
/**
 * Exception containing an API problem.
 */
class ApiProblemException extends HttpException
{
    public function __construct(private readonly ApiProblem $problem, \Throwable|null $previous = null, array $headers = [], int $code = 0)
    {
        parent::__construct($this->problem->getStatus(), $this->problem->getTitle(), $previous, $headers, $code);
    }
    /**
     * Gets the API problem.
     */
    public function getApiProblem(): ApiProblem
    {
        return $this->problem;
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Contao Manager.
 *
 * (c) Contao Association
 *
 * @license LGPL-3.0-or-later
 */
namespace _ContaoManager\Contao\ManagerApi\Exception;

use _ContaoManager\Symfony\Component\Process\Process;
class ProcessOutputException extends \RuntimeException
{
    private readonly Process $process;
    public function __construct(string $message, Process $process, \Throwable|null $previous = null)
    {
        parent::__construct($message, $process->getExitCode(), $previous);
        $this->process = $process;
    }
    /**
     * Gets the process object.
     */
    public function getProcess(): Process
    {
        return $this->process;
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Contao Manager.
 *
 * (c) Contao Association
 *
 * @license LGPL-3.0-or-later
 */
namespace _ContaoManager\Contao\ManagerApi\Exception;

use _ContaoManager\Symfony\Component\Security\Core\Exception\BadCredentialsException;
use _ContaoManager\Symfony\Component\Security\Core\User\UserInterface;
class InvalidTotpException extends BadCredentialsException
{
    private UserInterface|null $user = null;
    public function getUser(): UserInterface|null
    {
        return $this->user;
    }
    public function setUser(UserInterface $user): void
    {
        $this->user = $user;
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Contao Manager.
 *
 * (c) Contao Association
 *
 * @license LGPL-3.0-or-later
 */
namespace _ContaoManager\Contao\ManagerApi\Exception;

class InvalidJsonException extends \InvalidArgumentException
{
    private readonly int $jsonError;
    private readonly string $jsonErrorMsg;
    public function __construct(private readonly string $filename, private readonly string $content = '', int $code = 0, \Throwable|null $previous = null)
    {
        parent::__construct(\sprintf('File "%s" does not contain valid JSON.', $this->filename), $code, $previous);
        $this->jsonError = json_last_error();
        $this->jsonErrorMsg = json_last_error_msg();
    }
    /**
     * Gets name of the JSON file.
     */
    public function getFilename(): string
    {
        return $this->filename;
    }
    /**
     * Gets the invalid file content.
     */
    public function getContent(): string
    {
        return $this->content;
    }
    /**
     * Gets the json_last_error.
     */
    public function getJsonError(): int
    {
        return $this->jsonError;
    }
    /**
     * Gets the json_last_error_msg.
     */
    public function getJsonErrorMessage(): string
    {
        return $this->jsonErrorMsg;
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Contao Manager.
 *
 * (c) Contao Association
 *
 * @license LGPL-3.0-or-later
 */
namespace _ContaoManager\Contao\ManagerApi\Exception;

class RequestException extends \RuntimeException
{
    public function __construct(private readonly string $url, private readonly int|null $statusCode, \Throwable|null $previous = null)
    {
        $message = \sprintf('HTTP request to %s failed ', $this->url);
        if (null !== $this->statusCode) {
            $message .= 'with status code ' . $this->statusCode;
        }
        if (null !== $previous) {
            $message .= ' (' . $previous->getMessage() . ')';
        }
        parent::__construct($message, $previous?->getCode() ?? 0, $previous);
    }
    public function getUrl(): string
    {
        return $this->url;
    }
    public function getStatusCode(): int
    {
        return $this->statusCode;
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Contao Manager.
 *
 * (c) Contao Association
 *
 * @license LGPL-3.0-or-later
 */
namespace _ContaoManager\Contao\ManagerApi\IntegrityCheck;

use _ContaoManager\Crell\ApiProblem\ApiProblem;
class AllowUrlFopenCheck extends AbstractIntegrityCheck
{
    public function run(): ApiProblem|null
    {
        if (\ini_get('allow_url_fopen')) {
            return null;
        }
        return new ApiProblem($this->trans('allow_url_fopen.title'), 'https://php.net/allow_url_fopen');
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Contao Manager.
 *
 * (c) Contao Association
 *
 * @license LGPL-3.0-or-later
 */
namespace _ContaoManager\Contao\ManagerApi\IntegrityCheck;

use _ContaoManager\Crell\ApiProblem\ApiProblem;
class GraphicsLibCheck extends AbstractIntegrityCheck
{
    public function run(): ApiProblem|null
    {
        if ($this->hasGraphicsLib()) {
            return null;
        }
        return (new ApiProblem($this->trans('graphics_lib.title'), 'https://php.net/gd'))->setDetail($this->trans('graphics_lib.detail'));
    }
    private function hasGraphicsLib(): bool
    {
        if (\function_exists('gd_info') && version_compare(\constant('GD_VERSION'), '2.0.1', '>')) {
            return \true;
        }
        if (class_exists('Imagick')) {
            return \true;
        }
        if (class_exists('Gmagick')) {
            return \true;
        }
        return \false;
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Contao Manager.
 *
 * (c) Contao Association
 *
 * @license LGPL-3.0-or-later
 */
namespace _ContaoManager\Contao\ManagerApi\IntegrityCheck;

use Composer\Util\Platform;
use _ContaoManager\Crell\ApiProblem\ApiProblem;
use _ContaoManager\Symfony\Component\Process\ExecutableFinder;
class ZipCheck extends AbstractIntegrityCheck
{
    public function run(): ApiProblem|null
    {
        if (class_exists(\ZipArchive::class)) {
            return null;
        }
        $finder = new ExecutableFinder();
        if ($finder->find('unzip') || $finder->find('7z', null, ['C:\Program Files\7-Zip']) || !Platform::isWindows() && $finder->find('7zz')) {
            return null;
        }
        return new ApiProblem($this->trans('zip.title'), 'https://getcomposer.org/doc/articles/troubleshooting.md#zip-archives-are-not-unpacked-correctly-');
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Contao Manager.
 *
 * (c) Contao Association
 *
 * @license LGPL-3.0-or-later
 */
namespace _ContaoManager\Contao\ManagerApi\IntegrityCheck;

use _ContaoManager\Contao\ManagerApi\I18n\Translator;
use _ContaoManager\Crell\ApiProblem\ApiProblem;
use _ContaoManager\Symfony\Component\Filesystem\Exception\IOException;
use _ContaoManager\Symfony\Component\Filesystem\Filesystem;
class SysTempDirCheck extends AbstractIntegrityCheck
{
    public function __construct(private readonly Filesystem $filesystem, Translator $translator)
    {
        parent::__construct($translator);
    }
    public function run(): ApiProblem|null
    {
        $tempdir = rtrim(sys_get_temp_dir(), '/');
        $subdir = $tempdir . '/' . md5(__DIR__);
        if (!$this->canWriteFileInDirectory($tempdir) || !$this->canWriteFileInDirectory($subdir, \true)) {
            return (new ApiProblem($this->trans('systempdir.title'), 'https://php.net/open_basedir'))->setDetail($this->trans('systempdir.detail'));
        }
        return null;
    }
    private function canWriteFileInDirectory(string $path, bool $createDirectory = \false): bool
    {
        if ($createDirectory) {
            try {
                $this->filesystem->remove($path);
            } catch (IOException) {
            }
            try {
                $this->filesystem->mkdir($path);
            } catch (IOException) {
            }
        }
        $file = $path . '/' . md5(__FILE__);
        try {
            $this->filesystem->touch($file);
            $result = is_writable($file);
        } catch (IOException) {
            $result = \false;
        }
        try {
            $this->filesystem->remove($file);
        } catch (IOException) {
        }
        if ($createDirectory) {
            try {
                $this->filesystem->remove($path);
            } catch (IOException) {
            }
        }
        return $result;
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Contao Manager.
 *
 * (c) Contao Association
 *
 * @license LGPL-3.0-or-later
 */
namespace _ContaoManager\Contao\ManagerApi\IntegrityCheck;

use _ContaoManager\Crell\ApiProblem\ApiProblem;
interface IntegrityCheckInterface
{
    /**
     * Runs the integrity check.
     */
    public function run(): ApiProblem|null;
}
<?php

declare (strict_types=1);
/*
 * This file is part of Contao Manager.
 *
 * (c) Contao Association
 *
 * @license LGPL-3.0-or-later
 */
namespace _ContaoManager\Contao\ManagerApi\IntegrityCheck;

use _ContaoManager\Crell\ApiProblem\ApiProblem;
class ProcessCheck extends AbstractIntegrityCheck
{
    public function run(): ApiProblem|null
    {
        if (\function_exists('proc_open') && \function_exists('proc_close') && \function_exists('proc_get_status') && \function_exists('proc_terminate')) {
            return null;
        }
        return (new ApiProblem($this->trans('process.title'), 'https://php.net/proc_open'))->setDetail($this->trans('process.detail'));
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Contao Manager.
 *
 * (c) Contao Association
 *
 * @license LGPL-3.0-or-later
 */
namespace _ContaoManager\Contao\ManagerApi\IntegrityCheck;

use _ContaoManager\Contao\ManagerApi\ApiKernel;
use _ContaoManager\Contao\ManagerApi\I18n\Translator;
use _ContaoManager\Crell\ApiProblem\ApiProblem;
use _ContaoManager\Symfony\Component\Filesystem\Filesystem;
class SymlinkCheck extends AbstractIntegrityCheck
{
    public function __construct(private readonly ApiKernel $kernel, private readonly Filesystem $filesystem, Translator $translator)
    {
        parent::__construct($translator);
    }
    public function run(): ApiProblem|null
    {
        if (null === $error = $this->canCreateSymlinks()) {
            return null;
        }
        return (new ApiProblem($this->trans('symlink.title'), 'https://php.net/symlink'))->setDetail($error);
    }
    private function canCreateSymlinks(): string|null
    {
        if (!\function_exists('symlink') && !\function_exists('_ContaoManager\symlink')) {
            return '';
        }
        try {
            $tempname = $this->filesystem->tempnam(sys_get_temp_dir(), '');
            $this->filesystem->remove($tempname);
            $this->filesystem->symlink($this->kernel->getProjectDir(), $tempname);
            $this->filesystem->remove($tempname);
        } catch (\Exception $exception) {
            return $exception->getMessage();
        }
        return null;
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Contao Manager.
 *
 * (c) Contao Association
 *
 * @license LGPL-3.0-or-later
 */
namespace _ContaoManager\Contao\ManagerApi\IntegrityCheck;

use _ContaoManager\Crell\ApiProblem\ApiProblem;
class SessionCheck extends AbstractIntegrityCheck
{
    public function run(): ApiProblem|null
    {
        $detail = '';
        try {
            $options = ['read_and_close' => '1', 'use_cookies' => '0'];
            if (session_start($options)) {
                return null;
            }
        } catch (\Exception $exception) {
            $detail = $exception->getMessage();
        }
        return (new ApiProblem($this->trans('session.title'), 'https://php.net/session_start'))->setDetail($detail);
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Contao Manager.
 *
 * (c) Contao Association
 *
 * @license LGPL-3.0-or-later
 */
namespace _ContaoManager\Contao\ManagerApi\IntegrityCheck;

use _ContaoManager\Crell\ApiProblem\ApiProblem;
class MemoryLimitCheck extends AbstractIntegrityCheck
{
    public function run(): ApiProblem|null
    {
        if (\PHP_SAPI !== 'cli' || $this->hasEnoughMemory()) {
            return null;
        }
        return (new ApiProblem($this->trans('memory_limit.title'), 'https://php.net/memory_limit'))->setDetail($this->trans('memory_limit.detail', ['limit' => trim(\ini_get('memory_limit'))]));
    }
    private function hasEnoughMemory(): bool
    {
        $memoryLimit = trim((string) \ini_get('memory_limit'));
        if ('-1' === $memoryLimit) {
            return \true;
        }
        /** @noinspection SubStrUsedAsArrayAccessInspection */
        $unit = strtolower(substr($memoryLimit, -1, 1));
        $memoryLimit = (int) $memoryLimit;
        switch ($unit) {
            case 'g':
                $memoryLimit *= 1024;
            // no break
            case 'm':
                $memoryLimit *= 1024;
            // no break (cumulative multiplier)
            case 'k':
                $memoryLimit *= 1024;
        }
        return $memoryLimit >= 1024 * 1024 * 256;
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Contao Manager.
 *
 * (c) Contao Association
 *
 * @license LGPL-3.0-or-later
 */
namespace _ContaoManager\Contao\ManagerApi\IntegrityCheck;

use _ContaoManager\Crell\ApiProblem\ApiProblem;
class PhpExtensionsCheck extends AbstractIntegrityCheck
{
    private static array $extensions = ['intl', 'dom', 'xmlreader', 'openssl'];
    public function run(): ApiProblem|null
    {
        foreach (self::$extensions as $extension) {
            if (null !== $problem = $this->checkExtension($extension)) {
                return $problem;
            }
        }
        return null;
    }
    private function checkExtension(string $extension): ApiProblem|null
    {
        if (\extension_loaded($extension)) {
            return null;
        }
        return (new ApiProblem($this->trans($extension . '.title'), 'https://php.net/' . $extension))->setDetail($this->trans($extension . '.detail'));
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Contao Manager.
 *
 * (c) Contao Association
 *
 * @license LGPL-3.0-or-later
 */
namespace _ContaoManager\Contao\ManagerApi\IntegrityCheck;

use _ContaoManager\Contao\ManagerApi\I18n\Translator;
abstract class AbstractIntegrityCheck implements IntegrityCheckInterface
{
    public function __construct(private readonly Translator $translator)
    {
    }
    /**
     * Translates a string from the "integrity" domain.
     */
    protected function trans(string $id, array $params = []): string
    {
        return $this->translator->trans('integrity.' . $id, $params);
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Contao Manager.
 *
 * (c) Contao Association
 *
 * @license LGPL-3.0-or-later
 */
namespace _ContaoManager\Contao\ManagerApi\IntegrityCheck;

use _ContaoManager\Crell\ApiProblem\ApiProblem;
use _ContaoManager\Psr\Container\ContainerInterface;
use _ContaoManager\Symfony\Contracts\Service\ServiceSubscriberInterface;
class IntegrityCheckFactory implements ServiceSubscriberInterface
{
    private static array $webChecks = [AllowUrlFopenCheck::class, SysTempDirCheck::class, PhpExtensionsCheck::class, GraphicsLibCheck::class, SymlinkCheck::class, SessionCheck::class, MemoryLimitCheck::class, ProcessCheck::class];
    private static array $cliChecks = [MemoryLimitCheck::class, AllowUrlFopenCheck::class, SysTempDirCheck::class, PhpExtensionsCheck::class, SymlinkCheck::class, ProcessCheck::class];
    public function __construct(private readonly ContainerInterface $container)
    {
    }
    public function runWebChecks(): ApiProblem|null
    {
        return $this->runChecks(self::$webChecks);
    }
    public function runCliCheck(): ApiProblem|null
    {
        return $this->runChecks(self::$cliChecks);
    }
    public static function getSubscribedServices(): array
    {
        return array_unique(array_merge(self::$cliChecks, self::$webChecks));
    }
    private function runChecks(array $classes): ApiProblem|null
    {
        foreach ($classes as $class) {
            /** @var IntegrityCheckInterface $check */
            $check = $this->container->get($class);
            if (($problem = $check->run()) instanceof ApiProblem) {
                return $problem;
            }
        }
        return null;
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Contao Manager.
 *
 * (c) Contao Association
 *
 * @license LGPL-3.0-or-later
 */
namespace _ContaoManager\Contao\ManagerApi\Process;

use _ContaoManager\Seld\JsonLint\JsonParser;
use _ContaoManager\Seld\JsonLint\ParsingException;
use _ContaoManager\Symfony\Component\Filesystem\Filesystem;
use _ContaoManager\Symfony\Component\Process\Exception\ExceptionInterface;
use _ContaoManager\Symfony\Component\Process\Exception\ProcessFailedException;
class ContaoApi
{
    private array|null $apiInfo = null;
    public function __construct(private readonly ConsoleProcessFactory $processFactory, private readonly Filesystem $filesystem)
    {
    }
    /**
     * Gets the Contao API version.
     */
    public function getVersion(): int
    {
        return (int) $this->getApiInfo()['version'];
    }
    /**
     * Returns list of available API commands.
     */
    public function getCommands(): array
    {
        return $this->getApiInfo()['commands'];
    }
    /**
     * Returns whether the given API command is available.
     */
    public function hasCommand(string $name): bool
    {
        return \in_array($name, $this->getApiInfo()['commands'], \true);
    }
    /**
     * Returns list of available API features.
     */
    public function getFeatures(): array
    {
        return $this->getApiInfo()['features'];
    }
    public function runCommand(array|string $arguments): string
    {
        $process = $this->processFactory->createContaoApiProcess((array) $arguments);
        $process->mustRun();
        return $process->getOutput();
    }
    /**
     * @throws ParsingException
     * @throws ProcessFailedException
     */
    public function runJsonCommand(array|string $arguments): array|null
    {
        $process = $this->processFactory->createContaoApiProcess((array) $arguments);
        $process->mustRun();
        return $this->parseJson($process->getOutput());
    }
    /**
     * Checks whether the Contao API binary exists.
     */
    private function hasBinary(): bool
    {
        return $this->filesystem->exists($this->processFactory->getContaoApiPath());
    }
    /**
     * Returns version, commands and features of the Contao API.
     */
    private function getApiInfo(): array
    {
        if (null !== $this->apiInfo) {
            return $this->apiInfo;
        }
        $default = ['version' => 0, 'commands' => [], 'features' => []];
        if (!$this->hasBinary()) {
            return $this->apiInfo = $default;
        }
        try {
            $process = $this->processFactory->createContaoApiProcess(['version']);
            $process->mustRun();
        } catch (ExceptionInterface) {
            return $default;
        }
        $version = trim($process->getOutput());
        if (preg_match('/^\d+$/', $version)) {
            $default['version'] = (int) $version;
            return $this->apiInfo = $default;
        }
        try {
            return $this->apiInfo = $this->parseJson($version);
        } catch (ParsingException $exception) {
            $default['error'] = $exception->getMessage();
            return $this->apiInfo = $default;
        }
    }
    /**
     * @throws ParsingException
     */
    private function parseJson(string $output): array|null
    {
        $data = json_decode($output, \true);
        if (null === $data && \JSON_ERROR_NONE !== json_last_error()) {
            $parser = new JsonParser();
            $result = $parser->lint($output);
            if (null !== $result) {
                throw $result;
            }
        }
        return $data;
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Contao Manager.
 *
 * (c) Contao Association
 *
 * @license LGPL-3.0-or-later
 */
namespace _ContaoManager\Contao\ManagerApi\Process;

use _ContaoManager\Contao\ManagerApi\Process\Forker\ForkerInterface;
use _ContaoManager\Symfony\Component\Filesystem\Filesystem;
use _ContaoManager\Symfony\Component\Process\Process;
class ProcessController extends AbstractProcess
{
    /**
     * @var array
     */
    protected $config = [];
    /**
     * @var array<ForkerInterface>
     */
    private array $forkers = [];
    /**
     * @throws \InvalidArgumentException If the working directory does not exist
     */
    public function __construct(array $config, string $workDir)
    {
        if (!isset($config['status'])) {
            $config['status'] = Process::STATUS_READY;
        }
        $this->config = $config;
        parent::__construct($this->config['id'], $workDir);
    }
    public function addForker(ForkerInterface $forker): void
    {
        $this->forkers[] = $forker;
    }
    /**
     * Gets the task ID.
     */
    public function getId(): string
    {
        return (string) $this->config['id'];
    }
    /**
     * Stores meta information about the process.
     */
    public function setMeta(array $meta): void
    {
        $this->config['meta'] = $meta;
        $this->saveConfig(\true);
    }
    /**
     * Gets meta information of the process.
     */
    public function getMeta(): array|null
    {
        return $this->config['meta'] ?? null;
    }
    public function start(): void
    {
        if (Process::STATUS_STARTED === $this->config['status']) {
            return;
        }
        $forker = $this->getForker();
        $this->saveConfig(\true);
        $this->config['status'] = Process::STATUS_STARTED;
        $forker->run($this->setFile);
    }
    public function getPid(): int|null
    {
        $this->updateStatus();
        return isset($this->config['pid']) ? (int) $this->config['pid'] : null;
    }
    public function getExitCode(): int|null
    {
        $this->updateStatus();
        return isset($this->config['exitcode']) ? (int) $this->config['exitcode'] : null;
    }
    public function getExitCodeText(): string
    {
        if (null === $exitcode = $this->getExitCode()) {
            return '';
        }
        return Process::$exitCodes[$exitcode] ?? 'Unknown error';
    }
    public function isSuccessful(): bool
    {
        return 0 === $this->getExitCode();
    }
    public function hasBeenSignaled(): bool
    {
        return isset($this->config['signaled']) && $this->config['signaled'];
    }
    public function getTermSignal(): int|null
    {
        return isset($this->config['termsig']) ? (int) $this->config['termsig'] : null;
    }
    public function hasBeenStopped(): bool
    {
        return isset($this->config['stopped']) && $this->config['stopped'];
    }
    public function getStopSignal(): int|null
    {
        return isset($this->config['stopsig']) ? (int) $this->config['stopsig'] : null;
    }
    public function isRunning(): bool
    {
        return Process::STATUS_STARTED === $this->getStatus();
    }
    public function isStarted(): bool
    {
        return Process::STATUS_READY !== $this->getStatus();
    }
    public function isTerminated(): bool
    {
        return Process::STATUS_TERMINATED === $this->getStatus();
    }
    public function isTimedOut(): bool
    {
        return Process::STATUS_TERMINATED === $this->getStatus() && $this->config['timedout'] > 0;
    }
    public function getStatus(): string
    {
        $this->updateStatus();
        return $this->config['status'];
    }
    public function stop(): void
    {
        $this->config['stop'] = \true;
        $this->saveConfig();
    }
    public function delete(): void
    {
        if ($this->isRunning()) {
            throw new \LogicException('Cannot delete a running process.');
        }
        $this->close();
    }
    public function getCommandLine(): string
    {
        if (!\is_array($this->config['commandline'])) {
            return (string) $this->config['commandline'];
        }
        return implode(' ', $this->config['commandline']);
    }
    public function setCommandLine(array $commandline): void
    {
        $this->config['commandline'] = $commandline;
        $this->saveConfig();
    }
    public function setWorkingDirectory(string $cwd): void
    {
        $this->config['cwd'] = $cwd;
        $this->saveConfig();
    }
    public function getOutput(): string
    {
        if (!is_file($this->outputFile)) {
            return '';
        }
        return file_get_contents($this->outputFile);
    }
    public function setTimeout(int $timeout): void
    {
        $this->config['timeout'] = $timeout;
        $this->saveConfig();
    }
    public function setIdleTimeout(int $timeout): void
    {
        $this->config['idleTimeout'] = $timeout;
        $this->saveConfig();
    }
    public function getForker(): ForkerInterface
    {
        $class = $this->config['forker'] ?? null;
        foreach ($this->forkers as $forker) {
            if (null === $class ? $forker->isSupported() : $forker instanceof $class) {
                $this->config['forker'] = $forker::class;
                return $forker;
            }
        }
        throw new \RuntimeException('No forker found for your current platform.');
    }
    public static function create(string $workDir, array $commandline, string|null $cwd = null, string|null $id = null): self
    {
        return new self(['id' => $id ?: md5(uniqid('', \true)), 'commandline' => $commandline, 'cwd' => $cwd ?: getcwd()], $workDir);
    }
    public static function restore(string $workDir, string $id): self
    {
        $config = static::readConfig($workDir . '/' . $id . '.set.json');
        if (is_file($getFile = $workDir . '/' . $id . '.get.json')) {
            $config = array_merge($config, static::readConfig($getFile));
        }
        return new self($config, $workDir);
    }
    private function saveConfig(bool $always = \false): void
    {
        if ($always || Process::STATUS_STARTED === $this->config['status']) {
            static::writeConfig($this->setFile, $this->config);
        }
    }
    private function updateStatus(): void
    {
        if (Process::STATUS_STARTED !== $this->config['status']) {
            return;
        }
        if (is_file($this->getFile)) {
            $this->config = array_merge($this->config, static::readConfig($this->getFile));
        }
    }
    private function close(): void
    {
        $fs = new Filesystem();
        $fs->remove($this->setFile);
        $fs->remove($this->getFile);
        $fs->remove($this->inputFile);
        $fs->remove($this->outputFile);
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Contao Manager.
 *
 * (c) Contao Association
 *
 * @license LGPL-3.0-or-later
 */
namespace _ContaoManager\Contao\ManagerApi\Process\Forker;

use _ContaoManager\Psr\Log\LoggerInterface;
use _ContaoManager\Symfony\Component\Process\Process;
abstract class AbstractForker implements ForkerInterface
{
    private int $timeout = 500;
    public function __construct(protected array $command, protected array|null $env = null, protected LoggerInterface|null $logger = null)
    {
    }
    public function setCommand(array $command): ForkerInterface
    {
        $this->command = $command;
        return $this;
    }
    public function getCommand(): array
    {
        return $this->command;
    }
    public function setTimeout(int $timeout): ForkerInterface
    {
        $this->timeout = $timeout;
        return $this;
    }
    public function getTimeout(): int
    {
        return $this->timeout;
    }
    protected function startCommand(string $commandline): Process
    {
        if (null !== $this->logger) {
            $this->logger->info('Starting "{commandline}" with {forker_class}', ['commandline' => $commandline, 'forker_class' => static::class]);
        }
        $process = Process::fromShellCommandline($commandline);
        $process->setTimeout(null);
        $process->setIdleTimeout(null);
        $process->start(null, $this->env ?: []);
        usleep($this->timeout);
        if (null !== $this->logger && !$process->isStarted()) {
            $this->logger->error('Process did not start correctly', ['commandline' => $commandline, 'forker_class' => static::class, 'exit_code' => $process->getExitCode(), 'exit_text' => $process->getExitCodeText(), 'stopped' => $process->hasBeenStopped(), 'signaled' => $process->hasBeenSignaled(), 'stopsignal' => $process->getStopSignal(), 'termsignal' => $process->getTermSignal()]);
        }
        return $process;
    }
    /**
     * Escapes a string to be used as a shell argument.
     *
     * @see Process::escapeArgument()
     */
    protected function escapeArgument(string|null $argument): string
    {
        if ('' === $argument || null === $argument) {
            return '""';
        }
        if ('\\' !== \DIRECTORY_SEPARATOR) {
            return "'" . str_replace("'", "'\\''", $argument) . "'";
        }
        if (str_contains($argument, "\x00")) {
            $argument = str_replace("\x00", '?', $argument);
        }
        if (!preg_match('/[\/()%!^"<>&|\s]/', $argument)) {
            return $argument;
        }
        $argument = preg_replace('/(\\\\+)$/', '$1$1', $argument);
        return '"' . str_replace(['"', '^', '%', '!', "\n"], ['""', '"^^"', '"^%"', '"^!"', '!LF!'], $argument) . '"';
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Contao Manager.
 *
 * (c) Contao Association
 *
 * @license LGPL-3.0-or-later
 */
namespace _ContaoManager\Contao\ManagerApi\Process\Forker;

use _ContaoManager\Psr\Log\LoggerInterface;
interface ForkerInterface
{
    public function __construct(array $arguments, array|null $env = null, LoggerInterface|null $logger = null);
    /**
     * Sets the command to use for the background process.
     */
    public function setCommand(array $command): self;
    /**
     * Gets the command to use for the background process.
     */
    public function getCommand(): array;
    /**
     * Sets the timeout in milliseconds to wait after starting a process.
     */
    public function setTimeout(int $timeout): self;
    /**
     * Gets the timeout in milliseconds to wait after starting a process.
     */
    public function getTimeout(): int;
    /**
     * Executes a command.
     */
    public function run(string $configFile): void;
    /**
     * Returns whether this forker is supported on the current platform.
     */
    public function isSupported(): bool;
}
<?php

declare (strict_types=1);
/*
 * This file is part of Contao Manager.
 *
 * (c) Contao Association
 *
 * @license LGPL-3.0-or-later
 */
namespace _ContaoManager\Contao\ManagerApi\Process\Forker;

use _ContaoManager\Symfony\Component\Process\Exception\ProcessFailedException;
use _ContaoManager\Symfony\Component\Process\Process;
class DisownForker extends AbstractForker
{
    public function run(string $configFile): void
    {
        $commandline = \sprintf('exec %s %s >/dev/null 2>&1 </dev/null & disown', implode(' ', array_map([$this, 'escapeArgument'], $this->command)), $this->escapeArgument($configFile));
        $this->startCommand($commandline);
    }
    public function isSupported(): bool
    {
        try {
            Process::fromShellCommandline("exec echo '' & disown")->mustRun(null, $this->env);
        } catch (ProcessFailedException) {
            return \false;
        }
        return \true;
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Contao Manager.
 *
 * (c) Contao Association
 *
 * @license LGPL-3.0-or-later
 */
namespace _ContaoManager\Contao\ManagerApi\Process\Forker;

use _ContaoManager\Symfony\Component\Process\Exception\ProcessFailedException;
use _ContaoManager\Symfony\Component\Process\Process;
class NohupForker extends AbstractForker
{
    public function run(string $configFile): void
    {
        $commandline = \sprintf('exec nohup %s %s >/dev/null </dev/null 2>&1 &', implode(' ', array_map([$this, 'escapeArgument'], $this->command)), $this->escapeArgument($configFile));
        $this->startCommand($commandline);
    }
    public function isSupported(): bool
    {
        try {
            Process::fromShellCommandline('exec nohup ls')->mustRun(null, $this->env);
        } catch (ProcessFailedException) {
            return \false;
        }
        return \true;
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Contao Manager.
 *
 * (c) Contao Association
 *
 * @license LGPL-3.0-or-later
 */
namespace _ContaoManager\Contao\ManagerApi\Process\Forker;

use _ContaoManager\Symfony\Component\Process\Exception\ProcessFailedException;
use _ContaoManager\Symfony\Component\Process\Process;
class WindowsStartForker extends AbstractForker
{
    public function run(string $configFile): void
    {
        $commandline = \sprintf('start /b %s %s 2>&1 >nul <nul', implode(' ', array_map([$this, 'escapeArgument'], $this->command)), $this->escapeArgument($configFile));
        $this->startCommand($commandline);
    }
    public function isSupported(): bool
    {
        if ('\\' !== \DIRECTORY_SEPARATOR) {
            return \false;
        }
        try {
            Process::fromShellCommandline('start /b dir')->mustRun(null, $this->env);
        } catch (ProcessFailedException) {
            return \false;
        }
        return \true;
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Contao Manager.
 *
 * (c) Contao Association
 *
 * @license LGPL-3.0-or-later
 */
namespace _ContaoManager\Contao\ManagerApi\Process\Forker;

class InlineForker extends AbstractForker
{
    public function run(string $configFile): void
    {
        $arguments = $this->command;
        $binary = array_shift($arguments);
        $commandline = \sprintf('%s %s %s', escapeshellcmd($binary), implode(' ', array_map([$this, 'escapeArgument'], $arguments)), $this->escapeArgument($configFile));
        $process = $this->startCommand($commandline);
        $process->wait();
    }
    public function isSupported(): bool
    {
        return \true;
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Contao Manager.
 *
 * (c) Contao Association
 *
 * @license LGPL-3.0-or-later
 */
namespace _ContaoManager\Contao\ManagerApi\Process;

use _ContaoManager\Symfony\Component\Process\Process;
class Utf8Process extends Process
{
    public function getOutput(): string
    {
        return $this->normalizeOutput(parent::getOutput());
    }
    public function getErrorOutput(): string
    {
        return $this->normalizeOutput(parent::getErrorOutput());
    }
    /**
     * Normalize encoding and try to fix PHP error level issues.
     */
    private function normalizeOutput(string $output): string
    {
        $output = $this->convertEncoding($output);
        return implode("\n", array_filter(preg_split('/\r\n|\r|\n/', $output), static fn(string $line): bool => !str_starts_with($line, 'PHP Warning:') && !str_starts_with($line, 'Warning:') && !str_starts_with($line, 'Deprecated:') && !str_starts_with($line, 'Runtime Notice:') && !str_starts_with($line, 'Failed loading ')));
    }
    private function convertEncoding(string $data): string
    {
        if (\false !== @json_encode($data)) {
            return $data;
        }
        if (\function_exists('mb_convert_encoding')) {
            $encoding = null;
            if (\function_exists('mb_detect_encoding')) {
                $encoding = mb_detect_encoding($data, mb_detect_order(), \true) ?: null;
            }
            return mb_convert_encoding($data, 'UTF-8', $encoding);
        }
        if (\function_exists('utf8_encode')) {
            return utf8_encode($data);
        }
        return $data;
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Contao Manager.
 *
 * (c) Contao Association
 *
 * @license LGPL-3.0-or-later
 */
declare (ticks=1);
namespace _ContaoManager\Contao\ManagerApi\Process;

use _ContaoManager\Symfony\Component\Process\Exception\ProcessTimedOutException;
use _ContaoManager\Symfony\Component\Process\Process;
class ProcessRunner extends AbstractProcess
{
    private readonly Utf8Process $process;
    private ProcessTimedOutException|null $timeout = null;
    /**
     * @var resource
     */
    private $stdin;
    /**
     * @var resource
     */
    private $stdout;
    public function __construct(string $configFile)
    {
        $config = static::readConfig($configFile);
        parent::__construct($config['id'], \dirname($configFile));
        $commandline = $config['commandline'] ?? [];
        $cwd = $config['cwd'] ?? null;
        $this->process = new Utf8Process($commandline, $cwd);
        $this->loadConfig($config);
    }
    public function __destruct()
    {
        $this->stop(0);
    }
    public function run(int $interval = 1): int
    {
        $this->start();
        return $this->wait($interval);
    }
    public function start(): void
    {
        if ($this->process->isStarted()) {
            return;
        }
        $handler = function ($signo = 15) {
            $this->signalHandler($signo);
            return null;
        };
        register_shutdown_function($handler);
        if (\function_exists('pcntl_signal')) {
            pcntl_signal(\SIGHUP, $handler);
            pcntl_signal(\SIGINT, $handler);
            pcntl_signal(\SIGQUIT, $handler);
            pcntl_signal(\SIGTERM, $handler);
        }
        if (is_file($this->inputFile)) {
            $this->stdin = fopen($this->inputFile, 'r');
            $this->process->setInput($this->stdin);
        }
        $this->process->start(function ($type, $data): void {
            $this->addOutput($data);
        });
        $this->saveConfig();
    }
    public function wait(int $interval): int
    {
        do {
            usleep($interval * 1000000);
            try {
                $this->process->checkTimeout();
                $running = $this->process->isRunning();
            } catch (ProcessTimedOutException $e) {
                $this->timeout = $e;
                $running = \false;
            }
            $config = $this->loadConfig();
            if ($running && isset($config['stop']) && $config['stop']) {
                return $this->stop();
            }
            $this->saveConfig();
        } while ($running);
        $this->close();
        return $this->process->getExitCode();
    }
    public function stop(int $timeout = 10): int
    {
        if (!$this->process->isRunning()) {
            return $this->process->getExitCode();
        }
        $exitCode = $this->process->stop($timeout);
        $this->saveConfig();
        $this->close();
        return $exitCode;
    }
    public function addOutput(string $line): void
    {
        if (!\is_resource($this->stdout)) {
            $this->stdout = fopen($this->outputFile, 'w');
        }
        fwrite($this->stdout, $line);
    }
    private function close(): void
    {
        if (\is_resource($this->stdin)) {
            fclose($this->stdin);
        }
        if (\is_resource($this->stdout)) {
            fclose($this->stdout);
        }
    }
    private function signalHandler(int $signo): void
    {
        $this->stop(15 === $signo ? 0 : 10);
    }
    private function loadConfig(array|null $config = null): array
    {
        if (null === $config) {
            $config = static::readConfig($this->setFile);
        }
        $props = ['timeout' => 'setTimeout', 'idleTimeout' => 'setIdleTimeout'];
        foreach ($props as $key => $setter) {
            if (isset($config[$key])) {
                $this->process->{$setter}($config[$key]);
            }
        }
        return $config;
    }
    private function saveConfig(): void
    {
        $status = $this->process->getStatus();
        $config = ['cwd' => $this->process->getWorkingDirectory(), 'timeout' => $this->process->getTimeout(), 'idleTimeout' => $this->process->getIdleTimeout(), 'pid' => $this->process->getPid(), 'status' => $status];
        if (Process::STATUS_TERMINATED === $status) {
            $config['exitcode'] = $this->process->getExitCode();
            $config['signaled'] = $this->process->hasBeenSignaled();
            $config['termsig'] = $this->process->getTermSignal();
            $config['stopped'] = $this->process->hasBeenStopped();
            $config['stopsig'] = $this->process->getStopSignal();
            $config['timedout'] = $this->timeoutCode();
        }
        static::writeConfig($this->getFile, $config);
    }
    /**
     * Returns the timeout type.
     */
    private function timeoutCode(): int
    {
        if ($this->timeout instanceof ProcessTimedOutException) {
            if ($this->timeout->isGeneralTimeout()) {
                return ProcessTimedOutException::TYPE_GENERAL;
            }
            if ($this->timeout->isIdleTimeout()) {
                return ProcessTimedOutException::TYPE_IDLE;
            }
        }
        return 0;
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Contao Manager.
 *
 * (c) Contao Association
 *
 * @license LGPL-3.0-or-later
 */
namespace _ContaoManager\Contao\ManagerApi\Process;

use _ContaoManager\Contao\ManagerApi\Exception\InvalidJsonException;
use _ContaoManager\Symfony\Component\Filesystem\Exception\IOException;
use _ContaoManager\Symfony\Component\Filesystem\Filesystem;
abstract class AbstractProcess
{
    protected string $setFile;
    protected string $getFile;
    protected string $inputFile;
    protected string $outputFile;
    /**
     * @throws \InvalidArgumentException If the working directory does not exist
     */
    public function __construct(string $id, string $workDir)
    {
        $dir = realpath(rtrim($workDir, '/'));
        if (\false === $dir) {
            throw new \InvalidArgumentException(\sprintf('Working directory "%s" does not exist.', $workDir));
        }
        $this->setFile = $dir . '/' . $id . '.set.json';
        $this->getFile = $dir . '/' . $id . '.get.json';
        $this->inputFile = $dir . '/' . $id . '.in.log';
        $this->outputFile = $dir . '/' . $id . '.out.log';
    }
    /**
     * @throws InvalidJsonException
     */
    protected static function readConfig(string $filename): array
    {
        // Make sure new process files are found (see
        // https://github.com/contao/contao-manager/issues/438)
        clearstatcache();
        $content = @file_get_contents($filename);
        if (\false === $content) {
            throw new \InvalidArgumentException(\sprintf('Config file "%s" is not readable or does not exist.', $filename));
        }
        $config = json_decode($content, \true);
        if (!\is_array($config)) {
            throw new InvalidJsonException($filename, $content);
        }
        return $config;
    }
    /**
     * @throws \RuntimeException
     */
    protected static function writeConfig(string $filename, array $config): void
    {
        try {
            (new Filesystem())->dumpFile($filename, json_encode($config));
        } catch (IOException $ioException) {
            throw new \RuntimeException(\sprintf('Unable to write config file to %s. ' . $ioException->getMessage(), $filename), 0, $ioException);
        }
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Contao Manager.
 *
 * (c) Contao Association
 *
 * @license LGPL-3.0-or-later
 */
namespace _ContaoManager\Contao\ManagerApi\Process;

use Composer\Semver\VersionParser;
use Composer\Util\Platform;
use _ContaoManager\Contao\ManagerApi\Exception\ProcessOutputException;
use _ContaoManager\Symfony\Component\Process\Exception\ProcessFailedException;
class ContaoConsole
{
    private string|null $version = null;
    private array|null $commands = null;
    private array|null $config = null;
    public function __construct(private readonly ConsoleProcessFactory $processFactory)
    {
    }
    /**
     * Gets the Contao version.
     *
     * @throws ProcessOutputException
     */
    public function getVersion(): string
    {
        if (null !== $this->version) {
            return $this->version;
        }
        $this->getCommandList(\true);
        // @phpstan-ignore notIdentical.alwaysFalse
        if (null !== $this->version) {
            return $this->version;
        }
        $process = $this->processFactory->createContaoConsoleProcess(['contao:version']);
        $process->run();
        $version = trim($process->getOutput());
        try {
            // Run parser to check whether a valid version was returned
            $parser = new VersionParser();
            $parser->normalize($version);
        } catch (\UnexpectedValueException) {
            throw new ProcessOutputException('Console output is not a valid version string.', $process);
        }
        return $this->version = $version;
    }
    public function getCommandList(bool $throw = \false): array
    {
        if (null !== $this->commands) {
            return $this->commands;
        }
        $process = $this->processFactory->createContaoConsoleProcess(['list', '--format=json']);
        $process->run();
        // If the console does not work, we don't have any command support.
        if (!$process->isSuccessful() || !\is_array($data = json_decode(trim($process->getOutput()), \true))) {
            if ($throw) {
                throw new ProcessOutputException('Unable to retrieve console commands.', $process);
            }
            return $this->commands = [];
        }
        if ('Contao Managed Edition' === ($data['application']['name'] ?? '') && isset($data['application']['version'])) {
            try {
                // Run parser to check whether a valid version was returned
                $parser = new VersionParser();
                $parser->normalize($data['application']['version']);
                $this->version = $data['application']['version'];
            } catch (\UnexpectedValueException) {
                // ignore version from command list
            }
        }
        return $this->commands = $this->normalizeCommands($data['commands'] ?? []);
    }
    public function getConfig(): array|null
    {
        if (null !== $this->config) {
            return $this->config;
        }
        $commands = $this->getCommandList();
        if (!isset($commands['debug:config']['options']) || !\in_array('format', $commands['debug:config']['options'], \true)) {
            return $this->config = [];
        }
        $process = $this->processFactory->createContaoConsoleProcess(['debug:config', 'contao', '--format=json', '--resolve-env']);
        $process->run();
        // If the console does not work, we don't have any command support.
        if (!$process->isSuccessful() || !\is_array($data = json_decode(trim($process->getOutput()), \true))) {
            return $this->config = [];
        }
        return $this->config = $data['contao'] ?? [];
    }
    public function checkDatabaseMigrations(): array|null
    {
        $commands = $this->getCommandList();
        if (!isset($commands['contao:migrate']['options']) || !\in_array('format', $commands['contao:migrate']['options'], \true) || !\in_array('dry-run', $commands['contao:migrate']['options'], \true)) {
            return null;
        }
        $arguments = ['contao:migrate', '--format=ndjson', '--dry-run', '--no-interaction'];
        if (\in_array('no-backup', $commands['contao:migrate']['options'], \true)) {
            $arguments[] = '--no-backup';
        }
        $process = $this->processFactory->createContaoConsoleProcess($arguments);
        $process->run();
        $output = trim($process->getOutput());
        // Process could exit with error but still output JSON
        if (!$process->isSuccessful() && !str_starts_with($output, '{')) {
            return ['type' => 'error', 'total' => 1, 'message' => $process->getOutput() . $process->getErrorOutput(), 'warnings' => 0];
        }
        $warnings = 0;
        if ('' !== $output) {
            $lines = explode("\n", $output);
            while ($line = array_shift($lines)) {
                $data = json_decode($line, \true);
                $type = $data['type'] ?? null;
                if ('warning' === $type) {
                    ++$warnings;
                    continue;
                }
                if ('error' === $type || 'problem' === $type) {
                    return ['type' => $type, 'total' => 1, 'message' => $data['message'] ?? '', 'warnings' => $warnings];
                }
                if ('migration-pending' === $type && !empty($data['names'])) {
                    return ['type' => 'migration', 'total' => \count($data['names']), 'warnings' => $warnings];
                }
                if ('schema-pending' === $type && !empty($data['commands'])) {
                    return ['type' => 'schema', 'total' => \count($data['commands']), 'warnings' => $warnings];
                }
            }
        }
        return ['type' => 'empty', 'total' => 0, 'warnings' => $warnings];
    }
    public function getUsers(bool $throw = \false): array|null
    {
        $commands = $this->getCommandList();
        if (!isset($commands['contao:user:list']['options']) || !\in_array('format', $commands['contao:user:list']['options'], \true) || !\in_array('column', $commands['contao:user:list']['options'], \true)) {
            return null;
        }
        $arguments = ['contao:user:list', '--format=json', '--column=username', '--column=name', '--column=admin', '--column=dateAdded', '--column=lastLogin', '--no-interaction'];
        $process = $this->processFactory->createContaoConsoleProcess($arguments);
        $process->run();
        if (!$process->isSuccessful()) {
            if ($throw) {
                throw new ProcessFailedException($process);
            }
            return null;
        }
        $data = json_decode($process->getOutput(), \true);
        if (!\is_array($data)) {
            if ($throw) {
                throw new ProcessOutputException('Unable to list Contao users', $process);
            }
            return null;
        }
        return $data;
    }
    /**
     * @throws \RuntimeException
     * @throws ProcessFailedException
     */
    public function createBackendUser(array $user, string $password, bool $admin = \true): void
    {
        $commands = $this->getCommandList();
        if (!isset($commands['contao:user:create']['options']) || $admin && !\in_array('admin', $commands['contao:user:create']['options'], \true) || [] !== array_diff(array_keys($user), $commands['contao:user:create']['options'])) {
            throw new \RuntimeException('Unsupported argument to the contao:user:create command.');
        }
        $arguments = ['contao:user:create'];
        foreach ($user as $k => $v) {
            $arguments[] = '--' . $k . '=' . $v;
        }
        if ($admin) {
            $arguments[] = '--admin';
        }
        if (Platform::isWindows()) {
            $arguments[] = '--password=' . $password;
        }
        $process = $this->processFactory->createContaoConsoleProcess($arguments);
        if (!Platform::isWindows()) {
            $process->setInput($password . \PHP_EOL . $password . \PHP_EOL);
            // Password and confirmation
        }
        $process->mustRun();
    }
    private function normalizeCommands(array $commands): array
    {
        $data = [];
        foreach ($commands as $command) {
            $data[$command['name']] = ['arguments' => array_keys($command['definition']['arguments'] ?? []), 'options' => array_keys($command['definition']['options'] ?? [])];
        }
        return $data;
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Contao Manager.
 *
 * (c) Contao Association
 *
 * @license LGPL-3.0-or-later
 */
namespace _ContaoManager\Contao\ManagerApi\Process;

use _ContaoManager\Psr\Log\LoggerInterface;
use _ContaoManager\Symfony\Component\Process\Exception\RuntimeException;
use _ContaoManager\Symfony\Component\Process\Process;
class PhpExecutableFinder
{
    private array $names = ['php-cli', 'php'];
    public function __construct(private readonly LoggerInterface $logger)
    {
    }
    /**
     * Finds the best matching PHP executable on the system. Contrary to
     * symfony/process PhpExecutableFinder we actually test if the binary is the same
     * version as the currently running web process.
     */
    public function find(array $paths = [], bool $discover = \true): string|null
    {
        if (!$discover) {
            return $this->findBestBinary($paths);
        }
        if ($bin = \constant('PHP_BINARY')) {
            if (\false !== $suffix = strrchr(basename($bin), '-')) {
                $php = substr($bin, 0, -\strlen($suffix));
                $paths[] = $php . '-cli';
                $paths[] = $php;
            }
            $paths[] = $bin . '-cli';
            $paths[] = $bin;
            $this->includePath($paths, \dirname($bin));
        }
        if (\defined('PHP_BINDIR') && '' !== \PHP_BINDIR) {
            $this->includePath($paths, \PHP_BINDIR);
        }
        if ($php = getenv('PHP_PATH')) {
            $paths[] = $php;
        }
        if ($php = getenv('PHP_PEAR_PHP_BIN')) {
            $paths[] = $php;
        }
        $paths[] = '/usr/bin/php';
        $paths = array_merge($paths, $this->findExecutables());
        $paths = array_unique($paths);
        ksort($paths);
        return $this->findBestBinary($paths);
    }
    public function getServerInfo(string $cli): array|null
    {
        $phar = \Phar::running(\false);
        $arguments = [$cli, '-q'];
        $arguments[] = $phar ?: \dirname(__DIR__) . '/console';
        $arguments[] = 'test';
        try {
            $process = new Process($arguments);
            $process->mustRun(null, array_map(static fn(): bool => \false, $_ENV));
            $output = @json_decode(trim($process->getOutput()), \true);
            if (null === $output) {
                throw new RuntimeException('Unexpected output from "' . implode(' ', $arguments) . '": ' . $process->getOutput());
            }
            return $output;
        } catch (RuntimeException $exception) {
            // Do not log every attempt to find a PHP binary (exit code 127 = Command not found)
            if (127 === $process->getExitCode()) {
                return null;
            }
            $this->logger->error($exception->getMessage(), ['exception' => $exception]);
            throw $exception;
        }
    }
    /**
     * Finds PHP executables within open_basedir or PATH environment variable.
     */
    private function findExecutables(): array
    {
        $results = [];
        if (\ini_get('open_basedir')) {
            $searchPath = explode(\PATH_SEPARATOR, \ini_get('open_basedir'));
            $dirs = [];
            foreach ($searchPath as $path) {
                // Silencing against https://bugs.php.net/69240
                if (@is_dir($path)) {
                    $dirs[] = $path;
                } elseif (@is_executable($path) && \in_array(basename($path), $this->names, \true)) {
                    $results[] = $path;
                }
            }
        } else {
            $dirs = [];
            if ($path = getenv('PATH') ?: getenv('Path')) {
                $dirs = explode(\PATH_SEPARATOR, $path);
            }
            if ('\\' === \DIRECTORY_SEPARATOR) {
                $dirs[] = 'C:\xampp\php\\';
            }
        }
        $suffixes = [''];
        if ('\\' === \DIRECTORY_SEPARATOR) {
            $pathExt = getenv('PATHEXT');
            $suffixes = array_merge($suffixes, $pathExt ? explode(\PATH_SEPARATOR, $pathExt) : ['.exe', '.bat', '.cmd', '.com']);
        }
        foreach ($this->names as $name) {
            foreach ($suffixes as $suffix) {
                foreach ($dirs as $dir) {
                    if (@is_file($file = $dir . \DIRECTORY_SEPARATOR . $name . $suffix) && ('\\' === \DIRECTORY_SEPARATOR || is_executable($file))) {
                        $results[] = $file;
                    }
                }
            }
        }
        return $results;
    }
    private function findBestBinary(array $paths): string|null
    {
        $fallbackPath = null;
        $fallbackSapi = null;
        if ($openBasedir = \ini_get('open_basedir')) {
            $openBasedir = explode(\PATH_SEPARATOR, $openBasedir);
        }
        foreach ($paths as $path) {
            // we only test for is_executable if no open_basedir restrictions are set or the
            // target is within allowed paths. If the path is not within open_basedir we can
            // still execute the binary on the command line and check the version.
            if ((!$openBasedir || $this->isAllowed($path, $openBasedir)) && !is_executable($path)) {
                continue;
            }
            try {
                $info = $this->getServerInfo($path);
            } catch (RuntimeException) {
                continue;
            }
            if (!\is_array($info)) {
                continue;
            }
            if ('cli' === $info['sapi'] && version_compare(\PHP_VERSION, $info['version'], 'eq')) {
                return $path;
            }
            $vWeb = \PHP_MAJOR_VERSION . '.' . \PHP_MINOR_VERSION;
            $vCli = vsprintf('%s.%s', explode('.', (string) $info['version']));
            // Ignore binary if minor version does not match
            if (!version_compare($vWeb, $vCli, 'eq')) {
                continue;
            }
            // Allow fallback to another patch version of the same PHP major/minor and prefer
            // a CLI SAPI over e.g. a CGI SAPI.
            if (null === $fallbackPath || 'cli' !== $fallbackSapi && 'cli' === $info['sapi']) {
                $fallbackPath = $path;
                $fallbackSapi = $info['sapi'];
            }
        }
        return $fallbackPath;
    }
    /**
     * Tests if the given path is within any of the given directories.
     */
    private function isAllowed(string $path, array $dirs): bool
    {
        foreach ($dirs as $dir) {
            if (str_starts_with($path, (string) $dir)) {
                return \true;
            }
        }
        return \false;
    }
    /**
     * Adds the all binaries for given path to paths array.
     */
    private function includePath(array &$paths, string $path): void
    {
        foreach ($this->names as $name) {
            $paths[] = $path . \DIRECTORY_SEPARATOR . $name;
        }
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Contao Manager.
 *
 * (c) Contao Association
 *
 * @license LGPL-3.0-or-later
 */
namespace _ContaoManager\Contao\ManagerApi\Process;

use _ContaoManager\Contao\ManagerApi\ApiKernel;
use _ContaoManager\Contao\ManagerApi\Exception\ApiProblemException;
use _ContaoManager\Contao\ManagerApi\Exception\InvalidJsonException;
use _ContaoManager\Contao\ManagerApi\System\ServerInfo;
use _ContaoManager\Crell\ApiProblem\ApiProblem;
use _ContaoManager\Psr\Log\LoggerAwareInterface;
use _ContaoManager\Psr\Log\LoggerAwareTrait;
use _ContaoManager\Symfony\Component\DependencyInjection\Attribute\AutoconfigureTag;
use _ContaoManager\Symfony\Component\Filesystem\Filesystem;
use _ContaoManager\Symfony\Component\Process\Process;
/**
 * Creates foreground and background processes for the Contao or Manager console.
 */
#[AutoconfigureTag('monolog.logger', ['channel' => 'tasks'])]
class ConsoleProcessFactory implements LoggerAwareInterface
{
    use LoggerAwareTrait;
    public function __construct(private readonly ApiKernel $kernel, private readonly ServerInfo $serverInfo, private readonly Filesystem $filesystem)
    {
    }
    /**
     * Gets the path to manager console or Phar file.
     */
    public function getManagerConsolePath(): string
    {
        if ('' !== $phar = \Phar::running(\false)) {
            return $phar;
        }
        return $this->kernel->getRootDir() . '/console';
    }
    /**
     * Gets the path to the Contao console.
     */
    public function getContaoConsolePath(): string
    {
        $contaoPath = $this->kernel->getProjectDir() . '/vendor/contao/contao/manager-bundle/bin/contao-console';
        if ($this->kernel->isDebug() && $this->filesystem->exists($contaoPath)) {
            return $contaoPath;
        }
        return $this->kernel->getProjectDir() . '/vendor/contao/manager-bundle/bin/contao-console';
    }
    /**
     * Gets the path to the Contao API.
     */
    public function getContaoApiPath(): string
    {
        $contaoPath = $this->kernel->getProjectDir() . '/vendor/contao/contao/manager-bundle/bin/contao-api';
        if ($this->kernel->isDebug() && $this->filesystem->exists($contaoPath)) {
            return $contaoPath;
        }
        return $this->kernel->getProjectDir() . '/vendor/contao/manager-bundle/bin/contao-api';
    }
    /**
     * Creates a foreground process for the Manager console.
     */
    public function createManagerConsoleProcess(array $arguments): Process
    {
        array_unshift($arguments, $this->getManagerConsolePath());
        return $this->createForegroundProcess($arguments);
    }
    /**
     * Creates a background process for the Manager console.
     */
    public function createManagerConsoleBackgroundProcess(array $arguments, string|null $id = null): ProcessController
    {
        array_unshift($arguments, $this->getManagerConsolePath());
        return $this->createBackgroundProcess($arguments, $id);
    }
    /**
     * Creates a foreground process for the Contao console.
     */
    public function createContaoConsoleProcess(array $arguments): Process
    {
        array_unshift($arguments, $this->getContaoConsolePath());
        return $this->createForegroundProcess($arguments);
    }
    /**
     * Creates a background process for the Contao console.
     */
    public function createContaoConsoleBackgroundProcess(array $arguments, string|null $id = null): ProcessController
    {
        array_unshift($arguments, $this->getContaoConsolePath());
        return $this->createBackgroundProcess($arguments, $id);
    }
    /**
     * Creates a foreground process for the Contao API.
     */
    public function createContaoApiProcess(array $arguments): Process
    {
        array_unshift($arguments, $this->getContaoApiPath());
        return $this->createForegroundProcess($arguments);
    }
    /**
     * Restores the ProcessController for given task ID.
     *
     * @throws ApiProblemException
     */
    public function restoreBackgroundProcess(string $id): ProcessController
    {
        try {
            $process = ProcessController::restore($this->kernel->getConfigDir(), $id);
        } catch (InvalidJsonException $exception) {
            $problem = (new ApiProblem($exception->getMessage()))->setDetail($exception->getJsonErrorMessage() . "\n\n" . $exception->getContent());
            throw new ApiProblemException($problem, $exception);
        }
        $this->addForkers($process);
        return $process;
    }
    /**
     * Creates a foreground process.
     */
    private function createForegroundProcess(array $arguments): Process
    {
        return (new Utf8Process($this->addPhpRuntime($arguments), $this->kernel->getProjectDir(), $this->serverInfo->getPhpEnv()))->setTimeout(0);
    }
    /**
     * Creates a background process controller.
     */
    private function createBackgroundProcess(array $arguments, string|null $id = null): ProcessController
    {
        $process = ProcessController::create($this->kernel->getConfigDir(), $this->addPhpRuntime($arguments), $this->kernel->getProjectDir(), $id);
        $process->setTimeout(0);
        $this->addForkers($process);
        return $process;
    }
    /**
     * Adds forker instances to the process controller.
     */
    private function addForkers(ProcessController $process): void
    {
        $backgroundCommand = $this->addPhpRuntime([$this->getManagerConsolePath(), '--no-interaction', 'run']);
        foreach ($this->serverInfo->getProcessForkers() as $class) {
            $forker = new $class($backgroundCommand, $this->serverInfo->getPhpEnv(), $this->logger);
            $forker->setTimeout(5000);
            $process->addForker($forker);
        }
    }
    /**
     * Adds PHP runtime to console arguments.
     */
    private function addPhpRuntime(array $arguments): array
    {
        if (null === $phpCli = $this->serverInfo->getPhpExecutable()) {
            return $arguments;
        }
        $defaultArgs = [$phpCli, '-q'];
        if ($this->filesystem->exists($this->kernel->getConfigDir() . '/php.ini')) {
            $defaultArgs[] = '-c';
            $defaultArgs[] = $this->kernel->getConfigDir() . '/php.ini';
        }
        $defaultArgs[] = '-dmax_execution_time=0';
        $defaultArgs[] = '-dmemory_limit=-1';
        $defaultArgs[] = '-ddisplay_errors=0';
        $defaultArgs[] = '-ddisplay_startup_errors=0';
        $defaultArgs[] = '-derror_reporting=0';
        $defaultArgs[] = '-dallow_url_fopen=1';
        $defaultArgs[] = '-ddisable_functions=';
        $defaultArgs[] = '-ddate.timezone=' . @date_default_timezone_get();
        return array_merge($defaultArgs, $arguments);
    }
}
<?php

namespace _ContaoManager;

/*
 * This file is part of Contao Manager.
 *
 * Copyright (c) 2016-2017 Contao Association
 *
 * @license LGPL-3.0+
 */
\setlocale(\LC_ALL, 'C');
require __DIR__ . '/../vendor/autoload.php';
use Composer\Console\Application as ComposerApplication;
use Composer\Util\Platform;
use Composer\XdebugHandler\XdebugHandler;
use _ContaoManager\Contao\ManagerApi\ApiApplication;
use _ContaoManager\Contao\ManagerApi\ApiKernel;
use _ContaoManager\Symfony\Component\Console\Input\ArgvInput;
\error_reporting(-1);
\set_time_limit(0);
$xdebug = new XdebugHandler('ContaoManager');
$xdebug->check();
unset($xdebug);
if (\function_exists('ini_set')) {
    @\ini_set('display_errors', 1);
    @\ini_set('zlib.output_compression', 0);
    // Set user defined memory limit
    if ($memoryLimit = \getenv('COMPOSER_MEMORY_LIMIT')) {
        @\ini_set('memory_limit', $memoryLimit);
    } else {
        $memoryInBytes = static function ($value) {
            $unit = \strtolower(\substr($value, -1, 1));
            $value = (int) $value;
            switch ($unit) {
                /** @noinspection PhpMissingBreakStatementInspection */
                case 'g':
                    $value *= 1024;
                // no break (cumulative multiplier)
                /** @noinspection PhpMissingBreakStatementInspection */
                case 'm':
                    $value *= 1024;
                // no break (cumulative multiplier)
                case 'k':
                    $value *= 1024;
            }
            return $value;
        };
        $memoryLimit = \trim(\ini_get('memory_limit'));
        // Increase memory_limit if it is lower than 1.5GB
        if ($memoryLimit != -1 && $memoryInBytes($memoryLimit) < 1024 * 1024 * 1536) {
            @\ini_set('memory_limit', '1536M');
        }
        unset($memoryInBytes);
    }
    unset($memoryLimit);
}
// Workaround PHP bug on Windows where env vars containing Unicode chars are mangled in $_SERVER
// see https://github.com/php/php-src/issues/7896
if (\PHP_VERSION_ID >= 70113 && (\PHP_VERSION_ID < 80016 || \PHP_VERSION_ID >= 80100 && \PHP_VERSION_ID < 80103) && Platform::isWindows()) {
    foreach ($_SERVER as $serverVar => $serverVal) {
        if (($serverVal = \getenv($serverVar)) !== \false) {
            $_SERVER[$serverVar] = $serverVal;
        }
    }
}
Platform::putEnv('COMPOSER_BINARY', \realpath($_SERVER['argv'][0]));
// Always create kernel to initialize the application
$kernel = new ApiKernel('prod' === 'prod' ? 'prod' : 'dev');
$input = new ArgvInput();
switch ($input->getFirstArgument()) {
    // This "test" command is only for the dev version, if the Phar is compiled this is done in the stub.php
    case 'test':
        die(\json_encode(['version' => \PHP_VERSION, 'version_id' => \PHP_VERSION_ID, 'sapi' => \PHP_SAPI]));
    case 'composer':
        $application = new ComposerApplication();
        $argv = $_SERVER['argv'];
        \array_shift($argv);
        $input = new ArgvInput($argv);
        break;
    default:
        $application = new ApiApplication($kernel);
}
$application->run($input);
<?php

declare (strict_types=1);
/*
 * This file is part of Contao Manager.
 *
 * (c) Contao Association
 *
 * @license LGPL-3.0-or-later
 */
namespace _ContaoManager\Contao\ManagerApi\EventListener;

use _ContaoManager\Symfony\Component\DependencyInjection\Attribute\AsDecorator;
use _ContaoManager\Symfony\Component\EventDispatcher\EventSubscriberInterface;
use _ContaoManager\Symfony\Component\HttpKernel\Event\FinishRequestEvent;
use _ContaoManager\Symfony\Component\HttpKernel\Event\KernelEvent;
use _ContaoManager\Symfony\Component\HttpKernel\Event\RequestEvent;
use _ContaoManager\Symfony\Component\HttpKernel\EventListener\LocaleListener as BaseLocaleListener;
#[AsDecorator('locale_listener')]
class LocaleListener implements EventSubscriberInterface
{
    public function __construct(private readonly BaseLocaleListener $inner)
    {
    }
    public function setDefaultLocale(KernelEvent $event): void
    {
        $this->inner->setDefaultLocale($event);
    }
    public function onKernelRequest(RequestEvent $event): void
    {
        $this->inner->onKernelRequest($event);
        $request = $event->getRequest();
        if ($locale = $request->getPreferredLanguage()) {
            $request->setLocale($locale);
        }
    }
    public function onKernelFinishRequest(FinishRequestEvent $event): void
    {
        $this->inner->onKernelFinishRequest($event);
    }
    public static function getSubscribedEvents(): array
    {
        return BaseLocaleListener::getSubscribedEvents();
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Contao Manager.
 *
 * (c) Contao Association
 *
 * @license LGPL-3.0-or-later
 */
namespace _ContaoManager\Contao\ManagerApi\EventListener;

use _ContaoManager\Contao\ManagerApi\HttpKernel\ApiProblemResponse;
use _ContaoManager\Psr\Log\LoggerInterface;
use _ContaoManager\Symfony\Component\EventDispatcher\Attribute\AsEventListener;
use _ContaoManager\Symfony\Component\HttpFoundation\Response;
use _ContaoManager\Symfony\Component\HttpKernel\Event\ExceptionEvent;
use _ContaoManager\Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;
use _ContaoManager\Symfony\Component\HttpKernel\Exception\HttpExceptionInterface;
use _ContaoManager\Symfony\Component\Security\Core\Exception\AccessDeniedException;
use _ContaoManager\Symfony\Component\Security\Core\Exception\AuthenticationException;
#[AsEventListener(priority: 10)]
class ExceptionListener
{
    public function __construct(private readonly LoggerInterface $logger, private readonly bool $debug = \false)
    {
    }
    /**
     * Responds with application/problem+json on kernel.exception.
     */
    public function __invoke(ExceptionEvent $event): void
    {
        if (!\in_array('application/json', $event->getRequest()->getAcceptableContentTypes(), \true)) {
            return;
        }
        Response::closeOutputBuffers(0, \false);
        $exception = $this->convertException($event->getThrowable());
        $this->logException($exception);
        $response = ApiProblemResponse::createFromException($exception, $this->debug);
        $event->setResponse($response);
    }
    /**
     * Logs the exception if a logger is available.
     */
    private function logException(\Throwable $exception): void
    {
        $message = \sprintf('Uncaught PHP Exception %s: "%s" at %s line %s', $exception::class, $exception->getMessage(), $exception->getFile(), $exception->getLine());
        if (!$exception instanceof HttpExceptionInterface || $exception->getStatusCode() >= 500) {
            $this->logger->critical($message, ['exception' => $exception]);
        } else {
            $this->logger->error($message, ['exception' => $exception]);
        }
    }
    /**
     * Tries to convert known exceptions to a HttpException.
     */
    private function convertException(\Throwable $exception): \Throwable
    {
        return match (\true) {
            $exception instanceof AccessDeniedException, $exception instanceof AuthenticationException => new AccessDeniedHttpException($exception->getMessage(), $exception),
            default => $exception,
        };
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Contao Manager.
 *
 * (c) Contao Association
 *
 * @license LGPL-3.0-or-later
 */
namespace _ContaoManager\Contao\ManagerApi\EventListener;

use _ContaoManager\Contao\ManagerApi\Security\JwtAuthenticator;
use _ContaoManager\Contao\ManagerApi\Security\JwtManager;
use _ContaoManager\Symfony\Component\EventDispatcher\Attribute\AsEventListener;
use _ContaoManager\Symfony\Component\HttpKernel\Event\ResponseEvent;
use _ContaoManager\Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
use _ContaoManager\Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface;
#[AsEventListener]
class SecurityListener
{
    public function __construct(private readonly JwtManager $jwtManager, private readonly TokenStorageInterface $tokenStorage, private readonly AuthorizationCheckerInterface $authorizationChecker)
    {
    }
    /**
     * Adds and/or renews the JWT token on kernel.response event.
     */
    public function __invoke(ResponseEvent $event): void
    {
        if (!$event->isMainRequest() || $this->jwtManager->hasResponseToken($event->getResponse())) {
            return;
        }
        $token = $this->tokenStorage->getToken();
        if (null !== $token && $token->hasAttribute('authenticator') && JwtAuthenticator::class === $token->getAttribute('authenticator') && $this->authorizationChecker->isGranted('ROLE_USER')) {
            $this->jwtManager->addToken($event->getRequest(), $event->getResponse(), $token);
        } else {
            $this->jwtManager->removeToken($event->getRequest(), $event->getResponse());
        }
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Contao Manager.
 *
 * (c) Contao Association
 *
 * @license LGPL-3.0-or-later
 */
namespace _ContaoManager\Contao\ManagerApi\EventListener;

use _ContaoManager\Contao\ManagerApi\Security\TotpBadge;
use _ContaoManager\Contao\ManagerApi\Security\User;
use _ContaoManager\Symfony\Component\EventDispatcher\Attribute\AsEventListener;
use _ContaoManager\Symfony\Component\Security\Http\Event\CheckPassportEvent;
#[AsEventListener]
class CheckTotpListener
{
    public function __invoke(CheckPassportEvent $event): void
    {
        $passport = $event->getPassport();
        if (!$passport->hasBadge(TotpBadge::class)) {
            return;
        }
        /** @var TotpBadge $badge */
        $badge = $passport->getBadge(TotpBadge::class);
        $user = $passport->getUser();
        if ($badge->isResolved() || !$user instanceof User) {
            return;
        }
        $badge->verify($user);
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Contao Manager.
 *
 * (c) Contao Association
 *
 * @license LGPL-3.0-or-later
 */
namespace _ContaoManager\Contao\ManagerApi\EventListener;

use _ContaoManager\Symfony\Component\EventDispatcher\Attribute\AsEventListener;
use _ContaoManager\Symfony\Component\HttpKernel\Event\RequestEvent;
use _ContaoManager\Symfony\Component\HttpKernel\Exception\BadRequestHttpException;
use _ContaoManager\Symfony\Component\HttpKernel\Exception\UnsupportedMediaTypeHttpException;
// Priority must be lower than the router (defaults to 32)
#[AsEventListener(priority: 20)]
class JsonRequestListener
{
    /**
     * Disallow everything except JSON and convert data to request content.
     *
     * @throws UnsupportedMediaTypeHttpException
     * @throws BadRequestHttpException
     */
    public function __invoke(RequestEvent $event): void
    {
        $request = $event->getRequest();
        $content = $request->getContent();
        if ('' === $content && $request->attributes->get('form-data')) {
            return;
        }
        $data = [];
        if ('' !== $content) {
            if ('json' !== $request->getContentTypeFormat()) {
                throw new UnsupportedMediaTypeHttpException('Only JSON requests are supported.');
            }
            $data = json_decode($content, \true);
            if (!\is_array($data)) {
                throw new BadRequestHttpException('Invalid JSON data received.');
            }
        }
        $request->request->replace($data);
    }
}
<?php

namespace _ContaoManager;

/*
 * This file is part of Contao Manager.
 *
 * (c) Contao Association
 *
 * @license LGPL-3.0-or-later
 */
class ContaoManagerDowngrade
{
    public static function run()
    {
        if (isset($_SERVER['argv'][1]) && 'test' === $_SERVER['argv'][1]) {
            // Ignore test command to check different PHP binaries
            return;
        }
        if (('cli' === \PHP_SAPI || !isset($_SERVER['REQUEST_URI'])) && (!isset($_SERVER['argv'][1]) || 'downgrade' !== $_SERVER['argv'][1])) {
            echo 'You are using PHP ' . \phpversion() . " but you need at least PHP 8.1.0 to run the Contao Manager.\n";
            echo 'Run "' . $_SERVER['argv'][0] . " downgrade\" to downgrade to a PHP 7.2 compatible version.\n";
            exit;
        }
        $phar = \Phar::running(\false);
        $tempFile = $phar . '.downgrade';
        $url = 'https://download.contao.org/contao-manager/1.8/contao-manager.phar';
        $stream = @\fopen($url, 'rb', \false, StreamContextFactory::getContext($url));
        $failMsg = 'You are using PHP ' . \phpversion() . " which is not supported by this Contao Manager. Automatic downgrade to version 1.8 was not successful.\n";
        if (\false === $stream || \false === \file_put_contents($tempFile, $stream)) {
            die($failMsg);
        }
        if (\false === \rename($tempFile, $phar)) {
            // If rename fails, try to rename original script first
            if (\false === \rename($phar, $phar . '.old')) {
                die($failMsg);
            }
            if (\false === \rename($tempFile, $phar)) {
                @\rename($phar . '.old', $phar);
                die($failMsg);
            }
            @\unlink($phar . '.old');
        }
        if (\function_exists('opcache_reset')) {
            \opcache_reset();
        }
        $reload = '';
        if (!empty($_SERVER['REQUEST_URI'])) {
            $reload = '<script>setTimeout(function() { window.location.reload(true) }, 5000)</script>';
        }
        die("Contao Manager was downgraded to the latest version supported by your PHP version.\n{$reload}");
    }
}
/*
 * This file is part of Contao Manager.
 *
 * (c) Contao Association
 *
 * @license LGPL-3.0-or-later
 */
\class_alias('_ContaoManager\ContaoManagerDowngrade', 'ContaoManagerDowngrade', \false);
/**
 * @see Composer\Util\StreamContextFactory
 */
class StreamContextFactory
{
    /**
     * Creates a context supporting HTTP proxies
     *
     * @param  string            $url            URL the context is to be used for
     * @param  array             $defaultOptions Options to merge with the default
     * @param  array             $defaultParams  Parameters to specify on the context
     * @throws \RuntimeException if https proxy required and OpenSSL uninstalled
     * @return resource          Default context
     */
    public static function getContext($url, array $defaultOptions = array(), array $defaultParams = array())
    {
        $options = array('http' => array(
            // specify defaults again to try and work better with curlwrappers enabled
            'follow_location' => 1,
            'max_redirects' => 20,
        ));
        // Handle HTTP_PROXY/http_proxy on CLI only for security reasons
        if ((\PHP_SAPI === 'cli' || \PHP_SAPI === 'phpdbg') && (!empty($_SERVER['HTTP_PROXY']) || !empty($_SERVER['http_proxy']))) {
            $proxy = \parse_url(!empty($_SERVER['http_proxy']) ? $_SERVER['http_proxy'] : $_SERVER['HTTP_PROXY']);
        }
        // Prefer CGI_HTTP_PROXY if available
        if (!empty($_SERVER['CGI_HTTP_PROXY'])) {
            $proxy = \parse_url($_SERVER['CGI_HTTP_PROXY']);
        }
        // Override with HTTPS proxy if present and URL is https
        if (\preg_match('{^https://}i', $url) && (!empty($_SERVER['HTTPS_PROXY']) || !empty($_SERVER['https_proxy']))) {
            $proxy = \parse_url(!empty($_SERVER['https_proxy']) ? $_SERVER['https_proxy'] : $_SERVER['HTTPS_PROXY']);
        }
        // Remove proxy if URL matches no_proxy directive
        if ((!empty($_SERVER['NO_PROXY']) || !empty($_SERVER['no_proxy'])) && \parse_url($url, \PHP_URL_HOST)) {
            $pattern = new NoProxyPattern(!empty($_SERVER['no_proxy']) ? $_SERVER['no_proxy'] : $_SERVER['NO_PROXY']);
            if ($pattern->test($url)) {
                unset($proxy);
            }
        }
        if (!empty($proxy)) {
            $proxyURL = isset($proxy['scheme']) ? $proxy['scheme'] . '://' : '';
            $proxyURL .= isset($proxy['host']) ? $proxy['host'] : '';
            if (isset($proxy['port'])) {
                $proxyURL .= ":" . $proxy['port'];
            } elseif ('http://' === \substr($proxyURL, 0, 7)) {
                $proxyURL .= ":80";
            } elseif ('https://' === \substr($proxyURL, 0, 8)) {
                $proxyURL .= ":443";
            }
            // http(s):// is not supported in proxy
            $proxyURL = \str_replace(array('http://', 'https://'), array('tcp://', 'ssl://'), $proxyURL);
            if (0 === \strpos($proxyURL, 'ssl:') && !\extension_loaded('openssl')) {
                throw new \RuntimeException('You must enable the openssl extension to use a proxy over https');
            }
            $options['http']['proxy'] = $proxyURL;
            // enabled request_fulluri unless it is explicitly disabled
            switch (\parse_url($url, \PHP_URL_SCHEME)) {
                case 'http':
                    // default request_fulluri to true
                    $reqFullUriEnv = \getenv('HTTP_PROXY_REQUEST_FULLURI');
                    if ($reqFullUriEnv === \false || $reqFullUriEnv === '' || \strtolower($reqFullUriEnv) !== 'false' && (bool) $reqFullUriEnv) {
                        $options['http']['request_fulluri'] = \true;
                    }
                    break;
                case 'https':
                    // default request_fulluri to true
                    $reqFullUriEnv = \getenv('HTTPS_PROXY_REQUEST_FULLURI');
                    if ($reqFullUriEnv === \false || $reqFullUriEnv === '' || \strtolower($reqFullUriEnv) !== 'false' && (bool) $reqFullUriEnv) {
                        $options['http']['request_fulluri'] = \true;
                    }
                    break;
            }
            // add SNI opts for https URLs
            if ('https' === \parse_url($url, \PHP_URL_SCHEME)) {
                $options['ssl']['SNI_enabled'] = \true;
                if (\PHP_VERSION_ID < 50600) {
                    $options['ssl']['SNI_server_name'] = \parse_url($url, \PHP_URL_HOST);
                }
            }
            // handle proxy auth if present
            if (isset($proxy['user'])) {
                $auth = \rawurldecode($proxy['user']);
                if (isset($proxy['pass'])) {
                    $auth .= ':' . \rawurldecode($proxy['pass']);
                }
                $auth = \base64_encode($auth);
                // Preserve headers if already set in default options
                if (isset($defaultOptions['http']['header'])) {
                    if (\is_string($defaultOptions['http']['header'])) {
                        $defaultOptions['http']['header'] = array($defaultOptions['http']['header']);
                    }
                    $defaultOptions['http']['header'][] = "Proxy-Authorization: Basic {$auth}";
                } else {
                    $options['http']['header'] = array("Proxy-Authorization: Basic {$auth}");
                }
            }
        }
        $options = \array_replace_recursive($options, $defaultOptions);
        if (isset($options['http']['header'])) {
            $options['http']['header'] = self::fixHttpHeaderField($options['http']['header']);
        }
        if (\defined('HHVM_VERSION')) {
            $phpVersion = 'HHVM ' . \HHVM_VERSION;
        } else {
            $phpVersion = 'PHP ' . \PHP_MAJOR_VERSION . '.' . \PHP_MINOR_VERSION . '.' . \PHP_RELEASE_VERSION;
        }
        if (!isset($options['http']['header']) || \false === \stripos(\implode('', $options['http']['header']), 'user-agent')) {
            $options['http']['header'][] = \sprintf('User-Agent: Contao Manager/@package_version@ (%s; %s; %s%s)', \function_exists('php_uname') ? \php_uname('s') : 'Unknown', \function_exists('php_uname') ? \php_uname('r') : 'Unknown', $phpVersion, \getenv('CI') ? '; CI' : '');
        }
        return \stream_context_create($options, $defaultParams);
    }
    /**
     * A bug in PHP prevents the headers from correctly being sent when a content-type header is present and
     * NOT at the end of the array
     *
     * This method fixes the array by moving the content-type header to the end
     *
     * @link https://bugs.php.net/bug.php?id=61548
     * @param string|array $header
     * @return array
     */
    private static function fixHttpHeaderField($header)
    {
        if (!\is_array($header)) {
            $header = \explode("\r\n", $header);
        }
        \uasort($header, function ($el) {
            return \stripos($el, 'content-type') === 0 ? 1 : -1;
        });
        return $header;
    }
}
/**
 * @see Composer\Util\StreamContextFactory
 */
\class_alias('_ContaoManager\StreamContextFactory', 'StreamContextFactory', \false);
/**
 * @see Composer\Util\NoProxyPattern
 */
class NoProxyPattern
{
    /**
     * @var string[]
     */
    protected $rules = array();
    /**
     * @param string $pattern no_proxy pattern
     */
    public function __construct($pattern)
    {
        $this->rules = \preg_split("/[\\s,]+/", $pattern);
    }
    /**
     * Test a URL against the stored pattern.
     *
     * @param string $url
     *
     * @return bool true if the URL matches one of the rules.
     */
    public function test($url)
    {
        $host = \parse_url($url, \PHP_URL_HOST);
        $port = \parse_url($url, \PHP_URL_PORT);
        if (empty($port)) {
            switch (\parse_url($url, \PHP_URL_SCHEME)) {
                case 'http':
                    $port = 80;
                    break;
                case 'https':
                    $port = 443;
                    break;
            }
        }
        foreach ($this->rules as $rule) {
            if ($rule === '*') {
                return \true;
            }
            list($ruleHost) = \explode(':', $rule);
            list($base) = \explode('/', $ruleHost);
            if (\filter_var($base, \FILTER_VALIDATE_IP, \FILTER_FLAG_IPV4)) {
                // ip or cidr match
                if (!isset($ip)) {
                    $ip = \gethostbyname($host);
                }
                if (\strpos($ruleHost, '/') === \false) {
                    $match = $ip === $ruleHost;
                } else if ($ip === $host) {
                    $match = \false;
                } else {
                    // match resolved IP against the rule
                    $match = self::inCIDRBlock($ruleHost, $ip);
                }
            } else {
                // match end of domain
                $haystack = '.' . \trim($host, '.') . '.';
                $needle = '.' . \trim($ruleHost, '.') . '.';
                $match = \stripos(\strrev($haystack), \strrev($needle)) === 0;
            }
            // final port check
            if ($match && \strpos($rule, ':') !== \false) {
                list(, $rulePort) = \explode(':', $rule);
                if (!empty($rulePort) && $port != $rulePort) {
                    $match = \false;
                }
            }
            if ($match) {
                return \true;
            }
        }
        return \false;
    }
    /**
     * Check an IP address against a CIDR
     *
     * http://framework.zend.com/svn/framework/extras/incubator/library/ZendX/Whois/Adapter/Cidr.php
     *
     * @param string $cidr IPv4 block in CIDR notation
     * @param string $ip   IPv4 address
     *
     * @return bool
     */
    private static function inCIDRBlock($cidr, $ip)
    {
        // Get the base and the bits from the CIDR
        list($base, $bits) = \explode('/', $cidr);
        // Now split it up into it's classes
        list($a, $b, $c, $d) = \explode('.', $base);
        // Now do some bit shifting/switching to convert to ints
        $i = ($a << 24) + ($b << 16) + ($c << 8) + $d;
        $mask = $bits == 0 ? 0 : ~0 << 32 - $bits;
        // Here's our lowest int
        $low = $i & $mask;
        // Here's our highest int
        $high = $i | ~$mask & 0xffffffff;
        // Now split the ip we're checking against up into classes
        list($a, $b, $c, $d) = \explode('.', $ip);
        // Now convert the ip we're checking against to an int
        $check = ($a << 24) + ($b << 16) + ($c << 8) + $d;
        // If the ip is within the range, including highest/lowest values,
        // then it's within the CIDR range
        return $check >= $low && $check <= $high;
    }
}
/**
 * @see Composer\Util\NoProxyPattern
 */
\class_alias('_ContaoManager\NoProxyPattern', 'NoProxyPattern', \false);
if (\PHP_VERSION_ID < 80100) {
    ContaoManagerDowngrade::run();
}
{
    "_readme": [
        "This file locks the dependencies of your project to a known state",
        "Read more about it at http://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file",
        "This file is @generated automatically"
    ],
    "hash": "e5afe72073d9266712c8e1ddc1648513",
    "packages": [],
    "packages-dev": [],
    "aliases": [],
    "minimum-stability": "stable",
    "stability-flags": [],
    "prefer-stable": false,
    "prefer-lowest": false,
    "platform": {
        "php": ">=5.3"
    },
    "platform-dev": []
}
Copyright (c) 2015 Jordi Boggiano

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is furnished
to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
PHAR Utils
==========

PHAR file format utilities, for when PHP phars you up.

Installation
------------

`composer require seld/phar-utils`

API
---

### `Seld\PharUtils\Timestamps`

- `__construct($pharFile)`

  > Load a phar file in memory.

- `updateTimestamps($timestamp = null)`

  > Updates each file's unix timestamps in the PHAR so the PHAR signature
  > can be produced in a reproducible manner.

- `save($path, $signatureAlgo = '')`

  > Saves the updated phar file with an updated signature.
  > Algo must be one of `Phar::MD5`, `Phar::SHA1`, `Phar::SHA256`
  > or `Phar::SHA512`

### `Seld\PharUtils\Linter`

- `Linter::lint($pharFile)`

  > Lints all php files inside a given phar with the current PHP version.

Requirements
------------

PHP 5.3 and above

License
-------

PHAR Utils is licensed under the MIT License - see the LICENSE file for details
{
    "name": "seld\/phar-utils",
    "description": "PHAR file format utilities, for when PHP phars you up",
    "type": "library",
    "keywords": [
        "phar"
    ],
    "license": "MIT",
    "require": {
        "php": ">=5.3"
    },
    "authors": [
        {
            "name": "Jordi Boggiano",
            "email": "j.boggiano@seld.be"
        }
    ],
    "autoload": {
        "psr-4": {
            "_ContaoManager\\Seld\\PharUtils\\": "src\/"
        }
    },
    "extra": {
        "branch-alias": {
            "dev-master": "1.x-dev"
        }
    }
}<?php

/*
 * This file is part of PHAR Utils.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Seld\PharUtils;

class Linter
{
    /**
     * Lints all php files inside a given phar with the current PHP version
     *
     * @param string $path Phar file path
     * @param list<string> $excludedPaths Paths which should be skipped by the linter
     */
    public static function lint($path, array $excludedPaths = array())
    {
        $php = defined('PHP_BINARY') ? \PHP_BINARY : 'php';
        if ($isWindows = defined('PHP_WINDOWS_VERSION_BUILD')) {
            $tmpFile = @tempnam(sys_get_temp_dir(), '');
            if (!$tmpFile || !is_writable($tmpFile)) {
                throw new \RuntimeException('Unable to create temp file');
            }
            $php = self::escapeWindowsPath($php);
            $tmpFile = self::escapeWindowsPath($tmpFile);
            // PHP 8 encloses the command in double-quotes
            if (\PHP_VERSION_ID >= 80000) {
                $format = '%s -l %s';
            } else {
                $format = '"%s -l %s"';
            }
            $command = sprintf($format, $php, $tmpFile);
        } else {
            $command = "'" . $php . "' -l";
        }
        $descriptorspec = array(0 => array('pipe', 'r'), 1 => array('pipe', 'w'), 2 => array('pipe', 'w'));
        // path to phar + phar:// + trailing slash
        $baseLen = strlen(realpath($path)) + 7 + 1;
        foreach (new \RecursiveIteratorIterator(new \Phar($path)) as $file) {
            if ($file->isDir()) {
                continue;
            }
            if (substr($file, -4) === '.php') {
                $filename = (string) $file;
                if (in_array(substr($filename, $baseLen), $excludedPaths, \true)) {
                    continue;
                }
                if ($isWindows) {
                    file_put_contents($tmpFile, file_get_contents($filename));
                }
                $process = proc_open($command, $descriptorspec, $pipes);
                if (is_resource($process)) {
                    if (!$isWindows) {
                        fwrite($pipes[0], file_get_contents($filename));
                    }
                    fclose($pipes[0]);
                    $stdout = stream_get_contents($pipes[1]);
                    fclose($pipes[1]);
                    $stderr = stream_get_contents($pipes[2]);
                    fclose($pipes[2]);
                    $exitCode = proc_close($process);
                    if ($exitCode !== 0) {
                        if ($isWindows) {
                            $stderr = str_replace($tmpFile, $filename, $stderr);
                        }
                        throw new \UnexpectedValueException('Failed linting ' . $file . ': ' . $stderr);
                    }
                } else {
                    throw new \RuntimeException('Could not start linter process');
                }
            }
        }
        if ($isWindows) {
            @unlink($tmpFile);
        }
    }
    /**
     * Escapes a Windows file path
     *
     * @param string $path
     * @return string The escaped path
     */
    private static function escapeWindowsPath($path)
    {
        // Quote if path contains spaces or brackets
        if (strpbrk($path, " ()") !== \false) {
            $path = '"' . $path . '"';
        }
        return $path;
    }
}
<?php

/*
 * This file is part of PHAR Utils.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Seld\PharUtils;

class Timestamps
{
    private $contents;
    /**
     * @param string $file path to the phar file to use
     */
    public function __construct($file)
    {
        $this->contents = file_get_contents($file);
    }
    /**
     * Updates each file's unix timestamps in the PHAR
     *
     * The PHAR signature can then be produced in a reproducible manner.
     *
     * @param int|\DateTimeInterface|string $timestamp Date string or DateTime or unix timestamp to use
     */
    public function updateTimestamps($timestamp = null)
    {
        if ($timestamp instanceof \DateTime || $timestamp instanceof \DateTimeInterface) {
            $timestamp = $timestamp->getTimestamp();
        } elseif (is_string($timestamp)) {
            $timestamp = strtotime($timestamp);
        } elseif (!is_int($timestamp)) {
            $timestamp = strtotime('1984-12-24T00:00:00Z');
        }
        // detect manifest offset / end of stub
        if (!preg_match('{__HALT_COMPILER\(\);(?: +\?>)?\r?\n}', $this->contents, $match, \PREG_OFFSET_CAPTURE)) {
            throw new \RuntimeException('Could not detect the stub\'s end in the phar');
        }
        // set starting position and skip past manifest length
        $pos = $match[0][1] + strlen($match[0][0]);
        $stubEnd = $pos + $this->readUint($pos, 4);
        $pos += 4;
        $numFiles = $this->readUint($pos, 4);
        $pos += 4;
        // skip API version (YOLO)
        $pos += 2;
        // skip PHAR flags
        $pos += 4;
        $aliasLength = $this->readUint($pos, 4);
        $pos += 4 + $aliasLength;
        $metadataLength = $this->readUint($pos, 4);
        $pos += 4 + $metadataLength;
        while ($pos < $stubEnd) {
            $filenameLength = $this->readUint($pos, 4);
            $pos += 4 + $filenameLength;
            // skip filesize
            $pos += 4;
            // update timestamp to a fixed value
            $timeStampBytes = pack('L', $timestamp);
            $this->contents[$pos + 0] = $timeStampBytes[0];
            $this->contents[$pos + 1] = $timeStampBytes[1];
            $this->contents[$pos + 2] = $timeStampBytes[2];
            $this->contents[$pos + 3] = $timeStampBytes[3];
            // skip timestamp, compressed file size, crc32 checksum and file flags
            $pos += 4 * 4;
            $metadataLength = $this->readUint($pos, 4);
            $pos += 4 + $metadataLength;
            $numFiles--;
        }
        if ($numFiles !== 0) {
            throw new \LogicException('All files were not processed, something must have gone wrong');
        }
    }
    /**
     * Saves the updated phar file, optionally with an updated signature.
     *
     * @param  string $path
     * @param  int $signatureAlgo One of Phar::MD5, Phar::SHA1, Phar::SHA256 or Phar::SHA512
     * @return bool
     */
    public function save($path, $signatureAlgo)
    {
        $pos = $this->determineSignatureBegin();
        $algos = array(\Phar::MD5 => 'md5', \Phar::SHA1 => 'sha1', \Phar::SHA256 => 'sha256', \Phar::SHA512 => 'sha512');
        if (!isset($algos[$signatureAlgo])) {
            throw new \UnexpectedValueException('Invalid hash algorithm given: ' . $signatureAlgo . ' expected one of Phar::MD5, Phar::SHA1, Phar::SHA256 or Phar::SHA512');
        }
        $algo = $algos[$signatureAlgo];
        // re-sign phar
        //           signature
        $signature = hash($algo, substr($this->contents, 0, $pos), \true) . pack('L', $signatureAlgo) . 'GBMB';
        $this->contents = substr($this->contents, 0, $pos) . $signature;
        return file_put_contents($path, $this->contents);
    }
    private function readUint($pos, $bytes)
    {
        $res = unpack('V', substr($this->contents, $pos, $bytes));
        return $res[1];
    }
    /**
     * Determine the beginning of the signature.
     *
     * @return int
     */
    private function determineSignatureBegin()
    {
        // detect signature position
        if (!preg_match('{__HALT_COMPILER\(\);(?: +\?>)?\r?\n}', $this->contents, $match, \PREG_OFFSET_CAPTURE)) {
            throw new \RuntimeException('Could not detect the stub\'s end in the phar');
        }
        // set starting position and skip past manifest length
        $pos = $match[0][1] + strlen($match[0][0]);
        $manifestEnd = $pos + 4 + $this->readUint($pos, 4);
        $pos += 4;
        $numFiles = $this->readUint($pos, 4);
        $pos += 4;
        // skip API version (YOLO)
        $pos += 2;
        // skip PHAR flags
        $pos += 4;
        $aliasLength = $this->readUint($pos, 4);
        $pos += 4 + $aliasLength;
        $metadataLength = $this->readUint($pos, 4);
        $pos += 4 + $metadataLength;
        $compressedSizes = 0;
        while ($numFiles > 0 && $pos < $manifestEnd - 24) {
            $filenameLength = $this->readUint($pos, 4);
            $pos += 4 + $filenameLength;
            // skip filesize and timestamp
            $pos += 2 * 4;
            $compressedSizes += $this->readUint($pos, 4);
            // skip compressed file size, crc32 checksum and file flags
            $pos += 3 * 4;
            $metadataLength = $this->readUint($pos, 4);
            $pos += 4 + $metadataLength;
            $numFiles--;
        }
        if ($numFiles !== 0) {
            throw new \LogicException('All files were not processed, something must have gone wrong');
        }
        return $manifestEnd + $compressedSizes;
    }
}
Copyright (c) 2011 Jordi Boggiano

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is furnished
to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
#!/usr/bin/env php
<?php 
namespace _ContaoManager;

/*
 * This file is part of the JSON Lint package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
function includeIfExists($file)
{
    if (\file_exists($file)) {
        return include $file;
    }
}
if (!includeIfExists(__DIR__ . '/../vendor/autoload.php') && !includeIfExists(__DIR__ . '/../../../autoload.php')) {
    $msg = 'You must set up the project dependencies, run the following commands:' . \PHP_EOL . 'curl -sS https://getcomposer.org/installer | php' . \PHP_EOL . 'php composer.phar install' . \PHP_EOL;
    \fwrite(\STDERR, $msg);
    exit(1);
}
use _ContaoManager\Seld\JsonLint\JsonParser;
$files = array();
$quiet = \false;
if (isset($_SERVER['argc']) && $_SERVER['argc'] > 1) {
    for ($i = 1; $i < $_SERVER['argc']; $i++) {
        $arg = $_SERVER['argv'][$i];
        if ($arg == '-q' || $arg == '--quiet') {
            $quiet = \true;
        } else if ($arg == '-h' || $arg == '--help') {
            showUsage($_SERVER['argv'][0]);
        } else {
            $files[] = $arg;
        }
    }
}
if (!empty($files)) {
    // file linting
    $exitCode = 0;
    foreach ($files as $file) {
        $result = lintFile($file, $quiet);
        if ($result === \false) {
            $exitCode = 1;
        }
    }
    exit($exitCode);
} else if ($contents = \file_get_contents('php://stdin')) {
    lint($contents, $quiet);
} else {
    \fwrite(\STDERR, 'No file name or json input given' . \PHP_EOL);
    exit(1);
}
// stdin lint function
function lint($content, $quiet = \false)
{
    $parser = new JsonParser();
    if ($err = $parser->lint($content)) {
        \fwrite(\STDERR, $err->getMessage() . ' (stdin)' . \PHP_EOL);
        exit(1);
    }
    if (!$quiet) {
        echo 'Valid JSON (stdin)' . \PHP_EOL;
        exit(0);
    }
}
// file lint function
function lintFile($file, $quiet = \false)
{
    if (!\preg_match('{^https?://}i', $file)) {
        if (!\file_exists($file)) {
            \fwrite(\STDERR, 'File not found: ' . $file . \PHP_EOL);
            return \false;
        }
        if (!\is_readable($file)) {
            \fwrite(\STDERR, 'File not readable: ' . $file . \PHP_EOL);
            return \false;
        }
    }
    $content = \file_get_contents($file);
    $parser = new JsonParser();
    if ($err = $parser->lint($content)) {
        \fwrite(\STDERR, $file . ': ' . $err->getMessage() . \PHP_EOL);
        return \false;
    }
    if (!$quiet) {
        echo 'Valid JSON (' . $file . ')' . \PHP_EOL;
    }
    return \true;
}
// usage text function
function showUsage($programPath)
{
    echo 'Usage: ' . $programPath . ' file [options]' . \PHP_EOL;
    echo \PHP_EOL;
    echo 'Options:' . \PHP_EOL;
    echo '  -q, --quiet     Cause jsonlint to be quiet when no errors are found' . \PHP_EOL;
    echo '  -h, --help      Show this message' . \PHP_EOL;
    exit(0);
}
You can find newer changelog entries in [GitHub releases](https://github.com/Seldaek/jsonlint/releases)

### 1.10.0 (2023-05-11)

  * Added ALLOW_COMMENTS flag to parse while allowing (and ignoring) inline `//` and multiline `/* */` comments in the JSON document (#81)

### 1.9.0 (2022-04-01)

  * Internal cleanups and type fixes

### 1.8.1 (2020-08-13)

  * Added type annotations

### 1.8.0 (2020-04-30)

  * Improved lexer performance
  * Added (tentative) support for PHP 8
  * Fixed wording of error reporting for invalid strings when the error happened after the 20th character

### 1.7.2 (2019-10-24)

  * Fixed issue decoding some unicode escaped characters (for " and ')

### 1.7.1 (2018-01-24)

  * Fixed PHP 5.3 compatibility in bin/jsonlint

### 1.7.0 (2018-01-03)

  * Added ability to lint multiple files at once using the jsonlint binary

### 1.6.2 (2017-11-30)

  * No meaningful public changes

### 1.6.1 (2017-06-18)

  * Fixed parsing of `0` as invalid

### 1.6.0 (2017-03-06)

  * Added $flags arg to JsonParser::lint() to take the same flag as parse() did
  * Fixed backtracking performance issues on long strings with a lot of escaped characters

### 1.5.0 (2016-11-14)

  * Added support for PHP 7.1 (which converts `{"":""}` to an object property called `""` and not `"_empty_"` like 7.0 and below).

### 1.4.0 (2015-11-21)

  * Added a DuplicateKeyException allowing for more specific error detection and handling

### 1.3.1 (2015-01-04)

  * Fixed segfault when parsing large JSON strings

### 1.3.0 (2014-09-05)

  * Added parsing to an associative array via JsonParser::PARSE_TO_ASSOC
  * Fixed a warning when rendering parse errors on empty lines

### 1.2.0 (2014-07-20)

  * Added support for linting multiple files at once in bin/jsonlint
  * Added a -q/--quiet flag to suppress the output
  * Fixed error output being on STDOUT instead of STDERR
  * Fixed parameter parsing

### 1.1.2 (2013-11-04)

  * Fixed handling of Unicode BOMs to give a better failure hint

### 1.1.1 (2013-02-12)

  * Fixed handling of empty keys in objects in certain cases

### 1.1.0 (2012-12-13)

  * Added optional parsing of duplicate keys into key.2, key.3, etc via JsonParser::ALLOW_DUPLICATE_KEYS
  * Improved error reporting for common mistakes

### 1.0.1 (2012-04-03)

  * Added optional detection and error reporting for duplicate keys via JsonParser::DETECT_KEY_CONFLICTS
  * Added ability to pipe content through stdin into bin/jsonlint

### 1.0.0 (2012-03-12)

  * Initial release
JSON Lint
=========

[![Build Status](https://github.com/Seldaek/jsonlint/actions/workflows/continuous-integration.yml/badge.svg)](https://github.com/Seldaek/jsonlint/actions/workflows/continuous-integration.yml)

Usage
-----

```php
use Seld\JsonLint\JsonParser;

$parser = new JsonParser();

// returns null if it's valid json, or a ParsingException object.
$parser->lint($json);

// Call getMessage() on the exception object to get
// a well formatted error message error like this

// Parse error on line 2:
// ... "key": "value"    "numbers": [1, 2, 3]
// ----------------------^
// Expected one of: 'EOF', '}', ':', ',', ']'

// Call getDetails() on the exception to get more info.

// returns parsed json, like json_decode() does, but slower, throws
// exceptions on failure.
$parser->parse($json);
```

You can also pass additional flags to `JsonParser::lint/parse` that tweak the functionality:

- `JsonParser::DETECT_KEY_CONFLICTS` throws an exception on duplicate keys.
- `JsonParser::ALLOW_DUPLICATE_KEYS` collects duplicate keys. e.g. if you have two `foo` keys they will end up as `foo` and `foo.2`.
- `JsonParser::PARSE_TO_ASSOC` parses to associative arrays instead of stdClass objects.
- `JsonParser::ALLOW_COMMENTS` parses while allowing (and ignoring) inline `//` and multiline `/* */` comments in the JSON document.
- `JsonParser::ALLOW_DUPLICATE_KEYS_TO_ARRAY` collects duplicate keys. e.g. if you have two `foo` keys the `foo` key will become an object (or array in assoc mode) with all `foo` values accessible as an array in `$result->foo->__duplicates__` (or `$result['foo']['__duplicates__']` in assoc mode).

Example:

```php
$parser = new JsonParser;
try {
    $parser->parse(file_get_contents($jsonFile), JsonParser::DETECT_KEY_CONFLICTS);
} catch (DuplicateKeyException $e) {
    $details = $e->getDetails();
    echo 'Key '.$details['key'].' is a duplicate in '.$jsonFile.' at line '.$details['line'];
}
```

> **Note:** This library is meant to parse JSON while providing good error messages on failure. There is no way it can be as fast as php native `json_decode()`.
>
> It is recommended to parse with `json_decode`, and when it fails parse again with seld/jsonlint to get a proper error message back to the user. See for example [how Composer uses this library](https://github.com/composer/composer/blob/56edd53046fd697d32b2fd2fbaf45af5d7951671/src/Composer/Json/JsonFile.php#L283-L318):


Installation
------------

For a quick install with Composer use:

```bash
composer require seld/jsonlint
```

JSON Lint can easily be used within another app if you have a
[PSR-4](https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-4-autoloader.md)
autoloader, or it can be installed through [Composer](https://getcomposer.org/)
for use as a CLI util.
Once installed via Composer you can run the following command to lint a json file or URL:

    $ bin/jsonlint file.json

Requirements
------------

- PHP 5.3+
- [optional] PHPUnit 3.5+ to execute the test suite (phpunit --version)

Submitting bugs and feature requests
------------------------------------

Bugs and feature request are tracked on [GitHub](https://github.com/Seldaek/jsonlint/issues)

Author
------

Jordi Boggiano - <j.boggiano@seld.be> - <http://twitter.com/seldaek>

License
-------

JSON Lint is licensed under the MIT License - see the LICENSE file for details

Acknowledgements
----------------

This library is a port of the JavaScript [jsonlint](https://github.com/zaach/jsonlint) library.
{
    "name": "seld\/jsonlint",
    "description": "JSON Linter",
    "keywords": [
        "json",
        "parser",
        "linter",
        "validator"
    ],
    "type": "library",
    "license": "MIT",
    "authors": [
        {
            "name": "Jordi Boggiano",
            "email": "j.boggiano@seld.be",
            "homepage": "https:\/\/seld.be"
        }
    ],
    "require": {
        "php": "^5.3 || ^7.0 || ^8.0"
    },
    "require-dev": {
        "phpunit\/phpunit": "^4.8.35 || ^5.7 || ^6.0 || ^8.5.13",
        "phpstan\/phpstan": "^1.11"
    },
    "autoload": {
        "psr-4": {
            "_ContaoManager\\Seld\\JsonLint\\": "src\/Seld\/JsonLint\/"
        }
    },
    "bin": [
        "bin\/jsonlint"
    ],
    "scripts": {
        "test": "vendor\/bin\/phpunit",
        "phpstan": "vendor\/bin\/phpstan analyse"
    }
}<?php

/*
 * This file is part of the JSON Lint package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Seld\JsonLint;

class DuplicateKeyException extends ParsingException
{
    /**
     * @var array{key: string, line: int}
     */
    protected $details;
    /**
     * @param string $message
     * @param string $key
     * @phpstan-param array{line: int} $details
     */
    public function __construct($message, $key, array $details)
    {
        $details['key'] = $key;
        parent::__construct($message, $details);
    }
    /**
     * @return string
     */
    public function getKey()
    {
        return $this->details['key'];
    }
    /**
     * @phpstan-return array{key: string, line: int}
     */
    public function getDetails()
    {
        return $this->details;
    }
}
<?php

/*
 * This file is part of the JSON Lint package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Seld\JsonLint;

class ParsingException extends \Exception
{
    /**
     * @var array{text?: string, token?: string|int, line?: int, loc?: array{first_line: int, first_column: int, last_line: int, last_column: int}, expected?: string[]}
     */
    protected $details;
    /**
     * @param string $message
     * @phpstan-param array{text?: string, token?: string|int, line?: int, loc?: array{first_line: int, first_column: int, last_line: int, last_column: int}, expected?: string[]} $details
     */
    public function __construct($message, $details = array())
    {
        $this->details = $details;
        parent::__construct($message);
    }
    /**
     * @phpstan-return array{text?: string, token?: string|int, line?: int, loc?: array{first_line: int, first_column: int, last_line: int, last_column: int}, expected?: string[]}
     */
    public function getDetails()
    {
        return $this->details;
    }
}
<?php

/*
 * This file is part of the JSON Lint package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Seld\JsonLint;

/**
 * Lexer class
 *
 * Ported from https://github.com/zaach/jsonlint
 */
class Lexer
{
    /** @internal */
    const EOF = 1;
    /** @internal */
    const T_INVALID = -1;
    const T_SKIP_WHITESPACE = 0;
    const T_ERROR = 2;
    /** @internal */
    const T_BREAK_LINE = 3;
    /** @internal */
    const T_COMMENT = 30;
    /** @internal */
    const T_OPEN_COMMENT = 31;
    /** @internal */
    const T_CLOSE_COMMENT = 32;
    /**
     * @phpstan-var array<int<0,17>, string>
     * @const
     */
    private $rules = array(0 => '/\G\s*\n\r?/', 1 => '/\G\s+/', 2 => '/\G-?([0-9]|[1-9][0-9]+)(\.[0-9]+)?([eE][+-]?[0-9]+)?\b/', 3 => '{\G"(?>\\\\["bfnrt/\\\\]|\\\\u[a-fA-F0-9]{4}|[^\0-\x1f\\\\"]++)*+"}', 4 => '/\G\{/', 5 => '/\G\}/', 6 => '/\G\[/', 7 => '/\G\]/', 8 => '/\G,/', 9 => '/\G:/', 10 => '/\Gtrue\b/', 11 => '/\Gfalse\b/', 12 => '/\Gnull\b/', 13 => '/\G$/', 14 => '/\G\/\//', 15 => '/\G\/\*/', 16 => '/\G\*\//', 17 => '/\G./');
    /** @var string */
    private $input;
    /** @var bool */
    private $more;
    /** @var bool */
    private $done;
    /** @var 0|positive-int */
    private $offset;
    /** @var int */
    private $flags;
    /** @var string */
    public $match;
    /** @var 0|positive-int */
    public $yylineno;
    /** @var 0|positive-int */
    public $yyleng;
    /** @var string */
    public $yytext;
    /** @var array{first_line: 0|positive-int, first_column: 0|positive-int, last_line: 0|positive-int, last_column: 0|positive-int} */
    public $yylloc;
    /**
     * @param int $flags
     */
    public function __construct($flags = 0)
    {
        $this->flags = $flags;
    }
    /**
     * @return 0|1|4|6|8|10|11|14|17|18|21|22|23|24|30|-1
     */
    public function lex()
    {
        while (\true) {
            $symbol = $this->next();
            switch ($symbol) {
                case self::T_SKIP_WHITESPACE:
                case self::T_BREAK_LINE:
                    break;
                case self::T_COMMENT:
                case self::T_OPEN_COMMENT:
                    if (!($this->flags & JsonParser::ALLOW_COMMENTS)) {
                        $this->parseError('Lexical error on line ' . ($this->yylineno + 1) . ". Comments are not allowed.\n" . $this->showPosition());
                    }
                    $this->skipUntil($symbol === self::T_COMMENT ? self::T_BREAK_LINE : self::T_CLOSE_COMMENT);
                    if ($this->done) {
                        // last symbol '/\G$/' before EOF
                        return 14;
                    }
                    break;
                case self::T_CLOSE_COMMENT:
                    $this->parseError('Lexical error on line ' . ($this->yylineno + 1) . ". Unexpected token.\n" . $this->showPosition());
                default:
                    return $symbol;
            }
        }
    }
    /**
     * @param string $input
     * @return $this
     */
    public function setInput($input)
    {
        $this->input = $input;
        $this->more = \false;
        $this->done = \false;
        $this->offset = 0;
        $this->yylineno = $this->yyleng = 0;
        $this->yytext = $this->match = '';
        $this->yylloc = array('first_line' => 1, 'first_column' => 0, 'last_line' => 1, 'last_column' => 0);
        return $this;
    }
    /**
     * @return string
     */
    public function showPosition()
    {
        if ($this->yylineno === 0 && $this->offset === 1 && $this->match !== '{') {
            return $this->match . '...' . "\n^";
        }
        $pre = str_replace("\n", '', $this->getPastInput());
        $c = str_repeat('-', max(0, \strlen($pre) - 1));
        // new Array(pre.length + 1).join("-");
        return $pre . str_replace("\n", '', $this->getUpcomingInput()) . "\n" . $c . "^";
    }
    /**
     * @return string
     */
    public function getPastInput()
    {
        $pastLength = $this->offset - \strlen($this->match);
        return ($pastLength > 20 ? '...' : '') . substr($this->input, max(0, $pastLength - 20), min(20, $pastLength));
    }
    /**
     * @return string
     */
    public function getUpcomingInput()
    {
        $next = $this->match;
        if (\strlen($next) < 20) {
            $next .= substr($this->input, $this->offset, 20 - \strlen($next));
        }
        return substr($next, 0, 20) . (\strlen($next) > 20 ? '...' : '');
    }
    /**
     * @return string
     */
    public function getFullUpcomingInput()
    {
        $next = $this->match;
        if (substr($next, 0, 1) === '"' && substr_count($next, '"') === 1) {
            $len = \strlen($this->input);
            if ($len === $this->offset) {
                $strEnd = $len;
            } else {
                $strEnd = min(strpos($this->input, '"', $this->offset + 1) ?: $len, strpos($this->input, "\n", $this->offset + 1) ?: $len);
            }
            $next .= substr($this->input, $this->offset, $strEnd - $this->offset);
        } elseif (\strlen($next) < 20) {
            $next .= substr($this->input, $this->offset, 20 - \strlen($next));
        }
        return $next;
    }
    /**
     * @param string $str
     * @return never
     */
    protected function parseError($str)
    {
        throw new ParsingException($str);
    }
    /**
     * @param int $token
     * @return void
     */
    private function skipUntil($token)
    {
        $symbol = $this->next();
        while ($symbol !== $token && \false === $this->done) {
            $symbol = $this->next();
        }
    }
    /**
     * @return 0|1|3|4|6|8|10|11|14|17|18|21|22|23|24|30|31|32|-1
     */
    private function next()
    {
        if ($this->done) {
            return self::EOF;
        }
        if ($this->offset === \strlen($this->input)) {
            $this->done = \true;
        }
        $token = null;
        $match = null;
        $col = null;
        $lines = null;
        if (!$this->more) {
            $this->yytext = '';
            $this->match = '';
        }
        $rulesLen = count($this->rules);
        for ($i = 0; $i < $rulesLen; $i++) {
            if (preg_match($this->rules[$i], $this->input, $match, 0, $this->offset)) {
                $lines = explode("\n", $match[0]);
                array_shift($lines);
                $lineCount = \count($lines);
                $this->yylineno += $lineCount;
                $this->yylloc = array('first_line' => $this->yylloc['last_line'], 'last_line' => $this->yylineno + 1, 'first_column' => $this->yylloc['last_column'], 'last_column' => $lineCount > 0 ? \strlen($lines[$lineCount - 1]) : $this->yylloc['last_column'] + \strlen($match[0]));
                $this->yytext .= $match[0];
                $this->match .= $match[0];
                $this->yyleng = \strlen($this->yytext);
                $this->more = \false;
                $this->offset += \strlen($match[0]);
                return $this->performAction($i);
            }
        }
        if ($this->offset === \strlen($this->input)) {
            return self::EOF;
        }
        $this->parseError('Lexical error on line ' . ($this->yylineno + 1) . ". Unrecognized text.\n" . $this->showPosition());
    }
    /**
     * @param  int $rule
     * @return 0|3|4|6|8|10|11|14|17|18|21|22|23|24|30|31|32|-1
     */
    private function performAction($rule)
    {
        switch ($rule) {
            case 0:
                /* skip break line */
                return self::T_BREAK_LINE;
            case 1:
                /* skip whitespace */
                return self::T_SKIP_WHITESPACE;
            case 2:
                return 6;
            case 3:
                $this->yytext = substr($this->yytext, 1, $this->yyleng - 2);
                return 4;
            case 4:
                return 17;
            case 5:
                return 18;
            case 6:
                return 23;
            case 7:
                return 24;
            case 8:
                return 22;
            case 9:
                return 21;
            case 10:
                return 10;
            case 11:
                return 11;
            case 12:
                return 8;
            case 13:
                return 14;
            case 14:
                return self::T_COMMENT;
            case 15:
                return self::T_OPEN_COMMENT;
            case 16:
                return self::T_CLOSE_COMMENT;
            case 17:
                return self::T_INVALID;
            default:
                throw new \LogicException('Unsupported rule ' . $rule);
        }
    }
}
<?php

/*
 * This file is part of the JSON Lint package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Seld\JsonLint;

class Undefined
{
}
<?php

/*
 * This file is part of the JSON Lint package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Seld\JsonLint;

use stdClass;
/**
 * Parser class
 *
 * Example:
 *
 * $parser = new JsonParser();
 * // returns null if it's valid json, or an error object
 * $parser->lint($json);
 * // returns parsed json, like json_decode does, but slower, throws exceptions on failure.
 * $parser->parse($json);
 *
 * Ported from https://github.com/zaach/jsonlint
 */
class JsonParser
{
    const DETECT_KEY_CONFLICTS = 1;
    const ALLOW_DUPLICATE_KEYS = 2;
    const PARSE_TO_ASSOC = 4;
    const ALLOW_COMMENTS = 8;
    const ALLOW_DUPLICATE_KEYS_TO_ARRAY = 16;
    /** @var Lexer */
    private $lexer;
    /**
     * @var int
     * @phpstan-var int-mask-of<self::*>
     */
    private $flags;
    /** @var list<int> */
    private $stack;
    /** @var list<stdClass|array<mixed>|int|bool|float|string|null> */
    private $vstack;
    // semantic value stack
    /** @var list<array{first_line: int, first_column: int, last_line: int, last_column: int}> */
    private $lstack;
    // location stack
    /**
     * @phpstan-var array<string, int>
     */
    private $symbols = array('error' => 2, 'JSONString' => 3, 'STRING' => 4, 'JSONNumber' => 5, 'NUMBER' => 6, 'JSONNullLiteral' => 7, 'NULL' => 8, 'JSONBooleanLiteral' => 9, 'TRUE' => 10, 'FALSE' => 11, 'JSONText' => 12, 'JSONValue' => 13, 'EOF' => 14, 'JSONObject' => 15, 'JSONArray' => 16, '{' => 17, '}' => 18, 'JSONMemberList' => 19, 'JSONMember' => 20, ':' => 21, ',' => 22, '[' => 23, ']' => 24, 'JSONElementList' => 25, '$accept' => 0, '$end' => 1);
    /**
     * @phpstan-var array<int, string>
     * @const
     */
    private $terminals_ = array(2 => "error", 4 => "STRING", 6 => "NUMBER", 8 => "NULL", 10 => "TRUE", 11 => "FALSE", 14 => "EOF", 17 => "{", 18 => "}", 21 => ":", 22 => ",", 23 => "[", 24 => "]");
    /**
     * @phpstan-var array<int<1,21>, array{int, int}>
     * @const
     */
    private $productions_ = array(1 => array(3, 1), 2 => array(5, 1), 3 => array(7, 1), 4 => array(9, 1), 5 => array(9, 1), 6 => array(12, 2), 7 => array(13, 1), 8 => array(13, 1), 9 => array(13, 1), 10 => array(13, 1), 11 => array(13, 1), 12 => array(13, 1), 13 => array(15, 2), 14 => array(15, 3), 15 => array(20, 3), 16 => array(19, 1), 17 => array(19, 3), 18 => array(16, 2), 19 => array(16, 3), 20 => array(25, 1), 21 => array(25, 3));
    /**
     * @var array<int<0, 31>, array<int, array<int>|int>> List of stateID=>symbolID=>actionIDs|actionID
     * @const
     */
    private $table = array(0 => array(3 => 5, 4 => array(1, 12), 5 => 6, 6 => array(1, 13), 7 => 3, 8 => array(1, 9), 9 => 4, 10 => array(1, 10), 11 => array(1, 11), 12 => 1, 13 => 2, 15 => 7, 16 => 8, 17 => array(1, 14), 23 => array(1, 15)), 1 => array(1 => array(3)), 2 => array(14 => array(1, 16)), 3 => array(14 => array(2, 7), 18 => array(2, 7), 22 => array(2, 7), 24 => array(2, 7)), 4 => array(14 => array(2, 8), 18 => array(2, 8), 22 => array(2, 8), 24 => array(2, 8)), 5 => array(14 => array(2, 9), 18 => array(2, 9), 22 => array(2, 9), 24 => array(2, 9)), 6 => array(14 => array(2, 10), 18 => array(2, 10), 22 => array(2, 10), 24 => array(2, 10)), 7 => array(14 => array(2, 11), 18 => array(2, 11), 22 => array(2, 11), 24 => array(2, 11)), 8 => array(14 => array(2, 12), 18 => array(2, 12), 22 => array(2, 12), 24 => array(2, 12)), 9 => array(14 => array(2, 3), 18 => array(2, 3), 22 => array(2, 3), 24 => array(2, 3)), 10 => array(14 => array(2, 4), 18 => array(2, 4), 22 => array(2, 4), 24 => array(2, 4)), 11 => array(14 => array(2, 5), 18 => array(2, 5), 22 => array(2, 5), 24 => array(2, 5)), 12 => array(14 => array(2, 1), 18 => array(2, 1), 21 => array(2, 1), 22 => array(2, 1), 24 => array(2, 1)), 13 => array(14 => array(2, 2), 18 => array(2, 2), 22 => array(2, 2), 24 => array(2, 2)), 14 => array(3 => 20, 4 => array(1, 12), 18 => array(1, 17), 19 => 18, 20 => 19), 15 => array(3 => 5, 4 => array(1, 12), 5 => 6, 6 => array(1, 13), 7 => 3, 8 => array(1, 9), 9 => 4, 10 => array(1, 10), 11 => array(1, 11), 13 => 23, 15 => 7, 16 => 8, 17 => array(1, 14), 23 => array(1, 15), 24 => array(1, 21), 25 => 22), 16 => array(1 => array(2, 6)), 17 => array(14 => array(2, 13), 18 => array(2, 13), 22 => array(2, 13), 24 => array(2, 13)), 18 => array(18 => array(1, 24), 22 => array(1, 25)), 19 => array(18 => array(2, 16), 22 => array(2, 16)), 20 => array(21 => array(1, 26)), 21 => array(14 => array(2, 18), 18 => array(2, 18), 22 => array(2, 18), 24 => array(2, 18)), 22 => array(22 => array(1, 28), 24 => array(1, 27)), 23 => array(22 => array(2, 20), 24 => array(2, 20)), 24 => array(14 => array(2, 14), 18 => array(2, 14), 22 => array(2, 14), 24 => array(2, 14)), 25 => array(3 => 20, 4 => array(1, 12), 20 => 29), 26 => array(3 => 5, 4 => array(1, 12), 5 => 6, 6 => array(1, 13), 7 => 3, 8 => array(1, 9), 9 => 4, 10 => array(1, 10), 11 => array(1, 11), 13 => 30, 15 => 7, 16 => 8, 17 => array(1, 14), 23 => array(1, 15)), 27 => array(14 => array(2, 19), 18 => array(2, 19), 22 => array(2, 19), 24 => array(2, 19)), 28 => array(3 => 5, 4 => array(1, 12), 5 => 6, 6 => array(1, 13), 7 => 3, 8 => array(1, 9), 9 => 4, 10 => array(1, 10), 11 => array(1, 11), 13 => 31, 15 => 7, 16 => 8, 17 => array(1, 14), 23 => array(1, 15)), 29 => array(18 => array(2, 17), 22 => array(2, 17)), 30 => array(18 => array(2, 15), 22 => array(2, 15)), 31 => array(22 => array(2, 21), 24 => array(2, 21)));
    /**
     * @var array{16: array{2, 6}}
     * @const
     */
    private $defaultActions = array(16 => array(2, 6));
    /**
     * @param  string                $input JSON string
     * @param  int                   $flags Bitmask of parse/lint options (see constants of this class)
     * @return null|ParsingException null if no error is found, a ParsingException containing all details otherwise
     *
     * @phpstan-param int-mask-of<self::*> $flags
     */
    public function lint($input, $flags = 0)
    {
        try {
            $this->parse($input, $flags);
        } catch (ParsingException $e) {
            return $e;
        }
        return null;
    }
    /**
     * @param  string           $input JSON string
     * @param  int              $flags Bitmask of parse/lint options (see constants of this class)
     * @return mixed
     * @throws ParsingException
     *
     * @phpstan-param int-mask-of<self::*> $flags
     */
    public function parse($input, $flags = 0)
    {
        if ($flags & self::ALLOW_DUPLICATE_KEYS_TO_ARRAY && $flags & self::ALLOW_DUPLICATE_KEYS) {
            throw new \InvalidArgumentException('Only one of ALLOW_DUPLICATE_KEYS and ALLOW_DUPLICATE_KEYS_TO_ARRAY can be used, you passed in both.');
        }
        $this->failOnBOM($input);
        $this->flags = $flags;
        $this->stack = array(0);
        $this->vstack = array(null);
        $this->lstack = array();
        $yytext = '';
        $yylineno = 0;
        $yyleng = 0;
        /** @var int<0,3> */
        $recovering = 0;
        $this->lexer = new Lexer($flags);
        $this->lexer->setInput($input);
        $yyloc = $this->lexer->yylloc;
        $this->lstack[] = $yyloc;
        $symbol = null;
        $preErrorSymbol = null;
        $action = null;
        $a = null;
        $r = null;
        $p = null;
        $len = null;
        $newState = null;
        $expected = null;
        /** @var string|null */
        $errStr = null;
        while (\true) {
            // retrieve state number from top of stack
            $state = $this->stack[\count($this->stack) - 1];
            // use default actions if available
            if (isset($this->defaultActions[$state])) {
                $action = $this->defaultActions[$state];
            } else {
                if ($symbol === null) {
                    $symbol = $this->lexer->lex();
                }
                // read action for current state and first input
                /** @var array<int, int>|false */
                $action = isset($this->table[$state][$symbol]) ? $this->table[$state][$symbol] : \false;
            }
            // handle parse error
            if (!$action || !$action[0]) {
                assert(isset($symbol));
                if (!$recovering) {
                    // Report error
                    $expected = array();
                    foreach ($this->table[$state] as $p => $ignore) {
                        if (isset($this->terminals_[$p]) && $p > 2) {
                            $expected[] = "'" . $this->terminals_[$p] . "'";
                        }
                    }
                    $message = null;
                    if (\in_array("'STRING'", $expected) && \in_array(substr($this->lexer->match, 0, 1), array('"', "'"))) {
                        $message = "Invalid string";
                        if ("'" === substr($this->lexer->match, 0, 1)) {
                            $message .= ", it appears you used single quotes instead of double quotes";
                        } elseif (preg_match('{".+?(\\\\[^"bfnrt/\\\\u](...)?)}', $this->lexer->getFullUpcomingInput(), $match)) {
                            $message .= ", it appears you have an unescaped backslash at: " . $match[1];
                        } elseif (preg_match('{"(?:[^"]+|\\\\")*$}m', $this->lexer->getFullUpcomingInput())) {
                            $message .= ", it appears you forgot to terminate a string, or attempted to write a multiline string which is invalid";
                        }
                    }
                    $errStr = 'Parse error on line ' . ($yylineno + 1) . ":\n";
                    $errStr .= $this->lexer->showPosition() . "\n";
                    if ($message) {
                        $errStr .= $message;
                    } else {
                        $errStr .= \count($expected) > 1 ? "Expected one of: " : "Expected: ";
                        $errStr .= implode(', ', $expected);
                    }
                    if (',' === substr(trim($this->lexer->getPastInput()), -1)) {
                        $errStr .= " - It appears you have an extra trailing comma";
                    }
                    $this->parseError($errStr, array('text' => $this->lexer->match, 'token' => isset($this->terminals_[$symbol]) ? $this->terminals_[$symbol] : $symbol, 'line' => $this->lexer->yylineno, 'loc' => $yyloc, 'expected' => $expected));
                }
                // just recovered from another error
                if ($recovering == 3) {
                    if ($symbol === Lexer::EOF) {
                        throw new ParsingException($errStr ?: 'Parsing halted.');
                    }
                    // discard current lookahead and grab another
                    $yyleng = $this->lexer->yyleng;
                    $yytext = $this->lexer->yytext;
                    $yylineno = $this->lexer->yylineno;
                    $yyloc = $this->lexer->yylloc;
                    $symbol = $this->lexer->lex();
                }
                // try to recover from error
                while (\true) {
                    // check for error recovery rule in this state
                    if (\array_key_exists(Lexer::T_ERROR, $this->table[$state])) {
                        break;
                    }
                    if ($state == 0) {
                        throw new ParsingException($errStr ?: 'Parsing halted.');
                    }
                    $this->popStack(1);
                    $state = $this->stack[\count($this->stack) - 1];
                }
                $preErrorSymbol = $symbol;
                // save the lookahead token
                $symbol = Lexer::T_ERROR;
                // insert generic error symbol as new lookahead
                $state = $this->stack[\count($this->stack) - 1];
                /** @var array<int, int>|false */
                $action = isset($this->table[$state][Lexer::T_ERROR]) ? $this->table[$state][Lexer::T_ERROR] : \false;
                if ($action === \false) {
                    throw new \LogicException('No table value found for ' . $state . ' => ' . Lexer::T_ERROR);
                }
                $recovering = 3;
                // allow 3 real symbols to be shifted before reporting a new error
            }
            // this shouldn't happen, unless resolve defaults are off
            if (\is_array($action[0]) && \count($action) > 1) {
                throw new ParsingException('Parse Error: multiple actions possible at state: ' . $state . ', token: ' . $symbol);
            }
            switch ($action[0]) {
                case 1:
                    // shift
                    assert(isset($symbol));
                    $this->stack[] = $symbol;
                    $this->vstack[] = $this->lexer->yytext;
                    $this->lstack[] = $this->lexer->yylloc;
                    $this->stack[] = $action[1];
                    // push state
                    $symbol = null;
                    if (!$preErrorSymbol) {
                        // normal execution/no error
                        $yyleng = $this->lexer->yyleng;
                        $yytext = $this->lexer->yytext;
                        $yylineno = $this->lexer->yylineno;
                        $yyloc = $this->lexer->yylloc;
                        if ($recovering > 0) {
                            $recovering--;
                        }
                    } else {
                        // error just occurred, resume old lookahead from before error
                        $symbol = $preErrorSymbol;
                        $preErrorSymbol = null;
                    }
                    break;
                case 2:
                    // reduce
                    $len = $this->productions_[$action[1]][1];
                    // perform semantic action
                    $currentToken = $this->vstack[\count($this->vstack) - $len];
                    // default to $$ = $1
                    // default location, uses first token for firsts, last for lasts
                    $position = array(
                        // _$ = store
                        'first_line' => $this->lstack[\count($this->lstack) - ($len ?: 1)]['first_line'],
                        'last_line' => $this->lstack[\count($this->lstack) - 1]['last_line'],
                        'first_column' => $this->lstack[\count($this->lstack) - ($len ?: 1)]['first_column'],
                        'last_column' => $this->lstack[\count($this->lstack) - 1]['last_column'],
                    );
                    list($newToken, $actionResult) = $this->performAction($currentToken, $yytext, $yyleng, $yylineno, $action[1]);
                    if (!$actionResult instanceof Undefined) {
                        return $actionResult;
                    }
                    if ($len) {
                        $this->popStack($len);
                    }
                    $this->stack[] = $this->productions_[$action[1]][0];
                    // push nonterminal (reduce)
                    $this->vstack[] = $newToken;
                    $this->lstack[] = $position;
                    /** @var int */
                    $newState = $this->table[$this->stack[\count($this->stack) - 2]][$this->stack[\count($this->stack) - 1]];
                    $this->stack[] = $newState;
                    break;
                case 3:
                    // accept
                    return \true;
            }
        }
    }
    /**
     * @param  string $str
     * @param  array{text: string, token: string|int, line: int, loc: array{first_line: int, first_column: int, last_line: int, last_column: int}, expected: string[]}|null $hash
     * @return never
     */
    protected function parseError($str, $hash = null)
    {
        throw new ParsingException($str, $hash ?: array());
    }
    /**
     * @param  stdClass|array<mixed>|int|bool|float|string|null $currentToken
     * @param  string   $yytext
     * @param  int      $yyleng
     * @param  int      $yylineno
     * @param  int      $yystate
     * @return array{stdClass|array<mixed>|int|bool|float|string|null, stdClass|array<mixed>|int|bool|float|string|null|Undefined}
     */
    private function performAction($currentToken, $yytext, $yyleng, $yylineno, $yystate)
    {
        $token = $currentToken;
        $len = \count($this->vstack) - 1;
        switch ($yystate) {
            case 1:
                $yytext = preg_replace_callback('{(?:\\\\["bfnrt/\\\\]|\\\\u[a-fA-F0-9]{4})}', array($this, 'stringInterpolation'), $yytext);
                $token = $yytext;
                break;
            case 2:
                if (strpos($yytext, 'e') !== \false || strpos($yytext, 'E') !== \false) {
                    $token = \floatval($yytext);
                } else {
                    $token = strpos($yytext, '.') === \false ? \intval($yytext) : \floatval($yytext);
                }
                break;
            case 3:
                $token = null;
                break;
            case 4:
                $token = \true;
                break;
            case 5:
                $token = \false;
                break;
            case 6:
                $token = $this->vstack[$len - 1];
                return array($token, $token);
            case 13:
                if ($this->flags & self::PARSE_TO_ASSOC) {
                    $token = array();
                } else {
                    $token = new stdClass();
                }
                break;
            case 14:
                $token = $this->vstack[$len - 1];
                break;
            case 15:
                $token = array($this->vstack[$len - 2], $this->vstack[$len]);
                break;
            case 16:
                assert(\is_array($this->vstack[$len]));
                if (\PHP_VERSION_ID < 70100) {
                    $property = $this->vstack[$len][0] === '' ? '_empty_' : $this->vstack[$len][0];
                } else {
                    $property = $this->vstack[$len][0];
                }
                if ($this->flags & self::PARSE_TO_ASSOC) {
                    $token = array();
                    $token[$property] = $this->vstack[$len][1];
                } else {
                    $token = new stdClass();
                    $token->{$property} = $this->vstack[$len][1];
                }
                break;
            case 17:
                assert(\is_array($this->vstack[$len]));
                if ($this->flags & self::PARSE_TO_ASSOC) {
                    assert(\is_array($this->vstack[$len - 2]));
                    $token =& $this->vstack[$len - 2];
                    $key = $this->vstack[$len][0];
                    if ($this->flags & self::DETECT_KEY_CONFLICTS && isset($this->vstack[$len - 2][$key])) {
                        $errStr = 'Parse error on line ' . ($yylineno + 1) . ":\n";
                        $errStr .= $this->lexer->showPosition() . "\n";
                        $errStr .= "Duplicate key: " . $this->vstack[$len][0];
                        throw new DuplicateKeyException($errStr, $this->vstack[$len][0], array('line' => $yylineno + 1));
                    }
                    if ($this->flags & self::ALLOW_DUPLICATE_KEYS && isset($this->vstack[$len - 2][$key])) {
                        $duplicateCount = 1;
                        do {
                            $duplicateKey = $key . '.' . $duplicateCount++;
                        } while (isset($this->vstack[$len - 2][$duplicateKey]));
                        $this->vstack[$len - 2][$duplicateKey] = $this->vstack[$len][1];
                    } elseif ($this->flags & self::ALLOW_DUPLICATE_KEYS_TO_ARRAY && isset($this->vstack[$len - 2][$key])) {
                        if (!isset($this->vstack[$len - 2][$key]['__duplicates__']) || !is_array($this->vstack[$len - 2][$key]['__duplicates__'])) {
                            $this->vstack[$len - 2][$key] = array('__duplicates__' => array($this->vstack[$len - 2][$key]));
                        }
                        $this->vstack[$len - 2][$key]['__duplicates__'][] = $this->vstack[$len][1];
                    } else {
                        $this->vstack[$len - 2][$key] = $this->vstack[$len][1];
                    }
                } else {
                    assert($this->vstack[$len - 2] instanceof stdClass);
                    $token = $this->vstack[$len - 2];
                    if (\PHP_VERSION_ID < 70100) {
                        $key = $this->vstack[$len][0] === '' ? '_empty_' : $this->vstack[$len][0];
                    } else {
                        $key = $this->vstack[$len][0];
                    }
                    if ($this->flags & self::DETECT_KEY_CONFLICTS && isset($this->vstack[$len - 2]->{$key})) {
                        $errStr = 'Parse error on line ' . ($yylineno + 1) . ":\n";
                        $errStr .= $this->lexer->showPosition() . "\n";
                        $errStr .= "Duplicate key: " . $this->vstack[$len][0];
                        throw new DuplicateKeyException($errStr, $this->vstack[$len][0], array('line' => $yylineno + 1));
                    }
                    if ($this->flags & self::ALLOW_DUPLICATE_KEYS && isset($this->vstack[$len - 2]->{$key})) {
                        $duplicateCount = 1;
                        do {
                            $duplicateKey = $key . '.' . $duplicateCount++;
                        } while (isset($this->vstack[$len - 2]->{$duplicateKey}));
                        $this->vstack[$len - 2]->{$duplicateKey} = $this->vstack[$len][1];
                    } elseif ($this->flags & self::ALLOW_DUPLICATE_KEYS_TO_ARRAY && isset($this->vstack[$len - 2]->{$key})) {
                        if (!isset($this->vstack[$len - 2]->{$key}->__duplicates__)) {
                            $this->vstack[$len - 2]->{$key} = (object) array('__duplicates__' => array($this->vstack[$len - 2]->{$key}));
                        }
                        $this->vstack[$len - 2]->{$key}->__duplicates__[] = $this->vstack[$len][1];
                    } else {
                        $this->vstack[$len - 2]->{$key} = $this->vstack[$len][1];
                    }
                }
                break;
            case 18:
                $token = array();
                break;
            case 19:
                $token = $this->vstack[$len - 1];
                break;
            case 20:
                $token = array($this->vstack[$len]);
                break;
            case 21:
                assert(\is_array($this->vstack[$len - 2]));
                $this->vstack[$len - 2][] = $this->vstack[$len];
                $token = $this->vstack[$len - 2];
                break;
        }
        return array($token, new Undefined());
    }
    /**
     * @param  string $match
     * @return string
     */
    private function stringInterpolation($match)
    {
        switch ($match[0]) {
            case '\\\\':
                return '\\';
            case '\"':
                return '"';
            case '\b':
                return \chr(8);
            case '\f':
                return \chr(12);
            case '\n':
                return "\n";
            case '\r':
                return "\r";
            case '\t':
                return "\t";
            case '\/':
                return "/";
            default:
                return html_entity_decode('&#x' . ltrim(substr($match[0], 2), '0') . ';', \ENT_QUOTES, 'UTF-8');
        }
    }
    /**
     * @param  int $n
     * @return void
     */
    private function popStack($n)
    {
        $this->stack = \array_slice($this->stack, 0, -(2 * $n));
        $this->vstack = \array_slice($this->vstack, 0, -$n);
        $this->lstack = \array_slice($this->lstack, 0, -$n);
    }
    /**
     * @param  string $input
     * @return void
     */
    private function failOnBOM($input)
    {
        // UTF-8 ByteOrderMark sequence
        $bom = "﻿";
        if (substr($input, 0, 3) === $bom) {
            $this->parseError("BOM detected, make sure your input does not include a Unicode Byte-Order-Mark");
        }
    }
}
Copyright (c) 2015 Jordi Boggiano

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is furnished
to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
{
    "name": "seld\/signal-handler",
    "description": "Simple unix signal handler that silently fails where signals are not supported for easy cross-platform development",
    "keywords": [
        "unix",
        "posix",
        "signal",
        "sigint",
        "sigterm"
    ],
    "type": "library",
    "license": "MIT",
    "authors": [
        {
            "name": "Jordi Boggiano",
            "email": "j.boggiano@seld.be",
            "homepage": "http:\/\/seld.be"
        }
    ],
    "require": {
        "php": ">=7.2.0"
    },
    "require-dev": {
        "phpunit\/phpunit": "^7.5.20 || ^8.5.23",
        "psr\/log": "^1 || ^2 || ^3",
        "phpstan\/phpstan": "^1",
        "phpstan\/phpstan-phpunit": "^1",
        "phpstan\/phpstan-strict-rules": "^1.3",
        "phpstan\/phpstan-deprecation-rules": "^1.0"
    },
    "autoload": {
        "psr-4": {
            "_ContaoManager\\Seld\\Signal\\": "src\/"
        }
    },
    "autoload-dev": {
        "psr-4": {
            "_ContaoManager\\Seld\\Signal\\": "tests\/"
        }
    },
    "scripts": {
        "phpstan": "@php phpstan analyse",
        "test": "@php phpunit"
    },
    "extra": {
        "branch-alias": {
            "dev-main": "2.x-dev"
        }
    }
}<?php

/*
 * This file is part of signal-handler.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Seld\Signal;

use _ContaoManager\Psr\Log\LoggerInterface;
use Closure;
use WeakReference;
/**
 * SignalHandler and factory
 */
final class SignalHandler
{
    /**
     * The SIGHUP signal is sent to a process when its controlling terminal is closed. It was originally designed to
     * notify the process of a serial line drop (a hangup). In modern systems, this signal usually means that the
     * controlling pseudo or virtual terminal has been closed. Many daemons will reload their configuration files and
     * reopen their logfiles instead of exiting when receiving this signal. nohup is a command to make a command ignore
     * the signal.
     */
    public const SIGHUP = 'SIGHUP';
    /**
     * The SIGINT signal is sent to a process by its controlling terminal when a user wishes to interrupt the process.
     * This is typically initiated by pressing Ctrl-C, but on some systems, the "delete" character or "break" key can be
     * used.
     *
     * On Windows this is used to denote a PHP_WINDOWS_EVENT_CTRL_C
     */
    public const SIGINT = 'SIGINT';
    /**
     * The SIGQUIT signal is sent to a process by its controlling terminal when the user requests that the process quit
     * and perform a core dump.
     */
    public const SIGQUIT = 'SIGQUIT';
    /**
     * The SIGILL signal is sent to a process when it attempts to execute an illegal, malformed, unknown, or privileged
     * instruction.
     */
    public const SIGILL = 'SIGILL';
    /**
     * The SIGTRAP signal is sent to a process when an exception (or trap) occurs: a condition that a debugger has
     * requested to be informed of — for example, when a particular function is executed, or when a particular variable
     * changes value.
     */
    public const SIGTRAP = 'SIGTRAP';
    /**
     * The SIGABRT signal is sent to a process to tell it to abort, i.e. to terminate. The signal is usually initiated
     * by the process itself when it calls abort function of the C Standard Library, but it can be sent to the process
     * from outside like any other signal.
     */
    public const SIGABRT = 'SIGABRT';
    public const SIGIOT = 'SIGIOT';
    /**
     * The SIGBUS signal is sent to a process when it causes a bus error. The conditions that lead to the signal being
     * sent are, for example, incorrect memory access alignment or non-existent physical address.
     */
    public const SIGBUS = 'SIGBUS';
    public const SIGFPE = 'SIGFPE';
    /**
     * The SIGKILL signal is sent to a process to cause it to terminate immediately (kill). In contrast to SIGTERM and
     * SIGINT, this signal cannot be caught or ignored, and the receiving process cannot perform any clean-up upon
     * receiving this signal.
     */
    public const SIGKILL = 'SIGKILL';
    /**
     * The SIGUSR1 signal is sent to a process to indicate user-defined conditions.
     */
    public const SIGUSR1 = 'SIGUSR1';
    /**
     * The SIGUSR1 signa2 is sent to a process to indicate user-defined conditions.
     */
    public const SIGUSR2 = 'SIGUSR2';
    /**
     * The SIGSEGV signal is sent to a process when it makes an invalid virtual memory reference, or segmentation fault,
     * i.e. when it performs a segmentation violation.
     */
    public const SIGSEGV = 'SIGSEGV';
    /**
     * The SIGPIPE signal is sent to a process when it attempts to write to a pipe without a process connected to the
     * other end.
     */
    public const SIGPIPE = 'SIGPIPE';
    /**
     * The SIGALRM, SIGVTALRM and SIGPROF signal is sent to a process when the time limit specified in a call to a
     * preceding alarm setting function (such as setitimer) elapses. SIGALRM is sent when real or clock time elapses.
     * SIGVTALRM is sent when CPU time used by the process elapses. SIGPROF is sent when CPU time used by the process
     * and by the system on behalf of the process elapses.
     */
    public const SIGALRM = 'SIGALRM';
    /**
     * The SIGTERM signal is sent to a process to request its termination. Unlike the SIGKILL signal, it can be caught
     * and interpreted or ignored by the process. This allows the process to perform nice termination releasing
     * resources and saving state if appropriate. SIGINT is nearly identical to SIGTERM.
     */
    public const SIGTERM = 'SIGTERM';
    public const SIGSTKFLT = 'SIGSTKFLT';
    public const SIGCLD = 'SIGCLD';
    /**
     * The SIGCHLD signal is sent to a process when a child process terminates, is interrupted, or resumes after being
     * interrupted. One common usage of the signal is to instruct the operating system to clean up the resources used by
     * a child process after its termination without an explicit call to the wait system call.
     */
    public const SIGCHLD = 'SIGCHLD';
    /**
     * The SIGCONT signal instructs the operating system to continue (restart) a process previously paused by the
     * SIGSTOP or SIGTSTP signal. One important use of this signal is in job control in the Unix shell.
     */
    public const SIGCONT = 'SIGCONT';
    /**
     * The SIGSTOP signal instructs the operating system to stop a process for later resumption.
     */
    public const SIGSTOP = 'SIGSTOP';
    /**
     * The SIGTSTP signal is sent to a process by its controlling terminal to request it to stop (terminal stop). It is
     * commonly initiated by the user pressing Ctrl+Z. Unlike SIGSTOP, the process can register a signal handler for or
     * ignore the signal.
     */
    public const SIGTSTP = 'SIGTSTP';
    /**
     * The SIGTTIN signal is sent to a process when it attempts to read in from the tty while in the background.
     * Typically, this signal is received only by processes under job control; daemons do not have controlling
     */
    public const SIGTTIN = 'SIGTTIN';
    /**
     * The SIGTTOU signal is sent to a process when it attempts to write out from the tty while in the background.
     * Typically, this signal is received only by processes under job control; daemons do not have controlling
     */
    public const SIGTTOU = 'SIGTTOU';
    /**
     * The SIGURG signal is sent to a process when a socket has urgent or out-of-band data available to read.
     */
    public const SIGURG = 'SIGURG';
    /**
     * The SIGXCPU signal is sent to a process when it has used up the CPU for a duration that exceeds a certain
     * predetermined user-settable value. The arrival of a SIGXCPU signal provides the receiving process a chance to
     * quickly save any intermediate results and to exit gracefully, before it is terminated by the operating system
     * using the SIGKILL signal.
     */
    public const SIGXCPU = 'SIGXCPU';
    /**
     * The SIGXFSZ signal is sent to a process when it grows a file larger than the maximum allowed size
     */
    public const SIGXFSZ = 'SIGXFSZ';
    /**
     * The SIGVTALRM signal is sent to a process when the time limit specified in a call to a preceding alarm setting
     * function (such as setitimer) elapses. SIGVTALRM is sent when CPU time used by the process elapses.
     */
    public const SIGVTALRM = 'SIGVTALRM';
    /**
     * The SIGPROF signal is sent to a process when the time limit specified in a call to a preceding alarm setting
     * function (such as setitimer) elapses. SIGPROF is sent when CPU time used by the process and by the system on
     * behalf of the process elapses.
     */
    public const SIGPROF = 'SIGPROF';
    /**
     * The SIGWINCH signal is sent to a process when its controlling terminal changes its size (a window change).
     */
    public const SIGWINCH = 'SIGWINCH';
    /**
     * The SIGPOLL signal is sent when an event occurred on an explicitly watched file descriptor.Using it effectively
     * leads to making asynchronous I/O requests since the kernel will poll the descriptor in place of the caller. It
     * provides an alternative to active polling.
     */
    public const SIGPOLL = 'SIGPOLL';
    public const SIGIO = 'SIGIO';
    /**
     * The SIGPWR signal is sent to a process when the system experiences a power failure.
     */
    public const SIGPWR = 'SIGPWR';
    /**
     * The SIGSYS signal is sent to a process when it passes a bad argument to a system call. In practice, this kind of
     * signal is rarely encountered since applications rely on libraries (e.g. libc) to make the call for them.
     */
    public const SIGSYS = 'SIGSYS';
    public const SIGBABY = 'SIGBABY';
    /**
     * CTRL+Break support, available on Windows only for PHP_WINDOWS_EVENT_CTRL_BREAK
     */
    public const SIGBREAK = 'SIGBREAK';
    private const ALL_SIGNALS = [self::SIGHUP, self::SIGINT, self::SIGQUIT, self::SIGILL, self::SIGTRAP, self::SIGABRT, self::SIGIOT, self::SIGBUS, self::SIGFPE, self::SIGKILL, self::SIGUSR1, self::SIGUSR2, self::SIGSEGV, self::SIGPIPE, self::SIGALRM, self::SIGTERM, self::SIGSTKFLT, self::SIGCLD, self::SIGCHLD, self::SIGCONT, self::SIGSTOP, self::SIGTSTP, self::SIGTTIN, self::SIGTTOU, self::SIGURG, self::SIGXCPU, self::SIGXFSZ, self::SIGVTALRM, self::SIGPROF, self::SIGWINCH, self::SIGPOLL, self::SIGIO, self::SIGPWR, self::SIGSYS, self::SIGBABY, self::SIGBREAK];
    /**
     * @var self::SIG*|null
     */
    private $triggered = null;
    /**
     * @var list<self::SIG*>
     * @readonly
     */
    private $signals;
    /**
     * @var LoggerInterface|(callable(self::SIG* $name, SignalHandler $self): void)|null
     * @readonly
     */
    private $loggerOrCallback;
    /**
     * @var array<int, self|WeakReference<self>>
     */
    private static $handlers = [];
    /** @var Closure|null */
    private static $windowsHandler = null;
    /**
     * @param array<self::SIG*> $signals
     * @param LoggerInterface|(callable(self::SIG* $name, SignalHandler $self): void)|null $loggerOrCallback
     */
    private function __construct(array $signals, $loggerOrCallback)
    {
        if (!is_callable($loggerOrCallback) && !$loggerOrCallback instanceof LoggerInterface && $loggerOrCallback !== null) {
            throw new \InvalidArgumentException('$loggerOrCallback must be a ' . LoggerInterface::class . ' instance, a callable, or null, ' . (is_object($loggerOrCallback) ? get_class($loggerOrCallback) : gettype($loggerOrCallback)) . ' received.');
        }
        $this->signals = $signals;
        $this->loggerOrCallback = $loggerOrCallback;
    }
    /**
     * @param self::SIG* $signalName
     */
    private function trigger(string $signalName): void
    {
        $this->triggered = $signalName;
        if ($this->loggerOrCallback instanceof LoggerInterface) {
            $this->loggerOrCallback->info('Received ' . $signalName);
        } elseif ($this->loggerOrCallback !== null) {
            ($this->loggerOrCallback)($signalName, $this);
        }
    }
    /**
     * Fetches the triggered state of the handler
     *
     * @phpstan-impure
     */
    public function isTriggered(): bool
    {
        return $this->triggered !== null;
    }
    /**
     * Exits the process while communicating that the handled signal was what killed the process
     *
     * This is different from doing exit(SIGINT), and is also different to a successful exit(0).
     *
     * This should only be used when you received a signal and then handled it to gracefully shutdown and are now ready to shutdown.
     *
     * ```
     * $signal = SignalHandler::create([SignalHandler::SIGINT], function (string $signal, SignalHandler $handler) {
     *     // do cleanup here..
     *
     *     $handler->exitWithLastSignal();
     * });
     *
     * // or...
     *
     * $signal = SignalHandler::create([SignalHandler::SIGINT]);
     *
     * while ($doingThings) {
     *     if ($signal->isTriggered()) {
     *         $signal->exitWithLastSignal();
     *     }
     *
     *     // do more things
     * }
     * ```
     *
     * @see https://www.cons.org/cracauer/sigint.html
     * @return never
     */
    public function exitWithLastSignal(): void
    {
        $signal = $this->triggered ?? 'SIGINT';
        $signal = defined($signal) ? constant($signal) : 2;
        if (function_exists('posix_kill') && function_exists('posix_getpid')) {
            pcntl_signal($signal, \SIG_DFL);
            posix_kill(posix_getpid(), $signal);
        }
        // just in case posix_kill above could not run
        // not strictly correct but it's the best we can do here
        exit(128 + $signal);
    }
    /**
     * Resets the state to let a handler accept a signal again
     */
    public function reset(): void
    {
        $this->triggered = null;
    }
    public function __destruct()
    {
        $this->unregister();
    }
    /**
     * @param (string|int)[] $signals array of signal names (more portable, see SignalHandler::SIG*) or constants - defaults to [SIGINT, SIGTERM]
     * @param LoggerInterface|callable $loggerOrCallback A PSR-3 Logger or a callback($signal, $signalName)
     * @return self A handler on which you can call isTriggered to know if the signal was received, and reset() to forget
     *
     * @phpstan-param list<self::SIG*|int> $signals
     * @phpstan-param LoggerInterface|(callable(self::SIG* $name, SignalHandler $self): void) $loggerOrCallback
     */
    public static function create(?array $signals = null, $loggerOrCallback = null): self
    {
        if ($signals === null) {
            $signals = [self::SIGINT, self::SIGTERM];
        }
        $signals = array_map(function ($signal) {
            if (is_int($signal)) {
                return self::getSignalName($signal);
            } elseif (!in_array($signal, self::ALL_SIGNALS, \true)) {
                throw new \InvalidArgumentException('$signals must be an array of SIG* constants or self::SIG* constants, got ' . var_export($signal, \true));
            }
            return $signal;
        }, (array) $signals);
        $handler = new self($signals, $loggerOrCallback);
        if (\PHP_VERSION_ID >= 80000) {
            array_unshift(self::$handlers, WeakReference::create($handler));
        } else {
            array_unshift(self::$handlers, $handler);
        }
        if (function_exists('sapi_windows_set_ctrl_handler') && \PHP_SAPI === 'cli' && (in_array(self::SIGINT, $signals, \true) || in_array(self::SIGBREAK, $signals, \true))) {
            if (null === self::$windowsHandler) {
                self::$windowsHandler = Closure::fromCallable([self::class, 'handleWindowsSignal']);
                sapi_windows_set_ctrl_handler(self::$windowsHandler);
            }
        }
        if (function_exists('pcntl_signal') && function_exists('pcntl_async_signals')) {
            pcntl_async_signals(\true);
            self::registerPcntlHandler($signals);
        }
        return $handler;
    }
    /**
     * Clears the signal handler
     *
     * On PHP 8+ this is not necessary and it will happen automatically on __destruct, but PHP 7 does not
     * support weak references and thus there you need to manually do this.
     *
     * If another handler was registered previously to this one, it becomes active again
     */
    public function unregister(): void
    {
        $signals = $this->signals;
        $index = \false;
        foreach (self::$handlers as $key => $handler) {
            if ($handler instanceof WeakReference && $handler->get() === $this || $handler === $this) {
                $index = $key;
                break;
            }
        }
        if ($index === \false) {
            // guard against double-unregistration when __destruct happens
            return;
        }
        unset(self::$handlers[$index]);
        if (self::$windowsHandler !== null && (in_array(self::SIGINT, $signals, \true) || in_array(self::SIGBREAK, $signals, \true))) {
            if (self::getHandlerFor(self::SIGINT) === null && self::getHandlerFor(self::SIGBREAK) === null) {
                sapi_windows_set_ctrl_handler(self::$windowsHandler, \false);
                self::$windowsHandler = null;
            }
        }
        if (function_exists('pcntl_signal')) {
            foreach ($signals as $signal) {
                // skip missing signals, for example OSX does not have all signals
                if (!defined($signal)) {
                    continue;
                }
                // keep listening to signals where we have a handler registered
                if (self::getHandlerFor($signal) !== null) {
                    continue;
                }
                pcntl_signal(constant($signal), \SIG_DFL);
            }
        }
    }
    /**
     * Clears all signal handlers
     *
     * On PHP 8+ this should not be necessary as it will happen automatically on __destruct, but PHP 7 does not
     * support weak references and thus there you need to manually do this.
     *
     * This can be done to reset the global state, but ideally you should always call ->unregister() in a try/finally block to ensure it happens.
     */
    public static function unregisterAll(): void
    {
        if (self::$windowsHandler !== null) {
            sapi_windows_set_ctrl_handler(self::$windowsHandler, \false);
            self::$windowsHandler = null;
        }
        foreach (self::$handlers as $key => $handler) {
            if ($handler instanceof WeakReference) {
                $handler = $handler->get();
                if ($handler === null) {
                    unset(self::$handlers[$key]);
                    continue;
                }
            }
            $handler->unregister();
        }
    }
    /**
     * @param list<self::SIG*> $signals
     */
    private static function registerPcntlHandler(array $signals): void
    {
        static $callable;
        if ($callable === null) {
            $callable = Closure::fromCallable([self::class, 'handlePcntlSignal']);
        }
        foreach ($signals as $signal) {
            // skip missing signals, for example OSX does not have all signals
            if (!defined($signal)) {
                continue;
            }
            pcntl_signal(constant($signal), $callable);
        }
    }
    private static function handleWindowsSignal(int $event): void
    {
        if (\PHP_WINDOWS_EVENT_CTRL_C === $event) {
            self::callHandlerFor(self::SIGINT);
        } elseif (\PHP_WINDOWS_EVENT_CTRL_BREAK === $event) {
            self::callHandlerFor(self::SIGBREAK);
        }
    }
    private static function handlePcntlSignal(int $signal): void
    {
        self::callHandlerFor(self::getSignalName($signal));
    }
    /**
     * Calls the first handler from the top of the stack that can handle a given signal
     *
     * @param self::SIG* $signal
     */
    private static function callHandlerFor(string $signal): void
    {
        $handler = self::getHandlerFor($signal);
        if ($handler !== null) {
            $handler->trigger($signal);
        }
    }
    /**
     * Returns the first handler from the top of the stack that can handle a given signal
     *
     * @param self::SIG* $signal
     * @return self|null
     */
    private static function getHandlerFor(string $signal): ?self
    {
        foreach (self::$handlers as $key => $handler) {
            if ($handler instanceof WeakReference) {
                $handler = $handler->get();
                if ($handler === null) {
                    unset(self::$handlers[$key]);
                    continue;
                }
            }
            if (in_array($signal, $handler->signals, \true)) {
                return $handler;
            }
        }
        return null;
    }
    /**
     * @return self::SIG*
     */
    private static function getSignalName(int $signo): string
    {
        static $signals = null;
        if ($signals === null) {
            $signals = [];
            foreach (self::ALL_SIGNALS as $value) {
                if (defined($value)) {
                    $signals[constant($value)] = $value;
                }
            }
        }
        if (isset($signals[$signo])) {
            return $signals[$signo];
        }
        throw new \InvalidArgumentException('Unknown signal #' . $signo);
    }
}
<?php

// @generated by Humbug Box

$loader = (static function () {
    // Backup the autoloaded Composer files
    $existingComposerAutoloadFiles = isset($GLOBALS['__composer_autoload_files']) ? $GLOBALS['__composer_autoload_files'] : [];

    // autoload.php @generated by Composer

    if (PHP_VERSION_ID < 50600) {
        if (!headers_sent()) {
            header('HTTP/1.1 500 Internal Server Error');
        }
        $err = 'Composer 2.3.0 dropped support for autoloading on PHP <5.6 and you are running '.PHP_VERSION.', please upgrade PHP or use Composer 2.2 LTS via "composer self-update --2.2". Aborting.'.PHP_EOL;
        if (!ini_get('display_errors')) {
            if (PHP_SAPI === 'cli' || PHP_SAPI === 'phpdbg') {
                fwrite(STDERR, $err);
            } elseif (!headers_sent()) {
                echo $err;
            }
        }
        throw new RuntimeException($err);
    }

    require_once __DIR__ . '/composer/autoload_real.php';

    $loader = ComposerAutoloaderInit70603d6d4d667e5d8f93c56c4d3630ec::getLoader();

    // Ensure InstalledVersions is available
    $installedVersionsPath = __DIR__.'/composer/InstalledVersions.php';
    if (file_exists($installedVersionsPath)) require_once $installedVersionsPath;

    // Restore the backup and ensure the excluded files are properly marked as loaded
    $GLOBALS['__composer_autoload_files'] = \array_merge(
        $existingComposerAutoloadFiles,
        \array_fill_keys(['9eaa6b0f3f04e58e17ae5ecb754ea313', '320cde22f66dd4f5d3fd621d3e88b98f', 'acbe0d033c55cd0a032b415e08d14f4c', '8825ede83f2f289127722d4e842cf7e8', '36dfd6ed9dd74e8062aa61f09caf8554', 'e69f7f6ee287b969198c3c9d6777bd38', '5928a00fa978807cf85d90ec3f4b0147', '0e6d7bf4a5811bfa5cf40c5ccd6fae6a', '0d59ee240a4cd96ddbb4ff164fccea4d', 'a4a119a56e50fbb293281d9a48007e0e', '23c18046f52bef3eea034657bafda50f', '30c350846a78957e55d8ce1814c9d80b', '439927d75b11a5dc11560cd0ea0a9599', '662a729f963d39afe703c9d9b7ab4a8c', '1c231eb0a2980bfb45d2eedd095b0490', '7bfbed8d216c917b4d3e46b319a08b5c', '9d2b9fc6db0f153a0a149fefb182415e', 'ecbd807f4f8310e9d7f9fa9cb55b281c', '09f6b20656683369174dd6fa83b7e5fb', '54b9ab13bc86d8251a04a939888e357e', 'a89966141ddd51b9b7e868bc3b2f9bb0', '51421aa3e5e8003b70a289762d146a2a', 'f49032536fdd06afd9df7191c3f21453', '18e965175c6bcd96deba6bc791a44373', '7edcabe1b67fbb38f4972a722bbbb429', '7bdb062931f6e7102434c3ad28423eb6', 'd1fb64fd99fc22e28e29a95cc0ea533a', '7b0b5d7b98f96ad751222ae5cc98cfcb', 'e071a82732d15e17758a292fa42671d2', '2ce7b16f239603c90fab694e15bb9a83', 'b12cc48dd13968c20d14f4fdf56ced96', 'df0fb630b0bc80f94ae5f46644b0587b', 'd348f2569bd50bd17f658b9fced73856', '0728099c86c7da9b043674ffe354abee', 'b2f9f3fd5c396f96fa6e1e2bd938d3d0', '5d061a676f0194f3638848e71a903ec7', '963ad795d6b67b0f3b5bdb455e2783ae', '299128432f1508b581080d7faecb94e6', '0f0a493ec6424b03b28812b12c3a3083', '87005e5d70a864da11374798fc217696', 'f9fd4d0bdd191df87ed0092ea696bcbc', '88eb642bc60ad56d36dcb0cbcddc74f4', '3e593131d33cca33b86e55317d2bc0b3', '0e1fff5a03ce8edfa2fa9b52d709372a', 'ed74e3668930207f1a4ac3f94099e2e6', '5a966bedfea587acd3f5a140d050c889', '72e758a5054532edb6cb9ed0d015e600', '79ae8b3fe21b90a128627e3871279d1b', '6e3fae29631ef280660b3cdad06f25a8'], true)
    );

    return $loader;
})();

// Class aliases. For more information see:
// https://github.com/humbug/php-scoper/blob/master/docs/further-reading.md#class-aliases
if (!function_exists('humbug_phpscoper_expose_class')) {
    function humbug_phpscoper_expose_class($exposed, $prefixed) {
        if (!class_exists($exposed, false) && !interface_exists($exposed, false) && !trait_exists($exposed, false)) {
            spl_autoload_call($prefixed);
        }
    }
}
humbug_phpscoper_expose_class('ContaoManagerDowngrade', '_ContaoManager\ContaoManagerDowngrade');
humbug_phpscoper_expose_class('StreamContextFactory', '_ContaoManager\StreamContextFactory');
humbug_phpscoper_expose_class('NoProxyPattern', '_ContaoManager\NoProxyPattern');
humbug_phpscoper_expose_class('Stringable', '_ContaoManager\Stringable');
humbug_phpscoper_expose_class('Deprecated', '_ContaoManager\Deprecated');
humbug_phpscoper_expose_class('Symfony\Component\Finder\Finder', '_ContaoManager\Symfony\Component\Finder\Finder');
humbug_phpscoper_expose_class('ComposerAutoloaderInit70603d6d4d667e5d8f93c56c4d3630ec', '_ContaoManager\ComposerAutoloaderInit70603d6d4d667e5d8f93c56c4d3630ec');
humbug_phpscoper_expose_class('', '_ContaoManager\');

// Function aliases. For more information see:
// https://github.com/humbug/php-scoper/blob/master/docs/further-reading.md#function-aliases
if (!function_exists('dd')) { function dd() { return \_ContaoManager\dd(...func_get_args()); } }
if (!function_exists('dump')) { function dump() { return \_ContaoManager\dump(...func_get_args()); } }
if (!function_exists('getUrlFromPath')) { function getUrlFromPath() { return \_ContaoManager\getUrlFromPath(...func_get_args()); } }
if (!function_exists('includeIfExists')) { function includeIfExists() { return \_ContaoManager\includeIfExists(...func_get_args()); } }
if (!function_exists('lint')) { function lint() { return \_ContaoManager\lint(...func_get_args()); } }
if (!function_exists('lintFile')) { function lintFile() { return \_ContaoManager\lintFile(...func_get_args()); } }
if (!function_exists('litespeed_finish_request')) { function litespeed_finish_request() { return \_ContaoManager\litespeed_finish_request(...func_get_args()); } }
if (!function_exists('output')) { function output() { return \_ContaoManager\output(...func_get_args()); } }
if (!function_exists('parseHeaderValue')) { function parseHeaderValue() { return \_ContaoManager\parseHeaderValue(...func_get_args()); } }
if (!function_exists('showJsonError')) { function showJsonError() { return \_ContaoManager\showJsonError(...func_get_args()); } }
if (!function_exists('showUsage')) { function showUsage() { return \_ContaoManager\showUsage(...func_get_args()); } }
if (!function_exists('zend_monitor_custom_event')) { function zend_monitor_custom_event() { return \_ContaoManager\zend_monitor_custom_event(...func_get_args()); } }

return $loader;
MIT License

Copyright (c) 2016 Ondřej Mirtes
Copyright (c) 2025 PHPStan s.r.o.

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
<h1 align="center">PHPDoc Parser for PHPStan</h1>

<p align="center">
	<a href="https://github.com/phpstan/phpdoc-parser/actions"><img src="https://github.com/phpstan/phpdoc-parser/workflows/Build/badge.svg" alt="Build Status"></a>
	<a href="https://packagist.org/packages/phpstan/phpdoc-parser"><img src="https://poser.pugx.org/phpstan/phpdoc-parser/v/stable" alt="Latest Stable Version"></a>
	<a href="https://choosealicense.com/licenses/mit/"><img src="https://poser.pugx.org/phpstan/phpstan/license" alt="License"></a>
	<a href="https://phpstan.org/"><img src="https://img.shields.io/badge/PHPStan-enabled-brightgreen.svg?style=flat" alt="PHPStan Enabled"></a>
</p>

This library `phpstan/phpdoc-parser` represents PHPDocs with an AST (Abstract Syntax Tree). It supports parsing and modifying PHPDocs.

For the complete list of supported PHPDoc features check out PHPStan documentation. PHPStan is the main (but not the only) user of this library.

* [PHPDoc Basics](https://phpstan.org/writing-php-code/phpdocs-basics) (list of PHPDoc tags)
* [PHPDoc Types](https://phpstan.org/writing-php-code/phpdoc-types) (list of PHPDoc types)
* [phpdoc-parser API Reference](https://phpstan.github.io/phpdoc-parser/2.3.x/namespace-PHPStan.PhpDocParser.html) with all the AST node types etc.

This parser also supports parsing [Doctrine Annotations](https://github.com/doctrine/annotations). The AST nodes live in the [PHPStan\PhpDocParser\Ast\PhpDoc\Doctrine namespace](https://phpstan.github.io/phpdoc-parser/2.1.x/namespace-PHPStan.PhpDocParser.Ast.PhpDoc.Doctrine.html).

## Installation

```
composer require phpstan/phpdoc-parser
```

## Basic usage

```php
<?php

require_once __DIR__ . '/vendor/autoload.php';

use PHPStan\PhpDocParser\Ast\PhpDoc\ParamTagValueNode;
use PHPStan\PhpDocParser\Ast\PhpDoc\PhpDocNode;
use PHPStan\PhpDocParser\Ast\Type\IdentifierTypeNode;
use PHPStan\PhpDocParser\Lexer\Lexer;
use PHPStan\PhpDocParser\ParserConfig;
use PHPStan\PhpDocParser\Parser\ConstExprParser;
use PHPStan\PhpDocParser\Parser\PhpDocParser;
use PHPStan\PhpDocParser\Parser\TokenIterator;
use PHPStan\PhpDocParser\Parser\TypeParser;

// basic setup

$config = new ParserConfig(usedAttributes: []);
$lexer = new Lexer($config);
$constExprParser = new ConstExprParser($config);
$typeParser = new TypeParser($config, $constExprParser);
$phpDocParser = new PhpDocParser($config, $typeParser, $constExprParser);

// parsing and reading a PHPDoc string

$tokens = new TokenIterator($lexer->tokenize('/** @param Lorem $a */'));
$phpDocNode = $phpDocParser->parse($tokens); // PhpDocNode
$paramTags = $phpDocNode->getParamTagValues(); // ParamTagValueNode[]
echo $paramTags[0]->parameterName; // '$a'
echo $paramTags[0]->type; // IdentifierTypeNode - 'Lorem'
```

### Format-preserving printer

This component can be used to modify the AST
and print it again as close as possible to the original.

It's heavily inspired by format-preserving printer component in [nikic/PHP-Parser](https://github.com/nikic/PHP-Parser).

```php
<?php

require_once __DIR__ . '/vendor/autoload.php';

use PHPStan\PhpDocParser\Ast\NodeTraverser;
use PHPStan\PhpDocParser\Ast\NodeVisitor\CloningVisitor;
use PHPStan\PhpDocParser\Ast\PhpDoc\PhpDocNode;
use PHPStan\PhpDocParser\Ast\Type\IdentifierTypeNode;
use PHPStan\PhpDocParser\Lexer\Lexer;
use PHPStan\PhpDocParser\ParserConfig;
use PHPStan\PhpDocParser\Parser\ConstExprParser;
use PHPStan\PhpDocParser\Parser\PhpDocParser;
use PHPStan\PhpDocParser\Parser\TokenIterator;
use PHPStan\PhpDocParser\Parser\TypeParser;
use PHPStan\PhpDocParser\Printer\Printer;

// basic setup with enabled required lexer attributes

$config = new ParserConfig(usedAttributes: ['lines' => true, 'indexes' => true, 'comments' => true]);
$lexer = new Lexer($config);
$constExprParser = new ConstExprParser($config);
$typeParser = new TypeParser($config, $constExprParser);
$phpDocParser = new PhpDocParser($config, $typeParser, $constExprParser);

$tokens = new TokenIterator($lexer->tokenize('/** @param Lorem $a */'));
$phpDocNode = $phpDocParser->parse($tokens); // PhpDocNode

$cloningTraverser = new NodeTraverser([new CloningVisitor()]);

/** @var PhpDocNode $newPhpDocNode */
[$newPhpDocNode] = $cloningTraverser->traverse([$phpDocNode]);

// change something in $newPhpDocNode
$newPhpDocNode->getParamTagValues()[0]->type = new IdentifierTypeNode('Ipsum');

// print changed PHPDoc
$printer = new Printer();
$newPhpDoc = $printer->printFormatPreserving($newPhpDocNode, $phpDocNode, $tokens);
echo $newPhpDoc; // '/** @param Ipsum $a */'
```

## Code of Conduct

This project adheres to a [Contributor Code of Conduct](CODE_OF_CONDUCT.md). By participating in this project and its community, you are expected to uphold this code.

## Building

Initially you need to run `composer install`, or `composer update` in case you aren't working in a folder which was built before.

Afterwards you can either run the whole build including linting and coding standards using

    make

or run only tests using

    make tests
Upgrading from phpstan/phpdoc-parser 1.x to 2.0
=================================

### PHP version requirements

phpstan/phpdoc-parser now requires PHP 7.4 or newer to run.

### Changed constructors of parser classes

Instead of different arrays and boolean values passed into class constructors during setup, parser classes now share a common ParserConfig object.

Before:

```php
use PHPStan\PhpDocParser\Lexer\Lexer;
use PHPStan\PhpDocParser\Parser\ConstExprParser;
use PHPStan\PhpDocParser\Parser\TypeParser;
use PHPStan\PhpDocParser\Parser\PhpDocParser;

$usedAttributes = ['lines' => true, 'indexes' => true];

$lexer = new Lexer();
$constExprParser = new ConstExprParser(true, true, $usedAttributes);
$typeParser = new TypeParser($constExprParser, true, $usedAttributes);
$phpDocParser = new PhpDocParser($typeParser, $constExprParser, true, true, $usedAttributes);
```

After:

```php
use PHPStan\PhpDocParser\Lexer\Lexer;
use PHPStan\PhpDocParser\ParserConfig;
use PHPStan\PhpDocParser\Parser\ConstExprParser;
use PHPStan\PhpDocParser\Parser\TypeParser;
use PHPStan\PhpDocParser\Parser\PhpDocParser;

$config = new ParserConfig(usedAttributes: ['lines' => true, 'indexes' => true]);
$lexer = new Lexer($config);
$constExprParser = new ConstExprParser($config);
$typeParser = new TypeParser($config, $constExprParser);
$phpDocParser = new PhpDocParser($config, $typeParser, $constExprParser);
```

The point of ParserConfig is that over the course of phpstan/phpdoc-parser 2.x development series it's most likely going to gain new optional parameters akin to PHPStan's [bleeding edge](https://phpstan.org/blog/what-is-bleeding-edge). These parameters will allow opting in to new behaviour which will become the default in 3.0.

With ParserConfig object, it's now going to be impossible to configure parser classes inconsistently. Which [happened to users](https://github.com/phpstan/phpdoc-parser/issues/251#issuecomment-2333927959) when they were separate boolean values.

### Support for parsing Doctrine annotations

This parser now supports parsing [Doctrine Annotations](https://github.com/doctrine/annotations). The AST nodes representing Doctrine Annotations live in the [PHPStan\PhpDocParser\Ast\PhpDoc\Doctrine namespace](https://phpstan.github.io/phpdoc-parser/2.0.x/namespace-PHPStan.PhpDocParser.Ast.PhpDoc.Doctrine.html).

### Whitespace before description is required

phpdoc-parser 1.x sometimes silently consumed invalid part of a PHPDoc type as description:

```php
/** @return \Closure(...int, string): string */
```

This became `IdentifierTypeNode` of `\Closure` and with `(...int, string): string` as description. (Valid callable syntax is: `\Closure(int ...$u, string): string`.)

Another example:

```php
/** @return array{foo: int}} */
```

The extra `}` also became description.

Both of these examples are now InvalidTagValueNode.

If these parts are supposed to be PHPDoc descriptions, you need to put whitespace between the type and the description text:

```php
/** @return \Closure (...int, string): string */
/** @return array{foo: int} } */
```

### Type aliases with invalid types are preserved

In phpdoc-parser 1.x, invalid type alias syntax was represented as [`InvalidTagValueNode`](https://phpstan.github.io/phpdoc-parser/2.0.x/PHPStan.PhpDocParser.Ast.PhpDoc.InvalidTagValueNode.html), losing information about a type alias being present.

```php
/**
 * @phpstan-type TypeAlias
 */
```

This `@phpstan-type` is missing the actual type to alias. In phpdoc-parser 2.0 this is now represented as [`TypeAliasTagValueNode`](https://phpstan.github.io/phpdoc-parser/2.0.x/PHPStan.PhpDocParser.Ast.PhpDoc.TypeAliasTagValueNode.html) (instead of `InvalidTagValueNode`) with [`InvalidTypeNode`](https://phpstan.github.io/phpdoc-parser/2.0.x/PHPStan.PhpDocParser.Ast.Type.InvalidTypeNode.html) in place of the type.

### Removal of QuoteAwareConstExprStringNode

The class [QuoteAwareConstExprStringNode](https://phpstan.github.io/phpdoc-parser/1.23.x/PHPStan.PhpDocParser.Ast.ConstExpr.QuoteAwareConstExprStringNode.html) has been removed.

Instead, [ConstExprStringNode](https://phpstan.github.io/phpdoc-parser/2.0.x/PHPStan.PhpDocParser.Ast.ConstExpr.ConstExprStringNode.html) gained information about the kind of quotes being used.

### Removed 2nd parameter of `ConstExprParser::parse()` (`$trimStrings`)

`ConstExprStringNode::$value` now contains unescaped values without surrounding `''` or `""` quotes.

Use `ConstExprStringNode::__toString()` or [`Printer`](https://phpstan.github.io/phpdoc-parser/2.0.x/PHPStan.PhpDocParser.Printer.Printer.html) to get the escaped value along with surrounding quotes.

### Text between tags always belongs to description

Multi-line descriptions between tags were previously represented as separate [PhpDocTextNode](https://phpstan.github.io/phpdoc-parser/2.0.x/PHPStan.PhpDocParser.Ast.PhpDoc.PhpDocTextNode.html):

```php
/**
 * @param Foo $foo 1st multi world description
 * some text in the middle
 * @param Bar $bar 2nd multi world description
 */
```

The line with `some text in the middle` in phpdoc-parser 2.0 is now part of the description of the first `@param` tag.

### `ArrayShapeNode` construction changes

`ArrayShapeNode` constructor made private, added public static methods `createSealed()` and `createUnsealed()`.

### Minor BC breaks

* Constructor parameter `$isEquality` in `AssertTag*ValueNode` made required
* Constructor parameter `$templateTypes` in `MethodTagValueNode` made required
* Constructor parameter `$isReference` in `ParamTagValueNode` made required
* Constructor parameter `$isReference` in `TypelessParamTagValueNode` made required
* Constructor parameter `$templateTypes` in `CallableTypeNode` made required
* Constructor parameters `$expectedTokenValue` and `$currentTokenLine` in `ParserException` made required
* `ArrayShapeItemNode` and `ObjectShapeItemNode` are not standalone TypeNode, just Node
{
    "name": "phpstan\/phpdoc-parser",
    "description": "PHPDoc parser with support for nullable, intersection and generic types",
    "license": "MIT",
    "require": {
        "php": "^7.4 || ^8.0"
    },
    "require-dev": {
        "doctrine\/annotations": "^2.0",
        "nikic\/php-parser": "^5.3.0",
        "php-parallel-lint\/php-parallel-lint": "^1.2",
        "phpstan\/extension-installer": "^1.0",
        "phpstan\/phpstan": "^2.0",
        "phpstan\/phpstan-phpunit": "^2.0",
        "phpstan\/phpstan-strict-rules": "^2.0",
        "phpunit\/phpunit": "^9.6",
        "symfony\/process": "^5.2"
    },
    "config": {
        "platform": {
            "php": "7.4.6"
        },
        "sort-packages": true,
        "allow-plugins": {
            "phpstan\/extension-installer": true
        }
    },
    "autoload": {
        "psr-4": {
            "_ContaoManager\\PHPStan\\PhpDocParser\\": [
                "src\/"
            ]
        }
    },
    "autoload-dev": {
        "psr-4": {
            "_ContaoManager\\PHPStan\\PhpDocParser\\": [
                "tests\/PHPStan"
            ]
        }
    },
    "minimum-stability": "dev",
    "prefer-stable": true
}<?php

declare (strict_types=1);
namespace _ContaoManager\PHPStan\PhpDocParser\Lexer;

use _ContaoManager\PHPStan\PhpDocParser\ParserConfig;
use function implode;
use function preg_match_all;
use const PREG_SET_ORDER;
/**
 * Implementation based on Nette Tokenizer (New BSD License; https://github.com/nette/tokenizer)
 */
class Lexer
{
    public const TOKEN_REFERENCE = 0;
    public const TOKEN_UNION = 1;
    public const TOKEN_INTERSECTION = 2;
    public const TOKEN_NULLABLE = 3;
    public const TOKEN_OPEN_PARENTHESES = 4;
    public const TOKEN_CLOSE_PARENTHESES = 5;
    public const TOKEN_OPEN_ANGLE_BRACKET = 6;
    public const TOKEN_CLOSE_ANGLE_BRACKET = 7;
    public const TOKEN_OPEN_SQUARE_BRACKET = 8;
    public const TOKEN_CLOSE_SQUARE_BRACKET = 9;
    public const TOKEN_COMMA = 10;
    public const TOKEN_VARIADIC = 11;
    public const TOKEN_DOUBLE_COLON = 12;
    public const TOKEN_DOUBLE_ARROW = 13;
    public const TOKEN_EQUAL = 14;
    public const TOKEN_OPEN_PHPDOC = 15;
    public const TOKEN_CLOSE_PHPDOC = 16;
    public const TOKEN_PHPDOC_TAG = 17;
    public const TOKEN_DOCTRINE_TAG = 18;
    public const TOKEN_FLOAT = 19;
    public const TOKEN_INTEGER = 20;
    public const TOKEN_SINGLE_QUOTED_STRING = 21;
    public const TOKEN_DOUBLE_QUOTED_STRING = 22;
    public const TOKEN_DOCTRINE_ANNOTATION_STRING = 23;
    public const TOKEN_IDENTIFIER = 24;
    public const TOKEN_THIS_VARIABLE = 25;
    public const TOKEN_VARIABLE = 26;
    public const TOKEN_HORIZONTAL_WS = 27;
    public const TOKEN_PHPDOC_EOL = 28;
    public const TOKEN_OTHER = 29;
    public const TOKEN_END = 30;
    public const TOKEN_COLON = 31;
    public const TOKEN_WILDCARD = 32;
    public const TOKEN_OPEN_CURLY_BRACKET = 33;
    public const TOKEN_CLOSE_CURLY_BRACKET = 34;
    public const TOKEN_NEGATED = 35;
    public const TOKEN_ARROW = 36;
    public const TOKEN_COMMENT = 37;
    public const TOKEN_LABELS = [self::TOKEN_REFERENCE => '\'&\'', self::TOKEN_UNION => '\'|\'', self::TOKEN_INTERSECTION => '\'&\'', self::TOKEN_NULLABLE => '\'?\'', self::TOKEN_NEGATED => '\'!\'', self::TOKEN_OPEN_PARENTHESES => '\'(\'', self::TOKEN_CLOSE_PARENTHESES => '\')\'', self::TOKEN_OPEN_ANGLE_BRACKET => '\'<\'', self::TOKEN_CLOSE_ANGLE_BRACKET => '\'>\'', self::TOKEN_OPEN_SQUARE_BRACKET => '\'[\'', self::TOKEN_CLOSE_SQUARE_BRACKET => '\']\'', self::TOKEN_OPEN_CURLY_BRACKET => '\'{\'', self::TOKEN_CLOSE_CURLY_BRACKET => '\'}\'', self::TOKEN_COMMA => '\',\'', self::TOKEN_COMMENT => '\'//\'', self::TOKEN_COLON => '\':\'', self::TOKEN_VARIADIC => '\'...\'', self::TOKEN_DOUBLE_COLON => '\'::\'', self::TOKEN_DOUBLE_ARROW => '\'=>\'', self::TOKEN_ARROW => '\'->\'', self::TOKEN_EQUAL => '\'=\'', self::TOKEN_OPEN_PHPDOC => '\'/**\'', self::TOKEN_CLOSE_PHPDOC => '\'*/\'', self::TOKEN_PHPDOC_TAG => 'TOKEN_PHPDOC_TAG', self::TOKEN_DOCTRINE_TAG => 'TOKEN_DOCTRINE_TAG', self::TOKEN_PHPDOC_EOL => 'TOKEN_PHPDOC_EOL', self::TOKEN_FLOAT => 'TOKEN_FLOAT', self::TOKEN_INTEGER => 'TOKEN_INTEGER', self::TOKEN_SINGLE_QUOTED_STRING => 'TOKEN_SINGLE_QUOTED_STRING', self::TOKEN_DOUBLE_QUOTED_STRING => 'TOKEN_DOUBLE_QUOTED_STRING', self::TOKEN_DOCTRINE_ANNOTATION_STRING => 'TOKEN_DOCTRINE_ANNOTATION_STRING', self::TOKEN_IDENTIFIER => 'type', self::TOKEN_THIS_VARIABLE => '\'$this\'', self::TOKEN_VARIABLE => 'variable', self::TOKEN_HORIZONTAL_WS => 'TOKEN_HORIZONTAL_WS', self::TOKEN_OTHER => 'TOKEN_OTHER', self::TOKEN_END => 'TOKEN_END', self::TOKEN_WILDCARD => '*'];
    public const VALUE_OFFSET = 0;
    public const TYPE_OFFSET = 1;
    public const LINE_OFFSET = 2;
    private ParserConfig $config;
    // @phpstan-ignore property.onlyWritten
    private ?string $regexp = null;
    public function __construct(ParserConfig $config)
    {
        $this->config = $config;
    }
    /**
     * @return list<array{string, int, int}>
     */
    public function tokenize(string $s): array
    {
        if ($this->regexp === null) {
            $this->regexp = $this->generateRegexp();
        }
        preg_match_all($this->regexp, $s, $matches, PREG_SET_ORDER);
        $tokens = [];
        $line = 1;
        foreach ($matches as $match) {
            $type = (int) $match['MARK'];
            $tokens[] = [$match[0], $type, $line];
            if ($type !== self::TOKEN_PHPDOC_EOL) {
                continue;
            }
            $line++;
        }
        $tokens[] = ['', self::TOKEN_END, $line];
        return $tokens;
    }
    private function generateRegexp(): string
    {
        $patterns = [
            self::TOKEN_HORIZONTAL_WS => '[\x09\x20]++',
            self::TOKEN_IDENTIFIER => '(?:[\\\\]?+[a-z_\x80-\xFF][0-9a-z_\x80-\xFF-]*+)++',
            self::TOKEN_THIS_VARIABLE => '\$this(?![0-9a-z_\x80-\xFF])',
            self::TOKEN_VARIABLE => '\$[a-z_\x80-\xFF][0-9a-z_\x80-\xFF]*+',
            // '&' followed by TOKEN_VARIADIC, TOKEN_VARIABLE, TOKEN_EQUAL, TOKEN_EQUAL or TOKEN_CLOSE_PARENTHESES
            self::TOKEN_REFERENCE => '&(?=\s*+(?:[.,=)]|(?:\$(?!this(?![0-9a-z_\x80-\xFF])))))',
            self::TOKEN_UNION => '\|',
            self::TOKEN_INTERSECTION => '&',
            self::TOKEN_NULLABLE => '\?',
            self::TOKEN_NEGATED => '!',
            self::TOKEN_OPEN_PARENTHESES => '\(',
            self::TOKEN_CLOSE_PARENTHESES => '\)',
            self::TOKEN_OPEN_ANGLE_BRACKET => '<',
            self::TOKEN_CLOSE_ANGLE_BRACKET => '>',
            self::TOKEN_OPEN_SQUARE_BRACKET => '\[',
            self::TOKEN_CLOSE_SQUARE_BRACKET => '\]',
            self::TOKEN_OPEN_CURLY_BRACKET => '\{',
            self::TOKEN_CLOSE_CURLY_BRACKET => '\}',
            self::TOKEN_COMMA => ',',
            self::TOKEN_COMMENT => '\/\/[^\r\n]*(?=\n|\r|\*/)',
            self::TOKEN_VARIADIC => '\.\.\.',
            self::TOKEN_DOUBLE_COLON => '::',
            self::TOKEN_DOUBLE_ARROW => '=>',
            self::TOKEN_ARROW => '->',
            self::TOKEN_EQUAL => '=',
            self::TOKEN_COLON => ':',
            self::TOKEN_OPEN_PHPDOC => '/\*\*(?=\s)\x20?+',
            self::TOKEN_CLOSE_PHPDOC => '\*/',
            self::TOKEN_PHPDOC_TAG => '@(?:[a-z][a-z0-9-\\\\]+:)?[a-z][a-z0-9-\\\\]*+',
            self::TOKEN_DOCTRINE_TAG => '@[a-z_\\\\][a-z0-9_\:\\\\]*[a-z_][a-z0-9_]*',
            self::TOKEN_PHPDOC_EOL => '\r?+\n[\x09\x20]*+(?:\*(?!/)\x20?+)?',
            self::TOKEN_FLOAT => '[+\-]?(?:(?:[0-9]++(_[0-9]++)*\.[0-9]*+(_[0-9]++)*(?:e[+\-]?[0-9]++(_[0-9]++)*)?)|(?:[0-9]*+(_[0-9]++)*\.[0-9]++(_[0-9]++)*(?:e[+\-]?[0-9]++(_[0-9]++)*)?)|(?:[0-9]++(_[0-9]++)*e[+\-]?[0-9]++(_[0-9]++)*))',
            self::TOKEN_INTEGER => '[+\-]?(?:(?:0b[0-1]++(_[0-1]++)*)|(?:0o[0-7]++(_[0-7]++)*)|(?:0x[0-9a-f]++(_[0-9a-f]++)*)|(?:[0-9]++(_[0-9]++)*))',
            self::TOKEN_SINGLE_QUOTED_STRING => '\'(?:\\\\[^\r\n]|[^\'\r\n\\\\])*+\'',
            self::TOKEN_DOUBLE_QUOTED_STRING => '"(?:\\\\[^\r\n]|[^"\r\n\\\\])*+"',
            self::TOKEN_DOCTRINE_ANNOTATION_STRING => '"(?:""|[^"])*+"',
            self::TOKEN_WILDCARD => '\*',
            // anything but TOKEN_CLOSE_PHPDOC or TOKEN_HORIZONTAL_WS or TOKEN_EOL
            self::TOKEN_OTHER => '(?:(?!\*/)[^\s])++',
        ];
        foreach ($patterns as $type => &$pattern) {
            $pattern = '(?:' . $pattern . ')(*MARK:' . $type . ')';
        }
        return '~' . implode('|', $patterns) . '~Asi';
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\PHPStan\PhpDocParser\Printer;

/**
 * Inspired by https://github.com/nikic/PHP-Parser/tree/36a6dcd04e7b0285e8f0868f44bd4927802f7df1
 *
 * Copyright (c) 2011, Nikita Popov
 * All rights reserved.
 *
 * Implements the Myers diff algorithm.
 *
 * @internal
 */
class DiffElem
{
    public const TYPE_KEEP = 0;
    public const TYPE_REMOVE = 1;
    public const TYPE_ADD = 2;
    public const TYPE_REPLACE = 3;
    /** @var self::TYPE_* */
    public $type;
    /** @var mixed Is null for add operations */
    public $old;
    /** @var mixed Is null for remove operations */
    public $new;
    /**
     * @param self::TYPE_* $type
     * @param mixed $old Is null for add operations
     * @param mixed $new Is null for remove operations
     */
    public function __construct(int $type, $old, $new)
    {
        $this->type = $type;
        $this->old = $old;
        $this->new = $new;
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\PHPStan\PhpDocParser\Printer;

use Exception;
use function array_reverse;
use function count;
/**
 * Inspired by https://github.com/nikic/PHP-Parser/tree/36a6dcd04e7b0285e8f0868f44bd4927802f7df1
 *
 * Copyright (c) 2011, Nikita Popov
 * All rights reserved.
 *
 * Implements the Myers diff algorithm.
 *
 * Myers, Eugene W. "An O (ND) difference algorithm and its variations."
 * Algorithmica 1.1 (1986): 251-266.
 *
 * @template T
 * @internal
 */
class Differ
{
    /** @var callable(T, T): bool */
    private $isEqual;
    /**
     * Create differ over the given equality relation.
     *
     * @param callable(T, T): bool $isEqual Equality relation
     */
    public function __construct(callable $isEqual)
    {
        $this->isEqual = $isEqual;
    }
    /**
     * Calculate diff (edit script) from $old to $new.
     *
     * @param T[] $old Original array
     * @param T[] $new New array
     *
     * @return DiffElem[] Diff (edit script)
     */
    public function diff(array $old, array $new): array
    {
        [$trace, $x, $y] = $this->calculateTrace($old, $new);
        return $this->extractDiff($trace, $x, $y, $old, $new);
    }
    /**
     * Calculate diff, including "replace" operations.
     *
     * If a sequence of remove operations is followed by the same number of add operations, these
     * will be coalesced into replace operations.
     *
     * @param T[] $old Original array
     * @param T[] $new New array
     *
     * @return DiffElem[] Diff (edit script), including replace operations
     */
    public function diffWithReplacements(array $old, array $new): array
    {
        return $this->coalesceReplacements($this->diff($old, $new));
    }
    /**
     * @param T[] $old
     * @param T[] $new
     * @return array{array<int, array<int, int>>, int, int}
     */
    private function calculateTrace(array $old, array $new): array
    {
        $n = count($old);
        $m = count($new);
        $max = $n + $m;
        $v = [1 => 0];
        $trace = [];
        for ($d = 0; $d <= $max; $d++) {
            $trace[] = $v;
            for ($k = -$d; $k <= $d; $k += 2) {
                if ($k === -$d || $k !== $d && $v[$k - 1] < $v[$k + 1]) {
                    $x = $v[$k + 1];
                } else {
                    $x = $v[$k - 1] + 1;
                }
                $y = $x - $k;
                while ($x < $n && $y < $m && ($this->isEqual)($old[$x], $new[$y])) {
                    $x++;
                    $y++;
                }
                $v[$k] = $x;
                if ($x >= $n && $y >= $m) {
                    return [$trace, $x, $y];
                }
            }
        }
        throw new Exception('Should not happen');
    }
    /**
     * @param array<int, array<int, int>> $trace
     * @param T[] $old
     * @param T[] $new
     * @return DiffElem[]
     */
    private function extractDiff(array $trace, int $x, int $y, array $old, array $new): array
    {
        $result = [];
        for ($d = count($trace) - 1; $d >= 0; $d--) {
            $v = $trace[$d];
            $k = $x - $y;
            if ($k === -$d || $k !== $d && $v[$k - 1] < $v[$k + 1]) {
                $prevK = $k + 1;
            } else {
                $prevK = $k - 1;
            }
            $prevX = $v[$prevK];
            $prevY = $prevX - $prevK;
            while ($x > $prevX && $y > $prevY) {
                $result[] = new DiffElem(DiffElem::TYPE_KEEP, $old[$x - 1], $new[$y - 1]);
                $x--;
                $y--;
            }
            if ($d === 0) {
                break;
            }
            while ($x > $prevX) {
                $result[] = new DiffElem(DiffElem::TYPE_REMOVE, $old[$x - 1], null);
                $x--;
            }
            while ($y > $prevY) {
                $result[] = new DiffElem(DiffElem::TYPE_ADD, null, $new[$y - 1]);
                $y--;
            }
        }
        return array_reverse($result);
    }
    /**
     * Coalesce equal-length sequences of remove+add into a replace operation.
     *
     * @param DiffElem[] $diff
     * @return DiffElem[]
     */
    private function coalesceReplacements(array $diff): array
    {
        $newDiff = [];
        $c = count($diff);
        for ($i = 0; $i < $c; $i++) {
            $diffType = $diff[$i]->type;
            if ($diffType !== DiffElem::TYPE_REMOVE) {
                $newDiff[] = $diff[$i];
                continue;
            }
            $j = $i;
            while ($j < $c && $diff[$j]->type === DiffElem::TYPE_REMOVE) {
                $j++;
            }
            $k = $j;
            while ($k < $c && $diff[$k]->type === DiffElem::TYPE_ADD) {
                $k++;
            }
            if ($j - $i === $k - $j) {
                $len = $j - $i;
                for ($n = 0; $n < $len; $n++) {
                    $newDiff[] = new DiffElem(DiffElem::TYPE_REPLACE, $diff[$i + $n]->old, $diff[$j + $n]->new);
                }
            } else {
                for (; $i < $k; $i++) {
                    $newDiff[] = $diff[$i];
                }
            }
            $i = $k - 1;
        }
        return $newDiff;
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\PHPStan\PhpDocParser\Printer;

use LogicException;
use _ContaoManager\PHPStan\PhpDocParser\Ast\Attribute;
use _ContaoManager\PHPStan\PhpDocParser\Ast\Comment;
use _ContaoManager\PHPStan\PhpDocParser\Ast\ConstExpr\ConstExprArrayNode;
use _ContaoManager\PHPStan\PhpDocParser\Ast\ConstExpr\ConstExprNode;
use _ContaoManager\PHPStan\PhpDocParser\Ast\Node;
use _ContaoManager\PHPStan\PhpDocParser\Ast\PhpDoc\AssertTagMethodValueNode;
use _ContaoManager\PHPStan\PhpDocParser\Ast\PhpDoc\AssertTagPropertyValueNode;
use _ContaoManager\PHPStan\PhpDocParser\Ast\PhpDoc\AssertTagValueNode;
use _ContaoManager\PHPStan\PhpDocParser\Ast\PhpDoc\Doctrine\DoctrineAnnotation;
use _ContaoManager\PHPStan\PhpDocParser\Ast\PhpDoc\Doctrine\DoctrineArgument;
use _ContaoManager\PHPStan\PhpDocParser\Ast\PhpDoc\Doctrine\DoctrineArray;
use _ContaoManager\PHPStan\PhpDocParser\Ast\PhpDoc\Doctrine\DoctrineArrayItem;
use _ContaoManager\PHPStan\PhpDocParser\Ast\PhpDoc\Doctrine\DoctrineTagValueNode;
use _ContaoManager\PHPStan\PhpDocParser\Ast\PhpDoc\ExtendsTagValueNode;
use _ContaoManager\PHPStan\PhpDocParser\Ast\PhpDoc\ImplementsTagValueNode;
use _ContaoManager\PHPStan\PhpDocParser\Ast\PhpDoc\MethodTagValueNode;
use _ContaoManager\PHPStan\PhpDocParser\Ast\PhpDoc\MethodTagValueParameterNode;
use _ContaoManager\PHPStan\PhpDocParser\Ast\PhpDoc\MixinTagValueNode;
use _ContaoManager\PHPStan\PhpDocParser\Ast\PhpDoc\ParamClosureThisTagValueNode;
use _ContaoManager\PHPStan\PhpDocParser\Ast\PhpDoc\ParamImmediatelyInvokedCallableTagValueNode;
use _ContaoManager\PHPStan\PhpDocParser\Ast\PhpDoc\ParamLaterInvokedCallableTagValueNode;
use _ContaoManager\PHPStan\PhpDocParser\Ast\PhpDoc\ParamOutTagValueNode;
use _ContaoManager\PHPStan\PhpDocParser\Ast\PhpDoc\ParamTagValueNode;
use _ContaoManager\PHPStan\PhpDocParser\Ast\PhpDoc\PhpDocChildNode;
use _ContaoManager\PHPStan\PhpDocParser\Ast\PhpDoc\PhpDocNode;
use _ContaoManager\PHPStan\PhpDocParser\Ast\PhpDoc\PhpDocTagNode;
use _ContaoManager\PHPStan\PhpDocParser\Ast\PhpDoc\PhpDocTagValueNode;
use _ContaoManager\PHPStan\PhpDocParser\Ast\PhpDoc\PhpDocTextNode;
use _ContaoManager\PHPStan\PhpDocParser\Ast\PhpDoc\PropertyTagValueNode;
use _ContaoManager\PHPStan\PhpDocParser\Ast\PhpDoc\PureUnlessCallableIsImpureTagValueNode;
use _ContaoManager\PHPStan\PhpDocParser\Ast\PhpDoc\RequireExtendsTagValueNode;
use _ContaoManager\PHPStan\PhpDocParser\Ast\PhpDoc\RequireImplementsTagValueNode;
use _ContaoManager\PHPStan\PhpDocParser\Ast\PhpDoc\ReturnTagValueNode;
use _ContaoManager\PHPStan\PhpDocParser\Ast\PhpDoc\SealedTagValueNode;
use _ContaoManager\PHPStan\PhpDocParser\Ast\PhpDoc\SelfOutTagValueNode;
use _ContaoManager\PHPStan\PhpDocParser\Ast\PhpDoc\TemplateTagValueNode;
use _ContaoManager\PHPStan\PhpDocParser\Ast\PhpDoc\ThrowsTagValueNode;
use _ContaoManager\PHPStan\PhpDocParser\Ast\PhpDoc\TypeAliasImportTagValueNode;
use _ContaoManager\PHPStan\PhpDocParser\Ast\PhpDoc\TypeAliasTagValueNode;
use _ContaoManager\PHPStan\PhpDocParser\Ast\PhpDoc\UsesTagValueNode;
use _ContaoManager\PHPStan\PhpDocParser\Ast\PhpDoc\VarTagValueNode;
use _ContaoManager\PHPStan\PhpDocParser\Ast\Type\ArrayShapeItemNode;
use _ContaoManager\PHPStan\PhpDocParser\Ast\Type\ArrayShapeNode;
use _ContaoManager\PHPStan\PhpDocParser\Ast\Type\ArrayShapeUnsealedTypeNode;
use _ContaoManager\PHPStan\PhpDocParser\Ast\Type\ArrayTypeNode;
use _ContaoManager\PHPStan\PhpDocParser\Ast\Type\CallableTypeNode;
use _ContaoManager\PHPStan\PhpDocParser\Ast\Type\CallableTypeParameterNode;
use _ContaoManager\PHPStan\PhpDocParser\Ast\Type\ConditionalTypeForParameterNode;
use _ContaoManager\PHPStan\PhpDocParser\Ast\Type\ConditionalTypeNode;
use _ContaoManager\PHPStan\PhpDocParser\Ast\Type\ConstTypeNode;
use _ContaoManager\PHPStan\PhpDocParser\Ast\Type\GenericTypeNode;
use _ContaoManager\PHPStan\PhpDocParser\Ast\Type\IdentifierTypeNode;
use _ContaoManager\PHPStan\PhpDocParser\Ast\Type\IntersectionTypeNode;
use _ContaoManager\PHPStan\PhpDocParser\Ast\Type\InvalidTypeNode;
use _ContaoManager\PHPStan\PhpDocParser\Ast\Type\NullableTypeNode;
use _ContaoManager\PHPStan\PhpDocParser\Ast\Type\ObjectShapeItemNode;
use _ContaoManager\PHPStan\PhpDocParser\Ast\Type\ObjectShapeNode;
use _ContaoManager\PHPStan\PhpDocParser\Ast\Type\OffsetAccessTypeNode;
use _ContaoManager\PHPStan\PhpDocParser\Ast\Type\ThisTypeNode;
use _ContaoManager\PHPStan\PhpDocParser\Ast\Type\TypeNode;
use _ContaoManager\PHPStan\PhpDocParser\Ast\Type\UnionTypeNode;
use _ContaoManager\PHPStan\PhpDocParser\Lexer\Lexer;
use _ContaoManager\PHPStan\PhpDocParser\Parser\TokenIterator;
use function array_keys;
use function array_map;
use function assert;
use function count;
use function get_class;
use function get_object_vars;
use function implode;
use function in_array;
use function is_array;
use function preg_match_all;
use function sprintf;
use function str_replace;
use function strlen;
use function strpos;
use function trim;
use const PREG_SET_ORDER;
/**
 * Inspired by https://github.com/nikic/PHP-Parser/tree/36a6dcd04e7b0285e8f0868f44bd4927802f7df1
 *
 * Copyright (c) 2011, Nikita Popov
 * All rights reserved.
 */
final class Printer
{
    /** @var Differ<Node> */
    private Differ $differ;
    /**
     * Map From "{$class}->{$subNode}" to string that should be inserted
     * between elements of this list subnode
     *
     * @var array<string, string>
     */
    private array $listInsertionMap = [PhpDocNode::class . '->children' => "\n * ", UnionTypeNode::class . '->types' => '|', IntersectionTypeNode::class . '->types' => '&', ArrayShapeNode::class . '->items' => ', ', ObjectShapeNode::class . '->items' => ', ', CallableTypeNode::class . '->parameters' => ', ', CallableTypeNode::class . '->templateTypes' => ', ', GenericTypeNode::class . '->genericTypes' => ', ', ConstExprArrayNode::class . '->items' => ', ', MethodTagValueNode::class . '->parameters' => ', ', DoctrineArray::class . '->items' => ', ', DoctrineAnnotation::class . '->arguments' => ', '];
    /**
     * [$find, $extraLeft, $extraRight]
     *
     * @var array<string, array{string|null, string, string}>
     */
    private array $emptyListInsertionMap = [CallableTypeNode::class . '->parameters' => ['(', '', ''], ArrayShapeNode::class . '->items' => ['{', '', ''], ObjectShapeNode::class . '->items' => ['{', '', ''], DoctrineArray::class . '->items' => ['{', '', ''], DoctrineAnnotation::class . '->arguments' => ['(', '', '']];
    /** @var array<string, list<class-string<TypeNode>>> */
    private array $parenthesesMap = [CallableTypeNode::class . '->returnType' => [CallableTypeNode::class, UnionTypeNode::class, IntersectionTypeNode::class], ArrayTypeNode::class . '->type' => [CallableTypeNode::class, UnionTypeNode::class, IntersectionTypeNode::class, ConstTypeNode::class, NullableTypeNode::class], OffsetAccessTypeNode::class . '->type' => [CallableTypeNode::class, UnionTypeNode::class, IntersectionTypeNode::class, NullableTypeNode::class]];
    /** @var array<string, list<class-string<TypeNode>>> */
    private array $parenthesesListMap = [IntersectionTypeNode::class . '->types' => [IntersectionTypeNode::class, UnionTypeNode::class, NullableTypeNode::class], UnionTypeNode::class . '->types' => [IntersectionTypeNode::class, UnionTypeNode::class, NullableTypeNode::class]];
    public function printFormatPreserving(PhpDocNode $node, PhpDocNode $originalNode, TokenIterator $originalTokens): string
    {
        $this->differ = new Differ(static function ($a, $b) {
            if ($a instanceof Node && $b instanceof Node) {
                return $a === $b->getAttribute(Attribute::ORIGINAL_NODE);
            }
            return \false;
        });
        $tokenIndex = 0;
        $result = $this->printArrayFormatPreserving($node->children, $originalNode->children, $originalTokens, $tokenIndex, PhpDocNode::class, 'children');
        if ($result !== null) {
            return $result . $originalTokens->getContentBetween($tokenIndex, $originalTokens->getTokenCount());
        }
        return $this->print($node);
    }
    public function print(Node $node): string
    {
        if ($node instanceof PhpDocNode) {
            return "/**\n *" . implode("\n *", array_map(function (PhpDocChildNode $child): string {
                $s = $this->print($child);
                return $s === '' ? '' : ' ' . $s;
            }, $node->children)) . "\n */";
        }
        if ($node instanceof PhpDocTextNode) {
            return $node->text;
        }
        if ($node instanceof PhpDocTagNode) {
            if ($node->value instanceof DoctrineTagValueNode) {
                return $this->print($node->value);
            }
            return trim(sprintf('%s %s', $node->name, $this->print($node->value)));
        }
        if ($node instanceof PhpDocTagValueNode) {
            return $this->printTagValue($node);
        }
        if ($node instanceof TypeNode) {
            return $this->printType($node);
        }
        if ($node instanceof ConstExprNode) {
            return $this->printConstExpr($node);
        }
        if ($node instanceof MethodTagValueParameterNode) {
            $type = $node->type !== null ? $this->print($node->type) . ' ' : '';
            $isReference = $node->isReference ? '&' : '';
            $isVariadic = $node->isVariadic ? '...' : '';
            $default = $node->defaultValue !== null ? ' = ' . $this->print($node->defaultValue) : '';
            return "{$type}{$isReference}{$isVariadic}{$node->parameterName}{$default}";
        }
        if ($node instanceof CallableTypeParameterNode) {
            $type = $this->print($node->type) . ' ';
            $isReference = $node->isReference ? '&' : '';
            $isVariadic = $node->isVariadic ? '...' : '';
            $isOptional = $node->isOptional ? '=' : '';
            return trim("{$type}{$isReference}{$isVariadic}{$node->parameterName}") . $isOptional;
        }
        if ($node instanceof ArrayShapeUnsealedTypeNode) {
            if ($node->keyType !== null) {
                return sprintf('<%s, %s>', $this->printType($node->keyType), $this->printType($node->valueType));
            }
            return sprintf('<%s>', $this->printType($node->valueType));
        }
        if ($node instanceof DoctrineAnnotation) {
            return (string) $node;
        }
        if ($node instanceof DoctrineArgument) {
            return (string) $node;
        }
        if ($node instanceof DoctrineArray) {
            return (string) $node;
        }
        if ($node instanceof DoctrineArrayItem) {
            return (string) $node;
        }
        if ($node instanceof ArrayShapeItemNode) {
            if ($node->keyName !== null) {
                return sprintf('%s%s: %s', $this->print($node->keyName), $node->optional ? '?' : '', $this->printType($node->valueType));
            }
            return $this->printType($node->valueType);
        }
        if ($node instanceof ObjectShapeItemNode) {
            if ($node->keyName !== null) {
                return sprintf('%s%s: %s', $this->print($node->keyName), $node->optional ? '?' : '', $this->printType($node->valueType));
            }
            return $this->printType($node->valueType);
        }
        throw new LogicException(sprintf('Unknown node type %s', get_class($node)));
    }
    private function printTagValue(PhpDocTagValueNode $node): string
    {
        // only nodes that contain another node are handled here
        // the rest falls back on (string) $node
        if ($node instanceof AssertTagMethodValueNode) {
            $isNegated = $node->isNegated ? '!' : '';
            $isEquality = $node->isEquality ? '=' : '';
            $type = $this->printType($node->type);
            return trim("{$isNegated}{$isEquality}{$type} {$node->parameter}->{$node->method}() {$node->description}");
        }
        if ($node instanceof AssertTagPropertyValueNode) {
            $isNegated = $node->isNegated ? '!' : '';
            $isEquality = $node->isEquality ? '=' : '';
            $type = $this->printType($node->type);
            return trim("{$isNegated}{$isEquality}{$type} {$node->parameter}->{$node->property} {$node->description}");
        }
        if ($node instanceof AssertTagValueNode) {
            $isNegated = $node->isNegated ? '!' : '';
            $isEquality = $node->isEquality ? '=' : '';
            $type = $this->printType($node->type);
            return trim("{$isNegated}{$isEquality}{$type} {$node->parameter} {$node->description}");
        }
        if ($node instanceof ExtendsTagValueNode || $node instanceof ImplementsTagValueNode) {
            $type = $this->printType($node->type);
            return trim("{$type} {$node->description}");
        }
        if ($node instanceof MethodTagValueNode) {
            $static = $node->isStatic ? 'static ' : '';
            $returnType = $node->returnType !== null ? $this->printType($node->returnType) . ' ' : '';
            $parameters = implode(', ', array_map(fn(MethodTagValueParameterNode $parameter): string => $this->print($parameter), $node->parameters));
            $description = $node->description !== '' ? " {$node->description}" : '';
            $templateTypes = count($node->templateTypes) > 0 ? '<' . implode(', ', array_map(fn(TemplateTagValueNode $templateTag): string => $this->print($templateTag), $node->templateTypes)) . '>' : '';
            return "{$static}{$returnType}{$node->methodName}{$templateTypes}({$parameters}){$description}";
        }
        if ($node instanceof MixinTagValueNode) {
            $type = $this->printType($node->type);
            return trim("{$type} {$node->description}");
        }
        if ($node instanceof RequireExtendsTagValueNode) {
            $type = $this->printType($node->type);
            return trim("{$type} {$node->description}");
        }
        if ($node instanceof RequireImplementsTagValueNode) {
            $type = $this->printType($node->type);
            return trim("{$type} {$node->description}");
        }
        if ($node instanceof SealedTagValueNode) {
            $type = $this->printType($node->type);
            return trim("{$type} {$node->description}");
        }
        if ($node instanceof ParamOutTagValueNode) {
            $type = $this->printType($node->type);
            return trim("{$type} {$node->parameterName} {$node->description}");
        }
        if ($node instanceof ParamTagValueNode) {
            $reference = $node->isReference ? '&' : '';
            $variadic = $node->isVariadic ? '...' : '';
            $type = $this->printType($node->type);
            return trim("{$type} {$reference}{$variadic}{$node->parameterName} {$node->description}");
        }
        if ($node instanceof ParamImmediatelyInvokedCallableTagValueNode) {
            return trim("{$node->parameterName} {$node->description}");
        }
        if ($node instanceof ParamLaterInvokedCallableTagValueNode) {
            return trim("{$node->parameterName} {$node->description}");
        }
        if ($node instanceof ParamClosureThisTagValueNode) {
            return trim("{$node->type} {$node->parameterName} {$node->description}");
        }
        if ($node instanceof PureUnlessCallableIsImpureTagValueNode) {
            return trim("{$node->parameterName} {$node->description}");
        }
        if ($node instanceof PropertyTagValueNode) {
            $type = $this->printType($node->type);
            return trim("{$type} {$node->propertyName} {$node->description}");
        }
        if ($node instanceof ReturnTagValueNode) {
            $type = $this->printType($node->type);
            return trim("{$type} {$node->description}");
        }
        if ($node instanceof SelfOutTagValueNode) {
            $type = $this->printType($node->type);
            return trim($type . ' ' . $node->description);
        }
        if ($node instanceof TemplateTagValueNode) {
            $upperBound = $node->bound !== null ? ' of ' . $this->printType($node->bound) : '';
            $lowerBound = $node->lowerBound !== null ? ' super ' . $this->printType($node->lowerBound) : '';
            $default = $node->default !== null ? ' = ' . $this->printType($node->default) : '';
            return trim("{$node->name}{$upperBound}{$lowerBound}{$default} {$node->description}");
        }
        if ($node instanceof ThrowsTagValueNode) {
            $type = $this->printType($node->type);
            return trim("{$type} {$node->description}");
        }
        if ($node instanceof TypeAliasImportTagValueNode) {
            return trim("{$node->importedAlias} from " . $this->printType($node->importedFrom) . ($node->importedAs !== null ? " as {$node->importedAs}" : ''));
        }
        if ($node instanceof TypeAliasTagValueNode) {
            $type = $this->printType($node->type);
            return trim("{$node->alias} {$type}");
        }
        if ($node instanceof UsesTagValueNode) {
            $type = $this->printType($node->type);
            return trim("{$type} {$node->description}");
        }
        if ($node instanceof VarTagValueNode) {
            $type = $this->printType($node->type);
            return trim("{$type} " . trim("{$node->variableName} {$node->description}"));
        }
        return (string) $node;
    }
    private function printType(TypeNode $node): string
    {
        if ($node instanceof ArrayShapeNode) {
            $items = array_map(fn(ArrayShapeItemNode $item): string => $this->print($item), $node->items);
            if (!$node->sealed) {
                $items[] = '...' . ($node->unsealedType === null ? '' : $this->print($node->unsealedType));
            }
            return $node->kind . '{' . implode(', ', $items) . '}';
        }
        if ($node instanceof ArrayTypeNode) {
            return $this->printOffsetAccessType($node->type) . '[]';
        }
        if ($node instanceof CallableTypeNode) {
            if ($node->returnType instanceof CallableTypeNode || $node->returnType instanceof UnionTypeNode || $node->returnType instanceof IntersectionTypeNode) {
                $returnType = $this->wrapInParentheses($node->returnType);
            } else {
                $returnType = $this->printType($node->returnType);
            }
            $template = $node->templateTypes !== [] ? '<' . implode(', ', array_map(fn(TemplateTagValueNode $templateNode): string => $this->print($templateNode), $node->templateTypes)) . '>' : '';
            $parameters = implode(', ', array_map(fn(CallableTypeParameterNode $parameterNode): string => $this->print($parameterNode), $node->parameters));
            return "{$node->identifier}{$template}({$parameters}): {$returnType}";
        }
        if ($node instanceof ConditionalTypeForParameterNode) {
            return sprintf('(%s %s %s ? %s : %s)', $node->parameterName, $node->negated ? 'is not' : 'is', $this->printType($node->targetType), $this->printType($node->if), $this->printType($node->else));
        }
        if ($node instanceof ConditionalTypeNode) {
            return sprintf('(%s %s %s ? %s : %s)', $this->printType($node->subjectType), $node->negated ? 'is not' : 'is', $this->printType($node->targetType), $this->printType($node->if), $this->printType($node->else));
        }
        if ($node instanceof ConstTypeNode) {
            return $this->printConstExpr($node->constExpr);
        }
        if ($node instanceof GenericTypeNode) {
            $genericTypes = [];
            foreach ($node->genericTypes as $index => $type) {
                $variance = $node->variances[$index] ?? GenericTypeNode::VARIANCE_INVARIANT;
                if ($variance === GenericTypeNode::VARIANCE_INVARIANT) {
                    $genericTypes[] = $this->printType($type);
                } elseif ($variance === GenericTypeNode::VARIANCE_BIVARIANT) {
                    $genericTypes[] = '*';
                } else {
                    $genericTypes[] = sprintf('%s %s', $variance, $this->print($type));
                }
            }
            return $node->type . '<' . implode(', ', $genericTypes) . '>';
        }
        if ($node instanceof IdentifierTypeNode) {
            return $node->name;
        }
        if ($node instanceof IntersectionTypeNode || $node instanceof UnionTypeNode) {
            $items = [];
            foreach ($node->types as $type) {
                if ($type instanceof IntersectionTypeNode || $type instanceof UnionTypeNode || $type instanceof NullableTypeNode) {
                    $items[] = $this->wrapInParentheses($type);
                    continue;
                }
                $items[] = $this->printType($type);
            }
            return implode($node instanceof IntersectionTypeNode ? '&' : '|', $items);
        }
        if ($node instanceof InvalidTypeNode) {
            return (string) $node;
        }
        if ($node instanceof NullableTypeNode) {
            if ($node->type instanceof IntersectionTypeNode || $node->type instanceof UnionTypeNode) {
                return '?(' . $this->printType($node->type) . ')';
            }
            return '?' . $this->printType($node->type);
        }
        if ($node instanceof ObjectShapeNode) {
            $items = array_map(fn(ObjectShapeItemNode $item): string => $this->print($item), $node->items);
            return 'object{' . implode(', ', $items) . '}';
        }
        if ($node instanceof OffsetAccessTypeNode) {
            return $this->printOffsetAccessType($node->type) . '[' . $this->printType($node->offset) . ']';
        }
        if ($node instanceof ThisTypeNode) {
            return (string) $node;
        }
        throw new LogicException(sprintf('Unknown node type %s', get_class($node)));
    }
    private function wrapInParentheses(TypeNode $node): string
    {
        return '(' . $this->printType($node) . ')';
    }
    private function printOffsetAccessType(TypeNode $type): string
    {
        if ($type instanceof CallableTypeNode || $type instanceof UnionTypeNode || $type instanceof IntersectionTypeNode || $type instanceof NullableTypeNode) {
            return $this->wrapInParentheses($type);
        }
        return $this->printType($type);
    }
    private function printConstExpr(ConstExprNode $node): string
    {
        // this is fine - ConstExprNode classes do not contain nodes that need smart printer logic
        return (string) $node;
    }
    /**
     * @param Node[] $nodes
     * @param Node[] $originalNodes
     */
    private function printArrayFormatPreserving(array $nodes, array $originalNodes, TokenIterator $originalTokens, int &$tokenIndex, string $parentNodeClass, string $subNodeName): ?string
    {
        $diff = $this->differ->diffWithReplacements($originalNodes, $nodes);
        $mapKey = $parentNodeClass . '->' . $subNodeName;
        $insertStr = $this->listInsertionMap[$mapKey] ?? null;
        $result = '';
        $beforeFirstKeepOrReplace = \true;
        $delayedAdd = [];
        $insertNewline = \false;
        [$isMultiline, $beforeAsteriskIndent, $afterAsteriskIndent] = $this->isMultiline($tokenIndex, $originalNodes, $originalTokens);
        if ($insertStr === "\n * ") {
            $insertStr = sprintf('%s%s*%s', $originalTokens->getDetectedNewline() ?? "\n", $beforeAsteriskIndent, $afterAsteriskIndent);
        }
        foreach ($diff as $i => $diffElem) {
            $diffType = $diffElem->type;
            $arrItem = $diffElem->new;
            $origArrayItem = $diffElem->old;
            if ($diffType === DiffElem::TYPE_KEEP || $diffType === DiffElem::TYPE_REPLACE) {
                $beforeFirstKeepOrReplace = \false;
                if (!$arrItem instanceof Node || !$origArrayItem instanceof Node) {
                    return null;
                }
                /** @var int $itemStartPos */
                $itemStartPos = $origArrayItem->getAttribute(Attribute::START_INDEX);
                /** @var int $itemEndPos */
                $itemEndPos = $origArrayItem->getAttribute(Attribute::END_INDEX);
                if ($itemStartPos < 0 || $itemEndPos < 0 || $itemStartPos < $tokenIndex) {
                    throw new LogicException();
                }
                $comments = $arrItem->getAttribute(Attribute::COMMENTS) ?? [];
                $origComments = $origArrayItem->getAttribute(Attribute::COMMENTS) ?? [];
                $commentStartPos = count($origComments) > 0 ? $origComments[0]->startIndex : $itemStartPos;
                assert($commentStartPos >= 0);
                $result .= $originalTokens->getContentBetween($tokenIndex, $itemStartPos);
                if (count($delayedAdd) > 0) {
                    foreach ($delayedAdd as $delayedAddNode) {
                        $parenthesesNeeded = isset($this->parenthesesListMap[$mapKey]) && in_array(get_class($delayedAddNode), $this->parenthesesListMap[$mapKey], \true);
                        if ($parenthesesNeeded) {
                            $result .= '(';
                        }
                        if ($insertNewline) {
                            $delayedAddComments = $delayedAddNode->getAttribute(Attribute::COMMENTS) ?? [];
                            if (count($delayedAddComments) > 0) {
                                $result .= $this->printComments($delayedAddComments, $beforeAsteriskIndent, $afterAsteriskIndent);
                                $result .= sprintf('%s%s*%s', $originalTokens->getDetectedNewline() ?? "\n", $beforeAsteriskIndent, $afterAsteriskIndent);
                            }
                        }
                        $result .= $this->printNodeFormatPreserving($delayedAddNode, $originalTokens);
                        if ($parenthesesNeeded) {
                            $result .= ')';
                        }
                        if ($insertNewline) {
                            $result .= $insertStr . sprintf('%s%s*%s', $originalTokens->getDetectedNewline() ?? "\n", $beforeAsteriskIndent, $afterAsteriskIndent);
                        } else {
                            $result .= $insertStr;
                        }
                    }
                    $delayedAdd = [];
                }
                $parenthesesNeeded = isset($this->parenthesesListMap[$mapKey]) && in_array(get_class($arrItem), $this->parenthesesListMap[$mapKey], \true) && !in_array(get_class($origArrayItem), $this->parenthesesListMap[$mapKey], \true);
                $addParentheses = $parenthesesNeeded && !$originalTokens->hasParentheses($itemStartPos, $itemEndPos);
                if ($addParentheses) {
                    $result .= '(';
                }
                if ($comments !== $origComments) {
                    if (count($comments) > 0) {
                        $result .= $this->printComments($comments, $beforeAsteriskIndent, $afterAsteriskIndent);
                        $result .= sprintf('%s%s*%s', $originalTokens->getDetectedNewline() ?? "\n", $beforeAsteriskIndent, $afterAsteriskIndent);
                    }
                }
                $result .= $this->printNodeFormatPreserving($arrItem, $originalTokens);
                if ($addParentheses) {
                    $result .= ')';
                }
                $tokenIndex = $itemEndPos + 1;
            } elseif ($diffType === DiffElem::TYPE_ADD) {
                if ($insertStr === null) {
                    return null;
                }
                if (!$arrItem instanceof Node) {
                    return null;
                }
                if ($insertStr === ', ' && $isMultiline || count($arrItem->getAttribute(Attribute::COMMENTS) ?? []) > 0) {
                    $insertStr = ',';
                    $insertNewline = \true;
                }
                if ($beforeFirstKeepOrReplace) {
                    // Will be inserted at the next "replace" or "keep" element
                    $delayedAdd[] = $arrItem;
                    continue;
                }
                /** @var int $itemEndPos */
                $itemEndPos = $tokenIndex - 1;
                if ($insertNewline) {
                    $comments = $arrItem->getAttribute(Attribute::COMMENTS) ?? [];
                    $result .= $insertStr;
                    if (count($comments) > 0) {
                        $result .= sprintf('%s%s*%s', $originalTokens->getDetectedNewline() ?? "\n", $beforeAsteriskIndent, $afterAsteriskIndent);
                        $result .= $this->printComments($comments, $beforeAsteriskIndent, $afterAsteriskIndent);
                    }
                    $result .= sprintf('%s%s*%s', $originalTokens->getDetectedNewline() ?? "\n", $beforeAsteriskIndent, $afterAsteriskIndent);
                } else {
                    $result .= $insertStr;
                }
                $parenthesesNeeded = isset($this->parenthesesListMap[$mapKey]) && in_array(get_class($arrItem), $this->parenthesesListMap[$mapKey], \true);
                if ($parenthesesNeeded) {
                    $result .= '(';
                }
                $result .= $this->printNodeFormatPreserving($arrItem, $originalTokens);
                if ($parenthesesNeeded) {
                    $result .= ')';
                }
                $tokenIndex = $itemEndPos + 1;
            } elseif ($diffType === DiffElem::TYPE_REMOVE) {
                if (!$origArrayItem instanceof Node) {
                    return null;
                }
                /** @var int $itemStartPos */
                $itemStartPos = $origArrayItem->getAttribute(Attribute::START_INDEX);
                /** @var int $itemEndPos */
                $itemEndPos = $origArrayItem->getAttribute(Attribute::END_INDEX);
                if ($itemStartPos < 0 || $itemEndPos < 0) {
                    throw new LogicException();
                }
                if ($i === 0) {
                    // If we're removing from the start, keep the tokens before the node and drop those after it,
                    // instead of the other way around.
                    $originalTokensArray = $originalTokens->getTokens();
                    for ($j = $tokenIndex; $j < $itemStartPos; $j++) {
                        if ($originalTokensArray[$j][Lexer::TYPE_OFFSET] === Lexer::TOKEN_PHPDOC_EOL) {
                            break;
                        }
                        $result .= $originalTokensArray[$j][Lexer::VALUE_OFFSET];
                    }
                }
                $tokenIndex = $itemEndPos + 1;
            }
        }
        if (count($delayedAdd) > 0) {
            if (!isset($this->emptyListInsertionMap[$mapKey])) {
                return null;
            }
            [$findToken, $extraLeft, $extraRight] = $this->emptyListInsertionMap[$mapKey];
            if ($findToken !== null) {
                $originalTokensArray = $originalTokens->getTokens();
                for (; $tokenIndex < count($originalTokensArray); $tokenIndex++) {
                    $result .= $originalTokensArray[$tokenIndex][Lexer::VALUE_OFFSET];
                    if ($originalTokensArray[$tokenIndex][Lexer::VALUE_OFFSET] !== $findToken) {
                        continue;
                    }
                    $tokenIndex++;
                    break;
                }
            }
            $first = \true;
            $result .= $extraLeft;
            foreach ($delayedAdd as $delayedAddNode) {
                if (!$first) {
                    $result .= $insertStr;
                    if ($insertNewline) {
                        $result .= sprintf('%s%s*%s', $originalTokens->getDetectedNewline() ?? "\n", $beforeAsteriskIndent, $afterAsteriskIndent);
                    }
                }
                $result .= $this->printNodeFormatPreserving($delayedAddNode, $originalTokens);
                $first = \false;
            }
            $result .= $extraRight;
        }
        return $result;
    }
    /**
     * @param list<Comment> $comments
     */
    private function printComments(array $comments, string $beforeAsteriskIndent, string $afterAsteriskIndent): string
    {
        $formattedComments = [];
        foreach ($comments as $comment) {
            $formattedComments[] = str_replace("\n", "\n" . $beforeAsteriskIndent . '*' . $afterAsteriskIndent, $comment->getReformattedText());
        }
        return implode("\n{$beforeAsteriskIndent}*{$afterAsteriskIndent}", $formattedComments);
    }
    /**
     * @param array<Node|null> $nodes
     * @return array{bool, string, string}
     */
    private function isMultiline(int $initialIndex, array $nodes, TokenIterator $originalTokens): array
    {
        $isMultiline = count($nodes) > 1;
        $pos = $initialIndex;
        $allText = '';
        /** @var Node|null $node */
        foreach ($nodes as $node) {
            if (!$node instanceof Node) {
                continue;
            }
            $endPos = $node->getAttribute(Attribute::END_INDEX) + 1;
            $text = $originalTokens->getContentBetween($pos, $endPos);
            $allText .= $text;
            if (strpos($text, "\n") === \false) {
                // We require that a newline is present between *every* item. If the formatting
                // is inconsistent, with only some items having newlines, we don't consider it
                // as multiline
                $isMultiline = \false;
            }
            $pos = $endPos;
        }
        $c = preg_match_all('~\n(?<before>[\x09\x20]*)\*(?<after>\x20*)~', $allText, $matches, PREG_SET_ORDER);
        if ($c === 0) {
            return [$isMultiline, ' ', '  '];
        }
        $before = '';
        $after = '';
        foreach ($matches as $match) {
            if (strlen($match['before']) > strlen($before)) {
                $before = $match['before'];
            }
            if (strlen($match['after']) <= strlen($after)) {
                continue;
            }
            $after = $match['after'];
        }
        $before = strlen($before) === 0 ? ' ' : $before;
        $after = strlen($after) === 0 ? '  ' : $after;
        return [$isMultiline, $before, $after];
    }
    private function printNodeFormatPreserving(Node $node, TokenIterator $originalTokens): string
    {
        /** @var Node|null $originalNode */
        $originalNode = $node->getAttribute(Attribute::ORIGINAL_NODE);
        if ($originalNode === null) {
            return $this->print($node);
        }
        $class = get_class($node);
        if ($class !== get_class($originalNode)) {
            throw new LogicException();
        }
        $startPos = $originalNode->getAttribute(Attribute::START_INDEX);
        $endPos = $originalNode->getAttribute(Attribute::END_INDEX);
        if ($startPos < 0 || $endPos < 0) {
            throw new LogicException();
        }
        $result = '';
        $pos = $startPos;
        $subNodeNames = array_keys(get_object_vars($node));
        foreach ($subNodeNames as $subNodeName) {
            $subNode = $node->{$subNodeName};
            $origSubNode = $originalNode->{$subNodeName};
            if (!$subNode instanceof Node && $subNode !== null || !$origSubNode instanceof Node && $origSubNode !== null) {
                if ($subNode === $origSubNode) {
                    // Unchanged, can reuse old code
                    continue;
                }
                if (is_array($subNode) && is_array($origSubNode)) {
                    // Array subnode changed, we might be able to reconstruct it
                    $listResult = $this->printArrayFormatPreserving($subNode, $origSubNode, $originalTokens, $pos, $class, $subNodeName);
                    if ($listResult === null) {
                        return $this->print($node);
                    }
                    $result .= $listResult;
                    continue;
                }
                return $this->print($node);
            }
            if ($origSubNode === null) {
                if ($subNode === null) {
                    // Both null, nothing to do
                    continue;
                }
                return $this->print($node);
            }
            $subStartPos = $origSubNode->getAttribute(Attribute::START_INDEX);
            $subEndPos = $origSubNode->getAttribute(Attribute::END_INDEX);
            if ($subStartPos < 0 || $subEndPos < 0) {
                throw new LogicException();
            }
            if ($subEndPos < $subStartPos) {
                return $this->print($node);
            }
            if ($subNode === null) {
                return $this->print($node);
            }
            $result .= $originalTokens->getContentBetween($pos, $subStartPos);
            $mapKey = get_class($node) . '->' . $subNodeName;
            $parenthesesNeeded = isset($this->parenthesesMap[$mapKey]) && in_array(get_class($subNode), $this->parenthesesMap[$mapKey], \true);
            if ($subNode->getAttribute(Attribute::ORIGINAL_NODE) !== null) {
                $parenthesesNeeded = $parenthesesNeeded && !in_array(get_class($subNode->getAttribute(Attribute::ORIGINAL_NODE)), $this->parenthesesMap[$mapKey], \true);
            }
            $addParentheses = $parenthesesNeeded && !$originalTokens->hasParentheses($subStartPos, $subEndPos);
            if ($addParentheses) {
                $result .= '(';
            }
            $result .= $this->printNodeFormatPreserving($subNode, $originalTokens);
            if ($addParentheses) {
                $result .= ')';
            }
            $pos = $subEndPos + 1;
        }
        return $result . $originalTokens->getContentBetween($pos, $endPos + 1);
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\PHPStan\PhpDocParser\Parser;

use Exception;
use _ContaoManager\PHPStan\PhpDocParser\Lexer\Lexer;
use function assert;
use function json_encode;
use function sprintf;
use const JSON_INVALID_UTF8_SUBSTITUTE;
use const JSON_UNESCAPED_SLASHES;
use const JSON_UNESCAPED_UNICODE;
class ParserException extends Exception
{
    private string $currentTokenValue;
    private int $currentTokenType;
    private int $currentOffset;
    private int $expectedTokenType;
    private ?string $expectedTokenValue;
    private ?int $currentTokenLine;
    public function __construct(string $currentTokenValue, int $currentTokenType, int $currentOffset, int $expectedTokenType, ?string $expectedTokenValue, ?int $currentTokenLine)
    {
        $this->currentTokenValue = $currentTokenValue;
        $this->currentTokenType = $currentTokenType;
        $this->currentOffset = $currentOffset;
        $this->expectedTokenType = $expectedTokenType;
        $this->expectedTokenValue = $expectedTokenValue;
        $this->currentTokenLine = $currentTokenLine;
        parent::__construct(sprintf('Unexpected token %s, expected %s%s at offset %d%s', $this->formatValue($currentTokenValue), Lexer::TOKEN_LABELS[$expectedTokenType], $expectedTokenValue !== null ? sprintf(' (%s)', $this->formatValue($expectedTokenValue)) : '', $currentOffset, $currentTokenLine === null ? '' : sprintf(' on line %d', $currentTokenLine)));
    }
    public function getCurrentTokenValue(): string
    {
        return $this->currentTokenValue;
    }
    public function getCurrentTokenType(): int
    {
        return $this->currentTokenType;
    }
    public function getCurrentOffset(): int
    {
        return $this->currentOffset;
    }
    public function getExpectedTokenType(): int
    {
        return $this->expectedTokenType;
    }
    public function getExpectedTokenValue(): ?string
    {
        return $this->expectedTokenValue;
    }
    public function getCurrentTokenLine(): ?int
    {
        return $this->currentTokenLine;
    }
    private function formatValue(string $value): string
    {
        $json = json_encode($value, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES | JSON_INVALID_UTF8_SUBSTITUTE);
        assert($json !== \false);
        return $json;
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\PHPStan\PhpDocParser\Parser;

use LogicException;
use _ContaoManager\PHPStan\PhpDocParser\Ast;
use _ContaoManager\PHPStan\PhpDocParser\Ast\ConstExpr\ConstExprIntegerNode;
use _ContaoManager\PHPStan\PhpDocParser\Ast\ConstExpr\ConstExprStringNode;
use _ContaoManager\PHPStan\PhpDocParser\Ast\ConstExpr\ConstFetchNode;
use _ContaoManager\PHPStan\PhpDocParser\Ast\PhpDoc\Doctrine;
use _ContaoManager\PHPStan\PhpDocParser\Ast\Type\IdentifierTypeNode;
use _ContaoManager\PHPStan\PhpDocParser\Lexer\Lexer;
use _ContaoManager\PHPStan\PhpDocParser\ParserConfig;
use _ContaoManager\PHPStan\ShouldNotHappenException;
use function array_key_exists;
use function count;
use function rtrim;
use function str_replace;
use function trim;
/**
 * @phpstan-import-type ValueType from Doctrine\DoctrineArgument as DoctrineValueType
 */
class PhpDocParser
{
    private const DISALLOWED_DESCRIPTION_START_TOKENS = [Lexer::TOKEN_UNION, Lexer::TOKEN_INTERSECTION];
    private ParserConfig $config;
    private TypeParser $typeParser;
    private ConstExprParser $constantExprParser;
    private ConstExprParser $doctrineConstantExprParser;
    public function __construct(ParserConfig $config, TypeParser $typeParser, ConstExprParser $constantExprParser)
    {
        $this->config = $config;
        $this->typeParser = $typeParser;
        $this->constantExprParser = $constantExprParser;
        $this->doctrineConstantExprParser = $constantExprParser->toDoctrine();
    }
    public function parse(TokenIterator $tokens): Ast\PhpDoc\PhpDocNode
    {
        $tokens->consumeTokenType(Lexer::TOKEN_OPEN_PHPDOC);
        $tokens->tryConsumeTokenType(Lexer::TOKEN_PHPDOC_EOL);
        $children = [];
        if (!$tokens->isCurrentTokenType(Lexer::TOKEN_CLOSE_PHPDOC)) {
            $lastChild = $this->parseChild($tokens);
            $children[] = $lastChild;
            while (!$tokens->isCurrentTokenType(Lexer::TOKEN_CLOSE_PHPDOC)) {
                if ($lastChild instanceof Ast\PhpDoc\PhpDocTagNode && ($lastChild->value instanceof Doctrine\DoctrineTagValueNode || $lastChild->value instanceof Ast\PhpDoc\GenericTagValueNode)) {
                    $tokens->tryConsumeTokenType(Lexer::TOKEN_PHPDOC_EOL);
                    if ($tokens->isCurrentTokenType(Lexer::TOKEN_CLOSE_PHPDOC)) {
                        break;
                    }
                    $lastChild = $this->parseChild($tokens);
                    $children[] = $lastChild;
                    continue;
                }
                if (!$tokens->tryConsumeTokenType(Lexer::TOKEN_PHPDOC_EOL)) {
                    break;
                }
                if ($tokens->isCurrentTokenType(Lexer::TOKEN_CLOSE_PHPDOC)) {
                    break;
                }
                $lastChild = $this->parseChild($tokens);
                $children[] = $lastChild;
            }
        }
        try {
            $tokens->consumeTokenType(Lexer::TOKEN_CLOSE_PHPDOC);
        } catch (ParserException $e) {
            $name = '';
            $startLine = $tokens->currentTokenLine();
            $startIndex = $tokens->currentTokenIndex();
            if (count($children) > 0) {
                $lastChild = $children[count($children) - 1];
                if ($lastChild instanceof Ast\PhpDoc\PhpDocTagNode) {
                    $name = $lastChild->name;
                    $startLine = $tokens->currentTokenLine();
                    $startIndex = $tokens->currentTokenIndex();
                }
            }
            $tag = new Ast\PhpDoc\PhpDocTagNode($name, $this->enrichWithAttributes($tokens, new Ast\PhpDoc\InvalidTagValueNode($e->getMessage(), $e), $startLine, $startIndex));
            $tokens->forwardToTheEnd();
            $comments = $tokens->flushComments();
            if ($comments !== []) {
                throw new LogicException('Comments should already be flushed');
            }
            return $this->enrichWithAttributes($tokens, new Ast\PhpDoc\PhpDocNode([$this->enrichWithAttributes($tokens, $tag, $startLine, $startIndex)]), 1, 0);
        }
        $comments = $tokens->flushComments();
        if ($comments !== []) {
            throw new LogicException('Comments should already be flushed');
        }
        return $this->enrichWithAttributes($tokens, new Ast\PhpDoc\PhpDocNode($children), 1, 0);
    }
    /** @phpstan-impure */
    private function parseChild(TokenIterator $tokens): Ast\PhpDoc\PhpDocChildNode
    {
        if ($tokens->isCurrentTokenType(Lexer::TOKEN_PHPDOC_TAG)) {
            $startLine = $tokens->currentTokenLine();
            $startIndex = $tokens->currentTokenIndex();
            return $this->enrichWithAttributes($tokens, $this->parseTag($tokens), $startLine, $startIndex);
        }
        if ($tokens->isCurrentTokenType(Lexer::TOKEN_DOCTRINE_TAG)) {
            $startLine = $tokens->currentTokenLine();
            $startIndex = $tokens->currentTokenIndex();
            $tag = $tokens->currentTokenValue();
            $tokens->next();
            $tagStartLine = $tokens->currentTokenLine();
            $tagStartIndex = $tokens->currentTokenIndex();
            return $this->enrichWithAttributes($tokens, new Ast\PhpDoc\PhpDocTagNode($tag, $this->enrichWithAttributes($tokens, $this->parseDoctrineTagValue($tokens, $tag), $tagStartLine, $tagStartIndex)), $startLine, $startIndex);
        }
        $startLine = $tokens->currentTokenLine();
        $startIndex = $tokens->currentTokenIndex();
        $text = $this->parseText($tokens);
        return $this->enrichWithAttributes($tokens, $text, $startLine, $startIndex);
    }
    /**
     * @template T of Ast\Node
     * @param T $tag
     * @return T
     */
    private function enrichWithAttributes(TokenIterator $tokens, Ast\Node $tag, int $startLine, int $startIndex): Ast\Node
    {
        if ($this->config->useLinesAttributes) {
            $tag->setAttribute(Ast\Attribute::START_LINE, $startLine);
            $tag->setAttribute(Ast\Attribute::END_LINE, $tokens->currentTokenLine());
        }
        if ($this->config->useIndexAttributes) {
            $tag->setAttribute(Ast\Attribute::START_INDEX, $startIndex);
            $tag->setAttribute(Ast\Attribute::END_INDEX, $tokens->endIndexOfLastRelevantToken());
        }
        return $tag;
    }
    private function parseText(TokenIterator $tokens): Ast\PhpDoc\PhpDocTextNode
    {
        $text = '';
        $endTokens = [Lexer::TOKEN_CLOSE_PHPDOC, Lexer::TOKEN_END];
        $savepoint = \false;
        // if the next token is EOL, everything below is skipped and empty string is returned
        while (\true) {
            $tmpText = $tokens->getSkippedHorizontalWhiteSpaceIfAny() . $tokens->joinUntil(Lexer::TOKEN_PHPDOC_EOL, ...$endTokens);
            $text .= $tmpText;
            // stop if we're not at EOL - meaning it's the end of PHPDoc
            if (!$tokens->isCurrentTokenType(Lexer::TOKEN_PHPDOC_EOL, Lexer::TOKEN_CLOSE_PHPDOC)) {
                break;
            }
            if (!$savepoint) {
                $tokens->pushSavePoint();
                $savepoint = \true;
            } elseif ($tmpText !== '') {
                $tokens->dropSavePoint();
                $tokens->pushSavePoint();
            }
            $tokens->pushSavePoint();
            $tokens->next();
            // if we're at EOL, check what's next
            // if next is a PHPDoc tag, EOL, or end of PHPDoc, stop
            if ($tokens->isCurrentTokenType(Lexer::TOKEN_PHPDOC_TAG, Lexer::TOKEN_DOCTRINE_TAG, ...$endTokens)) {
                $tokens->rollback();
                break;
            }
            // otherwise if the next is text, continue building the description string
            $tokens->dropSavePoint();
            $text .= $tokens->getDetectedNewline() ?? "\n";
        }
        if ($savepoint) {
            $tokens->rollback();
            $text = rtrim($text, $tokens->getDetectedNewline() ?? "\n");
        }
        return new Ast\PhpDoc\PhpDocTextNode(trim($text, " \t"));
    }
    private function parseOptionalDescriptionAfterDoctrineTag(TokenIterator $tokens): string
    {
        $text = '';
        $endTokens = [Lexer::TOKEN_CLOSE_PHPDOC, Lexer::TOKEN_END];
        $savepoint = \false;
        // if the next token is EOL, everything below is skipped and empty string is returned
        while (\true) {
            $tmpText = $tokens->getSkippedHorizontalWhiteSpaceIfAny() . $tokens->joinUntil(Lexer::TOKEN_PHPDOC_TAG, Lexer::TOKEN_DOCTRINE_TAG, Lexer::TOKEN_PHPDOC_EOL, ...$endTokens);
            $text .= $tmpText;
            // stop if we're not at EOL - meaning it's the end of PHPDoc
            if (!$tokens->isCurrentTokenType(Lexer::TOKEN_PHPDOC_EOL, Lexer::TOKEN_CLOSE_PHPDOC)) {
                if (!$tokens->isPrecededByHorizontalWhitespace()) {
                    return trim($text . $this->parseText($tokens)->text, " \t");
                }
                if ($tokens->isCurrentTokenType(Lexer::TOKEN_PHPDOC_TAG)) {
                    $tokens->pushSavePoint();
                    $child = $this->parseChild($tokens);
                    if ($child instanceof Ast\PhpDoc\PhpDocTagNode) {
                        if ($child->value instanceof Ast\PhpDoc\GenericTagValueNode || $child->value instanceof Doctrine\DoctrineTagValueNode) {
                            $tokens->rollback();
                            break;
                        }
                        if ($child->value instanceof Ast\PhpDoc\InvalidTagValueNode) {
                            $tokens->rollback();
                            $tokens->pushSavePoint();
                            $tokens->next();
                            if ($tokens->isCurrentTokenType(Lexer::TOKEN_OPEN_PARENTHESES)) {
                                $tokens->rollback();
                                break;
                            }
                            $tokens->rollback();
                            return trim($text . $this->parseText($tokens)->text, " \t");
                        }
                    }
                    $tokens->rollback();
                    return trim($text . $this->parseText($tokens)->text, " \t");
                }
                break;
            }
            if (!$savepoint) {
                $tokens->pushSavePoint();
                $savepoint = \true;
            } elseif ($tmpText !== '') {
                $tokens->dropSavePoint();
                $tokens->pushSavePoint();
            }
            $tokens->pushSavePoint();
            $tokens->next();
            // if we're at EOL, check what's next
            // if next is a PHPDoc tag, EOL, or end of PHPDoc, stop
            if ($tokens->isCurrentTokenType(Lexer::TOKEN_PHPDOC_TAG, Lexer::TOKEN_DOCTRINE_TAG, ...$endTokens)) {
                $tokens->rollback();
                break;
            }
            // otherwise if the next is text, continue building the description string
            $tokens->dropSavePoint();
            $text .= $tokens->getDetectedNewline() ?? "\n";
        }
        if ($savepoint) {
            $tokens->rollback();
            $text = rtrim($text, $tokens->getDetectedNewline() ?? "\n");
        }
        return trim($text, " \t");
    }
    public function parseTag(TokenIterator $tokens): Ast\PhpDoc\PhpDocTagNode
    {
        $tag = $tokens->currentTokenValue();
        $tokens->next();
        $value = $this->parseTagValue($tokens, $tag);
        return new Ast\PhpDoc\PhpDocTagNode($tag, $value);
    }
    public function parseTagValue(TokenIterator $tokens, string $tag): Ast\PhpDoc\PhpDocTagValueNode
    {
        $startLine = $tokens->currentTokenLine();
        $startIndex = $tokens->currentTokenIndex();
        try {
            $tokens->pushSavePoint();
            switch ($tag) {
                case '@param':
                case '@phpstan-param':
                case '@psalm-param':
                case '@phan-param':
                    $tagValue = $this->parseParamTagValue($tokens);
                    break;
                case '@param-immediately-invoked-callable':
                case '@phpstan-param-immediately-invoked-callable':
                    $tagValue = $this->parseParamImmediatelyInvokedCallableTagValue($tokens);
                    break;
                case '@param-later-invoked-callable':
                case '@phpstan-param-later-invoked-callable':
                    $tagValue = $this->parseParamLaterInvokedCallableTagValue($tokens);
                    break;
                case '@param-closure-this':
                case '@phpstan-param-closure-this':
                    $tagValue = $this->parseParamClosureThisTagValue($tokens);
                    break;
                case '@pure-unless-callable-is-impure':
                case '@phpstan-pure-unless-callable-is-impure':
                    $tagValue = $this->parsePureUnlessCallableIsImpureTagValue($tokens);
                    break;
                case '@var':
                case '@phpstan-var':
                case '@psalm-var':
                case '@phan-var':
                    $tagValue = $this->parseVarTagValue($tokens);
                    break;
                case '@return':
                case '@phpstan-return':
                case '@psalm-return':
                case '@phan-return':
                case '@phan-real-return':
                    $tagValue = $this->parseReturnTagValue($tokens);
                    break;
                case '@throws':
                case '@phpstan-throws':
                    $tagValue = $this->parseThrowsTagValue($tokens);
                    break;
                case '@mixin':
                case '@phan-mixin':
                    $tagValue = $this->parseMixinTagValue($tokens);
                    break;
                case '@psalm-require-extends':
                case '@phpstan-require-extends':
                    $tagValue = $this->parseRequireExtendsTagValue($tokens);
                    break;
                case '@psalm-require-implements':
                case '@phpstan-require-implements':
                    $tagValue = $this->parseRequireImplementsTagValue($tokens);
                    break;
                case '@psalm-inheritors':
                case '@phpstan-sealed':
                    $tagValue = $this->parseSealedTagValue($tokens);
                    break;
                case '@deprecated':
                    $tagValue = $this->parseDeprecatedTagValue($tokens);
                    break;
                case '@property':
                case '@property-read':
                case '@property-write':
                case '@phpstan-property':
                case '@phpstan-property-read':
                case '@phpstan-property-write':
                case '@psalm-property':
                case '@psalm-property-read':
                case '@psalm-property-write':
                case '@phan-property':
                case '@phan-property-read':
                case '@phan-property-write':
                    $tagValue = $this->parsePropertyTagValue($tokens);
                    break;
                case '@method':
                case '@phpstan-method':
                case '@psalm-method':
                case '@phan-method':
                    $tagValue = $this->parseMethodTagValue($tokens);
                    break;
                case '@template':
                case '@phpstan-template':
                case '@psalm-template':
                case '@phan-template':
                case '@template-covariant':
                case '@phpstan-template-covariant':
                case '@psalm-template-covariant':
                case '@template-contravariant':
                case '@phpstan-template-contravariant':
                case '@psalm-template-contravariant':
                    $tagValue = $this->typeParser->parseTemplateTagValue($tokens, fn($tokens) => $this->parseOptionalDescription($tokens, \true));
                    break;
                case '@extends':
                case '@phpstan-extends':
                case '@phan-extends':
                case '@phan-inherits':
                case '@template-extends':
                    $tagValue = $this->parseExtendsTagValue('@extends', $tokens);
                    break;
                case '@implements':
                case '@phpstan-implements':
                case '@template-implements':
                    $tagValue = $this->parseExtendsTagValue('@implements', $tokens);
                    break;
                case '@use':
                case '@phpstan-use':
                case '@template-use':
                    $tagValue = $this->parseExtendsTagValue('@use', $tokens);
                    break;
                case '@phpstan-type':
                case '@psalm-type':
                case '@phan-type':
                    $tagValue = $this->parseTypeAliasTagValue($tokens);
                    break;
                case '@phpstan-import-type':
                case '@psalm-import-type':
                    $tagValue = $this->parseTypeAliasImportTagValue($tokens);
                    break;
                case '@phpstan-assert':
                case '@phpstan-assert-if-true':
                case '@phpstan-assert-if-false':
                case '@psalm-assert':
                case '@psalm-assert-if-true':
                case '@psalm-assert-if-false':
                case '@phan-assert':
                case '@phan-assert-if-true':
                case '@phan-assert-if-false':
                    $tagValue = $this->parseAssertTagValue($tokens);
                    break;
                case '@phpstan-this-out':
                case '@phpstan-self-out':
                case '@psalm-this-out':
                case '@psalm-self-out':
                    $tagValue = $this->parseSelfOutTagValue($tokens);
                    break;
                case '@param-out':
                case '@phpstan-param-out':
                case '@psalm-param-out':
                    $tagValue = $this->parseParamOutTagValue($tokens);
                    break;
                default:
                    if ($tokens->isCurrentTokenType(Lexer::TOKEN_OPEN_PARENTHESES)) {
                        $tagValue = $this->parseDoctrineTagValue($tokens, $tag);
                    } else {
                        $tagValue = new Ast\PhpDoc\GenericTagValueNode($this->parseOptionalDescriptionAfterDoctrineTag($tokens));
                    }
                    break;
            }
            $tokens->dropSavePoint();
        } catch (ParserException $e) {
            $tokens->rollback();
            $tagValue = new Ast\PhpDoc\InvalidTagValueNode($this->parseOptionalDescription($tokens, \false), $e);
        }
        return $this->enrichWithAttributes($tokens, $tagValue, $startLine, $startIndex);
    }
    private function parseDoctrineTagValue(TokenIterator $tokens, string $tag): Ast\PhpDoc\PhpDocTagValueNode
    {
        $startLine = $tokens->currentTokenLine();
        $startIndex = $tokens->currentTokenIndex();
        return new Doctrine\DoctrineTagValueNode($this->enrichWithAttributes($tokens, new Doctrine\DoctrineAnnotation($tag, $this->parseDoctrineArguments($tokens, \false)), $startLine, $startIndex), $this->parseOptionalDescriptionAfterDoctrineTag($tokens));
    }
    /**
     * @return list<Doctrine\DoctrineArgument>
     */
    private function parseDoctrineArguments(TokenIterator $tokens, bool $deep): array
    {
        if (!$tokens->isCurrentTokenType(Lexer::TOKEN_OPEN_PARENTHESES)) {
            return [];
        }
        if (!$deep) {
            $tokens->addEndOfLineToSkippedTokens();
        }
        $arguments = [];
        try {
            $tokens->consumeTokenType(Lexer::TOKEN_OPEN_PARENTHESES);
            do {
                if ($tokens->isCurrentTokenType(Lexer::TOKEN_CLOSE_PARENTHESES)) {
                    break;
                }
                $arguments[] = $this->parseDoctrineArgument($tokens);
            } while ($tokens->tryConsumeTokenType(Lexer::TOKEN_COMMA));
        } finally {
            if (!$deep) {
                $tokens->removeEndOfLineFromSkippedTokens();
            }
        }
        $tokens->consumeTokenType(Lexer::TOKEN_CLOSE_PARENTHESES);
        return $arguments;
    }
    private function parseDoctrineArgument(TokenIterator $tokens): Doctrine\DoctrineArgument
    {
        if (!$tokens->isCurrentTokenType(Lexer::TOKEN_IDENTIFIER)) {
            $startLine = $tokens->currentTokenLine();
            $startIndex = $tokens->currentTokenIndex();
            return $this->enrichWithAttributes($tokens, new Doctrine\DoctrineArgument(null, $this->parseDoctrineArgumentValue($tokens)), $startLine, $startIndex);
        }
        $startLine = $tokens->currentTokenLine();
        $startIndex = $tokens->currentTokenIndex();
        try {
            $tokens->pushSavePoint();
            $currentValue = $tokens->currentTokenValue();
            $tokens->consumeTokenType(Lexer::TOKEN_IDENTIFIER);
            $key = $this->enrichWithAttributes($tokens, new IdentifierTypeNode($currentValue), $startLine, $startIndex);
            $tokens->consumeTokenType(Lexer::TOKEN_EQUAL);
            $value = $this->parseDoctrineArgumentValue($tokens);
            $tokens->dropSavePoint();
            return $this->enrichWithAttributes($tokens, new Doctrine\DoctrineArgument($key, $value), $startLine, $startIndex);
        } catch (ParserException $e) {
            $tokens->rollback();
            return $this->enrichWithAttributes($tokens, new Doctrine\DoctrineArgument(null, $this->parseDoctrineArgumentValue($tokens)), $startLine, $startIndex);
        }
    }
    /**
     * @return DoctrineValueType
     */
    private function parseDoctrineArgumentValue(TokenIterator $tokens)
    {
        $startLine = $tokens->currentTokenLine();
        $startIndex = $tokens->currentTokenIndex();
        if ($tokens->isCurrentTokenType(Lexer::TOKEN_PHPDOC_TAG, Lexer::TOKEN_DOCTRINE_TAG)) {
            $name = $tokens->currentTokenValue();
            $tokens->next();
            return $this->enrichWithAttributes($tokens, new Doctrine\DoctrineAnnotation($name, $this->parseDoctrineArguments($tokens, \true)), $startLine, $startIndex);
        }
        if ($tokens->tryConsumeTokenType(Lexer::TOKEN_OPEN_CURLY_BRACKET)) {
            $items = [];
            do {
                if ($tokens->isCurrentTokenType(Lexer::TOKEN_CLOSE_CURLY_BRACKET)) {
                    break;
                }
                $items[] = $this->parseDoctrineArrayItem($tokens);
            } while ($tokens->tryConsumeTokenType(Lexer::TOKEN_COMMA));
            $tokens->consumeTokenType(Lexer::TOKEN_CLOSE_CURLY_BRACKET);
            return $this->enrichWithAttributes($tokens, new Doctrine\DoctrineArray($items), $startLine, $startIndex);
        }
        $currentTokenValue = $tokens->currentTokenValue();
        $tokens->pushSavePoint();
        // because of ConstFetchNode
        if ($tokens->tryConsumeTokenType(Lexer::TOKEN_IDENTIFIER)) {
            $identifier = $this->enrichWithAttributes($tokens, new Ast\Type\IdentifierTypeNode($currentTokenValue), $startLine, $startIndex);
            if (!$tokens->isCurrentTokenType(Lexer::TOKEN_DOUBLE_COLON)) {
                $tokens->dropSavePoint();
                return $identifier;
            }
            $tokens->rollback();
            // because of ConstFetchNode
        } else {
            $tokens->dropSavePoint();
            // because of ConstFetchNode
        }
        $currentTokenValue = $tokens->currentTokenValue();
        $currentTokenType = $tokens->currentTokenType();
        $currentTokenOffset = $tokens->currentTokenOffset();
        $currentTokenLine = $tokens->currentTokenLine();
        try {
            $constExpr = $this->doctrineConstantExprParser->parse($tokens);
            if ($constExpr instanceof Ast\ConstExpr\ConstExprArrayNode) {
                throw new ParserException($currentTokenValue, $currentTokenType, $currentTokenOffset, Lexer::TOKEN_IDENTIFIER, null, $currentTokenLine);
            }
            return $constExpr;
        } catch (LogicException $e) {
            throw new ParserException($currentTokenValue, $currentTokenType, $currentTokenOffset, Lexer::TOKEN_IDENTIFIER, null, $currentTokenLine);
        }
    }
    private function parseDoctrineArrayItem(TokenIterator $tokens): Doctrine\DoctrineArrayItem
    {
        $startLine = $tokens->currentTokenLine();
        $startIndex = $tokens->currentTokenIndex();
        try {
            $tokens->pushSavePoint();
            $key = $this->parseDoctrineArrayKey($tokens);
            if (!$tokens->tryConsumeTokenType(Lexer::TOKEN_EQUAL)) {
                if (!$tokens->tryConsumeTokenType(Lexer::TOKEN_COLON)) {
                    $tokens->consumeTokenType(Lexer::TOKEN_EQUAL);
                    // will throw exception
                }
            }
            $value = $this->parseDoctrineArgumentValue($tokens);
            $tokens->dropSavePoint();
            return $this->enrichWithAttributes($tokens, new Doctrine\DoctrineArrayItem($key, $value), $startLine, $startIndex);
        } catch (ParserException $e) {
            $tokens->rollback();
            return $this->enrichWithAttributes($tokens, new Doctrine\DoctrineArrayItem(null, $this->parseDoctrineArgumentValue($tokens)), $startLine, $startIndex);
        }
    }
    /**
     * @return ConstExprIntegerNode|ConstExprStringNode|IdentifierTypeNode|ConstFetchNode
     */
    private function parseDoctrineArrayKey(TokenIterator $tokens)
    {
        $startLine = $tokens->currentTokenLine();
        $startIndex = $tokens->currentTokenIndex();
        if ($tokens->isCurrentTokenType(Lexer::TOKEN_INTEGER)) {
            $key = new Ast\ConstExpr\ConstExprIntegerNode(str_replace('_', '', $tokens->currentTokenValue()));
            $tokens->next();
        } elseif ($tokens->isCurrentTokenType(Lexer::TOKEN_DOCTRINE_ANNOTATION_STRING)) {
            $key = $this->doctrineConstantExprParser->parseDoctrineString($tokens->currentTokenValue(), $tokens);
            $tokens->next();
        } elseif ($tokens->isCurrentTokenType(Lexer::TOKEN_SINGLE_QUOTED_STRING)) {
            $key = new Ast\ConstExpr\ConstExprStringNode(StringUnescaper::unescapeString($tokens->currentTokenValue()), Ast\ConstExpr\ConstExprStringNode::SINGLE_QUOTED);
            $tokens->next();
        } elseif ($tokens->isCurrentTokenType(Lexer::TOKEN_DOUBLE_QUOTED_STRING)) {
            $value = $tokens->currentTokenValue();
            $tokens->next();
            $key = $this->doctrineConstantExprParser->parseDoctrineString($value, $tokens);
        } else {
            $currentTokenValue = $tokens->currentTokenValue();
            $tokens->pushSavePoint();
            // because of ConstFetchNode
            if (!$tokens->tryConsumeTokenType(Lexer::TOKEN_IDENTIFIER)) {
                $tokens->dropSavePoint();
                throw new ParserException($tokens->currentTokenValue(), $tokens->currentTokenType(), $tokens->currentTokenOffset(), Lexer::TOKEN_IDENTIFIER, null, $tokens->currentTokenLine());
            }
            if (!$tokens->isCurrentTokenType(Lexer::TOKEN_DOUBLE_COLON)) {
                $tokens->dropSavePoint();
                return $this->enrichWithAttributes($tokens, new IdentifierTypeNode($currentTokenValue), $startLine, $startIndex);
            }
            $tokens->rollback();
            $constExpr = $this->doctrineConstantExprParser->parse($tokens);
            if (!$constExpr instanceof Ast\ConstExpr\ConstFetchNode) {
                throw new ParserException($tokens->currentTokenValue(), $tokens->currentTokenType(), $tokens->currentTokenOffset(), Lexer::TOKEN_IDENTIFIER, null, $tokens->currentTokenLine());
            }
            return $constExpr;
        }
        return $this->enrichWithAttributes($tokens, $key, $startLine, $startIndex);
    }
    /**
     * @return Ast\PhpDoc\ParamTagValueNode|Ast\PhpDoc\TypelessParamTagValueNode
     */
    private function parseParamTagValue(TokenIterator $tokens): Ast\PhpDoc\PhpDocTagValueNode
    {
        if ($tokens->isCurrentTokenType(Lexer::TOKEN_REFERENCE, Lexer::TOKEN_VARIADIC, Lexer::TOKEN_VARIABLE)) {
            $type = null;
        } else {
            $type = $this->typeParser->parse($tokens);
        }
        $isReference = $tokens->tryConsumeTokenType(Lexer::TOKEN_REFERENCE);
        $isVariadic = $tokens->tryConsumeTokenType(Lexer::TOKEN_VARIADIC);
        $parameterName = $this->parseRequiredVariableName($tokens);
        $description = $this->parseOptionalDescription($tokens, \false);
        if ($type !== null) {
            return new Ast\PhpDoc\ParamTagValueNode($type, $isVariadic, $parameterName, $description, $isReference);
        }
        return new Ast\PhpDoc\TypelessParamTagValueNode($isVariadic, $parameterName, $description, $isReference);
    }
    private function parseParamImmediatelyInvokedCallableTagValue(TokenIterator $tokens): Ast\PhpDoc\ParamImmediatelyInvokedCallableTagValueNode
    {
        $parameterName = $this->parseRequiredVariableName($tokens);
        $description = $this->parseOptionalDescription($tokens, \false);
        return new Ast\PhpDoc\ParamImmediatelyInvokedCallableTagValueNode($parameterName, $description);
    }
    private function parseParamLaterInvokedCallableTagValue(TokenIterator $tokens): Ast\PhpDoc\ParamLaterInvokedCallableTagValueNode
    {
        $parameterName = $this->parseRequiredVariableName($tokens);
        $description = $this->parseOptionalDescription($tokens, \false);
        return new Ast\PhpDoc\ParamLaterInvokedCallableTagValueNode($parameterName, $description);
    }
    private function parseParamClosureThisTagValue(TokenIterator $tokens): Ast\PhpDoc\ParamClosureThisTagValueNode
    {
        $type = $this->typeParser->parse($tokens);
        $parameterName = $this->parseRequiredVariableName($tokens);
        $description = $this->parseOptionalDescription($tokens, \false);
        return new Ast\PhpDoc\ParamClosureThisTagValueNode($type, $parameterName, $description);
    }
    private function parsePureUnlessCallableIsImpureTagValue(TokenIterator $tokens): Ast\PhpDoc\PureUnlessCallableIsImpureTagValueNode
    {
        $parameterName = $this->parseRequiredVariableName($tokens);
        $description = $this->parseOptionalDescription($tokens, \false);
        return new Ast\PhpDoc\PureUnlessCallableIsImpureTagValueNode($parameterName, $description);
    }
    private function parseVarTagValue(TokenIterator $tokens): Ast\PhpDoc\VarTagValueNode
    {
        $type = $this->typeParser->parse($tokens);
        $variableName = $this->parseOptionalVariableName($tokens);
        $description = $this->parseOptionalDescription($tokens, $variableName === '');
        return new Ast\PhpDoc\VarTagValueNode($type, $variableName, $description);
    }
    private function parseReturnTagValue(TokenIterator $tokens): Ast\PhpDoc\ReturnTagValueNode
    {
        $type = $this->typeParser->parse($tokens);
        $description = $this->parseOptionalDescription($tokens, \true);
        return new Ast\PhpDoc\ReturnTagValueNode($type, $description);
    }
    private function parseThrowsTagValue(TokenIterator $tokens): Ast\PhpDoc\ThrowsTagValueNode
    {
        $type = $this->typeParser->parse($tokens);
        $description = $this->parseOptionalDescription($tokens, \true);
        return new Ast\PhpDoc\ThrowsTagValueNode($type, $description);
    }
    private function parseMixinTagValue(TokenIterator $tokens): Ast\PhpDoc\MixinTagValueNode
    {
        $type = $this->typeParser->parse($tokens);
        $description = $this->parseOptionalDescription($tokens, \true);
        return new Ast\PhpDoc\MixinTagValueNode($type, $description);
    }
    private function parseRequireExtendsTagValue(TokenIterator $tokens): Ast\PhpDoc\RequireExtendsTagValueNode
    {
        $type = $this->typeParser->parse($tokens);
        $description = $this->parseOptionalDescription($tokens, \true);
        return new Ast\PhpDoc\RequireExtendsTagValueNode($type, $description);
    }
    private function parseRequireImplementsTagValue(TokenIterator $tokens): Ast\PhpDoc\RequireImplementsTagValueNode
    {
        $type = $this->typeParser->parse($tokens);
        $description = $this->parseOptionalDescription($tokens, \true);
        return new Ast\PhpDoc\RequireImplementsTagValueNode($type, $description);
    }
    private function parseSealedTagValue(TokenIterator $tokens): Ast\PhpDoc\SealedTagValueNode
    {
        $type = $this->typeParser->parse($tokens);
        $description = $this->parseOptionalDescription($tokens, \true);
        return new Ast\PhpDoc\SealedTagValueNode($type, $description);
    }
    private function parseDeprecatedTagValue(TokenIterator $tokens): Ast\PhpDoc\DeprecatedTagValueNode
    {
        $description = $this->parseOptionalDescription($tokens, \false);
        return new Ast\PhpDoc\DeprecatedTagValueNode($description);
    }
    private function parsePropertyTagValue(TokenIterator $tokens): Ast\PhpDoc\PropertyTagValueNode
    {
        $type = $this->typeParser->parse($tokens);
        $parameterName = $this->parseRequiredVariableName($tokens);
        $description = $this->parseOptionalDescription($tokens, \false);
        return new Ast\PhpDoc\PropertyTagValueNode($type, $parameterName, $description);
    }
    private function parseMethodTagValue(TokenIterator $tokens): Ast\PhpDoc\MethodTagValueNode
    {
        $staticKeywordOrReturnTypeOrMethodName = $this->typeParser->parse($tokens);
        if ($staticKeywordOrReturnTypeOrMethodName instanceof Ast\Type\IdentifierTypeNode && $staticKeywordOrReturnTypeOrMethodName->name === 'static') {
            $isStatic = \true;
            $returnTypeOrMethodName = $this->typeParser->parse($tokens);
        } else {
            $isStatic = \false;
            $returnTypeOrMethodName = $staticKeywordOrReturnTypeOrMethodName;
        }
        if ($tokens->isCurrentTokenType(Lexer::TOKEN_IDENTIFIER)) {
            $returnType = $returnTypeOrMethodName;
            $methodName = $tokens->currentTokenValue();
            $tokens->next();
        } elseif ($returnTypeOrMethodName instanceof Ast\Type\IdentifierTypeNode) {
            $returnType = $isStatic ? $staticKeywordOrReturnTypeOrMethodName : null;
            $methodName = $returnTypeOrMethodName->name;
            $isStatic = \false;
        } else {
            $tokens->consumeTokenType(Lexer::TOKEN_IDENTIFIER);
            // will throw exception
            exit;
        }
        $templateTypes = [];
        if ($tokens->tryConsumeTokenType(Lexer::TOKEN_OPEN_ANGLE_BRACKET)) {
            do {
                $startLine = $tokens->currentTokenLine();
                $startIndex = $tokens->currentTokenIndex();
                $templateTypes[] = $this->enrichWithAttributes($tokens, $this->typeParser->parseTemplateTagValue($tokens), $startLine, $startIndex);
            } while ($tokens->tryConsumeTokenType(Lexer::TOKEN_COMMA));
            $tokens->consumeTokenType(Lexer::TOKEN_CLOSE_ANGLE_BRACKET);
        }
        $parameters = [];
        $tokens->consumeTokenType(Lexer::TOKEN_OPEN_PARENTHESES);
        if (!$tokens->isCurrentTokenType(Lexer::TOKEN_CLOSE_PARENTHESES)) {
            $parameters[] = $this->parseMethodTagValueParameter($tokens);
            while ($tokens->tryConsumeTokenType(Lexer::TOKEN_COMMA)) {
                $parameters[] = $this->parseMethodTagValueParameter($tokens);
            }
        }
        $tokens->consumeTokenType(Lexer::TOKEN_CLOSE_PARENTHESES);
        $description = $this->parseOptionalDescription($tokens, \false);
        return new Ast\PhpDoc\MethodTagValueNode($isStatic, $returnType, $methodName, $parameters, $description, $templateTypes);
    }
    private function parseMethodTagValueParameter(TokenIterator $tokens): Ast\PhpDoc\MethodTagValueParameterNode
    {
        $startLine = $tokens->currentTokenLine();
        $startIndex = $tokens->currentTokenIndex();
        switch ($tokens->currentTokenType()) {
            case Lexer::TOKEN_IDENTIFIER:
            case Lexer::TOKEN_OPEN_PARENTHESES:
            case Lexer::TOKEN_NULLABLE:
                $parameterType = $this->typeParser->parse($tokens);
                break;
            default:
                $parameterType = null;
        }
        $isReference = $tokens->tryConsumeTokenType(Lexer::TOKEN_REFERENCE);
        $isVariadic = $tokens->tryConsumeTokenType(Lexer::TOKEN_VARIADIC);
        $parameterName = $tokens->currentTokenValue();
        $tokens->consumeTokenType(Lexer::TOKEN_VARIABLE);
        if ($tokens->tryConsumeTokenType(Lexer::TOKEN_EQUAL)) {
            $defaultValue = $this->constantExprParser->parse($tokens);
        } else {
            $defaultValue = null;
        }
        return $this->enrichWithAttributes($tokens, new Ast\PhpDoc\MethodTagValueParameterNode($parameterType, $isReference, $isVariadic, $parameterName, $defaultValue), $startLine, $startIndex);
    }
    private function parseExtendsTagValue(string $tagName, TokenIterator $tokens): Ast\PhpDoc\PhpDocTagValueNode
    {
        $startLine = $tokens->currentTokenLine();
        $startIndex = $tokens->currentTokenIndex();
        $baseType = new IdentifierTypeNode($tokens->currentTokenValue());
        $tokens->consumeTokenType(Lexer::TOKEN_IDENTIFIER);
        $type = $this->typeParser->parseGeneric($tokens, $this->typeParser->enrichWithAttributes($tokens, $baseType, $startLine, $startIndex));
        $description = $this->parseOptionalDescription($tokens, \true);
        switch ($tagName) {
            case '@extends':
                return new Ast\PhpDoc\ExtendsTagValueNode($type, $description);
            case '@implements':
                return new Ast\PhpDoc\ImplementsTagValueNode($type, $description);
            case '@use':
                return new Ast\PhpDoc\UsesTagValueNode($type, $description);
        }
        throw new ShouldNotHappenException();
    }
    private function parseTypeAliasTagValue(TokenIterator $tokens): Ast\PhpDoc\TypeAliasTagValueNode
    {
        $alias = $tokens->currentTokenValue();
        $tokens->consumeTokenType(Lexer::TOKEN_IDENTIFIER);
        // support phan-type/psalm-type syntax
        $tokens->tryConsumeTokenType(Lexer::TOKEN_EQUAL);
        $startLine = $tokens->currentTokenLine();
        $startIndex = $tokens->currentTokenIndex();
        try {
            $type = $this->typeParser->parse($tokens);
            if (!$tokens->isCurrentTokenType(Lexer::TOKEN_CLOSE_PHPDOC)) {
                if (!$tokens->isCurrentTokenType(Lexer::TOKEN_PHPDOC_EOL)) {
                    throw new ParserException($tokens->currentTokenValue(), $tokens->currentTokenType(), $tokens->currentTokenOffset(), Lexer::TOKEN_PHPDOC_EOL, null, $tokens->currentTokenLine());
                }
            }
            return new Ast\PhpDoc\TypeAliasTagValueNode($alias, $type);
        } catch (ParserException $e) {
            $this->parseOptionalDescription($tokens, \false);
            return new Ast\PhpDoc\TypeAliasTagValueNode($alias, $this->enrichWithAttributes($tokens, new Ast\Type\InvalidTypeNode($e), $startLine, $startIndex));
        }
    }
    private function parseTypeAliasImportTagValue(TokenIterator $tokens): Ast\PhpDoc\TypeAliasImportTagValueNode
    {
        $importedAlias = $tokens->currentTokenValue();
        $tokens->consumeTokenType(Lexer::TOKEN_IDENTIFIER);
        $tokens->consumeTokenValue(Lexer::TOKEN_IDENTIFIER, 'from');
        $identifierStartLine = $tokens->currentTokenLine();
        $identifierStartIndex = $tokens->currentTokenIndex();
        $importedFrom = $tokens->currentTokenValue();
        $tokens->consumeTokenType(Lexer::TOKEN_IDENTIFIER);
        $importedFromType = $this->enrichWithAttributes($tokens, new IdentifierTypeNode($importedFrom), $identifierStartLine, $identifierStartIndex);
        $importedAs = null;
        if ($tokens->tryConsumeTokenValue('as')) {
            $importedAs = $tokens->currentTokenValue();
            $tokens->consumeTokenType(Lexer::TOKEN_IDENTIFIER);
        }
        return new Ast\PhpDoc\TypeAliasImportTagValueNode($importedAlias, $importedFromType, $importedAs);
    }
    /**
     * @return Ast\PhpDoc\AssertTagValueNode|Ast\PhpDoc\AssertTagPropertyValueNode|Ast\PhpDoc\AssertTagMethodValueNode
     */
    private function parseAssertTagValue(TokenIterator $tokens): Ast\PhpDoc\PhpDocTagValueNode
    {
        $isNegated = $tokens->tryConsumeTokenType(Lexer::TOKEN_NEGATED);
        $isEquality = $tokens->tryConsumeTokenType(Lexer::TOKEN_EQUAL);
        $type = $this->typeParser->parse($tokens);
        $parameter = $this->parseAssertParameter($tokens);
        $description = $this->parseOptionalDescription($tokens, \false);
        if (array_key_exists('method', $parameter)) {
            return new Ast\PhpDoc\AssertTagMethodValueNode($type, $parameter['parameter'], $parameter['method'], $isNegated, $description, $isEquality);
        } elseif (array_key_exists('property', $parameter)) {
            return new Ast\PhpDoc\AssertTagPropertyValueNode($type, $parameter['parameter'], $parameter['property'], $isNegated, $description, $isEquality);
        }
        return new Ast\PhpDoc\AssertTagValueNode($type, $parameter['parameter'], $isNegated, $description, $isEquality);
    }
    /**
     * @return array{parameter: string}|array{parameter: string, property: string}|array{parameter: string, method: string}
     */
    private function parseAssertParameter(TokenIterator $tokens): array
    {
        if ($tokens->isCurrentTokenType(Lexer::TOKEN_THIS_VARIABLE)) {
            $parameter = '$this';
            $tokens->next();
        } else {
            $parameter = $tokens->currentTokenValue();
            $tokens->consumeTokenType(Lexer::TOKEN_VARIABLE);
        }
        if ($tokens->isCurrentTokenType(Lexer::TOKEN_ARROW)) {
            $tokens->consumeTokenType(Lexer::TOKEN_ARROW);
            $propertyOrMethod = $tokens->currentTokenValue();
            $tokens->consumeTokenType(Lexer::TOKEN_IDENTIFIER);
            if ($tokens->tryConsumeTokenType(Lexer::TOKEN_OPEN_PARENTHESES)) {
                $tokens->consumeTokenType(Lexer::TOKEN_CLOSE_PARENTHESES);
                return ['parameter' => $parameter, 'method' => $propertyOrMethod];
            }
            return ['parameter' => $parameter, 'property' => $propertyOrMethod];
        }
        return ['parameter' => $parameter];
    }
    private function parseSelfOutTagValue(TokenIterator $tokens): Ast\PhpDoc\SelfOutTagValueNode
    {
        $type = $this->typeParser->parse($tokens);
        $description = $this->parseOptionalDescription($tokens, \true);
        return new Ast\PhpDoc\SelfOutTagValueNode($type, $description);
    }
    private function parseParamOutTagValue(TokenIterator $tokens): Ast\PhpDoc\ParamOutTagValueNode
    {
        $type = $this->typeParser->parse($tokens);
        $parameterName = $this->parseRequiredVariableName($tokens);
        $description = $this->parseOptionalDescription($tokens, \false);
        return new Ast\PhpDoc\ParamOutTagValueNode($type, $parameterName, $description);
    }
    private function parseOptionalVariableName(TokenIterator $tokens): string
    {
        if ($tokens->isCurrentTokenType(Lexer::TOKEN_VARIABLE)) {
            $parameterName = $tokens->currentTokenValue();
            $tokens->next();
        } elseif ($tokens->isCurrentTokenType(Lexer::TOKEN_THIS_VARIABLE)) {
            $parameterName = '$this';
            $tokens->next();
        } else {
            $parameterName = '';
        }
        return $parameterName;
    }
    private function parseRequiredVariableName(TokenIterator $tokens): string
    {
        $parameterName = $tokens->currentTokenValue();
        $tokens->consumeTokenType(Lexer::TOKEN_VARIABLE);
        return $parameterName;
    }
    /**
     * @param bool $limitStartToken true should be used when the description immediately follows a parsed type
     */
    private function parseOptionalDescription(TokenIterator $tokens, bool $limitStartToken): string
    {
        if ($limitStartToken) {
            foreach (self::DISALLOWED_DESCRIPTION_START_TOKENS as $disallowedStartToken) {
                if (!$tokens->isCurrentTokenType($disallowedStartToken)) {
                    continue;
                }
                $tokens->consumeTokenType(Lexer::TOKEN_OTHER);
                // will throw exception
            }
            if (!$tokens->isCurrentTokenType(Lexer::TOKEN_PHPDOC_EOL, Lexer::TOKEN_CLOSE_PHPDOC, Lexer::TOKEN_END) && !$tokens->isPrecededByHorizontalWhitespace()) {
                $tokens->consumeTokenType(Lexer::TOKEN_HORIZONTAL_WS);
                // will throw exception
            }
        }
        return $this->parseText($tokens)->text;
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\PHPStan\PhpDocParser\Parser;

use _ContaoManager\PHPStan\PhpDocParser\Ast;
use _ContaoManager\PHPStan\PhpDocParser\Lexer\Lexer;
use _ContaoManager\PHPStan\PhpDocParser\ParserConfig;
use function str_replace;
use function strtolower;
class ConstExprParser
{
    private ParserConfig $config;
    private bool $parseDoctrineStrings;
    public function __construct(ParserConfig $config)
    {
        $this->config = $config;
        $this->parseDoctrineStrings = \false;
    }
    /**
     * @internal
     */
    public function toDoctrine(): self
    {
        $self = new self($this->config);
        $self->parseDoctrineStrings = \true;
        return $self;
    }
    public function parse(TokenIterator $tokens): Ast\ConstExpr\ConstExprNode
    {
        $startLine = $tokens->currentTokenLine();
        $startIndex = $tokens->currentTokenIndex();
        if ($tokens->isCurrentTokenType(Lexer::TOKEN_FLOAT)) {
            $value = $tokens->currentTokenValue();
            $tokens->next();
            return $this->enrichWithAttributes($tokens, new Ast\ConstExpr\ConstExprFloatNode(str_replace('_', '', $value)), $startLine, $startIndex);
        }
        if ($tokens->isCurrentTokenType(Lexer::TOKEN_INTEGER)) {
            $value = $tokens->currentTokenValue();
            $tokens->next();
            return $this->enrichWithAttributes($tokens, new Ast\ConstExpr\ConstExprIntegerNode(str_replace('_', '', $value)), $startLine, $startIndex);
        }
        if ($this->parseDoctrineStrings && $tokens->isCurrentTokenType(Lexer::TOKEN_DOCTRINE_ANNOTATION_STRING)) {
            $value = $tokens->currentTokenValue();
            $tokens->next();
            return $this->enrichWithAttributes($tokens, new Ast\ConstExpr\DoctrineConstExprStringNode(Ast\ConstExpr\DoctrineConstExprStringNode::unescape($value)), $startLine, $startIndex);
        }
        if ($tokens->isCurrentTokenType(Lexer::TOKEN_SINGLE_QUOTED_STRING, Lexer::TOKEN_DOUBLE_QUOTED_STRING)) {
            if ($this->parseDoctrineStrings) {
                if ($tokens->isCurrentTokenType(Lexer::TOKEN_SINGLE_QUOTED_STRING)) {
                    throw new ParserException($tokens->currentTokenValue(), $tokens->currentTokenType(), $tokens->currentTokenOffset(), Lexer::TOKEN_DOUBLE_QUOTED_STRING, null, $tokens->currentTokenLine());
                }
                $value = $tokens->currentTokenValue();
                $tokens->next();
                return $this->enrichWithAttributes($tokens, $this->parseDoctrineString($value, $tokens), $startLine, $startIndex);
            }
            $value = StringUnescaper::unescapeString($tokens->currentTokenValue());
            $type = $tokens->currentTokenType();
            $tokens->next();
            return $this->enrichWithAttributes($tokens, new Ast\ConstExpr\ConstExprStringNode($value, $type === Lexer::TOKEN_SINGLE_QUOTED_STRING ? Ast\ConstExpr\ConstExprStringNode::SINGLE_QUOTED : Ast\ConstExpr\ConstExprStringNode::DOUBLE_QUOTED), $startLine, $startIndex);
        } elseif ($tokens->isCurrentTokenType(Lexer::TOKEN_IDENTIFIER)) {
            $identifier = $tokens->currentTokenValue();
            $tokens->next();
            switch (strtolower($identifier)) {
                case 'true':
                    return $this->enrichWithAttributes($tokens, new Ast\ConstExpr\ConstExprTrueNode(), $startLine, $startIndex);
                case 'false':
                    return $this->enrichWithAttributes($tokens, new Ast\ConstExpr\ConstExprFalseNode(), $startLine, $startIndex);
                case 'null':
                    return $this->enrichWithAttributes($tokens, new Ast\ConstExpr\ConstExprNullNode(), $startLine, $startIndex);
                case 'array':
                    $tokens->consumeTokenType(Lexer::TOKEN_OPEN_PARENTHESES);
                    return $this->parseArray($tokens, Lexer::TOKEN_CLOSE_PARENTHESES, $startIndex);
            }
            if ($tokens->tryConsumeTokenType(Lexer::TOKEN_DOUBLE_COLON)) {
                $classConstantName = '';
                $lastType = null;
                while (\true) {
                    if ($lastType !== Lexer::TOKEN_IDENTIFIER && $tokens->currentTokenType() === Lexer::TOKEN_IDENTIFIER) {
                        $classConstantName .= $tokens->currentTokenValue();
                        $tokens->consumeTokenType(Lexer::TOKEN_IDENTIFIER);
                        $lastType = Lexer::TOKEN_IDENTIFIER;
                        continue;
                    }
                    if ($lastType !== Lexer::TOKEN_WILDCARD && $tokens->tryConsumeTokenType(Lexer::TOKEN_WILDCARD)) {
                        $classConstantName .= '*';
                        $lastType = Lexer::TOKEN_WILDCARD;
                        if ($tokens->getSkippedHorizontalWhiteSpaceIfAny() !== '') {
                            break;
                        }
                        continue;
                    }
                    if ($lastType === null) {
                        // trigger parse error if nothing valid was consumed
                        $tokens->consumeTokenType(Lexer::TOKEN_WILDCARD);
                    }
                    break;
                }
                return $this->enrichWithAttributes($tokens, new Ast\ConstExpr\ConstFetchNode($identifier, $classConstantName), $startLine, $startIndex);
            }
            return $this->enrichWithAttributes($tokens, new Ast\ConstExpr\ConstFetchNode('', $identifier), $startLine, $startIndex);
        } elseif ($tokens->tryConsumeTokenType(Lexer::TOKEN_OPEN_SQUARE_BRACKET)) {
            return $this->parseArray($tokens, Lexer::TOKEN_CLOSE_SQUARE_BRACKET, $startIndex);
        }
        throw new ParserException($tokens->currentTokenValue(), $tokens->currentTokenType(), $tokens->currentTokenOffset(), Lexer::TOKEN_IDENTIFIER, null, $tokens->currentTokenLine());
    }
    private function parseArray(TokenIterator $tokens, int $endToken, int $startIndex): Ast\ConstExpr\ConstExprArrayNode
    {
        $items = [];
        $startLine = $tokens->currentTokenLine();
        if (!$tokens->tryConsumeTokenType($endToken)) {
            do {
                $items[] = $this->parseArrayItem($tokens);
            } while ($tokens->tryConsumeTokenType(Lexer::TOKEN_COMMA) && !$tokens->isCurrentTokenType($endToken));
            $tokens->consumeTokenType($endToken);
        }
        return $this->enrichWithAttributes($tokens, new Ast\ConstExpr\ConstExprArrayNode($items), $startLine, $startIndex);
    }
    /**
     * This method is supposed to be called with TokenIterator after reading TOKEN_DOUBLE_QUOTED_STRING and shifting
     * to the next token.
     */
    public function parseDoctrineString(string $text, TokenIterator $tokens): Ast\ConstExpr\DoctrineConstExprStringNode
    {
        // Because of how Lexer works, a valid Doctrine string
        // can consist of a sequence of TOKEN_DOUBLE_QUOTED_STRING and TOKEN_DOCTRINE_ANNOTATION_STRING
        while ($tokens->isCurrentTokenType(Lexer::TOKEN_DOUBLE_QUOTED_STRING, Lexer::TOKEN_DOCTRINE_ANNOTATION_STRING)) {
            $text .= $tokens->currentTokenValue();
            $tokens->next();
        }
        return new Ast\ConstExpr\DoctrineConstExprStringNode(Ast\ConstExpr\DoctrineConstExprStringNode::unescape($text));
    }
    private function parseArrayItem(TokenIterator $tokens): Ast\ConstExpr\ConstExprArrayItemNode
    {
        $startLine = $tokens->currentTokenLine();
        $startIndex = $tokens->currentTokenIndex();
        $expr = $this->parse($tokens);
        if ($tokens->tryConsumeTokenType(Lexer::TOKEN_DOUBLE_ARROW)) {
            $key = $expr;
            $value = $this->parse($tokens);
        } else {
            $key = null;
            $value = $expr;
        }
        return $this->enrichWithAttributes($tokens, new Ast\ConstExpr\ConstExprArrayItemNode($key, $value), $startLine, $startIndex);
    }
    /**
     * @template T of Ast\ConstExpr\ConstExprNode
     * @param T $node
     * @return T
     */
    private function enrichWithAttributes(TokenIterator $tokens, Ast\ConstExpr\ConstExprNode $node, int $startLine, int $startIndex): Ast\ConstExpr\ConstExprNode
    {
        if ($this->config->useLinesAttributes) {
            $node->setAttribute(Ast\Attribute::START_LINE, $startLine);
            $node->setAttribute(Ast\Attribute::END_LINE, $tokens->currentTokenLine());
        }
        if ($this->config->useIndexAttributes) {
            $node->setAttribute(Ast\Attribute::START_INDEX, $startIndex);
            $node->setAttribute(Ast\Attribute::END_INDEX, $tokens->endIndexOfLastRelevantToken());
        }
        return $node;
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\PHPStan\PhpDocParser\Parser;

use _ContaoManager\PHPStan\ShouldNotHappenException;
use function chr;
use function hexdec;
use function octdec;
use function preg_replace_callback;
use function str_replace;
use function substr;
class StringUnescaper
{
    private const REPLACEMENTS = ['\\' => '\\', 'n' => "\n", 'r' => "\r", 't' => "\t", 'f' => "\f", 'v' => "\v", 'e' => "\x1b"];
    public static function unescapeString(string $string): string
    {
        $quote = $string[0];
        if ($quote === '\'') {
            return str_replace(['\\\\', '\\\''], ['\\', '\''], substr($string, 1, -1));
        }
        return self::parseEscapeSequences(substr($string, 1, -1), '"');
    }
    /**
     * Implementation based on https://github.com/nikic/PHP-Parser/blob/b0edd4c41111042d43bb45c6c657b2e0db367d9e/lib/PhpParser/Node/Scalar/String_.php#L90-L130
     */
    private static function parseEscapeSequences(string $str, string $quote): string
    {
        $str = str_replace('\\' . $quote, $quote, $str);
        return preg_replace_callback('~\\\\([\\\\nrtfve]|[xX][0-9a-fA-F]{1,2}|[0-7]{1,3}|u\{([0-9a-fA-F]+)\})~', static function ($matches) {
            $str = $matches[1];
            if (isset(self::REPLACEMENTS[$str])) {
                return self::REPLACEMENTS[$str];
            }
            if ($str[0] === 'x' || $str[0] === 'X') {
                return chr((int) hexdec(substr($str, 1)));
            }
            if ($str[0] === 'u') {
                if (!isset($matches[2])) {
                    throw new ShouldNotHappenException();
                }
                return self::codePointToUtf8((int) hexdec($matches[2]));
            }
            return chr((int) octdec($str));
        }, $str);
    }
    /**
     * Implementation based on https://github.com/nikic/PHP-Parser/blob/b0edd4c41111042d43bb45c6c657b2e0db367d9e/lib/PhpParser/Node/Scalar/String_.php#L132-L154
     */
    private static function codePointToUtf8(int $num): string
    {
        if ($num <= 0x7f) {
            return chr($num);
        }
        if ($num <= 0x7ff) {
            return chr(($num >> 6) + 0xc0) . chr(($num & 0x3f) + 0x80);
        }
        if ($num <= 0xffff) {
            return chr(($num >> 12) + 0xe0) . chr(($num >> 6 & 0x3f) + 0x80) . chr(($num & 0x3f) + 0x80);
        }
        if ($num <= 0x1fffff) {
            return chr(($num >> 18) + 0xf0) . chr(($num >> 12 & 0x3f) + 0x80) . chr(($num >> 6 & 0x3f) + 0x80) . chr(($num & 0x3f) + 0x80);
        }
        // Invalid UTF-8 codepoint escape sequence: Codepoint too large
        return "�";
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\PHPStan\PhpDocParser\Parser;

use LogicException;
use _ContaoManager\PHPStan\PhpDocParser\Ast;
use _ContaoManager\PHPStan\PhpDocParser\Ast\PhpDoc\TemplateTagValueNode;
use _ContaoManager\PHPStan\PhpDocParser\Lexer\Lexer;
use _ContaoManager\PHPStan\PhpDocParser\ParserConfig;
use function in_array;
use function str_replace;
use function strlen;
use function strpos;
use function substr_compare;
class TypeParser
{
    private ParserConfig $config;
    private ConstExprParser $constExprParser;
    public function __construct(ParserConfig $config, ConstExprParser $constExprParser)
    {
        $this->config = $config;
        $this->constExprParser = $constExprParser;
    }
    /** @phpstan-impure */
    public function parse(TokenIterator $tokens): Ast\Type\TypeNode
    {
        $startLine = $tokens->currentTokenLine();
        $startIndex = $tokens->currentTokenIndex();
        if ($tokens->isCurrentTokenType(Lexer::TOKEN_NULLABLE)) {
            $type = $this->parseNullable($tokens);
        } else {
            $type = $this->parseAtomic($tokens);
            $tokens->pushSavePoint();
            $tokens->skipNewLineTokensAndConsumeComments();
            try {
                $enrichedType = $this->enrichTypeOnUnionOrIntersection($tokens, $type);
            } catch (ParserException $parserException) {
                $enrichedType = null;
            }
            if ($enrichedType !== null) {
                $type = $enrichedType;
                $tokens->dropSavePoint();
            } else {
                $tokens->rollback();
                $type = $this->enrichTypeOnUnionOrIntersection($tokens, $type) ?? $type;
            }
        }
        return $this->enrichWithAttributes($tokens, $type, $startLine, $startIndex);
    }
    /** @phpstan-impure */
    private function enrichTypeOnUnionOrIntersection(TokenIterator $tokens, Ast\Type\TypeNode $type): ?Ast\Type\TypeNode
    {
        if ($tokens->isCurrentTokenType(Lexer::TOKEN_UNION)) {
            return $this->parseUnion($tokens, $type);
        }
        if ($tokens->isCurrentTokenType(Lexer::TOKEN_INTERSECTION)) {
            return $this->parseIntersection($tokens, $type);
        }
        return null;
    }
    /**
     * @internal
     * @template T of Ast\Node
     * @param T $type
     * @return T
     */
    public function enrichWithAttributes(TokenIterator $tokens, Ast\Node $type, int $startLine, int $startIndex): Ast\Node
    {
        if ($this->config->useLinesAttributes) {
            $type->setAttribute(Ast\Attribute::START_LINE, $startLine);
            $type->setAttribute(Ast\Attribute::END_LINE, $tokens->currentTokenLine());
        }
        $comments = $tokens->flushComments();
        if ($this->config->useCommentsAttributes) {
            $type->setAttribute(Ast\Attribute::COMMENTS, $comments);
        }
        if ($this->config->useIndexAttributes) {
            $type->setAttribute(Ast\Attribute::START_INDEX, $startIndex);
            $type->setAttribute(Ast\Attribute::END_INDEX, $tokens->endIndexOfLastRelevantToken());
        }
        return $type;
    }
    /** @phpstan-impure */
    private function subParse(TokenIterator $tokens): Ast\Type\TypeNode
    {
        $startLine = $tokens->currentTokenLine();
        $startIndex = $tokens->currentTokenIndex();
        if ($tokens->isCurrentTokenType(Lexer::TOKEN_NULLABLE)) {
            $type = $this->parseNullable($tokens);
        } elseif ($tokens->isCurrentTokenType(Lexer::TOKEN_VARIABLE)) {
            $type = $this->parseConditionalForParameter($tokens, $tokens->currentTokenValue());
        } else {
            $type = $this->parseAtomic($tokens);
            if ($tokens->isCurrentTokenValue('is')) {
                $type = $this->parseConditional($tokens, $type);
            } else {
                $tokens->skipNewLineTokensAndConsumeComments();
                if ($tokens->isCurrentTokenType(Lexer::TOKEN_UNION)) {
                    $type = $this->subParseUnion($tokens, $type);
                } elseif ($tokens->isCurrentTokenType(Lexer::TOKEN_INTERSECTION)) {
                    $type = $this->subParseIntersection($tokens, $type);
                }
            }
        }
        return $this->enrichWithAttributes($tokens, $type, $startLine, $startIndex);
    }
    /** @phpstan-impure */
    private function parseAtomic(TokenIterator $tokens): Ast\Type\TypeNode
    {
        $startLine = $tokens->currentTokenLine();
        $startIndex = $tokens->currentTokenIndex();
        if ($tokens->tryConsumeTokenType(Lexer::TOKEN_OPEN_PARENTHESES)) {
            $tokens->skipNewLineTokensAndConsumeComments();
            $type = $this->subParse($tokens);
            $tokens->skipNewLineTokensAndConsumeComments();
            $tokens->consumeTokenType(Lexer::TOKEN_CLOSE_PARENTHESES);
            if ($tokens->isCurrentTokenType(Lexer::TOKEN_OPEN_SQUARE_BRACKET)) {
                $type = $this->tryParseArrayOrOffsetAccess($tokens, $type);
            }
            return $this->enrichWithAttributes($tokens, $type, $startLine, $startIndex);
        }
        if ($tokens->tryConsumeTokenType(Lexer::TOKEN_THIS_VARIABLE)) {
            $type = $this->enrichWithAttributes($tokens, new Ast\Type\ThisTypeNode(), $startLine, $startIndex);
            if ($tokens->isCurrentTokenType(Lexer::TOKEN_OPEN_SQUARE_BRACKET)) {
                $type = $this->tryParseArrayOrOffsetAccess($tokens, $type);
            }
            return $this->enrichWithAttributes($tokens, $type, $startLine, $startIndex);
        }
        $currentTokenValue = $tokens->currentTokenValue();
        $tokens->pushSavePoint();
        // because of ConstFetchNode
        if ($tokens->tryConsumeTokenType(Lexer::TOKEN_IDENTIFIER)) {
            $type = $this->enrichWithAttributes($tokens, new Ast\Type\IdentifierTypeNode($currentTokenValue), $startLine, $startIndex);
            if (!$tokens->isCurrentTokenType(Lexer::TOKEN_DOUBLE_COLON)) {
                $tokens->dropSavePoint();
                // because of ConstFetchNode
                if ($tokens->isCurrentTokenType(Lexer::TOKEN_OPEN_ANGLE_BRACKET)) {
                    $tokens->pushSavePoint();
                    $isHtml = $this->isHtml($tokens);
                    $tokens->rollback();
                    if ($isHtml) {
                        return $type;
                    }
                    $origType = $type;
                    $type = $this->tryParseCallable($tokens, $type, \true);
                    if ($type === $origType) {
                        $type = $this->parseGeneric($tokens, $type);
                        if ($tokens->isCurrentTokenType(Lexer::TOKEN_OPEN_SQUARE_BRACKET)) {
                            $type = $this->tryParseArrayOrOffsetAccess($tokens, $type);
                        }
                    }
                } elseif ($tokens->isCurrentTokenType(Lexer::TOKEN_OPEN_PARENTHESES)) {
                    $type = $this->tryParseCallable($tokens, $type, \false);
                } elseif ($tokens->isCurrentTokenType(Lexer::TOKEN_OPEN_SQUARE_BRACKET)) {
                    $type = $this->tryParseArrayOrOffsetAccess($tokens, $type);
                } elseif (in_array($type->name, [Ast\Type\ArrayShapeNode::KIND_ARRAY, Ast\Type\ArrayShapeNode::KIND_LIST, Ast\Type\ArrayShapeNode::KIND_NON_EMPTY_ARRAY, Ast\Type\ArrayShapeNode::KIND_NON_EMPTY_LIST, 'object'], \true) && $tokens->isCurrentTokenType(Lexer::TOKEN_OPEN_CURLY_BRACKET) && !$tokens->isPrecededByHorizontalWhitespace()) {
                    if ($type->name === 'object') {
                        $type = $this->parseObjectShape($tokens);
                    } else {
                        $type = $this->parseArrayShape($tokens, $type, $type->name);
                    }
                    if ($tokens->isCurrentTokenType(Lexer::TOKEN_OPEN_SQUARE_BRACKET)) {
                        $type = $this->tryParseArrayOrOffsetAccess($tokens, $this->enrichWithAttributes($tokens, $type, $startLine, $startIndex));
                    }
                }
                return $this->enrichWithAttributes($tokens, $type, $startLine, $startIndex);
            } else {
                $tokens->rollback();
                // because of ConstFetchNode
            }
        } else {
            $tokens->dropSavePoint();
            // because of ConstFetchNode
        }
        $currentTokenValue = $tokens->currentTokenValue();
        $currentTokenType = $tokens->currentTokenType();
        $currentTokenOffset = $tokens->currentTokenOffset();
        $currentTokenLine = $tokens->currentTokenLine();
        try {
            $constExpr = $this->constExprParser->parse($tokens);
            if ($constExpr instanceof Ast\ConstExpr\ConstExprArrayNode) {
                throw new ParserException($currentTokenValue, $currentTokenType, $currentTokenOffset, Lexer::TOKEN_IDENTIFIER, null, $currentTokenLine);
            }
            $type = $this->enrichWithAttributes($tokens, new Ast\Type\ConstTypeNode($constExpr), $startLine, $startIndex);
            if ($tokens->isCurrentTokenType(Lexer::TOKEN_OPEN_SQUARE_BRACKET)) {
                $type = $this->tryParseArrayOrOffsetAccess($tokens, $type);
            }
            return $type;
        } catch (LogicException $e) {
            throw new ParserException($currentTokenValue, $currentTokenType, $currentTokenOffset, Lexer::TOKEN_IDENTIFIER, null, $currentTokenLine);
        }
    }
    /** @phpstan-impure */
    private function parseUnion(TokenIterator $tokens, Ast\Type\TypeNode $type): Ast\Type\TypeNode
    {
        $types = [$type];
        while ($tokens->tryConsumeTokenType(Lexer::TOKEN_UNION)) {
            $types[] = $this->parseAtomic($tokens);
            $tokens->pushSavePoint();
            $tokens->skipNewLineTokensAndConsumeComments();
            if (!$tokens->isCurrentTokenType(Lexer::TOKEN_UNION)) {
                $tokens->rollback();
                break;
            }
            $tokens->dropSavePoint();
        }
        return new Ast\Type\UnionTypeNode($types);
    }
    /** @phpstan-impure */
    private function subParseUnion(TokenIterator $tokens, Ast\Type\TypeNode $type): Ast\Type\TypeNode
    {
        $types = [$type];
        while ($tokens->tryConsumeTokenType(Lexer::TOKEN_UNION)) {
            $tokens->skipNewLineTokensAndConsumeComments();
            $types[] = $this->parseAtomic($tokens);
            $tokens->skipNewLineTokensAndConsumeComments();
        }
        return new Ast\Type\UnionTypeNode($types);
    }
    /** @phpstan-impure */
    private function parseIntersection(TokenIterator $tokens, Ast\Type\TypeNode $type): Ast\Type\TypeNode
    {
        $types = [$type];
        while ($tokens->tryConsumeTokenType(Lexer::TOKEN_INTERSECTION)) {
            $types[] = $this->parseAtomic($tokens);
            $tokens->pushSavePoint();
            $tokens->skipNewLineTokensAndConsumeComments();
            if (!$tokens->isCurrentTokenType(Lexer::TOKEN_INTERSECTION)) {
                $tokens->rollback();
                break;
            }
            $tokens->dropSavePoint();
        }
        return new Ast\Type\IntersectionTypeNode($types);
    }
    /** @phpstan-impure */
    private function subParseIntersection(TokenIterator $tokens, Ast\Type\TypeNode $type): Ast\Type\TypeNode
    {
        $types = [$type];
        while ($tokens->tryConsumeTokenType(Lexer::TOKEN_INTERSECTION)) {
            $tokens->skipNewLineTokensAndConsumeComments();
            $types[] = $this->parseAtomic($tokens);
            $tokens->skipNewLineTokensAndConsumeComments();
        }
        return new Ast\Type\IntersectionTypeNode($types);
    }
    /** @phpstan-impure */
    private function parseConditional(TokenIterator $tokens, Ast\Type\TypeNode $subjectType): Ast\Type\TypeNode
    {
        $tokens->consumeTokenType(Lexer::TOKEN_IDENTIFIER);
        $negated = \false;
        if ($tokens->isCurrentTokenValue('not')) {
            $negated = \true;
            $tokens->consumeTokenType(Lexer::TOKEN_IDENTIFIER);
        }
        $targetType = $this->parse($tokens);
        $tokens->skipNewLineTokensAndConsumeComments();
        $tokens->consumeTokenType(Lexer::TOKEN_NULLABLE);
        $tokens->skipNewLineTokensAndConsumeComments();
        $ifType = $this->parse($tokens);
        $tokens->skipNewLineTokensAndConsumeComments();
        $tokens->consumeTokenType(Lexer::TOKEN_COLON);
        $tokens->skipNewLineTokensAndConsumeComments();
        $elseType = $this->subParse($tokens);
        return new Ast\Type\ConditionalTypeNode($subjectType, $targetType, $ifType, $elseType, $negated);
    }
    /** @phpstan-impure */
    private function parseConditionalForParameter(TokenIterator $tokens, string $parameterName): Ast\Type\TypeNode
    {
        $tokens->consumeTokenType(Lexer::TOKEN_VARIABLE);
        $tokens->consumeTokenValue(Lexer::TOKEN_IDENTIFIER, 'is');
        $negated = \false;
        if ($tokens->isCurrentTokenValue('not')) {
            $negated = \true;
            $tokens->consumeTokenType(Lexer::TOKEN_IDENTIFIER);
        }
        $targetType = $this->parse($tokens);
        $tokens->skipNewLineTokensAndConsumeComments();
        $tokens->consumeTokenType(Lexer::TOKEN_NULLABLE);
        $tokens->skipNewLineTokensAndConsumeComments();
        $ifType = $this->parse($tokens);
        $tokens->skipNewLineTokensAndConsumeComments();
        $tokens->consumeTokenType(Lexer::TOKEN_COLON);
        $tokens->skipNewLineTokensAndConsumeComments();
        $elseType = $this->subParse($tokens);
        return new Ast\Type\ConditionalTypeForParameterNode($parameterName, $targetType, $ifType, $elseType, $negated);
    }
    /** @phpstan-impure */
    private function parseNullable(TokenIterator $tokens): Ast\Type\TypeNode
    {
        $tokens->consumeTokenType(Lexer::TOKEN_NULLABLE);
        $type = $this->parseAtomic($tokens);
        return new Ast\Type\NullableTypeNode($type);
    }
    /** @phpstan-impure */
    public function isHtml(TokenIterator $tokens): bool
    {
        $tokens->consumeTokenType(Lexer::TOKEN_OPEN_ANGLE_BRACKET);
        if (!$tokens->isCurrentTokenType(Lexer::TOKEN_IDENTIFIER)) {
            return \false;
        }
        $htmlTagName = $tokens->currentTokenValue();
        $tokens->next();
        if (!$tokens->tryConsumeTokenType(Lexer::TOKEN_CLOSE_ANGLE_BRACKET)) {
            return \false;
        }
        $endTag = '</' . $htmlTagName . '>';
        $endTagSearchOffset = -strlen($endTag);
        while (!$tokens->isCurrentTokenType(Lexer::TOKEN_END)) {
            if ($tokens->tryConsumeTokenType(Lexer::TOKEN_OPEN_ANGLE_BRACKET) && strpos($tokens->currentTokenValue(), '/' . $htmlTagName . '>') !== \false || substr_compare($tokens->currentTokenValue(), $endTag, $endTagSearchOffset) === 0) {
                return \true;
            }
            $tokens->next();
        }
        return \false;
    }
    /** @phpstan-impure */
    public function parseGeneric(TokenIterator $tokens, Ast\Type\IdentifierTypeNode $baseType): Ast\Type\GenericTypeNode
    {
        $tokens->consumeTokenType(Lexer::TOKEN_OPEN_ANGLE_BRACKET);
        $tokens->skipNewLineTokensAndConsumeComments();
        $startLine = $baseType->getAttribute(Ast\Attribute::START_LINE);
        $startIndex = $baseType->getAttribute(Ast\Attribute::START_INDEX);
        $genericTypes = [];
        $variances = [];
        $isFirst = \true;
        while ($isFirst || $tokens->tryConsumeTokenType(Lexer::TOKEN_COMMA)) {
            $tokens->skipNewLineTokensAndConsumeComments();
            // trailing comma case
            if (!$isFirst && $tokens->isCurrentTokenType(Lexer::TOKEN_CLOSE_ANGLE_BRACKET)) {
                break;
            }
            $isFirst = \false;
            [$genericTypes[], $variances[]] = $this->parseGenericTypeArgument($tokens);
            $tokens->skipNewLineTokensAndConsumeComments();
        }
        $type = new Ast\Type\GenericTypeNode($baseType, $genericTypes, $variances);
        if ($startLine !== null && $startIndex !== null) {
            $type = $this->enrichWithAttributes($tokens, $type, $startLine, $startIndex);
        }
        $tokens->consumeTokenType(Lexer::TOKEN_CLOSE_ANGLE_BRACKET);
        return $type;
    }
    /**
     * @phpstan-impure
     * @return array{Ast\Type\TypeNode, Ast\Type\GenericTypeNode::VARIANCE_*}
     */
    public function parseGenericTypeArgument(TokenIterator $tokens): array
    {
        $startLine = $tokens->currentTokenLine();
        $startIndex = $tokens->currentTokenIndex();
        if ($tokens->tryConsumeTokenType(Lexer::TOKEN_WILDCARD)) {
            return [$this->enrichWithAttributes($tokens, new Ast\Type\IdentifierTypeNode('mixed'), $startLine, $startIndex), Ast\Type\GenericTypeNode::VARIANCE_BIVARIANT];
        }
        if ($tokens->tryConsumeTokenValue('contravariant')) {
            $variance = Ast\Type\GenericTypeNode::VARIANCE_CONTRAVARIANT;
        } elseif ($tokens->tryConsumeTokenValue('covariant')) {
            $variance = Ast\Type\GenericTypeNode::VARIANCE_COVARIANT;
        } else {
            $variance = Ast\Type\GenericTypeNode::VARIANCE_INVARIANT;
        }
        $type = $this->parse($tokens);
        return [$type, $variance];
    }
    /**
     * @throws ParserException
     * @param ?callable(TokenIterator): string $parseDescription
     */
    public function parseTemplateTagValue(TokenIterator $tokens, ?callable $parseDescription = null): TemplateTagValueNode
    {
        $name = $tokens->currentTokenValue();
        $tokens->consumeTokenType(Lexer::TOKEN_IDENTIFIER);
        $upperBound = $lowerBound = null;
        if ($tokens->tryConsumeTokenValue('of') || $tokens->tryConsumeTokenValue('as')) {
            $upperBound = $this->parse($tokens);
        }
        if ($tokens->tryConsumeTokenValue('super')) {
            $lowerBound = $this->parse($tokens);
        }
        if ($tokens->tryConsumeTokenValue('=')) {
            $default = $this->parse($tokens);
        } else {
            $default = null;
        }
        if ($parseDescription !== null) {
            $description = $parseDescription($tokens);
        } else {
            $description = '';
        }
        if ($name === '') {
            throw new LogicException('Template tag name cannot be empty.');
        }
        return new Ast\PhpDoc\TemplateTagValueNode($name, $upperBound, $description, $default, $lowerBound);
    }
    /** @phpstan-impure */
    private function parseCallable(TokenIterator $tokens, Ast\Type\IdentifierTypeNode $identifier, bool $hasTemplate): Ast\Type\TypeNode
    {
        $templates = $hasTemplate ? $this->parseCallableTemplates($tokens) : [];
        $tokens->consumeTokenType(Lexer::TOKEN_OPEN_PARENTHESES);
        $tokens->skipNewLineTokensAndConsumeComments();
        $parameters = [];
        if (!$tokens->isCurrentTokenType(Lexer::TOKEN_CLOSE_PARENTHESES)) {
            $parameters[] = $this->parseCallableParameter($tokens);
            $tokens->skipNewLineTokensAndConsumeComments();
            while ($tokens->tryConsumeTokenType(Lexer::TOKEN_COMMA)) {
                $tokens->skipNewLineTokensAndConsumeComments();
                if ($tokens->isCurrentTokenType(Lexer::TOKEN_CLOSE_PARENTHESES)) {
                    break;
                }
                $parameters[] = $this->parseCallableParameter($tokens);
                $tokens->skipNewLineTokensAndConsumeComments();
            }
        }
        $tokens->consumeTokenType(Lexer::TOKEN_CLOSE_PARENTHESES);
        $tokens->consumeTokenType(Lexer::TOKEN_COLON);
        $startLine = $tokens->currentTokenLine();
        $startIndex = $tokens->currentTokenIndex();
        $returnType = $this->enrichWithAttributes($tokens, $this->parseCallableReturnType($tokens), $startLine, $startIndex);
        return new Ast\Type\CallableTypeNode($identifier, $parameters, $returnType, $templates);
    }
    /**
     * @return Ast\PhpDoc\TemplateTagValueNode[]
     *
     * @phpstan-impure
     */
    private function parseCallableTemplates(TokenIterator $tokens): array
    {
        $tokens->consumeTokenType(Lexer::TOKEN_OPEN_ANGLE_BRACKET);
        $templates = [];
        $isFirst = \true;
        while ($isFirst || $tokens->tryConsumeTokenType(Lexer::TOKEN_COMMA)) {
            $tokens->skipNewLineTokensAndConsumeComments();
            // trailing comma case
            if (!$isFirst && $tokens->isCurrentTokenType(Lexer::TOKEN_CLOSE_ANGLE_BRACKET)) {
                break;
            }
            $isFirst = \false;
            $templates[] = $this->parseCallableTemplateArgument($tokens);
            $tokens->skipNewLineTokensAndConsumeComments();
        }
        $tokens->consumeTokenType(Lexer::TOKEN_CLOSE_ANGLE_BRACKET);
        return $templates;
    }
    private function parseCallableTemplateArgument(TokenIterator $tokens): Ast\PhpDoc\TemplateTagValueNode
    {
        $startLine = $tokens->currentTokenLine();
        $startIndex = $tokens->currentTokenIndex();
        return $this->enrichWithAttributes($tokens, $this->parseTemplateTagValue($tokens), $startLine, $startIndex);
    }
    /** @phpstan-impure */
    private function parseCallableParameter(TokenIterator $tokens): Ast\Type\CallableTypeParameterNode
    {
        $startLine = $tokens->currentTokenLine();
        $startIndex = $tokens->currentTokenIndex();
        $type = $this->parse($tokens);
        $isReference = $tokens->tryConsumeTokenType(Lexer::TOKEN_REFERENCE);
        $isVariadic = $tokens->tryConsumeTokenType(Lexer::TOKEN_VARIADIC);
        if ($tokens->isCurrentTokenType(Lexer::TOKEN_VARIABLE)) {
            $parameterName = $tokens->currentTokenValue();
            $tokens->consumeTokenType(Lexer::TOKEN_VARIABLE);
        } else {
            $parameterName = '';
        }
        $isOptional = $tokens->tryConsumeTokenType(Lexer::TOKEN_EQUAL);
        return $this->enrichWithAttributes($tokens, new Ast\Type\CallableTypeParameterNode($type, $isReference, $isVariadic, $parameterName, $isOptional), $startLine, $startIndex);
    }
    /** @phpstan-impure */
    private function parseCallableReturnType(TokenIterator $tokens): Ast\Type\TypeNode
    {
        $startLine = $tokens->currentTokenLine();
        $startIndex = $tokens->currentTokenIndex();
        if ($tokens->isCurrentTokenType(Lexer::TOKEN_NULLABLE)) {
            return $this->parseNullable($tokens);
        } elseif ($tokens->tryConsumeTokenType(Lexer::TOKEN_OPEN_PARENTHESES)) {
            $type = $this->subParse($tokens);
            $tokens->consumeTokenType(Lexer::TOKEN_CLOSE_PARENTHESES);
            if ($tokens->isCurrentTokenType(Lexer::TOKEN_OPEN_SQUARE_BRACKET)) {
                $type = $this->tryParseArrayOrOffsetAccess($tokens, $type);
            }
            return $type;
        } elseif ($tokens->tryConsumeTokenType(Lexer::TOKEN_THIS_VARIABLE)) {
            $type = new Ast\Type\ThisTypeNode();
            if ($tokens->isCurrentTokenType(Lexer::TOKEN_OPEN_SQUARE_BRACKET)) {
                $type = $this->tryParseArrayOrOffsetAccess($tokens, $this->enrichWithAttributes($tokens, $type, $startLine, $startIndex));
            }
            return $type;
        } else {
            $currentTokenValue = $tokens->currentTokenValue();
            $tokens->pushSavePoint();
            // because of ConstFetchNode
            if ($tokens->tryConsumeTokenType(Lexer::TOKEN_IDENTIFIER)) {
                $type = new Ast\Type\IdentifierTypeNode($currentTokenValue);
                if (!$tokens->isCurrentTokenType(Lexer::TOKEN_DOUBLE_COLON)) {
                    if ($tokens->isCurrentTokenType(Lexer::TOKEN_OPEN_ANGLE_BRACKET)) {
                        $type = $this->parseGeneric($tokens, $this->enrichWithAttributes($tokens, $type, $startLine, $startIndex));
                        if ($tokens->isCurrentTokenType(Lexer::TOKEN_OPEN_SQUARE_BRACKET)) {
                            $type = $this->tryParseArrayOrOffsetAccess($tokens, $this->enrichWithAttributes($tokens, $type, $startLine, $startIndex));
                        }
                    } elseif ($tokens->isCurrentTokenType(Lexer::TOKEN_OPEN_SQUARE_BRACKET)) {
                        $type = $this->tryParseArrayOrOffsetAccess($tokens, $this->enrichWithAttributes($tokens, $type, $startLine, $startIndex));
                    } elseif (in_array($type->name, [Ast\Type\ArrayShapeNode::KIND_ARRAY, Ast\Type\ArrayShapeNode::KIND_LIST, Ast\Type\ArrayShapeNode::KIND_NON_EMPTY_ARRAY, Ast\Type\ArrayShapeNode::KIND_NON_EMPTY_LIST, 'object'], \true) && $tokens->isCurrentTokenType(Lexer::TOKEN_OPEN_CURLY_BRACKET) && !$tokens->isPrecededByHorizontalWhitespace()) {
                        if ($type->name === 'object') {
                            $type = $this->parseObjectShape($tokens);
                        } else {
                            $type = $this->parseArrayShape($tokens, $this->enrichWithAttributes($tokens, $type, $startLine, $startIndex), $type->name);
                        }
                        if ($tokens->isCurrentTokenType(Lexer::TOKEN_OPEN_SQUARE_BRACKET)) {
                            $type = $this->tryParseArrayOrOffsetAccess($tokens, $this->enrichWithAttributes($tokens, $type, $startLine, $startIndex));
                        }
                    }
                    return $type;
                } else {
                    $tokens->rollback();
                    // because of ConstFetchNode
                }
            } else {
                $tokens->dropSavePoint();
                // because of ConstFetchNode
            }
        }
        $currentTokenValue = $tokens->currentTokenValue();
        $currentTokenType = $tokens->currentTokenType();
        $currentTokenOffset = $tokens->currentTokenOffset();
        $currentTokenLine = $tokens->currentTokenLine();
        try {
            $constExpr = $this->constExprParser->parse($tokens);
            if ($constExpr instanceof Ast\ConstExpr\ConstExprArrayNode) {
                throw new ParserException($currentTokenValue, $currentTokenType, $currentTokenOffset, Lexer::TOKEN_IDENTIFIER, null, $currentTokenLine);
            }
            $type = $this->enrichWithAttributes($tokens, new Ast\Type\ConstTypeNode($constExpr), $startLine, $startIndex);
            if ($tokens->isCurrentTokenType(Lexer::TOKEN_OPEN_SQUARE_BRACKET)) {
                $type = $this->tryParseArrayOrOffsetAccess($tokens, $type);
            }
            return $type;
        } catch (LogicException $e) {
            throw new ParserException($currentTokenValue, $currentTokenType, $currentTokenOffset, Lexer::TOKEN_IDENTIFIER, null, $currentTokenLine);
        }
    }
    /** @phpstan-impure */
    private function tryParseCallable(TokenIterator $tokens, Ast\Type\IdentifierTypeNode $identifier, bool $hasTemplate): Ast\Type\TypeNode
    {
        try {
            $tokens->pushSavePoint();
            $type = $this->parseCallable($tokens, $identifier, $hasTemplate);
            $tokens->dropSavePoint();
        } catch (ParserException $e) {
            $tokens->rollback();
            $type = $identifier;
        }
        return $type;
    }
    /** @phpstan-impure */
    private function tryParseArrayOrOffsetAccess(TokenIterator $tokens, Ast\Type\TypeNode $type): Ast\Type\TypeNode
    {
        $startLine = $type->getAttribute(Ast\Attribute::START_LINE);
        $startIndex = $type->getAttribute(Ast\Attribute::START_INDEX);
        try {
            while ($tokens->isCurrentTokenType(Lexer::TOKEN_OPEN_SQUARE_BRACKET)) {
                $tokens->pushSavePoint();
                $canBeOffsetAccessType = !$tokens->isPrecededByHorizontalWhitespace();
                $tokens->consumeTokenType(Lexer::TOKEN_OPEN_SQUARE_BRACKET);
                if ($canBeOffsetAccessType && !$tokens->isCurrentTokenType(Lexer::TOKEN_CLOSE_SQUARE_BRACKET)) {
                    $offset = $this->parse($tokens);
                    $tokens->consumeTokenType(Lexer::TOKEN_CLOSE_SQUARE_BRACKET);
                    $tokens->dropSavePoint();
                    $type = new Ast\Type\OffsetAccessTypeNode($type, $offset);
                    if ($startLine !== null && $startIndex !== null) {
                        $type = $this->enrichWithAttributes($tokens, $type, $startLine, $startIndex);
                    }
                } else {
                    $tokens->consumeTokenType(Lexer::TOKEN_CLOSE_SQUARE_BRACKET);
                    $tokens->dropSavePoint();
                    $type = new Ast\Type\ArrayTypeNode($type);
                    if ($startLine !== null && $startIndex !== null) {
                        $type = $this->enrichWithAttributes($tokens, $type, $startLine, $startIndex);
                    }
                }
            }
        } catch (ParserException $e) {
            $tokens->rollback();
        }
        return $type;
    }
    /**
     * @phpstan-impure
     * @param Ast\Type\ArrayShapeNode::KIND_* $kind
     */
    private function parseArrayShape(TokenIterator $tokens, Ast\Type\TypeNode $type, string $kind): Ast\Type\ArrayShapeNode
    {
        $tokens->consumeTokenType(Lexer::TOKEN_OPEN_CURLY_BRACKET);
        $items = [];
        $sealed = \true;
        $unsealedType = null;
        $done = \false;
        do {
            $tokens->skipNewLineTokensAndConsumeComments();
            if ($tokens->tryConsumeTokenType(Lexer::TOKEN_CLOSE_CURLY_BRACKET)) {
                return Ast\Type\ArrayShapeNode::createSealed($items, $kind);
            }
            if ($tokens->tryConsumeTokenType(Lexer::TOKEN_VARIADIC)) {
                $sealed = \false;
                $tokens->skipNewLineTokensAndConsumeComments();
                if ($tokens->isCurrentTokenType(Lexer::TOKEN_OPEN_ANGLE_BRACKET)) {
                    if ($kind === Ast\Type\ArrayShapeNode::KIND_ARRAY) {
                        $unsealedType = $this->parseArrayShapeUnsealedType($tokens);
                    } else {
                        $unsealedType = $this->parseListShapeUnsealedType($tokens);
                    }
                    $tokens->skipNewLineTokensAndConsumeComments();
                }
                $tokens->tryConsumeTokenType(Lexer::TOKEN_COMMA);
                break;
            }
            $items[] = $this->parseArrayShapeItem($tokens);
            $tokens->skipNewLineTokensAndConsumeComments();
            if (!$tokens->tryConsumeTokenType(Lexer::TOKEN_COMMA)) {
                $done = \true;
            }
            if ($tokens->currentTokenType() !== Lexer::TOKEN_COMMENT) {
                continue;
            }
            $tokens->next();
        } while (!$done);
        $tokens->skipNewLineTokensAndConsumeComments();
        $tokens->consumeTokenType(Lexer::TOKEN_CLOSE_CURLY_BRACKET);
        if ($sealed) {
            return Ast\Type\ArrayShapeNode::createSealed($items, $kind);
        }
        return Ast\Type\ArrayShapeNode::createUnsealed($items, $unsealedType, $kind);
    }
    /** @phpstan-impure */
    private function parseArrayShapeItem(TokenIterator $tokens): Ast\Type\ArrayShapeItemNode
    {
        $startLine = $tokens->currentTokenLine();
        $startIndex = $tokens->currentTokenIndex();
        // parse any comments above the item
        $tokens->skipNewLineTokensAndConsumeComments();
        try {
            $tokens->pushSavePoint();
            $key = $this->parseArrayShapeKey($tokens);
            $optional = $tokens->tryConsumeTokenType(Lexer::TOKEN_NULLABLE);
            $tokens->consumeTokenType(Lexer::TOKEN_COLON);
            $value = $this->parse($tokens);
            $tokens->dropSavePoint();
            return $this->enrichWithAttributes($tokens, new Ast\Type\ArrayShapeItemNode($key, $optional, $value), $startLine, $startIndex);
        } catch (ParserException $e) {
            $tokens->rollback();
            $value = $this->parse($tokens);
            return $this->enrichWithAttributes($tokens, new Ast\Type\ArrayShapeItemNode(null, \false, $value), $startLine, $startIndex);
        }
    }
    /**
     * @phpstan-impure
     * @return Ast\ConstExpr\ConstExprIntegerNode|Ast\ConstExpr\ConstExprStringNode|Ast\ConstExpr\ConstFetchNode|Ast\Type\IdentifierTypeNode
     */
    private function parseArrayShapeKey(TokenIterator $tokens)
    {
        $startIndex = $tokens->currentTokenIndex();
        $startLine = $tokens->currentTokenLine();
        if ($tokens->isCurrentTokenType(Lexer::TOKEN_INTEGER)) {
            $key = new Ast\ConstExpr\ConstExprIntegerNode(str_replace('_', '', $tokens->currentTokenValue()));
            $tokens->next();
        } elseif ($tokens->isCurrentTokenType(Lexer::TOKEN_SINGLE_QUOTED_STRING)) {
            $key = new Ast\ConstExpr\ConstExprStringNode(StringUnescaper::unescapeString($tokens->currentTokenValue()), Ast\ConstExpr\ConstExprStringNode::SINGLE_QUOTED);
            $tokens->next();
        } elseif ($tokens->isCurrentTokenType(Lexer::TOKEN_DOUBLE_QUOTED_STRING)) {
            $key = new Ast\ConstExpr\ConstExprStringNode(StringUnescaper::unescapeString($tokens->currentTokenValue()), Ast\ConstExpr\ConstExprStringNode::DOUBLE_QUOTED);
            $tokens->next();
        } else {
            $identifier = $tokens->currentTokenValue();
            $tokens->consumeTokenType(Lexer::TOKEN_IDENTIFIER);
            if ($tokens->tryConsumeTokenType(Lexer::TOKEN_DOUBLE_COLON)) {
                $classConstantName = $tokens->currentTokenValue();
                $tokens->consumeTokenType(Lexer::TOKEN_IDENTIFIER);
                $key = new Ast\ConstExpr\ConstFetchNode($identifier, $classConstantName);
            } else {
                $key = new Ast\Type\IdentifierTypeNode($identifier);
            }
        }
        return $this->enrichWithAttributes($tokens, $key, $startLine, $startIndex);
    }
    /**
     * @phpstan-impure
     */
    private function parseArrayShapeUnsealedType(TokenIterator $tokens): Ast\Type\ArrayShapeUnsealedTypeNode
    {
        $startLine = $tokens->currentTokenLine();
        $startIndex = $tokens->currentTokenIndex();
        $tokens->consumeTokenType(Lexer::TOKEN_OPEN_ANGLE_BRACKET);
        $tokens->skipNewLineTokensAndConsumeComments();
        $valueType = $this->parse($tokens);
        $tokens->skipNewLineTokensAndConsumeComments();
        $keyType = null;
        if ($tokens->tryConsumeTokenType(Lexer::TOKEN_COMMA)) {
            $tokens->skipNewLineTokensAndConsumeComments();
            $keyType = $valueType;
            $valueType = $this->parse($tokens);
            $tokens->skipNewLineTokensAndConsumeComments();
        }
        $tokens->consumeTokenType(Lexer::TOKEN_CLOSE_ANGLE_BRACKET);
        return $this->enrichWithAttributes($tokens, new Ast\Type\ArrayShapeUnsealedTypeNode($valueType, $keyType), $startLine, $startIndex);
    }
    /**
     * @phpstan-impure
     */
    private function parseListShapeUnsealedType(TokenIterator $tokens): Ast\Type\ArrayShapeUnsealedTypeNode
    {
        $startLine = $tokens->currentTokenLine();
        $startIndex = $tokens->currentTokenIndex();
        $tokens->consumeTokenType(Lexer::TOKEN_OPEN_ANGLE_BRACKET);
        $tokens->skipNewLineTokensAndConsumeComments();
        $valueType = $this->parse($tokens);
        $tokens->skipNewLineTokensAndConsumeComments();
        $tokens->consumeTokenType(Lexer::TOKEN_CLOSE_ANGLE_BRACKET);
        return $this->enrichWithAttributes($tokens, new Ast\Type\ArrayShapeUnsealedTypeNode($valueType, null), $startLine, $startIndex);
    }
    /**
     * @phpstan-impure
     */
    private function parseObjectShape(TokenIterator $tokens): Ast\Type\ObjectShapeNode
    {
        $tokens->consumeTokenType(Lexer::TOKEN_OPEN_CURLY_BRACKET);
        $items = [];
        do {
            $tokens->skipNewLineTokensAndConsumeComments();
            if ($tokens->tryConsumeTokenType(Lexer::TOKEN_CLOSE_CURLY_BRACKET)) {
                return new Ast\Type\ObjectShapeNode($items);
            }
            $items[] = $this->parseObjectShapeItem($tokens);
            $tokens->skipNewLineTokensAndConsumeComments();
        } while ($tokens->tryConsumeTokenType(Lexer::TOKEN_COMMA));
        $tokens->skipNewLineTokensAndConsumeComments();
        $tokens->consumeTokenType(Lexer::TOKEN_CLOSE_CURLY_BRACKET);
        return new Ast\Type\ObjectShapeNode($items);
    }
    /** @phpstan-impure */
    private function parseObjectShapeItem(TokenIterator $tokens): Ast\Type\ObjectShapeItemNode
    {
        $startLine = $tokens->currentTokenLine();
        $startIndex = $tokens->currentTokenIndex();
        $tokens->skipNewLineTokensAndConsumeComments();
        $key = $this->parseObjectShapeKey($tokens);
        $optional = $tokens->tryConsumeTokenType(Lexer::TOKEN_NULLABLE);
        $tokens->consumeTokenType(Lexer::TOKEN_COLON);
        $value = $this->parse($tokens);
        return $this->enrichWithAttributes($tokens, new Ast\Type\ObjectShapeItemNode($key, $optional, $value), $startLine, $startIndex);
    }
    /**
     * @phpstan-impure
     * @return Ast\ConstExpr\ConstExprStringNode|Ast\Type\IdentifierTypeNode
     */
    private function parseObjectShapeKey(TokenIterator $tokens)
    {
        $startLine = $tokens->currentTokenLine();
        $startIndex = $tokens->currentTokenIndex();
        if ($tokens->isCurrentTokenType(Lexer::TOKEN_SINGLE_QUOTED_STRING)) {
            $key = new Ast\ConstExpr\ConstExprStringNode(StringUnescaper::unescapeString($tokens->currentTokenValue()), Ast\ConstExpr\ConstExprStringNode::SINGLE_QUOTED);
            $tokens->next();
        } elseif ($tokens->isCurrentTokenType(Lexer::TOKEN_DOUBLE_QUOTED_STRING)) {
            $key = new Ast\ConstExpr\ConstExprStringNode(StringUnescaper::unescapeString($tokens->currentTokenValue()), Ast\ConstExpr\ConstExprStringNode::DOUBLE_QUOTED);
            $tokens->next();
        } else {
            $key = new Ast\Type\IdentifierTypeNode($tokens->currentTokenValue());
            $tokens->consumeTokenType(Lexer::TOKEN_IDENTIFIER);
        }
        return $this->enrichWithAttributes($tokens, $key, $startLine, $startIndex);
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\PHPStan\PhpDocParser\Parser;

use LogicException;
use _ContaoManager\PHPStan\PhpDocParser\Ast\Comment;
use _ContaoManager\PHPStan\PhpDocParser\Lexer\Lexer;
use function array_pop;
use function assert;
use function count;
use function in_array;
use function strlen;
use function substr;
class TokenIterator
{
    /** @var list<array{string, int, int}> */
    private array $tokens;
    private int $index;
    /** @var list<Comment> */
    private array $comments = [];
    /** @var list<array{int, list<Comment>}> */
    private array $savePoints = [];
    /** @var list<int> */
    private array $skippedTokenTypes = [Lexer::TOKEN_HORIZONTAL_WS];
    private ?string $newline = null;
    /**
     * @param list<array{string, int, int}> $tokens
     */
    public function __construct(array $tokens, int $index = 0)
    {
        $this->tokens = $tokens;
        $this->index = $index;
        $this->skipIrrelevantTokens();
    }
    /**
     * @return list<array{string, int, int}>
     */
    public function getTokens(): array
    {
        return $this->tokens;
    }
    public function getContentBetween(int $startPos, int $endPos): string
    {
        if ($startPos < 0 || $endPos > count($this->tokens)) {
            throw new LogicException();
        }
        $content = '';
        for ($i = $startPos; $i < $endPos; $i++) {
            $content .= $this->tokens[$i][Lexer::VALUE_OFFSET];
        }
        return $content;
    }
    public function getTokenCount(): int
    {
        return count($this->tokens);
    }
    public function currentTokenValue(): string
    {
        return $this->tokens[$this->index][Lexer::VALUE_OFFSET];
    }
    public function currentTokenType(): int
    {
        return $this->tokens[$this->index][Lexer::TYPE_OFFSET];
    }
    public function currentTokenOffset(): int
    {
        $offset = 0;
        for ($i = 0; $i < $this->index; $i++) {
            $offset += strlen($this->tokens[$i][Lexer::VALUE_OFFSET]);
        }
        return $offset;
    }
    public function currentTokenLine(): int
    {
        return $this->tokens[$this->index][Lexer::LINE_OFFSET];
    }
    public function currentTokenIndex(): int
    {
        return $this->index;
    }
    public function endIndexOfLastRelevantToken(): int
    {
        $endIndex = $this->currentTokenIndex();
        $endIndex--;
        while (in_array($this->tokens[$endIndex][Lexer::TYPE_OFFSET], $this->skippedTokenTypes, \true)) {
            if (!isset($this->tokens[$endIndex - 1])) {
                break;
            }
            $endIndex--;
        }
        return $endIndex;
    }
    public function isCurrentTokenValue(string $tokenValue): bool
    {
        return $this->tokens[$this->index][Lexer::VALUE_OFFSET] === $tokenValue;
    }
    public function isCurrentTokenType(int ...$tokenType): bool
    {
        return in_array($this->tokens[$this->index][Lexer::TYPE_OFFSET], $tokenType, \true);
    }
    public function isPrecededByHorizontalWhitespace(): bool
    {
        return ($this->tokens[$this->index - 1][Lexer::TYPE_OFFSET] ?? -1) === Lexer::TOKEN_HORIZONTAL_WS;
    }
    /**
     * @throws ParserException
     */
    public function consumeTokenType(int $tokenType): void
    {
        if ($this->tokens[$this->index][Lexer::TYPE_OFFSET] !== $tokenType) {
            $this->throwError($tokenType);
        }
        if ($tokenType === Lexer::TOKEN_PHPDOC_EOL) {
            if ($this->newline === null) {
                $this->detectNewline();
            }
        }
        $this->next();
    }
    /**
     * @throws ParserException
     */
    public function consumeTokenValue(int $tokenType, string $tokenValue): void
    {
        if ($this->tokens[$this->index][Lexer::TYPE_OFFSET] !== $tokenType || $this->tokens[$this->index][Lexer::VALUE_OFFSET] !== $tokenValue) {
            $this->throwError($tokenType, $tokenValue);
        }
        $this->next();
    }
    /** @phpstan-impure */
    public function tryConsumeTokenValue(string $tokenValue): bool
    {
        if ($this->tokens[$this->index][Lexer::VALUE_OFFSET] !== $tokenValue) {
            return \false;
        }
        $this->next();
        return \true;
    }
    /**
     * @return list<Comment>
     */
    public function flushComments(): array
    {
        $res = $this->comments;
        $this->comments = [];
        return $res;
    }
    /** @phpstan-impure */
    public function tryConsumeTokenType(int $tokenType): bool
    {
        if ($this->tokens[$this->index][Lexer::TYPE_OFFSET] !== $tokenType) {
            return \false;
        }
        if ($tokenType === Lexer::TOKEN_PHPDOC_EOL) {
            if ($this->newline === null) {
                $this->detectNewline();
            }
        }
        $this->next();
        return \true;
    }
    /**
     * @deprecated Use skipNewLineTokensAndConsumeComments instead (when parsing a type)
     */
    public function skipNewLineTokens(): void
    {
        if (!$this->isCurrentTokenType(Lexer::TOKEN_PHPDOC_EOL)) {
            return;
        }
        do {
            $foundNewLine = $this->tryConsumeTokenType(Lexer::TOKEN_PHPDOC_EOL);
        } while ($foundNewLine === \true);
    }
    public function skipNewLineTokensAndConsumeComments(): void
    {
        if ($this->currentTokenType() === Lexer::TOKEN_COMMENT) {
            $this->comments[] = new Comment($this->currentTokenValue(), $this->currentTokenLine(), $this->currentTokenIndex());
            $this->next();
        }
        if (!$this->isCurrentTokenType(Lexer::TOKEN_PHPDOC_EOL)) {
            return;
        }
        do {
            $foundNewLine = $this->tryConsumeTokenType(Lexer::TOKEN_PHPDOC_EOL);
            if ($this->currentTokenType() !== Lexer::TOKEN_COMMENT) {
                continue;
            }
            $this->comments[] = new Comment($this->currentTokenValue(), $this->currentTokenLine(), $this->currentTokenIndex());
            $this->next();
        } while ($foundNewLine === \true);
    }
    private function detectNewline(): void
    {
        $value = $this->currentTokenValue();
        if (substr($value, 0, 2) === "\r\n") {
            $this->newline = "\r\n";
        } elseif (substr($value, 0, 1) === "\n") {
            $this->newline = "\n";
        }
    }
    public function getSkippedHorizontalWhiteSpaceIfAny(): string
    {
        if ($this->index > 0 && $this->tokens[$this->index - 1][Lexer::TYPE_OFFSET] === Lexer::TOKEN_HORIZONTAL_WS) {
            return $this->tokens[$this->index - 1][Lexer::VALUE_OFFSET];
        }
        return '';
    }
    /** @phpstan-impure */
    public function joinUntil(int ...$tokenType): string
    {
        $s = '';
        while (!in_array($this->tokens[$this->index][Lexer::TYPE_OFFSET], $tokenType, \true)) {
            $s .= $this->tokens[$this->index++][Lexer::VALUE_OFFSET];
        }
        return $s;
    }
    public function next(): void
    {
        $this->index++;
        $this->skipIrrelevantTokens();
    }
    private function skipIrrelevantTokens(): void
    {
        if (!isset($this->tokens[$this->index])) {
            return;
        }
        while (in_array($this->tokens[$this->index][Lexer::TYPE_OFFSET], $this->skippedTokenTypes, \true)) {
            if (!isset($this->tokens[$this->index + 1])) {
                break;
            }
            $this->index++;
        }
    }
    public function addEndOfLineToSkippedTokens(): void
    {
        $this->skippedTokenTypes = [Lexer::TOKEN_HORIZONTAL_WS, Lexer::TOKEN_PHPDOC_EOL];
    }
    public function removeEndOfLineFromSkippedTokens(): void
    {
        $this->skippedTokenTypes = [Lexer::TOKEN_HORIZONTAL_WS];
    }
    /** @phpstan-impure */
    public function forwardToTheEnd(): void
    {
        $lastToken = count($this->tokens) - 1;
        $this->index = $lastToken;
    }
    public function pushSavePoint(): void
    {
        $this->savePoints[] = [$this->index, $this->comments];
    }
    public function dropSavePoint(): void
    {
        array_pop($this->savePoints);
    }
    public function rollback(): void
    {
        $savepoint = array_pop($this->savePoints);
        assert($savepoint !== null);
        [$this->index, $this->comments] = $savepoint;
    }
    /**
     * @throws ParserException
     */
    private function throwError(int $expectedTokenType, ?string $expectedTokenValue = null): void
    {
        throw new ParserException($this->currentTokenValue(), $this->currentTokenType(), $this->currentTokenOffset(), $expectedTokenType, $expectedTokenValue, $this->currentTokenLine());
    }
    /**
     * Check whether the position is directly preceded by a certain token type.
     *
     * During this check TOKEN_HORIZONTAL_WS and TOKEN_PHPDOC_EOL are skipped
     */
    public function hasTokenImmediatelyBefore(int $pos, int $expectedTokenType): bool
    {
        $tokens = $this->tokens;
        $pos--;
        for (; $pos >= 0; $pos--) {
            $token = $tokens[$pos];
            $type = $token[Lexer::TYPE_OFFSET];
            if ($type === $expectedTokenType) {
                return \true;
            }
            if (!in_array($type, [Lexer::TOKEN_HORIZONTAL_WS, Lexer::TOKEN_PHPDOC_EOL], \true)) {
                break;
            }
        }
        return \false;
    }
    /**
     * Check whether the position is directly followed by a certain token type.
     *
     * During this check TOKEN_HORIZONTAL_WS and TOKEN_PHPDOC_EOL are skipped
     */
    public function hasTokenImmediatelyAfter(int $pos, int $expectedTokenType): bool
    {
        $tokens = $this->tokens;
        $pos++;
        for ($c = count($tokens); $pos < $c; $pos++) {
            $token = $tokens[$pos];
            $type = $token[Lexer::TYPE_OFFSET];
            if ($type === $expectedTokenType) {
                return \true;
            }
            if (!in_array($type, [Lexer::TOKEN_HORIZONTAL_WS, Lexer::TOKEN_PHPDOC_EOL], \true)) {
                break;
            }
        }
        return \false;
    }
    public function getDetectedNewline(): ?string
    {
        return $this->newline;
    }
    /**
     * Whether the given position is immediately surrounded by parenthesis.
     */
    public function hasParentheses(int $startPos, int $endPos): bool
    {
        return $this->hasTokenImmediatelyBefore($startPos, Lexer::TOKEN_OPEN_PARENTHESES) && $this->hasTokenImmediatelyAfter($endPos, Lexer::TOKEN_CLOSE_PARENTHESES);
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\PHPStan\PhpDocParser;

class ParserConfig
{
    public bool $useLinesAttributes;
    public bool $useIndexAttributes;
    public bool $useCommentsAttributes;
    /**
     * @param array{lines?: bool, indexes?: bool, comments?: bool} $usedAttributes
     */
    public function __construct(array $usedAttributes)
    {
        $this->useLinesAttributes = $usedAttributes['lines'] ?? \false;
        $this->useIndexAttributes = $usedAttributes['indexes'] ?? \false;
        $this->useCommentsAttributes = $usedAttributes['comments'] ?? \false;
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\PHPStan\PhpDocParser\Ast\PhpDoc;

use _ContaoManager\PHPStan\PhpDocParser\Ast\NodeAttributes;
use function trim;
class PureUnlessCallableIsImpureTagValueNode implements PhpDocTagValueNode
{
    use NodeAttributes;
    public string $parameterName;
    /** @var string (may be empty) */
    public string $description;
    public function __construct(string $parameterName, string $description)
    {
        $this->parameterName = $parameterName;
        $this->description = $description;
    }
    public function __toString(): string
    {
        return trim("{$this->parameterName} {$this->description}");
    }
    /**
     * @param array<string, mixed> $properties
     */
    public static function __set_state(array $properties): self
    {
        $instance = new self($properties['parameterName'], $properties['description']);
        if (isset($properties['attributes'])) {
            foreach ($properties['attributes'] as $key => $value) {
                $instance->setAttribute($key, $value);
            }
        }
        return $instance;
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\PHPStan\PhpDocParser\Ast\PhpDoc;

use _ContaoManager\PHPStan\PhpDocParser\Ast\NodeAttributes;
use _ContaoManager\PHPStan\PhpDocParser\Ast\Type\TypeNode;
use function trim;
class MixinTagValueNode implements PhpDocTagValueNode
{
    use NodeAttributes;
    public TypeNode $type;
    /** @var string (may be empty) */
    public string $description;
    public function __construct(TypeNode $type, string $description)
    {
        $this->type = $type;
        $this->description = $description;
    }
    public function __toString(): string
    {
        return trim("{$this->type} {$this->description}");
    }
    /**
     * @param array<string, mixed> $properties
     */
    public static function __set_state(array $properties): self
    {
        $instance = new self($properties['type'], $properties['description']);
        if (isset($properties['attributes'])) {
            foreach ($properties['attributes'] as $key => $value) {
                $instance->setAttribute($key, $value);
            }
        }
        return $instance;
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\PHPStan\PhpDocParser\Ast\PhpDoc;

use _ContaoManager\PHPStan\PhpDocParser\Ast\NodeAttributes;
use _ContaoManager\PHPStan\PhpDocParser\Ast\Type\TypeNode;
use function trim;
class TemplateTagValueNode implements PhpDocTagValueNode
{
    use NodeAttributes;
    /** @var non-empty-string */
    public string $name;
    public ?TypeNode $bound;
    public ?TypeNode $default;
    public ?TypeNode $lowerBound;
    /** @var string (may be empty) */
    public string $description;
    /**
     * @param non-empty-string $name
     */
    public function __construct(string $name, ?TypeNode $bound, string $description, ?TypeNode $default = null, ?TypeNode $lowerBound = null)
    {
        $this->name = $name;
        $this->bound = $bound;
        $this->lowerBound = $lowerBound;
        $this->default = $default;
        $this->description = $description;
    }
    public function __toString(): string
    {
        $upperBound = $this->bound !== null ? " of {$this->bound}" : '';
        $lowerBound = $this->lowerBound !== null ? " super {$this->lowerBound}" : '';
        $default = $this->default !== null ? " = {$this->default}" : '';
        return trim("{$this->name}{$upperBound}{$lowerBound}{$default} {$this->description}");
    }
    /**
     * @param array<string, mixed> $properties
     */
    public static function __set_state(array $properties): self
    {
        $instance = new self($properties['name'], $properties['bound'], $properties['description'], $properties['default'] ?? null, $properties['lowerBound'] ?? null);
        if (isset($properties['attributes'])) {
            foreach ($properties['attributes'] as $key => $value) {
                $instance->setAttribute($key, $value);
            }
        }
        return $instance;
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\PHPStan\PhpDocParser\Ast\PhpDoc;

use _ContaoManager\PHPStan\PhpDocParser\Ast\NodeAttributes;
use _ContaoManager\PHPStan\PhpDocParser\Ast\Type\TypeNode;
use function trim;
class AssertTagValueNode implements PhpDocTagValueNode
{
    use NodeAttributes;
    public TypeNode $type;
    public string $parameter;
    public bool $isNegated;
    public bool $isEquality;
    /** @var string (may be empty) */
    public string $description;
    public function __construct(TypeNode $type, string $parameter, bool $isNegated, string $description, bool $isEquality)
    {
        $this->type = $type;
        $this->parameter = $parameter;
        $this->isNegated = $isNegated;
        $this->isEquality = $isEquality;
        $this->description = $description;
    }
    public function __toString(): string
    {
        $isNegated = $this->isNegated ? '!' : '';
        $isEquality = $this->isEquality ? '=' : '';
        return trim("{$isNegated}{$isEquality}{$this->type} {$this->parameter} {$this->description}");
    }
    /**
     * @param array<string, mixed> $properties
     */
    public static function __set_state(array $properties): self
    {
        $instance = new self($properties['type'], $properties['parameter'], $properties['isNegated'], $properties['description'], $properties['isEquality']);
        if (isset($properties['attributes'])) {
            foreach ($properties['attributes'] as $key => $value) {
                $instance->setAttribute($key, $value);
            }
        }
        return $instance;
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\PHPStan\PhpDocParser\Ast\PhpDoc;

use _ContaoManager\PHPStan\PhpDocParser\Ast\NodeAttributes;
use _ContaoManager\PHPStan\PhpDocParser\Ast\Type\TypeNode;
use function trim;
class ThrowsTagValueNode implements PhpDocTagValueNode
{
    use NodeAttributes;
    public TypeNode $type;
    /** @var string (may be empty) */
    public string $description;
    public function __construct(TypeNode $type, string $description)
    {
        $this->type = $type;
        $this->description = $description;
    }
    public function __toString(): string
    {
        return trim("{$this->type} {$this->description}");
    }
    /**
     * @param array<string, mixed> $properties
     */
    public static function __set_state(array $properties): self
    {
        $instance = new self($properties['type'], $properties['description']);
        if (isset($properties['attributes'])) {
            foreach ($properties['attributes'] as $key => $value) {
                $instance->setAttribute($key, $value);
            }
        }
        return $instance;
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\PHPStan\PhpDocParser\Ast\PhpDoc;

use _ContaoManager\PHPStan\PhpDocParser\Ast\NodeAttributes;
use function trim;
class ParamLaterInvokedCallableTagValueNode implements PhpDocTagValueNode
{
    use NodeAttributes;
    public string $parameterName;
    /** @var string (may be empty) */
    public string $description;
    public function __construct(string $parameterName, string $description)
    {
        $this->parameterName = $parameterName;
        $this->description = $description;
    }
    public function __toString(): string
    {
        return trim("{$this->parameterName} {$this->description}");
    }
    /**
     * @param array<string, mixed> $properties
     */
    public static function __set_state(array $properties): self
    {
        $instance = new self($properties['parameterName'], $properties['description']);
        if (isset($properties['attributes'])) {
            foreach ($properties['attributes'] as $key => $value) {
                $instance->setAttribute($key, $value);
            }
        }
        return $instance;
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\PHPStan\PhpDocParser\Ast\PhpDoc;

use _ContaoManager\PHPStan\PhpDocParser\Ast\Node;
interface PhpDocTagValueNode extends Node
{
}
<?php

declare (strict_types=1);
namespace _ContaoManager\PHPStan\PhpDocParser\Ast\PhpDoc;

use _ContaoManager\PHPStan\PhpDocParser\Ast\NodeAttributes;
use _ContaoManager\PHPStan\PhpDocParser\Ast\Type\TypeNode;
use function trim;
class AssertTagPropertyValueNode implements PhpDocTagValueNode
{
    use NodeAttributes;
    public TypeNode $type;
    public string $parameter;
    public string $property;
    public bool $isNegated;
    public bool $isEquality;
    /** @var string (may be empty) */
    public string $description;
    public function __construct(TypeNode $type, string $parameter, string $property, bool $isNegated, string $description, bool $isEquality)
    {
        $this->type = $type;
        $this->parameter = $parameter;
        $this->property = $property;
        $this->isNegated = $isNegated;
        $this->isEquality = $isEquality;
        $this->description = $description;
    }
    public function __toString(): string
    {
        $isNegated = $this->isNegated ? '!' : '';
        $isEquality = $this->isEquality ? '=' : '';
        return trim("{$isNegated}{$isEquality}{$this->type} {$this->parameter}->{$this->property} {$this->description}");
    }
    /**
     * @param array<string, mixed> $properties
     */
    public static function __set_state(array $properties): self
    {
        $instance = new self($properties['type'], $properties['parameter'], $properties['property'], $properties['isNegated'], $properties['description'], $properties['isEquality']);
        if (isset($properties['attributes'])) {
            foreach ($properties['attributes'] as $key => $value) {
                $instance->setAttribute($key, $value);
            }
        }
        return $instance;
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\PHPStan\PhpDocParser\Ast\PhpDoc;

use _ContaoManager\PHPStan\PhpDocParser\Ast\NodeAttributes;
use _ContaoManager\PHPStan\PhpDocParser\Ast\Type\TypeNode;
use function trim;
class RequireImplementsTagValueNode implements PhpDocTagValueNode
{
    use NodeAttributes;
    public TypeNode $type;
    /** @var string (may be empty) */
    public string $description;
    public function __construct(TypeNode $type, string $description)
    {
        $this->type = $type;
        $this->description = $description;
    }
    public function __toString(): string
    {
        return trim("{$this->type} {$this->description}");
    }
    /**
     * @param array<string, mixed> $properties
     */
    public static function __set_state(array $properties): self
    {
        $instance = new self($properties['type'], $properties['description']);
        if (isset($properties['attributes'])) {
            foreach ($properties['attributes'] as $key => $value) {
                $instance->setAttribute($key, $value);
            }
        }
        return $instance;
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\PHPStan\PhpDocParser\Ast\PhpDoc;

use _ContaoManager\PHPStan\PhpDocParser\Ast\NodeAttributes;
use _ContaoManager\PHPStan\PhpDocParser\Ast\Type\TypeNode;
use function trim;
class SealedTagValueNode implements PhpDocTagValueNode
{
    use NodeAttributes;
    public TypeNode $type;
    /** @var string (may be empty) */
    public string $description;
    public function __construct(TypeNode $type, string $description)
    {
        $this->type = $type;
        $this->description = $description;
    }
    public function __toString(): string
    {
        return trim("{$this->type} {$this->description}");
    }
    /**
     * @param array<string, mixed> $properties
     */
    public static function __set_state(array $properties): self
    {
        $instance = new self($properties['type'], $properties['description']);
        if (isset($properties['attributes'])) {
            foreach ($properties['attributes'] as $key => $value) {
                $instance->setAttribute($key, $value);
            }
        }
        return $instance;
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\PHPStan\PhpDocParser\Ast\PhpDoc;

use _ContaoManager\PHPStan\PhpDocParser\Ast\NodeAttributes;
use _ContaoManager\PHPStan\PhpDocParser\Ast\Type\GenericTypeNode;
use function trim;
class ImplementsTagValueNode implements PhpDocTagValueNode
{
    use NodeAttributes;
    public GenericTypeNode $type;
    /** @var string (may be empty) */
    public string $description;
    public function __construct(GenericTypeNode $type, string $description)
    {
        $this->type = $type;
        $this->description = $description;
    }
    public function __toString(): string
    {
        return trim("{$this->type} {$this->description}");
    }
    /**
     * @param array<string, mixed> $properties
     */
    public static function __set_state(array $properties): self
    {
        $instance = new self($properties['type'], $properties['description']);
        if (isset($properties['attributes'])) {
            foreach ($properties['attributes'] as $key => $value) {
                $instance->setAttribute($key, $value);
            }
        }
        return $instance;
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\PHPStan\PhpDocParser\Ast\PhpDoc;

use _ContaoManager\PHPStan\PhpDocParser\Ast\NodeAttributes;
class PhpDocTextNode implements PhpDocChildNode
{
    use NodeAttributes;
    public string $text;
    public function __construct(string $text)
    {
        $this->text = $text;
    }
    public function __toString(): string
    {
        return $this->text;
    }
    /**
     * @param array<string, mixed> $properties
     */
    public static function __set_state(array $properties): self
    {
        $instance = new self($properties['text']);
        if (isset($properties['attributes'])) {
            foreach ($properties['attributes'] as $key => $value) {
                $instance->setAttribute($key, $value);
            }
        }
        return $instance;
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\PHPStan\PhpDocParser\Ast\PhpDoc;

use _ContaoManager\PHPStan\PhpDocParser\Ast\Node;
use _ContaoManager\PHPStan\PhpDocParser\Ast\NodeAttributes;
use function array_column;
use function array_filter;
use function array_map;
use function implode;
class PhpDocNode implements Node
{
    use NodeAttributes;
    /** @var PhpDocChildNode[] */
    public array $children;
    /**
     * @param PhpDocChildNode[] $children
     */
    public function __construct(array $children)
    {
        $this->children = $children;
    }
    /**
     * @return PhpDocTagNode[]
     */
    public function getTags(): array
    {
        return array_filter($this->children, static fn(PhpDocChildNode $child): bool => $child instanceof PhpDocTagNode);
    }
    /**
     * @return PhpDocTagNode[]
     */
    public function getTagsByName(string $tagName): array
    {
        return array_filter($this->getTags(), static fn(PhpDocTagNode $tag): bool => $tag->name === $tagName);
    }
    /**
     * @return VarTagValueNode[]
     */
    public function getVarTagValues(string $tagName = '@var'): array
    {
        return array_filter(array_column($this->getTagsByName($tagName), 'value'), static fn(PhpDocTagValueNode $value): bool => $value instanceof VarTagValueNode);
    }
    /**
     * @return ParamTagValueNode[]
     */
    public function getParamTagValues(string $tagName = '@param'): array
    {
        return array_filter(array_column($this->getTagsByName($tagName), 'value'), static fn(PhpDocTagValueNode $value): bool => $value instanceof ParamTagValueNode);
    }
    /**
     * @return TypelessParamTagValueNode[]
     */
    public function getTypelessParamTagValues(string $tagName = '@param'): array
    {
        return array_filter(array_column($this->getTagsByName($tagName), 'value'), static fn(PhpDocTagValueNode $value): bool => $value instanceof TypelessParamTagValueNode);
    }
    /**
     * @return ParamImmediatelyInvokedCallableTagValueNode[]
     */
    public function getParamImmediatelyInvokedCallableTagValues(string $tagName = '@param-immediately-invoked-callable'): array
    {
        return array_filter(array_column($this->getTagsByName($tagName), 'value'), static fn(PhpDocTagValueNode $value): bool => $value instanceof ParamImmediatelyInvokedCallableTagValueNode);
    }
    /**
     * @return ParamLaterInvokedCallableTagValueNode[]
     */
    public function getParamLaterInvokedCallableTagValues(string $tagName = '@param-later-invoked-callable'): array
    {
        return array_filter(array_column($this->getTagsByName($tagName), 'value'), static fn(PhpDocTagValueNode $value): bool => $value instanceof ParamLaterInvokedCallableTagValueNode);
    }
    /**
     * @return ParamClosureThisTagValueNode[]
     */
    public function getParamClosureThisTagValues(string $tagName = '@param-closure-this'): array
    {
        return array_filter(array_column($this->getTagsByName($tagName), 'value'), static fn(PhpDocTagValueNode $value): bool => $value instanceof ParamClosureThisTagValueNode);
    }
    /**
     * @return PureUnlessCallableIsImpureTagValueNode[]
     */
    public function getPureUnlessCallableIsImpureTagValues(string $tagName = '@pure-unless-callable-is-impure'): array
    {
        return array_filter(array_column($this->getTagsByName($tagName), 'value'), static fn(PhpDocTagValueNode $value): bool => $value instanceof PureUnlessCallableIsImpureTagValueNode);
    }
    /**
     * @return TemplateTagValueNode[]
     */
    public function getTemplateTagValues(string $tagName = '@template'): array
    {
        return array_filter(array_column($this->getTagsByName($tagName), 'value'), static fn(PhpDocTagValueNode $value): bool => $value instanceof TemplateTagValueNode);
    }
    /**
     * @return ExtendsTagValueNode[]
     */
    public function getExtendsTagValues(string $tagName = '@extends'): array
    {
        return array_filter(array_column($this->getTagsByName($tagName), 'value'), static fn(PhpDocTagValueNode $value): bool => $value instanceof ExtendsTagValueNode);
    }
    /**
     * @return ImplementsTagValueNode[]
     */
    public function getImplementsTagValues(string $tagName = '@implements'): array
    {
        return array_filter(array_column($this->getTagsByName($tagName), 'value'), static fn(PhpDocTagValueNode $value): bool => $value instanceof ImplementsTagValueNode);
    }
    /**
     * @return UsesTagValueNode[]
     */
    public function getUsesTagValues(string $tagName = '@use'): array
    {
        return array_filter(array_column($this->getTagsByName($tagName), 'value'), static fn(PhpDocTagValueNode $value): bool => $value instanceof UsesTagValueNode);
    }
    /**
     * @return ReturnTagValueNode[]
     */
    public function getReturnTagValues(string $tagName = '@return'): array
    {
        return array_filter(array_column($this->getTagsByName($tagName), 'value'), static fn(PhpDocTagValueNode $value): bool => $value instanceof ReturnTagValueNode);
    }
    /**
     * @return ThrowsTagValueNode[]
     */
    public function getThrowsTagValues(string $tagName = '@throws'): array
    {
        return array_filter(array_column($this->getTagsByName($tagName), 'value'), static fn(PhpDocTagValueNode $value): bool => $value instanceof ThrowsTagValueNode);
    }
    /**
     * @return MixinTagValueNode[]
     */
    public function getMixinTagValues(string $tagName = '@mixin'): array
    {
        return array_filter(array_column($this->getTagsByName($tagName), 'value'), static fn(PhpDocTagValueNode $value): bool => $value instanceof MixinTagValueNode);
    }
    /**
     * @return RequireExtendsTagValueNode[]
     */
    public function getRequireExtendsTagValues(string $tagName = '@phpstan-require-extends'): array
    {
        return array_filter(array_column($this->getTagsByName($tagName), 'value'), static fn(PhpDocTagValueNode $value): bool => $value instanceof RequireExtendsTagValueNode);
    }
    /**
     * @return RequireImplementsTagValueNode[]
     */
    public function getRequireImplementsTagValues(string $tagName = '@phpstan-require-implements'): array
    {
        return array_filter(array_column($this->getTagsByName($tagName), 'value'), static fn(PhpDocTagValueNode $value): bool => $value instanceof RequireImplementsTagValueNode);
    }
    /**
     * @return SealedTagValueNode[]
     */
    public function getSealedTagValues(string $tagName = '@phpstan-sealed'): array
    {
        return array_filter(array_column($this->getTagsByName($tagName), 'value'), static fn(PhpDocTagValueNode $value): bool => $value instanceof SealedTagValueNode);
    }
    /**
     * @return DeprecatedTagValueNode[]
     */
    public function getDeprecatedTagValues(): array
    {
        return array_filter(array_column($this->getTagsByName('@deprecated'), 'value'), static fn(PhpDocTagValueNode $value): bool => $value instanceof DeprecatedTagValueNode);
    }
    /**
     * @return PropertyTagValueNode[]
     */
    public function getPropertyTagValues(string $tagName = '@property'): array
    {
        return array_filter(array_column($this->getTagsByName($tagName), 'value'), static fn(PhpDocTagValueNode $value): bool => $value instanceof PropertyTagValueNode);
    }
    /**
     * @return PropertyTagValueNode[]
     */
    public function getPropertyReadTagValues(string $tagName = '@property-read'): array
    {
        return array_filter(array_column($this->getTagsByName($tagName), 'value'), static fn(PhpDocTagValueNode $value): bool => $value instanceof PropertyTagValueNode);
    }
    /**
     * @return PropertyTagValueNode[]
     */
    public function getPropertyWriteTagValues(string $tagName = '@property-write'): array
    {
        return array_filter(array_column($this->getTagsByName($tagName), 'value'), static fn(PhpDocTagValueNode $value): bool => $value instanceof PropertyTagValueNode);
    }
    /**
     * @return MethodTagValueNode[]
     */
    public function getMethodTagValues(string $tagName = '@method'): array
    {
        return array_filter(array_column($this->getTagsByName($tagName), 'value'), static fn(PhpDocTagValueNode $value): bool => $value instanceof MethodTagValueNode);
    }
    /**
     * @return TypeAliasTagValueNode[]
     */
    public function getTypeAliasTagValues(string $tagName = '@phpstan-type'): array
    {
        return array_filter(array_column($this->getTagsByName($tagName), 'value'), static fn(PhpDocTagValueNode $value): bool => $value instanceof TypeAliasTagValueNode);
    }
    /**
     * @return TypeAliasImportTagValueNode[]
     */
    public function getTypeAliasImportTagValues(string $tagName = '@phpstan-import-type'): array
    {
        return array_filter(array_column($this->getTagsByName($tagName), 'value'), static fn(PhpDocTagValueNode $value): bool => $value instanceof TypeAliasImportTagValueNode);
    }
    /**
     * @return AssertTagValueNode[]
     */
    public function getAssertTagValues(string $tagName = '@phpstan-assert'): array
    {
        return array_filter(array_column($this->getTagsByName($tagName), 'value'), static fn(PhpDocTagValueNode $value): bool => $value instanceof AssertTagValueNode);
    }
    /**
     * @return AssertTagPropertyValueNode[]
     */
    public function getAssertPropertyTagValues(string $tagName = '@phpstan-assert'): array
    {
        return array_filter(array_column($this->getTagsByName($tagName), 'value'), static fn(PhpDocTagValueNode $value): bool => $value instanceof AssertTagPropertyValueNode);
    }
    /**
     * @return AssertTagMethodValueNode[]
     */
    public function getAssertMethodTagValues(string $tagName = '@phpstan-assert'): array
    {
        return array_filter(array_column($this->getTagsByName($tagName), 'value'), static fn(PhpDocTagValueNode $value): bool => $value instanceof AssertTagMethodValueNode);
    }
    /**
     * @return SelfOutTagValueNode[]
     */
    public function getSelfOutTypeTagValues(string $tagName = '@phpstan-this-out'): array
    {
        return array_filter(array_column($this->getTagsByName($tagName), 'value'), static fn(PhpDocTagValueNode $value): bool => $value instanceof SelfOutTagValueNode);
    }
    /**
     * @return ParamOutTagValueNode[]
     */
    public function getParamOutTypeTagValues(string $tagName = '@param-out'): array
    {
        return array_filter(array_column($this->getTagsByName($tagName), 'value'), static fn(PhpDocTagValueNode $value): bool => $value instanceof ParamOutTagValueNode);
    }
    public function __toString(): string
    {
        $children = array_map(static function (PhpDocChildNode $child): string {
            $s = (string) $child;
            return $s === '' ? '' : ' ' . $s;
        }, $this->children);
        return "/**\n *" . implode("\n *", $children) . "\n */";
    }
    /**
     * @param array<string, mixed> $properties
     */
    public static function __set_state(array $properties): self
    {
        $instance = new self($properties['children']);
        if (isset($properties['attributes'])) {
            foreach ($properties['attributes'] as $key => $value) {
                $instance->setAttribute($key, $value);
            }
        }
        return $instance;
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\PHPStan\PhpDocParser\Ast\PhpDoc;

use _ContaoManager\PHPStan\PhpDocParser\Ast\NodeAttributes;
use _ContaoManager\PHPStan\PhpDocParser\Ast\Type\TypeNode;
use function trim;
class ParamClosureThisTagValueNode implements PhpDocTagValueNode
{
    use NodeAttributes;
    public TypeNode $type;
    public string $parameterName;
    /** @var string (may be empty) */
    public string $description;
    public function __construct(TypeNode $type, string $parameterName, string $description)
    {
        $this->type = $type;
        $this->parameterName = $parameterName;
        $this->description = $description;
    }
    public function __toString(): string
    {
        return trim("{$this->type} {$this->parameterName} {$this->description}");
    }
    /**
     * @param array<string, mixed> $properties
     */
    public static function __set_state(array $properties): self
    {
        $instance = new self($properties['type'], $properties['parameterName'], $properties['description']);
        if (isset($properties['attributes'])) {
            foreach ($properties['attributes'] as $key => $value) {
                $instance->setAttribute($key, $value);
            }
        }
        return $instance;
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\PHPStan\PhpDocParser\Ast\PhpDoc;

use _ContaoManager\PHPStan\PhpDocParser\Ast\NodeAttributes;
class GenericTagValueNode implements PhpDocTagValueNode
{
    use NodeAttributes;
    /** @var string (may be empty) */
    public string $value;
    public function __construct(string $value)
    {
        $this->value = $value;
    }
    public function __toString(): string
    {
        return $this->value;
    }
    /**
     * @param array<string, mixed> $properties
     */
    public static function __set_state(array $properties): self
    {
        $instance = new self($properties['value']);
        if (isset($properties['attributes'])) {
            foreach ($properties['attributes'] as $key => $value) {
                $instance->setAttribute($key, $value);
            }
        }
        return $instance;
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\PHPStan\PhpDocParser\Ast\PhpDoc;

use _ContaoManager\PHPStan\PhpDocParser\Ast\NodeAttributes;
use _ContaoManager\PHPStan\PhpDocParser\Ast\Type\TypeNode;
use function trim;
class TypeAliasTagValueNode implements PhpDocTagValueNode
{
    use NodeAttributes;
    public string $alias;
    public TypeNode $type;
    public function __construct(string $alias, TypeNode $type)
    {
        $this->alias = $alias;
        $this->type = $type;
    }
    public function __toString(): string
    {
        return trim("{$this->alias} {$this->type}");
    }
    /**
     * @param array<string, mixed> $properties
     */
    public static function __set_state(array $properties): self
    {
        $instance = new self($properties['alias'], $properties['type']);
        if (isset($properties['attributes'])) {
            foreach ($properties['attributes'] as $key => $value) {
                $instance->setAttribute($key, $value);
            }
        }
        return $instance;
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\PHPStan\PhpDocParser\Ast\PhpDoc;

use _ContaoManager\PHPStan\PhpDocParser\Ast\NodeAttributes;
use _ContaoManager\PHPStan\PhpDocParser\Ast\Type\TypeNode;
use function trim;
class ReturnTagValueNode implements PhpDocTagValueNode
{
    use NodeAttributes;
    public TypeNode $type;
    /** @var string (may be empty) */
    public string $description;
    public function __construct(TypeNode $type, string $description)
    {
        $this->type = $type;
        $this->description = $description;
    }
    public function __toString(): string
    {
        return trim("{$this->type} {$this->description}");
    }
    /**
     * @param array<string, mixed> $properties
     */
    public static function __set_state(array $properties): self
    {
        $instance = new self($properties['type'], $properties['description']);
        if (isset($properties['attributes'])) {
            foreach ($properties['attributes'] as $key => $value) {
                $instance->setAttribute($key, $value);
            }
        }
        return $instance;
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\PHPStan\PhpDocParser\Ast\PhpDoc;

use _ContaoManager\PHPStan\PhpDocParser\Ast\NodeAttributes;
use _ContaoManager\PHPStan\PhpDocParser\Ast\Type\GenericTypeNode;
use function trim;
class UsesTagValueNode implements PhpDocTagValueNode
{
    use NodeAttributes;
    public GenericTypeNode $type;
    /** @var string (may be empty) */
    public string $description;
    public function __construct(GenericTypeNode $type, string $description)
    {
        $this->type = $type;
        $this->description = $description;
    }
    public function __toString(): string
    {
        return trim("{$this->type} {$this->description}");
    }
    /**
     * @param array<string, mixed> $properties
     */
    public static function __set_state(array $properties): self
    {
        $instance = new self($properties['type'], $properties['description']);
        if (isset($properties['attributes'])) {
            foreach ($properties['attributes'] as $key => $value) {
                $instance->setAttribute($key, $value);
            }
        }
        return $instance;
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\PHPStan\PhpDocParser\Ast\PhpDoc;

use _ContaoManager\PHPStan\PhpDocParser\Ast\ConstExpr\ConstExprNode;
use _ContaoManager\PHPStan\PhpDocParser\Ast\Node;
use _ContaoManager\PHPStan\PhpDocParser\Ast\NodeAttributes;
use _ContaoManager\PHPStan\PhpDocParser\Ast\Type\TypeNode;
class MethodTagValueParameterNode implements Node
{
    use NodeAttributes;
    public ?TypeNode $type = null;
    public bool $isReference;
    public bool $isVariadic;
    public string $parameterName;
    public ?ConstExprNode $defaultValue = null;
    public function __construct(?TypeNode $type, bool $isReference, bool $isVariadic, string $parameterName, ?ConstExprNode $defaultValue)
    {
        $this->type = $type;
        $this->isReference = $isReference;
        $this->isVariadic = $isVariadic;
        $this->parameterName = $parameterName;
        $this->defaultValue = $defaultValue;
    }
    public function __toString(): string
    {
        $type = $this->type !== null ? "{$this->type} " : '';
        $isReference = $this->isReference ? '&' : '';
        $isVariadic = $this->isVariadic ? '...' : '';
        $default = $this->defaultValue !== null ? " = {$this->defaultValue}" : '';
        return "{$type}{$isReference}{$isVariadic}{$this->parameterName}{$default}";
    }
    /**
     * @param array<string, mixed> $properties
     */
    public static function __set_state(array $properties): self
    {
        $instance = new self($properties['type'], $properties['isReference'], $properties['isVariadic'], $properties['parameterName'], $properties['defaultValue']);
        if (isset($properties['attributes'])) {
            foreach ($properties['attributes'] as $key => $value) {
                $instance->setAttribute($key, $value);
            }
        }
        return $instance;
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\PHPStan\PhpDocParser\Ast\PhpDoc\Doctrine;

use _ContaoManager\PHPStan\PhpDocParser\Ast\ConstExpr\ConstExprNode;
use _ContaoManager\PHPStan\PhpDocParser\Ast\Node;
use _ContaoManager\PHPStan\PhpDocParser\Ast\NodeAttributes;
use _ContaoManager\PHPStan\PhpDocParser\Ast\Type\IdentifierTypeNode;
/**
 * @phpstan-type ValueType = DoctrineAnnotation|IdentifierTypeNode|DoctrineArray|ConstExprNode
 */
class DoctrineArgument implements Node
{
    use NodeAttributes;
    public ?IdentifierTypeNode $key = null;
    /** @var ValueType */
    public $value;
    /**
     * @param ValueType $value
     */
    public function __construct(?IdentifierTypeNode $key, $value)
    {
        $this->key = $key;
        $this->value = $value;
    }
    public function __toString(): string
    {
        if ($this->key === null) {
            return (string) $this->value;
        }
        return $this->key . '=' . $this->value;
    }
    /**
     * @param array<string, mixed> $properties
     */
    public static function __set_state(array $properties): self
    {
        $instance = new self($properties['key'], $properties['value']);
        if (isset($properties['attributes'])) {
            foreach ($properties['attributes'] as $key => $value) {
                $instance->setAttribute($key, $value);
            }
        }
        return $instance;
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\PHPStan\PhpDocParser\Ast\PhpDoc\Doctrine;

use _ContaoManager\PHPStan\PhpDocParser\Ast\Node;
use _ContaoManager\PHPStan\PhpDocParser\Ast\NodeAttributes;
use function implode;
class DoctrineAnnotation implements Node
{
    use NodeAttributes;
    public string $name;
    /** @var list<DoctrineArgument> */
    public array $arguments;
    /**
     * @param list<DoctrineArgument> $arguments
     */
    public function __construct(string $name, array $arguments)
    {
        $this->name = $name;
        $this->arguments = $arguments;
    }
    public function __toString(): string
    {
        $arguments = implode(', ', $this->arguments);
        return $this->name . '(' . $arguments . ')';
    }
    /**
     * @param array<string, mixed> $properties
     */
    public static function __set_state(array $properties): self
    {
        $instance = new self($properties['name'], $properties['arguments']);
        if (isset($properties['attributes'])) {
            foreach ($properties['attributes'] as $key => $value) {
                $instance->setAttribute($key, $value);
            }
        }
        return $instance;
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\PHPStan\PhpDocParser\Ast\PhpDoc\Doctrine;

use _ContaoManager\PHPStan\PhpDocParser\Ast\NodeAttributes;
use _ContaoManager\PHPStan\PhpDocParser\Ast\PhpDoc\PhpDocTagValueNode;
use function trim;
class DoctrineTagValueNode implements PhpDocTagValueNode
{
    use NodeAttributes;
    public DoctrineAnnotation $annotation;
    /** @var string (may be empty) */
    public string $description;
    public function __construct(DoctrineAnnotation $annotation, string $description)
    {
        $this->annotation = $annotation;
        $this->description = $description;
    }
    public function __toString(): string
    {
        return trim("{$this->annotation} {$this->description}");
    }
    /**
     * @param array<string, mixed> $properties
     */
    public static function __set_state(array $properties): self
    {
        $instance = new self($properties['annotation'], $properties['description']);
        if (isset($properties['attributes'])) {
            foreach ($properties['attributes'] as $key => $value) {
                $instance->setAttribute($key, $value);
            }
        }
        return $instance;
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\PHPStan\PhpDocParser\Ast\PhpDoc\Doctrine;

use _ContaoManager\PHPStan\PhpDocParser\Ast\ConstExpr\ConstExprIntegerNode;
use _ContaoManager\PHPStan\PhpDocParser\Ast\ConstExpr\ConstExprStringNode;
use _ContaoManager\PHPStan\PhpDocParser\Ast\ConstExpr\ConstFetchNode;
use _ContaoManager\PHPStan\PhpDocParser\Ast\Node;
use _ContaoManager\PHPStan\PhpDocParser\Ast\NodeAttributes;
use _ContaoManager\PHPStan\PhpDocParser\Ast\Type\IdentifierTypeNode;
/**
 * @phpstan-import-type ValueType from DoctrineArgument
 * @phpstan-type KeyType = ConstExprIntegerNode|ConstExprStringNode|IdentifierTypeNode|ConstFetchNode|null
 */
class DoctrineArrayItem implements Node
{
    use NodeAttributes;
    /** @var KeyType */
    public $key;
    /** @var ValueType */
    public $value;
    /**
     * @param KeyType $key
     * @param ValueType $value
     */
    public function __construct($key, $value)
    {
        $this->key = $key;
        $this->value = $value;
    }
    public function __toString(): string
    {
        if ($this->key === null) {
            return (string) $this->value;
        }
        return $this->key . '=' . $this->value;
    }
    /**
     * @param array<string, mixed> $properties
     */
    public static function __set_state(array $properties): self
    {
        $instance = new self($properties['key'], $properties['value']);
        if (isset($properties['attributes'])) {
            foreach ($properties['attributes'] as $key => $value) {
                $instance->setAttribute($key, $value);
            }
        }
        return $instance;
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\PHPStan\PhpDocParser\Ast\PhpDoc\Doctrine;

use _ContaoManager\PHPStan\PhpDocParser\Ast\Node;
use _ContaoManager\PHPStan\PhpDocParser\Ast\NodeAttributes;
use function implode;
class DoctrineArray implements Node
{
    use NodeAttributes;
    /** @var list<DoctrineArrayItem> */
    public array $items;
    /**
     * @param list<DoctrineArrayItem> $items
     */
    public function __construct(array $items)
    {
        $this->items = $items;
    }
    public function __toString(): string
    {
        $items = implode(', ', $this->items);
        return '{' . $items . '}';
    }
    /**
     * @param array<string, mixed> $properties
     */
    public static function __set_state(array $properties): self
    {
        $instance = new self($properties['items']);
        if (isset($properties['attributes'])) {
            foreach ($properties['attributes'] as $key => $value) {
                $instance->setAttribute($key, $value);
            }
        }
        return $instance;
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\PHPStan\PhpDocParser\Ast\PhpDoc;

use _ContaoManager\PHPStan\PhpDocParser\Ast\NodeAttributes;
use _ContaoManager\PHPStan\PhpDocParser\Parser\ParserException;
use function sprintf;
use function trigger_error;
use const E_USER_WARNING;
/**
 * @property ParserException $exception
 */
class InvalidTagValueNode implements PhpDocTagValueNode
{
    use NodeAttributes;
    /** @var string (may be empty) */
    public string $value;
    /** @var mixed[] */
    private array $exceptionArgs;
    public function __construct(string $value, ParserException $exception)
    {
        $this->value = $value;
        $this->exceptionArgs = [$exception->getCurrentTokenValue(), $exception->getCurrentTokenType(), $exception->getCurrentOffset(), $exception->getExpectedTokenType(), $exception->getExpectedTokenValue(), $exception->getCurrentTokenLine()];
    }
    public function __get(string $name): ?ParserException
    {
        if ($name !== 'exception') {
            trigger_error(sprintf('Undefined property: %s::$%s', self::class, $name), E_USER_WARNING);
            return null;
        }
        return new ParserException(...$this->exceptionArgs);
    }
    public function __toString(): string
    {
        return $this->value;
    }
    /**
     * @param array<string, mixed> $properties
     */
    public static function __set_state(array $properties): self
    {
        $exception = new ParserException(...$properties['exceptionArgs']);
        $instance = new self($properties['value'], $exception);
        if (isset($properties['attributes'])) {
            foreach ($properties['attributes'] as $key => $value) {
                $instance->setAttribute($key, $value);
            }
        }
        return $instance;
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\PHPStan\PhpDocParser\Ast\PhpDoc;

use _ContaoManager\PHPStan\PhpDocParser\Ast\NodeAttributes;
use _ContaoManager\PHPStan\PhpDocParser\Ast\Type\TypeNode;
use function trim;
class VarTagValueNode implements PhpDocTagValueNode
{
    use NodeAttributes;
    public TypeNode $type;
    /** @var string (may be empty) */
    public string $variableName;
    /** @var string (may be empty) */
    public string $description;
    public function __construct(TypeNode $type, string $variableName, string $description)
    {
        $this->type = $type;
        $this->variableName = $variableName;
        $this->description = $description;
    }
    public function __toString(): string
    {
        return trim("{$this->type} " . trim("{$this->variableName} {$this->description}"));
    }
    /**
     * @param array<string, mixed> $properties
     */
    public static function __set_state(array $properties): self
    {
        $instance = new self($properties['type'], $properties['variableName'], $properties['description']);
        if (isset($properties['attributes'])) {
            foreach ($properties['attributes'] as $key => $value) {
                $instance->setAttribute($key, $value);
            }
        }
        return $instance;
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\PHPStan\PhpDocParser\Ast\PhpDoc;

use _ContaoManager\PHPStan\PhpDocParser\Ast\NodeAttributes;
use _ContaoManager\PHPStan\PhpDocParser\Ast\PhpDoc\Doctrine\DoctrineTagValueNode;
use function trim;
class PhpDocTagNode implements PhpDocChildNode
{
    use NodeAttributes;
    public string $name;
    public PhpDocTagValueNode $value;
    public function __construct(string $name, PhpDocTagValueNode $value)
    {
        $this->name = $name;
        $this->value = $value;
    }
    public function __toString(): string
    {
        if ($this->value instanceof DoctrineTagValueNode) {
            return (string) $this->value;
        }
        return trim("{$this->name} {$this->value}");
    }
    /**
     * @param array<string, mixed> $properties
     */
    public static function __set_state(array $properties): self
    {
        $instance = new self($properties['name'], $properties['value']);
        if (isset($properties['attributes'])) {
            foreach ($properties['attributes'] as $key => $value) {
                $instance->setAttribute($key, $value);
            }
        }
        return $instance;
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\PHPStan\PhpDocParser\Ast\PhpDoc;

use _ContaoManager\PHPStan\PhpDocParser\Ast\NodeAttributes;
use _ContaoManager\PHPStan\PhpDocParser\Ast\Type\TypeNode;
use function trim;
class ParamOutTagValueNode implements PhpDocTagValueNode
{
    use NodeAttributes;
    public TypeNode $type;
    public string $parameterName;
    /** @var string (may be empty) */
    public string $description;
    public function __construct(TypeNode $type, string $parameterName, string $description)
    {
        $this->type = $type;
        $this->parameterName = $parameterName;
        $this->description = $description;
    }
    public function __toString(): string
    {
        return trim("{$this->type} {$this->parameterName} {$this->description}");
    }
    /**
     * @param array<string, mixed> $properties
     */
    public static function __set_state(array $properties): self
    {
        $instance = new self($properties['type'], $properties['parameterName'], $properties['description']);
        if (isset($properties['attributes'])) {
            foreach ($properties['attributes'] as $key => $value) {
                $instance->setAttribute($key, $value);
            }
        }
        return $instance;
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\PHPStan\PhpDocParser\Ast\PhpDoc;

use _ContaoManager\PHPStan\PhpDocParser\Ast\NodeAttributes;
use function trim;
class TypelessParamTagValueNode implements PhpDocTagValueNode
{
    use NodeAttributes;
    public bool $isReference;
    public bool $isVariadic;
    public string $parameterName;
    /** @var string (may be empty) */
    public string $description;
    public function __construct(bool $isVariadic, string $parameterName, string $description, bool $isReference)
    {
        $this->isReference = $isReference;
        $this->isVariadic = $isVariadic;
        $this->parameterName = $parameterName;
        $this->description = $description;
    }
    public function __toString(): string
    {
        $reference = $this->isReference ? '&' : '';
        $variadic = $this->isVariadic ? '...' : '';
        return trim("{$reference}{$variadic}{$this->parameterName} {$this->description}");
    }
    /**
     * @param array<string, mixed> $properties
     */
    public static function __set_state(array $properties): self
    {
        $instance = new self($properties['isVariadic'], $properties['parameterName'], $properties['description'], $properties['isReference']);
        if (isset($properties['attributes'])) {
            foreach ($properties['attributes'] as $key => $value) {
                $instance->setAttribute($key, $value);
            }
        }
        return $instance;
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\PHPStan\PhpDocParser\Ast\PhpDoc;

use _ContaoManager\PHPStan\PhpDocParser\Ast\NodeAttributes;
use _ContaoManager\PHPStan\PhpDocParser\Ast\Type\TypeNode;
use function trim;
class AssertTagMethodValueNode implements PhpDocTagValueNode
{
    use NodeAttributes;
    public TypeNode $type;
    public string $parameter;
    public string $method;
    public bool $isNegated;
    public bool $isEquality;
    /** @var string (may be empty) */
    public string $description;
    public function __construct(TypeNode $type, string $parameter, string $method, bool $isNegated, string $description, bool $isEquality)
    {
        $this->type = $type;
        $this->parameter = $parameter;
        $this->method = $method;
        $this->isNegated = $isNegated;
        $this->isEquality = $isEquality;
        $this->description = $description;
    }
    public function __toString(): string
    {
        $isNegated = $this->isNegated ? '!' : '';
        $isEquality = $this->isEquality ? '=' : '';
        return trim("{$isNegated}{$isEquality}{$this->type} {$this->parameter}->{$this->method}() {$this->description}");
    }
    /**
     * @param array<string, mixed> $properties
     */
    public static function __set_state(array $properties): self
    {
        $instance = new self($properties['type'], $properties['parameter'], $properties['method'], $properties['isNegated'], $properties['description'], $properties['isEquality']);
        if (isset($properties['attributes'])) {
            foreach ($properties['attributes'] as $key => $value) {
                $instance->setAttribute($key, $value);
            }
        }
        return $instance;
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\PHPStan\PhpDocParser\Ast\PhpDoc;

use _ContaoManager\PHPStan\PhpDocParser\Ast\NodeAttributes;
use _ContaoManager\PHPStan\PhpDocParser\Ast\Type\IdentifierTypeNode;
use function trim;
class TypeAliasImportTagValueNode implements PhpDocTagValueNode
{
    use NodeAttributes;
    public string $importedAlias;
    public IdentifierTypeNode $importedFrom;
    public ?string $importedAs = null;
    public function __construct(string $importedAlias, IdentifierTypeNode $importedFrom, ?string $importedAs)
    {
        $this->importedAlias = $importedAlias;
        $this->importedFrom = $importedFrom;
        $this->importedAs = $importedAs;
    }
    public function __toString(): string
    {
        return trim("{$this->importedAlias} from {$this->importedFrom}" . ($this->importedAs !== null ? " as {$this->importedAs}" : ''));
    }
    /**
     * @param array<string, mixed> $properties
     */
    public static function __set_state(array $properties): self
    {
        $instance = new self($properties['importedAlias'], $properties['importedFrom'], $properties['importedAs']);
        if (isset($properties['attributes'])) {
            foreach ($properties['attributes'] as $key => $value) {
                $instance->setAttribute($key, $value);
            }
        }
        return $instance;
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\PHPStan\PhpDocParser\Ast\PhpDoc;

use _ContaoManager\PHPStan\PhpDocParser\Ast\NodeAttributes;
use _ContaoManager\PHPStan\PhpDocParser\Ast\Type\TypeNode;
use function trim;
class PropertyTagValueNode implements PhpDocTagValueNode
{
    use NodeAttributes;
    public TypeNode $type;
    public string $propertyName;
    /** @var string (may be empty) */
    public string $description;
    public function __construct(TypeNode $type, string $propertyName, string $description)
    {
        $this->type = $type;
        $this->propertyName = $propertyName;
        $this->description = $description;
    }
    public function __toString(): string
    {
        return trim("{$this->type} {$this->propertyName} {$this->description}");
    }
    /**
     * @param array<string, mixed> $properties
     */
    public static function __set_state(array $properties): self
    {
        $instance = new self($properties['type'], $properties['propertyName'], $properties['description']);
        if (isset($properties['attributes'])) {
            foreach ($properties['attributes'] as $key => $value) {
                $instance->setAttribute($key, $value);
            }
        }
        return $instance;
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\PHPStan\PhpDocParser\Ast\PhpDoc;

use _ContaoManager\PHPStan\PhpDocParser\Ast\NodeAttributes;
use function trim;
class ParamImmediatelyInvokedCallableTagValueNode implements PhpDocTagValueNode
{
    use NodeAttributes;
    public string $parameterName;
    /** @var string (may be empty) */
    public string $description;
    public function __construct(string $parameterName, string $description)
    {
        $this->parameterName = $parameterName;
        $this->description = $description;
    }
    public function __toString(): string
    {
        return trim("{$this->parameterName} {$this->description}");
    }
    /**
     * @param array<string, mixed> $properties
     */
    public static function __set_state(array $properties): self
    {
        $instance = new self($properties['parameterName'], $properties['description']);
        if (isset($properties['attributes'])) {
            foreach ($properties['attributes'] as $key => $value) {
                $instance->setAttribute($key, $value);
            }
        }
        return $instance;
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\PHPStan\PhpDocParser\Ast\PhpDoc;

use _ContaoManager\PHPStan\PhpDocParser\Ast\Node;
interface PhpDocChildNode extends Node
{
}
<?php

declare (strict_types=1);
namespace _ContaoManager\PHPStan\PhpDocParser\Ast\PhpDoc;

use _ContaoManager\PHPStan\PhpDocParser\Ast\NodeAttributes;
use _ContaoManager\PHPStan\PhpDocParser\Ast\Type\GenericTypeNode;
use function trim;
class ExtendsTagValueNode implements PhpDocTagValueNode
{
    use NodeAttributes;
    public GenericTypeNode $type;
    /** @var string (may be empty) */
    public string $description;
    public function __construct(GenericTypeNode $type, string $description)
    {
        $this->type = $type;
        $this->description = $description;
    }
    public function __toString(): string
    {
        return trim("{$this->type} {$this->description}");
    }
    /**
     * @param array<string, mixed> $properties
     */
    public static function __set_state(array $properties): self
    {
        $instance = new self($properties['type'], $properties['description']);
        if (isset($properties['attributes'])) {
            foreach ($properties['attributes'] as $key => $value) {
                $instance->setAttribute($key, $value);
            }
        }
        return $instance;
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\PHPStan\PhpDocParser\Ast\PhpDoc;

use _ContaoManager\PHPStan\PhpDocParser\Ast\NodeAttributes;
use _ContaoManager\PHPStan\PhpDocParser\Ast\Type\TypeNode;
use function trim;
class ParamTagValueNode implements PhpDocTagValueNode
{
    use NodeAttributes;
    public TypeNode $type;
    public bool $isReference;
    public bool $isVariadic;
    public string $parameterName;
    /** @var string (may be empty) */
    public string $description;
    public function __construct(TypeNode $type, bool $isVariadic, string $parameterName, string $description, bool $isReference)
    {
        $this->type = $type;
        $this->isReference = $isReference;
        $this->isVariadic = $isVariadic;
        $this->parameterName = $parameterName;
        $this->description = $description;
    }
    public function __toString(): string
    {
        $reference = $this->isReference ? '&' : '';
        $variadic = $this->isVariadic ? '...' : '';
        return trim("{$this->type} {$reference}{$variadic}{$this->parameterName} {$this->description}");
    }
    /**
     * @param array<string, mixed> $properties
     */
    public static function __set_state(array $properties): self
    {
        $instance = new self($properties['type'], $properties['isVariadic'], $properties['parameterName'], $properties['description'], $properties['isReference']);
        if (isset($properties['attributes'])) {
            foreach ($properties['attributes'] as $key => $value) {
                $instance->setAttribute($key, $value);
            }
        }
        return $instance;
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\PHPStan\PhpDocParser\Ast\PhpDoc;

use _ContaoManager\PHPStan\PhpDocParser\Ast\NodeAttributes;
use _ContaoManager\PHPStan\PhpDocParser\Ast\Type\TypeNode;
use function count;
use function implode;
class MethodTagValueNode implements PhpDocTagValueNode
{
    use NodeAttributes;
    public bool $isStatic;
    public ?TypeNode $returnType = null;
    public string $methodName;
    /** @var TemplateTagValueNode[] */
    public array $templateTypes;
    /** @var MethodTagValueParameterNode[] */
    public array $parameters;
    /** @var string (may be empty) */
    public string $description;
    /**
     * @param MethodTagValueParameterNode[] $parameters
     * @param TemplateTagValueNode[] $templateTypes
     */
    public function __construct(bool $isStatic, ?TypeNode $returnType, string $methodName, array $parameters, string $description, array $templateTypes)
    {
        $this->isStatic = $isStatic;
        $this->returnType = $returnType;
        $this->methodName = $methodName;
        $this->parameters = $parameters;
        $this->description = $description;
        $this->templateTypes = $templateTypes;
    }
    public function __toString(): string
    {
        $static = $this->isStatic ? 'static ' : '';
        $returnType = $this->returnType !== null ? "{$this->returnType} " : '';
        $parameters = implode(', ', $this->parameters);
        $description = $this->description !== '' ? " {$this->description}" : '';
        $templateTypes = count($this->templateTypes) > 0 ? '<' . implode(', ', $this->templateTypes) . '>' : '';
        return "{$static}{$returnType}{$this->methodName}{$templateTypes}({$parameters}){$description}";
    }
    /**
     * @param array<string, mixed> $properties
     */
    public static function __set_state(array $properties): self
    {
        $instance = new self($properties['isStatic'], $properties['returnType'], $properties['methodName'], $properties['parameters'], $properties['description'], $properties['templateTypes']);
        if (isset($properties['attributes'])) {
            foreach ($properties['attributes'] as $key => $value) {
                $instance->setAttribute($key, $value);
            }
        }
        return $instance;
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\PHPStan\PhpDocParser\Ast\PhpDoc;

use _ContaoManager\PHPStan\PhpDocParser\Ast\NodeAttributes;
use _ContaoManager\PHPStan\PhpDocParser\Ast\Type\TypeNode;
use function trim;
class SelfOutTagValueNode implements PhpDocTagValueNode
{
    use NodeAttributes;
    public TypeNode $type;
    /** @var string (may be empty) */
    public string $description;
    public function __construct(TypeNode $type, string $description)
    {
        $this->type = $type;
        $this->description = $description;
    }
    public function __toString(): string
    {
        return trim($this->type . ' ' . $this->description);
    }
    /**
     * @param array<string, mixed> $properties
     */
    public static function __set_state(array $properties): self
    {
        $instance = new self($properties['type'], $properties['description']);
        if (isset($properties['attributes'])) {
            foreach ($properties['attributes'] as $key => $value) {
                $instance->setAttribute($key, $value);
            }
        }
        return $instance;
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\PHPStan\PhpDocParser\Ast\PhpDoc;

use _ContaoManager\PHPStan\PhpDocParser\Ast\NodeAttributes;
use function trim;
class DeprecatedTagValueNode implements PhpDocTagValueNode
{
    use NodeAttributes;
    /** @var string (may be empty) */
    public string $description;
    public function __construct(string $description)
    {
        $this->description = $description;
    }
    public function __toString(): string
    {
        return trim($this->description);
    }
    /**
     * @param array<string, mixed> $properties
     */
    public static function __set_state(array $properties): self
    {
        $instance = new self($properties['description']);
        if (isset($properties['attributes'])) {
            foreach ($properties['attributes'] as $key => $value) {
                $instance->setAttribute($key, $value);
            }
        }
        return $instance;
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\PHPStan\PhpDocParser\Ast\PhpDoc;

use _ContaoManager\PHPStan\PhpDocParser\Ast\NodeAttributes;
use _ContaoManager\PHPStan\PhpDocParser\Ast\Type\TypeNode;
use function trim;
class RequireExtendsTagValueNode implements PhpDocTagValueNode
{
    use NodeAttributes;
    public TypeNode $type;
    /** @var string (may be empty) */
    public string $description;
    public function __construct(TypeNode $type, string $description)
    {
        $this->type = $type;
        $this->description = $description;
    }
    public function __toString(): string
    {
        return trim("{$this->type} {$this->description}");
    }
    /**
     * @param array<string, mixed> $properties
     */
    public static function __set_state(array $properties): self
    {
        $instance = new self($properties['type'], $properties['description']);
        if (isset($properties['attributes'])) {
            foreach ($properties['attributes'] as $key => $value) {
                $instance->setAttribute($key, $value);
            }
        }
        return $instance;
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\PHPStan\PhpDocParser\Ast\ConstExpr;

use _ContaoManager\PHPStan\PhpDocParser\Ast\NodeAttributes;
class ConstFetchNode implements ConstExprNode
{
    use NodeAttributes;
    /** @var string class name for class constants or empty string for non-class constants */
    public string $className;
    public string $name;
    public function __construct(string $className, string $name)
    {
        $this->className = $className;
        $this->name = $name;
    }
    public function __toString(): string
    {
        if ($this->className === '') {
            return $this->name;
        }
        return "{$this->className}::{$this->name}";
    }
    /**
     * @param array<string, mixed> $properties
     */
    public static function __set_state(array $properties): self
    {
        $instance = new self($properties['className'], $properties['name']);
        if (isset($properties['attributes'])) {
            foreach ($properties['attributes'] as $key => $value) {
                $instance->setAttribute($key, $value);
            }
        }
        return $instance;
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\PHPStan\PhpDocParser\Ast\ConstExpr;

use _ContaoManager\PHPStan\PhpDocParser\Ast\NodeAttributes;
use function implode;
class ConstExprArrayNode implements ConstExprNode
{
    use NodeAttributes;
    /** @var ConstExprArrayItemNode[] */
    public array $items;
    /**
     * @param ConstExprArrayItemNode[] $items
     */
    public function __construct(array $items)
    {
        $this->items = $items;
    }
    public function __toString(): string
    {
        return '[' . implode(', ', $this->items) . ']';
    }
    /**
     * @param array<string, mixed> $properties
     */
    public static function __set_state(array $properties): self
    {
        $instance = new self($properties['items']);
        if (isset($properties['attributes'])) {
            foreach ($properties['attributes'] as $key => $value) {
                $instance->setAttribute($key, $value);
            }
        }
        return $instance;
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\PHPStan\PhpDocParser\Ast\ConstExpr;

use _ContaoManager\PHPStan\PhpDocParser\Ast\Node;
interface ConstExprNode extends Node
{
}
<?php

declare (strict_types=1);
namespace _ContaoManager\PHPStan\PhpDocParser\Ast\ConstExpr;

use _ContaoManager\PHPStan\PhpDocParser\Ast\NodeAttributes;
use function addcslashes;
use function assert;
use function dechex;
use function ord;
use function preg_replace_callback;
use function sprintf;
use function str_pad;
use function strlen;
use const STR_PAD_LEFT;
class ConstExprStringNode implements ConstExprNode
{
    public const SINGLE_QUOTED = 1;
    public const DOUBLE_QUOTED = 2;
    use NodeAttributes;
    public string $value;
    /** @var self::SINGLE_QUOTED|self::DOUBLE_QUOTED */
    public $quoteType;
    /**
     * @param self::SINGLE_QUOTED|self::DOUBLE_QUOTED $quoteType
     */
    public function __construct(string $value, int $quoteType)
    {
        $this->value = $value;
        $this->quoteType = $quoteType;
    }
    public function __toString(): string
    {
        if ($this->quoteType === self::SINGLE_QUOTED) {
            // from https://github.com/nikic/PHP-Parser/blob/0ffddce52d816f72d0efc4d9b02e276d3309ef01/lib/PhpParser/PrettyPrinter/Standard.php#L1007
            return sprintf("'%s'", addcslashes($this->value, '\'\\'));
        }
        // from https://github.com/nikic/PHP-Parser/blob/0ffddce52d816f72d0efc4d9b02e276d3309ef01/lib/PhpParser/PrettyPrinter/Standard.php#L1010-L1040
        return sprintf('"%s"', $this->escapeDoubleQuotedString());
    }
    private function escapeDoubleQuotedString(): string
    {
        $quote = '"';
        $escaped = addcslashes($this->value, "\n\r\t\f\v\$" . $quote . '\\');
        // Escape control characters and non-UTF-8 characters.
        // Regex based on https://stackoverflow.com/a/11709412/385378.
        $regex = '/(
              [\x00-\x08\x0E-\x1F] # Control characters
            | [\xC0-\xC1] # Invalid UTF-8 Bytes
            | [\xF5-\xFF] # Invalid UTF-8 Bytes
            | \xE0(?=[\x80-\x9F]) # Overlong encoding of prior code point
            | \xF0(?=[\x80-\x8F]) # Overlong encoding of prior code point
            | [\xC2-\xDF](?![\x80-\xBF]) # Invalid UTF-8 Sequence Start
            | [\xE0-\xEF](?![\x80-\xBF]{2}) # Invalid UTF-8 Sequence Start
            | [\xF0-\xF4](?![\x80-\xBF]{3}) # Invalid UTF-8 Sequence Start
            | (?<=[\x00-\x7F\xF5-\xFF])[\x80-\xBF] # Invalid UTF-8 Sequence Middle
            | (?<![\xC2-\xDF]|[\xE0-\xEF]|[\xE0-\xEF][\x80-\xBF]|[\xF0-\xF4]|[\xF0-\xF4][\x80-\xBF]|[\xF0-\xF4][\x80-\xBF]{2})[\x80-\xBF] # Overlong Sequence
            | (?<=[\xE0-\xEF])[\x80-\xBF](?![\x80-\xBF]) # Short 3 byte sequence
            | (?<=[\xF0-\xF4])[\x80-\xBF](?![\x80-\xBF]{2}) # Short 4 byte sequence
            | (?<=[\xF0-\xF4][\x80-\xBF])[\x80-\xBF](?![\x80-\xBF]) # Short 4 byte sequence (2)
        )/x';
        return preg_replace_callback($regex, static function ($matches) {
            assert(strlen($matches[0]) === 1);
            $hex = dechex(ord($matches[0]));
            return '\x' . str_pad($hex, 2, '0', STR_PAD_LEFT);
        }, $escaped);
    }
    /**
     * @param array<string, mixed> $properties
     */
    public static function __set_state(array $properties): self
    {
        $instance = new self($properties['value'], $properties['quoteType']);
        if (isset($properties['attributes'])) {
            foreach ($properties['attributes'] as $key => $value) {
                $instance->setAttribute($key, $value);
            }
        }
        return $instance;
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\PHPStan\PhpDocParser\Ast\ConstExpr;

use _ContaoManager\PHPStan\PhpDocParser\Ast\NodeAttributes;
class ConstExprTrueNode implements ConstExprNode
{
    use NodeAttributes;
    public function __toString(): string
    {
        return 'true';
    }
    /**
     * @param array<string, mixed> $properties
     */
    public static function __set_state(array $properties): self
    {
        $instance = new self();
        if (isset($properties['attributes'])) {
            foreach ($properties['attributes'] as $key => $value) {
                $instance->setAttribute($key, $value);
            }
        }
        return $instance;
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\PHPStan\PhpDocParser\Ast\ConstExpr;

use _ContaoManager\PHPStan\PhpDocParser\Ast\NodeAttributes;
class ConstExprIntegerNode implements ConstExprNode
{
    use NodeAttributes;
    public string $value;
    public function __construct(string $value)
    {
        $this->value = $value;
    }
    public function __toString(): string
    {
        return $this->value;
    }
    /**
     * @param array<string, mixed> $properties
     */
    public static function __set_state(array $properties): self
    {
        $instance = new self($properties['value']);
        if (isset($properties['attributes'])) {
            foreach ($properties['attributes'] as $key => $value) {
                $instance->setAttribute($key, $value);
            }
        }
        return $instance;
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\PHPStan\PhpDocParser\Ast\ConstExpr;

use _ContaoManager\PHPStan\PhpDocParser\Ast\NodeAttributes;
class ConstExprFalseNode implements ConstExprNode
{
    use NodeAttributes;
    public function __toString(): string
    {
        return 'false';
    }
    /**
     * @param array<string, mixed> $properties
     */
    public static function __set_state(array $properties): self
    {
        $instance = new self();
        if (isset($properties['attributes'])) {
            foreach ($properties['attributes'] as $key => $value) {
                $instance->setAttribute($key, $value);
            }
        }
        return $instance;
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\PHPStan\PhpDocParser\Ast\ConstExpr;

use _ContaoManager\PHPStan\PhpDocParser\Ast\NodeAttributes;
use function sprintf;
class ConstExprArrayItemNode implements ConstExprNode
{
    use NodeAttributes;
    public ?ConstExprNode $key = null;
    public ConstExprNode $value;
    public function __construct(?ConstExprNode $key, ConstExprNode $value)
    {
        $this->key = $key;
        $this->value = $value;
    }
    public function __toString(): string
    {
        if ($this->key !== null) {
            return sprintf('%s => %s', $this->key, $this->value);
        }
        return (string) $this->value;
    }
    /**
     * @param array<string, mixed> $properties
     */
    public static function __set_state(array $properties): self
    {
        $instance = new self($properties['key'], $properties['value']);
        if (isset($properties['attributes'])) {
            foreach ($properties['attributes'] as $key => $value) {
                $instance->setAttribute($key, $value);
            }
        }
        return $instance;
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\PHPStan\PhpDocParser\Ast\ConstExpr;

use _ContaoManager\PHPStan\PhpDocParser\Ast\NodeAttributes;
class ConstExprNullNode implements ConstExprNode
{
    use NodeAttributes;
    public function __toString(): string
    {
        return 'null';
    }
    /**
     * @param array<string, mixed> $properties
     */
    public static function __set_state(array $properties): self
    {
        $instance = new self();
        if (isset($properties['attributes'])) {
            foreach ($properties['attributes'] as $key => $value) {
                $instance->setAttribute($key, $value);
            }
        }
        return $instance;
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\PHPStan\PhpDocParser\Ast\ConstExpr;

use _ContaoManager\PHPStan\PhpDocParser\Ast\NodeAttributes;
use function sprintf;
use function str_replace;
use function strlen;
use function substr;
class DoctrineConstExprStringNode extends ConstExprStringNode
{
    use NodeAttributes;
    public string $value;
    public function __construct(string $value)
    {
        parent::__construct($value, self::DOUBLE_QUOTED);
        $this->value = $value;
    }
    public function __toString(): string
    {
        return self::escape($this->value);
    }
    public static function unescape(string $value): string
    {
        // from https://github.com/doctrine/annotations/blob/a9ec7af212302a75d1f92fa65d3abfbd16245a2a/lib/Doctrine/Common/Annotations/DocLexer.php#L103-L107
        return str_replace('""', '"', substr($value, 1, strlen($value) - 2));
    }
    private static function escape(string $value): string
    {
        // from https://github.com/phpstan/phpdoc-parser/issues/205#issuecomment-1662323656
        return sprintf('"%s"', str_replace('"', '""', $value));
    }
    /**
     * @param array<string, mixed> $properties
     */
    public static function __set_state(array $properties): self
    {
        $instance = new self($properties['value']);
        if (isset($properties['attributes'])) {
            foreach ($properties['attributes'] as $key => $value) {
                $instance->setAttribute($key, $value);
            }
        }
        return $instance;
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\PHPStan\PhpDocParser\Ast\ConstExpr;

use _ContaoManager\PHPStan\PhpDocParser\Ast\NodeAttributes;
class ConstExprFloatNode implements ConstExprNode
{
    use NodeAttributes;
    public string $value;
    public function __construct(string $value)
    {
        $this->value = $value;
    }
    public function __toString(): string
    {
        return $this->value;
    }
    /**
     * @param array<string, mixed> $properties
     */
    public static function __set_state(array $properties): self
    {
        $instance = new self($properties['value']);
        if (isset($properties['attributes'])) {
            foreach ($properties['attributes'] as $key => $value) {
                $instance->setAttribute($key, $value);
            }
        }
        return $instance;
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\PHPStan\PhpDocParser\Ast;

/**
 * Inspired by https://github.com/nikic/PHP-Parser/tree/36a6dcd04e7b0285e8f0868f44bd4927802f7df1
 *
 * Copyright (c) 2011, Nikita Popov
 * All rights reserved.
 */
interface NodeVisitor
{
    /**
     * Called once before traversal.
     *
     * Return value semantics:
     *  * null:      $nodes stays as-is
     *  * otherwise: $nodes is set to the return value
     *
     * @param Node[] $nodes Array of nodes
     *
     * @return Node[]|null Array of nodes
     */
    public function beforeTraverse(array $nodes): ?array;
    /**
     * Called when entering a node.
     *
     * Return value semantics:
     *  * null
     *        => $node stays as-is
     *  * array (of Nodes)
     *        => The return value is merged into the parent array (at the position of the $node)
     *  * NodeTraverser::REMOVE_NODE
     *        => $node is removed from the parent array
     *  * NodeTraverser::DONT_TRAVERSE_CHILDREN
     *        => Children of $node are not traversed. $node stays as-is
     *  * NodeTraverser::DONT_TRAVERSE_CURRENT_AND_CHILDREN
     *        => Further visitors for the current node are skipped, and its children are not
     *           traversed. $node stays as-is.
     *  * NodeTraverser::STOP_TRAVERSAL
     *        => Traversal is aborted. $node stays as-is
     *  * otherwise
     *        => $node is set to the return value
     *
     * @param Node $node Node
     *
     * @return Node|Node[]|NodeTraverser::*|null Replacement node (or special return value)
     */
    public function enterNode(Node $node);
    /**
     * Called when leaving a node.
     *
     * Return value semantics:
     *  * null
     *        => $node stays as-is
     *  * NodeTraverser::REMOVE_NODE
     *        => $node is removed from the parent array
     *  * NodeTraverser::STOP_TRAVERSAL
     *        => Traversal is aborted. $node stays as-is
     *  * array (of Nodes)
     *        => The return value is merged into the parent array (at the position of the $node)
     *  * otherwise
     *        => $node is set to the return value
     *
     * @param Node $node Node
     *
     * @return Node|Node[]|NodeTraverser::REMOVE_NODE|NodeTraverser::STOP_TRAVERSAL|null Replacement node (or special return value)
     */
    public function leaveNode(Node $node);
    /**
     * Called once after traversal.
     *
     * Return value semantics:
     *  * null:      $nodes stays as-is
     *  * otherwise: $nodes is set to the return value
     *
     * @param Node[] $nodes Array of nodes
     *
     * @return Node[]|null Array of nodes
     */
    public function afterTraverse(array $nodes): ?array;
}
<?php

declare (strict_types=1);
namespace _ContaoManager\PHPStan\PhpDocParser\Ast\NodeVisitor;

use _ContaoManager\PHPStan\PhpDocParser\Ast\AbstractNodeVisitor;
use _ContaoManager\PHPStan\PhpDocParser\Ast\Attribute;
use _ContaoManager\PHPStan\PhpDocParser\Ast\Node;
final class CloningVisitor extends AbstractNodeVisitor
{
    public function enterNode(Node $originalNode): Node
    {
        $node = clone $originalNode;
        $node->setAttribute(Attribute::ORIGINAL_NODE, $originalNode);
        return $node;
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\PHPStan\PhpDocParser\Ast;

final class Attribute
{
    public const START_LINE = 'startLine';
    public const END_LINE = 'endLine';
    public const START_INDEX = 'startIndex';
    public const END_INDEX = 'endIndex';
    public const ORIGINAL_NODE = 'originalNode';
    public const COMMENTS = 'comments';
}
<?php

declare (strict_types=1);
namespace _ContaoManager\PHPStan\PhpDocParser\Ast;

interface Node
{
    public function __toString(): string;
    /**
     * @param mixed $value
     */
    public function setAttribute(string $key, $value): void;
    public function hasAttribute(string $key): bool;
    /**
     * @return mixed
     */
    public function getAttribute(string $key);
}
<?php

declare (strict_types=1);
namespace _ContaoManager\PHPStan\PhpDocParser\Ast\Type;

use _ContaoManager\PHPStan\PhpDocParser\Ast\NodeAttributes;
use function array_map;
use function implode;
class UnionTypeNode implements TypeNode
{
    use NodeAttributes;
    /** @var TypeNode[] */
    public array $types;
    /**
     * @param TypeNode[] $types
     */
    public function __construct(array $types)
    {
        $this->types = $types;
    }
    public function __toString(): string
    {
        return '(' . implode(' | ', array_map(static function (TypeNode $type): string {
            if ($type instanceof NullableTypeNode) {
                return '(' . $type . ')';
            }
            return (string) $type;
        }, $this->types)) . ')';
    }
    /**
     * @param array<string, mixed> $properties
     */
    public static function __set_state(array $properties): self
    {
        $instance = new self($properties['types']);
        if (isset($properties['attributes'])) {
            foreach ($properties['attributes'] as $key => $value) {
                $instance->setAttribute($key, $value);
            }
        }
        return $instance;
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\PHPStan\PhpDocParser\Ast\Type;

use _ContaoManager\PHPStan\PhpDocParser\Ast\NodeAttributes;
use function array_map;
use function implode;
class IntersectionTypeNode implements TypeNode
{
    use NodeAttributes;
    /** @var TypeNode[] */
    public array $types;
    /**
     * @param TypeNode[] $types
     */
    public function __construct(array $types)
    {
        $this->types = $types;
    }
    public function __toString(): string
    {
        return '(' . implode(' & ', array_map(static function (TypeNode $type): string {
            if ($type instanceof NullableTypeNode) {
                return '(' . $type . ')';
            }
            return (string) $type;
        }, $this->types)) . ')';
    }
    /**
     * @param array<string, mixed> $properties
     */
    public static function __set_state(array $properties): self
    {
        $instance = new self($properties['types']);
        if (isset($properties['attributes'])) {
            foreach ($properties['attributes'] as $key => $value) {
                $instance->setAttribute($key, $value);
            }
        }
        return $instance;
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\PHPStan\PhpDocParser\Ast\Type;

use _ContaoManager\PHPStan\PhpDocParser\Ast\NodeAttributes;
class IdentifierTypeNode implements TypeNode
{
    use NodeAttributes;
    public string $name;
    public function __construct(string $name)
    {
        $this->name = $name;
    }
    public function __toString(): string
    {
        return $this->name;
    }
    /**
     * @param array<string, mixed> $properties
     */
    public static function __set_state(array $properties): self
    {
        $instance = new self($properties['name']);
        if (isset($properties['attributes'])) {
            foreach ($properties['attributes'] as $key => $value) {
                $instance->setAttribute($key, $value);
            }
        }
        return $instance;
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\PHPStan\PhpDocParser\Ast\Type;

use _ContaoManager\PHPStan\PhpDocParser\Ast\ConstExpr\ConstExprIntegerNode;
use _ContaoManager\PHPStan\PhpDocParser\Ast\ConstExpr\ConstExprStringNode;
use _ContaoManager\PHPStan\PhpDocParser\Ast\ConstExpr\ConstFetchNode;
use _ContaoManager\PHPStan\PhpDocParser\Ast\Node;
use _ContaoManager\PHPStan\PhpDocParser\Ast\NodeAttributes;
use function sprintf;
class ArrayShapeItemNode implements Node
{
    use NodeAttributes;
    /** @var ConstExprIntegerNode|ConstExprStringNode|ConstFetchNode|IdentifierTypeNode|null */
    public $keyName;
    public bool $optional;
    public TypeNode $valueType;
    /**
     * @param ConstExprIntegerNode|ConstExprStringNode|ConstFetchNode|IdentifierTypeNode|null $keyName
     */
    public function __construct($keyName, bool $optional, TypeNode $valueType)
    {
        $this->keyName = $keyName;
        $this->optional = $optional;
        $this->valueType = $valueType;
    }
    public function __toString(): string
    {
        if ($this->keyName !== null) {
            return sprintf('%s%s: %s', (string) $this->keyName, $this->optional ? '?' : '', (string) $this->valueType);
        }
        return (string) $this->valueType;
    }
    /**
     * @param array<string, mixed> $properties
     */
    public static function __set_state(array $properties): self
    {
        $instance = new self($properties['keyName'], $properties['optional'], $properties['valueType']);
        if (isset($properties['attributes'])) {
            foreach ($properties['attributes'] as $key => $value) {
                $instance->setAttribute($key, $value);
            }
        }
        return $instance;
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\PHPStan\PhpDocParser\Ast\Type;

use _ContaoManager\PHPStan\PhpDocParser\Ast\ConstExpr\ConstExprNode;
use _ContaoManager\PHPStan\PhpDocParser\Ast\NodeAttributes;
class ConstTypeNode implements TypeNode
{
    use NodeAttributes;
    public ConstExprNode $constExpr;
    public function __construct(ConstExprNode $constExpr)
    {
        $this->constExpr = $constExpr;
    }
    public function __toString(): string
    {
        return $this->constExpr->__toString();
    }
    /**
     * @param array<string, mixed> $properties
     */
    public static function __set_state(array $properties): self
    {
        $instance = new self($properties['constExpr']);
        if (isset($properties['attributes'])) {
            foreach ($properties['attributes'] as $key => $value) {
                $instance->setAttribute($key, $value);
            }
        }
        return $instance;
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\PHPStan\PhpDocParser\Ast\Type;

use _ContaoManager\PHPStan\PhpDocParser\Ast\Node;
use _ContaoManager\PHPStan\PhpDocParser\Ast\NodeAttributes;
use function trim;
class CallableTypeParameterNode implements Node
{
    use NodeAttributes;
    public TypeNode $type;
    public bool $isReference;
    public bool $isVariadic;
    /** @var string (may be empty) */
    public string $parameterName;
    public bool $isOptional;
    public function __construct(TypeNode $type, bool $isReference, bool $isVariadic, string $parameterName, bool $isOptional)
    {
        $this->type = $type;
        $this->isReference = $isReference;
        $this->isVariadic = $isVariadic;
        $this->parameterName = $parameterName;
        $this->isOptional = $isOptional;
    }
    public function __toString(): string
    {
        $type = "{$this->type} ";
        $isReference = $this->isReference ? '&' : '';
        $isVariadic = $this->isVariadic ? '...' : '';
        $isOptional = $this->isOptional ? '=' : '';
        return trim("{$type}{$isReference}{$isVariadic}{$this->parameterName}") . $isOptional;
    }
    /**
     * @param array<string, mixed> $properties
     */
    public static function __set_state(array $properties): self
    {
        $instance = new self($properties['type'], $properties['isReference'], $properties['isVariadic'], $properties['parameterName'], $properties['isOptional']);
        if (isset($properties['attributes'])) {
            foreach ($properties['attributes'] as $key => $value) {
                $instance->setAttribute($key, $value);
            }
        }
        return $instance;
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\PHPStan\PhpDocParser\Ast\Type;

use _ContaoManager\PHPStan\PhpDocParser\Ast\NodeAttributes;
use _ContaoManager\PHPStan\PhpDocParser\Ast\PhpDoc\TemplateTagValueNode;
use function implode;
class CallableTypeNode implements TypeNode
{
    use NodeAttributes;
    public IdentifierTypeNode $identifier;
    /** @var TemplateTagValueNode[] */
    public array $templateTypes;
    /** @var CallableTypeParameterNode[] */
    public array $parameters;
    public TypeNode $returnType;
    /**
     * @param CallableTypeParameterNode[] $parameters
     * @param TemplateTagValueNode[]  $templateTypes
     */
    public function __construct(IdentifierTypeNode $identifier, array $parameters, TypeNode $returnType, array $templateTypes)
    {
        $this->identifier = $identifier;
        $this->parameters = $parameters;
        $this->returnType = $returnType;
        $this->templateTypes = $templateTypes;
    }
    public function __toString(): string
    {
        $returnType = $this->returnType;
        if ($returnType instanceof self) {
            $returnType = "({$returnType})";
        }
        $template = $this->templateTypes !== [] ? '<' . implode(', ', $this->templateTypes) . '>' : '';
        $parameters = implode(', ', $this->parameters);
        return "{$this->identifier}{$template}({$parameters}): {$returnType}";
    }
    /**
     * @param array<string, mixed> $properties
     */
    public static function __set_state(array $properties): self
    {
        $instance = new self($properties['identifier'], $properties['parameters'], $properties['returnType'], $properties['templateTypes']);
        if (isset($properties['attributes'])) {
            foreach ($properties['attributes'] as $key => $value) {
                $instance->setAttribute($key, $value);
            }
        }
        return $instance;
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\PHPStan\PhpDocParser\Ast\Type;

use _ContaoManager\PHPStan\PhpDocParser\Ast\Node;
interface TypeNode extends Node
{
}
<?php

declare (strict_types=1);
namespace _ContaoManager\PHPStan\PhpDocParser\Ast\Type;

use _ContaoManager\PHPStan\PhpDocParser\Ast\ConstExpr\ConstExprStringNode;
use _ContaoManager\PHPStan\PhpDocParser\Ast\Node;
use _ContaoManager\PHPStan\PhpDocParser\Ast\NodeAttributes;
use function sprintf;
class ObjectShapeItemNode implements Node
{
    use NodeAttributes;
    /** @var ConstExprStringNode|IdentifierTypeNode */
    public $keyName;
    public bool $optional;
    public TypeNode $valueType;
    /**
     * @param ConstExprStringNode|IdentifierTypeNode $keyName
     */
    public function __construct($keyName, bool $optional, TypeNode $valueType)
    {
        $this->keyName = $keyName;
        $this->optional = $optional;
        $this->valueType = $valueType;
    }
    public function __toString(): string
    {
        if ($this->keyName !== null) {
            return sprintf('%s%s: %s', (string) $this->keyName, $this->optional ? '?' : '', (string) $this->valueType);
        }
        return (string) $this->valueType;
    }
    /**
     * @param array<string, mixed> $properties
     */
    public static function __set_state(array $properties): self
    {
        $instance = new self($properties['keyName'], $properties['optional'], $properties['valueType']);
        if (isset($properties['attributes'])) {
            foreach ($properties['attributes'] as $key => $value) {
                $instance->setAttribute($key, $value);
            }
        }
        return $instance;
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\PHPStan\PhpDocParser\Ast\Type;

use _ContaoManager\PHPStan\PhpDocParser\Ast\NodeAttributes;
class ThisTypeNode implements TypeNode
{
    use NodeAttributes;
    public function __toString(): string
    {
        return '$this';
    }
    /**
     * @param array<string, mixed> $properties
     */
    public static function __set_state(array $properties): self
    {
        $instance = new self();
        if (isset($properties['attributes'])) {
            foreach ($properties['attributes'] as $key => $value) {
                $instance->setAttribute($key, $value);
            }
        }
        return $instance;
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\PHPStan\PhpDocParser\Ast\Type;

use _ContaoManager\PHPStan\PhpDocParser\Ast\NodeAttributes;
use function implode;
class ObjectShapeNode implements TypeNode
{
    use NodeAttributes;
    /** @var ObjectShapeItemNode[] */
    public array $items;
    /**
     * @param ObjectShapeItemNode[] $items
     */
    public function __construct(array $items)
    {
        $this->items = $items;
    }
    public function __toString(): string
    {
        $items = $this->items;
        return 'object{' . implode(', ', $items) . '}';
    }
    /**
     * @param array<string, mixed> $properties
     */
    public static function __set_state(array $properties): self
    {
        $instance = new self($properties['items']);
        if (isset($properties['attributes'])) {
            foreach ($properties['attributes'] as $key => $value) {
                $instance->setAttribute($key, $value);
            }
        }
        return $instance;
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\PHPStan\PhpDocParser\Ast\Type;

use _ContaoManager\PHPStan\PhpDocParser\Ast\NodeAttributes;
use _ContaoManager\PHPStan\PhpDocParser\Parser\ParserException;
class InvalidTypeNode implements TypeNode
{
    use NodeAttributes;
    /** @var mixed[] */
    private array $exceptionArgs;
    public function __construct(ParserException $exception)
    {
        $this->exceptionArgs = [$exception->getCurrentTokenValue(), $exception->getCurrentTokenType(), $exception->getCurrentOffset(), $exception->getExpectedTokenType(), $exception->getExpectedTokenValue(), $exception->getCurrentTokenLine()];
    }
    public function getException(): ParserException
    {
        return new ParserException(...$this->exceptionArgs);
    }
    public function __toString(): string
    {
        return '*Invalid type*';
    }
    /**
     * @param array<string, mixed> $properties
     */
    public static function __set_state(array $properties): self
    {
        $exception = new ParserException(...$properties['exceptionArgs']);
        $instance = new self($exception);
        if (isset($properties['attributes'])) {
            foreach ($properties['attributes'] as $key => $value) {
                $instance->setAttribute($key, $value);
            }
        }
        return $instance;
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\PHPStan\PhpDocParser\Ast\Type;

use _ContaoManager\PHPStan\PhpDocParser\Ast\NodeAttributes;
class OffsetAccessTypeNode implements TypeNode
{
    use NodeAttributes;
    public TypeNode $type;
    public TypeNode $offset;
    public function __construct(TypeNode $type, TypeNode $offset)
    {
        $this->type = $type;
        $this->offset = $offset;
    }
    public function __toString(): string
    {
        if ($this->type instanceof CallableTypeNode || $this->type instanceof NullableTypeNode) {
            return '(' . $this->type . ')[' . $this->offset . ']';
        }
        return $this->type . '[' . $this->offset . ']';
    }
    /**
     * @param array<string, mixed> $properties
     */
    public static function __set_state(array $properties): self
    {
        $instance = new self($properties['type'], $properties['offset']);
        if (isset($properties['attributes'])) {
            foreach ($properties['attributes'] as $key => $value) {
                $instance->setAttribute($key, $value);
            }
        }
        return $instance;
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\PHPStan\PhpDocParser\Ast\Type;

use _ContaoManager\PHPStan\PhpDocParser\Ast\NodeAttributes;
use function sprintf;
class ConditionalTypeNode implements TypeNode
{
    use NodeAttributes;
    public TypeNode $subjectType;
    public TypeNode $targetType;
    public TypeNode $if;
    public TypeNode $else;
    public bool $negated;
    public function __construct(TypeNode $subjectType, TypeNode $targetType, TypeNode $if, TypeNode $else, bool $negated)
    {
        $this->subjectType = $subjectType;
        $this->targetType = $targetType;
        $this->if = $if;
        $this->else = $else;
        $this->negated = $negated;
    }
    public function __toString(): string
    {
        return sprintf('(%s %s %s ? %s : %s)', $this->subjectType, $this->negated ? 'is not' : 'is', $this->targetType, $this->if, $this->else);
    }
    /**
     * @param array<string, mixed> $properties
     */
    public static function __set_state(array $properties): self
    {
        $instance = new self($properties['subjectType'], $properties['targetType'], $properties['if'], $properties['else'], $properties['negated']);
        if (isset($properties['attributes'])) {
            foreach ($properties['attributes'] as $key => $value) {
                $instance->setAttribute($key, $value);
            }
        }
        return $instance;
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\PHPStan\PhpDocParser\Ast\Type;

use _ContaoManager\PHPStan\PhpDocParser\Ast\Node;
use _ContaoManager\PHPStan\PhpDocParser\Ast\NodeAttributes;
use function sprintf;
class ArrayShapeUnsealedTypeNode implements Node
{
    use NodeAttributes;
    public TypeNode $valueType;
    public ?TypeNode $keyType = null;
    public function __construct(TypeNode $valueType, ?TypeNode $keyType)
    {
        $this->valueType = $valueType;
        $this->keyType = $keyType;
    }
    public function __toString(): string
    {
        if ($this->keyType !== null) {
            return sprintf('<%s, %s>', $this->keyType, $this->valueType);
        }
        return sprintf('<%s>', $this->valueType);
    }
    /**
     * @param array<string, mixed> $properties
     */
    public static function __set_state(array $properties): self
    {
        $instance = new self($properties['valueType'], $properties['keyType']);
        if (isset($properties['attributes'])) {
            foreach ($properties['attributes'] as $key => $value) {
                $instance->setAttribute($key, $value);
            }
        }
        return $instance;
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\PHPStan\PhpDocParser\Ast\Type;

use _ContaoManager\PHPStan\PhpDocParser\Ast\NodeAttributes;
use function sprintf;
class ConditionalTypeForParameterNode implements TypeNode
{
    use NodeAttributes;
    public string $parameterName;
    public TypeNode $targetType;
    public TypeNode $if;
    public TypeNode $else;
    public bool $negated;
    public function __construct(string $parameterName, TypeNode $targetType, TypeNode $if, TypeNode $else, bool $negated)
    {
        $this->parameterName = $parameterName;
        $this->targetType = $targetType;
        $this->if = $if;
        $this->else = $else;
        $this->negated = $negated;
    }
    public function __toString(): string
    {
        return sprintf('(%s %s %s ? %s : %s)', $this->parameterName, $this->negated ? 'is not' : 'is', $this->targetType, $this->if, $this->else);
    }
    /**
     * @param array<string, mixed> $properties
     */
    public static function __set_state(array $properties): self
    {
        $instance = new self($properties['parameterName'], $properties['targetType'], $properties['if'], $properties['else'], $properties['negated']);
        if (isset($properties['attributes'])) {
            foreach ($properties['attributes'] as $key => $value) {
                $instance->setAttribute($key, $value);
            }
        }
        return $instance;
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\PHPStan\PhpDocParser\Ast\Type;

use _ContaoManager\PHPStan\PhpDocParser\Ast\NodeAttributes;
class NullableTypeNode implements TypeNode
{
    use NodeAttributes;
    public TypeNode $type;
    public function __construct(TypeNode $type)
    {
        $this->type = $type;
    }
    public function __toString(): string
    {
        return '?' . $this->type;
    }
    /**
     * @param array<string, mixed> $properties
     */
    public static function __set_state(array $properties): self
    {
        $instance = new self($properties['type']);
        if (isset($properties['attributes'])) {
            foreach ($properties['attributes'] as $key => $value) {
                $instance->setAttribute($key, $value);
            }
        }
        return $instance;
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\PHPStan\PhpDocParser\Ast\Type;

use _ContaoManager\PHPStan\PhpDocParser\Ast\NodeAttributes;
use function implode;
class ArrayShapeNode implements TypeNode
{
    public const KIND_ARRAY = 'array';
    public const KIND_LIST = 'list';
    public const KIND_NON_EMPTY_ARRAY = 'non-empty-array';
    public const KIND_NON_EMPTY_LIST = 'non-empty-list';
    use NodeAttributes;
    /** @var ArrayShapeItemNode[] */
    public array $items;
    public bool $sealed;
    /** @var self::KIND_* */
    public $kind;
    public ?ArrayShapeUnsealedTypeNode $unsealedType = null;
    /**
     * @param ArrayShapeItemNode[] $items
     * @param self::KIND_* $kind
     */
    private function __construct(array $items, bool $sealed = \true, ?ArrayShapeUnsealedTypeNode $unsealedType = null, string $kind = self::KIND_ARRAY)
    {
        $this->items = $items;
        $this->sealed = $sealed;
        $this->unsealedType = $unsealedType;
        $this->kind = $kind;
    }
    /**
     * @param ArrayShapeItemNode[] $items
     * @param self::KIND_* $kind
     */
    public static function createSealed(array $items, string $kind = self::KIND_ARRAY): self
    {
        return new self($items, \true, null, $kind);
    }
    /**
     * @param ArrayShapeItemNode[] $items
     * @param self::KIND_* $kind
     */
    public static function createUnsealed(array $items, ?ArrayShapeUnsealedTypeNode $unsealedType, string $kind = self::KIND_ARRAY): self
    {
        return new self($items, \false, $unsealedType, $kind);
    }
    public function __toString(): string
    {
        $items = $this->items;
        if (!$this->sealed) {
            $items[] = '...' . $this->unsealedType;
        }
        return $this->kind . '{' . implode(', ', $items) . '}';
    }
    /**
     * @param array<string, mixed> $properties
     */
    public static function __set_state(array $properties): self
    {
        $instance = new self($properties['items'], $properties['sealed'], $properties['unsealedType'], $properties['kind']);
        if (isset($properties['attributes'])) {
            foreach ($properties['attributes'] as $key => $value) {
                $instance->setAttribute($key, $value);
            }
        }
        return $instance;
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\PHPStan\PhpDocParser\Ast\Type;

use _ContaoManager\PHPStan\PhpDocParser\Ast\NodeAttributes;
use function implode;
use function sprintf;
class GenericTypeNode implements TypeNode
{
    public const VARIANCE_INVARIANT = 'invariant';
    public const VARIANCE_COVARIANT = 'covariant';
    public const VARIANCE_CONTRAVARIANT = 'contravariant';
    public const VARIANCE_BIVARIANT = 'bivariant';
    use NodeAttributes;
    public IdentifierTypeNode $type;
    /** @var TypeNode[] */
    public array $genericTypes;
    /** @var (self::VARIANCE_*)[] */
    public array $variances;
    /**
     * @param TypeNode[] $genericTypes
     * @param (self::VARIANCE_*)[] $variances
     */
    public function __construct(IdentifierTypeNode $type, array $genericTypes, array $variances = [])
    {
        $this->type = $type;
        $this->genericTypes = $genericTypes;
        $this->variances = $variances;
    }
    public function __toString(): string
    {
        $genericTypes = [];
        foreach ($this->genericTypes as $index => $type) {
            $variance = $this->variances[$index] ?? self::VARIANCE_INVARIANT;
            if ($variance === self::VARIANCE_INVARIANT) {
                $genericTypes[] = (string) $type;
            } elseif ($variance === self::VARIANCE_BIVARIANT) {
                $genericTypes[] = '*';
            } else {
                $genericTypes[] = sprintf('%s %s', $variance, $type);
            }
        }
        return $this->type . '<' . implode(', ', $genericTypes) . '>';
    }
    /**
     * @param array<string, mixed> $properties
     */
    public static function __set_state(array $properties): self
    {
        $instance = new self($properties['type'], $properties['genericTypes'], $properties['variances'] ?? []);
        if (isset($properties['attributes'])) {
            foreach ($properties['attributes'] as $key => $value) {
                $instance->setAttribute($key, $value);
            }
        }
        return $instance;
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\PHPStan\PhpDocParser\Ast\Type;

use _ContaoManager\PHPStan\PhpDocParser\Ast\NodeAttributes;
class ArrayTypeNode implements TypeNode
{
    use NodeAttributes;
    public TypeNode $type;
    public function __construct(TypeNode $type)
    {
        $this->type = $type;
    }
    public function __toString(): string
    {
        if ($this->type instanceof CallableTypeNode || $this->type instanceof ConstTypeNode || $this->type instanceof NullableTypeNode) {
            return '(' . $this->type . ')[]';
        }
        return $this->type . '[]';
    }
    /**
     * @param array<string, mixed> $properties
     */
    public static function __set_state(array $properties): self
    {
        $instance = new self($properties['type']);
        if (isset($properties['attributes'])) {
            foreach ($properties['attributes'] as $key => $value) {
                $instance->setAttribute($key, $value);
            }
        }
        return $instance;
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\PHPStan\PhpDocParser\Ast;

/**
 * Inspired by https://github.com/nikic/PHP-Parser/tree/36a6dcd04e7b0285e8f0868f44bd4927802f7df1
 *
 * Copyright (c) 2011, Nikita Popov
 * All rights reserved.
 */
abstract class AbstractNodeVisitor implements NodeVisitor
{
    public function beforeTraverse(array $nodes): ?array
    {
        return null;
    }
    public function enterNode(Node $node)
    {
        return null;
    }
    public function leaveNode(Node $node)
    {
        return null;
    }
    public function afterTraverse(array $nodes): ?array
    {
        return null;
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\PHPStan\PhpDocParser\Ast;

use function trim;
class Comment
{
    public string $text;
    public int $startLine;
    public int $startIndex;
    public function __construct(string $text, int $startLine = -1, int $startIndex = -1)
    {
        $this->text = $text;
        $this->startLine = $startLine;
        $this->startIndex = $startIndex;
    }
    public function getReformattedText(): string
    {
        return trim($this->text);
    }
    /**
     * @param array<string, mixed> $properties
     */
    public static function __set_state(array $properties): self
    {
        return new self($properties['text'], $properties['startLine'], $properties['startIndex']);
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\PHPStan\PhpDocParser\Ast;

use function array_key_exists;
trait NodeAttributes
{
    /** @var array<string, mixed> */
    private array $attributes = [];
    /**
     * @param mixed $value
     */
    public function setAttribute(string $key, $value): void
    {
        if ($value === null) {
            unset($this->attributes[$key]);
            return;
        }
        $this->attributes[$key] = $value;
    }
    public function hasAttribute(string $key): bool
    {
        return array_key_exists($key, $this->attributes);
    }
    /**
     * @return mixed
     */
    public function getAttribute(string $key)
    {
        if ($this->hasAttribute($key)) {
            return $this->attributes[$key];
        }
        return null;
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\PHPStan\PhpDocParser\Ast;

use LogicException;
use _ContaoManager\PHPStan\PhpDocParser\Ast\ConstExpr\ConstExprNode;
use _ContaoManager\PHPStan\PhpDocParser\Ast\PhpDoc\PhpDocChildNode;
use _ContaoManager\PHPStan\PhpDocParser\Ast\PhpDoc\PhpDocTagValueNode;
use _ContaoManager\PHPStan\PhpDocParser\Ast\Type\TypeNode;
use function array_keys;
use function array_pop;
use function array_splice;
use function count;
use function get_class;
use function get_object_vars;
use function gettype;
use function is_array;
use function sprintf;
/**
 * Inspired by https://github.com/nikic/PHP-Parser/tree/36a6dcd04e7b0285e8f0868f44bd4927802f7df1
 *
 * Copyright (c) 2011, Nikita Popov
 * All rights reserved.
 */
final class NodeTraverser
{
    /**
     * If NodeVisitor::enterNode() returns DONT_TRAVERSE_CHILDREN, child nodes
     * of the current node will not be traversed for any visitors.
     *
     * For subsequent visitors enterNode() will still be called on the current
     * node and leaveNode() will also be invoked for the current node.
     */
    public const DONT_TRAVERSE_CHILDREN = 1;
    /**
     * If NodeVisitor::enterNode() or NodeVisitor::leaveNode() returns
     * STOP_TRAVERSAL, traversal is aborted.
     *
     * The afterTraverse() method will still be invoked.
     */
    public const STOP_TRAVERSAL = 2;
    /**
     * If NodeVisitor::leaveNode() returns REMOVE_NODE for a node that occurs
     * in an array, it will be removed from the array.
     *
     * For subsequent visitors leaveNode() will still be invoked for the
     * removed node.
     */
    public const REMOVE_NODE = 3;
    /**
     * If NodeVisitor::enterNode() returns DONT_TRAVERSE_CURRENT_AND_CHILDREN, child nodes
     * of the current node will not be traversed for any visitors.
     *
     * For subsequent visitors enterNode() will not be called as well.
     * leaveNode() will be invoked for visitors that has enterNode() method invoked.
     */
    public const DONT_TRAVERSE_CURRENT_AND_CHILDREN = 4;
    /** @var list<NodeVisitor> Visitors */
    private array $visitors = [];
    /** @var bool Whether traversal should be stopped */
    private bool $stopTraversal;
    /**
     * @param list<NodeVisitor> $visitors
     */
    public function __construct(array $visitors)
    {
        $this->visitors = $visitors;
    }
    /**
     * Traverses an array of nodes using the registered visitors.
     *
     * @param Node[] $nodes Array of nodes
     *
     * @return Node[] Traversed array of nodes
     */
    public function traverse(array $nodes): array
    {
        $this->stopTraversal = \false;
        foreach ($this->visitors as $visitor) {
            $return = $visitor->beforeTraverse($nodes);
            if ($return === null) {
                continue;
            }
            $nodes = $return;
        }
        $nodes = $this->traverseArray($nodes);
        foreach ($this->visitors as $visitor) {
            $return = $visitor->afterTraverse($nodes);
            if ($return === null) {
                continue;
            }
            $nodes = $return;
        }
        return $nodes;
    }
    /**
     * Recursively traverse a node.
     *
     * @param Node $node Node to traverse.
     *
     * @return Node Result of traversal (may be original node or new one)
     */
    private function traverseNode(Node $node): Node
    {
        $subNodeNames = array_keys(get_object_vars($node));
        foreach ($subNodeNames as $name) {
            $subNode =& $node->{$name};
            if (is_array($subNode)) {
                $subNode = $this->traverseArray($subNode);
                if ($this->stopTraversal) {
                    break;
                }
            } elseif ($subNode instanceof Node) {
                $traverseChildren = \true;
                $breakVisitorIndex = null;
                foreach ($this->visitors as $visitorIndex => $visitor) {
                    $return = $visitor->enterNode($subNode);
                    if ($return === null) {
                        continue;
                    }
                    if ($return instanceof Node) {
                        $this->ensureReplacementReasonable($subNode, $return);
                        $subNode = $return;
                    } elseif ($return === self::DONT_TRAVERSE_CHILDREN) {
                        $traverseChildren = \false;
                    } elseif ($return === self::DONT_TRAVERSE_CURRENT_AND_CHILDREN) {
                        $traverseChildren = \false;
                        $breakVisitorIndex = $visitorIndex;
                        break;
                    } elseif ($return === self::STOP_TRAVERSAL) {
                        $this->stopTraversal = \true;
                        break 2;
                    } else {
                        throw new LogicException('enterNode() returned invalid value of type ' . gettype($return));
                    }
                }
                if ($traverseChildren) {
                    $subNode = $this->traverseNode($subNode);
                    if ($this->stopTraversal) {
                        break;
                    }
                }
                foreach ($this->visitors as $visitorIndex => $visitor) {
                    $return = $visitor->leaveNode($subNode);
                    if ($return !== null) {
                        if ($return instanceof Node) {
                            $this->ensureReplacementReasonable($subNode, $return);
                            $subNode = $return;
                        } elseif ($return === self::STOP_TRAVERSAL) {
                            $this->stopTraversal = \true;
                            break 2;
                        } elseif (is_array($return)) {
                            throw new LogicException('leaveNode() may only return an array ' . 'if the parent structure is an array');
                        } else {
                            throw new LogicException('leaveNode() returned invalid value of type ' . gettype($return));
                        }
                    }
                    if ($breakVisitorIndex === $visitorIndex) {
                        break;
                    }
                }
            }
        }
        return $node;
    }
    /**
     * Recursively traverse array (usually of nodes).
     *
     * @param mixed[] $nodes Array to traverse
     *
     * @return mixed[] Result of traversal (may be original array or changed one)
     */
    private function traverseArray(array $nodes): array
    {
        $doNodes = [];
        foreach ($nodes as $i => &$node) {
            if ($node instanceof Node) {
                $traverseChildren = \true;
                $breakVisitorIndex = null;
                foreach ($this->visitors as $visitorIndex => $visitor) {
                    $return = $visitor->enterNode($node);
                    if ($return === null) {
                        continue;
                    }
                    if ($return instanceof Node) {
                        $this->ensureReplacementReasonable($node, $return);
                        $node = $return;
                    } elseif (is_array($return)) {
                        $doNodes[] = [$i, $return];
                        continue 2;
                    } elseif ($return === self::REMOVE_NODE) {
                        $doNodes[] = [$i, []];
                        continue 2;
                    } elseif ($return === self::DONT_TRAVERSE_CHILDREN) {
                        $traverseChildren = \false;
                    } elseif ($return === self::DONT_TRAVERSE_CURRENT_AND_CHILDREN) {
                        $traverseChildren = \false;
                        $breakVisitorIndex = $visitorIndex;
                        break;
                    } elseif ($return === self::STOP_TRAVERSAL) {
                        $this->stopTraversal = \true;
                        break 2;
                    } else {
                        throw new LogicException('enterNode() returned invalid value of type ' . gettype($return));
                    }
                }
                if ($traverseChildren) {
                    $node = $this->traverseNode($node);
                    if ($this->stopTraversal) {
                        break;
                    }
                }
                foreach ($this->visitors as $visitorIndex => $visitor) {
                    $return = $visitor->leaveNode($node);
                    if ($return !== null) {
                        if ($return instanceof Node) {
                            $this->ensureReplacementReasonable($node, $return);
                            $node = $return;
                        } elseif (is_array($return)) {
                            $doNodes[] = [$i, $return];
                            break;
                        } elseif ($return === self::REMOVE_NODE) {
                            $doNodes[] = [$i, []];
                            break;
                        } elseif ($return === self::STOP_TRAVERSAL) {
                            $this->stopTraversal = \true;
                            break 2;
                        } else {
                            throw new LogicException('leaveNode() returned invalid value of type ' . gettype($return));
                        }
                    }
                    if ($breakVisitorIndex === $visitorIndex) {
                        break;
                    }
                }
            } elseif (is_array($node)) {
                throw new LogicException('Invalid node structure: Contains nested arrays');
            }
        }
        if (count($doNodes) > 0) {
            while ([$i, $replace] = array_pop($doNodes)) {
                array_splice($nodes, $i, 1, $replace);
            }
        }
        return $nodes;
    }
    private function ensureReplacementReasonable(Node $old, Node $new): void
    {
        if ($old instanceof TypeNode && !$new instanceof TypeNode) {
            throw new LogicException(sprintf('Trying to replace TypeNode with %s', get_class($new)));
        }
        if ($old instanceof ConstExprNode && !$new instanceof ConstExprNode) {
            throw new LogicException(sprintf('Trying to replace ConstExprNode with %s', get_class($new)));
        }
        if ($old instanceof PhpDocChildNode && !$new instanceof PhpDocChildNode) {
            throw new LogicException(sprintf('Trying to replace PhpDocChildNode with %s', get_class($new)));
        }
        if ($old instanceof PhpDocTagValueNode && !$new instanceof PhpDocTagValueNode) {
            throw new LogicException(sprintf('Trying to replace PhpDocTagValueNode with %s', get_class($new)));
        }
    }
}
MIT License

Copyright (c) 2017 Luís Cobucci

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
{
  "$schema": "https://docs.renovatebot.com/renovate-schema.json",
  "extends": [
    "local>lcobucci/.github:renovate-config"
  ]
}
{
    "name": "lcobucci\/clock",
    "description": "Yet another clock abstraction",
    "license": "MIT",
    "type": "library",
    "authors": [
        {
            "name": "Lu\u00eds Cobucci",
            "email": "lcobucci@gmail.com"
        }
    ],
    "require": {
        "php": "~8.1.0 || ~8.2.0",
        "psr\/clock": "^1.0"
    },
    "require-dev": {
        "infection\/infection": "^0.26",
        "lcobucci\/coding-standard": "^9.0",
        "phpstan\/extension-installer": "^1.2",
        "phpstan\/phpstan": "^1.9.4",
        "phpstan\/phpstan-deprecation-rules": "^1.1.1",
        "phpstan\/phpstan-phpunit": "^1.3.2",
        "phpstan\/phpstan-strict-rules": "^1.4.4",
        "phpunit\/phpunit": "^9.5.27"
    },
    "autoload": {
        "psr-4": {
            "_ContaoManager\\Lcobucci\\Clock\\": "src"
        }
    },
    "autoload-dev": {
        "psr-4": {
            "_ContaoManager\\Lcobucci\\Clock\\": "test"
        }
    },
    "config": {
        "preferred-install": "dist",
        "sort-packages": true,
        "allow-plugins": {
            "dealerdirect\/phpcodesniffer-composer-installer": true,
            "infection\/extension-installer": true,
            "phpstan\/extension-installer": true
        }
    },
    "provide": {
        "psr\/clock-implementation": "1.0"
    }
}<?php

declare (strict_types=1);
namespace _ContaoManager\Lcobucci\Clock;

use DateTimeImmutable;
use _ContaoManager\Psr\Clock\ClockInterface;
interface Clock extends ClockInterface
{
    public function now(): DateTimeImmutable;
}
<?php

declare (strict_types=1);
namespace _ContaoManager\Lcobucci\Clock;

use DateTimeImmutable;
use DateTimeZone;
final class FrozenClock implements Clock
{
    public function __construct(private DateTimeImmutable $now)
    {
    }
    public static function fromUTC(): self
    {
        return new self(new DateTimeImmutable('now', new DateTimeZone('UTC')));
    }
    public function setTo(DateTimeImmutable $now): void
    {
        $this->now = $now;
    }
    public function now(): DateTimeImmutable
    {
        return $this->now;
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\Lcobucci\Clock;

use DateTimeImmutable;
use DateTimeZone;
use function date_default_timezone_get;
final class SystemClock implements Clock
{
    public function __construct(private readonly DateTimeZone $timezone)
    {
    }
    public static function fromUTC(): self
    {
        return new self(new DateTimeZone('UTC'));
    }
    public static function fromSystemTimezone(): self
    {
        return new self(new DateTimeZone(date_default_timezone_get()));
    }
    public function now(): DateTimeImmutable
    {
        return new DateTimeImmutable('now', $this->timezone);
    }
}
#!/usr/bin/env php
<?php 
/**
 * Proxy PHP file generated by Composer
 *
 * This file includes the referenced bin path (../symfony/yaml/Resources/bin/yaml-lint)
 * using a stream wrapper to prevent the shebang from being output on PHP<8
 *
 * @generated
 */
namespace Composer;

$GLOBALS['_composer_bin_dir'] = __DIR__;
$GLOBALS['_composer_autoload_path'] = __DIR__ . '/..' . '/autoload.php';
if (\PHP_VERSION_ID < 80000) {
    if (!class_exists('Composer\BinProxyWrapper')) {
        /**
         * @internal
         */
        final class BinProxyWrapper
        {
            private $handle;
            private $position;
            private $realpath;
            public function stream_open($path, $mode, $options, &$opened_path)
            {
                // get rid of phpvfscomposer:// prefix for __FILE__ & __DIR__ resolution
                $opened_path = substr($path, 17);
                $this->realpath = realpath($opened_path) ?: $opened_path;
                $opened_path = $this->realpath;
                $this->handle = fopen($this->realpath, $mode);
                $this->position = 0;
                return (bool) $this->handle;
            }
            public function stream_read($count)
            {
                $data = fread($this->handle, $count);
                if ($this->position === 0) {
                    $data = preg_replace('{^#!.*\r?\n}', '', $data);
                }
                $this->position += strlen($data);
                return $data;
            }
            public function stream_cast($castAs)
            {
                return $this->handle;
            }
            public function stream_close()
            {
                fclose($this->handle);
            }
            public function stream_lock($operation)
            {
                return $operation ? flock($this->handle, $operation) : \true;
            }
            public function stream_seek($offset, $whence)
            {
                if (0 === fseek($this->handle, $offset, $whence)) {
                    $this->position = ftell($this->handle);
                    return \true;
                }
                return \false;
            }
            public function stream_tell()
            {
                return $this->position;
            }
            public function stream_eof()
            {
                return feof($this->handle);
            }
            public function stream_stat()
            {
                return array();
            }
            public function stream_set_option($option, $arg1, $arg2)
            {
                return \true;
            }
            public function url_stat($path, $flags)
            {
                $path = substr($path, 17);
                if (file_exists($path)) {
                    return stat($path);
                }
                return \false;
            }
        }
    }
    if (function_exists('stream_get_wrappers') && in_array('phpvfscomposer', stream_get_wrappers(), \true) || function_exists('stream_wrapper_register') && stream_wrapper_register('phpvfscomposer', 'Composer\BinProxyWrapper')) {
        return include "phpvfscomposer://" . __DIR__ . '/..' . '/symfony/yaml/Resources/bin/yaml-lint';
    }
}
return include __DIR__ . '/..' . '/symfony/yaml/Resources/bin/yaml-lint';
#!/usr/bin/env php
<?php 
/**
 * Proxy PHP file generated by Composer
 *
 * This file includes the referenced bin path (../symfony/error-handler/Resources/bin/patch-type-declarations)
 * using a stream wrapper to prevent the shebang from being output on PHP<8
 *
 * @generated
 */
namespace Composer;

$GLOBALS['_composer_bin_dir'] = __DIR__;
$GLOBALS['_composer_autoload_path'] = __DIR__ . '/..' . '/autoload.php';
if (\PHP_VERSION_ID < 80000) {
    if (!class_exists('Composer\BinProxyWrapper')) {
        /**
         * @internal
         */
        final class BinProxyWrapper
        {
            private $handle;
            private $position;
            private $realpath;
            public function stream_open($path, $mode, $options, &$opened_path)
            {
                // get rid of phpvfscomposer:// prefix for __FILE__ & __DIR__ resolution
                $opened_path = substr($path, 17);
                $this->realpath = realpath($opened_path) ?: $opened_path;
                $opened_path = $this->realpath;
                $this->handle = fopen($this->realpath, $mode);
                $this->position = 0;
                return (bool) $this->handle;
            }
            public function stream_read($count)
            {
                $data = fread($this->handle, $count);
                if ($this->position === 0) {
                    $data = preg_replace('{^#!.*\r?\n}', '', $data);
                }
                $this->position += strlen($data);
                return $data;
            }
            public function stream_cast($castAs)
            {
                return $this->handle;
            }
            public function stream_close()
            {
                fclose($this->handle);
            }
            public function stream_lock($operation)
            {
                return $operation ? flock($this->handle, $operation) : \true;
            }
            public function stream_seek($offset, $whence)
            {
                if (0 === fseek($this->handle, $offset, $whence)) {
                    $this->position = ftell($this->handle);
                    return \true;
                }
                return \false;
            }
            public function stream_tell()
            {
                return $this->position;
            }
            public function stream_eof()
            {
                return feof($this->handle);
            }
            public function stream_stat()
            {
                return array();
            }
            public function stream_set_option($option, $arg1, $arg2)
            {
                return \true;
            }
            public function url_stat($path, $flags)
            {
                $path = substr($path, 17);
                if (file_exists($path)) {
                    return stat($path);
                }
                return \false;
            }
        }
    }
    if (function_exists('stream_get_wrappers') && in_array('phpvfscomposer', stream_get_wrappers(), \true) || function_exists('stream_wrapper_register') && stream_wrapper_register('phpvfscomposer', 'Composer\BinProxyWrapper')) {
        return include "phpvfscomposer://" . __DIR__ . '/..' . '/symfony/error-handler/Resources/bin/patch-type-declarations';
    }
}
return include __DIR__ . '/..' . '/symfony/error-handler/Resources/bin/patch-type-declarations';
#!/usr/bin/env php
<?php 
/**
 * Proxy PHP file generated by Composer
 *
 * This file includes the referenced bin path (../justinrainbow/json-schema/bin/validate-json)
 * using a stream wrapper to prevent the shebang from being output on PHP<8
 *
 * @generated
 */
namespace Composer;

$GLOBALS['_composer_bin_dir'] = __DIR__;
$GLOBALS['_composer_autoload_path'] = __DIR__ . '/..' . '/autoload.php';
if (\PHP_VERSION_ID < 80000) {
    if (!class_exists('Composer\BinProxyWrapper')) {
        /**
         * @internal
         */
        final class BinProxyWrapper
        {
            private $handle;
            private $position;
            private $realpath;
            public function stream_open($path, $mode, $options, &$opened_path)
            {
                // get rid of phpvfscomposer:// prefix for __FILE__ & __DIR__ resolution
                $opened_path = substr($path, 17);
                $this->realpath = realpath($opened_path) ?: $opened_path;
                $opened_path = $this->realpath;
                $this->handle = fopen($this->realpath, $mode);
                $this->position = 0;
                return (bool) $this->handle;
            }
            public function stream_read($count)
            {
                $data = fread($this->handle, $count);
                if ($this->position === 0) {
                    $data = preg_replace('{^#!.*\r?\n}', '', $data);
                }
                $this->position += strlen($data);
                return $data;
            }
            public function stream_cast($castAs)
            {
                return $this->handle;
            }
            public function stream_close()
            {
                fclose($this->handle);
            }
            public function stream_lock($operation)
            {
                return $operation ? flock($this->handle, $operation) : \true;
            }
            public function stream_seek($offset, $whence)
            {
                if (0 === fseek($this->handle, $offset, $whence)) {
                    $this->position = ftell($this->handle);
                    return \true;
                }
                return \false;
            }
            public function stream_tell()
            {
                return $this->position;
            }
            public function stream_eof()
            {
                return feof($this->handle);
            }
            public function stream_stat()
            {
                return array();
            }
            public function stream_set_option($option, $arg1, $arg2)
            {
                return \true;
            }
            public function url_stat($path, $flags)
            {
                $path = substr($path, 17);
                if (file_exists($path)) {
                    return stat($path);
                }
                return \false;
            }
        }
    }
    if (function_exists('stream_get_wrappers') && in_array('phpvfscomposer', stream_get_wrappers(), \true) || function_exists('stream_wrapper_register') && stream_wrapper_register('phpvfscomposer', 'Composer\BinProxyWrapper')) {
        return include "phpvfscomposer://" . __DIR__ . '/..' . '/justinrainbow/json-schema/bin/validate-json';
    }
}
return include __DIR__ . '/..' . '/justinrainbow/json-schema/bin/validate-json';
#!/usr/bin/env php
<?php 
/**
 * Proxy PHP file generated by Composer
 *
 * This file includes the referenced bin path (../composer/composer/bin/composer)
 * using a stream wrapper to prevent the shebang from being output on PHP<8
 *
 * @generated
 */
namespace Composer;

$GLOBALS['_composer_bin_dir'] = __DIR__;
$GLOBALS['_composer_autoload_path'] = __DIR__ . '/..' . '/autoload.php';
if (\PHP_VERSION_ID < 80000) {
    if (!class_exists('Composer\BinProxyWrapper')) {
        /**
         * @internal
         */
        final class BinProxyWrapper
        {
            private $handle;
            private $position;
            private $realpath;
            public function stream_open($path, $mode, $options, &$opened_path)
            {
                // get rid of phpvfscomposer:// prefix for __FILE__ & __DIR__ resolution
                $opened_path = substr($path, 17);
                $this->realpath = realpath($opened_path) ?: $opened_path;
                $opened_path = $this->realpath;
                $this->handle = fopen($this->realpath, $mode);
                $this->position = 0;
                return (bool) $this->handle;
            }
            public function stream_read($count)
            {
                $data = fread($this->handle, $count);
                if ($this->position === 0) {
                    $data = preg_replace('{^#!.*\r?\n}', '', $data);
                }
                $this->position += strlen($data);
                return $data;
            }
            public function stream_cast($castAs)
            {
                return $this->handle;
            }
            public function stream_close()
            {
                fclose($this->handle);
            }
            public function stream_lock($operation)
            {
                return $operation ? flock($this->handle, $operation) : \true;
            }
            public function stream_seek($offset, $whence)
            {
                if (0 === fseek($this->handle, $offset, $whence)) {
                    $this->position = ftell($this->handle);
                    return \true;
                }
                return \false;
            }
            public function stream_tell()
            {
                return $this->position;
            }
            public function stream_eof()
            {
                return feof($this->handle);
            }
            public function stream_stat()
            {
                return array();
            }
            public function stream_set_option($option, $arg1, $arg2)
            {
                return \true;
            }
            public function url_stat($path, $flags)
            {
                $path = substr($path, 17);
                if (file_exists($path)) {
                    return stat($path);
                }
                return \false;
            }
        }
    }
    if (function_exists('stream_get_wrappers') && in_array('phpvfscomposer', stream_get_wrappers(), \true) || function_exists('stream_wrapper_register') && stream_wrapper_register('phpvfscomposer', 'Composer\BinProxyWrapper')) {
        return include "phpvfscomposer://" . __DIR__ . '/..' . '/composer/composer/bin/composer';
    }
}
return include __DIR__ . '/..' . '/composer/composer/bin/composer';
#!/usr/bin/env php
<?php 
/**
 * Proxy PHP file generated by Composer
 *
 * This file includes the referenced bin path (../symfony/var-dumper/Resources/bin/var-dump-server)
 * using a stream wrapper to prevent the shebang from being output on PHP<8
 *
 * @generated
 */
namespace Composer;

$GLOBALS['_composer_bin_dir'] = __DIR__;
$GLOBALS['_composer_autoload_path'] = __DIR__ . '/..' . '/autoload.php';
if (\PHP_VERSION_ID < 80000) {
    if (!class_exists('Composer\BinProxyWrapper')) {
        /**
         * @internal
         */
        final class BinProxyWrapper
        {
            private $handle;
            private $position;
            private $realpath;
            public function stream_open($path, $mode, $options, &$opened_path)
            {
                // get rid of phpvfscomposer:// prefix for __FILE__ & __DIR__ resolution
                $opened_path = substr($path, 17);
                $this->realpath = realpath($opened_path) ?: $opened_path;
                $opened_path = $this->realpath;
                $this->handle = fopen($this->realpath, $mode);
                $this->position = 0;
                return (bool) $this->handle;
            }
            public function stream_read($count)
            {
                $data = fread($this->handle, $count);
                if ($this->position === 0) {
                    $data = preg_replace('{^#!.*\r?\n}', '', $data);
                }
                $this->position += strlen($data);
                return $data;
            }
            public function stream_cast($castAs)
            {
                return $this->handle;
            }
            public function stream_close()
            {
                fclose($this->handle);
            }
            public function stream_lock($operation)
            {
                return $operation ? flock($this->handle, $operation) : \true;
            }
            public function stream_seek($offset, $whence)
            {
                if (0 === fseek($this->handle, $offset, $whence)) {
                    $this->position = ftell($this->handle);
                    return \true;
                }
                return \false;
            }
            public function stream_tell()
            {
                return $this->position;
            }
            public function stream_eof()
            {
                return feof($this->handle);
            }
            public function stream_stat()
            {
                return array();
            }
            public function stream_set_option($option, $arg1, $arg2)
            {
                return \true;
            }
            public function url_stat($path, $flags)
            {
                $path = substr($path, 17);
                if (file_exists($path)) {
                    return stat($path);
                }
                return \false;
            }
        }
    }
    if (function_exists('stream_get_wrappers') && in_array('phpvfscomposer', stream_get_wrappers(), \true) || function_exists('stream_wrapper_register') && stream_wrapper_register('phpvfscomposer', 'Composer\BinProxyWrapper')) {
        return include "phpvfscomposer://" . __DIR__ . '/..' . '/symfony/var-dumper/Resources/bin/var-dump-server';
    }
}
return include __DIR__ . '/..' . '/symfony/var-dumper/Resources/bin/var-dump-server';
#!/usr/bin/env php
<?php 
/**
 * Proxy PHP file generated by Composer
 *
 * This file includes the referenced bin path (../seld/jsonlint/bin/jsonlint)
 * using a stream wrapper to prevent the shebang from being output on PHP<8
 *
 * @generated
 */
namespace Composer;

$GLOBALS['_composer_bin_dir'] = __DIR__;
$GLOBALS['_composer_autoload_path'] = __DIR__ . '/..' . '/autoload.php';
if (\PHP_VERSION_ID < 80000) {
    if (!class_exists('Composer\BinProxyWrapper')) {
        /**
         * @internal
         */
        final class BinProxyWrapper
        {
            private $handle;
            private $position;
            private $realpath;
            public function stream_open($path, $mode, $options, &$opened_path)
            {
                // get rid of phpvfscomposer:// prefix for __FILE__ & __DIR__ resolution
                $opened_path = substr($path, 17);
                $this->realpath = realpath($opened_path) ?: $opened_path;
                $opened_path = $this->realpath;
                $this->handle = fopen($this->realpath, $mode);
                $this->position = 0;
                return (bool) $this->handle;
            }
            public function stream_read($count)
            {
                $data = fread($this->handle, $count);
                if ($this->position === 0) {
                    $data = preg_replace('{^#!.*\r?\n}', '', $data);
                }
                $this->position += strlen($data);
                return $data;
            }
            public function stream_cast($castAs)
            {
                return $this->handle;
            }
            public function stream_close()
            {
                fclose($this->handle);
            }
            public function stream_lock($operation)
            {
                return $operation ? flock($this->handle, $operation) : \true;
            }
            public function stream_seek($offset, $whence)
            {
                if (0 === fseek($this->handle, $offset, $whence)) {
                    $this->position = ftell($this->handle);
                    return \true;
                }
                return \false;
            }
            public function stream_tell()
            {
                return $this->position;
            }
            public function stream_eof()
            {
                return feof($this->handle);
            }
            public function stream_stat()
            {
                return array();
            }
            public function stream_set_option($option, $arg1, $arg2)
            {
                return \true;
            }
            public function url_stat($path, $flags)
            {
                $path = substr($path, 17);
                if (file_exists($path)) {
                    return stat($path);
                }
                return \false;
            }
        }
    }
    if (function_exists('stream_get_wrappers') && in_array('phpvfscomposer', stream_get_wrappers(), \true) || function_exists('stream_wrapper_register') && stream_wrapper_register('phpvfscomposer', 'Composer\BinProxyWrapper')) {
        return include "phpvfscomposer://" . __DIR__ . '/..' . '/seld/jsonlint/bin/jsonlint';
    }
}
return include __DIR__ . '/..' . '/seld/jsonlint/bin/jsonlint';
<?php

namespace _ContaoManager;

if (\PHP_VERSION_ID < 80000) {
    interface Stringable
    {
        /**
         * @return string
         */
        public function __toString();
    }
    \class_alias('_ContaoManager\Stringable', 'Stringable', \false);
}
# php-enum
[![Build Status](https://github.com/marc-mabe/php-enum/workflows/Test/badge.svg?branch=master)](https://github.com/marc-mabe/php-enum/actions?query=workflow%3ATest%20branch%3Amaster)
[![Code Coverage](https://codecov.io/github/marc-mabe/php-enum/coverage.svg?branch=master)](https://codecov.io/gh/marc-mabe/php-enum/branch/master/)
[![License](https://poser.pugx.org/marc-mabe/php-enum/license)](https://github.com/marc-mabe/php-enum/blob/master/LICENSE.txt)
[![Latest Stable](https://poser.pugx.org/marc-mabe/php-enum/v/stable.png)](https://packagist.org/packages/marc-mabe/php-enum)
[![Total Downloads](https://poser.pugx.org/marc-mabe/php-enum/downloads.png)](https://packagist.org/packages/marc-mabe/php-enum)
[![Monthly Downloads](https://poser.pugx.org/marc-mabe/php-enum/d/monthly)](https://packagist.org/packages/marc-mabe/php-enum)
[![Dependents](https://poser.pugx.org/marc-mabe/php-enum/dependents)](https://packagist.org/packages/marc-mabe/php-enum/dependents?order_by=downloads)

This is a native PHP implementation to add enumeration support to PHP.
It's an abstract class that needs to be extended to use it.


# What is an Enumeration?

[Wikipedia](http://wikipedia.org/wiki/Enumerated_type)
> In computer programming, an enumerated type (also called enumeration or enum)
> is a data type consisting of a set of named values called elements, members
> or enumerators of the type. The enumerator names are usually identifiers that
> behave as constants in the language. A variable that has been declared as
> having an enumerated type can be assigned any of the enumerators as a value.
> In other words, an enumerated type has values that are different from each
> other, and that can be compared and assigned, but which do not have any
> particular concrete representation in the computer's memory; compilers and
> interpreters can represent them arbitrarily.


# Usage

## Basics

```php
use MabeEnum\Enum;

// define an own enumeration class
class UserStatus extends Enum
{
    const INACTIVE = 'i';
    const ACTIVE   = 'a';
    const DELETED  = 'd';

    // all scalar data types and arrays are supported as enumerator values
    const NIL     = null;
    const BOOLEAN = true;
    const INT     = 1234;
    const STR     = 'string';
    const FLOAT   = 0.123;
    const ARR     = ['this', 'is', ['an', 'array']];

    // Enumerators will be generated from public constants only
    public    const PUBLIC_CONST    = 'public constant';    // this will be an enumerator
    protected const PROTECTED_CONST = 'protected constant'; // this will NOT be an enumerator
    private   const PRIVATE_CONST   = 'private constant';   // this will NOT be an enumerator

    // works since PHP-7.0 - see https://wiki.php.net/rfc/context_sensitive_lexer
    const TRUE      = 'true';
    const FALSE     = 'false';
    const NULL      = 'null';
    const PUBLIC    = 'public';
    const PRIVATE   = 'private';
    const PROTECTED = 'protected';
    const FUNCTION  = 'function';
    const TRAIT     = 'trait';
    const INTERFACE = 'interface';

    // Doesn't work - see https://wiki.php.net/rfc/class_name_scalars
    // const CLASS = 'class';
}

// ways to instantiate an enumerator
$status = UserStatus::get(UserStatus::ACTIVE); // by value or instance
$status = UserStatus::ACTIVE();                // by name as callable
$status = UserStatus::byValue('a');            // by value
$status = UserStatus::byName('ACTIVE');        // by name
$status = UserStatus::byOrdinal(1);            // by ordinal number

// basic methods of an instantiated enumerator
$status->getValue();   // returns the selected constant value
$status->getName();    // returns the selected constant name
$status->getOrdinal(); // returns the ordinal number of the selected constant

// basic methods to list defined enumerators
UserStatus::getEnumerators();  // returns a list of enumerator instances
UserStatus::getValues();       // returns a list of enumerator values
UserStatus::getNames();        // returns a list of enumerator names
UserStatus::getOrdinals();     // returns a list of ordinal numbers
UserStatus::getConstants();    // returns an associative array of enumerator names to enumerator values

// same enumerators (of the same enumeration class) holds the same instance
UserStatus::get(UserStatus::ACTIVE) === UserStatus::ACTIVE()
UserStatus::get(UserStatus::DELETED) != UserStatus::INACTIVE()

// simplified way to compare two enumerators
$status = UserStatus::ACTIVE();
$status->is(UserStatus::ACTIVE);     // true
$status->is(UserStatus::ACTIVE());   // true
$status->is(UserStatus::DELETED);    // false
$status->is(UserStatus::DELETED());  // false
```

## Type-Hint

```php
use MabeEnum\Enum;

class User
{
    protected $status;

    public function setStatus(UserStatus $status)
    {
        $this->status = $status;
    }

    public function getStatus()
    {
        if (!$this->status) {
            // initialize default
            $this->status = UserStatus::INACTIVE();
        }
        return $this->status;
    }
}
```

### Type-Hint issue

Because in normal OOP the above example allows `UserStatus` and types inherited from it.

Please think about the following example:

```php
class ExtendedUserStatus extends UserStatus
{
    const EXTENDED = 'extended';
}

$user = new User();
$user->setStatus(ExtendedUserStatus::EXTENDED());
```

Now the setter receives a status it doesn't know about but allows it.

#### Solution 1: Finalize the enumeration

```php
final class UserStatus extends Enum
{
    // ...
}

class User
{
    protected $status;

    public function setStatus(UserStatus $status)
    {
        $this->status = $status;
    }
}
````

* Nice and obvious solution

* Resulting behaviour matches native enumeration implementation of most other languages (like Java)

But as this library emulates enumerations it has a few downsides:

* Enumerator values can not be used directly
  * `$user->setStatus(UserStatus::ACTIVE)` fails
  * `$user->setStatus(UserStatus::ACTIVE())` works

* Does not help if the enumeration was defined in an external library


#### Solution 2: Using `Enum::get()`

```php
class User
{
    public function setStatus($status)
    {
        $this->status = UserStatus::get($status);
    }
}
```

* Makes sure the resulting enumerator exactly matches an enumeration. (Inherited enumerators are not allowed).

* Allows enumerator values directly
  * `$user->setStatus(UserStatus::ACTIVE)` works
  * `$user->setStatus(UserStatus::ACTIVE())` works

* Also works for enumerations defined in external libraries

But of course this solution has downsides, too:

* Looses declarative type-hint

* A bit slower


## EnumSet

An `EnumSet` is a specialized Set implementation for use with enumeration types.
All of the enumerators in an `EnumSet` must come from a single enumeration type that is specified, when the set is
created.

Enum sets are represented internally as bit vectors. The bit vector is either an integer type or a binary string type
depending on how many enumerators are defined in the enumeration type. This representation is extremely compact and
efficient. Bulk operations will run very quickly. Enumerators of an `EnumSet` are unique and ordered based on its
ordinal number by design.

It implements `IteratorAggregate` and `Countable` to be directly iterable with `foreach` and countable with `count()`.

The `EnumSet` has a mutable and an immutable interface.
Mutable methods start with `set`, `add` or `remove` while immutable methods start with `with`.

```php
use MabeEnum\EnumSet;

// create a new EnumSet and initialize with the given enumerators
$enumSet = new EnumSet('UserStatus', [UserStatus::ACTIVE()]);

// modify an EnumSet (mutable interface)

// add enumerators (by value or by instance)
$enumSet->addIterable([UserStatus::INACTIVE, UserStatus::DELETED()]);
// or
$enumSet->add(UserStatus::INACTIVE);
$enumSet->add(UserStatus::DELETED());

// remove enumerators (by value or by instance)
$enumSet->removeIterable([UserStatus::INACTIVE, UserStatus::DELETED()]);
// or
$enumSet->remove(UserStatus::INACTIVE);
$enumSet->remove(UserStatus::DELETED());


// The immutable interface will create a new EnumSet for each modification 

// add enumerators (by value or by instance)
$enumSet = $enumSet->withIterable([UserStatus::INACTIVE, UserStatus::DELETED()]);
// or
$enumSet = $enumSet->with(UserStatus::INACTIVE);
$enumSet = $enumSet->with(UserStatus::DELETED());

// remove enumerators (by value or by instance)
$enumSet->withoutIterable([UserStatus::INACTIVE, UserStatus::DELETED()]);
// or
$enumSet = $enumSet->without(UserStatus::INACTIVE);
$enumSet = $enumSet->without(UserStatus::DELETED());


// Test if an enumerator exists (by value or by instance)
$enumSet->has(UserStatus::INACTIVE); // bool


// count the number of enumerators
$enumSet->count();
count($enumSet);

// test for elements
$enumSet->isEmpty();

// convert to array
$enumSet->getValues();      // List of enumerator values
$enumSet->getEnumerators(); // List of enumerator instances
$enumSet->getNames();       // List of enumerator names
$enumSet->getOrdinals();    // List of ordinal numbers


// iterating over the set
foreach ($enumSet as $ordinal => $enum) {
    gettype($ordinal);  // int (the ordinal number of the enumerator)
    get_class($enum);   // UserStatus (enumerator object)
}


// compare two EnumSets
$enumSet->isEqual($other);    // Check if the EnumSet is the same as other
$enumSet->isSubset($other);   // Check if the EnumSet is a subset of other
$enumSet->isSuperset($other); // Check if the EnumSet is a superset of other


// union, intersect, difference and symmetric difference

// ... the mutable interface will modify the set
$enumSet->setUnion($other);     // Enumerators from both this and other (this | other)
$enumSet->setIntersect($other); // Enumerators common to both this and other (this & other)
$enumSet->setDiff($other);      // Enumerators in this but not in other (this - other)
$enumSet->setSymDiff($other);   // Enumerators in either this and other but not in both (this ^ other)

// ... the immutable interface will produce a new set
$enumSet = $enumSet->withUnion($other);     // Enumerators from both this and other (this | other)
$enumSet = $enumSet->withIntersect($other); // Enumerators common to both this and other (this & other)
$enumSet = $enumSet->withDiff($other);      // Enumerators in this but not in other (this - other)
$enumSet = $enumSet->withSymDiff($other);   // Enumerators in either this and other but not in both (this ^ other)
```


## EnumMap

An `EnumMap` maps enumerators of the same type to data assigned to.

It implements `ArrayAccess`, `Countable` and `IteratorAggregate`
so elements can be accessed, iterated and counted like a normal array
using `$enumMap[$key]`, `foreach` and `count()`.

```php
use MabeEnum\EnumMap;

// create a new EnumMap
$enumMap = new EnumMap('UserStatus');


// read and write key-value-pairs like an array
$enumMap[UserStatus::INACTIVE] = 'inaktiv';
$enumMap[UserStatus::ACTIVE]   = 'aktiv';
$enumMap[UserStatus::DELETED]  = 'gelöscht';
$enumMap[UserStatus::INACTIVE]; // 'inaktiv';
$enumMap[UserStatus::ACTIVE];   // 'aktiv';
$enumMap[UserStatus::DELETED];  // 'gelöscht';

isset($enumMap[UserStatus::DELETED]); // true
unset($enumMap[UserStatus::DELETED]);
isset($enumMap[UserStatus::DELETED]); // false

// ... no matter if you use enumerator values or enumerator objects
$enumMap[UserStatus::INACTIVE()] = 'inaktiv';
$enumMap[UserStatus::ACTIVE()]   = 'aktiv';
$enumMap[UserStatus::DELETED()]  = 'gelöscht';
$enumMap[UserStatus::INACTIVE()]; // 'inaktiv';
$enumMap[UserStatus::ACTIVE()];   // 'aktiv';
$enumMap[UserStatus::DELETED()];  // 'gelöscht';

isset($enumMap[UserStatus::DELETED()]); // true
unset($enumMap[UserStatus::DELETED()]);
isset($enumMap[UserStatus::DELETED()]); // false


// count number of attached elements
$enumMap->count();
count($enumMap);

// test for elements
$enumMap->isEmpty();

// support for null aware exists check
$enumMap[UserStatus::NULL] = null;
isset($enumMap[UserStatus::NULL]); // false
$enumMap->has(UserStatus::NULL);   // true


// iterating over the map
foreach ($enumMap as $enum => $value) {
    get_class($enum);  // UserStatus (enumerator object)
    gettype($value);   // mixed (the value the enumerators maps to)
}

// get a list of keys (= a list of enumerator objects)
$enumMap->getKeys();

// get a list of values (= a list of values the enumerator maps to)
$enumMap->getValues();
```


## Serializing

Because this enumeration implementation is based on a singleton pattern and in PHP
it's currently impossible to unserialize a singleton without creating a new instance
this feature isn't supported without any additional work.

As of it's an often requested feature there is a trait that can be added to your
enumeration definition. The trait adds serialization functionallity and injects
the unserialized enumeration instance in case it's the first one.
This reduces singleton behavior breakage but still it beaks if it's not the first
instance and you could result in two different instance of the same enumeration.

**Use it with caution!**

PS: `EnumSet` and `EnumMap` are serializable by default as long as you don't set other non-serializable values.


### Example of using EnumSerializableTrait

```php
use MabeEnum\Enum;
use MabeEnum\EnumSerializableTrait;
use Serializable;

class CardinalDirection extends Enum implements Serializable
{
    use EnumSerializableTrait;

    const NORTH = 'n';
    const EAST  = 'e';
    const WEST  = 'w';
    const SOUTH = 's';
}

$north1 = CardinalDirection::NORTH();
$north2 = unserialize(serialize($north1));

var_dump($north1 === $north2);  // returns FALSE as described above
var_dump($north1->is($north2)); // returns TRUE - this way the two instances are treated equal
var_dump($north2->is($north1)); // returns TRUE - equality works in both directions
```


# Generics and Static Code Analyzer

With version 4.3 we have added support for generics and added better type support.

* `EnumSet<T of Enum>`
* `EnumMap<T of Enum>`

Generic types will be detected by [PHPStan](https://phpstan.org/) and [Psalm](https://psalm.dev/).

Additionally, we have developed an [extension for PHPStan](https://github.com/marc-mabe/php-enum-phpstan/)
to make enumerator accessor methods known.


# Why not `SplEnum`

* `SplEnum` is not built-in into PHP and requires pecl extension installed.
* Instances of the same value of an `SplEnum` are not the same instance.
* No support for `EnumMap` or `EnumSet`.


# Changelog

Changes are documented in the [release page](https://github.com/marc-mabe/php-enum/releases).


# Install

## Composer

Add `marc-mabe/php-enum` to the project's composer.json dependencies and run
`php composer.phar install`

## GIT

`git clone git://github.com/marc-mabe/php-enum.git`

## ZIP / TAR

Download the last version from [Github](https://github.com/marc-mabe/php-enum/tags)
and extract it.


# Versioning and Releases

This project follows [SemVer](https://semver.org/) specification. 

There are **no** [LTS](https://en.wikipedia.org/wiki/Long-term_support) releases
and we don't have (fixed) time based release windows.
Instead releases happen as necessary.

We do support at least all maintained PHP versions.

Bug fixes will be backported to the latest maintained minor release.

Critical bug fixes and security relates fixes can also be backported to older releases.

| Release | Status      | PHP-Version     |
|---------|-------------|-----------------|
| 1.x     | EOL         | \>=5.3          |
| 2.x     | EOL         | \>=5.3 & HHVM<4 |
| 3.x     | EOL         | \>=5.6 & HHVM<4 |
| 4.x     | active      | \>=7.1          |


# New BSD License

The files in this archive are released under the New BSD License.
You can find a copy of this license in LICENSE.txt file.
Copyright (c) 2020, Marc Bennewitz
All rights reserved.

Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:

    * Redistributions of source code must retain the above copyright notice,
      this list of conditions and the following disclaimer.
    
    * Redistributions in binary form must reproduce the above copyright notice,
      this list of conditions and the following disclaimer in the documentation
      and/or other materials provided with the distribution.
    
    * Neither the name of the organisation nor the names of its contributors
      may be used to endorse or promote products derived from this software
      without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
{
    "name": "marc-mabe\/php-enum",
    "description": "Simple and fast implementation of enumerations with native PHP",
    "type": "library",
    "keywords": [
        "enum",
        "enumeration",
        "enumerator",
        "enumset",
        "enum-set",
        "set",
        "enummap",
        "enum-map",
        "map",
        "type",
        "typehint",
        "type-hint"
    ],
    "homepage": "https:\/\/github.com\/marc-mabe\/php-enum",
    "authors": [
        {
            "name": "Marc Bennewitz",
            "email": "dev@mabe.berlin",
            "homepage": "https:\/\/mabe.berlin\/",
            "role": "Lead"
        }
    ],
    "license": "BSD-3-Clause",
    "require": {
        "php": "^7.1 | ^8.0",
        "ext-reflection": "*"
    },
    "require-dev": {
        "phpbench\/phpbench": "^0.16.10 || ^1.0.4",
        "phpstan\/phpstan": "^1.3.1",
        "phpunit\/phpunit": "^7.5.20 | ^8.5.22 | ^9.5.11",
        "vimeo\/psalm": "^4.17.0 | ^5.26.1"
    },
    "autoload": {
        "psr-4": {
            "_ContaoManager\\MabeEnum\\": "src\/"
        },
        "classmap": [
            "stubs\/Stringable.php"
        ]
    },
    "autoload-dev": {
        "psr-4": {
            "_ContaoManager\\MabeEnumTest\\": "tests\/MabeEnumTest\/",
            "_ContaoManager\\MabeEnumStaticAnalysis\\": "tests\/MabeEnumStaticAnalysis\/",
            "_ContaoManager\\MabeEnumBench\\": "bench\/"
        }
    },
    "extra": {
        "branch-alias": {
            "dev-master": "4.7-dev",
            "dev-3.x": "3.2-dev"
        }
    }
}<?php

declare (strict_types=1);
namespace _ContaoManager\MabeEnum;

use RuntimeException;
use LogicException;
/**
 * Trait to make enumerations serializable
 *
 * This trait is a workaround to make enumerations serializable.
 *
 * Please note that this feature breaks singleton behaviour of your enumerations
 * if an enumeration will be unserialized after it was instantiated already.
 *
 * @copyright 2020, Marc Bennewitz
 * @license http://github.com/marc-mabe/php-enum/blob/master/LICENSE.txt New BSD License
 * @link http://github.com/marc-mabe/php-enum for the canonical source repository
 * @link https://github.com/marc-mabe/php-enum/issues/52 for further information about this feature
 */
trait EnumSerializableTrait
{
    /**
     * The method will be defined by MabeEnum\Enum
     * @return null|bool|int|float|string|array<mixed>
     */
    abstract public function getValue();
    /**
     * Returns an array of data to be serialized.
     * This magic method will be called by serialize() in PHP >= 7.4
     *
     * @return array<string, null|bool|int|float|string|array<mixed>>
     */
    public function __serialize(): array
    {
        return ['value' => $this->getValue()];
    }
    /**
     * Receives an array of data to be unserialized on a new instance without constructor.
     * This magic method will be called in PHP >= 7.4 is the data where serialized with PHP >= 7.4.
     *
     * @throws RuntimeException On missing, unknown or invalid value
     * @throws LogicException   On calling this method on an already initialized enumerator
     *
     * @param array<string, mixed> $data
     * @return void
     */
    public function __unserialize(array $data): void
    {
        if (!\array_key_exists('value', $data)) {
            throw new RuntimeException('Missing array key "value"');
        }
        /** @var mixed $value */
        $value = $data['value'];
        $constants = self::getConstants();
        $name = \array_search($value, $constants, \true);
        if ($name === \false) {
            $message = \is_scalar($value) ? 'Unknown value ' . \var_export($value, \true) : 'Invalid value of type ' . (\is_object($value) ? \get_class($value) : \gettype($value));
            throw new RuntimeException($message);
        }
        $class = static::class;
        $enumerator = $this;
        $closure = function () use ($class, $name, $value, $enumerator) {
            if ($value !== null && $this->value !== null) {
                throw new LogicException('Do not call this directly - please use unserialize($enum) instead');
            }
            $this->value = $value;
            if (!isset(self::$instances[$class][$name])) {
                self::$instances[$class][$name] = $enumerator;
            }
        };
        $closure->bindTo($this, Enum::class)();
    }
    /**
     * Serialize the value of the enumeration
     * This will be called automatically on `serialize()` if the enumeration implements the `Serializable` interface
     *
     * @return string
     * @deprecated Since PHP 7.4
     */
    public function serialize(): string
    {
        return \serialize($this->getValue());
    }
    /**
     * Unserializes a given serialized value and push it into the current instance
     * This will be called automatically on `unserialize()` if the enumeration implements the `Serializable` interface
     * @param string $serialized
     * @return void
     * @throws RuntimeException On an unknown or invalid value
     * @throws LogicException   On calling this method on an already initialized enumerator
     * @deprecated Since PHP 7.4
     */
    public function unserialize($serialized): void
    {
        $this->__unserialize(['value' => \unserialize($serialized)]);
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\MabeEnum;

use ReflectionClass;
use InvalidArgumentException;
use LogicException;
/**
 * Abstract base enumeration class.
 *
 * @copyright 2020, Marc Bennewitz
 * @license http://github.com/marc-mabe/php-enum/blob/master/LICENSE.txt New BSD License
 * @link http://github.com/marc-mabe/php-enum for the canonical source repository
 *
 * @psalm-immutable
 */
abstract class Enum implements \Stringable
{
    /**
     * The selected enumerator value
     *
     * @var null|bool|int|float|string|array<mixed>
     */
    private $value;
    /**
     * The ordinal number of the enumerator
     *
     * @var null|int
     */
    private $ordinal;
    /**
     * A map of enumerator names and values by enumeration class
     *
     * @var array<class-string<Enum>, array<string, null|bool|int|float|string|array<mixed>>>
     */
    private static $constants = [];
    /**
     * A List of available enumerator names by enumeration class
     *
     * @var array<class-string<Enum>, string[]>
     */
    private static $names = [];
    /**
     * A map of enumerator names and instances by enumeration class
     *
     * @var array<class-string<Enum>, array<string, Enum>>
     */
    private static $instances = [];
    /**
     * Constructor
     *
     * @param null|bool|int|float|string|array<mixed> $value   The value of the enumerator
     * @param int|null                                $ordinal The ordinal number of the enumerator
     */
    final private function __construct($value, $ordinal = null)
    {
        $this->value = $value;
        $this->ordinal = $ordinal;
    }
    /**
     * Get the name of the enumerator
     *
     * @return string
     * @see getName()
     */
    public function __toString(): string
    {
        return $this->getName();
    }
    /**
     * @throws LogicException Enums are not cloneable
     *                        because instances are implemented as singletons
     */
    final public function __clone()
    {
        throw new LogicException('Enums are not cloneable');
    }
    /**
     * @throws LogicException Serialization is not supported by default in this pseudo-enum implementation
     *
     * @psalm-return never-return
     */
    final public function __sleep()
    {
        throw new LogicException('Serialization is not supported by default in this pseudo-enum implementation');
    }
    /**
     * @throws LogicException Serialization is not supported by default in this pseudo-enum implementation
     *
     * @return array<string, mixed>
     */
    public function __serialize(): array
    {
        throw new LogicException('Serialization is not supported by default in this pseudo-enum implementation');
    }
    /**
     * @throws LogicException Serialization is not supported by default in this pseudo-enum implementation
     *
     * @psalm-return never-return
     */
    final public function __wakeup()
    {
        throw new LogicException('Serialization is not supported by default in this pseudo-enum implementation');
    }
    /**
     * @throws LogicException Serialization is not supported by default in this pseudo-enum implementation
     *
     * @param array<string, mixed> $data
     */
    public function __unserialize(array $data): void
    {
        throw new LogicException('Serialization is not supported by default in this pseudo-enum implementation');
    }
    /**
     * Get the value of the enumerator
     *
     * @return null|bool|int|float|string|array<mixed>
     */
    final public function getValue()
    {
        return $this->value;
    }
    /**
     * Get the name of the enumerator
     *
     * @return string
     *
     * @phpstan-return string
     * @psalm-return non-empty-string
     */
    final public function getName()
    {
        return self::$names[static::class][$this->ordinal ?? $this->getOrdinal()];
    }
    /**
     * Get the ordinal number of the enumerator
     *
     * @return int
     */
    final public function getOrdinal()
    {
        if ($this->ordinal === null) {
            $ordinal = 0;
            $value = $this->value;
            $constants = self::$constants[static::class] ?? static::getConstants();
            foreach ($constants as $constValue) {
                if ($value === $constValue) {
                    break;
                }
                ++$ordinal;
            }
            $this->ordinal = $ordinal;
        }
        return $this->ordinal;
    }
    /**
     * Compare this enumerator against another and check if it's the same.
     *
     * @param static|null|bool|int|float|string|array<mixed> $enumerator An enumerator object or value
     * @return bool
     */
    final public function is($enumerator)
    {
        return $this === $enumerator || $this->value === $enumerator || $enumerator instanceof static && \get_class($enumerator) === static::class && $enumerator->value === $this->value;
    }
    /**
     * Get an enumerator instance of the given enumerator value or instance
     *
     * @param static|null|bool|int|float|string|array<mixed> $enumerator An enumerator object or value
     * @return static
     * @throws InvalidArgumentException On an unknown or invalid value
     * @throws LogicException           On ambiguous constant values
     *
     * @psalm-pure
     */
    final public static function get($enumerator)
    {
        if ($enumerator instanceof static) {
            if (\get_class($enumerator) !== static::class) {
                throw new InvalidArgumentException(sprintf('Invalid value of type %s for enumeration %s', \get_class($enumerator), static::class));
            }
            return $enumerator;
        }
        return static::byValue($enumerator);
    }
    /**
     * Get an enumerator instance by the given value
     *
     * @param null|bool|int|float|string|array<mixed> $value Enumerator value
     * @return static
     * @throws InvalidArgumentException On an unknown or invalid value
     * @throws LogicException           On ambiguous constant values
     *
     * @psalm-pure
     */
    final public static function byValue($value)
    {
        /** @var mixed $value */
        $constants = self::$constants[static::class] ?? static::getConstants();
        $name = \array_search($value, $constants, \true);
        if ($name === \false) {
            throw new InvalidArgumentException(sprintf('Unknown value %s for enumeration %s', \is_scalar($value) ? \var_export($value, \true) : 'of type ' . (\is_object($value) ? \get_class($value) : \gettype($value)), static::class));
        }
        /** @var static $instance */
        $instance = self::$instances[static::class][$name] ?? self::$instances[static::class][$name] = new static($constants[$name]);
        return $instance;
    }
    /**
     * Get an enumerator instance by the given name
     *
     * @param string $name The name of the enumerator
     * @return static
     * @throws InvalidArgumentException On an invalid or unknown name
     * @throws LogicException           On ambiguous values
     *
     * @psalm-pure
     */
    final public static function byName(string $name)
    {
        if (isset(self::$instances[static::class][$name])) {
            /** @var static $instance */
            $instance = self::$instances[static::class][$name];
            return $instance;
        }
        $const = static::class . "::{$name}";
        if (!\defined($const)) {
            throw new InvalidArgumentException("{$const} not defined");
        }
        assert(self::noAmbiguousValues(static::getConstants()), 'Ambiguous enumerator values detected for ' . static::class);
        /** @var array<int|string, mixed>|bool|float|int|string|null $value */
        $value = \constant($const);
        return self::$instances[static::class][$name] = new static($value);
    }
    /**
     * Get an enumeration instance by the given ordinal number
     *
     * @param int $ordinal The ordinal number of the enumerator
     * @return static
     * @throws InvalidArgumentException On an invalid ordinal number
     * @throws LogicException           On ambiguous values
     *
     * @psalm-pure
     */
    final public static function byOrdinal(int $ordinal)
    {
        $constants = self::$constants[static::class] ?? static::getConstants();
        if (!isset(self::$names[static::class][$ordinal])) {
            throw new InvalidArgumentException(\sprintf('Invalid ordinal number %s, must between 0 and %s', $ordinal, \count(self::$names[static::class]) - 1));
        }
        $name = self::$names[static::class][$ordinal];
        /** @var static $instance */
        $instance = self::$instances[static::class][$name] ?? self::$instances[static::class][$name] = new static($constants[$name], $ordinal);
        return $instance;
    }
    /**
     * Get a list of enumerator instances ordered by ordinal number
     *
     * @return static[]
     *
     * @phpstan-return array<int, static>
     * @psalm-return list<static>
     * @psalm-pure
     */
    final public static function getEnumerators()
    {
        if (!isset(self::$names[static::class])) {
            static::getConstants();
        }
        /** @var callable $byNameFn */
        $byNameFn = [static::class, 'byName'];
        return \array_map($byNameFn, self::$names[static::class]);
    }
    /**
     * Get a list of enumerator values ordered by ordinal number
     *
     * @return (null|bool|int|float|string|array)[]
     *
     * @phpstan-return array<int, null|bool|int|float|string|array<int|string, mixed>>
     * @psalm-return list<null|bool|int|float|string|array>
     * @psalm-pure
     */
    final public static function getValues()
    {
        return \array_values(self::$constants[static::class] ?? static::getConstants());
    }
    /**
     * Get a list of enumerator names ordered by ordinal number
     *
     * @return string[]
     *
     * @phpstan-return array<int, string>
     * @psalm-return list<non-empty-string>
     * @psalm-pure
     */
    final public static function getNames()
    {
        if (!isset(self::$names[static::class])) {
            static::getConstants();
        }
        return self::$names[static::class];
    }
    /**
     * Get a list of enumerator ordinal numbers
     *
     * @return int[]
     *
     * @phpstan-return array<int, int>
     * @psalm-return list<int>
     * @psalm-pure
     */
    final public static function getOrdinals()
    {
        $count = \count(self::$constants[static::class] ?? static::getConstants());
        return $count ? \range(0, $count - 1) : [];
    }
    /**
     * Get all available constants of the called class
     *
     * @return (null|bool|int|float|string|array)[]
     * @throws LogicException On ambiguous constant values
     *
     * @phpstan-return array<string, null|bool|int|float|string|array<int|string, mixed>>
     * @psalm-return array<non-empty-string, null|bool|int|float|string|array>
     * @psalm-pure
     */
    final public static function getConstants()
    {
        if (isset(self::$constants[static::class])) {
            return self::$constants[static::class];
        }
        $reflection = new ReflectionClass(static::class);
        $constants = [];
        do {
            $scopeConstants = [];
            // Enumerators must be defined as public class constants
            foreach ($reflection->getReflectionConstants() as $reflConstant) {
                if ($reflConstant->isPublic()) {
                    $scopeConstants[$reflConstant->getName()] = $reflConstant->getValue();
                }
            }
            $constants = $scopeConstants + $constants;
        } while (($reflection = $reflection->getParentClass()) && $reflection->name !== __CLASS__);
        /** @var array<string, null|bool|int|float|string|array<mixed>> $constants */
        assert(self::noAmbiguousValues($constants), 'Ambiguous enumerator values detected for ' . static::class);
        self::$names[static::class] = \array_keys($constants);
        return self::$constants[static::class] = $constants;
    }
    /**
     * Test that the given constants does not contain ambiguous values
     * @param array<string, null|bool|int|float|string|array<mixed>> $constants
     * @return bool
     */
    private static function noAmbiguousValues($constants)
    {
        foreach ($constants as $value) {
            $names = \array_keys($constants, $value, \true);
            if (\count($names) > 1) {
                return \false;
            }
        }
        return \true;
    }
    /**
     * Test if the given enumerator is part of this enumeration
     *
     * @param static|null|bool|int|float|string|array<mixed> $enumerator
     * @return bool
     *
     * @psalm-pure
     */
    final public static function has($enumerator)
    {
        if ($enumerator instanceof static) {
            return \get_class($enumerator) === static::class;
        }
        return static::hasValue($enumerator);
    }
    /**
     * Test if the given enumerator value is part of this enumeration
     *
     * @param null|bool|int|float|string|array<mixed> $value
     * @return bool
     *
     * @psalm-pure
     */
    final public static function hasValue($value)
    {
        return \in_array($value, self::$constants[static::class] ?? static::getConstants(), \true);
    }
    /**
     * Test if the given enumerator name is part of this enumeration
     *
     * @param string $name
     * @return bool
     *
     * @psalm-pure
     */
    final public static function hasName(string $name)
    {
        return \defined("static::{$name}");
    }
    /**
     * Get an enumerator instance by the given name.
     *
     * This will be called automatically on calling a method
     * with the same name of a defined enumerator.
     *
     * @param string       $method The name of the enumerator (called as method)
     * @param array<mixed> $args   There should be no arguments
     * @return static
     * @throws InvalidArgumentException On an invalid or unknown name
     * @throws LogicException           On ambiguous constant values
     *
     * @psalm-pure
     */
    final public static function __callStatic(string $method, array $args)
    {
        return static::byName($method);
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\MabeEnum;

use ArrayAccess;
use Countable;
use InvalidArgumentException;
use Iterator;
use IteratorAggregate;
use UnexpectedValueException;
/**
 * A map of enumerators and data values (EnumMap<T of Enum, mixed>).
 *
 * @template T of Enum
 * @implements ArrayAccess<T, mixed>
 * @implements IteratorAggregate<T, mixed>
 *
 * @copyright 2020, Marc Bennewitz
 * @license http://github.com/marc-mabe/php-enum/blob/master/LICENSE.txt New BSD License
 * @link http://github.com/marc-mabe/php-enum for the canonical source repository
 */
class EnumMap implements ArrayAccess, Countable, IteratorAggregate
{
    /**
     * The classname of the enumeration type
     * @var class-string<T>
     */
    private $enumeration;
    /**
     * Internal map of ordinal number and data value
     * @var array<int, mixed>
     */
    private $map = [];
    /**
     * Constructor
     * @param class-string<T> $enumeration The classname of the enumeration type
     * @param null|iterable<T|null|bool|int|float|string|array<mixed>, mixed> $map Initialize map
     * @throws InvalidArgumentException
     */
    public function __construct(string $enumeration, ?iterable $map = null)
    {
        if (!\is_subclass_of($enumeration, Enum::class)) {
            throw new InvalidArgumentException(\sprintf('%s can handle subclasses of %s only', __CLASS__, Enum::class));
        }
        $this->enumeration = $enumeration;
        if ($map) {
            $this->addIterable($map);
        }
    }
    /**
     * Add virtual private property "__pairs" with a list of key-value-pairs
     * to the result of var_dump.
     *
     * This helps debugging as internally the map is using the ordinal number.
     *
     * @return array<string, mixed>
     */
    public function __debugInfo(): array
    {
        $dbg = (array) $this;
        $dbg["\x00" . self::class . "\x00__pairs"] = array_map(function ($k, $v) {
            return [$k, $v];
        }, $this->getKeys(), $this->getValues());
        return $dbg;
    }
    /* write access (mutable) */
    /**
     * Adds the given enumerator (object or value) mapping to the specified data value.
     * @param T|null|bool|int|float|string|array<mixed> $enumerator
     * @param mixed                                                 $value
     * @throws InvalidArgumentException On an invalid given enumerator
     * @see offsetSet()
     */
    public function add($enumerator, $value): void
    {
        $ord = $this->enumeration::get($enumerator)->getOrdinal();
        $this->map[$ord] = $value;
    }
    /**
     * Adds the given iterable, mapping enumerators (objects or values) to data values.
     * @param iterable<T|null|bool|int|float|string|array<mixed>, mixed> $map
     * @throws InvalidArgumentException On an invalid given enumerator
     */
    public function addIterable(iterable $map): void
    {
        $innerMap = $this->map;
        foreach ($map as $enumerator => $value) {
            $ord = $this->enumeration::get($enumerator)->getOrdinal();
            $innerMap[$ord] = $value;
        }
        $this->map = $innerMap;
    }
    /**
     * Removes the given enumerator (object or value) mapping.
     * @param T|null|bool|int|float|string|array<mixed> $enumerator
     * @throws InvalidArgumentException On an invalid given enumerator
     * @see offsetUnset()
     */
    public function remove($enumerator): void
    {
        $ord = $this->enumeration::get($enumerator)->getOrdinal();
        unset($this->map[$ord]);
    }
    /**
     * Removes the given iterable enumerator (object or value) mappings.
     * @param iterable<T|null|bool|int|float|string|array<mixed>> $enumerators
     * @throws InvalidArgumentException On an invalid given enumerator
     */
    public function removeIterable(iterable $enumerators): void
    {
        $map = $this->map;
        foreach ($enumerators as $enumerator) {
            $ord = $this->enumeration::get($enumerator)->getOrdinal();
            unset($map[$ord]);
        }
        $this->map = $map;
    }
    /* write access (immutable) */
    /**
     * Creates a new map with the given enumerator (object or value) mapping to the specified data value added.
     * @param T|null|bool|int|float|string|array<mixed> $enumerator
     * @param mixed                                                 $value
     * @return static
     * @throws InvalidArgumentException On an invalid given enumerator
     */
    public function with($enumerator, $value): self
    {
        $clone = clone $this;
        $clone->add($enumerator, $value);
        return $clone;
    }
    /**
     * Creates a new map with the given iterable mapping enumerators (objects or values) to data values added.
     * @param iterable<T|null|bool|int|float|string|array<mixed>, mixed> $map
     * @return static
     * @throws InvalidArgumentException On an invalid given enumerator
     */
    public function withIterable(iterable $map): self
    {
        $clone = clone $this;
        $clone->addIterable($map);
        return $clone;
    }
    /**
     * Create a new map with the given enumerator mapping removed.
     * @param T|null|bool|int|float|string|array<mixed> $enumerator
     * @return static
     * @throws InvalidArgumentException On an invalid given enumerator
     */
    public function without($enumerator): self
    {
        $clone = clone $this;
        $clone->remove($enumerator);
        return $clone;
    }
    /**
     * Creates a new map with the given iterable enumerator (object or value) mappings removed.
     * @param iterable<T|null|bool|int|float|string|array<mixed>> $enumerators
     * @return static
     * @throws InvalidArgumentException On an invalid given enumerator
     */
    public function withoutIterable(iterable $enumerators): self
    {
        $clone = clone $this;
        $clone->removeIterable($enumerators);
        return $clone;
    }
    /* read access */
    /**
     * Get the classname of the enumeration type.
     * @return class-string<T>
     */
    public function getEnumeration(): string
    {
        return $this->enumeration;
    }
    /**
     * Get the mapped data value of the given enumerator (object or value).
     * @param T|null|bool|int|float|string|array<mixed> $enumerator
     * @return mixed
     * @throws InvalidArgumentException On an invalid given enumerator
     * @throws UnexpectedValueException If the given enumerator does not exist in this map
     * @see offsetGet()
     */
    public function get($enumerator)
    {
        $enumerator = $this->enumeration::get($enumerator);
        $ord = $enumerator->getOrdinal();
        if (!\array_key_exists($ord, $this->map)) {
            throw new UnexpectedValueException(sprintf('Enumerator %s could not be found', \var_export($enumerator->getValue(), \true)));
        }
        return $this->map[$ord];
    }
    /**
     * Get a list of enumerator keys.
     * @return T[]
     *
     * @phpstan-return array<int, T>
     * @psalm-return list<T>
     */
    public function getKeys(): array
    {
        /** @var callable $byOrdinalFn */
        $byOrdinalFn = [$this->enumeration, 'byOrdinal'];
        return \array_map($byOrdinalFn, \array_keys($this->map));
    }
    /**
     * Get a list of mapped data values.
     * @return mixed[]
     *
     * @phpstan-return array<int, mixed>
     * @psalm-return list<mixed>
     */
    public function getValues(): array
    {
        return \array_values($this->map);
    }
    /**
     * Search for the given data value.
     * @param mixed $value
     * @param bool $strict Use strict type comparison
     * @return T|null The enumerator object of the first matching data value or NULL
     */
    public function search($value, bool $strict = \false)
    {
        /** @var false|int $ord */
        $ord = \array_search($value, $this->map, $strict);
        if ($ord !== \false) {
            return $this->enumeration::byOrdinal($ord);
        }
        return null;
    }
    /**
     * Test if the given enumerator key (object or value) exists.
     * @param T|null|bool|int|float|string|array<mixed> $enumerator
     * @return bool
     * @see offsetExists()
     */
    public function has($enumerator): bool
    {
        try {
            $ord = $this->enumeration::get($enumerator)->getOrdinal();
            return \array_key_exists($ord, $this->map);
        } catch (InvalidArgumentException $e) {
            // An invalid enumerator can't be contained in this map
            return \false;
        }
    }
    /**
     * Test if the given enumerator key (object or value) exists.
     * @param T|null|bool|int|float|string|array<mixed> $enumerator
     * @return bool
     * @see offsetExists()
     * @see has()
     * @deprecated Will trigger deprecation warning in last 4.x and removed in 5.x
     */
    public function contains($enumerator): bool
    {
        return $this->has($enumerator);
    }
    /* ArrayAccess */
    /**
     * Test if the given enumerator key (object or value) exists and is not NULL
     * @param T|null|bool|int|float|string|array<mixed> $enumerator
     * @return bool
     * @see contains()
     */
    public function offsetExists($enumerator): bool
    {
        try {
            return isset($this->map[$this->enumeration::get($enumerator)->getOrdinal()]);
        } catch (InvalidArgumentException $e) {
            // An invalid enumerator can't be an offset of this map
            return \false;
        }
    }
    /**
     * Get the mapped data value of the given enumerator (object or value).
     * @param T|null|bool|int|float|string|array<mixed> $enumerator
     * @return mixed The mapped date value of the given enumerator or NULL
     * @throws InvalidArgumentException On an invalid given enumerator
     * @see get()
     */
    #[\ReturnTypeWillChange]
    public function offsetGet($enumerator)
    {
        try {
            return $this->get($enumerator);
        } catch (UnexpectedValueException $e) {
            return null;
        }
    }
    /**
     * Adds the given enumerator (object or value) mapping to the specified data value.
     * @param T|null|bool|int|float|string|array<mixed> $enumerator
     * @param mixed                                     $value
     * @return void
     * @throws InvalidArgumentException On an invalid given enumerator
     * @see add()
     */
    public function offsetSet($enumerator, $value = null): void
    {
        $this->add($enumerator, $value);
    }
    /**
     * Removes the given enumerator (object or value) mapping.
     * @param T|null|bool|int|float|string|array<mixed> $enumerator
     * @return void
     * @throws InvalidArgumentException On an invalid given enumerator
     * @see remove()
     */
    public function offsetUnset($enumerator): void
    {
        $this->remove($enumerator);
    }
    /* IteratorAggregate */
    /**
     * Get a new Iterator.
     *
     * @return Iterator<T, mixed> Iterator<K extends Enum, V>
     */
    public function getIterator(): Iterator
    {
        $map = $this->map;
        foreach ($map as $ordinal => $value) {
            yield $this->enumeration::byOrdinal($ordinal) => $value;
        }
    }
    /* Countable */
    /**
     * Count the number of elements
     *
     * @return int
     */
    public function count(): int
    {
        return \count($this->map);
    }
    /**
     * Tests if the map is empty
     *
     * @return bool
     */
    public function isEmpty(): bool
    {
        return empty($this->map);
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\MabeEnum;

use Countable;
use InvalidArgumentException;
use Iterator;
use IteratorAggregate;
/**
 * A set of enumerators of the given enumeration (EnumSet<T of Enum>)
 * based on an integer or binary bitset depending of given enumeration size.
 *
 * @template T of Enum
 * @implements IteratorAggregate<int, T>
 *
 * @copyright 2020, Marc Bennewitz
 * @license http://github.com/marc-mabe/php-enum/blob/master/LICENSE.txt New BSD License
 * @link http://github.com/marc-mabe/php-enum for the canonical source repository
 */
class EnumSet implements IteratorAggregate, Countable
{
    /**
     * The classname of the Enumeration
     * @var class-string<T>
     */
    private $enumeration;
    /**
     * Number of enumerators defined in the enumeration
     * @var int
     */
    private $enumerationCount;
    /**
     * Integer or binary (little endian) bitset
     * @var int|string
     */
    private $bitset = 0;
    /**
     * Integer or binary (little endian) empty bitset
     *
     * @var int|string
     */
    private $emptyBitset = 0;
    /**#@+
     * Defines private method names to be called depended of how the bitset type was set too.
     * ... Integer or binary bitset.
     * ... *Int or *Bin method
     *
     * @var string
     */
    /** @var string */
    private $fnDoGetIterator = 'doGetIteratorInt';
    /** @var string */
    private $fnDoCount = 'doCountInt';
    /** @var string */
    private $fnDoGetOrdinals = 'doGetOrdinalsInt';
    /** @var string */
    private $fnDoGetBit = 'doGetBitInt';
    /** @var string */
    private $fnDoSetBit = 'doSetBitInt';
    /** @var string */
    private $fnDoUnsetBit = 'doUnsetBitInt';
    /** @var string */
    private $fnDoGetBinaryBitsetLe = 'doGetBinaryBitsetLeInt';
    /** @var string */
    private $fnDoSetBinaryBitsetLe = 'doSetBinaryBitsetLeInt';
    /**#@-*/
    /**
     * Constructor
     *
     * @param class-string<T> $enumeration The classname of the enumeration
     * @param iterable<T|null|bool|int|float|string|array<mixed>>|null $enumerators iterable list of enumerators initializing the set
     * @throws InvalidArgumentException
     */
    public function __construct(string $enumeration, ?iterable $enumerators = null)
    {
        if (!\is_subclass_of($enumeration, Enum::class)) {
            throw new InvalidArgumentException(\sprintf('%s can handle subclasses of %s only', __METHOD__, Enum::class));
        }
        $this->enumeration = $enumeration;
        $this->enumerationCount = \count($enumeration::getConstants());
        // By default the bitset is initialized as integer bitset
        // in case the enumeration has more enumerators then integer bits
        // we will switch this into a binary bitset
        if ($this->enumerationCount > \PHP_INT_SIZE * 8) {
            // init binary bitset with zeros
            $this->bitset = $this->emptyBitset = \str_repeat("\x00", (int) \ceil($this->enumerationCount / 8));
            // switch internal binary bitset functions
            $this->fnDoGetIterator = 'doGetIteratorBin';
            $this->fnDoCount = 'doCountBin';
            $this->fnDoGetOrdinals = 'doGetOrdinalsBin';
            $this->fnDoGetBit = 'doGetBitBin';
            $this->fnDoSetBit = 'doSetBitBin';
            $this->fnDoUnsetBit = 'doUnsetBitBin';
            $this->fnDoGetBinaryBitsetLe = 'doGetBinaryBitsetLeBin';
            $this->fnDoSetBinaryBitsetLe = 'doSetBinaryBitsetLeBin';
        }
        if ($enumerators !== null) {
            foreach ($enumerators as $enumerator) {
                $this->{$this->fnDoSetBit}($enumeration::get($enumerator)->getOrdinal());
            }
        }
    }
    /**
     * Add virtual private property "__enumerators" with a list of enumerator values set
     * to the result of var_dump.
     *
     * This helps debugging as internally the enumerators of this EnumSet gets stored
     * as either integer or binary bit-array.
     *
     * @return array<string, mixed>
     */
    public function __debugInfo()
    {
        $dbg = (array) $this;
        $dbg["\x00" . self::class . "\x00__enumerators"] = $this->getValues();
        return $dbg;
    }
    /**
     * Get the classname of the enumeration
     * @return class-string<T>
     */
    public function getEnumeration(): string
    {
        return $this->enumeration;
    }
    /* write access (mutable) */
    /**
     * Adds an enumerator object or value
     * @param T|null|bool|int|float|string|array<mixed> $enumerator Enumerator object or value
     * @return void
     * @throws InvalidArgumentException On an invalid given enumerator
     */
    public function add($enumerator): void
    {
        $this->{$this->fnDoSetBit}($this->enumeration::get($enumerator)->getOrdinal());
    }
    /**
     * Adds all enumerator objects or values of the given iterable
     * @param iterable<T|null|bool|int|float|string|array<mixed>> $enumerators Iterable list of enumerator objects or values
     * @return void
     * @throws InvalidArgumentException On an invalid given enumerator
     */
    public function addIterable(iterable $enumerators): void
    {
        $bitset = $this->bitset;
        try {
            foreach ($enumerators as $enumerator) {
                $this->{$this->fnDoSetBit}($this->enumeration::get($enumerator)->getOrdinal());
            }
        } catch (\Throwable $e) {
            // reset all changes until error happened
            $this->bitset = $bitset;
            throw $e;
        }
    }
    /**
     * Removes the given enumerator object or value
     * @param T|null|bool|int|float|string|array<mixed> $enumerator Enumerator object or value
     * @return void
     * @throws InvalidArgumentException On an invalid given enumerator
     */
    public function remove($enumerator): void
    {
        $this->{$this->fnDoUnsetBit}($this->enumeration::get($enumerator)->getOrdinal());
    }
    /**
     * Adds an enumerator object or value
     * @param T|null|bool|int|float|string|array<mixed> $enumerator Enumerator object or value
     * @return void
     * @throws InvalidArgumentException On an invalid given enumerator
     * @see add()
     * @see with()
     * @deprecated Will trigger deprecation warning in last 4.x and removed in 5.x
     */
    public function attach($enumerator): void
    {
        $this->add($enumerator);
    }
    /**
     * Removes the given enumerator object or value
     * @param T|null|bool|int|float|string|array<mixed> $enumerator Enumerator object or value
     * @return void
     * @throws InvalidArgumentException On an invalid given enumerator
     * @see remove()
     * @see without()
     * @deprecated Will trigger deprecation warning in last 4.x and removed in 5.x
     */
    public function detach($enumerator): void
    {
        $this->remove($enumerator);
    }
    /**
     * Removes all enumerator objects or values of the given iterable
     * @param iterable<T|null|bool|int|float|string|array<mixed>> $enumerators Iterable list of enumerator objects or values
     * @return void
     * @throws InvalidArgumentException On an invalid given enumerator
     */
    public function removeIterable(iterable $enumerators): void
    {
        $bitset = $this->bitset;
        try {
            foreach ($enumerators as $enumerator) {
                $this->{$this->fnDoUnsetBit}($this->enumeration::get($enumerator)->getOrdinal());
            }
        } catch (\Throwable $e) {
            // reset all changes until error happened
            $this->bitset = $bitset;
            throw $e;
        }
    }
    /**
     * Modify this set from both this and other (this | other)
     *
     * @param EnumSet<T> $other EnumSet of the same enumeration to produce the union
     * @return void
     * @throws InvalidArgumentException If $other doesn't match the enumeration
     */
    public function setUnion(EnumSet $other): void
    {
        if ($this->enumeration !== $other->enumeration) {
            throw new InvalidArgumentException(\sprintf('Other should be of the same enumeration as this %s', $this->enumeration));
        }
        $this->bitset = $this->bitset | $other->bitset;
    }
    /**
     * Modify this set with enumerators common to both this and other (this & other)
     *
     * @param EnumSet<T> $other EnumSet of the same enumeration to produce the intersect
     * @return void
     * @throws InvalidArgumentException If $other doesn't match the enumeration
     */
    public function setIntersect(EnumSet $other): void
    {
        if ($this->enumeration !== $other->enumeration) {
            throw new InvalidArgumentException(\sprintf('Other should be of the same enumeration as this %s', $this->enumeration));
        }
        $this->bitset = $this->bitset & $other->bitset;
    }
    /**
     * Modify this set with enumerators in this but not in other (this - other)
     *
     * @param EnumSet<T> $other EnumSet of the same enumeration to produce the diff
     * @return void
     * @throws InvalidArgumentException If $other doesn't match the enumeration
     */
    public function setDiff(EnumSet $other): void
    {
        if ($this->enumeration !== $other->enumeration) {
            throw new InvalidArgumentException(\sprintf('Other should be of the same enumeration as this %s', $this->enumeration));
        }
        $this->bitset = $this->bitset & ~$other->bitset;
    }
    /**
     * Modify this set with enumerators in either this and other but not in both (this ^ other)
     *
     * @param EnumSet<T> $other EnumSet of the same enumeration to produce the symmetric difference
     * @return void
     * @throws InvalidArgumentException If $other doesn't match the enumeration
     */
    public function setSymDiff(EnumSet $other): void
    {
        if ($this->enumeration !== $other->enumeration) {
            throw new InvalidArgumentException(\sprintf('Other should be of the same enumeration as this %s', $this->enumeration));
        }
        $this->bitset = $this->bitset ^ $other->bitset;
    }
    /**
     * Set the given binary bitset in little-endian order
     *
     * @param string $bitset
     * @return void
     * @throws InvalidArgumentException On out-of-range bits given as input bitset
     * @uses doSetBinaryBitsetLeBin()
     * @uses doSetBinaryBitsetLeInt()
     */
    public function setBinaryBitsetLe(string $bitset): void
    {
        $this->{$this->fnDoSetBinaryBitsetLe}($bitset);
    }
    /**
     * Set binary bitset in little-endian order
     *
     * @param string $bitset
     * @return void
     * @throws InvalidArgumentException On out-of-range bits given as input bitset
     * @see setBinaryBitsetLeBin()
     * @see doSetBinaryBitsetLeInt()
     */
    private function doSetBinaryBitsetLeBin($bitset): void
    {
        /** @var string $thisBitset */
        $thisBitset = $this->bitset;
        $size = \strlen($thisBitset);
        $sizeIn = \strlen($bitset);
        if ($sizeIn < $size) {
            // add "\0" if the given bitset is not long enough
            $bitset .= \str_repeat("\x00", $size - $sizeIn);
        } elseif ($sizeIn > $size) {
            if (\ltrim(\substr($bitset, $size), "\x00") !== '') {
                throw new InvalidArgumentException('out-of-range bits detected');
            }
            $bitset = \substr($bitset, 0, $size);
        }
        // truncate out-of-range bits of last byte
        $lastByteMaxOrd = $this->enumerationCount % 8;
        if ($lastByteMaxOrd !== 0) {
            $lastByte = $bitset[-1];
            $lastByteExpected = \chr((1 << $lastByteMaxOrd) - 1) & $lastByte;
            if ($lastByte !== $lastByteExpected) {
                throw new InvalidArgumentException('out-of-range bits detected');
            }
            $this->bitset = \substr($bitset, 0, -1) . $lastByteExpected;
        }
        $this->bitset = $bitset;
    }
    /**
     * Set binary bitset in little-endian order
     *
     * @param string $bitset
     * @return void
     * @throws InvalidArgumentException On out-of-range bits given as input bitset
     * @see setBinaryBitsetLeBin()
     * @see doSetBinaryBitsetLeBin()
     */
    private function doSetBinaryBitsetLeInt($bitset): void
    {
        $len = \strlen($bitset);
        $int = 0;
        for ($i = 0; $i < $len; ++$i) {
            $ord = \ord($bitset[$i]);
            if ($ord && $i > \PHP_INT_SIZE - 1) {
                throw new InvalidArgumentException('out-of-range bits detected');
            }
            $int |= $ord << 8 * $i;
        }
        if ($int & ~0 << $this->enumerationCount) {
            throw new InvalidArgumentException('out-of-range bits detected');
        }
        $this->bitset = $int;
    }
    /**
     * Set the given binary bitset in big-endian order
     *
     * @param string $bitset
     * @return void
     * @throws InvalidArgumentException On out-of-range bits given as input bitset
     */
    public function setBinaryBitsetBe(string $bitset): void
    {
        $this->{$this->fnDoSetBinaryBitsetLe}(\strrev($bitset));
    }
    /**
     * Set a bit at the given ordinal number
     *
     * @param int $ordinal Ordinal number of bit to set
     * @param bool $bit    The bit to set
     * @return void
     * @throws InvalidArgumentException If the given ordinal number is out-of-range
     * @uses doSetBitBin()
     * @uses doSetBitInt()
     * @uses doUnsetBitBin()
     * @uses doUnsetBitInt()
     */
    public function setBit(int $ordinal, bool $bit): void
    {
        if ($ordinal < 0 || $ordinal > $this->enumerationCount) {
            throw new InvalidArgumentException("Ordinal number must be between 0 and {$this->enumerationCount}");
        }
        if ($bit) {
            $this->{$this->fnDoSetBit}($ordinal);
        } else {
            $this->{$this->fnDoUnsetBit}($ordinal);
        }
    }
    /**
     * Set a bit at the given ordinal number.
     *
     * This is the binary bitset implementation.
     *
     * @param int $ordinal Ordinal number of bit to set
     * @return void
     * @see setBit()
     * @see doSetBitInt()
     */
    private function doSetBitBin($ordinal): void
    {
        /** @var string $thisBitset */
        $thisBitset = $this->bitset;
        $byte = (int) ($ordinal / 8);
        $thisBitset[$byte] = $thisBitset[$byte] | \chr(1 << $ordinal % 8);
        $this->bitset = $thisBitset;
    }
    /**
     * Set a bit at the given ordinal number.
     *
     * This is the binary bitset implementation.
     *
     * @param int $ordinal Ordinal number of bit to set
     * @return void
     * @see setBit()
     * @see doSetBitBin()
     */
    private function doSetBitInt($ordinal): void
    {
        /** @var int $thisBitset */
        $thisBitset = $this->bitset;
        $this->bitset = $thisBitset | 1 << $ordinal;
    }
    /**
     * Unset a bit at the given ordinal number.
     *
     * This is the binary bitset implementation.
     *
     * @param int $ordinal Ordinal number of bit to unset
     * @return void
     * @see setBit()
     * @see doUnsetBitInt()
     */
    private function doUnsetBitBin($ordinal): void
    {
        /** @var string $thisBitset */
        $thisBitset = $this->bitset;
        $byte = (int) ($ordinal / 8);
        $thisBitset[$byte] = $thisBitset[$byte] & \chr(~(1 << $ordinal % 8));
        $this->bitset = $thisBitset;
    }
    /**
     * Unset a bit at the given ordinal number.
     *
     * This is the integer bitset implementation.
     *
     * @param int $ordinal Ordinal number of bit to unset
     * @return void
     * @see setBit()
     * @see doUnsetBitBin()
     */
    private function doUnsetBitInt($ordinal): void
    {
        /** @var int $thisBitset */
        $thisBitset = $this->bitset;
        $this->bitset = $thisBitset & ~(1 << $ordinal);
    }
    /* write access (immutable) */
    /**
     * Creates a new set with the given enumerator object or value added
     * @param T|null|bool|int|float|string|array<mixed> $enumerator Enumerator object or value
     * @return static
     * @throws InvalidArgumentException On an invalid given enumerator
     */
    public function with($enumerator): self
    {
        $clone = clone $this;
        $clone->{$this->fnDoSetBit}($this->enumeration::get($enumerator)->getOrdinal());
        return $clone;
    }
    /**
     * Creates a new set with the given enumeration objects or values added
     * @param iterable<T|null|bool|int|float|string|array<mixed>> $enumerators Iterable list of enumerator objects or values
     * @return static
     * @throws InvalidArgumentException On an invalid given enumerator
     */
    public function withIterable(iterable $enumerators): self
    {
        $clone = clone $this;
        foreach ($enumerators as $enumerator) {
            $clone->{$this->fnDoSetBit}($this->enumeration::get($enumerator)->getOrdinal());
        }
        return $clone;
    }
    /**
     * Create a new set with the given enumerator object or value removed
     * @param T|null|bool|int|float|string|array<mixed> $enumerator Enumerator object or value
     * @return static
     * @throws InvalidArgumentException On an invalid given enumerator
     */
    public function without($enumerator): self
    {
        $clone = clone $this;
        $clone->{$this->fnDoUnsetBit}($this->enumeration::get($enumerator)->getOrdinal());
        return $clone;
    }
    /**
     * Creates a new set with the given enumeration objects or values removed
     * @param iterable<T|null|bool|int|float|string|array<mixed>> $enumerators Iterable list of enumerator objects or values
     * @return static
     * @throws InvalidArgumentException On an invalid given enumerator
     */
    public function withoutIterable(iterable $enumerators): self
    {
        $clone = clone $this;
        foreach ($enumerators as $enumerator) {
            $clone->{$this->fnDoUnsetBit}($this->enumeration::get($enumerator)->getOrdinal());
        }
        return $clone;
    }
    /**
     * Create a new set with enumerators from both this and other (this | other)
     *
     * @param EnumSet<T> $other EnumSet of the same enumeration to produce the union
     * @return static
     * @throws InvalidArgumentException If $other doesn't match the enumeration
     */
    public function withUnion(EnumSet $other): self
    {
        $clone = clone $this;
        $clone->setUnion($other);
        return $clone;
    }
    /**
     * Create a new set with enumerators from both this and other (this | other)
     *
     * @param EnumSet<T> $other EnumSet of the same enumeration to produce the union
     * @return static
     * @throws InvalidArgumentException If $other doesn't match the enumeration
     * @see withUnion()
     * @see setUnion()
     * @deprecated Will trigger deprecation warning in last 4.x and removed in 5.x
     */
    public function union(EnumSet $other): self
    {
        return $this->withUnion($other);
    }
    /**
     * Create a new set with enumerators common to both this and other (this & other)
     *
     * @param EnumSet<T> $other EnumSet of the same enumeration to produce the intersect
     * @return static
     * @throws InvalidArgumentException If $other doesn't match the enumeration
     */
    public function withIntersect(EnumSet $other): self
    {
        $clone = clone $this;
        $clone->setIntersect($other);
        return $clone;
    }
    /**
     * Create a new set with enumerators common to both this and other (this & other)
     *
     * @param EnumSet<T> $other EnumSet of the same enumeration to produce the intersect
     * @return static
     * @throws InvalidArgumentException If $other doesn't match the enumeration
     * @see withIntersect()
     * @see setIntersect()
     * @deprecated Will trigger deprecation warning in last 4.x and removed in 5.x
     */
    public function intersect(EnumSet $other): self
    {
        return $this->withIntersect($other);
    }
    /**
     * Create a new set with enumerators in this but not in other (this - other)
     *
     * @param EnumSet<T> $other EnumSet of the same enumeration to produce the diff
     * @return static
     * @throws InvalidArgumentException If $other doesn't match the enumeration
     */
    public function withDiff(EnumSet $other): self
    {
        $clone = clone $this;
        $clone->setDiff($other);
        return $clone;
    }
    /**
     * Create a new set with enumerators in this but not in other (this - other)
     *
     * @param EnumSet<T> $other EnumSet of the same enumeration to produce the diff
     * @return static
     * @throws InvalidArgumentException If $other doesn't match the enumeration
     * @see withDiff()
     * @see setDiff()
     * @deprecated Will trigger deprecation warning in last 4.x and removed in 5.x
     */
    public function diff(EnumSet $other): self
    {
        return $this->withDiff($other);
    }
    /**
     * Create a new set with enumerators in either this and other but not in both (this ^ other)
     *
     * @param EnumSet<T> $other EnumSet of the same enumeration to produce the symmetric difference
     * @return static
     * @throws InvalidArgumentException If $other doesn't match the enumeration
     */
    public function withSymDiff(EnumSet $other): self
    {
        $clone = clone $this;
        $clone->setSymDiff($other);
        return $clone;
    }
    /**
     * Create a new set with enumerators in either this and other but not in both (this ^ other)
     *
     * @param EnumSet<T> $other EnumSet of the same enumeration to produce the symmetric difference
     * @return static
     * @throws InvalidArgumentException If $other doesn't match the enumeration
     * @see withSymDiff()
     * @see setSymDiff()
     * @deprecated Will trigger deprecation warning in last 4.x and removed in 5.x
     */
    public function symDiff(EnumSet $other): self
    {
        return $this->withSymDiff($other);
    }
    /**
     * Create a new set with the given binary bitset in little-endian order
     *
     * @param string $bitset
     * @return static
     * @throws InvalidArgumentException On out-of-range bits given as input bitset
     * @uses doSetBinaryBitsetLeBin()
     * @uses doSetBinaryBitsetLeInt()
     */
    public function withBinaryBitsetLe(string $bitset): self
    {
        $clone = clone $this;
        $clone->{$this->fnDoSetBinaryBitsetLe}($bitset);
        return $clone;
    }
    /**
     * Create a new set with the given binary bitset in big-endian order
     *
     * @param string $bitset
     * @return static
     * @throws InvalidArgumentException On out-of-range bits given as input bitset
     */
    public function withBinaryBitsetBe(string $bitset): self
    {
        $clone = $this;
        $clone->{$this->fnDoSetBinaryBitsetLe}(\strrev($bitset));
        return $clone;
    }
    /**
     * Create a new set with the bit at the given ordinal number set
     *
     * @param int $ordinal Ordinal number of bit to set
     * @param bool $bit    The bit to set
     * @return static
     * @throws InvalidArgumentException If the given ordinal number is out-of-range
     * @uses doSetBitBin()
     * @uses doSetBitInt()
     * @uses doUnsetBitBin()
     * @uses doUnsetBitInt()
     */
    public function withBit(int $ordinal, bool $bit): self
    {
        $clone = clone $this;
        $clone->setBit($ordinal, $bit);
        return $clone;
    }
    /* read access */
    /**
     * Test if the given enumerator exists
     * @param T|null|bool|int|float|string|array<mixed> $enumerator
     * @return bool
     */
    public function has($enumerator): bool
    {
        return $this->{$this->fnDoGetBit}($this->enumeration::get($enumerator)->getOrdinal());
    }
    /**
     * Test if the given enumerator exists
     * @param T|null|bool|int|float|string|array<mixed> $enumerator
     * @return bool
     * @see has()
     * @deprecated Will trigger deprecation warning in last 4.x and removed in 5.x
     */
    public function contains($enumerator): bool
    {
        return $this->has($enumerator);
    }
    /* IteratorAggregate */
    /**
     * Get a new iterator
     * @return Iterator<int, T>
     * @uses doGetIteratorInt()
     * @uses doGetIteratorBin()
     */
    public function getIterator(): Iterator
    {
        return $this->{$this->fnDoGetIterator}();
    }
    /**
     * Get a new Iterator.
     *
     * This is the binary bitset implementation.
     *
     * @return Iterator<int, T>
     * @see getIterator()
     * @see goGetIteratorInt()
     */
    private function doGetIteratorBin()
    {
        /** @var string $bitset */
        $bitset = $this->bitset;
        $byteLen = \strlen($bitset);
        for ($bytePos = 0; $bytePos < $byteLen; ++$bytePos) {
            if ($bitset[$bytePos] === "\x00") {
                // fast skip null byte
                continue;
            }
            $ord = \ord($bitset[$bytePos]);
            for ($bitPos = 0; $bitPos < 8; ++$bitPos) {
                if ($ord & 1 << $bitPos) {
                    $ordinal = $bytePos * 8 + $bitPos;
                    yield $ordinal => $this->enumeration::byOrdinal($ordinal);
                }
            }
        }
    }
    /**
     * Get a new Iterator.
     *
     * This is the integer bitset implementation.
     *
     * @return Iterator<int, T>
     * @see getIterator()
     * @see doGetIteratorBin()
     */
    private function doGetIteratorInt()
    {
        /** @var int $bitset */
        $bitset = $this->bitset;
        $count = $this->enumerationCount;
        for ($ordinal = 0; $ordinal < $count; ++$ordinal) {
            if ($bitset & 1 << $ordinal) {
                yield $ordinal => $this->enumeration::byOrdinal($ordinal);
            }
        }
    }
    /* Countable */
    /**
     * Count the number of elements
     *
     * @return int
     * @uses doCountBin()
     * @uses doCountInt()
     */
    public function count(): int
    {
        return $this->{$this->fnDoCount}();
    }
    /**
     * Count the number of elements.
     *
     * This is the binary bitset implementation.
     *
     * @return int
     * @see count()
     * @see doCountInt()
     */
    private function doCountBin()
    {
        /** @var string $bitset */
        $bitset = $this->bitset;
        $count = 0;
        $byteLen = \strlen($bitset);
        for ($bytePos = 0; $bytePos < $byteLen; ++$bytePos) {
            if ($bitset[$bytePos] === "\x00") {
                // fast skip null byte
                continue;
            }
            $ord = \ord($bitset[$bytePos]);
            if ($ord & 0b1) {
                ++$count;
            }
            if ($ord & 0b10) {
                ++$count;
            }
            if ($ord & 0b100) {
                ++$count;
            }
            if ($ord & 0b1000) {
                ++$count;
            }
            if ($ord & 0b10000) {
                ++$count;
            }
            if ($ord & 0b100000) {
                ++$count;
            }
            if ($ord & 0b1000000) {
                ++$count;
            }
            if ($ord & 0b10000000) {
                ++$count;
            }
        }
        return $count;
    }
    /**
     * Count the number of elements.
     *
     * This is the integer bitset implementation.
     *
     * @return int
     * @see count()
     * @see doCountBin()
     */
    private function doCountInt()
    {
        /** @var int $bitset */
        $bitset = $this->bitset;
        $count = 0;
        // PHP does not support right shift unsigned
        if ($bitset < 0) {
            $count = 1;
            $bitset = $bitset & \PHP_INT_MAX;
        }
        // iterate byte by byte and count set bits
        $phpIntBitSize = \PHP_INT_SIZE * 8;
        for ($bitPos = 0; $bitPos < $phpIntBitSize; $bitPos += 8) {
            $bitChk = 0xff << $bitPos;
            $byte = $bitset & $bitChk;
            if ($byte) {
                $byte = $byte >> $bitPos;
                if ($byte & 0b1) {
                    ++$count;
                }
                if ($byte & 0b10) {
                    ++$count;
                }
                if ($byte & 0b100) {
                    ++$count;
                }
                if ($byte & 0b1000) {
                    ++$count;
                }
                if ($byte & 0b10000) {
                    ++$count;
                }
                if ($byte & 0b100000) {
                    ++$count;
                }
                if ($byte & 0b1000000) {
                    ++$count;
                }
                if ($byte & 0b10000000) {
                    ++$count;
                }
            }
            if ($bitset <= $bitChk) {
                break;
            }
        }
        return $count;
    }
    /**
     * Check if this EnumSet is the same as other
     * @param EnumSet<T> $other
     * @return bool
     */
    public function isEqual(EnumSet $other): bool
    {
        return $this->enumeration === $other->enumeration && $this->bitset === $other->bitset;
    }
    /**
     * Check if this EnumSet is a subset of other
     * @param EnumSet<T> $other
     * @return bool
     */
    public function isSubset(EnumSet $other): bool
    {
        return $this->enumeration === $other->enumeration && ($this->bitset & $other->bitset) === $this->bitset;
    }
    /**
     * Check if this EnumSet is a superset of other
     * @param EnumSet<T> $other
     * @return bool
     */
    public function isSuperset(EnumSet $other): bool
    {
        return $this->enumeration === $other->enumeration && ($this->bitset | $other->bitset) === $this->bitset;
    }
    /**
     * Tests if the set is empty
     *
     * @return bool
     */
    public function isEmpty(): bool
    {
        return $this->bitset === $this->emptyBitset;
    }
    /**
     * Get ordinal numbers of the defined enumerators as array
     * @return array<int, int>
     * @uses  doGetOrdinalsBin()
     * @uses  doGetOrdinalsInt()
     */
    public function getOrdinals(): array
    {
        return $this->{$this->fnDoGetOrdinals}();
    }
    /**
     * Get ordinal numbers of the defined enumerators as array.
     *
     * This is the binary bitset implementation.
     *
     * @return array<int, int>
     * @see getOrdinals()
     * @see goGetOrdinalsInt()
     */
    private function doGetOrdinalsBin()
    {
        /** @var string $bitset */
        $bitset = $this->bitset;
        $ordinals = [];
        $byteLen = \strlen($bitset);
        for ($bytePos = 0; $bytePos < $byteLen; ++$bytePos) {
            if ($bitset[$bytePos] === "\x00") {
                // fast skip null byte
                continue;
            }
            $ord = \ord($bitset[$bytePos]);
            for ($bitPos = 0; $bitPos < 8; ++$bitPos) {
                if ($ord & 1 << $bitPos) {
                    $ordinals[] = $bytePos * 8 + $bitPos;
                }
            }
        }
        return $ordinals;
    }
    /**
     * Get ordinal numbers of the defined enumerators as array.
     *
     * This is the integer bitset implementation.
     *
     * @return array<int, int>
     * @see getOrdinals()
     * @see doGetOrdinalsBin()
     */
    private function doGetOrdinalsInt()
    {
        /** @var int $bitset */
        $bitset = $this->bitset;
        $ordinals = [];
        $count = $this->enumerationCount;
        for ($ordinal = 0; $ordinal < $count; ++$ordinal) {
            if ($bitset & 1 << $ordinal) {
                $ordinals[] = $ordinal;
            }
        }
        return $ordinals;
    }
    /**
     * Get values of the defined enumerators as array
     * @return (null|bool|int|float|string|array)[]
     *
     * @phpstan-return array<int, null|bool|int|float|string|array<mixed>>
     * @psalm-return list<null|bool|int|float|string|array>
     */
    public function getValues(): array
    {
        $enumeration = $this->enumeration;
        $values = [];
        foreach ($this->getOrdinals() as $ord) {
            $values[] = $enumeration::byOrdinal($ord)->getValue();
        }
        return $values;
    }
    /**
     * Get names of the defined enumerators as array
     * @return string[]
     *
     * @phpstan-return array<int, string>
     * @psalm-return list<string>
     */
    public function getNames(): array
    {
        $enumeration = $this->enumeration;
        $names = [];
        foreach ($this->getOrdinals() as $ord) {
            $names[] = $enumeration::byOrdinal($ord)->getName();
        }
        return $names;
    }
    /**
     * Get the defined enumerators as array
     * @return Enum[]
     *
     * @phpstan-return array<int, T>
     * @psalm-return list<T>
     */
    public function getEnumerators(): array
    {
        $enumeration = $this->enumeration;
        $enumerators = [];
        foreach ($this->getOrdinals() as $ord) {
            $enumerators[] = $enumeration::byOrdinal($ord);
        }
        return $enumerators;
    }
    /**
     * Get binary bitset in little-endian order
     *
     * @return string
     * @uses doGetBinaryBitsetLeBin()
     * @uses doGetBinaryBitsetLeInt()
     */
    public function getBinaryBitsetLe(): string
    {
        return $this->{$this->fnDoGetBinaryBitsetLe}();
    }
    /**
     * Get binary bitset in little-endian order.
     *
     * This is the binary bitset implementation.
     *
     * @return string
     * @see getBinaryBitsetLe()
     * @see doGetBinaryBitsetLeInt()
     */
    private function doGetBinaryBitsetLeBin()
    {
        /** @var string $bitset */
        $bitset = $this->bitset;
        return $bitset;
    }
    /**
     * Get binary bitset in little-endian order.
     *
     * This is the integer bitset implementation.
     *
     * @return string
     * @see getBinaryBitsetLe()
     * @see doGetBinaryBitsetLeBin()
     */
    private function doGetBinaryBitsetLeInt()
    {
        $bin = \pack(\PHP_INT_SIZE === 8 ? 'P' : 'V', $this->bitset);
        return \substr($bin, 0, (int) \ceil($this->enumerationCount / 8));
    }
    /**
     * Get binary bitset in big-endian order
     *
     * @return string
     */
    public function getBinaryBitsetBe(): string
    {
        return \strrev($this->getBinaryBitsetLe());
    }
    /**
     * Get a bit at the given ordinal number
     *
     * @param int $ordinal Ordinal number of bit to get
     * @return bool
     * @throws InvalidArgumentException If the given ordinal number is out-of-range
     * @uses doGetBitBin()
     * @uses doGetBitInt()
     */
    public function getBit(int $ordinal): bool
    {
        if ($ordinal < 0 || $ordinal > $this->enumerationCount) {
            throw new InvalidArgumentException("Ordinal number must be between 0 and {$this->enumerationCount}");
        }
        return $this->{$this->fnDoGetBit}($ordinal);
    }
    /**
     * Get a bit at the given ordinal number.
     *
     * This is the binary bitset implementation.
     *
     * @param int $ordinal Ordinal number of bit to get
     * @return bool
     * @see getBit()
     * @see doGetBitInt()
     */
    private function doGetBitBin($ordinal)
    {
        /** @var string $bitset */
        $bitset = $this->bitset;
        return (\ord($bitset[(int) ($ordinal / 8)]) & 1 << $ordinal % 8) !== 0;
    }
    /**
     * Get a bit at the given ordinal number.
     *
     * This is the integer bitset implementation.
     *
     * @param int $ordinal Ordinal number of bit to get
     * @return bool
     * @see getBit()
     * @see doGetBitBin()
     */
    private function doGetBitInt($ordinal)
    {
        /** @var int $bitset */
        $bitset = $this->bitset;
        return (bool) ($bitset & 1 << $ordinal);
    }
}
MIT License

Copyright (c) 2018-2022 Spomky-Labs

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
{
    "name": "web-auth\/webauthn-lib",
    "type": "library",
    "license": "MIT",
    "description": "FIDO2\/Webauthn Support For PHP",
    "keywords": [
        "FIDO",
        "FIDO2",
        "webauthn"
    ],
    "homepage": "https:\/\/github.com\/web-auth",
    "authors": [
        {
            "name": "Florent Morselli",
            "homepage": "https:\/\/github.com\/Spomky"
        },
        {
            "name": "All contributors",
            "homepage": "https:\/\/github.com\/web-auth\/webauthn-library\/contributors"
        }
    ],
    "require": {
        "php": ">=8.1",
        "ext-json": "*",
        "ext-openssl": "*",
        "ext-mbstring": "*",
        "lcobucci\/clock": "^2.2|^3.0",
        "paragonie\/constant_time_encoding": "^2.6|^3.0",
        "psr\/clock": "^1.0",
        "psr\/event-dispatcher": "^1.0",
        "psr\/http-client": "^1.0",
        "psr\/http-factory": "^1.0",
        "psr\/log": "^1.0|^2.0|^3.0",
        "spomky-labs\/cbor-php": "^3.0",
        "spomky-labs\/pki-framework": "^1.0",
        "symfony\/uid": "^6.1|^7.0",
        "symfony\/deprecation-contracts": "^3.2",
        "web-auth\/cose-lib": "^4.2.3"
    },
    "autoload": {
        "psr-4": {
            "_ContaoManager\\Webauthn\\": "src\/"
        }
    },
    "extra": {
        "thanks": {
            "name": "web-auth\/webauthn-framework",
            "url": "https:\/\/github.com\/web-auth\/webauthn-framework"
        }
    },
    "suggest": {
        "symfony\/serializer": "As of 4.5.x, the symfony\/serializer component will become mandatory for converting objects such as the Metadata Statement",
        "symfony\/property-access": "As of 4.5.x, the symfony\/serializer component will become mandatory for converting objects such as the Metadata Statement",
        "symfony\/property-info": "As of 4.5.x, the symfony\/serializer component will become mandatory for converting objects such as the Metadata Statement",
        "phpdocumentor\/reflection-docblock": "As of 4.5.x, the phpdocumentor\/reflection-docblock component will become mandatory for converting objects such as the Metadata Statement",
        "psr\/log-implementation": "Recommended to receive logs from the library",
        "symfony\/event-dispatcher": "Recommended to use dispatched events",
        "psr\/clock-implementation": "As of 4.5.x, the PSR Clock implementation will replace lcobucci\/clock",
        "web-token\/jwt-library": "Mandatory for fetching Metadata Statement from distant sources"
    }
}<?php

declare (strict_types=1);
namespace _ContaoManager\Webauthn;

use _ContaoManager\Symfony\Component\HttpFoundation\Request;
interface FakeCredentialGenerator
{
    /**
     * @return PublicKeyCredentialDescriptor[]
     */
    public function generate(Request $request, string $username): array;
}
<?php

declare (strict_types=1);
namespace _ContaoManager\Webauthn;

use _ContaoManager\CBOR\Stream;
use _ContaoManager\Webauthn\Exception\InvalidDataException;
use function fclose;
use function fopen;
use function fread;
use function fwrite;
use function rewind;
use function sprintf;
final class StringStream implements Stream
{
    /**
     * @var resource
     */
    private $data;
    private readonly int $length;
    private int $totalRead = 0;
    public function __construct(string $data)
    {
        $this->length = mb_strlen($data, '8bit');
        $resource = fopen('php://memory', 'rb+');
        fwrite($resource, $data);
        rewind($resource);
        $this->data = $resource;
    }
    public function read(int $length): string
    {
        if ($length <= 0) {
            return '';
        }
        $read = fread($this->data, $length);
        $bytesRead = mb_strlen($read, '8bit');
        mb_strlen($read, '8bit') === $length || throw InvalidDataException::create(null, sprintf('Out of range. Expected: %d, read: %d.', $length, $bytesRead));
        $this->totalRead += $bytesRead;
        return $read;
    }
    public function close(): void
    {
        fclose($this->data);
    }
    public function isEOF(): bool
    {
        return $this->totalRead === $this->length;
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\Webauthn\CeremonyStep;

use _ContaoManager\CBOR\Decoder;
use _ContaoManager\CBOR\Normalizable;
use _ContaoManager\Cose\Algorithms;
use _ContaoManager\Cose\Key\Key;
use _ContaoManager\Webauthn\AuthenticatorAssertionResponse;
use _ContaoManager\Webauthn\AuthenticatorAttestationResponse;
use _ContaoManager\Webauthn\Exception\AuthenticatorResponseVerificationException;
use _ContaoManager\Webauthn\PublicKeyCredentialCreationOptions;
use _ContaoManager\Webauthn\PublicKeyCredentialRequestOptions;
use _ContaoManager\Webauthn\PublicKeyCredentialSource;
use _ContaoManager\Webauthn\StringStream;
use _ContaoManager\Webauthn\U2FPublicKey;
use function count;
use function in_array;
use function is_array;
use function sprintf;
class CheckAlgorithm implements CeremonyStep
{
    public function process(PublicKeyCredentialSource $publicKeyCredentialSource, AuthenticatorAssertionResponse|AuthenticatorAttestationResponse $authenticatorResponse, PublicKeyCredentialRequestOptions|PublicKeyCredentialCreationOptions $publicKeyCredentialOptions, ?string $userHandle, string $host): void
    {
        if (!$publicKeyCredentialOptions instanceof PublicKeyCredentialCreationOptions) {
            return;
        }
        $credentialPublicKey = $publicKeyCredentialSource->getAttestedCredentialData()->credentialPublicKey;
        $credentialPublicKey !== null || throw AuthenticatorResponseVerificationException::create('No public key available.');
        $algorithms = array_map(fn($pubKeyCredParam) => $pubKeyCredParam->alg, $publicKeyCredentialOptions->pubKeyCredParams);
        if (count($algorithms) === 0) {
            $algorithms = [Algorithms::COSE_ALGORITHM_ES256, Algorithms::COSE_ALGORITHM_RS256];
        }
        $coseKey = $this->getCoseKey($credentialPublicKey);
        in_array($coseKey->alg(), $algorithms, \true) || throw AuthenticatorResponseVerificationException::create(sprintf('Invalid algorithm. Expected one of %s but got %d', implode(', ', $algorithms), $coseKey->alg()));
    }
    private function getCoseKey(string $credentialPublicKey): Key
    {
        $isU2F = U2FPublicKey::isU2FKey($credentialPublicKey);
        if ($isU2F === \true) {
            $credentialPublicKey = U2FPublicKey::convertToCoseKey($credentialPublicKey);
        }
        $stream = new StringStream($credentialPublicKey);
        $credentialPublicKeyStream = Decoder::create()->decode($stream);
        $stream->isEOF() || throw AuthenticatorResponseVerificationException::create('Invalid key. Presence of extra bytes.');
        $stream->close();
        $credentialPublicKeyStream instanceof Normalizable || throw AuthenticatorResponseVerificationException::create('Invalid attestation object. Unexpected object.');
        $normalizedData = $credentialPublicKeyStream->normalize();
        is_array($normalizedData) || throw AuthenticatorResponseVerificationException::create('Invalid attestation object. Unexpected object.');
        /** @var array<int|string, mixed> $normalizedData */
        return Key::create($normalizedData);
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\Webauthn\CeremonyStep;

interface TopOriginValidator
{
    public function validate(string $topOrigin): void;
}
<?php

declare (strict_types=1);
namespace _ContaoManager\Webauthn\CeremonyStep;

use _ContaoManager\Webauthn\AuthenticatorAssertionResponse;
use _ContaoManager\Webauthn\AuthenticatorAttestationResponse;
use _ContaoManager\Webauthn\Exception\InvalidUserHandleException;
use _ContaoManager\Webauthn\PublicKeyCredentialCreationOptions;
use _ContaoManager\Webauthn\PublicKeyCredentialRequestOptions;
use _ContaoManager\Webauthn\PublicKeyCredentialSource;
final class CheckUserHandle implements CeremonyStep
{
    public function process(PublicKeyCredentialSource $publicKeyCredentialSource, AuthenticatorAssertionResponse|AuthenticatorAttestationResponse $authenticatorResponse, PublicKeyCredentialRequestOptions|PublicKeyCredentialCreationOptions $publicKeyCredentialOptions, ?string $userHandle, string $host): void
    {
        if (!$authenticatorResponse instanceof AuthenticatorAssertionResponse) {
            return;
        }
        $credentialUserHandle = $publicKeyCredentialSource->userHandle;
        $responseUserHandle = $authenticatorResponse->userHandle;
        if ($userHandle !== null) {
            //If the user was identified before the authentication ceremony was initiated,
            $credentialUserHandle === $userHandle || throw InvalidUserHandleException::create();
            if ($responseUserHandle !== null && $responseUserHandle !== '') {
                $credentialUserHandle === $responseUserHandle || throw InvalidUserHandleException::create();
            }
        } else {
            $responseUserHandle !== '' && $credentialUserHandle === $responseUserHandle || throw InvalidUserHandleException::create();
        }
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\Webauthn\CeremonyStep;

use _ContaoManager\Webauthn\AuthenticatorAssertionResponse;
use _ContaoManager\Webauthn\AuthenticatorAttestationResponse;
use _ContaoManager\Webauthn\Exception\AuthenticatorResponseVerificationException;
use _ContaoManager\Webauthn\PublicKeyCredentialCreationOptions;
use _ContaoManager\Webauthn\PublicKeyCredentialRequestOptions;
use _ContaoManager\Webauthn\PublicKeyCredentialSource;
final class CheckHasAttestedCredentialData implements CeremonyStep
{
    public function process(PublicKeyCredentialSource $publicKeyCredentialSource, AuthenticatorAssertionResponse|AuthenticatorAttestationResponse $authenticatorResponse, PublicKeyCredentialRequestOptions|PublicKeyCredentialCreationOptions $publicKeyCredentialOptions, ?string $userHandle, string $host): void
    {
        $authData = $authenticatorResponse instanceof AuthenticatorAssertionResponse ? $authenticatorResponse->authenticatorData : $authenticatorResponse->attestationObject->authData;
        $authData->hasAttestedCredentialData() || throw AuthenticatorResponseVerificationException::create('There is no attested credential data.');
        $authData->attestedCredentialData !== null || throw AuthenticatorResponseVerificationException::create('There is no attested credential data.');
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\Webauthn\CeremonyStep;

use _ContaoManager\Webauthn\AuthenticatorAssertionResponse;
use _ContaoManager\Webauthn\AuthenticatorAttestationResponse;
use _ContaoManager\Webauthn\PublicKeyCredentialCreationOptions;
use _ContaoManager\Webauthn\PublicKeyCredentialRequestOptions;
use _ContaoManager\Webauthn\PublicKeyCredentialSource;
final class CeremonyStepManager
{
    /**
     * @param CeremonyStep[] $steps
     */
    public function __construct(private readonly array $steps)
    {
    }
    public function process(PublicKeyCredentialSource $publicKeyCredentialSource, AuthenticatorAssertionResponse|AuthenticatorAttestationResponse $authenticatorResponse, PublicKeyCredentialRequestOptions|PublicKeyCredentialCreationOptions $publicKeyCredentialOptions, ?string $userHandle, string $host): void
    {
        foreach ($this->steps as $step) {
            $step->process($publicKeyCredentialSource, $authenticatorResponse, $publicKeyCredentialOptions, $userHandle, $host);
        }
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\Webauthn\CeremonyStep;

use _ContaoManager\Webauthn\AuthenticatorAssertionResponse;
use _ContaoManager\Webauthn\AuthenticatorAttestationResponse;
use _ContaoManager\Webauthn\AuthenticatorSelectionCriteria;
use _ContaoManager\Webauthn\Exception\AuthenticatorResponseVerificationException;
use _ContaoManager\Webauthn\PublicKeyCredentialCreationOptions;
use _ContaoManager\Webauthn\PublicKeyCredentialRequestOptions;
use _ContaoManager\Webauthn\PublicKeyCredentialSource;
final class CheckUserVerification implements CeremonyStep
{
    public function process(PublicKeyCredentialSource $publicKeyCredentialSource, AuthenticatorAssertionResponse|AuthenticatorAttestationResponse $authenticatorResponse, PublicKeyCredentialRequestOptions|PublicKeyCredentialCreationOptions $publicKeyCredentialOptions, ?string $userHandle, string $host): void
    {
        $userVerification = $publicKeyCredentialOptions instanceof PublicKeyCredentialRequestOptions ? $publicKeyCredentialOptions->userVerification : $publicKeyCredentialOptions->authenticatorSelection?->userVerification;
        if ($userVerification !== AuthenticatorSelectionCriteria::USER_VERIFICATION_REQUIREMENT_REQUIRED) {
            return;
        }
        $authData = $authenticatorResponse instanceof AuthenticatorAssertionResponse ? $authenticatorResponse->authenticatorData : $authenticatorResponse->attestationObject->authData;
        $authData->isUserVerified() || throw AuthenticatorResponseVerificationException::create('User authentication required.');
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\Webauthn\CeremonyStep;

use _ContaoManager\Webauthn\AuthenticatorAssertionResponse;
use _ContaoManager\Webauthn\AuthenticatorAttestationResponse;
use _ContaoManager\Webauthn\Exception\AuthenticatorResponseVerificationException;
use _ContaoManager\Webauthn\PublicKeyCredentialCreationOptions;
use _ContaoManager\Webauthn\PublicKeyCredentialRequestOptions;
use _ContaoManager\Webauthn\PublicKeyCredentialSource;
use function count;
final class CheckAllowedCredentialList implements CeremonyStep
{
    public function process(PublicKeyCredentialSource $publicKeyCredentialSource, AuthenticatorAssertionResponse|AuthenticatorAttestationResponse $authenticatorResponse, PublicKeyCredentialRequestOptions|PublicKeyCredentialCreationOptions $publicKeyCredentialOptions, ?string $userHandle, string $host): void
    {
        if (!$publicKeyCredentialOptions instanceof PublicKeyCredentialRequestOptions) {
            return;
        }
        if (count($publicKeyCredentialOptions->allowCredentials) === 0) {
            return;
        }
        foreach ($publicKeyCredentialOptions->allowCredentials as $allowedCredential) {
            if (hash_equals($allowedCredential->id, $publicKeyCredentialSource->publicKeyCredentialId)) {
                return;
            }
        }
        throw AuthenticatorResponseVerificationException::create('The credential ID is not allowed.');
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\Webauthn\CeremonyStep;

use _ContaoManager\Webauthn\AuthenticatorAssertionResponse;
use _ContaoManager\Webauthn\AuthenticatorAttestationResponse;
use _ContaoManager\Webauthn\Exception\AuthenticatorResponseVerificationException;
use _ContaoManager\Webauthn\PublicKeyCredentialCreationOptions;
use _ContaoManager\Webauthn\PublicKeyCredentialRequestOptions;
use _ContaoManager\Webauthn\PublicKeyCredentialSource;
class CheckCredentialId implements CeremonyStep
{
    public function process(PublicKeyCredentialSource $publicKeyCredentialSource, AuthenticatorAssertionResponse|AuthenticatorAttestationResponse $authenticatorResponse, PublicKeyCredentialRequestOptions|PublicKeyCredentialCreationOptions $publicKeyCredentialOptions, ?string $userHandle, string $host): void
    {
        $credentialId = $publicKeyCredentialSource->publicKeyCredentialId;
        mb_strlen($credentialId) <= 1023 || throw new AuthenticatorResponseVerificationException('Credential ID too long.');
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\Webauthn\CeremonyStep;

use _ContaoManager\Webauthn\AttestationStatement\AttestationStatementSupportManager;
use _ContaoManager\Webauthn\AuthenticatorAssertionResponse;
use _ContaoManager\Webauthn\AuthenticatorAttestationResponse;
use _ContaoManager\Webauthn\Exception\AuthenticatorResponseVerificationException;
use _ContaoManager\Webauthn\PublicKeyCredentialCreationOptions;
use _ContaoManager\Webauthn\PublicKeyCredentialRequestOptions;
use _ContaoManager\Webauthn\PublicKeyCredentialSource;
final class CheckAttestationFormatIsKnownAndValid implements CeremonyStep
{
    public function __construct(private readonly AttestationStatementSupportManager $attestationStatementSupportManager)
    {
    }
    public function process(PublicKeyCredentialSource $publicKeyCredentialSource, AuthenticatorAssertionResponse|AuthenticatorAttestationResponse $authenticatorResponse, PublicKeyCredentialRequestOptions|PublicKeyCredentialCreationOptions $publicKeyCredentialOptions, ?string $userHandle, string $host): void
    {
        $attestationObject = $authenticatorResponse->attestationObject;
        if ($attestationObject === null) {
            return;
        }
        $fmt = $attestationObject->attStmt->fmt;
        $this->attestationStatementSupportManager->has($fmt) || throw AuthenticatorResponseVerificationException::create('Unsupported attestation statement format.');
        $attestationStatementSupport = $this->attestationStatementSupportManager->get($fmt);
        $clientDataJSONHash = hash('sha256', $authenticatorResponse->clientDataJSON->rawData, \true);
        $attestationStatementSupport->isValid($clientDataJSONHash, $attestationObject->attStmt, $attestationObject->authData) || throw AuthenticatorResponseVerificationException::create('Invalid attestation statement.');
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\Webauthn\CeremonyStep;

use _ContaoManager\CBOR\Decoder;
use _ContaoManager\CBOR\Normalizable;
use _ContaoManager\Cose\Algorithm\Manager;
use _ContaoManager\Cose\Algorithm\Signature\ECDSA\ES256;
use _ContaoManager\Cose\Algorithm\Signature\RSA\RS256;
use _ContaoManager\Cose\Algorithm\Signature\Signature;
use _ContaoManager\Cose\Key\Key;
use _ContaoManager\Webauthn\AuthenticatorAssertionResponse;
use _ContaoManager\Webauthn\AuthenticatorAttestationResponse;
use _ContaoManager\Webauthn\Exception\AuthenticatorResponseVerificationException;
use _ContaoManager\Webauthn\PublicKeyCredentialCreationOptions;
use _ContaoManager\Webauthn\PublicKeyCredentialRequestOptions;
use _ContaoManager\Webauthn\PublicKeyCredentialSource;
use _ContaoManager\Webauthn\StringStream;
use _ContaoManager\Webauthn\U2FPublicKey;
use _ContaoManager\Webauthn\Util\CoseSignatureFixer;
use function is_array;
final class CheckSignature implements CeremonyStep
{
    private readonly Manager $algorithmManager;
    public function __construct(null|Manager $algorithmManager = null)
    {
        $this->algorithmManager = $algorithmManager ?? Manager::create()->add(ES256::create(), RS256::create());
    }
    public function process(PublicKeyCredentialSource $publicKeyCredentialSource, AuthenticatorAssertionResponse|AuthenticatorAttestationResponse $authenticatorResponse, PublicKeyCredentialRequestOptions|PublicKeyCredentialCreationOptions $publicKeyCredentialOptions, ?string $userHandle, string $host): void
    {
        if (!$authenticatorResponse instanceof AuthenticatorAssertionResponse) {
            return;
        }
        $credentialPublicKey = $publicKeyCredentialSource->getAttestedCredentialData()->credentialPublicKey;
        $credentialPublicKey !== null || throw AuthenticatorResponseVerificationException::create('No public key available.');
        $coseKey = $this->getCoseKey($credentialPublicKey);
        $getClientDataJSONHash = hash('sha256', $authenticatorResponse->clientDataJSON->rawData, \true);
        $dataToVerify = $authenticatorResponse->authenticatorData->authData . $getClientDataJSONHash;
        $signature = $authenticatorResponse->signature;
        $algorithm = $this->algorithmManager->get($coseKey->alg());
        $algorithm instanceof Signature || throw AuthenticatorResponseVerificationException::create('Invalid algorithm identifier. Should refer to a signature algorithm');
        $signature = CoseSignatureFixer::fix($signature, $algorithm);
        $algorithm->verify($dataToVerify, $coseKey, $signature) || throw AuthenticatorResponseVerificationException::create('Invalid signature.');
    }
    private function getCoseKey(string $credentialPublicKey): Key
    {
        $isU2F = U2FPublicKey::isU2FKey($credentialPublicKey);
        if ($isU2F === \true) {
            $credentialPublicKey = U2FPublicKey::convertToCoseKey($credentialPublicKey);
        }
        $stream = new StringStream($credentialPublicKey);
        $credentialPublicKeyStream = Decoder::create()->decode($stream);
        $stream->isEOF() || throw AuthenticatorResponseVerificationException::create('Invalid key. Presence of extra bytes.');
        $stream->close();
        $credentialPublicKeyStream instanceof Normalizable || throw AuthenticatorResponseVerificationException::create('Invalid attestation object. Unexpected object.');
        $normalizedData = $credentialPublicKeyStream->normalize();
        is_array($normalizedData) || throw AuthenticatorResponseVerificationException::create('Invalid attestation object. Unexpected object.');
        /** @var array<int|string, mixed> $normalizedData */
        return Key::create($normalizedData);
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\Webauthn\CeremonyStep;

use _ContaoManager\Webauthn\Exception\AuthenticatorResponseVerificationException;
final class HostTopOriginValidator implements TopOriginValidator
{
    public function __construct(private readonly string $host)
    {
    }
    public function validate(string $topOrigin): void
    {
        $topOrigin === $this->host || throw AuthenticatorResponseVerificationException::create('The top origin does not correspond to the host.');
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\Webauthn\CeremonyStep;

use _ContaoManager\Webauthn\AuthenticationExtensions\AuthenticationExtensions;
use _ContaoManager\Webauthn\AuthenticatorAssertionResponse;
use _ContaoManager\Webauthn\AuthenticatorAttestationResponse;
use _ContaoManager\Webauthn\Exception\AuthenticatorResponseVerificationException;
use _ContaoManager\Webauthn\PublicKeyCredentialCreationOptions;
use _ContaoManager\Webauthn\PublicKeyCredentialRequestOptions;
use _ContaoManager\Webauthn\PublicKeyCredentialSource;
use _ContaoManager\Webauthn\U2FPublicKey;
use function is_string;
final class CheckRelyingPartyIdIdHash implements CeremonyStep
{
    public function process(PublicKeyCredentialSource $publicKeyCredentialSource, AuthenticatorAssertionResponse|AuthenticatorAttestationResponse $authenticatorResponse, PublicKeyCredentialRequestOptions|PublicKeyCredentialCreationOptions $publicKeyCredentialOptions, ?string $userHandle, string $host): void
    {
        $authData = $authenticatorResponse instanceof AuthenticatorAssertionResponse ? $authenticatorResponse->authenticatorData : $authenticatorResponse->attestationObject->authData;
        $C = $authenticatorResponse->clientDataJSON;
        $attestedCredentialData = $publicKeyCredentialSource->getAttestedCredentialData();
        $credentialPublicKey = $attestedCredentialData->credentialPublicKey;
        $credentialPublicKey !== null || throw AuthenticatorResponseVerificationException::create('No public key available.');
        $isU2F = U2FPublicKey::isU2FKey($credentialPublicKey);
        $rpId = $publicKeyCredentialOptions->rpId ?? $publicKeyCredentialOptions->rp->id ?? $host;
        $facetId = $this->getFacetId($rpId, $publicKeyCredentialOptions->extensions, $authData->extensions);
        $rpIdHash = hash('sha256', $isU2F ? $C->origin : $facetId, \true);
        hash_equals($rpIdHash, $authData->rpIdHash) || throw AuthenticatorResponseVerificationException::create('rpId hash mismatch.');
    }
    private function getFacetId(string $rpId, AuthenticationExtensions $authenticationExtensionsClientInputs, null|AuthenticationExtensions $authenticationExtensionsClientOutputs): string
    {
        if ($authenticationExtensionsClientOutputs === null || !$authenticationExtensionsClientInputs->has('appid') || !$authenticationExtensionsClientOutputs->has('appid')) {
            return $rpId;
        }
        $appId = $authenticationExtensionsClientInputs->get('appid')->value;
        $wasUsed = $authenticationExtensionsClientOutputs->get('appid')->value;
        if (!is_string($appId) || $wasUsed !== \true) {
            return $rpId;
        }
        return $appId;
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\Webauthn\CeremonyStep;

use _ContaoManager\Webauthn\AuthenticatorAssertionResponse;
use _ContaoManager\Webauthn\AuthenticatorAttestationResponse;
use _ContaoManager\Webauthn\Exception\AuthenticatorResponseVerificationException;
use _ContaoManager\Webauthn\PublicKeyCredentialCreationOptions;
use _ContaoManager\Webauthn\PublicKeyCredentialRequestOptions;
use _ContaoManager\Webauthn\PublicKeyCredentialSource;
final class CheckBackupBitsAreConsistent implements CeremonyStep
{
    public function process(PublicKeyCredentialSource $publicKeyCredentialSource, AuthenticatorAssertionResponse|AuthenticatorAttestationResponse $authenticatorResponse, PublicKeyCredentialRequestOptions|PublicKeyCredentialCreationOptions $publicKeyCredentialOptions, ?string $userHandle, string $host): void
    {
        $authData = $authenticatorResponse instanceof AuthenticatorAssertionResponse ? $authenticatorResponse->authenticatorData : $authenticatorResponse->attestationObject->authData;
        if ($authData->isBackupEligible()) {
            return;
        }
        $authData->isBackedUp() !== \true || throw AuthenticatorResponseVerificationException::create('Backup up bit is set but the backup is not eligible.');
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\Webauthn\CeremonyStep;

use _ContaoManager\Webauthn\AuthenticatorAssertionResponse;
use _ContaoManager\Webauthn\AuthenticatorAttestationResponse;
use _ContaoManager\Webauthn\Exception\AuthenticatorResponseVerificationException;
use _ContaoManager\Webauthn\PublicKeyCredentialCreationOptions;
use _ContaoManager\Webauthn\PublicKeyCredentialRequestOptions;
use _ContaoManager\Webauthn\PublicKeyCredentialSource;
final class CheckUserWasPresent implements CeremonyStep
{
    public function process(PublicKeyCredentialSource $publicKeyCredentialSource, AuthenticatorAssertionResponse|AuthenticatorAttestationResponse $authenticatorResponse, PublicKeyCredentialRequestOptions|PublicKeyCredentialCreationOptions $publicKeyCredentialOptions, ?string $userHandle, string $host): void
    {
        $authData = $authenticatorResponse instanceof AuthenticatorAssertionResponse ? $authenticatorResponse->authenticatorData : $authenticatorResponse->attestationObject->authData;
        $authData->isUserPresent() || throw AuthenticatorResponseVerificationException::create('User was not present');
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\Webauthn\CeremonyStep;

use _ContaoManager\Webauthn\AuthenticatorAssertionResponse;
use _ContaoManager\Webauthn\AuthenticatorAttestationResponse;
use _ContaoManager\Webauthn\ClientDataCollector\ClientDataCollectorManager;
use _ContaoManager\Webauthn\ClientDataCollector\WebauthnAuthenticationCollector;
use _ContaoManager\Webauthn\PublicKeyCredentialCreationOptions;
use _ContaoManager\Webauthn\PublicKeyCredentialRequestOptions;
use _ContaoManager\Webauthn\PublicKeyCredentialSource;
final class CheckClientDataCollectorType implements CeremonyStep
{
    private readonly ClientDataCollectorManager $clientDataCollectorManager;
    public function __construct(null|ClientDataCollectorManager $clientDataCollectorManager = null)
    {
        $this->clientDataCollectorManager = $clientDataCollectorManager ?? new ClientDataCollectorManager([new WebauthnAuthenticationCollector()]);
    }
    public function process(PublicKeyCredentialSource $publicKeyCredentialSource, AuthenticatorAssertionResponse|AuthenticatorAttestationResponse $authenticatorResponse, PublicKeyCredentialRequestOptions|PublicKeyCredentialCreationOptions $publicKeyCredentialOptions, ?string $userHandle, string $host): void
    {
        $this->clientDataCollectorManager->collect($authenticatorResponse->clientDataJSON, $publicKeyCredentialOptions, $authenticatorResponse, $host);
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\Webauthn\CeremonyStep;

use _ContaoManager\Webauthn\AuthenticatorAssertionResponse;
use _ContaoManager\Webauthn\AuthenticatorAttestationResponse;
use _ContaoManager\Webauthn\Exception\AuthenticatorResponseVerificationException;
use _ContaoManager\Webauthn\PublicKeyCredentialCreationOptions;
use _ContaoManager\Webauthn\PublicKeyCredentialRequestOptions;
use _ContaoManager\Webauthn\PublicKeyCredentialSource;
final class CheckChallenge implements CeremonyStep
{
    public function process(PublicKeyCredentialSource $publicKeyCredentialSource, AuthenticatorAssertionResponse|AuthenticatorAttestationResponse $authenticatorResponse, PublicKeyCredentialRequestOptions|PublicKeyCredentialCreationOptions $publicKeyCredentialOptions, ?string $userHandle, string $host): void
    {
        $publicKeyCredentialOptions->challenge !== '' || throw AuthenticatorResponseVerificationException::create('Invalid challenge.');
        hash_equals($publicKeyCredentialOptions->challenge, $authenticatorResponse->clientDataJSON->challenge) || throw AuthenticatorResponseVerificationException::create('Invalid challenge.');
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\Webauthn\CeremonyStep;

use _ContaoManager\Webauthn\AuthenticatorAssertionResponse;
use _ContaoManager\Webauthn\AuthenticatorAttestationResponse;
use _ContaoManager\Webauthn\PublicKeyCredentialCreationOptions;
use _ContaoManager\Webauthn\PublicKeyCredentialRequestOptions;
use _ContaoManager\Webauthn\PublicKeyCredentialSource;
interface CeremonyStep
{
    public function process(PublicKeyCredentialSource $publicKeyCredentialSource, AuthenticatorAssertionResponse|AuthenticatorAttestationResponse $authenticatorResponse, PublicKeyCredentialRequestOptions|PublicKeyCredentialCreationOptions $publicKeyCredentialOptions, ?string $userHandle, string $host): void;
}
<?php

declare (strict_types=1);
namespace _ContaoManager\Webauthn\CeremonyStep;

use _ContaoManager\Webauthn\AuthenticatorAssertionResponse;
use _ContaoManager\Webauthn\AuthenticatorAttestationResponse;
use _ContaoManager\Webauthn\Counter\CounterChecker;
use _ContaoManager\Webauthn\PublicKeyCredentialCreationOptions;
use _ContaoManager\Webauthn\PublicKeyCredentialRequestOptions;
use _ContaoManager\Webauthn\PublicKeyCredentialSource;
final class CheckCounter implements CeremonyStep
{
    public function __construct(private readonly CounterChecker $counterChecker)
    {
    }
    public function process(PublicKeyCredentialSource $publicKeyCredentialSource, AuthenticatorAssertionResponse|AuthenticatorAttestationResponse $authenticatorResponse, PublicKeyCredentialRequestOptions|PublicKeyCredentialCreationOptions $publicKeyCredentialOptions, ?string $userHandle, string $host): void
    {
        $authData = $authenticatorResponse instanceof AuthenticatorAssertionResponse ? $authenticatorResponse->authenticatorData : $authenticatorResponse->attestationObject->authData;
        $storedCounter = $publicKeyCredentialSource->counter;
        $responseCounter = $authData->signCount;
        if ($responseCounter !== 0 || $storedCounter !== 0) {
            $this->counterChecker->check($publicKeyCredentialSource, $responseCounter);
        }
        $publicKeyCredentialSource->counter = $responseCounter;
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\Webauthn\CeremonyStep;

use _ContaoManager\Webauthn\AuthenticatorAssertionResponse;
use _ContaoManager\Webauthn\AuthenticatorAttestationResponse;
use _ContaoManager\Webauthn\Exception\AuthenticatorResponseVerificationException;
use _ContaoManager\Webauthn\PublicKeyCredentialCreationOptions;
use _ContaoManager\Webauthn\PublicKeyCredentialRequestOptions;
use _ContaoManager\Webauthn\PublicKeyCredentialSource;
class CheckTopOrigin implements CeremonyStep
{
    public function __construct(private readonly null|TopOriginValidator $topOriginValidator = null)
    {
    }
    public function process(PublicKeyCredentialSource $publicKeyCredentialSource, AuthenticatorAssertionResponse|AuthenticatorAttestationResponse $authenticatorResponse, PublicKeyCredentialRequestOptions|PublicKeyCredentialCreationOptions $publicKeyCredentialOptions, ?string $userHandle, string $host): void
    {
        $topOrigin = $authenticatorResponse->clientDataJSON->topOrigin;
        if ($topOrigin === null) {
            return;
        }
        if ($authenticatorResponse->clientDataJSON->crossOrigin !== \true) {
            throw AuthenticatorResponseVerificationException::create('The response is not cross-origin.');
        }
        if ($this->topOriginValidator === null) {
            (new HostTopOriginValidator($host))->validate($topOrigin);
        } else {
            $this->topOriginValidator->validate($topOrigin);
        }
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\Webauthn\CeremonyStep;

use _ContaoManager\Webauthn\AuthenticationExtensions\AuthenticationExtensions;
use _ContaoManager\Webauthn\AuthenticatorAssertionResponse;
use _ContaoManager\Webauthn\AuthenticatorAttestationResponse;
use _ContaoManager\Webauthn\Exception\AuthenticatorResponseVerificationException;
use _ContaoManager\Webauthn\PublicKeyCredentialCreationOptions;
use _ContaoManager\Webauthn\PublicKeyCredentialRequestOptions;
use _ContaoManager\Webauthn\PublicKeyCredentialSource;
use function in_array;
use function is_array;
use function is_string;
final class CheckOrigin implements CeremonyStep
{
    /**
     * @param string[] $securedRelyingPartyId
     */
    public function __construct(private readonly array $securedRelyingPartyId)
    {
    }
    public function process(PublicKeyCredentialSource $publicKeyCredentialSource, AuthenticatorAssertionResponse|AuthenticatorAttestationResponse $authenticatorResponse, PublicKeyCredentialRequestOptions|PublicKeyCredentialCreationOptions $publicKeyCredentialOptions, ?string $userHandle, string $host): void
    {
        $authData = $authenticatorResponse instanceof AuthenticatorAssertionResponse ? $authenticatorResponse->authenticatorData : $authenticatorResponse->attestationObject->authData;
        $C = $authenticatorResponse->clientDataJSON;
        $rpId = $publicKeyCredentialOptions->rpId ?? $publicKeyCredentialOptions->rp->id ?? $host;
        $facetId = $this->getFacetId($rpId, $publicKeyCredentialOptions->extensions, $authData->extensions);
        $parsedRelyingPartyId = parse_url($C->origin);
        is_array($parsedRelyingPartyId) || throw AuthenticatorResponseVerificationException::create('Invalid origin');
        if (!in_array($facetId, $this->securedRelyingPartyId, \true)) {
            $scheme = $parsedRelyingPartyId['scheme'] ?? '';
            $scheme === 'https' || throw AuthenticatorResponseVerificationException::create('Invalid scheme. HTTPS required.');
        }
        $clientDataRpId = $parsedRelyingPartyId['host'] ?? '';
        $clientDataRpId !== '' || throw AuthenticatorResponseVerificationException::create('Invalid origin rpId.');
        $rpIdLength = mb_strlen($facetId);
        mb_substr('.' . $clientDataRpId, -($rpIdLength + 1)) === '.' . $facetId || throw AuthenticatorResponseVerificationException::create('rpId mismatch.');
    }
    private function getFacetId(string $rpId, AuthenticationExtensions $authenticationExtensionsClientInputs, null|AuthenticationExtensions $authenticationExtensionsClientOutputs): string
    {
        if ($authenticationExtensionsClientOutputs === null || !$authenticationExtensionsClientInputs->has('appid') || !$authenticationExtensionsClientOutputs->has('appid')) {
            return $rpId;
        }
        $appId = $authenticationExtensionsClientInputs->get('appid')->value;
        $wasUsed = $authenticationExtensionsClientOutputs->get('appid')->value;
        if (!is_string($appId) || $wasUsed !== \true) {
            return $rpId;
        }
        return $appId;
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\Webauthn\CeremonyStep;

use _ContaoManager\Webauthn\AuthenticationExtensions\ExtensionOutputCheckerHandler;
use _ContaoManager\Webauthn\AuthenticatorAssertionResponse;
use _ContaoManager\Webauthn\AuthenticatorAttestationResponse;
use _ContaoManager\Webauthn\PublicKeyCredentialCreationOptions;
use _ContaoManager\Webauthn\PublicKeyCredentialRequestOptions;
use _ContaoManager\Webauthn\PublicKeyCredentialSource;
final class CheckExtensions implements CeremonyStep
{
    public function __construct(private readonly ExtensionOutputCheckerHandler $extensionOutputCheckerHandler)
    {
    }
    public function process(PublicKeyCredentialSource $publicKeyCredentialSource, AuthenticatorAssertionResponse|AuthenticatorAttestationResponse $authenticatorResponse, PublicKeyCredentialRequestOptions|PublicKeyCredentialCreationOptions $publicKeyCredentialOptions, ?string $userHandle, string $host): void
    {
        $authData = $authenticatorResponse instanceof AuthenticatorAssertionResponse ? $authenticatorResponse->authenticatorData : $authenticatorResponse->attestationObject->authData;
        $extensionsClientOutputs = $authData->extensions;
        if ($extensionsClientOutputs !== null) {
            $this->extensionOutputCheckerHandler->check($publicKeyCredentialOptions->extensions, $extensionsClientOutputs);
        }
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\Webauthn\CeremonyStep;

use _ContaoManager\Psr\Log\LoggerInterface;
use _ContaoManager\Psr\Log\NullLogger;
use _ContaoManager\Webauthn\AttestationStatement\AttestationStatement;
use _ContaoManager\Webauthn\AuthenticatorAssertionResponse;
use _ContaoManager\Webauthn\AuthenticatorAttestationResponse;
use _ContaoManager\Webauthn\Exception\AuthenticatorResponseVerificationException;
use _ContaoManager\Webauthn\MetadataService\CanLogData;
use _ContaoManager\Webauthn\MetadataService\CertificateChain\CertificateChainValidator;
use _ContaoManager\Webauthn\MetadataService\CertificateChain\CertificateToolbox;
use _ContaoManager\Webauthn\MetadataService\MetadataStatementRepository;
use _ContaoManager\Webauthn\MetadataService\Statement\MetadataStatement;
use _ContaoManager\Webauthn\MetadataService\StatusReportRepository;
use _ContaoManager\Webauthn\PublicKeyCredentialCreationOptions;
use _ContaoManager\Webauthn\PublicKeyCredentialRequestOptions;
use _ContaoManager\Webauthn\PublicKeyCredentialSource;
use _ContaoManager\Webauthn\TrustPath\CertificateTrustPath;
use function count;
use function in_array;
use function sprintf;
final class CheckMetadataStatement implements CeremonyStep, CanLogData
{
    private LoggerInterface $logger;
    private null|MetadataStatementRepository $metadataStatementRepository = null;
    private null|StatusReportRepository $statusReportRepository = null;
    private null|CertificateChainValidator $certificateChainValidator = null;
    public function __construct()
    {
        $this->logger = new NullLogger();
    }
    public function enableMetadataStatementSupport(MetadataStatementRepository $metadataStatementRepository, StatusReportRepository $statusReportRepository, CertificateChainValidator $certificateChainValidator): void
    {
        $this->metadataStatementRepository = $metadataStatementRepository;
        $this->statusReportRepository = $statusReportRepository;
        $this->certificateChainValidator = $certificateChainValidator;
    }
    public function enableCertificateChainValidator(CertificateChainValidator $certificateChainValidator): void
    {
        $this->certificateChainValidator = $certificateChainValidator;
    }
    public function setLogger(LoggerInterface $logger): void
    {
        $this->logger = $logger;
    }
    public function process(PublicKeyCredentialSource $publicKeyCredentialSource, AuthenticatorAssertionResponse|AuthenticatorAttestationResponse $authenticatorResponse, PublicKeyCredentialRequestOptions|PublicKeyCredentialCreationOptions $publicKeyCredentialOptions, ?string $userHandle, string $host): void
    {
        if (!$publicKeyCredentialOptions instanceof PublicKeyCredentialCreationOptions || !$authenticatorResponse instanceof AuthenticatorAttestationResponse) {
            return;
        }
        $attestationStatement = $authenticatorResponse->attestationObject->attStmt;
        $attestedCredentialData = $authenticatorResponse->attestationObject->authData->attestedCredentialData;
        $attestedCredentialData !== null || throw AuthenticatorResponseVerificationException::create('No attested credential data found');
        $aaguid = $attestedCredentialData->aaguid->__toString();
        if ($publicKeyCredentialOptions->attestation === null || $publicKeyCredentialOptions->attestation === PublicKeyCredentialCreationOptions::ATTESTATION_CONVEYANCE_PREFERENCE_NONE) {
            $this->logger->debug('No attestation is asked.');
            if ($aaguid === '00000000-0000-0000-0000-000000000000' && in_array($attestationStatement->type, [AttestationStatement::TYPE_NONE, AttestationStatement::TYPE_SELF], \true)) {
                $this->logger->debug('The Attestation Statement is anonymous.');
                $this->checkCertificateChain($attestationStatement, null);
                return;
            }
            return;
        }
        // If no Attestation Statement has been returned or if null AAGUID (=00000000-0000-0000-0000-000000000000)
        // => nothing to check
        if ($attestationStatement->type === AttestationStatement::TYPE_NONE) {
            $this->logger->debug('No attestation returned.');
            //No attestation is returned. We shall ensure that the AAGUID is a null one.
            //if ($aaguid !== '00000000-0000-0000-0000-000000000000') {
            //$this->logger->debug('Anonymization required. AAGUID and Attestation Statement changed.', [
            //    'aaguid' => $aaguid,
            //    'AttestationStatement' => $attestationStatement,
            //]);
            //$attestedCredentialData->aaguid = Uuid::fromString('00000000-0000-0000-0000-000000000000');
            //    return;
            //}
            return;
        }
        if ($aaguid === '00000000-0000-0000-0000-000000000000') {
            //No need to continue if the AAGUID is null.
            // This could be the case e.g. with AnonCA type
            return;
        }
        //The MDS Repository is mandatory here
        $this->metadataStatementRepository !== null || throw AuthenticatorResponseVerificationException::create('The Metadata Statement Repository is mandatory when requesting attestation objects.');
        $metadataStatement = $this->metadataStatementRepository->findOneByAAGUID($aaguid);
        // At this point, the Metadata Statement is mandatory
        $metadataStatement !== null || throw AuthenticatorResponseVerificationException::create(sprintf('The Metadata Statement for the AAGUID "%s" is missing', $aaguid));
        // We check the last status report
        $this->checkStatusReport($aaguid);
        // We check the certificate chain (if any)
        $this->checkCertificateChain($attestationStatement, $metadataStatement);
        // Check Attestation Type is allowed
        if (count($metadataStatement->attestationTypes) !== 0) {
            $type = $this->getAttestationType($attestationStatement);
            in_array($type, $metadataStatement->attestationTypes, \true) || throw AuthenticatorResponseVerificationException::create(sprintf('Invalid attestation statement. The attestation type "%s" is not allowed for this authenticator.', $type));
        }
    }
    private function getAttestationType(AttestationStatement $attestationStatement): string
    {
        return match ($attestationStatement->type) {
            AttestationStatement::TYPE_BASIC => MetadataStatement::ATTESTATION_BASIC_FULL,
            AttestationStatement::TYPE_SELF => MetadataStatement::ATTESTATION_BASIC_SURROGATE,
            AttestationStatement::TYPE_ATTCA => MetadataStatement::ATTESTATION_ATTCA,
            AttestationStatement::TYPE_ECDAA => MetadataStatement::ATTESTATION_ECDAA,
            AttestationStatement::TYPE_ANONCA => MetadataStatement::ATTESTATION_ANONCA,
            default => throw AuthenticatorResponseVerificationException::create('Invalid attestation type'),
        };
    }
    private function checkStatusReport(string $aaguid): void
    {
        $statusReports = $this->statusReportRepository === null ? [] : $this->statusReportRepository->findStatusReportsByAAGUID($aaguid);
        if (count($statusReports) !== 0) {
            $lastStatusReport = end($statusReports);
            if ($lastStatusReport->isCompromised()) {
                throw AuthenticatorResponseVerificationException::create('The authenticator is compromised and cannot be used');
            }
        }
    }
    private function checkCertificateChain(AttestationStatement $attestationStatement, ?MetadataStatement $metadataStatement): void
    {
        $trustPath = $attestationStatement->trustPath;
        if (!$trustPath instanceof CertificateTrustPath) {
            return;
        }
        $authenticatorCertificates = $trustPath->certificates;
        if ($metadataStatement === null) {
            $this->certificateChainValidator?->check($authenticatorCertificates, []);
            return;
        }
        $trustedCertificates = CertificateToolbox::fixPEMStructures($metadataStatement->attestationRootCertificates);
        $this->certificateChainValidator?->check($authenticatorCertificates, $trustedCertificates);
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\Webauthn\CeremonyStep;

use _ContaoManager\Cose\Algorithm\Manager;
use _ContaoManager\Cose\Algorithm\Signature\ECDSA\ES256;
use _ContaoManager\Cose\Algorithm\Signature\RSA\RS256;
use _ContaoManager\Webauthn\AttestationStatement\AttestationStatementSupportManager;
use _ContaoManager\Webauthn\AttestationStatement\NoneAttestationStatementSupport;
use _ContaoManager\Webauthn\AuthenticationExtensions\ExtensionOutputCheckerHandler;
use _ContaoManager\Webauthn\Counter\CounterChecker;
use _ContaoManager\Webauthn\Counter\ThrowExceptionIfInvalid;
use _ContaoManager\Webauthn\MetadataService\CertificateChain\CertificateChainValidator;
use _ContaoManager\Webauthn\MetadataService\MetadataStatementRepository;
use _ContaoManager\Webauthn\MetadataService\StatusReportRepository;
final class CeremonyStepManagerFactory
{
    private CounterChecker $counterChecker;
    private Manager $algorithmManager;
    private null|MetadataStatementRepository $metadataStatementRepository = null;
    private null|StatusReportRepository $statusReportRepository = null;
    private null|CertificateChainValidator $certificateChainValidator = null;
    private null|TopOriginValidator $topOriginValidator = null;
    /**
     * @var string[]
     */
    private null|array $securedRelyingPartyId = null;
    private AttestationStatementSupportManager $attestationStatementSupportManager;
    private ExtensionOutputCheckerHandler $extensionOutputCheckerHandler;
    public function __construct()
    {
        $this->counterChecker = new ThrowExceptionIfInvalid();
        $this->algorithmManager = Manager::create()->add(ES256::create(), RS256::create());
        $this->attestationStatementSupportManager = new AttestationStatementSupportManager([new NoneAttestationStatementSupport()]);
        $this->extensionOutputCheckerHandler = new ExtensionOutputCheckerHandler();
    }
    public function setCounterChecker(CounterChecker $counterChecker): void
    {
        $this->counterChecker = $counterChecker;
    }
    /**
     * @param string[] $securedRelyingPartyId
     */
    public function setSecuredRelyingPartyId(array $securedRelyingPartyId): void
    {
        $this->securedRelyingPartyId = $securedRelyingPartyId;
    }
    public function setExtensionOutputCheckerHandler(ExtensionOutputCheckerHandler $extensionOutputCheckerHandler): void
    {
        $this->extensionOutputCheckerHandler = $extensionOutputCheckerHandler;
    }
    public function setAttestationStatementSupportManager(AttestationStatementSupportManager $attestationStatementSupportManager): void
    {
        $this->attestationStatementSupportManager = $attestationStatementSupportManager;
    }
    public function setAlgorithmManager(Manager $algorithmManager): void
    {
        $this->algorithmManager = $algorithmManager;
    }
    public function enableMetadataStatementSupport(MetadataStatementRepository $metadataStatementRepository, StatusReportRepository $statusReportRepository, CertificateChainValidator $certificateChainValidator): void
    {
        $this->metadataStatementRepository = $metadataStatementRepository;
        $this->statusReportRepository = $statusReportRepository;
        $this->certificateChainValidator = $certificateChainValidator;
    }
    public function enableCertificateChainValidator(CertificateChainValidator $certificateChainValidator): void
    {
        $this->certificateChainValidator = $certificateChainValidator;
    }
    public function enableTopOriginValidator(TopOriginValidator $topOriginValidator): void
    {
        $this->topOriginValidator = $topOriginValidator;
    }
    /**
     * @param null|string[] $securedRelyingPartyId
     */
    public function creationCeremony(null|array $securedRelyingPartyId = null): CeremonyStepManager
    {
        $metadataStatementChecker = new CheckMetadataStatement();
        if ($this->certificateChainValidator !== null) {
            $metadataStatementChecker->enableCertificateChainValidator($this->certificateChainValidator);
        }
        if ($this->metadataStatementRepository !== null && $this->statusReportRepository !== null && $this->certificateChainValidator !== null) {
            $metadataStatementChecker->enableMetadataStatementSupport($this->metadataStatementRepository, $this->statusReportRepository, $this->certificateChainValidator);
        }
        /* @see https://www.w3.org/TR/webauthn-3/#sctn-registering-a-new-credential */
        return new CeremonyStepManager([new CheckClientDataCollectorType(), new CheckChallenge(), new CheckOrigin($this->securedRelyingPartyId ?? $securedRelyingPartyId ?? []), new CheckTopOrigin($this->topOriginValidator), new CheckRelyingPartyIdIdHash(), new CheckUserWasPresent(), new CheckUserVerification(), new CheckBackupBitsAreConsistent(), new CheckAlgorithm(), new CheckExtensions($this->extensionOutputCheckerHandler), new CheckAttestationFormatIsKnownAndValid($this->attestationStatementSupportManager), new CheckHasAttestedCredentialData(), $metadataStatementChecker, new CheckCredentialId()]);
    }
    /**
     * @param null|string[] $securedRelyingPartyId
     */
    public function requestCeremony(null|array $securedRelyingPartyId = null): CeremonyStepManager
    {
        /* @see https://www.w3.org/TR/webauthn-3/#sctn-verifying-assertion */
        return new CeremonyStepManager([new CheckAllowedCredentialList(), new CheckUserHandle(), new CheckClientDataCollectorType(), new CheckChallenge(), new CheckOrigin($this->securedRelyingPartyId ?? $securedRelyingPartyId ?? []), new CheckTopOrigin(null), new CheckRelyingPartyIdIdHash(), new CheckUserWasPresent(), new CheckUserVerification(), new CheckBackupBitsAreConsistent(), new CheckExtensions($this->extensionOutputCheckerHandler), new CheckSignature($this->algorithmManager), new CheckCounter($this->counterChecker)]);
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\Webauthn;

use _ContaoManager\ParagonIE\ConstantTime\Base64;
use _ContaoManager\ParagonIE\ConstantTime\Base64UrlSafe;
use _ContaoManager\Webauthn\Exception\InvalidDataException;
use function array_key_exists;
use function is_array;
use const JSON_THROW_ON_ERROR;
class PublicKeyCredentialUserEntity extends PublicKeyCredentialEntity
{
    public readonly string $id;
    public function __construct(string $name, string $id, public readonly string $displayName, ?string $icon = null)
    {
        parent::__construct($name, $icon);
        mb_strlen($id, '8bit') <= 64 || throw InvalidDataException::create($id, 'User ID max length is 64 bytes');
        $this->id = $id;
    }
    public static function create(string $name, string $id, string $displayName, ?string $icon = null): self
    {
        return new self($name, $id, $displayName, $icon);
    }
    /**
     * @deprecated since 4.7.0. Please use the property directly.
     * @infection-ignore-all
     */
    public function getId(): string
    {
        return $this->id;
    }
    /**
     * @deprecated since 4.7.0. Please use the property directly.
     * @infection-ignore-all
     */
    public function getDisplayName(): string
    {
        return $this->displayName;
    }
    /**
     * @deprecated since 4.8.0. Please use {Webauthn\Denormalizer\WebauthnSerializerFactory} for converting the object.
     * @infection-ignore-all
     */
    public static function createFromString(string $data): self
    {
        $data = json_decode($data, \true, flags: JSON_THROW_ON_ERROR);
        is_array($data) || throw InvalidDataException::create($data, 'Invalid data');
        return self::createFromArray($data);
    }
    /**
     * @param mixed[] $json
     * @deprecated since 4.8.0. Please use {Webauthn\Denormalizer\WebauthnSerializerFactory} for converting the object.
     * @infection-ignore-all
     */
    public static function createFromArray(array $json): self
    {
        array_key_exists('name', $json) || throw InvalidDataException::create($json, 'Invalid input. "name" is missing.');
        array_key_exists('id', $json) || throw InvalidDataException::create($json, 'Invalid input. "id" is missing.');
        array_key_exists('displayName', $json) || throw InvalidDataException::create($json, 'Invalid input. "displayName" is missing.');
        $id = Base64::decode($json['id'], \true);
        return self::create($json['name'], $id, $json['displayName'], $json['icon'] ?? null);
    }
    /**
     * @return mixed[]
     */
    public function jsonSerialize(): array
    {
        trigger_deprecation('web-auth/webauthn-bundle', '4.9.0', 'The "%s" method is deprecated and will be removed in 5.0. Please use the serializer instead.', __METHOD__);
        $json = parent::jsonSerialize();
        $json['id'] = Base64UrlSafe::encodeUnpadded($this->id);
        $json['displayName'] = $this->displayName;
        return $json;
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\Webauthn;

use _ContaoManager\Webauthn\MetadataService\CertificateChain\CertificateToolbox as BaseCertificateToolbox;
/**
 * @deprecated since v4.1. Please use Webauthn\MetadataService\CertificateChainChecker\PhpCertificateChainValidator instead
 * @infection-ignore-all
 */
class CertificateToolbox extends BaseCertificateToolbox
{
}
<?php

declare (strict_types=1);
namespace _ContaoManager\Webauthn\AuthenticationExtensions;

use ArrayAccess;
use ArrayIterator;
use Countable;
use Iterator;
use IteratorAggregate;
use JsonSerializable;
use _ContaoManager\Webauthn\Exception\AuthenticationExtensionException;
use function array_key_exists;
use function count;
use function is_string;
use function sprintf;
use const COUNT_NORMAL;
/**
 * @implements IteratorAggregate<AuthenticationExtension>
 * @final
 */
class AuthenticationExtensions implements JsonSerializable, Countable, IteratorAggregate, ArrayAccess
{
    /**
     * @var array<string, AuthenticationExtension>
     * @readonly
     */
    public array $extensions;
    /**
     * @param array<array-key, mixed|AuthenticationExtension> $extensions
     */
    public function __construct(array $extensions = [])
    {
        $list = [];
        foreach ($extensions as $key => $extension) {
            if ($extension instanceof AuthenticationExtension) {
                $list[$extension->name] = $extension;
                continue;
            }
            if (is_string($key)) {
                $list[$key] = AuthenticationExtension::create($key, $extension);
                continue;
            }
            throw new AuthenticationExtensionException('Invalid extension');
        }
        $this->extensions = $list;
    }
    /**
     * @param array<array-key, AuthenticationExtension> $extensions
     */
    public static function create(array $extensions = []): static
    {
        return new static($extensions);
    }
    /**
     * @deprecated since 4.7.0. Please use the property directly.
     * @infection-ignore-all
     */
    public function add(AuthenticationExtension ...$extensions): static
    {
        foreach ($extensions as $extension) {
            $this->extensions[$extension->name] = $extension;
        }
        return $this;
    }
    /**
     * @param array<string, mixed> $json
     * @deprecated since 4.8.0. Please use {Webauthn\Denormalizer\WebauthnSerializerFactory} for converting the object.
     * @infection-ignore-all
     */
    public static function createFromArray(array $json): static
    {
        return static::create(array_map(static fn(string $key, mixed $value): AuthenticationExtension => AuthenticationExtension::create($key, $value), array_keys($json), $json));
    }
    public function has(string $key): bool
    {
        return array_key_exists($key, $this->extensions);
    }
    public function get(string $key): AuthenticationExtension
    {
        $this->has($key) || throw AuthenticationExtensionException::create(sprintf('The extension with key "%s" is not available', $key));
        return $this->extensions[$key];
    }
    /**
     * @return array<string, AuthenticationExtension>
     */
    public function jsonSerialize(): array
    {
        trigger_deprecation('web-auth/webauthn-bundle', '4.9.0', 'The "%s" method is deprecated and will be removed in 5.0. Please use the serializer instead.', __METHOD__);
        return $this->extensions;
    }
    /**
     * @return Iterator<string, AuthenticationExtension>
     */
    public function getIterator(): Iterator
    {
        return new ArrayIterator($this->extensions);
    }
    public function count(int $mode = COUNT_NORMAL): int
    {
        return count($this->extensions, $mode);
    }
    public function offsetExists(mixed $offset): bool
    {
        return array_key_exists($offset, $this->extensions);
    }
    public function offsetGet(mixed $offset): mixed
    {
        return $this->extensions[$offset];
    }
    public function offsetSet(mixed $offset, mixed $value): void
    {
        if ($value === null) {
            return;
        }
        if ($value instanceof AuthenticationExtension) {
            $this->extensions[$value->name] = $value;
            return;
        }
        if (is_string($offset)) {
            $this->extensions[$offset] = AuthenticationExtension::create($offset, $value);
            return;
        }
        throw new AuthenticationExtensionException('Invalid extension');
    }
    public function offsetUnset(mixed $offset): void
    {
        unset($this->extensions[$offset]);
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\Webauthn\AuthenticationExtensions;

class ExtensionOutputCheckerHandler
{
    /**
     * @var ExtensionOutputChecker[]
     */
    private array $checkers = [];
    public static function create(): self
    {
        return new self();
    }
    public function add(ExtensionOutputChecker $checker): void
    {
        $this->checkers[] = $checker;
    }
    public function check(AuthenticationExtensions $inputs, AuthenticationExtensions $outputs): void
    {
        foreach ($this->checkers as $checker) {
            $checker->check($inputs, $outputs);
        }
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\Webauthn\AuthenticationExtensions;

/**
 * @deprecated since 4.8.0. Use {Webauthn\AuthenticationExtensions\AuthenticationExtensions} instead.
 */
class AuthenticationExtensionsClientInputs extends AuthenticationExtensions
{
}
<?php

declare (strict_types=1);
namespace _ContaoManager\Webauthn\AuthenticationExtensions;

use Exception;
use Throwable;
class ExtensionOutputError extends Exception
{
    public function __construct(public readonly AuthenticationExtension $authenticationExtension, string $message = '', int $code = 0, ?Throwable $previous = null)
    {
        parent::__construct($message, $code, $previous);
    }
    /**
     * @deprecated since 4.7.0. Please use the property directly.
     * @infection-ignore-all
     */
    public function getAuthenticationExtension(): AuthenticationExtension
    {
        return $this->authenticationExtension;
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\Webauthn\AuthenticationExtensions;

use JsonSerializable;
class AuthenticationExtension implements JsonSerializable
{
    public function __construct(public readonly string $name, public readonly mixed $value)
    {
    }
    public static function create(string $name, mixed $value): self
    {
        return new self($name, $value);
    }
    /**
     * @deprecated since 4.7.0. Please use the property directly.
     * @infection-ignore-all
     */
    public function name(): string
    {
        return $this->name;
    }
    /**
     * @deprecated since 4.7.0. Please use the property directly.
     * @infection-ignore-all
     */
    public function value(): mixed
    {
        return $this->value;
    }
    public function jsonSerialize(): mixed
    {
        trigger_deprecation('web-auth/webauthn-bundle', '4.9.0', 'The "%s" method is deprecated and will be removed in 5.0. Please use the serializer instead.', __METHOD__);
        return $this->value;
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\Webauthn\AuthenticationExtensions;

interface ExtensionOutputChecker
{
    public function check(AuthenticationExtensions $inputs, AuthenticationExtensions $outputs): void;
}
<?php

declare (strict_types=1);
namespace _ContaoManager\Webauthn\AuthenticationExtensions;

/**
 * @deprecated since 4.8.0. Use {Webauthn\AuthenticationExtensions\AuthenticationExtensions} instead.
 */
class AuthenticationExtensionsClientOutputs extends AuthenticationExtensions
{
}
<?php

declare (strict_types=1);
namespace _ContaoManager\Webauthn\AuthenticationExtensions;

use _ContaoManager\CBOR\CBORObject;
use _ContaoManager\CBOR\MapObject;
use _ContaoManager\Webauthn\Exception\AuthenticationExtensionException;
abstract class AuthenticationExtensionsClientOutputsLoader
{
    public static function load(CBORObject $object): AuthenticationExtensions
    {
        $object instanceof MapObject || throw AuthenticationExtensionException::create('Invalid extension object');
        $data = $object->normalize();
        return AuthenticationExtensionsClientOutputs::create(array_map(fn(mixed $value, string $key) => AuthenticationExtension::create($key, $value), $data, array_keys($data)));
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\Webauthn\AttestationStatement;

use _ContaoManager\Jose\Component\Core\Algorithm as AlgorithmInterface;
use _ContaoManager\Jose\Component\Core\AlgorithmManager;
use _ContaoManager\Jose\Component\KeyManagement\JWKFactory;
use _ContaoManager\Jose\Component\Signature\Algorithm\EdDSA;
use _ContaoManager\Jose\Component\Signature\Algorithm\ES256;
use _ContaoManager\Jose\Component\Signature\Algorithm\ES384;
use _ContaoManager\Jose\Component\Signature\Algorithm\ES512;
use _ContaoManager\Jose\Component\Signature\Algorithm\PS256;
use _ContaoManager\Jose\Component\Signature\Algorithm\PS384;
use _ContaoManager\Jose\Component\Signature\Algorithm\PS512;
use _ContaoManager\Jose\Component\Signature\Algorithm\RS256;
use _ContaoManager\Jose\Component\Signature\Algorithm\RS384;
use _ContaoManager\Jose\Component\Signature\Algorithm\RS512;
use _ContaoManager\Jose\Component\Signature\JWS;
use _ContaoManager\Jose\Component\Signature\JWSVerifier;
use _ContaoManager\Jose\Component\Signature\Serializer\CompactSerializer;
use _ContaoManager\Psr\Clock\ClockInterface;
use _ContaoManager\Psr\EventDispatcher\EventDispatcherInterface;
use _ContaoManager\Psr\Http\Client\ClientInterface;
use _ContaoManager\Psr\Http\Message\RequestFactoryInterface;
use _ContaoManager\Psr\Http\Message\ResponseInterface;
use _ContaoManager\Symfony\Contracts\HttpClient\HttpClientInterface;
use _ContaoManager\Webauthn\AuthenticatorData;
use _ContaoManager\Webauthn\Event\AttestationStatementLoaded;
use _ContaoManager\Webauthn\Event\CanDispatchEvents;
use _ContaoManager\Webauthn\Event\NullEventDispatcher;
use _ContaoManager\Webauthn\Exception\AttestationStatementLoadingException;
use _ContaoManager\Webauthn\Exception\AttestationStatementVerificationException;
use _ContaoManager\Webauthn\Exception\InvalidAttestationStatementException;
use _ContaoManager\Webauthn\Exception\UnsupportedFeatureException;
use _ContaoManager\Webauthn\MetadataService\CertificateChain\CertificateToolbox;
use _ContaoManager\Webauthn\TrustPath\CertificateTrustPath;
use function array_key_exists;
use function count;
use function is_array;
use function is_int;
use function is_string;
use function sprintf;
use const JSON_THROW_ON_ERROR;
/**
 * @deprecated since 4.9.0 and will be removed in 5.0.0. Android SafetyNet is now deprecated.
 */
final class AndroidSafetyNetAttestationStatementSupport implements AttestationStatementSupport, CanDispatchEvents
{
    private ?string $apiKey = null;
    private null|ClientInterface|HttpClientInterface $client = null;
    private readonly CompactSerializer $jwsSerializer;
    private ?JWSVerifier $jwsVerifier = null;
    private ?RequestFactoryInterface $requestFactory = null;
    private int $leeway = 0;
    private int $maxAge = 60000;
    private EventDispatcherInterface $dispatcher;
    public function __construct(private readonly null|ClockInterface $clock = null)
    {
        if ($this->clock === null) {
            trigger_deprecation('web-auth/webauthn-lib', '4.8.0', 'The parameter "$clock" will be required in 5.0.0. Please set a clock instance.');
        }
        if (!class_exists(RS256::class) || !class_exists(JWKFactory::class)) {
            throw UnsupportedFeatureException::create('The algorithm RS256 is missing. Did you forget to install the package web-token/jwt-library?');
        }
        $this->jwsSerializer = new CompactSerializer();
        $this->initJwsVerifier();
        $this->dispatcher = new NullEventDispatcher();
    }
    public function setEventDispatcher(EventDispatcherInterface $eventDispatcher): void
    {
        $this->dispatcher = $eventDispatcher;
    }
    public static function create(null|ClockInterface $clock = null): self
    {
        return new self($clock);
    }
    public function enableApiVerification(ClientInterface|HttpClientInterface $client, string $apiKey, ?RequestFactoryInterface $requestFactory = null): self
    {
        $this->apiKey = $apiKey;
        $this->client = $client;
        $this->requestFactory = $requestFactory;
        if ($requestFactory !== null && !$client instanceof HttpClientInterface) {
            trigger_deprecation('web-auth/metadata-service', '4.7.0', 'The parameter "$requestFactory" will be removed in 5.0.0. Please set it to null and set an Symfony\Contracts\HttpClient\HttpClientInterface as "$client" argument.');
        }
        return $this;
    }
    public function setMaxAge(int $maxAge): self
    {
        $this->maxAge = $maxAge;
        return $this;
    }
    public function setLeeway(int $leeway): self
    {
        $this->leeway = $leeway;
        return $this;
    }
    public function name(): string
    {
        return 'android-safetynet';
    }
    /**
     * @param array<string, mixed> $attestation
     */
    public function load(array $attestation): AttestationStatement
    {
        array_key_exists('attStmt', $attestation) || throw AttestationStatementLoadingException::create($attestation);
        foreach (['ver', 'response'] as $key) {
            array_key_exists($key, $attestation['attStmt']) || throw AttestationStatementLoadingException::create($attestation, sprintf('The attestation statement value "%s" is missing.', $key));
            $attestation['attStmt'][$key] !== '' || throw AttestationStatementLoadingException::create($attestation, sprintf('The attestation statement value "%s" is empty.', $key));
        }
        $jws = $this->jwsSerializer->unserialize($attestation['attStmt']['response']);
        $jwsHeader = $jws->getSignature(0)->getProtectedHeader();
        array_key_exists('x5c', $jwsHeader) || throw AttestationStatementLoadingException::create($attestation, 'The response in the attestation statement must contain a "x5c" header.');
        (is_countable($jwsHeader['x5c']) ? count($jwsHeader['x5c']) : 0) > 0 || throw AttestationStatementLoadingException::create($attestation, 'The "x5c" parameter in the attestation statement response must contain at least one certificate.');
        $certificates = $this->convertCertificatesToPem($jwsHeader['x5c']);
        $attestation['attStmt']['jws'] = $jws;
        $attestationStatement = AttestationStatement::createBasic($this->name(), $attestation['attStmt'], CertificateTrustPath::create($certificates));
        $this->dispatcher->dispatch(AttestationStatementLoaded::create($attestationStatement));
        return $attestationStatement;
    }
    public function isValid(string $clientDataJSONHash, AttestationStatement $attestationStatement, AuthenticatorData $authenticatorData): bool
    {
        $trustPath = $attestationStatement->trustPath;
        $trustPath instanceof CertificateTrustPath || throw InvalidAttestationStatementException::create($attestationStatement, 'Invalid trust path');
        $certificates = $trustPath->certificates;
        $firstCertificate = current($certificates);
        is_string($firstCertificate) || throw InvalidAttestationStatementException::create($attestationStatement, 'No certificate');
        $parsedCertificate = openssl_x509_parse($firstCertificate);
        is_array($parsedCertificate) || throw InvalidAttestationStatementException::create($attestationStatement, 'Invalid attestation object');
        array_key_exists('subject', $parsedCertificate) || throw InvalidAttestationStatementException::create($attestationStatement, 'Invalid attestation object');
        array_key_exists('CN', $parsedCertificate['subject']) || throw InvalidAttestationStatementException::create($attestationStatement, 'Invalid attestation object');
        $parsedCertificate['subject']['CN'] === 'attest.android.com' || throw InvalidAttestationStatementException::create($attestationStatement, 'Invalid attestation object');
        /** @var JWS $jws */
        $jws = $attestationStatement->get('jws');
        $payload = $jws->getPayload();
        $this->validatePayload($payload, $clientDataJSONHash, $authenticatorData);
        //Check the signature
        $this->validateSignature($jws, $trustPath);
        //Check against Google service
        $this->validateUsingGoogleApi($attestationStatement);
        return \true;
    }
    private function validatePayload(?string $payload, string $clientDataJSONHash, AuthenticatorData $authenticatorData): void
    {
        $payload !== null || throw AttestationStatementVerificationException::create('Invalid attestation object');
        $payload = json_decode($payload, \true, flags: JSON_THROW_ON_ERROR);
        array_key_exists('nonce', $payload) || throw AttestationStatementVerificationException::create('Invalid attestation object. "nonce" is missing.');
        $payload['nonce'] === base64_encode(hash('sha256', $authenticatorData->authData . $clientDataJSONHash, \true)) || throw AttestationStatementVerificationException::create('Invalid attestation object. Invalid nonce');
        array_key_exists('ctsProfileMatch', $payload) || throw AttestationStatementVerificationException::create('Invalid attestation object. "ctsProfileMatch" is missing.');
        $payload['ctsProfileMatch'] || throw AttestationStatementVerificationException::create('Invalid attestation object. "ctsProfileMatch" value is false.');
        array_key_exists('timestampMs', $payload) || throw AttestationStatementVerificationException::create('Invalid attestation object. Timestamp is missing.');
        is_int($payload['timestampMs']) || throw AttestationStatementVerificationException::create('Invalid attestation object. Timestamp shall be an integer.');
        $currentTime = ($this->clock?->now()->getTimestamp() ?? time()) * 1000;
        $payload['timestampMs'] <= $currentTime + $this->leeway || throw AttestationStatementVerificationException::create(sprintf('Invalid attestation object. Issued in the future. Current time: %d. Response time: %d', $currentTime, $payload['timestampMs']));
        $currentTime - $payload['timestampMs'] <= $this->maxAge || throw AttestationStatementVerificationException::create(sprintf('Invalid attestation object. Too old. Current time: %d. Response time: %d', $currentTime, $payload['timestampMs']));
    }
    private function validateSignature(JWS $jws, CertificateTrustPath $trustPath): void
    {
        $jwk = JWKFactory::createFromCertificate($trustPath->certificates[0]);
        $isValid = $this->jwsVerifier?->verifyWithKey($jws, $jwk, 0);
        $isValid === \true || throw AttestationStatementVerificationException::create('Invalid response signature');
    }
    private function validateUsingGoogleApi(AttestationStatement $attestationStatement): void
    {
        if ($this->client === null || $this->apiKey === null) {
            return;
        }
        $uri = sprintf('https://www.googleapis.com/androidcheck/v1/attestations/verify?key=%s', urlencode($this->apiKey));
        $requestBody = sprintf('{"signedAttestation":"%s"}', $attestationStatement->get('response'));
        if ($this->client instanceof HttpClientInterface) {
            $responseBody = $this->validateUsingGoogleApiWithSymfonyClient($requestBody, $uri);
        } else {
            $responseBody = $this->validateUsingGoogleApiWithPsrClient($requestBody, $uri);
        }
        $responseBodyJson = json_decode($responseBody, \true, flags: JSON_THROW_ON_ERROR);
        array_key_exists('isValidSignature', $responseBodyJson) || throw AttestationStatementVerificationException::create('Invalid response.');
        $responseBodyJson['isValidSignature'] === \true || throw AttestationStatementVerificationException::create('Invalid response.');
    }
    private function getResponseBody(ResponseInterface $response): string
    {
        $responseBody = '';
        $response->getBody()->rewind();
        do {
            $tmp = $response->getBody()->read(1024);
            if ($tmp === '') {
                break;
            }
            $responseBody .= $tmp;
        } while (\true);
        return $responseBody;
    }
    /**
     * @param string[] $certificates
     *
     * @return string[]
     */
    private function convertCertificatesToPem(array $certificates): array
    {
        foreach ($certificates as $k => $v) {
            $certificates[$k] = CertificateToolbox::fixPEMStructure($v);
        }
        return $certificates;
    }
    private function initJwsVerifier(): void
    {
        $algorithmClasses = [RS256::class, RS384::class, RS512::class, PS256::class, PS384::class, PS512::class, ES256::class, ES384::class, ES512::class, EdDSA::class];
        /** @var AlgorithmInterface[] $algorithms */
        $algorithms = [];
        foreach ($algorithmClasses as $algorithm) {
            if (class_exists($algorithm)) {
                $algorithms[] = new $algorithm();
            }
        }
        $algorithmManager = new AlgorithmManager($algorithms);
        $this->jwsVerifier = new JWSVerifier($algorithmManager);
    }
    private function validateUsingGoogleApiWithSymfonyClient(string $requestBody, string $uri): string
    {
        $response = $this->client->request('POST', $uri, ['headers' => ['content-type' => 'application/json'], 'body' => $requestBody]);
        $response->getStatusCode() === 200 || throw AttestationStatementVerificationException::create('Request did not succeeded');
        return $response->getContent();
    }
    private function validateUsingGoogleApiWithPsrClient(string $requestBody, string $uri): string
    {
        $request = $this->requestFactory->createRequest('POST', $uri);
        $request = $request->withHeader('content-type', 'application/json');
        $request->getBody()->write($requestBody);
        $response = $this->client->sendRequest($request);
        $response->getStatusCode() === 200 || throw AttestationStatementVerificationException::create('Request did not succeeded');
        return $this->getResponseBody($response);
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\Webauthn\AttestationStatement;

use _ContaoManager\CBOR\Decoder;
use _ContaoManager\CBOR\MapObject;
use _ContaoManager\Cose\Key\Ec2Key;
use _ContaoManager\Psr\EventDispatcher\EventDispatcherInterface;
use Throwable;
use _ContaoManager\Webauthn\AuthenticatorData;
use _ContaoManager\Webauthn\Event\AttestationStatementLoaded;
use _ContaoManager\Webauthn\Event\CanDispatchEvents;
use _ContaoManager\Webauthn\Event\NullEventDispatcher;
use _ContaoManager\Webauthn\Exception\AttestationStatementLoadingException;
use _ContaoManager\Webauthn\Exception\AttestationStatementVerificationException;
use _ContaoManager\Webauthn\Exception\InvalidAttestationStatementException;
use _ContaoManager\Webauthn\MetadataService\CertificateChain\CertificateToolbox;
use _ContaoManager\Webauthn\StringStream;
use _ContaoManager\Webauthn\TrustPath\CertificateTrustPath;
use function array_key_exists;
use function count;
use function is_array;
use function openssl_pkey_get_public;
use function openssl_verify;
use function sprintf;
use const OPENSSL_ALGO_SHA256;
final class FidoU2FAttestationStatementSupport implements AttestationStatementSupport, CanDispatchEvents
{
    private readonly Decoder $decoder;
    private EventDispatcherInterface $dispatcher;
    public function __construct()
    {
        $this->decoder = Decoder::create();
        $this->dispatcher = new NullEventDispatcher();
    }
    public function setEventDispatcher(EventDispatcherInterface $eventDispatcher): void
    {
        $this->dispatcher = $eventDispatcher;
    }
    public static function create(): self
    {
        return new self();
    }
    public function name(): string
    {
        return 'fido-u2f';
    }
    /**
     * @param array<string, mixed> $attestation
     */
    public function load(array $attestation): AttestationStatement
    {
        array_key_exists('attStmt', $attestation) || throw AttestationStatementLoadingException::create($attestation, 'Invalid attestation object');
        foreach (['sig', 'x5c'] as $key) {
            array_key_exists($key, $attestation['attStmt']) || throw AttestationStatementLoadingException::create($attestation, sprintf('The attestation statement value "%s" is missing.', $key));
        }
        $certificates = $attestation['attStmt']['x5c'];
        is_array($certificates) || throw AttestationStatementLoadingException::create($attestation, 'The attestation statement value "x5c" must be a list with one certificate.');
        count($certificates) === 1 || throw AttestationStatementLoadingException::create($attestation, 'The attestation statement value "x5c" must be a list with one certificate.');
        reset($certificates);
        $certificates = CertificateToolbox::convertAllDERToPEM($certificates);
        $this->checkCertificate($certificates[0]);
        $attestationStatement = AttestationStatement::createBasic($attestation['fmt'], $attestation['attStmt'], CertificateTrustPath::create($certificates));
        $this->dispatcher->dispatch(AttestationStatementLoaded::create($attestationStatement));
        return $attestationStatement;
    }
    public function isValid(string $clientDataJSONHash, AttestationStatement $attestationStatement, AuthenticatorData $authenticatorData): bool
    {
        $authenticatorData->attestedCredentialData?->aaguid->__toString() === '00000000-0000-0000-0000-000000000000' || throw InvalidAttestationStatementException::create($attestationStatement, 'Invalid AAGUID for fido-u2f attestation statement. Shall be "00000000-0000-0000-0000-000000000000"');
        $trustPath = $attestationStatement->trustPath;
        $trustPath instanceof CertificateTrustPath || throw InvalidAttestationStatementException::create($attestationStatement, 'Invalid trust path');
        $dataToVerify = "\x00";
        $dataToVerify .= $authenticatorData->rpIdHash;
        $dataToVerify .= $clientDataJSONHash;
        $dataToVerify .= $authenticatorData->attestedCredentialData->credentialId;
        $dataToVerify .= $this->extractPublicKey($authenticatorData->attestedCredentialData->credentialPublicKey);
        return openssl_verify($dataToVerify, $attestationStatement->get('sig'), $trustPath->certificates[0], OPENSSL_ALGO_SHA256) === 1;
    }
    private function extractPublicKey(?string $publicKey): string
    {
        $publicKey !== null || throw AttestationStatementVerificationException::create('The attested credential data does not contain a valid public key.');
        $publicKeyStream = new StringStream($publicKey);
        $coseKey = $this->decoder->decode($publicKeyStream);
        $publicKeyStream->isEOF() || throw AttestationStatementVerificationException::create('Invalid public key. Presence of extra bytes.');
        $publicKeyStream->close();
        $coseKey instanceof MapObject || throw AttestationStatementVerificationException::create('The attested credential data does not contain a valid public key.');
        $coseKey = $coseKey->normalize();
        $ec2Key = new Ec2Key($coseKey + [Ec2Key::TYPE => 2, Ec2Key::DATA_CURVE => Ec2Key::CURVE_P256]);
        return "\x04" . $ec2Key->x() . $ec2Key->y();
    }
    private function checkCertificate(string $publicKey): void
    {
        try {
            $resource = openssl_pkey_get_public($publicKey);
            $details = openssl_pkey_get_details($resource);
        } catch (Throwable $throwable) {
            throw AttestationStatementVerificationException::create('Invalid certificate or certificate chain', $throwable);
        }
        is_array($details) || throw AttestationStatementVerificationException::create('Invalid certificate or certificate chain');
        array_key_exists('ec', $details) || throw AttestationStatementVerificationException::create('Invalid certificate or certificate chain');
        array_key_exists('curve_name', $details['ec']) || throw AttestationStatementVerificationException::create('Invalid certificate or certificate chain');
        $details['ec']['curve_name'] === 'prime256v1' || throw AttestationStatementVerificationException::create('Invalid certificate or certificate chain');
        array_key_exists('curve_oid', $details['ec']) || throw AttestationStatementVerificationException::create('Invalid certificate or certificate chain');
        $details['ec']['curve_oid'] === '1.2.840.10045.3.1.7' || throw AttestationStatementVerificationException::create('Invalid certificate or certificate chain');
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\Webauthn\AttestationStatement;

use _ContaoManager\CBOR\Decoder;
use _ContaoManager\CBOR\Normalizable;
use _ContaoManager\Cose\Key\Ec2Key;
use _ContaoManager\Cose\Key\Key;
use _ContaoManager\Cose\Key\RsaKey;
use _ContaoManager\Psr\EventDispatcher\EventDispatcherInterface;
use _ContaoManager\Webauthn\AuthenticatorData;
use _ContaoManager\Webauthn\Event\AttestationStatementLoaded;
use _ContaoManager\Webauthn\Event\CanDispatchEvents;
use _ContaoManager\Webauthn\Event\NullEventDispatcher;
use _ContaoManager\Webauthn\Exception\AttestationStatementLoadingException;
use _ContaoManager\Webauthn\Exception\AttestationStatementVerificationException;
use _ContaoManager\Webauthn\Exception\InvalidAttestationStatementException;
use _ContaoManager\Webauthn\MetadataService\CertificateChain\CertificateToolbox;
use _ContaoManager\Webauthn\StringStream;
use _ContaoManager\Webauthn\TrustPath\CertificateTrustPath;
use function array_key_exists;
use function count;
use function is_array;
use function openssl_pkey_get_public;
final class AppleAttestationStatementSupport implements AttestationStatementSupport, CanDispatchEvents
{
    private readonly Decoder $decoder;
    private EventDispatcherInterface $dispatcher;
    public function __construct()
    {
        $this->decoder = Decoder::create();
        $this->dispatcher = new NullEventDispatcher();
    }
    public function setEventDispatcher(EventDispatcherInterface $eventDispatcher): void
    {
        $this->dispatcher = $eventDispatcher;
    }
    public static function create(): self
    {
        return new self();
    }
    public function name(): string
    {
        return 'apple';
    }
    /**
     * @param array<string, mixed> $attestation
     */
    public function load(array $attestation): AttestationStatement
    {
        array_key_exists('attStmt', $attestation) || throw AttestationStatementLoadingException::create($attestation, 'Invalid attestation object');
        array_key_exists('x5c', $attestation['attStmt']) || throw AttestationStatementLoadingException::create($attestation, 'The attestation statement value "x5c" is missing.');
        $certificates = $attestation['attStmt']['x5c'];
        (is_countable($certificates) ? count($certificates) : 0) > 0 || throw AttestationStatementLoadingException::create($attestation, 'The attestation statement value "x5c" must be a list with at least one certificate.');
        $certificates = CertificateToolbox::convertAllDERToPEM($certificates);
        $attestationStatement = AttestationStatement::createAnonymizationCA($attestation['fmt'], $attestation['attStmt'], CertificateTrustPath::create($certificates));
        $this->dispatcher->dispatch(AttestationStatementLoaded::create($attestationStatement));
        return $attestationStatement;
    }
    public function isValid(string $clientDataJSONHash, AttestationStatement $attestationStatement, AuthenticatorData $authenticatorData): bool
    {
        $trustPath = $attestationStatement->trustPath;
        $trustPath instanceof CertificateTrustPath || throw InvalidAttestationStatementException::create($attestationStatement, 'Invalid trust path');
        $certificates = $trustPath->certificates;
        //Decode leaf attestation certificate
        $leaf = $certificates[0];
        $this->checkCertificateAndGetPublicKey($leaf, $clientDataJSONHash, $authenticatorData);
        return \true;
    }
    private function checkCertificateAndGetPublicKey(string $certificate, string $clientDataHash, AuthenticatorData $authenticatorData): void
    {
        $resource = openssl_pkey_get_public($certificate);
        $details = openssl_pkey_get_details($resource);
        is_array($details) || throw AttestationStatementVerificationException::create('Unable to read the certificate');
        //Check that authData publicKey matches the public key in the attestation certificate
        $attestedCredentialData = $authenticatorData->attestedCredentialData;
        $attestedCredentialData !== null || throw AttestationStatementVerificationException::create('No attested credential data found');
        $publicKeyData = $attestedCredentialData->credentialPublicKey;
        $publicKeyData !== null || throw AttestationStatementVerificationException::create('No attested public key found');
        $publicDataStream = new StringStream($publicKeyData);
        $coseKey = $this->decoder->decode($publicDataStream);
        $coseKey instanceof Normalizable || throw AttestationStatementVerificationException::create('Invalid attested public key found');
        $publicDataStream->isEOF() || throw AttestationStatementVerificationException::create('Invalid public key data. Presence of extra bytes.');
        $publicDataStream->close();
        $publicKey = Key::createFromData($coseKey->normalize());
        $publicKey instanceof Ec2Key || $publicKey instanceof RsaKey || throw AttestationStatementVerificationException::create('Unsupported key type');
        //We check the attested key corresponds to the key in the certificate
        $publicKey->asPEM() === $details['key'] || throw AttestationStatementVerificationException::create('Invalid key');
        /*---------------------------*/
        $certDetails = openssl_x509_parse($certificate);
        //Find Apple Extension with OID "1.2.840.113635.100.8.2" in certificate extensions
        is_array($certDetails) || throw AttestationStatementVerificationException::create('The certificate is not valid');
        array_key_exists('extensions', $certDetails) || throw AttestationStatementVerificationException::create('The certificate has no extension');
        is_array($certDetails['extensions']) || throw AttestationStatementVerificationException::create('The certificate has no extension');
        array_key_exists('1.2.840.113635.100.8.2', $certDetails['extensions']) || throw AttestationStatementVerificationException::create('The certificate extension "1.2.840.113635.100.8.2" is missing');
        $extension = $certDetails['extensions']['1.2.840.113635.100.8.2'];
        $nonceToHash = $authenticatorData->authData . $clientDataHash;
        $nonce = hash('sha256', $nonceToHash);
        //'3024a1220420' corresponds to the Sequence+Explicitly Tagged Object + Octet Object
        '3024a1220420' . $nonce === bin2hex((string) $extension) || throw AttestationStatementVerificationException::create('The client data hash is not valid');
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\Webauthn\AttestationStatement;

use _ContaoManager\Psr\EventDispatcher\EventDispatcherInterface;
use _ContaoManager\Webauthn\AuthenticatorData;
use _ContaoManager\Webauthn\Event\AttestationStatementLoaded;
use _ContaoManager\Webauthn\Event\CanDispatchEvents;
use _ContaoManager\Webauthn\Event\NullEventDispatcher;
use _ContaoManager\Webauthn\Exception\AttestationStatementLoadingException;
use _ContaoManager\Webauthn\TrustPath\EmptyTrustPath;
use function count;
use function is_array;
use function is_string;
final class NoneAttestationStatementSupport implements AttestationStatementSupport, CanDispatchEvents
{
    private EventDispatcherInterface $dispatcher;
    public function __construct()
    {
        $this->dispatcher = new NullEventDispatcher();
    }
    public function setEventDispatcher(EventDispatcherInterface $eventDispatcher): void
    {
        $this->dispatcher = $eventDispatcher;
    }
    public static function create(): self
    {
        return new self();
    }
    public function name(): string
    {
        return 'none';
    }
    /**
     * @param array<string, mixed> $attestation
     */
    public function load(array $attestation): AttestationStatement
    {
        $format = $attestation['fmt'] ?? null;
        $attestationStatement = $attestation['attStmt'] ?? [];
        is_string($format) && $format !== '' || throw AttestationStatementLoadingException::create($attestation, 'Invalid attestation object');
        is_array($attestationStatement) && $attestationStatement === [] || throw AttestationStatementLoadingException::create($attestation, 'Invalid attestation object');
        $attestationStatement = AttestationStatement::createNone($format, $attestationStatement, EmptyTrustPath::create());
        $this->dispatcher->dispatch(AttestationStatementLoaded::create($attestationStatement));
        return $attestationStatement;
    }
    public function isValid(string $clientDataJSONHash, AttestationStatement $attestationStatement, AuthenticatorData $authenticatorData): bool
    {
        return count($attestationStatement->attStmt) === 0;
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\Webauthn\AttestationStatement;

use _ContaoManager\Webauthn\AuthenticatorData;
interface AttestationStatementSupport
{
    public function name(): string;
    /**
     * @param array<string, mixed> $attestation
     */
    public function load(array $attestation): AttestationStatement;
    public function isValid(string $clientDataJSONHash, AttestationStatement $attestationStatement, AuthenticatorData $authenticatorData): bool;
}
<?php

declare (strict_types=1);
namespace _ContaoManager\Webauthn\AttestationStatement;

use _ContaoManager\CBOR\Decoder;
use _ContaoManager\CBOR\Normalizable;
use _ContaoManager\Psr\EventDispatcher\EventDispatcherInterface;
use _ContaoManager\Psr\Log\LoggerInterface;
use _ContaoManager\Psr\Log\NullLogger;
use Throwable;
use _ContaoManager\Webauthn\AuthenticatorDataLoader;
use _ContaoManager\Webauthn\Event\AttestationObjectLoaded;
use _ContaoManager\Webauthn\Event\CanDispatchEvents;
use _ContaoManager\Webauthn\Event\NullEventDispatcher;
use _ContaoManager\Webauthn\Exception\InvalidDataException;
use _ContaoManager\Webauthn\MetadataService\CanLogData;
use _ContaoManager\Webauthn\StringStream;
use _ContaoManager\Webauthn\Util\Base64;
use function array_key_exists;
use function is_array;
class AttestationObjectLoader implements CanDispatchEvents, CanLogData
{
    private LoggerInterface $logger;
    private EventDispatcherInterface $dispatcher;
    public function __construct(private readonly AttestationStatementSupportManager $attestationStatementSupportManager)
    {
        $this->logger = new NullLogger();
        $this->dispatcher = new NullEventDispatcher();
    }
    public function setEventDispatcher(EventDispatcherInterface $eventDispatcher): void
    {
        $this->dispatcher = $eventDispatcher;
    }
    public static function create(AttestationStatementSupportManager $attestationStatementSupportManager): self
    {
        return new self($attestationStatementSupportManager);
    }
    public function load(string $data): AttestationObject
    {
        try {
            $this->logger->info('Trying to load the data', ['data' => $data]);
            $decodedData = Base64::decode($data);
            $stream = new StringStream($decodedData);
            $parsed = Decoder::create()->decode($stream);
            $this->logger->info('Loading the Attestation Statement');
            $parsed instanceof Normalizable || throw InvalidDataException::create($parsed, 'Invalid attestation object. Unexpected object.');
            $attestationObject = $parsed->normalize();
            $stream->isEOF() || throw InvalidDataException::create(null, 'Invalid attestation object. Presence of extra bytes.');
            $stream->close();
            is_array($attestationObject) || throw InvalidDataException::create($attestationObject, 'Invalid attestation object');
            array_key_exists('authData', $attestationObject) || throw InvalidDataException::create($attestationObject, 'Invalid attestation object');
            array_key_exists('fmt', $attestationObject) || throw InvalidDataException::create($attestationObject, 'Invalid attestation object');
            array_key_exists('attStmt', $attestationObject) || throw InvalidDataException::create($attestationObject, 'Invalid attestation object');
            $attestationStatementSupport = $this->attestationStatementSupportManager->get($attestationObject['fmt']);
            $attestationStatement = $attestationStatementSupport->load($attestationObject);
            $this->logger->info('Attestation Statement loaded');
            $this->logger->debug('Attestation Statement loaded', ['attestationStatement' => $attestationStatement]);
            $authData = $attestationObject['authData'];
            $authDataLoader = AuthenticatorDataLoader::create();
            $authenticatorData = $authDataLoader->load($authData);
            $attestationObject = AttestationObject::create($data, $attestationStatement, $authenticatorData);
            $this->logger->info('Attestation Object loaded');
            $this->logger->debug('Attestation Object', ['ed' => $attestationObject]);
            $this->dispatcher->dispatch(AttestationObjectLoaded::create($attestationObject));
            return $attestationObject;
        } catch (Throwable $throwable) {
            $this->logger->error('An error occurred', ['exception' => $throwable]);
            throw $throwable;
        }
    }
    public function setLogger(LoggerInterface $logger): void
    {
        $this->logger = $logger;
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\Webauthn\AttestationStatement;

use _ContaoManager\CBOR\Decoder;
use _ContaoManager\CBOR\MapObject;
use _ContaoManager\Cose\Algorithm\Manager;
use _ContaoManager\Cose\Algorithm\Signature\Signature;
use _ContaoManager\Cose\Algorithms;
use _ContaoManager\Cose\Key\Key;
use _ContaoManager\Psr\EventDispatcher\EventDispatcherInterface;
use _ContaoManager\Webauthn\AuthenticatorData;
use _ContaoManager\Webauthn\Event\AttestationStatementLoaded;
use _ContaoManager\Webauthn\Event\CanDispatchEvents;
use _ContaoManager\Webauthn\Event\NullEventDispatcher;
use _ContaoManager\Webauthn\Exception\AttestationStatementLoadingException;
use _ContaoManager\Webauthn\Exception\AttestationStatementVerificationException;
use _ContaoManager\Webauthn\Exception\InvalidAttestationStatementException;
use _ContaoManager\Webauthn\Exception\InvalidDataException;
use _ContaoManager\Webauthn\Exception\UnsupportedFeatureException;
use _ContaoManager\Webauthn\MetadataService\CertificateChain\CertificateToolbox;
use _ContaoManager\Webauthn\StringStream;
use _ContaoManager\Webauthn\TrustPath\CertificateTrustPath;
use _ContaoManager\Webauthn\TrustPath\EcdaaKeyIdTrustPath;
use _ContaoManager\Webauthn\TrustPath\EmptyTrustPath;
use _ContaoManager\Webauthn\Util\CoseSignatureFixer;
use function array_key_exists;
use function count;
use function in_array;
use function is_array;
use function is_string;
use function openssl_verify;
final class PackedAttestationStatementSupport implements AttestationStatementSupport, CanDispatchEvents
{
    private readonly Decoder $decoder;
    private EventDispatcherInterface $dispatcher;
    public function __construct(private readonly Manager $algorithmManager)
    {
        $this->decoder = Decoder::create();
        $this->dispatcher = new NullEventDispatcher();
    }
    public function setEventDispatcher(EventDispatcherInterface $eventDispatcher): void
    {
        $this->dispatcher = $eventDispatcher;
    }
    public static function create(Manager $algorithmManager): self
    {
        return new self($algorithmManager);
    }
    public function name(): string
    {
        return 'packed';
    }
    /**
     * @param array<string, mixed> $attestation
     */
    public function load(array $attestation): AttestationStatement
    {
        array_key_exists('sig', $attestation['attStmt']) || throw AttestationStatementLoadingException::create($attestation, 'The attestation statement value "sig" is missing.');
        array_key_exists('alg', $attestation['attStmt']) || throw AttestationStatementLoadingException::create($attestation, 'The attestation statement value "alg" is missing.');
        is_string($attestation['attStmt']['sig']) || throw AttestationStatementLoadingException::create($attestation, 'The attestation statement value "sig" is missing.');
        return match (\true) {
            array_key_exists('x5c', $attestation['attStmt']) => $this->loadBasicType($attestation),
            array_key_exists('ecdaaKeyId', $attestation['attStmt']) => $this->loadEcdaaType($attestation['attStmt']),
            default => $this->loadEmptyType($attestation),
        };
    }
    public function isValid(string $clientDataJSONHash, AttestationStatement $attestationStatement, AuthenticatorData $authenticatorData): bool
    {
        $trustPath = $attestationStatement->trustPath;
        return match (\true) {
            $trustPath instanceof CertificateTrustPath => $this->processWithCertificate($clientDataJSONHash, $attestationStatement, $authenticatorData, $trustPath),
            $trustPath instanceof EcdaaKeyIdTrustPath => $this->processWithECDAA(),
            $trustPath instanceof EmptyTrustPath => $this->processWithSelfAttestation($clientDataJSONHash, $attestationStatement, $authenticatorData),
            default => throw InvalidAttestationStatementException::create($attestationStatement, 'Unsupported attestation statement'),
        };
    }
    /**
     * @param mixed[] $attestation
     */
    private function loadBasicType(array $attestation): AttestationStatement
    {
        $certificates = $attestation['attStmt']['x5c'];
        is_array($certificates) || throw AttestationStatementVerificationException::create('The attestation statement value "x5c" must be a list with at least one certificate.');
        count($certificates) > 0 || throw AttestationStatementVerificationException::create('The attestation statement value "x5c" must be a list with at least one certificate.');
        $certificates = CertificateToolbox::convertAllDERToPEM($certificates);
        $attestationStatement = AttestationStatement::createBasic($attestation['fmt'], $attestation['attStmt'], CertificateTrustPath::create($certificates));
        $this->dispatcher->dispatch(AttestationStatementLoaded::create($attestationStatement));
        return $attestationStatement;
    }
    /**
     * @param array<string, mixed> $attestation
     */
    private function loadEcdaaType(array $attestation): AttestationStatement
    {
        $ecdaaKeyId = $attestation['attStmt']['ecdaaKeyId'];
        is_string($ecdaaKeyId) || throw AttestationStatementVerificationException::create('The attestation statement value "ecdaaKeyId" is invalid.');
        $attestationStatement = AttestationStatement::createEcdaa($attestation['fmt'], $attestation['attStmt'], new EcdaaKeyIdTrustPath($attestation['ecdaaKeyId']));
        $this->dispatcher->dispatch(AttestationStatementLoaded::create($attestationStatement));
        return $attestationStatement;
    }
    /**
     * @param mixed[] $attestation
     */
    private function loadEmptyType(array $attestation): AttestationStatement
    {
        $attestationStatement = AttestationStatement::createSelf($attestation['fmt'], $attestation['attStmt'], EmptyTrustPath::create());
        $this->dispatcher->dispatch(AttestationStatementLoaded::create($attestationStatement));
        return $attestationStatement;
    }
    private function checkCertificate(string $attestnCert, AuthenticatorData $authenticatorData): void
    {
        $parsed = openssl_x509_parse($attestnCert);
        is_array($parsed) || throw AttestationStatementVerificationException::create('Invalid certificate');
        //Check version
        isset($parsed['version']) || throw AttestationStatementVerificationException::create('Invalid certificate version');
        $parsed['version'] === 2 || throw AttestationStatementVerificationException::create('Invalid certificate version');
        //Check subject field
        isset($parsed['name']) || throw AttestationStatementVerificationException::create('Invalid certificate name. The Subject Organization Unit must be "Authenticator Attestation"');
        str_contains((string) $parsed['name'], '/OU=Authenticator Attestation') || throw AttestationStatementVerificationException::create('Invalid certificate name. The Subject Organization Unit must be "Authenticator Attestation"');
        //Check extensions
        isset($parsed['extensions']) || throw AttestationStatementVerificationException::create('Certificate extensions are missing');
        is_array($parsed['extensions']) || throw AttestationStatementVerificationException::create('Certificate extensions are missing');
        //Check certificate is not a CA cert
        isset($parsed['extensions']['basicConstraints']) || throw AttestationStatementVerificationException::create('The Basic Constraints extension must have the CA component set to false');
        $parsed['extensions']['basicConstraints'] === 'CA:FALSE' || throw AttestationStatementVerificationException::create('The Basic Constraints extension must have the CA component set to false');
        $attestedCredentialData = $authenticatorData->attestedCredentialData;
        $attestedCredentialData !== null || throw AttestationStatementVerificationException::create('No attested credential available');
        // id-fido-gen-ce-aaguid OID check
        if (in_array('1.3.6.1.4.1.45724.1.1.4', $parsed['extensions'], \true)) {
            hash_equals($attestedCredentialData->aaguid->toBinary(), $parsed['extensions']['1.3.6.1.4.1.45724.1.1.4']) || throw AttestationStatementVerificationException::create('The value of the "aaguid" does not match with the certificate');
        }
    }
    private function processWithCertificate(string $clientDataJSONHash, AttestationStatement $attestationStatement, AuthenticatorData $authenticatorData, CertificateTrustPath $trustPath): bool
    {
        $certificates = $trustPath->certificates;
        // Check leaf certificate
        $this->checkCertificate($certificates[0], $authenticatorData);
        // Get the COSE algorithm identifier and the corresponding OpenSSL one
        $coseAlgorithmIdentifier = (int) $attestationStatement->get('alg');
        $opensslAlgorithmIdentifier = Algorithms::getOpensslAlgorithmFor($coseAlgorithmIdentifier);
        // Verification of the signature
        $signedData = $authenticatorData->authData . $clientDataJSONHash;
        $result = openssl_verify($signedData, $attestationStatement->get('sig'), $certificates[0], $opensslAlgorithmIdentifier);
        return $result === 1;
    }
    private function processWithECDAA(): never
    {
        throw UnsupportedFeatureException::create('ECDAA not supported');
    }
    private function processWithSelfAttestation(string $clientDataJSONHash, AttestationStatement $attestationStatement, AuthenticatorData $authenticatorData): bool
    {
        $attestedCredentialData = $authenticatorData->attestedCredentialData;
        $attestedCredentialData !== null || throw AttestationStatementVerificationException::create('No attested credential available');
        $credentialPublicKey = $attestedCredentialData->credentialPublicKey;
        $credentialPublicKey !== null || throw AttestationStatementVerificationException::create('No credential public key available');
        $publicKeyStream = new StringStream($credentialPublicKey);
        $publicKey = $this->decoder->decode($publicKeyStream);
        $publicKeyStream->isEOF() || throw AttestationStatementVerificationException::create('Invalid public key. Presence of extra bytes.');
        $publicKeyStream->close();
        $publicKey instanceof MapObject || throw AttestationStatementVerificationException::create('The attested credential data does not contain a valid public key.');
        $publicKey = $publicKey->normalize();
        $publicKey = new Key($publicKey);
        $publicKey->alg() === (int) $attestationStatement->get('alg') || throw AttestationStatementVerificationException::create('The algorithm of the attestation statement and the key are not identical.');
        $dataToVerify = $authenticatorData->authData . $clientDataJSONHash;
        $algorithm = $this->algorithmManager->get((int) $attestationStatement->get('alg'));
        if (!$algorithm instanceof Signature) {
            throw InvalidDataException::create($algorithm, 'Invalid algorithm');
        }
        $signature = CoseSignatureFixer::fix($attestationStatement->get('sig'), $algorithm);
        return $algorithm->verify($dataToVerify, $publicKey, $signature);
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\Webauthn\AttestationStatement;

use _ContaoManager\Webauthn\AuthenticatorData;
use _ContaoManager\Webauthn\MetadataService\Statement\MetadataStatement;
class AttestationObject
{
    public ?MetadataStatement $metadataStatement = null;
    public function __construct(public readonly string $rawAttestationObject, public AttestationStatement $attStmt, public readonly AuthenticatorData $authData)
    {
    }
    public static function create(string $rawAttestationObject, AttestationStatement $attStmt, AuthenticatorData $authData): self
    {
        return new self($rawAttestationObject, $attStmt, $authData);
    }
    /**
     * @deprecated since 4.7.0. Please use the property directly.
     * @infection-ignore-all
     */
    public function getRawAttestationObject(): string
    {
        return $this->rawAttestationObject;
    }
    /**
     * @deprecated since 4.7.0. Please use the property directly.
     * @infection-ignore-all
     */
    public function getAttStmt(): AttestationStatement
    {
        return $this->attStmt;
    }
    /**
     * @deprecated since 4.7.0. Please use the property directly.
     * @infection-ignore-all
     */
    public function setAttStmt(AttestationStatement $attStmt): void
    {
        $this->attStmt = $attStmt;
    }
    /**
     * @deprecated since 4.7.0. Please use the property directly.
     * @infection-ignore-all
     */
    public function getAuthData(): AuthenticatorData
    {
        return $this->authData;
    }
    /**
     * @deprecated since 4.7.0. Please use the property directly.
     * @infection-ignore-all
     */
    public function getMetadataStatement(): ?MetadataStatement
    {
        return $this->metadataStatement;
    }
    /**
     * @deprecated since 4.7.0. Please use the property directly.
     * @infection-ignore-all
     */
    public function setMetadataStatement(MetadataStatement $metadataStatement): self
    {
        $this->metadataStatement = $metadataStatement;
        return $this;
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\Webauthn\AttestationStatement;

use _ContaoManager\CBOR\Decoder;
use _ContaoManager\CBOR\Normalizable;
use _ContaoManager\Cose\Algorithms;
use _ContaoManager\Cose\Key\Ec2Key;
use _ContaoManager\Cose\Key\Key;
use _ContaoManager\Cose\Key\RsaKey;
use _ContaoManager\Psr\EventDispatcher\EventDispatcherInterface;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Constructed\Sequence;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Primitive\OctetString;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Tagged\ExplicitTagging;
use _ContaoManager\Webauthn\AuthenticatorData;
use _ContaoManager\Webauthn\Event\AttestationStatementLoaded;
use _ContaoManager\Webauthn\Event\CanDispatchEvents;
use _ContaoManager\Webauthn\Event\NullEventDispatcher;
use _ContaoManager\Webauthn\Exception\AttestationStatementLoadingException;
use _ContaoManager\Webauthn\Exception\AttestationStatementVerificationException;
use _ContaoManager\Webauthn\Exception\InvalidAttestationStatementException;
use _ContaoManager\Webauthn\MetadataService\CertificateChain\CertificateToolbox;
use _ContaoManager\Webauthn\StringStream;
use _ContaoManager\Webauthn\TrustPath\CertificateTrustPath;
use function array_key_exists;
use function count;
use function is_array;
use function openssl_pkey_get_public;
use function openssl_verify;
use function sprintf;
final class AndroidKeyAttestationStatementSupport implements AttestationStatementSupport, CanDispatchEvents
{
    private readonly Decoder $decoder;
    private EventDispatcherInterface $dispatcher;
    public function __construct()
    {
        $this->decoder = Decoder::create();
        $this->dispatcher = new NullEventDispatcher();
    }
    public function setEventDispatcher(EventDispatcherInterface $eventDispatcher): void
    {
        $this->dispatcher = $eventDispatcher;
    }
    public static function create(): self
    {
        return new self();
    }
    public function name(): string
    {
        return 'android-key';
    }
    /**
     * @param array<string, mixed> $attestation
     */
    public function load(array $attestation): AttestationStatement
    {
        array_key_exists('attStmt', $attestation) || throw AttestationStatementLoadingException::create($attestation);
        foreach (['sig', 'x5c', 'alg'] as $key) {
            array_key_exists($key, $attestation['attStmt']) || throw AttestationStatementLoadingException::create($attestation, sprintf('The attestation statement value "%s" is missing.', $key));
        }
        $certificates = $attestation['attStmt']['x5c'];
        (is_countable($certificates) ? count($certificates) : 0) > 0 || throw AttestationStatementLoadingException::create($attestation, 'The attestation statement value "x5c" must be a list with at least one certificate.');
        $certificates = CertificateToolbox::convertAllDERToPEM($certificates);
        $attestationStatement = AttestationStatement::createBasic($attestation['fmt'], $attestation['attStmt'], CertificateTrustPath::create($certificates));
        $this->dispatcher->dispatch(AttestationStatementLoaded::create($attestationStatement));
        return $attestationStatement;
    }
    public function isValid(string $clientDataJSONHash, AttestationStatement $attestationStatement, AuthenticatorData $authenticatorData): bool
    {
        $trustPath = $attestationStatement->trustPath;
        $trustPath instanceof CertificateTrustPath || throw InvalidAttestationStatementException::create($attestationStatement, 'Invalid trust path. Shall contain certificates.');
        $certificates = $trustPath->certificates;
        //Decode leaf attestation certificate
        $leaf = $certificates[0];
        $this->checkCertificate($leaf, $clientDataJSONHash, $authenticatorData);
        $signedData = $authenticatorData->authData . $clientDataJSONHash;
        $alg = $attestationStatement->get('alg');
        return openssl_verify($signedData, $attestationStatement->get('sig'), $leaf, Algorithms::getOpensslAlgorithmFor((int) $alg)) === 1;
    }
    private function checkCertificate(string $certificate, string $clientDataHash, AuthenticatorData $authenticatorData): void
    {
        $resource = openssl_pkey_get_public($certificate);
        $details = openssl_pkey_get_details($resource);
        is_array($details) || throw AttestationStatementVerificationException::create('Unable to read the certificate');
        //Check that authData publicKey matches the public key in the attestation certificate
        $attestedCredentialData = $authenticatorData->attestedCredentialData;
        $attestedCredentialData !== null || throw AttestationStatementVerificationException::create('No attested credential data found');
        $publicKeyData = $attestedCredentialData->credentialPublicKey;
        $publicKeyData !== null || throw AttestationStatementVerificationException::create('No attested public key found');
        $publicDataStream = new StringStream($publicKeyData);
        $coseKey = $this->decoder->decode($publicDataStream);
        $coseKey instanceof Normalizable || throw AttestationStatementVerificationException::create('Invalid attested public key found');
        $publicDataStream->isEOF() || throw AttestationStatementVerificationException::create('Invalid public key data. Presence of extra bytes.');
        $publicDataStream->close();
        $publicKey = Key::createFromData($coseKey->normalize());
        $publicKey instanceof Ec2Key || $publicKey instanceof RsaKey || throw AttestationStatementVerificationException::create('Unsupported key type');
        $publicKey->asPEM() === $details['key'] || throw AttestationStatementVerificationException::create('Invalid key');
        /*---------------------------*/
        $certDetails = openssl_x509_parse($certificate);
        //Find Android KeyStore Extension with OID "1.3.6.1.4.1.11129.2.1.17" in certificate extensions
        is_array($certDetails) || throw AttestationStatementVerificationException::create('The certificate is not valid');
        array_key_exists('extensions', $certDetails) || throw AttestationStatementVerificationException::create('The certificate has no extension');
        is_array($certDetails['extensions']) || throw AttestationStatementVerificationException::create('The certificate has no extension');
        array_key_exists('1.3.6.1.4.1.11129.2.1.17', $certDetails['extensions']) || throw AttestationStatementVerificationException::create('The certificate extension "1.3.6.1.4.1.11129.2.1.17" is missing');
        $extension = $certDetails['extensions']['1.3.6.1.4.1.11129.2.1.17'];
        $extensionAsAsn1 = Sequence::fromDER($extension);
        $extensionAsAsn1->has(4);
        //Check that attestationChallenge is set to the clientDataHash.
        $extensionAsAsn1->has(4) || throw AttestationStatementVerificationException::create('The certificate extension "1.3.6.1.4.1.11129.2.1.17" is invalid');
        $ext = $extensionAsAsn1->at(4)->asElement();
        $ext instanceof OctetString || throw AttestationStatementVerificationException::create('The certificate extension "1.3.6.1.4.1.11129.2.1.17" is invalid');
        $clientDataHash === $ext->string() || throw AttestationStatementVerificationException::create('The client data hash is not valid');
        //Check that both teeEnforced and softwareEnforced structures don't contain allApplications(600) tag.
        $extensionAsAsn1->has(6) || throw AttestationStatementVerificationException::create('The certificate extension "1.3.6.1.4.1.11129.2.1.17" is invalid');
        $softwareEnforcedFlags = $extensionAsAsn1->at(6)->asElement();
        $softwareEnforcedFlags instanceof Sequence || throw AttestationStatementVerificationException::create('The certificate extension "1.3.6.1.4.1.11129.2.1.17" is invalid');
        $this->checkAbsenceOfAllApplicationsTag($softwareEnforcedFlags);
        $extensionAsAsn1->has(7) || throw AttestationStatementVerificationException::create('The certificate extension "1.3.6.1.4.1.11129.2.1.17" is invalid');
        $teeEnforcedFlags = $extensionAsAsn1->at(7)->asElement();
        $teeEnforcedFlags instanceof Sequence || throw AttestationStatementVerificationException::create('The certificate extension "1.3.6.1.4.1.11129.2.1.17" is invalid');
        $this->checkAbsenceOfAllApplicationsTag($teeEnforcedFlags);
    }
    private function checkAbsenceOfAllApplicationsTag(Sequence $sequence): void
    {
        foreach ($sequence->elements() as $tag) {
            $tag->asElement() instanceof ExplicitTagging || throw AttestationStatementVerificationException::create('Invalid tag');
            $tag->asElement()->tag() !== 600 || throw AttestationStatementVerificationException::create('Forbidden tag 600 found');
        }
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\Webauthn\AttestationStatement;

use _ContaoManager\Webauthn\Exception\InvalidDataException;
use function array_key_exists;
use function sprintf;
class AttestationStatementSupportManager
{
    /**
     * @param AttestationStatementSupport[] $attestationStatementSupports
     */
    public function __construct(private array $attestationStatementSupports = [])
    {
        $this->add(new NoneAttestationStatementSupport());
        foreach ($attestationStatementSupports as $attestationStatementSupport) {
            $this->add($attestationStatementSupport);
        }
    }
    /**
     * @param AttestationStatementSupport[] $attestationStatementSupports
     */
    public static function create(array $attestationStatementSupports = []): self
    {
        return new self($attestationStatementSupports);
    }
    public function add(AttestationStatementSupport $attestationStatementSupport): void
    {
        $this->attestationStatementSupports[$attestationStatementSupport->name()] = $attestationStatementSupport;
    }
    public function has(string $name): bool
    {
        return array_key_exists($name, $this->attestationStatementSupports);
    }
    public function get(string $name): AttestationStatementSupport
    {
        $this->has($name) || throw InvalidDataException::create($name, sprintf('The attestation statement format "%s" is not supported.', $name));
        return $this->attestationStatementSupports[$name];
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\Webauthn\AttestationStatement;

use _ContaoManager\CBOR\Decoder;
use _ContaoManager\CBOR\MapObject;
use _ContaoManager\Cose\Algorithms;
use _ContaoManager\Cose\Key\Ec2Key;
use _ContaoManager\Cose\Key\Key;
use _ContaoManager\Cose\Key\OkpKey;
use _ContaoManager\Cose\Key\RsaKey;
use DateTimeImmutable;
use DateTimeZone;
use _ContaoManager\Lcobucci\Clock\Clock;
use _ContaoManager\Lcobucci\Clock\SystemClock;
use _ContaoManager\ParagonIE\ConstantTime\Base64UrlSafe;
use _ContaoManager\Psr\Clock\ClockInterface;
use _ContaoManager\Psr\EventDispatcher\EventDispatcherInterface;
use _ContaoManager\Webauthn\AuthenticatorData;
use _ContaoManager\Webauthn\Event\AttestationStatementLoaded;
use _ContaoManager\Webauthn\Event\CanDispatchEvents;
use _ContaoManager\Webauthn\Event\NullEventDispatcher;
use _ContaoManager\Webauthn\Exception\AttestationStatementLoadingException;
use _ContaoManager\Webauthn\Exception\AttestationStatementVerificationException;
use _ContaoManager\Webauthn\Exception\InvalidAttestationStatementException;
use _ContaoManager\Webauthn\Exception\UnsupportedFeatureException;
use _ContaoManager\Webauthn\MetadataService\CertificateChain\CertificateToolbox;
use _ContaoManager\Webauthn\StringStream;
use _ContaoManager\Webauthn\TrustPath\CertificateTrustPath;
use _ContaoManager\Webauthn\TrustPath\EcdaaKeyIdTrustPath;
use function array_key_exists;
use function count;
use function in_array;
use function is_array;
use function is_int;
use function openssl_verify;
use function sprintf;
use function unpack;
final class TPMAttestationStatementSupport implements AttestationStatementSupport, CanDispatchEvents
{
    private readonly Clock|ClockInterface $clock;
    private EventDispatcherInterface $dispatcher;
    public function __construct(null|Clock|ClockInterface $clock = null)
    {
        if ($clock === null) {
            trigger_deprecation('web-auth/metadata-service', '4.5.0', 'The parameter "$clock" will become mandatory in 5.0.0. Please set a valid PSR Clock implementation instead of "null".');
            $clock = new SystemClock(new DateTimeZone('UTC'));
        }
        $this->clock = $clock;
        $this->dispatcher = new NullEventDispatcher();
    }
    public function setEventDispatcher(EventDispatcherInterface $eventDispatcher): void
    {
        $this->dispatcher = $eventDispatcher;
    }
    public static function create(null|Clock|ClockInterface $clock = null): self
    {
        return new self($clock);
    }
    public function name(): string
    {
        return 'tpm';
    }
    /**
     * @param array<string, mixed> $attestation
     */
    public function load(array $attestation): AttestationStatement
    {
        array_key_exists('attStmt', $attestation) || throw AttestationStatementLoadingException::create($attestation, 'Invalid attestation object');
        !array_key_exists('ecdaaKeyId', $attestation['attStmt']) || throw AttestationStatementLoadingException::create($attestation, 'ECDAA not supported');
        foreach (['ver', 'ver', 'sig', 'alg', 'certInfo', 'pubArea'] as $key) {
            array_key_exists($key, $attestation['attStmt']) || throw AttestationStatementLoadingException::create($attestation, sprintf('The attestation statement value "%s" is missing.', $key));
        }
        $attestation['attStmt']['ver'] === '2.0' || throw AttestationStatementLoadingException::create($attestation, 'Invalid attestation object');
        $certInfo = $this->checkCertInfo($attestation['attStmt']['certInfo']);
        bin2hex((string) $certInfo['type']) === '8017' || throw AttestationStatementLoadingException::create($attestation, 'Invalid attestation object');
        $pubArea = $this->checkPubArea($attestation['attStmt']['pubArea']);
        $pubAreaAttestedNameAlg = mb_substr((string) $certInfo['attestedName'], 0, 2, '8bit');
        $pubAreaHash = hash($this->getTPMHash($pubAreaAttestedNameAlg), (string) $attestation['attStmt']['pubArea'], \true);
        $attestedName = $pubAreaAttestedNameAlg . $pubAreaHash;
        $attestedName === $certInfo['attestedName'] || throw AttestationStatementLoadingException::create($attestation, 'Invalid attested name');
        $attestation['attStmt']['parsedCertInfo'] = $certInfo;
        $attestation['attStmt']['parsedPubArea'] = $pubArea;
        $certificates = CertificateToolbox::convertAllDERToPEM($attestation['attStmt']['x5c']);
        count($certificates) > 0 || throw AttestationStatementLoadingException::create($attestation, 'The attestation statement value "x5c" must be a list with at least one certificate.');
        $attestationStatement = AttestationStatement::createAttCA($this->name(), $attestation['attStmt'], CertificateTrustPath::create($certificates));
        $this->dispatcher->dispatch(AttestationStatementLoaded::create($attestationStatement));
        return $attestationStatement;
    }
    public function isValid(string $clientDataJSONHash, AttestationStatement $attestationStatement, AuthenticatorData $authenticatorData): bool
    {
        $attToBeSigned = $authenticatorData->authData . $clientDataJSONHash;
        $attToBeSignedHash = hash(Algorithms::getHashAlgorithmFor((int) $attestationStatement->get('alg')), $attToBeSigned, \true);
        $attestationStatement->get('parsedCertInfo')['extraData'] === $attToBeSignedHash || throw InvalidAttestationStatementException::create($attestationStatement, 'Invalid attestation hash');
        $credentialPublicKey = $authenticatorData->attestedCredentialData?->credentialPublicKey;
        $credentialPublicKey !== null || throw InvalidAttestationStatementException::create($attestationStatement, 'Not credential public key available in the attested credential data');
        $this->checkUniquePublicKey($attestationStatement->get('parsedPubArea')['unique'], $credentialPublicKey);
        return match (\true) {
            $attestationStatement->trustPath instanceof CertificateTrustPath => $this->processWithCertificate($attestationStatement, $authenticatorData),
            $attestationStatement->trustPath instanceof EcdaaKeyIdTrustPath => $this->processWithECDAA(),
            default => throw InvalidAttestationStatementException::create($attestationStatement, 'Unsupported attestation statement'),
        };
    }
    private function checkUniquePublicKey(string $unique, string $cborPublicKey): void
    {
        $cborDecoder = Decoder::create();
        $publicKey = $cborDecoder->decode(new StringStream($cborPublicKey));
        $publicKey instanceof MapObject || throw AttestationStatementVerificationException::create('Invalid public key');
        $key = Key::create($publicKey->normalize());
        switch ($key->type()) {
            case Key::TYPE_OKP:
                $uniqueFromKey = (new OkpKey($key->getData()))->x();
                break;
            case Key::TYPE_EC2:
                $ec2Key = new Ec2Key($key->getData());
                $uniqueFromKey = "\x04" . $ec2Key->x() . $ec2Key->y();
                break;
            case Key::TYPE_RSA:
                $uniqueFromKey = (new RsaKey($key->getData()))->n();
                break;
            default:
                throw AttestationStatementVerificationException::create('Invalid or unsupported key type.');
        }
        $unique === $uniqueFromKey || throw AttestationStatementVerificationException::create('Invalid pubArea.unique value');
    }
    /**
     * @return mixed[]
     */
    private function checkCertInfo(string $data): array
    {
        $certInfo = new StringStream($data);
        $magic = $certInfo->read(4);
        bin2hex($magic) === 'ff544347' || throw AttestationStatementVerificationException::create('Invalid attestation object');
        $type = $certInfo->read(2);
        $qualifiedSignerLength = unpack('n', $certInfo->read(2))[1];
        $qualifiedSigner = $certInfo->read($qualifiedSignerLength);
        //Ignored
        $extraDataLength = unpack('n', $certInfo->read(2))[1];
        $extraData = $certInfo->read($extraDataLength);
        $clockInfo = $certInfo->read(17);
        //Ignore
        $firmwareVersion = $certInfo->read(8);
        $attestedNameLength = unpack('n', $certInfo->read(2))[1];
        $attestedName = $certInfo->read($attestedNameLength);
        $attestedQualifiedNameLength = unpack('n', $certInfo->read(2))[1];
        $attestedQualifiedName = $certInfo->read($attestedQualifiedNameLength);
        //Ignore
        $certInfo->isEOF() || throw AttestationStatementVerificationException::create('Invalid certificate information. Presence of extra bytes.');
        $certInfo->close();
        return ['magic' => $magic, 'type' => $type, 'qualifiedSigner' => $qualifiedSigner, 'extraData' => $extraData, 'clockInfo' => $clockInfo, 'firmwareVersion' => $firmwareVersion, 'attestedName' => $attestedName, 'attestedQualifiedName' => $attestedQualifiedName];
    }
    /**
     * @return mixed[]
     */
    private function checkPubArea(string $data): array
    {
        $pubArea = new StringStream($data);
        $type = $pubArea->read(2);
        $nameAlg = $pubArea->read(2);
        $objectAttributes = $pubArea->read(4);
        $authPolicyLength = unpack('n', $pubArea->read(2))[1];
        $authPolicy = $pubArea->read($authPolicyLength);
        $parameters = $this->getParameters($type, $pubArea);
        $unique = $this->getUnique($type, $pubArea);
        $pubArea->isEOF() || throw AttestationStatementVerificationException::create('Invalid public area. Presence of extra bytes.');
        $pubArea->close();
        return ['type' => $type, 'nameAlg' => $nameAlg, 'objectAttributes' => $objectAttributes, 'authPolicy' => $authPolicy, 'parameters' => $parameters, 'unique' => $unique];
    }
    /**
     * @return mixed[]
     */
    private function getParameters(string $type, StringStream $stream): array
    {
        return match (bin2hex($type)) {
            '0001' => ['symmetric' => $stream->read(2), 'scheme' => $stream->read(2), 'keyBits' => unpack('n', $stream->read(2))[1], 'exponent' => $this->getExponent($stream->read(4))],
            '0023' => ['symmetric' => $stream->read(2), 'scheme' => $stream->read(2), 'curveId' => $stream->read(2), 'kdf' => $stream->read(2)],
            default => throw AttestationStatementVerificationException::create('Unsupported type'),
        };
    }
    private function getUnique(string $type, StringStream $stream): string
    {
        switch (bin2hex($type)) {
            case '0001':
                $uniqueLength = unpack('n', $stream->read(2))[1];
                return $stream->read($uniqueLength);
            case '0023':
                $xLen = unpack('n', $stream->read(2))[1];
                $x = $stream->read($xLen);
                $yLen = unpack('n', $stream->read(2))[1];
                $y = $stream->read($yLen);
                return "\x04" . $x . $y;
            default:
                throw AttestationStatementVerificationException::create('Unsupported type');
        }
    }
    private function getExponent(string $exponent): string
    {
        return bin2hex($exponent) === '00000000' ? Base64UrlSafe::decodeNoPadding('AQAB') : $exponent;
    }
    private function getTPMHash(string $nameAlg): string
    {
        return match (bin2hex($nameAlg)) {
            '0004' => 'sha1',
            '000b' => 'sha256',
            '000c' => 'sha384',
            '000d' => 'sha512',
            default => throw AttestationStatementVerificationException::create('Unsupported hash algorithm'),
        };
    }
    private function processWithCertificate(AttestationStatement $attestationStatement, AuthenticatorData $authenticatorData): bool
    {
        $trustPath = $attestationStatement->trustPath;
        $trustPath instanceof CertificateTrustPath || throw AttestationStatementVerificationException::create('Invalid trust path');
        $certificates = $trustPath->certificates;
        // Check certificate CA chain and returns the Attestation Certificate
        $this->checkCertificate($certificates[0], $authenticatorData);
        // Get the COSE algorithm identifier and the corresponding OpenSSL one
        $coseAlgorithmIdentifier = (int) $attestationStatement->get('alg');
        $opensslAlgorithmIdentifier = Algorithms::getOpensslAlgorithmFor($coseAlgorithmIdentifier);
        $result = openssl_verify($attestationStatement->get('certInfo'), $attestationStatement->get('sig'), $certificates[0], $opensslAlgorithmIdentifier);
        return $result === 1;
    }
    private function checkCertificate(string $attestnCert, AuthenticatorData $authenticatorData): void
    {
        $parsed = openssl_x509_parse($attestnCert);
        is_array($parsed) || throw AttestationStatementVerificationException::create('Invalid certificate');
        //Check version
        isset($parsed['version']) && $parsed['version'] === 2 || throw AttestationStatementVerificationException::create('Invalid certificate version');
        //Check subject field is empty
        isset($parsed['subject']) || throw AttestationStatementVerificationException::create('Invalid certificate name. The Subject should be empty');
        is_array($parsed['subject']) || throw AttestationStatementVerificationException::create('Invalid certificate name. The Subject should be empty');
        count($parsed['subject']) === 0 || throw AttestationStatementVerificationException::create('Invalid certificate name. The Subject should be empty');
        // Check period of validity
        array_key_exists('validFrom_time_t', $parsed) || throw AttestationStatementVerificationException::create('Invalid certificate start date.');
        is_int($parsed['validFrom_time_t']) || throw AttestationStatementVerificationException::create('Invalid certificate start date.');
        $startDate = (new DateTimeImmutable())->setTimestamp($parsed['validFrom_time_t']);
        $startDate < $this->clock->now() || throw AttestationStatementVerificationException::create('Invalid certificate start date.');
        array_key_exists('validTo_time_t', $parsed) || throw AttestationStatementVerificationException::create('Invalid certificate end date.');
        is_int($parsed['validTo_time_t']) || throw AttestationStatementVerificationException::create('Invalid certificate end date.');
        $endDate = (new DateTimeImmutable())->setTimestamp($parsed['validTo_time_t']);
        $endDate > $this->clock->now() || throw AttestationStatementVerificationException::create('Invalid certificate end date.');
        //Check extensions
        isset($parsed['extensions']) && is_array($parsed['extensions']) || throw AttestationStatementVerificationException::create('Certificate extensions are missing');
        //Check subjectAltName
        isset($parsed['extensions']['subjectAltName']) || throw AttestationStatementVerificationException::create('The "subjectAltName" is missing');
        //Check extendedKeyUsage
        isset($parsed['extensions']['extendedKeyUsage']) || throw AttestationStatementVerificationException::create('The "subjectAltName" is missing');
        $parsed['extensions']['extendedKeyUsage'] === '2.23.133.8.3' || throw AttestationStatementVerificationException::create('The "extendedKeyUsage" is invalid');
        // id-fido-gen-ce-aaguid OID check
        in_array('1.3.6.1.4.1.45724.1.1.4', $parsed['extensions'], \true) && !hash_equals($authenticatorData->attestedCredentialData?->aaguid->toBinary() ?? '', $parsed['extensions']['1.3.6.1.4.1.45724.1.1.4']) && throw AttestationStatementVerificationException::create('The value of the "aaguid" does not match with the certificate');
    }
    private function processWithECDAA(): never
    {
        throw UnsupportedFeatureException::create('ECDAA not supported');
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\Webauthn\AttestationStatement;

use JsonSerializable;
use _ContaoManager\Webauthn\Exception\InvalidDataException;
use _ContaoManager\Webauthn\TrustPath\TrustPath;
use _ContaoManager\Webauthn\TrustPath\TrustPathLoader;
use function array_key_exists;
use function sprintf;
class AttestationStatement implements JsonSerializable
{
    final public const TYPE_NONE = 'none';
    final public const TYPE_BASIC = 'basic';
    final public const TYPE_SELF = 'self';
    final public const TYPE_ATTCA = 'attca';
    /**
     * @deprecated since 4.2.0 and will be removed in 5.0.0. The ECDAA Trust Anchor does no longer exist in Webauthn specification.
     * @infection-ignore-all
     */
    final public const TYPE_ECDAA = 'ecdaa';
    final public const TYPE_ANONCA = 'anonca';
    /**
     * @param array<string, mixed> $attStmt
     */
    public function __construct(public readonly string $fmt, public readonly array $attStmt, public readonly string $type, public readonly TrustPath $trustPath)
    {
    }
    public static function create(string $fmt, array $attStmt, string $type, TrustPath $trustPath): self
    {
        return new self($fmt, $attStmt, $type, $trustPath);
    }
    /**
     * @param array<string, mixed> $attStmt
     */
    public static function createNone(string $fmt, array $attStmt, TrustPath $trustPath): self
    {
        return self::create($fmt, $attStmt, self::TYPE_NONE, $trustPath);
    }
    /**
     * @param array<string, mixed> $attStmt
     */
    public static function createBasic(string $fmt, array $attStmt, TrustPath $trustPath): self
    {
        return self::create($fmt, $attStmt, self::TYPE_BASIC, $trustPath);
    }
    /**
     * @param array<string, mixed> $attStmt
     */
    public static function createSelf(string $fmt, array $attStmt, TrustPath $trustPath): self
    {
        return self::create($fmt, $attStmt, self::TYPE_SELF, $trustPath);
    }
    /**
     * @param array<string, mixed> $attStmt
     */
    public static function createAttCA(string $fmt, array $attStmt, TrustPath $trustPath): self
    {
        return self::create($fmt, $attStmt, self::TYPE_ATTCA, $trustPath);
    }
    /**
     * @param array<string, mixed> $attStmt
     *
     * @deprecated since 4.2.0 and will be removed in 5.0.0. The ECDAA Trust Anchor does no longer exist in Webauthn specification.
     * @infection-ignore-all
     */
    public static function createEcdaa(string $fmt, array $attStmt, TrustPath $trustPath): self
    {
        return self::create($fmt, $attStmt, self::TYPE_ECDAA, $trustPath);
    }
    /**
     * @param array<string, mixed> $attStmt
     */
    public static function createAnonymizationCA(string $fmt, array $attStmt, TrustPath $trustPath): self
    {
        return self::create($fmt, $attStmt, self::TYPE_ANONCA, $trustPath);
    }
    /**
     * @deprecated since 4.7.0. Please use the property directly.
     * @infection-ignore-all
     */
    public function getFmt(): string
    {
        return $this->fmt;
    }
    /**
     * @return mixed[]
     * @deprecated since 4.7.0. Please use the property directly.
     * @infection-ignore-all
     */
    public function getAttStmt(): array
    {
        return $this->attStmt;
    }
    public function has(string $key): bool
    {
        return array_key_exists($key, $this->attStmt);
    }
    public function get(string $key): mixed
    {
        $this->has($key) || throw InvalidDataException::create($this->attStmt, sprintf('The attestation statement has no key "%s".', $key));
        return $this->attStmt[$key];
    }
    /**
     * @deprecated since 4.7.0. Please use the property directly.
     * @infection-ignore-all
     */
    public function getTrustPath(): TrustPath
    {
        return $this->trustPath;
    }
    /**
     * @deprecated since 4.7.0. Please use the property directly.
     * @infection-ignore-all
     */
    public function getType(): string
    {
        return $this->type;
    }
    /**
     * @param mixed[] $data
     * @deprecated since 4.8.0. Please use {Webauthn\Denormalizer\WebauthnSerializerFactory} for converting the object.
     * @infection-ignore-all
     */
    public static function createFromArray(array $data): self
    {
        foreach (['fmt', 'attStmt', 'trustPath', 'type'] as $key) {
            array_key_exists($key, $data) || throw InvalidDataException::create($data, sprintf('The key "%s" is missing', $key));
        }
        return self::create($data['fmt'], $data['attStmt'], $data['type'], TrustPathLoader::loadTrustPath($data['trustPath']));
    }
    /**
     * @return mixed[]
     */
    public function jsonSerialize(): array
    {
        trigger_deprecation('web-auth/webauthn-bundle', '4.9.0', 'The "%s" method is deprecated and will be removed in 5.0. Please use the serializer instead.', __METHOD__);
        return ['fmt' => $this->fmt, 'attStmt' => $this->attStmt, 'trustPath' => $this->trustPath, 'type' => $this->type];
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\Webauthn;

use InvalidArgumentException;
use _ContaoManager\ParagonIE\ConstantTime\Base64UrlSafe;
use _ContaoManager\Psr\Log\LoggerInterface;
use _ContaoManager\Psr\Log\NullLogger;
use _ContaoManager\Symfony\Component\Serializer\SerializerInterface;
use Throwable;
use _ContaoManager\Webauthn\AttestationStatement\AttestationObjectLoader;
use _ContaoManager\Webauthn\Exception\InvalidDataException;
use _ContaoManager\Webauthn\MetadataService\CanLogData;
use _ContaoManager\Webauthn\Util\Base64;
use function array_key_exists;
use function is_array;
use function is_string;
use function sprintf;
use const JSON_THROW_ON_ERROR;
/**
 * @deprecated since 4.8.0 and will be removed in 5.0.0. Please use the Symfony serializer instead
 */
class PublicKeyCredentialLoader implements CanLogData
{
    private LoggerInterface $logger;
    public function __construct(private readonly null|AttestationObjectLoader $attestationObjectLoader, private readonly null|SerializerInterface $serializer = null)
    {
        if ($this->attestationObjectLoader === null && $this->serializer === null) {
            throw new InvalidArgumentException('You must provide an attestation object loader or a serializer');
        }
        $this->logger = new NullLogger();
    }
    public static function create(null|AttestationObjectLoader $attestationObjectLoader, null|SerializerInterface $serializer = null): self
    {
        return new self($attestationObjectLoader, $serializer);
    }
    public function setLogger(LoggerInterface $logger): void
    {
        $this->logger = $logger;
    }
    /**
     * @param mixed[] $json
     * @infection-ignore-all
     */
    public function loadArray(array $json): PublicKeyCredential
    {
        $this->logger->info('Trying to load data from an array', ['data' => $json]);
        try {
            foreach (['id', 'rawId', 'type'] as $key) {
                array_key_exists($key, $json) || throw InvalidDataException::create($json, sprintf('The parameter "%s" is missing', $key));
                is_string($json[$key]) || throw InvalidDataException::create($json, sprintf('The parameter "%s" shall be a string', $key));
            }
            array_key_exists('response', $json) || throw InvalidDataException::create($json, 'The parameter "response" is missing');
            is_array($json['response']) || throw InvalidDataException::create($json, 'The parameter "response" shall be an array');
            $json['type'] === 'public-key' || throw InvalidDataException::create($json, sprintf('Unsupported type "%s"', $json['type']));
            $id = Base64UrlSafe::decodeNoPadding($json['id']);
            $rawId = Base64::decode($json['rawId']);
            hash_equals($id, $rawId) || throw InvalidDataException::create($json, 'Invalid ID');
            $publicKeyCredential = PublicKeyCredential::create(null, $json['type'], $rawId, $this->createResponse($json['response']));
            $this->logger->info('The data has been loaded');
            $this->logger->debug('Public Key Credential', ['publicKeyCredential' => $publicKeyCredential]);
            return $publicKeyCredential;
        } catch (Throwable $throwable) {
            $this->logger->error('An error occurred', ['exception' => $throwable]);
            throw $throwable;
        }
    }
    public function load(string $data): PublicKeyCredential
    {
        $this->logger->info('Trying to load data from a string', ['data' => $data]);
        try {
            if ($this->serializer !== null) {
                return $this->serializer->deserialize($data, PublicKeyCredential::class, 'json');
            }
            $json = json_decode($data, \true, flags: JSON_THROW_ON_ERROR);
            return $this->loadArray($json);
        } catch (Throwable $throwable) {
            $this->logger->error('An error occurred', ['exception' => $throwable]);
            throw InvalidDataException::create($data, 'Unable to load the data', $throwable);
        }
    }
    /**
     * @param mixed[] $response
     */
    private function createResponse(array $response): AuthenticatorResponse
    {
        array_key_exists('clientDataJSON', $response) || throw InvalidDataException::create($response, 'Invalid data. The parameter "clientDataJSON" is missing');
        is_string($response['clientDataJSON']) || throw InvalidDataException::create($response, 'Invalid data. The parameter "clientDataJSON" is invalid');
        $userHandle = $response['userHandle'] ?? null;
        $userHandle === null || is_string($userHandle) || throw InvalidDataException::create($response, 'Invalid data. The parameter "userHandle" is invalid');
        /** @var string[] $transports */
        $transports = $response['transports'] ?? [];
        is_array($transports) || throw InvalidDataException::create($response, 'Invalid data. The parameter "transports" is invalid');
        if ($this->serializer !== null) {
            return $this->serializer->deserialize($response, AuthenticatorResponse::class, 'json');
        }
        switch (\true) {
            case array_key_exists('attestationObject', $response):
                $attestationObject = $this->attestationObjectLoader->load($response['attestationObject']);
                return AuthenticatorAttestationResponse::create(CollectedClientData::createFormJson($response['clientDataJSON']), $attestationObject, $transports);
            case array_key_exists('signature', $response):
                $authDataLoader = AuthenticatorDataLoader::create();
                $authData = Base64UrlSafe::decodeNoPadding($response['authenticatorData'] ?? '');
                $authenticatorData = $authDataLoader->load($authData);
                try {
                    $signature = Base64::decode($response['signature']);
                } catch (Throwable $e) {
                    throw InvalidDataException::create($response['signature'], 'The signature shall be Base64 Url Safe encoded', $e);
                }
                $userHandle = $response['userHandle'] ?? null;
                if ($userHandle !== '' && $userHandle !== null) {
                    $userHandle = Base64::decode($userHandle);
                }
                return AuthenticatorAssertionResponse::create(CollectedClientData::createFormJson($response['clientDataJSON']), $authenticatorData, $signature, $userHandle);
            default:
                throw InvalidDataException::create($response, 'Unable to create the response object');
        }
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\Webauthn;

use _ContaoManager\Psr\Cache\CacheItemPoolInterface;
use _ContaoManager\Symfony\Component\HttpFoundation\Request;
use function count;
use function is_int;
final class SimpleFakeCredentialGenerator implements FakeCredentialGenerator
{
    public function __construct(private readonly null|CacheItemPoolInterface $cache = null)
    {
    }
    /**
     * @return PublicKeyCredentialDescriptor[]
     */
    public function generate(Request $request, string $username): array
    {
        if ($this->cache === null) {
            return $this->generateCredentials($username);
        }
        $cacheKey = 'fake_credentials_' . hash('xxh128', $username);
        $cacheItem = $this->cache->getItem($cacheKey);
        if ($cacheItem->isHit()) {
            return $cacheItem->get();
        }
        $credentials = $this->generateCredentials($username);
        $cacheItem->set($credentials);
        $this->cache->save($cacheItem);
        return $credentials;
    }
    /**
     * @return PublicKeyCredentialDescriptor[]
     */
    private function generateCredentials(string $username): array
    {
        $transports = [PublicKeyCredentialDescriptor::AUTHENTICATOR_TRANSPORT_USB, PublicKeyCredentialDescriptor::AUTHENTICATOR_TRANSPORT_NFC, PublicKeyCredentialDescriptor::AUTHENTICATOR_TRANSPORT_BLE];
        $credentials = [];
        for ($i = 0; $i < random_int(1, 3); $i++) {
            $randomTransportKeys = array_rand($transports, random_int(1, count($transports)));
            if (is_int($randomTransportKeys)) {
                $randomTransportKeys = [$randomTransportKeys];
            }
            $randomTransports = array_values(array_intersect_key($transports, array_flip($randomTransportKeys)));
            $credentials[] = PublicKeyCredentialDescriptor::create(PublicKeyCredentialDescriptor::CREDENTIAL_TYPE_PUBLIC_KEY, hash('sha256', random_bytes(16) . $username), $randomTransports);
        }
        return $credentials;
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\Webauthn\TokenBinding;

use _ContaoManager\ParagonIE\ConstantTime\Base64UrlSafe;
use _ContaoManager\Webauthn\Exception\InvalidDataException;
use function array_key_exists;
use function in_array;
use function sprintf;
/**
 * @deprecated Since 4.3.0 and will be removed in 5.0.0
 * @infection-ignore-all
 */
class TokenBinding
{
    final public const TOKEN_BINDING_STATUS_PRESENT = 'present';
    final public const TOKEN_BINDING_STATUS_SUPPORTED = 'supported';
    final public const TOKEN_BINDING_STATUS_NOT_SUPPORTED = 'not-supported';
    private readonly string $status;
    private readonly ?string $id;
    public function __construct(string $status, ?string $id)
    {
        $status === self::TOKEN_BINDING_STATUS_PRESENT && $id === null && throw InvalidDataException::create([$status, $id], 'The member "id" is required when status is "present"');
        $this->status = $status;
        $this->id = $id;
    }
    /**
     * @param mixed[] $json
     */
    public static function createFormArray(array $json): self
    {
        array_key_exists('status', $json) || throw InvalidDataException::create($json, 'The member "status" is required');
        $status = $json['status'];
        in_array($status, self::getSupportedStatus(), \true) || throw InvalidDataException::create($json, sprintf('The member "status" is invalid. Supported values are: %s', implode(', ', self::getSupportedStatus())));
        $id = array_key_exists('id', $json) ? Base64UrlSafe::decodeNoPadding($json['id']) : null;
        return new self($status, $id);
    }
    public function getStatus(): string
    {
        return $this->status;
    }
    public function getId(): ?string
    {
        return $this->id;
    }
    /**
     * @return string[]
     */
    private static function getSupportedStatus(): array
    {
        return [self::TOKEN_BINDING_STATUS_PRESENT, self::TOKEN_BINDING_STATUS_SUPPORTED, self::TOKEN_BINDING_STATUS_NOT_SUPPORTED];
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\Webauthn\TokenBinding;

use _ContaoManager\Psr\Http\Message\ServerRequestInterface;
use _ContaoManager\Webauthn\Exception\InvalidDataException;
use function count;
/**
 * @deprecated Since 4.3.0 and will be removed in 5.0.0
 * @infection-ignore-all
 */
final class SecTokenBindingHandler implements TokenBindingHandler
{
    public static function create(): self
    {
        return new self();
    }
    public function check(TokenBinding $tokenBinding, ServerRequestInterface $request): void
    {
        if ($tokenBinding->getStatus() !== TokenBinding::TOKEN_BINDING_STATUS_PRESENT) {
            return;
        }
        $request->hasHeader('Sec-Token-Binding') || throw InvalidDataException::create($tokenBinding, 'The header parameter "Sec-Token-Binding" is missing.');
        $tokenBindingIds = $request->getHeader('Sec-Token-Binding');
        count($tokenBindingIds) === 1 || throw InvalidDataException::create($tokenBinding, 'The header parameter "Sec-Token-Binding" is invalid.');
        $tokenBindingId = reset($tokenBindingIds);
        $tokenBindingId === $tokenBinding->getId() || throw InvalidDataException::create($tokenBinding, 'The header parameter "Sec-Token-Binding" is invalid.');
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\Webauthn\TokenBinding;

use _ContaoManager\Psr\Http\Message\ServerRequestInterface;
/**
 * @deprecated Since 4.3.0 and will be removed in 5.0.0
 * @infection-ignore-all
 */
final class IgnoreTokenBindingHandler implements TokenBindingHandler
{
    public static function create(): self
    {
        return new self();
    }
    public function check(TokenBinding $tokenBinding, ServerRequestInterface $request): void
    {
        //Does nothing
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\Webauthn\TokenBinding;

use _ContaoManager\Psr\Http\Message\ServerRequestInterface;
use _ContaoManager\Webauthn\Exception\InvalidDataException;
/**
 * @deprecated Since 4.3.0 and will be removed in 5.0.0
 * @infection-ignore-all
 */
final class TokenBindingNotSupportedHandler implements TokenBindingHandler
{
    public static function create(): self
    {
        return new self();
    }
    public function check(TokenBinding $tokenBinding, ServerRequestInterface $request): void
    {
        $tokenBinding->getStatus() !== TokenBinding::TOKEN_BINDING_STATUS_PRESENT || throw InvalidDataException::create($tokenBinding, 'Token binding not supported.');
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\Webauthn\TokenBinding;

use _ContaoManager\Psr\Http\Message\ServerRequestInterface;
/**
 * @deprecated Since 4.3.0 and will be removed in 5.0.0
 * @infection-ignore-all
 */
interface TokenBindingHandler
{
    public function check(TokenBinding $tokenBinding, ServerRequestInterface $request): void;
}
<?php

declare (strict_types=1);
namespace _ContaoManager\Webauthn\Util;

use _ContaoManager\Cose\Algorithm\Signature\ECDSA;
use _ContaoManager\Cose\Algorithm\Signature\ECDSA\ECSignature;
use _ContaoManager\Cose\Algorithm\Signature\ECDSA\ES256;
use _ContaoManager\Cose\Algorithm\Signature\ECDSA\ES256K;
use _ContaoManager\Cose\Algorithm\Signature\ECDSA\ES384;
use _ContaoManager\Cose\Algorithm\Signature\ECDSA\ES512;
use _ContaoManager\Cose\Algorithm\Signature\Signature;
/**
 * This class fixes the signature of the ECDSA based algorithms.
 *
 * @internal
 *
 * @see https://www.w3.org/TR/webauthn/#signature-attestation-types
 */
abstract class CoseSignatureFixer
{
    private const ES256_SIGNATURE_LENGTH = 64;
    private const ES384_SIGNATURE_LENGTH = 96;
    private const ES512_SIGNATURE_LENGTH = 132;
    public static function fix(string $signature, Signature $algorithm): string
    {
        switch ($algorithm::identifier()) {
            case ES256K::ID:
            case ES256::ID:
                if (mb_strlen($signature, '8bit') === self::ES256_SIGNATURE_LENGTH) {
                    return $signature;
                }
                return ECSignature::fromAsn1($signature, self::ES256_SIGNATURE_LENGTH);
            //TODO: fix this hardcoded value by adding a dedicated method for the algorithms
            case ES384::ID:
                if (mb_strlen($signature, '8bit') === self::ES384_SIGNATURE_LENGTH) {
                    return $signature;
                }
                return ECSignature::fromAsn1($signature, self::ES384_SIGNATURE_LENGTH);
            case ES512::ID:
                if (mb_strlen($signature, '8bit') === self::ES512_SIGNATURE_LENGTH) {
                    return $signature;
                }
                return ECSignature::fromAsn1($signature, self::ES512_SIGNATURE_LENGTH);
        }
        return $signature;
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\Webauthn\Util;

use _ContaoManager\ParagonIE\ConstantTime\Base64UrlSafe;
use Throwable;
use _ContaoManager\Webauthn\Exception\InvalidDataException;
abstract class Base64
{
    public static function decode(string $data): string
    {
        try {
            return Base64UrlSafe::decode($data);
        } catch (Throwable) {
        }
        try {
            return \_ContaoManager\ParagonIE\ConstantTime\Base64::decode($data);
        } catch (Throwable $e) {
            throw InvalidDataException::create($data, 'Invalid data submitted', $e);
        }
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\Webauthn;

use JsonSerializable;
use _ContaoManager\ParagonIE\ConstantTime\Base64;
use _ContaoManager\Symfony\Component\Uid\Uuid;
use _ContaoManager\Webauthn\Exception\InvalidDataException;
use function array_key_exists;
use function is_string;
/**
 * @see https://www.w3.org/TR/webauthn/#sec-attested-credential-data
 */
class AttestedCredentialData implements JsonSerializable
{
    public function __construct(public Uuid $aaguid, public readonly string $credentialId, public readonly ?string $credentialPublicKey)
    {
    }
    public static function create(Uuid $aaguid, string $credentialId, ?string $credentialPublicKey = null): self
    {
        return new self($aaguid, $credentialId, $credentialPublicKey);
    }
    /**
     * @deprecated since 4.7.0. Please use the property directly.
     * @infection-ignore-all
     */
    public function getAaguid(): Uuid
    {
        return $this->aaguid;
    }
    /**
     * @deprecated since 4.7.0. Please use the property directly.
     * @infection-ignore-all
     */
    public function setAaguid(Uuid $aaguid): void
    {
        $this->aaguid = $aaguid;
    }
    /**
     * @deprecated since 4.7.0. Please use the property directly.
     * @infection-ignore-all
     */
    public function getCredentialId(): string
    {
        return $this->credentialId;
    }
    /**
     * @deprecated since 4.7.0. Please use the property directly.
     * @infection-ignore-all
     */
    public function getCredentialPublicKey(): ?string
    {
        return $this->credentialPublicKey;
    }
    /**
     * @param mixed[] $json
     * @deprecated since 4.9.0 and will be removed in 5.0.0. Please use the serializer instead.
     */
    public static function createFromArray(array $json): self
    {
        array_key_exists('aaguid', $json) || throw InvalidDataException::create($json, 'Invalid input. "aaguid" is missing.');
        $aaguid = $json['aaguid'];
        is_string($aaguid) || throw InvalidDataException::create($json, 'Invalid input. "aaguid" shall be a string of 36 characters');
        mb_strlen($aaguid, '8bit') === 36 || throw InvalidDataException::create($json, 'Invalid input. "aaguid" shall be a string of 36 characters');
        $uuid = Uuid::fromString($aaguid);
        array_key_exists('credentialId', $json) || throw InvalidDataException::create($json, 'Invalid input. "credentialId" is missing.');
        $credentialId = $json['credentialId'];
        is_string($credentialId) || throw InvalidDataException::create($json, 'Invalid input. "credentialId" shall be a string');
        $credentialId = Base64::decode($credentialId, \true);
        $credentialPublicKey = null;
        if (isset($json['credentialPublicKey'])) {
            $credentialPublicKey = Base64::decode($json['credentialPublicKey'], \true);
        }
        return self::create($uuid, $credentialId, $credentialPublicKey);
    }
    /**
     * @return mixed[]
     */
    public function jsonSerialize(): array
    {
        trigger_deprecation('web-auth/webauthn-bundle', '4.9.0', 'The "%s" method is deprecated and will be removed in 5.0. Please use the serializer instead.', __METHOD__);
        $result = ['aaguid' => $this->aaguid->__toString(), 'credentialId' => base64_encode($this->credentialId)];
        if ($this->credentialPublicKey !== null) {
            $result['credentialPublicKey'] = base64_encode($this->credentialPublicKey);
        }
        return $result;
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\Webauthn;

use InvalidArgumentException;
use _ContaoManager\ParagonIE\ConstantTime\Base64UrlSafe;
/**
 * @see https://w3c.github.io/webappsec-credential-management/#credential
 */
abstract class Credential
{
    /**
     * @deprecated since 4.9.0. Please use the property rawId instead.
     */
    public readonly string $id;
    public readonly string $rawId;
    public function __construct(null|string $id, public readonly string $type, null|string $rawId = null)
    {
        if ($id === null && $rawId === null) {
            throw new InvalidArgumentException('You must provide a valid raw ID');
        }
        if ($id !== null) {
            trigger_deprecation('web-auth/webauthn-lib', '4.9.0', 'The property "$id" is deprecated and will be removed in 5.0.0. Please set null use "rawId" instead.');
        } else {
            $id = Base64UrlSafe::encodeUnpadded($rawId);
        }
        $this->id = $id;
        $this->rawId = $rawId ?? Base64UrlSafe::decodeNoPadding($id);
    }
    /**
     * @deprecated since 4.7.0. Please use the property directly.
     * @infection-ignore-all
     */
    public function getId(): string
    {
        return $this->id;
    }
    /**
     * @deprecated since 4.7.0. Please use the property directly.
     * @infection-ignore-all
     */
    public function getType(): string
    {
        return $this->type;
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\Webauthn;

use _ContaoManager\Psr\EventDispatcher\EventDispatcherInterface;
use _ContaoManager\Psr\Http\Message\ServerRequestInterface;
use _ContaoManager\Psr\Log\LoggerInterface;
use _ContaoManager\Psr\Log\NullLogger;
use Throwable;
use _ContaoManager\Webauthn\AttestationStatement\AttestationStatementSupportManager;
use _ContaoManager\Webauthn\AuthenticationExtensions\ExtensionOutputCheckerHandler;
use _ContaoManager\Webauthn\CeremonyStep\CeremonyStepManager;
use _ContaoManager\Webauthn\CeremonyStep\CeremonyStepManagerFactory;
use _ContaoManager\Webauthn\Event\AuthenticatorAttestationResponseValidationFailedEvent;
use _ContaoManager\Webauthn\Event\AuthenticatorAttestationResponseValidationSucceededEvent;
use _ContaoManager\Webauthn\Event\CanDispatchEvents;
use _ContaoManager\Webauthn\Event\NullEventDispatcher;
use _ContaoManager\Webauthn\Exception\AuthenticatorResponseVerificationException;
use _ContaoManager\Webauthn\MetadataService\CanLogData;
use _ContaoManager\Webauthn\MetadataService\CertificateChain\CertificateChainValidator;
use _ContaoManager\Webauthn\MetadataService\MetadataStatementRepository;
use _ContaoManager\Webauthn\MetadataService\StatusReportRepository;
use _ContaoManager\Webauthn\TokenBinding\TokenBindingHandler;
use function is_string;
use function sprintf;
class AuthenticatorAttestationResponseValidator implements CanLogData, CanDispatchEvents
{
    private LoggerInterface $logger;
    private EventDispatcherInterface $eventDispatcher;
    private readonly CeremonyStepManagerFactory $ceremonyStepManagerFactory;
    public function __construct(null|AttestationStatementSupportManager $attestationStatementSupportManager = null, private readonly null|PublicKeyCredentialSourceRepository $publicKeyCredentialSourceRepository = null, private readonly null|TokenBindingHandler $tokenBindingHandler = null, null|ExtensionOutputCheckerHandler $extensionOutputCheckerHandler = null, null|EventDispatcherInterface $eventDispatcher = null, private null|CeremonyStepManager $ceremonyStepManager = null)
    {
        if ($this->publicKeyCredentialSourceRepository !== null) {
            trigger_deprecation('web-auth/webauthn-lib', '4.6.0', 'The parameter "$publicKeyCredentialSourceRepository" is deprecated since 4.6.0 and will be removed in 5.0.0. Please set "null" instead.');
        }
        if ($this->tokenBindingHandler !== null) {
            trigger_deprecation('web-auth/webauthn-lib', '4.3.0', 'The parameter "$tokenBindingHandler" is deprecated since 4.3.0 and will be removed in 5.0.0. Please set "null" instead.');
        }
        if ($extensionOutputCheckerHandler !== null) {
            trigger_deprecation('web-auth/webauthn-lib', '4.8.0', 'The parameter "$extensionOutputCheckerHandler" is deprecated since 4.8.0 and will be removed in 5.0.0. Please set "null" instead and inject a CheckExtensions object into the CeremonyStepManager.');
        }
        $this->eventDispatcher = $eventDispatcher ?? new NullEventDispatcher();
        if ($eventDispatcher !== null) {
            trigger_deprecation('web-auth/webauthn-lib', '4.5.0', 'The parameter "$eventDispatcher" is deprecated since 4.5.0 will be removed in 5.0.0. Please use `setEventDispatcher` instead.');
        }
        if ($this->ceremonyStepManager === null) {
            trigger_deprecation('web-auth/webauthn-lib', '4.8.0', 'The parameter "$ceremonyStepManager" will mandatory in 5.0.0. Please set a CeremonyStepManager object instead and set null for $attestationStatementSupportManager and $extensionOutputCheckerHandler.');
        }
        $this->logger = new NullLogger();
        $this->ceremonyStepManagerFactory = new CeremonyStepManagerFactory();
        if ($attestationStatementSupportManager !== null) {
            $this->ceremonyStepManagerFactory->setAttestationStatementSupportManager($attestationStatementSupportManager);
            trigger_deprecation('web-auth/webauthn-lib', '4.8.0', 'The parameter "$attestationStatementSupportManager" is deprecated since 4.8.0 will be removed in 5.0.0. Please set a CheckAttestationFormatIsKnownAndValid object into CeremonyStepManager object instead.');
        }
        if ($extensionOutputCheckerHandler !== null) {
            $this->ceremonyStepManagerFactory->setExtensionOutputCheckerHandler($extensionOutputCheckerHandler);
        }
    }
    /**
     * @private Will become private in 5.0.0
     */
    public static function create(null|AttestationStatementSupportManager $attestationStatementSupportManager = null, null|PublicKeyCredentialSourceRepository $publicKeyCredentialSourceRepository = null, null|TokenBindingHandler $tokenBindingHandler = null, null|ExtensionOutputCheckerHandler $extensionOutputCheckerHandler = null, null|EventDispatcherInterface $eventDispatcher = null, null|CeremonyStepManager $ceremonyStepManager = null): self
    {
        return new self($attestationStatementSupportManager, $publicKeyCredentialSourceRepository, $tokenBindingHandler, $extensionOutputCheckerHandler, $eventDispatcher, $ceremonyStepManager);
    }
    public function setLogger(LoggerInterface $logger): void
    {
        $this->logger = $logger;
    }
    public function setEventDispatcher(EventDispatcherInterface $eventDispatcher): void
    {
        $this->eventDispatcher = $eventDispatcher;
    }
    /**
     * @deprecated since 4.8.0 and will be removed in 5.0.0. Please use the CheckMetadataStatement object from the CeremonyStepManager instead.
     */
    public function setCertificateChainValidator(CertificateChainValidator $certificateChainValidator): self
    {
        $this->ceremonyStepManagerFactory->enableCertificateChainValidator($certificateChainValidator);
        return $this;
    }
    /**
     * @deprecated since 4.8.0 and will be removed in 5.0.0. Please use the CheckMetadataStatement object from the CeremonyStepManager instead.
     */
    public function enableMetadataStatementSupport(MetadataStatementRepository $metadataStatementRepository, StatusReportRepository $statusReportRepository, CertificateChainValidator $certificateChainValidator): self
    {
        $this->ceremonyStepManagerFactory->enableMetadataStatementSupport($metadataStatementRepository, $statusReportRepository, $certificateChainValidator);
        return $this;
    }
    /**
     * @param string[] $securedRelyingPartyId
     *
     * @see https://www.w3.org/TR/webauthn/#registering-a-new-credential
     */
    public function check(AuthenticatorAttestationResponse $authenticatorAttestationResponse, PublicKeyCredentialCreationOptions $publicKeyCredentialCreationOptions, ServerRequestInterface|string $request, null|array $securedRelyingPartyId = null): PublicKeyCredentialSource
    {
        if ($request instanceof ServerRequestInterface) {
            trigger_deprecation('web-auth/webauthn-lib', '4.5.0', sprintf('Passing a %s to the method `check` of the class "%s" is deprecated since 4.5.0 and will be removed in 5.0.0. Please inject the host as a string instead.', ServerRequestInterface::class, self::class));
        }
        if ($securedRelyingPartyId !== null) {
            trigger_deprecation('web-auth/webauthn-lib', '4.8.0', sprintf('Passing a list or secured relying party IDs to the method `check` of the class "%s" is deprecated since 4.8.0 and will be removed in 5.0.0. Please inject the list instead.', self::class));
        }
        $host = is_string($request) ? $request : $request->getUri()->getHost();
        try {
            $this->logger->info('Checking the authenticator attestation response', ['authenticatorAttestationResponse' => $authenticatorAttestationResponse, 'publicKeyCredentialCreationOptions' => $publicKeyCredentialCreationOptions, 'host' => $host]);
            if ($this->ceremonyStepManager === null) {
                $this->ceremonyStepManager = $this->ceremonyStepManagerFactory->creationCeremony($securedRelyingPartyId);
            }
            $publicKeyCredentialSource = $this->createPublicKeyCredentialSource($authenticatorAttestationResponse, $publicKeyCredentialCreationOptions);
            $this->ceremonyStepManager->process($publicKeyCredentialSource, $authenticatorAttestationResponse, $publicKeyCredentialCreationOptions, $publicKeyCredentialCreationOptions->user->id, $host);
            $publicKeyCredentialSource->counter = $authenticatorAttestationResponse->attestationObject->authData->signCount;
            $publicKeyCredentialSource->backupEligible = $authenticatorAttestationResponse->attestationObject->authData->isBackupEligible();
            $publicKeyCredentialSource->backupStatus = $authenticatorAttestationResponse->attestationObject->authData->isBackedUp();
            $publicKeyCredentialSource->uvInitialized = $authenticatorAttestationResponse->attestationObject->authData->isUserVerified();
            $this->logger->info('The attestation is valid');
            $this->logger->debug('Public Key Credential Source', ['publicKeyCredentialSource' => $publicKeyCredentialSource]);
            $this->eventDispatcher->dispatch($this->createAuthenticatorAttestationResponseValidationSucceededEvent($authenticatorAttestationResponse, $publicKeyCredentialCreationOptions, $host, $publicKeyCredentialSource));
            return $publicKeyCredentialSource;
        } catch (Throwable $throwable) {
            $this->logger->error('An error occurred', ['exception' => $throwable]);
            $this->eventDispatcher->dispatch($this->createAuthenticatorAttestationResponseValidationFailedEvent($authenticatorAttestationResponse, $publicKeyCredentialCreationOptions, $host, $throwable));
            throw $throwable;
        }
    }
    protected function createAuthenticatorAttestationResponseValidationSucceededEvent(AuthenticatorAttestationResponse $authenticatorAttestationResponse, PublicKeyCredentialCreationOptions $publicKeyCredentialCreationOptions, ServerRequestInterface|string $host, PublicKeyCredentialSource $publicKeyCredentialSource): AuthenticatorAttestationResponseValidationSucceededEvent
    {
        if ($host instanceof ServerRequestInterface) {
            trigger_deprecation('web-auth/webauthn-lib', '4.5.0', sprintf('Passing a %s to the method `createAuthenticatorAttestationResponseValidationSucceededEvent` of the class "%s" is deprecated since 4.5.0 and will be removed in 5.0.0. Please inject the host as a string instead.', ServerRequestInterface::class, self::class));
        }
        return new AuthenticatorAttestationResponseValidationSucceededEvent($authenticatorAttestationResponse, $publicKeyCredentialCreationOptions, $host, $publicKeyCredentialSource);
    }
    protected function createAuthenticatorAttestationResponseValidationFailedEvent(AuthenticatorAttestationResponse $authenticatorAttestationResponse, PublicKeyCredentialCreationOptions $publicKeyCredentialCreationOptions, ServerRequestInterface|string $host, Throwable $throwable): AuthenticatorAttestationResponseValidationFailedEvent
    {
        if ($host instanceof ServerRequestInterface) {
            trigger_deprecation('web-auth/webauthn-lib', '4.5.0', sprintf('Passing a %s to the method `createAuthenticatorAttestationResponseValidationFailedEvent` of the class "%s" is deprecated since 4.5.0 and will be removed in 5.0.0. Please inject the host as a string instead.', ServerRequestInterface::class, self::class));
        }
        return new AuthenticatorAttestationResponseValidationFailedEvent($authenticatorAttestationResponse, $publicKeyCredentialCreationOptions, $host, $throwable);
    }
    private function createPublicKeyCredentialSource(AuthenticatorAttestationResponse $authenticatorAttestationResponse, PublicKeyCredentialCreationOptions $publicKeyCredentialCreationOptions): PublicKeyCredentialSource
    {
        $attestationObject = $authenticatorAttestationResponse->attestationObject;
        $attestedCredentialData = $attestationObject->authData->attestedCredentialData;
        $attestedCredentialData !== null || throw AuthenticatorResponseVerificationException::create('Not attested credential data');
        $credentialId = $attestedCredentialData->credentialId;
        $credentialPublicKey = $attestedCredentialData->credentialPublicKey;
        $credentialPublicKey !== null || throw AuthenticatorResponseVerificationException::create('Not credential public key available in the attested credential data');
        $userHandle = $publicKeyCredentialCreationOptions->user->id;
        $transports = $authenticatorAttestationResponse->transports;
        return PublicKeyCredentialSource::create($credentialId, PublicKeyCredentialDescriptor::CREDENTIAL_TYPE_PUBLIC_KEY, $transports, $attestationObject->attStmt->type, $attestationObject->attStmt->trustPath, $attestedCredentialData->aaguid, $credentialPublicKey, $userHandle, $attestationObject->authData->signCount);
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\Webauthn;

use JsonSerializable;
use _ContaoManager\Webauthn\Exception\InvalidDataException;
use function array_key_exists;
use const JSON_THROW_ON_ERROR;
class PublicKeyCredentialParameters implements JsonSerializable
{
    /**
     * @private
     */
    public function __construct(public readonly string $type, public readonly int $alg)
    {
    }
    public static function create(string $type, int $alg): self
    {
        return new self($type, $alg);
    }
    public static function createPk(int $alg): self
    {
        return self::create(PublicKeyCredentialDescriptor::CREDENTIAL_TYPE_PUBLIC_KEY, $alg);
    }
    /**
     * @deprecated since 4.7.0. Please use the property directly.
     * @infection-ignore-all
     */
    public function getType(): string
    {
        return $this->type;
    }
    /**
     * @deprecated since 4.7.0. Please use the property directly.
     * @infection-ignore-all
     */
    public function getAlg(): int
    {
        return $this->alg;
    }
    /**
     * @deprecated since 4.8.0. Please use {Webauthn\Denormalizer\WebauthnSerializerFactory} for converting the object.
     * @infection-ignore-all
     */
    public static function createFromString(string $data): self
    {
        $data = json_decode($data, \true, flags: JSON_THROW_ON_ERROR);
        return self::createFromArray($data);
    }
    /**
     * @param mixed[] $json
     * @deprecated since 4.8.0. Please use {Webauthn\Denormalizer\WebauthnSerializerFactory} for converting the object.
     * @infection-ignore-all
     */
    public static function createFromArray(array $json): self
    {
        array_key_exists('type', $json) || throw InvalidDataException::create($json, 'Invalid input. "type" is missing.');
        array_key_exists('alg', $json) || throw InvalidDataException::create($json, 'Invalid input. "alg" is missing.');
        return self::create($json['type'], $json['alg']);
    }
    /**
     * @return mixed[]
     */
    public function jsonSerialize(): array
    {
        trigger_deprecation('web-auth/webauthn-bundle', '4.9.0', 'The "%s" method is deprecated and will be removed in 5.0. Please use the serializer instead.', __METHOD__);
        return ['type' => $this->type, 'alg' => $this->alg];
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\Webauthn;

use JsonSerializable;
use _ContaoManager\ParagonIE\ConstantTime\Base64UrlSafe;
use _ContaoManager\Webauthn\Exception\InvalidDataException;
use function array_key_exists;
use function count;
use const JSON_THROW_ON_ERROR;
class PublicKeyCredentialDescriptor implements JsonSerializable
{
    final public const CREDENTIAL_TYPE_PUBLIC_KEY = 'public-key';
    final public const AUTHENTICATOR_TRANSPORT_USB = 'usb';
    final public const AUTHENTICATOR_TRANSPORT_NFC = 'nfc';
    final public const AUTHENTICATOR_TRANSPORT_BLE = 'ble';
    final public const AUTHENTICATOR_TRANSPORT_CABLE = 'cable';
    final public const AUTHENTICATOR_TRANSPORT_INTERNAL = 'internal';
    final public const AUTHENTICATOR_TRANSPORTS = [self::AUTHENTICATOR_TRANSPORT_USB, self::AUTHENTICATOR_TRANSPORT_NFC, self::AUTHENTICATOR_TRANSPORT_BLE, self::AUTHENTICATOR_TRANSPORT_CABLE, self::AUTHENTICATOR_TRANSPORT_INTERNAL];
    /**
     * @param string[] $transports
     */
    public function __construct(public readonly string $type, public readonly string $id, public readonly array $transports = [])
    {
    }
    /**
     * @param string[] $transports
     */
    public static function create(string $type, string $id, array $transports = []): self
    {
        return new self($type, $id, $transports);
    }
    /**
     * @deprecated since 4.7.0. Please use the property directly.
     * @infection-ignore-all
     */
    public function getType(): string
    {
        return $this->type;
    }
    /**
     * @deprecated since 4.7.0. Please use the property directly.
     * @infection-ignore-all
     */
    public function getId(): string
    {
        return $this->id;
    }
    /**
     * @return string[]
     * @deprecated since 4.7.0. Please use the property directly.
     * @infection-ignore-all
     */
    public function getTransports(): array
    {
        return $this->transports;
    }
    /**
     * @deprecated since 4.9.0 and will be removed in 5.0.0. Please use the serializer instead.
     */
    public static function createFromString(string $data): self
    {
        $data = json_decode($data, \true, flags: JSON_THROW_ON_ERROR);
        return self::createFromArray($data);
    }
    /**
     * @param mixed[] $json
     * @deprecated since 4.9.0 and will be removed in 5.0.0. Please use the serializer instead.
     */
    public static function createFromArray(array $json): self
    {
        array_key_exists('type', $json) || throw InvalidDataException::create($json, 'Invalid input. "type" is missing.');
        array_key_exists('id', $json) || throw InvalidDataException::create($json, 'Invalid input. "id" is missing.');
        $id = Base64UrlSafe::decodeNoPadding($json['id']);
        return self::create($json['type'], $id, $json['transports'] ?? []);
    }
    /**
     * @return mixed[]
     */
    public function jsonSerialize(): array
    {
        trigger_deprecation('web-auth/webauthn-bundle', '4.9.0', 'The "%s" method is deprecated and will be removed in 5.0. Please use the serializer instead.', __METHOD__);
        $json = ['type' => $this->type, 'id' => Base64UrlSafe::encodeUnpadded($this->id)];
        if (count($this->transports) !== 0) {
            $json['transports'] = $this->transports;
        }
        return $json;
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\Webauthn;

use _ContaoManager\Webauthn\Exception\InvalidDataException;
use function array_key_exists;
class PublicKeyCredentialRpEntity extends PublicKeyCredentialEntity
{
    public function __construct(string $name, public readonly ?string $id = null, ?string $icon = null)
    {
        parent::__construct($name, $icon);
    }
    public static function create(string $name, ?string $id = null, ?string $icon = null): self
    {
        return new self($name, $id, $icon);
    }
    /**
     * @deprecated since 4.7.0. Please use the property directly.
     * @infection-ignore-all
     */
    public function getId(): ?string
    {
        return $this->id;
    }
    /**
     * @param mixed[] $json
     * @deprecated since 4.8.0. Please use {Webauthn\Denormalizer\WebauthnSerializerFactory} for converting the object.
     * @infection-ignore-all
     */
    public static function createFromArray(array $json): self
    {
        array_key_exists('name', $json) || throw InvalidDataException::create($json, 'Invalid input. "name" is missing.');
        return self::create($json['name'], $json['id'] ?? null, $json['icon'] ?? null);
    }
    /**
     * @return mixed[]
     */
    public function jsonSerialize(): array
    {
        trigger_deprecation('web-auth/webauthn-bundle', '4.9.0', 'The "%s" method is deprecated and will be removed in 5.0. Please use the serializer instead.', __METHOD__);
        $json = parent::jsonSerialize();
        if ($this->id !== null) {
            $json['id'] = $this->id;
        }
        return $json;
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\Webauthn;

use _ContaoManager\Webauthn\AttestationStatement\AttestationObject;
/**
 * @see https://www.w3.org/TR/webauthn/#authenticatorattestationresponse
 */
class AuthenticatorAttestationResponse extends AuthenticatorResponse
{
    /**
     * @param string[] $transports
     */
    public function __construct(CollectedClientData $clientDataJSON, public readonly AttestationObject $attestationObject, public readonly array $transports = [])
    {
        parent::__construct($clientDataJSON);
    }
    /**
     * @param string[] $transports
     */
    public static function create(CollectedClientData $clientDataJSON, AttestationObject $attestationObject, array $transports = []): self
    {
        return new self($clientDataJSON, $attestationObject, $transports);
    }
    /**
     * @deprecated since 4.7.0. Please use the property directly.
     * @infection-ignore-all
     */
    public function getAttestationObject(): AttestationObject
    {
        return $this->attestationObject;
    }
    /**
     * @deprecated since 4.7.0. Please use the property directly.
     * @infection-ignore-all
     *
     * @return string[]
     */
    public function getTransports(): array
    {
        return $this->transports;
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\Webauthn;

use InvalidArgumentException;
use JsonSerializable;
use _ContaoManager\Webauthn\AuthenticationExtensions\AuthenticationExtension;
use _ContaoManager\Webauthn\AuthenticationExtensions\AuthenticationExtensions;
use _ContaoManager\Webauthn\AuthenticationExtensions\AuthenticationExtensionsClientInputs;
abstract class PublicKeyCredentialOptions implements JsonSerializable
{
    public AuthenticationExtensions $extensions;
    /**
     * @param positive-int|null $timeout
     * @param null|AuthenticationExtensions|array<string|int, mixed|AuthenticationExtensions> $extensions
     * @protected
     */
    public function __construct(public readonly string $challenge, public null|int $timeout = null, null|array|AuthenticationExtensions $extensions = null)
    {
        $this->timeout === null || $this->timeout > 0 || throw new InvalidArgumentException('Invalid timeout');
        if ($extensions === null) {
            $this->extensions = AuthenticationExtensionsClientInputs::create();
        } elseif ($extensions instanceof AuthenticationExtensions) {
            $this->extensions = $extensions;
        } else {
            $this->extensions = AuthenticationExtensions::create($extensions);
        }
    }
    /**
     * @deprecated since 4.7.0. Please use the {self::create} instead.
     * @infection-ignore-all
     */
    public function setTimeout(?int $timeout): static
    {
        $this->timeout = $timeout;
        return $this;
    }
    /**
     * @deprecated since 4.7.0. Please use the {self::create} instead.
     * @infection-ignore-all
     */
    public function addExtension(AuthenticationExtension $extension): static
    {
        $this->extensions[$extension->name] = $extension;
        return $this;
    }
    /**
     * @param AuthenticationExtension[] $extensions
     * @deprecated since 4.7.0. No replacement. Please use the {self::create} instead.
     * @infection-ignore-all
     */
    public function addExtensions(array $extensions): static
    {
        foreach ($extensions as $extension) {
            $this->extensions[$extension->name] = $extension;
        }
        return $this;
    }
    /**
     * @deprecated since 4.7.0. Please use the {self::create} instead.
     * @infection-ignore-all
     */
    public function setExtensions(AuthenticationExtensions $extensions): static
    {
        $this->extensions = $extensions;
        return $this;
    }
    /**
     * @deprecated since 4.7.0. Please use the property directly.
     * @infection-ignore-all
     */
    public function getChallenge(): string
    {
        return $this->challenge;
    }
    /**
     * @deprecated since 4.7.0. Please use the property directly.
     * @infection-ignore-all
     */
    public function getTimeout(): ?int
    {
        return $this->timeout;
    }
    /**
     * @deprecated since 4.7.0. Please use the property directly.
     * @infection-ignore-all
     */
    public function getExtensions(): AuthenticationExtensions
    {
        return $this->extensions;
    }
    /**
     * @deprecated since 4.8.0. Please use {Webauthn\Denormalizer\WebauthnSerializerFactory} for converting the object.
     * @infection-ignore-all
     */
    abstract public static function createFromString(string $data): static;
    /**
     * @param mixed[] $json
     * @deprecated since 4.8.0. Please use {Webauthn\Denormalizer\WebauthnSerializerFactory} for converting the object.
     * @infection-ignore-all
     */
    abstract public static function createFromArray(array $json): static;
}
<?php

declare (strict_types=1);
namespace _ContaoManager\Webauthn;

use _ContaoManager\Webauthn\AuthenticationExtensions\AuthenticationExtensions;
use function ord;
/**
 * @see https://www.w3.org/TR/webauthn/#sec-authenticator-data
 * @see https://www.w3.org/TR/webauthn/#flags
 */
class AuthenticatorData
{
    final public const FLAG_UP = 0b1;
    final public const FLAG_RFU1 = 0b10;
    final public const FLAG_UV = 0b100;
    final public const FLAG_BE = 0b1000;
    final public const FLAG_BS = 0b10000;
    /**
     * TODO: remove bits 3 and 4 as they have been assigned to BE and BS in Webauthn level 3.
     */
    final public const FLAG_RFU2 = 0b111000;
    final public const FLAG_AT = 0b1000000;
    final public const FLAG_ED = 0b10000000;
    public function __construct(public readonly string $authData, public readonly string $rpIdHash, public readonly string $flags, public readonly int $signCount, public readonly null|AttestedCredentialData $attestedCredentialData, public readonly null|AuthenticationExtensions $extensions)
    {
    }
    public static function create(string $authData, string $rpIdHash, string $flags, int $signCount, null|AttestedCredentialData $attestedCredentialData = null, null|AuthenticationExtensions $extensions = null): self
    {
        return new self($authData, $rpIdHash, $flags, $signCount, $attestedCredentialData, $extensions);
    }
    /**
     * @deprecated since 4.7.0. Please use the property directly.
     * @infection-ignore-all
     */
    public function getAuthData(): string
    {
        return $this->authData;
    }
    /**
     * @deprecated since 4.7.0. Please use the property directly.
     * @infection-ignore-all
     */
    public function getRpIdHash(): string
    {
        return $this->rpIdHash;
    }
    public function isUserPresent(): bool
    {
        return 0 !== (ord($this->flags) & self::FLAG_UP);
    }
    public function isUserVerified(): bool
    {
        return 0 !== (ord($this->flags) & self::FLAG_UV);
    }
    public function isBackupEligible(): bool
    {
        return 0 !== (ord($this->flags) & self::FLAG_BE);
    }
    public function isBackedUp(): bool
    {
        return 0 !== (ord($this->flags) & self::FLAG_BS);
    }
    public function hasAttestedCredentialData(): bool
    {
        return 0 !== (ord($this->flags) & self::FLAG_AT);
    }
    public function hasExtensions(): bool
    {
        return 0 !== (ord($this->flags) & self::FLAG_ED);
    }
    public function getReservedForFutureUse1(): int
    {
        return ord($this->flags) & self::FLAG_RFU1;
    }
    public function getReservedForFutureUse2(): int
    {
        return ord($this->flags) & self::FLAG_RFU2;
    }
    /**
     * @deprecated since 4.7.0. Please use the property directly.
     * @infection-ignore-all
     */
    public function getSignCount(): int
    {
        return $this->signCount;
    }
    /**
     * @deprecated since 4.7.0. Please use the property directly.
     * @infection-ignore-all
     */
    public function getAttestedCredentialData(): ?AttestedCredentialData
    {
        return $this->attestedCredentialData;
    }
    /**
     * @deprecated since 4.7.0. Please use the property directly.
     * @infection-ignore-all
     */
    public function getExtensions(): ?AuthenticationExtensions
    {
        return $this->extensions !== null && $this->hasExtensions() ? $this->extensions : null;
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\Webauthn;

use ArrayIterator;
use Countable;
use InvalidArgumentException;
use Iterator;
use IteratorAggregate;
use JsonSerializable;
use function array_key_exists;
use function count;
use const COUNT_NORMAL;
use const JSON_THROW_ON_ERROR;
/**
 * @implements IteratorAggregate<PublicKeyCredentialDescriptor>
 * @deprecated since 4.8.0 and will be removed in 5.0.0.
 * @infection-ignore-all
 */
class PublicKeyCredentialDescriptorCollection implements JsonSerializable, Countable, IteratorAggregate
{
    /**
     * @var array<string, PublicKeyCredentialDescriptor>
     * @readonly
     */
    public array $publicKeyCredentialDescriptors;
    /**
     * @private
     * @param PublicKeyCredentialDescriptor[] $pkCredentialDescriptors
     */
    public function __construct(array $pkCredentialDescriptors = [])
    {
        $this->publicKeyCredentialDescriptors = [];
        foreach ($pkCredentialDescriptors as $pkCredentialDescriptor) {
            $pkCredentialDescriptor instanceof PublicKeyCredentialDescriptor || throw new InvalidArgumentException('Expected only instances of ' . PublicKeyCredentialDescriptor::class);
            $this->publicKeyCredentialDescriptors[$pkCredentialDescriptor->id] = $pkCredentialDescriptor;
        }
    }
    /**
     * @param PublicKeyCredentialDescriptor[] $publicKeyCredentialDescriptors
     */
    public static function create(array $publicKeyCredentialDescriptors): self
    {
        return new self($publicKeyCredentialDescriptors);
    }
    /**
     * @infection-ignore-all
     */
    public function add(PublicKeyCredentialDescriptor ...$publicKeyCredentialDescriptors): void
    {
        foreach ($publicKeyCredentialDescriptors as $publicKeyCredentialDescriptor) {
            $this->publicKeyCredentialDescriptors[$publicKeyCredentialDescriptor->id] = $publicKeyCredentialDescriptor;
        }
    }
    /**
     * @infection-ignore-all
     */
    public function has(string $id): bool
    {
        return array_key_exists($id, $this->publicKeyCredentialDescriptors);
    }
    /**
     * @infection-ignore-all
     */
    public function remove(string $id): void
    {
        if (!array_key_exists($id, $this->publicKeyCredentialDescriptors)) {
            return;
        }
        unset($this->publicKeyCredentialDescriptors[$id]);
    }
    /**
     * @return Iterator<string, PublicKeyCredentialDescriptor>
     */
    public function getIterator(): Iterator
    {
        return new ArrayIterator($this->publicKeyCredentialDescriptors);
    }
    public function count(int $mode = COUNT_NORMAL): int
    {
        return count($this->publicKeyCredentialDescriptors, $mode);
    }
    /**
     * @return array<string, mixed>[]
     */
    public function jsonSerialize(): array
    {
        trigger_deprecation('web-auth/webauthn-bundle', '4.9.0', 'The "%s" method is deprecated and will be removed in 5.0. Please use the serializer instead.', __METHOD__);
        return $this->publicKeyCredentialDescriptors;
    }
    /**
     * @infection-ignore-all
     */
    public static function createFromString(string $data): self
    {
        $data = json_decode($data, \true, flags: JSON_THROW_ON_ERROR);
        return self::createFromArray($data);
    }
    /**
     * @param mixed[] $json
     * @infection-ignore-all
     */
    public static function createFromArray(array $json): self
    {
        return self::create(array_map(static fn(array $item): PublicKeyCredentialDescriptor => PublicKeyCredentialDescriptor::createFromArray($item), $json));
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\Webauthn;

/**
 * @see https://www.w3.org/TR/webauthn/#authenticatorresponse
 */
abstract class AuthenticatorResponse
{
    public function __construct(public readonly CollectedClientData $clientDataJSON)
    {
    }
    /**
     * @deprecated since 4.7.0. Please use the property directly.
     * @infection-ignore-all
     */
    public function getClientDataJSON(): CollectedClientData
    {
        return $this->clientDataJSON;
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\Webauthn;

use _ContaoManager\Cose\Algorithm\Manager;
use _ContaoManager\Psr\EventDispatcher\EventDispatcherInterface;
use _ContaoManager\Psr\Http\Message\ServerRequestInterface;
use _ContaoManager\Psr\Log\LoggerInterface;
use _ContaoManager\Psr\Log\NullLogger;
use Throwable;
use _ContaoManager\Webauthn\AuthenticationExtensions\ExtensionOutputCheckerHandler;
use _ContaoManager\Webauthn\CeremonyStep\CeremonyStepManager;
use _ContaoManager\Webauthn\CeremonyStep\CeremonyStepManagerFactory;
use _ContaoManager\Webauthn\Counter\CounterChecker;
use _ContaoManager\Webauthn\Event\AuthenticatorAssertionResponseValidationFailedEvent;
use _ContaoManager\Webauthn\Event\AuthenticatorAssertionResponseValidationSucceededEvent;
use _ContaoManager\Webauthn\Event\CanDispatchEvents;
use _ContaoManager\Webauthn\Event\NullEventDispatcher;
use _ContaoManager\Webauthn\Exception\AuthenticatorResponseVerificationException;
use _ContaoManager\Webauthn\MetadataService\CanLogData;
use _ContaoManager\Webauthn\TokenBinding\TokenBindingHandler;
use function is_string;
use function sprintf;
class AuthenticatorAssertionResponseValidator implements CanLogData, CanDispatchEvents
{
    private LoggerInterface $logger;
    private readonly CeremonyStepManagerFactory $ceremonyStepManagerFactory;
    private EventDispatcherInterface $eventDispatcher;
    public function __construct(private readonly null|PublicKeyCredentialSourceRepository $publicKeyCredentialSourceRepository = null, private readonly null|TokenBindingHandler $tokenBindingHandler = null, null|ExtensionOutputCheckerHandler $extensionOutputCheckerHandler = null, null|Manager $algorithmManager = null, null|EventDispatcherInterface $eventDispatcher = null, private null|CeremonyStepManager $ceremonyStepManager = null)
    {
        if ($this->publicKeyCredentialSourceRepository !== null) {
            trigger_deprecation('web-auth/webauthn-lib', '4.6.0', 'The parameter "$publicKeyCredentialSourceRepository" is deprecated since 4.6.0 and will be removed in 5.0.0. Please set "null" instead.');
        }
        if ($this->tokenBindingHandler !== null) {
            trigger_deprecation('web-auth/webauthn-lib', '4.3.0', 'The parameter "$tokenBindingHandler" is deprecated since 4.3.0 and will be removed in 5.0.0. Please set "null" instead.');
        }
        if ($extensionOutputCheckerHandler !== null) {
            trigger_deprecation('web-auth/webauthn-lib', '4.8.0', 'The parameter "$extensionOutputCheckerHandler" is deprecated since 4.8.0 and will be removed in 5.0.0. Please set "null" instead and inject a CheckExtensions object into the CeremonyStepManager.');
        }
        if ($algorithmManager !== null) {
            trigger_deprecation('web-auth/webauthn-lib', '4.8.0', 'The parameter "$algorithmManager" is deprecated since 4.8.0 and will be removed in 5.0.0. Please set "null" instead and inject a CheckSignature object into the CeremonyStepManager.');
        }
        $this->eventDispatcher = $eventDispatcher ?? new NullEventDispatcher();
        if ($eventDispatcher !== null) {
            trigger_deprecation('web-auth/webauthn-lib', '4.5.0', 'The parameter "$eventDispatcher" is deprecated since 4.5.0 will be removed in 5.0.0. Please use `setEventDispatcher` instead.');
        }
        if ($this->ceremonyStepManager === null) {
            trigger_deprecation('web-auth/webauthn-lib', '4.8.0', 'The parameter "$ceremonyStepManager" will become mandatory in 5.0.0. Please set a CeremonyStepManager object instead and set null for $algorithmManager and $extensionOutputCheckerHandler.');
        }
        $this->logger = new NullLogger();
        $this->ceremonyStepManagerFactory = new CeremonyStepManagerFactory();
        if ($extensionOutputCheckerHandler !== null) {
            $this->ceremonyStepManagerFactory->setExtensionOutputCheckerHandler($extensionOutputCheckerHandler);
        }
        if ($algorithmManager !== null) {
            $this->ceremonyStepManagerFactory->setAlgorithmManager($algorithmManager);
        }
    }
    public static function create(null|PublicKeyCredentialSourceRepository $publicKeyCredentialSourceRepository = null, null|TokenBindingHandler $tokenBindingHandler = null, null|ExtensionOutputCheckerHandler $extensionOutputCheckerHandler = null, null|Manager $algorithmManager = null, null|EventDispatcherInterface $eventDispatcher = null, null|CeremonyStepManager $ceremonyStepManager = null): self
    {
        return new self($publicKeyCredentialSourceRepository, $tokenBindingHandler, $extensionOutputCheckerHandler, $algorithmManager, $eventDispatcher, $ceremonyStepManager);
    }
    /**
     * @param string[] $securedRelyingPartyId
     *
     * @see https://www.w3.org/TR/webauthn/#verifying-assertion
     */
    public function check(string|PublicKeyCredentialSource $credentialId, AuthenticatorAssertionResponse $authenticatorAssertionResponse, PublicKeyCredentialRequestOptions $publicKeyCredentialRequestOptions, ServerRequestInterface|string $request, ?string $userHandle, null|array $securedRelyingPartyId = null): PublicKeyCredentialSource
    {
        if ($request instanceof ServerRequestInterface) {
            trigger_deprecation('web-auth/webauthn-lib', '4.5.0', sprintf('Passing a %s to the method `check` of the class "%s" is deprecated since 4.5.0 and will be removed in 5.0.0. Please inject the host as a string instead.', ServerRequestInterface::class, self::class));
        }
        if (is_string($credentialId)) {
            trigger_deprecation('web-auth/webauthn-lib', '4.6.0', sprintf('Passing a string as first to the method `check` of the class "%s" is deprecated since 4.6.0. Please inject a %s object instead.', self::class, PublicKeyCredentialSource::class));
        }
        if ($securedRelyingPartyId !== null) {
            trigger_deprecation('web-auth/webauthn-lib', '4.8.0', sprintf('Passing a list or secured relying party IDs to the method `check` of the class "%s" is deprecated since 4.8.0 and will be removed in 5.0.0. Please inject a CheckOrigin into the CeremonyStepManager instead.', self::class));
        }
        if ($credentialId instanceof PublicKeyCredentialSource) {
            $publicKeyCredentialSource = $credentialId;
        } else {
            $this->publicKeyCredentialSourceRepository instanceof PublicKeyCredentialSourceRepository || throw AuthenticatorResponseVerificationException::create('Please pass the Public Key Credential Source to the method "check".');
            $publicKeyCredentialSource = $this->publicKeyCredentialSourceRepository->findOneByCredentialId($credentialId);
        }
        $publicKeyCredentialSource !== null || throw AuthenticatorResponseVerificationException::create('The credential ID is invalid.');
        $host = is_string($request) ? $request : $request->getUri()->getHost();
        if ($this->ceremonyStepManager === null) {
            $this->ceremonyStepManager = $this->ceremonyStepManagerFactory->requestCeremony($securedRelyingPartyId);
        }
        try {
            $this->logger->info('Checking the authenticator assertion response', ['credentialId' => $credentialId, 'publicKeyCredentialSource' => $publicKeyCredentialSource, 'authenticatorAssertionResponse' => $authenticatorAssertionResponse, 'publicKeyCredentialRequestOptions' => $publicKeyCredentialRequestOptions, 'host' => $host, 'userHandle' => $userHandle]);
            $this->ceremonyStepManager->process($publicKeyCredentialSource, $authenticatorAssertionResponse, $publicKeyCredentialRequestOptions, $userHandle, $host);
            $publicKeyCredentialSource->counter = $authenticatorAssertionResponse->authenticatorData->signCount;
            //26.1.
            $publicKeyCredentialSource->backupEligible = $authenticatorAssertionResponse->authenticatorData->isBackupEligible();
            //26.2.
            $publicKeyCredentialSource->backupStatus = $authenticatorAssertionResponse->authenticatorData->isBackedUp();
            //26.2.
            if ($publicKeyCredentialSource->uvInitialized === \false) {
                $publicKeyCredentialSource->uvInitialized = $authenticatorAssertionResponse->authenticatorData->isUserVerified();
                //26.3.
            }
            /*
             * 26.3.
             * OPTIONALLY, if response.attestationObject is present, update credentialRecord.attestationObject to the value of response.attestationObject and update credentialRecord.attestationClientDataJSON to the value of response.clientDataJSON.
             */
            if (is_string($credentialId) && $this->publicKeyCredentialSourceRepository instanceof PublicKeyCredentialSourceRepository) {
                $this->publicKeyCredentialSourceRepository->saveCredentialSource($publicKeyCredentialSource);
            }
            //All good. We can continue.
            $this->logger->info('The assertion is valid');
            $this->logger->debug('Public Key Credential Source', ['publicKeyCredentialSource' => $publicKeyCredentialSource]);
            $this->eventDispatcher->dispatch($this->createAuthenticatorAssertionResponseValidationSucceededEvent(null, $authenticatorAssertionResponse, $publicKeyCredentialRequestOptions, $host, $userHandle, $publicKeyCredentialSource));
            // 27.
            return $publicKeyCredentialSource;
        } catch (AuthenticatorResponseVerificationException $throwable) {
            $this->logger->error('An error occurred', ['exception' => $throwable]);
            $this->eventDispatcher->dispatch($this->createAuthenticatorAssertionResponseValidationFailedEvent($publicKeyCredentialSource, $authenticatorAssertionResponse, $publicKeyCredentialRequestOptions, $host, $userHandle, $throwable));
            throw $throwable;
        }
    }
    public function setLogger(LoggerInterface $logger): void
    {
        $this->logger = $logger;
    }
    public function setEventDispatcher(EventDispatcherInterface $eventDispatcher): void
    {
        $this->eventDispatcher = $eventDispatcher;
    }
    /**
     * @deprecated since 4.8.0 and will be removed in 5.0.0. Please inject a CheckCounter object into a CeremonyStepManager instead.
     */
    public function setCounterChecker(CounterChecker $counterChecker): self
    {
        $this->ceremonyStepManagerFactory->setCounterChecker($counterChecker);
        return $this;
    }
    protected function createAuthenticatorAssertionResponseValidationSucceededEvent(null|string $credentialId, AuthenticatorAssertionResponse $authenticatorAssertionResponse, PublicKeyCredentialRequestOptions $publicKeyCredentialRequestOptions, ServerRequestInterface|string $host, ?string $userHandle, PublicKeyCredentialSource $publicKeyCredentialSource): AuthenticatorAssertionResponseValidationSucceededEvent
    {
        if ($host instanceof ServerRequestInterface) {
            trigger_deprecation('web-auth/webauthn-lib', '4.5.0', sprintf('Passing a %s to the method `createAuthenticatorAssertionResponseValidationSucceededEvent` of the class "%s" is deprecated since 4.5.0 and will be removed in 5.0.0. Please inject the host as a string instead.', ServerRequestInterface::class, self::class));
        }
        return new AuthenticatorAssertionResponseValidationSucceededEvent($credentialId, $authenticatorAssertionResponse, $publicKeyCredentialRequestOptions, $host, $userHandle, $publicKeyCredentialSource);
    }
    protected function createAuthenticatorAssertionResponseValidationFailedEvent(string|PublicKeyCredentialSource $publicKeyCredentialSource, AuthenticatorAssertionResponse $authenticatorAssertionResponse, PublicKeyCredentialRequestOptions $publicKeyCredentialRequestOptions, ServerRequestInterface|string $host, ?string $userHandle, Throwable $throwable): AuthenticatorAssertionResponseValidationFailedEvent
    {
        if ($host instanceof ServerRequestInterface) {
            trigger_deprecation('web-auth/webauthn-lib', '4.5.0', sprintf('Passing a %s to the method `createAuthenticatorAssertionResponseValidationFailedEvent` of the class "%s" is deprecated since 4.5.0 and will be removed in 5.0.0. Please inject the host as a string instead.', ServerRequestInterface::class, self::class));
        }
        return new AuthenticatorAssertionResponseValidationFailedEvent($publicKeyCredentialSource, $authenticatorAssertionResponse, $publicKeyCredentialRequestOptions, $host, $userHandle, $throwable);
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\Webauthn;

use _ContaoManager\Webauthn\AttestationStatement\AttestationObject;
/**
 * @see https://www.w3.org/TR/webauthn/#authenticatorassertionresponse
 */
class AuthenticatorAssertionResponse extends AuthenticatorResponse
{
    public function __construct(CollectedClientData $clientDataJSON, public readonly AuthenticatorData $authenticatorData, public readonly string $signature, public readonly ?string $userHandle, public readonly null|AttestationObject $attestationObject = null)
    {
        parent::__construct($clientDataJSON);
    }
    public static function create(CollectedClientData $clientDataJSON, AuthenticatorData $authenticatorData, string $signature, ?string $userHandle = null, null|AttestationObject $attestationObject = null): self
    {
        return new self($clientDataJSON, $authenticatorData, $signature, $userHandle, $attestationObject);
    }
    /**
     * @deprecated since 4.7.0. Please use the property directly.
     * @infection-ignore-all
     */
    public function getSignature(): string
    {
        return $this->signature;
    }
    /**
     * @deprecated since 4.7.0. Please use the property directly.
     * @infection-ignore-all
     */
    public function getUserHandle(): ?string
    {
        return $this->userHandle;
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\Webauthn\CertificateChainChecker;

use _ContaoManager\Webauthn\MetadataService\CertificateChain\PhpCertificateChainValidator;
/**
 * @deprecated since v4.1. Please use Webauthn\MetadataService\CertificateChainChecker\PhpCertificateChainValidator instead
 * @infection-ignore-all
 */
final class PhpCertificateChainChecker extends PhpCertificateChainValidator
{
}
<?php

declare (strict_types=1);
namespace _ContaoManager\Webauthn\CertificateChainChecker;

use _ContaoManager\Webauthn\MetadataService\CertificateChain\CertificateChainValidator;
/**
 * @deprecated since v4.1. Please use Webauthn\MetadataService\CertificateChainChecker\CertificateChainValidator instead
 * @infection-ignore-all
 */
interface CertificateChainChecker extends CertificateChainValidator
{
}
<?php

declare (strict_types=1);
namespace _ContaoManager\Webauthn;

use _ContaoManager\ParagonIE\ConstantTime\Base64UrlSafe;
use _ContaoManager\Webauthn\AuthenticationExtensions\AuthenticationExtensions;
use _ContaoManager\Webauthn\AuthenticationExtensions\AuthenticationExtensionsClientInputs;
use _ContaoManager\Webauthn\Exception\InvalidDataException;
use _ContaoManager\Webauthn\Util\Base64;
use function array_key_exists;
use function count;
use function in_array;
use const JSON_THROW_ON_ERROR;
final class PublicKeyCredentialRequestOptions extends PublicKeyCredentialOptions
{
    public const USER_VERIFICATION_REQUIREMENT_DEFAULT = null;
    public const USER_VERIFICATION_REQUIREMENT_REQUIRED = 'required';
    public const USER_VERIFICATION_REQUIREMENT_PREFERRED = 'preferred';
    public const USER_VERIFICATION_REQUIREMENT_DISCOURAGED = 'discouraged';
    public const USER_VERIFICATION_REQUIREMENTS = [self::USER_VERIFICATION_REQUIREMENT_DEFAULT, self::USER_VERIFICATION_REQUIREMENT_REQUIRED, self::USER_VERIFICATION_REQUIREMENT_PREFERRED, self::USER_VERIFICATION_REQUIREMENT_DISCOURAGED];
    /**
     * @private
     * @param PublicKeyCredentialDescriptor[] $allowCredentials
     * @param null|AuthenticationExtensions|array<string|int, mixed|AuthenticationExtensions> $extensions
     */
    public function __construct(string $challenge, public null|string $rpId = null, public array $allowCredentials = [], public null|string $userVerification = null, null|int $timeout = null, null|array|AuthenticationExtensions $extensions = null)
    {
        in_array($userVerification, self::USER_VERIFICATION_REQUIREMENTS, \true) || throw InvalidDataException::create($userVerification, 'Invalid user verification requirement');
        parent::__construct($challenge, $timeout, $extensions);
    }
    /**
     * @param PublicKeyCredentialDescriptor[] $allowCredentials
     * @param positive-int $timeout
     * @param null|AuthenticationExtensions|array<string|int, mixed|AuthenticationExtensions> $extensions
     */
    public static function create(string $challenge, null|string $rpId = null, array $allowCredentials = [], null|string $userVerification = null, null|int $timeout = null, null|array|AuthenticationExtensions $extensions = null): self
    {
        return new self($challenge, $rpId, $allowCredentials, $userVerification, $timeout, $extensions);
    }
    /**
     * @deprecated since 4.7.0. Please use the property directly.
     * @infection-ignore-all
     */
    public function setRpId(?string $rpId): self
    {
        $this->rpId = $rpId;
        return $this;
    }
    /**
     * @deprecated since 4.7.0. Please use the property directly.
     * @infection-ignore-all
     */
    public function allowCredential(PublicKeyCredentialDescriptor $allowCredential): self
    {
        $this->allowCredentials[] = $allowCredential;
        return $this;
    }
    /**
     * @deprecated since 4.7.0. No replacement. Please use the property directly.
     * @infection-ignore-all
     */
    public function allowCredentials(PublicKeyCredentialDescriptor ...$allowCredentials): self
    {
        foreach ($allowCredentials as $allowCredential) {
            $this->allowCredentials[] = $allowCredential;
        }
        return $this;
    }
    /**
     * @deprecated since 4.7.0. Please use the property directly.
     * @infection-ignore-all
     */
    public function setUserVerification(?string $userVerification): self
    {
        if ($userVerification === null) {
            $this->rpId = null;
            return $this;
        }
        in_array($userVerification, [self::USER_VERIFICATION_REQUIREMENT_REQUIRED, self::USER_VERIFICATION_REQUIREMENT_PREFERRED, self::USER_VERIFICATION_REQUIREMENT_DISCOURAGED], \true) || throw InvalidDataException::create($userVerification, 'Invalid user verification requirement');
        $this->userVerification = $userVerification;
        return $this;
    }
    /**
     * @deprecated since 4.7.0. Please use the property directly.
     * @infection-ignore-all
     */
    public function getRpId(): ?string
    {
        return $this->rpId;
    }
    /**
     * @return PublicKeyCredentialDescriptor[]
     * @deprecated since 4.7.0. Please use the property directly.
     * @infection-ignore-all
     */
    public function getAllowCredentials(): array
    {
        return $this->allowCredentials;
    }
    /**
     * @deprecated since 4.7.0. Please use the property directly.
     * @infection-ignore-all
     */
    public function getUserVerification(): ?string
    {
        return $this->userVerification;
    }
    /**
     * @deprecated since 4.8.0. Please use {Webauthn\Denormalizer\WebauthnSerializerFactory} for converting the object.
     * @infection-ignore-all
     */
    public static function createFromString(string $data): static
    {
        $data = json_decode($data, \true, flags: JSON_THROW_ON_ERROR);
        return self::createFromArray($data);
    }
    /**
     * @param mixed[] $json
     * @deprecated since 4.8.0. Please use {Webauthn\Denormalizer\WebauthnSerializerFactory} for converting the object.
     * @infection-ignore-all
     */
    public static function createFromArray(array $json): static
    {
        array_key_exists('challenge', $json) || throw InvalidDataException::create($json, 'Invalid input. "challenge" is missing.');
        $allowCredentials = [];
        $allowCredentialList = $json['allowCredentials'] ?? [];
        foreach ($allowCredentialList as $allowCredential) {
            $allowCredentials[] = PublicKeyCredentialDescriptor::createFromArray($allowCredential);
        }
        $challenge = Base64::decode($json['challenge']);
        $extensions = isset($json['extensions']) ? AuthenticationExtensionsClientInputs::createFromArray($json['extensions']) : AuthenticationExtensionsClientInputs::create();
        return self::create($challenge, $json['rpId'] ?? null, $allowCredentials, $json['userVerification'] ?? null, $json['timeout'] ?? null, $extensions);
    }
    /**
     * @return mixed[]
     */
    public function jsonSerialize(): array
    {
        trigger_deprecation('web-auth/webauthn-bundle', '4.9.0', 'The "%s" method is deprecated and will be removed in 5.0. Please use the serializer instead.', __METHOD__);
        $json = ['challenge' => Base64UrlSafe::encodeUnpadded($this->challenge)];
        if ($this->rpId !== null) {
            $json['rpId'] = $this->rpId;
        }
        if ($this->userVerification !== null) {
            $json['userVerification'] = $this->userVerification;
        }
        if (count($this->allowCredentials) !== 0) {
            $json['allowCredentials'] = $this->allowCredentials;
        }
        if ($this->extensions->count() !== 0) {
            $json['extensions'] = $this->extensions;
        }
        if ($this->timeout !== null) {
            $json['timeout'] = $this->timeout;
        }
        return $json;
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\Webauthn;

use _ContaoManager\CBOR\ByteStringObject;
use _ContaoManager\CBOR\Decoder;
use _ContaoManager\CBOR\ListObject;
use _ContaoManager\CBOR\MapObject;
use _ContaoManager\CBOR\NegativeIntegerObject;
use _ContaoManager\CBOR\TextStringObject;
use _ContaoManager\CBOR\UnsignedIntegerObject;
use _ContaoManager\Symfony\Component\Uid\Uuid;
use _ContaoManager\Webauthn\AuthenticationExtensions\AuthenticationExtensionsClientOutputsLoader;
use _ContaoManager\Webauthn\Exception\InvalidDataException;
use function chr;
use function ord;
final class AuthenticatorDataLoader
{
    private readonly Decoder $decoder;
    private function __construct()
    {
        $this->decoder = Decoder::create();
    }
    public static function create(): self
    {
        return new self();
    }
    public function load(string $authData): AuthenticatorData
    {
        $authData = $this->fixIncorrectEdDSAKey($authData);
        $authDataStream = new StringStream($authData);
        $rp_id_hash = $authDataStream->read(32);
        $flags = $authDataStream->read(1);
        $signCount = $authDataStream->read(4);
        $signCount = unpack('N', $signCount);
        $attestedCredentialData = null;
        if (0 !== (ord($flags) & AuthenticatorData::FLAG_AT)) {
            $aaguid = Uuid::fromBinary($authDataStream->read(16));
            $credentialLength = $authDataStream->read(2);
            $credentialLength = unpack('n', $credentialLength);
            $credentialId = $authDataStream->read($credentialLength[1]);
            $credentialPublicKey = $this->decoder->decode($authDataStream);
            $credentialPublicKey instanceof MapObject || throw InvalidDataException::create($authData, 'The data does not contain a valid credential public key.');
            $attestedCredentialData = AttestedCredentialData::create($aaguid, $credentialId, (string) $credentialPublicKey);
        }
        $extension = null;
        if (0 !== (ord($flags) & AuthenticatorData::FLAG_ED)) {
            $extension = $this->decoder->decode($authDataStream);
            $extension = AuthenticationExtensionsClientOutputsLoader::load($extension);
        }
        $authDataStream->isEOF() || throw InvalidDataException::create($authData, 'Invalid authentication data. Presence of extra bytes.');
        $authDataStream->close();
        return AuthenticatorData::create($authData, $rp_id_hash, $flags, $signCount[1], $attestedCredentialData, $extension);
    }
    private function fixIncorrectEdDSAKey(string $data): string
    {
        $needle = hex2bin('a301634f4b500327206745643235353139');
        $correct = hex2bin('a401634f4b500327206745643235353139');
        $position = mb_strpos($data, $needle, 0, '8bit');
        if ($position === \false) {
            return $data;
        }
        $begin = mb_substr($data, 0, $position, '8bit');
        $end = mb_substr($data, $position, null, '8bit');
        $end = str_replace($needle, $correct, $end);
        $cbor = new StringStream($end);
        $badKey = $this->decoder->decode($cbor);
        $badKey instanceof MapObject && $cbor->isEOF() || throw InvalidDataException::create($end, 'Invalid authentication data. Presence of extra bytes.');
        $badX = $badKey->get(-2);
        $badX instanceof ListObject || throw InvalidDataException::create($end, 'Invalid authentication data.');
        $keyBytes = array_reduce($badX->normalize(), static fn(string $carry, string $item): string => $carry . chr((int) $item), '');
        $correctX = ByteStringObject::create($keyBytes);
        $correctKey = MapObject::create()->add(UnsignedIntegerObject::create(1), TextStringObject::create('OKP'))->add(UnsignedIntegerObject::create(3), NegativeIntegerObject::create(-8))->add(NegativeIntegerObject::create(-1), TextStringObject::create('Ed25519'))->add(NegativeIntegerObject::create(-2), $correctX);
        return $begin . $correctKey;
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\Webauthn;

/**
 * @deprecated
 * @infection-ignore-all
 */
interface PublicKeyCredentialSourceRepository
{
    public function findOneByCredentialId(string $publicKeyCredentialId): ?PublicKeyCredentialSource;
    /**
     * @return PublicKeyCredentialSource[]
     */
    public function findAllForUserEntity(PublicKeyCredentialUserEntity $publicKeyCredentialUserEntity): array;
    public function saveCredentialSource(PublicKeyCredentialSource $publicKeyCredentialSource): void;
}
<?php

declare (strict_types=1);
namespace _ContaoManager\Webauthn\TrustPath;

use _ContaoManager\Webauthn\Exception\InvalidTrustPathException;
use function array_key_exists;
use function is_array;
use function is_string;
/**
 * @deprecated since 4.9.0 and will be removed in 5.0.0. Use the serializer instead
 */
final class TrustPathLoader
{
    /**
     * @param mixed[] $data
     */
    public static function loadTrustPath(array $data): TrustPath
    {
        return match (\true) {
            $data === [] || $data === ['type' => EmptyTrustPath::class] => EmptyTrustPath::create(),
            array_key_exists('x5c', $data) && is_array($data['x5c']) => CertificateTrustPath::create($data['x5c']),
            array_key_exists('ecdaaKeyId', $data) && is_string($data['ecdaaKeyId']) => new EcdaaKeyIdTrustPath($data['ecdaaKeyId']),
            default => throw InvalidTrustPathException::create('Unsupported trust path'),
        };
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\Webauthn\TrustPath;

use _ContaoManager\Webauthn\Exception\InvalidTrustPathException;
use function array_key_exists;
/**
 * @deprecated since 4.2.0 and will be removed in 5.0.0. The ECDAA Trust Anchor does no longer exist in Webauthn specification.
 * @infection-ignore-all
 */
final class EcdaaKeyIdTrustPath implements TrustPath
{
    public function __construct(private readonly string $ecdaaKeyId)
    {
    }
    public function getEcdaaKeyId(): string
    {
        return $this->ecdaaKeyId;
    }
    /**
     * @return string[]
     */
    public function jsonSerialize(): array
    {
        return ['type' => self::class, 'ecdaaKeyId' => $this->ecdaaKeyId];
    }
    public static function createFromArray(array $data): static
    {
        array_key_exists('ecdaaKeyId', $data) || throw InvalidTrustPathException::create('The trust path type is invalid');
        return new self($data['ecdaaKeyId']);
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\Webauthn\TrustPath;

use JsonSerializable;
interface TrustPath extends JsonSerializable
{
    /**
     * @param array<string, mixed> $data
     * @deprecated since 4.8.0. Please use {Webauthn\Denormalizer\WebauthnSerializerFactory} for converting the object.
     * @infection-ignore-all
     */
    public static function createFromArray(array $data): static;
}
<?php

declare (strict_types=1);
namespace _ContaoManager\Webauthn\TrustPath;

final class EmptyTrustPath implements TrustPath
{
    public static function create(): self
    {
        return new self();
    }
    /**
     * @return string[]
     */
    public function jsonSerialize(): array
    {
        trigger_deprecation('web-auth/webauthn-bundle', '4.9.0', 'The "%s" method is deprecated and will be removed in 5.0. Please use the serializer instead.', __METHOD__);
        return ['type' => self::class];
    }
    /**
     * @deprecated since 4.8.0. Please use {Webauthn\Denormalizer\WebauthnSerializerFactory} for converting the object.
     * @infection-ignore-all
     */
    public static function createFromArray(array $data): static
    {
        return self::create();
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\Webauthn\TrustPath;

use _ContaoManager\Webauthn\Exception\InvalidTrustPathException;
use function array_key_exists;
use function is_array;
final class CertificateTrustPath implements TrustPath
{
    /**
     * @param string[] $certificates
     */
    public function __construct(public readonly array $certificates)
    {
    }
    /**
     * @param string[] $certificates
     */
    public static function create(array $certificates): self
    {
        return new self($certificates);
    }
    /**
     * @return string[]
     * @deprecated since 4.7.0. Please use the property directly.
     * @infection-ignore-all
     */
    public function getCertificates(): array
    {
        return $this->certificates;
    }
    /**
     * @deprecated since 4.8.0. Please use {Webauthn\Denormalizer\WebauthnSerializerFactory} for converting the object.
     * @infection-ignore-all
     */
    public static function createFromArray(array $data): static
    {
        array_key_exists('x5c', $data) || throw InvalidTrustPathException::create('The trust path type is invalid');
        $x5c = $data['x5c'];
        is_array($x5c) || throw InvalidTrustPathException::create('The trust path type is invalid. The parameter "x5c" shall contain strings.');
        return self::create($x5c);
    }
    /**
     * @return mixed[]
     */
    public function jsonSerialize(): array
    {
        trigger_deprecation('web-auth/webauthn-bundle', '4.9.0', 'The "%s" method is deprecated and will be removed in 5.0. Please use the serializer instead.', __METHOD__);
        return ['type' => self::class, 'x5c' => $this->certificates];
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\Webauthn;

use JsonSerializable;
abstract class PublicKeyCredentialEntity implements JsonSerializable
{
    public function __construct(public readonly string $name, public readonly ?string $icon)
    {
    }
    /**
     * @deprecated since 4.7.0. Please use the property directly.
     * @infection-ignore-all
     */
    public function getName(): string
    {
        return $this->name;
    }
    /**
     * @deprecated since 4.7.0. Please use the property directly.
     * @infection-ignore-all
     */
    public function getIcon(): ?string
    {
        return $this->icon;
    }
    /**
     * @return mixed[]
     */
    public function jsonSerialize(): array
    {
        $json = ['name' => $this->name];
        if ($this->icon !== null) {
            $json['icon'] = $this->icon;
        }
        return $json;
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\Webauthn\ClientDataCollector;

use _ContaoManager\Webauthn\AuthenticatorResponse;
use _ContaoManager\Webauthn\CollectedClientData;
use _ContaoManager\Webauthn\PublicKeyCredentialOptions;
interface ClientDataCollector
{
    /**
     * @return string[]
     */
    public function supportedTypes(): array;
    public function verifyCollectedClientData(CollectedClientData $collectedClientData, PublicKeyCredentialOptions $publicKeyCredentialOptions, AuthenticatorResponse $authenticatorResponse, string $host): void;
}
<?php

declare (strict_types=1);
namespace _ContaoManager\Webauthn\ClientDataCollector;

use _ContaoManager\Webauthn\AuthenticatorResponse;
use _ContaoManager\Webauthn\CollectedClientData;
use _ContaoManager\Webauthn\Exception\AuthenticatorResponseVerificationException;
use _ContaoManager\Webauthn\PublicKeyCredentialOptions;
use function in_array;
final class ClientDataCollectorManager
{
    /**
     * @param ClientDataCollector[] $clientDataCollectors
     */
    public function __construct(private readonly iterable $clientDataCollectors)
    {
    }
    public function collect(CollectedClientData $collectedClientData, PublicKeyCredentialOptions $publicKeyCredentialOptions, AuthenticatorResponse $authenticatorResponse, string $host): void
    {
        foreach ($this->clientDataCollectors as $clientDataCollector) {
            if (in_array($collectedClientData->type, $clientDataCollector->supportedTypes(), \true)) {
                $clientDataCollector->verifyCollectedClientData($collectedClientData, $publicKeyCredentialOptions, $authenticatorResponse, $host);
                return;
            }
        }
        throw AuthenticatorResponseVerificationException::create('No client data collector found.');
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\Webauthn\ClientDataCollector;

use _ContaoManager\Webauthn\AuthenticatorResponse;
use _ContaoManager\Webauthn\CollectedClientData;
use _ContaoManager\Webauthn\Exception\AuthenticatorResponseVerificationException;
use _ContaoManager\Webauthn\PublicKeyCredentialOptions;
use function in_array;
use function sprintf;
final class WebauthnAuthenticationCollector implements ClientDataCollector
{
    public function supportedTypes(): array
    {
        return ['webauthn.get', 'webauthn.create'];
    }
    public function verifyCollectedClientData(CollectedClientData $collectedClientData, PublicKeyCredentialOptions $publicKeyCredentialOptions, AuthenticatorResponse $authenticatorResponse, string $host): void
    {
        in_array($collectedClientData->type, $this->supportedTypes(), \true) || throw AuthenticatorResponseVerificationException::create(sprintf('The client data type is not "%s" supported.', implode('", "', $this->supportedTypes())));
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\Webauthn\Counter;

use _ContaoManager\Psr\Log\LoggerInterface;
use _ContaoManager\Psr\Log\NullLogger;
use _ContaoManager\Webauthn\Exception\CounterException;
use _ContaoManager\Webauthn\MetadataService\CanLogData;
use _ContaoManager\Webauthn\PublicKeyCredentialSource;
final class ThrowExceptionIfInvalid implements CounterChecker, CanLogData
{
    public function __construct(private LoggerInterface $logger = new NullLogger())
    {
    }
    public function setLogger(LoggerInterface $logger): void
    {
        $this->logger = $logger;
    }
    public function check(PublicKeyCredentialSource $publicKeyCredentialSource, int $currentCounter): void
    {
        try {
            $currentCounter > $publicKeyCredentialSource->counter || throw CounterException::create($currentCounter, $publicKeyCredentialSource->counter, 'Invalid counter.');
        } catch (CounterException $throwable) {
            $this->logger->error('The counter is invalid', ['current' => $currentCounter, 'new' => $publicKeyCredentialSource->counter]);
            throw $throwable;
        }
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\Webauthn\Counter;

use _ContaoManager\Webauthn\PublicKeyCredentialSource;
interface CounterChecker
{
    public function check(PublicKeyCredentialSource $publicKeyCredentialSource, int $currentCounter): void;
}
<?php

declare (strict_types=1);
namespace _ContaoManager\Webauthn\Denormalizer;

use _ContaoManager\Symfony\Component\Serializer\Normalizer\DenormalizerInterface;
use _ContaoManager\Symfony\Component\Serializer\Normalizer\NormalizerInterface;
use _ContaoManager\Webauthn\AuthenticationExtensions\AuthenticationExtension;
use _ContaoManager\Webauthn\AuthenticationExtensions\AuthenticationExtensions;
use _ContaoManager\Webauthn\AuthenticationExtensions\AuthenticationExtensionsClientInputs;
use _ContaoManager\Webauthn\AuthenticationExtensions\AuthenticationExtensionsClientOutputs;
use function assert;
use function in_array;
use function is_array;
use function is_string;
final class AuthenticationExtensionsDenormalizer implements DenormalizerInterface, NormalizerInterface
{
    public function denormalize(mixed $data, string $type, ?string $format = null, array $context = []): mixed
    {
        if ($data instanceof AuthenticationExtensions) {
            return AuthenticationExtensions::create($data->extensions);
        }
        assert(is_array($data), 'The data should be an array.');
        foreach ($data as $key => $value) {
            if (!is_string($key)) {
                continue;
            }
            $data[$key] = AuthenticationExtension::create($key, $value);
        }
        return AuthenticationExtensions::create($data);
    }
    public function supportsDenormalization(mixed $data, string $type, ?string $format = null, array $context = []): bool
    {
        return in_array($type, [AuthenticationExtensions::class, AuthenticationExtensionsClientOutputs::class, AuthenticationExtensionsClientInputs::class], \true);
    }
    /**
     * @return array<class-string, bool>
     */
    public function getSupportedTypes(?string $format): array
    {
        return [AuthenticationExtensions::class => \true, AuthenticationExtensionsClientInputs::class => \true, AuthenticationExtensionsClientOutputs::class => \true];
    }
    /**
     * @return array<string, mixed>
     */
    public function normalize(mixed $data, ?string $format = null, array $context = []): array
    {
        assert($data instanceof AuthenticationExtensions);
        $extensions = [];
        foreach ($data->extensions as $extension) {
            $extensions[$extension->name] = $extension->value;
        }
        return $extensions;
    }
    public function supportsNormalization(mixed $data, ?string $format = null, array $context = []): bool
    {
        return $data instanceof AuthenticationExtensions;
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\Webauthn\Denormalizer;

use _ContaoManager\Symfony\Component\Serializer\Normalizer\DenormalizerInterface;
use _ContaoManager\Webauthn\AttestationStatement\AttestationStatement;
use _ContaoManager\Webauthn\AttestationStatement\AttestationStatementSupportManager;
final class AttestationStatementDenormalizer implements DenormalizerInterface
{
    public function __construct(private readonly AttestationStatementSupportManager $attestationStatementSupportManager)
    {
    }
    public function denormalize(mixed $data, string $type, ?string $format = null, array $context = []): mixed
    {
        $attestationStatementSupport = $this->attestationStatementSupportManager->get($data['fmt']);
        return $attestationStatementSupport->load($data);
    }
    public function supportsDenormalization(mixed $data, string $type, ?string $format = null, array $context = []): bool
    {
        return $type === AttestationStatement::class;
    }
    /**
     * @return array<class-string, bool>
     */
    public function getSupportedTypes(?string $format): array
    {
        return [AttestationStatement::class => \true];
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\Webauthn\Denormalizer;

use _ContaoManager\Symfony\Component\Serializer\Normalizer\NormalizerInterface;
use _ContaoManager\Webauthn\AuthenticationExtensions\AuthenticationExtension;
use function assert;
final class AuthenticationExtensionNormalizer implements NormalizerInterface
{
    /**
     * @return array<class-string, bool>
     */
    public function getSupportedTypes(?string $format): array
    {
        return [AuthenticationExtension::class => \true];
    }
    /**
     * @return array<mixed>
     */
    public function normalize(mixed $data, ?string $format = null, array $context = []): array
    {
        assert($data instanceof AuthenticationExtension);
        return $data->value;
    }
    public function supportsNormalization(mixed $data, ?string $format = null, array $context = []): bool
    {
        return $data instanceof AuthenticationExtension;
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\Webauthn\Denormalizer;

use _ContaoManager\Symfony\Component\Serializer\Normalizer\DenormalizerInterface;
use _ContaoManager\Symfony\Component\Serializer\Normalizer\NormalizerInterface;
use _ContaoManager\Webauthn\Exception\InvalidTrustPathException;
use _ContaoManager\Webauthn\TrustPath\CertificateTrustPath;
use _ContaoManager\Webauthn\TrustPath\EcdaaKeyIdTrustPath;
use _ContaoManager\Webauthn\TrustPath\EmptyTrustPath;
use _ContaoManager\Webauthn\TrustPath\TrustPath;
use function array_key_exists;
use function assert;
final class TrustPathDenormalizer implements DenormalizerInterface, NormalizerInterface
{
    public function denormalize(mixed $data, string $type, ?string $format = null, array $context = []): mixed
    {
        return match (\true) {
            array_key_exists('ecdaaKeyId', $data) => new EcdaaKeyIdTrustPath($data),
            array_key_exists('x5c', $data) => CertificateTrustPath::create($data),
            $data === [], isset($data['type']) && $data['type'] === EmptyTrustPath::class => EmptyTrustPath::create(),
            default => throw new InvalidTrustPathException('Unsupported trust path type'),
        };
    }
    public function supportsDenormalization(mixed $data, string $type, ?string $format = null, array $context = []): bool
    {
        return $type === TrustPath::class;
    }
    /**
     * @return array<class-string, bool>
     */
    public function getSupportedTypes(?string $format): array
    {
        return [TrustPath::class => \true];
    }
    /**
     * @return array<string, mixed>
     */
    public function normalize(mixed $data, ?string $format = null, array $context = []): array
    {
        assert($data instanceof TrustPath);
        return match (\true) {
            $data instanceof EcdaaKeyIdTrustPath => ['ecdaaKeyId' => $data->getEcdaaKeyId()],
            $data instanceof CertificateTrustPath => ['x5c' => $data->certificates],
            $data instanceof EmptyTrustPath => [],
            default => throw new InvalidTrustPathException('Unsupported trust path type'),
        };
    }
    public function supportsNormalization(mixed $data, ?string $format = null, array $context = []): bool
    {
        return $data instanceof TrustPath;
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\Webauthn\Denormalizer;

use _ContaoManager\ParagonIE\ConstantTime\Base64UrlSafe;
use _ContaoManager\Symfony\Component\Serializer\Normalizer\DenormalizerAwareInterface;
use _ContaoManager\Symfony\Component\Serializer\Normalizer\DenormalizerAwareTrait;
use _ContaoManager\Symfony\Component\Serializer\Normalizer\DenormalizerInterface;
use _ContaoManager\Webauthn\AuthenticatorResponse;
use _ContaoManager\Webauthn\Exception\InvalidDataException;
use _ContaoManager\Webauthn\PublicKeyCredential;
use _ContaoManager\Webauthn\Util\Base64;
use function array_key_exists;
final class PublicKeyCredentialDenormalizer implements DenormalizerInterface, DenormalizerAwareInterface
{
    use DenormalizerAwareTrait;
    public function denormalize(mixed $data, string $type, ?string $format = null, array $context = []): mixed
    {
        if (!array_key_exists('id', $data)) {
            return $data;
        }
        $id = Base64UrlSafe::decodeNoPadding($data['id']);
        $rawId = Base64::decode($data['rawId']);
        hash_equals($id, $rawId) || throw InvalidDataException::create($data, 'Invalid ID');
        $data['rawId'] = $rawId;
        return PublicKeyCredential::create(null, $data['type'], $data['rawId'], $this->denormalizer->denormalize($data['response'], AuthenticatorResponse::class, $format, $context));
    }
    public function supportsDenormalization(mixed $data, string $type, ?string $format = null, array $context = []): bool
    {
        return $type === PublicKeyCredential::class;
    }
    /**
     * @return array<class-string, bool>
     */
    public function getSupportedTypes(?string $format): array
    {
        return [PublicKeyCredential::class => \true];
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\Webauthn\Denormalizer;

use RuntimeException;
use _ContaoManager\Symfony\Component\PropertyInfo\Extractor\PhpDocExtractor;
use _ContaoManager\Symfony\Component\PropertyInfo\Extractor\ReflectionExtractor;
use _ContaoManager\Symfony\Component\PropertyInfo\PropertyInfoExtractor;
use _ContaoManager\Symfony\Component\Serializer\Encoder\JsonEncoder;
use _ContaoManager\Symfony\Component\Serializer\Normalizer\ArrayDenormalizer;
use _ContaoManager\Symfony\Component\Serializer\Normalizer\ObjectNormalizer;
use _ContaoManager\Symfony\Component\Serializer\Normalizer\UidNormalizer;
use _ContaoManager\Symfony\Component\Serializer\Serializer;
use _ContaoManager\Symfony\Component\Serializer\SerializerInterface;
use _ContaoManager\Webauthn\AttestationStatement\AttestationStatementSupportManager;
use function sprintf;
final class WebauthnSerializerFactory
{
    private const PACKAGE_SYMFONY_PROPERTY_INFO = 'symfony/property-info';
    private const PACKAGE_SYMFONY_SERIALIZER = 'symfony/serializer';
    private const PACKAGE_PHPDOCUMENTOR_REFLECTION_DOCBLOCK = 'phpdocumentor/reflection-docblock';
    public function __construct(private readonly AttestationStatementSupportManager $attestationStatementSupportManager)
    {
    }
    public function create(): SerializerInterface
    {
        foreach (self::getRequiredSerializerClasses() as $class => $package) {
            if (!class_exists($class)) {
                throw new RuntimeException(sprintf('The class "%s" is required. Please install the package "%s" to use this feature.', $class, $package));
            }
        }
        $denormalizers = [new ExtensionDescriptorDenormalizer(), new VerificationMethodANDCombinationsDenormalizer(), new AuthenticationExtensionNormalizer(), new PublicKeyCredentialDescriptorNormalizer(), new AttestedCredentialDataNormalizer(), new AttestationObjectDenormalizer(), new AttestationStatementDenormalizer($this->attestationStatementSupportManager), new AuthenticationExtensionsDenormalizer(), new AuthenticatorAssertionResponseDenormalizer(), new AuthenticatorAttestationResponseDenormalizer(), new AuthenticatorDataDenormalizer(), new AuthenticatorResponseDenormalizer(), new CollectedClientDataDenormalizer(), new PublicKeyCredentialDenormalizer(), new PublicKeyCredentialOptionsDenormalizer(), new PublicKeyCredentialSourceDenormalizer(), new PublicKeyCredentialUserEntityDenormalizer(), new TrustPathDenormalizer(), new UidNormalizer(), new ArrayDenormalizer(), new ObjectNormalizer(propertyTypeExtractor: new PropertyInfoExtractor(typeExtractors: [new PhpDocExtractor(), new ReflectionExtractor()]))];
        return new Serializer($denormalizers, [new JsonEncoder()]);
    }
    /**
     * @return array<class-string, string>
     */
    private static function getRequiredSerializerClasses(): array
    {
        return [UidNormalizer::class => self::PACKAGE_SYMFONY_SERIALIZER, ArrayDenormalizer::class => self::PACKAGE_SYMFONY_SERIALIZER, ObjectNormalizer::class => self::PACKAGE_SYMFONY_SERIALIZER, PropertyInfoExtractor::class => self::PACKAGE_SYMFONY_PROPERTY_INFO, PhpDocExtractor::class => self::PACKAGE_PHPDOCUMENTOR_REFLECTION_DOCBLOCK, ReflectionExtractor::class => self::PACKAGE_SYMFONY_PROPERTY_INFO, JsonEncoder::class => self::PACKAGE_SYMFONY_SERIALIZER, Serializer::class => self::PACKAGE_SYMFONY_SERIALIZER];
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\Webauthn\Denormalizer;

use _ContaoManager\Symfony\Component\Serializer\Normalizer\DenormalizerAwareInterface;
use _ContaoManager\Symfony\Component\Serializer\Normalizer\DenormalizerAwareTrait;
use _ContaoManager\Symfony\Component\Serializer\Normalizer\DenormalizerInterface;
use _ContaoManager\Webauthn\CollectedClientData;
use const JSON_THROW_ON_ERROR;
final class CollectedClientDataDenormalizer implements DenormalizerInterface, DenormalizerAwareInterface
{
    use DenormalizerAwareTrait;
    public function denormalize(mixed $data, string $type, ?string $format = null, array $context = []): mixed
    {
        return CollectedClientData::create($data, json_decode($data, \true, flags: JSON_THROW_ON_ERROR));
    }
    public function supportsDenormalization(mixed $data, string $type, ?string $format = null, array $context = []): bool
    {
        return $type === CollectedClientData::class;
    }
    /**
     * @return array<class-string, bool>
     */
    public function getSupportedTypes(?string $format): array
    {
        return [CollectedClientData::class => \true];
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\Webauthn\Denormalizer;

use _ContaoManager\Symfony\Component\Serializer\Normalizer\DenormalizerInterface;
use _ContaoManager\Webauthn\Exception\InvalidDataException;
use _ContaoManager\Webauthn\PublicKeyCredentialParameters;
use function array_key_exists;
final class PublicKeyCredentialParametersDenormalizer implements DenormalizerInterface
{
    public function denormalize(mixed $data, string $type, ?string $format = null, array $context = []): mixed
    {
        if (!array_key_exists('type', $data) || !array_key_exists('alg', $data)) {
            throw new InvalidDataException($data, 'Missing type or alg');
        }
        return PublicKeyCredentialParameters::create($data['type'], $data['alg']);
    }
    public function supportsDenormalization(mixed $data, string $type, ?string $format = null, array $context = []): bool
    {
        return $type === PublicKeyCredentialParameters::class;
    }
    /**
     * @return array<class-string, bool>
     */
    public function getSupportedTypes(?string $format): array
    {
        return [PublicKeyCredentialParameters::class => \true];
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\Webauthn\Denormalizer;

use _ContaoManager\ParagonIE\ConstantTime\Base64UrlSafe;
use _ContaoManager\Symfony\Component\Serializer\Normalizer\DenormalizerAwareInterface;
use _ContaoManager\Symfony\Component\Serializer\Normalizer\DenormalizerAwareTrait;
use _ContaoManager\Symfony\Component\Serializer\Normalizer\DenormalizerInterface;
use _ContaoManager\Webauthn\AttestationStatement\AttestationObject;
use _ContaoManager\Webauthn\AuthenticatorAttestationResponse;
use _ContaoManager\Webauthn\CollectedClientData;
use _ContaoManager\Webauthn\Util\Base64;
final class AuthenticatorAttestationResponseDenormalizer implements DenormalizerInterface, DenormalizerAwareInterface
{
    use DenormalizerAwareTrait;
    public function denormalize(mixed $data, string $type, ?string $format = null, array $context = []): mixed
    {
        $data['clientDataJSON'] = Base64UrlSafe::decodeNoPadding($data['clientDataJSON']);
        $data['attestationObject'] = Base64::decode($data['attestationObject']);
        $clientDataJSON = $this->denormalizer->denormalize($data['clientDataJSON'], CollectedClientData::class, $format, $context);
        $attestationObject = $this->denormalizer->denormalize($data['attestationObject'], AttestationObject::class, $format, $context);
        return AuthenticatorAttestationResponse::create($clientDataJSON, $attestationObject, $data['transports'] ?? []);
    }
    public function supportsDenormalization(mixed $data, string $type, ?string $format = null, array $context = []): bool
    {
        return $type === AuthenticatorAttestationResponse::class;
    }
    /**
     * @return array<class-string, bool>
     */
    public function getSupportedTypes(?string $format): array
    {
        return [AuthenticatorAttestationResponse::class => \true];
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\Webauthn\Denormalizer;

use _ContaoManager\Symfony\Component\Serializer\Normalizer\NormalizerAwareInterface;
use _ContaoManager\Symfony\Component\Serializer\Normalizer\NormalizerAwareTrait;
use _ContaoManager\Symfony\Component\Serializer\Normalizer\NormalizerInterface;
use _ContaoManager\Webauthn\AttestedCredentialData;
use function assert;
final class AttestedCredentialDataNormalizer implements NormalizerInterface, NormalizerAwareInterface
{
    use NormalizerAwareTrait;
    /**
     * @return array<string, mixed>
     */
    public function normalize(mixed $data, ?string $format = null, array $context = []): array
    {
        assert($data instanceof AttestedCredentialData);
        $result = ['aaguid' => $this->normalizer->normalize($data->aaguid, $format, $context), 'credentialId' => base64_encode($data->credentialId)];
        if ($data->credentialPublicKey !== null) {
            $result['credentialPublicKey'] = base64_encode($data->credentialPublicKey);
        }
        return $result;
    }
    public function supportsNormalization(mixed $data, ?string $format = null, array $context = []): bool
    {
        return $data instanceof AttestedCredentialData;
    }
    public function getSupportedTypes(?string $format): array
    {
        return [AttestedCredentialData::class => \true];
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\Webauthn\Denormalizer;

use _ContaoManager\ParagonIE\ConstantTime\Base64UrlSafe;
use _ContaoManager\Symfony\Component\Serializer\Normalizer\NormalizerAwareInterface;
use _ContaoManager\Symfony\Component\Serializer\Normalizer\NormalizerAwareTrait;
use _ContaoManager\Symfony\Component\Serializer\Normalizer\NormalizerInterface;
use _ContaoManager\Webauthn\PublicKeyCredentialDescriptor;
use function assert;
use function count;
final class PublicKeyCredentialDescriptorNormalizer implements NormalizerInterface, NormalizerAwareInterface
{
    use NormalizerAwareTrait;
    /**
     * @return array<string, mixed>
     */
    public function normalize(mixed $data, ?string $format = null, array $context = []): array
    {
        assert($data instanceof PublicKeyCredentialDescriptor);
        $result = ['type' => $data->type, 'id' => Base64UrlSafe::encodeUnpadded($data->id)];
        if (count($data->transports) !== 0) {
            $result['transports'] = $data->transports;
        }
        return $result;
    }
    public function supportsNormalization(mixed $data, ?string $format = null, array $context = []): bool
    {
        return $data instanceof PublicKeyCredentialDescriptor;
    }
    public function getSupportedTypes(?string $format): array
    {
        return [PublicKeyCredentialDescriptor::class => \true];
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\Webauthn\Denormalizer;

use _ContaoManager\CBOR\ByteStringObject;
use _ContaoManager\CBOR\Decoder;
use _ContaoManager\CBOR\ListObject;
use _ContaoManager\CBOR\MapObject;
use _ContaoManager\CBOR\NegativeIntegerObject;
use _ContaoManager\CBOR\TextStringObject;
use _ContaoManager\CBOR\UnsignedIntegerObject;
use _ContaoManager\Symfony\Component\Serializer\Normalizer\DenormalizerAwareInterface;
use _ContaoManager\Symfony\Component\Serializer\Normalizer\DenormalizerAwareTrait;
use _ContaoManager\Symfony\Component\Serializer\Normalizer\DenormalizerInterface;
use _ContaoManager\Symfony\Component\Uid\Uuid;
use _ContaoManager\Webauthn\AttestedCredentialData;
use _ContaoManager\Webauthn\AuthenticationExtensions\AuthenticationExtensions;
use _ContaoManager\Webauthn\AuthenticationExtensions\AuthenticationExtensionsClientOutputsLoader;
use _ContaoManager\Webauthn\AuthenticatorData;
use _ContaoManager\Webauthn\Exception\InvalidDataException;
use _ContaoManager\Webauthn\StringStream;
use function chr;
use function ord;
final class AuthenticatorDataDenormalizer implements DenormalizerInterface, DenormalizerAwareInterface
{
    use DenormalizerAwareTrait;
    private readonly Decoder $decoder;
    public function __construct()
    {
        $this->decoder = Decoder::create();
    }
    public function denormalize(mixed $data, string $type, ?string $format = null, array $context = []): mixed
    {
        $authData = $this->fixIncorrectEdDSAKey($data);
        $authDataStream = new StringStream($authData);
        $rp_id_hash = $authDataStream->read(32);
        $flags = $authDataStream->read(1);
        $signCount = $authDataStream->read(4);
        $signCount = unpack('N', $signCount);
        $attestedCredentialData = null;
        if (0 !== (ord($flags) & AuthenticatorData::FLAG_AT)) {
            $aaguid = Uuid::fromBinary($authDataStream->read(16));
            $credentialLength = $authDataStream->read(2);
            $credentialLength = unpack('n', $credentialLength);
            $credentialId = $authDataStream->read($credentialLength[1]);
            $credentialPublicKey = $this->decoder->decode($authDataStream);
            $credentialPublicKey instanceof MapObject || throw InvalidDataException::create($authData, 'The data does not contain a valid credential public key.');
            $attestedCredentialData = AttestedCredentialData::create($aaguid, $credentialId, (string) $credentialPublicKey);
        }
        $extension = null;
        if (0 !== (ord($flags) & AuthenticatorData::FLAG_ED)) {
            $extension = $this->decoder->decode($authDataStream);
            $extension = AuthenticationExtensionsClientOutputsLoader::load($extension);
        }
        $authDataStream->isEOF() || throw InvalidDataException::create($authData, 'Invalid authentication data. Presence of extra bytes.');
        $authDataStream->close();
        return AuthenticatorData::create($authData, $rp_id_hash, $flags, $signCount[1], $attestedCredentialData, $extension === null ? null : $this->denormalizer->denormalize($extension, AuthenticationExtensions::class, $format, $context));
    }
    public function supportsDenormalization(mixed $data, string $type, ?string $format = null, array $context = []): bool
    {
        return $type === AuthenticatorData::class;
    }
    /**
     * @return array<class-string, bool>
     */
    public function getSupportedTypes(?string $format): array
    {
        return [AuthenticatorData::class => \true];
    }
    private function fixIncorrectEdDSAKey(string $data): string
    {
        $needle = hex2bin('a301634f4b500327206745643235353139');
        $correct = hex2bin('a401634f4b500327206745643235353139');
        $position = mb_strpos($data, $needle, 0, '8bit');
        if ($position === \false) {
            return $data;
        }
        $begin = mb_substr($data, 0, $position, '8bit');
        $end = mb_substr($data, $position, null, '8bit');
        $end = str_replace($needle, $correct, $end);
        $cbor = new StringStream($end);
        $badKey = $this->decoder->decode($cbor);
        $badKey instanceof MapObject && $cbor->isEOF() || throw InvalidDataException::create($end, 'Invalid authentication data. Presence of extra bytes.');
        $badX = $badKey->get(-2);
        $badX instanceof ListObject || throw InvalidDataException::create($end, 'Invalid authentication data.');
        $keyBytes = array_reduce($badX->normalize(), static fn(string $carry, string $item): string => $carry . chr((int) $item), '');
        $correctX = ByteStringObject::create($keyBytes);
        $correctKey = MapObject::create()->add(UnsignedIntegerObject::create(1), TextStringObject::create('OKP'))->add(UnsignedIntegerObject::create(3), NegativeIntegerObject::create(-8))->add(NegativeIntegerObject::create(-1), TextStringObject::create('Ed25519'))->add(NegativeIntegerObject::create(-2), $correctX);
        return $begin . $correctKey;
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\Webauthn\Denormalizer;

use _ContaoManager\CBOR\Decoder;
use _ContaoManager\CBOR\Normalizable;
use _ContaoManager\Symfony\Component\Serializer\Normalizer\DenormalizerAwareInterface;
use _ContaoManager\Symfony\Component\Serializer\Normalizer\DenormalizerAwareTrait;
use _ContaoManager\Symfony\Component\Serializer\Normalizer\DenormalizerInterface;
use _ContaoManager\Webauthn\AttestationStatement\AttestationObject;
use _ContaoManager\Webauthn\AttestationStatement\AttestationStatement;
use _ContaoManager\Webauthn\AuthenticatorData;
use _ContaoManager\Webauthn\Exception\InvalidDataException;
use _ContaoManager\Webauthn\StringStream;
final class AttestationObjectDenormalizer implements DenormalizerInterface, DenormalizerAwareInterface
{
    use DenormalizerAwareTrait;
    public function denormalize(mixed $data, string $type, ?string $format = null, array $context = []): mixed
    {
        $stream = new StringStream($data);
        $parsed = Decoder::create()->decode($stream);
        $parsed instanceof Normalizable || throw InvalidDataException::create($parsed, 'Invalid attestation object. Unexpected object.');
        $attestationObject = $parsed->normalize();
        $stream->isEOF() || throw InvalidDataException::create(null, 'Invalid attestation object. Presence of extra bytes.');
        $stream->close();
        $authData = $attestationObject['authData'] ?? throw InvalidDataException::create($attestationObject, 'Invalid attestation object. Missing "authData" field.');
        return AttestationObject::create($data, $this->denormalizer->denormalize($attestationObject, AttestationStatement::class, $format, $context), $this->denormalizer->denormalize($authData, AuthenticatorData::class, $format, $context));
    }
    public function supportsDenormalization(mixed $data, string $type, ?string $format = null, array $context = []): bool
    {
        return $type === AttestationObject::class;
    }
    /**
     * @return array<class-string, bool>
     */
    public function getSupportedTypes(?string $format): array
    {
        return [AttestationObject::class => \true];
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\Webauthn\Denormalizer;

use _ContaoManager\ParagonIE\ConstantTime\Base64UrlSafe;
use _ContaoManager\Symfony\Component\Serializer\Normalizer\DenormalizerAwareInterface;
use _ContaoManager\Symfony\Component\Serializer\Normalizer\DenormalizerAwareTrait;
use _ContaoManager\Symfony\Component\Serializer\Normalizer\DenormalizerInterface;
use _ContaoManager\Symfony\Component\Serializer\Normalizer\NormalizerAwareInterface;
use _ContaoManager\Symfony\Component\Serializer\Normalizer\NormalizerAwareTrait;
use _ContaoManager\Symfony\Component\Serializer\Normalizer\NormalizerInterface;
use _ContaoManager\Symfony\Component\Uid\Uuid;
use _ContaoManager\Webauthn\Exception\InvalidDataException;
use _ContaoManager\Webauthn\PublicKeyCredentialSource;
use _ContaoManager\Webauthn\TrustPath\TrustPath;
use _ContaoManager\Webauthn\Util\Base64;
use function array_key_exists;
use function assert;
final class PublicKeyCredentialSourceDenormalizer implements DenormalizerInterface, DenormalizerAwareInterface, NormalizerInterface, NormalizerAwareInterface
{
    use NormalizerAwareTrait;
    use DenormalizerAwareTrait;
    public function denormalize(mixed $data, string $type, ?string $format = null, array $context = []): mixed
    {
        $keys = ['publicKeyCredentialId', 'credentialPublicKey', 'userHandle'];
        foreach ($keys as $key) {
            array_key_exists($key, $data) || throw InvalidDataException::create($data, 'Missing ' . $key);
            $data[$key] = Base64::decode($data[$key]);
        }
        return PublicKeyCredentialSource::create($data['publicKeyCredentialId'], $data['type'], $data['transports'], $data['attestationType'], $this->denormalizer->denormalize($data['trustPath'], TrustPath::class, $format, $context), Uuid::fromString($data['aaguid']), $data['credentialPublicKey'], $data['userHandle'], $data['counter'], $data['otherUI'] ?? null, $data['backupEligible'] ?? null, $data['backupStatus'] ?? null, $data['uvInitialized'] ?? null);
    }
    public function supportsDenormalization(mixed $data, string $type, ?string $format = null, array $context = []): bool
    {
        return $type === PublicKeyCredentialSource::class;
    }
    /**
     * @return array<class-string, bool>
     */
    public function getSupportedTypes(?string $format): array
    {
        return [PublicKeyCredentialSource::class => \true];
    }
    /**
     * @return array<string, mixed>
     */
    public function normalize(mixed $data, ?string $format = null, array $context = []): array
    {
        assert($data instanceof PublicKeyCredentialSource);
        $result = ['publicKeyCredentialId' => Base64UrlSafe::encodeUnpadded($data->publicKeyCredentialId), 'type' => $data->type, 'transports' => $data->transports, 'attestationType' => $data->attestationType, 'trustPath' => $this->normalizer->normalize($data->trustPath, $format, $context), 'aaguid' => $this->normalizer->normalize($data->aaguid, $format, $context), 'credentialPublicKey' => Base64UrlSafe::encodeUnpadded($data->credentialPublicKey), 'userHandle' => Base64UrlSafe::encodeUnpadded($data->userHandle), 'counter' => $data->counter, 'otherUI' => $data->otherUI, 'backupEligible' => $data->backupEligible, 'backupStatus' => $data->backupStatus, 'uvInitialized' => $data->uvInitialized];
        return array_filter($result, static fn($value): bool => $value !== null);
    }
    public function supportsNormalization(mixed $data, ?string $format = null, array $context = []): bool
    {
        return $data instanceof PublicKeyCredentialSource;
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\Webauthn\Denormalizer;

use _ContaoManager\ParagonIE\ConstantTime\Base64UrlSafe;
use _ContaoManager\Symfony\Component\Serializer\Normalizer\DenormalizerInterface;
use _ContaoManager\Symfony\Component\Serializer\Normalizer\NormalizerInterface;
use _ContaoManager\Webauthn\PublicKeyCredentialUserEntity;
use _ContaoManager\Webauthn\Util\Base64;
use function array_key_exists;
use function assert;
final class PublicKeyCredentialUserEntityDenormalizer implements DenormalizerInterface, NormalizerInterface
{
    public function denormalize(mixed $data, string $type, ?string $format = null, array $context = []): mixed
    {
        if (!array_key_exists('id', $data)) {
            return $data;
        }
        $data['id'] = Base64::decode($data['id']);
        return PublicKeyCredentialUserEntity::create($data['name'], $data['id'], $data['displayName'], $data['icon'] ?? null);
    }
    public function supportsDenormalization(mixed $data, string $type, ?string $format = null, array $context = []): bool
    {
        return $type === PublicKeyCredentialUserEntity::class;
    }
    /**
     * @return array<class-string, bool>
     */
    public function getSupportedTypes(?string $format): array
    {
        return [PublicKeyCredentialUserEntity::class => \true];
    }
    /**
     * @return array<string, mixed>
     */
    public function normalize(mixed $data, ?string $format = null, array $context = []): array
    {
        assert($data instanceof PublicKeyCredentialUserEntity);
        $normalized = ['id' => Base64UrlSafe::encodeUnpadded($data->id), 'name' => $data->name, 'displayName' => $data->displayName, 'icon' => $data->icon];
        return array_filter($normalized, fn($value) => $value !== null);
    }
    public function supportsNormalization(mixed $data, ?string $format = null, array $context = []): bool
    {
        return $data instanceof PublicKeyCredentialUserEntity;
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\Webauthn\Denormalizer;

use _ContaoManager\Symfony\Component\Serializer\Normalizer\DenormalizerAwareInterface;
use _ContaoManager\Symfony\Component\Serializer\Normalizer\DenormalizerAwareTrait;
use _ContaoManager\Symfony\Component\Serializer\Normalizer\DenormalizerInterface;
use _ContaoManager\Webauthn\MetadataService\Statement\ExtensionDescriptor;
use function array_key_exists;
/**
 * @final
 */
class ExtensionDescriptorDenormalizer implements DenormalizerInterface, DenormalizerAwareInterface
{
    use DenormalizerAwareTrait;
    private const ALREADY_CALLED = 'EXTENSION_DESCRIPTOR_PREPROCESS_ALREADY_CALLED';
    public function denormalize(mixed $data, string $type, ?string $format = null, array $context = []): mixed
    {
        if (array_key_exists('fail_if_unknown', $data)) {
            $data['failIfUnknown'] = $data['fail_if_unknown'];
            unset($data['fail_if_unknown']);
        }
        $context[self::ALREADY_CALLED] = \true;
        return $this->denormalizer->denormalize($data, $type, $format, $context);
    }
    public function supportsDenormalization(mixed $data, string $type, ?string $format = null, array $context = []): bool
    {
        if ($context[self::ALREADY_CALLED] ?? \false) {
            return \false;
        }
        return $type === ExtensionDescriptor::class;
    }
    /**
     * @return array<class-string, bool>
     */
    public function getSupportedTypes(?string $format): array
    {
        return [ExtensionDescriptor::class => \false];
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\Webauthn\Denormalizer;

use _ContaoManager\Symfony\Component\Serializer\Normalizer\NormalizerAwareInterface;
use _ContaoManager\Symfony\Component\Serializer\Normalizer\NormalizerAwareTrait;
use _ContaoManager\Symfony\Component\Serializer\Normalizer\NormalizerInterface;
use _ContaoManager\Webauthn\MetadataService\Statement\VerificationMethodANDCombinations;
use _ContaoManager\Webauthn\MetadataService\Statement\VerificationMethodDescriptor;
use function assert;
final class VerificationMethodANDCombinationsDenormalizer implements NormalizerInterface, NormalizerAwareInterface
{
    use NormalizerAwareTrait;
    /**
     * @return array<class-string, bool>
     */
    public function getSupportedTypes(?string $format): array
    {
        return [VerificationMethodANDCombinations::class => \true];
    }
    /**
     * @return array<VerificationMethodDescriptor>
     */
    public function normalize(mixed $object, ?string $format = null, array $context = []): array
    {
        assert($object instanceof VerificationMethodANDCombinations);
        return array_map(fn($verificationMethod) => $this->normalizer->normalize($verificationMethod, $format, $context), $object->verificationMethods);
    }
    public function supportsNormalization(mixed $data, ?string $format = null, array $context = []): bool
    {
        return $data instanceof VerificationMethodANDCombinations;
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\Webauthn\Denormalizer;

use _ContaoManager\ParagonIE\ConstantTime\Base64UrlSafe;
use _ContaoManager\Symfony\Component\Serializer\Normalizer\DenormalizerAwareInterface;
use _ContaoManager\Symfony\Component\Serializer\Normalizer\DenormalizerAwareTrait;
use _ContaoManager\Symfony\Component\Serializer\Normalizer\DenormalizerInterface;
use _ContaoManager\Webauthn\AttestationStatement\AttestationObject;
use _ContaoManager\Webauthn\AuthenticatorAssertionResponse;
use _ContaoManager\Webauthn\AuthenticatorData;
use _ContaoManager\Webauthn\CollectedClientData;
use _ContaoManager\Webauthn\Util\Base64;
final class AuthenticatorAssertionResponseDenormalizer implements DenormalizerInterface, DenormalizerAwareInterface
{
    use DenormalizerAwareTrait;
    public function denormalize(mixed $data, string $type, ?string $format = null, array $context = []): mixed
    {
        $data['authenticatorData'] = Base64::decode($data['authenticatorData']);
        $data['signature'] = Base64::decode($data['signature']);
        $data['clientDataJSON'] = Base64UrlSafe::decodeNoPadding($data['clientDataJSON']);
        $userHandle = $data['userHandle'] ?? null;
        if ($userHandle !== '' && $userHandle !== null) {
            $userHandle = Base64::decode($userHandle);
        }
        return AuthenticatorAssertionResponse::create($this->denormalizer->denormalize($data['clientDataJSON'], CollectedClientData::class, $format, $context), $this->denormalizer->denormalize($data['authenticatorData'], AuthenticatorData::class, $format, $context), $data['signature'], $userHandle ?? null, !isset($data['attestationObject']) ? null : $this->denormalizer->denormalize($data['attestationObject'], AttestationObject::class, $format, $context));
    }
    public function supportsDenormalization(mixed $data, string $type, ?string $format = null, array $context = []): bool
    {
        return $type === AuthenticatorAssertionResponse::class;
    }
    /**
     * @return array<class-string, bool>
     */
    public function getSupportedTypes(?string $format): array
    {
        return [AuthenticatorAssertionResponse::class => \true];
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\Webauthn\Denormalizer;

use _ContaoManager\Symfony\Component\Serializer\Normalizer\DenormalizerAwareInterface;
use _ContaoManager\Symfony\Component\Serializer\Normalizer\DenormalizerAwareTrait;
use _ContaoManager\Symfony\Component\Serializer\Normalizer\DenormalizerInterface;
use _ContaoManager\Webauthn\AuthenticatorAssertionResponse;
use _ContaoManager\Webauthn\AuthenticatorAttestationResponse;
use _ContaoManager\Webauthn\AuthenticatorResponse;
use _ContaoManager\Webauthn\Exception\InvalidDataException;
use function array_key_exists;
final class AuthenticatorResponseDenormalizer implements DenormalizerInterface, DenormalizerAwareInterface
{
    use DenormalizerAwareTrait;
    public function denormalize(mixed $data, string $type, ?string $format = null, array $context = []): mixed
    {
        $realType = match (\true) {
            array_key_exists('attestationObject', $data) => AuthenticatorAttestationResponse::class,
            array_key_exists('signature', $data) => AuthenticatorAssertionResponse::class,
            default => throw InvalidDataException::create($data, 'Unable to create the response object'),
        };
        return $this->denormalizer->denormalize($data, $realType, $format, $context);
    }
    public function supportsDenormalization(mixed $data, string $type, ?string $format = null, array $context = []): bool
    {
        return $type === AuthenticatorResponse::class;
    }
    /**
     * @return array<class-string, bool>
     */
    public function getSupportedTypes(?string $format): array
    {
        return [AuthenticatorResponse::class => \true];
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\Webauthn\Denormalizer;

use _ContaoManager\ParagonIE\ConstantTime\Base64UrlSafe;
use _ContaoManager\Symfony\Component\Serializer\Exception\BadMethodCallException;
use _ContaoManager\Symfony\Component\Serializer\Normalizer\DenormalizerAwareInterface;
use _ContaoManager\Symfony\Component\Serializer\Normalizer\DenormalizerAwareTrait;
use _ContaoManager\Symfony\Component\Serializer\Normalizer\DenormalizerInterface;
use _ContaoManager\Symfony\Component\Serializer\Normalizer\NormalizerAwareInterface;
use _ContaoManager\Symfony\Component\Serializer\Normalizer\NormalizerAwareTrait;
use _ContaoManager\Symfony\Component\Serializer\Normalizer\NormalizerInterface;
use _ContaoManager\Webauthn\AuthenticationExtensions\AuthenticationExtensions;
use _ContaoManager\Webauthn\AuthenticatorSelectionCriteria;
use _ContaoManager\Webauthn\PublicKeyCredentialCreationOptions;
use _ContaoManager\Webauthn\PublicKeyCredentialDescriptor;
use _ContaoManager\Webauthn\PublicKeyCredentialParameters;
use _ContaoManager\Webauthn\PublicKeyCredentialRequestOptions;
use _ContaoManager\Webauthn\PublicKeyCredentialRpEntity;
use _ContaoManager\Webauthn\PublicKeyCredentialUserEntity;
use function array_key_exists;
use function assert;
use function in_array;
final class PublicKeyCredentialOptionsDenormalizer implements DenormalizerInterface, DenormalizerAwareInterface, NormalizerInterface, NormalizerAwareInterface
{
    use DenormalizerAwareTrait;
    use NormalizerAwareTrait;
    public function denormalize(mixed $data, string $type, ?string $format = null, array $context = []): mixed
    {
        if (array_key_exists('challenge', $data)) {
            $data['challenge'] = Base64UrlSafe::decodeNoPadding($data['challenge']);
        }
        foreach (['allowCredentials', 'excludeCredentials'] as $key) {
            if (array_key_exists($key, $data)) {
                foreach ($data[$key] ?? [] as $item => $allowCredential) {
                    $data[$key][$item]['id'] = Base64UrlSafe::decodeNoPadding($allowCredential['id']);
                }
            }
        }
        if ($type === PublicKeyCredentialCreationOptions::class) {
            return PublicKeyCredentialCreationOptions::create($this->denormalizer->denormalize($data['rp'], PublicKeyCredentialRpEntity::class, $format, $context), $this->denormalizer->denormalize($data['user'], PublicKeyCredentialUserEntity::class, $format, $context), $data['challenge'], !isset($data['pubKeyCredParams']) ? [] : $this->denormalizer->denormalize($data['pubKeyCredParams'], PublicKeyCredentialParameters::class . '[]', $format, $context), !isset($data['authenticatorSelection']) ? null : $this->denormalizer->denormalize($data['authenticatorSelection'], AuthenticatorSelectionCriteria::class, $format, $context), $data['attestation'] ?? null, !isset($data['excludeCredentials']) ? [] : $this->denormalizer->denormalize($data['excludeCredentials'], PublicKeyCredentialDescriptor::class . '[]', $format, $context), $data['timeout'] ?? null, !isset($data['extensions']) ? null : $this->denormalizer->denormalize($data['extensions'], AuthenticationExtensions::class, $format, $context));
        }
        if ($type === PublicKeyCredentialRequestOptions::class) {
            return PublicKeyCredentialRequestOptions::create($data['challenge'], $data['rpId'] ?? null, !isset($data['allowCredentials']) ? [] : $this->denormalizer->denormalize($data['allowCredentials'], PublicKeyCredentialDescriptor::class . '[]', $format, $context), $data['userVerification'] ?? null, $data['timeout'] ?? null, !isset($data['extensions']) ? null : $this->denormalizer->denormalize($data['extensions'], AuthenticationExtensions::class, $format, $context));
        }
        throw new BadMethodCallException('Unsupported type');
    }
    public function supportsDenormalization(mixed $data, string $type, ?string $format = null, array $context = []): bool
    {
        return in_array($type, [PublicKeyCredentialCreationOptions::class, PublicKeyCredentialRequestOptions::class], \true);
    }
    public function supportsNormalization(mixed $data, ?string $format = null, array $context = []): bool
    {
        return $data instanceof PublicKeyCredentialCreationOptions || $data instanceof PublicKeyCredentialRequestOptions;
    }
    /**
     * @return array<class-string, bool>
     */
    public function getSupportedTypes(?string $format): array
    {
        return [PublicKeyCredentialCreationOptions::class => \true, PublicKeyCredentialRequestOptions::class => \true];
    }
    /**
     * @return array<string, mixed>
     */
    public function normalize(mixed $data, ?string $format = null, array $context = []): array
    {
        assert($data instanceof PublicKeyCredentialCreationOptions || $data instanceof PublicKeyCredentialRequestOptions);
        $json = ['challenge' => Base64UrlSafe::encodeUnpadded($data->challenge), 'timeout' => $data->timeout, 'extensions' => $data->extensions->count() === 0 ? null : $this->normalizer->normalize($data->extensions, $format, $context)];
        if ($data instanceof PublicKeyCredentialCreationOptions) {
            $json = [...$json, 'rp' => $this->normalizer->normalize($data->rp, $format, $context), 'user' => $this->normalizer->normalize($data->user, $format, $context), 'pubKeyCredParams' => $this->normalizer->normalize($data->pubKeyCredParams, PublicKeyCredentialParameters::class . '[]', $context), 'authenticatorSelection' => $data->authenticatorSelection === null ? null : $this->normalizer->normalize($data->authenticatorSelection, $format, $context), 'attestation' => $data->attestation, 'excludeCredentials' => $this->normalizer->normalize($data->excludeCredentials, $format, $context)];
        }
        if ($data instanceof PublicKeyCredentialRequestOptions) {
            $json = [...$json, 'rpId' => $data->rpId, 'allowCredentials' => $this->normalizer->normalize($data->allowCredentials, $format, $context), 'userVerification' => $data->userVerification];
        }
        return array_filter($json, static fn($value) => $value !== null && $value !== []);
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\Webauthn;

use Stringable;
use function sprintf;
use const E_USER_DEPRECATED;
use const JSON_THROW_ON_ERROR;
/**
 * @see https://www.w3.org/TR/webauthn/#iface-pkcredential
 */
class PublicKeyCredential extends Credential implements Stringable
{
    public function __construct(null|string $id, string $type, string $rawId, public readonly AuthenticatorResponse $response)
    {
        parent::__construct($id, $type, $rawId);
    }
    /**
     * @deprecated since 4.8.0.
     * @infection-ignore-all
     */
    public function __toString(): string
    {
        return json_encode($this->getPublicKeyCredentialDescriptor(), JSON_THROW_ON_ERROR);
    }
    public static function create(null|string $id, string $type, string $rawId, AuthenticatorResponse $response): self
    {
        return new self($id, $type, $rawId, $response);
    }
    /**
     * @deprecated since 4.7.0. Please use the property directly.
     * @infection-ignore-all
     */
    public function getRawId(): string
    {
        return $this->rawId;
    }
    /**
     * @deprecated since 4.7.0. Please use the property directly.
     * @infection-ignore-all
     */
    public function getResponse(): AuthenticatorResponse
    {
        return $this->response;
    }
    /**
     * @param string[] $transport
     */
    public function getPublicKeyCredentialDescriptor(null|array $transport = null): PublicKeyCredentialDescriptor
    {
        if ($transport !== null) {
            trigger_deprecation('web-auth/webauthn-lib', '4.8.0', 'The parameter "$transport" is deprecated and will be removed in 5.0.0.');
            @trigger_error(sprintf('The $transport argument of %s() is deprecated since 4.8.0 and will be removed in 5.0.0.', __METHOD__), E_USER_DEPRECATED);
        }
        $transport ??= $this->response instanceof AuthenticatorAttestationResponse ? $this->response->transports : [];
        return PublicKeyCredentialDescriptor::create($this->type, $this->rawId, $transport);
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\Webauthn\MetadataService;

use JsonException;
use LogicException;
use _ContaoManager\Psr\Http\Client\ClientInterface as Psr18ClientInterface;
use _ContaoManager\Psr\Http\Message\RequestFactoryInterface as Psr17RequestFactoryInterface;
use _ContaoManager\Psr\Http\Message\ResponseInterface as Psr17ResponseInterface;
use _ContaoManager\Psr\Http\Message\StreamFactoryInterface as Psr17StreamFactoryInterface;
use _ContaoManager\Symfony\Contracts\HttpClient\HttpClientInterface;
use _ContaoManager\Symfony\Contracts\HttpClient\ResponseInterface;
use _ContaoManager\Symfony\Contracts\HttpClient\ResponseStreamInterface;
use function is_array;
use const JSON_ERROR_NONE;
use const PHP_QUERY_RFC3986;
class Psr18HttpClient implements HttpClientInterface
{
    private array $options = [];
    public function __construct(private readonly Psr18ClientInterface $client, private readonly Psr17RequestFactoryInterface $requestFactory, private readonly Psr17StreamFactoryInterface $streamFactory)
    {
    }
    public function request(string $method, string $url, array $options = []): ResponseInterface
    {
        $baseUri = $options['base_uri'] ?? '';
        $query = $options['query'] ?? [];
        if ($query) {
            $url .= (!str_contains($url, '?') ? '?' : '&') . http_build_query($query, '', '&', PHP_QUERY_RFC3986);
        }
        $request = $this->requestFactory->createRequest($method, $baseUri . $url);
        $body = $options['body'] ?? null;
        if ($body !== null) {
            $request = $request->withBody($this->streamFactory->createStream($body));
        }
        foreach ($this->options as $name => $value) {
            $request = $request->withHeader($name, $value);
        }
        foreach ($options['headers'] ?? [] as $name => $value) {
            $request = $request->withHeader($name, $value);
        }
        $response = $this->client->sendRequest($request);
        return static::fromPsr17($response);
    }
    /**
     * @param ResponseInterface|iterable<array-key, ResponseInterface> $responses
     */
    public function stream(iterable|ResponseInterface $responses, ?float $timeout = null): ResponseStreamInterface
    {
        throw new LogicException('Not implemented');
    }
    public function withOptions(array $options): static
    {
        $this->options = $options;
        return $this;
    }
    protected static function fromPsr17(Psr17ResponseInterface $response): ResponseInterface
    {
        $headers = $response->getHeaders();
        $content = $response->getBody()->getContents();
        $status = $response->getStatusCode();
        return new class($status, $headers, $content) implements ResponseInterface
        {
            /**
             * @param array<array-key, string[]> $headers
             */
            public function __construct(private readonly int $status, private readonly array $headers, private readonly string $content)
            {
            }
            public function getStatusCode(): int
            {
                return $this->status;
            }
            /**
             * @return array<array-key, string[]>
             */
            public function getHeaders(bool $throw = \true): array
            {
                return $this->headers;
            }
            public function getContent(bool $throw = \true): string
            {
                return $this->content;
            }
            /**
             * @return array<array-key, mixed>
             */
            public function toArray(bool $throw = \true): array
            {
                $result = json_decode($this->content, \true);
                if (!is_array($result) || json_last_error() !== JSON_ERROR_NONE) {
                    throw new JsonException('Failed to decode JSON response: ' . json_last_error_msg());
                }
                return $result;
            }
            public function cancel(): void
            {
                // noop
            }
            public function getInfo(?string $type = null): mixed
            {
                return null;
            }
        };
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\Webauthn\MetadataService;

use _ContaoManager\Webauthn\MetadataService\Statement\StatusReport;
interface StatusReportRepository
{
    /**
     * @return StatusReport[]
     */
    public function findStatusReportsByAAGUID(string $aaguid): array;
}
<?php

declare (strict_types=1);
namespace _ContaoManager\Webauthn\MetadataService\CertificateChain;

interface CertificateChainValidator
{
    /**
     * @param string[] $untrustedCertificates
     * @param string[] $trustedCertificates
     */
    public function check(array $untrustedCertificates, array $trustedCertificates): void;
}
<?php

declare (strict_types=1);
namespace _ContaoManager\Webauthn\MetadataService\CertificateChain;

use _ContaoManager\ParagonIE\ConstantTime\Base64;
use function preg_replace;
use const PHP_EOL;
class CertificateToolbox
{
    private const PEM_HEADER = '-----BEGIN ';
    private const PEM_FOOTER = '-----END ';
    /**
     * @param string[] $data
     *
     * @return string[]
     */
    public static function fixPEMStructures(array $data, string $type = 'CERTIFICATE'): array
    {
        return array_map(static fn($d): string => self::fixPEMStructure($d, $type), $data);
    }
    public static function fixPEMStructure(string $data, string $type = 'CERTIFICATE'): string
    {
        if (str_contains($data, self::PEM_HEADER)) {
            return trim($data);
        }
        $pem = self::PEM_HEADER . $type . '-----' . PHP_EOL;
        $pem .= chunk_split($data, 64, PHP_EOL);
        return $pem . (self::PEM_FOOTER . $type . '-----' . PHP_EOL);
    }
    /**
     * @deprecated since 4.7.0 and will be removed in 5.0.0. No replacement as not used internally.
     * @infection-ignore-all
     */
    public static function convertPEMToDER(string $data): string
    {
        if (!str_contains($data, self::PEM_HEADER)) {
            return $data;
        }
        $data = preg_replace('/\-{5}.*\-{5}[\r\n]*/', '', $data);
        $data = preg_replace("/[\r\n]*/", '', (string) $data);
        return Base64::decode(trim((string) $data), \true);
    }
    public static function convertDERToPEM(string $data, string $type = 'CERTIFICATE'): string
    {
        if (str_contains($data, self::PEM_HEADER)) {
            return $data;
        }
        return self::fixPEMStructure(base64_encode($data), $type);
    }
    /**
     * @param string[] $data
     *
     * @return string[]
     */
    public static function convertAllDERToPEM(iterable $data, string $type = 'CERTIFICATE'): array
    {
        return array_map(static fn($d): string => self::convertDERToPEM($d, $type), $data);
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\Webauthn\MetadataService\CertificateChain;

use DateTimeZone;
use _ContaoManager\Lcobucci\Clock\Clock;
use _ContaoManager\Lcobucci\Clock\SystemClock;
use _ContaoManager\Psr\Clock\ClockInterface;
use _ContaoManager\Psr\EventDispatcher\EventDispatcherInterface;
use _ContaoManager\Psr\Http\Client\ClientInterface;
use _ContaoManager\Psr\Http\Message\RequestFactoryInterface;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\UnspecifiedType;
use _ContaoManager\SpomkyLabs\Pki\CryptoEncoding\PEM;
use _ContaoManager\SpomkyLabs\Pki\X509\Certificate\Certificate;
use _ContaoManager\SpomkyLabs\Pki\X509\CertificationPath\CertificationPath;
use _ContaoManager\SpomkyLabs\Pki\X509\CertificationPath\PathValidation\PathValidationConfig;
use _ContaoManager\Symfony\Contracts\HttpClient\HttpClientInterface;
use Throwable;
use _ContaoManager\Webauthn\Event\BeforeCertificateChainValidation;
use _ContaoManager\Webauthn\Event\CanDispatchEvents;
use _ContaoManager\Webauthn\Event\CertificateChainValidationFailed;
use _ContaoManager\Webauthn\Event\CertificateChainValidationSucceeded;
use _ContaoManager\Webauthn\Event\NullEventDispatcher;
use _ContaoManager\Webauthn\Exception\CertificateChainException;
use _ContaoManager\Webauthn\Exception\CertificateRevocationListException;
use _ContaoManager\Webauthn\Exception\InvalidCertificateException;
use function count;
use function in_array;
use function parse_url;
use function sprintf;
use const PHP_EOL;
use const PHP_URL_SCHEME;
class PhpCertificateChainValidator implements CertificateChainValidator, CanDispatchEvents
{
    private const MAX_VALIDATION_LENGTH = 5;
    private readonly Clock|ClockInterface $clock;
    private EventDispatcherInterface $dispatcher;
    public function __construct(private readonly ClientInterface|HttpClientInterface $client, private readonly ?RequestFactoryInterface $requestFactory = null, null|Clock|ClockInterface $clock = null, private readonly bool $allowFailures = \true)
    {
        if ($clock === null) {
            trigger_deprecation('web-auth/metadata-service', '4.5.0', 'The parameter "$clock" will become mandatory in 5.0.0. Please set a valid PSR Clock implementation instead of "null".');
            $clock = new SystemClock(new DateTimeZone('UTC'));
        }
        if ($requestFactory !== null && !$client instanceof HttpClientInterface) {
            trigger_deprecation('web-auth/metadata-service', '4.7.0', 'The parameter "$requestFactory" will be removed in 5.0.0. Please set it to null and set an Symfony\Contracts\HttpClient\HttpClientInterface as "$client" argument.');
        }
        $this->clock = $clock;
        $this->dispatcher = new NullEventDispatcher();
    }
    public static function create(HttpClientInterface $client, null|Clock|ClockInterface $clock = null, bool $allowFailures = \true): self
    {
        return new self($client, null, $clock, $allowFailures);
    }
    public function setEventDispatcher(EventDispatcherInterface $eventDispatcher): void
    {
        $this->dispatcher = $eventDispatcher;
    }
    /**
     * @param string[] $untrustedCertificates
     * @param string[] $trustedCertificates
     */
    public function check(array $untrustedCertificates, array $trustedCertificates): void
    {
        foreach ($trustedCertificates as $trustedCertificate) {
            $this->dispatcher->dispatch(BeforeCertificateChainValidation::create($untrustedCertificates, $trustedCertificate));
            try {
                if ($this->validateChain($untrustedCertificates, $trustedCertificate)) {
                    $this->dispatcher->dispatch(CertificateChainValidationSucceeded::create($untrustedCertificates, $trustedCertificate));
                    return;
                }
            } catch (Throwable $exception) {
                $this->dispatcher->dispatch(CertificateChainValidationFailed::create($untrustedCertificates, $trustedCertificate));
                throw $exception;
            }
        }
        throw CertificateChainException::create($untrustedCertificates, $trustedCertificates);
    }
    /**
     * @param string[] $untrustedCertificates
     */
    private function validateChain(array $untrustedCertificates, string $trustedCertificate): bool
    {
        $untrustedCertificates = array_map(static fn(string $cert): Certificate => Certificate::fromPEM(PEM::fromString($cert)), array_reverse($untrustedCertificates));
        $trustedCertificate = Certificate::fromPEM(PEM::fromString($trustedCertificate));
        // The trust path and the authenticator certificate are the same
        if (count($untrustedCertificates) === 1 && $untrustedCertificates[0]->toPEM()->string() === $trustedCertificate->toPEM()->string()) {
            return \true;
        }
        $uniqueCertificates = array_map(static fn(Certificate $cert): string => $cert->toPEM()->string(), [...$untrustedCertificates, $trustedCertificate]);
        count(array_unique($uniqueCertificates)) === count($uniqueCertificates) || throw CertificateChainException::create($untrustedCertificates, [$trustedCertificate], 'Invalid certificate chain with duplicated certificates.');
        if (!$this->validateCertificates($trustedCertificate, ...$untrustedCertificates)) {
            return \false;
        }
        $certificates = [$trustedCertificate, ...$untrustedCertificates];
        $numCerts = count($certificates);
        for ($i = 1; $i < $numCerts; $i++) {
            if ($this->isRevoked($certificates[$i])) {
                throw CertificateChainException::create($untrustedCertificates, [$trustedCertificate], 'Unable to validate the certificate chain. Revoked certificate found.');
            }
        }
        return \true;
    }
    private function isRevoked(Certificate $subject): bool
    {
        try {
            $csn = $subject->tbsCertificate()->serialNumber();
        } catch (Throwable $e) {
            throw InvalidCertificateException::create($subject->toPEM()->string(), sprintf('Failed to parse certificate: %s', $e->getMessage()), $e);
        }
        try {
            $urls = $this->getCrlUrlList($subject);
        } catch (Throwable $e) {
            if ($this->allowFailures) {
                return \false;
            }
            throw InvalidCertificateException::create($subject->toPEM()->string(), 'Failed to get CRL distribution points: ' . $e->getMessage(), $e);
        }
        foreach ($urls as $url) {
            try {
                $revokedCertificates = $this->retrieveRevokedSerialNumbers($url);
                if (in_array($csn, $revokedCertificates, \true)) {
                    return \true;
                }
            } catch (Throwable $e) {
                if ($this->allowFailures) {
                    return \false;
                }
                throw CertificateRevocationListException::create($url, sprintf('Failed to retrieve the CRL:' . PHP_EOL . '%s', $e->getMessage()), $e);
            }
        }
        return \false;
    }
    private function validateCertificates(Certificate ...$certificates): bool
    {
        try {
            $config = PathValidationConfig::create($this->clock->now(), self::MAX_VALIDATION_LENGTH);
            CertificationPath::create(...$certificates)->validate($config);
            return \true;
        } catch (Throwable) {
            return \false;
        }
    }
    /**
     * @return string[]
     */
    private function retrieveRevokedSerialNumbers(string $url): array
    {
        try {
            if ($this->client instanceof HttpClientInterface) {
                $crlData = $this->client->request('GET', $url)->getContent();
            } else {
                $crlData = $this->sendPsrRequest($url);
            }
            $crl = UnspecifiedType::fromDER($crlData)->asSequence();
            count($crl) === 3 || throw CertificateRevocationListException::create($url);
            $tbsCertList = $crl->at(0)->asSequence();
            count($tbsCertList) >= 6 || throw CertificateRevocationListException::create($url);
            $list = $tbsCertList->at(5)->asSequence();
            return array_map(static function (UnspecifiedType $r) use ($url): string {
                $sequence = $r->asSequence();
                count($sequence) >= 1 || throw CertificateRevocationListException::create($url);
                return $sequence->at(0)->asInteger()->number();
            }, $list->elements());
        } catch (Throwable $e) {
            throw CertificateRevocationListException::create($url, 'Failed to download the CRL', $e);
        }
    }
    /**
     * @return string[]
     */
    private function getCrlUrlList(Certificate $subject): array
    {
        try {
            $urls = [];
            $extensions = $subject->tbsCertificate()->extensions();
            if ($extensions->hasCRLDistributionPoints()) {
                $crlDists = $extensions->crlDistributionPoints();
                foreach ($crlDists->distributionPoints() as $dist) {
                    $url = $dist->fullName()->names()->firstURI();
                    $scheme = parse_url($url, PHP_URL_SCHEME);
                    if (!in_array($scheme, ['http', 'https'], \true)) {
                        continue;
                    }
                    $urls[] = $url;
                }
            }
            return $urls;
        } catch (Throwable $e) {
            throw InvalidCertificateException::create($subject->toPEM()->string(), 'Failed to get CRL distribution points from certificate: ' . $e->getMessage(), $e);
        }
    }
    private function sendPsrRequest(string $url): string
    {
        $request = $this->requestFactory->createRequest('GET', $url);
        $response = $this->client->sendRequest($request);
        if ($response->getStatusCode() !== 200) {
            throw CertificateRevocationListException::create($url, 'Failed to download the CRL');
        }
        return $response->getBody()->getContents();
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\Webauthn\MetadataService;

use _ContaoManager\Psr\Log\LoggerInterface;
interface CanLogData
{
    public function setLogger(LoggerInterface $logger): void;
}
<?php

declare (strict_types=1);
namespace _ContaoManager\Webauthn\MetadataService;

use _ContaoManager\Webauthn\MetadataService\Statement\MetadataStatement;
interface MetadataStatementRepository
{
    public function findOneByAAGUID(string $aaguid): ?MetadataStatement;
}
<?php

declare (strict_types=1);
namespace _ContaoManager\Webauthn\MetadataService\Statement;

use JsonSerializable;
use _ContaoManager\Webauthn\Exception\MetadataStatementLoadingException;
use _ContaoManager\Webauthn\MetadataService\ValueFilter;
use function array_key_exists;
class ExtensionDescriptor implements JsonSerializable
{
    use ValueFilter;
    public function __construct(public readonly string $id, public readonly ?int $tag, public readonly ?string $data, public readonly bool $failIfUnknown)
    {
        if ($tag !== null) {
            $tag >= 0 || throw MetadataStatementLoadingException::create('Invalid data. The parameter "tag" shall be a positive integer');
        }
    }
    public static function create(string $id, ?int $tag = null, ?string $data = null, bool $failIfUnknown = \false): self
    {
        return new self($id, $tag, $data, $failIfUnknown);
    }
    /**
     * @deprecated since 4.7.0. Please use the property directly.
     * @infection-ignore-all
     */
    public function getId(): string
    {
        return $this->id;
    }
    /**
     * @deprecated since 4.7.0. Please use the property directly.
     * @infection-ignore-all
     */
    public function getTag(): ?int
    {
        return $this->tag;
    }
    /**
     * @deprecated since 4.7.0. Please use the property directly.
     * @infection-ignore-all
     */
    public function getData(): ?string
    {
        return $this->data;
    }
    /**
     * @deprecated since 4.7.0. Please use the property directly.
     * @infection-ignore-all
     */
    public function isFailIfUnknown(): bool
    {
        return $this->failIfUnknown;
    }
    /**
     * @param array<string, mixed> $data
     * @deprecated since 4.7.0. Please use the symfony/serializer for converting the object.
     * @infection-ignore-all
     */
    public static function createFromArray(array $data): self
    {
        $data = self::filterNullValues($data);
        array_key_exists('id', $data) || throw MetadataStatementLoadingException::create('Invalid data. The parameter "id" is missing');
        array_key_exists('fail_if_unknown', $data) || throw MetadataStatementLoadingException::create('Invalid data. The parameter "fail_if_unknown" is missing');
        return new self($data['id'], $data['tag'] ?? null, $data['data'] ?? null, $data['fail_if_unknown']);
    }
    /**
     * @return array<string, mixed>
     */
    public function jsonSerialize(): array
    {
        trigger_deprecation('web-auth/webauthn-bundle', '4.9.0', 'The "%s" method is deprecated and will be removed in 5.0. Please use the serializer instead.', __METHOD__);
        $result = ['id' => $this->id, 'tag' => $this->tag, 'data' => $this->data, 'fail_if_unknown' => $this->failIfUnknown];
        return self::filterNullValues($result);
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\Webauthn\MetadataService\Statement;

use _ContaoManager\Webauthn\Exception\MetadataStatementLoadingException;
use _ContaoManager\Webauthn\MetadataService\ValueFilter;
use function array_key_exists;
class CodeAccuracyDescriptor extends AbstractDescriptor
{
    use ValueFilter;
    public function __construct(public readonly int $base, public readonly int $minLength, ?int $maxRetries = null, ?int $blockSlowdown = null)
    {
        $base >= 0 || throw MetadataStatementLoadingException::create('Invalid data. The value of "base" must be a positive integer');
        $minLength >= 0 || throw MetadataStatementLoadingException::create('Invalid data. The value of "minLength" must be a positive integer');
        parent::__construct($maxRetries, $blockSlowdown);
    }
    public static function create(int $base, int $minLength, ?int $maxRetries = null, ?int $blockSlowdown = null): self
    {
        return new self($base, $minLength, $maxRetries, $blockSlowdown);
    }
    /**
     * @deprecated since 4.7.0. Please use the property directly.
     * @infection-ignore-all
     */
    public function getBase(): int
    {
        return $this->base;
    }
    /**
     * @deprecated since 4.7.0. Please use the property directly.
     * @infection-ignore-all
     */
    public function getMinLength(): int
    {
        return $this->minLength;
    }
    /**
     * @param array<string, mixed> $data
     * @deprecated since 4.7.0. Please use the symfony/serializer for converting the object.
     * @infection-ignore-all
     */
    public static function createFromArray(array $data): self
    {
        array_key_exists('base', $data) || throw MetadataStatementLoadingException::create('The parameter "base" is missing');
        array_key_exists('minLength', $data) || throw MetadataStatementLoadingException::create('The parameter "minLength" is missing');
        return self::create($data['base'], $data['minLength'], $data['maxRetries'] ?? null, $data['blockSlowdown'] ?? null);
    }
    /**
     * @return array<string, mixed>
     */
    public function jsonSerialize(): array
    {
        trigger_deprecation('web-auth/webauthn-bundle', '4.9.0', 'The "%s" method is deprecated and will be removed in 5.0. Please use the serializer instead.', __METHOD__);
        $data = ['base' => $this->base, 'minLength' => $this->minLength, 'maxRetries' => $this->maxRetries, 'blockSlowdown' => $this->blockSlowdown];
        return self::filterNullValues($data);
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\Webauthn\MetadataService\Statement;

use _ContaoManager\Webauthn\Exception\MetadataStatementLoadingException;
use _ContaoManager\Webauthn\MetadataService\ValueFilter;
use function array_key_exists;
use function is_int;
use function sprintf;
class PatternAccuracyDescriptor extends AbstractDescriptor
{
    use ValueFilter;
    public function __construct(public readonly int $minComplexity, ?int $maxRetries = null, ?int $blockSlowdown = null)
    {
        $minComplexity >= 0 || throw MetadataStatementLoadingException::create('Invalid data. The value of "minComplexity" must be a positive integer');
        parent::__construct($maxRetries, $blockSlowdown);
    }
    public static function create(int $minComplexity, ?int $maxRetries = null, ?int $blockSlowdown = null): self
    {
        return new self($minComplexity, $maxRetries, $blockSlowdown);
    }
    /**
     * @deprecated since 4.7.0. Please use the property directly.
     * @infection-ignore-all
     */
    public function getMinComplexity(): int
    {
        return $this->minComplexity;
    }
    /**
     * @param array<string, mixed> $data
     * @deprecated since 4.7.0. Please use the symfony/serializer for converting the object.
     * @infection-ignore-all
     */
    public static function createFromArray(array $data): self
    {
        $data = self::filterNullValues($data);
        array_key_exists('minComplexity', $data) || throw MetadataStatementLoadingException::create('The key "minComplexity" is missing');
        foreach (['minComplexity', 'maxRetries', 'blockSlowdown'] as $key) {
            if (array_key_exists($key, $data)) {
                is_int($data[$key]) || throw MetadataStatementLoadingException::create(sprintf('Invalid data. The value of "%s" must be a positive integer', $key));
            }
        }
        return self::create($data['minComplexity'], $data['maxRetries'] ?? null, $data['blockSlowdown'] ?? null);
    }
    /**
     * @return array<string, int|null>
     */
    public function jsonSerialize(): array
    {
        trigger_deprecation('web-auth/webauthn-bundle', '4.9.0', 'The "%s" method is deprecated and will be removed in 5.0. Please use the serializer instead.', __METHOD__);
        $data = ['minComplexity' => $this->minComplexity, 'maxRetries' => $this->maxRetries, 'blockSlowdown' => $this->blockSlowdown];
        return self::filterNullValues($data);
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\Webauthn\MetadataService\Statement;

use JsonSerializable;
use _ContaoManager\Webauthn\Exception\MetadataStatementLoadingException;
use _ContaoManager\Webauthn\MetadataService\CertificateChain\CertificateToolbox;
use _ContaoManager\Webauthn\MetadataService\ValueFilter;
use function array_key_exists;
use function is_array;
use function is_string;
use function sprintf;
use const JSON_THROW_ON_ERROR;
class MetadataStatement implements JsonSerializable
{
    use ValueFilter;
    final public const KEY_PROTECTION_SOFTWARE = 'software';
    final public const KEY_PROTECTION_SOFTWARE_INT = 0x1;
    final public const KEY_PROTECTION_HARDWARE = 'hardware';
    final public const KEY_PROTECTION_HARDWARE_INT = 0x2;
    final public const KEY_PROTECTION_TEE = 'tee';
    final public const KEY_PROTECTION_TEE_INT = 0x4;
    final public const KEY_PROTECTION_SECURE_ELEMENT = 'secure_element';
    final public const KEY_PROTECTION_SECURE_ELEMENT_INT = 0x8;
    final public const KEY_PROTECTION_REMOTE_HANDLE = 'remote_handle';
    final public const KEY_PROTECTION_REMOTE_HANDLE_INT = 0x10;
    final public const KEY_PROTECTION_TYPES = [self::KEY_PROTECTION_SOFTWARE, self::KEY_PROTECTION_HARDWARE, self::KEY_PROTECTION_TEE, self::KEY_PROTECTION_SECURE_ELEMENT, self::KEY_PROTECTION_REMOTE_HANDLE];
    final public const KEY_PROTECTION_TYPES_INT = [self::KEY_PROTECTION_SOFTWARE_INT, self::KEY_PROTECTION_HARDWARE_INT, self::KEY_PROTECTION_TEE_INT, self::KEY_PROTECTION_SECURE_ELEMENT_INT, self::KEY_PROTECTION_REMOTE_HANDLE_INT];
    final public const MATCHER_PROTECTION_SOFTWARE = 'software';
    final public const MATCHER_PROTECTION_SOFTWARE_INT = 0x1;
    final public const MATCHER_PROTECTION_TEE = 'tee';
    final public const MATCHER_PROTECTION_TEE_INT = 0x2;
    final public const MATCHER_PROTECTION_ON_CHIP = 'on_chip';
    final public const MATCHER_PROTECTION_ON_CHIP_INT = 0x4;
    final public const MATCHER_PROTECTION_TYPES = [self::MATCHER_PROTECTION_SOFTWARE, self::MATCHER_PROTECTION_TEE, self::MATCHER_PROTECTION_ON_CHIP];
    final public const MATCHER_PROTECTION_TYPES_INT = [self::MATCHER_PROTECTION_SOFTWARE_INT, self::MATCHER_PROTECTION_TEE_INT, self::MATCHER_PROTECTION_ON_CHIP_INT];
    final public const ATTACHMENT_HINT_INTERNAL = 'internal';
    final public const ATTACHMENT_HINT_EXTERNAL = 'external';
    final public const ATTACHMENT_HINT_WIRED = 'wired';
    final public const ATTACHMENT_HINT_WIRELESS = 'wireless';
    final public const ATTACHMENT_HINT_NFC = 'nfc';
    final public const ATTACHMENT_HINT_BLUETOOTH = 'bluetooth';
    final public const ATTACHMENT_HINT_NETWORK = 'network';
    final public const ATTACHMENT_HINT_READY = 'ready';
    final public const ATTACHMENT_HINT_WIFI_DIRECT = 'wifi_direct';
    final public const TRANSACTION_CONFIRMATION_DISPLAY_ANY = 'any';
    final public const TRANSACTION_CONFIRMATION_DISPLAY_PRIVILEGED_SOFTWARE = 'privileged_software';
    final public const TRANSACTION_CONFIRMATION_DISPLAY_TEE = 'tee';
    final public const TRANSACTION_CONFIRMATION_DISPLAY_HARDWARE = 'hardware';
    final public const TRANSACTION_CONFIRMATION_DISPLAY_REMOTE = 'remote';
    final public const ALG_SIGN_SECP256R1_ECDSA_SHA256_RAW = 'secp256r1_ecdsa_sha256_raw';
    final public const ALG_SIGN_SECP256R1_ECDSA_SHA256_DER = 'secp256r1_ecdsa_sha256_der';
    final public const ALG_SIGN_RSASSA_PSS_SHA256_RAW = 'rsassa_pss_sha256_raw';
    final public const ALG_SIGN_RSASSA_PSS_SHA256_DER = 'rsassa_pss_sha256_der';
    final public const ALG_SIGN_SECP256K1_ECDSA_SHA256_RAW = 'secp256k1_ecdsa_sha256_raw';
    final public const ALG_SIGN_SECP256K1_ECDSA_SHA256_DER = 'secp256k1_ecdsa_sha256_der';
    final public const ALG_SIGN_SM2_SM3_RAW = 'sm2_sm3_raw';
    final public const ALG_SIGN_RSA_EMSA_PKCS1_SHA256_RAW = 'rsa_emsa_pkcs1_sha256_raw';
    final public const ALG_SIGN_RSA_EMSA_PKCS1_SHA256_DER = 'rsa_emsa_pkcs1_sha256_der';
    final public const ALG_SIGN_RSASSA_PSS_SHA384_RAW = 'rsassa_pss_sha384_raw';
    final public const ALG_SIGN_RSASSA_PSS_SHA512_RAW = 'rsassa_pss_sha256_raw';
    final public const ALG_SIGN_RSASSA_PKCSV15_SHA256_RAW = 'rsassa_pkcsv15_sha256_raw';
    final public const ALG_SIGN_RSASSA_PKCSV15_SHA384_RAW = 'rsassa_pkcsv15_sha384_raw';
    final public const ALG_SIGN_RSASSA_PKCSV15_SHA512_RAW = 'rsassa_pkcsv15_sha512_raw';
    final public const ALG_SIGN_RSASSA_PKCSV15_SHA1_RAW = 'rsassa_pkcsv15_sha1_raw';
    final public const ALG_SIGN_SECP384R1_ECDSA_SHA384_RAW = 'secp384r1_ecdsa_sha384_raw';
    final public const ALG_SIGN_SECP521R1_ECDSA_SHA512_RAW = 'secp512r1_ecdsa_sha256_raw';
    final public const ALG_SIGN_ED25519_EDDSA_SHA256_RAW = 'ed25519_eddsa_sha512_raw';
    final public const ALG_KEY_ECC_X962_RAW = 'ecc_x962_raw';
    final public const ALG_KEY_ECC_X962_DER = 'ecc_x962_der';
    final public const ALG_KEY_RSA_2048_RAW = 'rsa_2048_raw';
    final public const ALG_KEY_RSA_2048_DER = 'rsa_2048_der';
    final public const ALG_KEY_COSE = 'cose';
    final public const ATTESTATION_BASIC_FULL = 'basic_full';
    final public const ATTESTATION_BASIC_SURROGATE = 'basic_surrogate';
    /**
     * @deprecated since 4.2.0 and will be removed in 5.0.0. The ECDAA Trust Anchor does no longer exist in Webauthn specification.
     * @infection-ignore-all
     */
    final public const ATTESTATION_ECDAA = 'ecdaa';
    final public const ATTESTATION_ATTCA = 'attca';
    final public const ATTESTATION_ANONCA = 'anonca';
    public readonly AuthenticatorGetInfo $authenticatorGetInfo;
    /**
     * @param Version[] $upv
     * @param string[] $authenticationAlgorithms
     * @param string[] $publicKeyAlgAndEncodings
     * @param string[] $attestationTypes
     * @param VerificationMethodANDCombinations[] $userVerificationDetails
     * @param string[] $matcherProtection
     * @param string[] $tcDisplay
     * @param string[] $attestationRootCertificates
     * @param string[] $attestationCertificateKeyIdentifiers
     * @param string[] $keyProtection
     * @param string[] $attachmentHint
     * @param EcdaaTrustAnchor[] $ecdaaTrustAnchors
     * @param ExtensionDescriptor[] $supportedExtensions
     */
    public function __construct(public readonly string $description, public readonly int $authenticatorVersion, public readonly string $protocolFamily, public readonly int $schema, public readonly array $upv, public readonly array $authenticationAlgorithms, public readonly array $publicKeyAlgAndEncodings, public readonly array $attestationTypes, public readonly array $userVerificationDetails, public readonly array $matcherProtection, public readonly array $tcDisplay, public readonly array $attestationRootCertificates, public readonly ?AlternativeDescriptions $alternativeDescriptions = null, public ?string $legalHeader = null, public ?string $aaid = null, public ?string $aaguid = null, public array $attestationCertificateKeyIdentifiers = [], public array $keyProtection = [], public ?bool $isKeyRestricted = null, public ?bool $isFreshUserVerificationRequired = null, public ?int $cryptoStrength = null, public array $attachmentHint = [], public ?string $tcDisplayContentType = null, public array $tcDisplayPNGCharacteristics = [], public array $ecdaaTrustAnchors = [], public ?string $icon = null, public array $supportedExtensions = [], ?AuthenticatorGetInfo $authenticatorGetInfo = null)
    {
        $this->authenticatorGetInfo = $authenticatorGetInfo ?? AuthenticatorGetInfo::create($attestationTypes);
    }
    public static function create(string $description, int $authenticatorVersion, string $protocolFamily, int $schema, array $upv, array $authenticationAlgorithms, array $publicKeyAlgAndEncodings, array $attestationTypes, array $userVerificationDetails, array $matcherProtection, array $tcDisplay, array $attestationRootCertificates, array $alternativeDescriptions = [], ?string $legalHeader = null, ?string $aaid = null, ?string $aaguid = null, array $attestationCertificateKeyIdentifiers = [], array $keyProtection = [], ?bool $isKeyRestricted = null, ?bool $isFreshUserVerificationRequired = null, ?int $cryptoStrength = null, array $attachmentHint = [], ?string $tcDisplayContentType = null, array $tcDisplayPNGCharacteristics = [], array $ecdaaTrustAnchors = [], ?string $icon = null, array $supportedExtensions = [], ?AuthenticatorGetInfo $authenticatorGetInfo = null): self
    {
        return new self($description, $authenticatorVersion, $protocolFamily, $schema, $upv, $authenticationAlgorithms, $publicKeyAlgAndEncodings, $attestationTypes, $userVerificationDetails, $matcherProtection, $tcDisplay, $attestationRootCertificates, AlternativeDescriptions::create($alternativeDescriptions), $legalHeader, $aaid, $aaguid, $attestationCertificateKeyIdentifiers, $keyProtection, $isKeyRestricted, $isFreshUserVerificationRequired, $cryptoStrength, $attachmentHint, $tcDisplayContentType, $tcDisplayPNGCharacteristics, $ecdaaTrustAnchors, $icon, $supportedExtensions, $authenticatorGetInfo);
    }
    /**
     * @deprecated since 4.7.0. Please use the symfony/serializer for converting the object.
     * @infection-ignore-all
     */
    public static function createFromString(string $statement): self
    {
        $data = json_decode($statement, \true, flags: JSON_THROW_ON_ERROR);
        return self::createFromArray($data);
    }
    /**
     * @deprecated since 4.7.0. Please use the property directly.
     * @infection-ignore-all
     */
    public function getLegalHeader(): ?string
    {
        return $this->legalHeader;
    }
    /**
     * @deprecated since 4.7.0. Please use the property directly.
     * @infection-ignore-all
     */
    public function getAaid(): ?string
    {
        return $this->aaid;
    }
    /**
     * @deprecated since 4.7.0. Please use the property directly.
     * @infection-ignore-all
     */
    public function getAaguid(): ?string
    {
        return $this->aaguid;
    }
    public function isKeyRestricted(): ?bool
    {
        return $this->isKeyRestricted;
    }
    /**
     * @deprecated since 4.7.0. Please use the property directly.
     * @infection-ignore-all
     */
    public function isFreshUserVerificationRequired(): ?bool
    {
        return $this->isFreshUserVerificationRequired;
    }
    /**
     * @deprecated since 4.7.0. Please use the property directly.
     * @infection-ignore-all
     */
    public function getAuthenticatorGetInfo(): AuthenticatorGetInfo|null
    {
        return $this->authenticatorGetInfo;
    }
    /**
     * @return string[]
     * @deprecated since 4.7.0. Please use the property directly.
     * @infection-ignore-all
     */
    public function getAttestationCertificateKeyIdentifiers(): array
    {
        return $this->attestationCertificateKeyIdentifiers;
    }
    /**
     * @deprecated since 4.7.0. Please use the property directly.
     * @infection-ignore-all
     */
    public function getDescription(): string
    {
        return $this->description;
    }
    /**
     * @deprecated since 4.7.0. Please use the property directly.
     * @infection-ignore-all
     */
    public function getAlternativeDescriptions(): null|AlternativeDescriptions
    {
        return $this->alternativeDescriptions;
    }
    /**
     * @deprecated since 4.7.0. Please use the property directly.
     * @infection-ignore-all
     */
    public function getAuthenticatorVersion(): int
    {
        return $this->authenticatorVersion;
    }
    /**
     * @deprecated since 4.7.0. Please use the property directly.
     * @infection-ignore-all
     */
    public function getProtocolFamily(): string
    {
        return $this->protocolFamily;
    }
    /**
     * @return Version[]
     * @deprecated since 4.7.0. Please use the property directly.
     * @infection-ignore-all
     */
    public function getUpv(): array
    {
        return $this->upv;
    }
    /**
     * @deprecated since 4.7.0. Please use the property directly.
     * @infection-ignore-all
     */
    public function getSchema(): ?int
    {
        return $this->schema;
    }
    /**
     * @return string[]
     * @deprecated since 4.7.0. Please use the property directly.
     * @infection-ignore-all
     */
    public function getAuthenticationAlgorithms(): array
    {
        return $this->authenticationAlgorithms;
    }
    /**
     * @return string[]
     * @deprecated since 4.7.0. Please use the property directly.
     * @infection-ignore-all
     */
    public function getPublicKeyAlgAndEncodings(): array
    {
        return $this->publicKeyAlgAndEncodings;
    }
    /**
     * @return string[]
     * @deprecated since 4.7.0. Please use the property directly.
     * @infection-ignore-all
     */
    public function getAttestationTypes(): array
    {
        return $this->attestationTypes;
    }
    /**
     * @return VerificationMethodANDCombinations[]
     * @deprecated since 4.7.0. Please use the property directly.
     * @infection-ignore-all
     */
    public function getUserVerificationDetails(): array
    {
        return $this->userVerificationDetails;
    }
    /**
     * @return string[]
     * @deprecated since 4.7.0. Please use the property directly.
     * @infection-ignore-all
     */
    public function getKeyProtection(): array
    {
        return $this->keyProtection;
    }
    /**
     * @return string[]
     * @deprecated since 4.7.0. Please use the property directly.
     * @infection-ignore-all
     */
    public function getMatcherProtection(): array
    {
        return $this->matcherProtection;
    }
    /**
     * @deprecated since 4.7.0. Please use the property directly.
     * @infection-ignore-all
     */
    public function getCryptoStrength(): ?int
    {
        return $this->cryptoStrength;
    }
    /**
     * @return string[]
     * @deprecated since 4.7.0. Please use the property directly.
     * @infection-ignore-all
     */
    public function getAttachmentHint(): array
    {
        return $this->attachmentHint;
    }
    /**
     * @return string[]
     * @deprecated since 4.7.0. Please use the property directly.
     * @infection-ignore-all
     */
    public function getTcDisplay(): array
    {
        return $this->tcDisplay;
    }
    /**
     * @deprecated since 4.7.0. Please use the property directly.
     * @infection-ignore-all
     */
    public function getTcDisplayContentType(): ?string
    {
        return $this->tcDisplayContentType;
    }
    /**
     * @return DisplayPNGCharacteristicsDescriptor[]
     * @deprecated since 4.7.0. Please use the property directly.
     * @infection-ignore-all
     */
    public function getTcDisplayPNGCharacteristics(): array
    {
        return $this->tcDisplayPNGCharacteristics;
    }
    /**
     * @return string[]
     * @deprecated since 4.7.0. Please use the property directly.
     * @infection-ignore-all
     */
    public function getAttestationRootCertificates(): array
    {
        return $this->attestationRootCertificates;
    }
    /**
     * @return EcdaaTrustAnchor[]
     *
     * @deprecated since 4.2.0 and will be removed in 5.0.0. The ECDAA Trust Anchor does no longer exist in Webauthn specification.
     * @infection-ignore-all
     */
    public function getEcdaaTrustAnchors(): array
    {
        return $this->ecdaaTrustAnchors;
    }
    /**
     * @deprecated since 4.7.0. Please use the property directly.
     * @infection-ignore-all
     */
    public function getIcon(): ?string
    {
        return $this->icon;
    }
    /**
     * @return ExtensionDescriptor[]
     * @deprecated since 4.7.0. Please use the property directly.
     * @infection-ignore-all
     */
    public function getSupportedExtensions(): array
    {
        return $this->supportedExtensions;
    }
    /**
     * @param array<string, mixed> $data
     * @deprecated since 4.7.0. Please use the symfony/serializer for converting the object.
     * @infection-ignore-all
     */
    public static function createFromArray(array $data): self
    {
        $requiredKeys = ['description', 'authenticatorVersion', 'protocolFamily', 'schema', 'upv', 'authenticationAlgorithms', 'publicKeyAlgAndEncodings', 'attestationTypes', 'userVerificationDetails', 'matcherProtection', 'tcDisplay', 'attestationRootCertificates'];
        foreach ($requiredKeys as $key) {
            array_key_exists($key, $data) || throw MetadataStatementLoadingException::create(sprintf('Invalid data. The key "%s" is missing', $key));
        }
        $subObjects = ['authenticationAlgorithms', 'publicKeyAlgAndEncodings', 'attestationTypes', 'matcherProtection', 'tcDisplay', 'attestationRootCertificates'];
        foreach ($subObjects as $subObject) {
            is_array($data[$subObject]) || throw MetadataStatementLoadingException::create(sprintf('Invalid Metadata Statement. The parameter "%s" shall be a list of strings.', $subObject));
            foreach ($data[$subObject] as $datum) {
                is_string($datum) || throw MetadataStatementLoadingException::create(sprintf('Invalid Metadata Statement. The parameter "%s" shall be a list of strings.', $subObject));
            }
        }
        return self::create($data['description'], $data['authenticatorVersion'], $data['protocolFamily'], $data['schema'], array_map(static function ($upv): Version {
            is_array($upv) || throw MetadataStatementLoadingException::create('Invalid Metadata Statement. The parameter "upv" shall be a list of objects.');
            return Version::createFromArray($upv);
        }, $data['upv']), $data['authenticationAlgorithms'], $data['publicKeyAlgAndEncodings'], $data['attestationTypes'], array_map(static function ($userVerificationDetails): VerificationMethodANDCombinations {
            is_array($userVerificationDetails) || throw MetadataStatementLoadingException::create('Invalid Metadata Statement. The parameter "userVerificationDetails" shall be a list of objects.');
            return VerificationMethodANDCombinations::createFromArray($userVerificationDetails);
        }, $data['userVerificationDetails']), $data['matcherProtection'], $data['tcDisplay'], CertificateToolbox::fixPEMStructures($data['attestationRootCertificates']), $data['alternativeDescriptions'] ?? [], $data['legalHeader'] ?? null, $data['aaid'] ?? null, $data['aaguid'] ?? null, $data['attestationCertificateKeyIdentifiers'] ?? [], $data['keyProtection'] ?? [], $data['isKeyRestricted'] ?? null, $data['isFreshUserVerificationRequired'] ?? null, $data['cryptoStrength'] ?? null, $data['attachmentHint'] ?? [], $data['tcDisplayContentType'] ?? null, array_map(static fn(array $data): DisplayPNGCharacteristicsDescriptor => DisplayPNGCharacteristicsDescriptor::createFromArray($data), $data['tcDisplayPNGCharacteristics'] ?? []), $data['ecdaaTrustAnchors'] ?? [], $data['icon'] ?? null, array_map(static fn($supportedExtension): ExtensionDescriptor => ExtensionDescriptor::createFromArray($supportedExtension), $data['supportedExtensions'] ?? []), isset($data['authenticatorGetInfo']) ? AuthenticatorGetInfo::create($data['authenticatorGetInfo']) : null);
    }
    /**
     * @return array<string, mixed>
     */
    public function jsonSerialize(): array
    {
        trigger_deprecation('web-auth/webauthn-bundle', '4.9.0', 'The "%s" method is deprecated and will be removed in 5.0. Please use the serializer instead.', __METHOD__);
        $data = ['legalHeader' => $this->legalHeader, 'aaid' => $this->aaid, 'aaguid' => $this->aaguid, 'attestationCertificateKeyIdentifiers' => $this->attestationCertificateKeyIdentifiers, 'description' => $this->description, 'alternativeDescriptions' => $this->alternativeDescriptions, 'authenticatorVersion' => $this->authenticatorVersion, 'protocolFamily' => $this->protocolFamily, 'schema' => $this->schema, 'upv' => $this->upv, 'authenticationAlgorithms' => $this->authenticationAlgorithms, 'publicKeyAlgAndEncodings' => $this->publicKeyAlgAndEncodings, 'attestationTypes' => $this->attestationTypes, 'userVerificationDetails' => $this->userVerificationDetails, 'keyProtection' => $this->keyProtection, 'isKeyRestricted' => $this->isKeyRestricted, 'isFreshUserVerificationRequired' => $this->isFreshUserVerificationRequired, 'matcherProtection' => $this->matcherProtection, 'cryptoStrength' => $this->cryptoStrength, 'attachmentHint' => $this->attachmentHint, 'tcDisplay' => $this->tcDisplay, 'tcDisplayContentType' => $this->tcDisplayContentType, 'tcDisplayPNGCharacteristics' => $this->tcDisplayPNGCharacteristics, 'attestationRootCertificates' => CertificateToolbox::fixPEMStructures($this->attestationRootCertificates), 'ecdaaTrustAnchors' => $this->ecdaaTrustAnchors, 'icon' => $this->icon, 'authenticatorGetInfo' => $this->authenticatorGetInfo, 'supportedExtensions' => $this->supportedExtensions];
        return self::filterNullValues($data);
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\Webauthn\MetadataService\Statement;

use JsonSerializable;
class AuthenticatorGetInfo implements JsonSerializable
{
    /**
     * @param array<string|int, mixed> $info
     */
    public function __construct(public array $info = [])
    {
    }
    /**
     * @param array<string|int, mixed> $info
     */
    public static function create(array $info = []): self
    {
        return new self($info);
    }
    /**
     * @deprecated since 4.7.0. Please use the constructor directly.
     * @infection-ignore-all
     */
    public function add(string|int $key, mixed $value): self
    {
        $this->info[$key] = $value;
        return $this;
    }
    /**
     * @return string[]
     */
    public function jsonSerialize(): array
    {
        trigger_deprecation('web-auth/webauthn-bundle', '4.9.0', 'The "%s" method is deprecated and will be removed in 5.0. Please use the serializer instead.', __METHOD__);
        return $this->info;
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\Webauthn\MetadataService\Statement;

use JsonSerializable;
class VerificationMethodANDCombinations implements JsonSerializable
{
    /**
     * @param VerificationMethodDescriptor[] $verificationMethods
     */
    public function __construct(
        /** @readonly */
        public array $verificationMethods = []
    )
    {
    }
    /**
     * @param VerificationMethodDescriptor[] $verificationMethods
     */
    public static function create(array $verificationMethods): self
    {
        return new self($verificationMethods);
    }
    /**
     * @deprecated since 4.7.0. Please use the {self::create} directly.
     * @infection-ignore-all
     */
    public function addVerificationMethodDescriptor(VerificationMethodDescriptor $verificationMethodDescriptor): self
    {
        $this->verificationMethods[] = $verificationMethodDescriptor;
        return $this;
    }
    /**
     * @return VerificationMethodDescriptor[]
     * @deprecated since 4.7.0. Please use the property directly.
     * @infection-ignore-all
     */
    public function getVerificationMethods(): array
    {
        return $this->verificationMethods;
    }
    /**
     * @param array<string, mixed> $data
     * @deprecated since 4.7.0. Please use the symfony/serializer for converting the object.
     * @infection-ignore-all
     */
    public static function createFromArray(array $data): self
    {
        return self::create(array_map(static fn(array $datum): VerificationMethodDescriptor => VerificationMethodDescriptor::createFromArray($datum), $data));
    }
    /**
     * @return array<VerificationMethodDescriptor>
     */
    public function jsonSerialize(): array
    {
        trigger_deprecation('web-auth/webauthn-bundle', '4.9.0', 'The "%s" method is deprecated and will be removed in 5.0. Please use the serializer instead.', __METHOD__);
        return $this->verificationMethods;
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\Webauthn\MetadataService\Statement;

use JsonSerializable;
class BiometricStatusReport implements JsonSerializable
{
    private function __construct(public readonly ?int $certLevel, public readonly ?int $modality, public readonly ?string $effectiveDate, public readonly ?string $certificationDescriptor, public readonly ?string $certificateNumber, public readonly ?string $certificationPolicyVersion, public readonly ?string $certificationRequirementsVersion)
    {
    }
    public static function create(?int $certLevel, ?int $modality, ?string $effectiveDate, ?string $certificationDescriptor, ?string $certificateNumber, ?string $certificationPolicyVersion, ?string $certificationRequirementsVersion): self
    {
        return new self($certLevel, $modality, $effectiveDate, $certificationDescriptor, $certificateNumber, $certificationPolicyVersion, $certificationRequirementsVersion);
    }
    /**
     * @deprecated since 4.7.0. Please use the property directly.
     * @infection-ignore-all
     */
    public function getCertLevel(): int|null
    {
        return $this->certLevel;
    }
    /**
     * @deprecated since 4.7.0. Please use the property directly.
     * @infection-ignore-all
     */
    public function getModality(): int|null
    {
        return $this->modality;
    }
    /**
     * @deprecated since 4.7.0. Please use the property directly.
     * @infection-ignore-all
     */
    public function getEffectiveDate(): ?string
    {
        return $this->effectiveDate;
    }
    /**
     * @deprecated since 4.7.0. Please use the property directly.
     * @infection-ignore-all
     */
    public function getCertificationDescriptor(): ?string
    {
        return $this->certificationDescriptor;
    }
    /**
     * @deprecated since 4.7.0. Please use the property directly.
     * @infection-ignore-all
     */
    public function getCertificateNumber(): ?string
    {
        return $this->certificateNumber;
    }
    /**
     * @deprecated since 4.7.0. Please use the property directly.
     * @infection-ignore-all
     */
    public function getCertificationPolicyVersion(): ?string
    {
        return $this->certificationPolicyVersion;
    }
    /**
     * @deprecated since 4.7.0. Please use the property directly.
     * @infection-ignore-all
     */
    public function getCertificationRequirementsVersion(): ?string
    {
        return $this->certificationRequirementsVersion;
    }
    /**
     * @param array<string, mixed> $data
     * @deprecated since 4.7.0. Please use the symfony/serializer for converting the object.
     * @infection-ignore-all
     */
    public static function createFromArray(array $data): self
    {
        return self::create($data['certLevel'] ?? null, $data['modality'] ?? null, $data['effectiveDate'] ?? null, $data['certificationDescriptor'] ?? null, $data['certificateNumber'] ?? null, $data['certificationPolicyVersion'] ?? null, $data['certificationRequirementsVersion'] ?? null);
    }
    /**
     * @return array<string, mixed>
     */
    public function jsonSerialize(): array
    {
        trigger_deprecation('web-auth/webauthn-bundle', '4.9.0', 'The "%s" method is deprecated and will be removed in 5.0. Please use the serializer instead.', __METHOD__);
        $data = ['certLevel' => $this->certLevel, 'modality' => $this->modality, 'effectiveDate' => $this->effectiveDate, 'certificationDescriptor' => $this->certificationDescriptor, 'certificateNumber' => $this->certificateNumber, 'certificationPolicyVersion' => $this->certificationPolicyVersion, 'certificationRequirementsVersion' => $this->certificationRequirementsVersion];
        return array_filter($data, static fn($var): bool => $var !== null);
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\Webauthn\MetadataService\Statement;

final class AuthenticatorStatus
{
    final public const NOT_FIDO_CERTIFIED = 'NOT_FIDO_CERTIFIED';
    final public const FIDO_CERTIFIED = 'FIDO_CERTIFIED';
    final public const USER_VERIFICATION_BYPASS = 'USER_VERIFICATION_BYPASS';
    final public const ATTESTATION_KEY_COMPROMISE = 'ATTESTATION_KEY_COMPROMISE';
    final public const USER_KEY_REMOTE_COMPROMISE = 'USER_KEY_REMOTE_COMPROMISE';
    final public const USER_KEY_PHYSICAL_COMPROMISE = 'USER_KEY_PHYSICAL_COMPROMISE';
    final public const UPDATE_AVAILABLE = 'UPDATE_AVAILABLE';
    final public const REVOKED = 'REVOKED';
    final public const SELF_ASSERTION_SUBMITTED = 'SELF_ASSERTION_SUBMITTED';
    final public const FIDO_CERTIFIED_L1 = 'FIDO_CERTIFIED_L1';
    final public const FIDO_CERTIFIED_L1plus = 'FIDO_CERTIFIED_L1plus';
    final public const FIDO_CERTIFIED_L2 = 'FIDO_CERTIFIED_L2';
    final public const FIDO_CERTIFIED_L2plus = 'FIDO_CERTIFIED_L2plus';
    final public const FIDO_CERTIFIED_L3 = 'FIDO_CERTIFIED_L3';
    final public const FIDO_CERTIFIED_L3plus = 'FIDO_CERTIFIED_L3plus';
    final public const FIDO_CERTIFIED_L4 = 'FIDO_CERTIFIED_L4';
    final public const FIDO_CERTIFIED_L5 = 'FIDO_CERTIFIED_L5';
    final public const STATUSES = [self::NOT_FIDO_CERTIFIED, self::FIDO_CERTIFIED, self::USER_VERIFICATION_BYPASS, self::ATTESTATION_KEY_COMPROMISE, self::USER_KEY_REMOTE_COMPROMISE, self::USER_KEY_PHYSICAL_COMPROMISE, self::UPDATE_AVAILABLE, self::REVOKED, self::SELF_ASSERTION_SUBMITTED, self::FIDO_CERTIFIED_L1, self::FIDO_CERTIFIED_L1plus, self::FIDO_CERTIFIED_L2, self::FIDO_CERTIFIED_L2plus, self::FIDO_CERTIFIED_L3, self::FIDO_CERTIFIED_L3plus, self::FIDO_CERTIFIED_L4, self::FIDO_CERTIFIED_L5];
    /**
     * @return string[]
     * @deprecated since 4.7.0. Please use the constant STATUSES instead.
     * @infection-ignore-all
     */
    public static function list(): array
    {
        return self::STATUSES;
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\Webauthn\MetadataService\Statement;

use JsonSerializable;
use _ContaoManager\Webauthn\Exception\MetadataStatementLoadingException;
abstract class AbstractDescriptor implements JsonSerializable
{
    public function __construct(public readonly ?int $maxRetries = null, public readonly ?int $blockSlowdown = null)
    {
        $maxRetries >= 0 || throw MetadataStatementLoadingException::create('Invalid data. The value of "maxRetries" must be a positive integer');
        $blockSlowdown >= 0 || throw MetadataStatementLoadingException::create('Invalid data. The value of "blockSlowdown" must be a positive integer');
    }
    /**
     * @deprecated since 4.7.0. Please use the property directly.
     * @infection-ignore-all
     */
    public function getMaxRetries(): ?int
    {
        return $this->maxRetries;
    }
    /**
     * @deprecated since 4.7.0. Please use the property directly.
     * @infection-ignore-all
     */
    public function getBlockSlowdown(): ?int
    {
        return $this->blockSlowdown;
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\Webauthn\MetadataService\Statement;

use JsonSerializable;
use _ContaoManager\ParagonIE\ConstantTime\Base64UrlSafe;
use _ContaoManager\Webauthn\Exception\MetadataStatementLoadingException;
use _ContaoManager\Webauthn\MetadataService\ValueFilter;
use function array_key_exists;
use function sprintf;
/**
 * @deprecated since 4.2.0 and will be removed in 5.0.0. The ECDAA Trust Anchor does no longer exist in Webauthn specification.
 * @infection-ignore-all
 */
class EcdaaTrustAnchor implements JsonSerializable
{
    use ValueFilter;
    public function __construct(private readonly string $X, private readonly string $Y, private readonly string $c, private readonly string $sx, private readonly string $sy, private readonly string $G1Curve)
    {
    }
    public function getX(): string
    {
        return $this->X;
    }
    public function getY(): string
    {
        return $this->Y;
    }
    public function getC(): string
    {
        return $this->c;
    }
    public function getSx(): string
    {
        return $this->sx;
    }
    public function getSy(): string
    {
        return $this->sy;
    }
    public function getG1Curve(): string
    {
        return $this->G1Curve;
    }
    /**
     * @param array<string, mixed> $data
     * @deprecated since 4.7.0. Please use the symfony/serializer for converting the object.
     */
    public static function createFromArray(array $data): self
    {
        $data = self::filterNullValues($data);
        foreach (['X', 'Y', 'c', 'sx', 'sy', 'G1Curve'] as $key) {
            array_key_exists($key, $data) || throw MetadataStatementLoadingException::create(sprintf('Invalid data. The key "%s" is missing', $key));
        }
        return new self(Base64UrlSafe::decode($data['X']), Base64UrlSafe::decode($data['Y']), Base64UrlSafe::decode($data['c']), Base64UrlSafe::decode($data['sx']), Base64UrlSafe::decode($data['sy']), $data['G1Curve']);
    }
    /**
     * @return array<string, string>
     */
    public function jsonSerialize(): array
    {
        trigger_deprecation('web-auth/webauthn-bundle', '4.9.0', 'The "%s" method is deprecated and will be removed in 5.0. Please use the serializer instead.', __METHOD__);
        $data = ['X' => Base64UrlSafe::encodeUnpadded($this->X), 'Y' => Base64UrlSafe::encodeUnpadded($this->Y), 'c' => Base64UrlSafe::encodeUnpadded($this->c), 'sx' => Base64UrlSafe::encodeUnpadded($this->sx), 'sy' => Base64UrlSafe::encodeUnpadded($this->sy), 'G1Curve' => $this->G1Curve];
        return self::filterNullValues($data);
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\Webauthn\MetadataService\Statement;

use JsonSerializable;
use _ContaoManager\Webauthn\Exception\MetadataStatementLoadingException;
use _ContaoManager\Webauthn\MetadataService\ValueFilter;
use function array_key_exists;
use function in_array;
use function is_string;
use function sprintf;
class StatusReport implements JsonSerializable
{
    use ValueFilter;
    /**
     * @see AuthenticatorStatus
     */
    public function __construct(public readonly string $status, public readonly ?string $effectiveDate, public readonly ?string $certificate, public readonly ?string $url, public readonly ?string $certificationDescriptor, public readonly ?string $certificateNumber, public readonly ?string $certificationPolicyVersion, public readonly ?string $certificationRequirementsVersion)
    {
        in_array($status, AuthenticatorStatus::STATUSES, \true) || throw MetadataStatementLoadingException::create('The value of the key "status" is not acceptable');
    }
    public static function create(string $status, ?string $effectiveDate, ?string $certificate, ?string $url, ?string $certificationDescriptor, ?string $certificateNumber, ?string $certificationPolicyVersion, ?string $certificationRequirementsVersion): self
    {
        return new self($status, $effectiveDate, $certificate, $url, $certificationDescriptor, $certificateNumber, $certificationPolicyVersion, $certificationRequirementsVersion);
    }
    public function isCompromised(): bool
    {
        return in_array($this->status, [AuthenticatorStatus::ATTESTATION_KEY_COMPROMISE, AuthenticatorStatus::USER_KEY_PHYSICAL_COMPROMISE, AuthenticatorStatus::USER_KEY_REMOTE_COMPROMISE, AuthenticatorStatus::USER_VERIFICATION_BYPASS, AuthenticatorStatus::REVOKED], \true);
    }
    /**
     * @deprecated since 4.7.0. Please use the property directly.
     * @infection-ignore-all
     */
    public function getStatus(): string
    {
        return $this->status;
    }
    /**
     * @deprecated since 4.7.0. Please use the property directly.
     * @infection-ignore-all
     */
    public function getEffectiveDate(): ?string
    {
        return $this->effectiveDate;
    }
    /**
     * @deprecated since 4.7.0. Please use the property directly.
     * @infection-ignore-all
     */
    public function getCertificate(): ?string
    {
        return $this->certificate;
    }
    /**
     * @deprecated since 4.7.0. Please use the property directly.
     * @infection-ignore-all
     */
    public function getUrl(): ?string
    {
        return $this->url;
    }
    /**
     * @deprecated since 4.7.0. Please use the property directly.
     * @infection-ignore-all
     */
    public function getCertificationDescriptor(): ?string
    {
        return $this->certificationDescriptor;
    }
    /**
     * @deprecated since 4.7.0. Please use the property directly.
     * @infection-ignore-all
     */
    public function getCertificateNumber(): ?string
    {
        return $this->certificateNumber;
    }
    /**
     * @deprecated since 4.7.0. Please use the property directly.
     * @infection-ignore-all
     */
    public function getCertificationPolicyVersion(): ?string
    {
        return $this->certificationPolicyVersion;
    }
    /**
     * @deprecated since 4.7.0. Please use the property directly.
     * @infection-ignore-all
     */
    public function getCertificationRequirementsVersion(): ?string
    {
        return $this->certificationRequirementsVersion;
    }
    /**
     * @param array<string, mixed> $data
     * @deprecated since 4.7.0. Please use the symfony/serializer for converting the object.
     * @infection-ignore-all
     */
    public static function createFromArray(array $data): self
    {
        $data = self::filterNullValues($data);
        array_key_exists('status', $data) || throw MetadataStatementLoadingException::create('The key "status" is missing');
        foreach (['effectiveDate', 'certificate', 'url', 'certificationDescriptor', 'certificateNumber', 'certificationPolicyVersion', 'certificationRequirementsVersion'] as $key) {
            if (isset($data[$key])) {
                $value = $data[$key];
                $value === null || is_string($value) || throw MetadataStatementLoadingException::create(sprintf('The value of the key "%s" is invalid', $key));
            }
        }
        return self::create($data['status'], $data['effectiveDate'] ?? null, $data['certificate'] ?? null, $data['url'] ?? null, $data['certificationDescriptor'] ?? null, $data['certificateNumber'] ?? null, $data['certificationPolicyVersion'] ?? null, $data['certificationRequirementsVersion'] ?? null);
    }
    /**
     * @return array<string, mixed>
     */
    public function jsonSerialize(): array
    {
        trigger_deprecation('web-auth/webauthn-bundle', '4.9.0', 'The "%s" method is deprecated and will be removed in 5.0. Please use the serializer instead.', __METHOD__);
        $data = ['status' => $this->status, 'effectiveDate' => $this->effectiveDate, 'certificate' => $this->certificate, 'url' => $this->url, 'certificationDescriptor' => $this->certificationDescriptor, 'certificateNumber' => $this->certificateNumber, 'certificationPolicyVersion' => $this->certificationPolicyVersion, 'certificationRequirementsVersion' => $this->certificationRequirementsVersion];
        return self::filterNullValues($data);
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\Webauthn\MetadataService\Statement;

use JsonSerializable;
use _ContaoManager\Webauthn\Exception\MetadataStatementLoadingException;
use _ContaoManager\Webauthn\MetadataService\ValueFilter;
use function array_key_exists;
use function is_array;
use function sprintf;
class VerificationMethodDescriptor implements JsonSerializable
{
    use ValueFilter;
    final public const USER_VERIFY_PRESENCE_INTERNAL = 'presence_internal';
    final public const USER_VERIFY_PRESENCE_INTERNAL_INT = 0x1;
    final public const USER_VERIFY_FINGERPRINT_INTERNAL = 'fingerprint_internal';
    final public const USER_VERIFY_FINGERPRINT_INTERNAL_INT = 0x2;
    final public const USER_VERIFY_PASSCODE_INTERNAL = 'passcode_internal';
    final public const USER_VERIFY_PASSCODE_INTERNAL_INT = 0x4;
    final public const USER_VERIFY_VOICEPRINT_INTERNAL = 'voiceprint_internal';
    final public const USER_VERIFY_VOICEPRINT_INTERNAL_INT = 0x8;
    final public const USER_VERIFY_FACEPRINT_INTERNAL = 'faceprint_internal';
    final public const USER_VERIFY_FACEPRINT_INTERNAL_INT = 0x10;
    final public const USER_VERIFY_LOCATION_INTERNAL = 'location_internal';
    final public const USER_VERIFY_LOCATION_INTERNAL_INT = 0x20;
    final public const USER_VERIFY_EYEPRINT_INTERNAL = 'eyeprint_internal';
    final public const USER_VERIFY_EYEPRINT_INTERNAL_INT = 0x40;
    final public const USER_VERIFY_PATTERN_INTERNAL = 'pattern_internal';
    final public const USER_VERIFY_PATTERN_INTERNAL_INT = 0x80;
    final public const USER_VERIFY_HANDPRINT_INTERNAL = 'handprint_internal';
    final public const USER_VERIFY_HANDPRINT_INTERNAL_INT = 0x100;
    final public const USER_VERIFY_PASSCODE_EXTERNAL = 'passcode_external';
    final public const USER_VERIFY_PASSCODE_EXTERNAL_INT = 0x800;
    final public const USER_VERIFY_PATTERN_EXTERNAL = 'pattern_external';
    final public const USER_VERIFY_PATTERN_EXTERNAL_INT = 0x1000;
    final public const USER_VERIFY_NONE = 'none';
    final public const USER_VERIFY_NONE_INT = 0x200;
    final public const USER_VERIFY_ALL = 'all';
    final public const USER_VERIFY_ALL_INT = 0x400;
    final public const USER_VERIFICATION_METHODS = [self::USER_VERIFY_PRESENCE_INTERNAL, self::USER_VERIFY_FINGERPRINT_INTERNAL, self::USER_VERIFY_PASSCODE_INTERNAL, self::USER_VERIFY_VOICEPRINT_INTERNAL, self::USER_VERIFY_FACEPRINT_INTERNAL, self::USER_VERIFY_LOCATION_INTERNAL, self::USER_VERIFY_EYEPRINT_INTERNAL, self::USER_VERIFY_PATTERN_INTERNAL, self::USER_VERIFY_HANDPRINT_INTERNAL, self::USER_VERIFY_PASSCODE_EXTERNAL, self::USER_VERIFY_PATTERN_EXTERNAL, self::USER_VERIFY_NONE, self::USER_VERIFY_ALL];
    final public const USER_VERIFICATION_METHODS_INT = [self::USER_VERIFY_PRESENCE_INTERNAL_INT, self::USER_VERIFY_FINGERPRINT_INTERNAL_INT, self::USER_VERIFY_PASSCODE_INTERNAL_INT, self::USER_VERIFY_VOICEPRINT_INTERNAL_INT, self::USER_VERIFY_FACEPRINT_INTERNAL_INT, self::USER_VERIFY_LOCATION_INTERNAL_INT, self::USER_VERIFY_EYEPRINT_INTERNAL_INT, self::USER_VERIFY_PATTERN_INTERNAL_INT, self::USER_VERIFY_HANDPRINT_INTERNAL_INT, self::USER_VERIFY_PASSCODE_EXTERNAL_INT, self::USER_VERIFY_PATTERN_EXTERNAL_INT, self::USER_VERIFY_NONE_INT, self::USER_VERIFY_ALL_INT];
    public function __construct(public readonly string $userVerificationMethod, public readonly ?CodeAccuracyDescriptor $caDesc = null, public readonly ?BiometricAccuracyDescriptor $baDesc = null, public readonly ?PatternAccuracyDescriptor $paDesc = null)
    {
        $userVerificationMethod >= 0 || throw MetadataStatementLoadingException::create('The parameter "userVerificationMethod" is invalid');
    }
    public static function create(string $userVerificationMethod, ?CodeAccuracyDescriptor $caDesc = null, ?BiometricAccuracyDescriptor $baDesc = null, ?PatternAccuracyDescriptor $paDesc = null): self
    {
        return new self($userVerificationMethod, $caDesc, $baDesc, $paDesc);
    }
    /**
     * @deprecated since 4.7.0. Please use the property directly.
     * @infection-ignore-all
     */
    public function getUserVerificationMethod(): string
    {
        return $this->userVerificationMethod;
    }
    public function userPresence(): bool
    {
        return $this->userVerificationMethod === self::USER_VERIFY_PRESENCE_INTERNAL;
    }
    public function fingerprint(): bool
    {
        return $this->userVerificationMethod === self::USER_VERIFY_FINGERPRINT_INTERNAL;
    }
    public function passcodeInternal(): bool
    {
        return $this->userVerificationMethod === self::USER_VERIFY_PASSCODE_INTERNAL;
    }
    public function voicePrint(): bool
    {
        return $this->userVerificationMethod === self::USER_VERIFY_VOICEPRINT_INTERNAL;
    }
    public function facePrint(): bool
    {
        return $this->userVerificationMethod === self::USER_VERIFY_FACEPRINT_INTERNAL;
    }
    public function location(): bool
    {
        return $this->userVerificationMethod === self::USER_VERIFY_LOCATION_INTERNAL;
    }
    public function eyePrint(): bool
    {
        return $this->userVerificationMethod === self::USER_VERIFY_EYEPRINT_INTERNAL;
    }
    public function patternInternal(): bool
    {
        return $this->userVerificationMethod === self::USER_VERIFY_PATTERN_INTERNAL;
    }
    public function handprint(): bool
    {
        return $this->userVerificationMethod === self::USER_VERIFY_HANDPRINT_INTERNAL;
    }
    public function passcodeExternal(): bool
    {
        return $this->userVerificationMethod === self::USER_VERIFY_PASSCODE_EXTERNAL;
    }
    public function patternExternal(): bool
    {
        return $this->userVerificationMethod === self::USER_VERIFY_PATTERN_EXTERNAL;
    }
    public function none(): bool
    {
        return $this->userVerificationMethod === self::USER_VERIFY_NONE;
    }
    public function all(): bool
    {
        return $this->userVerificationMethod === self::USER_VERIFY_ALL;
    }
    /**
     * @deprecated since 4.7.0. Please use the property directly.
     * @infection-ignore-all
     */
    public function getCaDesc(): ?CodeAccuracyDescriptor
    {
        return $this->caDesc;
    }
    /**
     * @deprecated since 4.7.0. Please use the property directly.
     * @infection-ignore-all
     */
    public function getBaDesc(): ?BiometricAccuracyDescriptor
    {
        return $this->baDesc;
    }
    /**
     * @deprecated since 4.7.0. Please use the property directly.
     * @infection-ignore-all
     */
    public function getPaDesc(): ?PatternAccuracyDescriptor
    {
        return $this->paDesc;
    }
    /**
     * @param array<string, mixed> $data
     * @deprecated since 4.7.0. Please use the symfony/serializer for converting the object.
     * @infection-ignore-all
     */
    public static function createFromArray(array $data): self
    {
        $data = self::filterNullValues($data);
        if (isset($data['userVerification']) && !isset($data['userVerificationMethod'])) {
            $data['userVerificationMethod'] = $data['userVerification'];
            unset($data['userVerification']);
        }
        array_key_exists('userVerificationMethod', $data) || throw MetadataStatementLoadingException::create('The parameters "userVerificationMethod" is missing');
        foreach (['caDesc', 'baDesc', 'paDesc'] as $key) {
            if (isset($data[$key])) {
                is_array($data[$key]) || throw MetadataStatementLoadingException::create(sprintf('Invalid parameter "%s"', $key));
            }
        }
        $caDesc = isset($data['caDesc']) ? CodeAccuracyDescriptor::createFromArray($data['caDesc']) : null;
        $baDesc = isset($data['baDesc']) ? BiometricAccuracyDescriptor::createFromArray($data['baDesc']) : null;
        $paDesc = isset($data['paDesc']) ? PatternAccuracyDescriptor::createFromArray($data['paDesc']) : null;
        return self::create($data['userVerificationMethod'], $caDesc, $baDesc, $paDesc);
    }
    /**
     * @return array<string, mixed>
     */
    public function jsonSerialize(): array
    {
        trigger_deprecation('web-auth/webauthn-bundle', '4.9.0', 'The "%s" method is deprecated and will be removed in 5.0. Please use the serializer instead.', __METHOD__);
        $data = ['userVerificationMethod' => $this->userVerificationMethod, 'caDesc' => $this->caDesc, 'baDesc' => $this->baDesc, 'paDesc' => $this->paDesc];
        return self::filterNullValues($data);
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\Webauthn\MetadataService\Statement;

use JsonSerializable;
class AlternativeDescriptions implements JsonSerializable
{
    /**
     * @param array<string, string> $descriptions
     */
    public function __construct(public array $descriptions = [])
    {
    }
    /**
     * @param array<string, string> $descriptions
     */
    public static function create(array $descriptions = []): self
    {
        return new self($descriptions);
    }
    /**
     * @return array<string, string>
     * @deprecated since 4.7.0. Please use the property directly.
     * @infection-ignore-all
     */
    public function all(): array
    {
        return $this->descriptions;
    }
    /**
     * @deprecated since 4.7.0. Please use the property directly.
     * @infection-ignore-all
     */
    public function add(string $locale, string $description): self
    {
        $this->descriptions[$locale] = $description;
        return $this;
    }
    /**
     * @return array<string, string>
     */
    public function jsonSerialize(): array
    {
        trigger_deprecation('web-auth/webauthn-bundle', '4.9.0', 'The "%s" method is deprecated and will be removed in 5.0. Please use the serializer instead.', __METHOD__);
        return $this->descriptions;
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\Webauthn\MetadataService\Statement;

use _ContaoManager\Webauthn\MetadataService\ValueFilter;
class BiometricAccuracyDescriptor extends AbstractDescriptor
{
    use ValueFilter;
    public function __construct(public readonly ?float $selfAttestedFRR, public readonly ?float $selfAttestedFAR, public readonly ?float $maxTemplates, ?int $maxRetries = null, ?int $blockSlowdown = null)
    {
        parent::__construct($maxRetries, $blockSlowdown);
    }
    public static function create(?float $selfAttestedFRR, ?float $selfAttestedFAR, ?float $maxTemplates, ?int $maxRetries = null, ?int $blockSlowdown = null): self
    {
        return new self($selfAttestedFRR, $selfAttestedFAR, $maxTemplates, $maxRetries, $blockSlowdown);
    }
    /**
     * @deprecated since 4.7.0. Please use the property directly.
     */
    public function getSelfAttestedFRR(): ?float
    {
        return $this->selfAttestedFRR;
    }
    /**
     * @deprecated since 4.7.0. Please use the property directly.
     */
    public function getSelfAttestedFAR(): ?float
    {
        return $this->selfAttestedFAR;
    }
    /**
     * @deprecated since 4.7.0. Please use the property directly.
     */
    public function getMaxTemplates(): ?float
    {
        return $this->maxTemplates;
    }
    /**
     * @param array<string, mixed> $data
     * @deprecated since 4.7.0. Please use the symfony/serializer for converting the object.
     */
    public static function createFromArray(array $data): self
    {
        return self::create($data['selfAttestedFRR'] ?? null, $data['selfAttestedFAR'] ?? null, $data['maxTemplates'] ?? null, $data['maxRetries'] ?? null, $data['blockSlowdown'] ?? null);
    }
    /**
     * @return array<string, mixed>
     */
    public function jsonSerialize(): array
    {
        trigger_deprecation('web-auth/webauthn-bundle', '4.9.0', 'The "%s" method is deprecated and will be removed in 5.0. Please use the serializer instead.', __METHOD__);
        $data = ['selfAttestedFRR' => $this->selfAttestedFRR, 'selfAttestedFAR' => $this->selfAttestedFAR, 'maxTemplates' => $this->maxTemplates, 'maxRetries' => $this->maxRetries, 'blockSlowdown' => $this->blockSlowdown];
        return self::filterNullValues($data);
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\Webauthn\MetadataService\Statement;

use JsonSerializable;
use _ContaoManager\Webauthn\Exception\MetadataStatementLoadingException;
use _ContaoManager\Webauthn\MetadataService\ValueFilter;
use function array_key_exists;
use function is_int;
use function sprintf;
class Version implements JsonSerializable
{
    use ValueFilter;
    public function __construct(public readonly ?int $major, public readonly ?int $minor)
    {
        if ($major === null && $minor === null) {
            throw MetadataStatementLoadingException::create('Invalid data. Must contain at least one item');
        }
        $major >= 0 || throw MetadataStatementLoadingException::create('Invalid argument "major"');
        $minor >= 0 || throw MetadataStatementLoadingException::create('Invalid argument "minor"');
    }
    public static function create(?int $major, ?int $minor): self
    {
        return new self($major, $minor);
    }
    /**
     * @deprecated since 4.7.0. Please use the property directly.
     * @infection-ignore-all
     */
    public function getMajor(): ?int
    {
        return $this->major;
    }
    /**
     * @deprecated since 4.7.0. Please use the property directly.
     * @infection-ignore-all
     */
    public function getMinor(): ?int
    {
        return $this->minor;
    }
    /**
     * @param array<string, mixed> $data
     * @deprecated since 4.7.0. Please use the symfony/serializer for converting the object.
     * @infection-ignore-all
     */
    public static function createFromArray(array $data): self
    {
        $data = self::filterNullValues($data);
        foreach (['major', 'minor'] as $key) {
            if (array_key_exists($key, $data)) {
                is_int($data[$key]) || throw MetadataStatementLoadingException::create(sprintf('Invalid value for key "%s"', $key));
            }
        }
        return self::create($data['major'] ?? null, $data['minor'] ?? null);
    }
    /**
     * @return array<string, int|null>
     */
    public function jsonSerialize(): array
    {
        trigger_deprecation('web-auth/webauthn-bundle', '4.9.0', 'The "%s" method is deprecated and will be removed in 5.0. Please use the serializer instead.', __METHOD__);
        $data = ['major' => $this->major, 'minor' => $this->minor];
        return self::filterNullValues($data);
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\Webauthn\MetadataService\Statement;

use JsonSerializable;
use _ContaoManager\Webauthn\Exception\MetadataStatementLoadingException;
use function array_key_exists;
use function is_int;
use function sprintf;
class RgbPaletteEntry implements JsonSerializable
{
    public function __construct(public readonly int $r, public readonly int $g, public readonly int $b)
    {
        $r >= 0 && $r <= 255 || throw MetadataStatementLoadingException::create('The key "r" is invalid');
        $g >= 0 && $g <= 255 || throw MetadataStatementLoadingException::create('The key "g" is invalid');
        $b >= 0 && $b <= 255 || throw MetadataStatementLoadingException::create('The key "b" is invalid');
    }
    public static function create(int $r, int $g, int $b): self
    {
        return new self($r, $g, $b);
    }
    /**
     * @deprecated since 4.7.0. Please use the property directly.
     * @infection-ignore-all
     */
    public function getR(): int
    {
        return $this->r;
    }
    /**
     * @deprecated since 4.7.0. Please use the property directly.
     * @infection-ignore-all
     */
    public function getG(): int
    {
        return $this->g;
    }
    /**
     * @deprecated since 4.7.0. Please use the property directly.
     * @infection-ignore-all
     */
    public function getB(): int
    {
        return $this->b;
    }
    /**
     * @param array<string, mixed> $data
     * @deprecated since 4.7.0. Please use the symfony/serializer for converting the object.
     * @infection-ignore-all
     */
    public static function createFromArray(array $data): self
    {
        foreach (['r', 'g', 'b'] as $key) {
            array_key_exists($key, $data) || throw MetadataStatementLoadingException::create(sprintf('The key "%s" is missing', $key));
            is_int($data[$key]) || throw MetadataStatementLoadingException::create(sprintf('The key "%s" is invalid', $key));
        }
        return self::create($data['r'], $data['g'], $data['b']);
    }
    /**
     * @return array<string, int>
     */
    public function jsonSerialize(): array
    {
        trigger_deprecation('web-auth/webauthn-bundle', '4.9.0', 'The "%s" method is deprecated and will be removed in 5.0. Please use the serializer instead.', __METHOD__);
        return ['r' => $this->r, 'g' => $this->g, 'b' => $this->b];
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\Webauthn\MetadataService\Statement;

use JsonSerializable;
use _ContaoManager\Webauthn\Exception\MetadataStatementLoadingException;
use function array_key_exists;
use function is_string;
class RogueListEntry implements JsonSerializable
{
    public function __construct(public readonly string $sk, public readonly string $date)
    {
    }
    public static function create(string $sk, string $date): self
    {
        return new self($sk, $date);
    }
    /**
     * @deprecated since 4.7.0. Please use the property directly.
     * @infection-ignore-all
     */
    public function getSk(): string
    {
        return $this->sk;
    }
    /**
     * @deprecated since 4.7.0. Please use the property directly.
     * @infection-ignore-all
     */
    public function getDate(): ?string
    {
        return $this->date;
    }
    /**
     * @param array<string, mixed> $data
     * @deprecated since 4.7.0. Please use the symfony/serializer for converting the object.
     * @infection-ignore-all
     */
    public static function createFromArray(array $data): self
    {
        array_key_exists('sk', $data) || throw MetadataStatementLoadingException::create('The key "sk" is missing');
        is_string($data['sk']) || throw MetadataStatementLoadingException::create('The key "date" is invalid');
        array_key_exists('date', $data) || throw MetadataStatementLoadingException::create('The key "date" is missing');
        is_string($data['date']) || throw MetadataStatementLoadingException::create('The key "date" is invalid');
        return self::create($data['sk'], $data['date']);
    }
    /**
     * @return array<string, mixed>
     */
    public function jsonSerialize(): array
    {
        trigger_deprecation('web-auth/webauthn-bundle', '4.9.0', 'The "%s" method is deprecated and will be removed in 5.0. Please use the serializer instead.', __METHOD__);
        return ['sk' => $this->sk, 'date' => $this->date];
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\Webauthn\MetadataService\Statement;

use JsonSerializable;
use _ContaoManager\Webauthn\Exception\MetadataStatementLoadingException;
use _ContaoManager\Webauthn\MetadataService\ValueFilter;
use function array_key_exists;
use function sprintf;
class DisplayPNGCharacteristicsDescriptor implements JsonSerializable
{
    use ValueFilter;
    /**
     * @param RgbPaletteEntry[] $plte
     */
    public function __construct(
        public readonly int $width,
        public readonly int $height,
        public readonly int $bitDepth,
        public readonly int $colorType,
        public readonly int $compression,
        public readonly int $filter,
        public readonly int $interlace,
        /** @readonly */
        public array $plte = []
    )
    {
        $width >= 0 || throw MetadataStatementLoadingException::create('Invalid width');
        $height >= 0 || throw MetadataStatementLoadingException::create('Invalid height');
        $bitDepth >= 0 && $bitDepth <= 254 || throw MetadataStatementLoadingException::create('Invalid bit depth');
        $colorType >= 0 && $colorType <= 254 || throw MetadataStatementLoadingException::create('Invalid color type');
        $compression >= 0 && $compression <= 254 || throw MetadataStatementLoadingException::create('Invalid compression');
        $filter >= 0 && $filter <= 254 || throw MetadataStatementLoadingException::create('Invalid filter');
        $interlace >= 0 && $interlace <= 254 || throw MetadataStatementLoadingException::create('Invalid interlace');
    }
    /**
     * @param RgbPaletteEntry[] $plte
     */
    public static function create(int $width, int $height, int $bitDepth, int $colorType, int $compression, int $filter, int $interlace, array $plte = []): self
    {
        return new self($width, $height, $bitDepth, $colorType, $compression, $filter, $interlace, $plte);
    }
    /**
     * @deprecated since 4.7.0. Please use {self::create} directly.
     * @infection-ignore-all
     */
    public function addPalettes(RgbPaletteEntry ...$rgbPaletteEntries): self
    {
        foreach ($rgbPaletteEntries as $rgbPaletteEntry) {
            $this->plte[] = $rgbPaletteEntry;
        }
        return $this;
    }
    /**
     * @deprecated since 4.7.0. Please use the property directly.
     * @infection-ignore-all
     */
    public function getWidth(): int
    {
        return $this->width;
    }
    /**
     * @deprecated since 4.7.0. Please use the property directly.
     * @infection-ignore-all
     */
    public function getHeight(): int
    {
        return $this->height;
    }
    /**
     * @deprecated since 4.7.0. Please use the property directly.
     * @infection-ignore-all
     */
    public function getBitDepth(): int
    {
        return $this->bitDepth;
    }
    /**
     * @deprecated since 4.7.0. Please use the property directly.
     * @infection-ignore-all
     */
    public function getColorType(): int
    {
        return $this->colorType;
    }
    /**
     * @deprecated since 4.7.0. Please use the property directly.
     * @infection-ignore-all
     */
    public function getCompression(): int
    {
        return $this->compression;
    }
    /**
     * @deprecated since 4.7.0. Please use the property directly.
     * @infection-ignore-all
     */
    public function getFilter(): int
    {
        return $this->filter;
    }
    /**
     * @deprecated since 4.7.0. Please use the property directly.
     * @infection-ignore-all
     */
    public function getInterlace(): int
    {
        return $this->interlace;
    }
    /**
     * @return RgbPaletteEntry[]
     * @deprecated since 4.7.0. Please use the property directly.
     * @infection-ignore-all
     */
    public function getPaletteEntries(): array
    {
        return $this->plte;
    }
    /**
     * @param array<string, mixed> $data
     * @deprecated since 4.7.0. Please use the symfony/serializer for converting the object.
     * @infection-ignore-all
     */
    public static function createFromArray(array $data): self
    {
        $data = self::filterNullValues($data);
        foreach (['width', 'compression', 'height', 'bitDepth', 'colorType', 'compression', 'filter', 'interlace'] as $key) {
            array_key_exists($key, $data) || throw MetadataStatementLoadingException::create(sprintf('Invalid data. The key "%s" is missing', $key));
        }
        return self::create($data['width'], $data['height'], $data['bitDepth'], $data['colorType'], $data['compression'], $data['filter'], $data['interlace'], array_map(static fn(array $item) => RgbPaletteEntry::createFromArray($item), $data['plte'] ?? []));
    }
    /**
     * @return array<string, mixed>
     */
    public function jsonSerialize(): array
    {
        trigger_deprecation('web-auth/webauthn-bundle', '4.9.0', 'The "%s" method is deprecated and will be removed in 5.0. Please use the serializer instead.', __METHOD__);
        $data = ['width' => $this->width, 'height' => $this->height, 'bitDepth' => $this->bitDepth, 'colorType' => $this->colorType, 'compression' => $this->compression, 'filter' => $this->filter, 'interlace' => $this->interlace, 'plte' => $this->plte];
        return self::filterNullValues($data);
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\Webauthn\MetadataService;

/**
 * @internal
 */
trait ValueFilter
{
    /**
     * @param array<mixed> $data
     *
     * @return array<mixed>
     */
    private static function filterNullValues(array $data): array
    {
        return array_filter($data, static fn($var): bool => $var !== null);
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\Webauthn\MetadataService\Denormalizer;

use _ContaoManager\Webauthn\Denormalizer\ExtensionDescriptorDenormalizer as BaseExtensionDescriptorDenormalizer;
/**
 * @deprecated since 4.9.0 and will be removed in 5.0.0. Use Webauthn\Denormalizer\ExtensionDescriptorDenormalizer instead
 */
final class ExtensionDescriptorDenormalizer extends BaseExtensionDescriptorDenormalizer
{
}
<?php

declare (strict_types=1);
namespace _ContaoManager\Webauthn\MetadataService\Denormalizer;

use _ContaoManager\Symfony\Component\Serializer\SerializerInterface;
use _ContaoManager\Webauthn\AttestationStatement\AttestationStatementSupportManager;
use _ContaoManager\Webauthn\Denormalizer\WebauthnSerializerFactory;
/**
 * @deprecated since 4.9.0 and will be removed in 5.0.0. Use Webauthn\Denormalizer\WebauthnSerializerFactory instead
 */
final class MetadataStatementSerializerFactory
{
    public static function create(): SerializerInterface
    {
        $attestationStatementSupportManager = AttestationStatementSupportManager::create();
        $factory = new WebauthnSerializerFactory($attestationStatementSupportManager);
        return $factory->create();
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\Webauthn\MetadataService\Service;

use _ContaoManager\Jose\Component\Core\AlgorithmManager;
use _ContaoManager\Jose\Component\KeyManagement\JWKFactory;
use _ContaoManager\Jose\Component\Signature\Algorithm\ES256;
use _ContaoManager\Jose\Component\Signature\Algorithm\RS256;
use _ContaoManager\Jose\Component\Signature\JWSVerifier;
use _ContaoManager\Jose\Component\Signature\Serializer\CompactSerializer;
use _ContaoManager\Psr\EventDispatcher\EventDispatcherInterface;
use _ContaoManager\Psr\Http\Client\ClientInterface;
use _ContaoManager\Psr\Http\Message\RequestFactoryInterface;
use _ContaoManager\Symfony\Component\Serializer\SerializerInterface;
use _ContaoManager\Symfony\Contracts\HttpClient\HttpClientInterface;
use Throwable;
use _ContaoManager\Webauthn\AttestationStatement\AttestationStatementSupportManager;
use _ContaoManager\Webauthn\Denormalizer\WebauthnSerializerFactory;
use _ContaoManager\Webauthn\Event\CanDispatchEvents;
use _ContaoManager\Webauthn\Event\MetadataStatementFound;
use _ContaoManager\Webauthn\Event\NullEventDispatcher;
use _ContaoManager\Webauthn\Exception\MetadataStatementLoadingException;
use _ContaoManager\Webauthn\Exception\MissingMetadataStatementException;
use _ContaoManager\Webauthn\MetadataService\CertificateChain\CertificateChainValidator;
use _ContaoManager\Webauthn\MetadataService\CertificateChain\CertificateToolbox;
use _ContaoManager\Webauthn\MetadataService\Statement\MetadataStatement;
use _ContaoManager\Webauthn\MetadataService\Statement\StatusReport;
use function array_key_exists;
use function is_array;
use function sprintf;
use const JSON_THROW_ON_ERROR;
final class FidoAllianceCompliantMetadataService implements MetadataService, CanDispatchEvents
{
    private bool $loaded = \false;
    /**
     * @var MetadataStatement[]
     */
    private array $statements = [];
    /**
     * @var array<string, array<int, StatusReport>>
     */
    private array $statusReports = [];
    private EventDispatcherInterface $dispatcher;
    private readonly ?SerializerInterface $serializer;
    /**
     * @param array<string, mixed> $additionalHeaderParameters
     */
    public function __construct(private readonly ?RequestFactoryInterface $requestFactory, private readonly ClientInterface|HttpClientInterface $httpClient, private readonly string $uri, private readonly array $additionalHeaderParameters = [], private readonly ?CertificateChainValidator $certificateChainValidator = null, private readonly ?string $rootCertificateUri = null, ?SerializerInterface $serializer = null)
    {
        if ($requestFactory !== null && !$httpClient instanceof HttpClientInterface) {
            trigger_deprecation('web-auth/metadata-service', '4.7.0', 'The parameter "$requestFactory" will be removed in 5.0.0. Please set it to null and set an Symfony\Contracts\HttpClient\HttpClientInterface as "$httpClient" argument.');
        }
        $this->serializer = $serializer ?? (new WebauthnSerializerFactory(AttestationStatementSupportManager::create()))->create();
        $this->dispatcher = new NullEventDispatcher();
    }
    public function setEventDispatcher(EventDispatcherInterface $eventDispatcher): void
    {
        $this->dispatcher = $eventDispatcher;
    }
    /**
     * @param array<string, mixed> $additionalHeaderParameters
     */
    public static function create(?RequestFactoryInterface $requestFactory, ClientInterface|HttpClientInterface $httpClient, string $uri, array $additionalHeaderParameters = [], ?CertificateChainValidator $certificateChainValidator = null, ?string $rootCertificateUri = null, ?SerializerInterface $serializer = null): self
    {
        return new self($requestFactory, $httpClient, $uri, $additionalHeaderParameters, $certificateChainValidator, $rootCertificateUri, $serializer);
    }
    /**
     * @return string[]
     */
    public function list(): iterable
    {
        $this->loadData();
        yield from array_keys($this->statements);
    }
    public function has(string $aaguid): bool
    {
        $this->loadData();
        return array_key_exists($aaguid, $this->statements);
    }
    public function get(string $aaguid): MetadataStatement
    {
        $this->loadData();
        array_key_exists($aaguid, $this->statements) || throw MissingMetadataStatementException::create($aaguid);
        $mds = $this->statements[$aaguid];
        $this->dispatcher->dispatch(MetadataStatementFound::create($mds));
        return $mds;
    }
    /**
     * @return StatusReport[]
     */
    public function getStatusReports(string $aaguid): iterable
    {
        $this->loadData();
        return $this->statusReports[$aaguid] ?? [];
    }
    private function loadData(): void
    {
        if ($this->loaded) {
            return;
        }
        $content = $this->fetch($this->uri, $this->additionalHeaderParameters);
        $jwtCertificates = [];
        try {
            $payload = $this->getJwsPayload($content, $jwtCertificates);
            $this->validateCertificates(...$jwtCertificates);
            if ($this->serializer !== null) {
                $blob = $this->serializer->deserialize($payload, MetadataBLOBPayload::class, 'json');
                foreach ($blob->entries as $entry) {
                    $mds = $entry->metadataStatement;
                    if ($mds !== null && $entry->aaguid !== null) {
                        $this->statements[$entry->aaguid] = $mds;
                        $this->statusReports[$entry->aaguid] = $entry->statusReports;
                    }
                }
                $this->loaded = \true;
                return;
            }
            $data = json_decode($payload, \true, flags: JSON_THROW_ON_ERROR);
            foreach ($data['entries'] as $datum) {
                $entry = MetadataBLOBPayloadEntry::createFromArray($datum);
                $mds = $entry->metadataStatement;
                if ($mds !== null && $entry->aaguid !== null) {
                    $this->statements[$entry->aaguid] = $mds;
                    $this->statusReports[$entry->aaguid] = $entry->statusReports;
                }
            }
        } catch (Throwable) {
            // Nothing to do
        }
        $this->loaded = \true;
    }
    /**
     * @param array<string, mixed> $headerParameters
     */
    private function fetch(string $uri, array $headerParameters): string
    {
        if ($this->httpClient instanceof HttpClientInterface) {
            $content = $this->sendSymfonyRequest($uri, $headerParameters);
        } else {
            $content = $this->sendPsrRequest($uri, $headerParameters);
        }
        $content !== '' || throw MetadataStatementLoadingException::create('Unable to contact the server. The response has no content');
        return $content;
    }
    /**
     * @param string[] $rootCertificates
     */
    private function getJwsPayload(string $token, array &$rootCertificates): string
    {
        $jws = (new CompactSerializer())->unserialize($token);
        $jws->countSignatures() === 1 || throw MetadataStatementLoadingException::create('Invalid response from the metadata service. Only one signature shall be present.');
        $signature = $jws->getSignature(0);
        $payload = $jws->getPayload();
        $payload !== '' || throw MetadataStatementLoadingException::create('Invalid response from the metadata service. The token payload is empty.');
        $header = $signature->getProtectedHeader();
        array_key_exists('alg', $header) || throw MetadataStatementLoadingException::create('The "alg" parameter is missing.');
        array_key_exists('x5c', $header) || throw MetadataStatementLoadingException::create('The "x5c" parameter is missing.');
        is_array($header['x5c']) || throw MetadataStatementLoadingException::create('The "x5c" parameter should be an array.');
        $key = JWKFactory::createFromX5C($header['x5c']);
        $rootCertificates = $header['x5c'];
        $verifier = new JWSVerifier(new AlgorithmManager([new ES256(), new RS256()]));
        $isValid = $verifier->verifyWithKey($jws, $key, 0);
        $isValid || throw MetadataStatementLoadingException::create('Invalid response from the metadata service. The token signature is invalid.');
        $payload = $jws->getPayload();
        $payload !== null || throw MetadataStatementLoadingException::create('Invalid response from the metadata service. The payload is missing.');
        return $payload;
    }
    private function validateCertificates(string ...$untrustedCertificates): void
    {
        if ($this->certificateChainValidator === null || $this->rootCertificateUri === null) {
            return;
        }
        $untrustedCertificates = CertificateToolbox::fixPEMStructures($untrustedCertificates);
        $rootCertificate = CertificateToolbox::convertDERToPEM($this->fetch($this->rootCertificateUri, []));
        $this->certificateChainValidator->check($untrustedCertificates, [$rootCertificate]);
    }
    /**
     * @param array<string, string> $headerParameters
     */
    private function sendPsrRequest(string $uri, array $headerParameters): string
    {
        $request = $this->requestFactory->createRequest('GET', $uri);
        foreach ($headerParameters as $k => $v) {
            $request = $request->withHeader($k, $v);
        }
        $response = $this->httpClient->sendRequest($request);
        $response->getStatusCode() === 200 || throw MetadataStatementLoadingException::create(sprintf('Unable to contact the server. Response code is %d', $response->getStatusCode()));
        $response->getBody()->rewind();
        return $response->getBody()->getContents();
    }
    /**
     * @param array<string, string> $headerParameters
     */
    private function sendSymfonyRequest(string $uri, array $headerParameters): string
    {
        $response = $this->httpClient->request('GET', $uri, ['headers' => $headerParameters]);
        $response->getStatusCode() === 200 || throw MetadataStatementLoadingException::create(sprintf('Unable to contact the server. Response code is %d', $response->getStatusCode()));
        return $response->getContent();
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\Webauthn\MetadataService\Service;

use _ContaoManager\Psr\EventDispatcher\EventDispatcherInterface;
use _ContaoManager\Symfony\Component\Serializer\SerializerInterface;
use _ContaoManager\Webauthn\AttestationStatement\AttestationStatementSupportManager;
use _ContaoManager\Webauthn\Denormalizer\WebauthnSerializerFactory;
use _ContaoManager\Webauthn\Event\CanDispatchEvents;
use _ContaoManager\Webauthn\Event\MetadataStatementFound;
use _ContaoManager\Webauthn\Event\NullEventDispatcher;
use _ContaoManager\Webauthn\Exception\MissingMetadataStatementException;
use _ContaoManager\Webauthn\MetadataService\Statement\MetadataStatement;
use function array_key_exists;
final class JsonMetadataService implements MetadataService, CanDispatchEvents
{
    /**
     * @var MetadataStatement[]
     */
    private array $statements = [];
    private EventDispatcherInterface $dispatcher;
    private readonly ?SerializerInterface $serializer;
    /**
     * @param string[] $statements
     */
    public function __construct(array $statements, ?SerializerInterface $serializer = null)
    {
        $this->dispatcher = new NullEventDispatcher();
        $this->serializer = $serializer ?? (new WebauthnSerializerFactory(AttestationStatementSupportManager::create()))->create();
        foreach ($statements as $statement) {
            $this->addStatement($statement);
        }
    }
    public function setEventDispatcher(EventDispatcherInterface $eventDispatcher): void
    {
        $this->dispatcher = $eventDispatcher;
    }
    public function list(): iterable
    {
        yield from array_keys($this->statements);
    }
    public function has(string $aaguid): bool
    {
        return array_key_exists($aaguid, $this->statements);
    }
    public function get(string $aaguid): MetadataStatement
    {
        array_key_exists($aaguid, $this->statements) || throw MissingMetadataStatementException::create($aaguid);
        $mds = $this->statements[$aaguid];
        $this->dispatcher->dispatch(MetadataStatementFound::create($mds));
        return $mds;
    }
    private function addStatement(string $statement): void
    {
        if ($this->serializer === null) {
            $mds = MetadataStatement::createFromString($statement);
        } else {
            $mds = $this->serializer->deserialize($statement, MetadataStatement::class, 'json');
        }
        if ($mds->aaguid === null) {
            return;
        }
        $this->statements[$mds->aaguid] = $mds;
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\Webauthn\MetadataService\Service;

use _ContaoManager\Psr\EventDispatcher\EventDispatcherInterface;
use _ContaoManager\Webauthn\Event\CanDispatchEvents;
use _ContaoManager\Webauthn\Event\MetadataStatementFound;
use _ContaoManager\Webauthn\Event\NullEventDispatcher;
use _ContaoManager\Webauthn\Exception\MissingMetadataStatementException;
use _ContaoManager\Webauthn\MetadataService\Statement\MetadataStatement;
use function array_key_exists;
/**
 * @deprecated since 4.8.0 and will be removed in 5.0.0. Please use Webauthn\MetadataService\Service\JsonMetadataService instead.
 * @infection-ignore-all
 */
final class StringMetadataService implements MetadataService, CanDispatchEvents
{
    /**
     * @var MetadataStatement[]
     */
    private array $statements = [];
    private EventDispatcherInterface $dispatcher;
    public function __construct(string ...$statements)
    {
        foreach ($statements as $statement) {
            $this->addStatements(MetadataStatement::createFromString($statement));
        }
        $this->dispatcher = new NullEventDispatcher();
    }
    public function setEventDispatcher(EventDispatcherInterface $eventDispatcher): void
    {
        $this->dispatcher = $eventDispatcher;
    }
    public static function create(string ...$statements): self
    {
        return new self(...$statements);
    }
    public function addStatements(MetadataStatement ...$statements): self
    {
        foreach ($statements as $statement) {
            $aaguid = $statement->aaguid;
            if ($aaguid === null) {
                continue;
            }
            $this->statements[$aaguid] = $statement;
        }
        return $this;
    }
    public function list(): iterable
    {
        yield from array_keys($this->statements);
    }
    public function has(string $aaguid): bool
    {
        return array_key_exists($aaguid, $this->statements);
    }
    public function get(string $aaguid): MetadataStatement
    {
        array_key_exists($aaguid, $this->statements) || throw MissingMetadataStatementException::create($aaguid);
        $mds = $this->statements[$aaguid];
        $this->dispatcher->dispatch(MetadataStatementFound::create($mds));
        return $mds;
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\Webauthn\MetadataService\Service;

use JsonSerializable;
use _ContaoManager\Webauthn\Exception\MetadataStatementLoadingException;
use _ContaoManager\Webauthn\MetadataService\Statement\BiometricStatusReport;
use _ContaoManager\Webauthn\MetadataService\Statement\MetadataStatement;
use _ContaoManager\Webauthn\MetadataService\Statement\StatusReport;
use _ContaoManager\Webauthn\MetadataService\ValueFilter;
use function array_key_exists;
use function count;
use function is_array;
use function is_string;
class MetadataBLOBPayloadEntry implements JsonSerializable
{
    use ValueFilter;
    /**
     * @param StatusReport[] $statusReports
     * @param BiometricStatusReport[] $biometricStatusReports
     * @param string[] $attestationCertificateKeyIdentifiers
     */
    public function __construct(public readonly string $timeOfLastStatusChange, public array $statusReports, public readonly ?string $aaid = null, public readonly ?string $aaguid = null, public array $attestationCertificateKeyIdentifiers = [], public readonly ?MetadataStatement $metadataStatement = null, public readonly ?string $rogueListURL = null, public readonly ?string $rogueListHash = null, public array $biometricStatusReports = [])
    {
        if ($aaid !== null && $aaguid !== null) {
            throw MetadataStatementLoadingException::create('Authenticators cannot support both AAID and AAGUID');
        }
        if ($aaid === null && $aaguid === null && count($attestationCertificateKeyIdentifiers) === 0) {
            throw MetadataStatementLoadingException::create('If neither AAID nor AAGUID are set, the attestation certificate identifier list shall not be empty');
        }
        foreach ($attestationCertificateKeyIdentifiers as $attestationCertificateKeyIdentifier) {
            is_string($attestationCertificateKeyIdentifier) || throw MetadataStatementLoadingException::create('Invalid attestation certificate identifier. Shall be a list of strings');
            preg_match('/^[0-9a-f]+$/', $attestationCertificateKeyIdentifier) === 1 || throw MetadataStatementLoadingException::create('Invalid attestation certificate identifier. Shall be a list of strings');
        }
    }
    /**
     * @deprecated since 4.7.0. Please use the property directly.
     * @infection-ignore-all
     */
    public function getAaid(): ?string
    {
        return $this->aaid;
    }
    /**
     * @deprecated since 4.7.0. Please use the property directly.
     * @infection-ignore-all
     */
    public function getAaguid(): ?string
    {
        return $this->aaguid;
    }
    /**
     * @return string[]
     * @deprecated since 4.7.0. Please use the property directly.
     * @infection-ignore-all
     */
    public function getAttestationCertificateKeyIdentifiers(): array
    {
        return $this->attestationCertificateKeyIdentifiers;
    }
    /**
     * @deprecated since 4.7.0. Please use the property directly.
     * @infection-ignore-all
     */
    public function getMetadataStatement(): ?MetadataStatement
    {
        return $this->metadataStatement;
    }
    /**
     * @deprecated since 4.7.0. Please use the property directly.
     * @infection-ignore-all
     */
    public function addBiometricStatusReports(BiometricStatusReport ...$biometricStatusReports): self
    {
        foreach ($biometricStatusReports as $biometricStatusReport) {
            $this->biometricStatusReports[] = $biometricStatusReport;
        }
        return $this;
    }
    /**
     * @return BiometricStatusReport[]
     * @deprecated since 4.7.0. Please use the property directly.
     * @infection-ignore-all
     */
    public function getBiometricStatusReports(): array
    {
        return $this->biometricStatusReports;
    }
    /**
     * @deprecated since 4.7.0. Please use the property directly.
     * @infection-ignore-all
     */
    public function addStatusReports(StatusReport ...$statusReports): self
    {
        foreach ($statusReports as $statusReport) {
            $this->statusReports[] = $statusReport;
        }
        return $this;
    }
    /**
     * @return StatusReport[]
     * @deprecated since 4.7.0. Please use the property directly.
     * @infection-ignore-all
     */
    public function getStatusReports(): array
    {
        return $this->statusReports;
    }
    /**
     * @deprecated since 4.7.0. Please use the property directly.
     * @infection-ignore-all
     */
    public function getTimeOfLastStatusChange(): string
    {
        return $this->timeOfLastStatusChange;
    }
    /**
     * @deprecated since 4.7.0. Please use the property directly.
     * @infection-ignore-all
     */
    public function getRogueListURL(): string|null
    {
        return $this->rogueListURL;
    }
    /**
     * @deprecated since 4.7.0. Please use the property directly.
     * @infection-ignore-all
     */
    public function getRogueListHash(): string|null
    {
        return $this->rogueListHash;
    }
    /**
     * @param array<string, mixed> $data
     * @deprecated since 4.7.0. Please use the symfony/serializer for converting the object.
     * @infection-ignore-all
     */
    public static function createFromArray(array $data): self
    {
        $data = self::filterNullValues($data);
        array_key_exists('timeOfLastStatusChange', $data) || throw MetadataStatementLoadingException::create('Invalid data. The parameter "timeOfLastStatusChange" is missing');
        array_key_exists('statusReports', $data) || throw MetadataStatementLoadingException::create('Invalid data. The parameter "statusReports" is missing');
        is_array($data['statusReports']) || throw MetadataStatementLoadingException::create('Invalid data. The parameter "statusReports" shall be an array of StatusReport objects');
        return new self($data['timeOfLastStatusChange'], array_map(static fn(array $statusReport) => StatusReport::createFromArray($statusReport), $data['statusReports']), $data['aaid'] ?? null, $data['aaguid'] ?? null, $data['attestationCertificateKeyIdentifiers'] ?? [], isset($data['metadataStatement']) ? MetadataStatement::createFromArray($data['metadataStatement']) : null, $data['rogueListURL'] ?? null, $data['rogueListHash'] ?? null, array_map(static fn(array $biometricStatusReport) => BiometricStatusReport::createFromArray($biometricStatusReport), $data['biometricStatusReports'] ?? []));
    }
    /**
     * @return array<string, mixed>
     */
    public function jsonSerialize(): array
    {
        trigger_deprecation('web-auth/webauthn-bundle', '4.9.0', 'The "%s" method is deprecated and will be removed in 5.0. Please use the serializer instead.', __METHOD__);
        $data = ['aaid' => $this->aaid, 'aaguid' => $this->aaguid, 'attestationCertificateKeyIdentifiers' => $this->attestationCertificateKeyIdentifiers, 'statusReports' => $this->statusReports, 'timeOfLastStatusChange' => $this->timeOfLastStatusChange, 'rogueListURL' => $this->rogueListURL, 'rogueListHash' => $this->rogueListHash];
        return self::filterNullValues($data);
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\Webauthn\MetadataService\Service;

use _ContaoManager\ParagonIE\ConstantTime\Base64;
use _ContaoManager\Psr\EventDispatcher\EventDispatcherInterface;
use _ContaoManager\Psr\Http\Client\ClientInterface;
use _ContaoManager\Psr\Http\Message\RequestFactoryInterface;
use _ContaoManager\Symfony\Component\Serializer\SerializerInterface;
use _ContaoManager\Symfony\Contracts\HttpClient\HttpClientInterface;
use _ContaoManager\Webauthn\AttestationStatement\AttestationStatementSupportManager;
use _ContaoManager\Webauthn\Denormalizer\WebauthnSerializerFactory;
use _ContaoManager\Webauthn\Event\CanDispatchEvents;
use _ContaoManager\Webauthn\Event\MetadataStatementFound;
use _ContaoManager\Webauthn\Event\NullEventDispatcher;
use _ContaoManager\Webauthn\Exception\MetadataStatementLoadingException;
use _ContaoManager\Webauthn\Exception\MissingMetadataStatementException;
use _ContaoManager\Webauthn\MetadataService\Statement\MetadataStatement;
use function sprintf;
final class DistantResourceMetadataService implements MetadataService, CanDispatchEvents
{
    private ?MetadataStatement $statement = null;
    private EventDispatcherInterface $dispatcher;
    private readonly ?SerializerInterface $serializer;
    /**
     * @param array<string, string> $additionalHeaderParameters
     */
    public function __construct(private readonly ?RequestFactoryInterface $requestFactory, private readonly ClientInterface|HttpClientInterface $httpClient, private readonly string $uri, private readonly bool $isBase64Encoded = \false, private readonly array $additionalHeaderParameters = [], ?SerializerInterface $serializer = null)
    {
        if ($requestFactory !== null && !$httpClient instanceof HttpClientInterface) {
            trigger_deprecation('web-auth/metadata-service', '4.7.0', 'The parameter "$requestFactory" will be removed in 5.0.0. Please set it to null and set an Symfony\Contracts\HttpClient\HttpClientInterface as "$httpClient" argument.');
        }
        $this->serializer = $serializer ?? (new WebauthnSerializerFactory(AttestationStatementSupportManager::create()))->create();
        $this->dispatcher = new NullEventDispatcher();
    }
    public function setEventDispatcher(EventDispatcherInterface $eventDispatcher): void
    {
        $this->dispatcher = $eventDispatcher;
    }
    /**
     * @param array<string, mixed> $additionalHeaderParameters
     */
    public static function create(?RequestFactoryInterface $requestFactory, ClientInterface|HttpClientInterface $httpClient, string $uri, bool $isBase64Encoded = \false, array $additionalHeaderParameters = [], ?SerializerInterface $serializer = null): self
    {
        return new self($requestFactory, $httpClient, $uri, $isBase64Encoded, $additionalHeaderParameters, $serializer);
    }
    public function list(): iterable
    {
        $this->loadData();
        $this->statement !== null || throw MetadataStatementLoadingException::create();
        $aaguid = $this->statement->aaguid;
        if ($aaguid === null) {
            yield from [];
        } else {
            yield from [$aaguid];
        }
    }
    public function has(string $aaguid): bool
    {
        $this->loadData();
        $this->statement !== null || throw MetadataStatementLoadingException::create();
        return $aaguid === $this->statement->aaguid;
    }
    public function get(string $aaguid): MetadataStatement
    {
        $this->loadData();
        $this->statement !== null || throw MetadataStatementLoadingException::create();
        if ($aaguid === $this->statement->aaguid) {
            $this->dispatcher->dispatch(MetadataStatementFound::create($this->statement));
            return $this->statement;
        }
        throw MissingMetadataStatementException::create($aaguid);
    }
    private function loadData(): void
    {
        if ($this->statement !== null) {
            return;
        }
        $content = $this->fetch();
        if ($this->isBase64Encoded) {
            $content = Base64::decode($content, \true);
        }
        if ($this->serializer !== null) {
            $this->statement = $this->serializer->deserialize($content, MetadataStatement::class, 'json');
            return;
        }
        $this->statement = MetadataStatement::createFromString($content);
    }
    private function fetch(): string
    {
        if ($this->httpClient instanceof HttpClientInterface) {
            $content = $this->sendSymfonyRequest();
        } else {
            $content = $this->sendPsrRequest();
        }
        $content !== '' || throw MetadataStatementLoadingException::create('Unable to contact the server. The response has no content');
        return $content;
    }
    private function sendPsrRequest(): string
    {
        $request = $this->requestFactory->createRequest('GET', $this->uri);
        foreach ($this->additionalHeaderParameters as $k => $v) {
            $request = $request->withHeader($k, $v);
        }
        $response = $this->httpClient->sendRequest($request);
        $response->getStatusCode() === 200 || throw MetadataStatementLoadingException::create(sprintf('Unable to contact the server. Response code is %d', $response->getStatusCode()));
        $response->getBody()->rewind();
        return $response->getBody()->getContents();
    }
    private function sendSymfonyRequest(): string
    {
        $response = $this->httpClient->request('GET', $this->uri, ['headers' => $this->additionalHeaderParameters]);
        $response->getStatusCode() === 200 || throw MetadataStatementLoadingException::create(sprintf('Unable to contact the server. Response code is %d', $response->getStatusCode()));
        return $response->getContent();
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\Webauthn\MetadataService\Service;

use JsonSerializable;
use _ContaoManager\Webauthn\Exception\MetadataStatementLoadingException;
use _ContaoManager\Webauthn\MetadataService\ValueFilter;
use function array_key_exists;
use function is_array;
use function is_int;
use function is_string;
use function sprintf;
class MetadataBLOBPayload implements JsonSerializable
{
    use ValueFilter;
    /**
     * @var string[]
     */
    private array $rootCertificates = [];
    /**
     * @param MetadataBLOBPayloadEntry[] $entries
     */
    public function __construct(public readonly int $no, public readonly string $nextUpdate, public readonly ?string $legalHeader = null, public array $entries = [])
    {
    }
    /**
     * @deprecated since 4.7.0. Please use the property directly.
     * @infection-ignore-all
     */
    public function addEntry(MetadataBLOBPayloadEntry $entry): self
    {
        $this->entries[] = $entry;
        return $this;
    }
    /**
     * @deprecated since 4.7.0. Please use the property directly.
     * @infection-ignore-all
     */
    public function getLegalHeader(): ?string
    {
        return $this->legalHeader;
    }
    /**
     * @deprecated since 4.7.0. Please use the property directly.
     * @infection-ignore-all
     */
    public function getNo(): int
    {
        return $this->no;
    }
    /**
     * @deprecated since 4.7.0. Please use the property directly.
     * @infection-ignore-all
     */
    public function getNextUpdate(): string
    {
        return $this->nextUpdate;
    }
    /**
     * @return MetadataBLOBPayloadEntry[]
     * @deprecated since 4.7.0. Please use the property directly.
     * @infection-ignore-all
     */
    public function getEntries(): array
    {
        return $this->entries;
    }
    /**
     * @param array<string, mixed> $data
     * @deprecated since 4.7.0. Please use the symfony/serializer for converting the object.
     * @infection-ignore-all
     */
    public static function createFromArray(array $data): self
    {
        $data = self::filterNullValues($data);
        foreach (['no', 'nextUpdate', 'entries'] as $key) {
            array_key_exists($key, $data) || throw MetadataStatementLoadingException::create(sprintf('Invalid data. The parameter "%s" is missing', $key));
        }
        is_int($data['no']) || throw MetadataStatementLoadingException::create('Invalid data. The parameter "no" shall be an integer');
        is_string($data['nextUpdate']) || throw MetadataStatementLoadingException::create('Invalid data. The parameter "nextUpdate" shall be a string');
        is_array($data['entries']) || throw MetadataStatementLoadingException::create('Invalid data. The parameter "entries" shall be a n array of entries');
        $object = new self($data['no'], $data['nextUpdate'], $data['legalHeader'] ?? null);
        foreach ($data['entries'] as $entry) {
            $object->entries[] = MetadataBLOBPayloadEntry::createFromArray($entry);
        }
        return $object;
    }
    /**
     * @return array<string, mixed>
     */
    public function jsonSerialize(): array
    {
        trigger_deprecation('web-auth/webauthn-bundle', '4.9.0', 'The "%s" method is deprecated and will be removed in 5.0. Please use the serializer instead.', __METHOD__);
        trigger_deprecation('web-auth/webauthn-bundle', '4.9.0', 'The "%s" method is deprecated and will be removed in 5.0. Please use the serializer instead.', __METHOD__);
        $data = ['legalHeader' => $this->legalHeader, 'nextUpdate' => $this->nextUpdate, 'no' => $this->no, 'entries' => $this->entries];
        return self::filterNullValues($data);
    }
    /**
     * @return string[]
     * @deprecated since 4.7.0. Please use the property directly.
     * @infection-ignore-all
     */
    public function getRootCertificates(): array
    {
        return $this->rootCertificates;
    }
    /**
     * @param string[] $rootCertificates
     * @deprecated since 4.7.0. Please use the property directly.
     * @infection-ignore-all
     */
    public function setRootCertificates(array $rootCertificates): self
    {
        $this->rootCertificates = $rootCertificates;
        return $this;
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\Webauthn\MetadataService\Service;

use _ContaoManager\Webauthn\MetadataService\Statement\MetadataStatement;
interface MetadataService
{
    /**
     * @return string[] The list of AAGUID supported by the service
     */
    public function list(): iterable;
    public function has(string $aaguid): bool;
    public function get(string $aaguid): MetadataStatement;
}
<?php

declare (strict_types=1);
namespace _ContaoManager\Webauthn\MetadataService\Service;

use _ContaoManager\ParagonIE\ConstantTime\Base64;
use _ContaoManager\Psr\EventDispatcher\EventDispatcherInterface;
use _ContaoManager\Symfony\Component\Serializer\SerializerInterface;
use _ContaoManager\Webauthn\AttestationStatement\AttestationStatementSupportManager;
use _ContaoManager\Webauthn\Denormalizer\WebauthnSerializerFactory;
use _ContaoManager\Webauthn\Event\CanDispatchEvents;
use _ContaoManager\Webauthn\Event\MetadataStatementFound;
use _ContaoManager\Webauthn\Event\NullEventDispatcher;
use _ContaoManager\Webauthn\Exception\MetadataStatementLoadingException;
use _ContaoManager\Webauthn\Exception\MissingMetadataStatementException;
use _ContaoManager\Webauthn\MetadataService\Statement\MetadataStatement;
use function file_get_contents;
final class LocalResourceMetadataService implements MetadataService, CanDispatchEvents
{
    private ?MetadataStatement $statement = null;
    private EventDispatcherInterface $dispatcher;
    private readonly ?SerializerInterface $serializer;
    public function __construct(private readonly string $filename, private readonly bool $isBase64Encoded = \false, ?SerializerInterface $serializer = null)
    {
        $this->serializer = $serializer ?? (new WebauthnSerializerFactory(AttestationStatementSupportManager::create()))->create();
        $this->dispatcher = new NullEventDispatcher();
    }
    public static function create(string $filename, bool $isBase64Encoded = \false, ?SerializerInterface $serializer = null): self
    {
        return new self($filename, $isBase64Encoded, $serializer);
    }
    public function setEventDispatcher(EventDispatcherInterface $eventDispatcher): void
    {
        $this->dispatcher = $eventDispatcher;
    }
    public function list(): iterable
    {
        $this->loadData();
        $this->statement !== null || throw MetadataStatementLoadingException::create();
        $aaguid = $this->statement->aaguid;
        if ($aaguid === null) {
            yield from [];
        } else {
            yield from [$aaguid];
        }
    }
    public function has(string $aaguid): bool
    {
        $this->loadData();
        $this->statement !== null || throw MetadataStatementLoadingException::create();
        return $aaguid === $this->statement->aaguid;
    }
    public function get(string $aaguid): MetadataStatement
    {
        $this->loadData();
        $this->statement !== null || throw MetadataStatementLoadingException::create();
        if ($aaguid === $this->statement->aaguid) {
            $this->dispatcher->dispatch(MetadataStatementFound::create($this->statement));
            return $this->statement;
        }
        throw MissingMetadataStatementException::create($aaguid);
    }
    private function loadData(): void
    {
        if ($this->statement !== null) {
            return;
        }
        $content = file_get_contents($this->filename);
        if ($this->isBase64Encoded) {
            $content = Base64::decode($content, \true);
        }
        if ($this->serializer !== null) {
            $this->statement = $this->serializer->deserialize($content, MetadataStatement::class, 'json');
        } else {
            $this->statement = MetadataStatement::createFromString($content);
        }
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\Webauthn\MetadataService\Service;

use _ContaoManager\Webauthn\Exception\MissingMetadataStatementException;
use _ContaoManager\Webauthn\MetadataService\Statement\MetadataStatement;
final class ChainedMetadataServices implements MetadataService
{
    /**
     * @var MetadataService[]
     */
    private array $services = [];
    public function __construct(MetadataService ...$services)
    {
        foreach ($services as $service) {
            $this->addServices($service);
        }
    }
    public static function create(MetadataService ...$services): self
    {
        return new self(...$services);
    }
    public function addServices(MetadataService ...$services): self
    {
        foreach ($services as $service) {
            $this->services[] = $service;
        }
        return $this;
    }
    public function list(): iterable
    {
        foreach ($this->services as $service) {
            yield from $service->list();
        }
    }
    public function has(string $aaguid): bool
    {
        foreach ($this->services as $service) {
            if ($service->has($aaguid)) {
                return \true;
            }
        }
        return \false;
    }
    public function get(string $aaguid): MetadataStatement
    {
        foreach ($this->services as $service) {
            if ($service->has($aaguid)) {
                return $service->get($aaguid);
            }
        }
        throw MissingMetadataStatementException::create($aaguid);
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\Webauthn\MetadataService\Service;

use InvalidArgumentException;
use _ContaoManager\Symfony\Component\Serializer\SerializerInterface;
use _ContaoManager\Webauthn\AttestationStatement\AttestationStatementSupportManager;
use _ContaoManager\Webauthn\Denormalizer\WebauthnSerializerFactory;
use _ContaoManager\Webauthn\Exception\MetadataStatementLoadingException;
use _ContaoManager\Webauthn\MetadataService\Statement\MetadataStatement;
use function file_get_contents;
use function is_array;
use function sprintf;
use const DIRECTORY_SEPARATOR;
final class FolderResourceMetadataService implements MetadataService
{
    private readonly ?SerializerInterface $serializer;
    public function __construct(private string $rootPath, ?SerializerInterface $serializer = null)
    {
        $this->serializer = $serializer ?? (new WebauthnSerializerFactory(AttestationStatementSupportManager::create()))->create();
        $this->rootPath = rtrim($rootPath, DIRECTORY_SEPARATOR);
        is_dir($this->rootPath) || throw new InvalidArgumentException('The given parameter is not a valid folder.');
        is_readable($this->rootPath) || throw new InvalidArgumentException('The given parameter is not a valid folder.');
    }
    public static function create(string $rootPath, ?SerializerInterface $serializer = null): self
    {
        return new self($rootPath, $serializer);
    }
    public function list(): iterable
    {
        $files = glob($this->rootPath . DIRECTORY_SEPARATOR . '*');
        is_array($files) || throw MetadataStatementLoadingException::create('Unable to read files.');
        foreach ($files as $file) {
            if (is_dir($file) || !is_readable($file)) {
                continue;
            }
            yield basename($file);
        }
    }
    public function has(string $aaguid): bool
    {
        $filename = $this->rootPath . DIRECTORY_SEPARATOR . $aaguid;
        return is_file($filename) && is_readable($filename);
    }
    public function get(string $aaguid): MetadataStatement
    {
        $this->has($aaguid) || throw new InvalidArgumentException(sprintf('The MDS with the AAGUID "%s" does not exist.', $aaguid));
        $filename = $this->rootPath . DIRECTORY_SEPARATOR . $aaguid;
        $data = trim(file_get_contents($filename));
        if ($this->serializer !== null) {
            $mds = $this->serializer->deserialize($data, MetadataStatement::class, 'json');
        } else {
            $mds = MetadataStatement::createFromString($data);
        }
        $mds->aaguid !== null || throw MetadataStatementLoadingException::create('Invalid Metadata Statement.');
        return $mds;
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\Webauthn\MetadataService\Service;

use _ContaoManager\Psr\EventDispatcher\EventDispatcherInterface;
use _ContaoManager\Webauthn\Event\CanDispatchEvents;
use _ContaoManager\Webauthn\Event\MetadataStatementFound;
use _ContaoManager\Webauthn\Event\NullEventDispatcher;
use _ContaoManager\Webauthn\Exception\MissingMetadataStatementException;
use _ContaoManager\Webauthn\MetadataService\Statement\MetadataStatement;
use function array_key_exists;
final class InMemoryMetadataService implements MetadataService, CanDispatchEvents
{
    /**
     * @var MetadataStatement[]
     */
    private array $statements = [];
    private EventDispatcherInterface $dispatcher;
    public function __construct(MetadataStatement ...$statements)
    {
        foreach ($statements as $statement) {
            $this->addStatements($statement);
        }
        $this->dispatcher = new NullEventDispatcher();
    }
    public function setEventDispatcher(EventDispatcherInterface $eventDispatcher): void
    {
        $this->dispatcher = $eventDispatcher;
    }
    public static function create(MetadataStatement ...$statements): self
    {
        return new self(...$statements);
    }
    public function addStatements(MetadataStatement ...$statements): self
    {
        foreach ($statements as $statement) {
            $aaguid = $statement->aaguid;
            if ($aaguid === null) {
                continue;
            }
            $this->statements[$aaguid] = $statement;
        }
        return $this;
    }
    public function list(): iterable
    {
        yield from array_keys($this->statements);
    }
    public function has(string $aaguid): bool
    {
        return array_key_exists($aaguid, $this->statements);
    }
    public function get(string $aaguid): MetadataStatement
    {
        array_key_exists($aaguid, $this->statements) || throw MissingMetadataStatementException::create($aaguid);
        $mds = $this->statements[$aaguid];
        $this->dispatcher->dispatch(MetadataStatementFound::create($mds));
        return $mds;
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\Webauthn\MetadataService\Exception;

use _ContaoManager\Webauthn\Exception\InvalidCertificateException as BaseInvalidCertificateException;
/**
 * @deprecated since 4.9.0 and will be removed in 5.0.0. Use Webauthn\Exception\InvalidCertificateException instead
 */
final class InvalidCertificateException extends BaseInvalidCertificateException
{
}
<?php

declare (strict_types=1);
namespace _ContaoManager\Webauthn\MetadataService\Exception;

use _ContaoManager\Webauthn\Exception\MetadataServiceException as BaseMetadataServiceException;
/**
 * @deprecated since 4.9.0 and will be removed in 5.0.0. Use Webauthn\Exception\MetadataServiceException instead
 */
class MetadataServiceException extends BaseMetadataServiceException
{
}
<?php

declare (strict_types=1);
namespace _ContaoManager\Webauthn\MetadataService\Exception;

use _ContaoManager\Webauthn\Exception\ExpiredCertificateException as BaseExpiredCertificateException;
/**
 * @deprecated since 4.9.0 and will be removed in 5.0.0. Use Webauthn\Exception\ExpiredCertificateException instead
 */
final class ExpiredCertificateException extends BaseExpiredCertificateException
{
}
<?php

declare (strict_types=1);
namespace _ContaoManager\Webauthn\MetadataService\Exception;

use _ContaoManager\Webauthn\Exception\CertificateChainException as BaseCertificateException;
/**
 * @deprecated since 4.9.0 and will be removed in 5.0.0. Use Webauthn\Exception\CertificateException instead
 */
class CertificateException extends BaseCertificateException
{
}
<?php

declare (strict_types=1);
namespace _ContaoManager\Webauthn\MetadataService\Exception;

use _ContaoManager\Webauthn\Exception\MissingMetadataStatementException as BaseMissingMetadataStatementException;
/**
 * @deprecated since 4.9.0 and will be removed in 5.0.0. Use Webauthn\Exception\MissingMetadataStatementException instead
 */
final class MissingMetadataStatementException extends BaseMissingMetadataStatementException
{
}
<?php

declare (strict_types=1);
namespace _ContaoManager\Webauthn\MetadataService\Exception;

use _ContaoManager\Webauthn\Exception\RevokedCertificateException as BaseRevokedCertificateException;
/**
 * @deprecated since 4.9.0 and will be removed in 5.0.0. Use Webauthn\Exception\RevokedCertificateException instead
 */
final class RevokedCertificateException extends BaseRevokedCertificateException
{
}
<?php

declare (strict_types=1);
namespace _ContaoManager\Webauthn\MetadataService\Exception;

use _ContaoManager\Webauthn\Exception\MetadataStatementLoadingException as BaseMetadataStatementLoadingException;
/**
 * @deprecated since 4.9.0 and will be removed in 5.0.0. Use Webauthn\Exception\MetadataStatementLoadingException instead
 */
final class MetadataStatementLoadingException extends BaseMetadataStatementLoadingException
{
}
<?php

declare (strict_types=1);
namespace _ContaoManager\Webauthn\MetadataService\Exception;

use _ContaoManager\Webauthn\Exception\MetadataStatementException as BaseMetadataStatementException;
/**
 * @deprecated since 4.9.0 and will be removed in 5.0.0. Use Webauthn\Exception\MetadataStatementException instead
 */
class MetadataStatementException extends BaseMetadataStatementException
{
}
<?php

declare (strict_types=1);
namespace _ContaoManager\Webauthn\MetadataService\Exception;

use _ContaoManager\Webauthn\Exception\CertificateChainException as BaseCertificateChainException;
/**
 * @deprecated since 4.9.0 and will be removed in 5.0.0. Use Webauthn\Exception\CertificateChainException instead
 */
class CertificateChainException extends BaseCertificateChainException
{
}
<?php

declare (strict_types=1);
namespace _ContaoManager\Webauthn\MetadataService\Exception;

use _ContaoManager\Webauthn\Exception\CertificateRevocationListException as BaseCertificateRevocationListException;
/**
 * @deprecated since 4.9.0 and will be removed in 5.0.0. Use Webauthn\Exception\CertificateRevocationListException instead
 */
final class CertificateRevocationListException extends BaseCertificateRevocationListException
{
}
<?php

declare (strict_types=1);
namespace _ContaoManager\Webauthn\MetadataService\Event;

use _ContaoManager\Webauthn\Event\CanDispatchEvents as BaseCanDispatchEvents;
/**
 * @deprecated since 4.9.0 and will be removed in 5.0.0. Use Webauthn\Event\CanDispatchEvents instead
 */
interface CanDispatchEvents extends BaseCanDispatchEvents
{
}
<?php

declare (strict_types=1);
namespace _ContaoManager\Webauthn\MetadataService\Event;

use _ContaoManager\Webauthn\Event\WebauthnEvent as BaseWebauthnEvent;
/**
 * @deprecated since 4.9.0 and will be removed in 5.0.0. Use Webauthn\Event\WebauthnEvent instead
 */
interface WebauthnEvent extends BaseWebauthnEvent
{
}
<?php

declare (strict_types=1);
namespace _ContaoManager\Webauthn\MetadataService\Event;

use _ContaoManager\Webauthn\Event\BeforeCertificateChainValidation as BaseBeforeCertificateChainValidation;
/**
 * @deprecated since 4.9.0 and will be removed in 5.0.0. Use Webauthn\Event\BeforeCertificateChainValidation instead
 */
final class BeforeCertificateChainValidation extends BaseBeforeCertificateChainValidation
{
}
<?php

declare (strict_types=1);
namespace _ContaoManager\Webauthn\MetadataService\Event;

use _ContaoManager\Webauthn\Event\CertificateChainValidationFailed as BaseCertificateChainValidationFailed;
/**
 * @deprecated since 4.9.0 and will be removed in 5.0.0. Use Webauthn\Event\CertificateChainValidationFailed instead
 */
final class CertificateChainValidationFailed extends BaseCertificateChainValidationFailed
{
}
<?php

declare (strict_types=1);
namespace _ContaoManager\Webauthn\MetadataService\Event;

use _ContaoManager\Webauthn\Event\CertificateChainValidationSucceeded as BaseCertificateChainValidationSucceeded;
/**
 * @deprecated since 4.9.0 and will be removed in 5.0.0. Use Webauthn\Event\CertificateChainValidationSucceeded instead
 */
final class CertificateChainValidationSucceeded extends BaseCertificateChainValidationSucceeded
{
}
<?php

declare (strict_types=1);
namespace _ContaoManager\Webauthn\MetadataService\Event;

use _ContaoManager\Webauthn\Event\MetadataStatementFound as BaseMetadataStatementFound;
/**
 * @deprecated since 4.9.0 and will be removed in 5.0.0. Use Webauthn\Event\MetadataStatementFound instead
 */
final class MetadataStatementFound extends BaseMetadataStatementFound
{
}
<?php

declare (strict_types=1);
namespace _ContaoManager\Webauthn\MetadataService\Event;

use _ContaoManager\Webauthn\Event\NullEventDispatcher as BaseNullEventDispatcher;
/**
 * @deprecated since 4.9.0 and will be removed in 5.0.0. Use Webauthn\Event\NullEventDispatcher instead
 */
final class NullEventDispatcher extends BaseNullEventDispatcher
{
}
<?php

declare (strict_types=1);
namespace _ContaoManager\Webauthn;

use InvalidArgumentException;
use JsonSerializable;
use _ContaoManager\Webauthn\Exception\InvalidDataException;
use function in_array;
use function is_bool;
use function is_string;
use const JSON_THROW_ON_ERROR;
class AuthenticatorSelectionCriteria implements JsonSerializable
{
    final public const AUTHENTICATOR_ATTACHMENT_NO_PREFERENCE = null;
    final public const AUTHENTICATOR_ATTACHMENT_PLATFORM = 'platform';
    final public const AUTHENTICATOR_ATTACHMENT_CROSS_PLATFORM = 'cross-platform';
    final public const AUTHENTICATOR_ATTACHMENTS = [self::AUTHENTICATOR_ATTACHMENT_NO_PREFERENCE, self::AUTHENTICATOR_ATTACHMENT_PLATFORM, self::AUTHENTICATOR_ATTACHMENT_CROSS_PLATFORM];
    final public const USER_VERIFICATION_REQUIREMENT_REQUIRED = 'required';
    final public const USER_VERIFICATION_REQUIREMENT_PREFERRED = 'preferred';
    final public const USER_VERIFICATION_REQUIREMENT_DISCOURAGED = 'discouraged';
    final public const USER_VERIFICATION_REQUIREMENTS = [self::USER_VERIFICATION_REQUIREMENT_REQUIRED, self::USER_VERIFICATION_REQUIREMENT_PREFERRED, self::USER_VERIFICATION_REQUIREMENT_DISCOURAGED];
    final public const RESIDENT_KEY_REQUIREMENT_NO_PREFERENCE = null;
    /**
     * @deprecated Please use AuthenticatorSelectionCriteria::RESIDENT_KEY_REQUIREMENT_NO_PREFERENCE instead
     * @infection-ignore-all
     */
    final public const RESIDENT_KEY_REQUIREMENT_NONE = null;
    final public const RESIDENT_KEY_REQUIREMENT_REQUIRED = 'required';
    final public const RESIDENT_KEY_REQUIREMENT_PREFERRED = 'preferred';
    final public const RESIDENT_KEY_REQUIREMENT_DISCOURAGED = 'discouraged';
    final public const RESIDENT_KEY_REQUIREMENTS = [self::RESIDENT_KEY_REQUIREMENT_NO_PREFERENCE, self::RESIDENT_KEY_REQUIREMENT_REQUIRED, self::RESIDENT_KEY_REQUIREMENT_PREFERRED, self::RESIDENT_KEY_REQUIREMENT_DISCOURAGED];
    public function __construct(
        public null|string $authenticatorAttachment = null,
        public string $userVerification = self::USER_VERIFICATION_REQUIREMENT_PREFERRED,
        public null|string $residentKey = self::RESIDENT_KEY_REQUIREMENT_NO_PREFERENCE,
        /** @deprecated Will be removed in 5.0. Please use residentKey instead**/
        public null|bool $requireResidentKey = null
    )
    {
        in_array($authenticatorAttachment, self::AUTHENTICATOR_ATTACHMENTS, \true) || throw new InvalidArgumentException('Invalid authenticator attachment');
        in_array($userVerification, self::USER_VERIFICATION_REQUIREMENTS, \true) || throw new InvalidArgumentException('Invalid user verification');
        in_array($residentKey, self::RESIDENT_KEY_REQUIREMENTS, \true) || throw new InvalidArgumentException('Invalid resident key');
        if ($requireResidentKey === \true && $residentKey !== null && $residentKey !== self::RESIDENT_KEY_REQUIREMENT_REQUIRED) {
            throw new InvalidArgumentException('Invalid resident key requirement. Resident key is required but requireResidentKey is false');
        }
        if ($this->residentKey === null && $this->requireResidentKey === \true) {
            $this->residentKey = self::RESIDENT_KEY_REQUIREMENT_REQUIRED;
        }
        $this->requireResidentKey = $requireResidentKey ?? ($residentKey === null ? null : $residentKey === self::RESIDENT_KEY_REQUIREMENT_REQUIRED);
    }
    public static function create(?string $authenticatorAttachment = null, string $userVerification = self::USER_VERIFICATION_REQUIREMENT_PREFERRED, null|string $residentKey = self::RESIDENT_KEY_REQUIREMENT_NO_PREFERENCE, null|bool $requireResidentKey = null): self
    {
        return new self($authenticatorAttachment, $userVerification, $residentKey, $requireResidentKey);
    }
    /**
     * @deprecated since 4.7.0. Please use the {self::create} instead.
     * @infection-ignore-all
     */
    public function setAuthenticatorAttachment(?string $authenticatorAttachment): self
    {
        $this->authenticatorAttachment = $authenticatorAttachment;
        return $this;
    }
    /**
     * @deprecated since v4.1. Please use the {self::create} instead.
     * @infection-ignore-all
     */
    public function setRequireResidentKey(bool $requireResidentKey): self
    {
        $this->requireResidentKey = $requireResidentKey;
        if ($requireResidentKey === \true) {
            $this->residentKey = self::RESIDENT_KEY_REQUIREMENT_REQUIRED;
        }
        return $this;
    }
    /**
     * @deprecated since 4.7.0. Please use the {self::create} instead.
     * @infection-ignore-all
     */
    public function setUserVerification(string $userVerification): self
    {
        $this->userVerification = $userVerification;
        return $this;
    }
    /**
     * @deprecated since 4.7.0. Please use the {self::create} instead.
     * @infection-ignore-all
     */
    public function setResidentKey(null|string $residentKey): self
    {
        $this->residentKey = $residentKey;
        $this->requireResidentKey = $residentKey === self::RESIDENT_KEY_REQUIREMENT_REQUIRED;
        return $this;
    }
    /**
     * @deprecated since 4.7.0. Please use the property directly.
     * @infection-ignore-all
     */
    public function getAuthenticatorAttachment(): ?string
    {
        return $this->authenticatorAttachment;
    }
    /**
     * @deprecated Will be removed in 5.0. Please use the property directly.
     * @infection-ignore-all
     */
    public function isRequireResidentKey(): bool
    {
        return $this->requireResidentKey;
    }
    /**
     * @deprecated since 4.7.0. Please use the property directly.
     * @infection-ignore-all
     */
    public function getUserVerification(): string
    {
        return $this->userVerification;
    }
    /**
     * @deprecated since 4.7.0. Please use the property directly.
     * @infection-ignore-all
     */
    public function getResidentKey(): null|string
    {
        return $this->residentKey;
    }
    /**
     * @deprecated since 4.8.0. Please use {Webauthn\Denormalizer\WebauthnSerializerFactory} for converting the object.
     * @infection-ignore-all
     */
    public static function createFromString(string $data): self
    {
        $data = json_decode($data, \true, flags: JSON_THROW_ON_ERROR);
        return self::createFromArray($data);
    }
    /**
     * @param mixed[] $json
     * @deprecated since 4.8.0. Please use {Webauthn\Denormalizer\WebauthnSerializerFactory} for converting the object.
     * @infection-ignore-all
     */
    public static function createFromArray(array $json): self
    {
        $authenticatorAttachment = $json['authenticatorAttachment'] ?? null;
        $requireResidentKey = $json['requireResidentKey'] ?? null;
        $userVerification = $json['userVerification'] ?? self::USER_VERIFICATION_REQUIREMENT_PREFERRED;
        $residentKey = $json['residentKey'] ?? null;
        $authenticatorAttachment === null || is_string($authenticatorAttachment) || throw InvalidDataException::create($json, 'Invalid "authenticatorAttachment" value');
        $requireResidentKey === null || is_bool($requireResidentKey) || throw InvalidDataException::create($json, 'Invalid "requireResidentKey" value');
        is_string($userVerification) || throw InvalidDataException::create($json, 'Invalid "userVerification" value');
        $residentKey === null || is_string($residentKey) || throw InvalidDataException::create($json, 'Invalid "residentKey" value');
        return self::create($authenticatorAttachment ?? null, $userVerification, $residentKey, $requireResidentKey);
    }
    /**
     * @return mixed[]
     */
    public function jsonSerialize(): array
    {
        trigger_deprecation('web-auth/webauthn-bundle', '4.9.0', 'The "%s" method is deprecated and will be removed in 5.0. Please use the serializer instead.', __METHOD__);
        $json = ['requireResidentKey' => $this->requireResidentKey, 'userVerification' => $this->userVerification, 'residentKey' => $this->residentKey, 'authenticatorAttachment' => $this->authenticatorAttachment];
        foreach ($json as $key => $value) {
            if ($value === null) {
                unset($json[$key]);
            }
        }
        return $json;
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\Webauthn\Exception;

use Throwable;
final class AttestationStatementVerificationException extends AttestationStatementException
{
    public static function create(string $message = 'Invalid attestation object', ?Throwable $previous = null): self
    {
        return new self($message, $previous);
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\Webauthn\Exception;

use Throwable;
/**
 * @final
 */
class InvalidCertificateException extends MetadataServiceException
{
    public function __construct(public readonly string $certificate, string $message, ?Throwable $previous = null)
    {
        parent::__construct($message, $previous);
    }
    public static function create(string $certificate, string $message, ?Throwable $previous = null): self
    {
        return new self($certificate, $message, $previous);
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\Webauthn\Exception;

use Throwable;
use _ContaoManager\Webauthn\AttestationStatement\AttestationStatement;
final class InvalidAttestationStatementException extends AttestationStatementException
{
    public function __construct(public readonly AttestationStatement $attestationStatement, string $message, ?Throwable $previous = null)
    {
        parent::__construct($message, $previous);
    }
    public static function create(AttestationStatement $attestationStatement, string $message = 'Invalid attestation statement', ?Throwable $previous = null): self
    {
        return new self($attestationStatement, $message, $previous);
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\Webauthn\Exception;

use Exception;
use Throwable;
class MetadataServiceException extends Exception
{
    public function __construct(string $message, ?Throwable $previous = null)
    {
        parent::__construct($message, 0, $previous);
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\Webauthn\Exception;

use Throwable;
final class AuthenticationExtensionException extends WebauthnException
{
    public static function create(string $message, ?Throwable $previous = null): self
    {
        return new self($message, $previous);
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\Webauthn\Exception;

use Exception;
use Throwable;
class WebauthnException extends Exception
{
    public function __construct(string $message, ?Throwable $previous = null)
    {
        parent::__construct($message, 0, $previous);
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\Webauthn\Exception;

use Throwable;
final class InvalidTrustPathException extends WebauthnException
{
    public static function create(string $message, ?Throwable $previous = null): self
    {
        return new self($message, $previous);
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\Webauthn\Exception;

use Throwable;
class AuthenticatorResponseVerificationException extends WebauthnException
{
    public static function create(string $message, ?Throwable $previous = null): self
    {
        return new self($message, $previous);
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\Webauthn\Exception;

use Throwable;
/**
 * @final
 */
class ExpiredCertificateException extends CertificateException
{
    public static function create(string $certificate, string $message = 'Expired certificate', ?Throwable $previous = null): self
    {
        return new self($certificate, $message, $previous);
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\Webauthn\Exception;

use Throwable;
final class UnsupportedFeatureException extends WebauthnException
{
    public static function create(string $message, ?Throwable $previous = null): self
    {
        return new self($message, $previous);
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\Webauthn\Exception;

use Throwable;
class CertificateException extends MetadataServiceException
{
    public function __construct(public readonly string $certificate, string $message, ?Throwable $previous = null)
    {
        parent::__construct($message, $previous);
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\Webauthn\Exception;

use Throwable;
/**
 * @final
 */
class MissingMetadataStatementException extends MetadataStatementException
{
    public function __construct(public readonly string $aaguid, string $message, ?Throwable $previous = null)
    {
        parent::__construct($message, $previous);
    }
    public static function create(string $aaguid, string $message = 'The Metadata Statement is missing', ?Throwable $previous = null): self
    {
        return new self($aaguid, $message, $previous);
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\Webauthn\Exception;

/**
 * @final
 */
class RevokedCertificateException extends CertificateException
{
}
<?php

declare (strict_types=1);
namespace _ContaoManager\Webauthn\Exception;

class AttestationStatementException extends WebauthnException
{
}
<?php

declare (strict_types=1);
namespace _ContaoManager\Webauthn\Exception;

use Throwable;
/**
 * @final
 */
class MetadataStatementLoadingException extends MetadataStatementException
{
    public static function create(string $message = 'Unable to load the metadata statement', ?Throwable $previous = null): self
    {
        return new self($message, $previous);
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\Webauthn\Exception;

use Throwable;
final class CounterException extends WebauthnException
{
    public function __construct(public int $currentCounter, public int $authenticatorCounter, string $message, ?Throwable $previous = null)
    {
        parent::__construct($message, $previous);
    }
    public static function create(int $currentCounter, int $authenticatorCounter, string $message, ?Throwable $previous = null): self
    {
        return new self($currentCounter, $authenticatorCounter, $message, $previous);
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\Webauthn\Exception;

class MetadataStatementException extends MetadataServiceException
{
}
<?php

declare (strict_types=1);
namespace _ContaoManager\Webauthn\Exception;

use Throwable;
class CertificateChainException extends MetadataServiceException
{
    /**
     * @param array<string> $untrustedCertificates
     * @param array<string> $trustedCertificates
     */
    public function __construct(public readonly array $untrustedCertificates, public readonly array $trustedCertificates, string $message, ?Throwable $previous = null)
    {
        parent::__construct($message, $previous);
    }
    /**
     * @param array<string> $untrustedCertificates
     * @param array<string> $trustedCertificates
     */
    public static function create(array $untrustedCertificates, array $trustedCertificates, string $message = 'Unable to validate the certificate chain.', ?Throwable $previous = null): self
    {
        return new self($untrustedCertificates, $trustedCertificates, $message, $previous);
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\Webauthn\Exception;

use Throwable;
final class AttestationStatementLoadingException extends AttestationStatementException
{
    /**
     * @param array<string, mixed> $attestation
     */
    public function __construct(public readonly array $attestation, string $message, ?Throwable $previous = null)
    {
        parent::__construct($message, $previous);
    }
    /**
     * @param array<string, mixed> $attestation
     */
    public static function create(array $attestation, string $message = 'Invalid attestation object', ?Throwable $previous = null): self
    {
        return new self($attestation, $message, $previous);
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\Webauthn\Exception;

use Throwable;
final class InvalidDataException extends WebauthnException
{
    public function __construct(public readonly mixed $data, string $message, ?Throwable $previous = null)
    {
        parent::__construct($message, $previous);
    }
    public static function create(mixed $data, string $message, ?Throwable $previous = null): self
    {
        return new self($data, $message, $previous);
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\Webauthn\Exception;

use Throwable;
/**
 * @final
 */
class CertificateRevocationListException extends MetadataServiceException
{
    public function __construct(public readonly string $url, string $message, ?Throwable $previous = null)
    {
        parent::__construct($message, $previous);
    }
    public static function create(string $url, string $message = 'Invalid CRL.', ?Throwable $previous = null): self
    {
        return new self($url, $message, $previous);
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\Webauthn\Exception;

use Throwable;
final class InvalidUserHandleException extends AuthenticatorResponseVerificationException
{
    public static function create(string $message = 'Invalid user handle', ?Throwable $previous = null): self
    {
        return new self($message, $previous);
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\Webauthn;

use _ContaoManager\CBOR\ByteStringObject;
use _ContaoManager\CBOR\MapItem;
use _ContaoManager\CBOR\MapObject;
use _ContaoManager\CBOR\NegativeIntegerObject;
use _ContaoManager\CBOR\UnsignedIntegerObject;
use _ContaoManager\Cose\Algorithms;
use _ContaoManager\Cose\Key\Ec2Key;
/**
 * @internal
 */
final class U2FPublicKey
{
    private const U2F_KEY_PREFIX = "\x04";
    private const U2F_KEY_LENGTH = 65;
    private const U2F_KEY_PART_SIZE = 32;
    public static function isU2FKey(string $publicKey): bool
    {
        return $publicKey[0] === self::U2F_KEY_PREFIX && mb_strlen($publicKey, '8bit') === self::U2F_KEY_LENGTH;
    }
    public static function convertToCoseKey(string $publicKey): string
    {
        return MapObject::create([MapItem::create(UnsignedIntegerObject::create(Ec2Key::TYPE), UnsignedIntegerObject::create(Ec2Key::TYPE_EC2)), MapItem::create(UnsignedIntegerObject::create(Ec2Key::ALG), NegativeIntegerObject::create(Algorithms::COSE_ALGORITHM_ES256)), MapItem::create(NegativeIntegerObject::create(Ec2Key::DATA_CURVE), UnsignedIntegerObject::create(Ec2Key::CURVE_P256)), MapItem::create(NegativeIntegerObject::create(Ec2Key::DATA_X), ByteStringObject::create(mb_substr($publicKey, 1, self::U2F_KEY_PART_SIZE, '8bit'))), MapItem::create(NegativeIntegerObject::create(Ec2Key::DATA_Y), ByteStringObject::create(mb_substr($publicKey, 1 + self::U2F_KEY_PART_SIZE, null, '8bit')))])->__toString();
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\Webauthn\Event;

use _ContaoManager\Psr\EventDispatcher\EventDispatcherInterface;
interface CanDispatchEvents
{
    public function setEventDispatcher(EventDispatcherInterface $eventDispatcher): void;
}
<?php

declare (strict_types=1);
namespace _ContaoManager\Webauthn\Event;

use _ContaoManager\Psr\Http\Message\ServerRequestInterface;
use _ContaoManager\Webauthn\AuthenticatorAttestationResponse;
use _ContaoManager\Webauthn\PublicKeyCredentialCreationOptions;
use _ContaoManager\Webauthn\PublicKeyCredentialSource;
use function sprintf;
class AuthenticatorAttestationResponseValidationSucceededEvent
{
    public function __construct(public readonly AuthenticatorAttestationResponse $authenticatorAttestationResponse, public readonly PublicKeyCredentialCreationOptions $publicKeyCredentialCreationOptions, public readonly ServerRequestInterface|string $host, public readonly PublicKeyCredentialSource $publicKeyCredentialSource)
    {
        if ($host instanceof ServerRequestInterface) {
            trigger_deprecation('web-auth/webauthn-lib', '4.5.0', sprintf('Passing a %s to the class "%s" is deprecated since 4.5.0 and will be removed in 5.0.0. Please inject the host as a string instead.', ServerRequestInterface::class, self::class));
        }
    }
    /**
     * @deprecated since 4.8.0. Will be removed in 5.0.0. Please use the property instead.
     */
    public function getAuthenticatorAttestationResponse(): AuthenticatorAttestationResponse
    {
        return $this->authenticatorAttestationResponse;
    }
    /**
     * @deprecated since 4.8.0. Will be removed in 5.0.0. Please use the property instead.
     */
    public function getPublicKeyCredentialCreationOptions(): PublicKeyCredentialCreationOptions
    {
        return $this->publicKeyCredentialCreationOptions;
    }
    /**
     * @deprecated since 4.5.0 and will be removed in 5.0.0. Please use the `host` property instead
     * @infection-ignore-all
     */
    public function getRequest(): ServerRequestInterface|string
    {
        return $this->host;
    }
    /**
     * @deprecated since 4.8.0. Will be removed in 5.0.0. Please use the property instead.
     */
    public function getPublicKeyCredentialSource(): PublicKeyCredentialSource
    {
        return $this->publicKeyCredentialSource;
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\Webauthn\Event;

interface WebauthnEvent
{
}
<?php

declare (strict_types=1);
namespace _ContaoManager\Webauthn\Event;

use _ContaoManager\Webauthn\AttestationStatement\AttestationObject;
class AttestationObjectLoaded implements WebauthnEvent
{
    public function __construct(public readonly AttestationObject $attestationObject)
    {
    }
    public static function create(AttestationObject $attestationObject): self
    {
        return new self($attestationObject);
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\Webauthn\Event;

use _ContaoManager\Psr\Http\Message\ServerRequestInterface;
use _ContaoManager\Webauthn\AuthenticatorAssertionResponse;
use _ContaoManager\Webauthn\PublicKeyCredentialRequestOptions;
use _ContaoManager\Webauthn\PublicKeyCredentialSource;
use function sprintf;
class AuthenticatorAssertionResponseValidationSucceededEvent
{
    public function __construct(public readonly null|string $credentialId, public readonly AuthenticatorAssertionResponse $authenticatorAssertionResponse, public readonly PublicKeyCredentialRequestOptions $publicKeyCredentialRequestOptions, public readonly ServerRequestInterface|string $host, public readonly ?string $userHandle, public readonly PublicKeyCredentialSource $publicKeyCredentialSource)
    {
        if ($host instanceof ServerRequestInterface) {
            trigger_deprecation('web-auth/webauthn-lib', '4.5.0', sprintf('Passing a %s to the class "%s" is deprecated since 4.5.0 and will be removed in 5.0.0. Please inject the host as a string instead.', ServerRequestInterface::class, self::class));
        }
        if ($this->credentialId !== null) {
            trigger_deprecation('web-auth/webauthn-lib', '4.6.0', 'The argument "$credentialId" is deprecated since 4.6.0 and will be removed in 5.0.0. Please set null instead.');
        }
    }
    /**
     * @deprecated since 4.8.0. Will be removed in 5.0.0. Please use the property instead.
     */
    public function getCredentialId(): string
    {
        return $this->publicKeyCredentialSource->publicKeyCredentialId;
    }
    /**
     * @deprecated since 4.8.0. Will be removed in 5.0.0. Please use the property instead.
     */
    public function getAuthenticatorAssertionResponse(): AuthenticatorAssertionResponse
    {
        return $this->authenticatorAssertionResponse;
    }
    /**
     * @deprecated since 4.8.0. Will be removed in 5.0.0. Please use the property instead.
     */
    public function getPublicKeyCredentialRequestOptions(): PublicKeyCredentialRequestOptions
    {
        return $this->publicKeyCredentialRequestOptions;
    }
    /**
     * @deprecated since 4.5.0 and will be removed in 5.0.0. Please use the `host` property instead
     * @infection-ignore-all
     */
    public function getRequest(): ServerRequestInterface|string
    {
        return $this->host;
    }
    /**
     * @deprecated since 4.8.0. Will be removed in 5.0.0. Please use the property instead.
     */
    public function getUserHandle(): ?string
    {
        return $this->userHandle;
    }
    /**
     * @deprecated since 4.8.0. Will be removed in 5.0.0. Please use the property instead.
     */
    public function getPublicKeyCredentialSource(): PublicKeyCredentialSource
    {
        return $this->publicKeyCredentialSource;
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\Webauthn\Event;

use _ContaoManager\Psr\Http\Message\ServerRequestInterface;
use Throwable;
use _ContaoManager\Webauthn\AuthenticatorAssertionResponse;
use _ContaoManager\Webauthn\PublicKeyCredentialRequestOptions;
use _ContaoManager\Webauthn\PublicKeyCredentialSource;
use function sprintf;
class AuthenticatorAssertionResponseValidationFailedEvent
{
    public function __construct(public readonly string|PublicKeyCredentialSource $credentialId, public readonly AuthenticatorAssertionResponse $authenticatorAssertionResponse, public readonly PublicKeyCredentialRequestOptions $publicKeyCredentialRequestOptions, public readonly ServerRequestInterface|string $host, public readonly ?string $userHandle, public readonly Throwable $throwable)
    {
        if ($host instanceof ServerRequestInterface) {
            trigger_deprecation('web-auth/webauthn-lib', '4.5.0', sprintf('Passing a %s to the class "%s" is deprecated since 4.5.0 and will be removed in 5.0.0. Please inject the host as a string instead.', ServerRequestInterface::class, self::class));
        }
        if (!$this->credentialId instanceof PublicKeyCredentialSource) {
            trigger_deprecation('web-auth/webauthn-lib', '4.6.0', 'Passing a string for the argument "$credentialId" is deprecated since 4.6.0. Please set the PublicKeyCredentialSource instead.');
        }
    }
    /**
     * @deprecated since 4.7.0 and will be removed in 5.0.0. Please use the `getCredential()` method instead
     * @infection-ignore-all
     */
    public function getCredentialId(): string
    {
        return $this->credentialId instanceof PublicKeyCredentialSource ? $this->credentialId->publicKeyCredentialId : $this->credentialId;
    }
    public function getCredential(): ?PublicKeyCredentialSource
    {
        return $this->credentialId instanceof PublicKeyCredentialSource ? $this->credentialId : null;
    }
    /**
     * @deprecated since 4.8.0. Will be removed in 5.0.0. Please use the property instead.
     */
    public function getAuthenticatorAssertionResponse(): AuthenticatorAssertionResponse
    {
        return $this->authenticatorAssertionResponse;
    }
    public function getPublicKeyCredentialRequestOptions(): PublicKeyCredentialRequestOptions
    {
        return $this->publicKeyCredentialRequestOptions;
    }
    /**
     * @deprecated since 4.5.0 and will be removed in 5.0.0. Please use the `host` property instead
     * @infection-ignore-all
     */
    public function getRequest(): ServerRequestInterface|string
    {
        return $this->host;
    }
    /**
     * @deprecated since 4.8.0. Will be removed in 5.0.0. Please use the property instead.
     */
    public function getUserHandle(): ?string
    {
        return $this->userHandle;
    }
    /**
     * @deprecated since 4.8.0. Will be removed in 5.0.0. Please use the property instead.
     */
    public function getThrowable(): Throwable
    {
        return $this->throwable;
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\Webauthn\Event;

/**
 * @final
 */
class BeforeCertificateChainValidation implements WebauthnEvent
{
    /**
     * @param string[] $untrustedCertificates
     */
    public function __construct(public readonly array $untrustedCertificates, public readonly string $trustedCertificate)
    {
    }
    /**
     * @param string[] $untrustedCertificates
     */
    public static function create(array $untrustedCertificates, string $trustedCertificate): self
    {
        return new self($untrustedCertificates, $trustedCertificate);
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\Webauthn\Event;

/**
 * @final
 */
class CertificateChainValidationFailed implements WebauthnEvent
{
    /**
     * @param string[] $untrustedCertificates
     */
    public function __construct(public readonly array $untrustedCertificates, public readonly string $trustedCertificate)
    {
    }
    /**
     * @param string[] $untrustedCertificates
     */
    public static function create(array $untrustedCertificates, string $trustedCertificate): self
    {
        return new self($untrustedCertificates, $trustedCertificate);
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\Webauthn\Event;

/**
 * @final
 */
class CertificateChainValidationSucceeded implements WebauthnEvent
{
    /**
     * @param string[] $untrustedCertificates
     */
    public function __construct(public readonly array $untrustedCertificates, public readonly string $trustedCertificate)
    {
    }
    /**
     * @param string[] $untrustedCertificates
     */
    public static function create(array $untrustedCertificates, string $trustedCertificate): self
    {
        return new self($untrustedCertificates, $trustedCertificate);
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\Webauthn\Event;

use _ContaoManager\Webauthn\MetadataService\Statement\MetadataStatement;
/**
 * @final
 */
class MetadataStatementFound implements WebauthnEvent
{
    public function __construct(public readonly MetadataStatement $metadataStatement)
    {
    }
    public static function create(MetadataStatement $metadataStatement): self
    {
        return new self($metadataStatement);
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\Webauthn\Event;

use _ContaoManager\Psr\EventDispatcher\EventDispatcherInterface;
/**
 * @final
 */
class NullEventDispatcher implements EventDispatcherInterface
{
    public function dispatch(object $event): object
    {
        return $event;
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\Webauthn\Event;

use _ContaoManager\Psr\Http\Message\ServerRequestInterface;
use Throwable;
use _ContaoManager\Webauthn\AuthenticatorAttestationResponse;
use _ContaoManager\Webauthn\PublicKeyCredentialCreationOptions;
use function sprintf;
class AuthenticatorAttestationResponseValidationFailedEvent
{
    public function __construct(public readonly AuthenticatorAttestationResponse $authenticatorAttestationResponse, public readonly PublicKeyCredentialCreationOptions $publicKeyCredentialCreationOptions, public readonly ServerRequestInterface|string $host, public readonly Throwable $throwable)
    {
        if ($host instanceof ServerRequestInterface) {
            trigger_deprecation('web-auth/webauthn-lib', '4.5.0', sprintf('Passing a %s to the class "%s" is deprecated since 4.5.0 and will be removed in 5.0.0. Please inject the host as a string instead.', ServerRequestInterface::class, self::class));
        }
    }
    /**
     * @deprecated since 4.8.0. Will be removed in 5.0.0. Please use the property instead.
     */
    public function getAuthenticatorAttestationResponse(): AuthenticatorAttestationResponse
    {
        return $this->authenticatorAttestationResponse;
    }
    /**
     * @deprecated since 4.8.0. Will be removed in 5.0.0. Please use the property instead.
     */
    public function getPublicKeyCredentialCreationOptions(): PublicKeyCredentialCreationOptions
    {
        return $this->publicKeyCredentialCreationOptions;
    }
    /**
     * @deprecated since 4.5.0 and will be removed in 5.0.0. Please use the `host` property instead
     * @infection-ignore-all
     */
    public function getRequest(): ServerRequestInterface|string
    {
        return $this->host;
    }
    /**
     * @deprecated since 4.8.0. Will be removed in 5.0.0. Please use the property instead.
     */
    public function getThrowable(): Throwable
    {
        return $this->throwable;
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\Webauthn\Event;

use _ContaoManager\Webauthn\AttestationStatement\AttestationStatement;
class AttestationStatementLoaded implements WebauthnEvent
{
    public function __construct(public readonly AttestationStatement $attestationStatement)
    {
    }
    public static function create(AttestationStatement $attestationStatement): self
    {
        return new self($attestationStatement);
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\Webauthn;

use JsonSerializable;
use _ContaoManager\ParagonIE\ConstantTime\Base64UrlSafe;
use _ContaoManager\Symfony\Component\Uid\Uuid;
use Throwable;
use _ContaoManager\Webauthn\Exception\InvalidDataException;
use _ContaoManager\Webauthn\TrustPath\TrustPath;
use _ContaoManager\Webauthn\TrustPath\TrustPathLoader;
use function array_key_exists;
use function in_array;
use function sprintf;
/**
 * @see https://www.w3.org/TR/webauthn/#iface-pkcredential
 */
class PublicKeyCredentialSource implements JsonSerializable
{
    /**
     * @private
     * @param string[] $transports
     * @param array<string, mixed>|null $otherUI
     */
    public function __construct(public string $publicKeyCredentialId, public string $type, public array $transports, public string $attestationType, public TrustPath $trustPath, public Uuid $aaguid, public string $credentialPublicKey, public string $userHandle, public int $counter, public ?array $otherUI = null, public ?bool $backupEligible = null, public ?bool $backupStatus = null, public ?bool $uvInitialized = null)
    {
    }
    /**
     * @param string[] $transports
     * @param array<string, mixed>|null $otherUI
     */
    public static function create(string $publicKeyCredentialId, string $type, array $transports, string $attestationType, TrustPath $trustPath, Uuid $aaguid, string $credentialPublicKey, string $userHandle, int $counter, ?array $otherUI = null, ?bool $backupEligible = null, ?bool $backupStatus = null, ?bool $uvInitialized = null): self
    {
        return new self($publicKeyCredentialId, $type, $transports, $attestationType, $trustPath, $aaguid, $credentialPublicKey, $userHandle, $counter, $otherUI, $backupEligible, $backupStatus, $uvInitialized);
    }
    /**
     * @deprecated since 4.7.0. Please use the property directly.
     * @infection-ignore-all
     */
    public function getPublicKeyCredentialId(): string
    {
        return $this->publicKeyCredentialId;
    }
    public function getPublicKeyCredentialDescriptor(): PublicKeyCredentialDescriptor
    {
        return PublicKeyCredentialDescriptor::create($this->type, $this->publicKeyCredentialId, $this->transports);
    }
    /**
     * @deprecated since 4.7.0. Please use the property directly.
     * @infection-ignore-all
     */
    public function getAttestationType(): string
    {
        return $this->attestationType;
    }
    /**
     * @deprecated since 4.7.0. Please use the property directly.
     * @infection-ignore-all
     */
    public function getTrustPath(): TrustPath
    {
        return $this->trustPath;
    }
    public function getAttestedCredentialData(): AttestedCredentialData
    {
        return AttestedCredentialData::create($this->aaguid, $this->publicKeyCredentialId, $this->credentialPublicKey);
    }
    /**
     * @deprecated since 4.7.0. Please use the property directly.
     * @infection-ignore-all
     */
    public function getType(): string
    {
        return $this->type;
    }
    /**
     * @return string[]
     * @deprecated since 4.7.0. Please use the property directly.
     * @infection-ignore-all
     */
    public function getTransports(): array
    {
        return $this->transports;
    }
    /**
     * @deprecated since 4.7.0. Please use the property directly.
     * @infection-ignore-all
     */
    public function getAaguid(): Uuid
    {
        return $this->aaguid;
    }
    /**
     * @deprecated since 4.7.0. Please use the property directly.
     * @infection-ignore-all
     */
    public function getCredentialPublicKey(): string
    {
        return $this->credentialPublicKey;
    }
    /**
     * @deprecated since 4.7.0. Please use the property directly.
     * @infection-ignore-all
     */
    public function getUserHandle(): string
    {
        return $this->userHandle;
    }
    /**
     * @deprecated since 4.7.0. Please use the property directly.
     * @infection-ignore-all
     */
    public function getCounter(): int
    {
        return $this->counter;
    }
    /**
     * @deprecated since 4.7.0. Please use the property directly.
     * @infection-ignore-all
     */
    public function setCounter(int $counter): void
    {
        $this->counter = $counter;
    }
    /**
     * @return array<string, mixed>|null
     * @deprecated since 4.7.0. Please use the property directly.
     * @infection-ignore-all
     */
    public function getOtherUI(): ?array
    {
        return $this->otherUI;
    }
    /**
     * @param array<string, mixed>|null $otherUI
     * @deprecated since 4.7.0. Please use the property directly.
     * @infection-ignore-all
     */
    public function setOtherUI(?array $otherUI): self
    {
        $this->otherUI = $otherUI;
        return $this;
    }
    /**
     * @param mixed[] $data
     * @deprecated since 4.8.0. Please use {Webauthn\Denormalizer\WebauthnSerializerFactory} for converting the object.
     * @infection-ignore-all
     */
    public static function createFromArray(array $data): self
    {
        $keys = array_keys(get_class_vars(self::class));
        foreach ($keys as $key) {
            if (in_array($key, ['otherUI', 'backupEligible', 'backupStatus', 'uvInitialized'], \true)) {
                continue;
            }
            array_key_exists($key, $data) || throw InvalidDataException::create($data, sprintf('The parameter "%s" is missing', $key));
        }
        mb_strlen((string) $data['aaguid'], '8bit') === 36 || throw InvalidDataException::create($data, 'Invalid AAGUID');
        $uuid = Uuid::fromString($data['aaguid']);
        try {
            return self::create(Base64UrlSafe::decodeNoPadding($data['publicKeyCredentialId']), $data['type'], $data['transports'], $data['attestationType'], TrustPathLoader::loadTrustPath($data['trustPath']), $uuid, Base64UrlSafe::decodeNoPadding($data['credentialPublicKey']), Base64UrlSafe::decodeNoPadding($data['userHandle']), $data['counter'], $data['otherUI'] ?? null, $data['backupEligible'] ?? null, $data['backupStatus'] ?? null);
        } catch (Throwable $throwable) {
            throw InvalidDataException::create($data, 'Unable to load the data', $throwable);
        }
    }
    /**
     * @return mixed[]
     */
    public function jsonSerialize(): array
    {
        trigger_deprecation('web-auth/webauthn-bundle', '4.9.0', 'The "%s" method is deprecated and will be removed in 5.0. Please use the serializer instead.', __METHOD__);
        $result = ['publicKeyCredentialId' => Base64UrlSafe::encodeUnpadded($this->publicKeyCredentialId), 'type' => $this->type, 'transports' => $this->transports, 'attestationType' => $this->attestationType, 'trustPath' => $this->trustPath, 'aaguid' => $this->aaguid->__toString(), 'credentialPublicKey' => Base64UrlSafe::encodeUnpadded($this->credentialPublicKey), 'userHandle' => Base64UrlSafe::encodeUnpadded($this->userHandle), 'counter' => $this->counter, 'otherUI' => $this->otherUI, 'backupEligible' => $this->backupEligible, 'backupStatus' => $this->backupStatus, 'uvInitialized' => $this->uvInitialized];
        return array_filter($result, static fn($value): bool => $value !== null);
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\Webauthn;

use InvalidArgumentException;
use _ContaoManager\ParagonIE\ConstantTime\Base64UrlSafe;
use _ContaoManager\Webauthn\AuthenticationExtensions\AuthenticationExtensions;
use _ContaoManager\Webauthn\AuthenticationExtensions\AuthenticationExtensionsClientInputs;
use _ContaoManager\Webauthn\Exception\InvalidDataException;
use _ContaoManager\Webauthn\Util\Base64;
use function array_key_exists;
use function count;
use function in_array;
use function is_array;
use const JSON_THROW_ON_ERROR;
final class PublicKeyCredentialCreationOptions extends PublicKeyCredentialOptions
{
    public const ATTESTATION_CONVEYANCE_PREFERENCE_DEFAULT = null;
    public const ATTESTATION_CONVEYANCE_PREFERENCE_NONE = 'none';
    public const ATTESTATION_CONVEYANCE_PREFERENCE_INDIRECT = 'indirect';
    public const ATTESTATION_CONVEYANCE_PREFERENCE_DIRECT = 'direct';
    public const ATTESTATION_CONVEYANCE_PREFERENCE_ENTERPRISE = 'enterprise';
    public const ATTESTATION_CONVEYANCE_PREFERENCES = [self::ATTESTATION_CONVEYANCE_PREFERENCE_DEFAULT, self::ATTESTATION_CONVEYANCE_PREFERENCE_NONE, self::ATTESTATION_CONVEYANCE_PREFERENCE_INDIRECT, self::ATTESTATION_CONVEYANCE_PREFERENCE_DIRECT, self::ATTESTATION_CONVEYANCE_PREFERENCE_ENTERPRISE];
    /**
     * @private
     * @param PublicKeyCredentialParameters[] $pubKeyCredParams
     * @param PublicKeyCredentialDescriptor[] $excludeCredentials
     * @param null|positive-int $timeout
     */
    public function __construct(public readonly PublicKeyCredentialRpEntity $rp, public readonly PublicKeyCredentialUserEntity $user, string $challenge, public array $pubKeyCredParams = [], public null|AuthenticatorSelectionCriteria $authenticatorSelection = null, public null|string $attestation = null, public array $excludeCredentials = [], null|int $timeout = null, null|AuthenticationExtensions $extensions = null)
    {
        foreach ($pubKeyCredParams as $pubKeyCredParam) {
            $pubKeyCredParam instanceof PublicKeyCredentialParameters || throw new InvalidArgumentException('Invalid type for $pubKeyCredParams');
        }
        foreach ($excludeCredentials as $excludeCredential) {
            $excludeCredential instanceof PublicKeyCredentialDescriptor || throw new InvalidArgumentException('Invalid type for $excludeCredentials');
        }
        in_array($attestation, self::ATTESTATION_CONVEYANCE_PREFERENCES, \true) || throw InvalidDataException::create($attestation, 'Invalid attestation conveyance mode');
        parent::__construct($challenge, $timeout, $extensions);
    }
    /**
     * @param PublicKeyCredentialParameters[] $pubKeyCredParams
     * @param PublicKeyCredentialDescriptor[] $excludeCredentials
     * @param null|positive-int $timeout
     */
    public static function create(PublicKeyCredentialRpEntity $rp, PublicKeyCredentialUserEntity $user, string $challenge, array $pubKeyCredParams = [], null|AuthenticatorSelectionCriteria $authenticatorSelection = null, null|string $attestation = null, array $excludeCredentials = [], null|int $timeout = null, null|AuthenticationExtensions $extensions = null): self
    {
        return new self($rp, $user, $challenge, $pubKeyCredParams, $authenticatorSelection, $attestation, $excludeCredentials, $timeout, $extensions);
    }
    /**
     * @deprecated since 4.7.0. Please use the {self::create} instead.
     * @infection-ignore-all
     */
    public function addPubKeyCredParam(PublicKeyCredentialParameters $pubKeyCredParam): self
    {
        $this->pubKeyCredParams[] = $pubKeyCredParam;
        return $this;
    }
    /**
     * @deprecated since 4.7.0. No replacement. Please use the {self::create} instead.
     * @infection-ignore-all
     */
    public function addPubKeyCredParams(PublicKeyCredentialParameters ...$pubKeyCredParams): self
    {
        foreach ($pubKeyCredParams as $pubKeyCredParam) {
            $this->pubKeyCredParams[] = $pubKeyCredParam;
        }
        return $this;
    }
    /**
     * @deprecated since 4.7.0. Please use the {self::create} instead.
     * @infection-ignore-all
     */
    public function excludeCredential(PublicKeyCredentialDescriptor $excludeCredential): self
    {
        $this->excludeCredentials[] = $excludeCredential;
        return $this;
    }
    /**
     * @deprecated since 4.7.0. No replacement. Please use the {self::create} instead.
     * @infection-ignore-all
     */
    public function excludeCredentials(PublicKeyCredentialDescriptor ...$excludeCredentials): self
    {
        foreach ($excludeCredentials as $excludeCredential) {
            $this->excludeCredentials[] = $excludeCredential;
        }
        return $this;
    }
    /**
     * @deprecated since 4.7.0. Please use the {self::create} instead.
     * @infection-ignore-all
     */
    public function setAuthenticatorSelection(?AuthenticatorSelectionCriteria $authenticatorSelection): self
    {
        $this->authenticatorSelection = $authenticatorSelection;
        return $this;
    }
    /**
     * @deprecated since 4.7.0. Please use the {self::create} instead.
     * @infection-ignore-all
     */
    public function setAttestation(string $attestation): self
    {
        in_array($attestation, self::ATTESTATION_CONVEYANCE_PREFERENCES, \true) || throw InvalidDataException::create($attestation, 'Invalid attestation conveyance mode');
        $this->attestation = $attestation;
        return $this;
    }
    /**
     * @deprecated since 4.7.0. Please use the property directly.
     * @infection-ignore-all
     */
    public function getRp(): PublicKeyCredentialRpEntity
    {
        return $this->rp;
    }
    /**
     * @deprecated since 4.7.0. Please use the property directly.
     * @infection-ignore-all
     */
    public function getUser(): PublicKeyCredentialUserEntity
    {
        return $this->user;
    }
    /**
     * @return PublicKeyCredentialParameters[]
     * @deprecated since 4.7.0. Please use the property directly.
     * @infection-ignore-all
     */
    public function getPubKeyCredParams(): array
    {
        return $this->pubKeyCredParams;
    }
    /**
     * @return PublicKeyCredentialDescriptor[]
     * @deprecated since 4.7.0. Please use the property directly.
     * @infection-ignore-all
     */
    public function getExcludeCredentials(): array
    {
        return $this->excludeCredentials;
    }
    /**
     * @deprecated since 4.7.0. Please use the property directly.
     * @infection-ignore-all
     */
    public function getAuthenticatorSelection(): ?AuthenticatorSelectionCriteria
    {
        return $this->authenticatorSelection;
    }
    /**
     * @deprecated since 4.7.0. Please use the property directly.
     * @infection-ignore-all
     */
    public function getAttestation(): ?string
    {
        return $this->attestation;
    }
    /**
     * @deprecated since 4.8.0. Please use {Webauthn\Denormalizer\WebauthnSerializerFactory} for converting the object.
     * @infection-ignore-all
     */
    public static function createFromString(string $data): static
    {
        $data = json_decode($data, \true, flags: JSON_THROW_ON_ERROR);
        return self::createFromArray($data);
    }
    /**
     * @deprecated since 4.8.0. Please use {Webauthn\Denormalizer\WebauthnSerializerFactory} for converting the object.
     * @infection-ignore-all
     */
    public static function createFromArray(array $json): static
    {
        array_key_exists('rp', $json) || throw InvalidDataException::create($json, 'Invalid input. "rp" is missing.');
        array_key_exists('pubKeyCredParams', $json) || throw InvalidDataException::create($json, 'Invalid input. "pubKeyCredParams" is missing.');
        is_array($json['pubKeyCredParams']) || throw InvalidDataException::create($json, 'Invalid input. "pubKeyCredParams" is not an array.');
        array_key_exists('challenge', $json) || throw InvalidDataException::create($json, 'Invalid input. "challenge" is missing.');
        array_key_exists('attestation', $json) || throw InvalidDataException::create($json, 'Invalid input. "attestation" is missing.');
        array_key_exists('user', $json) || throw InvalidDataException::create($json, 'Invalid input. "user" is missing.');
        $pubKeyCredParams = [];
        foreach ($json['pubKeyCredParams'] as $pubKeyCredParam) {
            if (!is_array($pubKeyCredParam)) {
                continue;
            }
            $pubKeyCredParams[] = PublicKeyCredentialParameters::createFromArray($pubKeyCredParam);
        }
        $excludeCredentials = [];
        if (isset($json['excludeCredentials'])) {
            foreach ($json['excludeCredentials'] as $excludeCredential) {
                $excludeCredentials[] = PublicKeyCredentialDescriptor::createFromArray($excludeCredential);
            }
        }
        $challenge = Base64::decode($json['challenge']);
        $authenticatorSelection = isset($json['authenticatorSelection']) ? AuthenticatorSelectionCriteria::createFromArray($json['authenticatorSelection']) : null;
        $extensions = isset($json['extensions']) ? AuthenticationExtensionsClientInputs::createFromArray($json['extensions']) : AuthenticationExtensionsClientInputs::create();
        return self::create(PublicKeyCredentialRpEntity::createFromArray($json['rp']), PublicKeyCredentialUserEntity::createFromArray($json['user']), $challenge, $pubKeyCredParams, $authenticatorSelection, $json['attestation'] ?? null, $excludeCredentials, $json['timeout'] ?? null, $extensions);
    }
    /**
     * @return mixed[]
     */
    public function jsonSerialize(): array
    {
        trigger_deprecation('web-auth/webauthn-bundle', '4.9.0', 'The "%s" method is deprecated and will be removed in 5.0. Please use the serializer instead.', __METHOD__);
        $json = ['rp' => $this->rp, 'user' => $this->user, 'challenge' => Base64UrlSafe::encodeUnpadded($this->challenge), 'pubKeyCredParams' => $this->pubKeyCredParams];
        if ($this->timeout !== null) {
            $json['timeout'] = $this->timeout;
        }
        if (count($this->excludeCredentials) !== 0) {
            $json['excludeCredentials'] = $this->excludeCredentials;
        }
        if ($this->authenticatorSelection !== null) {
            $json['authenticatorSelection'] = $this->authenticatorSelection;
        }
        if ($this->attestation !== null) {
            $json['attestation'] = $this->attestation;
        }
        if ($this->extensions->count() !== 0) {
            $json['extensions'] = $this->extensions;
        }
        return $json;
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\Webauthn;

use _ContaoManager\ParagonIE\ConstantTime\Base64UrlSafe;
use _ContaoManager\Webauthn\Exception\InvalidDataException;
use _ContaoManager\Webauthn\TokenBinding\TokenBinding;
use function array_key_exists;
use function is_array;
use function is_string;
use function sprintf;
use const JSON_THROW_ON_ERROR;
class CollectedClientData
{
    /**
     * @var mixed[]
     */
    public readonly array $data;
    public readonly string $type;
    public readonly string $challenge;
    public readonly string $origin;
    public readonly null|string $topOrigin;
    public readonly bool $crossOrigin;
    /**
     * @var mixed[]|null
     * @deprecated Since 4.3.0 and will be removed in 5.0.0
     * @infection-ignore-all
     */
    public readonly ?array $tokenBinding;
    /**
     * @param mixed[] $data
     */
    public function __construct(public readonly string $rawData, array $data)
    {
        $type = $data['type'] ?? '';
        is_string($type) && $type !== '' || throw InvalidDataException::create($data, 'Invalid parameter "type". Shall be a non-empty string.');
        $this->type = $type;
        $challenge = $data['challenge'] ?? '';
        is_string($challenge) || throw InvalidDataException::create($data, 'Invalid parameter "challenge". Shall be a string.');
        $challenge = Base64UrlSafe::decodeNoPadding($challenge);
        $challenge !== '' || throw InvalidDataException::create($data, 'Invalid parameter "challenge". Shall not be empty.');
        $this->challenge = $challenge;
        $origin = $data['origin'] ?? '';
        is_string($origin) && $origin !== '' || throw InvalidDataException::create($data, 'Invalid parameter "origin". Shall be a non-empty string.');
        $this->origin = $origin;
        $this->topOrigin = $data['topOrigin'] ?? null;
        $this->crossOrigin = $data['crossOrigin'] ?? \false;
        $tokenBinding = $data['tokenBinding'] ?? null;
        $tokenBinding === null || is_array($tokenBinding) || throw InvalidDataException::create($data, 'Invalid parameter "tokenBinding". Shall be an object or .');
        $this->tokenBinding = $tokenBinding;
        $this->data = $data;
    }
    /**
     * @param mixed[] $data
     */
    public static function create(string $rawData, array $data): self
    {
        return new self($rawData, $data);
    }
    public static function createFormJson(string $data): self
    {
        $rawData = Base64UrlSafe::decodeNoPadding($data);
        $json = json_decode($rawData, \true, flags: JSON_THROW_ON_ERROR);
        is_array($json) || throw InvalidDataException::create($data, 'Invalid JSON data.');
        return self::create($rawData, $json);
    }
    /**
     * @deprecated since 4.7.0. Please use the property directly.
     * @infection-ignore-all
     */
    public function getType(): string
    {
        return $this->type;
    }
    /**
     * @deprecated since 4.7.0. Please use the property directly.
     * @infection-ignore-all
     */
    public function getChallenge(): string
    {
        return $this->challenge;
    }
    /**
     * @deprecated since 4.7.0. Please use the property directly.
     * @infection-ignore-all
     */
    public function getOrigin(): string
    {
        return $this->origin;
    }
    /**
     * @deprecated since 4.7.0. Please use the property directly.
     * @infection-ignore-all
     */
    public function getCrossOrigin(): bool
    {
        return $this->crossOrigin;
    }
    /**
     * @deprecated Since 4.3.0 and will be removed in 5.0.0
     * @infection-ignore-all
     */
    public function getTokenBinding(): ?TokenBinding
    {
        return $this->tokenBinding === null ? null : TokenBinding::createFormArray($this->tokenBinding);
    }
    /**
     * @deprecated since 4.7.0. Please use the property directly.
     * @infection-ignore-all
     */
    public function getRawData(): string
    {
        return $this->rawData;
    }
    /**
     * @return string[]
     */
    public function all(): array
    {
        return array_keys($this->data);
    }
    public function has(string $key): bool
    {
        return array_key_exists($key, $this->data);
    }
    public function get(string $key): mixed
    {
        if (!$this->has($key)) {
            throw InvalidDataException::create($this->data, sprintf('The key "%s" is missing', $key));
        }
        return $this->data[$key];
    }
}
# Contributor Covenant Code of Conduct

## Our Pledge

In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation.

## Our Standards

Examples of behavior that contributes to creating a positive environment include:

-   Using welcoming and inclusive language
-   Being respectful of differing viewpoints and experiences
-   Gracefully accepting constructive criticism
-   Focusing on what is best for the community
-   Showing empathy towards other community members

Examples of unacceptable behavior by participants include:

-   The use of sexualized language or imagery and unwelcome sexual attention or advances
-   Trolling, insulting/derogatory comments, and personal or political attacks
-   Public or private harassment
-   Publishing others' private information, such as a physical or electronic address, without explicit permission
-   Other conduct which could reasonably be considered inappropriate in a professional setting

## Our Responsibilities

Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior.

Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful.

## Scope

This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers.

## Enforcement

Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at contact@spomky-labs.com. The project team will review and investigate all complaints, and will respond in a way that it deems appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately.

Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership.

## Attribution

This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [http://contributor-covenant.org/version/1/4][version]

[homepage]: http://contributor-covenant.org
[version]: http://contributor-covenant.org/version/1/4/
# Versioning and Release

This document describes the versioning and release process of the Webauthn Framework.
This document is a living document, contents will be updated according to each release.

## Releases

Webauthn Framework releases will be versioned using dotted triples, similar to [Semantic Version](http://semver.org/).
For this specific document, we will refer to the respective components of this triple as `<major>.<minor>.<patch>`.
The version number may have additional information, such as "-rc1,-rc2,-rc3" to mark release candidate builds for earlier access.
Such releases will be considered as "pre-releases".

## Minor Release Support Matrix

| Version | Supported          |
|---------|--------------------|
| 4.5.x   | :white_check_mark: |
| < 4.5.x | :x:                |
MIT License

Copyright (c) 2018 Spomky-Labs

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
# COSE Library for PHP

[![CI](https://github.com/web-auth/cose-lib/actions/workflows/ci.yml/badge.svg)](https://github.com/web-auth/cose-lib/actions/workflows/ci.yml)
[![Latest Stable Version](https://poser.pugx.org/web-auth/cose-lib/v)](https://packagist.org/packages/web-auth/cose-lib)
[![Total Downloads](https://poser.pugx.org/web-auth/cose-lib/downloads)](https://packagist.org/packages/web-auth/cose-lib)
[![License](https://poser.pugx.org/web-auth/cose-lib/license)](https://packagist.org/packages/web-auth/cose-lib)

**CBOR Object Signing and Encryption (COSE) for PHP** is a comprehensive library that provides full support for COSE operations including signing, encryption, and MAC (Message Authentication Code) operations.

This library implements:
- **[RFC 9052](https://datatracker.ietf.org/doc/html/rfc9052)** - COSE: Structures and Process
- **[RFC 9053](https://datatracker.ietf.org/doc/html/rfc9053)** - COSE: Initial Algorithms

## Features

✅ **Complete COSE Tag Support**
- COSE_Sign1 (tag 18) - Single signature
- COSE_Sign (tag 98) - Multiple signatures
- COSE_Encrypt0 (tag 16) - Single recipient encryption
- COSE_Encrypt (tag 96) - Multiple recipients encryption
- COSE_Mac0 (tag 17) - MAC without recipients
- COSE_Mac (tag 97) - MAC with recipients

✅ **Cryptographic Algorithms**
- **Signatures**: ECDSA (ES256, ES384, ES512, ES256K), EdDSA (Ed25519, Ed448), RSA (RS256/384/512, PS256/384/512)
- **MAC**: HMAC with SHA-256/384/512
- Compatible with WebAuthn, FIDO2, and digital COVID certificates

✅ **Modern PHP**
- PHP 8.1+ with strict types
- Full type safety and PHPStan compliance
- Comprehensive test coverage

## Installation

Install the library with Composer:

```bash
composer require web-auth/cose-lib
```

For COSE tag support (Sign, Encrypt, Mac operations), also install:

```bash
composer require spomky-labs/cbor-php
```

## Quick Start

### Verifying a COSE_Sign1 Signature

```php
use CBOR\Decoder;
use CBOR\OtherObject\OtherObjectManager;
use CBOR\StringStream;
use CBOR\Tag\TagManager;
use Cose\Signature\CoseSign1Tag;
use Cose\Signature\Signature1;

// Setup decoder with COSE tag support
$tagManager = TagManager::create()->add(CoseSign1Tag::class);
$decoder = Decoder::create($tagManager, OtherObjectManager::create());

// Decode COSE_Sign1 message
$stream = new StringStream($encodedData);
$coseSign1 = $decoder->decode($stream);

// Extract components
$protectedHeader = $coseSign1->getProtectedHeader();
$payload = $coseSign1->getPayload();
$signature = $coseSign1->getSignature();

// Create signature structure for verification
$sigStructure = Signature1::create($protectedHeader, $payload);

// Verify (example with OpenSSL)
$isValid = openssl_verify(
    (string) $sigStructure,
    $derSignature,
    $publicKey,
    'sha256'
);
```

### Creating a COSE_Sign1 Message

```php
use CBOR\ByteStringObject;
use CBOR\MapItem;
use CBOR\MapObject;
use CBOR\NegativeIntegerObject;
use CBOR\UnsignedIntegerObject;
use Cose\Signature\CoseSign1Tag;

// Define headers
$protectedHeader = MapObject::create([
    MapItem::create(
        UnsignedIntegerObject::create(1), // alg
        NegativeIntegerObject::create(-7) // ES256
    ),
]);

$unprotectedHeader = MapObject::create([
    MapItem::create(
        UnsignedIntegerObject::create(4), // kid
        ByteStringObject::create('my-key-id')
    ),
]);

// Create COSE_Sign1
$coseSign1 = CoseSign1Tag::create(
    $protectedHeader,
    $unprotectedHeader,
    ByteStringObject::create('Message to sign'),
    ByteStringObject::create($signatureBytes)
);

// Encode to CBOR
$encoded = (string) $coseSign1;
```

## Documentation

- **[Usage Guide](doc/Usage.md)** - Complete documentation with examples
- **[RFC 9052](https://datatracker.ietf.org/doc/html/rfc9052)** - COSE Structures
- **[RFC 9053](https://datatracker.ietf.org/doc/html/rfc9053)** - COSE Algorithms

## Use Cases

This library is perfect for:

- 🏥 **Digital Health Certificates** - COVID-19 vaccination passes (EU Digital COVID Certificate)
- 🔐 **WebAuthn/FIDO2** - Authenticator attestation and assertion signatures
- 📱 **IoT Security** - Secure messaging for constrained devices
- 🌐 **Web PKI** - CBOR-based certificate chains
- 📄 **Document Signing** - Compact digital signatures

## Supported Algorithms

### Signature Algorithms

| Algorithm | Identifier | Description |
|-----------|------------|-------------|
| ES256 | -7 | ECDSA with SHA-256 |
| ES384 | -35 | ECDSA with SHA-384 |
| ES512 | -36 | ECDSA with SHA-512 |
| ES256K | -47 | ECDSA with secp256k1 |
| EdDSA | -8 | EdDSA |
| Ed25519 | - | EdDSA with Curve25519 |
| RS256 | -257 | RSASSA-PKCS1-v1_5 with SHA-256 |
| RS384 | -258 | RSASSA-PKCS1-v1_5 with SHA-384 |
| RS512 | -259 | RSASSA-PKCS1-v1_5 with SHA-512 |
| PS256 | -37 | RSASSA-PSS with SHA-256 |
| PS384 | -38 | RSASSA-PSS with SHA-384 |
| PS512 | -39 | RSASSA-PSS with SHA-512 |

### MAC Algorithms

| Algorithm | Identifier | Description |
|-----------|------------|-------------|
| HS256 | 5 | HMAC with SHA-256 |
| HS384 | 6 | HMAC with SHA-384 |
| HS512 | 7 | HMAC with SHA-512 |
| HS256/64 | 4 | HMAC with SHA-256 truncated to 64 bits |

## Testing

Run the test suite with:

```bash
composer test
```

Or using Castor:

```bash
castor phpunit
```

The library includes comprehensive tests including:
- Unit tests for all COSE tag types
- Integration tests with real cryptographic operations
- COVID-19 certificate verification examples
- Test fixtures with actual certificates

## Requirements

- PHP 8.1 or higher
- ext-json
- ext-openssl
- brick/math
- spomky-labs/pki-framework
- spomky-labs/cbor-php (for COSE tag support)

## Contributing

Contributions are welcome! Please see [CONTRIBUTING.md](doc/Contributing.md) for details.

For security vulnerabilities, please email **security [at] spomky-labs.com** instead of using the issue tracker.

## Support

I bring solutions to your problems and answer your questions.

If you really love this project and the work I have done, or if you want me to prioritize your issues, you can support me:

- [Become a sponsor on GitHub](https://github.com/sponsors/Spomky)
- [Become a Patreon](https://www.patreon.com/FlorentMorselli)

## License

This software is released under the [MIT License](LICENSE).

## Credits

Maintained by [Florent Morselli](https://github.com/Spomky) and [contributors](https://github.com/web-auth/cose-lib/contributors).

---

Made with ❤️ for the PHP community
{
    "name": "web-auth\/cose-lib",
    "type": "library",
    "license": "MIT",
    "description": "CBOR Object Signing and Encryption (COSE) For PHP",
    "keywords": [
        "COSE",
        "RFC8152"
    ],
    "homepage": "https:\/\/github.com\/web-auth",
    "authors": [
        {
            "name": "Florent Morselli",
            "homepage": "https:\/\/github.com\/Spomky"
        },
        {
            "name": "All contributors",
            "homepage": "https:\/\/github.com\/web-auth\/cose\/contributors"
        }
    ],
    "require": {
        "php": ">=8.1",
        "ext-json": "*",
        "ext-openssl": "*",
        "brick\/math": "^0.9|^0.10|^0.11|^0.12|^0.13|^0.14|^0.15|^0.16|^0.17",
        "spomky-labs\/pki-framework": "^1.0"
    },
    "require-dev": {
        "spomky-labs\/cbor-php": "^3.2.2"
    },
    "autoload": {
        "psr-4": {
            "_ContaoManager\\Cose\\": "src\/"
        }
    },
    "autoload-dev": {
        "psr-4": {
            "_ContaoManager\\Cose\\Tests\\": "tests\/"
        }
    },
    "suggest": {
        "ext-gmp": "For better performance, please install either GMP (recommended) or BCMath extension",
        "ext-bcmath": "For better performance, please install either GMP (recommended) or BCMath extension",
        "spomky-labs\/cbor-php": "For COSE Signature support"
    }
}# Security Policy

## Supported Versions

| Version | Supported                              |
| ------- |----------------------------------------|
| 4.0.x   | :white_check_mark:                     |
| 3.3.x   | :white_check_mark: (security fix only) |
| < 3.3.x | :x:                                    |

## Reporting a Vulnerability

If you think you have found a security issue, DO NOT open an issue. You MUST submit email security AT spomky-labs.com
<?php

declare (strict_types=1);
namespace _ContaoManager\Cose\Encryption;

use _ContaoManager\CBOR\ByteStringObject;
use _ContaoManager\CBOR\CBORObject;
use _ContaoManager\CBOR\Decoder;
use _ContaoManager\CBOR\ListObject;
use _ContaoManager\CBOR\MapObject;
use _ContaoManager\CBOR\OtherObject\OtherObjectManager;
use _ContaoManager\CBOR\StringStream;
use _ContaoManager\CBOR\Tag;
use _ContaoManager\CBOR\Tag\TagManager;
use InvalidArgumentException;
final class CoseEncryptTag extends Tag
{
    private const TAG_ID = 96;
    private readonly ByteStringObject $protectedHeader;
    private readonly MapObject $unprotectedHeader;
    private readonly ByteStringObject $ciphertext;
    private readonly ListObject $recipients;
    public function __construct(int $additionalInformation, ?string $data, CBORObject $object)
    {
        if (!$object instanceof ListObject) {
            throw new InvalidArgumentException('Not a valid CoseEncrypt object. No list.');
        }
        if ($object->count() !== 4) {
            throw new InvalidArgumentException('Not a valid CoseEncrypt object. The list shall have 4 items.');
        }
        $protectedHeader = $object->get(0);
        $unprotectedHeader = $object->get(1);
        $ciphertext = $object->get(2);
        $recipients = $object->get(3);
        if (!$protectedHeader instanceof ByteStringObject) {
            throw new InvalidArgumentException('Not a valid CoseEncrypt object. The item 1 shall be a ByteString object.');
        }
        if (!$unprotectedHeader instanceof MapObject) {
            throw new InvalidArgumentException('Not a valid CoseEncrypt object. The item 2 shall be a Map object.');
        }
        if (!$ciphertext instanceof ByteStringObject) {
            throw new InvalidArgumentException('Not a valid CoseEncrypt object. The item 3 shall be a ByteString object.');
        }
        if (!$recipients instanceof ListObject) {
            throw new InvalidArgumentException('Not a valid CoseEncrypt object. The item 4 shall be a List object.');
        }
        parent::__construct($additionalInformation, $data, $object);
        $this->protectedHeader = $protectedHeader;
        $this->unprotectedHeader = $unprotectedHeader;
        $this->ciphertext = $ciphertext;
        $this->recipients = $recipients;
    }
    public static function getTagId(): int
    {
        return self::TAG_ID;
    }
    public static function createFromLoadedData(int $additionalInformation, ?string $data, CBORObject $object): self
    {
        return new self($additionalInformation, $data, $object);
    }
    public static function create(MapObject $protectedHeader, MapObject $unprotectedHeader, ByteStringObject $ciphertext, ListObject $recipients): self
    {
        $protectedHeaderAsBytesString = ByteStringObject::create((string) $protectedHeader);
        $object = ListObject::create([$protectedHeaderAsBytesString, $unprotectedHeader, $ciphertext, $recipients]);
        [$additionalInformation, $data] = self::determineComponents(self::TAG_ID);
        return new self($additionalInformation, $data, $object);
    }
    public function getProtectedHeader(): ByteStringObject
    {
        return $this->protectedHeader;
    }
    public function getProtectedHeaderAsMap(?Decoder $decoder = null): MapObject
    {
        $stream = new StringStream($this->protectedHeader->getValue());
        $decoder ??= Decoder::create(TagManager::create(), OtherObjectManager::create());
        $decoded = $decoder->decode($stream);
        if (!$decoded instanceof MapObject) {
            throw new InvalidArgumentException('Protected header is not a valid Map object.');
        }
        return $decoded;
    }
    public function getUnprotectedHeader(): MapObject
    {
        return $this->unprotectedHeader;
    }
    public function getCiphertext(): ByteStringObject
    {
        return $this->ciphertext;
    }
    public function getRecipients(): ListObject
    {
        return $this->recipients;
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\Cose\Encryption;

use _ContaoManager\CBOR\ByteStringObject;
use _ContaoManager\CBOR\CBORObject;
use _ContaoManager\CBOR\Decoder;
use _ContaoManager\CBOR\ListObject;
use _ContaoManager\CBOR\MapObject;
use _ContaoManager\CBOR\OtherObject\OtherObjectManager;
use _ContaoManager\CBOR\StringStream;
use _ContaoManager\CBOR\Tag;
use _ContaoManager\CBOR\Tag\TagManager;
use InvalidArgumentException;
final class CoseEncrypt0Tag extends Tag
{
    private const TAG_ID = 16;
    private readonly ByteStringObject $protectedHeader;
    private readonly MapObject $unprotectedHeader;
    private readonly ByteStringObject $ciphertext;
    public function __construct(int $additionalInformation, ?string $data, CBORObject $object)
    {
        if (!$object instanceof ListObject) {
            throw new InvalidArgumentException('Not a valid CoseEncrypt0 object. No list.');
        }
        if ($object->count() !== 3) {
            throw new InvalidArgumentException('Not a valid CoseEncrypt0 object. The list shall have 3 items.');
        }
        $protectedHeader = $object->get(0);
        $unprotectedHeader = $object->get(1);
        $ciphertext = $object->get(2);
        if (!$protectedHeader instanceof ByteStringObject) {
            throw new InvalidArgumentException('Not a valid CoseEncrypt0 object. The item 1 shall be a ByteString object.');
        }
        if (!$unprotectedHeader instanceof MapObject) {
            throw new InvalidArgumentException('Not a valid CoseEncrypt0 object. The item 2 shall be a Map object.');
        }
        if (!$ciphertext instanceof ByteStringObject) {
            throw new InvalidArgumentException('Not a valid CoseEncrypt0 object. The item 3 shall be a ByteString object.');
        }
        parent::__construct($additionalInformation, $data, $object);
        $this->protectedHeader = $protectedHeader;
        $this->unprotectedHeader = $unprotectedHeader;
        $this->ciphertext = $ciphertext;
    }
    public static function getTagId(): int
    {
        return self::TAG_ID;
    }
    public static function createFromLoadedData(int $additionalInformation, ?string $data, CBORObject $object): self
    {
        return new self($additionalInformation, $data, $object);
    }
    public static function create(MapObject $protectedHeader, MapObject $unprotectedHeader, ByteStringObject $ciphertext): self
    {
        $protectedHeaderAsBytesString = ByteStringObject::create((string) $protectedHeader);
        $object = ListObject::create([$protectedHeaderAsBytesString, $unprotectedHeader, $ciphertext]);
        [$additionalInformation, $data] = self::determineComponents(self::TAG_ID);
        return new self($additionalInformation, $data, $object);
    }
    public function getProtectedHeader(): ByteStringObject
    {
        return $this->protectedHeader;
    }
    public function getProtectedHeaderAsMap(?Decoder $decoder = null): MapObject
    {
        $stream = new StringStream($this->protectedHeader->getValue());
        $decoder ??= Decoder::create(TagManager::create(), OtherObjectManager::create());
        $decoded = $decoder->decode($stream);
        if (!$decoded instanceof MapObject) {
            throw new InvalidArgumentException('Protected header is not a valid Map object.');
        }
        return $decoded;
    }
    public function getUnprotectedHeader(): MapObject
    {
        return $this->unprotectedHeader;
    }
    public function getCiphertext(): ByteStringObject
    {
        return $this->ciphertext;
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\Cose;

/**
 * @internal
 */
final class Hash
{
    private function __construct(private readonly string $hash, private readonly int $length, private readonly string $t)
    {
    }
    public static function sha1(): self
    {
        return new self('sha1', 20, "0!0\t\x06\x05+\x0e\x03\x02\x1a\x05\x00\x04\x14");
    }
    public static function sha256(): self
    {
        return new self('sha256', 32, "010\r\x06\t`\x86H\x01e\x03\x04\x02\x01\x05\x00\x04 ");
    }
    public static function sha384(): self
    {
        return new self('sha384', 48, "0A0\r\x06\t`\x86H\x01e\x03\x04\x02\x02\x05\x00\x040");
    }
    public static function sha512(): self
    {
        return new self('sha512', 64, "0Q0\r\x06\t`\x86H\x01e\x03\x04\x02\x03\x05\x00\x04@");
    }
    public function getLength(): int
    {
        return $this->length;
    }
    /**
     * Compute the HMAC.
     */
    public function hash(string $text): string
    {
        return hash($this->hash, $text, \true);
    }
    public function name(): string
    {
        return $this->hash;
    }
    public function t(): string
    {
        return $this->t;
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\Cose\Signature;

use _ContaoManager\CBOR\ByteStringObject;
use _ContaoManager\CBOR\CBORObject;
use _ContaoManager\CBOR\Decoder;
use _ContaoManager\CBOR\ListObject;
use _ContaoManager\CBOR\MapObject;
use _ContaoManager\CBOR\OtherObject\OtherObjectManager;
use _ContaoManager\CBOR\StringStream;
use _ContaoManager\CBOR\Tag;
use _ContaoManager\CBOR\Tag\TagManager;
use InvalidArgumentException;
final class CoseSignTag extends Tag
{
    private const TAG_ID = 98;
    private readonly ByteStringObject $protectedHeader;
    private readonly MapObject $unprotectedHeader;
    private readonly ByteStringObject $payload;
    private readonly ListObject $signatures;
    public function __construct(int $additionalInformation, ?string $data, CBORObject $object)
    {
        if (!$object instanceof ListObject) {
            throw new InvalidArgumentException('Not a valid CoseSign object. No list.');
        }
        if ($object->count() !== 4) {
            throw new InvalidArgumentException('Not a valid CoseSign object. The list shall have 4 items.');
        }
        $protectedHeader = $object->get(0);
        $unprotectedHeader = $object->get(1);
        $payload = $object->get(2);
        $signatures = $object->get(3);
        if (!$protectedHeader instanceof ByteStringObject) {
            throw new InvalidArgumentException('Not a valid CoseSign object. The item 1 shall be a ByteString object.');
        }
        if (!$unprotectedHeader instanceof MapObject) {
            throw new InvalidArgumentException('Not a valid CoseSign object. The item 2 shall be a Map object.');
        }
        if (!$payload instanceof ByteStringObject) {
            throw new InvalidArgumentException('Not a valid CoseSign object. The item 3 shall be a ByteString object.');
        }
        if (!$signatures instanceof ListObject) {
            throw new InvalidArgumentException('Not a valid CoseSign object. The item 4 shall be a List object.');
        }
        parent::__construct($additionalInformation, $data, $object);
        $this->protectedHeader = $protectedHeader;
        $this->unprotectedHeader = $unprotectedHeader;
        $this->payload = $payload;
        $this->signatures = $signatures;
    }
    public static function getTagId(): int
    {
        return self::TAG_ID;
    }
    public static function createFromLoadedData(int $additionalInformation, ?string $data, CBORObject $object): self
    {
        return new self($additionalInformation, $data, $object);
    }
    public static function create(MapObject $protectedHeader, MapObject $unprotectedHeader, ByteStringObject $payload, ListObject $signatures): self
    {
        $protectedHeaderAsBytesString = ByteStringObject::create((string) $protectedHeader);
        $object = ListObject::create([$protectedHeaderAsBytesString, $unprotectedHeader, $payload, $signatures]);
        [$additionalInformation, $data] = self::determineComponents(self::TAG_ID);
        return new self($additionalInformation, $data, $object);
    }
    public function getProtectedHeader(): ByteStringObject
    {
        return $this->protectedHeader;
    }
    public function getProtectedHeaderAsMap(?Decoder $decoder = null): MapObject
    {
        $stream = new StringStream($this->protectedHeader->getValue());
        $decoder ??= Decoder::create(TagManager::create(), OtherObjectManager::create());
        $decoded = $decoder->decode($stream);
        if (!$decoded instanceof MapObject) {
            throw new InvalidArgumentException('Protected header is not a valid Map object.');
        }
        return $decoded;
    }
    public function getUnprotectedHeader(): MapObject
    {
        return $this->unprotectedHeader;
    }
    public function getPayload(): ByteStringObject
    {
        return $this->payload;
    }
    public function getSignatures(): ListObject
    {
        return $this->signatures;
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\Cose\Signature;

use _ContaoManager\CBOR\ByteStringObject;
use _ContaoManager\CBOR\CBORObject;
use _ContaoManager\CBOR\Decoder;
use _ContaoManager\CBOR\ListObject;
use _ContaoManager\CBOR\MapObject;
use _ContaoManager\CBOR\OtherObject\OtherObjectManager;
use _ContaoManager\CBOR\StringStream;
use _ContaoManager\CBOR\Tag;
use _ContaoManager\CBOR\Tag\TagManager;
use InvalidArgumentException;
final class CoseSign1Tag extends Tag
{
    private const TAG_ID = 18;
    private readonly ByteStringObject $protectedHeader;
    private readonly MapObject $unprotectedHeader;
    private readonly ByteStringObject $payload;
    private readonly ByteStringObject $signature;
    public function __construct(int $additionalInformation, ?string $data, CBORObject $object)
    {
        if (!$object instanceof ListObject) {
            throw new InvalidArgumentException('Not a valid CoseSign1 object. No list.');
        }
        if ($object->count() !== 4) {
            throw new InvalidArgumentException('Not a valid CoseSign1 object. The list shall have 4 items.');
        }
        $protectedHeader = $object->get(0);
        $unprotectedHeader = $object->get(1);
        $payload = $object->get(2);
        $signature = $object->get(3);
        if (!$protectedHeader instanceof ByteStringObject) {
            throw new InvalidArgumentException('Not a valid CoseSign1 object. The item 1 shall be a ByteString object.');
        }
        if (!$unprotectedHeader instanceof MapObject) {
            throw new InvalidArgumentException('Not a valid CoseSign1 object. The item 2 shall be a Map object.');
        }
        if (!$payload instanceof ByteStringObject) {
            throw new InvalidArgumentException('Not a valid CoseSign1 object. The item 3 shall be a ByteString object.');
        }
        if (!$signature instanceof ByteStringObject) {
            throw new InvalidArgumentException('Not a valid CoseSign1 object. The item 4 shall be a ByteString object.');
        }
        parent::__construct($additionalInformation, $data, $object);
        $this->protectedHeader = $protectedHeader;
        $this->unprotectedHeader = $unprotectedHeader;
        $this->payload = $payload;
        $this->signature = $signature;
    }
    public static function getTagId(): int
    {
        return self::TAG_ID;
    }
    public static function createFromLoadedData(int $additionalInformation, ?string $data, CBORObject $object): self
    {
        return new self($additionalInformation, $data, $object);
    }
    public static function create(MapObject $protectedHeader, MapObject $unprotectedHeader, ByteStringObject $payload, ByteStringObject $signature): self
    {
        $protectedHeaderAsBytesString = ByteStringObject::create((string) $protectedHeader);
        $object = ListObject::create([$protectedHeaderAsBytesString, $unprotectedHeader, $payload, $signature]);
        [$additionalInformation, $data] = self::determineComponents(self::TAG_ID);
        return new self($additionalInformation, $data, $object);
    }
    public function getProtectedHeader(): ByteStringObject
    {
        return $this->protectedHeader;
    }
    public function getProtectedHeaderAsMap(?Decoder $decoder = null): MapObject
    {
        $stream = new StringStream($this->protectedHeader->getValue());
        $decoder ??= Decoder::create(TagManager::create(), OtherObjectManager::create());
        $decoded = $decoder->decode($stream);
        if (!$decoded instanceof MapObject) {
            throw new InvalidArgumentException('Protected header is not a valid Map object.');
        }
        return $decoded;
    }
    public function getUnprotectedHeader(): MapObject
    {
        return $this->unprotectedHeader;
    }
    public function getPayload(): ByteStringObject
    {
        return $this->payload;
    }
    public function getSignature(): ByteStringObject
    {
        return $this->signature;
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\Cose\Signature;

use _ContaoManager\CBOR\ByteStringObject;
use _ContaoManager\CBOR\ListObject;
use _ContaoManager\CBOR\TextStringObject;
use Stringable;
final class Signature1 implements Stringable
{
    public function __construct(private readonly ByteStringObject $protectedHeader, private readonly ByteStringObject $payload)
    {
    }
    public function __toString(): string
    {
        $structure = new ListObject();
        $structure->add(new TextStringObject('Signature1'));
        $structure->add($this->protectedHeader);
        $structure->add(new ByteStringObject(''));
        $structure->add($this->payload);
        return (string) $structure;
    }
    public static function create(ByteStringObject $protectedHeader, ByteStringObject $payload): self
    {
        return new self($protectedHeader, $payload);
    }
    public function getProtectedHeader(): ByteStringObject
    {
        return $this->protectedHeader;
    }
    public function getPayload(): ByteStringObject
    {
        return $this->payload;
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\Cose\Key;

use function array_key_exists;
use InvalidArgumentException;
use function sprintf;
class Key
{
    public const TYPE = 1;
    public const TYPE_OKP = 1;
    public const TYPE_EC2 = 2;
    public const TYPE_RSA = 3;
    public const TYPE_OCT = 4;
    public const TYPE_NAME_OKP = 'OKP';
    public const TYPE_NAME_EC2 = 'EC';
    public const TYPE_NAME_RSA = 'RSA';
    public const TYPE_NAME_OCT = 'oct';
    public const KID = 2;
    public const ALG = 3;
    public const KEY_OPS = 4;
    public const BASE_IV = 5;
    /**
     * @var array<int|string, mixed>
     */
    private readonly array $data;
    /**
     * @param array<int|string, mixed> $data
     */
    public function __construct(array $data)
    {
        if (!array_key_exists(self::TYPE, $data)) {
            throw new InvalidArgumentException('Invalid key: the type is not defined');
        }
        $this->data = $data;
    }
    /**
     * @param array<int|string, mixed> $data
     */
    public static function create(array $data): self
    {
        return new self($data);
    }
    /**
     * @param array<int, mixed> $data
     */
    public static function createFromData(array $data): self
    {
        if (!array_key_exists(self::TYPE, $data)) {
            throw new InvalidArgumentException('Invalid key: the type is not defined');
        }
        return match ($data[self::TYPE]) {
            '1' => new OkpKey($data),
            '2' => new Ec2Key($data),
            '3' => new RsaKey($data),
            '4' => new SymmetricKey($data),
            default => self::create($data),
        };
    }
    public function type(): int|string
    {
        return $this->data[self::TYPE];
    }
    public function alg(): int
    {
        return (int) $this->get(self::ALG);
    }
    /**
     * @return array<int|string, mixed>
     */
    public function getData(): array
    {
        return $this->data;
    }
    public function has(int|string $key): bool
    {
        return array_key_exists($key, $this->data);
    }
    public function get(int|string $key): mixed
    {
        if (!array_key_exists($key, $this->data)) {
            throw new InvalidArgumentException(sprintf('The key has no data at index %d', $key));
        }
        return $this->data[$key];
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\Cose\Key;

use function array_key_exists;
use _ContaoManager\Brick\Math\BigInteger;
use function in_array;
use InvalidArgumentException;
use _ContaoManager\SpomkyLabs\Pki\CryptoTypes\Asymmetric\PublicKeyInfo;
use _ContaoManager\SpomkyLabs\Pki\CryptoTypes\Asymmetric\RSA\RSAPrivateKey;
use _ContaoManager\SpomkyLabs\Pki\CryptoTypes\Asymmetric\RSA\RSAPublicKey;
/**
 * @final
 * @see \Cose\Tests\Key\RsaKeyTest
 */
class RsaKey extends Key
{
    final public const DATA_N = -1;
    final public const DATA_E = -2;
    final public const DATA_D = -3;
    final public const DATA_P = -4;
    final public const DATA_Q = -5;
    final public const DATA_DP = -6;
    final public const DATA_DQ = -7;
    final public const DATA_QI = -8;
    final public const DATA_OTHER = -9;
    final public const DATA_RI = -10;
    final public const DATA_DI = -11;
    final public const DATA_TI = -12;
    /**
     * @param array<int|string, mixed> $data
     */
    public function __construct(array $data)
    {
        foreach ([self::TYPE] as $key) {
            if (is_numeric($data[$key])) {
                $data[$key] = (int) $data[$key];
            }
        }
        parent::__construct($data);
        if ($data[self::TYPE] !== self::TYPE_RSA && $data[self::TYPE] !== self::TYPE_NAME_RSA) {
            throw new InvalidArgumentException('Invalid RSA key. The key type does not correspond to a RSA key');
        }
        if (!isset($data[self::DATA_N], $data[self::DATA_E])) {
            throw new InvalidArgumentException('Invalid RSA key. The modulus or the exponent is missing');
        }
    }
    /**
     * @param array<int|string, mixed> $data
     */
    public static function create(array $data): self
    {
        return new self($data);
    }
    public function n(): string
    {
        return $this->get(self::DATA_N);
    }
    public function e(): string
    {
        return $this->get(self::DATA_E);
    }
    public function d(): string
    {
        $this->checkKeyIsPrivate();
        return $this->get(self::DATA_D);
    }
    public function p(): string
    {
        $this->checkKeyIsPrivate();
        return $this->get(self::DATA_P);
    }
    public function q(): string
    {
        $this->checkKeyIsPrivate();
        return $this->get(self::DATA_Q);
    }
    public function dP(): string
    {
        $this->checkKeyIsPrivate();
        return $this->get(self::DATA_DP);
    }
    public function dQ(): string
    {
        $this->checkKeyIsPrivate();
        return $this->get(self::DATA_DQ);
    }
    public function QInv(): string
    {
        $this->checkKeyIsPrivate();
        return $this->get(self::DATA_QI);
    }
    /**
     * @return array<mixed>
     */
    public function other(): array
    {
        $this->checkKeyIsPrivate();
        return $this->get(self::DATA_OTHER);
    }
    public function rI(): string
    {
        $this->checkKeyIsPrivate();
        return $this->get(self::DATA_RI);
    }
    public function dI(): string
    {
        $this->checkKeyIsPrivate();
        return $this->get(self::DATA_DI);
    }
    public function tI(): string
    {
        $this->checkKeyIsPrivate();
        return $this->get(self::DATA_TI);
    }
    public function hasPrimes(): bool
    {
        return $this->has(self::DATA_P) && $this->has(self::DATA_Q);
    }
    /**
     * @return string[]
     */
    public function primes(): array
    {
        return [$this->p(), $this->q()];
    }
    public function hasExponents(): bool
    {
        return $this->has(self::DATA_DP) && $this->has(self::DATA_DQ);
    }
    /**
     * @return string[]
     */
    public function exponents(): array
    {
        return [$this->dP(), $this->dQ()];
    }
    public function hasCoefficient(): bool
    {
        return $this->has(self::DATA_QI);
    }
    public function isPublic(): bool
    {
        return !$this->isPrivate();
    }
    public function isPrivate(): bool
    {
        return array_key_exists(self::DATA_D, $this->getData());
    }
    public function asPem(): string
    {
        if ($this->isPrivate()) {
            $privateKey = RSAPrivateKey::create($this->binaryToBigInteger($this->n()), $this->binaryToBigInteger($this->e()), $this->binaryToBigInteger($this->d()), $this->binaryToBigInteger($this->p()), $this->binaryToBigInteger($this->q()), $this->binaryToBigInteger($this->dP()), $this->binaryToBigInteger($this->dQ()), $this->binaryToBigInteger($this->QInv()));
            return $privateKey->toPEM()->string();
        }
        $publicKey = RSAPublicKey::create($this->binaryToBigInteger($this->n()), $this->binaryToBigInteger($this->e()));
        $rsaKey = PublicKeyInfo::fromPublicKey($publicKey);
        return $rsaKey->toPEM()->string();
    }
    public function toPublic(): static
    {
        $toBeRemoved = [self::DATA_D, self::DATA_P, self::DATA_Q, self::DATA_DP, self::DATA_DQ, self::DATA_QI, self::DATA_OTHER, self::DATA_RI, self::DATA_DI, self::DATA_TI];
        $data = $this->getData();
        foreach ($data as $k => $v) {
            if (in_array($k, $toBeRemoved, \true)) {
                unset($data[$k]);
            }
        }
        return new static($data);
    }
    private function checkKeyIsPrivate(): void
    {
        if (!$this->isPrivate()) {
            throw new InvalidArgumentException('The key is not private.');
        }
    }
    private function binaryToBigInteger(string $data): string
    {
        $res = unpack('H*', $data);
        /** @var non-empty-string $res */
        $res = current($res);
        return BigInteger::fromBase($res, 16)->toBase(10);
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\Cose\Key;

use InvalidArgumentException;
/**
 * @final
 */
class SymmetricKey extends Key
{
    final public const DATA_K = -1;
    /**
     * @param array<int|string, mixed> $data
     */
    public function __construct(array $data)
    {
        parent::__construct($data);
        if (!isset($data[self::TYPE]) || (int) $data[self::TYPE] !== self::TYPE_OCT) {
            throw new InvalidArgumentException('Invalid symmetric key. The key type does not correspond to a symmetric key');
        }
        if (!isset($data[self::DATA_K])) {
            throw new InvalidArgumentException('Invalid symmetric key. The parameter "k" is missing');
        }
    }
    /**
     * @param array<int|string, mixed> $data
     */
    public static function create(array $data): self
    {
        return new self($data);
    }
    public function k(): string
    {
        return $this->get(self::DATA_K);
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\Cose\Key;

use function array_key_exists;
use function in_array;
use InvalidArgumentException;
use function is_int;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Constructed\Sequence;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Primitive\BitString;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Primitive\Integer;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Primitive\ObjectIdentifier;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Primitive\OctetString;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Tagged\ExplicitlyTaggedType;
use function sprintf;
use function strlen;
/**
 * @final
 * @see \Cose\Tests\Key\Ec2KeyTest
 */
class Ec2Key extends Key
{
    final public const CURVE_P256 = 1;
    final public const CURVE_P256K = 8;
    final public const CURVE_P384 = 2;
    final public const CURVE_P521 = 3;
    final public const CURVE_NAME_P256 = 'P-256';
    final public const CURVE_NAME_P256K = 'P-256K';
    final public const CURVE_NAME_P384 = 'P-384';
    final public const CURVE_NAME_P521 = 'P-521';
    final public const DATA_CURVE = -1;
    final public const DATA_X = -2;
    final public const DATA_Y = -3;
    final public const DATA_D = -4;
    private const SUPPORTED_CURVES_INT = [self::CURVE_P256, self::CURVE_P256K, self::CURVE_P384, self::CURVE_P521];
    private const SUPPORTED_CURVES_NAMES = [self::CURVE_NAME_P256, self::CURVE_NAME_P256K, self::CURVE_NAME_P384, self::CURVE_NAME_P521];
    private const NAMED_CURVE_OID = [
        self::CURVE_P256 => '1.2.840.10045.3.1.7',
        // NIST P-256 / secp256r1
        self::CURVE_P256K => '1.3.132.0.10',
        // NIST P-256K / secp256k1
        self::CURVE_P384 => '1.3.132.0.34',
        // NIST P-384 / secp384r1
        self::CURVE_P521 => '1.3.132.0.35',
    ];
    private const CURVE_KEY_LENGTH = [self::CURVE_P256 => 32, self::CURVE_P256K => 32, self::CURVE_P384 => 48, self::CURVE_P521 => 66, self::CURVE_NAME_P256 => 32, self::CURVE_NAME_P256K => 32, self::CURVE_NAME_P384 => 48, self::CURVE_NAME_P521 => 66];
    /**
     * @param array<int|string, mixed> $data
     */
    public function __construct(array $data)
    {
        foreach ([self::DATA_CURVE, self::TYPE] as $key) {
            if (is_numeric($data[$key])) {
                $data[$key] = (int) $data[$key];
            }
        }
        parent::__construct($data);
        if ($data[self::TYPE] !== self::TYPE_EC2 && $data[self::TYPE] !== self::TYPE_NAME_EC2) {
            throw new InvalidArgumentException('Invalid EC2 key. The key type does not correspond to an EC2 key');
        }
        if (!isset($data[self::DATA_CURVE], $data[self::DATA_X], $data[self::DATA_Y])) {
            throw new InvalidArgumentException('Invalid EC2 key. The curve or the "x/y" coordinates are missing');
        }
        if (strlen((string) $data[self::DATA_X]) !== self::CURVE_KEY_LENGTH[$data[self::DATA_CURVE]]) {
            throw new InvalidArgumentException('Invalid length for x coordinate');
        }
        if (strlen((string) $data[self::DATA_Y]) !== self::CURVE_KEY_LENGTH[$data[self::DATA_CURVE]]) {
            throw new InvalidArgumentException('Invalid length for y coordinate');
        }
        if (is_int($data[self::DATA_CURVE])) {
            if (!in_array($data[self::DATA_CURVE], self::SUPPORTED_CURVES_INT, \true)) {
                throw new InvalidArgumentException('The curve is not supported');
            }
        } elseif (!in_array($data[self::DATA_CURVE], self::SUPPORTED_CURVES_NAMES, \true)) {
            throw new InvalidArgumentException('The curve is not supported');
        }
    }
    /**
     * @param array<int|string, mixed> $data
     */
    public static function create(array $data): self
    {
        return new self($data);
    }
    public function toPublic(): self
    {
        $data = $this->getData();
        unset($data[self::DATA_D]);
        return new self($data);
    }
    public function x(): string
    {
        return $this->get(self::DATA_X);
    }
    public function y(): string
    {
        return $this->get(self::DATA_Y);
    }
    public function isPrivate(): bool
    {
        return array_key_exists(self::DATA_D, $this->getData());
    }
    public function d(): string
    {
        if (!$this->isPrivate()) {
            throw new InvalidArgumentException('The key is not private.');
        }
        return $this->get(self::DATA_D);
    }
    public function curve(): int|string
    {
        return $this->get(self::DATA_CURVE);
    }
    public function asPEM(): string
    {
        if ($this->isPrivate()) {
            $der = Sequence::create(Integer::create(1), OctetString::create($this->d()), ExplicitlyTaggedType::create(0, ObjectIdentifier::create($this->getCurveOid())), ExplicitlyTaggedType::create(1, BitString::create($this->getUncompressedCoordinates())));
            return $this->pem('EC PRIVATE KEY', $der->toDER());
        }
        $der = Sequence::create(Sequence::create(ObjectIdentifier::create('1.2.840.10045.2.1'), ObjectIdentifier::create($this->getCurveOid())), BitString::create($this->getUncompressedCoordinates()));
        return $this->pem('PUBLIC KEY', $der->toDER());
    }
    public function getUncompressedCoordinates(): string
    {
        return "\x04" . $this->x() . $this->y();
    }
    private function getCurveOid(): string
    {
        return self::NAMED_CURVE_OID[$this->curve()];
    }
    private function pem(string $type, string $der): string
    {
        return sprintf("-----BEGIN %s-----\n", strtoupper($type)) . chunk_split(base64_encode($der), 64, "\n") . sprintf("-----END %s-----\n", strtoupper($type));
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\Cose\Key;

use function array_key_exists;
use function in_array;
use InvalidArgumentException;
/**
 * @final
 * @see \Cose\Tests\Key\OkpKeyTest
 */
class OkpKey extends Key
{
    final public const CURVE_X25519 = 4;
    final public const CURVE_X448 = 5;
    final public const CURVE_ED25519 = 6;
    final public const CURVE_ED448 = 7;
    final public const CURVE_NAME_X25519 = 'X25519';
    final public const CURVE_NAME_X448 = 'X448';
    final public const CURVE_NAME_ED25519 = 'Ed25519';
    final public const CURVE_NAME_ED448 = 'Ed448';
    final public const DATA_CURVE = -1;
    final public const DATA_X = -2;
    final public const DATA_D = -4;
    private const SUPPORTED_CURVES_INT = [self::CURVE_X25519, self::CURVE_X448, self::CURVE_ED25519, self::CURVE_ED448];
    private const SUPPORTED_CURVES_NAME = [self::CURVE_NAME_X25519, self::CURVE_NAME_X448, self::CURVE_NAME_ED25519, self::CURVE_NAME_ED448];
    /**
     * @param array<int|string, mixed> $data
     */
    public function __construct(array $data)
    {
        foreach ([self::DATA_CURVE, self::TYPE] as $key) {
            if (is_numeric($data[$key])) {
                $data[$key] = (int) $data[$key];
            }
        }
        parent::__construct($data);
        if ($data[self::TYPE] !== self::TYPE_OKP && $data[self::TYPE] !== self::TYPE_NAME_OKP) {
            throw new InvalidArgumentException('Invalid OKP key. The key type does not correspond to an OKP key');
        }
        if (!isset($data[self::DATA_CURVE], $data[self::DATA_X])) {
            throw new InvalidArgumentException('Invalid EC2 key. The curve or the "x" coordinate is missing');
        }
        if (is_numeric($data[self::DATA_CURVE])) {
            if (!in_array((int) $data[self::DATA_CURVE], self::SUPPORTED_CURVES_INT, \true)) {
                throw new InvalidArgumentException('The curve is not supported');
            }
        } elseif (!in_array($data[self::DATA_CURVE], self::SUPPORTED_CURVES_NAME, \true)) {
            throw new InvalidArgumentException('The curve is not supported');
        }
    }
    /**
     * @param array<int|string, mixed> $data
     */
    public static function create(array $data): self
    {
        return new self($data);
    }
    public function x(): string
    {
        return $this->get(self::DATA_X);
    }
    public function isPrivate(): bool
    {
        return array_key_exists(self::DATA_D, $this->getData());
    }
    public function d(): string
    {
        if (!$this->isPrivate()) {
            throw new InvalidArgumentException('The key is not private.');
        }
        return $this->get(self::DATA_D);
    }
    public function curve(): int|string
    {
        return $this->get(self::DATA_CURVE);
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\Cose\Algorithm;

use function array_key_exists;
use InvalidArgumentException;
use function sprintf;
final class ManagerFactory
{
    /**
     * @var array<string, Algorithm>
     */
    private array $algorithms = [];
    public static function create(): self
    {
        return new self();
    }
    public function add(string $alias, Algorithm $algorithm): self
    {
        $this->algorithms[$alias] = $algorithm;
        return $this;
    }
    /**
     * @return string[]
     */
    public function list(): iterable
    {
        yield from array_keys($this->algorithms);
    }
    /**
     * @return Algorithm[]
     */
    public function all(): iterable
    {
        yield from $this->algorithms;
    }
    public function generate(string ...$aliases): Manager
    {
        $manager = Manager::create();
        foreach ($aliases as $alias) {
            if (!array_key_exists($alias, $this->algorithms)) {
                throw new InvalidArgumentException(sprintf('The algorithm with alias "%s" is not supported', $alias));
            }
            $manager->add($this->algorithms[$alias]);
        }
        return $manager;
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\Cose\Algorithm\Signature\ECDSA;

use _ContaoManager\Cose\Key\Ec2Key;
use const OPENSSL_ALGO_SHA256;
final class ES256 extends ECDSA
{
    public const ID = -7;
    public static function create(): self
    {
        return new self();
    }
    public static function identifier(): int
    {
        return self::ID;
    }
    protected function getHashAlgorithm(): int
    {
        return OPENSSL_ALGO_SHA256;
    }
    protected function getCurve(): int
    {
        return Ec2Key::CURVE_P256;
    }
    protected function getSignaturePartLength(): int
    {
        return 64;
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\Cose\Algorithm\Signature\ECDSA;

use _ContaoManager\Cose\Algorithm\Signature\Signature;
use _ContaoManager\Cose\Key\Ec2Key;
use _ContaoManager\Cose\Key\Key;
use InvalidArgumentException;
use function openssl_sign;
use function openssl_verify;
/**
 * @see \Cose\Tests\Algorithm\Signature\ECDSA\ECDSATest
 */
abstract class ECDSA implements Signature
{
    public function sign(string $data, Key $key): string
    {
        $key = $this->handleKey($key);
        openssl_sign($data, $signature, $key->asPEM(), $this->getHashAlgorithm());
        return ECSignature::fromAsn1($signature, $this->getSignaturePartLength());
    }
    public function verify(string $data, Key $key, string $signature): bool
    {
        $key = $this->handleKey($key);
        $publicKey = $key->toPublic();
        $signature = ECSignature::toAsn1($signature, $this->getSignaturePartLength());
        return openssl_verify($data, $signature, $publicKey->asPEM(), $this->getHashAlgorithm()) === 1;
    }
    abstract protected function getCurve(): int;
    abstract protected function getHashAlgorithm(): int;
    abstract protected function getSignaturePartLength(): int;
    private function handleKey(Key $key): Ec2Key
    {
        $key = Ec2Key::create($key->getData());
        if ($key->curve() !== $this->getCurve()) {
            throw new InvalidArgumentException('This key cannot be used with this algorithm');
        }
        return $key;
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\Cose\Algorithm\Signature\ECDSA;

use _ContaoManager\Cose\Key\Ec2Key;
use const OPENSSL_ALGO_SHA384;
final class ES384 extends ECDSA
{
    public const ID = -35;
    public static function create(): self
    {
        return new self();
    }
    public static function identifier(): int
    {
        return self::ID;
    }
    protected function getHashAlgorithm(): int
    {
        return OPENSSL_ALGO_SHA384;
    }
    protected function getCurve(): int
    {
        return Ec2Key::CURVE_P384;
    }
    protected function getSignaturePartLength(): int
    {
        return 96;
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\Cose\Algorithm\Signature\ECDSA;

use function bin2hex;
use function dechex;
use function hex2bin;
use function hexdec;
use InvalidArgumentException;
use function str_pad;
use const STR_PAD_LEFT;
use function strlen;
use function substr;
/**
 * @internal
 */
final class ECSignature
{
    private const ASN1_SEQUENCE = '30';
    private const ASN1_INTEGER = '02';
    private const ASN1_MAX_SINGLE_BYTE = 128;
    private const ASN1_LENGTH_2BYTES = '81';
    private const ASN1_BIG_INTEGER_LIMIT = '7f';
    private const ASN1_NEGATIVE_INTEGER = '00';
    private const BYTE_SIZE = 2;
    public static function toAsn1(string $signature, int $length): string
    {
        $signature = bin2hex($signature);
        if (self::octetLength($signature) !== $length) {
            throw new InvalidArgumentException('Invalid signature length.');
        }
        $pointR = self::preparePositiveInteger(substr($signature, 0, $length));
        $pointS = self::preparePositiveInteger(substr($signature, $length));
        $lengthR = self::octetLength($pointR);
        $lengthS = self::octetLength($pointS);
        $totalLength = $lengthR + $lengthS + self::BYTE_SIZE + self::BYTE_SIZE;
        $lengthPrefix = $totalLength > self::ASN1_MAX_SINGLE_BYTE ? self::ASN1_LENGTH_2BYTES : '';
        return hex2bin(self::ASN1_SEQUENCE . $lengthPrefix . dechex($totalLength) . self::ASN1_INTEGER . dechex($lengthR) . $pointR . self::ASN1_INTEGER . dechex($lengthS) . $pointS);
    }
    public static function fromAsn1(string $signature, int $length): string
    {
        $message = bin2hex($signature);
        $position = 0;
        if (self::readAsn1Content($message, $position, self::BYTE_SIZE) !== self::ASN1_SEQUENCE) {
            throw new InvalidArgumentException('Invalid data. Should start with a sequence.');
        }
        if (self::readAsn1Content($message, $position, self::BYTE_SIZE) === self::ASN1_LENGTH_2BYTES) {
            $position += self::BYTE_SIZE;
        }
        $pointR = self::retrievePositiveInteger(self::readAsn1Integer($message, $position));
        $pointS = self::retrievePositiveInteger(self::readAsn1Integer($message, $position));
        return hex2bin(str_pad($pointR, $length, '0', STR_PAD_LEFT) . str_pad($pointS, $length, '0', STR_PAD_LEFT));
    }
    private static function octetLength(string $data): int
    {
        return intdiv(strlen($data), self::BYTE_SIZE);
    }
    private static function preparePositiveInteger(string $data): string
    {
        if (substr($data, 0, self::BYTE_SIZE) > self::ASN1_BIG_INTEGER_LIMIT) {
            return self::ASN1_NEGATIVE_INTEGER . $data;
        }
        while (str_starts_with($data, self::ASN1_NEGATIVE_INTEGER) && substr($data, 2, self::BYTE_SIZE) <= self::ASN1_BIG_INTEGER_LIMIT) {
            $data = substr($data, 2);
        }
        return $data;
    }
    private static function readAsn1Content(string $message, int &$position, int $length): string
    {
        $content = substr($message, $position, $length);
        $position += $length;
        return $content;
    }
    private static function readAsn1Integer(string $message, int &$position): string
    {
        if (self::readAsn1Content($message, $position, self::BYTE_SIZE) !== self::ASN1_INTEGER) {
            throw new InvalidArgumentException('Invalid data. Should contain an integer.');
        }
        $length = (int) hexdec(self::readAsn1Content($message, $position, self::BYTE_SIZE));
        return self::readAsn1Content($message, $position, $length * self::BYTE_SIZE);
    }
    private static function retrievePositiveInteger(string $data): string
    {
        while (str_starts_with($data, self::ASN1_NEGATIVE_INTEGER) && substr($data, 2, self::BYTE_SIZE) > self::ASN1_BIG_INTEGER_LIMIT) {
            $data = substr($data, 2);
        }
        return $data;
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\Cose\Algorithm\Signature\ECDSA;

use _ContaoManager\Cose\Key\Ec2Key;
use const OPENSSL_ALGO_SHA256;
final class ES256K extends ECDSA
{
    public const ID = -46;
    public static function create(): self
    {
        return new self();
    }
    public static function identifier(): int
    {
        return self::ID;
    }
    protected function getHashAlgorithm(): int
    {
        return OPENSSL_ALGO_SHA256;
    }
    protected function getCurve(): int
    {
        return Ec2Key::CURVE_P256K;
    }
    protected function getSignaturePartLength(): int
    {
        return 64;
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\Cose\Algorithm\Signature\ECDSA;

use _ContaoManager\Cose\Key\Ec2Key;
use const OPENSSL_ALGO_SHA512;
final class ES512 extends ECDSA
{
    public const ID = -36;
    public static function create(): self
    {
        return new self();
    }
    public static function identifier(): int
    {
        return self::ID;
    }
    protected function getHashAlgorithm(): int
    {
        return OPENSSL_ALGO_SHA512;
    }
    protected function getCurve(): int
    {
        return Ec2Key::CURVE_P521;
    }
    protected function getSignaturePartLength(): int
    {
        return 132;
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\Cose\Algorithm\Signature\RSA;

use const OPENSSL_ALGO_SHA1;
final class RS1 extends RSA
{
    public const ID = -65535;
    public static function create(): self
    {
        return new self();
    }
    public static function identifier(): int
    {
        return self::ID;
    }
    protected function getHashAlgorithm(): int
    {
        return OPENSSL_ALGO_SHA1;
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\Cose\Algorithm\Signature\RSA;

use _ContaoManager\Cose\Algorithm\Signature\Signature;
use _ContaoManager\Cose\Key\Key;
use _ContaoManager\Cose\Key\RsaKey;
use InvalidArgumentException;
use function openssl_sign;
use function openssl_verify;
use Throwable;
/**
 * @see \Cose\Tests\Algorithm\Signature\RSA\RSATest
 */
abstract class RSA implements Signature
{
    public function sign(string $data, Key $key): string
    {
        $key = $this->handleKey($key);
        if (!$key->isPrivate()) {
            throw new InvalidArgumentException('The key is not private.');
        }
        try {
            openssl_sign($data, $signature, $key->asPem(), $this->getHashAlgorithm());
        } catch (Throwable $e) {
            throw new InvalidArgumentException('Unable to sign the data', 0, $e);
        }
        return $signature;
    }
    public function verify(string $data, Key $key, string $signature): bool
    {
        $key = $this->handleKey($key);
        return openssl_verify($data, $signature, $key->toPublic()->asPem(), $this->getHashAlgorithm()) === 1;
    }
    abstract protected function getHashAlgorithm(): int;
    private function handleKey(Key $key): RsaKey
    {
        return RsaKey::create($key->getData());
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\Cose\Algorithm\Signature\RSA;

use const OPENSSL_ALGO_SHA384;
final class RS384 extends RSA
{
    public const ID = -258;
    public static function create(): self
    {
        return new self();
    }
    public static function identifier(): int
    {
        return self::ID;
    }
    protected function getHashAlgorithm(): int
    {
        return OPENSSL_ALGO_SHA384;
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\Cose\Algorithm\Signature\RSA;

use _ContaoManager\Cose\Hash;
final class PS256 extends PSSRSA
{
    public const ID = -37;
    public static function create(): self
    {
        return new self();
    }
    public static function identifier(): int
    {
        return self::ID;
    }
    protected function getHashAlgorithm(): Hash
    {
        return Hash::sha256();
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\Cose\Algorithm\Signature\RSA;

use _ContaoManager\Cose\Hash;
final class PS384 extends PSSRSA
{
    public const ID = -38;
    public static function create(): self
    {
        return new self();
    }
    public static function identifier(): int
    {
        return self::ID;
    }
    protected function getHashAlgorithm(): Hash
    {
        return Hash::sha384();
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\Cose\Algorithm\Signature\RSA;

use const OPENSSL_ALGO_SHA256;
final class RS256 extends RSA
{
    public const ID = -257;
    public static function create(): self
    {
        return new self();
    }
    public static function identifier(): int
    {
        return self::ID;
    }
    protected function getHashAlgorithm(): int
    {
        return OPENSSL_ALGO_SHA256;
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\Cose\Algorithm\Signature\RSA;

use const OPENSSL_ALGO_SHA512;
final class RS512 extends RSA
{
    public const ID = -259;
    public static function create(): self
    {
        return new self();
    }
    public static function identifier(): int
    {
        return self::ID;
    }
    protected function getHashAlgorithm(): int
    {
        return OPENSSL_ALGO_SHA512;
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\Cose\Algorithm\Signature\RSA;

use function ceil;
use function chr;
use _ContaoManager\Cose\Algorithm\Signature\Signature;
use _ContaoManager\Cose\BigInteger;
use _ContaoManager\Cose\Hash;
use _ContaoManager\Cose\Key\Key;
use _ContaoManager\Cose\Key\RsaKey;
use function hash_equals;
use InvalidArgumentException;
use function ord;
use function pack;
use function random_bytes;
use RuntimeException;
use function str_pad;
use const STR_PAD_LEFT;
use function str_repeat;
use function strlen;
/**
 * @internal
 */
abstract class PSSRSA implements Signature
{
    public function sign(string $data, Key $key): string
    {
        $key = $this->handleKey($key);
        $modulusLength = strlen($key->n());
        $em = $this->encodeEMSAPSS($data, 8 * $modulusLength - 1, $this->getHashAlgorithm());
        $message = BigInteger::createFromBinaryString($em);
        $signature = $this->exponentiate($key, $message);
        return $this->convertIntegerToOctetString($signature, $modulusLength);
    }
    public function verify(string $data, Key $key, string $signature): bool
    {
        $key = $this->handleKey($key);
        $modulusLength = strlen($key->n());
        if (strlen($signature) !== $modulusLength) {
            throw new InvalidArgumentException('Invalid modulus length');
        }
        $s2 = BigInteger::createFromBinaryString($signature);
        $m2 = $this->exponentiate($key, $s2);
        $em = $this->convertIntegerToOctetString($m2, $modulusLength);
        $modBits = 8 * $modulusLength;
        return $this->verifyEMSAPSS($data, $em, $modBits - 1, $this->getHashAlgorithm());
    }
    /**
     * Exponentiate with or without Chinese Remainder Theorem. Operation with primes 'p' and 'q' is appox. 2x faster.
     */
    public function exponentiate(RsaKey $key, BigInteger $c): BigInteger
    {
        if ($c->compare(BigInteger::createFromDecimal(0)) < 0 || $c->compare(BigInteger::createFromBinaryString($key->n())) > 0) {
            throw new RuntimeException();
        }
        if ($key->isPublic() || !$key->hasPrimes() || !$key->hasExponents() || !$key->hasCoefficient()) {
            return $c->modPow(BigInteger::createFromBinaryString($key->e()), BigInteger::createFromBinaryString($key->n()));
        }
        [$pS, $qS] = $key->primes();
        [$dPS, $dQS] = $key->exponents();
        $qInv = BigInteger::createFromBinaryString($key->QInv());
        $p = BigInteger::createFromBinaryString($pS);
        $q = BigInteger::createFromBinaryString($qS);
        $dP = BigInteger::createFromBinaryString($dPS);
        $dQ = BigInteger::createFromBinaryString($dQS);
        $m1 = $c->modPow($dP, $p);
        $m2 = $c->modPow($dQ, $q);
        $h = $qInv->multiply($m1->subtract($m2)->add($p))->mod($p);
        return $m2->add($h->multiply($q));
    }
    abstract protected function getHashAlgorithm(): Hash;
    private function handleKey(Key $key): RsaKey
    {
        return RsaKey::create($key->getData());
    }
    private function convertIntegerToOctetString(BigInteger $x, int $xLen): string
    {
        $xB = $x->toBytes();
        if (strlen($xB) > $xLen) {
            throw new RuntimeException('Unable to convert the integer');
        }
        return str_pad($xB, $xLen, chr(0), STR_PAD_LEFT);
    }
    /**
     * MGF1.
     */
    private function getMGF1(string $mgfSeed, int $maskLen, Hash $mgfHash): string
    {
        $t = '';
        $count = ceil($maskLen / $mgfHash->getLength());
        for ($i = 0; $i < $count; ++$i) {
            $c = pack('N', $i);
            $t .= $mgfHash->hash($mgfSeed . $c);
        }
        return substr($t, 0, $maskLen);
    }
    /**
     * EMSA-PSS-ENCODE.
     */
    private function encodeEMSAPSS(string $message, int $modulusLength, Hash $hash): string
    {
        $emLen = $modulusLength + 1 >> 3;
        $sLen = $hash->getLength();
        $mHash = $hash->hash($message);
        if ($emLen <= $hash->getLength() + $sLen + 2) {
            throw new RuntimeException();
        }
        $salt = random_bytes($sLen);
        $m2 = "\x00\x00\x00\x00\x00\x00\x00\x00" . $mHash . $salt;
        $h = $hash->hash($m2);
        $ps = str_repeat(chr(0), $emLen - $sLen - $hash->getLength() - 2);
        $db = $ps . chr(1) . $salt;
        $dbMask = $this->getMGF1($h, $emLen - $hash->getLength() - 1, $hash);
        $maskedDB = $db ^ $dbMask;
        $maskedDB[0] = ~chr(0xff << ($modulusLength & 7)) & $maskedDB[0];
        return $maskedDB . $h . chr(0xbc);
    }
    /**
     * EMSA-PSS-VERIFY.
     */
    private function verifyEMSAPSS(string $m, string $em, int $emBits, Hash $hash): bool
    {
        $emLen = $emBits + 1 >> 3;
        $sLen = $hash->getLength();
        $mHash = $hash->hash($m);
        if ($emLen < $hash->getLength() + $sLen + 2) {
            throw new InvalidArgumentException();
        }
        if ($em[strlen($em) - 1] !== chr(0xbc)) {
            throw new InvalidArgumentException();
        }
        $maskedDB = substr($em, 0, -$hash->getLength() - 1);
        $h = substr($em, -$hash->getLength() - 1, $hash->getLength());
        $temp = chr(0xff << ($emBits & 7));
        if ((~$maskedDB[0] & $temp) !== $temp) {
            throw new InvalidArgumentException();
        }
        $dbMask = $this->getMGF1($h, $emLen - $hash->getLength() - 1, $hash);
        $db = $maskedDB ^ $dbMask;
        $db[0] = ~chr(0xff << ($emBits & 7)) & $db[0];
        $temp = $emLen - $hash->getLength() - $sLen - 2;
        if (!str_starts_with($db, str_repeat(chr(0), $temp))) {
            throw new InvalidArgumentException();
        }
        if (ord($db[$temp]) !== 1) {
            throw new InvalidArgumentException();
        }
        $salt = substr($db, $temp + 1);
        // should be $sLen long
        $m2 = "\x00\x00\x00\x00\x00\x00\x00\x00" . $mHash . $salt;
        $h2 = $hash->hash($m2);
        return hash_equals($h, $h2);
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\Cose\Algorithm\Signature\RSA;

use _ContaoManager\Cose\Hash;
final class PS512 extends PSSRSA
{
    public const ID = -39;
    public static function create(): self
    {
        return new self();
    }
    public static function identifier(): int
    {
        return self::ID;
    }
    protected function getHashAlgorithm(): Hash
    {
        return Hash::sha512();
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\Cose\Algorithm\Signature\EdDSA;

use _ContaoManager\Cose\Key\Key;
final class Ed512 extends EdDSA
{
    public const ID = -261;
    public static function create(): self
    {
        return new self();
    }
    public static function identifier(): int
    {
        return self::ID;
    }
    public function sign(string $data, Key $key): string
    {
        $hashedData = hash('sha512', $data, \true);
        return parent::sign($hashedData, $key);
    }
    public function verify(string $data, Key $key, string $signature): bool
    {
        $hashedData = hash('sha512', $data, \true);
        return parent::verify($hashedData, $key, $signature);
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\Cose\Algorithm\Signature\EdDSA;

use _ContaoManager\Cose\Algorithm\Signature\Signature;
use _ContaoManager\Cose\Algorithms;
use _ContaoManager\Cose\Key\Key;
use _ContaoManager\Cose\Key\OkpKey;
use InvalidArgumentException;
use function sodium_crypto_sign_detached;
use function sodium_crypto_sign_verify_detached;
use Throwable;
/**
 * @see \Cose\Tests\Algorithm\Signature\EdDSA\EdDSATest
 */
class EdDSA implements Signature
{
    public function sign(string $data, Key $key): string
    {
        $key = $this->handleKey($key);
        if (!$key->isPrivate()) {
            throw new InvalidArgumentException('The key is not private.');
        }
        $x = $key->x();
        $d = $key->d();
        $secret = $d . $x;
        return match ($key->curve()) {
            OkpKey::CURVE_ED25519 => sodium_crypto_sign_detached($data, $secret),
            OkpKey::CURVE_NAME_ED25519 => sodium_crypto_sign_detached($data, $secret),
            default => throw new InvalidArgumentException('Unsupported curve'),
        };
    }
    public function verify(string $data, Key $key, string $signature): bool
    {
        $key = $this->handleKey($key);
        if ($key->curve() !== OkpKey::CURVE_ED25519 && $key->curve() !== OkpKey::CURVE_NAME_ED25519) {
            throw new InvalidArgumentException('Unsupported curve');
        }
        try {
            return sodium_crypto_sign_verify_detached($signature, $data, $key->x());
        } catch (Throwable) {
            return \false;
        }
    }
    public static function identifier(): int
    {
        return Algorithms::COSE_ALGORITHM_EDDSA;
    }
    private function handleKey(Key $key): OkpKey
    {
        return OkpKey::create($key->getData());
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\Cose\Algorithm\Signature\EdDSA;

use _ContaoManager\Cose\Key\Key;
final class Ed256 extends EdDSA
{
    public const ID = -260;
    public static function create(): self
    {
        return new self();
    }
    public static function identifier(): int
    {
        return self::ID;
    }
    public function sign(string $data, Key $key): string
    {
        $hashedData = hash('sha256', $data, \true);
        return parent::sign($hashedData, $key);
    }
    public function verify(string $data, Key $key, string $signature): bool
    {
        $hashedData = hash('sha256', $data, \true);
        return parent::verify($hashedData, $key, $signature);
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\Cose\Algorithm\Signature\EdDSA;

final class Ed25519 extends EdDSA
{
    public const ID = -8;
    public static function create(): self
    {
        return new self();
    }
    public static function identifier(): int
    {
        return self::ID;
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\Cose\Algorithm\Signature;

use _ContaoManager\Cose\Algorithm\Algorithm;
use _ContaoManager\Cose\Key\Key;
interface Signature extends Algorithm
{
    public function sign(string $data, Key $key): string;
    public function verify(string $data, Key $key, string $signature): bool;
}
<?php

declare (strict_types=1);
namespace _ContaoManager\Cose\Algorithm;

interface Algorithm
{
    public static function identifier(): int;
}
<?php

declare (strict_types=1);
namespace _ContaoManager\Cose\Algorithm\Mac;

final class HS512 extends Hmac
{
    public const ID = 7;
    public static function create(): self
    {
        return new self();
    }
    public static function identifier(): int
    {
        return self::ID;
    }
    protected function getHashAlgorithm(): string
    {
        return 'sha512';
    }
    protected function getSignatureLength(): int
    {
        return 512;
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\Cose\Algorithm\Mac;

use _ContaoManager\Cose\Key\Key;
use _ContaoManager\Cose\Key\SymmetricKey;
use InvalidArgumentException;
/**
 * @see \Cose\Tests\Algorithm\Mac\HmacTest
 */
abstract class Hmac implements Mac
{
    public function hash(string $data, Key $key): string
    {
        $this->checKey($key);
        $signature = hash_hmac($this->getHashAlgorithm(), $data, (string) $key->get(SymmetricKey::DATA_K), \true);
        return substr($signature, 0, intdiv($this->getSignatureLength(), 8));
    }
    public function verify(string $data, Key $key, string $signature): bool
    {
        return hash_equals($this->hash($data, $key), $signature);
    }
    abstract protected function getHashAlgorithm(): string;
    abstract protected function getSignatureLength(): int;
    private function checKey(Key $key): void
    {
        if ($key->type() !== Key::TYPE_OCT && $key->type() !== Key::TYPE_NAME_OCT) {
            throw new InvalidArgumentException('Invalid key. Must be of type symmetric');
        }
        if (!$key->has(SymmetricKey::DATA_K)) {
            throw new InvalidArgumentException('Invalid key. The value of the key is missing');
        }
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\Cose\Algorithm\Mac;

use _ContaoManager\Cose\Algorithm\Algorithm;
use _ContaoManager\Cose\Key\Key;
interface Mac extends Algorithm
{
    public function hash(string $data, Key $key): string;
    public function verify(string $data, Key $key, string $signature): bool;
}
<?php

declare (strict_types=1);
namespace _ContaoManager\Cose\Algorithm\Mac;

final class HS384 extends Hmac
{
    public const ID = 6;
    public static function create(): self
    {
        return new self();
    }
    public static function identifier(): int
    {
        return self::ID;
    }
    protected function getHashAlgorithm(): string
    {
        return 'sha384';
    }
    protected function getSignatureLength(): int
    {
        return 384;
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\Cose\Algorithm\Mac;

final class HS256Truncated64 extends Hmac
{
    public const ID = 4;
    public static function create(): self
    {
        return new self();
    }
    public static function identifier(): int
    {
        return self::ID;
    }
    protected function getHashAlgorithm(): string
    {
        return 'sha256';
    }
    protected function getSignatureLength(): int
    {
        return 64;
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\Cose\Algorithm\Mac;

final class HS256 extends Hmac
{
    public const ID = 5;
    public static function create(): self
    {
        return new self();
    }
    public static function identifier(): int
    {
        return self::ID;
    }
    protected function getHashAlgorithm(): string
    {
        return 'sha256';
    }
    protected function getSignatureLength(): int
    {
        return 256;
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\Cose\Algorithm;

use function array_key_exists;
use InvalidArgumentException;
final class Manager
{
    /**
     * @var array<int, Algorithm>
     */
    private array $algorithms = [];
    public static function create(): self
    {
        return new self();
    }
    public function add(Algorithm ...$algorithms): self
    {
        foreach ($algorithms as $algorithm) {
            $identifier = $algorithm::identifier();
            $this->algorithms[$identifier] = $algorithm;
        }
        return $this;
    }
    /**
     * @return iterable<int>
     */
    public function list(): iterable
    {
        yield from array_keys($this->algorithms);
    }
    /**
     * @return iterable<int, Algorithm>
     */
    public function all(): iterable
    {
        yield from $this->algorithms;
    }
    public function has(int $identifier): bool
    {
        return array_key_exists($identifier, $this->algorithms);
    }
    public function get(int $identifier): Algorithm
    {
        if (!$this->has($identifier)) {
            throw new InvalidArgumentException('Unsupported algorithm');
        }
        return $this->algorithms[$identifier];
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\Cose;

use _ContaoManager\Brick\Math\BigInteger as BrickBigInteger;
use function chr;
use function hex2bin;
use function strlen;
use function unpack;
/**
 * @internal
 */
final class BigInteger
{
    private function __construct(private readonly BrickBigInteger $value)
    {
    }
    public static function createFromBinaryString(string $value): self
    {
        $res = unpack('H*', $value);
        /** @var non-empty-string $data */
        $data = current($res);
        return new self(BrickBigInteger::fromBase($data, 16));
    }
    public static function createFromDecimal(int $value): self
    {
        return new self(BrickBigInteger::of($value));
    }
    /**
     * Converts a BigInteger to a binary string.
     */
    public function toBytes(): string
    {
        if ($this->value->isEqualTo(BrickBigInteger::zero())) {
            return '';
        }
        $temp = $this->value->toBase(16);
        $temp = 0 !== (strlen($temp) & 1) ? '0' . $temp : $temp;
        $temp = hex2bin($temp);
        return ltrim($temp, chr(0));
    }
    /**
     * Adds two BigIntegers.
     */
    public function add(self $y): self
    {
        $value = $this->value->plus($y->value);
        return new self($value);
    }
    /**
     * Subtracts two BigIntegers.
     */
    public function subtract(self $y): self
    {
        $value = $this->value->minus($y->value);
        return new self($value);
    }
    /**
     * Multiplies two BigIntegers.
     */
    public function multiply(self $x): self
    {
        $value = $this->value->multipliedBy($x->value);
        return new self($value);
    }
    /**
     * Performs modular exponentiation.
     */
    public function modPow(self $e, self $n): self
    {
        $value = $this->value->modPow($e->value, $n->value);
        return new self($value);
    }
    /**
     * Performs modular exponentiation.
     */
    public function mod(self $d): self
    {
        $value = $this->value->mod($d->value);
        return new self($value);
    }
    /**
     * Compares two numbers.
     */
    public function compare(self $y): int
    {
        return $this->value->compareTo($y->value);
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\Cose\Mac;

use _ContaoManager\CBOR\ByteStringObject;
use _ContaoManager\CBOR\CBORObject;
use _ContaoManager\CBOR\Decoder;
use _ContaoManager\CBOR\ListObject;
use _ContaoManager\CBOR\MapObject;
use _ContaoManager\CBOR\OtherObject\OtherObjectManager;
use _ContaoManager\CBOR\StringStream;
use _ContaoManager\CBOR\Tag;
use _ContaoManager\CBOR\Tag\TagManager;
use InvalidArgumentException;
final class CoseMac0Tag extends Tag
{
    private const TAG_ID = 17;
    private readonly ByteStringObject $protectedHeader;
    private readonly MapObject $unprotectedHeader;
    private readonly ByteStringObject $payload;
    private readonly ByteStringObject $tag;
    public function __construct(int $additionalInformation, ?string $data, CBORObject $object)
    {
        if (!$object instanceof ListObject) {
            throw new InvalidArgumentException('Not a valid CoseMac0 object. No list.');
        }
        if ($object->count() !== 4) {
            throw new InvalidArgumentException('Not a valid CoseMac0 object. The list shall have 4 items.');
        }
        $protectedHeader = $object->get(0);
        $unprotectedHeader = $object->get(1);
        $payload = $object->get(2);
        $tag = $object->get(3);
        if (!$protectedHeader instanceof ByteStringObject) {
            throw new InvalidArgumentException('Not a valid CoseMac0 object. The item 1 shall be a ByteString object.');
        }
        if (!$unprotectedHeader instanceof MapObject) {
            throw new InvalidArgumentException('Not a valid CoseMac0 object. The item 2 shall be a Map object.');
        }
        if (!$payload instanceof ByteStringObject) {
            throw new InvalidArgumentException('Not a valid CoseMac0 object. The item 3 shall be a ByteString object.');
        }
        if (!$tag instanceof ByteStringObject) {
            throw new InvalidArgumentException('Not a valid CoseMac0 object. The item 4 shall be a ByteString object.');
        }
        parent::__construct($additionalInformation, $data, $object);
        $this->protectedHeader = $protectedHeader;
        $this->unprotectedHeader = $unprotectedHeader;
        $this->payload = $payload;
        $this->tag = $tag;
    }
    public static function getTagId(): int
    {
        return self::TAG_ID;
    }
    public static function createFromLoadedData(int $additionalInformation, ?string $data, CBORObject $object): self
    {
        return new self($additionalInformation, $data, $object);
    }
    public static function create(MapObject $protectedHeader, MapObject $unprotectedHeader, ByteStringObject $payload, ByteStringObject $tag): self
    {
        $protectedHeaderAsBytesString = ByteStringObject::create((string) $protectedHeader);
        $object = ListObject::create([$protectedHeaderAsBytesString, $unprotectedHeader, $payload, $tag]);
        [$additionalInformation, $data] = self::determineComponents(self::TAG_ID);
        return new self($additionalInformation, $data, $object);
    }
    public function getProtectedHeader(): ByteStringObject
    {
        return $this->protectedHeader;
    }
    public function getProtectedHeaderAsMap(?Decoder $decoder = null): MapObject
    {
        $stream = new StringStream($this->protectedHeader->getValue());
        $decoder ??= Decoder::create(TagManager::create(), OtherObjectManager::create());
        $decoded = $decoder->decode($stream);
        if (!$decoded instanceof MapObject) {
            throw new InvalidArgumentException('Protected header is not a valid Map object.');
        }
        return $decoded;
    }
    public function getUnprotectedHeader(): MapObject
    {
        return $this->unprotectedHeader;
    }
    public function getPayload(): ByteStringObject
    {
        return $this->payload;
    }
    public function getTag(): ByteStringObject
    {
        return $this->tag;
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\Cose\Mac;

use _ContaoManager\CBOR\ByteStringObject;
use _ContaoManager\CBOR\CBORObject;
use _ContaoManager\CBOR\Decoder;
use _ContaoManager\CBOR\ListObject;
use _ContaoManager\CBOR\MapObject;
use _ContaoManager\CBOR\OtherObject\OtherObjectManager;
use _ContaoManager\CBOR\StringStream;
use _ContaoManager\CBOR\Tag;
use _ContaoManager\CBOR\Tag\TagManager;
use InvalidArgumentException;
final class CoseMacTag extends Tag
{
    private const TAG_ID = 97;
    private readonly ByteStringObject $protectedHeader;
    private readonly MapObject $unprotectedHeader;
    private readonly ByteStringObject $payload;
    private readonly ByteStringObject $tag;
    private readonly ListObject $recipients;
    public function __construct(int $additionalInformation, ?string $data, CBORObject $object)
    {
        if (!$object instanceof ListObject) {
            throw new InvalidArgumentException('Not a valid CoseMac object. No list.');
        }
        if ($object->count() !== 5) {
            throw new InvalidArgumentException('Not a valid CoseMac object. The list shall have 5 items.');
        }
        $protectedHeader = $object->get(0);
        $unprotectedHeader = $object->get(1);
        $payload = $object->get(2);
        $tag = $object->get(3);
        $recipients = $object->get(4);
        if (!$protectedHeader instanceof ByteStringObject) {
            throw new InvalidArgumentException('Not a valid CoseMac object. The item 1 shall be a ByteString object.');
        }
        if (!$unprotectedHeader instanceof MapObject) {
            throw new InvalidArgumentException('Not a valid CoseMac object. The item 2 shall be a Map object.');
        }
        if (!$payload instanceof ByteStringObject) {
            throw new InvalidArgumentException('Not a valid CoseMac object. The item 3 shall be a ByteString object.');
        }
        if (!$tag instanceof ByteStringObject) {
            throw new InvalidArgumentException('Not a valid CoseMac object. The item 4 shall be a ByteString object.');
        }
        if (!$recipients instanceof ListObject) {
            throw new InvalidArgumentException('Not a valid CoseMac object. The item 5 shall be a List object.');
        }
        parent::__construct($additionalInformation, $data, $object);
        $this->protectedHeader = $protectedHeader;
        $this->unprotectedHeader = $unprotectedHeader;
        $this->payload = $payload;
        $this->tag = $tag;
        $this->recipients = $recipients;
    }
    public static function getTagId(): int
    {
        return self::TAG_ID;
    }
    public static function createFromLoadedData(int $additionalInformation, ?string $data, CBORObject $object): self
    {
        return new self($additionalInformation, $data, $object);
    }
    public static function create(MapObject $protectedHeader, MapObject $unprotectedHeader, ByteStringObject $payload, ByteStringObject $tag, ListObject $recipients): self
    {
        $protectedHeaderAsBytesString = ByteStringObject::create((string) $protectedHeader);
        $object = ListObject::create([$protectedHeaderAsBytesString, $unprotectedHeader, $payload, $tag, $recipients]);
        [$additionalInformation, $data] = self::determineComponents(self::TAG_ID);
        return new self($additionalInformation, $data, $object);
    }
    public function getProtectedHeader(): ByteStringObject
    {
        return $this->protectedHeader;
    }
    public function getProtectedHeaderAsMap(?Decoder $decoder = null): MapObject
    {
        $stream = new StringStream($this->protectedHeader->getValue());
        $decoder ??= Decoder::create(TagManager::create(), OtherObjectManager::create());
        $decoded = $decoder->decode($stream);
        if (!$decoded instanceof MapObject) {
            throw new InvalidArgumentException('Protected header is not a valid Map object.');
        }
        return $decoded;
    }
    public function getUnprotectedHeader(): MapObject
    {
        return $this->unprotectedHeader;
    }
    public function getPayload(): ByteStringObject
    {
        return $this->payload;
    }
    public function getTag(): ByteStringObject
    {
        return $this->tag;
    }
    public function getRecipients(): ListObject
    {
        return $this->recipients;
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\Cose;

use function array_key_exists;
use InvalidArgumentException;
use const OPENSSL_ALGO_SHA1;
use const OPENSSL_ALGO_SHA256;
use const OPENSSL_ALGO_SHA384;
use const OPENSSL_ALGO_SHA512;
/**
 * @see https://www.iana.org/assignments/cose/cose.xhtml#algorithms
 */
abstract class Algorithms
{
    final public const COSE_ALGORITHM_AES_CCM_64_128_256 = 33;
    final public const COSE_ALGORITHM_AES_CCM_64_128_128 = 32;
    final public const COSE_ALGORITHM_AES_CCM_16_128_256 = 31;
    final public const COSE_ALGORITHM_AES_CCM_16_128_128 = 30;
    final public const COSE_ALGORITHM_AES_MAC_256_128 = 26;
    final public const COSE_ALGORITHM_AES_MAC_128_128 = 25;
    final public const COSE_ALGORITHM_CHACHA20_POLY1305 = 24;
    final public const COSE_ALGORITHM_AES_MAC_256_64 = 15;
    final public const COSE_ALGORITHM_AES_MAC_128_64 = 14;
    final public const COSE_ALGORITHM_AES_CCM_64_64_256 = 13;
    final public const COSE_ALGORITHM_AES_CCM_64_64_128 = 12;
    final public const COSE_ALGORITHM_AES_CCM_16_64_256 = 11;
    final public const COSE_ALGORITHM_AES_CCM_16_64_128 = 10;
    final public const COSE_ALGORITHM_HS512 = 7;
    final public const COSE_ALGORITHM_HS384 = 6;
    final public const COSE_ALGORITHM_HS256 = 5;
    final public const COSE_ALGORITHM_HS256_64 = 4;
    final public const COSE_ALGORITHM_A256GCM = 3;
    final public const COSE_ALGORITHM_A192GCM = 2;
    final public const COSE_ALGORITHM_A128GCM = 1;
    final public const COSE_ALGORITHM_A128KW = -3;
    final public const COSE_ALGORITHM_A192KW = -4;
    final public const COSE_ALGORITHM_A256KW = -5;
    final public const COSE_ALGORITHM_DIRECT = -6;
    final public const COSE_ALGORITHM_ES256 = -7;
    /**
     * @deprecated since v4.0.6. Please use COSE_ALGORITHM_EDDSA instead. Will be removed in v5.0.0
     */
    final public const COSE_ALGORITHM_EdDSA = -8;
    final public const COSE_ALGORITHM_EDDSA = -8;
    final public const COSE_ALGORITHM_ED256 = -260;
    final public const COSE_ALGORITHM_ED512 = -261;
    final public const COSE_ALGORITHM_DIRECT_HKDF_SHA_256 = -10;
    final public const COSE_ALGORITHM_DIRECT_HKDF_SHA_512 = -11;
    final public const COSE_ALGORITHM_DIRECT_HKDF_AES_128 = -12;
    final public const COSE_ALGORITHM_DIRECT_HKDF_AES_256 = -13;
    final public const COSE_ALGORITHM_ECDH_ES_HKDF_256 = -25;
    final public const COSE_ALGORITHM_ECDH_ES_HKDF_512 = -26;
    final public const COSE_ALGORITHM_ECDH_SS_HKDF_256 = -27;
    final public const COSE_ALGORITHM_ECDH_SS_HKDF_512 = -28;
    final public const COSE_ALGORITHM_ECDH_ES_A128KW = -29;
    final public const COSE_ALGORITHM_ECDH_ES_A192KW = -30;
    final public const COSE_ALGORITHM_ECDH_ES_A256KW = -31;
    final public const COSE_ALGORITHM_ECDH_SS_A128KW = -32;
    final public const COSE_ALGORITHM_ECDH_SS_A192KW = -33;
    final public const COSE_ALGORITHM_ECDH_SS_A256KW = -34;
    final public const COSE_ALGORITHM_ES384 = -35;
    final public const COSE_ALGORITHM_ES512 = -36;
    final public const COSE_ALGORITHM_PS256 = -37;
    final public const COSE_ALGORITHM_PS384 = -38;
    final public const COSE_ALGORITHM_PS512 = -39;
    final public const COSE_ALGORITHM_RSAES_OAEP = -40;
    final public const COSE_ALGORITHM_RSAES_OAEP_256 = -41;
    final public const COSE_ALGORITHM_RSAES_OAEP_512 = -42;
    final public const COSE_ALGORITHM_ES256K = -47;
    final public const COSE_ALGORITHM_RS256 = -257;
    final public const COSE_ALGORITHM_RS384 = -258;
    final public const COSE_ALGORITHM_RS512 = -259;
    final public const COSE_ALGORITHM_RS1 = -65535;
    final public const COSE_ALGORITHM_MAP = [self::COSE_ALGORITHM_ES256 => OPENSSL_ALGO_SHA256, self::COSE_ALGORITHM_ES384 => OPENSSL_ALGO_SHA384, self::COSE_ALGORITHM_ES512 => OPENSSL_ALGO_SHA512, self::COSE_ALGORITHM_RS256 => OPENSSL_ALGO_SHA256, self::COSE_ALGORITHM_RS384 => OPENSSL_ALGO_SHA384, self::COSE_ALGORITHM_RS512 => OPENSSL_ALGO_SHA512, self::COSE_ALGORITHM_RS1 => OPENSSL_ALGO_SHA1];
    final public const COSE_HASH_MAP = [self::COSE_ALGORITHM_ES256K => 'sha256', self::COSE_ALGORITHM_ES256 => 'sha256', self::COSE_ALGORITHM_ES384 => 'sha384', self::COSE_ALGORITHM_ES512 => 'sha512', self::COSE_ALGORITHM_RS256 => 'sha256', self::COSE_ALGORITHM_RS384 => 'sha384', self::COSE_ALGORITHM_RS512 => 'sha512', self::COSE_ALGORITHM_PS256 => 'sha256', self::COSE_ALGORITHM_PS384 => 'sha384', self::COSE_ALGORITHM_PS512 => 'sha512', self::COSE_ALGORITHM_RS1 => 'sha1'];
    public static function getOpensslAlgorithmFor(int $algorithmIdentifier): int
    {
        if (!array_key_exists($algorithmIdentifier, self::COSE_ALGORITHM_MAP)) {
            throw new InvalidArgumentException('The specified algorithm identifier is not supported');
        }
        return self::COSE_ALGORITHM_MAP[$algorithmIdentifier];
    }
    public static function getHashAlgorithmFor(int $algorithmIdentifier): string
    {
        if (!array_key_exists($algorithmIdentifier, self::COSE_HASH_MAP)) {
            throw new InvalidArgumentException('The specified algorithm identifier is not supported');
        }
        return self::COSE_HASH_MAP[$algorithmIdentifier];
    }
}
<?php

// autoload_namespaces.php @generated by Composer

$vendorDir = dirname(__DIR__);
$baseDir = dirname($vendorDir);

return array(
);
MIT License

Copyright (c) 2017 Composer

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
## [Unreleased]

## [3.0.5] - 2024-05-06
  * Fixed: fail restart if PHP_BINARY is not available

## [3.0.4] - 2024-03-26
  * Added: Functional tests.
  * Fixed: Incompatibility with PHPUnit 10.

## [3.0.3] - 2022-02-25
  * Added: support for composer/pcre versions 2 and 3.

## [3.0.2] - 2022-02-24
  * Fixed: regression in 3.0.1 affecting Xdebug 2

## [3.0.1] - 2022-01-04
  * Fixed: error when calling `isXdebugActive` before class instantiation.

## [3.0.0] - 2021-12-23
  * Removed: support for legacy PHP versions (< PHP 7.2.5).
  * Added: type declarations to arguments and return values.
  * Added: strict typing to all classes.

## [2.0.3] - 2021-12-08
  * Added: support, type annotations and refactoring for stricter PHPStan analysis.

## [2.0.2] - 2021-07-31
  * Added: support for `xdebug_info('mode')` in Xdebug 3.1.
  * Added: support for Psr\Log versions 2 and 3.
  * Fixed: remove ini directives from non-cli HOST/PATH sections.

## [2.0.1] - 2021-05-05
  * Fixed: don't restart if the cwd is a UNC path and cmd.exe will be invoked.

## [2.0.0] - 2021-04-09
  * Break: this is a major release, see [UPGRADE.md](UPGRADE.md) for more information.
  * Break: removed optional `$colorOption` constructor param and passthru fallback.
  * Break: renamed `requiresRestart` param from `$isLoaded` to `$default`.
  * Break: changed `restart` param `$command` from a string to an array.
  * Added: support for Xdebug3 to only restart if Xdebug is not running with `xdebug.mode=off`.
  * Added: `isXdebugActive()` method to determine if Xdebug is still running in the restart.
  * Added: feature to bypass the shell in PHP-7.4+ by giving `proc_open` an array of arguments.
  * Added: Process utility class to the API.

## [1.4.6] - 2021-03-25
  * Fixed: fail restart if `proc_open` has been disabled in `disable_functions`.
  * Fixed: enable Windows CTRL event handling in the restarted process.

## [1.4.5] - 2020-11-13
  * Fixed: use `proc_open` when available for correct FD forwarding to the restarted process.

## [1.4.4] - 2020-10-24
  * Fixed: exception if 'pcntl_signal' is disabled.

## [1.4.3] - 2020-08-19
  * Fixed: restore SIGINT to default handler in restarted process if no other handler exists.

## [1.4.2] - 2020-06-04
  * Fixed: ignore SIGINTs to let the restarted process handle them.

## [1.4.1] - 2020-03-01
  * Fixed: restart fails if an ini file is empty.

## [1.4.0] - 2019-11-06
  * Added: support for `NO_COLOR` environment variable: https://no-color.org
  * Added: color support for Hyper terminal: https://github.com/zeit/hyper
  * Fixed: correct capitalization of Xdebug (apparently).
  * Fixed: improved handling for uopz extension.

## [1.3.3] - 2019-05-27
  * Fixed: add environment changes to `$_ENV` if it is being used.

## [1.3.2] - 2019-01-28
  * Fixed: exit call being blocked by uopz extension, resulting in application code running twice.

## [1.3.1] - 2018-11-29
  * Fixed: fail restart if `passthru` has been disabled in `disable_functions`.
  * Fixed: fail restart if an ini file cannot be opened, otherwise settings will be missing.

## [1.3.0] - 2018-08-31
  * Added: `setPersistent` method to use environment variables for the restart.
  * Fixed: improved debugging by writing output to stderr.
  * Fixed: no restart when `php_ini_scanned_files` is not functional and is needed.

## [1.2.1] - 2018-08-23
  * Fixed: fatal error with apc, when using `apc.mmap_file_mask`.

## [1.2.0] - 2018-08-16
  * Added: debug information using `XDEBUG_HANDLER_DEBUG`.
  * Added: fluent interface for setters.
  * Added: `PhpConfig` helper class for calling PHP sub-processes.
  * Added: `PHPRC` original value to restart stettings, for use in a restarted process.
  * Changed: internal procedure to disable ini-scanning, using `-n` command-line option.
  * Fixed: replaced `escapeshellarg` usage to avoid locale problems.
  * Fixed: improved color-option handling to respect double-dash delimiter.
  * Fixed: color-option handling regression from main script changes.
  * Fixed: improved handling when checking main script.
  * Fixed: handling for standard input, that never actually did anything.
  * Fixed: fatal error when ctype extension is not available.

## [1.1.0] - 2018-04-11
  * Added: `getRestartSettings` method for calling PHP processes in a restarted process.
  * Added: API definition and @internal class annotations.
  * Added: protected `requiresRestart` method for extending classes.
  * Added: `setMainScript` method for applications that change the working directory.
  * Changed: private `tmpIni` variable to protected for extending classes.
  * Fixed: environment variables not available in $_SERVER when restored in the restart.
  * Fixed: relative path problems caused by Phar::interceptFileFuncs.
  * Fixed: incorrect handling when script file cannot be found.

## [1.0.0] - 2018-03-08
  * Added: PSR3 logging for optional status output.
  * Added: existing ini settings are merged to catch command-line overrides.
  * Added: code, tests and other artefacts to decouple from Composer.
  * Break: the following class was renamed:
    - `Composer\XdebugHandler` -> `Composer\XdebugHandler\XdebugHandler`

[Unreleased]: https://github.com/composer/xdebug-handler/compare/3.0.5...HEAD
[3.0.5]: https://github.com/composer/xdebug-handler/compare/3.0.4...3.0.5
[3.0.4]: https://github.com/composer/xdebug-handler/compare/3.0.3...3.0.4
[3.0.3]: https://github.com/composer/xdebug-handler/compare/3.0.2...3.0.3
[3.0.2]: https://github.com/composer/xdebug-handler/compare/3.0.1...3.0.2
[3.0.1]: https://github.com/composer/xdebug-handler/compare/3.0.0...3.0.1
[3.0.0]: https://github.com/composer/xdebug-handler/compare/2.0.3...3.0.0
[2.0.3]: https://github.com/composer/xdebug-handler/compare/2.0.2...2.0.3
[2.0.2]: https://github.com/composer/xdebug-handler/compare/2.0.1...2.0.2
[2.0.1]: https://github.com/composer/xdebug-handler/compare/2.0.0...2.0.1
[2.0.0]: https://github.com/composer/xdebug-handler/compare/1.4.6...2.0.0
[1.4.6]: https://github.com/composer/xdebug-handler/compare/1.4.5...1.4.6
[1.4.5]: https://github.com/composer/xdebug-handler/compare/1.4.4...1.4.5
[1.4.4]: https://github.com/composer/xdebug-handler/compare/1.4.3...1.4.4
[1.4.3]: https://github.com/composer/xdebug-handler/compare/1.4.2...1.4.3
[1.4.2]: https://github.com/composer/xdebug-handler/compare/1.4.1...1.4.2
[1.4.1]: https://github.com/composer/xdebug-handler/compare/1.4.0...1.4.1
[1.4.0]: https://github.com/composer/xdebug-handler/compare/1.3.3...1.4.0
[1.3.3]: https://github.com/composer/xdebug-handler/compare/1.3.2...1.3.3
[1.3.2]: https://github.com/composer/xdebug-handler/compare/1.3.1...1.3.2
[1.3.1]: https://github.com/composer/xdebug-handler/compare/1.3.0...1.3.1
[1.3.0]: https://github.com/composer/xdebug-handler/compare/1.2.1...1.3.0
[1.2.1]: https://github.com/composer/xdebug-handler/compare/1.2.0...1.2.1
[1.2.0]: https://github.com/composer/xdebug-handler/compare/1.1.0...1.2.0
[1.1.0]: https://github.com/composer/xdebug-handler/compare/1.0.0...1.1.0
[1.0.0]: https://github.com/composer/xdebug-handler/compare/d66f0d15cb57...1.0.0
# composer/xdebug-handler

[![packagist](https://img.shields.io/packagist/v/composer/xdebug-handler)](https://packagist.org/packages/composer/xdebug-handler)
[![Continuous Integration](https://github.com/composer/xdebug-handler/actions/workflows/continuous-integration.yml/badge.svg?branch=main)](https://github.com/composer/xdebug-handler/actions?query=branch:main)
![license](https://img.shields.io/github/license/composer/xdebug-handler.svg)
![php](https://img.shields.io/packagist/php-v/composer/xdebug-handler?colorB=8892BF)

Restart a CLI process without loading the Xdebug extension, unless `xdebug.mode=off`.

Originally written as part of [composer/composer](https://github.com/composer/composer),
now extracted and made available as a stand-alone library.

### Version 3

Removed support for legacy PHP versions and added type declarations.

Long term support for version 2 (PHP 5.3.2 - 7.2.4) follows [Composer 2.2 LTS](https://blog.packagist.com/composer-2-2/) policy.

## Installation

Install the latest version with:

```bash
$ composer require composer/xdebug-handler
```

## Requirements

* PHP 7.2.5 minimum, although using the latest PHP version is highly recommended.

## Basic Usage
```php
use Composer\XdebugHandler\XdebugHandler;

$xdebug = new XdebugHandler('myapp');
$xdebug->check();
unset($xdebug);
```

The constructor takes a single parameter, `$envPrefix`, which is upper-cased and prepended to default base values to create two distinct environment variables. The above example enables the use of:

- `MYAPP_ALLOW_XDEBUG=1` to override automatic restart and allow Xdebug
- `MYAPP_ORIGINAL_INIS` to obtain ini file locations in a restarted process

## Advanced Usage

* [How it works](#how-it-works)
* [Limitations](#limitations)
* [Helper methods](#helper-methods)
* [Setter methods](#setter-methods)
* [Process configuration](#process-configuration)
* [Troubleshooting](#troubleshooting)
* [Extending the library](#extending-the-library)
* [Examples](#examples)

### How it works

A temporary ini file is created from the loaded (and scanned) ini files, with any references to the Xdebug extension commented out. Current ini settings are merged, so that most ini settings made on the command-line or by the application are included (see [Limitations](#limitations))

* `MYAPP_ALLOW_XDEBUG` is set with internal data to flag and use in the restart.
* The command-line and environment are [configured](#process-configuration) for the restart.
* The application is restarted in a new process.
    * The restart settings are stored in the environment.
    * `MYAPP_ALLOW_XDEBUG` is unset.
    * The application runs and exits.
* The main process exits with the exit code from the restarted process.

See [Examples](#examples) for further information.

#### Signal handling
Asynchronous signal handling is automatically enabled if the pcntl extension is loaded. `SIGINT` is set to `SIG_IGN` in the parent
process and restored to `SIG_DFL` in the restarted process (if no other handler has been set).

From PHP 7.4 on Windows, `CTRL+C` and `CTRL+BREAK` handling is automatically enabled in the restarted process and ignored in the parent process.

### Limitations
There are a few things to be aware of when running inside a restarted process.

* Extensions set on the command-line will not be loaded.
* Ini file locations will be reported as per the restart - see [getAllIniFiles()](#getallinifiles-array).
* Php sub-processes may be loaded with Xdebug enabled - see [Process configuration](#process-configuration).

### Helper methods
These static methods provide information from the current process, regardless of whether it has been restarted or not.

#### _getAllIniFiles(): array_
Returns an array of the original ini file locations. Use this instead of calling `php_ini_loaded_file` and `php_ini_scanned_files`, which will report the wrong values in a restarted process.

```php
use Composer\XdebugHandler\XdebugHandler;

$files = XdebugHandler::getAllIniFiles();

# $files[0] always exists, it could be an empty string
$loadedIni = array_shift($files);
$scannedInis = $files;
```

These locations are also available in the `MYAPP_ORIGINAL_INIS` environment variable. This is a path-separated string comprising the location returned from `php_ini_loaded_file`, which could be empty, followed by locations parsed from calling `php_ini_scanned_files`.

#### _getRestartSettings(): ?array_
Returns an array of settings that can be used with PHP [sub-processes](#sub-processes), or null if the process was not restarted.

```php
use Composer\XdebugHandler\XdebugHandler;

$settings = XdebugHandler::getRestartSettings();
/**
 * $settings: array (if the current process was restarted,
 * or called with the settings from a previous restart), or null
 *
 *    'tmpIni'      => the temporary ini file used in the restart (string)
 *    'scannedInis' => if there were any scanned inis (bool)
 *    'scanDir'     => the original PHP_INI_SCAN_DIR value (false|string)
 *    'phprc'       => the original PHPRC value (false|string)
 *    'inis'        => the original inis from getAllIniFiles (array)
 *    'skipped'     => the skipped version from getSkippedVersion (string)
 */
```

#### _getSkippedVersion(): string_
Returns the Xdebug version string that was skipped by the restart, or an empty string if there was no restart (or Xdebug is still loaded, perhaps by an extending class restarting for a reason other than removing Xdebug).

```php
use Composer\XdebugHandler\XdebugHandler;

$version = XdebugHandler::getSkippedVersion();
# $version: '3.1.1' (for example), or an empty string
```

#### _isXdebugActive(): bool_
Returns true if Xdebug is loaded and is running in an active mode (if it supports modes). Returns false if Xdebug is not loaded, or it is running with `xdebug.mode=off`.

### Setter methods
These methods implement a fluent interface and must be called before the main `check()` method.

#### _setLogger(LoggerInterface $logger): self_
Enables the output of status messages to an external PSR3 logger. All messages are reported with either `DEBUG` or `WARNING` log levels. For example (showing the level and message):

```
// No restart
DEBUG    Checking MYAPP_ALLOW_XDEBUG
DEBUG    The Xdebug extension is loaded (3.1.1) xdebug.mode=off
DEBUG    No restart (APP_ALLOW_XDEBUG=0) Allowed by xdebug.mode

// Restart overridden
DEBUG    Checking MYAPP_ALLOW_XDEBUG
DEBUG    The Xdebug extension is loaded (3.1.1) xdebug.mode=coverage,debug,develop
DEBUG    No restart (MYAPP_ALLOW_XDEBUG=1)

// Failed restart
DEBUG    Checking MYAPP_ALLOW_XDEBUG
DEBUG    The Xdebug extension is loaded (3.1.0)
WARNING  No restart (Unable to create temp ini file at: ...)
```

Status messages can also be output with `XDEBUG_HANDLER_DEBUG`. See [Troubleshooting](#troubleshooting).

#### _setMainScript(string $script): self_
Sets the location of the main script to run in the restart. This is only needed in more esoteric use-cases, or if the `argv[0]` location is inaccessible. The script name `--` is supported for standard input.

#### _setPersistent(): self_
Configures the restart using [persistent settings](#persistent-settings), so that Xdebug is not loaded in any sub-process.

Use this method if your application invokes one or more PHP sub-process and the Xdebug extension is not needed. This avoids the overhead of implementing specific [sub-process](#sub-processes) strategies.

Alternatively, this method can be used to set up a default _Xdebug-free_ environment which can be changed if a sub-process requires Xdebug, then restored afterwards:

```php
function SubProcessWithXdebug()
{
    $phpConfig = new Composer\XdebugHandler\PhpConfig();

    # Set the environment to the original configuration
    $phpConfig->useOriginal();

    # run the process with Xdebug loaded
    ...

    # Restore Xdebug-free environment
    $phpConfig->usePersistent();
}
```

### Process configuration
The library offers two strategies to invoke a new PHP process without loading Xdebug, using either _standard_ or _persistent_ settings. Note that this is only important if the application calls a PHP sub-process.

#### Standard settings
Uses command-line options to remove Xdebug from the new process only.

* The -n option is added to the command-line. This tells PHP not to scan for additional inis.
* The temporary ini is added to the command-line with the -c option.

>_If the new process calls a PHP sub-process, Xdebug will be loaded in that sub-process (unless it implements xdebug-handler, in which case there will be another restart)._

This is the default strategy used in the restart.

#### Persistent settings
Uses environment variables to remove Xdebug from the new process and persist these settings to any sub-process.

* `PHP_INI_SCAN_DIR` is set to an empty string. This tells PHP not to scan for additional inis.
* `PHPRC` is set to the temporary ini.

>_If the new process calls a PHP sub-process, Xdebug will not be loaded in that sub-process._

This strategy can be used in the restart by calling [setPersistent()](#setpersistent-self).

#### Sub-processes
The `PhpConfig` helper class makes it easy to invoke a PHP sub-process (with or without Xdebug loaded), regardless of whether there has been a restart.

Each of its methods returns an array of PHP options (to add to the command-line) and sets up the environment for the required strategy. The [getRestartSettings()](#getrestartsettings-array) method is used internally.

* `useOriginal()` - Xdebug will be loaded in the new process.
* `useStandard()` - Xdebug will **not** be loaded in the new process - see [standard settings](#standard-settings).
* `userPersistent()` - Xdebug will **not** be loaded in the new process - see [persistent settings](#persistent-settings)

If there was no restart, an empty options array is returned and the environment is not changed.

```php
use Composer\XdebugHandler\PhpConfig;

$config = new PhpConfig;

$options = $config->useOriginal();
# $options:     empty array
# environment:  PHPRC and PHP_INI_SCAN_DIR set to original values

$options = $config->useStandard();
# $options:     [-n, -c, tmpIni]
# environment:  PHPRC and PHP_INI_SCAN_DIR set to original values

$options = $config->usePersistent();
# $options:     empty array
# environment:  PHPRC=tmpIni, PHP_INI_SCAN_DIR=''
```

### Troubleshooting
The following environment settings can be used to troubleshoot unexpected behavior:

* `XDEBUG_HANDLER_DEBUG=1` Outputs status messages to `STDERR`, if it is defined, irrespective of any PSR3 logger. Each message is prefixed `xdebug-handler[pid]`, where pid is the process identifier.

* `XDEBUG_HANDLER_DEBUG=2` As above, but additionally saves the temporary ini file and reports its location in a status message.

### Extending the library
The API is defined by classes and their accessible elements that are not annotated as @internal. The main class has two protected methods that can be overridden to provide additional functionality:

#### _requiresRestart(bool $default): bool_
By default the process will restart if Xdebug is loaded and not running with `xdebug.mode=off`. Extending this method allows an application to decide, by returning a boolean (or equivalent) value.
It is only called if `MYAPP_ALLOW_XDEBUG` is empty, so it will not be called in the restarted process (where this variable contains internal data), or if the restart has been overridden.

Note that the [setMainScript()](#setmainscriptstring-script-self) and [setPersistent()](#setpersistent-self) setters can be used here, if required.

#### _restart(array $command): void_
An application can extend this to modify the temporary ini file, its location given in the `tmpIni` property. New settings can be safely appended to the end of the data, which is `PHP_EOL` terminated.

The `$command` parameter is an array of unescaped command-line arguments that will be used for the new process.

Remember to finish with `parent::restart($command)`.

#### Example
This example demonstrates two ways to extend basic functionality:

* To avoid the overhead of spinning up a new process, the restart is skipped if a simple help command is requested.

* The application needs write-access to phar files, so it will force a restart if `phar.readonly` is set (regardless of whether Xdebug is loaded) and change this value in the temporary ini file.

```php
use Composer\XdebugHandler\XdebugHandler;
use MyApp\Command;

class MyRestarter extends XdebugHandler
{
    private $required;

    protected function requiresRestart(bool $default): bool
    {
        if (Command::isHelp()) {
            # No need to disable Xdebug for this
            return false;
        }

        $this->required = (bool) ini_get('phar.readonly');
        return $this->required || $default;
    }

    protected function restart(array $command): void
    {
        if ($this->required) {
            # Add required ini setting to tmpIni
            $content = file_get_contents($this->tmpIni);
            $content .= 'phar.readonly=0'.PHP_EOL;
            file_put_contents($this->tmpIni, $content);
        }

        parent::restart($command);
    }
}
```

### Examples
The `tests\App` directory contains command-line scripts that demonstrate the internal workings in a variety of scenarios.
See [Functional Test Scripts](./tests/App/README.md).

## License
composer/xdebug-handler is licensed under the MIT License, see the LICENSE file for details.
{
    "name": "composer\/xdebug-handler",
    "description": "Restarts a process without Xdebug.",
    "type": "library",
    "license": "MIT",
    "keywords": [
        "xdebug",
        "performance"
    ],
    "authors": [
        {
            "name": "John Stevenson",
            "email": "john-stevenson@blueyonder.co.uk"
        }
    ],
    "support": {
        "irc": "ircs:\/\/irc.libera.chat:6697\/composer",
        "issues": "https:\/\/github.com\/composer\/xdebug-handler\/issues"
    },
    "require": {
        "php": "^7.2.5 || ^8.0",
        "psr\/log": "^1 || ^2 || ^3",
        "composer\/pcre": "^1 || ^2 || ^3"
    },
    "require-dev": {
        "phpstan\/phpstan": "^1.0",
        "phpstan\/phpstan-strict-rules": "^1.1",
        "phpunit\/phpunit": "^8.5 || ^9.6 || ^10.5"
    },
    "autoload": {
        "psr-4": {
            "Composer\\XdebugHandler\\": "src"
        }
    },
    "autoload-dev": {
        "psr-4": {
            "Composer\\XdebugHandler\\Tests\\": "tests"
        }
    },
    "scripts": {
        "test": "@php vendor\/bin\/phpunit",
        "phpstan": "@php vendor\/bin\/phpstan analyse"
    }
}<?php

declare (strict_types=1);
/*
 * This file is part of composer/xdebug-handler.
 *
 * (c) Composer <https://github.com/composer>
 *
 * For the full copyright and license information, please view
 * the LICENSE file that was distributed with this source code.
 */
namespace Composer\XdebugHandler;

/**
 * @author John Stevenson <john-stevenson@blueyonder.co.uk>
 *
 * @phpstan-type restartData array{tmpIni: string, scannedInis: bool, scanDir: false|string, phprc: false|string, inis: string[], skipped: string}
 */
class PhpConfig
{
    /**
     * Use the original PHP configuration
     *
     * @return string[] Empty array of PHP cli options
     */
    public function useOriginal(): array
    {
        $this->getDataAndReset();
        return [];
    }
    /**
     * Use standard restart settings
     *
     * @return string[] PHP cli options
     */
    public function useStandard(): array
    {
        $data = $this->getDataAndReset();
        if ($data !== null) {
            return ['-n', '-c', $data['tmpIni']];
        }
        return [];
    }
    /**
     * Use environment variables to persist settings
     *
     * @return string[] Empty array of PHP cli options
     */
    public function usePersistent(): array
    {
        $data = $this->getDataAndReset();
        if ($data !== null) {
            $this->updateEnv('PHPRC', $data['tmpIni']);
            $this->updateEnv('PHP_INI_SCAN_DIR', '');
        }
        return [];
    }
    /**
     * Returns restart data if available and resets the environment
     *
     * @phpstan-return restartData|null
     */
    private function getDataAndReset(): ?array
    {
        $data = \Composer\XdebugHandler\XdebugHandler::getRestartSettings();
        if ($data !== null) {
            $this->updateEnv('PHPRC', $data['phprc']);
            $this->updateEnv('PHP_INI_SCAN_DIR', $data['scanDir']);
        }
        return $data;
    }
    /**
     * Updates a restart settings value in the environment
     *
     * @param string $name
     * @param string|false $value
     */
    private function updateEnv(string $name, $value): void
    {
        \Composer\XdebugHandler\Process::setEnv($name, \false !== $value ? $value : null);
    }
}
<?php

/*
 * This file is part of composer/xdebug-handler.
 *
 * (c) Composer <https://github.com/composer>
 *
 * For the full copyright and license information, please view
 * the LICENSE file that was distributed with this source code.
 */
declare (strict_types=1);
namespace Composer\XdebugHandler;

use _ContaoManager\Psr\Log\LoggerInterface;
use _ContaoManager\Psr\Log\LogLevel;
/**
 * @author John Stevenson <john-stevenson@blueyonder.co.uk>
 * @internal
 */
class Status
{
    const ENV_RESTART = 'XDEBUG_HANDLER_RESTART';
    const CHECK = 'Check';
    const ERROR = 'Error';
    const INFO = 'Info';
    const NORESTART = 'NoRestart';
    const RESTART = 'Restart';
    const RESTARTING = 'Restarting';
    const RESTARTED = 'Restarted';
    /** @var bool */
    private $debug;
    /** @var string */
    private $envAllowXdebug;
    /** @var string|null */
    private $loaded;
    /** @var LoggerInterface|null */
    private $logger;
    /** @var bool */
    private $modeOff;
    /** @var float */
    private $time;
    /**
     * @param string $envAllowXdebug Prefixed _ALLOW_XDEBUG name
     * @param bool $debug Whether debug output is required
     */
    public function __construct(string $envAllowXdebug, bool $debug)
    {
        $start = getenv(self::ENV_RESTART);
        \Composer\XdebugHandler\Process::setEnv(self::ENV_RESTART);
        $this->time = is_numeric($start) ? round((microtime(\true) - $start) * 1000) : 0;
        $this->envAllowXdebug = $envAllowXdebug;
        $this->debug = $debug && defined('STDERR');
        $this->modeOff = \false;
    }
    /**
     * Activates status message output to a PSR3 logger
     *
     * @return void
     */
    public function setLogger(LoggerInterface $logger): void
    {
        $this->logger = $logger;
    }
    /**
     * Calls a handler method to report a message
     *
     * @throws \InvalidArgumentException If $op is not known
     */
    public function report(string $op, ?string $data): void
    {
        if ($this->logger !== null || $this->debug) {
            $param = (string) $data;
            switch ($op) {
                case self::CHECK:
                    $this->reportCheck($param);
                    break;
                case self::ERROR:
                    $this->reportError($param);
                    break;
                case self::INFO:
                    $this->reportInfo($param);
                    break;
                case self::NORESTART:
                    $this->reportNoRestart();
                    break;
                case self::RESTART:
                    $this->reportRestart();
                    break;
                case self::RESTARTED:
                    $this->reportRestarted();
                    break;
                case self::RESTARTING:
                    $this->reportRestarting($param);
                    break;
                default:
                    throw new \InvalidArgumentException('Unknown op handler: ' . $op);
            }
        }
    }
    /**
     * Outputs a status message
     */
    private function output(string $text, ?string $level = null): void
    {
        if ($this->logger !== null) {
            $this->logger->log($level !== null ? $level : LogLevel::DEBUG, $text);
        }
        if ($this->debug) {
            fwrite(\STDERR, sprintf('xdebug-handler[%d] %s', getmypid(), $text . \PHP_EOL));
        }
    }
    /**
     * Checking status message
     */
    private function reportCheck(string $loaded): void
    {
        list($version, $mode) = explode('|', $loaded);
        if ($version !== '') {
            $this->loaded = '(' . $version . ')' . ($mode !== '' ? ' xdebug.mode=' . $mode : '');
        }
        $this->modeOff = $mode === 'off';
        $this->output('Checking ' . $this->envAllowXdebug);
    }
    /**
     * Error status message
     */
    private function reportError(string $error): void
    {
        $this->output(sprintf('No restart (%s)', $error), LogLevel::WARNING);
    }
    /**
     * Info status message
     */
    private function reportInfo(string $info): void
    {
        $this->output($info);
    }
    /**
     * No restart status message
     */
    private function reportNoRestart(): void
    {
        $this->output($this->getLoadedMessage());
        if ($this->loaded !== null) {
            $text = sprintf('No restart (%s)', $this->getEnvAllow());
            if (!(bool) getenv($this->envAllowXdebug)) {
                $text .= ' Allowed by ' . ($this->modeOff ? 'xdebug.mode' : 'application');
            }
            $this->output($text);
        }
    }
    /**
     * Restart status message
     */
    private function reportRestart(): void
    {
        $this->output($this->getLoadedMessage());
        \Composer\XdebugHandler\Process::setEnv(self::ENV_RESTART, (string) microtime(\true));
    }
    /**
     * Restarted status message
     */
    private function reportRestarted(): void
    {
        $loaded = $this->getLoadedMessage();
        $text = sprintf('Restarted (%d ms). %s', $this->time, $loaded);
        $level = $this->loaded !== null ? LogLevel::WARNING : null;
        $this->output($text, $level);
    }
    /**
     * Restarting status message
     */
    private function reportRestarting(string $command): void
    {
        $text = sprintf('Process restarting (%s)', $this->getEnvAllow());
        $this->output($text);
        $text = 'Running: ' . $command;
        $this->output($text);
    }
    /**
     * Returns the _ALLOW_XDEBUG environment variable as name=value
     */
    private function getEnvAllow(): string
    {
        return $this->envAllowXdebug . '=' . getenv($this->envAllowXdebug);
    }
    /**
     * Returns the Xdebug status and version
     */
    private function getLoadedMessage(): string
    {
        $loaded = $this->loaded !== null ? sprintf('loaded %s', $this->loaded) : 'not loaded';
        return 'The Xdebug extension is ' . $loaded;
    }
}
<?php

/*
 * This file is part of composer/xdebug-handler.
 *
 * (c) Composer <https://github.com/composer>
 *
 * For the full copyright and license information, please view
 * the LICENSE file that was distributed with this source code.
 */
declare (strict_types=1);
namespace Composer\XdebugHandler;

use Composer\Pcre\Preg;
use _ContaoManager\Psr\Log\LoggerInterface;
/**
 * @author John Stevenson <john-stevenson@blueyonder.co.uk>
 *
 * @phpstan-import-type restartData from PhpConfig
 */
class XdebugHandler
{
    const SUFFIX_ALLOW = '_ALLOW_XDEBUG';
    const SUFFIX_INIS = '_ORIGINAL_INIS';
    const RESTART_ID = 'internal';
    const RESTART_SETTINGS = 'XDEBUG_HANDLER_SETTINGS';
    const DEBUG = 'XDEBUG_HANDLER_DEBUG';
    /** @var string|null */
    protected $tmpIni;
    /** @var bool */
    private static $inRestart;
    /** @var string */
    private static $name;
    /** @var string|null */
    private static $skipped;
    /** @var bool */
    private static $xdebugActive;
    /** @var string|null */
    private static $xdebugMode;
    /** @var string|null */
    private static $xdebugVersion;
    /** @var bool */
    private $cli;
    /** @var string|null */
    private $debug;
    /** @var string */
    private $envAllowXdebug;
    /** @var string */
    private $envOriginalInis;
    /** @var bool */
    private $persistent;
    /** @var string|null */
    private $script;
    /** @var Status */
    private $statusWriter;
    /**
     * Constructor
     *
     * The $envPrefix is used to create distinct environment variables. It is
     * uppercased and prepended to the default base values. For example 'myapp'
     * would result in MYAPP_ALLOW_XDEBUG and MYAPP_ORIGINAL_INIS.
     *
     * @param string $envPrefix Value used in environment variables
     * @throws \RuntimeException If the parameter is invalid
     */
    public function __construct(string $envPrefix)
    {
        if ($envPrefix === '') {
            throw new \RuntimeException('Invalid constructor parameter');
        }
        self::$name = strtoupper($envPrefix);
        $this->envAllowXdebug = self::$name . self::SUFFIX_ALLOW;
        $this->envOriginalInis = self::$name . self::SUFFIX_INIS;
        self::setXdebugDetails();
        self::$inRestart = \false;
        if ($this->cli = \PHP_SAPI === 'cli') {
            $this->debug = (string) getenv(self::DEBUG);
        }
        $this->statusWriter = new \Composer\XdebugHandler\Status($this->envAllowXdebug, (bool) $this->debug);
    }
    /**
     * Activates status message output to a PSR3 logger
     */
    public function setLogger(LoggerInterface $logger): self
    {
        $this->statusWriter->setLogger($logger);
        return $this;
    }
    /**
     * Sets the main script location if it cannot be called from argv
     */
    public function setMainScript(string $script): self
    {
        $this->script = $script;
        return $this;
    }
    /**
     * Persist the settings to keep Xdebug out of sub-processes
     */
    public function setPersistent(): self
    {
        $this->persistent = \true;
        return $this;
    }
    /**
     * Checks if Xdebug is loaded and the process needs to be restarted
     *
     * This behaviour can be disabled by setting the MYAPP_ALLOW_XDEBUG
     * environment variable to 1. This variable is used internally so that
     * the restarted process is created only once.
     */
    public function check(): void
    {
        $this->notify(\Composer\XdebugHandler\Status::CHECK, self::$xdebugVersion . '|' . self::$xdebugMode);
        $envArgs = explode('|', (string) getenv($this->envAllowXdebug));
        if (!(bool) $envArgs[0] && $this->requiresRestart(self::$xdebugActive)) {
            // Restart required
            $this->notify(\Composer\XdebugHandler\Status::RESTART);
            $command = $this->prepareRestart();
            if ($command !== null) {
                $this->restart($command);
            }
            return;
        }
        if (self::RESTART_ID === $envArgs[0] && count($envArgs) === 5) {
            // Restarted, so unset environment variable and use saved values
            $this->notify(\Composer\XdebugHandler\Status::RESTARTED);
            \Composer\XdebugHandler\Process::setEnv($this->envAllowXdebug);
            self::$inRestart = \true;
            if (self::$xdebugVersion === null) {
                // Skipped version is only set if Xdebug is not loaded
                self::$skipped = $envArgs[1];
            }
            $this->tryEnableSignals();
            // Put restart settings in the environment
            $this->setEnvRestartSettings($envArgs);
            return;
        }
        $this->notify(\Composer\XdebugHandler\Status::NORESTART);
        $settings = self::getRestartSettings();
        if ($settings !== null) {
            // Called with existing settings, so sync our settings
            $this->syncSettings($settings);
        }
    }
    /**
     * Returns an array of php.ini locations with at least one entry
     *
     * The equivalent of calling php_ini_loaded_file then php_ini_scanned_files.
     * The loaded ini location is the first entry and may be an empty string.
     *
     * @return non-empty-list<string>
     */
    public static function getAllIniFiles(): array
    {
        if (self::$name !== null) {
            $env = getenv(self::$name . self::SUFFIX_INIS);
            if (\false !== $env) {
                return explode(\PATH_SEPARATOR, $env);
            }
        }
        $paths = [(string) php_ini_loaded_file()];
        $scanned = php_ini_scanned_files();
        if ($scanned !== \false) {
            $paths = array_merge($paths, array_map('trim', explode(',', $scanned)));
        }
        return $paths;
    }
    /**
     * Returns an array of restart settings or null
     *
     * Settings will be available if the current process was restarted, or
     * called with the settings from an existing restart.
     *
     * @phpstan-return restartData|null
     */
    public static function getRestartSettings(): ?array
    {
        $envArgs = explode('|', (string) getenv(self::RESTART_SETTINGS));
        if (count($envArgs) !== 6 || !self::$inRestart && php_ini_loaded_file() !== $envArgs[0]) {
            return null;
        }
        return ['tmpIni' => $envArgs[0], 'scannedInis' => (bool) $envArgs[1], 'scanDir' => '*' === $envArgs[2] ? \false : $envArgs[2], 'phprc' => '*' === $envArgs[3] ? \false : $envArgs[3], 'inis' => explode(\PATH_SEPARATOR, $envArgs[4]), 'skipped' => $envArgs[5]];
    }
    /**
     * Returns the Xdebug version that triggered a successful restart
     */
    public static function getSkippedVersion(): string
    {
        return (string) self::$skipped;
    }
    /**
     * Returns whether Xdebug is loaded and active
     *
     * true: if Xdebug is loaded and is running in an active mode.
     * false: if Xdebug is not loaded, or it is running with xdebug.mode=off.
     */
    public static function isXdebugActive(): bool
    {
        self::setXdebugDetails();
        return self::$xdebugActive;
    }
    /**
     * Allows an extending class to decide if there should be a restart
     *
     * The default is to restart if Xdebug is loaded and its mode is not "off".
     */
    protected function requiresRestart(bool $default): bool
    {
        return $default;
    }
    /**
     * Allows an extending class to access the tmpIni
     *
     * @param non-empty-list<string> $command
     */
    protected function restart(array $command): void
    {
        $this->doRestart($command);
    }
    /**
     * Executes the restarted command then deletes the tmp ini
     *
     * @param non-empty-list<string> $command
     * @phpstan-return never
     */
    private function doRestart(array $command): void
    {
        if (\PHP_VERSION_ID >= 70400) {
            $cmd = $command;
            $displayCmd = sprintf('[%s]', implode(', ', $cmd));
        } else {
            $cmd = \Composer\XdebugHandler\Process::escapeShellCommand($command);
            if (defined('PHP_WINDOWS_VERSION_BUILD')) {
                // Outer quotes required on cmd string below PHP 8
                $cmd = '"' . $cmd . '"';
            }
            $displayCmd = $cmd;
        }
        $this->tryEnableSignals();
        $this->notify(\Composer\XdebugHandler\Status::RESTARTING, $displayCmd);
        $process = proc_open($cmd, [], $pipes);
        if (is_resource($process)) {
            $exitCode = proc_close($process);
        }
        if (!isset($exitCode)) {
            // Unlikely that php or the default shell cannot be invoked
            $this->notify(\Composer\XdebugHandler\Status::ERROR, 'Unable to restart process');
            $exitCode = -1;
        } else {
            $this->notify(\Composer\XdebugHandler\Status::INFO, 'Restarted process exited ' . $exitCode);
        }
        if ($this->debug === '2') {
            $this->notify(\Composer\XdebugHandler\Status::INFO, 'Temp ini saved: ' . $this->tmpIni);
        } else {
            @unlink((string) $this->tmpIni);
        }
        exit($exitCode);
    }
    /**
     * Returns the command line array if everything was written for the restart
     *
     * If any of the following fails (however unlikely) we must return false to
     * stop potential recursion:
     *   - tmp ini file creation
     *   - environment variable creation
     *
     * @return non-empty-list<string>|null
     */
    private function prepareRestart(): ?array
    {
        if (!$this->cli) {
            $this->notify(\Composer\XdebugHandler\Status::ERROR, 'Unsupported SAPI: ' . \PHP_SAPI);
            return null;
        }
        if (($argv = $this->checkServerArgv()) === null) {
            $this->notify(\Composer\XdebugHandler\Status::ERROR, '$_SERVER[argv] is not as expected');
            return null;
        }
        if (!$this->checkConfiguration($info)) {
            $this->notify(\Composer\XdebugHandler\Status::ERROR, $info);
            return null;
        }
        $mainScript = (string) $this->script;
        if (!$this->checkMainScript($mainScript, $argv)) {
            $this->notify(\Composer\XdebugHandler\Status::ERROR, 'Unable to access main script: ' . $mainScript);
            return null;
        }
        $tmpDir = sys_get_temp_dir();
        $iniError = 'Unable to create temp ini file at: ' . $tmpDir;
        if (($tmpfile = @tempnam($tmpDir, '')) === \false) {
            $this->notify(\Composer\XdebugHandler\Status::ERROR, $iniError);
            return null;
        }
        $error = null;
        $iniFiles = self::getAllIniFiles();
        $scannedInis = count($iniFiles) > 1;
        if (!$this->writeTmpIni($tmpfile, $iniFiles, $error)) {
            $this->notify(\Composer\XdebugHandler\Status::ERROR, $error ?? $iniError);
            @unlink($tmpfile);
            return null;
        }
        if (!$this->setEnvironment($scannedInis, $iniFiles, $tmpfile)) {
            $this->notify(\Composer\XdebugHandler\Status::ERROR, 'Unable to set environment variables');
            @unlink($tmpfile);
            return null;
        }
        $this->tmpIni = $tmpfile;
        return $this->getCommand($argv, $tmpfile, $mainScript);
    }
    /**
     * Returns true if the tmp ini file was written
     *
     * @param non-empty-list<string> $iniFiles All ini files used in the current process
     */
    private function writeTmpIni(string $tmpFile, array $iniFiles, ?string &$error): bool
    {
        // $iniFiles has at least one item and it may be empty
        if ($iniFiles[0] === '') {
            array_shift($iniFiles);
        }
        $content = '';
        $sectionRegex = '/^\s*\[(?:PATH|HOST)\s*=/mi';
        $xdebugRegex = '/^\s*(zend_extension\s*=.*xdebug.*)$/mi';
        foreach ($iniFiles as $file) {
            // Check for inaccessible ini files
            if (($data = @file_get_contents($file)) === \false) {
                $error = 'Unable to read ini: ' . $file;
                return \false;
            }
            // Check and remove directives after HOST and PATH sections
            if (Preg::isMatchWithOffsets($sectionRegex, $data, $matches)) {
                $data = substr($data, 0, $matches[0][1]);
            }
            $content .= Preg::replace($xdebugRegex, ';$1', $data) . \PHP_EOL;
        }
        // Merge loaded settings into our ini content, if it is valid
        $config = parse_ini_string($content);
        $loaded = ini_get_all(null, \false);
        if (\false === $config || \false === $loaded) {
            $error = 'Unable to parse ini data';
            return \false;
        }
        $content .= $this->mergeLoadedConfig($loaded, $config);
        // Work-around for https://bugs.php.net/bug.php?id=75932
        $content .= 'opcache.enable_cli=0' . \PHP_EOL;
        return (bool) @file_put_contents($tmpFile, $content);
    }
    /**
     * Returns the command line arguments for the restart
     *
     * @param non-empty-list<string> $argv
     * @return non-empty-list<string>
     */
    private function getCommand(array $argv, string $tmpIni, string $mainScript): array
    {
        $php = [\PHP_BINARY];
        $args = array_slice($argv, 1);
        if (!$this->persistent) {
            // Use command-line options
            array_push($php, '-n', '-c', $tmpIni);
        }
        return array_merge($php, [$mainScript], $args);
    }
    /**
     * Returns true if the restart environment variables were set
     *
     * No need to update $_SERVER since this is set in the restarted process.
     *
     * @param non-empty-list<string> $iniFiles All ini files used in the current process
     */
    private function setEnvironment(bool $scannedInis, array $iniFiles, string $tmpIni): bool
    {
        $scanDir = getenv('PHP_INI_SCAN_DIR');
        $phprc = getenv('PHPRC');
        // Make original inis available to restarted process
        if (!putenv($this->envOriginalInis . '=' . implode(\PATH_SEPARATOR, $iniFiles))) {
            return \false;
        }
        if ($this->persistent) {
            // Use the environment to persist the settings
            if (!putenv('PHP_INI_SCAN_DIR=') || !putenv('PHPRC=' . $tmpIni)) {
                return \false;
            }
        }
        // Flag restarted process and save values for it to use
        $envArgs = [self::RESTART_ID, self::$xdebugVersion, (int) $scannedInis, \false === $scanDir ? '*' : $scanDir, \false === $phprc ? '*' : $phprc];
        return putenv($this->envAllowXdebug . '=' . implode('|', $envArgs));
    }
    /**
     * Logs status messages
     */
    private function notify(string $op, ?string $data = null): void
    {
        $this->statusWriter->report($op, $data);
    }
    /**
     * Returns default, changed and command-line ini settings
     *
     * @param mixed[] $loadedConfig All current ini settings
     * @param mixed[] $iniConfig Settings from user ini files
     *
     */
    private function mergeLoadedConfig(array $loadedConfig, array $iniConfig): string
    {
        $content = '';
        foreach ($loadedConfig as $name => $value) {
            // Value will either be null, string or array (HHVM only)
            if (!is_string($value) || strpos($name, 'xdebug') === 0 || $name === 'apc.mmap_file_mask') {
                continue;
            }
            if (!isset($iniConfig[$name]) || $iniConfig[$name] !== $value) {
                // Double-quote escape each value
                $content .= $name . '="' . addcslashes($value, '\"') . '"' . \PHP_EOL;
            }
        }
        return $content;
    }
    /**
     * Returns true if the script name can be used
     *
     * @param non-empty-list<string> $argv
     */
    private function checkMainScript(string &$mainScript, array $argv): bool
    {
        if ($mainScript !== '') {
            // Allow an application to set -- for standard input
            return file_exists($mainScript) || '--' === $mainScript;
        }
        if (file_exists($mainScript = $argv[0])) {
            return \true;
        }
        // Use a backtrace to resolve Phar and chdir issues.
        $trace = debug_backtrace(\DEBUG_BACKTRACE_IGNORE_ARGS);
        $main = end($trace);
        if ($main !== \false && isset($main['file'])) {
            return file_exists($mainScript = $main['file']);
        }
        return \false;
    }
    /**
     * Adds restart settings to the environment
     *
     * @param non-empty-list<string> $envArgs
     */
    private function setEnvRestartSettings(array $envArgs): void
    {
        $settings = [php_ini_loaded_file(), $envArgs[2], $envArgs[3], $envArgs[4], getenv($this->envOriginalInis), self::$skipped];
        \Composer\XdebugHandler\Process::setEnv(self::RESTART_SETTINGS, implode('|', $settings));
    }
    /**
     * Syncs settings and the environment if called with existing settings
     *
     * @phpstan-param restartData $settings
     */
    private function syncSettings(array $settings): void
    {
        if (\false === getenv($this->envOriginalInis)) {
            // Called by another app, so make original inis available
            \Composer\XdebugHandler\Process::setEnv($this->envOriginalInis, implode(\PATH_SEPARATOR, $settings['inis']));
        }
        self::$skipped = $settings['skipped'];
        $this->notify(\Composer\XdebugHandler\Status::INFO, 'Process called with existing restart settings');
    }
    /**
     * Returns true if there are no known configuration issues
     */
    private function checkConfiguration(?string &$info): bool
    {
        if (!function_exists('proc_open')) {
            $info = 'proc_open function is disabled';
            return \false;
        }
        if (!file_exists(\PHP_BINARY)) {
            $info = 'PHP_BINARY is not available';
            return \false;
        }
        if (extension_loaded('uopz') && !(bool) ini_get('uopz.disable')) {
            // uopz works at opcode level and disables exit calls
            if (function_exists('uopz_allow_exit')) {
                @uopz_allow_exit(\true);
            } else {
                $info = 'uopz extension is not compatible';
                return \false;
            }
        }
        // Check UNC paths when using cmd.exe
        if (defined('PHP_WINDOWS_VERSION_BUILD') && \PHP_VERSION_ID < 70400) {
            $workingDir = getcwd();
            if ($workingDir === \false) {
                $info = 'unable to determine working directory';
                return \false;
            }
            if (0 === strpos($workingDir, '\\\\')) {
                $info = 'cmd.exe does not support UNC paths: ' . $workingDir;
                return \false;
            }
        }
        return \true;
    }
    /**
     * Enables async signals and control interrupts in the restarted process
     *
     * Available on Unix PHP 7.1+ with the pcntl extension and Windows PHP 7.4+.
     */
    private function tryEnableSignals(): void
    {
        if (function_exists('pcntl_async_signals') && function_exists('pcntl_signal')) {
            pcntl_async_signals(\true);
            $message = 'Async signals enabled';
            if (!self::$inRestart) {
                // Restarting, so ignore SIGINT in parent
                pcntl_signal(\SIGINT, \SIG_IGN);
            } elseif (is_int(pcntl_signal_get_handler(\SIGINT))) {
                // Restarted, no handler set so force default action
                pcntl_signal(\SIGINT, \SIG_DFL);
            }
        }
        if (!self::$inRestart && function_exists('sapi_windows_set_ctrl_handler')) {
            // Restarting, so set a handler to ignore CTRL events in the parent.
            // This ensures that CTRL+C events will be available in the child
            // process without having to enable them there, which is unreliable.
            sapi_windows_set_ctrl_handler(function ($evt) {
            });
        }
    }
    /**
     * Returns $_SERVER['argv'] if it is as expected
     *
     * @return non-empty-list<string>|null
     */
    private function checkServerArgv(): ?array
    {
        $result = [];
        if (isset($_SERVER['argv']) && is_array($_SERVER['argv'])) {
            foreach ($_SERVER['argv'] as $value) {
                if (!is_string($value)) {
                    return null;
                }
                $result[] = $value;
            }
        }
        return count($result) > 0 ? $result : null;
    }
    /**
     * Sets static properties $xdebugActive, $xdebugVersion and $xdebugMode
     */
    private static function setXdebugDetails(): void
    {
        if (self::$xdebugActive !== null) {
            return;
        }
        self::$xdebugActive = \false;
        if (!extension_loaded('xdebug')) {
            return;
        }
        $version = phpversion('xdebug');
        self::$xdebugVersion = $version !== \false ? $version : 'unknown';
        if (version_compare(self::$xdebugVersion, '3.1', '>=')) {
            $modes = xdebug_info('mode');
            self::$xdebugMode = count($modes) === 0 ? 'off' : implode(',', $modes);
            self::$xdebugActive = self::$xdebugMode !== 'off';
            return;
        }
        // See if xdebug.mode is supported in this version
        $iniMode = ini_get('xdebug.mode');
        if ($iniMode === \false) {
            self::$xdebugActive = \true;
            return;
        }
        // Environment value wins but cannot be empty
        $envMode = (string) getenv('XDEBUG_MODE');
        if ($envMode !== '') {
            self::$xdebugMode = $envMode;
        } else {
            self::$xdebugMode = $iniMode !== '' ? $iniMode : 'off';
        }
        // An empty comma-separated list is treated as mode 'off'
        if (Preg::isMatch('/^,+$/', str_replace(' ', '', self::$xdebugMode))) {
            self::$xdebugMode = 'off';
        }
        self::$xdebugActive = self::$xdebugMode !== 'off';
    }
}
<?php

/*
 * This file is part of composer/xdebug-handler.
 *
 * (c) Composer <https://github.com/composer>
 *
 * For the full copyright and license information, please view
 * the LICENSE file that was distributed with this source code.
 */
declare (strict_types=1);
namespace Composer\XdebugHandler;

use Composer\Pcre\Preg;
/**
 * Process utility functions
 *
 * @author John Stevenson <john-stevenson@blueyonder.co.uk>
 */
class Process
{
    /**
     * Escapes a string to be used as a shell argument.
     *
     * From https://github.com/johnstevenson/winbox-args
     * MIT Licensed (c) John Stevenson <john-stevenson@blueyonder.co.uk>
     *
     * @param string $arg  The argument to be escaped
     * @param bool $meta Additionally escape cmd.exe meta characters
     * @param bool $module The argument is the module to invoke
     */
    public static function escape(string $arg, bool $meta = \true, bool $module = \false): string
    {
        if (!defined('PHP_WINDOWS_VERSION_BUILD')) {
            return "'" . str_replace("'", "'\\''", $arg) . "'";
        }
        $quote = strpbrk($arg, " \t") !== \false || $arg === '';
        $arg = Preg::replace('/(\\\\*)"/', '$1$1\"', $arg, -1, $dquotes);
        $dquotes = (bool) $dquotes;
        if ($meta) {
            $meta = $dquotes || Preg::isMatch('/%[^%]+%/', $arg);
            if (!$meta) {
                $quote = $quote || strpbrk($arg, '^&|<>()') !== \false;
            } elseif ($module && !$dquotes && $quote) {
                $meta = \false;
            }
        }
        if ($quote) {
            $arg = '"' . Preg::replace('/(\\\\*)$/', '$1$1', $arg) . '"';
        }
        if ($meta) {
            $arg = Preg::replace('/(["^&|<>()%])/', '^$1', $arg);
        }
        return $arg;
    }
    /**
     * Escapes an array of arguments that make up a shell command
     *
     * @param string[] $args Argument list, with the module name first
     */
    public static function escapeShellCommand(array $args): string
    {
        $command = '';
        $module = array_shift($args);
        if ($module !== null) {
            $command = self::escape($module, \true, \true);
            foreach ($args as $arg) {
                $command .= ' ' . self::escape($arg);
            }
        }
        return $command;
    }
    /**
     * Makes putenv environment changes available in $_SERVER and $_ENV
     *
     * @param string $name
     * @param ?string $value A null value unsets the variable
     */
    public static function setEnv(string $name, ?string $value = null): bool
    {
        $unset = null === $value;
        if (!putenv($unset ? $name : $name . '=' . $value)) {
            return \false;
        }
        if ($unset) {
            unset($_SERVER[$name]);
        } else {
            $_SERVER[$name] = $value;
        }
        // Update $_ENV if it is being used
        if (\false !== stripos((string) ini_get('variables_order'), 'E')) {
            if ($unset) {
                unset($_ENV[$name]);
            } else {
                $_ENV[$name] = $value;
            }
        }
        return \true;
    }
}
Copyright (C) 2022 Composer

Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
composer/class-map-generator
============================

Utilities to generate class maps and scan PHP code.

[![Continuous Integration](https://github.com/composer/class-map-generator/actions/workflows/continuous-integration.yml/badge.svg?branch=main)](https://github.com/composer/class-map-generator/actions)

Installation
------------

Install the latest version with:

```bash
composer require composer/class-map-generator
```


Requirements
------------

* PHP 7.2 is required.


Basic usage
-----------

If all you want is to scan a directory and extract a classmap with all
classes/interfaces/traits/enums mapped to their paths, you can simply use:


```php
use Composer\ClassMapGenerator\ClassMapGenerator;

$map = ClassMapGenerator::createMap('path/to/scan');
foreach ($map as $symbol => $path) {
    // do your thing
}
```

For more advanced usage, you can instantiate a generator object and call scanPaths one or more time
then call getClassMap to get a ClassMap object containing the resulting map + eventual warnings.

```php
use Composer\ClassMapGenerator\ClassMapGenerator;

$generator = new ClassMapGenerator;
$generator->scanPaths('path/to/scan');
$generator->scanPaths('path/to/scan2');

$classMap = $generator->getClassMap();
$classMap->sort(); // optionally sort classes alphabetically
foreach ($classMap->getMap() as $symbol => $path) {
    // do your thing
}

foreach ($classMap->getAmbiguousClasses() as $symbol => $paths) {
    // warn user about ambiguous class resolution
}
```


License
-------

composer/class-map-generator is licensed under the MIT License, see the LICENSE file for details.
{
    "name": "composer\/class-map-generator",
    "description": "Utilities to scan PHP code and generate class maps.",
    "type": "library",
    "license": "MIT",
    "keywords": [
        "classmap"
    ],
    "authors": [
        {
            "name": "Jordi Boggiano",
            "email": "j.boggiano@seld.be",
            "homepage": "https:\/\/seld.be"
        }
    ],
    "require": {
        "php": "^7.2 || ^8.0",
        "symfony\/finder": "^4.4 || ^5.3 || ^6 || ^7 || ^8",
        "composer\/pcre": "^2.1 || ^3.1"
    },
    "require-dev": {
        "phpunit\/phpunit": "^8",
        "phpstan\/phpstan": "^1.12 || ^2",
        "phpstan\/phpstan-deprecation-rules": "^1 || ^2",
        "phpstan\/phpstan-strict-rules": "^1.1 || ^2",
        "phpstan\/phpstan-phpunit": "^1 || ^2",
        "symfony\/filesystem": "^5.4 || ^6 || ^7 || ^8"
    },
    "autoload": {
        "psr-4": {
            "Composer\\ClassMapGenerator\\": "src"
        }
    },
    "autoload-dev": {
        "psr-4": {
            "Composer\\ClassMapGenerator\\": "tests"
        }
    },
    "extra": {
        "branch-alias": {
            "dev-main": "1.x-dev"
        }
    },
    "scripts": {
        "test": "@php phpunit",
        "phpstan": "@php phpstan analyse"
    }
}<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
/*
 * This file was initially based on a version from the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 */
namespace Composer\ClassMapGenerator;

use Composer\Pcre\Preg;
use _ContaoManager\Symfony\Component\Finder\Finder;
use Composer\IO\IOInterface;
/**
 * ClassMapGenerator
 *
 * @author Gyula Sallai <salla016@gmail.com>
 * @author Jordi Boggiano <j.boggiano@seld.be>
 */
class ClassMapGenerator
{
    /**
     * @var list<string>
     */
    private $extensions;
    /**
     * @var FileList|null
     */
    private $scannedFiles = null;
    /**
     * @var ClassMap
     */
    private $classMap;
    /**
     * @var non-empty-string
     */
    private $streamWrappersRegex;
    /**
     * @param list<string> $extensions File extensions to scan for classes in the given paths
     */
    public function __construct(array $extensions = ['php', 'inc'])
    {
        $this->extensions = $extensions;
        $this->classMap = new \Composer\ClassMapGenerator\ClassMap();
        $this->streamWrappersRegex = sprintf('{^(?:%s)://}', implode('|', array_map('preg_quote', stream_get_wrappers())));
    }
    /**
     * When calling scanPaths repeatedly with paths that may overlap, calling this will ensure that the same class is never scanned twice
     *
     * You can provide your own FileList instance or use the default one if you pass no argument
     *
     * @return $this
     */
    public function avoidDuplicateScans(?\Composer\ClassMapGenerator\FileList $scannedFiles = null): self
    {
        $this->scannedFiles = $scannedFiles ?? new \Composer\ClassMapGenerator\FileList();
        return $this;
    }
    /**
     * Iterate over all files in the given directory searching for classes
     *
     * @param string|\Traversable<\SplFileInfo>|array<\SplFileInfo> $path The path to search in or an array/traversable of SplFileInfo (e.g. symfony/finder instance)
     * @return array<class-string, non-empty-string> A class map array
     *
     * @throws \RuntimeException When the path is neither an existing file nor directory
     */
    public static function createMap($path): array
    {
        $generator = new self();
        $generator->scanPaths($path);
        return $generator->getClassMap()->getMap();
    }
    public function getClassMap(): \Composer\ClassMapGenerator\ClassMap
    {
        return $this->classMap;
    }
    /**
     * Iterate over all files in the given directory searching for classes
     *
     * @param string|\Traversable<\SplFileInfo>|array<\SplFileInfo> $path         The path to search in or an array/traversable of SplFileInfo (e.g. symfony/finder instance)
     * @param non-empty-string|null                                 $excluded     Regex that matches file paths to be excluded from the classmap
     * @param 'classmap'|'psr-0'|'psr-4'                            $autoloadType Optional autoload standard to use mapping rules with the namespace instead of purely doing a classmap
     * @param string|null                                           $namespace    Optional namespace prefix to filter by, only for psr-0/psr-4 autoloading
     * @param array<string>                                         $excludedDirs Optional dirs to exclude from search relative to $path
     *
     * @throws \RuntimeException When the path is neither an existing file nor directory
     */
    public function scanPaths($path, ?string $excluded = null, string $autoloadType = 'classmap', ?string $namespace = null, array $excludedDirs = []): void
    {
        if (!in_array($autoloadType, ['psr-0', 'psr-4', 'classmap'], \true)) {
            throw new \InvalidArgumentException('$autoloadType must be one of: "psr-0", "psr-4" or "classmap"');
        }
        if ('classmap' !== $autoloadType) {
            if (!is_string($path)) {
                throw new \InvalidArgumentException('$path must be a string when specifying a psr-0 or psr-4 autoload type');
            }
            if (!is_string($namespace)) {
                throw new \InvalidArgumentException('$namespace must be given (even if it is an empty string if you do not want to filter) when specifying a psr-0 or psr-4 autoload type');
            }
            $basePath = $path;
        }
        if (is_string($path)) {
            if (is_file($path)) {
                $path = [new \SplFileInfo($path)];
            } elseif (is_dir($path) || strpos($path, '*') !== \false) {
                $path = Finder::create()->files()->followLinks()->name('/\.(?:' . implode('|', array_map('preg_quote', $this->extensions)) . ')$/')->in($path)->exclude($excludedDirs);
            } else {
                throw new \RuntimeException('Could not scan for classes inside "' . $path . '" which does not appear to be a file nor a folder');
            }
        }
        $cwd = realpath(self::getCwd());
        foreach ($path as $file) {
            $filePath = $file->getPathname();
            if (!in_array(pathinfo($filePath, \PATHINFO_EXTENSION), $this->extensions, \true)) {
                continue;
            }
            $isStreamWrapperPath = Preg::isMatch($this->streamWrappersRegex, $filePath);
            if (!self::isAbsolutePath($filePath) && !$isStreamWrapperPath) {
                $filePath = $cwd . '/' . $filePath;
                $filePath = self::normalizePath($filePath);
            } else {
                $filePath = Preg::replace('{(?<!:)[\\\\/]{2,}}', '/', $filePath);
            }
            if ('' === $filePath) {
                throw new \LogicException('Got an empty $filePath for ' . $file->getPathname());
            }
            $realPath = $isStreamWrapperPath ? $filePath : realpath($filePath);
            // fallback just in case but this really should not happen
            if (\false === $realPath) {
                throw new \RuntimeException('realpath of ' . $filePath . ' failed to resolve, got false');
            }
            // if a list of scanned files is given, avoid scanning twice the same file to save cycles and avoid generating warnings
            // in case a PSR-0/4 declaration follows another more specific one, or a classmap declaration, which covered this file already
            if ($this->scannedFiles !== null && $this->scannedFiles->contains($realPath)) {
                continue;
            }
            // check the realpath of the file against the excluded paths as the path might be a symlink and the excluded path is realpath'd so symlink are resolved
            if (null !== $excluded && Preg::isMatch($excluded, strtr($realPath, '\\', '/'))) {
                continue;
            }
            // check non-realpath of file for directories symlink in project dir
            if (null !== $excluded && Preg::isMatch($excluded, strtr($filePath, '\\', '/'))) {
                continue;
            }
            $classes = \Composer\ClassMapGenerator\PhpFileParser::findClasses($filePath);
            if ('classmap' !== $autoloadType && isset($namespace)) {
                $classes = $this->filterByNamespace($classes, $filePath, $namespace, $autoloadType, $basePath);
                // if no valid class was found in the file then we do not mark it as scanned as it might still be matched by another rule later
                if (\count($classes) > 0 && $this->scannedFiles !== null) {
                    $this->scannedFiles->add($realPath);
                }
            } elseif ($this->scannedFiles !== null) {
                // classmap autoload rules always collect all classes so for these we definitely do not want to scan again
                $this->scannedFiles->add($realPath);
            }
            foreach ($classes as $class) {
                if (!$this->classMap->hasClass($class)) {
                    $this->classMap->addClass($class, $filePath);
                } elseif ($filePath !== $this->classMap->getClassPath($class)) {
                    $this->classMap->addAmbiguousClass($class, $filePath);
                }
            }
        }
    }
    /**
     * Remove classes which could not have been loaded by namespace autoloaders
     *
     * @param  array<int, class-string> $classes       found classes in given file
     * @param  string                   $filePath      current file
     * @param  string                   $baseNamespace prefix of given autoload mapping
     * @param  'psr-0'|'psr-4'          $namespaceType
     * @param  string                   $basePath      root directory of given autoload mapping
     * @return array<int, class-string> valid classes
     *
     * @throws \InvalidArgumentException When namespaceType is neither psr-0 nor psr-4
     */
    private function filterByNamespace(array $classes, string $filePath, string $baseNamespace, string $namespaceType, string $basePath): array
    {
        $validClasses = [];
        $rejectedClasses = [];
        $realSubPath = substr($filePath, strlen($basePath) + 1);
        $dotPosition = strrpos($realSubPath, '.');
        $realSubPath = substr($realSubPath, 0, $dotPosition === \false ? \PHP_INT_MAX : $dotPosition);
        foreach ($classes as $class) {
            // transform class name to file path and validate
            if ('psr-0' === $namespaceType) {
                if ('' !== $baseNamespace && !str_starts_with($class, $baseNamespace)) {
                    $rejectedClasses[] = $class;
                    continue;
                }
                $namespaceLength = strrpos($class, '\\');
                if (\false !== $namespaceLength) {
                    $namespace = substr($class, 0, $namespaceLength + 1);
                    $className = substr($class, $namespaceLength + 1);
                    $subPath = str_replace('\\', \DIRECTORY_SEPARATOR, $namespace) . str_replace('_', \DIRECTORY_SEPARATOR, $className);
                } else {
                    $subPath = str_replace('_', \DIRECTORY_SEPARATOR, $class);
                }
            } elseif ('psr-4' === $namespaceType) {
                $subNamespace = '' !== $baseNamespace ? substr($class, strlen($baseNamespace)) : $class;
                $subPath = str_replace('\\', \DIRECTORY_SEPARATOR, $subNamespace);
            } else {
                throw new \InvalidArgumentException('$namespaceType must be "psr-0" or "psr-4"');
            }
            if ($subPath === $realSubPath) {
                $validClasses[] = $class;
            } else {
                $rejectedClasses[] = $class;
            }
        }
        // warn only if no valid classes, else silently skip invalid
        if (\count($validClasses) === 0) {
            $cwd = realpath(self::getCwd());
            if ($cwd === \false) {
                $cwd = self::getCwd();
            }
            $cwd = self::normalizePath($cwd);
            $shortPath = Preg::replace('{^' . preg_quote($cwd) . '}', '.', self::normalizePath($filePath), 1);
            $shortBasePath = Preg::replace('{^' . preg_quote($cwd) . '}', '.', self::normalizePath($basePath), 1);
            foreach ($rejectedClasses as $class) {
                $this->classMap->addPsrViolation("Class {$class} located in {$shortPath} does not comply with {$namespaceType} autoloading standard (rule: {$baseNamespace} => {$shortBasePath}). Skipping.", $class, $filePath);
            }
            return [];
        }
        return $validClasses;
    }
    /**
     * Checks if the given path is absolute
     *
     * @see Composer\Util\Filesystem::isAbsolutePath
     *
     * @param  string $path
     * @return bool
     */
    private static function isAbsolutePath(string $path): bool
    {
        return strpos($path, '/') === 0 || substr($path, 1, 1) === ':' || strpos($path, '\\\\') === 0;
    }
    /**
     * Normalize a path. This replaces backslashes with slashes, removes ending
     * slash and collapses redundant separators and up-level references.
     *
     * @see Composer\Util\Filesystem::normalizePath
     *
     * @param  string $path Path to the file or directory
     * @return string
     */
    private static function normalizePath(string $path): string
    {
        $parts = [];
        $path = strtr($path, '\\', '/');
        $prefix = '';
        $absolute = '';
        // extract windows UNC paths e.g. \\foo\bar
        if (strpos($path, '//') === 0 && \strlen($path) > 2) {
            $absolute = '//';
            $path = substr($path, 2);
        }
        // extract a prefix being a protocol://, protocol:, protocol://drive: or simply drive:
        if (Preg::isMatchStrictGroups('{^( [0-9a-z]{2,}+: (?: // (?: [a-z]: )? )? | [a-z]: )}ix', $path, $match)) {
            $prefix = $match[1];
            $path = substr($path, \strlen($prefix));
        }
        if (strpos($path, '/') === 0) {
            $absolute = '/';
            $path = substr($path, 1);
        }
        $up = \false;
        foreach (explode('/', $path) as $chunk) {
            if ('..' === $chunk && (\strlen($absolute) > 0 || $up)) {
                array_pop($parts);
                $up = !(\count($parts) === 0 || '..' === end($parts));
            } elseif ('.' !== $chunk && '' !== $chunk) {
                $parts[] = $chunk;
                $up = '..' !== $chunk;
            }
        }
        // ensure c: is normalized to C:
        $prefix = Preg::replaceCallback('{(?:^|://)[a-z]:$}i', function (array $m) {
            return strtoupper((string) $m[0]);
        }, $prefix);
        return $prefix . $absolute . implode('/', $parts);
    }
    /**
     * @see Composer\Util\Platform::getCwd
     */
    private static function getCwd(): string
    {
        $cwd = getcwd();
        if (\false === $cwd) {
            throw new \RuntimeException('Could not determine the current working directory');
        }
        return $cwd;
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer\ClassMapGenerator;

use Composer\Pcre\Preg;
/**
 * @author Jordi Boggiano <j.boggiano@seld.be>
 * @internal
 */
class PhpFileCleaner
{
    /** @var array<array{name: string, length: int, pattern: non-empty-string}> */
    private static $typeConfig;
    /** @var non-empty-string */
    private static $restPattern;
    /**
     * @readonly
     * @var string
     */
    private $contents;
    /**
     * @readonly
     * @var int
     */
    private $len;
    /**
     * @readonly
     * @var int
     */
    private $maxMatches;
    /** @var int */
    private $index = 0;
    /**
     * @param string[] $types
     */
    public static function setTypeConfig(array $types): void
    {
        foreach ($types as $type) {
            self::$typeConfig[$type[0]] = ['name' => $type, 'length' => \strlen($type), 'pattern' => '{.\b(?<![\$:>])' . $type . '\s++[a-zA-Z_\x7f-\xff:][a-zA-Z0-9_\x7f-\xff:\-]*+}Ais'];
        }
        self::$restPattern = '{[^?"\'</' . implode('', array_keys(self::$typeConfig)) . ']+}A';
    }
    public function __construct(string $contents, int $maxMatches)
    {
        $this->contents = $contents;
        $this->len = \strlen($this->contents);
        $this->maxMatches = $maxMatches;
    }
    public function clean(): string
    {
        $clean = '';
        while ($this->index < $this->len) {
            $this->skipToPhp();
            $clean .= '<?';
            while ($this->index < $this->len) {
                $char = $this->contents[$this->index];
                if ($char === '?' && $this->peek('>')) {
                    $clean .= '?>';
                    $this->index += 2;
                    continue 2;
                }
                if ($char === '"') {
                    $this->skipString('"');
                    $clean .= 'null';
                    continue;
                }
                if ($char === "'") {
                    $this->skipString("'");
                    $clean .= 'null';
                    continue;
                }
                if ($char === "<" && $this->peek('<') && $this->match('{<<<[ \t]*+([\'"]?)([a-zA-Z_\x80-\xff][a-zA-Z0-9_\x80-\xff]*+)\1(?:\r\n|\n|\r)}A', $match)) {
                    $this->index += \strlen($match[0]);
                    $this->skipHeredoc($match[2]);
                    $clean .= 'null';
                    continue;
                }
                if ($char === '/') {
                    if ($this->peek('/')) {
                        $this->skipToNewline();
                        continue;
                    }
                    if ($this->peek('*')) {
                        $this->skipComment();
                        continue;
                    }
                }
                if ($this->maxMatches === 1 && isset(self::$typeConfig[$char])) {
                    $type = self::$typeConfig[$char];
                    if (\substr($this->contents, $this->index, $type['length']) === $type['name'] && Preg::isMatch($type['pattern'], $this->contents, $match, 0, $this->index - 1)) {
                        return $clean . $match[0];
                    }
                }
                $this->index += 1;
                if ($this->match(self::$restPattern, $match)) {
                    $clean .= $char . $match[0];
                    $this->index += \strlen($match[0]);
                } else {
                    $clean .= $char;
                }
            }
        }
        return $clean;
    }
    private function skipToPhp(): void
    {
        while ($this->index < $this->len) {
            if ($this->contents[$this->index] === '<' && $this->peek('?')) {
                $this->index += 2;
                break;
            }
            $this->index += 1;
        }
    }
    private function skipString(string $delimiter): void
    {
        $this->index += 1;
        while ($this->index < $this->len) {
            if ($this->contents[$this->index] === '\\' && ($this->peek('\\') || $this->peek($delimiter))) {
                $this->index += 2;
                continue;
            }
            if ($this->contents[$this->index] === $delimiter) {
                $this->index += 1;
                break;
            }
            $this->index += 1;
        }
    }
    private function skipComment(): void
    {
        $this->index += 2;
        while ($this->index < $this->len) {
            if ($this->contents[$this->index] === '*' && $this->peek('/')) {
                $this->index += 2;
                break;
            }
            $this->index += 1;
        }
    }
    private function skipToNewline(): void
    {
        while ($this->index < $this->len) {
            if ($this->contents[$this->index] === "\r" || $this->contents[$this->index] === "\n") {
                return;
            }
            $this->index += 1;
        }
    }
    private function skipHeredoc(string $delimiter): void
    {
        $firstDelimiterChar = $delimiter[0];
        $delimiterLength = \strlen($delimiter);
        $delimiterPattern = '{' . preg_quote($delimiter) . '(?![a-zA-Z0-9_\x80-\xff])}A';
        while ($this->index < $this->len) {
            // check if we find the delimiter after some spaces/tabs
            switch ($this->contents[$this->index]) {
                case "\t":
                case " ":
                    $this->index += 1;
                    continue 2;
                case $firstDelimiterChar:
                    if (\substr($this->contents, $this->index, $delimiterLength) === $delimiter && $this->match($delimiterPattern)) {
                        $this->index += $delimiterLength;
                        return;
                    }
                    break;
            }
            // skip the rest of the line
            while ($this->index < $this->len) {
                $this->skipToNewline();
                // skip newlines
                while ($this->index < $this->len && ($this->contents[$this->index] === "\r" || $this->contents[$this->index] === "\n")) {
                    $this->index += 1;
                }
                break;
            }
        }
    }
    private function peek(string $char): bool
    {
        return $this->index + 1 < $this->len && $this->contents[$this->index + 1] === $char;
    }
    /**
     * @param non-empty-string $regex
     * @param null|array<mixed> $match
     * @param-out array<int|string, string> $match
     */
    private function match(string $regex, ?array &$match = null): bool
    {
        return Preg::isMatchStrictGroups($regex, $this->contents, $match, 0, $this->index);
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer\ClassMapGenerator;

/**
 * Contains a list of files which were scanned to generate a classmap
 *
 * @author Jordi Boggiano <j.boggiano@seld.be>
 */
class FileList
{
    /**
     * @var array<non-empty-string, true>
     */
    public $files = [];
    /**
     * @param non-empty-string $path
     */
    public function add(string $path): void
    {
        $this->files[$path] = \true;
    }
    /**
     * @param non-empty-string $path
     */
    public function contains(string $path): bool
    {
        return isset($this->files[$path]);
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer\ClassMapGenerator;

use RuntimeException;
use Composer\Pcre\Preg;
/**
 * @author Jordi Boggiano <j.boggiano@seld.be>
 */
class PhpFileParser
{
    /**
     * Extract the classes in the given file
     *
     * @param  string            $path The file to check
     * @throws RuntimeException
     * @return list<class-string> The found classes
     */
    public static function findClasses(string $path): array
    {
        $extraTypes = self::getExtraTypes();
        if (!function_exists('php_strip_whitespace')) {
            throw new RuntimeException('Classmap generation relies on the php_strip_whitespace function, but it has been disabled by the disable_functions directive.');
        }
        // Use @ here instead of Silencer to actively suppress 'unhelpful' output
        // @link https://github.com/composer/composer/pull/4886
        $contents = @php_strip_whitespace($path);
        if ('' === $contents) {
            if (!file_exists($path)) {
                $message = 'File at "%s" does not exist, check your classmap definitions';
            } elseif (!self::isReadable($path)) {
                $message = 'File at "%s" is not readable, check its permissions';
            } elseif ('' === trim((string) file_get_contents($path))) {
                // The input file was really empty and thus contains no classes
                return [];
            } else {
                $message = 'File at "%s" could not be parsed as PHP, it may be binary or corrupted';
            }
            $error = error_get_last();
            if (isset($error['message'])) {
                $message .= \PHP_EOL . 'The following message may be helpful:' . \PHP_EOL . $error['message'];
            }
            throw new RuntimeException(sprintf($message, $path));
        }
        // return early if there is no chance of matching anything in this file
        Preg::matchAllStrictGroups('{\b(?:class|interface|trait' . $extraTypes . ')\s}i', $contents, $matches);
        if ([] === $matches[0]) {
            return [];
        }
        $p = new \Composer\ClassMapGenerator\PhpFileCleaner($contents, count($matches[0]));
        $contents = $p->clean();
        unset($p);
        Preg::matchAll('{
            (?:
                 \b(?<![\\\\$:>])(?P<type>class|interface|trait' . $extraTypes . ') \s++ (?P<name>[a-zA-Z_\x7f-\xff:][a-zA-Z0-9_\x7f-\xff:\-]*+)
               | \b(?<![\\\\$:>])(?P<ns>namespace) (?P<nsname>\s++[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*+(?:\s*+\\\\\\s*+[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*+)*+)? \s*+ [\{;]
            )
        }ix', $contents, $matches);
        $classes = [];
        $namespace = '';
        for ($i = 0, $len = count($matches['type']); $i < $len; ++$i) {
            if (isset($matches['ns'][$i]) && $matches['ns'][$i] !== '') {
                $namespace = str_replace([' ', "\t", "\r", "\n"], '', (string) $matches['nsname'][$i]) . '\\';
            } else {
                $name = $matches['name'][$i];
                assert(is_string($name));
                // skip anon classes extending/implementing
                if ($name === 'extends') {
                    continue;
                }
                if ($name === 'implements') {
                    continue;
                }
                if ($name[0] === ':') {
                    // This is an XHP class, https://github.com/facebook/xhp
                    $name = 'xhp' . substr(str_replace(['-', ':'], ['_', '__'], $name), 1);
                } elseif (strtolower((string) $matches['type'][$i]) === 'enum') {
                    // something like:
                    //   enum Foo: int { HERP = '123'; }
                    // The regex above captures the colon, which isn't part of
                    // the class name.
                    // or:
                    //   enum Foo:int { HERP = '123'; }
                    // The regex above captures the colon and type, which isn't part of
                    // the class name.
                    $colonPos = strrpos($name, ':');
                    if (\false !== $colonPos) {
                        $name = substr($name, 0, $colonPos);
                    }
                }
                /** @var class-string */
                $className = ltrim($namespace . $name, '\\');
                $classes[] = $className;
            }
        }
        return $classes;
    }
    private static function getExtraTypes(): string
    {
        static $extraTypes = null;
        if (null === $extraTypes) {
            $extraTypes = '';
            $extraTypesArray = [];
            if (\PHP_VERSION_ID >= 80100 || defined('HHVM_VERSION') && version_compare(HHVM_VERSION, '3.3', '>=')) {
                $extraTypes .= '|enum';
                $extraTypesArray = ['enum'];
            }
            \Composer\ClassMapGenerator\PhpFileCleaner::setTypeConfig(array_merge(['class', 'interface', 'trait'], $extraTypesArray));
        }
        return $extraTypes;
    }
    /**
     * Cross-platform safe version of is_readable()
     *
     * This will also check for readability by reading the file as is_readable can not be trusted on network-mounts
     * and \\wsl$ paths. See https://github.com/composer/composer/issues/8231 and https://bugs.php.net/bug.php?id=68926
     *
     * @see Composer\Util\Filesystem::isReadable
     *
     * @return bool
     */
    private static function isReadable(string $path)
    {
        if (is_readable($path)) {
            return \true;
        }
        if (is_file($path)) {
            return \false !== @file_get_contents($path, \false, null, 0, 1);
        }
        // assume false otherwise
        return \false;
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer\ClassMapGenerator;

use Composer\Pcre\Preg;
/**
 * @author Jordi Boggiano <j.boggiano@seld.be>
 */
class ClassMap implements \Countable
{
    /**
     * @var array<class-string, non-empty-string>
     */
    public $map = [];
    /**
     * @var array<class-string, array<non-empty-string>>
     */
    private $ambiguousClasses = [];
    /**
     * @var array<string, array<array{warning: string, className: string}>>
     */
    private $psrViolations = [];
    /**
     * Returns the class map, which is a list of paths indexed by class name
     *
     * @return array<class-string, non-empty-string>
     */
    public function getMap(): array
    {
        return $this->map;
    }
    /**
     * Returns warning strings containing details about PSR-0/4 violations that were detected
     *
     * Violations are for ex a class which is in the wrong file/directory and thus should not be
     * found using psr-0/psr-4 autoloading but was found by the ClassMapGenerator as it scans all files.
     *
     * This is only happening when scanning paths using psr-0/psr-4 autoload type. Classmap type
     * always accepts every class as it finds it.
     *
     * @return string[]
     */
    public function getPsrViolations(): array
    {
        if (\count($this->psrViolations) === 0) {
            return [];
        }
        return array_map(static function (array $violation): string {
            return $violation['warning'];
        }, array_merge(...array_values($this->psrViolations)));
    }
    /**
     * A map of class names to their list of ambiguous paths
     *
     * This occurs when the same class can be found in several files
     *
     * To get the path the class is being mapped to, call getClassPath
     *
     * By default, paths that contain test(s), fixture(s), example(s) or stub(s) are ignored
     * as those are typically not problematic when they're dummy classes in the tests folder.
     * If you want to get these back as well you can pass false to $duplicatesFilter. Or
     * you can pass your own pattern to exclude if you need to change the default.
     *
     * @param non-empty-string|false $duplicatesFilter
     *
     * @return array<class-string, array<non-empty-string>>
     */
    public function getAmbiguousClasses($duplicatesFilter = '{/(test|fixture|example|stub)s?/}i'): array
    {
        if (\false === $duplicatesFilter) {
            return $this->ambiguousClasses;
        }
        if (\true === $duplicatesFilter) {
            throw new \InvalidArgumentException('$duplicatesFilter should be false or a string with a valid regex, got true.');
        }
        $ambiguousClasses = [];
        foreach ($this->ambiguousClasses as $class => $paths) {
            $paths = array_filter($paths, function ($path) use ($duplicatesFilter): bool {
                return !Preg::isMatch($duplicatesFilter, strtr($path, '\\', '/'));
            });
            if (\count($paths) > 0) {
                $ambiguousClasses[$class] = array_values($paths);
            }
        }
        return $ambiguousClasses;
    }
    /**
     * Sorts the class map alphabetically by class names
     */
    public function sort(): void
    {
        ksort($this->map);
    }
    /**
     * @param class-string $className
     * @param non-empty-string $path
     */
    public function addClass(string $className, string $path): void
    {
        unset($this->psrViolations[strtr($path, '\\', '/')]);
        $this->map[$className] = $path;
    }
    /**
     * @param class-string $className
     * @return non-empty-string
     */
    public function getClassPath(string $className): string
    {
        if (!isset($this->map[$className])) {
            throw new \OutOfBoundsException('Class ' . $className . ' is not present in the map');
        }
        return $this->map[$className];
    }
    /**
     * @param class-string $className
     */
    public function hasClass(string $className): bool
    {
        return isset($this->map[$className]);
    }
    public function addPsrViolation(string $warning, string $className, string $path): void
    {
        $path = rtrim(strtr($path, '\\', '/'), '/');
        $this->psrViolations[$path][] = ['warning' => $warning, 'className' => $className];
    }
    public function clearPsrViolationsByPath(string $pathPrefix): void
    {
        $pathPrefix = rtrim(strtr($pathPrefix, '\\', '/'), '/');
        foreach ($this->psrViolations as $path => $violations) {
            if ($path === $pathPrefix || 0 === \strpos($path, $pathPrefix . '/')) {
                unset($this->psrViolations[$path]);
            }
        }
    }
    /**
     * @param class-string $className
     * @param non-empty-string $path
     */
    public function addAmbiguousClass(string $className, string $path): void
    {
        $this->ambiguousClasses[$className][] = $path;
    }
    public function count(): int
    {
        return \count($this->map);
    }
    /**
     * Get the raw psr violations
     *
     * This is a map of filepath to an associative array of the warning string
     * and the offending class name.
     * @return array<string, array<array{warning: string, className: string}>>
     */
    public function getRawPsrViolations(): array
    {
        return $this->psrViolations;
    }
}

Copyright (c) Nils Adermann, Jordi Boggiano

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is furnished
to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

<?php

/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Composer\Autoload;

/**
 * ClassLoader implements a PSR-0, PSR-4 and classmap class loader.
 *
 *     $loader = new \Composer\Autoload\ClassLoader();
 *
 *     // register classes with namespaces
 *     $loader->add('Symfony\Component', __DIR__.'/component');
 *     $loader->add('Symfony',           __DIR__.'/framework');
 *
 *     // activate the autoloader
 *     $loader->register();
 *
 *     // to enable searching the include path (eg. for PEAR packages)
 *     $loader->setUseIncludePath(true);
 *
 * In this example, if you try to use a class in the Symfony\Component
 * namespace or one of its children (Symfony\Component\Console for instance),
 * the autoloader will first look for the class under the component/
 * directory, and it will then fallback to the framework/ directory if not
 * found before giving up.
 *
 * This class is loosely based on the Symfony UniversalClassLoader.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 * @author Jordi Boggiano <j.boggiano@seld.be>
 * @see    https://www.php-fig.org/psr/psr-0/
 * @see    https://www.php-fig.org/psr/psr-4/
 */
class ClassLoader
{
    /** @var \Closure(string):void */
    private static $includeFile;

    /** @var string|null */
    private $vendorDir;

    // PSR-4
    /**
     * @var array<string, array<string, int>>
     */
    private $prefixLengthsPsr4 = array();
    /**
     * @var array<string, list<string>>
     */
    private $prefixDirsPsr4 = array();
    /**
     * @var list<string>
     */
    private $fallbackDirsPsr4 = array();

    // PSR-0
    /**
     * List of PSR-0 prefixes
     *
     * Structured as array('F (first letter)' => array('Foo\Bar (full prefix)' => array('path', 'path2')))
     *
     * @var array<string, array<string, list<string>>>
     */
    private $prefixesPsr0 = array();
    /**
     * @var list<string>
     */
    private $fallbackDirsPsr0 = array();

    /** @var bool */
    private $useIncludePath = false;

    /**
     * @var array<string, string>
     */
    private $classMap = array();

    /** @var bool */
    private $classMapAuthoritative = false;

    /**
     * @var array<string, bool>
     */
    private $missingClasses = array();

    /** @var string|null */
    private $apcuPrefix;

    /**
     * @var array<string, self>
     */
    private static $registeredLoaders = array();

    /**
     * @param string|null $vendorDir
     */
    public function __construct($vendorDir = null)
    {
        $this->vendorDir = $vendorDir;
        self::initializeIncludeClosure();
    }

    /**
     * @return array<string, list<string>>
     */
    public function getPrefixes()
    {
        if (!empty($this->prefixesPsr0)) {
            return call_user_func_array('array_merge', array_values($this->prefixesPsr0));
        }

        return array();
    }

    /**
     * @return array<string, list<string>>
     */
    public function getPrefixesPsr4()
    {
        return $this->prefixDirsPsr4;
    }

    /**
     * @return list<string>
     */
    public function getFallbackDirs()
    {
        return $this->fallbackDirsPsr0;
    }

    /**
     * @return list<string>
     */
    public function getFallbackDirsPsr4()
    {
        return $this->fallbackDirsPsr4;
    }

    /**
     * @return array<string, string> Array of classname => path
     */
    public function getClassMap()
    {
        return $this->classMap;
    }

    /**
     * @param array<string, string> $classMap Class to filename map
     *
     * @return void
     */
    public function addClassMap(array $classMap)
    {
        if ($this->classMap) {
            $this->classMap = array_merge($this->classMap, $classMap);
        } else {
            $this->classMap = $classMap;
        }
    }

    /**
     * Registers a set of PSR-0 directories for a given prefix, either
     * appending or prepending to the ones previously set for this prefix.
     *
     * @param string              $prefix  The prefix
     * @param list<string>|string $paths   The PSR-0 root directories
     * @param bool                $prepend Whether to prepend the directories
     *
     * @return void
     */
    public function add($prefix, $paths, $prepend = false)
    {
        $paths = (array) $paths;
        if (!$prefix) {
            if ($prepend) {
                $this->fallbackDirsPsr0 = array_merge(
                    $paths,
                    $this->fallbackDirsPsr0
                );
            } else {
                $this->fallbackDirsPsr0 = array_merge(
                    $this->fallbackDirsPsr0,
                    $paths
                );
            }

            return;
        }

        $first = $prefix[0];
        if (!isset($this->prefixesPsr0[$first][$prefix])) {
            $this->prefixesPsr0[$first][$prefix] = $paths;

            return;
        }
        if ($prepend) {
            $this->prefixesPsr0[$first][$prefix] = array_merge(
                $paths,
                $this->prefixesPsr0[$first][$prefix]
            );
        } else {
            $this->prefixesPsr0[$first][$prefix] = array_merge(
                $this->prefixesPsr0[$first][$prefix],
                $paths
            );
        }
    }

    /**
     * Registers a set of PSR-4 directories for a given namespace, either
     * appending or prepending to the ones previously set for this namespace.
     *
     * @param string              $prefix  The prefix/namespace, with trailing '\\'
     * @param list<string>|string $paths   The PSR-4 base directories
     * @param bool                $prepend Whether to prepend the directories
     *
     * @throws \InvalidArgumentException
     *
     * @return void
     */
    public function addPsr4($prefix, $paths, $prepend = false)
    {
        $paths = (array) $paths;
        if (!$prefix) {
            // Register directories for the root namespace.
            if ($prepend) {
                $this->fallbackDirsPsr4 = array_merge(
                    $paths,
                    $this->fallbackDirsPsr4
                );
            } else {
                $this->fallbackDirsPsr4 = array_merge(
                    $this->fallbackDirsPsr4,
                    $paths
                );
            }
        } elseif (!isset($this->prefixDirsPsr4[$prefix])) {
            // Register directories for a new namespace.
            $length = strlen($prefix);
            if ('\\' !== $prefix[$length - 1]) {
                throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
            }
            $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
            $this->prefixDirsPsr4[$prefix] = $paths;
        } elseif ($prepend) {
            // Prepend directories for an already registered namespace.
            $this->prefixDirsPsr4[$prefix] = array_merge(
                $paths,
                $this->prefixDirsPsr4[$prefix]
            );
        } else {
            // Append directories for an already registered namespace.
            $this->prefixDirsPsr4[$prefix] = array_merge(
                $this->prefixDirsPsr4[$prefix],
                $paths
            );
        }
    }

    /**
     * Registers a set of PSR-0 directories for a given prefix,
     * replacing any others previously set for this prefix.
     *
     * @param string              $prefix The prefix
     * @param list<string>|string $paths  The PSR-0 base directories
     *
     * @return void
     */
    public function set($prefix, $paths)
    {
        if (!$prefix) {
            $this->fallbackDirsPsr0 = (array) $paths;
        } else {
            $this->prefixesPsr0[$prefix[0]][$prefix] = (array) $paths;
        }
    }

    /**
     * Registers a set of PSR-4 directories for a given namespace,
     * replacing any others previously set for this namespace.
     *
     * @param string              $prefix The prefix/namespace, with trailing '\\'
     * @param list<string>|string $paths  The PSR-4 base directories
     *
     * @throws \InvalidArgumentException
     *
     * @return void
     */
    public function setPsr4($prefix, $paths)
    {
        if (!$prefix) {
            $this->fallbackDirsPsr4 = (array) $paths;
        } else {
            $length = strlen($prefix);
            if ('\\' !== $prefix[$length - 1]) {
                throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
            }
            $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
            $this->prefixDirsPsr4[$prefix] = (array) $paths;
        }
    }

    /**
     * Turns on searching the include path for class files.
     *
     * @param bool $useIncludePath
     *
     * @return void
     */
    public function setUseIncludePath($useIncludePath)
    {
        $this->useIncludePath = $useIncludePath;
    }

    /**
     * Can be used to check if the autoloader uses the include path to check
     * for classes.
     *
     * @return bool
     */
    public function getUseIncludePath()
    {
        return $this->useIncludePath;
    }

    /**
     * Turns off searching the prefix and fallback directories for classes
     * that have not been registered with the class map.
     *
     * @param bool $classMapAuthoritative
     *
     * @return void
     */
    public function setClassMapAuthoritative($classMapAuthoritative)
    {
        $this->classMapAuthoritative = $classMapAuthoritative;
    }

    /**
     * Should class lookup fail if not found in the current class map?
     *
     * @return bool
     */
    public function isClassMapAuthoritative()
    {
        return $this->classMapAuthoritative;
    }

    /**
     * APCu prefix to use to cache found/not-found classes, if the extension is enabled.
     *
     * @param string|null $apcuPrefix
     *
     * @return void
     */
    public function setApcuPrefix($apcuPrefix)
    {
        $this->apcuPrefix = function_exists('apcu_fetch') && filter_var(ini_get('apc.enabled'), FILTER_VALIDATE_BOOLEAN) ? $apcuPrefix : null;
    }

    /**
     * The APCu prefix in use, or null if APCu caching is not enabled.
     *
     * @return string|null
     */
    public function getApcuPrefix()
    {
        return $this->apcuPrefix;
    }

    /**
     * Registers this instance as an autoloader.
     *
     * @param bool $prepend Whether to prepend the autoloader or not
     *
     * @return void
     */
    public function register($prepend = false)
    {
        spl_autoload_register(array($this, 'loadClass'), true, $prepend);

        if (null === $this->vendorDir) {
            return;
        }

        if ($prepend) {
            self::$registeredLoaders = array($this->vendorDir => $this) + self::$registeredLoaders;
        } else {
            unset(self::$registeredLoaders[$this->vendorDir]);
            self::$registeredLoaders[$this->vendorDir] = $this;
        }
    }

    /**
     * Unregisters this instance as an autoloader.
     *
     * @return void
     */
    public function unregister()
    {
        spl_autoload_unregister(array($this, 'loadClass'));

        if (null !== $this->vendorDir) {
            unset(self::$registeredLoaders[$this->vendorDir]);
        }
    }

    /**
     * Loads the given class or interface.
     *
     * @param  string    $class The name of the class
     * @return true|null True if loaded, null otherwise
     */
    public function loadClass($class)
    {
        if ($file = $this->findFile($class)) {
            $includeFile = self::$includeFile;
            $includeFile($file);

            return true;
        }

        return null;
    }

    /**
     * Finds the path to the file where the class is defined.
     *
     * @param string $class The name of the class
     *
     * @return string|false The path if found, false otherwise
     */
    public function findFile($class)
    {
        // class map lookup
        if (isset($this->classMap[$class])) {
            return $this->classMap[$class];
        }
        if ($this->classMapAuthoritative || isset($this->missingClasses[$class])) {
            return false;
        }
        if (null !== $this->apcuPrefix) {
            $file = apcu_fetch($this->apcuPrefix.$class, $hit);
            if ($hit) {
                return $file;
            }
        }

        $file = $this->findFileWithExtension($class, '.php');

        // Search for Hack files if we are running on HHVM
        if (false === $file && defined('HHVM_VERSION')) {
            $file = $this->findFileWithExtension($class, '.hh');
        }

        if (null !== $this->apcuPrefix) {
            apcu_add($this->apcuPrefix.$class, $file);
        }

        if (false === $file) {
            // Remember that this class does not exist.
            $this->missingClasses[$class] = true;
        }

        return $file;
    }

    /**
     * Returns the currently registered loaders keyed by their corresponding vendor directories.
     *
     * @return array<string, self>
     */
    public static function getRegisteredLoaders()
    {
        return self::$registeredLoaders;
    }

    /**
     * @param  string       $class
     * @param  string       $ext
     * @return string|false
     */
    private function findFileWithExtension($class, $ext)
    {
        // PSR-4 lookup
        $logicalPathPsr4 = strtr($class, '\\', DIRECTORY_SEPARATOR) . $ext;

        $first = $class[0];
        if (isset($this->prefixLengthsPsr4[$first])) {
            $subPath = $class;
            while (false !== $lastPos = strrpos($subPath, '\\')) {
                $subPath = substr($subPath, 0, $lastPos);
                $search = $subPath . '\\';
                if (isset($this->prefixDirsPsr4[$search])) {
                    $pathEnd = DIRECTORY_SEPARATOR . substr($logicalPathPsr4, $lastPos + 1);
                    foreach ($this->prefixDirsPsr4[$search] as $dir) {
                        if (file_exists($file = $dir . $pathEnd)) {
                            return $file;
                        }
                    }
                }
            }
        }

        // PSR-4 fallback dirs
        foreach ($this->fallbackDirsPsr4 as $dir) {
            if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr4)) {
                return $file;
            }
        }

        // PSR-0 lookup
        if (false !== $pos = strrpos($class, '\\')) {
            // namespaced class name
            $logicalPathPsr0 = substr($logicalPathPsr4, 0, $pos + 1)
                . strtr(substr($logicalPathPsr4, $pos + 1), '_', DIRECTORY_SEPARATOR);
        } else {
            // PEAR-like class name
            $logicalPathPsr0 = strtr($class, '_', DIRECTORY_SEPARATOR) . $ext;
        }

        if (isset($this->prefixesPsr0[$first])) {
            foreach ($this->prefixesPsr0[$first] as $prefix => $dirs) {
                if (0 === strpos($class, $prefix)) {
                    foreach ($dirs as $dir) {
                        if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {
                            return $file;
                        }
                    }
                }
            }
        }

        // PSR-0 fallback dirs
        foreach ($this->fallbackDirsPsr0 as $dir) {
            if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {
                return $file;
            }
        }

        // PSR-0 include paths.
        if ($this->useIncludePath && $file = stream_resolve_include_path($logicalPathPsr0)) {
            return $file;
        }

        return false;
    }

    /**
     * @return void
     */
    private static function initializeIncludeClosure()
    {
        if (self::$includeFile !== null) {
            return;
        }

        /**
         * Scope isolated include.
         *
         * Prevents access to $this/self from included files.
         *
         * @param  string $file
         * @return void
         */
        self::$includeFile = \Closure::bind(static function($file) {
            include $file;
        }, null, null);
    }
}
# Composer-specific PHPStan extensions
#
# These can be reused by third party packages by including 'vendor/composer/composer/phpstan/rules.neon'
# in your phpstan config

services:
    -
        class: Composer\PHPStan\ConfigReturnTypeExtension
        tags:
            - phpstan.broker.dynamicMethodReturnTypeExtension
    -
        class: Composer\PHPStan\RuleReasonDataReturnTypeExtension
        tags:
            - phpstan.broker.dynamicMethodReturnTypeExtension
{
    "$schema": "https://json-schema.org/draft-04/schema#",
    "title": "Composer Package",
    "type": "object",
    "properties": {
        "name": {
            "type": "string",
            "description": "Package name, including 'vendor-name/' prefix.",
            "pattern": "^[a-z0-9]([_.-]?[a-z0-9]+)*\/[a-z0-9](([_.]|-{1,2})?[a-z0-9]+)*$"
        },
        "description": {
            "type": "string",
            "description": "Short package description."
        },
        "license": {
            "type": ["string", "array"],
            "description": "License name. Or an array of license names."
        },
        "type": {
            "description": "Package type, either 'library' for common packages, 'composer-plugin' for plugins, 'metapackage' for empty packages, or a custom type ([a-z0-9-]+) defined by whatever project this package applies to.",
            "type": "string",
            "pattern": "^[a-z0-9-]+$"
        },
        "abandoned": {
            "type": ["boolean", "string"],
            "description": "Indicates whether this package has been abandoned, it can be boolean or a package name/URL pointing to a recommended alternative. Defaults to false."
        },
        "version": {
            "type": "string",
            "description": "Package version, see https://getcomposer.org/doc/04-schema.md#version for more info on valid schemes.",
            "pattern": "^[vV]?\\d+(?:[.-]\\d+){0,3}[._-]?(?:(?:[sS][tT][aA][bB][lL][eE]|[bB][eE][tT][aA]|[bB]|[rR][cC]|[aA][lL][pP][hH][aA]|[aA]|[pP][aA][tT][cC][hH]|[pP][lL]|[pP])(?:(?:[.-]?\\d+)*)?)?(?:[.-]?[dD][eE][vV]|\\.x-dev)?(?:\\+.*)?$|^dev-.*$"
        },
        "default-branch": {
            "type": ["boolean"],
            "description": "Internal use only, do not specify this in composer.json. Indicates whether this version is the default branch of the linked VCS repository. Defaults to false."
        },
        "non-feature-branches": {
            "type": ["array"],
            "description": "A set of string or regex patterns for non-numeric branch names that will not be handled as feature branches.",
            "items": {
                "type": "string"
            }
        },
        "keywords": {
            "type": "array",
            "items": {
                "type": "string",
                "description": "A tag/keyword that this package relates to."
            }
        },
        "readme": {
            "type": "string",
            "description": "Relative path to the readme document."
        },
        "time": {
            "type": "string",
            "description": "Package release date, in 'YYYY-MM-DD', 'YYYY-MM-DD HH:MM:SS' or 'YYYY-MM-DDTHH:MM:SSZ' format."
        },
        "authors": {
            "$ref": "#/definitions/authors"
        },
        "homepage": {
            "type": "string",
            "description": "Homepage URL for the project.",
            "format": "uri"
        },
        "support": {
            "type": "object",
            "properties": {
                "email": {
                    "type": "string",
                    "description": "Email address for support.",
                    "format": "email"
                },
                "issues": {
                    "type": "string",
                    "description": "URL to the issue tracker.",
                    "format": "uri"
                },
                "forum": {
                    "type": "string",
                    "description": "URL to the forum.",
                    "format": "uri"
                },
                "wiki": {
                    "type": "string",
                    "description": "URL to the wiki.",
                    "format": "uri"
                },
                "irc": {
                    "type": "string",
                    "description": "IRC channel for support, as irc://server/channel.",
                    "format": "uri"
                },
                "chat": {
                    "type": "string",
                    "description": "URL to the support chat.",
                    "format": "uri"
                },
                "source": {
                    "type": "string",
                    "description": "URL to browse or download the sources.",
                    "format": "uri"
                },
                "docs": {
                    "type": "string",
                    "description": "URL to the documentation.",
                    "format": "uri"
                },
                "rss": {
                    "type": "string",
                    "description": "URL to the RSS feed.",
                    "format": "uri"
                },
                "security": {
                    "type": "string",
                    "description": "URL to the vulnerability disclosure policy (VDP).",
                    "format": "uri"
                }
            }
        },
        "funding": {
            "type": "array",
            "description": "A list of options to fund the development and maintenance of the package.",
            "items": {
                "type": "object",
                "properties": {
                    "type": {
                        "type": "string",
                        "description": "Type of funding or platform through which funding is possible."
                    },
                    "url": {
                        "type": "string",
                        "description": "URL to a website with details on funding and a way to fund the package.",
                        "format": "uri"
                    }
                }
            }
        },
        "source": {
            "$ref": "#/definitions/source"
        },
        "dist": {
            "$ref": "#/definitions/dist"
        },
        "_comment": {
            "type": ["array", "string"],
            "description": "A key to store comments in"
        },
        "require": {
            "type": "object",
            "description": "This is an object of package name (keys) and version constraints (values) that are required to run this package.",
            "additionalProperties": {
                "type": "string"
            }
        },
        "require-dev": {
            "type": "object",
            "description": "This is an object of package name (keys) and version constraints (values) that this package requires for developing it (testing tools and such).",
            "additionalProperties": {
                "type": "string"
            }
        },
        "replace": {
            "type": "object",
            "description": "This is an object of package name (keys) and version constraints (values) that can be replaced by this package.",
            "additionalProperties": {
                "type": "string"
            }
        },
        "conflict": {
            "type": "object",
            "description": "This is an object of package name (keys) and version constraints (values) that conflict with this package.",
            "additionalProperties": {
                "type": "string"
            }
        },
        "provide": {
            "type": "object",
            "description": "This is an object of package name (keys) and version constraints (values) that this package provides in addition to this package's name.",
            "additionalProperties": {
                "type": "string"
            }
        },
        "suggest": {
            "type": "object",
            "description": "This is an object of package name (keys) and descriptions (values) that this package suggests work well with it (this will be suggested to the user during installation).",
            "additionalProperties": {
                "type": "string"
            }
        },
        "repositories": {
            "type": ["object", "array"],
            "description": "A set of additional repositories where packages can be found.",
            "additionalProperties": {
                "anyOf": [
                    { "$ref": "#/definitions/anonymous-repository" },
                    { "type": "boolean", "enum": [false] }
                ]
            },
            "items": {
                "anyOf": [
                    { "$ref": "#/definitions/repository" },
                    {
                        "type": "object",
                        "additionalProperties": { "type": "boolean", "enum": [false] },
                        "minProperties": 1,
                        "maxProperties": 1
                    }
                ]
            }
        },
        "minimum-stability": {
            "type": ["string"],
            "description": "The minimum stability the packages must have to be install-able. Possible values are: dev, alpha, beta, RC, stable.",
            "enum": ["dev", "alpha", "beta", "rc", "RC", "stable"]
        },
        "prefer-stable": {
            "type": ["boolean"],
            "description": "If set to true, stable packages will be preferred to dev packages when possible, even if the minimum-stability allows unstable packages."
        },
        "autoload": {
            "$ref": "#/definitions/autoload"
        },
        "autoload-dev": {
            "type": "object",
            "description": "Description of additional autoload rules for development purpose (eg. a test suite).",
            "properties": {
                "psr-0": {
                    "type": "object",
                    "description": "This is an object of namespaces (keys) and the directories they can be found into (values, can be arrays of paths) by the autoloader.",
                    "additionalProperties": {
                        "type": ["string", "array"],
                        "items": {
                            "type": "string"
                        }
                    }
                },
                "psr-4": {
                    "type": "object",
                    "description": "This is an object of namespaces (keys) and the PSR-4 directories they can map to (values, can be arrays of paths) by the autoloader.",
                    "additionalProperties": {
                        "type": ["string", "array"],
                        "items": {
                            "type": "string"
                        }
                    }
                },
                "classmap": {
                    "type": "array",
                    "description": "This is an array of paths that contain classes to be included in the class-map generation process."
                },
                "files": {
                    "type": "array",
                    "description": "This is an array of files that are always required on every request."
                }
            }
        },
        "target-dir": {
            "description": "DEPRECATED: Forces the package to be installed into the given subdirectory path. This is used for autoloading PSR-0 packages that do not contain their full path. Use forward slashes for cross-platform compatibility.",
            "type": "string"
        },
        "include-path": {
            "type": ["array"],
            "description": "DEPRECATED: A list of directories which should get added to PHP's include path. This is only present to support legacy projects, and all new code should preferably use autoloading.",
            "items": {
                "type": "string"
            }
        },
        "bin": {
            "type": ["string", "array"],
            "description": "A set of files, or a single file, that should be treated as binaries and symlinked into bin-dir (from config).",
            "items": {
                "type": "string"
            }
        },
        "archive": {
            "type": ["object"],
            "description": "Options for creating package archives for distribution.",
            "properties": {
                "name": {
                    "type": "string",
                    "description": "A base name for archive."
                },
                "exclude": {
                    "type": "array",
                    "description": "A list of patterns for paths to exclude or include if prefixed with an exclamation mark."
                }
            }
        },
        "php-ext": {
            "type": "object",
            "description": "Settings for PHP extension packages.",
            "properties": {
                "extension-name": {
                    "type": "string",
                    "description": "If specified, this will be used as the name of the extension, where needed by tooling. If this is not specified, the extension name will be derived from the Composer package name (e.g. `vendor/name` would become `ext-name`). The extension name may be specified with or without the `ext-` prefix, and tools that use this must normalise this appropriately.",
                    "example": "ext-xdebug"
                },
                "priority": {
                    "type": "integer",
                    "description": "This is used to add a prefix to the INI file, e.g. `90-xdebug.ini` which affects the loading order. The priority is a number in the range 10-99 inclusive, with 10 being the highest priority (i.e. will be processed first), and 99 being the lowest priority (i.e. will be processed last). There are two digits so that the files sort correctly on any platform, whether the sorting is natural or not.",
                    "minimum": 10,
                    "maximum": 99,
                    "example": 80,
                    "default": 80
                },
                "support-zts": {
                    "type": "boolean",
                    "description": "Does this package support Zend Thread Safety",
                    "example": false,
                    "default": true
                },
                "support-nts": {
                    "type": "boolean",
                    "description": "Does this package support non-Thread Safe mode",
                    "example": false,
                    "default": true
                },
                "build-path": {
                    "type": ["string", "null"],
                    "description": "If specified, this is the subdirectory that will be used to build the extension instead of the root of the project.",
                    "example": "my-extension-source",
                    "default": null
                },
                "download-url-method": {
                    "oneOf": [
                        {
                            "type": "string",
                            "description": "If specified, this technique will be used to override the URL that PIE uses to download the asset. The default, if not specified, is composer-default.",
                            "deprecated": true,
                            "enum": ["composer-default", "pre-packaged-source", "pre-packaged-binary"],
                            "example": "composer-default",
                            "default": "composer-default"
                        },
                        {
                            "type": "array",
                            "description": "Multiple techniques can be specified, in which case PIE will try each in turn until one succeeds. The first technique that succeeds will be used.",
                            "items": {
                                "type": "string",
                                "description": "If specified, this technique will be used to override the URL that PIE uses to download the asset. The default, if not specified, is composer-default.",
                                "enum": ["composer-default", "pre-packaged-source", "pre-packaged-binary"],
                                "example": ["pre-packaged-binary", "composer-default"]
                            },
                            "minItems": 1,
                            "default": ["composer-default"]
                        }
                    ]
                },
                "os-families": {
                    "type": "array",
                    "minItems": 1,
                    "description": "An array of OS families to mark as compatible with the extension. Specifying this property will mean this package is not installable with PIE on any OS family not listed here. Must not be specified alongside os-families-exclude.",
                    "items": {
                        "type": "string",
                        "enum": ["windows", "bsd", "darwin", "solaris", "linux", "unknown"],
                        "description": "The name of the OS family to mark as compatible."
                    }
                },
                "os-families-exclude": {
                    "type": "array",
                    "minItems": 1,
                    "description": "An array of OS families to mark as incompatible with the extension. Specifying this property will mean this package is installable on any OS family except those listed here. Must not be specified alongside os-families.",
                    "items": {
                        "type": "string",
                        "enum": ["windows", "bsd", "darwin", "solaris", "linux", "unknown"],
                        "description": "The name of the OS family to exclude."
                    }
                },
                "configure-options": {
                    "type": "array",
                    "description": "These configure options make up the flags that can be passed to ./configure when installing the extension.",
                    "items": {
                        "type": "object",
                        "required": ["name"],
                        "properties": {
                            "name": {
                                "type": "string",
                                "description": "The name of the flag, this would typically be prefixed with `--`, for example, the value 'the-flag' would be passed as `./configure --the-flag`.",
                                "example": "without-xdebug-compression",
                                "pattern": "^[a-zA-Z0-9][a-zA-Z0-9-_]*$"
                            },
                            "needs-value": {
                                "type": "boolean",
                                "description": "If this is set to true, the flag needs a value (e.g. --with-somelib=<path>), otherwise it is a flag without a value (e.g. --enable-some-feature).",
                                "example": false,
                                "default": false
                            },
                            "description": {
                                "type": "string",
                                "description": "The description of what the flag does or means.",
                                "example": "Disable compression through zlib"
                            }
                        }
                    }
                }
            },
            "allOf": [
                {
                    "not": {
                        "required": ["os-families", "os-families-exclude"]
                    }
                }
            ]
        },
        "config": {
            "type": "object",
            "description": "Composer options.",
            "properties": {
                "platform": {
                    "type": "object",
                    "description": "This is an object of package name (keys) and version (values) that will be used to mock the platform packages on this machine, the version can be set to false to make it appear like the package is not present.",
                    "additionalProperties": {
                        "type": ["string", "boolean"]
                    }
                },
                "allow-plugins": {
                    "type": ["object", "boolean"],
                    "description": "This is an object of {\"pattern\": true|false} with packages which are allowed to be loaded as plugins, or true to allow all, false to allow none. Defaults to {} which prompts when an unknown plugin is added.",
                    "additionalProperties": {
                        "type": ["boolean"]
                    }
                },
                "process-timeout": {
                    "type": "integer",
                    "description": "The timeout in seconds for process executions, defaults to 300 (5mins)."
                },
                "use-include-path": {
                    "type": "boolean",
                    "description": "If true, the Composer autoloader will also look for classes in the PHP include path."
                },
                "use-parent-dir": {
                    "type": ["string", "boolean"],
                    "description": "When running Composer in a directory where there is no composer.json, if there is one present in a directory above Composer will by default ask you whether you want to use that directory's composer.json instead. One of: true (always use parent if needed), false (never ask or use it) or \"prompt\" (ask every time), defaults to prompt."
                },
                "preferred-install": {
                    "type": ["string", "object"],
                    "description": "The install method Composer will prefer to use, defaults to auto and can be any of source, dist, auto, or an object of {\"pattern\": \"preference\"}.",
                    "additionalProperties": {
                        "type": ["string"]
                    }
                },
                "audit": {
                    "type": "object",
                    "description": "Security audit and version blocking configuration options",
                    "properties": {
                        "ignore": {
                            "anyOf": [
                                {
                                    "type": "object",
                                    "description": "A list of advisory ids, remote ids, CVE ids or package names (keys) with either explanations (string values) or detailed configuration (object values with 'apply' and 'reason' fields) for why they're ignored.",
                                    "additionalProperties": {
                                        "anyOf": [
                                            {
                                                "type": "string",
                                                "description": "Explanation for ignoring this advisory (applies to audit reports and version blocking)"
                                            },
                                            {
                                                "type": "object",
                                                "description": "Detailed configuration for ignoring this advisory",
                                                "properties": {
                                                    "apply": {
                                                        "type": "string",
                                                        "enum": ["audit", "block", "all"],
                                                        "description": "Where to apply this ignore: 'audit' (only audit reports), 'block' (only version blocking), or 'all' (both)"
                                                    },
                                                    "reason": {
                                                        "type": "string",
                                                        "description": "Explanation for ignoring this advisory, e.g. vulnerable code path not reachable in application"
                                                    }
                                                }
                                            },
                                            {
                                                "type": "null",
                                                "description": "Ignore without explanation (applies to audit reports and version blocking)"
                                            }
                                        ]
                                    }
                                },
                                {
                                    "type": "array",
                                    "description": "A set of advisory ids, remote ids, CVE ids or package names that are reported but let the audit command pass. Applies to audit reports and version blocking.",
                                    "items": {
                                        "type": "string"
                                    }
                                }
                            ]
                        },
                        "abandoned": {
                            "enum": ["ignore", "report", "fail"],
                            "description": "Whether abandoned packages should be ignored, reported as problems or cause an audit failure. Applies only to audit reports, not to version blocking."
                        },
                        "ignore-severity": {
                            "anyOf": [
                                {
                                    "type": "object",
                                    "description": "A list of severities (keys) with either explanations (string values) or detailed configuration (object values with 'apply' fields) for why they're ignored.",
                                    "additionalProperties": {
                                        "anyOf": [
                                            {
                                                "type": "string",
                                                "description": "Explanation for ignoring this severity (applies to audit reports and version blocking)"
                                            },
                                            {
                                                "type": "object",
                                                "description": "Detailed configuration for ignoring this severity",
                                                "properties": {
                                                    "apply": {
                                                        "type": "string",
                                                        "enum": ["audit", "block", "all"],
                                                        "description": "Where to apply this ignore: 'audit' (only audit reports), 'block' (only version blocking), or 'all' (both)"
                                                    }
                                                }
                                            },
                                            {
                                                "type": "null",
                                                "description": "Ignore without explanation (applies to audit reports and version blocking)"
                                            }
                                        ]
                                    }
                                },
                                {
                                    "type": "array",
                                    "description": "A list of severities for which advisories with matching severity will be ignored, e.g. critical, high, medium, low, or none. Applies to audit reports and version blocking.",
                                    "items": {
                                        "type": "string"
                                    }
                                }
                            ]
                        },
                        "ignore-unreachable": {
                            "type": "boolean",
                            "description": "Whether repositories that are unreachable or return a non-200 status code should be ignored or not. Applies only to the composer audit command, does not affect audit report summaries in other commands or version blocking."
                        },
                        "block-insecure": {
                            "type": "boolean",
                            "description": "Whether insecure versions should be blocked during a composer update/require command or not.",
                            "default": true
                        },
                        "block-abandoned": {
                            "type": "boolean",
                            "description": "Whether abandoned packages should be blocked during a composer update/require command or not. Applies only if blocking of insecure versions is enabled.",
                            "default": false
                        },
                        "ignore-abandoned": {
                            "anyOf": [
                                {
                                    "type": "object",
                                    "description": "A list of abandoned package names (keys) with either explanations (string values) or detailed configuration (object values with 'apply' and 'reason' fields) for why they're ignored.",
                                    "additionalProperties": {
                                        "anyOf": [
                                            {
                                                "type": "string",
                                                "description": "Explanation for ignoring this abandoned package (applies to audit reports and version blocking)"
                                            },
                                            {
                                                "type": "object",
                                                "description": "Detailed configuration for ignoring this abandoned package",
                                                "properties": {
                                                    "apply": {
                                                        "type": "string",
                                                        "enum": ["audit", "block", "all"],
                                                        "description": "Where to apply this ignore: 'audit' (only audit reports), 'block' (only version blocking), or 'all' (both)"
                                                    },
                                                    "reason": {
                                                        "type": "string",
                                                        "description": "Explanation for ignoring this abandoned package"
                                                    }
                                                }
                                            },
                                            {
                                                "type": "null",
                                                "description": "Ignore without explanation (applies to audit reports and version blocking)"
                                            }
                                        ]
                                    }
                                },
                                {
                                    "type": "array",
                                    "description": "A set of abandoned package names that are reported but let the audit command pass and that are not blocked during updates/requires.",
                                    "items": {
                                        "type": "string"
                                    }
                                }
                            ]
                        }
                    }
                },
                "notify-on-install": {
                    "type": "boolean",
                    "description": "Composer allows repositories to define a notification URL, so that they get notified whenever a package from that repository is installed. This option allows you to disable that behaviour, defaults to true."
                },
                "github-protocols": {
                    "type": "array",
                    "description": "A list of protocols to use for github.com clones, in priority order, defaults to [\"https\", \"ssh\", \"git\"].",
                    "items": {
                        "type": "string"
                    }
                },
                "github-oauth": {
                    "type": "object",
                    "description": "An object of domain name => github API oauth tokens, typically {\"github.com\":\"<token>\"}.",
                    "additionalProperties": {
                        "type": "string"
                    }
                },
                "gitlab-oauth": {
                    "type": "object",
                    "description": "An object of domain name => gitlab API oauth tokens, typically {\"gitlab.com\":{\"expires-at\":\"<expiration date>\", \"refresh-token\":\"<refresh token>\", \"token\":\"<token>\"}}.",
                    "additionalProperties": {
                        "type": ["string", "object"],
                        "required": [ "token"],
                        "properties": {
                            "expires-at": {
                                "type": "integer",
                                "description": "The expiration date for this GitLab token"
                            },
                            "refresh-token": {
                                "type": "string",
                                "description": "The refresh token used for GitLab authentication"
                            },
                            "token": {
                                "type": "string",
                                "description": "The token used for GitLab authentication"
                            }
                        }
                    }
                },
                "gitlab-token": {
                    "type": "object",
                    "description": "An object of domain name => gitlab private tokens, typically {\"gitlab.com\":\"<token>\"}, or an object with username and token keys.",
                    "additionalProperties": {
                        "type": ["string", "object"],
                        "required": ["username", "token"],
                        "properties": {
                            "username": {
                                "type": "string",
                                "description": "The username used for GitLab authentication"
                            },
                            "token": {
                                "type": "string",
                                "description": "The token used for GitLab authentication"
                            }
                        }
                    }
                },
                "gitlab-protocol": {
                    "enum": ["git", "http", "https"],
                    "description": "A protocol to force use of when creating a repository URL for the `source` value of the package metadata. One of `git` or `http`. By default, Composer will generate a git URL for private repositories and http one for public repos."
                },
                "bearer": {
                    "type": "object",
                    "description": "An object of domain name => bearer authentication token, for example {\"example.com\":\"<token>\"}.",
                    "additionalProperties": {
                        "type": "string"
                    }
                },
                "custom-headers": {
                    "type": "object",
                    "description": "Custom HTTP headers for specific domains.",
                    "additionalProperties": {
                        "type": "array",
                        "items": {
                            "type": "string",
                            "description": "A header in format 'Header-Name: Header-Value'"
                        }
                    }
                },
                "forgejo-token": {
                    "type": "object",
                    "description": "An object of domain name => forgejo username/access token, typically {\"codeberg.org\":{\"username\": \"<username>\", \"token\": \"<access-token>\"}}.",
                    "additionalProperties": {
                        "type": ["object"],
                        "required": ["username", "token"],
                        "properties": {
                            "username": {
                                "type": "string",
                                "description": "The username used for Forgejo authentication"
                            },
                            "token": {
                                "type": "string",
                                "description": "The access token used for Forgejo authentication"
                            }
                        }
                    }
                },
                "disable-tls": {
                    "type": "boolean",
                    "description": "Defaults to `false`. If set to true all HTTPS URLs will be tried with HTTP instead and no network level encryption is performed. Enabling this is a security risk and is NOT recommended. The better way is to enable the php_openssl extension in php.ini."
                },
                "secure-http": {
                    "type": "boolean",
                    "description": "Defaults to `true`. If set to true only HTTPS URLs are allowed to be downloaded via Composer. If you really absolutely need HTTP access to something then you can disable it, but using \"Let's Encrypt\" to get a free SSL certificate is generally a better alternative."
                },
                "secure-svn-domains": {
                    "type": "array",
                    "description": "A list of domains which should be trusted/marked as using a secure Subversion/SVN transport. By default svn:// protocol is seen as insecure and will throw. This is a better/safer alternative to disabling `secure-http` altogether.",
                    "items": {
                        "type": "string"
                    }
                },
                "cafile": {
                    "type": "string",
                    "description": "A way to set the path to the openssl CA file. In PHP 5.6+ you should rather set this via openssl.cafile in php.ini, although PHP 5.6+ should be able to detect your system CA file automatically."
                },
                "capath": {
                    "type": "string",
                    "description": "If cafile is not specified or if the certificate is not found there, the directory pointed to by capath is searched for a suitable certificate. capath must be a correctly hashed certificate directory."
                },
                "http-basic": {
                    "type": "object",
                    "description": "An object of domain name => {\"username\": \"...\", \"password\": \"...\"}.",
                    "additionalProperties": {
                        "type": "object",
                        "required": ["username", "password"],
                        "properties": {
                            "username": {
                                "type": "string",
                                "description": "The username used for HTTP Basic authentication"
                            },
                            "password": {
                                "type": "string",
                                "description": "The password used for HTTP Basic authentication"
                            }
                        }
                    }
                },
                "client-certificate": {
                    "type": "object",
                    "description": "An object of domain name => {\"local_cert\": \"...\", \"local_pk\"?: \"...\", \"passphrase\"?: \"...\"} to provide client certificate.",
                    "additionalProperties": {
                        "type": "object",
                        "required": ["local_cert"],
                        "properties": {
                            "local_cert": {
                                "type": "string",
                                "description": "Path to a certificate (pem) or pair certificate+key (pem)"
                            },
                            "local_pk": {
                                "type": "string",
                                "description": "Path to a private key file (pem)"
                            },
                            "passphrase": {
                                "type": "string",
                                "description": "Passphrase for private key"
                            }
                        }
                    }
                },
                "store-auths": {
                    "type": ["string", "boolean"],
                    "description": "What to do after prompting for authentication, one of: true (store), false (do not store) or \"prompt\" (ask every time), defaults to prompt."
                },
                "vendor-dir": {
                    "type": "string",
                    "description": "The location where all packages are installed, defaults to \"vendor\"."
                },
                "bin-dir": {
                    "type": "string",
                    "description": "The location where all binaries are linked, defaults to \"vendor/bin\"."
                },
                "data-dir": {
                    "type": "string",
                    "description": "The location where old phar files are stored, defaults to \"$home\" except on XDG Base Directory compliant unixes."
                },
                "cache-dir": {
                    "type": "string",
                    "description": "The location where all caches are located, defaults to \"~/.composer/cache\" on *nix and \"%LOCALAPPDATA%\\Composer\" on windows."
                },
                "cache-files-dir": {
                    "type": "string",
                    "description": "The location where files (zip downloads) are cached, defaults to \"{$cache-dir}/files\"."
                },
                "cache-repo-dir": {
                    "type": "string",
                    "description": "The location where repo (git/hg repo clones) are cached, defaults to \"{$cache-dir}/repo\"."
                },
                "cache-vcs-dir": {
                    "type": "string",
                    "description": "The location where vcs infos (git clones, github api calls, etc. when reading vcs repos) are cached, defaults to \"{$cache-dir}/vcs\"."
                },
                "cache-ttl": {
                    "type": "integer",
                    "description": "The default cache time-to-live, defaults to 15552000 (6 months)."
                },
                "cache-files-ttl": {
                    "type": "integer",
                    "description": "The cache time-to-live for files, defaults to the value of cache-ttl."
                },
                "cache-files-maxsize": {
                    "type": ["string", "integer"],
                    "description": "The cache max size for the files cache, defaults to \"300MiB\"."
                },
                "cache-read-only": {
                    "type": ["boolean"],
                    "description": "Whether to use the Composer cache in read-only mode."
                },
                "bin-compat": {
                    "enum": ["auto", "full", "proxy", "symlink"],
                    "description": "The compatibility of the binaries, defaults to \"auto\" (automatically guessed), can be \"full\" (compatible with both Windows and Unix-based systems) and \"proxy\" (only bash-style proxy)."
                },
                "discard-changes": {
                    "type": ["string", "boolean"],
                    "description": "The default style of handling dirty updates, defaults to false and can be any of true, false or \"stash\"."
                },
                "autoloader-suffix": {
                    "type": "string",
                    "description": "Optional string to be used as a suffix for the generated Composer autoloader. When null a random one will be generated."
                },
                "optimize-autoloader": {
                    "type": "boolean",
                    "description": "Always optimize when dumping the autoloader."
                },
                "prepend-autoloader": {
                    "type": "boolean",
                    "description": "If false, the composer autoloader will not be prepended to existing autoloaders, defaults to true."
                },
                "classmap-authoritative": {
                    "type": "boolean",
                    "description": "If true, the composer autoloader will not scan the filesystem for classes that are not found in the class map, defaults to false."
                },
                "apcu-autoloader": {
                    "type": "boolean",
                    "description": "If true, the Composer autoloader will check for APCu and use it to cache found/not-found classes when the extension is enabled, defaults to false."
                },
                "github-domains": {
                    "type": "array",
                    "description": "A list of domains to use in github mode. This is used for GitHub Enterprise setups, defaults to [\"github.com\"].",
                    "items": {
                        "type": "string"
                    }
                },
                "github-expose-hostname": {
                    "type": "boolean",
                    "description": "Defaults to true. If set to false, the OAuth tokens created to access the github API will have a date instead of the machine hostname."
                },
                "gitlab-domains": {
                    "type": "array",
                    "description": "A list of domains to use in gitlab mode. This is used for custom GitLab setups, defaults to [\"gitlab.com\"].",
                    "items": {
                        "type": "string"
                    }
                },
                "forgejo-domains": {
                    "type": "array",
                    "description": "A list of domains to use in forgejo mode. This is used for custom Forgejo setups, defaults to [\"codeberg.org\"].",
                    "items": {
                        "type": "string"
                    }
                },
                "bitbucket-oauth": {
                    "type": "object",
                    "description": "An object of domain name => {\"consumer-key\": \"...\", \"consumer-secret\": \"...\"}.",
                    "additionalProperties": {
                        "type": "object",
                        "required": ["consumer-key", "consumer-secret"],
                        "properties": {
                            "consumer-key": {
                                "type": "string",
                                "description": "The consumer-key used for OAuth authentication"
                            },
                            "consumer-secret": {
                                "type": "string",
                                "description": "The consumer-secret used for OAuth authentication"
                            },
                            "access-token": {
                                "type": "string",
                                "description": "The OAuth token retrieved from Bitbucket's API, this is written by Composer and you should not set it nor modify it."
                            },
                            "access-token-expiration": {
                                "type": "integer",
                                "description": "The generated token's expiration timestamp, this is written by Composer and you should not set it nor modify it."
                            }
                        }
                    }
                },
                "use-github-api": {
                    "type": "boolean",
                    "description": "Defaults to true.  If set to false, globally disables the use of the GitHub API for all GitHub repositories and clones the repository as it would for any other repository."
                },
                "archive-format": {
                    "type": "string",
                    "description": "The default archiving format when not provided on cli, defaults to \"tar\"."
                },
                "archive-dir": {
                    "type": "string",
                    "description": "The default archive path when not provided on cli, defaults to \".\"."
                },
                "htaccess-protect": {
                    "type": "boolean",
                    "description": "Defaults to true. If set to false, Composer will not create .htaccess files in the composer home, cache, and data directories."
                },
                "sort-packages": {
                    "type": "boolean",
                    "description": "Defaults to false. If set to true, Composer will sort packages when adding/updating a new dependency."
                },
                "lock": {
                    "type": "boolean",
                    "description": "Defaults to true. If set to false, Composer will not create a composer.lock file."
                },
                "platform-check": {
                    "type": ["boolean", "string"],
                    "enum": ["php-only", true, false],
                    "description": "Defaults to \"php-only\" which checks only the PHP version. Setting to true will also check the presence of required PHP extensions. If set to false, Composer will not create and require a platform_check.php file as part of the autoloader bootstrap."
                },
                "bump-after-update": {
                    "type": ["string", "boolean"],
                    "enum": ["dev", "no-dev", true, false],
                    "description": "Defaults to false and can be any of true, false, \"dev\"` or \"no-dev\"`. If set to true, Composer will run the bump command after running the update command. If set to \"dev\" or \"no-dev\" then only the corresponding dependencies will be bumped."
                },
                "allow-missing-requirements": {
                    "type": ["boolean"],
                    "description": "Defaults to false. If set to true, Composer will allow install when lock file is not up to date with the latest changes in composer.json."
                },
                "update-with-minimal-changes": {
                    "type": ["boolean"],
                    "description": "Defaults to false. If set to true, Composer will only perform absolutely necessary changes to transitive dependencies during update."
                }
            }
        },
        "extra": {
            "type": ["object", "array"],
            "description": "Arbitrary extra data that can be used by plugins, for example, package of type composer-plugin may have a 'class' key defining an installer class name.",
            "additionalProperties": true
        },
        "scripts": {
            "type": ["object"],
            "description": "Script listeners that will be executed before/after some events.",
            "properties": {
                "pre-install-cmd": {
                    "type": ["array", "string"],
                    "description": "Occurs before the install command is executed, contains one or more Class::method callables or shell commands."
                },
                "post-install-cmd": {
                    "type": ["array", "string"],
                    "description": "Occurs after the install command is executed, contains one or more Class::method callables or shell commands."
                },
                "pre-update-cmd": {
                    "type": ["array", "string"],
                    "description": "Occurs before the update command is executed, contains one or more Class::method callables or shell commands."
                },
                "post-update-cmd": {
                    "type": ["array", "string"],
                    "description": "Occurs after the update command is executed, contains one or more Class::method callables or shell commands."
                },
                "pre-status-cmd": {
                    "type": ["array", "string"],
                    "description": "Occurs before the status command is executed, contains one or more Class::method callables or shell commands."
                },
                "post-status-cmd": {
                    "type": ["array", "string"],
                    "description": "Occurs after the status command is executed, contains one or more Class::method callables or shell commands."
                },
                "pre-package-install": {
                    "type": ["array", "string"],
                    "description": "Occurs before a package is installed, contains one or more Class::method callables or shell commands."
                },
                "post-package-install": {
                    "type": ["array", "string"],
                    "description": "Occurs after a package is installed, contains one or more Class::method callables or shell commands."
                },
                "pre-package-update": {
                    "type": ["array", "string"],
                    "description": "Occurs before a package is updated, contains one or more Class::method callables or shell commands."
                },
                "post-package-update": {
                    "type": ["array", "string"],
                    "description": "Occurs after a package is updated, contains one or more Class::method callables or shell commands."
                },
                "pre-package-uninstall": {
                    "type": ["array", "string"],
                    "description": "Occurs before a package has been uninstalled, contains one or more Class::method callables or shell commands."
                },
                "post-package-uninstall": {
                    "type": ["array", "string"],
                    "description": "Occurs after a package has been uninstalled, contains one or more Class::method callables or shell commands."
                },
                "pre-autoload-dump": {
                    "type": ["array", "string"],
                    "description": "Occurs before the autoloader is dumped, contains one or more Class::method callables or shell commands."
                },
                "post-autoload-dump": {
                    "type": ["array", "string"],
                    "description": "Occurs after the autoloader is dumped, contains one or more Class::method callables or shell commands."
                },
                "post-root-package-install": {
                    "type": ["array", "string"],
                    "description": "Occurs after the root-package is installed, contains one or more Class::method callables or shell commands."
                },
                "post-create-project-cmd": {
                    "type": ["array", "string"],
                    "description": "Occurs after the create-project command is executed, contains one or more Class::method callables or shell commands."
                }
            }
        },
        "scripts-descriptions": {
            "type": ["object"],
            "description": "Descriptions for custom commands, shown in console help.",
            "additionalProperties": {
                "type": "string"
            }
        },
        "scripts-aliases": {
            "type": ["object"],
            "description": "Aliases for custom commands.",
            "additionalProperties": {
                "type": "array"
            }
        }
    },
    "definitions": {
        "authors": {
            "type": "array",
            "description": "List of authors that contributed to the package. This is typically the main maintainers, not the full list.",
            "items": {
                "type": "object",
                "additionalProperties": false,
                "required": [ "name"],
                "properties": {
                    "name": {
                        "type": "string",
                        "description": "Full name of the author."
                    },
                    "email": {
                        "type": "string",
                        "description": "Email address of the author.",
                        "format": "email"
                    },
                    "homepage": {
                        "type": "string",
                        "description": "Homepage URL for the author.",
                        "format": "uri"
                    },
                    "role": {
                        "type": "string",
                        "description": "Author's role in the project."
                    }
                }
            }
        },
        "autoload": {
            "type": "object",
            "description": "Description of how the package can be autoloaded.",
            "properties": {
                "psr-0": {
                    "type": "object",
                    "description": "This is an object of namespaces (keys) and the directories they can be found in (values, can be arrays of paths) by the autoloader.",
                    "additionalProperties": {
                        "type": ["string", "array"],
                        "items": {
                            "type": "string"
                        }
                    }
                },
                "psr-4": {
                    "type": "object",
                    "description": "This is an object of namespaces (keys) and the PSR-4 directories they can map to (values, can be arrays of paths) by the autoloader.",
                    "additionalProperties": {
                        "type": ["string", "array"],
                        "items": {
                            "type": "string"
                        }
                    }
                },
                "classmap": {
                    "type": "array",
                    "description": "This is an array of paths that contain classes to be included in the class-map generation process."
                },
                "files": {
                    "type": "array",
                    "description": "This is an array of files that are always required on every request."
                },
                "exclude-from-classmap": {
                    "type": "array",
                    "description": "This is an array of patterns to exclude from autoload classmap generation. (e.g. \"exclude-from-classmap\": [\"/test/\", \"/tests/\", \"/Tests/\"]"
                }
            }
        },
        "repository": {
            "type": "object",
            "anyOf": [
                { "$ref": "#/definitions/composer-repository" },
                { "$ref": "#/definitions/vcs-repository" },
                { "$ref": "#/definitions/path-repository" },
                { "$ref": "#/definitions/artifact-repository" },
                { "$ref": "#/definitions/pear-repository" },
                { "$ref": "#/definitions/package-repository" }
            ]
        },
        "anonymous-repository": {
            "allOf": [
                { "$ref": "#/definitions/repository" },
                { "not": { "required": ["name"] } }
            ]
        },
        "composer-repository": {
            "type": "object",
            "required": ["type", "url"],
            "properties": {
                "name": { "type":  "string" },
                "type": { "type": "string", "enum": ["composer"] },
                "url": { "type": "string" },
                "canonical": { "type": "boolean" },
                "only": {
                    "type": "array",
                    "items": {
                        "type": "string"
                    }
                },
                "exclude": {
                    "type": "array",
                    "items": {
                        "type": "string"
                    }
                },
                "options": {
                    "type": "object",
                    "additionalProperties": true
                },
                "allow_ssl_downgrade": { "type": "boolean" },
                "force-lazy-providers": { "type": "boolean" }
            }
        },
        "vcs-repository": {
            "type": "object",
            "required": ["type", "url"],
            "properties": {
                "name": { "type":  "string" },
                "type": { "type": "string", "enum": ["vcs", "github", "git", "gitlab", "bitbucket", "git-bitbucket", "hg", "fossil", "perforce", "svn", "forgejo"] },
                "url": { "type": "string" },
                "canonical": { "type": "boolean" },
                "only": {
                    "type": "array",
                    "items": {
                        "type": "string"
                    }
                },
                "exclude": {
                    "type": "array",
                    "items": {
                        "type": "string"
                    }
                },
                "no-api": { "type": "boolean" },
                "secure-http": { "type": "boolean" },
                "svn-cache-credentials": { "type": "boolean" },
                "trunk-path": { "type": ["string", "boolean"] },
                "branches-path": { "type": ["string", "boolean"] },
                "tags-path": { "type": ["string", "boolean"] },
                "package-path": { "type": "string" },
                "depot": { "type": "string" },
                "branch": { "type": "string" },
                "unique_perforce_client_name": { "type": "string" },
                "p4user": { "type": "string" },
                "p4password": { "type": "string" }
            }
        },
        "path-repository": {
            "type": "object",
            "required": ["type", "url"],
            "properties": {
                "name": { "type":  "string" },
                "type": { "type": "string", "enum": ["path"] },
                "url": { "type": "string" },
                "canonical": { "type": "boolean" },
                "only": {
                    "type": "array",
                    "items": {
                        "type": "string"
                    }
                },
                "exclude": {
                    "type": "array",
                    "items": {
                        "type": "string"
                    }
                },
                "options": {
                    "type": "object",
                    "properties": {
                        "reference": { "type": ["string"], "enum": ["none", "config", "auto"] },
                        "symlink": { "type": ["boolean", "null"] },
                        "relative": { "type": ["boolean"] },
                        "versions": { "type": "object", "additionalProperties": { "type": "string" } }
                    },
                    "additionalProperties": true
                }
            }
        },
        "artifact-repository": {
            "type": "object",
            "required": ["type", "url"],
            "properties": {
                "name": { "type":  "string" },
                "type": { "type": "string", "enum": ["artifact"] },
                "url": { "type": "string" },
                "canonical": { "type": "boolean" },
                "only": {
                    "type": "array",
                    "items": {
                        "type": "string"
                    }
                },
                "exclude": {
                    "type": "array",
                    "items": {
                        "type": "string"
                    }
                }
            }
        },
        "pear-repository": {
            "type": "object",
            "required": ["type", "url"],
            "properties": {
                "name": { "type":  "string" },
                "type": { "type": "string", "enum": ["pear"] },
                "url": { "type": "string" },
                "canonical": { "type": "boolean" },
                "only": {
                    "type": "array",
                    "items": {
                        "type": "string"
                    }
                },
                "exclude": {
                    "type": "array",
                    "items": {
                        "type": "string"
                    }
                },
                "vendor-alias": { "type": "string" }
            }
        },
        "package-repository": {
            "type": "object",
            "required": ["type", "package"],
            "properties": {
                "name": { "type":  "string" },
                "type": { "type": "string", "enum": ["package"] },
                "canonical": { "type": "boolean" },
                "only": {
                    "type": "array",
                    "items": {
                        "type": "string"
                    }
                },
                "exclude": {
                    "type": "array",
                    "items": {
                        "type": "string"
                    }
                },
                "package": {
                    "oneOf": [
                        { "$ref": "#/definitions/inline-package" },
                        {
                            "type": "array",
                            "items": { "$ref": "#/definitions/inline-package" }
                        }
                    ]
                }
            }
        },
        "inline-package": {
            "type": "object",
            "required": ["name", "version"],
            "properties": {
                "name": {
                    "type": "string",
                    "description": "Package name, including 'vendor-name/' prefix."
                },
                "type": {
                    "type": "string"
                },
                "target-dir": {
                    "description": "DEPRECATED: Forces the package to be installed into the given subdirectory path. This is used for autoloading PSR-0 packages that do not contain their full path. Use forward slashes for cross-platform compatibility.",
                    "type": "string"
                },
                "description": {
                    "type": "string"
                },
                "keywords": {
                    "type": "array",
                    "items": {
                        "type": "string"
                    }
                },
                "homepage": {
                    "type": "string",
                    "format": "uri"
                },
                "version": {
                    "type": "string"
                },
                "time": {
                    "type": "string"
                },
                "license": {
                    "type": [
                        "string",
                        "array"
                    ]
                },
                "authors": {
                    "$ref": "#/definitions/authors"
                },
                "require": {
                    "type": "object",
                    "additionalProperties": {
                        "type": "string"
                    }
                },
                "replace": {
                    "type": "object",
                    "additionalProperties": {
                        "type": "string"
                    }
                },
                "conflict": {
                    "type": "object",
                    "additionalProperties": {
                        "type": "string"
                    }
                },
                "provide": {
                    "type": "object",
                    "additionalProperties": {
                        "type": "string"
                    }
                },
                "require-dev": {
                    "type": "object",
                    "additionalProperties": {
                        "type": "string"
                    }
                },
                "suggest": {
                    "type": "object",
                    "additionalProperties": {
                        "type": "string"
                    }
                },
                "extra": {
                    "type": ["object", "array"],
                    "additionalProperties": true
                },
                "autoload": {
                    "$ref": "#/definitions/autoload"
                },
                "archive": {
                    "type": ["object"],
                    "properties": {
                        "exclude": {
                            "type": "array"
                        }
                    }
                },
                "bin": {
                    "type": ["string", "array"],
                    "description": "A set of files, or a single file, that should be treated as binaries and symlinked into bin-dir (from config).",
                    "items": {
                        "type": "string"
                    }
                },
                "include-path": {
                    "type": ["array"],
                    "description": "DEPRECATED: A list of directories which should get added to PHP's include path. This is only present to support legacy projects, and all new code should preferably use autoloading.",
                    "items": {
                        "type": "string"
                    }
                },
                "source": {
                    "$ref": "#/definitions/source"
                },
                "dist": {
                    "$ref": "#/definitions/dist"
                }
            },
            "additionalProperties": true
        },
        "source": {
            "type": "object",
            "required": ["type", "url", "reference"],
            "properties": {
                "type": {
                    "type": "string"
                },
                "url": {
                    "type": "string"
                },
                "reference": {
                    "type": "string"
                },
                "mirrors": {
                    "type": "array"
                }
            }
        },
        "dist": {
            "type": "object",
            "required": ["type", "url"],
            "properties": {
                "type": {
                    "type": "string"
                },
                "url": {
                    "type": "string"
                },
                "reference": {
                    "type": "string"
                },
                "shasum": {
                    "type": "string"
                },
                "mirrors": {
                    "type": "array"
                }
            }
        }
    }
}
{
    "$schema": "https://json-schema.org/draft-04/schema#",
    "title": "Composer Lock File",
    "type": "object",
    "required": [ "content-hash", "packages", "packages-dev" ],
    "additionalProperties": true,
    "properties": {
        "_readme": {
            "type": "array",
            "items": {
                "type": "string"
            },
            "description": "Informational text for humans reading the file"
        },
        "content-hash": {
            "type": "string",
            "description": "Hash of all relevant properties of the composer.json that was used to create this lock file."
        },
        "packages": {
            "type": "array",
            "description": "An array of packages that are required.",
            "items": {
                "$ref": "./composer-schema.json",
                "required": ["name", "version"]
            }
        },
        "packages-dev": {
            "type": "array",
            "description": "An array of packages that are required in require-dev.",
            "items": {
                "$ref": "./composer-schema.json"
            }
        },
        "aliases": {
            "type": "array",
            "description": "Inline aliases defined in the root package.",
            "items": {
                "type": "object",
                "required": [ "package", "version", "alias", "alias_normalized" ],
                "properties": {
                    "package": {
                        "type": "string"
                    },
                    "version": {
                        "type": "string"
                    },
                    "alias": {
                        "type": "string"
                    },
                    "alias_normalized": {
                        "type": "string"
                    }
                }
            }
        },
        "minimum-stability": {
            "type": "string",
            "description": "The minimum-stability used to generate this lock file."
        },
        "stability-flags": {
            "type": "object",
            "description": "Root package stability flags changing the minimum-stability for specific packages.",
            "additionalProperties": {
                "type": "integer"
            }
        },
        "prefer-stable": {
            "type": "boolean",
            "description": "Whether the --prefer-stable flag was used when building this lock file."
        },
        "prefer-lowest": {
            "type": "boolean",
            "description": "Whether the --prefer-lowest flag was used when building this lock file."
        },
        "platform": {
            "type": "object",
            "description": "Platform requirements of the root package.",
            "additionalProperties": {
                "type": "string"
            }
        },
        "platform-dev": {
            "type": "object",
            "description": "Platform dev-requirements of the root package.",
            "additionalProperties": {
                "type": "string"
            }
        },
        "platform-overrides": {
            "type": "object",
            "description": "Platform config overrides of the root package.",
            "additionalProperties": {
                "type": "string"
            }
        },
        "plugin-api-version": {
            "type": "string",
            "description": "The composer-plugin-api version that was used to generate this lock file."
        }
    }
}
{
    "$schema": "https://json-schema.org/draft-04/schema#",
    "title": "Composer Package Repository",
    "type": "object",
    "oneOf": [
        { "required": [ "packages" ] },
        { "required": [ "providers" ] },
        { "required": [ "provider-includes", "providers-url" ] },
        { "required": [ "metadata-url" ] }
    ],
    "properties": {
        "packages": {
            "type": ["object", "array"],
            "description": "A hashmap of package names in the form of <vendor>/<name>.",
            "additionalProperties": { "$ref": "#/definitions/versions" }
        },
        "metadata-url": {
            "type": "string",
            "description": "Endpoint to retrieve package metadata data from, in Composer v2 format, e.g. '/p2/%package%.json'."
        },
        "available-packages": {
            "type": "array",
            "items": {
                "type": "string"
            },
            "description": "If your repository only has a small number of packages, and you want to avoid serving many 404s, specify all the package names that your repository contains here."
        },
        "available-package-patterns": {
            "type": "array",
            "items": {
                "type": "string"
            },
            "description": "If your repository only has a small number of packages, and you want to avoid serving many 404s, specify package name patterns containing wildcards (*) that your repository contains here."
        },
        "security-advisories": {
            "type": "array",
            "items": {
                "type": "object",
                "required": ["metadata", "api-url"],
                "properties": {
                    "metadata": {
                        "type": "boolean",
                        "description": "Whether metadata files contain security advisory data or whether it should always be queried using the API URL."
                    },
                    "api-url": {
                        "type": "string",
                        "description": "Endpoint to call to retrieve security advisories data."
                    }
                }
            }
        },
        "metadata-changes-url": {
            "type": "string",
            "description": "Endpoint to retrieve package metadata updates from. This should receive a timestamp since last call to be able to return new changes. e.g. '/metadata/changes.json'."
        },
        "providers-api": {
            "type": "string",
            "description": "Endpoint to retrieve package names providing a given name from, e.g. '/providers/%package%.json'."
        },
        "notify-batch": {
            "type": "string",
            "description": "Endpoint to call after multiple packages have been installed, e.g. '/downloads/'."
        },
        "search": {
            "type": "string",
            "description": "Endpoint that provides search capabilities, e.g. '/search.json?q=%query%&type=%type%'."
        },
        "list": {
            "type": "string",
            "description": "Endpoint that provides a full list of packages present in the repository. It should accept an optional `?filter=xx` query param, which can contain `*` as wildcards matching any substring. e.g. '/list.json'."
        },
        "warnings": {
            "type": "array",
            "items": {
                "type": "object",
                "required": ["message", "versions"],
                "properties": {
                    "message": {
                        "type": "string",
                        "description": "A message that will be output by Composer as a warning when this source is consulted."
                    },
                    "versions": {
                        "type": "string",
                        "description": "A version constraint to limit to which Composer versions the warning should be shown."
                    }
                }
            }
        },
        "infos": {
            "type": "array",
            "items": {
                "type": "object",
                "required": ["message", "versions"],
                "properties": {
                    "message": {
                        "type": "string",
                        "description": "A message that will be output by Composer as info when this source is consulted."
                    },
                    "versions": {
                        "type": "string",
                        "description": "A version constraint to limit to which Composer versions the info should be shown."
                    }
                }
            }
        },
        "providers-url": {
            "type": "string",
            "description": "DEPRECATED: Endpoint to retrieve provider data from, e.g. '/p/%package%$%hash%.json'."
        },
        "provider-includes": {
            "type": "object",
            "description": "DEPRECATED: A hashmap of provider listings.",
            "additionalProperties": { "$ref": "#/definitions/provider" }
        },
        "providers": {
            "type": "object",
            "description": "DEPRECATED: A hashmap of package names in the form of <vendor>/<name>.",
            "additionalProperties": { "$ref": "#/definitions/provider" }
        },
        "warning": {
            "type": "string",
            "description": "DEPRECATED: A message that will be output by Composer as a warning when this source is consulted."
        },
        "warning-versions": {
            "type": "string",
            "description": "DEPRECATED: A version constraint to limit to which Composer versions the warning should be shown."
        },
        "info": {
            "type": "string",
            "description": "DEPRECATED: A message that will be output by Composer as a info when this source is consulted."
        },
        "info-versions": {
            "type": "string",
            "description": "DEPRECATED: A version constraint to limit to which Composer versions the info should be shown."
        }
    },
    "definitions": {
        "versions": {
            "type": "object",
            "description": "A hashmap of versions and their metadata.",
            "additionalProperties": { "$ref": "#/definitions/version" }
        },
        "version": {
            "type": "object",
            "oneOf": [
                { "$ref": "#/definitions/package" },
                { "$ref": "#/definitions/metapackage" }
            ]
        },
        "package-base": {
            "properties": {
                "name": { "type": "string" },
                "type": { "type": "string" },
                "version": { "type": "string" },
                "version_normalized": {
                    "type": "string",
                    "description": "Normalized version, optional but can save computational time on client side."
                },
                "autoload": { "type": "object" },
                "require": { "type": "object" },
                "replace": { "type": "object" },
                "conflict": { "type": "object" },
                "provide": { "type": "object" },
                "time": { "type": "string" }
            },
            "additionalProperties": true
        },
        "package": {
            "allOf": [
                { "$ref": "#/definitions/package-base" },
                {
                    "properties": {
                        "dist": { "type": "object" },
                        "source": { "type": "object" }
                    }
                },
                { "oneOf": [
                    { "required": [ "name", "version", "source" ] },
                    { "required": [ "name", "version", "dist" ] }
                ] }
            ]
        },
        "metapackage": {
            "allOf": [
                { "$ref": "#/definitions/package-base" },
                {
                    "properties": {
                        "type": { "type": "string", "enum": [ "metapackage" ] }
                    },
                    "required": [ "name", "version", "type" ]
                }
            ]
        },
        "provider": {
            "type": "object",
            "properties": {
                "sha256": {
                    "type": "string",
                    "description": "Hash value that can be used to validate the resource."
                }
            }
        }
    }
}
{
    "_readme": [
        "This file locks the dependencies of your project to a known state",
        "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
        "This file is @generated automatically"
    ],
    "content-hash": "bf258f8cbec69ad23a35e119a3807dc5",
    "packages": [
        {
            "name": "composer/ca-bundle",
            "version": "1.5.11",
            "source": {
                "type": "git",
                "url": "https://github.com/composer/ca-bundle.git",
                "reference": "68ff39175e8e94a4bb1d259407ce51a6a60f09e6"
            },
            "dist": {
                "type": "zip",
                "url": "https://api.github.com/repos/composer/ca-bundle/zipball/68ff39175e8e94a4bb1d259407ce51a6a60f09e6",
                "reference": "68ff39175e8e94a4bb1d259407ce51a6a60f09e6",
                "shasum": ""
            },
            "require": {
                "ext-openssl": "*",
                "ext-pcre": "*",
                "php": "^7.2 || ^8.0"
            },
            "require-dev": {
                "phpstan/phpstan": "^1.10",
                "phpunit/phpunit": "^8 || ^9",
                "psr/log": "^1.0 || ^2.0 || ^3.0",
                "symfony/process": "^4.0 || ^5.0 || ^6.0 || ^7.0"
            },
            "type": "library",
            "extra": {
                "branch-alias": {
                    "dev-main": "1.x-dev"
                }
            },
            "autoload": {
                "psr-4": {
                    "Composer\\CaBundle\\": "src"
                }
            },
            "notification-url": "https://packagist.org/downloads/",
            "license": [
                "MIT"
            ],
            "authors": [
                {
                    "name": "Jordi Boggiano",
                    "email": "j.boggiano@seld.be",
                    "homepage": "http://seld.be"
                }
            ],
            "description": "Lets you find a path to the system CA bundle, and includes a fallback to the Mozilla CA bundle.",
            "keywords": [
                "cabundle",
                "cacert",
                "certificate",
                "ssl",
                "tls"
            ],
            "support": {
                "irc": "irc://irc.freenode.org/composer",
                "issues": "https://github.com/composer/ca-bundle/issues",
                "source": "https://github.com/composer/ca-bundle/tree/1.5.11"
            },
            "funding": [
                {
                    "url": "https://packagist.com",
                    "type": "custom"
                },
                {
                    "url": "https://github.com/composer",
                    "type": "github"
                }
            ],
            "time": "2026-03-30T09:16:10+00:00"
        },
        {
            "name": "composer/class-map-generator",
            "version": "1.7.2",
            "source": {
                "type": "git",
                "url": "https://github.com/composer/class-map-generator.git",
                "reference": "6a9c2f0970022ab00dc58c07d0685dd712f2231b"
            },
            "dist": {
                "type": "zip",
                "url": "https://api.github.com/repos/composer/class-map-generator/zipball/6a9c2f0970022ab00dc58c07d0685dd712f2231b",
                "reference": "6a9c2f0970022ab00dc58c07d0685dd712f2231b",
                "shasum": ""
            },
            "require": {
                "composer/pcre": "^2.1 || ^3.1",
                "php": "^7.2 || ^8.0",
                "symfony/finder": "^4.4 || ^5.3 || ^6 || ^7 || ^8"
            },
            "require-dev": {
                "phpstan/phpstan": "^1.12 || ^2",
                "phpstan/phpstan-deprecation-rules": "^1 || ^2",
                "phpstan/phpstan-phpunit": "^1 || ^2",
                "phpstan/phpstan-strict-rules": "^1.1 || ^2",
                "phpunit/phpunit": "^8",
                "symfony/filesystem": "^5.4 || ^6 || ^7 || ^8"
            },
            "type": "library",
            "extra": {
                "branch-alias": {
                    "dev-main": "1.x-dev"
                }
            },
            "autoload": {
                "psr-4": {
                    "Composer\\ClassMapGenerator\\": "src"
                }
            },
            "notification-url": "https://packagist.org/downloads/",
            "license": [
                "MIT"
            ],
            "authors": [
                {
                    "name": "Jordi Boggiano",
                    "email": "j.boggiano@seld.be",
                    "homepage": "https://seld.be"
                }
            ],
            "description": "Utilities to scan PHP code and generate class maps.",
            "keywords": [
                "classmap"
            ],
            "support": {
                "issues": "https://github.com/composer/class-map-generator/issues",
                "source": "https://github.com/composer/class-map-generator/tree/1.7.2"
            },
            "funding": [
                {
                    "url": "https://packagist.com",
                    "type": "custom"
                },
                {
                    "url": "https://github.com/composer",
                    "type": "github"
                }
            ],
            "time": "2026-03-30T15:36:56+00:00"
        },
        {
            "name": "composer/metadata-minifier",
            "version": "1.0.0",
            "source": {
                "type": "git",
                "url": "https://github.com/composer/metadata-minifier.git",
                "reference": "c549d23829536f0d0e984aaabbf02af91f443207"
            },
            "dist": {
                "type": "zip",
                "url": "https://api.github.com/repos/composer/metadata-minifier/zipball/c549d23829536f0d0e984aaabbf02af91f443207",
                "reference": "c549d23829536f0d0e984aaabbf02af91f443207",
                "shasum": ""
            },
            "require": {
                "php": "^5.3.2 || ^7.0 || ^8.0"
            },
            "require-dev": {
                "composer/composer": "^2",
                "phpstan/phpstan": "^0.12.55",
                "symfony/phpunit-bridge": "^4.2 || ^5"
            },
            "type": "library",
            "extra": {
                "branch-alias": {
                    "dev-main": "1.x-dev"
                }
            },
            "autoload": {
                "psr-4": {
                    "Composer\\MetadataMinifier\\": "src"
                }
            },
            "notification-url": "https://packagist.org/downloads/",
            "license": [
                "MIT"
            ],
            "authors": [
                {
                    "name": "Jordi Boggiano",
                    "email": "j.boggiano@seld.be",
                    "homepage": "http://seld.be"
                }
            ],
            "description": "Small utility library that handles metadata minification and expansion.",
            "keywords": [
                "composer",
                "compression"
            ],
            "support": {
                "issues": "https://github.com/composer/metadata-minifier/issues",
                "source": "https://github.com/composer/metadata-minifier/tree/1.0.0"
            },
            "funding": [
                {
                    "url": "https://packagist.com",
                    "type": "custom"
                },
                {
                    "url": "https://github.com/composer",
                    "type": "github"
                },
                {
                    "url": "https://tidelift.com/funding/github/packagist/composer/composer",
                    "type": "tidelift"
                }
            ],
            "time": "2021-04-07T13:37:33+00:00"
        },
        {
            "name": "composer/pcre",
            "version": "2.3.2",
            "source": {
                "type": "git",
                "url": "https://github.com/composer/pcre.git",
                "reference": "ebb81df8f52b40172d14062ae96a06939d80a069"
            },
            "dist": {
                "type": "zip",
                "url": "https://api.github.com/repos/composer/pcre/zipball/ebb81df8f52b40172d14062ae96a06939d80a069",
                "reference": "ebb81df8f52b40172d14062ae96a06939d80a069",
                "shasum": ""
            },
            "require": {
                "php": "^7.2 || ^8.0"
            },
            "conflict": {
                "phpstan/phpstan": "<1.11.10"
            },
            "require-dev": {
                "phpstan/phpstan": "^1.12 || ^2",
                "phpstan/phpstan-strict-rules": "^1 || ^2",
                "phpunit/phpunit": "^8 || ^9"
            },
            "type": "library",
            "extra": {
                "phpstan": {
                    "includes": [
                        "extension.neon"
                    ]
                },
                "branch-alias": {
                    "dev-main": "2.x-dev"
                }
            },
            "autoload": {
                "psr-4": {
                    "Composer\\Pcre\\": "src"
                }
            },
            "notification-url": "https://packagist.org/downloads/",
            "license": [
                "MIT"
            ],
            "authors": [
                {
                    "name": "Jordi Boggiano",
                    "email": "j.boggiano@seld.be",
                    "homepage": "http://seld.be"
                }
            ],
            "description": "PCRE wrapping library that offers type-safe preg_* replacements.",
            "keywords": [
                "PCRE",
                "preg",
                "regex",
                "regular expression"
            ],
            "support": {
                "issues": "https://github.com/composer/pcre/issues",
                "source": "https://github.com/composer/pcre/tree/2.3.2"
            },
            "funding": [
                {
                    "url": "https://packagist.com",
                    "type": "custom"
                },
                {
                    "url": "https://github.com/composer",
                    "type": "github"
                },
                {
                    "url": "https://tidelift.com/funding/github/packagist/composer/composer",
                    "type": "tidelift"
                }
            ],
            "time": "2024-11-12T16:24:47+00:00"
        },
        {
            "name": "composer/semver",
            "version": "3.4.4",
            "source": {
                "type": "git",
                "url": "https://github.com/composer/semver.git",
                "reference": "198166618906cb2de69b95d7d47e5fa8aa1b2b95"
            },
            "dist": {
                "type": "zip",
                "url": "https://api.github.com/repos/composer/semver/zipball/198166618906cb2de69b95d7d47e5fa8aa1b2b95",
                "reference": "198166618906cb2de69b95d7d47e5fa8aa1b2b95",
                "shasum": ""
            },
            "require": {
                "php": "^5.3.2 || ^7.0 || ^8.0"
            },
            "require-dev": {
                "phpstan/phpstan": "^1.11",
                "symfony/phpunit-bridge": "^3 || ^7"
            },
            "type": "library",
            "extra": {
                "branch-alias": {
                    "dev-main": "3.x-dev"
                }
            },
            "autoload": {
                "psr-4": {
                    "Composer\\Semver\\": "src"
                }
            },
            "notification-url": "https://packagist.org/downloads/",
            "license": [
                "MIT"
            ],
            "authors": [
                {
                    "name": "Nils Adermann",
                    "email": "naderman@naderman.de",
                    "homepage": "http://www.naderman.de"
                },
                {
                    "name": "Jordi Boggiano",
                    "email": "j.boggiano@seld.be",
                    "homepage": "http://seld.be"
                },
                {
                    "name": "Rob Bast",
                    "email": "rob.bast@gmail.com",
                    "homepage": "http://robbast.nl"
                }
            ],
            "description": "Semver library that offers utilities, version constraint parsing and validation.",
            "keywords": [
                "semantic",
                "semver",
                "validation",
                "versioning"
            ],
            "support": {
                "irc": "ircs://irc.libera.chat:6697/composer",
                "issues": "https://github.com/composer/semver/issues",
                "source": "https://github.com/composer/semver/tree/3.4.4"
            },
            "funding": [
                {
                    "url": "https://packagist.com",
                    "type": "custom"
                },
                {
                    "url": "https://github.com/composer",
                    "type": "github"
                }
            ],
            "time": "2025-08-20T19:15:30+00:00"
        },
        {
            "name": "composer/spdx-licenses",
            "version": "1.6.0",
            "source": {
                "type": "git",
                "url": "https://github.com/composer/spdx-licenses.git",
                "reference": "5ecd0cb4177696f9fd48f1605dda81db3dee7889"
            },
            "dist": {
                "type": "zip",
                "url": "https://api.github.com/repos/composer/spdx-licenses/zipball/5ecd0cb4177696f9fd48f1605dda81db3dee7889",
                "reference": "5ecd0cb4177696f9fd48f1605dda81db3dee7889",
                "shasum": ""
            },
            "require": {
                "php": "^7.2 || ^8.0"
            },
            "require-dev": {
                "phpstan/phpstan": "^1.11",
                "symfony/phpunit-bridge": "^6.4.25 || ^7.3.3 || ^8.0"
            },
            "type": "library",
            "extra": {
                "branch-alias": {
                    "dev-main": "1.x-dev"
                }
            },
            "autoload": {
                "psr-4": {
                    "Composer\\Spdx\\": "src"
                }
            },
            "notification-url": "https://packagist.org/downloads/",
            "license": [
                "MIT"
            ],
            "authors": [
                {
                    "name": "Nils Adermann",
                    "email": "naderman@naderman.de",
                    "homepage": "http://www.naderman.de"
                },
                {
                    "name": "Jordi Boggiano",
                    "email": "j.boggiano@seld.be",
                    "homepage": "http://seld.be"
                },
                {
                    "name": "Rob Bast",
                    "email": "rob.bast@gmail.com",
                    "homepage": "http://robbast.nl"
                }
            ],
            "description": "SPDX licenses list and validation library.",
            "keywords": [
                "license",
                "spdx",
                "validator"
            ],
            "support": {
                "irc": "ircs://irc.libera.chat:6697/composer",
                "issues": "https://github.com/composer/spdx-licenses/issues",
                "source": "https://github.com/composer/spdx-licenses/tree/1.6.0"
            },
            "funding": [
                {
                    "url": "https://packagist.com",
                    "type": "custom"
                },
                {
                    "url": "https://github.com/composer",
                    "type": "github"
                }
            ],
            "time": "2026-04-08T20:18:39+00:00"
        },
        {
            "name": "composer/xdebug-handler",
            "version": "3.0.5",
            "source": {
                "type": "git",
                "url": "https://github.com/composer/xdebug-handler.git",
                "reference": "6c1925561632e83d60a44492e0b344cf48ab85ef"
            },
            "dist": {
                "type": "zip",
                "url": "https://api.github.com/repos/composer/xdebug-handler/zipball/6c1925561632e83d60a44492e0b344cf48ab85ef",
                "reference": "6c1925561632e83d60a44492e0b344cf48ab85ef",
                "shasum": ""
            },
            "require": {
                "composer/pcre": "^1 || ^2 || ^3",
                "php": "^7.2.5 || ^8.0",
                "psr/log": "^1 || ^2 || ^3"
            },
            "require-dev": {
                "phpstan/phpstan": "^1.0",
                "phpstan/phpstan-strict-rules": "^1.1",
                "phpunit/phpunit": "^8.5 || ^9.6 || ^10.5"
            },
            "type": "library",
            "autoload": {
                "psr-4": {
                    "Composer\\XdebugHandler\\": "src"
                }
            },
            "notification-url": "https://packagist.org/downloads/",
            "license": [
                "MIT"
            ],
            "authors": [
                {
                    "name": "John Stevenson",
                    "email": "john-stevenson@blueyonder.co.uk"
                }
            ],
            "description": "Restarts a process without Xdebug.",
            "keywords": [
                "Xdebug",
                "performance"
            ],
            "support": {
                "irc": "ircs://irc.libera.chat:6697/composer",
                "issues": "https://github.com/composer/xdebug-handler/issues",
                "source": "https://github.com/composer/xdebug-handler/tree/3.0.5"
            },
            "funding": [
                {
                    "url": "https://packagist.com",
                    "type": "custom"
                },
                {
                    "url": "https://github.com/composer",
                    "type": "github"
                },
                {
                    "url": "https://tidelift.com/funding/github/packagist/composer/composer",
                    "type": "tidelift"
                }
            ],
            "time": "2024-05-06T16:37:16+00:00"
        },
        {
            "name": "justinrainbow/json-schema",
            "version": "6.8.0",
            "source": {
                "type": "git",
                "url": "https://github.com/jsonrainbow/json-schema.git",
                "reference": "89ac92bcfe5d0a8a4433c7b89d394553ae7250cc"
            },
            "dist": {
                "type": "zip",
                "url": "https://api.github.com/repos/jsonrainbow/json-schema/zipball/89ac92bcfe5d0a8a4433c7b89d394553ae7250cc",
                "reference": "89ac92bcfe5d0a8a4433c7b89d394553ae7250cc",
                "shasum": ""
            },
            "require": {
                "ext-json": "*",
                "marc-mabe/php-enum": "^4.4",
                "php": "^7.2 || ^8.0"
            },
            "require-dev": {
                "friendsofphp/php-cs-fixer": "3.3.0",
                "json-schema/json-schema-test-suite": "^23.2",
                "marc-mabe/php-enum-phpstan": "^2.0",
                "phpspec/prophecy": "^1.19",
                "phpstan/phpstan": "^1.12",
                "phpunit/phpunit": "^8.5"
            },
            "bin": [
                "bin/validate-json"
            ],
            "type": "library",
            "extra": {
                "branch-alias": {
                    "dev-master": "6.x-dev"
                }
            },
            "autoload": {
                "psr-4": {
                    "JsonSchema\\": "src/JsonSchema/"
                }
            },
            "notification-url": "https://packagist.org/downloads/",
            "license": [
                "MIT"
            ],
            "authors": [
                {
                    "name": "Bruno Prieto Reis",
                    "email": "bruno.p.reis@gmail.com"
                },
                {
                    "name": "Justin Rainbow",
                    "email": "justin.rainbow@gmail.com"
                },
                {
                    "name": "Igor Wiedler",
                    "email": "igor@wiedler.ch"
                },
                {
                    "name": "Robert Schönthal",
                    "email": "seroscho@googlemail.com"
                }
            ],
            "description": "A library to validate a json schema.",
            "homepage": "https://github.com/jsonrainbow/json-schema",
            "keywords": [
                "json",
                "schema"
            ],
            "support": {
                "issues": "https://github.com/jsonrainbow/json-schema/issues",
                "source": "https://github.com/jsonrainbow/json-schema/tree/6.8.0"
            },
            "time": "2026-04-02T12:43:11+00:00"
        },
        {
            "name": "marc-mabe/php-enum",
            "version": "v4.7.2",
            "source": {
                "type": "git",
                "url": "https://github.com/marc-mabe/php-enum.git",
                "reference": "bb426fcdd65c60fb3638ef741e8782508fda7eef"
            },
            "dist": {
                "type": "zip",
                "url": "https://api.github.com/repos/marc-mabe/php-enum/zipball/bb426fcdd65c60fb3638ef741e8782508fda7eef",
                "reference": "bb426fcdd65c60fb3638ef741e8782508fda7eef",
                "shasum": ""
            },
            "require": {
                "ext-reflection": "*",
                "php": "^7.1 | ^8.0"
            },
            "require-dev": {
                "phpbench/phpbench": "^0.16.10 || ^1.0.4",
                "phpstan/phpstan": "^1.3.1",
                "phpunit/phpunit": "^7.5.20 | ^8.5.22 | ^9.5.11",
                "vimeo/psalm": "^4.17.0 | ^5.26.1"
            },
            "type": "library",
            "extra": {
                "branch-alias": {
                    "dev-3.x": "3.2-dev",
                    "dev-master": "4.7-dev"
                }
            },
            "autoload": {
                "psr-4": {
                    "MabeEnum\\": "src/"
                },
                "classmap": [
                    "stubs/Stringable.php"
                ]
            },
            "notification-url": "https://packagist.org/downloads/",
            "license": [
                "BSD-3-Clause"
            ],
            "authors": [
                {
                    "name": "Marc Bennewitz",
                    "email": "dev@mabe.berlin",
                    "homepage": "https://mabe.berlin/",
                    "role": "Lead"
                }
            ],
            "description": "Simple and fast implementation of enumerations with native PHP",
            "homepage": "https://github.com/marc-mabe/php-enum",
            "keywords": [
                "enum",
                "enum-map",
                "enum-set",
                "enumeration",
                "enumerator",
                "enummap",
                "enumset",
                "map",
                "set",
                "type",
                "type-hint",
                "typehint"
            ],
            "support": {
                "issues": "https://github.com/marc-mabe/php-enum/issues",
                "source": "https://github.com/marc-mabe/php-enum/tree/v4.7.2"
            },
            "time": "2025-09-14T11:18:39+00:00"
        },
        {
            "name": "psr/container",
            "version": "1.1.1",
            "source": {
                "type": "git",
                "url": "https://github.com/php-fig/container.git",
                "reference": "8622567409010282b7aeebe4bb841fe98b58dcaf"
            },
            "dist": {
                "type": "zip",
                "url": "https://api.github.com/repos/php-fig/container/zipball/8622567409010282b7aeebe4bb841fe98b58dcaf",
                "reference": "8622567409010282b7aeebe4bb841fe98b58dcaf",
                "shasum": ""
            },
            "require": {
                "php": ">=7.2.0"
            },
            "type": "library",
            "autoload": {
                "psr-4": {
                    "Psr\\Container\\": "src/"
                }
            },
            "notification-url": "https://packagist.org/downloads/",
            "license": [
                "MIT"
            ],
            "authors": [
                {
                    "name": "PHP-FIG",
                    "homepage": "https://www.php-fig.org/"
                }
            ],
            "description": "Common Container Interface (PHP FIG PSR-11)",
            "homepage": "https://github.com/php-fig/container",
            "keywords": [
                "PSR-11",
                "container",
                "container-interface",
                "container-interop",
                "psr"
            ],
            "support": {
                "issues": "https://github.com/php-fig/container/issues",
                "source": "https://github.com/php-fig/container/tree/1.1.1"
            },
            "time": "2021-03-05T17:36:06+00:00"
        },
        {
            "name": "psr/log",
            "version": "1.1.4",
            "source": {
                "type": "git",
                "url": "https://github.com/php-fig/log.git",
                "reference": "d49695b909c3b7628b6289db5479a1c204601f11"
            },
            "dist": {
                "type": "zip",
                "url": "https://api.github.com/repos/php-fig/log/zipball/d49695b909c3b7628b6289db5479a1c204601f11",
                "reference": "d49695b909c3b7628b6289db5479a1c204601f11",
                "shasum": ""
            },
            "require": {
                "php": ">=5.3.0"
            },
            "type": "library",
            "extra": {
                "branch-alias": {
                    "dev-master": "1.1.x-dev"
                }
            },
            "autoload": {
                "psr-4": {
                    "Psr\\Log\\": "Psr/Log/"
                }
            },
            "notification-url": "https://packagist.org/downloads/",
            "license": [
                "MIT"
            ],
            "authors": [
                {
                    "name": "PHP-FIG",
                    "homepage": "https://www.php-fig.org/"
                }
            ],
            "description": "Common interface for logging libraries",
            "homepage": "https://github.com/php-fig/log",
            "keywords": [
                "log",
                "psr",
                "psr-3"
            ],
            "support": {
                "source": "https://github.com/php-fig/log/tree/1.1.4"
            },
            "time": "2021-05-03T11:20:27+00:00"
        },
        {
            "name": "react/promise",
            "version": "v3.3.0",
            "source": {
                "type": "git",
                "url": "https://github.com/reactphp/promise.git",
                "reference": "23444f53a813a3296c1368bb104793ce8d88f04a"
            },
            "dist": {
                "type": "zip",
                "url": "https://api.github.com/repos/reactphp/promise/zipball/23444f53a813a3296c1368bb104793ce8d88f04a",
                "reference": "23444f53a813a3296c1368bb104793ce8d88f04a",
                "shasum": ""
            },
            "require": {
                "php": ">=7.1.0"
            },
            "require-dev": {
                "phpstan/phpstan": "1.12.28 || 1.4.10",
                "phpunit/phpunit": "^9.6 || ^7.5"
            },
            "type": "library",
            "autoload": {
                "files": [
                    "src/functions_include.php"
                ],
                "psr-4": {
                    "React\\Promise\\": "src/"
                }
            },
            "notification-url": "https://packagist.org/downloads/",
            "license": [
                "MIT"
            ],
            "authors": [
                {
                    "name": "Jan Sorgalla",
                    "email": "jsorgalla@gmail.com",
                    "homepage": "https://sorgalla.com/"
                },
                {
                    "name": "Christian Lück",
                    "email": "christian@clue.engineering",
                    "homepage": "https://clue.engineering/"
                },
                {
                    "name": "Cees-Jan Kiewiet",
                    "email": "reactphp@ceesjankiewiet.nl",
                    "homepage": "https://wyrihaximus.net/"
                },
                {
                    "name": "Chris Boden",
                    "email": "cboden@gmail.com",
                    "homepage": "https://cboden.dev/"
                }
            ],
            "description": "A lightweight implementation of CommonJS Promises/A for PHP",
            "keywords": [
                "promise",
                "promises"
            ],
            "support": {
                "issues": "https://github.com/reactphp/promise/issues",
                "source": "https://github.com/reactphp/promise/tree/v3.3.0"
            },
            "funding": [
                {
                    "url": "https://opencollective.com/reactphp",
                    "type": "open_collective"
                }
            ],
            "time": "2025-08-19T18:57:03+00:00"
        },
        {
            "name": "seld/jsonlint",
            "version": "1.11.0",
            "source": {
                "type": "git",
                "url": "https://github.com/Seldaek/jsonlint.git",
                "reference": "1748aaf847fc731cfad7725aec413ee46f0cc3a2"
            },
            "dist": {
                "type": "zip",
                "url": "https://api.github.com/repos/Seldaek/jsonlint/zipball/1748aaf847fc731cfad7725aec413ee46f0cc3a2",
                "reference": "1748aaf847fc731cfad7725aec413ee46f0cc3a2",
                "shasum": ""
            },
            "require": {
                "php": "^5.3 || ^7.0 || ^8.0"
            },
            "require-dev": {
                "phpstan/phpstan": "^1.11",
                "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.0 || ^8.5.13"
            },
            "bin": [
                "bin/jsonlint"
            ],
            "type": "library",
            "autoload": {
                "psr-4": {
                    "Seld\\JsonLint\\": "src/Seld/JsonLint/"
                }
            },
            "notification-url": "https://packagist.org/downloads/",
            "license": [
                "MIT"
            ],
            "authors": [
                {
                    "name": "Jordi Boggiano",
                    "email": "j.boggiano@seld.be",
                    "homepage": "https://seld.be"
                }
            ],
            "description": "JSON Linter",
            "keywords": [
                "json",
                "linter",
                "parser",
                "validator"
            ],
            "support": {
                "issues": "https://github.com/Seldaek/jsonlint/issues",
                "source": "https://github.com/Seldaek/jsonlint/tree/1.11.0"
            },
            "funding": [
                {
                    "url": "https://github.com/Seldaek",
                    "type": "github"
                },
                {
                    "url": "https://tidelift.com/funding/github/packagist/seld/jsonlint",
                    "type": "tidelift"
                }
            ],
            "time": "2024-07-11T14:55:45+00:00"
        },
        {
            "name": "seld/phar-utils",
            "version": "1.2.1",
            "source": {
                "type": "git",
                "url": "https://github.com/Seldaek/phar-utils.git",
                "reference": "ea2f4014f163c1be4c601b9b7bd6af81ba8d701c"
            },
            "dist": {
                "type": "zip",
                "url": "https://api.github.com/repos/Seldaek/phar-utils/zipball/ea2f4014f163c1be4c601b9b7bd6af81ba8d701c",
                "reference": "ea2f4014f163c1be4c601b9b7bd6af81ba8d701c",
                "shasum": ""
            },
            "require": {
                "php": ">=5.3"
            },
            "type": "library",
            "extra": {
                "branch-alias": {
                    "dev-master": "1.x-dev"
                }
            },
            "autoload": {
                "psr-4": {
                    "Seld\\PharUtils\\": "src/"
                }
            },
            "notification-url": "https://packagist.org/downloads/",
            "license": [
                "MIT"
            ],
            "authors": [
                {
                    "name": "Jordi Boggiano",
                    "email": "j.boggiano@seld.be"
                }
            ],
            "description": "PHAR file format utilities, for when PHP phars you up",
            "keywords": [
                "phar"
            ],
            "support": {
                "issues": "https://github.com/Seldaek/phar-utils/issues",
                "source": "https://github.com/Seldaek/phar-utils/tree/1.2.1"
            },
            "time": "2022-08-31T10:31:18+00:00"
        },
        {
            "name": "seld/signal-handler",
            "version": "2.0.2",
            "source": {
                "type": "git",
                "url": "https://github.com/Seldaek/signal-handler.git",
                "reference": "04a6112e883ad76c0ada8e4a9f7520bbfdb6bb98"
            },
            "dist": {
                "type": "zip",
                "url": "https://api.github.com/repos/Seldaek/signal-handler/zipball/04a6112e883ad76c0ada8e4a9f7520bbfdb6bb98",
                "reference": "04a6112e883ad76c0ada8e4a9f7520bbfdb6bb98",
                "shasum": ""
            },
            "require": {
                "php": ">=7.2.0"
            },
            "require-dev": {
                "phpstan/phpstan": "^1",
                "phpstan/phpstan-deprecation-rules": "^1.0",
                "phpstan/phpstan-phpunit": "^1",
                "phpstan/phpstan-strict-rules": "^1.3",
                "phpunit/phpunit": "^7.5.20 || ^8.5.23",
                "psr/log": "^1 || ^2 || ^3"
            },
            "type": "library",
            "extra": {
                "branch-alias": {
                    "dev-main": "2.x-dev"
                }
            },
            "autoload": {
                "psr-4": {
                    "Seld\\Signal\\": "src/"
                }
            },
            "notification-url": "https://packagist.org/downloads/",
            "license": [
                "MIT"
            ],
            "authors": [
                {
                    "name": "Jordi Boggiano",
                    "email": "j.boggiano@seld.be",
                    "homepage": "http://seld.be"
                }
            ],
            "description": "Simple unix signal handler that silently fails where signals are not supported for easy cross-platform development",
            "keywords": [
                "posix",
                "sigint",
                "signal",
                "sigterm",
                "unix"
            ],
            "support": {
                "issues": "https://github.com/Seldaek/signal-handler/issues",
                "source": "https://github.com/Seldaek/signal-handler/tree/2.0.2"
            },
            "time": "2023-09-03T09:24:00+00:00"
        },
        {
            "name": "symfony/console",
            "version": "v5.4.47",
            "source": {
                "type": "git",
                "url": "https://github.com/symfony/console.git",
                "reference": "c4ba980ca61a9eb18ee6bcc73f28e475852bb1ed"
            },
            "dist": {
                "type": "zip",
                "url": "https://api.github.com/repos/symfony/console/zipball/c4ba980ca61a9eb18ee6bcc73f28e475852bb1ed",
                "reference": "c4ba980ca61a9eb18ee6bcc73f28e475852bb1ed",
                "shasum": ""
            },
            "require": {
                "php": ">=7.2.5",
                "symfony/deprecation-contracts": "^2.1|^3",
                "symfony/polyfill-mbstring": "~1.0",
                "symfony/polyfill-php73": "^1.9",
                "symfony/polyfill-php80": "^1.16",
                "symfony/service-contracts": "^1.1|^2|^3",
                "symfony/string": "^5.1|^6.0"
            },
            "conflict": {
                "psr/log": ">=3",
                "symfony/dependency-injection": "<4.4",
                "symfony/dotenv": "<5.1",
                "symfony/event-dispatcher": "<4.4",
                "symfony/lock": "<4.4",
                "symfony/process": "<4.4"
            },
            "provide": {
                "psr/log-implementation": "1.0|2.0"
            },
            "require-dev": {
                "psr/log": "^1|^2",
                "symfony/config": "^4.4|^5.0|^6.0",
                "symfony/dependency-injection": "^4.4|^5.0|^6.0",
                "symfony/event-dispatcher": "^4.4|^5.0|^6.0",
                "symfony/lock": "^4.4|^5.0|^6.0",
                "symfony/process": "^4.4|^5.0|^6.0",
                "symfony/var-dumper": "^4.4|^5.0|^6.0"
            },
            "suggest": {
                "psr/log": "For using the console logger",
                "symfony/event-dispatcher": "",
                "symfony/lock": "",
                "symfony/process": ""
            },
            "type": "library",
            "autoload": {
                "psr-4": {
                    "Symfony\\Component\\Console\\": ""
                },
                "exclude-from-classmap": [
                    "/Tests/"
                ]
            },
            "notification-url": "https://packagist.org/downloads/",
            "license": [
                "MIT"
            ],
            "authors": [
                {
                    "name": "Fabien Potencier",
                    "email": "fabien@symfony.com"
                },
                {
                    "name": "Symfony Community",
                    "homepage": "https://symfony.com/contributors"
                }
            ],
            "description": "Eases the creation of beautiful and testable command line interfaces",
            "homepage": "https://symfony.com",
            "keywords": [
                "cli",
                "command-line",
                "console",
                "terminal"
            ],
            "support": {
                "source": "https://github.com/symfony/console/tree/v5.4.47"
            },
            "funding": [
                {
                    "url": "https://symfony.com/sponsor",
                    "type": "custom"
                },
                {
                    "url": "https://github.com/fabpot",
                    "type": "github"
                },
                {
                    "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
                    "type": "tidelift"
                }
            ],
            "time": "2024-11-06T11:30:55+00:00"
        },
        {
            "name": "symfony/deprecation-contracts",
            "version": "v2.5.4",
            "source": {
                "type": "git",
                "url": "https://github.com/symfony/deprecation-contracts.git",
                "reference": "605389f2a7e5625f273b53960dc46aeaf9c62918"
            },
            "dist": {
                "type": "zip",
                "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/605389f2a7e5625f273b53960dc46aeaf9c62918",
                "reference": "605389f2a7e5625f273b53960dc46aeaf9c62918",
                "shasum": ""
            },
            "require": {
                "php": ">=7.1"
            },
            "type": "library",
            "extra": {
                "thanks": {
                    "url": "https://github.com/symfony/contracts",
                    "name": "symfony/contracts"
                },
                "branch-alias": {
                    "dev-main": "2.5-dev"
                }
            },
            "autoload": {
                "files": [
                    "function.php"
                ]
            },
            "notification-url": "https://packagist.org/downloads/",
            "license": [
                "MIT"
            ],
            "authors": [
                {
                    "name": "Nicolas Grekas",
                    "email": "p@tchwork.com"
                },
                {
                    "name": "Symfony Community",
                    "homepage": "https://symfony.com/contributors"
                }
            ],
            "description": "A generic function and convention to trigger deprecation notices",
            "homepage": "https://symfony.com",
            "support": {
                "source": "https://github.com/symfony/deprecation-contracts/tree/v2.5.4"
            },
            "funding": [
                {
                    "url": "https://symfony.com/sponsor",
                    "type": "custom"
                },
                {
                    "url": "https://github.com/fabpot",
                    "type": "github"
                },
                {
                    "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
                    "type": "tidelift"
                }
            ],
            "time": "2024-09-25T14:11:13+00:00"
        },
        {
            "name": "symfony/filesystem",
            "version": "v5.4.45",
            "source": {
                "type": "git",
                "url": "https://github.com/symfony/filesystem.git",
                "reference": "57c8294ed37d4a055b77057827c67f9558c95c54"
            },
            "dist": {
                "type": "zip",
                "url": "https://api.github.com/repos/symfony/filesystem/zipball/57c8294ed37d4a055b77057827c67f9558c95c54",
                "reference": "57c8294ed37d4a055b77057827c67f9558c95c54",
                "shasum": ""
            },
            "require": {
                "php": ">=7.2.5",
                "symfony/polyfill-ctype": "~1.8",
                "symfony/polyfill-mbstring": "~1.8",
                "symfony/polyfill-php80": "^1.16"
            },
            "require-dev": {
                "symfony/process": "^5.4|^6.4"
            },
            "type": "library",
            "autoload": {
                "psr-4": {
                    "Symfony\\Component\\Filesystem\\": ""
                },
                "exclude-from-classmap": [
                    "/Tests/"
                ]
            },
            "notification-url": "https://packagist.org/downloads/",
            "license": [
                "MIT"
            ],
            "authors": [
                {
                    "name": "Fabien Potencier",
                    "email": "fabien@symfony.com"
                },
                {
                    "name": "Symfony Community",
                    "homepage": "https://symfony.com/contributors"
                }
            ],
            "description": "Provides basic utilities for the filesystem",
            "homepage": "https://symfony.com",
            "support": {
                "source": "https://github.com/symfony/filesystem/tree/v5.4.45"
            },
            "funding": [
                {
                    "url": "https://symfony.com/sponsor",
                    "type": "custom"
                },
                {
                    "url": "https://github.com/fabpot",
                    "type": "github"
                },
                {
                    "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
                    "type": "tidelift"
                }
            ],
            "time": "2024-10-22T13:05:35+00:00"
        },
        {
            "name": "symfony/finder",
            "version": "v5.4.45",
            "source": {
                "type": "git",
                "url": "https://github.com/symfony/finder.git",
                "reference": "63741784cd7b9967975eec610b256eed3ede022b"
            },
            "dist": {
                "type": "zip",
                "url": "https://api.github.com/repos/symfony/finder/zipball/63741784cd7b9967975eec610b256eed3ede022b",
                "reference": "63741784cd7b9967975eec610b256eed3ede022b",
                "shasum": ""
            },
            "require": {
                "php": ">=7.2.5",
                "symfony/deprecation-contracts": "^2.1|^3",
                "symfony/polyfill-php80": "^1.16"
            },
            "type": "library",
            "autoload": {
                "psr-4": {
                    "Symfony\\Component\\Finder\\": ""
                },
                "exclude-from-classmap": [
                    "/Tests/"
                ]
            },
            "notification-url": "https://packagist.org/downloads/",
            "license": [
                "MIT"
            ],
            "authors": [
                {
                    "name": "Fabien Potencier",
                    "email": "fabien@symfony.com"
                },
                {
                    "name": "Symfony Community",
                    "homepage": "https://symfony.com/contributors"
                }
            ],
            "description": "Finds files and directories via an intuitive fluent interface",
            "homepage": "https://symfony.com",
            "support": {
                "source": "https://github.com/symfony/finder/tree/v5.4.45"
            },
            "funding": [
                {
                    "url": "https://symfony.com/sponsor",
                    "type": "custom"
                },
                {
                    "url": "https://github.com/fabpot",
                    "type": "github"
                },
                {
                    "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
                    "type": "tidelift"
                }
            ],
            "time": "2024-09-28T13:32:08+00:00"
        },
        {
            "name": "symfony/polyfill-ctype",
            "version": "v1.34.0",
            "source": {
                "type": "git",
                "url": "https://github.com/symfony/polyfill-ctype.git",
                "reference": "141046a8f9477948ff284fa65be2095baafb94f2"
            },
            "dist": {
                "type": "zip",
                "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/141046a8f9477948ff284fa65be2095baafb94f2",
                "reference": "141046a8f9477948ff284fa65be2095baafb94f2",
                "shasum": ""
            },
            "require": {
                "php": ">=7.2"
            },
            "provide": {
                "ext-ctype": "*"
            },
            "suggest": {
                "ext-ctype": "For best performance"
            },
            "type": "library",
            "extra": {
                "thanks": {
                    "url": "https://github.com/symfony/polyfill",
                    "name": "symfony/polyfill"
                }
            },
            "autoload": {
                "files": [
                    "bootstrap.php"
                ],
                "psr-4": {
                    "Symfony\\Polyfill\\Ctype\\": ""
                }
            },
            "notification-url": "https://packagist.org/downloads/",
            "license": [
                "MIT"
            ],
            "authors": [
                {
                    "name": "Gert de Pagter",
                    "email": "BackEndTea@gmail.com"
                },
                {
                    "name": "Symfony Community",
                    "homepage": "https://symfony.com/contributors"
                }
            ],
            "description": "Symfony polyfill for ctype functions",
            "homepage": "https://symfony.com",
            "keywords": [
                "compatibility",
                "ctype",
                "polyfill",
                "portable"
            ],
            "support": {
                "source": "https://github.com/symfony/polyfill-ctype/tree/v1.34.0"
            },
            "funding": [
                {
                    "url": "https://symfony.com/sponsor",
                    "type": "custom"
                },
                {
                    "url": "https://github.com/fabpot",
                    "type": "github"
                },
                {
                    "url": "https://github.com/nicolas-grekas",
                    "type": "github"
                },
                {
                    "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
                    "type": "tidelift"
                }
            ],
            "time": "2026-04-10T16:19:22+00:00"
        },
        {
            "name": "symfony/polyfill-intl-grapheme",
            "version": "v1.34.0",
            "source": {
                "type": "git",
                "url": "https://github.com/symfony/polyfill-intl-grapheme.git",
                "reference": "ad1b7b9092976d6c948b8a187cec9faaea9ec1df"
            },
            "dist": {
                "type": "zip",
                "url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/ad1b7b9092976d6c948b8a187cec9faaea9ec1df",
                "reference": "ad1b7b9092976d6c948b8a187cec9faaea9ec1df",
                "shasum": ""
            },
            "require": {
                "php": ">=7.2"
            },
            "suggest": {
                "ext-intl": "For best performance"
            },
            "type": "library",
            "extra": {
                "thanks": {
                    "url": "https://github.com/symfony/polyfill",
                    "name": "symfony/polyfill"
                }
            },
            "autoload": {
                "files": [
                    "bootstrap.php"
                ],
                "psr-4": {
                    "Symfony\\Polyfill\\Intl\\Grapheme\\": ""
                }
            },
            "notification-url": "https://packagist.org/downloads/",
            "license": [
                "MIT"
            ],
            "authors": [
                {
                    "name": "Nicolas Grekas",
                    "email": "p@tchwork.com"
                },
                {
                    "name": "Symfony Community",
                    "homepage": "https://symfony.com/contributors"
                }
            ],
            "description": "Symfony polyfill for intl's grapheme_* functions",
            "homepage": "https://symfony.com",
            "keywords": [
                "compatibility",
                "grapheme",
                "intl",
                "polyfill",
                "portable",
                "shim"
            ],
            "support": {
                "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.34.0"
            },
            "funding": [
                {
                    "url": "https://symfony.com/sponsor",
                    "type": "custom"
                },
                {
                    "url": "https://github.com/fabpot",
                    "type": "github"
                },
                {
                    "url": "https://github.com/nicolas-grekas",
                    "type": "github"
                },
                {
                    "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
                    "type": "tidelift"
                }
            ],
            "time": "2026-04-10T16:19:22+00:00"
        },
        {
            "name": "symfony/polyfill-intl-normalizer",
            "version": "v1.34.0",
            "source": {
                "type": "git",
                "url": "https://github.com/symfony/polyfill-intl-normalizer.git",
                "reference": "3833d7255cc303546435cb650316bff708a1c75c"
            },
            "dist": {
                "type": "zip",
                "url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/3833d7255cc303546435cb650316bff708a1c75c",
                "reference": "3833d7255cc303546435cb650316bff708a1c75c",
                "shasum": ""
            },
            "require": {
                "php": ">=7.2"
            },
            "suggest": {
                "ext-intl": "For best performance"
            },
            "type": "library",
            "extra": {
                "thanks": {
                    "url": "https://github.com/symfony/polyfill",
                    "name": "symfony/polyfill"
                }
            },
            "autoload": {
                "files": [
                    "bootstrap.php"
                ],
                "psr-4": {
                    "Symfony\\Polyfill\\Intl\\Normalizer\\": ""
                },
                "classmap": [
                    "Resources/stubs"
                ]
            },
            "notification-url": "https://packagist.org/downloads/",
            "license": [
                "MIT"
            ],
            "authors": [
                {
                    "name": "Nicolas Grekas",
                    "email": "p@tchwork.com"
                },
                {
                    "name": "Symfony Community",
                    "homepage": "https://symfony.com/contributors"
                }
            ],
            "description": "Symfony polyfill for intl's Normalizer class and related functions",
            "homepage": "https://symfony.com",
            "keywords": [
                "compatibility",
                "intl",
                "normalizer",
                "polyfill",
                "portable",
                "shim"
            ],
            "support": {
                "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.34.0"
            },
            "funding": [
                {
                    "url": "https://symfony.com/sponsor",
                    "type": "custom"
                },
                {
                    "url": "https://github.com/fabpot",
                    "type": "github"
                },
                {
                    "url": "https://github.com/nicolas-grekas",
                    "type": "github"
                },
                {
                    "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
                    "type": "tidelift"
                }
            ],
            "time": "2024-09-09T11:45:10+00:00"
        },
        {
            "name": "symfony/polyfill-mbstring",
            "version": "v1.34.0",
            "source": {
                "type": "git",
                "url": "https://github.com/symfony/polyfill-mbstring.git",
                "reference": "6a21eb99c6973357967f6ce3708cd55a6bec6315"
            },
            "dist": {
                "type": "zip",
                "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/6a21eb99c6973357967f6ce3708cd55a6bec6315",
                "reference": "6a21eb99c6973357967f6ce3708cd55a6bec6315",
                "shasum": ""
            },
            "require": {
                "ext-iconv": "*",
                "php": ">=7.2"
            },
            "provide": {
                "ext-mbstring": "*"
            },
            "suggest": {
                "ext-mbstring": "For best performance"
            },
            "type": "library",
            "extra": {
                "thanks": {
                    "url": "https://github.com/symfony/polyfill",
                    "name": "symfony/polyfill"
                }
            },
            "autoload": {
                "files": [
                    "bootstrap.php"
                ],
                "psr-4": {
                    "Symfony\\Polyfill\\Mbstring\\": ""
                }
            },
            "notification-url": "https://packagist.org/downloads/",
            "license": [
                "MIT"
            ],
            "authors": [
                {
                    "name": "Nicolas Grekas",
                    "email": "p@tchwork.com"
                },
                {
                    "name": "Symfony Community",
                    "homepage": "https://symfony.com/contributors"
                }
            ],
            "description": "Symfony polyfill for the Mbstring extension",
            "homepage": "https://symfony.com",
            "keywords": [
                "compatibility",
                "mbstring",
                "polyfill",
                "portable",
                "shim"
            ],
            "support": {
                "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.34.0"
            },
            "funding": [
                {
                    "url": "https://symfony.com/sponsor",
                    "type": "custom"
                },
                {
                    "url": "https://github.com/fabpot",
                    "type": "github"
                },
                {
                    "url": "https://github.com/nicolas-grekas",
                    "type": "github"
                },
                {
                    "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
                    "type": "tidelift"
                }
            ],
            "time": "2026-04-10T17:25:58+00:00"
        },
        {
            "name": "symfony/polyfill-php73",
            "version": "v1.34.0",
            "source": {
                "type": "git",
                "url": "https://github.com/symfony/polyfill-php73.git",
                "reference": "0f68c03565dcaaf25a890667542e8bd75fe7e5bb"
            },
            "dist": {
                "type": "zip",
                "url": "https://api.github.com/repos/symfony/polyfill-php73/zipball/0f68c03565dcaaf25a890667542e8bd75fe7e5bb",
                "reference": "0f68c03565dcaaf25a890667542e8bd75fe7e5bb",
                "shasum": ""
            },
            "require": {
                "php": ">=7.2"
            },
            "type": "library",
            "extra": {
                "thanks": {
                    "url": "https://github.com/symfony/polyfill",
                    "name": "symfony/polyfill"
                }
            },
            "autoload": {
                "files": [
                    "bootstrap.php"
                ],
                "psr-4": {
                    "Symfony\\Polyfill\\Php73\\": ""
                },
                "classmap": [
                    "Resources/stubs"
                ]
            },
            "notification-url": "https://packagist.org/downloads/",
            "license": [
                "MIT"
            ],
            "authors": [
                {
                    "name": "Nicolas Grekas",
                    "email": "p@tchwork.com"
                },
                {
                    "name": "Symfony Community",
                    "homepage": "https://symfony.com/contributors"
                }
            ],
            "description": "Symfony polyfill backporting some PHP 7.3+ features to lower PHP versions",
            "homepage": "https://symfony.com",
            "keywords": [
                "compatibility",
                "polyfill",
                "portable",
                "shim"
            ],
            "support": {
                "source": "https://github.com/symfony/polyfill-php73/tree/v1.34.0"
            },
            "funding": [
                {
                    "url": "https://symfony.com/sponsor",
                    "type": "custom"
                },
                {
                    "url": "https://github.com/fabpot",
                    "type": "github"
                },
                {
                    "url": "https://github.com/nicolas-grekas",
                    "type": "github"
                },
                {
                    "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
                    "type": "tidelift"
                }
            ],
            "time": "2024-09-09T11:45:10+00:00"
        },
        {
            "name": "symfony/polyfill-php80",
            "version": "v1.34.0",
            "source": {
                "type": "git",
                "url": "https://github.com/symfony/polyfill-php80.git",
                "reference": "dfb55726c3a76ea3b6459fcfda1ec2d80a682411"
            },
            "dist": {
                "type": "zip",
                "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/dfb55726c3a76ea3b6459fcfda1ec2d80a682411",
                "reference": "dfb55726c3a76ea3b6459fcfda1ec2d80a682411",
                "shasum": ""
            },
            "require": {
                "php": ">=7.2"
            },
            "type": "library",
            "extra": {
                "thanks": {
                    "url": "https://github.com/symfony/polyfill",
                    "name": "symfony/polyfill"
                }
            },
            "autoload": {
                "files": [
                    "bootstrap.php"
                ],
                "psr-4": {
                    "Symfony\\Polyfill\\Php80\\": ""
                },
                "classmap": [
                    "Resources/stubs"
                ]
            },
            "notification-url": "https://packagist.org/downloads/",
            "license": [
                "MIT"
            ],
            "authors": [
                {
                    "name": "Ion Bazan",
                    "email": "ion.bazan@gmail.com"
                },
                {
                    "name": "Nicolas Grekas",
                    "email": "p@tchwork.com"
                },
                {
                    "name": "Symfony Community",
                    "homepage": "https://symfony.com/contributors"
                }
            ],
            "description": "Symfony polyfill backporting some PHP 8.0+ features to lower PHP versions",
            "homepage": "https://symfony.com",
            "keywords": [
                "compatibility",
                "polyfill",
                "portable",
                "shim"
            ],
            "support": {
                "source": "https://github.com/symfony/polyfill-php80/tree/v1.34.0"
            },
            "funding": [
                {
                    "url": "https://symfony.com/sponsor",
                    "type": "custom"
                },
                {
                    "url": "https://github.com/fabpot",
                    "type": "github"
                },
                {
                    "url": "https://github.com/nicolas-grekas",
                    "type": "github"
                },
                {
                    "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
                    "type": "tidelift"
                }
            ],
            "time": "2026-04-10T16:19:22+00:00"
        },
        {
            "name": "symfony/polyfill-php81",
            "version": "v1.34.0",
            "source": {
                "type": "git",
                "url": "https://github.com/symfony/polyfill-php81.git",
                "reference": "4a4cfc2d253c21a5ad0e53071df248ed48c6ce5c"
            },
            "dist": {
                "type": "zip",
                "url": "https://api.github.com/repos/symfony/polyfill-php81/zipball/4a4cfc2d253c21a5ad0e53071df248ed48c6ce5c",
                "reference": "4a4cfc2d253c21a5ad0e53071df248ed48c6ce5c",
                "shasum": ""
            },
            "require": {
                "php": ">=7.2"
            },
            "type": "library",
            "extra": {
                "thanks": {
                    "url": "https://github.com/symfony/polyfill",
                    "name": "symfony/polyfill"
                }
            },
            "autoload": {
                "files": [
                    "bootstrap.php"
                ],
                "psr-4": {
                    "Symfony\\Polyfill\\Php81\\": ""
                },
                "classmap": [
                    "Resources/stubs"
                ]
            },
            "notification-url": "https://packagist.org/downloads/",
            "license": [
                "MIT"
            ],
            "authors": [
                {
                    "name": "Nicolas Grekas",
                    "email": "p@tchwork.com"
                },
                {
                    "name": "Symfony Community",
                    "homepage": "https://symfony.com/contributors"
                }
            ],
            "description": "Symfony polyfill backporting some PHP 8.1+ features to lower PHP versions",
            "homepage": "https://symfony.com",
            "keywords": [
                "compatibility",
                "polyfill",
                "portable",
                "shim"
            ],
            "support": {
                "source": "https://github.com/symfony/polyfill-php81/tree/v1.34.0"
            },
            "funding": [
                {
                    "url": "https://symfony.com/sponsor",
                    "type": "custom"
                },
                {
                    "url": "https://github.com/fabpot",
                    "type": "github"
                },
                {
                    "url": "https://github.com/nicolas-grekas",
                    "type": "github"
                },
                {
                    "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
                    "type": "tidelift"
                }
            ],
            "time": "2024-09-09T11:45:10+00:00"
        },
        {
            "name": "symfony/polyfill-php84",
            "version": "v1.34.0",
            "source": {
                "type": "git",
                "url": "https://github.com/symfony/polyfill-php84.git",
                "reference": "88486db2c389b290bf87ff1de7ebc1e13e42bb06"
            },
            "dist": {
                "type": "zip",
                "url": "https://api.github.com/repos/symfony/polyfill-php84/zipball/88486db2c389b290bf87ff1de7ebc1e13e42bb06",
                "reference": "88486db2c389b290bf87ff1de7ebc1e13e42bb06",
                "shasum": ""
            },
            "require": {
                "php": ">=7.2"
            },
            "type": "library",
            "extra": {
                "thanks": {
                    "url": "https://github.com/symfony/polyfill",
                    "name": "symfony/polyfill"
                }
            },
            "autoload": {
                "files": [
                    "bootstrap.php"
                ],
                "psr-4": {
                    "Symfony\\Polyfill\\Php84\\": ""
                },
                "classmap": [
                    "Resources/stubs"
                ]
            },
            "notification-url": "https://packagist.org/downloads/",
            "license": [
                "MIT"
            ],
            "authors": [
                {
                    "name": "Nicolas Grekas",
                    "email": "p@tchwork.com"
                },
                {
                    "name": "Symfony Community",
                    "homepage": "https://symfony.com/contributors"
                }
            ],
            "description": "Symfony polyfill backporting some PHP 8.4+ features to lower PHP versions",
            "homepage": "https://symfony.com",
            "keywords": [
                "compatibility",
                "polyfill",
                "portable",
                "shim"
            ],
            "support": {
                "source": "https://github.com/symfony/polyfill-php84/tree/v1.34.0"
            },
            "funding": [
                {
                    "url": "https://symfony.com/sponsor",
                    "type": "custom"
                },
                {
                    "url": "https://github.com/fabpot",
                    "type": "github"
                },
                {
                    "url": "https://github.com/nicolas-grekas",
                    "type": "github"
                },
                {
                    "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
                    "type": "tidelift"
                }
            ],
            "time": "2026-04-10T18:47:49+00:00"
        },
        {
            "name": "symfony/process",
            "version": "v5.4.51",
            "source": {
                "type": "git",
                "url": "https://github.com/symfony/process.git",
                "reference": "467bfc56f18f5ef6d5ccb09324d7e988c1c0a98f"
            },
            "dist": {
                "type": "zip",
                "url": "https://api.github.com/repos/symfony/process/zipball/467bfc56f18f5ef6d5ccb09324d7e988c1c0a98f",
                "reference": "467bfc56f18f5ef6d5ccb09324d7e988c1c0a98f",
                "shasum": ""
            },
            "require": {
                "php": ">=7.2.5",
                "symfony/polyfill-php80": "^1.16"
            },
            "type": "library",
            "autoload": {
                "psr-4": {
                    "Symfony\\Component\\Process\\": ""
                },
                "exclude-from-classmap": [
                    "/Tests/"
                ]
            },
            "notification-url": "https://packagist.org/downloads/",
            "license": [
                "MIT"
            ],
            "authors": [
                {
                    "name": "Fabien Potencier",
                    "email": "fabien@symfony.com"
                },
                {
                    "name": "Symfony Community",
                    "homepage": "https://symfony.com/contributors"
                }
            ],
            "description": "Executes commands in sub-processes",
            "homepage": "https://symfony.com",
            "support": {
                "source": "https://github.com/symfony/process/tree/v5.4.51"
            },
            "funding": [
                {
                    "url": "https://symfony.com/sponsor",
                    "type": "custom"
                },
                {
                    "url": "https://github.com/fabpot",
                    "type": "github"
                },
                {
                    "url": "https://github.com/nicolas-grekas",
                    "type": "github"
                },
                {
                    "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
                    "type": "tidelift"
                }
            ],
            "time": "2026-01-26T15:53:37+00:00"
        },
        {
            "name": "symfony/service-contracts",
            "version": "v2.5.4",
            "source": {
                "type": "git",
                "url": "https://github.com/symfony/service-contracts.git",
                "reference": "f37b419f7aea2e9abf10abd261832cace12e3300"
            },
            "dist": {
                "type": "zip",
                "url": "https://api.github.com/repos/symfony/service-contracts/zipball/f37b419f7aea2e9abf10abd261832cace12e3300",
                "reference": "f37b419f7aea2e9abf10abd261832cace12e3300",
                "shasum": ""
            },
            "require": {
                "php": ">=7.2.5",
                "psr/container": "^1.1",
                "symfony/deprecation-contracts": "^2.1|^3"
            },
            "conflict": {
                "ext-psr": "<1.1|>=2"
            },
            "suggest": {
                "symfony/service-implementation": ""
            },
            "type": "library",
            "extra": {
                "thanks": {
                    "url": "https://github.com/symfony/contracts",
                    "name": "symfony/contracts"
                },
                "branch-alias": {
                    "dev-main": "2.5-dev"
                }
            },
            "autoload": {
                "psr-4": {
                    "Symfony\\Contracts\\Service\\": ""
                }
            },
            "notification-url": "https://packagist.org/downloads/",
            "license": [
                "MIT"
            ],
            "authors": [
                {
                    "name": "Nicolas Grekas",
                    "email": "p@tchwork.com"
                },
                {
                    "name": "Symfony Community",
                    "homepage": "https://symfony.com/contributors"
                }
            ],
            "description": "Generic abstractions related to writing services",
            "homepage": "https://symfony.com",
            "keywords": [
                "abstractions",
                "contracts",
                "decoupling",
                "interfaces",
                "interoperability",
                "standards"
            ],
            "support": {
                "source": "https://github.com/symfony/service-contracts/tree/v2.5.4"
            },
            "funding": [
                {
                    "url": "https://symfony.com/sponsor",
                    "type": "custom"
                },
                {
                    "url": "https://github.com/fabpot",
                    "type": "github"
                },
                {
                    "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
                    "type": "tidelift"
                }
            ],
            "time": "2024-09-25T14:11:13+00:00"
        },
        {
            "name": "symfony/string",
            "version": "v5.4.47",
            "source": {
                "type": "git",
                "url": "https://github.com/symfony/string.git",
                "reference": "136ca7d72f72b599f2631aca474a4f8e26719799"
            },
            "dist": {
                "type": "zip",
                "url": "https://api.github.com/repos/symfony/string/zipball/136ca7d72f72b599f2631aca474a4f8e26719799",
                "reference": "136ca7d72f72b599f2631aca474a4f8e26719799",
                "shasum": ""
            },
            "require": {
                "php": ">=7.2.5",
                "symfony/polyfill-ctype": "~1.8",
                "symfony/polyfill-intl-grapheme": "~1.0",
                "symfony/polyfill-intl-normalizer": "~1.0",
                "symfony/polyfill-mbstring": "~1.0",
                "symfony/polyfill-php80": "~1.15"
            },
            "conflict": {
                "symfony/translation-contracts": ">=3.0"
            },
            "require-dev": {
                "symfony/error-handler": "^4.4|^5.0|^6.0",
                "symfony/http-client": "^4.4|^5.0|^6.0",
                "symfony/translation-contracts": "^1.1|^2",
                "symfony/var-exporter": "^4.4|^5.0|^6.0"
            },
            "type": "library",
            "autoload": {
                "files": [
                    "Resources/functions.php"
                ],
                "psr-4": {
                    "Symfony\\Component\\String\\": ""
                },
                "exclude-from-classmap": [
                    "/Tests/"
                ]
            },
            "notification-url": "https://packagist.org/downloads/",
            "license": [
                "MIT"
            ],
            "authors": [
                {
                    "name": "Nicolas Grekas",
                    "email": "p@tchwork.com"
                },
                {
                    "name": "Symfony Community",
                    "homepage": "https://symfony.com/contributors"
                }
            ],
            "description": "Provides an object-oriented API to strings and deals with bytes, UTF-8 code points and grapheme clusters in a unified way",
            "homepage": "https://symfony.com",
            "keywords": [
                "grapheme",
                "i18n",
                "string",
                "unicode",
                "utf-8",
                "utf8"
            ],
            "support": {
                "source": "https://github.com/symfony/string/tree/v5.4.47"
            },
            "funding": [
                {
                    "url": "https://symfony.com/sponsor",
                    "type": "custom"
                },
                {
                    "url": "https://github.com/fabpot",
                    "type": "github"
                },
                {
                    "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
                    "type": "tidelift"
                }
            ],
            "time": "2024-11-10T20:33:58+00:00"
        }
    ],
    "packages-dev": [
        {
            "name": "phpstan/phpstan",
            "version": "1.12.33",
            "dist": {
                "type": "zip",
                "url": "https://api.github.com/repos/phpstan/phpstan/zipball/37982d6fc7cbb746dda7773530cda557cdf119e1",
                "reference": "37982d6fc7cbb746dda7773530cda557cdf119e1",
                "shasum": ""
            },
            "require": {
                "php": "^7.2|^8.0"
            },
            "conflict": {
                "phpstan/phpstan-shim": "*"
            },
            "bin": [
                "phpstan",
                "phpstan.phar"
            ],
            "type": "library",
            "autoload": {
                "files": [
                    "bootstrap.php"
                ]
            },
            "notification-url": "https://packagist.org/downloads/",
            "license": [
                "MIT"
            ],
            "description": "PHPStan - PHP Static Analysis Tool",
            "keywords": [
                "dev",
                "static analysis"
            ],
            "support": {
                "docs": "https://phpstan.org/user-guide/getting-started",
                "forum": "https://github.com/phpstan/phpstan/discussions",
                "issues": "https://github.com/phpstan/phpstan/issues",
                "security": "https://github.com/phpstan/phpstan/security/policy",
                "source": "https://github.com/phpstan/phpstan-src"
            },
            "funding": [
                {
                    "url": "https://github.com/ondrejmirtes",
                    "type": "github"
                },
                {
                    "url": "https://github.com/phpstan",
                    "type": "github"
                }
            ],
            "time": "2026-02-28T20:30:03+00:00"
        },
        {
            "name": "phpstan/phpstan-deprecation-rules",
            "version": "1.2.1",
            "source": {
                "type": "git",
                "url": "https://github.com/phpstan/phpstan-deprecation-rules.git",
                "reference": "f94d246cc143ec5a23da868f8f7e1393b50eaa82"
            },
            "dist": {
                "type": "zip",
                "url": "https://api.github.com/repos/phpstan/phpstan-deprecation-rules/zipball/f94d246cc143ec5a23da868f8f7e1393b50eaa82",
                "reference": "f94d246cc143ec5a23da868f8f7e1393b50eaa82",
                "shasum": ""
            },
            "require": {
                "php": "^7.2 || ^8.0",
                "phpstan/phpstan": "^1.12"
            },
            "require-dev": {
                "php-parallel-lint/php-parallel-lint": "^1.2",
                "phpstan/phpstan-phpunit": "^1.0",
                "phpunit/phpunit": "^9.5"
            },
            "type": "phpstan-extension",
            "extra": {
                "phpstan": {
                    "includes": [
                        "rules.neon"
                    ]
                }
            },
            "autoload": {
                "psr-4": {
                    "PHPStan\\": "src/"
                }
            },
            "notification-url": "https://packagist.org/downloads/",
            "license": [
                "MIT"
            ],
            "description": "PHPStan rules for detecting usage of deprecated classes, methods, properties, constants and traits.",
            "support": {
                "issues": "https://github.com/phpstan/phpstan-deprecation-rules/issues",
                "source": "https://github.com/phpstan/phpstan-deprecation-rules/tree/1.2.1"
            },
            "time": "2024-09-11T15:52:35+00:00"
        },
        {
            "name": "phpstan/phpstan-phpunit",
            "version": "1.4.2",
            "source": {
                "type": "git",
                "url": "https://github.com/phpstan/phpstan-phpunit.git",
                "reference": "72a6721c9b64b3e4c9db55abbc38f790b318267e"
            },
            "dist": {
                "type": "zip",
                "url": "https://api.github.com/repos/phpstan/phpstan-phpunit/zipball/72a6721c9b64b3e4c9db55abbc38f790b318267e",
                "reference": "72a6721c9b64b3e4c9db55abbc38f790b318267e",
                "shasum": ""
            },
            "require": {
                "php": "^7.2 || ^8.0",
                "phpstan/phpstan": "^1.12"
            },
            "conflict": {
                "phpunit/phpunit": "<7.0"
            },
            "require-dev": {
                "nikic/php-parser": "^4.13.0",
                "php-parallel-lint/php-parallel-lint": "^1.2",
                "phpstan/phpstan-strict-rules": "^1.5.1",
                "phpunit/phpunit": "^9.5"
            },
            "type": "phpstan-extension",
            "extra": {
                "phpstan": {
                    "includes": [
                        "extension.neon",
                        "rules.neon"
                    ]
                }
            },
            "autoload": {
                "psr-4": {
                    "PHPStan\\": "src/"
                }
            },
            "notification-url": "https://packagist.org/downloads/",
            "license": [
                "MIT"
            ],
            "description": "PHPUnit extensions and rules for PHPStan",
            "support": {
                "issues": "https://github.com/phpstan/phpstan-phpunit/issues",
                "source": "https://github.com/phpstan/phpstan-phpunit/tree/1.4.2"
            },
            "time": "2024-12-17T17:20:49+00:00"
        },
        {
            "name": "phpstan/phpstan-strict-rules",
            "version": "1.6.2",
            "source": {
                "type": "git",
                "url": "https://github.com/phpstan/phpstan-strict-rules.git",
                "reference": "b564ca479e7e735f750aaac4935af965572a7845"
            },
            "dist": {
                "type": "zip",
                "url": "https://api.github.com/repos/phpstan/phpstan-strict-rules/zipball/b564ca479e7e735f750aaac4935af965572a7845",
                "reference": "b564ca479e7e735f750aaac4935af965572a7845",
                "shasum": ""
            },
            "require": {
                "php": "^7.2 || ^8.0",
                "phpstan/phpstan": "^1.12.4"
            },
            "require-dev": {
                "nikic/php-parser": "^4.13.0",
                "php-parallel-lint/php-parallel-lint": "^1.2",
                "phpstan/phpstan-deprecation-rules": "^1.1",
                "phpstan/phpstan-phpunit": "^1.0",
                "phpunit/phpunit": "^9.5"
            },
            "type": "phpstan-extension",
            "extra": {
                "phpstan": {
                    "includes": [
                        "rules.neon"
                    ]
                }
            },
            "autoload": {
                "psr-4": {
                    "PHPStan\\": "src/"
                }
            },
            "notification-url": "https://packagist.org/downloads/",
            "license": [
                "MIT"
            ],
            "description": "Extra strict and opinionated rules for PHPStan",
            "support": {
                "issues": "https://github.com/phpstan/phpstan-strict-rules/issues",
                "source": "https://github.com/phpstan/phpstan-strict-rules/tree/1.6.2"
            },
            "time": "2025-01-19T13:02:24+00:00"
        },
        {
            "name": "phpstan/phpstan-symfony",
            "version": "1.4.16",
            "source": {
                "type": "git",
                "url": "https://github.com/phpstan/phpstan-symfony.git",
                "reference": "18df9086a84fc28e9a231ea8e91d5aff1a0a3d6f"
            },
            "dist": {
                "type": "zip",
                "url": "https://api.github.com/repos/phpstan/phpstan-symfony/zipball/18df9086a84fc28e9a231ea8e91d5aff1a0a3d6f",
                "reference": "18df9086a84fc28e9a231ea8e91d5aff1a0a3d6f",
                "shasum": ""
            },
            "require": {
                "ext-simplexml": "*",
                "php": "^7.2 || ^8.0",
                "phpstan/phpstan": "^1.12"
            },
            "conflict": {
                "symfony/framework-bundle": "<3.0"
            },
            "require-dev": {
                "nikic/php-parser": "^4.13.0",
                "php-parallel-lint/php-parallel-lint": "^1.2",
                "phpstan/phpstan-phpunit": "^1.3.11",
                "phpstan/phpstan-strict-rules": "^1.5.1",
                "phpunit/phpunit": "^8.5.29 || ^9.5",
                "psr/container": "1.0 || 1.1.1",
                "symfony/config": "^5.4 || ^6.1",
                "symfony/console": "^5.4 || ^6.1",
                "symfony/dependency-injection": "^5.4 || ^6.1",
                "symfony/form": "^5.4 || ^6.1",
                "symfony/framework-bundle": "^5.4 || ^6.1",
                "symfony/http-foundation": "^5.4 || ^6.1",
                "symfony/messenger": "^5.4",
                "symfony/polyfill-php80": "^1.24",
                "symfony/serializer": "^5.4",
                "symfony/service-contracts": "^2.2.0"
            },
            "type": "phpstan-extension",
            "extra": {
                "phpstan": {
                    "includes": [
                        "extension.neon",
                        "rules.neon"
                    ]
                }
            },
            "autoload": {
                "psr-4": {
                    "PHPStan\\": "src/"
                }
            },
            "notification-url": "https://packagist.org/downloads/",
            "license": [
                "MIT"
            ],
            "authors": [
                {
                    "name": "Lukáš Unger",
                    "email": "looky.msc@gmail.com",
                    "homepage": "https://lookyman.net"
                }
            ],
            "description": "Symfony Framework extensions and rules for PHPStan",
            "support": {
                "issues": "https://github.com/phpstan/phpstan-symfony/issues",
                "source": "https://github.com/phpstan/phpstan-symfony/tree/1.4.16"
            },
            "time": "2025-09-07T06:55:28+00:00"
        },
        {
            "name": "symfony/phpunit-bridge",
            "version": "v7.3.4",
            "source": {
                "type": "git",
                "url": "https://github.com/symfony/phpunit-bridge.git",
                "reference": "ed77a629c13979e051b7000a317966474d566398"
            },
            "dist": {
                "type": "zip",
                "url": "https://api.github.com/repos/symfony/phpunit-bridge/zipball/ed77a629c13979e051b7000a317966474d566398",
                "reference": "ed77a629c13979e051b7000a317966474d566398",
                "shasum": ""
            },
            "require": {
                "php": ">=7.2.5"
            },
            "conflict": {
                "phpunit/phpunit": "<7.5|9.1.2"
            },
            "require-dev": {
                "symfony/deprecation-contracts": "^2.5|^3.0",
                "symfony/error-handler": "^5.4|^6.4|^7.0",
                "symfony/polyfill-php81": "^1.27"
            },
            "bin": [
                "bin/simple-phpunit"
            ],
            "type": "symfony-bridge",
            "extra": {
                "thanks": {
                    "url": "https://github.com/sebastianbergmann/phpunit",
                    "name": "phpunit/phpunit"
                }
            },
            "autoload": {
                "files": [
                    "bootstrap.php"
                ],
                "psr-4": {
                    "Symfony\\Bridge\\PhpUnit\\": ""
                },
                "exclude-from-classmap": [
                    "/Tests/",
                    "/bin/"
                ]
            },
            "notification-url": "https://packagist.org/downloads/",
            "license": [
                "MIT"
            ],
            "authors": [
                {
                    "name": "Nicolas Grekas",
                    "email": "p@tchwork.com"
                },
                {
                    "name": "Symfony Community",
                    "homepage": "https://symfony.com/contributors"
                }
            ],
            "description": "Provides utilities for PHPUnit, especially user deprecation notices management",
            "homepage": "https://symfony.com",
            "keywords": [
                "testing"
            ],
            "support": {
                "source": "https://github.com/symfony/phpunit-bridge/tree/v7.3.4"
            },
            "funding": [
                {
                    "url": "https://symfony.com/sponsor",
                    "type": "custom"
                },
                {
                    "url": "https://github.com/fabpot",
                    "type": "github"
                },
                {
                    "url": "https://github.com/nicolas-grekas",
                    "type": "github"
                },
                {
                    "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
                    "type": "tidelift"
                }
            ],
            "time": "2025-09-12T12:18:52+00:00"
        }
    ],
    "aliases": [],
    "minimum-stability": "stable",
    "stability-flags": {},
    "prefer-stable": false,
    "prefer-lowest": false,
    "platform": {
        "php": "^7.2.5 || ^8.0",
        "ext-json": "*"
    },
    "platform-dev": {},
    "platform-overrides": {
        "php": "7.2.5"
    },
    "plugin-api-version": "2.9.0"
}
Copyright (c) Nils Adermann, Jordi Boggiano

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is furnished
to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
#!/usr/bin/env php
<?php 
namespace _ContaoManager;

if (\PHP_SAPI !== 'cli' && \PHP_SAPI !== 'phpdbg') {
    if (0 === \strpos(__FILE__, 'phar:') && \ini_get('register_argc_argv')) {
        echo 'Composer cannot be run safely on non-CLI SAPIs with register_argc_argv=On. Aborting.' . \PHP_EOL;
        exit(1);
    }
    echo 'Warning: Composer should be invoked via the CLI version of PHP, not the ' . \PHP_SAPI . ' SAPI' . \PHP_EOL;
}
if (\PHP_VERSION_ID < 70205) {
    echo 'Composer 2.3.0 dropped support for PHP <7.2.5 and you are running ' . \PHP_VERSION . ', please upgrade PHP or use Composer 2.2 LTS via "composer self-update --2.2". Aborting.' . \PHP_EOL;
    exit(1);
}
if (\ini_get('opcache.enable_cli') && \ini_get('opcache.preload')) {
    \register_shutdown_function(static function () {
        $e = \error_get_last();
        if ($e !== null && (\strpos($e['message'], 'Cannot redeclare class') !== \false || \strpos($e['message'], 'Declaration of') !== \false && \strpos($e['message'], 'must be compatible with') !== \false)) {
            echo 'Warning: The error above might be caused by the fact opcache.enable_cli is enabled and opcache.preload is set in php.ini. We recommend disabling opcache.enable_cli if you really need preloading on this machine.' . \PHP_EOL;
        }
    });
}
\setlocale(\LC_ALL, 'C');
require __DIR__ . '/../src/bootstrap.php';
use Composer\Console\Application;
use Composer\XdebugHandler\XdebugHandler;
use Composer\Util\Platform;
use Composer\Util\ErrorHandler;
\error_reporting(-1);
// Restart without Xdebug
$xdebug = new XdebugHandler('Composer');
$xdebug->check();
unset($xdebug);
if (\defined('HHVM_VERSION') && \version_compare(\HHVM_VERSION, '4.0', '>=')) {
    echo 'HHVM 4.0 has dropped support for Composer, please use PHP instead. Aborting.' . \PHP_EOL;
    exit(1);
}
if (!\extension_loaded('iconv') && !\extension_loaded('mbstring')) {
    echo 'The iconv OR mbstring extension is required and both are missing.' . \PHP_EOL . 'Install either of them or recompile php without --disable-iconv.' . \PHP_EOL . 'Aborting.' . \PHP_EOL;
    exit(1);
}
if (\function_exists('ini_set')) {
    // check if error logging is on, but to an empty destination - for the CLI SAPI, that means stderr
    $logsToSapiDefault = '' === \ini_get('error_log') && (bool) \ini_get('log_errors');
    // on the CLI SAPI, ensure errors are displayed on stderr, either via display_errors or via error_log
    if (\PHP_SAPI === 'cli') {
        @\ini_set('display_errors', $logsToSapiDefault ? '0' : 'stderr');
    }
    // Set user defined memory limit
    if ($memoryLimit = \getenv('COMPOSER_MEMORY_LIMIT')) {
        @\ini_set('memory_limit', $memoryLimit);
    } else {
        $memoryInBytes = function ($value) {
            $unit = \strtolower(\substr($value, -1, 1));
            $value = (int) $value;
            switch ($unit) {
                case 'g':
                    $value *= 1024;
                // no break (cumulative multiplier)
                case 'm':
                    $value *= 1024;
                // no break (cumulative multiplier)
                case 'k':
                    $value *= 1024;
            }
            return $value;
        };
        $memoryLimit = \trim(\ini_get('memory_limit'));
        // Increase memory_limit if it is lower than 1.5GB
        if ($memoryLimit != -1 && $memoryInBytes($memoryLimit) < 1024 * 1024 * 1536) {
            @\ini_set('memory_limit', '1536M');
        }
        unset($memoryInBytes);
    }
    unset($memoryLimit);
}
// Workaround PHP bug on Windows where env vars containing Unicode chars are mangled in $_SERVER
// see https://github.com/php/php-src/issues/7896
if (\PHP_VERSION_ID >= 70113 && (\PHP_VERSION_ID < 80016 || \PHP_VERSION_ID >= 80100 && \PHP_VERSION_ID < 80103) && Platform::isWindows()) {
    foreach ($_SERVER as $serverVar => $serverVal) {
        if (($serverVal = \getenv($serverVar)) !== \false) {
            $_SERVER[$serverVar] = $serverVal;
        }
    }
}
Platform::putEnv('COMPOSER_BINARY', \realpath($_SERVER['argv'][0]));
ErrorHandler::register();
// run the command application
$application = new Application();
$application->run();
#!/usr/bin/env php
<?php 
namespace _ContaoManager;

$cwd = \getcwd();
\assert(\is_string($cwd));
\chdir(__DIR__ . '/../');
$ts = \rtrim(\exec('git rev-list --no-commit-header -n1 --format=%ct HEAD'));
if (!\is_numeric($ts)) {
    echo 'Could not detect date using "git rev-list --no-commit-header -n1 --format=%ct HEAD"' . \PHP_EOL;
    exit(1);
}
// Install with the current version to force it having the right ClassLoader version
// Install without dev packages to clean up the included classmap from phpunit classes
\exec('php bin/composer config autoloader-suffix ComposerPhar' . $ts, $output, $result);
if (0 !== $result) {
    echo 'Could not set the autoloader suffix, make sure exec is allowed and php can be found in your PATH';
    exit(1);
}
\exec('php bin/composer install -q --no-dev', $output, $result);
if (0 !== $result) {
    echo 'Could not remove dev deps, make sure exec is allowed and php can be found in your PATH';
    exit(1);
}
\exec('php bin/composer config autoloader-suffix --unset', $output, $result);
if (0 !== $result) {
    echo 'Could not remove the autoloader suffix, make sure exec is allowed and php can be found in your PATH';
    exit(1);
}
\chdir($cwd);
require __DIR__ . '/../src/bootstrap.php';
use Composer\Compiler;
\error_reporting(-1);
\ini_set('display_errors', '1');
try {
    $compiler = new Compiler();
    $compiler->compile();
} catch (\Exception $e) {
    echo 'Failed to compile phar: [' . \get_class($e) . '] ' . $e->getMessage() . ' at ' . $e->getFile() . ':' . $e->getLine() . \PHP_EOL;
    exit(1);
}
{
    "name": "composer\/composer",
    "type": "library",
    "description": "Composer helps you declare, manage and install dependencies of PHP projects. It ensures you have the right stack everywhere.",
    "keywords": [
        "package",
        "dependency",
        "autoload"
    ],
    "homepage": "https:\/\/getcomposer.org\/",
    "license": "MIT",
    "authors": [
        {
            "name": "Nils Adermann",
            "email": "naderman@naderman.de",
            "homepage": "https:\/\/www.naderman.de"
        },
        {
            "name": "Jordi Boggiano",
            "email": "j.boggiano@seld.be",
            "homepage": "https:\/\/seld.be"
        }
    ],
    "require": {
        "php": "^7.2.5 || ^8.0",
        "ext-json": "*",
        "composer\/ca-bundle": "^1.5",
        "composer\/class-map-generator": "^1.4.0",
        "composer\/metadata-minifier": "^1.0",
        "composer\/semver": "^3.3",
        "composer\/spdx-licenses": "^1.5.7",
        "composer\/xdebug-handler": "^2.0.2 || ^3.0.3",
        "justinrainbow\/json-schema": "^6.5.1",
        "psr\/log": "^1.0 || ^2.0 || ^3.0",
        "seld\/jsonlint": "^1.4",
        "seld\/phar-utils": "^1.2",
        "symfony\/console": "^5.4.47 || ^6.4.25 || ^7.1.10 || ^8.0",
        "symfony\/filesystem": "^5.4.45 || ^6.4.24 || ^7.1.10 || ^8.0",
        "symfony\/finder": "^5.4.45 || ^6.4.24 || ^7.1.10 || ^8.0",
        "symfony\/process": "^5.4.47 || ^6.4.25 || ^7.1.10 || ^8.0",
        "react\/promise": "^3.3",
        "composer\/pcre": "^2.3 || ^3.3",
        "symfony\/polyfill-php73": "^1.24",
        "symfony\/polyfill-php80": "^1.24",
        "symfony\/polyfill-php81": "^1.24",
        "symfony\/polyfill-php84": "^1.30",
        "seld\/signal-handler": "^2.0"
    },
    "require-dev": {
        "symfony\/phpunit-bridge": "^6.4.25 || ^7.3.3 || ^8.0",
        "phpstan\/phpstan": "^1.11.8",
        "phpstan\/phpstan-phpunit": "^1.4.0",
        "phpstan\/phpstan-deprecation-rules": "^1.2.0",
        "phpstan\/phpstan-strict-rules": "^1.6.0",
        "phpstan\/phpstan-symfony": "^1.4.0"
    },
    "suggest": {
        "ext-curl": "Provides HTTP support (will fallback to PHP streams if missing)",
        "ext-openssl": "Enables access to repositories and packages over HTTPS",
        "ext-zip": "Allows direct extraction of ZIP archives (unzip\/7z binaries will be used instead if available)",
        "ext-zlib": "Enables gzip for HTTP requests"
    },
    "config": {
        "platform": {
            "php": "7.2.5"
        },
        "platform-check": false
    },
    "extra": {
        "branch-alias": {
            "dev-main": "2.9-dev"
        },
        "phpstan": {
            "includes": [
                "phpstan\/rules.neon"
            ]
        }
    },
    "autoload": {
        "psr-4": {
            "Composer\\": "src\/Composer\/"
        }
    },
    "autoload-dev": {
        "psr-4": {
            "Composer\\Test\\": "tests\/Composer\/Test\/"
        },
        "exclude-from-classmap": [
            "tests\/Composer\/Test\/Fixtures\/",
            "tests\/Composer\/Test\/Autoload\/Fixtures",
            "tests\/Composer\/Test\/Autoload\/MinimumVersionSupport",
            "tests\/Composer\/Test\/Plugin\/Fixtures"
        ]
    },
    "bin": [
        "bin\/composer"
    ],
    "scripts": {
        "compile": "@php -dphar.readonly=0 bin\/compile",
        "test": "@php simple-phpunit",
        "phpstan": "@php vendor\/bin\/phpstan analyse --configuration=phpstan\/config.neon"
    },
    "scripts-descriptions": {
        "compile": "Compile composer.phar",
        "test": "Run all tests",
        "phpstan": "Runs PHPStan"
    },
    "support": {
        "issues": "https:\/\/github.com\/composer\/composer\/issues",
        "irc": "ircs:\/\/irc.libera.chat:6697\/composer",
        "security": "https:\/\/github.com\/composer\/composer\/security\/policy"
    }
}<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer\PHPStan;

use Composer\DependencyResolver\Rule;
use Composer\Package\BasePackage;
use Composer\Package\Link;
use Composer\Semver\Constraint\ConstraintInterface;
use _ContaoManager\PhpParser\Node\Expr\MethodCall;
use _ContaoManager\PHPStan\Analyser\Scope;
use _ContaoManager\PHPStan\Reflection\MethodReflection;
use _ContaoManager\PHPStan\Type\Accessory\AccessoryNonEmptyStringType;
use _ContaoManager\PHPStan\Type\Constant\ConstantArrayType;
use _ContaoManager\PHPStan\Type\Constant\ConstantStringType;
use _ContaoManager\PHPStan\Type\Constant\ConstantIntegerType;
use _ContaoManager\PHPStan\Type\DynamicMethodReturnTypeExtension;
use _ContaoManager\PHPStan\Type\IntegerType;
use _ContaoManager\PHPStan\Type\StringType;
use _ContaoManager\PHPStan\Type\Type;
use _ContaoManager\PHPStan\Type\ObjectType;
use _ContaoManager\PHPStan\Type\TypeCombinator;
use _ContaoManager\PhpParser\Node\Identifier;
final class RuleReasonDataReturnTypeExtension implements DynamicMethodReturnTypeExtension
{
    public function getClass(): string
    {
        return Rule::class;
    }
    public function isMethodSupported(MethodReflection $methodReflection): bool
    {
        return strtolower($methodReflection->getName()) === 'getreasondata';
    }
    public function getTypeFromMethodCall(MethodReflection $methodReflection, MethodCall $methodCall, Scope $scope): Type
    {
        $reasonType = $scope->getType(new MethodCall($methodCall->var, new Identifier('getReason')));
        $types = [Rule::RULE_ROOT_REQUIRE => new ConstantArrayType([new ConstantStringType('packageName'), new ConstantStringType('constraint')], [new StringType(), new ObjectType(ConstraintInterface::class)]), Rule::RULE_FIXED => new ConstantArrayType([new ConstantStringType('package')], [new ObjectType(BasePackage::class)]), Rule::RULE_PACKAGE_CONFLICT => new ObjectType(Link::class), Rule::RULE_PACKAGE_REQUIRES => new ObjectType(Link::class), Rule::RULE_PACKAGE_SAME_NAME => TypeCombinator::intersect(new StringType(), new AccessoryNonEmptyStringType()), Rule::RULE_LEARNED => new IntegerType(), Rule::RULE_PACKAGE_ALIAS => new ObjectType(BasePackage::class), Rule::RULE_PACKAGE_INVERSE_ALIAS => new ObjectType(BasePackage::class)];
        foreach ($types as $const => $type) {
            if ((new ConstantIntegerType($const))->isSuperTypeOf($reasonType)->yes()) {
                return $type;
            }
        }
        return TypeCombinator::union(...$types);
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer\PHPStan;

use Composer\Config;
use Composer\Json\JsonFile;
use _ContaoManager\PhpParser\Node\Expr\MethodCall;
use _ContaoManager\PHPStan\Analyser\Scope;
use _ContaoManager\PHPStan\Reflection\MethodReflection;
use _ContaoManager\PHPStan\Type\ArrayType;
use _ContaoManager\PHPStan\Type\BooleanType;
use _ContaoManager\PHPStan\Type\Constant\ConstantArrayType;
use _ContaoManager\PHPStan\Type\Constant\ConstantBooleanType;
use _ContaoManager\PHPStan\Type\Constant\ConstantStringType;
use _ContaoManager\PHPStan\Type\DynamicMethodReturnTypeExtension;
use _ContaoManager\PHPStan\Type\IntegerRangeType;
use _ContaoManager\PHPStan\Type\IntegerType;
use _ContaoManager\PHPStan\Type\MixedType;
use _ContaoManager\PHPStan\Type\StringType;
use _ContaoManager\PHPStan\Type\Type;
use _ContaoManager\PHPStan\Type\TypeCombinator;
use _ContaoManager\PHPStan\Type\TypeUtils;
use _ContaoManager\PHPStan\Type\UnionType;
final class ConfigReturnTypeExtension implements DynamicMethodReturnTypeExtension
{
    /** @var array<string, Type> */
    private $properties = [];
    public function __construct()
    {
        $schema = JsonFile::parseJson((string) file_get_contents(JsonFile::COMPOSER_SCHEMA_PATH));
        /**
         * @var string $prop
         */
        foreach ($schema['properties']['config']['properties'] as $prop => $conf) {
            $type = $this->parseType($conf, $prop);
            $this->properties[$prop] = $type;
        }
    }
    public function getClass(): string
    {
        return Config::class;
    }
    public function isMethodSupported(MethodReflection $methodReflection): bool
    {
        return strtolower($methodReflection->getName()) === 'get';
    }
    public function getTypeFromMethodCall(MethodReflection $methodReflection, MethodCall $methodCall, Scope $scope): ?Type
    {
        $args = $methodCall->getArgs();
        if (count($args) < 1) {
            return null;
        }
        $keyType = $scope->getType($args[0]->value);
        if (method_exists($keyType, 'getConstantStrings')) {
            // @phpstan-ignore function.alreadyNarrowedType (- depending on PHPStan version, this method will always exist, or not.)
            $strings = $keyType->getConstantStrings();
        } else {
            // for compat with old phpstan versions, we use a deprecated phpstan method.
            $strings = TypeUtils::getConstantStrings($keyType);
            // @phpstan-ignore staticMethod.deprecated (ignore deprecation)
        }
        if ($strings !== []) {
            $types = [];
            foreach ($strings as $string) {
                if (!isset($this->properties[$string->getValue()])) {
                    return null;
                }
                $types[] = $this->properties[$string->getValue()];
            }
            return TypeCombinator::union(...$types);
        }
        return null;
    }
    /**
     * @param array<mixed> $def
     */
    private function parseType(array $def, string $path): Type
    {
        if (isset($def['type'])) {
            $types = [];
            foreach ((array) $def['type'] as $type) {
                switch ($type) {
                    case 'integer':
                        if (in_array($path, ['process-timeout', 'cache-ttl', 'cache-files-ttl', 'cache-files-maxsize'], \true)) {
                            $types[] = IntegerRangeType::createAllGreaterThanOrEqualTo(0);
                        } else {
                            $types[] = new IntegerType();
                        }
                        break;
                    case 'string':
                        if ($path === 'cache-files-maxsize') {
                            // passthru, skip as it is always converted to int
                        } elseif ($path === 'discard-changes') {
                            $types[] = new ConstantStringType('stash');
                        } elseif ($path === 'use-parent-dir') {
                            $types[] = new ConstantStringType('prompt');
                        } elseif ($path === 'store-auths') {
                            $types[] = new ConstantStringType('prompt');
                        } elseif ($path === 'platform-check') {
                            $types[] = new ConstantStringType('php-only');
                        } elseif ($path === 'github-protocols') {
                            $types[] = new UnionType([new ConstantStringType('git'), new ConstantStringType('https'), new ConstantStringType('ssh'), new ConstantStringType('http')]);
                        } elseif (str_starts_with($path, 'preferred-install')) {
                            $types[] = new UnionType([new ConstantStringType('source'), new ConstantStringType('dist'), new ConstantStringType('auto')]);
                        } else {
                            $types[] = new StringType();
                        }
                        break;
                    case 'boolean':
                        if ($path === 'platform.additionalProperties') {
                            $types[] = new ConstantBooleanType(\false);
                        } else {
                            $types[] = new BooleanType();
                        }
                        break;
                    case 'object':
                        $addlPropType = null;
                        if (isset($def['additionalProperties'])) {
                            $addlPropType = $this->parseType($def['additionalProperties'], $path . '.additionalProperties');
                        }
                        if (isset($def['properties'])) {
                            $keyNames = [];
                            $valTypes = [];
                            $optionalKeys = [];
                            $propIndex = 0;
                            foreach ($def['properties'] as $propName => $propdef) {
                                $keyNames[] = new ConstantStringType($propName);
                                $valType = $this->parseType($propdef, $path . '.' . $propName);
                                if (!isset($def['required']) || !in_array($propName, $def['required'], \true)) {
                                    $valType = TypeCombinator::addNull($valType);
                                    $optionalKeys[] = $propIndex;
                                }
                                $valTypes[] = $valType;
                                $propIndex++;
                            }
                            if ($addlPropType !== null) {
                                $types[] = new ArrayType(TypeCombinator::union(new StringType(), ...$keyNames), TypeCombinator::union($addlPropType, ...$valTypes));
                            } else {
                                $types[] = new ConstantArrayType($keyNames, $valTypes, [0], $optionalKeys);
                            }
                        } else {
                            $types[] = new ArrayType(new StringType(), $addlPropType ?? new MixedType());
                        }
                        break;
                    case 'array':
                        if (isset($def['items'])) {
                            $valType = $this->parseType($def['items'], $path . '.items');
                        } else {
                            $valType = new MixedType();
                        }
                        $types[] = new ArrayType(new IntegerType(), $valType);
                        break;
                    default:
                        $types[] = new MixedType();
                }
            }
            $type = TypeCombinator::union(...$types);
        } elseif (isset($def['enum'])) {
            $type = TypeCombinator::union(...array_map(static function (string $value): ConstantStringType {
                return new ConstantStringType($value);
            }, $def['enum']));
        } else {
            $type = new MixedType();
        }
        // allow-plugins defaults to null until July 1st 2022 for some BC hackery, but after that it is not nullable anymore
        if ($path === 'allow-plugins' && time() < strtotime('2022-07-01')) {
            $type = TypeCombinator::addNull($type);
        }
        // default null props
        if (in_array($path, ['autoloader-suffix', 'gitlab-protocol'], \true)) {
            $type = TypeCombinator::addNull($type);
        }
        return $type;
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer;

use Composer\Config\JsonConfigSource;
use Composer\Json\JsonFile;
use Composer\IO\IOInterface;
use Composer\Package\Archiver;
use Composer\Package\Version\VersionGuesser;
use Composer\Package\RootPackageInterface;
use Composer\Repository\FilesystemRepository;
use Composer\Repository\RepositoryManager;
use Composer\Repository\RepositoryFactory;
use Composer\Util\Filesystem;
use Composer\Util\Platform;
use Composer\Util\ProcessExecutor;
use Composer\Util\HttpDownloader;
use Composer\Util\Loop;
use Composer\Util\Silencer;
use Composer\Plugin\PluginEvents;
use Composer\EventDispatcher\Event;
use Phar;
use _ContaoManager\Symfony\Component\Console\Formatter\OutputFormatter;
use _ContaoManager\Symfony\Component\Console\Formatter\OutputFormatterStyle;
use _ContaoManager\Symfony\Component\Console\Output\ConsoleOutput;
use Composer\EventDispatcher\EventDispatcher;
use Composer\Autoload\AutoloadGenerator;
use Composer\Package\Version\VersionParser;
use Composer\Downloader\TransportException;
use Composer\Json\JsonValidationException;
use Composer\Repository\InstalledRepositoryInterface;
use UnexpectedValueException;
use ZipArchive;
/**
 * Creates a configured instance of composer.
 *
 * @author Ryan Weaver <ryan@knplabs.com>
 * @author Jordi Boggiano <j.boggiano@seld.be>
 * @author Igor Wiedler <igor@wiedler.ch>
 * @author Nils Adermann <naderman@naderman.de>
 */
class Factory
{
    /**
     * @throws \RuntimeException
     */
    protected static function getHomeDir(): string
    {
        $home = Platform::getEnv('COMPOSER_HOME');
        if ($home) {
            return $home;
        }
        if (Platform::isWindows()) {
            if (!Platform::getEnv('APPDATA')) {
                throw new \RuntimeException('The APPDATA or COMPOSER_HOME environment variable must be set for composer to run correctly');
            }
            return rtrim(strtr(Platform::getEnv('APPDATA'), '\\', '/'), '/') . '/Composer';
        }
        $userDir = self::getUserDir();
        $dirs = [];
        if (self::useXdg()) {
            // XDG Base Directory Specifications
            $xdgConfig = Platform::getEnv('XDG_CONFIG_HOME');
            if (!$xdgConfig) {
                $xdgConfig = $userDir . '/.config';
            }
            $dirs[] = $xdgConfig . '/composer';
        }
        $dirs[] = $userDir . '/.composer';
        // select first dir which exists of: $XDG_CONFIG_HOME/composer or ~/.composer
        foreach ($dirs as $dir) {
            if (Silencer::call('is_dir', $dir)) {
                return $dir;
            }
        }
        // if none exists, we default to first defined one (XDG one if system uses it, or ~/.composer otherwise)
        return $dirs[0];
    }
    protected static function getCacheDir(string $home): string
    {
        $cacheDir = Platform::getEnv('COMPOSER_CACHE_DIR');
        if ($cacheDir) {
            return $cacheDir;
        }
        $homeEnv = Platform::getEnv('COMPOSER_HOME');
        if ($homeEnv) {
            return $homeEnv . '/cache';
        }
        if (Platform::isWindows()) {
            if ($cacheDir = Platform::getEnv('LOCALAPPDATA')) {
                $cacheDir .= '/Composer';
            } else {
                $cacheDir = $home . '/cache';
            }
            return rtrim(strtr($cacheDir, '\\', '/'), '/');
        }
        $userDir = self::getUserDir();
        if (\PHP_OS === 'Darwin') {
            // Migrate existing cache dir in old location if present
            if (is_dir($home . '/cache') && !is_dir($userDir . '/Library/Caches/composer')) {
                Silencer::call('rename', $home . '/cache', $userDir . '/Library/Caches/composer');
            }
            return $userDir . '/Library/Caches/composer';
        }
        if ($home === $userDir . '/.composer' && is_dir($home . '/cache')) {
            return $home . '/cache';
        }
        if (self::useXdg()) {
            $xdgCache = Platform::getEnv('XDG_CACHE_HOME') ?: $userDir . '/.cache';
            return $xdgCache . '/composer';
        }
        return $home . '/cache';
    }
    protected static function getDataDir(string $home): string
    {
        $homeEnv = Platform::getEnv('COMPOSER_HOME');
        if ($homeEnv) {
            return $homeEnv;
        }
        if (Platform::isWindows()) {
            return strtr($home, '\\', '/');
        }
        $userDir = self::getUserDir();
        if ($home !== $userDir . '/.composer' && self::useXdg()) {
            $xdgData = Platform::getEnv('XDG_DATA_HOME') ?: $userDir . '/.local/share';
            return $xdgData . '/composer';
        }
        return $home;
    }
    public static function createConfig(?IOInterface $io = null, ?string $cwd = null): \Composer\Config
    {
        $cwd = $cwd ?? Platform::getCwd(\true);
        $config = new \Composer\Config(\true, $cwd);
        // determine and add main dirs to the config
        $home = self::getHomeDir();
        $config->merge(['config' => ['home' => $home, 'cache-dir' => self::getCacheDir($home), 'data-dir' => self::getDataDir($home)]], \Composer\Config::SOURCE_DEFAULT);
        // load global config
        $file = new JsonFile($config->get('home') . '/config.json');
        if ($file->exists()) {
            if ($io instanceof IOInterface) {
                $io->writeError('Loading config file ' . $file->getPath(), \true, IOInterface::DEBUG);
            }
            self::validateJsonSchema($io, $file);
            $config->merge($file->read(), $file->getPath());
        }
        $config->setConfigSource(new JsonConfigSource($file));
        $htaccessProtect = $config->get('htaccess-protect');
        if ($htaccessProtect) {
            // Protect directory against web access. Since HOME could be
            // the www-data's user home and be web-accessible it is a
            // potential security risk
            $dirs = [$config->get('home'), $config->get('cache-dir'), $config->get('data-dir')];
            foreach ($dirs as $dir) {
                if (!file_exists($dir . '/.htaccess')) {
                    if (!is_dir($dir)) {
                        Silencer::call('mkdir', $dir, 0777, \true);
                    }
                    Silencer::call('file_put_contents', $dir . '/.htaccess', 'Deny from all');
                }
            }
        }
        // load global auth file
        $file = new JsonFile($config->get('home') . '/auth.json');
        if ($file->exists()) {
            if ($io instanceof IOInterface) {
                $io->writeError('Loading config file ' . $file->getPath(), \true, IOInterface::DEBUG);
            }
            self::validateJsonSchema($io, $file, JsonFile::AUTH_SCHEMA);
            $config->merge(['config' => $file->read()], $file->getPath());
        }
        $config->setAuthConfigSource(new JsonConfigSource($file, \true));
        self::loadComposerAuthEnv($config, $io);
        return $config;
    }
    public static function getComposerFile(): string
    {
        $env = Platform::getEnv('COMPOSER');
        if (is_string($env)) {
            $env = trim($env);
            if ('' !== $env) {
                if (is_dir($env)) {
                    throw new \RuntimeException('The COMPOSER environment variable is set to ' . $env . ' which is a directory, this variable should point to a composer.json or be left unset.');
                }
                return $env;
            }
        }
        return './composer.json';
    }
    public static function getLockFile(string $composerFile): string
    {
        return "json" === pathinfo($composerFile, \PATHINFO_EXTENSION) ? substr($composerFile, 0, -4) . 'lock' : $composerFile . '.lock';
    }
    /**
     * @return array{highlight: OutputFormatterStyle, warning: OutputFormatterStyle}
     */
    public static function createAdditionalStyles(): array
    {
        return ['highlight' => new OutputFormatterStyle('red'), 'warning' => new OutputFormatterStyle('black', 'yellow')];
    }
    public static function createOutput(): ConsoleOutput
    {
        $styles = self::createAdditionalStyles();
        $formatter = new OutputFormatter(\false, $styles);
        return new ConsoleOutput(ConsoleOutput::VERBOSITY_NORMAL, null, $formatter);
    }
    /**
     * Creates a Composer instance
     *
     * @param  IOInterface                       $io             IO instance
     * @param  array<string, mixed>|string|null  $localConfig    either a configuration array or a filename to read from, if null it will
     *                                                           read from the default filename
     * @param  bool|'local'|'global'             $disablePlugins Whether plugins should not be loaded, can be set to local or global to only disable local/global plugins
     * @param  bool                              $disableScripts Whether scripts should not be run
     * @param  bool                              $fullLoad       Whether to initialize everything or only main project stuff (used when loading the global composer)
     * @throws \InvalidArgumentException
     * @throws UnexpectedValueException
     * @return Composer|PartialComposer Composer if $fullLoad is true, otherwise PartialComposer
     * @phpstan-return ($fullLoad is true ? Composer : PartialComposer)
     */
    public function createComposer(IOInterface $io, $localConfig = null, $disablePlugins = \false, ?string $cwd = null, bool $fullLoad = \true, bool $disableScripts = \false)
    {
        // if a custom composer.json path is given, we change the default cwd to be that file's directory
        if (is_string($localConfig) && is_file($localConfig) && null === $cwd) {
            $cwd = dirname($localConfig);
        }
        $cwd = $cwd ?? Platform::getCwd(\true);
        // load Composer configuration
        if (null === $localConfig) {
            $localConfig = static::getComposerFile();
        }
        $localConfigSource = \Composer\Config::SOURCE_UNKNOWN;
        if (is_string($localConfig)) {
            $composerFile = $localConfig;
            $file = new JsonFile($localConfig, null, $io);
            if (!$file->exists()) {
                if ($localConfig === './composer.json' || $localConfig === 'composer.json') {
                    $message = 'Composer could not find a composer.json file in ' . $cwd;
                } else {
                    $message = 'Composer could not find the config file: ' . $localConfig;
                }
                $instructions = $fullLoad ? 'To initialize a project, please create a composer.json file. See https://getcomposer.org/basic-usage' : '';
                throw new \InvalidArgumentException($message . \PHP_EOL . $instructions);
            }
            if (!Platform::isInputCompletionProcess()) {
                try {
                    $file->validateSchema(JsonFile::LAX_SCHEMA);
                } catch (JsonValidationException $e) {
                    $errors = ' - ' . implode(\PHP_EOL . ' - ', $e->getErrors());
                    $message = $e->getMessage() . ':' . \PHP_EOL . $errors;
                    throw new JsonValidationException($message);
                }
            }
            $localConfig = $file->read();
            $localConfigSource = $file->getPath();
        }
        // Load config and override with local config/auth config
        $config = static::createConfig($io, $cwd);
        $isGlobal = $localConfigSource !== \Composer\Config::SOURCE_UNKNOWN && realpath($config->get('home')) === realpath(dirname($localConfigSource));
        $config->merge($localConfig, $localConfigSource);
        if (isset($composerFile)) {
            $io->writeError('Loading config file ' . $composerFile . ' (' . realpath($composerFile) . ')', \true, IOInterface::DEBUG);
            $config->setConfigSource(new JsonConfigSource(new JsonFile(realpath($composerFile), null, $io)));
            $localAuthFile = new JsonFile(dirname(realpath($composerFile)) . '/auth.json', null, $io);
            if ($localAuthFile->exists()) {
                $io->writeError('Loading config file ' . $localAuthFile->getPath(), \true, IOInterface::DEBUG);
                self::validateJsonSchema($io, $localAuthFile, JsonFile::AUTH_SCHEMA);
                $config->merge(['config' => $localAuthFile->read()], $localAuthFile->getPath());
                $config->setLocalAuthConfigSource(new JsonConfigSource($localAuthFile, \true));
            }
        }
        // make sure we load the auth env again over the local auth.json + composer.json config
        self::loadComposerAuthEnv($config, $io);
        $vendorDir = $config->get('vendor-dir');
        // initialize composer
        $composer = $fullLoad ? new \Composer\Composer() : new \Composer\PartialComposer();
        $composer->setConfig($config);
        if ($isGlobal) {
            $composer->setGlobal();
        }
        if ($fullLoad) {
            // load auth configs into the IO instance
            $io->loadConfiguration($config);
            // load existing Composer\InstalledVersions instance if available and scripts/plugins are allowed, as they might need it
            // we only load if the InstalledVersions class wasn't defined yet so that this is only loaded once
            if (\false === $disablePlugins && \false === $disableScripts && !class_exists('Composer\InstalledVersions', \false) && file_exists($installedVersionsPath = $config->get('vendor-dir') . '/composer/installed.php')) {
                // force loading the class at this point so it is loaded from the composer phar and not from the vendor dir
                // as we cannot guarantee integrity of that file
                if (class_exists('Composer\InstalledVersions')) {
                    FilesystemRepository::safelyLoadInstalledVersions($installedVersionsPath);
                }
            }
        }
        $httpDownloader = self::createHttpDownloader($io, $config);
        $process = new ProcessExecutor($io);
        $loop = new Loop($httpDownloader, $process);
        $composer->setLoop($loop);
        // initialize event dispatcher
        $dispatcher = new EventDispatcher($composer, $io, $process);
        $dispatcher->setRunScripts(!$disableScripts);
        $composer->setEventDispatcher($dispatcher);
        // initialize repository manager
        $rm = RepositoryFactory::manager($io, $config, $httpDownloader, $dispatcher, $process);
        $composer->setRepositoryManager($rm);
        // force-set the version of the global package if not defined as
        // guessing it adds no value and only takes time
        if (!$fullLoad && !isset($localConfig['version'])) {
            $localConfig['version'] = '1.0.0';
        }
        // load package
        $parser = new VersionParser();
        $guesser = new VersionGuesser($config, $process, $parser, $io);
        $loader = $this->loadRootPackage($rm, $config, $parser, $guesser, $io);
        $package = $loader->load($localConfig, 'Composer\Package\RootPackage', $cwd);
        $composer->setPackage($package);
        // load local repository
        $this->addLocalRepository($io, $rm, $vendorDir, $package, $process);
        // initialize installation manager
        $im = $this->createInstallationManager($loop, $io, $dispatcher);
        $composer->setInstallationManager($im);
        if ($composer instanceof \Composer\Composer) {
            // initialize download manager
            $dm = $this->createDownloadManager($io, $config, $httpDownloader, $process, $dispatcher);
            $composer->setDownloadManager($dm);
            // initialize autoload generator
            $generator = new AutoloadGenerator($dispatcher, $io);
            $composer->setAutoloadGenerator($generator);
            // initialize archive manager
            $am = $this->createArchiveManager($config, $dm, $loop);
            $composer->setArchiveManager($am);
        }
        // add installers to the manager (must happen after download manager is created since they read it out of $composer)
        $this->createDefaultInstallers($im, $composer, $io, $process);
        // init locker if possible
        if ($composer instanceof \Composer\Composer && isset($composerFile)) {
            $lockFile = self::getLockFile($composerFile);
            if (!$config->get('lock') && file_exists($lockFile)) {
                $io->writeError('<warning>' . $lockFile . ' is present but ignored as the "lock" config option is disabled.</warning>');
            }
            $locker = new \Composer\Package\Locker($io, new JsonFile($config->get('lock') ? $lockFile : Platform::getDevNull(), null, $io), $im, file_get_contents($composerFile), $process);
            $composer->setLocker($locker);
        } elseif ($composer instanceof \Composer\Composer) {
            $locker = new \Composer\Package\Locker($io, new JsonFile(Platform::getDevNull(), null, $io), $im, JsonFile::encode($localConfig), $process);
            $composer->setLocker($locker);
        }
        if ($composer instanceof \Composer\Composer) {
            $globalComposer = null;
            if (!$composer->isGlobal()) {
                $globalComposer = $this->createGlobalComposer($io, $config, $disablePlugins, $disableScripts);
            }
            $pm = $this->createPluginManager($io, $composer, $globalComposer, $disablePlugins);
            $composer->setPluginManager($pm);
            if ($composer->isGlobal()) {
                $pm->setRunningInGlobalDir(\true);
            }
            $pm->loadInstalledPlugins();
        }
        if ($fullLoad) {
            $initEvent = new Event(PluginEvents::INIT);
            $composer->getEventDispatcher()->dispatch($initEvent->getName(), $initEvent);
            // once everything is initialized we can
            // purge packages from local repos if they have been deleted on the filesystem
            $this->purgePackages($rm->getLocalRepository(), $im);
        }
        return $composer;
    }
    /**
     * @param  bool          $disablePlugins Whether plugins should not be loaded
     * @param  bool          $disableScripts Whether scripts should not be executed
     */
    public static function createGlobal(IOInterface $io, bool $disablePlugins = \false, bool $disableScripts = \false): ?\Composer\Composer
    {
        $factory = new static();
        return $factory->createGlobalComposer($io, static::createConfig($io), $disablePlugins, $disableScripts, \true);
    }
    protected function addLocalRepository(IOInterface $io, RepositoryManager $rm, string $vendorDir, RootPackageInterface $rootPackage, ?ProcessExecutor $process = null): void
    {
        $fs = null;
        if ($process) {
            $fs = new Filesystem($process);
        }
        $rm->setLocalRepository(new \Composer\Repository\InstalledFilesystemRepository(new JsonFile($vendorDir . '/composer/installed.json', null, $io), \true, $rootPackage, $fs));
    }
    /**
     * @param bool|'local'|'global' $disablePlugins Whether plugins should not be loaded, can be set to local or global to only disable local/global plugins
     * @return PartialComposer|Composer|null By default PartialComposer, but Composer if $fullLoad is set to true
     * @phpstan-return ($fullLoad is true ? Composer|null : PartialComposer|null)
     */
    protected function createGlobalComposer(IOInterface $io, \Composer\Config $config, $disablePlugins, bool $disableScripts, bool $fullLoad = \false): ?\Composer\PartialComposer
    {
        // make sure if disable plugins was 'local' it is now turned off
        $disablePlugins = $disablePlugins === 'global' || $disablePlugins === \true;
        $composer = null;
        try {
            $composer = $this->createComposer($io, $config->get('home') . '/composer.json', $disablePlugins, $config->get('home'), $fullLoad, $disableScripts);
        } catch (\Exception $e) {
            $io->writeError('Failed to initialize global composer: ' . $e->getMessage(), \true, IOInterface::DEBUG);
        }
        return $composer;
    }
    public function createDownloadManager(IOInterface $io, \Composer\Config $config, HttpDownloader $httpDownloader, ProcessExecutor $process, ?EventDispatcher $eventDispatcher = null): \Composer\Downloader\DownloadManager
    {
        $cache = null;
        if ($config->get('cache-files-ttl') > 0) {
            $cache = new \Composer\Cache($io, $config->get('cache-files-dir'), 'a-z0-9_./');
            $cache->setReadOnly($config->get('cache-read-only'));
        }
        $fs = new Filesystem($process);
        $dm = new \Composer\Downloader\DownloadManager($io, \false, $fs);
        switch ($preferred = $config->get('preferred-install')) {
            case 'dist':
                $dm->setPreferDist(\true);
                break;
            case 'source':
                $dm->setPreferSource(\true);
                break;
            case 'auto':
            default:
                // noop
                break;
        }
        if (is_array($preferred)) {
            $dm->setPreferences($preferred);
        }
        $dm->setDownloader('git', new \Composer\Downloader\GitDownloader($io, $config, $process, $fs));
        $dm->setDownloader('svn', new \Composer\Downloader\SvnDownloader($io, $config, $process, $fs));
        $dm->setDownloader('fossil', new \Composer\Downloader\FossilDownloader($io, $config, $process, $fs));
        $dm->setDownloader('hg', new \Composer\Downloader\HgDownloader($io, $config, $process, $fs));
        $dm->setDownloader('perforce', new \Composer\Downloader\PerforceDownloader($io, $config, $process, $fs));
        $dm->setDownloader('zip', new \Composer\Downloader\ZipDownloader($io, $config, $httpDownloader, $eventDispatcher, $cache, $fs, $process));
        $dm->setDownloader('rar', new \Composer\Downloader\RarDownloader($io, $config, $httpDownloader, $eventDispatcher, $cache, $fs, $process));
        $dm->setDownloader('tar', new \Composer\Downloader\TarDownloader($io, $config, $httpDownloader, $eventDispatcher, $cache, $fs, $process));
        $dm->setDownloader('gzip', new \Composer\Downloader\GzipDownloader($io, $config, $httpDownloader, $eventDispatcher, $cache, $fs, $process));
        $dm->setDownloader('xz', new \Composer\Downloader\XzDownloader($io, $config, $httpDownloader, $eventDispatcher, $cache, $fs, $process));
        $dm->setDownloader('phar', new \Composer\Downloader\PharDownloader($io, $config, $httpDownloader, $eventDispatcher, $cache, $fs, $process));
        $dm->setDownloader('file', new \Composer\Downloader\FileDownloader($io, $config, $httpDownloader, $eventDispatcher, $cache, $fs, $process));
        $dm->setDownloader('path', new \Composer\Downloader\PathDownloader($io, $config, $httpDownloader, $eventDispatcher, $cache, $fs, $process));
        return $dm;
    }
    /**
     * @param  Config                     $config The configuration
     * @param  Downloader\DownloadManager $dm     Manager use to download sources
     * @return Archiver\ArchiveManager
     */
    public function createArchiveManager(\Composer\Config $config, \Composer\Downloader\DownloadManager $dm, Loop $loop)
    {
        $am = new Archiver\ArchiveManager($dm, $loop);
        if (class_exists(ZipArchive::class)) {
            $am->addArchiver(new Archiver\ZipArchiver());
        }
        if (class_exists(Phar::class)) {
            $am->addArchiver(new Archiver\PharArchiver());
        }
        return $am;
    }
    /**
     * @param  bool|'local'|'global' $disablePlugins Whether plugins should not be loaded, can be set to local or global to only disable local/global plugins
     */
    protected function createPluginManager(IOInterface $io, \Composer\Composer $composer, ?\Composer\PartialComposer $globalComposer = null, $disablePlugins = \false): \Composer\Plugin\PluginManager
    {
        return new \Composer\Plugin\PluginManager($io, $composer, $globalComposer, $disablePlugins);
    }
    public function createInstallationManager(Loop $loop, IOInterface $io, ?EventDispatcher $eventDispatcher = null): \Composer\Installer\InstallationManager
    {
        return new \Composer\Installer\InstallationManager($loop, $io, $eventDispatcher);
    }
    protected function createDefaultInstallers(\Composer\Installer\InstallationManager $im, \Composer\PartialComposer $composer, IOInterface $io, ?ProcessExecutor $process = null): void
    {
        $fs = new Filesystem($process);
        $binaryInstaller = new \Composer\Installer\BinaryInstaller($io, rtrim($composer->getConfig()->get('bin-dir'), '/'), $composer->getConfig()->get('bin-compat'), $fs, rtrim($composer->getConfig()->get('vendor-dir'), '/'));
        $im->addInstaller(new \Composer\Installer\LibraryInstaller($io, $composer, null, $fs, $binaryInstaller));
        $im->addInstaller(new \Composer\Installer\PluginInstaller($io, $composer, $fs, $binaryInstaller));
        $im->addInstaller(new \Composer\Installer\MetapackageInstaller($io));
    }
    /**
     * @param InstalledRepositoryInterface   $repo repository to purge packages from
     * @param Installer\InstallationManager  $im   manager to check whether packages are still installed
     */
    protected function purgePackages(InstalledRepositoryInterface $repo, \Composer\Installer\InstallationManager $im): void
    {
        foreach ($repo->getPackages() as $package) {
            if (!$im->isPackageInstalled($repo, $package)) {
                $repo->removePackage($package);
            }
        }
    }
    protected function loadRootPackage(RepositoryManager $rm, \Composer\Config $config, VersionParser $parser, VersionGuesser $guesser, IOInterface $io): \Composer\Package\Loader\RootPackageLoader
    {
        return new \Composer\Package\Loader\RootPackageLoader($rm, $config, $parser, $guesser, $io);
    }
    /**
     * @param  IOInterface $io             IO instance
     * @param  mixed       $config         either a configuration array or a filename to read from, if null it will read from
     *                                     the default filename
     * @param  bool|'local'|'global' $disablePlugins Whether plugins should not be loaded, can be set to local or global to only disable local/global plugins
     * @param  bool        $disableScripts Whether scripts should not be run
     */
    public static function create(IOInterface $io, $config = null, $disablePlugins = \false, bool $disableScripts = \false): \Composer\Composer
    {
        $factory = new static();
        // for BC reasons, if a config is passed in either as array or a path that is not the default composer.json path
        // we disable local plugins as they really should not be loaded from CWD
        // If you want to avoid this behavior, you should be calling createComposer directly with a $cwd arg set correctly
        // to the path where the composer.json being loaded resides
        if ($config !== null && $config !== self::getComposerFile() && $disablePlugins === \false) {
            $disablePlugins = 'local';
        }
        return $factory->createComposer($io, $config, $disablePlugins, null, \true, $disableScripts);
    }
    /**
     * If you are calling this in a plugin, you probably should instead use $composer->getLoop()->getHttpDownloader()
     *
     * @param  IOInterface    $io      IO instance
     * @param  Config         $config  Config instance
     * @param  mixed[]        $options Array of options passed directly to HttpDownloader constructor
     */
    public static function createHttpDownloader(IOInterface $io, \Composer\Config $config, array $options = []): HttpDownloader
    {
        static $warned = \false;
        $disableTls = \false;
        // allow running the config command if disable-tls is in the arg list, even if openssl is missing, to allow disabling it via the config command
        if (isset($_SERVER['argv']) && in_array('disable-tls', $_SERVER['argv']) && (in_array('conf', $_SERVER['argv']) || in_array('config', $_SERVER['argv']))) {
            $warned = \true;
            $disableTls = !extension_loaded('openssl');
        } elseif ($config->get('disable-tls') === \true) {
            if (!$warned) {
                $io->writeError('<warning>You are running Composer with SSL/TLS protection disabled.</warning>');
            }
            $warned = \true;
            $disableTls = \true;
        } elseif (!extension_loaded('openssl')) {
            throw new \Composer\Exception\NoSslException('The openssl extension is required for SSL/TLS protection but is not available. ' . 'If you can not enable the openssl extension, you can disable this error, at your own risk, by setting the \'disable-tls\' option to true.');
        }
        $httpDownloaderOptions = [];
        if ($disableTls === \false) {
            if ('' !== $config->get('cafile')) {
                $httpDownloaderOptions['ssl']['cafile'] = $config->get('cafile');
            }
            if ('' !== $config->get('capath')) {
                $httpDownloaderOptions['ssl']['capath'] = $config->get('capath');
            }
            $httpDownloaderOptions = array_replace_recursive($httpDownloaderOptions, $options);
        }
        try {
            $httpDownloader = new HttpDownloader($io, $config, $httpDownloaderOptions, $disableTls);
        } catch (TransportException $e) {
            if (\false !== strpos($e->getMessage(), 'cafile')) {
                $io->write('<error>Unable to locate a valid CA certificate file. You must set a valid \'cafile\' option.</error>');
                $io->write('<error>A valid CA certificate file is required for SSL/TLS protection.</error>');
                $io->write('<error>You can disable this error, at your own risk, by setting the \'disable-tls\' option to true.</error>');
            }
            throw $e;
        }
        return $httpDownloader;
    }
    private static function loadComposerAuthEnv(\Composer\Config $config, ?IOInterface $io): void
    {
        $composerAuthEnv = Platform::getEnv('COMPOSER_AUTH');
        if (\false === $composerAuthEnv || '' === $composerAuthEnv) {
            return;
        }
        $authData = json_decode($composerAuthEnv);
        if (null === $authData) {
            throw new UnexpectedValueException('COMPOSER_AUTH environment variable is malformed, should be a valid JSON object');
        }
        if ($io instanceof IOInterface) {
            $io->writeError('Loading auth config from COMPOSER_AUTH', \true, IOInterface::DEBUG);
        }
        self::validateJsonSchema($io, $authData, JsonFile::AUTH_SCHEMA, 'COMPOSER_AUTH');
        $authData = json_decode($composerAuthEnv, \true);
        if (null !== $authData) {
            $config->merge(['config' => $authData], 'COMPOSER_AUTH');
        }
    }
    private static function useXdg(): bool
    {
        foreach (array_keys($_SERVER) as $key) {
            if (strpos((string) $key, 'XDG_') === 0) {
                return \true;
            }
        }
        if (Silencer::call('is_dir', '/etc/xdg')) {
            return \true;
        }
        return \false;
    }
    /**
     * @throws \RuntimeException
     */
    private static function getUserDir(): string
    {
        $home = Platform::getEnv('HOME');
        if (!$home) {
            throw new \RuntimeException('The HOME or COMPOSER_HOME environment variable must be set for composer to run correctly');
        }
        return rtrim(strtr($home, '\\', '/'), '/');
    }
    /**
     * @param mixed $fileOrData
     * @param JsonFile::*_SCHEMA $schema
     */
    private static function validateJsonSchema(?IOInterface $io, $fileOrData, int $schema = JsonFile::LAX_SCHEMA, ?string $source = null): void
    {
        if (Platform::isInputCompletionProcess()) {
            return;
        }
        try {
            if ($fileOrData instanceof JsonFile) {
                $fileOrData->validateSchema($schema);
            } else {
                if (null === $source) {
                    throw new \InvalidArgumentException('$source is required to be provided if $fileOrData is arbitrary data');
                }
                JsonFile::validateJsonSchema($source, $fileOrData, $schema);
            }
        } catch (JsonValidationException $e) {
            $msg = $e->getMessage() . ', this may result in errors and should be resolved:' . \PHP_EOL . ' - ' . implode(\PHP_EOL . ' - ', $e->getErrors());
            if ($io instanceof IOInterface) {
                $io->writeError('<warning>' . $msg . '</>');
            } else {
                throw new UnexpectedValueException($msg);
            }
        }
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer\Repository;

use Composer\Package\PackageInterface;
use Composer\Package\BasePackage;
use Composer\Semver\Constraint\ConstraintInterface;
/**
 * Repository interface.
 *
 * @author Nils Adermann <naderman@naderman.de>
 * @author Konstantin Kudryashov <ever.zet@gmail.com>
 * @author Jordi Boggiano <j.boggiano@seld.be>
 */
interface RepositoryInterface extends \Countable
{
    public const SEARCH_FULLTEXT = 0;
    public const SEARCH_NAME = 1;
    public const SEARCH_VENDOR = 2;
    /**
     * Checks if specified package registered (installed).
     *
     * @param PackageInterface $package package instance
     *
     * @return bool
     */
    public function hasPackage(PackageInterface $package);
    /**
     * Searches for the first match of a package by name and version.
     *
     * @param string                     $name       package name
     * @param string|ConstraintInterface $constraint package version or version constraint to match against
     *
     * @return BasePackage|null
     */
    public function findPackage(string $name, $constraint);
    /**
     * Searches for all packages matching a name and optionally a version.
     *
     * @param string                     $name       package name
     * @param string|ConstraintInterface $constraint package version or version constraint to match against
     *
     * @return BasePackage[]
     */
    public function findPackages(string $name, $constraint = null);
    /**
     * Returns list of registered packages.
     *
     * @return BasePackage[]
     */
    public function getPackages();
    /**
     * Returns list of registered packages with the supplied name
     *
     * - The packages returned are the packages found which match the constraints, acceptable stability and stability flags provided
     * - The namesFound returned are names which should be considered as canonically found in this repository, that should not be looked up in any further lower priority repositories
     *
     * @param ConstraintInterface[]                          $packageNameMap        package names pointing to constraints
     * @param array<string, int>        $acceptableStabilities array of stability => BasePackage::STABILITY_* value
     * @param array<string, BasePackage::STABILITY_*>        $stabilityFlags        an array of package name => BasePackage::STABILITY_* value
     * @param array<string, array<string, PackageInterface>> $alreadyLoaded         an array of package name => package version => package
     *
     * @return array
     *
     * @phpstan-param  array<key-of<BasePackage::STABILITIES>, BasePackage::STABILITY_*> $acceptableStabilities
     * @phpstan-param  array<string, ConstraintInterface|null> $packageNameMap
     * @phpstan-return array{namesFound: array<string>, packages: array<BasePackage>}
     */
    public function loadPackages(array $packageNameMap, array $acceptableStabilities, array $stabilityFlags, array $alreadyLoaded = []);
    /**
     * Searches the repository for packages containing the query
     *
     * @param string  $query search query, for SEARCH_NAME and SEARCH_VENDOR regular expressions metacharacters are supported by implementations, and user input should be escaped through preg_quote by callers
     * @param int     $mode  a set of SEARCH_* constants to search on, implementations should do a best effort only, default is SEARCH_FULLTEXT
     * @param ?string $type  The type of package to search for. Defaults to all types of packages
     *
     * @return array[] an array of array('name' => '...', 'description' => '...'|null, 'abandoned' => 'string'|true|unset) For SEARCH_VENDOR the name will be in "vendor" form
     * @phpstan-return list<array{name: string, description: ?string, abandoned?: string|true, url?: string}>
     */
    public function search(string $query, int $mode = 0, ?string $type = null);
    /**
     * Returns a list of packages providing a given package name
     *
     * Packages which have the same name as $packageName should not be returned, only those that have a "provide" on it.
     *
     * @param string $packageName package name which must be provided
     *
     * @return array[] an array with the provider name as key and value of array('name' => '...', 'description' => '...', 'type' => '...')
     * @phpstan-return array<string, array{name: string, description: string|null, type: string}>
     */
    public function getProviders(string $packageName);
    /**
     * Returns a name representing this repository to the user
     *
     * This is best effort and definitely can not always be very precise
     *
     * @return string
     */
    public function getRepoName();
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer\Repository;

/**
 * Installed filesystem repository.
 *
 * @author Jordi Boggiano <j.boggiano@seld.be>
 */
class InstalledFilesystemRepository extends \Composer\Repository\FilesystemRepository implements \Composer\Repository\InstalledRepositoryInterface
{
    public function getRepoName()
    {
        return 'installed ' . parent::getRepoName();
    }
    /**
     * @inheritDoc
     */
    public function isFresh()
    {
        return !$this->file->exists();
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer\Repository;

use Composer\Advisory\PartialSecurityAdvisory;
use Composer\Advisory\SecurityAdvisory;
use Composer\Package\Loader\ArrayLoader;
use Composer\Package\Loader\ValidatingArrayLoader;
use Composer\Package\Version\VersionParser;
use Composer\Pcre\Preg;
/**
 * Package repository.
 *
 * @author Jordi Boggiano <j.boggiano@seld.be>
 */
class PackageRepository extends \Composer\Repository\ArrayRepository implements \Composer\Repository\AdvisoryProviderInterface
{
    /** @var mixed[] */
    private $config;
    /** @var mixed[] */
    private $securityAdvisories;
    /**
     * Initializes filesystem repository.
     *
     * @param array{package: mixed[]} $config package definition
     */
    public function __construct(array $config)
    {
        parent::__construct();
        $this->config = $config['package'];
        // make sure we have an array of package definitions
        if (!is_numeric(key($this->config))) {
            $this->config = [$this->config];
        }
        $this->securityAdvisories = $config['security-advisories'] ?? [];
    }
    /**
     * Initializes repository (reads file, or remote address).
     */
    protected function initialize(): void
    {
        parent::initialize();
        $loader = new ValidatingArrayLoader(new ArrayLoader(null, \true), \true);
        foreach ($this->config as $package) {
            try {
                $package = $loader->load($package);
            } catch (\Exception $e) {
                throw new \Composer\Repository\InvalidRepositoryException('A repository of type "package" contains an invalid package definition: ' . $e->getMessage() . "\n\nInvalid package definition:\n" . json_encode($package));
            }
            $this->addPackage($package);
        }
    }
    public function getRepoName(): string
    {
        return Preg::replace('{^array }', 'package ', parent::getRepoName());
    }
    public function hasSecurityAdvisories(): bool
    {
        return count($this->securityAdvisories) > 0;
    }
    /**
     * @todo not sure if this is a good idea, just helped setting up the test fixtures
     */
    public function getSecurityAdvisories(array $packageConstraintMap, bool $allowPartialAdvisories = \false): array
    {
        $parser = new VersionParser();
        $advisories = [];
        foreach ($this->securityAdvisories as $packageName => $packageAdvisories) {
            if (isset($packageConstraintMap[$packageName])) {
                $advisories[$packageName] = array_values(array_filter(array_map(function (array $data) use ($packageName, $allowPartialAdvisories, $packageConstraintMap, $parser) {
                    $advisory = PartialSecurityAdvisory::create($packageName, $data, $parser);
                    if (!$allowPartialAdvisories && !$advisory instanceof SecurityAdvisory) {
                        throw new \RuntimeException('Advisory for ' . $packageName . ' could not be loaded as a full advisory from ' . $this->getRepoName() . \PHP_EOL . var_export($data, \true));
                    }
                    if (!$advisory->affectedVersions->matches($packageConstraintMap[$packageName])) {
                        return null;
                    }
                    return $advisory;
                }, $packageAdvisories)));
            }
        }
        return ['advisories' => array_filter($advisories, static function ($adv): bool {
            return \count($adv) > 0;
        }), 'namesFound' => array_keys($advisories)];
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer\Repository;

/**
 * Lock array repository.
 *
 * Regular array repository, only uses a different type to identify the lock file as the source of info
 *
 * @author Nils Adermann <naderman@naderman.de>
 */
class LockArrayRepository extends \Composer\Repository\ArrayRepository
{
    use \Composer\Repository\CanonicalPackagesTrait;
    public function getRepoName(): string
    {
        return 'lock repo';
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer\Repository;

use Composer\Composer;
use Composer\Package\CompletePackage;
use Composer\Package\CompletePackageInterface;
use Composer\Package\Link;
use Composer\Package\PackageInterface;
use Composer\Package\Version\VersionParser;
use Composer\Pcre\Preg;
use Composer\Platform\HhvmDetector;
use Composer\Platform\Runtime;
use Composer\Platform\Version;
use Composer\Plugin\PluginInterface;
use Composer\Semver\Constraint\Constraint;
use Composer\Util\Silencer;
use Composer\XdebugHandler\XdebugHandler;
/**
 * @author Jordi Boggiano <j.boggiano@seld.be>
 */
class PlatformRepository extends \Composer\Repository\ArrayRepository
{
    /**
     * @deprecated use PlatformRepository::isPlatformPackage(string $name) instead
     * @private
     */
    public const PLATFORM_PACKAGE_REGEX = '{^(?:php(?:-64bit|-ipv6|-zts|-debug)?|hhvm|(?:ext|lib)-[a-z0-9](?:[_.-]?[a-z0-9]+)*|composer(?:-(?:plugin|runtime)-api)?)$}iD';
    /**
     * @var ?string
     */
    private static $lastSeenPlatformPhp = null;
    /**
     * @var VersionParser
     */
    private $versionParser;
    /**
     * Defines overrides so that the platform can be mocked
     *
     * Keyed by package name (lowercased)
     *
     * @var array<string, array{name: string, version: string|false}>
     */
    private $overrides = [];
    /**
     * Stores which packages have been disabled and their actual version
     *
     * @var array<string, CompletePackageInterface>
     */
    private $disabledPackages = [];
    /** @var Runtime */
    private $runtime;
    /** @var HhvmDetector */
    private $hhvmDetector;
    /**
     * @param array<string, string|false> $overrides
     */
    public function __construct(array $packages = [], array $overrides = [], ?Runtime $runtime = null, ?HhvmDetector $hhvmDetector = null)
    {
        $this->runtime = $runtime ?: new Runtime();
        $this->hhvmDetector = $hhvmDetector ?: new HhvmDetector();
        foreach ($overrides as $name => $version) {
            if (!is_string($version) && \false !== $version) {
                // @phpstan-ignore-line
                throw new \UnexpectedValueException('config.platform.' . $name . ' should be a string or false, but got ' . get_debug_type($version) . ' ' . var_export($version, \true));
            }
            if ($name === 'php' && $version === \false) {
                throw new \UnexpectedValueException('config.platform.' . $name . ' cannot be set to false as you cannot disable php entirely.');
            }
            $this->overrides[strtolower($name)] = ['name' => $name, 'version' => $version];
        }
        parent::__construct($packages);
    }
    public function getRepoName(): string
    {
        return 'platform repo';
    }
    public function isPlatformPackageDisabled(string $name): bool
    {
        return isset($this->disabledPackages[$name]);
    }
    /**
     * @return array<string, CompletePackageInterface>
     */
    public function getDisabledPackages(): array
    {
        return $this->disabledPackages;
    }
    protected function initialize(): void
    {
        parent::initialize();
        $libraries = [];
        $this->versionParser = new VersionParser();
        // Add each of the override versions as options.
        // Later we might even replace the extensions instead.
        foreach ($this->overrides as $override) {
            // Check that it's a platform package.
            if (!self::isPlatformPackage($override['name'])) {
                throw new \InvalidArgumentException('Invalid platform package name in config.platform: ' . $override['name']);
            }
            if ($override['version'] !== \false) {
                $this->addOverriddenPackage($override);
            }
        }
        $prettyVersion = Composer::getVersion();
        $version = $this->versionParser->normalize($prettyVersion);
        $composer = new CompletePackage('composer', $version, $prettyVersion);
        $composer->setDescription('Composer package');
        $this->addPackage($composer);
        $prettyVersion = PluginInterface::PLUGIN_API_VERSION;
        $version = $this->versionParser->normalize($prettyVersion);
        $composerPluginApi = new CompletePackage('composer-plugin-api', $version, $prettyVersion);
        $composerPluginApi->setDescription('The Composer Plugin API');
        $this->addPackage($composerPluginApi);
        $prettyVersion = Composer::RUNTIME_API_VERSION;
        $version = $this->versionParser->normalize($prettyVersion);
        $composerRuntimeApi = new CompletePackage('composer-runtime-api', $version, $prettyVersion);
        $composerRuntimeApi->setDescription('The Composer Runtime API');
        $this->addPackage($composerRuntimeApi);
        try {
            $prettyVersion = $this->runtime->getConstant('PHP_VERSION');
            $version = $this->versionParser->normalize($prettyVersion);
        } catch (\UnexpectedValueException $e) {
            $prettyVersion = Preg::replace('#^([^~+-]+).*$#', '$1', $this->runtime->getConstant('PHP_VERSION'));
            $version = $this->versionParser->normalize($prettyVersion);
        }
        $php = new CompletePackage('php', $version, $prettyVersion);
        $php->setDescription('The PHP interpreter');
        $this->addPackage($php);
        if ($this->runtime->getConstant('PHP_DEBUG')) {
            $phpdebug = new CompletePackage('php-debug', $version, $prettyVersion);
            $phpdebug->setDescription('The PHP interpreter, with debugging symbols');
            $this->addPackage($phpdebug);
        }
        if ($this->runtime->hasConstant('PHP_ZTS') && $this->runtime->getConstant('PHP_ZTS')) {
            $phpzts = new CompletePackage('php-zts', $version, $prettyVersion);
            $phpzts->setDescription('The PHP interpreter, with Zend Thread Safety');
            $this->addPackage($phpzts);
        }
        if ($this->runtime->getConstant('PHP_INT_SIZE') === 8) {
            $php64 = new CompletePackage('php-64bit', $version, $prettyVersion);
            $php64->setDescription('The PHP interpreter, 64bit');
            $this->addPackage($php64);
        }
        // The AF_INET6 constant is only defined if ext-sockets is available but
        // IPv6 support might still be available.
        if ($this->runtime->hasConstant('AF_INET6') || Silencer::call([$this->runtime, 'invoke'], 'inet_pton', ['::']) !== \false) {
            $phpIpv6 = new CompletePackage('php-ipv6', $version, $prettyVersion);
            $phpIpv6->setDescription('The PHP interpreter, with IPv6 support');
            $this->addPackage($phpIpv6);
        }
        $loadedExtensions = $this->runtime->getExtensions();
        // Extensions scanning
        foreach ($loadedExtensions as $name) {
            if (in_array($name, ['standard', 'Core'])) {
                continue;
            }
            $this->addExtension($name, $this->runtime->getExtensionVersion($name));
        }
        // Check for Xdebug in a restarted process
        if (!in_array('xdebug', $loadedExtensions, \true) && $prettyVersion = XdebugHandler::getSkippedVersion()) {
            $this->addExtension('xdebug', $prettyVersion);
        }
        // Another quick loop, just for possible libraries
        // Doing it this way to know that functions or constants exist before
        // relying on them.
        foreach ($loadedExtensions as $name) {
            switch ($name) {
                case 'amqp':
                    $info = $this->runtime->getExtensionInfo($name);
                    // librabbitmq version => 0.9.0
                    if (Preg::isMatch('/^librabbitmq version => (?<version>.+)$/im', $info, $librabbitmqMatches)) {
                        $this->addLibrary($libraries, $name . '-librabbitmq', $librabbitmqMatches['version'], 'AMQP librabbitmq version');
                    }
                    // AMQP protocol version => 0-9-1
                    if (Preg::isMatchStrictGroups('/^AMQP protocol version => (?<version>.+)$/im', $info, $protocolMatches)) {
                        $this->addLibrary($libraries, $name . '-protocol', str_replace('-', '.', $protocolMatches['version']), 'AMQP protocol version');
                    }
                    break;
                case 'bz2':
                    $info = $this->runtime->getExtensionInfo($name);
                    // BZip2 Version => 1.0.6, 6-Sept-2010
                    if (Preg::isMatch('/^BZip2 Version => (?<version>.*),/im', $info, $matches)) {
                        $this->addLibrary($libraries, $name, $matches['version']);
                    }
                    break;
                case 'curl':
                    $curlVersion = $this->runtime->invoke('curl_version');
                    $this->addLibrary($libraries, $name, $curlVersion['version']);
                    $info = $this->runtime->getExtensionInfo($name);
                    // SSL Version => OpenSSL/1.0.1t
                    if (Preg::isMatchStrictGroups('{^SSL Version => (?<library>[^/]+)/(?<version>.+)$}im', $info, $sslMatches)) {
                        $library = strtolower($sslMatches['library']);
                        if ($library === 'openssl') {
                            $parsedVersion = Version::parseOpenssl($sslMatches['version'], $isFips);
                            $this->addLibrary($libraries, $name . '-openssl' . ($isFips ? '-fips' : ''), $parsedVersion, 'curl OpenSSL version (' . $parsedVersion . ')', [], $isFips ? ['curl-openssl'] : []);
                        } else {
                            if (str_starts_with($library, '(securetransport)') && Preg::isMatch('{^\(securetransport\) ([a-z0-9]+)}', $library, $securetransportMatches)) {
                                $shortlib = 'securetransport';
                                $sslLib = 'curl-' . $securetransportMatches[1];
                            } else {
                                $shortlib = $library;
                                $sslLib = 'curl-openssl';
                            }
                            $this->addLibrary($libraries, $name . '-' . $shortlib, $sslMatches['version'], 'curl ' . $library . ' version (' . $sslMatches['version'] . ')', [$sslLib]);
                        }
                    }
                    // libSSH Version => libssh2/1.4.3
                    if (Preg::isMatchStrictGroups('{^libSSH Version => (?<library>[^/]+)/(?<version>.+?)(?:/.*)?$}im', $info, $sshMatches)) {
                        $this->addLibrary($libraries, $name . '-' . strtolower($sshMatches['library']), $sshMatches['version'], 'curl ' . $sshMatches['library'] . ' version');
                    }
                    // ZLib Version => 1.2.8
                    if (Preg::isMatchStrictGroups('{^ZLib Version => (?<version>.+)$}im', $info, $zlibMatches)) {
                        $this->addLibrary($libraries, $name . '-zlib', $zlibMatches['version'], 'curl zlib version');
                    }
                    break;
                case 'date':
                    $info = $this->runtime->getExtensionInfo($name);
                    // timelib version => 2018.03
                    if (Preg::isMatchStrictGroups('/^timelib version => (?<version>.+)$/im', $info, $timelibMatches)) {
                        $this->addLibrary($libraries, $name . '-timelib', $timelibMatches['version'], 'date timelib version');
                    }
                    // Timezone Database => internal
                    if (Preg::isMatchStrictGroups('/^Timezone Database => (?<source>internal|external)$/im', $info, $zoneinfoSourceMatches)) {
                        $external = $zoneinfoSourceMatches['source'] === 'external';
                        if (Preg::isMatchStrictGroups('/^"Olson" Timezone Database Version => (?<version>.+?)(?:\.system)?$/im', $info, $zoneinfoMatches)) {
                            // If the timezonedb is provided by ext/timezonedb, register that version as a replacement
                            if ($external && in_array('timezonedb', $loadedExtensions, \true)) {
                                $this->addLibrary($libraries, 'timezonedb-zoneinfo', $zoneinfoMatches['version'], 'zoneinfo ("Olson") database for date (replaced by timezonedb)', [$name . '-zoneinfo']);
                            } else {
                                $this->addLibrary($libraries, $name . '-zoneinfo', $zoneinfoMatches['version'], 'zoneinfo ("Olson") database for date');
                            }
                        }
                    }
                    break;
                case 'fileinfo':
                    $info = $this->runtime->getExtensionInfo($name);
                    // libmagic => 537
                    if (Preg::isMatch('/^libmagic => (?<version>.+)$/im', $info, $magicMatches)) {
                        $this->addLibrary($libraries, $name . '-libmagic', $magicMatches['version'], 'fileinfo libmagic version');
                    }
                    break;
                case 'gd':
                    $this->addLibrary($libraries, $name, $this->runtime->getConstant('GD_VERSION'));
                    $info = $this->runtime->getExtensionInfo($name);
                    if (Preg::isMatchStrictGroups('/^libJPEG Version => (?<version>.+?)(?: compatible)?$/im', $info, $libjpegMatches)) {
                        $this->addLibrary($libraries, $name . '-libjpeg', Version::parseLibjpeg($libjpegMatches['version']), 'libjpeg version for gd');
                    }
                    if (Preg::isMatchStrictGroups('/^libPNG Version => (?<version>.+)$/im', $info, $libpngMatches)) {
                        $this->addLibrary($libraries, $name . '-libpng', $libpngMatches['version'], 'libpng version for gd');
                    }
                    if (Preg::isMatchStrictGroups('/^FreeType Version => (?<version>.+)$/im', $info, $freetypeMatches)) {
                        $this->addLibrary($libraries, $name . '-freetype', $freetypeMatches['version'], 'freetype version for gd');
                    }
                    if (Preg::isMatchStrictGroups('/^libXpm Version => (?<versionId>\d+)$/im', $info, $libxpmMatches)) {
                        $this->addLibrary($libraries, $name . '-libxpm', Version::convertLibxpmVersionId((int) $libxpmMatches['versionId']), 'libxpm version for gd');
                    }
                    break;
                case 'gmp':
                    $this->addLibrary($libraries, $name, $this->runtime->getConstant('GMP_VERSION'));
                    break;
                case 'iconv':
                    $this->addLibrary($libraries, $name, $this->runtime->getConstant('ICONV_VERSION'));
                    break;
                case 'intl':
                    $info = $this->runtime->getExtensionInfo($name);
                    $description = 'The ICU unicode and globalization support library';
                    // Truthy check is for testing only so we can make the condition fail
                    if ($this->runtime->hasConstant('INTL_ICU_VERSION')) {
                        $this->addLibrary($libraries, 'icu', $this->runtime->getConstant('INTL_ICU_VERSION'), $description);
                    } elseif (Preg::isMatch('/^ICU version => (?<version>.+)$/im', $info, $matches)) {
                        $this->addLibrary($libraries, 'icu', $matches['version'], $description);
                    }
                    // ICU TZData version => 2019c
                    if (Preg::isMatchStrictGroups('/^ICU TZData version => (?<version>.*)$/im', $info, $zoneinfoMatches) && null !== $version = Version::parseZoneinfoVersion($zoneinfoMatches['version'])) {
                        $this->addLibrary($libraries, 'icu-zoneinfo', $version, 'zoneinfo ("Olson") database for icu');
                    }
                    // Add a separate version for the CLDR library version
                    if ($this->runtime->hasClass('ResourceBundle')) {
                        $resourceBundle = $this->runtime->invoke(['ResourceBundle', 'create'], ['root', 'ICUDATA', \false]);
                        if ($resourceBundle !== null) {
                            $this->addLibrary($libraries, 'icu-cldr', $resourceBundle->get('Version'), 'ICU CLDR project version');
                        }
                    }
                    if ($this->runtime->hasClass('IntlChar')) {
                        $this->addLibrary($libraries, 'icu-unicode', implode('.', array_slice($this->runtime->invoke(['IntlChar', 'getUnicodeVersion']), 0, 3)), 'ICU unicode version');
                    }
                    break;
                case 'imagick':
                    // @phpstan-ignore staticMethod.dynamicCall (called like this for mockability)
                    $imageMagickVersion = $this->runtime->construct('Imagick')->getVersion();
                    // 6.x: ImageMagick 6.2.9 08/24/06 Q16 http://www.imagemagick.org
                    // 7.x: ImageMagick 7.0.8-34 Q16 x86_64 2019-03-23 https://imagemagick.org
                    if (Preg::isMatch('/^ImageMagick (?<version>[\d.]+)(?:-(?<patch>\d+))?/', $imageMagickVersion['versionString'], $matches)) {
                        $version = $matches['version'];
                        if (isset($matches['patch'])) {
                            $version .= '.' . $matches['patch'];
                        }
                        $this->addLibrary($libraries, $name . '-imagemagick', $version, null, ['imagick']);
                    }
                    break;
                case 'ldap':
                    $info = $this->runtime->getExtensionInfo($name);
                    if (Preg::isMatchStrictGroups('/^Vendor Version => (?<versionId>\d+)$/im', $info, $matches) && Preg::isMatchStrictGroups('/^Vendor Name => (?<vendor>.+)$/im', $info, $vendorMatches)) {
                        $this->addLibrary($libraries, $name . '-' . strtolower($vendorMatches['vendor']), Version::convertOpenldapVersionId((int) $matches['versionId']), $vendorMatches['vendor'] . ' version of ldap');
                    }
                    break;
                case 'libxml':
                    // ext/dom, ext/simplexml, ext/xmlreader and ext/xmlwriter use the same libxml as the ext/libxml
                    $libxmlProvides = array_map(static function ($extension): string {
                        return $extension . '-libxml';
                    }, array_intersect($loadedExtensions, ['dom', 'simplexml', 'xml', 'xmlreader', 'xmlwriter']));
                    $this->addLibrary($libraries, $name, $this->runtime->getConstant('LIBXML_DOTTED_VERSION'), 'libxml library version', [], $libxmlProvides);
                    break;
                case 'mbstring':
                    $info = $this->runtime->getExtensionInfo($name);
                    // libmbfl version => 1.3.2
                    if (Preg::isMatch('/^libmbfl version => (?<version>.+)$/im', $info, $libmbflMatches)) {
                        $this->addLibrary($libraries, $name . '-libmbfl', $libmbflMatches['version'], 'mbstring libmbfl version');
                    }
                    if ($this->runtime->hasConstant('MB_ONIGURUMA_VERSION')) {
                        $this->addLibrary($libraries, $name . '-oniguruma', $this->runtime->getConstant('MB_ONIGURUMA_VERSION'), 'mbstring oniguruma version');
                        // Multibyte regex (oniguruma) version => 5.9.5
                        // oniguruma version => 6.9.0
                    } elseif (Preg::isMatch('/^(?:oniguruma|Multibyte regex \(oniguruma\)) version => (?<version>.+)$/im', $info, $onigurumaMatches)) {
                        $this->addLibrary($libraries, $name . '-oniguruma', $onigurumaMatches['version'], 'mbstring oniguruma version');
                    }
                    break;
                case 'memcached':
                    $info = $this->runtime->getExtensionInfo($name);
                    // libmemcached version => 1.0.18
                    if (Preg::isMatch('/^libmemcached version => (?<version>.+)$/im', $info, $matches)) {
                        $this->addLibrary($libraries, $name . '-libmemcached', $matches['version'], 'libmemcached version');
                    }
                    break;
                case 'openssl':
                    // OpenSSL 1.1.1g  21 Apr 2020
                    if (Preg::isMatchStrictGroups('{^(?:OpenSSL|LibreSSL)?\s*(?<version>\S+)}i', $this->runtime->getConstant('OPENSSL_VERSION_TEXT'), $matches)) {
                        $parsedVersion = Version::parseOpenssl($matches['version'], $isFips);
                        $this->addLibrary($libraries, $name . ($isFips ? '-fips' : ''), $parsedVersion, $this->runtime->getConstant('OPENSSL_VERSION_TEXT'), [], $isFips ? [$name] : []);
                    }
                    break;
                case 'pcre':
                    $this->addLibrary($libraries, $name, Preg::replace('{^(\S+).*}', '$1', $this->runtime->getConstant('PCRE_VERSION')));
                    $info = $this->runtime->getExtensionInfo($name);
                    // PCRE Unicode Version => 12.1.0
                    if (Preg::isMatchStrictGroups('/^PCRE Unicode Version => (?<version>.+)$/im', $info, $pcreUnicodeMatches)) {
                        $this->addLibrary($libraries, $name . '-unicode', $pcreUnicodeMatches['version'], 'PCRE Unicode version support');
                    }
                    break;
                case 'mysqlnd':
                case 'pdo_mysql':
                    $info = $this->runtime->getExtensionInfo($name);
                    if (Preg::isMatchStrictGroups('/^(?:Client API version|Version) => mysqlnd (?<version>.+?) /mi', $info, $matches)) {
                        $this->addLibrary($libraries, $name . '-mysqlnd', $matches['version'], 'mysqlnd library version for ' . $name);
                    }
                    break;
                case 'mongodb':
                    $info = $this->runtime->getExtensionInfo($name);
                    if (Preg::isMatchStrictGroups('/^libmongoc bundled version => (?<version>.+)$/im', $info, $libmongocMatches)) {
                        $this->addLibrary($libraries, $name . '-libmongoc', $libmongocMatches['version'], 'libmongoc version of mongodb');
                    }
                    if (Preg::isMatchStrictGroups('/^libbson bundled version => (?<version>.+)$/im', $info, $libbsonMatches)) {
                        $this->addLibrary($libraries, $name . '-libbson', $libbsonMatches['version'], 'libbson version of mongodb');
                    }
                    break;
                case 'pgsql':
                    if ($this->runtime->hasConstant('PGSQL_LIBPQ_VERSION')) {
                        $this->addLibrary($libraries, 'pgsql-libpq', $this->runtime->getConstant('PGSQL_LIBPQ_VERSION'), 'libpq for pgsql');
                        break;
                    }
                // intentional fall-through to next case...
                case 'pdo_pgsql':
                    $info = $this->runtime->getExtensionInfo($name);
                    if (Preg::isMatch('/^PostgreSQL\(libpq\) Version => (?<version>.*)$/im', $info, $matches)) {
                        $this->addLibrary($libraries, $name . '-libpq', $matches['version'], 'libpq for ' . $name);
                    }
                    break;
                case 'pq':
                    $info = $this->runtime->getExtensionInfo($name);
                    // Used Library => Compiled => Linked
                    // libpq => 14.3 (Ubuntu 14.3-1.pgdg22.04+1) => 15.0.2
                    if (Preg::isMatch('/^libpq => (?<compiled>.+) => (?<linked>.+)$/im', $info, $matches)) {
                        $this->addLibrary($libraries, $name . '-libpq', $matches['linked'], 'libpq for ' . $name);
                    }
                    break;
                case 'rdkafka':
                    if ($this->runtime->hasConstant('RD_KAFKA_VERSION')) {
                        /**
                         * Interpreted as hex \c MM.mm.rr.xx:
                         *  - MM = Major
                         *  - mm = minor
                         *  - rr = revision
                         *  - xx = pre-release id (0xff is the final release)
                         *
                         * pre-release ID in practice is always 0xff even for RCs etc, so we ignore it
                         */
                        $libRdKafkaVersionInt = $this->runtime->getConstant('RD_KAFKA_VERSION');
                        $this->addLibrary($libraries, $name . '-librdkafka', sprintf('%d.%d.%d', ($libRdKafkaVersionInt & 0x7f000000) >> 24, ($libRdKafkaVersionInt & 0xff0000) >> 16, ($libRdKafkaVersionInt & 0xff00) >> 8), 'librdkafka for ' . $name);
                    }
                    break;
                case 'libsodium':
                case 'sodium':
                    if ($this->runtime->hasConstant('SODIUM_LIBRARY_VERSION')) {
                        $this->addLibrary($libraries, 'libsodium', $this->runtime->getConstant('SODIUM_LIBRARY_VERSION'));
                        $this->addLibrary($libraries, 'libsodium', $this->runtime->getConstant('SODIUM_LIBRARY_VERSION'));
                    }
                    break;
                case 'sqlite3':
                case 'pdo_sqlite':
                    $info = $this->runtime->getExtensionInfo($name);
                    if (Preg::isMatch('/^SQLite Library => (?<version>.+)$/im', $info, $matches)) {
                        $this->addLibrary($libraries, $name . '-sqlite', $matches['version']);
                    }
                    break;
                case 'ssh2':
                    $info = $this->runtime->getExtensionInfo($name);
                    if (Preg::isMatch('/^libssh2 version => (?<version>.+)$/im', $info, $matches)) {
                        $this->addLibrary($libraries, $name . '-libssh2', $matches['version']);
                    }
                    break;
                case 'xsl':
                    $this->addLibrary($libraries, 'libxslt', $this->runtime->getConstant('LIBXSLT_DOTTED_VERSION'), null, ['xsl']);
                    $info = $this->runtime->getExtensionInfo('xsl');
                    if (Preg::isMatch('/^libxslt compiled against libxml Version => (?<version>.+)$/im', $info, $matches)) {
                        $this->addLibrary($libraries, 'libxslt-libxml', $matches['version'], 'libxml version libxslt is compiled against');
                    }
                    break;
                case 'yaml':
                    $info = $this->runtime->getExtensionInfo('yaml');
                    if (Preg::isMatch('/^LibYAML Version => (?<version>.+)$/im', $info, $matches)) {
                        $this->addLibrary($libraries, $name . '-libyaml', $matches['version'], 'libyaml version of yaml');
                    }
                    break;
                case 'zip':
                    if ($this->runtime->hasConstant('LIBZIP_VERSION', 'ZipArchive')) {
                        $this->addLibrary($libraries, $name . '-libzip', $this->runtime->getConstant('LIBZIP_VERSION', 'ZipArchive'), null, ['zip']);
                    }
                    break;
                case 'zlib':
                    if ($this->runtime->hasConstant('ZLIB_VERSION')) {
                        $this->addLibrary($libraries, $name, $this->runtime->getConstant('ZLIB_VERSION'));
                        // Linked Version => 1.2.8
                    } elseif (Preg::isMatch('/^Linked Version => (?<version>.+)$/im', $this->runtime->getExtensionInfo($name), $matches)) {
                        $this->addLibrary($libraries, $name, $matches['version']);
                    }
                    break;
                default:
                    break;
            }
        }
        $hhvmVersion = $this->hhvmDetector->getVersion();
        if ($hhvmVersion) {
            try {
                $prettyVersion = $hhvmVersion;
                $version = $this->versionParser->normalize($prettyVersion);
            } catch (\UnexpectedValueException $e) {
                $prettyVersion = Preg::replace('#^([^~+-]+).*$#', '$1', $hhvmVersion);
                $version = $this->versionParser->normalize($prettyVersion);
            }
            $hhvm = new CompletePackage('hhvm', $version, $prettyVersion);
            $hhvm->setDescription('The HHVM Runtime (64bit)');
            $this->addPackage($hhvm);
        }
    }
    /**
     * @inheritDoc
     */
    public function addPackage(PackageInterface $package): void
    {
        if (!$package instanceof CompletePackage) {
            throw new \UnexpectedValueException('Expected CompletePackage but got ' . get_class($package));
        }
        // Skip if overridden
        if (isset($this->overrides[$package->getName()])) {
            if ($this->overrides[$package->getName()]['version'] === \false) {
                $this->addDisabledPackage($package);
                return;
            }
            $overrider = $this->findPackage($package->getName(), '*');
            if ($package->getVersion() === $overrider->getVersion()) {
                $actualText = 'same as actual';
            } else {
                $actualText = 'actual: ' . $package->getPrettyVersion();
            }
            if ($overrider instanceof CompletePackageInterface) {
                $overrider->setDescription($overrider->getDescription() . ', ' . $actualText);
            }
            return;
        }
        // Skip if PHP is overridden and we are adding a php-* package
        if (isset($this->overrides['php']) && 0 === strpos($package->getName(), 'php-')) {
            $overrider = $this->addOverriddenPackage($this->overrides['php'], $package->getPrettyName());
            if ($package->getVersion() === $overrider->getVersion()) {
                $actualText = 'same as actual';
            } else {
                $actualText = 'actual: ' . $package->getPrettyVersion();
            }
            $overrider->setDescription($overrider->getDescription() . ', ' . $actualText);
            return;
        }
        parent::addPackage($package);
    }
    /**
     * @param array{version: string, name: string} $override
     */
    private function addOverriddenPackage(array $override, ?string $name = null): CompletePackage
    {
        $version = $this->versionParser->normalize($override['version']);
        $package = new CompletePackage($name ?: $override['name'], $version, $override['version']);
        $package->setDescription('Package overridden via config.platform');
        $package->setExtra(['config.platform' => \true]);
        parent::addPackage($package);
        if ($package->getName() === 'php') {
            self::$lastSeenPlatformPhp = implode('.', array_slice(explode('.', $package->getVersion()), 0, 3));
        }
        return $package;
    }
    private function addDisabledPackage(CompletePackage $package): void
    {
        $package->setDescription($package->getDescription() . '. <warning>Package disabled via config.platform</warning>');
        $package->setExtra(['config.platform' => \true]);
        $this->disabledPackages[$package->getName()] = $package;
    }
    /**
     * Parses the version and adds a new package to the repository
     */
    private function addExtension(string $name, string $prettyVersion): void
    {
        $extraDescription = null;
        try {
            $version = $this->versionParser->normalize($prettyVersion);
        } catch (\UnexpectedValueException $e) {
            $extraDescription = ' (actual version: ' . $prettyVersion . ')';
            if (Preg::isMatchStrictGroups('{^(\d+\.\d+\.\d+(?:\.\d+)?)}', $prettyVersion, $match)) {
                $prettyVersion = $match[1];
            } else {
                $prettyVersion = '0';
            }
            $version = $this->versionParser->normalize($prettyVersion);
        }
        $packageName = $this->buildPackageName($name);
        $ext = new CompletePackage($packageName, $version, $prettyVersion);
        $ext->setDescription('The ' . $name . ' PHP extension' . $extraDescription);
        $ext->setType('php-ext');
        if ($name === 'uuid') {
            $ext->setReplaces(['lib-uuid' => new Link('ext-uuid', 'lib-uuid', new Constraint('=', $version), Link::TYPE_REPLACE, $ext->getPrettyVersion())]);
        }
        $this->addPackage($ext);
    }
    private function buildPackageName(string $name): string
    {
        return 'ext-' . str_replace(' ', '-', strtolower($name));
    }
    /**
     * @param array<string, bool> $libraries
     * @param array<string> $replaces
     * @param array<string> $provides
     */
    private function addLibrary(array &$libraries, string $name, ?string $prettyVersion, ?string $description = null, array $replaces = [], array $provides = []): void
    {
        if (null === $prettyVersion) {
            return;
        }
        try {
            $version = $this->versionParser->normalize($prettyVersion);
        } catch (\UnexpectedValueException $e) {
            return;
        }
        // avoid adding the same lib twice even if two conflicting extensions provide the same lib
        // see https://github.com/composer/composer/issues/12082
        if (isset($libraries['lib-' . $name])) {
            return;
        }
        $libraries['lib-' . $name] = \true;
        if ($description === null) {
            $description = 'The ' . $name . ' library';
        }
        $lib = new CompletePackage('lib-' . $name, $version, $prettyVersion);
        $lib->setDescription($description);
        $replaceLinks = [];
        foreach ($replaces as $replace) {
            $replace = strtolower($replace);
            $replaceLinks[$replace] = new Link('lib-' . $name, 'lib-' . $replace, new Constraint('=', $version), Link::TYPE_REPLACE, $lib->getPrettyVersion());
        }
        $provideLinks = [];
        foreach ($provides as $provide) {
            $provide = strtolower($provide);
            $provideLinks[$provide] = new Link('lib-' . $name, 'lib-' . $provide, new Constraint('=', $version), Link::TYPE_PROVIDE, $lib->getPrettyVersion());
        }
        $lib->setReplaces($replaceLinks);
        $lib->setProvides($provideLinks);
        $this->addPackage($lib);
    }
    /**
     * Check if a package name is a platform package.
     */
    public static function isPlatformPackage(string $name): bool
    {
        static $cache = [];
        if (isset($cache[$name])) {
            return $cache[$name];
        }
        return $cache[$name] = Preg::isMatch(\Composer\Repository\PlatformRepository::PLATFORM_PACKAGE_REGEX, $name);
    }
    /**
     * Returns the last seen config.platform.php version if defined
     *
     * This is a best effort attempt for internal purposes, retrieve the real
     * packages from a PlatformRepository instance if you need a version guaranteed to
     * be correct.
     *
     * @internal
     */
    public static function getPlatformPhpVersion(): ?string
    {
        return self::$lastSeenPlatformPhp;
    }
    public function search(string $query, int $mode = 0, ?string $type = null): array
    {
        // suppress vendor search as there are no vendors to match in platform packages
        if ($mode === self::SEARCH_VENDOR) {
            return [];
        }
        return parent::search($query, $mode, $type);
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer\Repository;

use Composer\Factory;
use Composer\IO\IOInterface;
use Composer\Config;
use Composer\EventDispatcher\EventDispatcher;
use Composer\Pcre\Preg;
use Composer\Util\HttpDownloader;
use Composer\Util\ProcessExecutor;
use Composer\Json\JsonFile;
/**
 * @author Jordi Boggiano <j.boggiano@seld.be>
 */
class RepositoryFactory
{
    /**
     * @return array|mixed
     */
    public static function configFromString(IOInterface $io, Config $config, string $repository, bool $allowFilesystem = \false)
    {
        if (0 === strpos($repository, 'http')) {
            $repoConfig = ['type' => 'composer', 'url' => $repository];
        } elseif ("json" === pathinfo($repository, \PATHINFO_EXTENSION)) {
            $json = new JsonFile($repository, Factory::createHttpDownloader($io, $config));
            $data = $json->read();
            if (!empty($data['packages']) || !empty($data['includes']) || !empty($data['provider-includes'])) {
                $repoConfig = ['type' => 'composer', 'url' => 'file://' . strtr(realpath($repository), '\\', '/')];
            } elseif ($allowFilesystem) {
                $repoConfig = ['type' => 'filesystem', 'json' => $json];
            } else {
                throw new \InvalidArgumentException("Invalid repository URL ({$repository}) given. This file does not contain a valid composer repository.");
            }
        } elseif (strpos($repository, '{') === 0) {
            // assume it is a json object that makes a repo config
            $repoConfig = JsonFile::parseJson($repository);
        } else {
            throw new \InvalidArgumentException("Invalid repository url ({$repository}) given. Has to be a .json file, an http url or a JSON object.");
        }
        return $repoConfig;
    }
    public static function fromString(IOInterface $io, Config $config, string $repository, bool $allowFilesystem = \false, ?\Composer\Repository\RepositoryManager $rm = null): \Composer\Repository\RepositoryInterface
    {
        $repoConfig = static::configFromString($io, $config, $repository, $allowFilesystem);
        return static::createRepo($io, $config, $repoConfig, $rm);
    }
    /**
     * @param  array<string, mixed> $repoConfig
     */
    public static function createRepo(IOInterface $io, Config $config, array $repoConfig, ?\Composer\Repository\RepositoryManager $rm = null): \Composer\Repository\RepositoryInterface
    {
        if (!$rm) {
            @trigger_error('Not passing a repository manager when calling createRepo is deprecated since Composer 2.3.6', \E_USER_DEPRECATED);
            $rm = static::manager($io, $config);
        }
        $repos = self::createRepos($rm, [$repoConfig]);
        return reset($repos);
    }
    /**
     * @return RepositoryInterface[]
     */
    public static function defaultRepos(?IOInterface $io = null, ?Config $config = null, ?\Composer\Repository\RepositoryManager $rm = null): array
    {
        if (null === $rm) {
            @trigger_error('Not passing a repository manager when calling defaultRepos is deprecated since Composer 2.3.6, use defaultReposWithDefaultManager() instead if you cannot get a manager.', \E_USER_DEPRECATED);
        }
        if (null === $config) {
            $config = Factory::createConfig($io);
        }
        if (null !== $io) {
            $io->loadConfiguration($config);
        }
        if (null === $rm) {
            if (null === $io) {
                throw new \InvalidArgumentException('This function requires either an IOInterface or a RepositoryManager');
            }
            $rm = static::manager($io, $config, Factory::createHttpDownloader($io, $config));
        }
        return self::createRepos($rm, $config->getRepositories());
    }
    public static function manager(IOInterface $io, Config $config, ?HttpDownloader $httpDownloader = null, ?EventDispatcher $eventDispatcher = null, ?ProcessExecutor $process = null): \Composer\Repository\RepositoryManager
    {
        if ($httpDownloader === null) {
            $httpDownloader = Factory::createHttpDownloader($io, $config);
        }
        if ($process === null) {
            $process = new ProcessExecutor($io);
            $process->enableAsync();
        }
        $rm = new \Composer\Repository\RepositoryManager($io, $config, $httpDownloader, $eventDispatcher, $process);
        $rm->setRepositoryClass('composer', 'Composer\Repository\ComposerRepository');
        $rm->setRepositoryClass('vcs', 'Composer\Repository\VcsRepository');
        $rm->setRepositoryClass('package', 'Composer\Repository\PackageRepository');
        $rm->setRepositoryClass('pear', 'Composer\Repository\PearRepository');
        $rm->setRepositoryClass('git', 'Composer\Repository\VcsRepository');
        $rm->setRepositoryClass('bitbucket', 'Composer\Repository\VcsRepository');
        $rm->setRepositoryClass('git-bitbucket', 'Composer\Repository\VcsRepository');
        $rm->setRepositoryClass('github', 'Composer\Repository\VcsRepository');
        $rm->setRepositoryClass('gitlab', 'Composer\Repository\VcsRepository');
        $rm->setRepositoryClass('svn', 'Composer\Repository\VcsRepository');
        $rm->setRepositoryClass('fossil', 'Composer\Repository\VcsRepository');
        $rm->setRepositoryClass('perforce', 'Composer\Repository\VcsRepository');
        $rm->setRepositoryClass('hg', 'Composer\Repository\VcsRepository');
        $rm->setRepositoryClass('artifact', 'Composer\Repository\ArtifactRepository');
        $rm->setRepositoryClass('path', 'Composer\Repository\PathRepository');
        return $rm;
    }
    /**
     * @return RepositoryInterface[]
     */
    public static function defaultReposWithDefaultManager(IOInterface $io): array
    {
        $manager = \Composer\Repository\RepositoryFactory::manager($io, $config = Factory::createConfig($io));
        $io->loadConfiguration($config);
        return \Composer\Repository\RepositoryFactory::defaultRepos($io, $config, $manager);
    }
    /**
     * @param array<int|string, mixed> $repoConfigs
     *
     * @return RepositoryInterface[]
     */
    private static function createRepos(\Composer\Repository\RepositoryManager $rm, array $repoConfigs): array
    {
        $repos = [];
        foreach ($repoConfigs as $index => $repo) {
            if (is_string($repo)) {
                throw new \UnexpectedValueException('"repositories" should be an array of repository definitions, only a single repository was given');
            }
            if (!is_array($repo)) {
                throw new \UnexpectedValueException('Repository "' . $index . '" (' . json_encode($repo) . ') should be an array, ' . get_debug_type($repo) . ' given');
            }
            if (!isset($repo['type'])) {
                throw new \UnexpectedValueException('Repository "' . $index . '" (' . json_encode($repo) . ') must have a type defined');
            }
            $name = self::generateRepositoryName($index, $repo, $repos);
            if ($repo['type'] === 'filesystem') {
                $repos[$name] = new \Composer\Repository\FilesystemRepository($repo['json']);
            } else {
                $repos[$name] = $rm->createRepository($repo['type'], $repo, (string) $index);
            }
        }
        return $repos;
    }
    /**
     * @param int|string $index
     * @param array{url?: string} $repo
     * @param array<int|string, mixed> $existingRepos
     */
    public static function generateRepositoryName($index, array $repo, array $existingRepos): string
    {
        $name = is_int($index) && isset($repo['url']) ? Preg::replace('{^https?://}i', '', $repo['url']) : (string) $index;
        while (isset($existingRepos[$name])) {
            $name .= '2';
        }
        return $name;
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer\Repository;

/**
 * Installable repository interface.
 *
 * Just used to tag installed repositories so the base classes can act differently on Alias packages
 *
 * @author Jordi Boggiano <j.boggiano@seld.be>
 */
interface InstalledRepositoryInterface extends \Composer\Repository\WritableRepositoryInterface
{
    /**
     * @return bool|null true if dev requirements were installed, false if --no-dev was used, null if yet unknown
     */
    public function getDevMode();
    /**
     * @return bool true if packages were never installed in this repository
     */
    public function isFresh();
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer\Repository;

use Composer\Package\PackageInterface;
use Composer\Installer\InstallationManager;
/**
 * Writable repository interface.
 *
 * @author Konstantin Kudryashov <ever.zet@gmail.com>
 */
interface WritableRepositoryInterface extends \Composer\Repository\RepositoryInterface
{
    /**
     * Writes repository (f.e. to the disc).
     *
     * @param bool $devMode Whether dev requirements were included or not in this installation
     * @return void
     */
    public function write(bool $devMode, InstallationManager $installationManager);
    /**
     * Adds package to the repository.
     *
     * @param PackageInterface $package package instance
     * @return void
     */
    public function addPackage(PackageInterface $package);
    /**
     * Removes package from the repository.
     *
     * @param PackageInterface $package package instance
     * @return void
     */
    public function removePackage(PackageInterface $package);
    /**
     * Get unique packages (at most one package of each name), with aliases resolved and removed.
     *
     * @return PackageInterface[]
     */
    public function getCanonicalPackages();
    /**
     * Forces a reload of all packages.
     *
     * @return void
     */
    public function reload();
    /**
     * @param string[] $devPackageNames
     * @return void
     */
    public function setDevPackageNames(array $devPackageNames);
    /**
     * @return string[] Names of dependencies installed through require-dev
     */
    public function getDevPackageNames();
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer\Repository;

use Composer\Package\PackageInterface;
/**
 * @author Jordi Boggiano <j.boggiano@seld.be>
 *
 * @see RepositorySet for ways to work with sets of repos
 */
class RepositoryUtils
{
    /**
     * Find all of $packages which are required by $requirer, either directly or transitively
     *
     * Require-dev is ignored by default, you can enable the require-dev of the initial $requirer
     * packages by passing $includeRequireDev=true, but require-dev of transitive dependencies
     * are always ignored.
     *
     * @template T of PackageInterface
     * @param  array<T> $packages
     * @param  list<T> $bucket Do not pass this in, only used to avoid recursion with circular deps
     * @return list<T>
     */
    public static function filterRequiredPackages(array $packages, PackageInterface $requirer, bool $includeRequireDev = \false, array $bucket = []): array
    {
        $requires = $requirer->getRequires();
        if ($includeRequireDev) {
            $requires = array_merge($requires, $requirer->getDevRequires());
        }
        foreach ($packages as $candidate) {
            foreach ($candidate->getNames() as $name) {
                if (isset($requires[$name])) {
                    if (!in_array($candidate, $bucket, \true)) {
                        $bucket[] = $candidate;
                        $bucket = self::filterRequiredPackages($packages, $candidate, \false, $bucket);
                    }
                    break;
                }
            }
        }
        return $bucket;
    }
    /**
     * Unwraps CompositeRepository, InstalledRepository and optionally FilterRepository to get a flat array of pure repository instances
     *
     * @return RepositoryInterface[]
     */
    public static function flattenRepositories(\Composer\Repository\RepositoryInterface $repo, bool $unwrapFilterRepos = \true): array
    {
        // unwrap filter repos
        if ($unwrapFilterRepos && $repo instanceof \Composer\Repository\FilterRepository) {
            $repo = $repo->getRepository();
        }
        if (!$repo instanceof \Composer\Repository\CompositeRepository) {
            return [$repo];
        }
        $repos = [];
        foreach ($repo->getRepositories() as $r) {
            foreach (self::flattenRepositories($r, $unwrapFilterRepos) as $r2) {
                $repos[] = $r2;
            }
        }
        return $repos;
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer\Repository;

/**
 * Thrown when a security problem, like a broken or missing signature
 *
 * @author Eric Daspet <edaspet@survol.fr>
 */
class RepositorySecurityException extends \Exception
{
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer\Repository;

use Composer\Package\BasePackage;
use Composer\Package\PackageInterface;
/**
 * Composite repository.
 *
 * @author Beau Simensen <beau@dflydev.com>
 */
class CompositeRepository implements \Composer\Repository\RepositoryInterface
{
    /**
     * List of repositories
     * @var RepositoryInterface[]
     */
    private $repositories;
    /**
     * Constructor
     * @param RepositoryInterface[] $repositories
     */
    public function __construct(array $repositories)
    {
        $this->repositories = [];
        foreach ($repositories as $repo) {
            $this->addRepository($repo);
        }
    }
    public function getRepoName(): string
    {
        return 'composite repo (' . implode(', ', array_map(static function ($repo): string {
            return $repo->getRepoName();
        }, $this->repositories)) . ')';
    }
    /**
     * Returns all the wrapped repositories
     *
     * @return RepositoryInterface[]
     */
    public function getRepositories(): array
    {
        return $this->repositories;
    }
    /**
     * @inheritDoc
     */
    public function hasPackage(PackageInterface $package): bool
    {
        foreach ($this->repositories as $repository) {
            /* @var $repository RepositoryInterface */
            if ($repository->hasPackage($package)) {
                return \true;
            }
        }
        return \false;
    }
    /**
     * @inheritDoc
     */
    public function findPackage($name, $constraint): ?BasePackage
    {
        foreach ($this->repositories as $repository) {
            /* @var $repository RepositoryInterface */
            $package = $repository->findPackage($name, $constraint);
            if (null !== $package) {
                return $package;
            }
        }
        return null;
    }
    /**
     * @inheritDoc
     */
    public function findPackages($name, $constraint = null): array
    {
        $packages = [];
        foreach ($this->repositories as $repository) {
            /* @var $repository RepositoryInterface */
            $packages[] = $repository->findPackages($name, $constraint);
        }
        return $packages ? array_merge(...$packages) : [];
    }
    /**
     * @inheritDoc
     */
    public function loadPackages(array $packageNameMap, array $acceptableStabilities, array $stabilityFlags, array $alreadyLoaded = []): array
    {
        $packages = [];
        $namesFound = [];
        foreach ($this->repositories as $repository) {
            /* @var $repository RepositoryInterface */
            $result = $repository->loadPackages($packageNameMap, $acceptableStabilities, $stabilityFlags, $alreadyLoaded);
            $packages[] = $result['packages'];
            $namesFound[] = $result['namesFound'];
        }
        return ['packages' => $packages ? array_merge(...$packages) : [], 'namesFound' => $namesFound ? array_unique(array_merge(...$namesFound)) : []];
    }
    /**
     * @inheritDoc
     */
    public function search(string $query, int $mode = 0, ?string $type = null): array
    {
        $matches = [];
        foreach ($this->repositories as $repository) {
            /* @var $repository RepositoryInterface */
            $matches[] = $repository->search($query, $mode, $type);
        }
        return \count($matches) > 0 ? array_merge(...$matches) : [];
    }
    /**
     * @inheritDoc
     */
    public function getPackages(): array
    {
        $packages = [];
        foreach ($this->repositories as $repository) {
            /* @var $repository RepositoryInterface */
            $packages[] = $repository->getPackages();
        }
        return $packages ? array_merge(...$packages) : [];
    }
    /**
     * @inheritDoc
     */
    public function getProviders($packageName): array
    {
        $results = [];
        foreach ($this->repositories as $repository) {
            /* @var $repository RepositoryInterface */
            $results[] = $repository->getProviders($packageName);
        }
        return $results ? array_merge(...$results) : [];
    }
    public function removePackage(PackageInterface $package): void
    {
        foreach ($this->repositories as $repository) {
            if ($repository instanceof \Composer\Repository\WritableRepositoryInterface) {
                $repository->removePackage($package);
            }
        }
    }
    /**
     * @inheritDoc
     */
    public function count(): int
    {
        $total = 0;
        foreach ($this->repositories as $repository) {
            /* @var $repository RepositoryInterface */
            $total += $repository->count();
        }
        return $total;
    }
    /**
     * Add a repository.
     */
    public function addRepository(\Composer\Repository\RepositoryInterface $repository): void
    {
        if ($repository instanceof self) {
            foreach ($repository->getRepositories() as $repo) {
                $this->addRepository($repo);
            }
        } else {
            $this->repositories[] = $repository;
        }
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer\Repository;

use Composer\Package\AliasPackage;
use Composer\Package\BasePackage;
use Composer\Package\CompleteAliasPackage;
use Composer\Package\CompletePackage;
use Composer\Package\PackageInterface;
use Composer\Package\CompletePackageInterface;
use Composer\Package\Version\VersionParser;
use Composer\Package\Version\StabilityFilter;
use Composer\Pcre\Preg;
use Composer\Semver\Constraint\ConstraintInterface;
use Composer\Semver\Constraint\Constraint;
/**
 * A repository implementation that simply stores packages in an array
 *
 * @author Nils Adermann <naderman@naderman.de>
 */
class ArrayRepository implements \Composer\Repository\RepositoryInterface
{
    /** @var ?array<BasePackage> */
    protected $packages = null;
    /**
     * @var ?array<BasePackage> indexed by package unique name and used to cache hasPackage calls
     */
    protected $packageMap = null;
    /**
     * @param array<PackageInterface> $packages
     */
    public function __construct(array $packages = [])
    {
        foreach ($packages as $package) {
            $this->addPackage($package);
        }
    }
    public function getRepoName()
    {
        return 'array repo (defining ' . $this->count() . ' package' . ($this->count() > 1 ? 's' : '') . ')';
    }
    /**
     * @inheritDoc
     */
    public function loadPackages(array $packageNameMap, array $acceptableStabilities, array $stabilityFlags, array $alreadyLoaded = [])
    {
        $packages = $this->getPackages();
        $result = [];
        $namesFound = [];
        foreach ($packages as $package) {
            if (array_key_exists($package->getName(), $packageNameMap)) {
                if ((!$packageNameMap[$package->getName()] || $packageNameMap[$package->getName()]->matches(new Constraint('==', $package->getVersion()))) && StabilityFilter::isPackageAcceptable($acceptableStabilities, $stabilityFlags, $package->getNames(), $package->getStability()) && !isset($alreadyLoaded[$package->getName()][$package->getVersion()])) {
                    // add selected packages which match stability requirements
                    $result[spl_object_hash($package)] = $package;
                    // add the aliased package for packages where the alias matches
                    if ($package instanceof AliasPackage && !isset($result[spl_object_hash($package->getAliasOf())])) {
                        $result[spl_object_hash($package->getAliasOf())] = $package->getAliasOf();
                    }
                }
                $namesFound[$package->getName()] = \true;
            }
        }
        // add aliases of packages that were selected, even if the aliases did not match
        foreach ($packages as $package) {
            if ($package instanceof AliasPackage) {
                if (isset($result[spl_object_hash($package->getAliasOf())])) {
                    $result[spl_object_hash($package)] = $package;
                }
            }
        }
        return ['namesFound' => array_keys($namesFound), 'packages' => $result];
    }
    /**
     * @inheritDoc
     */
    public function findPackage(string $name, $constraint)
    {
        $name = strtolower($name);
        if (!$constraint instanceof ConstraintInterface) {
            $versionParser = new VersionParser();
            $constraint = $versionParser->parseConstraints($constraint);
        }
        foreach ($this->getPackages() as $package) {
            if ($name === $package->getName()) {
                $pkgConstraint = new Constraint('==', $package->getVersion());
                if ($constraint->matches($pkgConstraint)) {
                    return $package;
                }
            }
        }
        return null;
    }
    /**
     * @inheritDoc
     */
    public function findPackages(string $name, $constraint = null)
    {
        // normalize name
        $name = strtolower($name);
        $packages = [];
        if (null !== $constraint && !$constraint instanceof ConstraintInterface) {
            $versionParser = new VersionParser();
            $constraint = $versionParser->parseConstraints($constraint);
        }
        foreach ($this->getPackages() as $package) {
            if ($name === $package->getName()) {
                if (null === $constraint || $constraint->matches(new Constraint('==', $package->getVersion()))) {
                    $packages[] = $package;
                }
            }
        }
        return $packages;
    }
    /**
     * @inheritDoc
     */
    public function search(string $query, int $mode = 0, ?string $type = null)
    {
        if ($mode === self::SEARCH_FULLTEXT) {
            $regex = '{(?:' . implode('|', Preg::split('{\s+}', preg_quote($query))) . ')}i';
        } else {
            // vendor/name searches expect the caller to have preg_quoted the query
            $regex = '{(?:' . implode('|', Preg::split('{\s+}', $query)) . ')}i';
        }
        $matches = [];
        foreach ($this->getPackages() as $package) {
            $name = $package->getName();
            if ($mode === self::SEARCH_VENDOR) {
                [$name] = explode('/', $name);
            }
            if (isset($matches[$name])) {
                continue;
            }
            if (null !== $type && $package->getType() !== $type) {
                continue;
            }
            if (Preg::isMatch($regex, $name) || $mode === self::SEARCH_FULLTEXT && $package instanceof CompletePackageInterface && Preg::isMatch($regex, implode(' ', (array) $package->getKeywords()) . ' ' . $package->getDescription())) {
                if ($mode === self::SEARCH_VENDOR) {
                    $matches[$name] = ['name' => $name, 'description' => null];
                } else {
                    $matches[$name] = ['name' => $package->getPrettyName(), 'description' => $package instanceof CompletePackageInterface ? $package->getDescription() : null];
                    if ($package instanceof CompletePackageInterface && $package->isAbandoned()) {
                        $matches[$name]['abandoned'] = $package->getReplacementPackage() ?: \true;
                    }
                }
            }
        }
        return array_values($matches);
    }
    /**
     * @inheritDoc
     */
    public function hasPackage(PackageInterface $package)
    {
        if ($this->packageMap === null) {
            $this->packageMap = [];
            foreach ($this->getPackages() as $repoPackage) {
                $this->packageMap[$repoPackage->getUniqueName()] = $repoPackage;
            }
        }
        return isset($this->packageMap[$package->getUniqueName()]);
    }
    /**
     * Adds a new package to the repository
     *
     * @return void
     */
    public function addPackage(PackageInterface $package)
    {
        if (!$package instanceof BasePackage) {
            throw new \InvalidArgumentException('Only subclasses of BasePackage are supported');
        }
        if (null === $this->packages) {
            $this->initialize();
        }
        $package->setRepository($this);
        $this->packages[] = $package;
        if ($package instanceof AliasPackage) {
            $aliasedPackage = $package->getAliasOf();
            if (null === $aliasedPackage->getRepository()) {
                $this->addPackage($aliasedPackage);
            }
        }
        // invalidate package map cache
        $this->packageMap = null;
    }
    /**
     * @inheritDoc
     */
    public function getProviders(string $packageName)
    {
        $result = [];
        foreach ($this->getPackages() as $candidate) {
            if (isset($result[$candidate->getName()])) {
                continue;
            }
            foreach ($candidate->getProvides() as $link) {
                if ($packageName === $link->getTarget()) {
                    $result[$candidate->getName()] = ['name' => $candidate->getName(), 'description' => $candidate instanceof CompletePackageInterface ? $candidate->getDescription() : null, 'type' => $candidate->getType()];
                    continue 2;
                }
            }
        }
        return $result;
    }
    /**
     * @return AliasPackage|CompleteAliasPackage
     */
    protected function createAliasPackage(BasePackage $package, string $alias, string $prettyAlias)
    {
        while ($package instanceof AliasPackage) {
            $package = $package->getAliasOf();
        }
        if ($package instanceof CompletePackage) {
            return new CompleteAliasPackage($package, $alias, $prettyAlias);
        }
        return new AliasPackage($package, $alias, $prettyAlias);
    }
    /**
     * Removes package from repository.
     *
     * @param PackageInterface $package package instance
     *
     * @return void
     */
    public function removePackage(PackageInterface $package)
    {
        $packageId = $package->getUniqueName();
        foreach ($this->getPackages() as $key => $repoPackage) {
            if ($packageId === $repoPackage->getUniqueName()) {
                array_splice($this->packages, $key, 1);
                // invalidate package map cache
                $this->packageMap = null;
                return;
            }
        }
    }
    /**
     * @inheritDoc
     */
    public function getPackages()
    {
        if (null === $this->packages) {
            $this->initialize();
        }
        if (null === $this->packages) {
            throw new \LogicException('initialize failed to initialize the packages array');
        }
        return $this->packages;
    }
    /**
     * Returns the number of packages in this repository
     *
     * @return 0|positive-int Number of packages
     */
    public function count(): int
    {
        if (null === $this->packages) {
            $this->initialize();
        }
        return count($this->packages);
    }
    /**
     * Initializes the packages array. Mostly meant as an extension point.
     *
     * @return void
     */
    protected function initialize()
    {
        $this->packages = [];
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer\Repository;

use Composer\Installer\InstallationManager;
/**
 * Writable array repository.
 *
 * @author Jordi Boggiano <j.boggiano@seld.be>
 */
class WritableArrayRepository extends \Composer\Repository\ArrayRepository implements \Composer\Repository\WritableRepositoryInterface
{
    use \Composer\Repository\CanonicalPackagesTrait;
    /**
     * @var string[]
     */
    protected $devPackageNames = [];
    /** @var bool|null */
    private $devMode = null;
    /**
     * @return bool|null true if dev requirements were installed, false if --no-dev was used, null if yet unknown
     */
    public function getDevMode()
    {
        return $this->devMode;
    }
    /**
     * @inheritDoc
     */
    public function setDevPackageNames(array $devPackageNames)
    {
        $this->devPackageNames = $devPackageNames;
    }
    /**
     * @inheritDoc
     */
    public function getDevPackageNames()
    {
        return $this->devPackageNames;
    }
    /**
     * @inheritDoc
     */
    public function write(bool $devMode, InstallationManager $installationManager)
    {
        $this->devMode = $devMode;
    }
    /**
     * @inheritDoc
     */
    public function reload()
    {
        $this->devMode = null;
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer\Repository;

use Composer\Downloader\TransportException;
use Composer\Pcre\Preg;
use Composer\Repository\Vcs\VcsDriverInterface;
use Composer\Package\Version\VersionParser;
use Composer\Package\Loader\ArrayLoader;
use Composer\Package\Loader\ValidatingArrayLoader;
use Composer\Package\Loader\InvalidPackageException;
use Composer\Package\Loader\LoaderInterface;
use Composer\EventDispatcher\EventDispatcher;
use Composer\Util\Platform;
use Composer\Util\ProcessExecutor;
use Composer\Util\HttpDownloader;
use Composer\Util\Url;
use Composer\Semver\Constraint\Constraint;
use Composer\IO\IOInterface;
use Composer\Config;
/**
 * @author Jordi Boggiano <j.boggiano@seld.be>
 */
class VcsRepository extends \Composer\Repository\ArrayRepository implements \Composer\Repository\ConfigurableRepositoryInterface
{
    /** @var string */
    protected $url;
    /** @var ?string */
    protected $packageName;
    /** @var bool */
    protected $isVerbose;
    /** @var bool */
    protected $isVeryVerbose;
    /** @var IOInterface */
    protected $io;
    /** @var Config */
    protected $config;
    /** @var VersionParser */
    protected $versionParser;
    /** @var string */
    protected $type;
    /** @var ?LoaderInterface */
    protected $loader;
    /** @var array<string, mixed> */
    protected $repoConfig;
    /** @var HttpDownloader */
    protected $httpDownloader;
    /** @var ProcessExecutor */
    protected $processExecutor;
    /** @var bool */
    protected $branchErrorOccurred = \false;
    /** @var array<string, class-string<VcsDriverInterface>> */
    private $drivers;
    /** @var ?VcsDriverInterface */
    private $driver;
    /** @var ?VersionCacheInterface */
    private $versionCache;
    /** @var list<string> */
    private $emptyReferences = [];
    /** @var array<'tags'|'branches', array<string, TransportException>> */
    private $versionTransportExceptions = [];
    /**
     * @param array{url: string, type?: string}&array<string, mixed> $repoConfig
     * @param array<string, class-string<VcsDriverInterface>>|null $drivers
     */
    public function __construct(array $repoConfig, IOInterface $io, Config $config, HttpDownloader $httpDownloader, ?EventDispatcher $dispatcher = null, ?ProcessExecutor $process = null, ?array $drivers = null, ?\Composer\Repository\VersionCacheInterface $versionCache = null)
    {
        parent::__construct();
        $this->drivers = $drivers ?: [
            'github' => 'Composer\Repository\Vcs\GitHubDriver',
            'gitlab' => 'Composer\Repository\Vcs\GitLabDriver',
            'bitbucket' => 'Composer\Repository\Vcs\GitBitbucketDriver',
            'git-bitbucket' => 'Composer\Repository\Vcs\GitBitbucketDriver',
            'forgejo' => 'Composer\Repository\Vcs\ForgejoDriver',
            'git' => 'Composer\Repository\Vcs\GitDriver',
            'hg' => 'Composer\Repository\Vcs\HgDriver',
            'perforce' => 'Composer\Repository\Vcs\PerforceDriver',
            'fossil' => 'Composer\Repository\Vcs\FossilDriver',
            // svn must be last because identifying a subversion server for sure is practically impossible
            'svn' => 'Composer\Repository\Vcs\SvnDriver',
        ];
        $this->url = $repoConfig['url'] = Platform::expandPath($repoConfig['url']);
        $this->io = $io;
        $this->type = $repoConfig['type'] ?? 'vcs';
        $this->isVerbose = $io->isVerbose();
        $this->isVeryVerbose = $io->isVeryVerbose();
        $this->config = $config;
        $this->repoConfig = $repoConfig;
        $this->versionCache = $versionCache;
        $this->httpDownloader = $httpDownloader;
        $this->processExecutor = $process ?? new ProcessExecutor($io);
    }
    public function getRepoName()
    {
        $driverClass = get_class($this->getDriver());
        $driverType = array_search($driverClass, $this->drivers);
        if (!$driverType) {
            $driverType = $driverClass;
        }
        return 'vcs repo (' . $driverType . ' ' . Url::sanitize($this->url) . ')';
    }
    public function getRepoConfig()
    {
        return $this->repoConfig;
    }
    public function setLoader(LoaderInterface $loader): void
    {
        $this->loader = $loader;
    }
    public function getDriver(): ?VcsDriverInterface
    {
        if ($this->driver) {
            return $this->driver;
        }
        if (isset($this->drivers[$this->type])) {
            $class = $this->drivers[$this->type];
            $this->driver = new $class($this->repoConfig, $this->io, $this->config, $this->httpDownloader, $this->processExecutor);
            $this->driver->initialize();
            return $this->driver;
        }
        foreach ($this->drivers as $driver) {
            if ($driver::supports($this->io, $this->config, $this->url)) {
                $this->driver = new $driver($this->repoConfig, $this->io, $this->config, $this->httpDownloader, $this->processExecutor);
                $this->driver->initialize();
                return $this->driver;
            }
        }
        foreach ($this->drivers as $driver) {
            if ($driver::supports($this->io, $this->config, $this->url, \true)) {
                $this->driver = new $driver($this->repoConfig, $this->io, $this->config, $this->httpDownloader, $this->processExecutor);
                $this->driver->initialize();
                return $this->driver;
            }
        }
        return null;
    }
    public function hadInvalidBranches(): bool
    {
        return $this->branchErrorOccurred;
    }
    /**
     * @return list<string>
     */
    public function getEmptyReferences(): array
    {
        return $this->emptyReferences;
    }
    /**
     * @return array<'tags'|'branches', array<string, TransportException>>
     */
    public function getVersionTransportExceptions(): array
    {
        return $this->versionTransportExceptions;
    }
    protected function initialize()
    {
        parent::initialize();
        $isVerbose = $this->isVerbose;
        $isVeryVerbose = $this->isVeryVerbose;
        $driver = $this->getDriver();
        if (!$driver) {
            throw new \InvalidArgumentException('No driver found to handle VCS repository ' . $this->url);
        }
        $this->versionParser = new VersionParser();
        if (!$this->loader) {
            $this->loader = new ArrayLoader($this->versionParser);
        }
        $hasRootIdentifierComposerJson = \false;
        try {
            $hasRootIdentifierComposerJson = $driver->hasComposerFile($driver->getRootIdentifier());
            if ($hasRootIdentifierComposerJson) {
                $data = $driver->getComposerInformation($driver->getRootIdentifier());
                $this->packageName = !empty($data['name']) ? $data['name'] : null;
            }
        } catch (\Exception $e) {
            if ($e instanceof TransportException && $this->shouldRethrowTransportException($e)) {
                throw $e;
            }
            if ($isVeryVerbose) {
                $this->io->writeError('<error>Skipped parsing ' . $driver->getRootIdentifier() . ', ' . $e->getMessage() . '</error>');
            }
        }
        foreach ($driver->getTags() as $tag => $identifier) {
            $tag = (string) $tag;
            $msg = 'Reading composer.json of <info>' . ($this->packageName ?: $this->url) . '</info> (<comment>' . $tag . '</comment>)';
            // strip the release- prefix from tags if present
            $tag = str_replace('release-', '', $tag);
            $cachedPackage = $this->getCachedPackageVersion($tag, $identifier, $isVerbose, $isVeryVerbose);
            if ($cachedPackage) {
                $this->addPackage($cachedPackage);
                continue;
            }
            if ($cachedPackage === \false) {
                $this->emptyReferences[] = $identifier;
                continue;
            }
            if (!$parsedTag = $this->validateTag($tag)) {
                if ($isVeryVerbose) {
                    $this->io->writeError('<warning>Skipped tag ' . $tag . ', invalid tag name</warning>');
                }
                continue;
            }
            if ($isVeryVerbose) {
                $this->io->writeError($msg);
            } elseif ($isVerbose) {
                $this->io->overwriteError($msg, \false);
            }
            try {
                $data = $driver->getComposerInformation($identifier);
                if (null === $data) {
                    if ($isVeryVerbose) {
                        $this->io->writeError('<warning>Skipped tag ' . $tag . ', no composer file</warning>');
                    }
                    $this->emptyReferences[] = $identifier;
                    continue;
                }
                // manually versioned package
                if (isset($data['version'])) {
                    $data['version_normalized'] = $this->versionParser->normalize($data['version']);
                } else {
                    // auto-versioned package, read value from tag
                    $data['version'] = $tag;
                    $data['version_normalized'] = $parsedTag;
                }
                // make sure tag packages have no -dev flag
                $data['version'] = Preg::replace('{[.-]?dev$}i', '', $data['version']);
                $data['version_normalized'] = Preg::replace('{(^dev-|[.-]?dev$)}i', '', $data['version_normalized']);
                // make sure tag do not contain the default-branch marker
                unset($data['default-branch']);
                // broken package, version doesn't match tag
                if ($data['version_normalized'] !== $parsedTag) {
                    if ($isVeryVerbose) {
                        if (Preg::isMatch('{(^dev-|[.-]?dev$)}i', $parsedTag)) {
                            $this->io->writeError('<warning>Skipped tag ' . $tag . ', invalid tag name, tags can not use dev prefixes or suffixes</warning>');
                        } else {
                            $this->io->writeError('<warning>Skipped tag ' . $tag . ', tag (' . $parsedTag . ') does not match version (' . $data['version_normalized'] . ') in composer.json</warning>');
                        }
                    }
                    continue;
                }
                $tagPackageName = $this->packageName ?: $data['name'] ?? '';
                if ($existingPackage = $this->findPackage($tagPackageName, $data['version_normalized'])) {
                    if ($isVeryVerbose) {
                        $this->io->writeError('<warning>Skipped tag ' . $tag . ', it conflicts with an another tag (' . $existingPackage->getPrettyVersion() . ') as both resolve to ' . $data['version_normalized'] . ' internally</warning>');
                    }
                    continue;
                }
                if ($isVeryVerbose) {
                    $this->io->writeError('Importing tag ' . $tag . ' (' . $data['version_normalized'] . ')');
                }
                $this->addPackage($this->loader->load($this->preProcess($driver, $data, $identifier)));
            } catch (\Exception $e) {
                if ($e instanceof TransportException) {
                    $this->versionTransportExceptions['tags'][$tag] = $e;
                    if ($e->getCode() === 404) {
                        $this->emptyReferences[] = $identifier;
                    }
                    if ($this->shouldRethrowTransportException($e)) {
                        throw $e;
                    }
                }
                if ($isVeryVerbose) {
                    $this->io->writeError('<warning>Skipped tag ' . $tag . ', ' . ($e instanceof TransportException ? 'no composer file was found (' . $e->getCode() . ' HTTP status code)' : $e->getMessage()) . '</warning>');
                }
                continue;
            }
        }
        if (!$isVeryVerbose) {
            $this->io->overwriteError('', \false);
        }
        $branches = $driver->getBranches();
        // make sure the root identifier branch gets loaded first
        if ($hasRootIdentifierComposerJson && isset($branches[$driver->getRootIdentifier()])) {
            $branches = [$driver->getRootIdentifier() => $branches[$driver->getRootIdentifier()]] + $branches;
        }
        foreach ($branches as $branch => $identifier) {
            $branch = (string) $branch;
            $msg = 'Reading composer.json of <info>' . ($this->packageName ?: $this->url) . '</info> (<comment>' . $branch . '</comment>)';
            if ($isVeryVerbose) {
                $this->io->writeError($msg);
            } elseif ($isVerbose) {
                $this->io->overwriteError($msg, \false);
            }
            if (!$parsedBranch = $this->validateBranch($branch)) {
                if ($isVeryVerbose) {
                    $this->io->writeError('<warning>Skipped branch ' . $branch . ', invalid name</warning>');
                }
                continue;
            }
            // make sure branch packages have a dev flag
            if (strpos($parsedBranch, 'dev-') === 0 || VersionParser::DEFAULT_BRANCH_ALIAS === $parsedBranch) {
                $version = 'dev-' . str_replace('#', '+', $branch);
                $parsedBranch = str_replace('#', '+', $parsedBranch);
            } else {
                $prefix = strpos($branch, 'v') === 0 ? 'v' : '';
                $version = $prefix . Preg::replace('{(\.9{7})+}', '.x', $parsedBranch);
            }
            $cachedPackage = $this->getCachedPackageVersion($version, $identifier, $isVerbose, $isVeryVerbose, $driver->getRootIdentifier() === $branch);
            if ($cachedPackage) {
                $this->addPackage($cachedPackage);
                continue;
            }
            if ($cachedPackage === \false) {
                $this->emptyReferences[] = $identifier;
                continue;
            }
            try {
                $data = $driver->getComposerInformation($identifier);
                if (null === $data) {
                    if ($isVeryVerbose) {
                        $this->io->writeError('<warning>Skipped branch ' . $branch . ', no composer file</warning>');
                    }
                    $this->emptyReferences[] = $identifier;
                    continue;
                }
                // branches are always auto-versioned, read value from branch name
                $data['version'] = $version;
                $data['version_normalized'] = $parsedBranch;
                unset($data['default-branch']);
                if ($driver->getRootIdentifier() === $branch) {
                    $data['default-branch'] = \true;
                }
                if ($isVeryVerbose) {
                    $this->io->writeError('Importing branch ' . $branch . ' (' . $data['version'] . ')');
                }
                $packageData = $this->preProcess($driver, $data, $identifier);
                $package = $this->loader->load($packageData);
                if ($this->loader instanceof ValidatingArrayLoader && \count($this->loader->getWarnings()) > 0) {
                    throw new InvalidPackageException($this->loader->getErrors(), $this->loader->getWarnings(), $packageData);
                }
                $this->addPackage($package);
            } catch (TransportException $e) {
                $this->versionTransportExceptions['branches'][$branch] = $e;
                if ($e->getCode() === 404) {
                    $this->emptyReferences[] = $identifier;
                }
                if ($this->shouldRethrowTransportException($e)) {
                    throw $e;
                }
                if ($isVeryVerbose) {
                    $this->io->writeError('<warning>Skipped branch ' . $branch . ', no composer file was found (' . $e->getCode() . ' HTTP status code)</warning>');
                }
                continue;
            } catch (\Exception $e) {
                if (!$isVeryVerbose) {
                    $this->io->writeError('');
                }
                $this->branchErrorOccurred = \true;
                $this->io->writeError('<error>Skipped branch ' . $branch . ', ' . $e->getMessage() . '</error>');
                $this->io->writeError('');
                continue;
            }
        }
        $driver->cleanup();
        if (!$isVeryVerbose) {
            $this->io->overwriteError('', \false);
        }
        if (!$this->getPackages()) {
            throw new \Composer\Repository\InvalidRepositoryException('No valid composer.json was found in any branch or tag of ' . $this->url . ', could not load a package from it.');
        }
    }
    /**
     * @param array{name?: string, dist?: array{type: string, url: string, reference: string, shasum: string}, source?: array{type: string, url: string, reference: string}} $data
     *
     * @return array{name: string|null, dist: array{type: string, url: string, reference: string, shasum: string}|null, source: array{type: string, url: string, reference: string}}
     */
    protected function preProcess(VcsDriverInterface $driver, array $data, string $identifier): array
    {
        // keep the name of the main identifier for all packages
        // this ensures that a package can be renamed in one place and that all old tags
        // will still be installable using that new name without requiring re-tagging
        $dataPackageName = $data['name'] ?? null;
        $data['name'] = $this->packageName ?: $dataPackageName;
        if (!isset($data['dist'])) {
            $data['dist'] = $driver->getDist($identifier);
        }
        if (!isset($data['source'])) {
            $data['source'] = $driver->getSource($identifier);
        }
        // if custom dist info is provided but does not provide a reference, copy the source reference to it
        if (is_array($data['dist']) && !isset($data['dist']['reference']) && isset($data['source']['reference'])) {
            $data['dist']['reference'] = $data['source']['reference'];
        }
        return $data;
    }
    /**
     * @return string|false
     */
    private function validateBranch(string $branch)
    {
        try {
            $normalizedBranch = $this->versionParser->normalizeBranch($branch);
            // validate that the branch name has no weird characters conflicting with constraints
            $this->versionParser->parseConstraints($normalizedBranch);
            return $normalizedBranch;
        } catch (\Exception $e) {
        }
        return \false;
    }
    /**
     * @return string|false
     */
    private function validateTag(string $version)
    {
        try {
            return $this->versionParser->normalize($version);
        } catch (\Exception $e) {
        }
        return \false;
    }
    /**
     * @return \Composer\Package\CompletePackage|\Composer\Package\CompleteAliasPackage|null|false null if no cache present, false if the absence of a version was cached
     */
    private function getCachedPackageVersion(string $version, string $identifier, bool $isVerbose, bool $isVeryVerbose, bool $isDefaultBranch = \false)
    {
        if (!$this->versionCache) {
            return null;
        }
        $cachedPackage = $this->versionCache->getVersionPackage($version, $identifier);
        if ($cachedPackage === \false) {
            if ($isVeryVerbose) {
                $this->io->writeError('<warning>Skipped ' . $version . ', no composer file (cached from ref ' . $identifier . ')</warning>');
            }
            return \false;
        }
        if ($cachedPackage) {
            $msg = 'Found cached composer.json of <info>' . ($this->packageName ?: $this->url) . '</info> (<comment>' . $version . '</comment>)';
            if ($isVeryVerbose) {
                $this->io->writeError($msg);
            } elseif ($isVerbose) {
                $this->io->overwriteError($msg, \false);
            }
            unset($cachedPackage['default-branch']);
            if ($isDefaultBranch) {
                $cachedPackage['default-branch'] = \true;
            }
            if ($existingPackage = $this->findPackage($cachedPackage['name'], new Constraint('=', $cachedPackage['version_normalized']))) {
                if ($isVeryVerbose) {
                    $this->io->writeError('<warning>Skipped cached version ' . $version . ', it conflicts with an another tag (' . $existingPackage->getPrettyVersion() . ') as both resolve to ' . $cachedPackage['version_normalized'] . ' internally</warning>');
                }
                $cachedPackage = null;
            }
        }
        if ($cachedPackage) {
            return $this->loader->load($cachedPackage);
        }
        return null;
    }
    private function shouldRethrowTransportException(TransportException $e): bool
    {
        return in_array($e->getCode(), [401, 403, 429], \true) || $e->getCode() >= 500;
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer\Repository;

use Composer\Advisory\PartialSecurityAdvisory;
use Composer\Advisory\SecurityAdvisory;
use Composer\Package\BasePackage;
use Composer\Package\Loader\ArrayLoader;
use Composer\Package\PackageInterface;
use Composer\Package\AliasPackage;
use Composer\Package\CompletePackage;
use Composer\Package\CompleteAliasPackage;
use Composer\Package\Version\VersionParser;
use Composer\Package\Version\StabilityFilter;
use Composer\Json\JsonFile;
use Composer\Cache;
use Composer\Config;
use Composer\IO\IOInterface;
use Composer\Pcre\Preg;
use Composer\Plugin\PostFileDownloadEvent;
use Composer\Semver\CompilingMatcher;
use Composer\Util\HttpDownloader;
use Composer\Util\Loop;
use Composer\Plugin\PluginEvents;
use Composer\Plugin\PreFileDownloadEvent;
use Composer\EventDispatcher\EventDispatcher;
use Composer\Downloader\TransportException;
use Composer\Semver\Constraint\ConstraintInterface;
use Composer\Semver\Constraint\Constraint;
use Composer\Semver\Constraint\MatchAllConstraint;
use Composer\Util\Http\Response;
use Composer\MetadataMinifier\MetadataMinifier;
use Composer\Util\Url;
use React\Promise\PromiseInterface;
/**
 * @author Jordi Boggiano <j.boggiano@seld.be>
 */
class ComposerRepository extends \Composer\Repository\ArrayRepository implements \Composer\Repository\ConfigurableRepositoryInterface, \Composer\Repository\AdvisoryProviderInterface
{
    /**
     * @var mixed[]
     * @phpstan-var array{url: string, options?: mixed[], type?: 'composer', allow_ssl_downgrade?: bool}
     */
    private $repoConfig;
    /** @var mixed[] */
    private $options;
    /** @var non-empty-string */
    private $url;
    /** @var non-empty-string */
    private $baseUrl;
    /** @var IOInterface */
    private $io;
    /** @var HttpDownloader */
    private $httpDownloader;
    /** @var Loop */
    private $loop;
    /** @var Cache */
    protected $cache;
    /** @var ?non-empty-string */
    protected $notifyUrl = null;
    /** @var ?non-empty-string */
    protected $searchUrl = null;
    /** @var ?non-empty-string a URL containing %package% which can be queried to get providers of a given name */
    protected $providersApiUrl = null;
    /** @var bool */
    protected $hasProviders = \false;
    /** @var ?non-empty-string */
    protected $providersUrl = null;
    /** @var ?non-empty-string */
    protected $listUrl = null;
    /** @var bool Indicates whether a comprehensive list of packages this repository might provide is expressed in the repository root. **/
    protected $hasAvailablePackageList = \false;
    /** @var ?array<string> */
    protected $availablePackages = null;
    /** @var ?array<non-empty-string> */
    protected $availablePackagePatterns = null;
    /** @var ?non-empty-string */
    protected $lazyProvidersUrl = null;
    /** @var ?array<string, array{sha256: string}> */
    protected $providerListing;
    /** @var ArrayLoader */
    protected $loader;
    /** @var bool */
    private $allowSslDowngrade = \false;
    /** @var ?EventDispatcher */
    private $eventDispatcher;
    /** @var ?array<string, list<array{url: non-empty-string, preferred: bool}>> */
    private $sourceMirrors;
    /** @var ?list<array{url: non-empty-string, preferred: bool}> */
    private $distMirrors;
    /** @var bool */
    private $degradedMode = \false;
    /** @var mixed[]|true */
    private $rootData;
    /** @var bool */
    private $hasPartialPackages = \false;
    /** @var ?array<string, mixed[]> */
    private $partialPackagesByName = null;
    /** @var bool */
    private $displayedWarningAboutNonMatchingPackageIndex = \false;
    /** @var array{metadata: bool, api-url: string|null}|null */
    private $securityAdvisoryConfig = null;
    /**
     * @var array list of package names which are fresh and can be loaded from the cache directly in case loadPackage is called several times
     *            useful for v2 metadata repositories with lazy providers
     * @phpstan-var array<string, true>
     */
    private $freshMetadataUrls = [];
    /**
     * @var array list of package names which returned a 404 and should not be re-fetched in case loadPackage is called several times
     *            useful for v2 metadata repositories with lazy providers
     * @phpstan-var array<string, true>
     */
    private $packagesNotFoundCache = [];
    /**
     * @var VersionParser
     */
    private $versionParser;
    /**
     * @param array<string, mixed> $repoConfig
     * @phpstan-param array{url: non-empty-string, options?: mixed[], type?: 'composer', allow_ssl_downgrade?: bool} $repoConfig
     */
    public function __construct(array $repoConfig, IOInterface $io, Config $config, HttpDownloader $httpDownloader, ?EventDispatcher $eventDispatcher = null)
    {
        parent::__construct();
        if (!Preg::isMatch('{^[\w.]+\??://}', $repoConfig['url'])) {
            if (($localFilePath = realpath($repoConfig['url'])) !== \false) {
                // it is a local path, add file scheme
                $repoConfig['url'] = 'file://' . $localFilePath;
            } else {
                // otherwise, assume http as the default protocol
                $repoConfig['url'] = 'http://' . $repoConfig['url'];
            }
        }
        $repoConfig['url'] = rtrim($repoConfig['url'], '/');
        if ($repoConfig['url'] === '') {
            throw new \InvalidArgumentException('The repository url must not be an empty string');
        }
        if (str_starts_with($repoConfig['url'], 'https?')) {
            $repoConfig['url'] = (extension_loaded('openssl') ? 'https' : 'http') . substr($repoConfig['url'], 6);
        }
        $urlBits = parse_url(strtr($repoConfig['url'], '\\', '/'));
        if ($urlBits === \false || empty($urlBits['scheme'])) {
            throw new \UnexpectedValueException('Invalid url given for Composer repository: ' . $repoConfig['url']);
        }
        if (!isset($repoConfig['options'])) {
            $repoConfig['options'] = [];
        }
        if (isset($repoConfig['allow_ssl_downgrade']) && \true === $repoConfig['allow_ssl_downgrade']) {
            $this->allowSslDowngrade = \true;
        }
        $this->options = $repoConfig['options'];
        $this->url = $repoConfig['url'];
        // force url for packagist.org to repo.packagist.org
        if (Preg::isMatch('{^(?P<proto>https?)://packagist\.org/?$}i', $this->url, $match)) {
            $this->url = $match['proto'] . '://repo.packagist.org';
        }
        $baseUrl = rtrim(Preg::replace('{(?:/[^/\\\\]+\.json)?(?:[?#].*)?$}', '', $this->url), '/');
        assert($baseUrl !== '');
        $this->baseUrl = $baseUrl;
        $this->io = $io;
        $this->cache = new Cache($io, $config->get('cache-repo-dir') . '/' . Preg::replace('{[^a-z0-9.]}i', '-', Url::sanitize($this->url)), 'a-z0-9.$~_');
        $this->cache->setReadOnly($config->get('cache-read-only'));
        $this->versionParser = new VersionParser();
        $this->loader = new ArrayLoader($this->versionParser);
        $this->httpDownloader = $httpDownloader;
        $this->eventDispatcher = $eventDispatcher;
        $this->repoConfig = $repoConfig;
        $this->loop = new Loop($this->httpDownloader);
    }
    public function getRepoName()
    {
        return 'composer repo (' . Url::sanitize($this->url) . ')';
    }
    public function getRepoConfig()
    {
        return $this->repoConfig;
    }
    /**
     * @inheritDoc
     */
    public function findPackage(string $name, $constraint)
    {
        // this call initializes loadRootServerFile which is needed for the rest below to work
        $hasProviders = $this->hasProviders();
        $name = strtolower($name);
        if (!$constraint instanceof ConstraintInterface) {
            $constraint = $this->versionParser->parseConstraints($constraint);
        }
        if ($this->lazyProvidersUrl) {
            if ($this->hasPartialPackages() && isset($this->partialPackagesByName[$name])) {
                return $this->filterPackages($this->whatProvides($name), $constraint, \true);
            }
            if ($this->hasAvailablePackageList && !$this->lazyProvidersRepoContains($name)) {
                return null;
            }
            $packages = $this->loadAsyncPackages([$name => $constraint]);
            if (count($packages['packages']) > 0) {
                return reset($packages['packages']);
            }
            return null;
        }
        if ($hasProviders) {
            foreach ($this->getProviderNames() as $providerName) {
                if ($name === $providerName) {
                    return $this->filterPackages($this->whatProvides($providerName), $constraint, \true);
                }
            }
            return null;
        }
        return parent::findPackage($name, $constraint);
    }
    /**
     * @inheritDoc
     */
    public function findPackages(string $name, $constraint = null)
    {
        // this call initializes loadRootServerFile which is needed for the rest below to work
        $hasProviders = $this->hasProviders();
        $name = strtolower($name);
        if (null !== $constraint && !$constraint instanceof ConstraintInterface) {
            $constraint = $this->versionParser->parseConstraints($constraint);
        }
        if ($this->lazyProvidersUrl) {
            if ($this->hasPartialPackages() && isset($this->partialPackagesByName[$name])) {
                return $this->filterPackages($this->whatProvides($name), $constraint);
            }
            if ($this->hasAvailablePackageList && !$this->lazyProvidersRepoContains($name)) {
                return [];
            }
            $result = $this->loadAsyncPackages([$name => $constraint]);
            return $result['packages'];
        }
        if ($hasProviders) {
            foreach ($this->getProviderNames() as $providerName) {
                if ($name === $providerName) {
                    return $this->filterPackages($this->whatProvides($providerName), $constraint);
                }
            }
            return [];
        }
        return parent::findPackages($name, $constraint);
    }
    /**
     * @param array<BasePackage> $packages
     *
     * @return BasePackage|array<BasePackage>|null
     */
    private function filterPackages(array $packages, ?ConstraintInterface $constraint = null, bool $returnFirstMatch = \false)
    {
        if (null === $constraint) {
            if ($returnFirstMatch) {
                return reset($packages);
            }
            return $packages;
        }
        $filteredPackages = [];
        foreach ($packages as $package) {
            $pkgConstraint = new Constraint('==', $package->getVersion());
            if ($constraint->matches($pkgConstraint)) {
                if ($returnFirstMatch) {
                    return $package;
                }
                $filteredPackages[] = $package;
            }
        }
        if ($returnFirstMatch) {
            return null;
        }
        return $filteredPackages;
    }
    public function getPackages()
    {
        $hasProviders = $this->hasProviders();
        if ($this->lazyProvidersUrl) {
            if (is_array($this->availablePackages) && !$this->availablePackagePatterns) {
                $packageMap = [];
                foreach ($this->availablePackages as $name) {
                    $packageMap[$name] = new MatchAllConstraint();
                }
                $result = $this->loadAsyncPackages($packageMap);
                return array_values($result['packages']);
            }
            if ($this->hasPartialPackages()) {
                if (!is_array($this->partialPackagesByName)) {
                    throw new \LogicException('hasPartialPackages failed to initialize $this->partialPackagesByName');
                }
                return $this->createPackages($this->partialPackagesByName, 'packages.json inline packages');
            }
            throw new \LogicException('Composer repositories that have lazy providers and no available-packages list can not load the complete list of packages, use getPackageNames instead.');
        }
        if ($hasProviders) {
            throw new \LogicException('Composer repositories that have providers can not load the complete list of packages, use getPackageNames instead.');
        }
        return parent::getPackages();
    }
    /**
     * @param string|null $packageFilter Package pattern filter which can include "*" as a wildcard
     *
     * @return string[]
     */
    public function getPackageNames(?string $packageFilter = null)
    {
        $hasProviders = $this->hasProviders();
        $filterResults = static function (array $results): array {
            return $results;
        };
        if (null !== $packageFilter && '' !== $packageFilter) {
            $packageFilterRegex = BasePackage::packageNameToRegexp($packageFilter);
            $filterResults = static function (array $results) use ($packageFilterRegex): array {
                /** @var list<string> $results */
                return Preg::grep($packageFilterRegex, $results);
            };
        }
        if ($this->lazyProvidersUrl) {
            if (is_array($this->availablePackages)) {
                return $filterResults(array_keys($this->availablePackages));
            }
            if ($this->listUrl) {
                // no need to call $filterResults here as the $packageFilter is applied in the function itself
                return $this->loadPackageList($packageFilter);
            }
            if ($this->hasPartialPackages() && $this->partialPackagesByName !== null) {
                return $filterResults(array_keys($this->partialPackagesByName));
            }
            return [];
        }
        if ($hasProviders) {
            return $filterResults($this->getProviderNames());
        }
        $names = [];
        foreach ($this->getPackages() as $package) {
            $names[] = $package->getPrettyName();
        }
        return $filterResults($names);
    }
    /**
     * @return list<string>
     */
    private function getVendorNames(): array
    {
        $cacheKey = 'vendor-list.txt';
        $cacheAge = $this->cache->getAge($cacheKey);
        if (\false !== $cacheAge && $cacheAge < 600 && ($cachedData = $this->cache->read($cacheKey)) !== \false) {
            $cachedData = explode("\n", $cachedData);
            return $cachedData;
        }
        $names = $this->getPackageNames();
        $uniques = [];
        foreach ($names as $name) {
            $uniques[explode('/', $name, 2)[0]] = \true;
        }
        $vendors = array_keys($uniques);
        if (!$this->cache->isReadOnly()) {
            $this->cache->write($cacheKey, implode("\n", $vendors));
        }
        return $vendors;
    }
    /**
     * @return list<string>
     */
    private function loadPackageList(?string $packageFilter = null): array
    {
        if (null === $this->listUrl) {
            throw new \LogicException('Make sure to call loadRootServerFile before loadPackageList');
        }
        $url = $this->listUrl;
        if (is_string($packageFilter) && $packageFilter !== '') {
            $url .= '?filter=' . urlencode($packageFilter);
            $result = $this->httpDownloader->get($url, $this->options)->decodeJson();
            return $result['packageNames'];
        }
        $cacheKey = 'package-list.txt';
        $cacheAge = $this->cache->getAge($cacheKey);
        if (\false !== $cacheAge && $cacheAge < 600 && ($cachedData = $this->cache->read($cacheKey)) !== \false) {
            $cachedData = explode("\n", $cachedData);
            return $cachedData;
        }
        $result = $this->httpDownloader->get($url, $this->options)->decodeJson();
        if (!$this->cache->isReadOnly()) {
            $this->cache->write($cacheKey, implode("\n", $result['packageNames']));
        }
        return $result['packageNames'];
    }
    public function loadPackages(array $packageNameMap, array $acceptableStabilities, array $stabilityFlags, array $alreadyLoaded = [])
    {
        // this call initializes loadRootServerFile which is needed for the rest below to work
        $hasProviders = $this->hasProviders();
        if (!$hasProviders && !$this->hasPartialPackages() && null === $this->lazyProvidersUrl) {
            return parent::loadPackages($packageNameMap, $acceptableStabilities, $stabilityFlags, $alreadyLoaded);
        }
        $packages = [];
        $namesFound = [];
        if ($hasProviders || $this->hasPartialPackages()) {
            foreach ($packageNameMap as $name => $constraint) {
                $matches = [];
                // if a repo has no providers but only partial packages and the partial packages are missing
                // then we don't want to call whatProvides as it would try to load from the providers and fail
                if (!$hasProviders && !isset($this->partialPackagesByName[$name])) {
                    continue;
                }
                $candidates = $this->whatProvides($name, $acceptableStabilities, $stabilityFlags, $alreadyLoaded);
                foreach ($candidates as $candidate) {
                    if ($candidate->getName() !== $name) {
                        throw new \LogicException('whatProvides should never return a package with a different name than the requested one');
                    }
                    $namesFound[$name] = \true;
                    if (!$constraint || $constraint->matches(new Constraint('==', $candidate->getVersion()))) {
                        $matches[spl_object_hash($candidate)] = $candidate;
                        if ($candidate instanceof AliasPackage && !isset($matches[spl_object_hash($candidate->getAliasOf())])) {
                            $matches[spl_object_hash($candidate->getAliasOf())] = $candidate->getAliasOf();
                        }
                    }
                }
                // add aliases of matched packages even if they did not match the constraint
                foreach ($candidates as $candidate) {
                    if ($candidate instanceof AliasPackage) {
                        if (isset($matches[spl_object_hash($candidate->getAliasOf())])) {
                            $matches[spl_object_hash($candidate)] = $candidate;
                        }
                    }
                }
                $packages = array_merge($packages, $matches);
                unset($packageNameMap[$name]);
            }
        }
        if ($this->lazyProvidersUrl && count($packageNameMap)) {
            if ($this->hasAvailablePackageList) {
                foreach ($packageNameMap as $name => $constraint) {
                    if (!$this->lazyProvidersRepoContains(strtolower($name))) {
                        unset($packageNameMap[$name]);
                    }
                }
            }
            $result = $this->loadAsyncPackages($packageNameMap, $acceptableStabilities, $stabilityFlags, $alreadyLoaded);
            $packages = array_merge($packages, $result['packages']);
            $namesFound = array_merge($namesFound, $result['namesFound']);
        }
        return ['namesFound' => array_keys($namesFound), 'packages' => $packages];
    }
    /**
     * @inheritDoc
     */
    public function search(string $query, int $mode = 0, ?string $type = null)
    {
        $this->loadRootServerFile(600);
        if ($this->searchUrl && $mode === self::SEARCH_FULLTEXT) {
            $url = str_replace(['%query%', '%type%'], [urlencode($query), $type], $this->searchUrl);
            $search = $this->httpDownloader->get($url, $this->options)->decodeJson();
            if (empty($search['results'])) {
                return [];
            }
            $results = [];
            foreach ($search['results'] as $result) {
                // do not show virtual packages in results as they are not directly useful from a composer perspective
                if (!empty($result['virtual'])) {
                    continue;
                }
                $results[] = $result;
            }
            return $results;
        }
        if ($mode === self::SEARCH_VENDOR) {
            $results = [];
            $regex = '{(?:' . implode('|', Preg::split('{\s+}', $query)) . ')}i';
            $vendorNames = $this->getVendorNames();
            foreach (Preg::grep($regex, $vendorNames) as $name) {
                $results[] = ['name' => $name, 'description' => ''];
            }
            return $results;
        }
        if ($this->hasProviders() || $this->lazyProvidersUrl) {
            // optimize search for "^foo/bar" where at least "^foo/" is present by loading this directly from the listUrl if present
            if (Preg::isMatchStrictGroups('{^\^(?P<query>(?P<vendor>[a-z0-9_.-]+)/[a-z0-9_.-]*)\*?$}i', $query, $match) && $this->listUrl !== null) {
                $url = $this->listUrl . '?vendor=' . urlencode($match['vendor']) . '&filter=' . urlencode($match['query'] . '*');
                $result = $this->httpDownloader->get($url, $this->options)->decodeJson();
                $results = [];
                foreach ($result['packageNames'] as $name) {
                    $results[] = ['name' => $name, 'description' => ''];
                }
                return $results;
            }
            $results = [];
            $regex = '{(?:' . implode('|', Preg::split('{\s+}', $query)) . ')}i';
            $packageNames = $this->getPackageNames();
            foreach (Preg::grep($regex, $packageNames) as $name) {
                $results[] = ['name' => $name, 'description' => ''];
            }
            return $results;
        }
        return parent::search($query, $mode);
    }
    public function hasSecurityAdvisories(): bool
    {
        $this->loadRootServerFile(600);
        return $this->securityAdvisoryConfig !== null && ($this->securityAdvisoryConfig['metadata'] || $this->securityAdvisoryConfig['api-url'] !== null);
    }
    /**
     * @inheritDoc
     */
    public function getSecurityAdvisories(array $packageConstraintMap, bool $allowPartialAdvisories = \false): array
    {
        $this->loadRootServerFile(600);
        if (null === $this->securityAdvisoryConfig) {
            return ['namesFound' => [], 'advisories' => []];
        }
        $advisories = [];
        $namesFound = [];
        $apiUrl = $this->securityAdvisoryConfig['api-url'];
        // respect available-package-patterns / available-packages directives from the repo
        if ($this->hasAvailablePackageList) {
            foreach ($packageConstraintMap as $name => $constraint) {
                if (!$this->lazyProvidersRepoContains(strtolower($name))) {
                    unset($packageConstraintMap[$name]);
                }
            }
        }
        $parser = new VersionParser();
        /**
         * @param array<mixed> $data
         * @param string $name
         * @return ($allowPartialAdvisories is false ? SecurityAdvisory|null : PartialSecurityAdvisory|SecurityAdvisory|null)
         */
        $create = function (array $data, string $name) use ($parser, $allowPartialAdvisories, &$packageConstraintMap): ?PartialSecurityAdvisory {
            $advisory = PartialSecurityAdvisory::create($name, $data, $parser);
            if (!$allowPartialAdvisories && !$advisory instanceof SecurityAdvisory) {
                throw new \RuntimeException('Advisory for ' . $name . ' could not be loaded as a full advisory from ' . $this->getRepoName() . \PHP_EOL . var_export($data, \true));
            }
            if (!$advisory->affectedVersions->matches($packageConstraintMap[$name])) {
                return null;
            }
            return $advisory;
        };
        if ($this->securityAdvisoryConfig['metadata'] && ($allowPartialAdvisories || $apiUrl === null)) {
            $promises = [];
            foreach ($packageConstraintMap as $name => $constraint) {
                $name = strtolower($name);
                // skip platform packages, root package and composer-plugin-api
                if (\Composer\Repository\PlatformRepository::isPlatformPackage($name) || '__root__' === $name) {
                    continue;
                }
                $promises[] = $this->startCachedAsyncDownload($name, $name)->then(static function (array $spec) use (&$advisories, &$namesFound, &$packageConstraintMap, $name, $create): void {
                    [$response] = $spec;
                    if (!isset($response['security-advisories']) || !is_array($response['security-advisories'])) {
                        return;
                    }
                    $namesFound[$name] = \true;
                    if (count($response['security-advisories']) > 0) {
                        $advisories[$name] = array_values(array_filter(array_map(static function ($data) use ($name, $create) {
                            return $create($data, $name);
                        }, $response['security-advisories'])));
                    }
                    unset($packageConstraintMap[$name]);
                });
            }
            $this->loop->wait($promises);
        }
        if ($apiUrl !== null && count($packageConstraintMap) > 0) {
            $options = $this->options;
            $options['http']['method'] = 'POST';
            if (isset($options['http']['header'])) {
                $options['http']['header'] = (array) $options['http']['header'];
            }
            $options['http']['header'][] = 'Content-type: application/x-www-form-urlencoded';
            $options['http']['timeout'] = 10;
            $options['http']['content'] = http_build_query(['packages' => array_keys($packageConstraintMap)]);
            $response = $this->httpDownloader->get($apiUrl, $options);
            $warned = \false;
            /** @var string $name */
            foreach ($response->decodeJson()['advisories'] as $name => $list) {
                if (!isset($packageConstraintMap[$name])) {
                    if (!$warned) {
                        $this->io->writeError('<warning>' . $this->getRepoName() . ' returned names which were not requested in response to the security-advisories API. ' . $name . ' was not requested but is present in the response. Requested names were: ' . implode(', ', array_keys($packageConstraintMap)) . '</warning>');
                        $warned = \true;
                    }
                    continue;
                }
                if (count($list) > 0) {
                    $advisories[$name] = array_values(array_filter(array_map(static function ($data) use ($name, $create) {
                        return $create($data, $name);
                    }, $list)));
                }
                $namesFound[$name] = \true;
            }
        }
        return ['namesFound' => array_keys($namesFound), 'advisories' => array_filter($advisories, static function ($adv): bool {
            return \count($adv) > 0;
        })];
    }
    public function getProviders(string $packageName)
    {
        $this->loadRootServerFile();
        $result = [];
        if ($this->providersApiUrl) {
            try {
                $apiResult = $this->httpDownloader->get(str_replace('%package%', $packageName, $this->providersApiUrl), $this->options)->decodeJson();
            } catch (TransportException $e) {
                if ($e->getStatusCode() === 404) {
                    return $result;
                }
                throw $e;
            }
            foreach ($apiResult['providers'] as $provider) {
                $result[$provider['name']] = $provider;
            }
            return $result;
        }
        if ($this->hasPartialPackages()) {
            if (!is_array($this->partialPackagesByName)) {
                throw new \LogicException('hasPartialPackages failed to initialize $this->partialPackagesByName');
            }
            foreach ($this->partialPackagesByName as $versions) {
                foreach ($versions as $candidate) {
                    if (isset($result[$candidate['name']]) || !isset($candidate['provide'][$packageName])) {
                        continue;
                    }
                    $result[$candidate['name']] = ['name' => $candidate['name'], 'description' => $candidate['description'] ?? '', 'type' => $candidate['type'] ?? ''];
                }
            }
        }
        if ($this->packages) {
            $result = array_merge($result, parent::getProviders($packageName));
        }
        return $result;
    }
    /**
     * @return string[]
     */
    private function getProviderNames(): array
    {
        $this->loadRootServerFile();
        if (null === $this->providerListing) {
            $data = $this->loadRootServerFile();
            if (is_array($data)) {
                $this->loadProviderListings($data);
            }
        }
        if ($this->lazyProvidersUrl) {
            // Can not determine list of provided packages for lazy repositories
            return [];
        }
        if (null !== $this->providersUrl && null !== $this->providerListing) {
            return array_keys($this->providerListing);
        }
        return [];
    }
    protected function configurePackageTransportOptions(PackageInterface $package): void
    {
        foreach ($package->getDistUrls() as $url) {
            if (strpos($url, $this->baseUrl) === 0) {
                $package->setTransportOptions($this->options);
                return;
            }
        }
    }
    private function hasProviders(): bool
    {
        $this->loadRootServerFile();
        return $this->hasProviders;
    }
    /**
     * @param  string      $name package name
     * @param array<string, int>|null $acceptableStabilities
     * @phpstan-param array<key-of<BasePackage::STABILITIES>, BasePackage::STABILITY_*>|null $acceptableStabilities
     * @param array<string, int>|null $stabilityFlags an array of package name => BasePackage::STABILITY_* value
     * @phpstan-param array<string, BasePackage::STABILITY_*>|null $stabilityFlags
     * @param array<string, array<string, PackageInterface>> $alreadyLoaded
     *
     * @return array<string, BasePackage>
     */
    private function whatProvides(string $name, ?array $acceptableStabilities = null, ?array $stabilityFlags = null, array $alreadyLoaded = []): array
    {
        $packagesSource = null;
        if (!$this->hasPartialPackages() || !isset($this->partialPackagesByName[$name])) {
            // skip platform packages, root package and composer-plugin-api
            if (\Composer\Repository\PlatformRepository::isPlatformPackage($name) || '__root__' === $name) {
                return [];
            }
            if (null === $this->providerListing) {
                $data = $this->loadRootServerFile();
                if (is_array($data)) {
                    $this->loadProviderListings($data);
                }
            }
            $useLastModifiedCheck = \false;
            if ($this->lazyProvidersUrl && !isset($this->providerListing[$name])) {
                $hash = null;
                $url = str_replace('%package%', $name, $this->lazyProvidersUrl);
                $cacheKey = 'provider-' . strtr($name, '/', '$') . '.json';
                $useLastModifiedCheck = \true;
            } elseif ($this->providersUrl) {
                // package does not exist in this repo
                if (!isset($this->providerListing[$name])) {
                    return [];
                }
                $hash = $this->providerListing[$name]['sha256'];
                $url = str_replace(['%package%', '%hash%'], [$name, $hash], $this->providersUrl);
                $cacheKey = 'provider-' . strtr($name, '/', '$') . '.json';
            } else {
                return [];
            }
            $packages = null;
            if (!$useLastModifiedCheck && $hash && $this->cache->sha256($cacheKey) === $hash) {
                $packages = json_decode($this->cache->read($cacheKey), \true);
                $packagesSource = 'cached file (' . $cacheKey . ' originating from ' . Url::sanitize($url) . ')';
            } elseif ($useLastModifiedCheck) {
                if ($contents = $this->cache->read($cacheKey)) {
                    $contents = json_decode($contents, \true);
                    // we already loaded some packages from this file, so assume it is fresh and avoid fetching it again
                    if (isset($alreadyLoaded[$name])) {
                        $packages = $contents;
                        $packagesSource = 'cached file (' . $cacheKey . ' originating from ' . Url::sanitize($url) . ')';
                    } elseif (isset($contents['last-modified'])) {
                        $response = $this->fetchFileIfLastModified($url, $cacheKey, $contents['last-modified']);
                        $packages = \true === $response ? $contents : $response;
                        $packagesSource = \true === $response ? 'cached file (' . $cacheKey . ' originating from ' . Url::sanitize($url) . ')' : 'downloaded file (' . Url::sanitize($url) . ')';
                    }
                }
            }
            if (!$packages) {
                try {
                    $packages = $this->fetchFile($url, $cacheKey, $hash, $useLastModifiedCheck);
                    $packagesSource = 'downloaded file (' . Url::sanitize($url) . ')';
                } catch (TransportException $e) {
                    // 404s are acceptable for lazy provider repos
                    if ($this->lazyProvidersUrl && in_array($e->getStatusCode(), [404, 499], \true)) {
                        $packages = ['packages' => []];
                        $packagesSource = 'not-found file (' . Url::sanitize($url) . ')';
                        if ($e->getStatusCode() === 499) {
                            $this->io->error('<warning>' . $e->getMessage() . '</warning>');
                        }
                    } else {
                        throw $e;
                    }
                }
            }
            $loadingPartialPackage = \false;
        } else {
            $packages = ['packages' => ['versions' => $this->partialPackagesByName[$name]]];
            $packagesSource = 'root file (' . Url::sanitize($this->getPackagesJsonUrl()) . ')';
            $loadingPartialPackage = \true;
        }
        $result = [];
        $versionsToLoad = [];
        foreach ($packages['packages'] as $versions) {
            foreach ($versions as $version) {
                $normalizedName = strtolower($version['name']);
                // only load the actual named package, not other packages that might find themselves in the same file
                if ($normalizedName !== $name) {
                    continue;
                }
                if (!$loadingPartialPackage && $this->hasPartialPackages() && isset($this->partialPackagesByName[$normalizedName])) {
                    continue;
                }
                if (!isset($versionsToLoad[$version['uid']])) {
                    if (!isset($version['version_normalized'])) {
                        $version['version_normalized'] = $this->versionParser->normalize($version['version']);
                    } elseif ($version['version_normalized'] === VersionParser::DEFAULT_BRANCH_ALIAS) {
                        // handling of existing repos which need to remain composer v1 compatible, in case the version_normalized contained VersionParser::DEFAULT_BRANCH_ALIAS, we renormalize it
                        $version['version_normalized'] = $this->versionParser->normalize($version['version']);
                    }
                    // avoid loading packages which have already been loaded
                    if (isset($alreadyLoaded[$name][$version['version_normalized']])) {
                        continue;
                    }
                    if ($this->isVersionAcceptable(null, $normalizedName, $version, $acceptableStabilities, $stabilityFlags)) {
                        $versionsToLoad[$version['uid']] = $version;
                    }
                }
            }
        }
        // load acceptable packages in the providers
        $loadedPackages = $this->createPackages($versionsToLoad, $packagesSource);
        $uids = array_keys($versionsToLoad);
        foreach ($loadedPackages as $index => $package) {
            $package->setRepository($this);
            $uid = $uids[$index];
            if ($package instanceof AliasPackage) {
                $aliased = $package->getAliasOf();
                $aliased->setRepository($this);
                $result[$uid] = $aliased;
                $result[$uid . '-alias'] = $package;
            } else {
                $result[$uid] = $package;
            }
        }
        return $result;
    }
    /**
     * @inheritDoc
     */
    protected function initialize()
    {
        parent::initialize();
        $repoData = $this->loadDataFromServer();
        foreach ($this->createPackages($repoData, 'root file (' . Url::sanitize($this->getPackagesJsonUrl()) . ')') as $package) {
            $this->addPackage($package);
        }
    }
    /**
     * Adds a new package to the repository
     */
    public function addPackage(PackageInterface $package)
    {
        parent::addPackage($package);
        $this->configurePackageTransportOptions($package);
    }
    /**
     * @param array<string, ConstraintInterface|null> $packageNames array of package name => ConstraintInterface|null - if a constraint is provided, only
     *                                                packages matching it will be loaded
     * @param array<string, int>|null $acceptableStabilities
     * @phpstan-param array<key-of<BasePackage::STABILITIES>, BasePackage::STABILITY_*>|null $acceptableStabilities
     * @param array<string, int>|null $stabilityFlags an array of package name => BasePackage::STABILITY_* value
     * @phpstan-param array<string, BasePackage::STABILITY_*>|null $stabilityFlags
     * @param array<string, array<string, PackageInterface>> $alreadyLoaded
     *
     * @return array{namesFound: array<string, true>, packages: array<string, BasePackage>}
     */
    private function loadAsyncPackages(array $packageNames, ?array $acceptableStabilities = null, ?array $stabilityFlags = null, array $alreadyLoaded = []): array
    {
        $this->loadRootServerFile();
        $packages = [];
        $namesFound = [];
        $promises = [];
        if (null === $this->lazyProvidersUrl) {
            throw new \LogicException('loadAsyncPackages only supports v2 protocol composer repos with a metadata-url');
        }
        // load ~dev versions of the packages as well if needed
        foreach ($packageNames as $name => $constraint) {
            if ($acceptableStabilities === null || $stabilityFlags === null || StabilityFilter::isPackageAcceptable($acceptableStabilities, $stabilityFlags, [$name], 'dev')) {
                $packageNames[$name . '~dev'] = $constraint;
            }
            // if only dev stability is requested, we skip loading the non dev file
            if (isset($acceptableStabilities['dev']) && count($acceptableStabilities) === 1 && count($stabilityFlags) === 0) {
                unset($packageNames[$name]);
            }
        }
        foreach ($packageNames as $name => $constraint) {
            $name = strtolower($name);
            $realName = Preg::replace('{~dev$}', '', $name);
            // skip platform packages, root package and composer-plugin-api
            if (\Composer\Repository\PlatformRepository::isPlatformPackage($realName) || '__root__' === $realName) {
                continue;
            }
            $promises[] = $this->startCachedAsyncDownload($name, $realName)->then(function (array $spec) use (&$packages, &$namesFound, $realName, $constraint, $acceptableStabilities, $stabilityFlags, $alreadyLoaded): void {
                [$response, $packagesSource] = $spec;
                if (null === $response || !isset($response['packages'][$realName])) {
                    return;
                }
                $versions = $response['packages'][$realName];
                if (isset($response['minified']) && $response['minified'] === 'composer/2.0') {
                    $versions = MetadataMinifier::expand($versions);
                }
                $namesFound[$realName] = \true;
                $versionsToLoad = [];
                foreach ($versions as $version) {
                    if (!isset($version['version_normalized'])) {
                        $version['version_normalized'] = $this->versionParser->normalize($version['version']);
                    } elseif ($version['version_normalized'] === VersionParser::DEFAULT_BRANCH_ALIAS) {
                        // handling of existing repos which need to remain composer v1 compatible, in case the version_normalized contained VersionParser::DEFAULT_BRANCH_ALIAS, we renormalize it
                        $version['version_normalized'] = $this->versionParser->normalize($version['version']);
                    }
                    // avoid loading packages which have already been loaded
                    if (isset($alreadyLoaded[$realName][$version['version_normalized']])) {
                        continue;
                    }
                    if ($this->isVersionAcceptable($constraint, $realName, $version, $acceptableStabilities, $stabilityFlags)) {
                        $versionsToLoad[] = $version;
                    }
                }
                $loadedPackages = $this->createPackages($versionsToLoad, $packagesSource);
                foreach ($loadedPackages as $package) {
                    $package->setRepository($this);
                    $packages[spl_object_hash($package)] = $package;
                    if ($package instanceof AliasPackage && !isset($packages[spl_object_hash($package->getAliasOf())])) {
                        $package->getAliasOf()->setRepository($this);
                        $packages[spl_object_hash($package->getAliasOf())] = $package->getAliasOf();
                    }
                }
            });
        }
        $this->loop->wait($promises);
        return ['namesFound' => $namesFound, 'packages' => $packages];
    }
    /**
     * @phpstan-return PromiseInterface<array{mixed, string}>
     */
    private function startCachedAsyncDownload(string $fileName, ?string $packageName = null): PromiseInterface
    {
        if (null === $this->lazyProvidersUrl) {
            throw new \LogicException('startCachedAsyncDownload only supports v2 protocol composer repos with a metadata-url');
        }
        $name = strtolower($fileName);
        $packageName = $packageName ?? $name;
        $url = str_replace('%package%', $name, $this->lazyProvidersUrl);
        $cacheKey = 'provider-' . strtr($name, '/', '~') . '.json';
        $lastModified = null;
        if ($contents = $this->cache->read($cacheKey)) {
            $contents = json_decode($contents, \true);
            $lastModified = $contents['last-modified'] ?? null;
        }
        return $this->asyncFetchFile($url, $cacheKey, $lastModified)->then(static function ($response) use ($url, $cacheKey, $contents, $packageName): array {
            $packagesSource = 'downloaded file (' . Url::sanitize($url) . ')';
            if (\true === $response) {
                $packagesSource = 'cached file (' . $cacheKey . ' originating from ' . Url::sanitize($url) . ')';
                $response = $contents;
            }
            if (!isset($response['packages'][$packageName]) && !isset($response['security-advisories'])) {
                return [null, $packagesSource];
            }
            return [$response, $packagesSource];
        });
    }
    /**
     * @param string $name package name (must be lowercased already)
     * @param array<string, mixed> $versionData
     * @param array<string, int>|null $acceptableStabilities
     * @phpstan-param array<key-of<BasePackage::STABILITIES>, BasePackage::STABILITY_*>|null $acceptableStabilities
     * @param array<string, int>|null $stabilityFlags an array of package name => BasePackage::STABILITY_* value
     * @phpstan-param array<string, BasePackage::STABILITY_*>|null $stabilityFlags
     */
    private function isVersionAcceptable(?ConstraintInterface $constraint, string $name, array $versionData, ?array $acceptableStabilities = null, ?array $stabilityFlags = null): bool
    {
        $versions = [$versionData['version_normalized']];
        if ($alias = $this->loader->getBranchAlias($versionData)) {
            $versions[] = $alias;
        }
        foreach ($versions as $version) {
            if (null !== $acceptableStabilities && null !== $stabilityFlags && !StabilityFilter::isPackageAcceptable($acceptableStabilities, $stabilityFlags, [$name], VersionParser::parseStability($version))) {
                continue;
            }
            if ($constraint && !CompilingMatcher::match($constraint, Constraint::OP_EQ, $version)) {
                continue;
            }
            return \true;
        }
        return \false;
    }
    private function getPackagesJsonUrl(): string
    {
        $jsonUrlParts = parse_url(strtr($this->url, '\\', '/'));
        if (isset($jsonUrlParts['path']) && \false !== strpos($jsonUrlParts['path'], '.json')) {
            return $this->url;
        }
        return $this->url . '/packages.json';
    }
    /**
     * @return array<'providers'|'provider-includes'|'packages'|'providers-url'|'notify-batch'|'search'|'mirrors'|'providers-lazy-url'|'metadata-url'|'available-packages'|'available-package-patterns', mixed>|true
     */
    protected function loadRootServerFile(?int $rootMaxAge = null)
    {
        if (null !== $this->rootData) {
            return $this->rootData;
        }
        if (!extension_loaded('openssl') && strpos($this->url, 'https') === 0) {
            throw new \RuntimeException('You must enable the openssl extension in your php.ini to load information from ' . $this->url);
        }
        if ($cachedData = $this->cache->read('packages.json')) {
            $cachedData = json_decode($cachedData, \true);
            if ($rootMaxAge !== null && ($age = $this->cache->getAge('packages.json')) !== \false && $age <= $rootMaxAge) {
                $data = $cachedData;
            } elseif (isset($cachedData['last-modified'])) {
                $response = $this->fetchFileIfLastModified($this->getPackagesJsonUrl(), 'packages.json', $cachedData['last-modified']);
                $data = \true === $response ? $cachedData : $response;
            }
        }
        if (!isset($data)) {
            $data = $this->fetchFile($this->getPackagesJsonUrl(), 'packages.json', null, \true);
        }
        if (!empty($data['notify-batch'])) {
            $this->notifyUrl = $this->canonicalizeUrl($data['notify-batch']);
        } elseif (!empty($data['notify'])) {
            $this->notifyUrl = $this->canonicalizeUrl($data['notify']);
        }
        if (!empty($data['search'])) {
            $this->searchUrl = $this->canonicalizeUrl($data['search']);
        }
        if (!empty($data['mirrors'])) {
            foreach ($data['mirrors'] as $mirror) {
                if (!empty($mirror['git-url'])) {
                    $this->sourceMirrors['git'][] = ['url' => $mirror['git-url'], 'preferred' => !empty($mirror['preferred'])];
                }
                if (!empty($mirror['hg-url'])) {
                    $this->sourceMirrors['hg'][] = ['url' => $mirror['hg-url'], 'preferred' => !empty($mirror['preferred'])];
                }
                if (!empty($mirror['dist-url'])) {
                    $this->distMirrors[] = ['url' => $this->canonicalizeUrl($mirror['dist-url']), 'preferred' => !empty($mirror['preferred'])];
                }
            }
        }
        if (!empty($data['providers-lazy-url'])) {
            $this->lazyProvidersUrl = $this->canonicalizeUrl($data['providers-lazy-url']);
            $this->hasProviders = \true;
            $this->hasPartialPackages = !empty($data['packages']) && is_array($data['packages']);
        }
        // metadata-url indicates V2 repo protocol so it takes over from all the V1 types
        // V2 only has lazyProviders and possibly partial packages, but no ability to process anything else,
        // V2 also supports async loading
        if (!empty($data['metadata-url'])) {
            $this->lazyProvidersUrl = $this->canonicalizeUrl($data['metadata-url']);
            $this->providersUrl = null;
            $this->hasProviders = \false;
            $this->hasPartialPackages = !empty($data['packages']) && is_array($data['packages']);
            $this->allowSslDowngrade = \false;
            // provides a list of package names that are available in this repo
            // this disables lazy-provider behavior in the sense that if a list is available we assume it is finite and won't search for other packages in that repo
            // while if no list is there lazyProvidersUrl is used when looking for any package name to see if the repo knows it
            if (!empty($data['available-packages'])) {
                $availPackages = array_map('strtolower', $data['available-packages']);
                $this->availablePackages = array_combine($availPackages, $availPackages);
                $this->hasAvailablePackageList = \true;
            }
            // Provides a list of package name patterns (using * wildcards to match any substring, e.g. "vendor/*") that are available in this repo
            // Disables lazy-provider behavior as with available-packages, but may allow much more compact expression of packages covered by this repository.
            // Over-specifying covered packages is safe, but may result in increased traffic to your repository.
            if (!empty($data['available-package-patterns'])) {
                $this->availablePackagePatterns = array_map(static function ($pattern): string {
                    return BasePackage::packageNameToRegexp($pattern);
                }, $data['available-package-patterns']);
                $this->hasAvailablePackageList = \true;
            }
            // Remove legacy keys as most repos need to be compatible with Composer v1
            // as well but we are not interested in the old format anymore at this point
            unset($data['providers-url'], $data['providers'], $data['providers-includes']);
            if (isset($data['security-advisories']) && is_array($data['security-advisories'])) {
                $this->securityAdvisoryConfig = ['metadata' => $data['security-advisories']['metadata'] ?? \false, 'api-url' => isset($data['security-advisories']['api-url']) && is_string($data['security-advisories']['api-url']) ? $this->canonicalizeUrl($data['security-advisories']['api-url']) : null];
                if ($this->securityAdvisoryConfig['api-url'] === null && !$this->hasAvailablePackageList) {
                    throw new \UnexpectedValueException('Invalid security advisory configuration on ' . $this->getRepoName() . ': If the repository does not provide a security-advisories.api-url then available-packages or available-package-patterns are required to be provided for performance reason.');
                }
            }
        }
        if ($this->allowSslDowngrade) {
            $this->url = str_replace('https://', 'http://', $this->url);
            $this->baseUrl = str_replace('https://', 'http://', $this->baseUrl);
        }
        if (!empty($data['providers-url'])) {
            $this->providersUrl = $this->canonicalizeUrl($data['providers-url']);
            $this->hasProviders = \true;
        }
        if (!empty($data['list'])) {
            $this->listUrl = $this->canonicalizeUrl($data['list']);
        }
        if (!empty($data['providers']) || !empty($data['providers-includes'])) {
            $this->hasProviders = \true;
        }
        if (!empty($data['providers-api'])) {
            $this->providersApiUrl = $this->canonicalizeUrl($data['providers-api']);
        }
        return $this->rootData = $data;
    }
    /**
     * @return non-empty-string
     */
    private function canonicalizeUrl(string $url): string
    {
        if (strlen($url) === 0) {
            throw new \InvalidArgumentException('Expected a string with a value and not an empty string');
        }
        if (str_starts_with($url, '/')) {
            if (Preg::isMatch('{^[^:]++://[^/]*+}', $this->url, $matches)) {
                return $matches[0] . $url;
            }
            return $this->url;
        }
        return $url;
    }
    /**
     * @return mixed[]
     */
    private function loadDataFromServer(): array
    {
        $data = $this->loadRootServerFile();
        if (\true === $data) {
            throw new \LogicException('loadRootServerFile should not return true during initialization');
        }
        return $this->loadIncludes($data);
    }
    private function hasPartialPackages(): bool
    {
        if ($this->hasPartialPackages && null === $this->partialPackagesByName) {
            $this->initializePartialPackages();
        }
        return $this->hasPartialPackages;
    }
    /**
     * @param array{providers?: mixed[], provider-includes?: mixed[]} $data
     */
    private function loadProviderListings($data): void
    {
        if (isset($data['providers'])) {
            if (!is_array($this->providerListing)) {
                $this->providerListing = [];
            }
            $this->providerListing = array_merge($this->providerListing, $data['providers']);
        }
        if ($this->providersUrl && isset($data['provider-includes'])) {
            $includes = $data['provider-includes'];
            foreach ($includes as $include => $metadata) {
                $url = $this->baseUrl . '/' . str_replace('%hash%', $metadata['sha256'], $include);
                $cacheKey = str_replace(['%hash%', '$'], '', $include);
                if ($this->cache->sha256($cacheKey) === $metadata['sha256']) {
                    $includedData = json_decode($this->cache->read($cacheKey), \true);
                } else {
                    $includedData = $this->fetchFile($url, $cacheKey, $metadata['sha256']);
                }
                $this->loadProviderListings($includedData);
            }
        }
    }
    /**
     * @param mixed[] $data
     *
     * @return mixed[]
     */
    private function loadIncludes(array $data): array
    {
        $packages = [];
        // legacy repo handling
        if (!isset($data['packages']) && !isset($data['includes'])) {
            foreach ($data as $pkg) {
                if (isset($pkg['versions']) && is_array($pkg['versions'])) {
                    foreach ($pkg['versions'] as $metadata) {
                        $packages[] = $metadata;
                    }
                }
            }
            return $packages;
        }
        if (isset($data['packages'])) {
            foreach ($data['packages'] as $package => $versions) {
                $packageName = strtolower((string) $package);
                foreach ($versions as $version => $metadata) {
                    $packages[] = $metadata;
                    if (!$this->displayedWarningAboutNonMatchingPackageIndex && $packageName !== strtolower((string) ($metadata['name'] ?? ''))) {
                        $this->displayedWarningAboutNonMatchingPackageIndex = \true;
                        $this->io->writeError(sprintf("<warning>Warning: the packages key '%s' doesn't match the name defined in the package metadata '%s' in repository %s</warning>", $package, $metadata['name'] ?? '', $this->baseUrl));
                    }
                }
            }
        }
        if (isset($data['includes'])) {
            foreach ($data['includes'] as $include => $metadata) {
                if (isset($metadata['sha1']) && $this->cache->sha1((string) $include) === $metadata['sha1']) {
                    $includedData = json_decode($this->cache->read((string) $include), \true);
                } else {
                    $includedData = $this->fetchFile($include);
                }
                $packages = array_merge($packages, $this->loadIncludes($includedData));
            }
        }
        return $packages;
    }
    /**
     * @param mixed[] $packages
     *
     * @return list<CompletePackage|CompleteAliasPackage>
     */
    private function createPackages(array $packages, ?string $source = null): array
    {
        if (!$packages) {
            return [];
        }
        try {
            foreach ($packages as &$data) {
                if (!isset($data['notification-url'])) {
                    $data['notification-url'] = $this->notifyUrl;
                }
            }
            $packageInstances = $this->loader->loadPackages($packages);
            foreach ($packageInstances as $package) {
                if (isset($this->sourceMirrors[$package->getSourceType()])) {
                    $package->setSourceMirrors($this->sourceMirrors[$package->getSourceType()]);
                }
                $package->setDistMirrors($this->distMirrors);
                $this->configurePackageTransportOptions($package);
            }
            return $packageInstances;
        } catch (\Exception $e) {
            throw new \RuntimeException('Could not load packages in ' . $this->getRepoName() . ($source ? ' from ' . $source : '') . ': [' . get_class($e) . '] ' . $e->getMessage(), 0, $e);
        }
    }
    /**
     * @return array<mixed>
     */
    protected function fetchFile(string $filename, ?string $cacheKey = null, ?string $sha256 = null, bool $storeLastModifiedTime = \false)
    {
        if ('' === $filename) {
            throw new \InvalidArgumentException('$filename should not be an empty string');
        }
        if (null === $cacheKey) {
            $cacheKey = $filename;
            $filename = $this->baseUrl . '/' . $filename;
        }
        // url-encode $ signs in URLs as bad proxies choke on them
        if (($pos = strpos($filename, '$')) && Preg::isMatch('{^https?://}i', $filename)) {
            $filename = substr($filename, 0, $pos) . '%24' . substr($filename, $pos + 1);
        }
        $retries = 3;
        while ($retries--) {
            try {
                $options = $this->options;
                if ($this->eventDispatcher) {
                    $preFileDownloadEvent = new PreFileDownloadEvent(PluginEvents::PRE_FILE_DOWNLOAD, $this->httpDownloader, $filename, 'metadata', ['repository' => $this]);
                    $preFileDownloadEvent->setTransportOptions($this->options);
                    $this->eventDispatcher->dispatch($preFileDownloadEvent->getName(), $preFileDownloadEvent);
                    $filename = $preFileDownloadEvent->getProcessedUrl();
                    $options = $preFileDownloadEvent->getTransportOptions();
                }
                $response = $this->httpDownloader->get($filename, $options);
                $json = (string) $response->getBody();
                if ($sha256 && $sha256 !== hash('sha256', $json)) {
                    // undo downgrade before trying again if http seems to be hijacked or modifying content somehow
                    if ($this->allowSslDowngrade) {
                        $this->url = str_replace('http://', 'https://', $this->url);
                        $this->baseUrl = str_replace('http://', 'https://', $this->baseUrl);
                        $filename = str_replace('http://', 'https://', $filename);
                    }
                    if ($retries > 0) {
                        usleep(100000);
                        continue;
                    }
                    // TODO use scarier wording once we know for sure it doesn't do false positives anymore
                    throw new \Composer\Repository\RepositorySecurityException('The contents of ' . $filename . ' do not match its signature. This could indicate a man-in-the-middle attack or e.g. antivirus software corrupting files. Try running composer again and report this if you think it is a mistake.');
                }
                if ($this->eventDispatcher) {
                    $postFileDownloadEvent = new PostFileDownloadEvent(PluginEvents::POST_FILE_DOWNLOAD, null, $sha256, $filename, 'metadata', ['response' => $response, 'repository' => $this]);
                    $this->eventDispatcher->dispatch($postFileDownloadEvent->getName(), $postFileDownloadEvent);
                }
                $data = $response->decodeJson();
                HttpDownloader::outputWarnings($this->io, $this->url, $data);
                if ($cacheKey && !$this->cache->isReadOnly()) {
                    if ($storeLastModifiedTime) {
                        $lastModifiedDate = $response->getHeader('last-modified');
                        if ($lastModifiedDate) {
                            $data['last-modified'] = $lastModifiedDate;
                            $json = JsonFile::encode($data, 0);
                        }
                    }
                    $this->cache->write($cacheKey, $json);
                }
                $response->collect();
                break;
            } catch (\Exception $e) {
                if ($e instanceof \LogicException) {
                    throw $e;
                }
                if ($e instanceof TransportException && $e->getStatusCode() === 404) {
                    throw $e;
                }
                if ($e instanceof \Composer\Repository\RepositorySecurityException) {
                    throw $e;
                }
                if ($cacheKey && $contents = $this->cache->read($cacheKey)) {
                    if (!$this->degradedMode) {
                        $this->io->writeError('<warning>' . $this->url . ' could not be fully loaded (' . $e->getMessage() . '), package information was loaded from the local cache and may be out of date</warning>');
                    }
                    $this->degradedMode = \true;
                    $data = JsonFile::parseJson($contents, $this->cache->getRoot() . $cacheKey);
                    break;
                }
                throw $e;
            }
        }
        if (!isset($data)) {
            throw new \LogicException("ComposerRepository: Undefined \$data. Please report at https://github.com/composer/composer/issues/new.");
        }
        return $data;
    }
    /**
     * @return array<mixed>|true
     */
    private function fetchFileIfLastModified(string $filename, string $cacheKey, string $lastModifiedTime)
    {
        if ('' === $filename) {
            throw new \InvalidArgumentException('$filename should not be an empty string');
        }
        try {
            $options = $this->options;
            if ($this->eventDispatcher) {
                $preFileDownloadEvent = new PreFileDownloadEvent(PluginEvents::PRE_FILE_DOWNLOAD, $this->httpDownloader, $filename, 'metadata', ['repository' => $this]);
                $preFileDownloadEvent->setTransportOptions($this->options);
                $this->eventDispatcher->dispatch($preFileDownloadEvent->getName(), $preFileDownloadEvent);
                $filename = $preFileDownloadEvent->getProcessedUrl();
                $options = $preFileDownloadEvent->getTransportOptions();
            }
            if (isset($options['http']['header'])) {
                $options['http']['header'] = (array) $options['http']['header'];
            }
            $options['http']['header'][] = 'If-Modified-Since: ' . $lastModifiedTime;
            $response = $this->httpDownloader->get($filename, $options);
            $json = (string) $response->getBody();
            if ($json === '' && $response->getStatusCode() === 304) {
                return \true;
            }
            if ($this->eventDispatcher) {
                $postFileDownloadEvent = new PostFileDownloadEvent(PluginEvents::POST_FILE_DOWNLOAD, null, null, $filename, 'metadata', ['response' => $response, 'repository' => $this]);
                $this->eventDispatcher->dispatch($postFileDownloadEvent->getName(), $postFileDownloadEvent);
            }
            $data = $response->decodeJson();
            HttpDownloader::outputWarnings($this->io, $this->url, $data);
            $lastModifiedDate = $response->getHeader('last-modified');
            $response->collect();
            if ($lastModifiedDate) {
                $data['last-modified'] = $lastModifiedDate;
                $json = JsonFile::encode($data, 0);
            }
            if (!$this->cache->isReadOnly()) {
                $this->cache->write($cacheKey, $json);
            }
            return $data;
        } catch (\Exception $e) {
            if ($e instanceof \LogicException) {
                throw $e;
            }
            if ($e instanceof TransportException && $e->getStatusCode() === 404) {
                throw $e;
            }
            if (!$this->degradedMode) {
                $this->io->writeError('<warning>' . $this->url . ' could not be fully loaded (' . $e->getMessage() . '), package information was loaded from the local cache and may be out of date</warning>');
            }
            $this->degradedMode = \true;
            return \true;
        }
    }
    /**
     * @phpstan-return PromiseInterface<array<mixed>|true> true if the response was a 304 and the cache is fresh, otherwise it returns the decoded json
     */
    private function asyncFetchFile(string $filename, string $cacheKey, ?string $lastModifiedTime = null): PromiseInterface
    {
        if ('' === $filename) {
            throw new \InvalidArgumentException('$filename should not be an empty string');
        }
        if (isset($this->packagesNotFoundCache[$filename])) {
            return \React\Promise\resolve(['packages' => []]);
        }
        if (isset($this->freshMetadataUrls[$filename]) && $lastModifiedTime) {
            // make it look like we got a 304 response
            /** @var PromiseInterface<true> $promise */
            $promise = \React\Promise\resolve(\true);
            return $promise;
        }
        $httpDownloader = $this->httpDownloader;
        $options = $this->options;
        if ($this->eventDispatcher) {
            $preFileDownloadEvent = new PreFileDownloadEvent(PluginEvents::PRE_FILE_DOWNLOAD, $this->httpDownloader, $filename, 'metadata', ['repository' => $this]);
            $preFileDownloadEvent->setTransportOptions($this->options);
            $this->eventDispatcher->dispatch($preFileDownloadEvent->getName(), $preFileDownloadEvent);
            $filename = $preFileDownloadEvent->getProcessedUrl();
            $options = $preFileDownloadEvent->getTransportOptions();
        }
        if ($lastModifiedTime) {
            if (isset($options['http']['header'])) {
                $options['http']['header'] = (array) $options['http']['header'];
            }
            $options['http']['header'][] = 'If-Modified-Since: ' . $lastModifiedTime;
        }
        $io = $this->io;
        $url = $this->url;
        $cache = $this->cache;
        $degradedMode =& $this->degradedMode;
        $eventDispatcher = $this->eventDispatcher;
        /**
         * @return array<mixed>|true true if the response was a 304 and the cache is fresh
         */
        $accept = function ($response) use ($io, $url, $filename, $cache, $cacheKey, $eventDispatcher) {
            // package not found is acceptable for a v2 protocol repository
            if ($response->getStatusCode() === 404) {
                $this->packagesNotFoundCache[$filename] = \true;
                return ['packages' => []];
            }
            $json = (string) $response->getBody();
            if ($json === '' && $response->getStatusCode() === 304) {
                $this->freshMetadataUrls[$filename] = \true;
                return \true;
            }
            if ($eventDispatcher) {
                $postFileDownloadEvent = new PostFileDownloadEvent(PluginEvents::POST_FILE_DOWNLOAD, null, null, $filename, 'metadata', ['response' => $response, 'repository' => $this]);
                $eventDispatcher->dispatch($postFileDownloadEvent->getName(), $postFileDownloadEvent);
            }
            $data = $response->decodeJson();
            HttpDownloader::outputWarnings($io, $url, $data);
            $lastModifiedDate = $response->getHeader('last-modified');
            $response->collect();
            if ($lastModifiedDate) {
                $data['last-modified'] = $lastModifiedDate;
                $json = JsonFile::encode($data, \JSON_UNESCAPED_SLASHES | \JSON_UNESCAPED_UNICODE);
            }
            if (!$cache->isReadOnly()) {
                $cache->write($cacheKey, $json);
            }
            $this->freshMetadataUrls[$filename] = \true;
            return $data;
        };
        $reject = function ($e) use ($filename, $accept, $io, $url, &$degradedMode, $lastModifiedTime) {
            if ($e instanceof TransportException && $e->getStatusCode() === 404) {
                $this->packagesNotFoundCache[$filename] = \true;
                return \false;
            }
            if (!$degradedMode) {
                $io->writeError('<warning>' . $url . ' could not be fully loaded (' . $e->getMessage() . '), package information was loaded from the local cache and may be out of date</warning>');
            }
            $degradedMode = \true;
            // if the file is in the cache, we fake a 304 Not Modified to allow the process to continue
            if ($lastModifiedTime) {
                return $accept(new Response(['url' => $url], 304, [], ''));
            }
            // special error code returned when network is being artificially disabled
            if ($e instanceof TransportException && $e->getStatusCode() === 499) {
                return $accept(new Response(['url' => $url], 404, [], ''));
            }
            throw $e;
        };
        return $httpDownloader->add($filename, $options)->then($accept, $reject);
    }
    /**
     * This initializes the packages key of a partial packages.json that contain some packages inlined + a providers-lazy-url
     *
     * This should only be called once
     */
    private function initializePartialPackages(): void
    {
        $rootData = $this->loadRootServerFile();
        if ($rootData === \true) {
            return;
        }
        $this->partialPackagesByName = [];
        foreach ($rootData['packages'] as $package => $versions) {
            foreach ($versions as $version) {
                $versionPackageName = strtolower((string) ($version['name'] ?? ''));
                $this->partialPackagesByName[$versionPackageName][] = $version;
                if (!$this->displayedWarningAboutNonMatchingPackageIndex && $versionPackageName !== strtolower($package)) {
                    $this->io->writeError(sprintf("<warning>Warning: the packages key '%s' doesn't match the name defined in the package metadata '%s' in repository %s</warning>", $package, $version['name'] ?? '', $this->baseUrl));
                    $this->displayedWarningAboutNonMatchingPackageIndex = \true;
                }
            }
        }
        // wipe rootData as it is fully consumed at this point and this saves some memory
        $this->rootData = \true;
    }
    /**
     * Checks if the package name is present in this lazy providers repo
     *
     * @return bool   true if the package name is present in availablePackages or matched by availablePackagePatterns
     */
    protected function lazyProvidersRepoContains(string $name)
    {
        if (!$this->hasAvailablePackageList) {
            throw new \LogicException('lazyProvidersRepoContains should not be called unless hasAvailablePackageList is true');
        }
        if (is_array($this->availablePackages) && isset($this->availablePackages[$name])) {
            return \true;
        }
        if (is_array($this->availablePackagePatterns)) {
            foreach ($this->availablePackagePatterns as $providerRegex) {
                if (Preg::isMatch($providerRegex, $name)) {
                    return \true;
                }
            }
        }
        return \false;
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer\Repository;

/**
 * Builds list of package from PEAR channel.
 *
 * Packages read from channel are named as 'pear-{channelName}/{packageName}'
 * and has aliased as 'pear-{channelAlias}/{packageName}'
 *
 * @author Benjamin Eberlei <kontakt@beberlei.de>
 * @author Jordi Boggiano <j.boggiano@seld.be>
 * @deprecated
 * @private
 */
class PearRepository extends \Composer\Repository\ArrayRepository
{
    public function __construct()
    {
        throw new \InvalidArgumentException('The PEAR repository has been removed from Composer 2.x');
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer\Repository;

use Composer\DependencyResolver\PoolOptimizer;
use Composer\DependencyResolver\Pool;
use Composer\DependencyResolver\PoolBuilder;
use Composer\DependencyResolver\Request;
use Composer\DependencyResolver\SecurityAdvisoryPoolFilter;
use Composer\EventDispatcher\EventDispatcher;
use Composer\Advisory\SecurityAdvisory;
use Composer\Advisory\PartialSecurityAdvisory;
use Composer\IO\IOInterface;
use Composer\IO\NullIO;
use Composer\Package\BasePackage;
use Composer\Package\AliasPackage;
use Composer\Package\CompleteAliasPackage;
use Composer\Package\CompletePackage;
use Composer\Package\PackageInterface;
use Composer\Semver\Constraint\Constraint;
use Composer\Semver\Constraint\ConstraintInterface;
use Composer\Package\Version\StabilityFilter;
use Composer\Semver\Constraint\MatchAllConstraint;
use Composer\Semver\Constraint\MultiConstraint;
/**
 * @author Nils Adermann <naderman@naderman.de>
 *
 * @see RepositoryUtils for ways to work with single repos
 */
class RepositorySet
{
    /**
     * Packages are returned even though their stability does not match the required stability
     */
    public const ALLOW_UNACCEPTABLE_STABILITIES = 1;
    /**
     * Packages will be looked up in all repositories, even after they have been found in a higher prio one
     */
    public const ALLOW_SHADOWED_REPOSITORIES = 2;
    /**
     * @var array[]
     * @phpstan-var array<string, array<string, array{alias: string, alias_normalized: string}>>
     */
    private $rootAliases;
    /**
     * @var string[]
     * @phpstan-var array<string, string>
     */
    private $rootReferences;
    /** @var RepositoryInterface[] */
    private $repositories = [];
    /**
     * @var int[] array of stability => BasePackage::STABILITY_* value
     * @phpstan-var array<key-of<BasePackage::STABILITIES>, BasePackage::STABILITY_*>
     */
    private $acceptableStabilities;
    /**
     * @var int[] array of package name => BasePackage::STABILITY_* value
     * @phpstan-var array<string, BasePackage::STABILITY_*>
     */
    private $stabilityFlags;
    /**
     * @var ConstraintInterface[]
     * @phpstan-var array<string, ConstraintInterface>
     */
    private $rootRequires;
    /**
     * @var array<string, ConstraintInterface>
     */
    private $temporaryConstraints;
    /** @var bool */
    private $locked = \false;
    /** @var bool */
    private $allowInstalledRepositories = \false;
    /**
     * In most cases if you are looking to use this class as a way to find packages from repositories
     * passing minimumStability is all you need to worry about. The rest is for advanced pool creation including
     * aliases, pinned references and other special cases.
     *
     * @param key-of<BasePackage::STABILITIES> $minimumStability
     * @param int[]  $stabilityFlags   an array of package name => BasePackage::STABILITY_* value
     * @phpstan-param array<string, BasePackage::STABILITY_*> $stabilityFlags
     * @param array[] $rootAliases
     * @phpstan-param list<array{package: string, version: string, alias: string, alias_normalized: string}> $rootAliases
     * @param string[] $rootReferences an array of package name => source reference
     * @phpstan-param array<string, string> $rootReferences
     * @param ConstraintInterface[] $rootRequires an array of package name => constraint from the root package
     * @phpstan-param array<string, ConstraintInterface> $rootRequires
     * @param array<string, ConstraintInterface> $temporaryConstraints Runtime temporary constraints that will be used to filter packages
     */
    public function __construct(string $minimumStability = 'stable', array $stabilityFlags = [], array $rootAliases = [], array $rootReferences = [], array $rootRequires = [], array $temporaryConstraints = [])
    {
        $this->rootAliases = self::getRootAliasesPerPackage($rootAliases);
        $this->rootReferences = $rootReferences;
        $this->acceptableStabilities = [];
        foreach (BasePackage::STABILITIES as $stability => $value) {
            if ($value <= BasePackage::STABILITIES[$minimumStability]) {
                $this->acceptableStabilities[$stability] = $value;
            }
        }
        $this->stabilityFlags = $stabilityFlags;
        $this->rootRequires = $rootRequires;
        foreach ($rootRequires as $name => $constraint) {
            if (\Composer\Repository\PlatformRepository::isPlatformPackage($name)) {
                unset($this->rootRequires[$name]);
            }
        }
        $this->temporaryConstraints = $temporaryConstraints;
    }
    public function allowInstalledRepositories(bool $allow = \true): void
    {
        $this->allowInstalledRepositories = $allow;
    }
    /**
     * @return ConstraintInterface[] an array of package name => constraint from the root package, platform requirements excluded
     * @phpstan-return array<string, ConstraintInterface>
     */
    public function getRootRequires(): array
    {
        return $this->rootRequires;
    }
    /**
     * @return array<string, ConstraintInterface> Runtime temporary constraints that will be used to filter packages
     */
    public function getTemporaryConstraints(): array
    {
        return $this->temporaryConstraints;
    }
    /**
     * Adds a repository to this repository set
     *
     * The first repos added have a higher priority. As soon as a package is found in any
     * repository the search for that package ends, and following repos will not be consulted.
     *
     * @param RepositoryInterface $repo A package repository
     */
    public function addRepository(\Composer\Repository\RepositoryInterface $repo): void
    {
        if ($this->locked) {
            throw new \RuntimeException("Pool has already been created from this repository set, it cannot be modified anymore.");
        }
        if ($repo instanceof \Composer\Repository\CompositeRepository) {
            $repos = $repo->getRepositories();
        } else {
            $repos = [$repo];
        }
        foreach ($repos as $repo) {
            $this->repositories[] = $repo;
        }
    }
    /**
     * Find packages providing or matching a name and optionally meeting a constraint in all repositories
     *
     * Returned in the order of repositories, matching priority
     *
     * @param  int                      $flags      any of the ALLOW_* constants from this class to tweak what is returned
     * @return BasePackage[]
     */
    public function findPackages(string $name, ?ConstraintInterface $constraint = null, int $flags = 0): array
    {
        $ignoreStability = ($flags & self::ALLOW_UNACCEPTABLE_STABILITIES) !== 0;
        $loadFromAllRepos = ($flags & self::ALLOW_SHADOWED_REPOSITORIES) !== 0;
        $packages = [];
        if ($loadFromAllRepos) {
            foreach ($this->repositories as $repository) {
                $packages[] = $repository->findPackages($name, $constraint) ?: [];
            }
        } else {
            foreach ($this->repositories as $repository) {
                $result = $repository->loadPackages([$name => $constraint], $ignoreStability ? BasePackage::STABILITIES : $this->acceptableStabilities, $ignoreStability ? [] : $this->stabilityFlags);
                $packages[] = $result['packages'];
                foreach ($result['namesFound'] as $nameFound) {
                    // avoid loading the same package again from other repositories once it has been found
                    if ($name === $nameFound) {
                        break 2;
                    }
                }
            }
        }
        $candidates = $packages ? array_merge(...$packages) : [];
        // when using loadPackages above (!$loadFromAllRepos) the repos already filter for stability so no need to do it again
        if ($ignoreStability || !$loadFromAllRepos) {
            return $candidates;
        }
        $result = [];
        foreach ($candidates as $candidate) {
            if ($this->isPackageAcceptable($candidate->getNames(), $candidate->getStability())) {
                $result[] = $candidate;
            }
        }
        return $result;
    }
    /**
     * @param string[] $packageNames
     * @return ($allowPartialAdvisories is true ? array{advisories: array<string, array<PartialSecurityAdvisory|SecurityAdvisory>>, unreachableRepos: array<string>} : array{advisories: array<string, array<SecurityAdvisory>>, unreachableRepos: array<string>})
     */
    public function getSecurityAdvisories(array $packageNames, bool $allowPartialAdvisories, bool $ignoreUnreachable = \false): array
    {
        $map = [];
        foreach ($packageNames as $name) {
            $map[$name] = new MatchAllConstraint();
        }
        $unreachableRepos = [];
        $advisories = $this->getSecurityAdvisoriesForConstraints($map, $allowPartialAdvisories, $ignoreUnreachable, $unreachableRepos);
        return ['advisories' => $advisories, 'unreachableRepos' => $unreachableRepos];
    }
    /**
     * @param PackageInterface[] $packages
     * @return ($allowPartialAdvisories is true ? array{advisories: array<string, array<PartialSecurityAdvisory|SecurityAdvisory>>, unreachableRepos: array<string>} : array{advisories: array<string, array<SecurityAdvisory>>, unreachableRepos: array<string>})
     */
    public function getMatchingSecurityAdvisories(array $packages, bool $allowPartialAdvisories = \false, bool $ignoreUnreachable = \false): array
    {
        $map = [];
        foreach ($packages as $package) {
            // ignore root alias versions as they are not actual package versions and should not matter when it comes to vulnerabilities
            if ($package instanceof AliasPackage && $package->isRootPackageAlias()) {
                continue;
            }
            if (isset($map[$package->getName()])) {
                $map[$package->getName()] = new MultiConstraint([new Constraint('=', $package->getVersion()), $map[$package->getName()]], \false);
            } else {
                $map[$package->getName()] = new Constraint('=', $package->getVersion());
            }
        }
        $unreachableRepos = [];
        $advisories = $this->getSecurityAdvisoriesForConstraints($map, $allowPartialAdvisories, $ignoreUnreachable, $unreachableRepos);
        return ['advisories' => $advisories, 'unreachableRepos' => $unreachableRepos];
    }
    /**
     * @param array<string, ConstraintInterface> $packageConstraintMap
     * @param array<string> &$unreachableRepos Array to store messages about unreachable repositories
     * @return ($allowPartialAdvisories is true ? array<string, array<PartialSecurityAdvisory|SecurityAdvisory>> : array<string, array<SecurityAdvisory>>)
     */
    private function getSecurityAdvisoriesForConstraints(array $packageConstraintMap, bool $allowPartialAdvisories, bool $ignoreUnreachable = \false, array &$unreachableRepos = []): array
    {
        $repoAdvisories = [];
        foreach ($this->repositories as $repository) {
            try {
                if (!$repository instanceof \Composer\Repository\AdvisoryProviderInterface || !$repository->hasSecurityAdvisories()) {
                    continue;
                }
                $repoAdvisories[] = $repository->getSecurityAdvisories($packageConstraintMap, $allowPartialAdvisories)['advisories'];
            } catch (\Composer\Downloader\TransportException $e) {
                if (!$ignoreUnreachable) {
                    throw $e;
                }
                $unreachableRepos[] = $e->getMessage();
            }
        }
        $advisories = count($repoAdvisories) > 0 ? array_merge_recursive([], ...$repoAdvisories) : [];
        ksort($advisories);
        return $advisories;
    }
    /**
     * @return array[] an array with the provider name as key and value of array('name' => '...', 'description' => '...', 'type' => '...')
     * @phpstan-return array<string, array{name: string, description: string|null, type: string}>
     */
    public function getProviders(string $packageName): array
    {
        $providers = [];
        foreach ($this->repositories as $repository) {
            if ($repoProviders = $repository->getProviders($packageName)) {
                $providers = array_merge($providers, $repoProviders);
            }
        }
        return $providers;
    }
    /**
     * Check for each given package name whether it would be accepted by this RepositorySet in the given $stability
     *
     * @param string[] $names
     * @param key-of<BasePackage::STABILITIES> $stability one of 'stable', 'RC', 'beta', 'alpha' or 'dev'
     */
    public function isPackageAcceptable(array $names, string $stability): bool
    {
        return StabilityFilter::isPackageAcceptable($this->acceptableStabilities, $this->stabilityFlags, $names, $stability);
    }
    /**
     * Create a pool for dependency resolution from the packages in this repository set.
     *
     * @param list<string>      $ignoredTypes Packages of those types are ignored
     * @param list<string>|null $allowedTypes Only packages of those types are allowed if set to non-null
     */
    public function createPool(Request $request, IOInterface $io, ?EventDispatcher $eventDispatcher = null, ?PoolOptimizer $poolOptimizer = null, array $ignoredTypes = [], ?array $allowedTypes = null, ?SecurityAdvisoryPoolFilter $securityAdvisoryPoolFilter = null): Pool
    {
        $poolBuilder = new PoolBuilder($this->acceptableStabilities, $this->stabilityFlags, $this->rootAliases, $this->rootReferences, $io, $eventDispatcher, $poolOptimizer, $this->temporaryConstraints, $securityAdvisoryPoolFilter);
        $poolBuilder->setIgnoredTypes($ignoredTypes);
        $poolBuilder->setAllowedTypes($allowedTypes);
        foreach ($this->repositories as $repo) {
            if (($repo instanceof \Composer\Repository\InstalledRepositoryInterface || $repo instanceof \Composer\Repository\InstalledRepository) && !$this->allowInstalledRepositories) {
                throw new \LogicException('The pool can not accept packages from an installed repository');
            }
        }
        $this->locked = \true;
        return $poolBuilder->buildPool($this->repositories, $request);
    }
    /**
     * Create a pool for dependency resolution from the packages in this repository set.
     */
    public function createPoolWithAllPackages(): Pool
    {
        foreach ($this->repositories as $repo) {
            if (($repo instanceof \Composer\Repository\InstalledRepositoryInterface || $repo instanceof \Composer\Repository\InstalledRepository) && !$this->allowInstalledRepositories) {
                throw new \LogicException('The pool can not accept packages from an installed repository');
            }
        }
        $this->locked = \true;
        $packages = [];
        foreach ($this->repositories as $repository) {
            foreach ($repository->getPackages() as $package) {
                $packages[] = $package;
                if (isset($this->rootAliases[$package->getName()][$package->getVersion()])) {
                    $alias = $this->rootAliases[$package->getName()][$package->getVersion()];
                    while ($package instanceof AliasPackage) {
                        $package = $package->getAliasOf();
                    }
                    if ($package instanceof CompletePackage) {
                        $aliasPackage = new CompleteAliasPackage($package, $alias['alias_normalized'], $alias['alias']);
                    } else {
                        $aliasPackage = new AliasPackage($package, $alias['alias_normalized'], $alias['alias']);
                    }
                    $aliasPackage->setRootPackageAlias(\true);
                    $packages[] = $aliasPackage;
                }
            }
        }
        return new Pool($packages);
    }
    public function createPoolForPackage(string $packageName, ?\Composer\Repository\LockArrayRepository $lockedRepo = null): Pool
    {
        // TODO unify this with above in some simpler version without "request"?
        return $this->createPoolForPackages([$packageName], $lockedRepo);
    }
    /**
     * @param string[] $packageNames
     */
    public function createPoolForPackages(array $packageNames, ?\Composer\Repository\LockArrayRepository $lockedRepo = null): Pool
    {
        $request = new Request($lockedRepo);
        $allowedPackages = [];
        foreach ($packageNames as $packageName) {
            if (\Composer\Repository\PlatformRepository::isPlatformPackage($packageName)) {
                throw new \LogicException('createPoolForPackage(s) can not be used for platform packages, as they are never loaded by the PoolBuilder which expects them to be fixed. Use createPoolWithAllPackages or pass in a proper request with the platform packages you need fixed in it.');
            }
            $request->requireName($packageName);
            $allowedPackages[] = strtolower($packageName);
        }
        if (count($allowedPackages) > 0) {
            $request->restrictPackages($allowedPackages);
        }
        return $this->createPool($request, new NullIO());
    }
    /**
     * @param array[] $aliases
     * @phpstan-param list<array{package: string, version: string, alias: string, alias_normalized: string}> $aliases
     *
     * @return array<string, array<string, array{alias: string, alias_normalized: string}>>
     */
    private static function getRootAliasesPerPackage(array $aliases): array
    {
        $normalizedAliases = [];
        foreach ($aliases as $alias) {
            $normalizedAliases[$alias['package']][$alias['version']] = ['alias' => $alias['alias'], 'alias_normalized' => $alias['alias_normalized']];
        }
        return $normalizedAliases;
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer\Repository;

use Composer\IO\IOInterface;
use Composer\Json\JsonFile;
use Composer\Package\BasePackage;
use Composer\Package\Loader\ArrayLoader;
use Composer\Package\Loader\LoaderInterface;
use Composer\Util\Platform;
use Composer\Util\Tar;
use Composer\Util\Zip;
/**
 * @author Serge Smertin <serg.smertin@gmail.com>
 */
class ArtifactRepository extends \Composer\Repository\ArrayRepository implements \Composer\Repository\ConfigurableRepositoryInterface
{
    /** @var LoaderInterface */
    protected $loader;
    /** @var string */
    protected $lookup;
    /** @var array{url: string} */
    protected $repoConfig;
    /** @var IOInterface */
    private $io;
    /**
     * @param array{url: string} $repoConfig
     */
    public function __construct(array $repoConfig, IOInterface $io)
    {
        parent::__construct();
        if (!extension_loaded('zip')) {
            throw new \RuntimeException('The artifact repository requires PHP\'s zip extension');
        }
        $this->loader = new ArrayLoader();
        $this->lookup = Platform::expandPath($repoConfig['url']);
        $this->io = $io;
        $this->repoConfig = $repoConfig;
    }
    public function getRepoName()
    {
        return 'artifact repo (' . $this->lookup . ')';
    }
    public function getRepoConfig()
    {
        return $this->repoConfig;
    }
    protected function initialize()
    {
        parent::initialize();
        $this->scanDirectory($this->lookup);
    }
    private function scanDirectory(string $path): void
    {
        $io = $this->io;
        $directory = new \RecursiveDirectoryIterator($path, \RecursiveDirectoryIterator::FOLLOW_SYMLINKS);
        $iterator = new \RecursiveIteratorIterator($directory);
        $regex = new \RegexIterator($iterator, '/^.+\.(zip|tar|gz|tgz)$/i');
        foreach ($regex as $file) {
            /* @var $file \SplFileInfo */
            if (!$file->isFile()) {
                continue;
            }
            $package = $this->getComposerInformation($file);
            if (!$package) {
                $io->writeError("File <comment>{$file->getBasename()}</comment> doesn't seem to hold a package", \true, IOInterface::VERBOSE);
                continue;
            }
            $template = 'Found package <info>%s</info> (<comment>%s</comment>) in file <info>%s</info>';
            $io->writeError(sprintf($template, $package->getName(), $package->getPrettyVersion(), $file->getBasename()), \true, IOInterface::VERBOSE);
            $this->addPackage($package);
        }
    }
    private function getComposerInformation(\SplFileInfo $file): ?BasePackage
    {
        $json = null;
        $fileType = null;
        $fileExtension = pathinfo($file->getPathname(), \PATHINFO_EXTENSION);
        if (in_array($fileExtension, ['gz', 'tar', 'tgz'], \true)) {
            $fileType = 'tar';
        } elseif ($fileExtension === 'zip') {
            $fileType = 'zip';
        } else {
            throw new \RuntimeException('Files with "' . $fileExtension . '" extensions aren\'t supported. Only ZIP and TAR/TAR.GZ/TGZ archives are supported.');
        }
        try {
            if ($fileType === 'tar') {
                $json = Tar::getComposerJson($file->getPathname());
            } else {
                $json = Zip::getComposerJson($file->getPathname());
            }
        } catch (\Exception $exception) {
            $this->io->write('Failed loading package ' . $file->getPathname() . ': ' . $exception->getMessage(), \false, IOInterface::VERBOSE);
        }
        if (null === $json) {
            return null;
        }
        $package = JsonFile::parseJson($json, $file->getPathname() . '#composer.json');
        $package['dist'] = ['type' => $fileType, 'url' => strtr($file->getPathname(), '\\', '/'), 'shasum' => hash_file('sha1', $file->getRealPath())];
        try {
            $package = $this->loader->load($package);
        } catch (\UnexpectedValueException $e) {
            throw new \UnexpectedValueException('Failed loading package in ' . $file . ': ' . $e->getMessage(), 0, $e);
        }
        return $package;
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer\Repository;

use Composer\Package\RootPackageInterface;
/**
 * Root package repository.
 *
 * This is used for serving the RootPackage inside an in-memory InstalledRepository
 *
 * @author Jordi Boggiano <j.boggiano@seld.be>
 */
class RootPackageRepository extends \Composer\Repository\ArrayRepository
{
    public function __construct(RootPackageInterface $package)
    {
        parent::__construct([$package]);
    }
    public function getRepoName(): string
    {
        return 'root package repo';
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer\Repository;

use Composer\IO\IOInterface;
use Composer\Config;
use Composer\EventDispatcher\EventDispatcher;
use Composer\Package\PackageInterface;
use Composer\Util\HttpDownloader;
use Composer\Util\ProcessExecutor;
/**
 * Repositories manager.
 *
 * @author Jordi Boggiano <j.boggiano@seld.be>
 * @author Konstantin Kudryashov <ever.zet@gmail.com>
 * @author François Pluchino <francois.pluchino@opendisplay.com>
 */
class RepositoryManager
{
    /** @var InstalledRepositoryInterface */
    private $localRepository;
    /** @var list<RepositoryInterface> */
    private $repositories = [];
    /** @var array<string, class-string<RepositoryInterface>> */
    private $repositoryClasses = [];
    /** @var IOInterface */
    private $io;
    /** @var Config */
    private $config;
    /** @var HttpDownloader */
    private $httpDownloader;
    /** @var ?EventDispatcher */
    private $eventDispatcher;
    /** @var ProcessExecutor */
    private $process;
    public function __construct(IOInterface $io, Config $config, HttpDownloader $httpDownloader, ?EventDispatcher $eventDispatcher = null, ?ProcessExecutor $process = null)
    {
        $this->io = $io;
        $this->config = $config;
        $this->httpDownloader = $httpDownloader;
        $this->eventDispatcher = $eventDispatcher;
        $this->process = $process ?? new ProcessExecutor($io);
    }
    /**
     * Searches for a package by its name and version in managed repositories.
     *
     * @param string                                                 $name       package name
     * @param string|\Composer\Semver\Constraint\ConstraintInterface $constraint package version or version constraint to match against
     */
    public function findPackage(string $name, $constraint): ?PackageInterface
    {
        foreach ($this->repositories as $repository) {
            /** @var RepositoryInterface $repository */
            if ($package = $repository->findPackage($name, $constraint)) {
                return $package;
            }
        }
        return null;
    }
    /**
     * Searches for all packages matching a name and optionally a version in managed repositories.
     *
     * @param string                                                 $name       package name
     * @param string|\Composer\Semver\Constraint\ConstraintInterface $constraint package version or version constraint to match against
     *
     * @return PackageInterface[]
     */
    public function findPackages(string $name, $constraint): array
    {
        $packages = [];
        foreach ($this->getRepositories() as $repository) {
            $packages = array_merge($packages, $repository->findPackages($name, $constraint));
        }
        return $packages;
    }
    /**
     * Adds repository
     *
     * @param RepositoryInterface $repository repository instance
     */
    public function addRepository(\Composer\Repository\RepositoryInterface $repository): void
    {
        $this->repositories[] = $repository;
    }
    /**
     * Adds a repository to the beginning of the chain
     *
     * This is useful when injecting additional repositories that should trump Packagist, e.g. from a plugin.
     *
     * @param RepositoryInterface $repository repository instance
     */
    public function prependRepository(\Composer\Repository\RepositoryInterface $repository): void
    {
        array_unshift($this->repositories, $repository);
    }
    /**
     * Returns a new repository for a specific installation type.
     *
     * @param  string                    $type   repository type
     * @param  array<string, mixed>      $config repository configuration
     * @param  string                    $name   repository name
     * @throws \InvalidArgumentException if repository for provided type is not registered
     */
    public function createRepository(string $type, array $config, ?string $name = null): \Composer\Repository\RepositoryInterface
    {
        if (!isset($this->repositoryClasses[$type])) {
            throw new \InvalidArgumentException('Repository type is not registered: ' . $type);
        }
        if (isset($config['packagist']) && \false === $config['packagist']) {
            $this->io->writeError('<warning>Repository "' . $name . '" (' . json_encode($config) . ') has a packagist key which should be in its own repository definition</warning>');
        }
        $class = $this->repositoryClasses[$type];
        if (isset($config['only']) || isset($config['exclude']) || isset($config['canonical'])) {
            $filterConfig = $config;
            unset($config['only'], $config['exclude'], $config['canonical']);
        }
        $repository = new $class($config, $this->io, $this->config, $this->httpDownloader, $this->eventDispatcher, $this->process);
        if (isset($filterConfig)) {
            $repository = new \Composer\Repository\FilterRepository($repository, $filterConfig);
        }
        return $repository;
    }
    /**
     * Stores repository class for a specific installation type.
     *
     * @param string $type  installation type
     * @param class-string<RepositoryInterface> $class class name of the repo implementation
     */
    public function setRepositoryClass(string $type, $class): void
    {
        $this->repositoryClasses[$type] = $class;
    }
    /**
     * Returns all repositories, except local one.
     *
     * @return RepositoryInterface[]
     */
    public function getRepositories(): array
    {
        return $this->repositories;
    }
    /**
     * Sets local repository for the project.
     *
     * @param InstalledRepositoryInterface $repository repository instance
     */
    public function setLocalRepository(\Composer\Repository\InstalledRepositoryInterface $repository): void
    {
        $this->localRepository = $repository;
    }
    /**
     * Returns local repository for the project.
     */
    public function getLocalRepository(): \Composer\Repository\InstalledRepositoryInterface
    {
        return $this->localRepository;
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer\Repository\Vcs;

use Composer\Config;
use Composer\Downloader\TransportException;
use Composer\Json\JsonFile;
use Composer\Cache;
use Composer\IO\IOInterface;
use Composer\Pcre\Preg;
use Composer\Util\GitHub;
use Composer\Util\Http\Response;
/**
 * @author Jordi Boggiano <j.boggiano@seld.be>
 */
class GitHubDriver extends \Composer\Repository\Vcs\VcsDriver
{
    /** @var string */
    protected $owner;
    /** @var string */
    protected $repository;
    /** @var array<int|string, string> Map of tag name to identifier */
    protected $tags;
    /** @var array<int|string, string> Map of branch name to identifier */
    protected $branches;
    /** @var string */
    protected $rootIdentifier;
    /** @var mixed[] */
    protected $repoData;
    /** @var bool */
    protected $hasIssues = \false;
    /** @var bool */
    protected $isPrivate = \false;
    /** @var bool */
    private $isArchived = \false;
    /** @var array<int, array{type: string, url: string}>|false|null */
    private $fundingInfo;
    /** @var bool */
    private $allowGitFallback = \true;
    /**
     * Git Driver
     *
     * @var ?GitDriver
     */
    protected $gitDriver = null;
    /**
     * @inheritDoc
     */
    public function initialize(): void
    {
        if (!Preg::isMatch('#^(?:(?:https?|git)://([^/]+)/|git@([^:]+):/?)([^/]+)/([^/]+?)(?:\.git|/)?$#', $this->url, $match)) {
            throw new \InvalidArgumentException(sprintf('The GitHub repository URL %s is invalid.', $this->url));
        }
        $this->owner = $match[3];
        $this->repository = $match[4];
        $this->originUrl = strtolower($match[1] ?? (string) $match[2]);
        if ($this->originUrl === 'www.github.com') {
            $this->originUrl = 'github.com';
        }
        $this->cache = new Cache($this->io, $this->config->get('cache-repo-dir') . '/' . $this->originUrl . '/' . $this->owner . '/' . $this->repository);
        $this->cache->setReadOnly($this->config->get('cache-read-only'));
        if (isset($this->repoConfig['allow-git-fallback']) && $this->repoConfig['allow-git-fallback'] === \false) {
            $this->allowGitFallback = \false;
        }
        if ($this->config->get('use-github-api') === \false || isset($this->repoConfig['no-api']) && $this->repoConfig['no-api']) {
            $this->setupGitDriver($this->url);
            return;
        }
        $this->fetchRootIdentifier();
    }
    public function getRepositoryUrl(): string
    {
        return 'https://' . $this->originUrl . '/' . $this->owner . '/' . $this->repository;
    }
    /**
     * @inheritDoc
     */
    public function getRootIdentifier(): string
    {
        if ($this->gitDriver) {
            return $this->gitDriver->getRootIdentifier();
        }
        return $this->rootIdentifier;
    }
    /**
     * @inheritDoc
     */
    public function getUrl(): string
    {
        if ($this->gitDriver) {
            return $this->gitDriver->getUrl();
        }
        return 'https://' . $this->originUrl . '/' . $this->owner . '/' . $this->repository . '.git';
    }
    protected function getApiUrl(): string
    {
        if ('github.com' === $this->originUrl) {
            $apiUrl = 'api.github.com';
        } else {
            $apiUrl = $this->originUrl . '/api/v3';
        }
        return 'https://' . $apiUrl;
    }
    /**
     * @inheritDoc
     */
    public function getSource(string $identifier): array
    {
        if ($this->gitDriver) {
            return $this->gitDriver->getSource($identifier);
        }
        if ($this->isPrivate) {
            // Private GitHub repositories should be accessed using the
            // SSH version of the URL.
            $url = $this->generateSshUrl();
        } else {
            $url = $this->getUrl();
        }
        return ['type' => 'git', 'url' => $url, 'reference' => $identifier];
    }
    /**
     * @inheritDoc
     */
    public function getDist(string $identifier): ?array
    {
        $url = $this->getApiUrl() . '/repos/' . $this->owner . '/' . $this->repository . '/zipball/' . $identifier;
        return ['type' => 'zip', 'url' => $url, 'reference' => $identifier, 'shasum' => ''];
    }
    /**
     * @inheritDoc
     */
    public function getComposerInformation(string $identifier): ?array
    {
        if ($this->gitDriver) {
            return $this->gitDriver->getComposerInformation($identifier);
        }
        if (!isset($this->infoCache[$identifier])) {
            if ($this->shouldCache($identifier) && $res = $this->cache->read($identifier)) {
                $composer = JsonFile::parseJson($res);
            } else {
                $composer = $this->getBaseComposerInformation($identifier);
                if ($this->shouldCache($identifier)) {
                    $this->cache->write($identifier, JsonFile::encode($composer, \JSON_UNESCAPED_UNICODE | \JSON_UNESCAPED_SLASHES));
                }
            }
            if ($composer !== null) {
                // specials for github
                if (isset($composer['support']) && !is_array($composer['support'])) {
                    $composer['support'] = [];
                }
                if (!isset($composer['support']['source'])) {
                    $label = (array_search($identifier, $this->getTags()) ?: array_search($identifier, $this->getBranches())) ?: $identifier;
                    $composer['support']['source'] = sprintf('https://%s/%s/%s/tree/%s', $this->originUrl, $this->owner, $this->repository, $label);
                }
                if (!isset($composer['support']['issues']) && $this->hasIssues) {
                    $composer['support']['issues'] = sprintf('https://%s/%s/%s/issues', $this->originUrl, $this->owner, $this->repository);
                }
                if (!isset($composer['abandoned']) && $this->isArchived) {
                    $composer['abandoned'] = \true;
                }
                if (!isset($composer['funding']) && $funding = $this->getFundingInfo()) {
                    $composer['funding'] = $funding;
                }
            }
            $this->infoCache[$identifier] = $composer;
        }
        return $this->infoCache[$identifier];
    }
    /**
     * @return array<int, array{type: string, url: string}>|false
     */
    private function getFundingInfo()
    {
        if (null !== $this->fundingInfo) {
            return $this->fundingInfo;
        }
        if ($this->originUrl !== 'github.com') {
            return $this->fundingInfo = \false;
        }
        foreach ([$this->getApiUrl() . '/repos/' . $this->owner . '/' . $this->repository . '/contents/.github/FUNDING.yml', $this->getApiUrl() . '/repos/' . $this->owner . '/.github/contents/FUNDING.yml'] as $file) {
            try {
                $response = $this->httpDownloader->get($file, ['retry-auth-failure' => \false])->decodeJson();
            } catch (TransportException $e) {
                continue;
            }
            if (empty($response['content']) || $response['encoding'] !== 'base64' || !$funding = base64_decode($response['content'])) {
                continue;
            }
            break;
        }
        if (empty($funding)) {
            return $this->fundingInfo = \false;
        }
        $result = [];
        $key = null;
        foreach (Preg::split('{\r?\n}', $funding) as $line) {
            $line = trim($line);
            if (Preg::isMatchStrictGroups('{^(\w+)\s*:\s*(.+)$}', $line, $match)) {
                if ($match[2] === '[') {
                    $key = $match[1];
                    continue;
                }
                if (Preg::isMatchStrictGroups('{^\[(.*?)\](?:\s*#.*)?$}', $match[2], $match2)) {
                    foreach (array_map('trim', Preg::split('{[\'"]?\s*,\s*[\'"]?}', $match2[1])) as $item) {
                        $result[] = ['type' => $match[1], 'url' => trim($item, '"\' ')];
                    }
                } elseif (Preg::isMatchStrictGroups('{^([^#].*?)(?:\s+#.*)?$}', $match[2], $match2)) {
                    $result[] = ['type' => $match[1], 'url' => trim($match2[1], '"\' ')];
                }
                $key = null;
            } elseif (Preg::isMatchStrictGroups('{^(\w+)\s*:\s*#\s*$}', $line, $match)) {
                $key = $match[1];
            } elseif ($key !== null && (Preg::isMatchStrictGroups('{^-\s*(.+)(?:\s+#.*)?$}', $line, $match) || Preg::isMatchStrictGroups('{^(.+),(?:\s*#.*)?$}', $line, $match))) {
                $result[] = ['type' => $key, 'url' => trim($match[1], '"\' ')];
            } elseif ($key !== null && $line === ']') {
                $key = null;
            }
        }
        foreach ($result as $key => $item) {
            switch ($item['type']) {
                case 'community_bridge':
                    $result[$key]['url'] = 'https://funding.communitybridge.org/projects/' . basename($item['url']);
                    break;
                case 'github':
                    $result[$key]['url'] = 'https://github.com/' . basename($item['url']);
                    break;
                case 'issuehunt':
                    $result[$key]['url'] = 'https://issuehunt.io/r/' . $item['url'];
                    break;
                case 'ko_fi':
                    $result[$key]['url'] = 'https://ko-fi.com/' . basename($item['url']);
                    break;
                case 'liberapay':
                    $result[$key]['url'] = 'https://liberapay.com/' . basename($item['url']);
                    break;
                case 'open_collective':
                    $result[$key]['url'] = 'https://opencollective.com/' . basename($item['url']);
                    break;
                case 'patreon':
                    $result[$key]['url'] = 'https://www.patreon.com/' . basename($item['url']);
                    break;
                case 'tidelift':
                    $result[$key]['url'] = 'https://tidelift.com/funding/github/' . $item['url'];
                    break;
                case 'polar':
                    $result[$key]['url'] = 'https://polar.sh/' . basename($item['url']);
                    break;
                case 'buy_me_a_coffee':
                    $result[$key]['url'] = 'https://www.buymeacoffee.com/' . basename($item['url']);
                    break;
                case 'thanks_dev':
                    $result[$key]['url'] = 'https://thanks.dev/' . $item['url'];
                    break;
                case 'otechie':
                    $result[$key]['url'] = 'https://otechie.com/' . basename($item['url']);
                    break;
                case 'custom':
                    $bits = parse_url($item['url']);
                    if ($bits === \false) {
                        unset($result[$key]);
                        break;
                    }
                    if (!array_key_exists('scheme', $bits) && !array_key_exists('host', $bits)) {
                        if (Preg::isMatch('{^[a-z0-9-]++\.[a-z]{2,3}$}', $item['url'])) {
                            $result[$key]['url'] = 'https://' . $item['url'];
                            break;
                        }
                        $this->io->writeError('<warning>Funding URL ' . $item['url'] . ' not in a supported format.</warning>');
                        unset($result[$key]);
                        break;
                    }
                    break;
            }
        }
        return $this->fundingInfo = $result;
    }
    /**
     * @inheritDoc
     */
    public function getFileContent(string $file, string $identifier): ?string
    {
        if ($this->gitDriver) {
            return $this->gitDriver->getFileContent($file, $identifier);
        }
        $resource = $this->getApiUrl() . '/repos/' . $this->owner . '/' . $this->repository . '/contents/' . $file . '?ref=' . urlencode($identifier);
        $resource = $this->getContents($resource)->decodeJson();
        // The GitHub contents API only returns files up to 1MB as base64 encoded files
        // larger files either need be fetched with a raw accept header or by using the git blob endpoint
        if ((!isset($resource['content']) || $resource['content'] === '') && $resource['encoding'] === 'none' && isset($resource['git_url'])) {
            $resource = $this->getContents($resource['git_url'])->decodeJson();
        }
        if (!isset($resource['content']) || $resource['encoding'] !== 'base64' || \false === $content = base64_decode($resource['content'])) {
            throw new \RuntimeException('Could not retrieve ' . $file . ' for ' . $identifier);
        }
        return $content;
    }
    /**
     * @inheritDoc
     */
    public function getChangeDate(string $identifier): ?\DateTimeImmutable
    {
        if ($this->gitDriver) {
            return $this->gitDriver->getChangeDate($identifier);
        }
        $resource = $this->getApiUrl() . '/repos/' . $this->owner . '/' . $this->repository . '/commits/' . urlencode($identifier);
        $commit = $this->getContents($resource)->decodeJson();
        return new \DateTimeImmutable($commit['commit']['committer']['date']);
    }
    /**
     * @inheritDoc
     */
    public function getTags(): array
    {
        if ($this->gitDriver) {
            return $this->gitDriver->getTags();
        }
        if (null === $this->tags) {
            $tags = [];
            $resource = $this->getApiUrl() . '/repos/' . $this->owner . '/' . $this->repository . '/tags?per_page=100';
            do {
                $response = $this->getContents($resource);
                $tagsData = $response->decodeJson();
                foreach ($tagsData as $tag) {
                    $tags[$tag['name']] = $tag['commit']['sha'];
                }
                $resource = $this->getNextPage($response);
            } while ($resource);
            $this->tags = $tags;
        }
        return $this->tags;
    }
    /**
     * @inheritDoc
     */
    public function getBranches(): array
    {
        if ($this->gitDriver) {
            return $this->gitDriver->getBranches();
        }
        if (null === $this->branches) {
            $branches = [];
            $resource = $this->getApiUrl() . '/repos/' . $this->owner . '/' . $this->repository . '/git/refs/heads?per_page=100';
            do {
                $response = $this->getContents($resource);
                $branchData = $response->decodeJson();
                foreach ($branchData as $branch) {
                    $name = substr($branch['ref'], 11);
                    if ($name !== 'gh-pages') {
                        $branches[$name] = $branch['object']['sha'];
                    }
                }
                $resource = $this->getNextPage($response);
            } while ($resource);
            $this->branches = $branches;
        }
        return $this->branches;
    }
    /**
     * @inheritDoc
     */
    public static function supports(IOInterface $io, Config $config, string $url, bool $deep = \false): bool
    {
        if (!Preg::isMatch('#^((?:https?|git)://([^/]+)/|git@([^:]+):/?)([^/]+)/([^/]+?)(?:\.git|/)?$#', $url, $matches)) {
            return \false;
        }
        $originUrl = $matches[2] ?? (string) $matches[3];
        if (!in_array(strtolower(Preg::replace('{^www\.}i', '', $originUrl)), $config->get('github-domains'))) {
            return \false;
        }
        if (!extension_loaded('openssl')) {
            $io->writeError('Skipping GitHub driver for ' . $url . ' because the OpenSSL PHP extension is missing.', \true, IOInterface::VERBOSE);
            return \false;
        }
        return \true;
    }
    /**
     * Gives back the loaded <github-api>/repos/<owner>/<repo> result
     *
     * @return mixed[]|null
     */
    public function getRepoData(): ?array
    {
        $this->fetchRootIdentifier();
        return $this->repoData;
    }
    /**
     * Generate an SSH URL
     */
    protected function generateSshUrl(): string
    {
        if (\false !== strpos($this->originUrl, ':')) {
            return 'ssh://git@' . $this->originUrl . '/' . $this->owner . '/' . $this->repository . '.git';
        }
        return 'git@' . $this->originUrl . ':' . $this->owner . '/' . $this->repository . '.git';
    }
    /**
     * @inheritDoc
     */
    protected function getContents(string $url, bool $fetchingRepoData = \false): Response
    {
        try {
            return parent::getContents($url);
        } catch (TransportException $e) {
            $gitHubUtil = new GitHub($this->io, $this->config, $this->process, $this->httpDownloader);
            switch ($e->getCode()) {
                case 401:
                case 404:
                    // try to authorize only if we are fetching the main /repos/foo/bar data, otherwise it must be a real 404
                    if (!$fetchingRepoData) {
                        throw $e;
                    }
                    if ($gitHubUtil->authorizeOAuth($this->originUrl)) {
                        return parent::getContents($url);
                    }
                    if (!$this->io->isInteractive()) {
                        $this->attemptCloneFallback($e);
                        return new Response(['url' => 'dummy'], 200, [], 'null');
                    }
                    $scopesIssued = [];
                    $scopesNeeded = [];
                    if ($headers = $e->getHeaders()) {
                        if ($scopes = Response::findHeaderValue($headers, 'X-OAuth-Scopes')) {
                            $scopesIssued = explode(' ', $scopes);
                        }
                        if ($scopes = Response::findHeaderValue($headers, 'X-Accepted-OAuth-Scopes')) {
                            $scopesNeeded = explode(' ', $scopes);
                        }
                    }
                    $scopesFailed = array_diff($scopesNeeded, $scopesIssued);
                    // non-authenticated requests get no scopesNeeded, so ask for credentials
                    // authenticated requests which failed some scopes should ask for new credentials too
                    if (!$headers || !count($scopesNeeded) || count($scopesFailed)) {
                        $gitHubUtil->authorizeOAuthInteractively($this->originUrl, 'Your GitHub credentials are required to fetch private repository metadata (<info>' . $this->url . '</info>)');
                    }
                    return parent::getContents($url);
                case 403:
                    if (!$this->io->hasAuthentication($this->originUrl) && $gitHubUtil->authorizeOAuth($this->originUrl)) {
                        return parent::getContents($url);
                    }
                    if (!$this->io->isInteractive() && $fetchingRepoData) {
                        $this->attemptCloneFallback($e);
                        return new Response(['url' => 'dummy'], 200, [], 'null');
                    }
                    $rateLimited = $gitHubUtil->isRateLimited((array) $e->getHeaders());
                    if (!$this->io->hasAuthentication($this->originUrl)) {
                        if (!$this->io->isInteractive()) {
                            $this->io->writeError('<error>GitHub API limit exhausted. Failed to get metadata for the ' . $this->url . ' repository, try running in interactive mode so that you can enter your GitHub credentials to increase the API limit</error>');
                            throw $e;
                        }
                        $gitHubUtil->authorizeOAuthInteractively($this->originUrl, 'API limit exhausted. Enter your GitHub credentials to get a larger API limit (<info>' . $this->url . '</info>)');
                        return parent::getContents($url);
                    }
                    if ($rateLimited) {
                        $rateLimit = $gitHubUtil->getRateLimit($e->getHeaders());
                        $this->io->writeError(sprintf('<error>GitHub API limit (%d calls/hr) is exhausted. You are already authorized so you have to wait until %s before doing more requests</error>', $rateLimit['limit'], $rateLimit['reset']));
                    }
                    throw $e;
                default:
                    throw $e;
            }
        }
    }
    /**
     * Fetch root identifier from GitHub
     *
     * @throws TransportException
     */
    protected function fetchRootIdentifier(): void
    {
        if ($this->repoData) {
            return;
        }
        $repoDataUrl = $this->getApiUrl() . '/repos/' . $this->owner . '/' . $this->repository;
        try {
            $this->repoData = $this->getContents($repoDataUrl, \true)->decodeJson();
        } catch (TransportException $e) {
            if ($e->getCode() === 499) {
                $this->attemptCloneFallback($e);
            } else {
                throw $e;
            }
        }
        if (null === $this->repoData && null !== $this->gitDriver) {
            return;
        }
        $this->owner = $this->repoData['owner']['login'];
        $this->repository = $this->repoData['name'];
        $this->isPrivate = !empty($this->repoData['private']);
        if (isset($this->repoData['default_branch'])) {
            $this->rootIdentifier = $this->repoData['default_branch'];
        } elseif (isset($this->repoData['master_branch'])) {
            $this->rootIdentifier = $this->repoData['master_branch'];
        } else {
            $this->rootIdentifier = 'master';
        }
        $this->hasIssues = !empty($this->repoData['has_issues']);
        $this->isArchived = !empty($this->repoData['archived']);
    }
    /**
     * @phpstan-impure
     *
     * @return true
     * @throws \RuntimeException
     */
    protected function attemptCloneFallback(?\Throwable $e = null): bool
    {
        if (!$this->allowGitFallback) {
            throw new \RuntimeException('Fallback to git driver disabled', 0, $e);
        }
        $this->isPrivate = \true;
        try {
            // If this repository may be private (hard to say for sure,
            // GitHub returns 404 for private repositories) and we
            // cannot ask for authentication credentials (because we
            // are not interactive) then we fallback to GitDriver.
            $this->setupGitDriver($this->generateSshUrl());
            return \true;
        } catch (\RuntimeException $e) {
            $this->gitDriver = null;
            $this->io->writeError('<error>Failed to clone the ' . $this->generateSshUrl() . ' repository, try running in interactive mode so that you can enter your GitHub credentials</error>');
            throw $e;
        }
    }
    protected function setupGitDriver(string $url): void
    {
        if (!$this->allowGitFallback) {
            throw new \RuntimeException('Fallback to git driver disabled');
        }
        $this->gitDriver = new \Composer\Repository\Vcs\GitDriver(['url' => $url], $this->io, $this->config, $this->httpDownloader, $this->process);
        $this->gitDriver->initialize();
    }
    protected function getNextPage(Response $response): ?string
    {
        $header = $response->getHeader('link');
        if (!$header) {
            return null;
        }
        $links = explode(',', $header);
        foreach ($links as $link) {
            if (Preg::isMatch('{<(.+?)>; *rel="next"}', $link, $match)) {
                return $match[1];
            }
        }
        return null;
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer\Repository\Vcs;

use Composer\Cache;
use Composer\Downloader\TransportException;
use Composer\Config;
use Composer\IO\IOInterface;
use Composer\Json\JsonFile;
use Composer\Pcre\Preg;
use Composer\Util\ProcessExecutor;
use Composer\Util\HttpDownloader;
use Composer\Util\Filesystem;
use Composer\Util\Http\Response;
/**
 * A driver implementation for driver with authentication interaction.
 *
 * @author François Pluchino <francois.pluchino@opendisplay.com>
 */
abstract class VcsDriver implements \Composer\Repository\Vcs\VcsDriverInterface
{
    /** @var string */
    protected $url;
    /** @var string */
    protected $originUrl;
    /** @var array<string, mixed> */
    protected $repoConfig;
    /** @var IOInterface */
    protected $io;
    /** @var Config */
    protected $config;
    /** @var ProcessExecutor */
    protected $process;
    /** @var HttpDownloader */
    protected $httpDownloader;
    /** @var array<int|string, mixed> */
    protected $infoCache = [];
    /** @var ?Cache */
    protected $cache;
    /**
     * Constructor.
     *
     * @param array{url: string}&array<string, mixed>           $repoConfig     The repository configuration
     * @param IOInterface     $io             The IO instance
     * @param Config          $config         The composer configuration
     * @param HttpDownloader  $httpDownloader Remote Filesystem, injectable for mocking
     * @param ProcessExecutor $process        Process instance, injectable for mocking
     */
    final public function __construct(array $repoConfig, IOInterface $io, Config $config, HttpDownloader $httpDownloader, ProcessExecutor $process)
    {
        if (Filesystem::isLocalPath($repoConfig['url'])) {
            $repoConfig['url'] = Filesystem::getPlatformPath($repoConfig['url']);
        }
        $this->url = $repoConfig['url'];
        $this->originUrl = $repoConfig['url'];
        $this->repoConfig = $repoConfig;
        $this->io = $io;
        $this->config = $config;
        $this->httpDownloader = $httpDownloader;
        $this->process = $process;
    }
    /**
     * Returns whether or not the given $identifier should be cached or not.
     * @phpstan-assert-if-true !null $this->cache
     */
    protected function shouldCache(string $identifier): bool
    {
        return $this->cache && Preg::isMatch('{^[a-f0-9]{40}$}iD', $identifier);
    }
    /**
     * @inheritDoc
     */
    public function getComposerInformation(string $identifier): ?array
    {
        if (!isset($this->infoCache[$identifier])) {
            if ($this->shouldCache($identifier) && $res = $this->cache->read($identifier)) {
                return $this->infoCache[$identifier] = JsonFile::parseJson($res);
            }
            $composer = $this->getBaseComposerInformation($identifier);
            if ($this->shouldCache($identifier)) {
                $this->cache->write($identifier, JsonFile::encode($composer, \JSON_UNESCAPED_UNICODE | \JSON_UNESCAPED_SLASHES));
            }
            $this->infoCache[$identifier] = $composer;
        }
        return $this->infoCache[$identifier];
    }
    /**
     * @return array<mixed>|null
     */
    protected function getBaseComposerInformation(string $identifier): ?array
    {
        $composerFileContent = $this->getFileContent('composer.json', $identifier);
        if (!$composerFileContent) {
            return null;
        }
        $composer = JsonFile::parseJson($composerFileContent, $identifier . ':composer.json');
        if ([] === $composer || !is_array($composer)) {
            return null;
        }
        if (empty($composer['time']) && null !== $changeDate = $this->getChangeDate($identifier)) {
            $composer['time'] = $changeDate->format(\DATE_RFC3339);
        }
        return $composer;
    }
    /**
     * @inheritDoc
     */
    public function hasComposerFile(string $identifier): bool
    {
        try {
            return null !== $this->getComposerInformation($identifier);
        } catch (TransportException $e) {
        }
        return \false;
    }
    /**
     * Get the https or http protocol depending on SSL support.
     *
     * Call this only if you know that the server supports both.
     *
     * @return string The correct type of protocol
     */
    protected function getScheme(): string
    {
        if (extension_loaded('openssl')) {
            return 'https';
        }
        return 'http';
    }
    /**
     * Get the remote content.
     *
     * @param string $url The URL of content
     *
     * @throws TransportException
     */
    protected function getContents(string $url): Response
    {
        $options = $this->repoConfig['options'] ?? [];
        return $this->httpDownloader->get($url, $options);
    }
    /**
     * @inheritDoc
     */
    public function cleanup(): void
    {
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer\Repository\Vcs;

use Composer\Cache;
use Composer\Config;
use Composer\Json\JsonFile;
use Composer\Pcre\Preg;
use Composer\Util\ProcessExecutor;
use Composer\Util\Filesystem;
use Composer\Util\Url;
use Composer\Util\Svn as SvnUtil;
use Composer\IO\IOInterface;
use Composer\Downloader\TransportException;
/**
 * @author Jordi Boggiano <j.boggiano@seld.be>
 * @author Till Klampaeckel <till@php.net>
 */
class SvnDriver extends \Composer\Repository\Vcs\VcsDriver
{
    /** @var string */
    protected $baseUrl;
    /** @var array<int|string, string> Map of tag name to identifier */
    protected $tags;
    /** @var array<int|string, string> Map of branch name to identifier */
    protected $branches;
    /** @var ?string */
    protected $rootIdentifier;
    /** @var string|false */
    protected $trunkPath = 'trunk';
    /** @var string */
    protected $branchesPath = 'branches';
    /** @var string */
    protected $tagsPath = 'tags';
    /** @var string */
    protected $packagePath = '';
    /** @var bool */
    protected $cacheCredentials = \true;
    /**
     * @var SvnUtil
     */
    private $util;
    /**
     * @inheritDoc
     */
    public function initialize(): void
    {
        $this->url = $this->baseUrl = rtrim(self::normalizeUrl($this->url), '/');
        SvnUtil::cleanEnv();
        if (isset($this->repoConfig['trunk-path'])) {
            $this->trunkPath = $this->repoConfig['trunk-path'];
        }
        if (isset($this->repoConfig['branches-path'])) {
            $this->branchesPath = $this->repoConfig['branches-path'];
        }
        if (isset($this->repoConfig['tags-path'])) {
            $this->tagsPath = $this->repoConfig['tags-path'];
        }
        if (array_key_exists('svn-cache-credentials', $this->repoConfig)) {
            $this->cacheCredentials = (bool) $this->repoConfig['svn-cache-credentials'];
        }
        if (isset($this->repoConfig['package-path'])) {
            $this->packagePath = '/' . trim($this->repoConfig['package-path'], '/');
        }
        if (\false !== $pos = strrpos($this->url, '/' . $this->trunkPath)) {
            $this->baseUrl = substr($this->url, 0, $pos);
        }
        $this->cache = new Cache($this->io, $this->config->get('cache-repo-dir') . '/' . Preg::replace('{[^a-z0-9.]}i', '-', Url::sanitize($this->baseUrl)));
        $this->cache->setReadOnly($this->config->get('cache-read-only'));
        $this->getBranches();
        $this->getTags();
    }
    /**
     * @inheritDoc
     */
    public function getRootIdentifier(): string
    {
        return $this->rootIdentifier ?: $this->trunkPath;
    }
    /**
     * @inheritDoc
     */
    public function getUrl(): string
    {
        return $this->url;
    }
    /**
     * @inheritDoc
     */
    public function getSource(string $identifier): array
    {
        return ['type' => 'svn', 'url' => $this->baseUrl, 'reference' => $identifier];
    }
    /**
     * @inheritDoc
     */
    public function getDist(string $identifier): ?array
    {
        return null;
    }
    /**
     * @inheritDoc
     */
    protected function shouldCache(string $identifier): bool
    {
        return $this->cache && Preg::isMatch('{@\d+$}', $identifier);
    }
    /**
     * @inheritDoc
     */
    public function getComposerInformation(string $identifier): ?array
    {
        if (!isset($this->infoCache[$identifier])) {
            if ($this->shouldCache($identifier) && $res = $this->cache->read($identifier . '.json')) {
                // old cache files had '' stored instead of null due to af3783b5f40bae32a23e353eaf0a00c9b8ce82e2, so we make sure here that we always return null or array
                // and fix outdated invalid cache files
                if ($res === '""') {
                    $res = 'null';
                    $this->cache->write($identifier . '.json', $res);
                }
                return $this->infoCache[$identifier] = JsonFile::parseJson($res);
            }
            try {
                $composer = $this->getBaseComposerInformation($identifier);
            } catch (TransportException $e) {
                $message = $e->getMessage();
                if (stripos($message, 'path not found') === \false && stripos($message, 'svn: warning: W160013') === \false) {
                    throw $e;
                }
                // remember a not-existent composer.json
                $composer = null;
            }
            if ($this->shouldCache($identifier)) {
                $this->cache->write($identifier . '.json', JsonFile::encode($composer, \JSON_UNESCAPED_UNICODE | \JSON_UNESCAPED_SLASHES));
            }
            $this->infoCache[$identifier] = $composer;
        }
        // old cache files had '' stored instead of null due to af3783b5f40bae32a23e353eaf0a00c9b8ce82e2, so we make sure here that we always return null or array
        if (!is_array($this->infoCache[$identifier])) {
            return null;
        }
        return $this->infoCache[$identifier];
    }
    public function getFileContent(string $file, string $identifier): ?string
    {
        $identifier = '/' . trim($identifier, '/') . '/';
        if (Preg::isMatch('{^(.+?)(@\d+)?/$}', $identifier, $match) && $match[2] !== null) {
            $path = $match[1];
            $rev = $match[2];
        } else {
            $path = $identifier;
            $rev = '';
        }
        try {
            $resource = $path . $file;
            $output = $this->execute(['svn', 'cat'], $this->baseUrl . $resource . $rev);
            if ('' === trim($output)) {
                return null;
            }
        } catch (\RuntimeException $e) {
            throw new TransportException($e->getMessage());
        }
        return $output;
    }
    /**
     * @inheritDoc
     */
    public function getChangeDate(string $identifier): ?\DateTimeImmutable
    {
        $identifier = '/' . trim($identifier, '/') . '/';
        if (Preg::isMatch('{^(.+?)(@\d+)?/$}', $identifier, $match) && null !== $match[2]) {
            $path = $match[1];
            $rev = $match[2];
        } else {
            $path = $identifier;
            $rev = '';
        }
        $output = $this->execute(['svn', 'info'], $this->baseUrl . $path . $rev);
        foreach ($this->process->splitLines($output) as $line) {
            if ($line !== '' && Preg::isMatchStrictGroups('{^Last Changed Date: ([^(]+)}', $line, $match)) {
                return new \DateTimeImmutable($match[1], new \DateTimeZone('UTC'));
            }
        }
        return null;
    }
    /**
     * @inheritDoc
     */
    public function getTags(): array
    {
        if (null === $this->tags) {
            $tags = [];
            if ($this->tagsPath !== \false) {
                $output = $this->execute(['svn', 'ls', '--verbose'], $this->baseUrl . '/' . $this->tagsPath);
                if ($output !== '') {
                    $lastRev = 0;
                    foreach ($this->process->splitLines($output) as $line) {
                        $line = trim($line);
                        if ($line !== '' && Preg::isMatch('{^\s*(\S+).*?(\S+)\s*$}', $line, $match)) {
                            if ($match[2] === './') {
                                $lastRev = (int) $match[1];
                            } else {
                                $tags[rtrim($match[2], '/')] = $this->buildIdentifier('/' . $this->tagsPath . '/' . $match[2], max($lastRev, (int) $match[1]));
                            }
                        }
                    }
                }
            }
            $this->tags = $tags;
        }
        return $this->tags;
    }
    /**
     * @inheritDoc
     */
    public function getBranches(): array
    {
        if (null === $this->branches) {
            $branches = [];
            if (\false === $this->trunkPath) {
                $trunkParent = $this->baseUrl . '/';
            } else {
                $trunkParent = $this->baseUrl . '/' . $this->trunkPath;
            }
            $output = $this->execute(['svn', 'ls', '--verbose'], $trunkParent);
            if ($output !== '') {
                foreach ($this->process->splitLines($output) as $line) {
                    $line = trim($line);
                    if ($line !== '' && Preg::isMatch('{^\s*(\S+).*?(\S+)\s*$}', $line, $match)) {
                        if ($match[2] === './') {
                            $branches['trunk'] = $this->buildIdentifier('/' . $this->trunkPath, (int) $match[1]);
                            $this->rootIdentifier = $branches['trunk'];
                            break;
                        }
                    }
                }
            }
            unset($output);
            if ($this->branchesPath !== \false) {
                $output = $this->execute(['svn', 'ls', '--verbose'], $this->baseUrl . '/' . $this->branchesPath);
                if ($output !== '') {
                    $lastRev = 0;
                    foreach ($this->process->splitLines(trim($output)) as $line) {
                        $line = trim($line);
                        if ($line !== '' && Preg::isMatch('{^\s*(\S+).*?(\S+)\s*$}', $line, $match)) {
                            if ($match[2] === './') {
                                $lastRev = (int) $match[1];
                            } else {
                                $branches[rtrim($match[2], '/')] = $this->buildIdentifier('/' . $this->branchesPath . '/' . $match[2], max($lastRev, (int) $match[1]));
                            }
                        }
                    }
                }
            }
            $this->branches = $branches;
        }
        return $this->branches;
    }
    /**
     * @inheritDoc
     */
    public static function supports(IOInterface $io, Config $config, string $url, bool $deep = \false): bool
    {
        $url = self::normalizeUrl($url);
        if (Preg::isMatch('#(^svn://|^svn\+ssh://|svn\.)#i', $url)) {
            return \true;
        }
        // proceed with deep check for local urls since they are fast to process
        if (!$deep && !Filesystem::isLocalPath($url)) {
            return \false;
        }
        $process = new ProcessExecutor($io);
        $exit = $process->execute(['svn', 'info', '--non-interactive', '--', $url], $ignoredOutput);
        if ($exit === 0) {
            // This is definitely a Subversion repository.
            return \true;
        }
        // Subversion client 1.7 and older
        if (\false !== stripos($process->getErrorOutput(), 'authorization failed:')) {
            // This is likely a remote Subversion repository that requires
            // authentication. We will handle actual authentication later.
            return \true;
        }
        // Subversion client 1.8 and newer
        if (\false !== stripos($process->getErrorOutput(), 'Authentication failed')) {
            // This is likely a remote Subversion or newer repository that requires
            // authentication. We will handle actual authentication later.
            return \true;
        }
        return \false;
    }
    /**
     * An absolute path (leading '/') is converted to a file:// url.
     */
    protected static function normalizeUrl(string $url): string
    {
        $fs = new Filesystem();
        if ($fs->isAbsolutePath($url)) {
            return 'file://' . strtr($url, '\\', '/');
        }
        return $url;
    }
    /**
     * Execute an SVN command and try to fix up the process with credentials
     * if necessary.
     *
     * @param  non-empty-list<string> $command The svn command to run.
     * @param  string            $url     The SVN URL.
     * @throws \RuntimeException
     */
    protected function execute(array $command, string $url): string
    {
        if (null === $this->util) {
            $this->util = new SvnUtil($this->baseUrl, $this->io, $this->config, $this->process);
            $this->util->setCacheCredentials($this->cacheCredentials);
        }
        try {
            return $this->util->execute($command, $url);
        } catch (\RuntimeException $e) {
            if (null === $this->util->binaryVersion()) {
                throw new \RuntimeException('Failed to load ' . $this->url . ', svn was not found, check that it is installed and in your PATH env.' . "\n\n" . $this->process->getErrorOutput());
            }
            throw new \RuntimeException('Repository ' . $this->url . ' could not be processed, ' . $e->getMessage());
        }
    }
    /**
     * Build the identifier respecting "package-path" config option
     *
     * @param string $baseDir  The path to trunk/branch/tag
     * @param int $revision The revision mark to add to identifier
     */
    protected function buildIdentifier(string $baseDir, int $revision): string
    {
        return rtrim($baseDir, '/') . $this->packagePath . '/@' . $revision;
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer\Repository\Vcs;

use Composer\Cache;
use Composer\Config;
use Composer\Downloader\TransportException;
use Composer\IO\IOInterface;
use Composer\Json\JsonFile;
use Composer\Pcre\Preg;
use Composer\Util\Forgejo;
use Composer\Util\ForgejoRepositoryData;
use Composer\Util\ForgejoUrl;
use Composer\Util\Http\Response;
class ForgejoDriver extends \Composer\Repository\Vcs\VcsDriver
{
    /** @var ForgejoUrl */
    private $forgejoUrl;
    /** @var ForgejoRepositoryData */
    private $repositoryData;
    /** @var ?GitDriver */
    protected $gitDriver = null;
    /** @var array<int|string, string> Map of tag name to identifier */
    private $tags;
    /** @var array<int|string, string> Map of branch name to identifier */
    private $branches;
    public function initialize(): void
    {
        $this->forgejoUrl = ForgejoUrl::create($this->url);
        $this->originUrl = $this->forgejoUrl->originUrl;
        $this->cache = new Cache($this->io, $this->config->get('cache-repo-dir') . '/' . $this->originUrl . '/' . $this->forgejoUrl->owner . '/' . $this->forgejoUrl->repository);
        $this->cache->setReadOnly($this->config->get('cache-read-only'));
        $this->fetchRepositoryData();
    }
    public function getFileContent(string $file, string $identifier): ?string
    {
        if ($this->gitDriver !== null) {
            return $this->gitDriver->getFileContent($file, $identifier);
        }
        $resource = $this->forgejoUrl->apiUrl . '/contents/' . $file . '?ref=' . urlencode($identifier);
        $resource = $this->getContents($resource)->decodeJson();
        // The Forgejo contents API only returns files up to 1MB as base64 encoded files
        // larger files either need be fetched with a raw accept header or by using the git blob endpoint
        if ((!isset($resource['content']) || $resource['content'] === '') && $resource['encoding'] === 'none' && isset($resource['git_url'])) {
            $resource = $this->getContents($resource['git_url'])->decodeJson();
        }
        if (!isset($resource['content']) || $resource['encoding'] !== 'base64' || \false === $content = base64_decode($resource['content'], \true)) {
            throw new \RuntimeException('Could not retrieve ' . $file . ' for ' . $identifier);
        }
        return $content;
    }
    public function getChangeDate(string $identifier): ?\DateTimeImmutable
    {
        if ($this->gitDriver !== null) {
            return $this->gitDriver->getChangeDate($identifier);
        }
        $resource = $this->forgejoUrl->apiUrl . '/git/commits/' . urlencode($identifier) . '?verification=false&files=false';
        $commit = $this->getContents($resource)->decodeJson();
        return new \DateTimeImmutable($commit['commit']['committer']['date']);
    }
    public function getRootIdentifier(): string
    {
        if ($this->gitDriver !== null) {
            return $this->gitDriver->getRootIdentifier();
        }
        return $this->repositoryData->defaultBranch;
    }
    public function getBranches(): array
    {
        if ($this->gitDriver !== null) {
            return $this->gitDriver->getBranches();
        }
        if (null === $this->branches) {
            $branches = [];
            $resource = $this->forgejoUrl->apiUrl . '/branches?per_page=100';
            do {
                $response = $this->getContents($resource);
                $branchData = $response->decodeJson();
                foreach ($branchData as $branch) {
                    $branches[$branch['name']] = $branch['commit']['id'];
                }
                $resource = $this->getNextPage($response);
            } while ($resource);
            $this->branches = $branches;
        }
        return $this->branches;
    }
    public function getTags(): array
    {
        if ($this->gitDriver !== null) {
            return $this->gitDriver->getTags();
        }
        if (null === $this->tags) {
            $tags = [];
            $resource = $this->forgejoUrl->apiUrl . '/tags?per_page=100';
            do {
                $response = $this->getContents($resource);
                $tagsData = $response->decodeJson();
                foreach ($tagsData as $tag) {
                    $tags[$tag['name']] = $tag['commit']['sha'];
                }
                $resource = $this->getNextPage($response);
            } while ($resource);
            $this->tags = $tags;
        }
        return $this->tags;
    }
    public function getDist(string $identifier): ?array
    {
        $url = $this->forgejoUrl->apiUrl . '/archive/' . $identifier . '.zip';
        return ['type' => 'zip', 'url' => $url, 'reference' => $identifier, 'shasum' => ''];
    }
    public function getComposerInformation(string $identifier): ?array
    {
        if ($this->gitDriver !== null) {
            return $this->gitDriver->getComposerInformation($identifier);
        }
        if (!isset($this->infoCache[$identifier])) {
            if ($this->shouldCache($identifier) && \false !== $res = $this->cache->read($identifier)) {
                $composer = JsonFile::parseJson($res);
            } else {
                $composer = $this->getBaseComposerInformation($identifier);
                if ($this->shouldCache($identifier)) {
                    $this->cache->write($identifier, JsonFile::encode($composer, \JSON_UNESCAPED_UNICODE | \JSON_UNESCAPED_SLASHES));
                }
            }
            if ($composer !== null) {
                // specials for forgejo
                if (isset($composer['support']) && !is_array($composer['support'])) {
                    $composer['support'] = [];
                }
                if (!isset($composer['support']['source'])) {
                    if (\false !== $label = array_search($identifier, $this->getTags(), \true)) {
                        $composer['support']['source'] = $this->repositoryData->htmlUrl . '/tag/' . $label;
                    } elseif (\false !== $label = array_search($identifier, $this->getBranches(), \true)) {
                        $composer['support']['source'] = $this->repositoryData->htmlUrl . '/branch/' . $label;
                    } else {
                        $composer['support']['source'] = $this->repositoryData->htmlUrl . '/commit/' . $identifier;
                    }
                }
                if (!isset($composer['support']['issues']) && $this->repositoryData->hasIssues) {
                    $composer['support']['issues'] = $this->repositoryData->htmlUrl . '/issues';
                }
                if (!isset($composer['abandoned']) && $this->repositoryData->isArchived) {
                    $composer['abandoned'] = \true;
                }
            }
            $this->infoCache[$identifier] = $composer;
        }
        return $this->infoCache[$identifier];
    }
    public function getSource(string $identifier): array
    {
        if ($this->gitDriver !== null) {
            return $this->gitDriver->getSource($identifier);
        }
        return ['type' => 'git', 'url' => $this->getUrl(), 'reference' => $identifier];
    }
    public function getUrl(): string
    {
        if ($this->gitDriver !== null) {
            return $this->gitDriver->getUrl();
        }
        return $this->repositoryData->isPrivate ? $this->repositoryData->sshUrl : $this->repositoryData->httpCloneUrl;
    }
    public static function supports(IOInterface $io, Config $config, string $url, bool $deep = \false): bool
    {
        $forgejoUrl = ForgejoUrl::tryFrom($url);
        if ($forgejoUrl === null) {
            return \false;
        }
        if (!in_array(strtolower($forgejoUrl->originUrl), $config->get('forgejo-domains'), \true)) {
            return \false;
        }
        if (!extension_loaded('openssl')) {
            $io->writeError('Skipping Forgejo driver for ' . $url . ' because the OpenSSL PHP extension is missing.', \true, IOInterface::VERBOSE);
            return \false;
        }
        return \true;
    }
    protected function setupGitDriver(string $url): void
    {
        $this->gitDriver = new \Composer\Repository\Vcs\GitDriver(['url' => $url], $this->io, $this->config, $this->httpDownloader, $this->process);
        $this->gitDriver->initialize();
    }
    private function fetchRepositoryData(): void
    {
        if ($this->repositoryData !== null) {
            return;
        }
        $data = $this->getContents($this->forgejoUrl->apiUrl, \true)->decodeJson();
        if (null === $data && null !== $this->gitDriver) {
            return;
        }
        $this->repositoryData = ForgejoRepositoryData::fromRemoteData($data);
    }
    protected function getNextPage(Response $response): ?string
    {
        $header = $response->getHeader('link');
        if ($header === null) {
            return null;
        }
        $links = explode(',', $header);
        foreach ($links as $link) {
            if (Preg::isMatch('{<(.+?)>; *rel="next"}', $link, $match)) {
                return $match[1];
            }
        }
        return null;
    }
    protected function getContents(string $url, bool $fetchingRepoData = \false): Response
    {
        $forgejo = new Forgejo($this->io, $this->config, $this->httpDownloader);
        try {
            return parent::getContents($url);
        } catch (TransportException $e) {
            switch ($e->getCode()) {
                case 401:
                case 403:
                case 404:
                case 429:
                    if (!$fetchingRepoData) {
                        throw $e;
                    }
                    if (!$this->io->isInteractive()) {
                        $this->attemptCloneFallback();
                        return new Response(['url' => 'dummy'], 200, [], 'null');
                    }
                    if (!$this->io->hasAuthentication($this->originUrl) && $forgejo->authorizeOAuthInteractively($this->forgejoUrl->originUrl, $e->getCode() === 429 ? 'API limit exhausted. Enter your Forgejo credentials to get a larger API limit (<info>' . $this->url . '</info>)' : null)) {
                        return parent::getContents($url);
                    }
                    throw $e;
                default:
                    throw $e;
            }
        }
    }
    /**
     * @phpstan-impure
     *
     * @return true
     * @throws \RuntimeException
     */
    protected function attemptCloneFallback(): bool
    {
        try {
            // If this repository may be private (hard to say for sure,
            // Forgejo returns 404 for private repositories) and we
            // cannot ask for authentication credentials (because we
            // are not interactive) then we fallback to GitDriver.
            $this->setupGitDriver($this->forgejoUrl->generateSshUrl());
            return \true;
        } catch (\RuntimeException $e) {
            $this->gitDriver = null;
            $this->io->writeError('<error>Failed to clone the ' . $this->forgejoUrl->generateSshUrl() . ' repository, try running in interactive mode so that you can enter your Forgejo credentials</error>');
            throw $e;
        }
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer\Repository\Vcs;

use Composer\Config;
use Composer\Cache;
use Composer\Pcre\Preg;
use Composer\Util\Hg as HgUtils;
use Composer\Util\ProcessExecutor;
use Composer\Util\Filesystem;
use Composer\IO\IOInterface;
use Composer\Util\Url;
/**
 * @author Per Bernhardt <plb@webfactory.de>
 */
class HgDriver extends \Composer\Repository\Vcs\VcsDriver
{
    /** @var array<int|string, string> Map of tag name to identifier */
    protected $tags;
    /** @var array<int|string, string> Map of branch name to identifier */
    protected $branches;
    /** @var string */
    protected $rootIdentifier;
    /** @var string */
    protected $repoDir;
    /**
     * @inheritDoc
     */
    public function initialize(): void
    {
        if (Filesystem::isLocalPath($this->url)) {
            $this->repoDir = $this->url;
        } else {
            if (!Cache::isUsable($this->config->get('cache-vcs-dir'))) {
                throw new \RuntimeException('HgDriver requires a usable cache directory, and it looks like you set it to be disabled');
            }
            $cacheDir = $this->config->get('cache-vcs-dir');
            $this->repoDir = $cacheDir . '/' . Preg::replace('{[^a-z0-9]}i', '-', Url::sanitize($this->url)) . '/';
            $fs = new Filesystem();
            $fs->ensureDirectoryExists($cacheDir);
            if (!is_writable(dirname($this->repoDir))) {
                throw new \RuntimeException('Can not clone ' . $this->url . ' to access package information. The "' . $cacheDir . '" directory is not writable by the current user.');
            }
            // Ensure we are allowed to use this URL by config
            $this->config->prohibitUrlByConfig($this->url, $this->io);
            $hgUtils = new HgUtils($this->io, $this->config, $this->process);
            // update the repo if it is a valid hg repository
            if (is_dir($this->repoDir) && 0 === $this->process->execute(['hg', 'summary'], $output, $this->repoDir)) {
                if (0 !== $this->process->execute(['hg', 'pull'], $output, $this->repoDir)) {
                    $this->io->writeError('<error>Failed to update ' . $this->url . ', package information from this repository may be outdated (' . $this->process->getErrorOutput() . ')</error>');
                }
            } else {
                // clean up directory and do a fresh clone into it
                $fs->removeDirectory($this->repoDir);
                $repoDir = $this->repoDir;
                $command = static function ($url) use ($repoDir): array {
                    return ['hg', 'clone', '--noupdate', '--', $url, $repoDir];
                };
                $hgUtils->runCommand($command, $this->url, null);
            }
        }
        $this->getTags();
        $this->getBranches();
    }
    /**
     * @inheritDoc
     */
    public function getRootIdentifier(): string
    {
        if (null === $this->rootIdentifier) {
            $this->process->execute(['hg', 'tip', '--template', '{node}'], $output, $this->repoDir);
            $output = $this->process->splitLines($output);
            $this->rootIdentifier = $output[0];
        }
        return $this->rootIdentifier;
    }
    /**
     * @inheritDoc
     */
    public function getUrl(): string
    {
        return $this->url;
    }
    /**
     * @inheritDoc
     */
    public function getSource(string $identifier): array
    {
        return ['type' => 'hg', 'url' => $this->getUrl(), 'reference' => $identifier];
    }
    /**
     * @inheritDoc
     */
    public function getDist(string $identifier): ?array
    {
        return null;
    }
    /**
     * @inheritDoc
     */
    public function getFileContent(string $file, string $identifier): ?string
    {
        if (isset($identifier[0]) && $identifier[0] === '-') {
            throw new \RuntimeException('Invalid hg identifier detected. Identifier must not start with a -, given: ' . $identifier);
        }
        $resource = ['hg', 'cat', '-r', $identifier, '--', $file];
        $this->process->execute($resource, $content, $this->repoDir);
        if (!trim($content)) {
            return null;
        }
        return $content;
    }
    /**
     * @inheritDoc
     */
    public function getChangeDate(string $identifier): ?\DateTimeImmutable
    {
        if (isset($identifier[0]) && $identifier[0] === '-') {
            throw new \RuntimeException('Invalid hg identifier detected. Identifier must not start with a -, given: ' . $identifier);
        }
        $this->process->execute(['hg', 'log', '--template', '{date|rfc3339date}', '-r', $identifier], $output, $this->repoDir);
        return new \DateTimeImmutable(trim($output), new \DateTimeZone('UTC'));
    }
    /**
     * @inheritDoc
     */
    public function getTags(): array
    {
        if (null === $this->tags) {
            $tags = [];
            $this->process->execute(['hg', 'tags'], $output, $this->repoDir);
            foreach ($this->process->splitLines($output) as $tag) {
                if ($tag && Preg::isMatchStrictGroups('(^([^\s]+)\s+\d+:(.*)$)', $tag, $match)) {
                    $tags[$match[1]] = $match[2];
                }
            }
            unset($tags['tip']);
            $this->tags = $tags;
        }
        return $this->tags;
    }
    /**
     * @inheritDoc
     */
    public function getBranches(): array
    {
        if (null === $this->branches) {
            $branches = [];
            $bookmarks = [];
            $this->process->execute(['hg', 'branches'], $output, $this->repoDir);
            foreach ($this->process->splitLines($output) as $branch) {
                if ($branch && Preg::isMatchStrictGroups('(^([^\s]+)\s+\d+:([a-f0-9]+))', $branch, $match) && $match[1][0] !== '-') {
                    $branches[$match[1]] = $match[2];
                }
            }
            $this->process->execute(['hg', 'bookmarks'], $output, $this->repoDir);
            foreach ($this->process->splitLines($output) as $branch) {
                if ($branch && Preg::isMatchStrictGroups('(^(?:[\s*]*)([^\s]+)\s+\d+:(.*)$)', $branch, $match) && $match[1][0] !== '-') {
                    $bookmarks[$match[1]] = $match[2];
                }
            }
            // Branches will have preference over bookmarks
            $this->branches = array_merge($bookmarks, $branches);
        }
        return $this->branches;
    }
    /**
     * @inheritDoc
     */
    public static function supports(IOInterface $io, Config $config, string $url, bool $deep = \false): bool
    {
        if (Preg::isMatch('#(^(?:https?|ssh)://(?:[^@]+@)?bitbucket.org|https://(?:.*?)\.kilnhg.com)#i', $url)) {
            return \true;
        }
        // local filesystem
        if (Filesystem::isLocalPath($url)) {
            $url = Filesystem::getPlatformPath($url);
            if (!is_dir($url)) {
                return \false;
            }
            $process = new ProcessExecutor($io);
            // check whether there is a hg repo in that path
            if ($process->execute(['hg', 'summary'], $output, $url) === 0) {
                return \true;
            }
        }
        if (!$deep) {
            return \false;
        }
        $process = new ProcessExecutor($io);
        $exit = $process->execute(['hg', 'identify', '--', $url], $ignored);
        return $exit === 0;
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer\Repository\Vcs;

use Composer\Config;
use Composer\Cache;
use Composer\IO\IOInterface;
use Composer\Pcre\Preg;
use Composer\Util\ProcessExecutor;
use Composer\Util\Perforce;
use Composer\Util\Http\Response;
/**
 * @author Matt Whittom <Matt.Whittom@veteransunited.com>
 */
class PerforceDriver extends \Composer\Repository\Vcs\VcsDriver
{
    /** @var string */
    protected $depot;
    /** @var string */
    protected $branch;
    /** @var ?Perforce */
    protected $perforce = null;
    /**
     * @inheritDoc
     */
    public function initialize(): void
    {
        $this->depot = $this->repoConfig['depot'];
        $this->branch = '';
        if (!empty($this->repoConfig['branch'])) {
            $this->branch = $this->repoConfig['branch'];
        }
        $this->initPerforce($this->repoConfig);
        $this->perforce->p4Login();
        $this->perforce->checkStream();
        $this->perforce->writeP4ClientSpec();
        $this->perforce->connectClient();
    }
    /**
     * @param array<string, mixed> $repoConfig
     */
    private function initPerforce(array $repoConfig): void
    {
        if (!empty($this->perforce)) {
            return;
        }
        if (!Cache::isUsable($this->config->get('cache-vcs-dir'))) {
            throw new \RuntimeException('PerforceDriver requires a usable cache directory, and it looks like you set it to be disabled');
        }
        $repoDir = $this->config->get('cache-vcs-dir') . '/' . $this->depot;
        $this->perforce = Perforce::create($repoConfig, $this->getUrl(), $repoDir, $this->process, $this->io);
    }
    /**
     * @inheritDoc
     */
    public function getFileContent(string $file, string $identifier): ?string
    {
        return $this->perforce->getFileContent($file, $identifier);
    }
    /**
     * @inheritDoc
     */
    public function getChangeDate(string $identifier): ?\DateTimeImmutable
    {
        return null;
    }
    /**
     * @inheritDoc
     */
    public function getRootIdentifier(): string
    {
        return $this->branch;
    }
    /**
     * @inheritDoc
     */
    public function getBranches(): array
    {
        return $this->perforce->getBranches();
    }
    /**
     * @inheritDoc
     */
    public function getTags(): array
    {
        return $this->perforce->getTags();
    }
    /**
     * @inheritDoc
     */
    public function getDist(string $identifier): ?array
    {
        return null;
    }
    /**
     * @inheritDoc
     */
    public function getSource(string $identifier): array
    {
        return ['type' => 'perforce', 'url' => $this->repoConfig['url'], 'reference' => $identifier, 'p4user' => $this->perforce->getUser()];
    }
    /**
     * @inheritDoc
     */
    public function getUrl(): string
    {
        return $this->url;
    }
    /**
     * @inheritDoc
     */
    public function hasComposerFile(string $identifier): bool
    {
        $composerInfo = $this->perforce->getComposerInformation('//' . $this->depot . '/' . $identifier);
        return !empty($composerInfo);
    }
    /**
     * @inheritDoc
     */
    public function getContents(string $url): Response
    {
        throw new \BadMethodCallException('Not implemented/used in PerforceDriver');
    }
    /**
     * @inheritDoc
     */
    public static function supports(IOInterface $io, Config $config, string $url, bool $deep = \false): bool
    {
        if ($deep || Preg::isMatch('#\b(perforce|p4)\b#i', $url)) {
            return Perforce::checkServerExists($url, new ProcessExecutor($io));
        }
        return \false;
    }
    /**
     * @inheritDoc
     */
    public function cleanup(): void
    {
        $this->perforce->cleanupClientSpec();
        $this->perforce = null;
    }
    public function getDepot(): string
    {
        return $this->depot;
    }
    public function getBranch(): string
    {
        return $this->branch;
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer\Repository\Vcs;

use Composer\Config;
use Composer\IO\IOInterface;
use Composer\Cache;
use Composer\Downloader\TransportException;
use Composer\Json\JsonFile;
use Composer\Pcre\Preg;
use Composer\Util\Bitbucket;
use Composer\Util\Http\Response;
/**
 * @author Per Bernhardt <plb@webfactory.de>
 */
class GitBitbucketDriver extends \Composer\Repository\Vcs\VcsDriver
{
    /** @var string */
    protected $owner;
    /** @var string */
    protected $repository;
    /** @var bool */
    private $hasIssues = \false;
    /** @var ?string */
    private $rootIdentifier;
    /** @var array<int|string, string> Map of tag name to identifier */
    private $tags;
    /** @var array<int|string, string> Map of branch name to identifier */
    private $branches;
    /** @var string */
    private $branchesUrl = '';
    /** @var string */
    private $tagsUrl = '';
    /** @var string */
    private $homeUrl = '';
    /** @var string */
    private $website = '';
    /** @var string */
    private $cloneHttpsUrl = '';
    /** @var array<string, mixed> */
    private $repoData;
    /**
     * @var ?VcsDriver
     */
    protected $fallbackDriver = null;
    /** @var string|null if set either git or hg */
    private $vcsType;
    /**
     * @inheritDoc
     */
    public function initialize(): void
    {
        if (!Preg::isMatchStrictGroups('#^https?://bitbucket\.org/([^/]+)/([^/]+?)(?:\.git|/?)?$#i', $this->url, $match)) {
            throw new \InvalidArgumentException(sprintf('The Bitbucket repository URL %s is invalid. It must be the HTTPS URL of a Bitbucket repository.', $this->url));
        }
        $this->owner = $match[1];
        $this->repository = $match[2];
        $this->originUrl = 'bitbucket.org';
        $this->cache = new Cache($this->io, implode('/', [$this->config->get('cache-repo-dir'), $this->originUrl, $this->owner, $this->repository]));
        $this->cache->setReadOnly($this->config->get('cache-read-only'));
    }
    /**
     * @inheritDoc
     */
    public function getUrl(): string
    {
        if ($this->fallbackDriver) {
            return $this->fallbackDriver->getUrl();
        }
        return $this->cloneHttpsUrl;
    }
    /**
     * Attempts to fetch the repository data via the BitBucket API and
     * sets some parameters which are used in other methods
     *
     * @phpstan-impure
     */
    protected function getRepoData(): bool
    {
        $resource = sprintf('https://api.bitbucket.org/2.0/repositories/%s/%s?%s', $this->owner, $this->repository, http_build_query(['fields' => '-project,-owner'], '', '&'));
        $repoData = $this->fetchWithOAuthCredentials($resource, \true)->decodeJson();
        if ($this->fallbackDriver) {
            return \false;
        }
        $this->parseCloneUrls($repoData['links']['clone']);
        $this->hasIssues = !empty($repoData['has_issues']);
        $this->branchesUrl = $repoData['links']['branches']['href'];
        $this->tagsUrl = $repoData['links']['tags']['href'];
        $this->homeUrl = $repoData['links']['html']['href'];
        $this->website = $repoData['website'];
        $this->vcsType = $repoData['scm'];
        $this->repoData = $repoData;
        return \true;
    }
    /**
     * @inheritDoc
     */
    public function getComposerInformation(string $identifier): ?array
    {
        if ($this->fallbackDriver) {
            return $this->fallbackDriver->getComposerInformation($identifier);
        }
        if (!isset($this->infoCache[$identifier])) {
            if ($this->shouldCache($identifier) && $res = $this->cache->read($identifier)) {
                $composer = JsonFile::parseJson($res);
            } else {
                $composer = $this->getBaseComposerInformation($identifier);
                if ($this->shouldCache($identifier)) {
                    $this->cache->write($identifier, JsonFile::encode($composer, \JSON_UNESCAPED_UNICODE | \JSON_UNESCAPED_SLASHES));
                }
            }
            if ($composer !== null) {
                // specials for bitbucket
                if (isset($composer['support']) && !is_array($composer['support'])) {
                    $composer['support'] = [];
                }
                if (!isset($composer['support']['source'])) {
                    $label = (array_search($identifier, $this->getTags()) ?: array_search($identifier, $this->getBranches())) ?: $identifier;
                    if (array_key_exists($label, $tags = $this->getTags())) {
                        $hash = $tags[$label];
                    } elseif (array_key_exists($label, $branches = $this->getBranches())) {
                        $hash = $branches[$label];
                    }
                    if (!isset($hash)) {
                        $composer['support']['source'] = sprintf('https://%s/%s/%s/src', $this->originUrl, $this->owner, $this->repository);
                    } else {
                        $composer['support']['source'] = sprintf('https://%s/%s/%s/src/%s/?at=%s', $this->originUrl, $this->owner, $this->repository, $hash, $label);
                    }
                }
                if (!isset($composer['support']['issues']) && $this->hasIssues) {
                    $composer['support']['issues'] = sprintf('https://%s/%s/%s/issues', $this->originUrl, $this->owner, $this->repository);
                }
                if (!isset($composer['homepage'])) {
                    $composer['homepage'] = empty($this->website) ? $this->homeUrl : $this->website;
                }
            }
            $this->infoCache[$identifier] = $composer;
        }
        return $this->infoCache[$identifier];
    }
    /**
     * @inheritDoc
     */
    public function getFileContent(string $file, string $identifier): ?string
    {
        if ($this->fallbackDriver) {
            return $this->fallbackDriver->getFileContent($file, $identifier);
        }
        if (strpos($identifier, '/') !== \false) {
            $branches = $this->getBranches();
            if (isset($branches[$identifier])) {
                $identifier = $branches[$identifier];
            }
        }
        $resource = sprintf('https://api.bitbucket.org/2.0/repositories/%s/%s/src/%s/%s', $this->owner, $this->repository, $identifier, $file);
        return $this->fetchWithOAuthCredentials($resource)->getBody();
    }
    /**
     * @inheritDoc
     */
    public function getChangeDate(string $identifier): ?\DateTimeImmutable
    {
        if ($this->fallbackDriver) {
            return $this->fallbackDriver->getChangeDate($identifier);
        }
        if (strpos($identifier, '/') !== \false) {
            $branches = $this->getBranches();
            if (isset($branches[$identifier])) {
                $identifier = $branches[$identifier];
            }
        }
        $resource = sprintf('https://api.bitbucket.org/2.0/repositories/%s/%s/commit/%s?fields=date', $this->owner, $this->repository, $identifier);
        $commit = $this->fetchWithOAuthCredentials($resource)->decodeJson();
        return new \DateTimeImmutable($commit['date']);
    }
    /**
     * @inheritDoc
     */
    public function getSource(string $identifier): array
    {
        if ($this->fallbackDriver) {
            return $this->fallbackDriver->getSource($identifier);
        }
        return ['type' => $this->vcsType, 'url' => $this->getUrl(), 'reference' => $identifier];
    }
    /**
     * @inheritDoc
     */
    public function getDist(string $identifier): ?array
    {
        if ($this->fallbackDriver) {
            return $this->fallbackDriver->getDist($identifier);
        }
        $url = sprintf('https://bitbucket.org/%s/%s/get/%s.zip', $this->owner, $this->repository, $identifier);
        return ['type' => 'zip', 'url' => $url, 'reference' => $identifier, 'shasum' => ''];
    }
    /**
     * @inheritDoc
     */
    public function getTags(): array
    {
        if ($this->fallbackDriver) {
            return $this->fallbackDriver->getTags();
        }
        if (null === $this->tags) {
            $tags = [];
            $resource = sprintf('%s?%s', $this->tagsUrl, http_build_query(['pagelen' => 100, 'fields' => 'values.name,values.target.hash,next', 'sort' => '-target.date'], '', '&'));
            $hasNext = \true;
            while ($hasNext) {
                $tagsData = $this->fetchWithOAuthCredentials($resource)->decodeJson();
                foreach ($tagsData['values'] as $data) {
                    $tags[$data['name']] = $data['target']['hash'];
                }
                if (empty($tagsData['next'])) {
                    $hasNext = \false;
                } else {
                    $resource = $tagsData['next'];
                }
            }
            $this->tags = $tags;
        }
        return $this->tags;
    }
    /**
     * @inheritDoc
     */
    public function getBranches(): array
    {
        if ($this->fallbackDriver) {
            return $this->fallbackDriver->getBranches();
        }
        if (null === $this->branches) {
            $branches = [];
            $resource = sprintf('%s?%s', $this->branchesUrl, http_build_query(['pagelen' => 100, 'fields' => 'values.name,values.target.hash,values.heads,next', 'sort' => '-target.date'], '', '&'));
            $hasNext = \true;
            while ($hasNext) {
                $branchData = $this->fetchWithOAuthCredentials($resource)->decodeJson();
                foreach ($branchData['values'] as $data) {
                    $branches[$data['name']] = $data['target']['hash'];
                }
                if (empty($branchData['next'])) {
                    $hasNext = \false;
                } else {
                    $resource = $branchData['next'];
                }
            }
            $this->branches = $branches;
        }
        return $this->branches;
    }
    /**
     * Get the remote content.
     *
     * @param string $url              The URL of content
     *
     * @return Response The result
     *
     * @phpstan-impure
     */
    protected function fetchWithOAuthCredentials(string $url, bool $fetchingRepoData = \false): Response
    {
        try {
            return parent::getContents($url);
        } catch (TransportException $e) {
            $bitbucketUtil = new Bitbucket($this->io, $this->config, $this->process, $this->httpDownloader);
            if (in_array($e->getCode(), [403, 404], \true) || 401 === $e->getCode() && strpos($e->getMessage(), 'Could not authenticate against') === 0) {
                if (!$this->io->hasAuthentication($this->originUrl) && $bitbucketUtil->authorizeOAuth($this->originUrl)) {
                    return parent::getContents($url);
                }
                if (!$this->io->isInteractive() && $fetchingRepoData) {
                    $this->attemptCloneFallback();
                    return new Response(['url' => 'dummy'], 200, [], 'null');
                }
            }
            throw $e;
        }
    }
    /**
     * Generate an SSH URL
     */
    protected function generateSshUrl(): string
    {
        return 'git@' . $this->originUrl . ':' . $this->owner . '/' . $this->repository . '.git';
    }
    /**
     * @phpstan-impure
     *
     * @return true
     * @throws \RuntimeException
     */
    protected function attemptCloneFallback(): bool
    {
        try {
            $this->setupFallbackDriver($this->generateSshUrl());
            return \true;
        } catch (\RuntimeException $e) {
            $this->fallbackDriver = null;
            $this->io->writeError('<error>Failed to clone the ' . $this->generateSshUrl() . ' repository, try running in interactive mode' . ' so that you can enter your Bitbucket OAuth consumer credentials</error>');
            throw $e;
        }
    }
    protected function setupFallbackDriver(string $url): void
    {
        $this->fallbackDriver = new \Composer\Repository\Vcs\GitDriver(['url' => $url], $this->io, $this->config, $this->httpDownloader, $this->process);
        $this->fallbackDriver->initialize();
    }
    /**
     * @param  array<array{name: string, href: string}> $cloneLinks
     */
    protected function parseCloneUrls(array $cloneLinks): void
    {
        foreach ($cloneLinks as $cloneLink) {
            if ($cloneLink['name'] === 'https') {
                // Format: https://(user@)bitbucket.org/{user}/{repo}
                // Strip username from URL (only present in clone URL's for private repositories)
                $this->cloneHttpsUrl = Preg::replace('/https:\/\/([^@]+@)?/', 'https://', $cloneLink['href']);
            }
        }
    }
    /**
     * @inheritDoc
     */
    public function getRootIdentifier(): string
    {
        if ($this->fallbackDriver) {
            return $this->fallbackDriver->getRootIdentifier();
        }
        if (null === $this->rootIdentifier) {
            if (!$this->getRepoData()) {
                if (!$this->fallbackDriver) {
                    throw new \LogicException('A fallback driver should be setup if getRepoData returns false');
                }
                return $this->fallbackDriver->getRootIdentifier();
            }
            if ($this->vcsType !== 'git') {
                throw new \RuntimeException($this->url . ' does not appear to be a git repository, use ' . $this->cloneHttpsUrl . ' but remember that Bitbucket no longer supports the mercurial repositories. ' . 'https://bitbucket.org/blog/sunsetting-mercurial-support-in-bitbucket');
            }
            $this->rootIdentifier = $this->repoData['mainbranch']['name'] ?? 'master';
        }
        return $this->rootIdentifier;
    }
    /**
     * @inheritDoc
     */
    public static function supports(IOInterface $io, Config $config, string $url, bool $deep = \false): bool
    {
        if (!Preg::isMatch('#^https?://bitbucket\.org/([^/]+)/([^/]+?)(\.git|/?)?$#i', $url)) {
            return \false;
        }
        if (!extension_loaded('openssl')) {
            $io->writeError('Skipping Bitbucket git driver for ' . $url . ' because the OpenSSL PHP extension is missing.', \true, IOInterface::VERBOSE);
            return \false;
        }
        return \true;
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer\Repository\Vcs;

use Composer\Pcre\Preg;
use Composer\Util\ProcessExecutor;
use Composer\Util\Filesystem;
use Composer\Util\Url;
use Composer\Util\Git as GitUtil;
use Composer\IO\IOInterface;
use Composer\Cache;
use Composer\Config;
/**
 * @author Jordi Boggiano <j.boggiano@seld.be>
 */
class GitDriver extends \Composer\Repository\Vcs\VcsDriver
{
    /** @var array<int|string, string> Map of tag name (can be turned to an int by php if it is a numeric name) to identifier */
    protected $tags;
    /** @var array<int|string, string> Map of branch name (can be turned to an int by php if it is a numeric name) to identifier */
    protected $branches;
    /** @var string */
    protected $rootIdentifier;
    /** @var string */
    protected $repoDir;
    /**
     * @inheritDoc
     */
    public function initialize(): void
    {
        if (Filesystem::isLocalPath($this->url)) {
            $this->url = Preg::replace('{[\/]\.git/?$}', '', $this->url);
            if (!is_dir($this->url)) {
                throw new \RuntimeException('Failed to read package information from ' . $this->url . ' as the path does not exist');
            }
            $this->repoDir = $this->url;
            $cacheUrl = realpath($this->url);
        } else {
            if (!Cache::isUsable($this->config->get('cache-vcs-dir'))) {
                throw new \RuntimeException('GitDriver requires a usable cache directory, and it looks like you set it to be disabled');
            }
            $this->repoDir = $this->config->get('cache-vcs-dir') . '/' . Preg::replace('{[^a-z0-9.]}i', '-', Url::sanitize($this->url)) . '/';
            GitUtil::cleanEnv($this->process);
            $fs = new Filesystem();
            $fs->ensureDirectoryExists(dirname($this->repoDir));
            if (!is_writable(dirname($this->repoDir))) {
                throw new \RuntimeException('Can not clone ' . $this->url . ' to access package information. The "' . dirname($this->repoDir) . '" directory is not writable by the current user.');
            }
            if (Preg::isMatch('{^ssh://[^@]+@[^:]+:[^0-9]+}', $this->url)) {
                throw new \InvalidArgumentException('The source URL ' . $this->url . ' is invalid, ssh URLs should have a port number after ":".' . "\n" . 'Use ssh://git@example.com:22/path or just git@example.com:path if you do not want to provide a password or custom port.');
            }
            $gitUtil = new GitUtil($this->io, $this->config, $this->process, $fs);
            if (!$gitUtil->syncMirror($this->url, $this->repoDir)) {
                if (!is_dir($this->repoDir)) {
                    throw new \RuntimeException('Failed to clone ' . $this->url . ' to read package information from it');
                }
                $this->io->writeError('<error>Failed to update ' . $this->url . ', package information from this repository may be outdated</error>');
            }
            $cacheUrl = $this->url;
        }
        $this->getTags();
        $this->getBranches();
        $this->cache = new Cache($this->io, $this->config->get('cache-repo-dir') . '/' . Preg::replace('{[^a-z0-9.]}i', '-', Url::sanitize($cacheUrl)));
        $this->cache->setReadOnly($this->config->get('cache-read-only'));
    }
    /**
     * @inheritDoc
     */
    public function getRootIdentifier(): string
    {
        if (null === $this->rootIdentifier) {
            $this->rootIdentifier = 'master';
            $gitUtil = new GitUtil($this->io, $this->config, $this->process, new Filesystem());
            if (!Filesystem::isLocalPath($this->url)) {
                $defaultBranch = $gitUtil->getMirrorDefaultBranch($this->url, $this->repoDir, \false);
                if ($defaultBranch !== null) {
                    return $this->rootIdentifier = $defaultBranch;
                }
            }
            // select currently checked out branch as default branch
            $this->process->execute(['git', 'branch', '--no-color'], $output, $this->repoDir);
            $branches = $this->process->splitLines($output);
            if (!in_array('* master', $branches)) {
                foreach ($branches as $branch) {
                    if ($branch && Preg::isMatchStrictGroups('{^\* +(\S+)}', $branch, $match)) {
                        $this->rootIdentifier = $match[1];
                        break;
                    }
                }
            }
        }
        return $this->rootIdentifier;
    }
    /**
     * @inheritDoc
     */
    public function getUrl(): string
    {
        return $this->url;
    }
    /**
     * @inheritDoc
     */
    public function getSource(string $identifier): array
    {
        return ['type' => 'git', 'url' => $this->getUrl(), 'reference' => $identifier];
    }
    /**
     * @inheritDoc
     */
    public function getDist(string $identifier): ?array
    {
        return null;
    }
    /**
     * @inheritDoc
     */
    public function getFileContent(string $file, string $identifier): ?string
    {
        if (isset($identifier[0]) && $identifier[0] === '-') {
            throw new \RuntimeException('Invalid git identifier detected. Identifier must not start with a -, given: ' . $identifier);
        }
        $this->process->execute(['git', 'show', $identifier . ':' . $file], $content, $this->repoDir);
        if (trim($content) === '') {
            return null;
        }
        return $content;
    }
    /**
     * @inheritDoc
     */
    public function getChangeDate(string $identifier): ?\DateTimeImmutable
    {
        if (isset($identifier[0]) && $identifier[0] === '-') {
            throw new \RuntimeException('Invalid git identifier detected. Identifier must not start with a -, given: ' . $identifier);
        }
        $command = GitUtil::buildRevListCommand($this->process, ['-n1', '--format=%at', $identifier]);
        $this->process->execute($command, $output, $this->repoDir);
        return new \DateTimeImmutable('@' . trim(GitUtil::parseRevListOutput($output, $this->process)), new \DateTimeZone('UTC'));
    }
    /**
     * @inheritDoc
     */
    public function getTags(): array
    {
        if (null === $this->tags) {
            $this->tags = [];
            $this->process->execute(['git', 'show-ref', '--tags', '--dereference'], $output, $this->repoDir);
            foreach ($this->process->splitLines($output) as $tag) {
                if ($tag !== '' && Preg::isMatch('{^([a-f0-9]{40}) refs/tags/(\S+?)(\^\{\})?$}', $tag, $match)) {
                    $this->tags[$match[2]] = $match[1];
                }
            }
        }
        return $this->tags;
    }
    /**
     * @inheritDoc
     */
    public function getBranches(): array
    {
        if (null === $this->branches) {
            $branches = [];
            $this->process->execute(['git', 'branch', '--no-color', '--no-abbrev', '-v'], $output, $this->repoDir);
            foreach ($this->process->splitLines($output) as $branch) {
                if ($branch !== '' && !Preg::isMatch('{^ *[^/]+/HEAD }', $branch)) {
                    if (Preg::isMatchStrictGroups('{^(?:\* )? *(\S+) *([a-f0-9]+)(?: .*)?$}', $branch, $match) && $match[1][0] !== '-') {
                        $branches[$match[1]] = $match[2];
                    }
                }
            }
            $this->branches = $branches;
        }
        return $this->branches;
    }
    /**
     * @inheritDoc
     */
    public static function supports(IOInterface $io, Config $config, string $url, bool $deep = \false): bool
    {
        if (Preg::isMatch('#(^git://|\.git/?$|git(?:olite)?@|//git\.|//github.com/)#i', $url)) {
            return \true;
        }
        // local filesystem
        if (Filesystem::isLocalPath($url)) {
            $url = Filesystem::getPlatformPath($url);
            if (!is_dir($url)) {
                return \false;
            }
            $process = new ProcessExecutor($io);
            // check whether there is a git repo in that path
            if ($process->execute(['git', 'tag'], $output, $url) === 0) {
                return \true;
            }
            GitUtil::checkForRepoOwnershipError($process->getErrorOutput(), $url);
        }
        if (!$deep) {
            return \false;
        }
        $process = new ProcessExecutor($io);
        $gitUtil = new GitUtil($io, $config, $process, new Filesystem());
        GitUtil::cleanEnv($process);
        try {
            $gitUtil->runCommands([['git', 'ls-remote', '--heads', '--', '%url%']], $url, sys_get_temp_dir());
        } catch (\RuntimeException $e) {
            return \false;
        }
        return \true;
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer\Repository\Vcs;

use Composer\Config;
use Composer\Cache;
use Composer\IO\IOInterface;
use Composer\Json\JsonFile;
use Composer\Downloader\TransportException;
use Composer\Pcre\Preg;
use Composer\Util\HttpDownloader;
use Composer\Util\GitLab;
use Composer\Util\Http\Response;
/**
 * Driver for GitLab API, use the Git driver for local checkouts.
 *
 * @author Henrik Bjørnskov <henrik@bjrnskov.dk>
 * @author Jérôme Tamarelle <jerome@tamarelle.net>
 */
class GitLabDriver extends \Composer\Repository\Vcs\VcsDriver
{
    /**
     * @var string
     * @phpstan-var 'https'|'http'
     */
    private $scheme;
    /** @var string */
    private $namespace;
    /** @var string */
    private $repository;
    /**
     * @var mixed[] Project data returned by GitLab API
     */
    private $project = null;
    /**
     * @var array<string|int, mixed[]> Keeps commits returned by GitLab API as commit id => info
     */
    private $commits = [];
    /** @var array<int|string, string> Map of tag name to identifier */
    private $tags;
    /** @var array<int|string, string> Map of branch name to identifier */
    private $branches;
    /**
     * Git Driver
     *
     * @var ?GitDriver
     */
    protected $gitDriver = null;
    /**
     * Protocol to force use of for repository URLs.
     *
     * @var string One of ssh, http
     */
    protected $protocol;
    /**
     * Defaults to true unless we can make sure it is public
     *
     * @var bool defines whether the repo is private or not
     */
    private $isPrivate = \true;
    /**
     * @var bool true if the origin has a port number or a path component in it
     */
    private $hasNonstandardOrigin = \false;
    public const URL_REGEX = '#^(?:(?P<scheme>https?)://(?P<domain>.+?)(?::(?P<port>[0-9]+))?/|git@(?P<domain2>[^:]+):)(?P<parts>.+)/(?P<repo>[^/]+?)(?:\.git|/)?$#';
    /**
     * Extracts information from the repository url.
     *
     * SSH urls use https by default. Set "secure-http": false on the repository config to use http instead.
     *
     * @inheritDoc
     */
    public function initialize(): void
    {
        if (!Preg::isMatch(self::URL_REGEX, $this->url, $match)) {
            throw new \InvalidArgumentException(sprintf('The GitLab repository URL %s is invalid. It must be the HTTP URL of a GitLab project.', $this->url));
        }
        $guessedDomain = $match['domain'] ?? (string) $match['domain2'];
        $configuredDomains = $this->config->get('gitlab-domains');
        $urlParts = explode('/', $match['parts']);
        $this->scheme = in_array($match['scheme'], ['https', 'http'], \true) ? $match['scheme'] : (isset($this->repoConfig['secure-http']) && $this->repoConfig['secure-http'] === \false ? 'http' : 'https');
        $origin = self::determineOrigin($configuredDomains, $guessedDomain, $urlParts, $match['port']);
        if (\false === $origin) {
            throw new \LogicException('It should not be possible to create a gitlab driver with an unparsable origin URL (' . $this->url . ')');
        }
        $this->originUrl = $origin;
        if (is_string($protocol = $this->config->get('gitlab-protocol'))) {
            // https treated as a synonym for http.
            if (!in_array($protocol, ['git', 'http', 'https'], \true)) {
                throw new \RuntimeException('gitlab-protocol must be one of git, http.');
            }
            $this->protocol = $protocol === 'git' ? 'ssh' : 'http';
        }
        if (\false !== strpos($this->originUrl, ':') || \false !== strpos($this->originUrl, '/')) {
            $this->hasNonstandardOrigin = \true;
        }
        $this->namespace = implode('/', $urlParts);
        $this->repository = Preg::replace('#(\.git)$#', '', $match['repo']);
        $this->cache = new Cache($this->io, $this->config->get('cache-repo-dir') . '/' . $this->originUrl . '/' . $this->namespace . '/' . $this->repository);
        $this->cache->setReadOnly($this->config->get('cache-read-only'));
        $this->fetchProject();
    }
    /**
     * Updates the HttpDownloader instance.
     * Mainly useful for tests.
     *
     * @internal
     */
    public function setHttpDownloader(HttpDownloader $httpDownloader): void
    {
        $this->httpDownloader = $httpDownloader;
    }
    /**
     * @inheritDoc
     */
    public function getComposerInformation(string $identifier): ?array
    {
        if ($this->gitDriver) {
            return $this->gitDriver->getComposerInformation($identifier);
        }
        if (!isset($this->infoCache[$identifier])) {
            if ($this->shouldCache($identifier) && $res = $this->cache->read($identifier)) {
                $composer = JsonFile::parseJson($res);
            } else {
                $composer = $this->getBaseComposerInformation($identifier);
                if ($this->shouldCache($identifier)) {
                    $this->cache->write($identifier, JsonFile::encode($composer, \JSON_UNESCAPED_UNICODE | \JSON_UNESCAPED_SLASHES));
                }
            }
            if (null !== $composer) {
                // specials for gitlab (this data is only available if authentication is provided)
                if (isset($composer['support']) && !is_array($composer['support'])) {
                    $composer['support'] = [];
                }
                if (!isset($composer['support']['source']) && isset($this->project['web_url'])) {
                    $label = (array_search($identifier, $this->getTags(), \true) ?: array_search($identifier, $this->getBranches(), \true)) ?: $identifier;
                    $composer['support']['source'] = sprintf('%s/-/tree/%s', $this->project['web_url'], $label);
                }
                if (!isset($composer['support']['issues']) && !empty($this->project['issues_enabled']) && isset($this->project['web_url'])) {
                    $composer['support']['issues'] = sprintf('%s/-/issues', $this->project['web_url']);
                }
                if (!isset($composer['abandoned']) && !empty($this->project['archived'])) {
                    $composer['abandoned'] = \true;
                }
            }
            $this->infoCache[$identifier] = $composer;
        }
        return $this->infoCache[$identifier];
    }
    /**
     * @inheritDoc
     */
    public function getFileContent(string $file, string $identifier): ?string
    {
        if ($this->gitDriver) {
            return $this->gitDriver->getFileContent($file, $identifier);
        }
        // Convert the root identifier to a cacheable commit id
        if (!Preg::isMatch('{[a-f0-9]{40}}i', $identifier)) {
            $branches = $this->getBranches();
            if (isset($branches[$identifier])) {
                $identifier = $branches[$identifier];
            }
        }
        $resource = $this->getApiUrl() . '/repository/files/' . $this->urlEncodeAll($file) . '/raw?ref=' . $identifier;
        try {
            $content = $this->getContents($resource)->getBody();
        } catch (TransportException $e) {
            if ($e->getCode() !== 404) {
                throw $e;
            }
            return null;
        }
        return $content;
    }
    /**
     * @inheritDoc
     */
    public function getChangeDate(string $identifier): ?\DateTimeImmutable
    {
        if ($this->gitDriver) {
            return $this->gitDriver->getChangeDate($identifier);
        }
        if (isset($this->commits[$identifier])) {
            return new \DateTimeImmutable($this->commits[$identifier]['committed_date']);
        }
        return null;
    }
    public function getRepositoryUrl(): string
    {
        if ($this->protocol) {
            return $this->project["{$this->protocol}_url_to_repo"];
        }
        return $this->isPrivate ? $this->project['ssh_url_to_repo'] : $this->project['http_url_to_repo'];
    }
    /**
     * @inheritDoc
     */
    public function getUrl(): string
    {
        if ($this->gitDriver) {
            return $this->gitDriver->getUrl();
        }
        return $this->project['web_url'];
    }
    /**
     * @inheritDoc
     */
    public function getDist(string $identifier): ?array
    {
        $url = $this->getApiUrl() . '/repository/archive.zip?sha=' . $identifier;
        return ['type' => 'zip', 'url' => $url, 'reference' => $identifier, 'shasum' => ''];
    }
    /**
     * @inheritDoc
     */
    public function getSource(string $identifier): array
    {
        if ($this->gitDriver) {
            return $this->gitDriver->getSource($identifier);
        }
        return ['type' => 'git', 'url' => $this->getRepositoryUrl(), 'reference' => $identifier];
    }
    /**
     * @inheritDoc
     */
    public function getRootIdentifier(): string
    {
        if ($this->gitDriver) {
            return $this->gitDriver->getRootIdentifier();
        }
        return $this->project['default_branch'];
    }
    /**
     * @inheritDoc
     */
    public function getBranches(): array
    {
        if ($this->gitDriver) {
            return $this->gitDriver->getBranches();
        }
        if (null === $this->branches) {
            $this->branches = $this->getReferences('branches');
        }
        return $this->branches;
    }
    /**
     * @inheritDoc
     */
    public function getTags(): array
    {
        if ($this->gitDriver) {
            return $this->gitDriver->getTags();
        }
        if (null === $this->tags) {
            $this->tags = $this->getReferences('tags');
        }
        return $this->tags;
    }
    /**
     * @return string Base URL for GitLab API v3
     */
    public function getApiUrl(): string
    {
        return $this->scheme . '://' . $this->originUrl . '/api/v4/projects/' . $this->urlEncodeAll($this->namespace) . '%2F' . $this->urlEncodeAll($this->repository);
    }
    /**
     * Urlencode all non alphanumeric characters. rawurlencode() can not be used as it does not encode `.`
     */
    private function urlEncodeAll(string $string): string
    {
        $encoded = '';
        for ($i = 0; isset($string[$i]); $i++) {
            $character = $string[$i];
            if (!ctype_alnum($character) && !in_array($character, ['-', '_'], \true)) {
                $character = '%' . sprintf('%02X', ord($character));
            }
            $encoded .= $character;
        }
        return $encoded;
    }
    /**
     * @return string[] where keys are named references like tags or branches and the value a sha
     */
    protected function getReferences(string $type): array
    {
        $perPage = 100;
        $resource = $this->getApiUrl() . '/repository/' . $type . '?per_page=' . $perPage;
        $references = [];
        do {
            $response = $this->getContents($resource);
            $data = $response->decodeJson();
            foreach ($data as $datum) {
                $references[$datum['name']] = $datum['commit']['id'];
                // Keep the last commit date of a reference to avoid
                // unnecessary API call when retrieving the composer file.
                $this->commits[$datum['commit']['id']] = $datum['commit'];
            }
            if (count($data) >= $perPage) {
                $resource = $this->getNextPage($response);
            } else {
                $resource = \false;
            }
        } while ($resource);
        return $references;
    }
    protected function fetchProject(): void
    {
        if (!is_null($this->project)) {
            return;
        }
        // we need to fetch the default branch from the api
        $resource = $this->getApiUrl();
        $this->project = $this->getContents($resource, \true)->decodeJson();
        if (isset($this->project['visibility'])) {
            $this->isPrivate = $this->project['visibility'] !== 'public';
        } else {
            // client is not authenticated, therefore repository has to be public
            $this->isPrivate = \false;
        }
    }
    /**
     * @phpstan-impure
     *
     * @return true
     * @throws \RuntimeException
     */
    protected function attemptCloneFallback(): bool
    {
        if ($this->isPrivate === \false) {
            $url = $this->generatePublicUrl();
        } else {
            $url = $this->generateSshUrl();
        }
        try {
            // If this repository may be private and we
            // cannot ask for authentication credentials (because we
            // are not interactive) then we fallback to GitDriver.
            $this->setupGitDriver($url);
            return \true;
        } catch (\RuntimeException $e) {
            $this->gitDriver = null;
            $this->io->writeError('<error>Failed to clone the ' . $url . ' repository, try running in interactive mode so that you can enter your credentials</error>');
            throw $e;
        }
    }
    /**
     * Generate an SSH URL
     */
    protected function generateSshUrl(): string
    {
        if ($this->hasNonstandardOrigin) {
            return 'ssh://git@' . $this->originUrl . '/' . $this->namespace . '/' . $this->repository . '.git';
        }
        return 'git@' . $this->originUrl . ':' . $this->namespace . '/' . $this->repository . '.git';
    }
    protected function generatePublicUrl(): string
    {
        return $this->scheme . '://' . $this->originUrl . '/' . $this->namespace . '/' . $this->repository . '.git';
    }
    protected function setupGitDriver(string $url): void
    {
        $this->gitDriver = new \Composer\Repository\Vcs\GitDriver(['url' => $url], $this->io, $this->config, $this->httpDownloader, $this->process);
        $this->gitDriver->initialize();
    }
    /**
     * @inheritDoc
     */
    protected function getContents(string $url, bool $fetchingRepoData = \false): Response
    {
        try {
            $response = parent::getContents($url);
            if ($fetchingRepoData) {
                $json = $response->decodeJson();
                // Accessing the API with a token with Guest (10) or Planner (15) access will return
                // more data than unauthenticated access but no default_branch data
                // accessing files via the API will then also fail
                if (!isset($json['default_branch']) && isset($json['permissions'])) {
                    $this->isPrivate = $json['visibility'] !== 'public';
                    $moreThanGuestAccess = \false;
                    // Check both access levels (e.g. project, group)
                    // - value will be null if no access is set
                    // - value will be array with key access_level if set
                    foreach ($json['permissions'] as $permission) {
                        if ($permission && $permission['access_level'] >= 20) {
                            $moreThanGuestAccess = \true;
                        }
                    }
                    if (!$moreThanGuestAccess) {
                        $this->io->writeError('<warning>GitLab token with Guest or Planner only access detected</warning>');
                        $this->attemptCloneFallback();
                        return new Response(['url' => 'dummy'], 200, [], 'null');
                    }
                }
                // force auth as the unauthenticated version of the API is broken
                if (!isset($json['default_branch'])) {
                    // GitLab allows you to disable the repository inside a project to use a project only for issues and wiki
                    if (isset($json['repository_access_level']) && $json['repository_access_level'] === 'disabled') {
                        throw new TransportException('The GitLab repository is disabled in the project', 400);
                    }
                    if (!empty($json['id'])) {
                        $this->isPrivate = \false;
                    }
                    throw new TransportException('GitLab API seems to not be authenticated as it did not return a default_branch', 401);
                }
            }
            return $response;
        } catch (TransportException $e) {
            $gitLabUtil = new GitLab($this->io, $this->config, $this->process, $this->httpDownloader);
            switch ($e->getCode()) {
                case 401:
                case 404:
                    // try to authorize only if we are fetching the main /repos/foo/bar data, otherwise it must be a real 404
                    if (!$fetchingRepoData) {
                        throw $e;
                    }
                    if ($gitLabUtil->authorizeOAuth($this->originUrl)) {
                        return parent::getContents($url);
                    }
                    if ($gitLabUtil->isOAuthExpired($this->originUrl) && $gitLabUtil->authorizeOAuthRefresh($this->scheme, $this->originUrl)) {
                        return parent::getContents($url);
                    }
                    if (!$this->io->isInteractive()) {
                        $this->attemptCloneFallback();
                        return new Response(['url' => 'dummy'], 200, [], 'null');
                    }
                    $this->io->writeError('<warning>Failed to download ' . $this->namespace . '/' . $this->repository . ':' . $e->getMessage() . '</warning>');
                    $gitLabUtil->authorizeOAuthInteractively($this->scheme, $this->originUrl, 'Your credentials are required to fetch private repository metadata (<info>' . $this->url . '</info>)');
                    return parent::getContents($url);
                case 403:
                    if (!$this->io->hasAuthentication($this->originUrl) && $gitLabUtil->authorizeOAuth($this->originUrl)) {
                        return parent::getContents($url);
                    }
                    if (!$this->io->isInteractive() && $fetchingRepoData) {
                        $this->attemptCloneFallback();
                        return new Response(['url' => 'dummy'], 200, [], 'null');
                    }
                    throw $e;
                default:
                    throw $e;
            }
        }
    }
    /**
     * Uses the config `gitlab-domains` to see if the driver supports the url for the
     * repository given.
     *
     * @inheritDoc
     */
    public static function supports(IOInterface $io, Config $config, string $url, bool $deep = \false): bool
    {
        if (!Preg::isMatch(self::URL_REGEX, $url, $match)) {
            return \false;
        }
        $scheme = $match['scheme'];
        $guessedDomain = $match['domain'] ?? (string) $match['domain2'];
        $urlParts = explode('/', $match['parts']);
        if (\false === self::determineOrigin($config->get('gitlab-domains'), $guessedDomain, $urlParts, $match['port'])) {
            return \false;
        }
        if ('https' === $scheme && !extension_loaded('openssl')) {
            $io->writeError('Skipping GitLab driver for ' . $url . ' because the OpenSSL PHP extension is missing.', \true, IOInterface::VERBOSE);
            return \false;
        }
        return \true;
    }
    /**
     * Gives back the loaded <gitlab-api>/projects/<owner>/<repo> result
     *
     * @return mixed[]|null
     */
    public function getRepoData(): ?array
    {
        $this->fetchProject();
        return $this->project;
    }
    protected function getNextPage(Response $response): ?string
    {
        $header = $response->getHeader('link');
        $links = explode(',', $header);
        foreach ($links as $link) {
            if (Preg::isMatchStrictGroups('{<(.+?)>; *rel="next"}', $link, $match)) {
                return $match[1];
            }
        }
        return null;
    }
    /**
     * @param  array<string> $configuredDomains
     * @param  array<string> $urlParts
     *
     * @return string|false
     */
    private static function determineOrigin(array $configuredDomains, string $guessedDomain, array &$urlParts, ?string $portNumber)
    {
        $guessedDomain = strtolower($guessedDomain);
        if (in_array($guessedDomain, $configuredDomains) || null !== $portNumber && in_array($guessedDomain . ':' . $portNumber, $configuredDomains)) {
            if (null !== $portNumber) {
                return $guessedDomain . ':' . $portNumber;
            }
            return $guessedDomain;
        }
        if (null !== $portNumber) {
            $guessedDomain .= ':' . $portNumber;
        }
        while (null !== $part = array_shift($urlParts)) {
            $guessedDomain .= '/' . $part;
            if (in_array($guessedDomain, $configuredDomains) || null !== $portNumber && in_array(Preg::replace('{:\d+}', '', $guessedDomain), $configuredDomains)) {
                return $guessedDomain;
            }
        }
        return \false;
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer\Repository\Vcs;

use Composer\Config;
use Composer\IO\IOInterface;
/**
 * @author Jordi Boggiano <j.boggiano@seld.be>
 * @internal
 */
interface VcsDriverInterface
{
    /**
     * Initializes the driver (git clone, svn checkout, fetch info etc)
     */
    public function initialize(): void;
    /**
     * Return the composer.json file information
     *
     * @param  string  $identifier Any identifier to a specific branch/tag/commit
     * @return mixed[]|null Array containing all infos from the composer.json file, or null to denote that no file was present
     */
    public function getComposerInformation(string $identifier): ?array;
    /**
     * Return the content of $file or null if the file does not exist.
     */
    public function getFileContent(string $file, string $identifier): ?string;
    /**
     * Get the changedate for $identifier.
     */
    public function getChangeDate(string $identifier): ?\DateTimeImmutable;
    /**
     * Return the root identifier (trunk, master, default/tip ..)
     *
     * @return string Identifier
     */
    public function getRootIdentifier(): string;
    /**
     * Return list of branches in the repository
     *
     * @return array<int|string, string> Branch names as keys, identifiers as values
     */
    public function getBranches(): array;
    /**
     * Return list of tags in the repository
     *
     * @return array<int|string, string> Tag names as keys, identifiers as values
     */
    public function getTags(): array;
    /**
     * @param string $identifier Any identifier to a specific branch/tag/commit
     *
     * @return array{type: string, url: string, reference: string, shasum: string}|null
     */
    public function getDist(string $identifier): ?array;
    /**
     * @param string $identifier Any identifier to a specific branch/tag/commit
     *
     * @return array{type: string, url: string, reference: string}
     */
    public function getSource(string $identifier): array;
    /**
     * Return the URL of the repository
     */
    public function getUrl(): string;
    /**
     * Return true if the repository has a composer file for a given identifier,
     * false otherwise.
     *
     * @param  string $identifier Any identifier to a specific branch/tag/commit
     * @return bool   Whether the repository has a composer file for a given identifier.
     */
    public function hasComposerFile(string $identifier): bool;
    /**
     * Performs any cleanup necessary as the driver is not longer needed
     */
    public function cleanup(): void;
    /**
     * Checks if this driver can handle a given url
     *
     * @param  IOInterface $io     IO instance
     * @param  Config      $config current $config
     * @param  string      $url    URL to validate/check
     * @param  bool        $deep   unless true, only shallow checks (url matching typically) should be done
     */
    public static function supports(IOInterface $io, Config $config, string $url, bool $deep = \false): bool;
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer\Repository\Vcs;

use Composer\Cache;
use Composer\Config;
use Composer\Pcre\Preg;
use Composer\Util\ProcessExecutor;
use Composer\Util\Filesystem;
use Composer\IO\IOInterface;
/**
 * @author BohwaZ <http://bohwaz.net/>
 */
class FossilDriver extends \Composer\Repository\Vcs\VcsDriver
{
    /** @var array<int|string, string> Map of tag name to identifier */
    protected $tags;
    /** @var array<int|string, string> Map of branch name to identifier */
    protected $branches;
    /** @var ?string */
    protected $rootIdentifier = null;
    /** @var ?string */
    protected $repoFile = null;
    /** @var string */
    protected $checkoutDir;
    /**
     * @inheritDoc
     */
    public function initialize(): void
    {
        // Make sure fossil is installed and reachable.
        $this->checkFossil();
        // Ensure we are allowed to use this URL by config.
        $this->config->prohibitUrlByConfig($this->url, $this->io);
        // Only if url points to a locally accessible directory, assume it's the checkout directory.
        // Otherwise, it should be something fossil can clone from.
        if (Filesystem::isLocalPath($this->url) && is_dir($this->url)) {
            $this->checkoutDir = $this->url;
        } else {
            if (!Cache::isUsable($this->config->get('cache-repo-dir')) || !Cache::isUsable($this->config->get('cache-vcs-dir'))) {
                throw new \RuntimeException('FossilDriver requires a usable cache directory, and it looks like you set it to be disabled');
            }
            $localName = Preg::replace('{[^a-z0-9]}i', '-', $this->url);
            $this->repoFile = $this->config->get('cache-repo-dir') . '/' . $localName . '.fossil';
            $this->checkoutDir = $this->config->get('cache-vcs-dir') . '/' . $localName . '/';
            $this->updateLocalRepo();
        }
        $this->getTags();
        $this->getBranches();
    }
    /**
     * Check that fossil can be invoked via command line.
     */
    protected function checkFossil(): void
    {
        if (0 !== $this->process->execute(['fossil', 'version'], $ignoredOutput)) {
            throw new \RuntimeException("fossil was not found, check that it is installed and in your PATH env.\n\n" . $this->process->getErrorOutput());
        }
    }
    /**
     * Clone or update existing local fossil repository.
     */
    protected function updateLocalRepo(): void
    {
        assert($this->repoFile !== null);
        $fs = new Filesystem();
        $fs->ensureDirectoryExists($this->checkoutDir);
        if (!is_writable(dirname($this->checkoutDir))) {
            throw new \RuntimeException('Can not clone ' . $this->url . ' to access package information. The "' . $this->checkoutDir . '" directory is not writable by the current user.');
        }
        // update the repo if it is a valid fossil repository
        if (is_file($this->repoFile) && is_dir($this->checkoutDir) && 0 === $this->process->execute(['fossil', 'info'], $output, $this->checkoutDir)) {
            if (0 !== $this->process->execute(['fossil', 'pull'], $output, $this->checkoutDir)) {
                $this->io->writeError('<error>Failed to update ' . $this->url . ', package information from this repository may be outdated (' . $this->process->getErrorOutput() . ')</error>');
            }
        } else {
            // clean up directory and do a fresh clone into it
            $fs->removeDirectory($this->checkoutDir);
            $fs->remove($this->repoFile);
            $fs->ensureDirectoryExists($this->checkoutDir);
            if (0 !== $this->process->execute(['fossil', 'clone', '--', $this->url, $this->repoFile], $output)) {
                $output = $this->process->getErrorOutput();
                throw new \RuntimeException('Failed to clone ' . $this->url . ' to repository ' . $this->repoFile . "\n\n" . $output);
            }
            if (0 !== $this->process->execute(['fossil', 'open', '--nested', '--', $this->repoFile], $output, $this->checkoutDir)) {
                $output = $this->process->getErrorOutput();
                throw new \RuntimeException('Failed to open repository ' . $this->repoFile . ' in ' . $this->checkoutDir . "\n\n" . $output);
            }
        }
    }
    /**
     * @inheritDoc
     */
    public function getRootIdentifier(): string
    {
        if (null === $this->rootIdentifier) {
            $this->rootIdentifier = 'trunk';
        }
        return $this->rootIdentifier;
    }
    /**
     * @inheritDoc
     */
    public function getUrl(): string
    {
        return $this->url;
    }
    /**
     * @inheritDoc
     */
    public function getSource(string $identifier): array
    {
        return ['type' => 'fossil', 'url' => $this->getUrl(), 'reference' => $identifier];
    }
    /**
     * @inheritDoc
     */
    public function getDist(string $identifier): ?array
    {
        return null;
    }
    /**
     * @inheritDoc
     */
    public function getFileContent(string $file, string $identifier): ?string
    {
        if (isset($identifier[0]) && $identifier[0] === '-') {
            throw new \RuntimeException('Invalid fossil identifier detected. Identifier must not start with a -, given: ' . $identifier);
        }
        $this->process->execute(['fossil', 'cat', '-r', $identifier, '--', $file], $content, $this->checkoutDir);
        if ('' === trim($content)) {
            return null;
        }
        return $content;
    }
    /**
     * @inheritDoc
     */
    public function getChangeDate(string $identifier): ?\DateTimeImmutable
    {
        $this->process->execute(['fossil', 'finfo', '-b', '-n', '1', 'composer.json'], $output, $this->checkoutDir);
        [, $date] = explode(' ', trim($output), 3);
        return new \DateTimeImmutable($date, new \DateTimeZone('UTC'));
    }
    /**
     * @inheritDoc
     */
    public function getTags(): array
    {
        if (null === $this->tags) {
            $tags = [];
            $this->process->execute(['fossil', 'tag', 'list'], $output, $this->checkoutDir);
            foreach ($this->process->splitLines($output) as $tag) {
                $tags[$tag] = $tag;
            }
            $this->tags = $tags;
        }
        return $this->tags;
    }
    /**
     * @inheritDoc
     */
    public function getBranches(): array
    {
        if (null === $this->branches) {
            $branches = [];
            $this->process->execute(['fossil', 'branch', 'list'], $output, $this->checkoutDir);
            foreach ($this->process->splitLines($output) as $branch) {
                $branch = trim(Preg::replace('/^\*/', '', trim($branch)));
                $branches[$branch] = $branch;
            }
            $this->branches = $branches;
        }
        return $this->branches;
    }
    /**
     * @inheritDoc
     */
    public static function supports(IOInterface $io, Config $config, string $url, bool $deep = \false): bool
    {
        if (Preg::isMatch('#(^(?:https?|ssh)://(?:[^@]@)?(?:chiselapp\.com|fossil\.))#i', $url)) {
            return \true;
        }
        if (Preg::isMatch('!/fossil/|\.fossil!', $url)) {
            return \true;
        }
        // local filesystem
        if (Filesystem::isLocalPath($url)) {
            $url = Filesystem::getPlatformPath($url);
            if (!is_dir($url)) {
                return \false;
            }
            $process = new ProcessExecutor($io);
            // check whether there is a fossil repo in that path
            if ($process->execute(['fossil', 'info'], $output, $url) === 0) {
                return \true;
            }
        }
        return \false;
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer\Repository;

use Composer\Config;
use Composer\EventDispatcher\EventDispatcher;
use Composer\IO\IOInterface;
use Composer\Json\JsonFile;
use Composer\Package\Loader\ArrayLoader;
use Composer\Package\Version\VersionGuesser;
use Composer\Package\Version\VersionParser;
use Composer\Pcre\Preg;
use Composer\Util\HttpDownloader;
use Composer\Util\Platform;
use Composer\Util\ProcessExecutor;
use Composer\Util\Filesystem;
use Composer\Util\Url;
use Composer\Util\Git as GitUtil;
/**
 * This repository allows installing local packages that are not necessarily under their own VCS.
 *
 * The local packages will be symlinked when possible, else they will be copied.
 *
 * @code
 * "require": {
 *     "<vendor>/<local-package>": "*"
 * },
 * "repositories": [
 *     {
 *         "type": "path",
 *         "url": "../../relative/path/to/package/"
 *     },
 *     {
 *         "type": "path",
 *         "url": "/absolute/path/to/package/"
 *     },
 *     {
 *         "type": "path",
 *         "url": "/absolute/path/to/several/packages/*"
 *     },
 *     {
 *         "type": "path",
 *         "url": "../../relative/path/to/package/",
 *         "options": {
 *             "symlink": false
 *         }
 *     },
 *     {
 *         "type": "path",
 *         "url": "../../relative/path/to/package/",
 *         "options": {
 *             "reference": "none"
 *         }
 *     },
 * ]
 * @endcode
 *
 * @author Samuel Roze <samuel.roze@gmail.com>
 * @author Johann Reinke <johann.reinke@gmail.com>
 */
class PathRepository extends \Composer\Repository\ArrayRepository implements \Composer\Repository\ConfigurableRepositoryInterface
{
    /**
     * @var ArrayLoader
     */
    private $loader;
    /**
     * @var VersionGuesser
     */
    private $versionGuesser;
    /**
     * @var string
     */
    private $url;
    /**
     * @var mixed[]
     * @phpstan-var array{url: string, options?: array{symlink?: bool, reference?: string, relative?: bool, versions?: array<string, string>}}
     */
    private $repoConfig;
    /**
     * @var ProcessExecutor
     */
    private $process;
    /**
     * @var array{symlink?: bool, reference?: string, relative?: bool, versions?: array<string, string>}
     */
    private $options;
    /**
     * Initializes path repository.
     *
     * @param array{url?: string, options?: array{symlink?: bool, reference?: string, relative?: bool, versions?: array<string, string>}} $repoConfig
     */
    public function __construct(array $repoConfig, IOInterface $io, Config $config, ?HttpDownloader $httpDownloader = null, ?EventDispatcher $dispatcher = null, ?ProcessExecutor $process = null)
    {
        if (!isset($repoConfig['url'])) {
            throw new \RuntimeException('You must specify the `url` configuration for the path repository');
        }
        $this->loader = new ArrayLoader(null, \true);
        $this->url = Platform::expandPath($repoConfig['url']);
        $this->process = $process ?? new ProcessExecutor($io);
        $this->versionGuesser = new VersionGuesser($config, $this->process, new VersionParser(), $io);
        $this->repoConfig = $repoConfig;
        $this->options = $repoConfig['options'] ?? [];
        if (!isset($this->options['relative'])) {
            $filesystem = new Filesystem();
            $this->options['relative'] = !$filesystem->isAbsolutePath($this->url);
        }
        parent::__construct();
    }
    public function getRepoName(): string
    {
        return 'path repo (' . Url::sanitize($this->repoConfig['url']) . ')';
    }
    public function getRepoConfig(): array
    {
        return $this->repoConfig;
    }
    /**
     * Initializes path repository.
     *
     * This method will basically read the folder and add the found package.
     */
    protected function initialize(): void
    {
        parent::initialize();
        $urlMatches = $this->getUrlMatches();
        if (empty($urlMatches)) {
            if (Preg::isMatch('{[*{}]}', $this->url)) {
                $url = $this->url;
                while (Preg::isMatch('{[*{}]}', $url)) {
                    $url = dirname($url);
                }
                // the parent directory before any wildcard exists, so we assume it is correctly configured but simply empty
                if (is_dir($url)) {
                    return;
                }
            }
            throw new \RuntimeException('The `url` supplied for the path (' . $this->url . ') repository does not exist');
        }
        foreach ($urlMatches as $url) {
            $path = realpath($url) . \DIRECTORY_SEPARATOR;
            $composerFilePath = $path . 'composer.json';
            if (!file_exists($composerFilePath)) {
                continue;
            }
            $json = file_get_contents($composerFilePath);
            $package = JsonFile::parseJson($json, $composerFilePath);
            $package['dist'] = ['type' => 'path', 'url' => $url];
            $reference = $this->options['reference'] ?? 'auto';
            if ('none' === $reference) {
                $package['dist']['reference'] = null;
            } elseif ('config' === $reference || 'auto' === $reference) {
                $package['dist']['reference'] = hash('sha1', $json . serialize($this->options));
            }
            // copy symlink/relative options to transport options
            $package['transport-options'] = array_intersect_key($this->options, ['symlink' => \true, 'relative' => \true]);
            // use the version provided as option if available
            if (isset($package['name'], $this->options['versions'][$package['name']])) {
                $package['version'] = $this->options['versions'][$package['name']];
            }
            // carry over the root package version if this path repo is in the same git repository as root package
            if (!isset($package['version']) && $rootVersion = Platform::getEnv('COMPOSER_ROOT_VERSION')) {
                if (0 === $this->process->execute(['git', 'rev-parse', 'HEAD'], $ref1, $path) && 0 === $this->process->execute(['git', 'rev-parse', 'HEAD'], $ref2) && $ref1 === $ref2) {
                    $package['version'] = $this->versionGuesser->getRootVersionFromEnv();
                }
            }
            $output = '';
            $command = GitUtil::buildRevListCommand($this->process, array_merge(['-n1', '--format=%H', 'HEAD'], GitUtil::getNoShowSignatureFlags($this->process)));
            if ('auto' === $reference && is_dir($path . \DIRECTORY_SEPARATOR . '.git') && 0 === $this->process->execute($command, $output, $path)) {
                $package['dist']['reference'] = trim(GitUtil::parseRevListOutput($output, $this->process));
            }
            if (!isset($package['version'])) {
                $versionData = $this->versionGuesser->guessVersion($package, $path);
                if (is_array($versionData) && $versionData['pretty_version']) {
                    // if there is a feature branch detected, we add a second packages with the feature branch version
                    if (!empty($versionData['feature_pretty_version'])) {
                        $package['version'] = $versionData['feature_pretty_version'];
                        $this->addPackage($this->loader->load($package));
                    }
                    $package['version'] = $versionData['pretty_version'];
                } else {
                    $package['version'] = 'dev-main';
                }
            }
            try {
                $this->addPackage($this->loader->load($package));
            } catch (\Exception $e) {
                throw new \RuntimeException('Failed loading the package in ' . $composerFilePath, 0, $e);
            }
        }
    }
    /**
     * Get a list of all (possibly relative) path names matching given url (supports globbing).
     *
     * @return string[]
     */
    private function getUrlMatches(): array
    {
        $flags = \GLOB_MARK | \GLOB_ONLYDIR;
        if (defined('GLOB_BRACE')) {
            $flags |= \GLOB_BRACE;
        } elseif (strpos($this->url, '{') !== \false || strpos($this->url, '}') !== \false) {
            throw new \RuntimeException('The operating system does not support GLOB_BRACE which is required for the url ' . $this->url);
        }
        // Ensure environment-specific path separators are normalized to URL separators
        return array_map(static function ($val): string {
            return rtrim(str_replace(\DIRECTORY_SEPARATOR, '/', $val), '/');
        }, glob($this->url, $flags));
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer\Repository;

interface VersionCacheInterface
{
    /**
     * @return mixed[]|null|false Package version data if found, false to indicate the identifier is known but has no package, null for an unknown identifier
     */
    public function getVersionPackage(string $version, string $identifier);
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer\Repository;

use Composer\Package\AliasPackage;
use Composer\Package\PackageInterface;
/**
 * Provides getCanonicalPackages() to various repository implementations
 *
 * @internal
 */
trait CanonicalPackagesTrait
{
    /**
     * Get unique packages (at most one package of each name), with aliases resolved and removed.
     *
     * @return PackageInterface[]
     */
    public function getCanonicalPackages()
    {
        $packages = $this->getPackages();
        // get at most one package of each name, preferring non-aliased ones
        $packagesByName = [];
        foreach ($packages as $package) {
            if (!isset($packagesByName[$package->getName()]) || $packagesByName[$package->getName()] instanceof AliasPackage) {
                $packagesByName[$package->getName()] = $package;
            }
        }
        $canonicalPackages = [];
        // unfold aliased packages
        foreach ($packagesByName as $package) {
            while ($package instanceof AliasPackage) {
                $package = $package->getAliasOf();
            }
            $canonicalPackages[] = $package;
        }
        return $canonicalPackages;
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer\Repository;

use Composer\Package\PackageInterface;
use Composer\Package\BasePackage;
use Composer\Pcre\Preg;
/**
 * Filters which packages are seen as canonical on this repo by loadPackages
 *
 * @author Jordi Boggiano <j.boggiano@seld.be>
 */
class FilterRepository implements \Composer\Repository\RepositoryInterface, \Composer\Repository\AdvisoryProviderInterface
{
    /** @var ?string */
    private $only = null;
    /** @var ?non-empty-string */
    private $exclude = null;
    /** @var bool */
    private $canonical = \true;
    /** @var RepositoryInterface */
    private $repo;
    /**
     * @param array{only?: array<string>, exclude?: array<string>, canonical?: bool} $options
     */
    public function __construct(\Composer\Repository\RepositoryInterface $repo, array $options)
    {
        if (isset($options['only'])) {
            if (!is_array($options['only'])) {
                throw new \InvalidArgumentException('"only" key for repository ' . $repo->getRepoName() . ' should be an array');
            }
            $this->only = BasePackage::packageNamesToRegexp($options['only']);
        }
        if (isset($options['exclude'])) {
            if (!is_array($options['exclude'])) {
                throw new \InvalidArgumentException('"exclude" key for repository ' . $repo->getRepoName() . ' should be an array');
            }
            $this->exclude = BasePackage::packageNamesToRegexp($options['exclude']);
        }
        if ($this->exclude && $this->only) {
            throw new \InvalidArgumentException('Only one of "only" and "exclude" can be specified for repository ' . $repo->getRepoName());
        }
        if (isset($options['canonical'])) {
            if (!is_bool($options['canonical'])) {
                throw new \InvalidArgumentException('"canonical" key for repository ' . $repo->getRepoName() . ' should be a boolean');
            }
            $this->canonical = $options['canonical'];
        }
        $this->repo = $repo;
    }
    public function getRepoName(): string
    {
        return $this->repo->getRepoName();
    }
    /**
     * Returns the wrapped repositories
     */
    public function getRepository(): \Composer\Repository\RepositoryInterface
    {
        return $this->repo;
    }
    /**
     * @inheritDoc
     */
    public function hasPackage(PackageInterface $package): bool
    {
        return $this->repo->hasPackage($package);
    }
    /**
     * @inheritDoc
     */
    public function findPackage($name, $constraint): ?BasePackage
    {
        if (!$this->isAllowed($name)) {
            return null;
        }
        return $this->repo->findPackage($name, $constraint);
    }
    /**
     * @inheritDoc
     */
    public function findPackages($name, $constraint = null): array
    {
        if (!$this->isAllowed($name)) {
            return [];
        }
        return $this->repo->findPackages($name, $constraint);
    }
    /**
     * @inheritDoc
     */
    public function loadPackages(array $packageNameMap, array $acceptableStabilities, array $stabilityFlags, array $alreadyLoaded = []): array
    {
        foreach ($packageNameMap as $name => $constraint) {
            if (!$this->isAllowed($name)) {
                unset($packageNameMap[$name]);
            }
        }
        if (!$packageNameMap) {
            return ['namesFound' => [], 'packages' => []];
        }
        $result = $this->repo->loadPackages($packageNameMap, $acceptableStabilities, $stabilityFlags, $alreadyLoaded);
        if (!$this->canonical) {
            $result['namesFound'] = [];
        }
        return $result;
    }
    /**
     * @inheritDoc
     */
    public function search(string $query, int $mode = 0, ?string $type = null): array
    {
        $result = [];
        foreach ($this->repo->search($query, $mode, $type) as $package) {
            if ($this->isAllowed($package['name'])) {
                $result[] = $package;
            }
        }
        return $result;
    }
    /**
     * @inheritDoc
     */
    public function getPackages(): array
    {
        $result = [];
        foreach ($this->repo->getPackages() as $package) {
            if ($this->isAllowed($package->getName())) {
                $result[] = $package;
            }
        }
        return $result;
    }
    /**
     * @inheritDoc
     */
    public function getProviders($packageName): array
    {
        $result = [];
        foreach ($this->repo->getProviders($packageName) as $name => $provider) {
            if ($this->isAllowed($provider['name'])) {
                $result[$name] = $provider;
            }
        }
        return $result;
    }
    /**
     * @inheritDoc
     */
    public function count(): int
    {
        if ($this->repo->count() > 0) {
            return count($this->getPackages());
        }
        return 0;
    }
    public function hasSecurityAdvisories(): bool
    {
        if (!$this->repo instanceof \Composer\Repository\AdvisoryProviderInterface) {
            return \false;
        }
        return $this->repo->hasSecurityAdvisories();
    }
    /**
     * @inheritDoc
     */
    public function getSecurityAdvisories(array $packageConstraintMap, bool $allowPartialAdvisories = \false): array
    {
        if (!$this->repo instanceof \Composer\Repository\AdvisoryProviderInterface) {
            return ['namesFound' => [], 'advisories' => []];
        }
        foreach ($packageConstraintMap as $name => $constraint) {
            if (!$this->isAllowed($name)) {
                unset($packageConstraintMap[$name]);
            }
        }
        return $this->repo->getSecurityAdvisories($packageConstraintMap, $allowPartialAdvisories);
    }
    private function isAllowed(string $name): bool
    {
        if (!$this->only && !$this->exclude) {
            return \true;
        }
        if ($this->only) {
            return Preg::isMatch($this->only, $name);
        }
        if ($this->exclude === null) {
            return \true;
        }
        return !Preg::isMatch($this->exclude, $name);
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer\Repository;

use Composer\Package\BasePackage;
use Composer\Package\PackageInterface;
use Composer\Package\Version\VersionParser;
use Composer\Semver\Constraint\ConstraintInterface;
use Composer\Semver\Constraint\Constraint;
use Composer\Semver\Constraint\MatchAllConstraint;
use Composer\Package\RootPackageInterface;
use Composer\Package\Link;
/**
 * Installed repository is a composite of all installed repo types.
 *
 * The main use case is tagging a repo as an "installed" repository, and offering a way to get providers/replacers easily.
 *
 * Installed repos are LockArrayRepository, InstalledRepositoryInterface, RootPackageRepository and PlatformRepository
 *
 * @author Jordi Boggiano <j.boggiano@seld.be>
 */
class InstalledRepository extends \Composer\Repository\CompositeRepository
{
    /**
     * @param ConstraintInterface|string|null $constraint
     *
     * @return BasePackage[]
     */
    public function findPackagesWithReplacersAndProviders(string $name, $constraint = null): array
    {
        $name = strtolower($name);
        if (null !== $constraint && !$constraint instanceof ConstraintInterface) {
            $versionParser = new VersionParser();
            $constraint = $versionParser->parseConstraints($constraint);
        }
        $matches = [];
        foreach ($this->getRepositories() as $repo) {
            foreach ($repo->getPackages() as $candidate) {
                if ($name === $candidate->getName()) {
                    if (null === $constraint || $constraint->matches(new Constraint('==', $candidate->getVersion()))) {
                        $matches[] = $candidate;
                    }
                    continue;
                }
                foreach (array_merge($candidate->getProvides(), $candidate->getReplaces()) as $link) {
                    if ($name === $link->getTarget() && ($constraint === null || $constraint->matches($link->getConstraint()))) {
                        $matches[] = $candidate;
                        continue 2;
                    }
                }
            }
        }
        return $matches;
    }
    /**
     * Returns a list of links causing the requested needle packages to be installed, as an associative array with the
     * dependent's name as key, and an array containing in order the PackageInterface and Link describing the relationship
     * as values. If recursive lookup was requested a third value is returned containing an identically formed array up
     * to the root package. That third value will be false in case a circular recursion was detected.
     *
     * @param  string|string[]          $needle        The package name(s) to inspect.
     * @param  ConstraintInterface|null $constraint    Optional constraint to filter by.
     * @param  bool                     $invert        Whether to invert matches to discover reasons for the package *NOT* to be installed.
     * @param  bool                     $recurse       Whether to recursively expand the requirement tree up to the root package.
     * @param  string[]                 $packagesFound Used internally when recurring
     *
     * @return array[] An associative array of arrays as described above.
     * @phpstan-return array<array{0: PackageInterface, 1: Link, 2: array<mixed>|false}>
     */
    public function getDependents($needle, ?ConstraintInterface $constraint = null, bool $invert = \false, bool $recurse = \true, ?array $packagesFound = null): array
    {
        $needles = array_map('strtolower', (array) $needle);
        $results = [];
        // initialize the array with the needles before any recursion occurs
        if (null === $packagesFound) {
            $packagesFound = $needles;
        }
        // locate root package for use below
        $rootPackage = null;
        foreach ($this->getPackages() as $package) {
            if ($package instanceof RootPackageInterface) {
                $rootPackage = $package;
                break;
            }
        }
        // Loop over all currently installed packages.
        foreach ($this->getPackages() as $package) {
            $links = $package->getRequires();
            // each loop needs its own "tree" as we want to show the complete dependent set of every needle
            // without warning all the time about finding circular deps
            $packagesInTree = $packagesFound;
            // Replacements are considered valid reasons for a package to be installed during forward resolution
            if (!$invert) {
                $links += $package->getReplaces();
                // On forward search, check if any replaced package was required and add the replaced
                // packages to the list of needles. Contrary to the cross-reference link check below,
                // replaced packages are the target of links.
                foreach ($package->getReplaces() as $link) {
                    foreach ($needles as $needle) {
                        if ($link->getSource() === $needle) {
                            if ($constraint === null || $link->getConstraint()->matches($constraint) === \true) {
                                // already displayed this node's dependencies, cutting short
                                if (in_array($link->getTarget(), $packagesInTree)) {
                                    $results[] = [$package, $link, \false];
                                    continue;
                                }
                                $packagesInTree[] = $link->getTarget();
                                $dependents = $recurse ? $this->getDependents($link->getTarget(), null, \false, \true, $packagesInTree) : [];
                                $results[] = [$package, $link, $dependents];
                                $needles[] = $link->getTarget();
                            }
                        }
                    }
                }
                unset($needle);
            }
            // Require-dev is only relevant for the root package
            if ($package instanceof RootPackageInterface) {
                $links += $package->getDevRequires();
            }
            // Cross-reference all discovered links to the needles
            foreach ($links as $link) {
                foreach ($needles as $needle) {
                    if ($link->getTarget() === $needle) {
                        if ($constraint === null || $link->getConstraint()->matches($constraint) === !$invert) {
                            // already displayed this node's dependencies, cutting short
                            if (in_array($link->getSource(), $packagesInTree)) {
                                $results[] = [$package, $link, \false];
                                continue;
                            }
                            $packagesInTree[] = $link->getSource();
                            $dependents = $recurse ? $this->getDependents($link->getSource(), null, \false, \true, $packagesInTree) : [];
                            $results[] = [$package, $link, $dependents];
                        }
                    }
                }
            }
            // When inverting, we need to check for conflicts of the needles against installed packages
            if ($invert && in_array($package->getName(), $needles, \true)) {
                foreach ($package->getConflicts() as $link) {
                    foreach ($this->findPackages($link->getTarget()) as $pkg) {
                        $version = new Constraint('=', $pkg->getVersion());
                        if ($link->getConstraint()->matches($version) === $invert) {
                            $results[] = [$package, $link, \false];
                        }
                    }
                }
            }
            // List conflicts against X as they may explain why the current version was selected, or explain why it is rejected if the conflict matched when inverting
            foreach ($package->getConflicts() as $link) {
                if (in_array($link->getTarget(), $needles, \true)) {
                    foreach ($this->findPackages($link->getTarget()) as $pkg) {
                        $version = new Constraint('=', $pkg->getVersion());
                        if ($link->getConstraint()->matches($version) === $invert) {
                            $results[] = [$package, $link, \false];
                        }
                    }
                }
            }
            // When inverting, we need to check for conflicts of the needles' requirements against installed packages
            if ($invert && $constraint && in_array($package->getName(), $needles, \true) && $constraint->matches(new Constraint('=', $package->getVersion()))) {
                foreach ($package->getRequires() as $link) {
                    if (\Composer\Repository\PlatformRepository::isPlatformPackage($link->getTarget())) {
                        if ($this->findPackage($link->getTarget(), $link->getConstraint())) {
                            continue;
                        }
                        $platformPkg = $this->findPackage($link->getTarget(), '*');
                        $description = $platformPkg ? 'but ' . $platformPkg->getPrettyVersion() . ' is installed' : 'but it is missing';
                        $results[] = [$package, new Link($package->getName(), $link->getTarget(), new MatchAllConstraint(), Link::TYPE_REQUIRE, $link->getPrettyConstraint() . ' ' . $description), \false];
                        continue;
                    }
                    foreach ($this->getPackages() as $pkg) {
                        if (!in_array($link->getTarget(), $pkg->getNames())) {
                            continue;
                        }
                        $version = new Constraint('=', $pkg->getVersion());
                        if ($link->getTarget() !== $pkg->getName()) {
                            foreach (array_merge($pkg->getReplaces(), $pkg->getProvides()) as $prov) {
                                if ($link->getTarget() === $prov->getTarget()) {
                                    $version = $prov->getConstraint();
                                    break;
                                }
                            }
                        }
                        if (!$link->getConstraint()->matches($version)) {
                            // if we have a root package (we should but can not guarantee..) we show
                            // the root requires as well to perhaps allow to find an issue there
                            if ($rootPackage) {
                                foreach (array_merge($rootPackage->getRequires(), $rootPackage->getDevRequires()) as $rootReq) {
                                    if (in_array($rootReq->getTarget(), $pkg->getNames()) && !$rootReq->getConstraint()->matches($link->getConstraint())) {
                                        $results[] = [$package, $link, \false];
                                        $results[] = [$rootPackage, $rootReq, \false];
                                        continue 3;
                                    }
                                }
                                $results[] = [$package, $link, \false];
                                $results[] = [$rootPackage, new Link($rootPackage->getName(), $link->getTarget(), new MatchAllConstraint(), Link::TYPE_DOES_NOT_REQUIRE, 'but ' . $pkg->getPrettyVersion() . ' is installed'), \false];
                            } else {
                                // no root so let's just print whatever we found
                                $results[] = [$package, $link, \false];
                            }
                        }
                        continue 2;
                    }
                }
            }
        }
        ksort($results);
        return $results;
    }
    public function getRepoName(): string
    {
        return 'installed repo (' . implode(', ', array_map(static function ($repo): string {
            return $repo->getRepoName();
        }, $this->getRepositories())) . ')';
    }
    /**
     * @inheritDoc
     */
    public function addRepository(\Composer\Repository\RepositoryInterface $repository): void
    {
        if ($repository instanceof \Composer\Repository\LockArrayRepository || $repository instanceof \Composer\Repository\InstalledRepositoryInterface || $repository instanceof \Composer\Repository\RootPackageRepository || $repository instanceof \Composer\Repository\PlatformRepository) {
            parent::addRepository($repository);
            return;
        }
        throw new \LogicException('An InstalledRepository can not contain a repository of type ' . get_class($repository) . ' (' . $repository->getRepoName() . ')');
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer\Repository;

use Composer\Semver\Constraint\ConstraintInterface;
use Composer\Advisory\PartialSecurityAdvisory;
use Composer\Advisory\SecurityAdvisory;
/**
 * Repositories that allow fetching security advisory data
 *
 * @author Jordi Boggiano <j.boggiano@seld.be>
 * @internal
 */
interface AdvisoryProviderInterface
{
    public function hasSecurityAdvisories(): bool;
    /**
     * @param array<string, ConstraintInterface> $packageConstraintMap Map of package name to constraint (can be MatchAllConstraint to fetch all advisories)
     * @return ($allowPartialAdvisories is true ? array{namesFound: string[], advisories: array<string, list<PartialSecurityAdvisory|SecurityAdvisory>>} : array{namesFound: string[], advisories: array<string, list<SecurityAdvisory>>})
     */
    public function getSecurityAdvisories(array $packageConstraintMap, bool $allowPartialAdvisories = \false): array;
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer\Repository;

use Composer\Json\JsonFile;
use Composer\Package\Loader\ArrayLoader;
use Composer\Package\PackageInterface;
use Composer\Package\RootAliasPackage;
use Composer\Package\RootPackageInterface;
use Composer\Package\AliasPackage;
use Composer\Package\Dumper\ArrayDumper;
use Composer\Installer\InstallationManager;
use Composer\Pcre\Preg;
use Composer\Util\Filesystem;
use Composer\Util\Platform;
/**
 * Filesystem repository.
 *
 * @author Konstantin Kudryashov <ever.zet@gmail.com>
 * @author Jordi Boggiano <j.boggiano@seld.be>
 */
class FilesystemRepository extends \Composer\Repository\WritableArrayRepository
{
    /** @var JsonFile */
    protected $file;
    /** @var bool */
    private $dumpVersions;
    /** @var ?RootPackageInterface */
    private $rootPackage;
    /** @var Filesystem */
    private $filesystem;
    /** @var bool|null */
    private $devMode = null;
    /**
     * Initializes filesystem repository.
     *
     * @param JsonFile              $repositoryFile repository json file
     * @param ?RootPackageInterface $rootPackage    Must be provided if $dumpVersions is true
     */
    public function __construct(JsonFile $repositoryFile, bool $dumpVersions = \false, ?RootPackageInterface $rootPackage = null, ?Filesystem $filesystem = null)
    {
        parent::__construct();
        $this->file = $repositoryFile;
        $this->dumpVersions = $dumpVersions;
        $this->rootPackage = $rootPackage;
        $this->filesystem = $filesystem ?: new Filesystem();
        if ($dumpVersions && !$rootPackage) {
            throw new \InvalidArgumentException('Expected a root package instance if $dumpVersions is true');
        }
    }
    /**
     * @return bool|null true if dev requirements were installed, false if --no-dev was used, null if yet unknown
     */
    public function getDevMode()
    {
        return $this->devMode;
    }
    /**
     * Initializes repository (reads file, or remote address).
     */
    protected function initialize()
    {
        parent::initialize();
        if (!$this->file->exists()) {
            return;
        }
        try {
            $data = $this->file->read();
            if (isset($data['packages'])) {
                $packages = $data['packages'];
            } else {
                $packages = $data;
            }
            if (isset($data['dev-package-names'])) {
                $this->setDevPackageNames($data['dev-package-names']);
            }
            if (isset($data['dev'])) {
                $this->devMode = $data['dev'];
            }
            if (!is_array($packages)) {
                throw new \UnexpectedValueException('Could not parse package list from the repository');
            }
        } catch (\Exception $e) {
            throw new \Composer\Repository\InvalidRepositoryException('Invalid repository data in ' . $this->file->getPath() . ', packages could not be loaded: [' . get_class($e) . '] ' . $e->getMessage());
        }
        $loader = new ArrayLoader(null, \true);
        foreach ($packages as $packageData) {
            $package = $loader->load($packageData);
            $this->addPackage($package);
        }
    }
    public function reload()
    {
        $this->packages = null;
        $this->initialize();
    }
    /**
     * Writes writable repository.
     */
    public function write(bool $devMode, InstallationManager $installationManager)
    {
        $data = ['packages' => [], 'dev' => $devMode, 'dev-package-names' => []];
        $dumper = new ArrayDumper();
        // make sure the directory is created so we can realpath it
        // as realpath() does some additional normalizations with network paths that normalizePath does not
        // and we need to find shortest path correctly
        $repoDir = dirname($this->file->getPath());
        $this->filesystem->ensureDirectoryExists($repoDir);
        $repoDir = $this->filesystem->normalizePath(realpath($repoDir));
        $installPaths = [];
        foreach ($this->getCanonicalPackages() as $package) {
            $pkgArray = $dumper->dump($package);
            $path = $installationManager->getInstallPath($package);
            $installPath = null;
            if ('' !== $path && null !== $path) {
                $normalizedPath = $this->filesystem->normalizePath($this->filesystem->isAbsolutePath($path) ? $path : Platform::getCwd() . '/' . $path);
                $installPath = $this->filesystem->findShortestPath($repoDir, $normalizedPath, \true);
            }
            $installPaths[$package->getName()] = $installPath;
            $pkgArray['install-path'] = $installPath;
            $data['packages'][] = $pkgArray;
            // only write to the files the names which are really installed, as we receive the full list
            // of dev package names before they get installed during composer install
            if (in_array($package->getName(), $this->devPackageNames, \true)) {
                $data['dev-package-names'][] = $package->getName();
            }
        }
        sort($data['dev-package-names']);
        usort($data['packages'], static function ($a, $b): int {
            return strcmp($a['name'], $b['name']);
        });
        $this->file->write($data);
        if ($this->dumpVersions) {
            $versions = $this->generateInstalledVersions($installationManager, $installPaths, $devMode, $repoDir);
            $this->filesystem->filePutContentsIfModified($repoDir . '/installed.php', '<?php return ' . $this->dumpToPhpCode($versions) . ';' . "\n");
            $installedVersionsClass = file_get_contents(__DIR__ . '/../InstalledVersions.php');
            // this normally should not happen but during upgrades of Composer when it is installed in the project it is a possibility
            if ($installedVersionsClass !== \false) {
                $this->filesystem->filePutContentsIfModified($repoDir . '/InstalledVersions.php', $installedVersionsClass);
                // make sure the in memory state is up to date with on disk
                \Composer\InstalledVersions::reload($versions);
                // make sure the selfDir matches the expected data at runtime if the class was loaded from the vendor dir, as it may have been
                // loaded from the Composer sources, causing packages to appear twice in that case if the installed.php is loaded in addition to the
                // in memory loaded data from above
                try {
                    $reflProp = new \ReflectionProperty(\Composer\InstalledVersions::class, 'selfDir');
                    \PHP_VERSION_ID < 80100 and $reflProp->setAccessible(\true);
                    $reflProp->setValue(null, strtr($repoDir, '\\', '/'));
                    $reflProp = new \ReflectionProperty(\Composer\InstalledVersions::class, 'installedIsLocalDir');
                    \PHP_VERSION_ID < 80100 and $reflProp->setAccessible(\true);
                    $reflProp->setValue(null, \true);
                } catch (\ReflectionException $e) {
                    if (!Preg::isMatch('{Property .*? does not exist}i', $e->getMessage())) {
                        throw $e;
                    }
                    // noop, if outdated class is loaded we do not want to cause trouble
                }
            }
        }
    }
    /**
     * As we load the file from vendor dir during bootstrap, we need to make sure it contains only expected code before executing it
     *
     * @internal
     */
    public static function safelyLoadInstalledVersions(string $path): bool
    {
        $installedVersionsData = @file_get_contents($path);
        $pattern = <<<'REGEX'
{(?(DEFINE)
   (?<number>  -? \s*+ \d++ (?:\.\d++)? )
   (?<boolean> true | false | null )
   (?<strings> (?&string) (?: \s*+ \. \s*+ (?&string))*+ )
   (?<string>  (?: " (?:[^"\\$]*+ | \\ ["\\0] )* " | ' (?:[^'\\]*+ | \\ ['\\] )* ' ) )
   (?<array>   array\( \s*+ (?: (?:(?&number)|(?&strings)) \s*+ => \s*+ (?: (?:__DIR__ \s*+ \. \s*+)? (?&strings) | (?&value) ) \s*+, \s*+ )*+  \s*+ \) )
   (?<value>   (?: (?&number) | (?&boolean) | (?&strings) | (?&array) ) )
)
^<\?php\s++return\s++(?&array)\s*+;$}ix
REGEX;
        if (is_string($installedVersionsData) && Preg::isMatch($pattern, trim($installedVersionsData))) {
            \Composer\InstalledVersions::reload(eval('?>' . Preg::replace('{=>\s*+__DIR__\s*+\.\s*+([\'"])}', '=> ' . var_export(dirname($path), \true) . ' . $1', $installedVersionsData)));
            return \true;
        }
        return \false;
    }
    /**
     * @param array<mixed> $array
     */
    private function dumpToPhpCode(array $array = [], int $level = 0): string
    {
        $lines = "array(\n";
        $level++;
        foreach ($array as $key => $value) {
            $lines .= str_repeat('    ', $level);
            $lines .= is_int($key) ? $key . ' => ' : var_export($key, \true) . ' => ';
            if (is_array($value)) {
                if (!empty($value)) {
                    $lines .= $this->dumpToPhpCode($value, $level);
                } else {
                    $lines .= "array(),\n";
                }
            } elseif ($key === 'install_path' && is_string($value)) {
                if ($this->filesystem->isAbsolutePath($value)) {
                    $lines .= var_export($value, \true) . ",\n";
                } else {
                    $lines .= "__DIR__ . " . var_export('/' . $value, \true) . ",\n";
                }
            } elseif (is_string($value)) {
                $lines .= var_export($value, \true) . ",\n";
            } elseif (is_bool($value)) {
                $lines .= ($value ? 'true' : 'false') . ",\n";
            } elseif (is_null($value)) {
                $lines .= "null,\n";
            } else {
                throw new \UnexpectedValueException('Unexpected type ' . get_debug_type($value));
            }
        }
        $lines .= str_repeat('    ', $level - 1) . ')' . ($level - 1 === 0 ? '' : ",\n");
        return $lines;
    }
    /**
     * @param array<string, string> $installPaths
     *
     * @return array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>}
     */
    private function generateInstalledVersions(InstallationManager $installationManager, array $installPaths, bool $devMode, string $repoDir): array
    {
        $devPackages = array_flip($this->devPackageNames);
        $packages = $this->getPackages();
        if (null === $this->rootPackage) {
            throw new \LogicException('It should not be possible to dump packages if no root package is given');
        }
        $packages[] = $rootPackage = $this->rootPackage;
        while ($rootPackage instanceof RootAliasPackage) {
            $rootPackage = $rootPackage->getAliasOf();
            $packages[] = $rootPackage;
        }
        $versions = ['root' => $this->dumpRootPackage($rootPackage, $installPaths, $devMode, $repoDir, $devPackages), 'versions' => []];
        // add real installed packages
        foreach ($packages as $package) {
            if ($package instanceof AliasPackage) {
                continue;
            }
            $versions['versions'][$package->getName()] = $this->dumpInstalledPackage($package, $installPaths, $repoDir, $devPackages);
        }
        // add provided/replaced packages
        foreach ($packages as $package) {
            $isDevPackage = isset($devPackages[$package->getName()]);
            foreach ($package->getReplaces() as $replace) {
                // exclude platform replaces as when they are really there we can not check for their presence
                if (\Composer\Repository\PlatformRepository::isPlatformPackage($replace->getTarget())) {
                    continue;
                }
                if (!isset($versions['versions'][$replace->getTarget()]['dev_requirement'])) {
                    $versions['versions'][$replace->getTarget()]['dev_requirement'] = $isDevPackage;
                } elseif (!$isDevPackage) {
                    $versions['versions'][$replace->getTarget()]['dev_requirement'] = \false;
                }
                $replaced = $replace->getPrettyConstraint();
                if ($replaced === 'self.version') {
                    $replaced = $package->getPrettyVersion();
                }
                if (!isset($versions['versions'][$replace->getTarget()]['replaced']) || !in_array($replaced, $versions['versions'][$replace->getTarget()]['replaced'], \true)) {
                    $versions['versions'][$replace->getTarget()]['replaced'][] = $replaced;
                }
            }
            foreach ($package->getProvides() as $provide) {
                // exclude platform provides as when they are really there we can not check for their presence
                if (\Composer\Repository\PlatformRepository::isPlatformPackage($provide->getTarget())) {
                    continue;
                }
                if (!isset($versions['versions'][$provide->getTarget()]['dev_requirement'])) {
                    $versions['versions'][$provide->getTarget()]['dev_requirement'] = $isDevPackage;
                } elseif (!$isDevPackage) {
                    $versions['versions'][$provide->getTarget()]['dev_requirement'] = \false;
                }
                $provided = $provide->getPrettyConstraint();
                if ($provided === 'self.version') {
                    $provided = $package->getPrettyVersion();
                }
                if (!isset($versions['versions'][$provide->getTarget()]['provided']) || !in_array($provided, $versions['versions'][$provide->getTarget()]['provided'], \true)) {
                    $versions['versions'][$provide->getTarget()]['provided'][] = $provided;
                }
            }
        }
        // add aliases
        foreach ($packages as $package) {
            if (!$package instanceof AliasPackage) {
                continue;
            }
            $versions['versions'][$package->getName()]['aliases'][] = $package->getPrettyVersion();
            if ($package instanceof RootPackageInterface) {
                $versions['root']['aliases'][] = $package->getPrettyVersion();
            }
        }
        ksort($versions['versions']);
        ksort($versions);
        foreach ($versions['versions'] as $name => $version) {
            foreach (['aliases', 'replaced', 'provided'] as $key) {
                if (isset($versions['versions'][$name][$key])) {
                    sort($versions['versions'][$name][$key], \SORT_NATURAL);
                }
            }
        }
        return $versions;
    }
    /**
     * @param array<string, string> $installPaths
     * @param array<string, int> $devPackages
     * @return array{pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev_requirement: bool}
     */
    private function dumpInstalledPackage(PackageInterface $package, array $installPaths, string $repoDir, array $devPackages): array
    {
        $reference = null;
        if ($package->getInstallationSource()) {
            $reference = $package->getInstallationSource() === 'source' ? $package->getSourceReference() : $package->getDistReference();
        }
        if (null === $reference) {
            $reference = ($package->getSourceReference() ?: $package->getDistReference()) ?: null;
        }
        if ($package instanceof RootPackageInterface) {
            $to = $this->filesystem->normalizePath(realpath(Platform::getCwd()));
            $installPath = $this->filesystem->findShortestPath($repoDir, $to, \true);
        } else {
            $installPath = $installPaths[$package->getName()];
        }
        $data = ['pretty_version' => $package->getPrettyVersion(), 'version' => $package->getVersion(), 'reference' => $reference, 'type' => $package->getType(), 'install_path' => $installPath, 'aliases' => [], 'dev_requirement' => isset($devPackages[$package->getName()])];
        return $data;
    }
    /**
     * @param array<string, string> $installPaths
     * @param array<string, int> $devPackages
     * @return array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}
     */
    private function dumpRootPackage(RootPackageInterface $package, array $installPaths, bool $devMode, string $repoDir, array $devPackages)
    {
        $data = $this->dumpInstalledPackage($package, $installPaths, $repoDir, $devPackages);
        return ['name' => $package->getName(), 'pretty_version' => $data['pretty_version'], 'version' => $data['version'], 'reference' => $data['reference'], 'type' => $data['type'], 'install_path' => $data['install_path'], 'aliases' => $data['aliases'], 'dev' => $devMode];
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer\Repository;

/**
 * Installed array repository.
 *
 * This is used as an in-memory InstalledRepository mostly for testing purposes
 *
 * @author Jordi Boggiano <j.boggiano@seld.be>
 */
class InstalledArrayRepository extends \Composer\Repository\WritableArrayRepository implements \Composer\Repository\InstalledRepositoryInterface
{
    public function getRepoName(): string
    {
        return 'installed ' . parent::getRepoName();
    }
    /**
     * @inheritDoc
     */
    public function isFresh(): bool
    {
        // this is not a completely correct implementation but there is no way to
        // distinguish an empty repo and a newly created one given this is all in-memory
        return $this->count() === 0;
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer\Repository;

/**
 * Configurable repository interface.
 *
 * @author Lukas Homza <lukashomz@gmail.com>
 */
interface ConfigurableRepositoryInterface
{
    /**
     * @return mixed[]
     */
    public function getRepoConfig();
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer\Repository;

/**
 * Exception thrown when a package repository is utterly broken
 *
 * @author Jordi Boggiano <j.boggiano@seld.be>
 */
class InvalidRepositoryException extends \Exception
{
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer\Util;

use Composer\Package\PackageInterface;
use Composer\Package\RootPackageInterface;
class PackageSorter
{
    /**
     * Returns the most recent version of a set of packages
     *
     * This is ideally the default branch version, or failing that it will return the package with the highest version
     *
     * @template T of PackageInterface
     * @param array<T> $packages
     * @return ($packages is non-empty-array<T> ? T : T|null)
     */
    public static function getMostCurrentVersion(array $packages): ?PackageInterface
    {
        if (count($packages) === 0) {
            return null;
        }
        $highest = reset($packages);
        foreach ($packages as $candidate) {
            if ($candidate->isDefaultBranch()) {
                return $candidate;
            }
            if (version_compare($highest->getVersion(), $candidate->getVersion(), '<')) {
                $highest = $candidate;
            }
        }
        return $highest;
    }
    /**
     * Sorts packages by name
     *
     * @template T of PackageInterface
     * @param array<T> $packages
     * @return array<T>
     */
    public static function sortPackagesAlphabetically(array $packages): array
    {
        usort($packages, static function (PackageInterface $a, PackageInterface $b) {
            return $a->getName() <=> $b->getName();
        });
        return $packages;
    }
    /**
     * Sorts packages by dependency weight
     *
     * Packages of equal weight are sorted alphabetically
     *
     * @param  PackageInterface[] $packages
     * @param  array<string, int> $weights Pre-set weights for some packages to give them more (negative number) or less (positive) weight offsets
     * @return PackageInterface[] sorted array
     */
    public static function sortPackages(array $packages, array $weights = []): array
    {
        $usageList = [];
        foreach ($packages as $package) {
            $links = $package->getRequires();
            if ($package instanceof RootPackageInterface) {
                $links = array_merge($links, $package->getDevRequires());
            }
            foreach ($links as $link) {
                $target = $link->getTarget();
                $usageList[$target][] = $package->getName();
            }
        }
        $computing = [];
        $computed = [];
        $computeImportance = static function ($name) use (&$computeImportance, &$computing, &$computed, $usageList, $weights) {
            // reusing computed importance
            if (isset($computed[$name])) {
                return $computed[$name];
            }
            // canceling circular dependency
            if (isset($computing[$name])) {
                return 0;
            }
            $computing[$name] = \true;
            $weight = $weights[$name] ?? 0;
            if (isset($usageList[$name])) {
                foreach ($usageList[$name] as $user) {
                    $weight -= 1 - $computeImportance($user);
                }
            }
            unset($computing[$name]);
            $computed[$name] = $weight;
            return $weight;
        };
        $weightedPackages = [];
        foreach ($packages as $index => $package) {
            $name = $package->getName();
            $weight = $computeImportance($name);
            $weightedPackages[] = ['name' => $name, 'weight' => $weight, 'index' => $index];
        }
        usort($weightedPackages, static function (array $a, array $b): int {
            if ($a['weight'] !== $b['weight']) {
                return $a['weight'] - $b['weight'];
            }
            return strnatcasecmp($a['name'], $b['name']);
        });
        $sortedPackages = [];
        foreach ($weightedPackages as $pkg) {
            $sortedPackages[] = $packages[$pkg['index']];
        }
        return $sortedPackages;
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer\Util;

use Composer\Package\Loader\ArrayLoader;
use Composer\Package\Loader\ValidatingArrayLoader;
use Composer\Package\Loader\InvalidPackageException;
use Composer\Json\JsonValidationException;
use Composer\IO\IOInterface;
use Composer\Json\JsonFile;
use Composer\Pcre\Preg;
use Composer\Spdx\SpdxLicenses;
use _ContaoManager\Seld\JsonLint\DuplicateKeyException;
use _ContaoManager\Seld\JsonLint\JsonParser;
/**
 * Validates a composer configuration.
 *
 * @author Robert Schönthal <seroscho@googlemail.com>
 * @author Jordi Boggiano <j.boggiano@seld.be>
 */
class ConfigValidator
{
    public const CHECK_VERSION = 1;
    /** @var IOInterface */
    private $io;
    public function __construct(IOInterface $io)
    {
        $this->io = $io;
    }
    /**
     * Validates the config, and returns the result.
     *
     * @param string $file                       The path to the file
     * @param int    $arrayLoaderValidationFlags Flags for ArrayLoader validation
     * @param int    $flags                      Flags for validation
     *
     * @return array{list<string>, list<string>, list<string>} a triple containing the errors, publishable errors, and warnings
     */
    public function validate(string $file, int $arrayLoaderValidationFlags = ValidatingArrayLoader::CHECK_ALL, int $flags = self::CHECK_VERSION): array
    {
        $errors = [];
        $publishErrors = [];
        $warnings = [];
        // validate json schema
        $laxValid = \false;
        $manifest = null;
        try {
            $json = new JsonFile($file, null, $this->io);
            $manifest = $json->read();
            $json->validateSchema(JsonFile::LAX_SCHEMA);
            $laxValid = \true;
            $json->validateSchema();
        } catch (JsonValidationException $e) {
            foreach ($e->getErrors() as $message) {
                if ($laxValid) {
                    $publishErrors[] = $message;
                } else {
                    $errors[] = $message;
                }
            }
        } catch (\Exception $e) {
            $errors[] = $e->getMessage();
            return [$errors, $publishErrors, $warnings];
        }
        if (is_array($manifest)) {
            $jsonParser = new JsonParser();
            try {
                $jsonParser->parse((string) file_get_contents($file), JsonParser::DETECT_KEY_CONFLICTS);
            } catch (DuplicateKeyException $e) {
                $details = $e->getDetails();
                $warnings[] = 'Key ' . $details['key'] . ' is a duplicate in ' . $file . ' at line ' . $details['line'];
            }
        }
        // validate actual data
        if (empty($manifest['license'])) {
            $warnings[] = 'No license specified, it is recommended to do so. For closed-source software you may use "proprietary" as license.';
        } else {
            $licenses = (array) $manifest['license'];
            // strip proprietary since it's not a valid SPDX identifier, but is accepted by composer
            foreach ($licenses as $key => $license) {
                if ('proprietary' === $license) {
                    unset($licenses[$key]);
                }
            }
            $licenseValidator = new SpdxLicenses();
            foreach ($licenses as $license) {
                $spdxLicense = $licenseValidator->getLicenseByIdentifier($license);
                if ($spdxLicense && $spdxLicense[3]) {
                    if (Preg::isMatch('{^[AL]?GPL-[123](\.[01])?\+$}i', $license)) {
                        $warnings[] = sprintf('License "%s" is a deprecated SPDX license identifier, use "' . str_replace('+', '', $license) . '-or-later" instead', $license);
                    } elseif (Preg::isMatch('{^[AL]?GPL-[123](\.[01])?$}i', $license)) {
                        $warnings[] = sprintf('License "%s" is a deprecated SPDX license identifier, use "' . $license . '-only" or "' . $license . '-or-later" instead', $license);
                    } else {
                        $warnings[] = sprintf('License "%s" is a deprecated SPDX license identifier, see https://spdx.org/licenses/', $license);
                    }
                }
            }
        }
        if ($flags & self::CHECK_VERSION && isset($manifest['version'])) {
            $warnings[] = 'The version field is present, it is recommended to leave it out if the package is published on Packagist.';
        }
        if (!empty($manifest['name']) && Preg::isMatch('{[A-Z]}', $manifest['name'])) {
            $suggestName = Preg::replace('{(?:([a-z])([A-Z])|([A-Z])([A-Z][a-z]))}', '\1\3-\2\4', $manifest['name']);
            $suggestName = strtolower($suggestName);
            $publishErrors[] = sprintf('Name "%s" does not match the best practice (e.g. lower-cased/with-dashes). We suggest using "%s" instead. As such you will not be able to submit it to Packagist.', $manifest['name'], $suggestName);
        }
        if (!empty($manifest['type']) && $manifest['type'] === 'composer-installer') {
            $warnings[] = "The package type 'composer-installer' is deprecated. Please distribute your custom installers as plugins from now on. See https://getcomposer.org/doc/articles/plugins.md for plugin documentation.";
        }
        // check for require-dev overrides
        if (isset($manifest['require'], $manifest['require-dev'])) {
            $requireOverrides = array_intersect_key($manifest['require'], $manifest['require-dev']);
            if (!empty($requireOverrides)) {
                $plural = count($requireOverrides) > 1 ? 'are' : 'is';
                $warnings[] = implode(', ', array_keys($requireOverrides)) . " {$plural} required both in require and require-dev, this can lead to unexpected behavior";
            }
        }
        // check for meaningless provide/replace satisfying requirements
        foreach (['provide', 'replace'] as $linkType) {
            if (isset($manifest[$linkType])) {
                foreach (['require', 'require-dev'] as $requireType) {
                    if (isset($manifest[$requireType])) {
                        foreach ($manifest[$linkType] as $provide => $constraint) {
                            if (isset($manifest[$requireType][$provide])) {
                                $warnings[] = 'The package ' . $provide . ' in ' . $requireType . ' is also listed in ' . $linkType . ' which satisfies the requirement. Remove it from ' . $linkType . ' if you wish to install it.';
                            }
                        }
                    }
                }
            }
        }
        // check for commit references
        $require = $manifest['require'] ?? [];
        $requireDev = $manifest['require-dev'] ?? [];
        $packages = array_merge($require, $requireDev);
        foreach ($packages as $package => $version) {
            if (Preg::isMatch('/#/', $version)) {
                $warnings[] = sprintf('The package "%s" is pointing to a commit-ref, this is bad practice and can cause unforeseen issues.', $package);
            }
        }
        // report scripts-descriptions for non-existent scripts
        $scriptsDescriptions = $manifest['scripts-descriptions'] ?? [];
        $scripts = $manifest['scripts'] ?? [];
        foreach ($scriptsDescriptions as $scriptName => $scriptDescription) {
            if (!array_key_exists($scriptName, $scripts)) {
                $warnings[] = sprintf('Description for non-existent script "%s" found in "scripts-descriptions"', $scriptName);
            }
        }
        // report scripts-aliases for non-existent scripts
        $scriptAliases = $manifest['scripts-aliases'] ?? [];
        foreach ($scriptAliases as $scriptName => $scriptAlias) {
            if (!array_key_exists($scriptName, $scripts)) {
                $warnings[] = sprintf('Aliases for non-existent script "%s" found in "scripts-aliases"', $scriptName);
            }
        }
        // check for empty psr-0/psr-4 namespace prefixes
        if (isset($manifest['autoload']['psr-0'][''])) {
            $warnings[] = "Defining autoload.psr-0 with an empty namespace prefix is a bad idea for performance";
        }
        if (isset($manifest['autoload']['psr-4'][''])) {
            $warnings[] = "Defining autoload.psr-4 with an empty namespace prefix is a bad idea for performance";
        }
        $loader = new ValidatingArrayLoader(new ArrayLoader(), \true, null, $arrayLoaderValidationFlags);
        try {
            if (!isset($manifest['version'])) {
                $manifest['version'] = '1.0.0';
            }
            if (!isset($manifest['name'])) {
                $manifest['name'] = 'dummy/dummy';
            }
            $loader->load($manifest);
        } catch (InvalidPackageException $e) {
            $errors = array_merge($errors, $e->getErrors());
        }
        $warnings = array_merge($warnings, $loader->getWarnings());
        return [$errors, $publishErrors, $warnings];
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer\Util;

use Composer\Config;
use Composer\IO\IOInterface;
use Composer\Pcre\Preg;
/**
 * @author Jordi Boggiano <j.boggiano@seld.be>
 */
class Git
{
    /** @var string|false|null */
    private static $version = \false;
    /** @var IOInterface */
    protected $io;
    /** @var Config */
    protected $config;
    /** @var ProcessExecutor */
    protected $process;
    /** @var Filesystem */
    protected $filesystem;
    /** @var HttpDownloader */
    protected $httpDownloader;
    public function __construct(IOInterface $io, Config $config, \Composer\Util\ProcessExecutor $process, \Composer\Util\Filesystem $fs)
    {
        $this->io = $io;
        $this->config = $config;
        $this->process = $process;
        $this->filesystem = $fs;
    }
    /**
     * @param IOInterface|null $io If present, a warning is output there instead of throwing, so pass this in only for cases where this is a soft failure
     */
    public static function checkForRepoOwnershipError(string $output, string $path, ?IOInterface $io = null): void
    {
        if (str_contains($output, 'fatal: detected dubious ownership')) {
            $msg = 'The repository at "' . $path . '" does not have the correct ownership and git refuses to use it:' . \PHP_EOL . \PHP_EOL . $output;
            if ($io === null) {
                throw new \RuntimeException($msg);
            }
            $io->writeError('<warning>' . $msg . '</warning>');
        }
    }
    public function setHttpDownloader(\Composer\Util\HttpDownloader $httpDownloader): void
    {
        $this->httpDownloader = $httpDownloader;
    }
    /**
     * Runs a set of commands using the $url or a variation of it (with auth, ssh, ..)
     *
     * Commands should use %url% placeholders for the URL instead of inlining it to allow this function to do its job
     * %sanitizedUrl% is also automatically replaced by the url without user/pass
     *
     * As soon as a single command fails it will halt, so assume the commands are run as && in bash
     *
     * @param non-empty-array<non-empty-list<string>> $commands
     * @param mixed $commandOutput  the output will be written into this var if passed by ref
     *                              if a callable is passed it will be used as output handler
     */
    public function runCommands(array $commands, string $url, ?string $cwd, bool $initialClone = \false, &$commandOutput = null): void
    {
        $callables = [];
        foreach ($commands as $cmd) {
            $callables[] = static function (string $url) use ($cmd): array {
                $map = ['%url%' => $url, '%sanitizedUrl%' => Preg::replace('{://([^@]+?):(.+?)@}', '://', $url)];
                return array_map(static function ($value) use ($map): string {
                    return $map[$value] ?? $value;
                }, $cmd);
            };
        }
        // @phpstan-ignore method.deprecated
        $this->runCommand($callables, $url, $cwd, $initialClone, $commandOutput);
    }
    /**
     * @param callable|array<callable> $commandCallable
     * @param mixed       $commandOutput  the output will be written into this var if passed by ref
     *                                    if a callable is passed it will be used as output handler
     * @deprecated Use runCommands with placeholders instead of callbacks for simplicity
     */
    public function runCommand($commandCallable, string $url, ?string $cwd, bool $initialClone = \false, &$commandOutput = null): void
    {
        $commandCallables = is_callable($commandCallable) ? [$commandCallable] : $commandCallable;
        $lastCommand = '';
        // Ensure we are allowed to use this URL by config
        $this->config->prohibitUrlByConfig($url, $this->io);
        if ($initialClone) {
            $origCwd = $cwd;
        }
        $runCommands = function ($url) use ($commandCallables, $cwd, &$commandOutput, &$lastCommand, $initialClone) {
            $collectOutputs = !is_callable($commandOutput);
            $outputs = [];
            $status = 0;
            $counter = 0;
            foreach ($commandCallables as $callable) {
                $lastCommand = $callable($url);
                if ($collectOutputs) {
                    $outputs[] = '';
                    $output =& $outputs[count($outputs) - 1];
                } else {
                    $output =& $commandOutput;
                }
                $status = $this->process->execute($lastCommand, $output, $initialClone && $counter === 0 ? null : $cwd);
                if ($status !== 0) {
                    break;
                }
                $counter++;
            }
            if ($collectOutputs) {
                $commandOutput = implode('', $outputs);
            }
            return $status;
        };
        if (Preg::isMatch('{^ssh://[^@]+@[^:]+:[^0-9]+}', $url)) {
            throw new \InvalidArgumentException('The source URL ' . $url . ' is invalid, ssh URLs should have a port number after ":".' . "\n" . 'Use ssh://git@example.com:22/path or just git@example.com:path if you do not want to provide a password or custom port.');
        }
        if (!$initialClone) {
            // capture username/password from URL if there is one and we have no auth configured yet
            $this->process->execute(['git', 'remote', '-v'], $output, $cwd);
            if (Preg::isMatchStrictGroups('{^(?:composer|origin)\s+https?://(.+):(.+)@([^/]+)}im', $output, $match) && !$this->io->hasAuthentication($match[3])) {
                $this->io->setAuthentication($match[3], rawurldecode($match[1]), rawurldecode($match[2]));
            }
        }
        $protocols = $this->config->get('github-protocols');
        // public github, autoswitch protocols
        // @phpstan-ignore composerPcre.maybeUnsafeStrictGroups
        if (Preg::isMatchStrictGroups('{^(?:https?|git)://' . self::getGitHubDomainsRegex($this->config) . '/(.*)}', $url, $match)) {
            $messages = [];
            foreach ($protocols as $protocol) {
                if ('ssh' === $protocol) {
                    $protoUrl = "git@" . $match[1] . ":" . $match[2];
                } else {
                    $protoUrl = $protocol . "://" . $match[1] . "/" . $match[2];
                }
                if (0 === $runCommands($protoUrl)) {
                    return;
                }
                $messages[] = '- ' . $protoUrl . "\n" . Preg::replace('#^#m', '  ', $this->process->getErrorOutput());
                if ($initialClone && isset($origCwd)) {
                    $this->filesystem->removeDirectory($origCwd);
                }
            }
            // failed to checkout, first check git accessibility
            if (!$this->io->hasAuthentication($match[1]) && !$this->io->isInteractive()) {
                $this->throwException('Failed to clone ' . $url . ' via ' . implode(', ', $protocols) . ' protocols, aborting.' . "\n\n" . implode("\n", $messages), $url);
            }
        }
        // if we have a private github url and the ssh protocol is disabled then we skip it and directly fallback to https
        $bypassSshForGitHub = Preg::isMatch('{^git@' . self::getGitHubDomainsRegex($this->config) . ':(.+?)\.git$}i', $url) && !in_array('ssh', $protocols, \true);
        $auth = null;
        $credentials = [];
        if ($bypassSshForGitHub || 0 !== $runCommands($url)) {
            $errorMsg = $this->process->getErrorOutput();
            // private github repository without ssh key access, try https with auth
            // @phpstan-ignore composerPcre.maybeUnsafeStrictGroups
            if (Preg::isMatchStrictGroups('{^git@' . self::getGitHubDomainsRegex($this->config) . ':(.+?)\.git$}i', $url, $match) || Preg::isMatchStrictGroups('{^https?://' . self::getGitHubDomainsRegex($this->config) . '/(.*?)(?:\.git)?$}i', $url, $match)) {
                if (!$this->io->hasAuthentication($match[1])) {
                    $gitHubUtil = new \Composer\Util\GitHub($this->io, $this->config, $this->process);
                    $message = 'Cloning failed using an ssh key for authentication, enter your GitHub credentials to access private repos';
                    if (!$gitHubUtil->authorizeOAuth($match[1]) && $this->io->isInteractive()) {
                        $gitHubUtil->authorizeOAuthInteractively($match[1], $message);
                    }
                }
                if ($this->io->hasAuthentication($match[1])) {
                    $auth = $this->io->getAuthentication($match[1]);
                    $authUrl = 'https://' . rawurlencode($auth['username']) . ':' . rawurlencode($auth['password']) . '@' . $match[1] . '/' . $match[2] . '.git';
                    if (0 === $runCommands($authUrl)) {
                        return;
                    }
                    $credentials = [rawurlencode($auth['username']), rawurlencode($auth['password'])];
                    $errorMsg = $this->process->getErrorOutput();
                }
                // @phpstan-ignore composerPcre.maybeUnsafeStrictGroups
            } elseif (Preg::isMatchStrictGroups('{^(https?)://(bitbucket\.org)/(.*?)(?:\.git)?$}i', $url, $match) || Preg::isMatchStrictGroups('{^(git)@(bitbucket\.org):(.+?\.git)$}i', $url, $match)) {
                //bitbucket either through oauth or app password, with fallback to ssh.
                $bitbucketUtil = new \Composer\Util\Bitbucket($this->io, $this->config, $this->process, $this->httpDownloader);
                $domain = $match[2];
                $repo_with_git_part = $match[3];
                if (!str_ends_with($repo_with_git_part, '.git')) {
                    $repo_with_git_part .= '.git';
                }
                if (!$this->io->hasAuthentication($domain)) {
                    $message = 'Enter your Bitbucket credentials to access private repos';
                    if (!$bitbucketUtil->authorizeOAuth($domain) && $this->io->isInteractive()) {
                        $bitbucketUtil->authorizeOAuthInteractively($domain, $message);
                        $accessToken = $bitbucketUtil->getToken();
                        $this->io->setAuthentication($domain, 'x-token-auth', $accessToken);
                    }
                }
                // First we try to authenticate with whatever we have stored.
                // This will be successful if there is for example an app
                // password in there.
                if ($this->io->hasAuthentication($domain)) {
                    $auth = $this->io->getAuthentication($domain);
                    // Bitbucket API tokens use the email address as the username for HTTP API calls and
                    // either the Bitbucket username or 'x-bitbucket-api-token-auth' as the username for git operations.
                    if (strpos((string) $auth['password'], 'ATAT') === 0) {
                        $auth['username'] = 'x-bitbucket-api-token-auth';
                    }
                    $authUrl = 'https://' . rawurlencode($auth['username']) . ':' . rawurlencode($auth['password']) . '@' . $domain . '/' . $repo_with_git_part;
                    if (0 === $runCommands($authUrl)) {
                        // Well if that succeeded on our first try, let's just
                        // take the win.
                        return;
                    }
                    //We already have an access_token from a previous request.
                    if ($auth['username'] !== 'x-token-auth') {
                        $accessToken = $bitbucketUtil->requestToken($domain, $auth['username'], $auth['password']);
                        if (!empty($accessToken)) {
                            $this->io->setAuthentication($domain, 'x-token-auth', $accessToken);
                        }
                    }
                }
                if ($this->io->hasAuthentication($domain)) {
                    $auth = $this->io->getAuthentication($domain);
                    $authUrl = 'https://' . rawurlencode($auth['username']) . ':' . rawurlencode($auth['password']) . '@' . $domain . '/' . $repo_with_git_part;
                    if (0 === $runCommands($authUrl)) {
                        return;
                    }
                    $credentials = [rawurlencode($auth['username']), rawurlencode($auth['password'])];
                }
                //Falling back to ssh
                $sshUrl = 'git@bitbucket.org:' . $repo_with_git_part;
                $this->io->writeError('    No bitbucket authentication configured. Falling back to ssh.');
                if (0 === $runCommands($sshUrl)) {
                    return;
                }
                $errorMsg = $this->process->getErrorOutput();
            } elseif (Preg::isMatchStrictGroups('{^(git)@' . self::getGitLabDomainsRegex($this->config) . ':(.+?\.git)$}i', $url, $match) || Preg::isMatchStrictGroups('{^(https?)://' . self::getGitLabDomainsRegex($this->config) . '/(.*)}i', $url, $match)) {
                if ($match[1] === 'git') {
                    $match[1] = 'https';
                }
                if (!$this->io->hasAuthentication($match[2])) {
                    $gitLabUtil = new \Composer\Util\GitLab($this->io, $this->config, $this->process);
                    $message = 'Cloning failed, enter your GitLab credentials to access private repos';
                    if (!$gitLabUtil->authorizeOAuth($match[2]) && $this->io->isInteractive()) {
                        $gitLabUtil->authorizeOAuthInteractively($match[1], $match[2], $message);
                    }
                }
                if ($this->io->hasAuthentication($match[2])) {
                    $auth = $this->io->getAuthentication($match[2]);
                    if ($auth['password'] === 'private-token' || $auth['password'] === 'oauth2' || $auth['password'] === 'gitlab-ci-token') {
                        $authUrl = $match[1] . '://' . rawurlencode($auth['password']) . ':' . rawurlencode((string) $auth['username']) . '@' . $match[2] . '/' . $match[3];
                        // swap username and password
                    } else {
                        $authUrl = $match[1] . '://' . rawurlencode((string) $auth['username']) . ':' . rawurlencode((string) $auth['password']) . '@' . $match[2] . '/' . $match[3];
                    }
                    if (0 === $runCommands($authUrl)) {
                        return;
                    }
                    $credentials = [rawurlencode((string) $auth['username']), rawurlencode((string) $auth['password'])];
                    $errorMsg = $this->process->getErrorOutput();
                }
            } elseif (null !== $match = $this->getAuthenticationFailure($url)) {
                // private non-github/gitlab/bitbucket repo that failed to authenticate
                if (str_contains($match[2], '@')) {
                    [$authParts, $match[2]] = explode('@', $match[2], 2);
                }
                $storeAuth = \false;
                if ($this->io->hasAuthentication($match[2])) {
                    $auth = $this->io->getAuthentication($match[2]);
                } elseif ($this->io->isInteractive()) {
                    $defaultUsername = null;
                    if (isset($authParts) && $authParts !== '') {
                        if (str_contains($authParts, ':')) {
                            [$defaultUsername] = explode(':', $authParts, 2);
                        } else {
                            $defaultUsername = $authParts;
                        }
                    }
                    $this->io->writeError('    Authentication required (<info>' . $match[2] . '</info>):');
                    $this->io->writeError('<warning>' . trim($errorMsg) . '</warning>', \true, IOInterface::VERBOSE);
                    $auth = ['username' => $this->io->ask('      Username: ', $defaultUsername), 'password' => $this->io->askAndHideAnswer('      Password: ')];
                    $storeAuth = $this->config->get('store-auths');
                }
                if (null !== $auth) {
                    $authUrl = $match[1] . rawurlencode((string) $auth['username']) . ':' . rawurlencode((string) $auth['password']) . '@' . $match[2] . $match[3];
                    if (0 === $runCommands($authUrl)) {
                        $this->io->setAuthentication($match[2], $auth['username'], $auth['password']);
                        $authHelper = new \Composer\Util\AuthHelper($this->io, $this->config);
                        $authHelper->storeAuth($match[2], $storeAuth);
                        return;
                    }
                    $credentials = [rawurlencode((string) $auth['username']), rawurlencode((string) $auth['password'])];
                    $errorMsg = $this->process->getErrorOutput();
                }
            }
            if ($initialClone && isset($origCwd)) {
                $this->filesystem->removeDirectory($origCwd);
            }
            if (\is_array($lastCommand)) {
                $lastCommand = implode(' ', $lastCommand);
            }
            if (count($credentials) > 0) {
                $lastCommand = $this->maskCredentials($lastCommand, $credentials);
                $errorMsg = $this->maskCredentials($errorMsg, $credentials);
            }
            $this->throwException('Failed to execute ' . $lastCommand . "\n\n" . $errorMsg, $url);
        }
    }
    public function syncMirror(string $url, string $dir): bool
    {
        if ((bool) \Composer\Util\Platform::getEnv('COMPOSER_DISABLE_NETWORK') && \Composer\Util\Platform::getEnv('COMPOSER_DISABLE_NETWORK') !== 'prime') {
            $this->io->writeError('<warning>Aborting git mirror sync of ' . $url . ' as network is disabled</warning>');
            return \false;
        }
        // update the repo if it is a valid git repository
        if (is_dir($dir) && 0 === $this->process->execute(['git', 'rev-parse', '--git-dir'], $output, $dir) && trim($output) === '.') {
            try {
                try {
                    $commands = [['git', 'remote', 'set-url', 'origin', '--', '%url%'], ['git', 'remote', 'update', '--prune', 'origin'], ['git', 'gc', '--auto']];
                    $this->runCommands($commands, $url, $dir);
                } finally {
                    $this->runCommands([['git', 'remote', 'set-url', 'origin', '--', '%sanitizedUrl%']], $url, $dir);
                }
            } catch (\Exception $e) {
                $this->io->writeError('<error>Sync mirror failed: ' . $e->getMessage() . '</error>', \true, IOInterface::DEBUG);
                return \false;
            }
            return \true;
        }
        self::checkForRepoOwnershipError($this->process->getErrorOutput(), $dir);
        // clean up directory and do a fresh clone into it
        $this->filesystem->removeDirectory($dir);
        $this->runCommands([['git', 'clone', '--mirror', '--', '%url%', $dir]], $url, $dir, \true);
        $this->runCommands([['git', 'remote', 'set-url', 'origin', '--', '%sanitizedUrl%']], $url, $dir);
        return \true;
    }
    public function fetchRefOrSyncMirror(string $url, string $dir, string $ref, ?string $prettyVersion = null): bool
    {
        if ($this->checkRefIsInMirror($dir, $ref)) {
            if (Preg::isMatch('{^[a-f0-9]{40}$}', $ref) && $prettyVersion !== null) {
                $branch = Preg::replace('{(?:^dev-|(?:\.x)?-dev$)}i', '', $prettyVersion);
                $branches = null;
                $tags = null;
                if (0 === $this->process->execute(['git', 'branch'], $output, $dir)) {
                    $branches = $output;
                }
                if (0 === $this->process->execute(['git', 'tag'], $output, $dir)) {
                    $tags = $output;
                }
                // if the pretty version cannot be found as a branch (nor branch with 'v' in front of the branch as it may have been stripped when generating pretty name),
                // nor as a tag, then we sync the mirror as otherwise it will likely fail during install.
                // this can occur if a git tag gets created *after* the reference is already put into the cache, as the ref check above will then not sync the new tags
                // see https://github.com/composer/composer/discussions/11002
                if (null !== $branches && !Preg::isMatch('{^[\s*]*v?' . preg_quote($branch) . '$}m', $branches) && null !== $tags && !Preg::isMatch('{^[\s*]*' . preg_quote($branch) . '$}m', $tags)) {
                    $this->syncMirror($url, $dir);
                }
            }
            return \true;
        }
        if ($this->syncMirror($url, $dir)) {
            return $this->checkRefIsInMirror($dir, $ref);
        }
        return \false;
    }
    public static function getNoShowSignatureFlag(\Composer\Util\ProcessExecutor $process): string
    {
        $gitVersion = self::getVersion($process);
        if ($gitVersion !== null && version_compare($gitVersion, '2.10.0-rc0', '>=')) {
            return ' --no-show-signature';
        }
        return '';
    }
    /**
     * @return list<string>
     */
    public static function getNoShowSignatureFlags(\Composer\Util\ProcessExecutor $process): array
    {
        $flags = static::getNoShowSignatureFlag($process);
        if ('' === $flags) {
            return [];
        }
        return explode(' ', substr($flags, 1));
    }
    /**
     * Checks if git version supports --no-commit-header flag (git 2.33+)
     *
     * @internal
     */
    public static function supportsNoCommitHeaderFlag(\Composer\Util\ProcessExecutor $process): bool
    {
        $gitVersion = self::getVersion($process);
        return $gitVersion !== null && version_compare($gitVersion, '2.33.0-rc0', '>=');
    }
    /**
     * Builds a git rev-list command with --no-commit-header flag when supported (git 2.33+)
     *
     * @internal
     * @param list<string> $arguments Additional arguments for git rev-list
     * @return non-empty-list<string>
     */
    public static function buildRevListCommand(\Composer\Util\ProcessExecutor $process, array $arguments): array
    {
        $command = ['git', 'rev-list'];
        if (self::supportsNoCommitHeaderFlag($process)) {
            $command[] = '--no-commit-header';
        }
        return array_merge($command, $arguments);
    }
    /**
     * Parses git rev-list output, removing 'commit <hash>' header lines for git < 2.33.
     *
     * When --no-commit-header is not available (git < 2.33), git rev-list --format outputs
     * "commit <hash>" before formatted output. This removes those lines.
     *
     * @internal
     */
    public static function parseRevListOutput(string $output, \Composer\Util\ProcessExecutor $process): string
    {
        // If git supports --no-commit-header, output is already clean
        if (self::supportsNoCommitHeaderFlag($process)) {
            return $output;
        }
        // Filter out "commit <hash>" lines for older git versions
        return Preg::replace('{^commit [a-f0-9]{40}\n?}m', '', $output);
    }
    private function checkRefIsInMirror(string $dir, string $ref): bool
    {
        if (is_dir($dir) && 0 === $this->process->execute(['git', 'rev-parse', '--git-dir'], $output, $dir) && trim($output) === '.') {
            $exitCode = $this->process->execute(['git', 'rev-parse', '--quiet', '--verify', $ref . '^{commit}'], $ignoredOutput, $dir);
            if ($exitCode === 0) {
                return \true;
            }
        }
        self::checkForRepoOwnershipError($this->process->getErrorOutput(), $dir);
        return \false;
    }
    /**
     * @return array<int, string>|null
     */
    private function getAuthenticationFailure(string $url): ?array
    {
        if (!Preg::isMatchStrictGroups('{^(https?://)([^/]+)(.*)$}i', $url, $match)) {
            return null;
        }
        $authFailures = ['fatal: Authentication failed', 'remote error: Invalid username or password.', 'error: 401 Unauthorized', 'fatal: unable to access', 'fatal: could not read Username'];
        $errorOutput = $this->process->getErrorOutput();
        foreach ($authFailures as $authFailure) {
            if (strpos($errorOutput, $authFailure) !== \false) {
                return $match;
            }
        }
        return null;
    }
    public function getMirrorDefaultBranch(string $url, string $dir, bool $isLocalPathRepository): ?string
    {
        if ((bool) \Composer\Util\Platform::getEnv('COMPOSER_DISABLE_NETWORK')) {
            return null;
        }
        try {
            if ($isLocalPathRepository) {
                $this->process->execute(['git', 'remote', 'show', 'origin'], $output, $dir);
            } else {
                $commands = [['git', 'remote', 'set-url', 'origin', '--', '%url%'], ['git', 'remote', 'show', 'origin'], ['git', 'remote', 'set-url', 'origin', '--', '%sanitizedUrl%']];
                $this->runCommands($commands, $url, $dir, \false, $output);
            }
            $lines = $this->process->splitLines($output);
            foreach ($lines as $line) {
                if (Preg::isMatch('{^\s*HEAD branch:\s(.+)\s*$}m', $line, $matches)) {
                    return $matches[1];
                }
            }
        } catch (\Exception $e) {
            $this->io->writeError('<error>Failed to fetch root identifier from remote: ' . $e->getMessage() . '</error>', \true, IOInterface::DEBUG);
        }
        return null;
    }
    public static function cleanEnv(?\Composer\Util\ProcessExecutor $process = null): void
    {
        $gitVersion = self::getVersion($process ?? new \Composer\Util\ProcessExecutor());
        if ($gitVersion !== null && version_compare($gitVersion, '2.3.0', '>=')) {
            // added in git 2.3.0, prevents prompting the user for username/password
            if (\Composer\Util\Platform::getEnv('GIT_TERMINAL_PROMPT') !== '0') {
                \Composer\Util\Platform::putEnv('GIT_TERMINAL_PROMPT', '0');
            }
        } else if (\Composer\Util\Platform::getEnv('GIT_ASKPASS') !== 'echo') {
            \Composer\Util\Platform::putEnv('GIT_ASKPASS', 'echo');
        }
        // clean up rogue git env vars in case this is running in a git hook
        if (\Composer\Util\Platform::getEnv('GIT_DIR')) {
            \Composer\Util\Platform::clearEnv('GIT_DIR');
        }
        if (\Composer\Util\Platform::getEnv('GIT_WORK_TREE')) {
            \Composer\Util\Platform::clearEnv('GIT_WORK_TREE');
        }
        // Run processes with predictable LANGUAGE
        if (\Composer\Util\Platform::getEnv('LANGUAGE') !== 'C') {
            \Composer\Util\Platform::putEnv('LANGUAGE', 'C');
        }
        // clean up env for OSX, see https://github.com/composer/composer/issues/2146#issuecomment-35478940
        \Composer\Util\Platform::clearEnv('DYLD_LIBRARY_PATH');
    }
    /**
     * @return non-empty-string
     */
    public static function getGitHubDomainsRegex(Config $config): string
    {
        return '(' . implode('|', array_map('preg_quote', $config->get('github-domains'))) . ')';
    }
    /**
     * @return non-empty-string
     */
    public static function getGitLabDomainsRegex(Config $config): string
    {
        return '(' . implode('|', array_map('preg_quote', $config->get('gitlab-domains'))) . ')';
    }
    /**
     * @param non-empty-string $message
     *
     * @return never
     */
    private function throwException($message, string $url): void
    {
        // git might delete a directory when it fails and php will not know
        clearstatcache();
        if (0 !== $this->process->execute(['git', '--version'], $ignoredOutput)) {
            throw new \RuntimeException(\Composer\Util\Url::sanitize('Failed to clone ' . $url . ', git was not found, check that it is installed and in your PATH env.' . "\n\n" . $this->process->getErrorOutput()));
        }
        throw new \RuntimeException(\Composer\Util\Url::sanitize($message));
    }
    /**
     * Retrieves the current git version.
     *
     * @return string|null The git version number, if present.
     */
    public static function getVersion(\Composer\Util\ProcessExecutor $process): ?string
    {
        if (\false === self::$version) {
            self::$version = null;
            if (0 === $process->execute(['git', '--version'], $output) && Preg::isMatch('/^git version (\d+(?:\.\d+)+)/m', $output, $matches)) {
                self::$version = $matches[1];
            }
        }
        return self::$version;
    }
    /**
     * @param string[] $credentials
     */
    private function maskCredentials(string $error, array $credentials): string
    {
        $maskedCredentials = [];
        foreach ($credentials as $credential) {
            if (in_array($credential, ['private-token', 'x-token-auth', 'oauth2', 'gitlab-ci-token', 'x-oauth-basic'])) {
                $maskedCredentials[] = $credential;
            } elseif (strlen($credential) > 6) {
                $maskedCredentials[] = substr($credential, 0, 3) . '...' . substr($credential, -3);
            } elseif (strlen($credential) > 3) {
                $maskedCredentials[] = substr($credential, 0, 3) . '...';
            } else {
                $maskedCredentials[] = 'XXX';
            }
        }
        return str_replace($credentials, $maskedCredentials, $error);
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer\Util;

use Composer\Config;
use Composer\IO\IOInterface;
use Composer\Pcre\Preg;
/**
 * @author Till Klampaeckel <till@php.net>
 * @author Jordi Boggiano <j.boggiano@seld.be>
 */
class Svn
{
    private const MAX_QTY_AUTH_TRIES = 5;
    /**
     * @var ?array{username: string, password: string}
     */
    protected $credentials;
    /**
     * @var bool
     */
    protected $hasAuth;
    /**
     * @var IOInterface
     */
    protected $io;
    /**
     * @var string
     */
    protected $url;
    /**
     * @var bool
     */
    protected $cacheCredentials = \true;
    /**
     * @var ProcessExecutor
     */
    protected $process;
    /**
     * @var int
     */
    protected $qtyAuthTries = 0;
    /**
     * @var Config
     */
    protected $config;
    /**
     * @var string|null
     */
    private static $version;
    public function __construct(string $url, IOInterface $io, Config $config, ?\Composer\Util\ProcessExecutor $process = null)
    {
        $this->url = $url;
        $this->io = $io;
        $this->config = $config;
        $this->process = $process ?: new \Composer\Util\ProcessExecutor($io);
    }
    public static function cleanEnv(): void
    {
        // clean up env for OSX, see https://github.com/composer/composer/issues/2146#issuecomment-35478940
        \Composer\Util\Platform::clearEnv('DYLD_LIBRARY_PATH');
    }
    /**
     * Execute an SVN remote command and try to fix up the process with credentials
     * if necessary.
     *
     * @param non-empty-list<string> $command SVN command to run
     * @param string  $url     SVN url
     * @param ?string $cwd     Working directory
     * @param ?string $path    Target for a checkout
     * @param bool    $verbose Output all output to the user
     *
     * @throws \RuntimeException
     */
    public function execute(array $command, string $url, ?string $cwd = null, ?string $path = null, bool $verbose = \false): string
    {
        // Ensure we are allowed to use this URL by config
        $this->config->prohibitUrlByConfig($url, $this->io);
        return $this->executeWithAuthRetry($command, $cwd, $url, $path, $verbose);
    }
    /**
     * Execute an SVN local command and try to fix up the process with credentials
     * if necessary.
     *
     * @param non-empty-list<string> $command SVN command to run
     * @param string $path    Path argument passed thru to the command
     * @param string $cwd     Working directory
     * @param bool   $verbose Output all output to the user
     *
     * @throws \RuntimeException
     */
    public function executeLocal(array $command, string $path, ?string $cwd = null, bool $verbose = \false): string
    {
        // A local command has no remote url
        return $this->executeWithAuthRetry($command, $cwd, '', $path, $verbose);
    }
    /**
     * @param non-empty-list<string> $svnCommand
     */
    private function executeWithAuthRetry(array $svnCommand, ?string $cwd, string $url, ?string $path, bool $verbose): ?string
    {
        // Regenerate the command at each try, to use the newly user-provided credentials
        $command = $this->getCommand($svnCommand, $url, $path);
        $output = null;
        $io = $this->io;
        $handler = static function ($type, $buffer) use (&$output, $io, $verbose) {
            if ($type !== 'out') {
                return null;
            }
            if (strpos($buffer, 'Redirecting to URL ') === 0) {
                return null;
            }
            $output .= $buffer;
            if ($verbose) {
                $io->writeError($buffer, \false);
            }
        };
        $status = $this->process->execute($command, $handler, $cwd);
        if (0 === $status) {
            return $output;
        }
        $errorOutput = $this->process->getErrorOutput();
        $fullOutput = trim(implode("\n", [$output, $errorOutput]));
        // the error is not auth-related
        if (\false === stripos($fullOutput, 'Could not authenticate to server:') && \false === stripos($fullOutput, 'authorization failed') && \false === stripos($fullOutput, 'svn: E170001:') && \false === stripos($fullOutput, 'svn: E215004:')) {
            throw new \RuntimeException($fullOutput);
        }
        if (!$this->hasAuth()) {
            $this->doAuthDance();
        }
        // try to authenticate if maximum quantity of tries not reached
        if ($this->qtyAuthTries++ < self::MAX_QTY_AUTH_TRIES) {
            // restart the process
            return $this->executeWithAuthRetry($svnCommand, $cwd, $url, $path, $verbose);
        }
        throw new \RuntimeException('wrong credentials provided (' . $fullOutput . ')');
    }
    public function setCacheCredentials(bool $cacheCredentials): void
    {
        $this->cacheCredentials = $cacheCredentials;
    }
    /**
     * Repositories requests credentials, let's put them in.
     *
     * @throws \RuntimeException
     */
    protected function doAuthDance(): \Composer\Util\Svn
    {
        // cannot ask for credentials in non interactive mode
        if (!$this->io->isInteractive()) {
            throw new \RuntimeException('can not ask for authentication in non interactive mode');
        }
        $this->io->writeError("The Subversion server ({$this->url}) requested credentials:");
        $this->hasAuth = \true;
        $this->credentials = ['username' => (string) $this->io->ask("Username: ", ''), 'password' => (string) $this->io->askAndHideAnswer("Password: ")];
        $this->cacheCredentials = $this->io->askConfirmation("Should Subversion cache these credentials? (yes/no) ");
        return $this;
    }
    /**
     * A method to create the svn commands run.
     *
     * @param non-empty-list<string> $cmd  Usually 'svn ls' or something like that.
     * @param string $url  Repo URL.
     * @param string $path Target for a checkout
     *
     * @return non-empty-list<string>
     */
    protected function getCommand(array $cmd, string $url, ?string $path = null): array
    {
        $cmd = array_merge($cmd, ['--non-interactive'], $this->getCredentialArgs(), ['--', $url]);
        if ($path !== null) {
            $cmd[] = $path;
        }
        return $cmd;
    }
    /**
     * Return the credential string for the svn command.
     *
     * Adds --no-auth-cache when credentials are present.
     *
     * @return list<string>
     */
    protected function getCredentialArgs(): array
    {
        if (!$this->hasAuth()) {
            return [];
        }
        return array_merge($this->getAuthCacheArgs(), ['--username', $this->getUsername(), '--password', $this->getPassword()]);
    }
    /**
     * Get the password for the svn command. Can be empty.
     *
     * @throws \LogicException
     */
    protected function getPassword(): string
    {
        if ($this->credentials === null) {
            throw new \LogicException("No svn auth detected.");
        }
        return $this->credentials['password'];
    }
    /**
     * Get the username for the svn command.
     *
     * @throws \LogicException
     */
    protected function getUsername(): string
    {
        if ($this->credentials === null) {
            throw new \LogicException("No svn auth detected.");
        }
        return $this->credentials['username'];
    }
    /**
     * Detect Svn Auth.
     */
    protected function hasAuth(): bool
    {
        if (null !== $this->hasAuth) {
            return $this->hasAuth;
        }
        if (\false === $this->createAuthFromConfig()) {
            $this->createAuthFromUrl();
        }
        return (bool) $this->hasAuth;
    }
    /**
     * Return the no-auth-cache switch.
     *
     * @return list<string>
     */
    protected function getAuthCacheArgs(): array
    {
        return $this->cacheCredentials ? [] : ['--no-auth-cache'];
    }
    /**
     * Create the auth params from the configuration file.
     */
    private function createAuthFromConfig(): bool
    {
        if (!$this->config->has('http-basic')) {
            return $this->hasAuth = \false;
        }
        $authConfig = $this->config->get('http-basic');
        $host = parse_url($this->url, \PHP_URL_HOST);
        if (isset($authConfig[$host])) {
            $this->credentials = ['username' => $authConfig[$host]['username'], 'password' => $authConfig[$host]['password']];
            return $this->hasAuth = \true;
        }
        return $this->hasAuth = \false;
    }
    /**
     * Create the auth params from the url
     */
    private function createAuthFromUrl(): bool
    {
        $uri = parse_url($this->url);
        if (empty($uri['user'])) {
            return $this->hasAuth = \false;
        }
        $this->credentials = ['username' => $uri['user'], 'password' => !empty($uri['pass']) ? $uri['pass'] : ''];
        return $this->hasAuth = \true;
    }
    /**
     * Returns the version of the svn binary contained in PATH
     */
    public function binaryVersion(): ?string
    {
        if (!self::$version) {
            if (0 === $this->process->execute(['svn', '--version'], $output)) {
                if (Preg::isMatch('{(\d+(?:\.\d+)+)}', $output, $match)) {
                    self::$version = $match[1];
                }
            }
        }
        return self::$version;
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer\Util;

use Composer\Pcre\Preg;
use stdClass;
/**
 * Tests URLs against NO_PROXY patterns
 */
class NoProxyPattern
{
    /**
     * @var string[]
     */
    protected $hostNames = [];
    /**
     * @var (null|object)[]
     */
    protected $rules = [];
    /**
     * @var bool
     */
    protected $noproxy;
    /**
     * @param string $pattern NO_PROXY pattern
     */
    public function __construct(string $pattern)
    {
        $this->hostNames = Preg::split('{[\s,]+}', $pattern, -1, \PREG_SPLIT_NO_EMPTY);
        $this->noproxy = empty($this->hostNames) || '*' === $this->hostNames[0];
    }
    /**
     * Returns true if a URL matches the NO_PROXY pattern
     */
    public function test(string $url): bool
    {
        if ($this->noproxy) {
            return \true;
        }
        if (!$urlData = $this->getUrlData($url)) {
            return \false;
        }
        foreach ($this->hostNames as $index => $hostName) {
            if ($this->match($index, $hostName, $urlData)) {
                return \true;
            }
        }
        return \false;
    }
    /**
     * Returns false is the url cannot be parsed, otherwise a data object
     *
     * @return bool|stdClass
     */
    protected function getUrlData(string $url)
    {
        if (!$host = parse_url($url, \PHP_URL_HOST)) {
            return \false;
        }
        $port = parse_url($url, \PHP_URL_PORT);
        if (empty($port)) {
            switch (parse_url($url, \PHP_URL_SCHEME)) {
                case 'http':
                    $port = 80;
                    break;
                case 'https':
                    $port = 443;
                    break;
            }
        }
        $hostName = $host . ($port ? ':' . $port : '');
        [$host, $port, $err] = $this->splitHostPort($hostName);
        if ($err || !$this->ipCheckData($host, $ipdata)) {
            return \false;
        }
        return $this->makeData($host, $port, $ipdata);
    }
    /**
     * Returns true if the url is matched by a rule
     */
    protected function match(int $index, string $hostName, stdClass $url): bool
    {
        if (!$rule = $this->getRule($index, $hostName)) {
            // Data must have been misformatted
            return \false;
        }
        if ($rule->ipdata) {
            // Match ipdata first
            if (!$url->ipdata) {
                return \false;
            }
            if ($rule->ipdata->netmask) {
                return $this->matchRange($rule->ipdata, $url->ipdata);
            }
            $match = $rule->ipdata->ip === $url->ipdata->ip;
        } else {
            // Match host and port
            $haystack = substr($url->name, -strlen($rule->name));
            $match = stripos($haystack, $rule->name) === 0;
        }
        if ($match && $rule->port) {
            $match = $rule->port === $url->port;
        }
        return $match;
    }
    /**
     * Returns true if the target ip is in the network range
     */
    protected function matchRange(stdClass $network, stdClass $target): bool
    {
        $net = unpack('C*', $network->ip);
        $mask = unpack('C*', $network->netmask);
        $ip = unpack('C*', $target->ip);
        if (\false === $net) {
            throw new \RuntimeException('Could not parse network IP ' . $network->ip);
        }
        if (\false === $mask) {
            throw new \RuntimeException('Could not parse netmask ' . $network->netmask);
        }
        if (\false === $ip) {
            throw new \RuntimeException('Could not parse target IP ' . $target->ip);
        }
        for ($i = 1; $i < 17; ++$i) {
            if (($net[$i] & $mask[$i]) !== ($ip[$i] & $mask[$i])) {
                return \false;
            }
        }
        return \true;
    }
    /**
     * Finds or creates rule data for a hostname
     *
     * @return null|stdClass Null if the hostname is invalid
     */
    private function getRule(int $index, string $hostName): ?stdClass
    {
        if (array_key_exists($index, $this->rules)) {
            return $this->rules[$index];
        }
        $this->rules[$index] = null;
        [$host, $port, $err] = $this->splitHostPort($hostName);
        if ($err || !$this->ipCheckData($host, $ipdata, \true)) {
            return null;
        }
        $this->rules[$index] = $this->makeData($host, $port, $ipdata);
        return $this->rules[$index];
    }
    /**
     * Creates an object containing IP data if the host is an IP address
     *
     * @param null|stdClass $ipdata      Set by method if IP address found
     * @param bool          $allowPrefix Whether a CIDR prefix-length is expected
     *
     * @return bool False if the host contains invalid data
     */
    private function ipCheckData(string $host, ?stdClass &$ipdata, bool $allowPrefix = \false): bool
    {
        $ipdata = null;
        $netmask = null;
        $prefix = null;
        $modified = \false;
        // Check for a CIDR prefix-length
        if (strpos($host, '/') !== \false) {
            [$host, $prefix] = explode('/', $host);
            if (!$allowPrefix || !$this->validateInt($prefix, 0, 128)) {
                return \false;
            }
            $prefix = (int) $prefix;
            $modified = \true;
        }
        // See if this is an ip address
        if (!filter_var($host, \FILTER_VALIDATE_IP)) {
            return !$modified;
        }
        [$ip, $size] = $this->ipGetAddr($host);
        if ($prefix !== null) {
            // Check for a valid prefix
            if ($prefix > $size * 8) {
                return \false;
            }
            [$ip, $netmask] = $this->ipGetNetwork($ip, $size, $prefix);
        }
        $ipdata = $this->makeIpData($ip, $size, $netmask);
        return \true;
    }
    /**
     * Returns an array of the IP in_addr and its byte size
     *
     * IPv4 addresses are always mapped to IPv6, which simplifies handling
     * and comparison.
     *
     * @return mixed[] in_addr, size
     */
    private function ipGetAddr(string $host): array
    {
        $ip = inet_pton($host);
        $size = strlen($ip);
        $mapped = $this->ipMapTo6($ip, $size);
        return [$mapped, $size];
    }
    /**
     * Returns the binary network mask mapped to IPv6
     *
     * @param int $prefix CIDR prefix-length
     * @param int $size   Byte size of in_addr
     */
    private function ipGetMask(int $prefix, int $size): string
    {
        $mask = '';
        if ($ones = floor($prefix / 8)) {
            $mask = str_repeat(chr(255), (int) $ones);
        }
        if ($remainder = $prefix % 8) {
            $mask .= chr(0xff ^ 0xff >> $remainder);
        }
        $mask = str_pad($mask, $size, chr(0));
        return $this->ipMapTo6($mask, $size);
    }
    /**
     * Calculates and returns the network and mask
     *
     * @param string $rangeIp IP in_addr
     * @param int    $size    Byte size of in_addr
     * @param int    $prefix  CIDR prefix-length
     *
     * @return string[] network in_addr, binary mask
     */
    private function ipGetNetwork(string $rangeIp, int $size, int $prefix): array
    {
        $netmask = $this->ipGetMask($prefix, $size);
        // Get the network from the address and mask
        $mask = unpack('C*', $netmask);
        $ip = unpack('C*', $rangeIp);
        $net = '';
        if (\false === $mask) {
            throw new \RuntimeException('Could not parse netmask ' . $netmask);
        }
        if (\false === $ip) {
            throw new \RuntimeException('Could not parse range IP ' . $rangeIp);
        }
        for ($i = 1; $i < 17; ++$i) {
            $net .= chr($ip[$i] & $mask[$i]);
        }
        return [$net, $netmask];
    }
    /**
     * Maps an IPv4 address to IPv6
     *
     * @param string $binary in_addr
     * @param int    $size   Byte size of in_addr
     *
     * @return string Mapped or existing in_addr
     */
    private function ipMapTo6(string $binary, int $size): string
    {
        if ($size === 4) {
            $prefix = str_repeat(chr(0), 10) . str_repeat(chr(255), 2);
            $binary = $prefix . $binary;
        }
        return $binary;
    }
    /**
     * Creates a rule data object
     */
    private function makeData(string $host, int $port, ?stdClass $ipdata): stdClass
    {
        return (object) ['host' => $host, 'name' => '.' . ltrim($host, '.'), 'port' => $port, 'ipdata' => $ipdata];
    }
    /**
     * Creates an ip data object
     *
     * @param string      $ip      in_addr
     * @param int         $size    Byte size of in_addr
     * @param null|string $netmask Network mask
     */
    private function makeIpData(string $ip, int $size, ?string $netmask): stdClass
    {
        return (object) ['ip' => $ip, 'size' => $size, 'netmask' => $netmask];
    }
    /**
     * Splits the hostname into host and port components
     *
     * @return mixed[] host, port, if there was error
     */
    private function splitHostPort(string $hostName): array
    {
        // host, port, err
        $error = ['', '', \true];
        $port = 0;
        $ip6 = '';
        // Check for square-bracket notation
        if ($hostName[0] === '[') {
            $index = strpos($hostName, ']');
            // The smallest ip6 address is ::
            if (\false === $index || $index < 3) {
                return $error;
            }
            $ip6 = substr($hostName, 1, $index - 1);
            $hostName = substr($hostName, $index + 1);
            if (strpbrk($hostName, '[]') !== \false || substr_count($hostName, ':') > 1) {
                return $error;
            }
        }
        if (substr_count($hostName, ':') === 1) {
            $index = strpos($hostName, ':');
            $port = substr($hostName, $index + 1);
            $hostName = substr($hostName, 0, $index);
            if (!$this->validateInt($port, 1, 65535)) {
                return $error;
            }
            $port = (int) $port;
        }
        $host = $ip6 . $hostName;
        return [$host, $port, \false];
    }
    /**
     * Wrapper around filter_var FILTER_VALIDATE_INT
     */
    private function validateInt(string $int, int $min, int $max): bool
    {
        $options = ['options' => ['min_range' => $min, 'max_range' => $max]];
        return \false !== filter_var($int, \FILTER_VALIDATE_INT, $options);
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer\Util;

use Composer\Pcre\Preg;
/**
 * Composer mirror utilities
 *
 * @author Jordi Boggiano <j.boggiano@seld.be>
 */
class ComposerMirror
{
    /**
     * @param non-empty-string $mirrorUrl
     * @return non-empty-string
     */
    public static function processUrl(string $mirrorUrl, string $packageName, string $version, ?string $reference, ?string $type, ?string $prettyVersion = null): string
    {
        if ($reference) {
            $reference = Preg::isMatch('{^([a-f0-9]*|%reference%)$}', $reference) ? $reference : hash('md5', $reference);
        }
        $version = strpos($version, '/') === \false ? $version : hash('md5', $version);
        $from = ['%package%', '%version%', '%reference%', '%type%'];
        $to = [$packageName, $version, $reference, $type];
        if (null !== $prettyVersion) {
            $from[] = '%prettyVersion%';
            $to[] = $prettyVersion;
        }
        $url = str_replace($from, $to, $mirrorUrl);
        assert($url !== '');
        return $url;
    }
    /**
     * @param non-empty-string $mirrorUrl
     */
    public static function processGitUrl(string $mirrorUrl, string $packageName, string $url, ?string $type): string
    {
        if (Preg::isMatch('#^(?:(?:https?|git)://github\.com/|git@github\.com:)([^/]+)/(.+?)(?:\.git)?$#', $url, $match)) {
            $url = 'gh-' . $match[1] . '/' . $match[2];
        } elseif (Preg::isMatch('#^https://bitbucket\.org/([^/]+)/(.+?)(?:\.git)?/?$#', $url, $match)) {
            $url = 'bb-' . $match[1] . '/' . $match[2];
        } else {
            $url = Preg::replace('{[^a-z0-9_.-]}i', '-', trim($url, '/'));
        }
        return str_replace(['%package%', '%normalizedUrl%', '%type%'], [$packageName, $url, $type], $mirrorUrl);
    }
    /**
     * @param non-empty-string $mirrorUrl
     */
    public static function processHgUrl(string $mirrorUrl, string $packageName, string $url, string $type): string
    {
        return self::processGitUrl($mirrorUrl, $packageName, $url, $type);
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer\Util;

use Composer\Package\CompletePackageInterface;
use Composer\Package\PackageInterface;
class PackageInfo
{
    public static function getViewSourceUrl(PackageInterface $package): ?string
    {
        if ($package instanceof CompletePackageInterface && isset($package->getSupport()['source']) && '' !== $package->getSupport()['source']) {
            return $package->getSupport()['source'];
        }
        return $package->getSourceUrl();
    }
    public static function getViewSourceOrHomepageUrl(PackageInterface $package): ?string
    {
        $url = self::getViewSourceUrl($package) ?? ($package instanceof CompletePackageInterface ? $package->getHomepage() : null);
        if ($url === '') {
            return null;
        }
        return $url;
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer\Util;

use Composer\Config;
use Composer\IO\IOInterface;
use Composer\Downloader\TransportException;
use Composer\Pcre\Preg;
/**
 * @author Jordi Boggiano <j.boggiano@seld.be>
 */
class AuthHelper
{
    /** @var IOInterface */
    protected $io;
    /** @var Config */
    protected $config;
    /** @var array<string, string> Map of origins to message displayed */
    private $displayedOriginAuthentications = [];
    /** @var array<string, bool> Map of URLs and whether they already retried with authentication from Bitbucket */
    private $bitbucketRetry = [];
    public function __construct(IOInterface $io, Config $config)
    {
        $this->io = $io;
        $this->config = $config;
    }
    /**
     * @param 'prompt'|bool $storeAuth
     */
    public function storeAuth(string $origin, $storeAuth): void
    {
        $store = \false;
        $configSource = $this->config->getAuthConfigSource();
        if ($storeAuth === \true) {
            $store = $configSource;
        } elseif ($storeAuth === 'prompt') {
            $answer = $this->io->askAndValidate('Do you want to store credentials for ' . $origin . ' in ' . $configSource->getName() . ' ? [Yn] ', static function ($value): string {
                $input = strtolower(substr(trim($value), 0, 1));
                if (in_array($input, ['y', 'n'])) {
                    return $input;
                }
                throw new \RuntimeException('Please answer (y)es or (n)o');
            }, null, 'y');
            if ($answer === 'y') {
                $store = $configSource;
            }
        }
        if ($store) {
            $store->addConfigSetting('http-basic.' . $origin, $this->io->getAuthentication($origin));
        }
    }
    /**
     * @param  int         $statusCode HTTP status code that triggered this call
     * @param  string|null $reason     a message/description explaining why this was called
     * @param  string[]    $headers
     * @param  int         $retryCount the amount of retries already done on this URL
     * @return array       containing retry (bool) and storeAuth (string|bool) keys, if retry is true the request should be
     *                                retried, if storeAuth is true then on a successful retry the authentication should be persisted to auth.json
     * @phpstan-return array{retry: bool, storeAuth: 'prompt'|bool}
     */
    public function promptAuthIfNeeded(string $url, string $origin, int $statusCode, ?string $reason = null, array $headers = [], int $retryCount = 0, ?string $responseBody = null): array
    {
        $storeAuth = \false;
        if (in_array($origin, $this->config->get('github-domains'), \true)) {
            $gitHubUtil = new \Composer\Util\GitHub($this->io, $this->config, null);
            $message = "\n";
            $rateLimited = $gitHubUtil->isRateLimited($headers);
            $requiresSso = $gitHubUtil->requiresSso($headers);
            if ($requiresSso) {
                $ssoUrl = $gitHubUtil->getSsoUrl($headers);
                $message = 'GitHub API token requires SSO authorization. Authorize this token at ' . $ssoUrl . "\n";
                $this->io->writeError($message);
                if (!$this->io->isInteractive()) {
                    throw new TransportException('Could not authenticate against ' . $origin, 403);
                }
                $this->io->ask('After authorizing your token, confirm that you would like to retry the request');
                return ['retry' => \true, 'storeAuth' => $storeAuth];
            }
            if ($rateLimited) {
                $rateLimit = $gitHubUtil->getRateLimit($headers);
                if ($this->io->hasAuthentication($origin)) {
                    $message = 'Review your configured GitHub OAuth token or enter a new one to go over the API rate limit.';
                } else {
                    $message = 'Create a GitHub OAuth token to go over the API rate limit.';
                }
                $message = sprintf('GitHub API limit (%d calls/hr) is exhausted, could not fetch ' . $url . '. ' . $message . ' You can also wait until %s for the rate limit to reset.', $rateLimit['limit'], $rateLimit['reset']) . "\n";
            } else {
                // Try to extract a more specific error message from GitHub's API response
                $gitHubApiMessage = null;
                if ($responseBody !== null) {
                    $decoded = json_decode($responseBody, \true);
                    if (is_array($decoded) && isset($decoded['message']) && is_string($decoded['message'])) {
                        $gitHubApiMessage = $decoded['message'];
                    }
                }
                if ($gitHubApiMessage !== null) {
                    $message .= 'Could not fetch ' . $url . ': ' . $gitHubApiMessage;
                } else {
                    $message .= 'Could not fetch ' . $url . ', please ';
                    if ($this->io->hasAuthentication($origin)) {
                        $message .= 'review your configured GitHub OAuth token or enter a new one to access private repos';
                    } else {
                        $message .= 'create a GitHub OAuth token to access private repos';
                    }
                }
            }
            if (!$gitHubUtil->authorizeOAuth($origin) && (!$this->io->isInteractive() || !$gitHubUtil->authorizeOAuthInteractively($origin, $message))) {
                throw new TransportException('Could not authenticate against ' . $origin, 401);
            }
        } elseif (in_array($origin, $this->config->get('gitlab-domains'), \true)) {
            $message = "\n" . 'Could not fetch ' . $url . ', enter your ' . $origin . ' credentials ' . ($statusCode === 401 ? 'to access private repos' : 'to go over the API rate limit');
            $gitLabUtil = new \Composer\Util\GitLab($this->io, $this->config, null);
            $auth = null;
            if ($this->io->hasAuthentication($origin)) {
                $auth = $this->io->getAuthentication($origin);
                if (in_array($auth['password'], ['gitlab-ci-token', 'private-token', 'oauth2'], \true)) {
                    throw new TransportException("Invalid credentials for '" . $url . "', aborting.", $statusCode);
                }
            }
            if (!$gitLabUtil->authorizeOAuth($origin) && (!$this->io->isInteractive() || !$gitLabUtil->authorizeOAuthInteractively(parse_url($url, \PHP_URL_SCHEME), $origin, $message))) {
                throw new TransportException('Could not authenticate against ' . $origin, 401);
            }
            if ($auth !== null && $this->io->hasAuthentication($origin)) {
                if ($auth === $this->io->getAuthentication($origin)) {
                    throw new TransportException("Invalid credentials for '" . $url . "', aborting.", $statusCode);
                }
            }
        } elseif ($origin === 'bitbucket.org' || $origin === 'api.bitbucket.org') {
            $askForOAuthToken = \true;
            $origin = 'bitbucket.org';
            if ($this->io->hasAuthentication($origin)) {
                $auth = $this->io->getAuthentication($origin);
                if ($auth['username'] !== 'x-token-auth') {
                    $bitbucketUtil = new \Composer\Util\Bitbucket($this->io, $this->config);
                    $accessToken = $bitbucketUtil->requestToken($origin, $auth['username'], $auth['password']);
                    if (!empty($accessToken)) {
                        $this->io->setAuthentication($origin, 'x-token-auth', $accessToken);
                        $askForOAuthToken = \false;
                    }
                } elseif (!isset($this->bitbucketRetry[$url])) {
                    // when multiple requests fire at the same time, they will all fail and the first one resets the token to be correct above but then the others
                    // reach the code path and without this fallback they would end up throwing below
                    // see https://github.com/composer/composer/pull/11464 for more details
                    $askForOAuthToken = \false;
                    $this->bitbucketRetry[$url] = \true;
                } else {
                    throw new TransportException('Could not authenticate against ' . $origin, 401);
                }
            }
            if ($askForOAuthToken) {
                $message = "\n" . 'Could not fetch ' . $url . ', please create a bitbucket OAuth token to ' . ($statusCode === 401 || $statusCode === 403 ? 'access private repos' : 'go over the API rate limit');
                $bitBucketUtil = new \Composer\Util\Bitbucket($this->io, $this->config);
                if (!$bitBucketUtil->authorizeOAuth($origin) && (!$this->io->isInteractive() || !$bitBucketUtil->authorizeOAuthInteractively($origin, $message))) {
                    throw new TransportException('Could not authenticate against ' . $origin, 401);
                }
            }
        } else {
            // 404s are only handled for github
            if ($statusCode === 404) {
                return ['retry' => \false, 'storeAuth' => \false];
            }
            // fail if the console is not interactive
            if (!$this->io->isInteractive()) {
                if ($statusCode === 401) {
                    $message = "The '" . $url . "' URL required authentication (HTTP 401).\nYou must be using the interactive console to authenticate";
                } elseif ($statusCode === 403) {
                    $message = "The '" . $url . "' URL could not be accessed (HTTP 403): " . $reason;
                } else {
                    $message = "Unknown error code '" . $statusCode . "', reason: " . $reason;
                }
                throw new TransportException($message, $statusCode);
            }
            // fail if we already have auth
            if ($this->io->hasAuthentication($origin)) {
                // if two or more requests are started together for the same host, and the first
                // received authentication already, we let the others retry before failing them
                if ($retryCount === 0) {
                    return ['retry' => \true, 'storeAuth' => \false];
                }
                throw new TransportException("Invalid credentials (HTTP {$statusCode}) for '{$url}', aborting.", $statusCode);
            }
            $this->io->writeError('    Authentication required (<info>' . $origin . '</info>):');
            $username = $this->io->ask('      Username: ');
            $password = $this->io->askAndHideAnswer('      Password: ');
            $this->io->setAuthentication($origin, $username, $password);
            $storeAuth = $this->config->get('store-auths');
        }
        return ['retry' => \true, 'storeAuth' => $storeAuth];
    }
    /**
     * @deprecated use addAuthenticationOptions instead
     *
     * @param string[] $headers
     *
     * @return string[] updated headers array
     */
    public function addAuthenticationHeader(array $headers, string $origin, string $url): array
    {
        trigger_error('AuthHelper::addAuthenticationHeader is deprecated since Composer 2.9 use addAuthenticationOptions instead.', \E_USER_DEPRECATED);
        $options = ['http' => ['header' => &$headers]];
        $options = $this->addAuthenticationOptions($options, $origin, $url);
        return $options['http']['header'];
    }
    /**
     * @param array<string, mixed> $options
     *
     * @return array<string, mixed> updated options
     */
    public function addAuthenticationOptions(array $options, string $origin, string $url): array
    {
        if (!isset($options['http'])) {
            $options['http'] = [];
        }
        if (!isset($options['http']['header'])) {
            $options['http']['header'] = [];
        }
        $headers =& $options['http']['header'];
        if ($this->io->hasAuthentication($origin)) {
            $authenticationDisplayMessage = null;
            $auth = $this->io->getAuthentication($origin);
            if ($auth['password'] === 'bearer') {
                $headers[] = 'Authorization: Bearer ' . $auth['username'];
            } elseif ($auth['password'] === 'custom-headers') {
                // Handle custom HTTP headers from auth.json
                $customHeaders = null;
                if (is_string($auth['username'])) {
                    $customHeaders = json_decode($auth['username'], \true);
                }
                if (is_array($customHeaders)) {
                    foreach ($customHeaders as $header) {
                        $headers[] = $header;
                    }
                    $authenticationDisplayMessage = 'Using custom HTTP headers for authentication';
                }
            } elseif ('github.com' === $origin && 'x-oauth-basic' === $auth['password']) {
                // only add the access_token if it is actually a github API URL
                if (Preg::isMatch('{^https?://api\.github\.com/}', $url)) {
                    $headers[] = 'Authorization: token ' . $auth['username'];
                    $authenticationDisplayMessage = 'Using GitHub token authentication';
                }
            } elseif (in_array($auth['password'], ['oauth2', 'private-token', 'gitlab-ci-token'], \true) && in_array($origin, $this->config->get('gitlab-domains'), \true)) {
                if ($auth['password'] === 'oauth2') {
                    $headers[] = 'Authorization: Bearer ' . $auth['username'];
                    $authenticationDisplayMessage = 'Using GitLab OAuth token authentication';
                } else {
                    $headers[] = 'PRIVATE-TOKEN: ' . $auth['username'];
                    $authenticationDisplayMessage = 'Using GitLab private token authentication';
                }
            } elseif ('bitbucket.org' === $origin && $url !== \Composer\Util\Bitbucket::OAUTH2_ACCESS_TOKEN_URL && 'x-token-auth' === $auth['username']) {
                if (!$this->isPublicBitBucketDownload($url)) {
                    $headers[] = 'Authorization: Bearer ' . $auth['password'];
                    $authenticationDisplayMessage = 'Using Bitbucket OAuth token authentication';
                }
            } elseif ('client-certificate' === $auth['username']) {
                $options['ssl'] = array_merge($options['ssl'] ?? [], json_decode((string) $auth['password'], \true));
                $authenticationDisplayMessage = 'Using SSL client certificate';
            } else {
                $authStr = base64_encode($auth['username'] . ':' . $auth['password']);
                $headers[] = 'Authorization: Basic ' . $authStr;
                $authenticationDisplayMessage = 'Using HTTP basic authentication with username "' . $auth['username'] . '"';
            }
            if ($authenticationDisplayMessage && (!isset($this->displayedOriginAuthentications[$origin]) || $this->displayedOriginAuthentications[$origin] !== $authenticationDisplayMessage)) {
                $this->io->writeError($authenticationDisplayMessage, \true, IOInterface::DEBUG);
                $this->displayedOriginAuthentications[$origin] = $authenticationDisplayMessage;
            }
        } elseif (in_array($origin, ['api.bitbucket.org', 'api.github.com'], \true)) {
            return $this->addAuthenticationOptions($options, str_replace('api.', '', $origin), $url);
        }
        return $options;
    }
    /**
     * @link https://github.com/composer/composer/issues/5584
     *
     * @param string $urlToBitBucketFile URL to a file at bitbucket.org.
     *
     * @return bool Whether the given URL is a public BitBucket download which requires no authentication.
     */
    public function isPublicBitBucketDownload(string $urlToBitBucketFile): bool
    {
        $domain = parse_url($urlToBitBucketFile, \PHP_URL_HOST);
        if (strpos($domain, 'bitbucket.org') === \false) {
            // Bitbucket downloads are hosted on amazonaws.
            // We do not need to authenticate there at all
            return \true;
        }
        $path = parse_url($urlToBitBucketFile, \PHP_URL_PATH);
        // Path for a public download follows this pattern /{user}/{repo}/downloads/{whatever}
        // {@link https://blog.bitbucket.org/2009/04/12/new-feature-downloads/}
        $pathParts = explode('/', $path);
        return count($pathParts) >= 4 && $pathParts[3] === 'downloads';
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer\Util;

/**
 * @author Andreas Schempp <andreas.schempp@terminal42.ch>
 */
class Zip
{
    /**
     * Gets content of the root composer.json inside a ZIP archive.
     */
    public static function getComposerJson(string $pathToZip): ?string
    {
        if (!extension_loaded('zip')) {
            throw new \RuntimeException('The Zip Util requires PHP\'s zip extension');
        }
        $zip = new \ZipArchive();
        if ($zip->open($pathToZip) !== \true) {
            return null;
        }
        if (0 === $zip->numFiles) {
            $zip->close();
            return null;
        }
        $foundFileIndex = self::locateFile($zip, 'composer.json');
        $content = null;
        $configurationFileName = $zip->getNameIndex($foundFileIndex);
        $stream = $zip->getStream($configurationFileName);
        if (\false !== $stream) {
            $content = stream_get_contents($stream);
        }
        $zip->close();
        return $content;
    }
    /**
     * Find a file by name, returning the one that has the shortest path.
     *
     * @throws \RuntimeException
     */
    private static function locateFile(\ZipArchive $zip, string $filename): int
    {
        // return root composer.json if it is there and is a file
        if (\false !== ($index = $zip->locateName($filename)) && $zip->getFromIndex($index) !== \false) {
            return $index;
        }
        $topLevelPaths = [];
        for ($i = 0; $i < $zip->numFiles; $i++) {
            $name = $zip->getNameIndex($i);
            $dirname = dirname($name);
            // ignore OSX specific resource fork folder
            if (strpos($name, '__MACOSX') !== \false) {
                continue;
            }
            // handle archives with proper TOC
            if ($dirname === '.') {
                $topLevelPaths[$name] = \true;
                if (\count($topLevelPaths) > 1) {
                    throw new \RuntimeException('Archive has more than one top level directories, and no composer.json was found on the top level, so it\'s an invalid archive. Top level paths found were: ' . implode(',', array_keys($topLevelPaths)));
                }
                continue;
            }
            // handle archives which do not have a TOC record for the directory itself
            if (\false === strpos($dirname, '\\') && \false === strpos($dirname, '/')) {
                $topLevelPaths[$dirname . '/'] = \true;
                if (\count($topLevelPaths) > 1) {
                    throw new \RuntimeException('Archive has more than one top level directories, and no composer.json was found on the top level, so it\'s an invalid archive. Top level paths found were: ' . implode(',', array_keys($topLevelPaths)));
                }
            }
        }
        if ($topLevelPaths && \false !== ($index = $zip->locateName(key($topLevelPaths) . $filename)) && $zip->getFromIndex($index) !== \false) {
            return $index;
        }
        throw new \RuntimeException('No composer.json found either at the top level or within the topmost directory');
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer\Util;

use Composer\Config;
use Composer\Downloader\TransportException;
use Composer\IO\IOInterface;
/**
 * @internal
 * @readonly
 */
final class Forgejo
{
    /** @var IOInterface */
    private $io;
    /** @var Config */
    private $config;
    /** @var HttpDownloader */
    private $httpDownloader;
    public function __construct(IOInterface $io, Config $config, \Composer\Util\HttpDownloader $httpDownloader)
    {
        $this->io = $io;
        $this->config = $config;
        $this->httpDownloader = $httpDownloader;
    }
    /**
     * Authorizes a Forgejo domain interactively
     *
     * @param  string                        $originUrl The host this Forgejo instance is located at
     * @param  string                        $message   The reason this authorization is required
     * @throws \RuntimeException
     * @throws TransportException|\Exception
     * @return bool                          true on success
     */
    public function authorizeOAuthInteractively(string $originUrl, ?string $message = null): bool
    {
        if ($message !== null) {
            $this->io->writeError($message);
        }
        $url = 'https://' . $originUrl . '/user/settings/applications';
        $this->io->writeError('Setup a personal access token with repository:read permissions on:');
        $this->io->writeError($url);
        $localAuthConfig = $this->config->getLocalAuthConfigSource();
        $this->io->writeError(sprintf('Tokens will be stored in plain text in "%s" for future use by Composer.', ($localAuthConfig !== null ? $localAuthConfig->getName() . ' OR ' : '') . $this->config->getAuthConfigSource()->getName()));
        $this->io->writeError('For additional information, check https://getcomposer.org/doc/articles/authentication-for-private-packages.md#forgejo-token');
        $storeInLocalAuthConfig = \false;
        if ($localAuthConfig !== null) {
            $storeInLocalAuthConfig = $this->io->askConfirmation('A local auth config source was found, do you want to store the token there?', \true);
        }
        $username = trim((string) $this->io->ask('Username: '));
        $token = trim((string) $this->io->askAndHideAnswer('Token (hidden): '));
        $addTokenManually = sprintf('You can also add it manually later by using "composer config --global --auth forgejo-token.%s <username> <token>"', $originUrl);
        if ($token === '' || $username === '') {
            $this->io->writeError('<warning>No username/token given, aborting.</warning>');
            $this->io->writeError($addTokenManually);
            return \false;
        }
        $this->io->setAuthentication($originUrl, $username, $token);
        try {
            $this->httpDownloader->get('https://' . $originUrl . '/api/v1/version', ['retry-auth-failure' => \false]);
        } catch (TransportException $e) {
            if (in_array($e->getCode(), [403, 401, 404], \true)) {
                $this->io->writeError('<error>Invalid access token provided.</error>');
                $this->io->writeError($addTokenManually);
                return \false;
            }
            throw $e;
        }
        // store value in local/user config
        $authConfigSource = $storeInLocalAuthConfig && $localAuthConfig !== null ? $localAuthConfig : $this->config->getAuthConfigSource();
        $this->config->getConfigSource()->removeConfigSetting('forgejo-token.' . $originUrl);
        $authConfigSource->addConfigSetting('forgejo-token.' . $originUrl, ['username' => $username, 'token' => $token]);
        $this->io->writeError('<info>Token stored successfully.</info>');
        return \true;
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer\Util;

/**
 * Temporarily suppress PHP error reporting, usually warnings and below.
 *
 * @author Niels Keurentjes <niels.keurentjes@omines.com>
 */
class Silencer
{
    /**
     * @var int[] Unpop stack
     */
    private static $stack = [];
    /**
     * Suppresses given mask or errors.
     *
     * @param  int|null $mask Error levels to suppress, default value NULL indicates all warnings and below.
     * @return int      The old error reporting level.
     */
    public static function suppress(?int $mask = null): int
    {
        if (!isset($mask)) {
            $mask = \E_WARNING | \E_NOTICE | \E_USER_WARNING | \E_USER_NOTICE | \E_DEPRECATED | \E_USER_DEPRECATED;
        }
        $old = error_reporting();
        self::$stack[] = $old;
        error_reporting($old & ~$mask);
        return $old;
    }
    /**
     * Restores a single state.
     */
    public static function restore(): void
    {
        if (!empty(self::$stack)) {
            error_reporting(array_pop(self::$stack));
        }
    }
    /**
     * Calls a specified function while silencing warnings and below.
     *
     * @param  callable   $callable Function to execute.
     * @param  mixed      $parameters Function to execute.
     * @throws \Exception Any exceptions from the callback are rethrown.
     * @return mixed      Return value of the callback.
     */
    public static function call(callable $callable, ...$parameters)
    {
        try {
            self::suppress();
            $result = $callable(...$parameters);
            self::restore();
            return $result;
        } catch (\Exception $e) {
            // Use a finally block for this when requirements are raised to PHP 5.5
            self::restore();
            throw $e;
        }
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer\Util;

use Composer\Pcre\Preg;
/**
 * @internal
 * @readonly
 */
final class ForgejoUrl
{
    public const URL_REGEX = '{^(?:(?:https?|git)://([^/]+)/|git@([^:]+):/?)([^/]+)/([^/]+?)(?:\.git|/)?$}';
    /** @var string */
    public $owner;
    /** @var string */
    public $repository;
    /** @var string */
    public $originUrl;
    /** @var string */
    public $apiUrl;
    private function __construct(string $owner, string $repository, string $originUrl, string $apiUrl)
    {
        $this->owner = $owner;
        $this->repository = $repository;
        $this->originUrl = $originUrl;
        $this->apiUrl = $apiUrl;
    }
    public static function create(string $repoUrl): self
    {
        $url = self::tryFrom($repoUrl);
        if ($url !== null) {
            return $url;
        }
        throw new \InvalidArgumentException('This is not a valid Forgejo URL: ' . $repoUrl);
    }
    public static function tryFrom(?string $repoUrl): ?self
    {
        if ($repoUrl === null || !Preg::isMatch(self::URL_REGEX, $repoUrl, $match)) {
            return null;
        }
        $originUrl = strtolower($match[1] ?? (string) $match[2]);
        $apiBase = $originUrl . '/api/v1';
        return new self($match[3], $match[4], $originUrl, sprintf('https://%s/repos/%s/%s', $apiBase, $match[3], $match[4]));
    }
    public function generateSshUrl(): string
    {
        return 'git@' . $this->originUrl . ':' . $this->owner . '/' . $this->repository . '.git';
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer\Util;

use Composer\Pcre\Preg;
use ErrorException;
use React\Promise\PromiseInterface;
use RecursiveDirectoryIterator;
use RecursiveIteratorIterator;
use _ContaoManager\Symfony\Component\Filesystem\Exception\IOException;
use _ContaoManager\Symfony\Component\Finder\Finder;
/**
 * @author Jordi Boggiano <j.boggiano@seld.be>
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
class Filesystem
{
    /** @var ?ProcessExecutor */
    private $processExecutor;
    public function __construct(?\Composer\Util\ProcessExecutor $executor = null)
    {
        $this->processExecutor = $executor;
    }
    /**
     * @return bool
     */
    public function remove(string $file)
    {
        if (is_dir($file)) {
            return $this->removeDirectory($file);
        }
        if (file_exists($file)) {
            return $this->unlink($file);
        }
        return \false;
    }
    /**
     * Checks if a directory is empty
     *
     * @return bool
     */
    public function isDirEmpty(string $dir)
    {
        $finder = Finder::create()->ignoreVCS(\false)->ignoreDotFiles(\false)->depth(0)->in($dir);
        return \count($finder) === 0;
    }
    /**
     * @return void
     */
    public function emptyDirectory(string $dir, bool $ensureDirectoryExists = \true)
    {
        if (is_link($dir) && file_exists($dir)) {
            $this->unlink($dir);
        }
        if ($ensureDirectoryExists) {
            $this->ensureDirectoryExists($dir);
        }
        if (is_dir($dir)) {
            $finder = Finder::create()->ignoreVCS(\false)->ignoreDotFiles(\false)->depth(0)->in($dir);
            foreach ($finder as $path) {
                $this->remove((string) $path);
            }
        }
    }
    /**
     * Recursively remove a directory
     *
     * Uses the process component if proc_open is enabled on the PHP
     * installation.
     *
     * @throws \RuntimeException
     * @return bool
     */
    public function removeDirectory(string $directory)
    {
        $edgeCaseResult = $this->removeEdgeCases($directory);
        if ($edgeCaseResult !== null) {
            return $edgeCaseResult;
        }
        if (\Composer\Util\Platform::isWindows()) {
            $cmd = ['rmdir', '/S', '/Q', \Composer\Util\Platform::realpath($directory)];
        } else {
            $cmd = ['rm', '-rf', $directory];
        }
        $result = $this->getProcess()->execute($cmd, $output) === 0;
        // clear stat cache because external processes aren't tracked by the php stat cache
        clearstatcache();
        if ($result && !is_dir($directory)) {
            return \true;
        }
        return $this->removeDirectoryPhp($directory);
    }
    /**
     * Recursively remove a directory asynchronously
     *
     * Uses the process component if proc_open is enabled on the PHP
     * installation.
     *
     * @throws \RuntimeException
     * @return PromiseInterface
     * @phpstan-return PromiseInterface<bool>
     */
    public function removeDirectoryAsync(string $directory)
    {
        $edgeCaseResult = $this->removeEdgeCases($directory);
        if ($edgeCaseResult !== null) {
            return \React\Promise\resolve($edgeCaseResult);
        }
        if (\Composer\Util\Platform::isWindows()) {
            $cmd = ['rmdir', '/S', '/Q', \Composer\Util\Platform::realpath($directory)];
        } else {
            $cmd = ['rm', '-rf', $directory];
        }
        $promise = $this->getProcess()->executeAsync($cmd);
        return $promise->then(function ($process) use ($directory) {
            // clear stat cache because external processes aren't tracked by the php stat cache
            clearstatcache();
            if ($process->isSuccessful()) {
                if (!is_dir($directory)) {
                    return \React\Promise\resolve(\true);
                }
            }
            return \React\Promise\resolve($this->removeDirectoryPhp($directory));
        });
    }
    /**
     * @return bool|null Returns null, when no edge case was hit. Otherwise a bool whether removal was successful
     */
    private function removeEdgeCases(string $directory, bool $fallbackToPhp = \true): ?bool
    {
        if ($this->isSymlinkedDirectory($directory)) {
            return $this->unlinkSymlinkedDirectory($directory);
        }
        if ($this->isJunction($directory)) {
            return $this->removeJunction($directory);
        }
        if (is_link($directory)) {
            return unlink($directory);
        }
        if (!is_dir($directory) || !file_exists($directory)) {
            return \true;
        }
        if (Preg::isMatch('{^(?:[a-z]:)?[/\\\\]+$}i', $directory)) {
            throw new \RuntimeException('Aborting an attempted deletion of ' . $directory . ', this was probably not intended, if it is a real use case please report it.');
        }
        if (!\function_exists('proc_open') && !\function_exists('_ContaoManager\proc_open') && $fallbackToPhp) {
            return $this->removeDirectoryPhp($directory);
        }
        return null;
    }
    /**
     * Recursively delete directory using PHP iterators.
     *
     * Uses a CHILD_FIRST RecursiveIteratorIterator to sort files
     * before directories, creating a single non-recursive loop
     * to delete files/directories in the correct order.
     *
     * @return bool
     */
    public function removeDirectoryPhp(string $directory)
    {
        $edgeCaseResult = $this->removeEdgeCases($directory, \false);
        if ($edgeCaseResult !== null) {
            return $edgeCaseResult;
        }
        try {
            $it = new RecursiveDirectoryIterator($directory, RecursiveDirectoryIterator::SKIP_DOTS);
        } catch (\UnexpectedValueException $e) {
            // re-try once after clearing the stat cache if it failed as it
            // sometimes fails without apparent reason, see https://github.com/composer/composer/issues/4009
            clearstatcache();
            usleep(100000);
            if (!is_dir($directory)) {
                return \true;
            }
            $it = new RecursiveDirectoryIterator($directory, RecursiveDirectoryIterator::SKIP_DOTS);
        }
        $ri = new RecursiveIteratorIterator($it, RecursiveIteratorIterator::CHILD_FIRST);
        foreach ($ri as $file) {
            if ($file->isDir()) {
                $this->rmdir($file->getPathname());
            } else {
                $this->unlink($file->getPathname());
            }
        }
        // release locks on the directory, see https://github.com/composer/composer/issues/9945
        unset($ri, $it, $file);
        return $this->rmdir($directory);
    }
    /**
     * @return void
     */
    public function ensureDirectoryExists(string $directory)
    {
        if (!is_dir($directory)) {
            if (file_exists($directory)) {
                throw new \RuntimeException($directory . ' exists and is not a directory.');
            }
            if (is_link($directory) && !@$this->unlinkImplementation($directory)) {
                throw new \RuntimeException('Could not delete symbolic link ' . $directory . ': ' . (error_get_last()['message'] ?? ''));
            }
            if (!@mkdir($directory, 0777, \true)) {
                $e = new \RuntimeException($directory . ' does not exist and could not be created: ' . (error_get_last()['message'] ?? ''));
                // in pathological cases with paths like path/to/broken-symlink/../foo is_dir will fail to detect path/to/foo
                // but normalizing the ../ away first makes it work so we attempt this just in case, and if it still fails we
                // report the initial error we had with the original path, and ignore the normalized path exception
                // see https://github.com/composer/composer/issues/11864
                $normalized = $this->normalizePath($directory);
                if ($normalized !== $directory) {
                    try {
                        $this->ensureDirectoryExists($normalized);
                        return;
                    } catch (\Throwable $ignoredEx) {
                    }
                }
                throw $e;
            }
        }
    }
    /**
     * Attempts to unlink a file and in case of failure retries after 350ms on windows
     *
     * @throws \RuntimeException
     * @return bool
     */
    public function unlink(string $path)
    {
        $unlinked = @$this->unlinkImplementation($path);
        if (!$unlinked) {
            // retry after a bit on windows since it tends to be touchy with mass removals
            if (\Composer\Util\Platform::isWindows()) {
                usleep(350000);
                $unlinked = @$this->unlinkImplementation($path);
            }
            if (!$unlinked) {
                $error = error_get_last();
                $message = 'Could not delete ' . $path . ': ' . ($error['message'] ?? '');
                if (\Composer\Util\Platform::isWindows()) {
                    $message .= "\nThis can be due to an antivirus or the Windows Search Indexer locking the file while they are analyzed";
                }
                throw new \RuntimeException($message);
            }
        }
        return \true;
    }
    /**
     * Attempts to rmdir a file and in case of failure retries after 350ms on windows
     *
     * @throws \RuntimeException
     * @return bool
     */
    public function rmdir(string $path)
    {
        $deleted = @rmdir($path);
        if (!$deleted) {
            // retry after a bit on windows since it tends to be touchy with mass removals
            if (\Composer\Util\Platform::isWindows()) {
                usleep(350000);
                $deleted = @rmdir($path);
            }
            if (!$deleted) {
                $error = error_get_last();
                $message = 'Could not delete ' . $path . ': ' . ($error['message'] ?? '');
                if (\Composer\Util\Platform::isWindows()) {
                    $message .= "\nThis can be due to an antivirus or the Windows Search Indexer locking the file while they are analyzed";
                }
                throw new \RuntimeException($message);
            }
        }
        return \true;
    }
    /**
     * Copy then delete is a non-atomic version of {@link rename}.
     *
     * Some systems can't rename and also don't have proc_open,
     * which requires this solution.
     *
     * @return void
     */
    public function copyThenRemove(string $source, string $target)
    {
        $this->copy($source, $target);
        if (!is_dir($source)) {
            $this->unlink($source);
            return;
        }
        $this->removeDirectoryPhp($source);
    }
    /**
     * Copies a file or directory from $source to $target.
     *
     * @return bool
     */
    public function copy(string $source, string $target)
    {
        // refs https://github.com/composer/composer/issues/11864
        $target = $this->normalizePath($target);
        if (!is_dir($source)) {
            try {
                return copy($source, $target);
            } catch (ErrorException $e) {
                // if copy fails we attempt to copy it manually as this can help bypass issues with VirtualBox shared folders
                // see https://github.com/composer/composer/issues/12057
                if (str_contains($e->getMessage(), 'Bad address')) {
                    $sourceHandle = fopen($source, 'r');
                    $targetHandle = fopen($target, 'w');
                    if (\false === $sourceHandle || \false === $targetHandle) {
                        throw $e;
                    }
                    while (!feof($sourceHandle)) {
                        if (\false === fwrite($targetHandle, (string) fread($sourceHandle, 1024 * 1024))) {
                            throw $e;
                        }
                    }
                    fclose($sourceHandle);
                    fclose($targetHandle);
                    return \true;
                }
                throw $e;
            }
        }
        $it = new RecursiveDirectoryIterator($source, RecursiveDirectoryIterator::SKIP_DOTS);
        $ri = new RecursiveIteratorIterator($it, RecursiveIteratorIterator::SELF_FIRST);
        $this->ensureDirectoryExists($target);
        $result = \true;
        foreach ($ri as $file) {
            $targetPath = $target . \DIRECTORY_SEPARATOR . $ri->getSubPathname();
            if ($file->isDir()) {
                $this->ensureDirectoryExists($targetPath);
            } else {
                $result = $result && copy($file->getPathname(), $targetPath);
            }
        }
        return $result;
    }
    /**
     * @return void
     */
    public function rename(string $source, string $target)
    {
        if (\true === @rename($source, $target)) {
            return;
        }
        if (!\function_exists('proc_open') && !\function_exists('_ContaoManager\proc_open')) {
            $this->copyThenRemove($source, $target);
            return;
        }
        if (\Composer\Util\Platform::isWindows()) {
            // Try to copy & delete - this is a workaround for random "Access denied" errors.
            $result = $this->getProcess()->execute(['xcopy', $source, $target, '/E', '/I', '/Q', '/Y'], $output);
            // clear stat cache because external processes aren't tracked by the php stat cache
            clearstatcache();
            if (0 === $result) {
                $this->remove($source);
                return;
            }
        } else {
            // We do not use PHP's "rename" function here since it does not support
            // the case where $source, and $target are located on different partitions.
            $result = $this->getProcess()->execute(['mv', $source, $target], $output);
            // clear stat cache because external processes aren't tracked by the php stat cache
            clearstatcache();
            if (0 === $result) {
                return;
            }
        }
        $this->copyThenRemove($source, $target);
    }
    /**
     * Returns the shortest path from $from to $to
     *
     * @param  bool                      $directories if true, the source/target are considered to be directories
     * @param  bool                      $preferRelative if true, relative paths will be preferred even if longer
     * @throws \InvalidArgumentException
     * @return string
     */
    public function findShortestPath(string $from, string $to, bool $directories = \false, bool $preferRelative = \false)
    {
        if (!$this->isAbsolutePath($from) || !$this->isAbsolutePath($to)) {
            throw new \InvalidArgumentException(sprintf('$from (%s) and $to (%s) must be absolute paths.', $from, $to));
        }
        $from = $this->normalizePath($from);
        $to = $this->normalizePath($to);
        if ($directories) {
            $from = rtrim($from, '/') . '/dummy_file';
        }
        if (\dirname($from) === \dirname($to)) {
            return './' . basename($to);
        }
        $commonPath = $to;
        while (strpos($from . '/', $commonPath . '/') !== 0 && '/' !== $commonPath && !Preg::isMatch('{^[A-Z]:/?$}i', $commonPath)) {
            $commonPath = strtr(\dirname($commonPath), '\\', '/');
        }
        // no commonality at all
        if (0 !== strpos($from, $commonPath)) {
            return $to;
        }
        $commonPath = rtrim($commonPath, '/') . '/';
        $sourcePathDepth = substr_count((string) substr($from, \strlen($commonPath)), '/');
        $commonPathCode = str_repeat('../', $sourcePathDepth);
        // allow top level /foo & /bar dirs to be addressed relatively as this is common in Docker setups
        if (!$preferRelative && '/' === $commonPath && $sourcePathDepth > 1) {
            return $to;
        }
        $result = $commonPathCode . substr($to, \strlen($commonPath));
        if (\strlen($result) === 0) {
            return './';
        }
        return $result;
    }
    /**
     * Returns PHP code that, when executed in $from, will return the path to $to
     *
     * @param  bool                      $directories if true, the source/target are considered to be directories
     * @param  bool                      $preferRelative if true, relative paths will be preferred even if longer
     * @throws \InvalidArgumentException
     * @return string
     */
    public function findShortestPathCode(string $from, string $to, bool $directories = \false, bool $staticCode = \false, bool $preferRelative = \false)
    {
        if (!$this->isAbsolutePath($from) || !$this->isAbsolutePath($to)) {
            throw new \InvalidArgumentException(sprintf('$from (%s) and $to (%s) must be absolute paths.', $from, $to));
        }
        $from = $this->normalizePath($from);
        $to = $this->normalizePath($to);
        if ($from === $to) {
            return $directories ? '__DIR__' : '__FILE__';
        }
        $commonPath = $to;
        while (strpos($from . '/', $commonPath . '/') !== 0 && '/' !== $commonPath && !Preg::isMatch('{^[A-Z]:/?$}i', $commonPath) && '.' !== $commonPath) {
            $commonPath = strtr(\dirname($commonPath), '\\', '/');
        }
        // no commonality at all
        if (0 !== strpos($from, $commonPath) || '.' === $commonPath) {
            return var_export($to, \true);
        }
        $commonPath = rtrim($commonPath, '/') . '/';
        if (str_starts_with($to, $from . '/')) {
            return '__DIR__ . ' . var_export((string) substr($to, \strlen($from)), \true);
        }
        $sourcePathDepth = substr_count((string) substr($from, \strlen($commonPath)), '/') + (int) $directories;
        // allow top level /foo & /bar dirs to be addressed relatively as this is common in Docker setups
        if (!$preferRelative && '/' === $commonPath && $sourcePathDepth > 1) {
            return var_export($to, \true);
        }
        if ($staticCode) {
            $commonPathCode = "__DIR__ . '" . str_repeat('/..', $sourcePathDepth) . "'";
        } else {
            $commonPathCode = str_repeat('dirname(', $sourcePathDepth) . '__DIR__' . str_repeat(')', $sourcePathDepth);
        }
        $relTarget = (string) substr($to, \strlen($commonPath));
        return $commonPathCode . (\strlen($relTarget) > 0 ? '.' . var_export('/' . $relTarget, \true) : '');
    }
    /**
     * Checks if the given path is absolute
     *
     * @return bool
     */
    public function isAbsolutePath(string $path)
    {
        return strpos($path, '/') === 0 || substr($path, 1, 1) === ':' || strpos($path, '\\\\') === 0;
    }
    /**
     * Returns size of a file or directory specified by path. If a directory is
     * given, its size will be computed recursively.
     *
     * @param  string            $path Path to the file or directory
     * @throws \RuntimeException
     * @return int
     */
    public function size(string $path)
    {
        if (!file_exists($path)) {
            throw new \RuntimeException("{$path} does not exist.");
        }
        if (is_dir($path)) {
            return $this->directorySize($path);
        }
        return (int) filesize($path);
    }
    /**
     * Normalize a path. This replaces backslashes with slashes, removes ending
     * slash and collapses redundant separators and up-level references.
     *
     * @param  string $path Path to the file or directory
     * @return string
     */
    public function normalizePath(string $path)
    {
        $parts = [];
        $path = strtr($path, '\\', '/');
        $prefix = '';
        $absolute = '';
        // extract windows UNC paths e.g. \\foo\bar
        if (strpos($path, '//') === 0 && \strlen($path) > 2) {
            $absolute = '//';
            $path = substr($path, 2);
        }
        // extract a prefix being a protocol://, protocol:, protocol://drive: or simply drive:
        if (Preg::isMatchStrictGroups('{^( [0-9a-z]{2,}+: (?: // (?: [a-z]: )? )? | [a-z]: )}ix', $path, $match)) {
            $prefix = $match[1];
            $path = substr($path, \strlen($prefix));
        }
        if (strpos($path, '/') === 0) {
            $absolute = '/';
            $path = substr($path, 1);
        }
        $up = \false;
        foreach (explode('/', $path) as $chunk) {
            if ('..' === $chunk && (\strlen($absolute) > 0 || $up)) {
                array_pop($parts);
                $up = !(\count($parts) === 0 || '..' === end($parts));
            } elseif ('.' !== $chunk && '' !== $chunk) {
                $parts[] = $chunk;
                $up = '..' !== $chunk;
            }
        }
        // ensure c: is normalized to C:
        $prefix = Preg::replaceCallback('{(^|://)[a-z]:$}i', static function (array $m) {
            return strtoupper($m[0]);
        }, $prefix);
        return $prefix . $absolute . implode('/', $parts);
    }
    /**
     * Remove trailing slashes if present to avoid issues with symlinks
     *
     * And other possible unforeseen disasters, see https://github.com/composer/composer/pull/9422
     *
     * @return string
     */
    public static function trimTrailingSlash(string $path)
    {
        if (!Preg::isMatch('{^[/\\\\]+$}', $path)) {
            $path = rtrim($path, '/\\');
        }
        return $path;
    }
    /**
     * Return if the given path is local
     *
     * @return bool
     */
    public static function isLocalPath(string $path)
    {
        // on windows, \\foo indicates network paths so we exclude those from local paths, however it is unsafe
        // on linux as file:////foo (which would be a network path \\foo on windows) will resolve to /foo which could be a local path
        if (\Composer\Util\Platform::isWindows()) {
            return Preg::isMatch('{^(file://(?!//)|/(?!/)|/?[a-z]:[\\\\/]|\.\.[\\\\/]|[a-z0-9_.-]+[\\\\/])}i', $path);
        }
        return Preg::isMatch('{^(file://|/|/?[a-z]:[\\\\/]|\.\.[\\\\/]|[a-z0-9_.-]+[\\\\/])}i', $path);
    }
    /**
     * @return string
     */
    public static function getPlatformPath(string $path)
    {
        if (\Composer\Util\Platform::isWindows()) {
            $path = Preg::replace('{^(?:file:///([a-z]):?/)}i', 'file://$1:/', $path);
        }
        return Preg::replace('{^file://}i', '', $path);
    }
    /**
     * Cross-platform safe version of is_readable()
     *
     * This will also check for readability by reading the file as is_readable can not be trusted on network-mounts
     * and \\wsl$ paths. See https://github.com/composer/composer/issues/8231 and https://bugs.php.net/bug.php?id=68926
     *
     * @return bool
     */
    public static function isReadable(string $path)
    {
        if (is_readable($path)) {
            return \true;
        }
        if (is_file($path)) {
            return \false !== \Composer\Util\Silencer::call('file_get_contents', $path, \false, null, 0, 1);
        }
        if (is_dir($path)) {
            return \false !== \Composer\Util\Silencer::call('opendir', $path);
        }
        // assume false otherwise
        return \false;
    }
    /**
     * @return int
     */
    protected function directorySize(string $directory)
    {
        $it = new RecursiveDirectoryIterator($directory, RecursiveDirectoryIterator::SKIP_DOTS);
        $ri = new RecursiveIteratorIterator($it, RecursiveIteratorIterator::CHILD_FIRST);
        $size = 0;
        foreach ($ri as $file) {
            if ($file->isFile()) {
                $size += $file->getSize();
            }
        }
        return $size;
    }
    /**
     * @return ProcessExecutor
     */
    protected function getProcess()
    {
        if (null === $this->processExecutor) {
            $this->processExecutor = new \Composer\Util\ProcessExecutor();
        }
        return $this->processExecutor;
    }
    /**
     * delete symbolic link implementation (commonly known as "unlink()")
     *
     * symbolic links on windows which link to directories need rmdir instead of unlink
     */
    private function unlinkImplementation(string $path): bool
    {
        if (\Composer\Util\Platform::isWindows() && is_dir($path) && is_link($path)) {
            return rmdir($path);
        }
        return unlink($path);
    }
    /**
     * Creates a relative symlink from $link to $target
     *
     * @param  string $target The path of the binary file to be symlinked
     * @param  string $link   The path where the symlink should be created
     * @return bool
     */
    public function relativeSymlink(string $target, string $link)
    {
        if (!function_exists('symlink')) {
            return \false;
        }
        $cwd = \Composer\Util\Platform::getCwd();
        $relativePath = $this->findShortestPath($link, $target);
        chdir(\dirname($link));
        $result = @symlink($relativePath, $link);
        chdir($cwd);
        return $result;
    }
    /**
     * return true if that directory is a symlink.
     *
     * @return bool
     */
    public function isSymlinkedDirectory(string $directory)
    {
        if (!is_dir($directory)) {
            return \false;
        }
        $resolved = $this->resolveSymlinkedDirectorySymlink($directory);
        return is_link($resolved);
    }
    private function unlinkSymlinkedDirectory(string $directory): bool
    {
        $resolved = $this->resolveSymlinkedDirectorySymlink($directory);
        return $this->unlink($resolved);
    }
    /**
     * resolve pathname to symbolic link of a directory
     *
     * @param string $pathname directory path to resolve
     *
     * @return string resolved path to symbolic link or original pathname (unresolved)
     */
    private function resolveSymlinkedDirectorySymlink(string $pathname): string
    {
        if (!is_dir($pathname)) {
            return $pathname;
        }
        $resolved = rtrim($pathname, '/');
        if (0 === \strlen($resolved)) {
            return $pathname;
        }
        return $resolved;
    }
    /**
     * Creates an NTFS junction.
     *
     * @return void
     */
    public function junction(string $target, string $junction)
    {
        if (!\Composer\Util\Platform::isWindows()) {
            throw new \LogicException(sprintf('Function %s is not available on non-Windows platform', __CLASS__));
        }
        if (!is_dir($target)) {
            throw new IOException(sprintf('Cannot junction to "%s" as it is not a directory.', $target), 0, null, $target);
        }
        // Removing any previously junction to ensure clean execution.
        if (!is_dir($junction) || $this->isJunction($junction)) {
            @rmdir($junction);
        }
        $cmd = ['mklink', '/J', str_replace('/', \DIRECTORY_SEPARATOR, $junction), \Composer\Util\Platform::realpath($target)];
        if ($this->getProcess()->execute($cmd, $output) !== 0) {
            throw new IOException(sprintf('Failed to create junction to "%s" at "%s".', $target, $junction), 0, null, $target);
        }
        clearstatcache(\true, $junction);
    }
    /**
     * Returns whether the target directory is a Windows NTFS Junction.
     *
     * We test if the path is a directory and not an ordinary link, then check
     * that the mode value returned from lstat (which gives the status of the
     * link itself) is not a directory, by replicating the POSIX S_ISDIR test.
     *
     * This logic works because PHP does not set the mode value for a junction,
     * since there is no universal file type flag for it. Unfortunately an
     * uninitialized variable in PHP prior to 7.2.16 and 7.3.3 may cause a
     * random value to be returned. See https://bugs.php.net/bug.php?id=77552
     *
     * If this random value passes the S_ISDIR test, then a junction will not be
     * detected and a recursive delete operation could lead to loss of data in
     * the target directory. Note that Windows rmdir can handle this situation
     * and will only delete the junction (from Windows 7 onwards).
     *
     * @param  string $junction Path to check.
     * @return bool
     */
    public function isJunction(string $junction)
    {
        if (!\Composer\Util\Platform::isWindows()) {
            return \false;
        }
        // Important to clear all caches first
        clearstatcache(\true, $junction);
        if (!is_dir($junction) || is_link($junction)) {
            return \false;
        }
        $stat = lstat($junction);
        // S_ISDIR test (S_IFDIR is 0x4000, S_IFMT is 0xF000 bitmask)
        return is_array($stat) ? 0x4000 !== ($stat['mode'] & 0xf000) : \false;
    }
    /**
     * Removes a Windows NTFS junction.
     *
     * @return bool
     */
    public function removeJunction(string $junction)
    {
        if (!\Composer\Util\Platform::isWindows()) {
            return \false;
        }
        $junction = rtrim(str_replace('/', \DIRECTORY_SEPARATOR, $junction), \DIRECTORY_SEPARATOR);
        if (!$this->isJunction($junction)) {
            throw new IOException(sprintf('%s is not a junction and thus cannot be removed as one', $junction));
        }
        return $this->rmdir($junction);
    }
    /**
     * @return int|false
     */
    public function filePutContentsIfModified(string $path, string $content)
    {
        $currentContent = \Composer\Util\Silencer::call('file_get_contents', $path);
        if (\false === $currentContent || $currentContent !== $content) {
            return file_put_contents($path, $content);
        }
        return 0;
    }
    /**
     * Copy file using stream_copy_to_stream to work around https://bugs.php.net/bug.php?id=6463
     */
    public function safeCopy(string $source, string $target): void
    {
        if (!file_exists($target) || !file_exists($source) || !$this->filesAreEqual($source, $target)) {
            $sourceHandle = fopen($source, 'r');
            assert($sourceHandle !== \false, 'Could not open "' . $source . '" for reading.');
            $targetHandle = fopen($target, 'w+');
            assert($targetHandle !== \false, 'Could not open "' . $target . '" for writing.');
            stream_copy_to_stream($sourceHandle, $targetHandle);
            fclose($sourceHandle);
            fclose($targetHandle);
            touch($target, (int) filemtime($source), (int) fileatime($source));
        }
    }
    /**
     * compare 2 files
     * https://stackoverflow.com/questions/3060125/can-i-use-file-get-contents-to-compare-two-files
     */
    private function filesAreEqual(string $a, string $b): bool
    {
        // Check if filesize is different
        if (filesize($a) !== filesize($b)) {
            return \false;
        }
        // Check if content is different
        $aHandle = fopen($a, 'rb');
        assert($aHandle !== \false, 'Could not open "' . $a . '" for reading.');
        $bHandle = fopen($b, 'rb');
        assert($bHandle !== \false, 'Could not open "' . $b . '" for reading.');
        $result = \true;
        while (!feof($aHandle)) {
            if (fread($aHandle, 8192) !== fread($bHandle, 8192)) {
                $result = \false;
                break;
            }
        }
        fclose($aHandle);
        fclose($bHandle);
        return $result;
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer\Util;

/**
 * @author Wissem Riahi <wissemr@gmail.com>
 */
class Tar
{
    public static function getComposerJson(string $pathToArchive): ?string
    {
        $phar = new \PharData($pathToArchive);
        if (!$phar->valid()) {
            return null;
        }
        return self::extractComposerJsonFromFolder($phar);
    }
    /**
     * @throws \RuntimeException
     */
    private static function extractComposerJsonFromFolder(\PharData $phar): string
    {
        if (isset($phar['composer.json'])) {
            return $phar['composer.json']->getContent();
        }
        $topLevelPaths = [];
        foreach ($phar as $folderFile) {
            $name = $folderFile->getBasename();
            if ($folderFile->isDir()) {
                $topLevelPaths[$name] = \true;
                if (\count($topLevelPaths) > 1) {
                    throw new \RuntimeException('Archive has more than one top level directories, and no composer.json was found on the top level, so it\'s an invalid archive. Top level paths found were: ' . implode(',', array_keys($topLevelPaths)));
                }
            }
        }
        $composerJsonPath = key($topLevelPaths) . '/composer.json';
        if (\count($topLevelPaths) > 0 && isset($phar[$composerJsonPath])) {
            return $phar[$composerJsonPath]->getContent();
        }
        throw new \RuntimeException('No composer.json found either at the top level or within the topmost directory');
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer\Util;

use Composer\Factory;
use Composer\IO\IOInterface;
use Composer\Config;
use Composer\Downloader\TransportException;
use Composer\Pcre\Preg;
/**
 * @author Jordi Boggiano <j.boggiano@seld.be>
 */
class GitHub
{
    public const GITHUB_TOKEN_REGEX = '{^([a-f0-9]{12,}|gh[a-z]_[a-zA-Z0-9_]+|github_pat_[a-zA-Z0-9_]+)$}';
    /** @var IOInterface */
    protected $io;
    /** @var Config */
    protected $config;
    /** @var ProcessExecutor */
    protected $process;
    /** @var HttpDownloader */
    protected $httpDownloader;
    /**
     * Constructor.
     *
     * @param IOInterface     $io             The IO instance
     * @param Config          $config         The composer configuration
     * @param ProcessExecutor $process        Process instance, injectable for mocking
     * @param HttpDownloader  $httpDownloader Remote Filesystem, injectable for mocking
     */
    public function __construct(IOInterface $io, Config $config, ?\Composer\Util\ProcessExecutor $process = null, ?\Composer\Util\HttpDownloader $httpDownloader = null)
    {
        $this->io = $io;
        $this->config = $config;
        $this->process = $process ?: new \Composer\Util\ProcessExecutor($io);
        $this->httpDownloader = $httpDownloader ?: Factory::createHttpDownloader($this->io, $config);
    }
    /**
     * Attempts to authorize a GitHub domain via OAuth
     *
     * @param  string $originUrl The host this GitHub instance is located at
     * @return bool   true on success
     */
    public function authorizeOAuth(string $originUrl): bool
    {
        if (!in_array($originUrl, $this->config->get('github-domains'))) {
            return \false;
        }
        // if available use token from git config
        if (0 === $this->process->execute(['git', 'config', 'github.accesstoken'], $output)) {
            $this->io->setAuthentication($originUrl, trim($output), 'x-oauth-basic');
            return \true;
        }
        return \false;
    }
    /**
     * Authorizes a GitHub domain interactively via OAuth
     *
     * @param  string                        $originUrl The host this GitHub instance is located at
     * @param  string                        $message   The reason this authorization is required
     * @throws \RuntimeException
     * @throws TransportException|\Exception
     * @return bool                          true on success
     */
    public function authorizeOAuthInteractively(string $originUrl, ?string $message = null): bool
    {
        if ($message) {
            $this->io->writeError($message);
        }
        $note = 'Composer';
        if ($this->config->get('github-expose-hostname') === \true && 0 === $this->process->execute(['hostname'], $output)) {
            $note .= ' on ' . trim($output);
        }
        $note .= ' ' . date('Y-m-d Hi');
        $localAuthConfig = $this->config->getLocalAuthConfigSource();
        $this->io->writeError(['You need to provide a GitHub access token.', sprintf('Tokens will be stored in plain text in "%s" for future use by Composer.', ($localAuthConfig !== null ? $localAuthConfig->getName() . ' OR ' : '') . $this->config->getAuthConfigSource()->getName()), 'Due to the security risk of tokens being exfiltrated, use tokens with short expiration times and only the minimum permissions necessary.', '', 'Carefully consider the following options in order:', '']);
        $this->io->writeError(['1. When you don\'t use \'vcs\'  type \'repositories\'  in composer.json and do not need to clone source or download dist files', 'from private GitHub repositories over HTTPS, use a fine-grained token with read-only access to public information.', 'Use the following URL to create such a token:', 'https://' . $originUrl . '/settings/personal-access-tokens/new?name=' . str_replace('%20', '+', rawurlencode($note)), '']);
        $this->io->writeError(['2. When all relevant _private_ GitHub repositories belong to a single user or organisation, use a fine-grained token with', 'repository "content" read-only permissions. You can start with the following URL, but you may need to change the resource owner', 'to the right user or organisation. Additionally, you can scope permissions down to apply only to selected repositories.', 'https://' . $originUrl . '/settings/personal-access-tokens/new?contents=read&name=' . str_replace('%20', '+', rawurlencode($note)), '']);
        $this->io->writeError(['3. A "classic" token grants broad permissions on your behalf to all repositories accessible by you.', 'This may include write permissions, even though not needed by Composer. Use it only when you need to access', 'private repositories across multiple organisations at the same time and using directory-specific authentication sources', 'is not an option. You can generate a classic token here:', 'https://' . $originUrl . '/settings/tokens/new?scopes=repo&description=' . str_replace('%20', '+', rawurlencode($note)), '']);
        $this->io->writeError('For additional information, check https://getcomposer.org/doc/articles/authentication-for-private-packages.md#github-oauth');
        $storeInLocalAuthConfig = \false;
        if ($localAuthConfig !== null) {
            $storeInLocalAuthConfig = $this->io->askConfirmation('A local auth config source was found, do you want to store the token there?', \true);
        }
        $token = trim((string) $this->io->askAndHideAnswer('Token (hidden): '));
        if ($token === '') {
            $this->io->writeError('<warning>No token given, aborting.</warning>');
            $this->io->writeError('You can also add it manually later by using "composer config --global --auth github-oauth.github.com <token>"');
            return \false;
        }
        $this->io->setAuthentication($originUrl, $token, 'x-oauth-basic');
        try {
            $apiUrl = 'github.com' === $originUrl ? 'api.github.com/' : $originUrl . '/api/v3/';
            $this->httpDownloader->get('https://' . $apiUrl, ['retry-auth-failure' => \false]);
        } catch (TransportException $e) {
            if (in_array($e->getCode(), [403, 401])) {
                $this->io->writeError('<error>Invalid token provided.</error>');
                $this->io->writeError('You can also add it manually later by using "composer config --global --auth github-oauth.github.com <token>"');
                return \false;
            }
            throw $e;
        }
        // store value in local/user config
        $authConfigSource = $storeInLocalAuthConfig && $localAuthConfig !== null ? $localAuthConfig : $this->config->getAuthConfigSource();
        $this->config->getConfigSource()->removeConfigSetting('github-oauth.' . $originUrl);
        $authConfigSource->addConfigSetting('github-oauth.' . $originUrl, $token);
        $this->io->writeError('<info>Token stored successfully.</info>');
        return \true;
    }
    /**
     * Extract rate limit from response.
     *
     * @param string[] $headers Headers from Composer\Downloader\TransportException.
     *
     * @return array{limit: int|'?', reset: string}
     */
    public function getRateLimit(array $headers): array
    {
        $rateLimit = ['limit' => '?', 'reset' => '?'];
        foreach ($headers as $header) {
            $header = trim($header);
            if (\false === stripos($header, 'x-ratelimit-')) {
                continue;
            }
            [$type, $value] = explode(':', $header, 2);
            switch (strtolower($type)) {
                case 'x-ratelimit-limit':
                    $rateLimit['limit'] = (int) trim($value);
                    break;
                case 'x-ratelimit-reset':
                    $rateLimit['reset'] = date('Y-m-d H:i:s', (int) trim($value));
                    break;
            }
        }
        return $rateLimit;
    }
    /**
     * Extract SSO URL from response.
     *
     * @param string[] $headers Headers from Composer\Downloader\TransportException.
     */
    public function getSsoUrl(array $headers): ?string
    {
        foreach ($headers as $header) {
            $header = trim($header);
            if (\false === stripos($header, 'x-github-sso: required')) {
                continue;
            }
            if (Preg::isMatch('{\burl=(?P<url>[^\s;]+)}', $header, $match)) {
                return $match['url'];
            }
        }
        return null;
    }
    /**
     * Finds whether a request failed due to rate limiting
     *
     * @param string[] $headers Headers from Composer\Downloader\TransportException.
     */
    public function isRateLimited(array $headers): bool
    {
        foreach ($headers as $header) {
            if (Preg::isMatch('{^x-ratelimit-remaining: *0$}i', trim($header))) {
                return \true;
            }
        }
        return \false;
    }
    /**
     * Finds whether a request failed due to lacking SSO authorization
     *
     * @see https://docs.github.com/en/rest/overview/other-authentication-methods#authenticating-for-saml-sso
     *
     * @param string[] $headers Headers from Composer\Downloader\TransportException.
     */
    public function requiresSso(array $headers): bool
    {
        foreach ($headers as $header) {
            if (Preg::isMatch('{^x-github-sso: required}i', trim($header))) {
                return \true;
            }
        }
        return \false;
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer\Util;

use Composer\IO\IOInterface;
use Composer\Config;
use Composer\Factory;
use Composer\Downloader\TransportException;
use Composer\Pcre\Preg;
/**
 * @author Roshan Gautam <roshan.gautam@hotmail.com>
 */
class GitLab
{
    /** @var IOInterface */
    protected $io;
    /** @var Config */
    protected $config;
    /** @var ProcessExecutor */
    protected $process;
    /** @var HttpDownloader */
    protected $httpDownloader;
    /**
     * Constructor.
     *
     * @param IOInterface     $io             The IO instance
     * @param Config          $config         The composer configuration
     * @param ProcessExecutor $process        Process instance, injectable for mocking
     * @param HttpDownloader  $httpDownloader Remote Filesystem, injectable for mocking
     */
    public function __construct(IOInterface $io, Config $config, ?\Composer\Util\ProcessExecutor $process = null, ?\Composer\Util\HttpDownloader $httpDownloader = null)
    {
        $this->io = $io;
        $this->config = $config;
        $this->process = $process ?: new \Composer\Util\ProcessExecutor($io);
        $this->httpDownloader = $httpDownloader ?: Factory::createHttpDownloader($this->io, $config);
    }
    /**
     * Attempts to authorize a GitLab domain via OAuth.
     *
     * @param string $originUrl The host this GitLab instance is located at
     *
     * @return bool true on success
     */
    public function authorizeOAuth(string $originUrl): bool
    {
        // before composer 1.9, origin URLs had no port number in them
        $bcOriginUrl = Preg::replace('{:\d+}', '', $originUrl);
        if (!in_array($originUrl, $this->config->get('gitlab-domains'), \true) && !in_array($bcOriginUrl, $this->config->get('gitlab-domains'), \true)) {
            return \false;
        }
        // if available use token from git config
        if (0 === $this->process->execute(['git', 'config', 'gitlab.accesstoken'], $output)) {
            $this->io->setAuthentication($originUrl, trim($output), 'oauth2');
            return \true;
        }
        // if available use deploy token from git config
        if (0 === $this->process->execute(['git', 'config', 'gitlab.deploytoken.user'], $tokenUser) && 0 === $this->process->execute(['git', 'config', 'gitlab.deploytoken.token'], $tokenPassword)) {
            $this->io->setAuthentication($originUrl, trim($tokenUser), trim($tokenPassword));
            return \true;
        }
        // if available use token from composer config
        $authTokens = $this->config->get('gitlab-token');
        if (isset($authTokens[$originUrl])) {
            $token = $authTokens[$originUrl];
        }
        if (isset($authTokens[$bcOriginUrl])) {
            $token = $authTokens[$bcOriginUrl];
        }
        if (isset($token)) {
            $username = is_array($token) ? $token["username"] : $token;
            $password = is_array($token) ? $token["token"] : 'private-token';
            // Composer expects the GitLab token to be stored as username and 'private-token' or 'gitlab-ci-token' to be stored as password
            // Detect cases where this is reversed and resolve automatically resolve it
            if (in_array($username, ['private-token', 'gitlab-ci-token', 'oauth2'], \true)) {
                $this->io->setAuthentication($originUrl, $password, $username);
            } else {
                $this->io->setAuthentication($originUrl, $username, $password);
            }
            return \true;
        }
        return \false;
    }
    /**
     * Authorizes a GitLab domain interactively via OAuth.
     *
     * @param string $scheme    Scheme used in the origin URL
     * @param string $originUrl The host this GitLab instance is located at
     * @param string $message   The reason this authorization is required
     *
     * @throws \RuntimeException
     * @throws TransportException|\Exception
     *
     * @return bool true on success
     */
    public function authorizeOAuthInteractively(string $scheme, string $originUrl, ?string $message = null): bool
    {
        if ($message) {
            $this->io->writeError($message);
        }
        $localAuthConfig = $this->config->getLocalAuthConfigSource();
        $personalAccessTokenLink = $scheme . '://' . $originUrl . '/-/user_settings/personal_access_tokens';
        $revokeLink = $scheme . '://' . $originUrl . '/-/user_settings/applications';
        $this->io->writeError(sprintf('A token will be created and stored in "%s", your password will never be stored', ($localAuthConfig !== null ? $localAuthConfig->getName() . ' OR ' : '') . $this->config->getAuthConfigSource()->getName()));
        $this->io->writeError('To revoke access to this token you can visit:');
        $this->io->writeError($revokeLink);
        $this->io->writeError('Alternatively you can setup an personal access token on:');
        $this->io->writeError($personalAccessTokenLink);
        $this->io->writeError('and store it under "gitlab-token" see https://getcomposer.org/doc/articles/authentication-for-private-packages.md#gitlab-token for more details.');
        $this->io->writeError('https://getcomposer.org/doc/articles/authentication-for-private-packages.md#gitlab-token');
        $this->io->writeError('for more details.');
        $storeInLocalAuthConfig = \false;
        if ($localAuthConfig !== null) {
            $storeInLocalAuthConfig = $this->io->askConfirmation('A local auth config source was found, do you want to store the token there?', \true);
        }
        $attemptCounter = 0;
        while ($attemptCounter++ < 5) {
            try {
                $response = $this->createToken($scheme, $originUrl);
            } catch (TransportException $e) {
                // 401 is bad credentials,
                // 403 is max login attempts exceeded
                if (in_array($e->getCode(), [403, 401])) {
                    if (401 === $e->getCode()) {
                        $response = json_decode($e->getResponse(), \true);
                        if (isset($response['error']) && $response['error'] === 'invalid_grant') {
                            $this->io->writeError('Bad credentials. If you have two factor authentication enabled you will have to manually create a personal access token');
                        } else {
                            $this->io->writeError('Bad credentials.');
                        }
                    } else {
                        $this->io->writeError('Maximum number of login attempts exceeded. Please try again later.');
                    }
                    $this->io->writeError('You can also manually create a personal access token enabling the "read_api" scope at:');
                    $this->io->writeError($personalAccessTokenLink);
                    $this->io->writeError('Add it using "composer config --global --auth gitlab-token.' . $originUrl . ' <token>"');
                    continue;
                }
                throw $e;
            }
            $this->io->setAuthentication($originUrl, $response['access_token'], 'oauth2');
            $authConfigSource = $storeInLocalAuthConfig && $localAuthConfig !== null ? $localAuthConfig : $this->config->getAuthConfigSource();
            // store value in user config in auth file
            if (isset($response['expires_in'])) {
                $authConfigSource->addConfigSetting('gitlab-oauth.' . $originUrl, ['expires-at' => intval($response['created_at']) + intval($response['expires_in']), 'refresh-token' => $response['refresh_token'], 'token' => $response['access_token']]);
            } else {
                $authConfigSource->addConfigSetting('gitlab-oauth.' . $originUrl, $response['access_token']);
            }
            return \true;
        }
        throw new \RuntimeException('Invalid GitLab credentials 5 times in a row, aborting.');
    }
    /**
     * Authorizes a GitLab domain interactively via OAuth.
     *
     * @param string $scheme    Scheme used in the origin URL
     * @param string $originUrl The host this GitLab instance is located at
     *
     * @throws \RuntimeException
     * @throws TransportException|\Exception
     *
     * @return bool true on success
     */
    public function authorizeOAuthRefresh(string $scheme, string $originUrl): bool
    {
        try {
            $response = $this->refreshToken($scheme, $originUrl);
        } catch (TransportException $e) {
            $this->io->writeError("Couldn't refresh access token: " . $e->getMessage());
            return \false;
        }
        $this->io->setAuthentication($originUrl, $response['access_token'], 'oauth2');
        // store value in user config in auth file
        $this->config->getAuthConfigSource()->addConfigSetting('gitlab-oauth.' . $originUrl, ['expires-at' => intval($response['created_at']) + intval($response['expires_in']), 'refresh-token' => $response['refresh_token'], 'token' => $response['access_token']]);
        return \true;
    }
    /**
     * @return array{access_token: non-empty-string, refresh_token: non-empty-string, token_type: non-empty-string, expires_in?: positive-int, created_at: positive-int}
     *
     * @see https://docs.gitlab.com/ee/api/oauth2.html#resource-owner-password-credentials-flow
     */
    private function createToken(string $scheme, string $originUrl): array
    {
        $username = $this->io->ask('Username: ');
        $password = $this->io->askAndHideAnswer('Password: ');
        $headers = ['Content-Type: application/x-www-form-urlencoded'];
        $apiUrl = $originUrl;
        $data = http_build_query(['username' => $username, 'password' => $password, 'grant_type' => 'password'], '', '&');
        $options = ['retry-auth-failure' => \false, 'http' => ['method' => 'POST', 'header' => $headers, 'content' => $data]];
        $token = $this->httpDownloader->get($scheme . '://' . $apiUrl . '/oauth/token', $options)->decodeJson();
        $this->io->writeError('Token successfully created');
        return $token;
    }
    /**
     * Is the OAuth access token expired?
     *
     * @return bool true on expired token, false if token is fresh or expiration date is not set
     */
    public function isOAuthExpired(string $originUrl): bool
    {
        $authTokens = $this->config->get('gitlab-oauth');
        if (isset($authTokens[$originUrl]['expires-at'])) {
            if ($authTokens[$originUrl]['expires-at'] < time()) {
                return \true;
            }
        }
        return \false;
    }
    /**
     * @return array{access_token: non-empty-string, refresh_token: non-empty-string, token_type: non-empty-string, expires_in: positive-int, created_at: positive-int}
     *
     * @see https://docs.gitlab.com/ee/api/oauth2.html#resource-owner-password-credentials-flow
     */
    private function refreshToken(string $scheme, string $originUrl): array
    {
        $authTokens = $this->config->get('gitlab-oauth');
        if (!isset($authTokens[$originUrl]['refresh-token'])) {
            throw new \RuntimeException('No GitLab refresh token present for ' . $originUrl . '.');
        }
        $refreshToken = $authTokens[$originUrl]['refresh-token'];
        $headers = ['Content-Type: application/x-www-form-urlencoded'];
        $data = http_build_query(['refresh_token' => $refreshToken, 'grant_type' => 'refresh_token'], '', '&');
        $options = ['retry-auth-failure' => \false, 'http' => ['method' => 'POST', 'header' => $headers, 'content' => $data]];
        $token = $this->httpDownloader->get($scheme . '://' . $originUrl . '/oauth/token', $options)->decodeJson();
        $this->io->writeError('GitLab token successfully refreshed', \true, IOInterface::VERY_VERBOSE);
        $this->io->writeError('To revoke access to this token you can visit ' . $scheme . '://' . $originUrl . '/-/user_settings/applications', \true, IOInterface::VERY_VERBOSE);
        return $token;
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer\Util;

use Composer\Factory;
use Composer\IO\IOInterface;
use Composer\Config;
use Composer\Downloader\TransportException;
/**
 * @author Paul Wenke <wenke.paul@gmail.com>
 */
class Bitbucket
{
    /** @var IOInterface */
    private $io;
    /** @var Config */
    private $config;
    /** @var ProcessExecutor */
    private $process;
    /** @var HttpDownloader */
    private $httpDownloader;
    /** @var array{access_token: string, expires_in?: int}|null */
    private $token = null;
    /** @var int|null */
    private $time;
    public const OAUTH2_ACCESS_TOKEN_URL = 'https://bitbucket.org/site/oauth2/access_token';
    /**
     * Constructor.
     *
     * @param IOInterface     $io             The IO instance
     * @param Config          $config         The composer configuration
     * @param ProcessExecutor $process        Process instance, injectable for mocking
     * @param HttpDownloader  $httpDownloader Remote Filesystem, injectable for mocking
     * @param int             $time           Timestamp, injectable for mocking
     */
    public function __construct(IOInterface $io, Config $config, ?\Composer\Util\ProcessExecutor $process = null, ?\Composer\Util\HttpDownloader $httpDownloader = null, ?int $time = null)
    {
        $this->io = $io;
        $this->config = $config;
        $this->process = $process ?: new \Composer\Util\ProcessExecutor($io);
        $this->httpDownloader = $httpDownloader ?: Factory::createHttpDownloader($this->io, $config);
        $this->time = $time;
    }
    public function getToken(): string
    {
        if (!isset($this->token['access_token'])) {
            return '';
        }
        return $this->token['access_token'];
    }
    /**
     * Attempts to authorize a Bitbucket domain via OAuth
     *
     * @param  string $originUrl The host this Bitbucket instance is located at
     * @return bool   true on success
     */
    public function authorizeOAuth(string $originUrl): bool
    {
        if ($originUrl !== 'bitbucket.org') {
            return \false;
        }
        // if available use token from git config
        if (0 === $this->process->execute(['git', 'config', 'bitbucket.accesstoken'], $output)) {
            $this->io->setAuthentication($originUrl, 'x-token-auth', trim($output));
            return \true;
        }
        return \false;
    }
    private function requestAccessToken(): bool
    {
        try {
            $response = $this->httpDownloader->get(self::OAUTH2_ACCESS_TOKEN_URL, ['retry-auth-failure' => \false, 'http' => ['method' => 'POST', 'content' => 'grant_type=client_credentials']]);
            $token = $response->decodeJson();
            if (!isset($token['expires_in']) || !isset($token['access_token'])) {
                throw new \LogicException('Expected a token configured with expires_in and access_token present, got ' . json_encode($token));
            }
            $this->token = $token;
        } catch (TransportException $e) {
            if ($e->getCode() === 400) {
                $this->io->writeError('<error>Invalid OAuth consumer provided.</error>');
                $this->io->writeError('This can have three reasons:');
                $this->io->writeError('1. You are authenticating with a bitbucket username/password combination');
                $this->io->writeError('2. You are using an OAuth consumer, but didn\'t configure a (dummy) callback url');
                $this->io->writeError('3. You are using an OAuth consumer, but didn\'t configure it as private consumer');
                return \false;
            }
            if (in_array($e->getCode(), [403, 401])) {
                $this->io->writeError('<error>Invalid OAuth consumer provided.</error>');
                $this->io->writeError('You can also add it manually later by using "composer config --global --auth bitbucket-oauth.bitbucket.org <consumer-key> <consumer-secret>"');
                return \false;
            }
            throw $e;
        }
        return \true;
    }
    /**
     * Authorizes a Bitbucket domain interactively via OAuth
     *
     * @param  string                        $originUrl The host this Bitbucket instance is located at
     * @param  string                        $message   The reason this authorization is required
     * @throws \RuntimeException
     * @throws TransportException|\Exception
     * @return bool                          true on success
     */
    public function authorizeOAuthInteractively(string $originUrl, ?string $message = null): bool
    {
        if ($message) {
            $this->io->writeError($message);
        }
        $localAuthConfig = $this->config->getLocalAuthConfigSource();
        $url = 'https://support.atlassian.com/bitbucket-cloud/docs/use-oauth-on-bitbucket-cloud/';
        $this->io->writeError('Follow the instructions here:');
        $this->io->writeError($url);
        $this->io->writeError(sprintf('to create a consumer. It will be stored in "%s" for future use by Composer.', ($localAuthConfig !== null ? $localAuthConfig->getName() . ' OR ' : '') . $this->config->getAuthConfigSource()->getName()));
        $this->io->writeError('Ensure you enter a "Callback URL" (http://example.com is fine) or it will not be possible to create an Access Token (this callback url will not be used by composer)');
        $storeInLocalAuthConfig = \false;
        if ($localAuthConfig !== null) {
            $storeInLocalAuthConfig = $this->io->askConfirmation('A local auth config source was found, do you want to store the token there?', \true);
        }
        $consumerKey = trim((string) $this->io->askAndHideAnswer('Consumer Key (hidden): '));
        if (!$consumerKey) {
            $this->io->writeError('<warning>No consumer key given, aborting.</warning>');
            $this->io->writeError('You can also add it manually later by using "composer config --global --auth bitbucket-oauth.bitbucket.org <consumer-key> <consumer-secret>"');
            return \false;
        }
        $consumerSecret = trim((string) $this->io->askAndHideAnswer('Consumer Secret (hidden): '));
        if (!$consumerSecret) {
            $this->io->writeError('<warning>No consumer secret given, aborting.</warning>');
            $this->io->writeError('You can also add it manually later by using "composer config --global --auth bitbucket-oauth.bitbucket.org <consumer-key> <consumer-secret>"');
            return \false;
        }
        $this->io->setAuthentication($originUrl, $consumerKey, $consumerSecret);
        if (!$this->requestAccessToken()) {
            return \false;
        }
        // store value in user config
        $authConfigSource = $storeInLocalAuthConfig && $localAuthConfig !== null ? $localAuthConfig : $this->config->getAuthConfigSource();
        $this->storeInAuthConfig($authConfigSource, $originUrl, $consumerKey, $consumerSecret);
        // Remove conflicting basic auth credentials (if available)
        $this->config->getAuthConfigSource()->removeConfigSetting('http-basic.' . $originUrl);
        $this->io->writeError('<info>Consumer stored successfully.</info>');
        return \true;
    }
    /**
     * Retrieves an access token from Bitbucket.
     */
    public function requestToken(string $originUrl, string $consumerKey, string $consumerSecret): string
    {
        if ($this->token !== null || $this->getTokenFromConfig($originUrl)) {
            return $this->token['access_token'];
        }
        $this->io->setAuthentication($originUrl, $consumerKey, $consumerSecret);
        if (!$this->requestAccessToken()) {
            return '';
        }
        $this->storeInAuthConfig($this->config->getLocalAuthConfigSource() ?? $this->config->getAuthConfigSource(), $originUrl, $consumerKey, $consumerSecret);
        if (!isset($this->token['access_token'])) {
            throw new \LogicException('Failed to initialize token above');
        }
        return $this->token['access_token'];
    }
    /**
     * Store the new/updated credentials to the configuration
     */
    private function storeInAuthConfig(Config\ConfigSourceInterface $authConfigSource, string $originUrl, string $consumerKey, string $consumerSecret): void
    {
        $this->config->getConfigSource()->removeConfigSetting('bitbucket-oauth.' . $originUrl);
        if (null === $this->token || !isset($this->token['expires_in'])) {
            throw new \LogicException('Expected a token configured with expires_in present, got ' . json_encode($this->token));
        }
        $time = null === $this->time ? time() : $this->time;
        $consumer = ["consumer-key" => $consumerKey, "consumer-secret" => $consumerSecret, "access-token" => $this->token['access_token'], "access-token-expiration" => $time + $this->token['expires_in']];
        $this->config->getAuthConfigSource()->addConfigSetting('bitbucket-oauth.' . $originUrl, $consumer);
    }
    /**
     * @phpstan-assert-if-true array{access_token: string} $this->token
     */
    private function getTokenFromConfig(string $originUrl): bool
    {
        $authConfig = $this->config->get('bitbucket-oauth');
        if (!isset($authConfig[$originUrl]['access-token'], $authConfig[$originUrl]['access-token-expiration']) || time() > $authConfig[$originUrl]['access-token-expiration']) {
            return \false;
        }
        $this->token = ['access_token' => $authConfig[$originUrl]['access-token']];
        return \true;
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer\Util;

use Composer\Config;
use Composer\IO\IOInterface;
use Composer\Downloader\TransportException;
use Composer\Pcre\Preg;
use Composer\Util\Http\Response;
use Composer\Util\Http\CurlDownloader;
use Composer\Composer;
use Composer\Package\Version\VersionParser;
use Composer\Semver\Constraint\Constraint;
use Composer\Exception\IrrecoverableDownloadException;
use React\Promise\Promise;
use React\Promise\PromiseInterface;
/**
 * @author Jordi Boggiano <j.boggiano@seld.be>
 * @phpstan-type Request array{url: non-empty-string, options: mixed[], copyTo: string|null}
 * @phpstan-type Job array{id: int, status: int, request: Request, sync: bool, origin: string, resolve?: callable, reject?: callable, curl_id?: int, response?: Response, exception?: \Throwable}
 */
class HttpDownloader
{
    private const STATUS_QUEUED = 1;
    private const STATUS_STARTED = 2;
    private const STATUS_COMPLETED = 3;
    private const STATUS_FAILED = 4;
    private const STATUS_ABORTED = 5;
    /** @var IOInterface */
    private $io;
    /** @var Config */
    private $config;
    /** @var array<Job> */
    private $jobs = [];
    /** @var mixed[] */
    private $options = [];
    /** @var int */
    private $runningJobs = 0;
    /** @var int */
    private $maxJobs = 12;
    /** @var ?CurlDownloader */
    private $curl;
    /** @var ?RemoteFilesystem */
    private $rfs;
    /** @var int */
    private $idGen = 0;
    /** @var bool */
    private $disabled;
    /** @var bool */
    private $allowAsync = \false;
    /**
     * @param IOInterface $io         The IO instance
     * @param Config      $config     The config
     * @param mixed[]     $options    The options
     */
    public function __construct(IOInterface $io, Config $config, array $options = [], bool $disableTls = \false)
    {
        $this->io = $io;
        $this->disabled = (bool) \Composer\Util\Platform::getEnv('COMPOSER_DISABLE_NETWORK');
        // Setup TLS options
        // The cafile option can be set via config.json
        if ($disableTls === \false) {
            $this->options = \Composer\Util\StreamContextFactory::getTlsDefaults($options, $io);
        }
        // handle the other externally set options normally.
        $this->options = array_replace_recursive($this->options, $options);
        $this->config = $config;
        if (self::isCurlEnabled()) {
            $this->curl = new CurlDownloader($io, $config, $options, $disableTls);
        }
        $this->rfs = new \Composer\Util\RemoteFilesystem($io, $config, $options, $disableTls);
        if (is_numeric($maxJobs = \Composer\Util\Platform::getEnv('COMPOSER_MAX_PARALLEL_HTTP'))) {
            $this->maxJobs = max(1, min(50, (int) $maxJobs));
        }
    }
    /**
     * Download a file synchronously
     *
     * @param  string             $url     URL to download
     * @param  mixed[]            $options Stream context options e.g. https://www.php.net/manual/en/context.http.php
     *                                     although not all options are supported when using the default curl downloader
     * @throws TransportException
     * @return Response
     */
    public function get(string $url, array $options = [])
    {
        if ('' === $url) {
            throw new \InvalidArgumentException('$url must not be an empty string');
        }
        [$job, $promise] = $this->addJob(['url' => $url, 'options' => $options, 'copyTo' => null], \true);
        $promise->then(null, static function (\Throwable $e) {
            // suppress error as it is rethrown to the caller by getResponse() a few lines below
        });
        $this->wait($job['id']);
        $response = $this->getResponse($job['id']);
        return $response;
    }
    /**
     * Create an async download operation
     *
     * @param  string             $url     URL to download
     * @param  mixed[]            $options Stream context options e.g. https://www.php.net/manual/en/context.http.php
     *                                     although not all options are supported when using the default curl downloader
     * @throws TransportException
     * @return PromiseInterface
     * @phpstan-return PromiseInterface<Response>
     */
    public function add(string $url, array $options = [])
    {
        if ('' === $url) {
            throw new \InvalidArgumentException('$url must not be an empty string');
        }
        [, $promise] = $this->addJob(['url' => $url, 'options' => $options, 'copyTo' => null]);
        return $promise;
    }
    /**
     * Copy a file synchronously
     *
     * @param  string             $url     URL to download
     * @param  string             $to      Path to copy to
     * @param  mixed[]            $options Stream context options e.g. https://www.php.net/manual/en/context.http.php
     *                                     although not all options are supported when using the default curl downloader
     * @throws TransportException
     * @return Response
     */
    public function copy(string $url, string $to, array $options = [])
    {
        if ('' === $url) {
            throw new \InvalidArgumentException('$url must not be an empty string');
        }
        [$job] = $this->addJob(['url' => $url, 'options' => $options, 'copyTo' => $to], \true);
        $this->wait($job['id']);
        return $this->getResponse($job['id']);
    }
    /**
     * Create an async copy operation
     *
     * @param  string             $url     URL to download
     * @param  string             $to      Path to copy to
     * @param  mixed[]            $options Stream context options e.g. https://www.php.net/manual/en/context.http.php
     *                                     although not all options are supported when using the default curl downloader
     * @throws TransportException
     * @return PromiseInterface
     * @phpstan-return PromiseInterface<Response>
     */
    public function addCopy(string $url, string $to, array $options = [])
    {
        if ('' === $url) {
            throw new \InvalidArgumentException('$url must not be an empty string');
        }
        [, $promise] = $this->addJob(['url' => $url, 'options' => $options, 'copyTo' => $to]);
        return $promise;
    }
    /**
     * Retrieve the options set in the constructor
     *
     * @return mixed[] Options
     */
    public function getOptions()
    {
        return $this->options;
    }
    /**
     * Merges new options
     *
     * @param  mixed[] $options
     * @return void
     */
    public function setOptions(array $options)
    {
        $this->options = array_replace_recursive($this->options, $options);
    }
    /**
     * @phpstan-param Request $request
     * @return array{Job, PromiseInterface}
     * @phpstan-return array{Job, PromiseInterface<Response>}
     */
    private function addJob(array $request, bool $sync = \false): array
    {
        $request['options'] = array_replace_recursive($this->options, $request['options']);
        /** @var Job */
        $job = ['id' => $this->idGen++, 'status' => self::STATUS_QUEUED, 'request' => $request, 'sync' => $sync, 'origin' => \Composer\Util\Url::getOrigin($this->config, $request['url'])];
        if (!$sync && !$this->allowAsync) {
            throw new \LogicException('You must use the HttpDownloader instance which is part of a Composer\Loop instance to be able to run async http requests');
        }
        // capture username/password from URL if there is one
        if (Preg::isMatchStrictGroups('{^https?://([^:/]+):([^@/]+)@([^/]+)}i', $request['url'], $match)) {
            $this->io->setAuthentication($job['origin'], rawurldecode($match[1]), rawurldecode($match[2]));
        }
        $rfs = $this->rfs;
        if ($this->canUseCurl($job)) {
            $resolver = static function ($resolve, $reject) use (&$job): void {
                $job['status'] = \Composer\Util\HttpDownloader::STATUS_QUEUED;
                $job['resolve'] = $resolve;
                $job['reject'] = $reject;
            };
        } else {
            $resolver = static function ($resolve, $reject) use (&$job, $rfs): void {
                // start job
                $url = $job['request']['url'];
                $options = $job['request']['options'];
                $job['status'] = \Composer\Util\HttpDownloader::STATUS_STARTED;
                if ($job['request']['copyTo']) {
                    $rfs->copy($job['origin'], $url, $job['request']['copyTo'], \false, $options);
                    $headers = $rfs->getLastHeaders();
                    $response = new Response($job['request'], $rfs->findStatusCode($headers), $headers, $job['request']['copyTo'] . '~');
                    $resolve($response);
                } else {
                    $body = $rfs->getContents($job['origin'], $url, \false, $options);
                    $headers = $rfs->getLastHeaders();
                    $response = new Response($job['request'], $rfs->findStatusCode($headers), $headers, $body);
                    $resolve($response);
                }
            };
        }
        $curl = $this->curl;
        $canceler = static function () use (&$job, $curl): void {
            if ($job['status'] === \Composer\Util\HttpDownloader::STATUS_QUEUED) {
                $job['status'] = \Composer\Util\HttpDownloader::STATUS_ABORTED;
            }
            if ($job['status'] !== \Composer\Util\HttpDownloader::STATUS_STARTED) {
                return;
            }
            $job['status'] = \Composer\Util\HttpDownloader::STATUS_ABORTED;
            if (isset($job['curl_id'])) {
                $curl->abortRequest($job['curl_id']);
            }
            throw new IrrecoverableDownloadException('Download of ' . \Composer\Util\Url::sanitize($job['request']['url']) . ' canceled');
        };
        $promise = new Promise($resolver, $canceler);
        $promise = $promise->then(function ($response) use (&$job) {
            $job['status'] = \Composer\Util\HttpDownloader::STATUS_COMPLETED;
            $job['response'] = $response;
            $this->markJobDone();
            return $response;
        }, function ($e) use (&$job): void {
            $job['status'] = \Composer\Util\HttpDownloader::STATUS_FAILED;
            $job['exception'] = $e;
            $this->markJobDone();
            throw $e;
        });
        $this->jobs[$job['id']] =& $job;
        if ($this->runningJobs < $this->maxJobs) {
            $this->startJob($job['id']);
        }
        return [$job, $promise];
    }
    private function startJob(int $id): void
    {
        $job =& $this->jobs[$id];
        if ($job['status'] !== self::STATUS_QUEUED) {
            return;
        }
        // start job
        $job['status'] = self::STATUS_STARTED;
        $this->runningJobs++;
        assert(isset($job['resolve']));
        assert(isset($job['reject']));
        $resolve = $job['resolve'];
        $reject = $job['reject'];
        $url = $job['request']['url'];
        $options = $job['request']['options'];
        $origin = $job['origin'];
        if ($this->disabled) {
            if (isset($job['request']['options']['http']['header']) && \false !== stripos(implode('', $job['request']['options']['http']['header']), 'if-modified-since')) {
                $resolve(new Response(['url' => $url], 304, [], ''));
            } else {
                $e = new TransportException('Network disabled, request canceled: ' . \Composer\Util\Url::sanitize($url), 499);
                $e->setStatusCode(499);
                $reject($e);
            }
            return;
        }
        try {
            if ($job['request']['copyTo']) {
                $job['curl_id'] = $this->curl->download($resolve, $reject, $origin, $url, $options, $job['request']['copyTo']);
            } else {
                $job['curl_id'] = $this->curl->download($resolve, $reject, $origin, $url, $options);
            }
        } catch (\Exception $exception) {
            $reject($exception);
        }
    }
    private function markJobDone(): void
    {
        $this->runningJobs--;
    }
    /**
     * Wait for current async download jobs to complete
     *
     * @param int|null $index For internal use only, the job id
     *
     * @return void
     */
    public function wait(?int $index = null)
    {
        do {
            $jobCount = $this->countActiveJobs($index);
        } while ($jobCount);
    }
    /**
     * @internal
     */
    public function enableAsync(): void
    {
        $this->allowAsync = \true;
    }
    /**
     * @internal
     *
     * @param  int|null $index For internal use only, the job id
     * @return int      number of active (queued or started) jobs
     */
    public function countActiveJobs(?int $index = null): int
    {
        if ($this->runningJobs < $this->maxJobs) {
            foreach ($this->jobs as $job) {
                if ($job['status'] === self::STATUS_QUEUED && $this->runningJobs < $this->maxJobs) {
                    $this->startJob($job['id']);
                }
            }
        }
        if ($this->curl) {
            $this->curl->tick();
        }
        if (null !== $index) {
            return $this->jobs[$index]['status'] < self::STATUS_COMPLETED ? 1 : 0;
        }
        $active = 0;
        foreach ($this->jobs as $job) {
            if ($job['status'] < self::STATUS_COMPLETED) {
                $active++;
            } elseif (!$job['sync']) {
                unset($this->jobs[$job['id']]);
            }
        }
        return $active;
    }
    /**
     * @param  int $index Job id
     */
    private function getResponse(int $index): Response
    {
        if (!isset($this->jobs[$index])) {
            throw new \LogicException('Invalid request id');
        }
        if ($this->jobs[$index]['status'] === self::STATUS_FAILED) {
            assert(isset($this->jobs[$index]['exception']));
            throw $this->jobs[$index]['exception'];
        }
        if (!isset($this->jobs[$index]['response'])) {
            throw new \LogicException('Response not available yet, call wait() first');
        }
        $resp = $this->jobs[$index]['response'];
        unset($this->jobs[$index]);
        return $resp;
    }
    /**
     * @internal
     *
     * @param  array{warning?: string, info?: string, warning-versions?: string, info-versions?: string, warnings?: array<array{versions: string, message: string}>, infos?: array<array{versions: string, message: string}>} $data
     */
    public static function outputWarnings(IOInterface $io, string $url, $data): void
    {
        $cleanMessage = static function ($msg) use ($io) {
            if (!$io->isDecorated()) {
                $msg = Preg::replace('{' . chr(27) . '\[[;\d]*m}u', '', $msg);
            }
            return $msg;
        };
        // legacy warning/info keys
        foreach (['warning', 'info'] as $type) {
            if (empty($data[$type])) {
                continue;
            }
            if (!empty($data[$type . '-versions'])) {
                $versionParser = new VersionParser();
                $constraint = $versionParser->parseConstraints($data[$type . '-versions']);
                $composer = new Constraint('==', $versionParser->normalize(Composer::getVersion()));
                if (!$constraint->matches($composer)) {
                    continue;
                }
            }
            $io->writeError('<' . $type . '>' . ucfirst($type) . ' from ' . \Composer\Util\Url::sanitize($url) . ': ' . $cleanMessage($data[$type]) . '</' . $type . '>');
        }
        // modern Composer 2.2+ format with support for multiple warning/info messages
        foreach (['warnings', 'infos'] as $key) {
            if (empty($data[$key])) {
                continue;
            }
            $versionParser = new VersionParser();
            foreach ($data[$key] as $spec) {
                $type = substr($key, 0, -1);
                $constraint = $versionParser->parseConstraints($spec['versions']);
                $composer = new Constraint('==', $versionParser->normalize(Composer::getVersion()));
                if (!$constraint->matches($composer)) {
                    continue;
                }
                $io->writeError('<' . $type . '>' . ucfirst($type) . ' from ' . \Composer\Util\Url::sanitize($url) . ': ' . $cleanMessage($spec['message']) . '</' . $type . '>');
            }
        }
    }
    /**
     * @internal
     *
     * @return ?string[]
     */
    public static function getExceptionHints(\Throwable $e): ?array
    {
        if (!$e instanceof TransportException) {
            return null;
        }
        if (\false !== strpos($e->getMessage(), 'Resolving timed out') || \false !== strpos($e->getMessage(), 'Could not resolve host')) {
            \Composer\Util\Silencer::suppress();
            $testConnectivity = file_get_contents('https://8.8.8.8', \false, stream_context_create(['ssl' => ['verify_peer' => \false], 'http' => ['follow_location' => \false, 'ignore_errors' => \true]]));
            \Composer\Util\Silencer::restore();
            if (\false !== $testConnectivity) {
                return ['<error>The following exception probably indicates you have misconfigured DNS resolver(s)</error>'];
            }
            return ['<error>The following exception probably indicates you are offline or have misconfigured DNS resolver(s)</error>'];
        }
        return null;
    }
    /**
     * @param  Job  $job
     */
    private function canUseCurl(array $job): bool
    {
        if (!$this->curl) {
            return \false;
        }
        if (!Preg::isMatch('{^https?://}i', $job['request']['url'])) {
            return \false;
        }
        if (!empty($job['request']['options']['ssl']['allow_self_signed'])) {
            return \false;
        }
        return \true;
    }
    /**
     * @internal
     */
    public static function isCurlEnabled(): bool
    {
        return \extension_loaded('curl') && \function_exists('curl_multi_exec') && \function_exists('curl_multi_init');
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer\Util;

use Composer\XdebugHandler\XdebugHandler;
/**
 * Provides ini file location functions that work with and without a restart.
 * When the process has restarted it uses a tmp ini and stores the original
 * ini locations in an environment variable.
 *
 * @author John Stevenson <john-stevenson@blueyonder.co.uk>
 */
class IniHelper
{
    /**
     * Returns an array of php.ini locations with at least one entry
     *
     * The equivalent of calling php_ini_loaded_file then php_ini_scanned_files.
     * The loaded ini location is the first entry and may be empty.
     *
     * @return string[]
     */
    public static function getAll(): array
    {
        return XdebugHandler::getAllIniFiles();
    }
    /**
     * Describes the location of the loaded php.ini file(s)
     */
    public static function getMessage(): string
    {
        $paths = self::getAll();
        if (empty($paths[0])) {
            array_shift($paths);
        }
        $ini = array_shift($paths);
        if (empty($ini)) {
            return 'A php.ini file does not exist. You will have to create one.';
        }
        if (!empty($paths)) {
            return 'Your command-line PHP is using multiple ini files. Run `php --ini` to show them.';
        }
        return 'The php.ini used by your command-line PHP is: ' . $ini;
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer\Util;

use Composer\Pcre\Preg;
/**
 * Platform helper for uniform platform-specific tests.
 *
 * @author Niels Keurentjes <niels.keurentjes@omines.com>
 */
class Platform
{
    /** @var ?bool */
    private static $isVirtualBoxGuest = null;
    /** @var ?bool */
    private static $isWindowsSubsystemForLinux = null;
    /** @var ?bool */
    private static $isDocker = null;
    /**
     * getcwd() equivalent which always returns a string
     *
     * @throws \RuntimeException
     */
    public static function getCwd(bool $allowEmpty = \false): string
    {
        $cwd = getcwd();
        // fallback to realpath('') just in case this works but odds are it would break as well if we are in a case where getcwd fails
        if (\false === $cwd) {
            $cwd = realpath('');
        }
        // crappy state, assume '' and hopefully relative paths allow things to continue
        if (\false === $cwd) {
            if ($allowEmpty) {
                return '';
            }
            throw new \RuntimeException('Could not determine the current working directory');
        }
        return $cwd;
    }
    /**
     * Infallible realpath version that falls back on the given $path if realpath is not working
     */
    public static function realpath(string $path): string
    {
        $realPath = realpath($path);
        if ($realPath === \false) {
            return $path;
        }
        return $realPath;
    }
    /**
     * getenv() equivalent but reads from the runtime global variables first
     *
     * @param non-empty-string $name
     *
     * @return string|false
     */
    public static function getEnv(string $name)
    {
        if (array_key_exists($name, $_SERVER)) {
            return (string) $_SERVER[$name];
        }
        if (array_key_exists($name, $_ENV)) {
            return (string) $_ENV[$name];
        }
        return getenv($name);
    }
    /**
     * putenv() equivalent but updates the runtime global variables too
     */
    public static function putEnv(string $name, string $value): void
    {
        putenv($name . '=' . $value);
        $_SERVER[$name] = $_ENV[$name] = $value;
    }
    /**
     * putenv('X') equivalent but updates the runtime global variables too
     */
    public static function clearEnv(string $name): void
    {
        putenv($name);
        unset($_SERVER[$name], $_ENV[$name]);
    }
    /**
     * Parses tildes and environment variables in paths.
     */
    public static function expandPath(string $path): string
    {
        if (Preg::isMatch('#^~[\/]#', $path)) {
            return self::getUserDirectory() . substr($path, 1);
        }
        return Preg::replaceCallback('#^(\$|(?P<percent>%))(?P<var>\w++)(?(percent)%)(?P<path>.*)#', static function ($matches): string {
            // Treat HOME as an alias for USERPROFILE on Windows for legacy reasons
            if (\Composer\Util\Platform::isWindows() && $matches['var'] === 'HOME') {
                if ((bool) \Composer\Util\Platform::getEnv('HOME')) {
                    return \Composer\Util\Platform::getEnv('HOME') . $matches['path'];
                }
                return \Composer\Util\Platform::getEnv('USERPROFILE') . $matches['path'];
            }
            return \Composer\Util\Platform::getEnv($matches['var']) . $matches['path'];
        }, $path);
    }
    /**
     * @throws \RuntimeException If the user home could not reliably be determined
     * @return string            The formal user home as detected from environment parameters
     */
    public static function getUserDirectory(): string
    {
        if (\false !== $home = self::getEnv('HOME')) {
            return $home;
        }
        if (self::isWindows() && \false !== $home = self::getEnv('USERPROFILE')) {
            return $home;
        }
        if (\function_exists('posix_getuid') && \function_exists('posix_getpwuid')) {
            $info = posix_getpwuid(posix_getuid());
            if (is_array($info)) {
                return $info['dir'];
            }
        }
        throw new \RuntimeException('Could not determine user directory');
    }
    /**
     * @return bool Whether the host machine is running on the Windows Subsystem for Linux (WSL)
     */
    public static function isWindowsSubsystemForLinux(): bool
    {
        if (null === self::$isWindowsSubsystemForLinux) {
            self::$isWindowsSubsystemForLinux = \false;
            // while WSL will be hosted within windows, WSL itself cannot be windows based itself.
            if (self::isWindows()) {
                return self::$isWindowsSubsystemForLinux = \false;
            }
            if (!(bool) ini_get('open_basedir') && is_readable('/proc/version') && \false !== stripos((string) \Composer\Util\Silencer::call('file_get_contents', '/proc/version'), 'microsoft') && !self::isDocker()) {
                return self::$isWindowsSubsystemForLinux = \true;
            }
        }
        return self::$isWindowsSubsystemForLinux;
    }
    /**
     * @return bool Whether the host machine is running a Windows OS
     */
    public static function isWindows(): bool
    {
        return \defined('PHP_WINDOWS_VERSION_BUILD');
    }
    public static function isDocker(): bool
    {
        if (null !== self::$isDocker) {
            return self::$isDocker;
        }
        // cannot check so assume no
        if ((bool) ini_get('open_basedir')) {
            return self::$isDocker = \false;
        }
        // .dockerenv and .containerenv are present in some cases but not reliably
        if (file_exists('/.dockerenv') || file_exists('/run/.containerenv') || file_exists('/var/run/.containerenv')) {
            return self::$isDocker = \true;
        }
        // see https://www.baeldung.com/linux/is-process-running-inside-container
        $cgroups = [
            '/proc/self/mountinfo',
            // cgroup v2
            '/proc/1/cgroup',
        ];
        foreach ($cgroups as $cgroup) {
            if (!is_readable($cgroup)) {
                continue;
            }
            // suppress errors as some environments have these files as readable but system restrictions prevent the read from succeeding
            // see https://github.com/composer/composer/issues/12095
            try {
                $data = @file_get_contents($cgroup);
            } catch (\Throwable $e) {
                break;
            }
            if (!is_string($data)) {
                continue;
            }
            // detect default mount points created by Docker/containerd
            if (str_contains($data, '/var/lib/docker/') || str_contains($data, '/io.containerd.snapshotter')) {
                return self::$isDocker = \true;
            }
        }
        return self::$isDocker = \false;
    }
    /**
     * @return int    return a guaranteed binary length of the string, regardless of silly mbstring configs
     */
    public static function strlen(string $str): int
    {
        static $useMbString = null;
        if (null === $useMbString) {
            $useMbString = \function_exists('mb_strlen') && (bool) ini_get('mbstring.func_overload');
        }
        if ($useMbString) {
            return mb_strlen($str, '8bit');
        }
        return \strlen($str);
    }
    /**
     * @param  ?resource $fd Open file descriptor or null to default to STDOUT
     */
    public static function isTty($fd = null): bool
    {
        if ($fd === null) {
            $fd = defined('STDOUT') ? \STDOUT : fopen('php://stdout', 'w');
            if ($fd === \false) {
                return \false;
            }
        }
        // detect msysgit/mingw and assume this is a tty because detection
        // does not work correctly, see https://github.com/composer/composer/issues/9690
        if (in_array(strtoupper((string) self::getEnv('MSYSTEM')), ['MINGW32', 'MINGW64'], \true)) {
            return \true;
        }
        // modern cross-platform function, includes the fstat
        // fallback so if it is present we trust it
        if (function_exists('stream_isatty')) {
            return stream_isatty($fd);
        }
        // only trusting this if it is positive, otherwise prefer fstat fallback
        if (function_exists('posix_isatty') && posix_isatty($fd)) {
            return \true;
        }
        $stat = @fstat($fd);
        if ($stat === \false) {
            return \false;
        }
        // Check if formatted mode is S_IFCHR
        return 020000 === ($stat['mode'] & 0170000);
    }
    /**
     * @return bool Whether the current command is for bash completion
     */
    public static function isInputCompletionProcess(): bool
    {
        return '_complete' === ($_SERVER['argv'][1] ?? null);
    }
    public static function workaroundFilesystemIssues(): void
    {
        if (self::isVirtualBoxGuest()) {
            usleep(200000);
        }
    }
    /**
     * Attempts detection of VirtualBox guest VMs
     *
     * This works based on the process' user being "vagrant", the COMPOSER_RUNTIME_ENV env var being set to "virtualbox", or lsmod showing the virtualbox guest additions are loaded
     */
    private static function isVirtualBoxGuest(): bool
    {
        if (null === self::$isVirtualBoxGuest) {
            self::$isVirtualBoxGuest = \false;
            if (self::isWindows()) {
                return self::$isVirtualBoxGuest;
            }
            if (function_exists('posix_getpwuid') && function_exists('posix_geteuid')) {
                $processUser = posix_getpwuid(posix_geteuid());
                if (is_array($processUser) && $processUser['name'] === 'vagrant') {
                    return self::$isVirtualBoxGuest = \true;
                }
            }
            if (self::getEnv('COMPOSER_RUNTIME_ENV') === 'virtualbox') {
                return self::$isVirtualBoxGuest = \true;
            }
            if (defined('PHP_OS_FAMILY') && \PHP_OS_FAMILY === 'Linux') {
                $process = new \Composer\Util\ProcessExecutor();
                try {
                    if (0 === $process->execute(['lsmod'], $output) && str_contains($output, 'vboxguest')) {
                        return self::$isVirtualBoxGuest = \true;
                    }
                } catch (\Exception $e) {
                    // noop
                }
            }
        }
        return self::$isVirtualBoxGuest;
    }
    /**
     * @return 'NUL'|'/dev/null'
     */
    public static function getDevNull(): string
    {
        if (self::isWindows()) {
            return 'NUL';
        }
        return '/dev/null';
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer\Util;

use Composer\Composer;
use Composer\CaBundle\CaBundle;
use Composer\Downloader\TransportException;
use Composer\Repository\PlatformRepository;
use Composer\Util\Http\ProxyManager;
use _ContaoManager\Psr\Log\LoggerInterface;
/**
 * Allows the creation of a basic context supporting http proxy
 *
 * @author Jordan Alliot <jordan.alliot@gmail.com>
 * @author Markus Tacker <m@coderbyheart.de>
 */
final class StreamContextFactory
{
    /**
     * Creates a context supporting HTTP proxies
     *
     * @param non-empty-string $url URL the context is to be used for
     * @phpstan-param array{http?: array{follow_location?: int, max_redirects?: int, header?: string|array<string>}} $defaultOptions
     * @param  mixed[]           $defaultOptions Options to merge with the default
     * @param  mixed[]           $defaultParams  Parameters to specify on the context
     * @throws \RuntimeException if https proxy required and OpenSSL uninstalled
     * @return resource          Default context
     */
    public static function getContext(string $url, array $defaultOptions = [], array $defaultParams = [])
    {
        $options = ['http' => [
            // specify defaults again to try and work better with curlwrappers enabled
            'follow_location' => 1,
            'max_redirects' => 20,
        ]];
        $options = array_replace_recursive($options, self::initOptions($url, $defaultOptions));
        unset($defaultOptions['http']['header']);
        $options = array_replace_recursive($options, $defaultOptions);
        if (isset($options['http']['header'])) {
            $options['http']['header'] = self::fixHttpHeaderField($options['http']['header']);
        }
        return stream_context_create($options, $defaultParams);
    }
    /**
     * @param non-empty-string $url
     * @param mixed[] $options
     * @param bool    $forCurl When true, will not add proxy values as these are handled separately
     * @phpstan-return array{http: array{header: string[], proxy?: string, request_fulluri: bool}, ssl?: mixed[]}
     * @return array formatted as a stream context array
     */
    public static function initOptions(string $url, array $options, bool $forCurl = \false): array
    {
        // Make sure the headers are in an array form
        if (!isset($options['http']['header'])) {
            $options['http']['header'] = [];
        }
        if (is_string($options['http']['header'])) {
            $options['http']['header'] = explode("\r\n", $options['http']['header']);
        }
        // Add stream proxy options if there is a proxy
        if (!$forCurl) {
            $proxy = ProxyManager::getInstance()->getProxyForRequest($url);
            $proxyOptions = $proxy->getContextOptions();
            if ($proxyOptions !== null) {
                $isHttpsRequest = 0 === strpos($url, 'https://');
                if ($proxy->isSecure()) {
                    if (!extension_loaded('openssl')) {
                        throw new TransportException('You must enable the openssl extension to use a secure proxy.');
                    }
                    if ($isHttpsRequest) {
                        throw new TransportException('You must enable the curl extension to make https requests through a secure proxy.');
                    }
                } elseif ($isHttpsRequest && !extension_loaded('openssl')) {
                    throw new TransportException('You must enable the openssl extension to make https requests through a proxy.');
                }
                // Header will be a Proxy-Authorization string or not set
                if (isset($proxyOptions['http']['header'])) {
                    $options['http']['header'][] = $proxyOptions['http']['header'];
                    unset($proxyOptions['http']['header']);
                }
                $options = array_replace_recursive($options, $proxyOptions);
            }
        }
        if (defined('HHVM_VERSION')) {
            $phpVersion = 'HHVM ' . HHVM_VERSION;
        } else {
            $phpVersion = 'PHP ' . \PHP_MAJOR_VERSION . '.' . \PHP_MINOR_VERSION . '.' . \PHP_RELEASE_VERSION;
        }
        if ($forCurl) {
            $curl = curl_version();
            $httpVersion = 'cURL ' . $curl['version'];
        } else {
            $httpVersion = 'streams';
        }
        if (!isset($options['http']['header']) || \false === stripos(implode('', $options['http']['header']), 'user-agent')) {
            $platformPhpVersion = PlatformRepository::getPlatformPhpVersion();
            $options['http']['header'][] = sprintf('User-Agent: Composer/%s (%s; %s; %s; %s%s%s)', Composer::getVersion(), function_exists('php_uname') ? php_uname('s') : 'Unknown', function_exists('php_uname') ? php_uname('r') : 'Unknown', $phpVersion, $httpVersion, $platformPhpVersion ? '; Platform-PHP ' . $platformPhpVersion : '', \Composer\Util\Platform::getEnv('CI') ? '; CI' : '');
        }
        return $options;
    }
    /**
     * @param mixed[] $options
     *
     * @return mixed[]
     */
    public static function getTlsDefaults(array $options, ?LoggerInterface $logger = null): array
    {
        $ciphers = implode(':', ['ECDHE-RSA-AES128-GCM-SHA256', 'ECDHE-ECDSA-AES128-GCM-SHA256', 'ECDHE-RSA-AES256-GCM-SHA384', 'ECDHE-ECDSA-AES256-GCM-SHA384', 'DHE-RSA-AES128-GCM-SHA256', 'DHE-DSS-AES128-GCM-SHA256', 'kEDH+AESGCM', 'ECDHE-RSA-AES128-SHA256', 'ECDHE-ECDSA-AES128-SHA256', 'ECDHE-RSA-AES128-SHA', 'ECDHE-ECDSA-AES128-SHA', 'ECDHE-RSA-AES256-SHA384', 'ECDHE-ECDSA-AES256-SHA384', 'ECDHE-RSA-AES256-SHA', 'ECDHE-ECDSA-AES256-SHA', 'DHE-RSA-AES128-SHA256', 'DHE-RSA-AES128-SHA', 'DHE-DSS-AES128-SHA256', 'DHE-RSA-AES256-SHA256', 'DHE-DSS-AES256-SHA', 'DHE-RSA-AES256-SHA', 'AES128-GCM-SHA256', 'AES256-GCM-SHA384', 'AES128-SHA256', 'AES256-SHA256', 'AES128-SHA', 'AES256-SHA', 'AES', 'CAMELLIA', '!aNULL', '!eNULL', '!EXPORT', '!DES', '!3DES', '!RC4', '!MD5', '!PSK', '!aECDH', '!EDH-DSS-DES-CBC3-SHA', '!EDH-RSA-DES-CBC3-SHA', '!KRB5-DES-CBC3-SHA']);
        /**
         * CN_match and SNI_server_name are only known once a URL is passed.
         * They will be set in the getOptionsForUrl() method which receives a URL.
         *
         * cafile or capath can be overridden by passing in those options to constructor.
         */
        $defaults = ['ssl' => ['ciphers' => $ciphers, 'verify_peer' => \true, 'verify_depth' => 7, 'SNI_enabled' => \true, 'capture_peer_cert' => \true]];
        if (isset($options['ssl'])) {
            $defaults['ssl'] = array_replace_recursive($defaults['ssl'], $options['ssl']);
        }
        /**
         * Attempt to find a local cafile or throw an exception if none pre-set
         * The user may go download one if this occurs.
         */
        if (!isset($defaults['ssl']['cafile']) && !isset($defaults['ssl']['capath'])) {
            $result = CaBundle::getSystemCaRootBundlePath($logger);
            if (is_dir($result)) {
                $defaults['ssl']['capath'] = $result;
            } else {
                $defaults['ssl']['cafile'] = $result;
            }
        }
        if (isset($defaults['ssl']['cafile']) && (!\Composer\Util\Filesystem::isReadable($defaults['ssl']['cafile']) || !CaBundle::validateCaFile($defaults['ssl']['cafile'], $logger))) {
            throw new TransportException('The configured cafile was not valid or could not be read.');
        }
        if (isset($defaults['ssl']['capath']) && (!is_dir($defaults['ssl']['capath']) || !\Composer\Util\Filesystem::isReadable($defaults['ssl']['capath']))) {
            throw new TransportException('The configured capath was not valid or could not be read.');
        }
        /**
         * Disable TLS compression to prevent CRIME attacks where supported.
         */
        $defaults['ssl']['disable_compression'] = \true;
        return $defaults;
    }
    /**
     * A bug in PHP prevents the headers from correctly being sent when a content-type header is present and
     * NOT at the end of the array
     *
     * This method fixes the array by moving the content-type header to the end
     *
     * @link https://bugs.php.net/bug.php?id=61548
     * @param  string|string[] $header
     * @return string[]
     */
    private static function fixHttpHeaderField($header): array
    {
        if (!is_array($header)) {
            $header = explode("\r\n", $header);
        }
        uasort($header, static function ($el): int {
            return stripos($el, 'content-type') === 0 ? 1 : -1;
        });
        return $header;
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer\Util;

use Composer\CaBundle\CaBundle;
use Composer\Pcre\Preg;
/**
 * @author Chris Smith <chris@cs278.org>
 * @deprecated Use composer/ca-bundle and composer/composer 2.2 if you still need PHP 5 compatibility, this class will be removed in Composer 3.0
 */
final class TlsHelper
{
    /**
     * Match hostname against a certificate.
     *
     * @param mixed  $certificate X.509 certificate
     * @param string $hostname    Hostname in the URL
     * @param string $cn          Set to the common name of the certificate iff match found
     */
    public static function checkCertificateHost($certificate, string $hostname, ?string &$cn = null): bool
    {
        $names = self::getCertificateNames($certificate);
        if (empty($names)) {
            return \false;
        }
        $combinedNames = array_merge($names['san'], [$names['cn']]);
        $hostname = strtolower($hostname);
        foreach ($combinedNames as $certName) {
            $matcher = self::certNameMatcher($certName);
            if ($matcher && $matcher($hostname)) {
                $cn = $names['cn'];
                return \true;
            }
        }
        return \false;
    }
    /**
     * Extract DNS names out of an X.509 certificate.
     *
     * @param mixed $certificate X.509 certificate
     *
     * @return array{cn: string, san: string[]}|null
     */
    public static function getCertificateNames($certificate): ?array
    {
        if (is_array($certificate)) {
            $info = $certificate;
        } elseif (CaBundle::isOpensslParseSafe()) {
            $info = openssl_x509_parse($certificate, \false);
        }
        if (!isset($info['subject']['commonName'])) {
            return null;
        }
        $commonName = strtolower($info['subject']['commonName']);
        $subjectAltNames = [];
        if (isset($info['extensions']['subjectAltName'])) {
            $subjectAltNames = Preg::split('{\s*,\s*}', $info['extensions']['subjectAltName']);
            $subjectAltNames = array_filter(array_map(static function ($name): ?string {
                if (0 === strpos($name, 'DNS:')) {
                    return strtolower(ltrim(substr($name, 4)));
                }
                return null;
            }, $subjectAltNames), static function (?string $san) {
                return $san !== null;
            });
            $subjectAltNames = array_values($subjectAltNames);
        }
        return ['cn' => $commonName, 'san' => $subjectAltNames];
    }
    /**
     * Get the certificate pin.
     *
     * By Kevin McArthur of StormTide Digital Studios Inc.
     * @KevinSMcArthur / https://github.com/StormTide
     *
     * See https://tools.ietf.org/html/draft-ietf-websec-key-pinning-02
     *
     * This method was adapted from Sslurp.
     * https://github.com/EvanDotPro/Sslurp
     *
     * (c) Evan Coury <me@evancoury.com>
     *
     * For the full copyright and license information, please see below:
     *
     * Copyright (c) 2013, Evan Coury
     * All rights reserved.
     *
     * Redistribution and use in source and binary forms, with or without modification,
     * are permitted provided that the following conditions are met:
     *
     *     * Redistributions of source code must retain the above copyright notice,
     *       this list of conditions and the following disclaimer.
     *
     *     * Redistributions in binary form must reproduce the above copyright notice,
     *       this list of conditions and the following disclaimer in the documentation
     *       and/or other materials provided with the distribution.
     *
     * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
     * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
     * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
     * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
     * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
     * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
     * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
     * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
     * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     */
    public static function getCertificateFingerprint(string $certificate): string
    {
        $pubkey = openssl_get_publickey($certificate);
        if ($pubkey === \false) {
            throw new \RuntimeException('Failed to retrieve the public key from certificate');
        }
        $pubkeydetails = openssl_pkey_get_details($pubkey);
        $pubkeypem = $pubkeydetails['key'];
        //Convert PEM to DER before SHA1'ing
        $start = '-----BEGIN PUBLIC KEY-----';
        $end = '-----END PUBLIC KEY-----';
        $pemtrim = substr($pubkeypem, strpos($pubkeypem, $start) + strlen($start), (strlen($pubkeypem) - strpos($pubkeypem, $end)) * -1);
        $der = base64_decode($pemtrim);
        return hash('sha1', $der);
    }
    /**
     * Test if it is safe to use the PHP function openssl_x509_parse().
     *
     * This checks if OpenSSL extensions is vulnerable to remote code execution
     * via the exploit documented as CVE-2013-6420.
     */
    public static function isOpensslParseSafe(): bool
    {
        return CaBundle::isOpensslParseSafe();
    }
    /**
     * Convert certificate name into matching function.
     *
     * @param string $certName CN/SAN
     */
    private static function certNameMatcher(string $certName): ?callable
    {
        $wildcards = substr_count($certName, '*');
        if (0 === $wildcards) {
            // Literal match.
            return static function ($hostname) use ($certName): bool {
                return $hostname === $certName;
            };
        }
        if (1 === $wildcards) {
            $components = explode('.', $certName);
            if (3 > count($components)) {
                // Must have 3+ components
                return null;
            }
            $firstComponent = $components[0];
            // Wildcard must be the last character.
            if ('*' !== $firstComponent[strlen($firstComponent) - 1]) {
                return null;
            }
            $wildcardRegex = preg_quote($certName);
            $wildcardRegex = str_replace('\*', '[a-z0-9-]+', $wildcardRegex);
            $wildcardRegex = "{^{$wildcardRegex}\$}";
            return static function ($hostname) use ($wildcardRegex): bool {
                return Preg::isMatch($wildcardRegex, $hostname);
            };
        }
        return null;
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer\Util;

use Composer\Config;
use Composer\Pcre\Preg;
/**
 * @author Jordi Boggiano <j.boggiano@seld.be>
 */
class Url
{
    /**
     * @param non-empty-string $url
     * @return non-empty-string the updated URL
     */
    public static function updateDistReference(Config $config, string $url, string $ref): string
    {
        $host = parse_url($url, \PHP_URL_HOST);
        if ($host === 'api.github.com' || $host === 'github.com' || $host === 'www.github.com') {
            if (Preg::isMatch('{^https?://(?:www\.)?github\.com/([^/]+)/([^/]+)/(zip|tar)ball/(.+)$}i', $url, $match)) {
                // update legacy github archives to API calls with the proper reference
                $url = 'https://api.github.com/repos/' . $match[1] . '/' . $match[2] . '/' . $match[3] . 'ball/' . $ref;
            } elseif (Preg::isMatch('{^https?://(?:www\.)?github\.com/([^/]+)/([^/]+)/archive/.+\.(zip|tar)(?:\.gz)?$}i', $url, $match)) {
                // update current github web archives to API calls with the proper reference
                $url = 'https://api.github.com/repos/' . $match[1] . '/' . $match[2] . '/' . $match[3] . 'ball/' . $ref;
            } elseif (Preg::isMatch('{^https?://api\.github\.com/repos/([^/]+)/([^/]+)/(zip|tar)ball(?:/.+)?$}i', $url, $match)) {
                // update api archives to the proper reference
                $url = 'https://api.github.com/repos/' . $match[1] . '/' . $match[2] . '/' . $match[3] . 'ball/' . $ref;
            }
        } elseif ($host === 'bitbucket.org' || $host === 'www.bitbucket.org') {
            if (Preg::isMatch('{^https?://(?:www\.)?bitbucket\.org/([^/]+)/([^/]+)/get/(.+)\.(zip|tar\.gz|tar\.bz2)$}i', $url, $match)) {
                // update Bitbucket archives to the proper reference
                $url = 'https://bitbucket.org/' . $match[1] . '/' . $match[2] . '/get/' . $ref . '.' . $match[4];
            }
        } elseif ($host === 'gitlab.com' || $host === 'www.gitlab.com') {
            if (Preg::isMatch('{^https?://(?:www\.)?gitlab\.com/api/v[34]/projects/([^/]+)/repository/archive\.(zip|tar\.gz|tar\.bz2|tar)\?sha=.+$}i', $url, $match)) {
                // update Gitlab archives to the proper reference
                $url = 'https://gitlab.com/api/v4/projects/' . $match[1] . '/repository/archive.' . $match[2] . '?sha=' . $ref;
            }
        } elseif (in_array($host, $config->get('github-domains'), \true)) {
            $url = Preg::replace('{(/repos/[^/]+/[^/]+/(zip|tar)ball)(?:/.+)?$}i', '$1/' . $ref, $url);
        } elseif (in_array($host, $config->get('gitlab-domains'), \true)) {
            $url = Preg::replace('{(/api/v[34]/projects/[^/]+/repository/archive\.(?:zip|tar\.gz|tar\.bz2|tar)\?sha=).+$}i', '${1}' . $ref, $url);
        }
        assert($url !== '');
        return $url;
    }
    /**
     * @param non-empty-string $url
     * @return non-empty-string
     */
    public static function getOrigin(Config $config, string $url): string
    {
        if (0 === strpos($url, 'file://')) {
            return $url;
        }
        $origin = (string) parse_url($url, \PHP_URL_HOST);
        if ($port = parse_url($url, \PHP_URL_PORT)) {
            $origin .= ':' . $port;
        }
        if (str_ends_with($origin, '.github.com') && $origin !== 'codeload.github.com') {
            return 'github.com';
        }
        if ($origin === 'repo.packagist.org') {
            return 'packagist.org';
        }
        if ($origin === '') {
            $origin = $url;
        }
        // Gitlab can be installed in a non-root context (i.e. gitlab.com/foo). When downloading archives the originUrl
        // is the host without the path, so we look for the registered gitlab-domains matching the host here
        if (\false === strpos($origin, '/') && !in_array($origin, $config->get('gitlab-domains'), \true)) {
            foreach ($config->get('gitlab-domains') as $gitlabDomain) {
                if ($gitlabDomain !== '' && str_starts_with($gitlabDomain, $origin)) {
                    return $gitlabDomain;
                }
            }
        }
        return $origin;
    }
    public static function sanitize(string $url): string
    {
        // GitHub repository rename result in redirect locations containing the access_token as GET parameter
        // e.g. https://api.github.com/repositories/9999999999?access_token=github_token
        $url = Preg::replace('{([&?]access_token=)[^&]+}', '$1***', $url);
        $url = Preg::replaceCallback('{^(?P<prefix>[a-z0-9]+://)?(?P<user>[^:/\s@]+):(?P<password>[^@\s/]+)@}i', static function ($m): string {
            // if the username looks like a long (12char+) hex string, or a modern github token (e.g. ghp_xxx, github_pat_xxx) we obfuscate that
            if (Preg::isMatch(\Composer\Util\GitHub::GITHUB_TOKEN_REGEX, $m['user'])) {
                return $m['prefix'] . '***:***@';
            }
            return $m['prefix'] . $m['user'] . ':***@';
        }, $url);
        return $url;
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer\Util;

use Composer\IO\IOInterface;
use Composer\Pcre\Preg;
use _ContaoManager\Symfony\Component\Process\ExecutableFinder;
use _ContaoManager\Symfony\Component\Process\Process;
/**
 * @author Matt Whittom <Matt.Whittom@veteransunited.com>
 *
 * @phpstan-type RepoConfig array{unique_perforce_client_name?: string, depot?: string, branch?: string, p4user?: string, p4password?: string}
 */
class Perforce
{
    /** @var string */
    protected $path;
    /** @var ?string */
    protected $p4Depot;
    /** @var ?string */
    protected $p4Client;
    /** @var ?string */
    protected $p4User;
    /** @var ?string */
    protected $p4Password;
    /** @var string */
    protected $p4Port;
    /** @var ?string */
    protected $p4Stream;
    /** @var string */
    protected $p4ClientSpec;
    /** @var ?string */
    protected $p4DepotType;
    /** @var ?string */
    protected $p4Branch;
    /** @var ProcessExecutor */
    protected $process;
    /** @var string */
    protected $uniquePerforceClientName;
    /** @var bool */
    protected $windowsFlag;
    /** @var string */
    protected $commandResult;
    /** @var IOInterface */
    protected $io;
    /** @var ?Filesystem */
    protected $filesystem;
    /**
     * @phpstan-param RepoConfig $repoConfig
     */
    public function __construct($repoConfig, string $port, string $path, \Composer\Util\ProcessExecutor $process, bool $isWindows, IOInterface $io)
    {
        $this->windowsFlag = $isWindows;
        $this->p4Port = $port;
        $this->initializePath($path);
        $this->process = $process;
        $this->initialize($repoConfig);
        $this->io = $io;
    }
    /**
     * @phpstan-param RepoConfig $repoConfig
     */
    public static function create($repoConfig, string $port, string $path, \Composer\Util\ProcessExecutor $process, IOInterface $io): self
    {
        return new \Composer\Util\Perforce($repoConfig, $port, $path, $process, \Composer\Util\Platform::isWindows(), $io);
    }
    public static function checkServerExists(string $url, \Composer\Util\ProcessExecutor $processExecutor): bool
    {
        return 0 === $processExecutor->execute(['p4', '-p', $url, 'info', '-s'], $ignoredOutput);
    }
    /**
     * @phpstan-param RepoConfig $repoConfig
     */
    public function initialize($repoConfig): void
    {
        $this->uniquePerforceClientName = $this->generateUniquePerforceClientName();
        if (!$repoConfig) {
            return;
        }
        if (isset($repoConfig['unique_perforce_client_name'])) {
            $this->uniquePerforceClientName = $repoConfig['unique_perforce_client_name'];
        }
        if (isset($repoConfig['depot'])) {
            $this->p4Depot = $repoConfig['depot'];
        }
        if (isset($repoConfig['branch'])) {
            $this->p4Branch = $repoConfig['branch'];
        }
        if (isset($repoConfig['p4user'])) {
            $this->p4User = $repoConfig['p4user'];
        } else {
            $this->p4User = $this->getP4variable('P4USER');
        }
        if (isset($repoConfig['p4password'])) {
            $this->p4Password = $repoConfig['p4password'];
        }
    }
    public function initializeDepotAndBranch(?string $depot, ?string $branch): void
    {
        if (isset($depot)) {
            $this->p4Depot = $depot;
        }
        if (isset($branch)) {
            $this->p4Branch = $branch;
        }
    }
    /**
     * @return non-empty-string
     */
    public function generateUniquePerforceClientName(): string
    {
        return gethostname() . "_" . time();
    }
    public function cleanupClientSpec(): void
    {
        $client = $this->getClient();
        $task = ['client', '-d', $client];
        $useP4Client = \false;
        $command = $this->generateP4Command($task, $useP4Client);
        $this->executeCommand($command);
        $clientSpec = $this->getP4ClientSpec();
        $fileSystem = $this->getFilesystem();
        $fileSystem->remove($clientSpec);
    }
    /**
     * @param non-empty-string|non-empty-list<string> $command
     */
    protected function executeCommand($command): int
    {
        $this->commandResult = '';
        return $this->process->execute($command, $this->commandResult);
    }
    public function getClient(): string
    {
        if (!isset($this->p4Client)) {
            $cleanStreamName = str_replace(['//', '/', '@'], ['', '_', ''], $this->getStream());
            $this->p4Client = 'composer_perforce_' . $this->uniquePerforceClientName . '_' . $cleanStreamName;
        }
        return $this->p4Client;
    }
    protected function getPath(): string
    {
        return $this->path;
    }
    public function initializePath(string $path): void
    {
        $this->path = $path;
        $fs = $this->getFilesystem();
        $fs->ensureDirectoryExists($path);
    }
    protected function getPort(): string
    {
        return $this->p4Port;
    }
    public function setStream(string $stream): void
    {
        $this->p4Stream = $stream;
        $index = strrpos($stream, '/');
        //Stream format is //depot/stream, while non-streaming depot is //depot
        if ($index > 2) {
            $this->p4DepotType = 'stream';
        }
    }
    public function isStream(): bool
    {
        return is_string($this->p4DepotType) && strcmp($this->p4DepotType, 'stream') === 0;
    }
    public function getStream(): string
    {
        if (!isset($this->p4Stream)) {
            if ($this->isStream()) {
                $this->p4Stream = '//' . $this->p4Depot . '/' . $this->p4Branch;
            } else {
                $this->p4Stream = '//' . $this->p4Depot;
            }
        }
        return $this->p4Stream;
    }
    public function getStreamWithoutLabel(string $stream): string
    {
        $index = strpos($stream, '@');
        if ($index === \false) {
            return $stream;
        }
        return substr($stream, 0, $index);
    }
    /**
     * @return non-empty-string
     */
    public function getP4ClientSpec(): string
    {
        return $this->path . '/' . $this->getClient() . '.p4.spec';
    }
    public function getUser(): ?string
    {
        return $this->p4User;
    }
    public function setUser(?string $user): void
    {
        $this->p4User = $user;
    }
    public function queryP4User(): void
    {
        $this->getUser();
        if (strlen((string) $this->p4User) > 0) {
            return;
        }
        $this->p4User = $this->getP4variable('P4USER');
        if (strlen((string) $this->p4User) > 0) {
            return;
        }
        $this->p4User = $this->io->ask('Enter P4 User:');
        if ($this->windowsFlag) {
            $command = $this->getP4Executable() . ' set P4USER=' . \Composer\Util\ProcessExecutor::escape($this->p4User);
        } else {
            $command = 'export P4USER=' . \Composer\Util\ProcessExecutor::escape($this->p4User);
        }
        $this->executeCommand($command);
    }
    protected function getP4variable(string $name): ?string
    {
        if ($this->windowsFlag) {
            $command = $this->getP4Executable() . ' set';
            $this->executeCommand($command);
            $result = trim($this->commandResult);
            $resArray = explode(\PHP_EOL, $result);
            foreach ($resArray as $line) {
                $fields = explode('=', $line);
                if (strcmp($name, $fields[0]) === 0) {
                    $index = strpos($fields[1], ' ');
                    if ($index === \false) {
                        $value = $fields[1];
                    } else {
                        $value = substr($fields[1], 0, $index);
                    }
                    $value = trim($value);
                    return $value;
                }
            }
            return null;
        }
        $command = 'echo $' . $name;
        $this->executeCommand($command);
        $result = trim($this->commandResult);
        return $result;
    }
    public function queryP4Password(): ?string
    {
        if (isset($this->p4Password)) {
            return $this->p4Password;
        }
        $password = $this->getP4variable('P4PASSWD');
        if (strlen((string) $password) <= 0) {
            $password = $this->io->askAndHideAnswer('Enter password for Perforce user ' . $this->getUser() . ': ');
        }
        $this->p4Password = $password;
        return $password;
    }
    /**
     * @internal
     * @param non-empty-list<string> $arguments Additional arguments for git rev-list
     * @return non-empty-list<string>
     */
    public function generateP4Command(array $arguments, bool $useClient = \true): array
    {
        $p4Command = [$this->getP4Executable()];
        if ($this->getUser() !== null) {
            $p4Command[] = '-u';
            $p4Command[] = $this->getUser();
        }
        if ($useClient) {
            $p4Command[] = '-c';
            $p4Command[] = $this->getClient();
        }
        $p4Command[] = '-p';
        $p4Command[] = $this->getPort();
        return array_merge($p4Command, $arguments);
    }
    public function isLoggedIn(): bool
    {
        $command = $this->generateP4Command(['login', '-s'], \false);
        $exitCode = $this->executeCommand($command);
        if ($exitCode) {
            $errorOutput = $this->process->getErrorOutput();
            $index = strpos($errorOutput, $this->getUser());
            if ($index === \false) {
                $index = strpos($errorOutput, 'p4');
                if ($index === \false) {
                    return \false;
                }
                throw new \Exception('p4 command not found in path: ' . $errorOutput);
            }
            throw new \Exception('Invalid user name: ' . $this->getUser());
        }
        return \true;
    }
    public function connectClient(): void
    {
        $p4CreateClientCommand = $this->generateP4Command(['client', '-i']);
        $process = new Process($p4CreateClientCommand, null, null, file_get_contents($this->getP4ClientSpec()));
        $process->run();
    }
    public function syncCodeBase(?string $sourceReference): void
    {
        $prevDir = \Composer\Util\Platform::getCwd();
        chdir($this->path);
        $p4SyncCommand = $this->generateP4Command(['sync', '-f']);
        if (null !== $sourceReference) {
            $p4SyncCommand[] = '@' . $sourceReference;
        }
        $this->executeCommand($p4SyncCommand);
        chdir($prevDir);
    }
    /**
     * @param resource|false $spec
     */
    public function writeClientSpecToFile($spec): void
    {
        fwrite($spec, 'Client: ' . $this->getClient() . \PHP_EOL . \PHP_EOL);
        fwrite($spec, 'Update: ' . date('Y/m/d H:i:s') . \PHP_EOL . \PHP_EOL);
        fwrite($spec, 'Access: ' . date('Y/m/d H:i:s') . \PHP_EOL);
        fwrite($spec, 'Owner:  ' . $this->getUser() . \PHP_EOL . \PHP_EOL);
        fwrite($spec, 'Description:' . \PHP_EOL);
        fwrite($spec, '  Created by ' . $this->getUser() . ' from composer.' . \PHP_EOL . \PHP_EOL);
        fwrite($spec, 'Root: ' . $this->getPath() . \PHP_EOL . \PHP_EOL);
        fwrite($spec, 'Options:  noallwrite noclobber nocompress unlocked modtime rmdir' . \PHP_EOL . \PHP_EOL);
        fwrite($spec, 'SubmitOptions:  revertunchanged' . \PHP_EOL . \PHP_EOL);
        fwrite($spec, 'LineEnd:  local' . \PHP_EOL . \PHP_EOL);
        if ($this->isStream()) {
            fwrite($spec, 'Stream:' . \PHP_EOL);
            fwrite($spec, '  ' . $this->getStreamWithoutLabel($this->p4Stream) . \PHP_EOL);
        } else {
            fwrite($spec, 'View:  ' . $this->getStream() . '/...  //' . $this->getClient() . '/... ' . \PHP_EOL);
        }
    }
    public function writeP4ClientSpec(): void
    {
        $clientSpec = $this->getP4ClientSpec();
        $spec = fopen($clientSpec, 'w');
        try {
            $this->writeClientSpecToFile($spec);
        } catch (\Exception $e) {
            fclose($spec);
            throw $e;
        }
        fclose($spec);
    }
    /**
     * @param resource $pipe
     * @param mixed    $name
     */
    protected function read($pipe, $name): void
    {
        if (feof($pipe)) {
            return;
        }
        $line = fgets($pipe);
        while ($line !== \false) {
            $line = fgets($pipe);
        }
    }
    public function windowsLogin(?string $password): int
    {
        $command = $this->generateP4Command(['login', '-a']);
        $process = new Process($command, null, null, $password);
        return $process->run();
    }
    public function p4Login(): void
    {
        $this->queryP4User();
        if (!$this->isLoggedIn()) {
            $password = $this->queryP4Password();
            if ($this->windowsFlag) {
                $this->windowsLogin($password);
            } else {
                $command = $this->generateP4Command(['login', '-a'], \false);
                $process = new Process($command, null, null, $password);
                $process->run();
                if (!$process->isSuccessful()) {
                    throw new \Exception("Error logging in:" . $this->process->getErrorOutput());
                }
            }
        }
    }
    /**
     * @return mixed[]|null
     */
    public function getComposerInformation(string $identifier): ?array
    {
        $composerFileContent = $this->getFileContent('composer.json', $identifier);
        if (!$composerFileContent) {
            return null;
        }
        return json_decode($composerFileContent, \true);
    }
    public function getFileContent(string $file, string $identifier): ?string
    {
        $path = $this->getFilePath($file, $identifier);
        if ($path === null) {
            return null;
        }
        $command = $this->generateP4Command(['print', $path]);
        $this->executeCommand($command);
        $result = $this->commandResult;
        if (!trim($result)) {
            return null;
        }
        return $result;
    }
    public function getFilePath(string $file, string $identifier): ?string
    {
        $index = strpos($identifier, '@');
        if ($index === \false) {
            return $identifier . '/' . $file;
        }
        $path = substr($identifier, 0, $index) . '/' . $file . substr($identifier, $index);
        $command = $this->generateP4Command(['files', $path], \false);
        $this->executeCommand($command);
        $result = $this->commandResult;
        $index2 = strpos($result, 'no such file(s).');
        if ($index2 === \false) {
            $index3 = strpos($result, 'change');
            if ($index3 !== \false) {
                $phrase = trim(substr($result, $index3));
                $fields = explode(' ', $phrase);
                return substr($identifier, 0, $index) . '/' . $file . '@' . $fields[1];
            }
        }
        return null;
    }
    /**
     * @return array{master: string}
     */
    public function getBranches(): array
    {
        $possibleBranches = [];
        if (!$this->isStream()) {
            $possibleBranches[$this->p4Branch] = $this->getStream();
        } else {
            $command = $this->generateP4Command(['streams', '//' . $this->p4Depot . '/...']);
            $this->executeCommand($command);
            $result = $this->commandResult;
            $resArray = explode(\PHP_EOL, $result);
            foreach ($resArray as $line) {
                $resBits = explode(' ', $line);
                if (count($resBits) > 4) {
                    $branch = Preg::replace('/[^A-Za-z0-9 ]/', '', $resBits[4]);
                    $possibleBranches[$branch] = $resBits[1];
                }
            }
        }
        $command = $this->generateP4Command(['changes', $this->getStream() . '/...'], \false);
        $this->executeCommand($command);
        $result = $this->commandResult;
        $resArray = explode(\PHP_EOL, $result);
        $lastCommit = $resArray[0];
        $lastCommitArr = explode(' ', $lastCommit);
        $lastCommitNum = $lastCommitArr[1];
        return ['master' => $possibleBranches[$this->p4Branch] . '@' . $lastCommitNum];
    }
    /**
     * @return array<string, string>
     */
    public function getTags(): array
    {
        $command = $this->generateP4Command(['labels']);
        $this->executeCommand($command);
        $result = $this->commandResult;
        $resArray = explode(\PHP_EOL, $result);
        $tags = [];
        foreach ($resArray as $line) {
            if (strpos($line, 'Label') !== \false) {
                $fields = explode(' ', $line);
                $tags[$fields[1]] = $this->getStream() . '@' . $fields[1];
            }
        }
        return $tags;
    }
    public function checkStream(): bool
    {
        $command = $this->generateP4Command(['depots'], \false);
        $this->executeCommand($command);
        $result = $this->commandResult;
        $resArray = explode(\PHP_EOL, $result);
        foreach ($resArray as $line) {
            if (strpos($line, 'Depot') !== \false) {
                $fields = explode(' ', $line);
                if (strcmp($this->p4Depot, $fields[1]) === 0) {
                    $this->p4DepotType = $fields[3];
                    return $this->isStream();
                }
            }
        }
        return \false;
    }
    /**
     * @return mixed|null
     */
    protected function getChangeList(string $reference): mixed
    {
        $index = strpos($reference, '@');
        if ($index === \false) {
            return null;
        }
        $label = substr($reference, $index);
        $command = $this->generateP4Command(['changes', '-m1', $label]);
        $this->executeCommand($command);
        $changes = $this->commandResult;
        if (strpos($changes, 'Change') !== 0) {
            return null;
        }
        $fields = explode(' ', $changes);
        return $fields[1];
    }
    /**
     * @return mixed|null
     */
    public function getCommitLogs(string $fromReference, string $toReference): mixed
    {
        $fromChangeList = $this->getChangeList($fromReference);
        if ($fromChangeList === null) {
            return null;
        }
        $toChangeList = $this->getChangeList($toReference);
        if ($toChangeList === null) {
            return null;
        }
        $index = strpos($fromReference, '@');
        $main = substr($fromReference, 0, $index) . '/...';
        $command = $this->generateP4Command(['filelog', $main . '@' . $fromChangeList . ',' . $toChangeList]);
        $this->executeCommand($command);
        return $this->commandResult;
    }
    public function getFilesystem(): \Composer\Util\Filesystem
    {
        if (null === $this->filesystem) {
            $this->filesystem = new \Composer\Util\Filesystem($this->process);
        }
        return $this->filesystem;
    }
    public function setFilesystem(\Composer\Util\Filesystem $fs): void
    {
        $this->filesystem = $fs;
    }
    private function getP4Executable(): string
    {
        static $p4Executable;
        if ($p4Executable) {
            return $p4Executable;
        }
        $finder = new ExecutableFinder();
        return $p4Executable = $finder->find('p4') ?? 'p4';
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer\Util\Http;

use Composer\Downloader\TransportException;
use Composer\Util\NoProxyPattern;
/**
 * @internal
 * @author John Stevenson <john-stevenson@blueyonder.co.uk>
 */
class ProxyManager
{
    /** @var ?string */
    private $error = null;
    /** @var ?ProxyItem */
    private $httpProxy = null;
    /** @var ?ProxyItem */
    private $httpsProxy = null;
    /** @var ?NoProxyPattern */
    private $noProxyHandler = null;
    /** @var ?self */
    private static $instance = null;
    private function __construct()
    {
        try {
            $this->getProxyData();
        } catch (\RuntimeException $e) {
            $this->error = $e->getMessage();
        }
    }
    public static function getInstance(): \Composer\Util\Http\ProxyManager
    {
        if (self::$instance === null) {
            self::$instance = new self();
        }
        return self::$instance;
    }
    /**
     * Clears the persistent instance
     */
    public static function reset(): void
    {
        self::$instance = null;
    }
    public function hasProxy(): bool
    {
        return $this->httpProxy !== null || $this->httpsProxy !== null;
    }
    /**
     * Returns a RequestProxy instance for the request url
     *
     * @param non-empty-string $requestUrl
     */
    public function getProxyForRequest(string $requestUrl): \Composer\Util\Http\RequestProxy
    {
        if ($this->error !== null) {
            throw new TransportException('Unable to use a proxy: ' . $this->error);
        }
        $scheme = (string) parse_url($requestUrl, \PHP_URL_SCHEME);
        $proxy = $this->getProxyForScheme($scheme);
        if ($proxy === null) {
            return \Composer\Util\Http\RequestProxy::none();
        }
        if ($this->noProxy($requestUrl)) {
            return \Composer\Util\Http\RequestProxy::noProxy();
        }
        return $proxy->toRequestProxy($scheme);
    }
    /**
     * Returns a ProxyItem if one is set for the scheme, otherwise null
     */
    private function getProxyForScheme(string $scheme): ?\Composer\Util\Http\ProxyItem
    {
        if ($scheme === 'http') {
            return $this->httpProxy;
        }
        if ($scheme === 'https') {
            return $this->httpsProxy;
        }
        return null;
    }
    /**
     * Finds proxy values from the environment and sets class properties
     */
    private function getProxyData(): void
    {
        // Handle http_proxy/HTTP_PROXY on CLI only for security reasons
        if (\PHP_SAPI === 'cli' || \PHP_SAPI === 'phpdbg') {
            [$env, $name] = $this->getProxyEnv('http_proxy');
            if ($env !== null) {
                $this->httpProxy = new \Composer\Util\Http\ProxyItem($env, $name);
            }
        }
        // Handle cgi_http_proxy/CGI_HTTP_PROXY if needed
        if ($this->httpProxy === null) {
            [$env, $name] = $this->getProxyEnv('cgi_http_proxy');
            if ($env !== null) {
                $this->httpProxy = new \Composer\Util\Http\ProxyItem($env, $name);
            }
        }
        // Handle https_proxy/HTTPS_PROXY
        [$env, $name] = $this->getProxyEnv('https_proxy');
        if ($env !== null) {
            $this->httpsProxy = new \Composer\Util\Http\ProxyItem($env, $name);
        }
        // Handle no_proxy/NO_PROXY
        [$env, $name] = $this->getProxyEnv('no_proxy');
        if ($env !== null) {
            $this->noProxyHandler = new NoProxyPattern($env);
        }
    }
    /**
     * Searches $_SERVER for case-sensitive values
     *
     * @return array{0: string|null, 1: string} value, name
     */
    private function getProxyEnv(string $envName): array
    {
        $names = [strtolower($envName), strtoupper($envName)];
        foreach ($names as $name) {
            if (is_string($_SERVER[$name] ?? null)) {
                if ($_SERVER[$name] !== '') {
                    return [$_SERVER[$name], $name];
                }
            }
        }
        return [null, ''];
    }
    /**
     * Returns true if a url matches no_proxy value
     */
    private function noProxy(string $requestUrl): bool
    {
        if ($this->noProxyHandler === null) {
            return \false;
        }
        return $this->noProxyHandler->test($requestUrl);
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer\Util\Http;

use Composer\Json\JsonFile;
use Composer\Pcre\Preg;
/**
 * @phpstan-type Request array{url: non-empty-string, options?: mixed[], copyTo?: string|null}
 */
class Response
{
    /** @var Request */
    private $request;
    /** @var int */
    private $code;
    /** @var list<string> */
    private $headers;
    /** @var ?string */
    private $body;
    /**
     * @param Request $request
     * @param list<string> $headers
     */
    public function __construct(array $request, ?int $code, array $headers, ?string $body)
    {
        if (!isset($request['url'])) {
            throw new \LogicException('url key missing from request array');
        }
        $this->request = $request;
        $this->code = (int) $code;
        $this->headers = $headers;
        $this->body = $body;
    }
    public function getStatusCode(): int
    {
        return $this->code;
    }
    public function getStatusMessage(): ?string
    {
        $value = null;
        foreach ($this->headers as $header) {
            if (Preg::isMatch('{^HTTP/\S+ \d+}i', $header)) {
                // In case of redirects, headers contain the headers of all responses
                // so we can not return directly and need to keep iterating
                $value = $header;
            }
        }
        return $value;
    }
    /**
     * @return string[]
     */
    public function getHeaders(): array
    {
        return $this->headers;
    }
    public function getHeader(string $name): ?string
    {
        return self::findHeaderValue($this->headers, $name);
    }
    public function getBody(): ?string
    {
        return $this->body;
    }
    /**
     * @return mixed
     */
    public function decodeJson()
    {
        return JsonFile::parseJson($this->body, $this->request['url']);
    }
    /**
     * @phpstan-impure
     */
    public function collect(): void
    {
        unset($this->request, $this->code, $this->headers, $this->body);
    }
    /**
     * @param  string[]    $headers array of returned headers like from getLastHeaders()
     * @param  string      $name    header name (case insensitive)
     */
    public static function findHeaderValue(array $headers, string $name): ?string
    {
        $value = null;
        foreach ($headers as $header) {
            if (Preg::isMatch('{^' . preg_quote($name) . ':\s*(.+?)\s*$}i', $header, $match)) {
                $value = $match[1];
            }
        }
        return $value;
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer\Util\Http;

use Composer\Downloader\TransportException;
/**
 * @internal
 * @author John Stevenson <john-stevenson@blueyonder.co.uk>
 *
 * @phpstan-type contextOptions array{http: array{proxy: string, header?: string, request_fulluri?: bool}}
 */
class RequestProxy
{
    /** @var ?contextOptions */
    private $contextOptions;
    /** @var ?non-empty-string */
    private $status;
    /** @var ?non-empty-string */
    private $url;
    /** @var ?non-empty-string */
    private $auth;
    /**
     * @param ?non-empty-string $url The proxy url, without authorization
     * @param ?non-empty-string $auth Authorization for curl
     * @param ?contextOptions $contextOptions
     * @param ?non-empty-string $status
     */
    public function __construct(?string $url, ?string $auth, ?array $contextOptions, ?string $status)
    {
        $this->url = $url;
        $this->auth = $auth;
        $this->contextOptions = $contextOptions;
        $this->status = $status;
    }
    public static function none(): \Composer\Util\Http\RequestProxy
    {
        return new self(null, null, null, null);
    }
    public static function noProxy(): \Composer\Util\Http\RequestProxy
    {
        return new self(null, null, null, 'excluded by no_proxy');
    }
    /**
     * Returns the context options to use for this request, otherwise null
     *
     * @return ?contextOptions
     */
    public function getContextOptions(): ?array
    {
        return $this->contextOptions;
    }
    /**
     * Returns an array of curl proxy options
     *
     * @param array<string, string|int> $sslOptions
     * @return array<int, string|int>
     */
    public function getCurlOptions(array $sslOptions): array
    {
        if ($this->isSecure() && !$this->supportsSecureProxy()) {
            throw new TransportException('Cannot use an HTTPS proxy. PHP >= 7.3 and cUrl >= 7.52.0 are required.');
        }
        // Always set a proxy url, even an empty value, because it tells curl
        // to ignore proxy environment variables
        $options = [\CURLOPT_PROXY => (string) $this->url];
        // If using a proxy, tell curl to ignore no_proxy environment variables
        if ($this->url !== null) {
            $options[\CURLOPT_NOPROXY] = '';
        }
        // Set any authorization
        if ($this->auth !== null) {
            $options[\CURLOPT_PROXYAUTH] = \CURLAUTH_BASIC;
            $options[\CURLOPT_PROXYUSERPWD] = $this->auth;
        }
        if ($this->isSecure()) {
            if (isset($sslOptions['cafile'])) {
                $options[\CURLOPT_PROXY_CAINFO] = $sslOptions['cafile'];
            }
            if (isset($sslOptions['capath'])) {
                $options[\CURLOPT_PROXY_CAPATH] = $sslOptions['capath'];
            }
        }
        return $options;
    }
    /**
     * Returns proxy info associated with this request
     *
     * An empty return value means that the user has not set a proxy.
     * A non-empty value will either be the sanitized proxy url if a proxy is
     * required, or a message indicating that a no_proxy value has disabled the
     * proxy.
     *
     * @param ?string $format Output format specifier
     */
    public function getStatus(?string $format = null): string
    {
        if ($this->status === null) {
            return '';
        }
        $format = $format ?? '%s';
        if (strpos($format, '%s') !== \false) {
            return sprintf($format, $this->status);
        }
        throw new \InvalidArgumentException('String format specifier is missing');
    }
    /**
     * Returns true if the request url has been excluded by a no_proxy value
     *
     * A false value can also mean that the user has not set a proxy.
     */
    public function isExcludedByNoProxy(): bool
    {
        return $this->status !== null && $this->url === null;
    }
    /**
     * Returns true if this is a secure (HTTPS) proxy
     *
     * A false value means that this is either an HTTP proxy, or that a proxy
     * is not required for this request, or that the user has not set a proxy.
     */
    public function isSecure(): bool
    {
        return 0 === strpos((string) $this->url, 'https://');
    }
    /**
     * Returns true if an HTTPS proxy can be used.
     *
     * This depends on PHP7.3+ for CURL_VERSION_HTTPS_PROXY
     * and curl including the feature (from version 7.52.0)
     */
    public function supportsSecureProxy(): bool
    {
        if (\false === ($version = curl_version()) || !defined('CURL_VERSION_HTTPS_PROXY')) {
            return \false;
        }
        $features = $version['features'];
        return (bool) ($features & \CURL_VERSION_HTTPS_PROXY);
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer\Util\Http;

use Composer\Config;
use Composer\Downloader\MaxFileSizeExceededException;
use Composer\IO\IOInterface;
use Composer\Downloader\TransportException;
use Composer\Pcre\Preg;
use Composer\Util\Platform;
use Composer\Util\StreamContextFactory;
use Composer\Util\AuthHelper;
use Composer\Util\Url;
use Composer\Util\HttpDownloader;
use React\Promise\Promise;
/**
 * @internal
 * @author Jordi Boggiano <j.boggiano@seld.be>
 * @author Nicolas Grekas <p@tchwork.com>
 * @phpstan-type Attributes array{retryAuthFailure: bool, redirects: int<0, max>, retries: int<0, max>, storeAuth: 'prompt'|bool, ipResolve: 4|6|null}
 * @phpstan-type Job array{url: non-empty-string, origin: string, attributes: Attributes, options: mixed[], progress: mixed[], curlHandle: \CurlHandle, filename: string|null, headerHandle: resource, bodyHandle: resource, resolve: callable, reject: callable, primaryIp: string}
 */
class CurlDownloader
{
    /**
     * Known libcurl's broken versions when proxy is in use with HTTP/2
     * multiplexing.
     *
     * @var list<non-empty-string>
     */
    private const BAD_MULTIPLEXING_CURL_VERSIONS = ['7.87.0', '7.88.0', '7.88.1'];
    /** @var \CurlMultiHandle */
    private $multiHandle;
    /** @var \CurlShareHandle */
    private $shareHandle;
    /** @var Job[] */
    private $jobs = [];
    /** @var IOInterface */
    private $io;
    /** @var Config */
    private $config;
    /** @var AuthHelper */
    private $authHelper;
    /** @var float */
    private $selectTimeout = 5.0;
    /** @var int */
    private $maxRedirects = 20;
    /** @var int */
    private $maxRetries = 3;
    /** @var array<int, string[]> */
    protected $multiErrors = [\CURLM_BAD_HANDLE => ['CURLM_BAD_HANDLE', 'The passed-in handle is not a valid CURLM handle.'], \CURLM_BAD_EASY_HANDLE => ['CURLM_BAD_EASY_HANDLE', "An easy handle was not good/valid. It could mean that it isn't an easy handle at all, or possibly that the handle already is in used by this or another multi handle."], \CURLM_OUT_OF_MEMORY => ['CURLM_OUT_OF_MEMORY', 'You are doomed.'], \CURLM_INTERNAL_ERROR => ['CURLM_INTERNAL_ERROR', 'This can only be returned if libcurl bugs. Please report it to us!']];
    /** @var mixed[] */
    private static $options = ['http' => ['method' => \CURLOPT_CUSTOMREQUEST, 'content' => \CURLOPT_POSTFIELDS, 'header' => \CURLOPT_HTTPHEADER, 'timeout' => \CURLOPT_TIMEOUT], 'ssl' => ['cafile' => \CURLOPT_CAINFO, 'capath' => \CURLOPT_CAPATH, 'verify_peer' => \CURLOPT_SSL_VERIFYPEER, 'verify_peer_name' => \CURLOPT_SSL_VERIFYHOST, 'local_cert' => \CURLOPT_SSLCERT, 'local_pk' => \CURLOPT_SSLKEY, 'passphrase' => \CURLOPT_SSLKEYPASSWD]];
    /** @var array<string, true> */
    private static $timeInfo = ['total_time' => \true, 'namelookup_time' => \true, 'connect_time' => \true, 'pretransfer_time' => \true, 'starttransfer_time' => \true, 'redirect_time' => \true];
    /**
     * @param mixed[] $options
     */
    public function __construct(IOInterface $io, Config $config, array $options = [], bool $disableTls = \false)
    {
        $this->io = $io;
        $this->config = $config;
        $this->multiHandle = $mh = curl_multi_init();
        if (function_exists('curl_multi_setopt')) {
            if (\Composer\Util\Http\ProxyManager::getInstance()->hasProxy() && ($version = curl_version()) !== \false && in_array($version['version'], self::BAD_MULTIPLEXING_CURL_VERSIONS, \true)) {
                /**
                 * Disable HTTP/2 multiplexing for some broken versions of libcurl.
                 *
                 * In certain versions of libcurl when proxy is in use with HTTP/2
                 * multiplexing, connections will continue stacking up. This was
                 * fixed in libcurl 8.0.0 in curl/curl@821f6e2a89de8aec1c7da3c0f381b92b2b801efc
                 */
                curl_multi_setopt(
                    $mh,
                    \CURLMOPT_PIPELINING,
                    /* CURLPIPE_NOTHING */
                    0
                );
            } else {
                curl_multi_setopt($mh, \CURLMOPT_PIPELINING, \PHP_VERSION_ID >= 70400 ? 2 : 3);
            }
            if (defined('CURLMOPT_MAX_HOST_CONNECTIONS') && !defined('HHVM_VERSION')) {
                curl_multi_setopt($mh, \CURLMOPT_MAX_HOST_CONNECTIONS, 8);
            }
        }
        if (function_exists('curl_share_init')) {
            $this->shareHandle = $sh = curl_share_init();
            curl_share_setopt($sh, \CURLSHOPT_SHARE, \CURL_LOCK_DATA_COOKIE);
            curl_share_setopt($sh, \CURLSHOPT_SHARE, \CURL_LOCK_DATA_DNS);
            curl_share_setopt($sh, \CURLSHOPT_SHARE, \CURL_LOCK_DATA_SSL_SESSION);
        }
        $this->authHelper = new AuthHelper($io, $config);
    }
    /**
     * @param mixed[]  $options
     * @param non-empty-string $url
     *
     * @return int internal job id
     */
    public function download(callable $resolve, callable $reject, string $origin, string $url, array $options, ?string $copyTo = null): int
    {
        $attributes = [];
        if (isset($options['retry-auth-failure'])) {
            $attributes['retryAuthFailure'] = $options['retry-auth-failure'];
            unset($options['retry-auth-failure']);
        }
        return $this->initDownload($resolve, $reject, $origin, $url, $options, $copyTo, $attributes);
    }
    /**
     * @param mixed[]  $options
     *
     * @param array{retryAuthFailure?: bool, redirects?: int<0, max>, retries?: int<0, max>, storeAuth?: 'prompt'|bool, ipResolve?: 4|6|null} $attributes
     * @param non-empty-string $url
     *
     * @return int internal job id
     */
    private function initDownload(callable $resolve, callable $reject, string $origin, string $url, array $options, ?string $copyTo = null, array $attributes = []): int
    {
        $attributes = array_merge(['retryAuthFailure' => \true, 'redirects' => 0, 'retries' => 0, 'storeAuth' => \false, 'ipResolve' => null], $attributes);
        if ($attributes['ipResolve'] === null && Platform::getEnv('COMPOSER_IPRESOLVE') === '4') {
            $attributes['ipResolve'] = 4;
        } elseif ($attributes['ipResolve'] === null && Platform::getEnv('COMPOSER_IPRESOLVE') === '6') {
            $attributes['ipResolve'] = 6;
        }
        $originalOptions = $options;
        // check URL can be accessed (i.e. is not insecure), but allow insecure Packagist calls to $hashed providers as file integrity is verified with sha256
        if (!Preg::isMatch('{^http://(repo\.)?packagist\.org/p/}', $url) || \false === strpos($url, '$') && \false === strpos($url, '%24')) {
            $this->config->prohibitUrlByConfig($url, $this->io, $options);
        }
        $curlHandle = curl_init();
        $headerHandle = fopen('php://temp/maxmemory:32768', 'w+b');
        if (\false === $headerHandle) {
            throw new \RuntimeException('Failed to open a temp stream to store curl headers');
        }
        if ($copyTo !== null) {
            $bodyTarget = $copyTo . '~';
        } else {
            $bodyTarget = 'php://temp/maxmemory:524288';
        }
        $errorMessage = '';
        set_error_handler(static function (int $code, string $msg) use (&$errorMessage): bool {
            if ($errorMessage) {
                $errorMessage .= "\n";
            }
            $errorMessage .= Preg::replace('{^fopen\(.*?\): }', '', $msg);
            return \true;
        });
        $bodyHandle = fopen($bodyTarget, 'w+b');
        restore_error_handler();
        if (\false === $bodyHandle) {
            throw new TransportException('The "' . $url . '" file could not be written to ' . ($copyTo ?? 'a temporary file') . ': ' . $errorMessage);
        }
        curl_setopt($curlHandle, \CURLOPT_URL, $url);
        curl_setopt($curlHandle, \CURLOPT_FOLLOWLOCATION, \false);
        curl_setopt($curlHandle, \CURLOPT_CONNECTTIMEOUT, 10);
        curl_setopt($curlHandle, \CURLOPT_TIMEOUT, max((int) ini_get("default_socket_timeout"), 300));
        curl_setopt($curlHandle, \CURLOPT_WRITEHEADER, $headerHandle);
        curl_setopt($curlHandle, \CURLOPT_FILE, $bodyHandle);
        curl_setopt($curlHandle, \CURLOPT_ENCODING, "");
        // let cURL set the Accept-Encoding header to what it supports
        curl_setopt($curlHandle, \CURLOPT_PROTOCOLS, \CURLPROTO_HTTP | \CURLPROTO_HTTPS);
        if ($attributes['ipResolve'] === 4) {
            curl_setopt($curlHandle, \CURLOPT_IPRESOLVE, \CURL_IPRESOLVE_V4);
        } elseif ($attributes['ipResolve'] === 6) {
            curl_setopt($curlHandle, \CURLOPT_IPRESOLVE, \CURL_IPRESOLVE_V6);
        }
        if (function_exists('curl_share_init')) {
            curl_setopt($curlHandle, \CURLOPT_SHARE, $this->shareHandle);
        }
        if (!isset($options['http']['header'])) {
            $options['http']['header'] = [];
        }
        $options['http']['header'] = array_diff($options['http']['header'], ['Connection: close']);
        $options['http']['header'][] = 'Connection: keep-alive';
        $version = curl_version();
        $features = $version['features'];
        $proxy = \Composer\Util\Http\ProxyManager::getInstance()->getProxyForRequest($url);
        if (0 === strpos($url, 'https://')) {
            $willUseProxy = $proxy->getStatus() !== '' && !$proxy->isExcludedByNoProxy();
            if (!$willUseProxy && \defined('CURL_VERSION_HTTP3') && \defined('CURL_HTTP_VERSION_3') && (\CURL_VERSION_HTTP3 & $features) !== 0) {
                curl_setopt($curlHandle, \CURLOPT_HTTP_VERSION, \CURL_HTTP_VERSION_3);
            } elseif (\defined('CURL_VERSION_HTTP2') && \defined('CURL_HTTP_VERSION_2_0') && (\CURL_VERSION_HTTP2 & $features) !== 0) {
                curl_setopt($curlHandle, \CURLOPT_HTTP_VERSION, \CURL_HTTP_VERSION_2_0);
            }
        }
        // curl 8.7.0 - 8.7.1 has a bug whereas automatic accept-encoding header results in an error when reading the response
        // https://github.com/composer/composer/issues/11913
        if (isset($version['version']) && in_array($version['version'], ['8.7.0', '8.7.1'], \true) && \defined('CURL_VERSION_LIBZ') && (\CURL_VERSION_LIBZ & $features) !== 0) {
            curl_setopt($curlHandle, \CURLOPT_ENCODING, "gzip");
        }
        $options = $this->authHelper->addAuthenticationOptions($options, $origin, $url);
        $options = StreamContextFactory::initOptions($url, $options, \true);
        foreach (self::$options as $type => $curlOptions) {
            foreach ($curlOptions as $name => $curlOption) {
                if (isset($options[$type][$name])) {
                    if ($type === 'ssl' && $name === 'verify_peer_name') {
                        curl_setopt($curlHandle, $curlOption, $options[$type][$name] === \true ? 2 : $options[$type][$name]);
                    } else {
                        curl_setopt($curlHandle, $curlOption, $options[$type][$name]);
                    }
                }
            }
        }
        curl_setopt_array($curlHandle, $proxy->getCurlOptions($options['ssl'] ?? []));
        $progress = array_diff_key(curl_getinfo($curlHandle), self::$timeInfo);
        $this->jobs[(int) $curlHandle] = ['url' => $url, 'origin' => $origin, 'attributes' => $attributes, 'options' => $originalOptions, 'progress' => $progress, 'curlHandle' => $curlHandle, 'filename' => $copyTo, 'headerHandle' => $headerHandle, 'bodyHandle' => $bodyHandle, 'resolve' => $resolve, 'reject' => $reject, 'primaryIp' => ''];
        $usingProxy = $proxy->getStatus(' using proxy (%s)');
        $ifModified = \false !== stripos(implode(',', $options['http']['header']), 'if-modified-since:') ? ' if modified' : '';
        if ($attributes['redirects'] === 0 && $attributes['retries'] === 0) {
            $this->io->writeError('Downloading ' . Url::sanitize($url) . $usingProxy . $ifModified, \true, IOInterface::DEBUG);
        }
        $this->checkCurlResult(curl_multi_add_handle($this->multiHandle, $curlHandle));
        // TODO progress
        return (int) $curlHandle;
    }
    public function abortRequest(int $id): void
    {
        if (isset($this->jobs[$id], $this->jobs[$id]['curlHandle'])) {
            $job = $this->jobs[$id];
            curl_multi_remove_handle($this->multiHandle, $job['curlHandle']);
            if (\PHP_VERSION_ID < 80000) {
                curl_close($job['curlHandle']);
            }
            if (is_resource($job['headerHandle'])) {
                fclose($job['headerHandle']);
            }
            if (is_resource($job['bodyHandle'])) {
                fclose($job['bodyHandle']);
            }
            if (null !== $job['filename']) {
                @unlink($job['filename'] . '~');
            }
            unset($this->jobs[$id]);
        }
    }
    public function tick(): void
    {
        static $timeoutWarning = \false;
        if (count($this->jobs) === 0) {
            return;
        }
        $active = \true;
        $this->checkCurlResult(curl_multi_exec($this->multiHandle, $active));
        if (-1 === curl_multi_select($this->multiHandle, $this->selectTimeout)) {
            // sleep in case select returns -1 as it can happen on old php versions or some platforms where curl does not manage to do the select
            usleep(150);
        }
        while ($progress = curl_multi_info_read($this->multiHandle)) {
            $curlHandle = $progress['handle'];
            $result = $progress['result'];
            $i = (int) $curlHandle;
            if (!isset($this->jobs[$i])) {
                continue;
            }
            $progress = curl_getinfo($curlHandle);
            if (\false === $progress) {
                throw new \RuntimeException('Failed getting info from curl handle ' . $i . ' (' . $this->jobs[$i]['url'] . ')');
            }
            $job = $this->jobs[$i];
            unset($this->jobs[$i]);
            $error = curl_error($curlHandle);
            $errno = curl_errno($curlHandle);
            curl_multi_remove_handle($this->multiHandle, $curlHandle);
            if (\PHP_VERSION_ID < 80000) {
                curl_close($curlHandle);
            }
            $headers = null;
            $statusCode = null;
            $response = null;
            try {
                // TODO progress
                if (\CURLE_OK !== $errno || $error || $result !== \CURLE_OK) {
                    $errno = $errno ?: $result;
                    if (!$error && function_exists('curl_strerror')) {
                        $error = curl_strerror($errno);
                    }
                    $progress['error_code'] = $errno;
                    if ($errno === 28 && \PHP_VERSION_ID >= 70300 && $progress['namelookup_time'] === 0.0 && !$timeoutWarning) {
                        $timeoutWarning = \true;
                        $this->io->writeError('<warning>A connection timeout was encountered. If you intend to run Composer without connecting to the internet, run the command again prefixed with COMPOSER_DISABLE_NETWORK=1 to make Composer run in offline mode.</warning>');
                    }
                    if ((!isset($job['options']['http']['method']) || $job['options']['http']['method'] === 'GET') && (in_array($errno, [7, 16, 92, 6, 28], \true) || in_array($errno, [56, 35], \true) && str_contains((string) $error, 'Connection reset by peer')) && $job['attributes']['retries'] < $this->maxRetries) {
                        $attributes = ['retries' => $job['attributes']['retries'] + 1];
                        if ($errno === 7 && !isset($job['attributes']['ipResolve'])) {
                            // CURLE_COULDNT_CONNECT, retry forcing IPv4 if no IP stack was selected
                            $attributes['ipResolve'] = 4;
                        }
                        $this->io->writeError('Retrying (' . ($job['attributes']['retries'] + 1) . ') ' . Url::sanitize($job['url']) . ' due to curl error ' . $errno, \true, IOInterface::DEBUG);
                        $this->restartJobWithDelay($job, $job['url'], $attributes);
                        continue;
                    }
                    // TODO: Remove this as soon as https://github.com/curl/curl/issues/10591 is resolved
                    if ($errno === 55) {
                        $this->io->writeError('Retrying (' . ($job['attributes']['retries'] + 1) . ') ' . Url::sanitize($job['url']) . ' due to curl error ' . $errno, \true, IOInterface::DEBUG);
                        $this->restartJobWithDelay($job, $job['url'], ['retries' => $job['attributes']['retries'] + 1]);
                        continue;
                    }
                    throw new TransportException('curl error ' . $errno . ' while downloading ' . Url::sanitize($progress['url']) . ': ' . $error);
                }
                $statusCode = $progress['http_code'];
                rewind($job['headerHandle']);
                $headers = explode("\r\n", rtrim(stream_get_contents($job['headerHandle'])));
                fclose($job['headerHandle']);
                if ($statusCode === 0) {
                    throw new \LogicException('Received unexpected http status code 0 without error for ' . Url::sanitize($progress['url']) . ': headers ' . var_export($headers, \true) . ' curl info ' . var_export($progress, \true));
                }
                // prepare response object
                if (null !== $job['filename']) {
                    $contents = $job['filename'] . '~';
                    if ($statusCode >= 300) {
                        rewind($job['bodyHandle']);
                        $contents = stream_get_contents($job['bodyHandle']);
                    }
                    $response = new \Composer\Util\Http\CurlResponse(['url' => $job['url']], $statusCode, $headers, $contents, $progress);
                    $this->io->writeError('[' . $statusCode . '] ' . Url::sanitize($job['url']), \true, IOInterface::DEBUG);
                } else {
                    $maxFileSize = $job['options']['max_file_size'] ?? null;
                    rewind($job['bodyHandle']);
                    if ($maxFileSize !== null) {
                        $contents = stream_get_contents($job['bodyHandle'], $maxFileSize);
                        // Gzipped responses with missing Content-Length header cannot be detected during the file download
                        // because $progress['size_download'] refers to the gzipped size downloaded, not the actual file size
                        if ($contents !== \false && Platform::strlen($contents) >= $maxFileSize) {
                            throw new MaxFileSizeExceededException('Maximum allowed download size reached. Downloaded ' . Platform::strlen($contents) . ' of allowed ' . $maxFileSize . ' bytes');
                        }
                    } else {
                        $contents = stream_get_contents($job['bodyHandle']);
                    }
                    $response = new \Composer\Util\Http\CurlResponse(['url' => $job['url']], $statusCode, $headers, $contents, $progress);
                    $this->io->writeError('[' . $statusCode . '] ' . Url::sanitize($job['url']), \true, IOInterface::DEBUG);
                }
                fclose($job['bodyHandle']);
                if ($response->getStatusCode() >= 300 && $response->getHeader('content-type') === 'application/json') {
                    HttpDownloader::outputWarnings($this->io, $job['origin'], json_decode($response->getBody(), \true));
                }
                $result = $this->isAuthenticatedRetryNeeded($job, $response);
                if ($result['retry']) {
                    $this->restartJob($job, $job['url'], ['storeAuth' => $result['storeAuth'], 'retries' => $job['attributes']['retries'] + 1]);
                    continue;
                }
                // handle 3xx redirects, 304 Not Modified is excluded
                if ($statusCode >= 300 && $statusCode <= 399 && $statusCode !== 304 && $job['attributes']['redirects'] < $this->maxRedirects) {
                    $location = $this->handleRedirect($job, $response);
                    if ($location) {
                        $this->restartJob($job, $location, ['redirects' => $job['attributes']['redirects'] + 1]);
                        continue;
                    }
                }
                // fail 4xx and 5xx responses and capture the response
                if ($statusCode >= 400 && $statusCode <= 599) {
                    if ((!isset($job['options']['http']['method']) || $job['options']['http']['method'] === 'GET') && in_array($statusCode, [423, 425, 500, 502, 503, 504, 507, 510], \true) && $job['attributes']['retries'] < $this->maxRetries) {
                        $this->io->writeError('Retrying (' . ($job['attributes']['retries'] + 1) . ') ' . Url::sanitize($job['url']) . ' due to status code ' . $statusCode, \true, IOInterface::DEBUG);
                        $this->restartJobWithDelay($job, $job['url'], ['retries' => $job['attributes']['retries'] + 1]);
                        continue;
                    }
                    throw $this->failResponse($job, $response, $response->getStatusMessage());
                }
                if ($job['attributes']['storeAuth'] !== \false) {
                    $this->authHelper->storeAuth($job['origin'], $job['attributes']['storeAuth']);
                }
                // resolve promise
                if (null !== $job['filename']) {
                    rename($job['filename'] . '~', $job['filename']);
                    $job['resolve']($response);
                } else {
                    $job['resolve']($response);
                }
            } catch (\Exception $e) {
                if ($e instanceof TransportException) {
                    if (null !== $headers) {
                        $e->setHeaders($headers);
                        $e->setStatusCode($statusCode);
                    }
                    if (null !== $response) {
                        $e->setResponse($response->getBody());
                    }
                    $e->setResponseInfo($progress);
                }
                $this->rejectJob($job, $e);
            }
        }
        foreach ($this->jobs as $i => $curlHandle) {
            $curlHandle = $this->jobs[$i]['curlHandle'];
            $progress = array_diff_key(curl_getinfo($curlHandle), self::$timeInfo);
            if ($this->jobs[$i]['progress'] !== $progress) {
                $this->jobs[$i]['progress'] = $progress;
                if (isset($this->jobs[$i]['options']['max_file_size'])) {
                    // Compare max_file_size with the content-length header this value will be -1 until the header is parsed
                    if ($this->jobs[$i]['options']['max_file_size'] < $progress['download_content_length']) {
                        $this->rejectJob($this->jobs[$i], new MaxFileSizeExceededException('Maximum allowed download size reached. Content-length header indicates ' . $progress['download_content_length'] . ' bytes. Allowed ' . $this->jobs[$i]['options']['max_file_size'] . ' bytes'));
                    }
                    // Compare max_file_size with the download size in bytes
                    if ($this->jobs[$i]['options']['max_file_size'] < $progress['size_download']) {
                        $this->rejectJob($this->jobs[$i], new MaxFileSizeExceededException('Maximum allowed download size reached. Downloaded ' . $progress['size_download'] . ' of allowed ' . $this->jobs[$i]['options']['max_file_size'] . ' bytes'));
                    }
                }
                if (isset($progress['primary_ip']) && $progress['primary_ip'] !== $this->jobs[$i]['primaryIp']) {
                    if (isset($this->jobs[$i]['options']['prevent_ip_access_callable']) && is_callable($this->jobs[$i]['options']['prevent_ip_access_callable']) && $this->jobs[$i]['options']['prevent_ip_access_callable']($progress['primary_ip'])) {
                        $this->rejectJob($this->jobs[$i], new TransportException(sprintf('IP "%s" is blocked for "%s".', $progress['primary_ip'], $progress['url'])));
                    }
                    $this->jobs[$i]['primaryIp'] = (string) $progress['primary_ip'];
                }
                // TODO progress
            }
        }
    }
    /**
     * @param  Job    $job
     */
    private function handleRedirect(array $job, \Composer\Util\Http\Response $response): string
    {
        if ($locationHeader = $response->getHeader('location')) {
            if (parse_url($locationHeader, \PHP_URL_SCHEME)) {
                // Absolute URL; e.g. https://example.com/composer
                $targetUrl = $locationHeader;
            } elseif (parse_url($locationHeader, \PHP_URL_HOST)) {
                // Scheme relative; e.g. //example.com/foo
                $targetUrl = parse_url($job['url'], \PHP_URL_SCHEME) . ':' . $locationHeader;
            } elseif ('/' === $locationHeader[0]) {
                // Absolute path; e.g. /foo
                $urlHost = parse_url($job['url'], \PHP_URL_HOST);
                // Replace path using hostname as an anchor.
                $targetUrl = Preg::replace('{^(.+(?://|@)' . preg_quote($urlHost) . '(?::\d+)?)(?:[/\?].*)?$}', '\1' . $locationHeader, $job['url']);
            } else {
                // Relative path; e.g. foo
                // This actually differs from PHP which seems to add duplicate slashes.
                $targetUrl = Preg::replace('{^(.+/)[^/?]*(?:\?.*)?$}', '\1' . $locationHeader, $job['url']);
            }
        }
        if (!empty($targetUrl)) {
            $this->io->writeError(sprintf('Following redirect (%u) %s', $job['attributes']['redirects'] + 1, Url::sanitize($targetUrl)), \true, IOInterface::DEBUG);
            return $targetUrl;
        }
        throw new TransportException('The "' . $job['url'] . '" file could not be downloaded, got redirect without Location (' . $response->getStatusMessage() . ')');
    }
    /**
     * @param  Job                                          $job
     * @return array{retry: bool, storeAuth: 'prompt'|bool}
     */
    private function isAuthenticatedRetryNeeded(array $job, \Composer\Util\Http\Response $response): array
    {
        if (in_array($response->getStatusCode(), [401, 403]) && $job['attributes']['retryAuthFailure']) {
            $result = $this->authHelper->promptAuthIfNeeded($job['url'], $job['origin'], $response->getStatusCode(), $response->getStatusMessage(), $response->getHeaders(), $job['attributes']['retries'], $response->getBody());
            if ($result['retry']) {
                return $result;
            }
        }
        $locationHeader = $response->getHeader('location');
        $needsAuthRetry = \false;
        // check for bitbucket login page asking to authenticate
        if ($job['origin'] === 'bitbucket.org' && !$this->authHelper->isPublicBitBucketDownload($job['url']) && substr($job['url'], -4) === '.zip' && (!$locationHeader || substr($locationHeader, -4) !== '.zip') && Preg::isMatch('{^text/html\b}i', $response->getHeader('content-type'))) {
            $needsAuthRetry = 'Bitbucket requires authentication and it was not provided';
        }
        // check for gitlab 404 when downloading archives
        if ($response->getStatusCode() === 404 && in_array($job['origin'], $this->config->get('gitlab-domains'), \true) && \false !== strpos($job['url'], 'archive.zip')) {
            $needsAuthRetry = 'GitLab requires authentication and it was not provided';
        }
        if ($needsAuthRetry) {
            if ($job['attributes']['retryAuthFailure']) {
                $result = $this->authHelper->promptAuthIfNeeded($job['url'], $job['origin'], 401, null, [], $job['attributes']['retries']);
                if ($result['retry']) {
                    return $result;
                }
            }
            throw $this->failResponse($job, $response, $needsAuthRetry);
        }
        return ['retry' => \false, 'storeAuth' => \false];
    }
    /**
     * @param  Job    $job
     * @param non-empty-string $url
     *
     * @param  array{retryAuthFailure?: bool, redirects?: int<0, max>, storeAuth?: 'prompt'|bool, retries?: int<1, max>, ipResolve?: 4|6} $attributes
     */
    private function restartJob(array $job, string $url, array $attributes = []): void
    {
        if (null !== $job['filename']) {
            @unlink($job['filename'] . '~');
        }
        $attributes = array_merge($job['attributes'], $attributes);
        $origin = Url::getOrigin($this->config, $url);
        $this->initDownload($job['resolve'], $job['reject'], $origin, $url, $job['options'], $job['filename'], $attributes);
    }
    /**
     * @param  Job    $job
     * @param non-empty-string $url
     *
     * @param  array{retryAuthFailure?: bool, redirects?: int<0, max>, storeAuth?: 'prompt'|bool, retries: int<1, max>, ipResolve?: 4|6} $attributes
     */
    private function restartJobWithDelay(array $job, string $url, array $attributes): void
    {
        if ($attributes['retries'] >= 3) {
            usleep(500000);
            // half a second delay for 3rd retry and beyond
        } elseif ($attributes['retries'] >= 2) {
            usleep(100000);
            // 100ms delay for 2nd retry
        }
        // no sleep for the first retry
        $this->restartJob($job, $url, $attributes);
    }
    /**
     * @param  Job                $job
     */
    private function failResponse(array $job, \Composer\Util\Http\Response $response, string $errorMessage): TransportException
    {
        if (null !== $job['filename']) {
            @unlink($job['filename'] . '~');
        }
        $details = '';
        if (in_array(strtolower((string) $response->getHeader('content-type')), ['application/json', 'application/json; charset=utf-8'], \true)) {
            $details = ':' . \PHP_EOL . substr($response->getBody(), 0, 200) . (strlen($response->getBody()) > 200 ? '...' : '');
        }
        return new TransportException('The "' . $job['url'] . '" file could not be downloaded (' . $errorMessage . ')' . $details, $response->getStatusCode());
    }
    /**
     * @param  Job                $job
     */
    private function rejectJob(array $job, \Exception $e): void
    {
        if (is_resource($job['headerHandle'])) {
            fclose($job['headerHandle']);
        }
        if (is_resource($job['bodyHandle'])) {
            fclose($job['bodyHandle']);
        }
        if (null !== $job['filename']) {
            @unlink($job['filename'] . '~');
        }
        $job['reject']($e);
    }
    private function checkCurlResult(int $code): void
    {
        if ($code !== \CURLM_OK && $code !== \CURLM_CALL_MULTI_PERFORM) {
            throw new \RuntimeException(isset($this->multiErrors[$code]) ? "cURL error: {$code} ({$this->multiErrors[$code][0]}): cURL message: {$this->multiErrors[$code][1]}" : 'Unexpected cURL error: ' . $code);
        }
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer\Util\Http;

/**
 * @phpstan-type CurlInfo array{url: mixed, content_type: mixed, http_code: mixed, header_size: mixed, request_size: mixed, filetime: mixed, ssl_verify_result: mixed, redirect_count: mixed, total_time: mixed, namelookup_time: mixed, connect_time: mixed, pretransfer_time: mixed, size_upload: mixed, size_download: mixed, speed_download: mixed, speed_upload: mixed, download_content_length: mixed, upload_content_length: mixed, starttransfer_time: mixed, redirect_time: mixed, certinfo: mixed, primary_ip: mixed, primary_port: mixed, local_ip: mixed, local_port: mixed, redirect_url: mixed}
 */
class CurlResponse extends \Composer\Util\Http\Response
{
    /**
     * @see https://www.php.net/curl_getinfo
     * @var array
     * @phpstan-var CurlInfo
     */
    private $curlInfo;
    /**
     * @phpstan-param CurlInfo $curlInfo
     */
    public function __construct(array $request, ?int $code, array $headers, ?string $body, array $curlInfo)
    {
        parent::__construct($request, $code, $headers, $body);
        $this->curlInfo = $curlInfo;
    }
    /**
     * @phpstan-return CurlInfo
     */
    public function getCurlInfo(): array
    {
        return $this->curlInfo;
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer\Util\Http;

/**
 * @internal
 * @author John Stevenson <john-stevenson@blueyonder.co.uk>
 */
class ProxyItem
{
    /** @var non-empty-string */
    private $url;
    /** @var non-empty-string */
    private $safeUrl;
    /** @var ?non-empty-string */
    private $curlAuth;
    /** @var string */
    private $optionsProxy;
    /** @var ?non-empty-string */
    private $optionsAuth;
    /**
     * @param string $proxyUrl The value from the environment
     * @param string $envName The name of the environment variable
     * @throws \RuntimeException If the proxy url is invalid
     */
    public function __construct(string $proxyUrl, string $envName)
    {
        $syntaxError = sprintf('unsupported `%s` syntax', $envName);
        if (strpbrk($proxyUrl, "\r\n\t") !== \false) {
            throw new \RuntimeException($syntaxError);
        }
        if (\false === $proxy = parse_url($proxyUrl)) {
            throw new \RuntimeException($syntaxError);
        }
        if (!isset($proxy['host'])) {
            throw new \RuntimeException('unable to find proxy host in ' . $envName);
        }
        $scheme = isset($proxy['scheme']) ? strtolower($proxy['scheme']) . '://' : 'http://';
        $safe = '';
        if (isset($proxy['user'])) {
            $safe = '***';
            $user = $proxy['user'];
            $auth = rawurldecode($proxy['user']);
            if (isset($proxy['pass'])) {
                $safe .= ':***';
                $user .= ':' . $proxy['pass'];
                $auth .= ':' . rawurldecode($proxy['pass']);
            }
            $safe .= '@';
            if (strlen($user) > 0) {
                $this->curlAuth = $user;
                $this->optionsAuth = 'Proxy-Authorization: Basic ' . base64_encode($auth);
            }
        }
        $host = $proxy['host'];
        $port = null;
        if (isset($proxy['port'])) {
            $port = $proxy['port'];
        } elseif ($scheme === 'http://') {
            $port = 80;
        } elseif ($scheme === 'https://') {
            $port = 443;
        }
        // We need a port because curl uses 1080 for http. Port 0 is reserved,
        // but is considered valid depending on the PHP or Curl version.
        if ($port === null) {
            throw new \RuntimeException('unable to find proxy port in ' . $envName);
        }
        if ($port === 0) {
            throw new \RuntimeException('port 0 is reserved in ' . $envName);
        }
        $this->url = sprintf('%s%s:%d', $scheme, $host, $port);
        $this->safeUrl = sprintf('%s%s%s:%d', $scheme, $safe, $host, $port);
        $scheme = str_replace(['http://', 'https://'], ['tcp://', 'ssl://'], $scheme);
        $this->optionsProxy = sprintf('%s%s:%d', $scheme, $host, $port);
    }
    /**
     * Returns a RequestProxy instance for the scheme of the request url
     *
     * @param string $scheme The scheme of the request url
     */
    public function toRequestProxy(string $scheme): \Composer\Util\Http\RequestProxy
    {
        $options = ['http' => ['proxy' => $this->optionsProxy]];
        if ($this->optionsAuth !== null) {
            $options['http']['header'] = $this->optionsAuth;
        }
        if ($scheme === 'http') {
            $options['http']['request_fulluri'] = \true;
        }
        return new \Composer\Util\Http\RequestProxy($this->url, $this->curlAuth, $options, $this->safeUrl);
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer\Util;

@trigger_error('Composer\Util\MetadataMinifier is deprecated, use Composer\MetadataMinifier\MetadataMinifier from composer/metadata-minifier instead.', \E_USER_DEPRECATED);
/**
 * @deprecated Use Composer\MetadataMinifier\MetadataMinifier instead
 */
class MetadataMinifier extends \Composer\MetadataMinifier\MetadataMinifier
{
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer\Util;

use Composer\IO\IOInterface;
use Composer\Pcre\Preg;
use _ContaoManager\Seld\Signal\SignalHandler;
use _ContaoManager\Symfony\Component\Process\Exception\ProcessSignaledException;
use _ContaoManager\Symfony\Component\Process\Process;
use _ContaoManager\Symfony\Component\Process\Exception\RuntimeException;
use React\Promise\Promise;
use React\Promise\PromiseInterface;
use _ContaoManager\Symfony\Component\Process\ExecutableFinder;
/**
 * @author Robert Schönthal <seroscho@googlemail.com>
 * @author Jordi Boggiano <j.boggiano@seld.be>
 */
class ProcessExecutor
{
    private const STATUS_QUEUED = 1;
    private const STATUS_STARTED = 2;
    private const STATUS_COMPLETED = 3;
    private const STATUS_FAILED = 4;
    private const STATUS_ABORTED = 5;
    private const BUILTIN_CMD_COMMANDS = ['assoc', 'break', 'call', 'cd', 'chdir', 'cls', 'color', 'copy', 'date', 'del', 'dir', 'echo', 'endlocal', 'erase', 'exit', 'for', 'ftype', 'goto', 'help', 'if', 'label', 'md', 'mkdir', 'mklink', 'move', 'path', 'pause', 'popd', 'prompt', 'pushd', 'rd', 'rem', 'ren', 'rename', 'rmdir', 'set', 'setlocal', 'shift', 'start', 'time', 'title', 'type', 'ver', 'vol'];
    private const GIT_CMDS_NEED_GIT_DIR = [['show'], ['log'], ['branch'], ['remote', 'set-url']];
    /** @var int */
    protected static $timeout = 300;
    /** @var bool */
    protected $captureOutput = \false;
    /** @var string */
    protected $errorOutput = '';
    /** @var ?IOInterface */
    protected $io;
    /**
     * @phpstan-var array<int, array<string, mixed>>
     */
    private $jobs = [];
    /** @var int */
    private $runningJobs = 0;
    /** @var int */
    private $maxJobs = 10;
    /** @var int */
    private $idGen = 0;
    /** @var bool */
    private $allowAsync = \false;
    /** @var array<string, string> */
    private static $executables = [];
    public function __construct(?IOInterface $io = null)
    {
        $this->io = $io;
        $this->resetMaxJobs();
    }
    /**
     * runs a process on the commandline
     *
     * @param  string|non-empty-list<string> $command the command to execute
     * @param  mixed   $output  the output will be written into this var if passed by ref
     *                          if a callable is passed it will be used as output handler
     * @param  null|string $cwd     the working directory
     * @return int     statuscode
     */
    public function execute($command, &$output = null, ?string $cwd = null): int
    {
        if (func_num_args() > 1) {
            return $this->doExecute($command, $cwd, \false, $output);
        }
        return $this->doExecute($command, $cwd, \false);
    }
    /**
     * runs a process on the commandline in TTY mode
     *
     * @param  string|non-empty-list<string>  $command the command to execute
     * @param  null|string $cwd     the working directory
     * @return int     statuscode
     */
    public function executeTty($command, ?string $cwd = null): int
    {
        if (\Composer\Util\Platform::isTty()) {
            return $this->doExecute($command, $cwd, \true);
        }
        return $this->doExecute($command, $cwd, \false);
    }
    /**
     * @param  string|non-empty-list<string> $command
     * @param  array<string, string>|null $env
     * @param  mixed   $output
     */
    private function runProcess($command, ?string $cwd, ?array $env, bool $tty, &$output = null): ?int
    {
        // On Windows, we don't rely on the OS to find the executable if possible to avoid lookups
        // in the current directory which could be untrusted. Instead we use the ExecutableFinder.
        if (is_string($command)) {
            if (\Composer\Util\Platform::isWindows() && Preg::isMatch('{^([^:/\\\\]++) }', $command, $match)) {
                $command = substr_replace($command, self::escape(self::getExecutable($match[1])), 0, strlen($match[1]));
            }
            $process = Process::fromShellCommandline($command, $cwd, $env, null, static::getTimeout());
        } else {
            if (\Composer\Util\Platform::isWindows() && \strlen($command[0]) === strcspn($command[0], ':/\\')) {
                $command[0] = self::getExecutable($command[0]);
            }
            $process = new Process($command, $cwd, $env, null, static::getTimeout());
        }
        if (!\Composer\Util\Platform::isWindows() && $tty) {
            try {
                $process->setTty(\true);
            } catch (RuntimeException $e) {
                // ignore TTY enabling errors
            }
        }
        $callback = is_callable($output) ? $output : function (string $type, string $buffer): void {
            $this->outputHandler($type, $buffer);
        };
        $signalHandler = SignalHandler::create([SignalHandler::SIGINT, SignalHandler::SIGTERM, SignalHandler::SIGHUP], function (string $signal) {
            if ($this->io !== null) {
                $this->io->writeError('Received ' . $signal . ', aborting when child process is done', \true, IOInterface::DEBUG);
            }
        });
        try {
            $process->run($callback);
            if ($this->captureOutput && !is_callable($output)) {
                $output = $process->getOutput();
            }
            $this->errorOutput = $process->getErrorOutput();
        } catch (ProcessSignaledException $e) {
            if ($signalHandler->isTriggered()) {
                // exiting as we were signaled and the child process exited too due to the signal
                $signalHandler->exitWithLastSignal();
            }
        } finally {
            $signalHandler->unregister();
        }
        return $process->getExitCode();
    }
    /**
     * @param  string|non-empty-list<string> $command
     * @param  mixed   $output
     */
    private function doExecute($command, ?string $cwd, bool $tty, &$output = null): int
    {
        $this->outputCommandRun($command, $cwd, \false);
        $this->captureOutput = func_num_args() > 3;
        $this->errorOutput = '';
        $env = null;
        $requiresGitDirEnv = $this->requiresGitDirEnv($command);
        if ($cwd !== null && $requiresGitDirEnv) {
            $isBareRepository = !is_dir(sprintf('%s/.git', rtrim($cwd, '/')));
            if ($isBareRepository) {
                $configValue = '';
                $this->runProcess(['git', 'config', 'safe.bareRepository'], $cwd, ['GIT_DIR' => $cwd], $tty, $configValue);
                $configValue = trim($configValue);
                if ($configValue === 'explicit') {
                    $env = ['GIT_DIR' => $cwd];
                }
            }
        }
        return $this->runProcess($command, $cwd, $env, $tty, $output);
    }
    /**
     * starts a process on the commandline in async mode
     *
     * @param  string|list<string> $command the command to execute
     * @param  string              $cwd     the working directory
     * @phpstan-return PromiseInterface<Process>
     */
    public function executeAsync($command, ?string $cwd = null): PromiseInterface
    {
        if (!$this->allowAsync) {
            throw new \LogicException('You must use the ProcessExecutor instance which is part of a Composer\Loop instance to be able to run async processes');
        }
        $job = ['id' => $this->idGen++, 'status' => self::STATUS_QUEUED, 'command' => $command, 'cwd' => $cwd];
        $resolver = static function ($resolve, $reject) use (&$job): void {
            $job['status'] = \Composer\Util\ProcessExecutor::STATUS_QUEUED;
            $job['resolve'] = $resolve;
            $job['reject'] = $reject;
        };
        $canceler = static function () use (&$job): void {
            if ($job['status'] === \Composer\Util\ProcessExecutor::STATUS_QUEUED) {
                $job['status'] = \Composer\Util\ProcessExecutor::STATUS_ABORTED;
            }
            if ($job['status'] !== \Composer\Util\ProcessExecutor::STATUS_STARTED) {
                return;
            }
            $job['status'] = \Composer\Util\ProcessExecutor::STATUS_ABORTED;
            try {
                if (defined('SIGINT')) {
                    $job['process']->signal(\SIGINT);
                }
            } catch (\Exception $e) {
                // signal can throw in various conditions, but we don't care if it fails
            }
            $job['process']->stop(1);
            throw new \RuntimeException('Aborted process');
        };
        $promise = new Promise($resolver, $canceler);
        $promise = $promise->then(function () use (&$job) {
            if ($job['process']->isSuccessful()) {
                $job['status'] = \Composer\Util\ProcessExecutor::STATUS_COMPLETED;
            } else {
                $job['status'] = \Composer\Util\ProcessExecutor::STATUS_FAILED;
            }
            $this->markJobDone();
            return $job['process'];
        }, function ($e) use (&$job): void {
            $job['status'] = \Composer\Util\ProcessExecutor::STATUS_FAILED;
            $this->markJobDone();
            throw $e;
        });
        $this->jobs[$job['id']] =& $job;
        if ($this->runningJobs < $this->maxJobs) {
            $this->startJob($job['id']);
        }
        return $promise;
    }
    protected function outputHandler(string $type, string $buffer): void
    {
        if ($this->captureOutput) {
            return;
        }
        if (null === $this->io) {
            echo $buffer;
            return;
        }
        if (Process::ERR === $type) {
            $this->io->writeErrorRaw($buffer, \false);
        } else {
            $this->io->writeRaw($buffer, \false);
        }
    }
    private function startJob(int $id): void
    {
        $job =& $this->jobs[$id];
        if ($job['status'] !== self::STATUS_QUEUED) {
            return;
        }
        // start job
        $job['status'] = self::STATUS_STARTED;
        $this->runningJobs++;
        $command = $job['command'];
        $cwd = $job['cwd'];
        $this->outputCommandRun($command, $cwd, \true);
        try {
            if (is_string($command)) {
                $process = Process::fromShellCommandline($command, $cwd, null, null, static::getTimeout());
            } else {
                $process = new Process($command, $cwd, null, null, static::getTimeout());
            }
        } catch (\Throwable $e) {
            $job['reject']($e);
            return;
        }
        $job['process'] = $process;
        try {
            $process->start();
        } catch (\Throwable $e) {
            $job['reject']($e);
            return;
        }
    }
    public function setMaxJobs(int $maxJobs): void
    {
        $this->maxJobs = $maxJobs;
    }
    public function resetMaxJobs(): void
    {
        if (is_numeric($maxJobs = \Composer\Util\Platform::getEnv('COMPOSER_MAX_PARALLEL_PROCESSES'))) {
            $this->maxJobs = max(1, min(50, (int) $maxJobs));
        } else {
            $this->maxJobs = 10;
        }
    }
    /**
     * @param  ?int $index job id
     */
    public function wait($index = null): void
    {
        while (\true) {
            if (0 === $this->countActiveJobs($index)) {
                return;
            }
            usleep(1000);
        }
    }
    /**
     * @internal
     */
    public function enableAsync(): void
    {
        $this->allowAsync = \true;
    }
    /**
     * @internal
     *
     * @param  ?int $index job id
     * @return int         number of active (queued or started) jobs
     */
    public function countActiveJobs($index = null): int
    {
        // tick
        foreach ($this->jobs as $job) {
            if ($job['status'] === self::STATUS_STARTED) {
                if (!$job['process']->isRunning()) {
                    call_user_func($job['resolve'], $job['process']);
                }
                $job['process']->checkTimeout();
            }
            if ($this->runningJobs < $this->maxJobs) {
                if ($job['status'] === self::STATUS_QUEUED) {
                    $this->startJob($job['id']);
                }
            }
        }
        if (null !== $index) {
            return $this->jobs[$index]['status'] < self::STATUS_COMPLETED ? 1 : 0;
        }
        $active = 0;
        foreach ($this->jobs as $job) {
            if ($job['status'] < self::STATUS_COMPLETED) {
                $active++;
            } else {
                unset($this->jobs[$job['id']]);
            }
        }
        return $active;
    }
    private function markJobDone(): void
    {
        $this->runningJobs--;
    }
    /**
     * @return string[]
     */
    public function splitLines(?string $output): array
    {
        $output = trim((string) $output);
        return $output === '' ? [] : Preg::split('{\r?\n}', $output);
    }
    /**
     * Get any error output from the last command
     */
    public function getErrorOutput(): string
    {
        return $this->errorOutput;
    }
    /**
     * @return int the timeout in seconds
     */
    public static function getTimeout(): int
    {
        return static::$timeout;
    }
    /**
     * @param  int  $timeout the timeout in seconds
     */
    public static function setTimeout(int $timeout): void
    {
        static::$timeout = $timeout;
    }
    /**
     * Escapes a string to be used as a shell argument.
     *
     * @param string|false|null $argument The argument that will be escaped
     *
     * @return string The escaped argument
     */
    public static function escape($argument): string
    {
        return self::escapeArgument($argument);
    }
    /**
     * @param string|list<string> $command
     */
    private function outputCommandRun($command, ?string $cwd, bool $async): void
    {
        if (null === $this->io || !$this->io->isDebug()) {
            return;
        }
        $commandString = is_string($command) ? $command : implode(' ', array_map(self::class . '::escape', $command));
        $safeCommand = Preg::replaceCallback('{://(?P<user>[^:/\s]+):(?P<password>[^@\s/]+)@}i', static function ($m): string {
            // if the username looks like a long (12char+) hex string, or a modern github token (e.g. ghp_xxx, github_pat_xxx) we obfuscate that
            if (Preg::isMatch(\Composer\Util\GitHub::GITHUB_TOKEN_REGEX, $m['user'])) {
                return '://***:***@';
            }
            if (Preg::isMatch('{^[a-f0-9]{12,}$}', $m['user'])) {
                return '://***:***@';
            }
            return '://' . $m['user'] . ':***@';
        }, $commandString);
        $safeCommand = Preg::replace("{--password (.*[^\\\\]\\') }", '--password \'***\' ', $safeCommand);
        $this->io->writeError('Executing' . ($async ? ' async' : '') . ' command (' . ($cwd ?: 'CWD') . '): ' . $safeCommand);
    }
    /**
     * Escapes a string to be used as a shell argument for Symfony Process.
     *
     * This method expects cmd.exe to be started with the /V:ON option, which
     * enables delayed environment variable expansion using ! as the delimiter.
     * If this is not the case, any escaped ^^!var^^! will be transformed to
     * ^!var^! and introduce two unintended carets.
     *
     * Modified from https://github.com/johnstevenson/winbox-args
     * MIT Licensed (c) John Stevenson <john-stevenson@blueyonder.co.uk>
     *
     * @param string|false|null $argument
     */
    private static function escapeArgument($argument): string
    {
        if ('' === $argument = (string) $argument) {
            return escapeshellarg($argument);
        }
        if (!\Composer\Util\Platform::isWindows()) {
            return "'" . str_replace("'", "'\\''", $argument) . "'";
        }
        // New lines break cmd.exe command parsing
        // and special chars like the fullwidth quote can be used to break out
        // of parameter encoding via "Best Fit" encoding conversion
        $argument = strtr($argument, ["\n" => ' ', "＂" => '"', "ʺ" => '"', "〝" => '"', "〞" => '"', "̎" => '"', "：" => ':', "։" => ':', "∶" => ':', "／" => '/', "⁄" => '/', "∕" => '/', "´" => '/']);
        // In addition to whitespace, commas need quoting to preserve paths
        $quote = strpbrk($argument, " \t,") !== \false;
        $argument = Preg::replace('/(\\\\*)"/', '$1$1\"', $argument, -1, $dquotes);
        $meta = $dquotes > 0 || Preg::isMatch('/%[^%]+%|![^!]+!/', $argument);
        if (!$meta && !$quote) {
            $quote = strpbrk($argument, '^&|<>()') !== \false;
        }
        if ($quote) {
            $argument = '"' . Preg::replace('/(\\\\*)$/', '$1$1', $argument) . '"';
        }
        if ($meta) {
            $argument = Preg::replace('/(["^&|<>()%])/', '^$1', $argument);
            $argument = Preg::replace('/(!)/', '^^$1', $argument);
        }
        return $argument;
    }
    /**
     * @param string[]|string $command
     */
    public function requiresGitDirEnv($command): bool
    {
        $cmd = !is_array($command) ? explode(' ', $command) : $command;
        if ($cmd[0] !== 'git') {
            return \false;
        }
        foreach (self::GIT_CMDS_NEED_GIT_DIR as $gitCmd) {
            if (array_intersect($cmd, $gitCmd) === $gitCmd) {
                return \true;
            }
        }
        return \false;
    }
    /**
     * Resolves executable paths on Windows
     */
    private static function getExecutable(string $name): string
    {
        if (\in_array(strtolower($name), self::BUILTIN_CMD_COMMANDS, \true)) {
            return $name;
        }
        if (!isset(self::$executables[$name])) {
            $path = (new ExecutableFinder())->find($name, $name);
            if ($path !== null) {
                self::$executables[$name] = $path;
            }
        }
        return self::$executables[$name] ?? $name;
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer\Util;

use Composer\Config;
use Composer\IO\IOInterface;
use Composer\Pcre\Preg;
/**
 * @author Jonas Renaudot <jonas.renaudot@gmail.com>
 */
class Hg
{
    /** @var string|false|null */
    private static $version = \false;
    /**
     * @var IOInterface
     */
    private $io;
    /**
     * @var Config
     */
    private $config;
    /**
     * @var ProcessExecutor
     */
    private $process;
    public function __construct(IOInterface $io, Config $config, \Composer\Util\ProcessExecutor $process)
    {
        $this->io = $io;
        $this->config = $config;
        $this->process = $process;
    }
    public function runCommand(callable $commandCallable, string $url, ?string $cwd): void
    {
        $this->config->prohibitUrlByConfig($url, $this->io);
        // Try as is
        $command = $commandCallable($url);
        if (0 === $this->process->execute($command, $ignoredOutput, $cwd)) {
            return;
        }
        // Try with the authentication information available
        if (Preg::isMatch('{^(?P<proto>ssh|https?)://(?:(?P<user>[^:@]+)(?::(?P<pass>[^:@]+))?@)?(?P<host>[^/]+)(?P<path>/.*)?}mi', $url, $matches) && $this->io->hasAuthentication($matches['host'])) {
            if ($matches['proto'] === 'ssh') {
                $user = '';
                if ($matches['user'] !== null) {
                    $user = rawurlencode($matches['user']) . '@';
                }
                $authenticatedUrl = $matches['proto'] . '://' . $user . $matches['host'] . $matches['path'];
            } else {
                $auth = $this->io->getAuthentication($matches['host']);
                $authenticatedUrl = $matches['proto'] . '://' . rawurlencode((string) $auth['username']) . ':' . rawurlencode((string) $auth['password']) . '@' . $matches['host'] . $matches['path'];
            }
            $command = $commandCallable($authenticatedUrl);
            if (0 === $this->process->execute($command, $ignoredOutput, $cwd)) {
                return;
            }
            $error = $this->process->getErrorOutput();
        } else {
            $error = 'The given URL (' . $url . ') does not match the required format (ssh|http(s)://(username:password@)example.com/path-to-repository)';
        }
        $this->throwException("Failed to clone {$url}, \n\n" . $error, $url);
    }
    /**
     * @param non-empty-string $message
     *
     * @return never
     */
    private function throwException($message, string $url): void
    {
        if (null === self::getVersion($this->process)) {
            throw new \RuntimeException(\Composer\Util\Url::sanitize('Failed to clone ' . $url . ', hg was not found, check that it is installed and in your PATH env.' . "\n\n" . $this->process->getErrorOutput()));
        }
        throw new \RuntimeException(\Composer\Util\Url::sanitize($message));
    }
    /**
     * Retrieves the current hg version.
     *
     * @return string|null The hg version number, if present.
     */
    public static function getVersion(\Composer\Util\ProcessExecutor $process): ?string
    {
        if (\false === self::$version) {
            self::$version = null;
            if (0 === $process->execute(['hg', '--version'], $output) && Preg::isMatch('/^.+? (\d+(?:\.\d+)+)(?:\+.*?)?\)?\r?\n/', $output, $matches)) {
                self::$version = $matches[1];
            }
        }
        return self::$version;
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer\Util;

use Closure;
use Composer\Config;
use Composer\Downloader\MaxFileSizeExceededException;
use Composer\IO\IOInterface;
use Composer\Downloader\TransportException;
use Composer\Pcre\Preg;
use Composer\Util\Http\Response;
use Composer\Util\Http\ProxyManager;
/**
 * @internal
 * @author François Pluchino <francois.pluchino@opendisplay.com>
 * @author Jordi Boggiano <j.boggiano@seld.be>
 * @author Nils Adermann <naderman@naderman.de>
 */
class RemoteFilesystem
{
    /** @var IOInterface */
    private $io;
    /** @var Config */
    private $config;
    /** @var string */
    private $scheme;
    /** @var int */
    private $bytesMax;
    /** @var string */
    private $originUrl;
    /** @var non-empty-string */
    private $fileUrl;
    /** @var ?string */
    private $fileName;
    /** @var bool */
    private $retry = \false;
    /** @var bool */
    private $progress;
    /** @var ?int */
    private $lastProgress;
    /** @var mixed[] */
    private $options = [];
    /** @var bool */
    private $disableTls = \false;
    /** @var list<string> */
    private $lastHeaders;
    /** @var bool */
    private $storeAuth = \false;
    /** @var AuthHelper */
    private $authHelper;
    /** @var bool */
    private $degradedMode = \false;
    /** @var int */
    private $redirects;
    /** @var int */
    private $maxRedirects = 20;
    /**
     * Constructor.
     *
     * @param IOInterface $io         The IO instance
     * @param Config      $config     The config
     * @param mixed[]     $options    The options
     */
    public function __construct(IOInterface $io, Config $config, array $options = [], bool $disableTls = \false, ?\Composer\Util\AuthHelper $authHelper = null)
    {
        $this->io = $io;
        // Setup TLS options
        // The cafile option can be set via config.json
        if ($disableTls === \false) {
            $this->options = \Composer\Util\StreamContextFactory::getTlsDefaults($options, $io);
        } else {
            $this->disableTls = \true;
        }
        // handle the other externally set options normally.
        $this->options = array_replace_recursive($this->options, $options);
        $this->config = $config;
        $this->authHelper = $authHelper ?? new \Composer\Util\AuthHelper($io, $config);
    }
    /**
     * Copy the remote file in local.
     *
     * @param string  $originUrl The origin URL
     * @param non-empty-string $fileUrl   The file URL
     * @param string  $fileName  the local filename
     * @param bool    $progress  Display the progression
     * @param mixed[] $options   Additional context options
     *
     * @return bool true
     */
    public function copy(string $originUrl, string $fileUrl, string $fileName, bool $progress = \true, array $options = [])
    {
        return $this->get($originUrl, $fileUrl, $options, $fileName, $progress);
    }
    /**
     * Get the content.
     *
     * @param string  $originUrl The origin URL
     * @param non-empty-string $fileUrl   The file URL
     * @param bool    $progress  Display the progression
     * @param mixed[] $options   Additional context options
     *
     * @return bool|string The content
     */
    public function getContents(string $originUrl, string $fileUrl, bool $progress = \true, array $options = [])
    {
        return $this->get($originUrl, $fileUrl, $options, null, $progress);
    }
    /**
     * Retrieve the options set in the constructor
     *
     * @return mixed[] Options
     */
    public function getOptions()
    {
        return $this->options;
    }
    /**
     * Merges new options
     *
     * @param  mixed[] $options
     * @return void
     */
    public function setOptions(array $options)
    {
        $this->options = array_replace_recursive($this->options, $options);
    }
    /**
     * Check is disable TLS.
     *
     * @return bool
     */
    public function isTlsDisabled()
    {
        return $this->disableTls === \true;
    }
    /**
     * Returns the headers of the last request
     *
     * @return list<string>
     */
    public function getLastHeaders()
    {
        return $this->lastHeaders;
    }
    /**
     * @param  string[] $headers array of returned headers like from getLastHeaders()
     * @return int|null
     */
    public static function findStatusCode(array $headers)
    {
        $value = null;
        foreach ($headers as $header) {
            if (Preg::isMatch('{^HTTP/\S+ (\d+)}i', $header, $match)) {
                // In case of redirects, http_response_headers contains the headers of all responses
                // so we can not return directly and need to keep iterating
                $value = (int) $match[1];
            }
        }
        return $value;
    }
    /**
     * @param  string[]    $headers array of returned headers like from getLastHeaders()
     * @return string|null
     */
    public function findStatusMessage(array $headers)
    {
        $value = null;
        foreach ($headers as $header) {
            if (Preg::isMatch('{^HTTP/\S+ \d+}i', $header)) {
                // In case of redirects, http_response_headers contains the headers of all responses
                // so we can not return directly and need to keep iterating
                $value = $header;
            }
        }
        return $value;
    }
    /**
     * Get file content or copy action.
     *
     * @param string  $originUrl         The origin URL
     * @param non-empty-string $fileUrl  The file URL
     * @param mixed[] $additionalOptions context options
     * @param string  $fileName          the local filename
     * @param bool    $progress          Display the progression
     *
     * @throws TransportException|\Exception
     * @throws TransportException            When the file could not be downloaded
     *
     * @return bool|string
     */
    protected function get(string $originUrl, string $fileUrl, array $additionalOptions = [], ?string $fileName = null, bool $progress = \true)
    {
        $this->scheme = parse_url(strtr($fileUrl, '\\', '/'), \PHP_URL_SCHEME);
        $this->bytesMax = 0;
        $this->originUrl = $originUrl;
        $this->fileUrl = $fileUrl;
        $this->fileName = $fileName;
        $this->progress = $progress;
        $this->lastProgress = null;
        $retryAuthFailure = \true;
        $this->lastHeaders = [];
        $this->redirects = 1;
        // The first request counts.
        $tempAdditionalOptions = $additionalOptions;
        if (isset($tempAdditionalOptions['retry-auth-failure'])) {
            $retryAuthFailure = (bool) $tempAdditionalOptions['retry-auth-failure'];
            unset($tempAdditionalOptions['retry-auth-failure']);
        }
        $isRedirect = \false;
        if (isset($tempAdditionalOptions['redirects'])) {
            $this->redirects = $tempAdditionalOptions['redirects'];
            $isRedirect = \true;
            unset($tempAdditionalOptions['redirects']);
        }
        $options = $this->getOptionsForUrl($originUrl, $tempAdditionalOptions);
        unset($tempAdditionalOptions);
        $origFileUrl = $fileUrl;
        if (isset($options['prevent_ip_access_callable'])) {
            throw new \RuntimeException("RemoteFilesystem doesn't support the 'prevent_ip_access_callable' config.");
        }
        if (isset($options['gitlab-token'])) {
            $fileUrl .= (\false === strpos($fileUrl, '?') ? '?' : '&') . 'access_token=' . $options['gitlab-token'];
            unset($options['gitlab-token']);
        }
        if (isset($options['http'])) {
            $options['http']['ignore_errors'] = \true;
        }
        if ($this->degradedMode && strpos($fileUrl, 'http://repo.packagist.org/') === 0) {
            // access packagist using the resolved IPv4 instead of the hostname to force IPv4 protocol
            $fileUrl = 'http://' . gethostbyname('repo.packagist.org') . substr($fileUrl, 20);
            $degradedPackagist = \true;
        }
        $maxFileSize = null;
        if (isset($options['max_file_size'])) {
            $maxFileSize = $options['max_file_size'];
            unset($options['max_file_size']);
        }
        $ctx = \Composer\Util\StreamContextFactory::getContext($fileUrl, $options, ['notification' => Closure::fromCallable([$this, 'callbackGet'])]);
        $proxy = ProxyManager::getInstance()->getProxyForRequest($fileUrl);
        $usingProxy = $proxy->getStatus(' using proxy (%s)');
        $this->io->writeError((strpos($origFileUrl, 'http') === 0 ? 'Downloading ' : 'Reading ') . \Composer\Util\Url::sanitize($origFileUrl) . $usingProxy, \true, IOInterface::DEBUG);
        unset($origFileUrl, $proxy, $usingProxy);
        // Check for secure HTTP, but allow insecure Packagist calls to $hashed providers as file integrity is verified with sha256
        if ((!Preg::isMatch('{^http://(repo\.)?packagist\.org/p/}', $fileUrl) || \false === strpos($fileUrl, '$') && \false === strpos($fileUrl, '%24')) && empty($degradedPackagist)) {
            $this->config->prohibitUrlByConfig($fileUrl, $this->io);
        }
        if ($this->progress && !$isRedirect) {
            $this->io->writeError("Downloading (<comment>connecting...</comment>)", \false);
        }
        $errorMessage = '';
        $errorCode = 0;
        $result = \false;
        set_error_handler(static function ($code, $msg) use (&$errorMessage): bool {
            if ($errorMessage) {
                $errorMessage .= "\n";
            }
            $errorMessage .= Preg::replace('{^file_get_contents\(.*?\): }', '', $msg);
            return \true;
        });
        $http_response_header = [];
        try {
            $result = $this->getRemoteContents($originUrl, $fileUrl, $ctx, $http_response_header, $maxFileSize);
            if (!empty($http_response_header[0])) {
                $statusCode = self::findStatusCode($http_response_header);
                if ($statusCode >= 300 && Response::findHeaderValue($http_response_header, 'content-type') === 'application/json') {
                    \Composer\Util\HttpDownloader::outputWarnings($this->io, $originUrl, json_decode($result, \true));
                }
                if (in_array($statusCode, [401, 403]) && $retryAuthFailure) {
                    $this->promptAuthAndRetry($statusCode, $this->findStatusMessage($http_response_header), $http_response_header);
                }
            }
            $contentLength = !empty($http_response_header[0]) ? Response::findHeaderValue($http_response_header, 'content-length') : null;
            if ($contentLength && \Composer\Util\Platform::strlen($result) < $contentLength) {
                // alas, this is not possible via the stream callback because STREAM_NOTIFY_COMPLETED is documented, but not implemented anywhere in PHP
                $e = new TransportException('Content-Length mismatch, received ' . \Composer\Util\Platform::strlen($result) . ' bytes out of the expected ' . $contentLength);
                $e->setHeaders($http_response_header);
                $e->setStatusCode(self::findStatusCode($http_response_header));
                try {
                    $e->setResponse($this->decodeResult($result, $http_response_header));
                } catch (\Exception $discarded) {
                    $e->setResponse($this->normalizeResult($result));
                }
                $this->io->writeError('Content-Length mismatch, received ' . \Composer\Util\Platform::strlen($result) . ' out of ' . $contentLength . ' bytes: (' . base64_encode($result) . ')', \true, IOInterface::DEBUG);
                throw $e;
            }
        } catch (\Exception $e) {
            if ($e instanceof TransportException && !empty($http_response_header[0])) {
                $e->setHeaders($http_response_header);
                $e->setStatusCode(self::findStatusCode($http_response_header));
            }
            if ($e instanceof TransportException && $result !== \false) {
                $e->setResponse($this->decodeResult($result, $http_response_header));
            }
            $result = \false;
        }
        if ($errorMessage && !filter_var(ini_get('allow_url_fopen'), \FILTER_VALIDATE_BOOLEAN)) {
            $errorMessage = 'allow_url_fopen must be enabled in php.ini (' . $errorMessage . ')';
        }
        restore_error_handler();
        if (isset($e) && !$this->retry) {
            if (!$this->degradedMode && \false !== strpos($e->getMessage(), 'Operation timed out')) {
                $this->degradedMode = \true;
                $this->io->writeError('');
                $this->io->writeError(['<error>' . $e->getMessage() . '</error>', '<error>Retrying with degraded mode, check https://getcomposer.org/doc/articles/troubleshooting.md#degraded-mode for more info</error>']);
                return $this->get($this->originUrl, $this->fileUrl, $additionalOptions, $this->fileName, $this->progress);
            }
            throw $e;
        }
        $statusCode = null;
        $contentType = null;
        $locationHeader = null;
        if (!empty($http_response_header[0])) {
            $statusCode = self::findStatusCode($http_response_header);
            $contentType = Response::findHeaderValue($http_response_header, 'content-type');
            $locationHeader = Response::findHeaderValue($http_response_header, 'location');
        }
        // check for bitbucket login page asking to authenticate
        if ($originUrl === 'bitbucket.org' && !$this->authHelper->isPublicBitBucketDownload($fileUrl) && substr($fileUrl, -4) === '.zip' && (!$locationHeader || substr(parse_url($locationHeader, \PHP_URL_PATH), -4) !== '.zip') && $contentType && Preg::isMatch('{^text/html\b}i', $contentType)) {
            $result = \false;
            if ($retryAuthFailure) {
                $this->promptAuthAndRetry(401);
            }
        }
        // check for gitlab 404 when downloading archives
        if ($statusCode === 404 && in_array($originUrl, $this->config->get('gitlab-domains'), \true) && \false !== strpos($fileUrl, 'archive.zip')) {
            $result = \false;
            if ($retryAuthFailure) {
                $this->promptAuthAndRetry(401);
            }
        }
        // handle 3xx redirects, 304 Not Modified is excluded
        $hasFollowedRedirect = \false;
        if ($statusCode >= 300 && $statusCode <= 399 && $statusCode !== 304 && $this->redirects < $this->maxRedirects) {
            $hasFollowedRedirect = \true;
            $result = $this->handleRedirect($http_response_header, $additionalOptions, $result);
        }
        // fail 4xx and 5xx responses and capture the response
        if ($statusCode && $statusCode >= 400 && $statusCode <= 599) {
            if (!$this->retry) {
                if ($this->progress && !$isRedirect) {
                    $this->io->overwriteError("Downloading (<error>failed</error>)", \false);
                }
                $e = new TransportException('The "' . $this->fileUrl . '" file could not be downloaded (' . $http_response_header[0] . ')', $statusCode);
                $e->setHeaders($http_response_header);
                $e->setResponse($this->decodeResult($result, $http_response_header));
                $e->setStatusCode($statusCode);
                throw $e;
            }
            $result = \false;
        }
        if ($this->progress && !$this->retry && !$isRedirect) {
            $this->io->overwriteError("Downloading (" . ($result === \false ? '<error>failed</error>' : '<comment>100%</comment>') . ")", \false);
        }
        // decode gzip
        if ($result && extension_loaded('zlib') && strpos($fileUrl, 'http') === 0 && !$hasFollowedRedirect) {
            try {
                $result = $this->decodeResult($result, $http_response_header);
            } catch (\Exception $e) {
                if ($this->degradedMode) {
                    throw $e;
                }
                $this->degradedMode = \true;
                $this->io->writeError(['', '<error>Failed to decode response: ' . $e->getMessage() . '</error>', '<error>Retrying with degraded mode, check https://getcomposer.org/doc/articles/troubleshooting.md#degraded-mode for more info</error>']);
                return $this->get($this->originUrl, $this->fileUrl, $additionalOptions, $this->fileName, $this->progress);
            }
        }
        // handle copy command if download was successful
        if (\false !== $result && null !== $fileName && !$isRedirect) {
            if ('' === $result) {
                throw new TransportException('"' . $this->fileUrl . '" appears broken, and returned an empty 200 response');
            }
            $errorMessage = '';
            set_error_handler(static function ($code, $msg) use (&$errorMessage): bool {
                if ($errorMessage) {
                    $errorMessage .= "\n";
                }
                $errorMessage .= Preg::replace('{^file_put_contents\(.*?\): }', '', $msg);
                return \true;
            });
            $result = (bool) file_put_contents($fileName, $result);
            restore_error_handler();
            if (\false === $result) {
                throw new TransportException('The "' . $this->fileUrl . '" file could not be written to ' . $fileName . ': ' . $errorMessage);
            }
        }
        if ($this->retry) {
            $this->retry = \false;
            $result = $this->get($this->originUrl, $this->fileUrl, $additionalOptions, $this->fileName, $this->progress);
            if ($this->storeAuth) {
                $this->authHelper->storeAuth($this->originUrl, $this->storeAuth);
                $this->storeAuth = \false;
            }
            return $result;
        }
        if (\false === $result) {
            $e = new TransportException('The "' . $this->fileUrl . '" file could not be downloaded: ' . $errorMessage, $errorCode);
            if (!empty($http_response_header[0])) {
                $e->setHeaders($http_response_header);
            }
            if (!$this->degradedMode && \false !== strpos($e->getMessage(), 'Operation timed out')) {
                $this->degradedMode = \true;
                $this->io->writeError('');
                $this->io->writeError(['<error>' . $e->getMessage() . '</error>', '<error>Retrying with degraded mode, check https://getcomposer.org/doc/articles/troubleshooting.md#degraded-mode for more info</error>']);
                return $this->get($this->originUrl, $this->fileUrl, $additionalOptions, $this->fileName, $this->progress);
            }
            throw $e;
        }
        if (!empty($http_response_header[0])) {
            $this->lastHeaders = $http_response_header;
        }
        return $result;
    }
    /**
     * Get contents of remote URL.
     *
     * @param string   $originUrl   The origin URL
     * @param string   $fileUrl     The file URL
     * @param resource $context     The stream context
     * @param string[] $responseHeaders
     * @param int      $maxFileSize The maximum allowed file size
     *
     * @return string|false The response contents or false on failure
     *
     * @param-out list<string> $responseHeaders
     */
    protected function getRemoteContents(string $originUrl, string $fileUrl, $context, ?array &$responseHeaders = null, ?int $maxFileSize = null)
    {
        $result = \false;
        if (\PHP_VERSION_ID >= 80400) {
            http_clear_last_response_headers();
        }
        try {
            $e = null;
            if ($maxFileSize !== null) {
                $result = file_get_contents($fileUrl, \false, $context, 0, $maxFileSize);
            } else {
                // passing `null` to file_get_contents will convert `null` to `0` and return 0 bytes
                $result = file_get_contents($fileUrl, \false, $context);
            }
        } catch (\Throwable $e) {
        }
        if ($result !== \false && $maxFileSize !== null && \Composer\Util\Platform::strlen($result) >= $maxFileSize) {
            throw new MaxFileSizeExceededException('Maximum allowed download size reached. Downloaded ' . \Composer\Util\Platform::strlen($result) . ' of allowed ' . $maxFileSize . ' bytes');
        }
        // https://www.php.net/manual/en/reserved.variables.httpresponseheader.php
        if (\PHP_VERSION_ID >= 80400) {
            $responseHeaders = http_get_last_response_headers() ?? [];
            http_clear_last_response_headers();
        } else {
            $responseHeaders = $http_response_header ?? [];
        }
        if (null !== $e) {
            throw $e;
        }
        return $result;
    }
    /**
     * Get notification action.
     *
     * @param int    $notificationCode The notification code
     * @param int    $severity         The severity level
     * @param string $message          The message
     * @param int    $messageCode      The message code
     * @param int    $bytesTransferred The loaded size
     * @param int    $bytesMax         The total size
     *
     * @return void
     *
     * @throws TransportException
     */
    protected function callbackGet(int $notificationCode, int $severity, ?string $message, int $messageCode, int $bytesTransferred, int $bytesMax)
    {
        switch ($notificationCode) {
            case \STREAM_NOTIFY_FAILURE:
                if (400 === $messageCode) {
                    // This might happen if your host is secured by ssl client certificate authentication
                    // but you do not send an appropriate certificate
                    throw new TransportException("The '" . $this->fileUrl . "' URL could not be accessed: " . $message, $messageCode);
                }
                break;
            case \STREAM_NOTIFY_FILE_SIZE_IS:
                $this->bytesMax = $bytesMax;
                break;
            case \STREAM_NOTIFY_PROGRESS:
                if ($this->bytesMax > 0 && $this->progress) {
                    $progression = min(100, (int) round($bytesTransferred / $this->bytesMax * 100));
                    if (0 === $progression % 5 && 100 !== $progression && $progression !== $this->lastProgress) {
                        $this->lastProgress = $progression;
                        $this->io->overwriteError("Downloading (<comment>{$progression}%</comment>)", \false);
                    }
                }
                break;
            default:
                break;
        }
    }
    /**
     * @param positive-int $httpStatus
     * @param string[]     $headers
     *
     * @return void
     */
    protected function promptAuthAndRetry($httpStatus, ?string $reason = null, array $headers = [])
    {
        $result = $this->authHelper->promptAuthIfNeeded($this->fileUrl, $this->originUrl, $httpStatus, $reason, $headers, 1);
        $this->storeAuth = $result['storeAuth'];
        $this->retry = $result['retry'];
        if ($this->retry) {
            throw new TransportException('RETRY');
        }
    }
    /**
     * @param mixed[] $additionalOptions
     *
     * @return mixed[]
     */
    protected function getOptionsForUrl(string $originUrl, array $additionalOptions)
    {
        $tlsOptions = [];
        $headers = [];
        if (extension_loaded('zlib')) {
            $headers[] = 'Accept-Encoding: gzip';
        }
        $options = array_replace_recursive($this->options, $tlsOptions, $additionalOptions);
        if (!$this->degradedMode) {
            // degraded mode disables HTTP/1.1 which causes issues with some bad
            // proxies/software due to the use of chunked encoding
            $options['http']['protocol_version'] = 1.1;
            $headers[] = 'Connection: close';
        }
        if (isset($options['http']['header']) && !is_array($options['http']['header'])) {
            $options['http']['header'] = explode("\r\n", trim($options['http']['header'], "\r\n"));
        }
        $options = $this->authHelper->addAuthenticationOptions($options, $originUrl, $this->fileUrl);
        $options['http']['follow_location'] = 0;
        foreach ($headers as $header) {
            $options['http']['header'][] = $header;
        }
        return $options;
    }
    /**
     * @param string[]     $responseHeaders
     * @param mixed[]      $additionalOptions
     * @param string|false $result
     *
     * @return bool|string
     */
    private function handleRedirect(array $responseHeaders, array $additionalOptions, $result)
    {
        if ($locationHeader = Response::findHeaderValue($responseHeaders, 'location')) {
            if (parse_url($locationHeader, \PHP_URL_SCHEME)) {
                // Absolute URL; e.g. https://example.com/composer
                $targetUrl = $locationHeader;
            } elseif (parse_url($locationHeader, \PHP_URL_HOST)) {
                // Scheme relative; e.g. //example.com/foo
                $targetUrl = $this->scheme . ':' . $locationHeader;
            } elseif ('/' === $locationHeader[0]) {
                // Absolute path; e.g. /foo
                $urlHost = parse_url($this->fileUrl, \PHP_URL_HOST);
                // Replace path using hostname as an anchor.
                $targetUrl = Preg::replace('{^(.+(?://|@)' . preg_quote($urlHost) . '(?::\d+)?)(?:[/\?].*)?$}', '\1' . $locationHeader, $this->fileUrl);
            } else {
                // Relative path; e.g. foo
                // This actually differs from PHP which seems to add duplicate slashes.
                $targetUrl = Preg::replace('{^(.+/)[^/?]*(?:\?.*)?$}', '\1' . $locationHeader, $this->fileUrl);
            }
        }
        if (!empty($targetUrl)) {
            $this->redirects++;
            $this->io->writeError('', \true, IOInterface::DEBUG);
            $this->io->writeError(sprintf('Following redirect (%u) %s', $this->redirects, \Composer\Util\Url::sanitize($targetUrl)), \true, IOInterface::DEBUG);
            $additionalOptions['redirects'] = $this->redirects;
            return $this->get(parse_url($targetUrl, \PHP_URL_HOST), $targetUrl, $additionalOptions, $this->fileName, $this->progress);
        }
        if (!$this->retry) {
            $e = new TransportException('The "' . $this->fileUrl . '" file could not be downloaded, got redirect without Location (' . $responseHeaders[0] . ')');
            $e->setHeaders($responseHeaders);
            $e->setResponse($this->decodeResult($result, $responseHeaders));
            throw $e;
        }
        return \false;
    }
    /**
     * @param string|false $result
     * @param string[]     $responseHeaders
     */
    private function decodeResult($result, array $responseHeaders): ?string
    {
        // decode gzip
        if ($result && extension_loaded('zlib')) {
            $contentEncoding = Response::findHeaderValue($responseHeaders, 'content-encoding');
            $decode = $contentEncoding && 'gzip' === strtolower($contentEncoding);
            if ($decode) {
                $result = zlib_decode($result);
                if ($result === \false) {
                    throw new TransportException('Failed to decode zlib stream');
                }
            }
        }
        return $this->normalizeResult($result);
    }
    /**
     * @param string|false $result
     */
    private function normalizeResult($result): ?string
    {
        if ($result === \false) {
            return null;
        }
        return $result;
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer\Util;

use Composer\IO\IOInterface;
/**
 * Convert PHP errors into exceptions
 *
 * @author Artem Lopata <biozshock@gmail.com>
 */
class ErrorHandler
{
    /** @var ?IOInterface */
    private static $io;
    /** @var int<0, 2> */
    private static $hasShownDeprecationNotice = 0;
    /**
     * Error handler
     *
     * @param int    $level   Level of the error raised
     * @param string $message Error message
     * @param string $file    Filename that the error was raised in
     * @param int    $line    Line number the error was raised at
     *
     * @static
     * @throws \ErrorException
     */
    public static function handle(int $level, string $message, string $file, int $line): bool
    {
        $isDeprecationNotice = $level === \E_DEPRECATED || $level === \E_USER_DEPRECATED;
        // error code is not included in error_reporting
        if (!$isDeprecationNotice && 0 === (error_reporting() & $level)) {
            return \true;
        }
        if (filter_var(ini_get('xdebug.scream'), \FILTER_VALIDATE_BOOLEAN)) {
            $message .= "\n\nWarning: You have xdebug.scream enabled, the warning above may be" . "\na legitimately suppressed error that you were not supposed to see.";
        }
        if (!$isDeprecationNotice) {
            // ignore some newly introduced warnings in new php versions until dependencies
            // can be fixed as we do not want to abort execution for those
            if (in_array($level, [\E_WARNING, \E_USER_WARNING], \true) && str_contains($message, 'should either be used or intentionally ignored by casting it as (void)')) {
                self::outputWarning('Ignored new PHP warning but it should be reported and fixed: ' . $message . ' in ' . $file . ':' . $line, \true);
                return \true;
            }
            throw new \ErrorException($message, 0, $level, $file, $line);
        }
        if (self::$io !== null) {
            if (self::$hasShownDeprecationNotice > 0 && !self::$io->isVerbose()) {
                if (self::$hasShownDeprecationNotice === 1) {
                    self::$io->writeError('<warning>More deprecation notices were hidden, run again with `-v` to show them.</warning>');
                    self::$hasShownDeprecationNotice = 2;
                }
                return \true;
            }
            self::$hasShownDeprecationNotice = 1;
            self::outputWarning('Deprecation Notice: ' . $message . ' in ' . $file . ':' . $line);
        }
        return \true;
    }
    /**
     * Register error handler.
     */
    public static function register(?IOInterface $io = null): void
    {
        set_error_handler([__CLASS__, 'handle']);
        error_reporting(\E_ALL);
        self::$io = $io;
    }
    private static function outputWarning(string $message, bool $outputEvenWithoutIO = \false): void
    {
        if (self::$io !== null) {
            self::$io->writeError('<warning>' . $message . '</warning>');
            if (self::$io->isVerbose()) {
                self::$io->writeError('<warning>Stack trace:</warning>');
                self::$io->writeError(array_filter(array_map(static function ($a): ?string {
                    if (isset($a['line'], $a['file'])) {
                        return '<warning> ' . $a['file'] . ':' . $a['line'] . '</warning>';
                    }
                    return null;
                }, array_slice(debug_backtrace(), 2)), static function (?string $line) {
                    return $line !== null;
                }));
            }
            return;
        }
        if ($outputEvenWithoutIO) {
            if (defined('STDERR') && is_resource(\STDERR)) {
                fwrite(\STDERR, 'Warning: ' . $message . \PHP_EOL);
            } else {
                echo 'Warning: ' . $message . \PHP_EOL;
            }
        }
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer\Util;

/**
 * @internal
 * @readonly
 */
final class ForgejoRepositoryData
{
    /** @var string */
    public $htmlUrl;
    /** @var string */
    public $sshUrl;
    /** @var string */
    public $httpCloneUrl;
    /** @var bool */
    public $isPrivate;
    /** @var string */
    public $defaultBranch;
    /** @var bool */
    public $hasIssues;
    /** @var bool */
    public $isArchived;
    public function __construct(string $htmlUrl, string $httpCloneUrl, string $sshUrl, bool $isPrivate, string $defaultBranch, bool $hasIssues, bool $isArchived)
    {
        $this->htmlUrl = $htmlUrl;
        $this->httpCloneUrl = $httpCloneUrl;
        $this->sshUrl = $sshUrl;
        $this->isPrivate = $isPrivate;
        $this->defaultBranch = $defaultBranch;
        $this->hasIssues = $hasIssues;
        $this->isArchived = $isArchived;
    }
    /**
     * @param array<string, mixed> $data
     */
    public static function fromRemoteData(array $data): self
    {
        return new self($data['html_url'], $data['clone_url'], $data['ssh_url'], $data['private'], $data['default_branch'], $data['has_issues'], $data['archived']);
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer\Util;

use Composer\Downloader\DownloaderInterface;
use Composer\Downloader\DownloadManager;
use Composer\Package\PackageInterface;
use React\Promise\PromiseInterface;
class SyncHelper
{
    /**
     * Helps you download + install a single package in a synchronous way
     *
     * This executes all the required steps and waits for promises to complete
     *
     * @param Loop                                $loop        Loop instance which you can get from $composer->getLoop()
     * @param DownloaderInterface|DownloadManager $downloader  DownloadManager instance or Downloader instance you can get from $composer->getDownloadManager()->getDownloader('zip') for example
     * @param string                              $path        The installation path for the package
     * @param PackageInterface                    $package     The package to install
     * @param PackageInterface|null               $prevPackage The previous package if this is an update and not an initial installation
     */
    public static function downloadAndInstallPackageSync(\Composer\Util\Loop $loop, $downloader, string $path, PackageInterface $package, ?PackageInterface $prevPackage = null): void
    {
        assert($downloader instanceof DownloaderInterface || $downloader instanceof DownloadManager);
        $type = $prevPackage !== null ? 'update' : 'install';
        try {
            self::await($loop, $downloader->download($package, $path, $prevPackage));
            self::await($loop, $downloader->prepare($type, $package, $path, $prevPackage));
            if ($type === 'update' && $prevPackage !== null) {
                self::await($loop, $downloader->update($package, $prevPackage, $path));
            } else {
                self::await($loop, $downloader->install($package, $path));
            }
        } catch (\Exception $e) {
            self::await($loop, $downloader->cleanup($type, $package, $path, $prevPackage));
            throw $e;
        }
        self::await($loop, $downloader->cleanup($type, $package, $path, $prevPackage));
    }
    /**
     * Waits for a promise to resolve
     *
     * @param Loop                  $loop    Loop instance which you can get from $composer->getLoop()
     * @phpstan-param PromiseInterface<mixed>|null $promise
     */
    public static function await(\Composer\Util\Loop $loop, ?PromiseInterface $promise = null): void
    {
        if ($promise !== null) {
            $loop->wait([$promise]);
        }
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer\Util;

use _ContaoManager\Symfony\Component\Console\Helper\ProgressBar;
use React\Promise\PromiseInterface;
/**
 * @author Jordi Boggiano <j.boggiano@seld.be>
 */
class Loop
{
    /** @var HttpDownloader */
    private $httpDownloader;
    /** @var ProcessExecutor|null */
    private $processExecutor;
    /** @var array<int, array<PromiseInterface<mixed>>> */
    private $currentPromises = [];
    /** @var int */
    private $waitIndex = 0;
    public function __construct(\Composer\Util\HttpDownloader $httpDownloader, ?\Composer\Util\ProcessExecutor $processExecutor = null)
    {
        $this->httpDownloader = $httpDownloader;
        $this->httpDownloader->enableAsync();
        $this->processExecutor = $processExecutor;
        if ($this->processExecutor) {
            $this->processExecutor->enableAsync();
        }
    }
    public function getHttpDownloader(): \Composer\Util\HttpDownloader
    {
        return $this->httpDownloader;
    }
    public function getProcessExecutor(): ?\Composer\Util\ProcessExecutor
    {
        return $this->processExecutor;
    }
    /**
     * @param array<PromiseInterface<mixed>> $promises
     */
    public function wait(array $promises, ?ProgressBar $progress = null): void
    {
        $uncaught = null;
        \React\Promise\all($promises)->then(static function (): void {
        }, static function (\Throwable $e) use (&$uncaught): void {
            $uncaught = $e;
        });
        // keep track of every group of promises that is waited on, so abortJobs can
        // cancel them all, even if wait() was called within a wait()
        $waitIndex = $this->waitIndex++;
        $this->currentPromises[$waitIndex] = $promises;
        if ($progress) {
            $totalJobs = 0;
            $totalJobs += $this->httpDownloader->countActiveJobs();
            if ($this->processExecutor) {
                $totalJobs += $this->processExecutor->countActiveJobs();
            }
            $progress->start($totalJobs);
        }
        $lastUpdate = 0;
        while (\true) {
            $activeJobs = 0;
            $activeJobs += $this->httpDownloader->countActiveJobs();
            if ($this->processExecutor) {
                $activeJobs += $this->processExecutor->countActiveJobs();
            }
            if ($progress && microtime(\true) - $lastUpdate > 0.1) {
                $lastUpdate = microtime(\true);
                $progress->setProgress($progress->getMaxSteps() - $activeJobs);
            }
            if (!$activeJobs) {
                break;
            }
        }
        // as we skip progress updates if they are too quick, make sure we do one last one here at 100%
        if ($progress) {
            $progress->finish();
        }
        unset($this->currentPromises[$waitIndex]);
        if (null !== $uncaught) {
            throw $uncaught;
        }
    }
    public function abortJobs(): void
    {
        foreach ($this->currentPromises as $promiseGroup) {
            foreach ($promiseGroup as $promise) {
                // to support react/promise 2.x we wrap the promise in a resolve() call for safety
                \React\Promise\resolve($promise)->cancel();
            }
        }
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer\Config;

use Composer\Json\JsonFile;
use Composer\Json\JsonManipulator;
use Composer\Json\JsonValidationException;
use Composer\Pcre\Preg;
use Composer\Util\Filesystem;
use Composer\Util\Silencer;
/**
 * JSON Configuration Source
 *
 * @author Jordi Boggiano <j.boggiano@seld.be>
 * @author Beau Simensen <beau@dflydev.com>
 */
class JsonConfigSource implements \Composer\Config\ConfigSourceInterface
{
    /**
     * @var JsonFile
     */
    private $file;
    /**
     * @var bool
     */
    private $authConfig;
    /**
     * Constructor
     */
    public function __construct(JsonFile $file, bool $authConfig = \false)
    {
        $this->file = $file;
        $this->authConfig = $authConfig;
    }
    /**
     * @inheritDoc
     */
    public function getName(): string
    {
        return $this->file->getPath();
    }
    /**
     * @inheritDoc
     */
    public function addRepository(string $name, $config, bool $append = \true): void
    {
        $this->manipulateJson('addRepository', static function (&$config, $repo, $repoConfig) use ($append): void {
            if (!array_is_list($config['repositories'] ?? [])) {
                $list = [];
                foreach ($config['repositories'] as $repositoryIndex => $repository) {
                    if (is_string($repositoryIndex) && is_array($repository)) {
                        // convert to list entry with name
                        if (!isset($repository['name'])) {
                            $repository = ['name' => $repositoryIndex] + $repository;
                        }
                        $list[] = $repository;
                    } elseif (is_string($repositoryIndex)) {
                        // keep boolean entries (e.g. 'packagist.org' => false)
                        $list[] = [$repositoryIndex => $repository];
                    } else {
                        $list[] = $repository;
                    }
                }
                $config['repositories'] = $list;
            }
            if ($repoConfig === \false) {
                if (isset($config['repositories'])) {
                    foreach ($config['repositories'] as &$repository) {
                        if (($repository['name'] ?? null) === $repo) {
                            $repository = [$repo => $repoConfig];
                            return;
                        }
                        if ($repository === [$repo => \false]) {
                            return;
                        }
                    }
                    unset($repository);
                } else {
                    $config['repositories'] = [];
                }
                $config['repositories'][] = [$repo => $repoConfig];
                return;
            }
            if (is_array($repoConfig) && $repo !== '' && !isset($repoConfig['name'])) {
                $repoConfig = ['name' => $repo] + $repoConfig;
            }
            // ensure uniqueness by removing any existing entries which use the same name
            $config['repositories'] = array_values(array_filter($config['repositories'] ?? [], static function ($val) use ($repo) {
                return !isset($val['name']) || $val['name'] !== $repo || $val !== [$repo => \false];
            }));
            if ($append) {
                $config['repositories'][] = $repoConfig;
            } else {
                array_unshift($config['repositories'], $repoConfig);
            }
        }, $name, $config, $append);
    }
    /**
     * @inheritDoc
     */
    public function insertRepository(string $name, $config, string $referenceName, int $offset = 0): void
    {
        $this->manipulateJson('insertRepository', static function (&$config, string $name, $repoConfig, string $referenceName, int $offset): void {
            if (!array_is_list($config['repositories'] ?? [])) {
                $list = [];
                foreach ($config['repositories'] as $repositoryIndex => $repository) {
                    if (is_string($repositoryIndex) && is_array($repository)) {
                        // convert to list entry with name
                        if (!isset($repository['name'])) {
                            $repository = ['name' => $repositoryIndex] + $repository;
                        }
                        $list[] = $repository;
                    } elseif (is_string($repositoryIndex)) {
                        // keep boolean entries (e.g. 'packagist.org' => false)
                        $list[] = [$repositoryIndex => $repository];
                    } else {
                        $list[] = $repository;
                    }
                }
                $config['repositories'] = $list;
            }
            // ensure uniqueness by removing any existing entries which use the same name
            $config['repositories'] = array_values(array_filter($config['repositories'] ?? [], static function ($val) use ($name) {
                return !isset($val['name']) || $val['name'] !== $name || $val !== [$name => \false];
            }));
            $indexToInsert = null;
            foreach ($config['repositories'] as $repositoryIndex => $repository) {
                if (($repository['name'] ?? null) === $referenceName) {
                    $indexToInsert = $repositoryIndex;
                    break;
                }
                if ([$referenceName => \false] === $repository) {
                    $indexToInsert = $repositoryIndex;
                    break;
                }
            }
            if ($indexToInsert === null) {
                throw new \RuntimeException(sprintf('The referenced repository "%s" does not exist.', $referenceName));
            }
            if (is_array($repoConfig) && $name !== '' && !isset($repoConfig['name'])) {
                $repoConfig = ['name' => $name] + $repoConfig;
            }
            array_splice($config['repositories'], $indexToInsert + $offset, 0, [$repoConfig]);
        }, $name, $config, $referenceName, $offset);
    }
    /**
     * @inheritDoc
     */
    public function setRepositoryUrl(string $name, string $url): void
    {
        $this->manipulateJson('setRepositoryUrl', static function (&$config, $name, $url): void {
            foreach ($config['repositories'] ?? [] as $index => $repository) {
                if ($name === $index) {
                    $config['repositories'][$index]['url'] = $url;
                    return;
                }
                if ($name === ($repository['name'] ?? null)) {
                    $config['repositories'][$index]['url'] = $url;
                    return;
                }
            }
        }, $name, $url);
    }
    /**
     * @inheritDoc
     */
    public function removeRepository(string $name): void
    {
        $this->manipulateJson('removeRepository', static function (&$config, $repo): void {
            if (isset($config['repositories'][$repo])) {
                unset($config['repositories'][$repo]);
            } else {
                $config['repositories'] = array_values(array_filter($config['repositories'] ?? [], static function ($val) use ($repo) {
                    return !isset($val['name']) || $val['name'] !== $repo || $val !== [$repo => \false];
                }));
            }
            if ([] === $config['repositories']) {
                unset($config['repositories']);
            }
        }, $name);
    }
    /**
     * @inheritDoc
     */
    public function addConfigSetting(string $name, $value): void
    {
        $authConfig = $this->authConfig;
        $this->manipulateJson('addConfigSetting', static function (&$config, $key, $val) use ($authConfig): void {
            if (Preg::isMatch('{^(bitbucket-oauth|github-oauth|gitlab-oauth|gitlab-token|bearer|http-basic|custom-headers|forgejo-token|platform)\.}', $key)) {
                [$key, $host] = explode('.', $key, 2);
                if ($authConfig) {
                    $config[$key][$host] = $val;
                } else {
                    $config['config'][$key][$host] = $val;
                }
            } else {
                $config['config'][$key] = $val;
            }
        }, $name, $value);
    }
    /**
     * @inheritDoc
     */
    public function removeConfigSetting(string $name): void
    {
        $authConfig = $this->authConfig;
        $this->manipulateJson('removeConfigSetting', static function (&$config, $key) use ($authConfig): void {
            if (Preg::isMatch('{^(bitbucket-oauth|github-oauth|gitlab-oauth|gitlab-token|bearer|http-basic|custom-headers|forgejo-token|platform)\.}', $key)) {
                [$key, $host] = explode('.', $key, 2);
                if ($authConfig) {
                    unset($config[$key][$host]);
                } else {
                    unset($config['config'][$key][$host]);
                }
            } else {
                unset($config['config'][$key]);
            }
        }, $name);
    }
    /**
     * @inheritDoc
     */
    public function addProperty(string $name, $value): void
    {
        $this->manipulateJson('addProperty', static function (&$config, $key, $val): void {
            if (strpos($key, 'extra.') === 0 || strpos($key, 'scripts.') === 0) {
                $bits = explode('.', $key);
                $last = array_pop($bits);
                $arr =& $config[reset($bits)];
                foreach ($bits as $bit) {
                    if (!isset($arr[$bit])) {
                        $arr[$bit] = [];
                    }
                    $arr =& $arr[$bit];
                }
                $arr[$last] = $val;
            } else {
                $config[$key] = $val;
            }
        }, $name, $value);
    }
    /**
     * @inheritDoc
     */
    public function removeProperty(string $name): void
    {
        $this->manipulateJson('removeProperty', static function (&$config, $key): void {
            if (strpos($key, 'extra.') === 0 || strpos($key, 'scripts.') === 0 || stripos($key, 'autoload.') === 0 || stripos($key, 'autoload-dev.') === 0) {
                $bits = explode('.', $key);
                $last = array_pop($bits);
                $arr =& $config[reset($bits)];
                foreach ($bits as $bit) {
                    if (!isset($arr[$bit])) {
                        return;
                    }
                    $arr =& $arr[$bit];
                }
                unset($arr[$last]);
            } else {
                unset($config[$key]);
            }
        }, $name);
    }
    /**
     * @inheritDoc
     */
    public function addLink(string $type, string $name, string $value): void
    {
        $this->manipulateJson('addLink', static function (&$config, $type, $name, $value): void {
            $config[$type][$name] = $value;
        }, $type, $name, $value);
    }
    /**
     * @inheritDoc
     */
    public function removeLink(string $type, string $name): void
    {
        $this->manipulateJson('removeSubNode', static function (&$config, $type, $name): void {
            unset($config[$type][$name]);
        }, $type, $name);
        $this->manipulateJson('removeMainKeyIfEmpty', static function (&$config, $type): void {
            if (0 === count($config[$type])) {
                unset($config[$type]);
            }
        }, $type);
    }
    /**
     * @param mixed ...$args
     */
    private function manipulateJson(string $method, callable $fallback, ...$args): void
    {
        if ($this->file->exists()) {
            if (!is_writable($this->file->getPath())) {
                throw new \RuntimeException(sprintf('The file "%s" is not writable.', $this->file->getPath()));
            }
            if (!Filesystem::isReadable($this->file->getPath())) {
                throw new \RuntimeException(sprintf('The file "%s" is not readable.', $this->file->getPath()));
            }
            $contents = file_get_contents($this->file->getPath());
        } elseif ($this->authConfig) {
            $contents = "{\n}\n";
        } else {
            $contents = "{\n    \"config\": {\n    }\n}\n";
        }
        $manipulator = new JsonManipulator($contents);
        $newFile = !$this->file->exists();
        // override manipulator method for auth config files
        if ($this->authConfig && $method === 'addConfigSetting') {
            $method = 'addSubNode';
            [$mainNode, $name] = explode('.', $args[0], 2);
            $args = [$mainNode, $name, $args[1]];
        } elseif ($this->authConfig && $method === 'removeConfigSetting') {
            $method = 'removeSubNode';
            [$mainNode, $name] = explode('.', $args[0], 2);
            $args = [$mainNode, $name];
        }
        // try to update cleanly
        if (call_user_func_array([$manipulator, $method], $args)) {
            file_put_contents($this->file->getPath(), $manipulator->getContents());
        } else {
            // on failed clean update, call the fallback and rewrite the whole file
            $config = $this->file->read();
            $this->arrayUnshiftRef($args, $config);
            $fallback(...$args);
            // avoid ending up with arrays for keys that should be objects
            foreach (['require', 'require-dev', 'conflict', 'provide', 'replace', 'suggest', 'config', 'autoload', 'autoload-dev', 'scripts', 'scripts-descriptions', 'scripts-aliases', 'support'] as $prop) {
                if (isset($config[$prop]) && $config[$prop] === []) {
                    $config[$prop] = new \stdClass();
                }
            }
            foreach (['psr-0', 'psr-4'] as $prop) {
                if (isset($config['autoload'][$prop]) && $config['autoload'][$prop] === []) {
                    $config['autoload'][$prop] = new \stdClass();
                }
                if (isset($config['autoload-dev'][$prop]) && $config['autoload-dev'][$prop] === []) {
                    $config['autoload-dev'][$prop] = new \stdClass();
                }
            }
            foreach (['platform', 'http-basic', 'bearer', 'gitlab-token', 'gitlab-oauth', 'github-oauth', 'custom-headers', 'forgejo-token', 'preferred-install'] as $prop) {
                if (isset($config['config'][$prop]) && $config['config'][$prop] === []) {
                    $config['config'][$prop] = new \stdClass();
                }
            }
            $this->file->write($config);
        }
        try {
            $this->file->validateSchema(JsonFile::LAX_SCHEMA);
        } catch (JsonValidationException $e) {
            // restore contents to the original state
            file_put_contents($this->file->getPath(), $contents);
            throw new \RuntimeException('Failed to update composer.json with a valid format, reverting to the original content. Please report an issue to us with details (command you run and a copy of your composer.json). ' . \PHP_EOL . implode(\PHP_EOL, $e->getErrors()), 0, $e);
        }
        if ($newFile) {
            Silencer::call('chmod', $this->file->getPath(), 0600);
        }
    }
    /**
     * Prepend a reference to an element to the beginning of an array.
     *
     * @param  mixed[] $array
     * @param  mixed $value
     */
    private function arrayUnshiftRef(array &$array, &$value): int
    {
        $return = array_unshift($array, '');
        $array[0] =& $value;
        return $return;
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer\Config;

/**
 * Configuration Source Interface
 *
 * @author Jordi Boggiano <j.boggiano@seld.be>
 * @author Beau Simensen <beau@dflydev.com>
 */
interface ConfigSourceInterface
{
    /**
     * Add a repository
     *
     * @param string        $name   Name
     * @param mixed[]|false $config Configuration
     * @param bool          $append Whether the repo should be appended (true) or prepended (false)
     */
    public function addRepository(string $name, $config, bool $append = \true): void;
    /**
     * Inserts a repository before/after another repository by name
     *
     * @param string        $name          Name
     * @param mixed[]|false $config        Configuration
     * @param string        $referenceName The referenced repository to search for and insert next to
     * @param int           $offset        The offset to use for insert in reference to the looked-up repository
     */
    public function insertRepository(string $name, $config, string $referenceName, int $offset = 0): void;
    /**
     * Changes the URL of the referenced repository by name
     */
    public function setRepositoryUrl(string $name, string $url): void;
    /**
     * Remove a repository
     */
    public function removeRepository(string $name): void;
    /**
     * Add a config setting
     *
     * @param string $name  Name
     * @param mixed  $value Value
     */
    public function addConfigSetting(string $name, $value): void;
    /**
     * Remove a config setting
     */
    public function removeConfigSetting(string $name): void;
    /**
     * Add a property
     *
     * @param string $name  Name
     * @param string|string[] $value Value
     */
    public function addProperty(string $name, $value): void;
    /**
     * Remove a property
     */
    public function removeProperty(string $name): void;
    /**
     * Add a package link
     *
     * @param string $type  Type (require, require-dev, provide, suggest, replace, conflict)
     * @param string $name  Name
     * @param string $value Value
     */
    public function addLink(string $type, string $name, string $value): void;
    /**
     * Remove a package link
     *
     * @param string $type Type (require, require-dev, provide, suggest, replace, conflict)
     * @param string $name Name
     */
    public function removeLink(string $type, string $name): void;
    /**
     * Gives a user-friendly name to this source (file path or so)
     */
    public function getName(): string;
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer\SelfUpdate;

use Composer\IO\IOInterface;
use Composer\Pcre\Preg;
use Composer\Util\HttpDownloader;
use Composer\Config;
/**
 * @author Jordi Boggiano <j.boggiano@seld.be>
 */
class Versions
{
    /**
     * @var string[]
     * @deprecated use Versions::CHANNELS
     */
    public static $channels = self::CHANNELS;
    public const CHANNELS = ['stable', 'preview', 'snapshot', '1', '2', '2.2'];
    /** @var HttpDownloader */
    private $httpDownloader;
    /** @var Config */
    private $config;
    /** @var string */
    private $channel;
    /** @var array<string, array<int, array{path: string, version: string, min-php: int, eol?: true}>>|null */
    private $versionsData = null;
    public function __construct(Config $config, HttpDownloader $httpDownloader)
    {
        $this->httpDownloader = $httpDownloader;
        $this->config = $config;
    }
    public function getChannel(): string
    {
        if ($this->channel) {
            return $this->channel;
        }
        $channelFile = $this->config->get('home') . '/update-channel';
        if (file_exists($channelFile)) {
            $channel = trim(file_get_contents($channelFile));
            if (in_array($channel, ['stable', 'preview', 'snapshot', '2.2'], \true)) {
                return $this->channel = $channel;
            }
        }
        return $this->channel = 'stable';
    }
    public function setChannel(string $channel, ?IOInterface $io = null): void
    {
        if (!in_array($channel, self::CHANNELS, \true)) {
            throw new \InvalidArgumentException('Invalid channel ' . $channel . ', must be one of: ' . implode(', ', self::CHANNELS));
        }
        $channelFile = $this->config->get('home') . '/update-channel';
        $this->channel = $channel;
        // rewrite '2' and '1' channels to stable for future self-updates, but LTS ones like '2.2' remain pinned
        $storedChannel = Preg::isMatch('{^\d+$}D', $channel) ? 'stable' : $channel;
        $previouslyStored = file_exists($channelFile) ? trim((string) file_get_contents($channelFile)) : null;
        file_put_contents($channelFile, $storedChannel . \PHP_EOL);
        if ($io !== null && $previouslyStored !== $storedChannel) {
            $io->writeError('Storing "<info>' . $storedChannel . '</info>" as default update channel for the next self-update run.');
        }
    }
    /**
     * @return array{path: string, version: string, min-php: int, eol?: true}
     */
    public function getLatest(?string $channel = null): array
    {
        $versions = $this->getVersionsData();
        foreach ($versions[$channel ?: $this->getChannel()] as $version) {
            if ($version['min-php'] <= \PHP_VERSION_ID) {
                return $version;
            }
        }
        throw new \UnexpectedValueException('There is no version of Composer available for your PHP version (' . \PHP_VERSION . ')');
    }
    /**
     * @return array<string, array<int, array{path: string, version: string, min-php: int, eol?: true}>>
     */
    private function getVersionsData(): array
    {
        if (null === $this->versionsData) {
            if ($this->config->get('disable-tls') === \true) {
                $protocol = 'http';
            } else {
                $protocol = 'https';
            }
            $this->versionsData = $this->httpDownloader->get($protocol . '://getcomposer.org/versions')->decodeJson();
        }
        return $this->versionsData;
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer\SelfUpdate;

use Composer\Pcre\Preg;
/**
 * @author Jordi Boggiano <j.boggiano@seld.be>
 */
class Keys
{
    public static function fingerprint(string $path): string
    {
        $hash = strtoupper(hash('sha256', Preg::replace('{\s}', '', file_get_contents($path))));
        return implode(' ', [
            substr($hash, 0, 8),
            substr($hash, 8, 8),
            substr($hash, 16, 8),
            substr($hash, 24, 8),
            '',
            // Extra space
            substr($hash, 32, 8),
            substr($hash, 40, 8),
            substr($hash, 48, 8),
            substr($hash, 56, 8),
        ]);
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer;

use Composer\IO\IOInterface;
use Composer\Pcre\Preg;
use Composer\Util\Filesystem;
use Composer\Util\Platform;
use Composer\Util\Silencer;
use _ContaoManager\Symfony\Component\Finder\Finder;
/**
 * Reads/writes to a filesystem cache
 *
 * @author Jordi Boggiano <j.boggiano@seld.be>
 */
class Cache
{
    /** @var bool|null */
    private static $cacheCollected = null;
    /** @var IOInterface */
    private $io;
    /** @var string */
    private $root;
    /** @var ?bool */
    private $enabled = null;
    /** @var string */
    private $allowlist;
    /** @var Filesystem */
    private $filesystem;
    /** @var bool */
    private $readOnly;
    /**
     * @param string      $cacheDir   location of the cache
     * @param string      $allowlist  List of characters that are allowed in path names (used in a regex character class)
     * @param Filesystem  $filesystem optional filesystem instance
     * @param bool        $readOnly   whether the cache is in readOnly mode
     */
    public function __construct(IOInterface $io, string $cacheDir, string $allowlist = 'a-z0-9._', ?Filesystem $filesystem = null, bool $readOnly = \false)
    {
        $this->io = $io;
        $this->root = rtrim($cacheDir, '/\\') . '/';
        $this->allowlist = $allowlist;
        $this->filesystem = $filesystem ?: new Filesystem();
        $this->readOnly = $readOnly;
        if (!self::isUsable($cacheDir)) {
            $this->enabled = \false;
        }
    }
    /**
     * @return void
     */
    public function setReadOnly(bool $readOnly)
    {
        $this->readOnly = $readOnly;
    }
    /**
     * @return bool
     */
    public function isReadOnly()
    {
        return $this->readOnly;
    }
    /**
     * @return bool
     */
    public static function isUsable(string $path)
    {
        return !Preg::isMatch('{(^|[\\\\/])(\$null|nul|NUL|/dev/null)([\\\\/]|$)}', $path);
    }
    /**
     * @return bool
     */
    public function isEnabled()
    {
        if ($this->enabled === null) {
            $this->enabled = \true;
            if (!$this->readOnly && (!is_dir($this->root) && !Silencer::call('mkdir', $this->root, 0777, \true) || !is_writable($this->root))) {
                $this->io->writeError('<warning>Cannot create cache directory ' . $this->root . ', or directory is not writable. Proceeding without cache. See also cache-read-only config if your filesystem is read-only.</warning>');
                $this->enabled = \false;
            }
        }
        return $this->enabled;
    }
    /**
     * @return string
     */
    public function getRoot()
    {
        return $this->root;
    }
    /**
     * @return string|false
     */
    public function read(string $file)
    {
        if ($this->isEnabled()) {
            $file = Preg::replace('{[^' . $this->allowlist . ']}i', '-', $file);
            if (file_exists($this->root . $file)) {
                $this->io->writeError('Reading ' . $this->root . $file . ' from cache', \true, IOInterface::DEBUG);
                return file_get_contents($this->root . $file);
            }
        }
        return \false;
    }
    /**
     * @return bool
     */
    public function write(string $file, string $contents)
    {
        $wasEnabled = $this->enabled === \true;
        if ($this->isEnabled() && !$this->readOnly) {
            $file = Preg::replace('{[^' . $this->allowlist . ']}i', '-', $file);
            $this->io->writeError('Writing ' . $this->root . $file . ' into cache', \true, IOInterface::DEBUG);
            $tempFileName = $this->root . $file . bin2hex(random_bytes(5)) . '.tmp';
            try {
                return file_put_contents($tempFileName, $contents) !== \false && rename($tempFileName, $this->root . $file);
            } catch (\ErrorException $e) {
                // If the write failed despite isEnabled checks passing earlier, rerun the isEnabled checks to
                // see if they are still current and recreate the cache dir if needed. Refs https://github.com/composer/composer/issues/11076
                if ($wasEnabled) {
                    clearstatcache();
                    $this->enabled = null;
                    return $this->write($file, $contents);
                }
                $this->io->writeError('<warning>Failed to write into cache: ' . $e->getMessage() . '</warning>', \true, IOInterface::DEBUG);
                if (Preg::isMatch('{^file_put_contents\(\): Only ([0-9]+) of ([0-9]+) bytes written}', $e->getMessage(), $m)) {
                    // Remove partial file.
                    unlink($tempFileName);
                    $message = sprintf('<warning>Writing %1$s into cache failed after %2$u of %3$u bytes written, only %4$s bytes of free space available</warning>', $tempFileName, $m[1], $m[2], function_exists('disk_free_space') ? @disk_free_space(dirname($tempFileName)) : 'unknown');
                    $this->io->writeError($message);
                    return \false;
                }
                throw $e;
            }
        }
        return \false;
    }
    /**
     * Copy a file into the cache
     *
     * @return bool
     */
    public function copyFrom(string $file, string $source)
    {
        if ($this->isEnabled() && !$this->readOnly) {
            $file = Preg::replace('{[^' . $this->allowlist . ']}i', '-', $file);
            $this->filesystem->ensureDirectoryExists(dirname($this->root . $file));
            if (!file_exists($source)) {
                $this->io->writeError('<error>' . $source . ' does not exist, can not write into cache</error>');
            } elseif ($this->io->isDebug()) {
                $this->io->writeError('Writing ' . $this->root . $file . ' into cache from ' . $source);
            }
            return $this->filesystem->copy($source, $this->root . $file);
        }
        return \false;
    }
    /**
     * Copy a file out of the cache
     *
     * @return bool
     */
    public function copyTo(string $file, string $target)
    {
        if ($this->isEnabled()) {
            $file = Preg::replace('{[^' . $this->allowlist . ']}i', '-', $file);
            if (file_exists($this->root . $file)) {
                try {
                    touch($this->root . $file, (int) filemtime($this->root . $file), time());
                } catch (\ErrorException $e) {
                    // fallback in case the above failed due to incorrect ownership
                    // see https://github.com/composer/composer/issues/4070
                    Silencer::call('touch', $this->root . $file);
                }
                $this->io->writeError('Reading ' . $this->root . $file . ' from cache', \true, IOInterface::DEBUG);
                return $this->filesystem->copy($this->root . $file, $target);
            }
        }
        return \false;
    }
    /**
     * @return bool
     */
    public function gcIsNecessary()
    {
        if (self::$cacheCollected) {
            return \false;
        }
        self::$cacheCollected = \true;
        if (Platform::getEnv('COMPOSER_TEST_SUITE')) {
            return \false;
        }
        if (Platform::isInputCompletionProcess()) {
            return \false;
        }
        return !random_int(0, 50);
    }
    /**
     * @return bool
     */
    public function remove(string $file)
    {
        if ($this->isEnabled() && !$this->readOnly) {
            $file = Preg::replace('{[^' . $this->allowlist . ']}i', '-', $file);
            if (file_exists($this->root . $file)) {
                return $this->filesystem->unlink($this->root . $file);
            }
        }
        return \false;
    }
    /**
     * @return bool
     */
    public function clear()
    {
        if ($this->isEnabled() && !$this->readOnly) {
            $this->filesystem->emptyDirectory($this->root);
            return \true;
        }
        return \false;
    }
    /**
     * @return int|false
     * @phpstan-return int<0, max>|false
     */
    public function getAge(string $file)
    {
        if ($this->isEnabled()) {
            $file = Preg::replace('{[^' . $this->allowlist . ']}i', '-', $file);
            if (file_exists($this->root . $file) && ($mtime = filemtime($this->root . $file)) !== \false) {
                return abs(time() - $mtime);
            }
        }
        return \false;
    }
    /**
     * @return bool
     */
    public function gc(int $ttl, int $maxSize)
    {
        if ($this->isEnabled() && !$this->readOnly) {
            $expire = new \DateTime();
            $expire->modify('-' . $ttl . ' seconds');
            $finder = $this->getFinder()->date('until ' . $expire->format('Y-m-d H:i:s'));
            foreach ($finder as $file) {
                $this->filesystem->unlink($file->getPathname());
            }
            $totalSize = $this->filesystem->size($this->root);
            if ($totalSize > $maxSize) {
                $iterator = $this->getFinder()->sortByAccessedTime()->getIterator();
                while ($totalSize > $maxSize && $iterator->valid()) {
                    $filepath = $iterator->current()->getPathname();
                    $totalSize -= $this->filesystem->size($filepath);
                    $this->filesystem->unlink($filepath);
                    $iterator->next();
                }
            }
            self::$cacheCollected = \true;
            return \true;
        }
        return \false;
    }
    public function gcVcsCache(int $ttl): bool
    {
        if ($this->isEnabled()) {
            $expire = new \DateTime();
            $expire->modify('-' . $ttl . ' seconds');
            $finder = Finder::create()->in($this->root)->directories()->depth(0)->date('until ' . $expire->format('Y-m-d H:i:s'));
            foreach ($finder as $file) {
                $this->filesystem->removeDirectory($file->getPathname());
            }
            self::$cacheCollected = \true;
            return \true;
        }
        return \false;
    }
    /**
     * @return string|false
     */
    public function sha1(string $file)
    {
        if ($this->isEnabled()) {
            $file = Preg::replace('{[^' . $this->allowlist . ']}i', '-', $file);
            if (file_exists($this->root . $file)) {
                return hash_file('sha1', $this->root . $file);
            }
        }
        return \false;
    }
    /**
     * @return string|false
     */
    public function sha256(string $file)
    {
        if ($this->isEnabled()) {
            $file = Preg::replace('{[^' . $this->allowlist . ']}i', '-', $file);
            if (file_exists($this->root . $file)) {
                return hash_file('sha256', $this->root . $file);
            }
        }
        return \false;
    }
    /**
     * @return Finder
     */
    protected function getFinder()
    {
        return Finder::create()->in($this->root)->files();
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer\EventDispatcher;

/**
 * The base event class
 *
 * @author Nils Adermann <naderman@naderman.de>
 */
class Event
{
    /**
     * @var string This event's name
     */
    protected $name;
    /**
     * @var string[] Arguments passed by the user, these will be forwarded to CLI script handlers
     */
    protected $args;
    /**
     * @var mixed[] Flags usable in PHP script handlers
     */
    protected $flags;
    /**
     * @var bool Whether the event should not be passed to more listeners
     */
    private $propagationStopped = \false;
    /**
     * Constructor.
     *
     * @param string   $name  The event name
     * @param string[] $args  Arguments passed by the user
     * @param mixed[]  $flags Optional flags to pass data not as argument
     */
    public function __construct(string $name, array $args = [], array $flags = [])
    {
        $this->name = $name;
        $this->args = $args;
        $this->flags = $flags;
    }
    /**
     * Returns the event's name.
     *
     * @return string The event name
     */
    public function getName(): string
    {
        return $this->name;
    }
    /**
     * Returns the event's arguments.
     *
     * @return string[] The event arguments
     */
    public function getArguments(): array
    {
        return $this->args;
    }
    /**
     * Returns the event's flags.
     *
     * @return mixed[] The event flags
     */
    public function getFlags(): array
    {
        return $this->flags;
    }
    /**
     * Checks if stopPropagation has been called
     *
     * @return bool Whether propagation has been stopped
     */
    public function isPropagationStopped(): bool
    {
        return $this->propagationStopped;
    }
    /**
     * Prevents the event from being passed to further listeners
     */
    public function stopPropagation(): void
    {
        $this->propagationStopped = \true;
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer\EventDispatcher;

/**
 * Thrown when a script running an external process exits with a non-0 status code
 *
 * @author Jordi Boggiano <j.boggiano@seld.be>
 */
class ScriptExecutionException extends \RuntimeException
{
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer\EventDispatcher;

use Composer\DependencyResolver\Transaction;
use Composer\Installer\InstallerEvent;
use Composer\IO\ConsoleIO;
use Composer\IO\IOInterface;
use Composer\Composer;
use Composer\Package\PackageInterface;
use Composer\PartialComposer;
use Composer\Pcre\Preg;
use Composer\Plugin\CommandEvent;
use Composer\Plugin\PreCommandRunEvent;
use Composer\Util\Platform;
use Composer\DependencyResolver\Operation\OperationInterface;
use Composer\Repository\RepositoryInterface;
use Composer\Script;
use Composer\Installer\PackageEvent;
use Composer\Installer\BinaryInstaller;
use Composer\Util\ProcessExecutor;
use Composer\Script\Event as ScriptEvent;
use Composer\Autoload\ClassLoader;
use _ContaoManager\Symfony\Component\Console\Application;
use _ContaoManager\Symfony\Component\Console\Command\Command;
use _ContaoManager\Symfony\Component\Console\Input\StringInput;
use _ContaoManager\Symfony\Component\Console\Output\ConsoleOutput;
use _ContaoManager\Symfony\Component\Process\PhpExecutableFinder;
use _ContaoManager\Symfony\Component\Process\ExecutableFinder;
/**
 * The Event Dispatcher.
 *
 * Example in command:
 *     $dispatcher = new EventDispatcher($this->requireComposer(), $this->getApplication()->getIO());
 *     // ...
 *     $dispatcher->dispatch(ScriptEvents::POST_INSTALL_CMD);
 *     // ...
 *
 * @author François Pluchino <francois.pluchino@opendisplay.com>
 * @author Jordi Boggiano <j.boggiano@seld.be>
 * @author Nils Adermann <naderman@naderman.de>
 */
class EventDispatcher
{
    /** @var PartialComposer */
    protected $composer;
    /** @var IOInterface */
    protected $io;
    /** @var ?ClassLoader */
    protected $loader;
    /** @var ProcessExecutor */
    protected $process;
    /** @var array<string, array<int, array<callable|string>>> */
    protected $listeners = [];
    /** @var bool */
    protected $runScripts = \true;
    /** @var list<string> */
    private $eventStack;
    /** @var list<string> */
    private $skipScripts;
    /** @var string|null */
    private $previousHash = null;
    /** @var array<string, true> */
    private $previousListeners = [];
    /**
     * Constructor.
     *
     * @param PartialComposer $composer The composer instance
     * @param IOInterface     $io       The IOInterface instance
     */
    public function __construct(PartialComposer $composer, IOInterface $io, ?ProcessExecutor $process = null)
    {
        $this->composer = $composer;
        $this->io = $io;
        $this->process = $process ?? new ProcessExecutor($io);
        $this->eventStack = [];
        $this->skipScripts = array_values(array_filter(array_map('trim', explode(',', (string) Platform::getEnv('COMPOSER_SKIP_SCRIPTS'))), static function ($val) {
            return $val !== '';
        }));
    }
    /**
     * Set whether script handlers are active or not
     *
     * @return $this
     */
    public function setRunScripts(bool $runScripts = \true): self
    {
        $this->runScripts = $runScripts;
        return $this;
    }
    /**
     * Dispatch an event
     *
     * @param  string|null $eventName The event name, required if no $event is provided
     * @param  Event       $event An event instance, required if no $eventName is provided
     * @return int         return code of the executed script if any, for php scripts a false return
     *                          value is changed to 1, anything else to 0
     */
    public function dispatch(?string $eventName, ?\Composer\EventDispatcher\Event $event = null): int
    {
        if (null === $event) {
            if (null === $eventName) {
                throw new \InvalidArgumentException('If no $event is passed in to ' . __METHOD__ . ' you have to pass in an $eventName, got null.');
            }
            $event = new \Composer\EventDispatcher\Event($eventName);
        }
        return $this->doDispatch($event);
    }
    /**
     * Dispatch a script event.
     *
     * @param  string               $eventName      The constant in ScriptEvents
     * @param  array<int, mixed>    $additionalArgs Arguments passed by the user
     * @param  array<string, mixed> $flags          Optional flags to pass data not as argument
     * @return int                                  return code of the executed script if any, for php scripts a false return
     *                                              value is changed to 1, anything else to 0
     */
    public function dispatchScript(string $eventName, bool $devMode = \false, array $additionalArgs = [], array $flags = []): int
    {
        assert($this->composer instanceof Composer, new \LogicException('This should only be reached with a fully loaded Composer'));
        return $this->doDispatch(new ScriptEvent($eventName, $this->composer, $this->io, $devMode, $additionalArgs, $flags));
    }
    /**
     * Dispatch a package event.
     *
     * @param string               $eventName  The constant in PackageEvents
     * @param bool                 $devMode    Whether or not we are in dev mode
     * @param RepositoryInterface  $localRepo  The installed repository
     * @param OperationInterface[] $operations The list of operations
     * @param OperationInterface   $operation  The package being installed/updated/removed
     *
     * @return int return code of the executed script if any, for php scripts a false return
     *             value is changed to 1, anything else to 0
     */
    public function dispatchPackageEvent(string $eventName, bool $devMode, RepositoryInterface $localRepo, array $operations, OperationInterface $operation): int
    {
        assert($this->composer instanceof Composer, new \LogicException('This should only be reached with a fully loaded Composer'));
        return $this->doDispatch(new PackageEvent($eventName, $this->composer, $this->io, $devMode, $localRepo, $operations, $operation));
    }
    /**
     * Dispatch a installer event.
     *
     * @param string      $eventName         The constant in InstallerEvents
     * @param bool        $devMode           Whether or not we are in dev mode
     * @param bool        $executeOperations True if operations will be executed, false in --dry-run
     * @param Transaction $transaction       The transaction contains the list of operations
     *
     * @return int return code of the executed script if any, for php scripts a false return
     *             value is changed to 1, anything else to 0
     */
    public function dispatchInstallerEvent(string $eventName, bool $devMode, bool $executeOperations, Transaction $transaction): int
    {
        assert($this->composer instanceof Composer, new \LogicException('This should only be reached with a fully loaded Composer'));
        return $this->doDispatch(new InstallerEvent($eventName, $this->composer, $this->io, $devMode, $executeOperations, $transaction));
    }
    /**
     * Triggers the listeners of an event.
     *
     * @param  Event                        $event The event object to pass to the event handlers/listeners.
     * @throws \RuntimeException|\Exception
     * @return int                          return code of the executed script if any, for php scripts a false return
     *                                            value is changed to 1, anything else to 0
     */
    protected function doDispatch(\Composer\EventDispatcher\Event $event)
    {
        if (Platform::getEnv('COMPOSER_DEBUG_EVENTS')) {
            $details = null;
            if ($event instanceof PackageEvent) {
                $details = (string) $event->getOperation();
            } elseif ($event instanceof CommandEvent) {
                $details = $event->getCommandName();
            } elseif ($event instanceof PreCommandRunEvent) {
                $details = $event->getCommand();
            }
            $this->io->writeError('Dispatching <info>' . $event->getName() . '</info>' . ($details ? ' (' . $details . ')' : '') . ' event');
        }
        $listeners = $this->getListeners($event);
        $this->pushEvent($event);
        $autoloadersBefore = spl_autoload_functions();
        try {
            $returnMax = 0;
            foreach ($listeners as $callable) {
                $return = 0;
                $this->ensureBinDirIsInPath();
                $additionalArgs = $event->getArguments();
                if (is_string($callable) && str_contains($callable, '@no_additional_args')) {
                    $callable = Preg::replace('{ ?@no_additional_args}', '', $callable);
                    $additionalArgs = [];
                }
                $formattedEventNameWithArgs = $event->getName() . ($additionalArgs !== [] ? ' (' . implode(', ', $additionalArgs) . ')' : '');
                if (!is_string($callable)) {
                    $this->makeAutoloader($event, $callable);
                    if (!is_callable($callable)) {
                        $className = is_object($callable[0]) ? get_class($callable[0]) : $callable[0];
                        throw new \RuntimeException('Subscriber ' . $className . '::' . $callable[1] . ' for event ' . $event->getName() . ' is not callable, make sure the function is defined and public');
                    }
                    if (is_array($callable) && (is_string($callable[0]) || is_object($callable[0])) && is_string($callable[1])) {
                        $this->io->writeError(sprintf('> %s: %s', $formattedEventNameWithArgs, (is_object($callable[0]) ? get_class($callable[0]) : $callable[0]) . '->' . $callable[1]), \true, IOInterface::VERBOSE);
                    }
                    $return = \false === $callable($event) ? 1 : 0;
                } elseif ($this->isComposerScript($callable)) {
                    $this->io->writeError(sprintf('> %s: %s', $formattedEventNameWithArgs, $callable), \true, IOInterface::VERBOSE);
                    $script = explode(' ', substr($callable, 1));
                    $scriptName = $script[0];
                    unset($script[0]);
                    $index = array_search('@additional_args', $script, \true);
                    if ($index !== \false) {
                        $args = array_splice($script, $index, 0, $additionalArgs);
                    } else {
                        $args = array_merge($script, $additionalArgs);
                    }
                    $flags = $event->getFlags();
                    if (isset($flags['script-alias-input'])) {
                        $argsString = implode(' ', array_map(static function ($arg) {
                            return ProcessExecutor::escape($arg);
                        }, $script));
                        $flags['script-alias-input'] = $argsString . ' ' . $flags['script-alias-input'];
                        unset($argsString);
                    }
                    if (strpos($callable, '@composer ') === 0) {
                        $exec = $this->getPhpExecCommand() . ' ' . ProcessExecutor::escape(Platform::getEnv('COMPOSER_BINARY')) . ' ' . implode(' ', $args);
                        if (0 !== $exitCode = $this->executeTty($exec)) {
                            $this->io->writeError(sprintf('<error>Script %s handling the %s event returned with error code ' . $exitCode . '</error>', $callable, $event->getName()), \true, IOInterface::QUIET);
                            throw new \Composer\EventDispatcher\ScriptExecutionException('Error Output: ' . $this->process->getErrorOutput(), $exitCode);
                        }
                    } else {
                        if (!$this->getListeners(new \Composer\EventDispatcher\Event($scriptName))) {
                            $this->io->writeError(sprintf('<warning>You made a reference to a non-existent script %s</warning>', $callable), \true, IOInterface::QUIET);
                        }
                        try {
                            /** @var InstallerEvent $event */
                            $scriptEvent = new ScriptEvent($scriptName, $event->getComposer(), $event->getIO(), $event->isDevMode(), $args, $flags);
                            $scriptEvent->setOriginatingEvent($event);
                            $return = $this->dispatch($scriptName, $scriptEvent);
                        } catch (\Composer\EventDispatcher\ScriptExecutionException $e) {
                            $this->io->writeError(sprintf('<error>Script %s was called via %s</error>', $callable, $event->getName()), \true, IOInterface::QUIET);
                            throw $e;
                        }
                    }
                } elseif ($this->isPhpScript($callable)) {
                    $className = substr($callable, 0, strpos($callable, '::'));
                    $methodName = substr($callable, strpos($callable, '::') + 2);
                    $this->makeAutoloader($event, $callable);
                    if (!class_exists($className)) {
                        $this->io->writeError('<warning>Class ' . $className . ' is not autoloadable, can not call ' . $event->getName() . ' script</warning>', \true, IOInterface::QUIET);
                        continue;
                    }
                    if (!is_callable($callable)) {
                        $this->io->writeError('<warning>Method ' . $callable . ' is not callable, can not call ' . $event->getName() . ' script</warning>', \true, IOInterface::QUIET);
                        continue;
                    }
                    try {
                        $return = \false === $this->executeEventPhpScript($className, $methodName, $event) ? 1 : 0;
                    } catch (\Exception $e) {
                        $message = "Script %s handling the %s event terminated with an exception";
                        $this->io->writeError('<error>' . sprintf($message, $callable, $event->getName()) . '</error>', \true, IOInterface::QUIET);
                        throw $e;
                    }
                } elseif ($this->isCommandClass($callable)) {
                    $className = $callable;
                    $this->makeAutoloader($event, [$callable, 'run']);
                    if (!class_exists($className)) {
                        $this->io->writeError('<warning>Class ' . $className . ' is not autoloadable, can not call ' . $event->getName() . ' script</warning>', \true, IOInterface::QUIET);
                        continue;
                    }
                    if (!is_a($className, Command::class, \true)) {
                        $this->io->writeError('<warning>Class ' . $className . ' does not extend ' . Command::class . ', can not call ' . $event->getName() . ' script</warning>', \true, IOInterface::QUIET);
                        continue;
                    }
                    if (defined('Composer\Script\ScriptEvents::' . str_replace('-', '_', strtoupper($event->getName())))) {
                        $this->io->writeError('<warning>You cannot bind ' . $event->getName() . ' to a Command class, use a non-reserved name</warning>', \true, IOInterface::QUIET);
                        continue;
                    }
                    $app = new Application();
                    $app->setCatchExceptions(\false);
                    if (method_exists($app, 'setCatchErrors')) {
                        $app->setCatchErrors(\false);
                    }
                    $app->setAutoExit(\false);
                    $cmd = new $className($event->getName());
                    // @phpstan-ignore method.notFound, function.alreadyNarrowedType
                    if (method_exists($app, 'addCommand')) {
                        $app->addCommand($cmd);
                    } else {
                        // Compatibility layer for symfony/console <7.4
                        // @phpstan-ignore method.notFound
                        $app->add($cmd);
                    }
                    $app->setDefaultCommand((string) $cmd->getName(), \true);
                    try {
                        $args = implode(' ', array_map(static function ($arg) {
                            return ProcessExecutor::escape($arg);
                        }, $additionalArgs));
                        // reusing the output from $this->io is mostly needed for tests, but generally speaking
                        // it does not hurt to keep the same stream as the current Application
                        if ($this->io instanceof ConsoleIO) {
                            $reflProp = new \ReflectionProperty($this->io, 'output');
                            if (\PHP_VERSION_ID < 80100) {
                                $reflProp->setAccessible(\true);
                            }
                            $output = $reflProp->getValue($this->io);
                        } else {
                            $output = new ConsoleOutput();
                        }
                        $return = $app->run(new StringInput($event->getFlags()['script-alias-input'] ?? $args), $output);
                    } catch (\Exception $e) {
                        $message = "Script %s handling the %s event terminated with an exception";
                        $this->io->writeError('<error>' . sprintf($message, $callable, $event->getName()) . '</error>', \true, IOInterface::QUIET);
                        throw $e;
                    }
                } else {
                    $args = implode(' ', array_map(['Composer\Util\ProcessExecutor', 'escape'], $additionalArgs));
                    // @putenv does not receive arguments
                    if (strpos($callable, '@putenv ') === 0) {
                        $exec = $callable;
                    } else if (str_contains($callable, '@additional_args')) {
                        $exec = str_replace('@additional_args', $args, $callable);
                    } else {
                        $exec = $callable . ($args === '' ? '' : ' ' . $args);
                    }
                    if ($this->io->isVerbose()) {
                        $this->io->writeError(sprintf('> %s: %s', $event->getName(), $exec));
                    } elseif ($this->eventNeedsToOutput($event)) {
                        $this->io->writeError(sprintf('> %s', $exec));
                    }
                    $possibleLocalBinaries = $this->composer->getPackage()->getBinaries();
                    if (count($possibleLocalBinaries) > 0) {
                        foreach ($possibleLocalBinaries as $localExec) {
                            if (Preg::isMatch('{\b' . preg_quote($callable) . '$}', $localExec)) {
                                $caller = BinaryInstaller::determineBinaryCaller($localExec);
                                $exec = Preg::replace('{^' . preg_quote($callable) . '}', $caller . ' ' . $localExec, $exec);
                                break;
                            }
                        }
                    }
                    if (strpos($exec, '@putenv ') === 0) {
                        if (\false === strpos($exec, '=')) {
                            Platform::clearEnv(substr($exec, 8));
                        } else {
                            [$var, $value] = explode('=', substr($exec, 8), 2);
                            Platform::putEnv($var, $value);
                        }
                        continue;
                    }
                    if (strpos($exec, '@php ') === 0) {
                        $pathAndArgs = substr($exec, 5);
                        if (Platform::isWindows()) {
                            $pathAndArgs = Preg::replaceCallback('{^\S+}', static function ($path) {
                                return str_replace('/', '\\', $path[0]);
                            }, $pathAndArgs);
                        }
                        // match somename (not in quote, and not a qualified path) and if it is not a valid path from CWD then try to find it
                        // in $PATH. This allows support for `@php foo` where foo is a binary name found in PATH but not an actual relative path
                        $matched = Preg::isMatchStrictGroups('{^[^\'"\s/\\\\]+}', $pathAndArgs, $match);
                        if ($matched && !file_exists($match[0])) {
                            $finder = new ExecutableFinder();
                            if ($pathToExec = $finder->find($match[0])) {
                                if (Platform::isWindows()) {
                                    $execWithoutExt = Preg::replace('{\.(exe|bat|cmd|com)$}i', '', $pathToExec);
                                    // prefer non-extension file if it exists when executing with PHP
                                    if (file_exists($execWithoutExt)) {
                                        $pathToExec = $execWithoutExt;
                                    }
                                    unset($execWithoutExt);
                                }
                                $pathAndArgs = $pathToExec . substr($pathAndArgs, strlen($match[0]));
                            }
                        }
                        $exec = $this->getPhpExecCommand() . ' ' . $pathAndArgs;
                    } else {
                        $finder = new PhpExecutableFinder();
                        $phpPath = $finder->find(\false);
                        if ($phpPath) {
                            Platform::putEnv('PHP_BINARY', $phpPath);
                        }
                        if (Platform::isWindows()) {
                            $exec = Preg::replaceCallback('{^\S+}', static function ($path) {
                                return str_replace('/', '\\', $path[0]);
                            }, $exec);
                        }
                    }
                    // if composer is being executed, make sure it runs the expected composer from current path
                    // resolution, even if bin-dir contains composer too because the project requires composer/composer
                    // see https://github.com/composer/composer/issues/8748
                    if (strpos($exec, 'composer ') === 0) {
                        $exec = $this->getPhpExecCommand() . ' ' . ProcessExecutor::escape(Platform::getEnv('COMPOSER_BINARY')) . substr($exec, 8);
                    }
                    if (0 !== $exitCode = $this->executeTty($exec)) {
                        $this->io->writeError(sprintf('<error>Script %s handling the %s event returned with error code ' . $exitCode . '</error>', $callable, $event->getName()), \true, IOInterface::QUIET);
                        throw new \Composer\EventDispatcher\ScriptExecutionException('Error Output: ' . $this->process->getErrorOutput(), $exitCode);
                    }
                }
                $returnMax = max($returnMax, $return);
                if ($event->isPropagationStopped()) {
                    break;
                }
            }
        } finally {
            $this->popEvent();
            $knownIdentifiers = [];
            foreach ($autoloadersBefore as $key => $cb) {
                $knownIdentifiers[$this->getCallbackIdentifier($cb)] = ['key' => $key, 'callback' => $cb];
            }
            foreach (spl_autoload_functions() as $cb) {
                // once we get to the first known autoloader, we can leave any appended autoloader without problems
                if (isset($knownIdentifiers[$this->getCallbackIdentifier($cb)]) && $knownIdentifiers[$this->getCallbackIdentifier($cb)]['key'] === 0) {
                    break;
                }
                // other newly appeared prepended autoloaders should be appended instead to ensure Composer loads its classes first
                if ($cb instanceof ClassLoader) {
                    $cb->unregister();
                    $cb->register(\false);
                } else {
                    spl_autoload_unregister($cb);
                    spl_autoload_register($cb);
                }
            }
        }
        return $returnMax;
    }
    protected function executeTty(string $exec): int
    {
        if ($this->io->isInteractive()) {
            return $this->process->executeTty($exec);
        }
        return $this->process->execute($exec);
    }
    protected function getPhpExecCommand(): string
    {
        $finder = new PhpExecutableFinder();
        $phpPath = $finder->find(\false);
        if (!$phpPath) {
            throw new \RuntimeException('Failed to locate PHP binary to execute ' . $phpPath);
        }
        $phpArgs = $finder->findArguments();
        $phpArgs = \count($phpArgs) > 0 ? ' ' . implode(' ', $phpArgs) : '';
        $allowUrlFOpenFlag = ' -d allow_url_fopen=' . ProcessExecutor::escape(ini_get('allow_url_fopen'));
        $disableFunctionsFlag = ' -d disable_functions=' . ProcessExecutor::escape(ini_get('disable_functions'));
        $memoryLimitFlag = ' -d memory_limit=' . ProcessExecutor::escape(ini_get('memory_limit'));
        return ProcessExecutor::escape($phpPath) . $phpArgs . $allowUrlFOpenFlag . $disableFunctionsFlag . $memoryLimitFlag;
    }
    /**
     * @param Event  $event      Event invoking the PHP callable
     *
     * @return mixed
     */
    protected function executeEventPhpScript(string $className, string $methodName, \Composer\EventDispatcher\Event $event)
    {
        if ($this->io->isVerbose()) {
            $this->io->writeError(sprintf('> %s: %s::%s', $event->getName(), $className, $methodName));
        } elseif ($this->eventNeedsToOutput($event)) {
            $this->io->writeError(sprintf('> %s::%s', $className, $methodName));
        }
        return $className::$methodName($event);
    }
    private function eventNeedsToOutput(\Composer\EventDispatcher\Event $event): bool
    {
        // do not output the command being run when using `composer exec` as it is fairly obvious the user is running it
        if ($event->getName() === '__exec_command') {
            return \false;
        }
        // do not output the command being run when using `composer <script-name>` as it is also fairly obvious the user is running it
        if (($event->getFlags()['script-alias-input'] ?? null) !== null) {
            return \false;
        }
        return \true;
    }
    /**
     * Add a listener for a particular event
     *
     * @param string          $eventName The event name - typically a constant
     * @param callable|string $listener  A callable expecting an event argument, or a command string to be executed (same as a composer.json "scripts" entry)
     * @param int             $priority  A higher value represents a higher priority
     */
    public function addListener(string $eventName, $listener, int $priority = 0): void
    {
        $this->listeners[$eventName][$priority][] = $listener;
    }
    /**
     * @param callable|object $listener A callable or an object instance for which all listeners should be removed
     */
    public function removeListener($listener): void
    {
        foreach ($this->listeners as $eventName => $priorities) {
            foreach ($priorities as $priority => $listeners) {
                foreach ($listeners as $index => $candidate) {
                    if ($listener === $candidate || is_array($candidate) && is_object($listener) && $candidate[0] === $listener) {
                        unset($this->listeners[$eventName][$priority][$index]);
                    }
                }
            }
        }
    }
    /**
     * Adds object methods as listeners for the events in getSubscribedEvents
     *
     * @see EventSubscriberInterface
     */
    public function addSubscriber(\Composer\EventDispatcher\EventSubscriberInterface $subscriber): void
    {
        foreach ($subscriber->getSubscribedEvents() as $eventName => $params) {
            if (is_string($params)) {
                $this->addListener($eventName, [$subscriber, $params]);
            } elseif (is_string($params[0])) {
                $this->addListener($eventName, [$subscriber, $params[0]], $params[1] ?? 0);
            } else {
                foreach ($params as $listener) {
                    $this->addListener($eventName, [$subscriber, $listener[0]], $listener[1] ?? 0);
                }
            }
        }
    }
    /**
     * Retrieves all listeners for a given event
     *
     * @return array<callable|string> All listeners: callables and scripts
     */
    protected function getListeners(\Composer\EventDispatcher\Event $event): array
    {
        $scriptListeners = $this->runScripts ? $this->getScriptListeners($event) : [];
        if (!isset($this->listeners[$event->getName()][0])) {
            $this->listeners[$event->getName()][0] = [];
        }
        krsort($this->listeners[$event->getName()]);
        $listeners = $this->listeners;
        $listeners[$event->getName()][0] = array_merge($listeners[$event->getName()][0], $scriptListeners);
        return array_merge(...$listeners[$event->getName()]);
    }
    /**
     * Checks if an event has listeners registered
     */
    public function hasEventListeners(\Composer\EventDispatcher\Event $event): bool
    {
        $listeners = $this->getListeners($event);
        return count($listeners) > 0;
    }
    /**
     * Finds all listeners defined as scripts in the package
     *
     * @param  Event $event Event object
     * @return string[] Listeners
     */
    protected function getScriptListeners(\Composer\EventDispatcher\Event $event): array
    {
        $package = $this->composer->getPackage();
        $scripts = $package->getScripts();
        if (empty($scripts[$event->getName()])) {
            return [];
        }
        if (in_array($event->getName(), $this->skipScripts, \true)) {
            $this->io->writeError('Skipped script listeners for <info>' . $event->getName() . '</info> because of COMPOSER_SKIP_SCRIPTS', \true, IOInterface::VERBOSE);
            return [];
        }
        return $scripts[$event->getName()];
    }
    /**
     * Checks if string given references a class path and method
     */
    protected function isPhpScript(string $callable): bool
    {
        return \false === strpos($callable, ' ') && \false !== strpos($callable, '::');
    }
    /**
     * Checks if string given references a command class
     */
    protected function isCommandClass(string $callable): bool
    {
        return str_contains($callable, '\\') && !str_contains($callable, ' ') && str_ends_with($callable, 'Command');
    }
    /**
     * Checks if string given references a composer run-script
     */
    protected function isComposerScript(string $callable): bool
    {
        return str_starts_with($callable, '@') && !str_starts_with($callable, '@php ') && !str_starts_with($callable, '@putenv ');
    }
    /**
     * Push an event to the stack of active event
     *
     * @throws \RuntimeException
     */
    protected function pushEvent(\Composer\EventDispatcher\Event $event): int
    {
        $eventName = $event->getName();
        if (in_array($eventName, $this->eventStack)) {
            throw new \RuntimeException(sprintf("Circular call to script handler '%s' detected", $eventName));
        }
        return array_push($this->eventStack, $eventName);
    }
    /**
     * Pops the active event from the stack
     */
    protected function popEvent(): ?string
    {
        return array_pop($this->eventStack);
    }
    private function ensureBinDirIsInPath(): void
    {
        $pathEnv = 'PATH';
        // checking if only Path and not PATH is set then we probably need to update the Path env
        // on Windows getenv is case-insensitive so we cannot check it via Platform::getEnv and
        // we need to check in $_SERVER directly
        if (!isset($_SERVER[$pathEnv]) && isset($_SERVER['Path'])) {
            $pathEnv = 'Path';
        }
        // add the bin dir to the PATH to make local binaries of deps usable in scripts
        $binDir = $this->composer->getConfig()->get('bin-dir');
        if (is_dir($binDir)) {
            $binDir = realpath($binDir);
            $pathValue = (string) Platform::getEnv($pathEnv);
            if (!Preg::isMatch('{(^|' . \PATH_SEPARATOR . ')' . preg_quote($binDir) . '($|' . \PATH_SEPARATOR . ')}', $pathValue)) {
                Platform::putEnv($pathEnv, $binDir . \PATH_SEPARATOR . $pathValue);
            }
        }
    }
    /**
     * @param callable $cb DO NOT MOVE TO TYPE HINT as private autoload callbacks are not technically callable
     */
    private function getCallbackIdentifier($cb): string
    {
        if (is_string($cb)) {
            return 'fn:' . $cb;
        }
        if (is_object($cb)) {
            return 'obj:' . spl_object_hash($cb);
        }
        if (is_array($cb)) {
            return 'array:' . (is_string($cb[0]) ? $cb[0] : get_class($cb[0]) . '#' . spl_object_hash($cb[0])) . '::' . $cb[1];
        }
        // not great but also do not want to break everything here
        return 'unsupported';
    }
    /**
     * @param mixed $callable Technically a callable shape but as the class may not be autoloadable yet PHP might not see it this way, so we cannot type hint as such
     */
    private function makeAutoloader(\Composer\EventDispatcher\Event $event, $callable): void
    {
        if (!$this->composer instanceof Composer) {
            return;
        }
        if (is_array($callable)) {
            if (is_string($callable[0])) {
                $callableKey = $callable[0] . '::' . $callable[1];
            } else {
                $callableKey = get_class($callable[0]) . '::' . $callable[1];
            }
        } elseif (is_string($callable)) {
            $callableKey = $callable;
        } elseif ($callable instanceof \Closure) {
            $callableKey = 'closure';
        } else {
            $callableKey = 'unknown';
        }
        if (isset($this->previousListeners[$callableKey])) {
            return;
        }
        $this->previousListeners[$callableKey] = \true;
        $package = $this->composer->getPackage();
        $packages = $this->composer->getRepositoryManager()->getLocalRepository()->getCanonicalPackages();
        $generator = $this->composer->getAutoloadGenerator();
        $hash = implode(',', array_map(static function (PackageInterface $p) {
            return $p->getName() . '/' . $p->getVersion();
        }, $packages));
        if ($event instanceof ScriptEvent || $event instanceof PackageEvent || $event instanceof InstallerEvent) {
            $generator->setDevMode($event->isDevMode());
            $hash .= $event->isDevMode() ? '/dev' : '';
        }
        $hash = hash('sha256', $hash);
        if ($this->previousHash === $hash) {
            return;
        }
        $this->previousHash = $hash;
        $packageMap = $generator->buildPackageMap($this->composer->getInstallationManager(), $package, $packages);
        $map = $generator->parseAutoloads($packageMap, $package);
        if ($this->loader !== null) {
            $this->loader->unregister();
        }
        $this->loader = $generator->createLoader($map, $this->composer->getConfig()->get('vendor-dir'));
        $this->loader->register(\false);
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer\EventDispatcher;

/**
 * An EventSubscriber knows which events it is interested in.
 *
 * If an EventSubscriber is added to an EventDispatcher, the manager invokes
 * {@link getSubscribedEvents} and registers the subscriber as a listener for all
 * returned events.
 *
 * @author Guilherme Blanco <guilhermeblanco@hotmail.com>
 * @author Jonathan Wage <jonwage@gmail.com>
 * @author Roman Borschel <roman@code-factory.org>
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
interface EventSubscriberInterface
{
    /**
     * Returns an array of event names this subscriber wants to listen to.
     *
     * The array keys are event names and the value can be:
     *
     * * The method name to call (priority defaults to 0)
     * * An array composed of the method name to call and the priority
     * * An array of arrays composed of the method names to call and respective
     *   priorities, or 0 if unset
     *
     * For instance:
     *
     * * array('eventName' => 'methodName')
     * * array('eventName' => array('methodName', $priority))
     * * array('eventName' => array(array('methodName1', $priority), array('methodName2'))
     *
     * @return array<string, string|array{0: string, 1?: int}|array<array{0: string, 1?: int}>> The event names to listen to
     */
    public static function getSubscribedEvents();
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer;

use Composer\Package\RootPackageInterface;
use Composer\Util\Loop;
use Composer\Repository\RepositoryManager;
use Composer\Installer\InstallationManager;
use Composer\EventDispatcher\EventDispatcher;
/**
 * @author Jordi Boggiano <j.boggiano@seld.be>
 */
class PartialComposer
{
    /**
     * @var bool
     */
    private $global = \false;
    /**
     * @var RootPackageInterface
     */
    private $package;
    /**
     * @var Loop
     */
    private $loop;
    /**
     * @var RepositoryManager
     */
    private $repositoryManager;
    /**
     * @var InstallationManager
     */
    private $installationManager;
    /**
     * @var Config
     */
    private $config;
    /**
     * @var EventDispatcher
     */
    private $eventDispatcher;
    public function setPackage(RootPackageInterface $package): void
    {
        $this->package = $package;
    }
    public function getPackage(): RootPackageInterface
    {
        return $this->package;
    }
    public function setConfig(\Composer\Config $config): void
    {
        $this->config = $config;
    }
    public function getConfig(): \Composer\Config
    {
        return $this->config;
    }
    public function setLoop(Loop $loop): void
    {
        $this->loop = $loop;
    }
    public function getLoop(): Loop
    {
        return $this->loop;
    }
    public function setRepositoryManager(RepositoryManager $manager): void
    {
        $this->repositoryManager = $manager;
    }
    public function getRepositoryManager(): RepositoryManager
    {
        return $this->repositoryManager;
    }
    public function setInstallationManager(InstallationManager $manager): void
    {
        $this->installationManager = $manager;
    }
    public function getInstallationManager(): InstallationManager
    {
        return $this->installationManager;
    }
    public function setEventDispatcher(EventDispatcher $eventDispatcher): void
    {
        $this->eventDispatcher = $eventDispatcher;
    }
    public function getEventDispatcher(): EventDispatcher
    {
        return $this->eventDispatcher;
    }
    public function isGlobal(): bool
    {
        return $this->global;
    }
    public function setGlobal(): void
    {
        $this->global = \true;
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer\Platform;

use Composer\Pcre\Preg;
class Runtime
{
    /**
     * @param class-string $class
     */
    public function hasConstant(string $constant, ?string $class = null): bool
    {
        return defined(ltrim($class . '::' . $constant, ':'));
    }
    /**
     * @param class-string $class
     *
     * @return mixed
     */
    public function getConstant(string $constant, ?string $class = null)
    {
        return constant(ltrim($class . '::' . $constant, ':'));
    }
    public function hasFunction(string $fn): bool
    {
        return function_exists($fn);
    }
    /**
     * @param mixed[] $arguments
     *
     * @return mixed
     */
    public function invoke(callable $callable, array $arguments = [])
    {
        return $callable(...$arguments);
    }
    /**
     * @param class-string $class
     */
    public function hasClass(string $class): bool
    {
        return class_exists($class, \false);
    }
    /**
     * @template T of object
     * @param mixed[] $arguments
     *
     * @phpstan-param class-string<T> $class
     * @phpstan-return T
     *
     * @throws \ReflectionException
     */
    public function construct(string $class, array $arguments = []): object
    {
        if (empty($arguments)) {
            return new $class();
        }
        $refl = new \ReflectionClass($class);
        return $refl->newInstanceArgs($arguments);
    }
    /** @return string[] */
    public function getExtensions(): array
    {
        return get_loaded_extensions();
    }
    public function getExtensionVersion(string $extension): string
    {
        $version = phpversion($extension);
        if ($version === \false) {
            $version = '0';
        }
        return $version;
    }
    /**
     * @throws \ReflectionException
     */
    public function getExtensionInfo(string $extension): string
    {
        $reflector = new \ReflectionExtension($extension);
        ob_start();
        $reflector->info();
        $info = (string) ob_get_clean();
        if ('cli' === \PHP_SAPI) {
            return $info;
        }
        return self::parseHtmlExtensionInfo($info);
    }
    /**
     * @internal Only public for unit tests
     */
    public static function parseHtmlExtensionInfo(string $html): string
    {
        $result = [];
        if ((bool) Preg::match('~<h2>\s*<a[^>]*>([^<]+)</a>\s*</h2>~i', $html, $matches)) {
            $result[] = trim(html_entity_decode($matches[1]));
            $result[] = '';
        }
        if ((bool) Preg::matchAll('~<tr>\s*<td class="e">\s*(.*?)\s*</td>\s*<td class="v">\s*(.*?)\s*</td>\s*</tr>~is', $html, $matches)) {
            $count = min(\count($matches[1]), \count($matches[2]));
            for ($i = 0; $i < $count; $i++) {
                $key = trim(html_entity_decode(strip_tags($matches[1][$i])));
                $value = trim(html_entity_decode(strip_tags($matches[2][$i])));
                $result[] = $key . ' => ' . $value;
            }
        }
        return implode("\n", $result);
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer\Platform;

use Composer\Util\Platform;
use Composer\Util\ProcessExecutor;
use _ContaoManager\Symfony\Component\Process\ExecutableFinder;
class HhvmDetector
{
    /** @var string|false|null */
    private static $hhvmVersion = null;
    /** @var ?ExecutableFinder */
    private $executableFinder;
    /** @var ?ProcessExecutor */
    private $processExecutor;
    public function __construct(?ExecutableFinder $executableFinder = null, ?ProcessExecutor $processExecutor = null)
    {
        $this->executableFinder = $executableFinder;
        $this->processExecutor = $processExecutor;
    }
    public function reset(): void
    {
        self::$hhvmVersion = null;
    }
    public function getVersion(): ?string
    {
        if (null !== self::$hhvmVersion) {
            return self::$hhvmVersion ?: null;
        }
        self::$hhvmVersion = defined('HHVM_VERSION') ? HHVM_VERSION : null;
        if (self::$hhvmVersion === null && !Platform::isWindows()) {
            self::$hhvmVersion = \false;
            $this->executableFinder = $this->executableFinder ?: new ExecutableFinder();
            $hhvmPath = $this->executableFinder->find('hhvm');
            if ($hhvmPath !== null) {
                $this->processExecutor = $this->processExecutor ?? new ProcessExecutor();
                $exitCode = $this->processExecutor->execute([$hhvmPath, '--php', '-d', 'hhvm.jit=0', '-r', 'echo HHVM_VERSION;'], self::$hhvmVersion);
                if ($exitCode !== 0) {
                    self::$hhvmVersion = \false;
                }
            }
        }
        return self::$hhvmVersion ?: null;
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer\Platform;

use Composer\Pcre\Preg;
/**
 * @author Lars Strojny <lars@strojny.net>
 */
class Version
{
    /**
     * @param bool $isFips Set by the method
     *
     * @param-out bool $isFips
     */
    public static function parseOpenssl(string $opensslVersion, ?bool &$isFips): ?string
    {
        $isFips = \false;
        if (!Preg::isMatchStrictGroups('/^(?<version>[0-9.]+)(?<patch>[a-z]{0,2})(?<suffix>(?:-?(?:dev|pre|alpha|beta|rc|fips)[\d]*)*)(?:-\w+)?(?: \(.+?\))?$/', $opensslVersion, $matches)) {
            return null;
        }
        // OpenSSL 1 used 1.2.3a style versioning, 3+ uses semver
        $patch = '';
        if (version_compare($matches['version'], '3.0.0', '<')) {
            $patch = '.' . self::convertAlphaVersionToIntVersion($matches['patch']);
        }
        $isFips = strpos($matches['suffix'], 'fips') !== \false;
        $suffix = strtr('-' . ltrim($matches['suffix'], '-'), ['-fips' => '', '-pre' => '-alpha']);
        return rtrim($matches['version'] . $patch . $suffix, '-');
    }
    public static function parseLibjpeg(string $libjpegVersion): ?string
    {
        if (!Preg::isMatchStrictGroups('/^(?<major>\d+)(?<minor>[a-z]*)$/', $libjpegVersion, $matches)) {
            return null;
        }
        return $matches['major'] . '.' . self::convertAlphaVersionToIntVersion($matches['minor']);
    }
    public static function parseZoneinfoVersion(string $zoneinfoVersion): ?string
    {
        if (!Preg::isMatchStrictGroups('/^(?<year>\d{4})(?<revision>[a-z]*)$/', $zoneinfoVersion, $matches)) {
            return null;
        }
        return $matches['year'] . '.' . self::convertAlphaVersionToIntVersion($matches['revision']);
    }
    /**
     * "" => 0, "a" => 1, "zg" => 33
     */
    private static function convertAlphaVersionToIntVersion(string $alpha): int
    {
        return strlen($alpha) * (-ord('a') + 1) + array_sum(array_map('ord', str_split($alpha)));
    }
    public static function convertLibxpmVersionId(int $versionId): string
    {
        return self::convertVersionId($versionId, 100);
    }
    public static function convertOpenldapVersionId(int $versionId): string
    {
        return self::convertVersionId($versionId, 100);
    }
    private static function convertVersionId(int $versionId, int $base): string
    {
        return sprintf('%d.%d.%d', $versionId / ($base * $base), (int) ($versionId / $base) % $base, $versionId % $base);
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer\IO;

use Composer\Pcre\Preg;
use _ContaoManager\Symfony\Component\Console\Helper\QuestionHelper;
use _ContaoManager\Symfony\Component\Console\Output\StreamOutput;
use _ContaoManager\Symfony\Component\Console\Formatter\OutputFormatterInterface;
use _ContaoManager\Symfony\Component\Console\Input\StreamableInputInterface;
use _ContaoManager\Symfony\Component\Console\Input\StringInput;
use _ContaoManager\Symfony\Component\Console\Helper\HelperSet;
/**
 * @author Jordi Boggiano <j.boggiano@seld.be>
 */
class BufferIO extends \Composer\IO\ConsoleIO
{
    public function __construct(string $input = '', int $verbosity = StreamOutput::VERBOSITY_NORMAL, ?OutputFormatterInterface $formatter = null)
    {
        $input = new StringInput($input);
        $input->setInteractive(\false);
        $stream = fopen('php://memory', 'rw');
        if ($stream === \false) {
            throw new \RuntimeException('Unable to open memory output stream');
        }
        $output = new StreamOutput($stream, $verbosity, $formatter !== null ? $formatter->isDecorated() : \false, $formatter);
        parent::__construct($input, $output, new HelperSet([new QuestionHelper()]));
    }
    /**
     * @return string output
     */
    public function getOutput(): string
    {
        assert($this->output instanceof StreamOutput);
        fseek($this->output->getStream(), 0);
        $output = (string) stream_get_contents($this->output->getStream());
        $output = Preg::replaceCallback("{(?<=^|\n|\x08)(.+?)(\x08+)}", static function ($matches): string {
            $pre = strip_tags($matches[1]);
            if (strlen($pre) === strlen($matches[2])) {
                return '';
            }
            // TODO reverse parse the string, skipping span tags and \033\[([0-9;]+)m(.*?)\033\[0m style blobs
            return rtrim($matches[1]) . "\n";
        }, $output);
        return $output;
    }
    /**
     * @param string[] $inputs
     *
     * @see createStream
     */
    public function setUserInputs(array $inputs): void
    {
        if (!$this->input instanceof StreamableInputInterface) {
            throw new \RuntimeException('Setting the user inputs requires at least the version 3.2 of the symfony/console component.');
        }
        $this->input->setStream($this->createStream($inputs));
        $this->input->setInteractive(\true);
    }
    /**
     * @param string[] $inputs
     *
     * @return resource stream
     */
    private function createStream(array $inputs)
    {
        $stream = fopen('php://memory', 'r+');
        if ($stream === \false) {
            throw new \RuntimeException('Unable to open memory output stream');
        }
        foreach ($inputs as $input) {
            fwrite($stream, $input . \PHP_EOL);
        }
        rewind($stream);
        return $stream;
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer\IO;

use Composer\Pcre\Preg;
use Composer\Question\StrictConfirmationQuestion;
use _ContaoManager\Symfony\Component\Console\Helper\HelperSet;
use _ContaoManager\Symfony\Component\Console\Helper\ProgressBar;
use _ContaoManager\Symfony\Component\Console\Helper\Table;
use _ContaoManager\Symfony\Component\Console\Input\InputInterface;
use _ContaoManager\Symfony\Component\Console\Output\ConsoleOutputInterface;
use _ContaoManager\Symfony\Component\Console\Output\OutputInterface;
use _ContaoManager\Symfony\Component\Console\Question\ChoiceQuestion;
use _ContaoManager\Symfony\Component\Console\Question\Question;
/**
 * The Input/Output helper.
 *
 * @author François Pluchino <francois.pluchino@opendisplay.com>
 * @author Jordi Boggiano <j.boggiano@seld.be>
 */
class ConsoleIO extends \Composer\IO\BaseIO
{
    /** @var InputInterface */
    protected $input;
    /** @var OutputInterface */
    protected $output;
    /** @var HelperSet */
    protected $helperSet;
    /** @var string */
    protected $lastMessage = '';
    /** @var string */
    protected $lastMessageErr = '';
    /** @var float */
    private $startTime;
    /** @var array<IOInterface::*, OutputInterface::VERBOSITY_*> */
    private $verbosityMap;
    /**
     * Constructor.
     *
     * @param InputInterface  $input     The input instance
     * @param OutputInterface $output    The output instance
     * @param HelperSet       $helperSet The helperSet instance
     */
    public function __construct(InputInterface $input, OutputInterface $output, HelperSet $helperSet)
    {
        $this->input = $input;
        $this->output = $output;
        $this->helperSet = $helperSet;
        $this->verbosityMap = [self::QUIET => OutputInterface::VERBOSITY_QUIET, self::NORMAL => OutputInterface::VERBOSITY_NORMAL, self::VERBOSE => OutputInterface::VERBOSITY_VERBOSE, self::VERY_VERBOSE => OutputInterface::VERBOSITY_VERY_VERBOSE, self::DEBUG => OutputInterface::VERBOSITY_DEBUG];
    }
    /**
     * @return void
     */
    public function enableDebugging(float $startTime)
    {
        $this->startTime = $startTime;
    }
    /**
     * @inheritDoc
     */
    public function isInteractive()
    {
        return $this->input->isInteractive();
    }
    /**
     * @inheritDoc
     */
    public function isDecorated()
    {
        return $this->output->isDecorated();
    }
    /**
     * @inheritDoc
     */
    public function isVerbose()
    {
        return $this->output->isVerbose();
    }
    /**
     * @inheritDoc
     */
    public function isVeryVerbose()
    {
        return $this->output->isVeryVerbose();
    }
    /**
     * @inheritDoc
     */
    public function isDebug()
    {
        return $this->output->isDebug();
    }
    /**
     * @inheritDoc
     */
    public function write($messages, bool $newline = \true, int $verbosity = self::NORMAL)
    {
        $messages = self::sanitize($messages);
        $this->doWrite($messages, $newline, \false, $verbosity);
    }
    /**
     * @inheritDoc
     */
    public function writeError($messages, bool $newline = \true, int $verbosity = self::NORMAL)
    {
        $messages = self::sanitize($messages);
        $this->doWrite($messages, $newline, \true, $verbosity);
    }
    /**
     * @inheritDoc
     */
    public function writeRaw($messages, bool $newline = \true, int $verbosity = self::NORMAL)
    {
        $this->doWrite($messages, $newline, \false, $verbosity, \true);
    }
    /**
     * @inheritDoc
     */
    public function writeErrorRaw($messages, bool $newline = \true, int $verbosity = self::NORMAL)
    {
        $this->doWrite($messages, $newline, \true, $verbosity, \true);
    }
    /**
     * @param string[]|string $messages
     */
    private function doWrite($messages, bool $newline, bool $stderr, int $verbosity, bool $raw = \false): void
    {
        $sfVerbosity = $this->verbosityMap[$verbosity];
        if ($sfVerbosity > $this->output->getVerbosity()) {
            return;
        }
        if ($raw) {
            $sfVerbosity |= OutputInterface::OUTPUT_RAW;
        }
        if (null !== $this->startTime) {
            $memoryUsage = memory_get_usage() / 1024 / 1024;
            $timeSpent = microtime(\true) - $this->startTime;
            $messages = array_map(static function ($message) use ($memoryUsage, $timeSpent): string {
                return sprintf('[%.1fMiB/%.2fs] %s', $memoryUsage, $timeSpent, $message);
            }, (array) $messages);
        }
        if (\true === $stderr && $this->output instanceof ConsoleOutputInterface) {
            $this->output->getErrorOutput()->write($messages, $newline, $sfVerbosity);
            $this->lastMessageErr = implode($newline ? "\n" : '', (array) $messages);
            return;
        }
        $this->output->write($messages, $newline, $sfVerbosity);
        $this->lastMessage = implode($newline ? "\n" : '', (array) $messages);
    }
    /**
     * @inheritDoc
     */
    public function overwrite($messages, bool $newline = \true, ?int $size = null, int $verbosity = self::NORMAL)
    {
        $this->doOverwrite($messages, $newline, $size, \false, $verbosity);
    }
    /**
     * @inheritDoc
     */
    public function overwriteError($messages, bool $newline = \true, ?int $size = null, int $verbosity = self::NORMAL)
    {
        $this->doOverwrite($messages, $newline, $size, \true, $verbosity);
    }
    /**
     * @param string[]|string $messages
     */
    private function doOverwrite($messages, bool $newline, ?int $size, bool $stderr, int $verbosity): void
    {
        // messages can be an array, let's convert it to string anyway
        $messages = implode($newline ? "\n" : '', (array) $messages);
        // since overwrite is supposed to overwrite last message...
        if (!isset($size)) {
            // removing possible formatting of lastMessage with strip_tags
            $size = strlen(strip_tags($stderr ? $this->lastMessageErr : $this->lastMessage));
        }
        // ...let's fill its length with backspaces
        $this->doWrite(str_repeat("\x08", $size), \false, $stderr, $verbosity);
        // write the new message
        $this->doWrite($messages, \false, $stderr, $verbosity);
        // In cmd.exe on Win8.1 (possibly 10?), the line can not be cleared, so we need to
        // track the length of previous output and fill it with spaces to make sure the line is cleared.
        // See https://github.com/composer/composer/pull/5836 for more details
        $fill = $size - strlen(strip_tags($messages));
        if ($fill > 0) {
            // whitespace whatever has left
            $this->doWrite(str_repeat(' ', $fill), \false, $stderr, $verbosity);
            // move the cursor back
            $this->doWrite(str_repeat("\x08", $fill), \false, $stderr, $verbosity);
        }
        if ($newline) {
            $this->doWrite('', \true, $stderr, $verbosity);
        }
        if ($stderr) {
            $this->lastMessageErr = $messages;
        } else {
            $this->lastMessage = $messages;
        }
    }
    /**
     * @return ProgressBar
     */
    public function getProgressBar(int $max = 0)
    {
        return new ProgressBar($this->getErrorOutput(), $max);
    }
    /**
     * @inheritDoc
     */
    public function ask($question, $default = null)
    {
        /** @var \Symfony\Component\Console\Helper\QuestionHelper $helper */
        $helper = $this->helperSet->get('question');
        $question = new Question(self::sanitize($question), is_string($default) ? self::sanitize($default) : $default);
        return $helper->ask($this->input, $this->getErrorOutput(), $question);
    }
    /**
     * @inheritDoc
     */
    public function askConfirmation($question, $default = \true)
    {
        /** @var \Symfony\Component\Console\Helper\QuestionHelper $helper */
        $helper = $this->helperSet->get('question');
        $question = new StrictConfirmationQuestion(self::sanitize($question), is_string($default) ? self::sanitize($default) : $default);
        return $helper->ask($this->input, $this->getErrorOutput(), $question);
    }
    /**
     * @inheritDoc
     */
    public function askAndValidate($question, $validator, $attempts = null, $default = null)
    {
        /** @var \Symfony\Component\Console\Helper\QuestionHelper $helper */
        $helper = $this->helperSet->get('question');
        $question = new Question(self::sanitize($question), is_string($default) ? self::sanitize($default) : $default);
        $question->setValidator($validator);
        $question->setMaxAttempts($attempts);
        return $helper->ask($this->input, $this->getErrorOutput(), $question);
    }
    /**
     * @inheritDoc
     */
    public function askAndHideAnswer($question)
    {
        /** @var \Symfony\Component\Console\Helper\QuestionHelper $helper */
        $helper = $this->helperSet->get('question');
        $question = new Question(self::sanitize($question));
        $question->setHidden(\true);
        return $helper->ask($this->input, $this->getErrorOutput(), $question);
    }
    /**
     * @inheritDoc
     */
    public function select($question, $choices, $default, $attempts = \false, $errorMessage = 'Value "%s" is invalid', $multiselect = \false)
    {
        /** @var \Symfony\Component\Console\Helper\QuestionHelper $helper */
        $helper = $this->helperSet->get('question');
        $question = new ChoiceQuestion(self::sanitize($question), self::sanitize($choices), is_string($default) ? self::sanitize($default) : $default);
        $question->setMaxAttempts($attempts ?: null);
        // IOInterface requires false, and Question requires null or int
        $question->setErrorMessage($errorMessage);
        $question->setMultiselect($multiselect);
        $result = $helper->ask($this->input, $this->getErrorOutput(), $question);
        $isAssoc = (bool) \count(array_filter(array_keys($choices), 'is_string'));
        if ($isAssoc) {
            return $result;
        }
        if (!is_array($result)) {
            return (string) array_search($result, $choices, \true);
        }
        $results = [];
        foreach ($choices as $index => $choice) {
            if (in_array($choice, $result, \true)) {
                $results[] = (string) $index;
            }
        }
        return $results;
    }
    public function getTable(): Table
    {
        return new Table($this->output);
    }
    private function getErrorOutput(): OutputInterface
    {
        if ($this->output instanceof ConsoleOutputInterface) {
            return $this->output->getErrorOutput();
        }
        return $this->output;
    }
    /**
     * Sanitize string to remove control characters
     *
     * If $allowNewlines is true, \x0A (\n) and \x0D\x0A (\r\n) are let through. Single \r are still sanitized away to prevent overwriting whole lines.
     *
     * All other control chars (except NULL bytes) as well as ANSI escape sequences are removed.
     *
     * Invalid unicode sequences are turned into question marks.
     *
     * @param string|iterable<string> $messages
     * @return string|array<string>
     * @phpstan-return ($messages is string ? string : array<string>)
     */
    public static function sanitize($messages, bool $allowNewlines = \true)
    {
        // Match ANSI escape sequences:
        // - CSI (Control Sequence Introducer): ESC [ params intermediate final
        // - OSC (Operating System Command): ESC ] ... ESC \ or BEL
        // - Other ESC sequences: ESC followed by any character
        $escapePattern = '\x1B\[[\x30-\x3F]*[\x20-\x2F]*[\x40-\x7E]|\x1B\].*?(?:\x1B\\\\|\x07)|\x1B.';
        $pattern = $allowNewlines ? "{{$escapePattern}|[\x01-\t\v\f\x0e-\x1a]|\r(?!\n)}u" : "{{$escapePattern}|[\x01-\x1a]}u";
        if (is_string($messages)) {
            $messages = self::ensureValidUtf8($messages);
            return Preg::replace($pattern, '', $messages);
        }
        $sanitized = [];
        foreach ($messages as $key => $message) {
            $message = self::ensureValidUtf8($message);
            $sanitized[$key] = Preg::replace($pattern, '', $message);
        }
        return $sanitized;
    }
    /**
     * Ensures a string is valid UTF-8, replacing invalid byte sequences with '?'
     */
    private static function ensureValidUtf8(string $string): string
    {
        // Quick check: if string is already valid UTF-8, return as-is
        if (function_exists('mb_check_encoding') && mb_check_encoding($string, 'UTF-8')) {
            return $string;
        }
        // Use mb_convert_encoding to replace invalid sequences with '?'
        // This makes it visible when data quality issues occur
        if (function_exists('mb_convert_encoding')) {
            return (string) mb_convert_encoding($string, 'UTF-8', 'UTF-8');
        }
        // Fallback to iconv if mbstring unavailable
        if (function_exists('iconv')) {
            $cleaned = @iconv('UTF-8', 'UTF-8//TRANSLIT', $string);
            if ($cleaned !== \false) {
                return $cleaned;
            }
        }
        // Last resort: return as-is (should never happen - Composer requires mbstring OR iconv)
        return $string;
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer\IO;

use Composer\Config;
use Composer\Pcre\Preg;
use Composer\Util\ProcessExecutor;
use Composer\Util\Silencer;
use _ContaoManager\Psr\Log\LogLevel;
abstract class BaseIO implements \Composer\IO\IOInterface
{
    /** @var array<string, array{username: string|null, password: string|null}> */
    protected $authentications = [];
    /**
     * @inheritDoc
     */
    public function getAuthentications()
    {
        return $this->authentications;
    }
    /**
     * @return void
     */
    public function resetAuthentications()
    {
        $this->authentications = [];
    }
    /**
     * @inheritDoc
     */
    public function hasAuthentication($repositoryName)
    {
        return isset($this->authentications[$repositoryName]);
    }
    /**
     * @inheritDoc
     */
    public function getAuthentication($repositoryName)
    {
        if (isset($this->authentications[$repositoryName])) {
            return $this->authentications[$repositoryName];
        }
        return ['username' => null, 'password' => null];
    }
    /**
     * @inheritDoc
     */
    public function setAuthentication($repositoryName, $username, $password = null)
    {
        $this->authentications[$repositoryName] = ['username' => $username, 'password' => $password];
    }
    /**
     * @inheritDoc
     */
    public function writeRaw($messages, bool $newline = \true, int $verbosity = self::NORMAL)
    {
        $this->write($messages, $newline, $verbosity);
    }
    /**
     * @inheritDoc
     */
    public function writeErrorRaw($messages, bool $newline = \true, int $verbosity = self::NORMAL)
    {
        $this->writeError($messages, $newline, $verbosity);
    }
    /**
     * Check for overwrite and set the authentication information for the repository.
     *
     * @param string $repositoryName The unique name of repository
     * @param string $username       The username
     * @param string $password       The password
     *
     * @return void
     */
    protected function checkAndSetAuthentication(string $repositoryName, string $username, ?string $password = null)
    {
        if ($this->hasAuthentication($repositoryName)) {
            $auth = $this->getAuthentication($repositoryName);
            if ($auth['username'] === $username && $auth['password'] === $password) {
                return;
            }
            $this->writeError(sprintf("<warning>Warning: You should avoid overwriting already defined auth settings for %s.</warning>", $repositoryName));
        }
        $this->setAuthentication($repositoryName, $username, $password);
    }
    /**
     * @inheritDoc
     */
    public function loadConfiguration(Config $config)
    {
        $bitbucketOauth = $config->get('bitbucket-oauth');
        $githubOauth = $config->get('github-oauth');
        $gitlabOauth = $config->get('gitlab-oauth');
        $gitlabToken = $config->get('gitlab-token');
        $forgejoToken = $config->get('forgejo-token');
        $httpBasic = $config->get('http-basic');
        $bearerToken = $config->get('bearer');
        $customHeaders = $config->get('custom-headers');
        $clientCertificate = $config->get('client-certificate');
        // reload oauth tokens from config if available
        foreach ($bitbucketOauth as $domain => $cred) {
            $this->checkAndSetAuthentication($domain, $cred['consumer-key'], $cred['consumer-secret']);
        }
        foreach ($githubOauth as $domain => $token) {
            if ($domain !== 'github.com' && !in_array($domain, $config->get('github-domains'), \true)) {
                $this->debug($domain . ' is not in the configured github-domains, adding it implicitly as authentication is configured for this domain');
                $config->merge(['config' => ['github-domains' => array_merge($config->get('github-domains'), [$domain])]], 'implicit-due-to-auth');
            }
            // allowed chars for GH tokens are from https://github.blog/changelog/2021-03-04-authentication-token-format-updates/
            // plus dots which were at some point used for GH app integration tokens
            if (!Preg::isMatch('{^[.A-Za-z0-9_]+$}', $token)) {
                throw new \UnexpectedValueException('Your github oauth token for ' . $domain . ' contains invalid characters: "' . $token . '"');
            }
            $this->checkAndSetAuthentication($domain, $token, 'x-oauth-basic');
        }
        foreach ($gitlabOauth as $domain => $token) {
            if ($domain !== 'gitlab.com' && !in_array($domain, $config->get('gitlab-domains'), \true)) {
                $this->debug($domain . ' is not in the configured gitlab-domains, adding it implicitly as authentication is configured for this domain');
                $config->merge(['config' => ['gitlab-domains' => array_merge($config->get('gitlab-domains'), [$domain])]], 'implicit-due-to-auth');
            }
            $token = is_array($token) ? $token["token"] : $token;
            $this->checkAndSetAuthentication($domain, $token, 'oauth2');
        }
        foreach ($gitlabToken as $domain => $token) {
            if ($domain !== 'gitlab.com' && !in_array($domain, $config->get('gitlab-domains'), \true)) {
                $this->debug($domain . ' is not in the configured gitlab-domains, adding it implicitly as authentication is configured for this domain');
                $config->merge(['config' => ['gitlab-domains' => array_merge($config->get('gitlab-domains'), [$domain])]], 'implicit-due-to-auth');
            }
            $username = is_array($token) ? $token["username"] : $token;
            $password = is_array($token) ? $token["token"] : 'private-token';
            $this->checkAndSetAuthentication($domain, $username, $password);
        }
        foreach ($forgejoToken as $domain => $cred) {
            if (!in_array($domain, $config->get('forgejo-domains'), \true)) {
                $this->debug($domain . ' is not in the configured forgejo-domains, adding it implicitly as authentication is configured for this domain');
                $config->merge(['config' => ['forgejo-domains' => array_merge($config->get('forgejo-domains'), [$domain])]], 'implicit-due-to-auth');
            }
            $this->checkAndSetAuthentication($domain, $cred['username'], $cred['token']);
        }
        // reload http basic credentials from config if available
        foreach ($httpBasic as $domain => $cred) {
            $this->checkAndSetAuthentication($domain, $cred['username'], $cred['password']);
        }
        foreach ($bearerToken as $domain => $token) {
            $this->checkAndSetAuthentication($domain, $token, 'bearer');
        }
        // load custom HTTP headers from config
        foreach ($customHeaders as $domain => $headers) {
            if ($headers !== null) {
                $this->checkAndSetAuthentication($domain, (string) json_encode($headers), 'custom-headers');
            }
        }
        // reload ssl client certificate credentials from config if available
        foreach ($clientCertificate as $domain => $cred) {
            $sslOptions = array_filter(['local_cert' => $cred['local_cert'] ?? null, 'local_pk' => $cred['local_pk'] ?? null, 'passphrase' => $cred['passphrase'] ?? null], static function (?string $value): bool {
                return $value !== null;
            });
            if (!isset($sslOptions['local_cert'])) {
                $this->writeError(sprintf('<warning>Warning: Client certificate configuration is missing key `local_cert` for %s.</warning>', $domain));
                continue;
            }
            $this->checkAndSetAuthentication($domain, 'client-certificate', (string) json_encode($sslOptions));
        }
        // setup process timeout
        ProcessExecutor::setTimeout($config->get('process-timeout'));
    }
    /**
     * @param string|\Stringable $message
     */
    public function emergency($message, array $context = []): void
    {
        $this->log(LogLevel::EMERGENCY, $message, $context);
    }
    /**
     * @param string|\Stringable $message
     */
    public function alert($message, array $context = []): void
    {
        $this->log(LogLevel::ALERT, $message, $context);
    }
    /**
     * @param string|\Stringable $message
     */
    public function critical($message, array $context = []): void
    {
        $this->log(LogLevel::CRITICAL, $message, $context);
    }
    /**
     * @param string|\Stringable $message
     */
    public function error($message, array $context = []): void
    {
        $this->log(LogLevel::ERROR, $message, $context);
    }
    /**
     * @param string|\Stringable $message
     */
    public function warning($message, array $context = []): void
    {
        $this->log(LogLevel::WARNING, $message, $context);
    }
    /**
     * @param string|\Stringable $message
     */
    public function notice($message, array $context = []): void
    {
        $this->log(LogLevel::NOTICE, $message, $context);
    }
    /**
     * @param string|\Stringable $message
     */
    public function info($message, array $context = []): void
    {
        $this->log(LogLevel::INFO, $message, $context);
    }
    /**
     * @param string|\Stringable $message
     */
    public function debug($message, array $context = []): void
    {
        $this->log(LogLevel::DEBUG, $message, $context);
    }
    /**
     * @param mixed|LogLevel::* $level
     * @param string|\Stringable $message
     */
    public function log($level, $message, array $context = []): void
    {
        $message = (string) $message;
        if ($context !== []) {
            $json = Silencer::call('json_encode', $context, \JSON_INVALID_UTF8_IGNORE | \JSON_UNESCAPED_SLASHES | \JSON_UNESCAPED_UNICODE);
            if ($json !== \false) {
                $message .= ' ' . $json;
            }
        }
        if (in_array($level, [LogLevel::EMERGENCY, LogLevel::ALERT, LogLevel::CRITICAL, LogLevel::ERROR])) {
            $this->writeError('<error>' . $message . '</error>');
        } elseif ($level === LogLevel::WARNING) {
            $this->writeError('<warning>' . $message . '</warning>');
        } elseif ($level === LogLevel::NOTICE) {
            $this->writeError('<info>' . $message . '</info>', \true, self::VERBOSE);
        } elseif ($level === LogLevel::INFO) {
            $this->writeError('<info>' . $message . '</info>', \true, self::VERY_VERBOSE);
        } else {
            $this->writeError($message, \true, self::DEBUG);
        }
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer\IO;

/**
 * IOInterface that is not interactive and never writes the output
 *
 * @author Christophe Coevoet <stof@notk.org>
 */
class NullIO extends \Composer\IO\BaseIO
{
    /**
     * @inheritDoc
     */
    public function isInteractive(): bool
    {
        return \false;
    }
    /**
     * @inheritDoc
     */
    public function isVerbose(): bool
    {
        return \false;
    }
    /**
     * @inheritDoc
     */
    public function isVeryVerbose(): bool
    {
        return \false;
    }
    /**
     * @inheritDoc
     */
    public function isDebug(): bool
    {
        return \false;
    }
    /**
     * @inheritDoc
     */
    public function isDecorated(): bool
    {
        return \false;
    }
    /**
     * @inheritDoc
     */
    public function write($messages, bool $newline = \true, int $verbosity = self::NORMAL): void
    {
    }
    /**
     * @inheritDoc
     */
    public function writeError($messages, bool $newline = \true, int $verbosity = self::NORMAL): void
    {
    }
    /**
     * @inheritDoc
     */
    public function overwrite($messages, bool $newline = \true, ?int $size = null, int $verbosity = self::NORMAL): void
    {
    }
    /**
     * @inheritDoc
     */
    public function overwriteError($messages, bool $newline = \true, ?int $size = null, int $verbosity = self::NORMAL): void
    {
    }
    /**
     * @inheritDoc
     */
    public function ask($question, $default = null)
    {
        return $default;
    }
    /**
     * @inheritDoc
     */
    public function askConfirmation($question, $default = \true): bool
    {
        return $default;
    }
    /**
     * @inheritDoc
     */
    public function askAndValidate($question, $validator, $attempts = null, $default = null)
    {
        return $default;
    }
    /**
     * @inheritDoc
     */
    public function askAndHideAnswer($question): ?string
    {
        return null;
    }
    /**
     * @inheritDoc
     */
    public function select($question, $choices, $default, $attempts = \false, $errorMessage = 'Value "%s" is invalid', $multiselect = \false)
    {
        return $default;
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer\IO;

use Composer\Config;
use _ContaoManager\Psr\Log\LoggerInterface;
/**
 * The Input/Output helper interface.
 *
 * @author François Pluchino <francois.pluchino@opendisplay.com>
 */
interface IOInterface extends LoggerInterface
{
    public const QUIET = 1;
    public const NORMAL = 2;
    public const VERBOSE = 4;
    public const VERY_VERBOSE = 8;
    public const DEBUG = 16;
    /**
     * Is this input means interactive?
     *
     * @return bool
     */
    public function isInteractive();
    /**
     * Is this output verbose?
     *
     * @return bool
     */
    public function isVerbose();
    /**
     * Is the output very verbose?
     *
     * @return bool
     */
    public function isVeryVerbose();
    /**
     * Is the output in debug verbosity?
     *
     * @return bool
     */
    public function isDebug();
    /**
     * Is this output decorated?
     *
     * @return bool
     */
    public function isDecorated();
    /**
     * Writes a message to the output.
     *
     * @param string|string[] $messages  The message as an array of lines or a single string
     * @param bool            $newline   Whether to add a newline or not
     * @param int             $verbosity Verbosity level from the VERBOSITY_* constants
     *
     * @return void
     */
    public function write($messages, bool $newline = \true, int $verbosity = self::NORMAL);
    /**
     * Writes a message to the error output.
     *
     * @param string|string[] $messages  The message as an array of lines or a single string
     * @param bool            $newline   Whether to add a newline or not
     * @param int             $verbosity Verbosity level from the VERBOSITY_* constants
     *
     * @return void
     */
    public function writeError($messages, bool $newline = \true, int $verbosity = self::NORMAL);
    /**
     * Writes a message to the output, without formatting it.
     *
     * @param string|string[] $messages  The message as an array of lines or a single string
     * @param bool            $newline   Whether to add a newline or not
     * @param int             $verbosity Verbosity level from the VERBOSITY_* constants
     *
     * @return void
     */
    public function writeRaw($messages, bool $newline = \true, int $verbosity = self::NORMAL);
    /**
     * Writes a message to the error output, without formatting it.
     *
     * @param string|string[] $messages  The message as an array of lines or a single string
     * @param bool            $newline   Whether to add a newline or not
     * @param int             $verbosity Verbosity level from the VERBOSITY_* constants
     *
     * @return void
     */
    public function writeErrorRaw($messages, bool $newline = \true, int $verbosity = self::NORMAL);
    /**
     * Overwrites a previous message to the output.
     *
     * @param string|string[] $messages  The message as an array of lines or a single string
     * @param bool            $newline   Whether to add a newline or not
     * @param int             $size      The size of line
     * @param int             $verbosity Verbosity level from the VERBOSITY_* constants
     *
     * @return void
     */
    public function overwrite($messages, bool $newline = \true, ?int $size = null, int $verbosity = self::NORMAL);
    /**
     * Overwrites a previous message to the error output.
     *
     * @param string|string[] $messages  The message as an array of lines or a single string
     * @param bool            $newline   Whether to add a newline or not
     * @param int             $size      The size of line
     * @param int             $verbosity Verbosity level from the VERBOSITY_* constants
     *
     * @return void
     */
    public function overwriteError($messages, bool $newline = \true, ?int $size = null, int $verbosity = self::NORMAL);
    /**
     * Asks a question to the user.
     *
     * @param string $question The question to ask
     * @param string|bool|int|float|null $default  The default answer if none is given by the user
     *
     * @throws \RuntimeException If there is no data to read in the input stream
     * @return mixed       The user answer
     */
    public function ask(string $question, $default = null);
    /**
     * Asks a confirmation to the user.
     *
     * The question will be asked until the user answers by nothing, yes, or no.
     *
     * @param string $question The question to ask
     * @param bool   $default  The default answer if the user enters nothing
     *
     * @return bool true if the user has confirmed, false otherwise
     */
    public function askConfirmation(string $question, bool $default = \true);
    /**
     * Asks for a value and validates the response.
     *
     * The validator receives the data to validate. It must return the
     * validated data when the data is valid and throw an exception
     * otherwise.
     *
     * @param string   $question  The question to ask
     * @param callable $validator A PHP callback
     * @param null|int $attempts  Max number of times to ask before giving up (default of null means infinite)
     * @param mixed    $default   The default answer if none is given by the user
     *
     * @throws \Exception When any of the validators return an error
     * @return mixed
     */
    public function askAndValidate(string $question, callable $validator, ?int $attempts = null, $default = null);
    /**
     * Asks a question to the user and hide the answer.
     *
     * @param string $question The question to ask
     *
     * @return string|null The answer
     */
    public function askAndHideAnswer(string $question);
    /**
     * Asks the user to select a value.
     *
     * @param string      $question     The question to ask
     * @param string[]    $choices      List of choices to pick from
     * @param bool|string $default      The default answer if the user enters nothing
     * @param bool|int    $attempts     Max number of times to ask before giving up (false by default, which means infinite)
     * @param string      $errorMessage Message which will be shown if invalid value from choice list would be picked
     * @param bool        $multiselect  Select more than one value separated by comma
     *
     * @throws \InvalidArgumentException
     *
     * @return int|string|list<string>|bool     The selected value or values (the key of the choices array)
     * @phpstan-return ($multiselect is true ? list<string> : string|int|bool)
     */
    public function select(string $question, array $choices, $default, $attempts = \false, string $errorMessage = 'Value "%s" is invalid', bool $multiselect = \false);
    /**
     * Get all authentication information entered.
     *
     * @return array<string, array{username: string|null, password: string|null}> The map of authentication data
     */
    public function getAuthentications();
    /**
     * Verify if the repository has a authentication information.
     *
     * @param string $repositoryName The unique name of repository
     *
     * @return bool
     */
    public function hasAuthentication(string $repositoryName);
    /**
     * Get the username and password of repository.
     *
     * @param string $repositoryName The unique name of repository
     *
     * @return array{username: string|null, password: string|null}
     */
    public function getAuthentication(string $repositoryName);
    /**
     * Set the authentication information for the repository.
     *
     * @param string      $repositoryName The unique name of repository
     * @param string      $username       The username
     * @param null|string $password       The password
     *
     * @return void
     */
    public function setAuthentication(string $repositoryName, string $username, ?string $password = null);
    /**
     * Loads authentications from a config instance
     *
     * @return void
     */
    public function loadConfiguration(Config $config);
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer\Plugin;

/**
 * The Plugin Events.
 *
 * @author Nils Adermann <naderman@naderman.de>
 */
class PluginEvents
{
    /**
     * The INIT event occurs after a Composer instance is done being initialized
     *
     * The event listener method receives a
     * Composer\EventDispatcher\Event instance.
     *
     * @var string
     */
    public const INIT = 'init';
    /**
     * The COMMAND event occurs as a command begins
     *
     * The event listener method receives a
     * Composer\Plugin\CommandEvent instance.
     *
     * @var string
     */
    public const COMMAND = 'command';
    /**
     * The PRE_FILE_DOWNLOAD event occurs before downloading a file
     *
     * The event listener method receives a
     * Composer\Plugin\PreFileDownloadEvent instance.
     *
     * @var string
     */
    public const PRE_FILE_DOWNLOAD = 'pre-file-download';
    /**
     * The POST_FILE_DOWNLOAD event occurs after downloading a package dist file
     *
     * The event listener method receives a
     * Composer\Plugin\PostFileDownloadEvent instance.
     *
     * @var string
     */
    public const POST_FILE_DOWNLOAD = 'post-file-download';
    /**
     * The PRE_COMMAND_RUN event occurs before a command is executed and lets you modify the input arguments/options
     *
     * The event listener method receives a
     * Composer\Plugin\PreCommandRunEvent instance.
     *
     * @var string
     */
    public const PRE_COMMAND_RUN = 'pre-command-run';
    /**
     * The PRE_POOL_CREATE event occurs before the Pool of packages is created, and lets
     * you filter the list of packages which is going to enter the Solver
     *
     * The event listener method receives a
     * Composer\Plugin\PrePoolCreateEvent instance.
     *
     * @var string
     */
    public const PRE_POOL_CREATE = 'pre-pool-create';
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer\Plugin;

use Composer\EventDispatcher\Event;
use _ContaoManager\Symfony\Component\Console\Input\InputInterface;
/**
 * The pre command run event.
 *
 * @author Jordi Boggiano <j.boggiano@seld.be>
 */
class PreCommandRunEvent extends Event
{
    /**
     * @var InputInterface
     */
    private $input;
    /**
     * @var string
     */
    private $command;
    /**
     * Constructor.
     *
     * @param string         $name    The event name
     * @param string         $command The command about to be executed
     */
    public function __construct(string $name, InputInterface $input, string $command)
    {
        parent::__construct($name);
        $this->input = $input;
        $this->command = $command;
    }
    /**
     * Returns the console input
     */
    public function getInput(): InputInterface
    {
        return $this->input;
    }
    /**
     * Returns the command about to be executed
     */
    public function getCommand(): string
    {
        return $this->command;
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer\Plugin\Capability;

/**
 * Commands Provider Interface
 *
 * This capability will receive an array with 'composer' and 'io' keys as
 * constructor argument. Those contain Composer\Composer and Composer\IO\IOInterface
 * instances. It also contains a 'plugin' key containing the plugin instance that
 * created the capability.
 *
 * @author Jérémy Derussé <jeremy@derusse.com>
 */
interface CommandProvider extends \Composer\Plugin\Capability\Capability
{
    /**
     * Retrieves an array of commands
     *
     * @return \Composer\Command\BaseCommand[]
     */
    public function getCommands();
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer\Plugin\Capability;

/**
 * Marker interface for Plugin capabilities.
 * Every new Capability which is added to the Plugin API must implement this interface.
 *
 * @api
 */
interface Capability
{
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer\Plugin;

use UnexpectedValueException;
class PluginBlockedException extends UnexpectedValueException
{
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer\Plugin;

use Composer\EventDispatcher\Event;
use _ContaoManager\Symfony\Component\Console\Input\InputInterface;
use _ContaoManager\Symfony\Component\Console\Output\OutputInterface;
/**
 * An event for all commands.
 *
 * @author Nils Adermann <naderman@naderman.de>
 */
class CommandEvent extends Event
{
    /**
     * @var string
     */
    private $commandName;
    /**
     * @var InputInterface
     */
    private $input;
    /**
     * @var OutputInterface
     */
    private $output;
    /**
     * Constructor.
     *
     * @param string          $name        The event name
     * @param string          $commandName The command name
     * @param mixed[]         $args        Arguments passed by the user
     * @param mixed[]         $flags       Optional flags to pass data not as argument
     */
    public function __construct(string $name, string $commandName, InputInterface $input, OutputInterface $output, array $args = [], array $flags = [])
    {
        parent::__construct($name, $args, $flags);
        $this->commandName = $commandName;
        $this->input = $input;
        $this->output = $output;
    }
    /**
     * Returns the command input interface
     */
    public function getInput(): InputInterface
    {
        return $this->input;
    }
    /**
     * Retrieves the command output interface
     */
    public function getOutput(): OutputInterface
    {
        return $this->output;
    }
    /**
     * Retrieves the name of the command being run
     */
    public function getCommandName(): string
    {
        return $this->commandName;
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer\Plugin;

use Composer\Composer;
use Composer\IO\IOInterface;
/**
 * Plugin interface
 *
 * @author Nils Adermann <naderman@naderman.de>
 */
interface PluginInterface
{
    /**
     * Version number of the internal composer-plugin-api package
     *
     * This is used to denote the API version of Plugin specific
     * features, but is also bumped to a new major if Composer
     * includes a major break in internal APIs which are susceptible
     * to be used by plugins.
     *
     * @var string
     */
    public const PLUGIN_API_VERSION = '2.9.0';
    /**
     * Apply plugin modifications to Composer
     *
     * @return void
     */
    public function activate(Composer $composer, IOInterface $io);
    /**
     * Remove any hooks from Composer
     *
     * This will be called when a plugin is deactivated before being
     * uninstalled, but also before it gets upgraded to a new version
     * so the old one can be deactivated and the new one activated.
     *
     * @return void
     */
    public function deactivate(Composer $composer, IOInterface $io);
    /**
     * Prepare the plugin to be uninstalled
     *
     * This will be called after deactivate.
     *
     * @return void
     */
    public function uninstall(Composer $composer, IOInterface $io);
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer\Plugin;

use Composer\Composer;
use Composer\EventDispatcher\EventSubscriberInterface;
use Composer\Installer\InstallerInterface;
use Composer\IO\IOInterface;
use Composer\Package\BasePackage;
use Composer\Package\CompletePackage;
use Composer\Package\Locker;
use Composer\Package\Package;
use Composer\Package\RootPackageInterface;
use Composer\Package\Version\VersionParser;
use Composer\PartialComposer;
use Composer\Pcre\Preg;
use Composer\Repository\RepositoryInterface;
use Composer\Repository\InstalledRepository;
use Composer\Repository\RepositoryUtils;
use Composer\Repository\RootPackageRepository;
use Composer\Package\PackageInterface;
use Composer\Package\Link;
use Composer\Semver\Constraint\Constraint;
use Composer\Plugin\Capability\Capability;
use Composer\Util\PackageSorter;
/**
 * Plugin manager
 *
 * @author Nils Adermann <naderman@naderman.de>
 * @author Jordi Boggiano <j.boggiano@seld.be>
 */
class PluginManager
{
    /** @var Composer */
    protected $composer;
    /** @var IOInterface */
    protected $io;
    /** @var PartialComposer|null */
    protected $globalComposer;
    /** @var VersionParser */
    protected $versionParser;
    /** @var bool|'local'|'global' */
    protected $disablePlugins = \false;
    /** @var array<PluginInterface> */
    protected $plugins = [];
    /** @var array<string, array<PluginInterface|InstallerInterface>> */
    protected $registeredPlugins = [];
    /**
     * @var array<non-empty-string, bool>|null
     */
    private $allowPluginRules;
    /**
     * @var array<non-empty-string, bool>|null
     */
    private $allowGlobalPluginRules;
    /** @var bool */
    private $runningInGlobalDir = \false;
    /** @var int */
    private static $classCounter = 0;
    /**
     * @param bool|'local'|'global' $disablePlugins Whether plugins should not be loaded, can be set to local or global to only disable local/global plugins
     */
    public function __construct(IOInterface $io, Composer $composer, ?PartialComposer $globalComposer = null, $disablePlugins = \false)
    {
        $this->io = $io;
        $this->composer = $composer;
        $this->globalComposer = $globalComposer;
        $this->versionParser = new VersionParser();
        $this->disablePlugins = $disablePlugins;
        $this->allowPluginRules = $this->parseAllowedPlugins($composer->getConfig()->get('allow-plugins'), $composer->getLocker());
        $this->allowGlobalPluginRules = $this->parseAllowedPlugins($globalComposer !== null ? $globalComposer->getConfig()->get('allow-plugins') : \false);
    }
    public function setRunningInGlobalDir(bool $runningInGlobalDir): void
    {
        $this->runningInGlobalDir = $runningInGlobalDir;
    }
    /**
     * Loads all plugins from currently installed plugin packages
     */
    public function loadInstalledPlugins(): void
    {
        if (!$this->arePluginsDisabled('local')) {
            $repo = $this->composer->getRepositoryManager()->getLocalRepository();
            $this->loadRepository($repo, \false, $this->composer->getPackage());
        }
        if ($this->globalComposer !== null && !$this->arePluginsDisabled('global')) {
            $this->loadRepository($this->globalComposer->getRepositoryManager()->getLocalRepository(), \true);
        }
    }
    /**
     * Deactivate all plugins from currently installed plugin packages
     */
    public function deactivateInstalledPlugins(): void
    {
        if (!$this->arePluginsDisabled('local')) {
            $repo = $this->composer->getRepositoryManager()->getLocalRepository();
            $this->deactivateRepository($repo, \false);
        }
        if ($this->globalComposer !== null && !$this->arePluginsDisabled('global')) {
            $this->deactivateRepository($this->globalComposer->getRepositoryManager()->getLocalRepository(), \true);
        }
    }
    /**
     * Gets all currently active plugin instances
     *
     * @return array<PluginInterface> plugins
     */
    public function getPlugins(): array
    {
        return $this->plugins;
    }
    /**
     * Gets all currently active plugin instances
     *
     * @internal
     * @return array<string> Plugin package names which are currently active
     */
    public function getRegisteredPlugins(): array
    {
        return array_keys($this->registeredPlugins);
    }
    /**
     * Gets global composer or null when main composer is not fully loaded
     */
    public function getGlobalComposer(): ?PartialComposer
    {
        return $this->globalComposer;
    }
    /**
     * Register a plugin package, activate it etc.
     *
     * If it's of type composer-installer it is registered as an installer
     * instead for BC
     *
     * @param bool             $failOnMissingClasses By default this silently skips plugins that can not be found, but if set to true it fails with an exception
     * @param bool             $isGlobalPlugin       Set to true to denote plugins which are installed in the global Composer directory
     *
     * @throws \UnexpectedValueException
     */
    public function registerPackage(PackageInterface $package, bool $failOnMissingClasses = \false, bool $isGlobalPlugin = \false): void
    {
        if ($this->arePluginsDisabled($isGlobalPlugin ? 'global' : 'local')) {
            $this->io->writeError('<warning>The "' . $package->getName() . '" plugin was not loaded as plugins are disabled.</warning>');
            return;
        }
        if ($package->getType() === 'composer-plugin') {
            $requiresComposer = null;
            foreach ($package->getRequires() as $link) {
                /** @var Link $link */
                if ('composer-plugin-api' === $link->getTarget()) {
                    $requiresComposer = $link->getConstraint();
                    break;
                }
            }
            if (!$requiresComposer) {
                throw new \RuntimeException("Plugin " . $package->getName() . " is missing a require statement for a version of the composer-plugin-api package.");
            }
            $currentPluginApiVersion = $this->getPluginApiVersion();
            $currentPluginApiConstraint = new Constraint('==', $this->versionParser->normalize($currentPluginApiVersion));
            if ($requiresComposer->getPrettyString() === $this->getPluginApiVersion()) {
                $this->io->writeError('<warning>The "' . $package->getName() . '" plugin requires composer-plugin-api ' . $this->getPluginApiVersion() . ', this *WILL* break in the future and it should be fixed ASAP (require ^' . $this->getPluginApiVersion() . ' instead for example).</warning>');
            } elseif (!$requiresComposer->matches($currentPluginApiConstraint)) {
                $this->io->writeError('<warning>The "' . $package->getName() . '" plugin ' . ($isGlobalPlugin || $this->runningInGlobalDir ? '(installed globally) ' : '') . 'was skipped because it requires a Plugin API version ("' . $requiresComposer->getPrettyString() . '") that does not match your Composer installation ("' . $currentPluginApiVersion . '"). You may need to run composer update with the "--no-plugins" option.</warning>');
                return;
            }
            if ($package->getName() === 'symfony/flex' && Preg::isMatch('{^[0-9.]+$}', $package->getVersion()) && version_compare($package->getVersion(), '1.9.8', '<')) {
                $this->io->writeError('<warning>The "' . $package->getName() . '" plugin ' . ($isGlobalPlugin || $this->runningInGlobalDir ? '(installed globally) ' : '') . 'was skipped because it is not compatible with Composer 2+. Make sure to update it to version 1.9.8 or greater.</warning>');
                return;
            }
        }
        if (!$this->isPluginAllowed($package->getName(), $isGlobalPlugin, \true === ($package->getExtra()['plugin-optional'] ?? \false))) {
            $this->io->writeError('Skipped loading "' . $package->getName() . '" ' . ($isGlobalPlugin || $this->runningInGlobalDir ? '(installed globally) ' : '') . 'as it is not in config.allow-plugins', \true, IOInterface::DEBUG);
            return;
        }
        $oldInstallerPlugin = $package->getType() === 'composer-installer';
        if (isset($this->registeredPlugins[$package->getName()])) {
            return;
        }
        $extra = $package->getExtra();
        if (empty($extra['class'])) {
            throw new \UnexpectedValueException('Error while installing ' . $package->getPrettyName() . ', composer-plugin packages should have a class defined in their extra key to be usable.');
        }
        $classes = is_array($extra['class']) ? $extra['class'] : [$extra['class']];
        $localRepo = $this->composer->getRepositoryManager()->getLocalRepository();
        $globalRepo = $this->globalComposer !== null ? $this->globalComposer->getRepositoryManager()->getLocalRepository() : null;
        $rootPackage = clone $this->composer->getPackage();
        // clear files autoload rules from the root package as the root dependencies are not
        // necessarily all present yet when booting this runtime autoloader
        $rootPackageAutoloads = $rootPackage->getAutoload();
        $rootPackageAutoloads['files'] = [];
        $rootPackage->setAutoload($rootPackageAutoloads);
        $rootPackageAutoloads = $rootPackage->getDevAutoload();
        $rootPackageAutoloads['files'] = [];
        $rootPackage->setDevAutoload($rootPackageAutoloads);
        unset($rootPackageAutoloads);
        $rootPackageRepo = new RootPackageRepository($rootPackage);
        $installedRepo = new InstalledRepository([$localRepo, $rootPackageRepo]);
        if ($globalRepo) {
            $installedRepo->addRepository($globalRepo);
        }
        $autoloadPackages = [$package->getName() => $package];
        $autoloadPackages = $this->collectDependencies($installedRepo, $autoloadPackages, $package);
        $generator = $this->composer->getAutoloadGenerator();
        $autoloads = [[$rootPackage, '']];
        foreach ($autoloadPackages as $autoloadPackage) {
            if ($autoloadPackage === $rootPackage) {
                continue;
            }
            $installPath = $this->getInstallPath($autoloadPackage, $globalRepo && $globalRepo->hasPackage($autoloadPackage));
            if ($installPath === null) {
                continue;
            }
            $autoloads[] = [$autoloadPackage, $installPath];
        }
        $map = $generator->parseAutoloads($autoloads, $rootPackage);
        $classLoader = $generator->createLoader($map, $this->composer->getConfig()->get('vendor-dir'));
        $classLoader->register(\false);
        foreach ($map['files'] as $fileIdentifier => $file) {
            // exclude laminas/laminas-zendframework-bridge:src/autoload.php as it breaks Composer in some conditions
            // see https://github.com/composer/composer/issues/10349 and https://github.com/composer/composer/issues/10401
            // this hack can be removed once this deprecated package stop being installed
            if ($fileIdentifier === '7e9bd612cc444b3eed788ebbe46263a0') {
                continue;
            }
            \Composer\Autoload\composerRequire($fileIdentifier, $file);
        }
        foreach ($classes as $class) {
            if (class_exists($class, \false)) {
                $class = trim($class, '\\');
                $path = $classLoader->findFile($class);
                $code = file_get_contents($path);
                $separatorPos = strrpos($class, '\\');
                $className = $class;
                if ($separatorPos) {
                    $className = substr($class, $separatorPos + 1);
                }
                $code = Preg::replace('{^((?:(?:final|readonly)\s+)*(?:\s*))class\s+(' . preg_quote($className) . ')}mi', '$1class $2_composer_tmp' . self::$classCounter, $code, 1);
                $code = strtr($code, ['__FILE__' => var_export($path, \true), '__DIR__' => var_export(dirname($path), \true), '__CLASS__' => var_export($class, \true)]);
                $code = Preg::replace('/^\s*<\?(php)?/i', '', $code, 1);
                eval($code);
                $class .= '_composer_tmp' . self::$classCounter;
                self::$classCounter++;
            }
            if ($oldInstallerPlugin) {
                if (!is_a($class, 'Composer\Installer\InstallerInterface', \true)) {
                    throw new \RuntimeException('Could not activate plugin "' . $package->getName() . '" as "' . $class . '" does not implement Composer\Installer\InstallerInterface');
                }
                $this->io->writeError('<warning>Loading "' . $package->getName() . '" ' . ($isGlobalPlugin || $this->runningInGlobalDir ? '(installed globally) ' : '') . 'which is a legacy composer-installer built for Composer 1.x, it is likely to cause issues as you are running Composer 2.x.</warning>');
                $installer = new $class($this->io, $this->composer);
                $this->composer->getInstallationManager()->addInstaller($installer);
                $this->registeredPlugins[$package->getName()][] = $installer;
            } elseif (class_exists($class)) {
                if (!is_a($class, 'Composer\Plugin\PluginInterface', \true)) {
                    throw new \RuntimeException('Could not activate plugin "' . $package->getName() . '" as "' . $class . '" does not implement Composer\Plugin\PluginInterface');
                }
                $plugin = new $class();
                $this->addPlugin($plugin, $isGlobalPlugin, $package);
                $this->registeredPlugins[$package->getName()][] = $plugin;
            } elseif ($failOnMissingClasses) {
                throw new \UnexpectedValueException('Plugin ' . $package->getName() . ' could not be initialized, class not found: ' . $class);
            }
        }
    }
    /**
     * Deactivates a plugin package
     *
     * If it's of type composer-installer it is unregistered from the installers
     * instead for BC
     *
     * @throws \UnexpectedValueException
     */
    public function deactivatePackage(PackageInterface $package): void
    {
        if (!isset($this->registeredPlugins[$package->getName()])) {
            return;
        }
        $plugins = $this->registeredPlugins[$package->getName()];
        foreach ($plugins as $plugin) {
            if ($plugin instanceof InstallerInterface) {
                $this->composer->getInstallationManager()->removeInstaller($plugin);
            } else {
                $this->removePlugin($plugin);
            }
        }
        unset($this->registeredPlugins[$package->getName()]);
    }
    /**
     * Uninstall a plugin package
     *
     * If it's of type composer-installer it is unregistered from the installers
     * instead for BC
     *
     * @throws \UnexpectedValueException
     */
    public function uninstallPackage(PackageInterface $package): void
    {
        if (!isset($this->registeredPlugins[$package->getName()])) {
            return;
        }
        $plugins = $this->registeredPlugins[$package->getName()];
        foreach ($plugins as $plugin) {
            if ($plugin instanceof InstallerInterface) {
                $this->composer->getInstallationManager()->removeInstaller($plugin);
            } else {
                $this->removePlugin($plugin);
                $this->uninstallPlugin($plugin);
            }
        }
        unset($this->registeredPlugins[$package->getName()]);
    }
    /**
     * Returns the version of the internal composer-plugin-api package.
     */
    protected function getPluginApiVersion(): string
    {
        return \Composer\Plugin\PluginInterface::PLUGIN_API_VERSION;
    }
    /**
     * Adds a plugin, activates it and registers it with the event dispatcher
     *
     * Ideally plugin packages should be registered via registerPackage, but if you use Composer
     * programmatically and want to register a plugin class directly this is a valid way
     * to do it.
     *
     * @param PluginInterface   $plugin        plugin instance
     * @param ?PackageInterface $sourcePackage Package from which the plugin comes from
     */
    public function addPlugin(\Composer\Plugin\PluginInterface $plugin, bool $isGlobalPlugin = \false, ?PackageInterface $sourcePackage = null): void
    {
        if ($this->arePluginsDisabled($isGlobalPlugin ? 'global' : 'local')) {
            return;
        }
        if ($sourcePackage === null) {
            trigger_error('Calling PluginManager::addPlugin without $sourcePackage is deprecated, if you are using this please get in touch with us to explain the use case', \E_USER_DEPRECATED);
        } elseif (!$this->isPluginAllowed($sourcePackage->getName(), $isGlobalPlugin, \true === ($sourcePackage->getExtra()['plugin-optional'] ?? \false))) {
            $this->io->writeError('Skipped loading "' . get_class($plugin) . ' from ' . $sourcePackage->getName() . '" ' . ($isGlobalPlugin || $this->runningInGlobalDir ? '(installed globally) ' : '') . ' as it is not in config.allow-plugins', \true, IOInterface::DEBUG);
            return;
        }
        $details = [];
        if ($sourcePackage) {
            $details[] = 'from ' . $sourcePackage->getName();
        }
        if ($isGlobalPlugin || $this->runningInGlobalDir) {
            $details[] = 'installed globally';
        }
        $this->io->writeError('Loading plugin ' . get_class($plugin) . ($details ? ' (' . implode(', ', $details) . ')' : ''), \true, IOInterface::DEBUG);
        $this->plugins[] = $plugin;
        $plugin->activate($this->composer, $this->io);
        if ($plugin instanceof EventSubscriberInterface) {
            $this->composer->getEventDispatcher()->addSubscriber($plugin);
        }
    }
    /**
     * Removes a plugin, deactivates it and removes any listener the plugin has set on the plugin instance
     *
     * Ideally plugin packages should be deactivated via deactivatePackage, but if you use Composer
     * programmatically and want to deregister a plugin class directly this is a valid way
     * to do it.
     *
     * @param PluginInterface $plugin plugin instance
     */
    public function removePlugin(\Composer\Plugin\PluginInterface $plugin): void
    {
        $index = array_search($plugin, $this->plugins, \true);
        if ($index === \false) {
            return;
        }
        $this->io->writeError('Unloading plugin ' . get_class($plugin), \true, IOInterface::DEBUG);
        unset($this->plugins[$index]);
        $plugin->deactivate($this->composer, $this->io);
        $this->composer->getEventDispatcher()->removeListener($plugin);
    }
    /**
     * Notifies a plugin it is being uninstalled and should clean up
     *
     * Ideally plugin packages should be uninstalled via uninstallPackage, but if you use Composer
     * programmatically and want to deregister a plugin class directly this is a valid way
     * to do it.
     *
     * @param PluginInterface $plugin plugin instance
     */
    public function uninstallPlugin(\Composer\Plugin\PluginInterface $plugin): void
    {
        $this->io->writeError('Uninstalling plugin ' . get_class($plugin), \true, IOInterface::DEBUG);
        $plugin->uninstall($this->composer, $this->io);
    }
    /**
     * Load all plugins and installers from a repository
     *
     * If a plugin requires another plugin, the required one will be loaded first
     *
     * Note that plugins in the specified repository that rely on events that
     * have fired prior to loading will be missed. This means you likely want to
     * call this method as early as possible.
     *
     * @param RepositoryInterface $repo Repository to scan for plugins to install
     *
     * @phpstan-param ($isGlobalRepo is true ? null : RootPackageInterface) $rootPackage
     *
     * @throws \RuntimeException
     */
    private function loadRepository(RepositoryInterface $repo, bool $isGlobalRepo, ?RootPackageInterface $rootPackage = null): void
    {
        $packages = $repo->getPackages();
        $weights = [];
        foreach ($packages as $package) {
            if ($package->getType() === 'composer-plugin') {
                $extra = $package->getExtra();
                if ($package->getName() === 'composer/installers' || \true === ($extra['plugin-modifies-install-path'] ?? \false)) {
                    $weights[$package->getName()] = -10000;
                }
            }
        }
        $sortedPackages = PackageSorter::sortPackages($packages, $weights);
        if (!$isGlobalRepo) {
            $requiredPackages = RepositoryUtils::filterRequiredPackages($packages, $rootPackage, \true);
        }
        foreach ($sortedPackages as $package) {
            if (!$package instanceof CompletePackage) {
                continue;
            }
            if (!in_array($package->getType(), ['composer-plugin', 'composer-installer'], \true)) {
                continue;
            }
            if (!$isGlobalRepo && !in_array($package, $requiredPackages, \true) && !$this->isPluginAllowed($package->getName(), \false, \true, \false)) {
                $this->io->writeError('<warning>The "' . $package->getName() . '" plugin was not loaded as it is not listed in allow-plugins and is not required by the root package anymore.</warning>');
                continue;
            }
            if ('composer-plugin' === $package->getType()) {
                $this->registerPackage($package, \false, $isGlobalRepo);
                // Backward compatibility
            } elseif ('composer-installer' === $package->getType()) {
                $this->registerPackage($package, \false, $isGlobalRepo);
            }
        }
    }
    /**
     * Deactivate all plugins and installers from a repository
     *
     * If a plugin requires another plugin, the required one will be deactivated last
     *
     * @param RepositoryInterface $repo Repository to scan for plugins to install
     */
    private function deactivateRepository(RepositoryInterface $repo, bool $isGlobalRepo): void
    {
        $packages = $repo->getPackages();
        $sortedPackages = array_reverse(PackageSorter::sortPackages($packages));
        foreach ($sortedPackages as $package) {
            if (!$package instanceof CompletePackage) {
                continue;
            }
            if ('composer-plugin' === $package->getType()) {
                $this->deactivatePackage($package);
                // Backward compatibility
            } elseif ('composer-installer' === $package->getType()) {
                $this->deactivatePackage($package);
            }
        }
    }
    /**
     * Recursively generates a map of package names to packages for all deps
     *
     * @param InstalledRepository             $installedRepo Set of local repos
     * @param array<string, PackageInterface> $collected     Current state of the map for recursion
     * @param PackageInterface                $package       The package to analyze
     *
     * @return array<string, PackageInterface> Map of package names to packages
     */
    private function collectDependencies(InstalledRepository $installedRepo, array $collected, PackageInterface $package): array
    {
        foreach ($package->getRequires() as $requireLink) {
            foreach ($installedRepo->findPackagesWithReplacersAndProviders($requireLink->getTarget()) as $requiredPackage) {
                if (!isset($collected[$requiredPackage->getName()])) {
                    $collected[$requiredPackage->getName()] = $requiredPackage;
                    $collected = $this->collectDependencies($installedRepo, $collected, $requiredPackage);
                }
            }
        }
        return $collected;
    }
    /**
     * Retrieves the path a package is installed to.
     *
     * @param bool             $global  Whether this is a global package
     *
     * @return string|null Install path
     */
    private function getInstallPath(PackageInterface $package, bool $global = \false): ?string
    {
        if (!$global) {
            return $this->composer->getInstallationManager()->getInstallPath($package);
        }
        assert(null !== $this->globalComposer);
        return $this->globalComposer->getInstallationManager()->getInstallPath($package);
    }
    /**
     * @throws \RuntimeException On empty or non-string implementation class name value
     * @return null|string       The fully qualified class of the implementation or null if Plugin is not of Capable type or does not provide it
     */
    protected function getCapabilityImplementationClassName(\Composer\Plugin\PluginInterface $plugin, string $capability): ?string
    {
        if (!$plugin instanceof \Composer\Plugin\Capable) {
            return null;
        }
        $capabilities = (array) $plugin->getCapabilities();
        if (!empty($capabilities[$capability]) && is_string($capabilities[$capability]) && trim($capabilities[$capability])) {
            return trim($capabilities[$capability]);
        }
        if (array_key_exists($capability, $capabilities) && (empty($capabilities[$capability]) || !is_string($capabilities[$capability]) || !trim($capabilities[$capability]))) {
            throw new \UnexpectedValueException('Plugin ' . get_class($plugin) . ' provided invalid capability class name(s), got ' . var_export($capabilities[$capability], \true));
        }
        return null;
    }
    /**
     * @template CapabilityClass of Capability
     * @param  class-string<CapabilityClass> $capabilityClassName The fully qualified name of the API interface which the plugin may provide
     *                                                            an implementation of.
     * @param  array<mixed>                  $ctorArgs            Arguments passed to Capability's constructor.
     *                                                            Keeping it an array will allow future values to be passed w\o changing the signature.
     * @phpstan-param class-string<CapabilityClass> $capabilityClassName
     * @phpstan-return null|CapabilityClass
     */
    public function getPluginCapability(\Composer\Plugin\PluginInterface $plugin, $capabilityClassName, array $ctorArgs = []): ?Capability
    {
        if ($capabilityClass = $this->getCapabilityImplementationClassName($plugin, $capabilityClassName)) {
            if (!class_exists($capabilityClass)) {
                throw new \RuntimeException("Cannot instantiate Capability, as class {$capabilityClass} from plugin " . get_class($plugin) . " does not exist.");
            }
            $ctorArgs['plugin'] = $plugin;
            $capabilityObj = new $capabilityClass($ctorArgs);
            // FIXME these could use is_a and do the check *before* instantiating once drop support for php<5.3.9
            if (!$capabilityObj instanceof Capability || !$capabilityObj instanceof $capabilityClassName) {
                throw new \RuntimeException('Class ' . $capabilityClass . ' must implement both Composer\Plugin\Capability\Capability and ' . $capabilityClassName . '.');
            }
            return $capabilityObj;
        }
        return null;
    }
    /**
     * @template CapabilityClass of Capability
     * @param  class-string<CapabilityClass> $capabilityClassName The fully qualified name of the API interface which the plugin may provide
     *                                                            an implementation of.
     * @param  array<mixed>                  $ctorArgs            Arguments passed to Capability's constructor.
     *                                                            Keeping it an array will allow future values to be passed w\o changing the signature.
     * @return CapabilityClass[]
     */
    public function getPluginCapabilities($capabilityClassName, array $ctorArgs = []): array
    {
        $capabilities = [];
        foreach ($this->getPlugins() as $plugin) {
            $capability = $this->getPluginCapability($plugin, $capabilityClassName, $ctorArgs);
            if (null !== $capability) {
                $capabilities[] = $capability;
            }
        }
        return $capabilities;
    }
    /**
     * @param  array<string, bool>|bool $allowPluginsConfig
     * @return array<non-empty-string, bool>|null
     */
    private function parseAllowedPlugins($allowPluginsConfig, ?Locker $locker = null): ?array
    {
        if ([] === $allowPluginsConfig && $locker !== null && $locker->isLocked() && version_compare($locker->getPluginApi(), '2.2.0', '<')) {
            return null;
        }
        if (\true === $allowPluginsConfig) {
            return ['{}' => \true];
        }
        if (\false === $allowPluginsConfig) {
            return ['{}' => \false];
        }
        $rules = [];
        foreach ($allowPluginsConfig as $pattern => $allow) {
            $rules[BasePackage::packageNameToRegexp($pattern)] = $allow;
        }
        return $rules;
    }
    /**
     * @internal
     *
     * @param 'local'|'global' $type
     * @return bool
     */
    public function arePluginsDisabled($type)
    {
        return $this->disablePlugins === \true || $this->disablePlugins === $type;
    }
    /**
     * @internal
     */
    public function disablePlugins(): void
    {
        $this->disablePlugins = \true;
    }
    /**
     * @internal
     */
    public function isPluginAllowed(string $package, bool $isGlobalPlugin, bool $optional = \false, bool $prompt = \true): bool
    {
        if ($isGlobalPlugin) {
            $rules =& $this->allowGlobalPluginRules;
        } else {
            $rules =& $this->allowPluginRules;
        }
        // This is a BC mode for lock files created pre-Composer-2.2 where the expectation of
        // an allow-plugins config being present cannot be made.
        if ($rules === null) {
            if (!$this->io->isInteractive()) {
                $this->io->writeError('<warning>For additional security you should declare the allow-plugins config with a list of packages names that are allowed to run code. See https://getcomposer.org/allow-plugins</warning>');
                $this->io->writeError('<warning>This warning will become an exception once you run composer update!</warning>');
                $rules = ['{}' => \true];
                // if no config is defined we allow all plugins for BC
                return \true;
            }
            // keep going and prompt the user
            $rules = [];
        }
        foreach ($rules as $pattern => $allow) {
            if (Preg::isMatch($pattern, $package)) {
                return $allow === \true;
            }
        }
        if ($package === 'composer/package-versions-deprecated') {
            return \false;
        }
        if ($this->io->isInteractive() && $prompt) {
            $composer = $isGlobalPlugin && $this->globalComposer !== null ? $this->globalComposer : $this->composer;
            $this->io->writeError('<warning>' . $package . ($isGlobalPlugin || $this->runningInGlobalDir ? ' (installed globally)' : '') . ' contains a Composer plugin which is currently not in your allow-plugins config. See https://getcomposer.org/allow-plugins</warning>');
            $attempts = 0;
            while (\true) {
                // do not allow more than 5 prints of the help message, at some point assume the
                // input is not interactive and bail defaulting to a disabled plugin
                $default = '?';
                if ($attempts > 5) {
                    $this->io->writeError('Too many failed prompts, aborting.');
                    break;
                }
                switch ($answer = $this->io->ask('Do you trust "<fg=green;options=bold>' . $package . '</>" to execute code and wish to enable it now? (writes "allow-plugins" to composer.json) [<comment>y,n,d,?</comment>] ', $default)) {
                    case 'y':
                    case 'n':
                    case 'd':
                        $allow = $answer === 'y';
                        // persist answer in current rules to avoid prompting again if the package gets reloaded
                        $rules[BasePackage::packageNameToRegexp($package)] = $allow;
                        // persist answer in composer.json if it wasn't simply discarded
                        if ($answer === 'y' || $answer === 'n') {
                            $allowPlugins = $composer->getConfig()->get('allow-plugins');
                            if (is_array($allowPlugins)) {
                                $allowPlugins[$package] = $allow;
                                if ($composer->getConfig()->get('sort-packages')) {
                                    ksort($allowPlugins);
                                }
                                $composer->getConfig()->getConfigSource()->addConfigSetting('allow-plugins', $allowPlugins);
                                $composer->getConfig()->merge(['config' => ['allow-plugins' => $allowPlugins]]);
                            }
                        }
                        return $allow;
                    case '?':
                    default:
                        $attempts++;
                        $this->io->writeError(['y - add package to allow-plugins in composer.json and let it run immediately', 'n - add package (as disallowed) to allow-plugins in composer.json to suppress further prompts', 'd - discard this, do not change composer.json and do not allow the plugin to run', '? - print help']);
                        break;
                }
            }
        } elseif ($optional) {
            return \false;
        }
        throw new \Composer\Plugin\PluginBlockedException($package . ($isGlobalPlugin || $this->runningInGlobalDir ? ' (installed globally)' : '') . ' contains a Composer plugin which is blocked by your allow-plugins config. You may add it to the list if you consider it safe.' . \PHP_EOL . 'You can run "composer ' . ($isGlobalPlugin || $this->runningInGlobalDir ? 'global ' : '') . 'config --no-plugins allow-plugins.' . $package . ' [true|false]" to enable it (true) or disable it explicitly and suppress this exception (false)' . \PHP_EOL . 'See https://getcomposer.org/allow-plugins');
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer\Plugin;

use Composer\EventDispatcher\Event;
use Composer\Util\HttpDownloader;
/**
 * The pre file download event.
 *
 * @author Nils Adermann <naderman@naderman.de>
 */
class PreFileDownloadEvent extends Event
{
    /**
     * @var HttpDownloader
     */
    private $httpDownloader;
    /**
     * @var non-empty-string
     */
    private $processedUrl;
    /**
     * @var string|null
     */
    private $customCacheKey;
    /**
     * @var string
     */
    private $type;
    /**
     * @var mixed
     */
    private $context;
    /**
     * @var mixed[]
     */
    private $transportOptions = [];
    /**
     * Constructor.
     *
     * @param string           $name           The event name
     * @param mixed            $context
     * @param non-empty-string $processedUrl
     */
    public function __construct(string $name, HttpDownloader $httpDownloader, string $processedUrl, string $type, $context = null)
    {
        parent::__construct($name);
        $this->httpDownloader = $httpDownloader;
        $this->processedUrl = $processedUrl;
        $this->type = $type;
        $this->context = $context;
    }
    public function getHttpDownloader(): HttpDownloader
    {
        return $this->httpDownloader;
    }
    /**
     * Retrieves the processed URL that will be downloaded.
     *
     * @return non-empty-string
     */
    public function getProcessedUrl(): string
    {
        return $this->processedUrl;
    }
    /**
     * Sets the processed URL that will be downloaded.
     *
     * @param non-empty-string $processedUrl New processed URL
     */
    public function setProcessedUrl(string $processedUrl): void
    {
        $this->processedUrl = $processedUrl;
    }
    /**
     * Retrieves a custom package cache key for this download.
     */
    public function getCustomCacheKey(): ?string
    {
        return $this->customCacheKey;
    }
    /**
     * Sets a custom package cache key for this download.
     *
     * @param string|null $customCacheKey New cache key
     */
    public function setCustomCacheKey(?string $customCacheKey): void
    {
        $this->customCacheKey = $customCacheKey;
    }
    /**
     * Returns the type of this download (package, metadata).
     */
    public function getType(): string
    {
        return $this->type;
    }
    /**
     * Returns the context of this download, if any.
     *
     * If this download is of type package, the package object is returned.
     * If the type is metadata, an array{repository: RepositoryInterface} is returned.
     *
     * @return mixed
     */
    public function getContext()
    {
        return $this->context;
    }
    /**
     * Returns transport options for the download.
     *
     * Only available for events with type metadata, for packages set the transport options on the package itself.
     *
     * @return mixed[]
     */
    public function getTransportOptions(): array
    {
        return $this->transportOptions;
    }
    /**
     * Sets transport options for the download.
     *
     * Only available for events with type metadata, for packages set the transport options on the package itself.
     *
     * @param mixed[] $options
     */
    public function setTransportOptions(array $options): void
    {
        $this->transportOptions = $options;
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer\Plugin;

use Composer\EventDispatcher\Event;
use Composer\Package\PackageInterface;
/**
 * The post file download event.
 *
 * @author Nils Adermann <naderman@naderman.de>
 */
class PostFileDownloadEvent extends Event
{
    /**
     * @var string
     */
    private $fileName;
    /**
     * @var string|null
     */
    private $checksum;
    /**
     * @var string
     */
    private $url;
    /**
     * @var mixed
     */
    private $context;
    /**
     * @var string
     */
    private $type;
    /**
     * Constructor.
     *
     * @param string      $name     The event name
     * @param string|null $fileName The file name
     * @param string|null $checksum The checksum
     * @param string      $url      The processed url
     * @param string      $type     The type (package or metadata).
     * @param mixed       $context  Additional context for the download.
     */
    public function __construct(string $name, ?string $fileName, ?string $checksum, string $url, string $type, $context = null)
    {
        /** @phpstan-ignore instanceof.alwaysFalse, booleanAnd.alwaysFalse */
        if ($context === null && $type instanceof PackageInterface) {
            $context = $type;
            $type = 'package';
            trigger_error('PostFileDownloadEvent::__construct should receive a $type=package and the package object in $context since Composer 2.1.', \E_USER_DEPRECATED);
        }
        parent::__construct($name);
        $this->fileName = $fileName;
        $this->checksum = $checksum;
        $this->url = $url;
        $this->context = $context;
        $this->type = $type;
    }
    /**
     * Retrieves the target file name location.
     *
     * If this download is of type metadata, null is returned.
     */
    public function getFileName(): ?string
    {
        return $this->fileName;
    }
    /**
     * Gets the checksum.
     */
    public function getChecksum(): ?string
    {
        return $this->checksum;
    }
    /**
     * Gets the processed URL.
     */
    public function getUrl(): string
    {
        return $this->url;
    }
    /**
     * Returns the context of this download, if any.
     *
     * If this download is of type package, the package object is returned. If
     * this download is of type metadata, an array{response: Response, repository: RepositoryInterface} is returned.
     *
     * @return mixed
     */
    public function getContext()
    {
        return $this->context;
    }
    /**
     * Get the package.
     *
     * If this download is of type metadata, null is returned.
     *
     * @return PackageInterface|null The package.
     * @deprecated Use getContext instead
     */
    public function getPackage(): ?PackageInterface
    {
        trigger_error('PostFileDownloadEvent::getPackage is deprecated since Composer 2.1, use getContext instead.', \E_USER_DEPRECATED);
        $context = $this->getContext();
        return $context instanceof PackageInterface ? $context : null;
    }
    /**
     * Returns the type of this download (package, metadata).
     */
    public function getType(): string
    {
        return $this->type;
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer\Plugin;

/**
 * Plugins which need to expose various implementations
 * of the Composer Plugin Capabilities must have their
 * declared Plugin class implementing this interface.
 *
 * @api
 */
interface Capable
{
    /**
     * Method by which a Plugin announces its API implementations, through an array
     * with a special structure.
     *
     * The key must be a string, representing a fully qualified class/interface name
     * which Composer Plugin API exposes.
     * The value must be a string as well, representing the fully qualified class name
     * of the implementing class.
     *
     * @tutorial
     *
     * return array(
     *     'Composer\Plugin\Capability\CommandProvider' => 'My\CommandProvider',
     *     'Composer\Plugin\Capability\Validator'       => 'My\Validator',
     * );
     *
     * @return string[]
     */
    public function getCapabilities();
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer\Plugin;

use Composer\EventDispatcher\Event;
use Composer\Repository\RepositoryInterface;
use Composer\DependencyResolver\Request;
use Composer\Package\BasePackage;
/**
 * The pre command run event.
 *
 * @author Jordi Boggiano <j.boggiano@seld.be>
 */
class PrePoolCreateEvent extends Event
{
    /**
     * @var RepositoryInterface[]
     */
    private $repositories;
    /**
     * @var Request
     */
    private $request;
    /**
     * @var int[] array of stability => BasePackage::STABILITY_* value
     * @phpstan-var array<string, BasePackage::STABILITY_*>
     */
    private $acceptableStabilities;
    /**
     * @var int[] array of package name => BasePackage::STABILITY_* value
     * @phpstan-var array<string, BasePackage::STABILITY_*>
     */
    private $stabilityFlags;
    /**
     * @var array[] of package => version => [alias, alias_normalized]
     * @phpstan-var array<string, array<string, array{alias: string, alias_normalized: string}>>
     */
    private $rootAliases;
    /**
     * @var string[]
     * @phpstan-var array<string, string>
     */
    private $rootReferences;
    /**
     * @var BasePackage[]
     */
    private $packages;
    /**
     * @var BasePackage[]
     */
    private $unacceptableFixedPackages;
    /**
     * @param string                $name                   The event name
     * @param RepositoryInterface[] $repositories
     * @param int[]                 $acceptableStabilities  array of stability => BasePackage::STABILITY_* value
     * @param int[]                 $stabilityFlags         array of package name => BasePackage::STABILITY_* value
     * @param array[]               $rootAliases            array of package => version => [alias, alias_normalized]
     * @param string[]              $rootReferences
     * @param BasePackage[]         $packages
     * @param BasePackage[]         $unacceptableFixedPackages
     *
     * @phpstan-param array<string, BasePackage::STABILITY_*> $acceptableStabilities
     * @phpstan-param array<string, BasePackage::STABILITY_*> $stabilityFlags
     * @phpstan-param array<string, array<string, array{alias: string, alias_normalized: string}>> $rootAliases
     * @phpstan-param array<string, string> $rootReferences
     */
    public function __construct(string $name, array $repositories, Request $request, array $acceptableStabilities, array $stabilityFlags, array $rootAliases, array $rootReferences, array $packages, array $unacceptableFixedPackages)
    {
        parent::__construct($name);
        $this->repositories = $repositories;
        $this->request = $request;
        $this->acceptableStabilities = $acceptableStabilities;
        $this->stabilityFlags = $stabilityFlags;
        $this->rootAliases = $rootAliases;
        $this->rootReferences = $rootReferences;
        $this->packages = $packages;
        $this->unacceptableFixedPackages = $unacceptableFixedPackages;
    }
    /**
     * @return RepositoryInterface[]
     */
    public function getRepositories(): array
    {
        return $this->repositories;
    }
    public function getRequest(): Request
    {
        return $this->request;
    }
    /**
     * @return int[] array of stability => BasePackage::STABILITY_* value
     * @phpstan-return array<string, BasePackage::STABILITY_*>
     */
    public function getAcceptableStabilities(): array
    {
        return $this->acceptableStabilities;
    }
    /**
     * @return int[] array of package name => BasePackage::STABILITY_* value
     * @phpstan-return array<string, BasePackage::STABILITY_*>
     */
    public function getStabilityFlags(): array
    {
        return $this->stabilityFlags;
    }
    /**
     * @return array[] of package => version => [alias, alias_normalized]
     * @phpstan-return array<string, array<string, array{alias: string, alias_normalized: string}>>
     */
    public function getRootAliases(): array
    {
        return $this->rootAliases;
    }
    /**
     * @return string[]
     * @phpstan-return array<string, string>
     */
    public function getRootReferences(): array
    {
        return $this->rootReferences;
    }
    /**
     * @return BasePackage[]
     */
    public function getPackages(): array
    {
        return $this->packages;
    }
    /**
     * @return BasePackage[]
     */
    public function getUnacceptableFixedPackages(): array
    {
        return $this->unacceptableFixedPackages;
    }
    /**
     * @param BasePackage[] $packages
     */
    public function setPackages(array $packages): void
    {
        $this->packages = $packages;
    }
    /**
     * @param BasePackage[] $packages
     */
    public function setUnacceptableFixedPackages(array $packages): void
    {
        $this->unacceptableFixedPackages = $packages;
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer\Downloader;

use React\Promise\PromiseInterface;
use Composer\Util\IniHelper;
use Composer\Util\Platform;
use Composer\Package\PackageInterface;
use RarArchive;
/**
 * RAR archive downloader.
 *
 * Based on previous work by Jordi Boggiano ({@see ZipDownloader}).
 *
 * @author Derrick Nelson <drrcknlsn@gmail.com>
 */
class RarDownloader extends \Composer\Downloader\ArchiveDownloader
{
    protected function extract(PackageInterface $package, string $file, string $path): PromiseInterface
    {
        $processError = null;
        // Try to use unrar on *nix
        if (!Platform::isWindows()) {
            $command = ['sh', '-c', 'unrar x -- "$0" "$1" >/dev/null && chmod -R u+w "$1"', $file, $path];
            if (0 === $this->process->execute($command, $ignoredOutput)) {
                return \React\Promise\resolve(null);
            }
            $processError = 'Failed to execute ' . implode(' ', $command) . "\n\n" . $this->process->getErrorOutput();
        }
        if (!class_exists('RarArchive')) {
            // php.ini path is added to the error message to help users find the correct file
            $iniMessage = IniHelper::getMessage();
            $error = "Could not decompress the archive, enable the PHP rar extension or install unrar.\n" . $iniMessage . "\n" . $processError;
            if (!Platform::isWindows()) {
                $error = "Could not decompress the archive, enable the PHP rar extension.\n" . $iniMessage;
            }
            throw new \RuntimeException($error);
        }
        $rarArchive = RarArchive::open($file);
        if (\false === $rarArchive) {
            throw new \UnexpectedValueException('Could not open RAR archive: ' . $file);
        }
        $entries = $rarArchive->getEntries();
        if (\false === $entries) {
            throw new \RuntimeException('Could not retrieve RAR archive entries');
        }
        foreach ($entries as $entry) {
            if (\false === $entry->extract($path)) {
                throw new \RuntimeException('Could not extract entry');
            }
        }
        $rarArchive->close();
        return \React\Promise\resolve(null);
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer\Downloader;

use Composer\Package\PackageInterface;
/**
 * VCS Capable Downloader interface.
 *
 * @author Steve Buzonas <steve@fancyguy.com>
 */
interface VcsCapableDownloaderInterface
{
    /**
     * Gets the VCS Reference for the package at path
     *
     * @param  PackageInterface $package package instance
     * @param  string           $path    package directory
     * @return string|null      reference or null
     */
    public function getVcsReference(PackageInterface $package, string $path): ?string;
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer\Downloader;

use Composer\Config;
use Composer\Package\Dumper\ArrayDumper;
use Composer\Package\PackageInterface;
use Composer\Package\Version\VersionGuesser;
use Composer\Package\Version\VersionParser;
use Composer\Util\ProcessExecutor;
use Composer\IO\IOInterface;
use Composer\Util\Filesystem;
use React\Promise\PromiseInterface;
use Composer\DependencyResolver\Operation\UpdateOperation;
use Composer\DependencyResolver\Operation\InstallOperation;
use Composer\DependencyResolver\Operation\UninstallOperation;
/**
 * @author Jordi Boggiano <j.boggiano@seld.be>
 */
abstract class VcsDownloader implements \Composer\Downloader\DownloaderInterface, \Composer\Downloader\ChangeReportInterface, \Composer\Downloader\VcsCapableDownloaderInterface
{
    /** @var IOInterface */
    protected $io;
    /** @var Config */
    protected $config;
    /** @var ProcessExecutor */
    protected $process;
    /** @var Filesystem */
    protected $filesystem;
    /** @var array<string, true> */
    protected $hasCleanedChanges = [];
    public function __construct(IOInterface $io, Config $config, ?ProcessExecutor $process = null, ?Filesystem $fs = null)
    {
        $this->io = $io;
        $this->config = $config;
        $this->process = $process ?? new ProcessExecutor($io);
        $this->filesystem = $fs ?? new Filesystem($this->process);
    }
    /**
     * @inheritDoc
     */
    public function getInstallationSource(): string
    {
        return 'source';
    }
    /**
     * @inheritDoc
     */
    public function download(PackageInterface $package, string $path, ?PackageInterface $prevPackage = null): PromiseInterface
    {
        if (!$package->getSourceReference()) {
            throw new \InvalidArgumentException('Package ' . $package->getPrettyName() . ' is missing reference information');
        }
        $urls = $this->prepareUrls($package->getSourceUrls());
        while ($url = array_shift($urls)) {
            try {
                return $this->doDownload($package, $path, $url, $prevPackage);
            } catch (\Exception $e) {
                // rethrow phpunit exceptions to avoid hard to debug bug failures
                if ($e instanceof \_ContaoManager\PHPUnit\Framework\Exception) {
                    throw $e;
                }
                if ($this->io->isDebug()) {
                    $this->io->writeError('Failed: [' . get_class($e) . '] ' . $e->getMessage());
                } elseif (count($urls)) {
                    $this->io->writeError('    Failed, trying the next URL');
                }
                if (!count($urls)) {
                    throw $e;
                }
            }
        }
        return \React\Promise\resolve(null);
    }
    /**
     * @inheritDoc
     */
    public function prepare(string $type, PackageInterface $package, string $path, ?PackageInterface $prevPackage = null): PromiseInterface
    {
        if ($type === 'update') {
            $this->cleanChanges($prevPackage, $path, \true);
            $this->hasCleanedChanges[$prevPackage->getUniqueName()] = \true;
        } elseif ($type === 'install') {
            $this->filesystem->emptyDirectory($path);
        } elseif ($type === 'uninstall') {
            $this->cleanChanges($package, $path, \false);
        }
        return \React\Promise\resolve(null);
    }
    /**
     * @inheritDoc
     */
    public function cleanup(string $type, PackageInterface $package, string $path, ?PackageInterface $prevPackage = null): PromiseInterface
    {
        if ($type === 'update' && isset($this->hasCleanedChanges[$prevPackage->getUniqueName()])) {
            $this->reapplyChanges($path);
            unset($this->hasCleanedChanges[$prevPackage->getUniqueName()]);
        }
        return \React\Promise\resolve(null);
    }
    /**
     * @inheritDoc
     */
    public function install(PackageInterface $package, string $path): PromiseInterface
    {
        if (!$package->getSourceReference()) {
            throw new \InvalidArgumentException('Package ' . $package->getPrettyName() . ' is missing reference information');
        }
        $this->io->writeError("  - " . InstallOperation::format($package) . ': ', \false);
        $urls = $this->prepareUrls($package->getSourceUrls());
        while ($url = array_shift($urls)) {
            try {
                $this->doInstall($package, $path, $url);
                break;
            } catch (\Exception $e) {
                // rethrow phpunit exceptions to avoid hard to debug bug failures
                if ($e instanceof \_ContaoManager\PHPUnit\Framework\Exception) {
                    throw $e;
                }
                if ($this->io->isDebug()) {
                    $this->io->writeError('Failed: [' . get_class($e) . '] ' . $e->getMessage());
                } elseif (count($urls)) {
                    $this->io->writeError('    Failed, trying the next URL');
                }
                if (!count($urls)) {
                    throw $e;
                }
            }
        }
        return \React\Promise\resolve(null);
    }
    /**
     * @inheritDoc
     */
    public function update(PackageInterface $initial, PackageInterface $target, string $path): PromiseInterface
    {
        if (!$target->getSourceReference()) {
            throw new \InvalidArgumentException('Package ' . $target->getPrettyName() . ' is missing reference information');
        }
        $this->io->writeError("  - " . UpdateOperation::format($initial, $target) . ': ', \false);
        $urls = $this->prepareUrls($target->getSourceUrls());
        $exception = null;
        while ($url = array_shift($urls)) {
            try {
                $this->doUpdate($initial, $target, $path, $url);
                $exception = null;
                break;
            } catch (\Exception $exception) {
                // rethrow phpunit exceptions to avoid hard to debug bug failures
                if ($exception instanceof \_ContaoManager\PHPUnit\Framework\Exception) {
                    throw $exception;
                }
                if ($this->io->isDebug()) {
                    $this->io->writeError('Failed: [' . get_class($exception) . '] ' . $exception->getMessage());
                } elseif (count($urls)) {
                    $this->io->writeError('    Failed, trying the next URL');
                }
            }
        }
        // print the commit logs if in verbose mode and VCS metadata is present
        // because in case of missing metadata code would trigger another exception
        if (!$exception && $this->io->isVerbose() && $this->hasMetadataRepository($path)) {
            $message = 'Pulling in changes:';
            $logs = $this->getCommitLogs($initial->getSourceReference(), $target->getSourceReference(), $path);
            if ('' === trim($logs)) {
                $message = 'Rolling back changes:';
                $logs = $this->getCommitLogs($target->getSourceReference(), $initial->getSourceReference(), $path);
            }
            if ('' !== trim($logs)) {
                $logs = implode("\n", array_map(static function ($line): string {
                    return '      ' . $line;
                }, explode("\n", $logs)));
                // escape angle brackets for proper output in the console
                $logs = str_replace('<', '\<', $logs);
                $this->io->writeError('    ' . $message);
                $this->io->writeError($logs);
            }
        }
        if (!$urls && $exception) {
            throw $exception;
        }
        return \React\Promise\resolve(null);
    }
    /**
     * @inheritDoc
     */
    public function remove(PackageInterface $package, string $path): PromiseInterface
    {
        $this->io->writeError("  - " . UninstallOperation::format($package));
        $promise = $this->filesystem->removeDirectoryAsync($path);
        return $promise->then(static function (bool $result) use ($path) {
            if (!$result) {
                throw new \RuntimeException('Could not completely delete ' . $path . ', aborting.');
            }
        });
    }
    /**
     * @inheritDoc
     */
    public function getVcsReference(PackageInterface $package, string $path): ?string
    {
        $parser = new VersionParser();
        $guesser = new VersionGuesser($this->config, $this->process, $parser, $this->io);
        $dumper = new ArrayDumper();
        $packageConfig = $dumper->dump($package);
        if ($packageVersion = $guesser->guessVersion($packageConfig, $path)) {
            return $packageVersion['commit'];
        }
        return null;
    }
    /**
     * Prompt the user to check if changes should be stashed/removed or the operation aborted
     *
     * @param  bool              $update  if true (update) the changes can be stashed and reapplied after an update,
     *                                    if false (remove) the changes should be assumed to be lost if the operation is not aborted
     *
     * @throws \RuntimeException in case the operation must be aborted
     * @phpstan-return PromiseInterface<void|null>
     */
    protected function cleanChanges(PackageInterface $package, string $path, bool $update): PromiseInterface
    {
        // the default implementation just fails if there are any changes, override in child classes to provide stash-ability
        if (null !== $this->getLocalChanges($package, $path)) {
            throw new \RuntimeException('Source directory ' . $path . ' has uncommitted changes.');
        }
        return \React\Promise\resolve(null);
    }
    /**
     * Reapply previously stashes changes if applicable, only called after an update (regardless if successful or not)
     *
     * @throws \RuntimeException in case the operation must be aborted or the patch does not apply cleanly
     */
    protected function reapplyChanges(string $path): void
    {
    }
    /**
     * Downloads data needed to run an install/update later
     *
     * @param PackageInterface      $package     package instance
     * @param string                $path        download path
     * @param string                $url         package url
     * @param PackageInterface|null $prevPackage previous package (in case of an update)
     * @phpstan-return PromiseInterface<void|null>
     */
    abstract protected function doDownload(PackageInterface $package, string $path, string $url, ?PackageInterface $prevPackage = null): PromiseInterface;
    /**
     * Downloads specific package into specific folder.
     *
     * @param PackageInterface $package package instance
     * @param string           $path    download path
     * @param string           $url     package url
     * @phpstan-return PromiseInterface<void|null>
     */
    abstract protected function doInstall(PackageInterface $package, string $path, string $url): PromiseInterface;
    /**
     * Updates specific package in specific folder from initial to target version.
     *
     * @param PackageInterface $initial initial package
     * @param PackageInterface $target  updated package
     * @param string           $path    download path
     * @param string           $url     package url
     * @phpstan-return PromiseInterface<void|null>
     */
    abstract protected function doUpdate(PackageInterface $initial, PackageInterface $target, string $path, string $url): PromiseInterface;
    /**
     * Fetches the commit logs between two commits
     *
     * @param  string $fromReference the source reference
     * @param  string $toReference   the target reference
     * @param  string $path          the package path
     */
    abstract protected function getCommitLogs(string $fromReference, string $toReference, string $path): string;
    /**
     * Checks if VCS metadata repository has been initialized
     * repository example: .git|.svn|.hg
     */
    abstract protected function hasMetadataRepository(string $path): bool;
    /**
     * @param string[] $urls
     *
     * @return string[]
     */
    private function prepareUrls(array $urls): array
    {
        foreach ($urls as $index => $url) {
            if (Filesystem::isLocalPath($url)) {
                // realpath() below will not understand
                // url that starts with "file://"
                $fileProtocol = 'file://';
                $isFileProtocol = \false;
                if (0 === strpos($url, $fileProtocol)) {
                    $url = substr($url, strlen($fileProtocol));
                    $isFileProtocol = \true;
                }
                // realpath() below will not understand %20 spaces etc.
                if (\false !== strpos($url, '%')) {
                    $url = rawurldecode($url);
                }
                $urls[$index] = realpath($url);
                if ($isFileProtocol) {
                    $urls[$index] = $fileProtocol . $urls[$index];
                }
            }
        }
        return $urls;
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer\Downloader;

/**
 * Exception thrown when issues exist on local filesystem
 *
 * @author Javier Spagnoletti <jspagnoletti@javierspagnoletti.com.ar>
 */
class FilesystemException extends \Exception
{
    public function __construct(string $message = '', int $code = 0, ?\Exception $previous = null)
    {
        parent::__construct("Filesystem exception: \n" . $message, $code, $previous);
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer\Downloader;

use Composer\Package\PackageInterface;
use Composer\IO\IOInterface;
use Composer\Pcre\Preg;
use Composer\Util\Filesystem;
use Composer\Exception\IrrecoverableDownloadException;
use React\Promise\PromiseInterface;
/**
 * Downloaders manager.
 *
 * @author Konstantin Kudryashov <ever.zet@gmail.com>
 */
class DownloadManager
{
    /** @var IOInterface */
    private $io;
    /** @var bool */
    private $preferDist = \false;
    /** @var bool */
    private $preferSource;
    /** @var array<string, string> */
    private $packagePreferences = [];
    /** @var Filesystem */
    private $filesystem;
    /** @var array<string, DownloaderInterface> */
    private $downloaders = [];
    /**
     * Initializes download manager.
     *
     * @param IOInterface     $io           The Input Output Interface
     * @param bool            $preferSource prefer downloading from source
     * @param Filesystem|null $filesystem   custom Filesystem object
     */
    public function __construct(IOInterface $io, bool $preferSource = \false, ?Filesystem $filesystem = null)
    {
        $this->io = $io;
        $this->preferSource = $preferSource;
        $this->filesystem = $filesystem ?: new Filesystem();
    }
    /**
     * Makes downloader prefer source installation over the dist.
     *
     * @param  bool            $preferSource prefer downloading from source
     */
    public function setPreferSource(bool $preferSource): self
    {
        $this->preferSource = $preferSource;
        return $this;
    }
    /**
     * Makes downloader prefer dist installation over the source.
     *
     * @param  bool            $preferDist prefer downloading from dist
     */
    public function setPreferDist(bool $preferDist): self
    {
        $this->preferDist = $preferDist;
        return $this;
    }
    /**
     * Sets fine tuned preference settings for package level source/dist selection.
     *
     * @param array<string, string> $preferences array of preferences by package patterns
     */
    public function setPreferences(array $preferences): self
    {
        $this->packagePreferences = $preferences;
        return $this;
    }
    /**
     * Sets installer downloader for a specific installation type.
     *
     * @param  string              $type       installation type
     * @param  DownloaderInterface $downloader downloader instance
     */
    public function setDownloader(string $type, \Composer\Downloader\DownloaderInterface $downloader): self
    {
        $type = strtolower($type);
        $this->downloaders[$type] = $downloader;
        return $this;
    }
    /**
     * Returns downloader for a specific installation type.
     *
     * @param  string                    $type installation type
     * @throws \InvalidArgumentException if downloader for provided type is not registered
     */
    public function getDownloader(string $type): \Composer\Downloader\DownloaderInterface
    {
        $type = strtolower($type);
        if (!isset($this->downloaders[$type])) {
            throw new \InvalidArgumentException(sprintf('Unknown downloader type: %s. Available types: %s.', $type, implode(', ', array_keys($this->downloaders))));
        }
        return $this->downloaders[$type];
    }
    /**
     * Returns downloader for already installed package.
     *
     * @param  PackageInterface          $package package instance
     * @throws \InvalidArgumentException if package has no installation source specified
     * @throws \LogicException           if specific downloader used to load package with
     *                                           wrong type
     */
    public function getDownloaderForPackage(PackageInterface $package): ?\Composer\Downloader\DownloaderInterface
    {
        $installationSource = $package->getInstallationSource();
        if ('metapackage' === $package->getType()) {
            return null;
        }
        if ('dist' === $installationSource) {
            $downloader = $this->getDownloader($package->getDistType());
        } elseif ('source' === $installationSource) {
            $downloader = $this->getDownloader($package->getSourceType());
        } else {
            throw new \InvalidArgumentException('Package ' . $package . ' does not have an installation source set');
        }
        if ($installationSource !== $downloader->getInstallationSource()) {
            throw new \LogicException(sprintf('Downloader "%s" is a %s type downloader and can not be used to download %s for package %s', get_class($downloader), $downloader->getInstallationSource(), $installationSource, $package));
        }
        return $downloader;
    }
    public function getDownloaderType(\Composer\Downloader\DownloaderInterface $downloader): string
    {
        return array_search($downloader, $this->downloaders);
    }
    /**
     * Downloads package into target dir.
     *
     * @param PackageInterface      $package     package instance
     * @param string                $targetDir   target dir
     * @param PackageInterface|null $prevPackage previous package instance in case of updates
     * @phpstan-return PromiseInterface<void|null>
     *
     * @throws \InvalidArgumentException if package have no urls to download from
     * @throws \RuntimeException
     */
    public function download(PackageInterface $package, string $targetDir, ?PackageInterface $prevPackage = null): PromiseInterface
    {
        $targetDir = $this->normalizeTargetDir($targetDir);
        $this->filesystem->ensureDirectoryExists(dirname($targetDir));
        $sources = $this->getAvailableSources($package, $prevPackage);
        $io = $this->io;
        $download = function ($retry = \false) use (&$sources, $io, $package, $targetDir, &$download, $prevPackage) {
            $source = array_shift($sources);
            if ($retry) {
                $io->writeError('    <warning>Now trying to download from ' . $source . '</warning>');
            }
            $package->setInstallationSource($source);
            $downloader = $this->getDownloaderForPackage($package);
            if (!$downloader) {
                return \React\Promise\resolve(null);
            }
            $handleError = static function ($e) use ($sources, $source, $package, $io, $download) {
                if ($e instanceof \RuntimeException && !$e instanceof IrrecoverableDownloadException) {
                    if (!$sources) {
                        throw $e;
                    }
                    $io->writeError('    <warning>Failed to download ' . $package->getPrettyName() . ' from ' . $source . ': ' . $e->getMessage() . '</warning>');
                    return $download(\true);
                }
                throw $e;
            };
            try {
                $result = $downloader->download($package, $targetDir, $prevPackage);
            } catch (\Exception $e) {
                return $handleError($e);
            }
            $res = $result->then(static function ($res) {
                return $res;
            }, $handleError);
            return $res;
        };
        return $download();
    }
    /**
     * Prepares an operation execution
     *
     * @param string                $type        one of install/update/uninstall
     * @param PackageInterface      $package     package instance
     * @param string                $targetDir   target dir
     * @param PackageInterface|null $prevPackage previous package instance in case of updates
     * @phpstan-return PromiseInterface<void|null>
     */
    public function prepare(string $type, PackageInterface $package, string $targetDir, ?PackageInterface $prevPackage = null): PromiseInterface
    {
        $targetDir = $this->normalizeTargetDir($targetDir);
        $downloader = $this->getDownloaderForPackage($package);
        if ($downloader) {
            return $downloader->prepare($type, $package, $targetDir, $prevPackage);
        }
        return \React\Promise\resolve(null);
    }
    /**
     * Installs package into target dir.
     *
     * @param PackageInterface $package   package instance
     * @param string           $targetDir target dir
     * @phpstan-return PromiseInterface<void|null>
     *
     * @throws \InvalidArgumentException if package have no urls to download from
     * @throws \RuntimeException
     */
    public function install(PackageInterface $package, string $targetDir): PromiseInterface
    {
        $targetDir = $this->normalizeTargetDir($targetDir);
        $downloader = $this->getDownloaderForPackage($package);
        if ($downloader) {
            return $downloader->install($package, $targetDir);
        }
        return \React\Promise\resolve(null);
    }
    /**
     * Updates package from initial to target version.
     *
     * @param PackageInterface $initial   initial package version
     * @param PackageInterface $target    target package version
     * @param string           $targetDir target dir
     * @phpstan-return PromiseInterface<void|null>
     *
     * @throws \InvalidArgumentException if initial package is not installed
     */
    public function update(PackageInterface $initial, PackageInterface $target, string $targetDir): PromiseInterface
    {
        $targetDir = $this->normalizeTargetDir($targetDir);
        $downloader = $this->getDownloaderForPackage($target);
        $initialDownloader = $this->getDownloaderForPackage($initial);
        // no downloaders present means update from metapackage to metapackage, nothing to do
        if (!$initialDownloader && !$downloader) {
            return \React\Promise\resolve(null);
        }
        // if we have a downloader present before, but not after, the package became a metapackage and its files should be removed
        if (!$downloader) {
            return $initialDownloader->remove($initial, $targetDir);
        }
        $initialType = $this->getDownloaderType($initialDownloader);
        $targetType = $this->getDownloaderType($downloader);
        if ($initialType === $targetType) {
            try {
                return $downloader->update($initial, $target, $targetDir);
            } catch (\RuntimeException $e) {
                if (!$this->io->isInteractive()) {
                    throw $e;
                }
                $this->io->writeError('<error>    Update failed (' . $e->getMessage() . ')</error>');
                if (!$this->io->askConfirmation('    Would you like to try reinstalling the package instead [<comment>yes</comment>]? ')) {
                    throw $e;
                }
            }
        }
        // if downloader type changed, or update failed and user asks for reinstall,
        // we wipe the dir and do a new install instead of updating it
        $promise = $initialDownloader->remove($initial, $targetDir);
        return $promise->then(function ($res) use ($target, $targetDir): PromiseInterface {
            return $this->install($target, $targetDir);
        });
    }
    /**
     * Removes package from target dir.
     *
     * @param PackageInterface $package   package instance
     * @param string           $targetDir target dir
     * @phpstan-return PromiseInterface<void|null>
     */
    public function remove(PackageInterface $package, string $targetDir): PromiseInterface
    {
        $targetDir = $this->normalizeTargetDir($targetDir);
        $downloader = $this->getDownloaderForPackage($package);
        if ($downloader) {
            return $downloader->remove($package, $targetDir);
        }
        return \React\Promise\resolve(null);
    }
    /**
     * Cleans up a failed operation
     *
     * @param string                $type        one of install/update/uninstall
     * @param PackageInterface      $package     package instance
     * @param string                $targetDir   target dir
     * @param PackageInterface|null $prevPackage previous package instance in case of updates
     * @phpstan-return PromiseInterface<void|null>
     */
    public function cleanup(string $type, PackageInterface $package, string $targetDir, ?PackageInterface $prevPackage = null): PromiseInterface
    {
        $targetDir = $this->normalizeTargetDir($targetDir);
        $downloader = $this->getDownloaderForPackage($package);
        if ($downloader) {
            return $downloader->cleanup($type, $package, $targetDir, $prevPackage);
        }
        return \React\Promise\resolve(null);
    }
    /**
     * Determines the install preference of a package
     *
     * @param PackageInterface $package package instance
     */
    protected function resolvePackageInstallPreference(PackageInterface $package): string
    {
        foreach ($this->packagePreferences as $pattern => $preference) {
            $pattern = '{^' . str_replace('\*', '.*', preg_quote($pattern)) . '$}i';
            if (Preg::isMatch($pattern, $package->getName())) {
                if ('dist' === $preference || !$package->isDev() && 'auto' === $preference) {
                    return 'dist';
                }
                return 'source';
            }
        }
        return $package->isDev() ? 'source' : 'dist';
    }
    /**
     * @return string[]
     * @phpstan-return array<'dist'|'source'>&non-empty-array
     */
    private function getAvailableSources(PackageInterface $package, ?PackageInterface $prevPackage = null): array
    {
        $sourceType = $package->getSourceType();
        $distType = $package->getDistType();
        // add source before dist by default
        $sources = [];
        if ($sourceType) {
            $sources[] = 'source';
        }
        if ($distType) {
            $sources[] = 'dist';
        }
        if (empty($sources)) {
            throw new \InvalidArgumentException('Package ' . $package . ' must have a source or dist specified');
        }
        if ($prevPackage && in_array($prevPackage->getInstallationSource(), $sources, \true) && !(!$prevPackage->isDev() && $prevPackage->getInstallationSource() === 'dist' && $package->isDev())) {
            $prevSource = $prevPackage->getInstallationSource();
            usort($sources, static function ($a, $b) use ($prevSource): int {
                return $a === $prevSource ? -1 : 1;
            });
            return $sources;
        }
        // reverse sources in case dist is the preferred source for this package
        if (!$this->preferSource && ($this->preferDist || 'dist' === $this->resolvePackageInstallPreference($package))) {
            $sources = array_reverse($sources);
        }
        return $sources;
    }
    /**
     * Downloaders expect a /path/to/dir without trailing slash
     *
     * If any Installer provides a path with a trailing slash, this can cause bugs so make sure we remove them
     */
    private function normalizeTargetDir(string $dir): string
    {
        if ($dir === '\\' || $dir === '/') {
            return $dir;
        }
        return rtrim($dir, '\/');
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer\Downloader;

use Composer\Package\PackageInterface;
use React\Promise\PromiseInterface;
/**
 * Downloader for tar files: tar, tar.gz or tar.bz2
 *
 * @author Kirill chEbba Chebunin <iam@chebba.org>
 */
class TarDownloader extends \Composer\Downloader\ArchiveDownloader
{
    /**
     * @inheritDoc
     */
    protected function extract(PackageInterface $package, string $file, string $path): PromiseInterface
    {
        // Can throw an UnexpectedValueException
        $archive = new \PharData($file);
        $archive->extractTo($path, null, \true);
        return \React\Promise\resolve(null);
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer\Downloader;

use Composer\Util\Platform;
use React\Promise\PromiseInterface;
use Composer\Package\PackageInterface;
use Composer\Pcre\Preg;
use RuntimeException;
/**
 * @author BohwaZ <http://bohwaz.net/>
 */
class FossilDownloader extends \Composer\Downloader\VcsDownloader
{
    /**
     * @inheritDoc
     */
    protected function doDownload(PackageInterface $package, string $path, string $url, ?PackageInterface $prevPackage = null): PromiseInterface
    {
        return \React\Promise\resolve(null);
    }
    /**
     * @inheritDoc
     */
    protected function doInstall(PackageInterface $package, string $path, string $url): PromiseInterface
    {
        // Ensure we are allowed to use this URL by config
        $this->config->prohibitUrlByConfig($url, $this->io);
        $repoFile = $path . '.fossil';
        $realPath = Platform::realpath($path);
        $this->io->writeError("Cloning " . $package->getSourceReference());
        $this->execute(['fossil', 'clone', '--', $url, $repoFile]);
        $this->execute(['fossil', 'open', '--nested', '--', $repoFile], $realPath);
        $this->execute(['fossil', 'update', '--', (string) $package->getSourceReference()], $realPath);
        return \React\Promise\resolve(null);
    }
    /**
     * @inheritDoc
     */
    protected function doUpdate(PackageInterface $initial, PackageInterface $target, string $path, string $url): PromiseInterface
    {
        // Ensure we are allowed to use this URL by config
        $this->config->prohibitUrlByConfig($url, $this->io);
        $this->io->writeError(" Updating to " . $target->getSourceReference());
        if (!$this->hasMetadataRepository($path)) {
            throw new RuntimeException('The .fslckout file is missing from ' . $path . ', see https://getcomposer.org/commit-deps for more information');
        }
        $realPath = Platform::realpath($path);
        $this->execute(['fossil', 'pull'], $realPath);
        $this->execute(['fossil', 'up', '--', (string) $target->getSourceReference()], $realPath);
        return \React\Promise\resolve(null);
    }
    /**
     * @inheritDoc
     */
    public function getLocalChanges(PackageInterface $package, string $path): ?string
    {
        if (!$this->hasMetadataRepository($path)) {
            return null;
        }
        $this->process->execute(['fossil', 'changes'], $output, Platform::realpath($path));
        $output = trim($output);
        return strlen($output) > 0 ? $output : null;
    }
    /**
     * @inheritDoc
     */
    protected function getCommitLogs(string $fromReference, string $toReference, string $path): string
    {
        $this->execute(['fossil', 'timeline', '-t', 'ci', '-W', '0', '-n', '0', 'before', $toReference], Platform::realpath($path), $output);
        $log = '';
        $match = '/\d\d:\d\d:\d\d\s+\[' . $toReference . '\]/';
        foreach ($this->process->splitLines($output) as $line) {
            if (Preg::isMatch($match, $line)) {
                break;
            }
            $log .= $line;
        }
        return $log;
    }
    /**
     * @param non-empty-list<string> $command
     * @throws RuntimeException
     */
    private function execute(array $command, ?string $cwd = null, ?string &$output = null): void
    {
        if (0 !== $this->process->execute($command, $output, $cwd)) {
            throw new RuntimeException('Failed to execute ' . implode(' ', $command) . "\n\n" . $this->process->getErrorOutput());
        }
    }
    /**
     * @inheritDoc
     */
    protected function hasMetadataRepository(string $path): bool
    {
        return is_file($path . '/.fslckout') || is_file($path . '/_FOSSIL_');
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer\Downloader;

class MaxFileSizeExceededException extends \Composer\Downloader\TransportException
{
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer\Downloader;

use Composer\Package\PackageInterface;
use React\Promise\PromiseInterface;
/**
 * Downloader interface.
 *
 * @author Konstantin Kudryashov <ever.zet@gmail.com>
 * @author Jordi Boggiano <j.boggiano@seld.be>
 */
interface DownloaderInterface
{
    /**
     * Returns installation source (either source or dist).
     *
     * @return string "source" or "dist"
     */
    public function getInstallationSource(): string;
    /**
     * This should do any network-related tasks to prepare for an upcoming install/update
     *
     * @param  string $path download path
     * @phpstan-return PromiseInterface<void|null|string>
     */
    public function download(PackageInterface $package, string $path, ?PackageInterface $prevPackage = null): PromiseInterface;
    /**
     * Do anything that needs to be done between all downloads have been completed and the actual operation is executed
     *
     * All packages get first downloaded, then all together prepared, then all together installed/updated/uninstalled. Therefore
     * for error recovery it is important to avoid failing during install/update/uninstall as much as possible, and risky things or
     * user prompts should happen in the prepare step rather. In case of failure, cleanup() will be called so that changes can
     * be undone as much as possible.
     *
     * @param  string                $type        one of install/update/uninstall
     * @param  PackageInterface      $package     package instance
     * @param  string                $path        download path
     * @param  PackageInterface      $prevPackage previous package instance in case of an update
     * @phpstan-return PromiseInterface<void|null>
     */
    public function prepare(string $type, PackageInterface $package, string $path, ?PackageInterface $prevPackage = null): PromiseInterface;
    /**
     * Installs specific package into specific folder.
     *
     * @param  PackageInterface      $package package instance
     * @param  string                $path    download path
     * @phpstan-return PromiseInterface<void|null>
     */
    public function install(PackageInterface $package, string $path): PromiseInterface;
    /**
     * Updates specific package in specific folder from initial to target version.
     *
     * @param  PackageInterface      $initial initial package
     * @param  PackageInterface      $target  updated package
     * @param  string                $path    download path
     * @phpstan-return PromiseInterface<void|null>
     */
    public function update(PackageInterface $initial, PackageInterface $target, string $path): PromiseInterface;
    /**
     * Removes specific package from specific folder.
     *
     * @param  PackageInterface      $package package instance
     * @param  string                $path    download path
     * @phpstan-return PromiseInterface<void|null>
     */
    public function remove(PackageInterface $package, string $path): PromiseInterface;
    /**
     * Do anything to cleanup changes applied in the prepare or install/update/uninstall steps
     *
     * Note that cleanup will be called for all packages, either after install/update/uninstall is complete,
     * or if any package failed any operation. This is to give all installers a change to cleanup things
     * they did previously, so you need to keep track of changes applied in the installer/downloader themselves.
     *
     * @param  string                $type        one of install/update/uninstall
     * @param  PackageInterface      $package     package instance
     * @param  string                $path        download path
     * @param  PackageInterface      $prevPackage previous package instance in case of an update
     * @phpstan-return PromiseInterface<void|null>
     */
    public function cleanup(string $type, PackageInterface $package, string $path, ?PackageInterface $prevPackage = null): PromiseInterface;
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer\Downloader;

use React\Promise\PromiseInterface;
use Composer\Package\PackageInterface;
/**
 * Xz archive downloader.
 *
 * @author Pavel Puchkin <i@neoascetic.me>
 * @author Pierre Rudloff <contact@rudloff.pro>
 */
class XzDownloader extends \Composer\Downloader\ArchiveDownloader
{
    protected function extract(PackageInterface $package, string $file, string $path): PromiseInterface
    {
        $command = ['tar', '-xJf', $file, '-C', $path];
        if (0 === $this->process->execute($command, $ignoredOutput)) {
            return \React\Promise\resolve(null);
        }
        $processError = 'Failed to execute ' . implode(' ', $command) . "\n\n" . $this->process->getErrorOutput();
        throw new \RuntimeException($processError);
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer\Downloader;

use React\Promise\PromiseInterface;
use Composer\Package\PackageInterface;
use Composer\Util\Hg as HgUtils;
/**
 * @author Per Bernhardt <plb@webfactory.de>
 */
class HgDownloader extends \Composer\Downloader\VcsDownloader
{
    /**
     * @inheritDoc
     */
    protected function doDownload(PackageInterface $package, string $path, string $url, ?PackageInterface $prevPackage = null): PromiseInterface
    {
        if (null === HgUtils::getVersion($this->process)) {
            throw new \RuntimeException('hg was not found in your PATH, skipping source download');
        }
        return \React\Promise\resolve(null);
    }
    /**
     * @inheritDoc
     */
    protected function doInstall(PackageInterface $package, string $path, string $url): PromiseInterface
    {
        $hgUtils = new HgUtils($this->io, $this->config, $this->process);
        $cloneCommand = static function (string $url) use ($path): array {
            return ['hg', 'clone', '--', $url, $path];
        };
        $hgUtils->runCommand($cloneCommand, $url, $path);
        $command = ['hg', 'up', '--', (string) $package->getSourceReference()];
        if (0 !== $this->process->execute($command, $ignoredOutput, realpath($path))) {
            throw new \RuntimeException('Failed to execute ' . implode(' ', $command) . "\n\n" . $this->process->getErrorOutput());
        }
        return \React\Promise\resolve(null);
    }
    /**
     * @inheritDoc
     */
    protected function doUpdate(PackageInterface $initial, PackageInterface $target, string $path, string $url): PromiseInterface
    {
        $hgUtils = new HgUtils($this->io, $this->config, $this->process);
        $ref = $target->getSourceReference();
        $this->io->writeError(" Updating to " . $target->getSourceReference());
        if (!$this->hasMetadataRepository($path)) {
            throw new \RuntimeException('The .hg directory is missing from ' . $path . ', see https://getcomposer.org/commit-deps for more information');
        }
        $command = static function ($url): array {
            return ['hg', 'pull', '--', $url];
        };
        $hgUtils->runCommand($command, $url, $path);
        $command = static function () use ($ref): array {
            return ['hg', 'up', '--', $ref];
        };
        $hgUtils->runCommand($command, $url, $path);
        return \React\Promise\resolve(null);
    }
    /**
     * @inheritDoc
     */
    public function getLocalChanges(PackageInterface $package, string $path): ?string
    {
        if (!is_dir($path . '/.hg')) {
            return null;
        }
        $this->process->execute(['hg', 'st'], $output, realpath($path));
        $output = trim($output);
        return strlen($output) > 0 ? $output : null;
    }
    /**
     * @inheritDoc
     */
    protected function getCommitLogs(string $fromReference, string $toReference, string $path): string
    {
        $command = ['hg', 'log', '-r', $fromReference . ':' . $toReference, '--style', 'compact'];
        if (0 !== $this->process->execute($command, $output, realpath($path))) {
            throw new \RuntimeException('Failed to execute ' . implode(' ', $command) . "\n\n" . $this->process->getErrorOutput());
        }
        return $output;
    }
    /**
     * @inheritDoc
     */
    protected function hasMetadataRepository(string $path): bool
    {
        return is_dir($path . '/.hg');
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer\Downloader;

use Composer\Package\PackageInterface;
use Composer\Pcre\Preg;
use Composer\Util\Svn as SvnUtil;
use Composer\Repository\VcsRepository;
use React\Promise\PromiseInterface;
/**
 * @author Ben Bieker <mail@ben-bieker.de>
 * @author Till Klampaeckel <till@php.net>
 */
class SvnDownloader extends \Composer\Downloader\VcsDownloader
{
    /** @var bool */
    protected $cacheCredentials = \true;
    /**
     * @inheritDoc
     */
    protected function doDownload(PackageInterface $package, string $path, string $url, ?PackageInterface $prevPackage = null): PromiseInterface
    {
        SvnUtil::cleanEnv();
        $util = new SvnUtil($url, $this->io, $this->config, $this->process);
        if (null === $util->binaryVersion()) {
            throw new \RuntimeException('svn was not found in your PATH, skipping source download');
        }
        return \React\Promise\resolve(null);
    }
    /**
     * @inheritDoc
     */
    protected function doInstall(PackageInterface $package, string $path, string $url): PromiseInterface
    {
        SvnUtil::cleanEnv();
        $ref = $package->getSourceReference();
        $repo = $package->getRepository();
        if ($repo instanceof VcsRepository) {
            $repoConfig = $repo->getRepoConfig();
            if (array_key_exists('svn-cache-credentials', $repoConfig)) {
                $this->cacheCredentials = (bool) $repoConfig['svn-cache-credentials'];
            }
        }
        $this->io->writeError(" Checking out " . $package->getSourceReference());
        $this->execute($package, $url, ['svn', 'co'], sprintf("%s/%s", $url, $ref), null, $path);
        return \React\Promise\resolve(null);
    }
    /**
     * @inheritDoc
     */
    protected function doUpdate(PackageInterface $initial, PackageInterface $target, string $path, string $url): PromiseInterface
    {
        SvnUtil::cleanEnv();
        $ref = $target->getSourceReference();
        if (!$this->hasMetadataRepository($path)) {
            throw new \RuntimeException('The .svn directory is missing from ' . $path . ', see https://getcomposer.org/commit-deps for more information');
        }
        $util = new SvnUtil($url, $this->io, $this->config, $this->process);
        $flags = [];
        if (version_compare($util->binaryVersion(), '1.7.0', '>=')) {
            $flags[] = '--ignore-ancestry';
        }
        $this->io->writeError(" Checking out " . $ref);
        $this->execute($target, $url, array_merge(['svn', 'switch'], $flags), sprintf("%s/%s", $url, $ref), $path);
        return \React\Promise\resolve(null);
    }
    /**
     * @inheritDoc
     */
    public function getLocalChanges(PackageInterface $package, string $path): ?string
    {
        if (!$this->hasMetadataRepository($path)) {
            return null;
        }
        $this->process->execute(['svn', 'status', '--ignore-externals'], $output, $path);
        return Preg::isMatch('{^ *[^X ] +}m', $output) ? $output : null;
    }
    /**
     * Execute an SVN command and try to fix up the process with credentials
     * if necessary.
     *
     * @param  string            $baseUrl Base URL of the repository
     * @param  non-empty-list<string> $command SVN command to run
     * @param  string            $url     SVN url
     * @param  string            $cwd     Working directory
     * @param  string            $path    Target for a checkout
     * @throws \RuntimeException
     */
    protected function execute(PackageInterface $package, string $baseUrl, array $command, string $url, ?string $cwd = null, ?string $path = null): string
    {
        $util = new SvnUtil($baseUrl, $this->io, $this->config, $this->process);
        $util->setCacheCredentials($this->cacheCredentials);
        try {
            return $util->execute($command, $url, $cwd, $path, $this->io->isVerbose());
        } catch (\RuntimeException $e) {
            throw new \RuntimeException($package->getPrettyName() . ' could not be downloaded, ' . $e->getMessage());
        }
    }
    /**
     * @inheritDoc
     */
    protected function cleanChanges(PackageInterface $package, string $path, bool $update): PromiseInterface
    {
        if (null === $changes = $this->getLocalChanges($package, $path)) {
            return \React\Promise\resolve(null);
        }
        if (!$this->io->isInteractive()) {
            if (\true === $this->config->get('discard-changes')) {
                return $this->discardChanges($path);
            }
            return parent::cleanChanges($package, $path, $update);
        }
        $changes = array_map(static function ($elem): string {
            return '    ' . $elem;
        }, Preg::split('{\s*\r?\n\s*}', $changes));
        $countChanges = count($changes);
        $this->io->writeError(sprintf('    <error>' . $package->getPrettyName() . ' has modified file%s:</error>', $countChanges === 1 ? '' : 's'));
        $this->io->writeError(array_slice($changes, 0, 10));
        if ($countChanges > 10) {
            $remainingChanges = $countChanges - 10;
            $this->io->writeError(sprintf('    <info>' . $remainingChanges . ' more file%s modified, choose "v" to view the full list</info>', $remainingChanges === 1 ? '' : 's'));
        }
        while (\true) {
            switch ($this->io->ask('    <info>Discard changes [y,n,v,?]?</info> ', '?')) {
                case 'y':
                    $this->discardChanges($path);
                    break 2;
                case 'n':
                    throw new \RuntimeException('Update aborted');
                case 'v':
                    $this->io->writeError($changes);
                    break;
                case '?':
                default:
                    $this->io->writeError(['    y - discard changes and apply the ' . ($update ? 'update' : 'uninstall'), '    n - abort the ' . ($update ? 'update' : 'uninstall') . ' and let you manually clean things up', '    v - view modified files', '    ? - print help']);
                    break;
            }
        }
        return \React\Promise\resolve(null);
    }
    /**
     * @inheritDoc
     */
    protected function getCommitLogs(string $fromReference, string $toReference, string $path): string
    {
        if (Preg::isMatch('{@(\d+)$}', $fromReference) && Preg::isMatch('{@(\d+)$}', $toReference)) {
            // retrieve the svn base url from the checkout folder
            $command = ['svn', 'info', '--non-interactive', '--xml', '--', $path];
            if (0 !== $this->process->execute($command, $output, $path)) {
                throw new \RuntimeException('Failed to execute ' . implode(' ', $command) . "\n\n" . $this->process->getErrorOutput());
            }
            $urlPattern = '#<url>(.*)</url>#';
            if (Preg::isMatchStrictGroups($urlPattern, $output, $matches)) {
                $baseUrl = $matches[1];
            } else {
                throw new \RuntimeException('Unable to determine svn url for path ' . $path);
            }
            // strip paths from references and only keep the actual revision
            $fromRevision = Preg::replace('{.*@(\d+)$}', '$1', $fromReference);
            $toRevision = Preg::replace('{.*@(\d+)$}', '$1', $toReference);
            $command = ['svn', 'log', '-r', $fromRevision . ':' . $toRevision, '--incremental'];
            $util = new SvnUtil($baseUrl, $this->io, $this->config, $this->process);
            $util->setCacheCredentials($this->cacheCredentials);
            try {
                return $util->executeLocal($command, $path, null, $this->io->isVerbose());
            } catch (\RuntimeException $e) {
                throw new \RuntimeException('Failed to execute ' . implode(' ', $command) . "\n\n" . $e->getMessage());
            }
        }
        return "Could not retrieve changes between {$fromReference} and {$toReference} due to missing revision information";
    }
    /**
     * @phpstan-return PromiseInterface<void|null>
     */
    protected function discardChanges(string $path): PromiseInterface
    {
        if (0 !== $this->process->execute(['svn', 'revert', '-R', '.'], $output, $path)) {
            throw new \RuntimeException("Could not reset changes\n\n:" . $this->process->getErrorOutput());
        }
        return \React\Promise\resolve(null);
    }
    /**
     * @inheritDoc
     */
    protected function hasMetadataRepository(string $path): bool
    {
        return is_dir($path . '/.svn');
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer\Downloader;

use Composer\Config;
use Composer\Cache;
use Composer\IO\IOInterface;
use Composer\IO\NullIO;
use Composer\Exception\IrrecoverableDownloadException;
use Composer\Package\Comparer\Comparer;
use Composer\DependencyResolver\Operation\UpdateOperation;
use Composer\DependencyResolver\Operation\InstallOperation;
use Composer\DependencyResolver\Operation\UninstallOperation;
use Composer\Package\PackageInterface;
use Composer\Plugin\PluginEvents;
use Composer\Plugin\PostFileDownloadEvent;
use Composer\Plugin\PreFileDownloadEvent;
use Composer\EventDispatcher\EventDispatcher;
use Composer\Util\Filesystem;
use Composer\Util\Http\Response;
use Composer\Util\Platform;
use Composer\Util\Silencer;
use Composer\Util\HttpDownloader;
use Composer\Util\Url as UrlUtil;
use Composer\Util\ProcessExecutor;
use React\Promise\PromiseInterface;
/**
 * Base downloader for files
 *
 * @author Kirill chEbba Chebunin <iam@chebba.org>
 * @author Jordi Boggiano <j.boggiano@seld.be>
 * @author François Pluchino <francois.pluchino@opendisplay.com>
 * @author Nils Adermann <naderman@naderman.de>
 */
class FileDownloader implements \Composer\Downloader\DownloaderInterface, \Composer\Downloader\ChangeReportInterface
{
    /** @var IOInterface */
    protected $io;
    /** @var Config */
    protected $config;
    /** @var HttpDownloader */
    protected $httpDownloader;
    /** @var Filesystem */
    protected $filesystem;
    /** @var ?Cache */
    protected $cache;
    /** @var ?EventDispatcher */
    protected $eventDispatcher;
    /** @var ProcessExecutor */
    protected $process;
    /**
     * @var array<string, int|string>
     * @private
     * @internal
     */
    public static $downloadMetadata = [];
    /**
     * Collects response headers when running on GH Actions
     *
     * @see https://github.com/composer/composer/issues/11148
     * @var array<string, array<string>>
     * @private
     * @internal
     */
    public static $responseHeaders = [];
    /**
     * @var array<string, string> Map of package name to cache key
     */
    private $lastCacheWrites = [];
    /** @var array<string, string[]> Map of package name to list of paths */
    private $additionalCleanupPaths = [];
    /**
     * Constructor.
     *
     * @param IOInterface     $io              The IO instance
     * @param Config          $config          The config
     * @param HttpDownloader  $httpDownloader  The remote filesystem
     * @param EventDispatcher $eventDispatcher The event dispatcher
     * @param Cache           $cache           Cache instance
     * @param Filesystem      $filesystem      The filesystem
     */
    public function __construct(IOInterface $io, Config $config, HttpDownloader $httpDownloader, ?EventDispatcher $eventDispatcher = null, ?Cache $cache = null, ?Filesystem $filesystem = null, ?ProcessExecutor $process = null)
    {
        $this->io = $io;
        $this->config = $config;
        $this->eventDispatcher = $eventDispatcher;
        $this->httpDownloader = $httpDownloader;
        $this->cache = $cache;
        $this->process = $process ?? new ProcessExecutor($io);
        $this->filesystem = $filesystem ?? new Filesystem($this->process);
        if ($this->cache !== null && $this->cache->gcIsNecessary()) {
            $this->io->writeError('Running cache garbage collection', \true, IOInterface::VERY_VERBOSE);
            $this->cache->gc($config->get('cache-files-ttl'), $config->get('cache-files-maxsize'));
        }
    }
    /**
     * @inheritDoc
     */
    public function getInstallationSource(): string
    {
        return 'dist';
    }
    /**
     * @inheritDoc
     */
    public function download(PackageInterface $package, string $path, ?PackageInterface $prevPackage = null, bool $output = \true): PromiseInterface
    {
        if (null === $package->getDistUrl()) {
            throw new \InvalidArgumentException('The given package is missing url information');
        }
        $cacheKeyGenerator = static function (PackageInterface $package, $key): string {
            $cacheKey = hash('sha1', $key);
            return $package->getName() . '/' . $cacheKey . '.' . $package->getDistType();
        };
        $retries = 3;
        $distUrls = $package->getDistUrls();
        /** @var array<array{base: non-empty-string, processed: non-empty-string, cacheKey: string}> $urls */
        $urls = [];
        foreach ($distUrls as $index => $url) {
            $processedUrl = $this->processUrl($package, $url);
            $urls[$index] = [
                'base' => $url,
                'processed' => $processedUrl,
                // we use the complete download url here to avoid conflicting entries
                // from different packages, which would potentially allow a given package
                // in a third party repo to pre-populate the cache for the same package in
                // packagist for example.
                'cacheKey' => $cacheKeyGenerator($package, $processedUrl),
            ];
        }
        assert(count($urls) > 0);
        $fileName = $this->getFileName($package, $path);
        $this->filesystem->ensureDirectoryExists($path);
        $this->filesystem->ensureDirectoryExists(dirname($fileName));
        $accept = null;
        $reject = null;
        $download = function () use ($output, $cacheKeyGenerator, $package, $fileName, &$urls, &$accept, &$reject) {
            $url = reset($urls);
            $index = key($urls);
            if ($this->eventDispatcher !== null) {
                $preFileDownloadEvent = new PreFileDownloadEvent(PluginEvents::PRE_FILE_DOWNLOAD, $this->httpDownloader, $url['processed'], 'package', $package);
                $this->eventDispatcher->dispatch($preFileDownloadEvent->getName(), $preFileDownloadEvent);
                if ($preFileDownloadEvent->getCustomCacheKey() !== null) {
                    $url['cacheKey'] = $cacheKeyGenerator($package, $preFileDownloadEvent->getCustomCacheKey());
                } elseif ($preFileDownloadEvent->getProcessedUrl() !== $url['processed']) {
                    $url['cacheKey'] = $cacheKeyGenerator($package, $preFileDownloadEvent->getProcessedUrl());
                }
                $url['processed'] = $preFileDownloadEvent->getProcessedUrl();
            }
            $urls[$index] = $url;
            $checksum = $package->getDistSha1Checksum();
            $cacheKey = $url['cacheKey'];
            // use from cache if it is present and has a valid checksum or we have no checksum to check against
            if ($this->cache !== null && ($checksum === null || $checksum === '' || $checksum === $this->cache->sha1($cacheKey)) && $this->cache->copyTo($cacheKey, $fileName)) {
                if ($output) {
                    $this->io->writeError("  - Loading <info>" . $package->getName() . "</info> (<comment>" . $package->getFullPrettyVersion() . "</comment>) from cache", \true, IOInterface::VERY_VERBOSE);
                }
                // mark the file as having been written in cache even though it is only read from cache, so that if
                // the cache is corrupt the archive will be deleted and the next attempt will re-download it
                // see https://github.com/composer/composer/issues/10028
                if (!$this->cache->isReadOnly()) {
                    $this->lastCacheWrites[$package->getName()] = $cacheKey;
                }
                $result = \React\Promise\resolve($fileName);
            } else {
                if ($output) {
                    $this->io->writeError("  - Downloading <info>" . $package->getName() . "</info> (<comment>" . $package->getFullPrettyVersion() . "</comment>)");
                }
                $result = $this->httpDownloader->addCopy($url['processed'], $fileName, $package->getTransportOptions())->then($accept, $reject);
            }
            return $result->then(function ($result) use ($fileName, $checksum, $url, $package): string {
                // in case of retry, the first call's Promise chain finally calls this twice at the end,
                // once with $result being the returned $fileName from $accept, and then once for every
                // failed request with a null result, which can be skipped.
                if (null === $result) {
                    return $fileName;
                }
                if (!file_exists($fileName)) {
                    throw new \UnexpectedValueException($url['base'] . ' could not be saved to ' . $fileName . ', make sure the' . ' directory is writable and you have internet connectivity');
                }
                if ($checksum !== null && $checksum !== '' && hash_file('sha1', $fileName) !== $checksum) {
                    throw new \UnexpectedValueException('The checksum verification of the file failed (downloaded from ' . $url['base'] . ')');
                }
                if ($this->eventDispatcher !== null) {
                    $postFileDownloadEvent = new PostFileDownloadEvent(PluginEvents::POST_FILE_DOWNLOAD, $fileName, $checksum, $url['processed'], 'package', $package);
                    $this->eventDispatcher->dispatch($postFileDownloadEvent->getName(), $postFileDownloadEvent);
                }
                return $fileName;
            });
        };
        $accept = function (Response $response) use ($package, $fileName, &$urls): string {
            $url = reset($urls);
            $cacheKey = $url['cacheKey'];
            $fileSize = @filesize($fileName);
            if (\false === $fileSize) {
                $fileSize = $response->getHeader('Content-Length') ?? '?';
            }
            \Composer\Downloader\FileDownloader::$downloadMetadata[$package->getName()] = $fileSize;
            if (Platform::getEnv('GITHUB_ACTIONS') !== \false && Platform::getEnv('COMPOSER_TESTS_ARE_RUNNING') === \false) {
                \Composer\Downloader\FileDownloader::$responseHeaders[$package->getName()] = $response->getHeaders();
            }
            if ($this->cache !== null && !$this->cache->isReadOnly()) {
                $this->lastCacheWrites[$package->getName()] = $cacheKey;
                $this->cache->copyFrom($cacheKey, $fileName);
            }
            $response->collect();
            return $fileName;
        };
        $reject = function ($e) use (&$urls, $download, $fileName, $package, &$retries) {
            // clean up
            if (file_exists($fileName)) {
                $this->filesystem->unlink($fileName);
            }
            $this->clearLastCacheWrite($package);
            if ($e instanceof IrrecoverableDownloadException) {
                throw $e;
            }
            if ($e instanceof \Composer\Downloader\MaxFileSizeExceededException) {
                throw $e;
            }
            if ($e instanceof \Composer\Downloader\TransportException) {
                // if we got an http response with a proper code, then requesting again will probably not help, abort
                if (0 !== $e->getCode() && !in_array($e->getCode(), [500, 502, 503, 504], \true)) {
                    $retries = 0;
                }
            }
            // special error code returned when network is being artificially disabled
            if ($e instanceof \Composer\Downloader\TransportException && $e->getStatusCode() === 499) {
                $retries = 0;
                $urls = [];
            }
            if ($retries > 0) {
                usleep(500000);
                $retries--;
                return $download();
            }
            array_shift($urls);
            if (\count($urls) > 0) {
                if ($this->io->isDebug()) {
                    $this->io->writeError('    Failed downloading ' . $package->getName() . ': [' . get_class($e) . '] ' . $e->getCode() . ': ' . $e->getMessage());
                    $this->io->writeError('    Trying the next URL for ' . $package->getName());
                } else {
                    $this->io->writeError('    Failed downloading ' . $package->getName() . ', trying the next URL (' . $e->getCode() . ': ' . $e->getMessage() . ')');
                }
                $retries = 3;
                usleep(100000);
                return $download();
            }
            throw $e;
        };
        return $download();
    }
    /**
     * @inheritDoc
     */
    public function prepare(string $type, PackageInterface $package, string $path, ?PackageInterface $prevPackage = null): PromiseInterface
    {
        return \React\Promise\resolve(null);
    }
    /**
     * @inheritDoc
     */
    public function cleanup(string $type, PackageInterface $package, string $path, ?PackageInterface $prevPackage = null): PromiseInterface
    {
        $fileName = $this->getFileName($package, $path);
        if (file_exists($fileName)) {
            $this->filesystem->unlink($fileName);
        }
        $dirsToCleanUp = [$path, $this->config->get('vendor-dir') . '/' . explode('/', $package->getPrettyName())[0], $this->config->get('vendor-dir') . '/composer/', $this->config->get('vendor-dir')];
        if (isset($this->additionalCleanupPaths[$package->getName()])) {
            foreach ($this->additionalCleanupPaths[$package->getName()] as $pathToClean) {
                $this->filesystem->remove($pathToClean);
            }
        }
        foreach ($dirsToCleanUp as $dir) {
            if (is_dir($dir) && $this->filesystem->isDirEmpty($dir) && realpath($dir) !== Platform::getCwd()) {
                $this->filesystem->removeDirectoryPhp($dir);
            }
        }
        return \React\Promise\resolve(null);
    }
    /**
     * @inheritDoc
     */
    public function install(PackageInterface $package, string $path, bool $output = \true): PromiseInterface
    {
        if ($output) {
            $this->io->writeError("  - " . InstallOperation::format($package));
        }
        $vendorDir = $this->config->get('vendor-dir');
        // clean up the target directory, unless it contains the vendor dir, as the vendor dir contains
        // the file to be installed. This is the case when installing with create-project in the current directory
        // but in that case we ensure the directory is empty already in ProjectInstaller so no need to empty it here.
        if (\false === strpos($this->filesystem->normalizePath($vendorDir), $this->filesystem->normalizePath($path . \DIRECTORY_SEPARATOR))) {
            $this->filesystem->emptyDirectory($path);
        }
        $this->filesystem->ensureDirectoryExists($path);
        $this->filesystem->rename($this->getFileName($package, $path), $path . '/' . $this->getDistPath($package, \PATHINFO_BASENAME));
        // Single files can not have a mode set like files in archives
        // so we make sure if the file is a binary that it is executable
        foreach ($package->getBinaries() as $bin) {
            if (file_exists($path . '/' . $bin) && !is_executable($path . '/' . $bin)) {
                Silencer::call('chmod', $path . '/' . $bin, 0777 & ~umask());
            }
        }
        return \React\Promise\resolve(null);
    }
    /**
     * @param PATHINFO_EXTENSION|PATHINFO_BASENAME $component
     */
    protected function getDistPath(PackageInterface $package, int $component): string
    {
        return pathinfo((string) parse_url(strtr((string) $package->getDistUrl(), '\\', '/'), \PHP_URL_PATH), $component);
    }
    protected function clearLastCacheWrite(PackageInterface $package): void
    {
        if ($this->cache !== null && isset($this->lastCacheWrites[$package->getName()])) {
            $this->cache->remove($this->lastCacheWrites[$package->getName()]);
            unset($this->lastCacheWrites[$package->getName()]);
        }
    }
    protected function addCleanupPath(PackageInterface $package, string $path): void
    {
        $this->additionalCleanupPaths[$package->getName()][] = $path;
    }
    protected function removeCleanupPath(PackageInterface $package, string $path): void
    {
        if (isset($this->additionalCleanupPaths[$package->getName()])) {
            $idx = array_search($path, $this->additionalCleanupPaths[$package->getName()], \true);
            if (\false !== $idx) {
                unset($this->additionalCleanupPaths[$package->getName()][$idx]);
            }
        }
    }
    /**
     * @inheritDoc
     */
    public function update(PackageInterface $initial, PackageInterface $target, string $path): PromiseInterface
    {
        $this->io->writeError("  - " . UpdateOperation::format($initial, $target) . $this->getInstallOperationAppendix($target, $path));
        $promise = $this->remove($initial, $path, \false);
        return $promise->then(function () use ($target, $path): PromiseInterface {
            return $this->install($target, $path, \false);
        });
    }
    /**
     * @inheritDoc
     */
    public function remove(PackageInterface $package, string $path, bool $output = \true): PromiseInterface
    {
        if ($output) {
            $this->io->writeError("  - " . UninstallOperation::format($package));
        }
        $promise = $this->filesystem->removeDirectoryAsync($path);
        return $promise->then(static function ($result) use ($path): void {
            if (!$result) {
                throw new \RuntimeException('Could not completely delete ' . $path . ', aborting.');
            }
        });
    }
    /**
     * Gets file name for specific package
     *
     * @param  PackageInterface $package package instance
     * @param  string           $path    download path
     * @return string           file name
     */
    protected function getFileName(PackageInterface $package, string $path): string
    {
        $extension = $this->getDistPath($package, \PATHINFO_EXTENSION);
        if ($extension === '') {
            $extension = $package->getDistType();
        }
        return rtrim($this->config->get('vendor-dir') . '/composer/tmp-' . hash('md5', $package . spl_object_hash($package)) . '.' . $extension, '.');
    }
    /**
     * Gets appendix message to add to the "- Upgrading x" string being output on update
     *
     * @param  PackageInterface $package package instance
     * @param  string           $path    download path
     */
    protected function getInstallOperationAppendix(PackageInterface $package, string $path): string
    {
        return '';
    }
    /**
     * Process the download url
     *
     * @param  PackageInterface  $package package instance
     * @param  non-empty-string  $url     download url
     * @throws \RuntimeException If any problem with the url
     * @return non-empty-string  url
     */
    protected function processUrl(PackageInterface $package, string $url): string
    {
        if (!extension_loaded('openssl') && 0 === strpos($url, 'https:')) {
            throw new \RuntimeException('You must enable the openssl extension to download files via https');
        }
        if ($package->getDistReference() !== null) {
            $url = UrlUtil::updateDistReference($this->config, $url, $package->getDistReference());
        }
        return $url;
    }
    /**
     * @inheritDoc
     * @throws \RuntimeException
     */
    public function getLocalChanges(PackageInterface $package, string $path): ?string
    {
        $prevIO = $this->io;
        $this->io = new NullIO();
        $this->io->loadConfiguration($this->config);
        $e = null;
        $output = '';
        $targetDir = Filesystem::trimTrailingSlash($path);
        try {
            if (is_dir($targetDir . '_compare')) {
                $this->filesystem->removeDirectory($targetDir . '_compare');
            }
            $promise = $this->download($package, $targetDir . '_compare', null, \false);
            $promise->then(null, static function ($ex) use (&$e) {
                $e = $ex;
            });
            $this->httpDownloader->wait();
            if ($e !== null) {
                throw $e;
            }
            $promise = $this->install($package, $targetDir . '_compare', \false);
            $promise->then(null, static function ($ex) use (&$e) {
                $e = $ex;
            });
            $this->process->wait();
            if ($e !== null) {
                throw $e;
            }
            $comparer = new Comparer();
            $comparer->setSource($targetDir . '_compare');
            $comparer->setUpdate($targetDir);
            $comparer->doCompare();
            $output = $comparer->getChangedAsString(\true);
            $this->filesystem->removeDirectory($targetDir . '_compare');
        } catch (\Exception $e) {
        }
        $this->io = $prevIO;
        if ($e !== null) {
            if ($this->io->isDebug()) {
                throw $e;
            }
            return 'Failed to detect changes: [' . get_class($e) . '] ' . $e->getMessage();
        }
        $output = trim($output);
        return strlen($output) > 0 ? $output : null;
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer\Downloader;

use Composer\Package\PackageInterface;
/**
 * ChangeReport interface.
 *
 * @author Sascha Egerer <sascha.egerer@dkd.de>
 */
interface ChangeReportInterface
{
    /**
     * Checks for changes to the local copy
     *
     * @param  PackageInterface $package package instance
     * @param  string           $path    package directory
     * @return string|null      changes or null
     */
    public function getLocalChanges(PackageInterface $package, string $path): ?string;
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer\Downloader;

/**
 * @author Jordi Boggiano <j.boggiano@seld.be>
 */
class TransportException extends \RuntimeException
{
    /** @var ?array<string> */
    protected $headers;
    /** @var ?string */
    protected $response;
    /** @var ?int */
    protected $statusCode;
    /** @var array<mixed> */
    protected $responseInfo = [];
    public function __construct(string $message = "", int $code = 400, ?\Throwable $previous = null)
    {
        parent::__construct($message, $code, $previous);
    }
    /**
     * @param array<string> $headers
     */
    public function setHeaders(array $headers): void
    {
        $this->headers = $headers;
    }
    /**
     * @return ?array<string>
     */
    public function getHeaders(): ?array
    {
        return $this->headers;
    }
    public function setResponse(?string $response): void
    {
        $this->response = $response;
    }
    public function getResponse(): ?string
    {
        return $this->response;
    }
    /**
     * @param ?int $statusCode
     */
    public function setStatusCode($statusCode): void
    {
        $this->statusCode = $statusCode;
    }
    public function getStatusCode(): ?int
    {
        return $this->statusCode;
    }
    /**
     * @return array<mixed>
     */
    public function getResponseInfo(): array
    {
        return $this->responseInfo;
    }
    /**
     * @param array<mixed> $responseInfo
     */
    public function setResponseInfo(array $responseInfo): void
    {
        $this->responseInfo = $responseInfo;
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer\Downloader;

use Composer\Package\PackageInterface;
use Composer\Util\Platform;
use _ContaoManager\Symfony\Component\Finder\Finder;
use React\Promise\PromiseInterface;
use Composer\DependencyResolver\Operation\InstallOperation;
/**
 * Base downloader for archives
 *
 * @author Kirill chEbba Chebunin <iam@chebba.org>
 * @author Jordi Boggiano <j.boggiano@seld.be>
 * @author François Pluchino <francois.pluchino@opendisplay.com>
 */
abstract class ArchiveDownloader extends \Composer\Downloader\FileDownloader
{
    /**
     * @var array<string, true>
     */
    protected $cleanupExecuted = [];
    public function prepare(string $type, PackageInterface $package, string $path, ?PackageInterface $prevPackage = null): PromiseInterface
    {
        unset($this->cleanupExecuted[$package->getName()]);
        return parent::prepare($type, $package, $path, $prevPackage);
    }
    public function cleanup(string $type, PackageInterface $package, string $path, ?PackageInterface $prevPackage = null): PromiseInterface
    {
        $this->cleanupExecuted[$package->getName()] = \true;
        return parent::cleanup($type, $package, $path, $prevPackage);
    }
    /**
     * @inheritDoc
     *
     * @throws \RuntimeException
     * @throws \UnexpectedValueException
     */
    public function install(PackageInterface $package, string $path, bool $output = \true): PromiseInterface
    {
        if ($output) {
            $this->io->writeError("  - " . InstallOperation::format($package) . $this->getInstallOperationAppendix($package, $path));
        }
        $vendorDir = $this->config->get('vendor-dir');
        // clean up the target directory, unless it contains the vendor dir, as the vendor dir contains
        // the archive to be extracted. This is the case when installing with create-project in the current directory
        // but in that case we ensure the directory is empty already in ProjectInstaller so no need to empty it here.
        if (\false === strpos($this->filesystem->normalizePath($vendorDir), $this->filesystem->normalizePath($path . \DIRECTORY_SEPARATOR))) {
            $this->filesystem->emptyDirectory($path);
        }
        do {
            $temporaryDir = $vendorDir . '/composer/' . bin2hex(random_bytes(4));
        } while (is_dir($temporaryDir));
        $this->addCleanupPath($package, $temporaryDir);
        // avoid cleaning up $path if installing in "." for eg create-project as we can not
        // delete the directory we are currently in on windows
        if (!is_dir($path) || realpath($path) !== Platform::getCwd()) {
            $this->addCleanupPath($package, $path);
        }
        $this->filesystem->ensureDirectoryExists($temporaryDir);
        $fileName = $this->getFileName($package, $path);
        $filesystem = $this->filesystem;
        $cleanup = function () use ($path, $filesystem, $temporaryDir, $package) {
            // remove cache if the file was corrupted
            $this->clearLastCacheWrite($package);
            // clean up
            $filesystem->removeDirectory($temporaryDir);
            if (is_dir($path) && realpath($path) !== Platform::getCwd()) {
                $filesystem->removeDirectory($path);
            }
            $this->removeCleanupPath($package, $temporaryDir);
            $realpath = realpath($path);
            if ($realpath !== \false) {
                $this->removeCleanupPath($package, $realpath);
            }
        };
        try {
            $promise = $this->extract($package, $fileName, $temporaryDir);
        } catch (\Exception $e) {
            $cleanup();
            throw $e;
        }
        return $promise->then(function () use ($package, $filesystem, $fileName, $temporaryDir, $path): PromiseInterface {
            if (file_exists($fileName)) {
                $filesystem->unlink($fileName);
            }
            /**
             * Returns the folder content, excluding .DS_Store
             *
             * @param  string         $dir Directory
             * @return \SplFileInfo[]
             */
            $getFolderContent = static function ($dir): array {
                $finder = Finder::create()->ignoreVCS(\false)->ignoreDotFiles(\false)->notName('.DS_Store')->depth(0)->in($dir);
                return iterator_to_array($finder);
            };
            $renameRecursively = null;
            /**
             * Renames (and recursively merges if needed) a folder into another one
             *
             * For custom installers, where packages may share paths, and given Composer 2's parallelism, we need to make sure
             * that the source directory gets merged into the target one if the target exists. Otherwise rename() by default would
             * put the source into the target e.g. src/ => target/src/ (assuming target exists) instead of src/ => target/
             *
             * @param  string $from Directory
             * @param  string $to   Directory
             * @return void
             */
            $renameRecursively = static function ($from, $to) use ($filesystem, $getFolderContent, $package, &$renameRecursively) {
                $contentDir = $getFolderContent($from);
                // move files back out of the temp dir
                foreach ($contentDir as $file) {
                    $file = (string) $file;
                    if (is_dir($to . '/' . basename($file))) {
                        if (!is_dir($file)) {
                            throw new \RuntimeException('Installing ' . $package . ' would lead to overwriting the ' . $to . '/' . basename($file) . ' directory with a file from the package, invalid operation.');
                        }
                        $renameRecursively($file, $to . '/' . basename($file));
                    } else {
                        $filesystem->rename($file, $to . '/' . basename($file));
                    }
                }
            };
            $renameAsOne = \false;
            if (!file_exists($path)) {
                $renameAsOne = \true;
            } elseif ($filesystem->isDirEmpty($path)) {
                try {
                    if ($filesystem->removeDirectoryPhp($path)) {
                        $renameAsOne = \true;
                    }
                } catch (\RuntimeException $e) {
                    // ignore error, and simply do not renameAsOne
                }
            }
            $contentDir = $getFolderContent($temporaryDir);
            $singleDirAtTopLevel = 1 === count($contentDir) && is_dir((string) reset($contentDir));
            if ($renameAsOne) {
                // if the target $path is clear, we can rename the whole package in one go instead of looping over the contents
                if ($singleDirAtTopLevel) {
                    $extractedDir = (string) reset($contentDir);
                } else {
                    $extractedDir = $temporaryDir;
                }
                $filesystem->rename($extractedDir, $path);
            } else {
                // only one dir in the archive, extract its contents out of it
                $from = $temporaryDir;
                if ($singleDirAtTopLevel) {
                    $from = (string) reset($contentDir);
                }
                $renameRecursively($from, $path);
            }
            $promise = $filesystem->removeDirectoryAsync($temporaryDir);
            return $promise->then(function () use ($package, $path, $temporaryDir) {
                $this->removeCleanupPath($package, $temporaryDir);
                $this->removeCleanupPath($package, $path);
            });
        }, static function ($e) use ($cleanup) {
            $cleanup();
            throw $e;
        });
    }
    /**
     * @inheritDoc
     */
    protected function getInstallOperationAppendix(PackageInterface $package, string $path): string
    {
        return ': Extracting archive';
    }
    /**
     * Extract file to directory
     *
     * @param string $file Extracted file
     * @param string $path Directory
     * @phpstan-return PromiseInterface<void|null>
     *
     * @throws \UnexpectedValueException If can not extract downloaded file to path
     */
    abstract protected function extract(PackageInterface $package, string $file, string $path): PromiseInterface;
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer\Downloader;

use Composer\Package\PackageInterface;
/**
 * DVCS Downloader interface.
 *
 * @author James Titcumb <james@asgrim.com>
 */
interface DvcsDownloaderInterface
{
    /**
     * Checks for unpushed changes to a current branch
     *
     * @param  PackageInterface $package package instance
     * @param  string           $path    package directory
     * @return string|null      changes or null
     */
    public function getUnpushedChanges(PackageInterface $package, string $path): ?string;
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer\Downloader;

use React\Promise\PromiseInterface;
use Composer\Package\PackageInterface;
/**
 * Downloader for phar files
 *
 * @author Kirill chEbba Chebunin <iam@chebba.org>
 */
class PharDownloader extends \Composer\Downloader\ArchiveDownloader
{
    /**
     * @inheritDoc
     */
    protected function extract(PackageInterface $package, string $file, string $path): PromiseInterface
    {
        // Can throw an UnexpectedValueException
        $archive = new \Phar($file);
        $archive->extractTo($path, null, \true);
        /* TODO: handle openssl signed phars
         * https://github.com/composer/composer/pull/33#issuecomment-2250768
         * https://github.com/koto/phar-util
         * http://blog.kotowicz.net/2010/08/hardening-php-how-to-securely-include.html
         */
        return \React\Promise\resolve(null);
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer\Downloader;

use React\Promise\PromiseInterface;
use Composer\Package\Archiver\ArchivableFilesFinder;
use Composer\Package\Dumper\ArrayDumper;
use Composer\Package\PackageInterface;
use Composer\Package\Version\VersionGuesser;
use Composer\Package\Version\VersionParser;
use Composer\Util\Platform;
use Composer\Util\Filesystem;
use _ContaoManager\Symfony\Component\Filesystem\Exception\IOException;
use _ContaoManager\Symfony\Component\Filesystem\Filesystem as SymfonyFilesystem;
use Composer\DependencyResolver\Operation\InstallOperation;
use Composer\DependencyResolver\Operation\UninstallOperation;
/**
 * Download a package from a local path.
 *
 * @author Samuel Roze <samuel.roze@gmail.com>
 * @author Johann Reinke <johann.reinke@gmail.com>
 */
class PathDownloader extends \Composer\Downloader\FileDownloader implements \Composer\Downloader\VcsCapableDownloaderInterface
{
    private const STRATEGY_SYMLINK = 10;
    private const STRATEGY_MIRROR = 20;
    /**
     * @inheritDoc
     */
    public function download(PackageInterface $package, string $path, ?PackageInterface $prevPackage = null, bool $output = \true): PromiseInterface
    {
        $path = Filesystem::trimTrailingSlash($path);
        $url = $package->getDistUrl();
        if (null === $url) {
            throw new \RuntimeException('The package ' . $package->getPrettyName() . ' has no dist url configured, cannot download.');
        }
        $realUrl = realpath($url);
        if (\false === $realUrl || !file_exists($realUrl) || !is_dir($realUrl)) {
            throw new \RuntimeException(sprintf('Source path "%s" is not found for package %s', $url, $package->getName()));
        }
        if (realpath($path) === $realUrl) {
            return \React\Promise\resolve(null);
        }
        if (strpos(realpath($path) . \DIRECTORY_SEPARATOR, $realUrl . \DIRECTORY_SEPARATOR) === 0) {
            // IMPORTANT NOTICE: If you wish to change this, don't. You are wasting your time and ours.
            //
            // Please see https://github.com/composer/composer/pull/5974 and https://github.com/composer/composer/pull/6174
            // for previous attempts that were shut down because they did not work well enough or introduced too many risks.
            throw new \RuntimeException(sprintf('Package %s cannot install to "%s" inside its source at "%s"', $package->getName(), realpath($path), $realUrl));
        }
        return \React\Promise\resolve(null);
    }
    /**
     * @inheritDoc
     */
    public function install(PackageInterface $package, string $path, bool $output = \true): PromiseInterface
    {
        $path = Filesystem::trimTrailingSlash($path);
        $url = $package->getDistUrl();
        if (null === $url) {
            throw new \RuntimeException('The package ' . $package->getPrettyName() . ' has no dist url configured, cannot install.');
        }
        $realUrl = realpath($url);
        if (\false === $realUrl) {
            throw new \RuntimeException('Failed to realpath ' . $url);
        }
        if (realpath($path) === $realUrl) {
            if ($output) {
                $this->io->writeError("  - " . InstallOperation::format($package) . $this->getInstallOperationAppendix($package, $path));
            }
            return \React\Promise\resolve(null);
        }
        // Get the transport options with default values
        $transportOptions = $package->getTransportOptions() + ['relative' => \true];
        [$currentStrategy, $allowedStrategies] = $this->computeAllowedStrategies($transportOptions);
        $symfonyFilesystem = new SymfonyFilesystem();
        $this->filesystem->removeDirectory($path);
        if ($output) {
            $this->io->writeError("  - " . InstallOperation::format($package) . ': ', \false);
        }
        $isFallback = \false;
        if (self::STRATEGY_SYMLINK === $currentStrategy) {
            try {
                if (Platform::isWindows()) {
                    // Implement symlinks as NTFS junctions on Windows
                    if ($output) {
                        $this->io->writeError(sprintf('Junctioning from %s', $url), \false);
                    }
                    $this->filesystem->junction($realUrl, $path);
                } else {
                    $path = rtrim($path, "/");
                    if ($output) {
                        $this->io->writeError(sprintf('Symlinking from %s', $url), \false);
                    }
                    if ($transportOptions['relative'] === \true) {
                        $absolutePath = $path;
                        if (!$this->filesystem->isAbsolutePath($absolutePath)) {
                            $absolutePath = Platform::getCwd() . \DIRECTORY_SEPARATOR . $path;
                        }
                        $shortestPath = $this->filesystem->findShortestPath($absolutePath, $realUrl, \false, \true);
                        $symfonyFilesystem->symlink($shortestPath . '/', $path);
                    } else {
                        $symfonyFilesystem->symlink($realUrl . '/', $path);
                    }
                }
            } catch (IOException $e) {
                if (in_array(self::STRATEGY_MIRROR, $allowedStrategies, \true)) {
                    if ($output) {
                        $this->io->writeError('');
                        $this->io->writeError('    <error>Symlink failed, fallback to use mirroring!</error>');
                    }
                    $currentStrategy = self::STRATEGY_MIRROR;
                    $isFallback = \true;
                } else {
                    throw new \RuntimeException(sprintf('Symlink from "%s" to "%s" failed!', $realUrl, $path));
                }
            }
        }
        // Fallback if symlink failed or if symlink is not allowed for the package
        if (self::STRATEGY_MIRROR === $currentStrategy) {
            $realUrl = $this->filesystem->normalizePath($realUrl);
            if ($output) {
                $this->io->writeError(sprintf('%sMirroring from %s', $isFallback ? '    ' : '', $url), \false);
            }
            $iterator = new ArchivableFilesFinder($realUrl, []);
            $symfonyFilesystem->mirror($realUrl, $path, $iterator);
        }
        if ($output) {
            $this->io->writeError('');
        }
        return \React\Promise\resolve(null);
    }
    /**
     * @inheritDoc
     */
    public function remove(PackageInterface $package, string $path, bool $output = \true): PromiseInterface
    {
        $path = Filesystem::trimTrailingSlash($path);
        /**
         * realpath() may resolve Windows junctions to the source path, so we'll check for a junction first
         * to prevent a false positive when checking if the dist and install paths are the same.
         * See https://bugs.php.net/bug.php?id=77639
         *
         * For junctions don't blindly rely on Filesystem::removeDirectory as it may be overzealous. If a process
         * inadvertently locks the file the removal will fail, but it would fall back to recursive delete which
         * is disastrous within a junction. So in that case we have no other real choice but to fail hard.
         */
        if (Platform::isWindows() && $this->filesystem->isJunction($path)) {
            if ($output) {
                $this->io->writeError("  - " . UninstallOperation::format($package) . ", source is still present in {$path}");
            }
            if (!$this->filesystem->removeJunction($path)) {
                $this->io->writeError("    <warning>Could not remove junction at " . $path . " - is another process locking it?</warning>");
                throw new \RuntimeException('Could not reliably remove junction for package ' . $package->getName());
            }
            return \React\Promise\resolve(null);
        }
        $url = $package->getDistUrl();
        if (null === $url) {
            throw new \RuntimeException('The package ' . $package->getPrettyName() . ' has no dist url configured, cannot remove.');
        }
        // ensure that the source path (dist url) is not the same as the install path, which
        // can happen when using custom installers, see https://github.com/composer/composer/pull/9116
        // not using realpath here as we do not want to resolve the symlink to the original dist url
        // it points to
        $fs = new Filesystem();
        $absPath = $fs->isAbsolutePath($path) ? $path : Platform::getCwd() . '/' . $path;
        $absDistUrl = $fs->isAbsolutePath($url) ? $url : Platform::getCwd() . '/' . $url;
        if ($fs->normalizePath($absPath) === $fs->normalizePath($absDistUrl)) {
            if ($output) {
                $this->io->writeError("  - " . UninstallOperation::format($package) . ", source is still present in {$path}");
            }
            return \React\Promise\resolve(null);
        }
        return parent::remove($package, $path, $output);
    }
    /**
     * @inheritDoc
     */
    public function getVcsReference(PackageInterface $package, string $path): ?string
    {
        $path = Filesystem::trimTrailingSlash($path);
        $parser = new VersionParser();
        $guesser = new VersionGuesser($this->config, $this->process, $parser, $this->io);
        $dumper = new ArrayDumper();
        $packageConfig = $dumper->dump($package);
        $packageVersion = $guesser->guessVersion($packageConfig, $path);
        if ($packageVersion !== null) {
            return $packageVersion['commit'];
        }
        return null;
    }
    /**
     * @inheritDoc
     */
    protected function getInstallOperationAppendix(PackageInterface $package, string $path): string
    {
        $url = $package->getDistUrl();
        if (null === $url) {
            throw new \RuntimeException('The package ' . $package->getPrettyName() . ' has no dist url configured, cannot install.');
        }
        $realUrl = realpath($url);
        if (\false === $realUrl) {
            throw new \RuntimeException('Failed to realpath ' . $url);
        }
        if (realpath($path) === $realUrl) {
            return ': Source already present';
        }
        [$currentStrategy] = $this->computeAllowedStrategies($package->getTransportOptions());
        if ($currentStrategy === self::STRATEGY_SYMLINK) {
            if (Platform::isWindows()) {
                return ': Junctioning from ' . $package->getDistUrl();
            }
            return ': Symlinking from ' . $package->getDistUrl();
        }
        return ': Mirroring from ' . $package->getDistUrl();
    }
    /**
     * @param mixed[] $transportOptions
     *
     * @phpstan-return array{self::STRATEGY_*, non-empty-list<self::STRATEGY_*>}
     */
    private function computeAllowedStrategies(array $transportOptions): array
    {
        // When symlink transport option is null, both symlink and mirror are allowed
        $currentStrategy = self::STRATEGY_SYMLINK;
        $allowedStrategies = [self::STRATEGY_SYMLINK, self::STRATEGY_MIRROR];
        $mirrorPathRepos = Platform::getEnv('COMPOSER_MIRROR_PATH_REPOS');
        if ((bool) $mirrorPathRepos) {
            $currentStrategy = self::STRATEGY_MIRROR;
        }
        $symlinkOption = $transportOptions['symlink'] ?? null;
        if (\true === $symlinkOption) {
            $currentStrategy = self::STRATEGY_SYMLINK;
            $allowedStrategies = [self::STRATEGY_SYMLINK];
        } elseif (\false === $symlinkOption) {
            $currentStrategy = self::STRATEGY_MIRROR;
            $allowedStrategies = [self::STRATEGY_MIRROR];
        }
        // Check we can use junctions safely if we are on Windows
        if (Platform::isWindows() && self::STRATEGY_SYMLINK === $currentStrategy && !$this->safeJunctions()) {
            if (!in_array(self::STRATEGY_MIRROR, $allowedStrategies, \true)) {
                throw new \RuntimeException('You are on an old Windows / old PHP combo which does not allow Composer to use junctions/symlinks and this path repository has symlink:true in its options so copying is not allowed');
            }
            $currentStrategy = self::STRATEGY_MIRROR;
            $allowedStrategies = [self::STRATEGY_MIRROR];
        }
        // Check we can use symlink() otherwise
        if (!Platform::isWindows() && self::STRATEGY_SYMLINK === $currentStrategy && !function_exists('symlink')) {
            if (!in_array(self::STRATEGY_MIRROR, $allowedStrategies, \true)) {
                throw new \RuntimeException('Your PHP has the symlink() function disabled which does not allow Composer to use symlinks and this path repository has symlink:true in its options so copying is not allowed');
            }
            $currentStrategy = self::STRATEGY_MIRROR;
            $allowedStrategies = [self::STRATEGY_MIRROR];
        }
        return [$currentStrategy, $allowedStrategies];
    }
    /**
     * Returns true if junctions can be created and safely used on Windows
     *
     * A PHP bug makes junction detection fragile, leading to possible data loss
     * when removing a package. See https://bugs.php.net/bug.php?id=77552
     *
     * For safety we require a minimum version of Windows 7, so we can call the
     * system rmdir which will preserve target content if given a junction.
     *
     * The PHP bug was fixed in 7.2.16 and 7.3.3 (requires at least Windows 7).
     */
    private function safeJunctions(): bool
    {
        // We need to call mklink, and rmdir on Windows 7 (version 6.1)
        return function_exists('proc_open') && (\PHP_WINDOWS_VERSION_MAJOR > 6 || \PHP_WINDOWS_VERSION_MAJOR === 6 && \PHP_WINDOWS_VERSION_MINOR >= 1);
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer\Downloader;

use React\Promise\PromiseInterface;
use Composer\Package\PackageInterface;
use Composer\Repository\VcsRepository;
use Composer\Util\Perforce;
/**
 * @author Matt Whittom <Matt.Whittom@veteransunited.com>
 */
class PerforceDownloader extends \Composer\Downloader\VcsDownloader
{
    /** @var Perforce|null */
    protected $perforce;
    /**
     * @inheritDoc
     */
    protected function doDownload(PackageInterface $package, string $path, string $url, ?PackageInterface $prevPackage = null): PromiseInterface
    {
        return \React\Promise\resolve(null);
    }
    /**
     * @inheritDoc
     */
    public function doInstall(PackageInterface $package, string $path, string $url): PromiseInterface
    {
        $ref = $package->getSourceReference();
        $label = $this->getLabelFromSourceReference((string) $ref);
        $this->io->writeError('Cloning ' . $ref);
        $this->initPerforce($package, $path, $url);
        $this->perforce->setStream($ref);
        $this->perforce->p4Login();
        $this->perforce->writeP4ClientSpec();
        $this->perforce->connectClient();
        $this->perforce->syncCodeBase($label);
        $this->perforce->cleanupClientSpec();
        return \React\Promise\resolve(null);
    }
    private function getLabelFromSourceReference(string $ref): ?string
    {
        $pos = strpos($ref, '@');
        if (\false !== $pos) {
            return substr($ref, $pos + 1);
        }
        return null;
    }
    public function initPerforce(PackageInterface $package, string $path, string $url): void
    {
        if (!empty($this->perforce)) {
            $this->perforce->initializePath($path);
            return;
        }
        $repository = $package->getRepository();
        $repoConfig = null;
        if ($repository instanceof VcsRepository) {
            $repoConfig = $this->getRepoConfig($repository);
        }
        $this->perforce = Perforce::create($repoConfig, $url, $path, $this->process, $this->io);
    }
    /**
     * @return array<string, mixed>
     */
    private function getRepoConfig(VcsRepository $repository): array
    {
        return $repository->getRepoConfig();
    }
    /**
     * @inheritDoc
     */
    protected function doUpdate(PackageInterface $initial, PackageInterface $target, string $path, string $url): PromiseInterface
    {
        return $this->doInstall($target, $path, $url);
    }
    /**
     * @inheritDoc
     */
    public function getLocalChanges(PackageInterface $package, string $path): ?string
    {
        $this->io->writeError('Perforce driver does not check for local changes before overriding');
        return null;
    }
    /**
     * @inheritDoc
     */
    protected function getCommitLogs(string $fromReference, string $toReference, string $path): string
    {
        return $this->perforce->getCommitLogs($fromReference, $toReference);
    }
    public function setPerforce(Perforce $perforce): void
    {
        $this->perforce = $perforce;
    }
    /**
     * @inheritDoc
     */
    protected function hasMetadataRepository(string $path): bool
    {
        return \true;
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer\Downloader;

use Composer\Config;
use Composer\IO\IOInterface;
use Composer\Package\PackageInterface;
use Composer\Pcre\Preg;
use Composer\Util\Filesystem;
use Composer\Util\Git as GitUtil;
use Composer\Util\Url;
use Composer\Util\Platform;
use Composer\Util\ProcessExecutor;
use Composer\Cache;
use React\Promise\PromiseInterface;
/**
 * @author Jordi Boggiano <j.boggiano@seld.be>
 */
class GitDownloader extends \Composer\Downloader\VcsDownloader implements \Composer\Downloader\DvcsDownloaderInterface
{
    /**
     * @var bool[]
     * @phpstan-var array<string, bool>
     */
    private $hasStashedChanges = [];
    /**
     * @var bool[]
     * @phpstan-var array<string, bool>
     */
    private $hasDiscardedChanges = [];
    /**
     * @var GitUtil
     */
    private $gitUtil;
    /**
     * @var array
     * @phpstan-var array<int, array<string, bool>>
     */
    private $cachedPackages = [];
    public function __construct(IOInterface $io, Config $config, ?ProcessExecutor $process = null, ?Filesystem $fs = null)
    {
        parent::__construct($io, $config, $process, $fs);
        $this->gitUtil = new GitUtil($this->io, $this->config, $this->process, $this->filesystem);
    }
    /**
     * @inheritDoc
     */
    protected function doDownload(PackageInterface $package, string $path, string $url, ?PackageInterface $prevPackage = null): PromiseInterface
    {
        // Do not create an extra local cache when repository is already local
        if (Filesystem::isLocalPath($url)) {
            return \React\Promise\resolve(null);
        }
        GitUtil::cleanEnv($this->process);
        $cachePath = $this->config->get('cache-vcs-dir') . '/' . Preg::replace('{[^a-z0-9.]}i', '-', Url::sanitize($url)) . '/';
        $gitVersion = GitUtil::getVersion($this->process);
        // --dissociate option is only available since git 2.3.0-rc0
        if ($gitVersion && version_compare($gitVersion, '2.3.0-rc0', '>=') && Cache::isUsable($cachePath)) {
            $this->io->writeError("  - Syncing <info>" . $package->getName() . "</info> (<comment>" . $package->getFullPrettyVersion() . "</comment>) into cache");
            $this->io->writeError(sprintf('    Cloning to cache at %s', $cachePath), \true, IOInterface::DEBUG);
            $ref = $package->getSourceReference();
            if ($this->gitUtil->fetchRefOrSyncMirror($url, $cachePath, $ref, $package->getPrettyVersion()) && is_dir($cachePath)) {
                $this->cachedPackages[$package->getId()][$ref] = \true;
            }
        } elseif (null === $gitVersion) {
            throw new \RuntimeException('git was not found in your PATH, skipping source download');
        }
        return \React\Promise\resolve(null);
    }
    /**
     * @inheritDoc
     */
    protected function doInstall(PackageInterface $package, string $path, string $url): PromiseInterface
    {
        GitUtil::cleanEnv($this->process);
        $path = $this->normalizePath($path);
        $cachePath = $this->config->get('cache-vcs-dir') . '/' . Preg::replace('{[^a-z0-9.]}i', '-', Url::sanitize($url)) . '/';
        $ref = $package->getSourceReference();
        if (!empty($this->cachedPackages[$package->getId()][$ref])) {
            $msg = "Cloning " . $this->getShortHash($ref) . ' from cache';
            $cloneFlags = ['--dissociate', '--reference', $cachePath];
            $transportOptions = $package->getTransportOptions();
            if (isset($transportOptions['git']['single_use_clone']) && $transportOptions['git']['single_use_clone']) {
                $cloneFlags = [];
            }
            $commands = [array_merge(['git', 'clone', '--no-checkout', $cachePath, $path], $cloneFlags), ['git', 'remote', 'set-url', 'origin', '--', '%sanitizedUrl%'], ['git', 'remote', 'add', 'composer', '--', '%sanitizedUrl%']];
        } else {
            $msg = "Cloning " . $this->getShortHash($ref);
            $commands = [array_merge(['git', 'clone', '--no-checkout', '--', '%url%', $path]), ['git', 'remote', 'add', 'composer', '--', '%url%'], ['git', 'fetch', 'composer'], ['git', 'remote', 'set-url', 'origin', '--', '%sanitizedUrl%'], ['git', 'remote', 'set-url', 'composer', '--', '%sanitizedUrl%']];
            if (Platform::getEnv('COMPOSER_DISABLE_NETWORK')) {
                throw new \RuntimeException('The required git reference for ' . $package->getName() . ' is not in cache and network is disabled, aborting');
            }
        }
        $this->io->writeError($msg);
        $this->gitUtil->runCommands($commands, $url, $path, \true);
        $sourceUrl = $package->getSourceUrl();
        if ($url !== $sourceUrl && $sourceUrl !== null) {
            $this->updateOriginUrl($path, $sourceUrl);
        } else {
            $this->setPushUrl($path, $url);
        }
        if ($newRef = $this->updateToCommit($package, $path, (string) $ref, $package->getPrettyVersion())) {
            if ($package->getDistReference() === $package->getSourceReference()) {
                $package->setDistReference($newRef);
            }
            $package->setSourceReference($newRef);
        }
        return \React\Promise\resolve(null);
    }
    /**
     * @inheritDoc
     */
    protected function doUpdate(PackageInterface $initial, PackageInterface $target, string $path, string $url): PromiseInterface
    {
        GitUtil::cleanEnv($this->process);
        $path = $this->normalizePath($path);
        if (!$this->hasMetadataRepository($path)) {
            throw new \RuntimeException('The .git directory is missing from ' . $path . ', see https://getcomposer.org/commit-deps for more information');
        }
        $cachePath = $this->config->get('cache-vcs-dir') . '/' . Preg::replace('{[^a-z0-9.]}i', '-', Url::sanitize($url)) . '/';
        $ref = $target->getSourceReference();
        if (!empty($this->cachedPackages[$target->getId()][$ref])) {
            $msg = "Checking out " . $this->getShortHash($ref) . ' from cache';
            $remoteUrl = $cachePath;
        } else {
            $msg = "Checking out " . $this->getShortHash($ref);
            $remoteUrl = '%url%';
            if (Platform::getEnv('COMPOSER_DISABLE_NETWORK')) {
                throw new \RuntimeException('The required git reference for ' . $target->getName() . ' is not in cache and network is disabled, aborting');
            }
        }
        $this->io->writeError($msg);
        if (0 !== $this->process->execute(['git', 'rev-parse', '--quiet', '--verify', $ref . '^{commit}'], $output, $path)) {
            $commands = [['git', 'remote', 'set-url', 'composer', '--', $remoteUrl], ['git', 'fetch', 'composer'], ['git', 'fetch', '--tags', 'composer']];
            $this->gitUtil->runCommands($commands, $url, $path);
        }
        $command = ['git', 'remote', 'set-url', 'composer', '--', '%sanitizedUrl%'];
        $this->gitUtil->runCommands([$command], $url, $path);
        if ($newRef = $this->updateToCommit($target, $path, (string) $ref, $target->getPrettyVersion())) {
            if ($target->getDistReference() === $target->getSourceReference()) {
                $target->setDistReference($newRef);
            }
            $target->setSourceReference($newRef);
        }
        $updateOriginUrl = \false;
        if (0 === $this->process->execute(['git', 'remote', '-v'], $output, $path) && Preg::isMatch('{^origin\s+(?P<url>\S+)}m', $output, $originMatch) && Preg::isMatch('{^composer\s+(?P<url>\S+)}m', $output, $composerMatch)) {
            if ($originMatch['url'] === $composerMatch['url'] && $composerMatch['url'] !== $target->getSourceUrl()) {
                $updateOriginUrl = \true;
            }
        }
        if ($updateOriginUrl && $target->getSourceUrl() !== null) {
            $this->updateOriginUrl($path, $target->getSourceUrl());
        }
        return \React\Promise\resolve(null);
    }
    /**
     * @inheritDoc
     */
    public function getLocalChanges(PackageInterface $package, string $path): ?string
    {
        GitUtil::cleanEnv($this->process);
        if (!$this->hasMetadataRepository($path)) {
            return null;
        }
        $command = ['git', 'status', '--porcelain', '--untracked-files=no'];
        if (0 !== $this->process->execute($command, $output, $path)) {
            throw new \RuntimeException('Failed to execute ' . implode(' ', $command) . "\n\n" . $this->process->getErrorOutput());
        }
        $output = trim($output);
        return strlen($output) > 0 ? $output : null;
    }
    public function getUnpushedChanges(PackageInterface $package, string $path): ?string
    {
        GitUtil::cleanEnv($this->process);
        $path = $this->normalizePath($path);
        if (!$this->hasMetadataRepository($path)) {
            return null;
        }
        $command = ['git', 'show-ref', '--head', '-d'];
        if (0 !== $this->process->execute($command, $output, $path)) {
            throw new \RuntimeException('Failed to execute ' . implode(' ', $command) . "\n\n" . $this->process->getErrorOutput());
        }
        $refs = trim($output);
        if (!Preg::isMatchStrictGroups('{^([a-f0-9]+) HEAD$}mi', $refs, $match)) {
            // could not match the HEAD for some reason
            return null;
        }
        $headRef = $match[1];
        if (!Preg::isMatchAllStrictGroups('{^' . preg_quote($headRef) . ' refs/heads/(.+)$}mi', $refs, $matches)) {
            // not on a branch, we are either on a not-modified tag or some sort of detached head, so skip this
            return null;
        }
        $candidateBranches = $matches[1];
        // use the first match as branch name for now
        $branch = $candidateBranches[0];
        $unpushedChanges = null;
        $branchNotFoundError = \false;
        // do two passes, as if we find anything we want to fetch and then re-try
        for ($i = 0; $i <= 1; $i++) {
            $remoteBranches = [];
            // try to find matching branch names in remote repos
            foreach ($candidateBranches as $candidate) {
                if (Preg::isMatchAllStrictGroups('{^[a-f0-9]+ refs/remotes/((?:[^/]+)/' . preg_quote($candidate) . ')$}mi', $refs, $matches)) {
                    foreach ($matches[1] as $match) {
                        $branch = $candidate;
                        $remoteBranches[] = $match;
                    }
                    break;
                }
            }
            // if it doesn't exist, then we assume it is an unpushed branch
            // this is bad as we have no reference point to do a diff so we just bail listing
            // the branch as being unpushed
            if (count($remoteBranches) === 0) {
                $unpushedChanges = 'Branch ' . $branch . ' could not be found on any remote and appears to be unpushed';
                $branchNotFoundError = \true;
            } else {
                // if first iteration found no remote branch but it has now found some, reset $unpushedChanges
                // so we get the real diff output no matter its length
                if ($branchNotFoundError) {
                    $unpushedChanges = null;
                }
                foreach ($remoteBranches as $remoteBranch) {
                    $command = ['git', 'diff', '--name-status', $remoteBranch . '...' . $branch, '--'];
                    if (0 !== $this->process->execute($command, $output, $path)) {
                        throw new \RuntimeException('Failed to execute ' . implode(' ', $command) . "\n\n" . $this->process->getErrorOutput());
                    }
                    $output = trim($output);
                    // keep the shortest diff from all remote branches we compare against
                    if ($unpushedChanges === null || strlen($output) < strlen($unpushedChanges)) {
                        $unpushedChanges = $output;
                    }
                }
            }
            // first pass and we found unpushed changes, fetch from all remotes to make sure we have up to date
            // remotes and then try again as outdated remotes can sometimes cause false-positives
            if ($unpushedChanges && $i === 0) {
                $this->process->execute(['git', 'fetch', '--all'], $output, $path);
                // update list of refs after fetching
                $command = ['git', 'show-ref', '--head', '-d'];
                if (0 !== $this->process->execute($command, $output, $path)) {
                    throw new \RuntimeException('Failed to execute ' . implode(' ', $command) . "\n\n" . $this->process->getErrorOutput());
                }
                $refs = trim($output);
            }
            // abort after first pass if we didn't find anything
            if (!$unpushedChanges) {
                break;
            }
        }
        return $unpushedChanges;
    }
    /**
     * @inheritDoc
     */
    protected function cleanChanges(PackageInterface $package, string $path, bool $update): PromiseInterface
    {
        GitUtil::cleanEnv($this->process);
        $path = $this->normalizePath($path);
        $unpushed = $this->getUnpushedChanges($package, $path);
        if ($unpushed && ($this->io->isInteractive() || $this->config->get('discard-changes') !== \true)) {
            throw new \RuntimeException('Source directory ' . $path . ' has unpushed changes on the current branch: ' . "\n" . $unpushed);
        }
        if (null === $changes = $this->getLocalChanges($package, $path)) {
            return \React\Promise\resolve(null);
        }
        if (!$this->io->isInteractive()) {
            $discardChanges = $this->config->get('discard-changes');
            if (\true === $discardChanges) {
                return $this->discardChanges($path);
            }
            if ('stash' === $discardChanges) {
                if (!$update) {
                    return parent::cleanChanges($package, $path, $update);
                }
                return $this->stashChanges($path);
            }
            return parent::cleanChanges($package, $path, $update);
        }
        $changes = array_map(static function ($elem): string {
            return '    ' . $elem;
        }, Preg::split('{\s*\r?\n\s*}', $changes));
        $this->io->writeError('    <error>' . $package->getPrettyName() . ' has modified files:</error>');
        $this->io->writeError(array_slice($changes, 0, 10));
        if (count($changes) > 10) {
            $this->io->writeError('    <info>' . (count($changes) - 10) . ' more files modified, choose "v" to view the full list</info>');
        }
        while (\true) {
            switch ($this->io->ask('    <info>Discard changes [y,n,v,d,' . ($update ? 's,' : '') . '?]?</info> ', '?')) {
                case 'y':
                    $this->discardChanges($path);
                    break 2;
                case 's':
                    if (!$update) {
                        goto help;
                    }
                    $this->stashChanges($path);
                    break 2;
                case 'n':
                    throw new \RuntimeException('Update aborted');
                case 'v':
                    $this->io->writeError($changes);
                    break;
                case 'd':
                    $this->viewDiff($path);
                    break;
                case '?':
                default:
                    help:
                    $this->io->writeError(['    y - discard changes and apply the ' . ($update ? 'update' : 'uninstall'), '    n - abort the ' . ($update ? 'update' : 'uninstall') . ' and let you manually clean things up', '    v - view modified files', '    d - view local modifications (diff)']);
                    if ($update) {
                        $this->io->writeError('    s - stash changes and try to reapply them after the update');
                    }
                    $this->io->writeError('    ? - print help');
                    break;
            }
        }
        return \React\Promise\resolve(null);
    }
    /**
     * @inheritDoc
     */
    protected function reapplyChanges(string $path): void
    {
        $path = $this->normalizePath($path);
        if (!empty($this->hasStashedChanges[$path])) {
            unset($this->hasStashedChanges[$path]);
            $this->io->writeError('    <info>Re-applying stashed changes</info>');
            if (0 !== $this->process->execute(['git', 'stash', 'pop'], $output, $path)) {
                throw new \RuntimeException("Failed to apply stashed changes:\n\n" . $this->process->getErrorOutput());
            }
        }
        unset($this->hasDiscardedChanges[$path]);
    }
    /**
     * Updates the given path to the given commit ref
     *
     * @throws \RuntimeException
     * @return null|string       if a string is returned, it is the commit reference that was checked out if the original could not be found
     */
    protected function updateToCommit(PackageInterface $package, string $path, string $reference, string $prettyVersion): ?string
    {
        $force = !empty($this->hasDiscardedChanges[$path]) || !empty($this->hasStashedChanges[$path]) ? ['-f'] : [];
        // This uses the "--" sequence to separate branch from file parameters.
        //
        // Otherwise git tries the branch name as well as file name.
        // If the non-existent branch is actually the name of a file, the file
        // is checked out.
        $branch = Preg::replace('{(?:^dev-|(?:\.x)?-dev$)}i', '', $prettyVersion);
        /**
         * @var \Closure(non-empty-list<string>): bool $execute
         * @phpstan-ignore varTag.nativeType
         */
        $execute = function (array $command) use (&$output, $path) {
            /** @var non-empty-list<string> $command */
            $output = '';
            return 0 === $this->process->execute($command, $output, $path);
        };
        $branches = null;
        if ($execute(['git', 'branch', '-r'])) {
            $branches = $output;
        }
        // check whether non-commitish are branches or tags, and fetch branches with the remote name
        $gitRef = $reference;
        if (!Preg::isMatch('{^[a-f0-9]{40}$}', $reference) && null !== $branches && Preg::isMatch('{^\s+composer/' . preg_quote($reference) . '$}m', $branches)) {
            $command1 = array_merge(['git', 'checkout'], $force, ['-B', $branch, 'composer/' . $reference, '--']);
            $command2 = ['git', 'reset', '--hard', 'composer/' . $reference, '--'];
            if ($execute($command1) && $execute($command2)) {
                return null;
            }
        }
        // try to checkout branch by name and then reset it so it's on the proper branch name
        if (Preg::isMatch('{^[a-f0-9]{40}$}', $reference)) {
            // add 'v' in front of the branch if it was stripped when generating the pretty name
            if (null !== $branches && !Preg::isMatch('{^\s+composer/' . preg_quote($branch) . '$}m', $branches) && Preg::isMatch('{^\s+composer/v' . preg_quote($branch) . '$}m', $branches)) {
                $branch = 'v' . $branch;
            }
            $command = ['git', 'checkout', $branch, '--'];
            $fallbackCommand = array_merge(['git', 'checkout'], $force, ['-B', $branch, 'composer/' . $branch, '--']);
            $resetCommand = ['git', 'reset', '--hard', $reference, '--'];
            if (($execute($command) || $execute($fallbackCommand)) && $execute($resetCommand)) {
                return null;
            }
        }
        $command1 = array_merge(['git', 'checkout'], $force, [$gitRef, '--']);
        $command2 = ['git', 'reset', '--hard', $gitRef, '--'];
        if ($execute($command1) && $execute($command2)) {
            return null;
        }
        $exceptionExtra = '';
        // reference was not found (prints "fatal: reference is not a tree: $ref")
        if (\false !== strpos($this->process->getErrorOutput(), $reference)) {
            $this->io->writeError('    <warning>' . $reference . ' is gone (history was rewritten?)</warning>');
            $exceptionExtra = "\nIt looks like the commit hash is not available in the repository, maybe " . ($package->isDev() ? 'the commit was removed from the branch' : 'the tag was recreated') . '? Run "composer update ' . $package->getPrettyName() . '" to resolve this.';
        }
        $command = implode(' ', $command1) . ' && ' . implode(' ', $command2);
        throw new \RuntimeException(Url::sanitize('Failed to execute ' . $command . "\n\n" . $this->process->getErrorOutput() . $exceptionExtra));
    }
    protected function updateOriginUrl(string $path, string $url): void
    {
        $this->process->execute(['git', 'remote', 'set-url', 'origin', '--', $url], $output, $path);
        $this->setPushUrl($path, $url);
    }
    protected function setPushUrl(string $path, string $url): void
    {
        // set push url for github projects
        if (Preg::isMatch('{^(?:https?|git)://' . GitUtil::getGitHubDomainsRegex($this->config) . '/([^/]+)/([^/]+?)(?:\.git)?$}', $url, $match)) {
            $protocols = $this->config->get('github-protocols');
            $pushUrl = 'git@' . $match[1] . ':' . $match[2] . '/' . $match[3] . '.git';
            if (!in_array('ssh', $protocols, \true)) {
                $pushUrl = 'https://' . $match[1] . '/' . $match[2] . '/' . $match[3] . '.git';
            }
            $cmd = ['git', 'remote', 'set-url', '--push', 'origin', '--', $pushUrl];
            $this->process->execute($cmd, $ignoredOutput, $path);
        }
    }
    /**
     * @inheritDoc
     */
    protected function getCommitLogs(string $fromReference, string $toReference, string $path): string
    {
        $path = $this->normalizePath($path);
        $command = GitUtil::buildRevListCommand($this->process, array_merge(['--format=%h - %an: %s', $fromReference . '..' . $toReference], GitUtil::getNoShowSignatureFlags($this->process)));
        if (0 !== $this->process->execute($command, $output, $path)) {
            throw new \RuntimeException('Failed to execute ' . implode(' ', $command) . "\n\n" . $this->process->getErrorOutput());
        }
        return GitUtil::parseRevListOutput($output, $this->process);
    }
    /**
     * @phpstan-return PromiseInterface<void|null>
     * @throws \RuntimeException
     */
    protected function discardChanges(string $path): PromiseInterface
    {
        $path = $this->normalizePath($path);
        if (0 !== $this->process->execute(['git', 'clean', '-df'], $output, $path)) {
            throw new \RuntimeException("Could not reset changes\n\n:" . $output);
        }
        if (0 !== $this->process->execute(['git', 'reset', '--hard'], $output, $path)) {
            throw new \RuntimeException("Could not reset changes\n\n:" . $output);
        }
        $this->hasDiscardedChanges[$path] = \true;
        return \React\Promise\resolve(null);
    }
    /**
     * @phpstan-return PromiseInterface<void|null>
     * @throws \RuntimeException
     */
    protected function stashChanges(string $path): PromiseInterface
    {
        $path = $this->normalizePath($path);
        if (0 !== $this->process->execute(['git', 'stash', '--include-untracked'], $output, $path)) {
            throw new \RuntimeException("Could not stash changes\n\n:" . $output);
        }
        $this->hasStashedChanges[$path] = \true;
        return \React\Promise\resolve(null);
    }
    /**
     * @throws \RuntimeException
     */
    protected function viewDiff(string $path): void
    {
        $path = $this->normalizePath($path);
        if (0 !== $this->process->execute(['git', 'diff', 'HEAD'], $output, $path)) {
            throw new \RuntimeException("Could not view diff\n\n:" . $output);
        }
        $this->io->writeError($output);
    }
    protected function normalizePath(string $path): string
    {
        if (Platform::isWindows() && strlen($path) > 0) {
            $basePath = $path;
            $removed = [];
            while (!is_dir($basePath) && $basePath !== '\\') {
                array_unshift($removed, basename($basePath));
                $basePath = dirname($basePath);
            }
            if ($basePath === '\\') {
                return $path;
            }
            $path = rtrim(realpath($basePath) . '/' . implode('/', $removed), '/');
        }
        return $path;
    }
    /**
     * @inheritDoc
     */
    protected function hasMetadataRepository(string $path): bool
    {
        $path = $this->normalizePath($path);
        return is_dir($path . '/.git');
    }
    protected function getShortHash(string $reference): string
    {
        if (!$this->io->isVerbose() && Preg::isMatch('{^[0-9a-f]{40}$}', $reference)) {
            return substr($reference, 0, 10);
        }
        return $reference;
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer\Downloader;

use Composer\Package\PackageInterface;
use Composer\Pcre\Preg;
use Composer\Util\IniHelper;
use Composer\Util\Platform;
use _ContaoManager\Symfony\Component\Process\ExecutableFinder;
use _ContaoManager\Symfony\Component\Process\Process;
use React\Promise\PromiseInterface;
use ZipArchive;
/**
 * @author Jordi Boggiano <j.boggiano@seld.be>
 */
class ZipDownloader extends \Composer\Downloader\ArchiveDownloader
{
    /** @var array<int, non-empty-list<string>> */
    private static $unzipCommands;
    /** @var bool */
    private static $hasZipArchive;
    /** @var bool */
    private static $isWindows;
    /** @var ZipArchive|null */
    private $zipArchiveObject;
    // @phpstan-ignore property.onlyRead (helper property that is set via reflection for testing purposes)
    /**
     * @inheritDoc
     */
    public function download(PackageInterface $package, string $path, ?PackageInterface $prevPackage = null, bool $output = \true): PromiseInterface
    {
        if (null === self::$unzipCommands) {
            self::$unzipCommands = [];
            $finder = new ExecutableFinder();
            if (Platform::isWindows() && null !== $cmd = $finder->find('7z', null, ['C:\Program Files\7-Zip'])) {
                self::$unzipCommands[] = ['7z', $cmd, 'x', '-bb0', '-y', '%file%', '-o%path%'];
            }
            if (null !== $cmd = $finder->find('unzip')) {
                self::$unzipCommands[] = ['unzip', $cmd, '-qq', '%file%', '-d', '%path%'];
            }
            if (!Platform::isWindows() && null !== $cmd = $finder->find('7z')) {
                // 7z linux/macOS support is only used if unzip is not present
                self::$unzipCommands[] = ['7z', $cmd, 'x', '-bb0', '-y', '%file%', '-o%path%'];
            } elseif (!Platform::isWindows() && null !== $cmd = $finder->find('7zz')) {
                // 7zz linux/macOS support is only used if unzip is not present
                self::$unzipCommands[] = ['7zz', $cmd, 'x', '-bb0', '-y', '%file%', '-o%path%'];
            } elseif (!Platform::isWindows() && null !== $cmd = $finder->find('7za')) {
                // 7za linux/macOS support is only used if unzip is not present
                self::$unzipCommands[] = ['7za', $cmd, 'x', '-bb0', '-y', '%file%', '-o%path%'];
            }
        }
        $procOpenMissing = \false;
        if (!function_exists('proc_open')) {
            self::$unzipCommands = [];
            $procOpenMissing = \true;
        }
        if (null === self::$hasZipArchive) {
            self::$hasZipArchive = class_exists('ZipArchive');
        }
        if (!self::$hasZipArchive && !self::$unzipCommands) {
            // php.ini path is added to the error message to help users find the correct file
            $iniMessage = IniHelper::getMessage();
            if ($procOpenMissing) {
                $error = "The zip extension is missing and unzip/7z commands cannot be called as proc_open is disabled, skipping.\n" . $iniMessage;
            } else {
                $error = "The zip extension and unzip/7z commands are both missing, skipping.\n" . $iniMessage;
            }
            throw new \RuntimeException($error);
        }
        if (null === self::$isWindows) {
            self::$isWindows = Platform::isWindows();
            if (!self::$isWindows && !self::$unzipCommands) {
                if ($procOpenMissing) {
                    $this->io->writeError("<warning>proc_open is disabled so 'unzip' and '7z' commands cannot be used, zip files are being unpacked using the PHP zip extension.</warning>");
                    $this->io->writeError("<warning>This may cause invalid reports of corrupted archives. Besides, any UNIX permissions (e.g. executable) defined in the archives will be lost.</warning>");
                    $this->io->writeError("<warning>Enabling proc_open and installing 'unzip' or '7z' (21.01+) may remediate them.</warning>");
                } else {
                    $this->io->writeError("<warning>As there is no 'unzip' nor '7z' command installed zip files are being unpacked using the PHP zip extension.</warning>");
                    $this->io->writeError("<warning>This may cause invalid reports of corrupted archives. Besides, any UNIX permissions (e.g. executable) defined in the archives will be lost.</warning>");
                    $this->io->writeError("<warning>Installing 'unzip' or '7z' (21.01+) may remediate them.</warning>");
                }
            }
        }
        return parent::download($package, $path, $prevPackage, $output);
    }
    /**
     * extract $file to $path with "unzip" command
     *
     * @param  string           $file File to extract
     * @param  string           $path Path where to extract file
     * @phpstan-return PromiseInterface<void|null>
     */
    private function extractWithSystemUnzip(PackageInterface $package, string $file, string $path): PromiseInterface
    {
        static $warned7ZipLinux = \false;
        // Force Exception throwing if the other alternative extraction method is not available
        $isLastChance = !self::$hasZipArchive;
        if (0 === \count(self::$unzipCommands)) {
            // This was call as the favorite extract way, but is not available
            // We switch to the alternative
            return $this->extractWithZipArchive($package, $file, $path);
        }
        $commandSpec = reset(self::$unzipCommands);
        $executable = $commandSpec[0];
        $command = array_slice($commandSpec, 1);
        $map = [
            // normalize separators to backslashes to avoid problems with 7-zip on windows
            // see https://github.com/composer/composer/issues/10058
            '%file%' => strtr($file, '/', \DIRECTORY_SEPARATOR),
            '%path%' => strtr($path, '/', \DIRECTORY_SEPARATOR),
        ];
        $command = array_map(static function ($value) use ($map) {
            return strtr($value, $map);
        }, $command);
        if (!$warned7ZipLinux && !Platform::isWindows() && in_array($executable, ['7z', '7zz', '7za'], \true)) {
            $warned7ZipLinux = \true;
            if (0 === $this->process->execute([$commandSpec[1]], $output)) {
                if (Preg::isMatchStrictGroups('{^\s*7-Zip(?: \[64\])? ([0-9.]+)}', $output, $match) && version_compare($match[1], '21.01', '<')) {
                    $this->io->writeError('    <warning>Unzipping using ' . $executable . ' ' . $match[1] . ' may result in incorrect file permissions. Install ' . $executable . ' 21.01+ or unzip to ensure you get correct permissions.</warning>');
                }
            }
        }
        $io = $this->io;
        $tryFallback = function (\Throwable $processError) use ($isLastChance, $io, $file, $path, $package, $executable): PromiseInterface {
            if ($isLastChance) {
                throw $processError;
            }
            if (str_contains($processError->getMessage(), 'zip bomb')) {
                throw $processError;
            }
            if (!is_file($file)) {
                $io->writeError('    <warning>' . $processError->getMessage() . '</warning>');
                $io->writeError('    <warning>This most likely is due to a custom installer plugin not handling the returned Promise from the downloader</warning>');
                $io->writeError('    <warning>See https://github.com/composer/installers/commit/5006d0c28730ade233a8f42ec31ac68fb1c5c9bb for an example fix</warning>');
            } else {
                $io->writeError('    <warning>' . $processError->getMessage() . '</warning>');
                $io->writeError('    The archive may contain identical file names with different capitalization (which fails on case insensitive filesystems)');
                $io->writeError('    Unzip with ' . $executable . ' command failed, falling back to ZipArchive class');
                // additional debug data to try to figure out GH actions issues https://github.com/composer/composer/issues/11148
                if (Platform::getEnv('GITHUB_ACTIONS') !== \false && Platform::getEnv('COMPOSER_TESTS_ARE_RUNNING') === \false) {
                    $io->writeError('    <warning>Additional debug info, please report to https://github.com/composer/composer/issues/11148 if you see this:</warning>');
                    $io->writeError('File size: ' . @filesize($file));
                    $io->writeError('File SHA1: ' . hash_file('sha1', $file));
                    $io->writeError('First 100 bytes (hex): ' . bin2hex(substr((string) file_get_contents($file), 0, 100)));
                    $io->writeError('Last 100 bytes (hex): ' . bin2hex(substr((string) file_get_contents($file), -100)));
                    if (strlen((string) $package->getDistUrl()) > 0) {
                        $io->writeError('Origin URL: ' . $this->processUrl($package, (string) $package->getDistUrl()));
                        $io->writeError('Response Headers: ' . json_encode(\Composer\Downloader\FileDownloader::$responseHeaders[$package->getName()] ?? []));
                    }
                }
            }
            return $this->extractWithZipArchive($package, $file, $path);
        };
        try {
            $promise = $this->process->executeAsync($command);
            return $promise->then(function (Process $process) use ($tryFallback, $command, $package, $file) {
                if (!$process->isSuccessful()) {
                    if (isset($this->cleanupExecuted[$package->getName()])) {
                        throw new \RuntimeException('Failed to extract ' . $package->getName() . ' as the installation was aborted by another package operation.');
                    }
                    $output = $process->getErrorOutput();
                    $output = str_replace(', ' . $file . '.zip or ' . $file . '.ZIP', '', $output);
                    return $tryFallback(new \RuntimeException('Failed to extract ' . $package->getName() . ': (' . $process->getExitCode() . ') ' . implode(' ', $command) . "\n\n" . $output));
                }
            });
        } catch (\Throwable $e) {
            return $tryFallback($e);
        }
    }
    /**
     * extract $file to $path with ZipArchive
     *
     * @param  string           $file File to extract
     * @param  string           $path Path where to extract file
     * @phpstan-return PromiseInterface<void|null>
     */
    private function extractWithZipArchive(PackageInterface $package, string $file, string $path): PromiseInterface
    {
        $processError = null;
        $zipArchive = $this->zipArchiveObject ?: new ZipArchive();
        try {
            if (!file_exists($file) || ($filesize = filesize($file)) === \false || $filesize === 0) {
                $retval = -1;
            } else {
                $retval = $zipArchive->open($file);
            }
            if (\true === $retval) {
                $totalSize = 0;
                $archiveSize = filesize($file);
                $totalFiles = $zipArchive->count();
                if ($totalFiles > 0) {
                    $inspectAll = \false;
                    $filesToInspect = min($totalFiles, 5);
                    for ($i = 0; $i < $filesToInspect; $i++) {
                        $stat = $zipArchive->statIndex($inspectAll ? $i : random_int(0, $totalFiles - 1));
                        if ($stat === \false) {
                            continue;
                        }
                        $totalSize += $stat['size'];
                        if (!$inspectAll && $stat['size'] > $stat['comp_size'] * 200) {
                            $totalSize = 0;
                            $inspectAll = \true;
                            $i = -1;
                            $filesToInspect = $totalFiles;
                        }
                    }
                    if ($archiveSize !== \false && $totalSize > $archiveSize * 100 && $totalSize > 50 * 1024 * 1024) {
                        throw new \RuntimeException('Invalid zip file for "' . $package->getName() . '" with compression ratio >99% (possible zip bomb)');
                    }
                }
                $extractResult = $zipArchive->extractTo($path);
                if (\true === $extractResult) {
                    $zipArchive->close();
                    return \React\Promise\resolve(null);
                }
                $processError = new \RuntimeException(rtrim("There was an error extracting the ZIP file for \"{$package->getName()}\", it is either corrupted or using an invalid format.\n"));
            } else {
                $processError = new \UnexpectedValueException(rtrim($this->getErrorMessage($retval, $file) . "\n"), $retval);
            }
        } catch (\ErrorException $e) {
            $processError = new \RuntimeException('The archive for "' . $package->getName() . '" may contain identical file names with different capitalization (which fails on case insensitive filesystems): ' . $e->getMessage(), 0, $e);
        } catch (\Throwable $e) {
            $processError = $e;
        }
        throw $processError;
    }
    /**
     * extract $file to $path
     *
     * @param  string                $file File to extract
     * @param  string                $path Path where to extract file
     */
    protected function extract(PackageInterface $package, string $file, string $path): PromiseInterface
    {
        return $this->extractWithSystemUnzip($package, $file, $path);
    }
    /**
     * Give a meaningful error message to the user.
     */
    protected function getErrorMessage(int $retval, string $file): string
    {
        switch ($retval) {
            case ZipArchive::ER_EXISTS:
                return sprintf("File '%s' already exists.", $file);
            case ZipArchive::ER_INCONS:
                return sprintf("Zip archive '%s' is inconsistent.", $file);
            case ZipArchive::ER_INVAL:
                return sprintf("Invalid argument (%s)", $file);
            case ZipArchive::ER_MEMORY:
                return sprintf("Malloc failure (%s)", $file);
            case ZipArchive::ER_NOENT:
                return sprintf("No such zip file: '%s'", $file);
            case ZipArchive::ER_NOZIP:
                return sprintf("'%s' is not a zip archive.", $file);
            case ZipArchive::ER_OPEN:
                return sprintf("Can't open zip file: %s", $file);
            case ZipArchive::ER_READ:
                return sprintf("Zip read error (%s)", $file);
            case ZipArchive::ER_SEEK:
                return sprintf("Zip seek error (%s)", $file);
            case -1:
                return sprintf("'%s' is a corrupted zip archive (0 bytes), try again.", $file);
            default:
                return sprintf("'%s' is not a valid zip archive, got error code: %s", $file, $retval);
        }
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer\Downloader;

use React\Promise\PromiseInterface;
use Composer\Package\PackageInterface;
use Composer\Util\Platform;
/**
 * GZip archive downloader.
 *
 * @author Pavel Puchkin <i@neoascetic.me>
 */
class GzipDownloader extends \Composer\Downloader\ArchiveDownloader
{
    protected function extract(PackageInterface $package, string $file, string $path): PromiseInterface
    {
        $filename = pathinfo(parse_url(strtr((string) $package->getDistUrl(), '\\', '/'), \PHP_URL_PATH), \PATHINFO_FILENAME);
        $targetFilepath = $path . \DIRECTORY_SEPARATOR . $filename;
        // Try to use gunzip on *nix
        if (!Platform::isWindows()) {
            $command = ['sh', '-c', 'gzip -cd -- "$0" > "$1"', $file, $targetFilepath];
            if (0 === $this->process->execute($command, $ignoredOutput)) {
                return \React\Promise\resolve(null);
            }
            if (extension_loaded('zlib')) {
                // Fallback to using the PHP extension.
                $this->extractUsingExt($file, $targetFilepath);
                return \React\Promise\resolve(null);
            }
            $processError = 'Failed to execute ' . implode(' ', $command) . "\n\n" . $this->process->getErrorOutput();
            throw new \RuntimeException($processError);
        }
        // Windows version of PHP has built-in support of gzip functions
        $this->extractUsingExt($file, $targetFilepath);
        return \React\Promise\resolve(null);
    }
    private function extractUsingExt(string $file, string $targetFilepath): void
    {
        $archiveFile = gzopen($file, 'rb');
        $targetFile = fopen($targetFilepath, 'wb');
        while ($string = gzread($archiveFile, 4096)) {
            fwrite($targetFile, $string, Platform::strlen($string));
        }
        gzclose($archiveFile);
        fclose($targetFile);
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer;

use Composer\Advisory\Auditor;
use Composer\Config\ConfigSourceInterface;
use Composer\Downloader\TransportException;
use Composer\IO\IOInterface;
use Composer\Pcre\Preg;
use Composer\Util\Platform;
use Composer\Util\ProcessExecutor;
/**
 * @author Jordi Boggiano <j.boggiano@seld.be>
 */
class Config
{
    public const SOURCE_DEFAULT = 'default';
    public const SOURCE_COMMAND = 'command';
    public const SOURCE_UNKNOWN = 'unknown';
    public const RELATIVE_PATHS = 1;
    /** @var array<string, mixed> */
    public static $defaultConfig = [
        'process-timeout' => 300,
        'use-include-path' => \false,
        'allow-plugins' => [],
        'use-parent-dir' => 'prompt',
        'preferred-install' => 'dist',
        'audit' => ['ignore' => [], 'abandoned' => Auditor::ABANDONED_FAIL],
        'notify-on-install' => \true,
        'github-protocols' => ['https', 'ssh', 'git'],
        'gitlab-protocol' => null,
        'vendor-dir' => 'vendor',
        'bin-dir' => '{$vendor-dir}/bin',
        'cache-dir' => '{$home}/cache',
        'data-dir' => '{$home}',
        'cache-files-dir' => '{$cache-dir}/files',
        'cache-repo-dir' => '{$cache-dir}/repo',
        'cache-vcs-dir' => '{$cache-dir}/vcs',
        'cache-ttl' => 15552000,
        // 6 months
        'cache-files-ttl' => null,
        // fallback to cache-ttl
        'cache-files-maxsize' => '300MiB',
        'cache-read-only' => \false,
        'bin-compat' => 'auto',
        'discard-changes' => \false,
        'autoloader-suffix' => null,
        'sort-packages' => \false,
        'optimize-autoloader' => \false,
        'classmap-authoritative' => \false,
        'apcu-autoloader' => \false,
        'prepend-autoloader' => \true,
        'update-with-minimal-changes' => \false,
        'github-domains' => ['github.com'],
        'bitbucket-expose-hostname' => \true,
        'disable-tls' => \false,
        'secure-http' => \true,
        'secure-svn-domains' => [],
        'cafile' => null,
        'capath' => null,
        'github-expose-hostname' => \true,
        'gitlab-domains' => ['gitlab.com'],
        'store-auths' => 'prompt',
        'platform' => [],
        'archive-format' => 'tar',
        'archive-dir' => '.',
        'htaccess-protect' => \true,
        'use-github-api' => \true,
        'lock' => \true,
        'platform-check' => 'php-only',
        'bitbucket-oauth' => [],
        'github-oauth' => [],
        'gitlab-oauth' => [],
        'gitlab-token' => [],
        'http-basic' => [],
        'bearer' => [],
        'custom-headers' => [],
        'bump-after-update' => \false,
        'allow-missing-requirements' => \false,
        'client-certificate' => [],
        'forgejo-domains' => ['codeberg.org'],
        'forgejo-token' => [],
    ];
    /** @var array<string, mixed> */
    public static $defaultRepositories = ['packagist.org' => ['type' => 'composer', 'url' => 'https://repo.packagist.org']];
    /** @var array<string, mixed> */
    private $config;
    /** @var ?non-empty-string */
    private $baseDir;
    /** @var array<int|string, mixed> */
    private $repositories;
    /** @var ConfigSourceInterface */
    private $configSource;
    /** @var ConfigSourceInterface */
    private $authConfigSource;
    /** @var ConfigSourceInterface|null */
    private $localAuthConfigSource = null;
    /** @var bool */
    private $useEnvironment;
    /** @var array<string, true> */
    private $warnedHosts = [];
    /** @var array<string, true> */
    private $sslVerifyWarnedHosts = [];
    /** @var array<string, string> */
    private $sourceOfConfigValue = [];
    /**
     * @param bool    $useEnvironment Use COMPOSER_ environment variables to replace config settings
     * @param ?string $baseDir        Optional base directory of the config
     */
    public function __construct(bool $useEnvironment = \true, ?string $baseDir = null)
    {
        // load defaults
        $this->config = static::$defaultConfig;
        $this->repositories = static::$defaultRepositories;
        $this->useEnvironment = $useEnvironment;
        $this->baseDir = is_string($baseDir) && '' !== $baseDir ? $baseDir : null;
        foreach ($this->config as $configKey => $configValue) {
            $this->setSourceOfConfigValue($configValue, $configKey, self::SOURCE_DEFAULT);
        }
        foreach ($this->repositories as $configKey => $configValue) {
            $this->setSourceOfConfigValue($configValue, 'repositories.' . $configKey, self::SOURCE_DEFAULT);
        }
    }
    /**
     * Changing this can break path resolution for relative config paths so do not call this without knowing what you are doing
     *
     * The $baseDir should be an absolute path and without trailing slash
     *
     * @param non-empty-string|null $baseDir
     */
    public function setBaseDir(?string $baseDir): void
    {
        $this->baseDir = $baseDir;
    }
    public function setConfigSource(ConfigSourceInterface $source): void
    {
        $this->configSource = $source;
    }
    public function getConfigSource(): ConfigSourceInterface
    {
        return $this->configSource;
    }
    public function setAuthConfigSource(ConfigSourceInterface $source): void
    {
        $this->authConfigSource = $source;
    }
    public function getAuthConfigSource(): ConfigSourceInterface
    {
        return $this->authConfigSource;
    }
    public function setLocalAuthConfigSource(ConfigSourceInterface $source): void
    {
        $this->localAuthConfigSource = $source;
    }
    public function getLocalAuthConfigSource(): ?ConfigSourceInterface
    {
        return $this->localAuthConfigSource;
    }
    /**
     * Merges new config values with the existing ones (overriding)
     *
     * @param array{config?: array<string, mixed>, repositories?: array<mixed>} $config
     */
    public function merge(array $config, string $source = self::SOURCE_UNKNOWN): void
    {
        // override defaults with given config
        if (!empty($config['config']) && is_array($config['config'])) {
            foreach ($config['config'] as $key => $val) {
                if (in_array($key, ['bitbucket-oauth', 'github-oauth', 'gitlab-oauth', 'gitlab-token', 'http-basic', 'bearer', 'client-certificate', 'forgejo-token'], \true) && isset($this->config[$key])) {
                    $this->config[$key] = array_merge($this->config[$key], $val);
                    $this->setSourceOfConfigValue($val, $key, $source);
                } elseif (in_array($key, ['allow-plugins'], \true) && isset($this->config[$key]) && is_array($this->config[$key]) && is_array($val)) {
                    // merging $val first to get the local config on top of the global one, then appending the global config,
                    // then merging local one again to make sure the values from local win over global ones for keys present in both
                    $this->config[$key] = array_merge($val, $this->config[$key], $val);
                    $this->setSourceOfConfigValue($val, $key, $source);
                } elseif (in_array($key, ['gitlab-domains', 'github-domains'], \true) && isset($this->config[$key])) {
                    $this->config[$key] = array_unique(array_merge($this->config[$key], $val));
                    $this->setSourceOfConfigValue($val, $key, $source);
                } elseif ('preferred-install' === $key && isset($this->config[$key])) {
                    if (is_array($val) || is_array($this->config[$key])) {
                        if (is_string($val)) {
                            $val = ['*' => $val];
                        }
                        if (is_string($this->config[$key])) {
                            $this->config[$key] = ['*' => $this->config[$key]];
                            $this->sourceOfConfigValue[$key . '*'] = $source;
                        }
                        $this->config[$key] = array_merge($this->config[$key], $val);
                        $this->setSourceOfConfigValue($val, $key, $source);
                        // the full match pattern needs to be last
                        if (isset($this->config[$key]['*'])) {
                            $wildcard = $this->config[$key]['*'];
                            unset($this->config[$key]['*']);
                            $this->config[$key]['*'] = $wildcard;
                        }
                    } else {
                        $this->config[$key] = $val;
                        $this->setSourceOfConfigValue($val, $key, $source);
                    }
                } elseif ('audit' === $key) {
                    $currentIgnores = $this->config['audit']['ignore'];
                    $this->config[$key] = array_merge($this->config['audit'], $val);
                    $this->setSourceOfConfigValue($val, $key, $source);
                    $this->config['audit']['ignore'] = array_merge($currentIgnores, $val['ignore'] ?? []);
                } else {
                    $this->config[$key] = $val;
                    $this->setSourceOfConfigValue($val, $key, $source);
                }
            }
        }
        if (!empty($config['repositories']) && is_array($config['repositories'])) {
            $this->repositories = array_reverse($this->repositories, \true);
            $newRepos = array_reverse($config['repositories'], \true);
            foreach ($newRepos as $name => $repository) {
                // disable a repository by name
                // this is a code path, that will be used less as the next check will be preferred
                if (\false === $repository) {
                    $this->disableRepoByName((string) $name);
                    continue;
                }
                // disable a repository with an anonymous {"name": false} repo
                if (is_array($repository) && 1 === count($repository) && \false === current($repository)) {
                    $this->disableRepoByName((string) key($repository));
                    continue;
                }
                // auto-deactivate the default packagist.org repo if it gets redefined
                if (isset($repository['type'], $repository['url']) && $repository['type'] === 'composer' && Preg::isMatch('{^https?://(?:[a-z0-9-.]+\.)?packagist.org(/|$)}', $repository['url'])) {
                    $this->disableRepoByName('packagist.org');
                }
                // store repo
                if (is_int($name)) {
                    if (!isset($this->repositories[$name])) {
                        $this->repositories[$name] = $repository;
                    } else {
                        $this->repositories[] = $repository;
                    }
                    $this->setSourceOfConfigValue($repository, 'repositories.' . array_search($repository, $this->repositories, \true), $source);
                } else if ($name === 'packagist') {
                    // BC support for default "packagist" named repo
                    $this->repositories[$name . '.org'] = $repository;
                    $this->setSourceOfConfigValue($repository, 'repositories.' . $name . '.org', $source);
                } else {
                    $this->repositories[$name] = $repository;
                    $this->setSourceOfConfigValue($repository, 'repositories.' . $name, $source);
                }
            }
            $this->repositories = array_reverse($this->repositories, \true);
        }
    }
    /**
     * @return array<int|string, mixed>
     */
    public function getRepositories(): array
    {
        return $this->repositories;
    }
    /**
     * Returns a setting
     *
     * @param  int               $flags Options (see class constants)
     * @throws \RuntimeException
     *
     * @return mixed
     */
    public function get(string $key, int $flags = 0)
    {
        switch ($key) {
            // strings/paths with env var and {$refs} support
            case 'vendor-dir':
            case 'bin-dir':
            case 'process-timeout':
            case 'data-dir':
            case 'cache-dir':
            case 'cache-files-dir':
            case 'cache-repo-dir':
            case 'cache-vcs-dir':
            case 'cafile':
            case 'capath':
                // convert foo-bar to COMPOSER_FOO_BAR and check if it exists since it overrides the local config
                $env = 'COMPOSER_' . strtoupper(strtr($key, '-', '_'));
                $val = $this->getComposerEnv($env);
                if ($val !== \false) {
                    $this->setSourceOfConfigValue($val, $key, $env);
                }
                if ($key === 'process-timeout') {
                    return max(0, \false !== $val ? (int) $val : $this->config[$key]);
                }
                $val = rtrim((string) $this->process(\false !== $val ? $val : $this->config[$key], $flags), '/\\');
                $val = Platform::expandPath($val);
                if (substr($key, -4) !== '-dir') {
                    return $val;
                }
                return ($flags & self::RELATIVE_PATHS) === self::RELATIVE_PATHS ? $val : $this->realpath($val);
            // booleans with env var support
            case 'cache-read-only':
            case 'htaccess-protect':
                // convert foo-bar to COMPOSER_FOO_BAR and check if it exists since it overrides the local config
                $env = 'COMPOSER_' . strtoupper(strtr($key, '-', '_'));
                $val = $this->getComposerEnv($env);
                if (\false === $val) {
                    $val = $this->config[$key];
                } else {
                    $this->setSourceOfConfigValue($val, $key, $env);
                }
                return $val !== 'false' && (bool) $val;
            // booleans without env var support
            case 'disable-tls':
            case 'secure-http':
            case 'use-github-api':
            case 'lock':
                // special case for secure-http
                if ($key === 'secure-http' && $this->get('disable-tls') === \true) {
                    return \false;
                }
                return $this->config[$key] !== 'false' && (bool) $this->config[$key];
            // ints without env var support
            case 'cache-ttl':
                return max(0, (int) $this->config[$key]);
            // numbers with kb/mb/gb support, without env var support
            case 'cache-files-maxsize':
                if (!Preg::isMatch('/^\s*([0-9.]+)\s*(?:([kmg])(?:i?b)?)?\s*$/i', (string) $this->config[$key], $matches)) {
                    throw new \RuntimeException("Could not parse the value of '{$key}': {$this->config[$key]}");
                }
                $size = (float) $matches[1];
                if (isset($matches[2])) {
                    switch (strtolower($matches[2])) {
                        case 'g':
                            $size *= 1024;
                        // intentional fallthrough
                        // no break
                        case 'm':
                            $size *= 1024;
                        // intentional fallthrough
                        // no break
                        case 'k':
                            $size *= 1024;
                            break;
                    }
                }
                return max(0, (int) $size);
            // special cases below
            case 'cache-files-ttl':
                if (isset($this->config[$key])) {
                    return max(0, (int) $this->config[$key]);
                }
                return $this->get('cache-ttl');
            case 'home':
                return rtrim($this->process(Platform::expandPath($this->config[$key]), $flags), '/\\');
            case 'bin-compat':
                $value = $this->getComposerEnv('COMPOSER_BIN_COMPAT') ?: $this->config[$key];
                if (!in_array($value, ['auto', 'full', 'proxy', 'symlink'])) {
                    throw new \RuntimeException("Invalid value for 'bin-compat': {$value}. Expected auto, full or proxy");
                }
                if ($value === 'symlink') {
                    trigger_error('config.bin-compat "symlink" is deprecated since Composer 2.2, use auto, full (for Windows compatibility) or proxy instead.', \E_USER_DEPRECATED);
                }
                return $value;
            case 'discard-changes':
                $env = $this->getComposerEnv('COMPOSER_DISCARD_CHANGES');
                if ($env !== \false) {
                    if (!in_array($env, ['stash', 'true', 'false', '1', '0'], \true)) {
                        throw new \RuntimeException("Invalid value for COMPOSER_DISCARD_CHANGES: {$env}. Expected 1, 0, true, false or stash");
                    }
                    if ('stash' === $env) {
                        return 'stash';
                    }
                    // convert string value to bool
                    return $env !== 'false' && (bool) $env;
                }
                if (!in_array($this->config[$key], [\true, \false, 'stash'], \true)) {
                    throw new \RuntimeException("Invalid value for 'discard-changes': {$this->config[$key]}. Expected true, false or stash");
                }
                return $this->config[$key];
            case 'github-protocols':
                $protos = $this->config['github-protocols'];
                if ($this->config['secure-http'] && \false !== $index = array_search('git', $protos)) {
                    unset($protos[$index]);
                }
                if (reset($protos) === 'http') {
                    throw new \RuntimeException('The http protocol for github is not available anymore, update your config\'s github-protocols to use "https", "git" or "ssh"');
                }
                return $protos;
            case 'autoloader-suffix':
                if ($this->config[$key] === '') {
                    // we need to guarantee null or non-empty-string
                    return null;
                }
                return $this->process($this->config[$key], $flags);
            case 'audit':
                $result = $this->config[$key];
                $abandonedEnv = $this->getComposerEnv('COMPOSER_AUDIT_ABANDONED');
                if (\false !== $abandonedEnv) {
                    if (!in_array($abandonedEnv, $validChoices = Auditor::ABANDONEDS, \true)) {
                        throw new \RuntimeException("Invalid value for COMPOSER_AUDIT_ABANDONED: {$abandonedEnv}. Expected one of " . implode(', ', Auditor::ABANDONEDS) . ".");
                    }
                    $result['abandoned'] = $abandonedEnv;
                }
                $blockAbandonedEnv = $this->getComposerEnv('COMPOSER_SECURITY_BLOCKING_ABANDONED');
                if (\false !== $blockAbandonedEnv) {
                    if (!in_array($blockAbandonedEnv, ['0', '1'], \true)) {
                        throw new \RuntimeException("Invalid value for COMPOSER_SECURITY_BLOCKING_ABANDONED: {$blockAbandonedEnv}. Expected 0 or 1.");
                    }
                    $result['block-abandoned'] = (bool) (int) $blockAbandonedEnv;
                }
                return $result;
            default:
                if (!isset($this->config[$key])) {
                    return null;
                }
                return $this->process($this->config[$key], $flags);
        }
    }
    /**
     * @return array<string, mixed[]>
     */
    public function all(int $flags = 0): array
    {
        $all = ['repositories' => $this->getRepositories()];
        foreach (array_keys($this->config) as $key) {
            $all['config'][$key] = $this->get($key, $flags);
        }
        return $all;
    }
    public function getSourceOfValue(string $key): string
    {
        $this->get($key);
        return $this->sourceOfConfigValue[$key] ?? self::SOURCE_UNKNOWN;
    }
    /**
     * @param mixed  $configValue
     */
    private function setSourceOfConfigValue($configValue, string $path, string $source): void
    {
        $this->sourceOfConfigValue[$path] = $source;
        if (is_array($configValue)) {
            foreach ($configValue as $key => $value) {
                $this->setSourceOfConfigValue($value, $path . '.' . $key, $source);
            }
        }
    }
    /**
     * @return array<string, mixed[]>
     */
    public function raw(): array
    {
        return ['repositories' => $this->getRepositories(), 'config' => $this->config];
    }
    /**
     * Checks whether a setting exists
     */
    public function has(string $key): bool
    {
        return array_key_exists($key, $this->config);
    }
    /**
     * Replaces {$refs} inside a config string
     *
     * @param  string|mixed $value a config string that can contain {$refs-to-other-config}
     * @param  int          $flags Options (see class constants)
     *
     * @return string|mixed
     */
    private function process($value, int $flags)
    {
        if (!is_string($value)) {
            return $value;
        }
        return Preg::replaceCallback('#\{\$(.+)\}#', function ($match) use ($flags) {
            return $this->get($match[1], $flags);
        }, $value);
    }
    /**
     * Turns relative paths in absolute paths without realpath()
     *
     * Since the dirs might not exist yet we can not call realpath or it will fail.
     */
    private function realpath(string $path): string
    {
        if (Preg::isMatch('{^(?:/|[a-z]:|[a-z0-9.]+://|\\\\\\\\)}i', $path)) {
            return $path;
        }
        return $this->baseDir !== null ? $this->baseDir . '/' . $path : $path;
    }
    /**
     * Reads the value of a Composer environment variable
     *
     * This should be used to read COMPOSER_ environment variables
     * that overload config values.
     *
     * @param non-empty-string $var
     *
     * @return string|false
     */
    private function getComposerEnv(string $var)
    {
        if ($this->useEnvironment) {
            return Platform::getEnv($var);
        }
        return \false;
    }
    private function disableRepoByName(string $name): void
    {
        if (isset($this->repositories[$name])) {
            unset($this->repositories[$name]);
        } elseif ($name === 'packagist') {
            // BC support for default "packagist" named repo
            unset($this->repositories['packagist.org']);
        }
    }
    /**
     * Validates that the passed URL is allowed to be used by current config, or throws an exception.
     *
     * @param mixed[]     $repoOptions
     */
    public function prohibitUrlByConfig(string $url, ?IOInterface $io = null, array $repoOptions = []): void
    {
        // Return right away if the URL is malformed or custom (see issue #5173), but only for non-HTTP(S) URLs
        if (\false === filter_var($url, \FILTER_VALIDATE_URL) && !Preg::isMatch('{^https?://}', $url)) {
            return;
        }
        // Extract scheme and throw exception on known insecure protocols
        $scheme = parse_url($url, \PHP_URL_SCHEME);
        $hostname = parse_url($url, \PHP_URL_HOST);
        if (in_array($scheme, ['http', 'git', 'ftp', 'svn'])) {
            if ($this->get('secure-http')) {
                if ($scheme === 'svn') {
                    if (in_array($hostname, $this->get('secure-svn-domains'), \true)) {
                        return;
                    }
                    throw new TransportException("Your configuration does not allow connections to {$url}. See https://getcomposer.org/doc/06-config.md#secure-svn-domains for details.");
                }
                throw new TransportException("Your configuration does not allow connections to {$url}. See https://getcomposer.org/doc/06-config.md#secure-http for details.");
            }
            if ($io !== null) {
                if (is_string($hostname)) {
                    if (!isset($this->warnedHosts[$hostname])) {
                        $io->writeError("<warning>Warning: Accessing {$hostname} over {$scheme} which is an insecure protocol.</warning>");
                    }
                    $this->warnedHosts[$hostname] = \true;
                }
            }
        }
        if ($io !== null && is_string($hostname) && !isset($this->sslVerifyWarnedHosts[$hostname])) {
            $warning = null;
            if (isset($repoOptions['ssl']['verify_peer']) && !(bool) $repoOptions['ssl']['verify_peer']) {
                $warning = 'verify_peer';
            }
            if (isset($repoOptions['ssl']['verify_peer_name']) && !(bool) $repoOptions['ssl']['verify_peer_name']) {
                $warning = $warning === null ? 'verify_peer_name' : $warning . ' and verify_peer_name';
            }
            if ($warning !== null) {
                $io->writeError("<warning>Warning: Accessing {$hostname} with {$warning} disabled.</warning>");
                $this->sslVerifyWarnedHosts[$hostname] = \true;
            }
        }
    }
    /**
     * Used by long-running custom scripts in composer.json
     *
     * "scripts": {
     *   "watch": [
     *     "Composer\\Config::disableProcessTimeout",
     *     "vendor/bin/long-running-script --watch"
     *   ]
     * }
     */
    public static function disableProcessTimeout(): void
    {
        // Override global timeout set earlier by environment or config
        ProcessExecutor::setTimeout(0);
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer\Script;

use Composer\Composer;
use Composer\IO\IOInterface;
use Composer\EventDispatcher\Event as BaseEvent;
/**
 * The script event class
 *
 * @author François Pluchino <francois.pluchino@opendisplay.com>
 * @author Nils Adermann <naderman@naderman.de>
 */
class Event extends BaseEvent
{
    /**
     * @var Composer The composer instance
     */
    private $composer;
    /**
     * @var IOInterface The IO instance
     */
    private $io;
    /**
     * @var bool Dev mode flag
     */
    private $devMode;
    /**
     * @var BaseEvent|null
     */
    private $originatingEvent;
    /**
     * Constructor.
     *
     * @param string $name The event name
     * @param Composer $composer The composer object
     * @param IOInterface $io The IOInterface object
     * @param bool $devMode Whether or not we are in dev mode
     * @param array<string|int|float|bool|null> $args Arguments passed by the user
     * @param mixed[] $flags Optional flags to pass data not as argument
     */
    public function __construct(string $name, Composer $composer, IOInterface $io, bool $devMode = \false, array $args = [], array $flags = [])
    {
        parent::__construct($name, $args, $flags);
        $this->composer = $composer;
        $this->io = $io;
        $this->devMode = $devMode;
    }
    /**
     * Returns the composer instance.
     */
    public function getComposer(): Composer
    {
        return $this->composer;
    }
    /**
     * Returns the IO instance.
     */
    public function getIO(): IOInterface
    {
        return $this->io;
    }
    /**
     * Return the dev mode flag
     */
    public function isDevMode(): bool
    {
        return $this->devMode;
    }
    /**
     * Set the originating event.
     */
    public function getOriginatingEvent(): ?BaseEvent
    {
        return $this->originatingEvent;
    }
    /**
     * Set the originating event.
     *
     * @return $this
     */
    public function setOriginatingEvent(BaseEvent $event): self
    {
        $this->originatingEvent = $this->calculateOriginatingEvent($event);
        return $this;
    }
    /**
     * Returns the upper-most event in chain.
     */
    private function calculateOriginatingEvent(BaseEvent $event): BaseEvent
    {
        if ($event instanceof \Composer\Script\Event && $event->getOriginatingEvent()) {
            return $this->calculateOriginatingEvent($event->getOriginatingEvent());
        }
        return $event;
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer\Script;

/**
 * The Script Events.
 *
 * @author François Pluchino <francois.pluchino@opendisplay.com>
 * @author Jordi Boggiano <j.boggiano@seld.be>
 */
class ScriptEvents
{
    /**
     * The PRE_INSTALL_CMD event occurs before the install command is executed.
     *
     * The event listener method receives a Composer\Script\Event instance.
     *
     * @var string
     */
    public const PRE_INSTALL_CMD = 'pre-install-cmd';
    /**
     * The POST_INSTALL_CMD event occurs after the install command is executed.
     *
     * The event listener method receives a Composer\Script\Event instance.
     *
     * @var string
     */
    public const POST_INSTALL_CMD = 'post-install-cmd';
    /**
     * The PRE_UPDATE_CMD event occurs before the update command is executed.
     *
     * The event listener method receives a Composer\Script\Event instance.
     *
     * @var string
     */
    public const PRE_UPDATE_CMD = 'pre-update-cmd';
    /**
     * The POST_UPDATE_CMD event occurs after the update command is executed.
     *
     * The event listener method receives a Composer\Script\Event instance.
     *
     * @var string
     */
    public const POST_UPDATE_CMD = 'post-update-cmd';
    /**
     * The PRE_STATUS_CMD event occurs before the status command is executed.
     *
     * The event listener method receives a Composer\Script\Event instance.
     *
     * @var string
     */
    public const PRE_STATUS_CMD = 'pre-status-cmd';
    /**
     * The POST_STATUS_CMD event occurs after the status command is executed.
     *
     * The event listener method receives a Composer\Script\Event instance.
     *
     * @var string
     */
    public const POST_STATUS_CMD = 'post-status-cmd';
    /**
     * The PRE_AUTOLOAD_DUMP event occurs before the autoload file is generated.
     *
     * The event listener method receives a Composer\Script\Event instance.
     *
     * @var string
     */
    public const PRE_AUTOLOAD_DUMP = 'pre-autoload-dump';
    /**
     * The POST_AUTOLOAD_DUMP event occurs after the autoload file has been generated.
     *
     * The event listener method receives a Composer\Script\Event instance.
     *
     * @var string
     */
    public const POST_AUTOLOAD_DUMP = 'post-autoload-dump';
    /**
     * The POST_ROOT_PACKAGE_INSTALL event occurs after the root package has been installed.
     *
     * The event listener method receives a Composer\Script\Event instance.
     *
     * @var string
     */
    public const POST_ROOT_PACKAGE_INSTALL = 'post-root-package-install';
    /**
     * The POST_CREATE_PROJECT event occurs after the create-project command has been executed.
     * Note: Event occurs after POST_INSTALL_CMD
     *
     * The event listener method receives a Composer\Script\Event instance.
     *
     * @var string
     */
    public const POST_CREATE_PROJECT_CMD = 'post-create-project-cmd';
    /**
     * The PRE_ARCHIVE_CMD event occurs before the update command is executed.
     *
     * The event listener method receives a Composer\Script\Event instance.
     *
     * @var string
     */
    public const PRE_ARCHIVE_CMD = 'pre-archive-cmd';
    /**
     * The POST_ARCHIVE_CMD event occurs after the status command is executed.
     *
     * The event listener method receives a Composer\Script\Event instance.
     *
     * @var string
     */
    public const POST_ARCHIVE_CMD = 'post-archive-cmd';
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer\Question;

use Composer\Pcre\Preg;
use _ContaoManager\Symfony\Component\Console\Exception\InvalidArgumentException;
use _ContaoManager\Symfony\Component\Console\Question\Question;
/**
 * Represents a yes/no question
 * Enforces strict responses rather than non-standard answers counting as default
 * Based on Symfony\Component\Console\Question\ConfirmationQuestion
 *
 * @author Theo Tonge <theo@theotonge.co.uk>
 */
class StrictConfirmationQuestion extends Question
{
    /** @var non-empty-string */
    private $trueAnswerRegex;
    /** @var non-empty-string */
    private $falseAnswerRegex;
    /**
     * Constructor.s
     *
     * @param string $question         The question to ask to the user
     * @param bool   $default          The default answer to return, true or false
     * @param non-empty-string $trueAnswerRegex  A regex to match the "yes" answer
     * @param non-empty-string $falseAnswerRegex A regex to match the "no" answer
     */
    public function __construct(string $question, bool $default = \true, string $trueAnswerRegex = '/^y(?:es)?$/i', string $falseAnswerRegex = '/^no?$/i')
    {
        parent::__construct($question, $default);
        $this->trueAnswerRegex = $trueAnswerRegex;
        $this->falseAnswerRegex = $falseAnswerRegex;
        $this->setNormalizer($this->getDefaultNormalizer());
        $this->setValidator($this->getDefaultValidator());
    }
    /**
     * Returns the default answer normalizer.
     */
    private function getDefaultNormalizer(): callable
    {
        $default = $this->getDefault();
        $trueRegex = $this->trueAnswerRegex;
        $falseRegex = $this->falseAnswerRegex;
        return static function ($answer) use ($default, $trueRegex, $falseRegex) {
            if (is_bool($answer)) {
                return $answer;
            }
            if (empty($answer) && !empty($default)) {
                return $default;
            }
            if (Preg::isMatch($trueRegex, $answer)) {
                return \true;
            }
            if (Preg::isMatch($falseRegex, $answer)) {
                return \false;
            }
            return null;
        };
    }
    /**
     * Returns the default answer validator.
     */
    private function getDefaultValidator(): callable
    {
        return static function ($answer): bool {
            if (!is_bool($answer)) {
                throw new InvalidArgumentException('Please answer yes, y, no, or n.');
            }
            return $answer;
        };
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer;

use Composer\Package\Locker;
use Composer\Pcre\Preg;
use Composer\Plugin\PluginManager;
use Composer\Downloader\DownloadManager;
use Composer\Autoload\AutoloadGenerator;
use Composer\Package\Archiver\ArchiveManager;
/**
 * @author Jordi Boggiano <j.boggiano@seld.be>
 * @author Konstantin Kudryashiv <ever.zet@gmail.com>
 * @author Nils Adermann <naderman@naderman.de>
 */
class Composer extends \Composer\PartialComposer
{
    /*
     * Examples of the following constants in the various configurations they can be in
     *
     * You are probably better off using Composer::getVersion() though as that will always return something usable
     *
     * releases (phar):
     * const VERSION = '1.8.2';
     * const BRANCH_ALIAS_VERSION = '';
     * const RELEASE_DATE = '2019-01-29 15:00:53';
     * const SOURCE_VERSION = '';
     *
     * snapshot builds (phar):
     * const VERSION = 'd3873a05650e168251067d9648845c220c50e2d7';
     * const BRANCH_ALIAS_VERSION = '1.9-dev';
     * const RELEASE_DATE = '2019-02-20 07:43:56';
     * const SOURCE_VERSION = '';
     *
     * source (git clone):
     * const VERSION = '@package_version@';
     * const BRANCH_ALIAS_VERSION = '@package_branch_alias_version@';
     * const RELEASE_DATE = '@release_date@';
     * const SOURCE_VERSION = '1.8-dev+source';
     *
     * @see getVersion()
     */
    public const VERSION = '2.9.7';
    public const BRANCH_ALIAS_VERSION = '';
    public const RELEASE_DATE = '2026-04-14 13:31:52';
    public const SOURCE_VERSION = '';
    /**
     * Version number of the internal composer-runtime-api package
     *
     * This is used to version features available to projects at runtime
     * like the platform-check file, the Composer\InstalledVersions class
     * and possibly others in the future.
     *
     * @var string
     */
    public const RUNTIME_API_VERSION = '2.2.2';
    public static function getVersion(): string
    {
        // no replacement done, this must be a source checkout
        if (self::VERSION === '@package_version' . '@') {
            return self::SOURCE_VERSION;
        }
        // we have a branch alias and version is a commit id, this must be a snapshot build
        if (self::BRANCH_ALIAS_VERSION !== '' && Preg::isMatch('{^[a-f0-9]{40}$}', self::VERSION)) {
            return self::BRANCH_ALIAS_VERSION . '+' . self::VERSION;
        }
        return self::VERSION;
    }
    /**
     * @var Locker
     */
    private $locker;
    /**
     * @var DownloadManager
     */
    private $downloadManager;
    /**
     * @var PluginManager
     */
    private $pluginManager;
    /**
     * @var AutoloadGenerator
     */
    private $autoloadGenerator;
    /**
     * @var ArchiveManager
     */
    private $archiveManager;
    public function setLocker(Locker $locker): void
    {
        $this->locker = $locker;
    }
    public function getLocker(): Locker
    {
        return $this->locker;
    }
    public function setDownloadManager(DownloadManager $manager): void
    {
        $this->downloadManager = $manager;
    }
    public function getDownloadManager(): DownloadManager
    {
        return $this->downloadManager;
    }
    public function setArchiveManager(ArchiveManager $manager): void
    {
        $this->archiveManager = $manager;
    }
    public function getArchiveManager(): ArchiveManager
    {
        return $this->archiveManager;
    }
    public function setPluginManager(PluginManager $manager): void
    {
        $this->pluginManager = $manager;
    }
    public function getPluginManager(): PluginManager
    {
        return $this->pluginManager;
    }
    public function setAutoloadGenerator(AutoloadGenerator $autoloadGenerator): void
    {
        $this->autoloadGenerator = $autoloadGenerator;
    }
    public function getAutoloadGenerator(): AutoloadGenerator
    {
        return $this->autoloadGenerator;
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer\Json;

use Exception;
/**
 * @author Jordi Boggiano <j.boggiano@seld.be>
 */
class JsonValidationException extends Exception
{
    /**
     * @var string[]
     */
    protected $errors;
    /**
     * @param string[] $errors
     */
    public function __construct(string $message, array $errors = [], ?Exception $previous = null)
    {
        $this->errors = $errors;
        parent::__construct((string) $message, 0, $previous);
    }
    /**
     * @return string[]
     */
    public function getErrors(): array
    {
        return $this->errors;
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer\Json;

use Composer\Pcre\Preg;
/**
 * Formats json strings used for php < 5.4 because the json_encode doesn't
 * supports the flags JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE
 * in these versions
 *
 * @author Konstantin Kudryashiv <ever.zet@gmail.com>
 * @author Jordi Boggiano <j.boggiano@seld.be>
 *
 * @deprecated Use json_encode or JsonFile::encode() with modern JSON_* flags to configure formatting - this class will be removed in 3.0
 */
class JsonFormatter
{
    /**
     * This code is based on the function found at:
     *  http://recursive-design.com/blog/2008/03/11/format-json-with-php/
     *
     * Originally licensed under MIT by Dave Perrett <mail@recursive-design.com>
     *
     * @param  bool   $unescapeUnicode Un escape unicode
     * @param  bool   $unescapeSlashes Un escape slashes
     */
    public static function format(string $json, bool $unescapeUnicode, bool $unescapeSlashes): string
    {
        $result = '';
        $pos = 0;
        $strLen = strlen($json);
        $indentStr = '    ';
        $newLine = "\n";
        $outOfQuotes = \true;
        $buffer = '';
        $noescape = \true;
        for ($i = 0; $i < $strLen; $i++) {
            // Grab the next character in the string
            $char = substr($json, $i, 1);
            // Are we inside a quoted string?
            if ('"' === $char && $noescape) {
                $outOfQuotes = !$outOfQuotes;
            }
            if (!$outOfQuotes) {
                $buffer .= $char;
                $noescape = '\\' === $char ? !$noescape : \true;
                continue;
            }
            if ('' !== $buffer) {
                if ($unescapeSlashes) {
                    $buffer = str_replace('\/', '/', $buffer);
                }
                if ($unescapeUnicode && function_exists('mb_convert_encoding')) {
                    // https://stackoverflow.com/questions/2934563/how-to-decode-unicode-escape-sequences-like-u00ed-to-proper-utf-8-encoded-cha
                    $buffer = Preg::replaceCallback('/(\\\\+)u([0-9a-f]{4})/i', static function ($match): string {
                        $l = strlen($match[1]);
                        if ($l % 2) {
                            $code = hexdec($match[2]);
                            // 0xD800..0xDFFF denotes UTF-16 surrogate pair which won't be unescaped
                            // see https://github.com/composer/composer/issues/7510
                            if (0xd800 <= $code && 0xdfff >= $code) {
                                return $match[0];
                            }
                            return str_repeat('\\', $l - 1) . mb_convert_encoding(pack('H*', $match[2]), 'UTF-8', 'UCS-2BE');
                        }
                        return $match[0];
                    }, $buffer);
                }
                $result .= $buffer . $char;
                $buffer = '';
                continue;
            }
            if (':' === $char) {
                // Add a space after the : character
                $char .= ' ';
            } elseif ('}' === $char || ']' === $char) {
                $pos--;
                $prevChar = substr($json, $i - 1, 1);
                if ('{' !== $prevChar && '[' !== $prevChar) {
                    // If this character is the end of an element,
                    // output a new line and indent the next line
                    $result .= $newLine;
                    $result .= str_repeat($indentStr, $pos);
                } else {
                    // Collapse empty {} and []
                    $result = rtrim($result);
                }
            }
            $result .= $char;
            // If the last character was the beginning of an element,
            // output a new line and indent the next line
            if (',' === $char || '{' === $char || '[' === $char) {
                $result .= $newLine;
                if ('{' === $char || '[' === $char) {
                    $pos++;
                }
                $result .= str_repeat($indentStr, $pos);
            }
        }
        return $result;
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer\Json;

use Composer\Pcre\Preg;
use Composer\Util\Filesystem;
use _ContaoManager\JsonSchema\Validator;
use _ContaoManager\Seld\JsonLint\JsonParser;
use _ContaoManager\Seld\JsonLint\ParsingException;
use Composer\Util\HttpDownloader;
use Composer\IO\IOInterface;
use Composer\Downloader\TransportException;
/**
 * Reads/writes json files.
 *
 * @author Konstantin Kudryashiv <ever.zet@gmail.com>
 * @author Jordi Boggiano <j.boggiano@seld.be>
 */
class JsonFile
{
    public const LAX_SCHEMA = 1;
    public const STRICT_SCHEMA = 2;
    public const AUTH_SCHEMA = 3;
    public const LOCK_SCHEMA = 4;
    /** @deprecated Use \JSON_UNESCAPED_SLASHES */
    public const JSON_UNESCAPED_SLASHES = 64;
    /** @deprecated Use \JSON_PRETTY_PRINT */
    public const JSON_PRETTY_PRINT = 128;
    /** @deprecated Use \JSON_UNESCAPED_UNICODE */
    public const JSON_UNESCAPED_UNICODE = 256;
    public const COMPOSER_SCHEMA_PATH = __DIR__ . '/../../../res/composer-schema.json';
    public const LOCK_SCHEMA_PATH = __DIR__ . '/../../../res/composer-lock-schema.json';
    public const INDENT_DEFAULT = '    ';
    /** @var string */
    private $path;
    /** @var ?HttpDownloader */
    private $httpDownloader;
    /** @var ?IOInterface */
    private $io;
    /** @var string */
    private $indent = self::INDENT_DEFAULT;
    /**
     * Initializes json file reader/parser.
     *
     * @param  string                    $path           path to a lockfile
     * @param  ?HttpDownloader           $httpDownloader required for loading http/https json files
     * @throws \InvalidArgumentException
     */
    public function __construct(string $path, ?HttpDownloader $httpDownloader = null, ?IOInterface $io = null)
    {
        $this->path = $path;
        if (null === $httpDownloader && Preg::isMatch('{^https?://}i', $path)) {
            throw new \InvalidArgumentException('http urls require a HttpDownloader instance to be passed');
        }
        $this->httpDownloader = $httpDownloader;
        $this->io = $io;
    }
    public function getPath(): string
    {
        return $this->path;
    }
    /**
     * Checks whether json file exists.
     */
    public function exists(): bool
    {
        return is_file($this->path);
    }
    /**
     * Reads json file.
     *
     * @throws ParsingException
     * @throws \RuntimeException
     * @return mixed
     */
    public function read()
    {
        try {
            if ($this->httpDownloader) {
                $json = $this->httpDownloader->get($this->path)->getBody();
            } else {
                if (!Filesystem::isReadable($this->path)) {
                    throw new \RuntimeException('The file "' . $this->path . '" is not readable.');
                }
                if ($this->io && $this->io->isDebug()) {
                    $realpathInfo = '';
                    $realpath = realpath($this->path);
                    if (\false !== $realpath && $realpath !== $this->path) {
                        $realpathInfo = ' (' . $realpath . ')';
                    }
                    $this->io->writeError('Reading ' . $this->path . $realpathInfo);
                }
                $json = file_get_contents($this->path);
            }
        } catch (TransportException $e) {
            throw new \RuntimeException($e->getMessage(), 0, $e);
        } catch (\Exception $e) {
            throw new \RuntimeException('Could not read ' . $this->path . "\n\n" . $e->getMessage());
        }
        if ($json === \false) {
            throw new \RuntimeException('Could not read ' . $this->path);
        }
        $this->indent = self::detectIndenting($json);
        return static::parseJson($json, $this->path);
    }
    /**
     * Writes json file.
     *
     * @param  mixed[]                              $hash    writes hash into json file
     * @param  int                                  $options json_encode options
     * @throws \UnexpectedValueException|\Exception
     * @return void
     */
    public function write(array $hash, int $options = \JSON_UNESCAPED_SLASHES | \JSON_PRETTY_PRINT | \JSON_UNESCAPED_UNICODE)
    {
        if ($this->path === 'php://memory') {
            file_put_contents($this->path, static::encode($hash, $options, $this->indent));
            return;
        }
        $dir = dirname($this->path);
        if (!is_dir($dir)) {
            if (file_exists($dir)) {
                throw new \UnexpectedValueException(realpath($dir) . ' exists and is not a directory.');
            }
            if (!@mkdir($dir, 0777, \true)) {
                throw new \UnexpectedValueException($dir . ' does not exist and could not be created.');
            }
        }
        $retries = 3;
        while ($retries--) {
            try {
                $this->filePutContentsIfModified($this->path, static::encode($hash, $options, $this->indent) . ($options & \JSON_PRETTY_PRINT ? "\n" : ''));
                break;
            } catch (\Exception $e) {
                if ($retries > 0) {
                    usleep(500000);
                    continue;
                }
                throw $e;
            }
        }
    }
    /**
     * Modify file properties only if content modified
     *
     * @return int|false
     */
    private function filePutContentsIfModified(string $path, string $content)
    {
        $currentContent = @file_get_contents($path);
        if (\false === $currentContent || $currentContent !== $content) {
            return file_put_contents($path, $content);
        }
        return 0;
    }
    /**
     * Validates the schema of the current json file according to composer-schema.json rules
     *
     * @param  int                     $schema     a JsonFile::*_SCHEMA constant
     * @param  string|null             $schemaFile a path to the schema file
     * @throws JsonValidationException
     * @throws ParsingException
     * @return true                    true on success
     *
     * @phpstan-param self::*_SCHEMA $schema
     */
    public function validateSchema(int $schema = self::STRICT_SCHEMA, ?string $schemaFile = null): bool
    {
        if (!Filesystem::isReadable($this->path)) {
            throw new \RuntimeException('The file "' . $this->path . '" is not readable.');
        }
        $content = file_get_contents($this->path);
        $data = json_decode($content);
        if (null === $data && 'null' !== $content) {
            self::validateSyntax($content, $this->path);
        }
        return self::validateJsonSchema($this->path, $data, $schema, $schemaFile);
    }
    /**
     * Validates the schema of the current json file according to composer-schema.json rules
     *
     * @param  mixed                   $data       Decoded JSON data to validate
     * @param  int                     $schema     a JsonFile::*_SCHEMA constant
     * @param  string|null             $schemaFile a path to the schema file
     * @throws JsonValidationException
     * @return true                    true on success
     *
     * @phpstan-param self::*_SCHEMA $schema
     */
    public static function validateJsonSchema(string $source, $data, int $schema, ?string $schemaFile = null): bool
    {
        $isComposerSchemaFile = \false;
        if (null === $schemaFile) {
            if ($schema === self::LOCK_SCHEMA) {
                $schemaFile = self::LOCK_SCHEMA_PATH;
            } else {
                $isComposerSchemaFile = \true;
                $schemaFile = self::COMPOSER_SCHEMA_PATH;
            }
        }
        // Prepend with file:// only when not using a special schema already (e.g. in the phar)
        if (\false === strpos($schemaFile, '://')) {
            $schemaFile = 'file://' . $schemaFile;
        }
        $schemaData = (object) ['$ref' => $schemaFile, '$schema' => "https://json-schema.org/draft-04/schema#"];
        if ($schema === self::STRICT_SCHEMA && $isComposerSchemaFile) {
            $schemaData = json_decode((string) file_get_contents($schemaFile));
            $schemaData->additionalProperties = \false;
            $schemaData->required = ['name', 'description'];
        } elseif ($schema === self::AUTH_SCHEMA && $isComposerSchemaFile) {
            $schemaData = (object) ['$ref' => $schemaFile . '#/properties/config', '$schema' => "https://json-schema.org/draft-04/schema#"];
        }
        $validator = new Validator();
        // convert assoc arrays to objects
        $data = json_decode((string) json_encode($data));
        $validator->validate($data, $schemaData);
        if (!$validator->isValid()) {
            $errors = [];
            foreach ($validator->getErrors() as $error) {
                $errors[] = ($error['property'] ? $error['property'] . ' : ' : '') . $error['message'];
            }
            throw new \Composer\Json\JsonValidationException('"' . $source . '" does not match the expected JSON schema', $errors);
        }
        return \true;
    }
    /**
     * Encodes an array into (optionally pretty-printed) JSON
     *
     * @param  mixed  $data    Data to encode into a formatted JSON string
     * @param  int    $options json_encode options (defaults to JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE)
     * @param  string $indent  Indentation string
     * @return string Encoded json
     */
    public static function encode($data, int $options = \JSON_UNESCAPED_SLASHES | \JSON_PRETTY_PRINT | \JSON_UNESCAPED_UNICODE, string $indent = self::INDENT_DEFAULT): string
    {
        $json = json_encode($data, $options);
        if (\false === $json) {
            self::throwEncodeError(json_last_error());
        }
        if (($options & \JSON_PRETTY_PRINT) > 0 && $indent !== self::INDENT_DEFAULT) {
            // Pretty printing and not using default indentation
            return Preg::replaceCallback('#^ {4,}#m', static function ($match) use ($indent): string {
                return str_repeat($indent, (int) (strlen($match[0]) / 4));
            }, $json);
        }
        return $json;
    }
    /**
     * Throws an exception according to a given code with a customized message
     *
     * @param  int               $code return code of json_last_error function
     * @throws \RuntimeException
     * @return never
     */
    private static function throwEncodeError(int $code): void
    {
        switch ($code) {
            case \JSON_ERROR_DEPTH:
                $msg = 'Maximum stack depth exceeded';
                break;
            case \JSON_ERROR_STATE_MISMATCH:
                $msg = 'Underflow or the modes mismatch';
                break;
            case \JSON_ERROR_CTRL_CHAR:
                $msg = 'Unexpected control character found';
                break;
            case \JSON_ERROR_UTF8:
                $msg = 'Malformed UTF-8 characters, possibly incorrectly encoded';
                break;
            default:
                $msg = 'Unknown error';
        }
        throw new \RuntimeException('JSON encoding failed: ' . $msg);
    }
    /**
     * Parses json string and returns hash.
     *
     * @param null|string $json json string
     * @param string $file the json file
     *
     * @throws ParsingException
     * @return mixed
     */
    public static function parseJson(?string $json, ?string $file = null)
    {
        if (null === $json) {
            return null;
        }
        $data = json_decode($json, \true);
        if (null === $data && \JSON_ERROR_NONE !== json_last_error()) {
            // attempt resolving simple conflicts in lock files so that one can run `composer update --lock` and get a valid lock file
            if ($file !== null && str_ends_with($file, '.lock') && str_contains($json, '"content-hash"')) {
                $replaced = Preg::replace('{\r?\n<<<<<<< [^\r\n]+\r?\n\s+"content-hash": *"[0-9a-f]+", *\r?\n(?:\|{7} [^\r\n]+\r?\n\s+"content-hash": *"[0-9a-f]+", *\r?\n)?=======\r?\n\s+"content-hash": *"[0-9a-f]+", *\r?\n>>>>>>> [^\r\n]+(\r?\n)}', '    "content-hash": "VCS merge conflict detected. Please run `composer update --lock`.",$1', $json, 1, $count);
                if ($count === 1) {
                    $data = json_decode($replaced, \true);
                    if ($data !== null) {
                        return $data;
                    }
                }
            }
            self::validateSyntax($json, $file);
        }
        return $data;
    }
    /**
     * Validates the syntax of a JSON string
     *
     * @throws \UnexpectedValueException
     * @throws ParsingException
     * @return bool                      true on success
     */
    protected static function validateSyntax(string $json, ?string $file = null): bool
    {
        $parser = new JsonParser();
        $result = $parser->lint($json);
        if (null === $result) {
            if (defined('JSON_ERROR_UTF8') && \JSON_ERROR_UTF8 === json_last_error()) {
                if ($file === null) {
                    throw new \UnexpectedValueException('The input is not UTF-8, could not parse as JSON');
                } else {
                    throw new \UnexpectedValueException('"' . $file . '" is not UTF-8, could not parse as JSON');
                }
            }
            return \true;
        }
        if ($file === null) {
            throw new ParsingException('The input does not contain valid JSON' . "\n" . $result->getMessage(), $result->getDetails());
        } else {
            throw new ParsingException('"' . $file . '" does not contain valid JSON' . "\n" . $result->getMessage(), $result->getDetails());
        }
    }
    public static function detectIndenting(?string $json): string
    {
        if (Preg::isMatchStrictGroups('#^([ \t]+)"#m', $json ?? '', $match)) {
            return $match[1];
        }
        return self::INDENT_DEFAULT;
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer\Json;

use Composer\Pcre\Preg;
use Composer\Repository\PlatformRepository;
/**
 * @author Jordi Boggiano <j.boggiano@seld.be>
 */
class JsonManipulator
{
    /** @var string */
    private const DEFINES = '(?(DEFINE)
       (?<number>    -? (?= [1-9]|0(?!\d) ) \d++ (?:\.\d++)? (?:[eE] [+-]?+ \d++)? )
       (?<boolean>   true | false | null )
       (?<string>    " (?:[^"\\\\]*+ | \\\\ ["\\\\bfnrt\/] | \\\\ u [0-9A-Fa-f]{4} )* " )
       (?<array>     \[  (?:  (?&json) \s*+ (?: , (?&json) \s*+ )*+  )?+  \s*+ \] )
       (?<pair>      \s*+ (?&string) \s*+ : (?&json) \s*+ )
       (?<object>    \{  (?:  (?&pair)  (?: , (?&pair)  )*+  )?+  \s*+ \} )
       (?<json>      \s*+ (?: (?&number) | (?&boolean) | (?&string) | (?&array) | (?&object) ) )
    )';
    /** @var string */
    private $contents;
    /** @var string */
    private $newline;
    /** @var string */
    private $indent;
    public function __construct(string $contents)
    {
        $contents = trim($contents);
        if ($contents === '') {
            $contents = '{}';
        }
        if (!Preg::isMatch('#^\{(.*)\}$#s', $contents)) {
            throw new \InvalidArgumentException('The json file must be an object ({})');
        }
        $this->newline = \false !== strpos($contents, "\r\n") ? "\r\n" : "\n";
        $this->contents = $contents === '{}' ? '{' . $this->newline . '}' : $contents;
        $this->detectIndenting();
    }
    public function getContents(): string
    {
        return $this->contents . $this->newline;
    }
    public function addLink(string $type, string $package, string $constraint, bool $sortPackages = \false): bool
    {
        $decoded = \Composer\Json\JsonFile::parseJson($this->contents);
        // no link of that type yet
        if (!isset($decoded[$type])) {
            return $this->addMainKey($type, [$package => $constraint]);
        }
        $regex = '{' . self::DEFINES . '^(?P<start>\s*\{\s*(?:(?&string)\s*:\s*(?&json)\s*,\s*)*?)' . '(?P<property>' . preg_quote(\Composer\Json\JsonFile::encode($type)) . '\s*:\s*)(?P<value>(?&json))(?P<end>.*)}sx';
        if (!Preg::isMatch($regex, $this->contents, $matches)) {
            return \false;
        }
        assert(is_string($matches['start']));
        assert(is_string($matches['value']));
        assert(is_string($matches['end']));
        $links = $matches['value'];
        // try to find existing link
        $packageRegex = str_replace('/', '\\\\?/', preg_quote($package));
        $regex = '{' . self::DEFINES . '"(?P<package>' . $packageRegex . ')"(\s*:\s*)(?&string)}ix';
        if (Preg::isMatch($regex, $links, $packageMatches)) {
            assert(is_string($packageMatches['package']));
            // update existing link
            $existingPackage = $packageMatches['package'];
            $packageRegex = str_replace('/', '\\\\?/', preg_quote($existingPackage));
            $links = Preg::replaceCallback('{' . self::DEFINES . '"' . $packageRegex . '"(?P<separator>\s*:\s*)(?&string)}ix', static function ($m) use ($existingPackage, $constraint): string {
                return \Composer\Json\JsonFile::encode(str_replace('\/', '/', $existingPackage)) . $m['separator'] . '"' . $constraint . '"';
            }, $links);
        } else if (Preg::isMatchStrictGroups('#^\s*\{\s*\S+.*?(\s*\}\s*)$#s', $links, $match)) {
            // link missing but non empty links
            $links = Preg::replace(
                '{' . preg_quote($match[1]) . '$}',
                // addcslashes is used to double up backslashes/$ since preg_replace resolves them as back references otherwise, see #1588
                addcslashes(',' . $this->newline . $this->indent . $this->indent . \Composer\Json\JsonFile::encode($package) . ': ' . \Composer\Json\JsonFile::encode($constraint) . $match[1], '\$'),
                $links
            );
        } else {
            // links empty
            $links = '{' . $this->newline . $this->indent . $this->indent . \Composer\Json\JsonFile::encode($package) . ': ' . \Composer\Json\JsonFile::encode($constraint) . $this->newline . $this->indent . '}';
        }
        if (\true === $sortPackages) {
            $requirements = json_decode($links, \true);
            $this->sortPackages($requirements);
            $links = $this->format($requirements);
        }
        $this->contents = $matches['start'] . $matches['property'] . $links . $matches['end'];
        return \true;
    }
    /**
     * Sorts packages by importance (platform packages first, then PHP dependencies) and alphabetically.
     *
     * @link https://getcomposer.org/doc/02-libraries.md#platform-packages
     *
     * @param array<string> $packages
     */
    private function sortPackages(array &$packages = []): void
    {
        $prefix = static function ($requirement): string {
            if (PlatformRepository::isPlatformPackage($requirement)) {
                return Preg::replace(['/^php/', '/^hhvm/', '/^ext/', '/^lib/', '/^\D/'], ['0-$0', '1-$0', '2-$0', '3-$0', '4-$0'], $requirement);
            }
            return '5-' . $requirement;
        };
        uksort($packages, static function ($a, $b) use ($prefix): int {
            return strnatcmp($prefix($a), $prefix($b));
        });
    }
    /**
     * @param array<string, mixed>|false $config
     */
    public function addRepository(string $name, $config, bool $append = \true): bool
    {
        if ("" !== $name && !$this->doRemoveRepository($name)) {
            return \false;
        }
        if (!$this->doConvertRepositoriesFromAssocToList()) {
            return \false;
        }
        if (is_array($config) && !is_numeric($name) && '' !== $name) {
            $config = ['name' => $name] + $config;
        } elseif ($config === \false) {
            $config = [$name => $config];
        }
        return $this->addListItem('repositories', $config, $append);
    }
    private function doConvertRepositoriesFromAssocToList(): bool
    {
        $decoded = json_decode($this->contents, \false);
        if (($decoded->repositories ?? null) instanceof \stdClass) {
            // delete from bottom to top, to ensure keys stay the same
            $entriesToRevert = array_reverse(array_keys((array) $decoded->repositories));
            foreach ($entriesToRevert as $entryKey) {
                if (!$this->removeSubNode('repositories', (string) $entryKey)) {
                    return \false;
                }
            }
            $this->changeEmptyMainKeyFromAssocToList('repositories');
            // re-add in order
            foreach ((array) $decoded->repositories as $repositoryName => $repository) {
                if (!$repository instanceof \stdClass) {
                    if (!$this->addListItem('repositories', [$repositoryName => $repository], \true)) {
                        return \false;
                    }
                } elseif (is_numeric($repositoryName)) {
                    if (!$this->addListItem('repositories', $repository, \true)) {
                        return \false;
                    }
                } else {
                    $repository = (array) $repository;
                    // prepend name property
                    $repository = ['name' => $repositoryName] + $repository;
                    if (!$this->addListItem('repositories', $repository, \true)) {
                        return \false;
                    }
                }
            }
        }
        return \true;
    }
    public function setRepositoryUrl(string $name, string $url): bool
    {
        $decoded = \Composer\Json\JsonFile::parseJson($this->contents);
        $repositoryIndex = null;
        foreach ($decoded['repositories'] ?? [] as $index => $repository) {
            if ($name === $index) {
                $repositoryIndex = $index;
                break;
            }
            if ($name === ($repository['name'] ?? null)) {
                $repositoryIndex = $index;
                break;
            }
        }
        if (null === $repositoryIndex) {
            return \false;
        }
        $listRegex = null;
        if (is_int($repositoryIndex)) {
            $listRegex = '{' . self::DEFINES . '^(?P<start>\s*\{\s*(?:(?&string)\s*:\s*(?&json)\s*,\s*)*?"repositories"\s*:\s*\[\s*((?&json)\s*+,\s*+){' . max(0, $repositoryIndex) . '})(?P<repository>(?&object))(?P<end>.*)}sx';
        }
        $objectRegex = '{' . self::DEFINES . '^(?P<start>\s*\{\s*(?:(?&string)\s*:\s*(?&json)\s*,\s*)*?"repositories"\s*:\s*\{\s*(?:(?&string)\s*:\s*(?&json)\s*,\s*)*?' . preg_quote(\Composer\Json\JsonFile::encode($repositoryIndex)) . '\s*:\s*)(?P<repository>(?&object))(?P<end>.*)}sx';
        $matches = null;
        if ($listRegex !== null && Preg::isMatch($listRegex, $this->contents, $matches) || Preg::isMatch($objectRegex, $this->contents, $matches)) {
            assert(isset($matches['start']) && is_string($matches['start']));
            assert(isset($matches['repository']) && is_string($matches['repository']));
            assert(isset($matches['end']) && is_string($matches['end']));
            // invalid match due to un-regexable content, abort
            if (\false === @json_decode($matches['repository'])) {
                return \false;
            }
            $repositoryRegex = '{' . self::DEFINES . '^(?P<start>\s*\{\s*(?:(?&string)\s*:\s*(?&json)\s*,\s*)*?"url"\s*:\s*)(?P<url>(?&string))(?P<end>.*)}sx';
            $this->contents = $matches['start'] . Preg::replaceCallback($repositoryRegex, static function (array $repositoryMatches) use ($url): string {
                return $repositoryMatches['start'] . \Composer\Json\JsonFile::encode($url) . $repositoryMatches['end'];
            }, $matches['repository']) . $matches['end'];
            return \true;
        }
        return \false;
    }
    /**
     * @param array<string, mixed>|false $config
     */
    public function insertRepository(string $name, $config, string $referenceName, int $offset = 0): bool
    {
        if ("" !== $name && !$this->doRemoveRepository($name)) {
            return \false;
        }
        if (!$this->doConvertRepositoriesFromAssocToList()) {
            return \false;
        }
        $indexToInsert = null;
        $decoded = \Composer\Json\JsonFile::parseJson($this->contents);
        foreach ($decoded['repositories'] as $repositoryIndex => $repository) {
            if (($repository['name'] ?? null) === $referenceName) {
                $indexToInsert = $repositoryIndex;
                break;
            }
            if ($repositoryIndex === $referenceName) {
                $indexToInsert = $repositoryIndex;
                break;
            }
            if ([$referenceName => \false] === $repository) {
                $indexToInsert = $repositoryIndex;
                break;
            }
        }
        if ($indexToInsert === null) {
            return \false;
        }
        if (is_array($config) && !is_numeric($name) && '' !== $name) {
            $config = ['name' => $name] + $config;
        } elseif ($config === \false) {
            $config = ['name' => $config];
        }
        return $this->insertListItem('repositories', $config, $indexToInsert + $offset);
    }
    public function removeRepository(string $name): bool
    {
        return $this->doRemoveRepository($name) && $this->removeMainKeyIfEmpty('repositories');
    }
    private function doRemoveRepository(string $name): bool
    {
        $decoded = json_decode($this->contents, \false);
        $isAssoc = ($decoded->repositories ?? null) instanceof \stdClass;
        foreach ((array) ($decoded->repositories ?? []) as $repositoryIndex => $repository) {
            if ($repositoryIndex === $name && $isAssoc) {
                if (!$this->removeSubNode('repositories', $repositoryIndex)) {
                    return \false;
                }
                break;
            }
            if (($repository->name ?? null) === $name) {
                if ($isAssoc) {
                    if (!$this->removeSubNode('repositories', (string) $repositoryIndex)) {
                        return \false;
                    }
                } else if (!$this->removeListItem('repositories', (int) $repositoryIndex)) {
                    return \false;
                }
                break;
            }
            if ($isAssoc) {
                if ($name === $repositoryIndex && \false === $repository) {
                    if (!$this->removeSubNode('repositories', $repositoryIndex)) {
                        return \false;
                    }
                    return \true;
                }
            } else {
                $repositoryAsArray = (array) $repository;
                if (\false === ($repositoryAsArray[$name] ?? null) && 1 === count($repositoryAsArray)) {
                    if (!$this->removeListItem('repositories', (int) $repositoryIndex)) {
                        return \false;
                    }
                    return \true;
                }
            }
        }
        return \true;
    }
    /**
     * @param mixed  $value
     */
    public function addConfigSetting(string $name, $value): bool
    {
        return $this->addSubNode('config', $name, $value);
    }
    public function removeConfigSetting(string $name): bool
    {
        return $this->removeSubNode('config', $name);
    }
    /**
     * @param mixed $value
     */
    public function addProperty(string $name, $value): bool
    {
        if (strpos($name, 'suggest.') === 0) {
            return $this->addSubNode('suggest', substr($name, 8), $value);
        }
        if (strpos($name, 'extra.') === 0) {
            return $this->addSubNode('extra', substr($name, 6), $value);
        }
        if (strpos($name, 'scripts.') === 0) {
            return $this->addSubNode('scripts', substr($name, 8), $value);
        }
        return $this->addMainKey($name, $value);
    }
    public function removeProperty(string $name): bool
    {
        if (strpos($name, 'suggest.') === 0) {
            return $this->removeSubNode('suggest', substr($name, 8));
        }
        if (strpos($name, 'extra.') === 0) {
            return $this->removeSubNode('extra', substr($name, 6));
        }
        if (strpos($name, 'scripts.') === 0) {
            return $this->removeSubNode('scripts', substr($name, 8));
        }
        if (strpos($name, 'autoload.') === 0) {
            return $this->removeSubNode('autoload', substr($name, 9));
        }
        if (strpos($name, 'autoload-dev.') === 0) {
            return $this->removeSubNode('autoload-dev', substr($name, 13));
        }
        return $this->removeMainKey($name);
    }
    /**
     * @param mixed  $value
     */
    public function addSubNode(string $mainNode, string $name, $value, bool $append = \true): bool
    {
        $decoded = \Composer\Json\JsonFile::parseJson($this->contents);
        $subName = null;
        if (in_array($mainNode, ['config', 'extra', 'scripts']) && \false !== strpos($name, '.')) {
            [$name, $subName] = explode('.', $name, 2);
        }
        // no main node yet
        if (!isset($decoded[$mainNode])) {
            if ($subName !== null) {
                $this->addMainKey($mainNode, [$name => [$subName => $value]]);
            } else {
                $this->addMainKey($mainNode, [$name => $value]);
            }
            return \true;
        }
        // main node content not match-able
        $nodeRegex = '{' . self::DEFINES . '^(?P<start> \s* \{ \s* (?: (?&string) \s* : (?&json) \s* , \s* )*?' . preg_quote(\Composer\Json\JsonFile::encode($mainNode)) . '\s*:\s*)(?P<content>(?&object))(?P<end>.*)}sx';
        try {
            if (!Preg::isMatch($nodeRegex, $this->contents, $match)) {
                return \false;
            }
        } catch (\RuntimeException $e) {
            if ($e->getCode() === \PREG_BACKTRACK_LIMIT_ERROR) {
                return \false;
            }
            throw $e;
        }
        assert(is_string($match['start']));
        assert(is_string($match['content']));
        assert(is_string($match['end']));
        $children = $match['content'];
        // invalid match due to un-regexable content, abort
        if (!@json_decode($children)) {
            return \false;
        }
        // child exists
        $childRegex = '{' . self::DEFINES . '(?P<start>"' . preg_quote($name) . '"\s*:\s*)(?P<content>(?&json))(?P<end>,?)}x';
        if (Preg::isMatch($childRegex, $children, $matches)) {
            $children = Preg::replaceCallback($childRegex, function ($matches) use ($subName, $value): string {
                if ($subName !== null && is_string($matches['content'])) {
                    $curVal = json_decode($matches['content'], \true);
                    if (!is_array($curVal)) {
                        $curVal = [];
                    }
                    $curVal[$subName] = $value;
                    $value = $curVal;
                }
                return $matches['start'] . $this->format($value, 1) . $matches['end'];
            }, $children);
        } elseif (Preg::isMatch('#^\{(?P<leadingspace>\s*?)(?P<content>\S+.*?)?(?P<trailingspace>\s*)\}$#s', $children, $match)) {
            $whitespace = $match['trailingspace'];
            if (null !== $match['content']) {
                if ($subName !== null) {
                    $value = [$subName => $value];
                }
                // child missing but non empty children
                if ($append) {
                    $children = Preg::replace('#' . $whitespace . '}$#', addcslashes(',' . $this->newline . $this->indent . $this->indent . \Composer\Json\JsonFile::encode($name) . ': ' . $this->format($value, 1) . $whitespace . '}', '\$'), $children);
                } else {
                    $whitespace = $match['leadingspace'];
                    $children = Preg::replace('#^{' . $whitespace . '#', addcslashes('{' . $whitespace . \Composer\Json\JsonFile::encode($name) . ': ' . $this->format($value, 1) . ',' . $this->newline . $this->indent . $this->indent, '\$'), $children);
                }
            } else {
                if ($subName !== null) {
                    $value = [$subName => $value];
                }
                // children present but empty
                $children = '{' . $this->newline . $this->indent . $this->indent . \Composer\Json\JsonFile::encode($name) . ': ' . $this->format($value, 1) . $whitespace . '}';
            }
        } else {
            throw new \LogicException('Nothing matched above for: ' . $children);
        }
        $this->contents = Preg::replaceCallback($nodeRegex, static function ($m) use ($children): string {
            return $m['start'] . $children . $m['end'];
        }, $this->contents);
        return \true;
    }
    public function removeSubNode(string $mainNode, string $name): bool
    {
        $decoded = \Composer\Json\JsonFile::parseJson($this->contents);
        // no node or empty node
        if (empty($decoded[$mainNode])) {
            return \true;
        }
        // no node content match-able
        $nodeRegex = '{' . self::DEFINES . '^(?P<start> \s* \{ \s* (?: (?&string) \s* : (?&json) \s* , \s* )*?' . preg_quote(\Composer\Json\JsonFile::encode($mainNode)) . '\s*:\s*)(?P<content>(?&object))(?P<end>.*)}sx';
        try {
            if (!Preg::isMatch($nodeRegex, $this->contents, $match)) {
                return \false;
            }
        } catch (\RuntimeException $e) {
            if ($e->getCode() === \PREG_BACKTRACK_LIMIT_ERROR) {
                return \false;
            }
            throw $e;
        }
        assert(is_string($match['start']));
        assert(is_string($match['content']));
        assert(is_string($match['end']));
        $children = $match['content'];
        // invalid match due to un-regexable content, abort
        if (!@json_decode($children, \true)) {
            return \false;
        }
        $subName = null;
        if (in_array($mainNode, ['config', 'extra', 'scripts']) && \false !== strpos($name, '.')) {
            [$name, $subName] = explode('.', $name, 2);
        }
        // no node to remove
        if (!isset($decoded[$mainNode][$name]) || $subName && !isset($decoded[$mainNode][$name][$subName])) {
            return \true;
        }
        // try and find a match for the subkey
        $keyRegex = str_replace('/', '\\\\?/', preg_quote($name));
        if (Preg::isMatch('{"' . $keyRegex . '"\s*:}i', $children)) {
            // find best match for the value of "name"
            if (Preg::isMatchAll('{' . self::DEFINES . '"' . $keyRegex . '"\s*:\s*(?:(?&json))}x', $children, $matches)) {
                $bestMatch = '';
                foreach ($matches[0] as $match) {
                    assert(is_string($match));
                    if (strlen($bestMatch) < strlen($match)) {
                        $bestMatch = $match;
                    }
                }
                $childrenClean = Preg::replace('{,\s*' . preg_quote($bestMatch) . '}i', '', $children, -1, $count);
                if (1 !== $count) {
                    $childrenClean = Preg::replace('{' . preg_quote($bestMatch) . '\s*,?\s*}i', '', $childrenClean, -1, $count);
                    if (1 !== $count) {
                        return \false;
                    }
                }
            }
        } else {
            $childrenClean = $children;
        }
        if (!isset($childrenClean)) {
            throw new \InvalidArgumentException("JsonManipulator: \$childrenClean is not defined. Please report at https://github.com/composer/composer/issues/new.");
        }
        // no child data left, $name was the only key in
        unset($match);
        if (Preg::isMatch('#^\{\s*?(?P<content>\S+.*?)?(?P<trailingspace>\s*)\}$#s', $childrenClean, $match)) {
            if (null === $match['content']) {
                $newline = $this->newline;
                $indent = $this->indent;
                $this->contents = Preg::replaceCallback($nodeRegex, static function ($matches) use ($indent, $newline): string {
                    return $matches['start'] . '{' . $newline . $indent . '}' . $matches['end'];
                }, $this->contents);
                // we have a subname, so we restore the rest of $name
                if ($subName !== null) {
                    $curVal = json_decode($children, \true);
                    unset($curVal[$name][$subName]);
                    if ($curVal[$name] === []) {
                        $curVal[$name] = new \ArrayObject();
                    }
                    $this->addSubNode($mainNode, $name, $curVal[$name]);
                }
                return \true;
            }
        }
        $this->contents = Preg::replaceCallback($nodeRegex, function ($matches) use ($name, $subName, $childrenClean): string {
            assert(is_string($matches['content']));
            if ($subName !== null) {
                $curVal = json_decode($matches['content'], \true);
                unset($curVal[$name][$subName]);
                if ($curVal[$name] === []) {
                    $curVal[$name] = new \ArrayObject();
                }
                $childrenClean = $this->format($curVal, 0, \true);
            }
            return $matches['start'] . $childrenClean . $matches['end'];
        }, $this->contents);
        return \true;
    }
    /**
     * @param mixed $value
     */
    public function addListItem(string $mainNode, $value, bool $append = \true): bool
    {
        $decoded = \Composer\Json\JsonFile::parseJson($this->contents);
        // no main node yet
        if (!isset($decoded[$mainNode])) {
            if (!$this->addMainKey($mainNode, [])) {
                return \false;
            }
        }
        // main node content not match-able
        $nodeRegex = '{' . self::DEFINES . '^(?P<start> \s* \{ \s* (?: (?&string) \s* : (?&json) \s* , \s* )*?' . preg_quote(\Composer\Json\JsonFile::encode($mainNode)) . '\s*:\s*)(?P<content>(?&array))(?P<end>.*)}sx';
        try {
            if (!Preg::isMatch($nodeRegex, $this->contents, $match)) {
                return \false;
            }
        } catch (\RuntimeException $e) {
            if ($e->getCode() === \PREG_BACKTRACK_LIMIT_ERROR) {
                return \false;
            }
            throw $e;
        }
        assert(is_string($match['start']));
        assert(is_string($match['content']));
        assert(is_string($match['end']));
        $children = $match['content'];
        // invalid match due to un-regexable content, abort
        if (\false === @json_decode($children)) {
            return \false;
        }
        if (Preg::isMatch('#^\[(?P<leadingspace>\s*?)(?P<content>\S+.*?)?(?P<trailingspace>\s*)\]$#s', $children, $match)) {
            $leadingWhitespace = $match['leadingspace'];
            $whitespace = $match['trailingspace'];
            $leadingItemWhitespace = $this->newline . $this->indent . $this->indent;
            $trailingItemWhitespace = $whitespace;
            $itemDepth = 1;
            // keep oneline lists as one line
            if (!str_contains($whitespace, $this->newline)) {
                $leadingItemWhitespace = $leadingWhitespace;
                $trailingItemWhitespace = $leadingWhitespace;
                $itemDepth = 0;
            }
            if (null !== $match['content']) {
                // child missing but non empty children
                if ($append) {
                    $children = Preg::replace('#' . $whitespace . ']$#', addcslashes(',' . $leadingItemWhitespace . $this->format($value, $itemDepth) . $trailingItemWhitespace . ']', '\$'), $children);
                } else {
                    $whitespace = $match['leadingspace'];
                    $children = Preg::replace('#^\[' . $whitespace . '#', addcslashes('[' . $whitespace . $this->format($value, $itemDepth) . ',' . $leadingItemWhitespace, '\$'), $children);
                }
            } else {
                // children present but empty
                $children = '[' . $leadingItemWhitespace . $this->format($value, $itemDepth) . $trailingItemWhitespace . ']';
            }
        } else {
            throw new \LogicException('Nothing matched above for: ' . $children);
        }
        $this->contents = Preg::replaceCallback($nodeRegex, static function ($m) use ($children): string {
            return $m['start'] . $children . $m['end'];
        }, $this->contents);
        return \true;
    }
    /**
     * @param mixed $value
     */
    public function insertListItem(string $mainNode, $value, int $index): bool
    {
        if ($index < 0) {
            throw new \InvalidArgumentException('Index can only be positive integer');
        }
        if ($index === 0) {
            return $this->addListItem($mainNode, $value, \false);
        }
        $decoded = \Composer\Json\JsonFile::parseJson($this->contents);
        // no main node yet
        if (!isset($decoded[$mainNode])) {
            if (!$this->addMainKey($mainNode, [])) {
                return \false;
            }
        }
        if (count($decoded[$mainNode]) === $index) {
            return $this->addListItem($mainNode, $value, \true);
        }
        // main node content not match-able
        $nodeRegex = '{' . self::DEFINES . '^(?P<start> \s* \{ \s* (?: (?&string) \s* : (?&json) \s* , \s* )*?' . preg_quote(\Composer\Json\JsonFile::encode($mainNode)) . '\s*:\s*)(?P<content>(?&array))(?P<end>.*)}sx';
        try {
            if (!Preg::isMatch($nodeRegex, $this->contents, $match)) {
                return \false;
            }
        } catch (\RuntimeException $e) {
            if ($e->getCode() === \PREG_BACKTRACK_LIMIT_ERROR) {
                return \false;
            }
            throw $e;
        }
        assert(is_string($match['start']));
        assert(is_string($match['content']));
        assert(is_string($match['end']));
        $children = $match['content'];
        // invalid match due to un-regexable content, abort
        if (\false === @json_decode($children)) {
            return \false;
        }
        $listSkipToItemRegex = '{' . self::DEFINES . '^(?P<start>\[\s*((?&json)\s*+,\s*?){' . max(0, $index) . '})(?P<space_before_item>(\s*))(?P<end>.*)}sx';
        $children = Preg::replaceCallback($listSkipToItemRegex, function ($m) use ($value): string {
            return $m['start'] . $m['space_before_item'] . $this->format($value, 1) . ',' . $m['space_before_item'] . $m['end'];
        }, $children);
        $this->contents = Preg::replaceCallback($nodeRegex, static function ($m) use ($children): string {
            return $m['start'] . $children . $m['end'];
        }, $this->contents);
        return \true;
    }
    public function removeListItem(string $mainNode, int $nodeIndex): bool
    {
        // invalid index, that cannot be removed anyway
        if ($nodeIndex < 0) {
            return \true;
        }
        $decoded = \Composer\Json\JsonFile::parseJson($this->contents);
        // no node or empty node
        if ([] === $decoded[$mainNode]) {
            return \true;
        }
        // no node content match-able
        $nodeRegex = '{' . self::DEFINES . '^(?P<start> \s* \{ \s* (?: (?&string) \s* : (?&json) \s* , \s* )*?' . preg_quote(\Composer\Json\JsonFile::encode($mainNode)) . '\s*:\s*)(?P<content>(?&array))(?P<end>.*)}sx';
        try {
            if (!Preg::isMatch($nodeRegex, $this->contents, $match)) {
                return \false;
            }
        } catch (\RuntimeException $e) {
            if ($e->getCode() === \PREG_BACKTRACK_LIMIT_ERROR) {
                return \false;
            }
            throw $e;
        }
        assert(is_string($match['start']));
        assert(is_string($match['content']));
        assert(is_string($match['end']));
        $children = $match['content'];
        // invalid match due to un-regexable content, abort
        if (\false === @json_decode($children, \true)) {
            return \false;
        }
        // no node to remove
        if (!isset($decoded[$mainNode][$nodeIndex])) {
            return \true;
        }
        $contentRegex = '(?&json)';
        if ($nodeIndex > 1) {
            $startRegex = '(?&json)\s*+(?:,(?&json)\s*+){' . ($nodeIndex - 1) . '}';
            // remove leading array separator in case we might remove the last
            $contentRegex = '\s*+,?\s*+' . $contentRegex;
            $endRegex = '(?:(\s*+,\s*+(?&json))*(?:\s*+(?&json))?)\s*+';
        } elseif ($nodeIndex > 0) {
            $startRegex = '(?&json)\s*+';
            // remove leading array separator in case we might remove the last
            $contentRegex = '\s*+,?\s*+' . $contentRegex;
            $endRegex = '(?:(\s*+,\s*+(?&json))*(?:\s*+(?&json))?)\s*+';
        } else {
            $startRegex = '\s*+';
            // remove trailing array separator when we delete first
            $contentRegex = $contentRegex . '\s*+,?\s*+';
            $endRegex = '(?:((?&json)\s*+,\s*+)*(?:\s*+(?&json))?)\s*+';
        }
        if (Preg::isMatch('{' . self::DEFINES . '(?P<start>\[' . $startRegex . ')(?P<content>' . $contentRegex . ')(?P<end>' . $endRegex . '\])}sx', $children, $childMatch)) {
            $this->contents = $match['start'] . $childMatch['start'] . $childMatch['end'] . $match['end'];
            return \true;
        }
        return \false;
    }
    /**
     * @param mixed  $content
     */
    public function addMainKey(string $key, $content): bool
    {
        $decoded = \Composer\Json\JsonFile::parseJson($this->contents);
        $content = $this->format($content);
        // key exists already
        $regex = '{' . self::DEFINES . '^(?P<start>\s*\{\s*(?:(?&string)\s*:\s*(?&json)\s*,\s*)*?)' . '(?P<key>' . preg_quote(\Composer\Json\JsonFile::encode($key)) . '\s*:\s*(?&json))(?P<end>.*)}sx';
        if (isset($decoded[$key]) && Preg::isMatch($regex, $this->contents, $matches)) {
            // invalid match due to un-regexable content, abort
            if (!@json_decode('{' . $matches['key'] . '}')) {
                return \false;
            }
            $this->contents = $matches['start'] . \Composer\Json\JsonFile::encode($key) . ': ' . $content . $matches['end'];
            return \true;
        }
        // append at the end of the file and keep whitespace
        if (Preg::isMatch('#[^{\s](\s*)\}$#', $this->contents, $match)) {
            $this->contents = Preg::replace('#' . $match[1] . '\}$#', addcslashes(',' . $this->newline . $this->indent . \Composer\Json\JsonFile::encode($key) . ': ' . $content . $this->newline . '}', '\$'), $this->contents);
            return \true;
        }
        // append at the end of the file
        $this->contents = Preg::replace('#\}$#', addcslashes($this->indent . \Composer\Json\JsonFile::encode($key) . ': ' . $content . $this->newline . '}', '\$'), $this->contents);
        return \true;
    }
    public function removeMainKey(string $key): bool
    {
        $decoded = \Composer\Json\JsonFile::parseJson($this->contents);
        if (!array_key_exists($key, $decoded)) {
            return \true;
        }
        // key exists already
        $regex = '{' . self::DEFINES . '^(?P<start>\s*\{\s*(?:(?&string)\s*:\s*(?&json)\s*,\s*)*?)' . '(?P<removal>' . preg_quote(\Composer\Json\JsonFile::encode($key)) . '\s*:\s*(?&json))\s*,?\s*(?P<end>.*)}sx';
        if (Preg::isMatch($regex, $this->contents, $matches)) {
            assert(is_string($matches['start']));
            assert(is_string($matches['removal']));
            assert(is_string($matches['end']));
            // invalid match due to un-regexable content, abort
            if (!@json_decode('{' . $matches['removal'] . '}')) {
                return \false;
            }
            // check that we are not leaving a dangling comma on the previous line if the last line was removed
            if (Preg::isMatchStrictGroups('#,\s*$#', $matches['start']) && Preg::isMatch('#^\}$#', $matches['end'])) {
                $matches['start'] = rtrim(Preg::replace('#,(\s*)$#', '$1', $matches['start']), $this->indent);
            }
            $this->contents = $matches['start'] . $matches['end'];
            if (Preg::isMatch('#^\{\s*\}\s*$#', $this->contents)) {
                $this->contents = "{\n}";
            }
            return \true;
        }
        return \false;
    }
    public function changeEmptyMainKeyFromAssocToList(string $key): bool
    {
        $decoded = \Composer\Json\JsonFile::parseJson($this->contents);
        if (!array_key_exists($key, $decoded)) {
            return \true;
        }
        $regex = '{' . self::DEFINES . '^(?P<start>\s*\{\s*(?:(?&string)\s*:\s*(?&json)\s*,\s*)*?' . preg_quote(\Composer\Json\JsonFile::encode($key)) . '\s*:\s*)(?P<removal>\{(?P<removal_space>\s*+)\})(?P<end>\s*,?\s*.*)}sx';
        if (Preg::isMatch($regex, $this->contents, $matches)) {
            assert(is_string($matches['start']));
            assert(is_string($matches['removal']));
            assert(is_string($matches['end']));
            // invalid match due to un-regexable content, abort
            if (\false === @json_decode($matches['removal'])) {
                return \false;
            }
            $this->contents = $matches['start'] . '[' . $matches['removal_space'] . ']' . $matches['end'];
            return \true;
        }
        return \false;
    }
    public function removeMainKeyIfEmpty(string $key): bool
    {
        $decoded = \Composer\Json\JsonFile::parseJson($this->contents);
        if (!array_key_exists($key, $decoded)) {
            return \true;
        }
        if (is_array($decoded[$key]) && count($decoded[$key]) === 0) {
            return $this->removeMainKey($key);
        }
        return \true;
    }
    /**
     * @param mixed $data
     */
    public function format($data, int $depth = 0, bool $wasObject = \false): string
    {
        if ($data instanceof \stdClass || $data instanceof \ArrayObject) {
            $data = (array) $data;
            $wasObject = \true;
        }
        if (is_array($data)) {
            if (\count($data) === 0) {
                return $wasObject ? '{' . $this->newline . str_repeat($this->indent, $depth + 1) . '}' : '[]';
            }
            if (array_is_list($data)) {
                foreach ($data as $key => $val) {
                    $data[$key] = $this->format($val, $depth + 1);
                }
                return '[' . implode(', ', $data) . ']';
            }
            $out = '{' . $this->newline;
            $elems = [];
            foreach ($data as $key => $val) {
                $elems[] = str_repeat($this->indent, $depth + 2) . \Composer\Json\JsonFile::encode((string) $key) . ': ' . $this->format($val, $depth + 1);
            }
            return $out . implode(',' . $this->newline, $elems) . $this->newline . str_repeat($this->indent, $depth + 1) . '}';
        }
        return \Composer\Json\JsonFile::encode($data);
    }
    protected function detectIndenting(): void
    {
        $this->indent = \Composer\Json\JsonFile::detectIndenting($this->contents);
    }
}
<?php

/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer;

use Composer\Autoload\ClassLoader;
use Composer\Semver\VersionParser;
/**
 * This class is copied in every Composer installed project and available to all
 *
 * See also https://getcomposer.org/doc/07-runtime.md#installed-versions
 *
 * To require its presence, you can require `composer-runtime-api ^2.0`
 *
 * @final
 */
class InstalledVersions
{
    /**
     * @var string|null if set (by reflection by Composer), this should be set to the path where this class is being copied to
     * @internal
     */
    private static $selfDir = null;
    /**
     * @var mixed[]|null
     * @psalm-var array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>}|array{}|null
     */
    private static $installed;
    /**
     * @var bool
     */
    private static $installedIsLocalDir;
    /**
     * @var bool|null
     */
    private static $canGetVendors;
    /**
     * @var array[]
     * @psalm-var array<string, array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>}>
     */
    private static $installedByVendor = array();
    /**
     * Returns a list of all package names which are present, either by being installed, replaced or provided
     *
     * @return string[]
     * @psalm-return list<string>
     */
    public static function getInstalledPackages()
    {
        $packages = array();
        foreach (self::getInstalled() as $installed) {
            $packages[] = array_keys($installed['versions']);
        }
        if (1 === \count($packages)) {
            return $packages[0];
        }
        return array_keys(array_flip(\call_user_func_array('array_merge', $packages)));
    }
    /**
     * Returns a list of all package names with a specific type e.g. 'library'
     *
     * @param  string   $type
     * @return string[]
     * @psalm-return list<string>
     */
    public static function getInstalledPackagesByType($type)
    {
        $packagesByType = array();
        foreach (self::getInstalled() as $installed) {
            foreach ($installed['versions'] as $name => $package) {
                if (isset($package['type']) && $package['type'] === $type) {
                    $packagesByType[] = $name;
                }
            }
        }
        return $packagesByType;
    }
    /**
     * Checks whether the given package is installed
     *
     * This also returns true if the package name is provided or replaced by another package
     *
     * @param  string $packageName
     * @param  bool   $includeDevRequirements
     * @return bool
     */
    public static function isInstalled($packageName, $includeDevRequirements = \true)
    {
        foreach (self::getInstalled() as $installed) {
            if (isset($installed['versions'][$packageName])) {
                return $includeDevRequirements || !isset($installed['versions'][$packageName]['dev_requirement']) || $installed['versions'][$packageName]['dev_requirement'] === \false;
            }
        }
        return \false;
    }
    /**
     * Checks whether the given package satisfies a version constraint
     *
     * e.g. If you want to know whether version 2.3+ of package foo/bar is installed, you would call:
     *
     *   Composer\InstalledVersions::satisfies(new VersionParser, 'foo/bar', '^2.3')
     *
     * @param  VersionParser $parser      Install composer/semver to have access to this class and functionality
     * @param  string        $packageName
     * @param  string|null   $constraint  A version constraint to check for, if you pass one you have to make sure composer/semver is required by your package
     * @return bool
     */
    public static function satisfies(VersionParser $parser, $packageName, $constraint)
    {
        $constraint = $parser->parseConstraints((string) $constraint);
        $provided = $parser->parseConstraints(self::getVersionRanges($packageName));
        return $provided->matches($constraint);
    }
    /**
     * Returns a version constraint representing all the range(s) which are installed for a given package
     *
     * It is easier to use this via isInstalled() with the $constraint argument if you need to check
     * whether a given version of a package is installed, and not just whether it exists
     *
     * @param  string $packageName
     * @return string Version constraint usable with composer/semver
     */
    public static function getVersionRanges($packageName)
    {
        foreach (self::getInstalled() as $installed) {
            if (!isset($installed['versions'][$packageName])) {
                continue;
            }
            $ranges = array();
            if (isset($installed['versions'][$packageName]['pretty_version'])) {
                $ranges[] = $installed['versions'][$packageName]['pretty_version'];
            }
            if (array_key_exists('aliases', $installed['versions'][$packageName])) {
                $ranges = array_merge($ranges, $installed['versions'][$packageName]['aliases']);
            }
            if (array_key_exists('replaced', $installed['versions'][$packageName])) {
                $ranges = array_merge($ranges, $installed['versions'][$packageName]['replaced']);
            }
            if (array_key_exists('provided', $installed['versions'][$packageName])) {
                $ranges = array_merge($ranges, $installed['versions'][$packageName]['provided']);
            }
            return implode(' || ', $ranges);
        }
        throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
    }
    /**
     * @param  string      $packageName
     * @return string|null If the package is being replaced or provided but is not really installed, null will be returned as version, use satisfies or getVersionRanges if you need to know if a given version is present
     */
    public static function getVersion($packageName)
    {
        foreach (self::getInstalled() as $installed) {
            if (!isset($installed['versions'][$packageName])) {
                continue;
            }
            if (!isset($installed['versions'][$packageName]['version'])) {
                return null;
            }
            return $installed['versions'][$packageName]['version'];
        }
        throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
    }
    /**
     * @param  string      $packageName
     * @return string|null If the package is being replaced or provided but is not really installed, null will be returned as version, use satisfies or getVersionRanges if you need to know if a given version is present
     */
    public static function getPrettyVersion($packageName)
    {
        foreach (self::getInstalled() as $installed) {
            if (!isset($installed['versions'][$packageName])) {
                continue;
            }
            if (!isset($installed['versions'][$packageName]['pretty_version'])) {
                return null;
            }
            return $installed['versions'][$packageName]['pretty_version'];
        }
        throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
    }
    /**
     * @param  string      $packageName
     * @return string|null If the package is being replaced or provided but is not really installed, null will be returned as reference
     */
    public static function getReference($packageName)
    {
        foreach (self::getInstalled() as $installed) {
            if (!isset($installed['versions'][$packageName])) {
                continue;
            }
            if (!isset($installed['versions'][$packageName]['reference'])) {
                return null;
            }
            return $installed['versions'][$packageName]['reference'];
        }
        throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
    }
    /**
     * @param  string      $packageName
     * @return string|null If the package is being replaced or provided but is not really installed, null will be returned as install path. Packages of type metapackages also have a null install path.
     */
    public static function getInstallPath($packageName)
    {
        foreach (self::getInstalled() as $installed) {
            if (!isset($installed['versions'][$packageName])) {
                continue;
            }
            return isset($installed['versions'][$packageName]['install_path']) ? $installed['versions'][$packageName]['install_path'] : null;
        }
        throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
    }
    /**
     * @return array
     * @psalm-return array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}
     */
    public static function getRootPackage()
    {
        $installed = self::getInstalled();
        return $installed[0]['root'];
    }
    /**
     * Returns the raw installed.php data for custom implementations
     *
     * @deprecated Use getAllRawData() instead which returns all datasets for all autoloaders present in the process. getRawData only returns the first dataset loaded, which may not be what you expect.
     * @return array[]
     * @psalm-return array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>}
     */
    public static function getRawData()
    {
        @trigger_error('getRawData only returns the first dataset loaded, which may not be what you expect. Use getAllRawData() instead which returns all datasets for all autoloaders present in the process.', \E_USER_DEPRECATED);
        if (null === self::$installed) {
            // only require the installed.php file if this file is loaded from its dumped location,
            // and not from its source location in the composer/composer package, see https://github.com/composer/composer/issues/9937
            if (substr(__DIR__, -8, 1) !== 'C') {
                self::$installed = include __DIR__ . '/installed.php';
            } else {
                self::$installed = array();
            }
        }
        return self::$installed;
    }
    /**
     * Returns the raw data of all installed.php which are currently loaded for custom implementations
     *
     * @return array[]
     * @psalm-return list<array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>}>
     */
    public static function getAllRawData()
    {
        return self::getInstalled();
    }
    /**
     * Lets you reload the static array from another file
     *
     * This is only useful for complex integrations in which a project needs to use
     * this class but then also needs to execute another project's autoloader in process,
     * and wants to ensure both projects have access to their version of installed.php.
     *
     * A typical case would be PHPUnit, where it would need to make sure it reads all
     * the data it needs from this class, then call reload() with
     * `require $CWD/vendor/composer/installed.php` (or similar) as input to make sure
     * the project in which it runs can then also use this class safely, without
     * interference between PHPUnit's dependencies and the project's dependencies.
     *
     * @param  array[] $data A vendor/composer/installed.php data set
     * @return void
     *
     * @psalm-param array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>} $data
     */
    public static function reload($data)
    {
        self::$installed = $data;
        self::$installedByVendor = array();
        // when using reload, we disable the duplicate protection to ensure that self::$installed data is
        // always returned, but we cannot know whether it comes from the installed.php in __DIR__ or not,
        // so we have to assume it does not, and that may result in duplicate data being returned when listing
        // all installed packages for example
        self::$installedIsLocalDir = \false;
    }
    /**
     * @return string
     */
    private static function getSelfDir()
    {
        if (self::$selfDir === null) {
            self::$selfDir = strtr(__DIR__, '\\', '/');
        }
        return self::$selfDir;
    }
    /**
     * @return array[]
     * @psalm-return list<array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>}>
     */
    private static function getInstalled()
    {
        if (null === self::$canGetVendors) {
            self::$canGetVendors = method_exists('Composer\Autoload\ClassLoader', 'getRegisteredLoaders');
        }
        $installed = array();
        $copiedLocalDir = \false;
        if (self::$canGetVendors) {
            $selfDir = self::getSelfDir();
            foreach (ClassLoader::getRegisteredLoaders() as $vendorDir => $loader) {
                $vendorDir = strtr($vendorDir, '\\', '/');
                if (isset(self::$installedByVendor[$vendorDir])) {
                    $installed[] = self::$installedByVendor[$vendorDir];
                } elseif (is_file($vendorDir . '/composer/installed.php')) {
                    /** @var array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>} $required */
                    $required = require $vendorDir . '/composer/installed.php';
                    self::$installedByVendor[$vendorDir] = $required;
                    $installed[] = $required;
                    if (self::$installed === null && $vendorDir . '/composer' === $selfDir) {
                        self::$installed = $required;
                        self::$installedIsLocalDir = \true;
                    }
                }
                if (self::$installedIsLocalDir && $vendorDir . '/composer' === $selfDir) {
                    $copiedLocalDir = \true;
                }
            }
        }
        if (null === self::$installed) {
            // only require the installed.php file if this file is loaded from its dumped location,
            // and not from its source location in the composer/composer package, see https://github.com/composer/composer/issues/9937
            if (substr(__DIR__, -8, 1) !== 'C') {
                /** @var array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>} $required */
                $required = require __DIR__ . '/installed.php';
                self::$installed = $required;
            } else {
                self::$installed = array();
            }
        }
        if (self::$installed !== array() && !$copiedLocalDir) {
            $installed[] = self::$installed;
        }
        return $installed;
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer\DependencyResolver\Operation;

use Composer\Package\PackageInterface;
/**
 * Solver install operation.
 *
 * @author Konstantin Kudryashov <ever.zet@gmail.com>
 */
class InstallOperation extends \Composer\DependencyResolver\Operation\SolverOperation implements \Composer\DependencyResolver\Operation\OperationInterface
{
    protected const TYPE = 'install';
    /**
     * @var PackageInterface
     */
    protected $package;
    public function __construct(PackageInterface $package)
    {
        $this->package = $package;
    }
    /**
     * Returns package instance.
     */
    public function getPackage(): PackageInterface
    {
        return $this->package;
    }
    /**
     * @inheritDoc
     */
    public function show($lock): string
    {
        return self::format($this->package, $lock);
    }
    public static function format(PackageInterface $package, bool $lock = \false): string
    {
        return ($lock ? 'Locking ' : 'Installing ') . '<info>' . $package->getPrettyName() . '</info> (<comment>' . $package->getFullPrettyVersion() . '</comment>)';
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer\DependencyResolver\Operation;

use Composer\Package\AliasPackage;
/**
 * Solver install operation.
 *
 * @author Nils Adermann <naderman@naderman.de>
 */
class MarkAliasInstalledOperation extends \Composer\DependencyResolver\Operation\SolverOperation implements \Composer\DependencyResolver\Operation\OperationInterface
{
    protected const TYPE = 'markAliasInstalled';
    /**
     * @var AliasPackage
     */
    protected $package;
    public function __construct(AliasPackage $package)
    {
        $this->package = $package;
    }
    /**
     * Returns package instance.
     */
    public function getPackage(): AliasPackage
    {
        return $this->package;
    }
    /**
     * @inheritDoc
     */
    public function show($lock): string
    {
        return 'Marking <info>' . $this->package->getPrettyName() . '</info> (<comment>' . $this->package->getFullPrettyVersion() . '</comment>) as installed, alias of <info>' . $this->package->getAliasOf()->getPrettyName() . '</info> (<comment>' . $this->package->getAliasOf()->getFullPrettyVersion() . '</comment>)';
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer\DependencyResolver\Operation;

/**
 * Solver operation interface.
 *
 * @author Konstantin Kudryashov <ever.zet@gmail.com>
 */
interface OperationInterface
{
    /**
     * Returns operation type.
     *
     * @return string
     */
    public function getOperationType();
    /**
     * Serializes the operation in a human readable format
     *
     * @param  bool   $lock Whether this is an operation on the lock file
     * @return string
     */
    public function show(bool $lock);
    /**
     * Serializes the operation in a human readable format
     *
     * @return string
     */
    public function __toString();
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer\DependencyResolver\Operation;

use Composer\Package\PackageInterface;
use Composer\Package\Version\VersionParser;
/**
 * Solver update operation.
 *
 * @author Konstantin Kudryashov <ever.zet@gmail.com>
 */
class UpdateOperation extends \Composer\DependencyResolver\Operation\SolverOperation implements \Composer\DependencyResolver\Operation\OperationInterface
{
    protected const TYPE = 'update';
    /**
     * @var PackageInterface
     */
    protected $initialPackage;
    /**
     * @var PackageInterface
     */
    protected $targetPackage;
    /**
     * @param PackageInterface $initial initial package
     * @param PackageInterface $target  target package (updated)
     */
    public function __construct(PackageInterface $initial, PackageInterface $target)
    {
        $this->initialPackage = $initial;
        $this->targetPackage = $target;
    }
    /**
     * Returns initial package.
     */
    public function getInitialPackage(): PackageInterface
    {
        return $this->initialPackage;
    }
    /**
     * Returns target package.
     */
    public function getTargetPackage(): PackageInterface
    {
        return $this->targetPackage;
    }
    /**
     * @inheritDoc
     */
    public function show($lock): string
    {
        return self::format($this->initialPackage, $this->targetPackage, $lock);
    }
    public static function format(PackageInterface $initialPackage, PackageInterface $targetPackage, bool $lock = \false): string
    {
        $fromVersion = $initialPackage->getFullPrettyVersion();
        $toVersion = $targetPackage->getFullPrettyVersion();
        if ($fromVersion === $toVersion && $initialPackage->getSourceReference() !== $targetPackage->getSourceReference()) {
            $fromVersion = $initialPackage->getFullPrettyVersion(\true, PackageInterface::DISPLAY_SOURCE_REF);
            $toVersion = $targetPackage->getFullPrettyVersion(\true, PackageInterface::DISPLAY_SOURCE_REF);
        } elseif ($fromVersion === $toVersion && $initialPackage->getDistReference() !== $targetPackage->getDistReference()) {
            $fromVersion = $initialPackage->getFullPrettyVersion(\true, PackageInterface::DISPLAY_DIST_REF);
            $toVersion = $targetPackage->getFullPrettyVersion(\true, PackageInterface::DISPLAY_DIST_REF);
        }
        $actionName = VersionParser::isUpgrade($initialPackage->getVersion(), $targetPackage->getVersion()) ? 'Upgrading' : 'Downgrading';
        return $actionName . ' <info>' . $initialPackage->getPrettyName() . '</info> (<comment>' . $fromVersion . '</comment> => <comment>' . $toVersion . '</comment>)';
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer\DependencyResolver\Operation;

/**
 * Abstract operation class.
 *
 * @author Aleksandr Bezpiatov <aleksandr.bezpiatov@spryker.com>
 */
abstract class SolverOperation implements \Composer\DependencyResolver\Operation\OperationInterface
{
    /**
     * @abstract must be redefined by extending classes
     */
    protected const TYPE = '';
    /**
     * Returns operation type.
     */
    public function getOperationType(): string
    {
        return static::TYPE;
    }
    /**
     * @inheritDoc
     */
    public function __toString()
    {
        return $this->show(\false);
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer\DependencyResolver\Operation;

use Composer\Package\PackageInterface;
/**
 * Solver uninstall operation.
 *
 * @author Konstantin Kudryashov <ever.zet@gmail.com>
 */
class UninstallOperation extends \Composer\DependencyResolver\Operation\SolverOperation implements \Composer\DependencyResolver\Operation\OperationInterface
{
    protected const TYPE = 'uninstall';
    /**
     * @var PackageInterface
     */
    protected $package;
    public function __construct(PackageInterface $package)
    {
        $this->package = $package;
    }
    /**
     * Returns package instance.
     */
    public function getPackage(): PackageInterface
    {
        return $this->package;
    }
    /**
     * @inheritDoc
     */
    public function show($lock): string
    {
        return self::format($this->package, $lock);
    }
    public static function format(PackageInterface $package, bool $lock = \false): string
    {
        return 'Removing <info>' . $package->getPrettyName() . '</info> (<comment>' . $package->getFullPrettyVersion() . '</comment>)';
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer\DependencyResolver\Operation;

use Composer\Package\AliasPackage;
/**
 * Solver install operation.
 *
 * @author Nils Adermann <naderman@naderman.de>
 */
class MarkAliasUninstalledOperation extends \Composer\DependencyResolver\Operation\SolverOperation implements \Composer\DependencyResolver\Operation\OperationInterface
{
    protected const TYPE = 'markAliasUninstalled';
    /**
     * @var AliasPackage
     */
    protected $package;
    public function __construct(AliasPackage $package)
    {
        $this->package = $package;
    }
    /**
     * Returns package instance.
     */
    public function getPackage(): AliasPackage
    {
        return $this->package;
    }
    /**
     * @inheritDoc
     */
    public function show($lock): string
    {
        return 'Marking <info>' . $this->package->getPrettyName() . '</info> (<comment>' . $this->package->getFullPrettyVersion() . '</comment>) as uninstalled, alias of <info>' . $this->package->getAliasOf()->getPrettyName() . '</info> (<comment>' . $this->package->getAliasOf()->getFullPrettyVersion() . '</comment>)';
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer\DependencyResolver;

use Composer\Package\AliasPackage;
use Composer\Package\CompletePackageInterface;
use Composer\Package\Link;
use Composer\Package\PackageInterface;
use Composer\Repository\PlatformRepository;
use Composer\DependencyResolver\Operation\OperationInterface;
/**
 * @author Nils Adermann <naderman@naderman.de>
 * @internal
 */
class Transaction
{
    /**
     * @var OperationInterface[]
     */
    protected $operations;
    /**
     * Packages present at the beginning of the transaction
     * @var PackageInterface[]
     */
    protected $presentPackages;
    /**
     * Package set resulting from this transaction
     * @var array<string, PackageInterface>
     */
    protected $resultPackageMap;
    /**
     * @var array<string, PackageInterface[]>
     */
    protected $resultPackagesByName = [];
    /**
     * @param PackageInterface[] $presentPackages
     * @param PackageInterface[] $resultPackages
     */
    public function __construct(array $presentPackages, array $resultPackages)
    {
        $this->presentPackages = $presentPackages;
        $this->setResultPackageMaps($resultPackages);
        $this->operations = $this->calculateOperations();
    }
    /**
     * @return OperationInterface[]
     */
    public function getOperations(): array
    {
        return $this->operations;
    }
    /**
     * @param PackageInterface[] $resultPackages
     */
    private function setResultPackageMaps(array $resultPackages): void
    {
        $packageSort = static function (PackageInterface $a, PackageInterface $b): int {
            // sort alias packages by the same name behind their non alias version
            if ($a->getName() === $b->getName()) {
                if ($a instanceof AliasPackage !== $b instanceof AliasPackage) {
                    return $a instanceof AliasPackage ? -1 : 1;
                }
                // if names are the same, compare version, e.g. to sort aliases reliably, actual order does not matter
                return strcmp($b->getVersion(), $a->getVersion());
            }
            return strcmp($b->getName(), $a->getName());
        };
        $this->resultPackageMap = [];
        foreach ($resultPackages as $package) {
            $this->resultPackageMap[spl_object_hash($package)] = $package;
            foreach ($package->getNames() as $name) {
                $this->resultPackagesByName[$name][] = $package;
            }
        }
        uasort($this->resultPackageMap, $packageSort);
        foreach ($this->resultPackagesByName as $name => $packages) {
            uasort($this->resultPackagesByName[$name], $packageSort);
        }
    }
    /**
     * @return OperationInterface[]
     */
    protected function calculateOperations(): array
    {
        $operations = [];
        $presentPackageMap = [];
        $removeMap = [];
        $presentAliasMap = [];
        $removeAliasMap = [];
        foreach ($this->presentPackages as $package) {
            if ($package instanceof AliasPackage) {
                $presentAliasMap[$package->getName() . '::' . $package->getVersion()] = $package;
                $removeAliasMap[$package->getName() . '::' . $package->getVersion()] = $package;
            } else {
                $presentPackageMap[$package->getName()] = $package;
                $removeMap[$package->getName()] = $package;
            }
        }
        $stack = $this->getRootPackages();
        $visited = [];
        $processed = [];
        while (\count($stack) > 0) {
            $package = array_pop($stack);
            if (isset($processed[spl_object_hash($package)])) {
                continue;
            }
            if (!isset($visited[spl_object_hash($package)])) {
                $visited[spl_object_hash($package)] = \true;
                $stack[] = $package;
                if ($package instanceof AliasPackage) {
                    $stack[] = $package->getAliasOf();
                } else {
                    foreach ($package->getRequires() as $link) {
                        $possibleRequires = $this->getProvidersInResult($link);
                        foreach ($possibleRequires as $require) {
                            $stack[] = $require;
                        }
                    }
                }
            } elseif (!isset($processed[spl_object_hash($package)])) {
                $processed[spl_object_hash($package)] = \true;
                if ($package instanceof AliasPackage) {
                    $aliasKey = $package->getName() . '::' . $package->getVersion();
                    if (isset($presentAliasMap[$aliasKey])) {
                        unset($removeAliasMap[$aliasKey]);
                    } else {
                        $operations[] = new \Composer\DependencyResolver\Operation\MarkAliasInstalledOperation($package);
                    }
                } else if (isset($presentPackageMap[$package->getName()])) {
                    $source = $presentPackageMap[$package->getName()];
                    // do we need to update?
                    // TODO different for lock?
                    if ($package->getVersion() !== $presentPackageMap[$package->getName()]->getVersion() || $package->getDistReference() !== $presentPackageMap[$package->getName()]->getDistReference() || $package->getSourceReference() !== $presentPackageMap[$package->getName()]->getSourceReference() || $package instanceof CompletePackageInterface && $presentPackageMap[$package->getName()] instanceof CompletePackageInterface && ($package->isAbandoned() !== $presentPackageMap[$package->getName()]->isAbandoned() || $package->getReplacementPackage() !== $presentPackageMap[$package->getName()]->getReplacementPackage())) {
                        $operations[] = new \Composer\DependencyResolver\Operation\UpdateOperation($source, $package);
                    }
                    unset($removeMap[$package->getName()]);
                } else {
                    $operations[] = new \Composer\DependencyResolver\Operation\InstallOperation($package);
                    unset($removeMap[$package->getName()]);
                }
            }
        }
        foreach ($removeMap as $name => $package) {
            array_unshift($operations, new \Composer\DependencyResolver\Operation\UninstallOperation($package));
        }
        foreach ($removeAliasMap as $nameVersion => $package) {
            $operations[] = new \Composer\DependencyResolver\Operation\MarkAliasUninstalledOperation($package);
        }
        $operations = $this->movePluginsToFront($operations);
        // TODO fix this:
        // we have to do this again here even though the above stack code did it because moving plugins moves them before uninstalls
        $operations = $this->moveUninstallsToFront($operations);
        // TODO skip updates which don't update? is this needed? we shouldn't schedule this update in the first place?
        /*
                if ('update' === $opType) {
                    $targetPackage = $operation->getTargetPackage();
                    if ($targetPackage->isDev()) {
                        $initialPackage = $operation->getInitialPackage();
                        if ($targetPackage->getVersion() === $initialPackage->getVersion()
                            && (!$targetPackage->getSourceReference() || $targetPackage->getSourceReference() === $initialPackage->getSourceReference())
                            && (!$targetPackage->getDistReference() || $targetPackage->getDistReference() === $initialPackage->getDistReference())
                        ) {
                            $this->io->writeError('  - Skipping update of ' . $targetPackage->getPrettyName() . ' to the same reference-locked version', true, IOInterface::DEBUG);
                            $this->io->writeError('', true, IOInterface::DEBUG);
        
                            continue;
                        }
                    }
                }*/
        return $this->operations = $operations;
    }
    /**
     * Determine which packages in the result are not required by any other packages in it.
     *
     * These serve as a starting point to enumerate packages in a topological order despite potential cycles.
     * If there are packages with a cycle on the top level the package with the lowest name gets picked
     *
     * @return array<string, PackageInterface>
     */
    protected function getRootPackages(): array
    {
        $roots = $this->resultPackageMap;
        foreach ($this->resultPackageMap as $packageHash => $package) {
            if (!isset($roots[$packageHash])) {
                continue;
            }
            foreach ($package->getRequires() as $link) {
                $possibleRequires = $this->getProvidersInResult($link);
                foreach ($possibleRequires as $require) {
                    if ($require !== $package) {
                        unset($roots[spl_object_hash($require)]);
                    }
                }
            }
        }
        return $roots;
    }
    /**
     * @return PackageInterface[]
     */
    protected function getProvidersInResult(Link $link): array
    {
        if (!isset($this->resultPackagesByName[$link->getTarget()])) {
            return [];
        }
        return $this->resultPackagesByName[$link->getTarget()];
    }
    /**
     * Workaround: if your packages depend on plugins, we must be sure
     * that those are installed / updated first; else it would lead to packages
     * being installed multiple times in different folders, when running Composer
     * twice.
     *
     * While this does not fix the root-causes of https://github.com/composer/composer/issues/1147,
     * it at least fixes the symptoms and makes usage of composer possible (again)
     * in such scenarios.
     *
     * @param  OperationInterface[] $operations
     * @return OperationInterface[] reordered operation list
     */
    private function movePluginsToFront(array $operations): array
    {
        $dlModifyingPluginsNoDeps = [];
        $dlModifyingPluginsWithDeps = [];
        $dlModifyingPluginRequires = [];
        $pluginsNoDeps = [];
        $pluginsWithDeps = [];
        $pluginRequires = [];
        foreach (array_reverse($operations, \true) as $idx => $op) {
            if ($op instanceof \Composer\DependencyResolver\Operation\InstallOperation) {
                $package = $op->getPackage();
            } elseif ($op instanceof \Composer\DependencyResolver\Operation\UpdateOperation) {
                $package = $op->getTargetPackage();
            } else {
                continue;
            }
            $extra = $package->getExtra();
            $isDownloadsModifyingPlugin = $package->getType() === 'composer-plugin' && isset($extra['plugin-modifies-downloads']) && $extra['plugin-modifies-downloads'] === \true;
            // is this a downloads modifying plugin or a dependency of one?
            if ($isDownloadsModifyingPlugin || \count(array_intersect($package->getNames(), $dlModifyingPluginRequires)) > 0) {
                // get the package's requires, but filter out any platform requirements
                $requires = array_filter(array_keys($package->getRequires()), static function ($req): bool {
                    return !PlatformRepository::isPlatformPackage($req);
                });
                // is this a plugin with no meaningful dependencies?
                if ($isDownloadsModifyingPlugin && 0 === \count($requires)) {
                    // plugins with no dependencies go to the very front
                    array_unshift($dlModifyingPluginsNoDeps, $op);
                } else {
                    // capture the requirements for this package so those packages will be moved up as well
                    $dlModifyingPluginRequires = array_merge($dlModifyingPluginRequires, $requires);
                    // move the operation to the front
                    array_unshift($dlModifyingPluginsWithDeps, $op);
                }
                unset($operations[$idx]);
                continue;
            }
            // is this package a plugin?
            $isPlugin = $package->getType() === 'composer-plugin' || $package->getType() === 'composer-installer';
            // is this a plugin or a dependency of a plugin?
            if ($isPlugin || \count(array_intersect($package->getNames(), $pluginRequires)) > 0) {
                // get the package's requires, but filter out any platform requirements
                $requires = array_filter(array_keys($package->getRequires()), static function ($req): bool {
                    return !PlatformRepository::isPlatformPackage($req);
                });
                // is this a plugin with no meaningful dependencies?
                if ($isPlugin && 0 === \count($requires)) {
                    // plugins with no dependencies go to the very front
                    array_unshift($pluginsNoDeps, $op);
                } else {
                    // capture the requirements for this package so those packages will be moved up as well
                    $pluginRequires = array_merge($pluginRequires, $requires);
                    // move the operation to the front
                    array_unshift($pluginsWithDeps, $op);
                }
                unset($operations[$idx]);
            }
        }
        return array_merge($dlModifyingPluginsNoDeps, $dlModifyingPluginsWithDeps, $pluginsNoDeps, $pluginsWithDeps, $operations);
    }
    /**
     * Removals of packages should be executed before installations in
     * case two packages resolve to the same path (due to custom installers)
     *
     * @param  OperationInterface[] $operations
     * @return OperationInterface[] reordered operation list
     */
    private function moveUninstallsToFront(array $operations): array
    {
        $uninstOps = [];
        foreach ($operations as $idx => $op) {
            if ($op instanceof \Composer\DependencyResolver\Operation\UninstallOperation || $op instanceof \Composer\DependencyResolver\Operation\MarkAliasUninstalledOperation) {
                $uninstOps[] = $op;
                unset($operations[$idx]);
            }
        }
        return array_merge($uninstOps, $operations);
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer\DependencyResolver;

use Composer\Package\PackageInterface;
use Composer\Semver\Constraint\Constraint;
/**
 * @author Nils Adermann <naderman@naderman.de>
 */
interface PolicyInterface
{
    /**
     * @phpstan-param Constraint::STR_OP_* $operator
     */
    public function versionCompare(PackageInterface $a, PackageInterface $b, string $operator): bool;
    /**
     * @param  non-empty-list<int>   $literals
     * @return non-empty-list<int>
     */
    public function selectPreferredPackages(\Composer\DependencyResolver\Pool $pool, array $literals, ?string $requiredPackage = null): array;
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer\DependencyResolver;

use Composer\Repository\InstalledRepositoryInterface;
use Composer\Repository\RepositoryInterface;
/**
 * @author Nils Adermann <naderman@naderman.de>
 * @internal
 */
class LocalRepoTransaction extends \Composer\DependencyResolver\Transaction
{
    public function __construct(RepositoryInterface $lockedRepository, InstalledRepositoryInterface $localRepository)
    {
        parent::__construct($localRepository->getPackages(), $lockedRepository->getPackages());
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer\DependencyResolver;

/**
 * The RuleWatchGraph efficiently propagates decisions to other rules
 *
 * All rules generated for solving a SAT problem should be inserted into the
 * graph. When a decision on a literal is made, the graph can be used to
 * propagate the decision to all other rules involving the literal, leading to
 * other trivial decisions resulting from unit clauses.
 *
 * @author Nils Adermann <naderman@naderman.de>
 */
class RuleWatchGraph
{
    /** @var array<int, RuleWatchChain> */
    protected $watchChains = [];
    /**
     * Inserts a rule node into the appropriate chains within the graph
     *
     * The node is prepended to the watch chains for each of the two literals it
     * watches.
     *
     * Assertions are skipped because they only depend on a single package and
     * have no alternative literal that could be true, so there is no need to
     * watch changes in any literals.
     *
     * @param RuleWatchNode $node The rule node to be inserted into the graph
     */
    public function insert(\Composer\DependencyResolver\RuleWatchNode $node): void
    {
        if ($node->getRule()->isAssertion()) {
            return;
        }
        if (!$node->getRule() instanceof \Composer\DependencyResolver\MultiConflictRule) {
            foreach ([$node->watch1, $node->watch2] as $literal) {
                if (!isset($this->watchChains[$literal])) {
                    $this->watchChains[$literal] = new \Composer\DependencyResolver\RuleWatchChain();
                }
                $this->watchChains[$literal]->unshift($node);
            }
        } else {
            foreach ($node->getRule()->getLiterals() as $literal) {
                if (!isset($this->watchChains[$literal])) {
                    $this->watchChains[$literal] = new \Composer\DependencyResolver\RuleWatchChain();
                }
                $this->watchChains[$literal]->unshift($node);
            }
        }
    }
    /**
     * Propagates a decision on a literal to all rules watching the literal
     *
     * If a decision, e.g. +A has been made, then all rules containing -A, e.g.
     * (-A|+B|+C) now need to satisfy at least one of the other literals, so
     * that the rule as a whole becomes true, since with +A applied the rule
     * is now (false|+B|+C) so essentially (+B|+C).
     *
     * This means that all rules watching the literal -A need to be updated to
     * watch 2 other literals which can still be satisfied instead. So literals
     * that conflict with previously made decisions are not an option.
     *
     * Alternatively it can occur that a unit clause results: e.g. if in the
     * above example the rule was (-A|+B), then A turning true means that
     * B must now be decided true as well.
     *
     * @param  int       $decidedLiteral The literal which was decided (A in our example)
     * @param  int       $level          The level at which the decision took place and at which
     *                                   all resulting decisions should be made.
     * @param  Decisions $decisions      Used to check previous decisions and to
     *                                   register decisions resulting from propagation
     * @return Rule|null If a conflict is found the conflicting rule is returned
     */
    public function propagateLiteral(int $decidedLiteral, int $level, \Composer\DependencyResolver\Decisions $decisions): ?\Composer\DependencyResolver\Rule
    {
        // we invert the decided literal here, example:
        // A was decided => (-A|B) now requires B to be true, so we look for
        // rules which are fulfilled by -A, rather than A.
        $literal = -$decidedLiteral;
        if (!isset($this->watchChains[$literal])) {
            return null;
        }
        $chain = $this->watchChains[$literal];
        $chain->rewind();
        while ($chain->valid()) {
            $node = $chain->current();
            if (!$node->getRule() instanceof \Composer\DependencyResolver\MultiConflictRule) {
                $otherWatch = $node->getOtherWatch($literal);
                if (!$node->getRule()->isDisabled() && !$decisions->satisfy($otherWatch)) {
                    $ruleLiterals = $node->getRule()->getLiterals();
                    $alternativeLiterals = array_filter($ruleLiterals, static function ($ruleLiteral) use ($literal, $otherWatch, $decisions): bool {
                        return $literal !== $ruleLiteral && $otherWatch !== $ruleLiteral && !$decisions->conflict($ruleLiteral);
                    });
                    if (\count($alternativeLiterals) > 0) {
                        reset($alternativeLiterals);
                        $this->moveWatch($literal, current($alternativeLiterals), $node);
                        continue;
                    }
                    if ($decisions->conflict($otherWatch)) {
                        return $node->getRule();
                    }
                    $decisions->decide($otherWatch, $level, $node->getRule());
                }
            } else {
                foreach ($node->getRule()->getLiterals() as $otherLiteral) {
                    if ($literal !== $otherLiteral && !$decisions->satisfy($otherLiteral)) {
                        if ($decisions->conflict($otherLiteral)) {
                            return $node->getRule();
                        }
                        $decisions->decide($otherLiteral, $level, $node->getRule());
                    }
                }
            }
            $chain->next();
        }
        return null;
    }
    /**
     * Moves a rule node from one watch chain to another
     *
     * The rule node's watched literals are updated accordingly.
     *
     * @param int           $fromLiteral A literal the node used to watch
     * @param int           $toLiteral   A literal the node should watch now
     * @param RuleWatchNode $node        The rule node to be moved
     */
    protected function moveWatch(int $fromLiteral, int $toLiteral, \Composer\DependencyResolver\RuleWatchNode $node): void
    {
        if (!isset($this->watchChains[$toLiteral])) {
            $this->watchChains[$toLiteral] = new \Composer\DependencyResolver\RuleWatchChain();
        }
        $node->moveWatch($fromLiteral, $toLiteral);
        $this->watchChains[$fromLiteral]->remove();
        $this->watchChains[$toLiteral]->unshift($node);
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer\DependencyResolver;

/**
 * @author Nils Adermann <naderman@naderman.de>
 */
class GenericRule extends \Composer\DependencyResolver\Rule
{
    /** @var list<int> */
    protected $literals;
    /**
     * @param list<int> $literals
     */
    public function __construct(array $literals, $reason, $reasonData)
    {
        parent::__construct($reason, $reasonData);
        // sort all packages ascending by id
        sort($literals);
        $this->literals = $literals;
    }
    /**
     * @return list<int>
     */
    public function getLiterals(): array
    {
        return $this->literals;
    }
    /**
     * @inheritDoc
     */
    public function getHash()
    {
        $data = unpack('ihash', (string) hash(\PHP_VERSION_ID > 80100 ? 'xxh3' : 'sha1', implode(',', $this->literals), \true));
        if (\false === $data) {
            throw new \RuntimeException('Failed unpacking: ' . implode(', ', $this->literals));
        }
        return $data['hash'];
    }
    /**
     * Checks if this rule is equal to another one
     *
     * Ignores whether either of the rules is disabled.
     *
     * @param  Rule $rule The rule to check against
     * @return bool Whether the rules are equal
     */
    public function equals(\Composer\DependencyResolver\Rule $rule): bool
    {
        return $this->literals === $rule->getLiterals();
    }
    public function isAssertion(): bool
    {
        return 1 === \count($this->literals);
    }
    /**
     * Formats a rule as a string of the format (Literal1|Literal2|...)
     */
    public function __toString(): string
    {
        $result = $this->isDisabled() ? 'disabled(' : '(';
        foreach ($this->literals as $i => $literal) {
            if ($i !== 0) {
                $result .= '|';
            }
            $result .= $literal;
        }
        $result .= ')';
        return $result;
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer\DependencyResolver;

use Composer\Package\AliasPackage;
use Composer\Package\BasePackage;
use Composer\Package\Package;
use Composer\Pcre\Preg;
/**
 * @author Nils Adermann <naderman@naderman.de>
 * @internal
 */
class LockTransaction extends \Composer\DependencyResolver\Transaction
{
    /**
     * packages in current lock file, platform repo or otherwise present
     *
     * Indexed by spl_object_hash
     *
     * @var array<string, BasePackage>
     */
    protected $presentMap;
    /**
     * Packages which cannot be mapped, platform repo, root package, other fixed repos
     *
     * Indexed by package id
     *
     * @var array<int, BasePackage>
     */
    protected $unlockableMap;
    /**
     * @var array{dev: BasePackage[], non-dev: BasePackage[], all: BasePackage[]}
     */
    protected $resultPackages;
    /**
     * @param array<string, BasePackage> $presentMap
     * @param array<int, BasePackage> $unlockableMap
     */
    public function __construct(\Composer\DependencyResolver\Pool $pool, array $presentMap, array $unlockableMap, \Composer\DependencyResolver\Decisions $decisions)
    {
        $this->presentMap = $presentMap;
        $this->unlockableMap = $unlockableMap;
        $this->setResultPackages($pool, $decisions);
        parent::__construct($this->presentMap, $this->resultPackages['all']);
    }
    // TODO make this a bit prettier instead of the two text indexes?
    public function setResultPackages(\Composer\DependencyResolver\Pool $pool, \Composer\DependencyResolver\Decisions $decisions): void
    {
        $this->resultPackages = ['all' => [], 'non-dev' => [], 'dev' => []];
        foreach ($decisions as $i => $decision) {
            $literal = $decision[\Composer\DependencyResolver\Decisions::DECISION_LITERAL];
            if ($literal > 0) {
                $package = $pool->literalToPackage($literal);
                $this->resultPackages['all'][] = $package;
                if (!isset($this->unlockableMap[$package->id])) {
                    $this->resultPackages['non-dev'][] = $package;
                }
            }
        }
    }
    public function setNonDevPackages(\Composer\DependencyResolver\LockTransaction $extractionResult): void
    {
        $packages = $extractionResult->getNewLockPackages(\false);
        $this->resultPackages['dev'] = $this->resultPackages['non-dev'];
        $this->resultPackages['non-dev'] = [];
        foreach ($packages as $package) {
            foreach ($this->resultPackages['dev'] as $i => $resultPackage) {
                // TODO this comparison is probably insufficient, aliases, what about modified versions? I guess they aren't possible?
                if ($package->getName() === $resultPackage->getName()) {
                    $this->resultPackages['non-dev'][] = $resultPackage;
                    unset($this->resultPackages['dev'][$i]);
                }
            }
        }
    }
    // TODO additionalFixedRepository needs to be looked at here as well?
    /**
     * @return BasePackage[]
     */
    public function getNewLockPackages(bool $devMode, bool $updateMirrors = \false): array
    {
        $packages = [];
        foreach ($this->resultPackages[$devMode ? 'dev' : 'non-dev'] as $package) {
            if ($package instanceof AliasPackage) {
                continue;
            }
            // if we're just updating mirrors we need to reset everything to the same as currently "present" packages' references to keep the lock file as-is
            if ($updateMirrors === \true && !array_key_exists(spl_object_hash($package), $this->presentMap)) {
                $package = $this->updateMirrorAndUrls($package);
            }
            $packages[] = $package;
        }
        return $packages;
    }
    /**
     * Try to return the original package from presentMap with updated URLs/mirrors
     *
     * If the type of source/dist changed, then we do not update those and keep them as they were
     */
    private function updateMirrorAndUrls(BasePackage $package): BasePackage
    {
        foreach ($this->presentMap as $presentPackage) {
            if ($package->getName() !== $presentPackage->getName()) {
                continue;
            }
            if ($package->getVersion() !== $presentPackage->getVersion()) {
                continue;
            }
            if ($presentPackage->getSourceReference() === null) {
                continue;
            }
            if ($presentPackage->getSourceType() !== $package->getSourceType()) {
                continue;
            }
            if ($presentPackage instanceof Package) {
                $presentPackage->setSourceUrl($package->getSourceUrl());
                $presentPackage->setSourceMirrors($package->getSourceMirrors());
            }
            // if the dist type changed, we only update the source url/mirrors
            if ($presentPackage->getDistType() !== $package->getDistType()) {
                return $presentPackage;
            }
            // update dist url if it is in a known format
            if ($package->getDistUrl() !== null && $presentPackage->getDistReference() !== null && Preg::isMatch('{^https?://(?:(?:www\.)?bitbucket\.org|(api\.)?github\.com|(?:www\.)?gitlab\.com)/}i', $package->getDistUrl())) {
                $presentPackage->setDistUrl(Preg::replace('{(?<=/|sha=)[a-f0-9]{40}(?=/|$)}i', $presentPackage->getDistReference(), $package->getDistUrl()));
            }
            $presentPackage->setDistMirrors($package->getDistMirrors());
            return $presentPackage;
        }
        return $package;
    }
    /**
     * Checks which of the given aliases from composer.json are actually in use for the lock file
     * @param list<array{package: string, version: string, alias: string, alias_normalized: string}> $aliases
     * @return list<array{package: string, version: string, alias: string, alias_normalized: string}>
     */
    public function getAliases(array $aliases): array
    {
        $usedAliases = [];
        foreach ($this->resultPackages['all'] as $package) {
            if ($package instanceof AliasPackage) {
                foreach ($aliases as $index => $alias) {
                    if ($alias['package'] === $package->getName()) {
                        $usedAliases[] = $alias;
                        unset($aliases[$index]);
                    }
                }
            }
        }
        usort($usedAliases, static function ($a, $b): int {
            return strcmp($a['package'], $b['package']);
        });
        return $usedAliases;
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer\DependencyResolver;

use Composer\Filter\PlatformRequirementFilter\IgnoreListPlatformRequirementFilter;
use Composer\Filter\PlatformRequirementFilter\PlatformRequirementFilterFactory;
use Composer\Filter\PlatformRequirementFilter\PlatformRequirementFilterInterface;
use Composer\IO\IOInterface;
use Composer\Package\BasePackage;
/**
 * @author Nils Adermann <naderman@naderman.de>
 */
class Solver
{
    private const BRANCH_LITERALS = 0;
    private const BRANCH_LEVEL = 1;
    /** @var PolicyInterface */
    protected $policy;
    /** @var Pool */
    protected $pool;
    /** @var RuleSet */
    protected $rules;
    /** @var RuleWatchGraph */
    protected $watchGraph;
    /** @var Decisions */
    protected $decisions;
    /** @var BasePackage[] */
    protected $fixedMap;
    /** @var int */
    protected $propagateIndex;
    /** @var array<int, array{array<int, int>, int}> */
    protected $branches = [];
    /** @var Problem[] */
    protected $problems = [];
    /** @var array<Rule[]> */
    protected $learnedPool = [];
    /** @var array<string, int> */
    protected $learnedWhy = [];
    /** @var bool */
    public $testFlagLearnedPositiveLiteral = \false;
    /** @var IOInterface */
    protected $io;
    public function __construct(\Composer\DependencyResolver\PolicyInterface $policy, \Composer\DependencyResolver\Pool $pool, IOInterface $io)
    {
        $this->io = $io;
        $this->policy = $policy;
        $this->pool = $pool;
    }
    public function getRuleSetSize(): int
    {
        return \count($this->rules);
    }
    public function getPool(): \Composer\DependencyResolver\Pool
    {
        return $this->pool;
    }
    // aka solver_makeruledecisions
    private function makeAssertionRuleDecisions(): void
    {
        $decisionStart = \count($this->decisions) - 1;
        $rulesCount = \count($this->rules);
        for ($ruleIndex = 0; $ruleIndex < $rulesCount; $ruleIndex++) {
            $rule = $this->rules->ruleById[$ruleIndex];
            if (!$rule->isAssertion() || $rule->isDisabled()) {
                continue;
            }
            $literals = $rule->getLiterals();
            $literal = $literals[0];
            if (!$this->decisions->decided($literal)) {
                $this->decisions->decide($literal, 1, $rule);
                continue;
            }
            if ($this->decisions->satisfy($literal)) {
                continue;
            }
            // found a conflict
            if (\Composer\DependencyResolver\RuleSet::TYPE_LEARNED === $rule->getType()) {
                $rule->disable();
                continue;
            }
            $conflict = $this->decisions->decisionRule($literal);
            if (\Composer\DependencyResolver\RuleSet::TYPE_PACKAGE === $conflict->getType()) {
                $problem = new \Composer\DependencyResolver\Problem();
                $problem->addRule($rule);
                $problem->addRule($conflict);
                $rule->disable();
                $this->problems[] = $problem;
                continue;
            }
            // conflict with another root require/fixed package
            $problem = new \Composer\DependencyResolver\Problem();
            $problem->addRule($rule);
            $problem->addRule($conflict);
            // push all of our rules (can only be root require/fixed package rules)
            // asserting this literal on the problem stack
            foreach ($this->rules->getIteratorFor(\Composer\DependencyResolver\RuleSet::TYPE_REQUEST) as $assertRule) {
                if ($assertRule->isDisabled() || !$assertRule->isAssertion()) {
                    continue;
                }
                $assertRuleLiterals = $assertRule->getLiterals();
                $assertRuleLiteral = $assertRuleLiterals[0];
                if (abs($literal) !== abs($assertRuleLiteral)) {
                    continue;
                }
                $problem->addRule($assertRule);
                $assertRule->disable();
            }
            $this->problems[] = $problem;
            $this->decisions->resetToOffset($decisionStart);
            $ruleIndex = -1;
        }
    }
    protected function setupFixedMap(\Composer\DependencyResolver\Request $request): void
    {
        $this->fixedMap = [];
        foreach ($request->getFixedPackages() as $package) {
            $this->fixedMap[$package->id] = $package;
        }
    }
    protected function checkForRootRequireProblems(\Composer\DependencyResolver\Request $request, PlatformRequirementFilterInterface $platformRequirementFilter): void
    {
        foreach ($request->getRequires() as $packageName => $constraint) {
            if ($platformRequirementFilter->isIgnored($packageName)) {
                continue;
            } elseif ($platformRequirementFilter instanceof IgnoreListPlatformRequirementFilter) {
                $constraint = $platformRequirementFilter->filterConstraint($packageName, $constraint);
            }
            if (0 === \count($this->pool->whatProvides($packageName, $constraint))) {
                $problem = new \Composer\DependencyResolver\Problem();
                $problem->addRule(new \Composer\DependencyResolver\GenericRule([], \Composer\DependencyResolver\Rule::RULE_ROOT_REQUIRE, ['packageName' => $packageName, 'constraint' => $constraint]));
                $this->problems[] = $problem;
            }
        }
    }
    public function solve(\Composer\DependencyResolver\Request $request, ?PlatformRequirementFilterInterface $platformRequirementFilter = null): \Composer\DependencyResolver\LockTransaction
    {
        $platformRequirementFilter = $platformRequirementFilter ?? PlatformRequirementFilterFactory::ignoreNothing();
        $this->setupFixedMap($request);
        $this->io->writeError('Generating rules', \true, IOInterface::DEBUG);
        $ruleSetGenerator = new \Composer\DependencyResolver\RuleSetGenerator($this->policy, $this->pool);
        $this->rules = $ruleSetGenerator->getRulesFor($request, $platformRequirementFilter);
        unset($ruleSetGenerator);
        $this->checkForRootRequireProblems($request, $platformRequirementFilter);
        $this->decisions = new \Composer\DependencyResolver\Decisions($this->pool);
        $this->watchGraph = new \Composer\DependencyResolver\RuleWatchGraph();
        foreach ($this->rules as $rule) {
            $this->watchGraph->insert(new \Composer\DependencyResolver\RuleWatchNode($rule));
        }
        /* make decisions based on root require/fix assertions */
        $this->makeAssertionRuleDecisions();
        $this->io->writeError('Resolving dependencies through SAT', \true, IOInterface::DEBUG);
        $before = microtime(\true);
        $this->runSat();
        $this->io->writeError('', \true, IOInterface::DEBUG);
        $this->io->writeError(sprintf('Dependency resolution completed in %.3f seconds', microtime(\true) - $before), \true, IOInterface::VERBOSE);
        if (\count($this->problems) > 0) {
            throw new \Composer\DependencyResolver\SolverProblemsException($this->problems, $this->learnedPool);
        }
        return new \Composer\DependencyResolver\LockTransaction($this->pool, $request->getPresentMap(), $request->getFixedPackagesMap(), $this->decisions);
    }
    /**
     * Makes a decision and propagates it to all rules.
     *
     * Evaluates each term affected by the decision (linked through watches)
     * If we find unit rules we make new decisions based on them
     *
     * @return Rule|null A rule on conflict, otherwise null.
     */
    protected function propagate(int $level): ?\Composer\DependencyResolver\Rule
    {
        while ($this->decisions->validOffset($this->propagateIndex)) {
            $decision = $this->decisions->atOffset($this->propagateIndex);
            $conflict = $this->watchGraph->propagateLiteral($decision[\Composer\DependencyResolver\Decisions::DECISION_LITERAL], $level, $this->decisions);
            $this->propagateIndex++;
            if ($conflict !== null) {
                return $conflict;
            }
        }
        return null;
    }
    /**
     * Reverts a decision at the given level.
     */
    private function revert(int $level): void
    {
        while (!$this->decisions->isEmpty()) {
            $literal = $this->decisions->lastLiteral();
            if ($this->decisions->undecided($literal)) {
                break;
            }
            $decisionLevel = $this->decisions->decisionLevel($literal);
            if ($decisionLevel <= $level) {
                break;
            }
            $this->decisions->revertLast();
            $this->propagateIndex = \count($this->decisions);
        }
        while (\count($this->branches) > 0 && $this->branches[\count($this->branches) - 1][self::BRANCH_LEVEL] >= $level) {
            array_pop($this->branches);
        }
    }
    /**
     * setpropagatelearn
     *
     * add free decision (a positive literal) to decision queue
     * increase level and propagate decision
     * return if no conflict.
     *
     * in conflict case, analyze conflict rule, add resulting
     * rule to learnt rule set, make decision from learnt
     * rule (always unit) and re-propagate.
     *
     * returns the new solver level or 0 if unsolvable
     */
    private function setPropagateLearn(int $level, int $literal, \Composer\DependencyResolver\Rule $rule): int
    {
        $level++;
        $this->decisions->decide($literal, $level, $rule);
        while (\true) {
            $rule = $this->propagate($level);
            if (null === $rule) {
                break;
            }
            if ($level === 1) {
                $this->analyzeUnsolvable($rule);
                return 0;
            }
            // conflict
            [$learnLiteral, $newLevel, $newRule, $why] = $this->analyze($level, $rule);
            if ($newLevel <= 0 || $newLevel >= $level) {
                throw new \Composer\DependencyResolver\SolverBugException("Trying to revert to invalid level " . $newLevel . " from level " . $level . ".");
            }
            $level = $newLevel;
            $this->revert($level);
            $this->rules->add($newRule, \Composer\DependencyResolver\RuleSet::TYPE_LEARNED);
            $this->learnedWhy[spl_object_hash($newRule)] = $why;
            $ruleNode = new \Composer\DependencyResolver\RuleWatchNode($newRule);
            $ruleNode->watch2OnHighest($this->decisions);
            $this->watchGraph->insert($ruleNode);
            $this->decisions->decide($learnLiteral, $level, $newRule);
        }
        return $level;
    }
    /**
     * @param non-empty-list<int> $decisionQueue
     */
    private function selectAndInstall(int $level, array $decisionQueue, \Composer\DependencyResolver\Rule $rule): int
    {
        // choose best package to install from decisionQueue
        $literals = $this->policy->selectPreferredPackages($this->pool, $decisionQueue, $rule->getRequiredPackage());
        $selectedLiteral = array_shift($literals);
        // if there are multiple candidates, then branch
        if (\count($literals) > 0) {
            $this->branches[] = [$literals, $level];
        }
        return $this->setPropagateLearn($level, $selectedLiteral, $rule);
    }
    /**
     * @return array{int, int, GenericRule, int}
     */
    protected function analyze(int $level, \Composer\DependencyResolver\Rule $rule): array
    {
        $analyzedRule = $rule;
        $ruleLevel = 1;
        $num = 0;
        $l1num = 0;
        $seen = [];
        $learnedLiteral = null;
        $otherLearnedLiterals = [];
        $decisionId = \count($this->decisions);
        $this->learnedPool[] = [];
        while (\true) {
            $this->learnedPool[\count($this->learnedPool) - 1][] = $rule;
            foreach ($rule->getLiterals() as $literal) {
                // multiconflictrule is really a bunch of rules in one, so some may not have finished propagating yet
                if ($rule instanceof \Composer\DependencyResolver\MultiConflictRule && !$this->decisions->decided($literal)) {
                    continue;
                }
                // skip the one true literal
                if ($this->decisions->satisfy($literal)) {
                    continue;
                }
                if (isset($seen[abs($literal)])) {
                    continue;
                }
                $seen[abs($literal)] = \true;
                $l = $this->decisions->decisionLevel($literal);
                if (1 === $l) {
                    $l1num++;
                } elseif ($level === $l) {
                    $num++;
                } else {
                    // not level1 or conflict level, add to new rule
                    $otherLearnedLiterals[] = $literal;
                    if ($l > $ruleLevel) {
                        $ruleLevel = $l;
                    }
                }
            }
            unset($literal);
            $l1retry = \true;
            while ($l1retry) {
                $l1retry = \false;
                if (0 === $num && 0 === --$l1num) {
                    // all level 1 literals done
                    break 2;
                }
                while (\true) {
                    if ($decisionId <= 0) {
                        throw new \Composer\DependencyResolver\SolverBugException("Reached invalid decision id {$decisionId} while looking through {$rule} for a literal present in the analyzed rule {$analyzedRule}.");
                    }
                    $decisionId--;
                    $decision = $this->decisions->atOffset($decisionId);
                    $literal = $decision[\Composer\DependencyResolver\Decisions::DECISION_LITERAL];
                    if (isset($seen[abs($literal)])) {
                        break;
                    }
                }
                unset($seen[abs($literal)]);
                if (0 !== $num && 0 === --$num) {
                    if ($literal < 0) {
                        $this->testFlagLearnedPositiveLiteral = \true;
                    }
                    $learnedLiteral = -$literal;
                    if (0 === $l1num) {
                        break 2;
                    }
                    foreach ($otherLearnedLiterals as $otherLiteral) {
                        unset($seen[abs($otherLiteral)]);
                    }
                    // only level 1 marks left
                    $l1num++;
                    $l1retry = \true;
                } else {
                    $decision = $this->decisions->atOffset($decisionId);
                    $rule = $decision[\Composer\DependencyResolver\Decisions::DECISION_REASON];
                    if ($rule instanceof \Composer\DependencyResolver\MultiConflictRule) {
                        // there is only ever exactly one positive decision in a MultiConflictRule
                        foreach ($rule->getLiterals() as $ruleLiteral) {
                            if (!isset($seen[abs($ruleLiteral)]) && $this->decisions->satisfy(-$ruleLiteral)) {
                                $this->learnedPool[\count($this->learnedPool) - 1][] = $rule;
                                $l = $this->decisions->decisionLevel($ruleLiteral);
                                if (1 === $l) {
                                    $l1num++;
                                } elseif ($level === $l) {
                                    $num++;
                                } else {
                                    // not level1 or conflict level, add to new rule
                                    $otherLearnedLiterals[] = $ruleLiteral;
                                    if ($l > $ruleLevel) {
                                        $ruleLevel = $l;
                                    }
                                }
                                $seen[abs($ruleLiteral)] = \true;
                                break;
                            }
                        }
                        $l1retry = \true;
                    }
                }
            }
            $decision = $this->decisions->atOffset($decisionId);
            $rule = $decision[\Composer\DependencyResolver\Decisions::DECISION_REASON];
        }
        $why = \count($this->learnedPool) - 1;
        if (null === $learnedLiteral) {
            throw new \Composer\DependencyResolver\SolverBugException("Did not find a learnable literal in analyzed rule {$analyzedRule}.");
        }
        array_unshift($otherLearnedLiterals, $learnedLiteral);
        $newRule = new \Composer\DependencyResolver\GenericRule($otherLearnedLiterals, \Composer\DependencyResolver\Rule::RULE_LEARNED, $why);
        return [$learnedLiteral, $ruleLevel, $newRule, $why];
    }
    /**
     * @param array<string, true> $ruleSeen
     */
    private function analyzeUnsolvableRule(\Composer\DependencyResolver\Problem $problem, \Composer\DependencyResolver\Rule $conflictRule, array &$ruleSeen): void
    {
        $why = spl_object_hash($conflictRule);
        $ruleSeen[$why] = \true;
        if ($conflictRule->getType() === \Composer\DependencyResolver\RuleSet::TYPE_LEARNED) {
            $learnedWhy = $this->learnedWhy[$why];
            $problemRules = $this->learnedPool[$learnedWhy];
            foreach ($problemRules as $problemRule) {
                if (!isset($ruleSeen[spl_object_hash($problemRule)])) {
                    $this->analyzeUnsolvableRule($problem, $problemRule, $ruleSeen);
                }
            }
            return;
        }
        if ($conflictRule->getType() === \Composer\DependencyResolver\RuleSet::TYPE_PACKAGE) {
            // package rules cannot be part of a problem
            return;
        }
        $problem->nextSection();
        $problem->addRule($conflictRule);
    }
    private function analyzeUnsolvable(\Composer\DependencyResolver\Rule $conflictRule): void
    {
        $problem = new \Composer\DependencyResolver\Problem();
        $problem->addRule($conflictRule);
        $ruleSeen = [];
        $this->analyzeUnsolvableRule($problem, $conflictRule, $ruleSeen);
        $this->problems[] = $problem;
        $seen = [];
        $literals = $conflictRule->getLiterals();
        foreach ($literals as $literal) {
            // skip the one true literal
            if ($this->decisions->satisfy($literal)) {
                continue;
            }
            $seen[abs($literal)] = \true;
        }
        foreach ($this->decisions as $decision) {
            $decisionLiteral = $decision[\Composer\DependencyResolver\Decisions::DECISION_LITERAL];
            // skip literals that are not in this rule
            if (!isset($seen[abs($decisionLiteral)])) {
                continue;
            }
            $why = $decision[\Composer\DependencyResolver\Decisions::DECISION_REASON];
            $problem->addRule($why);
            $this->analyzeUnsolvableRule($problem, $why, $ruleSeen);
            $literals = $why->getLiterals();
            foreach ($literals as $literal) {
                // skip the one true literal
                if ($this->decisions->satisfy($literal)) {
                    continue;
                }
                $seen[abs($literal)] = \true;
            }
        }
    }
    private function runSat(): void
    {
        $this->propagateIndex = 0;
        /*
         * here's the main loop:
         * 1) propagate new decisions (only needed once)
         * 2) fulfill root requires/fixed packages
         * 3) fulfill all unresolved rules
         * 4) minimalize solution if we had choices
         * if we encounter a problem, we rewind to a safe level and restart
         * with step 1
         */
        $level = 1;
        $systemLevel = $level + 1;
        while (\true) {
            if (1 === $level) {
                $conflictRule = $this->propagate($level);
                if (null !== $conflictRule) {
                    $this->analyzeUnsolvable($conflictRule);
                    return;
                }
            }
            // handle root require/fixed package rules
            if ($level < $systemLevel) {
                $iterator = $this->rules->getIteratorFor(\Composer\DependencyResolver\RuleSet::TYPE_REQUEST);
                foreach ($iterator as $rule) {
                    if ($rule->isEnabled()) {
                        $decisionQueue = [];
                        $noneSatisfied = \true;
                        foreach ($rule->getLiterals() as $literal) {
                            if ($this->decisions->satisfy($literal)) {
                                $noneSatisfied = \false;
                                break;
                            }
                            if ($literal > 0 && $this->decisions->undecided($literal)) {
                                $decisionQueue[] = $literal;
                            }
                        }
                        if ($noneSatisfied && \count($decisionQueue) > 0) {
                            // if any of the options in the decision queue are fixed, only use those
                            $prunedQueue = [];
                            foreach ($decisionQueue as $literal) {
                                if (isset($this->fixedMap[abs($literal)])) {
                                    $prunedQueue[] = $literal;
                                }
                            }
                            if (\count($prunedQueue) > 0) {
                                $decisionQueue = $prunedQueue;
                            }
                        }
                        if ($noneSatisfied && \count($decisionQueue) > 0) {
                            $oLevel = $level;
                            $level = $this->selectAndInstall($level, $decisionQueue, $rule);
                            if (0 === $level) {
                                return;
                            }
                            if ($level <= $oLevel) {
                                break;
                            }
                        }
                    }
                }
                $systemLevel = $level + 1;
                // root requires/fixed packages left
                $iterator->next();
                if ($iterator->valid()) {
                    continue;
                }
            }
            if ($level < $systemLevel) {
                $systemLevel = $level;
            }
            $rulesCount = \count($this->rules);
            $pass = 1;
            $this->io->writeError('Looking at all rules.', \true, IOInterface::DEBUG);
            for ($i = 0, $n = 0; $n < $rulesCount; $i++, $n++) {
                if ($i === $rulesCount) {
                    if (1 === $pass) {
                        $this->io->writeError("Something's changed, looking at all rules again (pass #{$pass})", \false, IOInterface::DEBUG);
                    } else {
                        $this->io->overwriteError("Something's changed, looking at all rules again (pass #{$pass})", \false, null, IOInterface::DEBUG);
                    }
                    $i = 0;
                    $pass++;
                }
                $rule = $this->rules->ruleById[$i];
                $literals = $rule->getLiterals();
                if ($rule->isDisabled()) {
                    continue;
                }
                $decisionQueue = [];
                // make sure that
                // * all negative literals are installed
                // * no positive literal is installed
                // i.e. the rule is not fulfilled and we
                // just need to decide on the positive literals
                //
                foreach ($literals as $literal) {
                    if ($literal <= 0) {
                        if (!$this->decisions->decidedInstall($literal)) {
                            continue 2;
                            // next rule
                        }
                    } else {
                        if ($this->decisions->decidedInstall($literal)) {
                            continue 2;
                            // next rule
                        }
                        if ($this->decisions->undecided($literal)) {
                            $decisionQueue[] = $literal;
                        }
                    }
                }
                // need to have at least 2 item to pick from
                if (\count($decisionQueue) < 2) {
                    continue;
                }
                $level = $this->selectAndInstall($level, $decisionQueue, $rule);
                if (0 === $level) {
                    return;
                }
                // something changed, so look at all rules again
                $rulesCount = \count($this->rules);
                $n = -1;
            }
            if ($level < $systemLevel) {
                continue;
            }
            // minimization step
            if (\count($this->branches) > 0) {
                $lastLiteral = null;
                $lastLevel = null;
                $lastBranchIndex = 0;
                $lastBranchOffset = 0;
                for ($i = \count($this->branches) - 1; $i >= 0; $i--) {
                    [$literals, $l] = $this->branches[$i];
                    foreach ($literals as $offset => $literal) {
                        if ($literal > 0 && $this->decisions->decisionLevel($literal) > $l + 1) {
                            $lastLiteral = $literal;
                            $lastBranchIndex = $i;
                            $lastBranchOffset = $offset;
                            $lastLevel = $l;
                        }
                    }
                }
                if ($lastLiteral !== null) {
                    assert($lastLevel !== null);
                    unset($this->branches[$lastBranchIndex][self::BRANCH_LITERALS][$lastBranchOffset]);
                    $level = $lastLevel;
                    $this->revert($level);
                    $why = $this->decisions->lastReason();
                    $level = $this->setPropagateLearn($level, $lastLiteral, $why);
                    if ($level === 0) {
                        return;
                    }
                    continue;
                }
            }
            break;
        }
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer\DependencyResolver;

use Composer\Package\AliasPackage;
use Composer\Package\BasePackage;
use Composer\Package\Link;
use Composer\Repository\PlatformRepository;
use Composer\Repository\RepositorySet;
use Composer\Package\Version\VersionParser;
use Composer\Semver\Constraint\Constraint;
use Composer\Semver\Constraint\ConstraintInterface;
/**
 * @author Nils Adermann <naderman@naderman.de>
 * @author Ruben Gonzalez <rubenrua@gmail.com>
 * @phpstan-type ReasonData Link|BasePackage|string|int|array{packageName: string, constraint: ConstraintInterface}|array{package: BasePackage}
 */
abstract class Rule
{
    // reason constants and // their reason data contents
    public const RULE_ROOT_REQUIRE = 2;
    // array{packageName: string, constraint: ConstraintInterface}
    public const RULE_FIXED = 3;
    // array{package: BasePackage}
    public const RULE_PACKAGE_CONFLICT = 6;
    // Link
    public const RULE_PACKAGE_REQUIRES = 7;
    // Link
    public const RULE_PACKAGE_SAME_NAME = 10;
    // string (package name)
    public const RULE_LEARNED = 12;
    // int (rule id)
    public const RULE_PACKAGE_ALIAS = 13;
    // BasePackage
    public const RULE_PACKAGE_INVERSE_ALIAS = 14;
    // BasePackage
    // bitfield defs
    private const BITFIELD_TYPE = 0;
    private const BITFIELD_REASON = 8;
    private const BITFIELD_DISABLED = 16;
    /** @var int */
    protected $bitfield;
    /** @var Request */
    protected $request;
    /**
     * @var Link|BasePackage|ConstraintInterface|string
     * @phpstan-var ReasonData
     */
    protected $reasonData;
    /**
     * @param self::RULE_* $reason     A RULE_* constant describing the reason for generating this rule
     * @param mixed        $reasonData
     *
     * @phpstan-param ReasonData $reasonData
     */
    public function __construct($reason, $reasonData)
    {
        $this->reasonData = $reasonData;
        $this->bitfield = 0 << self::BITFIELD_DISABLED | $reason << self::BITFIELD_REASON | 255 << self::BITFIELD_TYPE;
    }
    /**
     * @return list<int>
     */
    abstract public function getLiterals(): array;
    /**
     * @return int|string
     */
    abstract public function getHash();
    abstract public function __toString(): string;
    abstract public function equals(\Composer\DependencyResolver\Rule $rule): bool;
    /**
     * @return self::RULE_*
     */
    public function getReason(): int
    {
        return ($this->bitfield & 255 << self::BITFIELD_REASON) >> self::BITFIELD_REASON;
    }
    /**
     * @phpstan-return ReasonData
     */
    public function getReasonData()
    {
        return $this->reasonData;
    }
    public function getRequiredPackage(): ?string
    {
        switch ($this->getReason()) {
            case self::RULE_ROOT_REQUIRE:
                return $this->getReasonData()['packageName'];
            case self::RULE_FIXED:
                return $this->getReasonData()['package']->getName();
            case self::RULE_PACKAGE_REQUIRES:
                return $this->getReasonData()->getTarget();
        }
        return null;
    }
    /**
     * @param RuleSet::TYPE_* $type
     */
    public function setType($type): void
    {
        $this->bitfield = $this->bitfield & ~(255 << self::BITFIELD_TYPE) | (255 & $type) << self::BITFIELD_TYPE;
    }
    public function getType(): int
    {
        return ($this->bitfield & 255 << self::BITFIELD_TYPE) >> self::BITFIELD_TYPE;
    }
    public function disable(): void
    {
        $this->bitfield = $this->bitfield & ~(255 << self::BITFIELD_DISABLED) | 1 << self::BITFIELD_DISABLED;
    }
    public function enable(): void
    {
        $this->bitfield &= ~(255 << self::BITFIELD_DISABLED);
    }
    public function isDisabled(): bool
    {
        return 0 !== ($this->bitfield & 255 << self::BITFIELD_DISABLED) >> self::BITFIELD_DISABLED;
    }
    public function isEnabled(): bool
    {
        return 0 === ($this->bitfield & 255 << self::BITFIELD_DISABLED) >> self::BITFIELD_DISABLED;
    }
    abstract public function isAssertion(): bool;
    public function isCausedByLock(RepositorySet $repositorySet, \Composer\DependencyResolver\Request $request, \Composer\DependencyResolver\Pool $pool): bool
    {
        if ($this->getReason() === self::RULE_PACKAGE_REQUIRES) {
            if (PlatformRepository::isPlatformPackage($this->getReasonData()->getTarget())) {
                return \false;
            }
            if ($request->getLockedRepository() !== null) {
                foreach ($request->getLockedRepository()->getPackages() as $package) {
                    if ($package->getName() === $this->getReasonData()->getTarget()) {
                        if ($pool->isUnacceptableFixedOrLockedPackage($package)) {
                            return \true;
                        }
                        if (!$this->getReasonData()->getConstraint()->matches(new Constraint('=', $package->getVersion()))) {
                            return \true;
                        }
                        // required package was locked but has been unlocked and still matches
                        if (!$request->isLockedPackage($package)) {
                            return \true;
                        }
                        break;
                    }
                }
            }
        }
        if ($this->getReason() === self::RULE_ROOT_REQUIRE) {
            if (PlatformRepository::isPlatformPackage($this->getReasonData()['packageName'])) {
                return \false;
            }
            if ($request->getLockedRepository() !== null) {
                foreach ($request->getLockedRepository()->getPackages() as $package) {
                    if ($package->getName() === $this->getReasonData()['packageName']) {
                        if ($pool->isUnacceptableFixedOrLockedPackage($package)) {
                            return \true;
                        }
                        if (!$this->getReasonData()['constraint']->matches(new Constraint('=', $package->getVersion()))) {
                            return \true;
                        }
                        break;
                    }
                }
            }
        }
        return \false;
    }
    /**
     * @internal
     */
    public function getSourcePackage(\Composer\DependencyResolver\Pool $pool): BasePackage
    {
        $literals = $this->getLiterals();
        switch ($this->getReason()) {
            case self::RULE_PACKAGE_CONFLICT:
                $package1 = $this->deduplicateDefaultBranchAlias($pool->literalToPackage($literals[0]));
                $package2 = $this->deduplicateDefaultBranchAlias($pool->literalToPackage($literals[1]));
                $reasonData = $this->getReasonData();
                // swap literals if they are not in the right order with package2 being the conflicter
                if ($reasonData->getSource() === $package1->getName()) {
                    [$package2, $package1] = [$package1, $package2];
                }
                return $package2;
            case self::RULE_PACKAGE_REQUIRES:
                $sourceLiteral = $literals[0];
                $sourcePackage = $this->deduplicateDefaultBranchAlias($pool->literalToPackage($sourceLiteral));
                return $sourcePackage;
            default:
                throw new \LogicException('Not implemented');
        }
    }
    /**
     * @param BasePackage[] $installedMap
     * @param array<Rule[]> $learnedPool
     */
    public function getPrettyString(RepositorySet $repositorySet, \Composer\DependencyResolver\Request $request, \Composer\DependencyResolver\Pool $pool, bool $isVerbose, array $installedMap = [], array $learnedPool = []): string
    {
        $literals = $this->getLiterals();
        switch ($this->getReason()) {
            case self::RULE_ROOT_REQUIRE:
                $reasonData = $this->getReasonData();
                $packageName = $reasonData['packageName'];
                $constraint = $reasonData['constraint'];
                $packages = $pool->whatProvides($packageName, $constraint);
                if (0 === \count($packages)) {
                    return 'No package found to satisfy root composer.json require ' . $packageName . ' ' . $constraint->getPrettyString();
                }
                $packagesNonAlias = array_values(array_filter($packages, static function ($p): bool {
                    return !$p instanceof AliasPackage;
                }));
                if (\count($packagesNonAlias) === 1) {
                    $package = $packagesNonAlias[0];
                    if ($request->isLockedPackage($package)) {
                        return $package->getPrettyName() . ' is locked to version ' . $package->getPrettyVersion() . " and an update of this package was not requested.";
                    }
                }
                return 'Root composer.json requires ' . $packageName . ' ' . $constraint->getPrettyString() . ' -> satisfiable by ' . $this->formatPackagesUnique($pool, $packages, $isVerbose, $constraint) . '.';
            case self::RULE_FIXED:
                $package = $this->deduplicateDefaultBranchAlias($this->getReasonData()['package']);
                if ($request->isLockedPackage($package)) {
                    return $package->getPrettyName() . ' is locked to version ' . $package->getPrettyVersion() . ' and an update of this package was not requested.';
                }
                return $package->getPrettyName() . ' is present at version ' . $package->getPrettyVersion() . ' and cannot be modified by Composer';
            case self::RULE_PACKAGE_CONFLICT:
                $package1 = $this->deduplicateDefaultBranchAlias($pool->literalToPackage($literals[0]));
                $package2 = $this->deduplicateDefaultBranchAlias($pool->literalToPackage($literals[1]));
                $conflictTarget = $package1->getPrettyString();
                $reasonData = $this->getReasonData();
                // swap literals if they are not in the right order with package2 being the conflicter
                if ($reasonData->getSource() === $package1->getName()) {
                    [$package2, $package1] = [$package1, $package2];
                    $conflictTarget = $package1->getPrettyName() . ' ' . $reasonData->getPrettyConstraint();
                }
                // if the conflict is not directly against the package but something it provides/replaces,
                // we try to find that link to display a better message
                if ($reasonData->getTarget() !== $package1->getName()) {
                    $provideType = null;
                    $provided = null;
                    foreach ($package1->getProvides() as $provide) {
                        if ($provide->getTarget() === $reasonData->getTarget()) {
                            $provideType = 'provides';
                            $provided = $provide->getPrettyConstraint();
                            break;
                        }
                    }
                    foreach ($package1->getReplaces() as $replace) {
                        if ($replace->getTarget() === $reasonData->getTarget()) {
                            $provideType = 'replaces';
                            $provided = $replace->getPrettyConstraint();
                            break;
                        }
                    }
                    if (null !== $provideType) {
                        $conflictTarget = $reasonData->getTarget() . ' ' . $reasonData->getPrettyConstraint() . ' (' . $package1->getPrettyString() . ' ' . $provideType . ' ' . $reasonData->getTarget() . ' ' . $provided . ')';
                    }
                }
                return $package2->getPrettyString() . ' conflicts with ' . $conflictTarget . '.';
            case self::RULE_PACKAGE_REQUIRES:
                assert(\count($literals) > 0);
                $sourceLiteral = array_shift($literals);
                $sourcePackage = $this->deduplicateDefaultBranchAlias($pool->literalToPackage($sourceLiteral));
                $reasonData = $this->getReasonData();
                $requires = [];
                foreach ($literals as $literal) {
                    $requires[] = $pool->literalToPackage($literal);
                }
                $text = $reasonData->getPrettyString($sourcePackage);
                if (\count($requires) > 0) {
                    $text .= ' -> satisfiable by ' . $this->formatPackagesUnique($pool, $requires, $isVerbose, $reasonData->getConstraint()) . '.';
                } else {
                    $targetName = $reasonData->getTarget();
                    $reason = \Composer\DependencyResolver\Problem::getMissingPackageReason($repositorySet, $request, $pool, $isVerbose, $targetName, $reasonData->getConstraint());
                    return $text . ' -> ' . $reason[1];
                }
                return $text;
            case self::RULE_PACKAGE_SAME_NAME:
                $packageNames = [];
                foreach ($literals as $literal) {
                    $package = $pool->literalToPackage($literal);
                    $packageNames[$package->getName()] = \true;
                }
                unset($literal);
                $replacedName = $this->getReasonData();
                if (\count($packageNames) > 1) {
                    if (!isset($packageNames[$replacedName])) {
                        $reason = 'They ' . (\count($literals) === 2 ? 'both' : 'all') . ' replace ' . $replacedName . ' and thus cannot coexist.';
                    } else {
                        $replacerNames = $packageNames;
                        unset($replacerNames[$replacedName]);
                        $replacerNames = array_keys($replacerNames);
                        if (\count($replacerNames) === 1) {
                            $reason = $replacerNames[0] . ' replaces ';
                        } else {
                            $reason = '[' . implode(', ', $replacerNames) . '] replace ';
                        }
                        $reason .= $replacedName . ' and thus cannot coexist with it.';
                    }
                    $installedPackages = [];
                    $removablePackages = [];
                    foreach ($literals as $literal) {
                        if (isset($installedMap[abs($literal)])) {
                            $installedPackages[] = $pool->literalToPackage($literal);
                        } else {
                            $removablePackages[] = $pool->literalToPackage($literal);
                        }
                    }
                    if (\count($installedPackages) > 0 && \count($removablePackages) > 0) {
                        return $this->formatPackagesUnique($pool, $removablePackages, $isVerbose, null, \true) . ' cannot be installed as that would require removing ' . $this->formatPackagesUnique($pool, $installedPackages, $isVerbose, null, \true) . '. ' . $reason;
                    }
                    return 'Only one of these can be installed: ' . $this->formatPackagesUnique($pool, $literals, $isVerbose, null, \true) . '. ' . $reason;
                }
                return 'You can only install one version of a package, so only one of these can be installed: ' . $this->formatPackagesUnique($pool, $literals, $isVerbose, null, \true) . '.';
            case self::RULE_LEARNED:
                /** @TODO currently still generates way too much output to be helpful, and in some cases can even lead to endless recursion */
                // if (isset($learnedPool[$this->getReasonData()])) {
                //     echo $this->getReasonData()."\n";
                //     $learnedString = ', learned rules:' . Problem::formatDeduplicatedRules($learnedPool[$this->getReasonData()], '        ', $repositorySet, $request, $pool, $isVerbose, $installedMap, $learnedPool);
                // } else {
                //     $learnedString = ' (reasoning unavailable)';
                // }
                $learnedString = ' (conflict analysis result)';
                if (\count($literals) === 1) {
                    $ruleText = $pool->literalToPrettyString($literals[0], $installedMap);
                } else {
                    $groups = [];
                    foreach ($literals as $literal) {
                        $package = $pool->literalToPackage($literal);
                        if (isset($installedMap[$package->id])) {
                            $group = $literal > 0 ? 'keep' : 'remove';
                        } else {
                            $group = $literal > 0 ? 'install' : 'don\'t install';
                        }
                        $groups[$group][] = $this->deduplicateDefaultBranchAlias($package);
                    }
                    $ruleTexts = [];
                    foreach ($groups as $group => $packages) {
                        $ruleTexts[] = $group . (\count($packages) > 1 ? ' one of' : '') . ' ' . $this->formatPackagesUnique($pool, $packages, $isVerbose);
                    }
                    $ruleText = implode(' | ', $ruleTexts);
                }
                return 'Conclusion: ' . $ruleText . $learnedString;
            case self::RULE_PACKAGE_ALIAS:
                $aliasPackage = $pool->literalToPackage($literals[0]);
                // avoid returning content like "9999999-dev is an alias of dev-master" as it is useless
                if ($aliasPackage->getVersion() === VersionParser::DEFAULT_BRANCH_ALIAS) {
                    return '';
                }
                $package = $this->deduplicateDefaultBranchAlias($pool->literalToPackage($literals[1]));
                return $aliasPackage->getPrettyString() . ' is an alias of ' . $package->getPrettyString() . ' and thus requires it to be installed too.';
            case self::RULE_PACKAGE_INVERSE_ALIAS:
                // inverse alias rules work the other way around than above
                $aliasPackage = $pool->literalToPackage($literals[1]);
                // avoid returning content like "9999999-dev is an alias of dev-master" as it is useless
                if ($aliasPackage->getVersion() === VersionParser::DEFAULT_BRANCH_ALIAS) {
                    return '';
                }
                $package = $this->deduplicateDefaultBranchAlias($pool->literalToPackage($literals[0]));
                return $aliasPackage->getPrettyString() . ' is an alias of ' . $package->getPrettyString() . ' and must be installed with it.';
            default:
                $ruleText = '';
                foreach ($literals as $i => $literal) {
                    if ($i !== 0) {
                        $ruleText .= '|';
                    }
                    $ruleText .= $pool->literalToPrettyString($literal, $installedMap);
                }
                return '(' . $ruleText . ')';
        }
    }
    /**
     * @param array<int|BasePackage> $literalsOrPackages An array containing packages or literals
     */
    protected function formatPackagesUnique(\Composer\DependencyResolver\Pool $pool, array $literalsOrPackages, bool $isVerbose, ?ConstraintInterface $constraint = null, bool $useRemovedVersionGroup = \false): string
    {
        $packages = [];
        foreach ($literalsOrPackages as $package) {
            $packages[] = \is_object($package) ? $package : $pool->literalToPackage($package);
        }
        return \Composer\DependencyResolver\Problem::getPackageList($packages, $isVerbose, $pool, $constraint, $useRemovedVersionGroup);
    }
    private function deduplicateDefaultBranchAlias(BasePackage $package): BasePackage
    {
        if ($package instanceof AliasPackage && $package->getPrettyVersion() === VersionParser::DEFAULT_BRANCH_ALIAS) {
            $package = $package->getAliasOf();
        }
        return $package;
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer\DependencyResolver;

/**
 * @author Nils Adermann <naderman@naderman.de>
 * @phpstan-import-type ReasonData from Rule
 */
class Rule2Literals extends \Composer\DependencyResolver\Rule
{
    /** @var int */
    protected $literal1;
    /** @var int */
    protected $literal2;
    /**
     * @param Rule::RULE_* $reason A RULE_* constant
     * @param mixed $reasonData
     *
     * @phpstan-param ReasonData $reasonData
     */
    public function __construct(int $literal1, int $literal2, $reason, $reasonData)
    {
        parent::__construct($reason, $reasonData);
        if ($literal1 < $literal2) {
            $this->literal1 = $literal1;
            $this->literal2 = $literal2;
        } else {
            $this->literal1 = $literal2;
            $this->literal2 = $literal1;
        }
    }
    /**
     * @return non-empty-list<int>
     */
    public function getLiterals(): array
    {
        return [$this->literal1, $this->literal2];
    }
    /**
     * @inheritDoc
     */
    public function getHash()
    {
        return $this->literal1 . ',' . $this->literal2;
    }
    /**
     * Checks if this rule is equal to another one
     *
     * Ignores whether either of the rules is disabled.
     *
     * @param  Rule $rule The rule to check against
     * @return bool Whether the rules are equal
     */
    public function equals(\Composer\DependencyResolver\Rule $rule): bool
    {
        // specialized fast-case
        if ($rule instanceof self) {
            if ($this->literal1 !== $rule->literal1) {
                return \false;
            }
            if ($this->literal2 !== $rule->literal2) {
                return \false;
            }
            return \true;
        }
        $literals = $rule->getLiterals();
        if (2 !== \count($literals)) {
            return \false;
        }
        if ($this->literal1 !== $literals[0]) {
            return \false;
        }
        if ($this->literal2 !== $literals[1]) {
            return \false;
        }
        return \true;
    }
    /** @return false */
    public function isAssertion(): bool
    {
        return \false;
    }
    /**
     * Formats a rule as a string of the format (Literal1|Literal2|...)
     */
    public function __toString(): string
    {
        $result = $this->isDisabled() ? 'disabled(' : '(';
        $result .= $this->literal1 . '|' . $this->literal2 . ')';
        return $result;
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer\DependencyResolver;

use Composer\Util\IniHelper;
use Composer\Repository\RepositorySet;
/**
 * @author Nils Adermann <naderman@naderman.de>
 *
 * @method self::ERROR_DEPENDENCY_RESOLUTION_FAILED getCode()
 */
class SolverProblemsException extends \RuntimeException
{
    public const ERROR_DEPENDENCY_RESOLUTION_FAILED = 2;
    /** @var Problem[] */
    protected $problems;
    /** @var array<Rule[]> */
    protected $learnedPool;
    /**
     * @param Problem[] $problems
     * @param array<Rule[]> $learnedPool
     */
    public function __construct(array $problems, array $learnedPool)
    {
        $this->problems = $problems;
        $this->learnedPool = $learnedPool;
        parent::__construct('Failed resolving dependencies with ' . \count($problems) . ' problems, call getPrettyString to get formatted details', self::ERROR_DEPENDENCY_RESOLUTION_FAILED);
    }
    public function getPrettyString(RepositorySet $repositorySet, \Composer\DependencyResolver\Request $request, \Composer\DependencyResolver\Pool $pool, bool $isVerbose, bool $isDevExtraction = \false): string
    {
        $installedMap = $request->getPresentMap(\true);
        $missingExtensions = [];
        $isCausedByLock = \false;
        $problems = [];
        foreach ($this->problems as $problem) {
            $problems[] = $problem->getPrettyString($repositorySet, $request, $pool, $isVerbose, $installedMap, $this->learnedPool) . "\n";
            $missingExtensions = array_merge($missingExtensions, $this->getExtensionProblems($problem->getReasons()));
            $isCausedByLock = $isCausedByLock || $problem->isCausedByLock($repositorySet, $request, $pool);
        }
        $i = 1;
        $text = "\n";
        foreach (array_unique($problems) as $problem) {
            $text .= "  Problem " . $i++ . $problem;
        }
        $hints = [];
        if (!$isDevExtraction && (str_contains($text, 'could not be found') || str_contains($text, 'no matching package found'))) {
            $hints[] = "Potential causes:\n - A typo in the package name\n - The package is not available in a stable-enough version according to your minimum-stability setting\n   see <https://getcomposer.org/doc/04-schema.md#minimum-stability> for more details.\n - It's a private package and you forgot to add a custom repository to find it\n\nRead <https://getcomposer.org/doc/articles/troubleshooting.md> for further common problems.";
        }
        if (\count($missingExtensions) > 0) {
            $hints[] = $this->createExtensionHint($missingExtensions);
        }
        if ($isCausedByLock && !$isDevExtraction && !$request->getUpdateAllowTransitiveRootDependencies()) {
            $hints[] = "Use the option --with-all-dependencies (-W) to allow upgrades, downgrades and removals for packages currently locked to specific versions.";
        }
        if (str_contains($text, 'found composer-plugin-api[2.0.0] but it does not match') && str_contains($text, '- ocramius/package-versions')) {
            $hints[] = "<warning>ocramius/package-versions only provides support for Composer 2 in 1.8+, which requires PHP 7.4.</warning>\nIf you can not upgrade PHP you can require <info>composer/package-versions-deprecated</info> to resolve this with PHP 7.0+.";
        }
        if (!class_exists('_ContaoManager\PHPUnit\Framework\TestCase', \false)) {
            if (str_contains($text, 'found composer-plugin-api[2.0.0] but it does not match')) {
                $hints[] = "You are using Composer 2, which some of your plugins seem to be incompatible with. Make sure you update your plugins or report a plugin-issue to ask them to support Composer 2.";
            }
        }
        if (\count($hints) > 0) {
            $text .= "\n" . implode("\n\n", $hints);
        }
        return $text;
    }
    /**
     * @return Problem[]
     */
    public function getProblems(): array
    {
        return $this->problems;
    }
    /**
     * @param string[] $missingExtensions
     */
    private function createExtensionHint(array $missingExtensions): string
    {
        $paths = IniHelper::getAll();
        if ('' === $paths[0]) {
            if (count($paths) === 1) {
                return '';
            }
            array_shift($paths);
        }
        $ignoreExtensionsArguments = implode(" ", array_map(static function ($extension) {
            return "--ignore-platform-req={$extension}";
        }, array_unique($missingExtensions)));
        $text = "To enable extensions, verify that they are enabled in your .ini files:\n    - ";
        $text .= implode("\n    - ", $paths);
        $text .= "\nYou can also run `php --ini` in a terminal to see which files are used by PHP in CLI mode.";
        $text .= "\nAlternatively, you can run Composer with `{$ignoreExtensionsArguments}` to temporarily ignore these required extensions.";
        return $text;
    }
    /**
     * @param Rule[][] $reasonSets
     * @return string[]
     */
    private function getExtensionProblems(array $reasonSets): array
    {
        $missingExtensions = [];
        foreach ($reasonSets as $reasonSet) {
            foreach ($reasonSet as $rule) {
                $required = $rule->getRequiredPackage();
                if (null !== $required && 0 === strpos($required, 'ext-')) {
                    $missingExtensions[$required] = 1;
                }
            }
        }
        return array_keys($missingExtensions);
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer\DependencyResolver;

/**
 * @author Nils Adermann <naderman@naderman.de>
 */
class SolverBugException extends \RuntimeException
{
    public function __construct(string $message)
    {
        parent::__construct($message . "\nThis exception was most likely caused by a bug in Composer.\n" . "Please report the command you ran, the exact error you received, and your composer.json on https://github.com/composer/composer/issues - thank you!\n");
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer\DependencyResolver;

use Composer\Package\AliasPackage;
use Composer\Package\BasePackage;
use Composer\Package\PackageInterface;
use Composer\Semver\CompilingMatcher;
use Composer\Semver\Constraint\Constraint;
use Composer\Util\Platform;
/**
 * @author Nils Adermann <naderman@naderman.de>
 * @author Jordi Boggiano <j.boggiano@seld.be>
 */
class DefaultPolicy implements \Composer\DependencyResolver\PolicyInterface
{
    /** @var bool */
    private $preferStable;
    /** @var bool */
    private $preferLowest;
    /** @var bool */
    private $preferDevOverPrerelease;
    /** @var array<string, string>|null */
    private $preferredVersions;
    /** @var array<int, array<string, non-empty-list<int>>> */
    private $preferredPackageResultCachePerPool;
    /** @var array<int, array<string, int>> */
    private $sortingCachePerPool;
    /**
     * @param array<string, string>|null $preferredVersions Must be an array of package name => normalized version
     */
    public function __construct(bool $preferStable = \false, bool $preferLowest = \false, ?array $preferredVersions = null)
    {
        $this->preferStable = $preferStable;
        $this->preferLowest = $preferLowest;
        $this->preferredVersions = $preferredVersions;
        $this->preferDevOverPrerelease = (bool) Platform::getEnv('COMPOSER_PREFER_DEV_OVER_PRERELEASE');
    }
    /**
     * @param string $operator One of Constraint::STR_OP_*
     *
     * @phpstan-param Constraint::STR_OP_* $operator
     */
    public function versionCompare(PackageInterface $a, PackageInterface $b, string $operator): bool
    {
        if ($this->preferStable && ($stabA = $a->getStability()) !== $stabB = $b->getStability()) {
            if ($this->preferLowest && $this->preferDevOverPrerelease && 'stable' !== $stabA && 'stable' !== $stabB) {
                // When COMPOSER_PREFER_DEV_OVER_PRERELEASE is set and no stable version has been
                // released, "dev" should be considered more stable than "alpha", "beta" or "RC";
                // this allows testing lowest versions with potential fixes applied
                $stabA = 'dev' === $stabA ? 'stable' : $stabA;
                $stabB = 'dev' === $stabB ? 'stable' : $stabB;
            }
            return BasePackage::STABILITIES[$stabA] < BasePackage::STABILITIES[$stabB];
        }
        // dev versions need to be compared as branches via matchSpecific's special treatment, the rest can be optimized with compiling matcher
        if ($a->isDev() && str_starts_with($a->getVersion(), 'dev-') || $b->isDev() && str_starts_with($b->getVersion(), 'dev-')) {
            $constraint = new Constraint($operator, $b->getVersion());
            $version = new Constraint('==', $a->getVersion());
            return $constraint->matchSpecific($version, \true);
        }
        return CompilingMatcher::match(new Constraint($operator, $b->getVersion()), Constraint::OP_EQ, $a->getVersion());
    }
    /**
     * @param  non-empty-list<int>  $literals
     * @return non-empty-list<int>
     */
    public function selectPreferredPackages(\Composer\DependencyResolver\Pool $pool, array $literals, ?string $requiredPackage = null): array
    {
        sort($literals);
        $resultCacheKey = implode(',', $literals) . $requiredPackage;
        $poolId = spl_object_id($pool);
        if (isset($this->preferredPackageResultCachePerPool[$poolId][$resultCacheKey])) {
            return $this->preferredPackageResultCachePerPool[$poolId][$resultCacheKey];
        }
        $packages = $this->groupLiteralsByName($pool, $literals);
        foreach ($packages as &$nameLiterals) {
            usort($nameLiterals, function ($a, $b) use ($pool, $requiredPackage, $poolId): int {
                $cacheKey = 'i' . $a . '.' . $b . $requiredPackage;
                // i prefix -> ignoreReplace = true
                if (isset($this->sortingCachePerPool[$poolId][$cacheKey])) {
                    return $this->sortingCachePerPool[$poolId][$cacheKey];
                }
                return $this->sortingCachePerPool[$poolId][$cacheKey] = $this->compareByPriority($pool, $pool->literalToPackage($a), $pool->literalToPackage($b), $requiredPackage, \true);
            });
        }
        foreach ($packages as &$sortedLiterals) {
            $sortedLiterals = $this->pruneToBestVersion($pool, $sortedLiterals);
            $sortedLiterals = $this->pruneRemoteAliases($pool, $sortedLiterals);
        }
        $selected = array_merge(...array_values($packages));
        // now sort the result across all packages to respect replaces across packages
        usort($selected, function ($a, $b) use ($pool, $requiredPackage, $poolId): int {
            $cacheKey = $a . '.' . $b . $requiredPackage;
            // no i prefix -> ignoreReplace = false
            if (isset($this->sortingCachePerPool[$poolId][$cacheKey])) {
                return $this->sortingCachePerPool[$poolId][$cacheKey];
            }
            return $this->sortingCachePerPool[$poolId][$cacheKey] = $this->compareByPriority($pool, $pool->literalToPackage($a), $pool->literalToPackage($b), $requiredPackage);
        });
        return $this->preferredPackageResultCachePerPool[$poolId][$resultCacheKey] = $selected;
    }
    /**
     * @param  non-empty-list<int> $literals
     * @return non-empty-array<string, non-empty-list<int>>
     */
    protected function groupLiteralsByName(\Composer\DependencyResolver\Pool $pool, array $literals): array
    {
        $packages = [];
        foreach ($literals as $literal) {
            $packageName = $pool->literalToPackage($literal)->getName();
            if (!isset($packages[$packageName])) {
                $packages[$packageName] = [];
            }
            $packages[$packageName][] = $literal;
        }
        return $packages;
    }
    /**
     * @protected
     */
    public function compareByPriority(\Composer\DependencyResolver\Pool $pool, BasePackage $a, BasePackage $b, ?string $requiredPackage = null, bool $ignoreReplace = \false): int
    {
        // prefer aliases to the original package
        if ($a->getName() === $b->getName()) {
            $aAliased = $a instanceof AliasPackage;
            $bAliased = $b instanceof AliasPackage;
            if ($aAliased && !$bAliased) {
                return -1;
                // use a
            }
            if (!$aAliased && $bAliased) {
                return 1;
                // use b
            }
        }
        if (!$ignoreReplace) {
            // return original, not replaced
            if ($this->replaces($a, $b)) {
                return 1;
                // use b
            }
            if ($this->replaces($b, $a)) {
                return -1;
                // use a
            }
            // for replacers not replacing each other, put a higher prio on replacing
            // packages with the same vendor as the required package
            if ($requiredPackage !== null && \false !== $pos = strpos($requiredPackage, '/')) {
                $requiredVendor = substr($requiredPackage, 0, $pos);
                $aIsSameVendor = strpos($a->getName(), $requiredVendor) === 0;
                $bIsSameVendor = strpos($b->getName(), $requiredVendor) === 0;
                if ($bIsSameVendor !== $aIsSameVendor) {
                    return $aIsSameVendor ? -1 : 1;
                }
            }
        }
        // priority equal, sort by package id to make reproducible
        if ($a->id === $b->id) {
            return 0;
        }
        return $a->id < $b->id ? -1 : 1;
    }
    /**
     * Checks if source replaces a package with the same name as target.
     *
     * Replace constraints are ignored. This method should only be used for
     * prioritisation, not for actual constraint verification.
     */
    protected function replaces(BasePackage $source, BasePackage $target): bool
    {
        foreach ($source->getReplaces() as $link) {
            if ($link->getTarget() === $target->getName()) {
                return \true;
            }
        }
        return \false;
    }
    /**
     * @param  list<int> $literals
     * @return list<int>
     */
    protected function pruneToBestVersion(\Composer\DependencyResolver\Pool $pool, array $literals): array
    {
        if ($this->preferredVersions !== null) {
            $name = $pool->literalToPackage($literals[0])->getName();
            if (isset($this->preferredVersions[$name])) {
                $preferredVersion = $this->preferredVersions[$name];
                $bestLiterals = [];
                foreach ($literals as $literal) {
                    if ($pool->literalToPackage($literal)->getVersion() === $preferredVersion) {
                        $bestLiterals[] = $literal;
                    }
                }
                if (\count($bestLiterals) > 0) {
                    return $bestLiterals;
                }
            }
        }
        $operator = $this->preferLowest ? '<' : '>';
        $bestLiterals = [$literals[0]];
        $bestPackage = $pool->literalToPackage($literals[0]);
        foreach ($literals as $i => $literal) {
            if (0 === $i) {
                continue;
            }
            $package = $pool->literalToPackage($literal);
            if ($this->versionCompare($package, $bestPackage, $operator)) {
                $bestPackage = $package;
                $bestLiterals = [$literal];
            } elseif ($this->versionCompare($package, $bestPackage, '==')) {
                $bestLiterals[] = $literal;
            }
        }
        return $bestLiterals;
    }
    /**
     * Assumes that locally aliased (in root package requires) packages take priority over branch-alias ones
     *
     * If no package is a local alias, nothing happens
     *
     * @param  list<int> $literals
     * @return list<int>
     */
    protected function pruneRemoteAliases(\Composer\DependencyResolver\Pool $pool, array $literals): array
    {
        $hasLocalAlias = \false;
        foreach ($literals as $literal) {
            $package = $pool->literalToPackage($literal);
            if ($package instanceof AliasPackage && $package->isRootPackageAlias()) {
                $hasLocalAlias = \true;
                break;
            }
        }
        if (!$hasLocalAlias) {
            return $literals;
        }
        $selected = [];
        foreach ($literals as $literal) {
            $package = $pool->literalToPackage($literal);
            if ($package instanceof AliasPackage && $package->isRootPackageAlias()) {
                $selected[] = $literal;
            }
        }
        return $selected;
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer\DependencyResolver;

/**
 * Wrapper around a Rule which keeps track of the two literals it watches
 *
 * Used by RuleWatchGraph to store rules in two RuleWatchChains.
 *
 * @author Nils Adermann <naderman@naderman.de>
 */
class RuleWatchNode
{
    /** @var int */
    public $watch1;
    /** @var int */
    public $watch2;
    /** @var Rule */
    protected $rule;
    /**
     * Creates a new node watching the first and second literals of the rule.
     *
     * @param Rule $rule The rule to wrap
     */
    public function __construct(\Composer\DependencyResolver\Rule $rule)
    {
        $this->rule = $rule;
        $literals = $rule->getLiterals();
        $literalCount = \count($literals);
        $this->watch1 = $literalCount > 0 ? $literals[0] : 0;
        $this->watch2 = $literalCount > 1 ? $literals[1] : 0;
    }
    /**
     * Places the second watch on the rule's literal, decided at the highest level
     *
     * Useful for learned rules where the literal for the highest rule is most
     * likely to quickly lead to further decisions.
     *
     * @param Decisions $decisions The decisions made so far by the solver
     */
    public function watch2OnHighest(\Composer\DependencyResolver\Decisions $decisions): void
    {
        $literals = $this->rule->getLiterals();
        // if there are only 2 elements, both are being watched anyway
        if (\count($literals) < 3 || $this->rule instanceof \Composer\DependencyResolver\MultiConflictRule) {
            return;
        }
        $watchLevel = 0;
        foreach ($literals as $literal) {
            $level = $decisions->decisionLevel($literal);
            if ($level > $watchLevel) {
                $this->watch2 = $literal;
                $watchLevel = $level;
            }
        }
    }
    /**
     * Returns the rule this node wraps
     */
    public function getRule(): \Composer\DependencyResolver\Rule
    {
        return $this->rule;
    }
    /**
     * Given one watched literal, this method returns the other watched literal
     *
     * @param  int $literal The watched literal that should not be returned
     * @return int A literal
     */
    public function getOtherWatch(int $literal): int
    {
        if ($this->watch1 === $literal) {
            return $this->watch2;
        }
        return $this->watch1;
    }
    /**
     * Moves a watch from one literal to another
     *
     * @param int $from The previously watched literal
     * @param int $to   The literal to be watched now
     */
    public function moveWatch(int $from, int $to): void
    {
        if ($this->watch1 === $from) {
            $this->watch1 = $to;
        } else {
            $this->watch2 = $to;
        }
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer\DependencyResolver;

use Composer\Repository\RepositorySet;
/**
 * @author Nils Adermann <naderman@naderman.de>
 * @implements \IteratorAggregate<Rule>
 * @internal
 * @final
 */
class RuleSet implements \IteratorAggregate, \Countable
{
    // highest priority => lowest number
    public const TYPE_PACKAGE = 0;
    public const TYPE_REQUEST = 1;
    public const TYPE_LEARNED = 4;
    /**
     * READ-ONLY: Lookup table for rule id to rule object
     *
     * @var array<int, Rule>
     */
    public $ruleById = [];
    public const TYPES = [self::TYPE_PACKAGE => 'PACKAGE', self::TYPE_REQUEST => 'REQUEST', self::TYPE_LEARNED => 'LEARNED'];
    /** @var array<self::TYPE_*, Rule[]> */
    protected $rules;
    /** @var 0|positive-int */
    protected $nextRuleId = 0;
    /** @var array<int|string, Rule|Rule[]> */
    protected $rulesByHash = [];
    public function __construct()
    {
        foreach ($this->getTypes() as $type) {
            $this->rules[$type] = [];
        }
    }
    /**
     * @param self::TYPE_* $type
     */
    public function add(\Composer\DependencyResolver\Rule $rule, $type): void
    {
        if (!isset(self::TYPES[$type])) {
            throw new \OutOfBoundsException('Unknown rule type: ' . $type);
        }
        $hash = $rule->getHash();
        // Do not add if rule already exists
        if (isset($this->rulesByHash[$hash])) {
            $potentialDuplicates = $this->rulesByHash[$hash];
            if (\is_array($potentialDuplicates)) {
                foreach ($potentialDuplicates as $potentialDuplicate) {
                    if ($rule->equals($potentialDuplicate)) {
                        return;
                    }
                }
            } else if ($rule->equals($potentialDuplicates)) {
                return;
            }
        }
        if (!isset($this->rules[$type])) {
            $this->rules[$type] = [];
        }
        $this->rules[$type][] = $rule;
        $this->ruleById[$this->nextRuleId] = $rule;
        $rule->setType($type);
        $this->nextRuleId++;
        if (!isset($this->rulesByHash[$hash])) {
            $this->rulesByHash[$hash] = $rule;
        } elseif (\is_array($this->rulesByHash[$hash])) {
            $this->rulesByHash[$hash][] = $rule;
        } else {
            $originalRule = $this->rulesByHash[$hash];
            $this->rulesByHash[$hash] = [$originalRule, $rule];
        }
    }
    public function count(): int
    {
        return $this->nextRuleId;
    }
    public function ruleById(int $id): \Composer\DependencyResolver\Rule
    {
        return $this->ruleById[$id];
    }
    /** @return array<self::TYPE_*, Rule[]> */
    public function getRules(): array
    {
        return $this->rules;
    }
    public function getIterator(): \Composer\DependencyResolver\RuleSetIterator
    {
        return new \Composer\DependencyResolver\RuleSetIterator($this->getRules());
    }
    /**
     * @param  self::TYPE_*|array<self::TYPE_*> $types
     */
    public function getIteratorFor($types): \Composer\DependencyResolver\RuleSetIterator
    {
        if (!\is_array($types)) {
            $types = [$types];
        }
        $allRules = $this->getRules();
        /** @var array<self::TYPE_*, Rule[]> $rules */
        $rules = [];
        foreach ($types as $type) {
            $rules[$type] = $allRules[$type];
        }
        return new \Composer\DependencyResolver\RuleSetIterator($rules);
    }
    /**
     * @param array<self::TYPE_*>|self::TYPE_* $types
     */
    public function getIteratorWithout($types): \Composer\DependencyResolver\RuleSetIterator
    {
        if (!\is_array($types)) {
            $types = [$types];
        }
        $rules = $this->getRules();
        foreach ($types as $type) {
            unset($rules[$type]);
        }
        return new \Composer\DependencyResolver\RuleSetIterator($rules);
    }
    /**
     * @return array{self::TYPE_PACKAGE, self::TYPE_REQUEST, self::TYPE_LEARNED}
     */
    public function getTypes(): array
    {
        $types = self::TYPES;
        return array_keys($types);
    }
    public function getPrettyString(?RepositorySet $repositorySet = null, ?\Composer\DependencyResolver\Request $request = null, ?\Composer\DependencyResolver\Pool $pool = null, bool $isVerbose = \false): string
    {
        $string = "\n";
        foreach ($this->rules as $type => $rules) {
            $string .= str_pad(self::TYPES[$type], 8, ' ') . ": ";
            foreach ($rules as $rule) {
                $string .= ($repositorySet !== null && $request !== null && $pool !== null ? $rule->getPrettyString($repositorySet, $request, $pool, $isVerbose) : $rule) . "\n";
            }
            $string .= "\n\n";
        }
        return $string;
    }
    public function __toString(): string
    {
        return $this->getPrettyString();
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer\DependencyResolver;

use Composer\Advisory\PartialSecurityAdvisory;
use Composer\Advisory\SecurityAdvisory;
use Composer\Package\BasePackage;
use Composer\Package\Version\VersionParser;
use Composer\Semver\CompilingMatcher;
use Composer\Semver\Constraint\ConstraintInterface;
use Composer\Semver\Constraint\Constraint;
/**
 * A package pool contains all packages for dependency resolution
 *
 * @author Nils Adermann <naderman@naderman.de>
 * @author Jordi Boggiano <j.boggiano@seld.be>
 */
class Pool implements \Countable
{
    /** @var BasePackage[] */
    protected $packages = [];
    /** @var array<string, BasePackage[]> */
    protected $packageByName = [];
    /** @var VersionParser */
    protected $versionParser;
    /** @var array<string, array<string, BasePackage[]>> */
    protected $providerCache = [];
    /** @var BasePackage[] */
    protected $unacceptableFixedOrLockedPackages;
    /** @var array<string, array<string, string>> Map of package name => normalized version => pretty version */
    protected $removedVersions = [];
    /** @var array<string, array<string, string>> Map of package object hash => removed normalized versions => removed pretty version */
    protected $removedVersionsByPackage = [];
    /** @var array<string, array<string, array<SecurityAdvisory|PartialSecurityAdvisory>>> Map of package name => normalized version => security advisories */
    private $securityRemovedVersions = [];
    /** @var array<string, array<string, string>> Map of package name => normalized version => pretty version */
    private $abandonedRemovedVersions = [];
    /**
     * @param BasePackage[] $packages
     * @param BasePackage[] $unacceptableFixedOrLockedPackages
     * @param array<string, array<string, string>> $removedVersions
     * @param array<string, array<string, string>> $removedVersionsByPackage
     * @param array<string, array<string, array<SecurityAdvisory|PartialSecurityAdvisory>>> $securityRemovedVersions
     * @param array<string, array<string, string>> $abandonedRemovedVersions
     */
    public function __construct(array $packages = [], array $unacceptableFixedOrLockedPackages = [], array $removedVersions = [], array $removedVersionsByPackage = [], array $securityRemovedVersions = [], array $abandonedRemovedVersions = [])
    {
        $this->versionParser = new VersionParser();
        $this->setPackages($packages);
        $this->unacceptableFixedOrLockedPackages = $unacceptableFixedOrLockedPackages;
        $this->removedVersions = $removedVersions;
        $this->removedVersionsByPackage = $removedVersionsByPackage;
        $this->securityRemovedVersions = $securityRemovedVersions;
        $this->abandonedRemovedVersions = $abandonedRemovedVersions;
    }
    /**
     * @return array<string, string>
     */
    public function getRemovedVersions(string $name, ConstraintInterface $constraint): array
    {
        if (!isset($this->removedVersions[$name])) {
            return [];
        }
        $result = [];
        foreach ($this->removedVersions[$name] as $version => $prettyVersion) {
            if ($constraint->matches(new Constraint('==', $version))) {
                $result[$version] = $prettyVersion;
            }
        }
        return $result;
    }
    /**
     * @return array<string, array<string, string>>
     */
    public function getAllRemovedVersions(): array
    {
        return $this->removedVersions;
    }
    /**
     * @return array<string, string>
     */
    public function getRemovedVersionsByPackage(string $objectHash): array
    {
        if (!isset($this->removedVersionsByPackage[$objectHash])) {
            return [];
        }
        return $this->removedVersionsByPackage[$objectHash];
    }
    /**
     * @return array<string, array<string, string>>
     */
    public function getAllRemovedVersionsByPackage(): array
    {
        return $this->removedVersionsByPackage;
    }
    public function isSecurityRemovedPackageVersion(string $packageName, ?ConstraintInterface $constraint): bool
    {
        foreach ($this->securityRemovedVersions[$packageName] ?? [] as $version => $packageWithSecurityAdvisories) {
            if ($constraint !== null && $constraint->matches(new Constraint('==', $version))) {
                return \true;
            }
        }
        return \false;
    }
    /**
     * @return string[]
     */
    public function getSecurityAdvisoryIdentifiersForPackageVersion(string $packageName, ?ConstraintInterface $constraint): array
    {
        foreach ($this->securityRemovedVersions[$packageName] ?? [] as $version => $packageWithSecurityAdvisories) {
            if ($constraint !== null && $constraint->matches(new Constraint('==', $version))) {
                return array_map(static function ($advisory) {
                    return $advisory->advisoryId;
                }, $packageWithSecurityAdvisories);
            }
        }
        return [];
    }
    public function isAbandonedRemovedPackageVersion(string $packageName, ?ConstraintInterface $constraint): bool
    {
        foreach ($this->abandonedRemovedVersions[$packageName] ?? [] as $version => $prettyVersion) {
            if ($constraint !== null && $constraint->matches(new Constraint('==', $version))) {
                return \true;
            }
        }
        return \false;
    }
    /**
     * @return array<string, array<string, array<SecurityAdvisory|PartialSecurityAdvisory>>>
     */
    public function getAllSecurityRemovedPackageVersions(): array
    {
        return $this->securityRemovedVersions;
    }
    /**
     * @return array<string, array<string, string>>
     */
    public function getAllAbandonedRemovedPackageVersions(): array
    {
        return $this->abandonedRemovedVersions;
    }
    /**
     * @param BasePackage[] $packages
     */
    private function setPackages(array $packages): void
    {
        $id = 1;
        foreach ($packages as $package) {
            $this->packages[] = $package;
            $package->id = $id++;
            foreach ($package->getNames() as $provided) {
                $this->packageByName[$provided][] = $package;
            }
        }
    }
    /**
     * @return BasePackage[]
     */
    public function getPackages(): array
    {
        return $this->packages;
    }
    /**
     * Retrieves the package object for a given package id.
     */
    public function packageById(int $id): BasePackage
    {
        return $this->packages[$id - 1];
    }
    /**
     * Returns how many packages have been loaded into the pool
     */
    public function count(): int
    {
        return \count($this->packages);
    }
    /**
     * Searches all packages providing the given package name and match the constraint
     *
     * @param string $name The package name to be searched for
     * @param ?ConstraintInterface $constraint A constraint that all returned
     *                                         packages must match or null to return all
     * @return BasePackage[] A set of packages
     */
    public function whatProvides(string $name, ?ConstraintInterface $constraint = null): array
    {
        $key = (string) $constraint;
        if (isset($this->providerCache[$name][$key])) {
            return $this->providerCache[$name][$key];
        }
        return $this->providerCache[$name][$key] = $this->computeWhatProvides($name, $constraint);
    }
    /**
     * @param  string               $name       The package name to be searched for
     * @param  ?ConstraintInterface $constraint A constraint that all returned
     *                                          packages must match or null to return all
     * @return BasePackage[]
     */
    private function computeWhatProvides(string $name, ?ConstraintInterface $constraint = null): array
    {
        if (!isset($this->packageByName[$name])) {
            return [];
        }
        $matches = [];
        foreach ($this->packageByName[$name] as $candidate) {
            if ($this->match($candidate, $name, $constraint)) {
                $matches[] = $candidate;
            }
        }
        return $matches;
    }
    public function literalToPackage(int $literal): BasePackage
    {
        $packageId = abs($literal);
        return $this->packageById($packageId);
    }
    /**
     * @param array<int, BasePackage> $installedMap
     */
    public function literalToPrettyString(int $literal, array $installedMap): string
    {
        $package = $this->literalToPackage($literal);
        if (isset($installedMap[$package->id])) {
            $prefix = $literal > 0 ? 'keep' : 'remove';
        } else {
            $prefix = $literal > 0 ? 'install' : 'don\'t install';
        }
        return $prefix . ' ' . $package->getPrettyString();
    }
    /**
     * Checks if the package matches the given constraint directly or through
     * provided or replaced packages
     *
     * @param  string              $name       Name of the package to be matched
     */
    public function match(BasePackage $candidate, string $name, ?ConstraintInterface $constraint = null): bool
    {
        $candidateName = $candidate->getName();
        $candidateVersion = $candidate->getVersion();
        if ($candidateName === $name) {
            return $constraint === null || CompilingMatcher::match($constraint, Constraint::OP_EQ, $candidateVersion);
        }
        $provides = $candidate->getProvides();
        $replaces = $candidate->getReplaces();
        // aliases create multiple replaces/provides for one target so they can not use the shortcut below
        if (isset($replaces[0]) || isset($provides[0])) {
            foreach ($provides as $link) {
                if ($link->getTarget() === $name && ($constraint === null || $constraint->matches($link->getConstraint()))) {
                    return \true;
                }
            }
            foreach ($replaces as $link) {
                if ($link->getTarget() === $name && ($constraint === null || $constraint->matches($link->getConstraint()))) {
                    return \true;
                }
            }
            return \false;
        }
        if (isset($provides[$name]) && ($constraint === null || $constraint->matches($provides[$name]->getConstraint()))) {
            return \true;
        }
        if (isset($replaces[$name]) && ($constraint === null || $constraint->matches($replaces[$name]->getConstraint()))) {
            return \true;
        }
        return \false;
    }
    public function isUnacceptableFixedOrLockedPackage(BasePackage $package): bool
    {
        return \in_array($package, $this->unacceptableFixedOrLockedPackages, \true);
    }
    /**
     * @return BasePackage[]
     */
    public function getUnacceptableFixedOrLockedPackages(): array
    {
        return $this->unacceptableFixedOrLockedPackages;
    }
    public function __toString(): string
    {
        $str = "Pool:\n";
        foreach ($this->packages as $package) {
            $str .= '- ' . str_pad((string) $package->id, 6, ' ', \STR_PAD_LEFT) . ': ' . $package->getName() . "\n";
        }
        return $str;
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer\DependencyResolver;

/**
 * @author Nils Adermann <naderman@naderman.de>
 *
 * MultiConflictRule([A, B, C]) acts as Rule([-A, -B]), Rule([-A, -C]), Rule([-B, -C])
 */
class MultiConflictRule extends \Composer\DependencyResolver\Rule
{
    /** @var non-empty-list<int> */
    protected $literals;
    /**
     * @param non-empty-list<int> $literals
     */
    public function __construct(array $literals, $reason, $reasonData)
    {
        parent::__construct($reason, $reasonData);
        if (\count($literals) < 3) {
            throw new \RuntimeException("multi conflict rule requires at least 3 literals");
        }
        // sort all packages ascending by id
        sort($literals);
        $this->literals = $literals;
    }
    /**
     * @return non-empty-list<int>
     */
    public function getLiterals(): array
    {
        return $this->literals;
    }
    /**
     * @inheritDoc
     */
    public function getHash()
    {
        $data = unpack('ihash', (string) hash(\PHP_VERSION_ID > 80100 ? 'xxh3' : 'sha1', 'c:' . implode(',', $this->literals), \true));
        if (\false === $data) {
            throw new \RuntimeException('Failed unpacking: ' . implode(', ', $this->literals));
        }
        return $data['hash'];
    }
    /**
     * Checks if this rule is equal to another one
     *
     * Ignores whether either of the rules is disabled.
     *
     * @param  Rule $rule The rule to check against
     * @return bool Whether the rules are equal
     */
    public function equals(\Composer\DependencyResolver\Rule $rule): bool
    {
        if ($rule instanceof \Composer\DependencyResolver\MultiConflictRule) {
            return $this->literals === $rule->getLiterals();
        }
        return \false;
    }
    public function isAssertion(): bool
    {
        return \false;
    }
    /**
     * @return never
     * @throws \RuntimeException
     */
    public function disable(): void
    {
        throw new \RuntimeException("Disabling multi conflict rules is not possible. Please contact composer at https://github.com/composer/composer to let us debug what lead to this situation.");
    }
    /**
     * Formats a rule as a string of the format (Literal1|Literal2|...)
     */
    public function __toString(): string
    {
        // TODO multi conflict?
        $result = $this->isDisabled() ? 'disabled(multi(' : '(multi(';
        foreach ($this->literals as $i => $literal) {
            if ($i !== 0) {
                $result .= '|';
            }
            $result .= $literal;
        }
        $result .= '))';
        return $result;
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer\DependencyResolver;

use Composer\Package\BasePackage;
use Composer\Package\PackageInterface;
use Composer\Repository\LockArrayRepository;
use Composer\Semver\Constraint\ConstraintInterface;
use Composer\Semver\Constraint\MatchAllConstraint;
/**
 * @author Nils Adermann <naderman@naderman.de>
 */
class Request
{
    /**
     * Identifies a partial update for listed packages only, all dependencies will remain at locked versions
     */
    public const UPDATE_ONLY_LISTED = 0;
    /**
     * Identifies a partial update for listed packages and recursively all their dependencies, however dependencies
     * also directly required by the root composer.json and their dependencies will remain at the locked version.
     */
    public const UPDATE_LISTED_WITH_TRANSITIVE_DEPS_NO_ROOT_REQUIRE = 1;
    /**
     * Identifies a partial update for listed packages and recursively all their dependencies, even dependencies
     * also directly required by the root composer.json will be updated.
     */
    public const UPDATE_LISTED_WITH_TRANSITIVE_DEPS = 2;
    /** @var ?LockArrayRepository */
    protected $lockedRepository;
    /** @var array<string, ConstraintInterface> */
    protected $requires = [];
    /** @var array<string, BasePackage> */
    protected $fixedPackages = [];
    /** @var array<string, BasePackage> */
    protected $lockedPackages = [];
    /** @var array<string, BasePackage> */
    protected $fixedLockedPackages = [];
    /** @var array<string> */
    protected $updateAllowList = [];
    /** @var false|self::UPDATE_* */
    protected $updateAllowTransitiveDependencies = \false;
    /** @var non-empty-list<string>|null */
    private $restrictedPackages = null;
    public function __construct(?LockArrayRepository $lockedRepository = null)
    {
        $this->lockedRepository = $lockedRepository;
    }
    public function requireName(string $packageName, ?ConstraintInterface $constraint = null): void
    {
        $packageName = strtolower($packageName);
        if ($constraint === null) {
            $constraint = new MatchAllConstraint();
        }
        if (isset($this->requires[$packageName])) {
            throw new \LogicException('Overwriting requires seems like a bug (' . $packageName . ' ' . $this->requires[$packageName]->getPrettyString() . ' => ' . $constraint->getPrettyString() . ', check why it is happening, might be a root alias');
        }
        $this->requires[$packageName] = $constraint;
    }
    /**
     * Mark a package as currently present and having to remain installed
     *
     * This is used for platform packages which cannot be modified by Composer. A rule enforcing their installation is
     * generated for dependency resolution. Partial updates with dependencies cannot in any way modify these packages.
     */
    public function fixPackage(BasePackage $package): void
    {
        $this->fixedPackages[spl_object_hash($package)] = $package;
    }
    /**
     * Mark a package as locked to a specific version but removable
     *
     * This is used for lock file packages which need to be treated similar to fixed packages by the pool builder in
     * that by default they should really only have the currently present version loaded and no remote alternatives.
     *
     * However unlike fixed packages there will not be a special rule enforcing their installation for the solver, so
     * if nothing requires these packages they will be removed. Additionally in a partial update these packages can be
     * unlocked, meaning other versions can be installed if explicitly requested as part of the update.
     */
    public function lockPackage(BasePackage $package): void
    {
        $this->lockedPackages[spl_object_hash($package)] = $package;
    }
    /**
     * Marks a locked package fixed. So it's treated irremovable like a platform package.
     *
     * This is necessary for the composer install step which verifies the lock file integrity and should not allow
     * removal of any packages. At the same time lock packages there cannot simply be marked fixed, as error reporting
     * would then report them as platform packages, so this still marks them as locked packages at the same time.
     */
    public function fixLockedPackage(BasePackage $package): void
    {
        $this->fixedPackages[spl_object_hash($package)] = $package;
        $this->fixedLockedPackages[spl_object_hash($package)] = $package;
    }
    public function unlockPackage(BasePackage $package): void
    {
        unset($this->lockedPackages[spl_object_hash($package)]);
    }
    /**
     * @param array<string> $updateAllowList
     * @param false|self::UPDATE_* $updateAllowTransitiveDependencies
     */
    public function setUpdateAllowList(array $updateAllowList, $updateAllowTransitiveDependencies): void
    {
        $this->updateAllowList = $updateAllowList;
        $this->updateAllowTransitiveDependencies = $updateAllowTransitiveDependencies;
    }
    /**
     * @return array<string>
     */
    public function getUpdateAllowList(): array
    {
        return $this->updateAllowList;
    }
    public function getUpdateAllowTransitiveDependencies(): bool
    {
        return $this->updateAllowTransitiveDependencies !== self::UPDATE_ONLY_LISTED;
    }
    public function getUpdateAllowTransitiveRootDependencies(): bool
    {
        return $this->updateAllowTransitiveDependencies === self::UPDATE_LISTED_WITH_TRANSITIVE_DEPS;
    }
    /**
     * @return array<string, ConstraintInterface>
     */
    public function getRequires(): array
    {
        return $this->requires;
    }
    /**
     * @return array<string, BasePackage>
     */
    public function getFixedPackages(): array
    {
        return $this->fixedPackages;
    }
    public function isFixedPackage(BasePackage $package): bool
    {
        return isset($this->fixedPackages[spl_object_hash($package)]);
    }
    /**
     * @return array<string, BasePackage>
     */
    public function getLockedPackages(): array
    {
        return $this->lockedPackages;
    }
    public function isLockedPackage(PackageInterface $package): bool
    {
        return isset($this->lockedPackages[spl_object_hash($package)]) || isset($this->fixedLockedPackages[spl_object_hash($package)]);
    }
    /**
     * @return array<string, BasePackage>
     */
    public function getFixedOrLockedPackages(): array
    {
        return array_merge($this->fixedPackages, $this->lockedPackages);
    }
    /**
     * @return ($packageIds is true ? array<int, BasePackage> : array<string, BasePackage>)
     *
     * @TODO look into removing the packageIds option, the only place true is used
     *       is for the installed map in the solver problems.
     *       Some locked packages may not be in the pool,
     *       so they have a package->id of -1
     */
    public function getPresentMap(bool $packageIds = \false): array
    {
        $presentMap = [];
        if ($this->lockedRepository !== null) {
            foreach ($this->lockedRepository->getPackages() as $package) {
                $presentMap[$packageIds ? $package->getId() : spl_object_hash($package)] = $package;
            }
        }
        foreach ($this->fixedPackages as $package) {
            $presentMap[$packageIds ? $package->getId() : spl_object_hash($package)] = $package;
        }
        return $presentMap;
    }
    /**
     * @return array<int, BasePackage>
     */
    public function getFixedPackagesMap(): array
    {
        $fixedPackagesMap = [];
        foreach ($this->fixedPackages as $package) {
            $fixedPackagesMap[$package->getId()] = $package;
        }
        return $fixedPackagesMap;
    }
    public function getLockedRepository(): ?LockArrayRepository
    {
        return $this->lockedRepository;
    }
    /**
     * Restricts the pool builder from loading other packages than those listed here
     *
     * @param non-empty-list<string> $names
     */
    public function restrictPackages(array $names): void
    {
        $this->restrictedPackages = $names;
    }
    /**
     * @return list<string>
     */
    public function getRestrictedPackages(): ?array
    {
        return $this->restrictedPackages;
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer\DependencyResolver;

use Composer\Package\AliasPackage;
use Composer\Package\BasePackage;
use Composer\Package\Version\VersionParser;
use Composer\Semver\CompilingMatcher;
use Composer\Semver\Constraint\ConstraintInterface;
use Composer\Semver\Constraint\Constraint;
use Composer\Semver\Constraint\MultiConstraint;
use Composer\Semver\Intervals;
/**
 * Optimizes a given pool
 *
 * @author Yanick Witschi <yanick.witschi@terminal42.ch>
 */
class PoolOptimizer
{
    /**
     * @var PolicyInterface
     */
    private $policy;
    /**
     * @var array<int, true>
     */
    private $irremovablePackages = [];
    /**
     * @var array<string, array<string, ConstraintInterface>>
     */
    private $requireConstraintsPerPackage = [];
    /**
     * @var array<string, array<string, ConstraintInterface>>
     */
    private $conflictConstraintsPerPackage = [];
    /**
     * @var array<int, true>
     */
    private $packagesToRemove = [];
    /**
     * @var array<int, BasePackage[]>
     */
    private $aliasesPerPackage = [];
    /**
     * @var array<string, array<string, string>>
     */
    private $removedVersionsByPackage = [];
    public function __construct(\Composer\DependencyResolver\PolicyInterface $policy)
    {
        $this->policy = $policy;
    }
    public function optimize(\Composer\DependencyResolver\Request $request, \Composer\DependencyResolver\Pool $pool): \Composer\DependencyResolver\Pool
    {
        $this->prepare($request, $pool);
        $this->optimizeByIdenticalDependencies($request, $pool);
        $this->optimizeImpossiblePackagesAway($request, $pool);
        $optimizedPool = $this->applyRemovalsToPool($pool);
        // No need to run this recursively at the moment
        // because the current optimizations cannot provide
        // even more gains when ran again. Might change
        // in the future with additional optimizations.
        $this->irremovablePackages = [];
        $this->requireConstraintsPerPackage = [];
        $this->conflictConstraintsPerPackage = [];
        $this->packagesToRemove = [];
        $this->aliasesPerPackage = [];
        $this->removedVersionsByPackage = [];
        return $optimizedPool;
    }
    private function prepare(\Composer\DependencyResolver\Request $request, \Composer\DependencyResolver\Pool $pool): void
    {
        $irremovablePackageConstraintGroups = [];
        // Mark fixed or locked packages as irremovable
        foreach ($request->getFixedOrLockedPackages() as $package) {
            $irremovablePackageConstraintGroups[$package->getName()][] = new Constraint('==', $package->getVersion());
        }
        // Extract requested package requirements
        foreach ($request->getRequires() as $require => $constraint) {
            $this->extractRequireConstraintsPerPackage($require, $constraint);
        }
        // First pass over all packages to extract information and mark package constraints irremovable
        foreach ($pool->getPackages() as $package) {
            // Extract package requirements
            foreach ($package->getRequires() as $link) {
                $this->extractRequireConstraintsPerPackage($link->getTarget(), $link->getConstraint());
            }
            // Extract package conflicts
            foreach ($package->getConflicts() as $link) {
                $this->extractConflictConstraintsPerPackage($link->getTarget(), $link->getConstraint());
            }
            // Keep track of alias packages for every package so if either the alias or aliased is kept
            // we keep the others as they are a unit of packages really
            if ($package instanceof AliasPackage) {
                $this->aliasesPerPackage[$package->getAliasOf()->id][] = $package;
            }
        }
        $irremovablePackageConstraints = [];
        foreach ($irremovablePackageConstraintGroups as $packageName => $constraints) {
            $irremovablePackageConstraints[$packageName] = 1 === \count($constraints) ? $constraints[0] : new MultiConstraint($constraints, \false);
        }
        unset($irremovablePackageConstraintGroups);
        // Mark the packages as irremovable based on the constraints
        foreach ($pool->getPackages() as $package) {
            if (!isset($irremovablePackageConstraints[$package->getName()])) {
                continue;
            }
            if (CompilingMatcher::match($irremovablePackageConstraints[$package->getName()], Constraint::OP_EQ, $package->getVersion())) {
                $this->markPackageIrremovable($package);
            }
        }
    }
    private function markPackageIrremovable(BasePackage $package): void
    {
        $this->irremovablePackages[$package->id] = \true;
        if ($package instanceof AliasPackage) {
            // recursing here so aliasesPerPackage for the aliasOf can be checked
            // and all its aliases marked as irremovable as well
            $this->markPackageIrremovable($package->getAliasOf());
        }
        if (isset($this->aliasesPerPackage[$package->id])) {
            foreach ($this->aliasesPerPackage[$package->id] as $aliasPackage) {
                $this->irremovablePackages[$aliasPackage->id] = \true;
            }
        }
    }
    /**
     * @return Pool Optimized pool
     */
    private function applyRemovalsToPool(\Composer\DependencyResolver\Pool $pool): \Composer\DependencyResolver\Pool
    {
        $packages = [];
        $removedVersions = [];
        foreach ($pool->getPackages() as $package) {
            if (!isset($this->packagesToRemove[$package->id])) {
                $packages[] = $package;
            } else {
                $removedVersions[$package->getName()][$package->getVersion()] = $package->getPrettyVersion();
            }
        }
        $optimizedPool = new \Composer\DependencyResolver\Pool($packages, $pool->getUnacceptableFixedOrLockedPackages(), $removedVersions, $this->removedVersionsByPackage, $pool->getAllSecurityRemovedPackageVersions(), $pool->getAllAbandonedRemovedPackageVersions());
        return $optimizedPool;
    }
    private function optimizeByIdenticalDependencies(\Composer\DependencyResolver\Request $request, \Composer\DependencyResolver\Pool $pool): void
    {
        $identicalDefinitionsPerPackage = [];
        $packageIdenticalDefinitionLookup = [];
        foreach ($pool->getPackages() as $package) {
            // If that package was already marked irremovable, we can skip
            // the entire process for it
            if (isset($this->irremovablePackages[$package->id])) {
                continue;
            }
            $this->markPackageForRemoval($package->id);
            $dependencyHash = $this->calculateDependencyHash($package);
            foreach ($package->getNames(\false) as $packageName) {
                if (!isset($this->requireConstraintsPerPackage[$packageName])) {
                    continue;
                }
                foreach ($this->requireConstraintsPerPackage[$packageName] as $requireConstraint) {
                    $groupHashParts = [];
                    if (CompilingMatcher::match($requireConstraint, Constraint::OP_EQ, $package->getVersion())) {
                        $groupHashParts[] = 'require:' . (string) $requireConstraint;
                    }
                    if (\count($package->getReplaces()) > 0) {
                        foreach ($package->getReplaces() as $link) {
                            if (CompilingMatcher::match($link->getConstraint(), Constraint::OP_EQ, $package->getVersion())) {
                                // Use the same hash part as the regular require hash because that's what the replacement does
                                $groupHashParts[] = 'require:' . (string) $link->getConstraint();
                            }
                        }
                    }
                    if (isset($this->conflictConstraintsPerPackage[$packageName])) {
                        foreach ($this->conflictConstraintsPerPackage[$packageName] as $conflictConstraint) {
                            if (CompilingMatcher::match($conflictConstraint, Constraint::OP_EQ, $package->getVersion())) {
                                $groupHashParts[] = 'conflict:' . (string) $conflictConstraint;
                            }
                        }
                    }
                    if (0 === \count($groupHashParts)) {
                        continue;
                    }
                    $groupHash = implode('', $groupHashParts);
                    $identicalDefinitionsPerPackage[$packageName][$groupHash][$dependencyHash][] = $package;
                    $packageIdenticalDefinitionLookup[$package->id][$packageName] = ['groupHash' => $groupHash, 'dependencyHash' => $dependencyHash];
                }
            }
        }
        foreach ($identicalDefinitionsPerPackage as $constraintGroups) {
            foreach ($constraintGroups as $constraintGroup) {
                foreach ($constraintGroup as $packages) {
                    // Only one package in this constraint group has the same requirements, we're not allowed to remove that package
                    if (1 === \count($packages)) {
                        $this->keepPackage($packages[0], $identicalDefinitionsPerPackage, $packageIdenticalDefinitionLookup);
                        continue;
                    }
                    // Otherwise we find out which one is the preferred package in this constraint group which is
                    // then not allowed to be removed either
                    $literals = [];
                    foreach ($packages as $package) {
                        $literals[] = $package->id;
                    }
                    foreach ($this->policy->selectPreferredPackages($pool, $literals) as $preferredLiteral) {
                        $this->keepPackage($pool->literalToPackage($preferredLiteral), $identicalDefinitionsPerPackage, $packageIdenticalDefinitionLookup);
                    }
                }
            }
        }
    }
    private function calculateDependencyHash(BasePackage $package): string
    {
        $hash = '';
        $hashRelevantLinks = ['requires' => $package->getRequires(), 'conflicts' => $package->getConflicts(), 'replaces' => $package->getReplaces(), 'provides' => $package->getProvides()];
        foreach ($hashRelevantLinks as $key => $links) {
            if (0 === \count($links)) {
                continue;
            }
            // start new hash section
            $hash .= $key . ':';
            $subhash = [];
            foreach ($links as $link) {
                // To get the best dependency hash matches we should use Intervals::compactConstraint() here.
                // However, the majority of projects are going to specify their constraints already pretty
                // much in the best variant possible. In other words, we'd be wasting time here and it would actually hurt
                // performance more than the additional few packages that could be filtered out would benefit the process.
                $subhash[$link->getTarget()] = (string) $link->getConstraint();
            }
            // Sort for best result
            ksort($subhash);
            foreach ($subhash as $target => $constraint) {
                $hash .= $target . '@' . $constraint;
            }
        }
        return $hash;
    }
    private function markPackageForRemoval(int $id): void
    {
        // We are not allowed to remove packages if they have been marked as irremovable
        if (isset($this->irremovablePackages[$id])) {
            throw new \LogicException('Attempted removing a package which was previously marked irremovable');
        }
        $this->packagesToRemove[$id] = \true;
    }
    /**
     * @param array<string, array<string, array<string, list<BasePackage>>>> $identicalDefinitionsPerPackage
     * @param array<int, array<string, array{groupHash: string, dependencyHash: string}>> $packageIdenticalDefinitionLookup
     */
    private function keepPackage(BasePackage $package, array $identicalDefinitionsPerPackage, array $packageIdenticalDefinitionLookup): void
    {
        // Already marked to keep
        if (!isset($this->packagesToRemove[$package->id])) {
            return;
        }
        unset($this->packagesToRemove[$package->id]);
        if ($package instanceof AliasPackage) {
            // recursing here so aliasesPerPackage for the aliasOf can be checked
            // and all its aliases marked to be kept as well
            $this->keepPackage($package->getAliasOf(), $identicalDefinitionsPerPackage, $packageIdenticalDefinitionLookup);
        }
        // record all the versions of the package group so we can list them later in Problem output
        foreach ($package->getNames(\false) as $name) {
            if (isset($packageIdenticalDefinitionLookup[$package->id][$name])) {
                $packageGroupPointers = $packageIdenticalDefinitionLookup[$package->id][$name];
                $packageGroup = $identicalDefinitionsPerPackage[$name][$packageGroupPointers['groupHash']][$packageGroupPointers['dependencyHash']];
                foreach ($packageGroup as $pkg) {
                    if ($pkg instanceof AliasPackage && $pkg->getPrettyVersion() === VersionParser::DEFAULT_BRANCH_ALIAS) {
                        $pkg = $pkg->getAliasOf();
                    }
                    $this->removedVersionsByPackage[spl_object_hash($package)][$pkg->getVersion()] = $pkg->getPrettyVersion();
                }
            }
        }
        if (isset($this->aliasesPerPackage[$package->id])) {
            foreach ($this->aliasesPerPackage[$package->id] as $aliasPackage) {
                unset($this->packagesToRemove[$aliasPackage->id]);
                // record all the versions of the package group so we can list them later in Problem output
                foreach ($aliasPackage->getNames(\false) as $name) {
                    if (isset($packageIdenticalDefinitionLookup[$aliasPackage->id][$name])) {
                        $packageGroupPointers = $packageIdenticalDefinitionLookup[$aliasPackage->id][$name];
                        $packageGroup = $identicalDefinitionsPerPackage[$name][$packageGroupPointers['groupHash']][$packageGroupPointers['dependencyHash']];
                        foreach ($packageGroup as $pkg) {
                            if ($pkg instanceof AliasPackage && $pkg->getPrettyVersion() === VersionParser::DEFAULT_BRANCH_ALIAS) {
                                $pkg = $pkg->getAliasOf();
                            }
                            $this->removedVersionsByPackage[spl_object_hash($aliasPackage)][$pkg->getVersion()] = $pkg->getPrettyVersion();
                        }
                    }
                }
            }
        }
    }
    /**
     * Use the list of locked packages to constrain the loaded packages
     * This will reduce packages with significant numbers of historical versions to a smaller number
     * and reduce the resulting rule set that is generated
     */
    private function optimizeImpossiblePackagesAway(\Composer\DependencyResolver\Request $request, \Composer\DependencyResolver\Pool $pool): void
    {
        if (\count($request->getLockedPackages()) === 0) {
            return;
        }
        $packageIndex = [];
        foreach ($pool->getPackages() as $package) {
            $id = $package->id;
            // Do not remove irremovable packages
            if (isset($this->irremovablePackages[$id])) {
                continue;
            }
            // Do not remove a package aliased by another package, nor aliases
            if (isset($this->aliasesPerPackage[$id]) || $package instanceof AliasPackage) {
                continue;
            }
            // Do not remove locked packages
            if ($request->isFixedPackage($package) || $request->isLockedPackage($package)) {
                continue;
            }
            $packageIndex[$package->getName()][$package->id] = $package;
        }
        foreach ($request->getLockedPackages() as $package) {
            // If this locked package is no longer required by root or anything in the pool, it may get uninstalled so do not apply its requirements
            // In a case where a requirement WERE to appear in the pool by a package that would not be used, it would've been unlocked and so not filtered still
            $isUnusedPackage = \true;
            foreach ($package->getNames(\false) as $packageName) {
                if (isset($this->requireConstraintsPerPackage[$packageName])) {
                    $isUnusedPackage = \false;
                    break;
                }
            }
            if ($isUnusedPackage) {
                continue;
            }
            foreach ($package->getRequires() as $link) {
                $require = $link->getTarget();
                if (!isset($packageIndex[$require])) {
                    continue;
                }
                $linkConstraint = $link->getConstraint();
                foreach ($packageIndex[$require] as $id => $requiredPkg) {
                    if (\false === CompilingMatcher::match($linkConstraint, Constraint::OP_EQ, $requiredPkg->getVersion())) {
                        $this->markPackageForRemoval($id);
                        unset($packageIndex[$require][$id]);
                    }
                }
            }
        }
    }
    /**
     * Disjunctive require constraints need to be considered in their own group. E.g. "^2.14 || ^3.3" needs to generate
     * two require constraint groups in order for us to keep the best matching package for "^2.14" AND "^3.3" as otherwise, we'd
     * only keep either one which can cause trouble (e.g. when using --prefer-lowest).
     *
     * @return void
     */
    private function extractRequireConstraintsPerPackage(string $package, ConstraintInterface $constraint)
    {
        foreach ($this->expandDisjunctiveMultiConstraints($constraint) as $expanded) {
            $this->requireConstraintsPerPackage[$package][(string) $expanded] = $expanded;
        }
    }
    /**
     * Disjunctive conflict constraints need to be considered in their own group. E.g. "^2.14 || ^3.3" needs to generate
     * two conflict constraint groups in order for us to keep the best matching package for "^2.14" AND "^3.3" as otherwise, we'd
     * only keep either one which can cause trouble (e.g. when using --prefer-lowest).
     *
     * @return void
     */
    private function extractConflictConstraintsPerPackage(string $package, ConstraintInterface $constraint)
    {
        foreach ($this->expandDisjunctiveMultiConstraints($constraint) as $expanded) {
            $this->conflictConstraintsPerPackage[$package][(string) $expanded] = $expanded;
        }
    }
    /**
     * @return ConstraintInterface[]
     */
    private function expandDisjunctiveMultiConstraints(ConstraintInterface $constraint)
    {
        $constraint = Intervals::compactConstraint($constraint);
        if ($constraint instanceof MultiConstraint && $constraint->isDisjunctive()) {
            // No need to call ourselves recursively here because Intervals::compactConstraint() ensures that there
            // are no nested disjunctive MultiConstraint instances possible
            return $constraint->getConstraints();
        }
        // Regular constraints and conjunctive MultiConstraints
        return [$constraint];
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer\DependencyResolver;

use Composer\Filter\PlatformRequirementFilter\IgnoreListPlatformRequirementFilter;
use Composer\Filter\PlatformRequirementFilter\PlatformRequirementFilterFactory;
use Composer\Filter\PlatformRequirementFilter\PlatformRequirementFilterInterface;
use Composer\Package\BasePackage;
use Composer\Package\AliasPackage;
/**
 * @author Nils Adermann <naderman@naderman.de>
 * @phpstan-import-type ReasonData from Rule
 */
class RuleSetGenerator
{
    /** @var PolicyInterface */
    protected $policy;
    /** @var Pool */
    protected $pool;
    /** @var RuleSet */
    protected $rules;
    /** @var array<int, BasePackage> */
    protected $addedMap = [];
    /** @var array<string, BasePackage[]> */
    protected $addedPackagesByNames = [];
    public function __construct(\Composer\DependencyResolver\PolicyInterface $policy, \Composer\DependencyResolver\Pool $pool)
    {
        $this->policy = $policy;
        $this->pool = $pool;
        $this->rules = new \Composer\DependencyResolver\RuleSet();
    }
    /**
     * Creates a new rule for the requirements of a package
     *
     * This rule is of the form (-A|B|C), where B and C are the providers of
     * one requirement of the package A.
     *
     * @param  BasePackage $package The package with a requirement
     * @param  BasePackage[] $providers The providers of the requirement
     * @param  Rule::RULE_* $reason A RULE_* constant describing the reason for generating this rule
     * @param  mixed $reasonData Any data, e.g. the requirement name, that goes with the reason
     * @return Rule|null The generated rule or null if tautological
     *
     * @phpstan-param ReasonData $reasonData
     */
    protected function createRequireRule(BasePackage $package, array $providers, $reason, $reasonData): ?\Composer\DependencyResolver\Rule
    {
        $literals = [-$package->id];
        foreach ($providers as $provider) {
            // self fulfilling rule?
            if ($provider === $package) {
                return null;
            }
            $literals[] = $provider->id;
        }
        return new \Composer\DependencyResolver\GenericRule($literals, $reason, $reasonData);
    }
    /**
     * Creates a rule to install at least one of a set of packages
     *
     * The rule is (A|B|C) with A, B and C different packages. If the given
     * set of packages is empty an impossible rule is generated.
     *
     * @param  non-empty-array<BasePackage> $packages   The set of packages to choose from
     * @param  Rule::RULE_*  $reason     A RULE_* constant describing the reason for
     *                                   generating this rule
     * @param  mixed         $reasonData Additional data like the root require or fix request info
     * @return Rule          The generated rule
     *
     * @phpstan-param ReasonData $reasonData
     */
    protected function createInstallOneOfRule(array $packages, $reason, $reasonData): \Composer\DependencyResolver\Rule
    {
        $literals = [];
        foreach ($packages as $package) {
            $literals[] = $package->id;
        }
        return new \Composer\DependencyResolver\GenericRule($literals, $reason, $reasonData);
    }
    /**
     * Creates a rule for two conflicting packages
     *
     * The rule for conflicting packages A and B is (-A|-B). A is called the issuer
     * and B the provider.
     *
     * @param BasePackage $issuer The package declaring the conflict
     * @param BasePackage $provider The package causing the conflict
     * @param Rule::RULE_* $reason A RULE_* constant describing the reason for generating this rule
     * @param mixed $reasonData Any data, e.g. the package name, that goes with the reason
     * @return ?Rule The generated rule
     *
     * @phpstan-param ReasonData $reasonData
     */
    protected function createRule2Literals(BasePackage $issuer, BasePackage $provider, $reason, $reasonData): ?\Composer\DependencyResolver\Rule
    {
        // ignore self conflict
        if ($issuer === $provider) {
            return null;
        }
        return new \Composer\DependencyResolver\Rule2Literals(-$issuer->id, -$provider->id, $reason, $reasonData);
    }
    /**
     * @param non-empty-array<BasePackage> $packages
     * @param Rule::RULE_* $reason A RULE_* constant
     * @param mixed $reasonData
     *
     * @phpstan-param ReasonData $reasonData
     */
    protected function createMultiConflictRule(array $packages, $reason, $reasonData): \Composer\DependencyResolver\Rule
    {
        $literals = [];
        foreach ($packages as $package) {
            $literals[] = -$package->id;
        }
        if (\count($literals) === 2) {
            return new \Composer\DependencyResolver\Rule2Literals($literals[0], $literals[1], $reason, $reasonData);
        }
        return new \Composer\DependencyResolver\MultiConflictRule($literals, $reason, $reasonData);
    }
    /**
     * Adds a rule unless it duplicates an existing one of any type
     *
     * To be able to directly pass in the result of one of the rule creation
     * methods null is allowed which will not insert a rule.
     *
     * @param RuleSet::TYPE_* $type A TYPE_* constant defining the rule type
     * @param Rule $newRule The rule about to be added
     */
    private function addRule($type, ?\Composer\DependencyResolver\Rule $newRule = null): void
    {
        if (null === $newRule) {
            return;
        }
        $this->rules->add($newRule, $type);
    }
    protected function addRulesForPackage(BasePackage $package, PlatformRequirementFilterInterface $platformRequirementFilter): void
    {
        /** @var \SplQueue<BasePackage> */
        $workQueue = new \SplQueue();
        $workQueue->enqueue($package);
        while (!$workQueue->isEmpty()) {
            $package = $workQueue->dequeue();
            if (isset($this->addedMap[$package->id])) {
                continue;
            }
            $this->addedMap[$package->id] = $package;
            if (!$package instanceof AliasPackage) {
                foreach ($package->getNames(\false) as $name) {
                    $this->addedPackagesByNames[$name][] = $package;
                }
            } else {
                $workQueue->enqueue($package->getAliasOf());
                $this->addRule(\Composer\DependencyResolver\RuleSet::TYPE_PACKAGE, $this->createRequireRule($package, [$package->getAliasOf()], \Composer\DependencyResolver\Rule::RULE_PACKAGE_ALIAS, $package));
                // aliases must be installed with their main package, so create a rule the other way around as well
                $this->addRule(\Composer\DependencyResolver\RuleSet::TYPE_PACKAGE, $this->createRequireRule($package->getAliasOf(), [$package], \Composer\DependencyResolver\Rule::RULE_PACKAGE_INVERSE_ALIAS, $package->getAliasOf()));
                // if alias package has no self.version requires, its requirements do not
                // need to be added as the aliased package processing will take care of it
                if (!$package->hasSelfVersionRequires()) {
                    continue;
                }
            }
            foreach ($package->getRequires() as $link) {
                $constraint = $link->getConstraint();
                if ($platformRequirementFilter->isIgnored($link->getTarget())) {
                    continue;
                } elseif ($platformRequirementFilter instanceof IgnoreListPlatformRequirementFilter) {
                    $constraint = $platformRequirementFilter->filterConstraint($link->getTarget(), $constraint);
                }
                $possibleRequires = $this->pool->whatProvides($link->getTarget(), $constraint);
                $this->addRule(\Composer\DependencyResolver\RuleSet::TYPE_PACKAGE, $this->createRequireRule($package, $possibleRequires, \Composer\DependencyResolver\Rule::RULE_PACKAGE_REQUIRES, $link));
                foreach ($possibleRequires as $require) {
                    $workQueue->enqueue($require);
                }
            }
        }
    }
    protected function addConflictRules(PlatformRequirementFilterInterface $platformRequirementFilter): void
    {
        /** @var BasePackage $package */
        foreach ($this->addedMap as $package) {
            foreach ($package->getConflicts() as $link) {
                // even if conflict ends up being with an alias, there would be at least one actual package by this name
                if (!isset($this->addedPackagesByNames[$link->getTarget()])) {
                    continue;
                }
                $constraint = $link->getConstraint();
                if ($platformRequirementFilter->isIgnored($link->getTarget())) {
                    continue;
                } elseif ($platformRequirementFilter instanceof IgnoreListPlatformRequirementFilter) {
                    $constraint = $platformRequirementFilter->filterConstraint($link->getTarget(), $constraint, \false);
                }
                $conflicts = $this->pool->whatProvides($link->getTarget(), $constraint);
                foreach ($conflicts as $conflict) {
                    // define the conflict rule for regular packages, for alias packages it's only needed if the name
                    // matches the conflict exactly, otherwise the name match is by provide/replace which means the
                    // package which this is an alias of will conflict anyway, so no need to create additional rules
                    if (!$conflict instanceof AliasPackage || $conflict->getName() === $link->getTarget()) {
                        $this->addRule(\Composer\DependencyResolver\RuleSet::TYPE_PACKAGE, $this->createRule2Literals($package, $conflict, \Composer\DependencyResolver\Rule::RULE_PACKAGE_CONFLICT, $link));
                    }
                }
            }
        }
        foreach ($this->addedPackagesByNames as $name => $packages) {
            if (\count($packages) > 1) {
                $reason = \Composer\DependencyResolver\Rule::RULE_PACKAGE_SAME_NAME;
                $this->addRule(\Composer\DependencyResolver\RuleSet::TYPE_PACKAGE, $this->createMultiConflictRule($packages, $reason, $name));
            }
        }
    }
    protected function addRulesForRequest(\Composer\DependencyResolver\Request $request, PlatformRequirementFilterInterface $platformRequirementFilter): void
    {
        foreach ($request->getFixedPackages() as $package) {
            if ($package->id === -1) {
                // fixed package was not added to the pool as it did not pass the stability requirements, this is fine
                if ($this->pool->isUnacceptableFixedOrLockedPackage($package)) {
                    continue;
                }
                // otherwise, looks like a bug
                throw new \LogicException("Fixed package " . $package->getPrettyString() . " was not added to solver pool.");
            }
            $this->addRulesForPackage($package, $platformRequirementFilter);
            $rule = $this->createInstallOneOfRule([$package], \Composer\DependencyResolver\Rule::RULE_FIXED, ['package' => $package]);
            $this->addRule(\Composer\DependencyResolver\RuleSet::TYPE_REQUEST, $rule);
        }
        foreach ($request->getRequires() as $packageName => $constraint) {
            if ($platformRequirementFilter->isIgnored($packageName)) {
                continue;
            } elseif ($platformRequirementFilter instanceof IgnoreListPlatformRequirementFilter) {
                $constraint = $platformRequirementFilter->filterConstraint($packageName, $constraint);
            }
            $packages = $this->pool->whatProvides($packageName, $constraint);
            if (\count($packages) > 0) {
                foreach ($packages as $package) {
                    $this->addRulesForPackage($package, $platformRequirementFilter);
                }
                $rule = $this->createInstallOneOfRule($packages, \Composer\DependencyResolver\Rule::RULE_ROOT_REQUIRE, ['packageName' => $packageName, 'constraint' => $constraint]);
                $this->addRule(\Composer\DependencyResolver\RuleSet::TYPE_REQUEST, $rule);
            }
        }
    }
    protected function addRulesForRootAliases(PlatformRequirementFilterInterface $platformRequirementFilter): void
    {
        foreach ($this->pool->getPackages() as $package) {
            // ensure that rules for root alias packages and aliases of packages which were loaded are also loaded
            // even if the alias itself isn't required, otherwise a package could be installed without its alias which
            // leads to unexpected behavior
            if (!isset($this->addedMap[$package->id]) && $package instanceof AliasPackage && ($package->isRootPackageAlias() || isset($this->addedMap[$package->getAliasOf()->id]))) {
                $this->addRulesForPackage($package, $platformRequirementFilter);
            }
        }
    }
    public function getRulesFor(\Composer\DependencyResolver\Request $request, ?PlatformRequirementFilterInterface $platformRequirementFilter = null): \Composer\DependencyResolver\RuleSet
    {
        $platformRequirementFilter = $platformRequirementFilter ?? PlatformRequirementFilterFactory::ignoreNothing();
        $this->addRulesForRequest($request, $platformRequirementFilter);
        $this->addRulesForRootAliases($platformRequirementFilter);
        $this->addConflictRules($platformRequirementFilter);
        // Remove references to packages
        $this->addedMap = $this->addedPackagesByNames = [];
        $rules = $this->rules;
        $this->rules = new \Composer\DependencyResolver\RuleSet();
        return $rules;
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer\DependencyResolver;

/**
 * Stores decisions on installing, removing or keeping packages
 *
 * @author Nils Adermann <naderman@naderman.de>
 * @implements \Iterator<array{0: int, 1: Rule}>
 */
class Decisions implements \Iterator, \Countable
{
    public const DECISION_LITERAL = 0;
    public const DECISION_REASON = 1;
    /** @var Pool */
    protected $pool;
    /** @var array<int, int> */
    protected $decisionMap;
    /**
     * @var array<int, array{0: int, 1: Rule}>
     */
    protected $decisionQueue = [];
    public function __construct(\Composer\DependencyResolver\Pool $pool)
    {
        $this->pool = $pool;
        $this->decisionMap = [];
    }
    public function decide(int $literal, int $level, \Composer\DependencyResolver\Rule $why): void
    {
        $this->addDecision($literal, $level);
        $this->decisionQueue[] = [self::DECISION_LITERAL => $literal, self::DECISION_REASON => $why];
    }
    public function satisfy(int $literal): bool
    {
        $packageId = abs($literal);
        return $literal > 0 && isset($this->decisionMap[$packageId]) && $this->decisionMap[$packageId] > 0 || $literal < 0 && isset($this->decisionMap[$packageId]) && $this->decisionMap[$packageId] < 0;
    }
    public function conflict(int $literal): bool
    {
        $packageId = abs($literal);
        return isset($this->decisionMap[$packageId]) && $this->decisionMap[$packageId] > 0 && $literal < 0 || isset($this->decisionMap[$packageId]) && $this->decisionMap[$packageId] < 0 && $literal > 0;
    }
    public function decided(int $literalOrPackageId): bool
    {
        return ($this->decisionMap[abs($literalOrPackageId)] ?? 0) !== 0;
    }
    public function undecided(int $literalOrPackageId): bool
    {
        return ($this->decisionMap[abs($literalOrPackageId)] ?? 0) === 0;
    }
    public function decidedInstall(int $literalOrPackageId): bool
    {
        $packageId = abs($literalOrPackageId);
        return isset($this->decisionMap[$packageId]) && $this->decisionMap[$packageId] > 0;
    }
    public function decisionLevel(int $literalOrPackageId): int
    {
        $packageId = abs($literalOrPackageId);
        if (isset($this->decisionMap[$packageId])) {
            return abs($this->decisionMap[$packageId]);
        }
        return 0;
    }
    public function decisionRule(int $literalOrPackageId): \Composer\DependencyResolver\Rule
    {
        $packageId = abs($literalOrPackageId);
        foreach ($this->decisionQueue as $decision) {
            if ($packageId === abs($decision[self::DECISION_LITERAL])) {
                return $decision[self::DECISION_REASON];
            }
        }
        throw new \LogicException('Did not find a decision rule using ' . $literalOrPackageId);
    }
    /**
     * @return array{0: int, 1: Rule} a literal and decision reason
     */
    public function atOffset(int $queueOffset): array
    {
        return $this->decisionQueue[$queueOffset];
    }
    public function validOffset(int $queueOffset): bool
    {
        return $queueOffset >= 0 && $queueOffset < \count($this->decisionQueue);
    }
    public function lastReason(): \Composer\DependencyResolver\Rule
    {
        return $this->decisionQueue[\count($this->decisionQueue) - 1][self::DECISION_REASON];
    }
    public function lastLiteral(): int
    {
        return $this->decisionQueue[\count($this->decisionQueue) - 1][self::DECISION_LITERAL];
    }
    public function reset(): void
    {
        while ($decision = array_pop($this->decisionQueue)) {
            $this->decisionMap[abs($decision[self::DECISION_LITERAL])] = 0;
        }
    }
    /**
     * @param int<-1, max> $offset
     */
    public function resetToOffset(int $offset): void
    {
        while (\count($this->decisionQueue) > $offset + 1) {
            $decision = array_pop($this->decisionQueue);
            $this->decisionMap[abs($decision[self::DECISION_LITERAL])] = 0;
        }
    }
    public function revertLast(): void
    {
        $this->decisionMap[abs($this->lastLiteral())] = 0;
        array_pop($this->decisionQueue);
    }
    public function count(): int
    {
        return \count($this->decisionQueue);
    }
    public function rewind(): void
    {
        end($this->decisionQueue);
    }
    /**
     * @return array{0: int, 1: Rule}|false
     */
    #[\ReturnTypeWillChange]
    public function current()
    {
        return current($this->decisionQueue);
    }
    public function key(): ?int
    {
        return key($this->decisionQueue);
    }
    public function next(): void
    {
        prev($this->decisionQueue);
    }
    public function valid(): bool
    {
        return \false !== current($this->decisionQueue);
    }
    public function isEmpty(): bool
    {
        return \count($this->decisionQueue) === 0;
    }
    protected function addDecision(int $literal, int $level): void
    {
        $packageId = abs($literal);
        $previousDecision = $this->decisionMap[$packageId] ?? 0;
        if ($previousDecision !== 0) {
            $literalString = $this->pool->literalToPrettyString($literal, []);
            $package = $this->pool->literalToPackage($literal);
            throw new \Composer\DependencyResolver\SolverBugException("Trying to decide {$literalString} on level {$level}, even though {$package} was previously decided as " . $previousDecision . ".");
        }
        if ($literal > 0) {
            $this->decisionMap[$packageId] = $level;
        } else {
            $this->decisionMap[$packageId] = -$level;
        }
    }
    public function toString(?\Composer\DependencyResolver\Pool $pool = null): string
    {
        $decisionMap = $this->decisionMap;
        ksort($decisionMap);
        $str = '[';
        foreach ($decisionMap as $packageId => $level) {
            $str .= ($pool !== null ? $pool->literalToPackage($packageId) : $packageId) . ':' . $level . ',';
        }
        $str .= ']';
        return $str;
    }
    public function __toString(): string
    {
        return $this->toString();
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer\DependencyResolver;

use Composer\EventDispatcher\EventDispatcher;
use Composer\IO\IOInterface;
use Composer\Package\AliasPackage;
use Composer\Package\BasePackage;
use Composer\Package\CompleteAliasPackage;
use Composer\Package\CompletePackage;
use Composer\Package\PackageInterface;
use Composer\Package\Version\StabilityFilter;
use Composer\Pcre\Preg;
use Composer\Plugin\PluginEvents;
use Composer\Plugin\PrePoolCreateEvent;
use Composer\Repository\PlatformRepository;
use Composer\Repository\RepositoryInterface;
use Composer\Repository\RootPackageRepository;
use Composer\Semver\CompilingMatcher;
use Composer\Semver\Constraint\Constraint;
use Composer\Semver\Constraint\ConstraintInterface;
use Composer\Semver\Constraint\MatchAllConstraint;
use Composer\Semver\Constraint\MultiConstraint;
use Composer\Semver\Intervals;
/**
 * @author Nils Adermann <naderman@naderman.de>
 */
class PoolBuilder
{
    private const LOAD_BATCH_SIZE = 50;
    /**
     * @var int[]
     * @phpstan-var array<key-of<BasePackage::STABILITIES>, BasePackage::STABILITY_*>
     */
    private $acceptableStabilities;
    /**
     * @var int[]
     * @phpstan-var array<string, BasePackage::STABILITY_*>
     */
    private $stabilityFlags;
    /**
     * @var array[]
     * @phpstan-var array<string, array<string, array{alias: string, alias_normalized: string}>>
     */
    private $rootAliases;
    /**
     * @var string[]
     * @phpstan-var array<string, string>
     */
    private $rootReferences;
    /**
     * @var array<string, ConstraintInterface>
     */
    private $temporaryConstraints;
    /**
     * @var ?EventDispatcher
     */
    private $eventDispatcher;
    /**
     * @var PoolOptimizer|null
     */
    private $poolOptimizer;
    /**
     * @var IOInterface
     */
    private $io;
    /**
     * @var array[]
     * @phpstan-var array<string, AliasPackage[]>
     */
    private $aliasMap = [];
    /**
     * @var ConstraintInterface[]
     * @phpstan-var array<string, ConstraintInterface>
     */
    private $packagesToLoad = [];
    /**
     * @var ConstraintInterface[]
     * @phpstan-var array<string, ConstraintInterface>
     */
    private $loadedPackages = [];
    /**
     * @var array[]
     * @phpstan-var array<int, array<string, array<string, PackageInterface>>>
     */
    private $loadedPerRepo = [];
    /**
     * @var array<int, BasePackage>
     */
    private $packages = [];
    /**
     * @var BasePackage[]
     */
    private $unacceptableFixedOrLockedPackages = [];
    /** @var array<string> */
    private $updateAllowList = [];
    /** @var array<string, array<PackageInterface>> */
    private $skippedLoad = [];
    /** @var list<string> */
    private $ignoredTypes = [];
    /** @var list<string>|null */
    private $allowedTypes = null;
    /**
     * If provided, only these package names are loaded
     *
     * This is a special-use functionality of the Request class to optimize the pool creation process
     * when only a minimal subset of packages is needed and we do not need their dependencies.
     *
     * @var array<string, int>|null
     */
    private $restrictedPackagesList = null;
    /**
     * Keeps a list of dependencies which are locked but were auto-unlocked as they are path repositories
     *
     * This half-unlocked state means the package itself will update but the UPDATE_LISTED_WITH_TRANSITIVE_DEPS*
     * flags will not apply until the package really gets unlocked in some other way than being a path repo
     *
     * @var array<string, true>
     */
    private $pathRepoUnlocked = [];
    /**
     * Keeps a list of dependencies which are root requirements, and as such
     * have already their maximum required range loaded and can not be
     * extended by markPackageNameForLoading
     *
     * Packages get cleared from this list if they get unlocked as in that case
     * we need to actually load them
     *
     * @var array<string, true>
     */
    private $maxExtendedReqs = [];
    /**
     * @var array
     * @phpstan-var array<string, bool>
     */
    private $updateAllowWarned = [];
    /** @var int */
    private $indexCounter = 0;
    /** @var ?SecurityAdvisoryPoolFilter */
    private $securityAdvisoryPoolFilter;
    /**
     * @param int[] $acceptableStabilities array of stability => BasePackage::STABILITY_* value
     * @phpstan-param array<key-of<BasePackage::STABILITIES>, BasePackage::STABILITY_*> $acceptableStabilities
     * @param int[] $stabilityFlags an array of package name => BasePackage::STABILITY_* value
     * @phpstan-param array<string, BasePackage::STABILITY_*> $stabilityFlags
     * @param array[] $rootAliases
     * @phpstan-param array<string, array<string, array{alias: string, alias_normalized: string}>> $rootAliases
     * @param string[] $rootReferences an array of package name => source reference
     * @phpstan-param array<string, string> $rootReferences
     * @param array<string, ConstraintInterface> $temporaryConstraints Runtime temporary constraints that will be used to filter packages
     */
    public function __construct(array $acceptableStabilities, array $stabilityFlags, array $rootAliases, array $rootReferences, IOInterface $io, ?EventDispatcher $eventDispatcher = null, ?\Composer\DependencyResolver\PoolOptimizer $poolOptimizer = null, array $temporaryConstraints = [], ?\Composer\DependencyResolver\SecurityAdvisoryPoolFilter $securityAdvisoryPoolFilter = null)
    {
        $this->acceptableStabilities = $acceptableStabilities;
        $this->stabilityFlags = $stabilityFlags;
        $this->rootAliases = $rootAliases;
        $this->rootReferences = $rootReferences;
        $this->eventDispatcher = $eventDispatcher;
        $this->poolOptimizer = $poolOptimizer;
        $this->io = $io;
        $this->temporaryConstraints = $temporaryConstraints;
        $this->securityAdvisoryPoolFilter = $securityAdvisoryPoolFilter;
    }
    /**
     * Packages of those types are ignored
     *
     * @param list<string> $types
     */
    public function setIgnoredTypes(array $types): void
    {
        $this->ignoredTypes = $types;
    }
    /**
     * Only packages of those types are allowed if set to non-null
     *
     * @param list<string>|null $types
     */
    public function setAllowedTypes(?array $types): void
    {
        $this->allowedTypes = $types;
    }
    /**
     * @param RepositoryInterface[] $repositories
     */
    public function buildPool(array $repositories, \Composer\DependencyResolver\Request $request): \Composer\DependencyResolver\Pool
    {
        $this->restrictedPackagesList = $request->getRestrictedPackages() !== null ? array_flip($request->getRestrictedPackages()) : null;
        if (\count($request->getUpdateAllowList()) > 0) {
            $this->updateAllowList = $request->getUpdateAllowList();
            $this->warnAboutNonMatchingUpdateAllowList($request);
            if (null === $request->getLockedRepository()) {
                throw new \LogicException('No lock repo present and yet a partial update was requested.');
            }
            foreach ($request->getLockedRepository()->getPackages() as $lockedPackage) {
                if (!$this->isUpdateAllowed($lockedPackage)) {
                    // remember which packages we skipped loading remote content for in this partial update
                    $this->skippedLoad[$lockedPackage->getName()][] = $lockedPackage;
                    foreach ($lockedPackage->getReplaces() as $link) {
                        $this->skippedLoad[$link->getTarget()][] = $lockedPackage;
                    }
                    // Path repo packages are never loaded from lock, to force them to always remain in sync
                    // unless symlinking is disabled in which case we probably should rather treat them like
                    // regular packages. We mark them specially so they can be reloaded fully including update propagation
                    // if they do get unlocked, but by default they are unlocked without update propagation.
                    if ($lockedPackage->getDistType() === 'path') {
                        $transportOptions = $lockedPackage->getTransportOptions();
                        if (!isset($transportOptions['symlink']) || $transportOptions['symlink'] !== \false) {
                            $this->pathRepoUnlocked[$lockedPackage->getName()] = \true;
                            continue;
                        }
                    }
                    $request->lockPackage($lockedPackage);
                }
            }
        }
        foreach ($request->getFixedOrLockedPackages() as $package) {
            // using MatchAllConstraint here because fixed packages do not need to retrigger
            // loading any packages
            $this->loadedPackages[$package->getName()] = new MatchAllConstraint();
            // replace means conflict, so if a fixed package replaces a name, no need to load that one, packages would conflict anyways
            foreach ($package->getReplaces() as $link) {
                $this->loadedPackages[$link->getTarget()] = new MatchAllConstraint();
            }
            // TODO in how far can we do the above for conflicts? It's more tricky cause conflicts can be limited to
            // specific versions while replace is a conflict with all versions of the name
            if ($package->getRepository() instanceof RootPackageRepository || $package->getRepository() instanceof PlatformRepository || StabilityFilter::isPackageAcceptable($this->acceptableStabilities, $this->stabilityFlags, $package->getNames(), $package->getStability())) {
                $this->loadPackage($request, $repositories, $package, \false);
            } else {
                $this->unacceptableFixedOrLockedPackages[] = $package;
            }
        }
        foreach ($request->getRequires() as $packageName => $constraint) {
            // fixed and locked packages have already been added, so if a root require needs one of them, no need to do anything
            if (isset($this->loadedPackages[$packageName])) {
                continue;
            }
            $this->packagesToLoad[$packageName] = $constraint;
            $this->maxExtendedReqs[$packageName] = \true;
        }
        // clean up packagesToLoad for anything we manually marked loaded above
        foreach ($this->packagesToLoad as $name => $constraint) {
            if (isset($this->loadedPackages[$name])) {
                unset($this->packagesToLoad[$name]);
            }
        }
        while (\count($this->packagesToLoad) > 0) {
            $this->loadPackagesMarkedForLoading($request, $repositories);
        }
        if (\count($this->temporaryConstraints) > 0) {
            foreach ($this->packages as $i => $package) {
                // we check all alias related packages at once, so no need to check individual aliases
                if ($package instanceof AliasPackage) {
                    continue;
                }
                foreach ($package->getNames() as $packageName) {
                    if (!isset($this->temporaryConstraints[$packageName])) {
                        continue;
                    }
                    $constraint = $this->temporaryConstraints[$packageName];
                    $packageAndAliases = [$i => $package];
                    if (isset($this->aliasMap[spl_object_hash($package)])) {
                        $packageAndAliases += $this->aliasMap[spl_object_hash($package)];
                    }
                    $found = \false;
                    foreach ($packageAndAliases as $packageOrAlias) {
                        if (CompilingMatcher::match($constraint, Constraint::OP_EQ, $packageOrAlias->getVersion())) {
                            $found = \true;
                        }
                    }
                    if (!$found) {
                        foreach ($packageAndAliases as $index => $packageOrAlias) {
                            unset($this->packages[$index]);
                        }
                    }
                }
            }
        }
        if ($this->eventDispatcher !== null) {
            $prePoolCreateEvent = new PrePoolCreateEvent(PluginEvents::PRE_POOL_CREATE, $repositories, $request, $this->acceptableStabilities, $this->stabilityFlags, $this->rootAliases, $this->rootReferences, $this->packages, $this->unacceptableFixedOrLockedPackages);
            $this->eventDispatcher->dispatch($prePoolCreateEvent->getName(), $prePoolCreateEvent);
            $this->packages = $prePoolCreateEvent->getPackages();
            $this->unacceptableFixedOrLockedPackages = $prePoolCreateEvent->getUnacceptableFixedPackages();
        }
        $pool = new \Composer\DependencyResolver\Pool($this->packages, $this->unacceptableFixedOrLockedPackages);
        $this->aliasMap = [];
        $this->packagesToLoad = [];
        $this->loadedPackages = [];
        $this->loadedPerRepo = [];
        $this->packages = [];
        $this->unacceptableFixedOrLockedPackages = [];
        $this->maxExtendedReqs = [];
        $this->skippedLoad = [];
        $this->indexCounter = 0;
        $this->io->debug('Built pool.');
        // filter vulnerable packages before optimizing the pool otherwise we may end up with inconsistent state where the optimizer took away versions
        // that were not vulnerable and now suddenly the vulnerable ones are removed and we are missing some versions to make it solvable
        $pool = $this->runSecurityAdvisoryFilter($pool, $repositories, $request);
        $pool = $this->runOptimizer($request, $pool);
        Intervals::clear();
        return $pool;
    }
    private function markPackageNameForLoading(\Composer\DependencyResolver\Request $request, string $name, ConstraintInterface $constraint): void
    {
        // Skip platform requires at this stage
        if (PlatformRepository::isPlatformPackage($name)) {
            return;
        }
        // Root require (which was not unlocked) already loaded the maximum range so no
        // need to check anything here
        if (isset($this->maxExtendedReqs[$name])) {
            return;
        }
        // Root requires can not be overruled by dependencies so there is no point in
        // extending the loaded constraint for those.
        // This is triggered when loading a root require which was locked but got unlocked, then
        // we make sure that we load at most the intervals covered by the root constraint.
        $rootRequires = $request->getRequires();
        if (isset($rootRequires[$name]) && !Intervals::isSubsetOf($constraint, $rootRequires[$name])) {
            $constraint = $rootRequires[$name];
        }
        // Not yet loaded or already marked for a reload, set the constraint to be loaded
        if (!isset($this->loadedPackages[$name])) {
            // Maybe it was already marked before but not loaded yet. In that case
            // we have to extend the constraint (we don't check if they are identical because
            // MultiConstraint::create() will optimize anyway)
            if (isset($this->packagesToLoad[$name])) {
                // Already marked for loading and this does not expand the constraint to be loaded, nothing to do
                if (Intervals::isSubsetOf($constraint, $this->packagesToLoad[$name])) {
                    return;
                }
                // extend the constraint to be loaded
                $constraint = Intervals::compactConstraint(MultiConstraint::create([$this->packagesToLoad[$name], $constraint], \false));
            }
            $this->packagesToLoad[$name] = $constraint;
            return;
        }
        // No need to load this package with this constraint because it is
        // a subset of the constraint with which we have already loaded packages
        if (Intervals::isSubsetOf($constraint, $this->loadedPackages[$name])) {
            return;
        }
        // We have already loaded that package but not in the constraint that's
        // required. We extend the constraint and mark that package as not being loaded
        // yet so we get the required package versions
        $this->packagesToLoad[$name] = Intervals::compactConstraint(MultiConstraint::create([$this->loadedPackages[$name], $constraint], \false));
        unset($this->loadedPackages[$name]);
    }
    /**
     * @param RepositoryInterface[] $repositories
     */
    private function loadPackagesMarkedForLoading(\Composer\DependencyResolver\Request $request, array $repositories): void
    {
        foreach ($this->packagesToLoad as $name => $constraint) {
            if ($this->restrictedPackagesList !== null && !isset($this->restrictedPackagesList[$name])) {
                unset($this->packagesToLoad[$name]);
                continue;
            }
            $this->loadedPackages[$name] = $constraint;
        }
        // Load packages in chunks of 50 to prevent memory usage build-up due to caches of all sorts
        $packageBatches = array_chunk($this->packagesToLoad, self::LOAD_BATCH_SIZE, \true);
        $this->packagesToLoad = [];
        foreach ($repositories as $repoIndex => $repository) {
            // these repos have their packages fixed or locked if they need to be loaded so we
            // never need to load anything else from them
            if ($repository instanceof PlatformRepository || $repository === $request->getLockedRepository()) {
                continue;
            }
            if (0 === \count($packageBatches)) {
                break;
            }
            foreach ($packageBatches as $batchIndex => $packageBatch) {
                $result = $repository->loadPackages($packageBatch, $this->acceptableStabilities, $this->stabilityFlags, $this->loadedPerRepo[$repoIndex] ?? []);
                foreach ($result['namesFound'] as $name) {
                    // avoid loading the same package again from other repositories once it has been found
                    unset($packageBatches[$batchIndex][$name]);
                }
                foreach ($result['packages'] as $package) {
                    $this->loadedPerRepo[$repoIndex][$package->getName()][$package->getVersion()] = $package;
                    if (in_array($package->getType(), $this->ignoredTypes, \true) || $this->allowedTypes !== null && !in_array($package->getType(), $this->allowedTypes, \true)) {
                        continue;
                    }
                    $this->loadPackage($request, $repositories, $package, !isset($this->pathRepoUnlocked[$package->getName()]));
                }
            }
            $packageBatches = array_chunk(array_merge(...$packageBatches), self::LOAD_BATCH_SIZE, \true);
        }
    }
    /**
     * @param RepositoryInterface[] $repositories
     */
    private function loadPackage(\Composer\DependencyResolver\Request $request, array $repositories, BasePackage $package, bool $propagateUpdate): void
    {
        $index = $this->indexCounter++;
        $this->packages[$index] = $package;
        if ($package instanceof AliasPackage) {
            $this->aliasMap[spl_object_hash($package->getAliasOf())][$index] = $package;
        }
        $name = $package->getName();
        // we're simply setting the root references on all versions for a name here and rely on the solver to pick the
        // right version. It'd be more work to figure out which versions and which aliases of those versions this may
        // apply to
        if (isset($this->rootReferences[$name])) {
            // do not modify the references on already locked or fixed packages
            if (!$request->isLockedPackage($package) && !$request->isFixedPackage($package)) {
                $package->setSourceDistReferences($this->rootReferences[$name]);
            }
        }
        // if propagateUpdate is false we are loading a fixed or locked package, root aliases do not apply as they are
        // manually loaded as separate packages in this case
        //
        // packages in pathRepoUnlocked however need to also load root aliases, they have propagateUpdate set to
        // false because their deps should not be unlocked, but that is irrelevant for root aliases
        if (($propagateUpdate || isset($this->pathRepoUnlocked[$package->getName()])) && isset($this->rootAliases[$name][$package->getVersion()])) {
            $alias = $this->rootAliases[$name][$package->getVersion()];
            if ($package instanceof AliasPackage) {
                $basePackage = $package->getAliasOf();
            } else {
                $basePackage = $package;
            }
            if ($basePackage instanceof CompletePackage) {
                $aliasPackage = new CompleteAliasPackage($basePackage, $alias['alias_normalized'], $alias['alias']);
            } else {
                $aliasPackage = new AliasPackage($basePackage, $alias['alias_normalized'], $alias['alias']);
            }
            $aliasPackage->setRootPackageAlias(\true);
            $newIndex = $this->indexCounter++;
            $this->packages[$newIndex] = $aliasPackage;
            $this->aliasMap[spl_object_hash($aliasPackage->getAliasOf())][$newIndex] = $aliasPackage;
        }
        foreach ($package->getRequires() as $link) {
            $require = $link->getTarget();
            $linkConstraint = $link->getConstraint();
            // if the required package is loaded as a locked package only and hasn't had its deps analyzed
            if (isset($this->skippedLoad[$require])) {
                // if we're doing a full update or this is a partial update with transitive deps and we're currently
                // looking at a package which needs to be updated we need to unlock the package we now know is a
                // dependency of another package which we are trying to update, and then attempt to load it again
                if ($propagateUpdate && $request->getUpdateAllowTransitiveDependencies()) {
                    $skippedRootRequires = $this->getSkippedRootRequires($request, $require);
                    if ($request->getUpdateAllowTransitiveRootDependencies() || 0 === \count($skippedRootRequires)) {
                        $this->unlockPackage($request, $repositories, $require);
                        $this->markPackageNameForLoading($request, $require, $linkConstraint);
                    } else {
                        foreach ($skippedRootRequires as $rootRequire) {
                            if (!isset($this->updateAllowWarned[$rootRequire])) {
                                $this->updateAllowWarned[$rootRequire] = \true;
                                $this->io->writeError('<warning>Dependency ' . $rootRequire . ' is also a root requirement. Package has not been listed as an update argument, so keeping locked at old version. Use --with-all-dependencies (-W) to include root dependencies.</warning>');
                            }
                        }
                    }
                } elseif (isset($this->pathRepoUnlocked[$require]) && !isset($this->loadedPackages[$require])) {
                    // if doing a partial update and a package depends on a path-repo-unlocked package which is not referenced by the root, we need to ensure it gets loaded as it was not loaded by the request's root requirements
                    // and would not be loaded above if update propagation is not allowed (which happens if the requirer is itself a path-repo-unlocked package) or if transitive deps are not allowed to be unlocked
                    $this->markPackageNameForLoading($request, $require, $linkConstraint);
                }
            } else {
                $this->markPackageNameForLoading($request, $require, $linkConstraint);
            }
        }
        // if we're doing a partial update with deps we also need to unlock packages which are being replaced in case
        // they are currently locked and thus prevent this updateable package from being installable/updateable
        if ($propagateUpdate && $request->getUpdateAllowTransitiveDependencies()) {
            foreach ($package->getReplaces() as $link) {
                $replace = $link->getTarget();
                if (isset($this->loadedPackages[$replace], $this->skippedLoad[$replace])) {
                    $skippedRootRequires = $this->getSkippedRootRequires($request, $replace);
                    if ($request->getUpdateAllowTransitiveRootDependencies() || 0 === \count($skippedRootRequires)) {
                        $this->unlockPackage($request, $repositories, $replace);
                        // the replaced package only needs to be loaded if something else requires it
                        $this->markPackageNameForLoadingIfRequired($request, $replace);
                    } else {
                        foreach ($skippedRootRequires as $rootRequire) {
                            if (!isset($this->updateAllowWarned[$rootRequire])) {
                                $this->updateAllowWarned[$rootRequire] = \true;
                                $this->io->writeError('<warning>Dependency ' . $rootRequire . ' is also a root requirement. Package has not been listed as an update argument, so keeping locked at old version. Use --with-all-dependencies (-W) to include root dependencies.</warning>');
                            }
                        }
                    }
                }
            }
        }
    }
    /**
     * Checks if a particular name is required directly in the request
     *
     * @param string $name packageName
     */
    private function isRootRequire(\Composer\DependencyResolver\Request $request, string $name): bool
    {
        $rootRequires = $request->getRequires();
        return isset($rootRequires[$name]);
    }
    /**
     * @return string[]
     */
    private function getSkippedRootRequires(\Composer\DependencyResolver\Request $request, string $name): array
    {
        if (!isset($this->skippedLoad[$name])) {
            return [];
        }
        $rootRequires = $request->getRequires();
        $matches = [];
        if (isset($rootRequires[$name])) {
            return array_map(static function (PackageInterface $package) use ($name): string {
                if ($name !== $package->getName()) {
                    return $package->getName() . ' (via replace of ' . $name . ')';
                }
                return $package->getName();
            }, $this->skippedLoad[$name]);
        }
        foreach ($this->skippedLoad[$name] as $packageOrReplacer) {
            if (isset($rootRequires[$packageOrReplacer->getName()])) {
                $matches[] = $packageOrReplacer->getName();
            }
            foreach ($packageOrReplacer->getReplaces() as $link) {
                if (isset($rootRequires[$link->getTarget()])) {
                    if ($name !== $packageOrReplacer->getName()) {
                        $matches[] = $packageOrReplacer->getName() . ' (via replace of ' . $name . ')';
                    } else {
                        $matches[] = $packageOrReplacer->getName();
                    }
                    break;
                }
            }
        }
        return $matches;
    }
    /**
     * Checks whether the update allow list allows this package in the lock file to be updated
     */
    private function isUpdateAllowed(BasePackage $package): bool
    {
        foreach ($this->updateAllowList as $pattern) {
            $patternRegexp = BasePackage::packageNameToRegexp($pattern);
            if (Preg::isMatch($patternRegexp, $package->getName())) {
                return \true;
            }
        }
        return \false;
    }
    private function warnAboutNonMatchingUpdateAllowList(\Composer\DependencyResolver\Request $request): void
    {
        if (null === $request->getLockedRepository()) {
            throw new \LogicException('No lock repo present and yet a partial update was requested.');
        }
        foreach ($this->updateAllowList as $pattern) {
            $matchedPlatformPackage = \false;
            $patternRegexp = BasePackage::packageNameToRegexp($pattern);
            // update pattern matches a locked package? => all good
            foreach ($request->getLockedRepository()->getPackages() as $package) {
                if (Preg::isMatch($patternRegexp, $package->getName())) {
                    continue 2;
                }
            }
            // update pattern matches a root require? => all good, probably a new package
            foreach ($request->getRequires() as $packageName => $constraint) {
                if (Preg::isMatch($patternRegexp, $packageName)) {
                    if (PlatformRepository::isPlatformPackage($packageName)) {
                        $matchedPlatformPackage = \true;
                        continue;
                    }
                    continue 2;
                }
            }
            if ($matchedPlatformPackage) {
                $this->io->writeError('<warning>Pattern "' . $pattern . '" listed for update matches platform packages, but these cannot be updated by Composer.</warning>');
            } elseif (strpos($pattern, '*') !== \false) {
                $this->io->writeError('<warning>Pattern "' . $pattern . '" listed for update does not match any locked packages.</warning>');
            } else {
                $this->io->writeError('<warning>Package "' . $pattern . '" listed for update is not locked.</warning>');
            }
        }
    }
    /**
     * Reverts the decision to use a locked package if a partial update with transitive dependencies
     * found that this package actually needs to be updated
     *
     * @param RepositoryInterface[] $repositories
     */
    private function unlockPackage(\Composer\DependencyResolver\Request $request, array $repositories, string $name): void
    {
        foreach ($this->skippedLoad[$name] as $packageOrReplacer) {
            // if we unfixed a replaced package name, we also need to unfix the replacer itself
            // as long as it was not unfixed yet
            if ($packageOrReplacer->getName() !== $name && isset($this->skippedLoad[$packageOrReplacer->getName()])) {
                $replacerName = $packageOrReplacer->getName();
                if ($request->getUpdateAllowTransitiveRootDependencies() || !$this->isRootRequire($request, $name) && !$this->isRootRequire($request, $replacerName)) {
                    $this->unlockPackage($request, $repositories, $replacerName);
                    if ($this->isRootRequire($request, $replacerName)) {
                        $this->markPackageNameForLoading($request, $replacerName, new MatchAllConstraint());
                    } else {
                        foreach ($this->packages as $loadedPackage) {
                            $requires = $loadedPackage->getRequires();
                            if (isset($requires[$replacerName])) {
                                $this->markPackageNameForLoading($request, $replacerName, $requires[$replacerName]->getConstraint());
                            }
                        }
                    }
                }
            }
        }
        if (isset($this->pathRepoUnlocked[$name])) {
            foreach ($this->packages as $index => $package) {
                if ($package->getName() === $name) {
                    $this->removeLoadedPackage($request, $repositories, $package, $index);
                }
            }
        }
        unset($this->skippedLoad[$name], $this->loadedPackages[$name], $this->maxExtendedReqs[$name], $this->pathRepoUnlocked[$name]);
        // remove locked package by this name which was already initialized
        foreach ($request->getLockedPackages() as $lockedPackage) {
            if (!$lockedPackage instanceof AliasPackage && $lockedPackage->getName() === $name) {
                if (\false !== $index = array_search($lockedPackage, $this->packages, \true)) {
                    $request->unlockPackage($lockedPackage);
                    $this->removeLoadedPackage($request, $repositories, $lockedPackage, $index);
                    // make sure that any requirements for this package by other locked or fixed packages are now
                    // also loaded, as they were previously ignored because the locked (now unlocked) package already
                    // satisfied their requirements
                    // and if this package is replacing another that is required by a locked or fixed package, ensure
                    // that we load that replaced package in case an update to this package removes the replacement
                    foreach ($request->getFixedOrLockedPackages() as $fixedOrLockedPackage) {
                        if ($fixedOrLockedPackage === $lockedPackage) {
                            continue;
                        }
                        if (isset($this->skippedLoad[$fixedOrLockedPackage->getName()])) {
                            $requires = $fixedOrLockedPackage->getRequires();
                            if (isset($requires[$lockedPackage->getName()])) {
                                $this->markPackageNameForLoading($request, $lockedPackage->getName(), $requires[$lockedPackage->getName()]->getConstraint());
                            }
                            foreach ($lockedPackage->getReplaces() as $replace) {
                                if (isset($requires[$replace->getTarget()], $this->skippedLoad[$replace->getTarget()])) {
                                    $this->unlockPackage($request, $repositories, $replace->getTarget());
                                    // this package is in $requires so no need to call markPackageNameForLoadingIfRequired
                                    $this->markPackageNameForLoading($request, $replace->getTarget(), $replace->getConstraint());
                                }
                            }
                        }
                    }
                }
            }
        }
    }
    private function markPackageNameForLoadingIfRequired(\Composer\DependencyResolver\Request $request, string $name): void
    {
        if ($this->isRootRequire($request, $name)) {
            $this->markPackageNameForLoading($request, $name, $request->getRequires()[$name]);
        }
        foreach ($this->packages as $package) {
            foreach ($package->getRequires() as $link) {
                if ($name === $link->getTarget()) {
                    $this->markPackageNameForLoading($request, $link->getTarget(), $link->getConstraint());
                }
            }
        }
    }
    /**
     * @param RepositoryInterface[] $repositories
     */
    private function removeLoadedPackage(\Composer\DependencyResolver\Request $request, array $repositories, BasePackage $package, int $index): void
    {
        $repoIndex = array_search($package->getRepository(), $repositories, \true);
        unset($this->loadedPerRepo[$repoIndex][$package->getName()][$package->getVersion()]);
        unset($this->packages[$index]);
        if (isset($this->aliasMap[spl_object_hash($package)])) {
            foreach ($this->aliasMap[spl_object_hash($package)] as $aliasIndex => $aliasPackage) {
                unset($this->loadedPerRepo[$repoIndex][$aliasPackage->getName()][$aliasPackage->getVersion()]);
                unset($this->packages[$aliasIndex]);
            }
            unset($this->aliasMap[spl_object_hash($package)]);
        }
    }
    private function runOptimizer(\Composer\DependencyResolver\Request $request, \Composer\DependencyResolver\Pool $pool): \Composer\DependencyResolver\Pool
    {
        if (null === $this->poolOptimizer) {
            return $pool;
        }
        $this->io->debug('Running pool optimizer.');
        $before = microtime(\true);
        $total = \count($pool->getPackages());
        $pool = $this->poolOptimizer->optimize($request, $pool);
        $filtered = $total - \count($pool->getPackages());
        if (0 === $filtered) {
            return $pool;
        }
        $this->io->write(sprintf('Pool optimizer completed in %.3f seconds', microtime(\true) - $before), \true, IOInterface::VERY_VERBOSE);
        $this->io->write(sprintf('<info>Found %s package versions referenced in your dependency graph. %s (%d%%) were optimized away.</info>', number_format($total), number_format($filtered), round(100 / $total * $filtered)), \true, IOInterface::VERY_VERBOSE);
        return $pool;
    }
    /**
     * @param RepositoryInterface[] $repositories
     */
    private function runSecurityAdvisoryFilter(\Composer\DependencyResolver\Pool $pool, array $repositories, \Composer\DependencyResolver\Request $request): \Composer\DependencyResolver\Pool
    {
        if (null === $this->securityAdvisoryPoolFilter) {
            return $pool;
        }
        $this->io->debug('Running security advisory pool filter.');
        $before = microtime(\true);
        $total = \count($pool->getPackages());
        $pool = $this->securityAdvisoryPoolFilter->filter($pool, $repositories, $request);
        $filtered = $total - \count($pool->getPackages());
        if (0 === $filtered) {
            return $pool;
        }
        $this->io->write(sprintf('Security advisory pool filter completed in %.3f seconds', microtime(\true) - $before), \true, IOInterface::VERY_VERBOSE);
        $this->io->write(sprintf('<info>Found %s package versions referenced in your dependency graph. %s (%d%%) were filtered away.</info>', number_format($total), number_format($filtered), round(100 / $total * $filtered)), \true, IOInterface::VERY_VERBOSE);
        return $pool;
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer\DependencyResolver;

use Composer\Advisory\PartialSecurityAdvisory;
use Composer\Advisory\SecurityAdvisory;
use Composer\Package\CompletePackageInterface;
use Composer\Package\AliasPackage;
use Composer\Package\BasePackage;
use Composer\Package\Link;
use Composer\Package\PackageInterface;
use Composer\Package\RootPackageInterface;
use Composer\Pcre\Preg;
use Composer\Repository\RepositorySet;
use Composer\Repository\LockArrayRepository;
use Composer\Semver\Constraint\Constraint;
use Composer\Semver\Constraint\ConstraintInterface;
use Composer\Package\Version\VersionParser;
use Composer\Repository\PlatformRepository;
use Composer\Semver\Constraint\MultiConstraint;
use _ContaoManager\Symfony\Component\Console\Formatter\OutputFormatter;
/**
 * Represents a problem detected while solving dependencies
 *
 * @author Nils Adermann <naderman@naderman.de>
 */
class Problem
{
    /**
     * A map containing the id of each rule part of this problem as a key
     * @var array<string, true>
     */
    protected $reasonSeen;
    /**
     * A set of reasons for the problem, each is a rule or a root require and a rule
     * @var array<int, array<int, Rule>>
     */
    protected $reasons = [];
    /** @var int */
    protected $section = 0;
    /**
     * Add a rule as a reason
     *
     * @param Rule $rule A rule which is a reason for this problem
     */
    public function addRule(\Composer\DependencyResolver\Rule $rule): void
    {
        $this->addReason(spl_object_hash($rule), $rule);
    }
    /**
     * Retrieve all reasons for this problem
     *
     * @return array<int, array<int, Rule>> The problem's reasons
     */
    public function getReasons(): array
    {
        return $this->reasons;
    }
    /**
     * A human readable textual representation of the problem's reasons
     *
     * @param array<int|string, BasePackage> $installedMap A map of all present packages
     * @param array<Rule[]> $learnedPool
     */
    public function getPrettyString(RepositorySet $repositorySet, \Composer\DependencyResolver\Request $request, \Composer\DependencyResolver\Pool $pool, bool $isVerbose, array $installedMap = [], array $learnedPool = []): string
    {
        // TODO doesn't this entirely defeat the purpose of the problem sections? what's the point of sections?
        $reasons = array_merge(...array_reverse($this->reasons));
        if (\count($reasons) === 1) {
            reset($reasons);
            $rule = current($reasons);
            if ($rule->getReason() !== \Composer\DependencyResolver\Rule::RULE_ROOT_REQUIRE) {
                throw new \LogicException("Single reason problems must contain a root require rule.");
            }
            $reasonData = $rule->getReasonData();
            $packageName = $reasonData['packageName'];
            $constraint = $reasonData['constraint'];
            $packages = $pool->whatProvides($packageName, $constraint);
            if (\count($packages) === 0) {
                return "\n    " . implode(self::getMissingPackageReason($repositorySet, $request, $pool, $isVerbose, $packageName, $constraint));
            }
        }
        usort($reasons, function (\Composer\DependencyResolver\Rule $rule1, \Composer\DependencyResolver\Rule $rule2) use ($pool) {
            $rule1Prio = $this->getRulePriority($rule1);
            $rule2Prio = $this->getRulePriority($rule2);
            if ($rule1Prio !== $rule2Prio) {
                return $rule2Prio - $rule1Prio;
            }
            return $this->getSortableString($pool, $rule1) <=> $this->getSortableString($pool, $rule2);
        });
        return self::formatDeduplicatedRules($reasons, '    ', $repositorySet, $request, $pool, $isVerbose, $installedMap, $learnedPool);
    }
    private function getSortableString(\Composer\DependencyResolver\Pool $pool, \Composer\DependencyResolver\Rule $rule): string
    {
        switch ($rule->getReason()) {
            case \Composer\DependencyResolver\Rule::RULE_ROOT_REQUIRE:
                return $rule->getReasonData()['packageName'];
            case \Composer\DependencyResolver\Rule::RULE_FIXED:
                return (string) $rule->getReasonData()['package'];
            case \Composer\DependencyResolver\Rule::RULE_PACKAGE_CONFLICT:
            case \Composer\DependencyResolver\Rule::RULE_PACKAGE_REQUIRES:
                return $rule->getSourcePackage($pool) . '//' . $rule->getReasonData()->getPrettyString($rule->getSourcePackage($pool));
            case \Composer\DependencyResolver\Rule::RULE_PACKAGE_SAME_NAME:
            case \Composer\DependencyResolver\Rule::RULE_PACKAGE_ALIAS:
            case \Composer\DependencyResolver\Rule::RULE_PACKAGE_INVERSE_ALIAS:
                return (string) $rule->getReasonData();
            case \Composer\DependencyResolver\Rule::RULE_LEARNED:
                return implode('-', $rule->getLiterals());
        }
        // @phpstan-ignore deadCode.unreachable
        throw new \LogicException('Unknown rule type: ' . $rule->getReason());
    }
    private function getRulePriority(\Composer\DependencyResolver\Rule $rule): int
    {
        switch ($rule->getReason()) {
            case \Composer\DependencyResolver\Rule::RULE_FIXED:
                return 3;
            case \Composer\DependencyResolver\Rule::RULE_ROOT_REQUIRE:
                return 2;
            case \Composer\DependencyResolver\Rule::RULE_PACKAGE_CONFLICT:
            case \Composer\DependencyResolver\Rule::RULE_PACKAGE_REQUIRES:
                return 1;
            case \Composer\DependencyResolver\Rule::RULE_PACKAGE_SAME_NAME:
            case \Composer\DependencyResolver\Rule::RULE_LEARNED:
            case \Composer\DependencyResolver\Rule::RULE_PACKAGE_ALIAS:
            case \Composer\DependencyResolver\Rule::RULE_PACKAGE_INVERSE_ALIAS:
                return 0;
        }
        // @phpstan-ignore deadCode.unreachable
        throw new \LogicException('Unknown rule type: ' . $rule->getReason());
    }
    /**
     * @param Rule[] $rules
     * @param array<int|string, BasePackage> $installedMap A map of all present packages
     * @param array<Rule[]> $learnedPool
     * @internal
     */
    public static function formatDeduplicatedRules(array $rules, string $indent, RepositorySet $repositorySet, \Composer\DependencyResolver\Request $request, \Composer\DependencyResolver\Pool $pool, bool $isVerbose, array $installedMap = [], array $learnedPool = []): string
    {
        $messages = [];
        $templates = [];
        $parser = new VersionParser();
        $deduplicatableRuleTypes = [\Composer\DependencyResolver\Rule::RULE_PACKAGE_REQUIRES, \Composer\DependencyResolver\Rule::RULE_PACKAGE_CONFLICT];
        foreach ($rules as $rule) {
            $message = $rule->getPrettyString($repositorySet, $request, $pool, $isVerbose, $installedMap, $learnedPool);
            if (in_array($rule->getReason(), $deduplicatableRuleTypes, \true) && Preg::isMatchStrictGroups('{^(?P<package>\S+) (?P<version>\S+) (?P<type>requires|conflicts)}', $message, $m)) {
                $message = str_replace('%', '%%', $message);
                $template = Preg::replace('{^\S+ \S+ }', '%s%s ', $message);
                $messages[] = $template;
                $templates[$template][$m[1]][$parser->normalize($m[2])] = $m[2];
                $sourcePackage = $rule->getSourcePackage($pool);
                foreach ($pool->getRemovedVersionsByPackage(spl_object_hash($sourcePackage)) as $version => $prettyVersion) {
                    $templates[$template][$m[1]][$version] = $prettyVersion;
                }
            } elseif ($message !== '') {
                $messages[] = $message;
            }
        }
        $result = [];
        foreach (array_unique($messages) as $message) {
            if (isset($templates[$message])) {
                foreach ($templates[$message] as $package => $versions) {
                    uksort($versions, 'version_compare');
                    if (!$isVerbose) {
                        $versions = self::condenseVersionList($versions, 1);
                    }
                    if (\count($versions) > 1) {
                        // remove the s from requires/conflicts to correct grammar
                        $message = Preg::replace('{^(%s%s (?:require|conflict))s}', '$1', $message);
                        $result[] = sprintf($message, $package, '[' . implode(', ', $versions) . ']');
                    } else {
                        $result[] = sprintf($message, $package, ' ' . reset($versions));
                    }
                }
            } else {
                $result[] = $message;
            }
        }
        return "\n{$indent}- " . implode("\n{$indent}- ", $result);
    }
    public function isCausedByLock(RepositorySet $repositorySet, \Composer\DependencyResolver\Request $request, \Composer\DependencyResolver\Pool $pool): bool
    {
        foreach ($this->reasons as $sectionRules) {
            foreach ($sectionRules as $rule) {
                if ($rule->isCausedByLock($repositorySet, $request, $pool)) {
                    return \true;
                }
            }
        }
        return \false;
    }
    /**
     * Store a reason descriptor but ignore duplicates
     *
     * @param string $id     A canonical identifier for the reason
     * @param Rule   $reason The reason descriptor
     */
    protected function addReason(string $id, \Composer\DependencyResolver\Rule $reason): void
    {
        // TODO: if a rule is part of a problem description in two sections, isn't this going to remove a message
        // that is important to understand the issue?
        if (!isset($this->reasonSeen[$id])) {
            $this->reasonSeen[$id] = \true;
            $this->reasons[$this->section][] = $reason;
        }
    }
    public function nextSection(): void
    {
        $this->section++;
    }
    /**
     * @internal
     * @return array{0: string, 1: string}
     */
    public static function getMissingPackageReason(RepositorySet $repositorySet, \Composer\DependencyResolver\Request $request, \Composer\DependencyResolver\Pool $pool, bool $isVerbose, string $packageName, ?ConstraintInterface $constraint = null): array
    {
        if (PlatformRepository::isPlatformPackage($packageName)) {
            // handle php/php-*/hhvm
            if (0 === stripos($packageName, 'php') || $packageName === 'hhvm') {
                $version = self::getPlatformPackageVersion($pool, $packageName, phpversion());
                $msg = "- Root composer.json requires " . $packageName . self::constraintToText($constraint) . ' but ';
                if (defined('HHVM_VERSION') || $packageName === 'hhvm' && count($pool->whatProvides($packageName)) > 0) {
                    return [$msg, 'your HHVM version does not satisfy that requirement.'];
                }
                if ($packageName === 'hhvm') {
                    return [$msg, 'HHVM was not detected on this machine, make sure it is in your PATH.'];
                }
                if (null === $version) {
                    return [$msg, 'the ' . $packageName . ' package is disabled by your platform config. Enable it again with "composer config platform.' . $packageName . ' --unset".'];
                }
                return [$msg, 'your ' . $packageName . ' version (' . $version . ') does not satisfy that requirement.'];
            }
            // handle php extensions
            if (0 === stripos($packageName, 'ext-')) {
                if (\false !== strpos($packageName, ' ')) {
                    return ['- ', "PHP extension " . $packageName . ' should be required as ' . str_replace(' ', '-', $packageName) . '.'];
                }
                $ext = substr($packageName, 4);
                $msg = "- Root composer.json requires PHP extension " . $packageName . self::constraintToText($constraint) . ' but ';
                $version = self::getPlatformPackageVersion($pool, $packageName, phpversion($ext) === \false ? '0' : phpversion($ext));
                if (null === $version) {
                    $providersStr = self::getProvidersList($repositorySet, $packageName, 5);
                    if ($providersStr !== null) {
                        $providersStr = "\n\n      Alternatively you can require one of these packages that provide the extension (or parts of it):\n" . "      <warning>Keep in mind that the suggestions are automated and may not be valid or safe to use</warning>\n{$providersStr}";
                    }
                    if (extension_loaded($ext)) {
                        return [$msg, 'the ' . $packageName . ' package is disabled by your platform config. Enable it again with "composer config platform.' . $packageName . ' --unset".' . $providersStr];
                    }
                    return [$msg, 'it is missing from your system. Install or enable PHP\'s ' . $ext . ' extension.' . $providersStr];
                }
                return [$msg, 'it has the wrong version installed (' . $version . ').'];
            }
            // handle linked libs
            if (0 === stripos($packageName, 'lib-')) {
                if (strtolower($packageName) === 'lib-icu') {
                    $error = extension_loaded('intl') ? 'it has the wrong version installed, try upgrading the intl extension.' : 'it is missing from your system, make sure the intl extension is loaded.';
                    return ["- Root composer.json requires linked library " . $packageName . self::constraintToText($constraint) . ' but ', $error];
                }
                $providersStr = self::getProvidersList($repositorySet, $packageName, 5);
                if ($providersStr !== null) {
                    $providersStr = "\n\n      Alternatively you can require one of these packages that provide the library (or parts of it):\n" . "      <warning>Keep in mind that the suggestions are automated and may not be valid or safe to use</warning>\n{$providersStr}";
                }
                return ["- Root composer.json requires linked library " . $packageName . self::constraintToText($constraint) . ' but ', 'it has the wrong version installed or is missing from your system, make sure to load the extension providing it.' . $providersStr];
            }
        }
        $lockedPackage = null;
        foreach ($request->getLockedPackages() as $package) {
            if ($package->getName() === $packageName) {
                $lockedPackage = $package;
                if ($pool->isUnacceptableFixedOrLockedPackage($package)) {
                    return ["- ", $package->getPrettyName() . ' is fixed to ' . $package->getPrettyVersion() . ' (lock file version) by a partial update but that version is rejected by your minimum-stability. Make sure you list it as an argument for the update command.'];
                }
                break;
            }
        }
        if ($constraint instanceof Constraint && $constraint->getOperator() === Constraint::STR_OP_EQ && Preg::isMatch('{^dev-.*#.*}', $constraint->getPrettyString())) {
            $newConstraint = Preg::replace('{ +as +([^,\s|]+)$}', '', $constraint->getPrettyString());
            $packages = $repositorySet->findPackages($packageName, new MultiConstraint([new Constraint(Constraint::STR_OP_EQ, $newConstraint), new Constraint(Constraint::STR_OP_EQ, str_replace('#', '+', $newConstraint))], \false));
            if (\count($packages) > 0) {
                return ["- Root composer.json requires {$packageName}" . self::constraintToText($constraint) . ', ', 'found ' . self::getPackageList($packages, $isVerbose, $pool, $constraint) . '. The # character in branch names is replaced by a + character. Make sure to require it as "' . str_replace('#', '+', $constraint->getPrettyString()) . '".'];
            }
        }
        // first check if the actual requested package is found in normal conditions
        // if so it must mean it is rejected by another constraint than the one given here
        $packages = $repositorySet->findPackages($packageName, $constraint);
        if (\count($packages) > 0) {
            $rootReqs = $repositorySet->getRootRequires();
            if (isset($rootReqs[$packageName])) {
                $filtered = array_filter($packages, static function ($p) use ($rootReqs, $packageName): bool {
                    return $rootReqs[$packageName]->matches(new Constraint('==', $p->getVersion()));
                });
                if (0 === count($filtered)) {
                    return ["- Root composer.json requires {$packageName}" . self::constraintToText($constraint) . ', ', 'found ' . self::getPackageList($packages, $isVerbose, $pool, $constraint) . ' but ' . (self::hasMultipleNames($packages) ? 'these conflict' : 'it conflicts') . ' with your root composer.json require (' . $rootReqs[$packageName]->getPrettyString() . ').'];
                }
            }
            $tempReqs = $repositorySet->getTemporaryConstraints();
            foreach (reset($packages)->getNames() as $name) {
                if (isset($tempReqs[$name])) {
                    $filtered = array_filter($packages, static function ($p) use ($tempReqs, $name): bool {
                        return $tempReqs[$name]->matches(new Constraint('==', $p->getVersion()));
                    });
                    if (0 === count($filtered)) {
                        return ["- Root composer.json requires {$name}" . self::constraintToText($constraint) . ', ', 'found ' . self::getPackageList($packages, $isVerbose, $pool, $constraint) . ' but ' . (self::hasMultipleNames($packages) ? 'these conflict' : 'it conflicts') . ' with your temporary update constraint (' . $name . ':' . $tempReqs[$name]->getPrettyString() . ').'];
                    }
                }
            }
            if ($lockedPackage !== null) {
                $fixedConstraint = new Constraint('==', $lockedPackage->getVersion());
                $filtered = array_filter($packages, static function ($p) use ($fixedConstraint): bool {
                    return $fixedConstraint->matches(new Constraint('==', $p->getVersion()));
                });
                if (0 === count($filtered)) {
                    return ["- Root composer.json requires {$packageName}" . self::constraintToText($constraint) . ', ', 'found ' . self::getPackageList($packages, $isVerbose, $pool, $constraint) . ' but the package is fixed to ' . $lockedPackage->getPrettyVersion() . ' (lock file version) by a partial update and that version does not match. Make sure you list it as an argument for the update command.'];
                }
            }
            $nonLockedPackages = array_filter($packages, static function ($p): bool {
                return !$p->getRepository() instanceof LockArrayRepository;
            });
            if (0 === \count($nonLockedPackages)) {
                return ["- Root composer.json requires {$packageName}" . self::constraintToText($constraint) . ', ', 'found ' . self::getPackageList($packages, $isVerbose, $pool, $constraint) . ' in the lock file but not in remote repositories, make sure you avoid updating this package to keep the one from the lock file.'];
            }
            if ($pool->isAbandonedRemovedPackageVersion($packageName, $constraint)) {
                return ["- Root composer.json requires {$packageName}" . self::constraintToText($constraint) . ', ', 'found ' . self::getPackageList($packages, $isVerbose, $pool, $constraint) . ' but these were not loaded, because they are abandoned and you configured "block-abandoned" to true in your "audit" config.'];
            }
            if ($pool->isSecurityRemovedPackageVersion($packageName, $constraint)) {
                $advisories = $repositorySet->getMatchingSecurityAdvisories($packages, \false, \true);
                if (isset($advisories['advisories'][$packageName]) && \count($advisories['advisories'][$packageName]) > 0) {
                    $advisoriesList = array_map(static function (SecurityAdvisory $advisory): string {
                        if ($advisory->link !== null && $advisory->link !== '') {
                            return '<href=' . OutputFormatter::escape($advisory->link) . '>' . $advisory->advisoryId . '</>';
                        }
                        if (str_starts_with($advisory->advisoryId, 'PKSA-')) {
                            return '<href=' . OutputFormatter::escape('https://packagist.org/security-advisories/' . $advisory->advisoryId) . '>' . $advisory->advisoryId . '</>';
                        }
                        return $advisory->advisoryId;
                    }, $advisories['advisories'][$packageName]);
                } else {
                    $advisoriesList = array_map(static function (string $advisoryId): string {
                        if (str_starts_with($advisoryId, 'PKSA-')) {
                            return '<href=' . OutputFormatter::escape('https://packagist.org/security-advisories/' . $advisoryId) . '>' . $advisoryId . '</>';
                        }
                        return $advisoryId;
                    }, $pool->getSecurityAdvisoryIdentifiersForPackageVersion($packageName, $constraint));
                }
                return ["- Root composer.json requires {$packageName}" . self::constraintToText($constraint) . ', ', 'found ' . self::getPackageList($packages, $isVerbose, $pool, $constraint) . ' but these were not loaded, because they are affected by security advisories ("' . implode('", "', $advisoriesList) . '"). Go to https://packagist.org/security-advisories/ to find advisory details. To ignore the advisories, add them to the audit "ignore" config. To turn the feature off entirely, you can set "block-insecure" to false in your "audit" config.'];
            }
            return ["- Root composer.json requires {$packageName}" . self::constraintToText($constraint) . ', ', 'found ' . self::getPackageList($packages, $isVerbose, $pool, $constraint) . ' but these were not loaded, likely because ' . (self::hasMultipleNames($packages) ? 'they conflict' : 'it conflicts') . ' with another require.'];
        }
        // check if the package is found when bypassing stability checks
        $packages = $repositorySet->findPackages($packageName, $constraint, RepositorySet::ALLOW_UNACCEPTABLE_STABILITIES);
        if (\count($packages) > 0) {
            // we must first verify if a valid package would be found in a lower priority repository
            $allReposPackages = $repositorySet->findPackages($packageName, $constraint, RepositorySet::ALLOW_SHADOWED_REPOSITORIES);
            if (\count($allReposPackages) > 0) {
                return self::computeCheckForLowerPrioRepo($pool, $isVerbose, $packageName, $packages, $allReposPackages, 'minimum-stability', $constraint);
            }
            return ["- Root composer.json requires {$packageName}" . self::constraintToText($constraint) . ', ', 'found ' . self::getPackageList($packages, $isVerbose, $pool, $constraint) . ' but ' . (self::hasMultipleNames($packages) ? 'these do' : 'it does') . ' not match your minimum-stability.'];
        }
        // check if the package is found when bypassing the constraint and stability checks
        $packages = $repositorySet->findPackages($packageName, null, RepositorySet::ALLOW_UNACCEPTABLE_STABILITIES);
        if (\count($packages) > 0) {
            // we must first verify if a valid package would be found in a lower priority repository
            $allReposPackages = $repositorySet->findPackages($packageName, $constraint, RepositorySet::ALLOW_SHADOWED_REPOSITORIES);
            if (\count($allReposPackages) > 0) {
                return self::computeCheckForLowerPrioRepo($pool, $isVerbose, $packageName, $packages, $allReposPackages, 'constraint', $constraint);
            }
            $suffix = '';
            if ($constraint instanceof Constraint && $constraint->getVersion() === 'dev-master') {
                foreach ($packages as $candidate) {
                    if (in_array($candidate->getVersion(), ['dev-default', 'dev-main'], \true)) {
                        $suffix = ' Perhaps dev-master was renamed to ' . $candidate->getPrettyVersion() . '?';
                        break;
                    }
                }
            }
            // check if the root package is a name match and hint the dependencies on root troubleshooting article
            $allReposPackages = $packages;
            $topPackage = reset($allReposPackages);
            if ($topPackage instanceof RootPackageInterface) {
                $suffix = ' See https://getcomposer.org/dep-on-root for details and assistance.';
            }
            return ["- Root composer.json requires {$packageName}" . self::constraintToText($constraint) . ', ', 'found ' . self::getPackageList($packages, $isVerbose, $pool, $constraint) . ' but ' . (self::hasMultipleNames($packages) ? 'these do' : 'it does') . ' not match the constraint.' . $suffix];
        }
        if (!Preg::isMatch('{^[A-Za-z0-9_./-]+$}', $packageName)) {
            $illegalChars = Preg::replace('{[A-Za-z0-9_./-]+}', '', $packageName);
            return ["- Root composer.json requires {$packageName}, it ", 'could not be found, it looks like its name is invalid, "' . $illegalChars . '" is not allowed in package names.'];
        }
        $providersStr = self::getProvidersList($repositorySet, $packageName, 15);
        if ($providersStr !== null) {
            return ["- Root composer.json requires {$packageName}" . self::constraintToText($constraint) . ", it ", "could not be found in any version, but the following packages provide it:\n" . $providersStr . "      Consider requiring one of these to satisfy the {$packageName} requirement."];
        }
        return ["- Root composer.json requires {$packageName}, it ", "could not be found in any version, there may be a typo in the package name."];
    }
    /**
     * @internal
     * @param PackageInterface[] $packages
     */
    public static function getPackageList(array $packages, bool $isVerbose, ?\Composer\DependencyResolver\Pool $pool = null, ?ConstraintInterface $constraint = null, bool $useRemovedVersionGroup = \false): string
    {
        $prepared = [];
        $hasDefaultBranch = [];
        foreach ($packages as $package) {
            $prepared[$package->getName()]['name'] = $package->getPrettyName();
            $prepared[$package->getName()]['versions'][$package->getVersion()] = $package->getPrettyVersion() . ($package instanceof AliasPackage ? ' (alias of ' . $package->getAliasOf()->getPrettyVersion() . ')' : '');
            if ($pool !== null && $constraint !== null) {
                foreach ($pool->getRemovedVersions($package->getName(), $constraint) as $version => $prettyVersion) {
                    $prepared[$package->getName()]['versions'][$version] = $prettyVersion;
                }
            }
            if ($pool !== null && $useRemovedVersionGroup) {
                foreach ($pool->getRemovedVersionsByPackage(spl_object_hash($package)) as $version => $prettyVersion) {
                    $prepared[$package->getName()]['versions'][$version] = $prettyVersion;
                }
            }
            if ($package->isDefaultBranch()) {
                $hasDefaultBranch[$package->getName()] = \true;
            }
        }
        $preparedStrings = [];
        foreach ($prepared as $name => $package) {
            // remove the implicit default branch alias to avoid cruft in the display
            if (isset($package['versions'][VersionParser::DEFAULT_BRANCH_ALIAS], $hasDefaultBranch[$name])) {
                unset($package['versions'][VersionParser::DEFAULT_BRANCH_ALIAS]);
            }
            uksort($package['versions'], 'version_compare');
            if (!$isVerbose) {
                $package['versions'] = self::condenseVersionList($package['versions'], 4);
            }
            $preparedStrings[] = $package['name'] . '[' . implode(', ', $package['versions']) . ']';
        }
        return implode(', ', $preparedStrings);
    }
    /**
     * @param  string $version the effective runtime version of the platform package
     * @return ?string a version string or null if it appears the package was artificially disabled
     */
    private static function getPlatformPackageVersion(\Composer\DependencyResolver\Pool $pool, string $packageName, string $version): ?string
    {
        $available = $pool->whatProvides($packageName);
        if (\count($available) > 0) {
            $selected = null;
            foreach ($available as $pkg) {
                if ($pkg->getRepository() instanceof PlatformRepository) {
                    $selected = $pkg;
                    break;
                }
            }
            if ($selected === null) {
                $selected = reset($available);
            }
            // must be a package providing/replacing and not a real platform package
            if ($selected->getName() !== $packageName) {
                /** @var Link $link */
                foreach (array_merge(array_values($selected->getProvides()), array_values($selected->getReplaces())) as $link) {
                    if ($link->getTarget() === $packageName) {
                        return $link->getPrettyConstraint() . ' ' . substr($link->getDescription(), 0, -1) . 'd by ' . $selected->getPrettyString();
                    }
                }
            }
            $version = $selected->getPrettyVersion();
            $extra = $selected->getExtra();
            if ($selected instanceof CompletePackageInterface && isset($extra['config.platform']) && $extra['config.platform'] === \true) {
                $version .= '; ' . str_replace('Package ', '', (string) $selected->getDescription());
            }
        } else {
            return null;
        }
        return $version;
    }
    /**
     * @param array<string|int, string> $versions an array of pretty versions, with normalized versions as keys
     * @return list<string> a list of pretty versions and '...' where versions were removed
     */
    private static function condenseVersionList(array $versions, int $max, int $maxDev = 16): array
    {
        if (count($versions) <= $max) {
            return array_values($versions);
        }
        $filtered = [];
        $byMajor = [];
        foreach ($versions as $version => $pretty) {
            if (0 === stripos((string) $version, 'dev-')) {
                $byMajor['dev'][] = $pretty;
            } else {
                $byMajor[Preg::replace('{^(\d+)\..*}', '$1', (string) $version)][] = $pretty;
            }
        }
        foreach ($byMajor as $majorVersion => $versionsForMajor) {
            $maxVersions = $majorVersion === 'dev' ? $maxDev : $max;
            if (count($versionsForMajor) > $maxVersions) {
                // output only 1st and last versions
                $filtered[] = $versionsForMajor[0];
                $filtered[] = '...';
                $filtered[] = $versionsForMajor[count($versionsForMajor) - 1];
            } else {
                $filtered = array_merge($filtered, $versionsForMajor);
            }
        }
        return $filtered;
    }
    /**
     * @param PackageInterface[] $packages
     */
    private static function hasMultipleNames(array $packages): bool
    {
        $name = null;
        foreach ($packages as $package) {
            if ($name === null || $name === $package->getName()) {
                $name = $package->getName();
            } else {
                return \true;
            }
        }
        return \false;
    }
    /**
     * @param non-empty-array<PackageInterface> $higherRepoPackages
     * @param non-empty-array<PackageInterface> $allReposPackages
     * @return array{0: string, 1: string}
     */
    private static function computeCheckForLowerPrioRepo(\Composer\DependencyResolver\Pool $pool, bool $isVerbose, string $packageName, array $higherRepoPackages, array $allReposPackages, string $reason, ?ConstraintInterface $constraint = null): array
    {
        $nextRepoPackages = [];
        $nextRepo = null;
        foreach ($allReposPackages as $package) {
            if ($nextRepo === null || $nextRepo === $package->getRepository()) {
                $nextRepoPackages[] = $package;
                $nextRepo = $package->getRepository();
            } else {
                break;
            }
        }
        assert(null !== $nextRepo);
        if (\count($higherRepoPackages) > 0) {
            $topPackage = reset($higherRepoPackages);
            if ($topPackage instanceof RootPackageInterface) {
                return ["- Root composer.json requires {$packageName}" . self::constraintToText($constraint) . ', it is ', 'satisfiable by ' . self::getPackageList($nextRepoPackages, $isVerbose, $pool, $constraint) . ' from ' . $nextRepo->getRepoName() . ' but ' . $topPackage->getPrettyName() . ' ' . $topPackage->getPrettyVersion() . ' is the root package and cannot be modified. See https://getcomposer.org/dep-on-root for details and assistance.'];
            }
        }
        if ($nextRepo instanceof LockArrayRepository) {
            $singular = count($higherRepoPackages) === 1;
            $suggestion = 'Make sure you either fix the ' . $reason . ' or avoid updating this package to keep the one present in the lock file (' . self::getPackageList($nextRepoPackages, $isVerbose, $pool, $constraint) . ').';
            // symlinked path repos cannot be locked so do not suggest keeping it locked
            if ($nextRepoPackages[0]->getDistType() === 'path') {
                $transportOptions = $nextRepoPackages[0]->getTransportOptions();
                if (!isset($transportOptions['symlink']) || $transportOptions['symlink'] !== \false) {
                    $suggestion = 'Make sure you fix the ' . $reason . ' as packages installed from symlinked path repos are updated even in partial updates and the one from the lock file can thus not be used.';
                }
            }
            return ["- Root composer.json requires {$packageName}" . self::constraintToText($constraint) . ', ', 'found ' . self::getPackageList($higherRepoPackages, $isVerbose, $pool, $constraint) . ' but ' . ($singular ? 'it does' : 'these do') . ' not match your ' . $reason . ' and ' . ($singular ? 'is' : 'are') . ' therefore not installable. ' . $suggestion];
        }
        return ["- Root composer.json requires {$packageName}" . self::constraintToText($constraint) . ', it is ', 'satisfiable by ' . self::getPackageList($nextRepoPackages, $isVerbose, $pool, $constraint) . ' from ' . $nextRepo->getRepoName() . ' but ' . self::getPackageList($higherRepoPackages, $isVerbose, $pool, $constraint) . ' from ' . reset($higherRepoPackages)->getRepository()->getRepoName() . ' has higher repository priority. The packages from the higher priority repository do not match your ' . $reason . ' and are therefore not installable. That repository is canonical so the lower priority repo\'s packages are not installable. See https://getcomposer.org/repoprio for details and assistance.'];
    }
    /**
     * Turns a constraint into text usable in a sentence describing a request
     */
    protected static function constraintToText(?ConstraintInterface $constraint = null): string
    {
        if ($constraint instanceof Constraint && $constraint->getOperator() === Constraint::STR_OP_EQ && !str_starts_with($constraint->getVersion(), 'dev-')) {
            if (!Preg::isMatch('{^\d+(?:\.\d+)*$}', $constraint->getPrettyString())) {
                return ' ' . $constraint->getPrettyString() . ' (exact version match)';
            }
            $versions = [$constraint->getPrettyString()];
            for ($i = 3 - substr_count($versions[0], '.'); $i > 0; $i--) {
                $versions[] = end($versions) . '.0';
            }
            return ' ' . $constraint->getPrettyString() . ' (exact version match: ' . (count($versions) > 1 ? implode(', ', array_slice($versions, 0, -1)) . ' or ' . end($versions) : $versions[0]) . ')';
        }
        return $constraint !== null ? ' ' . $constraint->getPrettyString() : '';
    }
    private static function getProvidersList(RepositorySet $repositorySet, string $packageName, int $maxProviders): ?string
    {
        $providers = $repositorySet->getProviders($packageName);
        if (\count($providers) > 0) {
            $providersStr = implode(array_map(static function ($p): string {
                $description = $p['description'] !== '' && $p['description'] !== null ? ' ' . substr($p['description'], 0, 100) : '';
                return '      - ' . $p['name'] . $description . "\n";
            }, count($providers) > $maxProviders + 1 ? array_slice($providers, 0, $maxProviders) : $providers));
            if (count($providers) > $maxProviders + 1) {
                $providersStr .= '      ... and ' . (count($providers) - $maxProviders) . ' more.' . "\n";
            }
            return $providersStr;
        }
        return null;
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer\DependencyResolver;

/**
 * @author Nils Adermann <naderman@naderman.de>
 * @implements \Iterator<RuleSet::TYPE_*|-1, Rule>
 */
class RuleSetIterator implements \Iterator
{
    /** @var array<RuleSet::TYPE_*, Rule[]> */
    protected $rules;
    /** @var array<RuleSet::TYPE_*> */
    protected $types;
    /** @var int */
    protected $currentOffset;
    /** @var RuleSet::TYPE_*|-1 */
    protected $currentType;
    /** @var int */
    protected $currentTypeOffset;
    /**
     * @param array<RuleSet::TYPE_*, Rule[]> $rules
     */
    public function __construct(array $rules)
    {
        $this->rules = $rules;
        $this->types = array_keys($rules);
        sort($this->types);
        $this->rewind();
    }
    public function current(): \Composer\DependencyResolver\Rule
    {
        return $this->rules[$this->currentType][$this->currentOffset];
    }
    /**
     * @return RuleSet::TYPE_*|-1
     */
    public function key(): int
    {
        return $this->currentType;
    }
    public function next(): void
    {
        $this->currentOffset++;
        if (!isset($this->rules[$this->currentType])) {
            return;
        }
        if ($this->currentOffset >= \count($this->rules[$this->currentType])) {
            $this->currentOffset = 0;
            do {
                $this->currentTypeOffset++;
                if (!isset($this->types[$this->currentTypeOffset])) {
                    $this->currentType = -1;
                    break;
                }
                $this->currentType = $this->types[$this->currentTypeOffset];
            } while (0 === \count($this->rules[$this->currentType]));
        }
    }
    public function rewind(): void
    {
        $this->currentOffset = 0;
        $this->currentTypeOffset = -1;
        $this->currentType = -1;
        do {
            $this->currentTypeOffset++;
            if (!isset($this->types[$this->currentTypeOffset])) {
                $this->currentType = -1;
                break;
            }
            $this->currentType = $this->types[$this->currentTypeOffset];
        } while (0 === \count($this->rules[$this->currentType]));
    }
    public function valid(): bool
    {
        return isset($this->rules[$this->currentType], $this->rules[$this->currentType][$this->currentOffset]);
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer\DependencyResolver;

use Composer\Advisory\AuditConfig;
use Composer\Advisory\Auditor;
use Composer\Advisory\PartialSecurityAdvisory;
use Composer\Advisory\SecurityAdvisory;
use Composer\Package\PackageInterface;
use Composer\Package\RootPackageInterface;
use Composer\Repository\PlatformRepository;
use Composer\Repository\RepositoryInterface;
use Composer\Repository\RepositorySet;
use Composer\Semver\Constraint\Constraint;
/**
 * @internal
 */
class SecurityAdvisoryPoolFilter
{
    /** @var Auditor */
    private $auditor;
    /** @var AuditConfig $auditConfig */
    private $auditConfig;
    public function __construct(Auditor $auditor, AuditConfig $auditConfig)
    {
        $this->auditor = $auditor;
        $this->auditConfig = $auditConfig;
    }
    /**
     * @param array<RepositoryInterface> $repositories
     */
    public function filter(\Composer\DependencyResolver\Pool $pool, array $repositories, \Composer\DependencyResolver\Request $request): \Composer\DependencyResolver\Pool
    {
        if (!$this->auditConfig->blockInsecure) {
            return $pool;
        }
        $repoSet = new RepositorySet();
        foreach ($repositories as $repo) {
            $repoSet->addRepository($repo);
        }
        $packagesForAdvisories = [];
        foreach ($pool->getPackages() as $package) {
            if (!$package instanceof RootPackageInterface && !PlatformRepository::isPlatformPackage($package->getName()) && !$request->isLockedPackage($package)) {
                $packagesForAdvisories[] = $package;
            }
        }
        $allAdvisories = $repoSet->getMatchingSecurityAdvisories($packagesForAdvisories, \true, \true);
        if ($this->auditor->needsCompleteAdvisoryLoad($allAdvisories['advisories'], $this->auditConfig->ignoreListForBlocking)) {
            $allAdvisories = $repoSet->getMatchingSecurityAdvisories($packagesForAdvisories, \false, \true);
        }
        $advisoryMap = $this->auditor->processAdvisories($allAdvisories['advisories'], $this->auditConfig->ignoreListForBlocking, $this->auditConfig->ignoreSeverityForBlocking)['advisories'];
        $packages = [];
        $securityRemovedVersions = [];
        $abandonedRemovedVersions = [];
        foreach ($pool->getPackages() as $package) {
            if ($this->auditConfig->blockAbandoned && count($this->auditor->filterAbandonedPackages([$package], $this->auditConfig->ignoreAbandonedForBlocking)) !== 0) {
                foreach ($package->getNames(\false) as $packageName) {
                    $abandonedRemovedVersions[$packageName][$package->getVersion()] = $package->getPrettyVersion();
                }
                continue;
            }
            $matchingAdvisories = $this->getMatchingAdvisories($package, $advisoryMap);
            if (count($matchingAdvisories) > 0) {
                foreach ($package->getNames(\false) as $packageName) {
                    $securityRemovedVersions[$packageName][$package->getVersion()] = $matchingAdvisories;
                }
                continue;
            }
            $packages[] = $package;
        }
        return new \Composer\DependencyResolver\Pool($packages, $pool->getUnacceptableFixedOrLockedPackages(), $pool->getAllRemovedVersions(), $pool->getAllRemovedVersionsByPackage(), $securityRemovedVersions, $abandonedRemovedVersions);
    }
    /**
     * @param array<string, array<PartialSecurityAdvisory|SecurityAdvisory>> $advisoryMap
     * @return list<PartialSecurityAdvisory|SecurityAdvisory>
     */
    private function getMatchingAdvisories(PackageInterface $package, array $advisoryMap): array
    {
        if ($package->isDev()) {
            return [];
        }
        $matchingAdvisories = [];
        foreach ($package->getNames(\false) as $packageName) {
            if (!isset($advisoryMap[$packageName])) {
                continue;
            }
            $packageConstraint = new Constraint(Constraint::STR_OP_EQ, $package->getVersion());
            foreach ($advisoryMap[$packageName] as $advisory) {
                if ($advisory->affectedVersions->matches($packageConstraint)) {
                    $matchingAdvisories[] = $advisory;
                }
            }
        }
        return $matchingAdvisories;
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer\DependencyResolver;

/**
 * An extension of SplDoublyLinkedList with seek and removal of current element
 *
 * SplDoublyLinkedList only allows deleting a particular offset and has no
 * method to set the internal iterator to a particular offset.
 *
 * @author Nils Adermann <naderman@naderman.de>
 * @extends \SplDoublyLinkedList<RuleWatchNode>
 */
class RuleWatchChain extends \SplDoublyLinkedList
{
    /**
     * Moves the internal iterator to the specified offset
     *
     * @param int $offset The offset to seek to.
     */
    public function seek(int $offset): void
    {
        $this->rewind();
        for ($i = 0; $i < $offset; $i++, $this->next()) {
        }
    }
    /**
     * Removes the current element from the list
     *
     * As SplDoublyLinkedList only allows deleting a particular offset and
     * incorrectly sets the internal iterator if you delete the current value
     * this method sets the internal iterator back to the following element
     * using the seek method.
     */
    public function remove(): void
    {
        $offset = $this->key();
        $this->offsetUnset($offset);
        $this->seek($offset);
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer\Autoload;

use Composer\ClassMapGenerator\ClassMap;
use Composer\ClassMapGenerator\ClassMapGenerator;
use Composer\Config;
use Composer\EventDispatcher\EventDispatcher;
use Composer\Filter\PlatformRequirementFilter\IgnoreAllPlatformRequirementFilter;
use Composer\Filter\PlatformRequirementFilter\PlatformRequirementFilterFactory;
use Composer\Filter\PlatformRequirementFilter\PlatformRequirementFilterInterface;
use Composer\Installer\InstallationManager;
use Composer\IO\IOInterface;
use Composer\IO\NullIO;
use Composer\Package\AliasPackage;
use Composer\Package\PackageInterface;
use Composer\Package\RootPackageInterface;
use Composer\Pcre\Preg;
use Composer\Repository\InstalledRepositoryInterface;
use Composer\Semver\Constraint\Bound;
use Composer\Util\Filesystem;
use Composer\Util\Platform;
use Composer\Script\ScriptEvents;
use Composer\Util\PackageSorter;
use Composer\Json\JsonFile;
use Composer\Package\Locker;
use _ContaoManager\Symfony\Component\Console\Formatter\OutputFormatter;
/**
 * @author Igor Wiedler <igor@wiedler.ch>
 * @author Jordi Boggiano <j.boggiano@seld.be>
 */
class AutoloadGenerator
{
    /**
     * @var EventDispatcher
     */
    private $eventDispatcher;
    /**
     * @var IOInterface
     */
    private $io;
    /**
     * @var ?bool
     */
    private $devMode = null;
    /**
     * @var bool
     */
    private $classMapAuthoritative = \false;
    /**
     * @var bool
     */
    private $apcu = \false;
    /**
     * @var string|null
     */
    private $apcuPrefix;
    /**
     * @var bool
     */
    private $dryRun = \false;
    /**
     * @var bool
     */
    private $runScripts = \false;
    /**
     * @var PlatformRequirementFilterInterface
     */
    private $platformRequirementFilter;
    public function __construct(EventDispatcher $eventDispatcher, ?IOInterface $io = null)
    {
        $this->eventDispatcher = $eventDispatcher;
        $this->io = $io ?? new NullIO();
        $this->platformRequirementFilter = PlatformRequirementFilterFactory::ignoreNothing();
    }
    /**
     * @return void
     */
    public function setDevMode(bool $devMode = \true)
    {
        $this->devMode = $devMode;
    }
    /**
     * Whether generated autoloader considers the class map authoritative.
     *
     * @return void
     */
    public function setClassMapAuthoritative(bool $classMapAuthoritative)
    {
        $this->classMapAuthoritative = $classMapAuthoritative;
    }
    /**
     * Whether generated autoloader considers APCu caching.
     *
     * @return void
     */
    public function setApcu(bool $apcu, ?string $apcuPrefix = null)
    {
        $this->apcu = $apcu;
        $this->apcuPrefix = $apcuPrefix;
    }
    /**
     * Whether to run scripts or not
     *
     * @return void
     */
    public function setRunScripts(bool $runScripts = \true)
    {
        $this->runScripts = $runScripts;
    }
    /**
     * Whether to run in drymode or not
     */
    public function setDryRun(bool $dryRun = \true): void
    {
        $this->dryRun = $dryRun;
    }
    /**
     * Whether platform requirements should be ignored.
     *
     * If this is set to true, the platform check file will not be generated
     * If this is set to false, the platform check file will be generated with all requirements
     * If this is set to string[], those packages will be ignored from the platform check file
     *
     * @param bool|string[] $ignorePlatformReqs
     * @return void
     *
     * @deprecated use setPlatformRequirementFilter instead
     */
    public function setIgnorePlatformRequirements($ignorePlatformReqs)
    {
        trigger_error('AutoloadGenerator::setIgnorePlatformRequirements is deprecated since Composer 2.2, use setPlatformRequirementFilter instead.', \E_USER_DEPRECATED);
        $this->setPlatformRequirementFilter(PlatformRequirementFilterFactory::fromBoolOrList($ignorePlatformReqs));
    }
    /**
     * @return void
     */
    public function setPlatformRequirementFilter(PlatformRequirementFilterInterface $platformRequirementFilter)
    {
        $this->platformRequirementFilter = $platformRequirementFilter;
    }
    /**
     * @return ClassMap
     * @throws \Seld\JsonLint\ParsingException
     * @throws \RuntimeException
     */
    public function dump(Config $config, InstalledRepositoryInterface $localRepo, RootPackageInterface $rootPackage, InstallationManager $installationManager, string $targetDir, bool $scanPsrPackages = \false, ?string $suffix = null, ?Locker $locker = null, bool $strictAmbiguous = \false)
    {
        if ($this->classMapAuthoritative) {
            // Force scanPsrPackages when classmap is authoritative
            $scanPsrPackages = \true;
        }
        // auto-set devMode based on whether dev dependencies are installed or not
        if (null === $this->devMode) {
            // we assume no-dev mode if no vendor dir is present or it is too old to contain dev information
            $this->devMode = \false;
            $installedJson = new JsonFile($config->get('vendor-dir') . '/composer/installed.json');
            if ($installedJson->exists()) {
                $installedJson = $installedJson->read();
                if (isset($installedJson['dev'])) {
                    $this->devMode = $installedJson['dev'];
                }
            }
        }
        if ($this->runScripts) {
            // set COMPOSER_DEV_MODE in case not set yet so it is available in the dump-autoload event listeners
            if (!isset($_SERVER['COMPOSER_DEV_MODE'])) {
                Platform::putEnv('COMPOSER_DEV_MODE', $this->devMode ? '1' : '0');
            }
            $this->eventDispatcher->dispatchScript(ScriptEvents::PRE_AUTOLOAD_DUMP, $this->devMode, [], ['optimize' => $scanPsrPackages]);
        }
        $classMapGenerator = new ClassMapGenerator(['php', 'inc', 'hh']);
        $classMapGenerator->avoidDuplicateScans();
        $filesystem = new Filesystem();
        $filesystem->ensureDirectoryExists($config->get('vendor-dir'));
        // Do not remove double realpath() calls.
        // Fixes failing Windows realpath() implementation.
        // See https://bugs.php.net/bug.php?id=72738
        $basePath = $filesystem->normalizePath(realpath(realpath(Platform::getCwd())));
        $vendorPath = $filesystem->normalizePath(realpath(realpath($config->get('vendor-dir'))));
        $useGlobalIncludePath = $config->get('use-include-path');
        $prependAutoloader = $config->get('prepend-autoloader') === \false ? 'false' : 'true';
        $targetDir = $vendorPath . '/' . $targetDir;
        $filesystem->ensureDirectoryExists($targetDir);
        $vendorPathCode = $filesystem->findShortestPathCode(realpath($targetDir), $vendorPath, \true);
        $vendorPathToTargetDirCode = $filesystem->findShortestPathCode($vendorPath, realpath($targetDir), \true);
        $appBaseDirCode = $filesystem->findShortestPathCode($vendorPath, $basePath, \true);
        $appBaseDirCode = str_replace('__DIR__', '$vendorDir', $appBaseDirCode);
        $namespacesFile = <<<EOF
<?php

// autoload_namespaces.php @generated by Composer

\$vendorDir = {$vendorPathCode};
\$baseDir = {$appBaseDirCode};

return array(

EOF;
        $psr4File = <<<EOF
<?php

// autoload_psr4.php @generated by Composer

\$vendorDir = {$vendorPathCode};
\$baseDir = {$appBaseDirCode};

return array(

EOF;
        // Collect information from all packages.
        $devPackageNames = $localRepo->getDevPackageNames();
        $packageMap = $this->buildPackageMap($installationManager, $rootPackage, $localRepo->getCanonicalPackages());
        if ($this->devMode) {
            // if dev mode is enabled, then we do not filter any dev packages out so disable this entirely
            $filteredDevPackages = \false;
        } else {
            // if the list of dev package names is available we use that straight, otherwise pass true which means use legacy algo to figure them out
            $filteredDevPackages = $devPackageNames ?: \true;
        }
        $autoloads = $this->parseAutoloads($packageMap, $rootPackage, $filteredDevPackages);
        // Process the 'psr-0' base directories.
        foreach ($autoloads['psr-0'] as $namespace => $paths) {
            $exportedPaths = [];
            foreach ($paths as $path) {
                $exportedPaths[] = $this->getPathCode($filesystem, $basePath, $vendorPath, $path);
            }
            $exportedPrefix = var_export($namespace, \true);
            $namespacesFile .= "    {$exportedPrefix} => ";
            $namespacesFile .= "array(" . implode(', ', $exportedPaths) . "),\n";
        }
        $namespacesFile .= ");\n";
        // Process the 'psr-4' base directories.
        foreach ($autoloads['psr-4'] as $namespace => $paths) {
            $exportedPaths = [];
            foreach ($paths as $path) {
                $exportedPaths[] = $this->getPathCode($filesystem, $basePath, $vendorPath, $path);
            }
            $exportedPrefix = var_export($namespace, \true);
            $psr4File .= "    {$exportedPrefix} => ";
            $psr4File .= "array(" . implode(', ', $exportedPaths) . "),\n";
        }
        $psr4File .= ");\n";
        // add custom psr-0 autoloading if the root package has a target dir
        $targetDirLoader = null;
        $mainAutoload = $rootPackage->getAutoload();
        if ($rootPackage->getTargetDir() && !empty($mainAutoload['psr-0'])) {
            $levels = substr_count($filesystem->normalizePath($rootPackage->getTargetDir()), '/') + 1;
            $prefixes = implode(', ', array_map(static function ($prefix): string {
                return var_export($prefix, \true);
            }, array_keys($mainAutoload['psr-0'])));
            $baseDirFromTargetDirCode = $filesystem->findShortestPathCode($targetDir, $basePath, \true);
            $targetDirLoader = <<<EOF

    public static function autoload(\$class)
    {
        \$dir = {$baseDirFromTargetDirCode} . '/';
        \$prefixes = array({$prefixes});
        foreach (\$prefixes as \$prefix) {
            if (0 !== strpos(\$class, \$prefix)) {
                continue;
            }
            \$path = \$dir . implode('/', array_slice(explode('\\\\', \$class), {$levels})).'.php';
            if (!\$path = stream_resolve_include_path(\$path)) {
                return false;
            }
            require \$path;

            return true;
        }
    }

EOF;
        }
        $excluded = [];
        if (!empty($autoloads['exclude-from-classmap'])) {
            $excluded = $autoloads['exclude-from-classmap'];
        }
        foreach ($autoloads['classmap'] as $dir) {
            $classMapGenerator->scanPaths($dir, $this->buildExclusionRegex($dir, $excluded));
        }
        if ($scanPsrPackages) {
            $namespacesToScan = [];
            // Scan the PSR-0/4 directories for class files, and add them to the class map
            foreach (['psr-4', 'psr-0'] as $psrType) {
                foreach ($autoloads[$psrType] as $namespace => $paths) {
                    $namespacesToScan[$namespace][] = ['paths' => $paths, 'type' => $psrType];
                }
            }
            krsort($namespacesToScan);
            foreach ($namespacesToScan as $namespace => $groups) {
                foreach ($groups as $group) {
                    foreach ($group['paths'] as $dir) {
                        $dir = $filesystem->normalizePath($filesystem->isAbsolutePath($dir) ? $dir : $basePath . '/' . $dir);
                        if (!is_dir($dir)) {
                            continue;
                        }
                        // if the vendor dir is contained within a psr-0/psr-4 dir being scanned we exclude it
                        if (str_contains($vendorPath, $dir . '/')) {
                            $exclusionRegex = $this->buildExclusionRegex($dir, array_merge($excluded, [$vendorPath . '/']));
                        } else {
                            $exclusionRegex = $this->buildExclusionRegex($dir, $excluded);
                        }
                        $classMapGenerator->scanPaths($dir, $exclusionRegex, $group['type'], $namespace);
                    }
                }
            }
        }
        $classMap = $classMapGenerator->getClassMap();
        if ($strictAmbiguous) {
            $ambiguousClasses = $classMap->getAmbiguousClasses(\false);
        } else {
            $ambiguousClasses = $classMap->getAmbiguousClasses();
        }
        foreach ($ambiguousClasses as $className => $ambiguousPaths) {
            if (count($ambiguousPaths) > 1) {
                $this->io->writeError('<warning>Warning: Ambiguous class resolution, "' . $className . '"' . ' was found ' . (count($ambiguousPaths) + 1) . 'x: in "' . $classMap->getClassPath($className) . '" and "' . implode('", "', $ambiguousPaths) . '", the first will be used.</warning>');
            } else {
                $this->io->writeError('<warning>Warning: Ambiguous class resolution, "' . $className . '"' . ' was found in both "' . $classMap->getClassPath($className) . '" and "' . implode('", "', $ambiguousPaths) . '", the first will be used.</warning>');
            }
        }
        if (\count($ambiguousClasses) > 0) {
            $this->io->writeError('<info>To resolve ambiguity in classes not under your control you can ignore them by path using <href=' . OutputFormatter::escape('https://getcomposer.org/doc/04-schema.md#exclude-files-from-classmaps') . '>exclude-from-classmap</>');
        }
        // output PSR violations which are not coming from the vendor dir
        $classMap->clearPsrViolationsByPath($vendorPath);
        foreach ($classMap->getPsrViolations() as $msg) {
            $this->io->writeError("<warning>{$msg}</warning>");
        }
        $classMap->addClass('Composer\InstalledVersions', $vendorPath . '/composer/InstalledVersions.php');
        $classMap->sort();
        $classmapFile = <<<EOF
<?php

// autoload_classmap.php @generated by Composer

\$vendorDir = {$vendorPathCode};
\$baseDir = {$appBaseDirCode};

return array(

EOF;
        foreach ($classMap->getMap() as $className => $path) {
            $pathCode = $this->getPathCode($filesystem, $basePath, $vendorPath, $path) . ",\n";
            $classmapFile .= '    ' . var_export($className, \true) . ' => ' . $pathCode;
        }
        $classmapFile .= ");\n";
        if ('' === $suffix) {
            $suffix = null;
        }
        if (null === $suffix) {
            $suffix = $config->get('autoloader-suffix');
            // carry over existing autoload.php's suffix if possible and none is configured
            if (null === $suffix && Filesystem::isReadable($vendorPath . '/autoload.php')) {
                $content = (string) file_get_contents($vendorPath . '/autoload.php');
                if (Preg::isMatch('{ComposerAutoloaderInit([^:\s]+)::}', $content, $match)) {
                    $suffix = $match[1];
                }
            }
            if (null === $suffix) {
                $suffix = $locker !== null && $locker->isLocked() ? $locker->getLockData()['content-hash'] : bin2hex(random_bytes(16));
            }
        }
        if ($this->dryRun) {
            return $classMap;
        }
        $filesystem->filePutContentsIfModified($targetDir . '/autoload_namespaces.php', $namespacesFile);
        $filesystem->filePutContentsIfModified($targetDir . '/autoload_psr4.php', $psr4File);
        $filesystem->filePutContentsIfModified($targetDir . '/autoload_classmap.php', $classmapFile);
        $includePathFilePath = $targetDir . '/include_paths.php';
        if ($includePathFileContents = $this->getIncludePathsFile($packageMap, $filesystem, $basePath, $vendorPath, $vendorPathCode, $appBaseDirCode)) {
            $filesystem->filePutContentsIfModified($includePathFilePath, $includePathFileContents);
        } elseif (file_exists($includePathFilePath)) {
            unlink($includePathFilePath);
        }
        $includeFilesFilePath = $targetDir . '/autoload_files.php';
        if ($includeFilesFileContents = $this->getIncludeFilesFile($autoloads['files'], $filesystem, $basePath, $vendorPath, $vendorPathCode, $appBaseDirCode)) {
            $filesystem->filePutContentsIfModified($includeFilesFilePath, $includeFilesFileContents);
        } elseif (file_exists($includeFilesFilePath)) {
            unlink($includeFilesFilePath);
        }
        $filesystem->filePutContentsIfModified($targetDir . '/autoload_static.php', $this->getStaticFile($suffix, $targetDir, $vendorPath, $basePath));
        $checkPlatform = $config->get('platform-check') !== \false && !$this->platformRequirementFilter instanceof IgnoreAllPlatformRequirementFilter;
        $platformCheckContent = null;
        if ($checkPlatform) {
            $platformCheckContent = $this->getPlatformCheck($packageMap, $config->get('platform-check'), $devPackageNames);
            if (null === $platformCheckContent) {
                $checkPlatform = \false;
            }
        }
        if ($checkPlatform) {
            $filesystem->filePutContentsIfModified($targetDir . '/platform_check.php', $platformCheckContent);
        } elseif (file_exists($targetDir . '/platform_check.php')) {
            unlink($targetDir . '/platform_check.php');
        }
        $filesystem->filePutContentsIfModified($vendorPath . '/autoload.php', $this->getAutoloadFile($vendorPathToTargetDirCode, $suffix));
        $filesystem->filePutContentsIfModified($targetDir . '/autoload_real.php', $this->getAutoloadRealFile(\true, (bool) $includePathFileContents, $targetDirLoader, (bool) $includeFilesFileContents, $vendorPathCode, $appBaseDirCode, $suffix, $useGlobalIncludePath, $prependAutoloader, $checkPlatform));
        $filesystem->safeCopy(__DIR__ . '/ClassLoader.php', $targetDir . '/ClassLoader.php');
        $filesystem->safeCopy(__DIR__ . '/../../../LICENSE', $targetDir . '/LICENSE');
        if ($this->runScripts) {
            $this->eventDispatcher->dispatchScript(ScriptEvents::POST_AUTOLOAD_DUMP, $this->devMode, [], ['optimize' => $scanPsrPackages]);
        }
        return $classMap;
    }
    /**
     * @param array<string> $excluded
     * @return non-empty-string|null
     */
    private function buildExclusionRegex(string $dir, array $excluded): ?string
    {
        if ([] === $excluded) {
            return null;
        }
        // filter excluded patterns here to only use those matching $dir
        // exclude-from-classmap patterns are all realpath'd so we can only filter them if $dir exists so that realpath($dir) will work
        // if $dir does not exist, it should anyway not find anything there so no trouble
        if (file_exists($dir)) {
            // transform $dir in the same way that exclude-from-classmap patterns are transformed so we can match them against each other
            $dirMatch = preg_quote(strtr(realpath($dir), '\\', '/'));
            // also match against the non-realpath version for symlinks
            $fs = new Filesystem();
            $absDir = $fs->isAbsolutePath($dir) ? $dir : realpath(Platform::getCwd()) . '/' . $dir;
            $dirMatchNormalized = preg_quote(strtr($fs->normalizePath($absDir), '\\', '/'));
            $isSymlink = $dirMatch !== $dirMatchNormalized;
            foreach ($excluded as $index => $pattern) {
                // extract the constant string prefix of the pattern here, until we reach a non-escaped regex special character
                $pattern = Preg::replace('{^(([^.+*?\[^\]$(){}=!<>|:\\\\#-]+|\\\\[.+*?\[^\]$(){}=!<>|:#-])*).*}', '$1', $pattern);
                // if the pattern is not a subset or superset of $dir, it is unrelated and we skip it
                if (!str_starts_with($pattern, $dirMatch) && !str_starts_with($dirMatch, $pattern) && (!$isSymlink || !str_starts_with($pattern, $dirMatchNormalized) && !str_starts_with($dirMatchNormalized, $pattern))) {
                    unset($excluded[$index]);
                }
            }
        }
        return \count($excluded) > 0 ? '{(' . implode('|', $excluded) . ')}' : null;
    }
    /**
     * @param PackageInterface[] $packages
     * @return non-empty-array<int, array{0: PackageInterface, 1: string|null}>
     */
    public function buildPackageMap(InstallationManager $installationManager, PackageInterface $rootPackage, array $packages)
    {
        // build package => install path map
        $packageMap = [[$rootPackage, '']];
        foreach ($packages as $package) {
            if ($package instanceof AliasPackage) {
                continue;
            }
            $this->validatePackage($package);
            $packageMap[] = [$package, $installationManager->getInstallPath($package)];
        }
        return $packageMap;
    }
    /**
     * @return void
     * @throws \InvalidArgumentException Throws an exception, if the package has illegal settings.
     */
    protected function validatePackage(PackageInterface $package)
    {
        $autoload = $package->getAutoload();
        if (!empty($autoload['psr-4']) && null !== $package->getTargetDir()) {
            $name = $package->getName();
            $package->getTargetDir();
            throw new \InvalidArgumentException("PSR-4 autoloading is incompatible with the target-dir property, remove the target-dir in package '{$name}'.");
        }
        if (!empty($autoload['psr-4'])) {
            foreach ($autoload['psr-4'] as $namespace => $dirs) {
                if ($namespace !== '' && '\\' !== substr($namespace, -1)) {
                    throw new \InvalidArgumentException("psr-4 namespaces must end with a namespace separator, '{$namespace}' does not, use '{$namespace}\\'.");
                }
            }
        }
    }
    /**
     * Compiles an ordered list of namespace => path mappings
     *
     * @param non-empty-array<int, array{0: PackageInterface, 1: string|null}> $packageMap array of array(package, installDir-relative-to-composer.json or null for metapackages)
     * @param RootPackageInterface $rootPackage root package instance
     * @param bool|string[] $filteredDevPackages If an array, the list of packages that must be removed. If bool, whether to filter out require-dev packages
     * @return array
     * @phpstan-return array{
     *     'psr-0': array<string, array<string>>,
     *     'psr-4': array<string, array<string>>,
     *     'classmap': array<int, string>,
     *     'files': array<string, string>,
     *     'exclude-from-classmap': array<int, string>,
     * }
     */
    public function parseAutoloads(array $packageMap, PackageInterface $rootPackage, $filteredDevPackages = \false)
    {
        $rootPackageMap = array_shift($packageMap);
        if (is_array($filteredDevPackages)) {
            $packageMap = array_filter($packageMap, static function ($item) use ($filteredDevPackages): bool {
                return !in_array($item[0]->getName(), $filteredDevPackages, \true);
            });
        } elseif ($filteredDevPackages) {
            $packageMap = $this->filterPackageMap($packageMap, $rootPackage);
        }
        $sortedPackageMap = $this->sortPackageMap($packageMap);
        $sortedPackageMap[] = $rootPackageMap;
        $reverseSortedMap = array_reverse($sortedPackageMap);
        // reverse-sorted means root first, then dependents, then their dependents, etc.
        // which makes sense to allow root to override classmap or psr-0/4 entries with higher precedence rules
        $psr0 = $this->parseAutoloadsType($reverseSortedMap, 'psr-0', $rootPackage);
        $psr4 = $this->parseAutoloadsType($reverseSortedMap, 'psr-4', $rootPackage);
        $classmap = $this->parseAutoloadsType($reverseSortedMap, 'classmap', $rootPackage);
        // sorted (i.e. dependents first) for files to ensure that dependencies are loaded/available once a file is included
        $files = $this->parseAutoloadsType($sortedPackageMap, 'files', $rootPackage);
        // using sorted here but it does not really matter as all are excluded equally
        $exclude = $this->parseAutoloadsType($sortedPackageMap, 'exclude-from-classmap', $rootPackage);
        krsort($psr0);
        krsort($psr4);
        return ['psr-0' => $psr0, 'psr-4' => $psr4, 'classmap' => $classmap, 'files' => $files, 'exclude-from-classmap' => $exclude];
    }
    /**
     * Registers an autoloader based on an autoload-map returned by parseAutoloads
     *
     * @param array<string, mixed[]> $autoloads see parseAutoloads return value
     * @return ClassLoader
     */
    public function createLoader(array $autoloads, ?string $vendorDir = null)
    {
        $loader = new \Composer\Autoload\ClassLoader($vendorDir);
        if (isset($autoloads['psr-0'])) {
            foreach ($autoloads['psr-0'] as $namespace => $path) {
                $loader->add($namespace, $path);
            }
        }
        if (isset($autoloads['psr-4'])) {
            foreach ($autoloads['psr-4'] as $namespace => $path) {
                $loader->addPsr4($namespace, $path);
            }
        }
        if (isset($autoloads['classmap'])) {
            $excluded = [];
            if (!empty($autoloads['exclude-from-classmap'])) {
                $excluded = $autoloads['exclude-from-classmap'];
            }
            $classMapGenerator = new ClassMapGenerator(['php', 'inc', 'hh']);
            $classMapGenerator->avoidDuplicateScans();
            foreach ($autoloads['classmap'] as $dir) {
                try {
                    $classMapGenerator->scanPaths($dir, $this->buildExclusionRegex($dir, $excluded));
                } catch (\RuntimeException $e) {
                    $this->io->writeError('<warning>' . $e->getMessage() . '</warning>');
                }
            }
            $loader->addClassMap($classMapGenerator->getClassMap()->getMap());
        }
        return $loader;
    }
    /**
     * @param array<int, array{0: PackageInterface, 1: string|null}> $packageMap
     * @return ?string
     */
    protected function getIncludePathsFile(array $packageMap, Filesystem $filesystem, string $basePath, string $vendorPath, string $vendorPathCode, string $appBaseDirCode)
    {
        $includePaths = [];
        foreach ($packageMap as $item) {
            [$package, $installPath] = $item;
            // packages that are not installed cannot autoload anything
            if (null === $installPath) {
                continue;
            }
            if (null !== $package->getTargetDir() && strlen($package->getTargetDir()) > 0) {
                $installPath = substr($installPath, 0, -strlen('/' . $package->getTargetDir()));
            }
            foreach ($package->getIncludePaths() as $includePath) {
                $includePath = trim($includePath, '/');
                $includePaths[] = $installPath === '' ? $includePath : $installPath . '/' . $includePath;
            }
        }
        if (\count($includePaths) === 0) {
            return null;
        }
        $includePathsCode = '';
        foreach ($includePaths as $path) {
            $includePathsCode .= "    " . $this->getPathCode($filesystem, $basePath, $vendorPath, $path) . ",\n";
        }
        return <<<EOF
<?php

// include_paths.php @generated by Composer

\$vendorDir = {$vendorPathCode};
\$baseDir = {$appBaseDirCode};

return array(
{$includePathsCode});

EOF;
    }
    /**
     * @param array<string, string> $files
     * @return ?string
     */
    protected function getIncludeFilesFile(array $files, Filesystem $filesystem, string $basePath, string $vendorPath, string $vendorPathCode, string $appBaseDirCode)
    {
        // Get the path to each file, and make sure these paths are unique.
        $files = array_map(function (string $functionFile) use ($filesystem, $basePath, $vendorPath): string {
            return $this->getPathCode($filesystem, $basePath, $vendorPath, $functionFile);
        }, $files);
        $uniqueFiles = array_unique($files);
        if (count($uniqueFiles) < count($files)) {
            $this->io->writeError('<warning>The following "files" autoload rules are included multiple times, this may cause issues and should be resolved:</warning>');
            foreach (array_unique(array_diff_assoc($files, $uniqueFiles)) as $duplicateFile) {
                $this->io->writeError('<warning> - ' . $duplicateFile . '</warning>');
            }
        }
        unset($uniqueFiles);
        $filesCode = '';
        foreach ($files as $fileIdentifier => $functionFile) {
            $filesCode .= '    ' . var_export($fileIdentifier, \true) . ' => ' . $functionFile . ",\n";
        }
        if (!$filesCode) {
            return null;
        }
        return <<<EOF
<?php

// autoload_files.php @generated by Composer

\$vendorDir = {$vendorPathCode};
\$baseDir = {$appBaseDirCode};

return array(
{$filesCode});

EOF;
    }
    /**
     * @return string
     */
    protected function getPathCode(Filesystem $filesystem, string $basePath, string $vendorPath, string $path)
    {
        if (!$filesystem->isAbsolutePath($path)) {
            $path = $basePath . '/' . $path;
        }
        $path = $filesystem->normalizePath($path);
        $baseDir = '';
        if (strpos($path . '/', $vendorPath . '/') === 0) {
            $path = (string) substr($path, strlen($vendorPath));
            $baseDir = '$vendorDir . ';
        } else {
            $path = $filesystem->normalizePath($filesystem->findShortestPath($basePath, $path, \true));
            if (!$filesystem->isAbsolutePath($path)) {
                $baseDir = '$baseDir . ';
                $path = '/' . $path;
            }
        }
        if (Preg::isMatch('{\.phar([\\\\/]|$)}', $path)) {
            $baseDir = "'phar://' . " . $baseDir;
        }
        return $baseDir . var_export($path, \true);
    }
    /**
     * @param array<int, array{0: PackageInterface, 1: string|null}> $packageMap
     * @param bool|'php-only' $checkPlatform
     * @param string[] $devPackageNames
     * @return ?string
     */
    protected function getPlatformCheck(array $packageMap, $checkPlatform, array $devPackageNames)
    {
        $lowestPhpVersion = Bound::zero();
        $requiredPhp64bit = \false;
        $requiredExtensions = [];
        $extensionProviders = [];
        foreach ($packageMap as $item) {
            $package = $item[0];
            foreach (array_merge($package->getReplaces(), $package->getProvides()) as $link) {
                if (Preg::isMatch('{^ext-(.+)$}iD', $link->getTarget(), $match)) {
                    $extensionProviders[$match[1]][] = $link->getConstraint();
                }
            }
        }
        foreach ($packageMap as $item) {
            $package = $item[0];
            // skip dev dependencies platform requirements as platform-check really should only be a production safeguard
            if (in_array($package->getName(), $devPackageNames, \true)) {
                continue;
            }
            foreach ($package->getRequires() as $link) {
                if ($this->platformRequirementFilter->isIgnored($link->getTarget())) {
                    continue;
                }
                if (in_array($link->getTarget(), ['php', 'php-64bit'], \true)) {
                    $constraint = $link->getConstraint();
                    if ($constraint->getLowerBound()->compareTo($lowestPhpVersion, '>')) {
                        $lowestPhpVersion = $constraint->getLowerBound();
                    }
                }
                if ('php-64bit' === $link->getTarget()) {
                    $requiredPhp64bit = \true;
                }
                if ($checkPlatform === \true && Preg::isMatch('{^ext-(.+)$}iD', $link->getTarget(), $match)) {
                    // skip extension checks if they have a valid provider/replacer
                    if (isset($extensionProviders[$match[1]])) {
                        foreach ($extensionProviders[$match[1]] as $provided) {
                            if ($provided->matches($link->getConstraint())) {
                                continue 2;
                            }
                        }
                    }
                    if ($match[1] === 'zend-opcache') {
                        $match[1] = 'zend opcache';
                    }
                    $extension = var_export($match[1], \true);
                    if ($match[1] === 'pcntl' || $match[1] === 'readline') {
                        $requiredExtensions[$extension] = "PHP_SAPI !== 'cli' || extension_loaded({$extension}) || \$missingExtensions[] = {$extension};\n";
                    } else {
                        $requiredExtensions[$extension] = "extension_loaded({$extension}) || \$missingExtensions[] = {$extension};\n";
                    }
                }
            }
        }
        ksort($requiredExtensions);
        $formatToPhpVersionId = static function (Bound $bound): int {
            if ($bound->isZero()) {
                return 0;
            }
            if ($bound->isPositiveInfinity()) {
                return 99999;
            }
            $version = str_replace('-', '.', $bound->getVersion());
            $chunks = array_map('intval', explode('.', $version));
            return $chunks[0] * 10000 + $chunks[1] * 100 + $chunks[2];
        };
        $formatToHumanReadable = static function (Bound $bound) {
            if ($bound->isZero()) {
                return 0;
            }
            if ($bound->isPositiveInfinity()) {
                return 99999;
            }
            $version = str_replace('-', '.', $bound->getVersion());
            $chunks = explode('.', $version);
            $chunks = array_slice($chunks, 0, 3);
            return implode('.', $chunks);
        };
        $requiredPhp = '';
        $requiredPhpError = '';
        if (!$lowestPhpVersion->isZero()) {
            $operator = $lowestPhpVersion->isInclusive() ? '>=' : '>';
            $requiredPhp = 'PHP_VERSION_ID ' . $operator . ' ' . $formatToPhpVersionId($lowestPhpVersion);
            $requiredPhpError = '"' . $operator . ' ' . $formatToHumanReadable($lowestPhpVersion) . '"';
        }
        if ($requiredPhp) {
            $requiredPhp = <<<PHP_CHECK

if (!({$requiredPhp})) {
    \$issues[] = 'Your Composer dependencies require a PHP version {$requiredPhpError}. You are running ' . PHP_VERSION . '.';
}

PHP_CHECK;
        }
        if ($requiredPhp64bit) {
            $requiredPhp .= <<<PHP_CHECK

if (PHP_INT_SIZE !== 8) {
    \$issues[] = 'Your Composer dependencies require a 64-bit build of PHP.';
}

PHP_CHECK;
        }
        $requiredExtensions = implode('', $requiredExtensions);
        if ('' !== $requiredExtensions) {
            $requiredExtensions = <<<EXT_CHECKS

\$missingExtensions = array();
{$requiredExtensions}
if (\$missingExtensions) {
    \$issues[] = 'Your Composer dependencies require the following PHP extensions to be installed: ' . implode(', ', \$missingExtensions) . '.';
}

EXT_CHECKS;
        }
        if (!$requiredPhp && !$requiredExtensions) {
            return null;
        }
        return <<<PLATFORM_CHECK
<?php

// platform_check.php @generated by Composer

\$issues = array();
{$requiredPhp}{$requiredExtensions}
if (\$issues) {
    if (!headers_sent()) {
        header('HTTP/1.1 500 Internal Server Error');
    }
    if (!ini_get('display_errors')) {
        if (PHP_SAPI === 'cli' || PHP_SAPI === 'phpdbg') {
            fwrite(STDERR, 'Composer detected issues in your platform:' . PHP_EOL.PHP_EOL . implode(PHP_EOL, \$issues) . PHP_EOL.PHP_EOL);
        } elseif (!headers_sent()) {
            echo 'Composer detected issues in your platform:' . PHP_EOL.PHP_EOL . str_replace('You are running '.PHP_VERSION.'.', '', implode(PHP_EOL, \$issues)) . PHP_EOL.PHP_EOL;
        }
    }
    throw new \\RuntimeException(
        'Composer detected issues in your platform: ' . implode(' ', \$issues)
    );
}

PLATFORM_CHECK;
    }
    /**
     * @return string
     */
    protected function getAutoloadFile(string $vendorPathToTargetDirCode, string $suffix)
    {
        $lastChar = $vendorPathToTargetDirCode[strlen($vendorPathToTargetDirCode) - 1];
        if ("'" === $lastChar || '"' === $lastChar) {
            $vendorPathToTargetDirCode = substr($vendorPathToTargetDirCode, 0, -1) . '/autoload_real.php' . $lastChar;
        } else {
            $vendorPathToTargetDirCode .= " . '/autoload_real.php'";
        }
        return <<<AUTOLOAD
<?php

// autoload.php @generated by Composer

if (PHP_VERSION_ID < 50600) {
    if (!headers_sent()) {
        header('HTTP/1.1 500 Internal Server Error');
    }
    \$err = 'Composer 2.3.0 dropped support for autoloading on PHP <5.6 and you are running '.PHP_VERSION.', please upgrade PHP or use Composer 2.2 LTS via "composer self-update --2.2". Aborting.'.PHP_EOL;
    if (!ini_get('display_errors')) {
        if (PHP_SAPI === 'cli' || PHP_SAPI === 'phpdbg') {
            fwrite(STDERR, \$err);
        } elseif (!headers_sent()) {
            echo \$err;
        }
    }
    throw new RuntimeException(\$err);
}

require_once {$vendorPathToTargetDirCode};

return ComposerAutoloaderInit{$suffix}::getLoader();

AUTOLOAD;
    }
    /**
     * @param string $vendorPathCode unused in this method
     * @param string $appBaseDirCode unused in this method
     * @param string $prependAutoloader 'true'|'false'
     * @return string
     */
    protected function getAutoloadRealFile(bool $useClassMap, bool $useIncludePath, ?string $targetDirLoader, bool $useIncludeFiles, string $vendorPathCode, string $appBaseDirCode, string $suffix, bool $useGlobalIncludePath, string $prependAutoloader, bool $checkPlatform)
    {
        $file = <<<HEADER
<?php

// autoload_real.php @generated by Composer

class ComposerAutoloaderInit{$suffix}
{
    private static \$loader;

    public static function loadClassLoader(\$class)
    {
        if ('Composer\\Autoload\\ClassLoader' === \$class) {
            require __DIR__ . '/ClassLoader.php';
        }
    }

    /**
     * @return \\Composer\\Autoload\\ClassLoader
     */
    public static function getLoader()
    {
        if (null !== self::\$loader) {
            return self::\$loader;
        }


HEADER;
        if ($checkPlatform) {
            $file .= <<<'PLATFORM_CHECK'
        require __DIR__ . '/platform_check.php';


PLATFORM_CHECK;
        }
        $file .= <<<CLASSLOADER_INIT
        spl_autoload_register(array('ComposerAutoloaderInit{$suffix}', 'loadClassLoader'), true, {$prependAutoloader});
        self::\$loader = \$loader = new \\Composer\\Autoload\\ClassLoader(\\dirname(__DIR__));
        spl_autoload_unregister(array('ComposerAutoloaderInit{$suffix}', 'loadClassLoader'));


CLASSLOADER_INIT;
        if ($useIncludePath) {
            $file .= <<<'INCLUDE_PATH'
        $includePaths = require __DIR__ . '/include_paths.php';
        $includePaths[] = get_include_path();
        set_include_path(implode(PATH_SEPARATOR, $includePaths));


INCLUDE_PATH;
        }
        // keeping PHP 5.6+ compatibility for the autoloader here by using call_user_func vs getInitializer()()
        $file .= <<<STATIC_INIT
        require __DIR__ . '/autoload_static.php';
        call_user_func(\\Composer\\Autoload\\ComposerStaticInit{$suffix}::getInitializer(\$loader));


STATIC_INIT;
        if ($this->classMapAuthoritative) {
            $file .= <<<'CLASSMAPAUTHORITATIVE'
        $loader->setClassMapAuthoritative(true);

CLASSMAPAUTHORITATIVE;
        }
        if ($this->apcu) {
            $apcuPrefix = var_export($this->apcuPrefix !== null ? $this->apcuPrefix : bin2hex(random_bytes(10)), \true);
            $file .= <<<APCU
        \$loader->setApcuPrefix({$apcuPrefix});

APCU;
        }
        if ($useGlobalIncludePath) {
            $file .= <<<'INCLUDEPATH'
        $loader->setUseIncludePath(true);

INCLUDEPATH;
        }
        if ($targetDirLoader) {
            $file .= <<<REGISTER_TARGET_DIR_AUTOLOAD
        spl_autoload_register(array('ComposerAutoloaderInit{$suffix}', 'autoload'), true, true);


REGISTER_TARGET_DIR_AUTOLOAD;
        }
        $file .= <<<REGISTER_LOADER
        \$loader->register({$prependAutoloader});


REGISTER_LOADER;
        if ($useIncludeFiles) {
            $file .= <<<INCLUDE_FILES
        \$filesToLoad = \\Composer\\Autoload\\ComposerStaticInit{$suffix}::\$files;
        \$requireFile = \\Closure::bind(static function (\$fileIdentifier, \$file) {
            if (empty(\$GLOBALS['__composer_autoload_files'][\$fileIdentifier])) {
                \$GLOBALS['__composer_autoload_files'][\$fileIdentifier] = true;

                require \$file;
            }
        }, null, null);
        foreach (\$filesToLoad as \$fileIdentifier => \$file) {
            \$requireFile(\$fileIdentifier, \$file);
        }


INCLUDE_FILES;
        }
        $file .= <<<METHOD_FOOTER
        return \$loader;
    }

METHOD_FOOTER;
        $file .= $targetDirLoader;
        return $file . <<<FOOTER
}

FOOTER;
    }
    /**
     * @param string $vendorPath input for findShortestPathCode
     * @param string $basePath input for findShortestPathCode
     * @return string
     */
    protected function getStaticFile(string $suffix, string $targetDir, string $vendorPath, string $basePath)
    {
        $file = <<<HEADER
<?php

// autoload_static.php @generated by Composer

namespace Composer\\Autoload;

class ComposerStaticInit{$suffix}
{

HEADER;
        $loader = new \Composer\Autoload\ClassLoader();
        $map = require $targetDir . '/autoload_namespaces.php';
        foreach ($map as $namespace => $path) {
            $loader->set($namespace, $path);
        }
        $map = require $targetDir . '/autoload_psr4.php';
        foreach ($map as $namespace => $path) {
            $loader->setPsr4($namespace, $path);
        }
        /**
         * @var string $vendorDir
         * @var string $baseDir
         */
        $classMap = require $targetDir . '/autoload_classmap.php';
        if ($classMap) {
            $loader->addClassMap($classMap);
        }
        $filesystem = new Filesystem();
        $vendorPathCode = ' => ' . $filesystem->findShortestPathCode(realpath($targetDir), $vendorPath, \true, \true) . " . '/";
        $vendorPharPathCode = ' => \'phar://\' . ' . $filesystem->findShortestPathCode(realpath($targetDir), $vendorPath, \true, \true) . " . '/";
        $appBaseDirCode = ' => ' . $filesystem->findShortestPathCode(realpath($targetDir), $basePath, \true, \true) . " . '/";
        $appBaseDirPharCode = ' => \'phar://\' . ' . $filesystem->findShortestPathCode(realpath($targetDir), $basePath, \true, \true) . " . '/";
        $absoluteVendorPathCode = ' => ' . substr(var_export(rtrim($vendorDir, '\/') . '/', \true), 0, -1);
        $absoluteVendorPharPathCode = ' => ' . substr(var_export(rtrim('phar://' . $vendorDir, '\/') . '/', \true), 0, -1);
        $absoluteAppBaseDirCode = ' => ' . substr(var_export(rtrim($baseDir, '\/') . '/', \true), 0, -1);
        $absoluteAppBaseDirPharCode = ' => ' . substr(var_export(rtrim('phar://' . $baseDir, '\/') . '/', \true), 0, -1);
        $initializer = '';
        $prefix = "\x00Composer\\Autoload\\ClassLoader\x00";
        $prefixLen = strlen($prefix);
        if (file_exists($targetDir . '/autoload_files.php')) {
            $maps = ['files' => require $targetDir . '/autoload_files.php'];
        } else {
            $maps = [];
        }
        foreach ((array) $loader as $prop => $value) {
            if (!is_array($value) || \count($value) === 0 || !str_starts_with($prop, $prefix)) {
                continue;
            }
            $maps[substr($prop, $prefixLen)] = $value;
        }
        foreach ($maps as $prop => $value) {
            $value = strtr(var_export($value, \true), [$absoluteVendorPathCode => $vendorPathCode, $absoluteVendorPharPathCode => $vendorPharPathCode, $absoluteAppBaseDirCode => $appBaseDirCode, $absoluteAppBaseDirPharCode => $appBaseDirPharCode]);
            $value = ltrim(Preg::replace('/^ */m', '    $0$0', $value));
            $value = Preg::replace('/ +$/m', '', $value);
            $file .= sprintf("    public static \$%s = %s;\n\n", $prop, $value);
            if ('files' !== $prop) {
                $initializer .= "            \$loader->{$prop} = ComposerStaticInit{$suffix}::\${$prop};\n";
            }
        }
        return $file . <<<INITIALIZER
    public static function getInitializer(ClassLoader \$loader)
    {
        return \\Closure::bind(function () use (\$loader) {
{$initializer}
        }, null, ClassLoader::class);
    }
}

INITIALIZER;
    }
    /**
     * @param array<int, array{0: PackageInterface, 1: string|null}> $packageMap
     * @param string $type one of: 'psr-0'|'psr-4'|'classmap'|'files'
     * @return array<int, string>|array<string, array<string>>|array<string, string>
     */
    protected function parseAutoloadsType(array $packageMap, string $type, RootPackageInterface $rootPackage)
    {
        $autoloads = [];
        foreach ($packageMap as $item) {
            [$package, $installPath] = $item;
            // packages that are not installed cannot autoload anything
            if (null === $installPath) {
                continue;
            }
            $autoload = $package->getAutoload();
            if ($this->devMode && $package === $rootPackage) {
                $autoload = array_merge_recursive($autoload, $package->getDevAutoload());
            }
            // skip misconfigured packages
            if (!isset($autoload[$type]) || !is_array($autoload[$type])) {
                continue;
            }
            if (null !== $package->getTargetDir() && $package !== $rootPackage) {
                $installPath = substr($installPath, 0, -strlen('/' . $package->getTargetDir()));
            }
            foreach ($autoload[$type] as $namespace => $paths) {
                if (in_array($type, ['psr-4', 'psr-0'], \true)) {
                    // normalize namespaces to ensure "\" becomes "" and others do not have leading separators as they are not needed
                    $namespace = ltrim($namespace, '\\');
                }
                foreach ((array) $paths as $path) {
                    if (($type === 'files' || $type === 'classmap' || $type === 'exclude-from-classmap') && $package->getTargetDir() && !Filesystem::isReadable($installPath . '/' . $path)) {
                        // remove target-dir from file paths of the root package
                        if ($package === $rootPackage) {
                            $targetDir = str_replace('\<dirsep\>', '[\\\\/]', preg_quote(str_replace(['/', '\\'], '<dirsep>', $package->getTargetDir())));
                            $path = ltrim(Preg::replace('{^' . $targetDir . '}', '', ltrim($path, '\/')), '\/');
                        } else {
                            // add target-dir from file paths that don't have it
                            $path = $package->getTargetDir() . '/' . $path;
                        }
                    }
                    if ($type === 'exclude-from-classmap') {
                        // first escape user input
                        $path = Preg::replace('{/+}', '/', preg_quote(trim(strtr($path, '\\', '/'), '/')));
                        // add support for wildcards * and **
                        $path = strtr($path, ['\*\*' => '.+?', '\*' => '[^/]+?']);
                        // add support for up-level relative paths
                        $updir = null;
                        $path = Preg::replaceCallback('{^((?:(?:\\\\\\.){1,2}+/)+)}', static function ($matches) use (&$updir): string {
                            // undo preg_quote for the matched string
                            $updir = str_replace('\.', '.', $matches[1]);
                            return '';
                        }, $path);
                        if (empty($installPath)) {
                            $installPath = strtr(Platform::getCwd(), '\\', '/');
                        }
                        $resolvedPath = realpath($installPath . '/' . $updir);
                        if (\false === $resolvedPath) {
                            continue;
                        }
                        $autoloads[] = preg_quote(strtr($resolvedPath, '\\', '/')) . '/' . $path . '($|/)';
                        continue;
                    }
                    $relativePath = empty($installPath) ? empty($path) ? '.' : $path : $installPath . '/' . $path;
                    if ($type === 'files') {
                        $autoloads[$this->getFileIdentifier($package, $path)] = $relativePath;
                        continue;
                    }
                    if ($type === 'classmap') {
                        $autoloads[] = $relativePath;
                        continue;
                    }
                    $autoloads[$namespace][] = $relativePath;
                }
            }
        }
        return $autoloads;
    }
    /**
     * @return string
     */
    protected function getFileIdentifier(PackageInterface $package, string $path)
    {
        // TODO composer v3 change this to sha1 or xxh3? Possibly not worth the potential breakage though
        return hash('md5', $package->getName() . ':' . $path);
    }
    /**
     * Filters out dev-dependencies
     *
     * @param array<int, array{0: PackageInterface, 1: string|null}> $packageMap
     * @return array<int, array{0: PackageInterface, 1: string|null}>
     */
    protected function filterPackageMap(array $packageMap, RootPackageInterface $rootPackage)
    {
        $packages = [];
        $include = [];
        $replacedBy = [];
        foreach ($packageMap as $item) {
            $package = $item[0];
            $name = $package->getName();
            $packages[$name] = $package;
            foreach ($package->getReplaces() as $replace) {
                $replacedBy[$replace->getTarget()] = $name;
            }
        }
        $add = static function (PackageInterface $package) use (&$add, $packages, &$include, $replacedBy): void {
            foreach ($package->getRequires() as $link) {
                $target = $link->getTarget();
                if (isset($replacedBy[$target])) {
                    $target = $replacedBy[$target];
                }
                if (!isset($include[$target])) {
                    $include[$target] = \true;
                    if (isset($packages[$target])) {
                        $add($packages[$target]);
                    }
                }
            }
        };
        $add($rootPackage);
        return array_filter($packageMap, static function ($item) use ($include): bool {
            $package = $item[0];
            foreach ($package->getNames() as $name) {
                if (isset($include[$name])) {
                    return \true;
                }
            }
            return \false;
        });
    }
    /**
     * Sorts packages by dependency weight
     *
     * Packages of equal weight are sorted alphabetically
     *
     * @param array<int, array{0: PackageInterface, 1: string|null}> $packageMap
     * @return array<int, array{0: PackageInterface, 1: string|null}>
     */
    protected function sortPackageMap(array $packageMap)
    {
        $packages = [];
        $paths = [];
        foreach ($packageMap as $item) {
            [$package, $path] = $item;
            $name = $package->getName();
            $packages[$name] = $package;
            $paths[$name] = $path;
        }
        $sortedPackages = PackageSorter::sortPackages($packages);
        $sortedPackageMap = [];
        foreach ($sortedPackages as $package) {
            $name = $package->getName();
            $sortedPackageMap[] = [$packages[$name], $paths[$name]];
        }
        return $sortedPackageMap;
    }
}
function composerRequire(string $fileIdentifier, string $file): void
{
    if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) {
        $GLOBALS['__composer_autoload_files'][$fileIdentifier] = \true;
        require $file;
    }
}
<?php

/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer\Autoload;

/**
 * ClassLoader implements a PSR-0, PSR-4 and classmap class loader.
 *
 *     $loader = new \Composer\Autoload\ClassLoader();
 *
 *     // register classes with namespaces
 *     $loader->add('Symfony\Component', __DIR__.'/component');
 *     $loader->add('Symfony',           __DIR__.'/framework');
 *
 *     // activate the autoloader
 *     $loader->register();
 *
 *     // to enable searching the include path (eg. for PEAR packages)
 *     $loader->setUseIncludePath(true);
 *
 * In this example, if you try to use a class in the Symfony\Component
 * namespace or one of its children (Symfony\Component\Console for instance),
 * the autoloader will first look for the class under the component/
 * directory, and it will then fallback to the framework/ directory if not
 * found before giving up.
 *
 * This class is loosely based on the Symfony UniversalClassLoader.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 * @author Jordi Boggiano <j.boggiano@seld.be>
 * @see    https://www.php-fig.org/psr/psr-0/
 * @see    https://www.php-fig.org/psr/psr-4/
 */
class ClassLoader
{
    /** @var \Closure(string):void */
    private static $includeFile;
    /** @var string|null */
    private $vendorDir;
    // PSR-4
    /**
     * @var array<string, array<string, int>>
     */
    private $prefixLengthsPsr4 = array();
    /**
     * @var array<string, list<string>>
     */
    private $prefixDirsPsr4 = array();
    /**
     * @var list<string>
     */
    private $fallbackDirsPsr4 = array();
    // PSR-0
    /**
     * List of PSR-0 prefixes
     *
     * Structured as array('F (first letter)' => array('Foo\Bar (full prefix)' => array('path', 'path2')))
     *
     * @var array<string, array<string, list<string>>>
     */
    private $prefixesPsr0 = array();
    /**
     * @var list<string>
     */
    private $fallbackDirsPsr0 = array();
    /** @var bool */
    private $useIncludePath = \false;
    /**
     * @var array<string, string>
     */
    private $classMap = array();
    /** @var bool */
    private $classMapAuthoritative = \false;
    /**
     * @var array<string, bool>
     */
    private $missingClasses = array();
    /** @var string|null */
    private $apcuPrefix;
    /**
     * @var array<string, self>
     */
    private static $registeredLoaders = array();
    /**
     * @param string|null $vendorDir
     */
    public function __construct($vendorDir = null)
    {
        $this->vendorDir = $vendorDir;
        self::initializeIncludeClosure();
    }
    /**
     * @return array<string, list<string>>
     */
    public function getPrefixes()
    {
        if (!empty($this->prefixesPsr0)) {
            return call_user_func_array('array_merge', array_values($this->prefixesPsr0));
        }
        return array();
    }
    /**
     * @return array<string, list<string>>
     */
    public function getPrefixesPsr4()
    {
        return $this->prefixDirsPsr4;
    }
    /**
     * @return list<string>
     */
    public function getFallbackDirs()
    {
        return $this->fallbackDirsPsr0;
    }
    /**
     * @return list<string>
     */
    public function getFallbackDirsPsr4()
    {
        return $this->fallbackDirsPsr4;
    }
    /**
     * @return array<string, string> Array of classname => path
     */
    public function getClassMap()
    {
        return $this->classMap;
    }
    /**
     * @param array<string, string> $classMap Class to filename map
     *
     * @return void
     */
    public function addClassMap(array $classMap)
    {
        if ($this->classMap) {
            $this->classMap = array_merge($this->classMap, $classMap);
        } else {
            $this->classMap = $classMap;
        }
    }
    /**
     * Registers a set of PSR-0 directories for a given prefix, either
     * appending or prepending to the ones previously set for this prefix.
     *
     * @param string              $prefix  The prefix
     * @param list<string>|string $paths   The PSR-0 root directories
     * @param bool                $prepend Whether to prepend the directories
     *
     * @return void
     */
    public function add($prefix, $paths, $prepend = \false)
    {
        $paths = (array) $paths;
        if (!$prefix) {
            if ($prepend) {
                $this->fallbackDirsPsr0 = array_merge($paths, $this->fallbackDirsPsr0);
            } else {
                $this->fallbackDirsPsr0 = array_merge($this->fallbackDirsPsr0, $paths);
            }
            return;
        }
        $first = $prefix[0];
        if (!isset($this->prefixesPsr0[$first][$prefix])) {
            $this->prefixesPsr0[$first][$prefix] = $paths;
            return;
        }
        if ($prepend) {
            $this->prefixesPsr0[$first][$prefix] = array_merge($paths, $this->prefixesPsr0[$first][$prefix]);
        } else {
            $this->prefixesPsr0[$first][$prefix] = array_merge($this->prefixesPsr0[$first][$prefix], $paths);
        }
    }
    /**
     * Registers a set of PSR-4 directories for a given namespace, either
     * appending or prepending to the ones previously set for this namespace.
     *
     * @param string              $prefix  The prefix/namespace, with trailing '\\'
     * @param list<string>|string $paths   The PSR-4 base directories
     * @param bool                $prepend Whether to prepend the directories
     *
     * @throws \InvalidArgumentException
     *
     * @return void
     */
    public function addPsr4($prefix, $paths, $prepend = \false)
    {
        $paths = (array) $paths;
        if (!$prefix) {
            // Register directories for the root namespace.
            if ($prepend) {
                $this->fallbackDirsPsr4 = array_merge($paths, $this->fallbackDirsPsr4);
            } else {
                $this->fallbackDirsPsr4 = array_merge($this->fallbackDirsPsr4, $paths);
            }
        } elseif (!isset($this->prefixDirsPsr4[$prefix])) {
            // Register directories for a new namespace.
            $length = strlen($prefix);
            if ('\\' !== $prefix[$length - 1]) {
                throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
            }
            $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
            $this->prefixDirsPsr4[$prefix] = $paths;
        } elseif ($prepend) {
            // Prepend directories for an already registered namespace.
            $this->prefixDirsPsr4[$prefix] = array_merge($paths, $this->prefixDirsPsr4[$prefix]);
        } else {
            // Append directories for an already registered namespace.
            $this->prefixDirsPsr4[$prefix] = array_merge($this->prefixDirsPsr4[$prefix], $paths);
        }
    }
    /**
     * Registers a set of PSR-0 directories for a given prefix,
     * replacing any others previously set for this prefix.
     *
     * @param string              $prefix The prefix
     * @param list<string>|string $paths  The PSR-0 base directories
     *
     * @return void
     */
    public function set($prefix, $paths)
    {
        if (!$prefix) {
            $this->fallbackDirsPsr0 = (array) $paths;
        } else {
            $this->prefixesPsr0[$prefix[0]][$prefix] = (array) $paths;
        }
    }
    /**
     * Registers a set of PSR-4 directories for a given namespace,
     * replacing any others previously set for this namespace.
     *
     * @param string              $prefix The prefix/namespace, with trailing '\\'
     * @param list<string>|string $paths  The PSR-4 base directories
     *
     * @throws \InvalidArgumentException
     *
     * @return void
     */
    public function setPsr4($prefix, $paths)
    {
        if (!$prefix) {
            $this->fallbackDirsPsr4 = (array) $paths;
        } else {
            $length = strlen($prefix);
            if ('\\' !== $prefix[$length - 1]) {
                throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
            }
            $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
            $this->prefixDirsPsr4[$prefix] = (array) $paths;
        }
    }
    /**
     * Turns on searching the include path for class files.
     *
     * @param bool $useIncludePath
     *
     * @return void
     */
    public function setUseIncludePath($useIncludePath)
    {
        $this->useIncludePath = $useIncludePath;
    }
    /**
     * Can be used to check if the autoloader uses the include path to check
     * for classes.
     *
     * @return bool
     */
    public function getUseIncludePath()
    {
        return $this->useIncludePath;
    }
    /**
     * Turns off searching the prefix and fallback directories for classes
     * that have not been registered with the class map.
     *
     * @param bool $classMapAuthoritative
     *
     * @return void
     */
    public function setClassMapAuthoritative($classMapAuthoritative)
    {
        $this->classMapAuthoritative = $classMapAuthoritative;
    }
    /**
     * Should class lookup fail if not found in the current class map?
     *
     * @return bool
     */
    public function isClassMapAuthoritative()
    {
        return $this->classMapAuthoritative;
    }
    /**
     * APCu prefix to use to cache found/not-found classes, if the extension is enabled.
     *
     * @param string|null $apcuPrefix
     *
     * @return void
     */
    public function setApcuPrefix($apcuPrefix)
    {
        $this->apcuPrefix = function_exists('apcu_fetch') && filter_var(ini_get('apc.enabled'), \FILTER_VALIDATE_BOOLEAN) ? $apcuPrefix : null;
    }
    /**
     * The APCu prefix in use, or null if APCu caching is not enabled.
     *
     * @return string|null
     */
    public function getApcuPrefix()
    {
        return $this->apcuPrefix;
    }
    /**
     * Registers this instance as an autoloader.
     *
     * @param bool $prepend Whether to prepend the autoloader or not
     *
     * @return void
     */
    public function register($prepend = \false)
    {
        spl_autoload_register(array($this, 'loadClass'), \true, $prepend);
        if (null === $this->vendorDir) {
            return;
        }
        if ($prepend) {
            self::$registeredLoaders = array($this->vendorDir => $this) + self::$registeredLoaders;
        } else {
            unset(self::$registeredLoaders[$this->vendorDir]);
            self::$registeredLoaders[$this->vendorDir] = $this;
        }
    }
    /**
     * Unregisters this instance as an autoloader.
     *
     * @return void
     */
    public function unregister()
    {
        spl_autoload_unregister(array($this, 'loadClass'));
        if (null !== $this->vendorDir) {
            unset(self::$registeredLoaders[$this->vendorDir]);
        }
    }
    /**
     * Loads the given class or interface.
     *
     * @param  string    $class The name of the class
     * @return true|null True if loaded, null otherwise
     */
    public function loadClass($class)
    {
        if ($file = $this->findFile($class)) {
            $includeFile = self::$includeFile;
            $includeFile($file);
            return \true;
        }
        return null;
    }
    /**
     * Finds the path to the file where the class is defined.
     *
     * @param string $class The name of the class
     *
     * @return string|false The path if found, false otherwise
     */
    public function findFile($class)
    {
        // class map lookup
        if (isset($this->classMap[$class])) {
            return $this->classMap[$class];
        }
        if ($this->classMapAuthoritative || isset($this->missingClasses[$class])) {
            return \false;
        }
        if (null !== $this->apcuPrefix) {
            $file = apcu_fetch($this->apcuPrefix . $class, $hit);
            if ($hit) {
                return $file;
            }
        }
        $file = $this->findFileWithExtension($class, '.php');
        // Search for Hack files if we are running on HHVM
        if (\false === $file && defined('HHVM_VERSION')) {
            $file = $this->findFileWithExtension($class, '.hh');
        }
        if (null !== $this->apcuPrefix) {
            apcu_add($this->apcuPrefix . $class, $file);
        }
        if (\false === $file) {
            // Remember that this class does not exist.
            $this->missingClasses[$class] = \true;
        }
        return $file;
    }
    /**
     * Returns the currently registered loaders keyed by their corresponding vendor directories.
     *
     * @return array<string, self>
     */
    public static function getRegisteredLoaders()
    {
        return self::$registeredLoaders;
    }
    /**
     * @param  string       $class
     * @param  string       $ext
     * @return string|false
     */
    private function findFileWithExtension($class, $ext)
    {
        // PSR-4 lookup
        $logicalPathPsr4 = strtr($class, '\\', \DIRECTORY_SEPARATOR) . $ext;
        $first = $class[0];
        if (isset($this->prefixLengthsPsr4[$first])) {
            $subPath = $class;
            while (\false !== $lastPos = strrpos($subPath, '\\')) {
                $subPath = substr($subPath, 0, $lastPos);
                $search = $subPath . '\\';
                if (isset($this->prefixDirsPsr4[$search])) {
                    $pathEnd = \DIRECTORY_SEPARATOR . substr($logicalPathPsr4, $lastPos + 1);
                    foreach ($this->prefixDirsPsr4[$search] as $dir) {
                        if (file_exists($file = $dir . $pathEnd)) {
                            return $file;
                        }
                    }
                }
            }
        }
        // PSR-4 fallback dirs
        foreach ($this->fallbackDirsPsr4 as $dir) {
            if (file_exists($file = $dir . \DIRECTORY_SEPARATOR . $logicalPathPsr4)) {
                return $file;
            }
        }
        // PSR-0 lookup
        if (\false !== $pos = strrpos($class, '\\')) {
            // namespaced class name
            $logicalPathPsr0 = substr($logicalPathPsr4, 0, $pos + 1) . strtr(substr($logicalPathPsr4, $pos + 1), '_', \DIRECTORY_SEPARATOR);
        } else {
            // PEAR-like class name
            $logicalPathPsr0 = strtr($class, '_', \DIRECTORY_SEPARATOR) . $ext;
        }
        if (isset($this->prefixesPsr0[$first])) {
            foreach ($this->prefixesPsr0[$first] as $prefix => $dirs) {
                if (0 === strpos($class, $prefix)) {
                    foreach ($dirs as $dir) {
                        if (file_exists($file = $dir . \DIRECTORY_SEPARATOR . $logicalPathPsr0)) {
                            return $file;
                        }
                    }
                }
            }
        }
        // PSR-0 fallback dirs
        foreach ($this->fallbackDirsPsr0 as $dir) {
            if (file_exists($file = $dir . \DIRECTORY_SEPARATOR . $logicalPathPsr0)) {
                return $file;
            }
        }
        // PSR-0 include paths.
        if ($this->useIncludePath && $file = stream_resolve_include_path($logicalPathPsr0)) {
            return $file;
        }
        return \false;
    }
    /**
     * @return void
     */
    private static function initializeIncludeClosure()
    {
        if (self::$includeFile !== null) {
            return;
        }
        /**
         * Scope isolated include.
         *
         * Prevents access to $this/self from included files.
         *
         * @param  string $file
         * @return void
         */
        self::$includeFile = \Closure::bind(static function ($file) {
            include $file;
        }, null, null);
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
/*
 * This file is copied from the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 */
namespace Composer\Autoload;

use Composer\ClassMapGenerator\FileList;
use Composer\IO\IOInterface;
/**
 * ClassMapGenerator
 *
 * @author Gyula Sallai <salla016@gmail.com>
 * @author Jordi Boggiano <j.boggiano@seld.be>
 *
 * @deprecated Since Composer 2.4.0 use the composer/class-map-generator package instead
 */
class ClassMapGenerator
{
    /**
     * Generate a class map file
     *
     * @param \Traversable<string>|array<string> $dirs Directories or a single path to search in
     * @param string                             $file The name of the class map file
     */
    public static function dump(iterable $dirs, string $file): void
    {
        $maps = [];
        foreach ($dirs as $dir) {
            $maps = array_merge($maps, static::createMap($dir));
        }
        file_put_contents($file, sprintf('<?php return %s;', var_export($maps, \true)));
    }
    /**
     * Iterate over all files in the given directory searching for classes
     *
     * @param \Traversable<\SplFileInfo>|string|array<\SplFileInfo> $path The path to search in or an iterator
     * @param non-empty-string|null                                 $excluded     Regex that matches file paths to be excluded from the classmap
     * @param ?IOInterface                                          $io           IO object
     * @param null|string                                           $namespace    Optional namespace prefix to filter by
     * @param null|'psr-0'|'psr-4'|'classmap'                       $autoloadType psr-0|psr-4 Optional autoload standard to use mapping rules
     * @param array<non-empty-string, true>                         $scannedFiles
     * @return array<class-string, non-empty-string> A class map array
     * @throws \RuntimeException When the path is neither an existing file nor directory
     */
    public static function createMap($path, ?string $excluded = null, ?IOInterface $io = null, ?string $namespace = null, ?string $autoloadType = null, array &$scannedFiles = []): array
    {
        $generator = new \Composer\ClassMapGenerator\ClassMapGenerator(['php', 'inc', 'hh']);
        $fileList = new FileList();
        $fileList->files = $scannedFiles;
        $generator->avoidDuplicateScans($fileList);
        $generator->scanPaths($path, $excluded, $autoloadType ?? 'classmap', $namespace);
        $classMap = $generator->getClassMap();
        $scannedFiles = $fileList->files;
        if ($io !== null) {
            foreach ($classMap->getPsrViolations() as $msg) {
                $io->writeError("<warning>{$msg}</warning>");
            }
            foreach ($classMap->getAmbiguousClasses() as $class => $paths) {
                if (count($paths) > 1) {
                    $io->writeError('<warning>Warning: Ambiguous class resolution, "' . $class . '"' . ' was found ' . (count($paths) + 1) . 'x: in "' . $classMap->getClassPath($class) . '" and "' . implode('", "', $paths) . '", the first will be used.</warning>');
                } else {
                    $io->writeError('<warning>Warning: Ambiguous class resolution, "' . $class . '"' . ' was found in both "' . $classMap->getClassPath($class) . '" and "' . implode('", "', $paths) . '", the first will be used.</warning>');
                }
            }
        }
        return $classMap->getMap();
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer\Command;

use Composer\Repository\PlatformRepository;
use Composer\Repository\RootPackageRepository;
use Composer\Repository\InstalledRepository;
use Composer\Installer\SuggestedPackagesReporter;
use Composer\Console\Input\InputArgument;
use _ContaoManager\Symfony\Component\Console\Input\InputInterface;
use Composer\Console\Input\InputOption;
use _ContaoManager\Symfony\Component\Console\Output\OutputInterface;
class SuggestsCommand extends \Composer\Command\BaseCommand
{
    use \Composer\Command\CompletionTrait;
    protected function configure(): void
    {
        $this->setName('suggests')->setDescription('Shows package suggestions')->setDefinition([new InputOption('by-package', null, InputOption::VALUE_NONE, 'Groups output by suggesting package (default)'), new InputOption('by-suggestion', null, InputOption::VALUE_NONE, 'Groups output by suggested package'), new InputOption('all', 'a', InputOption::VALUE_NONE, 'Show suggestions from all dependencies, including transitive ones'), new InputOption('list', null, InputOption::VALUE_NONE, 'Show only list of suggested package names'), new InputOption('no-dev', null, InputOption::VALUE_NONE, 'Exclude suggestions from require-dev packages'), new InputArgument('packages', InputArgument::IS_ARRAY | InputArgument::OPTIONAL, 'Packages that you want to list suggestions from.', null, $this->suggestInstalledPackage())])->setHelp(<<<EOT

The <info>%command.name%</info> command shows a sorted list of suggested packages.

Read more at https://getcomposer.org/doc/03-cli.md#suggests
EOT
);
    }
    protected function execute(InputInterface $input, OutputInterface $output): int
    {
        $composer = $this->requireComposer();
        $installedRepos = [new RootPackageRepository(clone $composer->getPackage())];
        $locker = $composer->getLocker();
        if ($locker->isLocked()) {
            $installedRepos[] = new PlatformRepository([], $locker->getPlatformOverrides());
            $installedRepos[] = $locker->getLockedRepository(!$input->getOption('no-dev'));
        } else {
            $installedRepos[] = new PlatformRepository([], $composer->getConfig()->get('platform'));
            $installedRepos[] = $composer->getRepositoryManager()->getLocalRepository();
        }
        $installedRepo = new InstalledRepository($installedRepos);
        $reporter = new SuggestedPackagesReporter($this->getIO());
        $filter = $input->getArgument('packages');
        $packages = $installedRepo->getPackages();
        $packages[] = $composer->getPackage();
        foreach ($packages as $package) {
            if (!empty($filter) && !in_array($package->getName(), $filter)) {
                continue;
            }
            $reporter->addSuggestionsFromPackage($package);
        }
        // Determine output mode, default is by-package
        $mode = SuggestedPackagesReporter::MODE_BY_PACKAGE;
        // if by-suggestion is given we override the default
        if ($input->getOption('by-suggestion')) {
            $mode = SuggestedPackagesReporter::MODE_BY_SUGGESTION;
        }
        // unless by-package is also present then we enable both
        if ($input->getOption('by-package')) {
            $mode |= SuggestedPackagesReporter::MODE_BY_PACKAGE;
        }
        // list is exclusive and overrides everything else
        if ($input->getOption('list')) {
            $mode = SuggestedPackagesReporter::MODE_LIST;
        }
        $reporter->output($mode, $installedRepo, empty($filter) && !$input->getOption('all') ? $composer->getPackage() : null);
        return 0;
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer\Command;

use Composer\Json\JsonFile;
use _ContaoManager\Symfony\Component\Console\Formatter\OutputFormatter;
use _ContaoManager\Symfony\Component\Console\Input\InputInterface;
use Composer\Console\Input\InputArgument;
use Composer\Console\Input\InputOption;
use _ContaoManager\Symfony\Component\Console\Output\OutputInterface;
use Composer\Repository\CompositeRepository;
use Composer\Repository\PlatformRepository;
use Composer\Repository\RepositoryInterface;
use Composer\Plugin\CommandEvent;
use Composer\Plugin\PluginEvents;
/**
 * @author Robert Schönthal <seroscho@googlemail.com>
 */
class SearchCommand extends \Composer\Command\BaseCommand
{
    protected function configure(): void
    {
        $this->setName('search')->setDescription('Searches for packages')->setDefinition([new InputOption('only-name', 'N', InputOption::VALUE_NONE, 'Search only in package names'), new InputOption('only-vendor', 'O', InputOption::VALUE_NONE, 'Search only for vendor / organization names, returns only "vendor" as result'), new InputOption('type', 't', InputOption::VALUE_REQUIRED, 'Search for a specific package type'), new InputOption('format', 'f', InputOption::VALUE_REQUIRED, 'Format of the output: text or json', 'text', ['json', 'text']), new InputArgument('tokens', InputArgument::IS_ARRAY | InputArgument::REQUIRED, 'tokens to search for')])->setHelp(<<<EOT
The search command searches for packages by its name
<info>php composer.phar search symfony composer</info>

Read more at https://getcomposer.org/doc/03-cli.md#search
EOT
);
    }
    protected function execute(InputInterface $input, OutputInterface $output): int
    {
        // init repos
        $platformRepo = new PlatformRepository();
        $io = $this->getIO();
        $format = $input->getOption('format');
        if (!in_array($format, ['text', 'json'])) {
            $io->writeError(sprintf('Unsupported format "%s". See help for supported formats.', $format));
            return 1;
        }
        if (!$composer = $this->tryComposer()) {
            $composer = $this->createComposerInstance($input, $this->getIO(), []);
        }
        $localRepo = $composer->getRepositoryManager()->getLocalRepository();
        $installedRepo = new CompositeRepository([$localRepo, $platformRepo]);
        $repos = new CompositeRepository(array_merge([$installedRepo], $composer->getRepositoryManager()->getRepositories()));
        $commandEvent = new CommandEvent(PluginEvents::COMMAND, 'search', $input, $output);
        $composer->getEventDispatcher()->dispatch($commandEvent->getName(), $commandEvent);
        $mode = RepositoryInterface::SEARCH_FULLTEXT;
        if ($input->getOption('only-name') === \true) {
            if ($input->getOption('only-vendor') === \true) {
                throw new \InvalidArgumentException('--only-name and --only-vendor cannot be used together');
            }
            $mode = RepositoryInterface::SEARCH_NAME;
        } elseif ($input->getOption('only-vendor') === \true) {
            $mode = RepositoryInterface::SEARCH_VENDOR;
        }
        $type = $input->getOption('type');
        $query = implode(' ', $input->getArgument('tokens'));
        if ($mode !== RepositoryInterface::SEARCH_FULLTEXT) {
            $query = preg_quote($query);
        }
        $results = $repos->search($query, $mode, $type);
        if (\count($results) > 0 && $format === 'text') {
            $width = $this->getTerminalWidth();
            $nameLength = 0;
            foreach ($results as $result) {
                $nameLength = max(strlen($result['name']), $nameLength);
            }
            $nameLength += 1;
            foreach ($results as $result) {
                $description = $result['description'] ?? '';
                $warning = !empty($result['abandoned']) ? '<warning>! Abandoned !</warning> ' : '';
                $remaining = $width - $nameLength - strlen($warning) - 2;
                if (strlen($description) > $remaining) {
                    $description = substr($description, 0, $remaining - 3) . '...';
                }
                $link = $result['url'] ?? null;
                if ($link !== null) {
                    $io->write('<href=' . OutputFormatter::escape($link) . '>' . $result['name'] . '</>' . str_repeat(' ', $nameLength - strlen($result['name'])) . $warning . $description);
                } else {
                    $io->write(str_pad($result['name'], $nameLength, ' ') . $warning . $description);
                }
            }
        } elseif ($format === 'json') {
            $io->write(JsonFile::encode($results));
        }
        return 0;
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer\Command;

use Composer\IO\IOInterface;
use Composer\Package\AliasPackage;
use Composer\Package\BasePackage;
use Composer\Package\Version\VersionBumper;
use Composer\Pcre\Preg;
use Composer\Util\Filesystem;
use _ContaoManager\Symfony\Component\Console\Input\InputInterface;
use Composer\Console\Input\InputArgument;
use Composer\Console\Input\InputOption;
use _ContaoManager\Symfony\Component\Console\Output\OutputInterface;
use Composer\Factory;
use Composer\Json\JsonFile;
use Composer\Json\JsonManipulator;
use Composer\Repository\PlatformRepository;
use Composer\Util\Silencer;
/**
 * @author Jordi Boggiano <j.boggiano@seld.be>
 */
final class BumpCommand extends \Composer\Command\BaseCommand
{
    private const ERROR_GENERIC = 1;
    private const ERROR_LOCK_OUTDATED = 2;
    use \Composer\Command\CompletionTrait;
    protected function configure(): void
    {
        $this->setName('bump')->setDescription('Increases the lower limit of your composer.json requirements to the currently installed versions')->setDefinition([new InputArgument('packages', InputArgument::IS_ARRAY | InputArgument::OPTIONAL, 'Optional package name(s) to restrict which packages are bumped.', null, $this->suggestRootRequirement()), new InputOption('dev-only', 'D', InputOption::VALUE_NONE, 'Only bump requirements in "require-dev".'), new InputOption('no-dev-only', 'R', InputOption::VALUE_NONE, 'Only bump requirements in "require".'), new InputOption('dry-run', null, InputOption::VALUE_NONE, 'Outputs the packages to bump, but will not execute anything.')])->setHelp(<<<EOT
The <info>bump</info> command increases the lower limit of your composer.json requirements
to the currently installed versions. This helps to ensure your dependencies do not
accidentally get downgraded due to some other conflict, and can slightly improve
dependency resolution performance as it limits the amount of package versions
Composer has to look at.

Running this blindly on libraries is **NOT** recommended as it will narrow down
your allowed dependencies, which may cause dependency hell for your users.
Running it with <info>--dev-only</info> on libraries may be fine however as dev requirements
are local to the library and do not affect consumers of the package.

EOT
);
    }
    /**
     * @throws \Seld\JsonLint\ParsingException
     */
    protected function execute(InputInterface $input, OutputInterface $output): int
    {
        return $this->doBump($this->getIO(), $input->getOption('dev-only'), $input->getOption('no-dev-only'), $input->getOption('dry-run'), $input->getArgument('packages'));
    }
    /**
     * @internal
     * @param string[] $packagesFilter
     * @throws \Seld\JsonLint\ParsingException
     */
    public function doBump(IOInterface $io, bool $devOnly, bool $noDevOnly, bool $dryRun, array $packagesFilter, string $devOnlyFlagHint = '--dev-only'): int
    {
        /** @readonly */
        $composerJsonPath = Factory::getComposerFile();
        if (!Filesystem::isReadable($composerJsonPath)) {
            $io->writeError('<error>' . $composerJsonPath . ' is not readable.</error>');
            return self::ERROR_GENERIC;
        }
        $composerJson = new JsonFile($composerJsonPath);
        $contents = file_get_contents($composerJson->getPath());
        if (\false === $contents) {
            $io->writeError('<error>' . $composerJsonPath . ' is not readable.</error>');
            return self::ERROR_GENERIC;
        }
        // check for writability by writing to the file as is_writable can not be trusted on network-mounts
        // see https://github.com/composer/composer/issues/8231 and https://bugs.php.net/bug.php?id=68926
        if (!is_writable($composerJsonPath) && \false === Silencer::call('file_put_contents', $composerJsonPath, $contents)) {
            $io->writeError('<error>' . $composerJsonPath . ' is not writable.</error>');
            return self::ERROR_GENERIC;
        }
        unset($contents);
        $composer = $this->requireComposer();
        $hasLockfileDisabled = !$composer->getConfig()->has('lock') || $composer->getConfig()->get('lock');
        if (!$hasLockfileDisabled) {
            $repo = $composer->getLocker()->getLockedRepository(\true);
        } elseif ($composer->getLocker()->isLocked()) {
            if (!$composer->getLocker()->isFresh()) {
                $io->writeError('<error>The lock file is not up to date with the latest changes in composer.json. Run the appropriate `update` to fix that before you use the `bump` command.</error>');
                return self::ERROR_LOCK_OUTDATED;
            }
            $repo = $composer->getLocker()->getLockedRepository(\true);
        } else {
            $repo = $composer->getRepositoryManager()->getLocalRepository();
        }
        if ($composer->getPackage()->getType() !== 'project' && !$devOnly) {
            $io->writeError('<warning>Warning: Bumping dependency constraints is not recommended for libraries as it will narrow down your dependencies and may cause problems for your users.</warning>');
            $contents = $composerJson->read();
            if (!isset($contents['type'])) {
                $io->writeError('<warning>If your package is not a library, you can explicitly specify the "type" by using "composer config type project".</warning>');
                $io->writeError('<warning>Alternatively you can use ' . $devOnlyFlagHint . ' to only bump dependencies within "require-dev".</warning>');
            }
            unset($contents);
        }
        $bumper = new VersionBumper();
        $tasks = [];
        if (!$devOnly) {
            $tasks['require'] = $composer->getPackage()->getRequires();
        }
        if (!$noDevOnly) {
            $tasks['require-dev'] = $composer->getPackage()->getDevRequires();
        }
        if (count($packagesFilter) > 0) {
            // support proxied args from the update command that contain constraints together with the package names
            $packagesFilter = array_map(static function ($constraint) {
                return Preg::replace('{[:= ].+}', '', $constraint);
            }, $packagesFilter);
            $pattern = BasePackage::packageNamesToRegexp(array_unique(array_map('strtolower', $packagesFilter)));
            foreach ($tasks as $key => $reqs) {
                foreach ($reqs as $pkgName => $link) {
                    if (!Preg::isMatch($pattern, $pkgName)) {
                        unset($tasks[$key][$pkgName]);
                    }
                }
            }
        }
        $updates = [];
        foreach ($tasks as $key => $reqs) {
            foreach ($reqs as $pkgName => $link) {
                if (PlatformRepository::isPlatformPackage($pkgName)) {
                    continue;
                }
                $currentConstraint = $link->getPrettyConstraint();
                $package = $repo->findPackage($pkgName, '*');
                // name must be provided or replaced
                if (null === $package) {
                    continue;
                }
                while ($package instanceof AliasPackage) {
                    $package = $package->getAliasOf();
                }
                $bumped = $bumper->bumpRequirement($link->getConstraint(), $package);
                if ($bumped === $currentConstraint) {
                    continue;
                }
                $updates[$key][$pkgName] = $bumped;
            }
        }
        if (!$dryRun && !$this->updateFileCleanly($composerJson, $updates)) {
            $composerDefinition = $composerJson->read();
            foreach ($updates as $key => $packages) {
                foreach ($packages as $package => $version) {
                    $composerDefinition[$key][$package] = $version;
                }
            }
            $composerJson->write($composerDefinition);
        }
        $changeCount = array_sum(array_map('count', $updates));
        if ($changeCount > 0) {
            if ($dryRun) {
                $io->write('<info>' . $composerJsonPath . ' would be updated with:</info>');
                foreach ($updates as $requireType => $packages) {
                    foreach ($packages as $package => $version) {
                        $io->write(sprintf('<info> - %s.%s: %s</info>', $requireType, $package, $version));
                    }
                }
            } else {
                $io->write('<info>' . $composerJsonPath . ' has been updated (' . $changeCount . ' changes).</info>');
            }
        } else {
            $io->write('<info>No requirements to update in ' . $composerJsonPath . '.</info>');
        }
        if (!$dryRun && $composer->getLocker()->isLocked() && $composer->getConfig()->get('lock') && $changeCount > 0) {
            $composer->getLocker()->updateHash($composerJson);
        }
        if ($dryRun && $changeCount > 0) {
            return self::ERROR_GENERIC;
        }
        return 0;
    }
    /**
     * @param array<'require'|'require-dev', array<string, string>> $updates
     */
    private function updateFileCleanly(JsonFile $json, array $updates): bool
    {
        $contents = file_get_contents($json->getPath());
        if (\false === $contents) {
            throw new \RuntimeException('Unable to read ' . $json->getPath() . ' contents.');
        }
        $manipulator = new JsonManipulator($contents);
        foreach ($updates as $key => $packages) {
            foreach ($packages as $package => $version) {
                if (!$manipulator->addLink($key, $package, $version)) {
                    return \false;
                }
            }
        }
        if (\false === file_put_contents($json->getPath(), $manipulator->getContents())) {
            throw new \RuntimeException('Unable to write new ' . $json->getPath() . ' contents.');
        }
        return \true;
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer\Command;

use Composer\Factory;
use Composer\IO\IOInterface;
use Composer\Config;
use Composer\Composer;
use Composer\Package\BasePackage;
use Composer\Package\CompletePackageInterface;
use Composer\Package\Version\VersionParser;
use Composer\Package\Version\VersionSelector;
use Composer\Pcre\Preg;
use Composer\Repository\CompositeRepository;
use Composer\Repository\RepositoryFactory;
use Composer\Repository\RepositorySet;
use Composer\Script\ScriptEvents;
use Composer\Plugin\CommandEvent;
use Composer\Plugin\PluginEvents;
use Composer\Util\Filesystem;
use Composer\Util\Loop;
use Composer\Util\Platform;
use Composer\Util\ProcessExecutor;
use Composer\Console\Input\InputArgument;
use _ContaoManager\Symfony\Component\Console\Input\InputInterface;
use Composer\Console\Input\InputOption;
use _ContaoManager\Symfony\Component\Console\Output\OutputInterface;
/**
 * Creates an archive of a package for distribution.
 *
 * @author Nils Adermann <naderman@naderman.de>
 */
class ArchiveCommand extends \Composer\Command\BaseCommand
{
    use \Composer\Command\CompletionTrait;
    private const FORMATS = ['tar', 'tar.gz', 'tar.bz2', 'zip'];
    protected function configure(): void
    {
        $this->setName('archive')->setDescription('Creates an archive of this composer package')->setDefinition([new InputArgument('package', InputArgument::OPTIONAL, 'The package to archive instead of the current project', null, $this->suggestAvailablePackage()), new InputArgument('version', InputArgument::OPTIONAL, 'A version constraint to find the package to archive'), new InputOption('format', 'f', InputOption::VALUE_REQUIRED, 'Format of the resulting archive: tar, tar.gz, tar.bz2 or zip (default tar)', null, self::FORMATS), new InputOption('dir', null, InputOption::VALUE_REQUIRED, 'Write the archive to this directory'), new InputOption('file', null, InputOption::VALUE_REQUIRED, 'Write the archive with the given file name.' . ' Note that the format will be appended.'), new InputOption('ignore-filters', null, InputOption::VALUE_NONE, 'Ignore filters when saving package')])->setHelp(<<<EOT
The <info>archive</info> command creates an archive of the specified format
containing the files and directories of the Composer project or the specified
package in the specified version and writes it to the specified directory.

<info>php composer.phar archive [--format=zip] [--dir=/foo] [--file=filename] [package [version]]</info>

Read more at https://getcomposer.org/doc/03-cli.md#archive
EOT
);
    }
    protected function execute(InputInterface $input, OutputInterface $output): int
    {
        $composer = $this->tryComposer();
        $config = null;
        if ($composer) {
            $config = $composer->getConfig();
            $commandEvent = new CommandEvent(PluginEvents::COMMAND, 'archive', $input, $output);
            $eventDispatcher = $composer->getEventDispatcher();
            $eventDispatcher->dispatch($commandEvent->getName(), $commandEvent);
            $eventDispatcher->dispatchScript(ScriptEvents::PRE_ARCHIVE_CMD);
        }
        if (!$config) {
            $config = Factory::createConfig();
        }
        $format = $input->getOption('format') ?? $config->get('archive-format');
        $dir = $input->getOption('dir') ?? $config->get('archive-dir');
        $returnCode = $this->archive($this->getIO(), $config, $input->getArgument('package'), $input->getArgument('version'), $format, $dir, $input->getOption('file'), $input->getOption('ignore-filters'), $composer);
        if (0 === $returnCode && $composer) {
            $composer->getEventDispatcher()->dispatchScript(ScriptEvents::POST_ARCHIVE_CMD);
        }
        return $returnCode;
    }
    /**
     * @throws \Exception
     */
    protected function archive(IOInterface $io, Config $config, ?string $packageName, ?string $version, string $format, string $dest, ?string $fileName, bool $ignoreFilters, ?Composer $composer): int
    {
        if ($composer) {
            $archiveManager = $composer->getArchiveManager();
        } else {
            $factory = new Factory();
            $process = new ProcessExecutor();
            $httpDownloader = Factory::createHttpDownloader($io, $config);
            $downloadManager = $factory->createDownloadManager($io, $config, $httpDownloader, $process);
            $archiveManager = $factory->createArchiveManager($config, $downloadManager, new Loop($httpDownloader, $process));
        }
        if ($packageName) {
            $package = $this->selectPackage($io, $packageName, $version);
            if (!$package) {
                return 1;
            }
        } else {
            $package = $this->requireComposer()->getPackage();
        }
        $io->writeError('<info>Creating the archive into "' . $dest . '".</info>');
        $packagePath = $archiveManager->archive($package, $format, $dest, $fileName, $ignoreFilters);
        $fs = new Filesystem();
        $shortPath = $fs->findShortestPath(Platform::getCwd(), $packagePath, \true);
        $io->writeError('Created: ', \false);
        $io->write(strlen($shortPath) < strlen($packagePath) ? $shortPath : $packagePath);
        return 0;
    }
    /**
     * @return (BasePackage&CompletePackageInterface)|false
     */
    protected function selectPackage(IOInterface $io, string $packageName, ?string $version = null)
    {
        $io->writeError('<info>Searching for the specified package.</info>');
        if ($composer = $this->tryComposer()) {
            $localRepo = $composer->getRepositoryManager()->getLocalRepository();
            $repo = new CompositeRepository(array_merge([$localRepo], $composer->getRepositoryManager()->getRepositories()));
            $minStability = $composer->getPackage()->getMinimumStability();
        } else {
            $defaultRepos = RepositoryFactory::defaultReposWithDefaultManager($io);
            $io->writeError('No composer.json found in the current directory, searching packages from ' . implode(', ', array_keys($defaultRepos)));
            $repo = new CompositeRepository($defaultRepos);
            $minStability = 'stable';
        }
        if ($version !== null && Preg::isMatchStrictGroups('{@(stable|RC|beta|alpha|dev)$}i', $version, $match)) {
            $minStability = VersionParser::normalizeStability($match[1]);
            $version = (string) substr($version, 0, -strlen($match[0]));
        }
        $repoSet = new RepositorySet($minStability);
        $repoSet->addRepository($repo);
        $parser = new VersionParser();
        $constraint = $version !== null ? $parser->parseConstraints($version) : null;
        $packages = $repoSet->findPackages(strtolower($packageName), $constraint);
        if (count($packages) > 1) {
            $versionSelector = new VersionSelector($repoSet);
            $package = $versionSelector->findBestCandidate(strtolower($packageName), $version, $minStability);
            if ($package === \false) {
                $package = reset($packages);
            }
            $io->writeError('<info>Found multiple matches, selected ' . $package->getPrettyString() . '.</info>');
            $io->writeError('Alternatives were ' . implode(', ', array_map(static function ($p): string {
                return $p->getPrettyString();
            }, $packages)) . '.');
            $io->writeError('<comment>Please use a more specific constraint to pick a different package.</comment>');
        } elseif (count($packages) === 1) {
            $package = reset($packages);
            $io->writeError('<info>Found an exact match ' . $package->getPrettyString() . '.</info>');
        } else {
            $io->writeError('<error>Could not find a package matching ' . $packageName . '.</error>');
            return \false;
        }
        if (!$package instanceof CompletePackageInterface) {
            throw new \LogicException('Expected a CompletePackageInterface instance but found ' . get_class($package));
        }
        if (!$package instanceof BasePackage) {
            throw new \LogicException('Expected a BasePackage instance but found ' . get_class($package));
        }
        return $package;
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer\Command;

use Composer\Advisory\AuditConfig;
use Composer\Composer;
use Composer\Repository\RepositorySet;
use Composer\Repository\RepositoryUtils;
use _ContaoManager\Symfony\Component\Console\Input\InputInterface;
use _ContaoManager\Symfony\Component\Console\Output\OutputInterface;
use Composer\Package\PackageInterface;
use Composer\Repository\InstalledRepository;
use Composer\Advisory\Auditor;
use Composer\Console\Input\InputOption;
class AuditCommand extends \Composer\Command\BaseCommand
{
    protected function configure(): void
    {
        $this->setName('audit')->setDescription('Checks for security vulnerability advisories for installed packages')->setDefinition([new InputOption('no-dev', null, InputOption::VALUE_NONE, 'Disables auditing of require-dev packages.'), new InputOption('format', 'f', InputOption::VALUE_REQUIRED, 'Output format. Must be "table", "plain", "json", or "summary".', Auditor::FORMAT_TABLE, Auditor::FORMATS), new InputOption('locked', null, InputOption::VALUE_NONE, 'Audit based on the lock file instead of the installed packages.'), new InputOption('abandoned', null, InputOption::VALUE_REQUIRED, 'Behavior on abandoned packages. Must be "ignore", "report", or "fail".', null, Auditor::ABANDONEDS), new InputOption('ignore-severity', null, InputOption::VALUE_IS_ARRAY | InputOption::VALUE_REQUIRED, 'Ignore advisories of a certain severity level.', [], ['low', 'medium', 'high', 'critical']), new InputOption('ignore-unreachable', null, InputOption::VALUE_NONE, 'Ignore repositories that are unreachable or return a non-200 status code.')])->setHelp(<<<EOT
The <info>audit</info> command checks for security vulnerability advisories for installed packages.

If you do not want to include dev dependencies in the audit you can omit them with --no-dev

If you want to ignore repositories that are unreachable or return a non-200 status code, use --ignore-unreachable

Read more at https://getcomposer.org/doc/03-cli.md#audit
EOT
);
    }
    protected function execute(InputInterface $input, OutputInterface $output): int
    {
        $composer = $this->requireComposer();
        $packages = $this->getPackages($composer, $input);
        if (count($packages) === 0) {
            $this->getIO()->writeError('No packages - skipping audit.');
            return 0;
        }
        $auditor = new Auditor();
        $repoSet = new RepositorySet();
        foreach ($composer->getRepositoryManager()->getRepositories() as $repo) {
            $repoSet->addRepository($repo);
        }
        $auditConfig = AuditConfig::fromConfig($composer->getConfig());
        $abandoned = $input->getOption('abandoned');
        if ($abandoned !== null && !in_array($abandoned, Auditor::ABANDONEDS, \true)) {
            throw new \InvalidArgumentException('--abandoned must be one of ' . implode(', ', Auditor::ABANDONEDS) . '.');
        }
        $abandoned = $abandoned ?? $auditConfig->auditAbandoned;
        $ignoreSeverities = array_merge(array_fill_keys($input->getOption('ignore-severity'), null), $auditConfig->ignoreSeverityForAudit);
        $ignoreUnreachable = $input->getOption('ignore-unreachable') || $auditConfig->ignoreUnreachable;
        return min(255, $auditor->audit($this->getIO(), $repoSet, $packages, $this->getAuditFormat($input, 'format'), \false, $auditConfig->ignoreListForAudit, $abandoned, $ignoreSeverities, $ignoreUnreachable, $auditConfig->ignoreAbandonedForAudit));
    }
    /**
     * @return PackageInterface[]
     */
    private function getPackages(Composer $composer, InputInterface $input): array
    {
        if ($input->getOption('locked')) {
            if (!$composer->getLocker()->isLocked()) {
                throw new \UnexpectedValueException('Valid composer.json and composer.lock files are required to run this command with --locked');
            }
            $locker = $composer->getLocker();
            return $locker->getLockedRepository(!$input->getOption('no-dev'))->getPackages();
        }
        $rootPkg = $composer->getPackage();
        $installedRepo = new InstalledRepository([$composer->getRepositoryManager()->getLocalRepository()]);
        if ($input->getOption('no-dev')) {
            return RepositoryUtils::filterRequiredPackages($installedRepo->getPackages(), $rootPkg);
        }
        return $installedRepo->getPackages();
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer\Command;

use Composer\Factory;
use Composer\IO\IOInterface;
use Composer\Package\Loader\ValidatingArrayLoader;
use Composer\Plugin\CommandEvent;
use Composer\Plugin\PluginEvents;
use Composer\Util\ConfigValidator;
use Composer\Util\Filesystem;
use _ContaoManager\Symfony\Component\Console\Input\InputArgument;
use _ContaoManager\Symfony\Component\Console\Input\InputInterface;
use _ContaoManager\Symfony\Component\Console\Input\InputOption;
use _ContaoManager\Symfony\Component\Console\Output\OutputInterface;
/**
 * ValidateCommand
 *
 * @author Robert Schönthal <seroscho@googlemail.com>
 * @author Jordi Boggiano <j.boggiano@seld.be>
 */
class ValidateCommand extends \Composer\Command\BaseCommand
{
    /**
     * configure
     */
    protected function configure(): void
    {
        $this->setName('validate')->setDescription('Validates a composer.json and composer.lock')->setDefinition([new InputOption('no-check-all', null, InputOption::VALUE_NONE, 'Do not validate requires for overly strict/loose constraints'), new InputOption('check-lock', null, InputOption::VALUE_NONE, 'Check if lock file is up to date (even when config.lock is false)'), new InputOption('no-check-lock', null, InputOption::VALUE_NONE, 'Do not check if lock file is up to date'), new InputOption('no-check-publish', null, InputOption::VALUE_NONE, 'Do not check for publish errors'), new InputOption('no-check-version', null, InputOption::VALUE_NONE, 'Do not report a warning if the version field is present'), new InputOption('with-dependencies', 'A', InputOption::VALUE_NONE, 'Also validate the composer.json of all installed dependencies'), new InputOption('strict', null, InputOption::VALUE_NONE, 'Return a non-zero exit code for warnings as well as errors'), new InputArgument('file', InputArgument::OPTIONAL, 'path to composer.json file')])->setHelp(<<<EOT
The validate command validates a given composer.json and composer.lock

Exit codes in case of errors are:
1 validation warning(s), only when --strict is given
2 validation error(s)
3 file unreadable or missing

Read more at https://getcomposer.org/doc/03-cli.md#validate
EOT
);
    }
    protected function execute(InputInterface $input, OutputInterface $output): int
    {
        $file = $input->getArgument('file') ?? Factory::getComposerFile();
        $io = $this->getIO();
        if (!file_exists($file)) {
            $io->writeError('<error>' . $file . ' not found.</error>');
            return 3;
        }
        if (!Filesystem::isReadable($file)) {
            $io->writeError('<error>' . $file . ' is not readable.</error>');
            return 3;
        }
        $validator = new ConfigValidator($io);
        $checkAll = $input->getOption('no-check-all') ? 0 : ValidatingArrayLoader::CHECK_ALL;
        $checkPublish = !$input->getOption('no-check-publish');
        $checkLock = !$input->getOption('no-check-lock');
        $checkVersion = $input->getOption('no-check-version') ? 0 : ConfigValidator::CHECK_VERSION;
        $isStrict = $input->getOption('strict');
        [$errors, $publishErrors, $warnings] = $validator->validate($file, $checkAll, $checkVersion);
        $lockErrors = [];
        $composer = $this->createComposerInstance($input, $io, $file);
        // config.lock = false ~= implicit --no-check-lock; --check-lock overrides
        $checkLock = $checkLock && $composer->getConfig()->get('lock') || $input->getOption('check-lock');
        $locker = $composer->getLocker();
        if ($locker->isLocked() && !$locker->isFresh()) {
            $lockErrors[] = '- The lock file is not up to date with the latest changes in composer.json, it is recommended that you run `composer update` or `composer update <package name>`.';
        }
        if ($locker->isLocked()) {
            $lockErrors = array_merge($lockErrors, $locker->getMissingRequirementInfo($composer->getPackage(), \true));
        }
        $this->outputResult($io, $file, $errors, $warnings, $checkPublish, $publishErrors, $checkLock, $lockErrors, \true);
        // $errors include publish and lock errors when exists
        $exitCode = count($errors) > 0 ? 2 : ($isStrict && count($warnings) > 0 ? 1 : 0);
        if ($input->getOption('with-dependencies')) {
            $localRepo = $composer->getRepositoryManager()->getLocalRepository();
            foreach ($localRepo->getPackages() as $package) {
                $path = $composer->getInstallationManager()->getInstallPath($package);
                if (null === $path) {
                    continue;
                }
                $file = $path . '/composer.json';
                if (is_dir($path) && file_exists($file)) {
                    [$errors, $publishErrors, $warnings] = $validator->validate($file, $checkAll, $checkVersion);
                    $this->outputResult($io, $package->getPrettyName(), $errors, $warnings, $checkPublish, $publishErrors);
                    // $errors include publish errors when exists
                    $depCode = count($errors) > 0 ? 2 : ($isStrict && count($warnings) > 0 ? 1 : 0);
                    $exitCode = max($depCode, $exitCode);
                }
            }
        }
        $commandEvent = new CommandEvent(PluginEvents::COMMAND, 'validate', $input, $output);
        $eventCode = $composer->getEventDispatcher()->dispatch($commandEvent->getName(), $commandEvent);
        return max($eventCode, $exitCode);
    }
    /**
     * @param string[] $errors
     * @param string[] $warnings
     * @param string[] $publishErrors
     * @param string[] $lockErrors
     */
    private function outputResult(IOInterface $io, string $name, array &$errors, array &$warnings, bool $checkPublish = \false, array $publishErrors = [], bool $checkLock = \false, array $lockErrors = [], bool $printSchemaUrl = \false): void
    {
        $doPrintSchemaUrl = \false;
        if (\count($errors) > 0) {
            $io->writeError('<error>' . $name . ' is invalid, the following errors/warnings were found:</error>');
        } elseif (\count($publishErrors) > 0 && $checkPublish) {
            $io->writeError('<info>' . $name . ' is valid for simple usage with Composer but has</info>');
            $io->writeError('<info>strict errors that make it unable to be published as a package</info>');
            $doPrintSchemaUrl = $printSchemaUrl;
        } elseif (\count($warnings) > 0) {
            $io->writeError('<info>' . $name . ' is valid, but with a few warnings</info>');
            $doPrintSchemaUrl = $printSchemaUrl;
        } elseif (\count($lockErrors) > 0) {
            $io->write('<info>' . $name . ' is valid but your composer.lock has some ' . ($checkLock ? 'errors' : 'warnings') . '</info>');
        } else {
            $io->write('<info>' . $name . ' is valid</info>');
        }
        if ($doPrintSchemaUrl) {
            $io->writeError('<warning>See https://getcomposer.org/doc/04-schema.md for details on the schema</warning>');
        }
        if (\count($errors) > 0) {
            $errors = array_map(static function ($err): string {
                return '- ' . $err;
            }, $errors);
            array_unshift($errors, '# General errors');
        }
        if (\count($warnings) > 0) {
            $warnings = array_map(static function ($err): string {
                return '- ' . $err;
            }, $warnings);
            array_unshift($warnings, '# General warnings');
        }
        // Avoid setting the exit code to 1 in case --strict and --no-check-publish/--no-check-lock are combined
        $extraWarnings = [];
        // If checking publish errors, display them as errors, otherwise just show them as warnings
        if (\count($publishErrors) > 0 && $checkPublish) {
            $publishErrors = array_map(static function ($err): string {
                return '- ' . $err;
            }, $publishErrors);
            array_unshift($publishErrors, '# Publish errors');
            $errors = array_merge($errors, $publishErrors);
        }
        // If checking lock errors, display them as errors, otherwise just show them as warnings
        if (\count($lockErrors) > 0) {
            if ($checkLock) {
                array_unshift($lockErrors, '# Lock file errors');
                $errors = array_merge($errors, $lockErrors);
            } else {
                array_unshift($lockErrors, '# Lock file warnings');
                $extraWarnings = array_merge($extraWarnings, $lockErrors);
            }
        }
        $messages = ['error' => $errors, 'warning' => array_merge($warnings, $extraWarnings)];
        foreach ($messages as $style => $msgs) {
            foreach ($msgs as $msg) {
                if (strpos($msg, '#') === 0) {
                    $io->writeError('<' . $style . '>' . $msg . '</' . $style . '>');
                } else {
                    $io->writeError($msg);
                }
            }
        }
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer\Command;

use Composer\Json\JsonFile;
use Composer\Package\AliasPackage;
use Composer\Package\BasePackage;
use Composer\Package\CompletePackageInterface;
use Composer\Pcre\Preg;
use Composer\Repository\CompositeRepository;
use Composer\Semver\Constraint\MatchAllConstraint;
use _ContaoManager\Symfony\Component\Console\Formatter\OutputFormatter;
use _ContaoManager\Symfony\Component\Console\Input\InputInterface;
use Composer\Console\Input\InputOption;
use _ContaoManager\Symfony\Component\Console\Output\OutputInterface;
/**
 * @author Nicolas Grekas <p@tchwork.com>
 * @author Jordi Boggiano <j.boggiano@seld.be>
 */
class FundCommand extends \Composer\Command\BaseCommand
{
    protected function configure(): void
    {
        $this->setName('fund')->setDescription('Discover how to help fund the maintenance of your dependencies')->setDefinition([new InputOption('format', 'f', InputOption::VALUE_REQUIRED, 'Format of the output: text or json', 'text', ['text', 'json'])]);
    }
    protected function execute(InputInterface $input, OutputInterface $output): int
    {
        $composer = $this->requireComposer();
        $repo = $composer->getRepositoryManager()->getLocalRepository();
        $remoteRepos = new CompositeRepository($composer->getRepositoryManager()->getRepositories());
        $fundings = [];
        $packagesToLoad = [];
        foreach ($repo->getPackages() as $package) {
            if ($package instanceof AliasPackage) {
                continue;
            }
            $packagesToLoad[$package->getName()] = new MatchAllConstraint();
        }
        // load all packages dev versions in parallel
        $result = $remoteRepos->loadPackages($packagesToLoad, ['dev' => BasePackage::STABILITY_DEV], []);
        // collect funding data from default branches
        foreach ($result['packages'] as $package) {
            if (!$package instanceof AliasPackage && $package instanceof CompletePackageInterface && $package->isDefaultBranch() && $package->getFunding() && isset($packagesToLoad[$package->getName()])) {
                $fundings = $this->insertFundingData($fundings, $package);
                unset($packagesToLoad[$package->getName()]);
            }
        }
        // collect funding from installed packages if none was found in the default branch above
        foreach ($repo->getPackages() as $package) {
            if ($package instanceof AliasPackage || !isset($packagesToLoad[$package->getName()])) {
                continue;
            }
            if ($package instanceof CompletePackageInterface && $package->getFunding()) {
                $fundings = $this->insertFundingData($fundings, $package);
            }
        }
        ksort($fundings);
        $io = $this->getIO();
        $format = $input->getOption('format');
        if (!in_array($format, ['text', 'json'])) {
            $io->writeError(sprintf('Unsupported format "%s". See help for supported formats.', $format));
            return 1;
        }
        if ($fundings && $format === 'text') {
            $prev = null;
            $io->write('The following packages were found in your dependencies which publish funding information:');
            foreach ($fundings as $vendor => $links) {
                $io->write('');
                $io->write(sprintf("<comment>%s</comment>", $vendor));
                foreach ($links as $url => $packages) {
                    $line = sprintf('  <info>%s</info>', implode(', ', $packages));
                    if ($prev !== $line) {
                        $io->write($line);
                        $prev = $line;
                    }
                    $io->write(sprintf('    <href=%s>%s</>', OutputFormatter::escape($url), $url));
                }
            }
            $io->write("");
            $io->write("Please consider following these links and sponsoring the work of package authors!");
            $io->write("Thank you!");
        } elseif ($format === 'json') {
            $io->write(JsonFile::encode($fundings));
        } else {
            $io->write("No funding links were found in your package dependencies. This doesn't mean they don't need your support!");
        }
        return 0;
    }
    /**
     * @param mixed[] $fundings
     * @return mixed[]
     */
    private function insertFundingData(array $fundings, CompletePackageInterface $package): array
    {
        foreach ($package->getFunding() as $fundingOption) {
            [$vendor, $packageName] = explode('/', $package->getPrettyName());
            // ignore malformed funding entries
            if (empty($fundingOption['url'])) {
                continue;
            }
            $url = $fundingOption['url'];
            if (!empty($fundingOption['type']) && $fundingOption['type'] === 'github' && Preg::isMatch('{^https://github.com/([^/]+)$}', $url, $match)) {
                $url = 'https://github.com/sponsors/' . $match[1];
            }
            $fundings[$vendor][$url][] = $packageName;
        }
        return $fundings;
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer\Command;

use Composer\Factory;
use Composer\Filter\PlatformRequirementFilter\IgnoreAllPlatformRequirementFilter;
use Composer\Filter\PlatformRequirementFilter\PlatformRequirementFilterFactory;
use Composer\IO\IOInterface;
use Composer\Package\BasePackage;
use Composer\Package\CompletePackageInterface;
use Composer\Package\PackageInterface;
use Composer\Package\Version\VersionParser;
use Composer\Package\Version\VersionSelector;
use Composer\Pcre\Preg;
use Composer\Repository\CompositeRepository;
use Composer\Repository\PlatformRepository;
use Composer\Repository\RepositoryFactory;
use Composer\Repository\RepositorySet;
use Composer\Semver\Constraint\Constraint;
use Composer\Util\Filesystem;
use _ContaoManager\Symfony\Component\Console\Input\InputInterface;
use _ContaoManager\Symfony\Component\Console\Output\OutputInterface;
/**
 * @internal
 */
trait PackageDiscoveryTrait
{
    /** @var ?CompositeRepository */
    private $repos;
    /** @var RepositorySet[] */
    private $repositorySets;
    protected function getRepos(): CompositeRepository
    {
        if (null === $this->repos) {
            $this->repos = new CompositeRepository(array_merge([new PlatformRepository()], RepositoryFactory::defaultReposWithDefaultManager($this->getIO())));
        }
        return $this->repos;
    }
    /**
     * @param key-of<BasePackage::STABILITIES>|null $minimumStability
     */
    private function getRepositorySet(InputInterface $input, ?string $minimumStability = null): RepositorySet
    {
        $key = $minimumStability ?? 'default';
        if (!isset($this->repositorySets[$key])) {
            $this->repositorySets[$key] = $repositorySet = new RepositorySet($minimumStability ?? $this->getMinimumStability($input));
            $repositorySet->addRepository($this->getRepos());
        }
        return $this->repositorySets[$key];
    }
    /**
     * @return key-of<BasePackage::STABILITIES>
     */
    private function getMinimumStability(InputInterface $input): string
    {
        if ($input->hasOption('stability')) {
            // @phpstan-ignore-line as InitCommand does have this option but not all classes using this trait do
            return VersionParser::normalizeStability($input->getOption('stability') ?? 'stable');
        }
        // @phpstan-ignore-next-line as RequireCommand does not have the option above so this code is reachable there
        $file = Factory::getComposerFile();
        if (is_file($file) && Filesystem::isReadable($file) && is_array($composer = json_decode((string) file_get_contents($file), \true))) {
            if (isset($composer['minimum-stability'])) {
                return VersionParser::normalizeStability($composer['minimum-stability']);
            }
        }
        return 'stable';
    }
    /**
     * @param array<string> $requires
     *
     * @return array<string>
     * @throws \Exception
     */
    final protected function determineRequirements(InputInterface $input, OutputInterface $output, array $requires = [], ?PlatformRepository $platformRepo = null, string $preferredStability = 'stable', bool $useBestVersionConstraint = \true, bool $fixed = \false): array
    {
        if (count($requires) > 0) {
            $requires = $this->normalizeRequirements($requires);
            $result = [];
            $io = $this->getIO();
            foreach ($requires as $requirement) {
                if (isset($requirement['version']) && Preg::isMatch('{^\d+(\.\d+)?$}', $requirement['version'])) {
                    $io->writeError('<warning>The "' . $requirement['version'] . '" constraint for "' . $requirement['name'] . '" appears too strict and will likely not match what you want. See https://getcomposer.org/constraints</warning>');
                }
                if (!isset($requirement['version'])) {
                    // determine the best version automatically
                    [$name, $version] = $this->findBestVersionAndNameForPackage($this->getIO(), $input, $requirement['name'], $platformRepo, $preferredStability, $fixed);
                    // replace package name from packagist.org
                    $requirement['name'] = $name;
                    if ($useBestVersionConstraint) {
                        $requirement['version'] = $version;
                        $io->writeError(sprintf('Using version <info>%s</info> for <info>%s</info>', $requirement['version'], $requirement['name']));
                    } else {
                        $requirement['version'] = 'guess';
                    }
                }
                $result[] = $requirement['name'] . ' ' . $requirement['version'];
            }
            return $result;
        }
        $versionParser = new VersionParser();
        // Collect existing packages
        $composer = $this->tryComposer();
        $installedRepo = null;
        if (null !== $composer) {
            $installedRepo = $composer->getRepositoryManager()->getLocalRepository();
        }
        $existingPackages = [];
        if (null !== $installedRepo) {
            foreach ($installedRepo->getPackages() as $package) {
                $existingPackages[] = $package->getName();
            }
        }
        unset($composer, $installedRepo);
        $io = $this->getIO();
        while (null !== $package = $io->ask('Search for a package: ')) {
            $matches = $this->getRepos()->search($package);
            if (count($matches) > 0) {
                // Remove existing packages from search results.
                foreach ($matches as $position => $foundPackage) {
                    if (in_array($foundPackage['name'], $existingPackages, \true)) {
                        unset($matches[$position]);
                    }
                }
                $matches = array_values($matches);
                $exactMatch = \false;
                foreach ($matches as $match) {
                    if ($match['name'] === $package) {
                        $exactMatch = \true;
                        break;
                    }
                }
                // no match, prompt which to pick
                if (!$exactMatch) {
                    $providers = $this->getRepos()->getProviders($package);
                    if (count($providers) > 0) {
                        array_unshift($matches, ['name' => $package, 'description' => '']);
                    }
                    $choices = [];
                    foreach ($matches as $position => $foundPackage) {
                        $abandoned = '';
                        if (isset($foundPackage['abandoned'])) {
                            if (is_string($foundPackage['abandoned'])) {
                                $replacement = sprintf('Use %s instead', $foundPackage['abandoned']);
                            } else {
                                $replacement = 'No replacement was suggested';
                            }
                            $abandoned = sprintf('<warning>Abandoned. %s.</warning>', $replacement);
                        }
                        $choices[] = sprintf(' <info>%5s</info> %s %s', "[{$position}]", $foundPackage['name'], $abandoned);
                    }
                    $io->writeError(['', sprintf('Found <info>%s</info> packages matching <info>%s</info>', count($matches), $package), '']);
                    $io->writeError($choices);
                    $io->writeError('');
                    $validator = static function (string $selection) use ($matches, $versionParser) {
                        if ('' === $selection) {
                            return \false;
                        }
                        if (is_numeric($selection) && isset($matches[(int) $selection])) {
                            $package = $matches[(int) $selection];
                            return $package['name'];
                        }
                        if (Preg::isMatch('{^\s*(?P<name>[\S/]+)(?:\s+(?P<version>\S+))?\s*$}', $selection, $packageMatches)) {
                            if (isset($packageMatches['version'])) {
                                // parsing `acme/example ~2.3`
                                // validate version constraint
                                $versionParser->parseConstraints($packageMatches['version']);
                                return $packageMatches['name'] . ' ' . $packageMatches['version'];
                            }
                            // parsing `acme/example`
                            return $packageMatches['name'];
                        }
                        throw new \Exception('Not a valid selection');
                    };
                    $package = $io->askAndValidate('Enter package # to add, or the complete package name if it is not listed: ', $validator, 3, '');
                }
                // no constraint yet, determine the best version automatically
                if (\false !== $package && \false === strpos($package, ' ')) {
                    $validator = static function (string $input) {
                        $input = trim($input);
                        return strlen($input) > 0 ? $input : \false;
                    };
                    $constraint = $io->askAndValidate('Enter the version constraint to require (or leave blank to use the latest version): ', $validator, 3, '');
                    if (\false === $constraint) {
                        [, $constraint] = $this->findBestVersionAndNameForPackage($this->getIO(), $input, $package, $platformRepo, $preferredStability);
                        $io->writeError(sprintf('Using version <info>%s</info> for <info>%s</info>', $constraint, $package));
                    }
                    $package .= ' ' . $constraint;
                }
                if (\false !== $package) {
                    $requires[] = $package;
                    $existingPackages[] = explode(' ', $package)[0];
                }
            }
        }
        return $requires;
    }
    /**
     * Given a package name, this determines the best version to use in the require key.
     *
     * This returns a version with the ~ operator prefixed when possible.
     *
     * @throws \InvalidArgumentException
     * @return array{string, string}     name version
     */
    private function findBestVersionAndNameForPackage(IOInterface $io, InputInterface $input, string $name, ?PlatformRepository $platformRepo = null, string $preferredStability = 'stable', bool $fixed = \false): array
    {
        // handle ignore-platform-reqs flag if present
        if ($input->hasOption('ignore-platform-reqs') && $input->hasOption('ignore-platform-req')) {
            $platformRequirementFilter = $this->getPlatformRequirementFilter($input);
        } else {
            $platformRequirementFilter = PlatformRequirementFilterFactory::ignoreNothing();
        }
        // find the latest version allowed in this repo set
        $repoSet = $this->getRepositorySet($input);
        $versionSelector = new VersionSelector($repoSet, $platformRepo);
        $effectiveMinimumStability = $this->getMinimumStability($input);
        $package = $versionSelector->findBestCandidate($name, null, $preferredStability, $platformRequirementFilter, 0, $this->getIO());
        if (\false === $package) {
            // platform packages can not be found in the pool in versions other than the local platform's has
            // so if platform reqs are ignored we just take the user's word for it
            if ($platformRequirementFilter->isIgnored($name)) {
                return [$name, '*'];
            }
            // Check if it is a virtual package provided by others
            $providers = $repoSet->getProviders($name);
            if (count($providers) > 0) {
                $constraint = '*';
                if ($input->isInteractive()) {
                    $constraint = $this->getIO()->askAndValidate('Package "<info>' . $name . '</info>" does not exist but is provided by ' . count($providers) . ' packages. Which version constraint would you like to use? [<info>*</info>] ', static function ($value) {
                        $parser = new VersionParser();
                        $parser->parseConstraints($value);
                        return $value;
                    }, 3, '*');
                }
                return [$name, $constraint];
            }
            // Check whether the package requirements were the problem
            if (!$platformRequirementFilter instanceof IgnoreAllPlatformRequirementFilter && \false !== $candidate = $versionSelector->findBestCandidate($name, null, $preferredStability, PlatformRequirementFilterFactory::ignoreAll())) {
                throw new \InvalidArgumentException(sprintf('Package %s has requirements incompatible with your PHP version, PHP extensions and Composer version' . $this->getPlatformExceptionDetails($candidate, $platformRepo), $name));
            }
            // Check whether the minimum stability was the problem but the package exists
            if (\false !== $package = $versionSelector->findBestCandidate($name, null, $preferredStability, $platformRequirementFilter, RepositorySet::ALLOW_UNACCEPTABLE_STABILITIES)) {
                // we must first verify if a valid package would be found in a lower priority repository
                if (\false !== $allReposPackage = $versionSelector->findBestCandidate($name, null, $preferredStability, $platformRequirementFilter, RepositorySet::ALLOW_SHADOWED_REPOSITORIES)) {
                    throw new \InvalidArgumentException('Package ' . $name . ' exists in ' . $allReposPackage->getRepository()->getRepoName() . ' and ' . $package->getRepository()->getRepoName() . ' which has a higher repository priority. The packages from the higher priority repository do not match your minimum-stability and are therefore not installable. That repository is canonical so the lower priority repo\'s packages are not installable. See https://getcomposer.org/repoprio for details and assistance.');
                }
                throw new \InvalidArgumentException(sprintf('Could not find a version of package %s matching your minimum-stability (%s). Require it with an explicit version constraint allowing its desired stability.', $name, $effectiveMinimumStability));
            }
            // Check whether the PHP version was the problem for all versions
            if (!$platformRequirementFilter instanceof IgnoreAllPlatformRequirementFilter && \false !== $candidate = $versionSelector->findBestCandidate($name, null, $preferredStability, PlatformRequirementFilterFactory::ignoreAll(), RepositorySet::ALLOW_UNACCEPTABLE_STABILITIES)) {
                $additional = '';
                if (\false === $versionSelector->findBestCandidate($name, null, $preferredStability, PlatformRequirementFilterFactory::ignoreAll())) {
                    $additional = \PHP_EOL . \PHP_EOL . 'Additionally, the package was only found with a stability of "' . $candidate->getStability() . '" while your minimum stability is "' . $effectiveMinimumStability . '".';
                }
                throw new \InvalidArgumentException(sprintf('Could not find package %s in any version matching your PHP version, PHP extensions and Composer version' . $this->getPlatformExceptionDetails($candidate, $platformRepo) . '%s', $name, $additional));
            }
            // Check for similar names/typos
            $similar = $this->findSimilar($name);
            if (count($similar) > 0) {
                if (in_array($name, $similar, \true)) {
                    throw new \InvalidArgumentException(sprintf("Could not find package %s. It was however found via repository search, which indicates a consistency issue with the repository.", $name));
                }
                if ($input->isInteractive()) {
                    $result = $io->select("<error>Could not find package {$name}.</error>\nPick one of these or leave empty to abort:", $similar, \false, 1);
                    if ($result !== \false) {
                        return $this->findBestVersionAndNameForPackage($io, $input, $similar[$result], $platformRepo, $preferredStability, $fixed);
                    }
                }
                throw new \InvalidArgumentException(sprintf("Could not find package %s.\n\nDid you mean " . (count($similar) > 1 ? 'one of these' : 'this') . "?\n    %s", $name, implode("\n    ", $similar)));
            }
            throw new \InvalidArgumentException(sprintf('Could not find a matching version of package %s. Check the package spelling, your version constraint and that the package is available in a stability which matches your minimum-stability (%s).', $name, $effectiveMinimumStability));
        }
        return [$package->getPrettyName(), $fixed ? $package->getPrettyVersion() : $versionSelector->findRecommendedRequireVersion($package)];
    }
    /**
     * @return array<string>
     */
    private function findSimilar(string $package): array
    {
        try {
            if (null === $this->repos) {
                throw new \LogicException('findSimilar was called before $this->repos was initialized');
            }
            $results = $this->repos->search($package);
        } catch (\Throwable $e) {
            if ($e instanceof \LogicException) {
                throw $e;
            }
            // ignore search errors
            return [];
        }
        $similarPackages = [];
        $installedRepo = $this->requireComposer()->getRepositoryManager()->getLocalRepository();
        foreach ($results as $result) {
            if (null !== $installedRepo->findPackage($result['name'], '*')) {
                // Ignore installed package
                continue;
            }
            $similarPackages[$result['name']] = levenshtein($package, $result['name']);
        }
        asort($similarPackages);
        return array_keys(array_slice($similarPackages, 0, 5));
    }
    private function getPlatformExceptionDetails(PackageInterface $candidate, ?PlatformRepository $platformRepo = null): string
    {
        $details = [];
        if (null === $platformRepo) {
            return '';
        }
        foreach ($candidate->getRequires() as $link) {
            if (!PlatformRepository::isPlatformPackage($link->getTarget())) {
                continue;
            }
            $platformPkg = $platformRepo->findPackage($link->getTarget(), '*');
            if (null === $platformPkg) {
                if ($platformRepo->isPlatformPackageDisabled($link->getTarget())) {
                    $details[] = $candidate->getPrettyName() . ' ' . $candidate->getPrettyVersion() . ' requires ' . $link->getTarget() . ' ' . $link->getPrettyConstraint() . ' but it is disabled by your platform config. Enable it again with "composer config platform.' . $link->getTarget() . ' --unset".';
                } else {
                    $details[] = $candidate->getPrettyName() . ' ' . $candidate->getPrettyVersion() . ' requires ' . $link->getTarget() . ' ' . $link->getPrettyConstraint() . ' but it is not present.';
                }
                continue;
            }
            if (!$link->getConstraint()->matches(new Constraint('==', $platformPkg->getVersion()))) {
                $platformPkgVersion = $platformPkg->getPrettyVersion();
                $platformExtra = $platformPkg->getExtra();
                if (isset($platformExtra['config.platform']) && $platformPkg instanceof CompletePackageInterface) {
                    $platformPkgVersion .= ' (' . $platformPkg->getDescription() . ')';
                }
                $details[] = $candidate->getPrettyName() . ' ' . $candidate->getPrettyVersion() . ' requires ' . $link->getTarget() . ' ' . $link->getPrettyConstraint() . ' which does not match your installed version ' . $platformPkgVersion . '.';
            }
        }
        if (count($details) === 0) {
            return '';
        }
        return ':' . \PHP_EOL . '  - ' . implode(\PHP_EOL . '  - ', $details);
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer\Command;

use Composer\Pcre\Preg;
use Composer\Util\Platform;
use _ContaoManager\Symfony\Component\Console\Input\InputInterface;
use Composer\Console\Input\InputOption;
use Composer\Console\Input\InputArgument;
use _ContaoManager\Symfony\Component\Console\Output\OutputInterface;
/**
 * @author Jordi Boggiano <j.boggiano@seld.be>
 */
class ScriptAliasCommand extends \Composer\Command\BaseCommand
{
    /** @var string */
    private $script;
    /** @var string */
    private $description;
    /** @var string[] */
    private $aliases;
    /**
     * @param string[] $aliases
     */
    public function __construct(string $script, ?string $description, array $aliases = [])
    {
        $this->script = $script;
        $this->description = $description ?? 'Runs the ' . $script . ' script as defined in composer.json';
        $this->aliases = $aliases;
        foreach ($this->aliases as $alias) {
            if (!is_string($alias)) {
                throw new \InvalidArgumentException('"scripts-aliases" element array values should contain only strings');
            }
        }
        $this->ignoreValidationErrors();
        parent::__construct();
    }
    protected function configure(): void
    {
        $this->setName($this->script)->setDescription($this->description)->setAliases($this->aliases)->setDefinition([new InputOption('dev', null, InputOption::VALUE_NONE, 'Sets the dev mode.'), new InputOption('no-dev', null, InputOption::VALUE_NONE, 'Disables the dev mode.'), new InputArgument('args', InputArgument::IS_ARRAY | InputArgument::OPTIONAL, '')])->setHelp(<<<EOT
The <info>run-script</info> command runs scripts defined in composer.json:

<info>php composer.phar run-script post-update-cmd</info>

Read more at https://getcomposer.org/doc/03-cli.md#run-script-run
EOT
);
    }
    protected function execute(InputInterface $input, OutputInterface $output): int
    {
        $composer = $this->requireComposer();
        $args = $input->getArguments();
        // TODO remove for Symfony 6+ as it is then in the interface
        if (!method_exists($input, '__toString')) {
            // @phpstan-ignore-line
            throw new \LogicException('Expected an Input instance that is stringable, got ' . get_class($input));
        }
        $devMode = $input->getOption('dev') || !$input->getOption('no-dev');
        Platform::putEnv('COMPOSER_DEV_MODE', $devMode ? '1' : '0');
        return $composer->getEventDispatcher()->dispatchScript($this->script, $devMode, $args['args'], ['script-alias-input' => Preg::replace('{^\S+ ?}', '', $input->__toString(), 1)]);
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer\Command;

use Composer\Config;
use Composer\Factory;
use Composer\Filter\PlatformRequirementFilter\IgnoreAllPlatformRequirementFilter;
use Composer\Filter\PlatformRequirementFilter\PlatformRequirementFilterFactory;
use Composer\Filter\PlatformRequirementFilter\PlatformRequirementFilterInterface;
use Composer\Installer;
use Composer\Installer\ProjectInstaller;
use Composer\Installer\SuggestedPackagesReporter;
use Composer\IO\IOInterface;
use Composer\Package\BasePackage;
use Composer\DependencyResolver\Operation\InstallOperation;
use Composer\Package\Version\VersionSelector;
use Composer\Package\AliasPackage;
use Composer\Pcre\Preg;
use Composer\Plugin\PluginBlockedException;
use Composer\Repository\RepositoryFactory;
use Composer\Repository\CompositeRepository;
use Composer\Repository\PlatformRepository;
use Composer\Repository\InstalledArrayRepository;
use Composer\Repository\RepositorySet;
use Composer\Script\ScriptEvents;
use Composer\Console\Input\InputArgument;
use _ContaoManager\Seld\Signal\SignalHandler;
use _ContaoManager\Symfony\Component\Console\Input\InputInterface;
use Composer\Console\Input\InputOption;
use _ContaoManager\Symfony\Component\Console\Output\OutputInterface;
use _ContaoManager\Symfony\Component\Finder\Finder;
use Composer\Json\JsonFile;
use Composer\Config\JsonConfigSource;
use Composer\Util\Filesystem;
use Composer\Util\Platform;
use Composer\Util\ProcessExecutor;
use Composer\Package\Version\VersionParser;
use Composer\Advisory\Auditor;
/**
 * Install a package as new project into new directory.
 *
 * @author Benjamin Eberlei <kontakt@beberlei.de>
 * @author Jordi Boggiano <j.boggiano@seld.be>
 * @author Tobias Munk <schmunk@usrbin.de>
 * @author Nils Adermann <naderman@naderman.de>
 */
class CreateProjectCommand extends \Composer\Command\BaseCommand
{
    use \Composer\Command\CompletionTrait;
    /**
     * @var SuggestedPackagesReporter
     */
    protected $suggestedPackagesReporter;
    protected function configure(): void
    {
        $this->setName('create-project')->setDescription('Creates new project from a package into given directory')->setDefinition([new InputArgument('package', InputArgument::OPTIONAL, 'Package name to be installed', null, $this->suggestAvailablePackage()), new InputArgument('directory', InputArgument::OPTIONAL, 'Directory where the files should be created'), new InputArgument('version', InputArgument::OPTIONAL, 'Version, will default to latest'), new InputOption('stability', 's', InputOption::VALUE_REQUIRED, 'Minimum-stability allowed (unless a version is specified).'), new InputOption('prefer-source', null, InputOption::VALUE_NONE, 'Forces installation from package sources when possible, including VCS information.'), new InputOption('prefer-dist', null, InputOption::VALUE_NONE, 'Forces installation from package dist (default behavior).'), new InputOption('prefer-install', null, InputOption::VALUE_REQUIRED, 'Forces installation from package dist|source|auto (auto chooses source for dev versions, dist for the rest).', null, $this->suggestPreferInstall()), new InputOption('repository', null, InputOption::VALUE_REQUIRED | InputOption::VALUE_IS_ARRAY, 'Add custom repositories to look the package up, either by URL or using JSON arrays'), new InputOption('repository-url', null, InputOption::VALUE_REQUIRED, 'DEPRECATED: Use --repository instead.'), new InputOption('add-repository', null, InputOption::VALUE_NONE, 'Add the custom repository in the composer.json. If a lock file is present it will be deleted and an update will be run instead of install.'), new InputOption('dev', null, InputOption::VALUE_NONE, 'Enables installation of require-dev packages (enabled by default, only present for BC).'), new InputOption('no-dev', null, InputOption::VALUE_NONE, 'Disables installation of require-dev packages.'), new InputOption('no-custom-installers', null, InputOption::VALUE_NONE, 'DEPRECATED: Use no-plugins instead.'), new InputOption('no-scripts', null, InputOption::VALUE_NONE, 'Whether to prevent execution of all defined scripts in the root package.'), new InputOption('no-progress', null, InputOption::VALUE_NONE, 'Do not output download progress.'), new InputOption('no-secure-http', null, InputOption::VALUE_NONE, 'Disable the secure-http config option temporarily while installing the root package. Use at your own risk. Using this flag is a bad idea.'), new InputOption('keep-vcs', null, InputOption::VALUE_NONE, 'Whether to prevent deleting the vcs folder.'), new InputOption('remove-vcs', null, InputOption::VALUE_NONE, 'Whether to force deletion of the vcs folder without prompting.'), new InputOption('no-install', null, InputOption::VALUE_NONE, 'Whether to skip installation of the package dependencies.'), new InputOption('no-audit', null, InputOption::VALUE_NONE, 'Whether to skip auditing of the installed package dependencies (can also be set via the COMPOSER_NO_AUDIT=1 env var).'), new InputOption('audit-format', null, InputOption::VALUE_REQUIRED, 'Audit output format. Must be "table", "plain", "json" or "summary".', Auditor::FORMAT_SUMMARY, Auditor::FORMATS), new InputOption('no-security-blocking', null, InputOption::VALUE_NONE, 'Allows installing packages with security advisories or that are abandoned (can also be set via the COMPOSER_NO_SECURITY_BLOCKING=1 env var).'), new InputOption('ignore-platform-req', null, InputOption::VALUE_REQUIRED | InputOption::VALUE_IS_ARRAY, 'Ignore a specific platform requirement (php & ext- packages).'), new InputOption('ignore-platform-reqs', null, InputOption::VALUE_NONE, 'Ignore all platform requirements (php & ext- packages).'), new InputOption('ask', null, InputOption::VALUE_NONE, 'Whether to ask for project directory.')])->setHelp(<<<EOT
The <info>create-project</info> command creates a new project from a given
package into a new directory. If executed without params and in a directory
with a composer.json file it installs the packages for the current project.

You can use this command to bootstrap new projects or setup a clean
version-controlled installation for developers of your project.

<info>php composer.phar create-project vendor/project target-directory [version]</info>

You can also specify the version with the package name using = or : as separator.

<info>php composer.phar create-project vendor/project:version target-directory</info>

To install unstable packages, either specify the version you want, or use the
--stability=dev (where dev can be one of RC, beta, alpha or dev).

To setup a developer workable version you should create the project using the source
controlled code by appending the <info>'--prefer-source'</info> flag.

To install a package from another repository than the default one you
can pass the <info>'--repository=https://myrepository.org'</info> flag.

Read more at https://getcomposer.org/doc/03-cli.md#create-project
EOT
);
    }
    protected function execute(InputInterface $input, OutputInterface $output): int
    {
        $config = Factory::createConfig();
        $io = $this->getIO();
        [$preferSource, $preferDist] = $this->getPreferredInstallOptions($config, $input, \true);
        if ($input->getOption('dev')) {
            $io->writeError('<warning>You are using the deprecated option "dev". Dev packages are installed by default now.</warning>');
        }
        if ($input->getOption('no-custom-installers')) {
            $io->writeError('<warning>You are using the deprecated option "no-custom-installers". Use "no-plugins" instead.</warning>');
            $input->setOption('no-plugins', \true);
        }
        if ($input->isInteractive() && $input->getOption('ask')) {
            $package = $input->getArgument('package');
            if (null === $package) {
                throw new \RuntimeException('Not enough arguments (missing: "package").');
            }
            $parts = explode("/", strtolower($package), 2);
            $input->setArgument('directory', $io->ask('New project directory [<comment>' . array_pop($parts) . '</comment>]: '));
        }
        return $this->installProject($io, $config, $input, $input->getArgument('package'), $input->getArgument('directory'), $input->getArgument('version'), $input->getOption('stability'), $preferSource, $preferDist, !$input->getOption('no-dev'), \count($input->getOption('repository')) > 0 ? $input->getOption('repository') : $input->getOption('repository-url'), $input->getOption('no-plugins'), $input->getOption('no-scripts'), $input->getOption('no-progress'), $input->getOption('no-install'), $this->getPlatformRequirementFilter($input), !$input->getOption('no-secure-http'), $input->getOption('add-repository'));
    }
    /**
     * @param string|array<string>|null $repositories
     *
     * @throws \Exception
     */
    public function installProject(IOInterface $io, Config $config, InputInterface $input, ?string $packageName = null, ?string $directory = null, ?string $packageVersion = null, ?string $stability = 'stable', bool $preferSource = \false, bool $preferDist = \false, bool $installDevPackages = \false, $repositories = null, bool $disablePlugins = \false, bool $disableScripts = \false, bool $noProgress = \false, bool $noInstall = \false, ?PlatformRequirementFilterInterface $platformRequirementFilter = null, bool $secureHttp = \true, bool $addRepository = \false): int
    {
        $oldCwd = Platform::getCwd();
        if ($repositories !== null && !is_array($repositories)) {
            $repositories = (array) $repositories;
        }
        $platformRequirementFilter = $platformRequirementFilter ?? PlatformRequirementFilterFactory::ignoreNothing();
        // we need to manually load the configuration to pass the auth credentials to the io interface!
        $io->loadConfiguration($config);
        $this->suggestedPackagesReporter = new SuggestedPackagesReporter($io);
        if ($packageName !== null) {
            $installedFromVcs = $this->installRootPackage($input, $io, $config, $packageName, $platformRequirementFilter, $directory, $packageVersion, $stability, $preferSource, $preferDist, $installDevPackages, $repositories, $disablePlugins, $disableScripts, $noProgress, $secureHttp);
        } else {
            $installedFromVcs = \false;
        }
        if ($repositories !== null && $addRepository && is_file('composer.lock')) {
            unlink('composer.lock');
        }
        $composer = $this->createComposerInstance($input, $io, null, $disablePlugins, $disableScripts);
        // add the repository to the composer.json and use it for the install run later
        if ($repositories !== null && $addRepository) {
            foreach ($repositories as $index => $repo) {
                $repoConfig = RepositoryFactory::configFromString($io, $composer->getConfig(), $repo, \true);
                $composerJsonRepositoriesConfig = $composer->getConfig()->getRepositories();
                $name = RepositoryFactory::generateRepositoryName($index, $repoConfig, $composerJsonRepositoriesConfig);
                $configSource = new JsonConfigSource(new JsonFile('composer.json'));
                if (isset($repoConfig['packagist']) && $repoConfig === ['packagist' => \false] || isset($repoConfig['packagist.org']) && $repoConfig === ['packagist.org' => \false]) {
                    $configSource->addRepository('packagist.org', \false);
                } else {
                    $configSource->addRepository($name, $repoConfig, \false);
                }
                $composer = $this->createComposerInstance($input, $io, null, $disablePlugins);
            }
        }
        $process = $composer->getLoop()->getProcessExecutor();
        $fs = new Filesystem($process);
        // dispatch event
        $composer->getEventDispatcher()->dispatchScript(ScriptEvents::POST_ROOT_PACKAGE_INSTALL, $installDevPackages);
        // use the new config including the newly installed project
        $config = $composer->getConfig();
        [$preferSource, $preferDist] = $this->getPreferredInstallOptions($config, $input);
        // install dependencies of the created project
        if ($noInstall === \false) {
            $composer->getInstallationManager()->setOutputProgress(!$noProgress);
            $installer = Installer::create($io, $composer);
            $installer->setPreferSource($preferSource)->setPreferDist($preferDist)->setDevMode($installDevPackages)->setPlatformRequirementFilter($platformRequirementFilter)->setSuggestedPackagesReporter($this->suggestedPackagesReporter)->setOptimizeAutoloader($config->get('optimize-autoloader'))->setClassMapAuthoritative($config->get('classmap-authoritative'))->setApcuAutoloader($config->get('apcu-autoloader'))->setAuditConfig($this->createAuditConfig($config, $input));
            if (!$composer->getLocker()->isLocked()) {
                $installer->setUpdate(\true);
            }
            if ($disablePlugins) {
                $installer->disablePlugins();
            }
            try {
                $status = $installer->run();
                if (0 !== $status) {
                    return $status;
                }
            } catch (PluginBlockedException $e) {
                $io->writeError('<error>Hint: To allow running the config command recommended below before dependencies are installed, run create-project with --no-install.</error>');
                $io->writeError('<error>You can then cd into ' . getcwd() . ', configure allow-plugins, and finally run a composer install to complete the process.</error>');
                throw $e;
            }
        }
        $hasVcs = $installedFromVcs;
        if (!$input->getOption('keep-vcs') && $installedFromVcs && ($input->getOption('remove-vcs') || !$io->isInteractive() || $io->askConfirmation('<info>Do you want to remove the existing VCS (.git, .svn..) history?</info> [<comment>y,n</comment>]? '))) {
            $finder = new Finder();
            $finder->depth(0)->directories()->in(Platform::getCwd())->ignoreVCS(\false)->ignoreDotFiles(\false);
            foreach (['.svn', '_svn', 'CVS', '_darcs', '.arch-params', '.monotone', '.bzr', '.git', '.hg', '.fslckout', '_FOSSIL_'] as $vcsName) {
                $finder->name($vcsName);
            }
            try {
                $dirs = iterator_to_array($finder);
                unset($finder);
                foreach ($dirs as $dir) {
                    if (!$fs->removeDirectory((string) $dir)) {
                        throw new \RuntimeException('Could not remove ' . $dir);
                    }
                }
            } catch (\Exception $e) {
                $io->writeError('<error>An error occurred while removing the VCS metadata: ' . $e->getMessage() . '</error>');
            }
            $hasVcs = \false;
        }
        // rewriting self.version dependencies with explicit version numbers if the package's vcs metadata is gone
        if (!$hasVcs) {
            $package = $composer->getPackage();
            $configSource = new JsonConfigSource(new JsonFile('composer.json'));
            foreach (BasePackage::$supportedLinkTypes as $type => $meta) {
                foreach ($package->{'get' . $meta['method']}() as $link) {
                    if ($link->getPrettyConstraint() === 'self.version') {
                        $configSource->addLink($type, $link->getTarget(), $package->getPrettyVersion());
                    }
                }
            }
        }
        // dispatch event
        $composer->getEventDispatcher()->dispatchScript(ScriptEvents::POST_CREATE_PROJECT_CMD, $installDevPackages);
        chdir($oldCwd);
        return 0;
    }
    /**
     * @param array<string>|null $repositories
     *
     * @throws \Exception
     */
    protected function installRootPackage(InputInterface $input, IOInterface $io, Config $config, string $packageName, PlatformRequirementFilterInterface $platformRequirementFilter, ?string $directory = null, ?string $packageVersion = null, ?string $stability = 'stable', bool $preferSource = \false, bool $preferDist = \false, bool $installDevPackages = \false, ?array $repositories = null, bool $disablePlugins = \false, bool $disableScripts = \false, bool $noProgress = \false, bool $secureHttp = \true): bool
    {
        $parser = new VersionParser();
        $requirements = $parser->parseNameVersionPairs([$packageName]);
        $name = strtolower($requirements[0]['name']);
        if (!$packageVersion && isset($requirements[0]['version'])) {
            $packageVersion = $requirements[0]['version'];
        }
        // if no directory was specified, use the 2nd part of the package name
        if (null === $directory) {
            $parts = explode("/", $name, 2);
            $directory = Platform::getCwd() . \DIRECTORY_SEPARATOR . array_pop($parts);
        }
        $directory = rtrim($directory, '/\\');
        $process = new ProcessExecutor($io);
        $fs = new Filesystem($process);
        if (!$fs->isAbsolutePath($directory)) {
            $directory = Platform::getCwd() . \DIRECTORY_SEPARATOR . $directory;
        }
        if ('' === $directory) {
            throw new \UnexpectedValueException('Got an empty target directory, something went wrong');
        }
        // set the base dir to ensure $config->all() below resolves the correct absolute paths to vendor-dir etc
        $config->setBaseDir($directory);
        if (!$secureHttp) {
            $config->merge(['config' => ['secure-http' => \false]], Config::SOURCE_COMMAND);
        }
        $io->writeError('<info>Creating a "' . $packageName . '" project at "' . $fs->findShortestPath(Platform::getCwd(), $directory, \true) . '"</info>');
        if (file_exists($directory)) {
            if (!is_dir($directory)) {
                throw new \InvalidArgumentException('Cannot create project directory at "' . $directory . '", it exists as a file.');
            }
            if (!$fs->isDirEmpty($directory)) {
                throw new \InvalidArgumentException('Project directory "' . $directory . '" is not empty.');
            }
        }
        if (null === $stability) {
            if (null === $packageVersion) {
                $stability = 'stable';
            } elseif (Preg::isMatchStrictGroups('{^[^,\s]*?@(' . implode('|', array_keys(BasePackage::STABILITIES)) . ')$}i', $packageVersion, $match)) {
                $stability = $match[1];
            } else {
                $stability = VersionParser::parseStability($packageVersion);
            }
        }
        $stability = VersionParser::normalizeStability($stability);
        if (!isset(BasePackage::STABILITIES[$stability])) {
            throw new \InvalidArgumentException('Invalid stability provided (' . $stability . '), must be one of: ' . implode(', ', array_keys(BasePackage::STABILITIES)));
        }
        $composer = $this->createComposerInstance($input, $io, $config->all(), $disablePlugins, $disableScripts);
        $config = $composer->getConfig();
        // set the base dir here again on the new config instance, as otherwise in case the vendor dir is defined in an env var for example it would still override the value set above by $config->all()
        $config->setBaseDir($directory);
        $rm = $composer->getRepositoryManager();
        $repositorySet = new RepositorySet($stability);
        if (null === $repositories) {
            $repositorySet->addRepository(new CompositeRepository(RepositoryFactory::defaultRepos($io, $config, $rm)));
        } else {
            foreach ($repositories as $repo) {
                $repoConfig = RepositoryFactory::configFromString($io, $config, $repo, \true);
                if (isset($repoConfig['packagist']) && $repoConfig === ['packagist' => \false] || isset($repoConfig['packagist.org']) && $repoConfig === ['packagist.org' => \false]) {
                    continue;
                }
                // disable symlinking for the root package by default as that most likely makes no sense
                if (($repoConfig['type'] ?? null) === 'path' && !isset($repoConfig['options']['symlink'])) {
                    $repoConfig['options']['symlink'] = \false;
                }
                $repositorySet->addRepository(RepositoryFactory::createRepo($io, $config, $repoConfig, $rm));
            }
        }
        $platformOverrides = $config->get('platform');
        $platformRepo = new PlatformRepository([], $platformOverrides);
        // find the latest version if there are multiple
        $versionSelector = new VersionSelector($repositorySet, $platformRepo);
        $package = $versionSelector->findBestCandidate($name, $packageVersion, $stability, $platformRequirementFilter, 0, $io);
        if (!$package) {
            $errorMessage = "Could not find package {$name} with " . ($packageVersion ? "version {$packageVersion}" : "stability {$stability}");
            if (!$platformRequirementFilter instanceof IgnoreAllPlatformRequirementFilter && $versionSelector->findBestCandidate($name, $packageVersion, $stability, PlatformRequirementFilterFactory::ignoreAll())) {
                throw new \InvalidArgumentException($errorMessage . ' in a version installable using your PHP version, PHP extensions and Composer version.');
            }
            throw new \InvalidArgumentException($errorMessage . '.');
        }
        // handler Ctrl+C aborts gracefully
        @mkdir($directory, 0777, \true);
        if (\false !== $realDir = realpath($directory)) {
            $signalHandler = SignalHandler::create([SignalHandler::SIGINT, SignalHandler::SIGTERM, SignalHandler::SIGHUP], function (string $signal, SignalHandler $handler) use ($realDir) {
                $this->getIO()->writeError('Received ' . $signal . ', aborting', \true, IOInterface::DEBUG);
                $fs = new Filesystem();
                $fs->removeDirectory($realDir);
                $handler->exitWithLastSignal();
            });
        }
        // avoid displaying 9999999-dev as version if default-branch was selected
        if ($package instanceof AliasPackage && $package->getPrettyVersion() === VersionParser::DEFAULT_BRANCH_ALIAS) {
            $package = $package->getAliasOf();
        }
        $io->writeError('<info>Installing ' . $package->getName() . ' (' . $package->getFullPrettyVersion(\false) . ')</info>');
        if ($disablePlugins) {
            $io->writeError('<info>Plugins have been disabled.</info>');
        }
        if ($package instanceof AliasPackage) {
            $package = $package->getAliasOf();
        }
        $dm = $composer->getDownloadManager();
        $dm->setPreferSource($preferSource)->setPreferDist($preferDist);
        $projectInstaller = new ProjectInstaller($directory, $dm, $fs);
        $im = $composer->getInstallationManager();
        $im->setOutputProgress(!$noProgress);
        $im->addInstaller($projectInstaller);
        $im->execute(new InstalledArrayRepository(), [new InstallOperation($package)]);
        $im->notifyInstalls($io);
        // collect suggestions
        $this->suggestedPackagesReporter->addSuggestionsFromPackage($package);
        $installedFromVcs = 'source' === $package->getInstallationSource();
        $io->writeError('<info>Created project in ' . $directory . '</info>');
        chdir($directory);
        // ensure that the env var being set does not interfere with create-project
        // as it is probably not meant to be used here, so we do not use it if a composer.json can be found
        // in the project
        if (file_exists($directory . '/composer.json') && Platform::getEnv('COMPOSER') !== \false) {
            Platform::clearEnv('COMPOSER');
        }
        Platform::putEnv('COMPOSER_ROOT_VERSION', $package->getPrettyVersion());
        // once the root project is fully initialized, we do not need to wipe everything on user abort anymore even if it happens during deps install
        if (isset($signalHandler)) {
            $signalHandler->unregister();
        }
        return $installedFromVcs;
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer\Command;

use Composer\Composer;
use Composer\Config;
use Composer\Console\Application;
use Composer\Console\Input\InputArgument;
use Composer\Console\Input\InputOption;
use Composer\Factory;
use Composer\Filter\PlatformRequirementFilter\PlatformRequirementFilterFactory;
use Composer\Filter\PlatformRequirementFilter\PlatformRequirementFilterInterface;
use Composer\IO\IOInterface;
use Composer\IO\NullIO;
use Composer\Plugin\PreCommandRunEvent;
use Composer\Package\Version\VersionParser;
use Composer\Plugin\PluginEvents;
use Composer\Advisory\Auditor;
use Composer\Advisory\AuditConfig;
use Composer\Util\Platform;
use _ContaoManager\Symfony\Component\Console\Completion\CompletionInput;
use _ContaoManager\Symfony\Component\Console\Completion\CompletionSuggestions;
use _ContaoManager\Symfony\Component\Console\Helper\Table;
use _ContaoManager\Symfony\Component\Console\Helper\TableSeparator;
use _ContaoManager\Symfony\Component\Console\Input\InputInterface;
use _ContaoManager\Symfony\Component\Console\Output\OutputInterface;
use _ContaoManager\Symfony\Component\Console\Command\Command;
use _ContaoManager\Symfony\Component\Console\Terminal;
/**
 * Base class for Composer commands
 *
 * @author Ryan Weaver <ryan@knplabs.com>
 * @author Konstantin Kudryashov <ever.zet@gmail.com>
 */
abstract class BaseCommand extends Command
{
    /**
     * @var Composer|null
     */
    private $composer;
    /**
     * @var IOInterface
     */
    private $io;
    /**
     * Gets the application instance for this command.
     */
    public function getApplication(): Application
    {
        $application = parent::getApplication();
        if (!$application instanceof Application) {
            throw new \RuntimeException('Composer commands can only work with an ' . Application::class . ' instance set');
        }
        return $application;
    }
    /**
     * @param  bool              $required       Should be set to false, or use `requireComposer` instead
     * @param  bool|null         $disablePlugins If null, reads --no-plugins as default
     * @param  bool|null         $disableScripts If null, reads --no-scripts as default
     * @throws \RuntimeException
     * @return Composer|null
     * @deprecated since Composer 2.3.0 use requireComposer or tryComposer depending on whether you have $required set to true or false
     */
    public function getComposer(bool $required = \true, ?bool $disablePlugins = null, ?bool $disableScripts = null)
    {
        if ($required) {
            return $this->requireComposer($disablePlugins, $disableScripts);
        }
        return $this->tryComposer($disablePlugins, $disableScripts);
    }
    /**
     * Retrieves the default Composer\Composer instance or throws
     *
     * Use this instead of getComposer if you absolutely need an instance
     *
     * @param bool|null $disablePlugins If null, reads --no-plugins as default
     * @param bool|null $disableScripts If null, reads --no-scripts as default
     * @throws \RuntimeException
     */
    public function requireComposer(?bool $disablePlugins = null, ?bool $disableScripts = null): Composer
    {
        if (null === $this->composer) {
            $application = parent::getApplication();
            if ($application instanceof Application) {
                $this->composer = $application->getComposer(\true, $disablePlugins, $disableScripts);
                assert($this->composer instanceof Composer);
            } else {
                throw new \RuntimeException('Could not create a Composer\Composer instance, you must inject ' . 'one if this command is not used with a Composer\Console\Application instance');
            }
        }
        return $this->composer;
    }
    /**
     * Retrieves the default Composer\Composer instance or null
     *
     * Use this instead of getComposer(false)
     *
     * @param bool|null $disablePlugins If null, reads --no-plugins as default
     * @param bool|null $disableScripts If null, reads --no-scripts as default
     */
    public function tryComposer(?bool $disablePlugins = null, ?bool $disableScripts = null): ?Composer
    {
        if (null === $this->composer) {
            $application = parent::getApplication();
            if ($application instanceof Application) {
                $this->composer = $application->getComposer(\false, $disablePlugins, $disableScripts);
            }
        }
        return $this->composer;
    }
    /**
     * @return void
     */
    public function setComposer(Composer $composer)
    {
        $this->composer = $composer;
    }
    /**
     * Removes the cached composer instance
     *
     * @return void
     */
    public function resetComposer()
    {
        $this->composer = null;
        $this->getApplication()->resetComposer();
    }
    /**
     * Whether or not this command is meant to call another command.
     *
     * This is mainly needed to avoid duplicated warnings messages.
     *
     * @return bool
     */
    public function isProxyCommand()
    {
        return \false;
    }
    /**
     * @return IOInterface
     */
    public function getIO()
    {
        if (null === $this->io) {
            $application = parent::getApplication();
            if ($application instanceof Application) {
                $this->io = $application->getIO();
            } else {
                $this->io = new NullIO();
            }
        }
        return $this->io;
    }
    /**
     * @return void
     */
    public function setIO(IOInterface $io)
    {
        $this->io = $io;
    }
    /**
     * @inheritdoc
     *
     * Backport suggested values definition from symfony/console 6.1+
     *
     * TODO drop when PHP 8.1 / symfony 6.1+ can be required
     */
    public function complete(CompletionInput $input, CompletionSuggestions $suggestions): void
    {
        $definition = $this->getDefinition();
        $name = (string) $input->getCompletionName();
        if (CompletionInput::TYPE_OPTION_VALUE === $input->getCompletionType() && $definition->hasOption($name) && ($option = $definition->getOption($name)) instanceof InputOption) {
            $option->complete($input, $suggestions);
        } elseif (CompletionInput::TYPE_ARGUMENT_VALUE === $input->getCompletionType() && $definition->hasArgument($name) && ($argument = $definition->getArgument($name)) instanceof InputArgument) {
            $argument->complete($input, $suggestions);
        } else {
            parent::complete($input, $suggestions);
        }
    }
    /**
     * @inheritDoc
     */
    protected function initialize(InputInterface $input, OutputInterface $output): void
    {
        // initialize a plugin-enabled Composer instance, either local or global
        $disablePlugins = $input->hasParameterOption('--no-plugins');
        $disableScripts = $input->hasParameterOption('--no-scripts');
        $application = parent::getApplication();
        if ($application instanceof Application && $application->getDisablePluginsByDefault()) {
            $disablePlugins = \true;
        }
        if ($application instanceof Application && $application->getDisableScriptsByDefault()) {
            $disableScripts = \true;
        }
        if ($this instanceof \Composer\Command\SelfUpdateCommand) {
            $disablePlugins = \true;
            $disableScripts = \true;
        }
        $composer = $this->tryComposer($disablePlugins, $disableScripts);
        $io = $this->getIO();
        if (null === $composer) {
            $composer = Factory::createGlobal($this->getIO(), $disablePlugins, $disableScripts);
        }
        if ($composer) {
            $preCommandRunEvent = new PreCommandRunEvent(PluginEvents::PRE_COMMAND_RUN, $input, $this->getName());
            $composer->getEventDispatcher()->dispatch($preCommandRunEvent->getName(), $preCommandRunEvent);
        }
        if (\true === $input->hasParameterOption(['--no-ansi']) && $input->hasOption('no-progress')) {
            $input->setOption('no-progress', \true);
        }
        $envOptions = ['COMPOSER_NO_AUDIT' => ['no-audit'], 'COMPOSER_NO_DEV' => ['no-dev', 'update-no-dev'], 'COMPOSER_PREFER_STABLE' => ['prefer-stable'], 'COMPOSER_PREFER_LOWEST' => ['prefer-lowest'], 'COMPOSER_MINIMAL_CHANGES' => ['minimal-changes'], 'COMPOSER_WITH_DEPENDENCIES' => ['with-dependencies'], 'COMPOSER_WITH_ALL_DEPENDENCIES' => ['with-all-dependencies'], 'COMPOSER_NO_SECURITY_BLOCKING' => ['no-security-blocking']];
        foreach ($envOptions as $envName => $optionNames) {
            foreach ($optionNames as $optionName) {
                if (\true === $input->hasOption($optionName)) {
                    if (\false === $input->getOption($optionName) && (bool) Platform::getEnv($envName)) {
                        $input->setOption($optionName, \true);
                    }
                }
            }
        }
        if (\true === $input->hasOption('ignore-platform-reqs')) {
            if (!$input->getOption('ignore-platform-reqs') && (bool) Platform::getEnv('COMPOSER_IGNORE_PLATFORM_REQS')) {
                $input->setOption('ignore-platform-reqs', \true);
                $io->writeError('<warning>COMPOSER_IGNORE_PLATFORM_REQS is set. You may experience unexpected errors.</warning>');
            }
        }
        if (\true === $input->hasOption('ignore-platform-req') && (!$input->hasOption('ignore-platform-reqs') || !$input->getOption('ignore-platform-reqs'))) {
            $ignorePlatformReqEnv = Platform::getEnv('COMPOSER_IGNORE_PLATFORM_REQ');
            if (0 === count($input->getOption('ignore-platform-req')) && is_string($ignorePlatformReqEnv) && '' !== $ignorePlatformReqEnv) {
                $input->setOption('ignore-platform-req', explode(',', $ignorePlatformReqEnv));
                $io->writeError('<warning>COMPOSER_IGNORE_PLATFORM_REQ is set to ignore ' . $ignorePlatformReqEnv . '. You may experience unexpected errors.</warning>');
            }
        }
        parent::initialize($input, $output);
    }
    /**
     * Calls {@see Factory::create()} with the given arguments, taking into account flags and default states for disabling scripts and plugins
     *
     * @param  mixed    $config either a configuration array or a filename to read from, if null it will read from
     *                          the default filename
     */
    protected function createComposerInstance(InputInterface $input, IOInterface $io, $config = null, ?bool $disablePlugins = null, ?bool $disableScripts = null): Composer
    {
        $disablePlugins = $disablePlugins === \true || $input->hasParameterOption('--no-plugins');
        $disableScripts = $disableScripts === \true || $input->hasParameterOption('--no-scripts');
        $application = parent::getApplication();
        if ($application instanceof Application && $application->getDisablePluginsByDefault()) {
            $disablePlugins = \true;
        }
        if ($application instanceof Application && $application->getDisableScriptsByDefault()) {
            $disableScripts = \true;
        }
        return Factory::create($io, $config, $disablePlugins, $disableScripts);
    }
    /**
     * Returns preferSource and preferDist values based on the configuration.
     *
     * @return bool[] An array composed of the preferSource and preferDist values
     */
    protected function getPreferredInstallOptions(Config $config, InputInterface $input, bool $keepVcsRequiresPreferSource = \false)
    {
        $preferSource = \false;
        $preferDist = \false;
        switch ($config->get('preferred-install')) {
            case 'source':
                $preferSource = \true;
                break;
            case 'dist':
                $preferDist = \true;
                break;
            case 'auto':
            default:
                // noop
                break;
        }
        if (!$input->hasOption('prefer-dist') || !$input->hasOption('prefer-source')) {
            return [$preferSource, $preferDist];
        }
        if ($input->hasOption('prefer-install') && is_string($input->getOption('prefer-install'))) {
            if ($input->getOption('prefer-source')) {
                throw new \InvalidArgumentException('--prefer-source can not be used together with --prefer-install');
            }
            if ($input->getOption('prefer-dist')) {
                throw new \InvalidArgumentException('--prefer-dist can not be used together with --prefer-install');
            }
            switch ($input->getOption('prefer-install')) {
                case 'dist':
                    $input->setOption('prefer-dist', \true);
                    break;
                case 'source':
                    $input->setOption('prefer-source', \true);
                    break;
                case 'auto':
                    $preferDist = \false;
                    $preferSource = \false;
                    break;
                default:
                    throw new \UnexpectedValueException('--prefer-install accepts one of "dist", "source" or "auto", got ' . $input->getOption('prefer-install'));
            }
        }
        if ($input->getOption('prefer-source') || $input->getOption('prefer-dist') || $keepVcsRequiresPreferSource && $input->hasOption('keep-vcs') && $input->getOption('keep-vcs')) {
            $preferSource = $input->getOption('prefer-source') || $keepVcsRequiresPreferSource && $input->hasOption('keep-vcs') && $input->getOption('keep-vcs');
            $preferDist = $input->getOption('prefer-dist');
        }
        return [$preferSource, $preferDist];
    }
    protected function getPlatformRequirementFilter(InputInterface $input): PlatformRequirementFilterInterface
    {
        if (!$input->hasOption('ignore-platform-reqs') || !$input->hasOption('ignore-platform-req')) {
            throw new \LogicException('Calling getPlatformRequirementFilter from a command which does not define the --ignore-platform-req[s] flags is not permitted.');
        }
        if (\true === $input->getOption('ignore-platform-reqs')) {
            return PlatformRequirementFilterFactory::ignoreAll();
        }
        $ignores = $input->getOption('ignore-platform-req');
        if (count($ignores) > 0) {
            return PlatformRequirementFilterFactory::fromBoolOrList($ignores);
        }
        return PlatformRequirementFilterFactory::ignoreNothing();
    }
    /**
     * @param array<string> $requirements
     *
     * @return array<string, string>
     */
    protected function formatRequirements(array $requirements)
    {
        $requires = [];
        $requirements = $this->normalizeRequirements($requirements);
        foreach ($requirements as $requirement) {
            if (!isset($requirement['version'])) {
                throw new \UnexpectedValueException('Option ' . $requirement['name'] . ' is missing a version constraint, use e.g. ' . $requirement['name'] . ':^1.0');
            }
            $requires[$requirement['name']] = $requirement['version'];
        }
        return $requires;
    }
    /**
     * @param array<string> $requirements
     *
     * @return list<array{name: string, version?: string}>
     */
    protected function normalizeRequirements(array $requirements)
    {
        $parser = new VersionParser();
        return $parser->parseNameVersionPairs($requirements);
    }
    /**
     * @param array<TableSeparator|mixed[]> $table
     *
     * @return void
     */
    protected function renderTable(array $table, OutputInterface $output)
    {
        $renderer = new Table($output);
        $renderer->setStyle('compact');
        $renderer->setRows($table)->render();
    }
    /**
     * @return int
     */
    protected function getTerminalWidth()
    {
        $terminal = new Terminal();
        $width = $terminal->getWidth();
        if (Platform::isWindows()) {
            $width--;
        } else {
            $width = max(80, $width);
        }
        return $width;
    }
    /**
     * @internal
     * @param 'format'|'audit-format' $optName
     * @return Auditor::FORMAT_*
     */
    protected function getAuditFormat(InputInterface $input, string $optName = 'audit-format'): string
    {
        if (!$input->hasOption($optName)) {
            throw new \LogicException('This should not be called on a Command which has no ' . $optName . ' option defined.');
        }
        $val = $input->getOption($optName);
        if (!in_array($val, Auditor::FORMATS, \true)) {
            throw new \InvalidArgumentException('--' . $optName . ' must be one of ' . implode(', ', Auditor::FORMATS) . '.');
        }
        return $val;
    }
    /**
     * Creates an AuditConfig from the Config object, optionally overriding security blocking based on input options
     *
     * @internal
     */
    protected function createAuditConfig(Config $config, InputInterface $input): AuditConfig
    {
        // Handle both --audit and --no-audit flags
        if ($input->hasOption('audit')) {
            $audit = (bool) $input->getOption('audit');
        } else {
            $audit = !($input->hasOption('no-audit') && $input->getOption('no-audit'));
        }
        $auditFormat = $input->hasOption('audit-format') ? $this->getAuditFormat($input) : Auditor::FORMAT_SUMMARY;
        $auditConfig = AuditConfig::fromConfig($config, $audit, $auditFormat);
        if ((bool) Platform::getEnv('COMPOSER_NO_SECURITY_BLOCKING') || $input->hasOption('no-security-blocking') && $input->getOption('no-security-blocking')) {
            $auditConfig = new AuditConfig(
                $auditConfig->audit,
                $auditConfig->auditFormat,
                $auditConfig->auditAbandoned,
                \false,
                // blockInsecure
                $auditConfig->blockAbandoned,
                $auditConfig->ignoreUnreachable,
                $auditConfig->ignoreListForAudit,
                $auditConfig->ignoreListForBlocking,
                $auditConfig->ignoreSeverityForAudit,
                $auditConfig->ignoreSeverityForBlocking,
                $auditConfig->ignoreAbandonedForAudit,
                $auditConfig->ignoreAbandonedForBlocking
            );
        }
        return $auditConfig;
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer\Command;

use _ContaoManager\Symfony\Component\Console\Input\InputInterface;
use Composer\Console\Input\InputArgument;
use _ContaoManager\Symfony\Component\Console\Input\ArrayInput;
use Composer\Console\Input\InputOption;
use _ContaoManager\Symfony\Component\Console\Output\OutputInterface;
/**
 * @author Jordi Boggiano <j.boggiano@seld.be>
 */
class OutdatedCommand extends \Composer\Command\BaseCommand
{
    use \Composer\Command\CompletionTrait;
    protected function configure(): void
    {
        $this->setName('outdated')->setDescription('Shows a list of installed packages that have updates available, including their latest version')->setDefinition([new InputArgument('package', InputArgument::OPTIONAL, 'Package to inspect. Or a name including a wildcard (*) to filter lists of packages instead.', null, $this->suggestInstalledPackage(\false)), new InputOption('outdated', 'o', InputOption::VALUE_NONE, 'Show only packages that are outdated (this is the default, but present here for compat with `show`'), new InputOption('all', 'a', InputOption::VALUE_NONE, 'Show all installed packages with their latest versions'), new InputOption('locked', null, InputOption::VALUE_NONE, 'Shows updates for packages from the lock file, regardless of what is currently in vendor dir'), new InputOption('direct', 'D', InputOption::VALUE_NONE, 'Shows only packages that are directly required by the root package'), new InputOption('strict', null, InputOption::VALUE_NONE, 'Return a non-zero exit code when there are outdated packages'), new InputOption('major-only', 'M', InputOption::VALUE_NONE, 'Show only packages that have major SemVer-compatible updates.'), new InputOption('minor-only', 'm', InputOption::VALUE_NONE, 'Show only packages that have minor SemVer-compatible updates.'), new InputOption('patch-only', 'p', InputOption::VALUE_NONE, 'Show only packages that have patch SemVer-compatible updates.'), new InputOption('sort-by-age', 'A', InputOption::VALUE_NONE, 'Displays the installed version\'s age, and sorts packages oldest first.'), new InputOption('format', 'f', InputOption::VALUE_REQUIRED, 'Format of the output: text or json', 'text', ['json', 'text']), new InputOption('ignore', null, InputOption::VALUE_REQUIRED | InputOption::VALUE_IS_ARRAY, 'Ignore specified package(s). Can contain wildcards (*). Use it if you don\'t want to be informed about new versions of some packages.', null, $this->suggestInstalledPackage(\false)), new InputOption('no-dev', null, InputOption::VALUE_NONE, 'Disables search in require-dev packages.'), new InputOption('ignore-platform-req', null, InputOption::VALUE_REQUIRED | InputOption::VALUE_IS_ARRAY, 'Ignore a specific platform requirement (php & ext- packages). Use with the --outdated option'), new InputOption('ignore-platform-reqs', null, InputOption::VALUE_NONE, 'Ignore all platform requirements (php & ext- packages). Use with the --outdated option')])->setHelp(<<<EOT
The outdated command is just a proxy for `composer show -l`

The color coding (or signage if you have ANSI colors disabled) for dependency versions is as such:

- <info>green</info> (=): Dependency is in the latest version and is up to date.
- <comment>yellow</comment> (~): Dependency has a new version available that includes backwards
  compatibility breaks according to semver, so upgrade when you can but it
  may involve work.
- <highlight>red</highlight> (!): Dependency has a new version that is semver-compatible and you should upgrade it.

Read more at https://getcomposer.org/doc/03-cli.md#outdated
EOT
);
    }
    protected function execute(InputInterface $input, OutputInterface $output): int
    {
        $args = ['command' => 'show', '--latest' => \true];
        if ($input->getOption('no-interaction')) {
            $args['--no-interaction'] = \true;
        }
        if ($input->getOption('no-plugins')) {
            $args['--no-plugins'] = \true;
        }
        if ($input->getOption('no-scripts')) {
            $args['--no-scripts'] = \true;
        }
        if ($input->getOption('no-cache')) {
            $args['--no-cache'] = \true;
        }
        if (!$input->getOption('all')) {
            $args['--outdated'] = \true;
        }
        if ($input->getOption('direct')) {
            $args['--direct'] = \true;
        }
        if (null !== $input->getArgument('package')) {
            $args['package'] = $input->getArgument('package');
        }
        if ($input->getOption('strict')) {
            $args['--strict'] = \true;
        }
        if ($input->getOption('major-only')) {
            $args['--major-only'] = \true;
        }
        if ($input->getOption('minor-only')) {
            $args['--minor-only'] = \true;
        }
        if ($input->getOption('patch-only')) {
            $args['--patch-only'] = \true;
        }
        if ($input->getOption('locked')) {
            $args['--locked'] = \true;
        }
        if ($input->getOption('no-dev')) {
            $args['--no-dev'] = \true;
        }
        if ($input->getOption('sort-by-age')) {
            $args['--sort-by-age'] = \true;
        }
        $args['--ignore-platform-req'] = $input->getOption('ignore-platform-req');
        if ($input->getOption('ignore-platform-reqs')) {
            $args['--ignore-platform-reqs'] = \true;
        }
        $args['--format'] = $input->getOption('format');
        $args['--ignore'] = $input->getOption('ignore');
        $input = new ArrayInput($args);
        return $this->getApplication()->run($input, $output);
    }
    /**
     * @inheritDoc
     */
    public function isProxyCommand(): bool
    {
        return \true;
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer\Command;

use Composer\Plugin\CommandEvent;
use Composer\Plugin\PluginEvents;
use _ContaoManager\Symfony\Component\Console\Input\InputInterface;
use _ContaoManager\Symfony\Component\Console\Input\InputOption;
use _ContaoManager\Symfony\Component\Console\Output\OutputInterface;
/**
 * @author Jordi Boggiano <j.boggiano@seld.be>
 */
class DumpAutoloadCommand extends \Composer\Command\BaseCommand
{
    protected function configure(): void
    {
        $this->setName('dump-autoload')->setAliases(['dumpautoload'])->setDescription('Dumps the autoloader')->setDefinition([new InputOption('optimize', 'o', InputOption::VALUE_NONE, 'Optimizes PSR0 and PSR4 packages to be loaded with classmaps too, good for production.'), new InputOption('classmap-authoritative', 'a', InputOption::VALUE_NONE, 'Autoload classes from the classmap only. Implicitly enables `--optimize`.'), new InputOption('apcu', null, InputOption::VALUE_NONE, 'Use APCu to cache found/not-found classes.'), new InputOption('apcu-prefix', null, InputOption::VALUE_REQUIRED, 'Use a custom prefix for the APCu autoloader cache. Implicitly enables --apcu'), new InputOption('dry-run', null, InputOption::VALUE_NONE, 'Outputs the operations but will not execute anything.'), new InputOption('dev', null, InputOption::VALUE_NONE, 'Enables autoload-dev rules. Composer will by default infer this automatically according to the last install or update --no-dev state.'), new InputOption('no-dev', null, InputOption::VALUE_NONE, 'Disables autoload-dev rules. Composer will by default infer this automatically according to the last install or update --no-dev state.'), new InputOption('ignore-platform-req', null, InputOption::VALUE_REQUIRED | InputOption::VALUE_IS_ARRAY, 'Ignore a specific platform requirement (php & ext- packages).'), new InputOption('ignore-platform-reqs', null, InputOption::VALUE_NONE, 'Ignore all platform requirements (php & ext- packages).'), new InputOption('strict-psr', null, InputOption::VALUE_NONE, 'Return a failed status code (1) if PSR-4 or PSR-0 mapping errors are present. Requires --optimize to work.'), new InputOption('strict-ambiguous', null, InputOption::VALUE_NONE, 'Return a failed status code (2) if the same class is found in multiple files. Requires --optimize to work.')])->setHelp(<<<EOT
<info>php composer.phar dump-autoload</info>

Read more at https://getcomposer.org/doc/03-cli.md#dump-autoload-dumpautoload
EOT
);
    }
    protected function execute(InputInterface $input, OutputInterface $output): int
    {
        $composer = $this->requireComposer();
        $commandEvent = new CommandEvent(PluginEvents::COMMAND, 'dump-autoload', $input, $output);
        $composer->getEventDispatcher()->dispatch($commandEvent->getName(), $commandEvent);
        $installationManager = $composer->getInstallationManager();
        $localRepo = $composer->getRepositoryManager()->getLocalRepository();
        $package = $composer->getPackage();
        $config = $composer->getConfig();
        $missingDependencies = \false;
        foreach ($localRepo->getCanonicalPackages() as $localPkg) {
            $installPath = $installationManager->getInstallPath($localPkg);
            if ($installPath !== null && file_exists($installPath) === \false) {
                $missingDependencies = \true;
                $this->getIO()->write('<warning>Not all dependencies are installed. Make sure to run a "composer install" to install missing dependencies</warning>');
                break;
            }
        }
        $optimize = $input->getOption('optimize') || $config->get('optimize-autoloader');
        $authoritative = $input->getOption('classmap-authoritative') || $config->get('classmap-authoritative');
        $apcuPrefix = $input->getOption('apcu-prefix');
        $apcu = $apcuPrefix !== null || $input->getOption('apcu') || $config->get('apcu-autoloader');
        if ($input->getOption('strict-psr') && !$optimize && !$authoritative) {
            throw new \InvalidArgumentException('--strict-psr mode only works with optimized autoloader, use --optimize or --classmap-authoritative if you want a strict return value.');
        }
        if ($input->getOption('strict-ambiguous') && !$optimize && !$authoritative) {
            throw new \InvalidArgumentException('--strict-ambiguous mode only works with optimized autoloader, use --optimize or --classmap-authoritative if you want a strict return value.');
        }
        if ($authoritative) {
            $this->getIO()->write('<info>Generating optimized autoload files (authoritative)</info>');
        } elseif ($optimize) {
            $this->getIO()->write('<info>Generating optimized autoload files</info>');
        } else {
            $this->getIO()->write('<info>Generating autoload files</info>');
        }
        $generator = $composer->getAutoloadGenerator();
        if ($input->getOption('dry-run')) {
            $generator->setDryRun(\true);
        }
        if ($input->getOption('no-dev')) {
            $generator->setDevMode(\false);
        }
        if ($input->getOption('dev')) {
            if ($input->getOption('no-dev')) {
                throw new \InvalidArgumentException('You can not use both --no-dev and --dev as they conflict with each other.');
            }
            $generator->setDevMode(\true);
        }
        $generator->setClassMapAuthoritative($authoritative);
        $generator->setRunScripts(\true);
        $generator->setApcu($apcu, $apcuPrefix);
        $generator->setPlatformRequirementFilter($this->getPlatformRequirementFilter($input));
        $classMap = $generator->dump($config, $localRepo, $package, $installationManager, 'composer', $optimize, null, $composer->getLocker(), $input->getOption('strict-ambiguous'));
        $numberOfClasses = count($classMap);
        if ($authoritative) {
            $this->getIO()->write('<info>Generated optimized autoload files (authoritative) containing ' . $numberOfClasses . ' classes</info>');
        } elseif ($optimize) {
            $this->getIO()->write('<info>Generated optimized autoload files containing ' . $numberOfClasses . ' classes</info>');
        } else {
            $this->getIO()->write('<info>Generated autoload files</info>');
        }
        if ($missingDependencies || $input->getOption('strict-psr') && count($classMap->getPsrViolations()) > 0) {
            return 1;
        }
        if ($input->getOption('strict-ambiguous') && count($classMap->getAmbiguousClasses(\false)) > 0) {
            return 2;
        }
        return 0;
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer\Command;

use Composer\Package\CompletePackageInterface;
use Composer\Repository\RepositoryInterface;
use Composer\Repository\RootPackageRepository;
use Composer\Repository\RepositoryFactory;
use Composer\Util\Platform;
use Composer\Util\ProcessExecutor;
use Composer\Console\Input\InputArgument;
use Composer\Console\Input\InputOption;
use _ContaoManager\Symfony\Component\Console\Input\InputInterface;
use _ContaoManager\Symfony\Component\Console\Output\OutputInterface;
/**
 * @author Robert Schönthal <seroscho@googlemail.com>
 */
class HomeCommand extends \Composer\Command\BaseCommand
{
    use \Composer\Command\CompletionTrait;
    /**
     * @inheritDoc
     */
    protected function configure(): void
    {
        $this->setName('browse')->setAliases(['home'])->setDescription('Opens the package\'s repository URL or homepage in your browser')->setDefinition([new InputArgument('packages', InputArgument::IS_ARRAY, 'Package(s) to browse to.', null, $this->suggestInstalledPackage()), new InputOption('homepage', 'H', InputOption::VALUE_NONE, 'Open the homepage instead of the repository URL.'), new InputOption('show', 's', InputOption::VALUE_NONE, 'Only show the homepage or repository URL.')])->setHelp(<<<EOT
The home command opens or shows a package's repository URL or
homepage in your default browser.

To open the homepage by default, use -H or --homepage.
To show instead of open the repository or homepage URL, use -s or --show.

Read more at https://getcomposer.org/doc/03-cli.md#browse-home
EOT
);
    }
    protected function execute(InputInterface $input, OutputInterface $output): int
    {
        $repos = $this->initializeRepos();
        $io = $this->getIO();
        $return = 0;
        $packages = $input->getArgument('packages');
        if (count($packages) === 0) {
            $io->writeError('No package specified, opening homepage for the root package');
            $packages = [$this->requireComposer()->getPackage()->getName()];
        }
        foreach ($packages as $packageName) {
            $handled = \false;
            $packageExists = \false;
            foreach ($repos as $repo) {
                foreach ($repo->findPackages($packageName) as $package) {
                    $packageExists = \true;
                    if ($package instanceof CompletePackageInterface && $this->handlePackage($package, $input->getOption('homepage'), $input->getOption('show'))) {
                        $handled = \true;
                        break 2;
                    }
                }
            }
            if (!$packageExists) {
                $return = 1;
                $io->writeError('<warning>Package ' . $packageName . ' not found</warning>');
            }
            if (!$handled) {
                $return = 1;
                $io->writeError('<warning>' . ($input->getOption('homepage') ? 'Invalid or missing homepage' : 'Invalid or missing repository URL') . ' for ' . $packageName . '</warning>');
            }
        }
        return $return;
    }
    private function handlePackage(CompletePackageInterface $package, bool $showHomepage, bool $showOnly): bool
    {
        $support = $package->getSupport();
        $url = $support['source'] ?? $package->getSourceUrl();
        if (!$url || $showHomepage) {
            $url = $package->getHomepage();
        }
        if (!$url || !filter_var($url, \FILTER_VALIDATE_URL)) {
            return \false;
        }
        if ($showOnly) {
            $this->getIO()->write(sprintf('<info>%s</info>', $url));
        } else {
            $this->openBrowser($url);
        }
        return \true;
    }
    /**
     * opens a url in your system default browser
     */
    private function openBrowser(string $url): void
    {
        $process = new ProcessExecutor($this->getIO());
        if (Platform::isWindows()) {
            $process->execute(['start', '"web"', 'explorer', $url], $output);
            return;
        }
        $linux = $process->execute(['which', 'xdg-open'], $output);
        $osx = $process->execute(['which', 'open'], $output);
        if (0 === $linux) {
            $process->execute(['xdg-open', $url], $output);
        } elseif (0 === $osx) {
            $process->execute(['open', $url], $output);
        } else {
            $this->getIO()->writeError('No suitable browser opening command found, open yourself: ' . $url);
        }
    }
    /**
     * Initializes repositories
     *
     * Returns an array of repos in order they should be checked in
     *
     * @return RepositoryInterface[]
     */
    private function initializeRepos(): array
    {
        $composer = $this->tryComposer();
        if ($composer) {
            return array_merge(
                [new RootPackageRepository(clone $composer->getPackage())],
                // root package
                [$composer->getRepositoryManager()->getLocalRepository()],
                // installed packages
                $composer->getRepositoryManager()->getRepositories()
            );
        }
        return RepositoryFactory::defaultReposWithDefaultManager($this->getIO());
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer\Command;

use Composer\DependencyResolver\Operation\InstallOperation;
use Composer\DependencyResolver\Operation\UninstallOperation;
use Composer\DependencyResolver\Transaction;
use Composer\Package\AliasPackage;
use Composer\Package\BasePackage;
use Composer\Pcre\Preg;
use Composer\Plugin\CommandEvent;
use Composer\Plugin\PluginEvents;
use Composer\Script\ScriptEvents;
use Composer\Util\Platform;
use _ContaoManager\Symfony\Component\Console\Input\InputInterface;
use Composer\Console\Input\InputOption;
use Composer\Console\Input\InputArgument;
use _ContaoManager\Symfony\Component\Console\Output\OutputInterface;
/**
 * @author Jordi Boggiano <j.boggiano@seld.be>
 */
class ReinstallCommand extends \Composer\Command\BaseCommand
{
    use \Composer\Command\CompletionTrait;
    protected function configure(): void
    {
        $this->setName('reinstall')->setDescription('Uninstalls and reinstalls the given package names')->setDefinition([new InputOption('prefer-source', null, InputOption::VALUE_NONE, 'Forces installation from package sources when possible, including VCS information.'), new InputOption('prefer-dist', null, InputOption::VALUE_NONE, 'Forces installation from package dist (default behavior).'), new InputOption('prefer-install', null, InputOption::VALUE_REQUIRED, 'Forces installation from package dist|source|auto (auto chooses source for dev versions, dist for the rest).', null, $this->suggestPreferInstall()), new InputOption('no-autoloader', null, InputOption::VALUE_NONE, 'Skips autoloader generation'), new InputOption('no-progress', null, InputOption::VALUE_NONE, 'Do not output download progress.'), new InputOption('optimize-autoloader', 'o', InputOption::VALUE_NONE, 'Optimize autoloader during autoloader dump'), new InputOption('classmap-authoritative', 'a', InputOption::VALUE_NONE, 'Autoload classes from the classmap only. Implicitly enables `--optimize-autoloader`.'), new InputOption('apcu-autoloader', null, InputOption::VALUE_NONE, 'Use APCu to cache found/not-found classes.'), new InputOption('apcu-autoloader-prefix', null, InputOption::VALUE_REQUIRED, 'Use a custom prefix for the APCu autoloader cache. Implicitly enables --apcu-autoloader'), new InputOption('ignore-platform-req', null, InputOption::VALUE_REQUIRED | InputOption::VALUE_IS_ARRAY, 'Ignore a specific platform requirement (php & ext- packages).'), new InputOption('ignore-platform-reqs', null, InputOption::VALUE_NONE, 'Ignore all platform requirements (php & ext- packages).'), new InputOption('type', null, InputOption::VALUE_REQUIRED | InputOption::VALUE_IS_ARRAY, 'Filter packages to reinstall by type(s)', null, $this->suggestInstalledPackageTypes(\false)), new InputArgument('packages', InputArgument::IS_ARRAY, 'List of package names to reinstall, can include a wildcard (*) to match any substring.', null, $this->suggestInstalledPackage(\false))])->setHelp(<<<EOT
The <info>reinstall</info> command looks up installed packages by name,
uninstalls them and reinstalls them. This lets you do a clean install
of a package if you messed with its files, or if you wish to change
the installation type using --prefer-install.

<info>php composer.phar reinstall acme/foo "acme/bar-*"</info>

Read more at https://getcomposer.org/doc/03-cli.md#reinstall
EOT
);
    }
    protected function execute(InputInterface $input, OutputInterface $output): int
    {
        $io = $this->getIO();
        $composer = $this->requireComposer();
        $localRepo = $composer->getRepositoryManager()->getLocalRepository();
        $packagesToReinstall = [];
        $packageNamesToReinstall = [];
        if (\count($input->getOption('type')) > 0) {
            if (\count($input->getArgument('packages')) > 0) {
                throw new \InvalidArgumentException('You cannot specify package names and filter by type at the same time.');
            }
            foreach ($localRepo->getCanonicalPackages() as $package) {
                if (in_array($package->getType(), $input->getOption('type'), \true)) {
                    $packagesToReinstall[] = $package;
                    $packageNamesToReinstall[] = $package->getName();
                }
            }
        } else {
            if (\count($input->getArgument('packages')) === 0) {
                throw new \InvalidArgumentException('You must pass one or more package names to be reinstalled.');
            }
            foreach ($input->getArgument('packages') as $pattern) {
                $patternRegexp = BasePackage::packageNameToRegexp($pattern);
                $matched = \false;
                foreach ($localRepo->getCanonicalPackages() as $package) {
                    if (Preg::isMatch($patternRegexp, $package->getName())) {
                        $matched = \true;
                        $packagesToReinstall[] = $package;
                        $packageNamesToReinstall[] = $package->getName();
                    }
                }
                if (!$matched) {
                    $io->writeError('<warning>Pattern "' . $pattern . '" does not match any currently installed packages.</warning>');
                }
            }
        }
        if (0 === \count($packagesToReinstall)) {
            $io->writeError('<warning>Found no packages to reinstall, aborting.</warning>');
            return 1;
        }
        $uninstallOperations = [];
        foreach ($packagesToReinstall as $package) {
            $uninstallOperations[] = new UninstallOperation($package);
        }
        // make sure we have a list of install operations ordered by dependency/plugins
        $presentPackages = $localRepo->getPackages();
        $resultPackages = $presentPackages;
        foreach ($presentPackages as $index => $package) {
            if (in_array($package->getName(), $packageNamesToReinstall, \true)) {
                unset($presentPackages[$index]);
            }
        }
        $transaction = new Transaction($presentPackages, $resultPackages);
        $installOperations = $transaction->getOperations();
        // reverse-sort the uninstalls based on the install order
        $installOrder = [];
        foreach ($installOperations as $index => $op) {
            if ($op instanceof InstallOperation && !$op->getPackage() instanceof AliasPackage) {
                $installOrder[$op->getPackage()->getName()] = $index;
            }
        }
        usort($uninstallOperations, static function ($a, $b) use ($installOrder): int {
            return $installOrder[$b->getPackage()->getName()] - $installOrder[$a->getPackage()->getName()];
        });
        $commandEvent = new CommandEvent(PluginEvents::COMMAND, 'reinstall', $input, $output);
        $eventDispatcher = $composer->getEventDispatcher();
        $eventDispatcher->dispatch($commandEvent->getName(), $commandEvent);
        $config = $composer->getConfig();
        [$preferSource, $preferDist] = $this->getPreferredInstallOptions($config, $input);
        $installationManager = $composer->getInstallationManager();
        $downloadManager = $composer->getDownloadManager();
        $package = $composer->getPackage();
        $installationManager->setOutputProgress(!$input->getOption('no-progress'));
        if ($input->getOption('no-plugins')) {
            $installationManager->disablePlugins();
        }
        $downloadManager->setPreferSource($preferSource);
        $downloadManager->setPreferDist($preferDist);
        $devMode = $localRepo->getDevMode() !== null ? $localRepo->getDevMode() : \true;
        Platform::putEnv('COMPOSER_DEV_MODE', $devMode ? '1' : '0');
        $eventDispatcher->dispatchScript(ScriptEvents::PRE_INSTALL_CMD, $devMode);
        $installationManager->execute($localRepo, $uninstallOperations, $devMode);
        $installationManager->execute($localRepo, $installOperations, $devMode);
        if (!$input->getOption('no-autoloader')) {
            $optimize = $input->getOption('optimize-autoloader') || $config->get('optimize-autoloader');
            $authoritative = $input->getOption('classmap-authoritative') || $config->get('classmap-authoritative');
            $apcuPrefix = $input->getOption('apcu-autoloader-prefix');
            $apcu = $apcuPrefix !== null || $input->getOption('apcu-autoloader') || $config->get('apcu-autoloader');
            $generator = $composer->getAutoloadGenerator();
            $generator->setClassMapAuthoritative($authoritative);
            $generator->setApcu($apcu, $apcuPrefix);
            $generator->setPlatformRequirementFilter($this->getPlatformRequirementFilter($input));
            $generator->dump($config, $localRepo, $package, $installationManager, 'composer', $optimize, null, $composer->getLocker());
        }
        $eventDispatcher->dispatchScript(ScriptEvents::POST_INSTALL_CMD, $devMode);
        return 0;
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer\Command;

use Composer\Config\JsonConfigSource;
use Composer\DependencyResolver\Request;
use Composer\Installer;
use Composer\Pcre\Preg;
use Composer\Plugin\CommandEvent;
use Composer\Plugin\PluginEvents;
use Composer\Json\JsonFile;
use Composer\Factory;
use _ContaoManager\Symfony\Component\Console\Exception\InvalidArgumentException;
use _ContaoManager\Symfony\Component\Console\Input\InputInterface;
use Composer\Console\Input\InputOption;
use Composer\Console\Input\InputArgument;
use _ContaoManager\Symfony\Component\Console\Output\OutputInterface;
use Composer\Package\BasePackage;
use Composer\Advisory\Auditor;
/**
 * @author Pierre du Plessis <pdples@gmail.com>
 * @author Jordi Boggiano <j.boggiano@seld.be>
 */
class RemoveCommand extends \Composer\Command\BaseCommand
{
    use \Composer\Command\CompletionTrait;
    protected function configure(): void
    {
        $this->setName('remove')->setAliases(['rm', 'uninstall'])->setDescription('Removes a package from the require or require-dev')->setDefinition([new InputArgument('packages', InputArgument::IS_ARRAY, 'Packages that should be removed.', null, $this->suggestRootRequirement()), new InputOption('dev', null, InputOption::VALUE_NONE, 'Removes a package from the require-dev section.'), new InputOption('dry-run', null, InputOption::VALUE_NONE, 'Outputs the operations but will not execute anything (implicitly enables --verbose).'), new InputOption('no-progress', null, InputOption::VALUE_NONE, 'Do not output download progress.'), new InputOption('no-update', null, InputOption::VALUE_NONE, 'Disables the automatic update of the dependencies (implies --no-install).'), new InputOption('no-install', null, InputOption::VALUE_NONE, 'Skip the install step after updating the composer.lock file.'), new InputOption('no-audit', null, InputOption::VALUE_NONE, 'Skip the audit step after updating the composer.lock file (can also be set via the COMPOSER_NO_AUDIT=1 env var).'), new InputOption('audit-format', null, InputOption::VALUE_REQUIRED, 'Audit output format. Must be "table", "plain", "json", or "summary".', Auditor::FORMAT_SUMMARY, Auditor::FORMATS), new InputOption('no-security-blocking', null, InputOption::VALUE_NONE, 'Allows installing packages with security advisories or that are abandoned (can also be set via the COMPOSER_NO_SECURITY_BLOCKING=1 env var).'), new InputOption('update-no-dev', null, InputOption::VALUE_NONE, 'Run the dependency update with the --no-dev option.'), new InputOption('update-with-dependencies', 'w', InputOption::VALUE_NONE, 'Allows inherited dependencies to be updated with explicit dependencies (can also be set via the COMPOSER_WITH_DEPENDENCIES=1 env var). (Deprecated, is now default behavior)'), new InputOption('update-with-all-dependencies', 'W', InputOption::VALUE_NONE, 'Allows all inherited dependencies to be updated, including those that are root requirements (can also be set via the COMPOSER_WITH_ALL_DEPENDENCIES=1 env var).'), new InputOption('with-all-dependencies', null, InputOption::VALUE_NONE, 'Alias for --update-with-all-dependencies'), new InputOption('no-update-with-dependencies', null, InputOption::VALUE_NONE, 'Does not allow inherited dependencies to be updated with explicit dependencies.'), new InputOption('minimal-changes', 'm', InputOption::VALUE_NONE, 'During an update with -w/-W, only perform absolutely necessary changes to transitive dependencies (can also be set via the COMPOSER_MINIMAL_CHANGES=1 env var).'), new InputOption('unused', null, InputOption::VALUE_NONE, 'Remove all packages which are locked but not required by any other package.'), new InputOption('ignore-platform-req', null, InputOption::VALUE_REQUIRED | InputOption::VALUE_IS_ARRAY, 'Ignore a specific platform requirement (php & ext- packages).'), new InputOption('ignore-platform-reqs', null, InputOption::VALUE_NONE, 'Ignore all platform requirements (php & ext- packages).'), new InputOption('optimize-autoloader', 'o', InputOption::VALUE_NONE, 'Optimize autoloader during autoloader dump'), new InputOption('classmap-authoritative', 'a', InputOption::VALUE_NONE, 'Autoload classes from the classmap only. Implicitly enables `--optimize-autoloader`.'), new InputOption('apcu-autoloader', null, InputOption::VALUE_NONE, 'Use APCu to cache found/not-found classes.'), new InputOption('apcu-autoloader-prefix', null, InputOption::VALUE_REQUIRED, 'Use a custom prefix for the APCu autoloader cache. Implicitly enables --apcu-autoloader')])->setHelp(<<<EOT
The <info>remove</info> command removes a package from the current
list of installed packages

<info>php composer.phar remove</info>

Read more at https://getcomposer.org/doc/03-cli.md#remove-rm
EOT
);
    }
    /**
     * @throws \Seld\JsonLint\ParsingException
     */
    protected function execute(InputInterface $input, OutputInterface $output): int
    {
        if ($input->getArgument('packages') === [] && !$input->getOption('unused')) {
            throw new InvalidArgumentException('Not enough arguments (missing: "packages").');
        }
        $packages = $input->getArgument('packages');
        $packages = array_map('strtolower', $packages);
        if ($input->getOption('unused')) {
            $composer = $this->requireComposer();
            $locker = $composer->getLocker();
            if (!$locker->isLocked()) {
                throw new \UnexpectedValueException('A valid composer.lock file is required to run this command with --unused');
            }
            $lockedPackages = $locker->getLockedRepository()->getPackages();
            $required = [];
            foreach (array_merge($composer->getPackage()->getRequires(), $composer->getPackage()->getDevRequires()) as $link) {
                $required[$link->getTarget()] = \true;
            }
            do {
                $found = \false;
                foreach ($lockedPackages as $index => $package) {
                    foreach ($package->getNames() as $name) {
                        if (isset($required[$name])) {
                            foreach ($package->getRequires() as $link) {
                                $required[$link->getTarget()] = \true;
                            }
                            $found = \true;
                            unset($lockedPackages[$index]);
                            break;
                        }
                    }
                }
            } while ($found);
            $unused = [];
            foreach ($lockedPackages as $package) {
                $unused[] = $package->getName();
            }
            $packages = array_merge($packages, $unused);
            if (count($packages) === 0) {
                $this->getIO()->writeError('<info>No unused packages to remove</info>');
                return 0;
            }
        }
        $file = Factory::getComposerFile();
        $jsonFile = new JsonFile($file);
        /** @var array{require?: array<string, string>, require-dev?: array<string, string>} $composer */
        $composer = $jsonFile->read();
        $composerBackup = file_get_contents($jsonFile->getPath());
        $json = new JsonConfigSource($jsonFile);
        $type = $input->getOption('dev') ? 'require-dev' : 'require';
        $altType = !$input->getOption('dev') ? 'require-dev' : 'require';
        $io = $this->getIO();
        if ($input->getOption('update-with-dependencies')) {
            $io->writeError('<warning>You are using the deprecated option "update-with-dependencies". This is now default behaviour. The --no-update-with-dependencies option can be used to remove a package without its dependencies.</warning>');
        }
        // make sure name checks are done case insensitively
        foreach (['require', 'require-dev'] as $linkType) {
            if (isset($composer[$linkType])) {
                foreach ($composer[$linkType] as $name => $version) {
                    $composer[$linkType][strtolower($name)] = $name;
                }
            }
        }
        $dryRun = $input->getOption('dry-run');
        $toRemove = [];
        foreach ($packages as $package) {
            if (isset($composer[$type][$package])) {
                if ($dryRun) {
                    $toRemove[$type][] = $composer[$type][$package];
                } else {
                    $json->removeLink($type, $composer[$type][$package]);
                }
            } elseif (isset($composer[$altType][$package])) {
                $io->writeError('<warning>' . $composer[$altType][$package] . ' could not be found in ' . $type . ' but it is present in ' . $altType . '</warning>');
                if ($io->isInteractive()) {
                    if ($io->askConfirmation('Do you want to remove it from ' . $altType . ' [<comment>yes</comment>]? ')) {
                        if ($dryRun) {
                            $toRemove[$altType][] = $composer[$altType][$package];
                        } else {
                            $json->removeLink($altType, $composer[$altType][$package]);
                        }
                    }
                }
            } elseif (isset($composer[$type]) && count($matches = Preg::grep(BasePackage::packageNameToRegexp($package), array_keys($composer[$type]))) > 0) {
                foreach ($matches as $matchedPackage) {
                    if ($dryRun) {
                        $toRemove[$type][] = $matchedPackage;
                    } else {
                        $json->removeLink($type, $matchedPackage);
                    }
                }
            } elseif (isset($composer[$altType]) && count($matches = Preg::grep(BasePackage::packageNameToRegexp($package), array_keys($composer[$altType]))) > 0) {
                foreach ($matches as $matchedPackage) {
                    $io->writeError('<warning>' . $matchedPackage . ' could not be found in ' . $type . ' but it is present in ' . $altType . '</warning>');
                    if ($io->isInteractive()) {
                        if ($io->askConfirmation('Do you want to remove it from ' . $altType . ' [<comment>yes</comment>]? ')) {
                            if ($dryRun) {
                                $toRemove[$altType][] = $matchedPackage;
                            } else {
                                $json->removeLink($altType, $matchedPackage);
                            }
                        }
                    }
                }
            } else {
                $io->writeError('<warning>' . $package . ' is not required in your composer.json and has not been removed</warning>');
            }
        }
        $io->writeError('<info>' . $file . ' has been updated</info>');
        if ($input->getOption('no-update')) {
            return 0;
        }
        if ($composer = $this->tryComposer()) {
            $composer->getPluginManager()->deactivateInstalledPlugins();
        }
        // Update packages
        $this->resetComposer();
        $composer = $this->requireComposer();
        if ($dryRun) {
            $rootPackage = $composer->getPackage();
            $links = ['require' => $rootPackage->getRequires(), 'require-dev' => $rootPackage->getDevRequires()];
            foreach ($toRemove as $type => $names) {
                foreach ($names as $name) {
                    unset($links[$type][$name]);
                }
            }
            $rootPackage->setRequires($links['require']);
            $rootPackage->setDevRequires($links['require-dev']);
        }
        $commandEvent = new CommandEvent(PluginEvents::COMMAND, 'remove', $input, $output);
        $composer->getEventDispatcher()->dispatch($commandEvent->getName(), $commandEvent);
        $allowPlugins = $composer->getConfig()->get('allow-plugins');
        $removedPlugins = is_array($allowPlugins) ? array_intersect(array_keys($allowPlugins), $packages) : [];
        if (!$dryRun && is_array($allowPlugins) && count($removedPlugins) > 0) {
            if (count($allowPlugins) === count($removedPlugins)) {
                $json->removeConfigSetting('allow-plugins');
            } else {
                foreach ($removedPlugins as $plugin) {
                    $json->removeConfigSetting('allow-plugins.' . $plugin);
                }
            }
        }
        $composer->getInstallationManager()->setOutputProgress(!$input->getOption('no-progress'));
        $install = Installer::create($io, $composer);
        $updateDevMode = !$input->getOption('update-no-dev');
        $optimize = $input->getOption('optimize-autoloader') || $composer->getConfig()->get('optimize-autoloader');
        $authoritative = $input->getOption('classmap-authoritative') || $composer->getConfig()->get('classmap-authoritative');
        $apcuPrefix = $input->getOption('apcu-autoloader-prefix');
        $apcu = $apcuPrefix !== null || $input->getOption('apcu-autoloader') || $composer->getConfig()->get('apcu-autoloader');
        $minimalChanges = $input->getOption('minimal-changes') || $composer->getConfig()->get('update-with-minimal-changes');
        $updateAllowTransitiveDependencies = Request::UPDATE_LISTED_WITH_TRANSITIVE_DEPS_NO_ROOT_REQUIRE;
        $flags = '';
        if ($input->getOption('update-with-all-dependencies') || $input->getOption('with-all-dependencies')) {
            $updateAllowTransitiveDependencies = Request::UPDATE_LISTED_WITH_TRANSITIVE_DEPS;
            $flags .= ' --with-all-dependencies';
        } elseif ($input->getOption('no-update-with-dependencies')) {
            $updateAllowTransitiveDependencies = Request::UPDATE_ONLY_LISTED;
            $flags .= ' --with-dependencies';
        }
        $io->writeError('<info>Running composer update ' . implode(' ', $packages) . $flags . '</info>');
        $install->setVerbose($input->getOption('verbose'))->setDevMode($updateDevMode)->setOptimizeAutoloader($optimize)->setClassMapAuthoritative($authoritative)->setApcuAutoloader($apcu, $apcuPrefix)->setUpdate(\true)->setInstall(!$input->getOption('no-install'))->setUpdateAllowTransitiveDependencies($updateAllowTransitiveDependencies)->setPlatformRequirementFilter($this->getPlatformRequirementFilter($input))->setDryRun($dryRun)->setAuditConfig($this->createAuditConfig($composer->getConfig(), $input))->setMinimalUpdate($minimalChanges);
        // if no lock is present, we do not do a partial update as
        // this is not supported by the Installer
        if ($composer->getLocker()->isLocked()) {
            $install->setUpdateAllowList($packages);
        }
        $status = $install->run();
        if ($status !== 0) {
            $io->writeError("\n" . '<error>Removal failed, reverting ' . $file . ' to its original content.</error>');
            file_put_contents($jsonFile->getPath(), $composerBackup);
        }
        if (!$dryRun) {
            foreach ($packages as $package) {
                if ($composer->getRepositoryManager()->getLocalRepository()->findPackages($package)) {
                    $io->writeError('<error>Removal failed, ' . $package . ' is still present, it may be required by another package. See `composer why ' . $package . '`.</error>');
                    return 2;
                }
            }
        }
        return $status;
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer\Command;

use Composer\Composer;
use Composer\DependencyResolver\DefaultPolicy;
use Composer\Filter\PlatformRequirementFilter\PlatformRequirementFilterInterface;
use Composer\IO\IOInterface;
use Composer\Json\JsonFile;
use Composer\Package\BasePackage;
use Composer\Package\CompletePackageInterface;
use Composer\Package\Link;
use Composer\Package\AliasPackage;
use Composer\Package\PackageInterface;
use Composer\Package\Version\VersionParser;
use Composer\Package\Version\VersionSelector;
use Composer\Pcre\Preg;
use Composer\Plugin\CommandEvent;
use Composer\Plugin\PluginEvents;
use Composer\Repository\InstalledArrayRepository;
use Composer\Repository\ComposerRepository;
use Composer\Repository\CompositeRepository;
use Composer\Repository\FilterRepository;
use Composer\Repository\PlatformRepository;
use Composer\Repository\RepositoryFactory;
use Composer\Repository\InstalledRepository;
use Composer\Repository\RepositoryInterface;
use Composer\Repository\RepositorySet;
use Composer\Repository\RepositoryUtils;
use Composer\Repository\RootPackageRepository;
use Composer\Semver\Constraint\ConstraintInterface;
use Composer\Semver\Semver;
use Composer\Spdx\SpdxLicenses;
use Composer\Util\PackageInfo;
use DateTimeInterface;
use _ContaoManager\Symfony\Component\Console\Completion\CompletionInput;
use _ContaoManager\Symfony\Component\Console\Formatter\OutputFormatter;
use _ContaoManager\Symfony\Component\Console\Formatter\OutputFormatterStyle;
use Composer\Console\Input\InputArgument;
use _ContaoManager\Symfony\Component\Console\Input\InputInterface;
use Composer\Console\Input\InputOption;
use _ContaoManager\Symfony\Component\Console\Output\OutputInterface;
/**
 * @author Robert Schönthal <seroscho@googlemail.com>
 * @author Jordi Boggiano <j.boggiano@seld.be>
 * @author Jérémy Romey <jeremyFreeAgent>
 * @author Mihai Plasoianu <mihai@plasoianu.de>
 *
 * @phpstan-import-type AutoloadRules from PackageInterface
 * @phpstan-type JsonStructure array<string, null|string|array<string|null>|AutoloadRules>
 */
class ShowCommand extends \Composer\Command\BaseCommand
{
    use \Composer\Command\CompletionTrait;
    /** @var VersionParser */
    protected $versionParser;
    /** @var string[] */
    protected $colors;
    /** @var ?RepositorySet */
    private $repositorySet;
    protected function configure(): void
    {
        $this->setName('show')->setAliases(['info'])->setDescription('Shows information about packages')->setDefinition([new InputArgument('package', InputArgument::OPTIONAL, 'Package to inspect. Or a name including a wildcard (*) to filter lists of packages instead.', null, $this->suggestPackageBasedOnMode()), new InputArgument('version', InputArgument::OPTIONAL, 'Version or version constraint to inspect'), new InputOption('all', null, InputOption::VALUE_NONE, 'List all packages'), new InputOption('locked', null, InputOption::VALUE_NONE, 'List all locked packages'), new InputOption('installed', 'i', InputOption::VALUE_NONE, 'List installed packages only (enabled by default, only present for BC).'), new InputOption('platform', 'p', InputOption::VALUE_NONE, 'List platform packages only'), new InputOption('available', 'a', InputOption::VALUE_NONE, 'List available packages only'), new InputOption('self', 's', InputOption::VALUE_NONE, 'Show the root package information'), new InputOption('name-only', 'N', InputOption::VALUE_NONE, 'List package names only'), new InputOption('path', 'P', InputOption::VALUE_NONE, 'Show package paths'), new InputOption('tree', 't', InputOption::VALUE_NONE, 'List the dependencies as a tree'), new InputOption('latest', 'l', InputOption::VALUE_NONE, 'Show the latest version'), new InputOption('outdated', 'o', InputOption::VALUE_NONE, 'Show the latest version but only for packages that are outdated'), new InputOption('ignore', null, InputOption::VALUE_REQUIRED | InputOption::VALUE_IS_ARRAY, 'Ignore specified package(s). Can contain wildcards (*). Use it with the --outdated option if you don\'t want to be informed about new versions of some packages.', null, $this->suggestInstalledPackage(\false)), new InputOption('major-only', 'M', InputOption::VALUE_NONE, 'Show only packages that have major SemVer-compatible updates. Use with the --latest or --outdated option.'), new InputOption('minor-only', 'm', InputOption::VALUE_NONE, 'Show only packages that have minor SemVer-compatible updates. Use with the --latest or --outdated option.'), new InputOption('patch-only', null, InputOption::VALUE_NONE, 'Show only packages that have patch SemVer-compatible updates. Use with the --latest or --outdated option.'), new InputOption('sort-by-age', 'A', InputOption::VALUE_NONE, 'Displays the installed version\'s age, and sorts packages oldest first. Use with the --latest or --outdated option.'), new InputOption('direct', 'D', InputOption::VALUE_NONE, 'Shows only packages that are directly required by the root package'), new InputOption('strict', null, InputOption::VALUE_NONE, 'Return a non-zero exit code when there are outdated packages'), new InputOption('format', 'f', InputOption::VALUE_REQUIRED, 'Format of the output: text or json', 'text', ['json', 'text']), new InputOption('no-dev', null, InputOption::VALUE_NONE, 'Disables search in require-dev packages.'), new InputOption('ignore-platform-req', null, InputOption::VALUE_REQUIRED | InputOption::VALUE_IS_ARRAY, 'Ignore a specific platform requirement (php & ext- packages). Use with the --outdated option'), new InputOption('ignore-platform-reqs', null, InputOption::VALUE_NONE, 'Ignore all platform requirements (php & ext- packages). Use with the --outdated option')])->setHelp(<<<EOT
The show command displays detailed information about a package, or
lists all packages available.

Read more at https://getcomposer.org/doc/03-cli.md#show-info
EOT
);
    }
    protected function suggestPackageBasedOnMode(): \Closure
    {
        return function (CompletionInput $input) {
            if ($input->getOption('available') || $input->getOption('all')) {
                return $this->suggestAvailablePackageInclPlatform()($input);
            }
            if ($input->getOption('platform')) {
                return $this->suggestPlatformPackage()($input);
            }
            return $this->suggestInstalledPackage(\false)($input);
        };
    }
    protected function execute(InputInterface $input, OutputInterface $output): int
    {
        $this->versionParser = new VersionParser();
        if ($input->getOption('tree')) {
            $this->initStyles($output);
        }
        $composer = $this->tryComposer();
        $io = $this->getIO();
        if ($input->getOption('installed') && !$input->getOption('self')) {
            $io->writeError('<warning>You are using the deprecated option "installed". Only installed packages are shown by default now. The --all option can be used to show all packages.</warning>');
        }
        if ($input->getOption('outdated')) {
            $input->setOption('latest', \true);
        } elseif (count($input->getOption('ignore')) > 0) {
            $io->writeError('<warning>You are using the option "ignore" for action other than "outdated", it will be ignored.</warning>');
        }
        if ($input->getOption('direct') && ($input->getOption('all') || $input->getOption('available') || $input->getOption('platform'))) {
            $io->writeError('The --direct (-D) option is not usable in combination with --all, --platform (-p) or --available (-a)');
            return 1;
        }
        if ($input->getOption('tree') && ($input->getOption('all') || $input->getOption('available'))) {
            $io->writeError('The --tree (-t) option is not usable in combination with --all or --available (-a)');
            return 1;
        }
        if (count(array_filter([$input->getOption('patch-only'), $input->getOption('minor-only'), $input->getOption('major-only')])) > 1) {
            $io->writeError('Only one of --major-only, --minor-only or --patch-only can be used at once');
            return 1;
        }
        if ($input->getOption('tree') && $input->getOption('latest')) {
            $io->writeError('The --tree (-t) option is not usable in combination with --latest (-l)');
            return 1;
        }
        if ($input->getOption('tree') && $input->getOption('path')) {
            $io->writeError('The --tree (-t) option is not usable in combination with --path (-P)');
            return 1;
        }
        $format = $input->getOption('format');
        if (!in_array($format, ['text', 'json'])) {
            $io->writeError(sprintf('Unsupported format "%s". See help for supported formats.', $format));
            return 1;
        }
        $platformReqFilter = $this->getPlatformRequirementFilter($input);
        // init repos
        $platformOverrides = [];
        if ($composer) {
            $platformOverrides = $composer->getConfig()->get('platform');
        }
        $platformRepo = new PlatformRepository([], $platformOverrides);
        $lockedRepo = null;
        if ($input->getOption('self') && !$input->getOption('installed') && !$input->getOption('locked')) {
            $package = clone $this->requireComposer()->getPackage();
            if ($input->getOption('name-only')) {
                $io->write($package->getName());
                return 0;
            }
            if ($input->getArgument('package')) {
                throw new \InvalidArgumentException('You cannot use --self together with a package name');
            }
            $repos = $installedRepo = new InstalledRepository([new RootPackageRepository($package)]);
        } elseif ($input->getOption('platform')) {
            $repos = $installedRepo = new InstalledRepository([$platformRepo]);
        } elseif ($input->getOption('available')) {
            $installedRepo = new InstalledRepository([$platformRepo]);
            if ($composer) {
                $repos = new CompositeRepository($composer->getRepositoryManager()->getRepositories());
                $installedRepo->addRepository($composer->getRepositoryManager()->getLocalRepository());
            } else {
                $defaultRepos = RepositoryFactory::defaultReposWithDefaultManager($io);
                $repos = new CompositeRepository($defaultRepos);
                $io->writeError('No composer.json found in the current directory, showing available packages from ' . implode(', ', array_keys($defaultRepos)));
            }
        } elseif ($input->getOption('all') && $composer) {
            $localRepo = $composer->getRepositoryManager()->getLocalRepository();
            $locker = $composer->getLocker();
            if ($locker->isLocked()) {
                $lockedRepo = $locker->getLockedRepository(\true);
                $installedRepo = new InstalledRepository([$lockedRepo, $localRepo, $platformRepo]);
            } else {
                $installedRepo = new InstalledRepository([$localRepo, $platformRepo]);
            }
            $repos = new CompositeRepository(array_merge([new FilterRepository($installedRepo, ['canonical' => \false])], $composer->getRepositoryManager()->getRepositories()));
        } elseif ($input->getOption('all')) {
            $defaultRepos = RepositoryFactory::defaultReposWithDefaultManager($io);
            $io->writeError('No composer.json found in the current directory, showing available packages from ' . implode(', ', array_keys($defaultRepos)));
            $installedRepo = new InstalledRepository([$platformRepo]);
            $repos = new CompositeRepository(array_merge([$installedRepo], $defaultRepos));
        } elseif ($input->getOption('locked')) {
            if (!$composer || !$composer->getLocker()->isLocked()) {
                throw new \UnexpectedValueException('A valid composer.json and composer.lock files is required to run this command with --locked');
            }
            $locker = $composer->getLocker();
            $lockedRepo = $locker->getLockedRepository(!$input->getOption('no-dev'));
            if ($input->getOption('self')) {
                $lockedRepo->addPackage(clone $composer->getPackage());
            }
            $repos = $installedRepo = new InstalledRepository([$lockedRepo]);
        } else {
            // --installed / default case
            if (!$composer) {
                $composer = $this->requireComposer();
            }
            $rootPkg = $composer->getPackage();
            $rootRepo = new InstalledArrayRepository();
            if ($input->getOption('self')) {
                $rootRepo = new RootPackageRepository(clone $rootPkg);
            }
            if ($input->getOption('no-dev')) {
                $packages = RepositoryUtils::filterRequiredPackages($composer->getRepositoryManager()->getLocalRepository()->getPackages(), $rootPkg);
                $repos = $installedRepo = new InstalledRepository([$rootRepo, new InstalledArrayRepository(array_map(static function ($pkg): PackageInterface {
                    return clone $pkg;
                }, $packages))]);
            } else {
                $repos = $installedRepo = new InstalledRepository([$rootRepo, $composer->getRepositoryManager()->getLocalRepository()]);
            }
            if (!$installedRepo->getPackages()) {
                $hasNonPlatformReqs = static function (array $reqs): bool {
                    return (bool) array_filter(array_keys($reqs), static function (string $name) {
                        return !PlatformRepository::isPlatformPackage($name);
                    });
                };
                if ($hasNonPlatformReqs($rootPkg->getRequires()) || $hasNonPlatformReqs($rootPkg->getDevRequires())) {
                    $io->writeError('<warning>No dependencies installed. Try running composer install or update.</warning>');
                }
            }
        }
        if ($composer) {
            $commandEvent = new CommandEvent(PluginEvents::COMMAND, 'show', $input, $output);
            $composer->getEventDispatcher()->dispatch($commandEvent->getName(), $commandEvent);
        }
        if ($input->getOption('latest') && null === $composer) {
            $io->writeError('No composer.json found in the current directory, disabling "latest" option');
            $input->setOption('latest', \false);
        }
        $packageFilter = $input->getArgument('package');
        // show single package or single version
        if (isset($package)) {
            $versions = [$package->getPrettyVersion() => $package->getVersion()];
        } elseif (null !== $packageFilter && !str_contains($packageFilter, '*')) {
            [$package, $versions] = $this->getPackage($installedRepo, $repos, $packageFilter, $input->getArgument('version'));
            if (isset($package) && $input->getOption('direct')) {
                if (!in_array($package->getName(), $this->getRootRequires(), \true)) {
                    throw new \InvalidArgumentException('Package "' . $package->getName() . '" is installed but not a direct dependent of the root package.');
                }
            }
            if (!isset($package)) {
                $options = $input->getOptions();
                $hint = '';
                if ($input->getOption('locked')) {
                    $hint .= ' in lock file';
                }
                if (isset($options['working-dir'])) {
                    $hint .= ' in ' . $options['working-dir'] . '/composer.json';
                }
                if (PlatformRepository::isPlatformPackage($packageFilter) && !$input->getOption('platform')) {
                    $hint .= ', try using --platform (-p) to show platform packages';
                }
                if (!$input->getOption('all') && !$input->getOption('available')) {
                    $hint .= ', try using --available (-a) to show all available packages';
                }
                throw new \InvalidArgumentException('Package "' . $packageFilter . '" not found' . $hint . '.');
            }
        }
        if (isset($package)) {
            assert(isset($versions));
            $exitCode = 0;
            if ($input->getOption('tree')) {
                $arrayTree = $this->generatePackageTree($package, $installedRepo, $repos);
                if ('json' === $format) {
                    $io->write(JsonFile::encode(['installed' => [$arrayTree]]));
                } else {
                    $this->displayPackageTree([$arrayTree]);
                }
                return $exitCode;
            }
            $latestPackage = null;
            if ($input->getOption('latest')) {
                $latestPackage = $this->findLatestPackage($package, $composer, $platformRepo, $input->getOption('major-only'), $input->getOption('minor-only'), $input->getOption('patch-only'), $platformReqFilter);
            }
            if ($input->getOption('outdated') && $input->getOption('strict') && null !== $latestPackage && $latestPackage->getFullPrettyVersion() !== $package->getFullPrettyVersion() && (!$latestPackage instanceof CompletePackageInterface || !$latestPackage->isAbandoned())) {
                $exitCode = 1;
            }
            if ($input->getOption('path')) {
                $io->write($package->getName(), \false);
                $path = $composer->getInstallationManager()->getInstallPath($package);
                if (is_string($path)) {
                    $io->write(' ' . strtok(realpath($path), "\r\n"));
                } else {
                    $io->write(' null');
                }
                return $exitCode;
            }
            if ('json' === $format) {
                $this->printPackageInfoAsJson($package, $versions, $installedRepo, $latestPackage ?: null);
            } else {
                $this->printPackageInfo($package, $versions, $installedRepo, $latestPackage ?: null);
            }
            return $exitCode;
        }
        // show tree view if requested
        if ($input->getOption('tree')) {
            $rootRequires = $this->getRootRequires();
            $packages = $installedRepo->getPackages();
            usort($packages, static function (BasePackage $a, BasePackage $b): int {
                return strcmp((string) $a, (string) $b);
            });
            $arrayTree = [];
            foreach ($packages as $package) {
                if (in_array($package->getName(), $rootRequires, \true)) {
                    $arrayTree[] = $this->generatePackageTree($package, $installedRepo, $repos);
                }
            }
            if ('json' === $format) {
                $io->write(JsonFile::encode(['installed' => $arrayTree]));
            } else {
                $this->displayPackageTree($arrayTree);
            }
            return 0;
        }
        // list packages
        /** @var array<string, array<string, string|CompletePackageInterface>> $packages */
        $packages = [];
        $packageFilterRegex = null;
        if (null !== $packageFilter) {
            $packageFilterRegex = '{^' . str_replace('\*', '.*?', preg_quote($packageFilter)) . '$}i';
        }
        $packageListFilter = null;
        if ($input->getOption('direct')) {
            $packageListFilter = $this->getRootRequires();
        }
        if ($input->getOption('path') && null === $composer) {
            $io->writeError('No composer.json found in the current directory, disabling "path" option');
            $input->setOption('path', \false);
        }
        foreach (RepositoryUtils::flattenRepositories($repos) as $repo) {
            if ($repo === $platformRepo) {
                $type = 'platform';
            } elseif ($lockedRepo !== null && $repo === $lockedRepo) {
                $type = 'locked';
            } elseif ($repo === $installedRepo || in_array($repo, $installedRepo->getRepositories(), \true)) {
                $type = 'installed';
            } else {
                $type = 'available';
            }
            if ($repo instanceof ComposerRepository) {
                foreach ($repo->getPackageNames($packageFilter) as $name) {
                    $packages[$type][$name] = $name;
                }
            } else {
                foreach ($repo->getPackages() as $package) {
                    if (!isset($packages[$type][$package->getName()]) || !is_object($packages[$type][$package->getName()]) || version_compare($packages[$type][$package->getName()]->getVersion(), $package->getVersion(), '<')) {
                        while ($package instanceof AliasPackage) {
                            $package = $package->getAliasOf();
                        }
                        if (!$packageFilterRegex || Preg::isMatch($packageFilterRegex, $package->getName())) {
                            if (null === $packageListFilter || in_array($package->getName(), $packageListFilter, \true)) {
                                $packages[$type][$package->getName()] = $package;
                            }
                        }
                    }
                }
                if ($repo === $platformRepo) {
                    foreach ($platformRepo->getDisabledPackages() as $name => $package) {
                        $packages[$type][$name] = $package;
                    }
                }
            }
        }
        $showAllTypes = $input->getOption('all');
        $showLatest = $input->getOption('latest');
        $showMajorOnly = $input->getOption('major-only');
        $showMinorOnly = $input->getOption('minor-only');
        $showPatchOnly = $input->getOption('patch-only');
        $ignoredPackagesRegex = BasePackage::packageNamesToRegexp(array_map('strtolower', $input->getOption('ignore')));
        $indent = $showAllTypes ? '  ' : '';
        /** @var PackageInterface[] $latestPackages */
        $latestPackages = [];
        $exitCode = 0;
        $viewData = [];
        $viewMetaData = [];
        $writeVersion = \false;
        $writeDescription = \false;
        foreach (['platform' => \true, 'locked' => \true, 'available' => \false, 'installed' => \true] as $type => $showVersion) {
            if (isset($packages[$type])) {
                ksort($packages[$type]);
                $nameLength = $versionLength = $latestLength = $releaseDateLength = 0;
                if ($showLatest && $showVersion) {
                    foreach ($packages[$type] as $package) {
                        if (is_object($package) && !Preg::isMatch($ignoredPackagesRegex, $package->getPrettyName())) {
                            $latestPackage = $this->findLatestPackage($package, $composer, $platformRepo, $showMajorOnly, $showMinorOnly, $showPatchOnly, $platformReqFilter);
                            if ($latestPackage === null) {
                                continue;
                            }
                            $latestPackages[$package->getPrettyName()] = $latestPackage;
                        }
                    }
                }
                $writePath = !$input->getOption('name-only') && $input->getOption('path');
                $writeVersion = !$input->getOption('name-only') && !$input->getOption('path') && $showVersion;
                $writeLatest = $writeVersion && $showLatest;
                $writeDescription = !$input->getOption('name-only') && !$input->getOption('path');
                $writeReleaseDate = $writeLatest && ($input->getOption('sort-by-age') || $format === 'json');
                $hasOutdatedPackages = \false;
                if ($input->getOption('sort-by-age')) {
                    usort($packages[$type], static function ($a, $b) {
                        if (is_object($a) && is_object($b)) {
                            return $a->getReleaseDate() <=> $b->getReleaseDate();
                        }
                        return 0;
                    });
                }
                $viewData[$type] = [];
                foreach ($packages[$type] as $package) {
                    $packageViewData = [];
                    if (is_object($package)) {
                        $latestPackage = null;
                        if ($showLatest && isset($latestPackages[$package->getPrettyName()])) {
                            $latestPackage = $latestPackages[$package->getPrettyName()];
                        }
                        // Determine if Composer is checking outdated dependencies and if current package should trigger non-default exit code
                        $packageIsUpToDate = $latestPackage && $latestPackage->getFullPrettyVersion() === $package->getFullPrettyVersion() && (!$latestPackage instanceof CompletePackageInterface || !$latestPackage->isAbandoned());
                        // When using --major-only, and no bigger version than current major is found then it is considered up to date
                        $packageIsUpToDate = $packageIsUpToDate || $latestPackage === null && $showMajorOnly;
                        $packageIsIgnored = Preg::isMatch($ignoredPackagesRegex, $package->getPrettyName());
                        if ($input->getOption('outdated') && ($packageIsUpToDate || $packageIsIgnored)) {
                            continue;
                        }
                        if ($input->getOption('outdated') || $input->getOption('strict')) {
                            $hasOutdatedPackages = \true;
                        }
                        $packageViewData['name'] = $package->getPrettyName();
                        $packageViewData['direct-dependency'] = in_array($package->getName(), $this->getRootRequires(), \true);
                        if ($format !== 'json' || \true !== $input->getOption('name-only')) {
                            $packageViewData['homepage'] = $package instanceof CompletePackageInterface ? $package->getHomepage() : null;
                            $packageViewData['source'] = PackageInfo::getViewSourceUrl($package);
                        }
                        $nameLength = max($nameLength, strlen($packageViewData['name']));
                        if ($writeVersion) {
                            $packageViewData['version'] = $package->getFullPrettyVersion();
                            if ($format === 'text') {
                                $packageViewData['version'] = ltrim($packageViewData['version'], 'v');
                            }
                            $versionLength = max($versionLength, strlen($packageViewData['version']));
                        }
                        if ($writeReleaseDate) {
                            if ($package->getReleaseDate() !== null) {
                                $packageViewData['release-age'] = str_replace(' ago', ' old', $this->getRelativeTime($package->getReleaseDate()));
                                if (!str_contains($packageViewData['release-age'], ' old')) {
                                    $packageViewData['release-age'] = 'from ' . $packageViewData['release-age'];
                                }
                                $releaseDateLength = max($releaseDateLength, strlen($packageViewData['release-age']));
                                $packageViewData['release-date'] = $package->getReleaseDate()->format(DateTimeInterface::ATOM);
                            } else {
                                $packageViewData['release-age'] = '';
                                $packageViewData['release-date'] = '';
                            }
                        }
                        if ($writeLatest && $latestPackage) {
                            $packageViewData['latest'] = $latestPackage->getFullPrettyVersion();
                            if ($format === 'text') {
                                $packageViewData['latest'] = ltrim($packageViewData['latest'], 'v');
                            }
                            $packageViewData['latest-status'] = $this->getUpdateStatus($latestPackage, $package);
                            $latestLength = max($latestLength, strlen($packageViewData['latest']));
                            if ($latestPackage->getReleaseDate() !== null) {
                                $packageViewData['latest-release-date'] = $latestPackage->getReleaseDate()->format(DateTimeInterface::ATOM);
                            } else {
                                $packageViewData['latest-release-date'] = '';
                            }
                        } elseif ($writeLatest) {
                            $packageViewData['latest'] = '[none matched]';
                            $packageViewData['latest-status'] = 'up-to-date';
                            $latestLength = max($latestLength, strlen($packageViewData['latest']));
                        }
                        if ($writeDescription && $package instanceof CompletePackageInterface) {
                            $packageViewData['description'] = $package->getDescription();
                        }
                        if ($writePath) {
                            $path = $composer->getInstallationManager()->getInstallPath($package);
                            if (is_string($path)) {
                                $packageViewData['path'] = strtok(realpath($path), "\r\n");
                            } else {
                                $packageViewData['path'] = null;
                            }
                        }
                        $packageIsAbandoned = \false;
                        if ($latestPackage instanceof CompletePackageInterface && $latestPackage->isAbandoned()) {
                            $replacementPackageName = $latestPackage->getReplacementPackage();
                            $replacement = $replacementPackageName !== null ? 'Use ' . $latestPackage->getReplacementPackage() . ' instead' : 'No replacement was suggested';
                            $packageWarning = sprintf('Package %s is abandoned, you should avoid using it. %s.', $package->getPrettyName(), $replacement);
                            $packageViewData['warning'] = $packageWarning;
                            $packageIsAbandoned = $replacementPackageName ?? \true;
                        }
                        $packageViewData['abandoned'] = $packageIsAbandoned;
                    } else {
                        $packageViewData['name'] = $package;
                        $nameLength = max($nameLength, strlen($package));
                    }
                    $viewData[$type][] = $packageViewData;
                }
                $viewMetaData[$type] = ['nameLength' => $nameLength, 'versionLength' => $versionLength, 'latestLength' => $latestLength, 'releaseDateLength' => $releaseDateLength, 'writeLatest' => $writeLatest, 'writeReleaseDate' => $writeReleaseDate];
                if ($input->getOption('strict') && $hasOutdatedPackages) {
                    $exitCode = 1;
                    break;
                }
            }
        }
        if ('json' === $format) {
            $io->write(JsonFile::encode($viewData));
        } else {
            if ($input->getOption('latest') && array_filter($viewData)) {
                if (!$io->isDecorated()) {
                    $io->writeError('Legend:');
                    $io->writeError('! patch or minor release available - update recommended');
                    $io->writeError('~ major release available - update possible');
                    if (!$input->getOption('outdated')) {
                        $io->writeError('= up to date version');
                    }
                } else {
                    $io->writeError('<info>Color legend:</info>');
                    $io->writeError('- <highlight>patch or minor</highlight> release available - update recommended');
                    $io->writeError('- <comment>major</comment> release available - update possible');
                    if (!$input->getOption('outdated')) {
                        $io->writeError('- <info>up to date</info> version');
                    }
                }
            }
            $width = $this->getTerminalWidth();
            foreach ($viewData as $type => $packages) {
                $nameLength = $viewMetaData[$type]['nameLength'];
                $versionLength = $viewMetaData[$type]['versionLength'];
                $latestLength = $viewMetaData[$type]['latestLength'];
                $releaseDateLength = $viewMetaData[$type]['releaseDateLength'];
                $writeLatest = $viewMetaData[$type]['writeLatest'];
                $writeReleaseDate = $viewMetaData[$type]['writeReleaseDate'];
                $versionFits = $nameLength + $versionLength + 3 <= $width;
                $latestFits = $nameLength + $versionLength + $latestLength + 3 <= $width;
                $releaseDateFits = $nameLength + $versionLength + $latestLength + $releaseDateLength + 3 <= $width;
                $descriptionFits = $nameLength + $versionLength + $latestLength + $releaseDateLength + 24 <= $width;
                if ($latestFits && !$io->isDecorated()) {
                    $latestLength += 2;
                }
                if ($showAllTypes) {
                    if ('available' === $type) {
                        $io->write('<comment>' . $type . '</comment>:');
                    } else {
                        $io->write('<info>' . $type . '</info>:');
                    }
                }
                if ($writeLatest && !$input->getOption('direct')) {
                    $directDeps = [];
                    $transitiveDeps = [];
                    foreach ($packages as $pkg) {
                        if ($pkg['direct-dependency'] ?? \false) {
                            $directDeps[] = $pkg;
                        } else {
                            $transitiveDeps[] = $pkg;
                        }
                    }
                    $io->writeError('');
                    $io->writeError('<info>Direct dependencies required in composer.json:</>');
                    if (\count($directDeps) > 0) {
                        $this->printPackages($io, $directDeps, $indent, $writeVersion && $versionFits, $latestFits, $writeDescription && $descriptionFits, $width, $versionLength, $nameLength, $latestLength, $writeReleaseDate && $releaseDateFits, $releaseDateLength);
                    } else {
                        $io->writeError('Everything up to date');
                    }
                    $io->writeError('');
                    $io->writeError('<info>Transitive dependencies not required in composer.json:</>');
                    if (\count($transitiveDeps) > 0) {
                        $this->printPackages($io, $transitiveDeps, $indent, $writeVersion && $versionFits, $latestFits, $writeDescription && $descriptionFits, $width, $versionLength, $nameLength, $latestLength, $writeReleaseDate && $releaseDateFits, $releaseDateLength);
                    } else {
                        $io->writeError('Everything up to date');
                    }
                } else if ($writeLatest && \count($packages) === 0) {
                    $io->writeError('All your direct dependencies are up to date');
                } else {
                    $this->printPackages($io, $packages, $indent, $writeVersion && $versionFits, $writeLatest && $latestFits, $writeDescription && $descriptionFits, $width, $versionLength, $nameLength, $latestLength, $writeReleaseDate && $releaseDateFits, $releaseDateLength);
                }
                if ($showAllTypes) {
                    $io->write('');
                }
            }
        }
        return $exitCode;
    }
    /**
     * @param array<array{name: string, direct-dependency?: bool, version?: string, latest?: string, latest-status?: string, description?: string|null, path?: string|null, source?: string|null, homepage?: string|null, warning?: string, abandoned?: bool|string}> $packages
     */
    private function printPackages(IOInterface $io, array $packages, string $indent, bool $writeVersion, bool $writeLatest, bool $writeDescription, int $width, int $versionLength, int $nameLength, int $latestLength, bool $writeReleaseDate, int $releaseDateLength): void
    {
        $padName = $writeVersion || $writeLatest || $writeReleaseDate || $writeDescription;
        $padVersion = $writeLatest || $writeReleaseDate || $writeDescription;
        $padLatest = $writeDescription || $writeReleaseDate;
        $padReleaseDate = $writeDescription;
        foreach ($packages as $package) {
            $link = $package['source'] ?? $package['homepage'] ?? '';
            if ($link !== '') {
                $io->write($indent . '<href=' . OutputFormatter::escape($link) . '>' . $package['name'] . '</>' . str_repeat(' ', $padName ? $nameLength - strlen($package['name']) : 0), \false);
            } else {
                $io->write($indent . str_pad($package['name'], $padName ? $nameLength : 0, ' '), \false);
            }
            if (isset($package['version']) && $writeVersion) {
                $io->write(' ' . str_pad($package['version'], $padVersion ? $versionLength : 0, ' '), \false);
            }
            if (isset($package['latest']) && isset($package['latest-status']) && $writeLatest) {
                $latestVersion = $package['latest'];
                $updateStatus = $package['latest-status'];
                $style = $this->updateStatusToVersionStyle($updateStatus);
                if (!$io->isDecorated()) {
                    $latestVersion = str_replace(['up-to-date', 'semver-safe-update', 'update-possible'], ['=', '!', '~'], $updateStatus) . ' ' . $latestVersion;
                }
                $io->write(' <' . $style . '>' . str_pad($latestVersion, $padLatest ? $latestLength : 0, ' ') . '</' . $style . '>', \false);
                if ($writeReleaseDate && isset($package['release-age'])) {
                    $io->write(' ' . str_pad($package['release-age'], $padReleaseDate ? $releaseDateLength : 0, ' '), \false);
                }
            }
            if (isset($package['description']) && $writeDescription) {
                $description = (string) strtok($package['description'], "\r\n");
                // Compute remaining width available for the description.
                $remaining = $width - $nameLength - $versionLength - $releaseDateLength - 4;
                if ($writeLatest) {
                    $remaining -= $latestLength;
                }
                // If nothing fits, clear the description.
                if ($remaining <= 0) {
                    $description = '';
                } elseif (extension_loaded('mbstring')) {
                    // Use mb_strwidth/mb_strimwidth to measure and trim by display width
                    // (CJK characters count as width 2). mb_strimwidth counts the trim
                    // marker ('...') in the width parameter, so pass $remaining directly.
                    if (mb_strwidth($description, 'UTF-8') > $remaining) {
                        $description = mb_strimwidth($description, 0, $remaining, '...', 'UTF-8');
                    }
                } else {
                    // Fallback when mbstring is not available: do a conservative byte-based cut.
                    // Ensure cut length is non-negative and leave room for the ellipsis.
                    $cut = max(0, $remaining - 3);
                    if (strlen($description) > $cut) {
                        $description = substr($description, 0, $cut) . '...';
                    }
                }
                $io->write(' ' . $description, \false);
            }
            if (array_key_exists('path', $package)) {
                $io->write(' ' . (is_string($package['path']) ? $package['path'] : 'null'), \false);
            }
            $io->write('');
            if (isset($package['warning'])) {
                $io->write('<warning>' . $package['warning'] . '</warning>');
            }
        }
    }
    /**
     * @return string[]
     */
    protected function getRootRequires(): array
    {
        $composer = $this->tryComposer();
        if ($composer === null) {
            return [];
        }
        $rootPackage = $composer->getPackage();
        return array_map('strtolower', array_keys(array_merge($rootPackage->getRequires(), $rootPackage->getDevRequires())));
    }
    /**
     * @return array|string|string[]
     */
    protected function getVersionStyle(PackageInterface $latestPackage, PackageInterface $package)
    {
        return $this->updateStatusToVersionStyle($this->getUpdateStatus($latestPackage, $package));
    }
    /**
     * finds a package by name and version if provided
     *
     * @param  ConstraintInterface|string $version
     * @throws \InvalidArgumentException
     * @return array{CompletePackageInterface|null, array<string, string>}
     */
    protected function getPackage(InstalledRepository $installedRepo, RepositoryInterface $repos, string $name, $version = null): array
    {
        $name = strtolower($name);
        $constraint = is_string($version) ? $this->versionParser->parseConstraints($version) : $version;
        $policy = new DefaultPolicy();
        $repositorySet = new RepositorySet('dev');
        $repositorySet->allowInstalledRepositories();
        $repositorySet->addRepository($repos);
        $matchedPackage = null;
        $versions = [];
        if (PlatformRepository::isPlatformPackage($name)) {
            $pool = $repositorySet->createPoolWithAllPackages();
        } else {
            $pool = $repositorySet->createPoolForPackage($name);
        }
        $matches = $pool->whatProvides($name, $constraint);
        $literals = [];
        foreach ($matches as $package) {
            // avoid showing the 9999999-dev alias if the default branch has no branch-alias set
            if ($package instanceof AliasPackage && $package->getVersion() === VersionParser::DEFAULT_BRANCH_ALIAS) {
                $package = $package->getAliasOf();
            }
            // select an exact match if it is in the installed repo and no specific version was required
            if (null === $version && $installedRepo->hasPackage($package)) {
                $matchedPackage = $package;
            }
            $versions[$package->getPrettyVersion()] = $package->getVersion();
            $literals[] = $package->getId();
        }
        // select preferred package according to policy rules
        if (null === $matchedPackage && \count($literals) > 0) {
            $preferred = $policy->selectPreferredPackages($pool, $literals);
            $matchedPackage = $pool->literalToPackage($preferred[0]);
        }
        if ($matchedPackage !== null && !$matchedPackage instanceof CompletePackageInterface) {
            throw new \LogicException('ShowCommand::getPackage can only work with CompletePackageInterface, but got ' . get_class($matchedPackage));
        }
        return [$matchedPackage, $versions];
    }
    /**
     * Prints package info.
     *
     * @param array<string, string>    $versions
     */
    protected function printPackageInfo(CompletePackageInterface $package, array $versions, InstalledRepository $installedRepo, ?PackageInterface $latestPackage = null): void
    {
        $io = $this->getIO();
        $this->printMeta($package, $versions, $installedRepo, $latestPackage ?: null);
        $this->printLinks($package, Link::TYPE_REQUIRE);
        $this->printLinks($package, Link::TYPE_DEV_REQUIRE, 'requires (dev)');
        if ($package->getSuggests()) {
            $io->write("\n<info>suggests</info>");
            foreach ($package->getSuggests() as $suggested => $reason) {
                $io->write($suggested . ' <comment>' . $reason . '</comment>');
            }
        }
        $this->printLinks($package, Link::TYPE_PROVIDE);
        $this->printLinks($package, Link::TYPE_CONFLICT);
        $this->printLinks($package, Link::TYPE_REPLACE);
    }
    /**
     * Prints package metadata.
     *
     * @param array<string, string>    $versions
     */
    protected function printMeta(CompletePackageInterface $package, array $versions, InstalledRepository $installedRepo, ?PackageInterface $latestPackage = null): void
    {
        $isInstalledPackage = !PlatformRepository::isPlatformPackage($package->getName()) && $installedRepo->hasPackage($package);
        $io = $this->getIO();
        $io->write('<info>name</info>     : ' . $package->getPrettyName());
        $io->write('<info>descrip.</info> : ' . $package->getDescription());
        $io->write('<info>keywords</info> : ' . implode(', ', $package->getKeywords() ?: []));
        $this->printVersions($package, $versions, $installedRepo);
        if ($isInstalledPackage && $package->getReleaseDate() !== null) {
            $io->write('<info>released</info> : ' . $package->getReleaseDate()->format('Y-m-d') . ', ' . $this->getRelativeTime($package->getReleaseDate()));
        }
        if ($latestPackage) {
            $style = $this->getVersionStyle($latestPackage, $package);
            $releasedTime = $latestPackage->getReleaseDate() === null ? '' : ' released ' . $latestPackage->getReleaseDate()->format('Y-m-d') . ', ' . $this->getRelativeTime($latestPackage->getReleaseDate());
            $io->write('<info>latest</info>   : <' . $style . '>' . $latestPackage->getPrettyVersion() . '</' . $style . '>' . $releasedTime);
        } else {
            $latestPackage = $package;
        }
        $io->write('<info>type</info>     : ' . $package->getType());
        $this->printLicenses($package);
        $io->write('<info>homepage</info> : ' . $package->getHomepage());
        $io->write('<info>source</info>   : ' . sprintf('[%s] <comment>%s</comment> %s', $package->getSourceType(), $package->getSourceUrl(), $package->getSourceReference()));
        $io->write('<info>dist</info>     : ' . sprintf('[%s] <comment>%s</comment> %s', $package->getDistType(), $package->getDistUrl(), $package->getDistReference()));
        if ($isInstalledPackage) {
            $path = $this->requireComposer()->getInstallationManager()->getInstallPath($package);
            if (is_string($path)) {
                $io->write('<info>path</info>     : ' . realpath($path));
            } else {
                $io->write('<info>path</info>     : null');
            }
        }
        $io->write('<info>names</info>    : ' . implode(', ', $package->getNames()));
        if ($latestPackage instanceof CompletePackageInterface && $latestPackage->isAbandoned()) {
            $replacement = $latestPackage->getReplacementPackage() !== null ? ' The author suggests using the ' . $latestPackage->getReplacementPackage() . ' package instead.' : null;
            $io->writeError(sprintf('<warning>Attention: This package is abandoned and no longer maintained.%s</warning>', $replacement));
        }
        if ($package->getSupport()) {
            $io->write("\n<info>support</info>");
            foreach ($package->getSupport() as $type => $value) {
                $io->write('<comment>' . $type . '</comment> : ' . $value);
            }
        }
        if (\count($package->getAutoload()) > 0) {
            $io->write("\n<info>autoload</info>");
            $autoloadConfig = $package->getAutoload();
            foreach ($autoloadConfig as $type => $autoloads) {
                $io->write('<comment>' . $type . '</comment>');
                if ($type === 'psr-0' || $type === 'psr-4') {
                    foreach ($autoloads as $name => $path) {
                        $io->write(($name ?: '*') . ' => ' . (is_array($path) ? implode(', ', $path) : ($path ?: '.')));
                    }
                } elseif ($type === 'classmap') {
                    $io->write(implode(', ', $autoloadConfig[$type]));
                }
            }
            if ($package->getIncludePaths()) {
                $io->write('<comment>include-path</comment>');
                $io->write(implode(', ', $package->getIncludePaths()));
            }
        }
    }
    /**
     * Prints all available versions of this package and highlights the installed one if any.
     *
     * @param array<string, string> $versions
     */
    protected function printVersions(CompletePackageInterface $package, array $versions, InstalledRepository $installedRepo): void
    {
        $versions = array_keys($versions);
        $versions = Semver::rsort($versions);
        // highlight installed version
        if ($installedPackages = $installedRepo->findPackages($package->getName())) {
            foreach ($installedPackages as $installedPackage) {
                $installedVersion = $installedPackage->getPrettyVersion();
                $key = array_search($installedVersion, $versions);
                if (\false !== $key) {
                    $versions[$key] = '<info>* ' . $installedVersion . '</info>';
                }
            }
        }
        $versions = implode(', ', $versions);
        $this->getIO()->write('<info>versions</info> : ' . $versions);
    }
    /**
     * print link objects
     */
    protected function printLinks(CompletePackageInterface $package, string $linkType, ?string $title = null): void
    {
        $title = $title ?: $linkType;
        $io = $this->getIO();
        if ($links = $package->{'get' . ucfirst($linkType)}()) {
            $io->write("\n<info>" . $title . "</info>");
            foreach ($links as $link) {
                $io->write($link->getTarget() . ' <comment>' . $link->getPrettyConstraint() . '</comment>');
            }
        }
    }
    /**
     * Prints the licenses of a package with metadata
     */
    protected function printLicenses(CompletePackageInterface $package): void
    {
        $spdxLicenses = new SpdxLicenses();
        $licenses = $package->getLicense();
        $io = $this->getIO();
        foreach ($licenses as $licenseId) {
            $license = $spdxLicenses->getLicenseByIdentifier($licenseId);
            // keys: 0 fullname, 1 osi, 2 url
            if (!$license) {
                $out = $licenseId;
            } else if ($license[1] === \true) {
                $out = sprintf('%s (%s) (OSI approved) %s', $license[0], $licenseId, $license[2]);
            } else {
                $out = sprintf('%s (%s) %s', $license[0], $licenseId, $license[2]);
            }
            $io->write('<info>license</info>  : ' . $out);
        }
    }
    /**
     * Prints package info in JSON format.
     *
     * @param array<string, string>    $versions
     */
    protected function printPackageInfoAsJson(CompletePackageInterface $package, array $versions, InstalledRepository $installedRepo, ?PackageInterface $latestPackage = null): void
    {
        $json = ['name' => $package->getPrettyName(), 'description' => $package->getDescription(), 'keywords' => $package->getKeywords() ?: [], 'type' => $package->getType(), 'homepage' => $package->getHomepage(), 'names' => $package->getNames()];
        $json = $this->appendVersions($json, $versions);
        $json = $this->appendLicenses($json, $package);
        if ($latestPackage) {
            $json['latest'] = $latestPackage->getPrettyVersion();
        } else {
            $latestPackage = $package;
        }
        if (null !== $package->getSourceType()) {
            $json['source'] = ['type' => $package->getSourceType(), 'url' => $package->getSourceUrl(), 'reference' => $package->getSourceReference()];
        }
        if (null !== $package->getDistType()) {
            $json['dist'] = ['type' => $package->getDistType(), 'url' => $package->getDistUrl(), 'reference' => $package->getDistReference()];
        }
        if (!PlatformRepository::isPlatformPackage($package->getName()) && $installedRepo->hasPackage($package)) {
            $path = $this->requireComposer()->getInstallationManager()->getInstallPath($package);
            if (is_string($path)) {
                $path = realpath($path);
                if ($path !== \false) {
                    $json['path'] = $path;
                }
            } else {
                $json['path'] = null;
            }
            if ($package->getReleaseDate() !== null) {
                $json['released'] = $package->getReleaseDate()->format(\DATE_ATOM);
            }
        }
        if ($latestPackage instanceof CompletePackageInterface && $latestPackage->isAbandoned()) {
            $json['replacement'] = $latestPackage->getReplacementPackage();
        }
        if ($package->getSuggests()) {
            $json['suggests'] = $package->getSuggests();
        }
        if ($package->getSupport()) {
            $json['support'] = $package->getSupport();
        }
        $json = $this->appendAutoload($json, $package);
        if ($package->getIncludePaths()) {
            $json['include_path'] = $package->getIncludePaths();
        }
        $json = $this->appendLinks($json, $package);
        $this->getIO()->write(JsonFile::encode($json));
    }
    /**
     * @param JsonStructure $json
     * @param array<string, string> $versions
     * @return JsonStructure
     */
    private function appendVersions(array $json, array $versions): array
    {
        uasort($versions, 'version_compare');
        $versions = array_keys(array_reverse($versions));
        $json['versions'] = $versions;
        return $json;
    }
    /**
     * @param JsonStructure $json
     * @return JsonStructure
     */
    private function appendLicenses(array $json, CompletePackageInterface $package): array
    {
        if ($licenses = $package->getLicense()) {
            $spdxLicenses = new SpdxLicenses();
            $json['licenses'] = array_map(static function ($licenseId) use ($spdxLicenses) {
                $license = $spdxLicenses->getLicenseByIdentifier($licenseId);
                // keys: 0 fullname, 1 osi, 2 url
                if (!$license) {
                    return $licenseId;
                }
                return ['name' => $license[0], 'osi' => $licenseId, 'url' => $license[2]];
            }, $licenses);
        }
        return $json;
    }
    /**
     * @param JsonStructure $json
     * @return JsonStructure
     */
    private function appendAutoload(array $json, CompletePackageInterface $package): array
    {
        if (\count($package->getAutoload()) > 0) {
            $autoload = [];
            foreach ($package->getAutoload() as $type => $autoloads) {
                if ($type === 'psr-0' || $type === 'psr-4') {
                    $psr = [];
                    foreach ($autoloads as $name => $path) {
                        if (!$path) {
                            $path = '.';
                        }
                        $psr[$name ?: '*'] = $path;
                    }
                    $autoload[$type] = $psr;
                } elseif ($type === 'classmap') {
                    $autoload['classmap'] = $autoloads;
                }
            }
            $json['autoload'] = $autoload;
        }
        return $json;
    }
    /**
     * @param JsonStructure $json
     * @return JsonStructure
     */
    private function appendLinks(array $json, CompletePackageInterface $package): array
    {
        foreach (Link::$TYPES as $linkType) {
            $json = $this->appendLink($json, $package, $linkType);
        }
        return $json;
    }
    /**
     * @param JsonStructure $json
     * @return JsonStructure
     */
    private function appendLink(array $json, CompletePackageInterface $package, string $linkType): array
    {
        $links = $package->{'get' . ucfirst($linkType)}();
        if ($links) {
            $json[$linkType] = [];
            foreach ($links as $link) {
                $json[$linkType][$link->getTarget()] = $link->getPrettyConstraint();
            }
        }
        return $json;
    }
    /**
     * Init styles for tree
     */
    protected function initStyles(OutputInterface $output): void
    {
        $this->colors = ['green', 'yellow', 'cyan', 'magenta', 'blue'];
        foreach ($this->colors as $color) {
            $style = new OutputFormatterStyle($color);
            $output->getFormatter()->setStyle($color, $style);
        }
    }
    /**
     * Display the tree
     *
     * @param array<int, array<string, string|mixed[]>> $arrayTree
     */
    protected function displayPackageTree(array $arrayTree): void
    {
        $io = $this->getIO();
        foreach ($arrayTree as $package) {
            $io->write(sprintf('<info>%s</info>', $package['name']), \false);
            $io->write(' ' . $package['version'], \false);
            if (isset($package['description'])) {
                $io->write(' ' . strtok($package['description'], "\r\n"));
            } else {
                // output newline
                $io->write('');
            }
            if (isset($package['requires'])) {
                $requires = $package['requires'];
                $treeBar = '├';
                $j = 0;
                $total = count($requires);
                foreach ($requires as $require) {
                    $requireName = $require['name'];
                    $j++;
                    if ($j === $total) {
                        $treeBar = '└';
                    }
                    $level = 1;
                    $color = $this->colors[$level];
                    $info = sprintf('%s──<%s>%s</%s> %s', $treeBar, $color, $requireName, $color, $require['version']);
                    $this->writeTreeLine($info);
                    $treeBar = str_replace('└', ' ', $treeBar);
                    $packagesInTree = [$package['name'], $requireName];
                    $this->displayTree($require, $packagesInTree, $treeBar, $level + 1);
                }
            }
        }
    }
    /**
     * Generate the package tree
     *
     * @return array<string, array<int, array<string, mixed[]|string>>|string|null>
     */
    protected function generatePackageTree(PackageInterface $package, InstalledRepository $installedRepo, RepositoryInterface $remoteRepos): array
    {
        $requires = $package->getRequires();
        ksort($requires);
        $children = [];
        foreach ($requires as $requireName => $require) {
            $packagesInTree = [$package->getName(), $requireName];
            $treeChildDesc = ['name' => $requireName, 'version' => $require->getPrettyConstraint()];
            $deepChildren = $this->addTree($requireName, $require, $installedRepo, $remoteRepos, $packagesInTree);
            if ($deepChildren) {
                $treeChildDesc['requires'] = $deepChildren;
            }
            $children[] = $treeChildDesc;
        }
        $tree = ['name' => $package->getPrettyName(), 'version' => $package->getPrettyVersion(), 'description' => $package instanceof CompletePackageInterface ? $package->getDescription() : ''];
        if ($children) {
            $tree['requires'] = $children;
        }
        return $tree;
    }
    /**
     * Display a package tree
     *
     * @param array<string, array<int, array<string, mixed[]|string>>|string|null>|string $package
     * @param array<int, string|mixed[]> $packagesInTree
     */
    protected function displayTree($package, array $packagesInTree, string $previousTreeBar = '├', int $level = 1): void
    {
        $previousTreeBar = str_replace('├', '│', $previousTreeBar);
        if (is_array($package) && isset($package['requires'])) {
            $requires = $package['requires'];
            $treeBar = $previousTreeBar . '  ├';
            $i = 0;
            $total = count($requires);
            foreach ($requires as $require) {
                $currentTree = $packagesInTree;
                $i++;
                if ($i === $total) {
                    $treeBar = $previousTreeBar . '  └';
                }
                $colorIdent = $level % count($this->colors);
                $color = $this->colors[$colorIdent];
                assert(is_string($require['name']));
                assert(is_string($require['version']));
                $circularWarn = in_array($require['name'], $currentTree, \true) ? '(circular dependency aborted here)' : '';
                $info = rtrim(sprintf('%s──<%s>%s</%s> %s %s', $treeBar, $color, $require['name'], $color, $require['version'], $circularWarn));
                $this->writeTreeLine($info);
                $treeBar = str_replace('└', ' ', $treeBar);
                $currentTree[] = $require['name'];
                $this->displayTree($require, $currentTree, $treeBar, $level + 1);
            }
        }
    }
    /**
     * Display a package tree
     *
     * @param  string[] $packagesInTree
     * @return array<int, array<string, array<int, array<string, string>>|string>>
     */
    protected function addTree(string $name, Link $link, InstalledRepository $installedRepo, RepositoryInterface $remoteRepos, array $packagesInTree): array
    {
        $children = [];
        [$package] = $this->getPackage($installedRepo, $remoteRepos, $name, $link->getPrettyConstraint() === 'self.version' ? $link->getConstraint() : $link->getPrettyConstraint());
        if (is_object($package)) {
            $requires = $package->getRequires();
            ksort($requires);
            foreach ($requires as $requireName => $require) {
                $currentTree = $packagesInTree;
                $treeChildDesc = ['name' => $requireName, 'version' => $require->getPrettyConstraint()];
                if (!in_array($requireName, $currentTree, \true)) {
                    $currentTree[] = $requireName;
                    $deepChildren = $this->addTree($requireName, $require, $installedRepo, $remoteRepos, $currentTree);
                    if ($deepChildren) {
                        $treeChildDesc['requires'] = $deepChildren;
                    }
                }
                $children[] = $treeChildDesc;
            }
        }
        return $children;
    }
    private function updateStatusToVersionStyle(string $updateStatus): string
    {
        // 'up-to-date' is printed green
        // 'semver-safe-update' is printed red
        // 'update-possible' is printed yellow
        return str_replace(['up-to-date', 'semver-safe-update', 'update-possible'], ['info', 'highlight', 'comment'], $updateStatus);
    }
    private function getUpdateStatus(PackageInterface $latestPackage, PackageInterface $package): string
    {
        if ($latestPackage->getFullPrettyVersion() === $package->getFullPrettyVersion()) {
            return 'up-to-date';
        }
        $constraint = $package->getVersion();
        if (0 !== strpos($constraint, 'dev-')) {
            $constraint = '^' . $constraint;
        }
        if ($latestPackage->getVersion() && Semver::satisfies($latestPackage->getVersion(), $constraint)) {
            // it needs an immediate semver-compliant upgrade
            return 'semver-safe-update';
        }
        // it needs an upgrade but has potential BC breaks so is not urgent
        return 'update-possible';
    }
    private function writeTreeLine(string $line): void
    {
        $io = $this->getIO();
        if (!$io->isDecorated()) {
            $line = str_replace(['└', '├', '──', '│'], ['`-', '|-', '-', '|'], $line);
        }
        $io->write($line);
    }
    /**
     * Given a package, this finds the latest package matching it
     */
    private function findLatestPackage(PackageInterface $package, Composer $composer, PlatformRepository $platformRepo, bool $majorOnly, bool $minorOnly, bool $patchOnly, PlatformRequirementFilterInterface $platformReqFilter): ?PackageInterface
    {
        // find the latest version allowed in this repo set
        $name = $package->getName();
        $versionSelector = new VersionSelector($this->getRepositorySet($composer), $platformRepo);
        $stability = $composer->getPackage()->getMinimumStability();
        $flags = $composer->getPackage()->getStabilityFlags();
        if (isset($flags[$name])) {
            $stability = array_search($flags[$name], BasePackage::STABILITIES, \true);
        }
        $bestStability = $stability;
        if ($composer->getPackage()->getPreferStable()) {
            $bestStability = $package->getStability();
        }
        $targetVersion = null;
        if (0 === strpos($package->getVersion(), 'dev-')) {
            $targetVersion = $package->getVersion();
            // dev-x branches are considered to be on the latest major version always, do not look up for a new commit as that is deemed a minor upgrade (albeit risky)
            if ($majorOnly) {
                return null;
            }
        }
        if ($targetVersion === null) {
            if ($majorOnly && Preg::isMatch('{^(?P<zero_major>(?:0\.)+)?(?P<first_meaningful>\d+)\.}', $package->getVersion(), $match)) {
                $targetVersion = '>=' . $match['zero_major'] . ((int) $match['first_meaningful'] + 1) . ',<9999999-dev';
            }
            if ($minorOnly) {
                $targetVersion = '^' . $package->getVersion();
            }
            if ($patchOnly) {
                $trimmedVersion = Preg::replace('{(\.0)+$}D', '', $package->getVersion());
                $partsNeeded = substr($trimmedVersion, 0, 1) === '0' ? 4 : 3;
                while (substr_count($trimmedVersion, '.') + 1 < $partsNeeded) {
                    $trimmedVersion .= '.0';
                }
                $targetVersion = '~' . $trimmedVersion;
            }
        }
        if ($this->getIO()->isVerbose()) {
            $showWarnings = \true;
        } else {
            $showWarnings = static function (PackageInterface $candidate) use ($package): bool {
                if (str_starts_with($candidate->getVersion(), 'dev-') || str_starts_with($package->getVersion(), 'dev-')) {
                    return \false;
                }
                return version_compare($candidate->getVersion(), $package->getVersion(), '<=');
            };
        }
        $candidate = $versionSelector->findBestCandidate($name, $targetVersion, $bestStability, $platformReqFilter, 0, $this->getIO(), $showWarnings);
        while ($candidate instanceof AliasPackage) {
            $candidate = $candidate->getAliasOf();
        }
        return $candidate !== \false ? $candidate : null;
    }
    private function getRepositorySet(Composer $composer): RepositorySet
    {
        if (!$this->repositorySet) {
            $this->repositorySet = new RepositorySet($composer->getPackage()->getMinimumStability(), $composer->getPackage()->getStabilityFlags());
            $this->repositorySet->addRepository(new CompositeRepository($composer->getRepositoryManager()->getRepositories()));
        }
        return $this->repositorySet;
    }
    private function getRelativeTime(DateTimeInterface $releaseDate): string
    {
        if ($releaseDate->format('Ymd') === date('Ymd')) {
            return 'today';
        }
        $diff = $releaseDate->diff(new \DateTimeImmutable());
        if ($diff->days < 7) {
            return 'this week';
        }
        if ($diff->days < 14) {
            return 'last week';
        }
        if ($diff->m < 1 && $diff->days < 31) {
            return floor($diff->days / 7) . ' weeks ago';
        }
        if ($diff->y < 1) {
            return $diff->m . ' month' . ($diff->m > 1 ? 's' : '') . ' ago';
        }
        return $diff->y . ' year' . ($diff->y > 1 ? 's' : '') . ' ago';
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer\Command;

use Composer\Installer;
use Composer\Plugin\CommandEvent;
use Composer\Plugin\PluginEvents;
use Composer\Advisory\Auditor;
use Composer\Util\HttpDownloader;
use _ContaoManager\Symfony\Component\Console\Input\InputInterface;
use Composer\Console\Input\InputOption;
use Composer\Console\Input\InputArgument;
use _ContaoManager\Symfony\Component\Console\Output\OutputInterface;
/**
 * @author Jordi Boggiano <j.boggiano@seld.be>
 * @author Ryan Weaver <ryan@knplabs.com>
 * @author Konstantin Kudryashov <ever.zet@gmail.com>
 * @author Nils Adermann <naderman@naderman.de>
 */
class InstallCommand extends \Composer\Command\BaseCommand
{
    use \Composer\Command\CompletionTrait;
    protected function configure(): void
    {
        $this->setName('install')->setAliases(['i'])->setDescription('Installs the project dependencies from the composer.lock file if present, or falls back on the composer.json')->setDefinition([new InputOption('prefer-source', null, InputOption::VALUE_NONE, 'Forces installation from package sources when possible, including VCS information.'), new InputOption('prefer-dist', null, InputOption::VALUE_NONE, 'Forces installation from package dist (default behavior).'), new InputOption('prefer-install', null, InputOption::VALUE_REQUIRED, 'Forces installation from package dist|source|auto (auto chooses source for dev versions, dist for the rest).', null, $this->suggestPreferInstall()), new InputOption('dry-run', null, InputOption::VALUE_NONE, 'Outputs the operations but will not execute anything (implicitly enables --verbose).'), new InputOption('download-only', null, InputOption::VALUE_NONE, 'Download only, do not install packages.'), new InputOption('dev', null, InputOption::VALUE_NONE, 'DEPRECATED: Enables installation of require-dev packages (enabled by default, only present for BC).'), new InputOption('no-suggest', null, InputOption::VALUE_NONE, 'DEPRECATED: This flag does not exist anymore.'), new InputOption('no-dev', null, InputOption::VALUE_NONE, 'Disables installation of require-dev packages.'), new InputOption('no-security-blocking', null, InputOption::VALUE_NONE, 'Allows installing packages with security advisories or that are abandoned (can also be set via the COMPOSER_NO_SECURITY_BLOCKING=1 env var). Only applies when no lock file is present.'), new InputOption('no-autoloader', null, InputOption::VALUE_NONE, 'Skips autoloader generation'), new InputOption('no-progress', null, InputOption::VALUE_NONE, 'Do not output download progress.'), new InputOption('no-install', null, InputOption::VALUE_NONE, 'Do not use, only defined here to catch misuse of the install command.'), new InputOption('audit', null, InputOption::VALUE_NONE, 'Run an audit after installation is complete.'), new InputOption('audit-format', null, InputOption::VALUE_REQUIRED, 'Audit output format. Must be "table", "plain", "json", or "summary".', Auditor::FORMAT_SUMMARY, Auditor::FORMATS), new InputOption('verbose', 'v|vv|vvv', InputOption::VALUE_NONE, 'Shows more details including new commits pulled in when updating packages.'), new InputOption('optimize-autoloader', 'o', InputOption::VALUE_NONE, 'Optimize autoloader during autoloader dump'), new InputOption('classmap-authoritative', 'a', InputOption::VALUE_NONE, 'Autoload classes from the classmap only. Implicitly enables `--optimize-autoloader`.'), new InputOption('apcu-autoloader', null, InputOption::VALUE_NONE, 'Use APCu to cache found/not-found classes.'), new InputOption('apcu-autoloader-prefix', null, InputOption::VALUE_REQUIRED, 'Use a custom prefix for the APCu autoloader cache. Implicitly enables --apcu-autoloader'), new InputOption('ignore-platform-req', null, InputOption::VALUE_REQUIRED | InputOption::VALUE_IS_ARRAY, 'Ignore a specific platform requirement (php & ext- packages).'), new InputOption('ignore-platform-reqs', null, InputOption::VALUE_NONE, 'Ignore all platform requirements (php & ext- packages).'), new InputArgument('packages', InputArgument::IS_ARRAY | InputArgument::OPTIONAL, 'Should not be provided, use composer require instead to add a given package to composer.json.')])->setHelp(<<<EOT
The <info>install</info> command reads the composer.lock file from
the current directory, processes it, and downloads and installs all the
libraries and dependencies outlined in that file. If the file does not
exist it will look for composer.json and do the same.

<info>php composer.phar install</info>

Read more at https://getcomposer.org/doc/03-cli.md#install-i
EOT
);
    }
    protected function execute(InputInterface $input, OutputInterface $output): int
    {
        $io = $this->getIO();
        if ($input->getOption('dev')) {
            $io->writeError('<warning>You are using the deprecated option "--dev". It has no effect and will break in Composer 3.</warning>');
        }
        if ($input->getOption('no-suggest')) {
            $io->writeError('<warning>You are using the deprecated option "--no-suggest". It has no effect and will break in Composer 3.</warning>');
        }
        $args = $input->getArgument('packages');
        if (count($args) > 0) {
            $io->writeError('<error>Invalid argument ' . implode(' ', $args) . '. Use "composer require ' . implode(' ', $args) . '" instead to add packages to your composer.json.</error>');
            return 1;
        }
        if ($input->getOption('no-install')) {
            $io->writeError('<error>Invalid option "--no-install". Use "composer update --no-install" instead if you are trying to update the composer.lock file.</error>');
            return 1;
        }
        $composer = $this->requireComposer();
        if (!$composer->getLocker()->isLocked() && !HttpDownloader::isCurlEnabled()) {
            $io->writeError('<warning>Composer is operating significantly slower than normal because you do not have the PHP curl extension enabled.</warning>');
        }
        $commandEvent = new CommandEvent(PluginEvents::COMMAND, 'install', $input, $output);
        $composer->getEventDispatcher()->dispatch($commandEvent->getName(), $commandEvent);
        $install = Installer::create($io, $composer);
        $config = $composer->getConfig();
        [$preferSource, $preferDist] = $this->getPreferredInstallOptions($config, $input);
        $optimize = $input->getOption('optimize-autoloader') || $config->get('optimize-autoloader');
        $authoritative = $input->getOption('classmap-authoritative') || $config->get('classmap-authoritative');
        $apcuPrefix = $input->getOption('apcu-autoloader-prefix');
        $apcu = $apcuPrefix !== null || $input->getOption('apcu-autoloader') || $config->get('apcu-autoloader');
        $composer->getInstallationManager()->setOutputProgress(!$input->getOption('no-progress'));
        $install->setDryRun($input->getOption('dry-run'))->setDownloadOnly($input->getOption('download-only'))->setVerbose($input->getOption('verbose'))->setPreferSource($preferSource)->setPreferDist($preferDist)->setDevMode(!$input->getOption('no-dev'))->setDumpAutoloader(!$input->getOption('no-autoloader'))->setOptimizeAutoloader($optimize)->setClassMapAuthoritative($authoritative)->setApcuAutoloader($apcu, $apcuPrefix)->setPlatformRequirementFilter($this->getPlatformRequirementFilter($input))->setAuditConfig($this->createAuditConfig($composer->getConfig(), $input))->setErrorOnAudit($input->getOption('audit'));
        if ($input->getOption('no-plugins')) {
            $install->disablePlugins();
        }
        return $install->run();
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer\Command;

use Composer\Factory;
use Composer\Json\JsonFile;
use Composer\Json\JsonValidationException;
use Composer\Package\BasePackage;
use Composer\Pcre\Preg;
use Composer\Repository\CompositeRepository;
use Composer\Repository\PlatformRepository;
use Composer\Repository\RepositoryFactory;
use Composer\Spdx\SpdxLicenses;
use Composer\Util\Filesystem;
use Composer\Util\Silencer;
use _ContaoManager\Symfony\Component\Console\Input\ArrayInput;
use _ContaoManager\Symfony\Component\Console\Input\InputInterface;
use Composer\Console\Input\InputOption;
use Composer\Util\ProcessExecutor;
use _ContaoManager\Symfony\Component\Console\Output\OutputInterface;
use _ContaoManager\Symfony\Component\Console\Helper\FormatterHelper;
/**
 * @author Justin Rainbow <justin.rainbow@gmail.com>
 * @author Jordi Boggiano <j.boggiano@seld.be>
 */
class InitCommand extends \Composer\Command\BaseCommand
{
    use \Composer\Command\CompletionTrait;
    use \Composer\Command\PackageDiscoveryTrait;
    /** @var array<string, string> */
    private $gitConfig;
    /**
     * @inheritDoc
     */
    protected function configure(): void
    {
        $this->setName('init')->setDescription('Creates a basic composer.json file in current directory')->setDefinition([new InputOption('name', null, InputOption::VALUE_REQUIRED, 'Name of the package'), new InputOption('description', null, InputOption::VALUE_REQUIRED, 'Description of package'), new InputOption('author', null, InputOption::VALUE_REQUIRED, 'Author name of package'), new InputOption('type', null, InputOption::VALUE_REQUIRED, 'Type of package (e.g. library, project, metapackage, composer-plugin)'), new InputOption('homepage', null, InputOption::VALUE_REQUIRED, 'Homepage of package'), new InputOption('require', null, InputOption::VALUE_IS_ARRAY | InputOption::VALUE_REQUIRED, 'Package to require with a version constraint, e.g. foo/bar:1.0.0 or foo/bar=1.0.0 or "foo/bar 1.0.0"', null, $this->suggestAvailablePackageInclPlatform()), new InputOption('require-dev', null, InputOption::VALUE_IS_ARRAY | InputOption::VALUE_REQUIRED, 'Package to require for development with a version constraint, e.g. foo/bar:1.0.0 or foo/bar=1.0.0 or "foo/bar 1.0.0"', null, $this->suggestAvailablePackageInclPlatform()), new InputOption('stability', 's', InputOption::VALUE_REQUIRED, 'Minimum stability (empty or one of: ' . implode(', ', array_keys(BasePackage::STABILITIES)) . ')'), new InputOption('license', 'l', InputOption::VALUE_REQUIRED, 'License of package'), new InputOption('repository', null, InputOption::VALUE_REQUIRED | InputOption::VALUE_IS_ARRAY, 'Add custom repositories, either by URL or using JSON arrays'), new InputOption('autoload', 'a', InputOption::VALUE_REQUIRED, 'Add PSR-4 autoload mapping. Maps your package\'s namespace to the provided directory. (Expects a relative path, e.g. src/)')])->setHelp(<<<EOT
The <info>init</info> command creates a basic composer.json file
in the current directory.

<info>php composer.phar init</info>

Read more at https://getcomposer.org/doc/03-cli.md#init
EOT
);
    }
    /**
     * @throws \Seld\JsonLint\ParsingException
     */
    protected function execute(InputInterface $input, OutputInterface $output): int
    {
        $io = $this->getIO();
        $allowlist = ['name', 'description', 'author', 'type', 'homepage', 'require', 'require-dev', 'stability', 'license', 'autoload'];
        $options = array_filter(array_intersect_key($input->getOptions(), array_flip($allowlist)), static function ($val) {
            return $val !== null && $val !== [];
        });
        if (isset($options['name']) && !Preg::isMatch('{^[a-z0-9]([_.-]?[a-z0-9]+)*\/[a-z0-9](([_.]|-{1,2})?[a-z0-9]+)*$}D', $options['name'])) {
            throw new \InvalidArgumentException('The package name ' . $options['name'] . ' is invalid, it should be lowercase and have a vendor name, a forward slash, and a package name, matching: [a-z0-9_.-]+/[a-z0-9_.-]+');
        }
        if (isset($options['author'])) {
            $options['authors'] = $this->formatAuthors($options['author']);
            unset($options['author']);
        }
        $repositories = $input->getOption('repository');
        if (count($repositories) > 0) {
            $config = Factory::createConfig($io);
            foreach ($repositories as $repo) {
                $options['repositories'][] = RepositoryFactory::configFromString($io, $config, $repo, \true);
            }
        }
        if (isset($options['stability'])) {
            $options['minimum-stability'] = $options['stability'];
            unset($options['stability']);
        }
        $options['require'] = isset($options['require']) ? $this->formatRequirements($options['require']) : new \stdClass();
        if ([] === $options['require']) {
            $options['require'] = new \stdClass();
        }
        if (isset($options['require-dev'])) {
            $options['require-dev'] = $this->formatRequirements($options['require-dev']);
            if ([] === $options['require-dev']) {
                $options['require-dev'] = new \stdClass();
            }
        }
        // --autoload - create autoload object
        $autoloadPath = null;
        if (isset($options['autoload'])) {
            $autoloadPath = $options['autoload'];
            $namespace = $this->namespaceFromPackageName((string) $input->getOption('name'));
            $options['autoload'] = (object) ['psr-4' => [$namespace . '\\' => $autoloadPath]];
        }
        $file = new JsonFile(Factory::getComposerFile());
        $json = JsonFile::encode($options);
        if ($input->isInteractive()) {
            $io->writeError(['', $json, '']);
            if (!$io->askConfirmation('Do you confirm generation [<comment>yes</comment>]? ')) {
                $io->writeError('<error>Command aborted</error>');
                return 1;
            }
        } else {
            $io->writeError('Writing ' . $file->getPath());
        }
        $file->write($options);
        try {
            $file->validateSchema(JsonFile::LAX_SCHEMA);
        } catch (JsonValidationException $e) {
            $io->writeError('<error>Schema validation error, aborting</error>');
            $errors = ' - ' . implode(\PHP_EOL . ' - ', $e->getErrors());
            $io->writeError($e->getMessage() . ':' . \PHP_EOL . $errors);
            Silencer::call('unlink', $file->getPath());
            return 1;
        }
        // --autoload - Create src folder
        if ($autoloadPath) {
            $filesystem = new Filesystem();
            $filesystem->ensureDirectoryExists($autoloadPath);
            // dump-autoload only for projects without added dependencies.
            if (!$this->hasDependencies($options)) {
                $this->runDumpAutoloadCommand($output);
            }
        }
        if ($input->isInteractive() && is_dir('.git')) {
            $ignoreFile = realpath('.gitignore');
            if (\false === $ignoreFile) {
                $ignoreFile = realpath('.') . '/.gitignore';
            }
            if (!$this->hasVendorIgnore($ignoreFile)) {
                $question = 'Would you like the <info>vendor</info> directory added to your <info>.gitignore</info> [<comment>yes</comment>]? ';
                if ($io->askConfirmation($question)) {
                    $this->addVendorIgnore($ignoreFile);
                }
            }
        }
        $question = 'Would you like to install dependencies now [<comment>yes</comment>]? ';
        if ($input->isInteractive() && $this->hasDependencies($options) && $io->askConfirmation($question)) {
            $this->updateDependencies($output);
        }
        // --autoload - Show post-install configuration info
        if ($autoloadPath) {
            $namespace = $this->namespaceFromPackageName((string) $input->getOption('name'));
            $io->writeError('PSR-4 autoloading configured. Use "<comment>namespace ' . $namespace . ';</comment>" in ' . $autoloadPath);
            $io->writeError('Include the Composer autoloader with: <comment>require \'vendor/autoload.php\';</comment>');
        }
        return 0;
    }
    protected function initialize(InputInterface $input, OutputInterface $output): void
    {
        parent::initialize($input, $output);
        if (!$input->isInteractive()) {
            if ($input->getOption('name') === null) {
                $input->setOption('name', $this->getDefaultPackageName());
            }
            if ($input->getOption('author') === null) {
                $input->setOption('author', $this->getDefaultAuthor());
            }
        }
    }
    /**
     * @inheritDoc
     */
    protected function interact(InputInterface $input, OutputInterface $output): void
    {
        $io = $this->getIO();
        /** @var FormatterHelper $formatter */
        $formatter = $this->getHelperSet()->get('formatter');
        // initialize repos if configured
        $repositories = $input->getOption('repository');
        if (count($repositories) > 0) {
            $config = Factory::createConfig($io);
            $io->loadConfiguration($config);
            $repoManager = RepositoryFactory::manager($io, $config);
            $repos = [new PlatformRepository()];
            $createDefaultPackagistRepo = \true;
            foreach ($repositories as $repo) {
                $repoConfig = RepositoryFactory::configFromString($io, $config, $repo, \true);
                if (isset($repoConfig['packagist']) && $repoConfig === ['packagist' => \false] || isset($repoConfig['packagist.org']) && $repoConfig === ['packagist.org' => \false]) {
                    $createDefaultPackagistRepo = \false;
                    continue;
                }
                $repos[] = RepositoryFactory::createRepo($io, $config, $repoConfig, $repoManager);
            }
            if ($createDefaultPackagistRepo) {
                $repos[] = RepositoryFactory::createRepo($io, $config, ['type' => 'composer', 'url' => 'https://repo.packagist.org'], $repoManager);
            }
            $this->repos = new CompositeRepository($repos);
            unset($repos, $config, $repositories);
        }
        $io->writeError(['', $formatter->formatBlock('Welcome to the Composer config generator', 'bg=blue;fg=white', \true), '']);
        // namespace
        $io->writeError(['', 'This command will guide you through creating your composer.json config.', '']);
        $name = $input->getOption('name') ?? $this->getDefaultPackageName();
        $name = $io->askAndValidate('Package name (<vendor>/<name>) [<comment>' . $name . '</comment>]: ', static function ($value) use ($name) {
            if (null === $value) {
                return $name;
            }
            if (!Preg::isMatch('{^[a-z0-9]([_.-]?[a-z0-9]+)*\/[a-z0-9](([_.]|-{1,2})?[a-z0-9]+)*$}D', $value)) {
                throw new \InvalidArgumentException('The package name ' . $value . ' is invalid, it should be lowercase and have a vendor name, a forward slash, and a package name, matching: [a-z0-9_.-]+/[a-z0-9_.-]+');
            }
            return $value;
        }, null, $name);
        $input->setOption('name', $name);
        $description = $input->getOption('description') ?: null;
        $description = $io->ask('Description [<comment>' . $description . '</comment>]: ', $description);
        $input->setOption('description', $description);
        $author = $input->getOption('author') ?? $this->getDefaultAuthor();
        $author = $io->askAndValidate('Author [' . (is_string($author) ? '<comment>' . $author . '</comment>, ' : '') . 'n to skip]: ', function ($value) use ($author) {
            if ($value === 'n' || $value === 'no') {
                return;
            }
            $value = $value ?: $author;
            $author = $this->parseAuthorString($value ?? '');
            if ($author['email'] === null) {
                return $author['name'];
            }
            return sprintf('%s <%s>', $author['name'], $author['email']);
        }, null, $author);
        $input->setOption('author', $author);
        $minimumStability = $input->getOption('stability') ?: null;
        $minimumStability = $io->askAndValidate('Minimum Stability [<comment>' . $minimumStability . '</comment>]: ', static function ($value) use ($minimumStability) {
            if (null === $value) {
                return $minimumStability;
            }
            if (!isset(BasePackage::STABILITIES[$value])) {
                throw new \InvalidArgumentException('Invalid minimum stability "' . $value . '". Must be empty or one of: ' . implode(', ', array_keys(BasePackage::STABILITIES)));
            }
            return $value;
        }, null, $minimumStability);
        $input->setOption('stability', $minimumStability);
        $type = $input->getOption('type');
        $type = $io->ask('Package Type (e.g. library, project, metapackage, composer-plugin) [<comment>' . $type . '</comment>]: ', $type);
        if ($type === '' || $type === \false) {
            $type = null;
        }
        $input->setOption('type', $type);
        if (null === $license = $input->getOption('license')) {
            if (!empty($_SERVER['COMPOSER_DEFAULT_LICENSE'])) {
                $license = $_SERVER['COMPOSER_DEFAULT_LICENSE'];
            }
        }
        $license = $io->ask('License [<comment>' . $license . '</comment>]: ', $license);
        $spdx = new SpdxLicenses();
        if (null !== $license && !$spdx->validate($license) && $license !== 'proprietary') {
            throw new \InvalidArgumentException('Invalid license provided: ' . $license . '. Only SPDX license identifiers (https://spdx.org/licenses/) or "proprietary" are accepted.');
        }
        $input->setOption('license', $license);
        $io->writeError(['', 'Define your dependencies.', '']);
        // prepare to resolve dependencies
        $repos = $this->getRepos();
        $preferredStability = $minimumStability ?: 'stable';
        $platformRepo = null;
        if ($repos instanceof CompositeRepository) {
            foreach ($repos->getRepositories() as $candidateRepo) {
                if ($candidateRepo instanceof PlatformRepository) {
                    $platformRepo = $candidateRepo;
                    break;
                }
            }
        }
        $question = 'Would you like to define your dependencies (require) interactively [<comment>yes</comment>]? ';
        $require = $input->getOption('require');
        $requirements = [];
        if (count($require) > 0 || $io->askConfirmation($question)) {
            $requirements = $this->determineRequirements($input, $output, $require, $platformRepo, $preferredStability);
        }
        $input->setOption('require', $requirements);
        $question = 'Would you like to define your dev dependencies (require-dev) interactively [<comment>yes</comment>]? ';
        $requireDev = $input->getOption('require-dev');
        $devRequirements = [];
        if (count($requireDev) > 0 || $io->askConfirmation($question)) {
            $devRequirements = $this->determineRequirements($input, $output, $requireDev, $platformRepo, $preferredStability);
        }
        $input->setOption('require-dev', $devRequirements);
        // --autoload - input and validation
        $autoload = $input->getOption('autoload') ?: 'src/';
        $namespace = $this->namespaceFromPackageName((string) $input->getOption('name'));
        $autoload = $io->askAndValidate('Add PSR-4 autoload mapping? Maps namespace "' . $namespace . '" to the entered relative path. [<comment>' . $autoload . '</comment>, n to skip]: ', static function ($value) use ($autoload) {
            if (null === $value) {
                return $autoload;
            }
            if ($value === 'n' || $value === 'no') {
                return;
            }
            $value = $value ?: $autoload;
            if (!Preg::isMatch('{^[^/][A-Za-z0-9\-_/]+/$}', $value)) {
                throw new \InvalidArgumentException(sprintf('The src folder name "%s" is invalid. Please add a relative path with tailing forward slash. [A-Za-z0-9_-/]+/', $value));
            }
            return $value;
        }, null, $autoload);
        $input->setOption('autoload', $autoload);
    }
    /**
     * @return array{name: string, email: string|null}
     */
    private function parseAuthorString(string $author): array
    {
        if (Preg::isMatch('/^(?P<name>[- .,\p{L}\p{N}\p{Mn}\'’"()]+)(?:\s+<(?P<email>.+?)>)?$/u', $author, $match)) {
            if (null !== $match['email'] && !$this->isValidEmail($match['email'])) {
                throw new \InvalidArgumentException('Invalid email "' . $match['email'] . '"');
            }
            return ['name' => trim($match['name']), 'email' => $match['email']];
        }
        throw new \InvalidArgumentException('Invalid author string.  Must be in the formats: ' . 'Jane Doe or John Smith <john@example.com>');
    }
    /**
     * @return array<int, array{name: string, email?: string}>
     */
    protected function formatAuthors(string $author): array
    {
        $author = $this->parseAuthorString($author);
        if (null === $author['email']) {
            unset($author['email']);
        }
        return [$author];
    }
    /**
     * Extract namespace from package's vendor name.
     *
     * new_projects.acme-extra/package-name becomes "NewProjectsAcmeExtra\PackageName"
     */
    public function namespaceFromPackageName(string $packageName): ?string
    {
        if (!$packageName || strpos($packageName, '/') === \false) {
            return null;
        }
        $namespace = array_map(static function ($part): string {
            $part = Preg::replace('/[^a-z0-9]/i', ' ', $part);
            $part = ucwords($part);
            return str_replace(' ', '', $part);
        }, explode('/', $packageName));
        return implode('\\', $namespace);
    }
    /**
     * @return array<string, string>
     */
    protected function getGitConfig(): array
    {
        if (null !== $this->gitConfig) {
            return $this->gitConfig;
        }
        $process = new ProcessExecutor($this->getIO());
        if (0 === $process->execute(['git', 'config', '-l'], $output)) {
            $this->gitConfig = [];
            Preg::matchAllStrictGroups('{^([^=]+)=(.*)$}m', $output, $matches);
            foreach ($matches[1] as $key => $match) {
                $this->gitConfig[$match] = $matches[2][$key];
            }
            return $this->gitConfig;
        }
        return $this->gitConfig = [];
    }
    /**
     * Checks the local .gitignore file for the Composer vendor directory.
     *
     * Tested patterns include:
     *  "/$vendor"
     *  "$vendor"
     *  "$vendor/"
     *  "/$vendor/"
     *  "/$vendor/*"
     *  "$vendor/*"
     */
    protected function hasVendorIgnore(string $ignoreFile, string $vendor = 'vendor'): bool
    {
        if (!file_exists($ignoreFile)) {
            return \false;
        }
        $pattern = sprintf('{^/?%s(/\*?)?$}', preg_quote($vendor));
        $lines = file($ignoreFile, \FILE_IGNORE_NEW_LINES);
        foreach ($lines as $line) {
            if (Preg::isMatch($pattern, $line)) {
                return \true;
            }
        }
        return \false;
    }
    protected function addVendorIgnore(string $ignoreFile, string $vendor = '/vendor/'): void
    {
        $contents = "";
        if (file_exists($ignoreFile)) {
            $contents = file_get_contents($ignoreFile);
            if (strpos($contents, "\n") !== 0) {
                $contents .= "\n";
            }
        }
        file_put_contents($ignoreFile, $contents . $vendor . "\n");
    }
    protected function isValidEmail(string $email): bool
    {
        // assume it's valid if we can't validate it
        if (!function_exists('filter_var')) {
            return \true;
        }
        return \false !== filter_var($email, \FILTER_VALIDATE_EMAIL);
    }
    private function updateDependencies(OutputInterface $output): void
    {
        try {
            $updateCommand = $this->getApplication()->find('update');
            $this->getApplication()->resetComposer();
            $updateCommand->run(new ArrayInput([]), $output);
        } catch (\Exception $e) {
            $this->getIO()->writeError('Could not update dependencies. Run `composer update` to see more information.');
        }
    }
    private function runDumpAutoloadCommand(OutputInterface $output): void
    {
        try {
            $command = $this->getApplication()->find('dump-autoload');
            $this->getApplication()->resetComposer();
            $command->run(new ArrayInput([]), $output);
        } catch (\Exception $e) {
            $this->getIO()->writeError('Could not run dump-autoload.');
        }
    }
    /**
     * @param array<string, string|array<string>> $options
     */
    private function hasDependencies(array $options): bool
    {
        $requires = (array) $options['require'];
        $devRequires = isset($options['require-dev']) ? (array) $options['require-dev'] : [];
        return !empty($requires) || !empty($devRequires);
    }
    private function sanitizePackageNameComponent(string $name): string
    {
        $name = Preg::replace('{(?:([a-z])([A-Z])|([A-Z])([A-Z][a-z]))}', '\1\3-\2\4', $name);
        $name = strtolower($name);
        $name = Preg::replace('{^[_.-]+|[_.-]+$|[^a-z0-9_.-]}u', '', $name);
        $name = Preg::replace('{([_.-]){2,}}u', '$1', $name);
        return $name;
    }
    private function getDefaultPackageName(): string
    {
        $git = $this->getGitConfig();
        $cwd = realpath(".");
        $name = basename($cwd);
        $name = $this->sanitizePackageNameComponent($name);
        $vendor = $name;
        if (!empty($_SERVER['COMPOSER_DEFAULT_VENDOR'])) {
            $vendor = $_SERVER['COMPOSER_DEFAULT_VENDOR'];
        } elseif (isset($git['github.user'])) {
            $vendor = $git['github.user'];
        } elseif (!empty($_SERVER['USERNAME'])) {
            $vendor = $_SERVER['USERNAME'];
        } elseif (!empty($_SERVER['USER'])) {
            $vendor = $_SERVER['USER'];
        } elseif (get_current_user()) {
            $vendor = get_current_user();
        }
        $vendor = $this->sanitizePackageNameComponent($vendor);
        return $vendor . '/' . $name;
    }
    private function getDefaultAuthor(): ?string
    {
        $git = $this->getGitConfig();
        if (!empty($_SERVER['COMPOSER_DEFAULT_AUTHOR'])) {
            $author_name = $_SERVER['COMPOSER_DEFAULT_AUTHOR'];
        } elseif (isset($git['user.name'])) {
            $author_name = $git['user.name'];
        }
        if (!empty($_SERVER['COMPOSER_DEFAULT_EMAIL'])) {
            $author_email = $_SERVER['COMPOSER_DEFAULT_EMAIL'];
        } elseif (isset($git['user.email'])) {
            $author_email = $git['user.email'];
        }
        if (isset($author_name, $author_email)) {
            return sprintf('%s <%s>', $author_name, $author_email);
        }
        return null;
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer\Command;

use Composer\Script\Event as ScriptEvent;
use Composer\Script\ScriptEvents;
use Composer\Util\ProcessExecutor;
use Composer\Util\Platform;
use _ContaoManager\Symfony\Component\Console\Command\Command;
use _ContaoManager\Symfony\Component\Console\Input\InputInterface;
use Composer\Console\Input\InputOption;
use Composer\Console\Input\InputArgument;
use _ContaoManager\Symfony\Component\Console\Output\OutputInterface;
/**
 * @author Fabien Potencier <fabien.potencier@gmail.com>
 */
class RunScriptCommand extends \Composer\Command\BaseCommand
{
    /**
     * @var string[] Array with command events
     */
    protected $scriptEvents = [ScriptEvents::PRE_INSTALL_CMD, ScriptEvents::POST_INSTALL_CMD, ScriptEvents::PRE_UPDATE_CMD, ScriptEvents::POST_UPDATE_CMD, ScriptEvents::PRE_STATUS_CMD, ScriptEvents::POST_STATUS_CMD, ScriptEvents::POST_ROOT_PACKAGE_INSTALL, ScriptEvents::POST_CREATE_PROJECT_CMD, ScriptEvents::PRE_ARCHIVE_CMD, ScriptEvents::POST_ARCHIVE_CMD, ScriptEvents::PRE_AUTOLOAD_DUMP, ScriptEvents::POST_AUTOLOAD_DUMP];
    protected function configure(): void
    {
        $this->setName('run-script')->setAliases(['run'])->setDescription('Runs the scripts defined in composer.json')->setDefinition([new InputArgument('script', InputArgument::OPTIONAL, 'Script name to run.', null, function () {
            return array_map(static function ($script) {
                return $script['name'];
            }, $this->getScripts());
        }), new InputArgument('args', InputArgument::IS_ARRAY | InputArgument::OPTIONAL, ''), new InputOption('timeout', null, InputOption::VALUE_REQUIRED, 'Sets script timeout in seconds, or 0 for never.'), new InputOption('dev', null, InputOption::VALUE_NONE, 'Sets the dev mode.'), new InputOption('no-dev', null, InputOption::VALUE_NONE, 'Disables the dev mode.'), new InputOption('list', 'l', InputOption::VALUE_NONE, 'List scripts.')])->setHelp(<<<EOT
The <info>run-script</info> command runs scripts defined in composer.json:

<info>php composer.phar run-script post-update-cmd</info>

Read more at https://getcomposer.org/doc/03-cli.md#run-script-run
EOT
);
    }
    protected function interact(InputInterface $input, OutputInterface $output): void
    {
        $scripts = $this->getScripts();
        if (count($scripts) === 0) {
            return;
        }
        if ($input->getArgument('script') !== null || $input->getOption('list')) {
            return;
        }
        $options = [];
        foreach ($scripts as $script) {
            $options[$script['name']] = $script['description'];
        }
        $io = $this->getIO();
        $script = $io->select('Script to run: ', $options, '', 1, 'Invalid script name "%s"');
        $input->setArgument('script', $script);
    }
    protected function execute(InputInterface $input, OutputInterface $output): int
    {
        if ($input->getOption('list')) {
            return $this->listScripts($output);
        }
        $script = $input->getArgument('script');
        if ($script === null) {
            throw new \RuntimeException('Missing required argument "script"');
        }
        if (!in_array($script, $this->scriptEvents)) {
            if (defined('Composer\Script\ScriptEvents::' . str_replace('-', '_', strtoupper($script)))) {
                throw new \InvalidArgumentException(sprintf('Script "%s" cannot be run with this command', $script));
            }
        }
        $composer = $this->requireComposer();
        $devMode = $input->getOption('dev') || !$input->getOption('no-dev');
        $event = new ScriptEvent($script, $composer, $this->getIO(), $devMode);
        $hasListeners = $composer->getEventDispatcher()->hasEventListeners($event);
        if (!$hasListeners) {
            throw new \InvalidArgumentException(sprintf('Script "%s" is not defined in this package', $script));
        }
        $args = $input->getArgument('args');
        if (null !== $timeout = $input->getOption('timeout')) {
            if (!ctype_digit($timeout)) {
                throw new \RuntimeException('Timeout value must be numeric and positive if defined, or 0 for forever');
            }
            // Override global timeout set before in Composer by environment or config
            ProcessExecutor::setTimeout((int) $timeout);
        }
        Platform::putEnv('COMPOSER_DEV_MODE', $devMode ? '1' : '0');
        return $composer->getEventDispatcher()->dispatchScript($script, $devMode, $args);
    }
    protected function listScripts(OutputInterface $output): int
    {
        $scripts = $this->getScripts();
        if (count($scripts) === 0) {
            return 0;
        }
        $io = $this->getIO();
        $io->writeError('<info>scripts:</info>');
        $table = [];
        foreach ($scripts as $script) {
            $table[] = ['  ' . $script['name'], $script['description']];
        }
        $this->renderTable($table, $output);
        return 0;
    }
    /**
     * @return list<array{name: string, description: string}>
     */
    private function getScripts(): array
    {
        $scripts = $this->requireComposer()->getPackage()->getScripts();
        if (count($scripts) === 0) {
            return [];
        }
        $result = [];
        foreach ($scripts as $name => $script) {
            $description = '';
            try {
                $cmd = $this->getApplication()->find($name);
                $description = $cmd->getDescription();
            } catch (\_ContaoManager\Symfony\Component\Console\Exception\CommandNotFoundException $e) {
                // ignore scripts that have no command associated, like native Composer script listeners
            }
            $result[] = ['name' => $name, 'description' => $description];
        }
        return $result;
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer\Command;

use Composer\Advisory\Auditor;
use Composer\Pcre\Preg;
use Composer\Util\Filesystem;
use Composer\Util\Platform;
use Composer\Util\Silencer;
use _ContaoManager\Symfony\Component\Console\Input\InputInterface;
use Composer\Console\Input\InputArgument;
use _ContaoManager\Symfony\Component\Console\Completion\CompletionInput;
use _ContaoManager\Symfony\Component\Console\Input\InputOption;
use _ContaoManager\Symfony\Component\Console\Output\OutputInterface;
use Composer\Config;
use Composer\Config\JsonConfigSource;
use Composer\Factory;
use Composer\IO\IOInterface;
use Composer\Json\JsonFile;
use Composer\Semver\VersionParser;
use Composer\Package\BasePackage;
/**
 * @author Joshua Estes <Joshua.Estes@iostudio.com>
 * @author Jordi Boggiano <j.boggiano@seld.be>
 */
class ConfigCommand extends \Composer\Command\BaseConfigCommand
{
    /**
     * List of additional configurable package-properties
     *
     * @var string[]
     */
    protected const CONFIGURABLE_PACKAGE_PROPERTIES = ['name', 'type', 'description', 'homepage', 'version', 'minimum-stability', 'prefer-stable', 'keywords', 'license', 'repositories', 'suggest', 'extra'];
    /**
     * @var JsonFile
     */
    protected $authConfigFile;
    /**
     * @var JsonConfigSource
     */
    protected $authConfigSource;
    protected function configure(): void
    {
        $this->setName('config')->setDescription('Sets config options')->setDefinition([new InputOption('global', 'g', InputOption::VALUE_NONE, 'Apply command to the global config file'), new InputOption('editor', 'e', InputOption::VALUE_NONE, 'Open editor'), new InputOption('auth', 'a', InputOption::VALUE_NONE, 'Affect auth config file (only used for --editor)'), new InputOption('unset', null, InputOption::VALUE_NONE, 'Unset the given setting-key'), new InputOption('list', 'l', InputOption::VALUE_NONE, 'List configuration settings'), new InputOption('file', 'f', InputOption::VALUE_REQUIRED, 'If you want to choose a different composer.json or config.json'), new InputOption('absolute', null, InputOption::VALUE_NONE, 'Returns absolute paths when fetching *-dir config values instead of relative'), new InputOption('json', 'j', InputOption::VALUE_NONE, 'JSON decode the setting value, to be used with extra.* keys'), new InputOption('merge', 'm', InputOption::VALUE_NONE, 'Merge the setting value with the current value, to be used with extra.* or audit.ignore[-abandoned] keys in combination with --json'), new InputOption('append', null, InputOption::VALUE_NONE, 'When adding a repository, append it (lowest priority) to the existing ones instead of prepending it (highest priority)'), new InputOption('source', null, InputOption::VALUE_NONE, 'Display where the config value is loaded from'), new InputArgument('setting-key', null, 'Setting key', null, $this->suggestSettingKeys()), new InputArgument('setting-value', InputArgument::IS_ARRAY, 'Setting value')])->setHelp(<<<EOT
This command allows you to edit composer config settings and repositories
in either the local composer.json file or the global config.json file.

Additionally it lets you edit most properties in the local composer.json.

To set a config setting:

    <comment>%command.full_name% bin-dir bin/</comment>

To read a config setting:

    <comment>%command.full_name% bin-dir</comment>
    Outputs: <info>bin</info>

To edit the global config.json file:

    <comment>%command.full_name% --global</comment>

To add a repository:

    <comment>%command.full_name% repositories.foo vcs https://bar.com</comment>

To remove a repository (repo is a short alias for repositories):

    <comment>%command.full_name% --unset repo.foo</comment>

To disable packagist.org:

    <comment>%command.full_name% repo.packagist.org false</comment>

You can alter repositories in the global config.json file by passing in the
<info>--global</info> option.

To add or edit suggested packages you can use:

    <comment>%command.full_name% suggest.package reason for the suggestion</comment>

To add or edit extra properties you can use:

    <comment>%command.full_name% extra.property value</comment>

Or to add a complex value you can use json with:

    <comment>%command.full_name% extra.property --json '{"foo":true, "bar": []}'</comment>

To edit the file in an external editor:

    <comment>%command.full_name% --editor</comment>

To choose your editor you can set the "EDITOR" env variable.

To get a list of configuration values in the file:

    <comment>%command.full_name% --list</comment>

You can always pass more than one option. As an example, if you want to edit the
global config.json file.

    <comment>%command.full_name% --editor --global</comment>

Read more at https://getcomposer.org/doc/03-cli.md#config
EOT
);
    }
    /**
     * @throws \Exception
     */
    protected function initialize(InputInterface $input, OutputInterface $output): void
    {
        parent::initialize($input, $output);
        $authConfigFile = $this->getAuthConfigFile($input, $this->config);
        $this->authConfigFile = new JsonFile($authConfigFile, null, $this->getIO());
        $this->authConfigSource = new JsonConfigSource($this->authConfigFile, \true);
        // Initialize the global file if it's not there, ignoring any warnings or notices
        if ($input->getOption('global') && !$this->authConfigFile->exists()) {
            touch($this->authConfigFile->getPath());
            $this->authConfigFile->write(['bitbucket-oauth' => new \ArrayObject(), 'github-oauth' => new \ArrayObject(), 'gitlab-oauth' => new \ArrayObject(), 'gitlab-token' => new \ArrayObject(), 'http-basic' => new \ArrayObject(), 'bearer' => new \ArrayObject(), 'forgejo-token' => new \ArrayObject()]);
            Silencer::call('chmod', $this->authConfigFile->getPath(), 0600);
        }
    }
    /**
     * @throws \Seld\JsonLint\ParsingException
     */
    protected function execute(InputInterface $input, OutputInterface $output): int
    {
        // Open file in editor
        if (\true === $input->getOption('editor')) {
            $editor = Platform::getEnv('EDITOR');
            if (\false === $editor || '' === $editor) {
                if (Platform::isWindows()) {
                    $editor = 'notepad';
                } else {
                    foreach (['editor', 'vim', 'vi', 'nano', 'pico', 'ed'] as $candidate) {
                        if (exec('which ' . $candidate)) {
                            $editor = $candidate;
                            break;
                        }
                    }
                }
            } else {
                $editor = escapeshellcmd($editor);
            }
            $file = $input->getOption('auth') ? $this->authConfigFile->getPath() : $this->configFile->getPath();
            system($editor . ' ' . $file . (Platform::isWindows() ? '' : ' > `tty`'));
            return 0;
        }
        if (\false === $input->getOption('global')) {
            $this->config->merge($this->configFile->read(), $this->configFile->getPath());
            $this->config->merge(['config' => $this->authConfigFile->exists() ? $this->authConfigFile->read() : []], $this->authConfigFile->getPath());
        }
        $this->getIO()->loadConfiguration($this->config);
        // List the configuration of the file settings
        if (\true === $input->getOption('list')) {
            $this->listConfiguration($this->config->all(), $this->config->raw(), $output, null, $input->getOption('source'));
            return 0;
        }
        $settingKey = $input->getArgument('setting-key');
        if (!is_string($settingKey)) {
            return 0;
        }
        // If the user enters in a config variable, parse it and save to file
        if ([] !== $input->getArgument('setting-value') && $input->getOption('unset')) {
            throw new \RuntimeException('You can not combine a setting value with --unset');
        }
        // show the value if no value is provided
        if ([] === $input->getArgument('setting-value') && !$input->getOption('unset')) {
            $properties = self::CONFIGURABLE_PACKAGE_PROPERTIES;
            $propertiesDefaults = ['type' => 'library', 'description' => '', 'homepage' => '', 'minimum-stability' => 'stable', 'prefer-stable' => \false, 'keywords' => [], 'license' => [], 'suggest' => [], 'extra' => []];
            $rawData = $this->configFile->read();
            $data = $this->config->all();
            $source = $this->config->getSourceOfValue($settingKey);
            if (Preg::isMatch('/^repos?(?:itories)?(?:\.(.+))?/', $settingKey, $matches)) {
                if (!isset($matches[1])) {
                    $value = $data['repositories'] ?? [];
                } else {
                    if (!isset($data['repositories'][$matches[1]])) {
                        throw new \InvalidArgumentException('There is no ' . $matches[1] . ' repository defined');
                    }
                    $value = $data['repositories'][$matches[1]];
                }
            } elseif (strpos($settingKey, '.')) {
                $bits = explode('.', $settingKey);
                if ($bits[0] === 'extra' || $bits[0] === 'suggest') {
                    $data = $rawData;
                } else {
                    $data = $data['config'];
                }
                $match = \false;
                foreach ($bits as $bit) {
                    $key = isset($key) ? $key . '.' . $bit : $bit;
                    $match = \false;
                    if (isset($data[$key])) {
                        $match = \true;
                        $data = $data[$key];
                        unset($key);
                    }
                }
                if (!$match) {
                    throw new \RuntimeException($settingKey . ' is not defined.');
                }
                $value = $data;
            } elseif (isset($data['config'][$settingKey])) {
                $value = $this->config->get($settingKey, $input->getOption('absolute') ? 0 : Config::RELATIVE_PATHS);
                // ensure we get {} output for properties which are objects
                if ($value === []) {
                    $schema = JsonFile::parseJson((string) file_get_contents(JsonFile::COMPOSER_SCHEMA_PATH));
                    if (isset($schema['properties']['config']['properties'][$settingKey]['type']) && in_array('object', (array) $schema['properties']['config']['properties'][$settingKey]['type'], \true)) {
                        $value = new \stdClass();
                    }
                }
            } elseif (isset($rawData[$settingKey]) && in_array($settingKey, $properties, \true)) {
                $value = $rawData[$settingKey];
                $source = $this->configFile->getPath();
            } elseif (isset($propertiesDefaults[$settingKey])) {
                $value = $propertiesDefaults[$settingKey];
                $source = 'defaults';
            } else {
                throw new \RuntimeException($settingKey . ' is not defined');
            }
            if (is_array($value) || is_object($value) || is_bool($value)) {
                $value = JsonFile::encode($value, \JSON_UNESCAPED_SLASHES | \JSON_UNESCAPED_UNICODE);
            }
            $sourceOfConfigValue = '';
            if ($input->getOption('source')) {
                $sourceOfConfigValue = ' (' . $source . ')';
            }
            $this->getIO()->write($value . $sourceOfConfigValue, \true, IOInterface::QUIET);
            return 0;
        }
        $values = $input->getArgument('setting-value');
        // what the user is trying to add/change
        $booleanValidator = static function ($val): bool {
            return in_array($val, ['true', 'false', '1', '0'], \true);
        };
        $booleanNormalizer = static function ($val): bool {
            return $val !== 'false' && (bool) $val;
        };
        // handle config values
        $uniqueConfigValues = ['process-timeout' => ['is_numeric', 'intval'], 'use-include-path' => [$booleanValidator, $booleanNormalizer], 'use-github-api' => [$booleanValidator, $booleanNormalizer], 'preferred-install' => [static function ($val): bool {
            return in_array($val, ['auto', 'source', 'dist'], \true);
        }, static function ($val) {
            return $val;
        }], 'gitlab-protocol' => [static function ($val): bool {
            return in_array($val, ['git', 'http', 'https'], \true);
        }, static function ($val) {
            return $val;
        }], 'store-auths' => [static function ($val): bool {
            return in_array($val, ['true', 'false', 'prompt'], \true);
        }, static function ($val) {
            if ('prompt' === $val) {
                return 'prompt';
            }
            return $val !== 'false' && (bool) $val;
        }], 'notify-on-install' => [$booleanValidator, $booleanNormalizer], 'vendor-dir' => ['is_string', static function ($val) {
            return $val;
        }], 'bin-dir' => ['is_string', static function ($val) {
            return $val;
        }], 'archive-dir' => ['is_string', static function ($val) {
            return $val;
        }], 'archive-format' => ['is_string', static function ($val) {
            return $val;
        }], 'data-dir' => ['is_string', static function ($val) {
            return $val;
        }], 'cache-dir' => ['is_string', static function ($val) {
            return $val;
        }], 'cache-files-dir' => ['is_string', static function ($val) {
            return $val;
        }], 'cache-repo-dir' => ['is_string', static function ($val) {
            return $val;
        }], 'cache-vcs-dir' => ['is_string', static function ($val) {
            return $val;
        }], 'cache-ttl' => ['is_numeric', 'intval'], 'cache-files-ttl' => ['is_numeric', 'intval'], 'cache-files-maxsize' => [static function ($val): bool {
            return Preg::isMatch('/^\s*([0-9.]+)\s*(?:([kmg])(?:i?b)?)?\s*$/i', $val);
        }, static function ($val) {
            return $val;
        }], 'bin-compat' => [static function ($val): bool {
            return in_array($val, ['auto', 'full', 'proxy', 'symlink']);
        }, static function ($val) {
            return $val;
        }], 'discard-changes' => [static function ($val): bool {
            return in_array($val, ['stash', 'true', 'false', '1', '0'], \true);
        }, static function ($val) {
            if ('stash' === $val) {
                return 'stash';
            }
            return $val !== 'false' && (bool) $val;
        }], 'autoloader-suffix' => ['is_string', static function ($val) {
            return $val === 'null' ? null : $val;
        }], 'sort-packages' => [$booleanValidator, $booleanNormalizer], 'optimize-autoloader' => [$booleanValidator, $booleanNormalizer], 'classmap-authoritative' => [$booleanValidator, $booleanNormalizer], 'apcu-autoloader' => [$booleanValidator, $booleanNormalizer], 'prepend-autoloader' => [$booleanValidator, $booleanNormalizer], 'update-with-minimal-changes' => [$booleanValidator, $booleanNormalizer], 'disable-tls' => [$booleanValidator, $booleanNormalizer], 'secure-http' => [$booleanValidator, $booleanNormalizer], 'bump-after-update' => [static function ($val): bool {
            return in_array($val, ['dev', 'no-dev', 'true', 'false', '1', '0'], \true);
        }, static function ($val) {
            if ('dev' === $val || 'no-dev' === $val) {
                return $val;
            }
            return $val !== 'false' && (bool) $val;
        }], 'cafile' => [static function ($val): bool {
            return file_exists($val) && Filesystem::isReadable($val);
        }, static function ($val) {
            return $val === 'null' ? null : $val;
        }], 'capath' => [static function ($val): bool {
            return is_dir($val) && Filesystem::isReadable($val);
        }, static function ($val) {
            return $val === 'null' ? null : $val;
        }], 'github-expose-hostname' => [$booleanValidator, $booleanNormalizer], 'htaccess-protect' => [$booleanValidator, $booleanNormalizer], 'lock' => [$booleanValidator, $booleanNormalizer], 'allow-plugins' => [$booleanValidator, $booleanNormalizer], 'platform-check' => [static function ($val): bool {
            return in_array($val, ['php-only', 'true', 'false', '1', '0'], \true);
        }, static function ($val) {
            if ('php-only' === $val) {
                return 'php-only';
            }
            return $val !== 'false' && (bool) $val;
        }], 'use-parent-dir' => [static function ($val): bool {
            return in_array($val, ['true', 'false', 'prompt'], \true);
        }, static function ($val) {
            if ('prompt' === $val) {
                return 'prompt';
            }
            return $val !== 'false' && (bool) $val;
        }], 'audit.abandoned' => [static function ($val): bool {
            return in_array($val, [Auditor::ABANDONED_IGNORE, Auditor::ABANDONED_REPORT, Auditor::ABANDONED_FAIL], \true);
        }, static function ($val) {
            return $val;
        }], 'audit.ignore-unreachable' => [$booleanValidator, $booleanNormalizer], 'audit.block-insecure' => [$booleanValidator, $booleanNormalizer], 'audit.block-abandoned' => [$booleanValidator, $booleanNormalizer]];
        $multiConfigValues = ['github-protocols' => [static function ($vals) {
            if (!is_array($vals)) {
                return 'array expected';
            }
            foreach ($vals as $val) {
                if (!in_array($val, ['git', 'https', 'ssh'])) {
                    return 'valid protocols include: git, https, ssh';
                }
            }
            return \true;
        }, static function ($vals) {
            return $vals;
        }], 'github-domains' => [static function ($vals) {
            if (!is_array($vals)) {
                return 'array expected';
            }
            return \true;
        }, static function ($vals) {
            return $vals;
        }], 'gitlab-domains' => [static function ($vals) {
            if (!is_array($vals)) {
                return 'array expected';
            }
            return \true;
        }, static function ($vals) {
            return $vals;
        }], 'audit.ignore-severity' => [static function ($vals) {
            if (!is_array($vals)) {
                return 'array expected';
            }
            foreach ($vals as $val) {
                if (!in_array($val, ['low', 'medium', 'high', 'critical'], \true)) {
                    return 'valid severities include: low, medium, high, critical';
                }
            }
            return \true;
        }, static function ($vals) {
            return $vals;
        }]];
        // allow unsetting audit config entirely
        if ($input->getOption('unset') && $settingKey === 'audit') {
            $this->configSource->removeConfigSetting($settingKey);
            return 0;
        }
        if ($input->getOption('unset') && (isset($uniqueConfigValues[$settingKey]) || isset($multiConfigValues[$settingKey]))) {
            if ($settingKey === 'disable-tls' && $this->config->get('disable-tls')) {
                $this->getIO()->writeError('<info>You are now running Composer with SSL/TLS protection enabled.</info>');
            }
            $this->configSource->removeConfigSetting($settingKey);
            return 0;
        }
        if (isset($uniqueConfigValues[$settingKey])) {
            $this->handleSingleValue($settingKey, $uniqueConfigValues[$settingKey], $values, 'addConfigSetting');
            return 0;
        }
        if (isset($multiConfigValues[$settingKey])) {
            $this->handleMultiValue($settingKey, $multiConfigValues[$settingKey], $values, 'addConfigSetting');
            return 0;
        }
        // handle preferred-install per-package config
        if (Preg::isMatch('/^preferred-install\.(.+)/', $settingKey, $matches)) {
            if ($input->getOption('unset')) {
                $this->configSource->removeConfigSetting($settingKey);
                return 0;
            }
            [$validator] = $uniqueConfigValues['preferred-install'];
            if (!$validator($values[0])) {
                throw new \RuntimeException('Invalid value for ' . $settingKey . '. Should be one of: auto, source, or dist');
            }
            $this->configSource->addConfigSetting($settingKey, $values[0]);
            return 0;
        }
        // handle allow-plugins config setting elements true or false to add/remove
        if (Preg::isMatch('{^allow-plugins\.([a-zA-Z0-9/*-]+)}', $settingKey, $matches)) {
            if ($input->getOption('unset')) {
                $this->configSource->removeConfigSetting($settingKey);
                return 0;
            }
            if (\true !== $booleanValidator($values[0])) {
                throw new \RuntimeException(sprintf('"%s" is an invalid value', $values[0]));
            }
            $normalizedValue = $booleanNormalizer($values[0]);
            $this->configSource->addConfigSetting($settingKey, $normalizedValue);
            return 0;
        }
        // handle properties
        $uniqueProps = ['name' => ['is_string', static function ($val) {
            return $val;
        }], 'type' => ['is_string', static function ($val) {
            return $val;
        }], 'description' => ['is_string', static function ($val) {
            return $val;
        }], 'homepage' => ['is_string', static function ($val) {
            return $val;
        }], 'version' => ['is_string', static function ($val) {
            return $val;
        }], 'minimum-stability' => [static function ($val): bool {
            return isset(BasePackage::STABILITIES[VersionParser::normalizeStability($val)]);
        }, static function ($val): string {
            return VersionParser::normalizeStability($val);
        }], 'prefer-stable' => [$booleanValidator, $booleanNormalizer]];
        $multiProps = ['keywords' => [static function ($vals) {
            if (!is_array($vals)) {
                return 'array expected';
            }
            return \true;
        }, static function ($vals) {
            return $vals;
        }], 'license' => [static function ($vals) {
            if (!is_array($vals)) {
                return 'array expected';
            }
            return \true;
        }, static function ($vals) {
            return $vals;
        }]];
        if ($input->getOption('global') && (isset($uniqueProps[$settingKey]) || isset($multiProps[$settingKey]) || strpos($settingKey, 'extra.') === 0)) {
            throw new \InvalidArgumentException('The ' . $settingKey . ' property can not be set in the global config.json file. Use `composer global config` to apply changes to the global composer.json');
        }
        if ($input->getOption('unset') && (isset($uniqueProps[$settingKey]) || isset($multiProps[$settingKey]))) {
            $this->configSource->removeProperty($settingKey);
            return 0;
        }
        if (isset($uniqueProps[$settingKey])) {
            $this->handleSingleValue($settingKey, $uniqueProps[$settingKey], $values, 'addProperty');
            return 0;
        }
        if (isset($multiProps[$settingKey])) {
            $this->handleMultiValue($settingKey, $multiProps[$settingKey], $values, 'addProperty');
            return 0;
        }
        // handle repositories
        if (Preg::isMatchStrictGroups('/^repos?(?:itories)?\.(.+)/', $settingKey, $matches)) {
            if ($input->getOption('unset')) {
                $this->configSource->removeRepository($matches[1]);
                return 0;
            }
            if (2 === count($values)) {
                $this->configSource->addRepository($matches[1], ['type' => $values[0], 'url' => $values[1]], $input->getOption('append'));
                return 0;
            }
            if (1 === count($values)) {
                $value = strtolower($values[0]);
                if (\true === $booleanValidator($value)) {
                    if (\false === $booleanNormalizer($value)) {
                        $this->configSource->addRepository($matches[1], \false, $input->getOption('append'));
                        return 0;
                    }
                } else {
                    $value = JsonFile::parseJson($values[0]);
                    $this->configSource->addRepository($matches[1], $value, $input->getOption('append'));
                    return 0;
                }
            }
            throw new \RuntimeException('You must pass the type and a url. Example: php composer.phar config repositories.foo vcs https://bar.com');
        }
        // handle extra
        if (Preg::isMatch('/^extra\.(.+)/', $settingKey, $matches)) {
            if ($input->getOption('unset')) {
                $this->configSource->removeProperty($settingKey);
                return 0;
            }
            $value = $values[0];
            if ($input->getOption('json')) {
                $value = JsonFile::parseJson($value);
                if ($input->getOption('merge')) {
                    $currentValue = $this->configFile->read();
                    $bits = explode('.', $settingKey);
                    foreach ($bits as $bit) {
                        $currentValue = $currentValue[$bit] ?? null;
                    }
                    if (is_array($currentValue) && is_array($value)) {
                        if (array_is_list($currentValue) && array_is_list($value)) {
                            $value = array_merge($currentValue, $value);
                        } else {
                            $value = $value + $currentValue;
                        }
                    }
                }
            }
            $this->configSource->addProperty($settingKey, $value);
            return 0;
        }
        // handle suggest
        if (Preg::isMatch('/^suggest\.(.+)/', $settingKey, $matches)) {
            if ($input->getOption('unset')) {
                $this->configSource->removeProperty($settingKey);
                return 0;
            }
            $this->configSource->addProperty($settingKey, implode(' ', $values));
            return 0;
        }
        // handle unsetting extra/suggest
        if (in_array($settingKey, ['suggest', 'extra'], \true) && $input->getOption('unset')) {
            $this->configSource->removeProperty($settingKey);
            return 0;
        }
        // handle platform
        if (Preg::isMatch('/^platform\.(.+)/', $settingKey, $matches)) {
            if ($input->getOption('unset')) {
                $this->configSource->removeConfigSetting($settingKey);
                return 0;
            }
            $this->configSource->addConfigSetting($settingKey, $values[0] === 'false' ? \false : $values[0]);
            return 0;
        }
        // handle unsetting platform
        if ($settingKey === 'platform' && $input->getOption('unset')) {
            $this->configSource->removeConfigSetting($settingKey);
            return 0;
        }
        // handle audit.ignore and audit.ignore-abandoned with --merge support
        if (in_array($settingKey, ['audit.ignore', 'audit.ignore-abandoned'], \true)) {
            if ($input->getOption('unset')) {
                $this->configSource->removeConfigSetting($settingKey);
                return 0;
            }
            $value = $values;
            if ($input->getOption('json')) {
                $value = JsonFile::parseJson($values[0]);
                if (!is_array($value)) {
                    throw new \RuntimeException('Expected an array or object for ' . $settingKey);
                }
            }
            if ($input->getOption('merge')) {
                $currentConfig = $this->configFile->read();
                $currentValue = $currentConfig['config']['audit'][str_replace('audit.', '', $settingKey)] ?? null;
                if ($currentValue !== null && is_array($currentValue) && is_array($value)) {
                    if (array_is_list($currentValue) && array_is_list($value)) {
                        // Both are lists, merge them
                        $value = array_merge($currentValue, $value);
                    } elseif (!array_is_list($currentValue) && !array_is_list($value)) {
                        // Both are associative arrays (objects), merge them
                        $value = $value + $currentValue;
                    } else {
                        throw new \RuntimeException('Cannot merge array and object for ' . $settingKey);
                    }
                }
            }
            $this->configSource->addConfigSetting($settingKey, $value);
            return 0;
        }
        // handle auth
        if (Preg::isMatch('/^(bitbucket-oauth|github-oauth|gitlab-oauth|gitlab-token|http-basic|custom-headers|bearer|forgejo-token)\.(.+)/', $settingKey, $matches)) {
            if ($input->getOption('unset')) {
                $this->authConfigSource->removeConfigSetting($matches[1] . '.' . $matches[2]);
                $this->configSource->removeConfigSetting($matches[1] . '.' . $matches[2]);
                return 0;
            }
            if ($matches[1] === 'bitbucket-oauth') {
                if (2 !== count($values)) {
                    throw new \RuntimeException('Expected two arguments (consumer-key, consumer-secret), got ' . count($values));
                }
                $this->configSource->removeConfigSetting($matches[1] . '.' . $matches[2]);
                $this->authConfigSource->addConfigSetting($matches[1] . '.' . $matches[2], ['consumer-key' => $values[0], 'consumer-secret' => $values[1]]);
            } elseif ($matches[1] === 'gitlab-token' && 2 === count($values)) {
                $this->configSource->removeConfigSetting($matches[1] . '.' . $matches[2]);
                $this->authConfigSource->addConfigSetting($matches[1] . '.' . $matches[2], ['username' => $values[0], 'token' => $values[1]]);
            } elseif (in_array($matches[1], ['github-oauth', 'gitlab-oauth', 'gitlab-token', 'bearer'], \true)) {
                if (1 !== count($values)) {
                    throw new \RuntimeException('Too many arguments, expected only one token');
                }
                $this->configSource->removeConfigSetting($matches[1] . '.' . $matches[2]);
                $this->authConfigSource->addConfigSetting($matches[1] . '.' . $matches[2], $values[0]);
            } elseif ($matches[1] === 'http-basic') {
                if (2 !== count($values)) {
                    throw new \RuntimeException('Expected two arguments (username, password), got ' . count($values));
                }
                $this->configSource->removeConfigSetting($matches[1] . '.' . $matches[2]);
                $this->authConfigSource->addConfigSetting($matches[1] . '.' . $matches[2], ['username' => $values[0], 'password' => $values[1]]);
            } elseif ($matches[1] === 'custom-headers') {
                if (count($values) === 0) {
                    throw new \RuntimeException('Expected at least one argument (header), got none');
                }
                // Validate headers format
                $formattedHeaders = [];
                foreach ($values as $header) {
                    if (!is_string($header)) {
                        throw new \RuntimeException('Headers must be strings in "Header-Name: Header-Value" format');
                    }
                    // Check if the header is in correct "Name: Value" format
                    if (!Preg::isMatch('/^[^:]+:\s*.+$/', $header, $headerParts)) {
                        throw new \RuntimeException('Header "' . $header . '" is not in "Header-Name: Header-Value" format');
                    }
                    $formattedHeaders[] = $header;
                }
                $this->configSource->removeConfigSetting($matches[1] . '.' . $matches[2]);
                $this->authConfigSource->addConfigSetting($matches[1] . '.' . $matches[2], $formattedHeaders);
            } elseif ($matches[1] === 'forgejo-token') {
                if (2 !== count($values)) {
                    throw new \RuntimeException('Expected two arguments (username, access token), got ' . count($values));
                }
                $this->configSource->removeConfigSetting($matches[1] . '.' . $matches[2]);
                $this->authConfigSource->addConfigSetting($matches[1] . '.' . $matches[2], ['username' => $values[0], 'token' => $values[1]]);
            }
            return 0;
        }
        // handle script
        if (Preg::isMatch('/^scripts\.(.+)/', $settingKey, $matches)) {
            if ($input->getOption('unset')) {
                $this->configSource->removeProperty($settingKey);
                return 0;
            }
            $this->configSource->addProperty($settingKey, count($values) > 1 ? $values : $values[0]);
            return 0;
        }
        // handle unsetting other top level properties
        if ($input->getOption('unset')) {
            $this->configSource->removeProperty($settingKey);
            return 0;
        }
        throw new \InvalidArgumentException('Setting ' . $settingKey . ' does not exist or is not supported by this command');
    }
    /**
     * @param array{callable, callable} $callbacks Validator and normalizer callbacks
     * @param array<string> $values
     */
    protected function handleSingleValue(string $key, array $callbacks, array $values, string $method): void
    {
        [$validator, $normalizer] = $callbacks;
        if (1 !== count($values)) {
            throw new \RuntimeException('You can only pass one value. Example: php composer.phar config process-timeout 300');
        }
        if (\true !== $validation = $validator($values[0])) {
            throw new \RuntimeException(sprintf('"%s" is an invalid value' . ($validation ? ' (' . $validation . ')' : ''), $values[0]));
        }
        $normalizedValue = $normalizer($values[0]);
        if ($key === 'disable-tls') {
            if (!$normalizedValue && $this->config->get('disable-tls')) {
                $this->getIO()->writeError('<info>You are now running Composer with SSL/TLS protection enabled.</info>');
            } elseif ($normalizedValue && !$this->config->get('disable-tls')) {
                $this->getIO()->writeError('<warning>You are now running Composer with SSL/TLS protection disabled.</warning>');
            }
        }
        call_user_func([$this->configSource, $method], $key, $normalizedValue);
    }
    /**
     * @param array{callable, callable} $callbacks Validator and normalizer callbacks
     * @param array<string> $values
     */
    protected function handleMultiValue(string $key, array $callbacks, array $values, string $method): void
    {
        [$validator, $normalizer] = $callbacks;
        if (\true !== $validation = $validator($values)) {
            throw new \RuntimeException(sprintf('%s is an invalid value' . ($validation ? ' (' . $validation . ')' : ''), json_encode($values)));
        }
        call_user_func([$this->configSource, $method], $key, $normalizer($values));
    }
    /**
     * Display the contents of the file in a pretty formatted way
     *
     * @param array<mixed[]|bool|string> $contents
     * @param array<mixed[]|string>      $rawContents
     */
    protected function listConfiguration(array $contents, array $rawContents, OutputInterface $output, ?string $k = null, bool $showSource = \false): void
    {
        $origK = $k;
        $io = $this->getIO();
        foreach ($contents as $key => $value) {
            if ($k === null && !in_array($key, ['config', 'repositories'])) {
                continue;
            }
            $rawVal = $rawContents[$key] ?? null;
            if (is_array($value) && (!is_numeric(key($value)) || $key === 'repositories' && null === $k)) {
                $k .= Preg::replace('{^config\.}', '', $key . '.');
                $this->listConfiguration($value, $rawVal, $output, $k, $showSource);
                $k = $origK;
                continue;
            }
            if (is_array($value)) {
                $value = array_map(static function ($val) {
                    return is_array($val) ? json_encode($val) : $val;
                }, $value);
                $value = '[' . implode(', ', $value) . ']';
            }
            if (is_bool($value)) {
                $value = var_export($value, \true);
            }
            $source = '';
            if ($showSource) {
                $source = ' (' . $this->config->getSourceOfValue($k . $key) . ')';
            }
            if (null !== $k && 0 === strpos($k, 'repositories')) {
                $link = 'https://getcomposer.org/doc/05-repositories.md';
            } else {
                $id = Preg::replace('{\..*$}', '', $k === '' || $k === null ? (string) $key : $k);
                $id = Preg::replace('{[^a-z0-9]}i', '-', strtolower(trim($id)));
                $id = Preg::replace('{-+}', '-', $id);
                $link = 'https://getcomposer.org/doc/06-config.md#' . $id;
            }
            if (is_string($rawVal) && $rawVal !== $value) {
                $io->write('[<fg=yellow;href=' . $link . '>' . $k . $key . '</>] <info>' . $rawVal . ' (' . $value . ')</info>' . $source, \true, IOInterface::QUIET);
            } else {
                $io->write('[<fg=yellow;href=' . $link . '>' . $k . $key . '</>] <info>' . $value . '</info>' . $source, \true, IOInterface::QUIET);
            }
        }
    }
    /**
     * Suggest setting-keys, while taking given options in account.
     */
    private function suggestSettingKeys(): \Closure
    {
        return function (CompletionInput $input): array {
            if ($input->getOption('list') || $input->getOption('editor') || $input->getOption('auth')) {
                return [];
            }
            // initialize configuration
            $config = Factory::createConfig();
            // load configuration
            $configFile = new JsonFile($this->getComposerConfigFile($input, $config));
            if ($configFile->exists()) {
                $config->merge($configFile->read(), $configFile->getPath());
            }
            // load auth-configuration
            $authConfigFile = new JsonFile($this->getAuthConfigFile($input, $config));
            if ($authConfigFile->exists()) {
                $config->merge(['config' => $authConfigFile->read()], $authConfigFile->getPath());
            }
            // collect all configuration setting-keys
            $rawConfig = $config->raw();
            $keys = array_merge($this->flattenSettingKeys($rawConfig['config']), $this->flattenSettingKeys($rawConfig['repositories'], 'repositories.'));
            // if unsetting …
            if ($input->getOption('unset')) {
                // … keep only the currently customized setting-keys …
                $sources = [$configFile->getPath(), $authConfigFile->getPath()];
                $keys = array_filter($keys, static function (string $key) use ($config, $sources): bool {
                    return in_array($config->getSourceOfValue($key), $sources, \true);
                });
                // … else if showing or setting a value …
            } else {
                // … add all configurable package-properties, no matter if it exist
                $keys = array_merge($keys, self::CONFIGURABLE_PACKAGE_PROPERTIES);
                // it would be nice to distinguish between showing and setting
                // a value, but that makes the implementation much more complex
                // and partially impossible because symfony's implementation
                // does not complete arguments followed by other arguments
            }
            // add all existing configurable package-properties
            if ($configFile->exists()) {
                $properties = array_filter($configFile->read(), static function (string $key): bool {
                    return in_array($key, self::CONFIGURABLE_PACKAGE_PROPERTIES, \true);
                }, \ARRAY_FILTER_USE_KEY);
                $keys = array_merge($keys, $this->flattenSettingKeys($properties));
            }
            // filter settings-keys by completion value
            $completionValue = $input->getCompletionValue();
            if ($completionValue !== '') {
                $keys = array_filter($keys, static function (string $key) use ($completionValue): bool {
                    return str_starts_with($key, $completionValue);
                });
            }
            sort($keys);
            return array_unique($keys);
        };
    }
    /**
     * build a flat list of dot-separated setting-keys from given config
     *
     * @param array<mixed[]|string>  $config
     * @return string[]
     */
    private function flattenSettingKeys(array $config, string $prefix = ''): array
    {
        $keys = [];
        foreach ($config as $key => $value) {
            $keys[] = [$prefix . $key];
            // array-lists must not be added to completion
            // sub-keys of repository-keys must not be added to completion
            if (is_array($value) && !array_is_list($value) && $prefix !== 'repositories.') {
                $keys[] = $this->flattenSettingKeys($value, $prefix . $key . '.');
            }
        }
        return array_merge(...$keys);
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer\Command;

use Composer\Config;
use Composer\Config\JsonConfigSource;
use Composer\Json\JsonFile;
use Composer\Factory;
use Composer\Util\Platform;
use Composer\Util\Silencer;
use _ContaoManager\Symfony\Component\Console\Input\InputInterface;
use _ContaoManager\Symfony\Component\Console\Output\OutputInterface;
abstract class BaseConfigCommand extends \Composer\Command\BaseCommand
{
    /**
     * @var Config
     */
    protected $config;
    /**
     * @var JsonFile
     */
    protected $configFile;
    /**
     * @var JsonConfigSource
     */
    protected $configSource;
    protected function initialize(InputInterface $input, OutputInterface $output): void
    {
        parent::initialize($input, $output);
        if ($input->getOption('global') && null !== $input->getOption('file')) {
            throw new \RuntimeException('--file and --global can not be combined');
        }
        $io = $this->getIO();
        $this->config = Factory::createConfig($io);
        // When using --global flag, set baseDir to home directory for correct absolute path resolution
        if ($input->getOption('global')) {
            $this->config->setBaseDir($this->config->get('home'));
        }
        $configFile = $this->getComposerConfigFile($input, $this->config);
        // Create global composer.json if invoked using `composer global [config-cmd]`
        if (($configFile === 'composer.json' || $configFile === './composer.json') && !file_exists($configFile) && realpath(Platform::getCwd()) === realpath($this->config->get('home'))) {
            file_put_contents($configFile, "{\n}\n");
        }
        $this->configFile = new JsonFile($configFile, null, $io);
        $this->configSource = new JsonConfigSource($this->configFile);
        // Initialize the global file if it's not there, ignoring any warnings or notices
        if ($input->getOption('global') && !$this->configFile->exists()) {
            touch($this->configFile->getPath());
            $this->configFile->write(['config' => new \ArrayObject()]);
            Silencer::call('chmod', $this->configFile->getPath(), 0600);
        }
        if (!$this->configFile->exists()) {
            throw new \RuntimeException(sprintf('File "%s" cannot be found in the current directory', $configFile));
        }
    }
    /**
     * Get the local composer.json, global config.json, or the file passed by the user
     */
    protected function getComposerConfigFile(InputInterface $input, Config $config): string
    {
        return $input->getOption('global') ? $config->get('home') . '/config.json' : $input->getOption('file') ?? Factory::getComposerFile();
    }
    /**
     * Get the local auth.json or global auth.json, or if the user passed in a file to use,
     * the corresponding auth.json
     */
    protected function getAuthConfigFile(InputInterface $input, Config $config): string
    {
        return $input->getOption('global') ? $config->get('home') . '/auth.json' : dirname($this->getComposerConfigFile($input, $config)) . '/auth.json';
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer\Command;

use Composer\Console\Input\InputOption;
use Composer\Json\JsonFile;
use Composer\Package\CompletePackageInterface;
use Composer\Plugin\CommandEvent;
use Composer\Plugin\PluginEvents;
use Composer\Repository\RepositoryUtils;
use Composer\Util\PackageInfo;
use Composer\Util\PackageSorter;
use _ContaoManager\Symfony\Component\Console\Formatter\OutputFormatter;
use _ContaoManager\Symfony\Component\Console\Helper\Table;
use _ContaoManager\Symfony\Component\Console\Input\InputInterface;
use _ContaoManager\Symfony\Component\Console\Output\OutputInterface;
use _ContaoManager\Symfony\Component\Console\Style\SymfonyStyle;
/**
 * @author Benoît Merlet <benoit.merlet@gmail.com>
 */
class LicensesCommand extends \Composer\Command\BaseCommand
{
    protected function configure(): void
    {
        $this->setName('licenses')->setDescription('Shows information about licenses of dependencies')->setDefinition([new InputOption('format', 'f', InputOption::VALUE_REQUIRED, 'Format of the output: text, json or summary', 'text', ['text', 'json', 'summary']), new InputOption('no-dev', null, InputOption::VALUE_NONE, 'Disables search in require-dev packages.'), new InputOption('locked', null, InputOption::VALUE_NONE, 'Shows licenses from the lock file instead of installed packages.')])->setHelp(<<<EOT
The license command displays detailed information about the licenses of
the installed dependencies.

Use --locked to show licenses from composer.lock instead of what's currently
installed in the vendor directory.

Read more at https://getcomposer.org/doc/03-cli.md#licenses
EOT
);
    }
    protected function execute(InputInterface $input, OutputInterface $output): int
    {
        $composer = $this->requireComposer();
        $commandEvent = new CommandEvent(PluginEvents::COMMAND, 'licenses', $input, $output);
        $composer->getEventDispatcher()->dispatch($commandEvent->getName(), $commandEvent);
        $root = $composer->getPackage();
        if ($input->getOption('locked')) {
            if (!$composer->getLocker()->isLocked()) {
                throw new \UnexpectedValueException('Valid composer.json and composer.lock files are required to run this command with --locked');
            }
            $locker = $composer->getLocker();
            $repo = $locker->getLockedRepository(!$input->getOption('no-dev'));
            $packages = $repo->getPackages();
        } else {
            $repo = $composer->getRepositoryManager()->getLocalRepository();
            if ($input->getOption('no-dev')) {
                $packages = RepositoryUtils::filterRequiredPackages($repo->getPackages(), $root);
            } else {
                $packages = $repo->getPackages();
            }
        }
        $packages = PackageSorter::sortPackagesAlphabetically($packages);
        $io = $this->getIO();
        switch ($format = $input->getOption('format')) {
            case 'text':
                $io->write('Name: <comment>' . $root->getPrettyName() . '</comment>');
                $io->write('Version: <comment>' . $root->getFullPrettyVersion() . '</comment>');
                $io->write('Licenses: <comment>' . (implode(', ', $root->getLicense()) ?: 'none') . '</comment>');
                $io->write('Dependencies:');
                $io->write('');
                $table = new Table($output);
                $table->setStyle('compact');
                $table->setHeaders(['Name', 'Version', 'Licenses']);
                foreach ($packages as $package) {
                    $link = PackageInfo::getViewSourceOrHomepageUrl($package);
                    if ($link !== null) {
                        $name = '<href=' . OutputFormatter::escape($link) . '>' . $package->getPrettyName() . '</>';
                    } else {
                        $name = $package->getPrettyName();
                    }
                    $table->addRow([$name, $package->getFullPrettyVersion(), implode(', ', $package instanceof CompletePackageInterface ? $package->getLicense() : []) ?: 'none']);
                }
                $table->render();
                break;
            case 'json':
                $dependencies = [];
                foreach ($packages as $package) {
                    $dependencies[$package->getPrettyName()] = ['version' => $package->getFullPrettyVersion(), 'license' => $package instanceof CompletePackageInterface ? $package->getLicense() : []];
                }
                $io->write(JsonFile::encode(['name' => $root->getPrettyName(), 'version' => $root->getFullPrettyVersion(), 'license' => $root->getLicense(), 'dependencies' => $dependencies]));
                break;
            case 'summary':
                $usedLicenses = [];
                foreach ($packages as $package) {
                    $licenses = $package instanceof CompletePackageInterface ? $package->getLicense() : [];
                    if (count($licenses) === 0) {
                        $licenses[] = 'none';
                    }
                    foreach ($licenses as $licenseName) {
                        if (!isset($usedLicenses[$licenseName])) {
                            $usedLicenses[$licenseName] = 0;
                        }
                        $usedLicenses[$licenseName]++;
                    }
                }
                // Sort licenses so that the most used license will appear first
                arsort($usedLicenses, \SORT_NUMERIC);
                $rows = [];
                foreach ($usedLicenses as $usedLicense => $numberOfDependencies) {
                    $rows[] = [$usedLicense, $numberOfDependencies];
                }
                $symfonyIo = new SymfonyStyle($input, $output);
                $symfonyIo->table(['License', 'Number of dependencies'], $rows);
                break;
            default:
                throw new \RuntimeException(sprintf('Unsupported format "%s".  See help for supported formats.', $format));
        }
        return 0;
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer\Command;

use Composer\Composer;
use Composer\DependencyResolver\Request;
use Composer\Installer;
use Composer\IO\IOInterface;
use Composer\Package\BasePackage;
use Composer\Package\Loader\RootPackageLoader;
use Composer\Package\Version\VersionSelector;
use Composer\Pcre\Preg;
use Composer\Plugin\CommandEvent;
use Composer\Plugin\PluginEvents;
use Composer\Package\Version\VersionParser;
use Composer\Repository\CompositeRepository;
use Composer\Repository\PlatformRepository;
use Composer\Repository\RepositoryInterface;
use Composer\Repository\RepositorySet;
use Composer\Semver\Constraint\MultiConstraint;
use Composer\Semver\Intervals;
use Composer\Util\HttpDownloader;
use Composer\Advisory\Auditor;
use _ContaoManager\Symfony\Component\Console\Helper\Table;
use _ContaoManager\Symfony\Component\Console\Input\InputInterface;
use Composer\Console\Input\InputOption;
use Composer\Console\Input\InputArgument;
use _ContaoManager\Symfony\Component\Console\Output\OutputInterface;
/**
 * @author Jordi Boggiano <j.boggiano@seld.be>
 * @author Nils Adermann <naderman@naderman.de>
 */
class UpdateCommand extends \Composer\Command\BaseCommand
{
    use \Composer\Command\CompletionTrait;
    protected function configure(): void
    {
        $this->setName('update')->setAliases(['u', 'upgrade'])->setDescription('Updates your dependencies to the latest version according to composer.json, and updates the composer.lock file')->setDefinition([new InputArgument('packages', InputArgument::IS_ARRAY | InputArgument::OPTIONAL, 'Packages that should be updated, if not provided all packages are.', null, $this->suggestInstalledPackage(\false)), new InputOption('with', null, InputOption::VALUE_IS_ARRAY | InputOption::VALUE_REQUIRED, 'Temporary version constraint to add, e.g. foo/bar:1.0.0 or foo/bar=1.0.0'), new InputOption('prefer-source', null, InputOption::VALUE_NONE, 'Forces installation from package sources when possible, including VCS information.'), new InputOption('prefer-dist', null, InputOption::VALUE_NONE, 'Forces installation from package dist (default behavior).'), new InputOption('prefer-install', null, InputOption::VALUE_REQUIRED, 'Forces installation from package dist|source|auto (auto chooses source for dev versions, dist for the rest).', null, $this->suggestPreferInstall()), new InputOption('dry-run', null, InputOption::VALUE_NONE, 'Outputs the operations but will not execute anything (implicitly enables --verbose).'), new InputOption('dev', null, InputOption::VALUE_NONE, 'DEPRECATED: Enables installation of require-dev packages (enabled by default, only present for BC).'), new InputOption('no-dev', null, InputOption::VALUE_NONE, 'Disables installation of require-dev packages.'), new InputOption('lock', null, InputOption::VALUE_NONE, 'Overwrites the lock file hash to suppress warning about the lock file being out of date without updating package versions. Package metadata like mirrors and URLs are updated if they changed.'), new InputOption('no-install', null, InputOption::VALUE_NONE, 'Skip the install step after updating the composer.lock file.'), new InputOption('no-audit', null, InputOption::VALUE_NONE, 'Skip the audit step after updating the composer.lock file (can also be set via the COMPOSER_NO_AUDIT=1 env var).'), new InputOption('audit-format', null, InputOption::VALUE_REQUIRED, 'Audit output format. Must be "table", "plain", "json", or "summary".', Auditor::FORMAT_SUMMARY, Auditor::FORMATS), new InputOption('no-security-blocking', null, InputOption::VALUE_NONE, 'Allows installing packages with security advisories or that are abandoned (can also be set via the COMPOSER_NO_SECURITY_BLOCKING=1 env var).'), new InputOption('no-autoloader', null, InputOption::VALUE_NONE, 'Skips autoloader generation'), new InputOption('no-suggest', null, InputOption::VALUE_NONE, 'DEPRECATED: This flag does not exist anymore.'), new InputOption('no-progress', null, InputOption::VALUE_NONE, 'Do not output download progress.'), new InputOption('with-dependencies', 'w', InputOption::VALUE_NONE, 'Update also dependencies of packages in the argument list, except those which are root requirements (can also be set via the COMPOSER_WITH_DEPENDENCIES=1 env var).'), new InputOption('with-all-dependencies', 'W', InputOption::VALUE_NONE, 'Update also dependencies of packages in the argument list, including those which are root requirements (can also be set via the COMPOSER_WITH_ALL_DEPENDENCIES=1 env var).'), new InputOption('verbose', 'v|vv|vvv', InputOption::VALUE_NONE, 'Shows more details including new commits pulled in when updating packages.'), new InputOption('optimize-autoloader', 'o', InputOption::VALUE_NONE, 'Optimize autoloader during autoloader dump.'), new InputOption('classmap-authoritative', 'a', InputOption::VALUE_NONE, 'Autoload classes from the classmap only. Implicitly enables `--optimize-autoloader`.'), new InputOption('apcu-autoloader', null, InputOption::VALUE_NONE, 'Use APCu to cache found/not-found classes.'), new InputOption('apcu-autoloader-prefix', null, InputOption::VALUE_REQUIRED, 'Use a custom prefix for the APCu autoloader cache. Implicitly enables --apcu-autoloader'), new InputOption('ignore-platform-req', null, InputOption::VALUE_REQUIRED | InputOption::VALUE_IS_ARRAY, 'Ignore a specific platform requirement (php & ext- packages).'), new InputOption('ignore-platform-reqs', null, InputOption::VALUE_NONE, 'Ignore all platform requirements (php & ext- packages).'), new InputOption('prefer-stable', null, InputOption::VALUE_NONE, 'Prefer stable versions of dependencies (can also be set via the COMPOSER_PREFER_STABLE=1 env var).'), new InputOption('prefer-lowest', null, InputOption::VALUE_NONE, 'Prefer lowest versions of dependencies (can also be set via the COMPOSER_PREFER_LOWEST=1 env var).'), new InputOption('minimal-changes', 'm', InputOption::VALUE_NONE, 'Only perform absolutely necessary changes to dependencies. If packages cannot be kept at their currently locked version they are updated. For partial updates the allow-listed packages are always updated fully. (can also be set via the COMPOSER_MINIMAL_CHANGES=1 env var).'), new InputOption('patch-only', null, InputOption::VALUE_NONE, 'Only allow patch version updates for currently installed dependencies.'), new InputOption('interactive', 'i', InputOption::VALUE_NONE, 'Interactive interface with autocompletion to select the packages to update.'), new InputOption('root-reqs', null, InputOption::VALUE_NONE, 'Restricts the update to your first degree dependencies.'), new InputOption('bump-after-update', null, InputOption::VALUE_OPTIONAL, 'Runs bump after performing the update.', \false, ['dev', 'no-dev', 'all'])])->setHelp(<<<EOT
The <info>update</info> command reads the composer.json file from the
current directory, processes it, and updates, removes or installs all the
dependencies.

<info>php composer.phar update</info>

To limit the update operation to a few packages, you can list the package(s)
you want to update as such:

<info>php composer.phar update vendor/package1 foo/mypackage [...]</info>

You may also use an asterisk (*) pattern to limit the update operation to package(s)
from a specific vendor:

<info>php composer.phar update vendor/package1 foo/* [...]</info>

To run an update with more restrictive constraints you can use:

<info>php composer.phar update --with vendor/package:1.0.*</info>

To run a partial update with more restrictive constraints you can use the shorthand:

<info>php composer.phar update vendor/package:1.0.*</info>

To select packages names interactively with auto-completion use <info>-i</info>.

Read more at https://getcomposer.org/doc/03-cli.md#update-u-upgrade
EOT
);
    }
    protected function execute(InputInterface $input, OutputInterface $output): int
    {
        $io = $this->getIO();
        if ($input->getOption('dev')) {
            $io->writeError('<warning>You are using the deprecated option "--dev". It has no effect and will break in Composer 3.</warning>');
        }
        if ($input->getOption('no-suggest')) {
            $io->writeError('<warning>You are using the deprecated option "--no-suggest". It has no effect and will break in Composer 3.</warning>');
        }
        $composer = $this->requireComposer();
        if (!HttpDownloader::isCurlEnabled()) {
            $io->writeError('<warning>Composer is operating significantly slower than normal because you do not have the PHP curl extension enabled.</warning>');
        }
        $packages = $input->getArgument('packages');
        $reqs = $this->formatRequirements($input->getOption('with'));
        // extract --with shorthands from the allowlist
        if (count($packages) > 0) {
            $allowlistPackagesWithRequirements = array_filter($packages, static function ($pkg): bool {
                return Preg::isMatch('{\S+[ =:]\S+}', $pkg);
            });
            foreach ($this->formatRequirements($allowlistPackagesWithRequirements) as $package => $constraint) {
                $reqs[$package] = $constraint;
            }
            // replace the foo/bar:req by foo/bar in the allowlist
            foreach ($allowlistPackagesWithRequirements as $package) {
                $packageName = Preg::replace('{^([^ =:]+)[ =:].*$}', '$1', $package);
                $index = array_search($package, $packages);
                $packages[$index] = $packageName;
            }
        }
        $rootPackage = $composer->getPackage();
        $rootPackage->setReferences(RootPackageLoader::extractReferences($reqs, $rootPackage->getReferences()));
        $rootPackage->setStabilityFlags(RootPackageLoader::extractStabilityFlags($reqs, $rootPackage->getMinimumStability(), $rootPackage->getStabilityFlags()));
        $parser = new VersionParser();
        $temporaryConstraints = [];
        $rootRequirements = array_merge($rootPackage->getRequires(), $rootPackage->getDevRequires());
        foreach ($reqs as $package => $constraint) {
            $package = strtolower($package);
            $parsedConstraint = $parser->parseConstraints($constraint);
            $temporaryConstraints[$package] = $parsedConstraint;
            if (isset($rootRequirements[$package]) && !Intervals::haveIntersections($parsedConstraint, $rootRequirements[$package]->getConstraint())) {
                $io->writeError('<error>The temporary constraint "' . $constraint . '" for "' . $package . '" must be a subset of the constraint in your composer.json (' . $rootRequirements[$package]->getPrettyConstraint() . ')</error>');
                $io->write('<info>Run `composer require ' . $package . '` or `composer require ' . $package . ':' . $constraint . '` instead to replace the constraint</info>');
                return self::FAILURE;
            }
        }
        if ($input->getOption('patch-only')) {
            if (!$composer->getLocker()->isLocked()) {
                throw new \InvalidArgumentException('patch-only can only be used with a lock file present');
            }
            foreach ($composer->getLocker()->getLockedRepository(\true)->getCanonicalPackages() as $package) {
                if ($package->isDev()) {
                    continue;
                }
                if (!Preg::isMatch('{^(\d+\.\d+\.\d+)}', $package->getVersion(), $match)) {
                    continue;
                }
                $constraint = $parser->parseConstraints('~' . $match[1]);
                if (isset($temporaryConstraints[$package->getName()])) {
                    $temporaryConstraints[$package->getName()] = MultiConstraint::create([$temporaryConstraints[$package->getName()], $constraint], \true);
                } else {
                    $temporaryConstraints[$package->getName()] = $constraint;
                }
            }
        }
        if ($input->getOption('interactive')) {
            $packages = $this->getPackagesInteractively($io, $input, $output, $composer, $packages);
        }
        if ($input->getOption('root-reqs')) {
            $requires = array_keys($rootPackage->getRequires());
            if (!$input->getOption('no-dev')) {
                $requires = array_merge($requires, array_keys($rootPackage->getDevRequires()));
            }
            if (!empty($packages)) {
                $packages = array_intersect($packages, $requires);
            } else {
                $packages = $requires;
            }
        }
        // the arguments lock/nothing/mirrors are not package names but trigger a mirror update instead
        // they are further mutually exclusive with listing actual package names
        $filteredPackages = array_filter($packages, static function ($package): bool {
            return !in_array($package, ['lock', 'nothing', 'mirrors'], \true);
        });
        $updateMirrors = $input->getOption('lock') || count($filteredPackages) !== count($packages);
        $packages = $filteredPackages;
        if ($updateMirrors && !empty($packages)) {
            $io->writeError('<error>You cannot simultaneously update only a selection of packages and regenerate the lock file metadata.</error>');
            return -1;
        }
        $commandEvent = new CommandEvent(PluginEvents::COMMAND, 'update', $input, $output);
        $composer->getEventDispatcher()->dispatch($commandEvent->getName(), $commandEvent);
        $composer->getInstallationManager()->setOutputProgress(!$input->getOption('no-progress'));
        $install = Installer::create($io, $composer);
        $config = $composer->getConfig();
        [$preferSource, $preferDist] = $this->getPreferredInstallOptions($config, $input);
        $optimize = $input->getOption('optimize-autoloader') || $config->get('optimize-autoloader');
        $authoritative = $input->getOption('classmap-authoritative') || $config->get('classmap-authoritative');
        $apcuPrefix = $input->getOption('apcu-autoloader-prefix');
        $apcu = $apcuPrefix !== null || $input->getOption('apcu-autoloader') || $config->get('apcu-autoloader');
        $minimalChanges = $input->getOption('minimal-changes') || $config->get('update-with-minimal-changes');
        $updateAllowTransitiveDependencies = Request::UPDATE_ONLY_LISTED;
        if ($input->getOption('with-all-dependencies')) {
            $updateAllowTransitiveDependencies = Request::UPDATE_LISTED_WITH_TRANSITIVE_DEPS;
        } elseif ($input->getOption('with-dependencies')) {
            $updateAllowTransitiveDependencies = Request::UPDATE_LISTED_WITH_TRANSITIVE_DEPS_NO_ROOT_REQUIRE;
        }
        $install->setDryRun($input->getOption('dry-run'))->setVerbose($input->getOption('verbose'))->setPreferSource($preferSource)->setPreferDist($preferDist)->setDevMode(!$input->getOption('no-dev'))->setDumpAutoloader(!$input->getOption('no-autoloader'))->setOptimizeAutoloader($optimize)->setClassMapAuthoritative($authoritative)->setApcuAutoloader($apcu, $apcuPrefix)->setUpdate(\true)->setInstall(!$input->getOption('no-install'))->setUpdateMirrors($updateMirrors)->setUpdateAllowList($packages)->setUpdateAllowTransitiveDependencies($updateAllowTransitiveDependencies)->setPlatformRequirementFilter($this->getPlatformRequirementFilter($input))->setPreferStable($input->getOption('prefer-stable'))->setPreferLowest($input->getOption('prefer-lowest'))->setTemporaryConstraints($temporaryConstraints)->setAuditConfig($this->createAuditConfig($composer->getConfig(), $input))->setMinimalUpdate($minimalChanges);
        if ($input->getOption('no-plugins')) {
            $install->disablePlugins();
        }
        $result = $install->run();
        if ($result === 0 && !$input->getOption('lock')) {
            $bumpAfterUpdate = $input->getOption('bump-after-update');
            if (\false === $bumpAfterUpdate) {
                $bumpAfterUpdate = $composer->getConfig()->get('bump-after-update');
            }
            if (\false !== $bumpAfterUpdate) {
                $io->writeError('<info>Bumping dependencies</info>');
                $bumpCommand = new \Composer\Command\BumpCommand();
                $bumpCommand->setComposer($composer);
                $result = $bumpCommand->doBump($io, $bumpAfterUpdate === 'dev', $bumpAfterUpdate === 'no-dev', $input->getOption('dry-run'), $input->getArgument('packages'), '--bump-after-update=dev');
            }
        }
        return $result;
    }
    /**
     * @param array<string> $packages
     * @return array<string>
     */
    private function getPackagesInteractively(IOInterface $io, InputInterface $input, OutputInterface $output, Composer $composer, array $packages): array
    {
        if (!$input->isInteractive()) {
            throw new \InvalidArgumentException('--interactive cannot be used in non-interactive terminals.');
        }
        $platformReqFilter = $this->getPlatformRequirementFilter($input);
        $stabilityFlags = $composer->getPackage()->getStabilityFlags();
        $requires = array_merge($composer->getPackage()->getRequires(), $composer->getPackage()->getDevRequires());
        $filter = \count($packages) > 0 ? BasePackage::packageNamesToRegexp($packages) : null;
        $io->writeError('<info>Loading packages that can be updated...</info>');
        $autocompleterValues = [];
        $installedPackages = $composer->getLocker()->isLocked() ? $composer->getLocker()->getLockedRepository(\true)->getPackages() : $composer->getRepositoryManager()->getLocalRepository()->getPackages();
        $versionSelector = $this->createVersionSelector($composer);
        foreach ($installedPackages as $package) {
            if ($filter !== null && !Preg::isMatch($filter, $package->getName())) {
                continue;
            }
            $currentVersion = $package->getPrettyVersion();
            $constraint = isset($requires[$package->getName()]) ? $requires[$package->getName()]->getPrettyConstraint() : null;
            $stability = isset($stabilityFlags[$package->getName()]) ? (string) array_search($stabilityFlags[$package->getName()], BasePackage::STABILITIES, \true) : $composer->getPackage()->getMinimumStability();
            $latestVersion = $versionSelector->findBestCandidate($package->getName(), $constraint, $stability, $platformReqFilter);
            if ($latestVersion !== \false && ($package->getVersion() !== $latestVersion->getVersion() || $latestVersion->isDev())) {
                $autocompleterValues[$package->getName()] = '<comment>' . $currentVersion . '</comment> => <comment>' . $latestVersion->getPrettyVersion() . '</comment>';
            }
        }
        if (0 === \count($installedPackages)) {
            foreach ($requires as $req => $constraint) {
                if (PlatformRepository::isPlatformPackage($req)) {
                    continue;
                }
                $autocompleterValues[$req] = '';
            }
        }
        if (0 === \count($autocompleterValues)) {
            throw new \RuntimeException('Could not find any package with new versions available');
        }
        $packages = $io->select('Select packages: (Select more than one value separated by comma) ', $autocompleterValues, \false, 1, 'No package named "%s" is installed.', \true);
        $table = new Table($output);
        $table->setHeaders(['Selected packages']);
        foreach ($packages as $package) {
            $table->addRow([$package]);
        }
        $table->render();
        if ($io->askConfirmation(sprintf('Would you like to continue and update the above package%s [<comment>yes</comment>]? ', 1 === count($packages) ? '' : 's'))) {
            return $packages;
        }
        throw new \RuntimeException('Installation aborted.');
    }
    private function createVersionSelector(Composer $composer): VersionSelector
    {
        $repositorySet = new RepositorySet();
        $repositorySet->addRepository(new CompositeRepository(array_filter($composer->getRepositoryManager()->getRepositories(), static function (RepositoryInterface $repository) {
            return !$repository instanceof PlatformRepository;
        })));
        return new VersionSelector($repositorySet);
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer\Command;

use Composer\Factory;
use Composer\Json\JsonFile;
use Composer\Pcre\Preg;
use Composer\Console\Input\InputArgument;
use _ContaoManager\Symfony\Component\Console\Completion\CompletionInput;
use _ContaoManager\Symfony\Component\Console\Input\InputInterface;
use Composer\Console\Input\InputOption;
use _ContaoManager\Symfony\Component\Console\Output\OutputInterface;
/**
 * Manage repositories
 *
 * Examples:
 *  - composer repo list
 *  - composer repo add foo vcs https://github.com/acme/foo
 *  - composer repo remove foo
 *  - composer repo set-url foo https://git.example.org/acme/foo
 *  - composer repo get-url foo
 *  - composer repo disable packagist.org
 *  - composer repo enable packagist.org
 */
class RepositoryCommand extends \Composer\Command\BaseConfigCommand
{
    protected function configure(): void
    {
        $this->setName('repository')->setAliases(['repo'])->setDescription('Manages repositories')->setDefinition([new InputOption('global', 'g', InputOption::VALUE_NONE, 'Apply command to the global config file'), new InputOption('file', 'f', InputOption::VALUE_REQUIRED, 'If you want to choose a different composer.json or config.json'), new InputOption('append', null, InputOption::VALUE_NONE, 'When adding a repository, append it (lower priority) instead of prepending it'), new InputOption('before', null, InputOption::VALUE_REQUIRED, 'When adding a repository, insert it before the given repository name', null, $this->suggestRepoNames()), new InputOption('after', null, InputOption::VALUE_REQUIRED, 'When adding a repository, insert it after the given repository name', null, $this->suggestRepoNames()), new InputArgument('action', InputArgument::OPTIONAL, 'Action to perform: list, add, remove, set-url, get-url, enable, disable', 'list', ['list', 'add', 'remove', 'set-url', 'get-url', 'enable', 'disable']), new InputArgument('name', InputArgument::OPTIONAL, 'Repository name (or special name packagist.org for enable/disable)', null, $this->suggestRepoNames()), new InputArgument('arg1', InputArgument::OPTIONAL, 'Type for add, or new URL for set-url, or JSON config for add', null, $this->suggestTypeForAdd()), new InputArgument('arg2', InputArgument::OPTIONAL, 'URL for add (if not using JSON)')])->setHelp(<<<EOT
This command lets you manage repositories in your composer.json.

Examples:
  composer repo list
  composer repo add foo vcs https://github.com/acme/foo
  composer repo add bar composer https://repo.packagist.com/bar
  composer repo add zips '{"type":"artifact","url":"/path/to/dir/with/zips"}'
  composer repo add baz vcs https://example.org --before foo
  composer repo add qux vcs https://example.org --after bar
  composer repo remove foo
  composer repo set-url foo https://git.example.org/acme/foo
  composer repo get-url foo
  composer repo disable packagist.org
  composer repo enable packagist.org

Use --global/-g to alter the global config.json instead.
Use --file to alter a specific file.
EOT
);
    }
    protected function execute(InputInterface $input, OutputInterface $output): int
    {
        $action = strtolower((string) $input->getArgument('action'));
        $name = $input->getArgument('name');
        $arg1 = $input->getArgument('arg1');
        $arg2 = $input->getArgument('arg2');
        $this->config->merge($this->configFile->read(), $this->configFile->getPath());
        $repos = $this->config->getRepositories();
        switch ($action) {
            case 'list':
            case 'ls':
            case 'show':
                $this->listRepositories($repos);
                return 0;
            case 'add':
                if ($name === null) {
                    throw new \RuntimeException('You must pass a repository name. Example: composer repo add foo vcs https://example.org');
                }
                if ($arg1 === null) {
                    throw new \RuntimeException('You must pass the type and a url, or a JSON string.');
                }
                if (is_string($arg1) && Preg::isMatch('{^\s*\{}', $arg1)) {
                    // JSON config
                    $repoConfig = JsonFile::parseJson($arg1);
                } else {
                    if ($arg2 === null) {
                        throw new \RuntimeException('You must pass the type and a url. Example: composer repo add foo vcs https://example.org');
                    }
                    $repoConfig = ['type' => (string) $arg1, 'url' => (string) $arg2];
                }
                // ordering options
                $before = $input->getOption('before');
                $after = $input->getOption('after');
                if ($before !== null && $after !== null) {
                    throw new \RuntimeException('You can not combine --before and --after');
                }
                if ($before !== null || $after !== null) {
                    if ($repoConfig === \false) {
                        throw new \RuntimeException('Cannot use --before/--after with boolean repository values');
                    }
                    $this->configSource->insertRepository((string) $name, $repoConfig, $before ?? $after, $after !== null ? 1 : 0);
                    return 0;
                }
                $this->configSource->addRepository((string) $name, $repoConfig, (bool) $input->getOption('append'));
                return 0;
            case 'remove':
            case 'rm':
            case 'delete':
                if ($name === null) {
                    throw new \RuntimeException('You must pass the repository name to remove.');
                }
                $this->configSource->removeRepository((string) $name);
                if (in_array($name, ['packagist', 'packagist.org'], \true)) {
                    $this->configSource->addRepository('packagist.org', \false);
                }
                return 0;
            case 'set-url':
            case 'seturl':
                if ($name === null || $arg1 === null) {
                    throw new \RuntimeException('Usage: composer repo set-url <name> <new-url>');
                }
                $this->configSource->setRepositoryUrl($name, $arg1);
                return 0;
            case 'get-url':
            case 'geturl':
                if ($name === null) {
                    throw new \RuntimeException('Usage: composer repo get-url <name>');
                }
                if (isset($repos[$name]) && is_array($repos[$name])) {
                    $url = $repos[$name]['url'] ?? null;
                    if (!is_string($url)) {
                        throw new \InvalidArgumentException('The ' . $name . ' repository does not have a URL');
                    }
                    $this->getIO()->write($url);
                    return 0;
                }
                // try named-list: find entry with matching name
                if (is_array($repos)) {
                    foreach ($repos as $val) {
                        if (is_array($val) && isset($val['name']) && $val['name'] === $name) {
                            $url = $val['url'] ?? null;
                            if (!is_string($url)) {
                                throw new \InvalidArgumentException('The ' . $name . ' repository does not have a URL');
                            }
                            $this->getIO()->write($url);
                            return 0;
                        }
                    }
                }
                throw new \InvalidArgumentException('There is no ' . $name . ' repository defined');
            case 'disable':
                if ($name === null) {
                    throw new \RuntimeException('Usage: composer repo disable packagist.org');
                }
                if (in_array($name, ['packagist', 'packagist.org'], \true)) {
                    // special handling mirrors ConfigCommand behavior
                    $this->configSource->addRepository('packagist.org', \false, (bool) $input->getOption('append'));
                    return 0;
                }
                throw new \RuntimeException('Only packagist.org can be enabled/disabled using this command. Use add/remove for other repositories.');
            case 'enable':
                if ($name === null) {
                    throw new \RuntimeException('Usage: composer repo enable packagist.org');
                }
                if (in_array($name, ['packagist', 'packagist.org'], \true)) {
                    // Remove a false flag by setting packagist.org to true via removing the key
                    // Here we re-add the default by removing overrides
                    $this->configSource->removeRepository('packagist.org');
                    return 0;
                }
                throw new \RuntimeException('Only packagist.org can be enabled/disabled using this command.');
            default:
                throw new \InvalidArgumentException('Unknown action "' . $action . '". Use list, add, remove, set-url, get-url, enable, disable');
        }
    }
    /**
     * @param array<int|string, mixed> $repos
     */
    private function listRepositories(array $repos): void
    {
        $io = $this->getIO();
        $packagistPresent = \false;
        foreach ($repos as $key => $repo) {
            if (isset($repo['type'], $repo['url']) && $repo['type'] === 'composer' && str_ends_with((string) parse_url($repo['url'], \PHP_URL_HOST), 'packagist.org')) {
                $packagistPresent = \true;
                break;
            }
        }
        if (!$packagistPresent) {
            $repos[] = ['packagist.org' => \false];
        }
        if ($repos === []) {
            $io->write('No repositories configured');
            return;
        }
        foreach ($repos as $key => $repo) {
            if ($repo === \false) {
                $io->write('[' . $key . '] <info>disabled</info>');
                continue;
            }
            if (is_array($repo)) {
                if (1 === \count($repo) && \false === current($repo)) {
                    $io->write('[' . array_key_first($repo) . '] <info>disabled</info>');
                    continue;
                }
                $name = $repo['name'] ?? $key;
                $type = $repo['type'] ?? 'unknown';
                $url = $repo['url'] ?? JsonFile::encode($repo);
                $io->write('[' . $name . '] <info>' . $type . '</info> ' . $url);
            }
        }
    }
    private function suggestTypeForAdd(): \Closure
    {
        return static function (CompletionInput $input): array {
            if ($input->getArgument('action') === 'add') {
                return ['composer', 'vcs', 'artifact', 'path'];
            }
            return [];
        };
    }
    private function suggestRepoNames(): \Closure
    {
        return function (CompletionInput $input): array {
            if (in_array($input->getArgument('action'), ['enable', 'disable'], \true)) {
                return ['packagist.org'];
            }
            if (!in_array($input->getArgument('action'), ['remove', 'set-url', 'get-url'], \true)) {
                return [];
            }
            $config = Factory::createConfig();
            $configFile = new JsonFile($this->getComposerConfigFile($input, $config));
            $data = $configFile->read();
            $repos = [];
            foreach ($data['repositories'] ?? [] as $repo) {
                if (isset($repo['name'])) {
                    $repos[] = $repo['name'];
                }
            }
            sort($repos);
            return $repos;
        };
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer\Command;

use _ContaoManager\Symfony\Component\Console\Input\InputInterface;
use Composer\Console\Input\InputOption;
use _ContaoManager\Symfony\Component\Console\Output\OutputInterface;
use Composer\Downloader\ChangeReportInterface;
use Composer\Downloader\DvcsDownloaderInterface;
use Composer\Downloader\VcsCapableDownloaderInterface;
use Composer\Package\Dumper\ArrayDumper;
use Composer\Package\Version\VersionGuesser;
use Composer\Package\Version\VersionParser;
use Composer\Plugin\CommandEvent;
use Composer\Plugin\PluginEvents;
use Composer\Script\ScriptEvents;
use Composer\Util\ProcessExecutor;
/**
 * @author Tiago Ribeiro <tiago.ribeiro@seegno.com>
 * @author Rui Marinho <rui.marinho@seegno.com>
 */
class StatusCommand extends \Composer\Command\BaseCommand
{
    private const EXIT_CODE_ERRORS = 1;
    private const EXIT_CODE_UNPUSHED_CHANGES = 2;
    private const EXIT_CODE_VERSION_CHANGES = 4;
    /**
     * @throws \Symfony\Component\Console\Exception\InvalidArgumentException
     */
    protected function configure(): void
    {
        $this->setName('status')->setDescription('Shows a list of locally modified packages')->setDefinition([new InputOption('verbose', 'v|vv|vvv', InputOption::VALUE_NONE, 'Show modified files for each directory that contains changes.')])->setHelp(<<<EOT
The status command displays a list of dependencies that have
been modified locally.

Read more at https://getcomposer.org/doc/03-cli.md#status
EOT
);
    }
    protected function execute(InputInterface $input, OutputInterface $output): int
    {
        $composer = $this->requireComposer();
        $commandEvent = new CommandEvent(PluginEvents::COMMAND, 'status', $input, $output);
        $composer->getEventDispatcher()->dispatch($commandEvent->getName(), $commandEvent);
        // Dispatch pre-status-command
        $composer->getEventDispatcher()->dispatchScript(ScriptEvents::PRE_STATUS_CMD, \true);
        $exitCode = $this->doExecute($input);
        // Dispatch post-status-command
        $composer->getEventDispatcher()->dispatchScript(ScriptEvents::POST_STATUS_CMD, \true);
        return $exitCode;
    }
    private function doExecute(InputInterface $input): int
    {
        // init repos
        $composer = $this->requireComposer();
        $installedRepo = $composer->getRepositoryManager()->getLocalRepository();
        $dm = $composer->getDownloadManager();
        $im = $composer->getInstallationManager();
        $errors = [];
        $io = $this->getIO();
        $unpushedChanges = [];
        $vcsVersionChanges = [];
        $parser = new VersionParser();
        $guesser = new VersionGuesser($composer->getConfig(), $composer->getLoop()->getProcessExecutor() ?? new ProcessExecutor($io), $parser, $io);
        $dumper = new ArrayDumper();
        // list packages
        foreach ($installedRepo->getCanonicalPackages() as $package) {
            $downloader = $dm->getDownloaderForPackage($package);
            $targetDir = $im->getInstallPath($package);
            if ($targetDir === null) {
                continue;
            }
            if ($downloader instanceof ChangeReportInterface) {
                if (is_link($targetDir)) {
                    $errors[$targetDir] = $targetDir . ' is a symbolic link.';
                }
                if (null !== $changes = $downloader->getLocalChanges($package, $targetDir)) {
                    $errors[$targetDir] = $changes;
                }
            }
            if ($downloader instanceof VcsCapableDownloaderInterface) {
                if ($downloader->getVcsReference($package, $targetDir)) {
                    switch ($package->getInstallationSource()) {
                        case 'source':
                            $previousRef = $package->getSourceReference();
                            break;
                        case 'dist':
                            $previousRef = $package->getDistReference();
                            break;
                        default:
                            $previousRef = null;
                    }
                    $currentVersion = $guesser->guessVersion($dumper->dump($package), $targetDir);
                    if ($previousRef && $currentVersion && $currentVersion['commit'] !== $previousRef && $currentVersion['pretty_version'] !== $previousRef) {
                        $vcsVersionChanges[$targetDir] = ['previous' => ['version' => $package->getPrettyVersion(), 'ref' => $previousRef], 'current' => ['version' => $currentVersion['pretty_version'], 'ref' => $currentVersion['commit']]];
                    }
                }
            }
            if ($downloader instanceof DvcsDownloaderInterface) {
                if ($unpushed = $downloader->getUnpushedChanges($package, $targetDir)) {
                    $unpushedChanges[$targetDir] = $unpushed;
                }
            }
        }
        // output errors/warnings
        if (!$errors && !$unpushedChanges && !$vcsVersionChanges) {
            $io->writeError('<info>No local changes</info>');
            return 0;
        }
        if ($errors) {
            $io->writeError('<error>You have changes in the following dependencies:</error>');
            foreach ($errors as $path => $changes) {
                if ($input->getOption('verbose')) {
                    $indentedChanges = implode("\n", array_map(static function ($line): string {
                        return '    ' . ltrim($line);
                    }, explode("\n", $changes)));
                    $io->write('<info>' . $path . '</info>:');
                    $io->write($indentedChanges);
                } else {
                    $io->write($path);
                }
            }
        }
        if ($unpushedChanges) {
            $io->writeError('<warning>You have unpushed changes on the current branch in the following dependencies:</warning>');
            foreach ($unpushedChanges as $path => $changes) {
                if ($input->getOption('verbose')) {
                    $indentedChanges = implode("\n", array_map(static function ($line): string {
                        return '    ' . ltrim($line);
                    }, explode("\n", $changes)));
                    $io->write('<info>' . $path . '</info>:');
                    $io->write($indentedChanges);
                } else {
                    $io->write($path);
                }
            }
        }
        if ($vcsVersionChanges) {
            $io->writeError('<warning>You have version variations in the following dependencies:</warning>');
            foreach ($vcsVersionChanges as $path => $changes) {
                if ($input->getOption('verbose')) {
                    // If we don't can't find a version, use the ref instead.
                    $currentVersion = $changes['current']['version'] ?: $changes['current']['ref'];
                    $previousVersion = $changes['previous']['version'] ?: $changes['previous']['ref'];
                    if ($io->isVeryVerbose()) {
                        // Output the ref regardless of whether or not it's being used as the version
                        $currentVersion .= sprintf(' (%s)', $changes['current']['ref']);
                        $previousVersion .= sprintf(' (%s)', $changes['previous']['ref']);
                    }
                    $io->write('<info>' . $path . '</info>:');
                    $io->write(sprintf('    From <comment>%s</comment> to <comment>%s</comment>', $previousVersion, $currentVersion));
                } else {
                    $io->write($path);
                }
            }
        }
        if (($errors || $unpushedChanges || $vcsVersionChanges) && !$input->getOption('verbose')) {
            $io->writeError('Use --verbose (-v) to see a list of files');
        }
        return ($errors ? self::EXIT_CODE_ERRORS : 0) + ($unpushedChanges ? self::EXIT_CODE_UNPUSHED_CHANGES : 0) + ($vcsVersionChanges ? self::EXIT_CODE_VERSION_CHANGES : 0);
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer\Command;

use Composer\Package\Link;
use Composer\Package\Package;
use Composer\Package\PackageInterface;
use Composer\Package\CompletePackageInterface;
use Composer\Package\RootPackage;
use Composer\Repository\InstalledArrayRepository;
use Composer\Repository\CompositeRepository;
use Composer\Repository\RootPackageRepository;
use Composer\Repository\InstalledRepository;
use Composer\Repository\PlatformRepository;
use Composer\Repository\RepositoryFactory;
use Composer\Plugin\CommandEvent;
use Composer\Plugin\PluginEvents;
use Composer\Semver\Constraint\Bound;
use _ContaoManager\Symfony\Component\Console\Formatter\OutputFormatter;
use _ContaoManager\Symfony\Component\Console\Formatter\OutputFormatterStyle;
use Composer\Package\Version\VersionParser;
use _ContaoManager\Symfony\Component\Console\Input\InputInterface;
use _ContaoManager\Symfony\Component\Console\Output\OutputInterface;
use Composer\Util\PackageInfo;
/**
 * Base implementation for commands mapping dependency relationships.
 *
 * @author Niels Keurentjes <niels.keurentjes@omines.com>
 */
abstract class BaseDependencyCommand extends \Composer\Command\BaseCommand
{
    protected const ARGUMENT_PACKAGE = 'package';
    protected const ARGUMENT_CONSTRAINT = 'version';
    protected const OPTION_RECURSIVE = 'recursive';
    protected const OPTION_TREE = 'tree';
    /** @var string[] */
    protected $colors;
    /**
     * Execute the command.
     *
     * @param  bool            $inverted Whether to invert matching process (why-not vs why behaviour)
     * @return int             Exit code of the operation.
     */
    protected function doExecute(InputInterface $input, OutputInterface $output, bool $inverted = \false): int
    {
        // Emit command event on startup
        $composer = $this->requireComposer();
        $commandEvent = new CommandEvent(PluginEvents::COMMAND, $this->getName(), $input, $output);
        $composer->getEventDispatcher()->dispatch($commandEvent->getName(), $commandEvent);
        $repos = [];
        $repos[] = new RootPackageRepository(clone $composer->getPackage());
        if ($input->getOption('locked')) {
            $locker = $composer->getLocker();
            if (!$locker->isLocked()) {
                throw new \UnexpectedValueException('A valid composer.lock file is required to run this command with --locked');
            }
            $repos[] = $locker->getLockedRepository(\true);
            $repos[] = new PlatformRepository([], $locker->getPlatformOverrides());
        } else {
            $localRepo = $composer->getRepositoryManager()->getLocalRepository();
            $rootPkg = $composer->getPackage();
            if (count($localRepo->getPackages()) === 0 && (count($rootPkg->getRequires()) > 0 || count($rootPkg->getDevRequires()) > 0)) {
                $output->writeln('<warning>No dependencies installed. Try running composer install or update, or use --locked.</warning>');
                return 1;
            }
            $repos[] = $localRepo;
            $platformOverrides = $composer->getConfig()->get('platform') ?: [];
            $repos[] = new PlatformRepository([], $platformOverrides);
        }
        $installedRepo = new InstalledRepository($repos);
        // Parse package name and constraint
        $needle = $input->getArgument(self::ARGUMENT_PACKAGE);
        $textConstraint = $input->hasArgument(self::ARGUMENT_CONSTRAINT) ? $input->getArgument(self::ARGUMENT_CONSTRAINT) : '*';
        // Find packages that are or provide the requested package first
        $packages = $installedRepo->findPackagesWithReplacersAndProviders($needle);
        if (empty($packages)) {
            throw new \InvalidArgumentException(sprintf('Could not find package "%s" in your project', $needle));
        }
        // If the version we ask for is not installed then we need to locate it in remote repos and add it.
        // This is needed for why-not to resolve conflicts from an uninstalled version against installed packages.
        $matchedPackage = $installedRepo->findPackage($needle, $textConstraint);
        if (!$matchedPackage) {
            $defaultRepos = new CompositeRepository(RepositoryFactory::defaultRepos($this->getIO(), $composer->getConfig(), $composer->getRepositoryManager()));
            if ($match = $defaultRepos->findPackage($needle, $textConstraint)) {
                $installedRepo->addRepository(new InstalledArrayRepository([clone $match]));
            } elseif (PlatformRepository::isPlatformPackage($needle)) {
                $parser = new VersionParser();
                $constraint = $parser->parseConstraints($textConstraint);
                if ($constraint->getLowerBound() !== Bound::zero()) {
                    $tempPlatformPkg = new Package($needle, $constraint->getLowerBound()->getVersion(), $constraint->getLowerBound()->getVersion());
                    $installedRepo->addRepository(new InstalledArrayRepository([$tempPlatformPkg]));
                }
            } else {
                $this->getIO()->writeError('<error>Package "' . $needle . '" could not be found with constraint "' . $textConstraint . '", results below will most likely be incomplete.</error>');
            }
        } elseif (PlatformRepository::isPlatformPackage($needle)) {
            $extraNotice = '';
            if (($matchedPackage->getExtra()['config.platform'] ?? \false) === \true) {
                $extraNotice = ' (version provided by config.platform)';
            }
            $this->getIO()->writeError('<info>Package "' . $needle . ' ' . $textConstraint . '" found in version "' . $matchedPackage->getPrettyVersion() . '"' . $extraNotice . '.</info>');
        } elseif ($inverted) {
            $this->getIO()->write('<comment>Package "' . $needle . '" ' . $matchedPackage->getPrettyVersion() . ' is already installed! To find out why, run `composer why ' . $needle . '`</comment>');
            return 0;
        }
        // Include replaced packages for inverted lookups as they are then the actual starting point to consider
        $needles = [$needle];
        if ($inverted) {
            foreach ($packages as $package) {
                $needles = array_merge($needles, array_map(static function (Link $link): string {
                    return $link->getTarget();
                }, $package->getReplaces()));
            }
        }
        // Parse constraint if one was supplied
        if ('*' !== $textConstraint) {
            $versionParser = new VersionParser();
            $constraint = $versionParser->parseConstraints($textConstraint);
        } else {
            $constraint = null;
        }
        // Parse rendering options
        $renderTree = $input->getOption(self::OPTION_TREE);
        $recursive = $renderTree || $input->getOption(self::OPTION_RECURSIVE);
        $return = $inverted ? 1 : 0;
        // Resolve dependencies
        $results = $installedRepo->getDependents($needles, $constraint, $inverted, $recursive);
        if (empty($results)) {
            $extra = null !== $constraint ? sprintf(' in versions %smatching %s', $inverted ? 'not ' : '', $textConstraint) : '';
            $this->getIO()->writeError(sprintf('<info>There is no installed package depending on "%s"%s</info>', $needle, $extra));
            $return = $inverted ? 0 : 1;
        } elseif ($renderTree) {
            $this->initStyles($output);
            $root = $packages[0];
            $this->getIO()->write(sprintf('<info>%s</info> %s %s', $root->getPrettyName(), $root->getPrettyVersion(), $root instanceof CompletePackageInterface ? $root->getDescription() : ''));
            $this->printTree($results);
        } else {
            $this->printTable($output, $results);
        }
        if ($inverted && $input->hasArgument(self::ARGUMENT_CONSTRAINT) && !PlatformRepository::isPlatformPackage($needle)) {
            $composerCommand = 'update';
            foreach ($composer->getPackage()->getRequires() as $rootRequirement) {
                if ($rootRequirement->getTarget() === $needle) {
                    $composerCommand = 'require';
                    break;
                }
            }
            foreach ($composer->getPackage()->getDevRequires() as $rootRequirement) {
                if ($rootRequirement->getTarget() === $needle) {
                    $composerCommand = 'require --dev';
                    break;
                }
            }
            $this->getIO()->writeError('Not finding what you were looking for? Try calling `composer ' . $composerCommand . ' "' . $needle . ':' . $textConstraint . '" --dry-run` to get another view on the problem.');
        }
        return $return;
    }
    /**
     * Assembles and prints a bottom-up table of the dependencies.
     *
     * @param array{PackageInterface, Link, array<mixed>|false}[] $results
     */
    protected function printTable(OutputInterface $output, array $results): void
    {
        $table = [];
        $doubles = [];
        do {
            $queue = [];
            $rows = [];
            foreach ($results as $result) {
                /**
                 * @var PackageInterface $package
                 * @var Link             $link
                 */
                [$package, $link, $children] = $result;
                $unique = (string) $link;
                if (isset($doubles[$unique])) {
                    continue;
                }
                $doubles[$unique] = \true;
                $version = $package->getPrettyVersion() === RootPackage::DEFAULT_PRETTY_VERSION ? '-' : $package->getPrettyVersion();
                $packageUrl = PackageInfo::getViewSourceOrHomepageUrl($package);
                $nameWithLink = $packageUrl !== null ? '<href=' . OutputFormatter::escape($packageUrl) . '>' . $package->getPrettyName() . '</>' : $package->getPrettyName();
                $rows[] = [$nameWithLink, $version, $link->getDescription(), sprintf('%s (%s)', $link->getTarget(), $link->getPrettyConstraint())];
                if (is_array($children)) {
                    $queue = array_merge($queue, $children);
                }
            }
            $results = $queue;
            $table = array_merge($rows, $table);
        } while (\count($results) > 0);
        $this->renderTable($table, $output);
    }
    /**
     * Init styles for tree
     */
    protected function initStyles(OutputInterface $output): void
    {
        $this->colors = ['green', 'yellow', 'cyan', 'magenta', 'blue'];
        foreach ($this->colors as $color) {
            $style = new OutputFormatterStyle($color);
            $output->getFormatter()->setStyle($color, $style);
        }
    }
    /**
     * Recursively prints a tree of the selected results.
     *
     * @param array{PackageInterface, Link, array<mixed>|false}[] $results Results to be printed at this level.
     * @param string  $prefix  Prefix of the current tree level.
     * @param int     $level   Current level of recursion.
     */
    protected function printTree(array $results, string $prefix = '', int $level = 1): void
    {
        $count = count($results);
        $idx = 0;
        foreach ($results as $result) {
            [$package, $link, $children] = $result;
            $color = $this->colors[$level % count($this->colors)];
            $prevColor = $this->colors[($level - 1) % count($this->colors)];
            $isLast = ++$idx === $count;
            $versionText = $package->getPrettyVersion() === RootPackage::DEFAULT_PRETTY_VERSION ? '' : $package->getPrettyVersion();
            $packageUrl = PackageInfo::getViewSourceOrHomepageUrl($package);
            $nameWithLink = $packageUrl !== null ? '<href=' . OutputFormatter::escape($packageUrl) . '>' . $package->getPrettyName() . '</>' : $package->getPrettyName();
            $packageText = rtrim(sprintf('<%s>%s</%1$s> %s', $color, $nameWithLink, $versionText));
            $linkText = sprintf('%s <%s>%s</%2$s> %s', $link->getDescription(), $prevColor, $link->getTarget(), $link->getPrettyConstraint());
            $circularWarn = $children === \false ? '(circular dependency aborted here)' : '';
            $this->writeTreeLine(rtrim(sprintf("%s%s%s (%s) %s", $prefix, $isLast ? '└──' : '├──', $packageText, $linkText, $circularWarn)));
            if (is_array($children)) {
                $this->printTree($children, $prefix . ($isLast ? '   ' : '│  '), $level + 1);
            }
        }
    }
    private function writeTreeLine(string $line): void
    {
        $io = $this->getIO();
        if (!$io->isDecorated()) {
            $line = str_replace(['└', '├', '──', '│'], ['`-', '|-', '-', '|'], $line);
        }
        $io->write($line);
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer\Command;

use _ContaoManager\Symfony\Component\Console\Input\InputInterface;
use _ContaoManager\Symfony\Component\Console\Output\OutputInterface;
use Composer\Console\Input\InputArgument;
use Composer\Console\Input\InputOption;
/**
 * @author Niels Keurentjes <niels.keurentjes@omines.com>
 */
class DependsCommand extends \Composer\Command\BaseDependencyCommand
{
    use \Composer\Command\CompletionTrait;
    /**
     * Configure command metadata.
     */
    protected function configure(): void
    {
        $this->setName('depends')->setAliases(['why'])->setDescription('Shows which packages cause the given package to be installed')->setDefinition([new InputArgument(self::ARGUMENT_PACKAGE, InputArgument::REQUIRED, 'Package to inspect', null, $this->suggestInstalledPackage(\true, \true)), new InputOption(self::OPTION_RECURSIVE, 'r', InputOption::VALUE_NONE, 'Recursively resolves up to the root package'), new InputOption(self::OPTION_TREE, 't', InputOption::VALUE_NONE, 'Prints the results as a nested tree'), new InputOption('locked', null, InputOption::VALUE_NONE, 'Read dependency information from composer.lock')])->setHelp(<<<EOT
Displays detailed information about where a package is referenced.

<info>php composer.phar depends composer/composer</info>

Read more at https://getcomposer.org/doc/03-cli.md#depends-why
EOT
);
    }
    protected function execute(InputInterface $input, OutputInterface $output): int
    {
        return parent::doExecute($input, $output);
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer\Command;

use _ContaoManager\Symfony\Component\Console\Input\InputInterface;
use _ContaoManager\Symfony\Component\Console\Output\OutputInterface;
use Composer\Console\Input\InputArgument;
use Composer\Console\Input\InputOption;
/**
 * @author Niels Keurentjes <niels.keurentjes@omines.com>
 */
class ProhibitsCommand extends \Composer\Command\BaseDependencyCommand
{
    use \Composer\Command\CompletionTrait;
    /**
     * Configure command metadata.
     */
    protected function configure(): void
    {
        $this->setName('prohibits')->setAliases(['why-not'])->setDescription('Shows which packages prevent the given package from being installed')->setDefinition([new InputArgument(self::ARGUMENT_PACKAGE, InputArgument::REQUIRED, 'Package to inspect', null, $this->suggestAvailablePackage()), new InputArgument(self::ARGUMENT_CONSTRAINT, InputArgument::REQUIRED, 'Version constraint, which version you expected to be installed'), new InputOption(self::OPTION_RECURSIVE, 'r', InputOption::VALUE_NONE, 'Recursively resolves up to the root package'), new InputOption(self::OPTION_TREE, 't', InputOption::VALUE_NONE, 'Prints the results as a nested tree'), new InputOption('locked', null, InputOption::VALUE_NONE, 'Read dependency information from composer.lock')])->setHelp(<<<EOT
Displays detailed information about why a package cannot be installed.

<info>php composer.phar prohibits composer/composer</info>

Read more at https://getcomposer.org/doc/03-cli.md#prohibits-why-not
EOT
);
    }
    protected function execute(InputInterface $input, OutputInterface $output): int
    {
        return parent::doExecute($input, $output, \true);
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer\Command;

use Composer\Package\Link;
use Composer\Semver\Constraint\Constraint;
use _ContaoManager\Symfony\Component\Console\Input\InputInterface;
use Composer\Console\Input\InputOption;
use _ContaoManager\Symfony\Component\Console\Output\OutputInterface;
use Composer\Repository\PlatformRepository;
use Composer\Repository\RootPackageRepository;
use Composer\Repository\InstalledRepository;
use Composer\Json\JsonFile;
class CheckPlatformReqsCommand extends \Composer\Command\BaseCommand
{
    protected function configure(): void
    {
        $this->setName('check-platform-reqs')->setDescription('Check that platform requirements are satisfied')->setDefinition([new InputOption('no-dev', null, InputOption::VALUE_NONE, 'Disables checking of require-dev packages requirements.'), new InputOption('lock', null, InputOption::VALUE_NONE, 'Checks requirements only from the lock file, not from installed packages.'), new InputOption('format', 'f', InputOption::VALUE_REQUIRED, 'Format of the output: text or json', 'text', ['json', 'text'])])->setHelp(<<<EOT
Checks that your PHP and extensions versions match the platform requirements of the installed packages.

Unlike update/install, this command will ignore config.platform settings and check the real platform packages so you can be certain you have the required platform dependencies.

<info>php composer.phar check-platform-reqs</info>

EOT
);
    }
    protected function execute(InputInterface $input, OutputInterface $output): int
    {
        $composer = $this->requireComposer();
        $requires = [];
        $removePackages = [];
        if ($input->getOption('lock')) {
            $this->getIO()->writeError('<info>Checking ' . ($input->getOption('no-dev') ? 'non-dev ' : '') . 'platform requirements using the lock file</info>');
            $installedRepo = $composer->getLocker()->getLockedRepository(!$input->getOption('no-dev'));
        } else {
            $installedRepo = $composer->getRepositoryManager()->getLocalRepository();
            // fallback to lockfile if installed repo is empty
            if (!$installedRepo->getPackages()) {
                $this->getIO()->writeError('<warning>No vendor dir present, checking ' . ($input->getOption('no-dev') ? 'non-dev ' : '') . 'platform requirements from the lock file</warning>');
                $installedRepo = $composer->getLocker()->getLockedRepository(!$input->getOption('no-dev'));
            } else {
                if ($input->getOption('no-dev')) {
                    $removePackages = $installedRepo->getDevPackageNames();
                }
                $this->getIO()->writeError('<info>Checking ' . ($input->getOption('no-dev') ? 'non-dev ' : '') . 'platform requirements for packages in the vendor dir</info>');
            }
        }
        if (!$input->getOption('no-dev')) {
            foreach ($composer->getPackage()->getDevRequires() as $require => $link) {
                $requires[$require] = [$link];
            }
        }
        $installedRepo = new InstalledRepository([$installedRepo, new RootPackageRepository(clone $composer->getPackage())]);
        foreach ($installedRepo->getPackages() as $package) {
            if (in_array($package->getName(), $removePackages, \true)) {
                continue;
            }
            foreach ($package->getRequires() as $require => $link) {
                $requires[$require][] = $link;
            }
        }
        ksort($requires);
        $installedRepo->addRepository(new PlatformRepository([], []));
        $results = [];
        $exitCode = 0;
        /**
         * @var Link[] $links
         */
        foreach ($requires as $require => $links) {
            if (PlatformRepository::isPlatformPackage($require)) {
                $candidates = $installedRepo->findPackagesWithReplacersAndProviders($require);
                if ($candidates) {
                    $reqResults = [];
                    foreach ($candidates as $candidate) {
                        $candidateConstraint = null;
                        if ($candidate->getName() === $require) {
                            $candidateConstraint = new Constraint('=', $candidate->getVersion());
                            $candidateConstraint->setPrettyString($candidate->getPrettyVersion());
                        } else {
                            foreach (array_merge($candidate->getProvides(), $candidate->getReplaces()) as $link) {
                                if ($link->getTarget() === $require) {
                                    $candidateConstraint = $link->getConstraint();
                                    break;
                                }
                            }
                        }
                        // safety check for phpstan, but it should not be possible to get a candidate out of findPackagesWithReplacersAndProviders without a constraint matching $require
                        if (!$candidateConstraint) {
                            continue;
                        }
                        foreach ($links as $link) {
                            if (!$link->getConstraint()->matches($candidateConstraint)) {
                                $reqResults[] = [$candidate->getName() === $require ? $candidate->getPrettyName() : $require, $candidateConstraint->getPrettyString(), $link, '<error>failed</error>', $candidate->getName() === $require ? '' : '<comment>provided by ' . $candidate->getPrettyName() . '</comment>'];
                                // skip to next candidate
                                continue 2;
                            }
                        }
                        $results[] = [$candidate->getName() === $require ? $candidate->getPrettyName() : $require, $candidateConstraint->getPrettyString(), null, '<info>success</info>', $candidate->getName() === $require ? '' : '<comment>provided by ' . $candidate->getPrettyName() . '</comment>'];
                        // candidate matched, skip to next requirement
                        continue 2;
                    }
                    // show the first error from every failed candidate
                    $results = array_merge($results, $reqResults);
                    $exitCode = max($exitCode, 1);
                    continue;
                }
                $results[] = [$require, 'n/a', $links[0], '<error>missing</error>', ''];
                $exitCode = max($exitCode, 2);
            }
        }
        $this->printTable($output, $results, $input->getOption('format'));
        return $exitCode;
    }
    /**
     * @param mixed[] $results
     */
    protected function printTable(OutputInterface $output, array $results, string $format): void
    {
        $rows = [];
        foreach ($results as $result) {
            /**
             * @var Link|null $link
             */
            [$platformPackage, $version, $link, $status, $provider] = $result;
            if ('json' === $format) {
                $rows[] = ["name" => $platformPackage, "version" => $version, "status" => strip_tags($status), "failed_requirement" => $link instanceof Link ? ['source' => $link->getSource(), 'type' => $link->getDescription(), 'target' => $link->getTarget(), 'constraint' => $link->getPrettyConstraint()] : null, "provider" => $provider === '' ? null : strip_tags($provider)];
            } else {
                $rows[] = [$platformPackage, $version, $link, $link ? sprintf('%s %s %s (%s)', $link->getSource(), $link->getDescription(), $link->getTarget(), $link->getPrettyConstraint()) : '', rtrim($status . ' ' . $provider)];
            }
        }
        if ('json' === $format) {
            $this->getIO()->write(JsonFile::encode($rows));
        } else {
            $this->renderTable($rows, $output);
        }
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer\Command;

use Composer\Composer;
use Composer\Factory;
use Composer\Config;
use Composer\Pcre\Preg;
use Composer\Util\Filesystem;
use Composer\Util\Platform;
use Composer\SelfUpdate\Keys;
use Composer\SelfUpdate\Versions;
use Composer\IO\IOInterface;
use Composer\Downloader\FilesystemException;
use Composer\Downloader\TransportException;
use Phar;
use _ContaoManager\Symfony\Component\Console\Input\InputInterface;
use Composer\Console\Input\InputOption;
use Composer\Console\Input\InputArgument;
use _ContaoManager\Symfony\Component\Console\Output\OutputInterface;
use _ContaoManager\Symfony\Component\Finder\Finder;
/**
 * @author Igor Wiedler <igor@wiedler.ch>
 * @author Kevin Ran <kran@adobe.com>
 * @author Jordi Boggiano <j.boggiano@seld.be>
 */
class SelfUpdateCommand extends \Composer\Command\BaseCommand
{
    private const HOMEPAGE = 'getcomposer.org';
    private const OLD_INSTALL_EXT = '-old.phar';
    protected function configure(): void
    {
        $this->setName('self-update')->setAliases(['selfupdate'])->setDescription('Updates composer.phar to the latest version')->setDefinition([new InputOption('rollback', 'r', InputOption::VALUE_NONE, 'Revert to an older installation of composer'), new InputOption('clean-backups', null, InputOption::VALUE_NONE, 'Delete old backups during an update. This makes the current version of composer the only backup available after the update'), new InputArgument('version', InputArgument::OPTIONAL, 'The version to update to'), new InputOption('no-progress', null, InputOption::VALUE_NONE, 'Do not output download progress.'), new InputOption('update-keys', null, InputOption::VALUE_NONE, 'Prompt user for a key update'), new InputOption('stable', null, InputOption::VALUE_NONE, 'Force an update to the stable channel'), new InputOption('preview', null, InputOption::VALUE_NONE, 'Force an update to the preview channel'), new InputOption('snapshot', null, InputOption::VALUE_NONE, 'Force an update to the snapshot channel'), new InputOption('1', null, InputOption::VALUE_NONE, 'Force an update to the stable channel, but only use 1.x versions'), new InputOption('2', null, InputOption::VALUE_NONE, 'Force an update to the stable channel, but only use 2.x versions'), new InputOption('2.2', null, InputOption::VALUE_NONE, 'Force an update to the stable channel, but only use 2.2.x LTS versions'), new InputOption('set-channel-only', null, InputOption::VALUE_NONE, 'Only store the channel as the default one and then exit')])->setHelp(<<<EOT
The <info>self-update</info> command checks getcomposer.org for newer
versions of composer and if found, installs the latest.

<info>php composer.phar self-update</info>

Read more at https://getcomposer.org/doc/03-cli.md#self-update-selfupdate
EOT
);
    }
    /**
     * @throws FilesystemException
     */
    protected function execute(InputInterface $input, OutputInterface $output): int
    {
        if (strpos(__FILE__, 'phar:') !== 0) {
            if (str_contains(strtr(__DIR__, '\\', '/'), 'vendor/composer/composer')) {
                $projDir = dirname(__DIR__, 6);
                $output->writeln('<error>This instance of Composer does not have the self-update command.</error>');
                $output->writeln('<comment>You are running Composer installed as a package in your current project ("' . $projDir . '").</comment>');
                $output->writeln('<comment>To update Composer, download a composer.phar from https://getcomposer.org and then run `composer.phar update composer/composer` in your project.</comment>');
            } else {
                $output->writeln('<error>This instance of Composer does not have the self-update command.</error>');
                $output->writeln('<comment>This could be due to a number of reasons, such as Composer being installed as a system package on your OS, or Composer being installed as a package in the current project.</comment>');
            }
            return 1;
        }
        if ($_SERVER['argv'][0] === 'Standard input code') {
            return 1;
        }
        // trigger autoloading of a few classes which may be needed when verifying/swapping the phar file
        // to ensure we do not try to load them from the new phar, see https://github.com/composer/composer/issues/10252
        class_exists('Composer\Util\Platform');
        class_exists('Composer\Downloader\FilesystemException');
        $config = Factory::createConfig();
        if ($config->get('disable-tls') === \true) {
            $baseUrl = 'http://' . self::HOMEPAGE;
        } else {
            $baseUrl = 'https://' . self::HOMEPAGE;
        }
        $io = $this->getIO();
        $httpDownloader = Factory::createHttpDownloader($io, $config);
        $versionsUtil = new Versions($config, $httpDownloader);
        // switch channel if requested
        $requestedChannel = null;
        foreach (Versions::CHANNELS as $channel) {
            if ($input->getOption($channel)) {
                $requestedChannel = $channel;
                $versionsUtil->setChannel($channel, $io);
                break;
            }
        }
        if ($input->getOption('set-channel-only')) {
            return 0;
        }
        $cacheDir = $config->get('cache-dir');
        $rollbackDir = $config->get('data-dir');
        $home = $config->get('home');
        $localFilename = Phar::running(\false);
        if ('' === $localFilename) {
            throw new \RuntimeException('Could not determine the location of the composer.phar file as it appears you are not running this code from a phar archive.');
        }
        if ($input->getOption('update-keys')) {
            $this->fetchKeys($io, $config);
            return 0;
        }
        // ensure composer.phar location is accessible
        if (!file_exists($localFilename)) {
            throw new FilesystemException('Composer update failed: the "' . $localFilename . '" is not accessible');
        }
        // check if current dir is writable and if not try the cache dir from settings
        $tmpDir = is_writable(dirname($localFilename)) ? dirname($localFilename) : $cacheDir;
        // check for permissions in local filesystem before start connection process
        if (!is_writable($tmpDir)) {
            throw new FilesystemException('Composer update failed: the "' . $tmpDir . '" directory used to download the temp file could not be written');
        }
        // check if composer is running as the same user that owns the directory root, only if POSIX is defined and callable
        if (function_exists('posix_getpwuid') && function_exists('posix_geteuid')) {
            $composerUser = posix_getpwuid(posix_geteuid());
            $homeDirOwnerId = fileowner($home);
            if (is_array($composerUser) && $homeDirOwnerId !== \false) {
                $homeOwner = posix_getpwuid($homeDirOwnerId);
                if (is_array($homeOwner) && $composerUser['name'] !== $homeOwner['name']) {
                    $io->writeError('<warning>You are running Composer as "' . $composerUser['name'] . '", while "' . $home . '" is owned by "' . $homeOwner['name'] . '"</warning>');
                }
            }
        }
        if ($input->getOption('rollback')) {
            return $this->rollback($output, $rollbackDir, $localFilename);
        }
        if ($input->getArgument('command') === 'self' && $input->getArgument('version') === 'update') {
            $input->setArgument('version', null);
        }
        $latest = $versionsUtil->getLatest();
        $latestStable = $versionsUtil->getLatest('stable');
        try {
            $latestPreview = $versionsUtil->getLatest('preview');
        } catch (\UnexpectedValueException $e) {
            $latestPreview = $latestStable;
        }
        $latestVersion = $latest['version'];
        $updateVersion = $input->getArgument('version') ?? $latestVersion;
        $currentMajorVersion = Preg::replace('{^(\d+).*}', '$1', Composer::getVersion());
        $updateMajorVersion = Preg::replace('{^(\d+).*}', '$1', $updateVersion);
        $previewMajorVersion = Preg::replace('{^(\d+).*}', '$1', $latestPreview['version']);
        if ($versionsUtil->getChannel() === 'stable' && null === $input->getArgument('version')) {
            // if requesting stable channel and no specific version, avoid automatically upgrading to the next major
            // simply output a warning that the next major stable is available and let users upgrade to it manually
            if ($currentMajorVersion < $updateMajorVersion) {
                $skippedVersion = $updateVersion;
                $versionsUtil->setChannel($currentMajorVersion);
                $latest = $versionsUtil->getLatest();
                $latestStable = $versionsUtil->getLatest('stable');
                $latestVersion = $latest['version'];
                $updateVersion = $latestVersion;
                $io->writeError('<warning>A new stable major version of Composer is available (' . $skippedVersion . '), run "composer self-update --' . $updateMajorVersion . '" to update to it. See also https://getcomposer.org/' . $updateMajorVersion . '</warning>');
            } elseif ($currentMajorVersion < $previewMajorVersion) {
                // promote next major version if available in preview
                $io->writeError('<warning>A preview release of the next major version of Composer is available (' . $latestPreview['version'] . '), run "composer self-update --preview" to give it a try. See also https://github.com/composer/composer/releases for changelogs.</warning>');
            }
        }
        $effectiveChannel = $requestedChannel === null ? $versionsUtil->getChannel() : $requestedChannel;
        if (is_numeric($effectiveChannel) && strpos($latestStable['version'], $effectiveChannel) !== 0) {
            $io->writeError('<warning>Warning: You forced the install of ' . $latestVersion . ' via --' . $effectiveChannel . ', but ' . $latestStable['version'] . ' is the latest stable version. Updating to it via composer self-update --stable is recommended.</warning>');
        }
        if (isset($latest['eol'])) {
            $io->writeError('<warning>Warning: Version ' . $latestVersion . ' is EOL / End of Life. ' . $latestStable['version'] . ' is the latest stable version. Updating to it via composer self-update --stable is recommended.</warning>');
        }
        if (Preg::isMatch('{^[0-9a-f]{40}$}', $updateVersion) && $updateVersion !== $latestVersion) {
            $io->writeError('<error>You can not update to a specific SHA-1 as those phars are not available for download</error>');
            return 1;
        }
        $channelString = $versionsUtil->getChannel();
        if (is_numeric($channelString)) {
            $channelString .= '.x';
        }
        if (Composer::VERSION === $updateVersion) {
            $io->writeError(sprintf('<info>You are already using the latest available Composer version %s (%s channel).</info>', $updateVersion, $channelString));
            // remove all backups except for the most recent, if any
            if ($input->getOption('clean-backups')) {
                $this->cleanBackups($rollbackDir, $this->getLastBackupVersion($rollbackDir));
            }
            return 0;
        }
        $tempFilename = $tmpDir . '/' . basename($localFilename, '.phar') . '-temp' . random_int(0, 10000000) . '.phar';
        $backupFile = sprintf('%s/%s-%s%s', $rollbackDir, strtr(Composer::RELEASE_DATE, ' :', '_-'), Preg::replace('{^([0-9a-f]{7})[0-9a-f]{33}$}', '$1', Composer::VERSION), self::OLD_INSTALL_EXT);
        $updatingToTag = !Preg::isMatch('{^[0-9a-f]{40}$}', $updateVersion);
        $io->write(sprintf("Upgrading to version <info>%s</info> (%s channel).", $updateVersion, $channelString));
        $remoteFilename = $baseUrl . ($updatingToTag ? "/download/{$updateVersion}/composer.phar" : '/composer.phar');
        try {
            $signature = $httpDownloader->get($remoteFilename . '.sig')->getBody();
        } catch (TransportException $e) {
            if ($e->getStatusCode() === 404) {
                throw new \InvalidArgumentException('Version "' . $updateVersion . '" could not be found.', 0, $e);
            }
            throw $e;
        }
        $io->writeError('   ', \false);
        $httpDownloader->copy($remoteFilename, $tempFilename);
        $io->writeError('');
        if (!file_exists($tempFilename) || null === $signature || '' === $signature) {
            $io->writeError('<error>The download of the new composer version failed for an unexpected reason</error>');
            return 1;
        }
        // verify phar signature
        if (!extension_loaded('openssl') && $config->get('disable-tls')) {
            $io->writeError('<warning>Skipping phar signature verification as you have disabled OpenSSL via config.disable-tls</warning>');
        } else {
            if (!extension_loaded('openssl')) {
                throw new \RuntimeException('The openssl extension is required for phar signatures to be verified but it is not available. ' . 'If you can not enable the openssl extension, you can disable this error, at your own risk, by setting the \'disable-tls\' option to true.');
            }
            $sigFile = 'file://' . $home . '/' . ($updatingToTag ? 'keys.tags.pub' : 'keys.dev.pub');
            if (!file_exists($sigFile)) {
                file_put_contents($home . '/keys.dev.pub', <<<DEVPUBKEY
-----BEGIN PUBLIC KEY-----
MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAnBDHjZS6e0ZMoK3xTD7f
FNCzlXjX/Aie2dit8QXA03pSrOTbaMnxON3hUL47Lz3g1SC6YJEMVHr0zYq4elWi
i3ecFEgzLcj+pZM5X6qWu2Ozz4vWx3JYo1/a/HYdOuW9e3lwS8VtS0AVJA+U8X0A
hZnBmGpltHhO8hPKHgkJtkTUxCheTcbqn4wGHl8Z2SediDcPTLwqezWKUfrYzu1f
o/j3WFwFs6GtK4wdYtiXr+yspBZHO3y1udf8eFFGcb2V3EaLOrtfur6XQVizjOuk
8lw5zzse1Qp/klHqbDRsjSzJ6iL6F4aynBc6Euqt/8ccNAIz0rLjLhOraeyj4eNn
8iokwMKiXpcrQLTKH+RH1JCuOVxQ436bJwbSsp1VwiqftPQieN+tzqy+EiHJJmGf
TBAbWcncicCk9q2md+AmhNbvHO4PWbbz9TzC7HJb460jyWeuMEvw3gNIpEo2jYa9
pMV6cVqnSa+wOc0D7pC9a6bne0bvLcm3S+w6I5iDB3lZsb3A9UtRiSP7aGSo7D72
8tC8+cIgZcI7k9vjvOqH+d7sdOU2yPCnRY6wFh62/g8bDnUpr56nZN1G89GwM4d4
r/TU7BQQIzsZgAiqOGXvVklIgAMiV0iucgf3rNBLjjeNEwNSTTG9F0CtQ+7JLwaE
wSEuAuRm+pRqi8BRnQ/GKUcCAwEAAQ==
-----END PUBLIC KEY-----
DEVPUBKEY
);
                file_put_contents($home . '/keys.tags.pub', <<<TAGSPUBKEY
-----BEGIN PUBLIC KEY-----
MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA0Vi/2K6apCVj76nCnCl2
MQUPdK+A9eqkYBacXo2wQBYmyVlXm2/n/ZsX6pCLYPQTHyr5jXbkQzBw8SKqPdlh
vA7NpbMeNCz7wP/AobvUXM8xQuXKbMDTY2uZ4O7sM+PfGbptKPBGLe8Z8d2sUnTO
bXtX6Lrj13wkRto7st/w/Yp33RHe9SlqkiiS4MsH1jBkcIkEHsRaveZzedUaxY0M
mba0uPhGUInpPzEHwrYqBBEtWvP97t2vtfx8I5qv28kh0Y6t+jnjL1Urid2iuQZf
noCMFIOu4vksK5HxJxxrN0GOmGmwVQjOOtxkwikNiotZGPR4KsVj8NnBrLX7oGuM
nQvGciiu+KoC2r3HDBrpDeBVdOWxDzT5R4iI0KoLzFh2pKqwbY+obNPS2bj+2dgJ
rV3V5Jjry42QOCBN3c88wU1PKftOLj2ECpewY6vnE478IipiEu7EAdK8Zwj2LmTr
RKQUSa9k7ggBkYZWAeO/2Ag0ey3g2bg7eqk+sHEq5ynIXd5lhv6tC5PBdHlWipDK
tl2IxiEnejnOmAzGVivE1YGduYBjN+mjxDVy8KGBrjnz1JPgAvgdwJ2dYw4Rsc/e
TzCFWGk/HM6a4f0IzBWbJ5ot0PIi4amk07IotBXDWwqDiQTwyuGCym5EqWQ2BD95
RGv89BPD+2DLnJysngsvVaUCAwEAAQ==
-----END PUBLIC KEY-----
TAGSPUBKEY
);
            }
            $pubkeyid = openssl_pkey_get_public($sigFile);
            if (\false === $pubkeyid) {
                throw new \RuntimeException('Failed loading the public key from ' . $sigFile);
            }
            $algo = defined('OPENSSL_ALGO_SHA384') ? \OPENSSL_ALGO_SHA384 : 'SHA384';
            if (!in_array('sha384', array_map('strtolower', openssl_get_md_methods()), \true)) {
                throw new \RuntimeException('SHA384 is not supported by your openssl extension, could not verify the phar file integrity');
            }
            $signatureData = json_decode($signature, \true);
            $signatureSha384 = base64_decode($signatureData['sha384'], \true);
            if (\false === $signatureSha384) {
                throw new \RuntimeException('Failed loading the phar signature from ' . $remoteFilename . '.sig, got ' . $signature);
            }
            $verified = 1 === openssl_verify((string) file_get_contents($tempFilename), $signatureSha384, $pubkeyid, $algo);
            // PHP 8 automatically frees the key instance and deprecates the function
            if (\PHP_VERSION_ID < 80000) {
                // @phpstan-ignore function.deprecated
                openssl_free_key($pubkeyid);
            }
            if (!$verified) {
                throw new \RuntimeException('The phar signature did not match the file you downloaded, this means your public keys are outdated or that the phar file is corrupt/has been modified');
            }
        }
        // remove saved installations of composer
        if ($input->getOption('clean-backups')) {
            $this->cleanBackups($rollbackDir);
        }
        if (!$this->setLocalPhar($localFilename, $tempFilename, $backupFile)) {
            @unlink($tempFilename);
            return 1;
        }
        if (file_exists($backupFile)) {
            $io->writeError(sprintf('Use <info>composer self-update --rollback</info> to return to version <comment>%s</comment>', Composer::VERSION));
        } else {
            $io->writeError('<warning>A backup of the current version could not be written to ' . $backupFile . ', no rollback possible</warning>');
        }
        return 0;
    }
    /**
     * @throws \Exception
     */
    protected function fetchKeys(IOInterface $io, Config $config): void
    {
        if (!$io->isInteractive()) {
            throw new \RuntimeException('Public keys can not be fetched in non-interactive mode, please run Composer interactively');
        }
        $io->write('Open <info>https://composer.github.io/pubkeys.html</info> to find the latest keys');
        $validator = static function ($value): string {
            $value = (string) $value;
            if (!Preg::isMatch('{^-----BEGIN PUBLIC KEY-----$}', trim($value))) {
                throw new \UnexpectedValueException('Invalid input');
            }
            return trim($value) . "\n";
        };
        $devKey = '';
        while (!Preg::isMatch('{(-----BEGIN PUBLIC KEY-----.+?-----END PUBLIC KEY-----)}s', $devKey, $match)) {
            $devKey = $io->askAndValidate('Enter Dev / Snapshot Public Key (including lines with -----): ', $validator);
            while ($line = $io->ask('', '')) {
                $devKey .= trim($line) . "\n";
                if (trim($line) === '-----END PUBLIC KEY-----') {
                    break;
                }
            }
        }
        file_put_contents($keyPath = $config->get('home') . '/keys.dev.pub', $match[0]);
        $io->write('Stored key with fingerprint: ' . Keys::fingerprint($keyPath));
        $tagsKey = '';
        while (!Preg::isMatch('{(-----BEGIN PUBLIC KEY-----.+?-----END PUBLIC KEY-----)}s', $tagsKey, $match)) {
            $tagsKey = $io->askAndValidate('Enter Tags Public Key (including lines with -----): ', $validator);
            while ($line = $io->ask('', '')) {
                $tagsKey .= trim($line) . "\n";
                if (trim($line) === '-----END PUBLIC KEY-----') {
                    break;
                }
            }
        }
        file_put_contents($keyPath = $config->get('home') . '/keys.tags.pub', $match[0]);
        $io->write('Stored key with fingerprint: ' . Keys::fingerprint($keyPath));
        $io->write('Public keys stored in ' . $config->get('home'));
    }
    /**
     * @throws FilesystemException
     */
    protected function rollback(OutputInterface $output, string $rollbackDir, string $localFilename): int
    {
        $rollbackVersion = $this->getLastBackupVersion($rollbackDir);
        if (null === $rollbackVersion) {
            throw new \UnexpectedValueException('Composer rollback failed: no installation to roll back to in "' . $rollbackDir . '"');
        }
        $oldFile = $rollbackDir . '/' . $rollbackVersion . self::OLD_INSTALL_EXT;
        if (!is_file($oldFile)) {
            throw new FilesystemException('Composer rollback failed: "' . $oldFile . '" could not be found');
        }
        if (!Filesystem::isReadable($oldFile)) {
            throw new FilesystemException('Composer rollback failed: "' . $oldFile . '" could not be read');
        }
        $io = $this->getIO();
        $io->writeError(sprintf("Rolling back to version <info>%s</info>.", $rollbackVersion));
        if (!$this->setLocalPhar($localFilename, $oldFile)) {
            return 1;
        }
        return 0;
    }
    /**
     * Checks if the downloaded/rollback phar is valid then moves it
     *
     * @param  string              $localFilename The composer.phar location
     * @param  string              $newFilename   The downloaded or backup phar
     * @param  string              $backupTarget  The filename to use for the backup
     * @throws FilesystemException If the file cannot be moved
     * @return bool                Whether the phar is valid and has been moved
     */
    protected function setLocalPhar(string $localFilename, string $newFilename, ?string $backupTarget = null): bool
    {
        $io = $this->getIO();
        $perms = @fileperms($localFilename);
        if ($perms !== \false) {
            @chmod($newFilename, $perms);
        }
        // check phar validity
        if (!$this->validatePhar($newFilename, $error)) {
            $io->writeError('<error>The ' . ($backupTarget !== null ? 'update' : 'backup') . ' file is corrupted (' . $error . ')</error>');
            if ($backupTarget !== null) {
                $io->writeError('<error>Please re-run the self-update command to try again.</error>');
            }
            return \false;
        }
        // copy current file into backups dir
        if ($backupTarget !== null) {
            @copy($localFilename, $backupTarget);
        }
        try {
            if (Platform::isWindows()) {
                // use copy to apply permissions from the destination directory
                // as rename uses source permissions and may block other users
                copy($newFilename, $localFilename);
                @unlink($newFilename);
            } else {
                rename($newFilename, $localFilename);
            }
            return \true;
        } catch (\Exception $e) {
            // see if we can run this operation as an Admin on Windows
            if (!is_writable(dirname($localFilename)) && $io->isInteractive() && $this->isWindowsNonAdminUser()) {
                return $this->tryAsWindowsAdmin($localFilename, $newFilename);
            }
            @unlink($newFilename);
            $action = 'Composer ' . ($backupTarget !== null ? 'update' : 'rollback');
            throw new FilesystemException($action . ' failed: "' . $localFilename . '" could not be written.' . \PHP_EOL . $e->getMessage());
        }
    }
    protected function cleanBackups(string $rollbackDir, ?string $except = null): void
    {
        $finder = $this->getOldInstallationFinder($rollbackDir);
        $io = $this->getIO();
        $fs = new Filesystem();
        foreach ($finder as $file) {
            if ($file->getBasename(self::OLD_INSTALL_EXT) === $except) {
                continue;
            }
            $file = (string) $file;
            $io->writeError('<info>Removing: ' . $file . '</info>');
            $fs->remove($file);
        }
    }
    protected function getLastBackupVersion(string $rollbackDir): ?string
    {
        $finder = $this->getOldInstallationFinder($rollbackDir);
        $finder->sortByName();
        $files = iterator_to_array($finder);
        if (count($files) > 0) {
            return end($files)->getBasename(self::OLD_INSTALL_EXT);
        }
        return null;
    }
    protected function getOldInstallationFinder(string $rollbackDir): Finder
    {
        return Finder::create()->depth(0)->files()->name('*' . self::OLD_INSTALL_EXT)->in($rollbackDir);
    }
    /**
     * Validates the downloaded/backup phar file
     *
     * @param string      $pharFile The downloaded or backup phar
     * @param null|string $error    Set by method on failure
     *
     * Code taken from getcomposer.org/installer. Any changes should be made
     * there and replicated here
     *
     * @throws \Exception
     * @return bool       If the operation succeeded
     */
    protected function validatePhar(string $pharFile, ?string &$error): bool
    {
        if ((bool) ini_get('phar.readonly')) {
            return \true;
        }
        try {
            // Test the phar validity
            $phar = new Phar($pharFile);
            // Free the variable to unlock the file
            unset($phar);
            $result = \true;
        } catch (\Exception $e) {
            if (!$e instanceof \UnexpectedValueException && !$e instanceof \PharException) {
                throw $e;
            }
            $error = $e->getMessage();
            $result = \false;
        }
        return $result;
    }
    /**
     * Returns true if this is a non-admin Windows user account
     */
    protected function isWindowsNonAdminUser(): bool
    {
        if (!Platform::isWindows()) {
            return \false;
        }
        // fltmc.exe manages filter drivers and errors without admin privileges
        exec('fltmc.exe filters', $output, $exitCode);
        return $exitCode !== 0;
    }
    /**
     * Invokes a UAC prompt to update composer.phar as an admin
     *
     * Uses either sudo.exe or VBScript to elevate and run cmd.exe move.
     *
     * @param  string $localFilename The composer.phar location
     * @param  string $newFilename   The downloaded or backup phar
     * @return bool   Whether composer.phar has been updated
     */
    protected function tryAsWindowsAdmin(string $localFilename, string $newFilename): bool
    {
        $io = $this->getIO();
        $io->writeError('<error>Unable to write "' . $localFilename . '". Access is denied.</error>');
        $helpMessage = 'Please run the self-update command as an Administrator.';
        $question = 'Complete this operation with Administrator privileges [<comment>Y,n</comment>]? ';
        if (!$io->askConfirmation($question, \true)) {
            $io->writeError('<warning>Operation cancelled. ' . $helpMessage . '</warning>');
            return \false;
        }
        $tmpFile = tempnam(sys_get_temp_dir(), '');
        if (\false === $tmpFile) {
            $io->writeError('<error>Operation failed. ' . $helpMessage . '</error>');
            return \false;
        }
        exec('sudo config 2> NUL', $output, $exitCode);
        $usingSudo = $exitCode === 0;
        $script = $usingSudo ? $tmpFile . '.bat' : $tmpFile . '.vbs';
        rename($tmpFile, $script);
        $checksum = hash_file('sha256', $newFilename);
        // cmd's internal move is fussy about backslashes
        $source = str_replace('/', '\\', $newFilename);
        $destination = str_replace('/', '\\', $localFilename);
        if ($usingSudo) {
            $code = sprintf('move "%s" "%s"', $source, $destination);
        } else {
            $code = <<<EOT
Set UAC = CreateObject("Shell.Application")
UAC.ShellExecute "cmd.exe", "/c move /y ""{$source}"" ""{$destination}""", "", "runas", 0
EOT;
        }
        file_put_contents($script, $code);
        $command = $usingSudo ? sprintf('sudo "%s"', $script) : sprintf('"%s"', $script);
        exec($command);
        // Allow time for the operation to complete
        usleep(300000);
        @unlink($script);
        // see if the file was moved and is still accessible
        if ($result = Filesystem::isReadable($localFilename) && hash_file('sha256', $localFilename) === $checksum) {
            $io->writeError('<info>Operation succeeded.</info>');
        } else {
            $io->writeError('<error>Operation failed. ' . $helpMessage . '</error>');
        }
        return $result;
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer\Command;

use Composer\DependencyResolver\Request;
use Composer\Package\AliasPackage;
use Composer\Package\CompletePackageInterface;
use Composer\Package\Loader\RootPackageLoader;
use Composer\Package\PackageInterface;
use Composer\Package\Version\VersionSelector;
use Composer\Pcre\Preg;
use Composer\Repository\RepositorySet;
use Composer\Util\Filesystem;
use Composer\Util\PackageSorter;
use _ContaoManager\Seld\Signal\SignalHandler;
use _ContaoManager\Symfony\Component\Console\Input\InputInterface;
use Composer\Console\Input\InputArgument;
use Composer\Console\Input\InputOption;
use _ContaoManager\Symfony\Component\Console\Output\OutputInterface;
use Composer\Factory;
use Composer\Installer;
use Composer\Installer\InstallerEvents;
use Composer\Json\JsonFile;
use Composer\Json\JsonManipulator;
use Composer\Package\Version\VersionParser;
use Composer\Package\Loader\ArrayLoader;
use Composer\Package\BasePackage;
use Composer\Plugin\CommandEvent;
use Composer\Plugin\PluginEvents;
use Composer\Repository\CompositeRepository;
use Composer\Repository\PlatformRepository;
use Composer\IO\IOInterface;
use Composer\Advisory\Auditor;
use Composer\Util\Silencer;
/**
 * @author Jérémy Romey <jeremy@free-agent.fr>
 * @author Jordi Boggiano <j.boggiano@seld.be>
 */
class RequireCommand extends \Composer\Command\BaseCommand
{
    use \Composer\Command\CompletionTrait;
    use \Composer\Command\PackageDiscoveryTrait;
    /** @var bool */
    private $newlyCreated;
    /** @var bool */
    private $firstRequire;
    /** @var JsonFile */
    private $json;
    /** @var string */
    private $file;
    /** @var string */
    private $composerBackup;
    /** @var string file name */
    private $lock;
    /** @var ?string contents before modification if the lock file exists */
    private $lockBackup;
    /** @var bool */
    private $dependencyResolutionCompleted = \false;
    protected function configure(): void
    {
        $this->setName('require')->setAliases(['r'])->setDescription('Adds required packages to your composer.json and installs them')->setDefinition([new InputArgument('packages', InputArgument::IS_ARRAY | InputArgument::OPTIONAL, 'Optional package name can also include a version constraint, e.g. foo/bar or foo/bar:1.0.0 or foo/bar=1.0.0 or "foo/bar 1.0.0"', null, $this->suggestAvailablePackageInclPlatform()), new InputOption('dev', null, InputOption::VALUE_NONE, 'Add requirement to require-dev.'), new InputOption('dry-run', null, InputOption::VALUE_NONE, 'Outputs the operations but will not execute anything (implicitly enables --verbose).'), new InputOption('prefer-source', null, InputOption::VALUE_NONE, 'Forces installation from package sources when possible, including VCS information.'), new InputOption('prefer-dist', null, InputOption::VALUE_NONE, 'Forces installation from package dist (default behavior).'), new InputOption('prefer-install', null, InputOption::VALUE_REQUIRED, 'Forces installation from package dist|source|auto (auto chooses source for dev versions, dist for the rest).', null, $this->suggestPreferInstall()), new InputOption('fixed', null, InputOption::VALUE_NONE, 'Write fixed version to the composer.json.'), new InputOption('no-suggest', null, InputOption::VALUE_NONE, 'DEPRECATED: This flag does not exist anymore.'), new InputOption('no-progress', null, InputOption::VALUE_NONE, 'Do not output download progress.'), new InputOption('no-update', null, InputOption::VALUE_NONE, 'Disables the automatic update of the dependencies (implies --no-install).'), new InputOption('no-install', null, InputOption::VALUE_NONE, 'Skip the install step after updating the composer.lock file.'), new InputOption('no-audit', null, InputOption::VALUE_NONE, 'Skip the audit step after updating the composer.lock file (can also be set via the COMPOSER_NO_AUDIT=1 env var).'), new InputOption('audit-format', null, InputOption::VALUE_REQUIRED, 'Audit output format. Must be "table", "plain", "json", or "summary".', Auditor::FORMAT_SUMMARY, Auditor::FORMATS), new InputOption('no-security-blocking', null, InputOption::VALUE_NONE, 'Allows installing packages with security advisories or that are abandoned (can also be set via the COMPOSER_NO_SECURITY_BLOCKING=1 env var).'), new InputOption('update-no-dev', null, InputOption::VALUE_NONE, 'Run the dependency update with the --no-dev option.'), new InputOption('update-with-dependencies', 'w', InputOption::VALUE_NONE, 'Allows inherited dependencies to be updated, except those that are root requirements (can also be set via the COMPOSER_WITH_DEPENDENCIES=1 env var).'), new InputOption('update-with-all-dependencies', 'W', InputOption::VALUE_NONE, 'Allows all inherited dependencies to be updated, including those that are root requirements (can also be set via the COMPOSER_WITH_ALL_DEPENDENCIES=1 env var).'), new InputOption('with-dependencies', null, InputOption::VALUE_NONE, 'Alias for --update-with-dependencies'), new InputOption('with-all-dependencies', null, InputOption::VALUE_NONE, 'Alias for --update-with-all-dependencies'), new InputOption('ignore-platform-req', null, InputOption::VALUE_REQUIRED | InputOption::VALUE_IS_ARRAY, 'Ignore a specific platform requirement (php & ext- packages).'), new InputOption('ignore-platform-reqs', null, InputOption::VALUE_NONE, 'Ignore all platform requirements (php & ext- packages).'), new InputOption('prefer-stable', null, InputOption::VALUE_NONE, 'Prefer stable versions of dependencies (can also be set via the COMPOSER_PREFER_STABLE=1 env var).'), new InputOption('prefer-lowest', null, InputOption::VALUE_NONE, 'Prefer lowest versions of dependencies (can also be set via the COMPOSER_PREFER_LOWEST=1 env var).'), new InputOption('minimal-changes', 'm', InputOption::VALUE_NONE, 'During an update with -w/-W, only perform absolutely necessary changes to transitive dependencies (can also be set via the COMPOSER_MINIMAL_CHANGES=1 env var).'), new InputOption('sort-packages', null, InputOption::VALUE_NONE, 'Sorts packages when adding/updating a new dependency'), new InputOption('optimize-autoloader', 'o', InputOption::VALUE_NONE, 'Optimize autoloader during autoloader dump'), new InputOption('classmap-authoritative', 'a', InputOption::VALUE_NONE, 'Autoload classes from the classmap only. Implicitly enables `--optimize-autoloader`.'), new InputOption('apcu-autoloader', null, InputOption::VALUE_NONE, 'Use APCu to cache found/not-found classes.'), new InputOption('apcu-autoloader-prefix', null, InputOption::VALUE_REQUIRED, 'Use a custom prefix for the APCu autoloader cache. Implicitly enables --apcu-autoloader')])->setHelp(<<<EOT
The require command adds required packages to your composer.json and installs them.

If you do not specify a package, composer will prompt you to search for a package, and given results, provide a list of
matches to require.

If you do not specify a version constraint, composer will choose a suitable one based on the available package versions.

If you do not want to install the new dependencies immediately you can call it with --no-update

Read more at https://getcomposer.org/doc/03-cli.md#require-r
EOT
);
    }
    /**
     * @throws \Seld\JsonLint\ParsingException
     */
    protected function execute(InputInterface $input, OutputInterface $output): int
    {
        $this->file = Factory::getComposerFile();
        $io = $this->getIO();
        if ($input->getOption('no-suggest')) {
            $io->writeError('<warning>You are using the deprecated option "--no-suggest". It has no effect and will break in Composer 3.</warning>');
        }
        $this->newlyCreated = !file_exists($this->file);
        if ($this->newlyCreated && !file_put_contents($this->file, "{\n}\n")) {
            $io->writeError('<error>' . $this->file . ' could not be created.</error>');
            return 1;
        }
        if (!Filesystem::isReadable($this->file)) {
            $io->writeError('<error>' . $this->file . ' is not readable.</error>');
            return 1;
        }
        if (filesize($this->file) === 0) {
            file_put_contents($this->file, "{\n}\n");
        }
        $this->json = new JsonFile($this->file);
        $this->lock = Factory::getLockFile($this->file);
        $this->composerBackup = file_get_contents($this->json->getPath());
        $this->lockBackup = file_exists($this->lock) ? file_get_contents($this->lock) : null;
        $signalHandler = SignalHandler::create([SignalHandler::SIGINT, SignalHandler::SIGTERM, SignalHandler::SIGHUP], function (string $signal, SignalHandler $handler) {
            $this->getIO()->writeError('Received ' . $signal . ', aborting', \true, IOInterface::DEBUG);
            $this->revertComposerFile();
            $handler->exitWithLastSignal();
        });
        // check for writability by writing to the file as is_writable can not be trusted on network-mounts
        // see https://github.com/composer/composer/issues/8231 and https://bugs.php.net/bug.php?id=68926
        if (!is_writable($this->file) && \false === Silencer::call('file_put_contents', $this->file, $this->composerBackup)) {
            $io->writeError('<error>' . $this->file . ' is not writable.</error>');
            return 1;
        }
        if ($input->getOption('fixed') === \true) {
            $config = $this->json->read();
            $packageType = empty($config['type']) ? 'library' : $config['type'];
            /**
             * @see https://github.com/composer/composer/pull/8313#issuecomment-532637955
             */
            if ($packageType !== 'project' && !$input->getOption('dev')) {
                $io->writeError('<error>The "--fixed" option is only allowed for packages with a "project" type or for dev dependencies to prevent possible misuses.</error>');
                if (!isset($config['type'])) {
                    $io->writeError('<error>If your package is not a library, you can explicitly specify the "type" by using "composer config type project".</error>');
                }
                return 1;
            }
        }
        $composer = $this->requireComposer();
        $repos = $composer->getRepositoryManager()->getRepositories();
        $platformOverrides = $composer->getConfig()->get('platform');
        // initialize $this->repos as it is used by the PackageDiscoveryTrait
        $this->repos = new CompositeRepository(array_merge([$platformRepo = new PlatformRepository([], $platformOverrides)], $repos));
        if ($composer->getPackage()->getPreferStable()) {
            $preferredStability = 'stable';
        } else {
            $preferredStability = $composer->getPackage()->getMinimumStability();
        }
        try {
            $requirements = $this->determineRequirements(
                $input,
                $output,
                $input->getArgument('packages'),
                $platformRepo,
                $preferredStability,
                $input->getOption('no-update'),
                // if there is no update, we need to use the best possible version constraint directly as we cannot rely on the solver to guess the best constraint
                $input->getOption('fixed')
            );
        } catch (\Exception $e) {
            if ($this->newlyCreated) {
                $this->revertComposerFile();
                throw new \RuntimeException('No composer.json present in the current directory (' . $this->file . '), this may be the cause of the following exception.', 0, $e);
            }
            throw $e;
        }
        $requirements = $this->formatRequirements($requirements);
        if (!$input->getOption('dev') && $io->isInteractive() && !$composer->isGlobal()) {
            $devPackages = [];
            $devTags = ['dev', 'testing', 'static analysis'];
            $currentRequiresByKey = $this->getPackagesByRequireKey();
            foreach ($requirements as $name => $version) {
                // skip packages which are already in the composer.json as those have already been decided
                if (isset($currentRequiresByKey[$name])) {
                    continue;
                }
                $pkg = PackageSorter::getMostCurrentVersion($this->getRepos()->findPackages($name));
                if ($pkg instanceof CompletePackageInterface) {
                    $pkgDevTags = array_intersect($devTags, array_map('strtolower', $pkg->getKeywords()));
                    if (count($pkgDevTags) > 0) {
                        $devPackages[] = $pkgDevTags;
                    }
                }
            }
            if (count($devPackages) === count($requirements)) {
                $plural = count($requirements) > 1 ? 's' : '';
                $plural2 = count($requirements) > 1 ? 'are' : 'is';
                $plural3 = count($requirements) > 1 ? 'they are' : 'it is';
                $pkgDevTags = array_unique(array_merge(...$devPackages));
                $io->warning('The package' . $plural . ' you required ' . $plural2 . ' recommended to be placed in require-dev (because ' . $plural3 . ' tagged as "' . implode('", "', $pkgDevTags) . '") but you did not use --dev.');
                if ($io->askConfirmation('<info>Do you want to re-run the command with --dev?</> [<comment>yes</>]? ')) {
                    $input->setOption('dev', \true);
                }
            }
            unset($devPackages, $pkgDevTags);
        }
        $requireKey = $input->getOption('dev') ? 'require-dev' : 'require';
        $removeKey = $input->getOption('dev') ? 'require' : 'require-dev';
        // check which requirements need the version guessed
        $requirementsToGuess = [];
        foreach ($requirements as $package => $constraint) {
            if ($constraint === 'guess') {
                $requirements[$package] = '*';
                $requirementsToGuess[] = $package;
            }
        }
        // validate requirements format
        $versionParser = new VersionParser();
        foreach ($requirements as $package => $constraint) {
            if (strtolower($package) === $composer->getPackage()->getName()) {
                $io->writeError(sprintf('<error>Root package \'%s\' cannot require itself in its composer.json</error>', $package));
                return 1;
            }
            if ($constraint === 'self.version') {
                continue;
            }
            $versionParser->parseConstraints($constraint);
        }
        $inconsistentRequireKeys = $this->getInconsistentRequireKeys($requirements, $requireKey);
        if (count($inconsistentRequireKeys) > 0) {
            foreach ($inconsistentRequireKeys as $package) {
                $io->warning(sprintf('%s is currently present in the %s key and you ran the command %s the --dev flag, which will move it to the %s key.', $package, $removeKey, $input->getOption('dev') ? 'with' : 'without', $requireKey));
            }
            if ($io->isInteractive()) {
                if (!$io->askConfirmation(sprintf('<info>Do you want to move %s?</info> [<comment>no</comment>]? ', count($inconsistentRequireKeys) > 1 ? 'these requirements' : 'this requirement'), \false)) {
                    if (!$io->askConfirmation(sprintf('<info>Do you want to re-run the command %s --dev?</info> [<comment>yes</comment>]? ', $input->getOption('dev') ? 'without' : 'with'), \true)) {
                        return 0;
                    }
                    $input->setOption('dev', \true);
                    [$requireKey, $removeKey] = [$removeKey, $requireKey];
                }
            }
        }
        $sortPackages = $input->getOption('sort-packages') || $composer->getConfig()->get('sort-packages');
        $this->firstRequire = $this->newlyCreated;
        if (!$this->firstRequire) {
            $composerDefinition = $this->json->read();
            if (count($composerDefinition['require'] ?? []) === 0 && count($composerDefinition['require-dev'] ?? []) === 0) {
                $this->firstRequire = \true;
            }
        }
        if (!$input->getOption('dry-run')) {
            $this->updateFile($this->json, $requirements, $requireKey, $removeKey, $sortPackages);
        }
        $io->writeError('<info>' . $this->file . ' has been ' . ($this->newlyCreated ? 'created' : 'updated') . '</info>');
        if ($input->getOption('no-update')) {
            return 0;
        }
        $composer->getPluginManager()->deactivateInstalledPlugins();
        try {
            $result = $this->doUpdate($input, $output, $io, $requirements, $requireKey, $removeKey);
            if ($result === 0 && count($requirementsToGuess) > 0) {
                $result = $this->updateRequirementsAfterResolution($requirementsToGuess, $requireKey, $removeKey, $sortPackages, $input->getOption('dry-run'), $input->getOption('fixed'));
            }
            return $result;
        } catch (\Exception $e) {
            if (!$this->dependencyResolutionCompleted) {
                $this->revertComposerFile();
            }
            throw $e;
        } finally {
            if ($input->getOption('dry-run') && $this->newlyCreated) {
                @unlink($this->json->getPath());
            }
            $signalHandler->unregister();
        }
    }
    /**
     * @param array<string, string> $newRequirements
     * @return string[]
     */
    private function getInconsistentRequireKeys(array $newRequirements, string $requireKey): array
    {
        $requireKeys = $this->getPackagesByRequireKey();
        $inconsistentRequirements = [];
        foreach ($requireKeys as $package => $packageRequireKey) {
            if (!isset($newRequirements[$package])) {
                continue;
            }
            if ($requireKey !== $packageRequireKey) {
                $inconsistentRequirements[] = $package;
            }
        }
        return $inconsistentRequirements;
    }
    /**
     * @return array<string, string>
     */
    private function getPackagesByRequireKey(): array
    {
        $composerDefinition = $this->json->read();
        $require = [];
        $requireDev = [];
        if (isset($composerDefinition['require'])) {
            $require = $composerDefinition['require'];
        }
        if (isset($composerDefinition['require-dev'])) {
            $requireDev = $composerDefinition['require-dev'];
        }
        return array_merge(array_fill_keys(array_keys($require), 'require'), array_fill_keys(array_keys($requireDev), 'require-dev'));
    }
    /**
     * @param array<string, string> $requirements
     * @param 'require'|'require-dev' $requireKey
     * @param 'require'|'require-dev' $removeKey
     * @throws \Exception
     */
    private function doUpdate(InputInterface $input, OutputInterface $output, IOInterface $io, array $requirements, string $requireKey, string $removeKey): int
    {
        // Update packages
        $this->resetComposer();
        $composer = $this->requireComposer();
        $this->dependencyResolutionCompleted = \false;
        $composer->getEventDispatcher()->addListener(InstallerEvents::PRE_OPERATIONS_EXEC, function (): void {
            $this->dependencyResolutionCompleted = \true;
        }, 10000);
        if ($input->getOption('dry-run')) {
            $rootPackage = $composer->getPackage();
            $links = ['require' => $rootPackage->getRequires(), 'require-dev' => $rootPackage->getDevRequires()];
            $loader = new ArrayLoader();
            $newLinks = $loader->parseLinks($rootPackage->getName(), $rootPackage->getPrettyVersion(), BasePackage::$supportedLinkTypes[$requireKey]['method'], $requirements);
            $links[$requireKey] = array_merge($links[$requireKey], $newLinks);
            foreach ($requirements as $package => $constraint) {
                unset($links[$removeKey][$package]);
            }
            $rootPackage->setRequires($links['require']);
            $rootPackage->setDevRequires($links['require-dev']);
            // extract stability flags & references as they weren't present when loading the unmodified composer.json
            $references = $rootPackage->getReferences();
            $references = RootPackageLoader::extractReferences($requirements, $references);
            $rootPackage->setReferences($references);
            $stabilityFlags = $rootPackage->getStabilityFlags();
            $stabilityFlags = RootPackageLoader::extractStabilityFlags($requirements, $rootPackage->getMinimumStability(), $stabilityFlags);
            $rootPackage->setStabilityFlags($stabilityFlags);
            unset($stabilityFlags, $references);
        }
        $updateDevMode = !$input->getOption('update-no-dev');
        $optimize = $input->getOption('optimize-autoloader') || $composer->getConfig()->get('optimize-autoloader');
        $authoritative = $input->getOption('classmap-authoritative') || $composer->getConfig()->get('classmap-authoritative');
        $apcuPrefix = $input->getOption('apcu-autoloader-prefix');
        $apcu = $apcuPrefix !== null || $input->getOption('apcu-autoloader') || $composer->getConfig()->get('apcu-autoloader');
        $minimalChanges = $input->getOption('minimal-changes') || $composer->getConfig()->get('update-with-minimal-changes');
        $updateAllowTransitiveDependencies = Request::UPDATE_ONLY_LISTED;
        $flags = '';
        if ($input->getOption('update-with-all-dependencies') || $input->getOption('with-all-dependencies')) {
            $updateAllowTransitiveDependencies = Request::UPDATE_LISTED_WITH_TRANSITIVE_DEPS;
            $flags .= ' --with-all-dependencies';
        } elseif ($input->getOption('update-with-dependencies') || $input->getOption('with-dependencies')) {
            $updateAllowTransitiveDependencies = Request::UPDATE_LISTED_WITH_TRANSITIVE_DEPS_NO_ROOT_REQUIRE;
            $flags .= ' --with-dependencies';
        }
        $io->writeError('<info>Running composer update ' . implode(' ', array_keys($requirements)) . $flags . '</info>');
        $commandEvent = new CommandEvent(PluginEvents::COMMAND, 'require', $input, $output);
        $composer->getEventDispatcher()->dispatch($commandEvent->getName(), $commandEvent);
        $composer->getInstallationManager()->setOutputProgress(!$input->getOption('no-progress'));
        $install = Installer::create($io, $composer);
        [$preferSource, $preferDist] = $this->getPreferredInstallOptions($composer->getConfig(), $input);
        $install->setDryRun($input->getOption('dry-run'))->setVerbose($input->getOption('verbose'))->setPreferSource($preferSource)->setPreferDist($preferDist)->setDevMode($updateDevMode)->setOptimizeAutoloader($optimize)->setClassMapAuthoritative($authoritative)->setApcuAutoloader($apcu, $apcuPrefix)->setUpdate(\true)->setInstall(!$input->getOption('no-install'))->setUpdateAllowTransitiveDependencies($updateAllowTransitiveDependencies)->setPlatformRequirementFilter($this->getPlatformRequirementFilter($input))->setPreferStable($input->getOption('prefer-stable'))->setPreferLowest($input->getOption('prefer-lowest'))->setAuditConfig($this->createAuditConfig($composer->getConfig(), $input))->setMinimalUpdate($minimalChanges);
        // if no lock is present, or the file is brand new, we do not do a
        // partial update as this is not supported by the Installer
        if (!$this->firstRequire && $composer->getLocker()->isLocked()) {
            $install->setUpdateAllowList(array_keys($requirements));
        }
        $status = $install->run();
        if ($status !== 0 && $status !== Installer::ERROR_AUDIT_FAILED) {
            if ($status === Installer::ERROR_DEPENDENCY_RESOLUTION_FAILED) {
                foreach ($this->normalizeRequirements($input->getArgument('packages')) as $req) {
                    if (!isset($req['version'])) {
                        $io->writeError('You can also try re-running composer require with an explicit version constraint, e.g. "composer require ' . $req['name'] . ':*" to figure out if any version is installable, or "composer require ' . $req['name'] . ':^2.1" if you know which you need.');
                        break;
                    }
                }
            }
            $this->revertComposerFile();
        }
        return $status;
    }
    /**
     * @param list<string> $requirementsToUpdate
     */
    private function updateRequirementsAfterResolution(array $requirementsToUpdate, string $requireKey, string $removeKey, bool $sortPackages, bool $dryRun, bool $fixed): int
    {
        $composer = $this->requireComposer();
        $locker = $composer->getLocker();
        $requirements = [];
        $versionSelector = new VersionSelector(new RepositorySet());
        $repo = $locker->isLocked() ? $composer->getLocker()->getLockedRepository(\true) : $composer->getRepositoryManager()->getLocalRepository();
        foreach ($requirementsToUpdate as $packageName) {
            $package = $repo->findPackage($packageName, '*');
            while ($package instanceof AliasPackage) {
                $package = $package->getAliasOf();
            }
            if (!$package instanceof PackageInterface) {
                continue;
            }
            if ($fixed) {
                $requirements[$packageName] = $package->getPrettyVersion();
            } else {
                $requirements[$packageName] = $versionSelector->findRecommendedRequireVersion($package);
            }
            $this->getIO()->writeError(sprintf('Using version <info>%s</info> for <info>%s</info>', $requirements[$packageName], $packageName));
            if (Preg::isMatch('{^dev-(?!main$|master$|trunk$|latest$)}', $requirements[$packageName])) {
                $this->getIO()->warning('Version ' . $requirements[$packageName] . ' looks like it may be a feature branch which is unlikely to keep working in the long run and may be in an unstable state');
                if ($this->getIO()->isInteractive() && !$this->getIO()->askConfirmation('Are you sure you want to use this constraint (<comment>y</comment>) or would you rather abort (<comment>n</comment>) the whole operation [<comment>y,n</comment>]? ')) {
                    $this->revertComposerFile();
                    return 1;
                }
            }
        }
        if (!$dryRun) {
            $this->updateFile($this->json, $requirements, $requireKey, $removeKey, $sortPackages);
            if ($locker->isLocked() && $composer->getConfig()->get('lock')) {
                $stabilityFlags = RootPackageLoader::extractStabilityFlags($requirements, $composer->getPackage()->getMinimumStability(), []);
                $locker->updateHash($this->json, static function (array $lockData) use ($stabilityFlags) {
                    foreach ($stabilityFlags as $packageName => $flag) {
                        $lockData['stability-flags'][$packageName] = $flag;
                    }
                    return $lockData;
                });
            }
        }
        return 0;
    }
    /**
     * @param array<string, string> $new
     */
    private function updateFile(JsonFile $json, array $new, string $requireKey, string $removeKey, bool $sortPackages): void
    {
        if ($this->updateFileCleanly($json, $new, $requireKey, $removeKey, $sortPackages)) {
            return;
        }
        $composerDefinition = $this->json->read();
        foreach ($new as $package => $version) {
            $composerDefinition[$requireKey][$package] = $version;
            unset($composerDefinition[$removeKey][$package]);
            if (isset($composerDefinition[$removeKey]) && count($composerDefinition[$removeKey]) === 0) {
                unset($composerDefinition[$removeKey]);
            }
        }
        $this->json->write($composerDefinition);
    }
    /**
     * @param array<string, string> $new
     */
    private function updateFileCleanly(JsonFile $json, array $new, string $requireKey, string $removeKey, bool $sortPackages): bool
    {
        $contents = file_get_contents($json->getPath());
        $manipulator = new JsonManipulator($contents);
        foreach ($new as $package => $constraint) {
            if (!$manipulator->addLink($requireKey, $package, $constraint, $sortPackages)) {
                return \false;
            }
            if (!$manipulator->removeSubNode($removeKey, $package)) {
                return \false;
            }
        }
        $manipulator->removeMainKeyIfEmpty($removeKey);
        file_put_contents($json->getPath(), $manipulator->getContents());
        return \true;
    }
    protected function interact(InputInterface $input, OutputInterface $output): void
    {
    }
    private function revertComposerFile(): void
    {
        $io = $this->getIO();
        if ($this->newlyCreated) {
            $io->writeError("\n" . '<error>Installation failed, deleting ' . $this->file . '.</error>');
            unlink($this->json->getPath());
            if (file_exists($this->lock)) {
                unlink($this->lock);
            }
        } else {
            $msg = ' to its ';
            if ($this->lockBackup) {
                $msg = ' and ' . $this->lock . ' to their ';
            }
            $io->writeError("\n" . '<error>Installation failed, reverting ' . $this->file . $msg . 'original content.</error>');
            file_put_contents($this->json->getPath(), $this->composerBackup);
            if ($this->lockBackup) {
                file_put_contents($this->lock, $this->lockBackup);
            }
        }
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer\Command;

use Composer\Composer;
use Composer\Package\BasePackage;
use Composer\Package\PackageInterface;
use Composer\Pcre\Preg;
use Composer\Repository\CompositeRepository;
use Composer\Repository\InstalledRepository;
use Composer\Repository\PlatformRepository;
use Composer\Repository\RepositoryInterface;
use Composer\Repository\RootPackageRepository;
use _ContaoManager\Symfony\Component\Console\Completion\CompletionInput;
/**
 * Adds completion to arguments and options.
 *
 * @internal
 */
trait CompletionTrait
{
    /**
     * @see BaseCommand::requireComposer()
     */
    abstract public function requireComposer(?bool $disablePlugins = null, ?bool $disableScripts = null): Composer;
    /**
     * Suggestion values for "prefer-install" option
     *
     * @return list<string>
     */
    private function suggestPreferInstall(): array
    {
        return ['dist', 'source', 'auto'];
    }
    /**
     * Suggest package names from root requirements.
     */
    private function suggestRootRequirement(): \Closure
    {
        return function (CompletionInput $input): array {
            $composer = $this->requireComposer();
            return array_merge(array_keys($composer->getPackage()->getRequires()), array_keys($composer->getPackage()->getDevRequires()));
        };
    }
    /**
     * Suggest package names from installed.
     */
    private function suggestInstalledPackage(bool $includeRootPackage = \true, bool $includePlatformPackages = \false): \Closure
    {
        return function (CompletionInput $input) use ($includeRootPackage, $includePlatformPackages): array {
            $composer = $this->requireComposer();
            $installedRepos = [];
            if ($includeRootPackage) {
                $installedRepos[] = new RootPackageRepository(clone $composer->getPackage());
            }
            $locker = $composer->getLocker();
            if ($locker->isLocked()) {
                $installedRepos[] = $locker->getLockedRepository(\true);
            } else {
                $installedRepos[] = $composer->getRepositoryManager()->getLocalRepository();
            }
            $platformHint = [];
            if ($includePlatformPackages) {
                if ($locker->isLocked()) {
                    $platformRepo = new PlatformRepository([], $locker->getPlatformOverrides());
                } else {
                    $platformRepo = new PlatformRepository([], $composer->getConfig()->get('platform'));
                }
                if ($input->getCompletionValue() === '') {
                    // to reduce noise, when no text is yet entered we list only two entries for ext- and lib- prefixes
                    $hintsToFind = ['ext-' => 0, 'lib-' => 0, 'php' => 99, 'composer' => 99];
                    foreach ($platformRepo->getPackages() as $pkg) {
                        foreach ($hintsToFind as $hintPrefix => $hintCount) {
                            if (str_starts_with($pkg->getName(), $hintPrefix)) {
                                if ($hintCount === 0 || $hintCount >= 99) {
                                    $platformHint[] = $pkg->getName();
                                    $hintsToFind[$hintPrefix]++;
                                } elseif ($hintCount === 1) {
                                    unset($hintsToFind[$hintPrefix]);
                                    $platformHint[] = substr($pkg->getName(), 0, max(strlen($pkg->getName()) - 3, strlen($hintPrefix) + 1)) . '...';
                                }
                                continue 2;
                            }
                        }
                    }
                } else {
                    $installedRepos[] = $platformRepo;
                }
            }
            $installedRepo = new InstalledRepository($installedRepos);
            return array_merge(array_map(static function (PackageInterface $package) {
                return $package->getName();
            }, $installedRepo->getPackages()), $platformHint);
        };
    }
    /**
     * Suggest package names from installed.
     */
    private function suggestInstalledPackageTypes(bool $includeRootPackage = \true): \Closure
    {
        return function (CompletionInput $input) use ($includeRootPackage): array {
            $composer = $this->requireComposer();
            $installedRepos = [];
            if ($includeRootPackage) {
                $installedRepos[] = new RootPackageRepository(clone $composer->getPackage());
            }
            $locker = $composer->getLocker();
            if ($locker->isLocked()) {
                $installedRepos[] = $locker->getLockedRepository(\true);
            } else {
                $installedRepos[] = $composer->getRepositoryManager()->getLocalRepository();
            }
            $installedRepo = new InstalledRepository($installedRepos);
            return array_values(array_unique(array_map(static function (PackageInterface $package) {
                return $package->getType();
            }, $installedRepo->getPackages())));
        };
    }
    /**
     * Suggest package names available on all configured repositories.
     */
    private function suggestAvailablePackage(int $max = 99): \Closure
    {
        return function (CompletionInput $input) use ($max): array {
            if ($max < 1) {
                return [];
            }
            $composer = $this->requireComposer();
            $repos = new CompositeRepository($composer->getRepositoryManager()->getRepositories());
            $results = [];
            $showVendors = \false;
            if (!str_contains($input->getCompletionValue(), '/')) {
                $results = $repos->search('^' . preg_quote($input->getCompletionValue()), RepositoryInterface::SEARCH_VENDOR);
                $showVendors = \true;
            }
            // if we get a single vendor, we expand it into its contents already
            if (\count($results) <= 1) {
                $results = $repos->search('^' . preg_quote($input->getCompletionValue()), RepositoryInterface::SEARCH_NAME);
                $showVendors = \false;
            }
            $results = array_column($results, 'name');
            if ($showVendors) {
                $results = array_map(static function (string $name): string {
                    return $name . '/';
                }, $results);
                // sort shorter results first to avoid auto-expanding the completion to a longer string than needed
                usort($results, static function (string $a, string $b) {
                    $lenA = \strlen($a);
                    $lenB = \strlen($b);
                    if ($lenA === $lenB) {
                        return $a <=> $b;
                    }
                    return $lenA - $lenB;
                });
                $pinned = [];
                // ensure if the input is an exact match that it is always in the result set
                $completionInput = $input->getCompletionValue() . '/';
                if (\false !== $exactIndex = array_search($completionInput, $results, \true)) {
                    $pinned[] = $completionInput;
                    array_splice($results, $exactIndex, 1);
                }
                return array_merge($pinned, array_slice($results, 0, $max - \count($pinned)));
            }
            return array_slice($results, 0, $max);
        };
    }
    /**
     * Suggest package names available on all configured repositories or
     * platform packages from the ones available on the currently-running PHP
     */
    private function suggestAvailablePackageInclPlatform(): \Closure
    {
        return function (CompletionInput $input): array {
            if (Preg::isMatch('{^(ext|lib|php)(-|$)|^com}', $input->getCompletionValue())) {
                $matches = $this->suggestPlatformPackage()($input);
            } else {
                $matches = [];
            }
            return array_merge($matches, $this->suggestAvailablePackage(99 - \count($matches))($input));
        };
    }
    /**
     * Suggest platform packages from the ones available on the currently-running PHP
     */
    private function suggestPlatformPackage(): \Closure
    {
        return function (CompletionInput $input): array {
            $repos = new PlatformRepository([], $this->requireComposer()->getConfig()->get('platform'));
            $pattern = BasePackage::packageNameToRegexp($input->getCompletionValue() . '*');
            return array_filter(array_map(static function (PackageInterface $package) {
                return $package->getName();
            }, $repos->getPackages()), static function (string $name) use ($pattern): bool {
                return Preg::isMatch($pattern, $name);
            });
        };
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer\Command;

use Composer\Cache;
use Composer\Factory;
use _ContaoManager\Symfony\Component\Console\Input\InputInterface;
use _ContaoManager\Symfony\Component\Console\Input\InputOption;
use _ContaoManager\Symfony\Component\Console\Output\OutputInterface;
/**
 * @author David Neilsen <petah.p@gmail.com>
 */
class ClearCacheCommand extends \Composer\Command\BaseCommand
{
    protected function configure(): void
    {
        $this->setName('clear-cache')->setAliases(['clearcache', 'cc'])->setDescription('Clears composer\'s internal package cache')->setDefinition([new InputOption('gc', null, InputOption::VALUE_NONE, 'Only run garbage collection, not a full cache clear')])->setHelp(<<<EOT
The <info>clear-cache</info> deletes all cached packages from composer's
cache directory.

Read more at https://getcomposer.org/doc/03-cli.md#clear-cache-clearcache-cc
EOT
);
    }
    protected function execute(InputInterface $input, OutputInterface $output): int
    {
        $composer = $this->tryComposer();
        if ($composer !== null) {
            $config = $composer->getConfig();
        } else {
            $config = Factory::createConfig();
        }
        $io = $this->getIO();
        $cachePaths = ['cache-vcs-dir' => $config->get('cache-vcs-dir'), 'cache-repo-dir' => $config->get('cache-repo-dir'), 'cache-files-dir' => $config->get('cache-files-dir'), 'cache-dir' => $config->get('cache-dir')];
        foreach ($cachePaths as $key => $cachePath) {
            // only individual dirs get garbage collected
            if ($key === 'cache-dir' && $input->getOption('gc')) {
                continue;
            }
            $cachePath = realpath($cachePath);
            if (!$cachePath) {
                $io->writeError("<info>Cache directory does not exist ({$key}): {$cachePath}</info>");
                continue;
            }
            $cache = new Cache($io, $cachePath);
            $cache->setReadOnly($config->get('cache-read-only'));
            if (!$cache->isEnabled()) {
                $io->writeError("<info>Cache is not enabled ({$key}): {$cachePath}</info>");
                continue;
            }
            if ($input->getOption('gc')) {
                $io->writeError("<info>Garbage-collecting cache ({$key}): {$cachePath}</info>");
                if ($key === 'cache-files-dir') {
                    $cache->gc($config->get('cache-files-ttl'), $config->get('cache-files-maxsize'));
                } elseif ($key === 'cache-repo-dir') {
                    $cache->gc($config->get('cache-ttl'), 1024 * 1024 * 1024);
                } elseif ($key === 'cache-vcs-dir') {
                    $cache->gcVcsCache($config->get('cache-ttl'));
                }
            } else {
                $io->writeError("<info>Clearing cache ({$key}): {$cachePath}</info>");
                $cache->clear();
            }
        }
        if ($input->getOption('gc')) {
            $io->writeError('<info>All caches garbage-collected.</info>');
        } else {
            $io->writeError('<info>All caches cleared.</info>');
        }
        return 0;
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer\Command;

use Composer\Advisory\Auditor;
use Composer\Composer;
use Composer\Factory;
use Composer\Config;
use Composer\Downloader\TransportException;
use Composer\IO\BufferIO;
use Composer\Json\JsonFile;
use Composer\Json\JsonValidationException;
use Composer\Package\Locker;
use Composer\Package\RootPackage;
use Composer\Package\Version\VersionParser;
use Composer\Pcre\Preg;
use Composer\Repository\ComposerRepository;
use Composer\Repository\FilesystemRepository;
use Composer\Repository\PlatformRepository;
use Composer\Plugin\CommandEvent;
use Composer\Plugin\PluginEvents;
use Composer\Repository\RepositorySet;
use Composer\Util\ConfigValidator;
use Composer\Util\Git;
use Composer\Util\IniHelper;
use Composer\Util\ProcessExecutor;
use Composer\Util\HttpDownloader;
use Composer\Util\Platform;
use Composer\SelfUpdate\Keys;
use Composer\SelfUpdate\Versions;
use Composer\IO\NullIO;
use Composer\Package\CompletePackageInterface;
use Composer\XdebugHandler\XdebugHandler;
use _ContaoManager\Symfony\Component\Console\Input\InputInterface;
use _ContaoManager\Symfony\Component\Console\Output\OutputInterface;
use _ContaoManager\Symfony\Component\Process\ExecutableFinder;
use Composer\Util\Http\ProxyManager;
use Composer\Util\Http\RequestProxy;
/**
 * @author Jordi Boggiano <j.boggiano@seld.be>
 */
class DiagnoseCommand extends \Composer\Command\BaseCommand
{
    /** @var HttpDownloader */
    protected $httpDownloader;
    /** @var ProcessExecutor */
    protected $process;
    /** @var int */
    protected $exitCode = 0;
    protected function configure(): void
    {
        $this->setName('diagnose')->setDescription('Diagnoses the system to identify common errors')->setHelp(<<<EOT
The <info>diagnose</info> command checks common errors to help debugging problems.

The process exit code will be 1 in case of warnings and 2 for errors.

Read more at https://getcomposer.org/doc/03-cli.md#diagnose
EOT
);
    }
    protected function execute(InputInterface $input, OutputInterface $output): int
    {
        $composer = $this->tryComposer();
        $io = $this->getIO();
        if ($composer) {
            $config = $composer->getConfig();
            $commandEvent = new CommandEvent(PluginEvents::COMMAND, 'diagnose', $input, $output);
            $composer->getEventDispatcher()->dispatch($commandEvent->getName(), $commandEvent);
            $this->process = $composer->getLoop()->getProcessExecutor() ?? new ProcessExecutor($io);
        } else {
            $config = Factory::createConfig();
            $this->process = new ProcessExecutor($io);
        }
        $config->merge(['config' => ['secure-http' => \false]], Config::SOURCE_COMMAND);
        $config->prohibitUrlByConfig('http://repo.packagist.org', new NullIO());
        $this->httpDownloader = Factory::createHttpDownloader($io, $config);
        if (strpos(__FILE__, 'phar:') === 0) {
            $io->write('Checking pubkeys: ', \false);
            $this->outputResult($this->checkPubKeys($config));
            $io->write('Checking Composer version: ', \false);
            $this->outputResult($this->checkVersion($config));
        }
        $io->write(sprintf('Composer version: <comment>%s</comment>', Composer::getVersion()));
        $io->write('Checking Composer and its dependencies for vulnerabilities: ', \false);
        $this->outputResult($this->checkComposerAudit($config));
        $platformOverrides = $config->get('platform') ?: [];
        $platformRepo = new PlatformRepository([], $platformOverrides);
        $phpPkg = $platformRepo->findPackage('php', '*');
        $phpVersion = $phpPkg->getPrettyVersion();
        if ($phpPkg instanceof CompletePackageInterface && str_contains((string) $phpPkg->getDescription(), 'overridden')) {
            $phpVersion .= ' - ' . $phpPkg->getDescription();
        }
        $io->write(sprintf('PHP version: <comment>%s</comment>', $phpVersion));
        if (defined('PHP_BINARY')) {
            $io->write(sprintf('PHP binary path: <comment>%s</comment>', \PHP_BINARY));
        }
        $io->write('OpenSSL version: ' . (defined('OPENSSL_VERSION_TEXT') ? '<comment>' . \OPENSSL_VERSION_TEXT . '</comment>' : '<error>missing</error>'));
        $io->write('curl version: ' . $this->getCurlVersion());
        $finder = new ExecutableFinder();
        $hasSystemUnzip = (bool) $finder->find('unzip');
        $bin7zip = '';
        if ($hasSystem7zip = (bool) $finder->find('7z', null, ['C:\Program Files\7-Zip'])) {
            $bin7zip = '7z';
        } elseif (!Platform::isWindows() && $hasSystem7zip = (bool) $finder->find('7zz')) {
            $bin7zip = '7zz';
        } elseif (!Platform::isWindows() && $hasSystem7zip = (bool) $finder->find('7za')) {
            $bin7zip = '7za';
        }
        $io->write('zip: ' . (extension_loaded('zip') ? '<comment>extension present</comment>' : '<comment>extension not loaded</comment>') . ', ' . ($hasSystemUnzip ? '<comment>unzip present</comment>' : '<comment>unzip not available</comment>') . ', ' . ($hasSystem7zip ? '<comment>7-Zip present (' . $bin7zip . ')</comment>' : '<comment>7-Zip not available</comment>') . (($hasSystem7zip || $hasSystemUnzip) && !function_exists('proc_open') ? ', <warning>proc_open is disabled or not present, unzip/7-z will not be usable</warning>' : ''));
        if ($composer) {
            $io->write('Active plugins: ' . implode(', ', $composer->getPluginManager()->getRegisteredPlugins()));
            $io->write('Checking composer.json: ', \false);
            $this->outputResult($this->checkComposerSchema());
            if ($composer->getLocker()->isLocked()) {
                $io->write('Checking composer.lock: ', \false);
                $this->outputResult($this->checkComposerLockSchema($composer->getLocker()));
            }
        }
        $io->write('Checking platform settings: ', \false);
        $this->outputResult($this->checkPlatform());
        $io->write('Checking git settings: ', \false);
        $this->outputResult($this->checkGit());
        $io->write('Checking http connectivity to packagist: ', \false);
        $this->outputResult($this->checkHttp('http', $config));
        $io->write('Checking https connectivity to packagist: ', \false);
        $this->outputResult($this->checkHttp('https', $config));
        foreach ($config->getRepositories() as $repo) {
            if (($repo['type'] ?? null) === 'composer' && isset($repo['url'])) {
                $composerRepo = new ComposerRepository($repo, $this->getIO(), $config, $this->httpDownloader);
                $reflMethod = new \ReflectionMethod($composerRepo, 'getPackagesJsonUrl');
                if (\PHP_VERSION_ID < 80100) {
                    $reflMethod->setAccessible(\true);
                }
                $url = $reflMethod->invoke($composerRepo);
                if (!str_starts_with($url, 'http')) {
                    continue;
                }
                if (str_starts_with($url, 'https://repo.packagist.org')) {
                    continue;
                }
                $io->write('Checking connectivity to ' . $repo['url'] . ': ', \false);
                $this->outputResult($this->checkComposerRepo($url, $config));
            }
        }
        $proxyManager = ProxyManager::getInstance();
        $protos = $config->get('disable-tls') === \true ? ['http'] : ['http', 'https'];
        try {
            foreach ($protos as $proto) {
                $proxy = $proxyManager->getProxyForRequest($proto . '://repo.packagist.org');
                if ($proxy->getStatus() !== '') {
                    $type = $proxy->isSecure() ? 'HTTPS' : 'HTTP';
                    $io->write('Checking ' . $type . ' proxy with ' . $proto . ': ', \false);
                    $this->outputResult($this->checkHttpProxy($proxy, $proto));
                }
            }
        } catch (TransportException $e) {
            $io->write('Checking HTTP proxy: ', \false);
            $status = $this->checkConnectivityAndComposerNetworkHttpEnablement();
            $this->outputResult(is_string($status) ? $status : $e);
        }
        if (count($oauth = $config->get('github-oauth')) > 0) {
            foreach ($oauth as $domain => $token) {
                $io->write('Checking ' . $domain . ' oauth access: ', \false);
                $this->outputResult($this->checkGithubOauth($domain, $token));
            }
        } else {
            $io->write('Checking github.com rate limit: ', \false);
            try {
                $rate = $this->getGithubRateLimit('github.com');
                if (!is_array($rate)) {
                    $this->outputResult($rate);
                } elseif (10 > $rate['remaining']) {
                    $io->write('<warning>WARNING</warning>');
                    $io->write(sprintf('<comment>GitHub has a rate limit on their API. ' . 'You currently have <options=bold>%u</options=bold> ' . 'out of <options=bold>%u</options=bold> requests left.' . \PHP_EOL . 'See https://developer.github.com/v3/#rate-limiting and also' . \PHP_EOL . '    https://getcomposer.org/doc/articles/troubleshooting.md#api-rate-limit-and-oauth-tokens</comment>', $rate['remaining'], $rate['limit']));
                } else {
                    $this->outputResult(\true);
                }
            } catch (\Exception $e) {
                if ($e instanceof TransportException && $e->getCode() === 401) {
                    $this->outputResult('<comment>The oauth token for github.com seems invalid, run "composer config --global --unset github-oauth.github.com" to remove it</comment>');
                } else {
                    $this->outputResult($e);
                }
            }
        }
        $io->write('Checking disk free space: ', \false);
        $this->outputResult($this->checkDiskSpace($config));
        return $this->exitCode;
    }
    /**
     * @return string|true
     */
    private function checkComposerSchema()
    {
        $validator = new ConfigValidator($this->getIO());
        [$errors, , $warnings] = $validator->validate(Factory::getComposerFile());
        if ($errors || $warnings) {
            $messages = ['error' => $errors, 'warning' => $warnings];
            $output = '';
            foreach ($messages as $style => $msgs) {
                foreach ($msgs as $msg) {
                    $output .= '<' . $style . '>' . $msg . '</' . $style . '>' . \PHP_EOL;
                }
            }
            return rtrim($output);
        }
        return \true;
    }
    /**
     * @return string|true
     */
    private function checkComposerLockSchema(Locker $locker)
    {
        $json = $locker->getJsonFile();
        try {
            $json->validateSchema(JsonFile::LOCK_SCHEMA);
        } catch (JsonValidationException $e) {
            $output = '';
            foreach ($e->getErrors() as $error) {
                $output .= '<error>' . $error . '</error>' . \PHP_EOL;
            }
            return trim($output);
        }
        return \true;
    }
    private function checkGit(): string
    {
        if (!function_exists('proc_open')) {
            return '<comment>proc_open is not available, git cannot be used</comment>';
        }
        $this->process->execute(['git', 'config', 'color.ui'], $output);
        if (strtolower(trim($output)) === 'always') {
            return '<comment>Your git color.ui setting is set to always, this is known to create issues. Use "git config --global color.ui true" to set it correctly.</comment>';
        }
        $gitVersion = Git::getVersion($this->process);
        if (null === $gitVersion) {
            return '<comment>No git process found</>';
        }
        if (version_compare('2.24.0', $gitVersion, '>')) {
            return '<warning>Your git version (' . $gitVersion . ') is too old and possibly will cause issues. Please upgrade to git 2.24 or above</>';
        }
        return '<info>OK</> <comment>git version ' . $gitVersion . '</>';
    }
    /**
     * @return string|string[]|true
     */
    private function checkHttp(string $proto, Config $config)
    {
        $result = $this->checkConnectivityAndComposerNetworkHttpEnablement();
        if ($result !== \true) {
            return $result;
        }
        $result = [];
        if ($proto === 'https' && $config->get('disable-tls') === \true) {
            $tlsWarning = '<warning>Composer is configured to disable SSL/TLS protection. This will leave remote HTTPS requests vulnerable to Man-In-The-Middle attacks.</warning>';
        }
        try {
            $this->httpDownloader->get($proto . '://repo.packagist.org/packages.json');
        } catch (TransportException $e) {
            $hints = HttpDownloader::getExceptionHints($e);
            if (null !== $hints && count($hints) > 0) {
                foreach ($hints as $hint) {
                    $result[] = $hint;
                }
            }
            $result[] = '<error>[' . get_class($e) . '] ' . $e->getMessage() . '</error>';
        }
        if (isset($tlsWarning)) {
            $result[] = $tlsWarning;
        }
        if (count($result) > 0) {
            return $result;
        }
        return \true;
    }
    /**
     * @return string|string[]|true
     */
    private function checkComposerRepo(string $url, Config $config)
    {
        $result = $this->checkConnectivityAndComposerNetworkHttpEnablement();
        if ($result !== \true) {
            return $result;
        }
        $result = [];
        if (str_starts_with($url, 'https://') && $config->get('disable-tls') === \true) {
            $tlsWarning = '<warning>Composer is configured to disable SSL/TLS protection. This will leave remote HTTPS requests vulnerable to Man-In-The-Middle attacks.</warning>';
        }
        try {
            $this->httpDownloader->get($url);
        } catch (TransportException $e) {
            $hints = HttpDownloader::getExceptionHints($e);
            if (null !== $hints && count($hints) > 0) {
                foreach ($hints as $hint) {
                    $result[] = $hint;
                }
            }
            $result[] = '<error>[' . get_class($e) . '] ' . $e->getMessage() . '</error>';
        }
        if (isset($tlsWarning)) {
            $result[] = $tlsWarning;
        }
        if (count($result) > 0) {
            return $result;
        }
        return \true;
    }
    /**
     * @return string|\Exception
     */
    private function checkHttpProxy(RequestProxy $proxy, string $protocol)
    {
        $result = $this->checkConnectivityAndComposerNetworkHttpEnablement();
        if ($result !== \true) {
            return $result;
        }
        try {
            $proxyStatus = $proxy->getStatus();
            if ($proxy->isExcludedByNoProxy()) {
                return '<info>SKIP</> <comment>Because repo.packagist.org is ' . $proxyStatus . '</>';
            }
            $json = $this->httpDownloader->get($protocol . '://repo.packagist.org/packages.json')->decodeJson();
            if (isset($json['provider-includes'])) {
                $hash = reset($json['provider-includes']);
                $hash = $hash['sha256'];
                $path = str_replace('%hash%', $hash, key($json['provider-includes']));
                $provider = $this->httpDownloader->get($protocol . '://repo.packagist.org/' . $path)->getBody();
                if (hash('sha256', $provider) !== $hash) {
                    return '<warning>It seems that your proxy (' . $proxyStatus . ') is modifying ' . $protocol . ' traffic on the fly</>';
                }
            }
            return '<info>OK</> <comment>' . $proxyStatus . '</>';
        } catch (\Exception $e) {
            return $e;
        }
    }
    /**
     * @return string|\Exception
     */
    private function checkGithubOauth(string $domain, string $token)
    {
        $result = $this->checkConnectivityAndComposerNetworkHttpEnablement();
        if ($result !== \true) {
            return $result;
        }
        $this->getIO()->setAuthentication($domain, $token, 'x-oauth-basic');
        try {
            $url = $domain === 'github.com' ? 'https://api.' . $domain . '/' : 'https://' . $domain . '/api/v3/';
            $response = $this->httpDownloader->get($url, ['retry-auth-failure' => \false]);
            $expiration = $response->getHeader('github-authentication-token-expiration');
            if ($expiration === null) {
                return '<info>OK</> <comment>does not expire</>';
            }
            return '<info>OK</> <comment>expires on ' . $expiration . '</>';
        } catch (\Exception $e) {
            if ($e instanceof TransportException && $e->getCode() === 401) {
                return '<comment>The oauth token for ' . $domain . ' seems invalid, run "composer config --global --unset github-oauth.' . $domain . '" to remove it</comment>';
            }
            return $e;
        }
    }
    /**
     * @throws TransportException
     * @return mixed|string
     */
    private function getGithubRateLimit(string $domain, ?string $token = null)
    {
        $result = $this->checkConnectivityAndComposerNetworkHttpEnablement();
        if ($result !== \true) {
            return $result;
        }
        if ($token) {
            $this->getIO()->setAuthentication($domain, $token, 'x-oauth-basic');
        }
        $url = $domain === 'github.com' ? 'https://api.' . $domain . '/rate_limit' : 'https://' . $domain . '/api/rate_limit';
        $data = $this->httpDownloader->get($url, ['retry-auth-failure' => \false])->decodeJson();
        return $data['resources']['core'];
    }
    /**
     * @return string|true
     */
    private function checkDiskSpace(Config $config)
    {
        if (!function_exists('disk_free_space')) {
            return \true;
        }
        $minSpaceFree = 1024 * 1024;
        if (($df = @disk_free_space($dir = $config->get('home'))) !== \false && $df < $minSpaceFree || ($df = @disk_free_space($dir = $config->get('vendor-dir'))) !== \false && $df < $minSpaceFree) {
            return '<error>The disk hosting ' . $dir . ' is full</error>';
        }
        return \true;
    }
    /**
     * @return string[]|true
     */
    private function checkPubKeys(Config $config)
    {
        $home = $config->get('home');
        $errors = [];
        $io = $this->getIO();
        if (file_exists($home . '/keys.tags.pub') && file_exists($home . '/keys.dev.pub')) {
            $io->write('');
        }
        if (file_exists($home . '/keys.tags.pub')) {
            $io->write('Tags Public Key Fingerprint: ' . Keys::fingerprint($home . '/keys.tags.pub'));
        } else {
            $errors[] = '<error>Missing pubkey for tags verification</error>';
        }
        if (file_exists($home . '/keys.dev.pub')) {
            $io->write('Dev Public Key Fingerprint: ' . Keys::fingerprint($home . '/keys.dev.pub'));
        } else {
            $errors[] = '<error>Missing pubkey for dev verification</error>';
        }
        if ($errors) {
            $errors[] = '<error>Run composer self-update --update-keys to set them up</error>';
        }
        return $errors ?: \true;
    }
    /**
     * @return string|\Exception|true
     */
    private function checkVersion(Config $config)
    {
        $result = $this->checkConnectivityAndComposerNetworkHttpEnablement();
        if ($result !== \true) {
            return $result;
        }
        $versionsUtil = new Versions($config, $this->httpDownloader);
        try {
            $latest = $versionsUtil->getLatest();
        } catch (\Exception $e) {
            return $e;
        }
        if (Composer::VERSION !== $latest['version'] && Composer::VERSION !== '@package_version@') {
            return '<comment>You are not running the latest ' . $versionsUtil->getChannel() . ' version, run `composer self-update` to update (' . Composer::VERSION . ' => ' . $latest['version'] . ')</comment>';
        }
        return \true;
    }
    /**
     * @return string|true
     */
    private function checkComposerAudit(Config $config)
    {
        $result = $this->checkConnectivityAndComposerNetworkHttpEnablement();
        if ($result !== \true) {
            return $result;
        }
        $auditor = new Auditor();
        $repoSet = new RepositorySet();
        $installedJson = new JsonFile(__DIR__ . '/../../../vendor/composer/installed.json');
        if (!$installedJson->exists()) {
            return '<warning>Could not find Composer\'s installed.json, this must be a non-standard Composer installation.</>';
        }
        $localRepo = new FilesystemRepository($installedJson);
        $version = Composer::getVersion();
        $packages = $localRepo->getCanonicalPackages();
        if ($version !== '@package_version@') {
            $versionParser = new VersionParser();
            $normalizedVersion = $versionParser->normalize($version);
            $rootPkg = new RootPackage('composer/composer', $normalizedVersion, $version);
            $packages[] = $rootPkg;
        }
        $repoSet->addRepository(new ComposerRepository(['type' => 'composer', 'url' => 'https://packagist.org'], new NullIO(), $config, $this->httpDownloader));
        try {
            $io = new BufferIO();
            $result = $auditor->audit($io, $repoSet, $packages, Auditor::FORMAT_TABLE, \true, [], Auditor::ABANDONED_IGNORE);
        } catch (\Throwable $e) {
            return '<highlight>Failed performing audit: ' . $e->getMessage() . '</>';
        }
        if ($result > 0) {
            return '<highlight>Audit found some issues:</>' . \PHP_EOL . $io->getOutput();
        }
        return \true;
    }
    private function getCurlVersion(): string
    {
        if (extension_loaded('curl')) {
            if (!HttpDownloader::isCurlEnabled()) {
                return '<error>disabled via disable_functions, using php streams fallback, which reduces performance</error>';
            }
            $version = curl_version();
            $libzVersion = isset($version['libz_version']) && $version['libz_version'] !== '' ? $version['libz_version'] : 'missing';
            $brotliVersion = isset($version['brotli_version']) && $version['brotli_version'] !== '' ? $version['brotli_version'] : 'missing';
            $sslVersion = isset($version['ssl_version']) && $version['ssl_version'] !== '' ? $version['ssl_version'] : 'missing';
            $hasZstd = isset($version['features']) && defined('CURL_VERSION_ZSTD') && 0 !== ($version['features'] & \CURL_VERSION_ZSTD);
            $httpVersions = '1.0, 1.1';
            if (isset($version['features']) && \defined('CURL_VERSION_HTTP2') && \defined('CURL_HTTP_VERSION_2_0') && (\CURL_VERSION_HTTP2 & $version['features']) !== 0) {
                $httpVersions .= ', 2';
            }
            if (isset($version['features']) && \defined('CURL_VERSION_HTTP3') && ($version['features'] & \CURL_VERSION_HTTP3) !== 0) {
                $httpVersions .= ', 3';
            }
            return '<comment>' . $version['version'] . '</comment> ' . 'libz <comment>' . $libzVersion . '</comment> ' . 'brotli <comment>' . $brotliVersion . '</comment> ' . 'zstd <comment>' . ($hasZstd ? 'supported' : 'missing') . '</comment> ' . 'ssl <comment>' . $sslVersion . '</comment> ' . 'HTTP <comment>' . $httpVersions . '</comment>';
        }
        return '<error>missing, using php streams fallback, which reduces performance</error>';
    }
    /**
     * @param bool|string|string[]|\Exception $result
     */
    private function outputResult($result): void
    {
        $io = $this->getIO();
        if (\true === $result) {
            $io->write('<info>OK</info>');
            return;
        }
        $hadError = \false;
        $hadWarning = \false;
        if ($result instanceof \Exception) {
            $result = '<error>[' . get_class($result) . '] ' . $result->getMessage() . '</error>';
        }
        if (!$result) {
            // falsey results should be considered as an error, even if there is nothing to output
            $hadError = \true;
        } else {
            if (!is_array($result)) {
                $result = [$result];
            }
            foreach ($result as $message) {
                if (\false !== strpos($message, '<error>')) {
                    $hadError = \true;
                } elseif (\false !== strpos($message, '<warning>')) {
                    $hadWarning = \true;
                }
            }
        }
        if ($hadError) {
            $io->write('<error>FAIL</error>');
            $this->exitCode = max($this->exitCode, 2);
        } elseif ($hadWarning) {
            $io->write('<warning>WARNING</warning>');
            $this->exitCode = max($this->exitCode, 1);
        }
        if ($result) {
            foreach ($result as $message) {
                $io->write(trim($message));
            }
        }
    }
    /**
     * @return string|true
     */
    private function checkPlatform()
    {
        $output = '';
        $out = static function ($msg, $style) use (&$output): void {
            $output .= '<' . $style . '>' . $msg . '</' . $style . '>' . \PHP_EOL;
        };
        // code below taken from getcomposer.org/installer, any changes should be made there and replicated here
        $errors = [];
        $warnings = [];
        $displayIniMessage = \false;
        $iniMessage = \PHP_EOL . \PHP_EOL . IniHelper::getMessage();
        $iniMessage .= \PHP_EOL . 'If you can not modify the ini file, you can also run `php -d option=value` to modify ini values on the fly. You can use -d multiple times.';
        if (!function_exists('json_decode')) {
            $errors['json'] = \true;
        }
        if (!extension_loaded('Phar')) {
            $errors['phar'] = \true;
        }
        if (!extension_loaded('filter')) {
            $errors['filter'] = \true;
        }
        if (!extension_loaded('hash')) {
            $errors['hash'] = \true;
        }
        if (!extension_loaded('iconv') && !extension_loaded('mbstring')) {
            $errors['iconv_mbstring'] = \true;
        }
        if (!filter_var(ini_get('allow_url_fopen'), \FILTER_VALIDATE_BOOLEAN)) {
            $errors['allow_url_fopen'] = \true;
        }
        if (extension_loaded('ionCube Loader') && ioncube_loader_iversion() < 40009) {
            $errors['ioncube'] = ioncube_loader_version();
        }
        if (\PHP_VERSION_ID < 70205) {
            $errors['php'] = \PHP_VERSION;
        }
        if (!extension_loaded('openssl')) {
            $errors['openssl'] = \true;
        }
        if (extension_loaded('openssl') && \OPENSSL_VERSION_NUMBER < 0x1000100f) {
            $warnings['openssl_version'] = \true;
        }
        if (!defined('HHVM_VERSION') && !extension_loaded('apcu') && filter_var(ini_get('apc.enable_cli'), \FILTER_VALIDATE_BOOLEAN)) {
            $warnings['apc_cli'] = \true;
        }
        if (!extension_loaded('zlib')) {
            $warnings['zlib'] = \true;
        }
        ob_start();
        phpinfo(\INFO_GENERAL);
        $phpinfo = ob_get_clean();
        if (is_string($phpinfo) && Preg::isMatchStrictGroups('{Configure Command(?: *</td><td class="v">| *=> *)(.*?)(?:</td>|$)}m', $phpinfo, $match)) {
            $configure = $match[1];
            if (str_contains($configure, '--enable-sigchild')) {
                $warnings['sigchild'] = \true;
            }
            if (str_contains($configure, '--with-curlwrappers')) {
                $warnings['curlwrappers'] = \true;
            }
        }
        if (filter_var(ini_get('xdebug.profiler_enabled'), \FILTER_VALIDATE_BOOLEAN)) {
            $warnings['xdebug_profile'] = \true;
        } elseif (XdebugHandler::isXdebugActive()) {
            $warnings['xdebug_loaded'] = \true;
        }
        if (defined('PHP_WINDOWS_VERSION_BUILD') && (version_compare(\PHP_VERSION, '7.2.23', '<') || version_compare(\PHP_VERSION, '7.3.0', '>=') && version_compare(\PHP_VERSION, '7.3.10', '<'))) {
            $warnings['onedrive'] = \PHP_VERSION;
        }
        if (extension_loaded('uopz') && !(filter_var(ini_get('uopz.disable'), \FILTER_VALIDATE_BOOLEAN) || filter_var(ini_get('uopz.exit'), \FILTER_VALIDATE_BOOLEAN))) {
            $warnings['uopz'] = \true;
        }
        if (!empty($errors)) {
            foreach ($errors as $error => $current) {
                switch ($error) {
                    case 'json':
                        $text = \PHP_EOL . "The json extension is missing." . \PHP_EOL;
                        $text .= "Install it or recompile php without --disable-json";
                        break;
                    case 'phar':
                        $text = \PHP_EOL . "The phar extension is missing." . \PHP_EOL;
                        $text .= "Install it or recompile php without --disable-phar";
                        break;
                    case 'filter':
                        $text = \PHP_EOL . "The filter extension is missing." . \PHP_EOL;
                        $text .= "Install it or recompile php without --disable-filter";
                        break;
                    case 'hash':
                        $text = \PHP_EOL . "The hash extension is missing." . \PHP_EOL;
                        $text .= "Install it or recompile php without --disable-hash";
                        break;
                    case 'iconv_mbstring':
                        $text = \PHP_EOL . "The iconv OR mbstring extension is required and both are missing." . \PHP_EOL;
                        $text .= "Install either of them or recompile php without --disable-iconv";
                        break;
                    case 'php':
                        $text = \PHP_EOL . "Your PHP ({$current}) is too old, you must upgrade to PHP 7.2.5 or higher.";
                        break;
                    case 'allow_url_fopen':
                        $text = \PHP_EOL . "The allow_url_fopen setting is incorrect." . \PHP_EOL;
                        $text .= "Add the following to the end of your `php.ini`:" . \PHP_EOL;
                        $text .= "    allow_url_fopen = On";
                        $displayIniMessage = \true;
                        break;
                    case 'ioncube':
                        $text = \PHP_EOL . "Your ionCube Loader extension ({$current}) is incompatible with Phar files." . \PHP_EOL;
                        $text .= "Upgrade to ionCube 4.0.9 or higher or remove this line (path may be different) from your `php.ini` to disable it:" . \PHP_EOL;
                        $text .= "    zend_extension = /usr/lib/php5/20090626+lfs/ioncube_loader_lin_5.3.so";
                        $displayIniMessage = \true;
                        break;
                    case 'openssl':
                        $text = \PHP_EOL . "The openssl extension is missing, which means that secure HTTPS transfers are impossible." . \PHP_EOL;
                        $text .= "If possible you should enable it or recompile php with --with-openssl";
                        break;
                    default:
                        throw new \InvalidArgumentException(sprintf("DiagnoseCommand: Unknown error type \"%s\". Please report at https://github.com/composer/composer/issues/new.", $error));
                }
                $out($text, 'error');
            }
            $output .= \PHP_EOL;
        }
        if (!empty($warnings)) {
            foreach ($warnings as $warning => $current) {
                switch ($warning) {
                    case 'apc_cli':
                        $text = "The apc.enable_cli setting is incorrect." . \PHP_EOL;
                        $text .= "Add the following to the end of your `php.ini`:" . \PHP_EOL;
                        $text .= "  apc.enable_cli = Off";
                        $displayIniMessage = \true;
                        break;
                    case 'zlib':
                        $text = 'The zlib extension is not loaded, this can slow down Composer a lot.' . \PHP_EOL;
                        $text .= 'If possible, enable it or recompile php with --with-zlib' . \PHP_EOL;
                        $displayIniMessage = \true;
                        break;
                    case 'sigchild':
                        $text = "PHP was compiled with --enable-sigchild which can cause issues on some platforms." . \PHP_EOL;
                        $text .= "Recompile it without this flag if possible, see also:" . \PHP_EOL;
                        $text .= "  https://bugs.php.net/bug.php?id=22999";
                        break;
                    case 'curlwrappers':
                        $text = "PHP was compiled with --with-curlwrappers which will cause issues with HTTP authentication and GitHub." . \PHP_EOL;
                        $text .= " Recompile it without this flag if possible";
                        break;
                    case 'openssl_version':
                        // Attempt to parse version number out, fallback to whole string value.
                        $opensslVersion = strstr(trim(strstr(\OPENSSL_VERSION_TEXT, ' ')), ' ', \true);
                        $opensslVersion = $opensslVersion ?: \OPENSSL_VERSION_TEXT;
                        $text = "The OpenSSL library ({$opensslVersion}) used by PHP does not support TLSv1.2 or TLSv1.1." . \PHP_EOL;
                        $text .= "If possible you should upgrade OpenSSL to version 1.0.1 or above.";
                        break;
                    case 'xdebug_loaded':
                        $text = "The xdebug extension is loaded, this can slow down Composer a little." . \PHP_EOL;
                        $text .= " Disabling it when using Composer is recommended.";
                        break;
                    case 'xdebug_profile':
                        $text = "The xdebug.profiler_enabled setting is enabled, this can slow down Composer a lot." . \PHP_EOL;
                        $text .= "Add the following to the end of your `php.ini` to disable it:" . \PHP_EOL;
                        $text .= "  xdebug.profiler_enabled = 0";
                        $displayIniMessage = \true;
                        break;
                    case 'onedrive':
                        $text = "The Windows OneDrive folder is not supported on PHP versions below 7.2.23 and 7.3.10." . \PHP_EOL;
                        $text .= "Upgrade your PHP ({$current}) to use this location with Composer." . \PHP_EOL;
                        break;
                    case 'uopz':
                        $text = "The uopz extension ignores exit calls and may not work with all Composer commands." . \PHP_EOL;
                        $text .= "Disabling it when using Composer is recommended.";
                        break;
                    default:
                        throw new \InvalidArgumentException(sprintf("DiagnoseCommand: Unknown warning type \"%s\". Please report at https://github.com/composer/composer/issues/new.", $warning));
                }
                $out($text, 'comment');
            }
        }
        if ($displayIniMessage) {
            $out($iniMessage, 'comment');
        }
        if (in_array(Platform::getEnv('COMPOSER_IPRESOLVE'), ['4', '6'], \true)) {
            $warnings['ipresolve'] = \true;
            $out('The COMPOSER_IPRESOLVE env var is set to ' . Platform::getEnv('COMPOSER_IPRESOLVE') . ' which may result in network failures below.', 'comment');
        }
        return count($warnings) === 0 && count($errors) === 0 ? \true : $output;
    }
    /**
     * Check if allow_url_fopen is ON
     *
     * @return string|true
     */
    private function checkConnectivity()
    {
        if (!ini_get('allow_url_fopen')) {
            return '<info>SKIP</> <comment>Because allow_url_fopen is missing.</>';
        }
        return \true;
    }
    /**
     * @return string|true
     */
    private function checkConnectivityAndComposerNetworkHttpEnablement()
    {
        $result = $this->checkConnectivity();
        if ($result !== \true) {
            return $result;
        }
        $result = $this->checkComposerNetworkHttpEnablement();
        if ($result !== \true) {
            return $result;
        }
        return \true;
    }
    /**
     * Check if Composer network is enabled for HTTP/S
     *
     * @return string|true
     */
    private function checkComposerNetworkHttpEnablement()
    {
        if ((bool) Platform::getEnv('COMPOSER_DISABLE_NETWORK')) {
            return '<info>SKIP</> <comment>Network is disabled by COMPOSER_DISABLE_NETWORK.</>';
        }
        return \true;
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer\Command;

use Composer\Factory;
use Composer\Pcre\Preg;
use Composer\Util\Filesystem;
use Composer\Util\Platform;
use _ContaoManager\Symfony\Component\Console\Command\Command;
use _ContaoManager\Symfony\Component\Console\Completion\CompletionInput;
use _ContaoManager\Symfony\Component\Console\Completion\CompletionSuggestions;
use _ContaoManager\Symfony\Component\Console\Input\InputInterface;
use Composer\Console\Input\InputArgument;
use _ContaoManager\Symfony\Component\Console\Input\StringInput;
use _ContaoManager\Symfony\Component\Console\Output\OutputInterface;
/**
 * @author Jordi Boggiano <j.boggiano@seld.be>
 */
class GlobalCommand extends \Composer\Command\BaseCommand
{
    public function complete(CompletionInput $input, CompletionSuggestions $suggestions): void
    {
        $application = $this->getApplication();
        if ($input->mustSuggestArgumentValuesFor('command-name')) {
            $suggestions->suggestValues(array_values(array_filter(array_map(static function (Command $command) {
                return $command->isHidden() ? null : $command->getName();
            }, $application->all()), static function (?string $cmd) {
                return $cmd !== null;
            })));
            return;
        }
        if ($application->has($commandName = $input->getArgument('command-name'))) {
            $input = $this->prepareSubcommandInput($input, \true);
            $input = CompletionInput::fromString($input->__toString(), 2);
            $command = $application->find($commandName);
            $command->mergeApplicationDefinition();
            $input->bind($command->getDefinition());
            $command->complete($input, $suggestions);
        }
    }
    protected function configure(): void
    {
        $this->setName('global')->setDescription('Allows running commands in the global composer dir ($COMPOSER_HOME)')->setDefinition([new InputArgument('command-name', InputArgument::REQUIRED, ''), new InputArgument('args', InputArgument::IS_ARRAY | InputArgument::OPTIONAL, '')])->setHelp(<<<EOT
Use this command as a wrapper to run other Composer commands
within the global context of COMPOSER_HOME.

You can use this to install CLI utilities globally, all you need
is to add the COMPOSER_HOME/vendor/bin dir to your PATH env var.

COMPOSER_HOME is c:\\Users\\<user>\\AppData\\Roaming\\Composer on Windows
and /home/<user>/.composer on unix systems.

If your system uses freedesktop.org standards, then it will first check
XDG_CONFIG_HOME or default to /home/<user>/.config/composer

Note: This path may vary depending on customizations to bin-dir in
composer.json or the environmental variable COMPOSER_BIN_DIR.

Read more at https://getcomposer.org/doc/03-cli.md#global
EOT
);
    }
    /**
     * @throws \Symfony\Component\Console\Exception\ExceptionInterface
     */
    public function run(InputInterface $input, OutputInterface $output): int
    {
        // TODO remove for Symfony 6+ as it is then in the interface
        if (!method_exists($input, '__toString')) {
            // @phpstan-ignore-line
            throw new \LogicException('Expected an Input instance that is stringable, got ' . get_class($input));
        }
        // extract real command name
        $tokens = Preg::split('{\s+}', $input->__toString());
        $args = [];
        foreach ($tokens as $token) {
            if ($token && $token[0] !== '-') {
                $args[] = $token;
                if (count($args) >= 2) {
                    break;
                }
            }
        }
        // show help for this command if no command was found
        if (count($args) < 2) {
            return parent::run($input, $output);
        }
        $input = $this->prepareSubcommandInput($input);
        return $this->getApplication()->run($input, $output);
    }
    private function prepareSubcommandInput(InputInterface $input, bool $quiet = \false): StringInput
    {
        // TODO remove for Symfony 6+ as it is then in the interface
        if (!method_exists($input, '__toString')) {
            // @phpstan-ignore-line
            throw new \LogicException('Expected an Input instance that is stringable, got ' . get_class($input));
        }
        // The COMPOSER env var should not apply to the global execution scope
        if (Platform::getEnv('COMPOSER')) {
            Platform::clearEnv('COMPOSER');
        }
        // change to global dir
        $config = Factory::createConfig();
        $home = $config->get('home');
        if (!is_dir($home)) {
            $fs = new Filesystem();
            $fs->ensureDirectoryExists($home);
            if (!is_dir($home)) {
                throw new \RuntimeException('Could not create home directory');
            }
        }
        try {
            chdir($home);
        } catch (\Exception $e) {
            throw new \RuntimeException('Could not switch to home directory "' . $home . '"', 0, $e);
        }
        if (!$quiet) {
            $this->getIO()->writeError('<info>Changed current directory to ' . $home . '</info>');
        }
        // create new input without "global" command prefix
        $input = new StringInput(Preg::replace('{\bg(?:l(?:o(?:b(?:a(?:l)?)?)?)?)?\b}', '', $input->__toString(), 1));
        $this->getApplication()->resetComposer();
        return $input;
    }
    /**
     * @inheritDoc
     */
    public function isProxyCommand(): bool
    {
        return \true;
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer\Command;

use Composer\Composer;
use _ContaoManager\Symfony\Component\Console\Input\InputInterface;
use _ContaoManager\Symfony\Component\Console\Output\OutputInterface;
/**
 * @author Jordi Boggiano <j.boggiano@seld.be>
 */
class AboutCommand extends \Composer\Command\BaseCommand
{
    protected function configure(): void
    {
        $this->setName('about')->setDescription('Shows a short information about Composer')->setHelp(<<<EOT
<info>php composer.phar about</info>
EOT
);
    }
    protected function execute(InputInterface $input, OutputInterface $output): int
    {
        $composerVersion = Composer::getVersion();
        $this->getIO()->write(<<<EOT
<info>Composer - Dependency Manager for PHP - version {$composerVersion}</info>
<comment>Composer is a dependency manager tracking local dependencies of your projects and libraries.
See https://getcomposer.org/ for more information.</comment>
EOT
);
        return 0;
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer\Command;

use _ContaoManager\Symfony\Component\Console\Input\InputInterface;
use Composer\Console\Input\InputOption;
use _ContaoManager\Symfony\Component\Console\Output\OutputInterface;
use Composer\Console\Input\InputArgument;
/**
 * @author Davey Shafik <me@daveyshafik.com>
 */
class ExecCommand extends \Composer\Command\BaseCommand
{
    protected function configure(): void
    {
        $this->setName('exec')->setDescription('Executes a vendored binary/script')->setDefinition([new InputOption('list', 'l', InputOption::VALUE_NONE), new InputArgument('binary', InputArgument::OPTIONAL, 'The binary to run, e.g. phpunit', null, function () {
            return $this->getBinaries(\false);
        }), new InputArgument('args', InputArgument::IS_ARRAY | InputArgument::OPTIONAL, 'Arguments to pass to the binary. Use <info>--</info> to separate from composer arguments')])->setHelp(<<<EOT
Executes a vendored binary/script.

Read more at https://getcomposer.org/doc/03-cli.md#exec
EOT
);
    }
    protected function interact(InputInterface $input, OutputInterface $output): void
    {
        $binaries = $this->getBinaries(\false);
        if (count($binaries) === 0) {
            return;
        }
        if ($input->getArgument('binary') !== null || $input->getOption('list')) {
            return;
        }
        $io = $this->getIO();
        /** @var int $binary */
        $binary = $io->select('Binary to run: ', $binaries, '', 1, 'Invalid binary name "%s"');
        $input->setArgument('binary', $binaries[$binary]);
    }
    protected function execute(InputInterface $input, OutputInterface $output): int
    {
        $composer = $this->requireComposer();
        if ($input->getOption('list') || null === $input->getArgument('binary')) {
            $bins = $this->getBinaries(\true);
            if ([] === $bins) {
                $binDir = $composer->getConfig()->get('bin-dir');
                throw new \RuntimeException("No binaries found in composer.json or in bin-dir ({$binDir})");
            }
            $this->getIO()->write(<<<EOT
<comment>Available binaries:</comment>
EOT
);
            foreach ($bins as $bin) {
                $this->getIO()->write(<<<EOT
<info>- {$bin}</info>
EOT
);
            }
            return 0;
        }
        $binary = $input->getArgument('binary');
        $dispatcher = $composer->getEventDispatcher();
        $dispatcher->addListener('__exec_command', $binary);
        // If the CWD was modified, we restore it to what it was initially, as it was
        // most likely modified by the global command, and we want exec to run in the local working directory
        // not the global one
        if (getcwd() !== $this->getApplication()->getInitialWorkingDirectory() && $this->getApplication()->getInitialWorkingDirectory() !== \false) {
            try {
                chdir($this->getApplication()->getInitialWorkingDirectory());
            } catch (\Exception $e) {
                throw new \RuntimeException('Could not switch back to working directory "' . $this->getApplication()->getInitialWorkingDirectory() . '"', 0, $e);
            }
        }
        return $dispatcher->dispatchScript('__exec_command', \true, $input->getArgument('args'));
    }
    /**
     * @return list<string>
     */
    private function getBinaries(bool $forDisplay): array
    {
        $composer = $this->requireComposer();
        $binDir = $composer->getConfig()->get('bin-dir');
        $bins = glob($binDir . '/*');
        $localBins = $composer->getPackage()->getBinaries();
        if ($forDisplay) {
            $localBins = array_map(static function ($e) {
                return "{$e} (local)";
            }, $localBins);
        }
        $binaries = [];
        foreach (array_merge($bins, $localBins) as $bin) {
            // skip .bat copies
            if (isset($previousBin) && $bin === $previousBin . '.bat') {
                continue;
            }
            $previousBin = $bin;
            $binaries[] = basename($bin);
        }
        return $binaries;
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer;

use Composer\Advisory\AuditConfig;
use Composer\Autoload\AutoloadGenerator;
use Composer\Console\GithubActionError;
use Composer\DependencyResolver\DefaultPolicy;
use Composer\DependencyResolver\LocalRepoTransaction;
use Composer\DependencyResolver\LockTransaction;
use Composer\DependencyResolver\Operation\UpdateOperation;
use Composer\DependencyResolver\Operation\InstallOperation;
use Composer\DependencyResolver\Operation\UninstallOperation;
use Composer\DependencyResolver\PoolOptimizer;
use Composer\DependencyResolver\Pool;
use Composer\DependencyResolver\Request;
use Composer\DependencyResolver\SecurityAdvisoryPoolFilter;
use Composer\DependencyResolver\Solver;
use Composer\DependencyResolver\SolverProblemsException;
use Composer\DependencyResolver\PolicyInterface;
use Composer\Downloader\DownloadManager;
use Composer\Downloader\TransportException;
use Composer\EventDispatcher\EventDispatcher;
use Composer\Filter\PlatformRequirementFilter\IgnoreListPlatformRequirementFilter;
use Composer\Filter\PlatformRequirementFilter\PlatformRequirementFilterFactory;
use Composer\Filter\PlatformRequirementFilter\PlatformRequirementFilterInterface;
use Composer\Installer\InstallationManager;
use Composer\Installer\InstallerEvents;
use Composer\Installer\SuggestedPackagesReporter;
use Composer\IO\IOInterface;
use Composer\Package\AliasPackage;
use Composer\Package\RootAliasPackage;
use Composer\Package\BasePackage;
use Composer\Package\CompletePackage;
use Composer\Package\CompletePackageInterface;
use Composer\Package\Link;
use Composer\Package\Loader\ArrayLoader;
use Composer\Package\Dumper\ArrayDumper;
use Composer\Package\Version\VersionParser;
use Composer\Package\Package;
use Composer\Repository\ArrayRepository;
use Composer\Repository\RepositorySet;
use Composer\Repository\CompositeRepository;
use Composer\Semver\Constraint\Constraint;
use Composer\Package\Locker;
use Composer\Package\RootPackageInterface;
use Composer\Repository\InstalledArrayRepository;
use Composer\Repository\InstalledRepositoryInterface;
use Composer\Repository\InstalledRepository;
use Composer\Repository\RootPackageRepository;
use Composer\Repository\PlatformRepository;
use Composer\Repository\RepositoryInterface;
use Composer\Repository\RepositoryManager;
use Composer\Repository\LockArrayRepository;
use Composer\Script\ScriptEvents;
use Composer\Semver\Constraint\ConstraintInterface;
use Composer\Advisory\Auditor;
use Composer\Util\Platform;
/**
 * @author Jordi Boggiano <j.boggiano@seld.be>
 * @author Beau Simensen <beau@dflydev.com>
 * @author Konstantin Kudryashov <ever.zet@gmail.com>
 * @author Nils Adermann <naderman@naderman.de>
 */
class Installer
{
    public const ERROR_NONE = 0;
    // no error/success state
    public const ERROR_GENERIC_FAILURE = 1;
    public const ERROR_NO_LOCK_FILE_FOR_PARTIAL_UPDATE = 3;
    public const ERROR_LOCK_FILE_INVALID = 4;
    // used/declared in SolverProblemsException, carried over here for completeness
    public const ERROR_DEPENDENCY_RESOLUTION_FAILED = 2;
    public const ERROR_AUDIT_FAILED = 5;
    // technically exceptions are thrown with various status codes >400, but the process exit code is normalized to 100
    public const ERROR_TRANSPORT_EXCEPTION = 100;
    /**
     * @var IOInterface
     */
    protected $io;
    /**
     * @var Config
     */
    protected $config;
    /**
     * @var RootPackageInterface&BasePackage
     */
    protected $package;
    // TODO can we get rid of the below and just use the package itself?
    /**
     * @var RootPackageInterface&BasePackage
     */
    protected $fixedRootPackage;
    /**
     * @var DownloadManager
     */
    protected $downloadManager;
    /**
     * @var RepositoryManager
     */
    protected $repositoryManager;
    /**
     * @var Locker
     */
    protected $locker;
    /**
     * @var InstallationManager
     */
    protected $installationManager;
    /**
     * @var EventDispatcher
     */
    protected $eventDispatcher;
    /**
     * @var AutoloadGenerator
     */
    protected $autoloadGenerator;
    /** @var bool */
    protected $preferSource = \false;
    /** @var bool */
    protected $preferDist = \false;
    /** @var bool */
    protected $optimizeAutoloader = \false;
    /** @var bool */
    protected $classMapAuthoritative = \false;
    /** @var bool */
    protected $apcuAutoloader = \false;
    /** @var string|null */
    protected $apcuAutoloaderPrefix = null;
    /** @var bool */
    protected $devMode = \false;
    /** @var bool */
    protected $dryRun = \false;
    /** @var bool */
    protected $downloadOnly = \false;
    /** @var bool */
    protected $verbose = \false;
    /** @var bool */
    protected $update = \false;
    /** @var bool */
    protected $install = \true;
    /** @var bool */
    protected $dumpAutoloader = \true;
    /** @var bool */
    protected $runScripts = \true;
    /** @var bool */
    protected $preferStable = \false;
    /** @var bool */
    protected $preferLowest = \false;
    /** @var bool */
    protected $minimalUpdate = \false;
    /** @var bool */
    protected $writeLock;
    /** @var bool */
    protected $executeOperations = \true;
    /** @var bool */
    protected $audit = \true;
    /** @var bool */
    protected $errorOnAudit = \false;
    /** @var Auditor::FORMAT_* */
    protected $auditFormat = Auditor::FORMAT_SUMMARY;
    /** @var AuditConfig|null */
    private $auditConfig = null;
    /** @var list<string> */
    private $ignoredTypes = ['php-ext', 'php-ext-zend'];
    /** @var list<string>|null */
    private $allowedTypes = null;
    /** @var bool */
    protected $updateMirrors = \false;
    /**
     * Array of package names/globs flagged for update
     *
     * @var non-empty-list<string>|null
     */
    protected $updateAllowList = null;
    /** @var Request::UPDATE_* */
    protected $updateAllowTransitiveDependencies = Request::UPDATE_ONLY_LISTED;
    /**
     * @var SuggestedPackagesReporter
     */
    protected $suggestedPackagesReporter;
    /**
     * @var PlatformRequirementFilterInterface
     */
    protected $platformRequirementFilter;
    /**
     * @var ?RepositoryInterface
     */
    protected $additionalFixedRepository;
    /** @var array<string, ConstraintInterface> */
    protected $temporaryConstraints = [];
    /**
     * Constructor
     *
     * @param RootPackageInterface&BasePackage $package
     */
    public function __construct(IOInterface $io, \Composer\Config $config, RootPackageInterface $package, DownloadManager $downloadManager, RepositoryManager $repositoryManager, Locker $locker, InstallationManager $installationManager, EventDispatcher $eventDispatcher, AutoloadGenerator $autoloadGenerator)
    {
        $this->io = $io;
        $this->config = $config;
        $this->package = $package;
        $this->downloadManager = $downloadManager;
        $this->repositoryManager = $repositoryManager;
        $this->locker = $locker;
        $this->installationManager = $installationManager;
        $this->eventDispatcher = $eventDispatcher;
        $this->autoloadGenerator = $autoloadGenerator;
        $this->suggestedPackagesReporter = new SuggestedPackagesReporter($this->io);
        $this->platformRequirementFilter = PlatformRequirementFilterFactory::ignoreNothing();
        $this->writeLock = $config->get('lock');
    }
    /**
     * Run installation (or update)
     *
     * @throws \Exception
     * @return int        0 on success or a positive error code on failure
     * @phpstan-return self::ERROR_*
     */
    public function run(): int
    {
        // Disable GC to save CPU cycles, as the dependency solver can create hundreds of thousands
        // of PHP objects, the GC can spend quite some time walking the tree of references looking
        // for stuff to collect while there is nothing to collect. This slows things down dramatically
        // and turning it off results in much better performance. Do not try this at home however.
        gc_collect_cycles();
        gc_disable();
        if ($this->updateAllowList !== null && $this->updateMirrors) {
            throw new \RuntimeException("The installer options updateMirrors and updateAllowList are mutually exclusive.");
        }
        $isFreshInstall = $this->repositoryManager->getLocalRepository()->isFresh();
        // Force update if there is no lock file present
        if (!$this->update && !$this->locker->isLocked()) {
            $this->io->writeError('<warning>No composer.lock file present. Updating dependencies to latest instead of installing from lock file. See https://getcomposer.org/install for more information.</warning>');
            $this->update = \true;
        }
        if ($this->dryRun) {
            $this->verbose = \true;
            $this->runScripts = \false;
            $this->executeOperations = \false;
            $this->writeLock = \false;
            $this->dumpAutoloader = \false;
            $this->mockLocalRepositories($this->repositoryManager);
        }
        if ($this->downloadOnly) {
            $this->dumpAutoloader = \false;
        }
        if ($this->update && !$this->install) {
            $this->dumpAutoloader = \false;
        }
        if ($this->runScripts) {
            Platform::putEnv('COMPOSER_DEV_MODE', $this->devMode ? '1' : '0');
            // dispatch pre event
            // should we treat this more strictly as running an update and then running an install, triggering events multiple times?
            $eventName = $this->update ? ScriptEvents::PRE_UPDATE_CMD : ScriptEvents::PRE_INSTALL_CMD;
            $this->eventDispatcher->dispatchScript($eventName, $this->devMode);
        }
        $this->downloadManager->setPreferSource($this->preferSource);
        $this->downloadManager->setPreferDist($this->preferDist);
        $localRepo = $this->repositoryManager->getLocalRepository();
        try {
            if ($this->update) {
                $res = $this->doUpdate($localRepo, $this->install);
            } else {
                $res = $this->doInstall($localRepo);
            }
            if ($res !== 0) {
                return $res;
            }
        } catch (\Exception $e) {
            if ($this->executeOperations && $this->install && $this->config->get('notify-on-install')) {
                $this->installationManager->notifyInstalls($this->io);
            }
            throw $e;
        }
        if ($this->executeOperations && $this->install && $this->config->get('notify-on-install')) {
            $this->installationManager->notifyInstalls($this->io);
        }
        if ($this->update) {
            $installedRepo = new InstalledRepository([$this->locker->getLockedRepository($this->devMode), $this->createPlatformRepo(\false), new RootPackageRepository(clone $this->package)]);
            if ($isFreshInstall) {
                $this->suggestedPackagesReporter->addSuggestionsFromPackage($this->package);
            }
            $this->suggestedPackagesReporter->outputMinimalistic($installedRepo);
        }
        // Find abandoned packages and warn user
        $lockedRepository = $this->locker->getLockedRepository(\true);
        foreach ($lockedRepository->getPackages() as $package) {
            if (!$package instanceof CompletePackage || !$package->isAbandoned()) {
                continue;
            }
            $replacement = is_string($package->getReplacementPackage()) ? 'Use ' . $package->getReplacementPackage() . ' instead' : 'No replacement was suggested';
            $this->io->writeError(sprintf("<warning>Package %s is abandoned, you should avoid using it. %s.</warning>", $package->getPrettyName(), $replacement));
        }
        if ($this->dumpAutoloader) {
            // write autoloader
            if ($this->optimizeAutoloader) {
                $this->io->writeError('<info>Generating optimized autoload files</info>');
            } else {
                $this->io->writeError('<info>Generating autoload files</info>');
            }
            $this->autoloadGenerator->setClassMapAuthoritative($this->classMapAuthoritative);
            $this->autoloadGenerator->setApcu($this->apcuAutoloader, $this->apcuAutoloaderPrefix);
            $this->autoloadGenerator->setRunScripts($this->runScripts);
            $this->autoloadGenerator->setPlatformRequirementFilter($this->platformRequirementFilter);
            $this->autoloadGenerator->dump($this->config, $localRepo, $this->package, $this->installationManager, 'composer', $this->optimizeAutoloader, null, $this->locker);
        }
        if ($this->install && $this->executeOperations) {
            // force binaries re-generation in case they are missing
            foreach ($localRepo->getPackages() as $package) {
                $this->installationManager->ensureBinariesPresence($package);
            }
        }
        $fundEnv = Platform::getEnv('COMPOSER_FUND');
        $showFunding = \true;
        if (is_numeric($fundEnv)) {
            $showFunding = intval($fundEnv) !== 0;
        }
        if ($showFunding) {
            $fundingCount = 0;
            foreach ($localRepo->getPackages() as $package) {
                if ($package instanceof CompletePackageInterface && !$package instanceof AliasPackage && $package->getFunding()) {
                    $fundingCount++;
                }
            }
            if ($fundingCount > 0) {
                $this->io->writeError([sprintf("<info>%d package%s you are using %s looking for funding.</info>", $fundingCount, 1 === $fundingCount ? '' : 's', 1 === $fundingCount ? 'is' : 'are'), '<info>Use the `composer fund` command to find out more!</info>']);
            }
        }
        if ($this->runScripts) {
            // dispatch post event
            $eventName = $this->update ? ScriptEvents::POST_UPDATE_CMD : ScriptEvents::POST_INSTALL_CMD;
            $this->eventDispatcher->dispatchScript($eventName, $this->devMode);
        }
        // re-enable GC except on HHVM which triggers a warning here
        if (!defined('HHVM_VERSION')) {
            gc_enable();
        }
        $auditConfig = $this->getAuditConfig();
        if ($auditConfig->audit) {
            if ($this->update && !$this->install) {
                $packages = $lockedRepository->getCanonicalPackages();
                $target = 'locked';
            } else {
                $packages = $localRepo->getCanonicalPackages();
                $target = 'installed';
            }
            if (count($packages) > 0) {
                try {
                    $auditor = new Auditor();
                    $repoSet = new RepositorySet();
                    foreach ($this->repositoryManager->getRepositories() as $repo) {
                        $repoSet->addRepository($repo);
                    }
                    return $auditor->audit($this->io, $repoSet, $packages, $auditConfig->auditFormat, \true, $auditConfig->ignoreListForAudit, $auditConfig->auditAbandoned, $auditConfig->ignoreSeverityForAudit, $auditConfig->ignoreUnreachable, $auditConfig->ignoreAbandonedForAudit) > 0 && $this->errorOnAudit ? self::ERROR_AUDIT_FAILED : 0;
                } catch (TransportException $e) {
                    $this->io->error('Failed to audit ' . $target . ' packages.');
                    if ($this->io->isVerbose()) {
                        $this->io->error('[' . get_class($e) . '] ' . $e->getMessage());
                    }
                }
            } else {
                $this->io->writeError('No ' . $target . ' packages - skipping audit.');
            }
        }
        return 0;
    }
    /**
     * @phpstan-return self::ERROR_*
     */
    protected function doUpdate(InstalledRepositoryInterface $localRepo, bool $doInstall): int
    {
        $platformRepo = $this->createPlatformRepo(\true);
        $aliases = $this->getRootAliases(\true);
        $lockedRepository = null;
        try {
            if ($this->locker->isLocked()) {
                $lockedRepository = $this->locker->getLockedRepository(\true);
            }
        } catch (\_ContaoManager\Seld\JsonLint\ParsingException $e) {
            if ($this->updateAllowList !== null || $this->updateMirrors) {
                // in case we are doing a partial update or updating mirrors, the lock file is needed so we error
                throw $e;
            }
            // otherwise, ignoring parse errors as the lock file will be regenerated from scratch when
            // doing a full update
        }
        if (($this->updateAllowList !== null || $this->updateMirrors) && !$lockedRepository) {
            $this->io->writeError('<error>Cannot update ' . ($this->updateMirrors ? 'lock file information' : 'only a partial set of packages') . ' without a lock file present. Run `composer update` to generate a lock file.</error>', \true, IOInterface::QUIET);
            return self::ERROR_NO_LOCK_FILE_FOR_PARTIAL_UPDATE;
        }
        $this->io->writeError('<info>Loading composer repositories with package information</info>');
        // creating repository set
        $policy = $this->createPolicy(\true, $lockedRepository);
        $repositorySet = $this->createRepositorySet(\true, $platformRepo, $aliases);
        $repositories = $this->repositoryManager->getRepositories();
        foreach ($repositories as $repository) {
            $repositorySet->addRepository($repository);
        }
        if ($lockedRepository) {
            $repositorySet->addRepository($lockedRepository);
        }
        $request = $this->createRequest($this->fixedRootPackage, $platformRepo, $lockedRepository);
        $this->requirePackagesForUpdate($request, $lockedRepository, \true);
        // pass the allow list into the request, so the pool builder can apply it
        if ($this->updateAllowList !== null) {
            $request->setUpdateAllowList($this->updateAllowList, $this->updateAllowTransitiveDependencies);
        }
        $pool = $repositorySet->createPool($request, $this->io, $this->eventDispatcher, $this->createPoolOptimizer($policy), $this->ignoredTypes, $this->allowedTypes, $this->createSecurityAuditPoolFilter());
        $this->io->writeError('<info>Updating dependencies</info>');
        // solve dependencies
        $solver = new Solver($policy, $pool, $this->io);
        try {
            $lockTransaction = $solver->solve($request, $this->platformRequirementFilter);
            $ruleSetSize = $solver->getRuleSetSize();
            $solver = null;
        } catch (SolverProblemsException $e) {
            $err = 'Your requirements could not be resolved to an installable set of packages.';
            $prettyProblem = $e->getPrettyString($repositorySet, $request, $pool, $this->io->isVerbose());
            $this->io->writeError('<error>' . $err . '</error>', \true, IOInterface::QUIET);
            $this->io->writeError($prettyProblem);
            if (!$this->devMode) {
                $this->io->writeError('<warning>Running update with --no-dev does not mean require-dev is ignored, it just means the packages will not be installed. If dev requirements are blocking the update you have to resolve those problems.</warning>', \true, IOInterface::QUIET);
            }
            $ghe = new GithubActionError($this->io);
            $ghe->emit($err . "\n" . $prettyProblem);
            return max(self::ERROR_GENERIC_FAILURE, $e->getCode());
        }
        $this->io->writeError("Analyzed " . count($pool) . " packages to resolve dependencies", \true, IOInterface::VERBOSE);
        $this->io->writeError("Analyzed " . $ruleSetSize . " rules to resolve dependencies", \true, IOInterface::VERBOSE);
        $pool = null;
        if (!$lockTransaction->getOperations()) {
            $this->io->writeError('Nothing to modify in lock file');
            if ($this->minimalUpdate && $this->updateAllowList === null && $this->locker->isFresh()) {
                $this->io->writeError('<warning>The --minimal-changes option should be used with package arguments or after modifying composer.json requirements, otherwise it will likely not yield any dependency changes.</warning>');
            }
        }
        $exitCode = $this->extractDevPackages($lockTransaction, $platformRepo, $aliases, $policy, $lockedRepository);
        if ($exitCode !== 0) {
            return $exitCode;
        }
        \Composer\Semver\CompilingMatcher::clear();
        // write lock
        $platformReqs = $this->extractPlatformRequirements($this->package->getRequires());
        $platformDevReqs = $this->extractPlatformRequirements($this->package->getDevRequires());
        $installsUpdates = $uninstalls = [];
        if ($lockTransaction->getOperations()) {
            $installNames = $updateNames = $uninstallNames = [];
            foreach ($lockTransaction->getOperations() as $operation) {
                if ($operation instanceof InstallOperation) {
                    $installsUpdates[] = $operation;
                    $installNames[] = $operation->getPackage()->getPrettyName() . ':' . $operation->getPackage()->getFullPrettyVersion();
                } elseif ($operation instanceof UpdateOperation) {
                    // when mirrors/metadata from a package gets updated we do not want to list it as an
                    // update in the output as it is only an internal lock file metadata update
                    if ($this->updateMirrors && $operation->getInitialPackage()->getName() === $operation->getTargetPackage()->getName() && $operation->getInitialPackage()->getVersion() === $operation->getTargetPackage()->getVersion()) {
                        continue;
                    }
                    $installsUpdates[] = $operation;
                    $updateNames[] = $operation->getTargetPackage()->getPrettyName() . ':' . $operation->getTargetPackage()->getFullPrettyVersion();
                } elseif ($operation instanceof UninstallOperation) {
                    $uninstalls[] = $operation;
                    $uninstallNames[] = $operation->getPackage()->getPrettyName();
                }
            }
            if ($this->config->get('lock')) {
                $this->io->writeError(sprintf("<info>Lock file operations: %d install%s, %d update%s, %d removal%s</info>", count($installNames), 1 === count($installNames) ? '' : 's', count($updateNames), 1 === count($updateNames) ? '' : 's', count($uninstalls), 1 === count($uninstalls) ? '' : 's'));
                if ($installNames) {
                    $this->io->writeError("Installs: " . implode(', ', $installNames), \true, IOInterface::VERBOSE);
                }
                if ($updateNames) {
                    $this->io->writeError("Updates: " . implode(', ', $updateNames), \true, IOInterface::VERBOSE);
                }
                if ($uninstalls) {
                    $this->io->writeError("Removals: " . implode(', ', $uninstallNames), \true, IOInterface::VERBOSE);
                }
            }
        }
        $sortByName = static function ($a, $b): int {
            if ($a instanceof UpdateOperation) {
                $a = $a->getTargetPackage()->getName();
            } else {
                $a = $a->getPackage()->getName();
            }
            if ($b instanceof UpdateOperation) {
                $b = $b->getTargetPackage()->getName();
            } else {
                $b = $b->getPackage()->getName();
            }
            return strcmp($a, $b);
        };
        usort($uninstalls, $sortByName);
        usort($installsUpdates, $sortByName);
        foreach (array_merge($uninstalls, $installsUpdates) as $operation) {
            // collect suggestions
            if ($operation instanceof InstallOperation) {
                $this->suggestedPackagesReporter->addSuggestionsFromPackage($operation->getPackage());
            }
            // output op if lock file is enabled, but alias op only in debug verbosity
            if ($this->config->get('lock') && (\false === strpos($operation->getOperationType(), 'Alias') || $this->io->isDebug())) {
                $sourceRepo = '';
                if ($this->io->isVeryVerbose() && \false === strpos($operation->getOperationType(), 'Alias')) {
                    $operationPkg = $operation instanceof UpdateOperation ? $operation->getTargetPackage() : $operation->getPackage();
                    if ($operationPkg->getRepository() !== null) {
                        $sourceRepo = ' from ' . $operationPkg->getRepository()->getRepoName();
                    }
                }
                $this->io->writeError('  - ' . $operation->show(\true) . $sourceRepo);
            }
        }
        $updatedLock = $this->locker->setLockData($lockTransaction->getNewLockPackages(\false, $this->updateMirrors), $lockTransaction->getNewLockPackages(\true, $this->updateMirrors), $platformReqs, $platformDevReqs, $lockTransaction->getAliases($aliases), $this->package->getMinimumStability(), $this->package->getStabilityFlags(), $this->preferStable || $this->package->getPreferStable(), $this->preferLowest, $this->config->get('platform') ?: [], $this->writeLock && $this->executeOperations);
        if ($updatedLock && $this->writeLock && $this->executeOperations) {
            $this->io->writeError('<info>Writing lock file</info>');
        }
        if ($doInstall) {
            // TODO ensure lock is used from locker as-is, since it may not have been written to disk in case of executeOperations == false
            return $this->doInstall($localRepo, \true);
        }
        return 0;
    }
    /**
     * Run the solver a second time on top of the existing update result with only the current result set in the pool
     * and see what packages would get removed if we only had the non-dev packages in the solver request
     *
     * @param array<int, array<string, string>> $aliases
     *
     * @phpstan-param list<array{package: string, version: string, alias: string, alias_normalized: string}> $aliases
     * @phpstan-return self::ERROR_*
     */
    protected function extractDevPackages(LockTransaction $lockTransaction, PlatformRepository $platformRepo, array $aliases, PolicyInterface $policy, ?LockArrayRepository $lockedRepository = null): int
    {
        if (!$this->package->getDevRequires()) {
            return 0;
        }
        $resultRepo = new ArrayRepository([]);
        $loader = new ArrayLoader(null, \true);
        $dumper = new ArrayDumper();
        foreach ($lockTransaction->getNewLockPackages(\false) as $pkg) {
            $resultRepo->addPackage($loader->load($dumper->dump($pkg)));
        }
        $repositorySet = $this->createRepositorySet(\true, $platformRepo, $aliases);
        $repositorySet->addRepository($resultRepo);
        $request = $this->createRequest($this->fixedRootPackage, $platformRepo);
        $this->requirePackagesForUpdate($request, $lockedRepository, \false);
        $pool = $repositorySet->createPoolWithAllPackages();
        $solver = new Solver($policy, $pool, $this->io);
        try {
            $nonDevLockTransaction = $solver->solve($request, $this->platformRequirementFilter);
            $solver = null;
        } catch (SolverProblemsException $e) {
            $err = 'Unable to find a compatible set of packages based on your non-dev requirements alone.';
            $prettyProblem = $e->getPrettyString($repositorySet, $request, $pool, $this->io->isVerbose(), \true);
            $this->io->writeError('<error>' . $err . '</error>', \true, IOInterface::QUIET);
            $this->io->writeError('Your requirements can be resolved successfully when require-dev packages are present.');
            $this->io->writeError('You may need to move packages from require-dev or some of their dependencies to require.');
            $this->io->writeError($prettyProblem);
            $ghe = new GithubActionError($this->io);
            $ghe->emit($err . "\n" . $prettyProblem);
            return $e->getCode();
        }
        $lockTransaction->setNonDevPackages($nonDevLockTransaction);
        return 0;
    }
    /**
     * @param  bool                         $alreadySolved Whether the function is called as part of an update command or independently
     * @return int                          exit code
     * @phpstan-return self::ERROR_*
     */
    protected function doInstall(InstalledRepositoryInterface $localRepo, bool $alreadySolved = \false): int
    {
        if ($this->config->get('lock')) {
            $this->io->writeError('<info>Installing dependencies from lock file' . ($this->devMode ? ' (including require-dev)' : '') . '</info>');
        }
        $lockedRepository = $this->locker->getLockedRepository($this->devMode);
        // verify that the lock file works with the current platform repository
        // we can skip this part if we're doing this as the second step after an update
        if (!$alreadySolved) {
            $this->io->writeError('<info>Verifying lock file contents can be installed on current platform.</info>');
            $platformRepo = $this->createPlatformRepo(\false);
            // creating repository set
            $policy = $this->createPolicy(\false);
            // use aliases from lock file only, so empty root aliases here
            $repositorySet = $this->createRepositorySet(\false, $platformRepo, [], $lockedRepository);
            $repositorySet->addRepository($lockedRepository);
            // creating requirements request
            $request = $this->createRequest($this->fixedRootPackage, $platformRepo, $lockedRepository);
            if (!$this->locker->isFresh()) {
                $this->io->writeError('<warning>Warning: The lock file is not up to date with the latest changes in composer.json. You may be getting outdated dependencies. It is recommended that you run `composer update` or `composer update <package name>`.</warning>', \true, IOInterface::QUIET);
            }
            $missingRequirementInfo = $this->locker->getMissingRequirementInfo($this->package, $this->devMode);
            if ($missingRequirementInfo !== []) {
                $this->io->writeError($missingRequirementInfo);
                if (!$this->config->get('allow-missing-requirements')) {
                    return self::ERROR_LOCK_FILE_INVALID;
                }
            }
            foreach ($lockedRepository->getPackages() as $package) {
                $request->fixLockedPackage($package);
            }
            $rootRequires = $this->package->getRequires();
            if ($this->devMode) {
                $rootRequires = array_merge($rootRequires, $this->package->getDevRequires());
            }
            foreach ($rootRequires as $link) {
                if (PlatformRepository::isPlatformPackage($link->getTarget())) {
                    $request->requireName($link->getTarget(), $link->getConstraint());
                }
            }
            foreach ($this->locker->getPlatformRequirements($this->devMode) as $link) {
                if (!isset($rootRequires[$link->getTarget()])) {
                    $request->requireName($link->getTarget(), $link->getConstraint());
                }
            }
            unset($rootRequires, $link);
            $pool = $repositorySet->createPool($request, $this->io, $this->eventDispatcher, null, $this->ignoredTypes, $this->allowedTypes, null);
            // solve dependencies
            $solver = new Solver($policy, $pool, $this->io);
            try {
                $lockTransaction = $solver->solve($request, $this->platformRequirementFilter);
                $solver = null;
                // installing the locked packages on this platform resulted in lock modifying operations, there wasn't a conflict, but the lock file as-is seems to not work on this system
                if (0 !== count($lockTransaction->getOperations())) {
                    $this->io->writeError('<error>Your lock file cannot be installed on this system without changes. Please run composer update.</error>', \true, IOInterface::QUIET);
                    return self::ERROR_LOCK_FILE_INVALID;
                }
            } catch (SolverProblemsException $e) {
                $err = 'Your lock file does not contain a compatible set of packages. Please run composer update.';
                $prettyProblem = $e->getPrettyString($repositorySet, $request, $pool, $this->io->isVerbose());
                $this->io->writeError('<error>' . $err . '</error>', \true, IOInterface::QUIET);
                $this->io->writeError($prettyProblem);
                $ghe = new GithubActionError($this->io);
                $ghe->emit($err . "\n" . $prettyProblem);
                return max(self::ERROR_GENERIC_FAILURE, $e->getCode());
            }
        }
        // TODO in how far do we need to do anything here to ensure dev packages being updated to latest in lock without version change are treated correctly?
        $localRepoTransaction = new LocalRepoTransaction($lockedRepository, $localRepo);
        $this->eventDispatcher->dispatchInstallerEvent(InstallerEvents::PRE_OPERATIONS_EXEC, $this->devMode, $this->executeOperations, $localRepoTransaction);
        $installs = $updates = $uninstalls = [];
        foreach ($localRepoTransaction->getOperations() as $operation) {
            if ($operation instanceof InstallOperation) {
                $installs[] = $operation->getPackage()->getPrettyName() . ':' . $operation->getPackage()->getFullPrettyVersion();
            } elseif ($operation instanceof UpdateOperation) {
                $updates[] = $operation->getTargetPackage()->getPrettyName() . ':' . $operation->getTargetPackage()->getFullPrettyVersion();
            } elseif ($operation instanceof UninstallOperation) {
                $uninstalls[] = $operation->getPackage()->getPrettyName();
            }
        }
        if ($installs === [] && $updates === [] && $uninstalls === []) {
            $this->io->writeError('Nothing to install, update or remove');
        } else {
            $this->io->writeError(sprintf("<info>Package operations: %d install%s, %d update%s, %d removal%s</info>", count($installs), 1 === count($installs) ? '' : 's', count($updates), 1 === count($updates) ? '' : 's', count($uninstalls), 1 === count($uninstalls) ? '' : 's'));
            if ($installs) {
                $this->io->writeError("Installs: " . implode(', ', $installs), \true, IOInterface::VERBOSE);
            }
            if ($updates) {
                $this->io->writeError("Updates: " . implode(', ', $updates), \true, IOInterface::VERBOSE);
            }
            if ($uninstalls) {
                $this->io->writeError("Removals: " . implode(', ', $uninstalls), \true, IOInterface::VERBOSE);
            }
        }
        if ($this->executeOperations) {
            $localRepo->setDevPackageNames($this->locker->getDevPackageNames());
            $this->installationManager->execute($localRepo, $localRepoTransaction->getOperations(), $this->devMode, $this->runScripts, $this->downloadOnly);
            // see https://github.com/composer/composer/issues/2764
            if (count($localRepoTransaction->getOperations()) > 0) {
                $vendorDir = $this->config->get('vendor-dir');
                if (is_dir($vendorDir)) {
                    // suppress errors as this fails sometimes on OSX for no apparent reason
                    // see https://github.com/composer/composer/issues/4070#issuecomment-129792748
                    @touch($vendorDir);
                }
            }
        } else {
            foreach ($localRepoTransaction->getOperations() as $operation) {
                // output op, but alias op only in debug verbosity
                if (\false === strpos($operation->getOperationType(), 'Alias') || $this->io->isDebug()) {
                    $this->io->writeError('  - ' . $operation->show(\false));
                }
            }
        }
        return 0;
    }
    protected function createPlatformRepo(bool $forUpdate): PlatformRepository
    {
        if ($forUpdate) {
            $platformOverrides = $this->config->get('platform') ?: [];
        } else {
            $platformOverrides = $this->locker->getPlatformOverrides();
        }
        return new PlatformRepository([], $platformOverrides);
    }
    /**
     * @param  array<int, array<string, string>> $rootAliases
     *
     * @phpstan-param list<array{package: string, version: string, alias: string, alias_normalized: string}> $rootAliases
     */
    private function createRepositorySet(bool $forUpdate, PlatformRepository $platformRepo, array $rootAliases = [], ?RepositoryInterface $lockedRepository = null): RepositorySet
    {
        if ($forUpdate) {
            $minimumStability = $this->package->getMinimumStability();
            $stabilityFlags = $this->package->getStabilityFlags();
            $requires = array_merge($this->package->getRequires(), $this->package->getDevRequires());
        } else {
            $minimumStability = $this->locker->getMinimumStability();
            $stabilityFlags = $this->locker->getStabilityFlags();
            $requires = [];
            foreach ($lockedRepository->getPackages() as $package) {
                $constraint = new Constraint('=', $package->getVersion());
                $constraint->setPrettyString($package->getPrettyVersion());
                $requires[$package->getName()] = $constraint;
            }
        }
        $rootRequires = [];
        foreach ($requires as $req => $constraint) {
            if ($constraint instanceof Link) {
                $constraint = $constraint->getConstraint();
            }
            // skip platform requirements from the root package to avoid filtering out existing platform packages
            if ($this->platformRequirementFilter->isIgnored($req)) {
                continue;
            } elseif ($this->platformRequirementFilter instanceof IgnoreListPlatformRequirementFilter) {
                $constraint = $this->platformRequirementFilter->filterConstraint($req, $constraint);
            }
            $rootRequires[$req] = $constraint;
        }
        $this->fixedRootPackage = clone $this->package;
        $this->fixedRootPackage->setRequires([]);
        $this->fixedRootPackage->setDevRequires([]);
        $stabilityFlags[$this->package->getName()] = BasePackage::STABILITIES[VersionParser::parseStability($this->package->getVersion())];
        $repositorySet = new RepositorySet($minimumStability, $stabilityFlags, $rootAliases, $this->package->getReferences(), $rootRequires, $this->temporaryConstraints);
        $repositorySet->addRepository(new RootPackageRepository($this->fixedRootPackage));
        $repositorySet->addRepository($platformRepo);
        if ($this->additionalFixedRepository) {
            // allow using installed repos if needed to avoid warnings about installed repositories being used in the RepositorySet
            // see https://github.com/composer/composer/pull/9574
            $additionalFixedRepositories = $this->additionalFixedRepository;
            if ($additionalFixedRepositories instanceof CompositeRepository) {
                $additionalFixedRepositories = $additionalFixedRepositories->getRepositories();
            } else {
                $additionalFixedRepositories = [$additionalFixedRepositories];
            }
            foreach ($additionalFixedRepositories as $additionalFixedRepository) {
                if ($additionalFixedRepository instanceof InstalledRepository || $additionalFixedRepository instanceof InstalledRepositoryInterface) {
                    $repositorySet->allowInstalledRepositories();
                    break;
                }
            }
            $repositorySet->addRepository($this->additionalFixedRepository);
        }
        return $repositorySet;
    }
    private function createPolicy(bool $forUpdate, ?LockArrayRepository $lockedRepo = null): DefaultPolicy
    {
        $preferStable = null;
        $preferLowest = null;
        if (!$forUpdate) {
            $preferStable = $this->locker->getPreferStable();
            $preferLowest = $this->locker->getPreferLowest();
        }
        // old lock file without prefer stable/lowest will return null
        // so in this case we use the composer.json info
        if (null === $preferStable) {
            $preferStable = $this->preferStable || $this->package->getPreferStable();
        }
        if (null === $preferLowest) {
            $preferLowest = $this->preferLowest;
        }
        $preferredVersions = null;
        if ($forUpdate && $this->minimalUpdate && $lockedRepo !== null) {
            $preferredVersions = [];
            foreach ($lockedRepo->getPackages() as $pkg) {
                if ($pkg instanceof AliasPackage || $this->updateAllowList !== null && in_array($pkg->getName(), $this->updateAllowList, \true)) {
                    continue;
                }
                $preferredVersions[$pkg->getName()] = $pkg->getVersion();
            }
        }
        return new DefaultPolicy($preferStable, $preferLowest, $preferredVersions);
    }
    /**
     * @param RootPackageInterface&BasePackage $rootPackage
     */
    private function createRequest(RootPackageInterface $rootPackage, PlatformRepository $platformRepo, ?LockArrayRepository $lockedRepository = null): Request
    {
        $request = new Request($lockedRepository);
        $request->fixPackage($rootPackage);
        if ($rootPackage instanceof RootAliasPackage) {
            $request->fixPackage($rootPackage->getAliasOf());
        }
        $fixedPackages = $platformRepo->getPackages();
        if ($this->additionalFixedRepository) {
            $fixedPackages = array_merge($fixedPackages, $this->additionalFixedRepository->getPackages());
        }
        // fix the version of all platform packages + additionally installed packages
        // to prevent the solver trying to remove or update those
        // TODO why not replaces?
        $provided = $rootPackage->getProvides();
        foreach ($fixedPackages as $package) {
            // skip platform packages that are provided by the root package
            if ($package->getRepository() !== $platformRepo || !isset($provided[$package->getName()]) || !$provided[$package->getName()]->getConstraint()->matches(new Constraint('=', $package->getVersion()))) {
                $request->fixPackage($package);
            }
        }
        return $request;
    }
    private function requirePackagesForUpdate(Request $request, ?LockArrayRepository $lockedRepository = null, bool $includeDevRequires = \true): void
    {
        // if we're updating mirrors we want to keep exactly the same versions installed which are in the lock file, but we want current remote metadata
        if ($this->updateMirrors) {
            $excludedPackages = [];
            if (!$includeDevRequires) {
                $excludedPackages = array_flip($this->locker->getDevPackageNames());
            }
            foreach ($lockedRepository->getPackages() as $lockedPackage) {
                // exclude alias packages here as for root aliases, both alias and aliased are
                // present in the lock repo and we only want to require the aliased version
                if (!$lockedPackage instanceof AliasPackage && !isset($excludedPackages[$lockedPackage->getName()])) {
                    $request->requireName($lockedPackage->getName(), new Constraint('==', $lockedPackage->getVersion()));
                }
            }
        } else {
            $links = $this->package->getRequires();
            if ($includeDevRequires) {
                $links = array_merge($links, $this->package->getDevRequires());
            }
            foreach ($links as $link) {
                $request->requireName($link->getTarget(), $link->getConstraint());
            }
        }
    }
    /**
     * @return array<int, array<string, string>>
     *
     * @phpstan-return list<array{package: string, version: string, alias: string, alias_normalized: string}>
     */
    private function getRootAliases(bool $forUpdate): array
    {
        if ($forUpdate) {
            $aliases = $this->package->getAliases();
        } else {
            $aliases = $this->locker->getAliases();
        }
        return $aliases;
    }
    /**
     * @param Link[] $links
     *
     * @return array<string, string>
     */
    private function extractPlatformRequirements(array $links): array
    {
        $platformReqs = [];
        foreach ($links as $link) {
            if (PlatformRepository::isPlatformPackage($link->getTarget())) {
                $platformReqs[$link->getTarget()] = $link->getPrettyConstraint();
            }
        }
        return $platformReqs;
    }
    /**
     * Replace local repositories with InstalledArrayRepository instances
     *
     * This is to prevent any accidental modification of the existing repos on disk
     */
    private function mockLocalRepositories(RepositoryManager $rm): void
    {
        $packages = [];
        foreach ($rm->getLocalRepository()->getPackages() as $package) {
            $packages[(string) $package] = clone $package;
        }
        foreach ($packages as $key => $package) {
            if ($package instanceof AliasPackage) {
                $alias = (string) $package->getAliasOf();
                $className = get_class($package);
                $packages[$key] = new $className($packages[$alias], $package->getVersion(), $package->getPrettyVersion());
            }
        }
        $rm->setLocalRepository(new InstalledArrayRepository($packages));
    }
    private function createPoolOptimizer(PolicyInterface $policy): ?PoolOptimizer
    {
        // Not the best architectural decision here, would need to be able
        // to configure from the outside of Installer but this is only
        // a debugging tool and should never be required in any other use case
        if ('0' === Platform::getEnv('COMPOSER_POOL_OPTIMIZER')) {
            $this->io->write('Pool Optimizer was disabled for debugging purposes.', \true, IOInterface::DEBUG);
            return null;
        }
        return new PoolOptimizer($policy);
    }
    private function getAuditConfig(): AuditConfig
    {
        if (null === $this->auditConfig) {
            $this->auditConfig = AuditConfig::fromConfig($this->config, $this->audit, $this->auditFormat);
        }
        return $this->auditConfig;
    }
    private function createSecurityAuditPoolFilter(): ?SecurityAdvisoryPoolFilter
    {
        $auditConfig = $this->getAuditConfig();
        if ($auditConfig->blockInsecure && !$this->updateMirrors) {
            return new SecurityAdvisoryPoolFilter(new Auditor(), $auditConfig);
        }
        return null;
    }
    /**
     * Create Installer
     */
    public static function create(IOInterface $io, \Composer\Composer $composer): self
    {
        return new static($io, $composer->getConfig(), $composer->getPackage(), $composer->getDownloadManager(), $composer->getRepositoryManager(), $composer->getLocker(), $composer->getInstallationManager(), $composer->getEventDispatcher(), $composer->getAutoloadGenerator());
    }
    /**
     * Packages of those types are ignored, by default php-ext and php-ext-zend are ignored
     *
     * @param list<string> $types
     * @return $this
     */
    public function setIgnoredTypes(array $types): self
    {
        $this->ignoredTypes = $types;
        return $this;
    }
    /**
     * Only packages of those types are allowed if set to non-null
     *
     * @param list<string>|null $types
     * @return $this
     */
    public function setAllowedTypes(?array $types): self
    {
        $this->allowedTypes = $types;
        return $this;
    }
    /**
     * @return $this
     */
    public function setAdditionalFixedRepository(RepositoryInterface $additionalFixedRepository): self
    {
        $this->additionalFixedRepository = $additionalFixedRepository;
        return $this;
    }
    /**
     * @param array<string, ConstraintInterface> $constraints
     */
    public function setTemporaryConstraints(array $constraints): self
    {
        $this->temporaryConstraints = $constraints;
        return $this;
    }
    /**
     * Whether to run in drymode or not
     */
    public function setDryRun(bool $dryRun = \true): self
    {
        $this->dryRun = $dryRun;
        return $this;
    }
    /**
     * Checks, if this is a dry run (simulation mode).
     */
    public function isDryRun(): bool
    {
        return $this->dryRun;
    }
    /**
     * Whether to download only or not.
     */
    public function setDownloadOnly(bool $downloadOnly = \true): self
    {
        $this->downloadOnly = $downloadOnly;
        return $this;
    }
    /**
     * prefer source installation
     */
    public function setPreferSource(bool $preferSource = \true): self
    {
        $this->preferSource = $preferSource;
        return $this;
    }
    /**
     * prefer dist installation
     */
    public function setPreferDist(bool $preferDist = \true): self
    {
        $this->preferDist = $preferDist;
        return $this;
    }
    /**
     * Whether or not generated autoloader are optimized
     */
    public function setOptimizeAutoloader(bool $optimizeAutoloader): self
    {
        $this->optimizeAutoloader = $optimizeAutoloader;
        if (!$this->optimizeAutoloader) {
            // Force classMapAuthoritative off when not optimizing the
            // autoloader
            $this->setClassMapAuthoritative(\false);
        }
        return $this;
    }
    /**
     * Whether or not generated autoloader considers the class map
     * authoritative.
     */
    public function setClassMapAuthoritative(bool $classMapAuthoritative): self
    {
        $this->classMapAuthoritative = $classMapAuthoritative;
        if ($this->classMapAuthoritative) {
            // Force optimizeAutoloader when classmap is authoritative
            $this->setOptimizeAutoloader(\true);
        }
        return $this;
    }
    /**
     * Whether or not generated autoloader considers APCu caching.
     */
    public function setApcuAutoloader(bool $apcuAutoloader, ?string $apcuAutoloaderPrefix = null): self
    {
        $this->apcuAutoloader = $apcuAutoloader;
        $this->apcuAutoloaderPrefix = $apcuAutoloaderPrefix;
        return $this;
    }
    /**
     * update packages
     */
    public function setUpdate(bool $update): self
    {
        $this->update = $update;
        return $this;
    }
    /**
     * Allows disabling the install step after an update
     */
    public function setInstall(bool $install): self
    {
        $this->install = $install;
        return $this;
    }
    /**
     * enables dev packages
     */
    public function setDevMode(bool $devMode = \true): self
    {
        $this->devMode = $devMode;
        return $this;
    }
    /**
     * set whether to run autoloader or not
     *
     * This is disabled implicitly when enabling dryRun
     */
    public function setDumpAutoloader(bool $dumpAutoloader = \true): self
    {
        $this->dumpAutoloader = $dumpAutoloader;
        return $this;
    }
    /**
     * set whether to run scripts or not
     *
     * This is disabled implicitly when enabling dryRun
     *
     * @deprecated Use setRunScripts(false) on the EventDispatcher instance being injected instead
     */
    public function setRunScripts(bool $runScripts = \true): self
    {
        $this->runScripts = $runScripts;
        return $this;
    }
    /**
     * set the config instance
     */
    public function setConfig(\Composer\Config $config): self
    {
        $this->config = $config;
        return $this;
    }
    /**
     * run in verbose mode
     */
    public function setVerbose(bool $verbose = \true): self
    {
        $this->verbose = $verbose;
        return $this;
    }
    /**
     * Checks, if running in verbose mode.
     */
    public function isVerbose(): bool
    {
        return $this->verbose;
    }
    /**
     * set ignore Platform Package requirements
     *
     * If this is set to true, all platform requirements are ignored
     * If this is set to false, no platform requirements are ignored
     * If this is set to string[], those packages will be ignored
     *
     * @param  bool|string[] $ignorePlatformReqs
     *
     *
     * @deprecated use setPlatformRequirementFilter instead
     */
    public function setIgnorePlatformRequirements($ignorePlatformReqs): self
    {
        trigger_error('Installer::setIgnorePlatformRequirements is deprecated since Composer 2.2, use setPlatformRequirementFilter instead.', \E_USER_DEPRECATED);
        return $this->setPlatformRequirementFilter(PlatformRequirementFilterFactory::fromBoolOrList($ignorePlatformReqs));
    }
    public function setPlatformRequirementFilter(PlatformRequirementFilterInterface $platformRequirementFilter): self
    {
        $this->platformRequirementFilter = $platformRequirementFilter;
        return $this;
    }
    /**
     * Update the lock file to the exact same versions and references but use current remote metadata like URLs and mirror info
     */
    public function setUpdateMirrors(bool $updateMirrors): self
    {
        $this->updateMirrors = $updateMirrors;
        return $this;
    }
    /**
     * restrict the update operation to a few packages, all other packages
     * that are already installed will be kept at their current version
     *
     * @param string[] $packages
     */
    public function setUpdateAllowList(array $packages): self
    {
        if (count($packages) === 0) {
            $this->updateAllowList = null;
        } else {
            $this->updateAllowList = array_values(array_unique(array_map('strtolower', $packages)));
        }
        return $this;
    }
    /**
     * Should dependencies of packages marked for update be updated?
     *
     * Depending on the chosen constant this will either only update the directly named packages, all transitive
     * dependencies which are not root requirement or all transitive dependencies including root requirements
     *
     * @param  int       $updateAllowTransitiveDependencies One of the UPDATE_ constants on the Request class
     */
    public function setUpdateAllowTransitiveDependencies(int $updateAllowTransitiveDependencies): self
    {
        if (!in_array($updateAllowTransitiveDependencies, [Request::UPDATE_ONLY_LISTED, Request::UPDATE_LISTED_WITH_TRANSITIVE_DEPS_NO_ROOT_REQUIRE, Request::UPDATE_LISTED_WITH_TRANSITIVE_DEPS], \true)) {
            throw new \RuntimeException("Invalid value for updateAllowTransitiveDependencies supplied");
        }
        $this->updateAllowTransitiveDependencies = $updateAllowTransitiveDependencies;
        return $this;
    }
    /**
     * Should packages be preferred in a stable version when updating?
     */
    public function setPreferStable(bool $preferStable = \true): self
    {
        $this->preferStable = $preferStable;
        return $this;
    }
    /**
     * Should packages be preferred in a lowest version when updating?
     */
    public function setPreferLowest(bool $preferLowest = \true): self
    {
        $this->preferLowest = $preferLowest;
        return $this;
    }
    /**
     * Only relevant for partial updates (with setUpdateAllowList), if this is enabled currently locked versions will be preferred for packages which are not in the allowlist
     *
     * This reduces the update to
     */
    public function setMinimalUpdate(bool $minimalUpdate = \true): self
    {
        $this->minimalUpdate = $minimalUpdate;
        return $this;
    }
    /**
     * Should the lock file be updated when updating?
     *
     * This is disabled implicitly when enabling dryRun
     */
    public function setWriteLock(bool $writeLock = \true): self
    {
        $this->writeLock = $writeLock;
        return $this;
    }
    /**
     * Should the operations (package install, update and removal) be executed on disk?
     *
     * This is disabled implicitly when enabling dryRun
     */
    public function setExecuteOperations(bool $executeOperations = \true): self
    {
        $this->executeOperations = $executeOperations;
        return $this;
    }
    /**
     * Should an audit be run after installation is complete?
     *
     * @deprecated Use setAuditConfig instead of calling this
     */
    public function setAudit(bool $audit): self
    {
        $this->audit = $audit;
        $this->auditConfig = null;
        // Invalidate cached config
        return $this;
    }
    /**
     * Should exit with status code 5 on audit error
     */
    public function setErrorOnAudit(bool $errorOnAudit): self
    {
        $this->errorOnAudit = $errorOnAudit;
        return $this;
    }
    /**
     * What format should be used for audit output?
     *
     * @param Auditor::FORMAT_* $auditFormat
     *
     * @deprecated Use setAuditConfig instead of calling this
     */
    public function setAuditFormat(string $auditFormat): self
    {
        $this->auditFormat = $auditFormat;
        $this->auditConfig = null;
        // Invalidate cached config
        return $this;
    }
    /**
     * Sets a custom AuditConfig to override the default configuration from Config
     */
    public function setAuditConfig(AuditConfig $auditConfig): self
    {
        $this->auditConfig = $auditConfig;
        return $this;
    }
    /**
     * Disables plugins.
     *
     * Call this if you want to ensure that third-party code never gets
     * executed. The default is to automatically install, and execute
     * custom third-party installers.
     */
    public function disablePlugins(): self
    {
        $this->installationManager->disablePlugins();
        return $this;
    }
    public function setSuggestedPackagesReporter(SuggestedPackagesReporter $suggestedPackagesReporter): self
    {
        $this->suggestedPackagesReporter = $suggestedPackagesReporter;
        return $this;
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer\Filter\PlatformRequirementFilter;

interface PlatformRequirementFilterInterface
{
    public function isIgnored(string $req): bool;
    public function isUpperBoundIgnored(string $req): bool;
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer\Filter\PlatformRequirementFilter;

use Composer\Repository\PlatformRepository;
final class IgnoreAllPlatformRequirementFilter implements \Composer\Filter\PlatformRequirementFilter\PlatformRequirementFilterInterface
{
    public function isIgnored(string $req): bool
    {
        return PlatformRepository::isPlatformPackage($req);
    }
    public function isUpperBoundIgnored(string $req): bool
    {
        return $this->isIgnored($req);
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer\Filter\PlatformRequirementFilter;

use Composer\Package\BasePackage;
use Composer\Pcre\Preg;
use Composer\Repository\PlatformRepository;
use Composer\Semver\Constraint\Constraint;
use Composer\Semver\Constraint\ConstraintInterface;
use Composer\Semver\Constraint\MatchAllConstraint;
use Composer\Semver\Constraint\MultiConstraint;
use Composer\Semver\Interval;
use Composer\Semver\Intervals;
final class IgnoreListPlatformRequirementFilter implements \Composer\Filter\PlatformRequirementFilter\PlatformRequirementFilterInterface
{
    /**
     * @var non-empty-string
     */
    private $ignoreRegex;
    /**
     * @var non-empty-string
     */
    private $ignoreUpperBoundRegex;
    /**
     * @param string[] $reqList
     */
    public function __construct(array $reqList)
    {
        $ignoreAll = $ignoreUpperBound = [];
        foreach ($reqList as $req) {
            if (substr($req, -1) === '+') {
                $ignoreUpperBound[] = substr($req, 0, -1);
            } else {
                $ignoreAll[] = $req;
            }
        }
        $this->ignoreRegex = BasePackage::packageNamesToRegexp($ignoreAll);
        $this->ignoreUpperBoundRegex = BasePackage::packageNamesToRegexp($ignoreUpperBound);
    }
    public function isIgnored(string $req): bool
    {
        if (!PlatformRepository::isPlatformPackage($req)) {
            return \false;
        }
        return Preg::isMatch($this->ignoreRegex, $req);
    }
    public function isUpperBoundIgnored(string $req): bool
    {
        if (!PlatformRepository::isPlatformPackage($req)) {
            return \false;
        }
        return $this->isIgnored($req) || Preg::isMatch($this->ignoreUpperBoundRegex, $req);
    }
    /**
     * @param bool $allowUpperBoundOverride For conflicts we do not want the upper bound to be skipped
     */
    public function filterConstraint(string $req, ConstraintInterface $constraint, bool $allowUpperBoundOverride = \true): ConstraintInterface
    {
        if (!PlatformRepository::isPlatformPackage($req)) {
            return $constraint;
        }
        if (!$allowUpperBoundOverride || !Preg::isMatch($this->ignoreUpperBoundRegex, $req)) {
            return $constraint;
        }
        if (Preg::isMatch($this->ignoreRegex, $req)) {
            return new MatchAllConstraint();
        }
        $intervals = Intervals::get($constraint);
        $last = end($intervals['numeric']);
        if ($last !== \false && (string) $last->getEnd() !== (string) Interval::untilPositiveInfinity()) {
            $constraint = new MultiConstraint([$constraint, new Constraint('>=', $last->getEnd()->getVersion())], \false);
        }
        return $constraint;
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer\Filter\PlatformRequirementFilter;

final class IgnoreNothingPlatformRequirementFilter implements \Composer\Filter\PlatformRequirementFilter\PlatformRequirementFilterInterface
{
    /**
     * @return false
     */
    public function isIgnored(string $req): bool
    {
        return \false;
    }
    /**
     * @return false
     */
    public function isUpperBoundIgnored(string $req): bool
    {
        return \false;
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer\Filter\PlatformRequirementFilter;

final class PlatformRequirementFilterFactory
{
    /**
     * @param mixed $boolOrList
     */
    public static function fromBoolOrList($boolOrList): \Composer\Filter\PlatformRequirementFilter\PlatformRequirementFilterInterface
    {
        if (is_bool($boolOrList)) {
            return $boolOrList ? self::ignoreAll() : self::ignoreNothing();
        }
        if (is_array($boolOrList)) {
            return new \Composer\Filter\PlatformRequirementFilter\IgnoreListPlatformRequirementFilter($boolOrList);
        }
        throw new \InvalidArgumentException(sprintf('PlatformRequirementFilter: Unknown $boolOrList parameter %s. Please report at https://github.com/composer/composer/issues/new.', get_debug_type($boolOrList)));
    }
    public static function ignoreAll(): \Composer\Filter\PlatformRequirementFilter\PlatformRequirementFilterInterface
    {
        return new \Composer\Filter\PlatformRequirementFilter\IgnoreAllPlatformRequirementFilter();
    }
    public static function ignoreNothing(): \Composer\Filter\PlatformRequirementFilter\PlatformRequirementFilterInterface
    {
        return new \Composer\Filter\PlatformRequirementFilter\IgnoreNothingPlatformRequirementFilter();
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer\Installer;

/**
 * Package Events.
 *
 * @author Jordi Boggiano <j.boggiano@seld.be>
 */
class PackageEvents
{
    /**
     * The PRE_PACKAGE_INSTALL event occurs before a package is installed.
     *
     * The event listener method receives a Composer\Installer\PackageEvent instance.
     *
     * @var string
     */
    public const PRE_PACKAGE_INSTALL = 'pre-package-install';
    /**
     * The POST_PACKAGE_INSTALL event occurs after a package is installed.
     *
     * The event listener method receives a Composer\Installer\PackageEvent instance.
     *
     * @var string
     */
    public const POST_PACKAGE_INSTALL = 'post-package-install';
    /**
     * The PRE_PACKAGE_UPDATE event occurs before a package is updated.
     *
     * The event listener method receives a Composer\Installer\PackageEvent instance.
     *
     * @var string
     */
    public const PRE_PACKAGE_UPDATE = 'pre-package-update';
    /**
     * The POST_PACKAGE_UPDATE event occurs after a package is updated.
     *
     * The event listener method receives a Composer\Installer\PackageEvent instance.
     *
     * @var string
     */
    public const POST_PACKAGE_UPDATE = 'post-package-update';
    /**
     * The PRE_PACKAGE_UNINSTALL event occurs before a package has been uninstalled.
     *
     * The event listener method receives a Composer\Installer\PackageEvent instance.
     *
     * @var string
     */
    public const PRE_PACKAGE_UNINSTALL = 'pre-package-uninstall';
    /**
     * The POST_PACKAGE_UNINSTALL event occurs after a package has been uninstalled.
     *
     * The event listener method receives a Composer\Installer\PackageEvent instance.
     *
     * @var string
     */
    public const POST_PACKAGE_UNINSTALL = 'post-package-uninstall';
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer\Installer;

use Composer\IO\IOInterface;
use Composer\Package\PackageInterface;
use Composer\Pcre\Preg;
use Composer\Util\Filesystem;
use Composer\Util\Platform;
use Composer\Util\ProcessExecutor;
use Composer\Util\Silencer;
/**
 * Utility to handle installation of package "bin"/binaries
 *
 * @author Jordi Boggiano <j.boggiano@seld.be>
 * @author Konstantin Kudryashov <ever.zet@gmail.com>
 * @author Helmut Hummel <info@helhum.io>
 */
class BinaryInstaller
{
    /** @var string */
    protected $binDir;
    /** @var string */
    protected $binCompat;
    /** @var IOInterface */
    protected $io;
    /** @var Filesystem */
    protected $filesystem;
    /** @var string|null */
    private $vendorDir;
    public function __construct(IOInterface $io, string $binDir, string $binCompat, ?Filesystem $filesystem = null, ?string $vendorDir = null)
    {
        $this->binDir = $binDir;
        $this->binCompat = $binCompat;
        $this->io = $io;
        $this->filesystem = $filesystem ?: new Filesystem();
        $this->vendorDir = $vendorDir;
    }
    public function installBinaries(PackageInterface $package, string $installPath, bool $warnOnOverwrite = \true): void
    {
        $binaries = $this->getBinaries($package);
        if (!$binaries) {
            return;
        }
        Platform::workaroundFilesystemIssues();
        foreach ($binaries as $bin) {
            $binPath = $installPath . '/' . $bin;
            if (!file_exists($binPath)) {
                $this->io->writeError('    <warning>Skipped installation of bin ' . $bin . ' for package ' . $package->getName() . ': file not found in package</warning>');
                continue;
            }
            if (is_dir($binPath)) {
                $this->io->writeError('    <warning>Skipped installation of bin ' . $bin . ' for package ' . $package->getName() . ': found a directory at that path</warning>');
                continue;
            }
            if (!$this->filesystem->isAbsolutePath($binPath)) {
                // in case a custom installer returned a relative path for the
                // $package, we can now safely turn it into a absolute path (as we
                // already checked the binary's existence). The following helpers
                // will require absolute paths to work properly.
                $binPath = realpath($binPath);
            }
            $this->initializeBinDir();
            $link = $this->binDir . '/' . basename($bin);
            if (file_exists($link)) {
                if (!is_link($link)) {
                    if ($warnOnOverwrite) {
                        $this->io->writeError('    Skipped installation of bin ' . $bin . ' for package ' . $package->getName() . ': name conflicts with an existing file');
                    }
                    continue;
                }
                if (realpath($link) === realpath($binPath)) {
                    // It is a linked binary from a previous installation, which can be replaced with a proxy file
                    $this->filesystem->unlink($link);
                }
            }
            $binCompat = $this->binCompat;
            if ($binCompat === "auto" && (Platform::isWindows() || Platform::isWindowsSubsystemForLinux())) {
                $binCompat = 'full';
            }
            if ($binCompat === "full") {
                $this->installFullBinaries($binPath, $link, $bin, $package);
            } else {
                $this->installUnixyProxyBinaries($binPath, $link);
            }
            Silencer::call('chmod', $binPath, 0777 & ~umask());
        }
    }
    public function removeBinaries(PackageInterface $package): void
    {
        $this->initializeBinDir();
        $binaries = $this->getBinaries($package);
        if (!$binaries) {
            return;
        }
        foreach ($binaries as $bin) {
            $link = $this->binDir . '/' . basename($bin);
            if (is_link($link) || file_exists($link)) {
                // still checking for symlinks here for legacy support
                $this->filesystem->unlink($link);
            }
            if (is_file($link . '.bat')) {
                $this->filesystem->unlink($link . '.bat');
            }
        }
        // attempt removing the bin dir in case it is left empty
        if (is_dir($this->binDir) && $this->filesystem->isDirEmpty($this->binDir)) {
            Silencer::call('rmdir', $this->binDir);
        }
    }
    public static function determineBinaryCaller(string $bin): string
    {
        if ('.bat' === substr($bin, -4) || '.exe' === substr($bin, -4)) {
            return 'call';
        }
        $handle = fopen($bin, 'r');
        $line = fgets($handle);
        fclose($handle);
        if (Preg::isMatchStrictGroups('{^#!/(?:usr/bin/env )?(?:[^/]+/)*(.+)$}m', (string) $line, $match)) {
            return trim($match[1]);
        }
        return 'php';
    }
    /**
     * @return string[]
     */
    protected function getBinaries(PackageInterface $package): array
    {
        return $package->getBinaries();
    }
    protected function installFullBinaries(string $binPath, string $link, string $bin, PackageInterface $package): void
    {
        // add unixy support for cygwin and similar environments
        if ('.bat' !== substr($binPath, -4)) {
            $this->installUnixyProxyBinaries($binPath, $link);
            $link .= '.bat';
            if (file_exists($link)) {
                $this->io->writeError('    Skipped installation of bin ' . $bin . '.bat proxy for package ' . $package->getName() . ': a .bat proxy was already installed');
            }
        }
        if (!file_exists($link)) {
            file_put_contents($link, $this->generateWindowsProxyCode($binPath, $link));
            Silencer::call('chmod', $link, 0777 & ~umask());
        }
    }
    protected function installUnixyProxyBinaries(string $binPath, string $link): void
    {
        file_put_contents($link, $this->generateUnixyProxyCode($binPath, $link));
        Silencer::call('chmod', $link, 0777 & ~umask());
    }
    protected function initializeBinDir(): void
    {
        $this->filesystem->ensureDirectoryExists($this->binDir);
        $this->binDir = realpath($this->binDir);
    }
    protected function generateWindowsProxyCode(string $bin, string $link): string
    {
        $binPath = $this->filesystem->findShortestPath($link, $bin);
        $caller = self::determineBinaryCaller($bin);
        // if the target is a php file, we run the unixy proxy file
        // to ensure that _composer_autoload_path gets defined, instead
        // of running the binary directly
        if ($caller === 'php') {
            return "@ECHO OFF\r\n" . "setlocal DISABLEDELAYEDEXPANSION\r\n" . "SET BIN_TARGET=%~dp0/" . trim(ProcessExecutor::escape(basename($link, '.bat')), '"\'') . "\r\n" . "SET COMPOSER_RUNTIME_BIN_DIR=%~dp0\r\n" . "{$caller} \"%BIN_TARGET%\" %*\r\n";
        }
        return "@ECHO OFF\r\n" . "setlocal DISABLEDELAYEDEXPANSION\r\n" . "SET BIN_TARGET=%~dp0/" . trim(ProcessExecutor::escape($binPath), '"\'') . "\r\n" . "SET COMPOSER_RUNTIME_BIN_DIR=%~dp0\r\n" . "{$caller} \"%BIN_TARGET%\" %*\r\n";
    }
    protected function generateUnixyProxyCode(string $bin, string $link): string
    {
        $binPath = $this->filesystem->findShortestPath($link, $bin);
        $binDir = ProcessExecutor::escape(dirname($binPath));
        $binFile = basename($binPath);
        $binContents = (string) file_get_contents($bin, \false, null, 0, 500);
        // For php files, we generate a PHP proxy instead of a shell one,
        // which allows calling the proxy with a custom php process
        if (Preg::isMatch('{^(#!.*\r?\n)?[\r\n\t ]*<\?php}', $binContents, $match)) {
            // carry over the existing shebang if present, otherwise add our own
            $proxyCode = $match[1] === null ? '#!/usr/bin/env php' : trim($match[1]);
            $binPathExported = $this->filesystem->findShortestPathCode($link, $bin, \false, \true);
            $streamProxyCode = $streamHint = '';
            $globalsCode = '$GLOBALS[\'_composer_bin_dir\'] = __DIR__;' . "\n";
            $phpunitHack1 = $phpunitHack2 = '';
            // Don't expose autoload path when vendor dir was not set in custom installers
            if ($this->vendorDir !== null) {
                // ensure comparisons work accurately if the CWD is a symlink, as $link is realpath'd already
                $vendorDirReal = realpath($this->vendorDir);
                if ($vendorDirReal === \false) {
                    $vendorDirReal = $this->vendorDir;
                }
                $globalsCode .= '$GLOBALS[\'_composer_autoload_path\'] = ' . $this->filesystem->findShortestPathCode($link, $vendorDirReal . '/autoload.php', \false, \true) . ";\n";
            }
            // Add workaround for PHPUnit process isolation
            if ($this->filesystem->normalizePath($bin) === $this->filesystem->normalizePath($this->vendorDir . '/phpunit/phpunit/phpunit')) {
                // workaround issue on PHPUnit 6.5+ running on PHP 8+
                $globalsCode .= '$GLOBALS[\'__PHPUNIT_ISOLATION_EXCLUDE_LIST\'] = $GLOBALS[\'__PHPUNIT_ISOLATION_BLACKLIST\'] = array(realpath(' . $binPathExported . '));' . "\n";
                // workaround issue on all PHPUnit versions running on PHP <8
                $phpunitHack1 = "'phpvfscomposer://'.";
                $phpunitHack2 = '
                $data = str_replace(\'__DIR__\', var_export(dirname($this->realpath), true), $data);
                $data = str_replace(\'__FILE__\', var_export($this->realpath, true), $data);';
            }
            if (trim($match[0]) !== '<?php') {
                $streamHint = ' using a stream wrapper to prevent the shebang from being output on PHP<8' . "\n *";
                $streamProxyCode = <<<STREAMPROXY
if (PHP_VERSION_ID < 80000) {
    if (!class_exists('Composer\\BinProxyWrapper')) {
        /**
         * @internal
         */
        final class BinProxyWrapper
        {
            private \$handle;
            private \$position;
            private \$realpath;

            public function stream_open(\$path, \$mode, \$options, &\$opened_path)
            {
                // get rid of phpvfscomposer:// prefix for __FILE__ & __DIR__ resolution
                \$opened_path = substr(\$path, 17);
                \$this->realpath = realpath(\$opened_path) ?: \$opened_path;
                \$opened_path = {$phpunitHack1}\$this->realpath;
                \$this->handle = fopen(\$this->realpath, \$mode);
                \$this->position = 0;

                return (bool) \$this->handle;
            }

            public function stream_read(\$count)
            {
                \$data = fread(\$this->handle, \$count);

                if (\$this->position === 0) {
                    \$data = preg_replace('{^#!.*\\r?\\n}', '', \$data);
                }{$phpunitHack2}

                \$this->position += strlen(\$data);

                return \$data;
            }

            public function stream_cast(\$castAs)
            {
                return \$this->handle;
            }

            public function stream_close()
            {
                fclose(\$this->handle);
            }

            public function stream_lock(\$operation)
            {
                return \$operation ? flock(\$this->handle, \$operation) : true;
            }

            public function stream_seek(\$offset, \$whence)
            {
                if (0 === fseek(\$this->handle, \$offset, \$whence)) {
                    \$this->position = ftell(\$this->handle);
                    return true;
                }

                return false;
            }

            public function stream_tell()
            {
                return \$this->position;
            }

            public function stream_eof()
            {
                return feof(\$this->handle);
            }

            public function stream_stat()
            {
                return array();
            }

            public function stream_set_option(\$option, \$arg1, \$arg2)
            {
                return true;
            }

            public function url_stat(\$path, \$flags)
            {
                \$path = substr(\$path, 17);
                if (file_exists(\$path)) {
                    return stat(\$path);
                }

                return false;
            }
        }
    }

    if (
        (function_exists('stream_get_wrappers') && in_array('phpvfscomposer', stream_get_wrappers(), true))
        || (function_exists('stream_wrapper_register') && stream_wrapper_register('phpvfscomposer', 'Composer\\BinProxyWrapper'))
    ) {
        return include("phpvfscomposer://" . {$binPathExported});
    }
}

STREAMPROXY;
            }
            return $proxyCode . "\n" . <<<PROXY
<?php

/**
 * Proxy PHP file generated by Composer
 *
 * This file includes the referenced bin path ({$binPath})
 *{$streamHint}
 * @generated
 */

namespace Composer;

{$globalsCode}
{$streamProxyCode}
return include {$binPathExported};

PROXY;
        }
        return <<<PROXY
#!/usr/bin/env sh

# Support bash to support `source` with fallback on \$0 if this does not run with bash
# https://stackoverflow.com/a/35006505/6512
selfArg="\$BASH_SOURCE"
if [ -z "\$selfArg" ]; then
    selfArg="\$0"
fi

self=\$(realpath "\$selfArg" 2> /dev/null)
if [ -z "\$self" ]; then
    self="\$selfArg"
fi

dir=\$(cd "\${self%[/\\\\]*}" > /dev/null; cd {$binDir} && pwd)

if [ -d /proc/cygdrive ]; then
    case \$(which php) in
        \$(readlink -n /proc/cygdrive)/*)
            # We are in Cygwin using Windows php, so the path must be translated
            dir=\$(cygpath -m "\$dir");
            ;;
    esac
fi

export COMPOSER_RUNTIME_BIN_DIR="\$(cd "\${self%[/\\\\]*}" > /dev/null; pwd)"

# If bash is sourcing this file, we have to source the target as well
bashSource="\$BASH_SOURCE"
if [ -n "\$bashSource" ]; then
    if [ "\$bashSource" != "\$0" ]; then
        source "\${dir}/{$binFile}" "\$@"
        return
    fi
fi

exec "\${dir}/{$binFile}" "\$@"

PROXY;
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer\Installer;

use Composer\Composer;
use Composer\IO\IOInterface;
use Composer\PartialComposer;
use Composer\Repository\InstalledRepositoryInterface;
use Composer\Package\PackageInterface;
use Composer\Plugin\PluginManager;
use Composer\Util\Filesystem;
use Composer\Util\Platform;
use React\Promise\PromiseInterface;
/**
 * Installer for plugin packages
 *
 * @author Jordi Boggiano <j.boggiano@seld.be>
 * @author Nils Adermann <naderman@naderman.de>
 */
class PluginInstaller extends \Composer\Installer\LibraryInstaller
{
    public function __construct(IOInterface $io, PartialComposer $composer, ?Filesystem $fs = null, ?\Composer\Installer\BinaryInstaller $binaryInstaller = null)
    {
        parent::__construct($io, $composer, 'composer-plugin', $fs, $binaryInstaller);
    }
    /**
     * @inheritDoc
     */
    public function supports(string $packageType)
    {
        return $packageType === 'composer-plugin' || $packageType === 'composer-installer';
    }
    public function disablePlugins(): void
    {
        $this->getPluginManager()->disablePlugins();
    }
    /**
     * @inheritDoc
     */
    public function prepare($type, PackageInterface $package, ?PackageInterface $prevPackage = null)
    {
        // fail install process early if it is going to fail due to a plugin not being allowed
        if (($type === 'install' || $type === 'update') && !$this->getPluginManager()->arePluginsDisabled('local')) {
            $this->getPluginManager()->isPluginAllowed($package->getName(), \false, \true === ($package->getExtra()['plugin-optional'] ?? \false));
        }
        return parent::prepare($type, $package, $prevPackage);
    }
    /**
     * @inheritDoc
     */
    public function download(PackageInterface $package, ?PackageInterface $prevPackage = null)
    {
        $extra = $package->getExtra();
        if (empty($extra['class'])) {
            throw new \UnexpectedValueException('Error while installing ' . $package->getPrettyName() . ', composer-plugin packages should have a class defined in their extra key to be usable.');
        }
        return parent::download($package, $prevPackage);
    }
    /**
     * @inheritDoc
     */
    public function install(InstalledRepositoryInterface $repo, PackageInterface $package)
    {
        $promise = parent::install($repo, $package);
        if (!$promise instanceof PromiseInterface) {
            $promise = \React\Promise\resolve(null);
        }
        return $promise->then(function () use ($package, $repo): void {
            try {
                Platform::workaroundFilesystemIssues();
                $this->getPluginManager()->registerPackage($package, \true);
            } catch (\Exception $e) {
                $this->rollbackInstall($e, $repo, $package);
            }
        });
    }
    /**
     * @inheritDoc
     */
    public function update(InstalledRepositoryInterface $repo, PackageInterface $initial, PackageInterface $target)
    {
        $promise = parent::update($repo, $initial, $target);
        if (!$promise instanceof PromiseInterface) {
            $promise = \React\Promise\resolve(null);
        }
        return $promise->then(function () use ($initial, $target, $repo): void {
            try {
                Platform::workaroundFilesystemIssues();
                $this->getPluginManager()->deactivatePackage($initial);
                $this->getPluginManager()->registerPackage($target, \true);
            } catch (\Exception $e) {
                $this->rollbackInstall($e, $repo, $target);
            }
        });
    }
    public function uninstall(InstalledRepositoryInterface $repo, PackageInterface $package)
    {
        $this->getPluginManager()->uninstallPackage($package);
        return parent::uninstall($repo, $package);
    }
    private function rollbackInstall(\Exception $e, InstalledRepositoryInterface $repo, PackageInterface $package): void
    {
        $this->io->writeError('Plugin initialization failed (' . $e->getMessage() . '), uninstalling plugin');
        parent::uninstall($repo, $package);
        throw $e;
    }
    protected function getPluginManager(): PluginManager
    {
        assert($this->composer instanceof Composer, new \LogicException(self::class . ' should be initialized with a fully loaded Composer instance.'));
        $pluginManager = $this->composer->getPluginManager();
        return $pluginManager;
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer\Installer;

use Composer\Package\PackageInterface;
/**
 * Interface for the package installation manager that handle binary installation.
 *
 * @author Jordi Boggiano <j.boggiano@seld.be>
 */
interface BinaryPresenceInterface
{
    /**
     * Make sure binaries are installed for a given package.
     *
     * @param PackageInterface $package package instance
     *
     * @return void
     */
    public function ensureBinariesPresence(PackageInterface $package);
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer\Installer;

class InstallerEvents
{
    /**
     * The PRE_OPERATIONS_EXEC event occurs before the lock file gets
     * installed and operations are executed.
     *
     * The event listener method receives an Composer\Installer\InstallerEvent instance.
     *
     * @var string
     */
    public const PRE_OPERATIONS_EXEC = 'pre-operations-exec';
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer\Installer;

use Composer\Composer;
use Composer\IO\IOInterface;
use Composer\DependencyResolver\Operation\OperationInterface;
use Composer\Repository\RepositoryInterface;
use Composer\EventDispatcher\Event;
/**
 * The Package Event.
 *
 * @author Jordi Boggiano <j.boggiano@seld.be>
 */
class PackageEvent extends Event
{
    /**
     * @var Composer
     */
    private $composer;
    /**
     * @var IOInterface
     */
    private $io;
    /**
     * @var bool
     */
    private $devMode;
    /**
     * @var RepositoryInterface
     */
    private $localRepo;
    /**
     * @var OperationInterface[]
     */
    private $operations;
    /**
     * @var OperationInterface The operation instance which is being executed
     */
    private $operation;
    /**
     * Constructor.
     *
     * @param OperationInterface[] $operations
     */
    public function __construct(string $eventName, Composer $composer, IOInterface $io, bool $devMode, RepositoryInterface $localRepo, array $operations, OperationInterface $operation)
    {
        parent::__construct($eventName);
        $this->composer = $composer;
        $this->io = $io;
        $this->devMode = $devMode;
        $this->localRepo = $localRepo;
        $this->operations = $operations;
        $this->operation = $operation;
    }
    public function getComposer(): Composer
    {
        return $this->composer;
    }
    public function getIO(): IOInterface
    {
        return $this->io;
    }
    public function isDevMode(): bool
    {
        return $this->devMode;
    }
    public function getLocalRepo(): RepositoryInterface
    {
        return $this->localRepo;
    }
    /**
     * @return OperationInterface[]
     */
    public function getOperations(): array
    {
        return $this->operations;
    }
    /**
     * Returns the package instance.
     */
    public function getOperation(): OperationInterface
    {
        return $this->operation;
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer\Installer;

use Composer\Composer;
use Composer\DependencyResolver\Transaction;
use Composer\EventDispatcher\Event;
use Composer\IO\IOInterface;
class InstallerEvent extends Event
{
    /**
     * @var Composer
     */
    private $composer;
    /**
     * @var IOInterface
     */
    private $io;
    /**
     * @var bool
     */
    private $devMode;
    /**
     * @var bool
     */
    private $executeOperations;
    /**
     * @var Transaction
     */
    private $transaction;
    /**
     * Constructor.
     */
    public function __construct(string $eventName, Composer $composer, IOInterface $io, bool $devMode, bool $executeOperations, Transaction $transaction)
    {
        parent::__construct($eventName);
        $this->composer = $composer;
        $this->io = $io;
        $this->devMode = $devMode;
        $this->executeOperations = $executeOperations;
        $this->transaction = $transaction;
    }
    public function getComposer(): Composer
    {
        return $this->composer;
    }
    public function getIO(): IOInterface
    {
        return $this->io;
    }
    public function isDevMode(): bool
    {
        return $this->devMode;
    }
    public function isExecutingOperations(): bool
    {
        return $this->executeOperations;
    }
    public function getTransaction(): ?Transaction
    {
        return $this->transaction;
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer\Installer;

use Composer\Composer;
use Composer\IO\IOInterface;
use Composer\PartialComposer;
use Composer\Pcre\Preg;
use Composer\Repository\InstalledRepositoryInterface;
use Composer\Package\PackageInterface;
use Composer\Util\Filesystem;
use Composer\Util\Silencer;
use Composer\Util\Platform;
use React\Promise\PromiseInterface;
use Composer\Downloader\DownloadManager;
/**
 * Package installation manager.
 *
 * @author Jordi Boggiano <j.boggiano@seld.be>
 * @author Konstantin Kudryashov <ever.zet@gmail.com>
 */
class LibraryInstaller implements \Composer\Installer\InstallerInterface, \Composer\Installer\BinaryPresenceInterface
{
    /** @var PartialComposer */
    protected $composer;
    /** @var string */
    protected $vendorDir;
    /** @var DownloadManager|null */
    protected $downloadManager;
    /** @var IOInterface */
    protected $io;
    /** @var string */
    protected $type;
    /** @var Filesystem */
    protected $filesystem;
    /** @var BinaryInstaller */
    protected $binaryInstaller;
    /**
     * Initializes library installer.
     */
    public function __construct(IOInterface $io, PartialComposer $composer, ?string $type = 'library', ?Filesystem $filesystem = null, ?\Composer\Installer\BinaryInstaller $binaryInstaller = null)
    {
        $this->composer = $composer;
        $this->downloadManager = $composer instanceof Composer ? $composer->getDownloadManager() : null;
        $this->io = $io;
        $this->type = $type;
        $this->filesystem = $filesystem ?: new Filesystem();
        $this->vendorDir = rtrim($composer->getConfig()->get('vendor-dir'), '/');
        $this->binaryInstaller = $binaryInstaller ?: new \Composer\Installer\BinaryInstaller($this->io, rtrim($composer->getConfig()->get('bin-dir'), '/'), $composer->getConfig()->get('bin-compat'), $this->filesystem, $this->vendorDir);
    }
    /**
     * @inheritDoc
     */
    public function supports(string $packageType)
    {
        return $packageType === $this->type || null === $this->type;
    }
    /**
     * @inheritDoc
     */
    public function isInstalled(InstalledRepositoryInterface $repo, PackageInterface $package)
    {
        if (!$repo->hasPackage($package)) {
            return \false;
        }
        $installPath = $this->getInstallPath($package);
        if (Filesystem::isReadable($installPath)) {
            return \true;
        }
        if (Platform::isWindows() && $this->filesystem->isJunction($installPath)) {
            return \true;
        }
        if (is_link($installPath)) {
            if (realpath($installPath) === \false) {
                return \false;
            }
            return \true;
        }
        return \false;
    }
    /**
     * @inheritDoc
     */
    public function download(PackageInterface $package, ?PackageInterface $prevPackage = null)
    {
        $this->initializeVendorDir();
        $downloadPath = $this->getInstallPath($package);
        return $this->getDownloadManager()->download($package, $downloadPath, $prevPackage);
    }
    /**
     * @inheritDoc
     */
    public function prepare($type, PackageInterface $package, ?PackageInterface $prevPackage = null)
    {
        $this->initializeVendorDir();
        $downloadPath = $this->getInstallPath($package);
        return $this->getDownloadManager()->prepare($type, $package, $downloadPath, $prevPackage);
    }
    /**
     * @inheritDoc
     */
    public function cleanup($type, PackageInterface $package, ?PackageInterface $prevPackage = null)
    {
        $this->initializeVendorDir();
        $downloadPath = $this->getInstallPath($package);
        return $this->getDownloadManager()->cleanup($type, $package, $downloadPath, $prevPackage);
    }
    /**
     * @inheritDoc
     */
    public function install(InstalledRepositoryInterface $repo, PackageInterface $package)
    {
        $this->initializeVendorDir();
        $downloadPath = $this->getInstallPath($package);
        // remove the binaries if it appears the package files are missing
        if (!Filesystem::isReadable($downloadPath) && $repo->hasPackage($package)) {
            $this->binaryInstaller->removeBinaries($package);
        }
        $promise = $this->installCode($package);
        if (!$promise instanceof PromiseInterface) {
            $promise = \React\Promise\resolve(null);
        }
        $binaryInstaller = $this->binaryInstaller;
        $installPath = $this->getInstallPath($package);
        return $promise->then(static function () use ($binaryInstaller, $installPath, $package, $repo): void {
            $binaryInstaller->installBinaries($package, $installPath);
            if (!$repo->hasPackage($package)) {
                $repo->addPackage(clone $package);
            }
        });
    }
    /**
     * @inheritDoc
     */
    public function update(InstalledRepositoryInterface $repo, PackageInterface $initial, PackageInterface $target)
    {
        if (!$repo->hasPackage($initial)) {
            throw new \InvalidArgumentException('Package is not installed: ' . $initial);
        }
        $this->initializeVendorDir();
        $this->binaryInstaller->removeBinaries($initial);
        $promise = $this->updateCode($initial, $target);
        if (!$promise instanceof PromiseInterface) {
            $promise = \React\Promise\resolve(null);
        }
        $binaryInstaller = $this->binaryInstaller;
        $installPath = $this->getInstallPath($target);
        return $promise->then(static function () use ($binaryInstaller, $installPath, $target, $initial, $repo): void {
            $binaryInstaller->installBinaries($target, $installPath);
            $repo->removePackage($initial);
            if (!$repo->hasPackage($target)) {
                $repo->addPackage(clone $target);
            }
        });
    }
    /**
     * @inheritDoc
     */
    public function uninstall(InstalledRepositoryInterface $repo, PackageInterface $package)
    {
        if (!$repo->hasPackage($package)) {
            throw new \InvalidArgumentException('Package is not installed: ' . $package);
        }
        $promise = $this->removeCode($package);
        if (!$promise instanceof PromiseInterface) {
            $promise = \React\Promise\resolve(null);
        }
        $binaryInstaller = $this->binaryInstaller;
        $downloadPath = $this->getPackageBasePath($package);
        $filesystem = $this->filesystem;
        return $promise->then(static function () use ($binaryInstaller, $filesystem, $downloadPath, $package, $repo): void {
            $binaryInstaller->removeBinaries($package);
            $repo->removePackage($package);
            if (strpos($package->getName(), '/')) {
                $packageVendorDir = dirname($downloadPath);
                if (is_dir($packageVendorDir) && $filesystem->isDirEmpty($packageVendorDir)) {
                    Silencer::call('rmdir', $packageVendorDir);
                }
            }
        });
    }
    /**
     * @inheritDoc
     *
     * @return string
     */
    public function getInstallPath(PackageInterface $package)
    {
        $this->initializeVendorDir();
        $basePath = ($this->vendorDir ? $this->vendorDir . '/' : '') . $package->getPrettyName();
        $targetDir = $package->getTargetDir();
        return $basePath . ($targetDir ? '/' . $targetDir : '');
    }
    /**
     * Make sure binaries are installed for a given package.
     *
     * @param PackageInterface $package Package instance
     */
    public function ensureBinariesPresence(PackageInterface $package)
    {
        $this->binaryInstaller->installBinaries($package, $this->getInstallPath($package), \false);
    }
    /**
     * Returns the base path of the package without target-dir path
     *
     * It is used for BC as getInstallPath tends to be overridden by
     * installer plugins but not getPackageBasePath
     *
     * @return string
     */
    protected function getPackageBasePath(PackageInterface $package)
    {
        $installPath = $this->getInstallPath($package);
        $targetDir = $package->getTargetDir();
        if ($targetDir) {
            return Preg::replace('{/*' . str_replace('/', '/+', preg_quote($targetDir)) . '/?$}', '', $installPath);
        }
        return $installPath;
    }
    /**
     * @return PromiseInterface|null
     * @phpstan-return PromiseInterface<void|null>|null
     */
    protected function installCode(PackageInterface $package)
    {
        $downloadPath = $this->getInstallPath($package);
        return $this->getDownloadManager()->install($package, $downloadPath);
    }
    /**
     * @return PromiseInterface|null
     * @phpstan-return PromiseInterface<void|null>|null
     */
    protected function updateCode(PackageInterface $initial, PackageInterface $target)
    {
        $initialDownloadPath = $this->getInstallPath($initial);
        $targetDownloadPath = $this->getInstallPath($target);
        if ($targetDownloadPath !== $initialDownloadPath) {
            // if the target and initial dirs intersect, we force a remove + install
            // to avoid the rename wiping the target dir as part of the initial dir cleanup
            if (strpos($initialDownloadPath, $targetDownloadPath) === 0 || strpos($targetDownloadPath, $initialDownloadPath) === 0) {
                $promise = $this->removeCode($initial);
                if (!$promise instanceof PromiseInterface) {
                    $promise = \React\Promise\resolve(null);
                }
                return $promise->then(function () use ($target): PromiseInterface {
                    $promise = $this->installCode($target);
                    if ($promise instanceof PromiseInterface) {
                        return $promise;
                    }
                    return \React\Promise\resolve(null);
                });
            }
            $this->filesystem->rename($initialDownloadPath, $targetDownloadPath);
        }
        return $this->getDownloadManager()->update($initial, $target, $targetDownloadPath);
    }
    /**
     * @return PromiseInterface|null
     * @phpstan-return PromiseInterface<void|null>|null
     */
    protected function removeCode(PackageInterface $package)
    {
        $downloadPath = $this->getPackageBasePath($package);
        return $this->getDownloadManager()->remove($package, $downloadPath);
    }
    /**
     * @return void
     */
    protected function initializeVendorDir()
    {
        $this->filesystem->ensureDirectoryExists($this->vendorDir);
        $this->vendorDir = realpath($this->vendorDir);
    }
    protected function getDownloadManager(): DownloadManager
    {
        assert($this->downloadManager instanceof DownloadManager, new \LogicException(self::class . ' should be initialized with a fully loaded Composer instance to be able to install/... packages'));
        return $this->downloadManager;
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer\Installer;

use Composer\Package\PackageInterface;
use Composer\Repository\InstalledRepositoryInterface;
use InvalidArgumentException;
use React\Promise\PromiseInterface;
/**
 * Interface for the package installation manager.
 *
 * @author Konstantin Kudryashov <ever.zet@gmail.com>
 * @author Jordi Boggiano <j.boggiano@seld.be>
 */
interface InstallerInterface
{
    /**
     * Decides if the installer supports the given type
     *
     * @return bool
     */
    public function supports(string $packageType);
    /**
     * Checks that provided package is installed.
     *
     * @param InstalledRepositoryInterface $repo    repository in which to check
     * @param PackageInterface             $package package instance
     *
     * @return bool
     */
    public function isInstalled(InstalledRepositoryInterface $repo, PackageInterface $package);
    /**
     * Downloads the files needed to later install the given package.
     *
     * @param  PackageInterface      $package     package instance
     * @param  PackageInterface      $prevPackage previous package instance in case of an update
     * @return PromiseInterface|null
     * @phpstan-return PromiseInterface<void|null>|null
     */
    public function download(PackageInterface $package, ?PackageInterface $prevPackage = null);
    /**
     * Do anything that needs to be done between all downloads have been completed and the actual operation is executed
     *
     * All packages get first downloaded, then all together prepared, then all together installed/updated/uninstalled. Therefore
     * for error recovery it is important to avoid failing during install/update/uninstall as much as possible, and risky things or
     * user prompts should happen in the prepare step rather. In case of failure, cleanup() will be called so that changes can
     * be undone as much as possible.
     *
     * @param  string                $type        one of install/update/uninstall
     * @param  PackageInterface      $package     package instance
     * @param  PackageInterface      $prevPackage previous package instance in case of an update
     * @return PromiseInterface|null
     * @phpstan-return PromiseInterface<void|null>|null
     */
    public function prepare(string $type, PackageInterface $package, ?PackageInterface $prevPackage = null);
    /**
     * Installs specific package.
     *
     * @param  InstalledRepositoryInterface $repo    repository in which to check
     * @param  PackageInterface             $package package instance
     * @return PromiseInterface|null
     * @phpstan-return PromiseInterface<void|null>|null
     */
    public function install(InstalledRepositoryInterface $repo, PackageInterface $package);
    /**
     * Updates specific package.
     *
     * @param  InstalledRepositoryInterface $repo    repository in which to check
     * @param  PackageInterface             $initial already installed package version
     * @param  PackageInterface             $target  updated version
     * @throws InvalidArgumentException     if $initial package is not installed
     * @return PromiseInterface|null
     * @phpstan-return PromiseInterface<void|null>|null
     */
    public function update(InstalledRepositoryInterface $repo, PackageInterface $initial, PackageInterface $target);
    /**
     * Uninstalls specific package.
     *
     * @param  InstalledRepositoryInterface $repo    repository in which to check
     * @param  PackageInterface             $package package instance
     * @return PromiseInterface|null
     * @phpstan-return PromiseInterface<void|null>|null
     */
    public function uninstall(InstalledRepositoryInterface $repo, PackageInterface $package);
    /**
     * Do anything to cleanup changes applied in the prepare or install/update/uninstall steps
     *
     * Note that cleanup will be called for all packages regardless if they failed an operation or not, to give
     * all installers a change to cleanup things they did previously, so you need to keep track of changes
     * applied in the installer/downloader themselves.
     *
     * @param  string                $type        one of install/update/uninstall
     * @param  PackageInterface      $package     package instance
     * @param  PackageInterface      $prevPackage previous package instance in case of an update
     * @return PromiseInterface|null
     * @phpstan-return PromiseInterface<void|null>|null
     */
    public function cleanup(string $type, PackageInterface $package, ?PackageInterface $prevPackage = null);
    /**
     * Returns the absolute installation path of a package.
     *
     * @return string|null absolute path to install to, which MUST not end with a slash, or null if the package does not have anything installed on disk
     */
    public function getInstallPath(PackageInterface $package);
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer\Installer;

use Composer\Repository\InstalledRepositoryInterface;
use Composer\Package\PackageInterface;
use Composer\IO\IOInterface;
use Composer\DependencyResolver\Operation\UpdateOperation;
use Composer\DependencyResolver\Operation\InstallOperation;
use Composer\DependencyResolver\Operation\UninstallOperation;
/**
 * Metapackage installation manager.
 *
 * @author Martin Hasoň <martin.hason@gmail.com>
 */
class MetapackageInstaller implements \Composer\Installer\InstallerInterface
{
    /** @var IOInterface */
    private $io;
    public function __construct(IOInterface $io)
    {
        $this->io = $io;
    }
    /**
     * @inheritDoc
     */
    public function supports(string $packageType)
    {
        return $packageType === 'metapackage';
    }
    /**
     * @inheritDoc
     */
    public function isInstalled(InstalledRepositoryInterface $repo, PackageInterface $package)
    {
        return $repo->hasPackage($package);
    }
    /**
     * @inheritDoc
     */
    public function download(PackageInterface $package, ?PackageInterface $prevPackage = null)
    {
        // noop
        return \React\Promise\resolve(null);
    }
    /**
     * @inheritDoc
     */
    public function prepare($type, PackageInterface $package, ?PackageInterface $prevPackage = null)
    {
        // noop
        return \React\Promise\resolve(null);
    }
    /**
     * @inheritDoc
     */
    public function cleanup($type, PackageInterface $package, ?PackageInterface $prevPackage = null)
    {
        // noop
        return \React\Promise\resolve(null);
    }
    /**
     * @inheritDoc
     */
    public function install(InstalledRepositoryInterface $repo, PackageInterface $package)
    {
        $this->io->writeError("  - " . InstallOperation::format($package));
        $repo->addPackage(clone $package);
        return \React\Promise\resolve(null);
    }
    /**
     * @inheritDoc
     */
    public function update(InstalledRepositoryInterface $repo, PackageInterface $initial, PackageInterface $target)
    {
        if (!$repo->hasPackage($initial)) {
            throw new \InvalidArgumentException('Package is not installed: ' . $initial);
        }
        $this->io->writeError("  - " . UpdateOperation::format($initial, $target));
        $repo->removePackage($initial);
        $repo->addPackage(clone $target);
        return \React\Promise\resolve(null);
    }
    /**
     * @inheritDoc
     */
    public function uninstall(InstalledRepositoryInterface $repo, PackageInterface $package)
    {
        if (!$repo->hasPackage($package)) {
            throw new \InvalidArgumentException('Package is not installed: ' . $package);
        }
        $this->io->writeError("  - " . UninstallOperation::format($package));
        $repo->removePackage($package);
        return \React\Promise\resolve(null);
    }
    /**
     * @inheritDoc
     *
     * @return null
     */
    public function getInstallPath(PackageInterface $package)
    {
        return null;
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer\Installer;

use React\Promise\PromiseInterface;
use Composer\Package\PackageInterface;
use Composer\Downloader\DownloadManager;
use Composer\Repository\InstalledRepositoryInterface;
use Composer\Util\Filesystem;
/**
 * Project Installer is used to install a single package into a directory as
 * root project.
 *
 * @author Benjamin Eberlei <kontakt@beberlei.de>
 */
class ProjectInstaller implements \Composer\Installer\InstallerInterface
{
    /** @var string */
    private $installPath;
    /** @var DownloadManager */
    private $downloadManager;
    /** @var Filesystem */
    private $filesystem;
    public function __construct(string $installPath, DownloadManager $dm, Filesystem $fs)
    {
        $this->installPath = rtrim(strtr($installPath, '\\', '/'), '/') . '/';
        $this->downloadManager = $dm;
        $this->filesystem = $fs;
    }
    /**
     * Decides if the installer supports the given type
     */
    public function supports(string $packageType): bool
    {
        return \true;
    }
    /**
     * @inheritDoc
     */
    public function isInstalled(InstalledRepositoryInterface $repo, PackageInterface $package): bool
    {
        return \false;
    }
    /**
     * @inheritDoc
     */
    public function download(PackageInterface $package, ?PackageInterface $prevPackage = null): ?PromiseInterface
    {
        $installPath = $this->installPath;
        if (file_exists($installPath) && !$this->filesystem->isDirEmpty($installPath)) {
            throw new \InvalidArgumentException("Project directory {$installPath} is not empty.");
        }
        if (!is_dir($installPath)) {
            mkdir($installPath, 0777, \true);
        }
        return $this->downloadManager->download($package, $installPath, $prevPackage);
    }
    /**
     * @inheritDoc
     */
    public function prepare($type, PackageInterface $package, ?PackageInterface $prevPackage = null): ?PromiseInterface
    {
        return $this->downloadManager->prepare($type, $package, $this->installPath, $prevPackage);
    }
    /**
     * @inheritDoc
     */
    public function cleanup($type, PackageInterface $package, ?PackageInterface $prevPackage = null): ?PromiseInterface
    {
        return $this->downloadManager->cleanup($type, $package, $this->installPath, $prevPackage);
    }
    /**
     * @inheritDoc
     */
    public function install(InstalledRepositoryInterface $repo, PackageInterface $package): ?PromiseInterface
    {
        return $this->downloadManager->install($package, $this->installPath);
    }
    /**
     * @inheritDoc
     */
    public function update(InstalledRepositoryInterface $repo, PackageInterface $initial, PackageInterface $target): ?PromiseInterface
    {
        throw new \InvalidArgumentException("not supported");
    }
    /**
     * @inheritDoc
     */
    public function uninstall(InstalledRepositoryInterface $repo, PackageInterface $package): ?PromiseInterface
    {
        throw new \InvalidArgumentException("not supported");
    }
    /**
     * Returns the installation path of a package
     *
     * @return string configured install path
     */
    public function getInstallPath(PackageInterface $package): string
    {
        return $this->installPath;
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer\Installer;

use Composer\IO\IOInterface;
use Composer\Package\PackageInterface;
use Composer\Pcre\Preg;
use Composer\Repository\InstalledRepository;
use _ContaoManager\Symfony\Component\Console\Formatter\OutputFormatter;
/**
 * Add suggested packages from different places to output them in the end.
 *
 * @author Haralan Dobrev <hkdobrev@gmail.com>
 */
class SuggestedPackagesReporter
{
    public const MODE_LIST = 1;
    public const MODE_BY_PACKAGE = 2;
    public const MODE_BY_SUGGESTION = 4;
    /**
     * @var array<array{source: string, target: string, reason: string}>
     */
    protected $suggestedPackages = [];
    /**
     * @var IOInterface
     */
    private $io;
    public function __construct(IOInterface $io)
    {
        $this->io = $io;
    }
    /**
     * @return array<array{source: string, target: string, reason: string}> Suggested packages with source, target and reason keys.
     */
    public function getPackages(): array
    {
        return $this->suggestedPackages;
    }
    /**
     * Add suggested packages to be listed after install
     *
     * Could be used to add suggested packages both from the installer
     * or from CreateProjectCommand.
     *
     * @param  string                    $source Source package which made the suggestion
     * @param  string                    $target Target package to be suggested
     * @param  string                    $reason Reason the target package to be suggested
     */
    public function addPackage(string $source, string $target, string $reason): \Composer\Installer\SuggestedPackagesReporter
    {
        $this->suggestedPackages[] = ['source' => $source, 'target' => $target, 'reason' => $reason];
        return $this;
    }
    /**
     * Add all suggestions from a package.
     */
    public function addSuggestionsFromPackage(PackageInterface $package): \Composer\Installer\SuggestedPackagesReporter
    {
        $source = $package->getPrettyName();
        foreach ($package->getSuggests() as $target => $reason) {
            $this->addPackage($source, $target, $reason);
        }
        return $this;
    }
    /**
     * Output suggested packages.
     *
     * Do not list the ones already installed if installed repository provided.
     *
     * @param  int                      $mode             One of the MODE_* constants from this class
     * @param  InstalledRepository|null $installedRepo    If passed in, suggested packages which are installed already will be skipped
     * @param  PackageInterface|null    $onlyDependentsOf If passed in, only the suggestions from direct dependents of that package, or from the package itself, will be shown
     */
    public function output(int $mode, ?InstalledRepository $installedRepo = null, ?PackageInterface $onlyDependentsOf = null): void
    {
        $suggestedPackages = $this->getFilteredSuggestions($installedRepo, $onlyDependentsOf);
        $suggesters = [];
        $suggested = [];
        foreach ($suggestedPackages as $suggestion) {
            $suggesters[$suggestion['source']][$suggestion['target']] = $suggestion['reason'];
            $suggested[$suggestion['target']][$suggestion['source']] = $suggestion['reason'];
        }
        ksort($suggesters);
        ksort($suggested);
        // Simple mode
        if ($mode & self::MODE_LIST) {
            foreach (array_keys($suggested) as $name) {
                $this->io->write(sprintf('<info>%s</info>', $name));
            }
            return;
        }
        // Grouped by package
        if ($mode & self::MODE_BY_PACKAGE) {
            foreach ($suggesters as $suggester => $suggestions) {
                $this->io->write(sprintf('<comment>%s</comment> suggests:', $suggester));
                foreach ($suggestions as $suggestion => $reason) {
                    $this->io->write(sprintf(' - <info>%s</info>' . ($reason ? ': %s' : ''), $suggestion, $this->escapeOutput($reason)));
                }
                $this->io->write('');
            }
        }
        // Grouped by suggestion
        if ($mode & self::MODE_BY_SUGGESTION) {
            // Improve readability in full mode
            if ($mode & self::MODE_BY_PACKAGE) {
                $this->io->write(str_repeat('-', 78));
            }
            foreach ($suggested as $suggestion => $suggesters) {
                $this->io->write(sprintf('<comment>%s</comment> is suggested by:', $suggestion));
                foreach ($suggesters as $suggester => $reason) {
                    $this->io->write(sprintf(' - <info>%s</info>' . ($reason ? ': %s' : ''), $suggester, $this->escapeOutput($reason)));
                }
                $this->io->write('');
            }
        }
        if ($onlyDependentsOf) {
            $allSuggestedPackages = $this->getFilteredSuggestions($installedRepo);
            $diff = count($allSuggestedPackages) - count($suggestedPackages);
            if ($diff) {
                $this->io->write('<info>' . $diff . ' additional suggestions</info> by transitive dependencies can be shown with <info>--all</info>');
            }
        }
    }
    /**
     * Output number of new suggested packages and a hint to use suggest command.
     *
     * @param  InstalledRepository|null $installedRepo    If passed in, suggested packages which are installed already will be skipped
     * @param  PackageInterface|null    $onlyDependentsOf If passed in, only the suggestions from direct dependents of that package, or from the package itself, will be shown
     */
    public function outputMinimalistic(?InstalledRepository $installedRepo = null, ?PackageInterface $onlyDependentsOf = null): void
    {
        $suggestedPackages = $this->getFilteredSuggestions($installedRepo, $onlyDependentsOf);
        if ($suggestedPackages) {
            $this->io->writeError('<info>' . count($suggestedPackages) . ' package suggestions were added by new dependencies, use `composer suggest` to see details.</info>');
        }
    }
    /**
     * @param  InstalledRepository|null $installedRepo    If passed in, suggested packages which are installed already will be skipped
     * @param  PackageInterface|null    $onlyDependentsOf If passed in, only the suggestions from direct dependents of that package, or from the package itself, will be shown
     * @return mixed[]
     */
    private function getFilteredSuggestions(?InstalledRepository $installedRepo = null, ?PackageInterface $onlyDependentsOf = null): array
    {
        $suggestedPackages = $this->getPackages();
        $installedNames = [];
        if (null !== $installedRepo && !empty($suggestedPackages)) {
            foreach ($installedRepo->getPackages() as $package) {
                $installedNames = array_merge($installedNames, $package->getNames());
            }
        }
        $sourceFilter = [];
        if ($onlyDependentsOf) {
            $sourceFilter = array_map(static function ($link): string {
                return $link->getTarget();
            }, array_merge($onlyDependentsOf->getRequires(), $onlyDependentsOf->getDevRequires()));
            $sourceFilter[] = $onlyDependentsOf->getName();
        }
        $suggestions = [];
        foreach ($suggestedPackages as $suggestion) {
            if (in_array($suggestion['target'], $installedNames) || \count($sourceFilter) > 0 && !in_array($suggestion['source'], $sourceFilter)) {
                continue;
            }
            $suggestions[] = $suggestion;
        }
        return $suggestions;
    }
    private function escapeOutput(string $string): string
    {
        return OutputFormatter::escape($this->removeControlCharacters($string));
    }
    private function removeControlCharacters(string $string): string
    {
        return Preg::replace('/[[:cntrl:]]/', '', str_replace("\n", ' ', $string));
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer\Installer;

use Composer\IO\IOInterface;
use Composer\IO\ConsoleIO;
use Composer\Package\PackageInterface;
use Composer\Package\AliasPackage;
use Composer\Repository\InstalledRepositoryInterface;
use Composer\DependencyResolver\Operation\OperationInterface;
use Composer\DependencyResolver\Operation\InstallOperation;
use Composer\DependencyResolver\Operation\UpdateOperation;
use Composer\DependencyResolver\Operation\UninstallOperation;
use Composer\DependencyResolver\Operation\MarkAliasInstalledOperation;
use Composer\DependencyResolver\Operation\MarkAliasUninstalledOperation;
use Composer\Downloader\FileDownloader;
use Composer\EventDispatcher\EventDispatcher;
use Composer\Util\Loop;
use Composer\Util\Platform;
use React\Promise\PromiseInterface;
use _ContaoManager\Seld\Signal\SignalHandler;
/**
 * Package operation manager.
 *
 * @author Konstantin Kudryashov <ever.zet@gmail.com>
 * @author Jordi Boggiano <j.boggiano@seld.be>
 * @author Nils Adermann <naderman@naderman.de>
 */
class InstallationManager
{
    /** @var list<InstallerInterface> */
    private $installers = [];
    /** @var array<string, InstallerInterface> */
    private $cache = [];
    /** @var array<string, array<PackageInterface>> */
    private $notifiablePackages = [];
    /** @var Loop */
    private $loop;
    /** @var IOInterface */
    private $io;
    /** @var ?EventDispatcher */
    private $eventDispatcher;
    /** @var bool */
    private $outputProgress;
    public function __construct(Loop $loop, IOInterface $io, ?EventDispatcher $eventDispatcher = null)
    {
        $this->loop = $loop;
        $this->io = $io;
        $this->eventDispatcher = $eventDispatcher;
    }
    public function reset(): void
    {
        $this->notifiablePackages = [];
        FileDownloader::$downloadMetadata = [];
    }
    /**
     * Adds installer
     *
     * @param InstallerInterface $installer installer instance
     */
    public function addInstaller(\Composer\Installer\InstallerInterface $installer): void
    {
        array_unshift($this->installers, $installer);
        $this->cache = [];
    }
    /**
     * Removes installer
     *
     * @param InstallerInterface $installer installer instance
     */
    public function removeInstaller(\Composer\Installer\InstallerInterface $installer): void
    {
        if (\false !== $key = array_search($installer, $this->installers, \true)) {
            array_splice($this->installers, $key, 1);
            $this->cache = [];
        }
    }
    /**
     * Disables plugins.
     *
     * We prevent any plugins from being instantiated by
     * disabling the PluginManager. This ensures that no third-party
     * code is ever executed.
     */
    public function disablePlugins(): void
    {
        foreach ($this->installers as $i => $installer) {
            if (!$installer instanceof \Composer\Installer\PluginInstaller) {
                continue;
            }
            $installer->disablePlugins();
        }
    }
    /**
     * Returns installer for a specific package type.
     *
     * @param string $type package type
     *
     * @throws \InvalidArgumentException if installer for provided type is not registered
     */
    public function getInstaller(string $type): \Composer\Installer\InstallerInterface
    {
        $type = strtolower($type);
        if (isset($this->cache[$type])) {
            return $this->cache[$type];
        }
        foreach ($this->installers as $installer) {
            if ($installer->supports($type)) {
                return $this->cache[$type] = $installer;
            }
        }
        throw new \InvalidArgumentException('Unknown installer type: ' . $type);
    }
    /**
     * Checks whether provided package is installed in one of the registered installers.
     *
     * @param InstalledRepositoryInterface $repo    repository in which to check
     * @param PackageInterface             $package package instance
     */
    public function isPackageInstalled(InstalledRepositoryInterface $repo, PackageInterface $package): bool
    {
        if ($package instanceof AliasPackage) {
            return $repo->hasPackage($package) && $this->isPackageInstalled($repo, $package->getAliasOf());
        }
        return $this->getInstaller($package->getType())->isInstalled($repo, $package);
    }
    /**
     * Install binary for the given package.
     * If the installer associated to this package doesn't handle that function, it'll do nothing.
     *
     * @param PackageInterface $package Package instance
     */
    public function ensureBinariesPresence(PackageInterface $package): void
    {
        try {
            $installer = $this->getInstaller($package->getType());
        } catch (\InvalidArgumentException $e) {
            // no installer found for the current package type (@see `getInstaller()`)
            return;
        }
        // if the given installer support installing binaries
        if ($installer instanceof \Composer\Installer\BinaryPresenceInterface) {
            $installer->ensureBinariesPresence($package);
        }
    }
    /**
     * Executes solver operation.
     *
     * @param InstalledRepositoryInterface $repo         repository in which to add/remove/update packages
     * @param OperationInterface[]         $operations   operations to execute
     * @param bool                         $devMode      whether the install is being run in dev mode
     * @param bool                         $runScripts   whether to dispatch script events
     * @param bool                         $downloadOnly whether to only download packages
     */
    public function execute(InstalledRepositoryInterface $repo, array $operations, bool $devMode = \true, bool $runScripts = \true, bool $downloadOnly = \false): void
    {
        /** @var array<callable(): ?PromiseInterface<void|null>> $cleanupPromises */
        $cleanupPromises = [];
        $signalHandler = SignalHandler::create([SignalHandler::SIGINT, SignalHandler::SIGTERM, SignalHandler::SIGHUP], function (string $signal, SignalHandler $handler) use (&$cleanupPromises) {
            $this->io->writeError('Received ' . $signal . ', aborting', \true, IOInterface::DEBUG);
            $this->runCleanup($cleanupPromises);
            $handler->exitWithLastSignal();
        });
        try {
            // execute operations in batches to make sure download-modifying-plugins are installed
            // before the other packages get downloaded
            $batches = [];
            $batch = [];
            foreach ($operations as $index => $operation) {
                if ($operation instanceof UpdateOperation || $operation instanceof InstallOperation) {
                    $package = $operation instanceof UpdateOperation ? $operation->getTargetPackage() : $operation->getPackage();
                    if ($package->getType() === 'composer-plugin') {
                        $extra = $package->getExtra();
                        if (isset($extra['plugin-modifies-downloads']) && $extra['plugin-modifies-downloads'] === \true) {
                            if (count($batch) > 0) {
                                $batches[] = $batch;
                            }
                            $batches[] = [$index => $operation];
                            $batch = [];
                            continue;
                        }
                    }
                }
                $batch[$index] = $operation;
            }
            if (count($batch) > 0) {
                $batches[] = $batch;
            }
            foreach ($batches as $batchToExecute) {
                $this->downloadAndExecuteBatch($repo, $batchToExecute, $cleanupPromises, $devMode, $runScripts, $downloadOnly, $operations);
            }
        } catch (\Exception $e) {
            $this->runCleanup($cleanupPromises);
            throw $e;
        } finally {
            $signalHandler->unregister();
        }
        if ($downloadOnly) {
            return;
        }
        // do a last write so that we write the repository even if nothing changed
        // as that can trigger an update of some files like InstalledVersions.php if
        // running a new composer version
        $repo->write($devMode, $this);
    }
    /**
     * @param OperationInterface[] $operations    List of operations to execute in this batch
     * @param OperationInterface[] $allOperations Complete list of operations to be executed in the install job, used for event listeners
     * @phpstan-param array<callable(): ?PromiseInterface<void|null>> $cleanupPromises
     */
    private function downloadAndExecuteBatch(InstalledRepositoryInterface $repo, array $operations, array &$cleanupPromises, bool $devMode, bool $runScripts, bool $downloadOnly, array $allOperations): void
    {
        $promises = [];
        foreach ($operations as $index => $operation) {
            $opType = $operation->getOperationType();
            // ignoring alias ops as they don't need to execute anything at this stage
            if (!in_array($opType, ['update', 'install', 'uninstall'], \true)) {
                continue;
            }
            if ($opType === 'update') {
                /** @var UpdateOperation $operation */
                $package = $operation->getTargetPackage();
                $initialPackage = $operation->getInitialPackage();
            } else {
                /** @var InstallOperation|MarkAliasInstalledOperation|MarkAliasUninstalledOperation|UninstallOperation $operation */
                $package = $operation->getPackage();
                $initialPackage = null;
            }
            $installer = $this->getInstaller($package->getType());
            $cleanupPromises[$index] = static function () use ($opType, $installer, $package, $initialPackage): ?PromiseInterface {
                // avoid calling cleanup if the download was not even initialized for a package
                // as without installation source configured nothing will work
                if (null === $package->getInstallationSource()) {
                    return \React\Promise\resolve(null);
                }
                return $installer->cleanup($opType, $package, $initialPackage);
            };
            if ($opType !== 'uninstall') {
                $promise = $installer->download($package, $initialPackage);
                if (null !== $promise) {
                    $promises[] = $promise;
                }
            }
        }
        // execute all downloads first
        if (count($promises) > 0) {
            $this->waitOnPromises($promises);
        }
        if ($downloadOnly) {
            $this->runCleanup($cleanupPromises);
            return;
        }
        // execute operations in batches to make sure every plugin is installed in the
        // right order and activated before the packages depending on it are installed
        $batches = [];
        $batch = [];
        foreach ($operations as $index => $operation) {
            if ($operation instanceof InstallOperation || $operation instanceof UpdateOperation) {
                $package = $operation instanceof UpdateOperation ? $operation->getTargetPackage() : $operation->getPackage();
                if ($package->getType() === 'composer-plugin' || $package->getType() === 'composer-installer') {
                    if (count($batch) > 0) {
                        $batches[] = $batch;
                    }
                    $batches[] = [$index => $operation];
                    $batch = [];
                    continue;
                }
            }
            $batch[$index] = $operation;
        }
        if (count($batch) > 0) {
            $batches[] = $batch;
        }
        foreach ($batches as $batchToExecute) {
            $this->executeBatch($repo, $batchToExecute, $cleanupPromises, $devMode, $runScripts, $allOperations);
        }
    }
    /**
     * @param OperationInterface[] $operations    List of operations to execute in this batch
     * @param OperationInterface[] $allOperations Complete list of operations to be executed in the install job, used for event listeners
     * @phpstan-param array<callable(): ?PromiseInterface<void|null>> $cleanupPromises
     */
    private function executeBatch(InstalledRepositoryInterface $repo, array $operations, array $cleanupPromises, bool $devMode, bool $runScripts, array $allOperations): void
    {
        $promises = [];
        $postExecCallbacks = [];
        foreach ($operations as $index => $operation) {
            $opType = $operation->getOperationType();
            // ignoring alias ops as they don't need to execute anything
            if (!in_array($opType, ['update', 'install', 'uninstall'], \true)) {
                // output alias ops in debug verbosity as they have no output otherwise
                if ($this->io->isDebug()) {
                    $this->io->writeError('  - ' . $operation->show(\false));
                }
                $this->{$opType}($repo, $operation);
                continue;
            }
            if ($opType === 'update') {
                /** @var UpdateOperation $operation */
                $package = $operation->getTargetPackage();
                $initialPackage = $operation->getInitialPackage();
            } else {
                /** @var InstallOperation|MarkAliasInstalledOperation|MarkAliasUninstalledOperation|UninstallOperation $operation */
                $package = $operation->getPackage();
                $initialPackage = null;
            }
            $installer = $this->getInstaller($package->getType());
            $eventName = ['install' => \Composer\Installer\PackageEvents::PRE_PACKAGE_INSTALL, 'update' => \Composer\Installer\PackageEvents::PRE_PACKAGE_UPDATE, 'uninstall' => \Composer\Installer\PackageEvents::PRE_PACKAGE_UNINSTALL][$opType];
            if ($runScripts && $this->eventDispatcher !== null) {
                $this->eventDispatcher->dispatchPackageEvent($eventName, $devMode, $repo, $allOperations, $operation);
            }
            $dispatcher = $this->eventDispatcher;
            $io = $this->io;
            $promise = $installer->prepare($opType, $package, $initialPackage);
            if (!$promise instanceof PromiseInterface) {
                $promise = \React\Promise\resolve(null);
            }
            $promise = $promise->then(function () use ($opType, $repo, $operation) {
                return $this->{$opType}($repo, $operation);
            })->then($cleanupPromises[$index])->then(function () use ($devMode, $repo): void {
                $repo->write($devMode, $this);
            }, static function ($e) use ($opType, $package, $io): void {
                $io->writeError('    <error>' . ucfirst($opType) . ' of ' . $package->getPrettyName() . ' failed</error>');
                throw $e;
            });
            $eventName = ['install' => \Composer\Installer\PackageEvents::POST_PACKAGE_INSTALL, 'update' => \Composer\Installer\PackageEvents::POST_PACKAGE_UPDATE, 'uninstall' => \Composer\Installer\PackageEvents::POST_PACKAGE_UNINSTALL][$opType];
            if ($runScripts && $dispatcher !== null) {
                $postExecCallbacks[] = static function () use ($dispatcher, $eventName, $devMode, $repo, $allOperations, $operation): void {
                    $dispatcher->dispatchPackageEvent($eventName, $devMode, $repo, $allOperations, $operation);
                };
            }
            $promises[] = $promise;
        }
        // execute all prepare => installs/updates/removes => cleanup steps
        if (count($promises) > 0) {
            $this->waitOnPromises($promises);
        }
        Platform::workaroundFilesystemIssues();
        foreach ($postExecCallbacks as $cb) {
            $cb();
        }
    }
    /**
     * @param array<PromiseInterface<void|null>> $promises
     */
    private function waitOnPromises(array $promises): void
    {
        $progress = null;
        if ($this->outputProgress && $this->io instanceof ConsoleIO && !(bool) Platform::getEnv('CI') && !$this->io->isDebug() && count($promises) > 1) {
            $progress = $this->io->getProgressBar();
        }
        $this->loop->wait($promises, $progress);
        if ($progress !== null) {
            $progress->clear();
            // ProgressBar in non-decorated output does not output a final line-break and clear() does nothing
            if (!$this->io->isDecorated()) {
                $this->io->writeError('');
            }
        }
    }
    /**
     * Executes download operation.
     *
     * @phpstan-return PromiseInterface<void|null>|null
     */
    public function download(PackageInterface $package): ?PromiseInterface
    {
        $installer = $this->getInstaller($package->getType());
        $promise = $installer->cleanup("install", $package);
        return $promise;
    }
    /**
     * Executes install operation.
     *
     * @param InstalledRepositoryInterface $repo      repository in which to check
     * @param InstallOperation             $operation operation instance
     * @phpstan-return PromiseInterface<void|null>|null
     */
    public function install(InstalledRepositoryInterface $repo, InstallOperation $operation): ?PromiseInterface
    {
        $package = $operation->getPackage();
        $installer = $this->getInstaller($package->getType());
        $promise = $installer->install($repo, $package);
        $this->markForNotification($package);
        return $promise;
    }
    /**
     * Executes update operation.
     *
     * @param InstalledRepositoryInterface $repo      repository in which to check
     * @param UpdateOperation              $operation operation instance
     * @phpstan-return PromiseInterface<void|null>|null
     */
    public function update(InstalledRepositoryInterface $repo, UpdateOperation $operation): ?PromiseInterface
    {
        $initial = $operation->getInitialPackage();
        $target = $operation->getTargetPackage();
        $initialType = $initial->getType();
        $targetType = $target->getType();
        if ($initialType === $targetType) {
            $installer = $this->getInstaller($initialType);
            $promise = $installer->update($repo, $initial, $target);
            $this->markForNotification($target);
        } else {
            $promise = $this->getInstaller($initialType)->uninstall($repo, $initial);
            if (!$promise instanceof PromiseInterface) {
                $promise = \React\Promise\resolve(null);
            }
            $installer = $this->getInstaller($targetType);
            $promise = $promise->then(static function () use ($installer, $repo, $target): PromiseInterface {
                $promise = $installer->install($repo, $target);
                if ($promise instanceof PromiseInterface) {
                    return $promise;
                }
                return \React\Promise\resolve(null);
            });
        }
        return $promise;
    }
    /**
     * Uninstalls package.
     *
     * @param InstalledRepositoryInterface $repo      repository in which to check
     * @param UninstallOperation           $operation operation instance
     * @phpstan-return PromiseInterface<void|null>|null
     */
    public function uninstall(InstalledRepositoryInterface $repo, UninstallOperation $operation): ?PromiseInterface
    {
        $package = $operation->getPackage();
        $installer = $this->getInstaller($package->getType());
        return $installer->uninstall($repo, $package);
    }
    /**
     * Executes markAliasInstalled operation.
     *
     * @param InstalledRepositoryInterface $repo      repository in which to check
     * @param MarkAliasInstalledOperation  $operation operation instance
     */
    public function markAliasInstalled(InstalledRepositoryInterface $repo, MarkAliasInstalledOperation $operation): void
    {
        $package = $operation->getPackage();
        if (!$repo->hasPackage($package)) {
            $repo->addPackage(clone $package);
        }
    }
    /**
     * Executes markAlias operation.
     *
     * @param InstalledRepositoryInterface  $repo      repository in which to check
     * @param MarkAliasUninstalledOperation $operation operation instance
     */
    public function markAliasUninstalled(InstalledRepositoryInterface $repo, MarkAliasUninstalledOperation $operation): void
    {
        $package = $operation->getPackage();
        $repo->removePackage($package);
    }
    /**
     * Returns the installation path of a package
     *
     * @return string|null absolute path to install to, which does not end with a slash, or null if the package does not have anything installed on disk
     */
    public function getInstallPath(PackageInterface $package): ?string
    {
        $installer = $this->getInstaller($package->getType());
        return $installer->getInstallPath($package);
    }
    public function setOutputProgress(bool $outputProgress): void
    {
        $this->outputProgress = $outputProgress;
    }
    public function notifyInstalls(IOInterface $io): void
    {
        $promises = [];
        try {
            foreach ($this->notifiablePackages as $repoUrl => $packages) {
                // non-batch API, deprecated
                if (str_contains($repoUrl, '%package%')) {
                    foreach ($packages as $package) {
                        $url = str_replace('%package%', $package->getPrettyName(), $repoUrl);
                        $params = ['version' => $package->getPrettyVersion(), 'version_normalized' => $package->getVersion()];
                        $opts = ['retry-auth-failure' => \false, 'http' => ['method' => 'POST', 'header' => ['Content-type: application/x-www-form-urlencoded'], 'content' => http_build_query($params, '', '&'), 'timeout' => 3]];
                        $promises[] = $this->loop->getHttpDownloader()->add($url, $opts);
                    }
                    continue;
                }
                $postData = ['downloads' => []];
                foreach ($packages as $package) {
                    $packageNotification = ['name' => $package->getPrettyName(), 'version' => $package->getVersion()];
                    if (strpos($repoUrl, 'packagist.org/') !== \false) {
                        if (isset(FileDownloader::$downloadMetadata[$package->getName()])) {
                            $packageNotification['downloaded'] = FileDownloader::$downloadMetadata[$package->getName()];
                        } else {
                            $packageNotification['downloaded'] = \false;
                        }
                    }
                    $postData['downloads'][] = $packageNotification;
                }
                $opts = ['retry-auth-failure' => \false, 'http' => ['method' => 'POST', 'header' => ['Content-Type: application/json'], 'content' => json_encode($postData), 'timeout' => 6]];
                $promises[] = $this->loop->getHttpDownloader()->add($repoUrl, $opts);
            }
            $this->loop->wait($promises);
        } catch (\Exception $e) {
        }
        $this->reset();
    }
    private function markForNotification(PackageInterface $package): void
    {
        if ($package->getNotificationUrl() !== null) {
            $this->notifiablePackages[$package->getNotificationUrl()][$package->getName()] = $package;
        }
    }
    /**
     * @phpstan-param array<callable(): ?PromiseInterface<void|null>> $cleanupPromises
     */
    private function runCleanup(array $cleanupPromises): void
    {
        $promises = [];
        $this->loop->abortJobs();
        foreach ($cleanupPromises as $cleanup) {
            $promises[] = new \React\Promise\Promise(static function ($resolve) use ($cleanup): void {
                $promise = $cleanup();
                if (!$promise instanceof PromiseInterface) {
                    $resolve(null);
                } else {
                    $promise->then(static function () use ($resolve): void {
                        $resolve(null);
                    });
                }
            });
        }
        if (count($promises) > 0) {
            $this->loop->wait($promises);
        }
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer\Installer;

use Composer\Repository\InstalledRepositoryInterface;
use Composer\Package\PackageInterface;
/**
 * Does not install anything but marks packages installed in the repo
 *
 * Useful for dry runs
 *
 * @author Jordi Boggiano <j.boggiano@seld.be>
 */
class NoopInstaller implements \Composer\Installer\InstallerInterface
{
    /**
     * @inheritDoc
     */
    public function supports(string $packageType)
    {
        return \true;
    }
    /**
     * @inheritDoc
     */
    public function isInstalled(InstalledRepositoryInterface $repo, PackageInterface $package)
    {
        return $repo->hasPackage($package);
    }
    /**
     * @inheritDoc
     */
    public function download(PackageInterface $package, ?PackageInterface $prevPackage = null)
    {
        return \React\Promise\resolve(null);
    }
    /**
     * @inheritDoc
     */
    public function prepare($type, PackageInterface $package, ?PackageInterface $prevPackage = null)
    {
        return \React\Promise\resolve(null);
    }
    /**
     * @inheritDoc
     */
    public function cleanup($type, PackageInterface $package, ?PackageInterface $prevPackage = null)
    {
        return \React\Promise\resolve(null);
    }
    /**
     * @inheritDoc
     */
    public function install(InstalledRepositoryInterface $repo, PackageInterface $package)
    {
        if (!$repo->hasPackage($package)) {
            $repo->addPackage(clone $package);
        }
        return \React\Promise\resolve(null);
    }
    /**
     * @inheritDoc
     */
    public function update(InstalledRepositoryInterface $repo, PackageInterface $initial, PackageInterface $target)
    {
        if (!$repo->hasPackage($initial)) {
            throw new \InvalidArgumentException('Package is not installed: ' . $initial);
        }
        $repo->removePackage($initial);
        if (!$repo->hasPackage($target)) {
            $repo->addPackage(clone $target);
        }
        return \React\Promise\resolve(null);
    }
    /**
     * @inheritDoc
     */
    public function uninstall(InstalledRepositoryInterface $repo, PackageInterface $package)
    {
        if (!$repo->hasPackage($package)) {
            throw new \InvalidArgumentException('Package is not installed: ' . $package);
        }
        $repo->removePackage($package);
        return \React\Promise\resolve(null);
    }
    /**
     * @inheritDoc
     */
    public function getInstallPath(PackageInterface $package)
    {
        $targetDir = $package->getTargetDir();
        return $package->getPrettyName() . ($targetDir ? '/' . $targetDir : '');
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer\Advisory;

use Composer\Semver\Constraint\ConstraintInterface;
use DateTimeImmutable;
class SecurityAdvisory extends \Composer\Advisory\PartialSecurityAdvisory
{
    /**
     * @var string
     * @readonly
     */
    public $title;
    /**
     * @var string|null
     * @readonly
     */
    public $cve;
    /**
     * @var string|null
     * @readonly
     */
    public $link;
    /**
     * @var DateTimeImmutable
     * @readonly
     */
    public $reportedAt;
    /**
     * @var non-empty-array<array{name: string, remoteId: string}>
     * @readonly
     */
    public $sources;
    /**
     * @var string|null
     * @readonly
     */
    public $severity;
    /**
     * @param non-empty-array<array{name: string, remoteId: string}> $sources
     */
    public function __construct(string $packageName, string $advisoryId, ConstraintInterface $affectedVersions, string $title, array $sources, DateTimeImmutable $reportedAt, ?string $cve = null, ?string $link = null, ?string $severity = null)
    {
        parent::__construct($packageName, $advisoryId, $affectedVersions);
        $this->title = $title;
        $this->sources = $sources;
        $this->reportedAt = $reportedAt;
        $this->cve = $cve;
        $this->link = $link;
        $this->severity = $severity;
    }
    /**
     * @internal
     */
    public function toIgnoredAdvisory(?string $ignoreReason): \Composer\Advisory\IgnoredSecurityAdvisory
    {
        return new \Composer\Advisory\IgnoredSecurityAdvisory($this->packageName, $this->advisoryId, $this->affectedVersions, $this->title, $this->sources, $this->reportedAt, $this->cve, $this->link, $ignoreReason, $this->severity);
    }
    /**
     * @return mixed
     */
    #[\ReturnTypeWillChange]
    public function jsonSerialize()
    {
        $data = parent::jsonSerialize();
        $data['reportedAt'] = $data['reportedAt']->format(\DATE_RFC3339);
        return $data;
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer\Advisory;

use Composer\Pcre\Preg;
use Composer\Semver\Constraint\Constraint;
use Composer\Semver\Constraint\ConstraintInterface;
use Composer\Semver\VersionParser;
use JsonSerializable;
class PartialSecurityAdvisory implements JsonSerializable
{
    /**
     * @var string
     * @readonly
     */
    public $advisoryId;
    /**
     * @var string
     * @readonly
     */
    public $packageName;
    /**
     * @var ConstraintInterface
     * @readonly
     */
    public $affectedVersions;
    /**
     * @param array<mixed> $data
     * @return SecurityAdvisory|PartialSecurityAdvisory
     */
    public static function create(string $packageName, array $data, VersionParser $parser): self
    {
        try {
            $constraint = $parser->parseConstraints($data['affectedVersions']);
        } catch (\UnexpectedValueException $e) {
            // try to keep only the essential part of the constraint to turn invalid ones like <=3.20-test2 into <=3.20 which is better than nothing
            try {
                $affectedVersion = Preg::replace('{(^[>=<^~]*[\d.]+).*}', '$1', $data['affectedVersions']);
                $constraint = $parser->parseConstraints($affectedVersion);
            } catch (\UnexpectedValueException $e) {
                $constraint = new Constraint('==', '0.0.0-invalid-version');
            }
        }
        if (isset($data['title'], $data['sources'], $data['reportedAt'])) {
            return new \Composer\Advisory\SecurityAdvisory($packageName, $data['advisoryId'], $constraint, $data['title'], $data['sources'], new \DateTimeImmutable($data['reportedAt'], new \DateTimeZone('UTC')), $data['cve'] ?? null, $data['link'] ?? null, $data['severity'] ?? null);
        }
        return new self($packageName, $data['advisoryId'], $constraint);
    }
    public function __construct(string $packageName, string $advisoryId, ConstraintInterface $affectedVersions)
    {
        $this->advisoryId = $advisoryId;
        $this->packageName = $packageName;
        $this->affectedVersions = $affectedVersions;
    }
    /**
     * @return mixed
     */
    #[\ReturnTypeWillChange]
    public function jsonSerialize()
    {
        $data = (array) $this;
        $data['affectedVersions'] = $data['affectedVersions']->getPrettyString();
        return $data;
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer\Advisory;

use Composer\Config;
/**
 * @readonly
 * @internal
 */
class AuditConfig
{
    /**
     * @var bool Whether to run audit
     */
    public $audit;
    /**
     * @var Auditor::FORMAT_*
     */
    public $auditFormat;
    /**
     * @var Auditor::ABANDONED_*
     */
    public $auditAbandoned;
    /**
     * @var bool Should insecure versions be blocked during a composer update/required command
     */
    public $blockInsecure;
    /**
     * @var bool Should abandoned packages be blocked during a composer update/required command
     */
    public $blockAbandoned;
    /**
     * @var bool Should repositories that are unreachable or return a non-200 status code be ignored.
     */
    public $ignoreUnreachable;
    /**
     * @var array<string, string|null> List of advisory IDs to ignore during auditing => reason for ignoring
     */
    public $ignoreListForAudit;
    /**
     * @var array<string, string|null> List of advisory IDs to ignore during blocking
     */
    public $ignoreListForBlocking;
    /**
     * @var array<string, string|null> List of severities to ignore during auditing
     */
    public $ignoreSeverityForAudit;
    /**
     * @var array<string, string|null> List of severities to ignore during blocking
     */
    public $ignoreSeverityForBlocking;
    /**
     * @var array<string, string|null> List of abandoned packages to ignore during auditing
     */
    public $ignoreAbandonedForAudit;
    /**
     * @var array<string, string|null> List of abandoned packages to ignore during blocking
     */
    public $ignoreAbandonedForBlocking;
    /**
     * @param Auditor::FORMAT_* $auditFormat
     * @param Auditor::ABANDONED_* $auditAbandoned
     * @param array<string, string|null> $ignoreListForAudit
     * @param array<string, string|null> $ignoreListForBlocking
     * @param array<string, string|null> $ignoreSeverityForAudit
     * @param array<string, string|null> $ignoreSeverityForBlocking
     * @param array<string, string|null> $ignoreAbandonedForAudit
     * @param array<string, string|null> $ignoreAbandonedForBlocking
     */
    public function __construct(bool $audit, string $auditFormat, string $auditAbandoned, bool $blockInsecure, bool $blockAbandoned, bool $ignoreUnreachable, array $ignoreListForAudit, array $ignoreListForBlocking, array $ignoreSeverityForAudit, array $ignoreSeverityForBlocking, array $ignoreAbandonedForAudit, array $ignoreAbandonedForBlocking)
    {
        $this->audit = $audit;
        $this->auditFormat = $auditFormat;
        $this->auditAbandoned = $auditAbandoned;
        $this->blockInsecure = $blockInsecure;
        $this->blockAbandoned = $blockAbandoned;
        $this->ignoreUnreachable = $ignoreUnreachable;
        $this->ignoreListForAudit = $ignoreListForAudit;
        $this->ignoreListForBlocking = $ignoreListForBlocking;
        $this->ignoreSeverityForAudit = $ignoreSeverityForAudit;
        $this->ignoreSeverityForBlocking = $ignoreSeverityForBlocking;
        $this->ignoreAbandonedForAudit = $ignoreAbandonedForAudit;
        $this->ignoreAbandonedForBlocking = $ignoreAbandonedForBlocking;
    }
    /**
     * Parse ignore configuration supporting both simple and detailed formats with apply scopes
     *
     * Simple format: ['CVE-123', 'CVE-456'] or ['CVE-123' => 'reason']
     * Detailed format: ['CVE-123' => ['apply' => 'audit|block|all', 'reason' => '...']]
     *
     * @param array<mixed> $config
     * @return array{audit: array<string, string|null>, block: array<string, string|null>}
     */
    private static function parseIgnoreWithApply(array $config): array
    {
        $forAudit = [];
        $forBlock = [];
        foreach ($config as $key => $value) {
            // Simple format: ['CVE-123']
            if (is_int($key) && is_string($value)) {
                $id = $value;
                $apply = 'all';
                $reason = null;
            } elseif (is_string($value)) {
                $id = $key;
                $apply = 'all';
                $reason = $value;
            } elseif (is_array($value)) {
                $id = $key;
                $apply = $value['apply'] ?? 'all';
                $reason = $value['reason'] ?? null;
                // Validate apply value
                if (!in_array($apply, ['audit', 'block', 'all'], \true)) {
                    throw new \InvalidArgumentException("Invalid 'apply' value for '{$id}': {$apply}. Expected 'audit', 'block', or 'all'.");
                }
            } elseif ($value === null) {
                $id = $key;
                $apply = 'all';
                $reason = null;
            } else {
                continue;
            }
            // Store in appropriate lists based on apply scope
            if ($apply === 'audit' || $apply === 'all') {
                $forAudit[$id] = $reason;
            }
            if ($apply === 'block' || $apply === 'all') {
                $forBlock[$id] = $reason;
            }
        }
        return ['audit' => $forAudit, 'block' => $forBlock];
    }
    /**
     * @param Auditor::FORMAT_* $auditFormat
     */
    public static function fromConfig(Config $config, bool $audit = \true, string $auditFormat = \Composer\Advisory\Auditor::FORMAT_SUMMARY): self
    {
        $auditConfig = $config->get('audit');
        // Parse ignore lists with apply scopes
        $ignoreListParsed = self::parseIgnoreWithApply($auditConfig['ignore'] ?? []);
        $ignoreAbandonedParsed = self::parseIgnoreWithApply($auditConfig['ignore-abandoned'] ?? []);
        $ignoreSeverityParsed = self::parseIgnoreWithApply($auditConfig['ignore-severity'] ?? []);
        return new self($audit, $auditFormat, $auditConfig['abandoned'] ?? \Composer\Advisory\Auditor::ABANDONED_FAIL, (bool) ($auditConfig['block-insecure'] ?? \true), (bool) ($auditConfig['block-abandoned'] ?? \false), (bool) ($auditConfig['ignore-unreachable'] ?? \false), $ignoreListParsed['audit'], $ignoreListParsed['block'], $ignoreSeverityParsed['audit'], $ignoreSeverityParsed['block'], $ignoreAbandonedParsed['audit'], $ignoreAbandonedParsed['block']);
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer\Advisory;

use Composer\IO\ConsoleIO;
use Composer\IO\IOInterface;
use Composer\Json\JsonFile;
use Composer\Package\BasePackage;
use Composer\Package\CompletePackageInterface;
use Composer\Package\PackageInterface;
use Composer\Pcre\Preg;
use Composer\Repository\RepositorySet;
use Composer\Util\PackageInfo;
use InvalidArgumentException;
use _ContaoManager\Symfony\Component\Console\Formatter\OutputFormatter;
/**
 * @internal
 */
class Auditor
{
    public const FORMAT_TABLE = 'table';
    public const FORMAT_PLAIN = 'plain';
    public const FORMAT_JSON = 'json';
    public const FORMAT_SUMMARY = 'summary';
    public const FORMATS = [self::FORMAT_TABLE, self::FORMAT_PLAIN, self::FORMAT_JSON, self::FORMAT_SUMMARY];
    public const ABANDONED_IGNORE = 'ignore';
    public const ABANDONED_REPORT = 'report';
    public const ABANDONED_FAIL = 'fail';
    /** @internal */
    public const ABANDONEDS = [self::ABANDONED_IGNORE, self::ABANDONED_REPORT, self::ABANDONED_FAIL];
    /** Values to determine the audit result. */
    public const STATUS_OK = 0;
    public const STATUS_VULNERABLE = 1;
    public const STATUS_ABANDONED = 2;
    /**
     * @param PackageInterface[] $packages
     * @param self::FORMAT_* $format The format that will be used to output audit results.
     * @param bool $warningOnly If true, outputs a warning. If false, outputs an error.
     * @param array<string, string|null> $ignoreList List of advisory IDs, remote IDs, CVE IDs or package names that reported but not listed as vulnerabilities.
     * @param self::ABANDONED_* $abandoned
     * @param array<string, string|null> $ignoredSeverities List of ignored severity levels
     * @param array<string, string|null> $ignoreAbandoned List of abandoned package name that reported but not listed as vulnerabilities.
     *
     * @return int-mask<self::STATUS_*> A bitmask of STATUS_* constants or 0 on success
     * @throws InvalidArgumentException If no packages are passed in
     */
    public function audit(IOInterface $io, RepositorySet $repoSet, array $packages, string $format, bool $warningOnly = \true, array $ignoreList = [], string $abandoned = self::ABANDONED_FAIL, array $ignoredSeverities = [], bool $ignoreUnreachable = \false, array $ignoreAbandoned = []): int
    {
        $result = $repoSet->getMatchingSecurityAdvisories($packages, $format === self::FORMAT_SUMMARY, $ignoreUnreachable);
        $allAdvisories = $result['advisories'];
        $unreachableRepos = $result['unreachableRepos'];
        // we need the CVE & remote IDs set to filter ignores correctly so if we have any matches using the optimized codepath above
        // and ignores are set then we need to query again the full data to make sure it can be filtered
        if ($format === self::FORMAT_SUMMARY && $this->needsCompleteAdvisoryLoad($allAdvisories, $ignoreList)) {
            $result = $repoSet->getMatchingSecurityAdvisories($packages, \false, $ignoreUnreachable);
            $allAdvisories = $result['advisories'];
            $unreachableRepos = array_merge($unreachableRepos, $result['unreachableRepos']);
        }
        ['advisories' => $advisories, 'ignoredAdvisories' => $ignoredAdvisories] = $this->processAdvisories($allAdvisories, $ignoreList, $ignoredSeverities);
        $abandonedCount = 0;
        $affectedPackagesCount = count($advisories);
        if ($abandoned === self::ABANDONED_IGNORE) {
            $abandonedPackages = [];
        } else {
            $abandonedPackages = $this->filterAbandonedPackages($packages, $ignoreAbandoned);
            if ($abandoned === self::ABANDONED_FAIL) {
                $abandonedCount = count($abandonedPackages);
            }
        }
        $auditBitmask = $this->calculateBitmask(0 < $affectedPackagesCount, 0 < $abandonedCount);
        if (self::FORMAT_JSON === $format) {
            $json = ['advisories' => $advisories];
            if ($ignoredAdvisories !== []) {
                $json['ignored-advisories'] = $ignoredAdvisories;
            }
            if ($unreachableRepos !== []) {
                $json['unreachable-repositories'] = $unreachableRepos;
            }
            $json['abandoned'] = array_reduce($abandonedPackages, static function (array $carry, CompletePackageInterface $package): array {
                $carry[$package->getPrettyName()] = $package->getReplacementPackage();
                return $carry;
            }, []);
            $io->write(JsonFile::encode($json));
            return $auditBitmask;
        }
        $errorOrWarn = $warningOnly ? 'warning' : 'error';
        if ($affectedPackagesCount > 0 || count($ignoredAdvisories) > 0) {
            $passes = [[$ignoredAdvisories, "<info>Found %d ignored security vulnerability advisor%s affecting %d package%s%s</info>"], [$advisories, "<{$errorOrWarn}>Found %d security vulnerability advisor%s affecting %d package%s%s</{$errorOrWarn}>"]];
            foreach ($passes as [$advisoriesToOutput, $message]) {
                [$pkgCount, $totalAdvisoryCount] = $this->countAdvisories($advisoriesToOutput);
                if ($pkgCount > 0) {
                    $plurality = $totalAdvisoryCount === 1 ? 'y' : 'ies';
                    $pkgPlurality = $pkgCount === 1 ? '' : 's';
                    $punctuation = $format === 'summary' ? '.' : ':';
                    $io->writeError(sprintf($message, $totalAdvisoryCount, $plurality, $pkgCount, $pkgPlurality, $punctuation));
                    $this->outputAdvisories($io, $advisoriesToOutput, $format);
                }
            }
            if ($format === self::FORMAT_SUMMARY) {
                $io->writeError('Run "composer audit" for a full list of advisories.');
            }
        } else {
            $io->writeError('<info>No security vulnerability advisories found.</info>');
        }
        if (count($unreachableRepos) > 0) {
            $io->writeError('<warning>The following repositories were unreachable:</warning>');
            foreach ($unreachableRepos as $repo) {
                $io->writeError('  - ' . $repo);
            }
        }
        if (count($abandonedPackages) > 0 && $format !== self::FORMAT_SUMMARY) {
            $this->outputAbandonedPackages($io, $abandonedPackages, $format);
        }
        return $auditBitmask;
    }
    /**
     * @param array<string, array<SecurityAdvisory|PartialSecurityAdvisory>> $advisories
     * @param array<string, string|null> $ignoreList
     * @return bool
     */
    public function needsCompleteAdvisoryLoad(array $advisories, array $ignoreList): bool
    {
        if (\count($advisories) === 0) {
            return \false;
        }
        // no partial advisories present
        if (array_all($advisories, static function (array $pkgAdvisories) {
            return array_all($pkgAdvisories, static function ($advisory) {
                return $advisory instanceof \Composer\Advisory\SecurityAdvisory;
            });
        })) {
            return \false;
        }
        $ignoredIds = array_keys($ignoreList);
        return array_any($ignoredIds, static function (string $id) {
            return !str_starts_with($id, 'PKSA-');
        });
    }
    /**
     * @param array<PackageInterface> $packages
     * @param array<string, string|null> $ignoreAbandoned
     * @return array<CompletePackageInterface>
     */
    public function filterAbandonedPackages(array $packages, array $ignoreAbandoned): array
    {
        $filter = null;
        if (\count($ignoreAbandoned) !== 0) {
            $filter = BasePackage::packageNamesToRegexp(array_keys($ignoreAbandoned));
        }
        return array_filter($packages, static function (PackageInterface $pkg) use ($filter): bool {
            return $pkg instanceof CompletePackageInterface && $pkg->isAbandoned() && ($filter === null || !Preg::isMatch($filter, $pkg->getName()));
        });
    }
    /**
     * @phpstan-param array<string, array<PartialSecurityAdvisory|SecurityAdvisory>> $allAdvisories
     * @param array<string, string|null> $ignoreList List of advisory IDs, remote IDs, CVE IDs or package names that reported but not listed as vulnerabilities.
     * @param array<string, string|null> $ignoredSeverities List of ignored severity levels
     * @phpstan-return array{advisories: array<string, array<PartialSecurityAdvisory|SecurityAdvisory>>, ignoredAdvisories: array<string, array<PartialSecurityAdvisory|SecurityAdvisory>>}
     */
    public function processAdvisories(array $allAdvisories, array $ignoreList, array $ignoredSeverities): array
    {
        if ($ignoreList === [] && $ignoredSeverities === []) {
            return ['advisories' => $allAdvisories, 'ignoredAdvisories' => []];
        }
        $advisories = [];
        $ignored = [];
        $ignoreReason = null;
        foreach ($allAdvisories as $package => $pkgAdvisories) {
            foreach ($pkgAdvisories as $advisory) {
                $isActive = \true;
                if (array_key_exists($package, $ignoreList)) {
                    $isActive = \false;
                    $ignoreReason = $ignoreList[$package] ?? null;
                }
                if (array_key_exists($advisory->advisoryId, $ignoreList)) {
                    $isActive = \false;
                    $ignoreReason = $ignoreList[$advisory->advisoryId] ?? null;
                }
                if ($advisory instanceof \Composer\Advisory\SecurityAdvisory) {
                    if (is_string($advisory->severity) && array_key_exists($advisory->severity, $ignoredSeverities)) {
                        $isActive = \false;
                        $ignoreReason = $ignoredSeverities[$advisory->severity] ?? $advisory->severity . ' severity is ignored';
                    }
                    if (is_string($advisory->cve) && array_key_exists($advisory->cve, $ignoreList)) {
                        $isActive = \false;
                        $ignoreReason = $ignoreList[$advisory->cve] ?? null;
                    }
                    foreach ($advisory->sources as $source) {
                        if (array_key_exists($source['remoteId'], $ignoreList)) {
                            $isActive = \false;
                            $ignoreReason = $ignoreList[$source['remoteId']] ?? null;
                            break;
                        }
                    }
                }
                if ($isActive) {
                    $advisories[$package][] = $advisory;
                    continue;
                }
                // Partial security advisories only used in summary mode
                // and in that case we do not need to cast the object.
                if ($advisory instanceof \Composer\Advisory\SecurityAdvisory) {
                    $advisory = $advisory->toIgnoredAdvisory($ignoreReason);
                }
                $ignored[$package][] = $advisory;
            }
        }
        return ['advisories' => $advisories, 'ignoredAdvisories' => $ignored];
    }
    /**
     * @param array<string, array<PartialSecurityAdvisory>> $advisories
     * @return array{int, int} Count of affected packages and total count of advisories
     */
    private function countAdvisories(array $advisories): array
    {
        $count = 0;
        foreach ($advisories as $packageAdvisories) {
            $count += count($packageAdvisories);
        }
        return [count($advisories), $count];
    }
    /**
     * @param array<string, array<SecurityAdvisory>> $advisories
     * @param self::FORMAT_* $format The format that will be used to output audit results.
     */
    private function outputAdvisories(IOInterface $io, array $advisories, string $format): void
    {
        switch ($format) {
            case self::FORMAT_TABLE:
                if (!$io instanceof ConsoleIO) {
                    throw new InvalidArgumentException('Cannot use table format with ' . get_class($io));
                }
                $this->outputAdvisoriesTable($io, $advisories);
                return;
            case self::FORMAT_PLAIN:
                $this->outputAdvisoriesPlain($io, $advisories);
                return;
            case self::FORMAT_SUMMARY:
                return;
            default:
                throw new InvalidArgumentException('Invalid format "' . $format . '".');
        }
    }
    /**
     * @param array<string, array<SecurityAdvisory>> $advisories
     */
    private function outputAdvisoriesTable(ConsoleIO $io, array $advisories): void
    {
        foreach ($advisories as $packageAdvisories) {
            foreach ($packageAdvisories as $advisory) {
                $headers = ['Package', 'Severity', 'Advisory ID', 'CVE', 'Title', 'URL', 'Affected versions', 'Reported at'];
                $row = [$advisory->packageName, $this->getSeverity($advisory), $this->getAdvisoryId($advisory), $this->getCVE($advisory), $advisory->title, $this->getURL($advisory), $advisory->affectedVersions->getPrettyString(), $advisory->reportedAt->format(\DATE_ATOM)];
                if ($advisory instanceof \Composer\Advisory\IgnoredSecurityAdvisory) {
                    $headers[] = 'Ignore reason';
                    $row[] = $advisory->ignoreReason ?? 'None specified';
                }
                $io->getTable()->setHorizontal()->setHeaders($headers)->addRow(ConsoleIO::sanitize($row))->setColumnWidth(1, 80)->setColumnMaxWidth(1, 80)->render();
            }
        }
    }
    /**
     * @param array<string, array<SecurityAdvisory>> $advisories
     */
    private function outputAdvisoriesPlain(IOInterface $io, array $advisories): void
    {
        $error = [];
        $firstAdvisory = \true;
        foreach ($advisories as $packageAdvisories) {
            foreach ($packageAdvisories as $advisory) {
                if (!$firstAdvisory) {
                    $error[] = '--------';
                }
                $error[] = "Package: " . $advisory->packageName;
                $error[] = "Severity: " . $this->getSeverity($advisory);
                $error[] = "Advisory ID: " . $this->getAdvisoryId($advisory);
                $error[] = "CVE: " . $this->getCVE($advisory);
                $error[] = "Title: " . OutputFormatter::escape($advisory->title);
                $error[] = "URL: " . $this->getURL($advisory);
                $error[] = "Affected versions: " . OutputFormatter::escape($advisory->affectedVersions->getPrettyString());
                $error[] = "Reported at: " . $advisory->reportedAt->format(\DATE_ATOM);
                if ($advisory instanceof \Composer\Advisory\IgnoredSecurityAdvisory) {
                    $error[] = "Ignore reason: " . ($advisory->ignoreReason ?? 'None specified');
                }
                $firstAdvisory = \false;
            }
        }
        $io->writeError($error);
    }
    /**
     * @param array<CompletePackageInterface> $packages
     * @param self::FORMAT_PLAIN|self::FORMAT_TABLE $format
     */
    private function outputAbandonedPackages(IOInterface $io, array $packages, string $format): void
    {
        $io->writeError(sprintf('<error>Found %d abandoned package%s:</error>', count($packages), count($packages) > 1 ? 's' : ''));
        if ($format === self::FORMAT_PLAIN) {
            foreach ($packages as $pkg) {
                $replacement = $pkg->getReplacementPackage() !== null ? 'Use ' . $pkg->getReplacementPackage() . ' instead' : 'No replacement was suggested';
                $io->writeError(sprintf('%s is abandoned. %s.', $this->getPackageNameWithLink($pkg), $replacement));
            }
            return;
        }
        if (!$io instanceof ConsoleIO) {
            throw new InvalidArgumentException('Cannot use table format with ' . get_class($io));
        }
        $table = $io->getTable()->setHeaders(['Abandoned Package', 'Suggested Replacement'])->setColumnWidth(1, 80)->setColumnMaxWidth(1, 80);
        foreach ($packages as $pkg) {
            $replacement = $pkg->getReplacementPackage() !== null ? $pkg->getReplacementPackage() : 'none';
            $table->addRow(ConsoleIO::sanitize([$this->getPackageNameWithLink($pkg), $replacement]));
        }
        $table->render();
    }
    private function getPackageNameWithLink(PackageInterface $package): string
    {
        $packageUrl = PackageInfo::getViewSourceOrHomepageUrl($package);
        return $packageUrl !== null ? '<href=' . OutputFormatter::escape($packageUrl) . '>' . $package->getPrettyName() . '</>' : $package->getPrettyName();
    }
    private function getSeverity(\Composer\Advisory\SecurityAdvisory $advisory): string
    {
        if ($advisory->severity === null) {
            return '';
        }
        return $advisory->severity;
    }
    private function getAdvisoryId(\Composer\Advisory\SecurityAdvisory $advisory): string
    {
        if (str_starts_with($advisory->advisoryId, 'PKSA-')) {
            return '<href=https://packagist.org/security-advisories/' . $advisory->advisoryId . '>' . $advisory->advisoryId . '</>';
        }
        return $advisory->advisoryId;
    }
    private function getCVE(\Composer\Advisory\SecurityAdvisory $advisory): string
    {
        if ($advisory->cve === null) {
            return 'NO CVE';
        }
        return '<href=https://cve.mitre.org/cgi-bin/cvename.cgi?name=' . $advisory->cve . '>' . $advisory->cve . '</>';
    }
    private function getURL(\Composer\Advisory\SecurityAdvisory $advisory): string
    {
        if ($advisory->link === null) {
            return '';
        }
        return '<href=' . OutputFormatter::escape($advisory->link) . '>' . OutputFormatter::escape($advisory->link) . '</>';
    }
    /**
     * @return int-mask<self::STATUS_*>
     */
    private function calculateBitmask(bool $hasVulnerablePackages, bool $hasAbandonedPackages): int
    {
        $bitmask = self::STATUS_OK;
        if ($hasVulnerablePackages) {
            $bitmask |= self::STATUS_VULNERABLE;
        }
        if ($hasAbandonedPackages) {
            $bitmask |= self::STATUS_ABANDONED;
        }
        return $bitmask;
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer\Advisory;

use Composer\Semver\Constraint\ConstraintInterface;
use DateTimeImmutable;
class IgnoredSecurityAdvisory extends \Composer\Advisory\SecurityAdvisory
{
    /**
     * @var string|null
     * @readonly
     */
    public $ignoreReason;
    /**
     * @param non-empty-array<array{name: string, remoteId: string}> $sources
     */
    public function __construct(string $packageName, string $advisoryId, ConstraintInterface $affectedVersions, string $title, array $sources, DateTimeImmutable $reportedAt, ?string $cve = null, ?string $link = null, ?string $ignoreReason = null, ?string $severity = null)
    {
        parent::__construct($packageName, $advisoryId, $affectedVersions, $title, $sources, $reportedAt, $cve, $link, $severity);
        $this->ignoreReason = $ignoreReason;
    }
    /**
     * @return mixed
     */
    #[\ReturnTypeWillChange]
    public function jsonSerialize()
    {
        $data = parent::jsonSerialize();
        if ($this->ignoreReason === null) {
            unset($data['ignoreReason']);
        }
        return $data;
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer\Exception;

/**
 * @author Jordi Boggiano <j.boggiano@seld.be>
 */
class IrrecoverableDownloadException extends \RuntimeException
{
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer\Exception;

/**
 * Specific exception for Composer\Util\HttpDownloader creation.
 *
 * @author Jordi Boggiano <j.boggiano@seld.be>
 */
class NoSslException extends \RuntimeException
{
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer;

use Composer\Json\JsonFile;
use Composer\CaBundle\CaBundle;
use Composer\Pcre\Preg;
use Composer\Util\Git;
use Composer\Util\ProcessExecutor;
use _ContaoManager\Symfony\Component\Finder\Finder;
use _ContaoManager\Seld\PharUtils\Timestamps;
use _ContaoManager\Seld\PharUtils\Linter;
/**
 * The Compiler class compiles composer into a phar
 *
 * @author Fabien Potencier <fabien@symfony.com>
 * @author Jordi Boggiano <j.boggiano@seld.be>
 */
class Compiler
{
    /** @var string */
    private $version;
    /** @var string */
    private $branchAliasVersion = '';
    /** @var \DateTime */
    private $versionDate;
    /**
     * Compiles composer into a single phar file
     *
     * @param string $pharFile The full path to the file to create
     *
     * @throws \RuntimeException
     */
    public function compile(string $pharFile = 'composer.phar'): void
    {
        if (file_exists($pharFile)) {
            unlink($pharFile);
        }
        $process = new ProcessExecutor();
        $command = Git::buildRevListCommand($process, ['-n1', '--format=%H', 'HEAD']);
        if (0 !== $process->execute($command, $output, dirname(__DIR__, 2))) {
            throw new \RuntimeException('Can\'t run git rev-list. You must ensure to run compile from composer git repository clone and that git binary is available.');
        }
        $this->version = trim(Git::parseRevListOutput($output, $process));
        $command = Git::buildRevListCommand($process, ['-n1', '--format=%ci', 'HEAD']);
        if (0 !== $process->execute($command, $output, dirname(__DIR__, 2))) {
            throw new \RuntimeException('Can\'t run git rev-list. You must ensure to run compile from composer git repository clone and that git binary is available.');
        }
        $this->versionDate = new \DateTime(trim(Git::parseRevListOutput($output, $process)));
        $this->versionDate->setTimezone(new \DateTimeZone('UTC'));
        if (0 === $process->execute(['git', 'describe', '--tags', '--exact-match', 'HEAD'], $output, dirname(__DIR__, 2))) {
            $this->version = trim($output);
        } else {
            // get branch-alias defined in composer.json for dev-main (if any)
            $localConfig = __DIR__ . '/../../composer.json';
            $file = new JsonFile($localConfig);
            $localConfig = $file->read();
            if (isset($localConfig['extra']['branch-alias']['dev-main'])) {
                $this->branchAliasVersion = $localConfig['extra']['branch-alias']['dev-main'];
            }
        }
        if ('' === $this->version) {
            throw new \UnexpectedValueException('Version detection failed');
        }
        $phar = new \Phar($pharFile, 0, 'composer.phar');
        $phar->setSignatureAlgorithm(\Phar::SHA512);
        $phar->startBuffering();
        $finderSort = static function ($a, $b): int {
            return strcmp(strtr($a->getRealPath(), '\\', '/'), strtr($b->getRealPath(), '\\', '/'));
        };
        // Add Composer sources
        $finder = new Finder();
        $finder->files()->ignoreVCS(\true)->name('*.php')->notName('Compiler.php')->notName('ClassLoader.php')->notName('InstalledVersions.php')->in(__DIR__ . '/..')->sort($finderSort);
        foreach ($finder as $file) {
            $this->addFile($phar, $file);
        }
        // Add runtime utilities separately to make sure they retains the docblocks as these will get copied into projects
        $this->addFile($phar, new \SplFileInfo(__DIR__ . '/Autoload/ClassLoader.php'), \false);
        $this->addFile($phar, new \SplFileInfo(__DIR__ . '/InstalledVersions.php'), \false);
        // Add Composer resources
        $finder = new Finder();
        $finder->files()->in(__DIR__ . '/../../res')->sort($finderSort);
        foreach ($finder as $file) {
            $this->addFile($phar, $file, \false);
        }
        // Add vendor files
        $finder = new Finder();
        $finder->files()->ignoreVCS(\true)->notPath('/\/(composer\.(?:json|lock)|[A-Z]+\.md(?:own)?|\.gitignore|appveyor.yml|phpunit\.xml\.dist|phpstan\.neon\.dist|phpstan-config\.neon|phpstan-baseline\.neon|UPGRADE.*\.(?:md|txt))$/')->notPath('/bin\/(jsonlint|validate-json|simple-phpunit|phpstan|phpstan\.phar)(\.bat)?$/')->notPath('justinrainbow/json-schema/demo/')->notPath('justinrainbow/json-schema/dist/')->notPath('justinrainbow/json-schema/bin/')->notPath('composer/pcre/extension.neon')->notPath('composer/LICENSE')->exclude('Tests')->exclude('tests')->exclude('docs')->in(__DIR__ . '/../../vendor/')->sort($finderSort);
        $extraFiles = [];
        foreach ([__DIR__ . '/../../vendor/composer/installed.json', __DIR__ . '/../../vendor/composer/spdx-licenses/res/spdx-exceptions.json', __DIR__ . '/../../vendor/composer/spdx-licenses/res/spdx-licenses.json', CaBundle::getBundledCaBundlePath(), __DIR__ . '/../../vendor/symfony/console/Resources/bin/hiddeninput.exe', __DIR__ . '/../../vendor/symfony/console/Resources/completion.bash'] as $file) {
            $extraFiles[$file] = realpath($file);
            if (!file_exists($file)) {
                throw new \RuntimeException('Extra file listed is missing from the filesystem: ' . $file);
            }
        }
        $unexpectedFiles = [];
        foreach ($finder as $file) {
            if (\false !== $index = array_search($file->getRealPath(), $extraFiles, \true)) {
                unset($extraFiles[$index]);
            } elseif (!Preg::isMatch('{(^LICENSE(?:\.txt)?$|\.php$)}', $file->getFilename())) {
                $unexpectedFiles[] = (string) $file;
            }
            if (Preg::isMatch('{\.php[\d.]*$}', $file->getFilename())) {
                $this->addFile($phar, $file);
            } else {
                $this->addFile($phar, $file, \false);
            }
        }
        if (count($extraFiles) > 0) {
            throw new \RuntimeException('These files were expected but not added to the phar, they might be excluded or gone from the source package:' . \PHP_EOL . var_export($extraFiles, \true));
        }
        if (count($unexpectedFiles) > 0) {
            throw new \RuntimeException('These files were unexpectedly added to the phar, make sure they are excluded or listed in $extraFiles:' . \PHP_EOL . var_export($unexpectedFiles, \true));
        }
        // Add bin/composer
        $this->addComposerBin($phar);
        // Stubs
        $phar->setStub($this->getStub());
        $phar->stopBuffering();
        // disabled for interoperability with systems without gzip ext
        // $phar->compressFiles(\Phar::GZ);
        $this->addFile($phar, new \SplFileInfo(__DIR__ . '/../../LICENSE'), \false);
        unset($phar);
        // re-sign the phar with reproducible timestamp / signature
        $util = new Timestamps($pharFile);
        $util->updateTimestamps($this->versionDate);
        $util->save($pharFile, \Phar::SHA512);
        Linter::lint($pharFile, ['vendor/symfony/console/Attribute/AsCommand.php', 'vendor/symfony/polyfill-intl-grapheme/bootstrap80.php', 'vendor/symfony/polyfill-intl-normalizer/bootstrap80.php', 'vendor/symfony/polyfill-mbstring/bootstrap80.php', 'vendor/symfony/polyfill-php73/Resources/stubs/JsonException.php', 'vendor/symfony/service-contracts/Attribute/SubscribedService.php', 'vendor/symfony/polyfill-php84/Resources/stubs/Deprecated.php', 'vendor/symfony/polyfill-php84/Resources/Deprecated.php', 'vendor/symfony/polyfill-php84/Resources/RoundingMode.php', 'vendor/symfony/polyfill-php84/bootstrap82.php']);
    }
    private function getRelativeFilePath(\SplFileInfo $file): string
    {
        $realPath = $file->getRealPath();
        $pathPrefix = dirname(__DIR__, 2) . \DIRECTORY_SEPARATOR;
        $pos = strpos($realPath, $pathPrefix);
        $relativePath = $pos !== \false ? substr_replace($realPath, '', $pos, strlen($pathPrefix)) : $realPath;
        return strtr($relativePath, '\\', '/');
    }
    private function addFile(\Phar $phar, \SplFileInfo $file, bool $strip = \true): void
    {
        $path = $this->getRelativeFilePath($file);
        $content = file_get_contents((string) $file);
        if ($strip) {
            $content = $this->stripWhitespace($content);
        } elseif ('LICENSE' === $file->getFilename()) {
            $content = "\n" . $content . "\n";
        }
        if ($path === 'src/Composer/Composer.php') {
            $content = strtr($content, ['@package_version@' => $this->version, '@package_branch_alias_version@' => $this->branchAliasVersion, '@release_date@' => $this->versionDate->format('Y-m-d H:i:s')]);
            $content = Preg::replace('{SOURCE_VERSION = \'[^\']+\';}', 'SOURCE_VERSION = \'\';', $content);
        }
        $phar->addFromString($path, $content);
    }
    private function addComposerBin(\Phar $phar): void
    {
        $content = file_get_contents(__DIR__ . '/../../bin/composer');
        $content = Preg::replace('{^#!/usr/bin/env php\s*}', '', $content);
        $phar->addFromString('bin/composer', $content);
    }
    /**
     * Removes whitespace from a PHP source string while preserving line numbers.
     *
     * @param  string $source A PHP string
     * @return string The PHP string with the whitespace removed
     */
    private function stripWhitespace(string $source): string
    {
        if (!function_exists('token_get_all')) {
            return $source;
        }
        $output = '';
        foreach (token_get_all($source) as $token) {
            if (is_string($token)) {
                $output .= $token;
            } elseif (in_array($token[0], [\T_COMMENT, \T_DOC_COMMENT])) {
                $output .= str_repeat("\n", substr_count($token[1], "\n"));
            } elseif (\T_WHITESPACE === $token[0]) {
                // reduce wide spaces
                $whitespace = Preg::replace('{[ \t]+}', ' ', $token[1]);
                // normalize newlines to \n
                $whitespace = Preg::replace('{(?:\r\n|\r|\n)}', "\n", $whitespace);
                // trim leading spaces
                $whitespace = Preg::replace('{\n +}', "\n", $whitespace);
                $output .= $whitespace;
            } else {
                $output .= $token[1];
            }
        }
        return $output;
    }
    private function getStub(): string
    {
        $stub = <<<'EOF'
#!/usr/bin/env php
<?php
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view
 * the license that is located at the bottom of this file.
 */

// Avoid APC causing random fatal errors per https://github.com/composer/composer/issues/264
if (extension_loaded('apc') && filter_var(ini_get('apc.enable_cli'), FILTER_VALIDATE_BOOLEAN) && filter_var(ini_get('apc.cache_by_default'), FILTER_VALIDATE_BOOLEAN)) {
    if (version_compare(phpversion('apc'), '3.0.12', '>=')) {
        ini_set('apc.cache_by_default', 0);
    } else {
        fwrite(STDERR, 'Warning: APC <= 3.0.12 may cause fatal errors when running composer commands.'.PHP_EOL);
        fwrite(STDERR, 'Update APC, or set apc.enable_cli or apc.cache_by_default to 0 in your php.ini.'.PHP_EOL);
    }
}

if (!class_exists('Phar')) {
    echo 'PHP\'s phar extension is missing. Composer requires it to run. Enable the extension or recompile php without --disable-phar then try again.' . PHP_EOL;
    exit(1);
}

Phar::mapPhar('composer.phar');

EOF;
        // add warning once the phar is older than 60 days
        if (Preg::isMatch('{^[a-f0-9]+$}', $this->version)) {
            $warningTime = (int) $this->versionDate->format('U') + 60 * 86400;
            $stub .= "define('COMPOSER_DEV_WARNING_TIME', {$warningTime});\n";
        }
        return $stub . <<<'EOF'
require 'phar://composer.phar/bin/composer';

__HALT_COMPILER();
EOF;
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer\Package;

use Composer\Package\Version\VersionParser;
use Composer\Pcre\Preg;
use Composer\Util\ComposerMirror;
/**
 * Core package definitions that are needed to resolve dependencies and install packages
 *
 * @author Nils Adermann <naderman@naderman.de>
 *
 * @phpstan-import-type AutoloadRules from PackageInterface
 * @phpstan-import-type DevAutoloadRules from PackageInterface
 * @phpstan-import-type PhpExtConfig from PackageInterface
 */
class Package extends \Composer\Package\BasePackage
{
    /** @var string */
    protected $type;
    /** @var ?string */
    protected $targetDir;
    /** @var 'source'|'dist'|null */
    protected $installationSource;
    /** @var ?string */
    protected $sourceType;
    /** @var ?string */
    protected $sourceUrl;
    /** @var ?string */
    protected $sourceReference;
    /** @var ?list<array{url: non-empty-string, preferred: bool}> */
    protected $sourceMirrors;
    /** @var ?non-empty-string */
    protected $distType;
    /** @var ?non-empty-string */
    protected $distUrl;
    /** @var ?string */
    protected $distReference;
    /** @var ?string */
    protected $distSha1Checksum;
    /** @var ?list<array{url: non-empty-string, preferred: bool}> */
    protected $distMirrors;
    /** @var string */
    protected $version;
    /** @var string */
    protected $prettyVersion;
    /** @var ?\DateTimeInterface */
    protected $releaseDate;
    /** @var mixed[] */
    protected $extra = [];
    /** @var string[] */
    protected $binaries = [];
    /** @var bool */
    protected $dev;
    /**
     * @var string
     * @phpstan-var 'stable'|'RC'|'beta'|'alpha'|'dev'
     */
    protected $stability;
    /** @var ?string */
    protected $notificationUrl;
    /** @var array<string, Link> */
    protected $requires = [];
    /** @var array<string, Link> */
    protected $conflicts = [];
    /** @var array<string, Link> */
    protected $provides = [];
    /** @var array<string, Link> */
    protected $replaces = [];
    /** @var array<string, Link> */
    protected $devRequires = [];
    /** @var array<string, string> */
    protected $suggests = [];
    /**
     * @var array
     * @phpstan-var AutoloadRules
     */
    protected $autoload = [];
    /**
     * @var array
     * @phpstan-var DevAutoloadRules
     */
    protected $devAutoload = [];
    /** @var string[] */
    protected $includePaths = [];
    /** @var bool */
    protected $isDefaultBranch = \false;
    /** @var mixed[] */
    protected $transportOptions = [];
    /**
     * @var array|null
     * @phpstan-var PhpExtConfig|null
     */
    protected $phpExt = null;
    /**
     * Creates a new in memory package.
     *
     * @param string $name          The package's name
     * @param string $version       The package's version
     * @param string $prettyVersion The package's non-normalized version
     */
    public function __construct(string $name, string $version, string $prettyVersion)
    {
        parent::__construct($name);
        $this->version = $version;
        $this->prettyVersion = $prettyVersion;
        $this->stability = VersionParser::parseStability($version);
        $this->dev = $this->stability === 'dev';
    }
    /**
     * @inheritDoc
     */
    public function isDev(): bool
    {
        return $this->dev;
    }
    public function setType(string $type): void
    {
        $this->type = $type;
    }
    /**
     * @inheritDoc
     */
    public function getType(): string
    {
        return $this->type ?: 'library';
    }
    /**
     * @inheritDoc
     */
    public function getStability(): string
    {
        return $this->stability;
    }
    public function setTargetDir(?string $targetDir): void
    {
        $this->targetDir = $targetDir;
    }
    /**
     * @inheritDoc
     */
    public function getTargetDir(): ?string
    {
        if (null === $this->targetDir) {
            return null;
        }
        return ltrim(Preg::replace('{ (?:^|[\\\\/]+) \.\.? (?:[\\\\/]+|$) (?:\.\.? (?:[\\\\/]+|$) )*}x', '/', $this->targetDir), '/');
    }
    /**
     * @param mixed[] $extra
     */
    public function setExtra(array $extra): void
    {
        $this->extra = $extra;
    }
    /**
     * @inheritDoc
     */
    public function getExtra(): array
    {
        return $this->extra;
    }
    /**
     * @param string[] $binaries
     */
    public function setBinaries(array $binaries): void
    {
        $this->binaries = $binaries;
    }
    /**
     * @inheritDoc
     */
    public function getBinaries(): array
    {
        return $this->binaries;
    }
    /**
     * @inheritDoc
     */
    public function setInstallationSource(?string $type): void
    {
        $this->installationSource = $type;
    }
    /**
     * @inheritDoc
     */
    public function getInstallationSource(): ?string
    {
        return $this->installationSource;
    }
    public function setSourceType(?string $type): void
    {
        $this->sourceType = $type;
    }
    /**
     * @inheritDoc
     */
    public function getSourceType(): ?string
    {
        return $this->sourceType;
    }
    public function setSourceUrl(?string $url): void
    {
        $this->sourceUrl = $url;
    }
    /**
     * @inheritDoc
     */
    public function getSourceUrl(): ?string
    {
        return $this->sourceUrl;
    }
    public function setSourceReference(?string $reference): void
    {
        $this->sourceReference = $reference;
    }
    /**
     * @inheritDoc
     */
    public function getSourceReference(): ?string
    {
        return $this->sourceReference;
    }
    public function setSourceMirrors(?array $mirrors): void
    {
        $this->sourceMirrors = $mirrors;
    }
    /**
     * @inheritDoc
     */
    public function getSourceMirrors(): ?array
    {
        return $this->sourceMirrors;
    }
    /**
     * @inheritDoc
     */
    public function getSourceUrls(): array
    {
        return $this->getUrls($this->sourceUrl, $this->sourceMirrors, $this->sourceReference, $this->sourceType, 'source');
    }
    public function setDistType(?string $type): void
    {
        $this->distType = $type === '' ? null : $type;
    }
    /**
     * @inheritDoc
     */
    public function getDistType(): ?string
    {
        return $this->distType;
    }
    public function setDistUrl(?string $url): void
    {
        $this->distUrl = $url === '' ? null : $url;
    }
    /**
     * @inheritDoc
     */
    public function getDistUrl(): ?string
    {
        return $this->distUrl;
    }
    public function setDistReference(?string $reference): void
    {
        $this->distReference = $reference;
    }
    /**
     * @inheritDoc
     */
    public function getDistReference(): ?string
    {
        return $this->distReference;
    }
    public function setDistSha1Checksum(?string $sha1checksum): void
    {
        $this->distSha1Checksum = $sha1checksum;
    }
    /**
     * @inheritDoc
     */
    public function getDistSha1Checksum(): ?string
    {
        return $this->distSha1Checksum;
    }
    public function setDistMirrors(?array $mirrors): void
    {
        $this->distMirrors = $mirrors;
    }
    /**
     * @inheritDoc
     */
    public function getDistMirrors(): ?array
    {
        return $this->distMirrors;
    }
    /**
     * @inheritDoc
     */
    public function getDistUrls(): array
    {
        return $this->getUrls($this->distUrl, $this->distMirrors, $this->distReference, $this->distType, 'dist');
    }
    /**
     * @inheritDoc
     */
    public function getTransportOptions(): array
    {
        return $this->transportOptions;
    }
    /**
     * @inheritDoc
     */
    public function setTransportOptions(array $options): void
    {
        $this->transportOptions = $options;
    }
    /**
     * @inheritDoc
     */
    public function getVersion(): string
    {
        return $this->version;
    }
    /**
     * @inheritDoc
     */
    public function getPrettyVersion(): string
    {
        return $this->prettyVersion;
    }
    public function setReleaseDate(?\DateTimeInterface $releaseDate): void
    {
        $this->releaseDate = $releaseDate;
    }
    /**
     * @inheritDoc
     */
    public function getReleaseDate(): ?\DateTimeInterface
    {
        return $this->releaseDate;
    }
    /**
     * Set the required packages
     *
     * @param array<string, Link> $requires A set of package links
     */
    public function setRequires(array $requires): void
    {
        if (isset($requires[0])) {
            // @phpstan-ignore-line
            $requires = $this->convertLinksToMap($requires, 'setRequires');
        }
        $this->requires = $requires;
    }
    /**
     * @inheritDoc
     */
    public function getRequires(): array
    {
        return $this->requires;
    }
    /**
     * Set the conflicting packages
     *
     * @param array<string, Link> $conflicts A set of package links
     */
    public function setConflicts(array $conflicts): void
    {
        if (isset($conflicts[0])) {
            // @phpstan-ignore-line
            $conflicts = $this->convertLinksToMap($conflicts, 'setConflicts');
        }
        $this->conflicts = $conflicts;
    }
    /**
     * @inheritDoc
     * @return array<string, Link>
     */
    public function getConflicts(): array
    {
        return $this->conflicts;
    }
    /**
     * Set the provided virtual packages
     *
     * @param array<string, Link> $provides A set of package links
     */
    public function setProvides(array $provides): void
    {
        if (isset($provides[0])) {
            // @phpstan-ignore-line
            $provides = $this->convertLinksToMap($provides, 'setProvides');
        }
        $this->provides = $provides;
    }
    /**
     * @inheritDoc
     * @return array<string, Link>
     */
    public function getProvides(): array
    {
        return $this->provides;
    }
    /**
     * Set the packages this one replaces
     *
     * @param array<string, Link> $replaces A set of package links
     */
    public function setReplaces(array $replaces): void
    {
        if (isset($replaces[0])) {
            // @phpstan-ignore-line
            $replaces = $this->convertLinksToMap($replaces, 'setReplaces');
        }
        $this->replaces = $replaces;
    }
    /**
     * @inheritDoc
     * @return array<string, Link>
     */
    public function getReplaces(): array
    {
        return $this->replaces;
    }
    /**
     * Set the recommended packages
     *
     * @param array<string, Link> $devRequires A set of package links
     */
    public function setDevRequires(array $devRequires): void
    {
        if (isset($devRequires[0])) {
            // @phpstan-ignore-line
            $devRequires = $this->convertLinksToMap($devRequires, 'setDevRequires');
        }
        $this->devRequires = $devRequires;
    }
    /**
     * @inheritDoc
     */
    public function getDevRequires(): array
    {
        return $this->devRequires;
    }
    /**
     * Set the suggested packages
     *
     * @param array<string, string> $suggests A set of package names/comments
     */
    public function setSuggests(array $suggests): void
    {
        $this->suggests = $suggests;
    }
    /**
     * @inheritDoc
     */
    public function getSuggests(): array
    {
        return $this->suggests;
    }
    /**
     * Set the autoload mapping
     *
     * @param array $autoload Mapping of autoloading rules
     *
     * @phpstan-param AutoloadRules $autoload
     */
    public function setAutoload(array $autoload): void
    {
        $this->autoload = $autoload;
    }
    /**
     * @inheritDoc
     */
    public function getAutoload(): array
    {
        return $this->autoload;
    }
    /**
     * Set the dev autoload mapping
     *
     * @param array $devAutoload Mapping of dev autoloading rules
     *
     * @phpstan-param DevAutoloadRules $devAutoload
     */
    public function setDevAutoload(array $devAutoload): void
    {
        $this->devAutoload = $devAutoload;
    }
    /**
     * @inheritDoc
     */
    public function getDevAutoload(): array
    {
        return $this->devAutoload;
    }
    /**
     * Sets the list of paths added to PHP's include path.
     *
     * @param string[] $includePaths List of directories.
     */
    public function setIncludePaths(array $includePaths): void
    {
        $this->includePaths = $includePaths;
    }
    /**
     * @inheritDoc
     */
    public function getIncludePaths(): array
    {
        return $this->includePaths;
    }
    /**
     * Sets the settings for php extension packages
     *
     *
     * @phpstan-param PhpExtConfig|null $phpExt
     */
    public function setPhpExt(?array $phpExt): void
    {
        $this->phpExt = $phpExt;
    }
    /**
     * @inheritDoc
     */
    public function getPhpExt(): ?array
    {
        return $this->phpExt;
    }
    /**
     * Sets the notification URL
     */
    public function setNotificationUrl(string $notificationUrl): void
    {
        $this->notificationUrl = $notificationUrl;
    }
    /**
     * @inheritDoc
     */
    public function getNotificationUrl(): ?string
    {
        return $this->notificationUrl;
    }
    public function setIsDefaultBranch(bool $defaultBranch): void
    {
        $this->isDefaultBranch = $defaultBranch;
    }
    /**
     * @inheritDoc
     */
    public function isDefaultBranch(): bool
    {
        return $this->isDefaultBranch;
    }
    /**
     * @inheritDoc
     */
    public function setSourceDistReferences(string $reference): void
    {
        $this->setSourceReference($reference);
        // only bitbucket, github and gitlab have auto generated dist URLs that easily allow replacing the reference in the dist URL
        // TODO generalize this a bit for self-managed/on-prem versions? Some kind of replace token in dist urls which allow this?
        if ($this->getDistUrl() !== null && Preg::isMatch('{^https?://(?:(?:www\.)?bitbucket\.org|(api\.)?github\.com|(?:www\.)?gitlab\.com)/}i', $this->getDistUrl())) {
            $this->setDistReference($reference);
            $this->setDistUrl(Preg::replace('{(?<=/|sha=)[a-f0-9]{40}(?=/|$)}i', $reference, $this->getDistUrl()));
        } elseif ($this->getDistReference()) {
            // update the dist reference if there was one, but if none was provided ignore it
            $this->setDistReference($reference);
        }
    }
    /**
     * Replaces current version and pretty version with passed values.
     * It also sets stability.
     *
     * @param string $version       The package's normalized version
     * @param string $prettyVersion The package's non-normalized version
     */
    public function replaceVersion(string $version, string $prettyVersion): void
    {
        $this->version = $version;
        $this->prettyVersion = $prettyVersion;
        $this->stability = VersionParser::parseStability($version);
        $this->dev = $this->stability === 'dev';
    }
    /**
     * @param mixed[]|null $mirrors
     *
     * @return list<non-empty-string>
     *
     * @phpstan-param list<array{url: non-empty-string, preferred: bool}>|null $mirrors
     */
    protected function getUrls(?string $url, ?array $mirrors, ?string $ref, ?string $type, string $urlType): array
    {
        if (!$url) {
            return [];
        }
        if ($urlType === 'dist' && \false !== strpos($url, '%')) {
            $url = ComposerMirror::processUrl($url, $this->name, $this->version, $ref, $type, $this->prettyVersion);
        }
        $urls = [$url];
        if ($mirrors) {
            foreach ($mirrors as $mirror) {
                if ($urlType === 'dist') {
                    $mirrorUrl = ComposerMirror::processUrl($mirror['url'], $this->name, $this->version, $ref, $type, $this->prettyVersion);
                } elseif ($urlType === 'source' && $type === 'git') {
                    $mirrorUrl = ComposerMirror::processGitUrl($mirror['url'], $this->name, $url, $type);
                } elseif ($urlType === 'source' && $type === 'hg') {
                    $mirrorUrl = ComposerMirror::processHgUrl($mirror['url'], $this->name, $url, $type);
                } else {
                    continue;
                }
                if (!\in_array($mirrorUrl, $urls)) {
                    $func = $mirror['preferred'] ? 'array_unshift' : 'array_push';
                    $func($urls, $mirrorUrl);
                }
            }
        }
        return $urls;
    }
    /**
     * @param  array<int, Link> $links
     * @return array<string, Link>
     */
    private function convertLinksToMap(array $links, string $source): array
    {
        trigger_error('Package::' . $source . ' must be called with a map of lowercased package name => Link object, got a indexed array, this is deprecated and you should fix your usage.');
        $newLinks = [];
        foreach ($links as $link) {
            $newLinks[$link->getTarget()] = $link;
        }
        return $newLinks;
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer\Package;

use Composer\Semver\Constraint\ConstraintInterface;
/**
 * Represents a link between two packages, represented by their names
 *
 * @author Nils Adermann <naderman@naderman.de>
 */
class Link
{
    public const TYPE_REQUIRE = 'requires';
    public const TYPE_DEV_REQUIRE = 'devRequires';
    public const TYPE_PROVIDE = 'provides';
    public const TYPE_CONFLICT = 'conflicts';
    public const TYPE_REPLACE = 'replaces';
    /**
     * Special type
     * @internal
     */
    public const TYPE_DOES_NOT_REQUIRE = 'does not require';
    private const TYPE_UNKNOWN = 'relates to';
    /**
     * Will be converted into a constant once the min PHP version allows this
     *
     * @internal
     * @var string[]
     * @phpstan-var array<self::TYPE_REQUIRE|self::TYPE_DEV_REQUIRE|self::TYPE_PROVIDE|self::TYPE_CONFLICT|self::TYPE_REPLACE>
     */
    public static $TYPES = [self::TYPE_REQUIRE, self::TYPE_DEV_REQUIRE, self::TYPE_PROVIDE, self::TYPE_CONFLICT, self::TYPE_REPLACE];
    /**
     * @var string
     */
    protected $source;
    /**
     * @var string
     */
    protected $target;
    /**
     * @var ConstraintInterface
     */
    protected $constraint;
    /**
     * @var string
     * @phpstan-var string $description
     */
    protected $description;
    /**
     * @var ?string
     */
    protected $prettyConstraint;
    /**
     * Creates a new package link.
     *
     * @param ConstraintInterface $constraint       Constraint applying to the target of this link
     * @param self::TYPE_*        $description      Used to create a descriptive string representation
     */
    public function __construct(string $source, string $target, ConstraintInterface $constraint, $description = self::TYPE_UNKNOWN, ?string $prettyConstraint = null)
    {
        $this->source = strtolower($source);
        $this->target = strtolower($target);
        $this->constraint = $constraint;
        $this->description = self::TYPE_DEV_REQUIRE === $description ? 'requires (for development)' : $description;
        $this->prettyConstraint = $prettyConstraint;
    }
    public function getDescription(): string
    {
        return $this->description;
    }
    public function getSource(): string
    {
        return $this->source;
    }
    public function getTarget(): string
    {
        return $this->target;
    }
    public function getConstraint(): ConstraintInterface
    {
        return $this->constraint;
    }
    /**
     * @throws \UnexpectedValueException If no pretty constraint was provided
     */
    public function getPrettyConstraint(): string
    {
        if (null === $this->prettyConstraint) {
            throw new \UnexpectedValueException(sprintf('Link %s has been misconfigured and had no prettyConstraint given.', $this));
        }
        return $this->prettyConstraint;
    }
    public function __toString(): string
    {
        return $this->source . ' ' . $this->description . ' ' . $this->target . ' (' . $this->constraint . ')';
    }
    public function getPrettyString(\Composer\Package\PackageInterface $sourcePackage): string
    {
        return $sourcePackage->getPrettyString() . ' ' . $this->description . ' ' . $this->target . ' ' . $this->constraint->getPrettyString();
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer\Package;

/**
 * Defines package metadata that is not necessarily needed for solving and installing packages
 *
 * PackageInterface & derivatives are considered internal, you may use them in type hints but extending/implementing them is not recommended and not supported. Things may change without notice.
 *
 * @author Nils Adermann <naderman@naderman.de>
 */
interface CompletePackageInterface extends \Composer\Package\PackageInterface
{
    /**
     * Returns the scripts of this package
     *
     * @return array<string, string[]> Map of script name to array of handlers
     */
    public function getScripts(): array;
    /**
     * @param  array<string, string[]> $scripts
     */
    public function setScripts(array $scripts): void;
    /**
     * Returns an array of repositories
     *
     * @return mixed[] Repositories
     */
    public function getRepositories(): array;
    /**
     * Set the repositories
     *
     * @param  mixed[] $repositories
     */
    public function setRepositories(array $repositories): void;
    /**
     * Returns the package license, e.g. MIT, BSD, GPL
     *
     * @return string[] The package licenses
     */
    public function getLicense(): array;
    /**
     * Set the license
     *
     * @param  string[] $license
     */
    public function setLicense(array $license): void;
    /**
     * Returns an array of keywords relating to the package
     *
     * @return string[]
     */
    public function getKeywords(): array;
    /**
     * Set the keywords
     *
     * @param  string[] $keywords
     */
    public function setKeywords(array $keywords): void;
    /**
     * Returns the package description
     */
    public function getDescription(): ?string;
    /**
     * Set the description
     */
    public function setDescription(string $description): void;
    /**
     * Returns the package homepage
     */
    public function getHomepage(): ?string;
    /**
     * Set the homepage
     */
    public function setHomepage(string $homepage): void;
    /**
     * Returns an array of authors of the package
     *
     * Each item can contain name/homepage/email keys
     *
     * @return array<array{name?: string, homepage?: string, email?: string, role?: string}>
     */
    public function getAuthors(): array;
    /**
     * Set the authors
     *
     * @param  array<array{name?: string, homepage?: string, email?: string, role?: string}> $authors
     */
    public function setAuthors(array $authors): void;
    /**
     * Returns the support information
     *
     * @return array{issues?: string, forum?: string, wiki?: string, source?: string, email?: string, irc?: string, docs?: string, rss?: string, chat?: string, security?: string}
     */
    public function getSupport(): array;
    /**
     * Set the support information
     *
     * @param  array{issues?: string, forum?: string, wiki?: string, source?: string, email?: string, irc?: string, docs?: string, rss?: string, chat?: string, security?: string} $support
     */
    public function setSupport(array $support): void;
    /**
     * Returns an array of funding options for the package
     *
     * Each item will contain type and url keys
     *
     * @return array<array{type?: string, url?: string}>
     */
    public function getFunding(): array;
    /**
     * Set the funding
     *
     * @param  array<array{type?: string, url?: string}> $funding
     */
    public function setFunding(array $funding): void;
    /**
     * Returns if the package is abandoned or not
     */
    public function isAbandoned(): bool;
    /**
     * If the package is abandoned and has a suggested replacement, this method returns it
     */
    public function getReplacementPackage(): ?string;
    /**
     * @param  bool|string $abandoned
     */
    public function setAbandoned($abandoned): void;
    /**
     * Returns default base filename for archive
     */
    public function getArchiveName(): ?string;
    /**
     * Sets default base filename for archive
     */
    public function setArchiveName(string $name): void;
    /**
     * Returns a list of patterns to exclude from package archives
     *
     * @return string[]
     */
    public function getArchiveExcludes(): array;
    /**
     * Sets a list of patterns to be excluded from archives
     *
     * @param  string[] $excludes
     */
    public function setArchiveExcludes(array $excludes): void;
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer\Package\Archiver;

use Composer\Downloader\DownloadManager;
use Composer\Package\RootPackageInterface;
use Composer\Pcre\Preg;
use Composer\Util\Filesystem;
use Composer\Util\Loop;
use Composer\Util\SyncHelper;
use Composer\Json\JsonFile;
use Composer\Package\CompletePackageInterface;
/**
 * @author Matthieu Moquet <matthieu@moquet.net>
 * @author Till Klampaeckel <till@php.net>
 */
class ArchiveManager
{
    /** @var DownloadManager */
    protected $downloadManager;
    /** @var Loop */
    protected $loop;
    /**
     * @var ArchiverInterface[]
     */
    protected $archivers = [];
    /**
     * @var bool
     */
    protected $overwriteFiles = \true;
    /**
     * @param DownloadManager $downloadManager A manager used to download package sources
     */
    public function __construct(DownloadManager $downloadManager, Loop $loop)
    {
        $this->downloadManager = $downloadManager;
        $this->loop = $loop;
    }
    public function addArchiver(\Composer\Package\Archiver\ArchiverInterface $archiver): void
    {
        $this->archivers[] = $archiver;
    }
    /**
     * Set whether existing archives should be overwritten
     *
     * @param bool $overwriteFiles New setting
     *
     * @return $this
     */
    public function setOverwriteFiles(bool $overwriteFiles): self
    {
        $this->overwriteFiles = $overwriteFiles;
        return $this;
    }
    /**
     * @return array<string, string>
     * @internal
     */
    public function getPackageFilenameParts(CompletePackageInterface $package): array
    {
        $baseName = $package->getArchiveName();
        if (null === $baseName) {
            $baseName = Preg::replace('#[^a-z0-9-_]#i', '-', $package->getName());
        }
        $parts = ['base' => $baseName];
        $distReference = $package->getDistReference();
        if (null !== $distReference && Preg::isMatch('{^[a-f0-9]{40}$}', $distReference)) {
            $parts['dist_reference'] = $distReference;
            $parts['dist_type'] = $package->getDistType();
        } else {
            $parts['version'] = $package->getPrettyVersion();
            $parts['dist_reference'] = $distReference;
        }
        $sourceReference = $package->getSourceReference();
        if (null !== $sourceReference) {
            $parts['source_reference'] = substr(hash('sha1', $sourceReference), 0, 6);
        }
        $parts = array_filter($parts, static function (?string $part) {
            return $part !== null;
        });
        foreach ($parts as $key => $part) {
            $parts[$key] = str_replace('/', '-', $part);
        }
        return $parts;
    }
    /**
     * @param array<string, string> $parts
     *
     * @internal
     */
    public function getPackageFilenameFromParts(array $parts): string
    {
        return implode('-', $parts);
    }
    /**
     * Generate a distinct filename for a particular version of a package.
     *
     * @param CompletePackageInterface $package The package to get a name for
     *
     * @return string A filename without an extension
     */
    public function getPackageFilename(CompletePackageInterface $package): string
    {
        return $this->getPackageFilenameFromParts($this->getPackageFilenameParts($package));
    }
    /**
     * Create an archive of the specified package.
     *
     * @param  CompletePackageInterface  $package       The package to archive
     * @param  string                    $format        The format of the archive (zip, tar, ...)
     * @param  string                    $targetDir     The directory where to build the archive
     * @param  string|null               $fileName      The relative file name to use for the archive, or null to generate
     *                                                  the package name. Note that the format will be appended to this name
     * @param  bool                      $ignoreFilters Ignore filters when looking for files in the package
     * @throws \InvalidArgumentException
     * @throws \RuntimeException
     * @return string                    The path of the created archive
     */
    public function archive(CompletePackageInterface $package, string $format, string $targetDir, ?string $fileName = null, bool $ignoreFilters = \false): string
    {
        if (empty($format)) {
            throw new \InvalidArgumentException('Format must be specified');
        }
        // Search for the most appropriate archiver
        $usableArchiver = null;
        foreach ($this->archivers as $archiver) {
            if ($archiver->supports($format, $package->getSourceType())) {
                $usableArchiver = $archiver;
                break;
            }
        }
        // Checks the format/source type are supported before downloading the package
        if (null === $usableArchiver) {
            throw new \RuntimeException(sprintf('No archiver found to support %s format', $format));
        }
        $filesystem = new Filesystem();
        if ($package instanceof RootPackageInterface) {
            $sourcePath = realpath('.');
        } else {
            // Directory used to download the sources
            $sourcePath = sys_get_temp_dir() . '/composer_archive' . bin2hex(random_bytes(5));
            $filesystem->ensureDirectoryExists($sourcePath);
            try {
                // Download sources
                $promise = $this->downloadManager->download($package, $sourcePath);
                SyncHelper::await($this->loop, $promise);
                $promise = $this->downloadManager->install($package, $sourcePath);
                SyncHelper::await($this->loop, $promise);
            } catch (\Exception $e) {
                $filesystem->removeDirectory($sourcePath);
                throw $e;
            }
            // Check exclude from downloaded composer.json
            if (file_exists($composerJsonPath = $sourcePath . '/composer.json')) {
                $jsonFile = new JsonFile($composerJsonPath);
                $jsonData = $jsonFile->read();
                if (!empty($jsonData['archive']['name'])) {
                    $package->setArchiveName($jsonData['archive']['name']);
                }
                if (!empty($jsonData['archive']['exclude'])) {
                    $package->setArchiveExcludes($jsonData['archive']['exclude']);
                }
            }
        }
        $supportedFormats = $this->getSupportedFormats();
        $packageNameParts = null === $fileName ? $this->getPackageFilenameParts($package) : ['base' => $fileName];
        $packageName = $this->getPackageFilenameFromParts($packageNameParts);
        $excludePatterns = $this->buildExcludePatterns($packageNameParts, $supportedFormats);
        // Archive filename
        $filesystem->ensureDirectoryExists($targetDir);
        $target = realpath($targetDir) . '/' . $packageName . '.' . $format;
        $filesystem->ensureDirectoryExists(dirname($target));
        if (!$this->overwriteFiles && file_exists($target)) {
            return $target;
        }
        // Create the archive
        $tempTarget = sys_get_temp_dir() . '/composer_archive' . bin2hex(random_bytes(5)) . '.' . $format;
        $filesystem->ensureDirectoryExists(dirname($tempTarget));
        $archivePath = $usableArchiver->archive($sourcePath, $tempTarget, $format, array_merge($excludePatterns, $package->getArchiveExcludes()), $ignoreFilters);
        $filesystem->rename($archivePath, $target);
        // cleanup temporary download
        if (!$package instanceof RootPackageInterface) {
            $filesystem->removeDirectory($sourcePath);
        }
        $filesystem->remove($tempTarget);
        return $target;
    }
    /**
     * @param string[] $parts
     * @param string[] $formats
     *
     * @return string[]
     */
    private function buildExcludePatterns(array $parts, array $formats): array
    {
        $base = $parts['base'];
        if (count($parts) > 1) {
            $base .= '-*';
        }
        $patterns = [];
        foreach ($formats as $format) {
            $patterns[] = "{$base}.{$format}";
        }
        return $patterns;
    }
    /**
     * @return string[]
     */
    private function getSupportedFormats(): array
    {
        // The problem is that the \Composer\Package\Archiver\ArchiverInterface
        // doesn't provide method to get the supported formats.
        // Supported formats are also hard-coded into the description of the
        // --format option.
        // See \Composer\Command\ArchiveCommand::configure().
        $formats = [];
        foreach ($this->archivers as $archiver) {
            $items = [];
            switch (get_class($archiver)) {
                case \Composer\Package\Archiver\ZipArchiver::class:
                    $items = ['zip'];
                    break;
                case \Composer\Package\Archiver\PharArchiver::class:
                    $items = ['zip', 'tar', 'tar.gz', 'tar.bz2'];
                    break;
            }
            $formats = array_merge($formats, $items);
        }
        return array_unique($formats);
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer\Package\Archiver;

use Composer\Pcre\Preg;
use Composer\Util\Filesystem;
use FilesystemIterator;
use FilterIterator;
use Iterator;
use _ContaoManager\Symfony\Component\Finder\Finder;
use _ContaoManager\Symfony\Component\Finder\SplFileInfo;
/**
 * A Symfony Finder wrapper which locates files that should go into archives
 *
 * Handles .gitignore, .gitattributes and .hgignore files as well as composer's
 * own exclude rules from composer.json
 *
 * @author Nils Adermann <naderman@naderman.de>
 * @phpstan-extends FilterIterator<string, SplFileInfo, Iterator<string, SplFileInfo>>
 */
class ArchivableFilesFinder extends FilterIterator
{
    /**
     * @var Finder
     */
    protected $finder;
    /**
     * Initializes the internal Symfony Finder with appropriate filters
     *
     * @param string $sources Path to source files to be archived
     * @param string[] $excludes Composer's own exclude rules from composer.json
     * @param bool $ignoreFilters Ignore filters when looking for files
     */
    public function __construct(string $sources, array $excludes, bool $ignoreFilters = \false)
    {
        $fs = new Filesystem();
        $sourcesRealPath = realpath($sources);
        if ($sourcesRealPath === \false) {
            throw new \RuntimeException('Could not realpath() the source directory "' . $sources . '"');
        }
        $sources = $fs->normalizePath($sourcesRealPath);
        if ($ignoreFilters) {
            $filters = [];
        } else {
            $filters = [new \Composer\Package\Archiver\GitExcludeFilter($sources), new \Composer\Package\Archiver\ComposerExcludeFilter($sources, $excludes)];
        }
        $this->finder = new Finder();
        $filter = static function (\SplFileInfo $file) use ($sources, $filters, $fs): bool {
            $realpath = $file->getRealPath();
            if ($realpath === \false) {
                return \false;
            }
            if ($file->isLink() && strpos($realpath, $sources) !== 0) {
                return \false;
            }
            $relativePath = Preg::replace('#^' . preg_quote($sources, '#') . '#', '', $fs->normalizePath($realpath));
            $exclude = \false;
            foreach ($filters as $filter) {
                $exclude = $filter->filter($relativePath, $exclude);
            }
            return !$exclude;
        };
        $this->finder->in($sources)->filter($filter)->ignoreVCS(\true)->ignoreDotFiles(\false)->sortByName();
        parent::__construct($this->finder->getIterator());
    }
    public function accept(): bool
    {
        /** @var SplFileInfo $current */
        $current = $this->getInnerIterator()->current();
        if (!$current->isDir()) {
            return \true;
        }
        $iterator = new FilesystemIterator((string) $current, FilesystemIterator::SKIP_DOTS);
        return !$iterator->valid();
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer\Package\Archiver;

use PharData;
/**
 * @author Till Klampaeckel <till@php.net>
 * @author Nils Adermann <naderman@naderman.de>
 * @author Matthieu Moquet <matthieu@moquet.net>
 */
class PharArchiver implements \Composer\Package\Archiver\ArchiverInterface
{
    /** @var array<string, int> */
    protected static $formats = ['zip' => \Phar::ZIP, 'tar' => \Phar::TAR, 'tar.gz' => \Phar::TAR, 'tar.bz2' => \Phar::TAR];
    /** @var array<string, int> */
    protected static $compressFormats = ['tar.gz' => \Phar::GZ, 'tar.bz2' => \Phar::BZ2];
    /**
     * @inheritDoc
     */
    public function archive(string $sources, string $target, string $format, array $excludes = [], bool $ignoreFilters = \false): string
    {
        $sources = realpath($sources);
        // Phar would otherwise load the file which we don't want
        if (file_exists($target)) {
            unlink($target);
        }
        try {
            $filename = substr($target, 0, strrpos($target, $format) - 1);
            // Check if compress format
            if (isset(static::$compressFormats[$format])) {
                // Current compress format supported base on tar
                $target = $filename . '.tar';
            }
            $phar = new PharData($target, \FilesystemIterator::KEY_AS_PATHNAME | \FilesystemIterator::CURRENT_AS_FILEINFO, '', static::$formats[$format]);
            $files = new \Composer\Package\Archiver\ArchivableFilesFinder($sources, $excludes, $ignoreFilters);
            $filesOnly = new \Composer\Package\Archiver\ArchivableFilesFilter($files);
            $phar->buildFromIterator($filesOnly, $sources);
            $filesOnly->addEmptyDir($phar, $sources);
            if (!file_exists($target)) {
                $target = $filename . '.' . $format;
                unset($phar);
                if ($format === 'tar') {
                    // create an empty tar file (=10240 null bytes) if the tar file is empty and PharData thus did not write it to disk
                    file_put_contents($target, str_repeat("\x00", 10240));
                } elseif ($format === 'zip') {
                    // create minimal valid ZIP file (Empty Central Directory + End of Central Directory record)
                    $eocd = pack(
                        'VvvvvVVv',
                        0x6054b50,
                        // End of central directory signature
                        0,
                        // Number of this disk
                        0,
                        // Disk where central directory starts
                        0,
                        // Number of central directory records on this disk
                        0,
                        // Total number of central directory records
                        0,
                        // Size of central directory (bytes)
                        0,
                        // Offset of start of central directory
                        0
                    );
                    file_put_contents($target, $eocd);
                } elseif ($format === 'tar.gz' || $format === 'tar.bz2') {
                    if (!PharData::canCompress(static::$compressFormats[$format])) {
                        throw new \RuntimeException(sprintf('Can not compress to %s format', $format));
                    }
                    if ($format === 'tar.gz' && function_exists('gzcompress')) {
                        file_put_contents($target, gzcompress(str_repeat("\x00", 10240)));
                    } elseif ($format === 'tar.bz2' && function_exists('bzcompress')) {
                        file_put_contents($target, bzcompress(str_repeat("\x00", 10240)));
                    }
                }
                return $target;
            }
            if (isset(static::$compressFormats[$format])) {
                // Check can be compressed?
                if (!PharData::canCompress(static::$compressFormats[$format])) {
                    throw new \RuntimeException(sprintf('Can not compress to %s format', $format));
                }
                // Delete old tar
                unlink($target);
                // Compress the new tar
                $phar->compress(static::$compressFormats[$format]);
                // Make the correct filename
                $target = $filename . '.' . $format;
            }
            return $target;
        } catch (\UnexpectedValueException $e) {
            $message = sprintf("Could not create archive '%s' from '%s': %s", $target, $sources, $e->getMessage());
            throw new \RuntimeException($message, $e->getCode(), $e);
        }
    }
    /**
     * @inheritDoc
     */
    public function supports(string $format, ?string $sourceType): bool
    {
        return isset(static::$formats[$format]);
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer\Package\Archiver;

use Composer\Pcre\Preg;
use _ContaoManager\Symfony\Component\Finder;
/**
 * @author Nils Adermann <naderman@naderman.de>
 */
abstract class BaseExcludeFilter
{
    /**
     * @var string
     */
    protected $sourcePath;
    /**
     * @var array<array{0: non-empty-string, 1: bool, 2: bool}> array of [$pattern, $negate, $stripLeadingSlash] arrays
     */
    protected $excludePatterns;
    /**
     * @param string $sourcePath Directory containing sources to be filtered
     */
    public function __construct(string $sourcePath)
    {
        $this->sourcePath = $sourcePath;
        $this->excludePatterns = [];
    }
    /**
     * Checks the given path against all exclude patterns in this filter
     *
     * Negated patterns overwrite exclude decisions of previous filters.
     *
     * @param string $relativePath The file's path relative to the sourcePath
     * @param bool $exclude Whether a previous filter wants to exclude this file
     *
     * @return bool Whether the file should be excluded
     */
    public function filter(string $relativePath, bool $exclude): bool
    {
        foreach ($this->excludePatterns as $patternData) {
            [$pattern, $negate, $stripLeadingSlash] = $patternData;
            if ($stripLeadingSlash) {
                $path = substr($relativePath, 1);
            } else {
                $path = $relativePath;
            }
            try {
                if (Preg::isMatch($pattern, $path)) {
                    $exclude = !$negate;
                }
            } catch (\RuntimeException $e) {
                // suppressed
            }
        }
        return $exclude;
    }
    /**
     * Processes a file containing exclude rules of different formats per line
     *
     * @param string[] $lines A set of lines to be parsed
     * @param callable $lineParser The parser to be used on each line
     *
     * @return array<array{0: non-empty-string, 1: bool, 2: bool}> Exclude patterns to be used in filter()
     */
    protected function parseLines(array $lines, callable $lineParser): array
    {
        return array_filter(array_map(static function ($line) use ($lineParser) {
            $line = trim($line);
            if (!$line || 0 === strpos($line, '#')) {
                return null;
            }
            return $lineParser($line);
        }, $lines), static function ($pattern): bool {
            return $pattern !== null;
        });
    }
    /**
     * Generates a set of exclude patterns for filter() from gitignore rules
     *
     * @param string[] $rules A list of exclude rules in gitignore syntax
     *
     * @return array<int, array{0: non-empty-string, 1: bool, 2: bool}> Exclude patterns
     */
    protected function generatePatterns(array $rules): array
    {
        $patterns = [];
        foreach ($rules as $rule) {
            $patterns[] = $this->generatePattern($rule);
        }
        return $patterns;
    }
    /**
     * Generates an exclude pattern for filter() from a gitignore rule
     *
     * @param string $rule An exclude rule in gitignore syntax
     *
     * @return array{0: non-empty-string, 1: bool, 2: bool} An exclude pattern
     */
    protected function generatePattern(string $rule): array
    {
        $negate = \false;
        $pattern = '';
        if ($rule !== '' && $rule[0] === '!') {
            $negate = \true;
            $rule = ltrim($rule, '!');
        }
        $firstSlashPosition = strpos($rule, '/');
        if (0 === $firstSlashPosition) {
            $pattern = '^/';
        } elseif (\false === $firstSlashPosition || strlen($rule) - 1 === $firstSlashPosition) {
            $pattern = '/';
        }
        $rule = trim($rule, '/');
        // remove delimiters as well as caret (^) and dollar sign ($) from the regex
        $rule = substr(Finder\Glob::toRegex($rule), 2, -2);
        return ['{' . $pattern . $rule . '(?=$|/)}', $negate, \false];
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer\Package\Archiver;

use FilterIterator;
use Iterator;
use PharData;
use SplFileInfo;
/**
 * @phpstan-extends FilterIterator<string, SplFileInfo, Iterator<string, SplFileInfo>>
 */
class ArchivableFilesFilter extends FilterIterator
{
    /** @var string[] */
    private $dirs = [];
    /**
     * @return bool true if the current element is acceptable, otherwise false.
     */
    public function accept(): bool
    {
        $file = $this->getInnerIterator()->current();
        if ($file->isDir()) {
            $this->dirs[] = (string) $file;
            return \false;
        }
        return \true;
    }
    public function addEmptyDir(PharData $phar, string $sources): void
    {
        foreach ($this->dirs as $filepath) {
            $localname = str_replace($sources . "/", '', $filepath);
            $phar->addEmptyDir($localname);
        }
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer\Package\Archiver;

use Composer\Pcre\Preg;
/**
 * An exclude filter that processes gitattributes
 *
 * It respects export-ignore git attributes
 *
 * @author Nils Adermann <naderman@naderman.de>
 */
class GitExcludeFilter extends \Composer\Package\Archiver\BaseExcludeFilter
{
    /**
     * Parses .gitattributes if it exists
     */
    public function __construct(string $sourcePath)
    {
        parent::__construct($sourcePath);
        if (file_exists($sourcePath . '/.gitattributes')) {
            $this->excludePatterns = array_merge($this->excludePatterns, $this->parseLines(file($sourcePath . '/.gitattributes'), [$this, 'parseGitAttributesLine']));
        }
    }
    /**
     * Callback parser which finds export-ignore rules in git attribute lines
     *
     * @param string $line A line from .gitattributes
     *
     * @return array{0: string, 1: bool, 2: bool}|null An exclude pattern for filter()
     */
    public function parseGitAttributesLine(string $line): ?array
    {
        $parts = Preg::split('#\s+#', $line);
        if (count($parts) === 2 && $parts[1] === 'export-ignore') {
            return $this->generatePattern($parts[0]);
        }
        if (count($parts) === 2 && $parts[1] === '-export-ignore') {
            return $this->generatePattern('!' . $parts[0]);
        }
        return null;
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer\Package\Archiver;

/**
 * An exclude filter which processes composer's own exclude rules
 *
 * @author Nils Adermann <naderman@naderman.de>
 */
class ComposerExcludeFilter extends \Composer\Package\Archiver\BaseExcludeFilter
{
    /**
     * @param string $sourcePath Directory containing sources to be filtered
     * @param string[] $excludeRules An array of exclude rules from composer.json
     */
    public function __construct(string $sourcePath, array $excludeRules)
    {
        parent::__construct($sourcePath);
        $this->excludePatterns = $this->generatePatterns($excludeRules);
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer\Package\Archiver;

/**
 * @author Till Klampaeckel <till@php.net>
 * @author Matthieu Moquet <matthieu@moquet.net>
 * @author Nils Adermann <naderman@naderman.de>
 */
interface ArchiverInterface
{
    /**
     * Create an archive from the sources.
     *
     * @param string   $sources       The sources directory
     * @param string   $target        The target file
     * @param string   $format        The format used for archive
     * @param string[] $excludes      A list of patterns for files to exclude
     * @param bool     $ignoreFilters Whether to ignore filters when looking for files
     *
     * @return string The path to the written archive file
     */
    public function archive(string $sources, string $target, string $format, array $excludes = [], bool $ignoreFilters = \false): string;
    /**
     * Format supported by the archiver.
     *
     * @param string $format     The archive format
     * @param ?string $sourceType The source type (git, svn, hg, etc.)
     *
     * @return bool true if the format is supported by the archiver
     */
    public function supports(string $format, ?string $sourceType): bool;
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer\Package\Archiver;

use Composer\Util\Filesystem;
use Composer\Util\Platform;
use ZipArchive;
/**
 * @author Jan Prieser <jan@prieser.net>
 */
class ZipArchiver implements \Composer\Package\Archiver\ArchiverInterface
{
    /** @var array<string, bool> */
    protected static $formats = ['zip' => \true];
    /**
     * @inheritDoc
     */
    public function archive(string $sources, string $target, string $format, array $excludes = [], bool $ignoreFilters = \false): string
    {
        $fs = new Filesystem();
        $sourcesRealpath = realpath($sources);
        if (\false !== $sourcesRealpath) {
            $sources = $sourcesRealpath;
        }
        unset($sourcesRealpath);
        $sources = $fs->normalizePath($sources);
        $zip = new ZipArchive();
        $res = $zip->open($target, ZipArchive::CREATE);
        if ($res === \true) {
            $files = new \Composer\Package\Archiver\ArchivableFilesFinder($sources, $excludes, $ignoreFilters);
            foreach ($files as $file) {
                /** @var \Symfony\Component\Finder\SplFileInfo $file */
                $filepath = $file->getPathname();
                $relativePath = $file->getRelativePathname();
                if (Platform::isWindows()) {
                    $relativePath = strtr($relativePath, '\\', '/');
                }
                if ($file->isDir()) {
                    $zip->addEmptyDir($relativePath);
                } else {
                    $zip->addFile($filepath, $relativePath);
                }
                /**
                 * setExternalAttributesName() is only available with libzip 0.11.2 or above
                 */
                if (method_exists($zip, 'setExternalAttributesName')) {
                    $perms = fileperms($filepath);
                    /**
                     * Ensure to preserve the permission umasks for the filepath in the archive.
                     */
                    $zip->setExternalAttributesName($relativePath, ZipArchive::OPSYS_UNIX, $perms << 16);
                }
            }
            if ($zip->close()) {
                if (!file_exists($target)) {
                    // create minimal valid ZIP file (Empty Central Directory + End of Central Directory record)
                    $eocd = pack(
                        'VvvvvVVv',
                        0x6054b50,
                        // End of central directory signature
                        0,
                        // Number of this disk
                        0,
                        // Disk where central directory starts
                        0,
                        // Number of central directory records on this disk
                        0,
                        // Total number of central directory records
                        0,
                        // Size of central directory (bytes)
                        0,
                        // Offset of start of central directory
                        0
                    );
                    file_put_contents($target, $eocd);
                }
                return $target;
            }
        }
        $message = sprintf("Could not create archive '%s' from '%s': %s", $target, $sources, $zip->getStatusString());
        throw new \RuntimeException($message);
    }
    /**
     * @inheritDoc
     */
    public function supports(string $format, ?string $sourceType): bool
    {
        return isset(static::$formats[$format]) && $this->compressionAvailable();
    }
    private function compressionAvailable(): bool
    {
        return class_exists('ZipArchive');
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer\Package;

/**
 * @author Jordi Boggiano <j.boggiano@seld.be>
 */
class CompleteAliasPackage extends \Composer\Package\AliasPackage implements \Composer\Package\CompletePackageInterface
{
    /** @var CompletePackage */
    protected $aliasOf;
    /**
     * All descendants' constructors should call this parent constructor
     *
     * @param CompletePackage $aliasOf       The package this package is an alias of
     * @param string          $version       The version the alias must report
     * @param string          $prettyVersion The alias's non-normalized version
     */
    public function __construct(\Composer\Package\CompletePackage $aliasOf, string $version, string $prettyVersion)
    {
        parent::__construct($aliasOf, $version, $prettyVersion);
    }
    /**
     * @return CompletePackage
     */
    public function getAliasOf()
    {
        return $this->aliasOf;
    }
    public function getScripts(): array
    {
        return $this->aliasOf->getScripts();
    }
    public function setScripts(array $scripts): void
    {
        $this->aliasOf->setScripts($scripts);
    }
    public function getRepositories(): array
    {
        return $this->aliasOf->getRepositories();
    }
    public function setRepositories(array $repositories): void
    {
        $this->aliasOf->setRepositories($repositories);
    }
    public function getLicense(): array
    {
        return $this->aliasOf->getLicense();
    }
    public function setLicense(array $license): void
    {
        $this->aliasOf->setLicense($license);
    }
    public function getKeywords(): array
    {
        return $this->aliasOf->getKeywords();
    }
    public function setKeywords(array $keywords): void
    {
        $this->aliasOf->setKeywords($keywords);
    }
    public function getDescription(): ?string
    {
        return $this->aliasOf->getDescription();
    }
    public function setDescription(?string $description): void
    {
        $this->aliasOf->setDescription($description);
    }
    public function getHomepage(): ?string
    {
        return $this->aliasOf->getHomepage();
    }
    public function setHomepage(?string $homepage): void
    {
        $this->aliasOf->setHomepage($homepage);
    }
    public function getAuthors(): array
    {
        return $this->aliasOf->getAuthors();
    }
    public function setAuthors(array $authors): void
    {
        $this->aliasOf->setAuthors($authors);
    }
    public function getSupport(): array
    {
        return $this->aliasOf->getSupport();
    }
    public function setSupport(array $support): void
    {
        $this->aliasOf->setSupport($support);
    }
    public function getFunding(): array
    {
        return $this->aliasOf->getFunding();
    }
    public function setFunding(array $funding): void
    {
        $this->aliasOf->setFunding($funding);
    }
    public function isAbandoned(): bool
    {
        return $this->aliasOf->isAbandoned();
    }
    public function getReplacementPackage(): ?string
    {
        return $this->aliasOf->getReplacementPackage();
    }
    public function setAbandoned($abandoned): void
    {
        $this->aliasOf->setAbandoned($abandoned);
    }
    public function getArchiveName(): ?string
    {
        return $this->aliasOf->getArchiveName();
    }
    public function setArchiveName(?string $name): void
    {
        $this->aliasOf->setArchiveName($name);
    }
    public function getArchiveExcludes(): array
    {
        return $this->aliasOf->getArchiveExcludes();
    }
    public function setArchiveExcludes(array $excludes): void
    {
        $this->aliasOf->setArchiveExcludes($excludes);
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer\Package;

use Composer\Semver\Constraint\Constraint;
use Composer\Package\Version\VersionParser;
/**
 * @author Jordi Boggiano <j.boggiano@seld.be>
 */
class AliasPackage extends \Composer\Package\BasePackage
{
    /** @var string */
    protected $version;
    /** @var string */
    protected $prettyVersion;
    /** @var bool */
    protected $dev;
    /** @var bool */
    protected $rootPackageAlias = \false;
    /**
     * @var string
     * @phpstan-var 'stable'|'RC'|'beta'|'alpha'|'dev'
     */
    protected $stability;
    /** @var bool */
    protected $hasSelfVersionRequires = \false;
    /** @var BasePackage */
    protected $aliasOf;
    /** @var Link[] */
    protected $requires;
    /** @var Link[] */
    protected $devRequires;
    /** @var Link[] */
    protected $conflicts;
    /** @var Link[] */
    protected $provides;
    /** @var Link[] */
    protected $replaces;
    /**
     * All descendants' constructors should call this parent constructor
     *
     * @param BasePackage $aliasOf       The package this package is an alias of
     * @param string      $version       The version the alias must report
     * @param string      $prettyVersion The alias's non-normalized version
     */
    public function __construct(\Composer\Package\BasePackage $aliasOf, string $version, string $prettyVersion)
    {
        parent::__construct($aliasOf->getName());
        $this->version = $version;
        $this->prettyVersion = $prettyVersion;
        $this->aliasOf = $aliasOf;
        $this->stability = VersionParser::parseStability($version);
        $this->dev = $this->stability === 'dev';
        foreach (\Composer\Package\Link::$TYPES as $type) {
            $links = $aliasOf->{'get' . ucfirst($type)}();
            $this->{$type} = $this->replaceSelfVersionDependencies($links, $type);
        }
    }
    /**
     * @return BasePackage
     */
    public function getAliasOf()
    {
        return $this->aliasOf;
    }
    /**
     * @inheritDoc
     */
    public function getVersion(): string
    {
        return $this->version;
    }
    /**
     * @inheritDoc
     */
    public function getStability(): string
    {
        return $this->stability;
    }
    /**
     * @inheritDoc
     */
    public function getPrettyVersion(): string
    {
        return $this->prettyVersion;
    }
    /**
     * @inheritDoc
     */
    public function isDev(): bool
    {
        return $this->dev;
    }
    /**
     * @inheritDoc
     */
    public function getRequires(): array
    {
        return $this->requires;
    }
    /**
     * @inheritDoc
     * @return array<string|int, Link>
     */
    public function getConflicts(): array
    {
        return $this->conflicts;
    }
    /**
     * @inheritDoc
     * @return array<string|int, Link>
     */
    public function getProvides(): array
    {
        return $this->provides;
    }
    /**
     * @inheritDoc
     * @return array<string|int, Link>
     */
    public function getReplaces(): array
    {
        return $this->replaces;
    }
    /**
     * @inheritDoc
     */
    public function getDevRequires(): array
    {
        return $this->devRequires;
    }
    /**
     * Stores whether this is an alias created by an aliasing in the requirements of the root package or not
     *
     * Use by the policy for sorting manually aliased packages first, see #576
     */
    public function setRootPackageAlias(bool $value): void
    {
        $this->rootPackageAlias = $value;
    }
    /**
     * @see setRootPackageAlias
     */
    public function isRootPackageAlias(): bool
    {
        return $this->rootPackageAlias;
    }
    /**
     * @param Link[]       $links
     * @param Link::TYPE_* $linkType
     *
     * @return Link[]
     */
    protected function replaceSelfVersionDependencies(array $links, $linkType): array
    {
        // for self.version requirements, we use the original package's branch name instead, to avoid leaking the magic dev-master-alias to users
        $prettyVersion = $this->prettyVersion;
        if ($prettyVersion === VersionParser::DEFAULT_BRANCH_ALIAS) {
            $prettyVersion = $this->aliasOf->getPrettyVersion();
        }
        if (\in_array($linkType, [\Composer\Package\Link::TYPE_CONFLICT, \Composer\Package\Link::TYPE_PROVIDE, \Composer\Package\Link::TYPE_REPLACE], \true)) {
            $newLinks = [];
            foreach ($links as $link) {
                // link is self.version, but must be replacing also the replaced version
                if ('self.version' === $link->getPrettyConstraint()) {
                    $newLinks[] = new \Composer\Package\Link($link->getSource(), $link->getTarget(), $constraint = new Constraint('=', $this->version), $linkType, $prettyVersion);
                    $constraint->setPrettyString($prettyVersion);
                }
            }
            $links = array_merge($links, $newLinks);
        } else {
            foreach ($links as $index => $link) {
                if ('self.version' === $link->getPrettyConstraint()) {
                    if ($linkType === \Composer\Package\Link::TYPE_REQUIRE) {
                        $this->hasSelfVersionRequires = \true;
                    }
                    $links[$index] = new \Composer\Package\Link($link->getSource(), $link->getTarget(), $constraint = new Constraint('=', $this->version), $linkType, $prettyVersion);
                    $constraint->setPrettyString($prettyVersion);
                }
            }
        }
        return $links;
    }
    public function hasSelfVersionRequires(): bool
    {
        return $this->hasSelfVersionRequires;
    }
    public function __toString(): string
    {
        return parent::__toString() . ' (' . ($this->rootPackageAlias ? 'root ' : '') . 'alias of ' . $this->aliasOf->getVersion() . ')';
    }
    /***************************************
     * Wrappers around the aliased package *
     ***************************************/
    public function getType(): string
    {
        return $this->aliasOf->getType();
    }
    public function getTargetDir(): ?string
    {
        return $this->aliasOf->getTargetDir();
    }
    public function getExtra(): array
    {
        return $this->aliasOf->getExtra();
    }
    public function setInstallationSource(?string $type): void
    {
        $this->aliasOf->setInstallationSource($type);
    }
    public function getInstallationSource(): ?string
    {
        return $this->aliasOf->getInstallationSource();
    }
    public function getSourceType(): ?string
    {
        return $this->aliasOf->getSourceType();
    }
    public function getSourceUrl(): ?string
    {
        return $this->aliasOf->getSourceUrl();
    }
    public function getSourceUrls(): array
    {
        return $this->aliasOf->getSourceUrls();
    }
    public function getSourceReference(): ?string
    {
        return $this->aliasOf->getSourceReference();
    }
    public function setSourceReference(?string $reference): void
    {
        $this->aliasOf->setSourceReference($reference);
    }
    public function setSourceMirrors(?array $mirrors): void
    {
        $this->aliasOf->setSourceMirrors($mirrors);
    }
    public function getSourceMirrors(): ?array
    {
        return $this->aliasOf->getSourceMirrors();
    }
    public function getDistType(): ?string
    {
        return $this->aliasOf->getDistType();
    }
    public function getDistUrl(): ?string
    {
        return $this->aliasOf->getDistUrl();
    }
    public function getDistUrls(): array
    {
        return $this->aliasOf->getDistUrls();
    }
    public function getDistReference(): ?string
    {
        return $this->aliasOf->getDistReference();
    }
    public function setDistReference(?string $reference): void
    {
        $this->aliasOf->setDistReference($reference);
    }
    public function getDistSha1Checksum(): ?string
    {
        return $this->aliasOf->getDistSha1Checksum();
    }
    public function setTransportOptions(array $options): void
    {
        $this->aliasOf->setTransportOptions($options);
    }
    public function getTransportOptions(): array
    {
        return $this->aliasOf->getTransportOptions();
    }
    public function setDistMirrors(?array $mirrors): void
    {
        $this->aliasOf->setDistMirrors($mirrors);
    }
    public function getDistMirrors(): ?array
    {
        return $this->aliasOf->getDistMirrors();
    }
    public function getAutoload(): array
    {
        return $this->aliasOf->getAutoload();
    }
    public function getDevAutoload(): array
    {
        return $this->aliasOf->getDevAutoload();
    }
    public function getIncludePaths(): array
    {
        return $this->aliasOf->getIncludePaths();
    }
    public function getPhpExt(): ?array
    {
        return $this->aliasOf->getPhpExt();
    }
    public function getReleaseDate(): ?\DateTimeInterface
    {
        return $this->aliasOf->getReleaseDate();
    }
    public function getBinaries(): array
    {
        return $this->aliasOf->getBinaries();
    }
    public function getSuggests(): array
    {
        return $this->aliasOf->getSuggests();
    }
    public function getNotificationUrl(): ?string
    {
        return $this->aliasOf->getNotificationUrl();
    }
    public function isDefaultBranch(): bool
    {
        return $this->aliasOf->isDefaultBranch();
    }
    public function setDistUrl(?string $url): void
    {
        $this->aliasOf->setDistUrl($url);
    }
    public function setDistType(?string $type): void
    {
        $this->aliasOf->setDistType($type);
    }
    public function setSourceDistReferences(string $reference): void
    {
        $this->aliasOf->setSourceDistReferences($reference);
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer\Package;

use Composer\Json\JsonFile;
use Composer\Installer\InstallationManager;
use Composer\Pcre\Preg;
use Composer\Repository\InstalledRepository;
use Composer\Repository\LockArrayRepository;
use Composer\Repository\PlatformRepository;
use Composer\Repository\RootPackageRepository;
use Composer\Util\ProcessExecutor;
use Composer\Package\Dumper\ArrayDumper;
use Composer\Package\Loader\ArrayLoader;
use Composer\Package\Version\VersionParser;
use Composer\Plugin\PluginInterface;
use Composer\Util\Git as GitUtil;
use Composer\IO\IOInterface;
use _ContaoManager\Seld\JsonLint\ParsingException;
/**
 * Reads/writes project lockfile (composer.lock).
 *
 * @author Konstantin Kudryashiv <ever.zet@gmail.com>
 * @author Jordi Boggiano <j.boggiano@seld.be>
 */
class Locker
{
    /** @var JsonFile */
    private $lockFile;
    /** @var InstallationManager */
    private $installationManager;
    /** @var string */
    private $hash;
    /** @var string */
    private $contentHash;
    /** @var ArrayLoader */
    private $loader;
    /** @var ArrayDumper */
    private $dumper;
    /** @var ProcessExecutor */
    private $process;
    /** @var mixed[]|null */
    private $lockDataCache = null;
    /** @var bool */
    private $virtualFileWritten = \false;
    /**
     * Initializes packages locker.
     *
     * @param JsonFile            $lockFile             lockfile loader
     * @param InstallationManager $installationManager  installation manager instance
     * @param string              $composerFileContents The contents of the composer file
     */
    public function __construct(IOInterface $io, JsonFile $lockFile, InstallationManager $installationManager, string $composerFileContents, ?ProcessExecutor $process = null)
    {
        $this->lockFile = $lockFile;
        $this->installationManager = $installationManager;
        $this->hash = hash('md5', $composerFileContents);
        $this->contentHash = self::getContentHash($composerFileContents);
        $this->loader = new ArrayLoader(null, \true);
        $this->dumper = new ArrayDumper();
        $this->process = $process ?? new ProcessExecutor($io);
    }
    /**
     * @internal
     */
    public function getJsonFile(): JsonFile
    {
        return $this->lockFile;
    }
    /**
     * Returns the md5 hash of the sorted content of the composer file.
     *
     * @param string $composerFileContents The contents of the composer file.
     */
    public static function getContentHash(string $composerFileContents): string
    {
        $content = JsonFile::parseJson($composerFileContents, 'composer.json');
        $relevantKeys = ['name', 'version', 'require', 'require-dev', 'conflict', 'replace', 'provide', 'minimum-stability', 'prefer-stable', 'repositories', 'extra'];
        $relevantContent = [];
        foreach (array_intersect($relevantKeys, array_keys($content)) as $key) {
            $relevantContent[$key] = $content[$key];
        }
        if (isset($content['config']['platform'])) {
            $relevantContent['config']['platform'] = $content['config']['platform'];
        }
        ksort($relevantContent);
        return hash('md5', JsonFile::encode($relevantContent, 0));
    }
    /**
     * Checks whether locker has been locked (lockfile found).
     */
    public function isLocked(): bool
    {
        if (!$this->virtualFileWritten && !$this->lockFile->exists()) {
            return \false;
        }
        $data = $this->getLockData();
        return isset($data['packages']);
    }
    /**
     * Checks whether the lock file is still up to date with the current hash
     */
    public function isFresh(): bool
    {
        $lock = $this->lockFile->read();
        if (!empty($lock['content-hash'])) {
            // There is a content hash key, use that instead of the file hash
            return $this->contentHash === $lock['content-hash'];
        }
        // BC support for old lock files without content-hash
        if (!empty($lock['hash'])) {
            return $this->hash === $lock['hash'];
        }
        // should not be reached unless the lock file is corrupted, so assume it's out of date
        return \false;
    }
    /**
     * Searches and returns an array of locked packages, retrieved from registered repositories.
     *
     * @param  bool                                     $withDevReqs true to retrieve the locked dev packages
     * @throws \RuntimeException
     */
    public function getLockedRepository(bool $withDevReqs = \false): LockArrayRepository
    {
        $lockData = $this->getLockData();
        $packages = new LockArrayRepository();
        $lockedPackages = $lockData['packages'];
        if ($withDevReqs) {
            if (isset($lockData['packages-dev'])) {
                $lockedPackages = array_merge($lockedPackages, $lockData['packages-dev']);
            } else {
                throw new \RuntimeException('The lock file does not contain require-dev information, run install with the --no-dev option or delete it and run composer update to generate a new lock file.');
            }
        }
        if (empty($lockedPackages)) {
            return $packages;
        }
        if (isset($lockedPackages[0]['name'])) {
            $packageByName = [];
            foreach ($lockedPackages as $info) {
                $package = $this->loader->load($info);
                $packages->addPackage($package);
                $packageByName[$package->getName()] = $package;
                if ($package instanceof \Composer\Package\AliasPackage) {
                    $packageByName[$package->getAliasOf()->getName()] = $package->getAliasOf();
                }
            }
            if (isset($lockData['aliases'])) {
                foreach ($lockData['aliases'] as $alias) {
                    if (isset($packageByName[$alias['package']])) {
                        $aliasPkg = new \Composer\Package\CompleteAliasPackage($packageByName[$alias['package']], $alias['alias_normalized'], $alias['alias']);
                        $aliasPkg->setRootPackageAlias(\true);
                        $packages->addPackage($aliasPkg);
                    }
                }
            }
            return $packages;
        }
        throw new \RuntimeException('Your composer.lock is invalid. Run "composer update" to generate a new one.');
    }
    /**
     * @return string[] Names of dependencies installed through require-dev
     */
    public function getDevPackageNames(): array
    {
        $names = [];
        $lockData = $this->getLockData();
        if (isset($lockData['packages-dev'])) {
            foreach ($lockData['packages-dev'] as $package) {
                $names[] = strtolower($package['name']);
            }
        }
        return $names;
    }
    /**
     * Returns the platform requirements stored in the lock file
     *
     * @param  bool                     $withDevReqs if true, the platform requirements from the require-dev block are also returned
     * @return Link[]
     */
    public function getPlatformRequirements(bool $withDevReqs = \false): array
    {
        $lockData = $this->getLockData();
        $requirements = [];
        if (!empty($lockData['platform'])) {
            $requirements = $this->loader->parseLinks('__root__', '1.0.0', \Composer\Package\Link::TYPE_REQUIRE, $lockData['platform'] ?? []);
        }
        if ($withDevReqs && !empty($lockData['platform-dev'])) {
            $devRequirements = $this->loader->parseLinks('__root__', '1.0.0', \Composer\Package\Link::TYPE_REQUIRE, $lockData['platform-dev'] ?? []);
            $requirements = array_merge($requirements, $devRequirements);
        }
        return $requirements;
    }
    /**
     * @return key-of<BasePackage::STABILITIES>
     */
    public function getMinimumStability(): string
    {
        $lockData = $this->getLockData();
        return $lockData['minimum-stability'] ?? 'stable';
    }
    /**
     * @return array<string, string>
     */
    public function getStabilityFlags(): array
    {
        $lockData = $this->getLockData();
        return $lockData['stability-flags'] ?? [];
    }
    public function getPreferStable(): ?bool
    {
        $lockData = $this->getLockData();
        // return null if not set to allow caller logic to choose the
        // right behavior since old lock files have no prefer-stable
        return $lockData['prefer-stable'] ?? null;
    }
    public function getPreferLowest(): ?bool
    {
        $lockData = $this->getLockData();
        // return null if not set to allow caller logic to choose the
        // right behavior since old lock files have no prefer-lowest
        return $lockData['prefer-lowest'] ?? null;
    }
    /**
     * @return array<string, string>
     */
    public function getPlatformOverrides(): array
    {
        $lockData = $this->getLockData();
        return $lockData['platform-overrides'] ?? [];
    }
    /**
     * @return string[][]
     *
     * @phpstan-return list<array{package: string, version: string, alias: string, alias_normalized: string}>
     */
    public function getAliases(): array
    {
        $lockData = $this->getLockData();
        return $lockData['aliases'] ?? [];
    }
    /**
     * @return string
     */
    public function getPluginApi()
    {
        $lockData = $this->getLockData();
        return $lockData['plugin-api-version'] ?? '1.1.0';
    }
    /**
     * @return array<string, mixed>
     */
    public function getLockData(): array
    {
        if (null !== $this->lockDataCache) {
            return $this->lockDataCache;
        }
        if (!$this->lockFile->exists()) {
            throw new \LogicException('No lockfile found. Unable to read locked packages');
        }
        return $this->lockDataCache = $this->lockFile->read();
    }
    /**
     * Locks provided data into lockfile.
     *
     * @param PackageInterface[]          $packages          array of packages
     * @param PackageInterface[]|null     $devPackages       array of dev packages or null if installed without --dev
     * @param array<string, string>       $platformReqs      array of package name => constraint for required platform packages
     * @param array<string, string>       $platformDevReqs   array of package name => constraint for dev-required platform packages
     * @param string[][]                  $aliases           array of aliases
     * @param array<string, int>          $stabilityFlags
     * @param array<string, string|false> $platformOverrides
     * @param bool                        $write             Whether to actually write data to disk, useful in tests and for --dry-run
     *
     * @phpstan-param list<array{package: string, version: string, alias: string, alias_normalized: string}> $aliases
     */
    public function setLockData(array $packages, ?array $devPackages, array $platformReqs, array $platformDevReqs, array $aliases, string $minimumStability, array $stabilityFlags, bool $preferStable, bool $preferLowest, array $platformOverrides, bool $write = \true): bool
    {
        // keep old default branch names normalized to DEFAULT_BRANCH_ALIAS for BC as that is how Composer 1 outputs the lock file
        // when loading the lock file the version is anyway ignored in Composer 2, so it has no adverse effect
        $aliases = array_map(static function ($alias): array {
            if (in_array($alias['version'], ['dev-master', 'dev-trunk', 'dev-default'], \true)) {
                $alias['version'] = VersionParser::DEFAULT_BRANCH_ALIAS;
            }
            return $alias;
        }, $aliases);
        $lock = ['_readme' => ['This file locks the dependencies of your project to a known state', 'Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies', 'This file is @gener' . 'ated automatically'], 'content-hash' => $this->contentHash, 'packages' => $this->lockPackages($packages), 'packages-dev' => null, 'aliases' => $aliases, 'minimum-stability' => $minimumStability, 'stability-flags' => $stabilityFlags, 'prefer-stable' => $preferStable, 'prefer-lowest' => $preferLowest];
        if (null !== $devPackages) {
            $lock['packages-dev'] = $this->lockPackages($devPackages);
        }
        $lock['platform'] = $platformReqs;
        $lock['platform-dev'] = $platformDevReqs;
        if (\count($platformOverrides) > 0) {
            $lock['platform-overrides'] = $platformOverrides;
        }
        $lock['plugin-api-version'] = PluginInterface::PLUGIN_API_VERSION;
        $lock = $this->fixupJsonDataType($lock);
        try {
            $isLocked = $this->isLocked();
        } catch (ParsingException $e) {
            $isLocked = \false;
        }
        if (!$isLocked || $lock !== $this->getLockData()) {
            if ($write) {
                $this->lockFile->write($lock);
                $this->lockDataCache = null;
                $this->virtualFileWritten = \false;
            } else {
                $this->virtualFileWritten = \true;
                $this->lockDataCache = JsonFile::parseJson(JsonFile::encode($lock));
            }
            return \true;
        }
        return \false;
    }
    /**
     * Updates the lock file's hash in-place from a given composer.json's JsonFile
     *
     * This does not reload or require any packages, and retains the filemtime of the lock file.
     *
     * Use this only to update the lock file hash after updating a composer.json in ways that are guaranteed NOT to impact the dependency resolution.
     *
     * This is a risky method, use carefully.
     *
     * @param (callable(array<string, mixed>): array<string, mixed>)|null $dataProcessor Receives the lock data and can process it before it gets written to disk
     */
    public function updateHash(JsonFile $composerJson, ?callable $dataProcessor = null): void
    {
        $contents = file_get_contents($composerJson->getPath());
        if (\false === $contents) {
            throw new \RuntimeException('Unable to read ' . $composerJson->getPath() . ' contents to update the lock file hash.');
        }
        $lockMtime = filemtime($this->lockFile->getPath());
        $lockData = $this->lockFile->read();
        $lockData['content-hash'] = \Composer\Package\Locker::getContentHash($contents);
        if ($dataProcessor !== null) {
            $lockData = $dataProcessor($lockData);
        }
        $this->lockFile->write($this->fixupJsonDataType($lockData));
        $this->lockDataCache = null;
        $this->virtualFileWritten = \false;
        if (is_int($lockMtime)) {
            @touch($this->lockFile->getPath(), $lockMtime);
        }
    }
    /**
     * Ensures correct data types and ordering for the JSON lock format
     *
     * @param array<mixed> $lockData
     * @return array<mixed>
     */
    private function fixupJsonDataType(array $lockData): array
    {
        foreach (['stability-flags', 'platform', 'platform-dev'] as $key) {
            if (isset($lockData[$key]) && is_array($lockData[$key]) && \count($lockData[$key]) === 0) {
                $lockData[$key] = new \stdClass();
            }
        }
        if (is_array($lockData['stability-flags'])) {
            ksort($lockData['stability-flags']);
        }
        return $lockData;
    }
    /**
     * @param PackageInterface[] $packages
     *
     * @return mixed[][]
     *
     * @phpstan-return list<array<string, mixed>>
     */
    private function lockPackages(array $packages): array
    {
        $locked = [];
        foreach ($packages as $package) {
            if ($package instanceof \Composer\Package\AliasPackage) {
                continue;
            }
            $name = $package->getPrettyName();
            $version = $package->getPrettyVersion();
            if (!$name || !$version) {
                throw new \LogicException(sprintf('Package "%s" has no version or name and can not be locked', $package));
            }
            $spec = $this->dumper->dump($package);
            unset($spec['version_normalized']);
            // always move time to the end of the package definition
            $time = $spec['time'] ?? null;
            unset($spec['time']);
            if ($package->isDev() && $package->getInstallationSource() === 'source') {
                // use the exact commit time of the current reference if it's a dev package
                $time = $this->getPackageTime($package) ?: $time;
            }
            if (null !== $time) {
                $spec['time'] = $time;
            }
            unset($spec['installation-source']);
            $locked[] = $spec;
        }
        usort($locked, static function ($a, $b) {
            $comparison = strcmp($a['name'], $b['name']);
            if (0 !== $comparison) {
                return $comparison;
            }
            // If it is the same package, compare the versions to make the order deterministic
            return strcmp($a['version'], $b['version']);
        });
        return $locked;
    }
    /**
     * Returns the packages's datetime for its source reference.
     *
     * @param  PackageInterface $package The package to scan.
     * @return string|null      The formatted datetime or null if none was found.
     */
    private function getPackageTime(\Composer\Package\PackageInterface $package): ?string
    {
        if (!function_exists('proc_open')) {
            return null;
        }
        $path = $this->installationManager->getInstallPath($package);
        if ($path === null) {
            return null;
        }
        $path = realpath($path);
        $sourceType = $package->getSourceType();
        $datetime = null;
        if ($path && in_array($sourceType, ['git', 'hg'])) {
            $sourceRef = $package->getSourceReference() ?: $package->getDistReference();
            switch ($sourceType) {
                case 'git':
                    GitUtil::cleanEnv($this->process);
                    $command = GitUtil::buildRevListCommand($this->process, array_merge(['-n1', '--format=%ct', (string) $sourceRef], GitUtil::getNoShowSignatureFlags($this->process)));
                    if (0 === $this->process->execute($command, $output, $path)) {
                        $output = trim(GitUtil::parseRevListOutput($output, $this->process));
                        if (Preg::isMatch('{^\s*\d+\s*$}', $output)) {
                            $datetime = new \DateTime('@' . trim($output), new \DateTimeZone('UTC'));
                        }
                    }
                    break;
                case 'hg':
                    if (0 === $this->process->execute(['hg', 'log', '--template', '{date|hgdate}', '-r', (string) $sourceRef], $output, $path) && Preg::isMatch('{^\s*(\d+)\s*}', $output, $match)) {
                        $datetime = new \DateTime('@' . $match[1], new \DateTimeZone('UTC'));
                    }
                    break;
            }
        }
        return $datetime ? $datetime->format(\DATE_RFC3339) : null;
    }
    /**
     * @return array<string>
     */
    public function getMissingRequirementInfo(\Composer\Package\RootPackageInterface $package, bool $includeDev): array
    {
        $missingRequirementInfo = [];
        $missingRequirements = \false;
        $sets = [['repo' => $this->getLockedRepository(\false), 'method' => 'getRequires', 'description' => 'Required']];
        if ($includeDev === \true) {
            $sets[] = ['repo' => $this->getLockedRepository(\true), 'method' => 'getDevRequires', 'description' => 'Required (in require-dev)'];
        }
        $rootRepo = new RootPackageRepository(clone $package);
        foreach ($sets as $set) {
            $installedRepo = new InstalledRepository([$set['repo'], $rootRepo]);
            foreach (call_user_func([$package, $set['method']]) as $link) {
                if (PlatformRepository::isPlatformPackage($link->getTarget())) {
                    continue;
                }
                if ($link->getPrettyConstraint() === 'self.version') {
                    continue;
                }
                if ($installedRepo->findPackagesWithReplacersAndProviders($link->getTarget(), $link->getConstraint()) === []) {
                    $results = $installedRepo->findPackagesWithReplacersAndProviders($link->getTarget());
                    if ($results !== []) {
                        $provider = reset($results);
                        $description = $provider->getPrettyVersion();
                        if ($provider->getName() !== $link->getTarget()) {
                            foreach (['getReplaces' => 'replaced as %s by %s', 'getProvides' => 'provided as %s by %s'] as $method => $text) {
                                foreach (call_user_func([$provider, $method]) as $providerLink) {
                                    if ($providerLink->getTarget() === $link->getTarget()) {
                                        $description = sprintf($text, $providerLink->getPrettyConstraint(), $provider->getPrettyName() . ' ' . $provider->getPrettyVersion());
                                        break 2;
                                    }
                                }
                            }
                        }
                        $missingRequirementInfo[] = '- ' . $set['description'] . ' package "' . $link->getTarget() . '" is in the lock file as "' . $description . '" but that does not satisfy your constraint "' . $link->getPrettyConstraint() . '".';
                    } else {
                        $missingRequirementInfo[] = '- ' . $set['description'] . ' package "' . $link->getTarget() . '" is not present in the lock file.';
                    }
                    $missingRequirements = \true;
                }
            }
        }
        if ($missingRequirements) {
            $missingRequirementInfo[] = 'This usually happens when composer files are incorrectly merged or the composer.json file is manually edited.';
            $missingRequirementInfo[] = 'Read more about correctly resolving merge conflicts https://getcomposer.org/doc/articles/resolving-merge-conflicts.md';
            $missingRequirementInfo[] = 'and prefer using the "require" command over editing the composer.json file directly https://getcomposer.org/doc/03-cli.md#require-r';
        }
        return $missingRequirementInfo;
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer\Package;

use Composer\Repository\RepositoryInterface;
/**
 * Defines the essential information a package has that is used during solving/installation
 *
 * PackageInterface & derivatives are considered internal, you may use them in type hints but extending/implementing them is not recommended and not supported. Things may change without notice.
 *
 * @author Jordi Boggiano <j.boggiano@seld.be>
 *
 * @phpstan-type AutoloadRules    array{psr-0?: array<string, string|string[]>, psr-4?: array<string, string|string[]>, classmap?: list<string>, files?: list<string>, exclude-from-classmap?: list<string>}
 * @phpstan-type DevAutoloadRules array{psr-0?: array<string, string|string[]>, psr-4?: array<string, string|string[]>, classmap?: list<string>, files?: list<string>}
 * @phpstan-type PhpExtConfig     array{extension-name?: string, priority?: int, support-zts?: bool, support-nts?: bool, build-path?: string|null, download-url-method?: string|list<string>, os-families?: non-empty-list<non-empty-string>, os-families-exclude?: non-empty-list<non-empty-string>, configure-options?: list<array{name: string, description?: string}>}
 */
interface PackageInterface
{
    public const DISPLAY_SOURCE_REF_IF_DEV = 0;
    public const DISPLAY_SOURCE_REF = 1;
    public const DISPLAY_DIST_REF = 2;
    /**
     * Returns the package's name without version info, thus not a unique identifier
     *
     * @return string package name
     */
    public function getName(): string;
    /**
     * Returns the package's pretty (i.e. with proper case) name
     *
     * @return string package name
     */
    public function getPrettyName(): string;
    /**
     * Returns a set of names that could refer to this package
     *
     * No version or release type information should be included in any of the
     * names. Provided or replaced package names need to be returned as well.
     *
     * @param bool $provides Whether provided names should be included
     *
     * @return string[] An array of strings referring to this package
     */
    public function getNames(bool $provides = \true): array;
    /**
     * Allows the solver to set an id for this package to refer to it.
     */
    public function setId(int $id): void;
    /**
     * Retrieves the package's id set through setId
     *
     * @return int The previously set package id
     */
    public function getId(): int;
    /**
     * Returns whether the package is a development virtual package or a concrete one
     */
    public function isDev(): bool;
    /**
     * Returns the package type, e.g. library
     *
     * @return string The package type
     */
    public function getType(): string;
    /**
     * Returns the package targetDir property
     *
     * @return ?string The package targetDir
     */
    public function getTargetDir(): ?string;
    /**
     * Returns the package extra data
     *
     * @return mixed[] The package extra data
     */
    public function getExtra(): array;
    /**
     * Sets source from which this package was installed (source/dist).
     *
     * @param ?string $type source/dist
     * @phpstan-param 'source'|'dist'|null $type
     */
    public function setInstallationSource(?string $type): void;
    /**
     * Returns source from which this package was installed (source/dist).
     *
     * @return ?string source/dist
     * @phpstan-return 'source'|'dist'|null
     */
    public function getInstallationSource(): ?string;
    /**
     * Returns the repository type of this package, e.g. git, svn
     *
     * @return ?string The repository type
     */
    public function getSourceType(): ?string;
    /**
     * Returns the repository url of this package, e.g. git://github.com/naderman/composer.git
     *
     * @return ?string The repository url
     */
    public function getSourceUrl(): ?string;
    /**
     * Returns the repository urls of this package including mirrors, e.g. git://github.com/naderman/composer.git
     *
     * @return list<string>
     */
    public function getSourceUrls(): array;
    /**
     * Returns the repository reference of this package, e.g. master, 1.0.0 or a commit hash for git
     *
     * @return ?string The repository reference
     */
    public function getSourceReference(): ?string;
    /**
     * Returns the source mirrors of this package
     *
     * @return ?list<array{url: non-empty-string, preferred: bool}>
     */
    public function getSourceMirrors(): ?array;
    /**
     * @param  null|list<array{url: non-empty-string, preferred: bool}> $mirrors
     */
    public function setSourceMirrors(?array $mirrors): void;
    /**
     * Returns the type of the distribution archive of this version, e.g. zip, tarball
     *
     * @return ?string The repository type
     */
    public function getDistType(): ?string;
    /**
     * Returns the url of the distribution archive of this version
     *
     * @return ?non-empty-string
     */
    public function getDistUrl(): ?string;
    /**
     * Returns the urls of the distribution archive of this version, including mirrors
     *
     * @return non-empty-string[]
     */
    public function getDistUrls(): array;
    /**
     * Returns the reference of the distribution archive of this version, e.g. master, 1.0.0 or a commit hash for git
     */
    public function getDistReference(): ?string;
    /**
     * Returns the sha1 checksum for the distribution archive of this version
     *
     * Can be an empty string which should be treated as null
     */
    public function getDistSha1Checksum(): ?string;
    /**
     * Returns the dist mirrors of this package
     *
     * @return ?list<array{url: non-empty-string, preferred: bool}>
     */
    public function getDistMirrors(): ?array;
    /**
     * @param  null|list<array{url: non-empty-string, preferred: bool}> $mirrors
     */
    public function setDistMirrors(?array $mirrors): void;
    /**
     * Returns the version of this package
     *
     * @return string version
     */
    public function getVersion(): string;
    /**
     * Returns the pretty (i.e. non-normalized) version string of this package
     *
     * @return string version
     */
    public function getPrettyVersion(): string;
    /**
     * Returns the pretty version string plus a git or hg commit hash of this package
     *
     * @see getPrettyVersion
     *
     * @param  bool   $truncate    If the source reference is a sha1 hash, truncate it
     * @param  int    $displayMode One of the DISPLAY_ constants on this interface determining display of references
     * @return string version
     *
     * @phpstan-param self::DISPLAY_SOURCE_REF_IF_DEV|self::DISPLAY_SOURCE_REF|self::DISPLAY_DIST_REF $displayMode
     */
    public function getFullPrettyVersion(bool $truncate = \true, int $displayMode = self::DISPLAY_SOURCE_REF_IF_DEV): string;
    /**
     * Returns the release date of the package
     */
    public function getReleaseDate(): ?\DateTimeInterface;
    /**
     * Returns the stability of this package: one of (dev, alpha, beta, RC, stable)
     *
     * @phpstan-return 'stable'|'RC'|'beta'|'alpha'|'dev'
     */
    public function getStability(): string;
    /**
     * Returns a set of links to packages which need to be installed before
     * this package can be installed
     *
     * @return array<string, Link> A map of package links defining required packages, indexed by the require package's name
     */
    public function getRequires(): array;
    /**
     * Returns a set of links to packages which must not be installed at the
     * same time as this package
     *
     * @return Link[] An array of package links defining conflicting packages
     */
    public function getConflicts(): array;
    /**
     * Returns a set of links to virtual packages that are provided through
     * this package
     *
     * @return Link[] An array of package links defining provided packages
     */
    public function getProvides(): array;
    /**
     * Returns a set of links to packages which can alternatively be
     * satisfied by installing this package
     *
     * @return Link[] An array of package links defining replaced packages
     */
    public function getReplaces(): array;
    /**
     * Returns a set of links to packages which are required to develop
     * this package. These are installed if in dev mode.
     *
     * @return array<string, Link> A map of package links defining packages required for development, indexed by the require package's name
     */
    public function getDevRequires(): array;
    /**
     * Returns a set of package names and reasons why they are useful in
     * combination with this package.
     *
     * @return array An array of package suggestions with descriptions
     * @phpstan-return array<string, string>
     */
    public function getSuggests(): array;
    /**
     * Returns an associative array of autoloading rules
     *
     * {"<type>": {"<namespace": "<directory>"}}
     *
     * Type is either "psr-4", "psr-0", "classmap" or "files". Namespaces are mapped to
     * directories for autoloading using the type specified.
     *
     * @return array Mapping of autoloading rules
     * @phpstan-return AutoloadRules
     */
    public function getAutoload(): array;
    /**
     * Returns an associative array of dev autoloading rules
     *
     * {"<type>": {"<namespace": "<directory>"}}
     *
     * Type is either "psr-4", "psr-0", "classmap" or "files". Namespaces are mapped to
     * directories for autoloading using the type specified.
     *
     * @return array Mapping of dev autoloading rules
     * @phpstan-return DevAutoloadRules
     */
    public function getDevAutoload(): array;
    /**
     * Returns a list of directories which should get added to PHP's
     * include path.
     *
     * @return string[]
     */
    public function getIncludePaths(): array;
    /**
     * Returns the settings for php extension packages
     *
     *
     * @phpstan-return PhpExtConfig|null
     */
    public function getPhpExt(): ?array;
    /**
     * Stores a reference to the repository that owns the package
     */
    public function setRepository(RepositoryInterface $repository): void;
    /**
     * Returns a reference to the repository that owns the package
     */
    public function getRepository(): ?RepositoryInterface;
    /**
     * Returns the package binaries
     *
     * @return string[]
     */
    public function getBinaries(): array;
    /**
     * Returns package unique name, constructed from name and version.
     */
    public function getUniqueName(): string;
    /**
     * Returns the package notification url
     */
    public function getNotificationUrl(): ?string;
    /**
     * Converts the package into a readable and unique string
     */
    public function __toString(): string;
    /**
     * Converts the package into a pretty readable string
     */
    public function getPrettyString(): string;
    public function isDefaultBranch(): bool;
    /**
     * Returns a list of options to download package dist files
     *
     * @return mixed[]
     */
    public function getTransportOptions(): array;
    /**
     * Configures the list of options to download package dist files
     *
     * @param mixed[] $options
     */
    public function setTransportOptions(array $options): void;
    public function setSourceReference(?string $reference): void;
    public function setDistUrl(?string $url): void;
    public function setDistType(?string $type): void;
    public function setDistReference(?string $reference): void;
    /**
     * Set dist and source references and update dist URL for ones that contain a reference
     */
    public function setSourceDistReferences(string $reference): void;
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer\Package\Version;

use Composer\Package\PackageInterface;
use Composer\Package\Loader\ArrayLoader;
use Composer\Package\Dumper\ArrayDumper;
use Composer\Pcre\Preg;
use Composer\Semver\Constraint\Constraint;
use Composer\Semver\Constraint\ConstraintInterface;
use Composer\Semver\Intervals;
use Composer\Util\Platform;
/**
 * @author Jordi Boggiano <j.boggiano@seld.be>
 * @internal
 */
class VersionBumper
{
    /**
     * Given a constraint, this returns a new constraint with
     * the lower bound bumped to match the given package's version.
     *
     * For example:
     *  * ^1.0 + 1.2.1            -> ^1.2.1
     *  * ^1.2 + 1.2.0            -> ^1.2
     *  * ^1.2.0 + 1.3.0          -> ^1.3.0
     *  * ^1.2 || ^2.3 + 1.3.0    -> ^1.3 || ^2.3
     *  * ^1.2 || ^2.3 + 2.4.0    -> ^1.2 || ^2.4
     *  * ^3@dev + 3.2.99999-dev  -> ^3.2@dev
     *  * ~2 + 2.0-beta.1         -> ~2
     *  * ~2.0.0 + 2.0.3          -> ~2.0.3
     *  * ~2.0 + 2.0.3            -> ^2.0.3
     *  * dev-master + dev-master -> dev-master
     *  * * + 1.2.3               -> >=1.2.3
     */
    public function bumpRequirement(ConstraintInterface $constraint, PackageInterface $package): string
    {
        $parser = new \Composer\Package\Version\VersionParser();
        $prettyConstraint = $constraint->getPrettyString();
        if (str_starts_with($constraint->getPrettyString(), 'dev-')) {
            return $prettyConstraint;
        }
        $version = $package->getVersion();
        if (str_starts_with($package->getVersion(), 'dev-')) {
            $loader = new ArrayLoader($parser);
            $dumper = new ArrayDumper();
            $extra = $loader->getBranchAlias($dumper->dump($package));
            // dev packages without branch alias cannot be processed
            if (null === $extra || $extra === \Composer\Package\Version\VersionParser::DEFAULT_BRANCH_ALIAS) {
                return $prettyConstraint;
            }
            $version = $extra;
        }
        $intervals = Intervals::get($constraint);
        // complex constraints with branch names are not bumped
        if (\count($intervals['branches']['names']) > 0) {
            return $prettyConstraint;
        }
        $major = Preg::replace('{^([1-9][0-9]*|0\.\d+).*}', '$1', $version);
        $versionWithoutSuffix = Preg::replace('{(?:\.(?:0|9999999))+(-dev)?$}', '', $version);
        $newPrettyConstraint = '^' . $versionWithoutSuffix;
        // not a simple stable version, abort
        if (!Preg::isMatch('{^\^\d+(\.\d+)*$}', $newPrettyConstraint)) {
            return $prettyConstraint;
        }
        $pattern = '{
            (?<=,|\ |\||^) # leading separator
            (?P<constraint>
                \^v?' . $major . '(?:\.\d+)* # e.g. ^2.anything
                | ~v?' . $major . '(?:\.\d+){1,3} # e.g. ~2.2 or ~2.2.2 or ~2.2.2.2
                | v?' . $major . '(?:\.[*x])+ # e.g. 2.* or 2.*.* or 2.x.x.x etc
                | >=v?\d(?:\.\d+)* # e.g. >=2 or >=1.2 etc
                | \* # full wildcard
            )
            (?=,|$|\ |\||@) # trailing separator
        }x';
        if (Preg::isMatchAllWithOffsets($pattern, $prettyConstraint, $matches)) {
            $modified = $prettyConstraint;
            foreach (array_reverse($matches['constraint']) as $match) {
                assert(is_string($match[0]));
                $suffix = '';
                if (substr_count($match[0], '.') === 2 && substr_count($versionWithoutSuffix, '.') === 1) {
                    $suffix = '.0';
                }
                if (str_starts_with($match[0], '~') && substr_count($match[0], '.') !== 1) {
                    // take as many version bits from the current version as we have in the constraint to bump it without making it more specific
                    $versionBits = explode('.', $versionWithoutSuffix);
                    $versionBits = array_pad($versionBits, substr_count($match[0], '.') + 1, '0');
                    $replacement = '~' . implode('.', array_slice($versionBits, 0, substr_count($match[0], '.') + 1));
                } elseif ($match[0] === '*' || str_starts_with($match[0], '>=')) {
                    $replacement = '>=' . $versionWithoutSuffix . $suffix;
                } else {
                    $replacement = $newPrettyConstraint . $suffix;
                }
                $modified = substr_replace($modified, $replacement, $match[1], Platform::strlen($match[0]));
            }
            // if it is strictly equal to the previous one then no need to change anything
            $newConstraint = $parser->parseConstraints($modified);
            if (Intervals::isSubsetOf($newConstraint, $constraint) && Intervals::isSubsetOf($constraint, $newConstraint)) {
                return $prettyConstraint;
            }
            return $modified;
        }
        return $prettyConstraint;
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer\Package\Version;

use Composer\Package\BasePackage;
/**
 * @author Jordi Boggiano <j.boggiano@seld.be>
 */
class StabilityFilter
{
    /**
     * Checks if any of the provided package names in the given stability match the configured acceptable stability and flags
     *
     * @param int[] $acceptableStabilities array of stability => BasePackage::STABILITY_* value
     * @phpstan-param array<key-of<BasePackage::STABILITIES>, BasePackage::STABILITY_*> $acceptableStabilities
     * @param int[] $stabilityFlags an array of package name => BasePackage::STABILITY_* value
     * @phpstan-param array<string, BasePackage::STABILITY_*> $stabilityFlags
     * @param  string[] $names     The package name(s) to check for stability flags
     * @param  key-of<BasePackage::STABILITIES> $stability one of 'stable', 'RC', 'beta', 'alpha' or 'dev'
     * @return bool     true if any package name is acceptable
     */
    public static function isPackageAcceptable(array $acceptableStabilities, array $stabilityFlags, array $names, string $stability): bool
    {
        foreach ($names as $name) {
            // allow if package matches the package-specific stability flag
            if (isset($stabilityFlags[$name])) {
                if (BasePackage::STABILITIES[$stability] <= $stabilityFlags[$name]) {
                    return \true;
                }
            } elseif (isset($acceptableStabilities[$stability])) {
                // allow if package matches the global stability requirement and has no exception
                return \true;
            }
        }
        return \false;
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer\Package\Version;

use Composer\Config;
use Composer\IO\IOInterface;
use Composer\Pcre\Preg;
use Composer\Repository\Vcs\HgDriver;
use Composer\IO\NullIO;
use Composer\Semver\VersionParser as SemverVersionParser;
use Composer\Util\Git as GitUtil;
use Composer\Util\HttpDownloader;
use Composer\Util\Platform;
use Composer\Util\ProcessExecutor;
use Composer\Util\Svn as SvnUtil;
use _ContaoManager\Symfony\Component\Process\Process;
/**
 * Try to guess the current version number based on different VCS configuration.
 *
 * @author Jordi Boggiano <j.boggiano@seld.be>
 * @author Samuel Roze <samuel.roze@gmail.com>
 *
 * @phpstan-type Version array{version: string, commit: string|null, pretty_version: string|null}|array{version: string, commit: string|null, pretty_version: string|null, feature_version: string|null, feature_pretty_version: string|null}
 */
class VersionGuesser
{
    /**
     * @var Config
     */
    private $config;
    /**
     * @var ProcessExecutor
     */
    private $process;
    /**
     * @var SemverVersionParser
     */
    private $versionParser;
    /**
     * @var IOInterface|null
     */
    private $io;
    public function __construct(Config $config, ProcessExecutor $process, SemverVersionParser $versionParser, ?IOInterface $io = null)
    {
        $this->config = $config;
        $this->process = $process;
        $this->versionParser = $versionParser;
        $this->io = $io;
    }
    /**
     * @param array<string, mixed> $packageConfig
     * @param string               $path Path to guess into
     *
     * @phpstan-return Version|null
     */
    public function guessVersion(array $packageConfig, string $path): ?array
    {
        if (!function_exists('proc_open')) {
            return null;
        }
        // bypass version guessing in bash completions as it takes time to create
        // new processes and the root version is usually not that important
        if (Platform::isInputCompletionProcess()) {
            return null;
        }
        $versionData = $this->guessGitVersion($packageConfig, $path);
        if (null !== $versionData['version']) {
            return $this->postprocess($versionData);
        }
        $versionData = $this->guessHgVersion($packageConfig, $path);
        if (null !== $versionData && null !== $versionData['version']) {
            return $this->postprocess($versionData);
        }
        $versionData = $this->guessFossilVersion($path);
        if (null !== $versionData['version']) {
            return $this->postprocess($versionData);
        }
        $versionData = $this->guessSvnVersion($packageConfig, $path);
        if (null !== $versionData && null !== $versionData['version']) {
            return $this->postprocess($versionData);
        }
        return null;
    }
    /**
     * @phpstan-param Version $versionData
     *
     * @phpstan-return Version
     */
    private function postprocess(array $versionData): array
    {
        if (!empty($versionData['feature_version']) && $versionData['feature_version'] === $versionData['version'] && $versionData['feature_pretty_version'] === $versionData['pretty_version']) {
            unset($versionData['feature_version'], $versionData['feature_pretty_version']);
        }
        if ('-dev' === substr($versionData['version'], -4) && Preg::isMatch('{\.9{7}}', $versionData['version'])) {
            $versionData['pretty_version'] = Preg::replace('{(\.9{7})+}', '.x', $versionData['version']);
        }
        if (!empty($versionData['feature_version']) && '-dev' === substr($versionData['feature_version'], -4) && Preg::isMatch('{\.9{7}}', $versionData['feature_version'])) {
            $versionData['feature_pretty_version'] = Preg::replace('{(\.9{7})+}', '.x', $versionData['feature_version']);
        }
        return $versionData;
    }
    /**
     * @param array<string, mixed> $packageConfig
     *
     * @return array{version: string|null, commit: string|null, pretty_version: string|null, feature_version?: string|null, feature_pretty_version?: string|null}
     */
    private function guessGitVersion(array $packageConfig, string $path): array
    {
        GitUtil::cleanEnv($this->process);
        $commit = null;
        $version = null;
        $prettyVersion = null;
        $featureVersion = null;
        $featurePrettyVersion = null;
        $isDetached = \false;
        // try to fetch current version from git branch
        if (0 === $this->process->execute(['git', 'branch', '-a', '--no-color', '--no-abbrev', '-v'], $output, $path)) {
            $branches = [];
            $isFeatureBranch = \false;
            // find current branch and collect all branch names
            foreach ($this->process->splitLines($output) as $branch) {
                if ($branch && Preg::isMatchStrictGroups('{^(?:\* ) *(\(no branch\)|\(detached from \S+\)|\(HEAD detached at \S+\)|\S+) *([a-f0-9]+) .*$}', $branch, $match)) {
                    if ($match[1] === '(no branch)' || strpos($match[1], '(detached ') === 0 || strpos($match[1], '(HEAD detached at') === 0) {
                        $version = 'dev-' . $match[2];
                        $prettyVersion = $version;
                        $isFeatureBranch = \true;
                        $isDetached = \true;
                    } else {
                        $version = $this->versionParser->normalizeBranch($match[1]);
                        $prettyVersion = 'dev-' . $match[1];
                        $isFeatureBranch = $this->isFeatureBranch($packageConfig, $match[1]);
                    }
                    $commit = $match[2];
                }
                if ($branch && !Preg::isMatchStrictGroups('{^ *.+/HEAD }', $branch)) {
                    if (Preg::isMatchStrictGroups('{^(?:\* )? *((?:remotes/(?:origin|upstream)/)?[^\s/]+) *([a-f0-9]+) .*$}', $branch, $match)) {
                        $branches[] = $match[1];
                    }
                }
            }
            if ($isFeatureBranch) {
                $featureVersion = $version;
                $featurePrettyVersion = $prettyVersion;
                // try to find the best (nearest) version branch to assume this feature's version
                $result = $this->guessFeatureVersion($packageConfig, $version, $branches, ['git', 'rev-list', '%candidate%..%branch%'], $path);
                $version = $result['version'];
                $prettyVersion = $result['pretty_version'];
            }
        }
        GitUtil::checkForRepoOwnershipError($this->process->getErrorOutput(), $path, $this->io);
        if (!$version || $isDetached) {
            $result = $this->versionFromGitTags($path);
            if ($result) {
                $version = $result['version'];
                $prettyVersion = $result['pretty_version'];
                $featureVersion = null;
                $featurePrettyVersion = null;
            }
        }
        if (null === $commit) {
            $command = GitUtil::buildRevListCommand($this->process, array_merge(['--format=%H', '-n1', 'HEAD'], GitUtil::getNoShowSignatureFlags($this->process)));
            if (0 === $this->process->execute($command, $output, $path)) {
                $commit = trim(GitUtil::parseRevListOutput($output, $this->process)) ?: null;
            }
        }
        if ($featureVersion) {
            return ['version' => $version, 'commit' => $commit, 'pretty_version' => $prettyVersion, 'feature_version' => $featureVersion, 'feature_pretty_version' => $featurePrettyVersion];
        }
        return ['version' => $version, 'commit' => $commit, 'pretty_version' => $prettyVersion];
    }
    /**
     * @return array{version: string, pretty_version: string}|null
     */
    private function versionFromGitTags(string $path): ?array
    {
        // try to fetch current version from git tags
        if (0 === $this->process->execute(['git', 'describe', '--exact-match', '--tags'], $output, $path)) {
            try {
                $version = $this->versionParser->normalize(trim($output));
                return ['version' => $version, 'pretty_version' => trim($output)];
            } catch (\Exception $e) {
            }
        }
        return null;
    }
    /**
     * @param array<string, mixed> $packageConfig
     *
     * @return array{version: string|null, commit: ''|null, pretty_version: string|null, feature_version?: string|null, feature_pretty_version?: string|null}|null
     */
    private function guessHgVersion(array $packageConfig, string $path): ?array
    {
        // try to fetch current version from hg branch
        if (0 === $this->process->execute(['hg', 'branch'], $output, $path)) {
            $branch = trim($output);
            $version = $this->versionParser->normalizeBranch($branch);
            $isFeatureBranch = 0 === strpos($version, 'dev-');
            if (\Composer\Package\Version\VersionParser::DEFAULT_BRANCH_ALIAS === $version) {
                return ['version' => $version, 'commit' => null, 'pretty_version' => 'dev-' . $branch];
            }
            if (!$isFeatureBranch) {
                return ['version' => $version, 'commit' => null, 'pretty_version' => $version];
            }
            // re-use the HgDriver to fetch branches (this properly includes bookmarks)
            $io = new NullIO();
            $driver = new HgDriver(['url' => $path], $io, $this->config, new HttpDownloader($io, $this->config), $this->process);
            $branches = array_map('strval', array_keys($driver->getBranches()));
            // try to find the best (nearest) version branch to assume this feature's version
            $result = $this->guessFeatureVersion($packageConfig, $version, $branches, ['hg', 'log', '-r', 'not ancestors(\'%candidate%\') and ancestors(\'%branch%\')', '--template', '"{node}\n"'], $path);
            $result['commit'] = '';
            $result['feature_version'] = $version;
            $result['feature_pretty_version'] = $version;
            return $result;
        }
        return null;
    }
    /**
     * @param array<string, mixed>     $packageConfig
     * @param list<string>             $branches
     * @param list<string>             $scmCmdline
     *
     * @return array{version: string|null, pretty_version: string|null}
     */
    private function guessFeatureVersion(array $packageConfig, ?string $version, array $branches, array $scmCmdline, string $path): array
    {
        $prettyVersion = $version;
        // ignore feature branches if they have no branch-alias or self.version is used
        // and find the branch they came from to use as a version instead
        if (!isset($packageConfig['extra']['branch-alias'][$version]) || strpos(json_encode($packageConfig), '"self.version"')) {
            $branch = Preg::replace('{^dev-}', '', $version);
            $length = \PHP_INT_MAX;
            // return directly, if branch is configured to be non-feature branch
            if (!$this->isFeatureBranch($packageConfig, $branch)) {
                return ['version' => $version, 'pretty_version' => $prettyVersion];
            }
            // sort local branches first then remote ones
            // and sort numeric branches below named ones, to make sure if the branch has the same distance from main and 1.10 and 1.9 for example, 1.9 is picked
            // and sort using natural sort so that 1.10 will appear before 1.9
            usort($branches, static function ($a, $b): int {
                $aRemote = 0 === strpos($a, 'remotes/');
                $bRemote = 0 === strpos($b, 'remotes/');
                if ($aRemote !== $bRemote) {
                    return $aRemote ? 1 : -1;
                }
                return strnatcasecmp($b, $a);
            });
            $promises = [];
            $this->process->setMaxJobs(30);
            try {
                $lastIndex = -1;
                foreach ($branches as $index => $candidate) {
                    $candidateVersion = Preg::replace('{^remotes/\S+/}', '', $candidate);
                    // do not compare against itself or other feature branches
                    if ($candidate === $branch || $this->isFeatureBranch($packageConfig, $candidateVersion)) {
                        continue;
                    }
                    $cmdLine = array_map(static function (string $component) use ($candidate, $branch) {
                        return str_replace(['%candidate%', '%branch%'], [$candidate, $branch], $component);
                    }, $scmCmdline);
                    $promises[] = $this->process->executeAsync($cmdLine, $path)->then(function (Process $process) use (&$lastIndex, $index, &$length, &$version, &$prettyVersion, $candidateVersion, &$promises): void {
                        if (!$process->isSuccessful()) {
                            return;
                        }
                        $output = $process->getOutput();
                        // overwrite existing if we have a shorter diff, or we have an equal diff and an index that comes later in the array (i.e. older version)
                        // as newer versions typically have more commits, if the feature branch is based on a newer branch it should have a longer diff to the old version
                        // but if it doesn't and they have equal diffs, then it probably is based on the old version
                        if (strlen($output) < $length || strlen($output) === $length && $lastIndex < $index) {
                            $lastIndex = $index;
                            $length = strlen($output);
                            $version = $this->versionParser->normalizeBranch($candidateVersion);
                            $prettyVersion = 'dev-' . $candidateVersion;
                            if ($length === 0) {
                                foreach ($promises as $promise) {
                                    // to support react/promise 2.x we wrap the promise in a resolve() call for safety
                                    \React\Promise\resolve($promise)->cancel();
                                }
                            }
                        }
                    });
                }
                $this->process->wait();
            } finally {
                $this->process->resetMaxJobs();
            }
        }
        return ['version' => $version, 'pretty_version' => $prettyVersion];
    }
    /**
     * @param array<string, mixed> $packageConfig
     */
    private function isFeatureBranch(array $packageConfig, ?string $branchName): bool
    {
        $nonFeatureBranches = '';
        if (!empty($packageConfig['non-feature-branches'])) {
            $nonFeatureBranches = implode('|', $packageConfig['non-feature-branches']);
        }
        return !Preg::isMatch('{^(' . $nonFeatureBranches . '|master|main|latest|next|current|support|tip|trunk|default|develop|\d+\..+)$}', $branchName, $match);
    }
    /**
     * @return array{version: string|null, commit: '', pretty_version: string|null}
     */
    private function guessFossilVersion(string $path): array
    {
        $version = null;
        $prettyVersion = null;
        // try to fetch current version from fossil
        if (0 === $this->process->execute(['fossil', 'branch', 'list'], $output, $path)) {
            $branch = trim($output);
            $version = $this->versionParser->normalizeBranch($branch);
            $prettyVersion = 'dev-' . $branch;
        }
        // try to fetch current version from fossil tags
        if (0 === $this->process->execute(['fossil', 'tag', 'list'], $output, $path)) {
            try {
                $version = $this->versionParser->normalize(trim($output));
                $prettyVersion = trim($output);
            } catch (\Exception $e) {
            }
        }
        return ['version' => $version, 'commit' => '', 'pretty_version' => $prettyVersion];
    }
    /**
     * @param array<string, mixed> $packageConfig
     *
     * @return array{version: string, commit: '', pretty_version: string}|null
     */
    private function guessSvnVersion(array $packageConfig, string $path): ?array
    {
        SvnUtil::cleanEnv();
        // try to fetch current version from svn
        if (0 === $this->process->execute(['svn', 'info', '--xml'], $output, $path)) {
            $trunkPath = isset($packageConfig['trunk-path']) ? preg_quote($packageConfig['trunk-path'], '#') : 'trunk';
            $branchesPath = isset($packageConfig['branches-path']) ? preg_quote($packageConfig['branches-path'], '#') : 'branches';
            $tagsPath = isset($packageConfig['tags-path']) ? preg_quote($packageConfig['tags-path'], '#') : 'tags';
            $urlPattern = '#<url>.*/(' . $trunkPath . '|(' . $branchesPath . '|' . $tagsPath . ')/(.*))</url>#';
            if (Preg::isMatch($urlPattern, $output, $matches)) {
                if (isset($matches[2], $matches[3]) && ($branchesPath === $matches[2] || $tagsPath === $matches[2])) {
                    // we are in a branches path
                    $version = $this->versionParser->normalizeBranch($matches[3]);
                    $prettyVersion = 'dev-' . $matches[3];
                    return ['version' => $version, 'commit' => '', 'pretty_version' => $prettyVersion];
                }
                assert(is_string($matches[1]));
                $prettyVersion = trim($matches[1]);
                if ($prettyVersion === 'trunk') {
                    $version = 'dev-trunk';
                } else {
                    $version = $this->versionParser->normalize($prettyVersion);
                }
                return ['version' => $version, 'commit' => '', 'pretty_version' => $prettyVersion];
            }
        }
        return null;
    }
    public function getRootVersionFromEnv(): string
    {
        $version = Platform::getEnv('COMPOSER_ROOT_VERSION');
        if (!is_string($version) || $version === '') {
            throw new \RuntimeException('COMPOSER_ROOT_VERSION not set or empty');
        }
        if (Preg::isMatch('{^(\d+(?:\.\d+)*)-dev$}i', $version, $match)) {
            $version = $match[1] . '.x-dev';
        }
        return $version;
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer\Package\Version;

use Composer\Filter\PlatformRequirementFilter\IgnoreAllPlatformRequirementFilter;
use Composer\Filter\PlatformRequirementFilter\IgnoreListPlatformRequirementFilter;
use Composer\Filter\PlatformRequirementFilter\PlatformRequirementFilterFactory;
use Composer\Filter\PlatformRequirementFilter\PlatformRequirementFilterInterface;
use Composer\IO\IOInterface;
use Composer\Package\BasePackage;
use Composer\Package\AliasPackage;
use Composer\Package\PackageInterface;
use Composer\Composer;
use Composer\Package\Loader\ArrayLoader;
use Composer\Package\Dumper\ArrayDumper;
use Composer\Pcre\Preg;
use Composer\Repository\RepositorySet;
use Composer\Repository\PlatformRepository;
use Composer\Semver\Constraint\Constraint;
use Composer\Semver\Constraint\ConstraintInterface;
/**
 * Selects the best possible version for a package
 *
 * @author Ryan Weaver <ryan@knpuniversity.com>
 * @author Jordi Boggiano <j.boggiano@seld.be>
 */
class VersionSelector
{
    /** @var RepositorySet */
    private $repositorySet;
    /** @var array<string, ConstraintInterface[]> */
    private $platformConstraints = [];
    /** @var VersionParser */
    private $parser;
    /**
     * @param PlatformRepository $platformRepo If passed in, the versions found will be filtered against their requirements to eliminate any not matching the current platform packages
     */
    public function __construct(RepositorySet $repositorySet, ?PlatformRepository $platformRepo = null)
    {
        $this->repositorySet = $repositorySet;
        if ($platformRepo) {
            foreach ($platformRepo->getPackages() as $package) {
                $this->platformConstraints[$package->getName()][] = new Constraint('==', $package->getVersion());
            }
        }
    }
    /**
     * Given a package name and optional version, returns the latest PackageInterface
     * that matches.
     *
     * @param PlatformRequirementFilterInterface|bool|string[] $platformRequirementFilter
     * @param IOInterface|null                                 $io                        If passed, warnings will be output there in case versions cannot be selected due to platform requirements
     * @param callable(PackageInterface):bool|bool             $showWarnings
     * @return PackageInterface|false
     */
    public function findBestCandidate(string $packageName, ?string $targetPackageVersion = null, string $preferredStability = 'stable', $platformRequirementFilter = null, int $repoSetFlags = 0, ?IOInterface $io = null, $showWarnings = \true)
    {
        if (!isset(BasePackage::STABILITIES[$preferredStability])) {
            // If you get this, maybe you are still relying on the Composer 1.x signature where the 3rd arg was the php version
            throw new \UnexpectedValueException('Expected a valid stability name as 3rd argument, got ' . $preferredStability);
        }
        if (null === $platformRequirementFilter) {
            $platformRequirementFilter = PlatformRequirementFilterFactory::ignoreNothing();
        } elseif (!$platformRequirementFilter instanceof PlatformRequirementFilterInterface) {
            trigger_error('VersionSelector::findBestCandidate with ignored platform reqs as bool|array is deprecated since Composer 2.2, use an instance of PlatformRequirementFilterInterface instead.', \E_USER_DEPRECATED);
            $platformRequirementFilter = PlatformRequirementFilterFactory::fromBoolOrList($platformRequirementFilter);
        }
        $constraint = $targetPackageVersion ? $this->getParser()->parseConstraints($targetPackageVersion) : null;
        $candidates = $this->repositorySet->findPackages(strtolower($packageName), $constraint, $repoSetFlags);
        $minPriority = BasePackage::STABILITIES[$preferredStability];
        usort($candidates, static function (PackageInterface $a, PackageInterface $b) use ($minPriority) {
            $aPriority = $a->getStabilityPriority();
            $bPriority = $b->getStabilityPriority();
            // A is less stable than our preferred stability,
            // and B is more stable than A, select B
            if ($minPriority < $aPriority && $bPriority < $aPriority) {
                return 1;
            }
            // A is less stable than our preferred stability,
            // and B is less stable than A, select A
            if ($minPriority < $aPriority && $aPriority < $bPriority) {
                return -1;
            }
            // A is more stable than our preferred stability,
            // and B is less stable than preferred stability, select A
            if ($minPriority >= $aPriority && $minPriority < $bPriority) {
                return -1;
            }
            // select highest version of the two
            return version_compare($b->getVersion(), $a->getVersion());
        });
        if (count($this->platformConstraints) > 0 && !$platformRequirementFilter instanceof IgnoreAllPlatformRequirementFilter) {
            /** @var array<string, true> $alreadyWarnedNames */
            $alreadyWarnedNames = [];
            /** @var array<string, true> $alreadySeenNames */
            $alreadySeenNames = [];
            foreach ($candidates as $pkg) {
                $reqs = $pkg->getRequires();
                $skip = \false;
                foreach ($reqs as $name => $link) {
                    if (!PlatformRepository::isPlatformPackage($name) || $platformRequirementFilter->isIgnored($name)) {
                        continue;
                    }
                    if (isset($this->platformConstraints[$name])) {
                        foreach ($this->platformConstraints[$name] as $providedConstraint) {
                            if ($link->getConstraint()->matches($providedConstraint)) {
                                // constraint satisfied, go to next require
                                continue 2;
                            }
                            if ($platformRequirementFilter instanceof IgnoreListPlatformRequirementFilter && $platformRequirementFilter->isUpperBoundIgnored($name)) {
                                $filteredConstraint = $platformRequirementFilter->filterConstraint($name, $link->getConstraint());
                                if ($filteredConstraint->matches($providedConstraint)) {
                                    // constraint satisfied with the upper bound ignored, go to next require
                                    continue 2;
                                }
                            }
                        }
                        // constraint not satisfied
                        $reason = 'is not satisfied by your platform';
                    } else {
                        // Package requires a platform package that is unknown on current platform.
                        // It means that current platform cannot validate this constraint and so package is not installable.
                        $reason = 'is missing from your platform';
                    }
                    $isLatestVersion = !isset($alreadySeenNames[$pkg->getName()]);
                    $alreadySeenNames[$pkg->getName()] = \true;
                    if ($io !== null && ($showWarnings === \true || is_callable($showWarnings) && $showWarnings($pkg))) {
                        $isFirstWarning = !isset($alreadyWarnedNames[$pkg->getName() . '/' . $link->getTarget()]);
                        $alreadyWarnedNames[$pkg->getName() . '/' . $link->getTarget()] = \true;
                        $latest = $isLatestVersion ? "'s latest version" : '';
                        $io->writeError('<warning>Cannot use ' . $pkg->getPrettyName() . $latest . ' ' . $pkg->getPrettyVersion() . ' as it ' . $link->getDescription() . ' ' . $link->getTarget() . ' ' . $link->getPrettyConstraint() . ' which ' . $reason . '.</>', \true, $isFirstWarning ? IOInterface::NORMAL : IOInterface::VERBOSE);
                    }
                    // skip candidate
                    $skip = \true;
                }
                if ($skip) {
                    continue;
                }
                $package = $pkg;
                break;
            }
        } else {
            $package = count($candidates) > 0 ? $candidates[0] : null;
        }
        if (!isset($package)) {
            return \false;
        }
        // if we end up with 9999999-dev as selected package, make sure we use the original version instead of the alias
        if ($package instanceof AliasPackage && $package->getVersion() === \Composer\Package\Version\VersionParser::DEFAULT_BRANCH_ALIAS) {
            $package = $package->getAliasOf();
        }
        return $package;
    }
    /**
     * Given a concrete version, this returns a ^ constraint (when possible)
     * that should be used, for example, in composer.json.
     *
     * For example:
     *  * 1.2.1         -> ^1.2
     *  * 1.2.1.2       -> ^1.2
     *  * 1.2           -> ^1.2
     *  * v3.2.1        -> ^3.2
     *  * 2.0-beta.1    -> ^2.0@beta
     *  * dev-master    -> ^2.1@dev      (dev version with alias)
     *  * dev-master    -> dev-master    (dev versions are untouched)
     */
    public function findRecommendedRequireVersion(PackageInterface $package): string
    {
        // Extensions which are versioned in sync with PHP should rather be required as "*" to simplify
        // the requires and have only one required version to change when bumping the php requirement
        if (0 === strpos($package->getName(), 'ext-')) {
            $phpVersion = \PHP_MAJOR_VERSION . '.' . \PHP_MINOR_VERSION . '.' . \PHP_RELEASE_VERSION;
            $extVersion = implode('.', array_slice(explode('.', $package->getVersion()), 0, 3));
            if ($phpVersion === $extVersion) {
                return '*';
            }
        }
        $version = $package->getVersion();
        if (!$package->isDev()) {
            return $this->transformVersion($version, $package->getPrettyVersion(), $package->getStability());
        }
        $loader = new ArrayLoader($this->getParser());
        $dumper = new ArrayDumper();
        $extra = $loader->getBranchAlias($dumper->dump($package));
        if ($extra && $extra !== \Composer\Package\Version\VersionParser::DEFAULT_BRANCH_ALIAS) {
            $extra = Preg::replace('{^(\d+\.\d+\.\d+)(\.9999999)-dev$}', '$1.0', $extra, -1, $count);
            if ($count > 0) {
                $extra = str_replace('.9999999', '.0', $extra);
                return $this->transformVersion($extra, $extra, 'dev');
            }
        }
        return $package->getPrettyVersion();
    }
    private function transformVersion(string $version, string $prettyVersion, string $stability): string
    {
        // attempt to transform 2.1.1 to 2.1
        // this allows you to upgrade through minor versions
        $semanticVersionParts = explode('.', $version);
        // check to see if we have a semver-looking version
        if (count($semanticVersionParts) === 4 && Preg::isMatch('{^\d+\D?}', $semanticVersionParts[3])) {
            // remove the last parts (i.e. the patch version number and any extra)
            if ($semanticVersionParts[0] === '0') {
                unset($semanticVersionParts[3]);
            } else {
                unset($semanticVersionParts[2], $semanticVersionParts[3]);
            }
            $version = implode('.', $semanticVersionParts);
        } else {
            return $prettyVersion;
        }
        // append stability flag if not default
        if ($stability !== 'stable') {
            $version .= '@' . $stability;
        }
        // 2.1 -> ^2.1
        return '^' . $version;
    }
    private function getParser(): \Composer\Package\Version\VersionParser
    {
        if ($this->parser === null) {
            $this->parser = new \Composer\Package\Version\VersionParser();
        }
        return $this->parser;
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer\Package\Version;

use Composer\Pcre\Preg;
use Composer\Repository\PlatformRepository;
use Composer\Semver\VersionParser as SemverVersionParser;
use Composer\Semver\Semver;
use Composer\Semver\Constraint\ConstraintInterface;
class VersionParser extends SemverVersionParser
{
    public const DEFAULT_BRANCH_ALIAS = '9999999-dev';
    /** @var array<string, ConstraintInterface> Constraint parsing cache */
    private static $constraints = [];
    /**
     * @inheritDoc
     */
    public function parseConstraints($constraints): ConstraintInterface
    {
        if (!isset(self::$constraints[$constraints])) {
            self::$constraints[$constraints] = parent::parseConstraints($constraints);
        }
        return self::$constraints[$constraints];
    }
    /**
     * Parses an array of strings representing package/version pairs.
     *
     * The parsing results in an array of arrays, each of which
     * contain a 'name' key with value and optionally a 'version' key with value.
     *
     * @param string[] $pairs a set of package/version pairs separated by ":", "=" or " "
     *
     * @return list<array{name: string, version?: string}>
     */
    public function parseNameVersionPairs(array $pairs): array
    {
        $pairs = array_values($pairs);
        $result = [];
        for ($i = 0, $count = count($pairs); $i < $count; $i++) {
            $pair = Preg::replace('{^([^=: ]+)[=: ](.*)$}', '$1 $2', trim($pairs[$i]));
            if (\false === strpos($pair, ' ') && isset($pairs[$i + 1]) && \false === strpos($pairs[$i + 1], '/') && !Preg::isMatch('{(?<=[a-z0-9_/-])\*|\*(?=[a-z0-9_/-])}i', $pairs[$i + 1]) && !PlatformRepository::isPlatformPackage($pairs[$i + 1])) {
                $pair .= ' ' . $pairs[$i + 1];
                $i++;
            }
            if (strpos($pair, ' ')) {
                [$name, $version] = explode(' ', $pair, 2);
                $result[] = ['name' => $name, 'version' => $version];
            } else {
                $result[] = ['name' => $pair];
            }
        }
        return $result;
    }
    public static function isUpgrade(string $normalizedFrom, string $normalizedTo): bool
    {
        if ($normalizedFrom === $normalizedTo) {
            return \true;
        }
        if (in_array($normalizedFrom, ['dev-master', 'dev-trunk', 'dev-default'], \true)) {
            $normalizedFrom = \Composer\Package\Version\VersionParser::DEFAULT_BRANCH_ALIAS;
        }
        if (in_array($normalizedTo, ['dev-master', 'dev-trunk', 'dev-default'], \true)) {
            $normalizedTo = \Composer\Package\Version\VersionParser::DEFAULT_BRANCH_ALIAS;
        }
        if (strpos($normalizedFrom, 'dev-') === 0 || strpos($normalizedTo, 'dev-') === 0) {
            return \true;
        }
        $sorted = Semver::sort([$normalizedTo, $normalizedFrom]);
        return $sorted[0] === $normalizedFrom;
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer\Package\Loader;

use Composer\Package\BasePackage;
use Composer\Pcre\Preg;
use Composer\Semver\Constraint\Constraint;
use Composer\Package\Version\VersionParser;
use Composer\Repository\PlatformRepository;
use Composer\Semver\Constraint\MatchNoneConstraint;
use Composer\Semver\Intervals;
use Composer\Spdx\SpdxLicenses;
/**
 * @author Jordi Boggiano <j.boggiano@seld.be>
 */
class ValidatingArrayLoader implements \Composer\Package\Loader\LoaderInterface
{
    public const CHECK_ALL = 3;
    public const CHECK_UNBOUND_CONSTRAINTS = 1;
    public const CHECK_STRICT_CONSTRAINTS = 2;
    /** @var LoaderInterface */
    private $loader;
    /** @var VersionParser */
    private $versionParser;
    /** @var list<string> */
    private $errors;
    /** @var list<string> */
    private $warnings;
    /** @var mixed[] */
    private $config;
    /** @var int One or more of self::CHECK_* constants */
    private $flags;
    /**
     * @param true $strictName
     */
    public function __construct(\Composer\Package\Loader\LoaderInterface $loader, bool $strictName = \true, ?VersionParser $parser = null, int $flags = 0)
    {
        $this->loader = $loader;
        $this->versionParser = $parser ?? new VersionParser();
        $this->flags = $flags;
        if ($strictName !== \true) {
            // @phpstan-ignore-line
            trigger_error('$strictName must be set to true in ValidatingArrayLoader\'s constructor as of 2.2, and it will be removed in 3.0', \E_USER_DEPRECATED);
        }
    }
    /**
     * @inheritDoc
     */
    public function load(array $config, string $class = 'Composer\Package\CompletePackage'): BasePackage
    {
        $this->errors = [];
        $this->warnings = [];
        $this->config = $config;
        $this->validateString('name', \true);
        if (isset($config['name']) && null !== $err = self::hasPackageNamingError($config['name'])) {
            $this->errors[] = 'name : ' . $err;
        }
        if (isset($this->config['version'])) {
            if (!is_scalar($this->config['version'])) {
                $this->validateString('version');
            } else {
                if (!is_string($this->config['version'])) {
                    $this->config['version'] = (string) $this->config['version'];
                }
                try {
                    $this->versionParser->normalize($this->config['version']);
                } catch (\Exception $e) {
                    $this->errors[] = 'version : invalid value (' . $this->config['version'] . '): ' . $e->getMessage();
                    unset($this->config['version']);
                }
            }
        }
        if (isset($this->config['config']['platform'])) {
            foreach ((array) $this->config['config']['platform'] as $key => $platform) {
                if (\false === $platform) {
                    continue;
                }
                if (!is_string($platform)) {
                    $this->errors[] = 'config.platform.' . $key . ' : invalid value (' . get_debug_type($platform) . ' ' . var_export($platform, \true) . '): expected string or false';
                    continue;
                }
                try {
                    $this->versionParser->normalize($platform);
                } catch (\Exception $e) {
                    $this->errors[] = 'config.platform.' . $key . ' : invalid value (' . $platform . '): ' . $e->getMessage();
                }
            }
        }
        $this->validateRegex('type', '[A-Za-z0-9-]+');
        $this->validateString('target-dir');
        $this->validateArray('extra');
        if (isset($this->config['bin'])) {
            if (is_string($this->config['bin'])) {
                $this->validateString('bin');
            } else {
                $this->validateFlatArray('bin');
            }
        }
        $this->validateArray('scripts');
        // TODO validate event names & listener syntax
        $this->validateString('description');
        $this->validateUrl('homepage');
        $this->validateFlatArray('keywords', '[\p{N}\p{L} ._-]+');
        $releaseDate = null;
        $this->validateString('time');
        if (isset($this->config['time'])) {
            try {
                $releaseDate = new \DateTime($this->config['time'], new \DateTimeZone('UTC'));
            } catch (\Exception $e) {
                $this->errors[] = 'time : invalid value (' . $this->config['time'] . '): ' . $e->getMessage();
                unset($this->config['time']);
            }
        }
        if (isset($this->config['license'])) {
            // validate main data types
            if (is_array($this->config['license']) || is_string($this->config['license'])) {
                $licenses = (array) $this->config['license'];
                foreach ($licenses as $index => $license) {
                    if (!is_string($license)) {
                        $this->warnings[] = sprintf('License %s should be a string.', json_encode($license));
                        unset($licenses[$index]);
                    }
                }
                // check for license validity on newly updated branches/tags
                if (null === $releaseDate || $releaseDate->getTimestamp() >= strtotime('-8days')) {
                    $licenseValidator = new SpdxLicenses();
                    foreach ($licenses as $license) {
                        // replace proprietary by MIT for validation purposes since it's not a valid SPDX identifier, but is accepted by composer
                        if ('proprietary' === $license) {
                            continue;
                        }
                        $licenseToValidate = str_replace('proprietary', 'MIT', $license);
                        if (!$licenseValidator->validate($licenseToValidate)) {
                            if ($licenseValidator->validate(trim($licenseToValidate))) {
                                $this->warnings[] = sprintf('License %s must not contain extra spaces, make sure to trim it.', json_encode($license));
                            } else {
                                $this->warnings[] = sprintf('License %s is not a valid SPDX license identifier, see https://spdx.org/licenses/ if you use an open license.' . \PHP_EOL . 'If the software is closed-source, you may use "proprietary" as license.', json_encode($license));
                            }
                        }
                    }
                }
                $this->config['license'] = array_values($licenses);
            } else {
                $this->warnings[] = sprintf('License must be a string or array of strings, got %s.', json_encode($this->config['license']));
                unset($this->config['license']);
            }
        }
        if ($this->validateArray('authors')) {
            foreach ($this->config['authors'] as $key => $author) {
                if (!is_array($author)) {
                    $this->errors[] = 'authors.' . $key . ' : should be an array, ' . get_debug_type($author) . ' given';
                    unset($this->config['authors'][$key]);
                    continue;
                }
                foreach (['homepage', 'email', 'name', 'role'] as $authorData) {
                    if (isset($author[$authorData]) && !is_string($author[$authorData])) {
                        $this->errors[] = 'authors.' . $key . '.' . $authorData . ' : invalid value, must be a string';
                        unset($this->config['authors'][$key][$authorData]);
                    }
                }
                if (isset($author['homepage']) && !$this->filterUrl($author['homepage'])) {
                    $this->warnings[] = 'authors.' . $key . '.homepage : invalid value (' . $author['homepage'] . '), must be an http/https URL';
                    unset($this->config['authors'][$key]['homepage']);
                }
                if (isset($author['email']) && \false === filter_var($author['email'], \FILTER_VALIDATE_EMAIL)) {
                    $this->warnings[] = 'authors.' . $key . '.email : invalid value (' . $author['email'] . '), must be a valid email address';
                    unset($this->config['authors'][$key]['email']);
                }
                if (\count($this->config['authors'][$key]) === 0) {
                    unset($this->config['authors'][$key]);
                }
            }
            if (\count($this->config['authors']) === 0) {
                unset($this->config['authors']);
            }
        }
        if ($this->validateArray('support') && !empty($this->config['support'])) {
            foreach (['issues', 'forum', 'wiki', 'source', 'email', 'irc', 'docs', 'rss', 'chat', 'security'] as $key) {
                if (isset($this->config['support'][$key]) && !is_string($this->config['support'][$key])) {
                    $this->errors[] = 'support.' . $key . ' : invalid value, must be a string';
                    unset($this->config['support'][$key]);
                }
            }
            if (isset($this->config['support']['email']) && !filter_var($this->config['support']['email'], \FILTER_VALIDATE_EMAIL)) {
                $this->warnings[] = 'support.email : invalid value (' . $this->config['support']['email'] . '), must be a valid email address';
                unset($this->config['support']['email']);
            }
            if (isset($this->config['support']['irc']) && !$this->filterUrl($this->config['support']['irc'], ['irc', 'ircs'])) {
                $this->warnings[] = 'support.irc : invalid value (' . $this->config['support']['irc'] . '), must be a irc://<server>/<channel> or ircs:// URL';
                unset($this->config['support']['irc']);
            }
            foreach (['issues', 'forum', 'wiki', 'source', 'docs', 'chat', 'security'] as $key) {
                if (isset($this->config['support'][$key]) && !$this->filterUrl($this->config['support'][$key])) {
                    $this->warnings[] = 'support.' . $key . ' : invalid value (' . $this->config['support'][$key] . '), must be an http/https URL';
                    unset($this->config['support'][$key]);
                }
            }
            if (empty($this->config['support'])) {
                unset($this->config['support']);
            }
        }
        if ($this->validateArray('funding') && !empty($this->config['funding'])) {
            foreach ($this->config['funding'] as $key => $fundingOption) {
                if (!is_array($fundingOption)) {
                    $this->errors[] = 'funding.' . $key . ' : should be an array, ' . get_debug_type($fundingOption) . ' given';
                    unset($this->config['funding'][$key]);
                    continue;
                }
                foreach (['type', 'url'] as $fundingData) {
                    if (isset($fundingOption[$fundingData]) && !is_string($fundingOption[$fundingData])) {
                        $this->errors[] = 'funding.' . $key . '.' . $fundingData . ' : invalid value, must be a string';
                        unset($this->config['funding'][$key][$fundingData]);
                    }
                }
                if (isset($fundingOption['url']) && !$this->filterUrl($fundingOption['url'])) {
                    $this->warnings[] = 'funding.' . $key . '.url : invalid value (' . $fundingOption['url'] . '), must be an http/https URL';
                    unset($this->config['funding'][$key]['url']);
                }
                if (empty($this->config['funding'][$key])) {
                    unset($this->config['funding'][$key]);
                }
            }
            if (empty($this->config['funding'])) {
                unset($this->config['funding']);
            }
        }
        if (isset($this->config['php-ext']) && $this->validateArray('php-ext')) {
            if (!in_array($this->config['type'] ?? '', ['php-ext', 'php-ext-zend'], \true)) {
                $this->errors[] = 'php-ext can only be set by packages of type "php-ext" or "php-ext-zend" which must be C extensions';
                unset($this->config['php-ext']);
            }
            $phpExt =& $this->config['php-ext'];
            if (isset($phpExt['extension-name']) && !is_string($phpExt['extension-name'])) {
                $this->errors[] = 'php-ext.extension-name : should be a string, ' . get_debug_type($phpExt['extension-name']) . ' given';
                unset($phpExt['extension-name']);
            }
            if (isset($phpExt['priority']) && !is_int($phpExt['priority'])) {
                $this->errors[] = 'php-ext.priority : should be an integer, ' . get_debug_type($phpExt['priority']) . ' given';
                unset($phpExt['priority']);
            }
            if (isset($phpExt['support-zts']) && !is_bool($phpExt['support-zts'])) {
                $this->errors[] = 'php-ext.support-zts : should be a boolean, ' . get_debug_type($phpExt['support-zts']) . ' given';
                unset($phpExt['support-zts']);
            }
            if (isset($phpExt['support-nts']) && !is_bool($phpExt['support-nts'])) {
                $this->errors[] = 'php-ext.support-nts : should be a boolean, ' . get_debug_type($phpExt['support-nts']) . ' given';
                unset($phpExt['support-nts']);
            }
            if (isset($phpExt['build-path']) && !is_string($phpExt['build-path']) && !is_null($phpExt['build-path'])) {
                $this->errors[] = 'php-ext.build-path : should be a string or null, ' . get_debug_type($phpExt['build-path']) . ' given';
                unset($phpExt['build-path']);
            }
            if (isset($phpExt['download-url-method'])) {
                if (!is_array($phpExt['download-url-method']) && !is_string($phpExt['download-url-method'])) {
                    $this->errors[] = 'php-ext.download-url-method : should be an array or a string, ' . get_debug_type($phpExt['download-url-method']) . ' given';
                    unset($phpExt['download-url-method']);
                } else {
                    $validDownloadUrlMethods = ['composer-default', 'pre-packaged-source', 'pre-packaged-binary'];
                    $definedDownloadUrlMethods = is_array($phpExt['download-url-method']) ? $phpExt['download-url-method'] : [$phpExt['download-url-method']];
                    if ([] === $definedDownloadUrlMethods) {
                        $this->errors[] = 'php-ext.download-url-method : must contain at least one element';
                        unset($phpExt['download-url-method']);
                    } else {
                        foreach ($definedDownloadUrlMethods as $key => $downloadUrlMethod) {
                            if (!is_string($downloadUrlMethod)) {
                                $this->errors[] = 'php-ext.download-url-method.' . $key . ' : should be a string, ' . get_debug_type($downloadUrlMethod) . ' given';
                                unset($phpExt['download-url-method']);
                            } elseif (!in_array($downloadUrlMethod, $validDownloadUrlMethods, \true)) {
                                $this->errors[] = 'php-ext.download-url-method.' . $key . ' : invalid value (' . $downloadUrlMethod . '), must be one of ' . implode(', ', $validDownloadUrlMethods);
                                unset($phpExt['download-url-method']);
                            }
                        }
                    }
                }
            }
            if (isset($phpExt['os-families']) && isset($phpExt['os-families-exclude'])) {
                $this->errors[] = 'php-ext : os-families and os-families-exclude cannot both be specified';
                unset($phpExt['os-families'], $phpExt['os-families-exclude']);
            } else {
                $validOsFamilies = ['windows', 'bsd', 'darwin', 'solaris', 'linux', 'unknown'];
                foreach (['os-families', 'os-families-exclude'] as $fieldName) {
                    if (isset($phpExt[$fieldName])) {
                        if (!is_array($phpExt[$fieldName])) {
                            $this->errors[] = 'php-ext.' . $fieldName . ' : should be an array, ' . get_debug_type($phpExt[$fieldName]) . ' given';
                            unset($phpExt[$fieldName]);
                        } elseif ([] === $phpExt[$fieldName]) {
                            $this->errors[] = 'php-ext.' . $fieldName . ' : must contain at least one element';
                            unset($phpExt[$fieldName]);
                        } else {
                            foreach ($phpExt[$fieldName] as $key => $osFamily) {
                                if (!is_string($osFamily)) {
                                    $this->errors[] = 'php-ext.' . $fieldName . '.' . $key . ' : should be a string, ' . get_debug_type($osFamily) . ' given';
                                    unset($phpExt[$fieldName][$key]);
                                } elseif (!in_array($osFamily, $validOsFamilies, \true)) {
                                    $this->errors[] = 'php-ext.' . $fieldName . '.' . $key . ' : invalid value (' . $osFamily . '), must be one of ' . implode(', ', $validOsFamilies);
                                    unset($phpExt[$fieldName][$key]);
                                }
                            }
                            if ([] === $phpExt[$fieldName]) {
                                unset($phpExt[$fieldName]);
                            }
                        }
                    }
                }
            }
            if (isset($phpExt['configure-options'])) {
                if (!is_array($phpExt['configure-options'])) {
                    $this->errors[] = 'php-ext.configure-options : should be an array, ' . get_debug_type($phpExt['configure-options']) . ' given';
                    unset($phpExt['configure-options']);
                } else {
                    foreach ($phpExt['configure-options'] as $key => $option) {
                        if (!is_array($option)) {
                            $this->errors[] = 'php-ext.configure-options.' . $key . ' : should be an array, ' . get_debug_type($option) . ' given';
                            unset($phpExt['configure-options'][$key]);
                            continue;
                        }
                        if (!isset($option['name'])) {
                            $this->errors[] = 'php-ext.configure-options.' . $key . '.name : must be present';
                            unset($phpExt['configure-options'][$key]);
                            continue;
                        }
                        if (!is_string($option['name'])) {
                            $this->errors[] = 'php-ext.configure-options.' . $key . '.name : should be a string, ' . get_debug_type($option['name']) . ' given';
                            unset($phpExt['configure-options'][$key]);
                            continue;
                        }
                        if (isset($option['needs-value']) && !is_bool($option['needs-value'])) {
                            $this->errors[] = 'php-ext.configure-options.' . $key . '.needs-value : should be a boolean, ' . get_debug_type($option['needs-value']) . ' given';
                            unset($phpExt['configure-options'][$key]['needs-value']);
                        }
                        if (isset($option['description']) && !is_string($option['description'])) {
                            $this->errors[] = 'php-ext.configure-options.' . $key . '.description : should be a string, ' . get_debug_type($option['description']) . ' given';
                            unset($phpExt['configure-options'][$key]['description']);
                        }
                    }
                    if ([] === $phpExt['configure-options']) {
                        unset($phpExt['configure-options']);
                    }
                }
            }
            // If php-ext is now empty, unset it
            if ([] === $phpExt) {
                unset($this->config['php-ext']);
            }
            unset($phpExt);
        }
        $unboundConstraint = new Constraint('=', '10000000-dev');
        foreach (array_keys(BasePackage::$supportedLinkTypes) as $linkType) {
            if ($this->validateArray($linkType) && isset($this->config[$linkType])) {
                foreach ($this->config[$linkType] as $package => $constraint) {
                    $package = (string) $package;
                    if (isset($this->config['name']) && 0 === strcasecmp($package, $this->config['name'])) {
                        $this->errors[] = $linkType . '.' . $package . ' : a package cannot set a ' . $linkType . ' on itself';
                        unset($this->config[$linkType][$package]);
                        continue;
                    }
                    if ($err = self::hasPackageNamingError($package, \true)) {
                        $this->warnings[] = $linkType . '.' . $err;
                    } elseif (!Preg::isMatch('{^[A-Za-z0-9_./-]+$}', $package)) {
                        $this->errors[] = $linkType . '.' . $package . ' : invalid key, package names must be strings containing only [A-Za-z0-9_./-]';
                    }
                    if (!is_string($constraint)) {
                        $this->errors[] = $linkType . '.' . $package . ' : invalid value, must be a string containing a version constraint';
                        unset($this->config[$linkType][$package]);
                    } elseif ('self.version' !== $constraint) {
                        try {
                            $linkConstraint = $this->versionParser->parseConstraints($constraint);
                        } catch (\Exception $e) {
                            $this->errors[] = $linkType . '.' . $package . ' : invalid version constraint (' . $e->getMessage() . ')';
                            unset($this->config[$linkType][$package]);
                            continue;
                        }
                        // check requires for unbound constraints on non-platform packages
                        if ($this->flags & self::CHECK_UNBOUND_CONSTRAINTS && 'require' === $linkType && $linkConstraint->matches($unboundConstraint) && !PlatformRepository::isPlatformPackage($package)) {
                            $this->warnings[] = $linkType . '.' . $package . ' : unbound version constraints (' . $constraint . ') should be avoided';
                        } elseif ($this->flags & self::CHECK_STRICT_CONSTRAINTS && 'require' === $linkType && $linkConstraint instanceof Constraint && in_array($linkConstraint->getOperator(), ['==', '='], \true) && (new Constraint('>=', '1.0.0.0-dev'))->matches($linkConstraint)) {
                            $this->warnings[] = $linkType . '.' . $package . ' : exact version constraints (' . $constraint . ') should be avoided if the package follows semantic versioning';
                        }
                        $compacted = Intervals::compactConstraint($linkConstraint);
                        if ($compacted instanceof MatchNoneConstraint) {
                            $this->warnings[] = $linkType . '.' . $package . ' : this version constraint cannot possibly match anything (' . $constraint . ')';
                        }
                    }
                    if ($linkType === 'conflict' && isset($this->config['replace']) && $keys = array_intersect_key($this->config['replace'], $this->config['conflict'])) {
                        $this->errors[] = $linkType . '.' . $package . ' : you cannot conflict with a package that is also replaced, as replace already creates an implicit conflict rule';
                        unset($this->config[$linkType][$package]);
                    }
                }
            }
        }
        if ($this->validateArray('suggest') && isset($this->config['suggest'])) {
            foreach ($this->config['suggest'] as $package => $description) {
                if (!is_string($description)) {
                    $this->errors[] = 'suggest.' . $package . ' : invalid value, must be a string describing why the package is suggested';
                    unset($this->config['suggest'][$package]);
                }
            }
        }
        if ($this->validateString('minimum-stability') && isset($this->config['minimum-stability'])) {
            if (!isset(BasePackage::STABILITIES[strtolower($this->config['minimum-stability'])]) && $this->config['minimum-stability'] !== 'RC') {
                $this->errors[] = 'minimum-stability : invalid value (' . $this->config['minimum-stability'] . '), must be one of ' . implode(', ', array_keys(BasePackage::STABILITIES));
                unset($this->config['minimum-stability']);
            }
        }
        if ($this->validateArray('autoload') && isset($this->config['autoload'])) {
            $types = ['psr-0', 'psr-4', 'classmap', 'files', 'exclude-from-classmap'];
            foreach ($this->config['autoload'] as $type => $typeConfig) {
                if (!in_array($type, $types)) {
                    $this->errors[] = 'autoload : invalid value (' . $type . '), must be one of ' . implode(', ', $types);
                    unset($this->config['autoload'][$type]);
                }
                if ($type === 'psr-4') {
                    foreach ($typeConfig as $namespace => $dirs) {
                        if ($namespace !== '' && '\\' !== substr((string) $namespace, -1)) {
                            $this->errors[] = 'autoload.psr-4 : invalid value (' . $namespace . '), namespaces must end with a namespace separator, should be ' . $namespace . '\\\\';
                        }
                    }
                }
            }
        }
        if (isset($this->config['autoload']['psr-4']) && isset($this->config['target-dir'])) {
            $this->errors[] = 'target-dir : this can not be used together with the autoload.psr-4 setting, remove target-dir to upgrade to psr-4';
            // Unset the psr-4 setting, since unsetting target-dir might
            // interfere with other settings.
            unset($this->config['autoload']['psr-4']);
        }
        foreach (['source', 'dist'] as $srcType) {
            if ($this->validateArray($srcType) && !empty($this->config[$srcType])) {
                if (!isset($this->config[$srcType]['type'])) {
                    $this->errors[] = $srcType . '.type : must be present';
                }
                if (!isset($this->config[$srcType]['url'])) {
                    $this->errors[] = $srcType . '.url : must be present';
                }
                if ($srcType === 'source' && !isset($this->config[$srcType]['reference'])) {
                    $this->errors[] = $srcType . '.reference : must be present';
                }
                if (isset($this->config[$srcType]['type']) && !is_string($this->config[$srcType]['type'])) {
                    $this->errors[] = $srcType . '.type : should be a string, ' . get_debug_type($this->config[$srcType]['type']) . ' given';
                }
                if (isset($this->config[$srcType]['url']) && !is_string($this->config[$srcType]['url'])) {
                    $this->errors[] = $srcType . '.url : should be a string, ' . get_debug_type($this->config[$srcType]['url']) . ' given';
                }
                if (isset($this->config[$srcType]['reference']) && !is_string($this->config[$srcType]['reference']) && !is_int($this->config[$srcType]['reference'])) {
                    $this->errors[] = $srcType . '.reference : should be a string or int, ' . get_debug_type($this->config[$srcType]['reference']) . ' given';
                }
                if (isset($this->config[$srcType]['reference']) && Preg::isMatch('{^\s*-}', (string) $this->config[$srcType]['reference'])) {
                    $this->errors[] = $srcType . '.reference : must not start with a "-", "' . $this->config[$srcType]['reference'] . '" given';
                }
                if (isset($this->config[$srcType]['url']) && Preg::isMatch('{^\s*-}', (string) $this->config[$srcType]['url'])) {
                    $this->errors[] = $srcType . '.url : must not start with a "-", "' . $this->config[$srcType]['url'] . '" given';
                }
            }
        }
        // TODO validate repositories
        // TODO validate package repositories' packages using this recursively
        $this->validateFlatArray('include-path');
        $this->validateArray('transport-options');
        // branch alias validation
        if (isset($this->config['extra']['branch-alias'])) {
            if (!is_array($this->config['extra']['branch-alias'])) {
                $this->errors[] = 'extra.branch-alias : must be an array of versions => aliases';
            } else {
                foreach ($this->config['extra']['branch-alias'] as $sourceBranch => $targetBranch) {
                    if (!is_string($targetBranch)) {
                        $this->warnings[] = 'extra.branch-alias.' . $sourceBranch . ' : the target branch (' . json_encode($targetBranch) . ') must be a string, "' . get_debug_type($targetBranch) . '" received.';
                        unset($this->config['extra']['branch-alias'][$sourceBranch]);
                        continue;
                    }
                    // ensure it is an alias to a -dev package
                    if ('-dev' !== substr($targetBranch, -4)) {
                        $this->warnings[] = 'extra.branch-alias.' . $sourceBranch . ' : the target branch (' . $targetBranch . ') must end in -dev';
                        unset($this->config['extra']['branch-alias'][$sourceBranch]);
                        continue;
                    }
                    // normalize without -dev and ensure it's a numeric branch that is parseable
                    $validatedTargetBranch = $this->versionParser->normalizeBranch(substr($targetBranch, 0, -4));
                    if ('-dev' !== substr($validatedTargetBranch, -4)) {
                        $this->warnings[] = 'extra.branch-alias.' . $sourceBranch . ' : the target branch (' . $targetBranch . ') must be a parseable number like 2.0-dev';
                        unset($this->config['extra']['branch-alias'][$sourceBranch]);
                        continue;
                    }
                    // If using numeric aliases ensure the alias is a valid subversion
                    if (($sourcePrefix = $this->versionParser->parseNumericAliasPrefix($sourceBranch)) && ($targetPrefix = $this->versionParser->parseNumericAliasPrefix($targetBranch)) && stripos($targetPrefix, $sourcePrefix) !== 0) {
                        $this->warnings[] = 'extra.branch-alias.' . $sourceBranch . ' : the target branch (' . $targetBranch . ') is not a valid numeric alias for this version';
                        unset($this->config['extra']['branch-alias'][$sourceBranch]);
                    }
                }
            }
        }
        if ($this->errors) {
            throw new \Composer\Package\Loader\InvalidPackageException($this->errors, $this->warnings, $config);
        }
        $package = $this->loader->load($this->config, $class);
        $this->config = [];
        return $package;
    }
    /**
     * @return list<string>
     */
    public function getWarnings(): array
    {
        return $this->warnings;
    }
    /**
     * @return list<string>
     */
    public function getErrors(): array
    {
        return $this->errors;
    }
    public static function hasPackageNamingError(string $name, bool $isLink = \false): ?string
    {
        if (PlatformRepository::isPlatformPackage($name)) {
            return null;
        }
        if (!Preg::isMatch('{^[a-z0-9](?:[_.-]?[a-z0-9]++)*+/[a-z0-9](?:(?:[_.]|-{1,2})?[a-z0-9]++)*+$}iD', $name)) {
            return $name . ' is invalid, it should have a vendor name, a forward slash, and a package name. The vendor and package name can be words separated by -, . or _. The complete name should match "^[a-z0-9]([_.-]?[a-z0-9]+)*/[a-z0-9](([_.]?|-{0,2})[a-z0-9]+)*$".';
        }
        $reservedNames = ['nul', 'con', 'prn', 'aux', 'com1', 'com2', 'com3', 'com4', 'com5', 'com6', 'com7', 'com8', 'com9', 'lpt1', 'lpt2', 'lpt3', 'lpt4', 'lpt5', 'lpt6', 'lpt7', 'lpt8', 'lpt9'];
        $bits = explode('/', strtolower($name));
        if (in_array($bits[0], $reservedNames, \true) || in_array($bits[1], $reservedNames, \true)) {
            return $name . ' is reserved, package and vendor names can not match any of: ' . implode(', ', $reservedNames) . '.';
        }
        if (Preg::isMatch('{\.json$}', $name)) {
            return $name . ' is invalid, package names can not end in .json, consider renaming it or perhaps using a -json suffix instead.';
        }
        if (Preg::isMatch('{[A-Z]}', $name)) {
            if ($isLink) {
                return $name . ' is invalid, it should not contain uppercase characters. Please use ' . strtolower($name) . ' instead.';
            }
            $suggestName = Preg::replace('{(?:([a-z])([A-Z])|([A-Z])([A-Z][a-z]))}', '\1\3-\2\4', $name);
            $suggestName = strtolower($suggestName);
            return $name . ' is invalid, it should not contain uppercase characters. We suggest using ' . $suggestName . ' instead.';
        }
        return null;
    }
    /**
     * @phpstan-param non-empty-string $property
     * @phpstan-param non-empty-string $regex
     */
    private function validateRegex(string $property, string $regex, bool $mandatory = \false): bool
    {
        if (!$this->validateString($property, $mandatory)) {
            return \false;
        }
        if (!Preg::isMatch('{^' . $regex . '$}u', $this->config[$property])) {
            $message = $property . ' : invalid value (' . $this->config[$property] . '), must match ' . $regex;
            if ($mandatory) {
                $this->errors[] = $message;
            } else {
                $this->warnings[] = $message;
            }
            unset($this->config[$property]);
            return \false;
        }
        return \true;
    }
    /**
     * @phpstan-param non-empty-string $property
     */
    private function validateString(string $property, bool $mandatory = \false): bool
    {
        if (isset($this->config[$property]) && !is_string($this->config[$property])) {
            $this->errors[] = $property . ' : should be a string, ' . get_debug_type($this->config[$property]) . ' given';
            unset($this->config[$property]);
            return \false;
        }
        if (!isset($this->config[$property]) || trim($this->config[$property]) === '') {
            if ($mandatory) {
                $this->errors[] = $property . ' : must be present';
            }
            unset($this->config[$property]);
            return \false;
        }
        return \true;
    }
    /**
     * @phpstan-param non-empty-string $property
     */
    private function validateArray(string $property, bool $mandatory = \false): bool
    {
        if (isset($this->config[$property]) && !is_array($this->config[$property])) {
            $this->errors[] = $property . ' : should be an array, ' . get_debug_type($this->config[$property]) . ' given';
            unset($this->config[$property]);
            return \false;
        }
        if (!isset($this->config[$property]) || !count($this->config[$property])) {
            if ($mandatory) {
                $this->errors[] = $property . ' : must be present and contain at least one element';
            }
            unset($this->config[$property]);
            return \false;
        }
        return \true;
    }
    /**
     * @phpstan-param non-empty-string      $property
     * @phpstan-param non-empty-string|null $regex
     */
    private function validateFlatArray(string $property, ?string $regex = null, bool $mandatory = \false): bool
    {
        if (!$this->validateArray($property, $mandatory)) {
            return \false;
        }
        $pass = \true;
        foreach ($this->config[$property] as $key => $value) {
            if (!is_string($value) && !is_numeric($value)) {
                $this->errors[] = $property . '.' . $key . ' : must be a string or int, ' . get_debug_type($value) . ' given';
                unset($this->config[$property][$key]);
                $pass = \false;
                continue;
            }
            if ($regex && !Preg::isMatch('{^' . $regex . '$}u', (string) $value)) {
                $this->warnings[] = $property . '.' . $key . ' : invalid value (' . $value . '), must match ' . $regex;
                unset($this->config[$property][$key]);
                $pass = \false;
            }
        }
        return $pass;
    }
    /**
     * @phpstan-param non-empty-string $property
     */
    private function validateUrl(string $property, bool $mandatory = \false): bool
    {
        if (!$this->validateString($property, $mandatory)) {
            return \false;
        }
        if (!$this->filterUrl($this->config[$property])) {
            $this->warnings[] = $property . ' : invalid value (' . $this->config[$property] . '), must be an http/https URL';
            unset($this->config[$property]);
            return \false;
        }
        return \true;
    }
    /**
     * @param mixed    $value
     * @param string[] $schemes
     */
    private function filterUrl($value, array $schemes = ['http', 'https']): bool
    {
        if ($value === '') {
            return \true;
        }
        $bits = parse_url($value);
        if (empty($bits['scheme']) || empty($bits['host'])) {
            return \false;
        }
        if (!in_array($bits['scheme'], $schemes, \true)) {
            return \false;
        }
        return \true;
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer\Package\Loader;

/**
 * @author Jordi Boggiano <j.boggiano@seld.be>
 */
class InvalidPackageException extends \Exception
{
    /** @var list<string> */
    private $errors;
    /** @var list<string> */
    private $warnings;
    /** @var mixed[] package config */
    private $data;
    /**
     * @param list<string> $errors
     * @param list<string> $warnings
     * @param mixed[]  $data
     */
    public function __construct(array $errors, array $warnings, array $data)
    {
        $this->errors = $errors;
        $this->warnings = $warnings;
        $this->data = $data;
        parent::__construct("Invalid package information: \n" . implode("\n", array_merge($errors, $warnings)));
    }
    /**
     * @return mixed[]
     */
    public function getData(): array
    {
        return $this->data;
    }
    /**
     * @return list<string>
     */
    public function getErrors(): array
    {
        return $this->errors;
    }
    /**
     * @return list<string>
     */
    public function getWarnings(): array
    {
        return $this->warnings;
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer\Package\Loader;

use Composer\Package\BasePackage;
use Composer\Package\CompleteAliasPackage;
use Composer\Package\CompletePackage;
use Composer\Package\RootPackage;
use Composer\Package\PackageInterface;
use Composer\Package\CompletePackageInterface;
use Composer\Package\Link;
use Composer\Package\RootAliasPackage;
use Composer\Package\Version\VersionParser;
use Composer\Pcre\Preg;
/**
 * @author Konstantin Kudryashiv <ever.zet@gmail.com>
 * @author Jordi Boggiano <j.boggiano@seld.be>
 */
class ArrayLoader implements \Composer\Package\Loader\LoaderInterface
{
    /** @var VersionParser */
    protected $versionParser;
    /** @var bool */
    protected $loadOptions;
    public function __construct(?VersionParser $parser = null, bool $loadOptions = \false)
    {
        if (!$parser) {
            $parser = new VersionParser();
        }
        $this->versionParser = $parser;
        $this->loadOptions = $loadOptions;
    }
    /**
     * @inheritDoc
     */
    public function load(array $config, string $class = 'Composer\Package\CompletePackage'): BasePackage
    {
        if ($class !== 'Composer\Package\CompletePackage' && $class !== 'Composer\Package\RootPackage') {
            trigger_error('The $class arg is deprecated, please reach out to Composer maintainers ASAP if you still need this.', \E_USER_DEPRECATED);
        }
        $package = $this->createObject($config, $class);
        foreach (BasePackage::$supportedLinkTypes as $type => $opts) {
            if (!isset($config[$type]) || !is_array($config[$type])) {
                continue;
            }
            $method = 'set' . ucfirst($opts['method']);
            $package->{$method}($this->parseLinks($package->getName(), $package->getPrettyVersion(), $opts['method'], $config[$type]));
        }
        $package = $this->configureObject($package, $config);
        return $package;
    }
    /**
     * @param array<array<mixed>> $versions
     *
     * @return list<CompletePackage|CompleteAliasPackage>
     */
    public function loadPackages(array $versions): array
    {
        $packages = [];
        $linkCache = [];
        foreach ($versions as $version) {
            $package = $this->createObject($version, 'Composer\Package\CompletePackage');
            $this->configureCachedLinks($linkCache, $package, $version);
            $package = $this->configureObject($package, $version);
            $packages[] = $package;
        }
        return $packages;
    }
    /**
     * @template PackageClass of CompletePackage
     *
     * @param mixed[] $config package data
     * @param string  $class  FQCN to be instantiated
     *
     * @return CompletePackage|RootPackage
     *
     * @phpstan-param class-string<PackageClass> $class
     */
    private function createObject(array $config, string $class): CompletePackage
    {
        if (!isset($config['name'])) {
            throw new \UnexpectedValueException('Unknown package has no name defined (' . json_encode($config) . ').');
        }
        if (!isset($config['version']) || !is_scalar($config['version'])) {
            throw new \UnexpectedValueException('Package ' . $config['name'] . ' has no version defined.');
        }
        if (!is_string($config['version'])) {
            $config['version'] = (string) $config['version'];
        }
        // handle already normalized versions
        if (isset($config['version_normalized']) && is_string($config['version_normalized'])) {
            $version = $config['version_normalized'];
            // handling of existing repos which need to remain composer v1 compatible, in case the version_normalized contained VersionParser::DEFAULT_BRANCH_ALIAS, we renormalize it
            if ($version === VersionParser::DEFAULT_BRANCH_ALIAS) {
                $version = $this->versionParser->normalize($config['version']);
            }
        } else {
            try {
                $version = $this->versionParser->normalize($config['version']);
            } catch (\UnexpectedValueException $e) {
                throw new \UnexpectedValueException('Failed to normalize version for package "' . $config['name'] . '": ' . $e->getMessage(), $e->getCode(), $e);
            }
        }
        return new $class($config['name'], $version, $config['version']);
    }
    /**
     * @param CompletePackage $package
     * @param mixed[]         $config package data
     *
     * @return RootPackage|RootAliasPackage|CompletePackage|CompleteAliasPackage
     */
    private function configureObject(PackageInterface $package, array $config): BasePackage
    {
        if (!$package instanceof CompletePackage) {
            throw new \LogicException('ArrayLoader expects instances of the _ContaoManager\Composer\Package\CompletePackage class to function correctly');
        }
        $package->setType(isset($config['type']) ? strtolower($config['type']) : 'library');
        if (isset($config['target-dir'])) {
            $package->setTargetDir($config['target-dir']);
        }
        if (isset($config['extra']) && \is_array($config['extra'])) {
            $package->setExtra($config['extra']);
        }
        if (isset($config['bin'])) {
            if (!\is_array($config['bin'])) {
                $config['bin'] = [$config['bin']];
            }
            foreach ($config['bin'] as $key => $bin) {
                $config['bin'][$key] = ltrim($bin, '/');
            }
            $package->setBinaries($config['bin']);
        }
        if (isset($config['installation-source'])) {
            $package->setInstallationSource($config['installation-source']);
        }
        if (isset($config['default-branch']) && $config['default-branch'] === \true) {
            $package->setIsDefaultBranch(\true);
        }
        if (isset($config['source'])) {
            if (!isset($config['source']['type'], $config['source']['url'], $config['source']['reference'])) {
                throw new \UnexpectedValueException(sprintf("Package %s's source key should be specified as {\"type\": ..., \"url\": ..., \"reference\": ...},\n%s given.", $config['name'], json_encode($config['source'])));
            }
            $package->setSourceType($config['source']['type']);
            $package->setSourceUrl($config['source']['url']);
            $package->setSourceReference(isset($config['source']['reference']) ? (string) $config['source']['reference'] : null);
            if (isset($config['source']['mirrors'])) {
                $package->setSourceMirrors($config['source']['mirrors']);
            }
        }
        if (isset($config['dist'])) {
            if (!isset($config['dist']['type'], $config['dist']['url'])) {
                throw new \UnexpectedValueException(sprintf("Package %s's dist key should be specified as " . "{\"type\": ..., \"url\": ..., \"reference\": ..., \"shasum\": ...},\n%s given.", $config['name'], json_encode($config['dist'])));
            }
            $package->setDistType($config['dist']['type']);
            $package->setDistUrl($config['dist']['url']);
            $package->setDistReference(isset($config['dist']['reference']) ? (string) $config['dist']['reference'] : null);
            $package->setDistSha1Checksum($config['dist']['shasum'] ?? null);
            if (isset($config['dist']['mirrors'])) {
                $package->setDistMirrors($config['dist']['mirrors']);
            }
        }
        if (isset($config['suggest']) && \is_array($config['suggest'])) {
            foreach ($config['suggest'] as $target => $reason) {
                if ('self.version' === trim($reason)) {
                    $config['suggest'][$target] = $package->getPrettyVersion();
                }
            }
            $package->setSuggests($config['suggest']);
        }
        if (isset($config['autoload'])) {
            $package->setAutoload($config['autoload']);
        }
        if (isset($config['autoload-dev'])) {
            $package->setDevAutoload($config['autoload-dev']);
        }
        if (isset($config['include-path'])) {
            $package->setIncludePaths($config['include-path']);
        }
        if (isset($config['php-ext'])) {
            $package->setPhpExt($config['php-ext']);
        }
        if (!empty($config['time'])) {
            $time = Preg::isMatch('/^\d++$/D', $config['time']) ? '@' . $config['time'] : $config['time'];
            try {
                $date = new \DateTime($time, new \DateTimeZone('UTC'));
                $package->setReleaseDate($date);
            } catch (\Exception $e) {
            }
        }
        if (!empty($config['notification-url'])) {
            $package->setNotificationUrl($config['notification-url']);
        }
        if ($package instanceof CompletePackageInterface) {
            if (!empty($config['archive']['name'])) {
                $package->setArchiveName($config['archive']['name']);
            }
            if (!empty($config['archive']['exclude'])) {
                $package->setArchiveExcludes($config['archive']['exclude']);
            }
            if (isset($config['scripts']) && \is_array($config['scripts'])) {
                foreach ($config['scripts'] as $event => $listeners) {
                    $config['scripts'][$event] = (array) $listeners;
                }
                foreach (['composer', 'php', 'putenv'] as $reserved) {
                    if (isset($config['scripts'][$reserved])) {
                        trigger_error('The `' . $reserved . '` script name is reserved for internal use, please avoid defining it', \E_USER_DEPRECATED);
                    }
                }
                $package->setScripts($config['scripts']);
            }
            if (!empty($config['description']) && \is_string($config['description'])) {
                $package->setDescription($config['description']);
            }
            if (!empty($config['homepage']) && \is_string($config['homepage'])) {
                $package->setHomepage($config['homepage']);
            }
            if (!empty($config['keywords']) && \is_array($config['keywords'])) {
                $package->setKeywords(array_map('strval', $config['keywords']));
            }
            if (!empty($config['license'])) {
                $package->setLicense(\is_array($config['license']) ? $config['license'] : [$config['license']]);
            }
            if (!empty($config['authors']) && \is_array($config['authors'])) {
                $package->setAuthors($config['authors']);
            }
            if (isset($config['support']) && \is_array($config['support'])) {
                $package->setSupport($config['support']);
            }
            if (!empty($config['funding']) && \is_array($config['funding'])) {
                $package->setFunding($config['funding']);
            }
            if (isset($config['abandoned'])) {
                $package->setAbandoned($config['abandoned']);
            }
        }
        if ($this->loadOptions && isset($config['transport-options'])) {
            $package->setTransportOptions($config['transport-options']);
        }
        if ($aliasNormalized = $this->getBranchAlias($config)) {
            $prettyAlias = Preg::replace('{(\.9{7})+}', '.x', $aliasNormalized);
            if ($package instanceof RootPackage) {
                return new RootAliasPackage($package, $aliasNormalized, $prettyAlias);
            }
            return new CompleteAliasPackage($package, $aliasNormalized, $prettyAlias);
        }
        return $package;
    }
    /**
     * @param array<string, array<string, array<int|string, array<int|string, array{string, Link}>>>> $linkCache
     * @param mixed[]                                                                             $config
     */
    private function configureCachedLinks(array &$linkCache, PackageInterface $package, array $config): void
    {
        $name = $package->getName();
        $prettyVersion = $package->getPrettyVersion();
        foreach (BasePackage::$supportedLinkTypes as $type => $opts) {
            if (isset($config[$type])) {
                $method = 'set' . ucfirst($opts['method']);
                $links = [];
                foreach ($config[$type] as $prettyTarget => $constraint) {
                    $target = strtolower($prettyTarget);
                    // recursive links are not supported
                    if ($target === $name) {
                        continue;
                    }
                    if ($constraint === 'self.version') {
                        $links[$target] = $this->createLink($name, $prettyVersion, $opts['method'], $target, $constraint);
                    } else {
                        if (!isset($linkCache[$name][$type][$target][$constraint])) {
                            $linkCache[$name][$type][$target][$constraint] = [$target, $this->createLink($name, $prettyVersion, $opts['method'], $target, $constraint)];
                        }
                        [$target, $link] = $linkCache[$name][$type][$target][$constraint];
                        $links[$target] = $link;
                    }
                }
                $package->{$method}($links);
            }
        }
    }
    /**
     * @param  string                    $source        source package name
     * @param  string                    $sourceVersion source package version (pretty version ideally)
     * @param  string                    $description   link description (e.g. requires, replaces, ..)
     * @param  array<string|int, string> $links         array of package name => constraint mappings
     *
     * @return Link[]
     *
     * @phpstan-param Link::TYPE_* $description
     */
    public function parseLinks(string $source, string $sourceVersion, string $description, array $links): array
    {
        $res = [];
        foreach ($links as $target => $constraint) {
            if (!is_string($constraint)) {
                continue;
            }
            $target = strtolower((string) $target);
            $res[$target] = $this->createLink($source, $sourceVersion, $description, $target, $constraint);
        }
        return $res;
    }
    /**
     * @param  string       $source           source package name
     * @param  string       $sourceVersion    source package version (pretty version ideally)
     * @param  Link::TYPE_* $description      link description (e.g. requires, replaces, ..)
     * @param  string       $target           target package name
     * @param  string       $prettyConstraint constraint string
     */
    private function createLink(string $source, string $sourceVersion, string $description, string $target, string $prettyConstraint): Link
    {
        if (!\is_string($prettyConstraint)) {
            throw new \UnexpectedValueException('Link constraint in ' . $source . ' ' . $description . ' > ' . $target . ' should be a string, got ' . \get_debug_type($prettyConstraint) . ' (' . var_export($prettyConstraint, \true) . ')');
        }
        if ('self.version' === $prettyConstraint) {
            $constraint = $sourceVersion;
        } else {
            $constraint = $prettyConstraint;
        }
        try {
            $parsedConstraint = $this->versionParser->parseConstraints($constraint);
        } catch (\UnexpectedValueException $e) {
            throw new \UnexpectedValueException('Link constraint in ' . $source . ' ' . $description . ' > ' . $target . ' should be a valid version constraint, got "' . $constraint . '"', $e->getCode(), $e);
        }
        return new Link($source, $target, $parsedConstraint, $description, $prettyConstraint);
    }
    /**
     * Retrieves a branch alias (dev-master => 1.0.x-dev for example) if it exists
     *
     * @param mixed[] $config the entire package config
     *
     * @return string|null normalized version of the branch alias or null if there is none
     */
    public function getBranchAlias(array $config): ?string
    {
        if (!isset($config['version']) || !is_scalar($config['version'])) {
            throw new \UnexpectedValueException('no/invalid version defined');
        }
        if (!is_string($config['version'])) {
            $config['version'] = (string) $config['version'];
        }
        if (strpos($config['version'], 'dev-') !== 0 && '-dev' !== substr($config['version'], -4)) {
            return null;
        }
        if (isset($config['extra']['branch-alias']) && \is_array($config['extra']['branch-alias'])) {
            foreach ($config['extra']['branch-alias'] as $sourceBranch => $targetBranch) {
                $sourceBranch = (string) $sourceBranch;
                // ensure it is an alias to a -dev package
                if ('-dev' !== substr($targetBranch, -4)) {
                    continue;
                }
                // normalize without -dev and ensure it's a numeric branch that is parseable
                if ($targetBranch === VersionParser::DEFAULT_BRANCH_ALIAS) {
                    $validatedTargetBranch = VersionParser::DEFAULT_BRANCH_ALIAS;
                } else {
                    $validatedTargetBranch = $this->versionParser->normalizeBranch(substr($targetBranch, 0, -4));
                }
                if ('-dev' !== substr($validatedTargetBranch, -4)) {
                    continue;
                }
                // ensure that it is the current branch aliasing itself
                if (strtolower($config['version']) !== strtolower($sourceBranch)) {
                    continue;
                }
                // If using numeric aliases ensure the alias is a valid subversion
                if (($sourcePrefix = $this->versionParser->parseNumericAliasPrefix($sourceBranch)) && ($targetPrefix = $this->versionParser->parseNumericAliasPrefix($targetBranch)) && stripos($targetPrefix, $sourcePrefix) !== 0) {
                    continue;
                }
                return $validatedTargetBranch;
            }
        }
        if (isset($config['default-branch']) && $config['default-branch'] === \true && \false === $this->versionParser->parseNumericAliasPrefix(Preg::replace('{^v}', '', $config['version']))) {
            return VersionParser::DEFAULT_BRANCH_ALIAS;
        }
        return null;
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer\Package\Loader;

use Composer\Package\CompletePackage;
use Composer\Package\CompleteAliasPackage;
use Composer\Package\RootAliasPackage;
use Composer\Package\RootPackage;
use Composer\Package\BasePackage;
/**
 * Defines a loader that takes an array to create package instances
 *
 * @author Jordi Boggiano <j.boggiano@seld.be>
 */
interface LoaderInterface
{
    /**
     * Converts a package from an array to a real instance
     *
     * @param  mixed[] $config package data
     * @param  string  $class  FQCN to be instantiated
     *
     * @return CompletePackage|CompleteAliasPackage|RootPackage|RootAliasPackage
     *
     * @phpstan-param class-string<CompletePackage|RootPackage> $class
     */
    public function load(array $config, string $class = 'Composer\Package\CompletePackage'): BasePackage;
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer\Package\Loader;

use Composer\Package\BasePackage;
use Composer\Config;
use Composer\IO\IOInterface;
use Composer\Package\RootAliasPackage;
use Composer\Pcre\Preg;
use Composer\Repository\RepositoryFactory;
use Composer\Package\Version\VersionGuesser;
use Composer\Package\Version\VersionParser;
use Composer\Package\RootPackage;
use Composer\Repository\RepositoryManager;
use Composer\Util\Platform;
use Composer\Util\ProcessExecutor;
/**
 * ArrayLoader built for the sole purpose of loading the root package
 *
 * Sets additional defaults and loads repositories
 *
 * @author Jordi Boggiano <j.boggiano@seld.be>
 */
class RootPackageLoader extends \Composer\Package\Loader\ArrayLoader
{
    /**
     * @var RepositoryManager
     */
    private $manager;
    /**
     * @var Config
     */
    private $config;
    /**
     * @var VersionGuesser
     */
    private $versionGuesser;
    /**
     * @var IOInterface|null
     */
    private $io;
    public function __construct(RepositoryManager $manager, Config $config, ?VersionParser $parser = null, ?VersionGuesser $versionGuesser = null, ?IOInterface $io = null)
    {
        parent::__construct($parser);
        $this->manager = $manager;
        $this->config = $config;
        if (null === $versionGuesser) {
            $processExecutor = new ProcessExecutor($io);
            $processExecutor->enableAsync();
            $versionGuesser = new VersionGuesser($config, $processExecutor, $this->versionParser);
        }
        $this->versionGuesser = $versionGuesser;
        $this->io = $io;
    }
    /**
     * @inheritDoc
     *
     * @return RootPackage|RootAliasPackage
     *
     * @phpstan-param class-string<RootPackage> $class
     */
    public function load(array $config, string $class = 'Composer\Package\RootPackage', ?string $cwd = null): BasePackage
    {
        if ($class !== 'Composer\Package\RootPackage') {
            trigger_error('The $class arg is deprecated, please reach out to Composer maintainers ASAP if you still need this.', \E_USER_DEPRECATED);
        }
        if (!isset($config['name'])) {
            $config['name'] = '__root__';
        } elseif ($err = \Composer\Package\Loader\ValidatingArrayLoader::hasPackageNamingError($config['name'])) {
            throw new \RuntimeException('Your package name ' . $err);
        }
        $autoVersioned = \false;
        if (!isset($config['version'])) {
            $commit = null;
            // override with env var if available
            if (Platform::getEnv('COMPOSER_ROOT_VERSION')) {
                $config['version'] = $this->versionGuesser->getRootVersionFromEnv();
            } else {
                $versionData = $this->versionGuesser->guessVersion($config, $cwd ?? Platform::getCwd(\true));
                if ($versionData) {
                    $config['version'] = $versionData['pretty_version'];
                    $config['version_normalized'] = $versionData['version'];
                    $commit = $versionData['commit'];
                }
            }
            if (!isset($config['version'])) {
                if ($this->io !== null && $config['name'] !== '__root__' && 'project' !== ($config['type'] ?? '')) {
                    $this->io->warning(sprintf("Composer could not detect the root package (%s) version, defaulting to '1.0.0'. See https://getcomposer.org/root-version", $config['name']));
                }
                $config['version'] = '1.0.0';
                $autoVersioned = \true;
            }
            if ($commit) {
                $config['source'] = ['type' => '', 'url' => '', 'reference' => $commit];
                $config['dist'] = ['type' => '', 'url' => '', 'reference' => $commit];
            }
        }
        /** @var RootPackage|RootAliasPackage $package */
        $package = parent::load($config, $class);
        if ($package instanceof RootAliasPackage) {
            $realPackage = $package->getAliasOf();
        } else {
            $realPackage = $package;
        }
        if (!$realPackage instanceof RootPackage) {
            throw new \LogicException('Expecting a _ContaoManager\Composer\Package\RootPackage at this point');
        }
        if ($autoVersioned) {
            $realPackage->replaceVersion($realPackage->getVersion(), RootPackage::DEFAULT_PRETTY_VERSION);
        }
        if (isset($config['minimum-stability'])) {
            $realPackage->setMinimumStability(VersionParser::normalizeStability($config['minimum-stability']));
        }
        $aliases = [];
        $stabilityFlags = [];
        $references = [];
        foreach (['require', 'require-dev'] as $linkType) {
            if (isset($config[$linkType])) {
                $linkInfo = BasePackage::$supportedLinkTypes[$linkType];
                $method = 'get' . ucfirst($linkInfo['method']);
                $links = [];
                foreach ($realPackage->{$method}() as $link) {
                    $links[$link->getTarget()] = $link->getConstraint()->getPrettyString();
                }
                $aliases = $this->extractAliases($links, $aliases);
                $stabilityFlags = self::extractStabilityFlags($links, $realPackage->getMinimumStability(), $stabilityFlags);
                $references = self::extractReferences($links, $references);
                if (isset($links[$config['name']])) {
                    throw new \RuntimeException(sprintf('Root package \'%s\' cannot require itself in its composer.json' . \PHP_EOL . 'Did you accidentally name your root package after an external package?', $config['name']));
                }
            }
        }
        foreach (array_keys(BasePackage::$supportedLinkTypes) as $linkType) {
            if (isset($config[$linkType])) {
                foreach ($config[$linkType] as $linkName => $constraint) {
                    if ($err = \Composer\Package\Loader\ValidatingArrayLoader::hasPackageNamingError($linkName, \true)) {
                        throw new \RuntimeException($linkType . '.' . $err);
                    }
                }
            }
        }
        $realPackage->setAliases($aliases);
        $realPackage->setStabilityFlags($stabilityFlags);
        $realPackage->setReferences($references);
        if (isset($config['prefer-stable'])) {
            $realPackage->setPreferStable((bool) $config['prefer-stable']);
        }
        if (isset($config['config'])) {
            $realPackage->setConfig($config['config']);
        }
        $repos = RepositoryFactory::defaultRepos(null, $this->config, $this->manager);
        foreach ($repos as $repo) {
            $this->manager->addRepository($repo);
        }
        $realPackage->setRepositories($this->config->getRepositories());
        return $package;
    }
    /**
     * @param array<string, string>                                                                  $requires
     * @param list<array{package: string, version: string, alias: string, alias_normalized: string}> $aliases
     *
     * @return list<array{package: string, version: string, alias: string, alias_normalized: string}>
     */
    private function extractAliases(array $requires, array $aliases): array
    {
        foreach ($requires as $reqName => $reqVersion) {
            if (Preg::isMatchStrictGroups('{(?:^|\| *|, *)([^,\s#|]+)(?:#[^ ]+)? +as +([^,\s|]+)(?:$| *\|| *,)}', $reqVersion, $match)) {
                $aliases[] = ['package' => strtolower($reqName), 'version' => $this->versionParser->normalize($match[1], $reqVersion), 'alias' => $match[2], 'alias_normalized' => $this->versionParser->normalize($match[2], $reqVersion)];
            } elseif (strpos($reqVersion, ' as ') !== \false) {
                throw new \UnexpectedValueException('Invalid alias definition in "' . $reqName . '": "' . $reqVersion . '". Aliases should be in the form "exact-version as other-exact-version".');
            }
        }
        return $aliases;
    }
    /**
     * @internal
     *
     * @param array<string, string> $requires
     * @param array<string, int>    $stabilityFlags
     * @param key-of<BasePackage::STABILITIES> $minimumStability
     *
     * @return array<string, int>
     *
     * @phpstan-param array<string, BasePackage::STABILITY_*> $stabilityFlags
     * @phpstan-return array<string, BasePackage::STABILITY_*>
     */
    public static function extractStabilityFlags(array $requires, string $minimumStability, array $stabilityFlags): array
    {
        $stabilities = BasePackage::STABILITIES;
        $minimumStability = $stabilities[$minimumStability];
        foreach ($requires as $reqName => $reqVersion) {
            $constraints = [];
            // extract all sub-constraints in case it is an OR/AND multi-constraint
            $orSplit = Preg::split('{\s*\|\|?\s*}', trim($reqVersion));
            foreach ($orSplit as $orConstraint) {
                $andSplit = Preg::split('{(?<!^|as|[=>< ,]) *(?<!-)[, ](?!-) *(?!,|as|$)}', $orConstraint);
                foreach ($andSplit as $andConstraint) {
                    $constraints[] = $andConstraint;
                }
            }
            // parse explicit stability flags to the most unstable
            $matched = \false;
            foreach ($constraints as $constraint) {
                if (Preg::isMatchStrictGroups('{^[^@]*?@(' . implode('|', array_keys($stabilities)) . ')$}i', $constraint, $match)) {
                    $name = strtolower($reqName);
                    $stability = $stabilities[VersionParser::normalizeStability($match[1])];
                    if (isset($stabilityFlags[$name]) && $stabilityFlags[$name] > $stability) {
                        continue;
                    }
                    $stabilityFlags[$name] = $stability;
                    $matched = \true;
                }
            }
            if ($matched) {
                continue;
            }
            foreach ($constraints as $constraint) {
                // infer flags for requirements that have an explicit -dev or -beta version specified but only
                // for those that are more unstable than the minimumStability or existing flags
                $reqVersion = Preg::replace('{^([^,\s@]+) as .+$}', '$1', $constraint);
                if (Preg::isMatch('{^[^,\s@]+$}', $reqVersion) && 'stable' !== $stabilityName = VersionParser::parseStability($reqVersion)) {
                    $name = strtolower($reqName);
                    $stability = $stabilities[$stabilityName];
                    if (isset($stabilityFlags[$name]) && $stabilityFlags[$name] > $stability || $minimumStability > $stability) {
                        continue;
                    }
                    $stabilityFlags[$name] = $stability;
                }
            }
        }
        return $stabilityFlags;
    }
    /**
     * @internal
     *
     * @param array<string, string> $requires
     * @param array<string, string> $references
     *
     * @return array<string, string>
     */
    public static function extractReferences(array $requires, array $references): array
    {
        foreach ($requires as $reqName => $reqVersion) {
            $reqVersion = Preg::replace('{^([^,\s@]+) as .+$}', '$1', $reqVersion);
            if (Preg::isMatchStrictGroups('{^[^,\s@]+?#([a-f0-9]+)$}', $reqVersion, $match) && 'dev' === VersionParser::parseStability($reqVersion)) {
                $name = strtolower($reqName);
                $references[$name] = $match[1];
            }
        }
        return $references;
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer\Package\Loader;

use Composer\Json\JsonFile;
use Composer\Package\BasePackage;
use Composer\Package\CompletePackage;
use Composer\Package\CompleteAliasPackage;
use Composer\Package\RootPackage;
use Composer\Package\RootAliasPackage;
/**
 * @author Konstantin Kudryashiv <ever.zet@gmail.com>
 */
class JsonLoader
{
    /** @var LoaderInterface */
    private $loader;
    public function __construct(\Composer\Package\Loader\LoaderInterface $loader)
    {
        $this->loader = $loader;
    }
    /**
     * @param  string|JsonFile                      $json A filename, json string or JsonFile instance to load the package from
     * @return CompletePackage|CompleteAliasPackage|RootPackage|RootAliasPackage
     */
    public function load($json): BasePackage
    {
        if ($json instanceof JsonFile) {
            $config = $json->read();
        } elseif (file_exists($json)) {
            $config = JsonFile::parseJson(file_get_contents($json), $json);
        } elseif (is_string($json)) {
            $config = JsonFile::parseJson($json);
        } else {
            throw new \InvalidArgumentException(sprintf("JsonLoader: Unknown \$json parameter %s. Please report at https://github.com/composer/composer/issues/new.", get_debug_type($json)));
        }
        return $this->loader->load($config);
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer\Package;

use Composer\Repository\RepositoryInterface;
use Composer\Repository\PlatformRepository;
/**
 * Base class for packages providing name storage and default match implementation
 *
 * @author Nils Adermann <naderman@naderman.de>
 */
abstract class BasePackage implements \Composer\Package\PackageInterface
{
    /**
     * @phpstan-var array<non-empty-string, array{description: string, method: Link::TYPE_*}>
     * @internal
     */
    public static $supportedLinkTypes = ['require' => ['description' => 'requires', 'method' => \Composer\Package\Link::TYPE_REQUIRE], 'conflict' => ['description' => 'conflicts', 'method' => \Composer\Package\Link::TYPE_CONFLICT], 'provide' => ['description' => 'provides', 'method' => \Composer\Package\Link::TYPE_PROVIDE], 'replace' => ['description' => 'replaces', 'method' => \Composer\Package\Link::TYPE_REPLACE], 'require-dev' => ['description' => 'requires (for development)', 'method' => \Composer\Package\Link::TYPE_DEV_REQUIRE]];
    public const STABILITY_STABLE = 0;
    public const STABILITY_RC = 5;
    public const STABILITY_BETA = 10;
    public const STABILITY_ALPHA = 15;
    public const STABILITY_DEV = 20;
    public const STABILITIES = ['stable' => self::STABILITY_STABLE, 'RC' => self::STABILITY_RC, 'beta' => self::STABILITY_BETA, 'alpha' => self::STABILITY_ALPHA, 'dev' => self::STABILITY_DEV];
    /**
     * @deprecated
     * @readonly
     * @var array<key-of<BasePackage::STABILITIES>, self::STABILITY_*>
     * @phpstan-ignore property.readOnlyByPhpDocDefaultValue
     */
    public static $stabilities = self::STABILITIES;
    /**
     * READ-ONLY: The package id, public for fast access in dependency solver
     * @var int
     * @internal
     */
    public $id;
    /** @var string */
    protected $name;
    /** @var string */
    protected $prettyName;
    /** @var ?RepositoryInterface */
    protected $repository = null;
    /**
     * All descendants' constructors should call this parent constructor
     *
     * @param string $name The package's name
     */
    public function __construct(string $name)
    {
        $this->prettyName = $name;
        $this->name = strtolower($name);
        $this->id = -1;
    }
    /**
     * @inheritDoc
     */
    public function getName(): string
    {
        return $this->name;
    }
    /**
     * @inheritDoc
     */
    public function getPrettyName(): string
    {
        return $this->prettyName;
    }
    /**
     * @inheritDoc
     */
    public function getNames($provides = \true): array
    {
        $names = [$this->getName() => \true];
        if ($provides) {
            foreach ($this->getProvides() as $link) {
                $names[$link->getTarget()] = \true;
            }
        }
        foreach ($this->getReplaces() as $link) {
            $names[$link->getTarget()] = \true;
        }
        return array_keys($names);
    }
    /**
     * @inheritDoc
     */
    public function setId(int $id): void
    {
        $this->id = $id;
    }
    /**
     * @inheritDoc
     */
    public function getId(): int
    {
        return $this->id;
    }
    /**
     * @inheritDoc
     */
    public function setRepository(RepositoryInterface $repository): void
    {
        if ($this->repository && $repository !== $this->repository) {
            throw new \LogicException(sprintf('Package "%s" cannot be added to repository "%s" as it is already in repository "%s".', $this->getPrettyName(), $repository->getRepoName(), $this->repository->getRepoName()));
        }
        $this->repository = $repository;
    }
    /**
     * @inheritDoc
     */
    public function getRepository(): ?RepositoryInterface
    {
        return $this->repository;
    }
    /**
     * checks if this package is a platform package
     */
    public function isPlatform(): bool
    {
        return $this->getRepository() instanceof PlatformRepository;
    }
    /**
     * Returns package unique name, constructed from name, version and release type.
     */
    public function getUniqueName(): string
    {
        return $this->getName() . '-' . $this->getVersion();
    }
    public function equals(\Composer\Package\PackageInterface $package): bool
    {
        $self = $this;
        if ($this instanceof \Composer\Package\AliasPackage) {
            $self = $this->getAliasOf();
        }
        if ($package instanceof \Composer\Package\AliasPackage) {
            $package = $package->getAliasOf();
        }
        return $package === $self;
    }
    /**
     * Converts the package into a readable and unique string
     */
    public function __toString(): string
    {
        return $this->getUniqueName();
    }
    public function getPrettyString(): string
    {
        return $this->getPrettyName() . ' ' . $this->getPrettyVersion();
    }
    /**
     * @inheritDoc
     */
    public function getFullPrettyVersion(bool $truncate = \true, int $displayMode = \Composer\Package\PackageInterface::DISPLAY_SOURCE_REF_IF_DEV): string
    {
        if ($displayMode === \Composer\Package\PackageInterface::DISPLAY_SOURCE_REF_IF_DEV && (!$this->isDev() || !\in_array($this->getSourceType(), ['hg', 'git']) && ((string) $this->getSourceType() !== '' || (string) $this->getDistReference() === ''))) {
            return $this->getPrettyVersion();
        }
        switch ($displayMode) {
            case \Composer\Package\PackageInterface::DISPLAY_SOURCE_REF_IF_DEV:
                $reference = (string) $this->getSourceReference() !== '' ? $this->getSourceReference() : $this->getDistReference();
                break;
            case \Composer\Package\PackageInterface::DISPLAY_SOURCE_REF:
                $reference = $this->getSourceReference();
                break;
            case \Composer\Package\PackageInterface::DISPLAY_DIST_REF:
                $reference = $this->getDistReference();
                break;
            default:
                throw new \UnexpectedValueException('Display mode ' . $displayMode . ' is not supported');
        }
        if (null === $reference) {
            return $this->getPrettyVersion();
        }
        // if source reference is a sha1 hash -- truncate
        if ($truncate && \strlen($reference) === 40 && $this->getSourceType() !== 'svn') {
            return $this->getPrettyVersion() . ' ' . substr($reference, 0, 7);
        }
        return $this->getPrettyVersion() . ' ' . $reference;
    }
    /**
     * @phpstan-return self::STABILITY_*
     */
    public function getStabilityPriority(): int
    {
        return self::STABILITIES[$this->getStability()];
    }
    public function __clone()
    {
        $this->repository = null;
        $this->id = -1;
    }
    /**
     * Build a regexp from a package name, expanding * globs as required
     *
     * @param  non-empty-string $wrap         Wrap the cleaned string by the given string
     * @return non-empty-string
     */
    public static function packageNameToRegexp(string $allowPattern, string $wrap = '{^%s$}i'): string
    {
        $cleanedAllowPattern = str_replace('\*', '.*', preg_quote($allowPattern));
        return sprintf($wrap, $cleanedAllowPattern);
    }
    /**
     * Build a regexp from package names, expanding * globs as required
     *
     * @param string[] $packageNames
     * @param non-empty-string $wrap
     * @return non-empty-string
     */
    public static function packageNamesToRegexp(array $packageNames, string $wrap = '{^(?:%s)$}iD'): string
    {
        $packageNames = array_map(static function ($packageName): string {
            return \Composer\Package\BasePackage::packageNameToRegexp($packageName, '%s');
        }, $packageNames);
        return sprintf($wrap, implode('|', $packageNames));
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer\Package\Comparer;

use Composer\Util\Platform;
/**
 * class Comparer
 *
 * @author Hector Prats <hectorpratsortega@gmail.com>
 */
class Comparer
{
    /** @var string Source directory */
    private $source;
    /** @var string Target directory */
    private $update;
    /** @var array{changed?: string[], removed?: string[], added?: string[]} */
    private $changed;
    public function setSource(string $source): void
    {
        $this->source = $source;
    }
    public function setUpdate(string $update): void
    {
        $this->update = $update;
    }
    /**
     * @return array{changed?: string[], removed?: string[], added?: string[]}|false false if no change
     */
    public function getChanged(bool $explicated = \false)
    {
        $changed = $this->changed;
        if (!count($changed)) {
            return \false;
        }
        if ($explicated) {
            foreach ($changed as $sectionKey => $itemSection) {
                foreach ($itemSection as $itemKey => $item) {
                    $changed[$sectionKey][$itemKey] = $item . ' (' . $sectionKey . ')';
                }
            }
        }
        return $changed;
    }
    /**
     * @return string empty string if no changes
     */
    public function getChangedAsString(bool $toString = \false, bool $explicated = \false): string
    {
        $changed = $this->getChanged($explicated);
        if (\false === $changed) {
            return '';
        }
        $strings = [];
        foreach ($changed as $sectionKey => $itemSection) {
            foreach ($itemSection as $itemKey => $item) {
                $strings[] = $item . "\r\n";
            }
        }
        return trim(implode("\r\n", $strings));
    }
    public function doCompare(): void
    {
        $source = [];
        $destination = [];
        $this->changed = [];
        $currentDirectory = Platform::getCwd();
        chdir($this->source);
        $source = $this->doTree('.', $source);
        if (!is_array($source)) {
            return;
        }
        chdir($currentDirectory);
        chdir($this->update);
        $destination = $this->doTree('.', $destination);
        if (!is_array($destination)) {
            exit;
        }
        chdir($currentDirectory);
        foreach ($source as $dir => $value) {
            foreach ($value as $file => $hash) {
                if (isset($destination[$dir][$file])) {
                    if ($hash !== $destination[$dir][$file]) {
                        $this->changed['changed'][] = $dir . '/' . $file;
                    }
                } else {
                    $this->changed['removed'][] = $dir . '/' . $file;
                }
            }
        }
        foreach ($destination as $dir => $value) {
            foreach ($value as $file => $hash) {
                if (!isset($source[$dir][$file])) {
                    $this->changed['added'][] = $dir . '/' . $file;
                }
            }
        }
    }
    /**
     * @param mixed[] $array
     *
     * @return array<string, array<string, string|false>>|false
     */
    private function doTree(string $dir, array &$array)
    {
        if ($dh = opendir($dir)) {
            while ($file = readdir($dh)) {
                if ($file !== '.' && $file !== '..') {
                    if (is_link($dir . '/' . $file)) {
                        $array[$dir][$file] = readlink($dir . '/' . $file);
                    } elseif (is_dir($dir . '/' . $file)) {
                        if (!count($array)) {
                            $array[0] = 'Temp';
                        }
                        if (!$this->doTree($dir . '/' . $file, $array)) {
                            return \false;
                        }
                    } elseif (is_file($dir . '/' . $file) && filesize($dir . '/' . $file)) {
                        $array[$dir][$file] = hash_file(\PHP_VERSION_ID > 80100 ? 'xxh3' : 'sha1', $dir . '/' . $file);
                    }
                }
            }
            if (count($array) > 1 && isset($array['0'])) {
                unset($array['0']);
            }
            return $array;
        }
        return \false;
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer\Package;

/**
 * @author Jordi Boggiano <j.boggiano@seld.be>
 */
class RootAliasPackage extends \Composer\Package\CompleteAliasPackage implements \Composer\Package\RootPackageInterface
{
    /** @var RootPackage */
    protected $aliasOf;
    /**
     * All descendants' constructors should call this parent constructor
     *
     * @param RootPackage $aliasOf       The package this package is an alias of
     * @param string      $version       The version the alias must report
     * @param string      $prettyVersion The alias's non-normalized version
     */
    public function __construct(\Composer\Package\RootPackage $aliasOf, string $version, string $prettyVersion)
    {
        parent::__construct($aliasOf, $version, $prettyVersion);
    }
    /**
     * @return RootPackage
     */
    public function getAliasOf()
    {
        return $this->aliasOf;
    }
    /**
     * @inheritDoc
     */
    public function getAliases(): array
    {
        return $this->aliasOf->getAliases();
    }
    /**
     * @inheritDoc
     */
    public function getMinimumStability(): string
    {
        return $this->aliasOf->getMinimumStability();
    }
    /**
     * @inheritDoc
     */
    public function getStabilityFlags(): array
    {
        return $this->aliasOf->getStabilityFlags();
    }
    /**
     * @inheritDoc
     */
    public function getReferences(): array
    {
        return $this->aliasOf->getReferences();
    }
    /**
     * @inheritDoc
     */
    public function getPreferStable(): bool
    {
        return $this->aliasOf->getPreferStable();
    }
    /**
     * @inheritDoc
     */
    public function getConfig(): array
    {
        return $this->aliasOf->getConfig();
    }
    /**
     * @inheritDoc
     */
    public function setRequires(array $requires): void
    {
        $this->requires = $this->replaceSelfVersionDependencies($requires, \Composer\Package\Link::TYPE_REQUIRE);
        $this->aliasOf->setRequires($requires);
    }
    /**
     * @inheritDoc
     */
    public function setDevRequires(array $devRequires): void
    {
        $this->devRequires = $this->replaceSelfVersionDependencies($devRequires, \Composer\Package\Link::TYPE_DEV_REQUIRE);
        $this->aliasOf->setDevRequires($devRequires);
    }
    /**
     * @inheritDoc
     */
    public function setConflicts(array $conflicts): void
    {
        $this->conflicts = $this->replaceSelfVersionDependencies($conflicts, \Composer\Package\Link::TYPE_CONFLICT);
        $this->aliasOf->setConflicts($conflicts);
    }
    /**
     * @inheritDoc
     */
    public function setProvides(array $provides): void
    {
        $this->provides = $this->replaceSelfVersionDependencies($provides, \Composer\Package\Link::TYPE_PROVIDE);
        $this->aliasOf->setProvides($provides);
    }
    /**
     * @inheritDoc
     */
    public function setReplaces(array $replaces): void
    {
        $this->replaces = $this->replaceSelfVersionDependencies($replaces, \Composer\Package\Link::TYPE_REPLACE);
        $this->aliasOf->setReplaces($replaces);
    }
    /**
     * @inheritDoc
     */
    public function setAutoload(array $autoload): void
    {
        $this->aliasOf->setAutoload($autoload);
    }
    /**
     * @inheritDoc
     */
    public function setDevAutoload(array $devAutoload): void
    {
        $this->aliasOf->setDevAutoload($devAutoload);
    }
    /**
     * @inheritDoc
     */
    public function setStabilityFlags(array $stabilityFlags): void
    {
        $this->aliasOf->setStabilityFlags($stabilityFlags);
    }
    /**
     * @inheritDoc
     */
    public function setMinimumStability(string $minimumStability): void
    {
        $this->aliasOf->setMinimumStability($minimumStability);
    }
    /**
     * @inheritDoc
     */
    public function setPreferStable(bool $preferStable): void
    {
        $this->aliasOf->setPreferStable($preferStable);
    }
    /**
     * @inheritDoc
     */
    public function setConfig(array $config): void
    {
        $this->aliasOf->setConfig($config);
    }
    /**
     * @inheritDoc
     */
    public function setReferences(array $references): void
    {
        $this->aliasOf->setReferences($references);
    }
    /**
     * @inheritDoc
     */
    public function setAliases(array $aliases): void
    {
        $this->aliasOf->setAliases($aliases);
    }
    /**
     * @inheritDoc
     */
    public function setSuggests(array $suggests): void
    {
        $this->aliasOf->setSuggests($suggests);
    }
    /**
     * @inheritDoc
     */
    public function setExtra(array $extra): void
    {
        $this->aliasOf->setExtra($extra);
    }
    public function __clone()
    {
        parent::__clone();
        $this->aliasOf = clone $this->aliasOf;
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer\Package;

/**
 * Package containing additional metadata that is not used by the solver
 *
 * @author Nils Adermann <naderman@naderman.de>
 */
class CompletePackage extends \Composer\Package\Package implements \Composer\Package\CompletePackageInterface
{
    /** @var mixed[] */
    protected $repositories = [];
    /** @var string[] */
    protected $license = [];
    /** @var string[] */
    protected $keywords = [];
    /** @var array<array{name?: string, homepage?: string, email?: string, role?: string}> */
    protected $authors = [];
    /** @var ?string */
    protected $description = null;
    /** @var ?string */
    protected $homepage = null;
    /** @var array<string, string[]> Map of script name to array of handlers */
    protected $scripts = [];
    /** @var array{issues?: string, forum?: string, wiki?: string, source?: string, email?: string, irc?: string, docs?: string, rss?: string, chat?: string, security?: string} */
    protected $support = [];
    /** @var array<array{url?: string, type?: string}> */
    protected $funding = [];
    /** @var bool|string */
    protected $abandoned = \false;
    /** @var ?string */
    protected $archiveName = null;
    /** @var string[] */
    protected $archiveExcludes = [];
    /**
     * @inheritDoc
     */
    public function setScripts(array $scripts): void
    {
        $this->scripts = $scripts;
    }
    /**
     * @inheritDoc
     */
    public function getScripts(): array
    {
        return $this->scripts;
    }
    /**
     * @inheritDoc
     */
    public function setRepositories(array $repositories): void
    {
        $this->repositories = $repositories;
    }
    /**
     * @inheritDoc
     */
    public function getRepositories(): array
    {
        return $this->repositories;
    }
    /**
     * @inheritDoc
     */
    public function setLicense(array $license): void
    {
        $this->license = $license;
    }
    /**
     * @inheritDoc
     */
    public function getLicense(): array
    {
        return $this->license;
    }
    /**
     * @inheritDoc
     */
    public function setKeywords(array $keywords): void
    {
        $this->keywords = $keywords;
    }
    /**
     * @inheritDoc
     */
    public function getKeywords(): array
    {
        return $this->keywords;
    }
    /**
     * @inheritDoc
     */
    public function setAuthors(array $authors): void
    {
        $this->authors = $authors;
    }
    /**
     * @inheritDoc
     */
    public function getAuthors(): array
    {
        return $this->authors;
    }
    /**
     * @inheritDoc
     */
    public function setDescription(?string $description): void
    {
        $this->description = $description;
    }
    /**
     * @inheritDoc
     */
    public function getDescription(): ?string
    {
        return $this->description;
    }
    /**
     * @inheritDoc
     */
    public function setHomepage(?string $homepage): void
    {
        $this->homepage = $homepage;
    }
    /**
     * @inheritDoc
     */
    public function getHomepage(): ?string
    {
        return $this->homepage;
    }
    /**
     * @inheritDoc
     */
    public function setSupport(array $support): void
    {
        $this->support = $support;
    }
    /**
     * @inheritDoc
     */
    public function getSupport(): array
    {
        return $this->support;
    }
    /**
     * @inheritDoc
     */
    public function setFunding(array $funding): void
    {
        $this->funding = $funding;
    }
    /**
     * @inheritDoc
     */
    public function getFunding(): array
    {
        return $this->funding;
    }
    /**
     * @inheritDoc
     */
    public function isAbandoned(): bool
    {
        return (bool) $this->abandoned;
    }
    /**
     * @inheritDoc
     */
    public function setAbandoned($abandoned): void
    {
        $this->abandoned = $abandoned;
    }
    /**
     * @inheritDoc
     */
    public function getReplacementPackage(): ?string
    {
        return \is_string($this->abandoned) ? $this->abandoned : null;
    }
    /**
     * @inheritDoc
     */
    public function setArchiveName(?string $name): void
    {
        $this->archiveName = $name;
    }
    /**
     * @inheritDoc
     */
    public function getArchiveName(): ?string
    {
        return $this->archiveName;
    }
    /**
     * @inheritDoc
     */
    public function setArchiveExcludes(array $excludes): void
    {
        $this->archiveExcludes = $excludes;
    }
    /**
     * @inheritDoc
     */
    public function getArchiveExcludes(): array
    {
        return $this->archiveExcludes;
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer\Package;

/**
 * Defines additional fields that are only needed for the root package
 *
 * PackageInterface & derivatives are considered internal, you may use them in type hints but extending/implementing them is not recommended and not supported. Things may change without notice.
 *
 * @author Jordi Boggiano <j.boggiano@seld.be>
 *
 * @phpstan-import-type AutoloadRules from PackageInterface
 * @phpstan-import-type DevAutoloadRules from PackageInterface
 */
interface RootPackageInterface extends \Composer\Package\CompletePackageInterface
{
    /**
     * Returns a set of package names and their aliases
     *
     * @return list<array{package: string, version: string, alias: string, alias_normalized: string}>
     */
    public function getAliases(): array;
    /**
     * Returns the minimum stability of the package
     *
     * @return key-of<BasePackage::STABILITIES>
     */
    public function getMinimumStability(): string;
    /**
     * Returns the stability flags to apply to dependencies
     *
     * array('foo/bar' => 'dev')
     *
     * @return array<string, BasePackage::STABILITY_*>
     */
    public function getStabilityFlags(): array;
    /**
     * Returns a set of package names and source references that must be enforced on them
     *
     * array('foo/bar' => 'abcd1234')
     *
     * @return array<string, string>
     */
    public function getReferences(): array;
    /**
     * Returns true if the root package prefers picking stable packages over unstable ones
     */
    public function getPreferStable(): bool;
    /**
     * Returns the root package's configuration
     *
     * @return mixed[]
     */
    public function getConfig(): array;
    /**
     * Set the required packages
     *
     * @param Link[] $requires A set of package links
     */
    public function setRequires(array $requires): void;
    /**
     * Set the recommended packages
     *
     * @param Link[] $devRequires A set of package links
     */
    public function setDevRequires(array $devRequires): void;
    /**
     * Set the conflicting packages
     *
     * @param Link[] $conflicts A set of package links
     */
    public function setConflicts(array $conflicts): void;
    /**
     * Set the provided virtual packages
     *
     * @param Link[] $provides A set of package links
     */
    public function setProvides(array $provides): void;
    /**
     * Set the packages this one replaces
     *
     * @param Link[] $replaces A set of package links
     */
    public function setReplaces(array $replaces): void;
    /**
     * Set the autoload mapping
     *
     * @param array $autoload Mapping of autoloading rules
     * @phpstan-param AutoloadRules $autoload
     */
    public function setAutoload(array $autoload): void;
    /**
     * Set the dev autoload mapping
     *
     * @param array $devAutoload Mapping of dev autoloading rules
     * @phpstan-param DevAutoloadRules $devAutoload
     */
    public function setDevAutoload(array $devAutoload): void;
    /**
     * Set the stabilityFlags
     *
     * @phpstan-param array<string, BasePackage::STABILITY_*> $stabilityFlags
     */
    public function setStabilityFlags(array $stabilityFlags): void;
    /**
     * Set the minimumStability
     *
     * @phpstan-param key-of<BasePackage::STABILITIES> $minimumStability
     */
    public function setMinimumStability(string $minimumStability): void;
    /**
     * Set the preferStable
     */
    public function setPreferStable(bool $preferStable): void;
    /**
     * Set the config
     *
     * @param mixed[] $config
     */
    public function setConfig(array $config): void;
    /**
     * Set the references
     *
     * @param array<string, string> $references
     */
    public function setReferences(array $references): void;
    /**
     * Set the aliases
     *
     * @param list<array{package: string, version: string, alias: string, alias_normalized: string}> $aliases
     */
    public function setAliases(array $aliases): void;
    /**
     * Set the suggested packages
     *
     * @param array<string, string> $suggests A set of package names/comments
     */
    public function setSuggests(array $suggests): void;
    /**
     * @param mixed[] $extra
     */
    public function setExtra(array $extra): void;
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer\Package;

/**
 * The root package represents the project's composer.json and contains additional metadata
 *
 * @author Jordi Boggiano <j.boggiano@seld.be>
 */
class RootPackage extends \Composer\Package\CompletePackage implements \Composer\Package\RootPackageInterface
{
    public const DEFAULT_PRETTY_VERSION = '1.0.0+no-version-set';
    /** @var key-of<BasePackage::STABILITIES> */
    protected $minimumStability = 'stable';
    /** @var bool */
    protected $preferStable = \false;
    /** @var array<string, BasePackage::STABILITY_*> Map of package name to stability constant */
    protected $stabilityFlags = [];
    /** @var mixed[] */
    protected $config = [];
    /** @var array<string, string> Map of package name to reference/commit hash */
    protected $references = [];
    /** @var list<array{package: string, version: string, alias: string, alias_normalized: string}> */
    protected $aliases = [];
    /**
     * @inheritDoc
     */
    public function setMinimumStability(string $minimumStability): void
    {
        $this->minimumStability = $minimumStability;
    }
    /**
     * @inheritDoc
     */
    public function getMinimumStability(): string
    {
        return $this->minimumStability;
    }
    /**
     * @inheritDoc
     */
    public function setStabilityFlags(array $stabilityFlags): void
    {
        $this->stabilityFlags = $stabilityFlags;
    }
    /**
     * @inheritDoc
     */
    public function getStabilityFlags(): array
    {
        return $this->stabilityFlags;
    }
    /**
     * @inheritDoc
     */
    public function setPreferStable(bool $preferStable): void
    {
        $this->preferStable = $preferStable;
    }
    /**
     * @inheritDoc
     */
    public function getPreferStable(): bool
    {
        return $this->preferStable;
    }
    /**
     * @inheritDoc
     */
    public function setConfig(array $config): void
    {
        $this->config = $config;
    }
    /**
     * @inheritDoc
     */
    public function getConfig(): array
    {
        return $this->config;
    }
    /**
     * @inheritDoc
     */
    public function setReferences(array $references): void
    {
        $this->references = $references;
    }
    /**
     * @inheritDoc
     */
    public function getReferences(): array
    {
        return $this->references;
    }
    /**
     * @inheritDoc
     */
    public function setAliases(array $aliases): void
    {
        $this->aliases = $aliases;
    }
    /**
     * @inheritDoc
     */
    public function getAliases(): array
    {
        return $this->aliases;
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer\Package\Dumper;

use Composer\Package\BasePackage;
use Composer\Package\PackageInterface;
use Composer\Package\CompletePackageInterface;
use Composer\Package\RootPackageInterface;
/**
 * @author Konstantin Kudryashiv <ever.zet@gmail.com>
 * @author Jordi Boggiano <j.boggiano@seld.be>
 */
class ArrayDumper
{
    /**
     * @return array<string, mixed>
     */
    public function dump(PackageInterface $package): array
    {
        $keys = ['binaries' => 'bin', 'type', 'extra', 'installationSource' => 'installation-source', 'autoload', 'devAutoload' => 'autoload-dev', 'notificationUrl' => 'notification-url', 'includePaths' => 'include-path', 'phpExt' => 'php-ext'];
        $data = [];
        $data['name'] = $package->getPrettyName();
        $data['version'] = $package->getPrettyVersion();
        $data['version_normalized'] = $package->getVersion();
        if ($package->getTargetDir() !== null) {
            $data['target-dir'] = $package->getTargetDir();
        }
        if ($package->getSourceType() !== null) {
            $data['source']['type'] = $package->getSourceType();
            $data['source']['url'] = $package->getSourceUrl();
            if (null !== $value = $package->getSourceReference()) {
                $data['source']['reference'] = $value;
            }
            if ($mirrors = $package->getSourceMirrors()) {
                $data['source']['mirrors'] = $mirrors;
            }
        }
        if ($package->getDistType() !== null) {
            $data['dist']['type'] = $package->getDistType();
            $data['dist']['url'] = $package->getDistUrl();
            if (null !== $value = $package->getDistReference()) {
                $data['dist']['reference'] = $value;
            }
            if (null !== $value = $package->getDistSha1Checksum()) {
                $data['dist']['shasum'] = $value;
            }
            if ($mirrors = $package->getDistMirrors()) {
                $data['dist']['mirrors'] = $mirrors;
            }
        }
        foreach (BasePackage::$supportedLinkTypes as $type => $opts) {
            $links = $package->{'get' . ucfirst($opts['method'])}();
            if (\count($links) === 0) {
                continue;
            }
            foreach ($links as $link) {
                $data[$type][$link->getTarget()] = $link->getPrettyConstraint();
            }
            ksort($data[$type]);
        }
        $packages = $package->getSuggests();
        if (\count($packages) > 0) {
            ksort($packages);
            $data['suggest'] = $packages;
        }
        if ($package->getReleaseDate() instanceof \DateTimeInterface) {
            $data['time'] = $package->getReleaseDate()->format(\DATE_RFC3339);
        }
        if ($package->isDefaultBranch()) {
            $data['default-branch'] = \true;
        }
        $data = $this->dumpValues($package, $keys, $data);
        if ($package instanceof CompletePackageInterface) {
            if ($package->getArchiveName()) {
                $data['archive']['name'] = $package->getArchiveName();
            }
            if ($package->getArchiveExcludes()) {
                $data['archive']['exclude'] = $package->getArchiveExcludes();
            }
            $keys = ['scripts', 'license', 'authors', 'description', 'homepage', 'keywords', 'repositories', 'support', 'funding'];
            $data = $this->dumpValues($package, $keys, $data);
            if (isset($data['keywords']) && \is_array($data['keywords'])) {
                sort($data['keywords']);
            }
            if ($package->isAbandoned()) {
                $data['abandoned'] = $package->getReplacementPackage() ?: \true;
            }
        }
        if ($package instanceof RootPackageInterface) {
            $minimumStability = $package->getMinimumStability();
            if ($minimumStability !== '') {
                $data['minimum-stability'] = $minimumStability;
            }
        }
        if (\count($package->getTransportOptions()) > 0) {
            $data['transport-options'] = $package->getTransportOptions();
        }
        return $data;
    }
    /**
     * @param array<int|string, string> $keys
     * @param array<string, mixed>      $data
     *
     * @return array<string, mixed>
     */
    private function dumpValues(PackageInterface $package, array $keys, array $data): array
    {
        foreach ($keys as $method => $key) {
            if (is_numeric($method)) {
                $method = $key;
            }
            $getter = 'get' . ucfirst($method);
            $value = $package->{$getter}();
            if (null !== $value && !(\is_array($value) && 0 === \count($value))) {
                $data[$key] = $value;
            }
        }
        return $data;
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer\Console;

use Composer\Installer;
use Composer\IO\NullIO;
use Composer\Util\Filesystem;
use Composer\Util\Platform;
use Composer\Util\Silencer;
use LogicException;
use RuntimeException;
use _ContaoManager\Symfony\Component\Console\Application as BaseApplication;
use _ContaoManager\Symfony\Component\Console\Command\Command as SymfonyCommand;
use _ContaoManager\Symfony\Component\Console\Exception\CommandNotFoundException;
use _ContaoManager\Symfony\Component\Console\Exception\ExceptionInterface;
use _ContaoManager\Symfony\Component\Console\Helper\HelperSet;
use _ContaoManager\Symfony\Component\Console\Helper\QuestionHelper;
use _ContaoManager\Symfony\Component\Console\Input\InputDefinition;
use _ContaoManager\Symfony\Component\Console\Input\InputInterface;
use _ContaoManager\Symfony\Component\Console\Input\InputOption;
use _ContaoManager\Symfony\Component\Console\Output\ConsoleOutputInterface;
use _ContaoManager\Symfony\Component\Console\Output\OutputInterface;
use _ContaoManager\Seld\JsonLint\ParsingException;
use Composer\Command;
use Composer\Composer;
use Composer\Factory;
use Composer\Downloader\TransportException;
use Composer\IO\IOInterface;
use Composer\IO\ConsoleIO;
use Composer\Json\JsonValidationException;
use Composer\Util\ErrorHandler;
use Composer\Util\HttpDownloader;
use Composer\EventDispatcher\ScriptExecutionException;
use Composer\Exception\NoSslException;
use Composer\XdebugHandler\XdebugHandler;
use _ContaoManager\Symfony\Component\Console\SingleCommandApplication;
use _ContaoManager\Symfony\Component\Process\Exception\ProcessTimedOutException;
/**
 * The console application that handles the commands
 *
 * @author Ryan Weaver <ryan@knplabs.com>
 * @author Jordi Boggiano <j.boggiano@seld.be>
 * @author François Pluchino <francois.pluchino@opendisplay.com>
 */
class Application extends BaseApplication
{
    /**
     * @var ?Composer
     */
    protected $composer;
    /**
     * @var IOInterface
     */
    protected $io;
    /** @var string */
    private static $logo = '   ______
  / ____/___  ____ ___  ____  ____  ________  _____
 / /   / __ \/ __ `__ \/ __ \/ __ \/ ___/ _ \/ ___/
/ /___/ /_/ / / / / / / /_/ / /_/ (__  )  __/ /
\____/\____/_/ /_/ /_/ .___/\____/____/\___/_/
                    /_/
';
    /** @var bool */
    private $hasPluginCommands = \false;
    /** @var bool */
    private $disablePluginsByDefault = \false;
    /** @var bool */
    private $disableScriptsByDefault = \false;
    /**
     * @var string|false Store the initial working directory at startup time
     */
    private $initialWorkingDirectory;
    public function __construct(string $name = 'Composer', string $version = '')
    {
        if (method_exists($this, 'setCatchErrors')) {
            $this->setCatchErrors(\true);
        }
        static $shutdownRegistered = \false;
        if ($version === '') {
            $version = Composer::getVersion();
        }
        if (function_exists('ini_set') && extension_loaded('xdebug')) {
            ini_set('xdebug.show_exception_trace', '0');
            ini_set('xdebug.scream', '0');
        }
        if (function_exists('date_default_timezone_set') && function_exists('date_default_timezone_get')) {
            date_default_timezone_set(Silencer::call('date_default_timezone_get'));
        }
        $this->io = new NullIO();
        if (!$shutdownRegistered) {
            $shutdownRegistered = \true;
            register_shutdown_function(static function (): void {
                $lastError = error_get_last();
                if ($lastError && $lastError['message'] && (strpos($lastError['message'], 'Allowed memory') !== \false || strpos($lastError['message'], 'exceeded memory') !== \false)) {
                    echo "\n" . 'Check https://getcomposer.org/doc/articles/troubleshooting.md#memory-limit-errors for more info on how to handle out of memory errors.';
                }
            });
        }
        $this->initialWorkingDirectory = getcwd();
        parent::__construct($name, $version);
    }
    public function __destruct()
    {
    }
    public function run(?InputInterface $input = null, ?OutputInterface $output = null): int
    {
        if (null === $output) {
            $output = Factory::createOutput();
        }
        return parent::run($input, $output);
    }
    public function doRun(InputInterface $input, OutputInterface $output): int
    {
        $this->disablePluginsByDefault = $input->hasParameterOption('--no-plugins');
        $this->disableScriptsByDefault = $input->hasParameterOption('--no-scripts');
        static $stdin = null;
        if (null === $stdin) {
            $stdin = defined('STDIN') ? \STDIN : fopen('php://stdin', 'r');
        }
        if (Platform::getEnv('COMPOSER_TESTS_ARE_RUNNING') !== '1' && (Platform::getEnv('COMPOSER_NO_INTERACTION') || $stdin === \false || !Platform::isTty($stdin))) {
            $input->setInteractive(\false);
        }
        $io = $this->io = new ConsoleIO($input, $output, new HelperSet([new QuestionHelper()]));
        // Register error handler again to pass it the IO instance
        ErrorHandler::register($io);
        if ($input->hasParameterOption('--no-cache')) {
            $io->writeError('Disabling cache usage', \true, IOInterface::DEBUG);
            Platform::putEnv('COMPOSER_CACHE_DIR', Platform::isWindows() ? 'nul' : '/dev/null');
        }
        // switch working dir
        $newWorkDir = $this->getNewWorkingDir($input);
        if (null !== $newWorkDir) {
            $oldWorkingDir = Platform::getCwd(\true);
            chdir($newWorkDir);
            $this->initialWorkingDirectory = getcwd();
            $cwd = Platform::getCwd(\true);
            $io->writeError('Changed CWD to ' . ($cwd !== '' ? $cwd : $newWorkDir), \true, IOInterface::DEBUG);
        }
        // determine command name to be executed without including plugin commands
        $commandName = '';
        if ($rawCommandName = $this->getCommandNameBeforeBinding($input)) {
            try {
                $commandName = $this->find($rawCommandName)->getName();
            } catch (CommandNotFoundException $e) {
                // we'll check command validity again later after plugins are loaded
                $commandName = \false;
            } catch (\InvalidArgumentException $e) {
            }
        }
        // prompt user for dir change if no composer.json is present in current dir
        if (null === $newWorkDir && !in_array($commandName, ['', 'list', 'init', 'about', 'help', 'diagnose', 'self-update', 'global', 'create-project', 'outdated'], \true) && !file_exists(Factory::getComposerFile()) && ($useParentDirIfNoJsonAvailable = $this->getUseParentDirConfigValue()) !== \false && ($commandName !== 'config' || $input->hasParameterOption('--file', \true) === \false && $input->hasParameterOption('-f', \true) === \false) && $input->hasParameterOption('--help', \true) === \false && $input->hasParameterOption('-h', \true) === \false) {
            $dir = dirname(Platform::getCwd(\true));
            $home = realpath((Platform::getEnv('HOME') ?: Platform::getEnv('USERPROFILE')) ?: '/');
            // abort when we reach the home dir or top of the filesystem
            while (dirname($dir) !== $dir && $dir !== $home) {
                if (file_exists($dir . '/' . Factory::getComposerFile())) {
                    if ($useParentDirIfNoJsonAvailable !== \true && !$io->isInteractive()) {
                        $io->writeError('<info>No composer.json in current directory, to use the one at ' . $dir . ' run interactively or set config.use-parent-dir to true</info>');
                        break;
                    }
                    if ($useParentDirIfNoJsonAvailable === \true || $io->askConfirmation('<info>No composer.json in current directory, do you want to use the one at ' . $dir . '?</info> [<comment>y,n</comment>]? ')) {
                        if ($useParentDirIfNoJsonAvailable === \true) {
                            $io->writeError('<info>No composer.json in current directory, changing working directory to ' . $dir . '</info>');
                        } else {
                            $io->writeError('<info>Always want to use the parent dir? Use "composer config --global use-parent-dir true" to change the default.</info>');
                        }
                        $oldWorkingDir = Platform::getCwd(\true);
                        chdir($dir);
                    }
                    break;
                }
                $dir = dirname($dir);
            }
            unset($dir, $home);
        }
        $needsSudoCheck = !Platform::isWindows() && function_exists('exec') && !Platform::getEnv('COMPOSER_ALLOW_SUPERUSER') && !Platform::isDocker();
        $isNonAllowedRoot = \false;
        // Clobber sudo credentials if COMPOSER_ALLOW_SUPERUSER is not set before loading plugins
        if ($needsSudoCheck) {
            $isNonAllowedRoot = $this->isRunningAsRoot();
            if ($isNonAllowedRoot) {
                if ($uid = (int) Platform::getEnv('SUDO_UID')) {
                    // Silently clobber any sudo credentials on the invoking user to avoid privilege escalations later on
                    // ref. https://github.com/composer/composer/issues/5119
                    Silencer::call('exec', "sudo -u \\#{$uid} sudo -K > /dev/null 2>&1");
                }
            }
            // Silently clobber any remaining sudo leases on the current user as well to avoid privilege escalations
            Silencer::call('exec', 'sudo -K > /dev/null 2>&1');
        }
        // avoid loading plugins/initializing the Composer instance earlier than necessary if no plugin command is needed
        // if showing the version, we never need plugin commands
        $mayNeedPluginCommand = \false === $input->hasParameterOption(['--version', '-V']) && (\false === $commandName || in_array($commandName, ['', 'list', 'help'], \true) || $commandName === '_complete' && !$isNonAllowedRoot);
        $mayNeedScriptCommand = $mayNeedPluginCommand || $commandName === 'run-script' || $rawCommandName !== $commandName;
        if ($mayNeedPluginCommand && !$this->disablePluginsByDefault && !$this->hasPluginCommands) {
            // at this point plugins are needed, so if we are running as root and it is not allowed we need to prompt
            // if interactive, and abort otherwise
            if ($isNonAllowedRoot) {
                $io->writeError('<warning>Do not run Composer as root/super user! See https://getcomposer.org/root for details</warning>');
                if ($io->isInteractive() && $io->askConfirmation('<info>Continue as root/super user</info> [<comment>yes</comment>]? ')) {
                    // avoid a second prompt later
                    $isNonAllowedRoot = \false;
                } else {
                    $io->writeError('<warning>Aborting as no plugin should be loaded if running as super user is not explicitly allowed</warning>');
                    return 1;
                }
            }
            try {
                foreach ($this->getPluginCommands() as $command) {
                    if ($this->has($command->getName())) {
                        $io->writeError('<warning>Plugin command ' . $command->getName() . ' (' . get_class($command) . ') would override a Composer command and has been skipped</warning>');
                    } else {
                        // Compatibility layer for symfony/console <7.4
                        // @phpstan-ignore method.notFound, function.alreadyNarrowedType
                        method_exists($this, 'addCommand') ? $this->addCommand($command) : $this->add($command);
                    }
                }
            } catch (NoSslException $e) {
                // suppress these as they are not relevant at this point
            } catch (ParsingException $e) {
                $details = $e->getDetails();
                $file = realpath(Factory::getComposerFile());
                $line = null;
                if ($details && isset($details['line'])) {
                    $line = $details['line'];
                }
                $ghe = new \Composer\Console\GithubActionError($this->io);
                $ghe->emit($e->getMessage(), $file, $line);
                throw $e;
            }
            $this->hasPluginCommands = \true;
        }
        if (!$this->disablePluginsByDefault && $isNonAllowedRoot && !$io->isInteractive()) {
            $io->writeError('<error>Composer plugins have been disabled for safety in this non-interactive session.</error>');
            $io->writeError('<error>Set COMPOSER_ALLOW_SUPERUSER=1 if you want to allow plugins to run as root/super user.</error>');
            $this->disablePluginsByDefault = \true;
        }
        // determine command name to be executed incl plugin commands, and check if it's a proxy command
        $isProxyCommand = \false;
        if ($name = $this->getCommandNameBeforeBinding($input)) {
            try {
                $command = $this->find($name);
                $commandName = $command->getName();
                $isProxyCommand = $command instanceof Command\BaseCommand && $command->isProxyCommand();
            } catch (\InvalidArgumentException $e) {
            }
        }
        if (!$isProxyCommand) {
            $io->writeError(sprintf('Running %s (%s) with %s on %s', Composer::getVersion(), Composer::RELEASE_DATE, defined('HHVM_VERSION') ? 'HHVM ' . HHVM_VERSION : 'PHP ' . \PHP_VERSION, function_exists('php_uname') ? php_uname('s') . ' / ' . php_uname('r') : 'Unknown OS'), \true, IOInterface::DEBUG);
            if (\PHP_VERSION_ID < 70205) {
                $io->writeError('<warning>Composer supports PHP 7.2.5 and above, you will most likely encounter problems with your PHP ' . \PHP_VERSION . '. Upgrading is strongly recommended but you can use Composer 2.2.x LTS as a fallback.</warning>');
            }
            if (XdebugHandler::isXdebugActive() && !Platform::getEnv('COMPOSER_DISABLE_XDEBUG_WARN')) {
                $io->writeError('<warning>Composer is operating slower than normal because you have Xdebug enabled. See https://getcomposer.org/xdebug</warning>');
            }
            if (defined('COMPOSER_DEV_WARNING_TIME') && $commandName !== 'self-update' && $commandName !== 'selfupdate' && time() > \COMPOSER_DEV_WARNING_TIME) {
                $io->writeError(sprintf('<warning>Warning: This development build of Composer is over 60 days old. It is recommended to update it by running "%s self-update" to get the latest version.</warning>', $_SERVER['PHP_SELF']));
            }
            if ($isNonAllowedRoot) {
                if ($commandName !== 'self-update' && $commandName !== 'selfupdate' && $commandName !== '_complete') {
                    $io->writeError('<warning>Do not run Composer as root/super user! See https://getcomposer.org/root for details</warning>');
                    if ($io->isInteractive()) {
                        if (!$io->askConfirmation('<info>Continue as root/super user</info> [<comment>yes</comment>]? ')) {
                            return 1;
                        }
                    }
                }
            }
            // Check system temp folder for usability as it can cause weird runtime issues otherwise
            Silencer::call(static function () use ($io): void {
                $pid = function_exists('getmypid') ? getmypid() . '-' : '';
                $tempfile = sys_get_temp_dir() . '/temp-' . $pid . bin2hex(random_bytes(5));
                if (!(file_put_contents($tempfile, __FILE__) && file_get_contents($tempfile) === __FILE__ && unlink($tempfile) && !file_exists($tempfile))) {
                    $io->writeError(sprintf('<error>PHP temp directory (%s) does not exist or is not writable to Composer. Set sys_temp_dir in your php.ini</error>', sys_get_temp_dir()));
                }
            });
            // add non-standard scripts as own commands
            $file = Factory::getComposerFile();
            if ($mayNeedScriptCommand && is_file($file) && Filesystem::isReadable($file) && is_array($composerJson = json_decode(file_get_contents($file), \true))) {
                if (isset($composerJson['scripts']) && is_array($composerJson['scripts'])) {
                    foreach ($composerJson['scripts'] as $script => $dummy) {
                        if (!defined('Composer\Script\ScriptEvents::' . str_replace('-', '_', strtoupper($script)))) {
                            if ($this->has($script)) {
                                $io->writeError('<warning>A script named ' . $script . ' would override a Composer command and has been skipped</warning>');
                            } else {
                                $description = 'Runs the ' . $script . ' script as defined in composer.json';
                                if (isset($composerJson['scripts-descriptions'][$script])) {
                                    $description = $composerJson['scripts-descriptions'][$script];
                                }
                                $aliases = $composerJson['scripts-aliases'][$script] ?? [];
                                $composer = $this->getComposer(\false);
                                if ($composer !== null) {
                                    $rootPackage = $composer->getPackage();
                                    $generator = $composer->getAutoloadGenerator();
                                    $packageMap = $generator->buildPackageMap($composer->getInstallationManager(), $rootPackage, []);
                                    $map = $generator->parseAutoloads($packageMap, $rootPackage);
                                    $loader = $generator->createLoader($map, $composer->getConfig()->get('vendor-dir'));
                                    $loader->register(\false);
                                }
                                // if the command is not an array of commands, and points to a valid Command subclass, import its details directly
                                if (is_string($dummy) && class_exists($dummy) && is_subclass_of($dummy, SymfonyCommand::class)) {
                                    if (is_subclass_of($dummy, SingleCommandApplication::class)) {
                                        $io->writeError('<warning>The script named ' . $script . ' extends SingleCommandApplication which is not compatible with Composer 2.9+, make sure you extend Symfony\Component\Console\Command instead.</warning>');
                                    }
                                    $cmd = new $dummy($script);
                                    // makes sure the command is find()'able by the name defined in composer.json, and the name isn't overridden in its configure()
                                    if ($cmd->getName() !== '' && $cmd->getName() !== null && $cmd->getName() !== $script) {
                                        $io->writeError('<warning>The script named ' . $script . ' in composer.json has a mismatched name in its class definition. For consistency, either use the same name, or do not define one inside the class.</warning>');
                                        $cmd->setName($script);
                                        // override it with the defined script name
                                    }
                                    if ($cmd->getDescription() === '' && is_string($description)) {
                                        $cmd->setDescription($description);
                                    }
                                } else {
                                    // fallback to usual aliasing behavior
                                    $cmd = new Command\ScriptAliasCommand($script, $description, $aliases);
                                }
                                // Compatibility layer for symfony/console <7.4
                                // @phpstan-ignore method.notFound, function.alreadyNarrowedType
                                method_exists($this, 'addCommand') ? $this->addCommand($cmd) : $this->add($cmd);
                            }
                        }
                    }
                }
            }
        }
        try {
            if ($input->hasParameterOption('--profile')) {
                $startTime = microtime(\true);
                $this->io->enableDebugging($startTime);
            }
            $result = parent::doRun($input, $output);
            if (\true === $input->hasParameterOption(['--version', '-V'], \true)) {
                $io->writeError(sprintf('<info>PHP</info> version <comment>%s</comment> (%s)', \PHP_VERSION, \PHP_BINARY));
                $io->writeError('Run the "diagnose" command to get more detailed diagnostics output.');
            }
            // chdir back to $oldWorkingDir if set
            if (isset($oldWorkingDir) && '' !== $oldWorkingDir) {
                Silencer::call('chdir', $oldWorkingDir);
            }
            if (isset($startTime)) {
                $io->writeError('<info>Memory usage: ' . round(memory_get_usage() / 1024 / 1024, 2) . 'MiB (peak: ' . round(memory_get_peak_usage() / 1024 / 1024, 2) . 'MiB), time: ' . round(microtime(\true) - $startTime, 2) . 's</info>');
            }
            return $result;
        } catch (ScriptExecutionException $e) {
            if ($this->getDisablePluginsByDefault() && $this->isRunningAsRoot() && !$this->io->isInteractive()) {
                $io->writeError('<error>Plugins have been disabled automatically as you are running as root, this may be the cause of the script failure.</error>', \true, IOInterface::QUIET);
                $io->writeError('<error>See also https://getcomposer.org/root</error>', \true, IOInterface::QUIET);
            }
            return $e->getCode();
        } catch (\Throwable $e) {
            $ghe = new \Composer\Console\GithubActionError($this->io);
            $ghe->emit($e->getMessage());
            $this->hintCommonErrors($e, $output);
            // symfony/console <6.4 does not handle \Error subtypes so we have to renderThrowable ourselves
            // instead of rethrowing those for consumption by the parent class
            // can be removed when Composer supports PHP 8.1+
            if (!method_exists($this, 'setCatchErrors') && !$e instanceof \Exception) {
                if ($output instanceof ConsoleOutputInterface) {
                    $this->renderThrowable($e, $output->getErrorOutput());
                } else {
                    $this->renderThrowable($e, $output);
                }
                return max(1, $e->getCode());
            }
            // override TransportException's code for the purpose of parent::run() using it as process exit code
            // as http error codes are all beyond the 255 range of permitted exit codes
            if ($e instanceof TransportException) {
                $reflProp = new \ReflectionProperty($e, 'code');
                \PHP_VERSION_ID < 80100 and $reflProp->setAccessible(\true);
                $reflProp->setValue($e, Installer::ERROR_TRANSPORT_EXCEPTION);
            }
            throw $e;
        } finally {
            restore_error_handler();
        }
    }
    /**
     * @throws RuntimeException
     */
    private function getNewWorkingDir(InputInterface $input): ?string
    {
        /** @var string|null $workingDir */
        $workingDir = $input->getParameterOption(['--working-dir', '-d'], null, \true);
        if (null !== $workingDir && !is_dir($workingDir)) {
            throw new RuntimeException('Invalid working directory specified, ' . $workingDir . ' does not exist.');
        }
        return $workingDir;
    }
    private function hintCommonErrors(\Throwable $exception, OutputInterface $output): void
    {
        $io = $this->getIO();
        if ((get_class($exception) === LogicException::class || $exception instanceof \Error) && $output->getVerbosity() < OutputInterface::VERBOSITY_VERBOSE) {
            $output->setVerbosity(OutputInterface::VERBOSITY_VERBOSE);
        }
        Silencer::suppress();
        try {
            $composer = $this->getComposer(\false, \true);
            if (null !== $composer && function_exists('disk_free_space')) {
                $config = $composer->getConfig();
                $minSpaceFree = 100 * 1024 * 1024;
                if (($df = disk_free_space($dir = $config->get('home'))) !== \false && $df < $minSpaceFree || ($df = disk_free_space($dir = $config->get('vendor-dir'))) !== \false && $df < $minSpaceFree || ($df = disk_free_space($dir = sys_get_temp_dir())) !== \false && $df < $minSpaceFree) {
                    $io->writeError('<error>The disk hosting ' . $dir . ' has less than 100MiB of free space, this may be the cause of the following exception</error>', \true, IOInterface::QUIET);
                }
            }
        } catch (\Exception $e) {
        }
        Silencer::restore();
        if ($exception instanceof TransportException && str_contains($exception->getMessage(), 'Unable to use a proxy')) {
            $io->writeError('<error>The following exception indicates your proxy is misconfigured</error>', \true, IOInterface::QUIET);
            $io->writeError('<error>Check https://getcomposer.org/doc/faqs/how-to-use-composer-behind-a-proxy.md for details</error>', \true, IOInterface::QUIET);
        }
        if (Platform::isWindows() && $exception instanceof TransportException && str_contains($exception->getMessage(), 'unable to get local issuer certificate')) {
            $avastDetect = glob('C:\Program Files\Avast*');
            if (is_array($avastDetect) && count($avastDetect) !== 0) {
                $io->writeError('<error>The following exception indicates a possible issue with the Avast Firewall</error>', \true, IOInterface::QUIET);
                $io->writeError('<error>Check https://getcomposer.org/local-issuer for details</error>', \true, IOInterface::QUIET);
            } else {
                $io->writeError('<error>The following exception indicates a possible issue with a Firewall/Antivirus</error>', \true, IOInterface::QUIET);
                $io->writeError('<error>Check https://getcomposer.org/local-issuer for details</error>', \true, IOInterface::QUIET);
            }
        }
        if (Platform::isWindows() && \false !== strpos($exception->getMessage(), 'The system cannot find the path specified')) {
            $io->writeError('<error>The following exception may be caused by a stale entry in your cmd.exe AutoRun</error>', \true, IOInterface::QUIET);
            $io->writeError('<error>Check https://getcomposer.org/doc/articles/troubleshooting.md#-the-system-cannot-find-the-path-specified-windows- for details</error>', \true, IOInterface::QUIET);
        }
        if (\false !== strpos($exception->getMessage(), 'fork failed - Cannot allocate memory')) {
            $io->writeError('<error>The following exception is caused by a lack of memory or swap, or not having swap configured</error>', \true, IOInterface::QUIET);
            $io->writeError('<error>Check https://getcomposer.org/doc/articles/troubleshooting.md#proc-open-fork-failed-errors for details</error>', \true, IOInterface::QUIET);
        }
        if ($exception instanceof ProcessTimedOutException) {
            $io->writeError('<error>The following exception is caused by a process timeout</error>', \true, IOInterface::QUIET);
            $io->writeError('<error>Check https://getcomposer.org/doc/06-config.md#process-timeout for details</error>', \true, IOInterface::QUIET);
        }
        if ($this->getDisablePluginsByDefault() && $this->isRunningAsRoot() && !$this->io->isInteractive()) {
            $io->writeError('<error>Plugins have been disabled automatically as you are running as root, this may be the cause of the following exception. See also https://getcomposer.org/root</error>', \true, IOInterface::QUIET);
        } elseif ($exception instanceof CommandNotFoundException && $this->getDisablePluginsByDefault()) {
            $io->writeError('<error>Plugins have been disabled, which may be why some commands are missing, unless you made a typo</error>', \true, IOInterface::QUIET);
        }
        $hints = HttpDownloader::getExceptionHints($exception);
        if (null !== $hints && count($hints) > 0) {
            foreach ($hints as $hint) {
                $io->writeError($hint, \true, IOInterface::QUIET);
            }
        }
    }
    /**
     * @throws JsonValidationException
     * @throws \InvalidArgumentException
     * @return ?Composer If $required is true then the return value is guaranteed
     */
    public function getComposer(bool $required = \true, ?bool $disablePlugins = null, ?bool $disableScripts = null): ?Composer
    {
        if (null === $disablePlugins) {
            $disablePlugins = $this->disablePluginsByDefault;
        }
        if (null === $disableScripts) {
            $disableScripts = $this->disableScriptsByDefault;
        }
        if (null === $this->composer) {
            try {
                $this->composer = Factory::create(Platform::isInputCompletionProcess() ? new NullIO() : $this->io, null, $disablePlugins, $disableScripts);
            } catch (\InvalidArgumentException $e) {
                if ($required) {
                    $this->io->writeError($e->getMessage());
                    if ($this->areExceptionsCaught()) {
                        exit(1);
                    }
                    throw $e;
                }
            } catch (JsonValidationException $e) {
                if ($required) {
                    throw $e;
                }
            } catch (RuntimeException $e) {
                if ($required) {
                    throw $e;
                }
            }
        }
        return $this->composer;
    }
    /**
     * Removes the cached composer instance
     */
    public function resetComposer(): void
    {
        $this->composer = null;
        if (method_exists($this->getIO(), 'resetAuthentications')) {
            $this->getIO()->resetAuthentications();
        }
    }
    public function getIO(): IOInterface
    {
        return $this->io;
    }
    public function getHelp(): string
    {
        return self::$logo . parent::getHelp();
    }
    /**
     * Initializes all the composer commands.
     * @return SymfonyCommand[]
     */
    protected function getDefaultCommands(): array
    {
        return array_merge(parent::getDefaultCommands(), [new Command\AboutCommand(), new Command\ConfigCommand(), new Command\DependsCommand(), new Command\ProhibitsCommand(), new Command\InitCommand(), new Command\InstallCommand(), new Command\CreateProjectCommand(), new Command\UpdateCommand(), new Command\SearchCommand(), new Command\ValidateCommand(), new Command\AuditCommand(), new Command\ShowCommand(), new Command\SuggestsCommand(), new Command\RequireCommand(), new Command\DumpAutoloadCommand(), new Command\StatusCommand(), new Command\ArchiveCommand(), new Command\DiagnoseCommand(), new Command\RunScriptCommand(), new Command\LicensesCommand(), new Command\GlobalCommand(), new Command\ClearCacheCommand(), new Command\RemoveCommand(), new Command\HomeCommand(), new Command\ExecCommand(), new Command\OutdatedCommand(), new Command\CheckPlatformReqsCommand(), new Command\FundCommand(), new Command\ReinstallCommand(), new Command\BumpCommand(), new Command\RepositoryCommand(), new Command\SelfUpdateCommand()]);
    }
    /**
     * This ensures we can find the correct command name even if a global input option is present before it
     *
     * e.g. "composer -d foo bar" should detect bar as the command name, and not foo
     */
    private function getCommandNameBeforeBinding(InputInterface $input): ?string
    {
        $input = clone $input;
        try {
            // Makes ArgvInput::getFirstArgument() able to distinguish an option from an argument.
            $input->bind($this->getDefinition());
        } catch (ExceptionInterface $e) {
            // Errors must be ignored, full binding/validation happens later when the command is known.
        }
        return $input->getFirstArgument();
    }
    public function getLongVersion(): string
    {
        $branchAliasString = '';
        if (Composer::BRANCH_ALIAS_VERSION && Composer::BRANCH_ALIAS_VERSION !== '@package_branch_alias_version' . '@') {
            $branchAliasString = sprintf(' (%s)', Composer::BRANCH_ALIAS_VERSION);
        }
        return sprintf('<info>%s</info> version <comment>%s%s</comment> %s', $this->getName(), $this->getVersion(), $branchAliasString, Composer::RELEASE_DATE);
    }
    protected function getDefaultInputDefinition(): InputDefinition
    {
        $definition = parent::getDefaultInputDefinition();
        $definition->addOption(new InputOption('--profile', null, InputOption::VALUE_NONE, 'Display timing and memory usage information'));
        $definition->addOption(new InputOption('--no-plugins', null, InputOption::VALUE_NONE, 'Whether to disable plugins.'));
        $definition->addOption(new InputOption('--no-scripts', null, InputOption::VALUE_NONE, 'Skips the execution of all scripts defined in composer.json file.'));
        $definition->addOption(new InputOption('--working-dir', '-d', InputOption::VALUE_REQUIRED, 'If specified, use the given directory as working directory.'));
        $definition->addOption(new InputOption('--no-cache', null, InputOption::VALUE_NONE, 'Prevent use of the cache'));
        return $definition;
    }
    /**
     * @return Command\BaseCommand[]
     */
    private function getPluginCommands(): array
    {
        $commands = [];
        $composer = $this->getComposer(\false, \false);
        if (null === $composer) {
            $composer = Factory::createGlobal($this->io, $this->disablePluginsByDefault, $this->disableScriptsByDefault);
        }
        if (null !== $composer) {
            $pm = $composer->getPluginManager();
            foreach ($pm->getPluginCapabilities('Composer\Plugin\Capability\CommandProvider', ['composer' => $composer, 'io' => $this->io]) as $capability) {
                $newCommands = $capability->getCommands();
                if (!is_array($newCommands)) {
                    throw new \UnexpectedValueException('Plugin capability ' . get_class($capability) . ' failed to return an array from getCommands');
                }
                foreach ($newCommands as $command) {
                    if (!$command instanceof Command\BaseCommand) {
                        throw new \UnexpectedValueException('Plugin capability ' . get_class($capability) . ' returned an invalid value, we expected an array of Composer\Command\BaseCommand objects');
                    }
                }
                $commands = array_merge($commands, $newCommands);
            }
        }
        return $commands;
    }
    /**
     * Get the working directory at startup time
     *
     * @return string|false
     */
    public function getInitialWorkingDirectory()
    {
        return $this->initialWorkingDirectory;
    }
    public function getDisablePluginsByDefault(): bool
    {
        return $this->disablePluginsByDefault;
    }
    public function getDisableScriptsByDefault(): bool
    {
        return $this->disableScriptsByDefault;
    }
    /**
     * @return 'prompt'|bool
     */
    private function getUseParentDirConfigValue()
    {
        $config = Factory::createConfig($this->io);
        return $config->get('use-parent-dir');
    }
    private function isRunningAsRoot(): bool
    {
        return function_exists('posix_getuid') && posix_getuid() === 0;
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer\Console;

use Composer\IO\IOInterface;
use Composer\Util\Platform;
final class GithubActionError
{
    /**
     * @var IOInterface
     */
    protected $io;
    public function __construct(IOInterface $io)
    {
        $this->io = $io;
    }
    public function emit(string $message, ?string $file = null, ?int $line = null): void
    {
        if (Platform::getEnv('GITHUB_ACTIONS') && !Platform::getEnv('COMPOSER_TESTS_ARE_RUNNING')) {
            $message = $this->escapeData($message);
            if ($file && $line) {
                $file = $this->escapeProperty($file);
                $this->io->write("::error file=" . $file . ",line=" . $line . "::" . $message);
            } elseif ($file) {
                $file = $this->escapeProperty($file);
                $this->io->write("::error file=" . $file . "::" . $message);
            } else {
                $this->io->write("::error ::" . $message);
            }
        }
    }
    private function escapeData(string $data): string
    {
        // see https://github.com/actions/toolkit/blob/4f7fb6513a355689f69f0849edeb369a4dc81729/packages/core/src/command.ts#L80-L85
        $data = str_replace("%", '%25', $data);
        $data = str_replace("\r", '%0D', $data);
        $data = str_replace("\n", '%0A', $data);
        return $data;
    }
    private function escapeProperty(string $property): string
    {
        // see https://github.com/actions/toolkit/blob/4f7fb6513a355689f69f0849edeb369a4dc81729/packages/core/src/command.ts#L87-L94
        $property = str_replace("%", '%25', $property);
        $property = str_replace("\r", '%0D', $property);
        $property = str_replace("\n", '%0A', $property);
        $property = str_replace(":", '%3A', $property);
        $property = str_replace(",", '%2C', $property);
        return $property;
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer\Console\Input;

use _ContaoManager\Symfony\Component\Console\Completion\CompletionInput;
use _ContaoManager\Symfony\Component\Console\Completion\CompletionSuggestions;
use _ContaoManager\Symfony\Component\Console\Completion\Suggestion;
use _ContaoManager\Symfony\Component\Console\Exception\InvalidArgumentException;
use _ContaoManager\Symfony\Component\Console\Exception\LogicException;
use _ContaoManager\Symfony\Component\Console\Input\InputArgument as BaseInputArgument;
/**
 * Backport suggested values definition from symfony/console 6.1+
 *
 * @author Jérôme Tamarelle <jerome@tamarelle.net>
 *
 * @internal
 *
 * TODO symfony/console:6.1 drop when PHP 8.1 / symfony 6.1+ can be required
 */
class InputArgument extends BaseInputArgument
{
    /**
     * @var list<string>|\Closure(CompletionInput,CompletionSuggestions):list<string|Suggestion>
     */
    private $suggestedValues;
    /**
     * @param string                              $name        The argument name
     * @param int|null                            $mode        The argument mode: self::REQUIRED or self::OPTIONAL
     * @param string                              $description A description text
     * @param string|bool|int|float|string[]|null $default     The default value (for self::OPTIONAL mode only)
     * @param list<string>|\Closure(CompletionInput,CompletionSuggestions):list<string|Suggestion> $suggestedValues The values used for input completion
     *
     * @throws InvalidArgumentException When argument mode is not valid
     */
    public function __construct(string $name, ?int $mode = null, string $description = '', $default = null, $suggestedValues = [])
    {
        parent::__construct($name, $mode, $description, $default);
        $this->suggestedValues = $suggestedValues;
    }
    /**
     * Adds suggestions to $suggestions for the current completion input.
     *
     * @see Command::complete()
     */
    public function complete(CompletionInput $input, CompletionSuggestions $suggestions): void
    {
        $values = $this->suggestedValues;
        if ($values instanceof \Closure && !\is_array($values = $values($input, $suggestions))) {
            // @phpstan-ignore function.impossibleType
            throw new LogicException(sprintf('Closure for option "%s" must return an array. Got "%s".', $this->getName(), get_debug_type($values)));
        }
        if ([] !== $values) {
            $suggestions->suggestValues($values);
        }
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer\Console\Input;

use _ContaoManager\Symfony\Component\Console\Completion\CompletionInput;
use _ContaoManager\Symfony\Component\Console\Completion\CompletionSuggestions;
use _ContaoManager\Symfony\Component\Console\Completion\Suggestion;
use _ContaoManager\Symfony\Component\Console\Exception\InvalidArgumentException;
use _ContaoManager\Symfony\Component\Console\Exception\LogicException;
use _ContaoManager\Symfony\Component\Console\Input\InputOption as BaseInputOption;
/**
 * Backport suggested values definition from symfony/console 6.1+
 *
 * @author Jérôme Tamarelle <jerome@tamarelle.net>
 *
 * @internal
 *
 * TODO symfony/console:6.1 drop when PHP 8.1 / symfony 6.1+ can be required
 */
class InputOption extends BaseInputOption
{
    /**
     * @var list<string>|\Closure(CompletionInput,CompletionSuggestions):list<string|Suggestion>
     */
    private $suggestedValues;
    /**
     * @param string|string[]|null                $shortcut The shortcuts, can be null, a string of shortcuts delimited by | or an array of shortcuts
     * @param int|null                            $mode     The option mode: One of the VALUE_* constants
     * @param string|bool|int|float|string[]|null $default  The default value (must be null for self::VALUE_NONE)
     * @param list<string>|\Closure(CompletionInput,CompletionSuggestions):list<string|Suggestion> $suggestedValues The values used for input completionnull for self::VALUE_NONE)
     *
     * @throws InvalidArgumentException If option mode is invalid or incompatible
     */
    public function __construct(string $name, $shortcut = null, ?int $mode = null, string $description = '', $default = null, $suggestedValues = [])
    {
        parent::__construct($name, $shortcut, $mode, $description, $default);
        $this->suggestedValues = $suggestedValues;
        if ([] !== $suggestedValues && !$this->acceptValue()) {
            throw new LogicException('Cannot set suggested values if the option does not accept a value.');
        }
    }
    /**
     * Adds suggestions to $suggestions for the current completion input.
     *
     * @see Command::complete()
     */
    public function complete(CompletionInput $input, CompletionSuggestions $suggestions): void
    {
        $values = $this->suggestedValues;
        if ($values instanceof \Closure && !\is_array($values = $values($input, $suggestions))) {
            // @phpstan-ignore function.impossibleType
            throw new LogicException(sprintf('Closure for argument "%s" must return an array. Got "%s".', $this->getName(), get_debug_type($values)));
        }
        if ([] !== $values) {
            $suggestions->suggestValues($values);
        }
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer\Console;

use Closure;
use Composer\Pcre\Preg;
use _ContaoManager\Symfony\Component\Console\Formatter\OutputFormatter;
use _ContaoManager\Symfony\Component\Console\Formatter\OutputFormatterStyle;
/**
 * @author Jordi Boggiano <j.boggiano@seld.be>
 */
class HtmlOutputFormatter extends OutputFormatter
{
    /** @var array<int, string> */
    private static $availableForegroundColors = [30 => 'black', 31 => 'red', 32 => 'green', 33 => 'yellow', 34 => 'blue', 35 => 'magenta', 36 => 'cyan', 37 => 'white'];
    /** @var array<int, string> */
    private static $availableBackgroundColors = [40 => 'black', 41 => 'red', 42 => 'green', 43 => 'yellow', 44 => 'blue', 45 => 'magenta', 46 => 'cyan', 47 => 'white'];
    /** @var array<int, string> */
    private static $availableOptions = [1 => 'bold', 4 => 'underscore'];
    /**
     * @param array<string, OutputFormatterStyle> $styles Array of "name => FormatterStyle" instances
     */
    public function __construct(array $styles = [])
    {
        parent::__construct(\true, $styles);
    }
    public function format(?string $message): ?string
    {
        $formatted = parent::format($message);
        if ($formatted === null) {
            return null;
        }
        $clearEscapeCodes = '(?:39|49|0|22|24|25|27|28)';
        return Preg::replaceCallback("{\x1b\\[([0-9;]+)m(.*?)\x1b\\[(?:" . $clearEscapeCodes . ";)*?" . $clearEscapeCodes . "m}s", Closure::fromCallable([$this, 'formatHtml']), $formatted);
    }
    /**
     * @param array<string|null> $matches
     */
    private function formatHtml(array $matches): string
    {
        assert(is_string($matches[1]));
        $out = '<span style="';
        foreach (explode(';', $matches[1]) as $code) {
            if (isset(self::$availableForegroundColors[(int) $code])) {
                $out .= 'color:' . self::$availableForegroundColors[(int) $code] . ';';
            } elseif (isset(self::$availableBackgroundColors[(int) $code])) {
                $out .= 'background-color:' . self::$availableBackgroundColors[(int) $code] . ';';
            } elseif (isset(self::$availableOptions[(int) $code])) {
                switch (self::$availableOptions[(int) $code]) {
                    case 'bold':
                        $out .= 'font-weight:bold;';
                        break;
                    case 'underscore':
                        $out .= 'text-decoration:underline;';
                        break;
                }
            }
        }
        return $out . '">' . $matches[2] . '</span>';
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager;

/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
use Composer\Autoload\ClassLoader;
function includeIfExists(string $file): ?ClassLoader
{
    return \file_exists($file) ? include $file : null;
}
if (!($loader = includeIfExists(__DIR__ . '/../vendor/autoload.php')) && !$loader = includeIfExists(__DIR__ . '/../../../autoload.php')) {
    echo 'You must set up the project dependencies using `composer install`' . \PHP_EOL . 'See https://getcomposer.org/download/ for instructions on installing Composer' . \PHP_EOL;
    exit(1);
}
return $loader;
##
## Bundle of CA Root Certificates
##
## Certificate data from Mozilla last updated on: Wed Feb 11 18:26:30 2026 GMT
##
## Find updated versions here: https://curl.se/docs/caextract.html
##
## This is a bundle of X.509 certificates of public Certificate Authorities
## (CA). These were automatically extracted from Mozilla's root certificates
## file (certdata.txt).  This file can be found in the mozilla source tree:
## https://raw.githubusercontent.com/mozilla-firefox/firefox/refs/heads/release/security/nss/lib/ckfw/builtins/certdata.txt
##
## It contains the certificates in PEM format and therefore
## can be directly used with curl / libcurl / php_curl, or with
## an Apache+mod_ssl webserver for SSL client authentication.
## Just configure this file as the SSLCACertificateFile.
##
## Conversion done with mk-ca-bundle.pl version 1.32.
## SHA256: 3b98d4e3ff57a326d9587c33633039c8c3a9cf0b55f7ca581d7598ff329eb1f3
##


Entrust Root Certification Authority
====================================
-----BEGIN CERTIFICATE-----
MIIEkTCCA3mgAwIBAgIERWtQVDANBgkqhkiG9w0BAQUFADCBsDELMAkGA1UEBhMCVVMxFjAUBgNV
BAoTDUVudHJ1c3QsIEluYy4xOTA3BgNVBAsTMHd3dy5lbnRydXN0Lm5ldC9DUFMgaXMgaW5jb3Jw
b3JhdGVkIGJ5IHJlZmVyZW5jZTEfMB0GA1UECxMWKGMpIDIwMDYgRW50cnVzdCwgSW5jLjEtMCsG
A1UEAxMkRW50cnVzdCBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTA2MTEyNzIwMjM0
MloXDTI2MTEyNzIwNTM0MlowgbAxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1FbnRydXN0LCBJbmMu
MTkwNwYDVQQLEzB3d3cuZW50cnVzdC5uZXQvQ1BTIGlzIGluY29ycG9yYXRlZCBieSByZWZlcmVu
Y2UxHzAdBgNVBAsTFihjKSAyMDA2IEVudHJ1c3QsIEluYy4xLTArBgNVBAMTJEVudHJ1c3QgUm9v
dCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB
ALaVtkNC+sZtKm9I35RMOVcF7sN5EUFoNu3s/poBj6E4KPz3EEZmLk0eGrEaTsbRwJWIsMn/MYsz
A9u3g3s+IIRe7bJWKKf44LlAcTfFy0cOlypowCKVYhXbR9n10Cv/gkvJrT7eTNuQgFA/CYqEAOww
Cj0Yzfv9KlmaI5UXLEWeH25DeW0MXJj+SKfFI0dcXv1u5x609mhF0YaDW6KKjbHjKYD+JXGIrb68
j6xSlkuqUY3kEzEZ6E5Nn9uss2rVvDlUccp6en+Q3X0dgNmBu1kmwhH+5pPi94DkZfs0Nw4pgHBN
rziGLp5/V6+eF67rHMsoIV+2HNjnogQi+dPa2MsCAwEAAaOBsDCBrTAOBgNVHQ8BAf8EBAMCAQYw
DwYDVR0TAQH/BAUwAwEB/zArBgNVHRAEJDAigA8yMDA2MTEyNzIwMjM0MlqBDzIwMjYxMTI3MjA1
MzQyWjAfBgNVHSMEGDAWgBRokORnpKZTgMeGZqTx90tD+4S9bTAdBgNVHQ4EFgQUaJDkZ6SmU4DH
hmak8fdLQ/uEvW0wHQYJKoZIhvZ9B0EABBAwDhsIVjcuMTo0LjADAgSQMA0GCSqGSIb3DQEBBQUA
A4IBAQCT1DCw1wMgKtD5Y+iRDAUgqV8ZyntyTtSx29CW+1RaGSwMCPeyvIWonX9tO1KzKtvn1ISM
Y/YPyyYBkVBs9F8U4pN0wBOeMDpQ47RgxRzwIkSNcUesyBrJ6ZuaAGAT/3B+XxFNSRuzFVJ7yVTa
v52Vr2ua2J7p8eRDjeIRRDq/r72DQnNSi6q7pynP9WQcCk3RvKqsnyrQ/39/2n3qse0wJcGE2jTS
W3iDVuycNsMm4hH2Z0kdkquM++v/eu6FSqdQgPCnXEqULl8FmTxSQeDNtGPPAUO6nIPcj2A781q0
tHuu2guQOHXvgR1m0vdXcDazv/wor3ElhVsT/h5/WrQ8
-----END CERTIFICATE-----

QuoVadis Root CA 2
==================
-----BEGIN CERTIFICATE-----
MIIFtzCCA5+gAwIBAgICBQkwDQYJKoZIhvcNAQEFBQAwRTELMAkGA1UEBhMCQk0xGTAXBgNVBAoT
EFF1b1ZhZGlzIExpbWl0ZWQxGzAZBgNVBAMTElF1b1ZhZGlzIFJvb3QgQ0EgMjAeFw0wNjExMjQx
ODI3MDBaFw0zMTExMjQxODIzMzNaMEUxCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBM
aW1pdGVkMRswGQYDVQQDExJRdW9WYWRpcyBSb290IENBIDIwggIiMA0GCSqGSIb3DQEBAQUAA4IC
DwAwggIKAoICAQCaGMpLlA0ALa8DKYrwD4HIrkwZhR0In6spRIXzL4GtMh6QRr+jhiYaHv5+HBg6
XJxgFyo6dIMzMH1hVBHL7avg5tKifvVrbxi3Cgst/ek+7wrGsxDp3MJGF/hd/aTa/55JWpzmM+Yk
lvc/ulsrHHo1wtZn/qtmUIttKGAr79dgw8eTvI02kfN/+NsRE8Scd3bBrrcCaoF6qUWD4gXmuVbB
lDePSHFjIuwXZQeVikvfj8ZaCuWw419eaxGrDPmF60Tp+ARz8un+XJiM9XOva7R+zdRcAitMOeGy
lZUtQofX1bOQQ7dsE/He3fbE+Ik/0XX1ksOR1YqI0JDs3G3eicJlcZaLDQP9nL9bFqyS2+r+eXyt
66/3FsvbzSUr5R/7mp/iUcw6UwxI5g69ybR2BlLmEROFcmMDBOAENisgGQLodKcftslWZvB1Jdxn
wQ5hYIizPtGo/KPaHbDRsSNU30R2be1B2MGyIrZTHN81Hdyhdyox5C315eXbyOD/5YDXC2Og/zOh
D7osFRXql7PSorW+8oyWHhqPHWykYTe5hnMz15eWniN9gqRMgeKh0bpnX5UHoycR7hYQe7xFSkyy
BNKr79X9DFHOUGoIMfmR2gyPZFwDwzqLID9ujWc9Otb+fVuIyV77zGHcizN300QyNQliBJIWENie
J0f7OyHj+OsdWwIDAQABo4GwMIGtMA8GA1UdEwEB/wQFMAMBAf8wCwYDVR0PBAQDAgEGMB0GA1Ud
DgQWBBQahGK8SEwzJQTU7tD2A8QZRtGUazBuBgNVHSMEZzBlgBQahGK8SEwzJQTU7tD2A8QZRtGU
a6FJpEcwRTELMAkGA1UEBhMCQk0xGTAXBgNVBAoTEFF1b1ZhZGlzIExpbWl0ZWQxGzAZBgNVBAMT
ElF1b1ZhZGlzIFJvb3QgQ0EgMoICBQkwDQYJKoZIhvcNAQEFBQADggIBAD4KFk2fBluornFdLwUv
Z+YTRYPENvbzwCYMDbVHZF34tHLJRqUDGCdViXh9duqWNIAXINzng/iN/Ae42l9NLmeyhP3ZRPx3
UIHmfLTJDQtyU/h2BwdBR5YM++CCJpNVjP4iH2BlfF/nJrP3MpCYUNQ3cVX2kiF495V5+vgtJodm
VjB3pjd4M1IQWK4/YY7yarHvGH5KWWPKjaJW1acvvFYfzznB4vsKqBUsfU16Y8Zsl0Q80m/DShcK
+JDSV6IZUaUtl0HaB0+pUNqQjZRG4T7wlP0QADj1O+hA4bRuVhogzG9Yje0uRY/W6ZM/57Es3zrW
IozchLsib9D45MY56QSIPMO661V6bYCZJPVsAfv4l7CUW+v90m/xd2gNNWQjrLhVoQPRTUIZ3Ph1
WVaj+ahJefivDrkRoHy3au000LYmYjgahwz46P0u05B/B5EqHdZ+XIWDmbA4CD/pXvk1B+TJYm5X
f6dQlfe6yJvmjqIBxdZmv3lh8zwc4bmCXF2gw+nYSL0ZohEUGW6yhhtoPkg3Goi3XZZenMfvJ2II
4pEZXNLxId26F0KCl3GBUzGpn/Z9Yr9y4aOTHcyKJloJONDO1w2AFrR4pTqHTI2KpdVGl/IsELm8
VCLAAVBpQ570su9t+Oza8eOx79+Rj1QqCyXBJhnEUhAFZdWCEOrCMc0u
-----END CERTIFICATE-----

QuoVadis Root CA 3
==================
-----BEGIN CERTIFICATE-----
MIIGnTCCBIWgAwIBAgICBcYwDQYJKoZIhvcNAQEFBQAwRTELMAkGA1UEBhMCQk0xGTAXBgNVBAoT
EFF1b1ZhZGlzIExpbWl0ZWQxGzAZBgNVBAMTElF1b1ZhZGlzIFJvb3QgQ0EgMzAeFw0wNjExMjQx
OTExMjNaFw0zMTExMjQxOTA2NDRaMEUxCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBM
aW1pdGVkMRswGQYDVQQDExJRdW9WYWRpcyBSb290IENBIDMwggIiMA0GCSqGSIb3DQEBAQUAA4IC
DwAwggIKAoICAQDMV0IWVJzmmNPTTe7+7cefQzlKZbPoFog02w1ZkXTPkrgEQK0CSzGrvI2RaNgg
DhoB4hp7Thdd4oq3P5kazethq8Jlph+3t723j/z9cI8LoGe+AaJZz3HmDyl2/7FWeUUrH556VOij
KTVopAFPD6QuN+8bv+OPEKhyq1hX51SGyMnzW9os2l2ObjyjPtr7guXd8lyyBTNvijbO0BNO/79K
DDRMpsMhvVAEVeuxu537RR5kFd5VAYwCdrXLoT9CabwvvWhDFlaJKjdhkf2mrk7AyxRllDdLkgbv
BNDInIjbC3uBr7E9KsRlOni27tyAsdLTmZw67mtaa7ONt9XOnMK+pUsvFrGeaDsGb659n/je7Mwp
p5ijJUMv7/FfJuGITfhebtfZFG4ZM2mnO4SJk8RTVROhUXhA+LjJou57ulJCg54U7QVSWllWp5f8
nT8KKdjcT5EOE7zelaTfi5m+rJsziO+1ga8bxiJTyPbH7pcUsMV8eFLI8M5ud2CEpukqdiDtWAEX
MJPpGovgc2PZapKUSU60rUqFxKMiMPwJ7Wgic6aIDFUhWMXhOp8q3crhkODZc6tsgLjoC2SToJyM
Gf+z0gzskSaHirOi4XCPLArlzW1oUevaPwV/izLmE1xr/l9A4iLItLRkT9a6fUg+qGkM17uGcclz
uD87nSVL2v9A6wIDAQABo4IBlTCCAZEwDwYDVR0TAQH/BAUwAwEB/zCB4QYDVR0gBIHZMIHWMIHT
BgkrBgEEAb5YAAMwgcUwgZMGCCsGAQUFBwICMIGGGoGDQW55IHVzZSBvZiB0aGlzIENlcnRpZmlj
YXRlIGNvbnN0aXR1dGVzIGFjY2VwdGFuY2Ugb2YgdGhlIFF1b1ZhZGlzIFJvb3QgQ0EgMyBDZXJ0
aWZpY2F0ZSBQb2xpY3kgLyBDZXJ0aWZpY2F0aW9uIFByYWN0aWNlIFN0YXRlbWVudC4wLQYIKwYB
BQUHAgEWIWh0dHA6Ly93d3cucXVvdmFkaXNnbG9iYWwuY29tL2NwczALBgNVHQ8EBAMCAQYwHQYD
VR0OBBYEFPLAE+CCQz777i9nMpY1XNu4ywLQMG4GA1UdIwRnMGWAFPLAE+CCQz777i9nMpY1XNu4
ywLQoUmkRzBFMQswCQYDVQQGEwJCTTEZMBcGA1UEChMQUXVvVmFkaXMgTGltaXRlZDEbMBkGA1UE
AxMSUXVvVmFkaXMgUm9vdCBDQSAzggIFxjANBgkqhkiG9w0BAQUFAAOCAgEAT62gLEz6wPJv92ZV
qyM07ucp2sNbtrCD2dDQ4iH782CnO11gUyeim/YIIirnv6By5ZwkajGxkHon24QRiSemd1o417+s
hvzuXYO8BsbRd2sPbSQvS3pspweWyuOEn62Iix2rFo1bZhfZFvSLgNLd+LJ2w/w4E6oM3kJpK27z
POuAJ9v1pkQNn1pVWQvVDVJIxa6f8i+AxeoyUDUSly7B4f/xI4hROJ/yZlZ25w9Rl6VSDE1JUZU2
Pb+iSwwQHYaZTKrzchGT5Or2m9qoXadNt54CrnMAyNojA+j56hl0YgCUyyIgvpSnWbWCar6ZeXqp
8kokUvd0/bpO5qgdAm6xDYBEwa7TIzdfu4V8K5Iu6H6li92Z4b8nby1dqnuH/grdS/yO9SbkbnBC
bjPsMZ57k8HkyWkaPcBrTiJt7qtYTcbQQcEr6k8Sh17rRdhs9ZgC06DYVYoGmRmioHfRMJ6szHXu
g/WwYjnPbFfiTNKRCw51KBuav/0aQ/HKd/s7j2G4aSgWQgRecCocIdiP4b0jWy10QJLZYxkNc91p
vGJHvOB0K7Lrfb5BG7XARsWhIstfTsEokt4YutUqKLsRixeTmJlglFwjz1onl14LBQaTNx47aTbr
qZ5hHY8y2o4M1nQ+ewkk2gF3R8Q7zTSMmfXK4SVhM7JZG+Ju1zdXtg2pEto=
-----END CERTIFICATE-----

DigiCert Assured ID Root CA
===========================
-----BEGIN CERTIFICATE-----
MIIDtzCCAp+gAwIBAgIQDOfg5RfYRv6P5WD8G/AwOTANBgkqhkiG9w0BAQUFADBlMQswCQYDVQQG
EwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSQw
IgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgQ0EwHhcNMDYxMTEwMDAwMDAwWhcNMzEx
MTEwMDAwMDAwWjBlMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQL
ExB3d3cuZGlnaWNlcnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgQ0Ew
ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCtDhXO5EOAXLGH87dg+XESpa7cJpSIqvTO
9SA5KFhgDPiA2qkVlTJhPLWxKISKityfCgyDF3qPkKyK53lTXDGEKvYPmDI2dsze3Tyoou9q+yHy
UmHfnyDXH+Kx2f4YZNISW1/5WBg1vEfNoTb5a3/UsDg+wRvDjDPZ2C8Y/igPs6eD1sNuRMBhNZYW
/lmci3Zt1/GiSw0r/wty2p5g0I6QNcZ4VYcgoc/lbQrISXwxmDNsIumH0DJaoroTghHtORedmTpy
oeb6pNnVFzF1roV9Iq4/AUaG9ih5yLHa5FcXxH4cDrC0kqZWs72yl+2qp/C3xag/lRbQ/6GW6whf
GHdPAgMBAAGjYzBhMA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBRF
66Kv9JLLgjEtUYunpyGd823IDzAfBgNVHSMEGDAWgBRF66Kv9JLLgjEtUYunpyGd823IDzANBgkq
hkiG9w0BAQUFAAOCAQEAog683+Lt8ONyc3pklL/3cmbYMuRCdWKuh+vy1dneVrOfzM4UKLkNl2Bc
EkxY5NM9g0lFWJc1aRqoR+pWxnmrEthngYTffwk8lOa4JiwgvT2zKIn3X/8i4peEH+ll74fg38Fn
SbNd67IJKusm7Xi+fT8r87cmNW1fiQG2SVufAQWbqz0lwcy2f8Lxb4bG+mRo64EtlOtCt/qMHt1i
8b5QZ7dsvfPxH2sMNgcWfzd8qVttevESRmCD1ycEvkvOl77DZypoEd+A5wwzZr8TDRRu838fYxAe
+o0bJW1sj6W3YQGx0qMmoRBxna3iw/nDmVG3KwcIzi7mULKn+gpFL6Lw8g==
-----END CERTIFICATE-----

DigiCert Global Root CA
=======================
-----BEGIN CERTIFICATE-----
MIIDrzCCApegAwIBAgIQCDvgVpBCRrGhdWrJWZHHSjANBgkqhkiG9w0BAQUFADBhMQswCQYDVQQG
EwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSAw
HgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBDQTAeFw0wNjExMTAwMDAwMDBaFw0zMTExMTAw
MDAwMDBaMGExCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3
dy5kaWdpY2VydC5jb20xIDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IENBMIIBIjANBgkq
hkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA4jvhEXLeqKTTo1eqUKKPC3eQyaKl7hLOllsBCSDMAZOn
TjC3U/dDxGkAV53ijSLdhwZAAIEJzs4bg7/fzTtxRuLWZscFs3YnFo97nh6Vfe63SKMI2tavegw5
BmV/Sl0fvBf4q77uKNd0f3p4mVmFaG5cIzJLv07A6Fpt43C/dxC//AH2hdmoRBBYMql1GNXRor5H
4idq9Joz+EkIYIvUX7Q6hL+hqkpMfT7PT19sdl6gSzeRntwi5m3OFBqOasv+zbMUZBfHWymeMr/y
7vrTC0LUq7dBMtoM1O/4gdW7jVg/tRvoSSiicNoxBN33shbyTApOB6jtSj1etX+jkMOvJwIDAQAB
o2MwYTAOBgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUA95QNVbRTLtm
8KPiGxvDl7I90VUwHwYDVR0jBBgwFoAUA95QNVbRTLtm8KPiGxvDl7I90VUwDQYJKoZIhvcNAQEF
BQADggEBAMucN6pIExIK+t1EnE9SsPTfrgT1eXkIoyQY/EsrhMAtudXH/vTBH1jLuG2cenTnmCmr
EbXjcKChzUyImZOMkXDiqw8cvpOp/2PV5Adg06O/nVsJ8dWO41P0jmP6P6fbtGbfYmbW0W5BjfIt
tep3Sp+dWOIrWcBAI+0tKIJFPnlUkiaY4IBIqDfv8NZ5YBberOgOzW6sRBc4L0na4UU+Krk2U886
UAb3LujEV0lsYSEY1QSteDwsOoBrp+uvFRTp2InBuThs4pFsiv9kuXclVzDAGySj4dzp30d8tbQk
CAUw7C29C79Fv1C5qfPrmAESrciIxpg0X40KPMbp1ZWVbd4=
-----END CERTIFICATE-----

DigiCert High Assurance EV Root CA
==================================
-----BEGIN CERTIFICATE-----
MIIDxTCCAq2gAwIBAgIQAqxcJmoLQJuPC3nyrkYldzANBgkqhkiG9w0BAQUFADBsMQswCQYDVQQG
EwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSsw
KQYDVQQDEyJEaWdpQ2VydCBIaWdoIEFzc3VyYW5jZSBFViBSb290IENBMB4XDTA2MTExMDAwMDAw
MFoXDTMxMTExMDAwMDAwMFowbDELMAkGA1UEBhMCVVMxFTATBgNVBAoTDERpZ2lDZXJ0IEluYzEZ
MBcGA1UECxMQd3d3LmRpZ2ljZXJ0LmNvbTErMCkGA1UEAxMiRGlnaUNlcnQgSGlnaCBBc3N1cmFu
Y2UgRVYgUm9vdCBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMbM5XPm+9S75S0t
Mqbf5YE/yc0lSbZxKsPVlDRnogocsF9ppkCxxLeyj9CYpKlBWTrT3JTWPNt0OKRKzE0lgvdKpVMS
OO7zSW1xkX5jtqumX8OkhPhPYlG++MXs2ziS4wblCJEMxChBVfvLWokVfnHoNb9Ncgk9vjo4UFt3
MRuNs8ckRZqnrG0AFFoEt7oT61EKmEFBIk5lYYeBQVCmeVyJ3hlKV9Uu5l0cUyx+mM0aBhakaHPQ
NAQTXKFx01p8VdteZOE3hzBWBOURtCmAEvF5OYiiAhF8J2a3iLd48soKqDirCmTCv2ZdlYTBoSUe
h10aUAsgEsxBu24LUTi4S8sCAwEAAaNjMGEwDgYDVR0PAQH/BAQDAgGGMA8GA1UdEwEB/wQFMAMB
Af8wHQYDVR0OBBYEFLE+w2kD+L9HAdSYJhoIAu9jZCvDMB8GA1UdIwQYMBaAFLE+w2kD+L9HAdSY
JhoIAu9jZCvDMA0GCSqGSIb3DQEBBQUAA4IBAQAcGgaX3NecnzyIZgYIVyHbIUf4KmeqvxgydkAQ
V8GK83rZEWWONfqe/EW1ntlMMUu4kehDLI6zeM7b41N5cdblIZQB2lWHmiRk9opmzN6cN82oNLFp
myPInngiK3BD41VHMWEZ71jFhS9OMPagMRYjyOfiZRYzy78aG6A9+MpeizGLYAiJLQwGXFK3xPkK
mNEVX58Svnw2Yzi9RKR/5CYrCsSXaQ3pjOLAEFe4yHYSkVXySGnYvCoCWw9E1CAx2/S6cCZdkGCe
vEsXCS+0yx5DaMkHJ8HSXPfqIbloEpw8nL+e/IBcm2PN7EeqJSdnoDfzAIJ9VNep+OkuE6N36B9K
-----END CERTIFICATE-----

SwissSign Gold CA - G2
======================
-----BEGIN CERTIFICATE-----
MIIFujCCA6KgAwIBAgIJALtAHEP1Xk+wMA0GCSqGSIb3DQEBBQUAMEUxCzAJBgNVBAYTAkNIMRUw
EwYDVQQKEwxTd2lzc1NpZ24gQUcxHzAdBgNVBAMTFlN3aXNzU2lnbiBHb2xkIENBIC0gRzIwHhcN
MDYxMDI1MDgzMDM1WhcNMzYxMDI1MDgzMDM1WjBFMQswCQYDVQQGEwJDSDEVMBMGA1UEChMMU3dp
c3NTaWduIEFHMR8wHQYDVQQDExZTd2lzc1NpZ24gR29sZCBDQSAtIEcyMIICIjANBgkqhkiG9w0B
AQEFAAOCAg8AMIICCgKCAgEAr+TufoskDhJuqVAtFkQ7kpJcyrhdhJJCEyq8ZVeCQD5XJM1QiyUq
t2/876LQwB8CJEoTlo8jE+YoWACjR8cGp4QjK7u9lit/VcyLwVcfDmJlD909Vopz2q5+bbqBHH5C
jCA12UNNhPqE21Is8w4ndwtrvxEvcnifLtg+5hg3Wipy+dpikJKVyh+c6bM8K8vzARO/Ws/BtQpg
vd21mWRTuKCWs2/iJneRjOBiEAKfNA+k1ZIzUd6+jbqEemA8atufK+ze3gE/bk3lUIbLtK/tREDF
ylqM2tIrfKjuvqblCqoOpd8FUrdVxyJdMmqXl2MT28nbeTZ7hTpKxVKJ+STnnXepgv9VHKVxaSvR
AiTysybUa9oEVeXBCsdtMDeQKuSeFDNeFhdVxVu1yzSJkvGdJo+hB9TGsnhQ2wwMC3wLjEHXuend
jIj3o02yMszYF9rNt85mndT9Xv+9lz4pded+p2JYryU0pUHHPbwNUMoDAw8IWh+Vc3hiv69yFGkO
peUDDniOJihC8AcLYiAQZzlG+qkDzAQ4embvIIO1jEpWjpEA/I5cgt6IoMPiaG59je883WX0XaxR
7ySArqpWl2/5rX3aYT+YdzylkbYcjCbaZaIJbcHiVOO5ykxMgI93e2CaHt+28kgeDrpOVG2Y4OGi
GqJ3UM/EY5LsRxmd6+ZrzsECAwEAAaOBrDCBqTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUw
AwEB/zAdBgNVHQ4EFgQUWyV7lqRlUX64OfPAeGZe6Drn8O4wHwYDVR0jBBgwFoAUWyV7lqRlUX64
OfPAeGZe6Drn8O4wRgYDVR0gBD8wPTA7BglghXQBWQECAQEwLjAsBggrBgEFBQcCARYgaHR0cDov
L3JlcG9zaXRvcnkuc3dpc3NzaWduLmNvbS8wDQYJKoZIhvcNAQEFBQADggIBACe645R88a7A3hfm
5djV9VSwg/S7zV4Fe0+fdWavPOhWfvxyeDgD2StiGwC5+OlgzczOUYrHUDFu4Up+GC9pWbY9ZIEr
44OE5iKHjn3g7gKZYbge9LgriBIWhMIxkziWMaa5O1M/wySTVltpkuzFwbs4AOPsF6m43Md8AYOf
Mke6UiI0HTJ6CVanfCU2qT1L2sCCbwq7EsiHSycR+R4tx5M/nttfJmtS2S6K8RTGRI0Vqbe/vd6m
Gu6uLftIdxf+u+yvGPUqUfA5hJeVbG4bwyvEdGB5JbAKJ9/fXtI5z0V9QkvfsywexcZdylU6oJxp
mo/a77KwPJ+HbBIrZXAVUjEaJM9vMSNQH4xPjyPDdEFjHFWoFN0+4FFQz/EbMFYOkrCChdiDyyJk
vC24JdVUorgG6q2SpCSgwYa1ShNqR88uC1aVVMvOmttqtKay20EIhid392qgQmwLOM7XdVAyksLf
KzAiSNDVQTglXaTpXZ/GlHXQRf0wl0OPkKsKx4ZzYEppLd6leNcG2mqeSz53OiATIgHQv2ieY2Br
NU0LbbqhPcCT4H8js1WtciVORvnSFu+wZMEBnunKoGqYDs/YYPIvSbjkQuE4NRb0yG5P94FW6Lqj
viOvrv1vA+ACOzB2+httQc8Bsem4yWb02ybzOqR08kkkW8mw0FfB+j564ZfJ
-----END CERTIFICATE-----

SecureTrust CA
==============
-----BEGIN CERTIFICATE-----
MIIDuDCCAqCgAwIBAgIQDPCOXAgWpa1Cf/DrJxhZ0DANBgkqhkiG9w0BAQUFADBIMQswCQYDVQQG
EwJVUzEgMB4GA1UEChMXU2VjdXJlVHJ1c3QgQ29ycG9yYXRpb24xFzAVBgNVBAMTDlNlY3VyZVRy
dXN0IENBMB4XDTA2MTEwNzE5MzExOFoXDTI5MTIzMTE5NDA1NVowSDELMAkGA1UEBhMCVVMxIDAe
BgNVBAoTF1NlY3VyZVRydXN0IENvcnBvcmF0aW9uMRcwFQYDVQQDEw5TZWN1cmVUcnVzdCBDQTCC
ASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKukgeWVzfX2FI7CT8rU4niVWJxB4Q2ZQCQX
OZEzZum+4YOvYlyJ0fwkW2Gz4BERQRwdbvC4u/jep4G6pkjGnx29vo6pQT64lO0pGtSO0gMdA+9t
DWccV9cGrcrI9f4Or2YlSASWC12juhbDCE/RRvgUXPLIXgGZbf2IzIaowW8xQmxSPmjL8xk037uH
GFaAJsTQ3MBv396gwpEWoGQRS0S8Hvbn+mPeZqx2pHGj7DaUaHp3pLHnDi+BeuK1cobvomuL8A/b
01k/unK8RCSc43Oz969XL0Imnal0ugBS8kvNU3xHCzaFDmapCJcWNFfBZveA4+1wVMeT4C4oFVmH
ursCAwEAAaOBnTCBmjATBgkrBgEEAYI3FAIEBh4EAEMAQTALBgNVHQ8EBAMCAYYwDwYDVR0TAQH/
BAUwAwEB/zAdBgNVHQ4EFgQUQjK2FvoE/f5dS3rD/fdMQB1aQ68wNAYDVR0fBC0wKzApoCegJYYj
aHR0cDovL2NybC5zZWN1cmV0cnVzdC5jb20vU1RDQS5jcmwwEAYJKwYBBAGCNxUBBAMCAQAwDQYJ
KoZIhvcNAQEFBQADggEBADDtT0rhWDpSclu1pqNlGKa7UTt36Z3q059c4EVlew3KW+JwULKUBRSu
SceNQQcSc5R+DCMh/bwQf2AQWnL1mA6s7Ll/3XpvXdMc9P+IBWlCqQVxyLesJugutIxq/3HcuLHf
mbx8IVQr5Fiiu1cprp6poxkmD5kuCLDv/WnPmRoJjeOnnyvJNjR7JLN4TJUXpAYmHrZkUjZfYGfZ
nMUFdAvnZyPSCPyI6a6Lf+Ew9Dd+/cYy2i2eRDAwbO4H3tI0/NL/QPZL9GZGBlSm8jIKYyYwa5vR
3ItHuuG51WLQoqD0ZwV4KWMabwTW+MZMo5qxN7SN5ShLHZ4swrhovO0C7jE=
-----END CERTIFICATE-----

Secure Global CA
================
-----BEGIN CERTIFICATE-----
MIIDvDCCAqSgAwIBAgIQB1YipOjUiolN9BPI8PjqpTANBgkqhkiG9w0BAQUFADBKMQswCQYDVQQG
EwJVUzEgMB4GA1UEChMXU2VjdXJlVHJ1c3QgQ29ycG9yYXRpb24xGTAXBgNVBAMTEFNlY3VyZSBH
bG9iYWwgQ0EwHhcNMDYxMTA3MTk0MjI4WhcNMjkxMjMxMTk1MjA2WjBKMQswCQYDVQQGEwJVUzEg
MB4GA1UEChMXU2VjdXJlVHJ1c3QgQ29ycG9yYXRpb24xGTAXBgNVBAMTEFNlY3VyZSBHbG9iYWwg
Q0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCvNS7YrGxVaQZx5RNoJLNP2MwhR/jx
YDiJiQPpvepeRlMJ3Fz1Wuj3RSoC6zFh1ykzTM7HfAo3fg+6MpjhHZevj8fcyTiW89sa/FHtaMbQ
bqR8JNGuQsiWUGMu4P51/pinX0kuleM5M2SOHqRfkNJnPLLZ/kG5VacJjnIFHovdRIWCQtBJwB1g
8NEXLJXr9qXBkqPFwqcIYA1gBBCWeZ4WNOaptvolRTnIHmX5k/Wq8VLcmZg9pYYaDDUz+kulBAYV
HDGA76oYa8J719rO+TMg1fW9ajMtgQT7sFzUnKPiXB3jqUJ1XnvUd+85VLrJChgbEplJL4hL/VBi
0XPnj3pDAgMBAAGjgZ0wgZowEwYJKwYBBAGCNxQCBAYeBABDAEEwCwYDVR0PBAQDAgGGMA8GA1Ud
EwEB/wQFMAMBAf8wHQYDVR0OBBYEFK9EBMJBfkiD2045AuzshHrmzsmkMDQGA1UdHwQtMCswKaAn
oCWGI2h0dHA6Ly9jcmwuc2VjdXJldHJ1c3QuY29tL1NHQ0EuY3JsMBAGCSsGAQQBgjcVAQQDAgEA
MA0GCSqGSIb3DQEBBQUAA4IBAQBjGghAfaReUw132HquHw0LURYD7xh8yOOvaliTFGCRsoTciE6+
OYo68+aCiV0BN7OrJKQVDpI1WkpEXk5X+nXOH0jOZvQ8QCaSmGwb7iRGDBezUqXbpZGRzzfTb+cn
CDpOGR86p1hcF895P4vkp9MmI50mD1hp/Ed+stCNi5O/KU9DaXR2Z0vPB4zmAve14bRDtUstFJ/5
3CYNv6ZHdAbYiNE6KTCEztI5gGIbqMdXSbxqVVFnFUq+NQfk1XWYN3kwFNspnWzFacxHVaIw98xc
f8LDmBxrThaA63p4ZUWiABqvDA1VZDRIuJK58bRQKfJPIx/abKwfROHdI3hRW8cW
-----END CERTIFICATE-----

COMODO Certification Authority
==============================
-----BEGIN CERTIFICATE-----
MIIEHTCCAwWgAwIBAgIQToEtioJl4AsC7j41AkblPTANBgkqhkiG9w0BAQUFADCBgTELMAkGA1UE
BhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEaMBgG
A1UEChMRQ09NT0RPIENBIExpbWl0ZWQxJzAlBgNVBAMTHkNPTU9ETyBDZXJ0aWZpY2F0aW9uIEF1
dGhvcml0eTAeFw0wNjEyMDEwMDAwMDBaFw0yOTEyMzEyMzU5NTlaMIGBMQswCQYDVQQGEwJHQjEb
MBkGA1UECBMSR3JlYXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHEwdTYWxmb3JkMRowGAYDVQQKExFD
T01PRE8gQ0EgTGltaXRlZDEnMCUGA1UEAxMeQ09NT0RPIENlcnRpZmljYXRpb24gQXV0aG9yaXR5
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA0ECLi3LjkRv3UcEbVASY06m/weaKXTuH
+7uIzg3jLz8GlvCiKVCZrts7oVewdFFxze1CkU1B/qnI2GqGd0S7WWaXUF601CxwRM/aN5VCaTww
xHGzUvAhTaHYujl8HJ6jJJ3ygxaYqhZ8Q5sVW7euNJH+1GImGEaaP+vB+fGQV+useg2L23IwambV
4EajcNxo2f8ESIl33rXp+2dtQem8Ob0y2WIC8bGoPW43nOIv4tOiJovGuFVDiOEjPqXSJDlqR6sA
1KGzqSX+DT+nHbrTUcELpNqsOO9VUCQFZUaTNE8tja3G1CEZ0o7KBWFxB3NH5YoZEr0ETc5OnKVI
rLsm9wIDAQABo4GOMIGLMB0GA1UdDgQWBBQLWOWLxkwVN6RAqTCpIb5HNlpW/zAOBgNVHQ8BAf8E
BAMCAQYwDwYDVR0TAQH/BAUwAwEB/zBJBgNVHR8EQjBAMD6gPKA6hjhodHRwOi8vY3JsLmNvbW9k
b2NhLmNvbS9DT01PRE9DZXJ0aWZpY2F0aW9uQXV0aG9yaXR5LmNybDANBgkqhkiG9w0BAQUFAAOC
AQEAPpiem/Yb6dc5t3iuHXIYSdOH5EOC6z/JqvWote9VfCFSZfnVDeFs9D6Mk3ORLgLETgdxb8CP
OGEIqB6BCsAvIC9Bi5HcSEW88cbeunZrM8gALTFGTO3nnc+IlP8zwFboJIYmuNg4ON8qa90SzMc/
RxdMosIGlgnW2/4/PEZB31jiVg88O8EckzXZOFKs7sjsLjBOlDW0JB9LeGna8gI4zJVSk/BwJVmc
IGfE7vmLV2H0knZ9P4SNVbfo5azV8fUZVqZa+5Acr5Pr5RzUZ5ddBA6+C4OmF4O5MBKgxTMVBbkN
+8cFduPYSo38NBejxiEovjBFMR7HeL5YYTisO+IBZQ==
-----END CERTIFICATE-----

COMODO ECC Certification Authority
==================================
-----BEGIN CERTIFICATE-----
MIICiTCCAg+gAwIBAgIQH0evqmIAcFBUTAGem2OZKjAKBggqhkjOPQQDAzCBhTELMAkGA1UEBhMC
R0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEaMBgGA1UE
ChMRQ09NT0RPIENBIExpbWl0ZWQxKzApBgNVBAMTIkNPTU9ETyBFQ0MgQ2VydGlmaWNhdGlvbiBB
dXRob3JpdHkwHhcNMDgwMzA2MDAwMDAwWhcNMzgwMTE4MjM1OTU5WjCBhTELMAkGA1UEBhMCR0Ix
GzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEaMBgGA1UEChMR
Q09NT0RPIENBIExpbWl0ZWQxKzApBgNVBAMTIkNPTU9ETyBFQ0MgQ2VydGlmaWNhdGlvbiBBdXRo
b3JpdHkwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAAQDR3svdcmCFYX7deSRFtSrYpn1PlILBs5BAH+X
4QokPB0BBO490o0JlwzgdeT6+3eKKvUDYEs2ixYjFq0JcfRK9ChQtP6IHG4/bC8vCVlbpVsLM5ni
wz2J+Wos77LTBumjQjBAMB0GA1UdDgQWBBR1cacZSBm8nZ3qQUfflMRId5nTeTAOBgNVHQ8BAf8E
BAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAKBggqhkjOPQQDAwNoADBlAjEA7wNbeqy3eApyt4jf/7VG
FAkK+qDmfQjGGoe9GKhzvSbKYAydzpmfz1wPMOG+FDHqAjAU9JM8SaczepBGR7NjfRObTrdvGDeA
U/7dIOA1mjbRxwG55tzd8/8dLDoWV9mSOdY=
-----END CERTIFICATE-----

Certigna
========
-----BEGIN CERTIFICATE-----
MIIDqDCCApCgAwIBAgIJAP7c4wEPyUj/MA0GCSqGSIb3DQEBBQUAMDQxCzAJBgNVBAYTAkZSMRIw
EAYDVQQKDAlEaGlteW90aXMxETAPBgNVBAMMCENlcnRpZ25hMB4XDTA3MDYyOTE1MTMwNVoXDTI3
MDYyOTE1MTMwNVowNDELMAkGA1UEBhMCRlIxEjAQBgNVBAoMCURoaW15b3RpczERMA8GA1UEAwwI
Q2VydGlnbmEwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDIaPHJ1tazNHUmgh7stL7q
XOEm7RFHYeGifBZ4QCHkYJ5ayGPhxLGWkv8YbWkj4Sti993iNi+RB7lIzw7sebYs5zRLcAglozyH
GxnygQcPOJAZ0xH+hrTy0V4eHpbNgGzOOzGTtvKg0KmVEn2lmsxryIRWijOp5yIVUxbwzBfsV1/p
ogqYCd7jX5xv3EjjhQsVWqa6n6xI4wmy9/Qy3l40vhx4XUJbzg4ij02Q130yGLMLLGq/jj8UEYkg
DncUtT2UCIf3JR7VsmAA7G8qKCVuKj4YYxclPz5EIBb2JsglrgVKtOdjLPOMFlN+XPsRGgjBRmKf
Irjxwo1p3Po6WAbfAgMBAAGjgbwwgbkwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUGu3+QTmQ
tCRZvgHyUtVF9lo53BEwZAYDVR0jBF0wW4AUGu3+QTmQtCRZvgHyUtVF9lo53BGhOKQ2MDQxCzAJ
BgNVBAYTAkZSMRIwEAYDVQQKDAlEaGlteW90aXMxETAPBgNVBAMMCENlcnRpZ25hggkA/tzjAQ/J
SP8wDgYDVR0PAQH/BAQDAgEGMBEGCWCGSAGG+EIBAQQEAwIABzANBgkqhkiG9w0BAQUFAAOCAQEA
hQMeknH2Qq/ho2Ge6/PAD/Kl1NqV5ta+aDY9fm4fTIrv0Q8hbV6lUmPOEvjvKtpv6zf+EwLHyzs+
ImvaYS5/1HI93TDhHkxAGYwP15zRgzB7mFncfca5DClMoTOi62c6ZYTTluLtdkVwj7Ur3vkj1klu
PBS1xp81HlDQwY9qcEQCYsuuHWhBp6pX6FOqB9IG9tUUBguRA3UsbHK1YZWaDYu5Def131TN3ubY
1gkIl2PlwS6wt0QmwCbAr1UwnjvVNioZBPRcHv/PLLf/0P2HQBHVESO7SMAhqaQoLf0V+LBOK/Qw
WyH8EZE0vkHve52Xdf+XlcCWWC/qu0bXu+TZLg==
-----END CERTIFICATE-----

ePKI Root Certification Authority
=================================
-----BEGIN CERTIFICATE-----
MIIFsDCCA5igAwIBAgIQFci9ZUdcr7iXAF7kBtK8nTANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQG
EwJUVzEjMCEGA1UECgwaQ2h1bmdod2EgVGVsZWNvbSBDby4sIEx0ZC4xKjAoBgNVBAsMIWVQS0kg
Um9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0wNDEyMjAwMjMxMjdaFw0zNDEyMjAwMjMx
MjdaMF4xCzAJBgNVBAYTAlRXMSMwIQYDVQQKDBpDaHVuZ2h3YSBUZWxlY29tIENvLiwgTHRkLjEq
MCgGA1UECwwhZVBLSSBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIICIjANBgkqhkiG9w0B
AQEFAAOCAg8AMIICCgKCAgEA4SUP7o3biDN1Z82tH306Tm2d0y8U82N0ywEhajfqhFAHSyZbCUNs
IZ5qyNUD9WBpj8zwIuQf5/dqIjG3LBXy4P4AakP/h2XGtRrBp0xtInAhijHyl3SJCRImHJ7K2RKi
lTza6We/CKBk49ZCt0Xvl/T29de1ShUCWH2YWEtgvM3XDZoTM1PRYfl61dd4s5oz9wCGzh1NlDiv
qOx4UXCKXBCDUSH3ET00hl7lSM2XgYI1TBnsZfZrxQWh7kcT1rMhJ5QQCtkkO7q+RBNGMD+XPNjX
12ruOzjjK9SXDrkb5wdJfzcq+Xd4z1TtW0ado4AOkUPB1ltfFLqfpo0kR0BZv3I4sjZsN/+Z0V0O
WQqraffAsgRFelQArr5T9rXn4fg8ozHSqf4hUmTFpmfwdQcGlBSBVcYn5AGPF8Fqcde+S/uUWH1+
ETOxQvdibBjWzwloPn9s9h6PYq2lY9sJpx8iQkEeb5mKPtf5P0B6ebClAZLSnT0IFaUQAS2zMnao
lQ2zepr7BxB4EW/hj8e6DyUadCrlHJhBmd8hh+iVBmoKs2pHdmX2Os+PYhcZewoozRrSgx4hxyy/
vv9haLdnG7t4TY3OZ+XkwY63I2binZB1NJipNiuKmpS5nezMirH4JYlcWrYvjB9teSSnUmjDhDXi
Zo1jDiVN1Rmy5nk3pyKdVDECAwEAAaNqMGgwHQYDVR0OBBYEFB4M97Zn8uGSJglFwFU5Lnc/Qkqi
MAwGA1UdEwQFMAMBAf8wOQYEZyoHAAQxMC8wLQIBADAJBgUrDgMCGgUAMAcGBWcqAwAABBRFsMLH
ClZ87lt4DJX5GFPBphzYEDANBgkqhkiG9w0BAQUFAAOCAgEACbODU1kBPpVJufGBuvl2ICO1J2B0
1GqZNF5sAFPZn/KmsSQHRGoqxqWOeBLoR9lYGxMqXnmbnwoqZ6YlPwZpVnPDimZI+ymBV3QGypzq
KOg4ZyYr8dW1P2WT+DZdjo2NQCCHGervJ8A9tDkPJXtoUHRVnAxZfVo9QZQlUgjgRywVMRnVvwdV
xrsStZf0X4OFunHB2WyBEXYKCrC/gpf36j36+uwtqSiUO1bd0lEursC9CBWMd1I0ltabrNMdjmEP
NXubrjlpC2JgQCA2j6/7Nu4tCEoduL+bXPjqpRugc6bY+G7gMwRfaKonh+3ZwZCc7b3jajWvY9+r
GNm65ulK6lCKD2GTHuItGeIwlDWSXQ62B68ZgI9HkFFLLk3dheLSClIKF5r8GrBQAuUBo2M3IUxE
xJtRmREOc5wGj1QupyheRDmHVi03vYVElOEMSyycw5KFNGHLD7ibSkNS/jQ6fbjpKdx2qcgw+BRx
gMYeNkh0IkFch4LoGHGLQYlE535YW6i4jRPpp2zDR+2zGp1iro2C6pSe3VkQw63d4k3jMdXH7Ojy
sP6SHhYKGvzZ8/gntsm+HbRsZJB/9OTEW9c3rkIO3aQab3yIVMUWbuF6aC74Or8NpDyJO3inTmOD
BCEIZ43ygknQW/2xzQ+DhNQ+IIX3Sj0rnP0qCglN6oH4EZw=
-----END CERTIFICATE-----

certSIGN ROOT CA
================
-----BEGIN CERTIFICATE-----
MIIDODCCAiCgAwIBAgIGIAYFFnACMA0GCSqGSIb3DQEBBQUAMDsxCzAJBgNVBAYTAlJPMREwDwYD
VQQKEwhjZXJ0U0lHTjEZMBcGA1UECxMQY2VydFNJR04gUk9PVCBDQTAeFw0wNjA3MDQxNzIwMDRa
Fw0zMTA3MDQxNzIwMDRaMDsxCzAJBgNVBAYTAlJPMREwDwYDVQQKEwhjZXJ0U0lHTjEZMBcGA1UE
CxMQY2VydFNJR04gUk9PVCBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALczuX7I
JUqOtdu0KBuqV5Do0SLTZLrTk+jUrIZhQGpgV2hUhE28alQCBf/fm5oqrl0Hj0rDKH/v+yv6efHH
rfAQUySQi2bJqIirr1qjAOm+ukbuW3N7LBeCgV5iLKECZbO9xSsAfsT8AzNXDe3i+s5dRdY4zTW2
ssHQnIFKquSyAVwdj1+ZxLGt24gh65AIgoDzMKND5pCCrlUoSe1b16kQOA7+j0xbm0bqQfWwCHTD
0IgztnzXdN/chNFDDnU5oSVAKOp4yw4sLjmdjItuFhwvJoIQ4uNllAoEwF73XVv4EOLQunpL+943
AAAaWyjj0pxzPjKHmKHJUS/X3qwzs08CAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8B
Af8EBAMCAcYwHQYDVR0OBBYEFOCMm9slSbPxfIbWskKHC9BroNnkMA0GCSqGSIb3DQEBBQUAA4IB
AQA+0hyJLjX8+HXd5n9liPRyTMks1zJO890ZeUe9jjtbkw9QSSQTaxQGcu8J06Gh40CEyecYMnQ8
SG4Pn0vU9x7Tk4ZkVJdjclDVVc/6IJMCopvDI5NOFlV2oHB5bc0hH88vLbwZ44gx+FkagQnIl6Z0
x2DEW8xXjrJ1/RsCCdtZb3KTafcxQdaIOL+Hsr0Wefmq5L6IJd1hJyMctTEHBDa0GpC9oHRxUIlt
vBTjD4au8as+x6AJzKNI0eDbZOeStc+vckNwi/nDhDwTqn6Sm1dTk/pwwpEOMfmbZ13pljheX7Nz
TogVZ96edhBiIL5VaZVDADlN9u6wWk5JRFRYX0KD
-----END CERTIFICATE-----

NetLock Arany (Class Gold) Főtanúsítvány
========================================
-----BEGIN CERTIFICATE-----
MIIEFTCCAv2gAwIBAgIGSUEs5AAQMA0GCSqGSIb3DQEBCwUAMIGnMQswCQYDVQQGEwJIVTERMA8G
A1UEBwwIQnVkYXBlc3QxFTATBgNVBAoMDE5ldExvY2sgS2Z0LjE3MDUGA1UECwwuVGFuw7pzw610
dsOhbnlraWFkw7NrIChDZXJ0aWZpY2F0aW9uIFNlcnZpY2VzKTE1MDMGA1UEAwwsTmV0TG9jayBB
cmFueSAoQ2xhc3MgR29sZCkgRsWRdGFuw7pzw610dsOhbnkwHhcNMDgxMjExMTUwODIxWhcNMjgx
MjA2MTUwODIxWjCBpzELMAkGA1UEBhMCSFUxETAPBgNVBAcMCEJ1ZGFwZXN0MRUwEwYDVQQKDAxO
ZXRMb2NrIEtmdC4xNzA1BgNVBAsMLlRhbsO6c8OtdHbDoW55a2lhZMOzayAoQ2VydGlmaWNhdGlv
biBTZXJ2aWNlcykxNTAzBgNVBAMMLE5ldExvY2sgQXJhbnkgKENsYXNzIEdvbGQpIEbFkXRhbsO6
c8OtdHbDoW55MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAxCRec75LbRTDofTjl5Bu
0jBFHjzuZ9lk4BqKf8owyoPjIMHj9DrTlF8afFttvzBPhCf2nx9JvMaZCpDyD/V/Q4Q3Y1GLeqVw
/HpYzY6b7cNGbIRwXdrzAZAj/E4wqX7hJ2Pn7WQ8oLjJM2P+FpD/sLj916jAwJRDC7bVWaaeVtAk
H3B5r9s5VA1lddkVQZQBr17s9o3x/61k/iCa11zr/qYfCGSji3ZVrR47KGAuhyXoqq8fxmRGILdw
fzzeSNuWU7c5d+Qa4scWhHaXWy+7GRWF+GmF9ZmnqfI0p6m2pgP8b4Y9VHx2BJtr+UBdADTHLpl1
neWIA6pN+APSQnbAGwIDAKiLo0UwQzASBgNVHRMBAf8ECDAGAQH/AgEEMA4GA1UdDwEB/wQEAwIB
BjAdBgNVHQ4EFgQUzPpnk/C2uNClwB7zU/2MU9+D15YwDQYJKoZIhvcNAQELBQADggEBAKt/7hwW
qZw8UQCgwBEIBaeZ5m8BiFRhbvG5GK1Krf6BQCOUL/t1fC8oS2IkgYIL9WHxHG64YTjrgfpioTta
YtOUZcTh5m2C+C8lcLIhJsFyUR+MLMOEkMNaj7rP9KdlpeuY0fsFskZ1FSNqb4VjMIDw1Z4fKRzC
bLBQWV2QWzuoDTDPv31/zvGdg73JRm4gpvlhUbohL3u+pRVjodSVh/GeufOJ8z2FuLjbvrW5Kfna
NwUASZQDhETnv0Mxz3WLJdH0pmT1kvarBes96aULNmLazAZfNou2XjG4Kvte9nHfRCaexOYNkbQu
dZWAUWpLMKawYqGT8ZvYzsRjdT9ZR7E=
-----END CERTIFICATE-----

Microsec e-Szigno Root CA 2009
==============================
-----BEGIN CERTIFICATE-----
MIIECjCCAvKgAwIBAgIJAMJ+QwRORz8ZMA0GCSqGSIb3DQEBCwUAMIGCMQswCQYDVQQGEwJIVTER
MA8GA1UEBwwIQnVkYXBlc3QxFjAUBgNVBAoMDU1pY3Jvc2VjIEx0ZC4xJzAlBgNVBAMMHk1pY3Jv
c2VjIGUtU3ppZ25vIFJvb3QgQ0EgMjAwOTEfMB0GCSqGSIb3DQEJARYQaW5mb0BlLXN6aWduby5o
dTAeFw0wOTA2MTYxMTMwMThaFw0yOTEyMzAxMTMwMThaMIGCMQswCQYDVQQGEwJIVTERMA8GA1UE
BwwIQnVkYXBlc3QxFjAUBgNVBAoMDU1pY3Jvc2VjIEx0ZC4xJzAlBgNVBAMMHk1pY3Jvc2VjIGUt
U3ppZ25vIFJvb3QgQ0EgMjAwOTEfMB0GCSqGSIb3DQEJARYQaW5mb0BlLXN6aWduby5odTCCASIw
DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAOn4j/NjrdqG2KfgQvvPkd6mJviZpWNwrZuuyjNA
fW2WbqEORO7hE52UQlKavXWFdCyoDh2Tthi3jCyoz/tccbna7P7ofo/kLx2yqHWH2Leh5TvPmUpG
0IMZfcChEhyVbUr02MelTTMuhTlAdX4UfIASmFDHQWe4oIBhVKZsTh/gnQ4H6cm6M+f+wFUoLAKA
pxn1ntxVUwOXewdI/5n7N4okxFnMUBBjjqqpGrCEGob5X7uxUG6k0QrM1XF+H6cbfPVTbiJfyyvm
1HxdrtbCxkzlBQHZ7Vf8wSN5/PrIJIOV87VqUQHQd9bpEqH5GoP7ghu5sJf0dgYzQ0mg/wu1+rUC
AwEAAaOBgDB+MA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBTLD8bf
QkPMPcu1SCOhGnqmKrs0aDAfBgNVHSMEGDAWgBTLD8bfQkPMPcu1SCOhGnqmKrs0aDAbBgNVHREE
FDASgRBpbmZvQGUtc3ppZ25vLmh1MA0GCSqGSIb3DQEBCwUAA4IBAQDJ0Q5eLtXMs3w+y/w9/w0o
lZMEyL/azXm4Q5DwpL7v8u8hmLzU1F0G9u5C7DBsoKqpyvGvivo/C3NqPuouQH4frlRheesuCDfX
I/OMn74dseGkddug4lQUsbocKaQY9hK6ohQU4zE1yED/t+AFdlfBHFny+L/k7SViXITwfn4fs775
tyERzAMBVnCnEJIeGzSBHq2cGsMEPO0CYdYeBvNfOofyK/FFh+U9rNHHV4S9a67c2Pm2G2JwCz02
yULyMtd6YebS2z3PyKnJm9zbWETXbzivf3jTo60adbocwTZ8jx5tHMN1Rq41Bab2XD0h7lbwyYIi
LXpUq3DDfSJlgnCW
-----END CERTIFICATE-----

GlobalSign Root CA - R3
=======================
-----BEGIN CERTIFICATE-----
MIIDXzCCAkegAwIBAgILBAAAAAABIVhTCKIwDQYJKoZIhvcNAQELBQAwTDEgMB4GA1UECxMXR2xv
YmFsU2lnbiBSb290IENBIC0gUjMxEzARBgNVBAoTCkdsb2JhbFNpZ24xEzARBgNVBAMTCkdsb2Jh
bFNpZ24wHhcNMDkwMzE4MTAwMDAwWhcNMjkwMzE4MTAwMDAwWjBMMSAwHgYDVQQLExdHbG9iYWxT
aWduIFJvb3QgQ0EgLSBSMzETMBEGA1UEChMKR2xvYmFsU2lnbjETMBEGA1UEAxMKR2xvYmFsU2ln
bjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMwldpB5BngiFvXAg7aEyiie/QV2EcWt
iHL8RgJDx7KKnQRfJMsuS+FggkbhUqsMgUdwbN1k0ev1LKMPgj0MK66X17YUhhB5uzsTgHeMCOFJ
0mpiLx9e+pZo34knlTifBtc+ycsmWQ1z3rDI6SYOgxXG71uL0gRgykmmKPZpO/bLyCiR5Z2KYVc3
rHQU3HTgOu5yLy6c+9C7v/U9AOEGM+iCK65TpjoWc4zdQQ4gOsC0p6Hpsk+QLjJg6VfLuQSSaGjl
OCZgdbKfd/+RFO+uIEn8rUAVSNECMWEZXriX7613t2Saer9fwRPvm2L7DWzgVGkWqQPabumDk3F2
xmmFghcCAwEAAaNCMEAwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYE
FI/wS3+oLkUkrk1Q+mOai97i3Ru8MA0GCSqGSIb3DQEBCwUAA4IBAQBLQNvAUKr+yAzv95ZURUm7
lgAJQayzE4aGKAczymvmdLm6AC2upArT9fHxD4q/c2dKg8dEe3jgr25sbwMpjjM5RcOO5LlXbKr8
EpbsU8Yt5CRsuZRj+9xTaGdWPoO4zzUhw8lo/s7awlOqzJCK6fBdRoyV3XpYKBovHd7NADdBj+1E
bddTKJd+82cEHhXXipa0095MJ6RMG3NzdvQXmcIfeg7jLQitChws/zyrVQ4PkX4268NXSb7hLi18
YIvDQVETI53O9zJrlAGomecsMx86OyXShkDOOyyGeMlhLxS67ttVb9+E7gUJTb0o2HLO02JQZR7r
kpeDMdmztcpHWD9f
-----END CERTIFICATE-----

Izenpe.com
==========
-----BEGIN CERTIFICATE-----
MIIF8TCCA9mgAwIBAgIQALC3WhZIX7/hy/WL1xnmfTANBgkqhkiG9w0BAQsFADA4MQswCQYDVQQG
EwJFUzEUMBIGA1UECgwLSVpFTlBFIFMuQS4xEzARBgNVBAMMCkl6ZW5wZS5jb20wHhcNMDcxMjEz
MTMwODI4WhcNMzcxMjEzMDgyNzI1WjA4MQswCQYDVQQGEwJFUzEUMBIGA1UECgwLSVpFTlBFIFMu
QS4xEzARBgNVBAMMCkl6ZW5wZS5jb20wggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDJ
03rKDx6sp4boFmVqscIbRTJxldn+EFvMr+eleQGPicPK8lVx93e+d5TzcqQsRNiekpsUOqHnJJAK
ClaOxdgmlOHZSOEtPtoKct2jmRXagaKH9HtuJneJWK3W6wyyQXpzbm3benhB6QiIEn6HLmYRY2xU
+zydcsC8Lv/Ct90NduM61/e0aL6i9eOBbsFGb12N4E3GVFWJGjMxCrFXuaOKmMPsOzTFlUFpfnXC
PCDFYbpRR6AgkJOhkEvzTnyFRVSa0QUmQbC1TR0zvsQDyCV8wXDbO/QJLVQnSKwv4cSsPsjLkkxT
OTcj7NMB+eAJRE1NZMDhDVqHIrytG6P+JrUV86f8hBnp7KGItERphIPzidF0BqnMC9bC3ieFUCbK
F7jJeodWLBoBHmy+E60QrLUk9TiRodZL2vG70t5HtfG8gfZZa88ZU+mNFctKy6lvROUbQc/hhqfK
0GqfvEyNBjNaooXlkDWgYlwWTvDjovoDGrQscbNYLN57C9saD+veIR8GdwYDsMnvmfzAuU8Lhij+
0rnq49qlw0dpEuDb8PYZi+17cNcC1u2HGCgsBCRMd+RIihrGO5rUD8r6ddIBQFqNeb+Lz0vPqhbB
leStTIo+F5HUsWLlguWABKQDfo2/2n+iD5dPDNMN+9fR5XJ+HMh3/1uaD7euBUbl8agW7EekFwID
AQABo4H2MIHzMIGwBgNVHREEgagwgaWBD2luZm9AaXplbnBlLmNvbaSBkTCBjjFHMEUGA1UECgw+
SVpFTlBFIFMuQS4gLSBDSUYgQTAxMzM3MjYwLVJNZXJjLlZpdG9yaWEtR2FzdGVpeiBUMTA1NSBG
NjIgUzgxQzBBBgNVBAkMOkF2ZGEgZGVsIE1lZGl0ZXJyYW5lbyBFdG9yYmlkZWEgMTQgLSAwMTAx
MCBWaXRvcmlhLUdhc3RlaXowDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0O
BBYEFB0cZQ6o8iV7tJHP5LGx5r1VdGwFMA0GCSqGSIb3DQEBCwUAA4ICAQB4pgwWSp9MiDrAyw6l
Fn2fuUhfGI8NYjb2zRlrrKvV9pF9rnHzP7MOeIWblaQnIUdCSnxIOvVFfLMMjlF4rJUT3sb9fbga
kEyrkgPH7UIBzg/YsfqikuFgba56awmqxinuaElnMIAkejEWOVt+8Rwu3WwJrfIxwYJOubv5vr8q
hT/AQKM6WfxZSzwoJNu0FXWuDYi6LnPAvViH5ULy617uHjAimcs30cQhbIHsvm0m5hzkQiCeR7Cs
g1lwLDXWrzY0tM07+DKo7+N4ifuNRSzanLh+QBxh5z6ikixL8s36mLYp//Pye6kfLqCTVyvehQP5
aTfLnnhqBbTFMXiJ7HqnheG5ezzevh55hM6fcA5ZwjUukCox2eRFekGkLhObNA5me0mrZJfQRsN5
nXJQY6aYWwa9SG3YOYNw6DXwBdGqvOPbyALqfP2C2sJbUjWumDqtujWTI6cfSN01RpiyEGjkpTHC
ClguGYEQyVB1/OpaFs4R1+7vUIgtYf8/QnMFlEPVjjxOAToZpR9GTnfQXeWBIiGH/pR9hNiTrdZo
Q0iy2+tzJOeRf1SktoA+naM8THLCV8Sg1Mw4J87VBp6iSNnpn86CcDaTmjvfliHjWbcM2pE38P1Z
WrOZyGlsQyYBNWNgVYkDOnXYukrZVP/u3oDYLdE41V4tC5h9Pmzb/CaIxw==
-----END CERTIFICATE-----

Go Daddy Root Certificate Authority - G2
========================================
-----BEGIN CERTIFICATE-----
MIIDxTCCAq2gAwIBAgIBADANBgkqhkiG9w0BAQsFADCBgzELMAkGA1UEBhMCVVMxEDAOBgNVBAgT
B0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxGjAYBgNVBAoTEUdvRGFkZHkuY29tLCBJbmMu
MTEwLwYDVQQDEyhHbyBEYWRkeSBSb290IENlcnRpZmljYXRlIEF1dGhvcml0eSAtIEcyMB4XDTA5
MDkwMTAwMDAwMFoXDTM3MTIzMTIzNTk1OVowgYMxCzAJBgNVBAYTAlVTMRAwDgYDVQQIEwdBcml6
b25hMRMwEQYDVQQHEwpTY290dHNkYWxlMRowGAYDVQQKExFHb0RhZGR5LmNvbSwgSW5jLjExMC8G
A1UEAxMoR28gRGFkZHkgUm9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkgLSBHMjCCASIwDQYJKoZI
hvcNAQEBBQADggEPADCCAQoCggEBAL9xYgjx+lk09xvJGKP3gElY6SKDE6bFIEMBO4Tx5oVJnyfq
9oQbTqC023CYxzIBsQU+B07u9PpPL1kwIuerGVZr4oAH/PMWdYA5UXvl+TW2dE6pjYIT5LY/qQOD
+qK+ihVqf94Lw7YZFAXK6sOoBJQ7RnwyDfMAZiLIjWltNowRGLfTshxgtDj6AozO091GB94KPutd
fMh8+7ArU6SSYmlRJQVhGkSBjCypQ5Yj36w6gZoOKcUcqeldHraenjAKOc7xiID7S13MMuyFYkMl
NAJWJwGRtDtwKj9useiciAF9n9T521NtYJ2/LOdYq7hfRvzOxBsDPAnrSTFcaUaz4EcCAwEAAaNC
MEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFDqahQcQZyi27/a9
BUFuIMGU2g/eMA0GCSqGSIb3DQEBCwUAA4IBAQCZ21151fmXWWcDYfF+OwYxdS2hII5PZYe096ac
vNjpL9DbWu7PdIxztDhC2gV7+AJ1uP2lsdeu9tfeE8tTEH6KRtGX+rcuKxGrkLAngPnon1rpN5+r
5N9ss4UXnT3ZJE95kTXWXwTrgIOrmgIttRD02JDHBHNA7XIloKmf7J6raBKZV8aPEjoJpL1E/QYV
N8Gb5DKj7Tjo2GTzLH4U/ALqn83/B2gX2yKQOC16jdFU8WnjXzPKej17CuPKf1855eJ1usV2GDPO
LPAvTK33sefOT6jEm0pUBsV/fdUID+Ic/n4XuKxe9tQWskMJDE32p2u0mYRlynqI4uJEvlz36hz1
-----END CERTIFICATE-----

Starfield Root Certificate Authority - G2
=========================================
-----BEGIN CERTIFICATE-----
MIID3TCCAsWgAwIBAgIBADANBgkqhkiG9w0BAQsFADCBjzELMAkGA1UEBhMCVVMxEDAOBgNVBAgT
B0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxJTAjBgNVBAoTHFN0YXJmaWVsZCBUZWNobm9s
b2dpZXMsIEluYy4xMjAwBgNVBAMTKVN0YXJmaWVsZCBSb290IENlcnRpZmljYXRlIEF1dGhvcml0
eSAtIEcyMB4XDTA5MDkwMTAwMDAwMFoXDTM3MTIzMTIzNTk1OVowgY8xCzAJBgNVBAYTAlVTMRAw
DgYDVQQIEwdBcml6b25hMRMwEQYDVQQHEwpTY290dHNkYWxlMSUwIwYDVQQKExxTdGFyZmllbGQg
VGVjaG5vbG9naWVzLCBJbmMuMTIwMAYDVQQDEylTdGFyZmllbGQgUm9vdCBDZXJ0aWZpY2F0ZSBB
dXRob3JpdHkgLSBHMjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAL3twQP89o/8ArFv
W59I2Z154qK3A2FWGMNHttfKPTUuiUP3oWmb3ooa/RMgnLRJdzIpVv257IzdIvpy3Cdhl+72WoTs
bhm5iSzchFvVdPtrX8WJpRBSiUZV9Lh1HOZ/5FSuS/hVclcCGfgXcVnrHigHdMWdSL5stPSksPNk
N3mSwOxGXn/hbVNMYq/NHwtjuzqd+/x5AJhhdM8mgkBj87JyahkNmcrUDnXMN/uLicFZ8WJ/X7Nf
ZTD4p7dNdloedl40wOiWVpmKs/B/pM293DIxfJHP4F8R+GuqSVzRmZTRouNjWwl2tVZi4Ut0HZbU
JtQIBFnQmA4O5t78w+wfkPECAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC
AQYwHQYDVR0OBBYEFHwMMh+n2TB/xH1oo2Kooc6rB1snMA0GCSqGSIb3DQEBCwUAA4IBAQARWfol
TwNvlJk7mh+ChTnUdgWUXuEok21iXQnCoKjUsHU48TRqneSfioYmUeYs0cYtbpUgSpIB7LiKZ3sx
4mcujJUDJi5DnUox9g61DLu34jd/IroAow57UvtruzvE03lRTs2Q9GcHGcg8RnoNAX3FWOdt5oUw
F5okxBDgBPfg8n/Uqgr/Qh037ZTlZFkSIHc40zI+OIF1lnP6aI+xy84fxez6nH7PfrHxBy22/L/K
pL/QlwVKvOoYKAKQvVR4CSFx09F9HdkWsKlhPdAKACL8x3vLCWRFCztAgfd9fDL1mMpYjn0q7pBZ
c2T5NnReJaH1ZgUufzkVqSr7UIuOhWn0
-----END CERTIFICATE-----

Starfield Services Root Certificate Authority - G2
==================================================
-----BEGIN CERTIFICATE-----
MIID7zCCAtegAwIBAgIBADANBgkqhkiG9w0BAQsFADCBmDELMAkGA1UEBhMCVVMxEDAOBgNVBAgT
B0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxJTAjBgNVBAoTHFN0YXJmaWVsZCBUZWNobm9s
b2dpZXMsIEluYy4xOzA5BgNVBAMTMlN0YXJmaWVsZCBTZXJ2aWNlcyBSb290IENlcnRpZmljYXRl
IEF1dGhvcml0eSAtIEcyMB4XDTA5MDkwMTAwMDAwMFoXDTM3MTIzMTIzNTk1OVowgZgxCzAJBgNV
BAYTAlVTMRAwDgYDVQQIEwdBcml6b25hMRMwEQYDVQQHEwpTY290dHNkYWxlMSUwIwYDVQQKExxT
dGFyZmllbGQgVGVjaG5vbG9naWVzLCBJbmMuMTswOQYDVQQDEzJTdGFyZmllbGQgU2VydmljZXMg
Um9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkgLSBHMjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC
AQoCggEBANUMOsQq+U7i9b4Zl1+OiFOxHz/Lz58gE20pOsgPfTz3a3Y4Y9k2YKibXlwAgLIvWX/2
h/klQ4bnaRtSmpDhcePYLQ1Ob/bISdm28xpWriu2dBTrz/sm4xq6HZYuajtYlIlHVv8loJNwU4Pa
hHQUw2eeBGg6345AWh1KTs9DkTvnVtYAcMtS7nt9rjrnvDH5RfbCYM8TWQIrgMw0R9+53pBlbQLP
LJGmpufehRhJfGZOozptqbXuNC66DQO4M99H67FrjSXZm86B0UVGMpZwh94CDklDhbZsc7tk6mFB
rMnUVN+HL8cisibMn1lUaJ/8viovxFUcdUBgF4UCVTmLfwUCAwEAAaNCMEAwDwYDVR0TAQH/BAUw
AwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFJxfAN+qAdcwKziIorhtSpzyEZGDMA0GCSqG
SIb3DQEBCwUAA4IBAQBLNqaEd2ndOxmfZyMIbw5hyf2E3F/YNoHN2BtBLZ9g3ccaaNnRbobhiCPP
E95Dz+I0swSdHynVv/heyNXBve6SbzJ08pGCL72CQnqtKrcgfU28elUSwhXqvfdqlS5sdJ/PHLTy
xQGjhdByPq1zqwubdQxtRbeOlKyWN7Wg0I8VRw7j6IPdj/3vQQF3zCepYoUz8jcI73HPdwbeyBkd
iEDPfUYd/x7H4c7/I9vG+o1VTqkC50cRRj70/b17KSa7qWFiNyi2LSr2EIZkyXCn0q23KXB56jza
YyWf/Wi3MOxw+3WKt21gZ7IeyLnp2KhvAotnDU0mV3HaIPzBSlCNsSi6
-----END CERTIFICATE-----

AffirmTrust Commercial
======================
-----BEGIN CERTIFICATE-----
MIIDTDCCAjSgAwIBAgIId3cGJyapsXwwDQYJKoZIhvcNAQELBQAwRDELMAkGA1UEBhMCVVMxFDAS
BgNVBAoMC0FmZmlybVRydXN0MR8wHQYDVQQDDBZBZmZpcm1UcnVzdCBDb21tZXJjaWFsMB4XDTEw
MDEyOTE0MDYwNloXDTMwMTIzMTE0MDYwNlowRDELMAkGA1UEBhMCVVMxFDASBgNVBAoMC0FmZmly
bVRydXN0MR8wHQYDVQQDDBZBZmZpcm1UcnVzdCBDb21tZXJjaWFsMIIBIjANBgkqhkiG9w0BAQEF
AAOCAQ8AMIIBCgKCAQEA9htPZwcroRX1BiLLHwGy43NFBkRJLLtJJRTWzsO3qyxPxkEylFf6Eqdb
DuKPHx6GGaeqtS25Xw2Kwq+FNXkyLbscYjfysVtKPcrNcV/pQr6U6Mje+SJIZMblq8Yrba0F8PrV
C8+a5fBQpIs7R6UjW3p6+DM/uO+Zl+MgwdYoic+U+7lF7eNAFxHUdPALMeIrJmqbTFeurCA+ukV6
BfO9m2kVrn1OIGPENXY6BwLJN/3HR+7o8XYdcxXyl6S1yHp52UKqK39c/s4mT6NmgTWvRLpUHhww
MmWd5jyTXlBOeuM61G7MGvv50jeuJCqrVwMiKA1JdX+3KNp1v47j3A55MQIDAQABo0IwQDAdBgNV
HQ4EFgQUnZPGU4teyq8/nx4P5ZmVvCT2lI8wDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC
AQYwDQYJKoZIhvcNAQELBQADggEBAFis9AQOzcAN/wr91LoWXym9e2iZWEnStB03TX8nfUYGXUPG
hi4+c7ImfU+TqbbEKpqrIZcUsd6M06uJFdhrJNTxFq7YpFzUf1GO7RgBsZNjvbz4YYCanrHOQnDi
qX0GJX0nof5v7LMeJNrjS1UaADs1tDvZ110w/YETifLCBivtZ8SOyUOyXGsViQK8YvxO8rUzqrJv
0wqiUOP2O+guRMLbZjipM1ZI8W0bM40NjD9gN53Tym1+NH4Nn3J2ixufcv1SNUFFApYvHLKac0kh
sUlHRUe072o0EclNmsxZt9YCnlpOZbWUrhvfKbAW8b8Angc6F2S1BLUjIZkKlTuXfO8=
-----END CERTIFICATE-----

AffirmTrust Networking
======================
-----BEGIN CERTIFICATE-----
MIIDTDCCAjSgAwIBAgIIfE8EORzUmS0wDQYJKoZIhvcNAQEFBQAwRDELMAkGA1UEBhMCVVMxFDAS
BgNVBAoMC0FmZmlybVRydXN0MR8wHQYDVQQDDBZBZmZpcm1UcnVzdCBOZXR3b3JraW5nMB4XDTEw
MDEyOTE0MDgyNFoXDTMwMTIzMTE0MDgyNFowRDELMAkGA1UEBhMCVVMxFDASBgNVBAoMC0FmZmly
bVRydXN0MR8wHQYDVQQDDBZBZmZpcm1UcnVzdCBOZXR3b3JraW5nMIIBIjANBgkqhkiG9w0BAQEF
AAOCAQ8AMIIBCgKCAQEAtITMMxcua5Rsa2FSoOujz3mUTOWUgJnLVWREZY9nZOIG41w3SfYvm4SE
Hi3yYJ0wTsyEheIszx6e/jarM3c1RNg1lho9Nuh6DtjVR6FqaYvZ/Ls6rnla1fTWcbuakCNrmreI
dIcMHl+5ni36q1Mr3Lt2PpNMCAiMHqIjHNRqrSK6mQEubWXLviRmVSRLQESxG9fhwoXA3hA/Pe24
/PHxI1Pcv2WXb9n5QHGNfb2V1M6+oF4nI979ptAmDgAp6zxG8D1gvz9Q0twmQVGeFDdCBKNwV6gb
h+0t+nvujArjqWaJGctB+d1ENmHP4ndGyH329JKBNv3bNPFyfvMMFr20FQIDAQABo0IwQDAdBgNV
HQ4EFgQUBx/S55zawm6iQLSwelAQUHTEyL0wDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC
AQYwDQYJKoZIhvcNAQEFBQADggEBAIlXshZ6qML91tmbmzTCnLQyFE2npN/svqe++EPbkTfOtDIu
UFUaNU52Q3Eg75N3ThVwLofDwR1t3Mu1J9QsVtFSUzpE0nPIxBsFZVpikpzuQY0x2+c06lkh1QF6
12S4ZDnNye2v7UsDSKegmQGA3GWjNq5lWUhPgkvIZfFXHeVZLgo/bNjR9eUJtGxUAArgFU2HdW23
WJZa3W3SAKD0m0i+wzekujbgfIeFlxoVot4uolu9rxj5kFDNcFn4J2dHy8egBzp90SxdbBk6ZrV9
/ZFvgrG+CJPbFEfxojfHRZ48x3evZKiT3/Zpg4Jg8klCNO1aAFSFHBY2kgxc+qatv9s=
-----END CERTIFICATE-----

AffirmTrust Premium
===================
-----BEGIN CERTIFICATE-----
MIIFRjCCAy6gAwIBAgIIbYwURrGmCu4wDQYJKoZIhvcNAQEMBQAwQTELMAkGA1UEBhMCVVMxFDAS
BgNVBAoMC0FmZmlybVRydXN0MRwwGgYDVQQDDBNBZmZpcm1UcnVzdCBQcmVtaXVtMB4XDTEwMDEy
OTE0MTAzNloXDTQwMTIzMTE0MTAzNlowQTELMAkGA1UEBhMCVVMxFDASBgNVBAoMC0FmZmlybVRy
dXN0MRwwGgYDVQQDDBNBZmZpcm1UcnVzdCBQcmVtaXVtMIICIjANBgkqhkiG9w0BAQEFAAOCAg8A
MIICCgKCAgEAxBLfqV/+Qd3d9Z+K4/as4Tx4mrzY8H96oDMq3I0gW64tb+eT2TZwamjPjlGjhVtn
BKAQJG9dKILBl1fYSCkTtuG+kU3fhQxTGJoeJKJPj/CihQvL9Cl/0qRY7iZNyaqoe5rZ+jjeRFcV
5fiMyNlI4g0WJx0eyIOFJbe6qlVBzAMiSy2RjYvmia9mx+n/K+k8rNrSs8PhaJyJ+HoAVt70VZVs
+7pk3WKL3wt3MutizCaam7uqYoNMtAZ6MMgpv+0GTZe5HMQxK9VfvFMSF5yZVylmd2EhMQcuJUmd
GPLu8ytxjLW6OQdJd/zvLpKQBY0tL3d770O/Nbua2Plzpyzy0FfuKE4mX4+QaAkvuPjcBukumj5R
p9EixAqnOEhss/n/fauGV+O61oV4d7pD6kh/9ti+I20ev9E2bFhc8e6kGVQa9QPSdubhjL08s9NI
S+LI+H+SqHZGnEJlPqQewQcDWkYtuJfzt9WyVSHvutxMAJf7FJUnM7/oQ0dG0giZFmA7mn7S5u04
6uwBHjxIVkkJx0w3AJ6IDsBz4W9m6XJHMD4Q5QsDyZpCAGzFlH5hxIrff4IaC1nEWTJ3s7xgaVY5
/bQGeyzWZDbZvUjthB9+pSKPKrhC9IK31FOQeE4tGv2Bb0TXOwF0lkLgAOIua+rF7nKsu7/+6qqo
+Nz2snmKtmcCAwEAAaNCMEAwHQYDVR0OBBYEFJ3AZ6YMItkm9UWrpmVSESfYRaxjMA8GA1UdEwEB
/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMA0GCSqGSIb3DQEBDAUAA4ICAQCzV00QYk465KzquByv
MiPIs0laUZx2KI15qldGF9X1Uva3ROgIRL8YhNILgM3FEv0AVQVhh0HctSSePMTYyPtwni94loMg
Nt58D2kTiKV1NpgIpsbfrM7jWNa3Pt668+s0QNiigfV4Py/VpfzZotReBA4Xrf5B8OWycvpEgjNC
6C1Y91aMYj+6QrCcDFx+LmUmXFNPALJ4fqENmS2NuB2OosSw/WDQMKSOyARiqcTtNd56l+0OOF6S
L5Nwpamcb6d9Ex1+xghIsV5n61EIJenmJWtSKZGc0jlzCFfemQa0W50QBuHCAKi4HEoCChTQwUHK
+4w1IX2COPKpVJEZNZOUbWo6xbLQu4mGk+ibyQ86p3q4ofB4Rvr8Ny/lioTz3/4E2aFooC8k4gmV
BtWVyuEklut89pMFu+1z6S3RdTnX5yTb2E5fQ4+e0BQ5v1VwSJlXMbSc7kqYA5YwH2AG7hsj/oFg
IxpHYoWlzBk0gG+zrBrjn/B7SK3VAdlntqlyk+otZrWyuOQ9PLLvTIzq6we/qzWaVYa8GKa1qF60
g2xraUDTn9zxw2lrueFtCfTxqlB2Cnp9ehehVZZCmTEJ3WARjQUwfuaORtGdFNrHF+QFlozEJLUb
zxQHskD4o55BhrwE0GuWyCqANP2/7waj3VjFhT0+j/6eKeC2uAloGRwYQw==
-----END CERTIFICATE-----

AffirmTrust Premium ECC
=======================
-----BEGIN CERTIFICATE-----
MIIB/jCCAYWgAwIBAgIIdJclisc/elQwCgYIKoZIzj0EAwMwRTELMAkGA1UEBhMCVVMxFDASBgNV
BAoMC0FmZmlybVRydXN0MSAwHgYDVQQDDBdBZmZpcm1UcnVzdCBQcmVtaXVtIEVDQzAeFw0xMDAx
MjkxNDIwMjRaFw00MDEyMzExNDIwMjRaMEUxCzAJBgNVBAYTAlVTMRQwEgYDVQQKDAtBZmZpcm1U
cnVzdDEgMB4GA1UEAwwXQWZmaXJtVHJ1c3QgUHJlbWl1bSBFQ0MwdjAQBgcqhkjOPQIBBgUrgQQA
IgNiAAQNMF4bFZ0D0KF5Nbc6PJJ6yhUczWLznCZcBz3lVPqj1swS6vQUX+iOGasvLkjmrBhDeKzQ
N8O9ss0s5kfiGuZjuD0uL3jET9v0D6RoTFVya5UdThhClXjMNzyR4ptlKymjQjBAMB0GA1UdDgQW
BBSaryl6wBE1NSZRMADDav5A1a7WPDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAK
BggqhkjOPQQDAwNnADBkAjAXCfOHiFBar8jAQr9HX/VsaobgxCd05DhT1wV/GzTjxi+zygk8N53X
57hG8f2h4nECMEJZh0PUUd+60wkyWs6Iflc9nF9Ca/UHLbXwgpP5WW+uZPpY5Yse42O+tYHNbwKM
eQ==
-----END CERTIFICATE-----

Certum Trusted Network CA
=========================
-----BEGIN CERTIFICATE-----
MIIDuzCCAqOgAwIBAgIDBETAMA0GCSqGSIb3DQEBBQUAMH4xCzAJBgNVBAYTAlBMMSIwIAYDVQQK
ExlVbml6ZXRvIFRlY2hub2xvZ2llcyBTLkEuMScwJQYDVQQLEx5DZXJ0dW0gQ2VydGlmaWNhdGlv
biBBdXRob3JpdHkxIjAgBgNVBAMTGUNlcnR1bSBUcnVzdGVkIE5ldHdvcmsgQ0EwHhcNMDgxMDIy
MTIwNzM3WhcNMjkxMjMxMTIwNzM3WjB+MQswCQYDVQQGEwJQTDEiMCAGA1UEChMZVW5pemV0byBU
ZWNobm9sb2dpZXMgUy5BLjEnMCUGA1UECxMeQ2VydHVtIENlcnRpZmljYXRpb24gQXV0aG9yaXR5
MSIwIAYDVQQDExlDZXJ0dW0gVHJ1c3RlZCBOZXR3b3JrIENBMIIBIjANBgkqhkiG9w0BAQEFAAOC
AQ8AMIIBCgKCAQEA4/t9o3K6wvDJFIf1awFO4W5AB7ptJ11/91sts1rHUV+rpDKmYYe2bg+G0jAC
l/jXaVehGDldamR5xgFZrDwxSjh80gTSSyjoIF87B6LMTXPb865Px1bVWqeWifrzq2jUI4ZZJ88J
J7ysbnKDHDBy3+Ci6dLhdHUZvSqeexVUBBvXQzmtVSjF4hq79MDkrjhJM8x2hZ85RdKknvISjFH4
fOQtf/WsX+sWn7Et0brMkUJ3TCXJkDhv2/DM+44el1k+1WBO5gUo7Ul5E0u6SNsv+XLTOcr+H9g0
cvW0QM8xAcPs3hEtF10fuFDRXhmnad4HMyjKUJX5p1TLVIZQRan5SQIDAQABo0IwQDAPBgNVHRMB
Af8EBTADAQH/MB0GA1UdDgQWBBQIds3LB/8k9sXN7buQvOKEN0Z19zAOBgNVHQ8BAf8EBAMCAQYw
DQYJKoZIhvcNAQEFBQADggEBAKaorSLOAT2mo/9i0Eidi15ysHhE49wcrwn9I0j6vSrEuVUEtRCj
jSfeC4Jj0O7eDDd5QVsisrCaQVymcODU0HfLI9MA4GxWL+FpDQ3Zqr8hgVDZBqWo/5U30Kr+4rP1
mS1FhIrlQgnXdAIv94nYmem8J9RHjboNRhx3zxSkHLmkMcScKHQDNP8zGSal6Q10tz6XxnboJ5aj
Zt3hrvJBW8qYVoNzcOSGGtIxQbovvi0TWnZvTuhOgQ4/WwMioBK+ZlgRSssDxLQqKi2WF+A5VLxI
03YnnZotBqbJ7DnSq9ufmgsnAjUpsUCV5/nonFWIGUbWtzT1fs45mtk48VH3Tyw=
-----END CERTIFICATE-----

TWCA Root Certification Authority
=================================
-----BEGIN CERTIFICATE-----
MIIDezCCAmOgAwIBAgIBATANBgkqhkiG9w0BAQUFADBfMQswCQYDVQQGEwJUVzESMBAGA1UECgwJ
VEFJV0FOLUNBMRAwDgYDVQQLDAdSb290IENBMSowKAYDVQQDDCFUV0NBIFJvb3QgQ2VydGlmaWNh
dGlvbiBBdXRob3JpdHkwHhcNMDgwODI4MDcyNDMzWhcNMzAxMjMxMTU1OTU5WjBfMQswCQYDVQQG
EwJUVzESMBAGA1UECgwJVEFJV0FOLUNBMRAwDgYDVQQLDAdSb290IENBMSowKAYDVQQDDCFUV0NB
IFJvb3QgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEK
AoIBAQCwfnK4pAOU5qfeCTiRShFAh6d8WWQUe7UREN3+v9XAu1bihSX0NXIP+FPQQeFEAcK0HMMx
QhZHhTMidrIKbw/lJVBPhYa+v5guEGcevhEFhgWQxFnQfHgQsIBct+HHK3XLfJ+utdGdIzdjp9xC
oi2SBBtQwXu4PhvJVgSLL1KbralW6cH/ralYhzC2gfeXRfwZVzsrb+RH9JlF/h3x+JejiB03HFyP
4HYlmlD4oFT/RJB2I9IyxsOrBr/8+7/zrX2SYgJbKdM1o5OaQ2RgXbL6Mv87BK9NQGr5x+PvI/1r
y+UPizgN7gr8/g+YnzAx3WxSZfmLgb4i4RxYA7qRG4kHAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIB
BjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBRqOFsmjd6LWvJPelSDGRjjCDWmujANBgkqhkiG
9w0BAQUFAAOCAQEAPNV3PdrfibqHDAhUaiBQkr6wQT25JmSDCi/oQMCXKCeCMErJk/9q56YAf4lC
mtYR5VPOL8zy2gXE/uJQxDqGfczafhAJO5I1KlOy/usrBdlsXebQ79NqZp4VKIV66IIArB6nCWlW
QtNoURi+VJq/REG6Sb4gumlc7rh3zc5sH62Dlhh9DrUUOYTxKOkto557HnpyWoOzeW/vtPzQCqVY
T0bf+215WfKEIlKuD8z7fDvnaspHYcN6+NOSBB+4IIThNlQWx0DeO4pz3N/GCUzf7Nr/1FNCocny
Yh0igzyXxfkZYiesZSLX0zzG5Y6yU8xJzrww/nsOM5D77dIUkR8Hrw==
-----END CERTIFICATE-----

Security Communication RootCA2
==============================
-----BEGIN CERTIFICATE-----
MIIDdzCCAl+gAwIBAgIBADANBgkqhkiG9w0BAQsFADBdMQswCQYDVQQGEwJKUDElMCMGA1UEChMc
U0VDT00gVHJ1c3QgU3lzdGVtcyBDTy4sTFRELjEnMCUGA1UECxMeU2VjdXJpdHkgQ29tbXVuaWNh
dGlvbiBSb290Q0EyMB4XDTA5MDUyOTA1MDAzOVoXDTI5MDUyOTA1MDAzOVowXTELMAkGA1UEBhMC
SlAxJTAjBgNVBAoTHFNFQ09NIFRydXN0IFN5c3RlbXMgQ08uLExURC4xJzAlBgNVBAsTHlNlY3Vy
aXR5IENvbW11bmljYXRpb24gUm9vdENBMjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB
ANAVOVKxUrO6xVmCxF1SrjpDZYBLx/KWvNs2l9amZIyoXvDjChz335c9S672XewhtUGrzbl+dp++
+T42NKA7wfYxEUV0kz1XgMX5iZnK5atq1LXaQZAQwdbWQonCv/Q4EpVMVAX3NuRFg3sUZdbcDE3R
3n4MqzvEFb46VqZab3ZpUql6ucjrappdUtAtCms1FgkQhNBqyjoGADdH5H5XTz+L62e4iKrFvlNV
spHEfbmwhRkGeC7bYRr6hfVKkaHnFtWOojnflLhwHyg/i/xAXmODPIMqGplrz95Zajv8bxbXH/1K
EOtOghY6rCcMU/Gt1SSwawNQwS08Ft1ENCcadfsCAwEAAaNCMEAwHQYDVR0OBBYEFAqFqXdlBZh8
QIH4D5csOPEK7DzPMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEB
CwUAA4IBAQBMOqNErLlFsceTfsgLCkLfZOoc7llsCLqJX2rKSpWeeo8HxdpFcoJxDjrSzG+ntKEj
u/Ykn8sX/oymzsLS28yN/HH8AynBbF0zX2S2ZTuJbxh2ePXcokgfGT+Ok+vx+hfuzU7jBBJV1uXk
3fs+BXziHV7Gp7yXT2g69ekuCkO2r1dcYmh8t/2jioSgrGK+KwmHNPBqAbubKVY8/gA3zyNs8U6q
tnRGEmyR7jTV7JqR50S+kDFy1UkC9gLl9B/rfNmWVan/7Ir5mUf/NVoCqgTLiluHcSmRvaS0eg29
mvVXIwAHIRc/SjnRBUkLp7Y3gaVdjKozXoEofKd9J+sAro03
-----END CERTIFICATE-----

Actalis Authentication Root CA
==============================
-----BEGIN CERTIFICATE-----
MIIFuzCCA6OgAwIBAgIIVwoRl0LE48wwDQYJKoZIhvcNAQELBQAwazELMAkGA1UEBhMCSVQxDjAM
BgNVBAcMBU1pbGFuMSMwIQYDVQQKDBpBY3RhbGlzIFMucC5BLi8wMzM1ODUyMDk2NzEnMCUGA1UE
AwweQWN0YWxpcyBBdXRoZW50aWNhdGlvbiBSb290IENBMB4XDTExMDkyMjExMjIwMloXDTMwMDky
MjExMjIwMlowazELMAkGA1UEBhMCSVQxDjAMBgNVBAcMBU1pbGFuMSMwIQYDVQQKDBpBY3RhbGlz
IFMucC5BLi8wMzM1ODUyMDk2NzEnMCUGA1UEAwweQWN0YWxpcyBBdXRoZW50aWNhdGlvbiBSb290
IENBMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAp8bEpSmkLO/lGMWwUKNvUTufClrJ
wkg4CsIcoBh/kbWHuUA/3R1oHwiD1S0eiKD4j1aPbZkCkpAW1V8IbInX4ay8IMKx4INRimlNAJZa
by/ARH6jDuSRzVju3PvHHkVH3Se5CAGfpiEd9UEtL0z9KK3giq0itFZljoZUj5NDKd45RnijMCO6
zfB9E1fAXdKDa0hMxKufgFpbOr3JpyI/gCczWw63igxdBzcIy2zSekciRDXFzMwujt0q7bd9Zg1f
YVEiVRvjRuPjPdA1YprbrxTIW6HMiRvhMCb8oJsfgadHHwTrozmSBp+Z07/T6k9QnBn+locePGX2
oxgkg4YQ51Q+qDp2JE+BIcXjDwL4k5RHILv+1A7TaLndxHqEguNTVHnd25zS8gebLra8Pu2Fbe8l
EfKXGkJh90qX6IuxEAf6ZYGyojnP9zz/GPvG8VqLWeICrHuS0E4UT1lF9gxeKF+w6D9Fz8+vm2/7
hNN3WpVvrJSEnu68wEqPSpP4RCHiMUVhUE4Q2OM1fEwZtN4Fv6MGn8i1zeQf1xcGDXqVdFUNaBr8
EBtiZJ1t4JWgw5QHVw0U5r0F+7if5t+L4sbnfpb2U8WANFAoWPASUHEXMLrmeGO89LKtmyuy/uE5
jF66CyCU3nuDuP/jVo23Eek7jPKxwV2dpAtMK9myGPW1n0sCAwEAAaNjMGEwHQYDVR0OBBYEFFLY
iDrIn3hm7YnzezhwlMkCAjbQMA8GA1UdEwEB/wQFMAMBAf8wHwYDVR0jBBgwFoAUUtiIOsifeGbt
ifN7OHCUyQICNtAwDgYDVR0PAQH/BAQDAgEGMA0GCSqGSIb3DQEBCwUAA4ICAQALe3KHwGCmSUyI
WOYdiPcUZEim2FgKDk8TNd81HdTtBjHIgT5q1d07GjLukD0R0i70jsNjLiNmsGe+b7bAEzlgqqI0
JZN1Ut6nna0Oh4lScWoWPBkdg/iaKWW+9D+a2fDzWochcYBNy+A4mz+7+uAwTc+G02UQGRjRlwKx
K3JCaKygvU5a2hi/a5iB0P2avl4VSM0RFbnAKVy06Ij3Pjaut2L9HmLecHgQHEhb2rykOLpn7VU+
Xlff1ANATIGk0k9jpwlCCRT8AKnCgHNPLsBA2RF7SOp6AsDT6ygBJlh0wcBzIm2Tlf05fbsq4/aC
4yyXX04fkZT6/iyj2HYauE2yOE+b+h1IYHkm4vP9qdCa6HCPSXrW5b0KDtst842/6+OkfcvHlXHo
2qN8xcL4dJIEG4aspCJTQLas/kx2z/uUMsA1n3Y/buWQbqCmJqK4LL7RK4X9p2jIugErsWx0Hbhz
lefut8cl8ABMALJ+tguLHPPAUJ4lueAI3jZm/zel0btUZCzJJ7VLkn5l/9Mt4blOvH+kQSGQQXem
OR/qnuOf0GZvBeyqdn6/axag67XH/JJULysRJyU3eExRarDzzFhdFPFqSBX/wge2sY0PjlxQRrM9
vwGYT7JZVEc+NHt4bVaTLnPqZih4zR0Uv6CPLy64Lo7yFIrM6bV8+2ydDKXhlg==
-----END CERTIFICATE-----

Buypass Class 2 Root CA
=======================
-----BEGIN CERTIFICATE-----
MIIFWTCCA0GgAwIBAgIBAjANBgkqhkiG9w0BAQsFADBOMQswCQYDVQQGEwJOTzEdMBsGA1UECgwU
QnV5cGFzcyBBUy05ODMxNjMzMjcxIDAeBgNVBAMMF0J1eXBhc3MgQ2xhc3MgMiBSb290IENBMB4X
DTEwMTAyNjA4MzgwM1oXDTQwMTAyNjA4MzgwM1owTjELMAkGA1UEBhMCTk8xHTAbBgNVBAoMFEJ1
eXBhc3MgQVMtOTgzMTYzMzI3MSAwHgYDVQQDDBdCdXlwYXNzIENsYXNzIDIgUm9vdCBDQTCCAiIw
DQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBANfHXvfBB9R3+0Mh9PT1aeTuMgHbo4Yf5FkNuud1
g1Lr6hxhFUi7HQfKjK6w3Jad6sNgkoaCKHOcVgb/S2TwDCo3SbXlzwx87vFKu3MwZfPVL4O2fuPn
9Z6rYPnT8Z2SdIrkHJasW4DptfQxh6NR/Md+oW+OU3fUl8FVM5I+GC911K2GScuVr1QGbNgGE41b
/+EmGVnAJLqBcXmQRFBoJJRfuLMR8SlBYaNByyM21cHxMlAQTn/0hpPshNOOvEu/XAFOBz3cFIqU
CqTqc/sLUegTBxj6DvEr0VQVfTzh97QZQmdiXnfgolXsttlpF9U6r0TtSsWe5HonfOV116rLJeff
awrbD02TTqigzXsu8lkBarcNuAeBfos4GzjmCleZPe4h6KP1DBbdi+w0jpwqHAAVF41og9JwnxgI
zRFo1clrUs3ERo/ctfPYV3Me6ZQ5BL/T3jjetFPsaRyifsSP5BtwrfKi+fv3FmRmaZ9JUaLiFRhn
Bkp/1Wy1TbMz4GHrXb7pmA8y1x1LPC5aAVKRCfLf6o3YBkBjqhHk/sM3nhRSP/TizPJhk9H9Z2vX
Uq6/aKtAQ6BXNVN48FP4YUIHZMbXb5tMOA1jrGKvNouicwoN9SG9dKpN6nIDSdvHXx1iY8f93ZHs
M+71bbRuMGjeyNYmsHVee7QHIJihdjK4TWxPAgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wHQYD
VR0OBBYEFMmAd+BikoL1RpzzuvdMw964o605MA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQsF
AAOCAgEAU18h9bqwOlI5LJKwbADJ784g7wbylp7ppHR/ehb8t/W2+xUbP6umwHJdELFx7rxP462s
A20ucS6vxOOto70MEae0/0qyexAQH6dXQbLArvQsWdZHEIjzIVEpMMpghq9Gqx3tOluwlN5E40EI
osHsHdb9T7bWR9AUC8rmyrV7d35BH16Dx7aMOZawP5aBQW9gkOLo+fsicdl9sz1Gv7SEr5AcD48S
aq/v7h56rgJKihcrdv6sVIkkLE8/trKnToyokZf7KcZ7XC25y2a2t6hbElGFtQl+Ynhw/qlqYLYd
DnkM/crqJIByw5c/8nerQyIKx+u2DISCLIBrQYoIwOula9+ZEsuK1V6ADJHgJgg2SMX6OBE1/yWD
LfJ6v9r9jv6ly0UsH8SIU653DtmadsWOLB2jutXsMq7Aqqz30XpN69QH4kj3Io6wpJ9qzo6ysmD0
oyLQI+uUWnpp3Q+/QFesa1lQ2aOZ4W7+jQF5JyMV3pKdewlNWudLSDBaGOYKbeaP4NK75t98biGC
wWg5TbSYWGZizEqQXsP6JwSxeRV0mcy+rSDeJmAc61ZRpqPq5KM/p/9h3PFaTWwyI0PurKju7koS
CTxdccK+efrCh2gdC/1cacwG0Jp9VJkqyTkaGa9LKkPzY11aWOIv4x3kqdbQCtCev9eBCfHJxyYN
rJgWVqA=
-----END CERTIFICATE-----

Buypass Class 3 Root CA
=======================
-----BEGIN CERTIFICATE-----
MIIFWTCCA0GgAwIBAgIBAjANBgkqhkiG9w0BAQsFADBOMQswCQYDVQQGEwJOTzEdMBsGA1UECgwU
QnV5cGFzcyBBUy05ODMxNjMzMjcxIDAeBgNVBAMMF0J1eXBhc3MgQ2xhc3MgMyBSb290IENBMB4X
DTEwMTAyNjA4Mjg1OFoXDTQwMTAyNjA4Mjg1OFowTjELMAkGA1UEBhMCTk8xHTAbBgNVBAoMFEJ1
eXBhc3MgQVMtOTgzMTYzMzI3MSAwHgYDVQQDDBdCdXlwYXNzIENsYXNzIDMgUm9vdCBDQTCCAiIw
DQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAKXaCpUWUOOV8l6ddjEGMnqb8RB2uACatVI2zSRH
sJ8YZLya9vrVediQYkwiL944PdbgqOkcLNt4EemOaFEVcsfzM4fkoF0LXOBXByow9c3EN3coTRiR
5r/VUv1xLXA+58bEiuPwKAv0dpihi4dVsjoT/Lc+JzeOIuOoTyrvYLs9tznDDgFHmV0ST9tD+leh
7fmdvhFHJlsTmKtdFoqwNxxXnUX/iJY2v7vKB3tvh2PX0DJq1l1sDPGzbjniazEuOQAnFN44wOwZ
ZoYS6J1yFhNkUsepNxz9gjDthBgd9K5c/3ATAOux9TN6S9ZV+AWNS2mw9bMoNlwUxFFzTWsL8TQH
2xc519woe2v1n/MuwU8XKhDzzMro6/1rqy6any2CbgTUUgGTLT2G/H783+9CHaZr77kgxve9oKeV
/afmiSTYzIw0bOIjL9kSGiG5VZFvC5F5GQytQIgLcOJ60g7YaEi7ghM5EFjp2CoHxhLbWNvSO1UQ
RwUVZ2J+GGOmRj8JDlQyXr8NYnon74Do29lLBlo3WiXQCBJ31G8JUJc9yB3D34xFMFbG02SrZvPA
Xpacw8Tvw3xrizp5f7NJzz3iiZ+gMEuFuZyUJHmPfWupRWgPK9Dx2hzLabjKSWJtyNBjYt1gD1iq
j6G8BaVmos8bdrKEZLFMOVLAMLrwjEsCsLa3AgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wHQYD
VR0OBBYEFEe4zf/lb+74suwvTg75JbCOPGvDMA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQsF
AAOCAgEAACAjQTUEkMJAYmDv4jVM1z+s4jSQuKFvdvoWFqRINyzpkMLyPPgKn9iB5btb2iUspKdV
cSQy9sgL8rxq+JOssgfCX5/bzMiKqr5qb+FJEMwx14C7u8jYog5kV+qi9cKpMRXSIGrs/CIBKM+G
uIAeqcwRpTzyFrNHnfzSgCHEy9BHcEGhyoMZCCxt8l13nIoUE9Q2HJLw5QY33KbmkJs4j1xrG0aG
Q0JfPgEHU1RdZX33inOhmlRaHylDFCfChQ+1iHsaO5S3HWCntZznKWlXWpuTekMwGwPXYshApqr8
ZORK15FTAaggiG6cX0S5y2CBNOxv033aSF/rtJC8LakcC6wc1aJoIIAE1vyxjy+7SjENSoYc6+I2
KSb12tjE8nVhz36udmNKekBlk4f4HoCMhuWG1o8O/FMsYOgWYRqiPkN7zTlgVGr18okmAWiDSKIz
6MkEkbIRNBE+6tBDGR8Dk5AM/1E9V/RBbuHLoL7ryWPNbczk+DaqaJ3tvV2XcEQNtg413OEMXbug
UZTLfhbrES+jkkXITHHZvMmZUldGL1DPvTVp9D0VzgalLA8+9oG6lLvDu79leNKGef9JOxqDDPDe
eOzI8k1MGt6CKfjBWtrt7uYnXuhF0J0cUahoq0Tj0Itq4/g7u9xN12TyUb7mqqta6THuBrxzvxNi
Cp/HuZc=
-----END CERTIFICATE-----

T-TeleSec GlobalRoot Class 3
============================
-----BEGIN CERTIFICATE-----
MIIDwzCCAqugAwIBAgIBATANBgkqhkiG9w0BAQsFADCBgjELMAkGA1UEBhMCREUxKzApBgNVBAoM
IlQtU3lzdGVtcyBFbnRlcnByaXNlIFNlcnZpY2VzIEdtYkgxHzAdBgNVBAsMFlQtU3lzdGVtcyBU
cnVzdCBDZW50ZXIxJTAjBgNVBAMMHFQtVGVsZVNlYyBHbG9iYWxSb290IENsYXNzIDMwHhcNMDgx
MDAxMTAyOTU2WhcNMzMxMDAxMjM1OTU5WjCBgjELMAkGA1UEBhMCREUxKzApBgNVBAoMIlQtU3lz
dGVtcyBFbnRlcnByaXNlIFNlcnZpY2VzIEdtYkgxHzAdBgNVBAsMFlQtU3lzdGVtcyBUcnVzdCBD
ZW50ZXIxJTAjBgNVBAMMHFQtVGVsZVNlYyBHbG9iYWxSb290IENsYXNzIDMwggEiMA0GCSqGSIb3
DQEBAQUAA4IBDwAwggEKAoIBAQC9dZPwYiJvJK7genasfb3ZJNW4t/zN8ELg63iIVl6bmlQdTQyK
9tPPcPRStdiTBONGhnFBSivwKixVA9ZIw+A5OO3yXDw/RLyTPWGrTs0NvvAgJ1gORH8EGoel15YU
NpDQSXuhdfsaa3Ox+M6pCSzyU9XDFES4hqX2iys52qMzVNn6chr3IhUciJFrf2blw2qAsCTz34ZF
iP0Zf3WHHx+xGwpzJFu5ZeAsVMhg02YXP+HMVDNzkQI6pn97djmiH5a2OK61yJN0HZ65tOVgnS9W
0eDrXltMEnAMbEQgqxHY9Bn20pxSN+f6tsIxO0rUFJmtxxr1XV/6B7h8DR/Wgx6zAgMBAAGjQjBA
MA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBS1A/d2O2GCahKqGFPr
AyGUv/7OyjANBgkqhkiG9w0BAQsFAAOCAQEAVj3vlNW92nOyWL6ukK2YJ5f+AbGwUgC4TeQbIXQb
fsDuXmkqJa9c1h3a0nnJ85cp4IaH3gRZD/FZ1GSFS5mvJQQeyUapl96Cshtwn5z2r3Ex3XsFpSzT
ucpH9sry9uetuUg/vBa3wW306gmv7PO15wWeph6KU1HWk4HMdJP2udqmJQV0eVp+QD6CSyYRMG7h
P0HHRwA11fXT91Q+gT3aSWqas+8QPebrb9HIIkfLzM8BMZLZGOMivgkeGj5asuRrDFR6fUNOuIml
e9eiPZaGzPImNC1qkp2aGtAw4l1OBLBfiyB+d8E9lYLRRpo7PHi4b6HQDWSieB4pTpPDpFQUWw==
-----END CERTIFICATE-----

D-TRUST Root Class 3 CA 2 2009
==============================
-----BEGIN CERTIFICATE-----
MIIEMzCCAxugAwIBAgIDCYPzMA0GCSqGSIb3DQEBCwUAME0xCzAJBgNVBAYTAkRFMRUwEwYDVQQK
DAxELVRydXN0IEdtYkgxJzAlBgNVBAMMHkQtVFJVU1QgUm9vdCBDbGFzcyAzIENBIDIgMjAwOTAe
Fw0wOTExMDUwODM1NThaFw0yOTExMDUwODM1NThaME0xCzAJBgNVBAYTAkRFMRUwEwYDVQQKDAxE
LVRydXN0IEdtYkgxJzAlBgNVBAMMHkQtVFJVU1QgUm9vdCBDbGFzcyAzIENBIDIgMjAwOTCCASIw
DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANOySs96R+91myP6Oi/WUEWJNTrGa9v+2wBoqOAD
ER03UAifTUpolDWzU9GUY6cgVq/eUXjsKj3zSEhQPgrfRlWLJ23DEE0NkVJD2IfgXU42tSHKXzlA
BF9bfsyjxiupQB7ZNoTWSPOSHjRGICTBpFGOShrvUD9pXRl/RcPHAY9RySPocq60vFYJfxLLHLGv
KZAKyVXMD9O0Gu1HNVpK7ZxzBCHQqr0ME7UAyiZsxGsMlFqVlNpQmvH/pStmMaTJOKDfHR+4CS7z
p+hnUquVH+BGPtikw8paxTGA6Eian5Rp/hnd2HN8gcqW3o7tszIFZYQ05ub9VxC1X3a/L7AQDcUC
AwEAAaOCARowggEWMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFP3aFMSfMN4hvR5COfyrYyNJ
4PGEMA4GA1UdDwEB/wQEAwIBBjCB0wYDVR0fBIHLMIHIMIGAoH6gfIZ6bGRhcDovL2RpcmVjdG9y
eS5kLXRydXN0Lm5ldC9DTj1ELVRSVVNUJTIwUm9vdCUyMENsYXNzJTIwMyUyMENBJTIwMiUyMDIw
MDksTz1ELVRydXN0JTIwR21iSCxDPURFP2NlcnRpZmljYXRlcmV2b2NhdGlvbmxpc3QwQ6BBoD+G
PWh0dHA6Ly93d3cuZC10cnVzdC5uZXQvY3JsL2QtdHJ1c3Rfcm9vdF9jbGFzc18zX2NhXzJfMjAw
OS5jcmwwDQYJKoZIhvcNAQELBQADggEBAH+X2zDI36ScfSF6gHDOFBJpiBSVYEQBrLLpME+bUMJm
2H6NMLVwMeniacfzcNsgFYbQDfC+rAF1hM5+n02/t2A7nPPKHeJeaNijnZflQGDSNiH+0LS4F9p0
o3/U37CYAqxva2ssJSRyoWXuJVrl5jLn8t+rSfrzkGkj2wTZ51xY/GXUl77M/C4KzCUqNQT4YJEV
dT1B/yMfGchs64JTBKbkTCJNjYy6zltz7GRUUG3RnFX7acM2w4y8PIWmawomDeCTmGCufsYkl4ph
X5GOZpIJhzbNi5stPvZR1FDUWSi9g/LMKHtThm3YJohw1+qRzT65ysCQblrGXnRl11z+o+I=
-----END CERTIFICATE-----

D-TRUST Root Class 3 CA 2 EV 2009
=================================
-----BEGIN CERTIFICATE-----
MIIEQzCCAyugAwIBAgIDCYP0MA0GCSqGSIb3DQEBCwUAMFAxCzAJBgNVBAYTAkRFMRUwEwYDVQQK
DAxELVRydXN0IEdtYkgxKjAoBgNVBAMMIUQtVFJVU1QgUm9vdCBDbGFzcyAzIENBIDIgRVYgMjAw
OTAeFw0wOTExMDUwODUwNDZaFw0yOTExMDUwODUwNDZaMFAxCzAJBgNVBAYTAkRFMRUwEwYDVQQK
DAxELVRydXN0IEdtYkgxKjAoBgNVBAMMIUQtVFJVU1QgUm9vdCBDbGFzcyAzIENBIDIgRVYgMjAw
OTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAJnxhDRwui+3MKCOvXwEz75ivJn9gpfS
egpnljgJ9hBOlSJzmY3aFS3nBfwZcyK3jpgAvDw9rKFs+9Z5JUut8Mxk2og+KbgPCdM03TP1YtHh
zRnp7hhPTFiu4h7WDFsVWtg6uMQYZB7jM7K1iXdODL/ZlGsTl28So/6ZqQTMFexgaDbtCHu39b+T
7WYxg4zGcTSHThfqr4uRjRxWQa4iN1438h3Z0S0NL2lRp75mpoo6Kr3HGrHhFPC+Oh25z1uxav60
sUYgovseO3Dvk5h9jHOW8sXvhXCtKSb8HgQ+HKDYD8tSg2J87otTlZCpV6LqYQXY+U3EJ/pure35
11H3a6UCAwEAAaOCASQwggEgMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFNOUikxiEyoZLsyv
cop9NteaHNxnMA4GA1UdDwEB/wQEAwIBBjCB3QYDVR0fBIHVMIHSMIGHoIGEoIGBhn9sZGFwOi8v
ZGlyZWN0b3J5LmQtdHJ1c3QubmV0L0NOPUQtVFJVU1QlMjBSb290JTIwQ2xhc3MlMjAzJTIwQ0El
MjAyJTIwRVYlMjAyMDA5LE89RC1UcnVzdCUyMEdtYkgsQz1ERT9jZXJ0aWZpY2F0ZXJldm9jYXRp
b25saXN0MEagRKBChkBodHRwOi8vd3d3LmQtdHJ1c3QubmV0L2NybC9kLXRydXN0X3Jvb3RfY2xh
c3NfM19jYV8yX2V2XzIwMDkuY3JsMA0GCSqGSIb3DQEBCwUAA4IBAQA07XtaPKSUiO8aEXUHL7P+
PPoeUSbrh/Yp3uDx1MYkCenBz1UbtDDZzhr+BlGmFaQt77JLvyAoJUnRpjZ3NOhk31KxEcdzes05
nsKtjHEh8lprr988TlWvsoRlFIm5d8sqMb7Po23Pb0iUMkZv53GMoKaEGTcH8gNFCSuGdXzfX2lX
ANtu2KZyIktQ1HWYVt+3GP9DQ1CuekR78HlR10M9p9OB0/DJT7naxpeG0ILD5EJt/rDiZE4OJudA
NCa1CInXCGNjOCd1HjPqbqjdn5lPdE2BiYBL3ZqXKVwvvoFBuYz/6n1gBp7N1z3TLqMVvKjmJuVv
w9y4AyHqnxbxLFS1
-----END CERTIFICATE-----

CA Disig Root R2
================
-----BEGIN CERTIFICATE-----
MIIFaTCCA1GgAwIBAgIJAJK4iNuwisFjMA0GCSqGSIb3DQEBCwUAMFIxCzAJBgNVBAYTAlNLMRMw
EQYDVQQHEwpCcmF0aXNsYXZhMRMwEQYDVQQKEwpEaXNpZyBhLnMuMRkwFwYDVQQDExBDQSBEaXNp
ZyBSb290IFIyMB4XDTEyMDcxOTA5MTUzMFoXDTQyMDcxOTA5MTUzMFowUjELMAkGA1UEBhMCU0sx
EzARBgNVBAcTCkJyYXRpc2xhdmExEzARBgNVBAoTCkRpc2lnIGEucy4xGTAXBgNVBAMTEENBIERp
c2lnIFJvb3QgUjIwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCio8QACdaFXS1tFPbC
w3OeNcJxVX6B+6tGUODBfEl45qt5WDza/3wcn9iXAng+a0EE6UG9vgMsRfYvZNSrXaNHPWSb6Wia
xswbP7q+sos0Ai6YVRn8jG+qX9pMzk0DIaPY0jSTVpbLTAwAFjxfGs3Ix2ymrdMxp7zo5eFm1tL7
A7RBZckQrg4FY8aAamkw/dLukO8NJ9+flXP04SXabBbeQTg06ov80egEFGEtQX6sx3dOy1FU+16S
GBsEWmjGycT6txOgmLcRK7fWV8x8nhfRyyX+hk4kLlYMeE2eARKmK6cBZW58Yh2EhN/qwGu1pSqV
g8NTEQxzHQuyRpDRQjrOQG6Vrf/GlK1ul4SOfW+eioANSW1z4nuSHsPzwfPrLgVv2RvPN3YEyLRa
5Beny912H9AZdugsBbPWnDTYltxhh5EF5EQIM8HauQhl1K6yNg3ruji6DOWbnuuNZt2Zz9aJQfYE
koopKW1rOhzndX0CcQ7zwOe9yxndnWCywmZgtrEE7snmhrmaZkCo5xHtgUUDi/ZnWejBBhG93c+A
Ak9lQHhcR1DIm+YfgXvkRKhbhZri3lrVx/k6RGZL5DJUfORsnLMOPReisjQS1n6yqEm70XooQL6i
Fh/f5DcfEXP7kAplQ6INfPgGAVUzfbANuPT1rqVCV3w2EYx7XsQDnYx5nQIDAQABo0IwQDAPBgNV
HRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUtZn4r7CU9eMg1gqtzk5WpC5u
Qu0wDQYJKoZIhvcNAQELBQADggIBACYGXnDnZTPIgm7ZnBc6G3pmsgH2eDtpXi/q/075KMOYKmFM
tCQSin1tERT3nLXK5ryeJ45MGcipvXrA1zYObYVybqjGom32+nNjf7xueQgcnYqfGopTpti72TVV
sRHFqQOzVju5hJMiXn7B9hJSi+osZ7z+Nkz1uM/Rs0mSO9MpDpkblvdhuDvEK7Z4bLQjb/D907Je
dR+Zlais9trhxTF7+9FGs9K8Z7RiVLoJ92Owk6Ka+elSLotgEqv89WBW7xBci8QaQtyDW2QOy7W8
1k/BfDxujRNt+3vrMNDcTa/F1balTFtxyegxvug4BkihGuLq0t4SOVga/4AOgnXmt8kHbA7v/zjx
mHHEt38OFdAlab0inSvtBfZGR6ztwPDUO+Ls7pZbkBNOHlY667DvlruWIxG68kOGdGSVyCh13x01
utI3gzhTODY7z2zp+WsO0PsE6E9312UBeIYMej4hYvF/Y3EMyZ9E26gnonW+boE+18DrG5gPcFw0
sorMwIUY6256s/daoQe/qUKS82Ail+QUoQebTnbAjn39pCXHR+3/H3OszMOl6W8KjptlwlCFtaOg
UxLMVYdh84GuEEZhvUQhuMI9dM9+JDX6HAcOmz0iyu8xL4ysEr3vQCj8KWefshNPZiTEUxnpHikV
7+ZtsH8tZ/3zbBt1RqPlShfppNcL
-----END CERTIFICATE-----

ACCVRAIZ1
=========
-----BEGIN CERTIFICATE-----
MIIH0zCCBbugAwIBAgIIXsO3pkN/pOAwDQYJKoZIhvcNAQEFBQAwQjESMBAGA1UEAwwJQUNDVlJB
SVoxMRAwDgYDVQQLDAdQS0lBQ0NWMQ0wCwYDVQQKDARBQ0NWMQswCQYDVQQGEwJFUzAeFw0xMTA1
MDUwOTM3MzdaFw0zMDEyMzEwOTM3MzdaMEIxEjAQBgNVBAMMCUFDQ1ZSQUlaMTEQMA4GA1UECwwH
UEtJQUNDVjENMAsGA1UECgwEQUNDVjELMAkGA1UEBhMCRVMwggIiMA0GCSqGSIb3DQEBAQUAA4IC
DwAwggIKAoICAQCbqau/YUqXry+XZpp0X9DZlv3P4uRm7x8fRzPCRKPfmt4ftVTdFXxpNRFvu8gM
jmoYHtiP2Ra8EEg2XPBjs5BaXCQ316PWywlxufEBcoSwfdtNgM3802/J+Nq2DoLSRYWoG2ioPej0
RGy9ocLLA76MPhMAhN9KSMDjIgro6TenGEyxCQ0jVn8ETdkXhBilyNpAlHPrzg5XPAOBOp0KoVdD
aaxXbXmQeOW1tDvYvEyNKKGno6e6Ak4l0Squ7a4DIrhrIA8wKFSVf+DuzgpmndFALW4ir50awQUZ
0m/A8p/4e7MCQvtQqR0tkw8jq8bBD5L/0KIV9VMJcRz/RROE5iZe+OCIHAr8Fraocwa48GOEAqDG
WuzndN9wrqODJerWx5eHk6fGioozl2A3ED6XPm4pFdahD9GILBKfb6qkxkLrQaLjlUPTAYVtjrs7
8yM2x/474KElB0iryYl0/wiPgL/AlmXz7uxLaL2diMMxs0Dx6M/2OLuc5NF/1OVYm3z61PMOm3WR
5LpSLhl+0fXNWhn8ugb2+1KoS5kE3fj5tItQo05iifCHJPqDQsGH+tUtKSpacXpkatcnYGMN285J
9Y0fkIkyF/hzQ7jSWpOGYdbhdQrqeWZ2iE9x6wQl1gpaepPluUsXQA+xtrn13k/c4LOsOxFwYIRK
Q26ZIMApcQrAZQIDAQABo4ICyzCCAscwfQYIKwYBBQUHAQEEcTBvMEwGCCsGAQUFBzAChkBodHRw
Oi8vd3d3LmFjY3YuZXMvZmlsZWFkbWluL0FyY2hpdm9zL2NlcnRpZmljYWRvcy9yYWl6YWNjdjEu
Y3J0MB8GCCsGAQUFBzABhhNodHRwOi8vb2NzcC5hY2N2LmVzMB0GA1UdDgQWBBTSh7Tj3zcnk1X2
VuqB5TbMjB4/vTAPBgNVHRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFNKHtOPfNyeTVfZW6oHlNsyM
Hj+9MIIBcwYDVR0gBIIBajCCAWYwggFiBgRVHSAAMIIBWDCCASIGCCsGAQUFBwICMIIBFB6CARAA
QQB1AHQAbwByAGkAZABhAGQAIABkAGUAIABDAGUAcgB0AGkAZgBpAGMAYQBjAGkA8wBuACAAUgBh
AO0AegAgAGQAZQAgAGwAYQAgAEEAQwBDAFYAIAAoAEEAZwBlAG4AYwBpAGEAIABkAGUAIABUAGUA
YwBuAG8AbABvAGcA7QBhACAAeQAgAEMAZQByAHQAaQBmAGkAYwBhAGMAaQDzAG4AIABFAGwAZQBj
AHQAcgDzAG4AaQBjAGEALAAgAEMASQBGACAAUQA0ADYAMAAxADEANQA2AEUAKQAuACAAQwBQAFMA
IABlAG4AIABoAHQAdABwADoALwAvAHcAdwB3AC4AYQBjAGMAdgAuAGUAczAwBggrBgEFBQcCARYk
aHR0cDovL3d3dy5hY2N2LmVzL2xlZ2lzbGFjaW9uX2MuaHRtMFUGA1UdHwROMEwwSqBIoEaGRGh0
dHA6Ly93d3cuYWNjdi5lcy9maWxlYWRtaW4vQXJjaGl2b3MvY2VydGlmaWNhZG9zL3JhaXphY2N2
MV9kZXIuY3JsMA4GA1UdDwEB/wQEAwIBBjAXBgNVHREEEDAOgQxhY2N2QGFjY3YuZXMwDQYJKoZI
hvcNAQEFBQADggIBAJcxAp/n/UNnSEQU5CmH7UwoZtCPNdpNYbdKl02125DgBS4OxnnQ8pdpD70E
R9m+27Up2pvZrqmZ1dM8MJP1jaGo/AaNRPTKFpV8M9xii6g3+CfYCS0b78gUJyCpZET/LtZ1qmxN
YEAZSUNUY9rizLpm5U9EelvZaoErQNV/+QEnWCzI7UiRfD+mAM/EKXMRNt6GGT6d7hmKG9Ww7Y49
nCrADdg9ZuM8Db3VlFzi4qc1GwQA9j9ajepDvV+JHanBsMyZ4k0ACtrJJ1vnE5Bc5PUzolVt3OAJ
TS+xJlsndQAJxGJ3KQhfnlmstn6tn1QwIgPBHnFk/vk4CpYY3QIUrCPLBhwepH2NDd4nQeit2hW3
sCPdK6jT2iWH7ehVRE2I9DZ+hJp4rPcOVkkO1jMl1oRQQmwgEh0q1b688nCBpHBgvgW1m54ERL5h
I6zppSSMEYCUWqKiuUnSwdzRp+0xESyeGabu4VXhwOrPDYTkF7eifKXeVSUG7szAh1xA2syVP1Xg
Nce4hL60Xc16gwFy7ofmXx2utYXGJt/mwZrpHgJHnyqobalbz+xFd3+YJ5oyXSrjhO7FmGYvliAd
3djDJ9ew+f7Zfc3Qn48LFFhRny+Lwzgt3uiP1o2HpPVWQxaZLPSkVrQ0uGE3ycJYgBugl6H8WY3p
EfbRD0tVNEYqi4Y7
-----END CERTIFICATE-----

TWCA Global Root CA
===================
-----BEGIN CERTIFICATE-----
MIIFQTCCAymgAwIBAgICDL4wDQYJKoZIhvcNAQELBQAwUTELMAkGA1UEBhMCVFcxEjAQBgNVBAoT
CVRBSVdBTi1DQTEQMA4GA1UECxMHUm9vdCBDQTEcMBoGA1UEAxMTVFdDQSBHbG9iYWwgUm9vdCBD
QTAeFw0xMjA2MjcwNjI4MzNaFw0zMDEyMzExNTU5NTlaMFExCzAJBgNVBAYTAlRXMRIwEAYDVQQK
EwlUQUlXQU4tQ0ExEDAOBgNVBAsTB1Jvb3QgQ0ExHDAaBgNVBAMTE1RXQ0EgR2xvYmFsIFJvb3Qg
Q0EwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCwBdvI64zEbooh745NnHEKH1Jw7W2C
nJfF10xORUnLQEK1EjRsGcJ0pDFfhQKX7EMzClPSnIyOt7h52yvVavKOZsTuKwEHktSz0ALfUPZV
r2YOy+BHYC8rMjk1Ujoog/h7FsYYuGLWRyWRzvAZEk2tY/XTP3VfKfChMBwqoJimFb3u/Rk28OKR
Q4/6ytYQJ0lM793B8YVwm8rqqFpD/G2Gb3PpN0Wp8DbHzIh1HrtsBv+baz4X7GGqcXzGHaL3SekV
tTzWoWH1EfcFbx39Eb7QMAfCKbAJTibc46KokWofwpFFiFzlmLhxpRUZyXx1EcxwdE8tmx2RRP1W
KKD+u4ZqyPpcC1jcxkt2yKsi2XMPpfRaAok/T54igu6idFMqPVMnaR1sjjIsZAAmY2E2TqNGtz99
sy2sbZCilaLOz9qC5wc0GZbpuCGqKX6mOL6OKUohZnkfs8O1CWfe1tQHRvMq2uYiN2DLgbYPoA/p
yJV/v1WRBXrPPRXAb94JlAGD1zQbzECl8LibZ9WYkTunhHiVJqRaCPgrdLQABDzfuBSO6N+pjWxn
kjMdwLfS7JLIvgm/LCkFbwJrnu+8vyq8W8BQj0FwcYeyTbcEqYSjMq+u7msXi7Kx/mzhkIyIqJdI
zshNy/MGz19qCkKxHh53L46g5pIOBvwFItIm4TFRfTLcDwIDAQABoyMwITAOBgNVHQ8BAf8EBAMC
AQYwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAgEAXzSBdu+WHdXltdkCY4QWwa6g
cFGn90xHNcgL1yg9iXHZqjNB6hQbbCEAwGxCGX6faVsgQt+i0trEfJdLjbDorMjupWkEmQqSpqsn
LhpNgb+E1HAerUf+/UqdM+DyucRFCCEK2mlpc3INvjT+lIutwx4116KD7+U4x6WFH6vPNOw/KP4M
8VeGTslV9xzU2KV9Bnpv1d8Q34FOIWWxtuEXeZVFBs5fzNxGiWNoRI2T9GRwoD2dKAXDOXC4Ynsg
/eTb6QihuJ49CcdP+yz4k3ZB3lLg4VfSnQO8d57+nile98FRYB/e2guyLXW3Q0iT5/Z5xoRdgFlg
lPx4mI88k1HtQJAH32RjJMtOcQWh15QaiDLxInQirqWm2BJpTGCjAu4r7NRjkgtevi92a6O2JryP
A9gK8kxkRr05YuWW6zRjESjMlfGt7+/cgFhI6Uu46mWs6fyAtbXIRfmswZ/ZuepiiI7E8UuDEq3m
i4TWnsLrgxifarsbJGAzcMzs9zLzXNl5fe+epP7JI8Mk7hWSsT2RTyaGvWZzJBPqpK5jwa19hAM8
EHiGG3njxPPyBJUgriOCxLM6AGK/5jYk4Ve6xx6QddVfP5VhK8E7zeWzaGHQRiapIVJpLesux+t3
zqY6tQMzT3bR51xUAV3LePTJDL/PEo4XLSNolOer/qmyKwbQBM0=
-----END CERTIFICATE-----

TeliaSonera Root CA v1
======================
-----BEGIN CERTIFICATE-----
MIIFODCCAyCgAwIBAgIRAJW+FqD3LkbxezmCcvqLzZYwDQYJKoZIhvcNAQEFBQAwNzEUMBIGA1UE
CgwLVGVsaWFTb25lcmExHzAdBgNVBAMMFlRlbGlhU29uZXJhIFJvb3QgQ0EgdjEwHhcNMDcxMDE4
MTIwMDUwWhcNMzIxMDE4MTIwMDUwWjA3MRQwEgYDVQQKDAtUZWxpYVNvbmVyYTEfMB0GA1UEAwwW
VGVsaWFTb25lcmEgUm9vdCBDQSB2MTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAMK+
6yfwIaPzaSZVfp3FVRaRXP3vIb9TgHot0pGMYzHw7CTww6XScnwQbfQ3t+XmfHnqjLWCi65ItqwA
3GV17CpNX8GH9SBlK4GoRz6JI5UwFpB/6FcHSOcZrr9FZ7E3GwYq/t75rH2D+1665I+XZ75Ljo1k
B1c4VWk0Nj0TSO9P4tNmHqTPGrdeNjPUtAa9GAH9d4RQAEX1jF3oI7x+/jXh7VB7qTCNGdMJjmhn
Xb88lxhTuylixcpecsHHltTbLaC0H2kD7OriUPEMPPCs81Mt8Bz17Ww5OXOAFshSsCPN4D7c3TxH
oLs1iuKYaIu+5b9y7tL6pe0S7fyYGKkmdtwoSxAgHNN/Fnct7W+A90m7UwW7XWjH1Mh1Fj+JWov3
F0fUTPHSiXk+TT2YqGHeOh7S+F4D4MHJHIzTjU3TlTazN19jY5szFPAtJmtTfImMMsJu7D0hADnJ
oWjiUIMusDor8zagrC/kb2HCUQk5PotTubtn2txTuXZZNp1D5SDgPTJghSJRt8czu90VL6R4pgd7
gUY2BIbdeTXHlSw7sKMXNeVzH7RcWe/a6hBle3rQf5+ztCo3O3CLm1u5K7fsslESl1MpWtTwEhDc
TwK7EpIvYtQ/aUN8Ddb8WHUBiJ1YFkveupD/RwGJBmr2X7KQarMCpgKIv7NHfirZ1fpoeDVNAgMB
AAGjPzA9MA8GA1UdEwEB/wQFMAMBAf8wCwYDVR0PBAQDAgEGMB0GA1UdDgQWBBTwj1k4ALP1j5qW
DNXr+nuqF+gTEjANBgkqhkiG9w0BAQUFAAOCAgEAvuRcYk4k9AwI//DTDGjkk0kiP0Qnb7tt3oNm
zqjMDfz1mgbldxSR651Be5kqhOX//CHBXfDkH1e3damhXwIm/9fH907eT/j3HEbAek9ALCI18Bmx
0GtnLLCo4MBANzX2hFxc469CeP6nyQ1Q6g2EdvZR74NTxnr/DlZJLo961gzmJ1TjTQpgcmLNkQfW
pb/ImWvtxBnmq0wROMVvMeJuScg/doAmAyYp4Db29iBT4xdwNBedY2gea+zDTYa4EzAvXUYNR0PV
G6pZDrlcjQZIrXSHX8f8MVRBE+LHIQ6e4B4N4cB7Q4WQxYpYxmUKeFfyxiMPAdkgS94P+5KFdSpc
c41teyWRyu5FrgZLAMzTsVlQ2jqIOylDRl6XK1TOU2+NSueW+r9xDkKLfP0ooNBIytrEgUy7onOT
JsjrDNYmiLbAJM+7vVvrdX3pCI6GMyx5dwlppYn8s3CQh3aP0yK7Qs69cwsgJirQmz1wHiRszYd2
qReWt88NkvuOGKmYSdGe/mBEciG5Ge3C9THxOUiIkCR1VBatzvT4aRRkOfujuLpwQMcnHL/EVlP6
Y2XQ8xwOFvVrhlhNGNTkDY6lnVuR3HYkUD/GKvvZt5y11ubQ2egZixVxSK236thZiNSQvxaz2ems
WWFUyBy6ysHK4bkgTI86k4mloMy/0/Z1pHWWbVY=
-----END CERTIFICATE-----

T-TeleSec GlobalRoot Class 2
============================
-----BEGIN CERTIFICATE-----
MIIDwzCCAqugAwIBAgIBATANBgkqhkiG9w0BAQsFADCBgjELMAkGA1UEBhMCREUxKzApBgNVBAoM
IlQtU3lzdGVtcyBFbnRlcnByaXNlIFNlcnZpY2VzIEdtYkgxHzAdBgNVBAsMFlQtU3lzdGVtcyBU
cnVzdCBDZW50ZXIxJTAjBgNVBAMMHFQtVGVsZVNlYyBHbG9iYWxSb290IENsYXNzIDIwHhcNMDgx
MDAxMTA0MDE0WhcNMzMxMDAxMjM1OTU5WjCBgjELMAkGA1UEBhMCREUxKzApBgNVBAoMIlQtU3lz
dGVtcyBFbnRlcnByaXNlIFNlcnZpY2VzIEdtYkgxHzAdBgNVBAsMFlQtU3lzdGVtcyBUcnVzdCBD
ZW50ZXIxJTAjBgNVBAMMHFQtVGVsZVNlYyBHbG9iYWxSb290IENsYXNzIDIwggEiMA0GCSqGSIb3
DQEBAQUAA4IBDwAwggEKAoIBAQCqX9obX+hzkeXaXPSi5kfl82hVYAUdAqSzm1nzHoqvNK38DcLZ
SBnuaY/JIPwhqgcZ7bBcrGXHX+0CfHt8LRvWurmAwhiCFoT6ZrAIxlQjgeTNuUk/9k9uN0goOA/F
vudocP05l03Sx5iRUKrERLMjfTlH6VJi1hKTXrcxlkIF+3anHqP1wvzpesVsqXFP6st4vGCvx970
2cu+fjOlbpSD8DT6IavqjnKgP6TeMFvvhk1qlVtDRKgQFRzlAVfFmPHmBiiRqiDFt1MmUUOyCxGV
WOHAD3bZwI18gfNycJ5v/hqO2V81xrJvNHy+SE/iWjnX2J14np+GPgNeGYtEotXHAgMBAAGjQjBA
MA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBS/WSA2AHmgoCJrjNXy
YdK4LMuCSjANBgkqhkiG9w0BAQsFAAOCAQEAMQOiYQsfdOhyNsZt+U2e+iKo4YFWz827n+qrkRk4
r6p8FU3ztqONpfSO9kSpp+ghla0+AGIWiPACuvxhI+YzmzB6azZie60EI4RYZeLbK4rnJVM3YlNf
vNoBYimipidx5joifsFvHZVwIEoHNN/q/xWA5brXethbdXwFeilHfkCoMRN3zUA7tFFHei4R40cR
3p1m0IvVVGb6g1XqfMIpiRvpb7PO4gWEyS8+eIVibslfwXhjdFjASBgMmTnrpMwatXlajRWc2BQN
9noHV8cigwUtPJslJj0Ys6lDfMjIq2SPDqO/nBudMNva0Bkuqjzx+zOAduTNrRlPBSeOE6Fuwg==
-----END CERTIFICATE-----

Atos TrustedRoot 2011
=====================
-----BEGIN CERTIFICATE-----
MIIDdzCCAl+gAwIBAgIIXDPLYixfszIwDQYJKoZIhvcNAQELBQAwPDEeMBwGA1UEAwwVQXRvcyBU
cnVzdGVkUm9vdCAyMDExMQ0wCwYDVQQKDARBdG9zMQswCQYDVQQGEwJERTAeFw0xMTA3MDcxNDU4
MzBaFw0zMDEyMzEyMzU5NTlaMDwxHjAcBgNVBAMMFUF0b3MgVHJ1c3RlZFJvb3QgMjAxMTENMAsG
A1UECgwEQXRvczELMAkGA1UEBhMCREUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCV
hTuXbyo7LjvPpvMpNb7PGKw+qtn4TaA+Gke5vJrf8v7MPkfoepbCJI419KkM/IL9bcFyYie96mvr
54rMVD6QUM+A1JX76LWC1BTFtqlVJVfbsVD2sGBkWXppzwO3bw2+yj5vdHLqqjAqc2K+SZFhyBH+
DgMq92og3AIVDV4VavzjgsG1xZ1kCWyjWZgHJ8cblithdHFsQ/H3NYkQ4J7sVaE3IqKHBAUsR320
HLliKWYoyrfhk/WklAOZuXCFteZI6o1Q/NnezG8HDt0Lcp2AMBYHlT8oDv3FdU9T1nSatCQujgKR
z3bFmx5VdJx4IbHwLfELn8LVlhgf8FQieowHAgMBAAGjfTB7MB0GA1UdDgQWBBSnpQaxLKYJYO7R
l+lwrrw7GWzbITAPBgNVHRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFKelBrEspglg7tGX6XCuvDsZ
bNshMBgGA1UdIAQRMA8wDQYLKwYBBAGwLQMEAQEwDgYDVR0PAQH/BAQDAgGGMA0GCSqGSIb3DQEB
CwUAA4IBAQAmdzTblEiGKkGdLD4GkGDEjKwLVLgfuXvTBznk+j57sj1O7Z8jvZfza1zv7v1Apt+h
k6EKhqzvINB5Ab149xnYJDE0BAGmuhWawyfc2E8PzBhj/5kPDpFrdRbhIfzYJsdHt6bPWHJxfrrh
TZVHO8mvbaG0weyJ9rQPOLXiZNwlz6bb65pcmaHFCN795trV1lpFDMS3wrUU77QR/w4VtfX128a9
61qn8FYiqTxlVMYVqL2Gns2Dlmh6cYGJ4Qvh6hEbaAjMaZ7snkGeRDImeuKHCnE96+RapNLbxc3G
3mB/ufNPRJLvKrcYPqcZ2Qt9sTdBQrC6YB3y/gkRsPCHe6ed
-----END CERTIFICATE-----

QuoVadis Root CA 1 G3
=====================
-----BEGIN CERTIFICATE-----
MIIFYDCCA0igAwIBAgIUeFhfLq0sGUvjNwc1NBMotZbUZZMwDQYJKoZIhvcNAQELBQAwSDELMAkG
A1UEBhMCQk0xGTAXBgNVBAoTEFF1b1ZhZGlzIExpbWl0ZWQxHjAcBgNVBAMTFVF1b1ZhZGlzIFJv
b3QgQ0EgMSBHMzAeFw0xMjAxMTIxNzI3NDRaFw00MjAxMTIxNzI3NDRaMEgxCzAJBgNVBAYTAkJN
MRkwFwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMR4wHAYDVQQDExVRdW9WYWRpcyBSb290IENBIDEg
RzMwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCgvlAQjunybEC0BJyFuTHK3C3kEakE
PBtVwedYMB0ktMPvhd6MLOHBPd+C5k+tR4ds7FtJwUrVu4/sh6x/gpqG7D0DmVIB0jWerNrwU8lm
PNSsAgHaJNM7qAJGr6Qc4/hzWHa39g6QDbXwz8z6+cZM5cOGMAqNF34168Xfuw6cwI2H44g4hWf6
Pser4BOcBRiYz5P1sZK0/CPTz9XEJ0ngnjybCKOLXSoh4Pw5qlPafX7PGglTvF0FBM+hSo+LdoIN
ofjSxxR3W5A2B4GbPgb6Ul5jxaYA/qXpUhtStZI5cgMJYr2wYBZupt0lwgNm3fME0UDiTouG9G/l
g6AnhF4EwfWQvTA9xO+oabw4m6SkltFi2mnAAZauy8RRNOoMqv8hjlmPSlzkYZqn0ukqeI1RPToV
7qJZjqlc3sX5kCLliEVx3ZGZbHqfPT2YfF72vhZooF6uCyP8Wg+qInYtyaEQHeTTRCOQiJ/GKubX
9ZqzWB4vMIkIG1SitZgj7Ah3HJVdYdHLiZxfokqRmu8hqkkWCKi9YSgxyXSthfbZxbGL0eUQMk1f
iyA6PEkfM4VZDdvLCXVDaXP7a3F98N/ETH3Goy7IlXnLc6KOTk0k+17kBL5yG6YnLUlamXrXXAkg
t3+UuU/xDRxeiEIbEbfnkduebPRq34wGmAOtzCjvpUfzUwIDAQABo0IwQDAPBgNVHRMBAf8EBTAD
AQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUo5fW816iEOGrRZ88F2Q87gFwnMwwDQYJKoZI
hvcNAQELBQADggIBABj6W3X8PnrHX3fHyt/PX8MSxEBd1DKquGrX1RUVRpgjpeaQWxiZTOOtQqOC
MTaIzen7xASWSIsBx40Bz1szBpZGZnQdT+3Btrm0DWHMY37XLneMlhwqI2hrhVd2cDMT/uFPpiN3
GPoajOi9ZcnPP/TJF9zrx7zABC4tRi9pZsMbj/7sPtPKlL92CiUNqXsCHKnQO18LwIE6PWThv6ct
Tr1NxNgpxiIY0MWscgKCP6o6ojoilzHdCGPDdRS5YCgtW2jgFqlmgiNR9etT2DGbe+m3nUvriBbP
+V04ikkwj+3x6xn0dxoxGE1nVGwvb2X52z3sIexe9PSLymBlVNFxZPT5pqOBMzYzcfCkeF9OrYMh
3jRJjehZrJ3ydlo28hP0r+AJx2EqbPfgna67hkooby7utHnNkDPDs3b69fBsnQGQ+p6Q9pxyz0fa
wx/kNSBT8lTR32GDpgLiJTjehTItXnOQUl1CxM49S+H5GYQd1aJQzEH7QRTDvdbJWqNjZgKAvQU6
O0ec7AAmTPWIUb+oI38YB7AL7YsmoWTTYUrrXJ/es69nA7Mf3W1daWhpq1467HxpvMc7hU6eFbm0
FU/DlXpY18ls6Wy58yljXrQs8C097Vpl4KlbQMJImYFtnh8GKjwStIsPm6Ik8KaN1nrgS7ZklmOV
hMJKzRwuJIczYOXD
-----END CERTIFICATE-----

QuoVadis Root CA 2 G3
=====================
-----BEGIN CERTIFICATE-----
MIIFYDCCA0igAwIBAgIURFc0JFuBiZs18s64KztbpybwdSgwDQYJKoZIhvcNAQELBQAwSDELMAkG
A1UEBhMCQk0xGTAXBgNVBAoTEFF1b1ZhZGlzIExpbWl0ZWQxHjAcBgNVBAMTFVF1b1ZhZGlzIFJv
b3QgQ0EgMiBHMzAeFw0xMjAxMTIxODU5MzJaFw00MjAxMTIxODU5MzJaMEgxCzAJBgNVBAYTAkJN
MRkwFwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMR4wHAYDVQQDExVRdW9WYWRpcyBSb290IENBIDIg
RzMwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQChriWyARjcV4g/Ruv5r+LrI3HimtFh
ZiFfqq8nUeVuGxbULX1QsFN3vXg6YOJkApt8hpvWGo6t/x8Vf9WVHhLL5hSEBMHfNrMWn4rjyduY
NM7YMxcoRvynyfDStNVNCXJJ+fKH46nafaF9a7I6JaltUkSs+L5u+9ymc5GQYaYDFCDy54ejiK2t
oIz/pgslUiXnFgHVy7g1gQyjO/Dh4fxaXc6AcW34Sas+O7q414AB+6XrW7PFXmAqMaCvN+ggOp+o
MiwMzAkd056OXbxMmO7FGmh77FOm6RQ1o9/NgJ8MSPsc9PG/Srj61YxxSscfrf5BmrODXfKEVu+l
V0POKa2Mq1W/xPtbAd0jIaFYAI7D0GoT7RPjEiuA3GfmlbLNHiJuKvhB1PLKFAeNilUSxmn1uIZo
L1NesNKqIcGY5jDjZ1XHm26sGahVpkUG0CM62+tlXSoREfA7T8pt9DTEceT/AFr2XK4jYIVz8eQQ
sSWu1ZK7E8EM4DnatDlXtas1qnIhO4M15zHfeiFuuDIIfR0ykRVKYnLP43ehvNURG3YBZwjgQQvD
6xVu+KQZ2aKrr+InUlYrAoosFCT5v0ICvybIxo/gbjh9Uy3l7ZizlWNof/k19N+IxWA1ksB8aRxh
lRbQ694Lrz4EEEVlWFA4r0jyWbYW8jwNkALGcC4BrTwV1wIDAQABo0IwQDAPBgNVHRMBAf8EBTAD
AQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQU7edvdlq/YOxJW8ald7tyFnGbxD0wDQYJKoZI
hvcNAQELBQADggIBAJHfgD9DCX5xwvfrs4iP4VGyvD11+ShdyLyZm3tdquXK4Qr36LLTn91nMX66
AarHakE7kNQIXLJgapDwyM4DYvmL7ftuKtwGTTwpD4kWilhMSA/ohGHqPHKmd+RCroijQ1h5fq7K
pVMNqT1wvSAZYaRsOPxDMuHBR//47PERIjKWnML2W2mWeyAMQ0GaW/ZZGYjeVYg3UQt4XAoeo0L9
x52ID8DyeAIkVJOviYeIyUqAHerQbj5hLja7NQ4nlv1mNDthcnPxFlxHBlRJAHpYErAK74X9sbgz
dWqTHBLmYF5vHX/JHyPLhGGfHoJE+V+tYlUkmlKY7VHnoX6XOuYvHxHaU4AshZ6rNRDbIl9qxV6X
U/IyAgkwo1jwDQHVcsaxfGl7w/U2Rcxhbl5MlMVerugOXou/983g7aEOGzPuVBj+D77vfoRrQ+Nw
mNtddbINWQeFFSM51vHfqSYP1kjHs6Yi9TM3WpVHn3u6GBVv/9YUZINJ0gpnIdsPNWNgKCLjsZWD
zYWm3S8P52dSbrsvhXz1SnPnxT7AvSESBT/8twNJAlvIJebiVDj1eYeMHVOyToV7BjjHLPj4sHKN
JeV3UvQDHEimUF+IIDBu8oJDqz2XhOdT+yHBTw8imoa4WSr2Rz0ZiC3oheGe7IUIarFsNMkd7Egr
O3jtZsSOeWmD3n+M
-----END CERTIFICATE-----

QuoVadis Root CA 3 G3
=====================
-----BEGIN CERTIFICATE-----
MIIFYDCCA0igAwIBAgIULvWbAiin23r/1aOp7r0DoM8Sah0wDQYJKoZIhvcNAQELBQAwSDELMAkG
A1UEBhMCQk0xGTAXBgNVBAoTEFF1b1ZhZGlzIExpbWl0ZWQxHjAcBgNVBAMTFVF1b1ZhZGlzIFJv
b3QgQ0EgMyBHMzAeFw0xMjAxMTIyMDI2MzJaFw00MjAxMTIyMDI2MzJaMEgxCzAJBgNVBAYTAkJN
MRkwFwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMR4wHAYDVQQDExVRdW9WYWRpcyBSb290IENBIDMg
RzMwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCzyw4QZ47qFJenMioKVjZ/aEzHs286
IxSR/xl/pcqs7rN2nXrpixurazHb+gtTTK/FpRp5PIpM/6zfJd5O2YIyC0TeytuMrKNuFoM7pmRL
Mon7FhY4futD4tN0SsJiCnMK3UmzV9KwCoWdcTzeo8vAMvMBOSBDGzXRU7Ox7sWTaYI+FrUoRqHe
6okJ7UO4BUaKhvVZR74bbwEhELn9qdIoyhA5CcoTNs+cra1AdHkrAj80//ogaX3T7mH1urPnMNA3
I4ZyYUUpSFlob3emLoG+B01vr87ERRORFHAGjx+f+IdpsQ7vw4kZ6+ocYfx6bIrc1gMLnia6Et3U
VDmrJqMz6nWB2i3ND0/kA9HvFZcba5DFApCTZgIhsUfei5pKgLlVj7WiL8DWM2fafsSntARE60f7
5li59wzweyuxwHApw0BiLTtIadwjPEjrewl5qW3aqDCYz4ByA4imW0aucnl8CAMhZa634RylsSqi
Md5mBPfAdOhx3v89WcyWJhKLhZVXGqtrdQtEPREoPHtht+KPZ0/l7DxMYIBpVzgeAVuNVejH38DM
dyM0SXV89pgR6y3e7UEuFAUCf+D+IOs15xGsIs5XPd7JMG0QA4XN8f+MFrXBsj6IbGB/kE+V9/Yt
rQE5BwT6dYB9v0lQ7e/JxHwc64B+27bQ3RP+ydOc17KXqQIDAQABo0IwQDAPBgNVHRMBAf8EBTAD
AQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUxhfQvKjqAkPyGwaZXSuQILnXnOQwDQYJKoZI
hvcNAQELBQADggIBADRh2Va1EodVTd2jNTFGu6QHcrxfYWLopfsLN7E8trP6KZ1/AvWkyaiTt3px
KGmPc+FSkNrVvjrlt3ZqVoAh313m6Tqe5T72omnHKgqwGEfcIHB9UqM+WXzBusnIFUBhynLWcKzS
t/Ac5IYp8M7vaGPQtSCKFWGafoaYtMnCdvvMujAWzKNhxnQT5WvvoxXqA/4Ti2Tk08HS6IT7SdEQ
TXlm66r99I0xHnAUrdzeZxNMgRVhvLfZkXdxGYFgu/BYpbWcC/ePIlUnwEsBbTuZDdQdm2NnL9Du
DcpmvJRPpq3t/O5jrFc/ZSXPsoaP0Aj/uHYUbt7lJ+yreLVTubY/6CD50qi+YUbKh4yE8/nxoGib
Ih6BJpsQBJFxwAYf3KDTuVan45gtf4Od34wrnDKOMpTwATwiKp9Dwi7DmDkHOHv8XgBCH/MyJnmD
hPbl8MFREsALHgQjDFSlTC9JxUrRtm5gDWv8a4uFJGS3iQ6rJUdbPM9+Sb3H6QrG2vd+DhcI00iX
0HGS8A85PjRqHH3Y8iKuu2n0M7SmSFXRDw4m6Oy2Cy2nhTXN/VnIn9HNPlopNLk9hM6xZdRZkZFW
dSHBd575euFgndOtBBj0fOtek49TSiIp+EgrPk2GrFt/ywaZWWDYWGWVjUTR939+J399roD1B0y2
PpxxVJkES/1Y+Zj0
-----END CERTIFICATE-----

DigiCert Assured ID Root G2
===========================
-----BEGIN CERTIFICATE-----
MIIDljCCAn6gAwIBAgIQC5McOtY5Z+pnI7/Dr5r0SzANBgkqhkiG9w0BAQsFADBlMQswCQYDVQQG
EwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSQw
IgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgRzIwHhcNMTMwODAxMTIwMDAwWhcNMzgw
MTE1MTIwMDAwWjBlMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQL
ExB3d3cuZGlnaWNlcnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgRzIw
ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDZ5ygvUj82ckmIkzTz+GoeMVSAn61UQbVH
35ao1K+ALbkKz3X9iaV9JPrjIgwrvJUXCzO/GU1BBpAAvQxNEP4HteccbiJVMWWXvdMX0h5i89vq
bFCMP4QMls+3ywPgym2hFEwbid3tALBSfK+RbLE4E9HpEgjAALAcKxHad3A2m67OeYfcgnDmCXRw
VWmvo2ifv922ebPynXApVfSr/5Vh88lAbx3RvpO704gqu52/clpWcTs/1PPRCv4o76Pu2ZmvA9OP
YLfykqGxvYmJHzDNw6YuYjOuFgJ3RFrngQo8p0Quebg/BLxcoIfhG69Rjs3sLPr4/m3wOnyqi+Rn
lTGNAgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgGGMB0GA1UdDgQWBBTO
w0q5mVXyuNtgv6l+vVa1lzan1jANBgkqhkiG9w0BAQsFAAOCAQEAyqVVjOPIQW5pJ6d1Ee88hjZv
0p3GeDgdaZaikmkuOGybfQTUiaWxMTeKySHMq2zNixya1r9I0jJmwYrA8y8678Dj1JGG0VDjA9tz
d29KOVPt3ibHtX2vK0LRdWLjSisCx1BL4GnilmwORGYQRI+tBev4eaymG+g3NJ1TyWGqolKvSnAW
hsI6yLETcDbYz+70CjTVW0z9B5yiutkBclzzTcHdDrEcDcRjvq30FPuJ7KJBDkzMyFdA0G4Dqs0M
jomZmWzwPDCvON9vvKO+KSAnq3T/EyJ43pdSVR6DtVQgA+6uwE9W3jfMw3+qBCe703e4YtsXfJwo
IhNzbM8m9Yop5w==
-----END CERTIFICATE-----

DigiCert Assured ID Root G3
===========================
-----BEGIN CERTIFICATE-----
MIICRjCCAc2gAwIBAgIQC6Fa+h3foLVJRK/NJKBs7DAKBggqhkjOPQQDAzBlMQswCQYDVQQGEwJV
UzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSQwIgYD
VQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgRzMwHhcNMTMwODAxMTIwMDAwWhcNMzgwMTE1
MTIwMDAwWjBlMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
d3cuZGlnaWNlcnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgRzMwdjAQ
BgcqhkjOPQIBBgUrgQQAIgNiAAQZ57ysRGXtzbg/WPuNsVepRC0FFfLvC/8QdJ+1YlJfZn4f5dwb
RXkLzMZTCp2NXQLZqVneAlr2lSoOjThKiknGvMYDOAdfVdp+CW7if17QRSAPWXYQ1qAk8C3eNvJs
KTmjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgGGMB0GA1UdDgQWBBTL0L2p4ZgF
UaFNN6KDec6NHSrkhDAKBggqhkjOPQQDAwNnADBkAjAlpIFFAmsSS3V0T8gj43DydXLefInwz5Fy
YZ5eEJJZVrmDxxDnOOlYJjZ91eQ0hjkCMHw2U/Aw5WJjOpnitqM7mzT6HtoQknFekROn3aRukswy
1vUhZscv6pZjamVFkpUBtA==
-----END CERTIFICATE-----

DigiCert Global Root G2
=======================
-----BEGIN CERTIFICATE-----
MIIDjjCCAnagAwIBAgIQAzrx5qcRqaC7KGSxHQn65TANBgkqhkiG9w0BAQsFADBhMQswCQYDVQQG
EwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSAw
HgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBHMjAeFw0xMzA4MDExMjAwMDBaFw0zODAxMTUx
MjAwMDBaMGExCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3
dy5kaWdpY2VydC5jb20xIDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IEcyMIIBIjANBgkq
hkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAuzfNNNx7a8myaJCtSnX/RrohCgiN9RlUyfuI2/Ou8jqJ
kTx65qsGGmvPrC3oXgkkRLpimn7Wo6h+4FR1IAWsULecYxpsMNzaHxmx1x7e/dfgy5SDN67sH0NO
3Xss0r0upS/kqbitOtSZpLYl6ZtrAGCSYP9PIUkY92eQq2EGnI/yuum06ZIya7XzV+hdG82MHauV
BJVJ8zUtluNJbd134/tJS7SsVQepj5WztCO7TG1F8PapspUwtP1MVYwnSlcUfIKdzXOS0xZKBgyM
UNGPHgm+F6HmIcr9g+UQvIOlCsRnKPZzFBQ9RnbDhxSJITRNrw9FDKZJobq7nMWxM4MphQIDAQAB
o0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBhjAdBgNVHQ4EFgQUTiJUIBiV5uNu
5g/6+rkS7QYXjzkwDQYJKoZIhvcNAQELBQADggEBAGBnKJRvDkhj6zHd6mcY1Yl9PMWLSn/pvtsr
F9+wX3N3KjITOYFnQoQj8kVnNeyIv/iPsGEMNKSuIEyExtv4NeF22d+mQrvHRAiGfzZ0JFrabA0U
WTW98kndth/Jsw1HKj2ZL7tcu7XUIOGZX1NGFdtom/DzMNU+MeKNhJ7jitralj41E6Vf8PlwUHBH
QRFXGU7Aj64GxJUTFy8bJZ918rGOmaFvE7FBcf6IKshPECBV1/MUReXgRPTqh5Uykw7+U0b6LJ3/
iyK5S9kJRaTepLiaWN0bfVKfjllDiIGknibVb63dDcY3fe0Dkhvld1927jyNxF1WW6LZZm6zNTfl
MrY=
-----END CERTIFICATE-----

DigiCert Global Root G3
=======================
-----BEGIN CERTIFICATE-----
MIICPzCCAcWgAwIBAgIQBVVWvPJepDU1w6QP1atFcjAKBggqhkjOPQQDAzBhMQswCQYDVQQGEwJV
UzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSAwHgYD
VQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBHMzAeFw0xMzA4MDExMjAwMDBaFw0zODAxMTUxMjAw
MDBaMGExCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5k
aWdpY2VydC5jb20xIDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IEczMHYwEAYHKoZIzj0C
AQYFK4EEACIDYgAE3afZu4q4C/sLfyHS8L6+c/MzXRq8NOrexpu80JX28MzQC7phW1FGfp4tn+6O
YwwX7Adw9c+ELkCDnOg/QW07rdOkFFk2eJ0DQ+4QE2xy3q6Ip6FrtUPOZ9wj/wMco+I+o0IwQDAP
BgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBhjAdBgNVHQ4EFgQUs9tIpPmhxdiuNkHMEWNp
Yim8S8YwCgYIKoZIzj0EAwMDaAAwZQIxAK288mw/EkrRLTnDCgmXc/SINoyIJ7vmiI1Qhadj+Z4y
3maTD/HMsQmP3Wyr+mt/oAIwOWZbwmSNuJ5Q3KjVSaLtx9zRSX8XAbjIho9OjIgrqJqpisXRAL34
VOKa5Vt8sycX
-----END CERTIFICATE-----

DigiCert Trusted Root G4
========================
-----BEGIN CERTIFICATE-----
MIIFkDCCA3igAwIBAgIQBZsbV56OITLiOQe9p3d1XDANBgkqhkiG9w0BAQwFADBiMQswCQYDVQQG
EwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSEw
HwYDVQQDExhEaWdpQ2VydCBUcnVzdGVkIFJvb3QgRzQwHhcNMTMwODAxMTIwMDAwWhcNMzgwMTE1
MTIwMDAwWjBiMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
d3cuZGlnaWNlcnQuY29tMSEwHwYDVQQDExhEaWdpQ2VydCBUcnVzdGVkIFJvb3QgRzQwggIiMA0G
CSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC/5pBzaN675F1KPDAiMGkz7MKnJS7JIT3yithZwuEp
pz1Yq3aaza57G4QNxDAf8xukOBbrVsaXbR2rsnnyyhHS5F/WBTxSD1Ifxp4VpX6+n6lXFllVcq9o
k3DCsrp1mWpzMpTREEQQLt+C8weE5nQ7bXHiLQwb7iDVySAdYyktzuxeTsiT+CFhmzTrBcZe7Fsa
vOvJz82sNEBfsXpm7nfISKhmV1efVFiODCu3T6cw2Vbuyntd463JT17lNecxy9qTXtyOj4DatpGY
QJB5w3jHtrHEtWoYOAMQjdjUN6QuBX2I9YI+EJFwq1WCQTLX2wRzKm6RAXwhTNS8rhsDdV14Ztk6
MUSaM0C/CNdaSaTC5qmgZ92kJ7yhTzm1EVgX9yRcRo9k98FpiHaYdj1ZXUJ2h4mXaXpI8OCiEhtm
mnTK3kse5w5jrubU75KSOp493ADkRSWJtppEGSt+wJS00mFt6zPZxd9LBADMfRyVw4/3IbKyEbe7
f/LVjHAsQWCqsWMYRJUadmJ+9oCw++hkpjPRiQfhvbfmQ6QYuKZ3AeEPlAwhHbJUKSWJbOUOUlFH
dL4mrLZBdd56rF+NP8m800ERElvlEFDrMcXKchYiCd98THU/Y+whX8QgUWtvsauGi0/C1kVfnSD8
oR7FwI+isX4KJpn15GkvmB0t9dmpsh3lGwIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1Ud
DwEB/wQEAwIBhjAdBgNVHQ4EFgQU7NfjgtJxXWRM3y5nP+e6mK4cD08wDQYJKoZIhvcNAQEMBQAD
ggIBALth2X2pbL4XxJEbw6GiAI3jZGgPVs93rnD5/ZpKmbnJeFwMDF/k5hQpVgs2SV1EY+CtnJYY
ZhsjDT156W1r1lT40jzBQ0CuHVD1UvyQO7uYmWlrx8GnqGikJ9yd+SeuMIW59mdNOj6PWTkiU0Tr
yF0Dyu1Qen1iIQqAyHNm0aAFYF/opbSnr6j3bTWcfFqK1qI4mfN4i/RN0iAL3gTujJtHgXINwBQy
7zBZLq7gcfJW5GqXb5JQbZaNaHqasjYUegbyJLkJEVDXCLG4iXqEI2FCKeWjzaIgQdfRnGTZ6iah
ixTXTBmyUEFxPT9NcCOGDErcgdLMMpSEDQgJlxxPwO5rIHQw0uA5NBCFIRUBCOhVMt5xSdkoF1BN
5r5N0XWs0Mr7QbhDparTwwVETyw2m+L64kW4I1NsBm9nVX9GtUw/bihaeSbSpKhil9Ie4u1Ki7wb
/UdKDd9nZn6yW0HQO+T0O/QEY+nvwlQAUaCKKsnOeMzV6ocEGLPOr0mIr/OSmbaz5mEP0oUA51Aa
5BuVnRmhuZyxm7EAHu/QD09CbMkKvO5D+jpxpchNJqU1/YldvIViHTLSoCtU7ZpXwdv6EM8Zt4tK
G48BtieVU+i2iW1bvGjUI+iLUaJW+fCmgKDWHrO8Dw9TdSmq6hN35N6MgSGtBxBHEa2HPQfRdbzP
82Z+
-----END CERTIFICATE-----

COMODO RSA Certification Authority
==================================
-----BEGIN CERTIFICATE-----
MIIF2DCCA8CgAwIBAgIQTKr5yttjb+Af907YWwOGnTANBgkqhkiG9w0BAQwFADCBhTELMAkGA1UE
BhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEaMBgG
A1UEChMRQ09NT0RPIENBIExpbWl0ZWQxKzApBgNVBAMTIkNPTU9ETyBSU0EgQ2VydGlmaWNhdGlv
biBBdXRob3JpdHkwHhcNMTAwMTE5MDAwMDAwWhcNMzgwMTE4MjM1OTU5WjCBhTELMAkGA1UEBhMC
R0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEaMBgGA1UE
ChMRQ09NT0RPIENBIExpbWl0ZWQxKzApBgNVBAMTIkNPTU9ETyBSU0EgQ2VydGlmaWNhdGlvbiBB
dXRob3JpdHkwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCR6FSS0gpWsawNJN3Fz0Rn
dJkrN6N9I3AAcbxT38T6KhKPS38QVr2fcHK3YX/JSw8Xpz3jsARh7v8Rl8f0hj4K+j5c+ZPmNHrZ
FGvnnLOFoIJ6dq9xkNfs/Q36nGz637CC9BR++b7Epi9Pf5l/tfxnQ3K9DADWietrLNPtj5gcFKt+
5eNu/Nio5JIk2kNrYrhV/erBvGy2i/MOjZrkm2xpmfh4SDBF1a3hDTxFYPwyllEnvGfDyi62a+pG
x8cgoLEfZd5ICLqkTqnyg0Y3hOvozIFIQ2dOciqbXL1MGyiKXCJ7tKuY2e7gUYPDCUZObT6Z+pUX
2nwzV0E8jVHtC7ZcryxjGt9XyD+86V3Em69FmeKjWiS0uqlWPc9vqv9JWL7wqP/0uK3pN/u6uPQL
OvnoQ0IeidiEyxPx2bvhiWC4jChWrBQdnArncevPDt09qZahSL0896+1DSJMwBGB7FY79tOi4lu3
sgQiUpWAk2nojkxl8ZEDLXB0AuqLZxUpaVICu9ffUGpVRr+goyhhf3DQw6KqLCGqR84onAZFdr+C
GCe01a60y1Dma/RMhnEw6abfFobg2P9A3fvQQoh/ozM6LlweQRGBY84YcWsr7KaKtzFcOmpH4MN5
WdYgGq/yapiqcrxXStJLnbsQ/LBMQeXtHT1eKJ2czL+zUdqnR+WEUwIDAQABo0IwQDAdBgNVHQ4E
FgQUu69+Aj36pvE8hI6t7jiY7NkyMtQwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8w
DQYJKoZIhvcNAQEMBQADggIBAArx1UaEt65Ru2yyTUEUAJNMnMvlwFTPoCWOAvn9sKIN9SCYPBMt
rFaisNZ+EZLpLrqeLppysb0ZRGxhNaKatBYSaVqM4dc+pBroLwP0rmEdEBsqpIt6xf4FpuHA1sj+
nq6PK7o9mfjYcwlYRm6mnPTXJ9OV2jeDchzTc+CiR5kDOF3VSXkAKRzH7JsgHAckaVd4sjn8OoSg
tZx8jb8uk2IntznaFxiuvTwJaP+EmzzV1gsD41eeFPfR60/IvYcjt7ZJQ3mFXLrrkguhxuhoqEwW
sRqZCuhTLJK7oQkYdQxlqHvLI7cawiiFwxv/0Cti76R7CZGYZ4wUAc1oBmpjIXUDgIiKboHGhfKp
pC3n9KUkEEeDys30jXlYsQab5xoq2Z0B15R97QNKyvDb6KkBPvVWmckejkk9u+UJueBPSZI9FoJA
zMxZxuY67RIuaTxslbH9qh17f4a+Hg4yRvv7E491f0yLS0Zj/gA0QHDBw7mh3aZw4gSzQbzpgJHq
ZJx64SIDqZxubw5lT2yHh17zbqD5daWbQOhTsiedSrnAdyGN/4fy3ryM7xfft0kL0fJuMAsaDk52
7RH89elWsn2/x20Kk4yl0MC2Hb46TpSi125sC8KKfPog88Tk5c0NqMuRkrF8hey1FGlmDoLnzc7I
LaZRfyHBNVOFBkpdn627G190
-----END CERTIFICATE-----

USERTrust RSA Certification Authority
=====================================
-----BEGIN CERTIFICATE-----
MIIF3jCCA8agAwIBAgIQAf1tMPyjylGoG7xkDjUDLTANBgkqhkiG9w0BAQwFADCBiDELMAkGA1UE
BhMCVVMxEzARBgNVBAgTCk5ldyBKZXJzZXkxFDASBgNVBAcTC0plcnNleSBDaXR5MR4wHAYDVQQK
ExVUaGUgVVNFUlRSVVNUIE5ldHdvcmsxLjAsBgNVBAMTJVVTRVJUcnVzdCBSU0EgQ2VydGlmaWNh
dGlvbiBBdXRob3JpdHkwHhcNMTAwMjAxMDAwMDAwWhcNMzgwMTE4MjM1OTU5WjCBiDELMAkGA1UE
BhMCVVMxEzARBgNVBAgTCk5ldyBKZXJzZXkxFDASBgNVBAcTC0plcnNleSBDaXR5MR4wHAYDVQQK
ExVUaGUgVVNFUlRSVVNUIE5ldHdvcmsxLjAsBgNVBAMTJVVTRVJUcnVzdCBSU0EgQ2VydGlmaWNh
dGlvbiBBdXRob3JpdHkwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCAEmUXNg7D2wiz
0KxXDXbtzSfTTK1Qg2HiqiBNCS1kCdzOiZ/MPans9s/B3PHTsdZ7NygRK0faOca8Ohm0X6a9fZ2j
Y0K2dvKpOyuR+OJv0OwWIJAJPuLodMkYtJHUYmTbf6MG8YgYapAiPLz+E/CHFHv25B+O1ORRxhFn
RghRy4YUVD+8M/5+bJz/Fp0YvVGONaanZshyZ9shZrHUm3gDwFA66Mzw3LyeTP6vBZY1H1dat//O
+T23LLb2VN3I5xI6Ta5MirdcmrS3ID3KfyI0rn47aGYBROcBTkZTmzNg95S+UzeQc0PzMsNT79uq
/nROacdrjGCT3sTHDN/hMq7MkztReJVni+49Vv4M0GkPGw/zJSZrM233bkf6c0Plfg6lZrEpfDKE
Y1WJxA3Bk1QwGROs0303p+tdOmw1XNtB1xLaqUkL39iAigmTYo61Zs8liM2EuLE/pDkP2QKe6xJM
lXzzawWpXhaDzLhn4ugTncxbgtNMs+1b/97lc6wjOy0AvzVVdAlJ2ElYGn+SNuZRkg7zJn0cTRe8
yexDJtC/QV9AqURE9JnnV4eeUB9XVKg+/XRjL7FQZQnmWEIuQxpMtPAlR1n6BB6T1CZGSlCBst6+
eLf8ZxXhyVeEHg9j1uliutZfVS7qXMYoCAQlObgOK6nyTJccBz8NUvXt7y+CDwIDAQABo0IwQDAd
BgNVHQ4EFgQUU3m/WqorSs9UgOHYm8Cd8rIDZsswDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQF
MAMBAf8wDQYJKoZIhvcNAQEMBQADggIBAFzUfA3P9wF9QZllDHPFUp/L+M+ZBn8b2kMVn54CVVeW
FPFSPCeHlCjtHzoBN6J2/FNQwISbxmtOuowhT6KOVWKR82kV2LyI48SqC/3vqOlLVSoGIG1VeCkZ
7l8wXEskEVX/JJpuXior7gtNn3/3ATiUFJVDBwn7YKnuHKsSjKCaXqeYalltiz8I+8jRRa8YFWSQ
Eg9zKC7F4iRO/Fjs8PRF/iKz6y+O0tlFYQXBl2+odnKPi4w2r78NBc5xjeambx9spnFixdjQg3IM
8WcRiQycE0xyNN+81XHfqnHd4blsjDwSXWXavVcStkNr/+XeTWYRUc+ZruwXtuhxkYzeSf7dNXGi
FSeUHM9h4ya7b6NnJSFd5t0dCy5oGzuCr+yDZ4XUmFF0sbmZgIn/f3gZXHlKYC6SQK5MNyosycdi
yA5d9zZbyuAlJQG03RoHnHcAP9Dc1ew91Pq7P8yF1m9/qS3fuQL39ZeatTXaw2ewh0qpKJ4jjv9c
J2vhsE/zB+4ALtRZh8tSQZXq9EfX7mRBVXyNWQKV3WKdwrnuWih0hKWbt5DHDAff9Yk2dDLWKMGw
sAvgnEzDHNb842m1R0aBL6KCq9NjRHDEjf8tM7qtj3u1cIiuPhnPQCjY/MiQu12ZIvVS5ljFH4gx
Q+6IHdfGjjxDah2nGN59PRbxYvnKkKj9
-----END CERTIFICATE-----

USERTrust ECC Certification Authority
=====================================
-----BEGIN CERTIFICATE-----
MIICjzCCAhWgAwIBAgIQXIuZxVqUxdJxVt7NiYDMJjAKBggqhkjOPQQDAzCBiDELMAkGA1UEBhMC
VVMxEzARBgNVBAgTCk5ldyBKZXJzZXkxFDASBgNVBAcTC0plcnNleSBDaXR5MR4wHAYDVQQKExVU
aGUgVVNFUlRSVVNUIE5ldHdvcmsxLjAsBgNVBAMTJVVTRVJUcnVzdCBFQ0MgQ2VydGlmaWNhdGlv
biBBdXRob3JpdHkwHhcNMTAwMjAxMDAwMDAwWhcNMzgwMTE4MjM1OTU5WjCBiDELMAkGA1UEBhMC
VVMxEzARBgNVBAgTCk5ldyBKZXJzZXkxFDASBgNVBAcTC0plcnNleSBDaXR5MR4wHAYDVQQKExVU
aGUgVVNFUlRSVVNUIE5ldHdvcmsxLjAsBgNVBAMTJVVTRVJUcnVzdCBFQ0MgQ2VydGlmaWNhdGlv
biBBdXRob3JpdHkwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAAQarFRaqfloI+d61SRvU8Za2EurxtW2
0eZzca7dnNYMYf3boIkDuAUU7FfO7l0/4iGzzvfUinngo4N+LZfQYcTxmdwlkWOrfzCjtHDix6Ez
nPO/LlxTsV+zfTJ/ijTjeXmjQjBAMB0GA1UdDgQWBBQ64QmG1M8ZwpZ2dEl23OA1xmNjmjAOBgNV
HQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAKBggqhkjOPQQDAwNoADBlAjA2Z6EWCNzklwBB
HU6+4WMBzzuqQhFkoJ2UOQIReVx7Hfpkue4WQrO/isIJxOzksU0CMQDpKmFHjFJKS04YcPbWRNZu
9YO6bVi9JNlWSOrvxKJGgYhqOkbRqZtNyWHa0V1Xahg=
-----END CERTIFICATE-----

GlobalSign ECC Root CA - R5
===========================
-----BEGIN CERTIFICATE-----
MIICHjCCAaSgAwIBAgIRYFlJ4CYuu1X5CneKcflK2GwwCgYIKoZIzj0EAwMwUDEkMCIGA1UECxMb
R2xvYmFsU2lnbiBFQ0MgUm9vdCBDQSAtIFI1MRMwEQYDVQQKEwpHbG9iYWxTaWduMRMwEQYDVQQD
EwpHbG9iYWxTaWduMB4XDTEyMTExMzAwMDAwMFoXDTM4MDExOTAzMTQwN1owUDEkMCIGA1UECxMb
R2xvYmFsU2lnbiBFQ0MgUm9vdCBDQSAtIFI1MRMwEQYDVQQKEwpHbG9iYWxTaWduMRMwEQYDVQQD
EwpHbG9iYWxTaWduMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAER0UOlvt9Xb/pOdEh+J8LttV7HpI6
SFkc8GIxLcB6KP4ap1yztsyX50XUWPrRd21DosCHZTQKH3rd6zwzocWdTaRvQZU4f8kehOvRnkmS
h5SHDDqFSmafnVmTTZdhBoZKo0IwQDAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAd
BgNVHQ4EFgQUPeYpSJvqB8ohREom3m7e0oPQn1kwCgYIKoZIzj0EAwMDaAAwZQIxAOVpEslu28Yx
uglB4Zf4+/2a4n0Sye18ZNPLBSWLVtmg515dTguDnFt2KaAJJiFqYgIwcdK1j1zqO+F4CYWodZI7
yFz9SO8NdCKoCOJuxUnOxwy8p2Fp8fc74SrL+SvzZpA3
-----END CERTIFICATE-----

IdenTrust Commercial Root CA 1
==============================
-----BEGIN CERTIFICATE-----
MIIFYDCCA0igAwIBAgIQCgFCgAAAAUUjyES1AAAAAjANBgkqhkiG9w0BAQsFADBKMQswCQYDVQQG
EwJVUzESMBAGA1UEChMJSWRlblRydXN0MScwJQYDVQQDEx5JZGVuVHJ1c3QgQ29tbWVyY2lhbCBS
b290IENBIDEwHhcNMTQwMTE2MTgxMjIzWhcNMzQwMTE2MTgxMjIzWjBKMQswCQYDVQQGEwJVUzES
MBAGA1UEChMJSWRlblRydXN0MScwJQYDVQQDEx5JZGVuVHJ1c3QgQ29tbWVyY2lhbCBSb290IENB
IDEwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCnUBneP5k91DNG8W9RYYKyqU+PZ4ld
hNlT3Qwo2dfw/66VQ3KZ+bVdfIrBQuExUHTRgQ18zZshq0PirK1ehm7zCYofWjK9ouuU+ehcCuz/
mNKvcbO0U59Oh++SvL3sTzIwiEsXXlfEU8L2ApeN2WIrvyQfYo3fw7gpS0l4PJNgiCL8mdo2yMKi
1CxUAGc1bnO/AljwpN3lsKImesrgNqUZFvX9t++uP0D1bVoE/c40yiTcdCMbXTMTEl3EASX2MN0C
XZ/g1Ue9tOsbobtJSdifWwLziuQkkORiT0/Br4sOdBeo0XKIanoBScy0RnnGF7HamB4HWfp1IYVl
3ZBWzvurpWCdxJ35UrCLvYf5jysjCiN2O/cz4ckA82n5S6LgTrx+kzmEB/dEcH7+B1rlsazRGMzy
NeVJSQjKVsk9+w8YfYs7wRPCTY/JTw436R+hDmrfYi7LNQZReSzIJTj0+kuniVyc0uMNOYZKdHzV
WYfCP04MXFL0PfdSgvHqo6z9STQaKPNBiDoT7uje/5kdX7rL6B7yuVBgwDHTc+XvvqDtMwt0viAg
xGds8AgDelWAf0ZOlqf0Hj7h9tgJ4TNkK2PXMl6f+cB7D3hvl7yTmvmcEpB4eoCHFddydJxVdHix
uuFucAS6T6C6aMN7/zHwcz09lCqxC0EOoP5NiGVreTO01wIDAQABo0IwQDAOBgNVHQ8BAf8EBAMC
AQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQU7UQZwNPwBovupHu+QucmVMiONnYwDQYJKoZI
hvcNAQELBQADggIBAA2ukDL2pkt8RHYZYR4nKM1eVO8lvOMIkPkp165oCOGUAFjvLi5+U1KMtlwH
6oi6mYtQlNeCgN9hCQCTrQ0U5s7B8jeUeLBfnLOic7iPBZM4zY0+sLj7wM+x8uwtLRvM7Kqas6pg
ghstO8OEPVeKlh6cdbjTMM1gCIOQ045U8U1mwF10A0Cj7oV+wh93nAbowacYXVKV7cndJZ5t+qnt
ozo00Fl72u1Q8zW/7esUTTHHYPTa8Yec4kjixsU3+wYQ+nVZZjFHKdp2mhzpgq7vmrlR94gjmmmV
YjzlVYA211QC//G5Xc7UI2/YRYRKW2XviQzdFKcgyxilJbQN+QHwotL0AMh0jqEqSI5l2xPE4iUX
feu+h1sXIFRRk0pTAwvsXcoz7WL9RccvW9xYoIA55vrX/hMUpu09lEpCdNTDd1lzzY9GvlU47/ro
kTLql1gEIt44w8y8bckzOmoKaT+gyOpyj4xjhiO9bTyWnpXgSUyqorkqG5w2gXjtw+hG4iZZRHUe
2XWJUc0QhJ1hYMtd+ZciTY6Y5uN/9lu7rs3KSoFrXgvzUeF0K+l+J6fZmUlO+KWA2yUPHGNiiskz
Z2s8EIPGrd6ozRaOjfAHN3Gf8qv8QfXBi+wAN10J5U6A7/qxXDgGpRtK4dw4LTzcqx+QGtVKnO7R
cGzM7vRX+Bi6hG6H
-----END CERTIFICATE-----

IdenTrust Public Sector Root CA 1
=================================
-----BEGIN CERTIFICATE-----
MIIFZjCCA06gAwIBAgIQCgFCgAAAAUUjz0Z8AAAAAjANBgkqhkiG9w0BAQsFADBNMQswCQYDVQQG
EwJVUzESMBAGA1UEChMJSWRlblRydXN0MSowKAYDVQQDEyFJZGVuVHJ1c3QgUHVibGljIFNlY3Rv
ciBSb290IENBIDEwHhcNMTQwMTE2MTc1MzMyWhcNMzQwMTE2MTc1MzMyWjBNMQswCQYDVQQGEwJV
UzESMBAGA1UEChMJSWRlblRydXN0MSowKAYDVQQDEyFJZGVuVHJ1c3QgUHVibGljIFNlY3RvciBS
b290IENBIDEwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC2IpT8pEiv6EdrCvsnduTy
P4o7ekosMSqMjbCpwzFrqHd2hCa2rIFCDQjrVVi7evi8ZX3yoG2LqEfpYnYeEe4IFNGyRBb06tD6
Hi9e28tzQa68ALBKK0CyrOE7S8ItneShm+waOh7wCLPQ5CQ1B5+ctMlSbdsHyo+1W/CD80/HLaXI
rcuVIKQxKFdYWuSNG5qrng0M8gozOSI5Cpcu81N3uURF/YTLNiCBWS2ab21ISGHKTN9T0a9SvESf
qy9rg3LvdYDaBjMbXcjaY8ZNzaxmMc3R3j6HEDbhuaR672BQssvKplbgN6+rNBM5Jeg5ZuSYeqoS
mJxZZoY+rfGwyj4GD3vwEUs3oERte8uojHH01bWRNszwFcYr3lEXsZdMUD2xlVl8BX0tIdUAvwFn
ol57plzy9yLxkA2T26pEUWbMfXYD62qoKjgZl3YNa4ph+bz27nb9cCvdKTz4Ch5bQhyLVi9VGxyh
LrXHFub4qjySjmm2AcG1hp2JDws4lFTo6tyePSW8Uybt1as5qsVATFSrsrTZ2fjXctscvG29ZV/v
iDUqZi/u9rNl8DONfJhBaUYPQxxp+pu10GFqzcpL2UyQRqsVWaFHVCkugyhfHMKiq3IXAAaOReyL
4jM9f9oZRORicsPfIsbyVtTdX5Vy7W1f90gDW/3FKqD2cyOEEBsB5wIDAQABo0IwQDAOBgNVHQ8B
Af8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQU43HgntinQtnbcZFrlJPrw6PRFKMw
DQYJKoZIhvcNAQELBQADggIBAEf63QqwEZE4rU1d9+UOl1QZgkiHVIyqZJnYWv6IAcVYpZmxI1Qj
t2odIFflAWJBF9MJ23XLblSQdf4an4EKwt3X9wnQW3IV5B4Jaj0z8yGa5hV+rVHVDRDtfULAj+7A
mgjVQdZcDiFpboBhDhXAuM/FSRJSzL46zNQuOAXeNf0fb7iAaJg9TaDKQGXSc3z1i9kKlT/YPyNt
GtEqJBnZhbMX73huqVjRI9PHE+1yJX9dsXNw0H8GlwmEKYBhHfpe/3OsoOOJuBxxFcbeMX8S3OFt
m6/n6J91eEyrRjuazr8FGF1NFTwWmhlQBJqymm9li1JfPFgEKCXAZmExfrngdbkaqIHWchezxQMx
NRF4eKLg6TCMf4DfWN88uieW4oA0beOY02QnrEh+KHdcxiVhJfiFDGX6xDIvpZgF5PgLZxYWxoK4
Mhn5+bl53B/N66+rDt0b20XkeucC4pVd/GnwU2lhlXV5C15V5jgclKlZM57IcXR5f1GJtshquDDI
ajjDbp7hNxbqBWJMWxJH7ae0s1hWx0nzfxJoCTFx8G34Tkf71oXuxVhAGaQdp/lLQzfcaFpPz+vC
ZHTetBXZ9FRUGi8c15dxVJCO2SCdUyt/q4/i6jC8UDfv8Ue1fXwsBOxonbRJRBD0ckscZOf85muQ
3Wl9af0AVqW3rLatt8o+Ae+c
-----END CERTIFICATE-----

Entrust Root Certification Authority - G2
=========================================
-----BEGIN CERTIFICATE-----
MIIEPjCCAyagAwIBAgIESlOMKDANBgkqhkiG9w0BAQsFADCBvjELMAkGA1UEBhMCVVMxFjAUBgNV
BAoTDUVudHJ1c3QsIEluYy4xKDAmBgNVBAsTH1NlZSB3d3cuZW50cnVzdC5uZXQvbGVnYWwtdGVy
bXMxOTA3BgNVBAsTMChjKSAyMDA5IEVudHJ1c3QsIEluYy4gLSBmb3IgYXV0aG9yaXplZCB1c2Ug
b25seTEyMDAGA1UEAxMpRW50cnVzdCBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IC0gRzIw
HhcNMDkwNzA3MTcyNTU0WhcNMzAxMjA3MTc1NTU0WjCBvjELMAkGA1UEBhMCVVMxFjAUBgNVBAoT
DUVudHJ1c3QsIEluYy4xKDAmBgNVBAsTH1NlZSB3d3cuZW50cnVzdC5uZXQvbGVnYWwtdGVybXMx
OTA3BgNVBAsTMChjKSAyMDA5IEVudHJ1c3QsIEluYy4gLSBmb3IgYXV0aG9yaXplZCB1c2Ugb25s
eTEyMDAGA1UEAxMpRW50cnVzdCBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IC0gRzIwggEi
MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC6hLZy254Ma+KZ6TABp3bqMriVQRrJ2mFOWHLP
/vaCeb9zYQYKpSfYs1/TRU4cctZOMvJyig/3gxnQaoCAAEUesMfnmr8SVycco2gvCoe9amsOXmXz
HHfV1IWNcCG0szLni6LVhjkCsbjSR87kyUnEO6fe+1R9V77w6G7CebI6C1XiUJgWMhNcL3hWwcKU
s/Ja5CeanyTXxuzQmyWC48zCxEXFjJd6BmsqEZ+pCm5IO2/b1BEZQvePB7/1U1+cPvQXLOZprE4y
TGJ36rfo5bs0vBmLrpxR57d+tVOxMyLlbc9wPBr64ptntoP0jaWvYkxN4FisZDQSA/i2jZRjJKRx
AgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBRqciZ6
0B7vfec7aVHUbI2fkBJmqzANBgkqhkiG9w0BAQsFAAOCAQEAeZ8dlsa2eT8ijYfThwMEYGprmi5Z
iXMRrEPR9RP/jTkrwPK9T3CMqS/qF8QLVJ7UG5aYMzyorWKiAHarWWluBh1+xLlEjZivEtRh2woZ
Rkfz6/djwUAFQKXSt/S1mja/qYh2iARVBCuch38aNzx+LaUa2NSJXsq9rD1s2G2v1fN2D807iDgi
nWyTmsQ9v4IbZT+mD12q/OWyFcq1rca8PdCE6OoGcrBNOTJ4vz4RnAuknZoh8/CbCzB428Hch0P+
vGOaysXCHMnHjf87ElgI5rY97HosTvuDls4MPGmHVHOkc8KT/1EQrBVUAdj8BbGJoX90g5pJ19xO
e4pIb4tF9g==
-----END CERTIFICATE-----

Entrust Root Certification Authority - EC1
==========================================
-----BEGIN CERTIFICATE-----
MIIC+TCCAoCgAwIBAgINAKaLeSkAAAAAUNCR+TAKBggqhkjOPQQDAzCBvzELMAkGA1UEBhMCVVMx
FjAUBgNVBAoTDUVudHJ1c3QsIEluYy4xKDAmBgNVBAsTH1NlZSB3d3cuZW50cnVzdC5uZXQvbGVn
YWwtdGVybXMxOTA3BgNVBAsTMChjKSAyMDEyIEVudHJ1c3QsIEluYy4gLSBmb3IgYXV0aG9yaXpl
ZCB1c2Ugb25seTEzMDEGA1UEAxMqRW50cnVzdCBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5
IC0gRUMxMB4XDTEyMTIxODE1MjUzNloXDTM3MTIxODE1NTUzNlowgb8xCzAJBgNVBAYTAlVTMRYw
FAYDVQQKEw1FbnRydXN0LCBJbmMuMSgwJgYDVQQLEx9TZWUgd3d3LmVudHJ1c3QubmV0L2xlZ2Fs
LXRlcm1zMTkwNwYDVQQLEzAoYykgMjAxMiBFbnRydXN0LCBJbmMuIC0gZm9yIGF1dGhvcml6ZWQg
dXNlIG9ubHkxMzAxBgNVBAMTKkVudHJ1c3QgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAt
IEVDMTB2MBAGByqGSM49AgEGBSuBBAAiA2IABIQTydC6bUF74mzQ61VfZgIaJPRbiWlH47jCffHy
AsWfoPZb1YsGGYZPUxBtByQnoaD41UcZYUx9ypMn6nQM72+WCf5j7HBdNq1nd67JnXxVRDqiY1Ef
9eNi1KlHBz7MIKNCMEAwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYE
FLdj5xrdjekIplWDpOBqUEFlEUJJMAoGCCqGSM49BAMDA2cAMGQCMGF52OVCR98crlOZF7ZvHH3h
vxGU0QOIdeSNiaSKd0bebWHvAvX7td/M/k7//qnmpwIwW5nXhTcGtXsI/esni0qU+eH6p44mCOh8
kmhtc9hvJqwhAriZtyZBWyVgrtBIGu4G
-----END CERTIFICATE-----

CFCA EV ROOT
============
-----BEGIN CERTIFICATE-----
MIIFjTCCA3WgAwIBAgIEGErM1jANBgkqhkiG9w0BAQsFADBWMQswCQYDVQQGEwJDTjEwMC4GA1UE
CgwnQ2hpbmEgRmluYW5jaWFsIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MRUwEwYDVQQDDAxDRkNB
IEVWIFJPT1QwHhcNMTIwODA4MDMwNzAxWhcNMjkxMjMxMDMwNzAxWjBWMQswCQYDVQQGEwJDTjEw
MC4GA1UECgwnQ2hpbmEgRmluYW5jaWFsIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MRUwEwYDVQQD
DAxDRkNBIEVWIFJPT1QwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDXXWvNED8fBVnV
BU03sQ7smCuOFR36k0sXgiFxEFLXUWRwFsJVaU2OFW2fvwwbwuCjZ9YMrM8irq93VCpLTIpTUnrD
7i7es3ElweldPe6hL6P3KjzJIx1qqx2hp/Hz7KDVRM8Vz3IvHWOX6Jn5/ZOkVIBMUtRSqy5J35DN
uF++P96hyk0g1CXohClTt7GIH//62pCfCqktQT+x8Rgp7hZZLDRJGqgG16iI0gNyejLi6mhNbiyW
ZXvKWfry4t3uMCz7zEasxGPrb382KzRzEpR/38wmnvFyXVBlWY9ps4deMm/DGIq1lY+wejfeWkU7
xzbh72fROdOXW3NiGUgthxwG+3SYIElz8AXSG7Ggo7cbcNOIabla1jj0Ytwli3i/+Oh+uFzJlU9f
py25IGvPa931DfSCt/SyZi4QKPaXWnuWFo8BGS1sbn85WAZkgwGDg8NNkt0yxoekN+kWzqotaK8K
gWU6cMGbrU1tVMoqLUuFG7OA5nBFDWteNfB/O7ic5ARwiRIlk9oKmSJgamNgTnYGmE69g60dWIol
hdLHZR4tjsbftsbhf4oEIRUpdPA+nJCdDC7xij5aqgwJHsfVPKPtl8MeNPo4+QgO48BdK4PRVmrJ
tqhUUy54Mmc9gn900PvhtgVguXDbjgv5E1hvcWAQUhC5wUEJ73IfZzF4/5YFjQIDAQABo2MwYTAf
BgNVHSMEGDAWgBTj/i39KNALtbq2osS/BqoFjJP7LzAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB
/wQEAwIBBjAdBgNVHQ4EFgQU4/4t/SjQC7W6tqLEvwaqBYyT+y8wDQYJKoZIhvcNAQELBQADggIB
ACXGumvrh8vegjmWPfBEp2uEcwPenStPuiB/vHiyz5ewG5zz13ku9Ui20vsXiObTej/tUxPQ4i9q
ecsAIyjmHjdXNYmEwnZPNDatZ8POQQaIxffu2Bq41gt/UP+TqhdLjOztUmCypAbqTuv0axn96/Ua
4CUqmtzHQTb3yHQFhDmVOdYLO6Qn+gjYXB74BGBSESgoA//vU2YApUo0FmZ8/Qmkrp5nGm9BC2sG
E5uPhnEFtC+NiWYzKXZUmhH4J/qyP5Hgzg0b8zAarb8iXRvTvyUFTeGSGn+ZnzxEk8rUQElsgIfX
BDrDMlI1Dlb4pd19xIsNER9Tyx6yF7Zod1rg1MvIB671Oi6ON7fQAUtDKXeMOZePglr4UeWJoBjn
aH9dCi77o0cOPaYjesYBx4/IXr9tgFa+iiS6M+qf4TIRnvHST4D2G0CvOJ4RUHlzEhLN5mydLIhy
PDCBBpEi6lmt2hkuIsKNuYyH4Ga8cyNfIWRjgEj1oDwYPZTISEEdQLpe/v5WOaHIz16eGWRGENoX
kbcFgKyLmZJ956LYBws2J+dIeWCKw9cTXPhyQN9Ky8+ZAAoACxGV2lZFA4gKn2fQ1XmxqI1AbQ3C
ekD6819kR5LLU7m7Wc5P/dAVUwHY3+vZ5nbv0CO7O6l5s9UCKc2Jo5YPSjXnTkLAdc0Hz+Ys63su
-----END CERTIFICATE-----

OISTE WISeKey Global Root GB CA
===============================
-----BEGIN CERTIFICATE-----
MIIDtTCCAp2gAwIBAgIQdrEgUnTwhYdGs/gjGvbCwDANBgkqhkiG9w0BAQsFADBtMQswCQYDVQQG
EwJDSDEQMA4GA1UEChMHV0lTZUtleTEiMCAGA1UECxMZT0lTVEUgRm91bmRhdGlvbiBFbmRvcnNl
ZDEoMCYGA1UEAxMfT0lTVEUgV0lTZUtleSBHbG9iYWwgUm9vdCBHQiBDQTAeFw0xNDEyMDExNTAw
MzJaFw0zOTEyMDExNTEwMzFaMG0xCzAJBgNVBAYTAkNIMRAwDgYDVQQKEwdXSVNlS2V5MSIwIAYD
VQQLExlPSVNURSBGb3VuZGF0aW9uIEVuZG9yc2VkMSgwJgYDVQQDEx9PSVNURSBXSVNlS2V5IEds
b2JhbCBSb290IEdCIENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA2Be3HEokKtaX
scriHvt9OO+Y9bI5mE4nuBFde9IllIiCFSZqGzG7qFshISvYD06fWvGxWuR51jIjK+FTzJlFXHtP
rby/h0oLS5daqPZI7H17Dc0hBt+eFf1Biki3IPShehtX1F1Q/7pn2COZH8g/497/b1t3sWtuuMlk
9+HKQUYOKXHQuSP8yYFfTvdv37+ErXNku7dCjmn21HYdfp2nuFeKUWdy19SouJVUQHMD9ur06/4o
Qnc/nSMbsrY9gBQHTC5P99UKFg29ZkM3fiNDecNAhvVMKdqOmq0NpQSHiB6F4+lT1ZvIiwNjeOvg
GUpuuy9rM2RYk61pv48b74JIxwIDAQABo1EwTzALBgNVHQ8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB
/zAdBgNVHQ4EFgQUNQ/INmNe4qPs+TtmFc5RUuORmj0wEAYJKwYBBAGCNxUBBAMCAQAwDQYJKoZI
hvcNAQELBQADggEBAEBM+4eymYGQfp3FsLAmzYh7KzKNbrghcViXfa43FK8+5/ea4n32cZiZBKpD
dHij40lhPnOMTZTg+XHEthYOU3gf1qKHLwI5gSk8rxWYITD+KJAAjNHhy/peyP34EEY7onhCkRd0
VQreUGdNZtGn//3ZwLWoo4rOZvUPQ82nK1d7Y0Zqqi5S2PTt4W2tKZB4SLrhI6qjiey1q5bAtEui
HZeeevJuQHHfaPFlTc58Bd9TZaml8LGXBHAVRgOY1NK/VLSgWH1Sb9pWJmLU2NuJMW8c8CLC02Ic
Nc1MaRVUGpCY3useX8p3x8uOPUNpnJpY0CQ73xtAln41rYHHTnG6iBM=
-----END CERTIFICATE-----

SZAFIR ROOT CA2
===============
-----BEGIN CERTIFICATE-----
MIIDcjCCAlqgAwIBAgIUPopdB+xV0jLVt+O2XwHrLdzk1uQwDQYJKoZIhvcNAQELBQAwUTELMAkG
A1UEBhMCUEwxKDAmBgNVBAoMH0tyYWpvd2EgSXpiYSBSb3psaWN6ZW5pb3dhIFMuQS4xGDAWBgNV
BAMMD1NaQUZJUiBST09UIENBMjAeFw0xNTEwMTkwNzQzMzBaFw0zNTEwMTkwNzQzMzBaMFExCzAJ
BgNVBAYTAlBMMSgwJgYDVQQKDB9LcmFqb3dhIEl6YmEgUm96bGljemVuaW93YSBTLkEuMRgwFgYD
VQQDDA9TWkFGSVIgUk9PVCBDQTIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC3vD5Q
qEvNQLXOYeeWyrSh2gwisPq1e3YAd4wLz32ohswmUeQgPYUM1ljj5/QqGJ3a0a4m7utT3PSQ1hNK
DJA8w/Ta0o4NkjrcsbH/ON7Dui1fgLkCvUqdGw+0w8LBZwPd3BucPbOw3gAeqDRHu5rr/gsUvTaE
2g0gv/pby6kWIK05YO4vdbbnl5z5Pv1+TW9NL++IDWr63fE9biCloBK0TXC5ztdyO4mTp4CEHCdJ
ckm1/zuVnsHMyAHs6A6KCpbns6aH5db5BSsNl0BwPLqsdVqc1U2dAgrSS5tmS0YHF2Wtn2yIANwi
ieDhZNRnvDF5YTy7ykHNXGoAyDw4jlivAgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0P
AQH/BAQDAgEGMB0GA1UdDgQWBBQuFqlKGLXLzPVvUPMjX/hd56zwyDANBgkqhkiG9w0BAQsFAAOC
AQEAtXP4A9xZWx126aMqe5Aosk3AM0+qmrHUuOQn/6mWmc5G4G18TKI4pAZw8PRBEew/R40/cof5
O/2kbytTAOD/OblqBw7rHRz2onKQy4I9EYKL0rufKq8h5mOGnXkZ7/e7DDWQw4rtTw/1zBLZpD67
oPwglV9PJi8RI4NOdQcPv5vRtB3pEAT+ymCPoky4rc/hkA/NrgrHXXu3UNLUYfrVFdvXn4dRVOul
4+vJhaAlIDf7js4MNIThPIGyd05DpYhfhmehPea0XGG2Ptv+tyjFogeutcrKjSoS75ftwjCkySp6
+/NNIxuZMzSgLvWpCz/UXeHPhJ/iGcJfitYgHuNztw==
-----END CERTIFICATE-----

Certum Trusted Network CA 2
===========================
-----BEGIN CERTIFICATE-----
MIIF0jCCA7qgAwIBAgIQIdbQSk8lD8kyN/yqXhKN6TANBgkqhkiG9w0BAQ0FADCBgDELMAkGA1UE
BhMCUEwxIjAgBgNVBAoTGVVuaXpldG8gVGVjaG5vbG9naWVzIFMuQS4xJzAlBgNVBAsTHkNlcnR1
bSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTEkMCIGA1UEAxMbQ2VydHVtIFRydXN0ZWQgTmV0d29y
ayBDQSAyMCIYDzIwMTExMDA2MDgzOTU2WhgPMjA0NjEwMDYwODM5NTZaMIGAMQswCQYDVQQGEwJQ
TDEiMCAGA1UEChMZVW5pemV0byBUZWNobm9sb2dpZXMgUy5BLjEnMCUGA1UECxMeQ2VydHVtIENl
cnRpZmljYXRpb24gQXV0aG9yaXR5MSQwIgYDVQQDExtDZXJ0dW0gVHJ1c3RlZCBOZXR3b3JrIENB
IDIwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC9+Xj45tWADGSdhhuWZGc/IjoedQF9
7/tcZ4zJzFxrqZHmuULlIEub2pt7uZld2ZuAS9eEQCsn0+i6MLs+CRqnSZXvK0AkwpfHp+6bJe+o
CgCXhVqqndwpyeI1B+twTUrWwbNWuKFBOJvR+zF/j+Bf4bE/D44WSWDXBo0Y+aomEKsq09DRZ40b
Rr5HMNUuctHFY9rnY3lEfktjJImGLjQ/KUxSiyqnwOKRKIm5wFv5HdnnJ63/mgKXwcZQkpsCLL2p
uTRZCr+ESv/f/rOf69me4Jgj7KZrdxYq28ytOxykh9xGc14ZYmhFV+SQgkK7QtbwYeDBoz1mo130
GO6IyY0XRSmZMnUCMe4pJshrAua1YkV/NxVaI2iJ1D7eTiew8EAMvE0Xy02isx7QBlrd9pPPV3WZ
9fqGGmd4s7+W/jTcvedSVuWz5XV710GRBdxdaeOVDUO5/IOWOZV7bIBaTxNyxtd9KXpEulKkKtVB
Rgkg/iKgtlswjbyJDNXXcPiHUv3a76xRLgezTv7QCdpw75j6VuZt27VXS9zlLCUVyJ4ueE742pye
hizKV/Ma5ciSixqClnrDvFASadgOWkaLOusm+iPJtrCBvkIApPjW/jAux9JG9uWOdf3yzLnQh1vM
BhBgu4M1t15n3kfsmUjxpKEV/q2MYo45VU85FrmxY53/twIDAQABo0IwQDAPBgNVHRMBAf8EBTAD
AQH/MB0GA1UdDgQWBBS2oVQ5AsOgP46KvPrU+Bym0ToO/TAOBgNVHQ8BAf8EBAMCAQYwDQYJKoZI
hvcNAQENBQADggIBAHGlDs7k6b8/ONWJWsQCYftMxRQXLYtPU2sQF/xlhMcQSZDe28cmk4gmb3DW
Al45oPePq5a1pRNcgRRtDoGCERuKTsZPpd1iHkTfCVn0W3cLN+mLIMb4Ck4uWBzrM9DPhmDJ2vuA
L55MYIR4PSFk1vtBHxgP58l1cb29XN40hz5BsA72udY/CROWFC/emh1auVbONTqwX3BNXuMp8SMo
clm2q8KMZiYcdywmdjWLKKdpoPk79SPdhRB0yZADVpHnr7pH1BKXESLjokmUbOe3lEu6LaTaM4tM
pkT/WjzGHWTYtTHkpjx6qFcL2+1hGsvxznN3Y6SHb0xRONbkX8eftoEq5IVIeVheO/jbAoJnwTnb
w3RLPTYe+SmTiGhbqEQZIfCn6IENLOiTNrQ3ssqwGyZ6miUfmpqAnksqP/ujmv5zMnHCnsZy4Ypo
J/HkD7TETKVhk/iXEAcqMCWpuchxuO9ozC1+9eB+D4Kob7a6bINDd82Kkhehnlt4Fj1F4jNy3eFm
ypnTycUm/Q1oBEauttmbjL4ZvrHG8hnjXALKLNhvSgfZyTXaQHXyxKcZb55CEJh15pWLYLztxRLX
is7VmFxWlgPF7ncGNf/P5O4/E2Hu29othfDNrp2yGAlFw5Khchf8R7agCyzxxN5DaAhqXzvwdmP7
zAYspsbiDrW5viSP
-----END CERTIFICATE-----

Hellenic Academic and Research Institutions RootCA 2015
=======================================================
-----BEGIN CERTIFICATE-----
MIIGCzCCA/OgAwIBAgIBADANBgkqhkiG9w0BAQsFADCBpjELMAkGA1UEBhMCR1IxDzANBgNVBAcT
BkF0aGVuczFEMEIGA1UEChM7SGVsbGVuaWMgQWNhZGVtaWMgYW5kIFJlc2VhcmNoIEluc3RpdHV0
aW9ucyBDZXJ0LiBBdXRob3JpdHkxQDA+BgNVBAMTN0hlbGxlbmljIEFjYWRlbWljIGFuZCBSZXNl
YXJjaCBJbnN0aXR1dGlvbnMgUm9vdENBIDIwMTUwHhcNMTUwNzA3MTAxMTIxWhcNNDAwNjMwMTAx
MTIxWjCBpjELMAkGA1UEBhMCR1IxDzANBgNVBAcTBkF0aGVuczFEMEIGA1UEChM7SGVsbGVuaWMg
QWNhZGVtaWMgYW5kIFJlc2VhcmNoIEluc3RpdHV0aW9ucyBDZXJ0LiBBdXRob3JpdHkxQDA+BgNV
BAMTN0hlbGxlbmljIEFjYWRlbWljIGFuZCBSZXNlYXJjaCBJbnN0aXR1dGlvbnMgUm9vdENBIDIw
MTUwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDC+Kk/G4n8PDwEXT2QNrCROnk8Zlrv
bTkBSRq0t89/TSNTt5AA4xMqKKYx8ZEA4yjsriFBzh/a/X0SWwGDD7mwX5nh8hKDgE0GPt+sr+eh
iGsxr/CL0BgzuNtFajT0AoAkKAoCFZVedioNmToUW/bLy1O8E00BiDeUJRtCvCLYjqOWXjrZMts+
6PAQZe104S+nfK8nNLspfZu2zwnI5dMK/IhlZXQK3HMcXM1AsRzUtoSMTFDPaI6oWa7CJ06CojXd
FPQf/7J31Ycvqm59JCfnxssm5uX+Zwdj2EUN3TpZZTlYepKZcj2chF6IIbjV9Cz82XBST3i4vTwr
i5WY9bPRaM8gFH5MXF/ni+X1NYEZN9cRCLdmvtNKzoNXADrDgfgXy5I2XdGj2HUb4Ysn6npIQf1F
GQatJ5lOwXBH3bWfgVMS5bGMSF0xQxfjjMZ6Y5ZLKTBOhE5iGV48zpeQpX8B653g+IuJ3SWYPZK2
fu/Z8VFRfS0myGlZYeCsargqNhEEelC9MoS+L9xy1dcdFkfkR2YgP/SWxa+OAXqlD3pk9Q0Yh9mu
iNX6hME6wGkoLfINaFGq46V3xqSQDqE3izEjR8EJCOtu93ib14L8hCCZSRm2Ekax+0VVFqmjZayc
Bw/qa9wfLgZy7IaIEuQt218FL+TwA9MmM+eAws1CoRc0CwIDAQABo0IwQDAPBgNVHRMBAf8EBTAD
AQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUcRVnyMjJvXVdctA4GGqd83EkVAswDQYJKoZI
hvcNAQELBQADggIBAHW7bVRLqhBYRjTyYtcWNl0IXtVsyIe9tC5G8jH4fOpCtZMWVdyhDBKg2mF+
D1hYc2Ryx+hFjtyp8iY/xnmMsVMIM4GwVhO+5lFc2JsKT0ucVlMC6U/2DWDqTUJV6HwbISHTGzrM
d/K4kPFox/la/vot9L/J9UUbzjgQKjeKeaO04wlshYaT/4mWJ3iBj2fjRnRUjtkNaeJK9E10A/+y
d+2VZ5fkscWrv2oj6NSU4kQoYsRL4vDY4ilrGnB+JGGTe08DMiUNRSQrlrRGar9KC/eaj8GsGsVn
82800vpzY4zvFrCopEYq+OsS7HK07/grfoxSwIuEVPkvPuNVqNxmsdnhX9izjFk0WaSrT2y7Hxjb
davYy5LNlDhhDgcGH0tGEPEVvo2FXDtKK4F5D7Rpn0lQl033DlZdwJVqwjbDG2jJ9SrcR5q+ss7F
Jej6A7na+RZukYT1HCjI/CbM1xyQVqdfbzoEvM14iQuODy+jqk+iGxI9FghAD/FGTNeqewjBCvVt
J94Cj8rDtSvK6evIIVM4pcw72Hc3MKJP2W/R8kCtQXoXxdZKNYm3QdV8hn9VTYNKpXMgwDqvkPGa
JI7ZjnHKe7iG2rKPmT4dEw0SEe7Uq/DpFXYC5ODfqiAeW2GFZECpkJcNrVPSWh2HagCXZWK0vm9q
p/UsQu0yrbYhnr68
-----END CERTIFICATE-----

Hellenic Academic and Research Institutions ECC RootCA 2015
===========================================================
-----BEGIN CERTIFICATE-----
MIICwzCCAkqgAwIBAgIBADAKBggqhkjOPQQDAjCBqjELMAkGA1UEBhMCR1IxDzANBgNVBAcTBkF0
aGVuczFEMEIGA1UEChM7SGVsbGVuaWMgQWNhZGVtaWMgYW5kIFJlc2VhcmNoIEluc3RpdHV0aW9u
cyBDZXJ0LiBBdXRob3JpdHkxRDBCBgNVBAMTO0hlbGxlbmljIEFjYWRlbWljIGFuZCBSZXNlYXJj
aCBJbnN0aXR1dGlvbnMgRUNDIFJvb3RDQSAyMDE1MB4XDTE1MDcwNzEwMzcxMloXDTQwMDYzMDEw
MzcxMlowgaoxCzAJBgNVBAYTAkdSMQ8wDQYDVQQHEwZBdGhlbnMxRDBCBgNVBAoTO0hlbGxlbmlj
IEFjYWRlbWljIGFuZCBSZXNlYXJjaCBJbnN0aXR1dGlvbnMgQ2VydC4gQXV0aG9yaXR5MUQwQgYD
VQQDEztIZWxsZW5pYyBBY2FkZW1pYyBhbmQgUmVzZWFyY2ggSW5zdGl0dXRpb25zIEVDQyBSb290
Q0EgMjAxNTB2MBAGByqGSM49AgEGBSuBBAAiA2IABJKgQehLgoRc4vgxEZmGZE4JJS+dQS8KrjVP
dJWyUWRrjWvmP3CV8AVER6ZyOFB2lQJajq4onvktTpnvLEhvTCUp6NFxW98dwXU3tNf6e3pCnGoK
Vlp8aQuqgAkkbH7BRqNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0O
BBYEFLQiC4KZJAEOnLvkDv2/+5cgk5kqMAoGCCqGSM49BAMCA2cAMGQCMGfOFmI4oqxiRaeplSTA
GiecMjvAwNW6qef4BENThe5SId6d9SWDPp5YSy/XZxMOIQIwBeF1Ad5o7SofTUwJCA3sS61kFyjn
dc5FZXIhF8siQQ6ME5g4mlRtm8rifOoCWCKR
-----END CERTIFICATE-----

ISRG Root X1
============
-----BEGIN CERTIFICATE-----
MIIFazCCA1OgAwIBAgIRAIIQz7DSQONZRGPgu2OCiwAwDQYJKoZIhvcNAQELBQAwTzELMAkGA1UE
BhMCVVMxKTAnBgNVBAoTIEludGVybmV0IFNlY3VyaXR5IFJlc2VhcmNoIEdyb3VwMRUwEwYDVQQD
EwxJU1JHIFJvb3QgWDEwHhcNMTUwNjA0MTEwNDM4WhcNMzUwNjA0MTEwNDM4WjBPMQswCQYDVQQG
EwJVUzEpMCcGA1UEChMgSW50ZXJuZXQgU2VjdXJpdHkgUmVzZWFyY2ggR3JvdXAxFTATBgNVBAMT
DElTUkcgUm9vdCBYMTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAK3oJHP0FDfzm54r
Vygch77ct984kIxuPOZXoHj3dcKi/vVqbvYATyjb3miGbESTtrFj/RQSa78f0uoxmyF+0TM8ukj1
3Xnfs7j/EvEhmkvBioZxaUpmZmyPfjxwv60pIgbz5MDmgK7iS4+3mX6UA5/TR5d8mUgjU+g4rk8K
b4Mu0UlXjIB0ttov0DiNewNwIRt18jA8+o+u3dpjq+sWT8KOEUt+zwvo/7V3LvSye0rgTBIlDHCN
Aymg4VMk7BPZ7hm/ELNKjD+Jo2FR3qyHB5T0Y3HsLuJvW5iB4YlcNHlsdu87kGJ55tukmi8mxdAQ
4Q7e2RCOFvu396j3x+UCB5iPNgiV5+I3lg02dZ77DnKxHZu8A/lJBdiB3QW0KtZB6awBdpUKD9jf
1b0SHzUvKBds0pjBqAlkd25HN7rOrFleaJ1/ctaJxQZBKT5ZPt0m9STJEadao0xAH0ahmbWnOlFu
hjuefXKnEgV4We0+UXgVCwOPjdAvBbI+e0ocS3MFEvzG6uBQE3xDk3SzynTnjh8BCNAw1FtxNrQH
usEwMFxIt4I7mKZ9YIqioymCzLq9gwQbooMDQaHWBfEbwrbwqHyGO0aoSCqI3Haadr8faqU9GY/r
OPNk3sgrDQoo//fb4hVC1CLQJ13hef4Y53CIrU7m2Ys6xt0nUW7/vGT1M0NPAgMBAAGjQjBAMA4G
A1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBR5tFnme7bl5AFzgAiIyBpY
9umbbjANBgkqhkiG9w0BAQsFAAOCAgEAVR9YqbyyqFDQDLHYGmkgJykIrGF1XIpu+ILlaS/V9lZL
ubhzEFnTIZd+50xx+7LSYK05qAvqFyFWhfFQDlnrzuBZ6brJFe+GnY+EgPbk6ZGQ3BebYhtF8GaV
0nxvwuo77x/Py9auJ/GpsMiu/X1+mvoiBOv/2X/qkSsisRcOj/KKNFtY2PwByVS5uCbMiogziUwt
hDyC3+6WVwW6LLv3xLfHTjuCvjHIInNzktHCgKQ5ORAzI4JMPJ+GslWYHb4phowim57iaztXOoJw
TdwJx4nLCgdNbOhdjsnvzqvHu7UrTkXWStAmzOVyyghqpZXjFaH3pO3JLF+l+/+sKAIuvtd7u+Nx
e5AW0wdeRlN8NwdCjNPElpzVmbUq4JUagEiuTDkHzsxHpFKVK7q4+63SM1N95R1NbdWhscdCb+ZA
JzVcoyi3B43njTOQ5yOf+1CceWxG1bQVs5ZufpsMljq4Ui0/1lvh+wjChP4kqKOJ2qxq4RgqsahD
YVvTH9w7jXbyLeiNdd8XM2w9U/t7y0Ff/9yi0GE44Za4rF2LN9d11TPAmRGunUHBcnWEvgJBQl9n
JEiU0Zsnvgc/ubhPgXRR4Xq37Z0j4r7g1SgEEzwxA57demyPxgcYxn/eR44/KJ4EBs+lVDR3veyJ
m+kXQ99b21/+jh5Xos1AnX5iItreGCc=
-----END CERTIFICATE-----

AC RAIZ FNMT-RCM
================
-----BEGIN CERTIFICATE-----
MIIFgzCCA2ugAwIBAgIPXZONMGc2yAYdGsdUhGkHMA0GCSqGSIb3DQEBCwUAMDsxCzAJBgNVBAYT
AkVTMREwDwYDVQQKDAhGTk1ULVJDTTEZMBcGA1UECwwQQUMgUkFJWiBGTk1ULVJDTTAeFw0wODEw
MjkxNTU5NTZaFw0zMDAxMDEwMDAwMDBaMDsxCzAJBgNVBAYTAkVTMREwDwYDVQQKDAhGTk1ULVJD
TTEZMBcGA1UECwwQQUMgUkFJWiBGTk1ULVJDTTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoC
ggIBALpxgHpMhm5/yBNtwMZ9HACXjywMI7sQmkCpGreHiPibVmr75nuOi5KOpyVdWRHbNi63URcf
qQgfBBckWKo3Shjf5TnUV/3XwSyRAZHiItQDwFj8d0fsjz50Q7qsNI1NOHZnjrDIbzAzWHFctPVr
btQBULgTfmxKo0nRIBnuvMApGGWn3v7v3QqQIecaZ5JCEJhfTzC8PhxFtBDXaEAUwED653cXeuYL
j2VbPNmaUtu1vZ5Gzz3rkQUCwJaydkxNEJY7kvqcfw+Z374jNUUeAlz+taibmSXaXvMiwzn15Cou
08YfxGyqxRxqAQVKL9LFwag0Jl1mpdICIfkYtwb1TplvqKtMUejPUBjFd8g5CSxJkjKZqLsXF3mw
WsXmo8RZZUc1g16p6DULmbvkzSDGm0oGObVo/CK67lWMK07q87Hj/LaZmtVC+nFNCM+HHmpxffnT
tOmlcYF7wk5HlqX2doWjKI/pgG6BU6VtX7hI+cL5NqYuSf+4lsKMB7ObiFj86xsc3i1w4peSMKGJ
47xVqCfWS+2QrYv6YyVZLag13cqXM7zlzced0ezvXg5KkAYmY6252TUtB7p2ZSysV4999AeU14EC
ll2jB0nVetBX+RvnU0Z1qrB5QstocQjpYL05ac70r8NWQMetUqIJ5G+GR4of6ygnXYMgrwTJbFaa
i0b1AgMBAAGjgYMwgYAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYE
FPd9xf3E6Jobd2Sn9R2gzL+HYJptMD4GA1UdIAQ3MDUwMwYEVR0gADArMCkGCCsGAQUFBwIBFh1o
dHRwOi8vd3d3LmNlcnQuZm5tdC5lcy9kcGNzLzANBgkqhkiG9w0BAQsFAAOCAgEAB5BK3/MjTvDD
nFFlm5wioooMhfNzKWtN/gHiqQxjAb8EZ6WdmF/9ARP67Jpi6Yb+tmLSbkyU+8B1RXxlDPiyN8+s
D8+Nb/kZ94/sHvJwnvDKuO+3/3Y3dlv2bojzr2IyIpMNOmqOFGYMLVN0V2Ue1bLdI4E7pWYjJ2cJ
j+F3qkPNZVEI7VFY/uY5+ctHhKQV8Xa7pO6kO8Rf77IzlhEYt8llvhjho6Tc+hj507wTmzl6NLrT
Qfv6MooqtyuGC2mDOL7Nii4LcK2NJpLuHvUBKwrZ1pebbuCoGRw6IYsMHkCtA+fdZn71uSANA+iW
+YJF1DngoABd15jmfZ5nc8OaKveri6E6FO80vFIOiZiaBECEHX5FaZNXzuvO+FB8TxxuBEOb+dY7
Ixjp6o7RTUaN8Tvkasq6+yO3m/qZASlaWFot4/nUbQ4mrcFuNLwy+AwF+mWj2zs3gyLp1txyM/1d
8iC9djwj2ij3+RvrWWTV3F9yfiD8zYm1kGdNYno/Tq0dwzn+evQoFt9B9kiABdcPUXmsEKvU7ANm
5mqwujGSQkBqvjrTcuFqN1W8rB2Vt2lh8kORdOag0wokRqEIr9baRRmW1FMdW4R58MD3R++Lj8UG
rp1MYp3/RgT408m2ECVAdf4WqslKYIYvuu8wd+RU4riEmViAqhOLUTpPSPaLtrM=
-----END CERTIFICATE-----

Amazon Root CA 1
================
-----BEGIN CERTIFICATE-----
MIIDQTCCAimgAwIBAgITBmyfz5m/jAo54vB4ikPmljZbyjANBgkqhkiG9w0BAQsFADA5MQswCQYD
VQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6b24gUm9vdCBDQSAxMB4XDTE1
MDUyNjAwMDAwMFoXDTM4MDExNzAwMDAwMFowOTELMAkGA1UEBhMCVVMxDzANBgNVBAoTBkFtYXpv
bjEZMBcGA1UEAxMQQW1hem9uIFJvb3QgQ0EgMTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC
ggEBALJ4gHHKeNXjca9HgFB0fW7Y14h29Jlo91ghYPl0hAEvrAIthtOgQ3pOsqTQNroBvo3bSMgH
FzZM9O6II8c+6zf1tRn4SWiw3te5djgdYZ6k/oI2peVKVuRF4fn9tBb6dNqcmzU5L/qwIFAGbHrQ
gLKm+a/sRxmPUDgH3KKHOVj4utWp+UhnMJbulHheb4mjUcAwhmahRWa6VOujw5H5SNz/0egwLX0t
dHA114gk957EWW67c4cX8jJGKLhD+rcdqsq08p8kDi1L93FcXmn/6pUCyziKrlA4b9v7LWIbxcce
VOF34GfID5yHI9Y/QCB/IIDEgEw+OyQmjgSubJrIqg0CAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB
/zAOBgNVHQ8BAf8EBAMCAYYwHQYDVR0OBBYEFIQYzIU07LwMlJQuCFmcx7IQTgoIMA0GCSqGSIb3
DQEBCwUAA4IBAQCY8jdaQZChGsV2USggNiMOruYou6r4lK5IpDB/G/wkjUu0yKGX9rbxenDIU5PM
CCjjmCXPI6T53iHTfIUJrU6adTrCC2qJeHZERxhlbI1Bjjt/msv0tadQ1wUsN+gDS63pYaACbvXy
8MWy7Vu33PqUXHeeE6V/Uq2V8viTO96LXFvKWlJbYK8U90vvo/ufQJVtMVT8QtPHRh8jrdkPSHCa
2XV4cdFyQzR1bldZwgJcJmApzyMZFo6IQ6XU5MsI+yMRQ+hDKXJioaldXgjUkK642M4UwtBV8ob2
xJNDd2ZhwLnoQdeXeGADbkpyrqXRfboQnoZsG4q5WTP468SQvvG5
-----END CERTIFICATE-----

Amazon Root CA 2
================
-----BEGIN CERTIFICATE-----
MIIFQTCCAymgAwIBAgITBmyf0pY1hp8KD+WGePhbJruKNzANBgkqhkiG9w0BAQwFADA5MQswCQYD
VQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6b24gUm9vdCBDQSAyMB4XDTE1
MDUyNjAwMDAwMFoXDTQwMDUyNjAwMDAwMFowOTELMAkGA1UEBhMCVVMxDzANBgNVBAoTBkFtYXpv
bjEZMBcGA1UEAxMQQW1hem9uIFJvb3QgQ0EgMjCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoC
ggIBAK2Wny2cSkxKgXlRmeyKy2tgURO8TW0G/LAIjd0ZEGrHJgw12MBvIITplLGbhQPDW9tK6Mj4
kHbZW0/jTOgGNk3Mmqw9DJArktQGGWCsN0R5hYGCrVo34A3MnaZMUnbqQ523BNFQ9lXg1dKmSYXp
N+nKfq5clU1Imj+uIFptiJXZNLhSGkOQsL9sBbm2eLfq0OQ6PBJTYv9K8nu+NQWpEjTj82R0Yiw9
AElaKP4yRLuH3WUnAnE72kr3H9rN9yFVkE8P7K6C4Z9r2UXTu/Bfh+08LDmG2j/e7HJV63mjrdvd
fLC6HM783k81ds8P+HgfajZRRidhW+mez/CiVX18JYpvL7TFz4QuK/0NURBs+18bvBt+xa47mAEx
kv8LV/SasrlX6avvDXbR8O70zoan4G7ptGmh32n2M8ZpLpcTnqWHsFcQgTfJU7O7f/aS0ZzQGPSS
btqDT6ZjmUyl+17vIWR6IF9sZIUVyzfpYgwLKhbcAS4y2j5L9Z469hdAlO+ekQiG+r5jqFoz7Mt0
Q5X5bGlSNscpb/xVA1wf+5+9R+vnSUeVC06JIglJ4PVhHvG/LopyboBZ/1c6+XUyo05f7O0oYtlN
c/LMgRdg7c3r3NunysV+Ar3yVAhU/bQtCSwXVEqY0VThUWcI0u1ufm8/0i2BWSlmy5A5lREedCf+
3euvAgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgGGMB0GA1UdDgQWBBSw
DPBMMPQFWAJI/TPlUq9LhONmUjANBgkqhkiG9w0BAQwFAAOCAgEAqqiAjw54o+Ci1M3m9Zh6O+oA
A7CXDpO8Wqj2LIxyh6mx/H9z/WNxeKWHWc8w4Q0QshNabYL1auaAn6AFC2jkR2vHat+2/XcycuUY
+gn0oJMsXdKMdYV2ZZAMA3m3MSNjrXiDCYZohMr/+c8mmpJ5581LxedhpxfL86kSk5Nrp+gvU5LE
YFiwzAJRGFuFjWJZY7attN6a+yb3ACfAXVU3dJnJUH/jWS5E4ywl7uxMMne0nxrpS10gxdr9HIcW
xkPo1LsmmkVwXqkLN1PiRnsn/eBG8om3zEK2yygmbtmlyTrIQRNg91CMFa6ybRoVGld45pIq2WWQ
gj9sAq+uEjonljYE1x2igGOpm/HlurR8FLBOybEfdF849lHqm/osohHUqS0nGkWxr7JOcQ3AWEbW
aQbLU8uz/mtBzUF+fUwPfHJ5elnNXkoOrJupmHN5fLT0zLm4BwyydFy4x2+IoZCn9Kr5v2c69BoV
Yh63n749sSmvZ6ES8lgQGVMDMBu4Gon2nL2XA46jCfMdiyHxtN/kHNGfZQIG6lzWE7OE76KlXIx3
KadowGuuQNKotOrN8I1LOJwZmhsoVLiJkO/KdYE+HvJkJMcYr07/R54H9jVlpNMKVv/1F2Rs76gi
JUmTtt8AF9pYfl3uxRuw0dFfIRDH+fO6AgonB8Xx1sfT4PsJYGw=
-----END CERTIFICATE-----

Amazon Root CA 3
================
-----BEGIN CERTIFICATE-----
MIIBtjCCAVugAwIBAgITBmyf1XSXNmY/Owua2eiedgPySjAKBggqhkjOPQQDAjA5MQswCQYDVQQG
EwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6b24gUm9vdCBDQSAzMB4XDTE1MDUy
NjAwMDAwMFoXDTQwMDUyNjAwMDAwMFowOTELMAkGA1UEBhMCVVMxDzANBgNVBAoTBkFtYXpvbjEZ
MBcGA1UEAxMQQW1hem9uIFJvb3QgQ0EgMzBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABCmXp8ZB
f8ANm+gBG1bG8lKlui2yEujSLtf6ycXYqm0fc4E7O5hrOXwzpcVOho6AF2hiRVd9RFgdszflZwjr
Zt6jQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgGGMB0GA1UdDgQWBBSrttvXBp43
rDCGB5Fwx5zEGbF4wDAKBggqhkjOPQQDAgNJADBGAiEA4IWSoxe3jfkrBqWTrBqYaGFy+uGh0Psc
eGCmQ5nFuMQCIQCcAu/xlJyzlvnrxir4tiz+OpAUFteMYyRIHN8wfdVoOw==
-----END CERTIFICATE-----

Amazon Root CA 4
================
-----BEGIN CERTIFICATE-----
MIIB8jCCAXigAwIBAgITBmyf18G7EEwpQ+Vxe3ssyBrBDjAKBggqhkjOPQQDAzA5MQswCQYDVQQG
EwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6b24gUm9vdCBDQSA0MB4XDTE1MDUy
NjAwMDAwMFoXDTQwMDUyNjAwMDAwMFowOTELMAkGA1UEBhMCVVMxDzANBgNVBAoTBkFtYXpvbjEZ
MBcGA1UEAxMQQW1hem9uIFJvb3QgQ0EgNDB2MBAGByqGSM49AgEGBSuBBAAiA2IABNKrijdPo1MN
/sGKe0uoe0ZLY7Bi9i0b2whxIdIA6GO9mif78DluXeo9pcmBqqNbIJhFXRbb/egQbeOc4OO9X4Ri
83BkM6DLJC9wuoihKqB1+IGuYgbEgds5bimwHvouXKNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNV
HQ8BAf8EBAMCAYYwHQYDVR0OBBYEFNPsxzplbszh2naaVvuc84ZtV+WBMAoGCCqGSM49BAMDA2gA
MGUCMDqLIfG9fhGt0O9Yli/W651+kI0rz2ZVwyzjKKlwCkcO8DdZEv8tmZQoTipPNU0zWgIxAOp1
AE47xDqUEpHJWEadIRNyp4iciuRMStuW1KyLa2tJElMzrdfkviT8tQp21KW8EA==
-----END CERTIFICATE-----

TUBITAK Kamu SM SSL Kok Sertifikasi - Surum 1
=============================================
-----BEGIN CERTIFICATE-----
MIIEYzCCA0ugAwIBAgIBATANBgkqhkiG9w0BAQsFADCB0jELMAkGA1UEBhMCVFIxGDAWBgNVBAcT
D0dlYnplIC0gS29jYWVsaTFCMEAGA1UEChM5VHVya2l5ZSBCaWxpbXNlbCB2ZSBUZWtub2xvamlr
IEFyYXN0aXJtYSBLdXJ1bXUgLSBUVUJJVEFLMS0wKwYDVQQLEyRLYW11IFNlcnRpZmlrYXN5b24g
TWVya2V6aSAtIEthbXUgU00xNjA0BgNVBAMTLVRVQklUQUsgS2FtdSBTTSBTU0wgS29rIFNlcnRp
ZmlrYXNpIC0gU3VydW0gMTAeFw0xMzExMjUwODI1NTVaFw00MzEwMjUwODI1NTVaMIHSMQswCQYD
VQQGEwJUUjEYMBYGA1UEBxMPR2ViemUgLSBLb2NhZWxpMUIwQAYDVQQKEzlUdXJraXllIEJpbGlt
c2VsIHZlIFRla25vbG9qaWsgQXJhc3Rpcm1hIEt1cnVtdSAtIFRVQklUQUsxLTArBgNVBAsTJEth
bXUgU2VydGlmaWthc3lvbiBNZXJrZXppIC0gS2FtdSBTTTE2MDQGA1UEAxMtVFVCSVRBSyBLYW11
IFNNIFNTTCBLb2sgU2VydGlmaWthc2kgLSBTdXJ1bSAxMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A
MIIBCgKCAQEAr3UwM6q7a9OZLBI3hNmNe5eA027n/5tQlT6QlVZC1xl8JoSNkvoBHToP4mQ4t4y8
6Ij5iySrLqP1N+RAjhgleYN1Hzv/bKjFxlb4tO2KRKOrbEz8HdDc72i9z+SqzvBV96I01INrN3wc
wv61A+xXzry0tcXtAA9TNypN9E8Mg/uGz8v+jE69h/mniyFXnHrfA2eJLJ2XYacQuFWQfw4tJzh0
3+f92k4S400VIgLI4OD8D62K18lUUMw7D8oWgITQUVbDjlZ/iSIzL+aFCr2lqBs23tPcLG07xxO9
WSMs5uWk99gL7eqQQESolbuT1dCANLZGeA4fAJNG4e7p+exPFwIDAQABo0IwQDAdBgNVHQ4EFgQU
ZT/HiobGPN08VFw1+DrtUgxHV8gwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wDQYJ
KoZIhvcNAQELBQADggEBACo/4fEyjq7hmFxLXs9rHmoJ0iKpEsdeV31zVmSAhHqT5Am5EM2fKifh
AHe+SMg1qIGf5LgsyX8OsNJLN13qudULXjS99HMpw+0mFZx+CFOKWI3QSyjfwbPfIPP54+M638yc
lNhOT8NrF7f3cuitZjO1JVOr4PhMqZ398g26rrnZqsZr+ZO7rqu4lzwDGrpDxpa5RXI4s6ehlj2R
e37AIVNMh+3yC1SVUZPVIqUNivGTDj5UDrDYyU7c8jEyVupk+eq1nRZmQnLzf9OxMUP8pI4X8W0j
q5Rm+K37DwhuJi1/FwcJsoz7UMCflo3Ptv0AnVoUmr8CRPXBwp8iXqIPoeM=
-----END CERTIFICATE-----

GDCA TrustAUTH R5 ROOT
======================
-----BEGIN CERTIFICATE-----
MIIFiDCCA3CgAwIBAgIIfQmX/vBH6nowDQYJKoZIhvcNAQELBQAwYjELMAkGA1UEBhMCQ04xMjAw
BgNVBAoMKUdVQU5HIERPTkcgQ0VSVElGSUNBVEUgQVVUSE9SSVRZIENPLixMVEQuMR8wHQYDVQQD
DBZHRENBIFRydXN0QVVUSCBSNSBST09UMB4XDTE0MTEyNjA1MTMxNVoXDTQwMTIzMTE1NTk1OVow
YjELMAkGA1UEBhMCQ04xMjAwBgNVBAoMKUdVQU5HIERPTkcgQ0VSVElGSUNBVEUgQVVUSE9SSVRZ
IENPLixMVEQuMR8wHQYDVQQDDBZHRENBIFRydXN0QVVUSCBSNSBST09UMIICIjANBgkqhkiG9w0B
AQEFAAOCAg8AMIICCgKCAgEA2aMW8Mh0dHeb7zMNOwZ+Vfy1YI92hhJCfVZmPoiC7XJjDp6L3TQs
AlFRwxn9WVSEyfFrs0yw6ehGXTjGoqcuEVe6ghWinI9tsJlKCvLriXBjTnnEt1u9ol2x8kECK62p
OqPseQrsXzrj/e+APK00mxqriCZ7VqKChh/rNYmDf1+uKU49tm7srsHwJ5uu4/Ts765/94Y9cnrr
pftZTqfrlYwiOXnhLQiPzLyRuEH3FMEjqcOtmkVEs7LXLM3GKeJQEK5cy4KOFxg2fZfmiJqwTTQJ
9Cy5WmYqsBebnh52nUpmMUHfP/vFBu8btn4aRjb3ZGM74zkYI+dndRTVdVeSN72+ahsmUPI2JgaQ
xXABZG12ZuGR224HwGGALrIuL4xwp9E7PLOR5G62xDtw8mySlwnNR30YwPO7ng/Wi64HtloPzgsM
R6flPri9fcebNaBhlzpBdRfMK5Z3KpIhHtmVdiBnaM8Nvd/WHwlqmuLMc3GkL30SgLdTMEZeS1SZ
D2fJpcjyIMGC7J0R38IC+xo70e0gmu9lZJIQDSri3nDxGGeCjGHeuLzRL5z7D9Ar7Rt2ueQ5Vfj4
oR24qoAATILnsn8JuLwwoC8N9VKejveSswoAHQBUlwbgsQfZxw9cZX08bVlX5O2ljelAU58VS6Bx
9hoh49pwBiFYFIeFd3mqgnkCAwEAAaNCMEAwHQYDVR0OBBYEFOLJQJ9NzuiaoXzPDj9lxSmIahlR
MA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgGGMA0GCSqGSIb3DQEBCwUAA4ICAQDRSVfg
p8xoWLoBDysZzY2wYUWsEe1jUGn4H3++Fo/9nesLqjJHdtJnJO29fDMylyrHBYZmDRd9FBUb1Ov9
H5r2XpdptxolpAqzkT9fNqyL7FeoPueBihhXOYV0GkLH6VsTX4/5COmSdI31R9KrO9b7eGZONn35
6ZLpBN79SWP8bfsUcZNnL0dKt7n/HipzcEYwv1ryL3ml4Y0M2fmyYzeMN2WFcGpcWwlyua1jPLHd
+PwyvzeG5LuOmCd+uh8W4XAR8gPfJWIyJyYYMoSf/wA6E7qaTfRPuBRwIrHKK5DOKcFw9C+df/KQ
HtZa37dG/OaG+svgIHZ6uqbL9XzeYqWxi+7egmaKTjowHz+Ay60nugxe19CxVsp3cbK1daFQqUBD
F8Io2c9Si1vIY9RCPqAzekYu9wogRlR+ak8x8YF+QnQ4ZXMn7sZ8uI7XpTrXmKGcjBBV09tL7ECQ
8s1uV9JiDnxXk7Gnbc2dg7sq5+W2O3FYrf3RRbxake5TFW/TRQl1brqQXR4EzzffHqhmsYzmIGrv
/EhOdJhCrylvLmrH+33RZjEizIYAfmaDDEL0vTSSwxrqT8p+ck0LcIymSLumoRT2+1hEmRSuqguT
aaApJUqlyyvdimYHFngVV3Eb7PVHhPOeMTd61X8kreS8/f3MboPoDKi3QWwH3b08hpcv0g==
-----END CERTIFICATE-----

SSL.com Root Certification Authority RSA
========================================
-----BEGIN CERTIFICATE-----
MIIF3TCCA8WgAwIBAgIIeyyb0xaAMpkwDQYJKoZIhvcNAQELBQAwfDELMAkGA1UEBhMCVVMxDjAM
BgNVBAgMBVRleGFzMRAwDgYDVQQHDAdIb3VzdG9uMRgwFgYDVQQKDA9TU0wgQ29ycG9yYXRpb24x
MTAvBgNVBAMMKFNTTC5jb20gUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSBSU0EwHhcNMTYw
MjEyMTczOTM5WhcNNDEwMjEyMTczOTM5WjB8MQswCQYDVQQGEwJVUzEOMAwGA1UECAwFVGV4YXMx
EDAOBgNVBAcMB0hvdXN0b24xGDAWBgNVBAoMD1NTTCBDb3Jwb3JhdGlvbjExMC8GA1UEAwwoU1NM
LmNvbSBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IFJTQTCCAiIwDQYJKoZIhvcNAQEBBQAD
ggIPADCCAgoCggIBAPkP3aMrfcvQKv7sZ4Wm5y4bunfh4/WvpOz6Sl2RxFdHaxh3a3by/ZPkPQ/C
Fp4LZsNWlJ4Xg4XOVu/yFv0AYvUiCVToZRdOQbngT0aXqhvIuG5iXmmxX9sqAn78bMrzQdjt0Oj8
P2FI7bADFB0QDksZ4LtO7IZl/zbzXmcCC52GVWH9ejjt/uIZALdvoVBidXQ8oPrIJZK0bnoix/ge
oeOy3ZExqysdBP+lSgQ36YWkMyv94tZVNHwZpEpox7Ko07fKoZOI68GXvIz5HdkihCR0xwQ9aqkp
k8zruFvh/l8lqjRYyMEjVJ0bmBHDOJx+PYZspQ9AhnwC9FwCTyjLrnGfDzrIM/4RJTXq/LrFYD3Z
fBjVsqnTdXgDciLKOsMf7yzlLqn6niy2UUb9rwPW6mBo6oUWNmuF6R7As93EJNyAKoFBbZQ+yODJ
gUEAnl6/f8UImKIYLEJAs/lvOCdLToD0PYFH4Ih86hzOtXVcUS4cK38acijnALXRdMbX5J+tB5O2
UzU1/Dfkw/ZdFr4hc96SCvigY2q8lpJqPvi8ZVWb3vUNiSYE/CUapiVpy8JtynziWV+XrOvvLsi8
1xtZPCvM8hnIk2snYxnP/Okm+Mpxm3+T/jRnhE6Z6/yzeAkzcLpmpnbtG3PrGqUNxCITIJRWCk4s
bE6x/c+cCbqiM+2HAgMBAAGjYzBhMB0GA1UdDgQWBBTdBAkHovV6fVJTEpKV7jiAJQ2mWTAPBgNV
HRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFN0ECQei9Xp9UlMSkpXuOIAlDaZZMA4GA1UdDwEB/wQE
AwIBhjANBgkqhkiG9w0BAQsFAAOCAgEAIBgRlCn7Jp0cHh5wYfGVcpNxJK1ok1iOMq8bs3AD/CUr
dIWQPXhq9LmLpZc7tRiRux6n+UBbkflVma8eEdBcHadm47GUBwwyOabqG7B52B2ccETjit3E+ZUf
ijhDPwGFpUenPUayvOUiaPd7nNgsPgohyC0zrL/FgZkxdMF1ccW+sfAjRfSda/wZY52jvATGGAsl
u1OJD7OAUN5F7kR/q5R4ZJjT9ijdh9hwZXT7DrkT66cPYakylszeu+1jTBi7qUD3oFRuIIhxdRjq
erQ0cuAjJ3dctpDqhiVAq+8zD8ufgr6iIPv2tS0a5sKFsXQP+8hlAqRSAUfdSSLBv9jra6x+3uxj
MxW3IwiPxg+NQVrdjsW5j+VFP3jbutIbQLH+cU0/4IGiul607BXgk90IH37hVZkLId6Tngr75qNJ
vTYw/ud3sqB1l7UtgYgXZSD32pAAn8lSzDLKNXz1PQ/YK9f1JmzJBjSWFupwWRoyeXkLtoh/D1JI
Pb9s2KJELtFOt3JY04kTlf5Eq/jXixtunLwsoFvVagCvXzfh1foQC5ichucmj87w7G6KVwuA406y
wKBjYZC6VWg3dGq2ktufoYYitmUnDuy2n0Jg5GfCtdpBC8TTi2EbvPofkSvXRAdeuims2cXp71NI
WuuA8ShYIc2wBlX7Jz9TkHCpBB5XJ7k=
-----END CERTIFICATE-----

SSL.com Root Certification Authority ECC
========================================
-----BEGIN CERTIFICATE-----
MIICjTCCAhSgAwIBAgIIdebfy8FoW6gwCgYIKoZIzj0EAwIwfDELMAkGA1UEBhMCVVMxDjAMBgNV
BAgMBVRleGFzMRAwDgYDVQQHDAdIb3VzdG9uMRgwFgYDVQQKDA9TU0wgQ29ycG9yYXRpb24xMTAv
BgNVBAMMKFNTTC5jb20gUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSBFQ0MwHhcNMTYwMjEy
MTgxNDAzWhcNNDEwMjEyMTgxNDAzWjB8MQswCQYDVQQGEwJVUzEOMAwGA1UECAwFVGV4YXMxEDAO
BgNVBAcMB0hvdXN0b24xGDAWBgNVBAoMD1NTTCBDb3Jwb3JhdGlvbjExMC8GA1UEAwwoU1NMLmNv
bSBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IEVDQzB2MBAGByqGSM49AgEGBSuBBAAiA2IA
BEVuqVDEpiM2nl8ojRfLliJkP9x6jh3MCLOicSS6jkm5BBtHllirLZXI7Z4INcgn64mMU1jrYor+
8FsPazFSY0E7ic3s7LaNGdM0B9y7xgZ/wkWV7Mt/qCPgCemB+vNH06NjMGEwHQYDVR0OBBYEFILR
hXMw5zUE044CkvvlpNHEIejNMA8GA1UdEwEB/wQFMAMBAf8wHwYDVR0jBBgwFoAUgtGFczDnNQTT
jgKS++Wk0cQh6M0wDgYDVR0PAQH/BAQDAgGGMAoGCCqGSM49BAMCA2cAMGQCMG/n61kRpGDPYbCW
e+0F+S8Tkdzt5fxQaxFGRrMcIQBiu77D5+jNB5n5DQtdcj7EqgIwH7y6C+IwJPt8bYBVCpk+gA0z
5Wajs6O7pdWLjwkspl1+4vAHCGht0nxpbl/f5Wpl
-----END CERTIFICATE-----

SSL.com EV Root Certification Authority RSA R2
==============================================
-----BEGIN CERTIFICATE-----
MIIF6zCCA9OgAwIBAgIIVrYpzTS8ePYwDQYJKoZIhvcNAQELBQAwgYIxCzAJBgNVBAYTAlVTMQ4w
DAYDVQQIDAVUZXhhczEQMA4GA1UEBwwHSG91c3RvbjEYMBYGA1UECgwPU1NMIENvcnBvcmF0aW9u
MTcwNQYDVQQDDC5TU0wuY29tIEVWIFJvb3QgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgUlNBIFIy
MB4XDTE3MDUzMTE4MTQzN1oXDTQyMDUzMDE4MTQzN1owgYIxCzAJBgNVBAYTAlVTMQ4wDAYDVQQI
DAVUZXhhczEQMA4GA1UEBwwHSG91c3RvbjEYMBYGA1UECgwPU1NMIENvcnBvcmF0aW9uMTcwNQYD
VQQDDC5TU0wuY29tIEVWIFJvb3QgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgUlNBIFIyMIICIjAN
BgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAjzZlQOHWTcDXtOlG2mvqM0fNTPl9fb69LT3w23jh
hqXZuglXaO1XPqDQCEGD5yhBJB/jchXQARr7XnAjssufOePPxU7Gkm0mxnu7s9onnQqG6YE3Bf7w
cXHswxzpY6IXFJ3vG2fThVUCAtZJycxa4bH3bzKfydQ7iEGonL3Lq9ttewkfokxykNorCPzPPFTO
Zw+oz12WGQvE43LrrdF9HSfvkusQv1vrO6/PgN3B0pYEW3p+pKk8OHakYo6gOV7qd89dAFmPZiw+
B6KjBSYRaZfqhbcPlgtLyEDhULouisv3D5oi53+aNxPN8k0TayHRwMwi8qFG9kRpnMphNQcAb9Zh
CBHqurj26bNg5U257J8UZslXWNvNh2n4ioYSA0e/ZhN2rHd9NCSFg83XqpyQGp8hLH94t2S42Oim
9HizVcuE0jLEeK6jj2HdzghTreyI/BXkmg3mnxp3zkyPuBQVPWKchjgGAGYS5Fl2WlPAApiiECto
RHuOec4zSnaqW4EWG7WK2NAAe15itAnWhmMOpgWVSbooi4iTsjQc2KRVbrcc0N6ZVTsj9CLg+Slm
JuwgUHfbSguPvuUCYHBBXtSuUDkiFCbLsjtzdFVHB3mBOagwE0TlBIqulhMlQg+5U8Sb/M3kHN48
+qvWBkofZ6aYMBzdLNvcGJVXZsb/XItW9XcCAwEAAaNjMGEwDwYDVR0TAQH/BAUwAwEB/zAfBgNV
HSMEGDAWgBT5YLvU49U09rj1BoAlp3PbRmmonjAdBgNVHQ4EFgQU+WC71OPVNPa49QaAJadz20Zp
qJ4wDgYDVR0PAQH/BAQDAgGGMA0GCSqGSIb3DQEBCwUAA4ICAQBWs47LCp1Jjr+kxJG7ZhcFUZh1
++VQLHqe8RT6q9OKPv+RKY9ji9i0qVQBDb6Thi/5Sm3HXvVX+cpVHBK+Rw82xd9qt9t1wkclf7nx
Y/hoLVUE0fKNsKTPvDxeH3jnpaAgcLAExbf3cqfeIg29MyVGjGSSJuM+LmOW2puMPfgYCdcDzH2G
guDKBAdRUNf/ktUM79qGn5nX67evaOI5JpS6aLe/g9Pqemc9YmeuJeVy6OLk7K4S9ksrPJ/psEDz
OFSz/bdoyNrGj1E8svuR3Bznm53htw1yj+KkxKl4+esUrMZDBcJlOSgYAsOCsp0FvmXtll9ldDz7
CTUue5wT/RsPXcdtgTpWD8w74a8CLyKsRspGPKAcTNZEtF4uXBVmCeEmKf7GUmG6sXP/wwyc5Wxq
lD8UykAWlYTzWamsX0xhk23RO8yilQwipmdnRC652dKKQbNmC1r7fSOl8hqw/96bg5Qu0T/fkreR
rwU7ZcegbLHNYhLDkBvjJc40vG93drEQw/cFGsDWr3RiSBd3kmmQYRzelYB0VI8YHMPzA9C/pEN1
hlMYegouCRw2n5H9gooiS9EOUCXdywMMF8mDAAhONU2Ki+3wApRmLER/y5UnlhetCTCstnEXbosX
9hwJ1C07mKVx01QT2WDz9UtmT/rx7iASjbSsV7FFY6GsdqnC+w==
-----END CERTIFICATE-----

SSL.com EV Root Certification Authority ECC
===========================================
-----BEGIN CERTIFICATE-----
MIIClDCCAhqgAwIBAgIILCmcWxbtBZUwCgYIKoZIzj0EAwIwfzELMAkGA1UEBhMCVVMxDjAMBgNV
BAgMBVRleGFzMRAwDgYDVQQHDAdIb3VzdG9uMRgwFgYDVQQKDA9TU0wgQ29ycG9yYXRpb24xNDAy
BgNVBAMMK1NTTC5jb20gRVYgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSBFQ0MwHhcNMTYw
MjEyMTgxNTIzWhcNNDEwMjEyMTgxNTIzWjB/MQswCQYDVQQGEwJVUzEOMAwGA1UECAwFVGV4YXMx
EDAOBgNVBAcMB0hvdXN0b24xGDAWBgNVBAoMD1NTTCBDb3Jwb3JhdGlvbjE0MDIGA1UEAwwrU1NM
LmNvbSBFViBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IEVDQzB2MBAGByqGSM49AgEGBSuB
BAAiA2IABKoSR5CYG/vvw0AHgyBO8TCCogbR8pKGYfL2IWjKAMTH6kMAVIbc/R/fALhBYlzccBYy
3h+Z1MzFB8gIH2EWB1E9fVwHU+M1OIzfzZ/ZLg1KthkuWnBaBu2+8KGwytAJKaNjMGEwHQYDVR0O
BBYEFFvKXuXe0oGqzagtZFG22XKbl+ZPMA8GA1UdEwEB/wQFMAMBAf8wHwYDVR0jBBgwFoAUW8pe
5d7SgarNqC1kUbbZcpuX5k8wDgYDVR0PAQH/BAQDAgGGMAoGCCqGSM49BAMCA2gAMGUCMQCK5kCJ
N+vp1RPZytRrJPOwPYdGWBrssd9v+1a6cGvHOMzosYxPD/fxZ3YOg9AeUY8CMD32IygmTMZgh5Mm
m7I1HrrW9zzRHM76JTymGoEVW/MSD2zuZYrJh6j5B+BimoxcSg==
-----END CERTIFICATE-----

GlobalSign Root CA - R6
=======================
-----BEGIN CERTIFICATE-----
MIIFgzCCA2ugAwIBAgIORea7A4Mzw4VlSOb/RVEwDQYJKoZIhvcNAQEMBQAwTDEgMB4GA1UECxMX
R2xvYmFsU2lnbiBSb290IENBIC0gUjYxEzARBgNVBAoTCkdsb2JhbFNpZ24xEzARBgNVBAMTCkds
b2JhbFNpZ24wHhcNMTQxMjEwMDAwMDAwWhcNMzQxMjEwMDAwMDAwWjBMMSAwHgYDVQQLExdHbG9i
YWxTaWduIFJvb3QgQ0EgLSBSNjETMBEGA1UEChMKR2xvYmFsU2lnbjETMBEGA1UEAxMKR2xvYmFs
U2lnbjCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAJUH6HPKZvnsFMp7PPcNCPG0RQss
grRIxutbPK6DuEGSMxSkb3/pKszGsIhrxbaJ0cay/xTOURQh7ErdG1rG1ofuTToVBu1kZguSgMpE
3nOUTvOniX9PeGMIyBJQbUJmL025eShNUhqKGoC3GYEOfsSKvGRMIRxDaNc9PIrFsmbVkJq3MQbF
vuJtMgamHvm566qjuL++gmNQ0PAYid/kD3n16qIfKtJwLnvnvJO7bVPiSHyMEAc4/2ayd2F+4OqM
PKq0pPbzlUoSB239jLKJz9CgYXfIWHSw1CM69106yqLbnQneXUQtkPGBzVeS+n68UARjNN9rkxi+
azayOeSsJDa38O+2HBNXk7besvjihbdzorg1qkXy4J02oW9UivFyVm4uiMVRQkQVlO6jxTiWm05O
WgtH8wY2SXcwvHE35absIQh1/OZhFj931dmRl4QKbNQCTXTAFO39OfuD8l4UoQSwC+n+7o/hbguy
CLNhZglqsQY6ZZZZwPA1/cnaKI0aEYdwgQqomnUdnjqGBQCe24DWJfncBZ4nWUx2OVvq+aWh2IMP
0f/fMBH5hc8zSPXKbWQULHpYT9NLCEnFlWQaYw55PfWzjMpYrZxCRXluDocZXFSxZba/jJvcE+kN
b7gu3GduyYsRtYQUigAZcIN5kZeR1BonvzceMgfYFGM8KEyvAgMBAAGjYzBhMA4GA1UdDwEB/wQE
AwIBBjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBSubAWjkxPioufi1xzWx/B/yGdToDAfBgNV
HSMEGDAWgBSubAWjkxPioufi1xzWx/B/yGdToDANBgkqhkiG9w0BAQwFAAOCAgEAgyXt6NH9lVLN
nsAEoJFp5lzQhN7craJP6Ed41mWYqVuoPId8AorRbrcWc+ZfwFSY1XS+wc3iEZGtIxg93eFyRJa0
lV7Ae46ZeBZDE1ZXs6KzO7V33EByrKPrmzU+sQghoefEQzd5Mr6155wsTLxDKZmOMNOsIeDjHfrY
BzN2VAAiKrlNIC5waNrlU/yDXNOd8v9EDERm8tLjvUYAGm0CuiVdjaExUd1URhxN25mW7xocBFym
Fe944Hn+Xds+qkxV/ZoVqW/hpvvfcDDpw+5CRu3CkwWJ+n1jez/QcYF8AOiYrg54NMMl+68KnyBr
3TsTjxKM4kEaSHpzoHdpx7Zcf4LIHv5YGygrqGytXm3ABdJ7t+uA/iU3/gKbaKxCXcPu9czc8FB1
0jZpnOZ7BN9uBmm23goJSFmH63sUYHpkqmlD75HHTOwY3WzvUy2MmeFe8nI+z1TIvWfspA9MRf/T
uTAjB0yPEL+GltmZWrSZVxykzLsViVO6LAUP5MSeGbEYNNVMnbrt9x+vJJUEeKgDu+6B5dpffItK
oZB0JaezPkvILFa9x8jvOOJckvB595yEunQtYQEgfn7R8k8HWV+LLUNS60YMlOH1Zkd5d9VUWx+t
JDfLRVpOoERIyNiwmcUVhAn21klJwGW45hpxbqCo8YLoRT5s1gLXCmeDBVrJpBA=
-----END CERTIFICATE-----

OISTE WISeKey Global Root GC CA
===============================
-----BEGIN CERTIFICATE-----
MIICaTCCAe+gAwIBAgIQISpWDK7aDKtARb8roi066jAKBggqhkjOPQQDAzBtMQswCQYDVQQGEwJD
SDEQMA4GA1UEChMHV0lTZUtleTEiMCAGA1UECxMZT0lTVEUgRm91bmRhdGlvbiBFbmRvcnNlZDEo
MCYGA1UEAxMfT0lTVEUgV0lTZUtleSBHbG9iYWwgUm9vdCBHQyBDQTAeFw0xNzA1MDkwOTQ4MzRa
Fw00MjA1MDkwOTU4MzNaMG0xCzAJBgNVBAYTAkNIMRAwDgYDVQQKEwdXSVNlS2V5MSIwIAYDVQQL
ExlPSVNURSBGb3VuZGF0aW9uIEVuZG9yc2VkMSgwJgYDVQQDEx9PSVNURSBXSVNlS2V5IEdsb2Jh
bCBSb290IEdDIENBMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAETOlQwMYPchi82PG6s4nieUqjFqdr
VCTbUf/q9Akkwwsin8tqJ4KBDdLArzHkdIJuyiXZjHWd8dvQmqJLIX4Wp2OQ0jnUsYd4XxiWD1Ab
NTcPasbc2RNNpI6QN+a9WzGRo1QwUjAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAd
BgNVHQ4EFgQUSIcUrOPDnpBgOtfKie7TrYy0UGYwEAYJKwYBBAGCNxUBBAMCAQAwCgYIKoZIzj0E
AwMDaAAwZQIwJsdpW9zV57LnyAyMjMPdeYwbY9XJUpROTYJKcx6ygISpJcBMWm1JKWB4E+J+SOtk
AjEA2zQgMgj/mkkCtojeFK9dbJlxjRo/i9fgojaGHAeCOnZT/cKi7e97sIBPWA9LUzm9
-----END CERTIFICATE-----

UCA Global G2 Root
==================
-----BEGIN CERTIFICATE-----
MIIFRjCCAy6gAwIBAgIQXd+x2lqj7V2+WmUgZQOQ7zANBgkqhkiG9w0BAQsFADA9MQswCQYDVQQG
EwJDTjERMA8GA1UECgwIVW5pVHJ1c3QxGzAZBgNVBAMMElVDQSBHbG9iYWwgRzIgUm9vdDAeFw0x
NjAzMTEwMDAwMDBaFw00MDEyMzEwMDAwMDBaMD0xCzAJBgNVBAYTAkNOMREwDwYDVQQKDAhVbmlU
cnVzdDEbMBkGA1UEAwwSVUNBIEdsb2JhbCBHMiBSb290MIICIjANBgkqhkiG9w0BAQEFAAOCAg8A
MIICCgKCAgEAxeYrb3zvJgUno4Ek2m/LAfmZmqkywiKHYUGRO8vDaBsGxUypK8FnFyIdK+35KYmT
oni9kmugow2ifsqTs6bRjDXVdfkX9s9FxeV67HeToI8jrg4aA3++1NDtLnurRiNb/yzmVHqUwCoV
8MmNsHo7JOHXaOIxPAYzRrZUEaalLyJUKlgNAQLx+hVRZ2zA+te2G3/RVogvGjqNO7uCEeBHANBS
h6v7hn4PJGtAnTRnvI3HLYZveT6OqTwXS3+wmeOwcWDcC/Vkw85DvG1xudLeJ1uK6NjGruFZfc8o
LTW4lVYa8bJYS7cSN8h8s+1LgOGN+jIjtm+3SJUIsUROhYw6AlQgL9+/V087OpAh18EmNVQg7Mc/
R+zvWr9LesGtOxdQXGLYD0tK3Cv6brxzks3sx1DoQZbXqX5t2Okdj4q1uViSukqSKwxW/YDrCPBe
KW4bHAyvj5OJrdu9o54hyokZ7N+1wxrrFv54NkzWbtA+FxyQF2smuvt6L78RHBgOLXMDj6DlNaBa
4kx1HXHhOThTeEDMg5PXCp6dW4+K5OXgSORIskfNTip1KnvyIvbJvgmRlld6iIis7nCs+dwp4wwc
OxJORNanTrAmyPPZGpeRaOrvjUYG0lZFWJo8DA+DuAUlwznPO6Q0ibd5Ei9Hxeepl2n8pndntd97
8XplFeRhVmUCAwEAAaNCMEAwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0O
BBYEFIHEjMz15DD/pQwIX4wVZyF0Ad/fMA0GCSqGSIb3DQEBCwUAA4ICAQATZSL1jiutROTL/7lo
5sOASD0Ee/ojL3rtNtqyzm325p7lX1iPyzcyochltq44PTUbPrw7tgTQvPlJ9Zv3hcU2tsu8+Mg5
1eRfB70VVJd0ysrtT7q6ZHafgbiERUlMjW+i67HM0cOU2kTC5uLqGOiiHycFutfl1qnN3e92mI0A
Ds0b+gO3joBYDic/UvuUospeZcnWhNq5NXHzJsBPd+aBJ9J3O5oUb3n09tDh05S60FdRvScFDcH9
yBIw7m+NESsIndTUv4BFFJqIRNow6rSn4+7vW4LVPtateJLbXDzz2K36uGt/xDYotgIVilQsnLAX
c47QN6MUPJiVAAwpBVueSUmxX8fjy88nZY41F7dXyDDZQVu5FLbowg+UMaeUmMxq67XhJ/UQqAHo
jhJi6IjMtX9Gl8CbEGY4GjZGXyJoPd/JxhMnq1MGrKI8hgZlb7F+sSlEmqO6SWkoaY/X5V+tBIZk
bxqgDMUIYs6Ao9Dz7GjevjPHF1t/gMRMTLGmhIrDO7gJzRSBuhjjVFc2/tsvfEehOjPI+Vg7RE+x
ygKJBJYoaMVLuCaJu9YzL1DV/pqJuhgyklTGW+Cd+V7lDSKb9triyCGyYiGqhkCyLmTTX8jjfhFn
RR8F/uOi77Oos/N9j/gMHyIfLXC0uAE0djAA5SN4p1bXUB+K+wb1whnw0A==
-----END CERTIFICATE-----

UCA Extended Validation Root
============================
-----BEGIN CERTIFICATE-----
MIIFWjCCA0KgAwIBAgIQT9Irj/VkyDOeTzRYZiNwYDANBgkqhkiG9w0BAQsFADBHMQswCQYDVQQG
EwJDTjERMA8GA1UECgwIVW5pVHJ1c3QxJTAjBgNVBAMMHFVDQSBFeHRlbmRlZCBWYWxpZGF0aW9u
IFJvb3QwHhcNMTUwMzEzMDAwMDAwWhcNMzgxMjMxMDAwMDAwWjBHMQswCQYDVQQGEwJDTjERMA8G
A1UECgwIVW5pVHJ1c3QxJTAjBgNVBAMMHFVDQSBFeHRlbmRlZCBWYWxpZGF0aW9uIFJvb3QwggIi
MA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCpCQcoEwKwmeBkqh5DFnpzsZGgdT6o+uM4AHrs
iWogD4vFsJszA1qGxliG1cGFu0/GnEBNyr7uaZa4rYEwmnySBesFK5pI0Lh2PpbIILvSsPGP2KxF
Rv+qZ2C0d35qHzwaUnoEPQc8hQ2E0B92CvdqFN9y4zR8V05WAT558aopO2z6+I9tTcg1367r3CTu
eUWnhbYFiN6IXSV8l2RnCdm/WhUFhvMJHuxYMjMR83dksHYf5BA1FxvyDrFspCqjc/wJHx4yGVMR
59mzLC52LqGj3n5qiAno8geK+LLNEOfic0CTuwjRP+H8C5SzJe98ptfRr5//lpr1kXuYC3fUfugH
0mK1lTnj8/FtDw5lhIpjVMWAtuCeS31HJqcBCF3RiJ7XwzJE+oJKCmhUfzhTA8ykADNkUVkLo4KR
el7sFsLzKuZi2irbWWIQJUoqgQtHB0MGcIfS+pMRKXpITeuUx3BNr2fVUbGAIAEBtHoIppB/TuDv
B0GHr2qlXov7z1CymlSvw4m6WC31MJixNnI5fkkE/SmnTHnkBVfblLkWU41Gsx2VYVdWf6/wFlth
WG82UBEL2KwrlRYaDh8IzTY0ZRBiZtWAXxQgXy0MoHgKaNYs1+lvK9JKBZP8nm9rZ/+I8U6laUpS
NwXqxhaN0sSZ0YIrO7o1dfdRUVjzyAfd5LQDfwIDAQABo0IwQDAdBgNVHQ4EFgQU2XQ65DA9DfcS
3H5aBZ8eNJr34RQwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAYYwDQYJKoZIhvcNAQEL
BQADggIBADaNl8xCFWQpN5smLNb7rhVpLGsaGvdftvkHTFnq88nIua7Mui563MD1sC3AO6+fcAUR
ap8lTwEpcOPlDOHqWnzcSbvBHiqB9RZLcpHIojG5qtr8nR/zXUACE/xOHAbKsxSQVBcZEhrxH9cM
aVr2cXj0lH2RC47skFSOvG+hTKv8dGT9cZr4QQehzZHkPJrgmzI5c6sq1WnIeJEmMX3ixzDx/BR4
dxIOE/TdFpS/S2d7cFOFyrC78zhNLJA5wA3CXWvp4uXViI3WLL+rG761KIcSF3Ru/H38j9CHJrAb
+7lsq+KePRXBOy5nAliRn+/4Qh8st2j1da3Ptfb/EX3C8CSlrdP6oDyp+l3cpaDvRKS+1ujl5BOW
F3sGPjLtx7dCvHaj2GU4Kzg1USEODm8uNBNA4StnDG1KQTAYI1oyVZnJF+A83vbsea0rWBmirSwi
GpWOvpaQXUJXxPkUAzUrHC1RVwinOt4/5Mi0A3PCwSaAuwtCH60NryZy2sy+s6ODWA2CxR9GUeOc
GMyNm43sSet1UNWMKFnKdDTajAshqx7qG+XH/RU+wBeq+yNuJkbL+vmxcmtpzyKEC2IPrNkZAJSi
djzULZrtBJ4tBmIQN1IchXIbJ+XMxjHsN+xjWZsLHXbMfjKaiJUINlK73nZfdklJrX+9ZSCyycEr
dhh2n1ax
-----END CERTIFICATE-----

Certigna Root CA
================
-----BEGIN CERTIFICATE-----
MIIGWzCCBEOgAwIBAgIRAMrpG4nxVQMNo+ZBbcTjpuEwDQYJKoZIhvcNAQELBQAwWjELMAkGA1UE
BhMCRlIxEjAQBgNVBAoMCURoaW15b3RpczEcMBoGA1UECwwTMDAwMiA0ODE0NjMwODEwMDAzNjEZ
MBcGA1UEAwwQQ2VydGlnbmEgUm9vdCBDQTAeFw0xMzEwMDEwODMyMjdaFw0zMzEwMDEwODMyMjda
MFoxCzAJBgNVBAYTAkZSMRIwEAYDVQQKDAlEaGlteW90aXMxHDAaBgNVBAsMEzAwMDIgNDgxNDYz
MDgxMDAwMzYxGTAXBgNVBAMMEENlcnRpZ25hIFJvb3QgQ0EwggIiMA0GCSqGSIb3DQEBAQUAA4IC
DwAwggIKAoICAQDNGDllGlmx6mQWDoyUJJV8g9PFOSbcDO8WV43X2KyjQn+Cyu3NW9sOty3tRQgX
stmzy9YXUnIo245Onoq2C/mehJpNdt4iKVzSs9IGPjA5qXSjklYcoW9MCiBtnyN6tMbaLOQdLNyz
KNAT8kxOAkmhVECe5uUFoC2EyP+YbNDrihqECB63aCPuI9Vwzm1RaRDuoXrC0SIxwoKF0vJVdlB8
JXrJhFwLrN1CTivngqIkicuQstDuI7pmTLtipPlTWmR7fJj6o0ieD5Wupxj0auwuA0Wv8HT4Ks16
XdG+RCYyKfHx9WzMfgIhC59vpD++nVPiz32pLHxYGpfhPTc3GGYo0kDFUYqMwy3OU4gkWGQwFsWq
4NYKpkDfePb1BHxpE4S80dGnBs8B92jAqFe7OmGtBIyT46388NtEbVncSVmurJqZNjBBe3YzIoej
wpKGbvlw7q6Hh5UbxHq9MfPU0uWZ/75I7HX1eBYdpnDBfzwboZL7z8g81sWTCo/1VTp2lc5ZmIoJ
lXcymoO6LAQ6l73UL77XbJuiyn1tJslV1c/DeVIICZkHJC1kJWumIWmbat10TWuXekG9qxf5kBdI
jzb5LdXF2+6qhUVB+s06RbFo5jZMm5BX7CO5hwjCxAnxl4YqKE3idMDaxIzb3+KhF1nOJFl0Mdp/
/TBt2dzhauH8XwIDAQABo4IBGjCCARYwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYw
HQYDVR0OBBYEFBiHVuBud+4kNTxOc5of1uHieX4rMB8GA1UdIwQYMBaAFBiHVuBud+4kNTxOc5of
1uHieX4rMEQGA1UdIAQ9MDswOQYEVR0gADAxMC8GCCsGAQUFBwIBFiNodHRwczovL3d3d3cuY2Vy
dGlnbmEuZnIvYXV0b3JpdGVzLzBtBgNVHR8EZjBkMC+gLaArhilodHRwOi8vY3JsLmNlcnRpZ25h
LmZyL2NlcnRpZ25hcm9vdGNhLmNybDAxoC+gLYYraHR0cDovL2NybC5kaGlteW90aXMuY29tL2Nl
cnRpZ25hcm9vdGNhLmNybDANBgkqhkiG9w0BAQsFAAOCAgEAlLieT/DjlQgi581oQfccVdV8AOIt
OoldaDgvUSILSo3L6btdPrtcPbEo/uRTVRPPoZAbAh1fZkYJMyjhDSSXcNMQH+pkV5a7XdrnxIxP
TGRGHVyH41neQtGbqH6mid2PHMkwgu07nM3A6RngatgCdTer9zQoKJHyBApPNeNgJgH60BGM+RFq
7q89w1DTj18zeTyGqHNFkIwgtnJzFyO+B2XleJINugHA64wcZr+shncBlA2c5uk5jR+mUYyZDDl3
4bSb+hxnV29qao6pK0xXeXpXIs/NX2NGjVxZOob4Mkdio2cNGJHc+6Zr9UhhcyNZjgKnvETq9Emd
8VRY+WCv2hikLyhF3HqgiIZd8zvn/yk1gPxkQ5Tm4xxvvq0OKmOZK8l+hfZx6AYDlf7ej0gcWtSS
6Cvu5zHbugRqh5jnxV/vfaci9wHYTfmJ0A6aBVmknpjZbyvKcL5kwlWj9Omvw5Ip3IgWJJk8jSaY
tlu3zM63Nwf9JtmYhST/WSMDmu2dnajkXjjO11INb9I/bbEFa0nOipFGc/T2L/Coc3cOZayhjWZS
aX5LaAzHHjcng6WMxwLkFM1JAbBzs/3GkDpv0mztO+7skb6iQ12LAEpmJURw3kAP+HwV96LOPNde
E4yBFxgX0b3xdxA61GU5wSesVywlVP+i2k+KYTlerj1KjL0=
-----END CERTIFICATE-----

emSign Root CA - G1
===================
-----BEGIN CERTIFICATE-----
MIIDlDCCAnygAwIBAgIKMfXkYgxsWO3W2DANBgkqhkiG9w0BAQsFADBnMQswCQYDVQQGEwJJTjET
MBEGA1UECxMKZW1TaWduIFBLSTElMCMGA1UEChMcZU11ZGhyYSBUZWNobm9sb2dpZXMgTGltaXRl
ZDEcMBoGA1UEAxMTZW1TaWduIFJvb3QgQ0EgLSBHMTAeFw0xODAyMTgxODMwMDBaFw00MzAyMTgx
ODMwMDBaMGcxCzAJBgNVBAYTAklOMRMwEQYDVQQLEwplbVNpZ24gUEtJMSUwIwYDVQQKExxlTXVk
aHJhIFRlY2hub2xvZ2llcyBMaW1pdGVkMRwwGgYDVQQDExNlbVNpZ24gUm9vdCBDQSAtIEcxMIIB
IjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAk0u76WaK7p1b1TST0Bsew+eeuGQzf2N4aLTN
LnF115sgxk0pvLZoYIr3IZpWNVrzdr3YzZr/k1ZLpVkGoZM0Kd0WNHVO8oG0x5ZOrRkVUkr+PHB1
cM2vK6sVmjM8qrOLqs1D/fXqcP/tzxE7lM5OMhbTI0Aqd7OvPAEsbO2ZLIvZTmmYsvePQbAyeGHW
DV/D+qJAkh1cF+ZwPjXnorfCYuKrpDhMtTk1b+oDafo6VGiFbdbyL0NVHpENDtjVaqSW0RM8LHhQ
6DqS0hdW5TUaQBw+jSztOd9C4INBdN+jzcKGYEho42kLVACL5HZpIQ15TjQIXhTCzLG3rdd8cIrH
hQIDAQABo0IwQDAdBgNVHQ4EFgQU++8Nhp6w492pufEhF38+/PB3KxowDgYDVR0PAQH/BAQDAgEG
MA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBAFn/8oz1h31xPaOfG1vR2vjTnGs2
vZupYeveFix0PZ7mddrXuqe8QhfnPZHr5X3dPpzxz5KsbEjMwiI/aTvFthUvozXGaCocV685743Q
NcMYDHsAVhzNixl03r4PEuDQqqE/AjSxcM6dGNYIAwlG7mDgfrbESQRRfXBgvKqy/3lyeqYdPV8q
+Mri/Tm3R7nrft8EI6/6nAYH6ftjk4BAtcZsCjEozgyfz7MjNYBBjWzEN3uBL4ChQEKF6dk4jeih
U80Bv2noWgbyRQuQ+q7hv53yrlc8pa6yVvSLZUDp/TGBLPQ5Cdjua6e0ph0VpZj3AYHYhX3zUVxx
iN66zB+Afko=
-----END CERTIFICATE-----

emSign ECC Root CA - G3
=======================
-----BEGIN CERTIFICATE-----
MIICTjCCAdOgAwIBAgIKPPYHqWhwDtqLhDAKBggqhkjOPQQDAzBrMQswCQYDVQQGEwJJTjETMBEG
A1UECxMKZW1TaWduIFBLSTElMCMGA1UEChMcZU11ZGhyYSBUZWNobm9sb2dpZXMgTGltaXRlZDEg
MB4GA1UEAxMXZW1TaWduIEVDQyBSb290IENBIC0gRzMwHhcNMTgwMjE4MTgzMDAwWhcNNDMwMjE4
MTgzMDAwWjBrMQswCQYDVQQGEwJJTjETMBEGA1UECxMKZW1TaWduIFBLSTElMCMGA1UEChMcZU11
ZGhyYSBUZWNobm9sb2dpZXMgTGltaXRlZDEgMB4GA1UEAxMXZW1TaWduIEVDQyBSb290IENBIC0g
RzMwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAAQjpQy4LRL1KPOxst3iAhKAnjlfSU2fySU0WXTsuwYc
58Byr+iuL+FBVIcUqEqy6HyC5ltqtdyzdc6LBtCGI79G1Y4PPwT01xySfvalY8L1X44uT6EYGQIr
MgqCZH0Wk9GjQjBAMB0GA1UdDgQWBBR8XQKEE9TMipuBzhccLikenEhjQjAOBgNVHQ8BAf8EBAMC
AQYwDwYDVR0TAQH/BAUwAwEB/zAKBggqhkjOPQQDAwNpADBmAjEAvvNhzwIQHWSVB7gYboiFBS+D
CBeQyh+KTOgNG3qxrdWBCUfvO6wIBHxcmbHtRwfSAjEAnbpV/KlK6O3t5nYBQnvI+GDZjVGLVTv7
jHvrZQnD+JbNR6iC8hZVdyR+EhCVBCyj
-----END CERTIFICATE-----

emSign Root CA - C1
===================
-----BEGIN CERTIFICATE-----
MIIDczCCAlugAwIBAgILAK7PALrEzzL4Q7IwDQYJKoZIhvcNAQELBQAwVjELMAkGA1UEBhMCVVMx
EzARBgNVBAsTCmVtU2lnbiBQS0kxFDASBgNVBAoTC2VNdWRocmEgSW5jMRwwGgYDVQQDExNlbVNp
Z24gUm9vdCBDQSAtIEMxMB4XDTE4MDIxODE4MzAwMFoXDTQzMDIxODE4MzAwMFowVjELMAkGA1UE
BhMCVVMxEzARBgNVBAsTCmVtU2lnbiBQS0kxFDASBgNVBAoTC2VNdWRocmEgSW5jMRwwGgYDVQQD
ExNlbVNpZ24gUm9vdCBDQSAtIEMxMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAz+up
ufGZBczYKCFK83M0UYRWEPWgTywS4/oTmifQz/l5GnRfHXk5/Fv4cI7gklL35CX5VIPZHdPIWoU/
Xse2B+4+wM6ar6xWQio5JXDWv7V7Nq2s9nPczdcdioOl+yuQFTdrHCZH3DspVpNqs8FqOp099cGX
OFgFixwR4+S0uF2FHYP+eF8LRWgYSKVGczQ7/g/IdrvHGPMF0Ybzhe3nudkyrVWIzqa2kbBPrH4V
I5b2P/AgNBbeCsbEBEV5f6f9vtKppa+cxSMq9zwhbL2vj07FOrLzNBL834AaSaTUqZX3noleooms
lMuoaJuvimUnzYnu3Yy1aylwQ6BpC+S5DwIDAQABo0IwQDAdBgNVHQ4EFgQU/qHgcB4qAzlSWkK+
XJGFehiqTbUwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQELBQAD
ggEBAMJKVvoVIXsoounlHfv4LcQ5lkFMOycsxGwYFYDGrK9HWS8mC+M2sO87/kOXSTKZEhVb3xEp
/6tT+LvBeA+snFOvV71ojD1pM/CjoCNjO2RnIkSt1XHLVip4kqNPEjE2NuLe/gDEo2APJ62gsIq1
NnpSob0n9CAnYuhNlCQT5AoE6TyrLshDCUrGYQTlSTR+08TI9Q/Aqum6VF7zYytPT1DU/rl7mYw9
wC68AivTxEDkigcxHpvOJpkT+xHqmiIMERnHXhuBUDDIlhJu58tBf5E7oke3VIAb3ADMmpDqw8NQ
BmIMMMAVSKeoWXzhriKi4gp6D/piq1JM4fHfyr6DDUI=
-----END CERTIFICATE-----

emSign ECC Root CA - C3
=======================
-----BEGIN CERTIFICATE-----
MIICKzCCAbGgAwIBAgIKe3G2gla4EnycqDAKBggqhkjOPQQDAzBaMQswCQYDVQQGEwJVUzETMBEG
A1UECxMKZW1TaWduIFBLSTEUMBIGA1UEChMLZU11ZGhyYSBJbmMxIDAeBgNVBAMTF2VtU2lnbiBF
Q0MgUm9vdCBDQSAtIEMzMB4XDTE4MDIxODE4MzAwMFoXDTQzMDIxODE4MzAwMFowWjELMAkGA1UE
BhMCVVMxEzARBgNVBAsTCmVtU2lnbiBQS0kxFDASBgNVBAoTC2VNdWRocmEgSW5jMSAwHgYDVQQD
ExdlbVNpZ24gRUNDIFJvb3QgQ0EgLSBDMzB2MBAGByqGSM49AgEGBSuBBAAiA2IABP2lYa57JhAd
6bciMK4G9IGzsUJxlTm801Ljr6/58pc1kjZGDoeVjbk5Wum739D+yAdBPLtVb4OjavtisIGJAnB9
SMVK4+kiVCJNk7tCDK93nCOmfddhEc5lx/h//vXyqaNCMEAwHQYDVR0OBBYEFPtaSNCAIEDyqOkA
B2kZd6fmw/TPMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MAoGCCqGSM49BAMDA2gA
MGUCMQC02C8Cif22TGK6Q04ThHK1rt0c3ta13FaPWEBaLd4gTCKDypOofu4SQMfWh0/434UCMBwU
ZOR8loMRnLDRWmFLpg9J0wD8ofzkpf9/rdcw0Md3f76BB1UwUCAU9Vc4CqgxUQ==
-----END CERTIFICATE-----

Hongkong Post Root CA 3
=======================
-----BEGIN CERTIFICATE-----
MIIFzzCCA7egAwIBAgIUCBZfikyl7ADJk0DfxMauI7gcWqQwDQYJKoZIhvcNAQELBQAwbzELMAkG
A1UEBhMCSEsxEjAQBgNVBAgTCUhvbmcgS29uZzESMBAGA1UEBxMJSG9uZyBLb25nMRYwFAYDVQQK
Ew1Ib25na29uZyBQb3N0MSAwHgYDVQQDExdIb25na29uZyBQb3N0IFJvb3QgQ0EgMzAeFw0xNzA2
MDMwMjI5NDZaFw00MjA2MDMwMjI5NDZaMG8xCzAJBgNVBAYTAkhLMRIwEAYDVQQIEwlIb25nIEtv
bmcxEjAQBgNVBAcTCUhvbmcgS29uZzEWMBQGA1UEChMNSG9uZ2tvbmcgUG9zdDEgMB4GA1UEAxMX
SG9uZ2tvbmcgUG9zdCBSb290IENBIDMwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCz
iNfqzg8gTr7m1gNt7ln8wlffKWihgw4+aMdoWJwcYEuJQwy51BWy7sFOdem1p+/l6TWZ5Mwc50tf
jTMwIDNT2aa71T4Tjukfh0mtUC1Qyhi+AViiE3CWu4mIVoBc+L0sPOFMV4i707mV78vH9toxdCim
5lSJ9UExyuUmGs2C4HDaOym71QP1mbpV9WTRYA6ziUm4ii8F0oRFKHyPaFASePwLtVPLwpgchKOe
sL4jpNrcyCse2m5FHomY2vkALgbpDDtw1VAliJnLzXNg99X/NWfFobxeq81KuEXryGgeDQ0URhLj
0mRiikKYvLTGCAj4/ahMZJx2Ab0vqWwzD9g/KLg8aQFChn5pwckGyuV6RmXpwtZQQS4/t+TtbNe/
JgERohYpSms0BpDsE9K2+2p20jzt8NYt3eEV7KObLyzJPivkaTv/ciWxNoZbx39ri1UbSsUgYT2u
y1DhCDq+sI9jQVMwCFk8mB13umOResoQUGC/8Ne8lYePl8X+l2oBlKN8W4UdKjk60FSh0Tlxnf0h
+bV78OLgAo9uliQlLKAeLKjEiafv7ZkGL7YKTE/bosw3Gq9HhS2KX8Q0NEwA/RiTZxPRN+ZItIsG
xVd7GYYKecsAyVKvQv83j+GjHno9UKtjBucVtT+2RTeUN7F+8kjDf8V1/peNRY8apxpyKBpADwID
AQABo2MwYTAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAfBgNVHSMEGDAWgBQXnc0e
i9Y5K3DTXNSguB+wAPzFYTAdBgNVHQ4EFgQUF53NHovWOStw01zUoLgfsAD8xWEwDQYJKoZIhvcN
AQELBQADggIBAFbVe27mIgHSQpsY1Q7XZiNc4/6gx5LS6ZStS6LG7BJ8dNVI0lkUmcDrudHr9Egw
W62nV3OZqdPlt9EuWSRY3GguLmLYauRwCy0gUCCkMpXRAJi70/33MvJJrsZ64Ee+bs7Lo3I6LWld
y8joRTnU+kLBEUx3XZL7av9YROXrgZ6voJmtvqkBZss4HTzfQx/0TW60uhdG/H39h4F5ag0zD/ov
+BS5gLNdTaqX4fnkGMX41TiMJjz98iji7lpJiCzfeT2OnpA8vUFKOt1b9pq0zj8lMH8yfaIDlNDc
eqFS3m6TjRgm/VWsvY+b0s+v54Ysyx8Jb6NvqYTUc79NoXQbTiNg8swOqn+knEwlqLJmOzj/2ZQw
9nKEvmhVEA/GcywWaZMH/rFF7buiVWqw2rVKAiUnhde3t4ZEFolsgCs+l6mc1X5VTMbeRRAc6uk7
nwNT7u56AQIWeNTowr5GdogTPyK7SBIdUgC0An4hGh6cJfTzPV4e0hz5sy229zdcxsshTrD3mUcY
hcErulWuBurQB7Lcq9CClnXO0lD+mefPL5/ndtFhKvshuzHQqp9HpLIiyhY6UFfEW0NnxWViA0kB
60PZ2Pierc+xYw5F9KBaLJstxabArahH9CdMOA0uG0k7UvToiIMrVCjU8jVStDKDYmlkDJGcn5fq
dBb9HxEGmpv0
-----END CERTIFICATE-----

Microsoft ECC Root Certificate Authority 2017
=============================================
-----BEGIN CERTIFICATE-----
MIICWTCCAd+gAwIBAgIQZvI9r4fei7FK6gxXMQHC7DAKBggqhkjOPQQDAzBlMQswCQYDVQQGEwJV
UzEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMTYwNAYDVQQDEy1NaWNyb3NvZnQgRUND
IFJvb3QgQ2VydGlmaWNhdGUgQXV0aG9yaXR5IDIwMTcwHhcNMTkxMjE4MjMwNjQ1WhcNNDIwNzE4
MjMxNjA0WjBlMQswCQYDVQQGEwJVUzEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMTYw
NAYDVQQDEy1NaWNyb3NvZnQgRUNDIFJvb3QgQ2VydGlmaWNhdGUgQXV0aG9yaXR5IDIwMTcwdjAQ
BgcqhkjOPQIBBgUrgQQAIgNiAATUvD0CQnVBEyPNgASGAlEvaqiBYgtlzPbKnR5vSmZRogPZnZH6
thaxjG7efM3beaYvzrvOcS/lpaso7GMEZpn4+vKTEAXhgShC48Zo9OYbhGBKia/teQ87zvH2RPUB
eMCjVDBSMA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBTIy5lycFIM
+Oa+sgRXKSrPQhDtNTAQBgkrBgEEAYI3FQEEAwIBADAKBggqhkjOPQQDAwNoADBlAjBY8k3qDPlf
Xu5gKcs68tvWMoQZP3zVL8KxzJOuULsJMsbG7X7JNpQS5GiFBqIb0C8CMQCZ6Ra0DvpWSNSkMBaR
eNtUjGUBiudQZsIxtzm6uBoiB078a1QWIP8rtedMDE2mT3M=
-----END CERTIFICATE-----

Microsoft RSA Root Certificate Authority 2017
=============================================
-----BEGIN CERTIFICATE-----
MIIFqDCCA5CgAwIBAgIQHtOXCV/YtLNHcB6qvn9FszANBgkqhkiG9w0BAQwFADBlMQswCQYDVQQG
EwJVUzEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMTYwNAYDVQQDEy1NaWNyb3NvZnQg
UlNBIFJvb3QgQ2VydGlmaWNhdGUgQXV0aG9yaXR5IDIwMTcwHhcNMTkxMjE4MjI1MTIyWhcNNDIw
NzE4MjMwMDIzWjBlMQswCQYDVQQGEwJVUzEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9u
MTYwNAYDVQQDEy1NaWNyb3NvZnQgUlNBIFJvb3QgQ2VydGlmaWNhdGUgQXV0aG9yaXR5IDIwMTcw
ggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDKW76UM4wplZEWCpW9R2LBifOZNt9GkMml
7Xhqb0eRaPgnZ1AzHaGm++DlQ6OEAlcBXZxIQIJTELy/xztokLaCLeX0ZdDMbRnMlfl7rEqUrQ7e
S0MdhweSE5CAg2Q1OQT85elss7YfUJQ4ZVBcF0a5toW1HLUX6NZFndiyJrDKxHBKrmCk3bPZ7Pw7
1VdyvD/IybLeS2v4I2wDwAW9lcfNcztmgGTjGqwu+UcF8ga2m3P1eDNbx6H7JyqhtJqRjJHTOoI+
dkC0zVJhUXAoP8XFWvLJjEm7FFtNyP9nTUwSlq31/niol4fX/V4ggNyhSyL71Imtus5Hl0dVe49F
yGcohJUcaDDv70ngNXtk55iwlNpNhTs+VcQor1fznhPbRiefHqJeRIOkpcrVE7NLP8TjwuaGYaRS
MLl6IE9vDzhTyzMMEyuP1pq9KsgtsRx9S1HKR9FIJ3Jdh+vVReZIZZ2vUpC6W6IYZVcSn2i51BVr
lMRpIpj0M+Dt+VGOQVDJNE92kKz8OMHY4Xu54+OU4UZpyw4KUGsTuqwPN1q3ErWQgR5WrlcihtnJ
0tHXUeOrO8ZV/R4O03QK0dqq6mm4lyiPSMQH+FJDOvTKVTUssKZqwJz58oHhEmrARdlns87/I6KJ
ClTUFLkqqNfs+avNJVgyeY+QW5g5xAgGwax/Dj0ApQIDAQABo1QwUjAOBgNVHQ8BAf8EBAMCAYYw
DwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUCctZf4aycI8awznjwNnpv7tNsiMwEAYJKwYBBAGC
NxUBBAMCAQAwDQYJKoZIhvcNAQEMBQADggIBAKyvPl3CEZaJjqPnktaXFbgToqZCLgLNFgVZJ8og
6Lq46BrsTaiXVq5lQ7GPAJtSzVXNUzltYkyLDVt8LkS/gxCP81OCgMNPOsduET/m4xaRhPtthH80
dK2Jp86519efhGSSvpWhrQlTM93uCupKUY5vVau6tZRGrox/2KJQJWVggEbbMwSubLWYdFQl3JPk
+ONVFT24bcMKpBLBaYVu32TxU5nhSnUgnZUP5NbcA/FZGOhHibJXWpS2qdgXKxdJ5XbLwVaZOjex
/2kskZGT4d9Mozd2TaGf+G0eHdP67Pv0RR0Tbc/3WeUiJ3IrhvNXuzDtJE3cfVa7o7P4NHmJweDy
AmH3pvwPuxwXC65B2Xy9J6P9LjrRk5Sxcx0ki69bIImtt2dmefU6xqaWM/5TkshGsRGRxpl/j8nW
ZjEgQRCHLQzWwa80mMpkg/sTV9HB8Dx6jKXB/ZUhoHHBk2dxEuqPiAppGWSZI1b7rCoucL5mxAyE
7+WL85MB+GqQk2dLsmijtWKP6T+MejteD+eMuMZ87zf9dOLITzNy4ZQ5bb0Sr74MTnB8G2+NszKT
c0QWbej09+CVgI+WXTik9KveCjCHk9hNAHFiRSdLOkKEW39lt2c0Ui2cFmuqqNh7o0JMcccMyj6D
5KbvtwEwXlGjefVwaaZBRA+GsCyRxj3qrg+E
-----END CERTIFICATE-----

e-Szigno Root CA 2017
=====================
-----BEGIN CERTIFICATE-----
MIICQDCCAeWgAwIBAgIMAVRI7yH9l1kN9QQKMAoGCCqGSM49BAMCMHExCzAJBgNVBAYTAkhVMREw
DwYDVQQHDAhCdWRhcGVzdDEWMBQGA1UECgwNTWljcm9zZWMgTHRkLjEXMBUGA1UEYQwOVkFUSFUt
MjM1ODQ0OTcxHjAcBgNVBAMMFWUtU3ppZ25vIFJvb3QgQ0EgMjAxNzAeFw0xNzA4MjIxMjA3MDZa
Fw00MjA4MjIxMjA3MDZaMHExCzAJBgNVBAYTAkhVMREwDwYDVQQHDAhCdWRhcGVzdDEWMBQGA1UE
CgwNTWljcm9zZWMgTHRkLjEXMBUGA1UEYQwOVkFUSFUtMjM1ODQ0OTcxHjAcBgNVBAMMFWUtU3pp
Z25vIFJvb3QgQ0EgMjAxNzBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABJbcPYrYsHtvxie+RJCx
s1YVe45DJH0ahFnuY2iyxl6H0BVIHqiQrb1TotreOpCmYF9oMrWGQd+HWyx7xf58etqjYzBhMA8G
A1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBSHERUI0arBeAyxr87GyZDv
vzAEwDAfBgNVHSMEGDAWgBSHERUI0arBeAyxr87GyZDvvzAEwDAKBggqhkjOPQQDAgNJADBGAiEA
tVfd14pVCzbhhkT61NlojbjcI4qKDdQvfepz7L9NbKgCIQDLpbQS+ue16M9+k/zzNY9vTlp8tLxO
svxyqltZ+efcMQ==
-----END CERTIFICATE-----

certSIGN Root CA G2
===================
-----BEGIN CERTIFICATE-----
MIIFRzCCAy+gAwIBAgIJEQA0tk7GNi02MA0GCSqGSIb3DQEBCwUAMEExCzAJBgNVBAYTAlJPMRQw
EgYDVQQKEwtDRVJUU0lHTiBTQTEcMBoGA1UECxMTY2VydFNJR04gUk9PVCBDQSBHMjAeFw0xNzAy
MDYwOTI3MzVaFw00MjAyMDYwOTI3MzVaMEExCzAJBgNVBAYTAlJPMRQwEgYDVQQKEwtDRVJUU0lH
TiBTQTEcMBoGA1UECxMTY2VydFNJR04gUk9PVCBDQSBHMjCCAiIwDQYJKoZIhvcNAQEBBQADggIP
ADCCAgoCggIBAMDFdRmRfUR0dIf+DjuW3NgBFszuY5HnC2/OOwppGnzC46+CjobXXo9X69MhWf05
N0IwvlDqtg+piNguLWkh59E3GE59kdUWX2tbAMI5Qw02hVK5U2UPHULlj88F0+7cDBrZuIt4Imfk
abBoxTzkbFpG583H+u/E7Eu9aqSs/cwoUe+StCmrqzWaTOTECMYmzPhpn+Sc8CnTXPnGFiWeI8Mg
wT0PPzhAsP6CRDiqWhqKa2NYOLQV07YRaXseVO6MGiKscpc/I1mbySKEwQdPzH/iV8oScLumZfNp
dWO9lfsbl83kqK/20U6o2YpxJM02PbyWxPFsqa7lzw1uKA2wDrXKUXt4FMMgL3/7FFXhEZn91Qqh
ngLjYl/rNUssuHLoPj1PrCy7Lobio3aP5ZMqz6WryFyNSwb/EkaseMsUBzXgqd+L6a8VTxaJW732
jcZZroiFDsGJ6x9nxUWO/203Nit4ZoORUSs9/1F3dmKh7Gc+PoGD4FapUB8fepmrY7+EF3fxDTvf
95xhszWYijqy7DwaNz9+j5LP2RIUZNoQAhVB/0/E6xyjyfqZ90bp4RjZsbgyLcsUDFDYg2WD7rlc
z8sFWkz6GZdr1l0T08JcVLwyc6B49fFtHsufpaafItzRUZ6CeWRgKRM+o/1Pcmqr4tTluCRVLERL
iohEnMqE0yo7AgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1Ud
DgQWBBSCIS1mxteg4BXrzkwJd8RgnlRuAzANBgkqhkiG9w0BAQsFAAOCAgEAYN4auOfyYILVAzOB
ywaK8SJJ6ejqkX/GM15oGQOGO0MBzwdw5AgeZYWR5hEit/UCI46uuR59H35s5r0l1ZUa8gWmr4UC
b6741jH/JclKyMeKqdmfS0mbEVeZkkMR3rYzpMzXjWR91M08KCy0mpbqTfXERMQlqiCA2ClV9+BB
/AYm/7k29UMUA2Z44RGx2iBfRgB4ACGlHgAoYXhvqAEBj500mv/0OJD7uNGzcgbJceaBxXntC6Z5
8hMLnPddDnskk7RI24Zf3lCGeOdA5jGokHZwYa+cNywRtYK3qq4kNFtyDGkNzVmf9nGvnAvRCjj5
BiKDUyUM/FHE5r7iOZULJK2v0ZXkltd0ZGtxTgI8qoXzIKNDOXZbbFD+mpwUHmUUihW9o4JFWklW
atKcsWMy5WHgUyIOpwpJ6st+H6jiYoD2EEVSmAYY3qXNL3+q1Ok+CHLsIwMCPKaq2LxndD0UF/tU
Sxfj03k9bWtJySgOLnRQvwzZRjoQhsmnP+mg7H/rpXdYaXHmgwo38oZJar55CJD2AhZkPuXaTH4M
NMn5X7azKFGnpyuqSfqNZSlO42sTp5SjLVFteAxEy9/eCG/Oo2Sr05WE1LlSVHJ7liXMvGnjSG4N
0MedJ5qq+BOS3R7fY581qRY27Iy4g/Q9iY/NtBde17MXQRBdJ3NghVdJIgc=
-----END CERTIFICATE-----

Trustwave Global Certification Authority
========================================
-----BEGIN CERTIFICATE-----
MIIF2jCCA8KgAwIBAgIMBfcOhtpJ80Y1LrqyMA0GCSqGSIb3DQEBCwUAMIGIMQswCQYDVQQGEwJV
UzERMA8GA1UECAwISWxsaW5vaXMxEDAOBgNVBAcMB0NoaWNhZ28xITAfBgNVBAoMGFRydXN0d2F2
ZSBIb2xkaW5ncywgSW5jLjExMC8GA1UEAwwoVHJ1c3R3YXZlIEdsb2JhbCBDZXJ0aWZpY2F0aW9u
IEF1dGhvcml0eTAeFw0xNzA4MjMxOTM0MTJaFw00MjA4MjMxOTM0MTJaMIGIMQswCQYDVQQGEwJV
UzERMA8GA1UECAwISWxsaW5vaXMxEDAOBgNVBAcMB0NoaWNhZ28xITAfBgNVBAoMGFRydXN0d2F2
ZSBIb2xkaW5ncywgSW5jLjExMC8GA1UEAwwoVHJ1c3R3YXZlIEdsb2JhbCBDZXJ0aWZpY2F0aW9u
IEF1dGhvcml0eTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBALldUShLPDeS0YLOvR29
zd24q88KPuFd5dyqCblXAj7mY2Hf8g+CY66j96xz0XznswuvCAAJWX/NKSqIk4cXGIDtiLK0thAf
LdZfVaITXdHG6wZWiYj+rDKd/VzDBcdu7oaJuogDnXIhhpCujwOl3J+IKMujkkkP7NAP4m1ET4Bq
stTnoApTAbqOl5F2brz81Ws25kCI1nsvXwXoLG0R8+eyvpJETNKXpP7ScoFDB5zpET71ixpZfR9o
WN0EACyW80OzfpgZdNmcc9kYvkHHNHnZ9GLCQ7mzJ7Aiy/k9UscwR7PJPrhq4ufogXBeQotPJqX+
OsIgbrv4Fo7NDKm0G2x2EOFYeUY+VM6AqFcJNykbmROPDMjWLBz7BegIlT1lRtzuzWniTY+HKE40
Cz7PFNm73bZQmq131BnW2hqIyE4bJ3XYsgjxroMwuREOzYfwhI0Vcnyh78zyiGG69Gm7DIwLdVcE
uE4qFC49DxweMqZiNu5m4iK4BUBjECLzMx10coos9TkpoNPnG4CELcU9402x/RpvumUHO1jsQkUm
+9jaJXLE9gCxInm943xZYkqcBW89zubWR2OZxiRvchLIrH+QtAuRcOi35hYQcRfO3gZPSEF9NUqj
ifLJS3tBEW1ntwiYTOURGa5CgNz7kAXU+FDKvuStx8KU1xad5hePrzb7AgMBAAGjQjBAMA8GA1Ud
EwEB/wQFMAMBAf8wHQYDVR0OBBYEFJngGWcNYtt2s9o9uFvo/ULSMQ6HMA4GA1UdDwEB/wQEAwIB
BjANBgkqhkiG9w0BAQsFAAOCAgEAmHNw4rDT7TnsTGDZqRKGFx6W0OhUKDtkLSGm+J1WE2pIPU/H
PinbbViDVD2HfSMF1OQc3Og4ZYbFdada2zUFvXfeuyk3QAUHw5RSn8pk3fEbK9xGChACMf1KaA0H
ZJDmHvUqoai7PF35owgLEQzxPy0QlG/+4jSHg9bP5Rs1bdID4bANqKCqRieCNqcVtgimQlRXtpla
4gt5kNdXElE1GYhBaCXUNxeEFfsBctyV3lImIJgm4nb1J2/6ADtKYdkNy1GTKv0WBpanI5ojSP5R
vbbEsLFUzt5sQa0WZ37b/TjNuThOssFgy50X31ieemKyJo90lZvkWx3SD92YHJtZuSPTMaCm/zjd
zyBP6VhWOmfD0faZmZ26NraAL4hHT4a/RDqA5Dccprrql5gR0IRiR2Qequ5AvzSxnI9O4fKSTx+O
856X3vOmeWqJcU9LJxdI/uz0UA9PSX3MReO9ekDFQdxhVicGaeVyQYHTtgGJoC86cnn+OjC/QezH
Yj6RS8fZMXZC+fc8Y+wmjHMMfRod6qh8h6jCJ3zhM0EPz8/8AKAigJ5Kp28AsEFFtyLKaEjFQqKu
3R3y4G5OBVixwJAWKqQ9EEC+j2Jjg6mcgn0tAumDMHzLJ8n9HmYAsC7TIS+OMxZsmO0QqAfWzJPP
29FpHOTKyeC2nOnOcXHebD8WpHk=
-----END CERTIFICATE-----

Trustwave Global ECC P256 Certification Authority
=================================================
-----BEGIN CERTIFICATE-----
MIICYDCCAgegAwIBAgIMDWpfCD8oXD5Rld9dMAoGCCqGSM49BAMCMIGRMQswCQYDVQQGEwJVUzER
MA8GA1UECBMISWxsaW5vaXMxEDAOBgNVBAcTB0NoaWNhZ28xITAfBgNVBAoTGFRydXN0d2F2ZSBI
b2xkaW5ncywgSW5jLjE6MDgGA1UEAxMxVHJ1c3R3YXZlIEdsb2JhbCBFQ0MgUDI1NiBDZXJ0aWZp
Y2F0aW9uIEF1dGhvcml0eTAeFw0xNzA4MjMxOTM1MTBaFw00MjA4MjMxOTM1MTBaMIGRMQswCQYD
VQQGEwJVUzERMA8GA1UECBMISWxsaW5vaXMxEDAOBgNVBAcTB0NoaWNhZ28xITAfBgNVBAoTGFRy
dXN0d2F2ZSBIb2xkaW5ncywgSW5jLjE6MDgGA1UEAxMxVHJ1c3R3YXZlIEdsb2JhbCBFQ0MgUDI1
NiBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABH77bOYj
43MyCMpg5lOcunSNGLB4kFKA3TjASh3RqMyTpJcGOMoNFWLGjgEqZZ2q3zSRLoHB5DOSMcT9CTqm
P62jQzBBMA8GA1UdEwEB/wQFMAMBAf8wDwYDVR0PAQH/BAUDAwcGADAdBgNVHQ4EFgQUo0EGrJBt
0UrrdaVKEJmzsaGLSvcwCgYIKoZIzj0EAwIDRwAwRAIgB+ZU2g6gWrKuEZ+Hxbb/ad4lvvigtwjz
RM4q3wghDDcCIC0mA6AFvWvR9lz4ZcyGbbOcNEhjhAnFjXca4syc4XR7
-----END CERTIFICATE-----

Trustwave Global ECC P384 Certification Authority
=================================================
-----BEGIN CERTIFICATE-----
MIICnTCCAiSgAwIBAgIMCL2Fl2yZJ6SAaEc7MAoGCCqGSM49BAMDMIGRMQswCQYDVQQGEwJVUzER
MA8GA1UECBMISWxsaW5vaXMxEDAOBgNVBAcTB0NoaWNhZ28xITAfBgNVBAoTGFRydXN0d2F2ZSBI
b2xkaW5ncywgSW5jLjE6MDgGA1UEAxMxVHJ1c3R3YXZlIEdsb2JhbCBFQ0MgUDM4NCBDZXJ0aWZp
Y2F0aW9uIEF1dGhvcml0eTAeFw0xNzA4MjMxOTM2NDNaFw00MjA4MjMxOTM2NDNaMIGRMQswCQYD
VQQGEwJVUzERMA8GA1UECBMISWxsaW5vaXMxEDAOBgNVBAcTB0NoaWNhZ28xITAfBgNVBAoTGFRy
dXN0d2F2ZSBIb2xkaW5ncywgSW5jLjE6MDgGA1UEAxMxVHJ1c3R3YXZlIEdsb2JhbCBFQ0MgUDM4
NCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTB2MBAGByqGSM49AgEGBSuBBAAiA2IABGvaDXU1CDFH
Ba5FmVXxERMuSvgQMSOjfoPTfygIOiYaOs+Xgh+AtycJj9GOMMQKmw6sWASr9zZ9lCOkmwqKi6vr
/TklZvFe/oyujUF5nQlgziip04pt89ZF1PKYhDhloKNDMEEwDwYDVR0TAQH/BAUwAwEB/zAPBgNV
HQ8BAf8EBQMDBwYAMB0GA1UdDgQWBBRVqYSJ0sEyvRjLbKYHTsjnnb6CkDAKBggqhkjOPQQDAwNn
ADBkAjA3AZKXRRJ+oPM+rRk6ct30UJMDEr5E0k9BpIycnR+j9sKS50gU/k6bpZFXrsY3crsCMGcl
CrEMXu6pY5Jv5ZAL/mYiykf9ijH3g/56vxC+GCsej/YpHpRZ744hN8tRmKVuSw==
-----END CERTIFICATE-----

NAVER Global Root Certification Authority
=========================================
-----BEGIN CERTIFICATE-----
MIIFojCCA4qgAwIBAgIUAZQwHqIL3fXFMyqxQ0Rx+NZQTQ0wDQYJKoZIhvcNAQEMBQAwaTELMAkG
A1UEBhMCS1IxJjAkBgNVBAoMHU5BVkVSIEJVU0lORVNTIFBMQVRGT1JNIENvcnAuMTIwMAYDVQQD
DClOQVZFUiBHbG9iYWwgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0xNzA4MTgwODU4
NDJaFw0zNzA4MTgyMzU5NTlaMGkxCzAJBgNVBAYTAktSMSYwJAYDVQQKDB1OQVZFUiBCVVNJTkVT
UyBQTEFURk9STSBDb3JwLjEyMDAGA1UEAwwpTkFWRVIgR2xvYmFsIFJvb3QgQ2VydGlmaWNhdGlv
biBBdXRob3JpdHkwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC21PGTXLVAiQqrDZBb
UGOukJR0F0Vy1ntlWilLp1agS7gvQnXp2XskWjFlqxcX0TM62RHcQDaH38dq6SZeWYp34+hInDEW
+j6RscrJo+KfziFTowI2MMtSAuXaMl3Dxeb57hHHi8lEHoSTGEq0n+USZGnQJoViAbbJAh2+g1G7
XNr4rRVqmfeSVPc0W+m/6imBEtRTkZazkVrd/pBzKPswRrXKCAfHcXLJZtM0l/aM9BhK4dA9WkW2
aacp+yPOiNgSnABIqKYPszuSjXEOdMWLyEz59JuOuDxp7W87UC9Y7cSw0BwbagzivESq2M0UXZR4
Yb8ObtoqvC8MC3GmsxY/nOb5zJ9TNeIDoKAYv7vxvvTWjIcNQvcGufFt7QSUqP620wbGQGHfnZ3z
VHbOUzoBppJB7ASjjw2i1QnK1sua8e9DXcCrpUHPXFNwcMmIpi3Ua2FzUCaGYQ5fG8Ir4ozVu53B
A0K6lNpfqbDKzE0K70dpAy8i+/Eozr9dUGWokG2zdLAIx6yo0es+nPxdGoMuK8u180SdOqcXYZai
cdNwlhVNt0xz7hlcxVs+Qf6sdWA7G2POAN3aCJBitOUt7kinaxeZVL6HSuOpXgRM6xBtVNbv8ejy
YhbLgGvtPe31HzClrkvJE+2KAQHJuFFYwGY6sWZLxNUxAmLpdIQM201GLQIDAQABo0IwQDAdBgNV
HQ4EFgQU0p+I36HNLL3s9TsBAZMzJ7LrYEswDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMB
Af8wDQYJKoZIhvcNAQEMBQADggIBADLKgLOdPVQG3dLSLvCkASELZ0jKbY7gyKoNqo0hV4/GPnrK
21HUUrPUloSlWGB/5QuOH/XcChWB5Tu2tyIvCZwTFrFsDDUIbatjcu3cvuzHV+YwIHHW1xDBE1UB
jCpD5EHxzzp6U5LOogMFDTjfArsQLtk70pt6wKGm+LUx5vR1yblTmXVHIloUFcd4G7ad6Qz4G3bx
hYTeodoS76TiEJd6eN4MUZeoIUCLhr0N8F5OSza7OyAfikJW4Qsav3vQIkMsRIz75Sq0bBwcupTg
E34h5prCy8VCZLQelHsIJchxzIdFV4XTnyliIoNRlwAYl3dqmJLJfGBs32x9SuRwTMKeuB330DTH
D8z7p/8Dvq1wkNoL3chtl1+afwkyQf3NosxabUzyqkn+Zvjp2DXrDige7kgvOtB5CTh8piKCk5XQ
A76+AqAF3SAi428diDRgxuYKuQl1C/AH6GmWNcf7I4GOODm4RStDeKLRLBT/DShycpWbXgnbiUSY
qqFJu3FS8r/2/yehNq+4tneI3TqkbZs0kNwUXTC/t+sX5Ie3cdCh13cV1ELX8vMxmV2b3RZtP+oG
I/hGoiLtk/bdmuYqh7GYVPEi92tF4+KOdh2ajcQGjTa3FPOdVGm3jjzVpG2Tgbet9r1ke8LJaDmg
kpzNNIaRkPpkUZ3+/uul9XXeifdy
-----END CERTIFICATE-----

AC RAIZ FNMT-RCM SERVIDORES SEGUROS
===================================
-----BEGIN CERTIFICATE-----
MIICbjCCAfOgAwIBAgIQYvYybOXE42hcG2LdnC6dlTAKBggqhkjOPQQDAzB4MQswCQYDVQQGEwJF
UzERMA8GA1UECgwIRk5NVC1SQ00xDjAMBgNVBAsMBUNlcmVzMRgwFgYDVQRhDA9WQVRFUy1RMjgy
NjAwNEoxLDAqBgNVBAMMI0FDIFJBSVogRk5NVC1SQ00gU0VSVklET1JFUyBTRUdVUk9TMB4XDTE4
MTIyMDA5MzczM1oXDTQzMTIyMDA5MzczM1oweDELMAkGA1UEBhMCRVMxETAPBgNVBAoMCEZOTVQt
UkNNMQ4wDAYDVQQLDAVDZXJlczEYMBYGA1UEYQwPVkFURVMtUTI4MjYwMDRKMSwwKgYDVQQDDCNB
QyBSQUlaIEZOTVQtUkNNIFNFUlZJRE9SRVMgU0VHVVJPUzB2MBAGByqGSM49AgEGBSuBBAAiA2IA
BPa6V1PIyqvfNkpSIeSX0oNnnvBlUdBeh8dHsVnyV0ebAAKTRBdp20LHsbI6GA60XYyzZl2hNPk2
LEnb80b8s0RpRBNm/dfF/a82Tc4DTQdxz69qBdKiQ1oKUm8BA06Oi6NCMEAwDwYDVR0TAQH/BAUw
AwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFAG5L++/EYZg8k/QQW6rcx/n0m5JMAoGCCqG
SM49BAMDA2kAMGYCMQCuSuMrQMN0EfKVrRYj3k4MGuZdpSRea0R7/DjiT8ucRRcRTBQnJlU5dUoD
zBOQn5ICMQD6SmxgiHPz7riYYqnOK8LZiqZwMR2vsJRM60/G49HzYqc8/5MuB1xJAWdpEgJyv+c=
-----END CERTIFICATE-----

GlobalSign Root R46
===================
-----BEGIN CERTIFICATE-----
MIIFWjCCA0KgAwIBAgISEdK7udcjGJ5AXwqdLdDfJWfRMA0GCSqGSIb3DQEBDAUAMEYxCzAJBgNV
BAYTAkJFMRkwFwYDVQQKExBHbG9iYWxTaWduIG52LXNhMRwwGgYDVQQDExNHbG9iYWxTaWduIFJv
b3QgUjQ2MB4XDTE5MDMyMDAwMDAwMFoXDTQ2MDMyMDAwMDAwMFowRjELMAkGA1UEBhMCQkUxGTAX
BgNVBAoTEEdsb2JhbFNpZ24gbnYtc2ExHDAaBgNVBAMTE0dsb2JhbFNpZ24gUm9vdCBSNDYwggIi
MA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCsrHQy6LNl5brtQyYdpokNRbopiLKkHWPd08Es
CVeJOaFV6Wc0dwxu5FUdUiXSE2te4R2pt32JMl8Nnp8semNgQB+msLZ4j5lUlghYruQGvGIFAha/
r6gjA7aUD7xubMLL1aa7DOn2wQL7Id5m3RerdELv8HQvJfTqa1VbkNud316HCkD7rRlr+/fKYIje
2sGP1q7Vf9Q8g+7XFkyDRTNrJ9CG0Bwta/OrffGFqfUo0q3v84RLHIf8E6M6cqJaESvWJ3En7YEt
bWaBkoe0G1h6zD8K+kZPTXhc+CtI4wSEy132tGqzZfxCnlEmIyDLPRT5ge1lFgBPGmSXZgjPjHvj
K8Cd+RTyG/FWaha/LIWFzXg4mutCagI0GIMXTpRW+LaCtfOW3T3zvn8gdz57GSNrLNRyc0NXfeD4
12lPFzYE+cCQYDdF3uYM2HSNrpyibXRdQr4G9dlkbgIQrImwTDsHTUB+JMWKmIJ5jqSngiCNI/on
ccnfxkF0oE32kRbcRoxfKWMxWXEM2G/CtjJ9++ZdU6Z+Ffy7dXxd7Pj2Fxzsx2sZy/N78CsHpdls
eVR2bJ0cpm4O6XkMqCNqo98bMDGfsVR7/mrLZqrcZdCinkqaByFrgY/bxFn63iLABJzjqls2k+g9
vXqhnQt2sQvHnf3PmKgGwvgqo6GDoLclcqUC4wIDAQABo0IwQDAOBgNVHQ8BAf8EBAMCAYYwDwYD
VR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUA1yrc4GHqMywptWU4jaWSf8FmSwwDQYJKoZIhvcNAQEM
BQADggIBAHx47PYCLLtbfpIrXTncvtgdokIzTfnvpCo7RGkerNlFo048p9gkUbJUHJNOxO97k4Vg
JuoJSOD1u8fpaNK7ajFxzHmuEajwmf3lH7wvqMxX63bEIaZHU1VNaL8FpO7XJqti2kM3S+LGteWy
gxk6x9PbTZ4IevPuzz5i+6zoYMzRx6Fcg0XERczzF2sUyQQCPtIkpnnpHs6i58FZFZ8d4kuaPp92
CC1r2LpXFNqD6v6MVenQTqnMdzGxRBF6XLE+0xRFFRhiJBPSy03OXIPBNvIQtQ6IbbjhVp+J3pZm
OUdkLG5NrmJ7v2B0GbhWrJKsFjLtrWhV/pi60zTe9Mlhww6G9kuEYO4Ne7UyWHmRVSyBQ7N0H3qq
JZ4d16GLuc1CLgSkZoNNiTW2bKg2SnkheCLQQrzRQDGQob4Ez8pn7fXwgNNgyYMqIgXQBztSvwye
qiv5u+YfjyW6hY0XHgL+XVAEV8/+LbzvXMAaq7afJMbfc2hIkCwU9D9SGuTSyxTDYWnP4vkYxboz
nxSjBF25cfe1lNj2M8FawTSLfJvdkzrnE6JwYZ+vj+vYxXX4M2bUdGc6N3ec592kD3ZDZopD8p/7
DEJ4Y9HiD2971KE9dJeFt0g5QdYg/NA6s/rob8SKunE3vouXsXgxT7PntgMTzlSdriVZzH81Xwj3
QEUxeCp6
-----END CERTIFICATE-----

GlobalSign Root E46
===================
-----BEGIN CERTIFICATE-----
MIICCzCCAZGgAwIBAgISEdK7ujNu1LzmJGjFDYQdmOhDMAoGCCqGSM49BAMDMEYxCzAJBgNVBAYT
AkJFMRkwFwYDVQQKExBHbG9iYWxTaWduIG52LXNhMRwwGgYDVQQDExNHbG9iYWxTaWduIFJvb3Qg
RTQ2MB4XDTE5MDMyMDAwMDAwMFoXDTQ2MDMyMDAwMDAwMFowRjELMAkGA1UEBhMCQkUxGTAXBgNV
BAoTEEdsb2JhbFNpZ24gbnYtc2ExHDAaBgNVBAMTE0dsb2JhbFNpZ24gUm9vdCBFNDYwdjAQBgcq
hkjOPQIBBgUrgQQAIgNiAAScDrHPt+ieUnd1NPqlRqetMhkytAepJ8qUuwzSChDH2omwlwxwEwkB
jtjqR+q+soArzfwoDdusvKSGN+1wCAB16pMLey5SnCNoIwZD7JIvU4Tb+0cUB+hflGddyXqBPCCj
QjBAMA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBQxCpCPtsad0kRL
gLWi5h+xEk8blTAKBggqhkjOPQQDAwNoADBlAjEA31SQ7Zvvi5QCkxeCmb6zniz2C5GMn0oUsfZk
vLtoURMMA/cVi4RguYv/Uo7njLwcAjA8+RHUjE7AwWHCFUyqqx0LMV87HOIAl0Qx5v5zli/altP+
CAezNIm8BZ/3Hobui3A=
-----END CERTIFICATE-----

GLOBALTRUST 2020
================
-----BEGIN CERTIFICATE-----
MIIFgjCCA2qgAwIBAgILWku9WvtPilv6ZeUwDQYJKoZIhvcNAQELBQAwTTELMAkGA1UEBhMCQVQx
IzAhBgNVBAoTGmUtY29tbWVyY2UgbW9uaXRvcmluZyBHbWJIMRkwFwYDVQQDExBHTE9CQUxUUlVT
VCAyMDIwMB4XDTIwMDIxMDAwMDAwMFoXDTQwMDYxMDAwMDAwMFowTTELMAkGA1UEBhMCQVQxIzAh
BgNVBAoTGmUtY29tbWVyY2UgbW9uaXRvcmluZyBHbWJIMRkwFwYDVQQDExBHTE9CQUxUUlVTVCAy
MDIwMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAri5WrRsc7/aVj6B3GyvTY4+ETUWi
D59bRatZe1E0+eyLinjF3WuvvcTfk0Uev5E4C64OFudBc/jbu9G4UeDLgztzOG53ig9ZYybNpyrO
VPu44sB8R85gfD+yc/LAGbaKkoc1DZAoouQVBGM+uq/ufF7MpotQsjj3QWPKzv9pj2gOlTblzLmM
CcpL3TGQlsjMH/1WljTbjhzqLL6FLmPdqqmV0/0plRPwyJiT2S0WR5ARg6I6IqIoV6Lr/sCMKKCm
fecqQjuCgGOlYx8ZzHyyZqjC0203b+J+BlHZRYQfEs4kUmSFC0iAToexIiIwquuuvuAC4EDosEKA
A1GqtH6qRNdDYfOiaxaJSaSjpCuKAsR49GiKweR6NrFvG5Ybd0mN1MkGco/PU+PcF4UgStyYJ9OR
JitHHmkHr96i5OTUawuzXnzUJIBHKWk7buis/UDr2O1xcSvy6Fgd60GXIsUf1DnQJ4+H4xj04KlG
DfV0OoIu0G4skaMxXDtG6nsEEFZegB31pWXogvziB4xiRfUg3kZwhqG8k9MedKZssCz3AwyIDMvU
clOGvGBG85hqwvG/Q/lwIHfKN0F5VVJjjVsSn8VoxIidrPIwq7ejMZdnrY8XD2zHc+0klGvIg5rQ
mjdJBKuxFshsSUktq6HQjJLyQUp5ISXbY9e2nKd+Qmn7OmMCAwEAAaNjMGEwDwYDVR0TAQH/BAUw
AwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFNwuH9FhN3nkq9XVsxJxaD1qaJwiMB8GA1Ud
IwQYMBaAFNwuH9FhN3nkq9XVsxJxaD1qaJwiMA0GCSqGSIb3DQEBCwUAA4ICAQCR8EICaEDuw2jA
VC/f7GLDw56KoDEoqoOOpFaWEhCGVrqXctJUMHytGdUdaG/7FELYjQ7ztdGl4wJCXtzoRlgHNQIw
4Lx0SsFDKv/bGtCwr2zD/cuz9X9tAy5ZVp0tLTWMstZDFyySCstd6IwPS3BD0IL/qMy/pJTAvoe9
iuOTe8aPmxadJ2W8esVCgmxcB9CpwYhgROmYhRZf+I/KARDOJcP5YBugxZfD0yyIMaK9MOzQ0MAS
8cE54+X1+NZK3TTN+2/BT+MAi1bikvcoskJ3ciNnxz8RFbLEAwW+uxF7Cr+obuf/WEPPm2eggAe2
HcqtbepBEX4tdJP7wry+UUTF72glJ4DjyKDUEuzZpTcdN3y0kcra1LGWge9oXHYQSa9+pTeAsRxS
vTOBTI/53WXZFM2KJVj04sWDpQmQ1GwUY7VA3+vA/MRYfg0UFodUJ25W5HCEuGwyEn6CMUO+1918
oa2u1qsgEu8KwxCMSZY13At1XrFP1U80DhEgB3VDRemjEdqso5nCtnkn4rnvyOL2NSl6dPrFf4IF
YqYK6miyeUcGbvJXqBUzxvd4Sj1Ce2t+/vdG6tHrju+IaFvowdlxfv1k7/9nR4hYJS8+hge9+6jl
gqispdNpQ80xiEmEU5LAsTkbOYMBMMTyqfrQA71yN2BWHzZ8vTmR9W0Nv3vXkg==
-----END CERTIFICATE-----

ANF Secure Server Root CA
=========================
-----BEGIN CERTIFICATE-----
MIIF7zCCA9egAwIBAgIIDdPjvGz5a7EwDQYJKoZIhvcNAQELBQAwgYQxEjAQBgNVBAUTCUc2MzI4
NzUxMDELMAkGA1UEBhMCRVMxJzAlBgNVBAoTHkFORiBBdXRvcmlkYWQgZGUgQ2VydGlmaWNhY2lv
bjEUMBIGA1UECxMLQU5GIENBIFJhaXoxIjAgBgNVBAMTGUFORiBTZWN1cmUgU2VydmVyIFJvb3Qg
Q0EwHhcNMTkwOTA0MTAwMDM4WhcNMzkwODMwMTAwMDM4WjCBhDESMBAGA1UEBRMJRzYzMjg3NTEw
MQswCQYDVQQGEwJFUzEnMCUGA1UEChMeQU5GIEF1dG9yaWRhZCBkZSBDZXJ0aWZpY2FjaW9uMRQw
EgYDVQQLEwtBTkYgQ0EgUmFpejEiMCAGA1UEAxMZQU5GIFNlY3VyZSBTZXJ2ZXIgUm9vdCBDQTCC
AiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBANvrayvmZFSVgpCjcqQZAZ2cC4Ffc0m6p6zz
BE57lgvsEeBbphzOG9INgxwruJ4dfkUyYA8H6XdYfp9qyGFOtibBTI3/TO80sh9l2Ll49a2pcbnv
T1gdpd50IJeh7WhM3pIXS7yr/2WanvtH2Vdy8wmhrnZEE26cLUQ5vPnHO6RYPUG9tMJJo8gN0pcv
B2VSAKduyK9o7PQUlrZXH1bDOZ8rbeTzPvY1ZNoMHKGESy9LS+IsJJ1tk0DrtSOOMspvRdOoiXse
zx76W0OLzc2oD2rKDF65nkeP8Nm2CgtYZRczuSPkdxl9y0oukntPLxB3sY0vaJxizOBQ+OyRp1RM
VwnVdmPF6GUe7m1qzwmd+nxPrWAI/VaZDxUse6mAq4xhj0oHdkLePfTdsiQzW7i1o0TJrH93PB0j
7IKppuLIBkwC/qxcmZkLLxCKpvR/1Yd0DVlJRfbwcVw5Kda/SiOL9V8BY9KHcyi1Swr1+KuCLH5z
JTIdC2MKF4EA/7Z2Xue0sUDKIbvVgFHlSFJnLNJhiQcND85Cd8BEc5xEUKDbEAotlRyBr+Qc5RQe
8TZBAQIvfXOn3kLMTOmJDVb3n5HUA8ZsyY/b2BzgQJhdZpmYgG4t/wHFzstGH6wCxkPmrqKEPMVO
Hj1tyRRM4y5Bu8o5vzY8KhmqQYdOpc5LMnndkEl/AgMBAAGjYzBhMB8GA1UdIwQYMBaAFJxf0Gxj
o1+TypOYCK2Mh6UsXME3MB0GA1UdDgQWBBScX9BsY6Nfk8qTmAitjIelLFzBNzAOBgNVHQ8BAf8E
BAMCAYYwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAgEATh65isagmD9uw2nAalxJ
UqzLK114OMHVVISfk/CHGT0sZonrDUL8zPB1hT+L9IBdeeUXZ701guLyPI59WzbLWoAAKfLOKyzx
j6ptBZNscsdW699QIyjlRRA96Gejrw5VD5AJYu9LWaL2U/HANeQvwSS9eS9OICI7/RogsKQOLHDt
dD+4E5UGUcjohybKpFtqFiGS3XNgnhAY3jyB6ugYw3yJ8otQPr0R4hUDqDZ9MwFsSBXXiJCZBMXM
5gf0vPSQ7RPi6ovDj6MzD8EpTBNO2hVWcXNyglD2mjN8orGoGjR0ZVzO0eurU+AagNjqOknkJjCb
5RyKqKkVMoaZkgoQI1YS4PbOTOK7vtuNknMBZi9iPrJyJ0U27U1W45eZ/zo1PqVUSlJZS2Db7v54
EX9K3BR5YLZrZAPbFYPhor72I5dQ8AkzNqdxliXzuUJ92zg/LFis6ELhDtjTO0wugumDLmsx2d1H
hk9tl5EuT+IocTUW0fJz/iUrB0ckYyfI+PbZa/wSMVYIwFNCr5zQM378BvAxRAMU8Vjq8moNqRGy
g77FGr8H6lnco4g175x2MjxNBiLOFeXdntiP2t7SxDnlF4HPOEfrf4htWRvfn0IUrn7PqLBmZdo3
r5+qPeoott7VMVgWglvquxl1AnMaykgaIZOQCo6ThKd9OyMYkomgjaw=
-----END CERTIFICATE-----

Certum EC-384 CA
================
-----BEGIN CERTIFICATE-----
MIICZTCCAeugAwIBAgIQeI8nXIESUiClBNAt3bpz9DAKBggqhkjOPQQDAzB0MQswCQYDVQQGEwJQ
TDEhMB8GA1UEChMYQXNzZWNvIERhdGEgU3lzdGVtcyBTLkEuMScwJQYDVQQLEx5DZXJ0dW0gQ2Vy
dGlmaWNhdGlvbiBBdXRob3JpdHkxGTAXBgNVBAMTEENlcnR1bSBFQy0zODQgQ0EwHhcNMTgwMzI2
MDcyNDU0WhcNNDMwMzI2MDcyNDU0WjB0MQswCQYDVQQGEwJQTDEhMB8GA1UEChMYQXNzZWNvIERh
dGEgU3lzdGVtcyBTLkEuMScwJQYDVQQLEx5DZXJ0dW0gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkx
GTAXBgNVBAMTEENlcnR1bSBFQy0zODQgQ0EwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAATEKI6rGFtq
vm5kN2PkzeyrOvfMobgOgknXhimfoZTy42B4mIF4Bk3y7JoOV2CDn7TmFy8as10CW4kjPMIRBSqn
iBMY81CE1700LCeJVf/OTOffph8oxPBUw7l8t1Ot68KjQjBAMA8GA1UdEwEB/wQFMAMBAf8wHQYD
VR0OBBYEFI0GZnQkdjrzife81r1HfS+8EF9LMA4GA1UdDwEB/wQEAwIBBjAKBggqhkjOPQQDAwNo
ADBlAjADVS2m5hjEfO/JUG7BJw+ch69u1RsIGL2SKcHvlJF40jocVYli5RsJHrpka/F2tNQCMQC0
QoSZ/6vnnvuRlydd3LBbMHHOXjgaatkl5+r3YZJW+OraNsKHZZYuciUvf9/DE8k=
-----END CERTIFICATE-----

Certum Trusted Root CA
======================
-----BEGIN CERTIFICATE-----
MIIFwDCCA6igAwIBAgIQHr9ZULjJgDdMBvfrVU+17TANBgkqhkiG9w0BAQ0FADB6MQswCQYDVQQG
EwJQTDEhMB8GA1UEChMYQXNzZWNvIERhdGEgU3lzdGVtcyBTLkEuMScwJQYDVQQLEx5DZXJ0dW0g
Q2VydGlmaWNhdGlvbiBBdXRob3JpdHkxHzAdBgNVBAMTFkNlcnR1bSBUcnVzdGVkIFJvb3QgQ0Ew
HhcNMTgwMzE2MTIxMDEzWhcNNDMwMzE2MTIxMDEzWjB6MQswCQYDVQQGEwJQTDEhMB8GA1UEChMY
QXNzZWNvIERhdGEgU3lzdGVtcyBTLkEuMScwJQYDVQQLEx5DZXJ0dW0gQ2VydGlmaWNhdGlvbiBB
dXRob3JpdHkxHzAdBgNVBAMTFkNlcnR1bSBUcnVzdGVkIFJvb3QgQ0EwggIiMA0GCSqGSIb3DQEB
AQUAA4ICDwAwggIKAoICAQDRLY67tzbqbTeRn06TpwXkKQMlzhyC93yZn0EGze2jusDbCSzBfN8p
fktlL5On1AFrAygYo9idBcEq2EXxkd7fO9CAAozPOA/qp1x4EaTByIVcJdPTsuclzxFUl6s1wB52
HO8AU5853BSlLCIls3Jy/I2z5T4IHhQqNwuIPMqw9MjCoa68wb4pZ1Xi/K1ZXP69VyywkI3C7Te2
fJmItdUDmj0VDT06qKhF8JVOJVkdzZhpu9PMMsmN74H+rX2Ju7pgE8pllWeg8xn2A1bUatMn4qGt
g/BKEiJ3HAVz4hlxQsDsdUaakFjgao4rpUYwBI4Zshfjvqm6f1bxJAPXsiEodg42MEx51UGamqi4
NboMOvJEGyCI98Ul1z3G4z5D3Yf+xOr1Uz5MZf87Sst4WmsXXw3Hw09Omiqi7VdNIuJGmj8PkTQk
fVXjjJU30xrwCSss0smNtA0Aq2cpKNgB9RkEth2+dv5yXMSFytKAQd8FqKPVhJBPC/PgP5sZ0jeJ
P/J7UhyM9uH3PAeXjA6iWYEMspA90+NZRu0PqafegGtaqge2Gcu8V/OXIXoMsSt0Puvap2ctTMSY
njYJdmZm/Bo/6khUHL4wvYBQv3y1zgD2DGHZ5yQD4OMBgQ692IU0iL2yNqh7XAjlRICMb/gv1SHK
HRzQ+8S1h9E6Tsd2tTVItQIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBSM+xx1
vALTn04uSNn5YFSqxLNP+jAOBgNVHQ8BAf8EBAMCAQYwDQYJKoZIhvcNAQENBQADggIBAEii1QAL
LtA/vBzVtVRJHlpr9OTy4EA34MwUe7nJ+jW1dReTagVphZzNTxl4WxmB82M+w85bj/UvXgF2Ez8s
ALnNllI5SW0ETsXpD4YN4fqzX4IS8TrOZgYkNCvozMrnadyHncI013nR03e4qllY/p0m+jiGPp2K
h2RX5Rc64vmNueMzeMGQ2Ljdt4NR5MTMI9UGfOZR0800McD2RrsLrfw9EAUqO0qRJe6M1ISHgCq8
CYyqOhNf6DR5UMEQGfnTKB7U0VEwKbOukGfWHwpjscWpxkIxYxeU72nLL/qMFH3EQxiJ2fAyQOaA
4kZf5ePBAFmo+eggvIksDkc0C+pXwlM2/KfUrzHN/gLldfq5Jwn58/U7yn2fqSLLiMmq0Uc9Nneo
WWRrJ8/vJ8HjJLWG965+Mk2weWjROeiQWMODvA8s1pfrzgzhIMfatz7DP78v3DSk+yshzWePS/Tj
6tQ/50+6uaWTRRxmHyH6ZF5v4HaUMst19W7l9o/HuKTMqJZ9ZPskWkoDbGs4xugDQ5r3V7mzKWmT
OPQD8rv7gmsHINFSH5pkAnuYZttcTVoP0ISVoDwUQwbKytu4QTbaakRnh6+v40URFWkIsr4WOZck
bxJF0WddCajJFdr60qZfE2Efv4WstK2tBZQIgx51F9NxO5NQI1mg7TyRVJ12AMXDuDjb
-----END CERTIFICATE-----

TunTrust Root CA
================
-----BEGIN CERTIFICATE-----
MIIFszCCA5ugAwIBAgIUEwLV4kBMkkaGFmddtLu7sms+/BMwDQYJKoZIhvcNAQELBQAwYTELMAkG
A1UEBhMCVE4xNzA1BgNVBAoMLkFnZW5jZSBOYXRpb25hbGUgZGUgQ2VydGlmaWNhdGlvbiBFbGVj
dHJvbmlxdWUxGTAXBgNVBAMMEFR1blRydXN0IFJvb3QgQ0EwHhcNMTkwNDI2MDg1NzU2WhcNNDQw
NDI2MDg1NzU2WjBhMQswCQYDVQQGEwJUTjE3MDUGA1UECgwuQWdlbmNlIE5hdGlvbmFsZSBkZSBD
ZXJ0aWZpY2F0aW9uIEVsZWN0cm9uaXF1ZTEZMBcGA1UEAwwQVHVuVHJ1c3QgUm9vdCBDQTCCAiIw
DQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAMPN0/y9BFPdDCA61YguBUtB9YOCfvdZn56eY+hz
2vYGqU8ftPkLHzmMmiDQfgbU7DTZhrx1W4eI8NLZ1KMKsmwb60ksPqxd2JQDoOw05TDENX37Jk0b
bjBU2PWARZw5rZzJJQRNmpA+TkBuimvNKWfGzC3gdOgFVwpIUPp6Q9p+7FuaDmJ2/uqdHYVy7BG7
NegfJ7/Boce7SBbdVtfMTqDhuazb1YMZGoXRlJfXyqNlC/M4+QKu3fZnz8k/9YosRxqZbwUN/dAd
gjH8KcwAWJeRTIAAHDOFli/LQcKLEITDCSSJH7UP2dl3RxiSlGBcx5kDPP73lad9UKGAwqmDrViW
VSHbhlnUr8a83YFuB9tgYv7sEG7aaAH0gxupPqJbI9dkxt/con3YS7qC0lH4Zr8GRuR5KiY2eY8f
Tpkdso8MDhz/yV3A/ZAQprE38806JG60hZC/gLkMjNWb1sjxVj8agIl6qeIbMlEsPvLfe/ZdeikZ
juXIvTZxi11Mwh0/rViizz1wTaZQmCXcI/m4WEEIcb9PuISgjwBUFfyRbVinljvrS5YnzWuioYas
DXxU5mZMZl+QviGaAkYt5IPCgLnPSz7ofzwB7I9ezX/SKEIBlYrilz0QIX32nRzFNKHsLA4KUiwS
VXAkPcvCFDVDXSdOvsC9qnyW5/yeYa1E0wCXAgMBAAGjYzBhMB0GA1UdDgQWBBQGmpsfU33x9aTI
04Y+oXNZtPdEITAPBgNVHRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFAaamx9TffH1pMjThj6hc1m0
90QhMA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQsFAAOCAgEAqgVutt0Vyb+zxiD2BkewhpMl
0425yAA/l/VSJ4hxyXT968pk21vvHl26v9Hr7lxpuhbI87mP0zYuQEkHDVneixCwSQXi/5E/S7fd
Ao74gShczNxtr18UnH1YeA32gAm56Q6XKRm4t+v4FstVEuTGfbvE7Pi1HE4+Z7/FXxttbUcoqgRY
YdZ2vyJ/0Adqp2RT8JeNnYA/u8EH22Wv5psymsNUk8QcCMNE+3tjEUPRahphanltkE8pjkcFwRJp
adbGNjHh/PqAulxPxOu3Mqz4dWEX1xAZufHSCe96Qp1bWgvUxpVOKs7/B9dPfhgGiPEZtdmYu65x
xBzndFlY7wyJz4sfdZMaBBSSSFCp61cpABbjNhzI+L/wM9VBD8TMPN3pM0MBkRArHtG5Xc0yGYuP
jCB31yLEQtyEFpslbei0VXF/sHyz03FJuc9SpAQ/3D2gu68zngowYI7bnV2UqL1g52KAdoGDDIzM
MEZJ4gzSqK/rYXHv5yJiqfdcZGyfFoxnNidF9Ql7v/YQCvGwjVRDjAS6oz/v4jXH+XTgbzRB0L9z
ZVcg+ZtnemZoJE6AZb0QmQZZ8mWvuMZHu/2QeItBcy6vVR/cO5JyboTT0GFMDcx2V+IthSIVNg3r
AZ3r2OvEhJn7wAzMMujjd9qDRIueVSjAi1jTkD5OGwDxFa2DK5o=
-----END CERTIFICATE-----

HARICA TLS RSA Root CA 2021
===========================
-----BEGIN CERTIFICATE-----
MIIFpDCCA4ygAwIBAgIQOcqTHO9D88aOk8f0ZIk4fjANBgkqhkiG9w0BAQsFADBsMQswCQYDVQQG
EwJHUjE3MDUGA1UECgwuSGVsbGVuaWMgQWNhZGVtaWMgYW5kIFJlc2VhcmNoIEluc3RpdHV0aW9u
cyBDQTEkMCIGA1UEAwwbSEFSSUNBIFRMUyBSU0EgUm9vdCBDQSAyMDIxMB4XDTIxMDIxOTEwNTUz
OFoXDTQ1MDIxMzEwNTUzN1owbDELMAkGA1UEBhMCR1IxNzA1BgNVBAoMLkhlbGxlbmljIEFjYWRl
bWljIGFuZCBSZXNlYXJjaCBJbnN0aXR1dGlvbnMgQ0ExJDAiBgNVBAMMG0hBUklDQSBUTFMgUlNB
IFJvb3QgQ0EgMjAyMTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAIvC569lmwVnlskN
JLnQDmT8zuIkGCyEf3dRywQRNrhe7Wlxp57kJQmXZ8FHws+RFjZiPTgE4VGC/6zStGndLuwRo0Xu
a2s7TL+MjaQenRG56Tj5eg4MmOIjHdFOY9TnuEFE+2uva9of08WRiFukiZLRgeaMOVig1mlDqa2Y
Ulhu2wr7a89o+uOkXjpFc5gH6l8Cct4MpbOfrqkdtx2z/IpZ525yZa31MJQjB/OCFks1mJxTuy/K
5FrZx40d/JiZ+yykgmvwKh+OC19xXFyuQnspiYHLA6OZyoieC0AJQTPb5lh6/a6ZcMBaD9YThnEv
dmn8kN3bLW7R8pv1GmuebxWMevBLKKAiOIAkbDakO/IwkfN4E8/BPzWr8R0RI7VDIp4BkrcYAuUR
0YLbFQDMYTfBKnya4dC6s1BG7oKsnTH4+yPiAwBIcKMJJnkVU2DzOFytOOqBAGMUuTNe3QvboEUH
GjMJ+E20pwKmafTCWQWIZYVWrkvL4N48fS0ayOn7H6NhStYqE613TBoYm5EPWNgGVMWX+Ko/IIqm
haZ39qb8HOLubpQzKoNQhArlT4b4UEV4AIHrW2jjJo3Me1xR9BQsQL4aYB16cmEdH2MtiKrOokWQ
CPxrvrNQKlr9qEgYRtaQQJKQCoReaDH46+0N0x3GfZkYVVYnZS6NRcUk7M7jAgMBAAGjQjBAMA8G
A1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFApII6ZgpJIKM+qTW8VX6iVNvRLuMA4GA1UdDwEB/wQE
AwIBhjANBgkqhkiG9w0BAQsFAAOCAgEAPpBIqm5iFSVmewzVjIuJndftTgfvnNAUX15QvWiWkKQU
EapobQk1OUAJ2vQJLDSle1mESSmXdMgHHkdt8s4cUCbjnj1AUz/3f5Z2EMVGpdAgS1D0NTsY9FVq
QRtHBmg8uwkIYtlfVUKqrFOFrJVWNlar5AWMxajaH6NpvVMPxP/cyuN+8kyIhkdGGvMA9YCRotxD
QpSbIPDRzbLrLFPCU3hKTwSUQZqPJzLB5UkZv/HywouoCjkxKLR9YjYsTewfM7Z+d21+UPCfDtcR
j88YxeMn/ibvBZ3PzzfF0HvaO7AWhAw6k9a+F9sPPg4ZeAnHqQJyIkv3N3a6dcSFA1pj1bF1BcK5
vZStjBWZp5N99sXzqnTPBIWUmAD04vnKJGW/4GKvyMX6ssmeVkjaef2WdhW+o45WxLM0/L5H9MG0
qPzVMIho7suuyWPEdr6sOBjhXlzPrjoiUevRi7PzKzMHVIf6tLITe7pTBGIBnfHAT+7hOtSLIBD6
Alfm78ELt5BGnBkpjNxvoEppaZS3JGWg/6w/zgH7IS79aPib8qXPMThcFarmlwDB31qlpzmq6YR/
PFGoOtmUW4y/Twhx5duoXNTSpv4Ao8YWxw/ogM4cKGR0GQjTQuPOAF1/sdwTsOEFy9EgqoZ0njnn
kf3/W9b3raYvAwtt41dU63ZTGI0RmLo=
-----END CERTIFICATE-----

HARICA TLS ECC Root CA 2021
===========================
-----BEGIN CERTIFICATE-----
MIICVDCCAdugAwIBAgIQZ3SdjXfYO2rbIvT/WeK/zjAKBggqhkjOPQQDAzBsMQswCQYDVQQGEwJH
UjE3MDUGA1UECgwuSGVsbGVuaWMgQWNhZGVtaWMgYW5kIFJlc2VhcmNoIEluc3RpdHV0aW9ucyBD
QTEkMCIGA1UEAwwbSEFSSUNBIFRMUyBFQ0MgUm9vdCBDQSAyMDIxMB4XDTIxMDIxOTExMDExMFoX
DTQ1MDIxMzExMDEwOVowbDELMAkGA1UEBhMCR1IxNzA1BgNVBAoMLkhlbGxlbmljIEFjYWRlbWlj
IGFuZCBSZXNlYXJjaCBJbnN0aXR1dGlvbnMgQ0ExJDAiBgNVBAMMG0hBUklDQSBUTFMgRUNDIFJv
b3QgQ0EgMjAyMTB2MBAGByqGSM49AgEGBSuBBAAiA2IABDgI/rGgltJ6rK9JOtDA4MM7KKrxcm1l
AEeIhPyaJmuqS7psBAqIXhfyVYf8MLA04jRYVxqEU+kw2anylnTDUR9YSTHMmE5gEYd103KUkE+b
ECUqqHgtvpBBWJAVcqeht6NCMEAwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUyRtTgRL+BNUW
0aq8mm+3oJUZbsowDgYDVR0PAQH/BAQDAgGGMAoGCCqGSM49BAMDA2cAMGQCMBHervjcToiwqfAi
rcJRQO9gcS3ujwLEXQNwSaSS6sUUiHCm0w2wqsosQJz76YJumgIwK0eaB8bRwoF8yguWGEEbo/Qw
CZ61IygNnxS2PFOiTAZpffpskcYqSUXm7LcT4Tps
-----END CERTIFICATE-----

Autoridad de Certificacion Firmaprofesional CIF A62634068
=========================================================
-----BEGIN CERTIFICATE-----
MIIGFDCCA/ygAwIBAgIIG3Dp0v+ubHEwDQYJKoZIhvcNAQELBQAwUTELMAkGA1UEBhMCRVMxQjBA
BgNVBAMMOUF1dG9yaWRhZCBkZSBDZXJ0aWZpY2FjaW9uIEZpcm1hcHJvZmVzaW9uYWwgQ0lGIEE2
MjYzNDA2ODAeFw0xNDA5MjMxNTIyMDdaFw0zNjA1MDUxNTIyMDdaMFExCzAJBgNVBAYTAkVTMUIw
QAYDVQQDDDlBdXRvcmlkYWQgZGUgQ2VydGlmaWNhY2lvbiBGaXJtYXByb2Zlc2lvbmFsIENJRiBB
NjI2MzQwNjgwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDKlmuO6vj78aI14H9M2uDD
Utd9thDIAl6zQyrET2qyyhxdKJp4ERppWVevtSBC5IsP5t9bpgOSL/UR5GLXMnE42QQMcas9UX4P
B99jBVzpv5RvwSmCwLTaUbDBPLutN0pcyvFLNg4kq7/DhHf9qFD0sefGL9ItWY16Ck6WaVICqjaY
7Pz6FIMMNx/Jkjd/14Et5cS54D40/mf0PmbR0/RAz15iNA9wBj4gGFrO93IbJWyTdBSTo3OxDqqH
ECNZXyAFGUftaI6SEspd/NYrspI8IM/hX68gvqB2f3bl7BqGYTM+53u0P6APjqK5am+5hyZvQWyI
plD9amML9ZMWGxmPsu2bm8mQ9QEM3xk9Dz44I8kvjwzRAv4bVdZO0I08r0+k8/6vKtMFnXkIoctX
MbScyJCyZ/QYFpM6/EfY0XiWMR+6KwxfXZmtY4laJCB22N/9q06mIqqdXuYnin1oKaPnirjaEbsX
LZmdEyRG98Xi2J+Of8ePdG1asuhy9azuJBCtLxTa/y2aRnFHvkLfuwHb9H/TKI8xWVvTyQKmtFLK
bpf7Q8UIJm+K9Lv9nyiqDdVF8xM6HdjAeI9BZzwelGSuewvF6NkBiDkal4ZkQdU7hwxu+g/GvUgU
vzlN1J5Bto+WHWOWk9mVBngxaJ43BjuAiUVhOSPHG0SjFeUc+JIwuwIDAQABo4HvMIHsMB0GA1Ud
DgQWBBRlzeurNR4APn7VdMActHNHDhpkLzASBgNVHRMBAf8ECDAGAQH/AgEBMIGmBgNVHSAEgZ4w
gZswgZgGBFUdIAAwgY8wLwYIKwYBBQUHAgEWI2h0dHA6Ly93d3cuZmlybWFwcm9mZXNpb25hbC5j
b20vY3BzMFwGCCsGAQUFBwICMFAeTgBQAGEAcwBlAG8AIABkAGUAIABsAGEAIABCAG8AbgBhAG4A
bwB2AGEAIAA0ADcAIABCAGEAcgBjAGUAbABvAG4AYQAgADAAOAAwADEANzAOBgNVHQ8BAf8EBAMC
AQYwDQYJKoZIhvcNAQELBQADggIBAHSHKAIrdx9miWTtj3QuRhy7qPj4Cx2Dtjqn6EWKB7fgPiDL
4QjbEwj4KKE1soCzC1HA01aajTNFSa9J8OA9B3pFE1r/yJfY0xgsfZb43aJlQ3CTkBW6kN/oGbDb
LIpgD7dvlAceHabJhfa9NPhAeGIQcDq+fUs5gakQ1JZBu/hfHAsdCPKxsIl68veg4MSPi3i1O1il
I45PVf42O+AMt8oqMEEgtIDNrvx2ZnOorm7hfNoD6JQg5iKj0B+QXSBTFCZX2lSX3xZEEAEeiGaP
cjiT3SC3NL7X8e5jjkd5KAb881lFJWAiMxujX6i6KtoaPc1A6ozuBRWV1aUsIC+nmCjuRfzxuIgA
LI9C2lHVnOUTaHFFQ4ueCyE8S1wF3BqfmI7avSKecs2tCsvMo2ebKHTEm9caPARYpoKdrcd7b/+A
lun4jWq9GJAd/0kakFI3ky88Al2CdgtR5xbHV/g4+afNmyJU72OwFW1TZQNKXkqgsqeOSQBZONXH
9IBk9W6VULgRfhVwOEqwf9DEMnDAGf/JOC0ULGb0QkTmVXYbgBVX/8Cnp6o5qtjTcNAuuuuUavpf
NIbnYrX9ivAwhZTJryQCL2/W3Wf+47BVTwSYT6RBVuKT0Gro1vP7ZeDOdcQxWQzugsgMYDNKGbqE
ZycPvEJdvSRUDewdcAZfpLz6IHxV
-----END CERTIFICATE-----

vTrus ECC Root CA
=================
-----BEGIN CERTIFICATE-----
MIICDzCCAZWgAwIBAgIUbmq8WapTvpg5Z6LSa6Q75m0c1towCgYIKoZIzj0EAwMwRzELMAkGA1UE
BhMCQ04xHDAaBgNVBAoTE2lUcnVzQ2hpbmEgQ28uLEx0ZC4xGjAYBgNVBAMTEXZUcnVzIEVDQyBS
b290IENBMB4XDTE4MDczMTA3MjY0NFoXDTQzMDczMTA3MjY0NFowRzELMAkGA1UEBhMCQ04xHDAa
BgNVBAoTE2lUcnVzQ2hpbmEgQ28uLEx0ZC4xGjAYBgNVBAMTEXZUcnVzIEVDQyBSb290IENBMHYw
EAYHKoZIzj0CAQYFK4EEACIDYgAEZVBKrox5lkqqHAjDo6LN/llWQXf9JpRCux3NCNtzslt188+c
ToL0v/hhJoVs1oVbcnDS/dtitN9Ti72xRFhiQgnH+n9bEOf+QP3A2MMrMudwpremIFUde4BdS49n
TPEQo0IwQDAdBgNVHQ4EFgQUmDnNvtiyjPeyq+GtJK97fKHbH88wDwYDVR0TAQH/BAUwAwEB/zAO
BgNVHQ8BAf8EBAMCAQYwCgYIKoZIzj0EAwMDaAAwZQIwV53dVvHH4+m4SVBrm2nDb+zDfSXkV5UT
QJtS0zvzQBm8JsctBp61ezaf9SXUY2sAAjEA6dPGnlaaKsyh2j/IZivTWJwghfqrkYpwcBE4YGQL
YgmRWAD5Tfs0aNoJrSEGGJTO
-----END CERTIFICATE-----

vTrus Root CA
=============
-----BEGIN CERTIFICATE-----
MIIFVjCCAz6gAwIBAgIUQ+NxE9izWRRdt86M/TX9b7wFjUUwDQYJKoZIhvcNAQELBQAwQzELMAkG
A1UEBhMCQ04xHDAaBgNVBAoTE2lUcnVzQ2hpbmEgQ28uLEx0ZC4xFjAUBgNVBAMTDXZUcnVzIFJv
b3QgQ0EwHhcNMTgwNzMxMDcyNDA1WhcNNDMwNzMxMDcyNDA1WjBDMQswCQYDVQQGEwJDTjEcMBoG
A1UEChMTaVRydXNDaGluYSBDby4sTHRkLjEWMBQGA1UEAxMNdlRydXMgUm9vdCBDQTCCAiIwDQYJ
KoZIhvcNAQEBBQADggIPADCCAgoCggIBAL1VfGHTuB0EYgWgrmy3cLRB6ksDXhA/kFocizuwZots
SKYcIrrVQJLuM7IjWcmOvFjai57QGfIvWcaMY1q6n6MLsLOaXLoRuBLpDLvPbmyAhykUAyyNJJrI
ZIO1aqwTLDPxn9wsYTwaP3BVm60AUn/PBLn+NvqcwBauYv6WTEN+VRS+GrPSbcKvdmaVayqwlHeF
XgQPYh1jdfdr58tbmnDsPmcF8P4HCIDPKNsFxhQnL4Z98Cfe/+Z+M0jnCx5Y0ScrUw5XSmXX+6KA
YPxMvDVTAWqXcoKv8R1w6Jz1717CbMdHflqUhSZNO7rrTOiwCcJlwp2dCZtOtZcFrPUGoPc2BX70
kLJrxLT5ZOrpGgrIDajtJ8nU57O5q4IikCc9Kuh8kO+8T/3iCiSn3mUkpF3qwHYw03dQ+A0Em5Q2
AXPKBlim0zvc+gRGE1WKyURHuFE5Gi7oNOJ5y1lKCn+8pu8fA2dqWSslYpPZUxlmPCdiKYZNpGvu
/9ROutW04o5IWgAZCfEF2c6Rsffr6TlP9m8EQ5pV9T4FFL2/s1m02I4zhKOQUqqzApVg+QxMaPnu
1RcN+HFXtSXkKe5lXa/R7jwXC1pDxaWG6iSe4gUH3DRCEpHWOXSuTEGC2/KmSNGzm/MzqvOmwMVO
9fSddmPmAsYiS8GVP1BkLFTltvA8Kc9XAgMBAAGjQjBAMB0GA1UdDgQWBBRUYnBj8XWEQ1iO0RYg
scasGrz2iTAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQsFAAOC
AgEAKbqSSaet8PFww+SX8J+pJdVrnjT+5hpk9jprUrIQeBqfTNqK2uwcN1LgQkv7bHbKJAs5EhWd
nxEt/Hlk3ODg9d3gV8mlsnZwUKT+twpw1aA08XXXTUm6EdGz2OyC/+sOxL9kLX1jbhd47F18iMjr
jld22VkE+rxSH0Ws8HqA7Oxvdq6R2xCOBNyS36D25q5J08FsEhvMKar5CKXiNxTKsbhm7xqC5PD4
8acWabfbqWE8n/Uxy+QARsIvdLGx14HuqCaVvIivTDUHKgLKeBRtRytAVunLKmChZwOgzoy8sHJn
xDHO2zTlJQNgJXtxmOTAGytfdELSS8VZCAeHvsXDf+eW2eHcKJfWjwXj9ZtOyh1QRwVTsMo554Wg
icEFOwE30z9J4nfrI8iIZjs9OXYhRvHsXyO466JmdXTBQPfYaJqT4i2pLr0cox7IdMakLXogqzu4
sEb9b91fUlV1YvCXoHzXOP0l382gmxDPi7g4Xl7FtKYCNqEeXxzP4padKar9mK5S4fNBUvupLnKW
nyfjqnN9+BojZns7q2WwMgFLFT49ok8MKzWixtlnEjUwzXYuFrOZnk1PTi07NEPhmg4NpGaXutIc
SkwsKouLgU9xGqndXHt7CMUADTdA43x7VF8vhV929vensBxXVsFy6K2ir40zSbofitzmdHxghm+H
l3s=
-----END CERTIFICATE-----

ISRG Root X2
============
-----BEGIN CERTIFICATE-----
MIICGzCCAaGgAwIBAgIQQdKd0XLq7qeAwSxs6S+HUjAKBggqhkjOPQQDAzBPMQswCQYDVQQGEwJV
UzEpMCcGA1UEChMgSW50ZXJuZXQgU2VjdXJpdHkgUmVzZWFyY2ggR3JvdXAxFTATBgNVBAMTDElT
UkcgUm9vdCBYMjAeFw0yMDA5MDQwMDAwMDBaFw00MDA5MTcxNjAwMDBaME8xCzAJBgNVBAYTAlVT
MSkwJwYDVQQKEyBJbnRlcm5ldCBTZWN1cml0eSBSZXNlYXJjaCBHcm91cDEVMBMGA1UEAxMMSVNS
RyBSb290IFgyMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAEzZvVn4CDCuwJSvMWSj5cz3es3mcFDR0H
ttwW+1qLFNvicWDEukWVEYmO6gbf9yoWHKS5xcUy4APgHoIYOIvXRdgKam7mAHf7AlF9ItgKbppb
d9/w+kHsOdx1ymgHDB/qo0IwQDAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNV
HQ4EFgQUfEKWrt5LSDv6kviejM9ti6lyN5UwCgYIKoZIzj0EAwMDaAAwZQIwe3lORlCEwkSHRhtF
cP9Ymd70/aTSVaYgLXTWNLxBo1BfASdWtL4ndQavEi51mI38AjEAi/V3bNTIZargCyzuFJ0nN6T5
U6VR5CmD1/iQMVtCnwr1/q4AaOeMSQ+2b1tbFfLn
-----END CERTIFICATE-----

HiPKI Root CA - G1
==================
-----BEGIN CERTIFICATE-----
MIIFajCCA1KgAwIBAgIQLd2szmKXlKFD6LDNdmpeYDANBgkqhkiG9w0BAQsFADBPMQswCQYDVQQG
EwJUVzEjMCEGA1UECgwaQ2h1bmdod2EgVGVsZWNvbSBDby4sIEx0ZC4xGzAZBgNVBAMMEkhpUEtJ
IFJvb3QgQ0EgLSBHMTAeFw0xOTAyMjIwOTQ2MDRaFw0zNzEyMzExNTU5NTlaME8xCzAJBgNVBAYT
AlRXMSMwIQYDVQQKDBpDaHVuZ2h3YSBUZWxlY29tIENvLiwgTHRkLjEbMBkGA1UEAwwSSGlQS0kg
Um9vdCBDQSAtIEcxMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA9B5/UnMyDHPkvRN0
o9QwqNCuS9i233VHZvR85zkEHmpwINJaR3JnVfSl6J3VHiGh8Ge6zCFovkRTv4354twvVcg3Px+k
wJyz5HdcoEb+d/oaoDjq7Zpy3iu9lFc6uux55199QmQ5eiY29yTw1S+6lZgRZq2XNdZ1AYDgr/SE
YYwNHl98h5ZeQa/rh+r4XfEuiAU+TCK72h8q3VJGZDnzQs7ZngyzsHeXZJzA9KMuH5UHsBffMNsA
GJZMoYFL3QRtU6M9/Aes1MU3guvklQgZKILSQjqj2FPseYlgSGDIcpJQ3AOPgz+yQlda22rpEZfd
hSi8MEyr48KxRURHH+CKFgeW0iEPU8DtqX7UTuybCeyvQqww1r/REEXgphaypcXTT3OUM3ECoWqj
1jOXTyFjHluP2cFeRXF3D4FdXyGarYPM+l7WjSNfGz1BryB1ZlpK9p/7qxj3ccC2HTHsOyDry+K4
9a6SsvfhhEvyovKTmiKe0xRvNlS9H15ZFblzqMF8b3ti6RZsR1pl8w4Rm0bZ/W3c1pzAtH2lsN0/
Vm+h+fbkEkj9Bn8SV7apI09bA8PgcSojt/ewsTu8mL3WmKgMa/aOEmem8rJY5AIJEzypuxC00jBF
8ez3ABHfZfjcK0NVvxaXxA/VLGGEqnKG/uY6fsI/fe78LxQ+5oXdUG+3Se0CAwEAAaNCMEAwDwYD
VR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQU8ncX+l6o/vY9cdVouslGDDjYr7AwDgYDVR0PAQH/BAQD
AgGGMA0GCSqGSIb3DQEBCwUAA4ICAQBQUfB13HAE4/+qddRxosuej6ip0691x1TPOhwEmSKsxBHi
7zNKpiMdDg1H2DfHb680f0+BazVP6XKlMeJ45/dOlBhbQH3PayFUhuaVevvGyuqcSE5XCV0vrPSl
tJczWNWseanMX/mF+lLFjfiRFOs6DRfQUsJ748JzjkZ4Bjgs6FzaZsT0pPBWGTMpWmWSBUdGSquE
wx4noR8RkpkndZMPvDY7l1ePJlsMu5wP1G4wB9TcXzZoZjmDlicmisjEOf6aIW/Vcobpf2Lll07Q
JNBAsNB1CI69aO4I1258EHBGG3zgiLKecoaZAeO/n0kZtCW+VmWuF2PlHt/o/0elv+EmBYTksMCv
5wiZqAxeJoBF1PhoL5aPruJKHJwWDBNvOIf2u8g0X5IDUXlwpt/L9ZlNec1OvFefQ05rLisY+Gpz
jLrFNe85akEez3GoorKGB1s6yeHvP2UEgEcyRHCVTjFnanRbEEV16rCf0OY1/k6fi8wrkkVbbiVg
hUbN0aqwdmaTd5a+g744tiROJgvM7XpWGuDpWsZkrUx6AEhEL7lAuxM+vhV4nYWBSipX3tUZQ9rb
yltHhoMLP7YNdnhzeSJesYAfz77RP1YQmCuVh6EfnWQUYDksswBVLuT1sw5XxJFBAJw/6KXf6vb/
yPCtbVKoF6ubYfwSUTXkJf2vqmqGOQ==
-----END CERTIFICATE-----

GlobalSign ECC Root CA - R4
===========================
-----BEGIN CERTIFICATE-----
MIIB3DCCAYOgAwIBAgINAgPlfvU/k/2lCSGypjAKBggqhkjOPQQDAjBQMSQwIgYDVQQLExtHbG9i
YWxTaWduIEVDQyBSb290IENBIC0gUjQxEzARBgNVBAoTCkdsb2JhbFNpZ24xEzARBgNVBAMTCkds
b2JhbFNpZ24wHhcNMTIxMTEzMDAwMDAwWhcNMzgwMTE5MDMxNDA3WjBQMSQwIgYDVQQLExtHbG9i
YWxTaWduIEVDQyBSb290IENBIC0gUjQxEzARBgNVBAoTCkdsb2JhbFNpZ24xEzARBgNVBAMTCkds
b2JhbFNpZ24wWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAAS4xnnTj2wlDp8uORkcA6SumuU5BwkW
ymOxuYb4ilfBV85C+nOh92VC/x7BALJucw7/xyHlGKSq2XE/qNS5zowdo0IwQDAOBgNVHQ8BAf8E
BAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUVLB7rUW44kB/+wpu+74zyTyjhNUwCgYI
KoZIzj0EAwIDRwAwRAIgIk90crlgr/HmnKAWBVBfw147bmF0774BxL4YSFlhgjICICadVGNA3jdg
UM/I2O2dgq43mLyjj0xMqTQrbO/7lZsm
-----END CERTIFICATE-----

GTS Root R1
===========
-----BEGIN CERTIFICATE-----
MIIFVzCCAz+gAwIBAgINAgPlk28xsBNJiGuiFzANBgkqhkiG9w0BAQwFADBHMQswCQYDVQQGEwJV
UzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEUMBIGA1UEAxMLR1RTIFJvb3Qg
UjEwHhcNMTYwNjIyMDAwMDAwWhcNMzYwNjIyMDAwMDAwWjBHMQswCQYDVQQGEwJVUzEiMCAGA1UE
ChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEUMBIGA1UEAxMLR1RTIFJvb3QgUjEwggIiMA0G
CSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC2EQKLHuOhd5s73L+UPreVp0A8of2C+X0yBoJx9vaM
f/vo27xqLpeXo4xL+Sv2sfnOhB2x+cWX3u+58qPpvBKJXqeqUqv4IyfLpLGcY9vXmX7wCl7raKb0
xlpHDU0QM+NOsROjyBhsS+z8CZDfnWQpJSMHobTSPS5g4M/SCYe7zUjwTcLCeoiKu7rPWRnWr4+w
B7CeMfGCwcDfLqZtbBkOtdh+JhpFAz2weaSUKK0PfyblqAj+lug8aJRT7oM6iCsVlgmy4HqMLnXW
nOunVmSPlk9orj2XwoSPwLxAwAtcvfaHszVsrBhQf4TgTM2S0yDpM7xSma8ytSmzJSq0SPly4cpk
9+aCEI3oncKKiPo4Zor8Y/kB+Xj9e1x3+naH+uzfsQ55lVe0vSbv1gHR6xYKu44LtcXFilWr06zq
kUspzBmkMiVOKvFlRNACzqrOSbTqn3yDsEB750Orp2yjj32JgfpMpf/VjsPOS+C12LOORc92wO1A
K/1TD7Cn1TsNsYqiA94xrcx36m97PtbfkSIS5r762DL8EGMUUXLeXdYWk70paDPvOmbsB4om3xPX
V2V4J95eSRQAogB/mqghtqmxlbCluQ0WEdrHbEg8QOB+DVrNVjzRlwW5y0vtOUucxD/SVRNuJLDW
cfr0wbrM7Rv1/oFB2ACYPTrIrnqYNxgFlQIDAQABo0IwQDAOBgNVHQ8BAf8EBAMCAYYwDwYDVR0T
AQH/BAUwAwEB/zAdBgNVHQ4EFgQU5K8rJnEaK0gnhS9SZizv8IkTcT4wDQYJKoZIhvcNAQEMBQAD
ggIBAJ+qQibbC5u+/x6Wki4+omVKapi6Ist9wTrYggoGxval3sBOh2Z5ofmmWJyq+bXmYOfg6LEe
QkEzCzc9zolwFcq1JKjPa7XSQCGYzyI0zzvFIoTgxQ6KfF2I5DUkzps+GlQebtuyh6f88/qBVRRi
ClmpIgUxPoLW7ttXNLwzldMXG+gnoot7TiYaelpkttGsN/H9oPM47HLwEXWdyzRSjeZ2axfG34ar
J45JK3VmgRAhpuo+9K4l/3wV3s6MJT/KYnAK9y8JZgfIPxz88NtFMN9iiMG1D53Dn0reWVlHxYci
NuaCp+0KueIHoI17eko8cdLiA6EfMgfdG+RCzgwARWGAtQsgWSl4vflVy2PFPEz0tv/bal8xa5me
LMFrUKTX5hgUvYU/Z6tGn6D/Qqc6f1zLXbBwHSs09dR2CQzreExZBfMzQsNhFRAbd03OIozUhfJF
fbdT6u9AWpQKXCBfTkBdYiJ23//OYb2MI3jSNwLgjt7RETeJ9r/tSQdirpLsQBqvFAnZ0E6yove+
7u7Y/9waLd64NnHi/Hm3lCXRSHNboTXns5lndcEZOitHTtNCjv0xyBZm2tIMPNuzjsmhDYAPexZ3
FL//2wmUspO8IFgV6dtxQ/PeEMMA3KgqlbbC1j+Qa3bbbP6MvPJwNQzcmRk13NfIRmPVNnGuV/u3
gm3c
-----END CERTIFICATE-----

GTS Root R2
===========
-----BEGIN CERTIFICATE-----
MIIFVzCCAz+gAwIBAgINAgPlrsWNBCUaqxElqjANBgkqhkiG9w0BAQwFADBHMQswCQYDVQQGEwJV
UzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEUMBIGA1UEAxMLR1RTIFJvb3Qg
UjIwHhcNMTYwNjIyMDAwMDAwWhcNMzYwNjIyMDAwMDAwWjBHMQswCQYDVQQGEwJVUzEiMCAGA1UE
ChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEUMBIGA1UEAxMLR1RTIFJvb3QgUjIwggIiMA0G
CSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDO3v2m++zsFDQ8BwZabFn3GTXd98GdVarTzTukk3Lv
CvptnfbwhYBboUhSnznFt+4orO/LdmgUud+tAWyZH8QiHZ/+cnfgLFuv5AS/T3KgGjSY6Dlo7JUl
e3ah5mm5hRm9iYz+re026nO8/4Piy33B0s5Ks40FnotJk9/BW9BuXvAuMC6C/Pq8tBcKSOWIm8Wb
a96wyrQD8Nr0kLhlZPdcTK3ofmZemde4wj7I0BOdre7kRXuJVfeKH2JShBKzwkCX44ofR5GmdFrS
+LFjKBC4swm4VndAoiaYecb+3yXuPuWgf9RhD1FLPD+M2uFwdNjCaKH5wQzpoeJ/u1U8dgbuak7M
kogwTZq9TwtImoS1mKPV+3PBV2HdKFZ1E66HjucMUQkQdYhMvI35ezzUIkgfKtzra7tEscszcTJG
r61K8YzodDqs5xoic4DSMPclQsciOzsSrZYuxsN2B6ogtzVJV+mSSeh2FnIxZyuWfoqjx5RWIr9q
S34BIbIjMt/kmkRtWVtd9QCgHJvGeJeNkP+byKq0rxFROV7Z+2et1VsRnTKaG73VululycslaVNV
J1zgyjbLiGH7HrfQy+4W+9OmTN6SpdTi3/UGVN4unUu0kzCqgc7dGtxRcw1PcOnlthYhGXmy5okL
dWTK1au8CcEYof/UVKGFPP0UJAOyh9OktwIDAQABo0IwQDAOBgNVHQ8BAf8EBAMCAYYwDwYDVR0T
AQH/BAUwAwEB/zAdBgNVHQ4EFgQUu//KjiOfT5nK2+JopqUVJxce2Q4wDQYJKoZIhvcNAQEMBQAD
ggIBAB/Kzt3HvqGf2SdMC9wXmBFqiN495nFWcrKeGk6c1SuYJF2ba3uwM4IJvd8lRuqYnrYb/oM8
0mJhwQTtzuDFycgTE1XnqGOtjHsB/ncw4c5omwX4Eu55MaBBRTUoCnGkJE+M3DyCB19m3H0Q/gxh
swWV7uGugQ+o+MePTagjAiZrHYNSVc61LwDKgEDg4XSsYPWHgJ2uNmSRXbBoGOqKYcl3qJfEycel
/FVL8/B/uWU9J2jQzGv6U53hkRrJXRqWbTKH7QMgyALOWr7Z6v2yTcQvG99fevX4i8buMTolUVVn
jWQye+mew4K6Ki3pHrTgSAai/GevHyICc/sgCq+dVEuhzf9gR7A/Xe8bVr2XIZYtCtFenTgCR2y5
9PYjJbigapordwj6xLEokCZYCDzifqrXPW+6MYgKBesntaFJ7qBFVHvmJ2WZICGoo7z7GJa7Um8M
7YNRTOlZ4iBgxcJlkoKM8xAfDoqXvneCbT+PHV28SSe9zE8P4c52hgQjxcCMElv924SgJPFI/2R8
0L5cFtHvma3AH/vLrrw4IgYmZNralw4/KBVEqE8AyvCazM90arQ+POuV7LXTWtiBmelDGDfrs7vR
WGJB82bSj6p4lVQgw1oudCvV0b4YacCs1aTPObpRhANl6WLAYv7YTVWW4tAR+kg0Eeye7QUd5MjW
HYbL
-----END CERTIFICATE-----

GTS Root R3
===========
-----BEGIN CERTIFICATE-----
MIICCTCCAY6gAwIBAgINAgPluILrIPglJ209ZjAKBggqhkjOPQQDAzBHMQswCQYDVQQGEwJVUzEi
MCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEUMBIGA1UEAxMLR1RTIFJvb3QgUjMw
HhcNMTYwNjIyMDAwMDAwWhcNMzYwNjIyMDAwMDAwWjBHMQswCQYDVQQGEwJVUzEiMCAGA1UEChMZ
R29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEUMBIGA1UEAxMLR1RTIFJvb3QgUjMwdjAQBgcqhkjO
PQIBBgUrgQQAIgNiAAQfTzOHMymKoYTey8chWEGJ6ladK0uFxh1MJ7x/JlFyb+Kf1qPKzEUURout
736GjOyxfi//qXGdGIRFBEFVbivqJn+7kAHjSxm65FSWRQmx1WyRRK2EE46ajA2ADDL24CejQjBA
MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBTB8Sa6oC2uhYHP0/Eq
Er24Cmf9vDAKBggqhkjOPQQDAwNpADBmAjEA9uEglRR7VKOQFhG/hMjqb2sXnh5GmCCbn9MN2azT
L818+FsuVbu/3ZL3pAzcMeGiAjEA/JdmZuVDFhOD3cffL74UOO0BzrEXGhF16b0DjyZ+hOXJYKaV
11RZt+cRLInUue4X
-----END CERTIFICATE-----

GTS Root R4
===========
-----BEGIN CERTIFICATE-----
MIICCTCCAY6gAwIBAgINAgPlwGjvYxqccpBQUjAKBggqhkjOPQQDAzBHMQswCQYDVQQGEwJVUzEi
MCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEUMBIGA1UEAxMLR1RTIFJvb3QgUjQw
HhcNMTYwNjIyMDAwMDAwWhcNMzYwNjIyMDAwMDAwWjBHMQswCQYDVQQGEwJVUzEiMCAGA1UEChMZ
R29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEUMBIGA1UEAxMLR1RTIFJvb3QgUjQwdjAQBgcqhkjO
PQIBBgUrgQQAIgNiAATzdHOnaItgrkO4NcWBMHtLSZ37wWHO5t5GvWvVYRg1rkDdc/eJkTBa6zzu
hXyiQHY7qca4R9gq55KRanPpsXI5nymfopjTX15YhmUPoYRlBtHci8nHc8iMai/lxKvRHYqjQjBA
MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBSATNbrdP9JNqPV2Py1
PsVq8JQdjDAKBggqhkjOPQQDAwNpADBmAjEA6ED/g94D9J+uHXqnLrmvT/aDHQ4thQEd0dlq7A/C
r8deVl5c1RxYIigL9zC2L7F8AjEA8GE8p/SgguMh1YQdc4acLa/KNJvxn7kjNuK8YAOdgLOaVsjh
4rsUecrNIdSUtUlD
-----END CERTIFICATE-----

Telia Root CA v2
================
-----BEGIN CERTIFICATE-----
MIIFdDCCA1ygAwIBAgIPAWdfJ9b+euPkrL4JWwWeMA0GCSqGSIb3DQEBCwUAMEQxCzAJBgNVBAYT
AkZJMRowGAYDVQQKDBFUZWxpYSBGaW5sYW5kIE95ajEZMBcGA1UEAwwQVGVsaWEgUm9vdCBDQSB2
MjAeFw0xODExMjkxMTU1NTRaFw00MzExMjkxMTU1NTRaMEQxCzAJBgNVBAYTAkZJMRowGAYDVQQK
DBFUZWxpYSBGaW5sYW5kIE95ajEZMBcGA1UEAwwQVGVsaWEgUm9vdCBDQSB2MjCCAiIwDQYJKoZI
hvcNAQEBBQADggIPADCCAgoCggIBALLQPwe84nvQa5n44ndp586dpAO8gm2h/oFlH0wnrI4AuhZ7
6zBqAMCzdGh+sq/H1WKzej9Qyow2RCRj0jbpDIX2Q3bVTKFgcmfiKDOlyzG4OiIjNLh9vVYiQJ3q
9HsDrWj8soFPmNB06o3lfc1jw6P23pLCWBnglrvFxKk9pXSW/q/5iaq9lRdU2HhE8Qx3FZLgmEKn
pNaqIJLNwaCzlrI6hEKNfdWV5Nbb6WLEWLN5xYzTNTODn3WhUidhOPFZPY5Q4L15POdslv5e2QJl
tI5c0BE0312/UqeBAMN/mUWZFdUXyApT7GPzmX3MaRKGwhfwAZ6/hLzRUssbkmbOpFPlob/E2wnW
5olWK8jjfN7j/4nlNW4o6GwLI1GpJQXrSPjdscr6bAhR77cYbETKJuFzxokGgeWKrLDiKca5JLNr
RBH0pUPCTEPlcDaMtjNXepUugqD0XBCzYYP2AgWGLnwtbNwDRm41k9V6lS/eINhbfpSQBGq6WT0E
BXWdN6IOLj3rwaRSg/7Qa9RmjtzG6RJOHSpXqhC8fF6CfaamyfItufUXJ63RDolUK5X6wK0dmBR4
M0KGCqlztft0DbcbMBnEWg4cJ7faGND/isgFuvGqHKI3t+ZIpEYslOqodmJHixBTB0hXbOKSTbau
BcvcwUpej6w9GU7C7WB1K9vBykLVAgMBAAGjYzBhMB8GA1UdIwQYMBaAFHKs5DN5qkWH9v2sHZ7W
xy+G2CQ5MB0GA1UdDgQWBBRyrOQzeapFh/b9rB2e1scvhtgkOTAOBgNVHQ8BAf8EBAMCAQYwDwYD
VR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAgEAoDtZpwmUPjaE0n4vOaWWl/oRrfxn83EJ
8rKJhGdEr7nv7ZbsnGTbMjBvZ5qsfl+yqwE2foH65IRe0qw24GtixX1LDoJt0nZi0f6X+J8wfBj5
tFJ3gh1229MdqfDBmgC9bXXYfef6xzijnHDoRnkDry5023X4blMMA8iZGok1GTzTyVR8qPAs5m4H
eW9q4ebqkYJpCh3DflminmtGFZhb069GHWLIzoBSSRE/yQQSwxN8PzuKlts8oB4KtItUsiRnDe+C
y748fdHif64W1lZYudogsYMVoe+KTTJvQS8TUoKU1xrBeKJR3Stwbbca+few4GeXVtt8YVMJAygC
QMez2P2ccGrGKMOF6eLtGpOg3kuYooQ+BXcBlj37tCAPnHICehIv1aO6UXivKitEZU61/Qrowc15
h2Er3oBXRb9n8ZuRXqWk7FlIEA04x7D6w0RtBPV4UBySllva9bguulvP5fBqnUsvWHMtTy3EHD70
sz+rFQ47GUGKpMFXEmZxTPpT41frYpUJnlTd0cI8Vzy9OK2YZLe4A5pTVmBds9hCG1xLEooc6+t9
xnppxyd/pPiL8uSUZodL6ZQHCRJ5irLrdATczvREWeAWysUsWNc8e89ihmpQfTU2Zqf7N+cox9jQ
raVplI/owd8k+BsHMYeB2F326CjYSlKArBPuUBQemMc=
-----END CERTIFICATE-----

D-TRUST BR Root CA 1 2020
=========================
-----BEGIN CERTIFICATE-----
MIIC2zCCAmCgAwIBAgIQfMmPK4TX3+oPyWWa00tNljAKBggqhkjOPQQDAzBIMQswCQYDVQQGEwJE
RTEVMBMGA1UEChMMRC1UcnVzdCBHbWJIMSIwIAYDVQQDExlELVRSVVNUIEJSIFJvb3QgQ0EgMSAy
MDIwMB4XDTIwMDIxMTA5NDUwMFoXDTM1MDIxMTA5NDQ1OVowSDELMAkGA1UEBhMCREUxFTATBgNV
BAoTDEQtVHJ1c3QgR21iSDEiMCAGA1UEAxMZRC1UUlVTVCBCUiBSb290IENBIDEgMjAyMDB2MBAG
ByqGSM49AgEGBSuBBAAiA2IABMbLxyjR+4T1mu9CFCDhQ2tuda38KwOE1HaTJddZO0Flax7mNCq7
dPYSzuht56vkPE4/RAiLzRZxy7+SmfSk1zxQVFKQhYN4lGdnoxwJGT11NIXe7WB9xwy0QVK5buXu
QqOCAQ0wggEJMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFHOREKv/VbNafAkl1bK6CKBrqx9t
MA4GA1UdDwEB/wQEAwIBBjCBxgYDVR0fBIG+MIG7MD6gPKA6hjhodHRwOi8vY3JsLmQtdHJ1c3Qu
bmV0L2NybC9kLXRydXN0X2JyX3Jvb3RfY2FfMV8yMDIwLmNybDB5oHegdYZzbGRhcDovL2RpcmVj
dG9yeS5kLXRydXN0Lm5ldC9DTj1ELVRSVVNUJTIwQlIlMjBSb290JTIwQ0ElMjAxJTIwMjAyMCxP
PUQtVHJ1c3QlMjBHbWJILEM9REU/Y2VydGlmaWNhdGVyZXZvY2F0aW9ubGlzdDAKBggqhkjOPQQD
AwNpADBmAjEAlJAtE/rhY/hhY+ithXhUkZy4kzg+GkHaQBZTQgjKL47xPoFWwKrY7RjEsK70Pvom
AjEA8yjixtsrmfu3Ubgko6SUeho/5jbiA1czijDLgsfWFBHVdWNbFJWcHwHP2NVypw87
-----END CERTIFICATE-----

D-TRUST EV Root CA 1 2020
=========================
-----BEGIN CERTIFICATE-----
MIIC2zCCAmCgAwIBAgIQXwJB13qHfEwDo6yWjfv/0DAKBggqhkjOPQQDAzBIMQswCQYDVQQGEwJE
RTEVMBMGA1UEChMMRC1UcnVzdCBHbWJIMSIwIAYDVQQDExlELVRSVVNUIEVWIFJvb3QgQ0EgMSAy
MDIwMB4XDTIwMDIxMTEwMDAwMFoXDTM1MDIxMTA5NTk1OVowSDELMAkGA1UEBhMCREUxFTATBgNV
BAoTDEQtVHJ1c3QgR21iSDEiMCAGA1UEAxMZRC1UUlVTVCBFViBSb290IENBIDEgMjAyMDB2MBAG
ByqGSM49AgEGBSuBBAAiA2IABPEL3YZDIBnfl4XoIkqbz52Yv7QFJsnL46bSj8WeeHsxiamJrSc8
ZRCC/N/DnU7wMyPE0jL1HLDfMxddxfCxivnvubcUyilKwg+pf3VlSSowZ/Rk99Yad9rDwpdhQntJ
raOCAQ0wggEJMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFH8QARY3OqQo5FD4pPfsazK2/umL
MA4GA1UdDwEB/wQEAwIBBjCBxgYDVR0fBIG+MIG7MD6gPKA6hjhodHRwOi8vY3JsLmQtdHJ1c3Qu
bmV0L2NybC9kLXRydXN0X2V2X3Jvb3RfY2FfMV8yMDIwLmNybDB5oHegdYZzbGRhcDovL2RpcmVj
dG9yeS5kLXRydXN0Lm5ldC9DTj1ELVRSVVNUJTIwRVYlMjBSb290JTIwQ0ElMjAxJTIwMjAyMCxP
PUQtVHJ1c3QlMjBHbWJILEM9REU/Y2VydGlmaWNhdGVyZXZvY2F0aW9ubGlzdDAKBggqhkjOPQQD
AwNpADBmAjEAyjzGKnXCXnViOTYAYFqLwZOZzNnbQTs7h5kXO9XMT8oi96CAy/m0sRtW9XLS/BnR
AjEAkfcwkz8QRitxpNA7RJvAKQIFskF3UfN5Wp6OFKBOQtJbgfM0agPnIjhQW+0ZT0MW
-----END CERTIFICATE-----

DigiCert TLS ECC P384 Root G5
=============================
-----BEGIN CERTIFICATE-----
MIICGTCCAZ+gAwIBAgIQCeCTZaz32ci5PhwLBCou8zAKBggqhkjOPQQDAzBOMQswCQYDVQQGEwJV
UzEXMBUGA1UEChMORGlnaUNlcnQsIEluYy4xJjAkBgNVBAMTHURpZ2lDZXJ0IFRMUyBFQ0MgUDM4
NCBSb290IEc1MB4XDTIxMDExNTAwMDAwMFoXDTQ2MDExNDIzNTk1OVowTjELMAkGA1UEBhMCVVMx
FzAVBgNVBAoTDkRpZ2lDZXJ0LCBJbmMuMSYwJAYDVQQDEx1EaWdpQ2VydCBUTFMgRUNDIFAzODQg
Um9vdCBHNTB2MBAGByqGSM49AgEGBSuBBAAiA2IABMFEoc8Rl1Ca3iOCNQfN0MsYndLxf3c1Tzvd
lHJS7cI7+Oz6e2tYIOyZrsn8aLN1udsJ7MgT9U7GCh1mMEy7H0cKPGEQQil8pQgO4CLp0zVozptj
n4S1mU1YoI71VOeVyaNCMEAwHQYDVR0OBBYEFMFRRVBZqz7nLFr6ICISB4CIfBFqMA4GA1UdDwEB
/wQEAwIBhjAPBgNVHRMBAf8EBTADAQH/MAoGCCqGSM49BAMDA2gAMGUCMQCJao1H5+z8blUD2Wds
Jk6Dxv3J+ysTvLd6jLRl0mlpYxNjOyZQLgGheQaRnUi/wr4CMEfDFXuxoJGZSZOoPHzoRgaLLPIx
AJSdYsiJvRmEFOml+wG4DXZDjC5Ty3zfDBeWUA==
-----END CERTIFICATE-----

DigiCert TLS RSA4096 Root G5
============================
-----BEGIN CERTIFICATE-----
MIIFZjCCA06gAwIBAgIQCPm0eKj6ftpqMzeJ3nzPijANBgkqhkiG9w0BAQwFADBNMQswCQYDVQQG
EwJVUzEXMBUGA1UEChMORGlnaUNlcnQsIEluYy4xJTAjBgNVBAMTHERpZ2lDZXJ0IFRMUyBSU0E0
MDk2IFJvb3QgRzUwHhcNMjEwMTE1MDAwMDAwWhcNNDYwMTE0MjM1OTU5WjBNMQswCQYDVQQGEwJV
UzEXMBUGA1UEChMORGlnaUNlcnQsIEluYy4xJTAjBgNVBAMTHERpZ2lDZXJ0IFRMUyBSU0E0MDk2
IFJvb3QgRzUwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCz0PTJeRGd/fxmgefM1eS8
7IE+ajWOLrfn3q/5B03PMJ3qCQuZvWxX2hhKuHisOjmopkisLnLlvevxGs3npAOpPxG02C+JFvuU
AT27L/gTBaF4HI4o4EXgg/RZG5Wzrn4DReW+wkL+7vI8toUTmDKdFqgpwgscONyfMXdcvyej/Ces
tyu9dJsXLfKB2l2w4SMXPohKEiPQ6s+d3gMXsUJKoBZMpG2T6T867jp8nVid9E6P/DsjyG244gXa
zOvswzH016cpVIDPRFtMbzCe88zdH5RDnU1/cHAN1DrRN/BsnZvAFJNY781BOHW8EwOVfH/jXOnV
DdXifBBiqmvwPXbzP6PosMH976pXTayGpxi0KcEsDr9kvimM2AItzVwv8n/vFfQMFawKsPHTDU9q
TXeXAaDxZre3zu/O7Oyldcqs4+Fj97ihBMi8ez9dLRYiVu1ISf6nL3kwJZu6ay0/nTvEF+cdLvvy
z6b84xQslpghjLSR6Rlgg/IwKwZzUNWYOwbpx4oMYIwo+FKbbuH2TbsGJJvXKyY//SovcfXWJL5/
MZ4PbeiPT02jP/816t9JXkGPhvnxd3lLG7SjXi/7RgLQZhNeXoVPzthwiHvOAbWWl9fNff2C+MIk
wcoBOU+NosEUQB+cZtUMCUbW8tDRSHZWOkPLtgoRObqME2wGtZ7P6wIDAQABo0IwQDAdBgNVHQ4E
FgQUUTMc7TZArxfTJc1paPKvTiM+s0EwDgYDVR0PAQH/BAQDAgGGMA8GA1UdEwEB/wQFMAMBAf8w
DQYJKoZIhvcNAQEMBQADggIBAGCmr1tfV9qJ20tQqcQjNSH/0GEwhJG3PxDPJY7Jv0Y02cEhJhxw
GXIeo8mH/qlDZJY6yFMECrZBu8RHANmfGBg7sg7zNOok992vIGCukihfNudd5N7HPNtQOa27PShN
lnx2xlv0wdsUpasZYgcYQF+Xkdycx6u1UQ3maVNVzDl92sURVXLFO4uJ+DQtpBflF+aZfTCIITfN
MBc9uPK8qHWgQ9w+iUuQrm0D4ByjoJYJu32jtyoQREtGBzRj7TG5BO6jm5qu5jF49OokYTurWGT/
u4cnYiWB39yhL/btp/96j1EuMPikAdKFOV8BmZZvWltwGUb+hmA+rYAQCd05JS9Yf7vSdPD3Rh9G
OUrYU9DzLjtxpdRv/PNn5AeP3SYZ4Y1b+qOTEZvpyDrDVWiakuFSdjjo4bq9+0/V77PnSIMx8IIh
47a+p6tv75/fTM8BuGJqIz3nCU2AG3swpMPdB380vqQmsvZB6Akd4yCYqjdP//fx4ilwMUc/dNAU
FvohigLVigmUdy7yWSiLfFCSCmZ4OIN1xLVaqBHG5cGdZlXPU8Sv13WFqUITVuwhd4GTWgzqltlJ
yqEI8pc7bZsEGCREjnwB8twl2F6GmrE52/WRMmrRpnCKovfepEWFJqgejF0pW8hL2JpqA15w8oVP
bEtoL8pU9ozaMv7Da4M/OMZ+
-----END CERTIFICATE-----

Certainly Root R1
=================
-----BEGIN CERTIFICATE-----
MIIFRzCCAy+gAwIBAgIRAI4P+UuQcWhlM1T01EQ5t+AwDQYJKoZIhvcNAQELBQAwPTELMAkGA1UE
BhMCVVMxEjAQBgNVBAoTCUNlcnRhaW5seTEaMBgGA1UEAxMRQ2VydGFpbmx5IFJvb3QgUjEwHhcN
MjEwNDAxMDAwMDAwWhcNNDYwNDAxMDAwMDAwWjA9MQswCQYDVQQGEwJVUzESMBAGA1UEChMJQ2Vy
dGFpbmx5MRowGAYDVQQDExFDZXJ0YWlubHkgUm9vdCBSMTCCAiIwDQYJKoZIhvcNAQEBBQADggIP
ADCCAgoCggIBANA21B/q3avk0bbm+yLA3RMNansiExyXPGhjZjKcA7WNpIGD2ngwEc/csiu+kr+O
5MQTvqRoTNoCaBZ0vrLdBORrKt03H2As2/X3oXyVtwxwhi7xOu9S98zTm/mLvg7fMbedaFySpvXl
8wo0tf97ouSHocavFwDvA5HtqRxOcT3Si2yJ9HiG5mpJoM610rCrm/b01C7jcvk2xusVtyWMOvwl
DbMicyF0yEqWYZL1LwsYpfSt4u5BvQF5+paMjRcCMLT5r3gajLQ2EBAHBXDQ9DGQilHFhiZ5shGI
XsXwClTNSaa/ApzSRKft43jvRl5tcdF5cBxGX1HpyTfcX35pe0HfNEXgO4T0oYoKNp43zGJS4YkN
KPl6I7ENPT2a/Z2B7yyQwHtETrtJ4A5KVpK8y7XdeReJkd5hiXSSqOMyhb5OhaRLWcsrxXiOcVTQ
AjeZjOVJ6uBUcqQRBi8LjMFbvrWhsFNunLhgkR9Za/kt9JQKl7XsxXYDVBtlUrpMklZRNaBA2Cnb
rlJ2Oy0wQJuK0EJWtLeIAaSHO1OWzaMWj/Nmqhexx2DgwUMFDO6bW2BvBlyHWyf5QBGenDPBt+U1
VwV/J84XIIwc/PH72jEpSe31C4SnT8H2TsIonPru4K8H+zMReiFPCyEQtkA6qyI6BJyLm4SGcprS
p6XEtHWRqSsjAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MB0GA1Ud
DgQWBBTgqj8ljZ9EXME66C6ud0yEPmcM9DANBgkqhkiG9w0BAQsFAAOCAgEAuVevuBLaV4OPaAsz
HQNTVfSVcOQrPbA56/qJYv331hgELyE03fFo8NWWWt7CgKPBjcZq91l3rhVkz1t5BXdm6ozTaw3d
8VkswTOlMIAVRQdFGjEitpIAq5lNOo93r6kiyi9jyhXWx8bwPWz8HA2YEGGeEaIi1wrykXprOQ4v
MMM2SZ/g6Q8CRFA3lFV96p/2O7qUpUzpvD5RtOjKkjZUbVwlKNrdrRT90+7iIgXr0PK3aBLXWopB
GsaSpVo7Y0VPv+E6dyIvXL9G+VoDhRNCX8reU9ditaY1BMJH/5n9hN9czulegChB8n3nHpDYT3Y+
gjwN/KUD+nsa2UUeYNrEjvn8K8l7lcUq/6qJ34IxD3L/DCfXCh5WAFAeDJDBlrXYFIW7pw0WwfgH
JBu6haEaBQmAupVjyTrsJZ9/nbqkRxWbRHDxakvWOF5D8xh+UG7pWijmZeZ3Gzr9Hb4DJqPb1OG7
fpYnKx3upPvaJVQTA945xsMfTZDsjxtK0hzthZU4UHlG1sGQUDGpXJpuHfUzVounmdLyyCwzk5Iw
x06MZTMQZBf9JBeW0Y3COmor6xOLRPIh80oat3df1+2IpHLlOR+Vnb5nwXARPbv0+Em34yaXOp/S
X3z7wJl8OSngex2/DaeP0ik0biQVy96QXr8axGbqwua6OV+KmalBWQewLK8=
-----END CERTIFICATE-----

Certainly Root E1
=================
-----BEGIN CERTIFICATE-----
MIIB9zCCAX2gAwIBAgIQBiUzsUcDMydc+Y2aub/M+DAKBggqhkjOPQQDAzA9MQswCQYDVQQGEwJV
UzESMBAGA1UEChMJQ2VydGFpbmx5MRowGAYDVQQDExFDZXJ0YWlubHkgUm9vdCBFMTAeFw0yMTA0
MDEwMDAwMDBaFw00NjA0MDEwMDAwMDBaMD0xCzAJBgNVBAYTAlVTMRIwEAYDVQQKEwlDZXJ0YWlu
bHkxGjAYBgNVBAMTEUNlcnRhaW5seSBSb290IEUxMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAE3m/4
fxzf7flHh4axpMCK+IKXgOqPyEpeKn2IaKcBYhSRJHpcnqMXfYqGITQYUBsQ3tA3SybHGWCA6TS9
YBk2QNYphwk8kXr2vBMj3VlOBF7PyAIcGFPBMdjaIOlEjeR2o0IwQDAOBgNVHQ8BAf8EBAMCAQYw
DwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQU8ygYy2R17ikq6+2uI1g4hevIIgcwCgYIKoZIzj0E
AwMDaAAwZQIxALGOWiDDshliTd6wT99u0nCK8Z9+aozmut6Dacpps6kFtZaSF4fC0urQe87YQVt8
rgIwRt7qy12a7DLCZRawTDBcMPPaTnOGBtjOiQRINzf43TNRnXCve1XYAS59BWQOhriR
-----END CERTIFICATE-----

Security Communication ECC RootCA1
==================================
-----BEGIN CERTIFICATE-----
MIICODCCAb6gAwIBAgIJANZdm7N4gS7rMAoGCCqGSM49BAMDMGExCzAJBgNVBAYTAkpQMSUwIwYD
VQQKExxTRUNPTSBUcnVzdCBTeXN0ZW1zIENPLixMVEQuMSswKQYDVQQDEyJTZWN1cml0eSBDb21t
dW5pY2F0aW9uIEVDQyBSb290Q0ExMB4XDTE2MDYxNjA1MTUyOFoXDTM4MDExODA1MTUyOFowYTEL
MAkGA1UEBhMCSlAxJTAjBgNVBAoTHFNFQ09NIFRydXN0IFN5c3RlbXMgQ08uLExURC4xKzApBgNV
BAMTIlNlY3VyaXR5IENvbW11bmljYXRpb24gRUNDIFJvb3RDQTEwdjAQBgcqhkjOPQIBBgUrgQQA
IgNiAASkpW9gAwPDvTH00xecK4R1rOX9PVdu12O/5gSJko6BnOPpR27KkBLIE+CnnfdldB9sELLo
5OnvbYUymUSxXv3MdhDYW72ixvnWQuRXdtyQwjWpS4g8EkdtXP9JTxpKULGjQjBAMB0GA1UdDgQW
BBSGHOf+LaVKiwj+KBH6vqNm+GBZLzAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAK
BggqhkjOPQQDAwNoADBlAjAVXUI9/Lbu9zuxNuie9sRGKEkz0FhDKmMpzE2xtHqiuQ04pV1IKv3L
snNdo4gIxwwCMQDAqy0Obe0YottT6SXbVQjgUMzfRGEWgqtJsLKB7HOHeLRMsmIbEvoWTSVLY70e
N9k=
-----END CERTIFICATE-----

BJCA Global Root CA1
====================
-----BEGIN CERTIFICATE-----
MIIFdDCCA1ygAwIBAgIQVW9l47TZkGobCdFsPsBsIDANBgkqhkiG9w0BAQsFADBUMQswCQYDVQQG
EwJDTjEmMCQGA1UECgwdQkVJSklORyBDRVJUSUZJQ0FURSBBVVRIT1JJVFkxHTAbBgNVBAMMFEJK
Q0EgR2xvYmFsIFJvb3QgQ0ExMB4XDTE5MTIxOTAzMTYxN1oXDTQ0MTIxMjAzMTYxN1owVDELMAkG
A1UEBhMCQ04xJjAkBgNVBAoMHUJFSUpJTkcgQ0VSVElGSUNBVEUgQVVUSE9SSVRZMR0wGwYDVQQD
DBRCSkNBIEdsb2JhbCBSb290IENBMTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAPFm
CL3ZxRVhy4QEQaVpN3cdwbB7+sN3SJATcmTRuHyQNZ0YeYjjlwE8R4HyDqKYDZ4/N+AZspDyRhyS
sTphzvq3Rp4Dhtczbu33RYx2N95ulpH3134rhxfVizXuhJFyV9xgw8O558dnJCNPYwpj9mZ9S1Wn
P3hkSWkSl+BMDdMJoDIwOvqfwPKcxRIqLhy1BDPapDgRat7GGPZHOiJBhyL8xIkoVNiMpTAK+BcW
yqw3/XmnkRd4OJmtWO2y3syJfQOcs4ll5+M7sSKGjwZteAf9kRJ/sGsciQ35uMt0WwfCyPQ10WRj
eulumijWML3mG90Vr4TqnMfK9Q7q8l0ph49pczm+LiRvRSGsxdRpJQaDrXpIhRMsDQa4bHlW/KNn
MoH1V6XKV0Jp6VwkYe/iMBhORJhVb3rCk9gZtt58R4oRTklH2yiUAguUSiz5EtBP6DF+bHq/pj+b
OT0CFqMYs2esWz8sgytnOYFcuX6U1WTdno9uruh8W7TXakdI136z1C2OVnZOz2nxbkRs1CTqjSSh
GL+9V/6pmTW12xB3uD1IutbB5/EjPtffhZ0nPNRAvQoMvfXnjSXWgXSHRtQpdaJCbPdzied9v3pK
H9MiyRVVz99vfFXQpIsHETdfg6YmV6YBW37+WGgHqel62bno/1Afq8K0wM7o6v0PvY1NuLxxAgMB
AAGjQjBAMB0GA1UdDgQWBBTF7+3M2I0hxkjk49cULqcWk+WYATAPBgNVHRMBAf8EBTADAQH/MA4G
A1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQsFAAOCAgEAUoKsITQfI/Ki2Pm4rzc2IInRNwPWaZ+4
YRC6ojGYWUfo0Q0lHhVBDOAqVdVXUsv45Mdpox1NcQJeXyFFYEhcCY5JEMEE3KliawLwQ8hOnThJ
dMkycFRtwUf8jrQ2ntScvd0g1lPJGKm1Vrl2i5VnZu69mP6u775u+2D2/VnGKhs/I0qUJDAnyIm8
60Qkmss9vk/Ves6OF8tiwdneHg56/0OGNFK8YT88X7vZdrRTvJez/opMEi4r89fO4aL/3Xtw+zuh
TaRjAv04l5U/BXCga99igUOLtFkNSoxUnMW7gZ/NfaXvCyUeOiDbHPwfmGcCCtRzRBPbUYQaVQNW
4AB+dAb/OMRyHdOoP2gxXdMJxy6MW2Pg6Nwe0uxhHvLe5e/2mXZgLR6UcnHGCyoyx5JO1UbXHfmp
GQrI+pXObSOYqgs4rZpWDW+N8TEAiMEXnM0ZNjX+VVOg4DwzX5Ze4jLp3zO7Bkqp2IRzznfSxqxx
4VyjHQy7Ct9f4qNx2No3WqB4K/TUfet27fJhcKVlmtOJNBir+3I+17Q9eVzYH6Eze9mCUAyTF6ps
3MKCuwJXNq+YJyo5UOGwifUll35HaBC07HPKs5fRJNz2YqAo07WjuGS3iGJCz51TzZm+ZGiPTx4S
SPfSKcOYKMryMguTjClPPGAyzQWWYezyr/6zcCwupvI=
-----END CERTIFICATE-----

BJCA Global Root CA2
====================
-----BEGIN CERTIFICATE-----
MIICJTCCAaugAwIBAgIQLBcIfWQqwP6FGFkGz7RK6zAKBggqhkjOPQQDAzBUMQswCQYDVQQGEwJD
TjEmMCQGA1UECgwdQkVJSklORyBDRVJUSUZJQ0FURSBBVVRIT1JJVFkxHTAbBgNVBAMMFEJKQ0Eg
R2xvYmFsIFJvb3QgQ0EyMB4XDTE5MTIxOTAzMTgyMVoXDTQ0MTIxMjAzMTgyMVowVDELMAkGA1UE
BhMCQ04xJjAkBgNVBAoMHUJFSUpJTkcgQ0VSVElGSUNBVEUgQVVUSE9SSVRZMR0wGwYDVQQDDBRC
SkNBIEdsb2JhbCBSb290IENBMjB2MBAGByqGSM49AgEGBSuBBAAiA2IABJ3LgJGNU2e1uVCxA/jl
SR9BIgmwUVJY1is0j8USRhTFiy8shP8sbqjV8QnjAyEUxEM9fMEsxEtqSs3ph+B99iK++kpRuDCK
/eHeGBIK9ke35xe/J4rUQUyWPGCWwf0VHKNCMEAwHQYDVR0OBBYEFNJKsVF/BvDRgh9Obl+rg/xI
1LCRMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMAoGCCqGSM49BAMDA2gAMGUCMBq8
W9f+qdJUDkpd0m2xQNz0Q9XSSpkZElaA94M04TVOSG0ED1cxMDAtsaqdAzjbBgIxAMvMh1PLet8g
UXOQwKhbYdDFUDn9hf7B43j4ptZLvZuHjw/l1lOWqzzIQNph91Oj9w==
-----END CERTIFICATE-----

Sectigo Public Server Authentication Root E46
=============================================
-----BEGIN CERTIFICATE-----
MIICOjCCAcGgAwIBAgIQQvLM2htpN0RfFf51KBC49DAKBggqhkjOPQQDAzBfMQswCQYDVQQGEwJH
QjEYMBYGA1UEChMPU2VjdGlnbyBMaW1pdGVkMTYwNAYDVQQDEy1TZWN0aWdvIFB1YmxpYyBTZXJ2
ZXIgQXV0aGVudGljYXRpb24gUm9vdCBFNDYwHhcNMjEwMzIyMDAwMDAwWhcNNDYwMzIxMjM1OTU5
WjBfMQswCQYDVQQGEwJHQjEYMBYGA1UEChMPU2VjdGlnbyBMaW1pdGVkMTYwNAYDVQQDEy1TZWN0
aWdvIFB1YmxpYyBTZXJ2ZXIgQXV0aGVudGljYXRpb24gUm9vdCBFNDYwdjAQBgcqhkjOPQIBBgUr
gQQAIgNiAAR2+pmpbiDt+dd34wc7qNs9Xzjoq1WmVk/WSOrsfy2qw7LFeeyZYX8QeccCWvkEN/U0
NSt3zn8gj1KjAIns1aeibVvjS5KToID1AZTc8GgHHs3u/iVStSBDHBv+6xnOQ6OjQjBAMB0GA1Ud
DgQWBBTRItpMWfFLXyY4qp3W7usNw/upYTAOBgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB
/zAKBggqhkjOPQQDAwNnADBkAjAn7qRaqCG76UeXlImldCBteU/IvZNeWBj7LRoAasm4PdCkT0RH
lAFWovgzJQxC36oCMB3q4S6ILuH5px0CMk7yn2xVdOOurvulGu7t0vzCAxHrRVxgED1cf5kDW21U
SAGKcw==
-----END CERTIFICATE-----

Sectigo Public Server Authentication Root R46
=============================================
-----BEGIN CERTIFICATE-----
MIIFijCCA3KgAwIBAgIQdY39i658BwD6qSWn4cetFDANBgkqhkiG9w0BAQwFADBfMQswCQYDVQQG
EwJHQjEYMBYGA1UEChMPU2VjdGlnbyBMaW1pdGVkMTYwNAYDVQQDEy1TZWN0aWdvIFB1YmxpYyBT
ZXJ2ZXIgQXV0aGVudGljYXRpb24gUm9vdCBSNDYwHhcNMjEwMzIyMDAwMDAwWhcNNDYwMzIxMjM1
OTU5WjBfMQswCQYDVQQGEwJHQjEYMBYGA1UEChMPU2VjdGlnbyBMaW1pdGVkMTYwNAYDVQQDEy1T
ZWN0aWdvIFB1YmxpYyBTZXJ2ZXIgQXV0aGVudGljYXRpb24gUm9vdCBSNDYwggIiMA0GCSqGSIb3
DQEBAQUAA4ICDwAwggIKAoICAQCTvtU2UnXYASOgHEdCSe5jtrch/cSV1UgrJnwUUxDaef0rty2k
1Cz66jLdScK5vQ9IPXtamFSvnl0xdE8H/FAh3aTPaE8bEmNtJZlMKpnzSDBh+oF8HqcIStw+Kxwf
GExxqjWMrfhu6DtK2eWUAtaJhBOqbchPM8xQljeSM9xfiOefVNlI8JhD1mb9nxc4Q8UBUQvX4yMP
FF1bFOdLvt30yNoDN9HWOaEhUTCDsG3XME6WW5HwcCSrv0WBZEMNvSE6Lzzpng3LILVCJ8zab5vu
ZDCQOc2TZYEhMbUjUDM3IuM47fgxMMxF/mL50V0yeUKH32rMVhlATc6qu/m1dkmU8Sf4kaWD5Qaz
Yw6A3OASVYCmO2a0OYctyPDQ0RTp5A1NDvZdV3LFOxxHVp3i1fuBYYzMTYCQNFu31xR13NgESJ/A
wSiItOkcyqex8Va3e0lMWeUgFaiEAin6OJRpmkkGj80feRQXEgyDet4fsZfu+Zd4KKTIRJLpfSYF
plhym3kT2BFfrsU4YjRosoYwjviQYZ4ybPUHNs2iTG7sijbt8uaZFURww3y8nDnAtOFr94MlI1fZ
EoDlSfB1D++N6xybVCi0ITz8fAr/73trdf+LHaAZBav6+CuBQug4urv7qv094PPK306Xlynt8xhW
6aWWrL3DkJiy4Pmi1KZHQ3xtzwIDAQABo0IwQDAdBgNVHQ4EFgQUVnNYZJX5khqwEioEYnmhQBWI
IUkwDgYDVR0PAQH/BAQDAgGGMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEMBQADggIBAC9c
mTz8Bl6MlC5w6tIyMY208FHVvArzZJ8HXtXBc2hkeqK5Duj5XYUtqDdFqij0lgVQYKlJfp/imTYp
E0RHap1VIDzYm/EDMrraQKFz6oOht0SmDpkBm+S8f74TlH7Kph52gDY9hAaLMyZlbcp+nv4fjFg4
exqDsQ+8FxG75gbMY/qB8oFM2gsQa6H61SilzwZAFv97fRheORKkU55+MkIQpiGRqRxOF3yEvJ+M
0ejf5lG5Nkc/kLnHvALcWxxPDkjBJYOcCj+esQMzEhonrPcibCTRAUH4WAP+JWgiH5paPHxsnnVI
84HxZmduTILA7rpXDhjvLpr3Etiga+kFpaHpaPi8TD8SHkXoUsCjvxInebnMMTzD9joiFgOgyY9m
pFuiTdaBJQbpdqQACj7LzTWb4OE4y2BThihCQRxEV+ioratF4yUQvNs+ZUH7G6aXD+u5dHn5Hrwd
Vw1Hr8Mvn4dGp+smWg9WY7ViYG4A++MnESLn/pmPNPW56MORcr3Ywx65LvKRRFHQV80MNNVIIb/b
E/FmJUNS0nAiNs2fxBx1IK1jcmMGDw4nztJqDby1ORrp0XZ60Vzk50lJLVU3aPAaOpg+VBeHVOmm
J1CJeyAvP/+/oYtKR5j/K3tJPsMpRmAYQqszKbrAKbkTidOIijlBO8n9pu0f9GBj39ItVQGL
-----END CERTIFICATE-----

SSL.com TLS RSA Root CA 2022
============================
-----BEGIN CERTIFICATE-----
MIIFiTCCA3GgAwIBAgIQb77arXO9CEDii02+1PdbkTANBgkqhkiG9w0BAQsFADBOMQswCQYDVQQG
EwJVUzEYMBYGA1UECgwPU1NMIENvcnBvcmF0aW9uMSUwIwYDVQQDDBxTU0wuY29tIFRMUyBSU0Eg
Um9vdCBDQSAyMDIyMB4XDTIyMDgyNTE2MzQyMloXDTQ2MDgxOTE2MzQyMVowTjELMAkGA1UEBhMC
VVMxGDAWBgNVBAoMD1NTTCBDb3Jwb3JhdGlvbjElMCMGA1UEAwwcU1NMLmNvbSBUTFMgUlNBIFJv
b3QgQ0EgMjAyMjCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBANCkCXJPQIgSYT41I57u
9nTPL3tYPc48DRAokC+X94xI2KDYJbFMsBFMF3NQ0CJKY7uB0ylu1bUJPiYYf7ISf5OYt6/wNr/y
7hienDtSxUcZXXTzZGbVXcdotL8bHAajvI9AI7YexoS9UcQbOcGV0insS657Lb85/bRi3pZ7Qcac
oOAGcvvwB5cJOYF0r/c0WRFXCsJbwST0MXMwgsadugL3PnxEX4MN8/HdIGkWCVDi1FW24IBydm5M
R7d1VVm0U3TZlMZBrViKMWYPHqIbKUBOL9975hYsLfy/7PO0+r4Y9ptJ1O4Fbtk085zx7AGL0SDG
D6C1vBdOSHtRwvzpXGk3R2azaPgVKPC506QVzFpPulJwoxJF3ca6TvvC0PeoUidtbnm1jPx7jMEW
TO6Af77wdr5BUxIzrlo4QqvXDz5BjXYHMtWrifZOZ9mxQnUjbvPNQrL8VfVThxc7wDNY8VLS+YCk
8OjwO4s4zKTGkH8PnP2L0aPP2oOnaclQNtVcBdIKQXTbYxE3waWglksejBYSd66UNHsef8JmAOSq
g+qKkK3ONkRN0VHpvB/zagX9wHQfJRlAUW7qglFA35u5CCoGAtUjHBPW6dvbxrB6y3snm/vg1UYk
7RBLY0ulBY+6uB0rpvqR4pJSvezrZ5dtmi2fgTIFZzL7SAg/2SW4BCUvAgMBAAGjYzBhMA8GA1Ud
EwEB/wQFMAMBAf8wHwYDVR0jBBgwFoAU+y437uOEeicuzRk1sTN8/9REQrkwHQYDVR0OBBYEFPsu
N+7jhHonLs0ZNbEzfP/UREK5MA4GA1UdDwEB/wQEAwIBhjANBgkqhkiG9w0BAQsFAAOCAgEAjYlt
hEUY8U+zoO9opMAdrDC8Z2awms22qyIZZtM7QbUQnRC6cm4pJCAcAZli05bg4vsMQtfhWsSWTVTN
j8pDU/0quOr4ZcoBwq1gaAafORpR2eCNJvkLTqVTJXojpBzOCBvfR4iyrT7gJ4eLSYwfqUdYe5by
iB0YrrPRpgqU+tvT5TgKa3kSM/tKWTcWQA673vWJDPFs0/dRa1419dvAJuoSc06pkZCmF8NsLzjU
o3KUQyxi4U5cMj29TH0ZR6LDSeeWP4+a0zvkEdiLA9z2tmBVGKaBUfPhqBVq6+AL8BQx1rmMRTqo
ENjwuSfr98t67wVylrXEj5ZzxOhWc5y8aVFjvO9nHEMaX3cZHxj4HCUp+UmZKbaSPaKDN7Egkaib
MOlqbLQjk2UEqxHzDh1TJElTHaE/nUiSEeJ9DU/1172iWD54nR4fK/4huxoTtrEoZP2wAgDHbICi
vRZQIA9ygV/MlP+7mea6kMvq+cYMwq7FGc4zoWtcu358NFcXrfA/rs3qr5nsLFR+jM4uElZI7xc7
P0peYNLcdDa8pUNjyw9bowJWCZ4kLOGGgYz+qxcs+sjiMho6/4UIyYOf8kpIEFR3N+2ivEC+5BB0
9+Rbu7nzifmPQdjH5FCQNYA+HLhNkNPU98OwoX6EyneSMSy4kLGCenROmxMmtNVQZlR4rmA=
-----END CERTIFICATE-----

SSL.com TLS ECC Root CA 2022
============================
-----BEGIN CERTIFICATE-----
MIICOjCCAcCgAwIBAgIQFAP1q/s3ixdAW+JDsqXRxDAKBggqhkjOPQQDAzBOMQswCQYDVQQGEwJV
UzEYMBYGA1UECgwPU1NMIENvcnBvcmF0aW9uMSUwIwYDVQQDDBxTU0wuY29tIFRMUyBFQ0MgUm9v
dCBDQSAyMDIyMB4XDTIyMDgyNTE2MzM0OFoXDTQ2MDgxOTE2MzM0N1owTjELMAkGA1UEBhMCVVMx
GDAWBgNVBAoMD1NTTCBDb3Jwb3JhdGlvbjElMCMGA1UEAwwcU1NMLmNvbSBUTFMgRUNDIFJvb3Qg
Q0EgMjAyMjB2MBAGByqGSM49AgEGBSuBBAAiA2IABEUpNXP6wrgjzhR9qLFNoFs27iosU8NgCTWy
JGYmacCzldZdkkAZDsalE3D07xJRKF3nzL35PIXBz5SQySvOkkJYWWf9lCcQZIxPBLFNSeR7T5v1
5wj4A4j3p8OSSxlUgaNjMGEwDwYDVR0TAQH/BAUwAwEB/zAfBgNVHSMEGDAWgBSJjy+j6CugFFR7
81a4Jl9nOAuc0DAdBgNVHQ4EFgQUiY8vo+groBRUe/NWuCZfZzgLnNAwDgYDVR0PAQH/BAQDAgGG
MAoGCCqGSM49BAMDA2gAMGUCMFXjIlbp15IkWE8elDIPDAI2wv2sdDJO4fscgIijzPvX6yv/N33w
7deedWo1dlJF4AIxAMeNb0Igj762TVntd00pxCAgRWSGOlDGxK0tk/UYfXLtqc/ErFc2KAhl3zx5
Zn6g6g==
-----END CERTIFICATE-----

Atos TrustedRoot Root CA ECC TLS 2021
=====================================
-----BEGIN CERTIFICATE-----
MIICFTCCAZugAwIBAgIQPZg7pmY9kGP3fiZXOATvADAKBggqhkjOPQQDAzBMMS4wLAYDVQQDDCVB
dG9zIFRydXN0ZWRSb290IFJvb3QgQ0EgRUNDIFRMUyAyMDIxMQ0wCwYDVQQKDARBdG9zMQswCQYD
VQQGEwJERTAeFw0yMTA0MjIwOTI2MjNaFw00MTA0MTcwOTI2MjJaMEwxLjAsBgNVBAMMJUF0b3Mg
VHJ1c3RlZFJvb3QgUm9vdCBDQSBFQ0MgVExTIDIwMjExDTALBgNVBAoMBEF0b3MxCzAJBgNVBAYT
AkRFMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAEloZYKDcKZ9Cg3iQZGeHkBQcfl+3oZIK59sRxUM6K
DP/XtXa7oWyTbIOiaG6l2b4siJVBzV3dscqDY4PMwL502eCdpO5KTlbgmClBk1IQ1SQ4AjJn8ZQS
b+/Xxd4u/RmAo0IwQDAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBR2KCXWfeBmmnoJsmo7jjPX
NtNPojAOBgNVHQ8BAf8EBAMCAYYwCgYIKoZIzj0EAwMDaAAwZQIwW5kp85wxtolrbNa9d+F851F+
uDrNozZffPc8dz7kUK2o59JZDCaOMDtuCCrCp1rIAjEAmeMM56PDr9NJLkaCI2ZdyQAUEv049OGY
a3cpetskz2VAv9LcjBHo9H1/IISpQuQo
-----END CERTIFICATE-----

Atos TrustedRoot Root CA RSA TLS 2021
=====================================
-----BEGIN CERTIFICATE-----
MIIFZDCCA0ygAwIBAgIQU9XP5hmTC/srBRLYwiqipDANBgkqhkiG9w0BAQwFADBMMS4wLAYDVQQD
DCVBdG9zIFRydXN0ZWRSb290IFJvb3QgQ0EgUlNBIFRMUyAyMDIxMQ0wCwYDVQQKDARBdG9zMQsw
CQYDVQQGEwJERTAeFw0yMTA0MjIwOTIxMTBaFw00MTA0MTcwOTIxMDlaMEwxLjAsBgNVBAMMJUF0
b3MgVHJ1c3RlZFJvb3QgUm9vdCBDQSBSU0EgVExTIDIwMjExDTALBgNVBAoMBEF0b3MxCzAJBgNV
BAYTAkRFMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAtoAOxHm9BYx9sKOdTSJNy/BB
l01Z4NH+VoyX8te9j2y3I49f1cTYQcvyAh5x5en2XssIKl4w8i1mx4QbZFc4nXUtVsYvYe+W/CBG
vevUez8/fEc4BKkbqlLfEzfTFRVOvV98r61jx3ncCHvVoOX3W3WsgFWZkmGbzSoXfduP9LVq6hdK
ZChmFSlsAvFr1bqjM9xaZ6cF4r9lthawEO3NUDPJcFDsGY6wx/J0W2tExn2WuZgIWWbeKQGb9Cpt
0xU6kGpn8bRrZtkh68rZYnxGEFzedUlnnkL5/nWpo63/dgpnQOPF943HhZpZnmKaau1Fh5hnstVK
PNe0OwANwI8f4UDErmwh3El+fsqyjW22v5MvoVw+j8rtgI5Y4dtXz4U2OLJxpAmMkokIiEjxQGMY
sluMWuPD0xeqqxmjLBvk1cbiZnrXghmmOxYsL3GHX0WelXOTwkKBIROW1527k2gV+p2kHYzygeBY
Br3JtuP2iV2J+axEoctr+hbxx1A9JNr3w+SH1VbxT5Aw+kUJWdo0zuATHAR8ANSbhqRAvNncTFd+
rrcztl524WWLZt+NyteYr842mIycg5kDcPOvdO3GDjbnvezBc6eUWsuSZIKmAMFwoW4sKeFYV+xa
fJlrJaSQOoD0IJ2azsct+bJLKZWD6TWNp0lIpw9MGZHQ9b8Q4HECAwEAAaNCMEAwDwYDVR0TAQH/
BAUwAwEB/zAdBgNVHQ4EFgQUdEmZ0f+0emhFdcN+tNzMzjkz2ggwDgYDVR0PAQH/BAQDAgGGMA0G
CSqGSIb3DQEBDAUAA4ICAQAjQ1MkYlxt/T7Cz1UAbMVWiLkO3TriJQ2VSpfKgInuKs1l+NsW4AmS
4BjHeJi78+xCUvuppILXTdiK/ORO/auQxDh1MoSf/7OwKwIzNsAQkG8dnK/haZPso0UvFJ/1TCpl
Q3IM98P4lYsU84UgYt1UU90s3BiVaU+DR3BAM1h3Egyi61IxHkzJqM7F78PRreBrAwA0JrRUITWX
AdxfG/F851X6LWh3e9NpzNMOa7pNdkTWwhWaJuywxfW70Xp0wmzNxbVe9kzmWy2B27O3Opee7c9G
slA9hGCZcbUztVdF5kJHdWoOsAgMrr3e97sPWD2PAzHoPYJQyi9eDF20l74gNAf0xBLh7tew2Vkt
afcxBPTy+av5EzH4AXcOPUIjJsyacmdRIXrMPIWo6iFqO9taPKU0nprALN+AnCng33eU0aKAQv9q
TFsR0PXNor6uzFFcw9VUewyu1rkGd4Di7wcaaMxZUa1+XGdrudviB0JbuAEFWDlN5LuYo7Ey7Nmj
1m+UI/87tyll5gfp77YZ6ufCOB0yiJA8EytuzO+rdwY0d4RPcuSBhPm5dDTedk+SKlOxJTnbPP/l
PqYO5Wue/9vsL3SD3460s6neFE3/MaNFcyT6lSnMEpcEoji2jbDwN/zIIX8/syQbPYtuzE2wFg2W
HYMfRsCbvUOZ58SWLs5fyQ==
-----END CERTIFICATE-----

TrustAsia Global Root CA G3
===========================
-----BEGIN CERTIFICATE-----
MIIFpTCCA42gAwIBAgIUZPYOZXdhaqs7tOqFhLuxibhxkw8wDQYJKoZIhvcNAQEMBQAwWjELMAkG
A1UEBhMCQ04xJTAjBgNVBAoMHFRydXN0QXNpYSBUZWNobm9sb2dpZXMsIEluYy4xJDAiBgNVBAMM
G1RydXN0QXNpYSBHbG9iYWwgUm9vdCBDQSBHMzAeFw0yMTA1MjAwMjEwMTlaFw00NjA1MTkwMjEw
MTlaMFoxCzAJBgNVBAYTAkNOMSUwIwYDVQQKDBxUcnVzdEFzaWEgVGVjaG5vbG9naWVzLCBJbmMu
MSQwIgYDVQQDDBtUcnVzdEFzaWEgR2xvYmFsIFJvb3QgQ0EgRzMwggIiMA0GCSqGSIb3DQEBAQUA
A4ICDwAwggIKAoICAQDAMYJhkuSUGwoqZdC+BqmHO1ES6nBBruL7dOoKjbmzTNyPtxNST1QY4Sxz
lZHFZjtqz6xjbYdT8PfxObegQ2OwxANdV6nnRM7EoYNl9lA+sX4WuDqKAtCWHwDNBSHvBm3dIZwZ
Q0WhxeiAysKtQGIXBsaqvPPW5vxQfmZCHzyLpnl5hkA1nyDvP+uLRx+PjsXUjrYsyUQE49RDdT/V
P68czH5GX6zfZBCK70bwkPAPLfSIC7Epqq+FqklYqL9joDiR5rPmd2jE+SoZhLsO4fWvieylL1Ag
dB4SQXMeJNnKziyhWTXAyB1GJ2Faj/lN03J5Zh6fFZAhLf3ti1ZwA0pJPn9pMRJpxx5cynoTi+jm
9WAPzJMshH/x/Gr8m0ed262IPfN2dTPXS6TIi/n1Q1hPy8gDVI+lhXgEGvNz8teHHUGf59gXzhqc
D0r83ERoVGjiQTz+LISGNzzNPy+i2+f3VANfWdP3kXjHi3dqFuVJhZBFcnAvkV34PmVACxmZySYg
WmjBNb9Pp1Hx2BErW+Canig7CjoKH8GB5S7wprlppYiU5msTf9FkPz2ccEblooV7WIQn3MSAPmea
mseaMQ4w7OYXQJXZRe0Blqq/DPNL0WP3E1jAuPP6Z92bfW1K/zJMtSU7/xxnD4UiWQWRkUF3gdCF
TIcQcf+eQxuulXUtgQIDAQABo2MwYTAPBgNVHRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFEDk5PIj
7zjKsK5Xf/IhMBY027ySMB0GA1UdDgQWBBRA5OTyI+84yrCuV3/yITAWNNu8kjAOBgNVHQ8BAf8E
BAMCAQYwDQYJKoZIhvcNAQEMBQADggIBACY7UeFNOPMyGLS0XuFlXsSUT9SnYaP4wM8zAQLpw6o1
D/GUE3d3NZ4tVlFEbuHGLige/9rsR82XRBf34EzC4Xx8MnpmyFq2XFNFV1pF1AWZLy4jVe5jaN/T
G3inEpQGAHUNcoTpLrxaatXeL1nHo+zSh2bbt1S1JKv0Q3jbSwTEb93mPmY+KfJLaHEih6D4sTNj
duMNhXJEIlU/HHzp/LgV6FL6qj6jITk1dImmasI5+njPtqzn59ZW/yOSLlALqbUHM/Q4X6RJpstl
cHboCoWASzY9M/eVVHUl2qzEc4Jl6VL1XP04lQJqaTDFHApXB64ipCz5xUG3uOyfT0gA+QEEVcys
+TIxxHWVBqB/0Y0n3bOppHKH/lmLmnp0Ft0WpWIp6zqW3IunaFnT63eROfjXy9mPX1onAX1daBli
2MjN9LdyR75bl87yraKZk62Uy5P2EgmVtqvXO9A/EcswFi55gORngS1d7XB4tmBZrOFdRWOPyN9y
aFvqHbgB8X7754qz41SgOAngPN5C8sLtLpvzHzW2NtjjgKGLzZlkD8Kqq7HK9W+eQ42EVJmzbsAS
ZthwEPEGNTNDqJwuuhQxzhB/HIbjj9LV+Hfsm6vxL2PZQl/gZ4FkkfGXL/xuJvYz+NO1+MRiqzFR
JQJ6+N1rZdVtTTDIZbpoFGWsJwt0ivKH
-----END CERTIFICATE-----

TrustAsia Global Root CA G4
===========================
-----BEGIN CERTIFICATE-----
MIICVTCCAdygAwIBAgIUTyNkuI6XY57GU4HBdk7LKnQV1tcwCgYIKoZIzj0EAwMwWjELMAkGA1UE
BhMCQ04xJTAjBgNVBAoMHFRydXN0QXNpYSBUZWNobm9sb2dpZXMsIEluYy4xJDAiBgNVBAMMG1Ry
dXN0QXNpYSBHbG9iYWwgUm9vdCBDQSBHNDAeFw0yMTA1MjAwMjEwMjJaFw00NjA1MTkwMjEwMjJa
MFoxCzAJBgNVBAYTAkNOMSUwIwYDVQQKDBxUcnVzdEFzaWEgVGVjaG5vbG9naWVzLCBJbmMuMSQw
IgYDVQQDDBtUcnVzdEFzaWEgR2xvYmFsIFJvb3QgQ0EgRzQwdjAQBgcqhkjOPQIBBgUrgQQAIgNi
AATxs8045CVD5d4ZCbuBeaIVXxVjAd7Cq92zphtnS4CDr5nLrBfbK5bKfFJV4hrhPVbwLxYI+hW8
m7tH5j/uqOFMjPXTNvk4XatwmkcN4oFBButJ+bAp3TPsUKV/eSm4IJijYzBhMA8GA1UdEwEB/wQF
MAMBAf8wHwYDVR0jBBgwFoAUpbtKl86zK3+kMd6Xg1mDpm9xy94wHQYDVR0OBBYEFKW7SpfOsyt/
pDHel4NZg6ZvccveMA4GA1UdDwEB/wQEAwIBBjAKBggqhkjOPQQDAwNnADBkAjBe8usGzEkxn0AA
bbd+NvBNEU/zy4k6LHiRUKNbwMp1JvK/kF0LgoxgKJ/GcJpo5PECMFxYDlZ2z1jD1xCMuo6u47xk
dUfFVZDj/bpV6wfEU6s3qe4hsiFbYI89MvHVI5TWWA==
-----END CERTIFICATE-----

Telekom Security TLS ECC Root 2020
==================================
-----BEGIN CERTIFICATE-----
MIICQjCCAcmgAwIBAgIQNjqWjMlcsljN0AFdxeVXADAKBggqhkjOPQQDAzBjMQswCQYDVQQGEwJE
RTEnMCUGA1UECgweRGV1dHNjaGUgVGVsZWtvbSBTZWN1cml0eSBHbWJIMSswKQYDVQQDDCJUZWxl
a29tIFNlY3VyaXR5IFRMUyBFQ0MgUm9vdCAyMDIwMB4XDTIwMDgyNTA3NDgyMFoXDTQ1MDgyNTIz
NTk1OVowYzELMAkGA1UEBhMCREUxJzAlBgNVBAoMHkRldXRzY2hlIFRlbGVrb20gU2VjdXJpdHkg
R21iSDErMCkGA1UEAwwiVGVsZWtvbSBTZWN1cml0eSBUTFMgRUNDIFJvb3QgMjAyMDB2MBAGByqG
SM49AgEGBSuBBAAiA2IABM6//leov9Wq9xCazbzREaK9Z0LMkOsVGJDZos0MKiXrPk/OtdKPD/M1
2kOLAoC+b1EkHQ9rK8qfwm9QMuU3ILYg/4gND21Ju9sGpIeQkpT0CdDPf8iAC8GXs7s1J8nCG6NC
MEAwHQYDVR0OBBYEFONyzG6VmUex5rNhTNHLq+O6zd6fMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0P
AQH/BAQDAgEGMAoGCCqGSM49BAMDA2cAMGQCMHVSi7ekEE+uShCLsoRbQuHmKjYC2qBuGT8lv9pZ
Mo7k+5Dck2TOrbRBR2Diz6fLHgIwN0GMZt9Ba9aDAEH9L1r3ULRn0SyocddDypwnJJGDSA3PzfdU
ga/sf+Rn27iQ7t0l
-----END CERTIFICATE-----

Telekom Security TLS RSA Root 2023
==================================
-----BEGIN CERTIFICATE-----
MIIFszCCA5ugAwIBAgIQIZxULej27HF3+k7ow3BXlzANBgkqhkiG9w0BAQwFADBjMQswCQYDVQQG
EwJERTEnMCUGA1UECgweRGV1dHNjaGUgVGVsZWtvbSBTZWN1cml0eSBHbWJIMSswKQYDVQQDDCJU
ZWxla29tIFNlY3VyaXR5IFRMUyBSU0EgUm9vdCAyMDIzMB4XDTIzMDMyODEyMTY0NVoXDTQ4MDMy
NzIzNTk1OVowYzELMAkGA1UEBhMCREUxJzAlBgNVBAoMHkRldXRzY2hlIFRlbGVrb20gU2VjdXJp
dHkgR21iSDErMCkGA1UEAwwiVGVsZWtvbSBTZWN1cml0eSBUTFMgUlNBIFJvb3QgMjAyMzCCAiIw
DQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAO01oYGA88tKaVvC+1GDrib94W7zgRJ9cUD/h3VC
KSHtgVIs3xLBGYSJwb3FKNXVS2xE1kzbB5ZKVXrKNoIENqil/Cf2SfHVcp6R+SPWcHu79ZvB7JPP
GeplfohwoHP89v+1VmLhc2o0mD6CuKyVU/QBoCcHcqMAU6DksquDOFczJZSfvkgdmOGjup5czQRx
UX11eKvzWarE4GC+j4NSuHUaQTXtvPM6Y+mpFEXX5lLRbtLevOP1Czvm4MS9Q2QTps70mDdsipWo
l8hHD/BeEIvnHRz+sTugBTNoBUGCwQMrAcjnj02r6LX2zWtEtefdi+zqJbQAIldNsLGyMcEWzv/9
FIS3R/qy8XDe24tsNlikfLMR0cN3f1+2JeANxdKz+bi4d9s3cXFH42AYTyS2dTd4uaNir73Jco4v
zLuu2+QVUhkHM/tqty1LkCiCc/4YizWN26cEar7qwU02OxY2kTLvtkCJkUPg8qKrBC7m8kwOFjQg
rIfBLX7JZkcXFBGk8/ehJImr2BrIoVyxo/eMbcgByU/J7MT8rFEz0ciD0cmfHdRHNCk+y7AO+oML
KFjlKdw/fKifybYKu6boRhYPluV75Gp6SG12mAWl3G0eQh5C2hrgUve1g8Aae3g1LDj1H/1Joy7S
WWO/gLCMk3PLNaaZlSJhZQNg+y+TS/qanIA7AgMBAAGjYzBhMA4GA1UdDwEB/wQEAwIBBjAdBgNV
HQ4EFgQUtqeXgj10hZv3PJ+TmpV5dVKMbUcwDwYDVR0TAQH/BAUwAwEB/zAfBgNVHSMEGDAWgBS2
p5eCPXSFm/c8n5OalXl1UoxtRzANBgkqhkiG9w0BAQwFAAOCAgEAqMxhpr51nhVQpGv7qHBFfLp+
sVr8WyP6Cnf4mHGCDG3gXkaqk/QeoMPhk9tLrbKmXauw1GLLXrtm9S3ul0A8Yute1hTWjOKWi0Fp
kzXmuZlrYrShF2Y0pmtjxrlO8iLpWA1WQdH6DErwM807u20hOq6OcrXDSvvpfeWxm4bu4uB9tPcy
/SKE8YXJN3nptT+/XOR0so8RYgDdGGah2XsjX/GO1WfoVNpbOms2b/mBsTNHM3dA+VKq3dSDz4V4
mZqTuXNnQkYRIer+CqkbGmVps4+uFrb2S1ayLfmlyOw7YqPta9BO1UAJpB+Y1zqlklkg5LB9zVtz
aL1txKITDmcZuI1CfmwMmm6gJC3VRRvcxAIU/oVbZZfKTpBQCHpCNfnqwmbU+AGuHrS+w6jv/naa
oqYfRvaE7fzbzsQCzndILIyy7MMAo+wsVRjBfhnu4S/yrYObnqsZ38aKL4x35bcF7DvB7L6Gs4a8
wPfc5+pbrrLMtTWGS9DiP7bY+A4A7l3j941Y/8+LN+ljX273CXE2whJdV/LItM3z7gLfEdxquVeE
HVlNjM7IDiPCtyaaEBRx/pOyiriA8A4QntOoUAw3gi/q4Iqd4Sw5/7W0cwDk90imc6y/st53BIe0
o82bNSQ3+pCTE4FCxpgmdTdmQRCsu/WU48IxK63nI1bMNSWSs1A=
-----END CERTIFICATE-----

FIRMAPROFESIONAL CA ROOT-A WEB
==============================
-----BEGIN CERTIFICATE-----
MIICejCCAgCgAwIBAgIQMZch7a+JQn81QYehZ1ZMbTAKBggqhkjOPQQDAzBuMQswCQYDVQQGEwJF
UzEcMBoGA1UECgwTRmlybWFwcm9mZXNpb25hbCBTQTEYMBYGA1UEYQwPVkFURVMtQTYyNjM0MDY4
MScwJQYDVQQDDB5GSVJNQVBST0ZFU0lPTkFMIENBIFJPT1QtQSBXRUIwHhcNMjIwNDA2MDkwMTM2
WhcNNDcwMzMxMDkwMTM2WjBuMQswCQYDVQQGEwJFUzEcMBoGA1UECgwTRmlybWFwcm9mZXNpb25h
bCBTQTEYMBYGA1UEYQwPVkFURVMtQTYyNjM0MDY4MScwJQYDVQQDDB5GSVJNQVBST0ZFU0lPTkFM
IENBIFJPT1QtQSBXRUIwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAARHU+osEaR3xyrq89Zfe9MEkVz6
iMYiuYMQYneEMy3pA4jU4DP37XcsSmDq5G+tbbT4TIqk5B/K6k84Si6CcyvHZpsKjECcfIr28jlg
st7L7Ljkb+qbXbdTkBgyVcUgt5SjYzBhMA8GA1UdEwEB/wQFMAMBAf8wHwYDVR0jBBgwFoAUk+FD
Y1w8ndYn81LsF7Kpryz3dvgwHQYDVR0OBBYEFJPhQ2NcPJ3WJ/NS7Beyqa8s93b4MA4GA1UdDwEB
/wQEAwIBBjAKBggqhkjOPQQDAwNoADBlAjAdfKR7w4l1M+E7qUW/Runpod3JIha3RxEL2Jq68cgL
cFBTApFwhVmpHqTm6iMxoAACMQD94vizrxa5HnPEluPBMBnYfubDl94cT7iJLzPrSA8Z94dGXSaQ
pYXFuXqUPoeovQA=
-----END CERTIFICATE-----

TWCA CYBER Root CA
==================
-----BEGIN CERTIFICATE-----
MIIFjTCCA3WgAwIBAgIQQAE0jMIAAAAAAAAAATzyxjANBgkqhkiG9w0BAQwFADBQMQswCQYDVQQG
EwJUVzESMBAGA1UEChMJVEFJV0FOLUNBMRAwDgYDVQQLEwdSb290IENBMRswGQYDVQQDExJUV0NB
IENZQkVSIFJvb3QgQ0EwHhcNMjIxMTIyMDY1NDI5WhcNNDcxMTIyMTU1OTU5WjBQMQswCQYDVQQG
EwJUVzESMBAGA1UEChMJVEFJV0FOLUNBMRAwDgYDVQQLEwdSb290IENBMRswGQYDVQQDExJUV0NB
IENZQkVSIFJvb3QgQ0EwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDG+Moe2Qkgfh1s
Ts6P40czRJzHyWmqOlt47nDSkvgEs1JSHWdyKKHfi12VCv7qze33Kc7wb3+szT3vsxxFavcokPFh
V8UMxKNQXd7UtcsZyoC5dc4pztKFIuwCY8xEMCDa6pFbVuYdHNWdZsc/34bKS1PE2Y2yHer43CdT
o0fhYcx9tbD47nORxc5zb87uEB8aBs/pJ2DFTxnk684iJkXXYJndzk834H/nY62wuFm40AZoNWDT
Nq5xQwTxaWV4fPMf88oon1oglWa0zbfuj3ikRRjpJi+NmykosaS3Om251Bw4ckVYsV7r8Cibt4LK
/c/WMw+f+5eesRycnupfXtuq3VTpMCEobY5583WSjCb+3MX2w7DfRFlDo7YDKPYIMKoNM+HvnKkH
IuNZW0CP2oi3aQiotyMuRAlZN1vH4xfyIutuOVLF3lSnmMlLIJXcRolftBL5hSmO68gnFSDAS9TM
fAxsNAwmmyYxpjyn9tnQS6Jk/zuZQXLB4HCX8SS7K8R0IrGsayIyJNN4KsDAoS/xUgXJP+92ZuJF
2A09rZXIx4kmyA+upwMu+8Ff+iDhcK2wZSA3M2Cw1a/XDBzCkHDXShi8fgGwsOsVHkQGzaRP6AzR
wyAQ4VRlnrZR0Bp2a0JaWHY06rc3Ga4udfmW5cFZ95RXKSWNOkyrTZpB0F8mAwIDAQABo2MwYTAO
BgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAfBgNVHSMEGDAWgBSdhWEUfMFib5do5E83
QOGt4A1WNzAdBgNVHQ4EFgQUnYVhFHzBYm+XaORPN0DhreANVjcwDQYJKoZIhvcNAQEMBQADggIB
AGSPesRiDrWIzLjHhg6hShbNcAu3p4ULs3a2D6f/CIsLJc+o1IN1KriWiLb73y0ttGlTITVX1olN
c79pj3CjYcya2x6a4CD4bLubIp1dhDGaLIrdaqHXKGnK/nZVekZn68xDiBaiA9a5F/gZbG0jAn/x
X9AKKSM70aoK7akXJlQKTcKlTfjF/biBzysseKNnTKkHmvPfXvt89YnNdJdhEGoHK4Fa0o635yDR
IG4kqIQnoVesqlVYL9zZyvpoBJ7tRCT5dEA7IzOrg1oYJkK2bVS1FmAwbLGg+LhBoF1JSdJlBTrq
/p1hvIbZv97Tujqxf36SNI7JAG7cmL3c7IAFrQI932XtCwP39xaEBDG6k5TY8hL4iuO/Qq+n1M0R
FxbIQh0UqEL20kCGoE8jypZFVmAGzbdVAaYBlGX+bgUJurSkquLvWL69J1bY73NxW0Qz8ppy6rBe
Pm6pUlvscG21h483XjyMnM7k8M4MZ0HMzvaAq07MTFb1wWFZk7Q+ptq4NxKfKjLji7gh7MMrZQzv
It6IKTtM1/r+t+FHvpw+PoP7UV31aPcuIYXcv/Fa4nzXxeSDwWrruoBa3lwtcHb4yOWHh8qgnaHl
IhInD0Q9HWzq1MKLL295q39QpsQZp6F6t5b5wR9iWqJDB0BeJsas7a5wFsWqynKKTbDPAYsDP27X
-----END CERTIFICATE-----

SecureSign Root CA12
====================
-----BEGIN CERTIFICATE-----
MIIDcjCCAlqgAwIBAgIUZvnHwa/swlG07VOX5uaCwysckBYwDQYJKoZIhvcNAQELBQAwUTELMAkG
A1UEBhMCSlAxIzAhBgNVBAoTGkN5YmVydHJ1c3QgSmFwYW4gQ28uLCBMdGQuMR0wGwYDVQQDExRT
ZWN1cmVTaWduIFJvb3QgQ0ExMjAeFw0yMDA0MDgwNTM2NDZaFw00MDA0MDgwNTM2NDZaMFExCzAJ
BgNVBAYTAkpQMSMwIQYDVQQKExpDeWJlcnRydXN0IEphcGFuIENvLiwgTHRkLjEdMBsGA1UEAxMU
U2VjdXJlU2lnbiBSb290IENBMTIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC6OcE3
emhFKxS06+QT61d1I02PJC0W6K6OyX2kVzsqdiUzg2zqMoqUm048luT9Ub+ZyZN+v/mtp7JIKwcc
J/VMvHASd6SFVLX9kHrko+RRWAPNEHl57muTH2SOa2SroxPjcf59q5zdJ1M3s6oYwlkm7Fsf0uZl
fO+TvdhYXAvA42VvPMfKWeP+bl+sg779XSVOKik71gurFzJ4pOE+lEa+Ym6b3kaosRbnhW70CEBF
EaCeVESE99g2zvVQR9wsMJvuwPWW0v4JhscGWa5Pro4RmHvzC1KqYiaqId+OJTN5lxZJjfU+1Uef
NzFJM3IFTQy2VYzxV4+Kh9GtxRESOaCtAgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0P
AQH/BAQDAgEGMB0GA1UdDgQWBBRXNPN0zwRL1SXm8UC2LEzZLemgrTANBgkqhkiG9w0BAQsFAAOC
AQEAPrvbFxbS8hQBICw4g0utvsqFepq2m2um4fylOqyttCg6r9cBg0krY6LdmmQOmFxv3Y67ilQi
LUoT865AQ9tPkbeGGuwAtEGBpE/6aouIs3YIcipJQMPTw4WJmBClnW8Zt7vPemVV2zfrPIpyMpce
mik+rY3moxtt9XUa5rBouVui7mlHJzWhhpmA8zNL4WukJsPvdFlseqJkth5Ew1DgDzk9qTPxpfPS
vWKErI4cqc1avTc7bgoitPQV55FYxTpE05Uo2cBl6XLK0A+9H7MV2anjpEcJnuDLN/v9vZfVvhga
aaI5gdka9at/yOPiZwud9AzqVN/Ssq+xIvEg37xEHA==
-----END CERTIFICATE-----

SecureSign Root CA14
====================
-----BEGIN CERTIFICATE-----
MIIFcjCCA1qgAwIBAgIUZNtaDCBO6Ncpd8hQJ6JaJ90t8sswDQYJKoZIhvcNAQEMBQAwUTELMAkG
A1UEBhMCSlAxIzAhBgNVBAoTGkN5YmVydHJ1c3QgSmFwYW4gQ28uLCBMdGQuMR0wGwYDVQQDExRT
ZWN1cmVTaWduIFJvb3QgQ0ExNDAeFw0yMDA0MDgwNzA2MTlaFw00NTA0MDgwNzA2MTlaMFExCzAJ
BgNVBAYTAkpQMSMwIQYDVQQKExpDeWJlcnRydXN0IEphcGFuIENvLiwgTHRkLjEdMBsGA1UEAxMU
U2VjdXJlU2lnbiBSb290IENBMTQwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDF0nqh
1oq/FjHQmNE6lPxauG4iwWL3pwon71D2LrGeaBLwbCRjOfHw3xDG3rdSINVSW0KZnvOgvlIfX8xn
bacuUKLBl422+JX1sLrcneC+y9/3OPJH9aaakpUqYllQC6KxNedlsmGy6pJxaeQp8E+BgQQ8sqVb
1MWoWWd7VRxJq3qdwudzTe/NCcLEVxLbAQ4jeQkHO6Lo/IrPj8BGJJw4J+CDnRugv3gVEOuGTgpa
/d/aLIJ+7sr2KeH6caH3iGicnPCNvg9JkdjqOvn90Ghx2+m1K06Ckm9mH+Dw3EzsytHqunQG+bOE
kJTRX45zGRBdAuVwpcAQ0BB8b8VYSbSwbprafZX1zNoCr7gsfXmPvkPx+SgojQlD+Ajda8iLLCSx
jVIHvXiby8posqTdDEx5YMaZ0ZPxMBoH064iwurO8YQJzOAUbn8/ftKChazcqRZOhaBgy/ac18iz
ju3Gm5h1DVXoX+WViwKkrkMpKBGk5hIwAUt1ax5mnXkvpXYvHUC0bcl9eQjs0Wq2XSqypWa9a4X0
dFbD9ed1Uigspf9mR6XU/v6eVL9lfgHWMI+lNpyiUBzuOIABSMbHdPTGrMNASRZhdCyvjG817XsY
AFs2PJxQDcqSMxDxJklt33UkN4Ii1+iW/RVLApY+B3KVfqs9TC7XyvDf4Fg/LS8EmjijAQIDAQAB
o0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUBpOjCl4oaTeq
YR3r6/wtbyPk86AwDQYJKoZIhvcNAQEMBQADggIBAJaAcgkGfpzMkwQWu6A6jZJOtxEaCnFxEM0E
rX+lRVAQZk5KQaID2RFPeje5S+LGjzJmdSX7684/AykmjbgWHfYfM25I5uj4V7Ibed87hwriZLoA
ymzvftAj63iP/2SbNDefNWWipAA9EiOWWF3KY4fGoweITedpdopTzfFP7ELyk+OZpDc8h7hi2/Ds
Hzc/N19DzFGdtfCXwreFamgLRB7lUe6TzktuhsHSDCRZNhqfLJGP4xjblJUK7ZGqDpncllPjYYPG
FrojutzdfhrGe0K22VoF3Jpf1d+42kd92jjbrDnVHmtsKheMYc2xbXIBw8MgAGJoFjHVdqqGuw6q
nsb58Nn4DSEC5MUoFlkRudlpcyqSeLiSV5sI8jrlL5WwWLdrIBRtFO8KvH7YVdiI2i/6GaX7i+B/
OfVyK4XELKzvGUWSTLNhB9xNH27SgRNcmvMSZ4PPmz+Ln52kuaiWA3rF7iDeM9ovnhp6dB7h7sxa
OgTdsxoEqBRjrLdHEoOabPXm6RUVkRqEGQ6UROcSjiVbgGcZ3GOTEAtlLor6CZpO2oYofaphNdgO
pygau1LgePhsumywbrmHXumZNTfxPWQrqaA0k89jL9WB365jJ6UeTo3cKXhZ+PmhIIynJkBugnLN
eLLIjzwec+fBH7/PzqUqm9tEZDKgu39cJRNItX+S
-----END CERTIFICATE-----

SecureSign Root CA15
====================
-----BEGIN CERTIFICATE-----
MIICIzCCAamgAwIBAgIUFhXHw9hJp75pDIqI7fBw+d23PocwCgYIKoZIzj0EAwMwUTELMAkGA1UE
BhMCSlAxIzAhBgNVBAoTGkN5YmVydHJ1c3QgSmFwYW4gQ28uLCBMdGQuMR0wGwYDVQQDExRTZWN1
cmVTaWduIFJvb3QgQ0ExNTAeFw0yMDA0MDgwODMyNTZaFw00NTA0MDgwODMyNTZaMFExCzAJBgNV
BAYTAkpQMSMwIQYDVQQKExpDeWJlcnRydXN0IEphcGFuIENvLiwgTHRkLjEdMBsGA1UEAxMUU2Vj
dXJlU2lnbiBSb290IENBMTUwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAAQLUHSNZDKZmbPSYAi4Io5G
dCx4wCtELW1fHcmuS1Iggz24FG1Th2CeX2yF2wYUleDHKP+dX+Sq8bOLbe1PL0vJSpSRZHX+AezB
2Ot6lHhWGENfa4HL9rzatAy2KZMIaY+jQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQD
AgEGMB0GA1UdDgQWBBTrQciu/NWeUUj1vYv0hyCTQSvT9DAKBggqhkjOPQQDAwNoADBlAjEA2S6J
fl5OpBEHvVnCB96rMjhTKkZEBhd6zlHp4P9mLQlO4E/0BdGF9jVg3PVys0Z9AjBEmEYagoUeYWmJ
SwdLZrWeqrqgHkHZAXQ6bkU6iYAZezKYVWOr62Nuk22rGwlgMU4=
-----END CERTIFICATE-----

D-TRUST BR Root CA 2 2023
=========================
-----BEGIN CERTIFICATE-----
MIIFqTCCA5GgAwIBAgIQczswBEhb2U14LnNLyaHcZjANBgkqhkiG9w0BAQ0FADBIMQswCQYDVQQG
EwJERTEVMBMGA1UEChMMRC1UcnVzdCBHbWJIMSIwIAYDVQQDExlELVRSVVNUIEJSIFJvb3QgQ0Eg
MiAyMDIzMB4XDTIzMDUwOTA4NTYzMVoXDTM4MDUwOTA4NTYzMFowSDELMAkGA1UEBhMCREUxFTAT
BgNVBAoTDEQtVHJ1c3QgR21iSDEiMCAGA1UEAxMZRC1UUlVTVCBCUiBSb290IENBIDIgMjAyMzCC
AiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAK7/CVmRgApKaOYkP7in5Mg6CjoWzckjYaCT
cfKri3OPoGdlYNJUa2NRb0kz4HIHE304zQaSBylSa053bATTlfrdTIzZXcFhfUvnKLNEgXtRr90z
sWh81k5M/itoucpmacTsXld/9w3HnDY25QdgrMBM6ghs7wZ8T1soegj8k12b9py0i4a6Ibn08OhZ
WiihNIQaJZG2tY/vsvmA+vk9PBFy2OMvhnbFeSzBqZCTRphny4NqoFAjpzv2gTng7fC5v2Xx2Mt6
++9zA84A9H3X4F07ZrjcjrqDy4d2A/wl2ecjbwb9Z/Pg/4S8R7+1FhhGaRTMBffb00msa8yr5LUL
QyReS2tNZ9/WtT5PeB+UcSTq3nD88ZP+npNa5JRal1QMNXtfbO4AHyTsA7oC9Xb0n9Sa7YUsOCIv
x9gvdhFP/Wxc6PWOJ4d/GUohR5AdeY0cW/jPSoXk7bNbjb7EZChdQcRurDhaTyN0dKkSw/bSuREV
MweR2Ds3OmMwBtHFIjYoYiMQ4EbMl6zWK11kJNXuHA7e+whadSr2Y23OC0K+0bpwHJwh5Q8xaRfX
/Aq03u2AnMuStIv13lmiWAmlY0cL4UEyNEHZmrHZqLAbWt4NDfTisl01gLmB1IRpkQLLddCNxbU9
CZEJjxShFHR5PtbJFR2kWVki3PaKRT08EtY+XTIvAgMBAAGjgY4wgYswDwYDVR0TAQH/BAUwAwEB
/zAdBgNVHQ4EFgQUZ5Dw1t61GNVGKX5cq/ieCLxklRAwDgYDVR0PAQH/BAQDAgEGMEkGA1UdHwRC
MEAwPqA8oDqGOGh0dHA6Ly9jcmwuZC10cnVzdC5uZXQvY3JsL2QtdHJ1c3RfYnJfcm9vdF9jYV8y
XzIwMjMuY3JsMA0GCSqGSIb3DQEBDQUAA4ICAQA097N3U9swFrktpSHxQCF16+tIFoE9c+CeJyrr
d6kTpGoKWloUMz1oH4Guaf2Mn2VsNELZLdB/eBaxOqwjMa1ef67nriv6uvw8l5VAk1/DLQOj7aRv
U9f6QA4w9QAgLABMjDu0ox+2v5Eyq6+SmNMW5tTRVFxDWy6u71cqqLRvpO8NVhTaIasgdp4D/Ca4
nj8+AybmTNudX0KEPUUDAxxZiMrcLmEkWqTqJwtzEr5SswrPMhfiHocaFpVIbVrg0M8JkiZmkdij
YQ6qgYF/6FKC0ULn4B0Y+qSFNueG4A3rvNTJ1jxD8V1Jbn6Bm2m1iWKPiFLY1/4nwSPFyysCu7Ff
/vtDhQNGvl3GyiEm/9cCnnRK3PgTFbGBVzbLZVzRHTF36SXDw7IyN9XxmAnkbWOACKsGkoHU6XCP
pz+y7YaMgmo1yEJagtFSGkUPFaUA8JR7ZSdXOUPPfH/mvTWze/EZTN46ls/pdu4D58JDUjxqgejB
WoC9EV2Ta/vH5mQ/u2kc6d0li690yVRAysuTEwrt+2aSEcr1wPrYg1UDfNPFIkZ1cGt5SAYqgpq/
5usWDiJFAbzdNpQ0qTUmiteXue4Icr80knCDgKs4qllo3UCkGJCy89UDyibK79XH4I9TjvAA46jt
n/mtd+ArY0+ew+43u3gJhJ65bvspmZDogNOfJA==
-----END CERTIFICATE-----

TrustAsia TLS ECC Root CA
=========================
-----BEGIN CERTIFICATE-----
MIICMTCCAbegAwIBAgIUNnThTXxlE8msg1UloD5Sfi9QaMcwCgYIKoZIzj0EAwMwWDELMAkGA1UE
BhMCQ04xJTAjBgNVBAoTHFRydXN0QXNpYSBUZWNobm9sb2dpZXMsIEluYy4xIjAgBgNVBAMTGVRy
dXN0QXNpYSBUTFMgRUNDIFJvb3QgQ0EwHhcNMjQwNTE1MDU0MTU2WhcNNDQwNTE1MDU0MTU1WjBY
MQswCQYDVQQGEwJDTjElMCMGA1UEChMcVHJ1c3RBc2lhIFRlY2hub2xvZ2llcywgSW5jLjEiMCAG
A1UEAxMZVHJ1c3RBc2lhIFRMUyBFQ0MgUm9vdCBDQTB2MBAGByqGSM49AgEGBSuBBAAiA2IABLh/
pVs/AT598IhtrimY4ZtcU5nb9wj/1WrgjstEpvDBjL1P1M7UiFPoXlfXTr4sP/MSpwDpguMqWzJ8
S5sUKZ74LYO1644xST0mYekdcouJtgq7nDM1D9rs3qlKH8kzsaNCMEAwDwYDVR0TAQH/BAUwAwEB
/zAdBgNVHQ4EFgQULIVTu7FDzTLqnqOH/qKYqKaT6RAwDgYDVR0PAQH/BAQDAgEGMAoGCCqGSM49
BAMDA2gAMGUCMFRH18MtYYZI9HlaVQ01L18N9mdsd0AaRuf4aFtOJx24mH1/k78ITcTaRTChD15K
eAIxAKORh/IRM4PDwYqROkwrULG9IpRdNYlzg8WbGf60oenUoWa2AaU2+dhoYSi3dOGiMQ==
-----END CERTIFICATE-----

TrustAsia TLS RSA Root CA
=========================
-----BEGIN CERTIFICATE-----
MIIFgDCCA2igAwIBAgIUHBjYz+VTPyI1RlNUJDxsR9FcSpwwDQYJKoZIhvcNAQEMBQAwWDELMAkG
A1UEBhMCQ04xJTAjBgNVBAoTHFRydXN0QXNpYSBUZWNobm9sb2dpZXMsIEluYy4xIjAgBgNVBAMT
GVRydXN0QXNpYSBUTFMgUlNBIFJvb3QgQ0EwHhcNMjQwNTE1MDU0MTU3WhcNNDQwNTE1MDU0MTU2
WjBYMQswCQYDVQQGEwJDTjElMCMGA1UEChMcVHJ1c3RBc2lhIFRlY2hub2xvZ2llcywgSW5jLjEi
MCAGA1UEAxMZVHJ1c3RBc2lhIFRMUyBSU0EgUm9vdCBDQTCCAiIwDQYJKoZIhvcNAQEBBQADggIP
ADCCAgoCggIBAMMWuBtqpERz5dZO9LnPWwvB0ZqB9WOwj0PBuwhaGnrhB3YmH49pVr7+NmDQDIPN
lOrnxS1cLwUWAp4KqC/lYCZUlviYQB2srp10Zy9U+5RjmOMmSoPGlbYJQ1DNDX3eRA5gEk9bNb2/
mThtfWza4mhzH/kxpRkQcwUqwzIZheo0qt1CHjCNP561HmHVb70AcnKtEj+qpklz8oYVlQwQX1Fk
zv93uMltrOXVmPGZLmzjyUT5tUMnCE32ft5EebuyjBza00tsLtbDeLdM1aTk2tyKjg7/D8OmYCYo
zza/+lcK7Fs/6TAWe8TbxNRkoDD75f0dcZLdKY9BWN4ArTr9PXwaqLEX8E40eFgl1oUh63kd0Nyr
z2I8sMeXi9bQn9P+PN7F4/w6g3CEIR0JwqH8uyghZVNgepBtljhb//HXeltt08lwSUq6HTrQUNoy
IBnkiz/r1RYmNzz7dZ6wB3C4FGB33PYPXFIKvF1tjVEK2sUYyJtt3LCDs3+jTnhMmCWr8n4uIF6C
FabW2I+s5c0yhsj55NqJ4js+k8UTav/H9xj8Z7XvGCxUq0DTbE3txci3OE9kxJRMT6DNrqXGJyV1
J23G2pyOsAWZ1SgRxSHUuPzHlqtKZFlhaxP8S8ySpg+kUb8OWJDZgoM5pl+z+m6Ss80zDoWo8SnT
q1mt1tve1CuBAgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFLgHkXlcBvRG/XtZ
ylomkadFK/hTMA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQwFAAOCAgEAIZtqBSBdGBanEqT3
Rz/NyjuujsCCztxIJXgXbODgcMTWltnZ9r96nBO7U5WS/8+S4PPFJzVXqDuiGev4iqME3mmL5Dw8
veWv0BIb5Ylrc5tvJQJLkIKvQMKtuppgJFqBTQUYo+IzeXoLH5Pt7DlK9RME7I10nYEKqG/odv6L
TytpEoYKNDbdgptvT+Bz3Ul/KD7JO6NXBNiT2Twp2xIQaOHEibgGIOcberyxk2GaGUARtWqFVwHx
tlotJnMnlvm5P1vQiJ3koP26TpUJg3933FEFlJ0gcXax7PqJtZwuhfG5WyRasQmr2soaB82G39tp
27RIGAAtvKLEiUUjpQ7hRGU+isFqMB3iYPg6qocJQrmBktwliJiJ8Xw18WLK7nn4GS/+X/jbh87q
qA8MpugLoDzga5SYnH+tBuYc6kIQX+ImFTw3OffXvO645e8D7r0i+yiGNFjEWn9hongPXvPKnbwb
PKfILfanIhHKA9jnZwqKDss1jjQ52MjqjZ9k4DewbNfFj8GQYSbbJIweSsCI3zWQzj8C9GRh3sfI
B5XeMhg6j6JCQCTl1jNdfK7vsU1P1FeQNWrcrgSXSYk0ly4wBOeY99sLAZDBHwo/+ML+TvrbmnNz
FrwFuHnYWa8G5z9nODmxfKuU4CkUpijy323imttUQ/hHWKNddBWcwauwxzQ=
-----END CERTIFICATE-----

D-TRUST EV Root CA 2 2023
=========================
-----BEGIN CERTIFICATE-----
MIIFqTCCA5GgAwIBAgIQaSYJfoBLTKCnjHhiU19abzANBgkqhkiG9w0BAQ0FADBIMQswCQYDVQQG
EwJERTEVMBMGA1UEChMMRC1UcnVzdCBHbWJIMSIwIAYDVQQDExlELVRSVVNUIEVWIFJvb3QgQ0Eg
MiAyMDIzMB4XDTIzMDUwOTA5MTAzM1oXDTM4MDUwOTA5MTAzMlowSDELMAkGA1UEBhMCREUxFTAT
BgNVBAoTDEQtVHJ1c3QgR21iSDEiMCAGA1UEAxMZRC1UUlVTVCBFViBSb290IENBIDIgMjAyMzCC
AiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBANiOo4mAC7JXUtypU0w3uX9jFxPvp1sjW2l1
sJkKF8GLxNuo4MwxusLyzV3pt/gdr2rElYfXR8mV2IIEUD2BCP/kPbOx1sWy/YgJ25yE7CUXFId/
MHibaljJtnMoPDT3mfd/06b4HEV8rSyMlD/YZxBTfiLNTiVR8CUkNRFeEMbsh2aJgWi6zCudR3Mf
vc2RpHJqnKIbGKBv7FD0fUDCqDDPvXPIEysQEx6Lmqg6lHPTGGkKSv/BAQP/eX+1SH977ugpbzZM
lWGG2Pmic4ruri+W7mjNPU0oQvlFKzIbRlUWaqZLKfm7lVa/Rh3sHZMdwGWyH6FDrlaeoLGPaxK3
YG14C8qKXO0elg6DpkiVjTujIcSuWMYAsoS0I6SWhjW42J7YrDRJmGOVxcttSEfi8i4YHtAxq910
7PncjLgcjmgjutDzUNzPZY9zOjLHfP7KgiJPvo5iR2blzYfi6NUPGJ/lBHJLRjwQ8kTCZFZxTnXo
nMkmdMV9WdEKWw9t/p51HBjGGjp82A0EzM23RWV6sY+4roRIPrN6TagD4uJ+ARZZaBhDM7DS3LAa
QzXupdqpRlyuhoFBAUp0JuyfBr/CBTdkdXgpaP3F9ev+R/nkhbDhezGdpn9yo7nELC7MmVcOIQxF
AZRl62UJxmMiCzNJkkg8/M3OsD6Onov4/knFNXJHAgMBAAGjgY4wgYswDwYDVR0TAQH/BAUwAwEB
/zAdBgNVHQ4EFgQUqvyREBuHkV8Wub9PS5FeAByxMoAwDgYDVR0PAQH/BAQDAgEGMEkGA1UdHwRC
MEAwPqA8oDqGOGh0dHA6Ly9jcmwuZC10cnVzdC5uZXQvY3JsL2QtdHJ1c3RfZXZfcm9vdF9jYV8y
XzIwMjMuY3JsMA0GCSqGSIb3DQEBDQUAA4ICAQCTy6UfmRHsmg1fLBWTxj++EI14QvBukEdHjqOS
Mo1wj/Zbjb6JzkcBahsgIIlbyIIQbODnmaprxiqgYzWRaoUlrRc4pZt+UPJ26oUFKidBK7GB0aL2
QHWpDsvxVUjY7NHss+jOFKE17MJeNRqrphYBBo7q3C+jisosketSjl8MmxfPy3MHGcRqwnNU73xD
UmPBEcrCRbH0O1P1aa4846XerOhUt7KR/aypH/KH5BfGSah82ApB9PI+53c0BFLd6IHyTS9URZ0V
4U/M5d40VxDJI3IXcI1QcB9WbMy5/zpaT2N6w25lBx2Eof+pDGOJbbJAiDnXH3dotfyc1dZnaVuo
dNv8ifYbMvekJKZ2t0dT741Jj6m2g1qllpBFYfXeA08mD6iL8AOWsKwV0HFaanuU5nCT2vFp4LJi
TZ6P/4mdm13NRemUAiKN4DV/6PEEeXFsVIP4M7kFMhtYVRFP0OUnR3Hs7dpn1mKmS00PaaLJvOwi
S5THaJQXfuKOKD62xur1NGyfN4gHONuGcfrNlUhDbqNPgofXNJhuS5N5YHVpD/Aa1VP6IQzCP+k/
HxiMkl14p3ZnGbuy6n/pcAlWVqOwDAstNl7F6cTVg8uGF5csbBNvh1qvSaYd2804BC5f4ko1Di1L
+KIkBI3Y4WNeApI02phhXBxvWHZks/wCuPWdCg==
-----END CERTIFICATE-----

SwissSign RSA TLS Root CA 2022 - 1
==================================
-----BEGIN CERTIFICATE-----
MIIFkzCCA3ugAwIBAgIUQ/oMX04bgBhE79G0TzUfRPSA7cswDQYJKoZIhvcNAQELBQAwUTELMAkG
A1UEBhMCQ0gxFTATBgNVBAoTDFN3aXNzU2lnbiBBRzErMCkGA1UEAxMiU3dpc3NTaWduIFJTQSBU
TFMgUm9vdCBDQSAyMDIyIC0gMTAeFw0yMjA2MDgxMTA4MjJaFw00NzA2MDgxMTA4MjJaMFExCzAJ
BgNVBAYTAkNIMRUwEwYDVQQKEwxTd2lzc1NpZ24gQUcxKzApBgNVBAMTIlN3aXNzU2lnbiBSU0Eg
VExTIFJvb3QgQ0EgMjAyMiAtIDEwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDLKmji
C8NXvDVjvHClO/OMPE5Xlm7DTjak9gLKHqquuN6orx122ro10JFwB9+zBvKK8i5VUXu7LCTLf5Im
gKO0lPaCoaTo+nUdWfMHamFk4saMla+ju45vVs9xzF6BYQ1t8qsCLqSX5XH8irCRIFucdFJtrhUn
WXjyCcplDn/L9Ovn3KlMd/YrFgSVrpxxpT8q2kFC5zyEEPThPYxr4iuRR1VPuFa+Rd4iUU1OKNlf
GUEGjw5NBuBwQCMBauTLE5tzrE0USJIt/m2n+IdreXXhvhCxqohAWVTXz8TQm0SzOGlkjIHRI36q
OTw7D59Ke4LKa2/KIj4x0LDQKhySio/YGZxH5D4MucLNvkEM+KRHBdvBFzA4OmnczcNpI/2aDwLO
EGrOyvi5KaM2iYauC8BPY7kGWUleDsFpswrzd34unYyzJ5jSmY0lpx+Gs6ZUcDj8fV3oT4MM0ZPl
EuRU2j7yrTrePjxF8CgPBrnh25d7mUWe3f6VWQQvdT/TromZhqwUtKiE+shdOxtYk8EXlFXIC+OC
eYSf8wCENO7cMdWP8vpPlkwGqnj73mSiI80fPsWMvDdUDrtaclXvyFu1cvh43zcgTFeRc5JzrBh3
Q4IgaezprClG5QtO+DdziZaKHG29777YtvTKwP1H8K4LWCDFyB02rpeNUIMmJCn3nTsPBQIDAQAB
o2MwYTAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAfBgNVHSMEGDAWgBRvjmKLk0Ow
4UD2p8P98Q+4DxU4pTAdBgNVHQ4EFgQUb45ii5NDsOFA9qfD/fEPuA8VOKUwDQYJKoZIhvcNAQEL
BQADggIBAKwsKUF9+lz1GpUYvyypiqkkVHX1uECry6gkUSsYP2OprphWKwVDIqO310aewCoSPY6W
lkDfDDOLazeROpW7OSltwAJsipQLBwJNGD77+3v1dj2b9l4wBlgzHqp41eZUBDqyggmNzhYzWUUo
8aWjlw5DI/0LIICQ/+Mmz7hkkeUFjxOgdg3XNwwQiJb0Pr6VvfHDffCjw3lHC1ySFWPtUnWK50Zp
y1FVCypM9fJkT6lc/2cyjlUtMoIcgC9qkfjLvH4YoiaoLqNTKIftV+Vlek4ASltOU8liNr3Cjlvr
zG4ngRhZi0Rjn9UMZfQpZX+RLOV/fuiJz48gy20HQhFRJjKKLjpHE7iNvUcNCfAWpO2Whi4Z2L6M
OuhFLhG6rlrnub+xzI/goP+4s9GFe3lmozm1O2bYQL7Pt2eLSMkZJVX8vY3PXtpOpvJpzv1/THfQ
wUY1mFwjmwJFQ5Ra3bxHrSL+ul4vkSkphnsh3m5kt8sNjzdbowhq6/TdAo9QAwKxuDdollDruF/U
KIqlIgyKhPBZLtU30WHlQnNYKoH3dtvi4k0NX/a3vgW0rk4N3hY9A4GzJl5LuEsAz/+MF7psYC0n
hzck5npgL7XTgwSqT0N1osGDsieYK7EOgLrAhV5Cud+xYJHT6xh+cHiudoO+cVrQkOPKwRYlZ0rw
tnu64ZzZ
-----END CERTIFICATE-----

OISTE Server Root ECC G1
========================
-----BEGIN CERTIFICATE-----
MIICNTCCAbqgAwIBAgIQI/nD1jWvjyhLH/BU6n6XnTAKBggqhkjOPQQDAzBLMQswCQYDVQQGEwJD
SDEZMBcGA1UECgwQT0lTVEUgRm91bmRhdGlvbjEhMB8GA1UEAwwYT0lTVEUgU2VydmVyIFJvb3Qg
RUNDIEcxMB4XDTIzMDUzMTE0NDIyOFoXDTQ4MDUyNDE0NDIyN1owSzELMAkGA1UEBhMCQ0gxGTAX
BgNVBAoMEE9JU1RFIEZvdW5kYXRpb24xITAfBgNVBAMMGE9JU1RFIFNlcnZlciBSb290IEVDQyBH
MTB2MBAGByqGSM49AgEGBSuBBAAiA2IABBcv+hK8rBjzCvRE1nZCnrPoH7d5qVi2+GXROiFPqOuj
vqQycvO2Ackr/XeFblPdreqqLiWStukhEaivtUwL85Zgmjvn6hp4LrQ95SjeHIC6XG4N2xml4z+c
KrhAS93mT6NjMGEwDwYDVR0TAQH/BAUwAwEB/zAfBgNVHSMEGDAWgBQ3TYhlz/w9itWj8UnATgwQ
b0K0nDAdBgNVHQ4EFgQUN02IZc/8PYrVo/FJwE4MEG9CtJwwDgYDVR0PAQH/BAQDAgGGMAoGCCqG
SM49BAMDA2kAMGYCMQCpKjAd0MKfkFFRQD6VVCHNFmb3U2wIFjnQEnx/Yxvf4zgAOdktUyBFCxxg
ZzFDJe0CMQCSia7pXGKDYmH5LVerVrkR3SW+ak5KGoJr3M/TvEqzPNcum9v4KGm8ay3sMaE641c=
-----END CERTIFICATE-----

OISTE Server Root RSA G1
========================
-----BEGIN CERTIFICATE-----
MIIFgzCCA2ugAwIBAgIQVaXZZ5Qoxu0M+ifdWwFNGDANBgkqhkiG9w0BAQwFADBLMQswCQYDVQQG
EwJDSDEZMBcGA1UECgwQT0lTVEUgRm91bmRhdGlvbjEhMB8GA1UEAwwYT0lTVEUgU2VydmVyIFJv
b3QgUlNBIEcxMB4XDTIzMDUzMTE0MzcxNloXDTQ4MDUyNDE0MzcxNVowSzELMAkGA1UEBhMCQ0gx
GTAXBgNVBAoMEE9JU1RFIEZvdW5kYXRpb24xITAfBgNVBAMMGE9JU1RFIFNlcnZlciBSb290IFJT
QSBHMTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAKqu9KuCz/vlNwvn1ZatkOhLKdxV
YOPMvLO8LZK55KN68YG0nnJyQ98/qwsmtO57Gmn7KNByXEptaZnwYx4M0rH/1ow00O7brEi56rAU
jtgHqSSY3ekJvqgiG1k50SeH3BzN+Puz6+mTeO0Pzjd8JnduodgsIUzkik/HEzxux9UTl7Ko2yRp
g1bTacuCErudG/L4NPKYKyqOBGf244ehHa1uzjZ0Dl4zO8vbUZeUapU8zhhabkvG/AePLhq5Svdk
NCncpo1Q4Y2LS+VIG24ugBA/5J8bZT8RtOpXaZ+0AOuFJJkk9SGdl6r7NH8CaxWQrbueWhl/pIzY
+m0o/DjH40ytas7ZTpOSjswMZ78LS5bOZmdTaMsXEY5Z96ycG7mOaES3GK/m5Q9l3JUJsJMStR8+
lKXHiHUhsd4JJCpM4rzsTGdHwimIuQq6+cF0zowYJmXa92/GjHtoXAvuY8BeS/FOzJ8vD+HomnqT
8eDI278n5mUpezbgMxVz8p1rhAhoKzYHKyfMeNhqhw5HdPSqoBNdZH702xSu+zrkL8Fl47l6QGzw
Brd7KJvX4V84c5Ss2XCTLdyEr0YconosP4EmQufU2MVshGYRi3drVByjtdgQ8K4p92cIiBdcuJd5
z+orKu5YM+Vt6SmqZQENghPsJQtdLEByFSnTkCz3GkPVavBpAgMBAAGjYzBhMA8GA1UdEwEB/wQF
MAMBAf8wHwYDVR0jBBgwFoAU8snBDw1jALvsRQ5KH7WxszbNDo0wHQYDVR0OBBYEFPLJwQ8NYwC7
7EUOSh+1sbM2zQ6NMA4GA1UdDwEB/wQEAwIBhjANBgkqhkiG9w0BAQwFAAOCAgEANGd5sjrG5T33
I3K5Ce+SrScfoE4KsvXaFwyihdJ+klH9FWXXXGtkFu6KRcoMQzZENdl//nk6HOjG5D1rd9QhEOP2
8yBOqb6J8xycqd+8MDoX0TJD0KqKchxRKEzdNsjkLWd9kYccnbz8qyiWXmFcuCIzGEgWUOrKL+ml
Sdx/PKQZvDatkuK59EvV6wit53j+F8Bdh3foZ3dPAGav9LEDOr4SfEE15fSmG0eLy3n31r8Xbk5l
8PjaV8GUgeV6Vg27Rn9vkf195hfkgSe7BYhW3SCl95gtkRlpMV+bMPKZrXJAlszYd2abtNUOshD+
FKrDgHGdPY3ofRRsYWSGRqbXVMW215AWRqWFyp464+YTFrYVI8ypKVL9AMb2kI5Wj4kI3Zaq5tNq
qYY19tVFeEJKRvwDyF7YZvZFZSS0vod7VSCd9521Kvy5YhnLbDuv0204bKt7ph6N/Ome/msVuduC
msuY33OhkKCgxeDoAaijFJzIwZqsFVAzje18KotzlUBDJvyBpCpfOZC3J8tRd/iWkx7P8nd9H0aT
olkelUTFLXVksNb54Dxp6gS1HAviRkRNQzuXSXERvSS2wq1yVAb+axj5d9spLFKebXd7Yv0PTY6Y
MjAwcRLWJTXjn/hvnLXrahut6hDTlhZyBiElxky8j3C7DOReIoMt0r7+hVu05L0=
-----END CERTIFICATE-----

e-Szigno TLS Root CA 2023
=========================
-----BEGIN CERTIFICATE-----
MIICzzCCAjGgAwIBAgINAOhvGHvWOWuYSkmYCjAKBggqhkjOPQQDBDB1MQswCQYDVQQGEwJIVTER
MA8GA1UEBwwIQnVkYXBlc3QxFjAUBgNVBAoMDU1pY3Jvc2VjIEx0ZC4xFzAVBgNVBGEMDlZBVEhV
LTIzNTg0NDk3MSIwIAYDVQQDDBllLVN6aWdubyBUTFMgUm9vdCBDQSAyMDIzMB4XDTIzMDcxNzE0
MDAwMFoXDTM4MDcxNzE0MDAwMFowdTELMAkGA1UEBhMCSFUxETAPBgNVBAcMCEJ1ZGFwZXN0MRYw
FAYDVQQKDA1NaWNyb3NlYyBMdGQuMRcwFQYDVQRhDA5WQVRIVS0yMzU4NDQ5NzEiMCAGA1UEAwwZ
ZS1Temlnbm8gVExTIFJvb3QgQ0EgMjAyMzCBmzAQBgcqhkjOPQIBBgUrgQQAIwOBhgAEAGgP36J8
PKp0iGEKjcJMpQEiFNT3YHdCnAo4YKGMZz6zY+n6kbCLS+Y53wLCMAFSAL/fjO1ZrTJlqwlZULUZ
wmgcAOAFX9pQJhzDrAQixTpN7+lXWDajwRlTEArRzT/vSzUaQ49CE0y5LBqcvjC2xN7cS53kpDzL
Ltmt3999Cd8ukv+ho2MwYTAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4E
FgQUWYQCYlpGePVd3I8KECgj3NXW+0UwHwYDVR0jBBgwFoAUWYQCYlpGePVd3I8KECgj3NXW+0Uw
CgYIKoZIzj0EAwQDgYsAMIGHAkIBLdqu9S54tma4n7Zwf2Z0z+yOfP7AAXmazlIC58PRDHpty7Ve
7hekm9sEdu4pKeiv+62sUvTXK9Z3hBC9xdIoaDQCQTV2WnXzkoYI9bIeCvZlC9p2x1L/Cx6AcCIw
wzPbGO2E14vs7dOoY4G1VnxHx1YwlGhza9IuqbnZLBwpvQy6uWWL
-----END CERTIFICATE-----
Copyright (C) 2016 Composer

Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
composer/ca-bundle
==================

Small utility library that lets you find a path to the system CA bundle,
and includes a fallback to the Mozilla CA bundle.

Originally written as part of [composer/composer](https://github.com/composer/composer),
now extracted and made available as a stand-alone library.


Installation
------------

Install the latest version with:

```bash
$ composer require composer/ca-bundle
```


Requirements
------------

* PHP 5.3.2 is required but using the latest version of PHP is highly recommended.


Basic usage
-----------

### `Composer\CaBundle\CaBundle`

- `CaBundle::getSystemCaRootBundlePath()`: Returns the system CA bundle path, or a path to the bundled one as fallback
- `CaBundle::getBundledCaBundlePath()`: Returns the path to the bundled CA file
- `CaBundle::validateCaFile($filename)`: Validates a CA file using openssl_x509_parse only if it is safe to use
- `CaBundle::isOpensslParseSafe()`: Test if it is safe to use the PHP function openssl_x509_parse()
- `CaBundle::reset()`: Resets the static caches


#### To use with curl

```php
$curl = curl_init("https://example.org/");

$caPathOrFile = \Composer\CaBundle\CaBundle::getSystemCaRootBundlePath();
if (is_dir($caPathOrFile)) {
    curl_setopt($curl, CURLOPT_CAPATH, $caPathOrFile);
} else {
    curl_setopt($curl, CURLOPT_CAINFO, $caPathOrFile);
}

$result = curl_exec($curl);
```

#### To use with php streams

```php
$opts = array(
    'http' => array(
        'method' => "GET"
    )
);

$caPathOrFile = \Composer\CaBundle\CaBundle::getSystemCaRootBundlePath();
if (is_dir($caPathOrFile)) {
    $opts['ssl']['capath'] = $caPathOrFile;
} else {
    $opts['ssl']['cafile'] = $caPathOrFile;
}

$context = stream_context_create($opts);
$result = file_get_contents('https://example.com', false, $context);
```

#### To use with Guzzle

```php
$client = new \GuzzleHttp\Client([
    \GuzzleHttp\RequestOptions::VERIFY => \Composer\CaBundle\CaBundle::getSystemCaRootBundlePath()
]);
```

License
-------

composer/ca-bundle is licensed under the MIT License, see the LICENSE file for details.
{
    "name": "composer\/ca-bundle",
    "description": "Lets you find a path to the system CA bundle, and includes a fallback to the Mozilla CA bundle.",
    "type": "library",
    "license": "MIT",
    "keywords": [
        "cabundle",
        "cacert",
        "certificate",
        "ssl",
        "tls"
    ],
    "authors": [
        {
            "name": "Jordi Boggiano",
            "email": "j.boggiano@seld.be",
            "homepage": "http:\/\/seld.be"
        }
    ],
    "support": {
        "irc": "irc:\/\/irc.freenode.org\/composer",
        "issues": "https:\/\/github.com\/composer\/ca-bundle\/issues"
    },
    "require": {
        "ext-openssl": "*",
        "ext-pcre": "*",
        "php": "^7.2 || ^8.0"
    },
    "require-dev": {
        "phpunit\/phpunit": "^8 || ^9",
        "phpstan\/phpstan": "^1.10",
        "psr\/log": "^1.0 || ^2.0 || ^3.0",
        "symfony\/process": "^4.0 || ^5.0 || ^6.0 || ^7.0"
    },
    "autoload": {
        "psr-4": {
            "Composer\\CaBundle\\": "src"
        }
    },
    "autoload-dev": {
        "psr-4": {
            "Composer\\CaBundle\\": "tests"
        }
    },
    "extra": {
        "branch-alias": {
            "dev-main": "1.x-dev"
        }
    },
    "scripts": {
        "test": "@php phpunit",
        "phpstan": "@php phpstan analyse"
    }
}<?php

/*
 * This file is part of composer/ca-bundle.
 *
 * (c) Composer <https://github.com/composer>
 *
 * For the full copyright and license information, please view
 * the LICENSE file that was distributed with this source code.
 */
namespace Composer\CaBundle;

use _ContaoManager\Psr\Log\LoggerInterface;
use _ContaoManager\Symfony\Component\Process\PhpProcess;
/**
 * @author Chris Smith <chris@cs278.org>
 * @author Jordi Boggiano <j.boggiano@seld.be>
 */
class CaBundle
{
    /** @var string|null */
    private static $caPath;
    /** @var array<string, bool> */
    private static $caFileValidity = array();
    /**
     * Returns the system CA bundle path, or a path to the bundled one
     *
     * This method was adapted from Sslurp.
     * https://github.com/EvanDotPro/Sslurp
     *
     * (c) Evan Coury <me@evancoury.com>
     *
     * For the full copyright and license information, please see below:
     *
     * Copyright (c) 2013, Evan Coury
     * All rights reserved.
     *
     * Redistribution and use in source and binary forms, with or without modification,
     * are permitted provided that the following conditions are met:
     *
     *     * Redistributions of source code must retain the above copyright notice,
     *       this list of conditions and the following disclaimer.
     *
     *     * Redistributions in binary form must reproduce the above copyright notice,
     *       this list of conditions and the following disclaimer in the documentation
     *       and/or other materials provided with the distribution.
     *
     * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
     * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
     * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
     * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
     * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
     * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
     * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
     * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
     * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     *
     * @param  LoggerInterface $logger optional logger for information about which CA files were loaded
     * @return string          path to a CA bundle file or directory
     */
    public static function getSystemCaRootBundlePath(?LoggerInterface $logger = null)
    {
        if (self::$caPath !== null) {
            return self::$caPath;
        }
        $caBundlePaths = array();
        // If SSL_CERT_FILE env variable points to a valid certificate/bundle, use that.
        // This mimics how OpenSSL uses the SSL_CERT_FILE env variable.
        $caBundlePaths[] = self::getEnvVariable('SSL_CERT_FILE');
        // If SSL_CERT_DIR env variable points to a valid certificate/bundle, use that.
        // This mimics how OpenSSL uses the SSL_CERT_FILE env variable.
        $caBundlePaths[] = self::getEnvVariable('SSL_CERT_DIR');
        $caBundlePaths[] = ini_get('openssl.cafile');
        $caBundlePaths[] = ini_get('openssl.capath');
        $otherLocations = array(
            '/etc/pki/ca-trust/extracted/pem/tls-ca-bundle.pem',
            // Fedora, RHEL, CentOS (ca-certificates package) - NEW
            '/etc/pki/tls/certs/ca-bundle.crt',
            // Fedora, RHEL, CentOS (ca-certificates package) - Deprecated
            '/etc/ssl/certs/ca-certificates.crt',
            // Debian, Ubuntu, Gentoo, Arch Linux (ca-certificates package)
            '/etc/ssl/ca-bundle.pem',
            // SUSE, openSUSE (ca-certificates package)
            '/usr/ssl/certs/ca-bundle.crt',
            // Cygwin
            '/opt/local/share/curl/curl-ca-bundle.crt',
            // OS X macports, curl-ca-bundle package
            '/usr/local/share/curl/curl-ca-bundle.crt',
            // Default cURL CA bunde path (without --with-ca-bundle option)
            '/usr/share/ssl/certs/ca-bundle.crt',
            // Really old RedHat?
            '/etc/ssl/cert.pem',
            // OpenBSD
            '/usr/local/etc/openssl/cert.pem',
            // OS X homebrew, openssl package
            '/usr/local/etc/openssl@1.1/cert.pem',
            // OS X homebrew, openssl@1.1 package
            '/opt/homebrew/etc/openssl@3/cert.pem',
            // macOS silicon homebrew, openssl@3 package
            '/opt/homebrew/etc/openssl@1.1/cert.pem',
            // macOS silicon homebrew, openssl@1.1 package
            '/etc/pki/tls/certs',
            '/etc/ssl/certs',
        );
        $caBundlePaths = array_merge($caBundlePaths, $otherLocations);
        foreach ($caBundlePaths as $caBundle) {
            if ($caBundle && self::caFileUsable($caBundle, $logger)) {
                return self::$caPath = $caBundle;
            }
            if ($caBundle && self::caDirUsable($caBundle, $logger)) {
                return self::$caPath = $caBundle;
            }
        }
        return self::$caPath = static::getBundledCaBundlePath();
        // Bundled CA file, last resort
    }
    /**
     * Returns the path to the bundled CA file
     *
     * In case you don't want to trust the user or the system, you can use this directly
     *
     * @return string path to a CA bundle file
     */
    public static function getBundledCaBundlePath()
    {
        $caBundleFile = __DIR__ . '/../res/cacert.pem';
        // cURL does not understand 'phar://' paths
        // see https://github.com/composer/ca-bundle/issues/10
        if (0 === strpos($caBundleFile, 'phar://')) {
            $tempCaBundleFile = tempnam(sys_get_temp_dir(), 'openssl-ca-bundle-');
            if (\false === $tempCaBundleFile) {
                throw new \RuntimeException('Could not create a temporary file to store the bundled CA file');
            }
            file_put_contents($tempCaBundleFile, file_get_contents($caBundleFile));
            register_shutdown_function(function () use ($tempCaBundleFile) {
                @unlink($tempCaBundleFile);
            });
            $caBundleFile = $tempCaBundleFile;
        }
        return $caBundleFile;
    }
    /**
     * Validates a CA file using opensl_x509_parse only if it is safe to use
     *
     * @param string          $filename
     * @param LoggerInterface $logger   optional logger for information about which CA files were loaded
     *
     * @return bool
     */
    public static function validateCaFile($filename, ?LoggerInterface $logger = null)
    {
        static $warned = \false;
        if (isset(self::$caFileValidity[$filename])) {
            return self::$caFileValidity[$filename];
        }
        $contents = file_get_contents($filename);
        if (is_string($contents) && strlen($contents) > 0) {
            $contents = preg_replace("/^(\\-+(?:BEGIN|END))\\s+TRUSTED\\s+(CERTIFICATE\\-+)\$/m", '$1 $2', $contents);
            if (null === $contents) {
                // regex extraction failed
                $isValid = \false;
            } else {
                $isValid = (bool) openssl_x509_parse($contents);
            }
        } else {
            $isValid = \false;
        }
        if ($logger) {
            $logger->debug('Checked CA file ' . realpath($filename) . ': ' . ($isValid ? 'valid' : 'invalid'));
        }
        return self::$caFileValidity[$filename] = $isValid;
    }
    /**
     * Test if it is safe to use the PHP function openssl_x509_parse().
     *
     * This checks if OpenSSL extensions is vulnerable to remote code execution
     * via the exploit documented as CVE-2013-6420.
     *
     * @return bool
     */
    public static function isOpensslParseSafe()
    {
        return \true;
    }
    /**
     * Resets the static caches
     * @return void
     */
    public static function reset()
    {
        self::$caFileValidity = array();
        self::$caPath = null;
    }
    /**
     * @param  string $name
     * @return string|false
     */
    private static function getEnvVariable($name)
    {
        if (isset($_SERVER[$name])) {
            return (string) $_SERVER[$name];
        }
        if (\PHP_SAPI === 'cli' && ($value = getenv($name)) !== \false && $value !== null) {
            return (string) $value;
        }
        return \false;
    }
    /**
     * @param  string|false $certFile
     * @param  LoggerInterface|null $logger
     * @return bool
     */
    private static function caFileUsable($certFile, ?LoggerInterface $logger = null)
    {
        return $certFile && self::isFile($certFile, $logger) && self::isReadable($certFile, $logger) && self::validateCaFile($certFile, $logger);
    }
    /**
     * @param  string|false $certDir
     * @param  LoggerInterface|null $logger
     * @return bool
     */
    private static function caDirUsable($certDir, ?LoggerInterface $logger = null)
    {
        return $certDir && self::isDir($certDir, $logger) && self::isReadable($certDir, $logger) && self::glob($certDir . '/*', $logger);
    }
    /**
     * @param  string $certFile
     * @param  LoggerInterface|null $logger
     * @return bool
     */
    private static function isFile($certFile, ?LoggerInterface $logger = null)
    {
        $isFile = @is_file($certFile);
        if (!$isFile && $logger) {
            $logger->debug(sprintf('Checked CA file %s does not exist or it is not a file.', $certFile));
        }
        return $isFile;
    }
    /**
     * @param  string $certDir
     * @param  LoggerInterface|null $logger
     * @return bool
     */
    private static function isDir($certDir, ?LoggerInterface $logger = null)
    {
        $isDir = @is_dir($certDir);
        if (!$isDir && $logger) {
            $logger->debug(sprintf('Checked directory %s does not exist or it is not a directory.', $certDir));
        }
        return $isDir;
    }
    /**
     * @param  string $certFileOrDir
     * @param  LoggerInterface|null $logger
     * @return bool
     */
    private static function isReadable($certFileOrDir, ?LoggerInterface $logger = null)
    {
        $isReadable = @is_readable($certFileOrDir);
        if (!$isReadable && $logger) {
            $logger->debug(sprintf('Checked file or directory %s is not readable.', $certFileOrDir));
        }
        return $isReadable;
    }
    /**
     * @param  string $pattern
     * @param  LoggerInterface|null $logger
     * @return bool
     */
    private static function glob($pattern, ?LoggerInterface $logger = null)
    {
        $certs = glob($pattern);
        if ($certs === \false) {
            if ($logger) {
                $logger->debug(sprintf("An error occurred while trying to find certificates for pattern: %s", $pattern));
            }
            return \false;
        }
        if (count($certs) === 0) {
            if ($logger) {
                $logger->debug(sprintf("No CA files found for pattern: %s", $pattern));
            }
            return \false;
        }
        return \true;
    }
}
<?php

// autoload_psr4.php @generated by Composer

$vendorDir = dirname(__DIR__);
$baseDir = dirname($vendorDir);

return array(
    '_ContaoManager\\studio24\\Rotate\\' => array($vendorDir . '/studio24/rotate/src'),
    '_ContaoManager\\phpDocumentor\\Reflection\\' => array($vendorDir . '/phpdocumentor/reflection-docblock/src', $vendorDir . '/phpdocumentor/type-resolver/src', $vendorDir . '/phpdocumentor/reflection-common/src'),
    '_ContaoManager\\Webmozart\\Assert\\' => array($vendorDir . '/webmozart/assert/src'),
    '_ContaoManager\\Webauthn\\' => array($vendorDir . '/web-auth/webauthn-lib/src'),
    '_ContaoManager\\Terminal42\\ComposerLockValidator\\' => array($vendorDir . '/terminal42/composer-lock-validator/src'),
    '_ContaoManager\\Symfony\\Contracts\\Service\\' => array($vendorDir . '/symfony/service-contracts'),
    '_ContaoManager\\Symfony\\Contracts\\EventDispatcher\\' => array($vendorDir . '/symfony/event-dispatcher-contracts'),
    '_ContaoManager\\Symfony\\Contracts\\Cache\\' => array($vendorDir . '/symfony/cache-contracts'),
    '_ContaoManager\\Symfony\\Component\\Yaml\\' => array($vendorDir . '/symfony/yaml'),
    '_ContaoManager\\Symfony\\Component\\VarExporter\\' => array($vendorDir . '/symfony/var-exporter'),
    '_ContaoManager\\Symfony\\Component\\VarDumper\\' => array($vendorDir . '/symfony/var-dumper'),
    '_ContaoManager\\Symfony\\Component\\Uid\\' => array($vendorDir . '/symfony/uid'),
    '_ContaoManager\\Symfony\\Component\\String\\' => array($vendorDir . '/symfony/string'),
    '_ContaoManager\\Symfony\\Component\\Serializer\\' => array($vendorDir . '/symfony/serializer'),
    '_ContaoManager\\Symfony\\Component\\Security\\Http\\' => array($vendorDir . '/symfony/security-http'),
    '_ContaoManager\\Symfony\\Component\\Security\\Csrf\\' => array($vendorDir . '/symfony/security-csrf'),
    '_ContaoManager\\Symfony\\Component\\Security\\Core\\' => array($vendorDir . '/symfony/security-core'),
    '_ContaoManager\\Symfony\\Component\\Routing\\' => array($vendorDir . '/symfony/routing'),
    '_ContaoManager\\Symfony\\Component\\PropertyInfo\\' => array($vendorDir . '/symfony/property-info'),
    '_ContaoManager\\Symfony\\Component\\PropertyAccess\\' => array($vendorDir . '/symfony/property-access'),
    '_ContaoManager\\Symfony\\Component\\Process\\' => array($vendorDir . '/symfony/process'),
    '_ContaoManager\\Symfony\\Component\\PasswordHasher\\' => array($vendorDir . '/symfony/password-hasher'),
    '_ContaoManager\\Symfony\\Component\\HttpKernel\\' => array($vendorDir . '/symfony/http-kernel'),
    '_ContaoManager\\Symfony\\Component\\HttpFoundation\\' => array($vendorDir . '/symfony/http-foundation'),
    '_ContaoManager\\Symfony\\Component\\Finder\\' => array($vendorDir . '/symfony/finder'),
    '_ContaoManager\\Symfony\\Component\\Filesystem\\' => array($vendorDir . '/symfony/filesystem'),
    '_ContaoManager\\Symfony\\Component\\EventDispatcher\\' => array($vendorDir . '/symfony/event-dispatcher'),
    '_ContaoManager\\Symfony\\Component\\ErrorHandler\\' => array($vendorDir . '/symfony/error-handler'),
    '_ContaoManager\\Symfony\\Component\\DependencyInjection\\' => array($vendorDir . '/symfony/dependency-injection'),
    '_ContaoManager\\Symfony\\Component\\Console\\' => array($vendorDir . '/symfony/console'),
    '_ContaoManager\\Symfony\\Component\\Config\\' => array($vendorDir . '/symfony/config'),
    '_ContaoManager\\Symfony\\Component\\Clock\\' => array($vendorDir . '/symfony/clock'),
    '_ContaoManager\\Symfony\\Component\\Cache\\' => array($vendorDir . '/symfony/cache'),
    '_ContaoManager\\Symfony\\Bundle\\SecurityBundle\\' => array($vendorDir . '/symfony/security-bundle'),
    '_ContaoManager\\Symfony\\Bundle\\MonologBundle\\' => array($vendorDir . '/symfony/monolog-bundle/src'),
    '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\' => array($vendorDir . '/symfony/framework-bundle'),
    '_ContaoManager\\Symfony\\Bridge\\Monolog\\' => array($vendorDir . '/symfony/monolog-bridge'),
    '_ContaoManager\\SpomkyLabs\\Pki\\' => array($vendorDir . '/spomky-labs/pki-framework/src'),
    '_ContaoManager\\Seld\\Signal\\' => array($vendorDir . '/seld/signal-handler/src'),
    '_ContaoManager\\Seld\\PharUtils\\' => array($vendorDir . '/seld/phar-utils/src'),
    '_ContaoManager\\Seld\\JsonLint\\' => array($vendorDir . '/seld/jsonlint/src/Seld/JsonLint'),
    '_ContaoManager\\Ramsey\\Uuid\\' => array($vendorDir . '/ramsey/uuid/src'),
    '_ContaoManager\\Ramsey\\Collection\\' => array($vendorDir . '/ramsey/collection/src'),
    '_ContaoManager\\Psr\\Log\\' => array($vendorDir . '/psr/log/src'),
    '_ContaoManager\\Psr\\Http\\Message\\' => array($vendorDir . '/psr/http-factory/src', $vendorDir . '/psr/http-message/src'),
    '_ContaoManager\\Psr\\Http\\Client\\' => array($vendorDir . '/psr/http-client/src'),
    '_ContaoManager\\Psr\\EventDispatcher\\' => array($vendorDir . '/psr/event-dispatcher/src'),
    '_ContaoManager\\Psr\\Container\\' => array($vendorDir . '/psr/container/src'),
    '_ContaoManager\\Psr\\Clock\\' => array($vendorDir . '/psr/clock/src'),
    '_ContaoManager\\Psr\\Cache\\' => array($vendorDir . '/psr/cache/src'),
    '_ContaoManager\\ParagonIE\\ConstantTime\\' => array($vendorDir . '/paragonie/constant_time_encoding/src'),
    '_ContaoManager\\PHPStan\\PhpDocParser\\' => array($vendorDir . '/phpstan/phpdoc-parser/src'),
    '_ContaoManager\\OTPHP\\' => array($vendorDir . '/spomky-labs/otphp/src'),
    '_ContaoManager\\Monolog\\' => array($vendorDir . '/monolog/monolog/src/Monolog'),
    '_ContaoManager\\MabeEnum\\' => array($vendorDir . '/marc-mabe/php-enum/src'),
    '_ContaoManager\\Lcobucci\\Clock\\' => array($vendorDir . '/lcobucci/clock/src'),
    '_ContaoManager\\JsonSchema\\' => array($vendorDir . '/justinrainbow/json-schema/src/JsonSchema'),
    '_ContaoManager\\Firebase\\JWT\\' => array($vendorDir . '/firebase/php-jwt/src'),
    '_ContaoManager\\Doctrine\\Deprecations\\' => array($vendorDir . '/doctrine/deprecations/src'),
    '_ContaoManager\\Crell\\ApiProblem\\' => array($vendorDir . '/crell/api-problem/src'),
    '_ContaoManager\\Cose\\' => array($vendorDir . '/web-auth/cose-lib/src'),
    '_ContaoManager\\Contao\\ManagerApi\\' => array($baseDir . '/api'),
    '_ContaoManager\\CBOR\\' => array($vendorDir . '/spomky-labs/cbor-php/src'),
    '_ContaoManager\\Brick\\Math\\' => array($vendorDir . '/brick/math/src'),
    'Symfony\\Polyfill\\Uuid\\' => array($vendorDir . '/symfony/polyfill-uuid'),
    'Symfony\\Polyfill\\Php84\\' => array($vendorDir . '/symfony/polyfill-php84'),
    'Symfony\\Polyfill\\Php83\\' => array($vendorDir . '/symfony/polyfill-php83'),
    'Symfony\\Polyfill\\Php81\\' => array($vendorDir . '/symfony/polyfill-php81'),
    'Symfony\\Polyfill\\Php80\\' => array($vendorDir . '/symfony/polyfill-php80'),
    'Symfony\\Polyfill\\Php73\\' => array($vendorDir . '/symfony/polyfill-php73'),
    'Symfony\\Polyfill\\Mbstring\\' => array($vendorDir . '/symfony/polyfill-mbstring'),
    'Symfony\\Polyfill\\Intl\\Normalizer\\' => array($vendorDir . '/symfony/polyfill-intl-normalizer'),
    'Symfony\\Polyfill\\Intl\\Grapheme\\' => array($vendorDir . '/symfony/polyfill-intl-grapheme'),
    'Symfony\\Polyfill\\Ctype\\' => array($vendorDir . '/symfony/polyfill-ctype'),
    'React\\Promise\\' => array($vendorDir . '/react/promise/src'),
    'Composer\\XdebugHandler\\' => array($vendorDir . '/composer/xdebug-handler/src'),
    'Composer\\Spdx\\' => array($vendorDir . '/composer/spdx-licenses/src'),
    'Composer\\Semver\\' => array($vendorDir . '/composer/semver/src'),
    'Composer\\Pcre\\' => array($vendorDir . '/composer/pcre/src'),
    'Composer\\MetadataMinifier\\' => array($vendorDir . '/composer/metadata-minifier/src'),
    'Composer\\ClassMapGenerator\\' => array($vendorDir . '/composer/class-map-generator/src'),
    'Composer\\CaBundle\\' => array($vendorDir . '/composer/ca-bundle/src'),
    'Composer\\' => array($vendorDir . '/composer/composer/src/Composer'),
);
<?php

// autoload_classmap.php @generated by Composer

$vendorDir = dirname(__DIR__);
$baseDir = dirname($vendorDir);

return array(
    'Attribute' => $vendorDir . '/symfony/polyfill-php80/Resources/stubs/Attribute.php',
    'CURLStringFile' => $vendorDir . '/symfony/polyfill-php81/Resources/stubs/CURLStringFile.php',
    'Composer\\Advisory\\AuditConfig' => $vendorDir . '/composer/composer/src/Composer/Advisory/AuditConfig.php',
    'Composer\\Advisory\\Auditor' => $vendorDir . '/composer/composer/src/Composer/Advisory/Auditor.php',
    'Composer\\Advisory\\IgnoredSecurityAdvisory' => $vendorDir . '/composer/composer/src/Composer/Advisory/IgnoredSecurityAdvisory.php',
    'Composer\\Advisory\\PartialSecurityAdvisory' => $vendorDir . '/composer/composer/src/Composer/Advisory/PartialSecurityAdvisory.php',
    'Composer\\Advisory\\SecurityAdvisory' => $vendorDir . '/composer/composer/src/Composer/Advisory/SecurityAdvisory.php',
    'Composer\\Autoload\\AutoloadGenerator' => $vendorDir . '/composer/composer/src/Composer/Autoload/AutoloadGenerator.php',
    'Composer\\Autoload\\ClassLoader' => $vendorDir . '/composer/composer/src/Composer/Autoload/ClassLoader.php',
    'Composer\\Autoload\\ClassMapGenerator' => $vendorDir . '/composer/composer/src/Composer/Autoload/ClassMapGenerator.php',
    'Composer\\CaBundle\\CaBundle' => $vendorDir . '/composer/ca-bundle/src/CaBundle.php',
    'Composer\\Cache' => $vendorDir . '/composer/composer/src/Composer/Cache.php',
    'Composer\\ClassMapGenerator\\ClassMap' => $vendorDir . '/composer/class-map-generator/src/ClassMap.php',
    'Composer\\ClassMapGenerator\\ClassMapGenerator' => $vendorDir . '/composer/class-map-generator/src/ClassMapGenerator.php',
    'Composer\\ClassMapGenerator\\FileList' => $vendorDir . '/composer/class-map-generator/src/FileList.php',
    'Composer\\ClassMapGenerator\\PhpFileCleaner' => $vendorDir . '/composer/class-map-generator/src/PhpFileCleaner.php',
    'Composer\\ClassMapGenerator\\PhpFileParser' => $vendorDir . '/composer/class-map-generator/src/PhpFileParser.php',
    'Composer\\Command\\AboutCommand' => $vendorDir . '/composer/composer/src/Composer/Command/AboutCommand.php',
    'Composer\\Command\\ArchiveCommand' => $vendorDir . '/composer/composer/src/Composer/Command/ArchiveCommand.php',
    'Composer\\Command\\AuditCommand' => $vendorDir . '/composer/composer/src/Composer/Command/AuditCommand.php',
    'Composer\\Command\\BaseCommand' => $vendorDir . '/composer/composer/src/Composer/Command/BaseCommand.php',
    'Composer\\Command\\BaseConfigCommand' => $vendorDir . '/composer/composer/src/Composer/Command/BaseConfigCommand.php',
    'Composer\\Command\\BaseDependencyCommand' => $vendorDir . '/composer/composer/src/Composer/Command/BaseDependencyCommand.php',
    'Composer\\Command\\BumpCommand' => $vendorDir . '/composer/composer/src/Composer/Command/BumpCommand.php',
    'Composer\\Command\\CheckPlatformReqsCommand' => $vendorDir . '/composer/composer/src/Composer/Command/CheckPlatformReqsCommand.php',
    'Composer\\Command\\ClearCacheCommand' => $vendorDir . '/composer/composer/src/Composer/Command/ClearCacheCommand.php',
    'Composer\\Command\\CompletionTrait' => $vendorDir . '/composer/composer/src/Composer/Command/CompletionTrait.php',
    'Composer\\Command\\ConfigCommand' => $vendorDir . '/composer/composer/src/Composer/Command/ConfigCommand.php',
    'Composer\\Command\\CreateProjectCommand' => $vendorDir . '/composer/composer/src/Composer/Command/CreateProjectCommand.php',
    'Composer\\Command\\DependsCommand' => $vendorDir . '/composer/composer/src/Composer/Command/DependsCommand.php',
    'Composer\\Command\\DiagnoseCommand' => $vendorDir . '/composer/composer/src/Composer/Command/DiagnoseCommand.php',
    'Composer\\Command\\DumpAutoloadCommand' => $vendorDir . '/composer/composer/src/Composer/Command/DumpAutoloadCommand.php',
    'Composer\\Command\\ExecCommand' => $vendorDir . '/composer/composer/src/Composer/Command/ExecCommand.php',
    'Composer\\Command\\FundCommand' => $vendorDir . '/composer/composer/src/Composer/Command/FundCommand.php',
    'Composer\\Command\\GlobalCommand' => $vendorDir . '/composer/composer/src/Composer/Command/GlobalCommand.php',
    'Composer\\Command\\HomeCommand' => $vendorDir . '/composer/composer/src/Composer/Command/HomeCommand.php',
    'Composer\\Command\\InitCommand' => $vendorDir . '/composer/composer/src/Composer/Command/InitCommand.php',
    'Composer\\Command\\InstallCommand' => $vendorDir . '/composer/composer/src/Composer/Command/InstallCommand.php',
    'Composer\\Command\\LicensesCommand' => $vendorDir . '/composer/composer/src/Composer/Command/LicensesCommand.php',
    'Composer\\Command\\OutdatedCommand' => $vendorDir . '/composer/composer/src/Composer/Command/OutdatedCommand.php',
    'Composer\\Command\\PackageDiscoveryTrait' => $vendorDir . '/composer/composer/src/Composer/Command/PackageDiscoveryTrait.php',
    'Composer\\Command\\ProhibitsCommand' => $vendorDir . '/composer/composer/src/Composer/Command/ProhibitsCommand.php',
    'Composer\\Command\\ReinstallCommand' => $vendorDir . '/composer/composer/src/Composer/Command/ReinstallCommand.php',
    'Composer\\Command\\RemoveCommand' => $vendorDir . '/composer/composer/src/Composer/Command/RemoveCommand.php',
    'Composer\\Command\\RepositoryCommand' => $vendorDir . '/composer/composer/src/Composer/Command/RepositoryCommand.php',
    'Composer\\Command\\RequireCommand' => $vendorDir . '/composer/composer/src/Composer/Command/RequireCommand.php',
    'Composer\\Command\\RunScriptCommand' => $vendorDir . '/composer/composer/src/Composer/Command/RunScriptCommand.php',
    'Composer\\Command\\ScriptAliasCommand' => $vendorDir . '/composer/composer/src/Composer/Command/ScriptAliasCommand.php',
    'Composer\\Command\\SearchCommand' => $vendorDir . '/composer/composer/src/Composer/Command/SearchCommand.php',
    'Composer\\Command\\SelfUpdateCommand' => $vendorDir . '/composer/composer/src/Composer/Command/SelfUpdateCommand.php',
    'Composer\\Command\\ShowCommand' => $vendorDir . '/composer/composer/src/Composer/Command/ShowCommand.php',
    'Composer\\Command\\StatusCommand' => $vendorDir . '/composer/composer/src/Composer/Command/StatusCommand.php',
    'Composer\\Command\\SuggestsCommand' => $vendorDir . '/composer/composer/src/Composer/Command/SuggestsCommand.php',
    'Composer\\Command\\UpdateCommand' => $vendorDir . '/composer/composer/src/Composer/Command/UpdateCommand.php',
    'Composer\\Command\\ValidateCommand' => $vendorDir . '/composer/composer/src/Composer/Command/ValidateCommand.php',
    'Composer\\Compiler' => $vendorDir . '/composer/composer/src/Composer/Compiler.php',
    'Composer\\Composer' => $vendorDir . '/composer/composer/src/Composer/Composer.php',
    'Composer\\Config' => $vendorDir . '/composer/composer/src/Composer/Config.php',
    'Composer\\Config\\ConfigSourceInterface' => $vendorDir . '/composer/composer/src/Composer/Config/ConfigSourceInterface.php',
    'Composer\\Config\\JsonConfigSource' => $vendorDir . '/composer/composer/src/Composer/Config/JsonConfigSource.php',
    'Composer\\Console\\Application' => $vendorDir . '/composer/composer/src/Composer/Console/Application.php',
    'Composer\\Console\\GithubActionError' => $vendorDir . '/composer/composer/src/Composer/Console/GithubActionError.php',
    'Composer\\Console\\HtmlOutputFormatter' => $vendorDir . '/composer/composer/src/Composer/Console/HtmlOutputFormatter.php',
    'Composer\\Console\\Input\\InputArgument' => $vendorDir . '/composer/composer/src/Composer/Console/Input/InputArgument.php',
    'Composer\\Console\\Input\\InputOption' => $vendorDir . '/composer/composer/src/Composer/Console/Input/InputOption.php',
    'Composer\\DependencyResolver\\Decisions' => $vendorDir . '/composer/composer/src/Composer/DependencyResolver/Decisions.php',
    'Composer\\DependencyResolver\\DefaultPolicy' => $vendorDir . '/composer/composer/src/Composer/DependencyResolver/DefaultPolicy.php',
    'Composer\\DependencyResolver\\GenericRule' => $vendorDir . '/composer/composer/src/Composer/DependencyResolver/GenericRule.php',
    'Composer\\DependencyResolver\\LocalRepoTransaction' => $vendorDir . '/composer/composer/src/Composer/DependencyResolver/LocalRepoTransaction.php',
    'Composer\\DependencyResolver\\LockTransaction' => $vendorDir . '/composer/composer/src/Composer/DependencyResolver/LockTransaction.php',
    'Composer\\DependencyResolver\\MultiConflictRule' => $vendorDir . '/composer/composer/src/Composer/DependencyResolver/MultiConflictRule.php',
    'Composer\\DependencyResolver\\Operation\\InstallOperation' => $vendorDir . '/composer/composer/src/Composer/DependencyResolver/Operation/InstallOperation.php',
    'Composer\\DependencyResolver\\Operation\\MarkAliasInstalledOperation' => $vendorDir . '/composer/composer/src/Composer/DependencyResolver/Operation/MarkAliasInstalledOperation.php',
    'Composer\\DependencyResolver\\Operation\\MarkAliasUninstalledOperation' => $vendorDir . '/composer/composer/src/Composer/DependencyResolver/Operation/MarkAliasUninstalledOperation.php',
    'Composer\\DependencyResolver\\Operation\\OperationInterface' => $vendorDir . '/composer/composer/src/Composer/DependencyResolver/Operation/OperationInterface.php',
    'Composer\\DependencyResolver\\Operation\\SolverOperation' => $vendorDir . '/composer/composer/src/Composer/DependencyResolver/Operation/SolverOperation.php',
    'Composer\\DependencyResolver\\Operation\\UninstallOperation' => $vendorDir . '/composer/composer/src/Composer/DependencyResolver/Operation/UninstallOperation.php',
    'Composer\\DependencyResolver\\Operation\\UpdateOperation' => $vendorDir . '/composer/composer/src/Composer/DependencyResolver/Operation/UpdateOperation.php',
    'Composer\\DependencyResolver\\PolicyInterface' => $vendorDir . '/composer/composer/src/Composer/DependencyResolver/PolicyInterface.php',
    'Composer\\DependencyResolver\\Pool' => $vendorDir . '/composer/composer/src/Composer/DependencyResolver/Pool.php',
    'Composer\\DependencyResolver\\PoolBuilder' => $vendorDir . '/composer/composer/src/Composer/DependencyResolver/PoolBuilder.php',
    'Composer\\DependencyResolver\\PoolOptimizer' => $vendorDir . '/composer/composer/src/Composer/DependencyResolver/PoolOptimizer.php',
    'Composer\\DependencyResolver\\Problem' => $vendorDir . '/composer/composer/src/Composer/DependencyResolver/Problem.php',
    'Composer\\DependencyResolver\\Request' => $vendorDir . '/composer/composer/src/Composer/DependencyResolver/Request.php',
    'Composer\\DependencyResolver\\Rule' => $vendorDir . '/composer/composer/src/Composer/DependencyResolver/Rule.php',
    'Composer\\DependencyResolver\\Rule2Literals' => $vendorDir . '/composer/composer/src/Composer/DependencyResolver/Rule2Literals.php',
    'Composer\\DependencyResolver\\RuleSet' => $vendorDir . '/composer/composer/src/Composer/DependencyResolver/RuleSet.php',
    'Composer\\DependencyResolver\\RuleSetGenerator' => $vendorDir . '/composer/composer/src/Composer/DependencyResolver/RuleSetGenerator.php',
    'Composer\\DependencyResolver\\RuleSetIterator' => $vendorDir . '/composer/composer/src/Composer/DependencyResolver/RuleSetIterator.php',
    'Composer\\DependencyResolver\\RuleWatchChain' => $vendorDir . '/composer/composer/src/Composer/DependencyResolver/RuleWatchChain.php',
    'Composer\\DependencyResolver\\RuleWatchGraph' => $vendorDir . '/composer/composer/src/Composer/DependencyResolver/RuleWatchGraph.php',
    'Composer\\DependencyResolver\\RuleWatchNode' => $vendorDir . '/composer/composer/src/Composer/DependencyResolver/RuleWatchNode.php',
    'Composer\\DependencyResolver\\SecurityAdvisoryPoolFilter' => $vendorDir . '/composer/composer/src/Composer/DependencyResolver/SecurityAdvisoryPoolFilter.php',
    'Composer\\DependencyResolver\\Solver' => $vendorDir . '/composer/composer/src/Composer/DependencyResolver/Solver.php',
    'Composer\\DependencyResolver\\SolverBugException' => $vendorDir . '/composer/composer/src/Composer/DependencyResolver/SolverBugException.php',
    'Composer\\DependencyResolver\\SolverProblemsException' => $vendorDir . '/composer/composer/src/Composer/DependencyResolver/SolverProblemsException.php',
    'Composer\\DependencyResolver\\Transaction' => $vendorDir . '/composer/composer/src/Composer/DependencyResolver/Transaction.php',
    'Composer\\Downloader\\ArchiveDownloader' => $vendorDir . '/composer/composer/src/Composer/Downloader/ArchiveDownloader.php',
    'Composer\\Downloader\\ChangeReportInterface' => $vendorDir . '/composer/composer/src/Composer/Downloader/ChangeReportInterface.php',
    'Composer\\Downloader\\DownloadManager' => $vendorDir . '/composer/composer/src/Composer/Downloader/DownloadManager.php',
    'Composer\\Downloader\\DownloaderInterface' => $vendorDir . '/composer/composer/src/Composer/Downloader/DownloaderInterface.php',
    'Composer\\Downloader\\DvcsDownloaderInterface' => $vendorDir . '/composer/composer/src/Composer/Downloader/DvcsDownloaderInterface.php',
    'Composer\\Downloader\\FileDownloader' => $vendorDir . '/composer/composer/src/Composer/Downloader/FileDownloader.php',
    'Composer\\Downloader\\FilesystemException' => $vendorDir . '/composer/composer/src/Composer/Downloader/FilesystemException.php',
    'Composer\\Downloader\\FossilDownloader' => $vendorDir . '/composer/composer/src/Composer/Downloader/FossilDownloader.php',
    'Composer\\Downloader\\GitDownloader' => $vendorDir . '/composer/composer/src/Composer/Downloader/GitDownloader.php',
    'Composer\\Downloader\\GzipDownloader' => $vendorDir . '/composer/composer/src/Composer/Downloader/GzipDownloader.php',
    'Composer\\Downloader\\HgDownloader' => $vendorDir . '/composer/composer/src/Composer/Downloader/HgDownloader.php',
    'Composer\\Downloader\\MaxFileSizeExceededException' => $vendorDir . '/composer/composer/src/Composer/Downloader/MaxFileSizeExceededException.php',
    'Composer\\Downloader\\PathDownloader' => $vendorDir . '/composer/composer/src/Composer/Downloader/PathDownloader.php',
    'Composer\\Downloader\\PerforceDownloader' => $vendorDir . '/composer/composer/src/Composer/Downloader/PerforceDownloader.php',
    'Composer\\Downloader\\PharDownloader' => $vendorDir . '/composer/composer/src/Composer/Downloader/PharDownloader.php',
    'Composer\\Downloader\\RarDownloader' => $vendorDir . '/composer/composer/src/Composer/Downloader/RarDownloader.php',
    'Composer\\Downloader\\SvnDownloader' => $vendorDir . '/composer/composer/src/Composer/Downloader/SvnDownloader.php',
    'Composer\\Downloader\\TarDownloader' => $vendorDir . '/composer/composer/src/Composer/Downloader/TarDownloader.php',
    'Composer\\Downloader\\TransportException' => $vendorDir . '/composer/composer/src/Composer/Downloader/TransportException.php',
    'Composer\\Downloader\\VcsCapableDownloaderInterface' => $vendorDir . '/composer/composer/src/Composer/Downloader/VcsCapableDownloaderInterface.php',
    'Composer\\Downloader\\VcsDownloader' => $vendorDir . '/composer/composer/src/Composer/Downloader/VcsDownloader.php',
    'Composer\\Downloader\\XzDownloader' => $vendorDir . '/composer/composer/src/Composer/Downloader/XzDownloader.php',
    'Composer\\Downloader\\ZipDownloader' => $vendorDir . '/composer/composer/src/Composer/Downloader/ZipDownloader.php',
    'Composer\\EventDispatcher\\Event' => $vendorDir . '/composer/composer/src/Composer/EventDispatcher/Event.php',
    'Composer\\EventDispatcher\\EventDispatcher' => $vendorDir . '/composer/composer/src/Composer/EventDispatcher/EventDispatcher.php',
    'Composer\\EventDispatcher\\EventSubscriberInterface' => $vendorDir . '/composer/composer/src/Composer/EventDispatcher/EventSubscriberInterface.php',
    'Composer\\EventDispatcher\\ScriptExecutionException' => $vendorDir . '/composer/composer/src/Composer/EventDispatcher/ScriptExecutionException.php',
    'Composer\\Exception\\IrrecoverableDownloadException' => $vendorDir . '/composer/composer/src/Composer/Exception/IrrecoverableDownloadException.php',
    'Composer\\Exception\\NoSslException' => $vendorDir . '/composer/composer/src/Composer/Exception/NoSslException.php',
    'Composer\\Factory' => $vendorDir . '/composer/composer/src/Composer/Factory.php',
    'Composer\\Filter\\PlatformRequirementFilter\\IgnoreAllPlatformRequirementFilter' => $vendorDir . '/composer/composer/src/Composer/Filter/PlatformRequirementFilter/IgnoreAllPlatformRequirementFilter.php',
    'Composer\\Filter\\PlatformRequirementFilter\\IgnoreListPlatformRequirementFilter' => $vendorDir . '/composer/composer/src/Composer/Filter/PlatformRequirementFilter/IgnoreListPlatformRequirementFilter.php',
    'Composer\\Filter\\PlatformRequirementFilter\\IgnoreNothingPlatformRequirementFilter' => $vendorDir . '/composer/composer/src/Composer/Filter/PlatformRequirementFilter/IgnoreNothingPlatformRequirementFilter.php',
    'Composer\\Filter\\PlatformRequirementFilter\\PlatformRequirementFilterFactory' => $vendorDir . '/composer/composer/src/Composer/Filter/PlatformRequirementFilter/PlatformRequirementFilterFactory.php',
    'Composer\\Filter\\PlatformRequirementFilter\\PlatformRequirementFilterInterface' => $vendorDir . '/composer/composer/src/Composer/Filter/PlatformRequirementFilter/PlatformRequirementFilterInterface.php',
    'Composer\\IO\\BaseIO' => $vendorDir . '/composer/composer/src/Composer/IO/BaseIO.php',
    'Composer\\IO\\BufferIO' => $vendorDir . '/composer/composer/src/Composer/IO/BufferIO.php',
    'Composer\\IO\\ConsoleIO' => $vendorDir . '/composer/composer/src/Composer/IO/ConsoleIO.php',
    'Composer\\IO\\IOInterface' => $vendorDir . '/composer/composer/src/Composer/IO/IOInterface.php',
    'Composer\\IO\\NullIO' => $vendorDir . '/composer/composer/src/Composer/IO/NullIO.php',
    'Composer\\InstalledVersions' => $vendorDir . '/composer/InstalledVersions.php',
    'Composer\\Installer' => $vendorDir . '/composer/composer/src/Composer/Installer.php',
    'Composer\\Installer\\BinaryInstaller' => $vendorDir . '/composer/composer/src/Composer/Installer/BinaryInstaller.php',
    'Composer\\Installer\\BinaryPresenceInterface' => $vendorDir . '/composer/composer/src/Composer/Installer/BinaryPresenceInterface.php',
    'Composer\\Installer\\InstallationManager' => $vendorDir . '/composer/composer/src/Composer/Installer/InstallationManager.php',
    'Composer\\Installer\\InstallerEvent' => $vendorDir . '/composer/composer/src/Composer/Installer/InstallerEvent.php',
    'Composer\\Installer\\InstallerEvents' => $vendorDir . '/composer/composer/src/Composer/Installer/InstallerEvents.php',
    'Composer\\Installer\\InstallerInterface' => $vendorDir . '/composer/composer/src/Composer/Installer/InstallerInterface.php',
    'Composer\\Installer\\LibraryInstaller' => $vendorDir . '/composer/composer/src/Composer/Installer/LibraryInstaller.php',
    'Composer\\Installer\\MetapackageInstaller' => $vendorDir . '/composer/composer/src/Composer/Installer/MetapackageInstaller.php',
    'Composer\\Installer\\NoopInstaller' => $vendorDir . '/composer/composer/src/Composer/Installer/NoopInstaller.php',
    'Composer\\Installer\\PackageEvent' => $vendorDir . '/composer/composer/src/Composer/Installer/PackageEvent.php',
    'Composer\\Installer\\PackageEvents' => $vendorDir . '/composer/composer/src/Composer/Installer/PackageEvents.php',
    'Composer\\Installer\\PluginInstaller' => $vendorDir . '/composer/composer/src/Composer/Installer/PluginInstaller.php',
    'Composer\\Installer\\ProjectInstaller' => $vendorDir . '/composer/composer/src/Composer/Installer/ProjectInstaller.php',
    'Composer\\Installer\\SuggestedPackagesReporter' => $vendorDir . '/composer/composer/src/Composer/Installer/SuggestedPackagesReporter.php',
    'Composer\\Json\\JsonFile' => $vendorDir . '/composer/composer/src/Composer/Json/JsonFile.php',
    'Composer\\Json\\JsonFormatter' => $vendorDir . '/composer/composer/src/Composer/Json/JsonFormatter.php',
    'Composer\\Json\\JsonManipulator' => $vendorDir . '/composer/composer/src/Composer/Json/JsonManipulator.php',
    'Composer\\Json\\JsonValidationException' => $vendorDir . '/composer/composer/src/Composer/Json/JsonValidationException.php',
    'Composer\\MetadataMinifier\\MetadataMinifier' => $vendorDir . '/composer/metadata-minifier/src/MetadataMinifier.php',
    'Composer\\PHPStan\\ConfigReturnTypeExtension' => $vendorDir . '/composer/composer/src/Composer/PHPStan/ConfigReturnTypeExtension.php',
    'Composer\\PHPStan\\RuleReasonDataReturnTypeExtension' => $vendorDir . '/composer/composer/src/Composer/PHPStan/RuleReasonDataReturnTypeExtension.php',
    'Composer\\Package\\AliasPackage' => $vendorDir . '/composer/composer/src/Composer/Package/AliasPackage.php',
    'Composer\\Package\\Archiver\\ArchivableFilesFilter' => $vendorDir . '/composer/composer/src/Composer/Package/Archiver/ArchivableFilesFilter.php',
    'Composer\\Package\\Archiver\\ArchivableFilesFinder' => $vendorDir . '/composer/composer/src/Composer/Package/Archiver/ArchivableFilesFinder.php',
    'Composer\\Package\\Archiver\\ArchiveManager' => $vendorDir . '/composer/composer/src/Composer/Package/Archiver/ArchiveManager.php',
    'Composer\\Package\\Archiver\\ArchiverInterface' => $vendorDir . '/composer/composer/src/Composer/Package/Archiver/ArchiverInterface.php',
    'Composer\\Package\\Archiver\\BaseExcludeFilter' => $vendorDir . '/composer/composer/src/Composer/Package/Archiver/BaseExcludeFilter.php',
    'Composer\\Package\\Archiver\\ComposerExcludeFilter' => $vendorDir . '/composer/composer/src/Composer/Package/Archiver/ComposerExcludeFilter.php',
    'Composer\\Package\\Archiver\\GitExcludeFilter' => $vendorDir . '/composer/composer/src/Composer/Package/Archiver/GitExcludeFilter.php',
    'Composer\\Package\\Archiver\\PharArchiver' => $vendorDir . '/composer/composer/src/Composer/Package/Archiver/PharArchiver.php',
    'Composer\\Package\\Archiver\\ZipArchiver' => $vendorDir . '/composer/composer/src/Composer/Package/Archiver/ZipArchiver.php',
    'Composer\\Package\\BasePackage' => $vendorDir . '/composer/composer/src/Composer/Package/BasePackage.php',
    'Composer\\Package\\Comparer\\Comparer' => $vendorDir . '/composer/composer/src/Composer/Package/Comparer/Comparer.php',
    'Composer\\Package\\CompleteAliasPackage' => $vendorDir . '/composer/composer/src/Composer/Package/CompleteAliasPackage.php',
    'Composer\\Package\\CompletePackage' => $vendorDir . '/composer/composer/src/Composer/Package/CompletePackage.php',
    'Composer\\Package\\CompletePackageInterface' => $vendorDir . '/composer/composer/src/Composer/Package/CompletePackageInterface.php',
    'Composer\\Package\\Dumper\\ArrayDumper' => $vendorDir . '/composer/composer/src/Composer/Package/Dumper/ArrayDumper.php',
    'Composer\\Package\\Link' => $vendorDir . '/composer/composer/src/Composer/Package/Link.php',
    'Composer\\Package\\Loader\\ArrayLoader' => $vendorDir . '/composer/composer/src/Composer/Package/Loader/ArrayLoader.php',
    'Composer\\Package\\Loader\\InvalidPackageException' => $vendorDir . '/composer/composer/src/Composer/Package/Loader/InvalidPackageException.php',
    'Composer\\Package\\Loader\\JsonLoader' => $vendorDir . '/composer/composer/src/Composer/Package/Loader/JsonLoader.php',
    'Composer\\Package\\Loader\\LoaderInterface' => $vendorDir . '/composer/composer/src/Composer/Package/Loader/LoaderInterface.php',
    'Composer\\Package\\Loader\\RootPackageLoader' => $vendorDir . '/composer/composer/src/Composer/Package/Loader/RootPackageLoader.php',
    'Composer\\Package\\Loader\\ValidatingArrayLoader' => $vendorDir . '/composer/composer/src/Composer/Package/Loader/ValidatingArrayLoader.php',
    'Composer\\Package\\Locker' => $vendorDir . '/composer/composer/src/Composer/Package/Locker.php',
    'Composer\\Package\\Package' => $vendorDir . '/composer/composer/src/Composer/Package/Package.php',
    'Composer\\Package\\PackageInterface' => $vendorDir . '/composer/composer/src/Composer/Package/PackageInterface.php',
    'Composer\\Package\\RootAliasPackage' => $vendorDir . '/composer/composer/src/Composer/Package/RootAliasPackage.php',
    'Composer\\Package\\RootPackage' => $vendorDir . '/composer/composer/src/Composer/Package/RootPackage.php',
    'Composer\\Package\\RootPackageInterface' => $vendorDir . '/composer/composer/src/Composer/Package/RootPackageInterface.php',
    'Composer\\Package\\Version\\StabilityFilter' => $vendorDir . '/composer/composer/src/Composer/Package/Version/StabilityFilter.php',
    'Composer\\Package\\Version\\VersionBumper' => $vendorDir . '/composer/composer/src/Composer/Package/Version/VersionBumper.php',
    'Composer\\Package\\Version\\VersionGuesser' => $vendorDir . '/composer/composer/src/Composer/Package/Version/VersionGuesser.php',
    'Composer\\Package\\Version\\VersionParser' => $vendorDir . '/composer/composer/src/Composer/Package/Version/VersionParser.php',
    'Composer\\Package\\Version\\VersionSelector' => $vendorDir . '/composer/composer/src/Composer/Package/Version/VersionSelector.php',
    'Composer\\PartialComposer' => $vendorDir . '/composer/composer/src/Composer/PartialComposer.php',
    'Composer\\Pcre\\MatchAllResult' => $vendorDir . '/composer/pcre/src/MatchAllResult.php',
    'Composer\\Pcre\\MatchAllStrictGroupsResult' => $vendorDir . '/composer/pcre/src/MatchAllStrictGroupsResult.php',
    'Composer\\Pcre\\MatchAllWithOffsetsResult' => $vendorDir . '/composer/pcre/src/MatchAllWithOffsetsResult.php',
    'Composer\\Pcre\\MatchResult' => $vendorDir . '/composer/pcre/src/MatchResult.php',
    'Composer\\Pcre\\MatchStrictGroupsResult' => $vendorDir . '/composer/pcre/src/MatchStrictGroupsResult.php',
    'Composer\\Pcre\\MatchWithOffsetsResult' => $vendorDir . '/composer/pcre/src/MatchWithOffsetsResult.php',
    'Composer\\Pcre\\PHPStan\\InvalidRegexPatternRule' => $vendorDir . '/composer/pcre/src/PHPStan/InvalidRegexPatternRule.php',
    'Composer\\Pcre\\PHPStan\\PregMatchFlags' => $vendorDir . '/composer/pcre/src/PHPStan/PregMatchFlags.php',
    'Composer\\Pcre\\PHPStan\\PregMatchParameterOutTypeExtension' => $vendorDir . '/composer/pcre/src/PHPStan/PregMatchParameterOutTypeExtension.php',
    'Composer\\Pcre\\PHPStan\\PregMatchTypeSpecifyingExtension' => $vendorDir . '/composer/pcre/src/PHPStan/PregMatchTypeSpecifyingExtension.php',
    'Composer\\Pcre\\PHPStan\\PregReplaceCallbackClosureTypeExtension' => $vendorDir . '/composer/pcre/src/PHPStan/PregReplaceCallbackClosureTypeExtension.php',
    'Composer\\Pcre\\PHPStan\\UnsafeStrictGroupsCallRule' => $vendorDir . '/composer/pcre/src/PHPStan/UnsafeStrictGroupsCallRule.php',
    'Composer\\Pcre\\PcreException' => $vendorDir . '/composer/pcre/src/PcreException.php',
    'Composer\\Pcre\\Preg' => $vendorDir . '/composer/pcre/src/Preg.php',
    'Composer\\Pcre\\Regex' => $vendorDir . '/composer/pcre/src/Regex.php',
    'Composer\\Pcre\\ReplaceResult' => $vendorDir . '/composer/pcre/src/ReplaceResult.php',
    'Composer\\Pcre\\UnexpectedNullMatchException' => $vendorDir . '/composer/pcre/src/UnexpectedNullMatchException.php',
    'Composer\\Platform\\HhvmDetector' => $vendorDir . '/composer/composer/src/Composer/Platform/HhvmDetector.php',
    'Composer\\Platform\\Runtime' => $vendorDir . '/composer/composer/src/Composer/Platform/Runtime.php',
    'Composer\\Platform\\Version' => $vendorDir . '/composer/composer/src/Composer/Platform/Version.php',
    'Composer\\Plugin\\Capability\\Capability' => $vendorDir . '/composer/composer/src/Composer/Plugin/Capability/Capability.php',
    'Composer\\Plugin\\Capability\\CommandProvider' => $vendorDir . '/composer/composer/src/Composer/Plugin/Capability/CommandProvider.php',
    'Composer\\Plugin\\Capable' => $vendorDir . '/composer/composer/src/Composer/Plugin/Capable.php',
    'Composer\\Plugin\\CommandEvent' => $vendorDir . '/composer/composer/src/Composer/Plugin/CommandEvent.php',
    'Composer\\Plugin\\PluginBlockedException' => $vendorDir . '/composer/composer/src/Composer/Plugin/PluginBlockedException.php',
    'Composer\\Plugin\\PluginEvents' => $vendorDir . '/composer/composer/src/Composer/Plugin/PluginEvents.php',
    'Composer\\Plugin\\PluginInterface' => $vendorDir . '/composer/composer/src/Composer/Plugin/PluginInterface.php',
    'Composer\\Plugin\\PluginManager' => $vendorDir . '/composer/composer/src/Composer/Plugin/PluginManager.php',
    'Composer\\Plugin\\PostFileDownloadEvent' => $vendorDir . '/composer/composer/src/Composer/Plugin/PostFileDownloadEvent.php',
    'Composer\\Plugin\\PreCommandRunEvent' => $vendorDir . '/composer/composer/src/Composer/Plugin/PreCommandRunEvent.php',
    'Composer\\Plugin\\PreFileDownloadEvent' => $vendorDir . '/composer/composer/src/Composer/Plugin/PreFileDownloadEvent.php',
    'Composer\\Plugin\\PrePoolCreateEvent' => $vendorDir . '/composer/composer/src/Composer/Plugin/PrePoolCreateEvent.php',
    'Composer\\Question\\StrictConfirmationQuestion' => $vendorDir . '/composer/composer/src/Composer/Question/StrictConfirmationQuestion.php',
    'Composer\\Repository\\AdvisoryProviderInterface' => $vendorDir . '/composer/composer/src/Composer/Repository/AdvisoryProviderInterface.php',
    'Composer\\Repository\\ArrayRepository' => $vendorDir . '/composer/composer/src/Composer/Repository/ArrayRepository.php',
    'Composer\\Repository\\ArtifactRepository' => $vendorDir . '/composer/composer/src/Composer/Repository/ArtifactRepository.php',
    'Composer\\Repository\\CanonicalPackagesTrait' => $vendorDir . '/composer/composer/src/Composer/Repository/CanonicalPackagesTrait.php',
    'Composer\\Repository\\ComposerRepository' => $vendorDir . '/composer/composer/src/Composer/Repository/ComposerRepository.php',
    'Composer\\Repository\\CompositeRepository' => $vendorDir . '/composer/composer/src/Composer/Repository/CompositeRepository.php',
    'Composer\\Repository\\ConfigurableRepositoryInterface' => $vendorDir . '/composer/composer/src/Composer/Repository/ConfigurableRepositoryInterface.php',
    'Composer\\Repository\\FilesystemRepository' => $vendorDir . '/composer/composer/src/Composer/Repository/FilesystemRepository.php',
    'Composer\\Repository\\FilterRepository' => $vendorDir . '/composer/composer/src/Composer/Repository/FilterRepository.php',
    'Composer\\Repository\\InstalledArrayRepository' => $vendorDir . '/composer/composer/src/Composer/Repository/InstalledArrayRepository.php',
    'Composer\\Repository\\InstalledFilesystemRepository' => $vendorDir . '/composer/composer/src/Composer/Repository/InstalledFilesystemRepository.php',
    'Composer\\Repository\\InstalledRepository' => $vendorDir . '/composer/composer/src/Composer/Repository/InstalledRepository.php',
    'Composer\\Repository\\InstalledRepositoryInterface' => $vendorDir . '/composer/composer/src/Composer/Repository/InstalledRepositoryInterface.php',
    'Composer\\Repository\\InvalidRepositoryException' => $vendorDir . '/composer/composer/src/Composer/Repository/InvalidRepositoryException.php',
    'Composer\\Repository\\LockArrayRepository' => $vendorDir . '/composer/composer/src/Composer/Repository/LockArrayRepository.php',
    'Composer\\Repository\\PackageRepository' => $vendorDir . '/composer/composer/src/Composer/Repository/PackageRepository.php',
    'Composer\\Repository\\PathRepository' => $vendorDir . '/composer/composer/src/Composer/Repository/PathRepository.php',
    'Composer\\Repository\\PearRepository' => $vendorDir . '/composer/composer/src/Composer/Repository/PearRepository.php',
    'Composer\\Repository\\PlatformRepository' => $vendorDir . '/composer/composer/src/Composer/Repository/PlatformRepository.php',
    'Composer\\Repository\\RepositoryFactory' => $vendorDir . '/composer/composer/src/Composer/Repository/RepositoryFactory.php',
    'Composer\\Repository\\RepositoryInterface' => $vendorDir . '/composer/composer/src/Composer/Repository/RepositoryInterface.php',
    'Composer\\Repository\\RepositoryManager' => $vendorDir . '/composer/composer/src/Composer/Repository/RepositoryManager.php',
    'Composer\\Repository\\RepositorySecurityException' => $vendorDir . '/composer/composer/src/Composer/Repository/RepositorySecurityException.php',
    'Composer\\Repository\\RepositorySet' => $vendorDir . '/composer/composer/src/Composer/Repository/RepositorySet.php',
    'Composer\\Repository\\RepositoryUtils' => $vendorDir . '/composer/composer/src/Composer/Repository/RepositoryUtils.php',
    'Composer\\Repository\\RootPackageRepository' => $vendorDir . '/composer/composer/src/Composer/Repository/RootPackageRepository.php',
    'Composer\\Repository\\VcsRepository' => $vendorDir . '/composer/composer/src/Composer/Repository/VcsRepository.php',
    'Composer\\Repository\\Vcs\\ForgejoDriver' => $vendorDir . '/composer/composer/src/Composer/Repository/Vcs/ForgejoDriver.php',
    'Composer\\Repository\\Vcs\\FossilDriver' => $vendorDir . '/composer/composer/src/Composer/Repository/Vcs/FossilDriver.php',
    'Composer\\Repository\\Vcs\\GitBitbucketDriver' => $vendorDir . '/composer/composer/src/Composer/Repository/Vcs/GitBitbucketDriver.php',
    'Composer\\Repository\\Vcs\\GitDriver' => $vendorDir . '/composer/composer/src/Composer/Repository/Vcs/GitDriver.php',
    'Composer\\Repository\\Vcs\\GitHubDriver' => $vendorDir . '/composer/composer/src/Composer/Repository/Vcs/GitHubDriver.php',
    'Composer\\Repository\\Vcs\\GitLabDriver' => $vendorDir . '/composer/composer/src/Composer/Repository/Vcs/GitLabDriver.php',
    'Composer\\Repository\\Vcs\\HgDriver' => $vendorDir . '/composer/composer/src/Composer/Repository/Vcs/HgDriver.php',
    'Composer\\Repository\\Vcs\\PerforceDriver' => $vendorDir . '/composer/composer/src/Composer/Repository/Vcs/PerforceDriver.php',
    'Composer\\Repository\\Vcs\\SvnDriver' => $vendorDir . '/composer/composer/src/Composer/Repository/Vcs/SvnDriver.php',
    'Composer\\Repository\\Vcs\\VcsDriver' => $vendorDir . '/composer/composer/src/Composer/Repository/Vcs/VcsDriver.php',
    'Composer\\Repository\\Vcs\\VcsDriverInterface' => $vendorDir . '/composer/composer/src/Composer/Repository/Vcs/VcsDriverInterface.php',
    'Composer\\Repository\\VersionCacheInterface' => $vendorDir . '/composer/composer/src/Composer/Repository/VersionCacheInterface.php',
    'Composer\\Repository\\WritableArrayRepository' => $vendorDir . '/composer/composer/src/Composer/Repository/WritableArrayRepository.php',
    'Composer\\Repository\\WritableRepositoryInterface' => $vendorDir . '/composer/composer/src/Composer/Repository/WritableRepositoryInterface.php',
    'Composer\\Script\\Event' => $vendorDir . '/composer/composer/src/Composer/Script/Event.php',
    'Composer\\Script\\ScriptEvents' => $vendorDir . '/composer/composer/src/Composer/Script/ScriptEvents.php',
    'Composer\\SelfUpdate\\Keys' => $vendorDir . '/composer/composer/src/Composer/SelfUpdate/Keys.php',
    'Composer\\SelfUpdate\\Versions' => $vendorDir . '/composer/composer/src/Composer/SelfUpdate/Versions.php',
    'Composer\\Semver\\Comparator' => $vendorDir . '/composer/semver/src/Comparator.php',
    'Composer\\Semver\\CompilingMatcher' => $vendorDir . '/composer/semver/src/CompilingMatcher.php',
    'Composer\\Semver\\Constraint\\Bound' => $vendorDir . '/composer/semver/src/Constraint/Bound.php',
    'Composer\\Semver\\Constraint\\Constraint' => $vendorDir . '/composer/semver/src/Constraint/Constraint.php',
    'Composer\\Semver\\Constraint\\ConstraintInterface' => $vendorDir . '/composer/semver/src/Constraint/ConstraintInterface.php',
    'Composer\\Semver\\Constraint\\MatchAllConstraint' => $vendorDir . '/composer/semver/src/Constraint/MatchAllConstraint.php',
    'Composer\\Semver\\Constraint\\MatchNoneConstraint' => $vendorDir . '/composer/semver/src/Constraint/MatchNoneConstraint.php',
    'Composer\\Semver\\Constraint\\MultiConstraint' => $vendorDir . '/composer/semver/src/Constraint/MultiConstraint.php',
    'Composer\\Semver\\Interval' => $vendorDir . '/composer/semver/src/Interval.php',
    'Composer\\Semver\\Intervals' => $vendorDir . '/composer/semver/src/Intervals.php',
    'Composer\\Semver\\Semver' => $vendorDir . '/composer/semver/src/Semver.php',
    'Composer\\Semver\\VersionParser' => $vendorDir . '/composer/semver/src/VersionParser.php',
    'Composer\\Spdx\\SpdxLicenses' => $vendorDir . '/composer/spdx-licenses/src/SpdxLicenses.php',
    'Composer\\Util\\AuthHelper' => $vendorDir . '/composer/composer/src/Composer/Util/AuthHelper.php',
    'Composer\\Util\\Bitbucket' => $vendorDir . '/composer/composer/src/Composer/Util/Bitbucket.php',
    'Composer\\Util\\ComposerMirror' => $vendorDir . '/composer/composer/src/Composer/Util/ComposerMirror.php',
    'Composer\\Util\\ConfigValidator' => $vendorDir . '/composer/composer/src/Composer/Util/ConfigValidator.php',
    'Composer\\Util\\ErrorHandler' => $vendorDir . '/composer/composer/src/Composer/Util/ErrorHandler.php',
    'Composer\\Util\\Filesystem' => $vendorDir . '/composer/composer/src/Composer/Util/Filesystem.php',
    'Composer\\Util\\Forgejo' => $vendorDir . '/composer/composer/src/Composer/Util/Forgejo.php',
    'Composer\\Util\\ForgejoRepositoryData' => $vendorDir . '/composer/composer/src/Composer/Util/ForgejoRepositoryData.php',
    'Composer\\Util\\ForgejoUrl' => $vendorDir . '/composer/composer/src/Composer/Util/ForgejoUrl.php',
    'Composer\\Util\\Git' => $vendorDir . '/composer/composer/src/Composer/Util/Git.php',
    'Composer\\Util\\GitHub' => $vendorDir . '/composer/composer/src/Composer/Util/GitHub.php',
    'Composer\\Util\\GitLab' => $vendorDir . '/composer/composer/src/Composer/Util/GitLab.php',
    'Composer\\Util\\Hg' => $vendorDir . '/composer/composer/src/Composer/Util/Hg.php',
    'Composer\\Util\\HttpDownloader' => $vendorDir . '/composer/composer/src/Composer/Util/HttpDownloader.php',
    'Composer\\Util\\Http\\CurlDownloader' => $vendorDir . '/composer/composer/src/Composer/Util/Http/CurlDownloader.php',
    'Composer\\Util\\Http\\CurlResponse' => $vendorDir . '/composer/composer/src/Composer/Util/Http/CurlResponse.php',
    'Composer\\Util\\Http\\ProxyItem' => $vendorDir . '/composer/composer/src/Composer/Util/Http/ProxyItem.php',
    'Composer\\Util\\Http\\ProxyManager' => $vendorDir . '/composer/composer/src/Composer/Util/Http/ProxyManager.php',
    'Composer\\Util\\Http\\RequestProxy' => $vendorDir . '/composer/composer/src/Composer/Util/Http/RequestProxy.php',
    'Composer\\Util\\Http\\Response' => $vendorDir . '/composer/composer/src/Composer/Util/Http/Response.php',
    'Composer\\Util\\IniHelper' => $vendorDir . '/composer/composer/src/Composer/Util/IniHelper.php',
    'Composer\\Util\\Loop' => $vendorDir . '/composer/composer/src/Composer/Util/Loop.php',
    'Composer\\Util\\MetadataMinifier' => $vendorDir . '/composer/composer/src/Composer/Util/MetadataMinifier.php',
    'Composer\\Util\\NoProxyPattern' => $vendorDir . '/composer/composer/src/Composer/Util/NoProxyPattern.php',
    'Composer\\Util\\PackageInfo' => $vendorDir . '/composer/composer/src/Composer/Util/PackageInfo.php',
    'Composer\\Util\\PackageSorter' => $vendorDir . '/composer/composer/src/Composer/Util/PackageSorter.php',
    'Composer\\Util\\Perforce' => $vendorDir . '/composer/composer/src/Composer/Util/Perforce.php',
    'Composer\\Util\\Platform' => $vendorDir . '/composer/composer/src/Composer/Util/Platform.php',
    'Composer\\Util\\ProcessExecutor' => $vendorDir . '/composer/composer/src/Composer/Util/ProcessExecutor.php',
    'Composer\\Util\\RemoteFilesystem' => $vendorDir . '/composer/composer/src/Composer/Util/RemoteFilesystem.php',
    'Composer\\Util\\Silencer' => $vendorDir . '/composer/composer/src/Composer/Util/Silencer.php',
    'Composer\\Util\\StreamContextFactory' => $vendorDir . '/composer/composer/src/Composer/Util/StreamContextFactory.php',
    'Composer\\Util\\Svn' => $vendorDir . '/composer/composer/src/Composer/Util/Svn.php',
    'Composer\\Util\\SyncHelper' => $vendorDir . '/composer/composer/src/Composer/Util/SyncHelper.php',
    'Composer\\Util\\Tar' => $vendorDir . '/composer/composer/src/Composer/Util/Tar.php',
    'Composer\\Util\\TlsHelper' => $vendorDir . '/composer/composer/src/Composer/Util/TlsHelper.php',
    'Composer\\Util\\Url' => $vendorDir . '/composer/composer/src/Composer/Util/Url.php',
    'Composer\\Util\\Zip' => $vendorDir . '/composer/composer/src/Composer/Util/Zip.php',
    'Composer\\XdebugHandler\\PhpConfig' => $vendorDir . '/composer/xdebug-handler/src/PhpConfig.php',
    'Composer\\XdebugHandler\\Process' => $vendorDir . '/composer/xdebug-handler/src/Process.php',
    'Composer\\XdebugHandler\\Status' => $vendorDir . '/composer/xdebug-handler/src/Status.php',
    'Composer\\XdebugHandler\\XdebugHandler' => $vendorDir . '/composer/xdebug-handler/src/XdebugHandler.php',
    'DateError' => $vendorDir . '/symfony/polyfill-php83/Resources/stubs/DateError.php',
    'DateException' => $vendorDir . '/symfony/polyfill-php83/Resources/stubs/DateException.php',
    'DateInvalidOperationException' => $vendorDir . '/symfony/polyfill-php83/Resources/stubs/DateInvalidOperationException.php',
    'DateInvalidTimeZoneException' => $vendorDir . '/symfony/polyfill-php83/Resources/stubs/DateInvalidTimeZoneException.php',
    'DateMalformedIntervalStringException' => $vendorDir . '/symfony/polyfill-php83/Resources/stubs/DateMalformedIntervalStringException.php',
    'DateMalformedPeriodStringException' => $vendorDir . '/symfony/polyfill-php83/Resources/stubs/DateMalformedPeriodStringException.php',
    'DateMalformedStringException' => $vendorDir . '/symfony/polyfill-php83/Resources/stubs/DateMalformedStringException.php',
    'DateObjectError' => $vendorDir . '/symfony/polyfill-php83/Resources/stubs/DateObjectError.php',
    'DateRangeError' => $vendorDir . '/symfony/polyfill-php83/Resources/stubs/DateRangeError.php',
    'Deprecated' => $vendorDir . '/symfony/polyfill-php84/Resources/stubs/Deprecated.php',
    'JsonException' => $vendorDir . '/symfony/polyfill-php73/Resources/stubs/JsonException.php',
    'Normalizer' => $vendorDir . '/symfony/polyfill-intl-normalizer/Resources/stubs/Normalizer.php',
    'Override' => $vendorDir . '/symfony/polyfill-php83/Resources/stubs/Override.php',
    'Pdo\\Dblib' => $vendorDir . '/symfony/polyfill-php84/Resources/stubs/Pdo/Dblib.php',
    'Pdo\\Firebird' => $vendorDir . '/symfony/polyfill-php84/Resources/stubs/Pdo/Firebird.php',
    'Pdo\\Mysql' => $vendorDir . '/symfony/polyfill-php84/Resources/stubs/Pdo/Mysql.php',
    'Pdo\\Odbc' => $vendorDir . '/symfony/polyfill-php84/Resources/stubs/Pdo/Odbc.php',
    'Pdo\\Pgsql' => $vendorDir . '/symfony/polyfill-php84/Resources/stubs/Pdo/Pgsql.php',
    'Pdo\\Sqlite' => $vendorDir . '/symfony/polyfill-php84/Resources/stubs/Pdo/Sqlite.php',
    'PhpToken' => $vendorDir . '/symfony/polyfill-php80/Resources/stubs/PhpToken.php',
    'React\\Promise\\Deferred' => $vendorDir . '/react/promise/src/Deferred.php',
    'React\\Promise\\Exception\\CompositeException' => $vendorDir . '/react/promise/src/Exception/CompositeException.php',
    'React\\Promise\\Exception\\LengthException' => $vendorDir . '/react/promise/src/Exception/LengthException.php',
    'React\\Promise\\Internal\\CancellationQueue' => $vendorDir . '/react/promise/src/Internal/CancellationQueue.php',
    'React\\Promise\\Internal\\FulfilledPromise' => $vendorDir . '/react/promise/src/Internal/FulfilledPromise.php',
    'React\\Promise\\Internal\\RejectedPromise' => $vendorDir . '/react/promise/src/Internal/RejectedPromise.php',
    'React\\Promise\\Promise' => $vendorDir . '/react/promise/src/Promise.php',
    'React\\Promise\\PromiseInterface' => $vendorDir . '/react/promise/src/PromiseInterface.php',
    'ReflectionConstant' => $vendorDir . '/symfony/polyfill-php84/Resources/stubs/ReflectionConstant.php',
    'ReturnTypeWillChange' => $vendorDir . '/symfony/polyfill-php81/Resources/stubs/ReturnTypeWillChange.php',
    'RoundingMode' => $vendorDir . '/symfony/polyfill-php84/Resources/stubs/RoundingMode.php',
    'SQLite3Exception' => $vendorDir . '/symfony/polyfill-php83/Resources/stubs/SQLite3Exception.php',
    'Stringable' => $vendorDir . '/symfony/polyfill-php80/Resources/stubs/Stringable.php',
    'Symfony\\Polyfill\\Ctype\\Ctype' => $vendorDir . '/symfony/polyfill-ctype/Ctype.php',
    'Symfony\\Polyfill\\Intl\\Grapheme\\Grapheme' => $vendorDir . '/symfony/polyfill-intl-grapheme/Grapheme.php',
    'Symfony\\Polyfill\\Intl\\Normalizer\\Normalizer' => $vendorDir . '/symfony/polyfill-intl-normalizer/Normalizer.php',
    'Symfony\\Polyfill\\Mbstring\\Mbstring' => $vendorDir . '/symfony/polyfill-mbstring/Mbstring.php',
    'Symfony\\Polyfill\\Php73\\Php73' => $vendorDir . '/symfony/polyfill-php73/Php73.php',
    'Symfony\\Polyfill\\Php80\\Php80' => $vendorDir . '/symfony/polyfill-php80/Php80.php',
    'Symfony\\Polyfill\\Php80\\PhpToken' => $vendorDir . '/symfony/polyfill-php80/PhpToken.php',
    'Symfony\\Polyfill\\Php81\\Php81' => $vendorDir . '/symfony/polyfill-php81/Php81.php',
    'Symfony\\Polyfill\\Php83\\Php83' => $vendorDir . '/symfony/polyfill-php83/Php83.php',
    'Symfony\\Polyfill\\Php84\\Php84' => $vendorDir . '/symfony/polyfill-php84/Php84.php',
    'Symfony\\Polyfill\\Uuid\\Uuid' => $vendorDir . '/symfony/polyfill-uuid/Uuid.php',
    'UnhandledMatchError' => $vendorDir . '/symfony/polyfill-php80/Resources/stubs/UnhandledMatchError.php',
    'ValueError' => $vendorDir . '/symfony/polyfill-php80/Resources/stubs/ValueError.php',
    '_ContaoManager\\Brick\\Math\\BigDecimal' => $vendorDir . '/brick/math/src/BigDecimal.php',
    '_ContaoManager\\Brick\\Math\\BigInteger' => $vendorDir . '/brick/math/src/BigInteger.php',
    '_ContaoManager\\Brick\\Math\\BigNumber' => $vendorDir . '/brick/math/src/BigNumber.php',
    '_ContaoManager\\Brick\\Math\\BigRational' => $vendorDir . '/brick/math/src/BigRational.php',
    '_ContaoManager\\Brick\\Math\\Exception\\DivisionByZeroException' => $vendorDir . '/brick/math/src/Exception/DivisionByZeroException.php',
    '_ContaoManager\\Brick\\Math\\Exception\\IntegerOverflowException' => $vendorDir . '/brick/math/src/Exception/IntegerOverflowException.php',
    '_ContaoManager\\Brick\\Math\\Exception\\MathException' => $vendorDir . '/brick/math/src/Exception/MathException.php',
    '_ContaoManager\\Brick\\Math\\Exception\\NegativeNumberException' => $vendorDir . '/brick/math/src/Exception/NegativeNumberException.php',
    '_ContaoManager\\Brick\\Math\\Exception\\NumberFormatException' => $vendorDir . '/brick/math/src/Exception/NumberFormatException.php',
    '_ContaoManager\\Brick\\Math\\Exception\\RoundingNecessaryException' => $vendorDir . '/brick/math/src/Exception/RoundingNecessaryException.php',
    '_ContaoManager\\Brick\\Math\\Internal\\Calculator' => $vendorDir . '/brick/math/src/Internal/Calculator.php',
    '_ContaoManager\\Brick\\Math\\Internal\\Calculator\\BcMathCalculator' => $vendorDir . '/brick/math/src/Internal/Calculator/BcMathCalculator.php',
    '_ContaoManager\\Brick\\Math\\Internal\\Calculator\\GmpCalculator' => $vendorDir . '/brick/math/src/Internal/Calculator/GmpCalculator.php',
    '_ContaoManager\\Brick\\Math\\Internal\\Calculator\\NativeCalculator' => $vendorDir . '/brick/math/src/Internal/Calculator/NativeCalculator.php',
    '_ContaoManager\\Brick\\Math\\RoundingMode' => $vendorDir . '/brick/math/src/RoundingMode.php',
    '_ContaoManager\\CBOR\\AbstractCBORObject' => $vendorDir . '/spomky-labs/cbor-php/src/AbstractCBORObject.php',
    '_ContaoManager\\CBOR\\ByteStringObject' => $vendorDir . '/spomky-labs/cbor-php/src/ByteStringObject.php',
    '_ContaoManager\\CBOR\\CBORObject' => $vendorDir . '/spomky-labs/cbor-php/src/CBORObject.php',
    '_ContaoManager\\CBOR\\Decoder' => $vendorDir . '/spomky-labs/cbor-php/src/Decoder.php',
    '_ContaoManager\\CBOR\\DecoderInterface' => $vendorDir . '/spomky-labs/cbor-php/src/DecoderInterface.php',
    '_ContaoManager\\CBOR\\Encoder' => $vendorDir . '/spomky-labs/cbor-php/src/Encoder.php',
    '_ContaoManager\\CBOR\\EncoderInterface' => $vendorDir . '/spomky-labs/cbor-php/src/EncoderInterface.php',
    '_ContaoManager\\CBOR\\IndefiniteLengthByteStringObject' => $vendorDir . '/spomky-labs/cbor-php/src/IndefiniteLengthByteStringObject.php',
    '_ContaoManager\\CBOR\\IndefiniteLengthListObject' => $vendorDir . '/spomky-labs/cbor-php/src/IndefiniteLengthListObject.php',
    '_ContaoManager\\CBOR\\IndefiniteLengthMapObject' => $vendorDir . '/spomky-labs/cbor-php/src/IndefiniteLengthMapObject.php',
    '_ContaoManager\\CBOR\\IndefiniteLengthTextStringObject' => $vendorDir . '/spomky-labs/cbor-php/src/IndefiniteLengthTextStringObject.php',
    '_ContaoManager\\CBOR\\LengthCalculator' => $vendorDir . '/spomky-labs/cbor-php/src/LengthCalculator.php',
    '_ContaoManager\\CBOR\\ListObject' => $vendorDir . '/spomky-labs/cbor-php/src/ListObject.php',
    '_ContaoManager\\CBOR\\MapItem' => $vendorDir . '/spomky-labs/cbor-php/src/MapItem.php',
    '_ContaoManager\\CBOR\\MapObject' => $vendorDir . '/spomky-labs/cbor-php/src/MapObject.php',
    '_ContaoManager\\CBOR\\NegativeIntegerObject' => $vendorDir . '/spomky-labs/cbor-php/src/NegativeIntegerObject.php',
    '_ContaoManager\\CBOR\\Normalizable' => $vendorDir . '/spomky-labs/cbor-php/src/Normalizable.php',
    '_ContaoManager\\CBOR\\OtherObject' => $vendorDir . '/spomky-labs/cbor-php/src/OtherObject.php',
    '_ContaoManager\\CBOR\\OtherObject\\BreakObject' => $vendorDir . '/spomky-labs/cbor-php/src/OtherObject/BreakObject.php',
    '_ContaoManager\\CBOR\\OtherObject\\DoublePrecisionFloatObject' => $vendorDir . '/spomky-labs/cbor-php/src/OtherObject/DoublePrecisionFloatObject.php',
    '_ContaoManager\\CBOR\\OtherObject\\FalseObject' => $vendorDir . '/spomky-labs/cbor-php/src/OtherObject/FalseObject.php',
    '_ContaoManager\\CBOR\\OtherObject\\GenericObject' => $vendorDir . '/spomky-labs/cbor-php/src/OtherObject/GenericObject.php',
    '_ContaoManager\\CBOR\\OtherObject\\HalfPrecisionFloatObject' => $vendorDir . '/spomky-labs/cbor-php/src/OtherObject/HalfPrecisionFloatObject.php',
    '_ContaoManager\\CBOR\\OtherObject\\NullObject' => $vendorDir . '/spomky-labs/cbor-php/src/OtherObject/NullObject.php',
    '_ContaoManager\\CBOR\\OtherObject\\OtherObjectInterface' => $vendorDir . '/spomky-labs/cbor-php/src/OtherObject/OtherObjectInterface.php',
    '_ContaoManager\\CBOR\\OtherObject\\OtherObjectManager' => $vendorDir . '/spomky-labs/cbor-php/src/OtherObject/OtherObjectManager.php',
    '_ContaoManager\\CBOR\\OtherObject\\OtherObjectManagerInterface' => $vendorDir . '/spomky-labs/cbor-php/src/OtherObject/OtherObjectManagerInterface.php',
    '_ContaoManager\\CBOR\\OtherObject\\SimpleObject' => $vendorDir . '/spomky-labs/cbor-php/src/OtherObject/SimpleObject.php',
    '_ContaoManager\\CBOR\\OtherObject\\SinglePrecisionFloatObject' => $vendorDir . '/spomky-labs/cbor-php/src/OtherObject/SinglePrecisionFloatObject.php',
    '_ContaoManager\\CBOR\\OtherObject\\TrueObject' => $vendorDir . '/spomky-labs/cbor-php/src/OtherObject/TrueObject.php',
    '_ContaoManager\\CBOR\\OtherObject\\UndefinedObject' => $vendorDir . '/spomky-labs/cbor-php/src/OtherObject/UndefinedObject.php',
    '_ContaoManager\\CBOR\\Stream' => $vendorDir . '/spomky-labs/cbor-php/src/Stream.php',
    '_ContaoManager\\CBOR\\StringStream' => $vendorDir . '/spomky-labs/cbor-php/src/StringStream.php',
    '_ContaoManager\\CBOR\\Tag' => $vendorDir . '/spomky-labs/cbor-php/src/Tag.php',
    '_ContaoManager\\CBOR\\Tag\\Base16EncodingTag' => $vendorDir . '/spomky-labs/cbor-php/src/Tag/Base16EncodingTag.php',
    '_ContaoManager\\CBOR\\Tag\\Base64EncodingTag' => $vendorDir . '/spomky-labs/cbor-php/src/Tag/Base64EncodingTag.php',
    '_ContaoManager\\CBOR\\Tag\\Base64Tag' => $vendorDir . '/spomky-labs/cbor-php/src/Tag/Base64Tag.php',
    '_ContaoManager\\CBOR\\Tag\\Base64UrlEncodingTag' => $vendorDir . '/spomky-labs/cbor-php/src/Tag/Base64UrlEncodingTag.php',
    '_ContaoManager\\CBOR\\Tag\\Base64UrlTag' => $vendorDir . '/spomky-labs/cbor-php/src/Tag/Base64UrlTag.php',
    '_ContaoManager\\CBOR\\Tag\\BigFloatTag' => $vendorDir . '/spomky-labs/cbor-php/src/Tag/BigFloatTag.php',
    '_ContaoManager\\CBOR\\Tag\\CBOREncodingTag' => $vendorDir . '/spomky-labs/cbor-php/src/Tag/CBOREncodingTag.php',
    '_ContaoManager\\CBOR\\Tag\\CBORTag' => $vendorDir . '/spomky-labs/cbor-php/src/Tag/CBORTag.php',
    '_ContaoManager\\CBOR\\Tag\\DatetimeTag' => $vendorDir . '/spomky-labs/cbor-php/src/Tag/DatetimeTag.php',
    '_ContaoManager\\CBOR\\Tag\\DecimalFractionTag' => $vendorDir . '/spomky-labs/cbor-php/src/Tag/DecimalFractionTag.php',
    '_ContaoManager\\CBOR\\Tag\\GenericTag' => $vendorDir . '/spomky-labs/cbor-php/src/Tag/GenericTag.php',
    '_ContaoManager\\CBOR\\Tag\\MimeTag' => $vendorDir . '/spomky-labs/cbor-php/src/Tag/MimeTag.php',
    '_ContaoManager\\CBOR\\Tag\\NegativeBigIntegerTag' => $vendorDir . '/spomky-labs/cbor-php/src/Tag/NegativeBigIntegerTag.php',
    '_ContaoManager\\CBOR\\Tag\\TagInterface' => $vendorDir . '/spomky-labs/cbor-php/src/Tag/TagInterface.php',
    '_ContaoManager\\CBOR\\Tag\\TagManager' => $vendorDir . '/spomky-labs/cbor-php/src/Tag/TagManager.php',
    '_ContaoManager\\CBOR\\Tag\\TagManagerInterface' => $vendorDir . '/spomky-labs/cbor-php/src/Tag/TagManagerInterface.php',
    '_ContaoManager\\CBOR\\Tag\\TimestampTag' => $vendorDir . '/spomky-labs/cbor-php/src/Tag/TimestampTag.php',
    '_ContaoManager\\CBOR\\Tag\\UnsignedBigIntegerTag' => $vendorDir . '/spomky-labs/cbor-php/src/Tag/UnsignedBigIntegerTag.php',
    '_ContaoManager\\CBOR\\Tag\\UriTag' => $vendorDir . '/spomky-labs/cbor-php/src/Tag/UriTag.php',
    '_ContaoManager\\CBOR\\TextStringObject' => $vendorDir . '/spomky-labs/cbor-php/src/TextStringObject.php',
    '_ContaoManager\\CBOR\\UnsignedIntegerObject' => $vendorDir . '/spomky-labs/cbor-php/src/UnsignedIntegerObject.php',
    '_ContaoManager\\CBOR\\Utils' => $vendorDir . '/spomky-labs/cbor-php/src/Utils.php',
    '_ContaoManager\\Contao\\ManagerApi\\ApiApplication' => $baseDir . '/api/ApiApplication.php',
    '_ContaoManager\\Contao\\ManagerApi\\ApiKernel' => $baseDir . '/api/ApiKernel.php',
    '_ContaoManager\\Contao\\ManagerApi\\Command\\AboutCommand' => $baseDir . '/api/Command/AboutCommand.php',
    '_ContaoManager\\Contao\\ManagerApi\\Command\\IntegrityCheckCommand' => $baseDir . '/api/Command/IntegrityCheckCommand.php',
    '_ContaoManager\\Contao\\ManagerApi\\Command\\ProcessRunnerCommand' => $baseDir . '/api/Command/ProcessRunnerCommand.php',
    '_ContaoManager\\Contao\\ManagerApi\\Command\\TaskAbortCommand' => $baseDir . '/api/Command/TaskAbortCommand.php',
    '_ContaoManager\\Contao\\ManagerApi\\Command\\TaskDeleteCommand' => $baseDir . '/api/Command/TaskDeleteCommand.php',
    '_ContaoManager\\Contao\\ManagerApi\\Command\\TaskUpdateCommand' => $baseDir . '/api/Command/TaskUpdateCommand.php',
    '_ContaoManager\\Contao\\ManagerApi\\Command\\UpdateCommand' => $baseDir . '/api/Command/UpdateCommand.php',
    '_ContaoManager\\Contao\\ManagerApi\\Composer\\CloudChanges' => $baseDir . '/api/Composer/CloudChanges.php',
    '_ContaoManager\\Contao\\ManagerApi\\Composer\\CloudException' => $baseDir . '/api/Composer/CloudException.php',
    '_ContaoManager\\Contao\\ManagerApi\\Composer\\CloudJob' => $baseDir . '/api/Composer/CloudJob.php',
    '_ContaoManager\\Contao\\ManagerApi\\Composer\\CloudResolver' => $baseDir . '/api/Composer/CloudResolver.php',
    '_ContaoManager\\Contao\\ManagerApi\\Composer\\Environment' => $baseDir . '/api/Composer/Environment.php',
    '_ContaoManager\\Contao\\ManagerApi\\Config\\AbstractConfig' => $baseDir . '/api/Config/AbstractConfig.php',
    '_ContaoManager\\Contao\\ManagerApi\\Config\\AuthConfig' => $baseDir . '/api/Config/AuthConfig.php',
    '_ContaoManager\\Contao\\ManagerApi\\Config\\ComposerConfig' => $baseDir . '/api/Config/ComposerConfig.php',
    '_ContaoManager\\Contao\\ManagerApi\\Config\\ManagerConfig' => $baseDir . '/api/Config/ManagerConfig.php',
    '_ContaoManager\\Contao\\ManagerApi\\Config\\PartialConfig' => $baseDir . '/api/Config/PartialConfig.php',
    '_ContaoManager\\Contao\\ManagerApi\\Config\\UploadsConfig' => $baseDir . '/api/Config/UploadsConfig.php',
    '_ContaoManager\\Contao\\ManagerApi\\Config\\UserConfig' => $baseDir . '/api/Config/UserConfig.php',
    '_ContaoManager\\Contao\\ManagerApi\\Controller\\Config\\AbstractConfigController' => $baseDir . '/api/Controller/Config/AbstractConfigController.php',
    '_ContaoManager\\Contao\\ManagerApi\\Controller\\Config\\AuthController' => $baseDir . '/api/Controller/Config/AuthController.php',
    '_ContaoManager\\Contao\\ManagerApi\\Controller\\Config\\ComposerController' => $baseDir . '/api/Controller/Config/ComposerController.php',
    '_ContaoManager\\Contao\\ManagerApi\\Controller\\Config\\ManagerController' => $baseDir . '/api/Controller/Config/ManagerController.php',
    '_ContaoManager\\Contao\\ManagerApi\\Controller\\ConstraintController' => $baseDir . '/api/Controller/ConstraintController.php',
    '_ContaoManager\\Contao\\ManagerApi\\Controller\\Contao\\AccessKeyController' => $baseDir . '/api/Controller/Contao/AccessKeyController.php',
    '_ContaoManager\\Contao\\ManagerApi\\Controller\\Contao\\BackupController' => $baseDir . '/api/Controller/Contao/BackupController.php',
    '_ContaoManager\\Contao\\ManagerApi\\Controller\\Contao\\DatabaseMigrationController' => $baseDir . '/api/Controller/Contao/DatabaseMigrationController.php',
    '_ContaoManager\\Contao\\ManagerApi\\Controller\\Contao\\InstallToolLockController' => $baseDir . '/api/Controller/Contao/InstallToolLockController.php',
    '_ContaoManager\\Contao\\ManagerApi\\Controller\\Contao\\JwtCookieController' => $baseDir . '/api/Controller/Contao/JwtCookieController.php',
    '_ContaoManager\\Contao\\ManagerApi\\Controller\\Contao\\MaintenanceModeController' => $baseDir . '/api/Controller/Contao/MaintenanceModeController.php',
    '_ContaoManager\\Contao\\ManagerApi\\Controller\\FileController' => $baseDir . '/api/Controller/FileController.php',
    '_ContaoManager\\Contao\\ManagerApi\\Controller\\LogController' => $baseDir . '/api/Controller/LogController.php',
    '_ContaoManager\\Contao\\ManagerApi\\Controller\\Packages\\CloudController' => $baseDir . '/api/Controller/Packages/CloudController.php',
    '_ContaoManager\\Contao\\ManagerApi\\Controller\\Packages\\LocalPackagesController' => $baseDir . '/api/Controller/Packages/LocalPackagesController.php',
    '_ContaoManager\\Contao\\ManagerApi\\Controller\\Packages\\MissingPackagesController' => $baseDir . '/api/Controller/Packages/MissingPackagesController.php',
    '_ContaoManager\\Contao\\ManagerApi\\Controller\\Packages\\RootPackageController' => $baseDir . '/api/Controller/Packages/RootPackageController.php',
    '_ContaoManager\\Contao\\ManagerApi\\Controller\\Packages\\UploadPackagesController' => $baseDir . '/api/Controller/Packages/UploadPackagesController.php',
    '_ContaoManager\\Contao\\ManagerApi\\Controller\\Server\\AdminUserController' => $baseDir . '/api/Controller/Server/AdminUserController.php',
    '_ContaoManager\\Contao\\ManagerApi\\Controller\\Server\\ComposerController' => $baseDir . '/api/Controller/Server/ComposerController.php',
    '_ContaoManager\\Contao\\ManagerApi\\Controller\\Server\\ConfigController' => $baseDir . '/api/Controller/Server/ConfigController.php',
    '_ContaoManager\\Contao\\ManagerApi\\Controller\\Server\\ContaoController' => $baseDir . '/api/Controller/Server/ContaoController.php',
    '_ContaoManager\\Contao\\ManagerApi\\Controller\\Server\\DatabaseController' => $baseDir . '/api/Controller/Server/DatabaseController.php',
    '_ContaoManager\\Contao\\ManagerApi\\Controller\\Server\\OpcacheController' => $baseDir . '/api/Controller/Server/OpcacheController.php',
    '_ContaoManager\\Contao\\ManagerApi\\Controller\\Server\\PhpCliController' => $baseDir . '/api/Controller/Server/PhpCliController.php',
    '_ContaoManager\\Contao\\ManagerApi\\Controller\\Server\\PhpWebController' => $baseDir . '/api/Controller/Server/PhpWebController.php',
    '_ContaoManager\\Contao\\ManagerApi\\Controller\\Server\\PhpinfoController' => $baseDir . '/api/Controller/Server/PhpinfoController.php',
    '_ContaoManager\\Contao\\ManagerApi\\Controller\\Server\\SelfUpdateController' => $baseDir . '/api/Controller/Server/SelfUpdateController.php',
    '_ContaoManager\\Contao\\ManagerApi\\Controller\\SessionController' => $baseDir . '/api/Controller/SessionController.php',
    '_ContaoManager\\Contao\\ManagerApi\\Controller\\TaskController' => $baseDir . '/api/Controller/TaskController.php',
    '_ContaoManager\\Contao\\ManagerApi\\Controller\\UserController' => $baseDir . '/api/Controller/UserController.php',
    '_ContaoManager\\Contao\\ManagerApi\\EventListener\\CheckTotpListener' => $baseDir . '/api/EventListener/CheckTotpListener.php',
    '_ContaoManager\\Contao\\ManagerApi\\EventListener\\ExceptionListener' => $baseDir . '/api/EventListener/ExceptionListener.php',
    '_ContaoManager\\Contao\\ManagerApi\\EventListener\\JsonRequestListener' => $baseDir . '/api/EventListener/JsonRequestListener.php',
    '_ContaoManager\\Contao\\ManagerApi\\EventListener\\LocaleListener' => $baseDir . '/api/EventListener/LocaleListener.php',
    '_ContaoManager\\Contao\\ManagerApi\\EventListener\\SecurityListener' => $baseDir . '/api/EventListener/SecurityListener.php',
    '_ContaoManager\\Contao\\ManagerApi\\Exception\\ApiProblemException' => $baseDir . '/api/Exception/ApiProblemException.php',
    '_ContaoManager\\Contao\\ManagerApi\\Exception\\InvalidJsonException' => $baseDir . '/api/Exception/InvalidJsonException.php',
    '_ContaoManager\\Contao\\ManagerApi\\Exception\\InvalidTotpException' => $baseDir . '/api/Exception/InvalidTotpException.php',
    '_ContaoManager\\Contao\\ManagerApi\\Exception\\ProcessOutputException' => $baseDir . '/api/Exception/ProcessOutputException.php',
    '_ContaoManager\\Contao\\ManagerApi\\Exception\\RequestException' => $baseDir . '/api/Exception/RequestException.php',
    '_ContaoManager\\Contao\\ManagerApi\\HttpKernel\\ApiProblemResponse' => $baseDir . '/api/HttpKernel/ApiProblemResponse.php',
    '_ContaoManager\\Contao\\ManagerApi\\I18n\\Translator' => $baseDir . '/api/I18n/Translator.php',
    '_ContaoManager\\Contao\\ManagerApi\\IntegrityCheck\\AbstractIntegrityCheck' => $baseDir . '/api/IntegrityCheck/AbstractIntegrityCheck.php',
    '_ContaoManager\\Contao\\ManagerApi\\IntegrityCheck\\AllowUrlFopenCheck' => $baseDir . '/api/IntegrityCheck/AllowUrlFopenCheck.php',
    '_ContaoManager\\Contao\\ManagerApi\\IntegrityCheck\\GraphicsLibCheck' => $baseDir . '/api/IntegrityCheck/GraphicsLibCheck.php',
    '_ContaoManager\\Contao\\ManagerApi\\IntegrityCheck\\IntegrityCheckFactory' => $baseDir . '/api/IntegrityCheck/IntegrityCheckFactory.php',
    '_ContaoManager\\Contao\\ManagerApi\\IntegrityCheck\\IntegrityCheckInterface' => $baseDir . '/api/IntegrityCheck/IntegrityCheckInterface.php',
    '_ContaoManager\\Contao\\ManagerApi\\IntegrityCheck\\MemoryLimitCheck' => $baseDir . '/api/IntegrityCheck/MemoryLimitCheck.php',
    '_ContaoManager\\Contao\\ManagerApi\\IntegrityCheck\\PhpExtensionsCheck' => $baseDir . '/api/IntegrityCheck/PhpExtensionsCheck.php',
    '_ContaoManager\\Contao\\ManagerApi\\IntegrityCheck\\ProcessCheck' => $baseDir . '/api/IntegrityCheck/ProcessCheck.php',
    '_ContaoManager\\Contao\\ManagerApi\\IntegrityCheck\\SessionCheck' => $baseDir . '/api/IntegrityCheck/SessionCheck.php',
    '_ContaoManager\\Contao\\ManagerApi\\IntegrityCheck\\SymlinkCheck' => $baseDir . '/api/IntegrityCheck/SymlinkCheck.php',
    '_ContaoManager\\Contao\\ManagerApi\\IntegrityCheck\\SysTempDirCheck' => $baseDir . '/api/IntegrityCheck/SysTempDirCheck.php',
    '_ContaoManager\\Contao\\ManagerApi\\IntegrityCheck\\ZipCheck' => $baseDir . '/api/IntegrityCheck/ZipCheck.php',
    '_ContaoManager\\Contao\\ManagerApi\\Process\\AbstractProcess' => $baseDir . '/api/Process/AbstractProcess.php',
    '_ContaoManager\\Contao\\ManagerApi\\Process\\ConsoleProcessFactory' => $baseDir . '/api/Process/ConsoleProcessFactory.php',
    '_ContaoManager\\Contao\\ManagerApi\\Process\\ContaoApi' => $baseDir . '/api/Process/ContaoApi.php',
    '_ContaoManager\\Contao\\ManagerApi\\Process\\ContaoConsole' => $baseDir . '/api/Process/ContaoConsole.php',
    '_ContaoManager\\Contao\\ManagerApi\\Process\\Forker\\AbstractForker' => $baseDir . '/api/Process/Forker/AbstractForker.php',
    '_ContaoManager\\Contao\\ManagerApi\\Process\\Forker\\DisownForker' => $baseDir . '/api/Process/Forker/DisownForker.php',
    '_ContaoManager\\Contao\\ManagerApi\\Process\\Forker\\ForkerInterface' => $baseDir . '/api/Process/Forker/ForkerInterface.php',
    '_ContaoManager\\Contao\\ManagerApi\\Process\\Forker\\InlineForker' => $baseDir . '/api/Process/Forker/InlineForker.php',
    '_ContaoManager\\Contao\\ManagerApi\\Process\\Forker\\NohupForker' => $baseDir . '/api/Process/Forker/NohupForker.php',
    '_ContaoManager\\Contao\\ManagerApi\\Process\\Forker\\WindowsStartForker' => $baseDir . '/api/Process/Forker/WindowsStartForker.php',
    '_ContaoManager\\Contao\\ManagerApi\\Process\\PhpExecutableFinder' => $baseDir . '/api/Process/PhpExecutableFinder.php',
    '_ContaoManager\\Contao\\ManagerApi\\Process\\ProcessController' => $baseDir . '/api/Process/ProcessController.php',
    '_ContaoManager\\Contao\\ManagerApi\\Process\\ProcessRunner' => $baseDir . '/api/Process/ProcessRunner.php',
    '_ContaoManager\\Contao\\ManagerApi\\Process\\Utf8Process' => $baseDir . '/api/Process/Utf8Process.php',
    '_ContaoManager\\Contao\\ManagerApi\\Security\\AbstractBrowserAuthenticator' => $baseDir . '/api/Security/AbstractBrowserAuthenticator.php',
    '_ContaoManager\\Contao\\ManagerApi\\Security\\AuthenticationTrustResolver' => $baseDir . '/api/Security/AuthenticationTrustResolver.php',
    '_ContaoManager\\Contao\\ManagerApi\\Security\\JwtAuthenticator' => $baseDir . '/api/Security/JwtAuthenticator.php',
    '_ContaoManager\\Contao\\ManagerApi\\Security\\JwtManager' => $baseDir . '/api/Security/JwtManager.php',
    '_ContaoManager\\Contao\\ManagerApi\\Security\\LoginAuthenticator' => $baseDir . '/api/Security/LoginAuthenticator.php',
    '_ContaoManager\\Contao\\ManagerApi\\Security\\PasswordlessAuthenticator' => $baseDir . '/api/Security/PasswordlessAuthenticator.php',
    '_ContaoManager\\Contao\\ManagerApi\\Security\\TokenAuthenticator' => $baseDir . '/api/Security/TokenAuthenticator.php',
    '_ContaoManager\\Contao\\ManagerApi\\Security\\TotpBadge' => $baseDir . '/api/Security/TotpBadge.php',
    '_ContaoManager\\Contao\\ManagerApi\\Security\\User' => $baseDir . '/api/Security/User.php',
    '_ContaoManager\\Contao\\ManagerApi\\Security\\UserProvider' => $baseDir . '/api/Security/UserProvider.php',
    '_ContaoManager\\Contao\\ManagerApi\\Security\\WebauthnAuthenticator' => $baseDir . '/api/Security/WebauthnAuthenticator.php',
    '_ContaoManager\\Contao\\ManagerApi\\System\\Request' => $baseDir . '/api/System/Request.php',
    '_ContaoManager\\Contao\\ManagerApi\\System\\SelfUpdate' => $baseDir . '/api/System/SelfUpdate.php',
    '_ContaoManager\\Contao\\ManagerApi\\System\\ServerInfo' => $baseDir . '/api/System/ServerInfo.php',
    '_ContaoManager\\Contao\\ManagerApi\\TaskOperation\\AbstractInlineOperation' => $baseDir . '/api/TaskOperation/AbstractInlineOperation.php',
    '_ContaoManager\\Contao\\ManagerApi\\TaskOperation\\AbstractProcessOperation' => $baseDir . '/api/TaskOperation/AbstractProcessOperation.php',
    '_ContaoManager\\Contao\\ManagerApi\\TaskOperation\\Composer\\ClearCacheOperation' => $baseDir . '/api/TaskOperation/Composer/ClearCacheOperation.php',
    '_ContaoManager\\Contao\\ManagerApi\\TaskOperation\\Composer\\CloudOperation' => $baseDir . '/api/TaskOperation/Composer/CloudOperation.php',
    '_ContaoManager\\Contao\\ManagerApi\\TaskOperation\\Composer\\CreateProjectOperation' => $baseDir . '/api/TaskOperation/Composer/CreateProjectOperation.php',
    '_ContaoManager\\Contao\\ManagerApi\\TaskOperation\\Composer\\DumpAutoloadOperation' => $baseDir . '/api/TaskOperation/Composer/DumpAutoloadOperation.php',
    '_ContaoManager\\Contao\\ManagerApi\\TaskOperation\\Composer\\InstallOperation' => $baseDir . '/api/TaskOperation/Composer/InstallOperation.php',
    '_ContaoManager\\Contao\\ManagerApi\\TaskOperation\\Composer\\RemoveOperation' => $baseDir . '/api/TaskOperation/Composer/RemoveOperation.php',
    '_ContaoManager\\Contao\\ManagerApi\\TaskOperation\\Composer\\RequireOperation' => $baseDir . '/api/TaskOperation/Composer/RequireOperation.php',
    '_ContaoManager\\Contao\\ManagerApi\\TaskOperation\\Composer\\UpdateOperation' => $baseDir . '/api/TaskOperation/Composer/UpdateOperation.php',
    '_ContaoManager\\Contao\\ManagerApi\\TaskOperation\\ConsoleOutput' => $baseDir . '/api/TaskOperation/ConsoleOutput.php',
    '_ContaoManager\\Contao\\ManagerApi\\TaskOperation\\Contao\\BackupCreateOperation' => $baseDir . '/api/TaskOperation/Contao/BackupCreateOperation.php',
    '_ContaoManager\\Contao\\ManagerApi\\TaskOperation\\Contao\\BackupRestoreOperation' => $baseDir . '/api/TaskOperation/Contao/BackupRestoreOperation.php',
    '_ContaoManager\\Contao\\ManagerApi\\TaskOperation\\Contao\\CacheClearOperation' => $baseDir . '/api/TaskOperation/Contao/CacheClearOperation.php',
    '_ContaoManager\\Contao\\ManagerApi\\TaskOperation\\Contao\\CacheWarmupOperation' => $baseDir . '/api/TaskOperation/Contao/CacheWarmupOperation.php',
    '_ContaoManager\\Contao\\ManagerApi\\TaskOperation\\Contao\\CreateContaoOperation' => $baseDir . '/api/TaskOperation/Contao/CreateContaoOperation.php',
    '_ContaoManager\\Contao\\ManagerApi\\TaskOperation\\Contao\\MaintenanceModeOperation' => $baseDir . '/api/TaskOperation/Contao/MaintenanceModeOperation.php',
    '_ContaoManager\\Contao\\ManagerApi\\TaskOperation\\Filesystem\\InstallUploadsOperation' => $baseDir . '/api/TaskOperation/Filesystem/InstallUploadsOperation.php',
    '_ContaoManager\\Contao\\ManagerApi\\TaskOperation\\Filesystem\\RemoveArtifactsOperation' => $baseDir . '/api/TaskOperation/Filesystem/RemoveArtifactsOperation.php',
    '_ContaoManager\\Contao\\ManagerApi\\TaskOperation\\Filesystem\\RemoveCacheOperation' => $baseDir . '/api/TaskOperation/Filesystem/RemoveCacheOperation.php',
    '_ContaoManager\\Contao\\ManagerApi\\TaskOperation\\Filesystem\\RemoveUploadsOperation' => $baseDir . '/api/TaskOperation/Filesystem/RemoveUploadsOperation.php',
    '_ContaoManager\\Contao\\ManagerApi\\TaskOperation\\Filesystem\\RemoveVendorOperation' => $baseDir . '/api/TaskOperation/Filesystem/RemoveVendorOperation.php',
    '_ContaoManager\\Contao\\ManagerApi\\TaskOperation\\Manager\\SelfUpdateOperation' => $baseDir . '/api/TaskOperation/Manager/SelfUpdateOperation.php',
    '_ContaoManager\\Contao\\ManagerApi\\TaskOperation\\SponsoredOperationInterface' => $baseDir . '/api/TaskOperation/SponsoredOperationInterface.php',
    '_ContaoManager\\Contao\\ManagerApi\\TaskOperation\\TaskOperationInterface' => $baseDir . '/api/TaskOperation/TaskOperationInterface.php',
    '_ContaoManager\\Contao\\ManagerApi\\Task\\AbstractTask' => $baseDir . '/api/Task/AbstractTask.php',
    '_ContaoManager\\Contao\\ManagerApi\\Task\\Composer\\ClearCacheTask' => $baseDir . '/api/Task/Composer/ClearCacheTask.php',
    '_ContaoManager\\Contao\\ManagerApi\\Task\\Composer\\DumpAutoloadTask' => $baseDir . '/api/Task/Composer/DumpAutoloadTask.php',
    '_ContaoManager\\Contao\\ManagerApi\\Task\\Contao\\BackupCreateTask' => $baseDir . '/api/Task/Contao/BackupCreateTask.php',
    '_ContaoManager\\Contao\\ManagerApi\\Task\\Contao\\BackupRestoreTask' => $baseDir . '/api/Task/Contao/BackupRestoreTask.php',
    '_ContaoManager\\Contao\\ManagerApi\\Task\\Contao\\RebuildCacheTask' => $baseDir . '/api/Task/Contao/RebuildCacheTask.php',
    '_ContaoManager\\Contao\\ManagerApi\\Task\\Manager\\SelfUpdateTask' => $baseDir . '/api/Task/Manager/SelfUpdateTask.php',
    '_ContaoManager\\Contao\\ManagerApi\\Task\\Packages\\AbstractPackagesTask' => $baseDir . '/api/Task/Packages/AbstractPackagesTask.php',
    '_ContaoManager\\Contao\\ManagerApi\\Task\\Packages\\InstallTask' => $baseDir . '/api/Task/Packages/InstallTask.php',
    '_ContaoManager\\Contao\\ManagerApi\\Task\\Packages\\SetupTask' => $baseDir . '/api/Task/Packages/SetupTask.php',
    '_ContaoManager\\Contao\\ManagerApi\\Task\\Packages\\UpdateTask' => $baseDir . '/api/Task/Packages/UpdateTask.php',
    '_ContaoManager\\Contao\\ManagerApi\\Task\\TaskConfig' => $baseDir . '/api/Task/TaskConfig.php',
    '_ContaoManager\\Contao\\ManagerApi\\Task\\TaskInterface' => $baseDir . '/api/Task/TaskInterface.php',
    '_ContaoManager\\Contao\\ManagerApi\\Task\\TaskManager' => $baseDir . '/api/Task/TaskManager.php',
    '_ContaoManager\\Contao\\ManagerApi\\Task\\TaskStatus' => $baseDir . '/api/Task/TaskStatus.php',
    '_ContaoManager\\Contao\\ManagerApi\\Tests\\Composer\\CloudJobTest' => $baseDir . '/api/Tests/Composer/CloudJobTest.php',
    '_ContaoManager\\Contao\\ManagerApi\\Tests\\Controller\\LogPatternTest' => $baseDir . '/api/Tests/Controller/LogPatternTest.php',
    '_ContaoManager\\Cose\\Algorithm\\Algorithm' => $vendorDir . '/web-auth/cose-lib/src/Algorithm/Algorithm.php',
    '_ContaoManager\\Cose\\Algorithm\\Mac\\HS256' => $vendorDir . '/web-auth/cose-lib/src/Algorithm/Mac/HS256.php',
    '_ContaoManager\\Cose\\Algorithm\\Mac\\HS256Truncated64' => $vendorDir . '/web-auth/cose-lib/src/Algorithm/Mac/HS256Truncated64.php',
    '_ContaoManager\\Cose\\Algorithm\\Mac\\HS384' => $vendorDir . '/web-auth/cose-lib/src/Algorithm/Mac/HS384.php',
    '_ContaoManager\\Cose\\Algorithm\\Mac\\HS512' => $vendorDir . '/web-auth/cose-lib/src/Algorithm/Mac/HS512.php',
    '_ContaoManager\\Cose\\Algorithm\\Mac\\Hmac' => $vendorDir . '/web-auth/cose-lib/src/Algorithm/Mac/Hmac.php',
    '_ContaoManager\\Cose\\Algorithm\\Mac\\Mac' => $vendorDir . '/web-auth/cose-lib/src/Algorithm/Mac/Mac.php',
    '_ContaoManager\\Cose\\Algorithm\\Manager' => $vendorDir . '/web-auth/cose-lib/src/Algorithm/Manager.php',
    '_ContaoManager\\Cose\\Algorithm\\ManagerFactory' => $vendorDir . '/web-auth/cose-lib/src/Algorithm/ManagerFactory.php',
    '_ContaoManager\\Cose\\Algorithm\\Signature\\ECDSA\\ECDSA' => $vendorDir . '/web-auth/cose-lib/src/Algorithm/Signature/ECDSA/ECDSA.php',
    '_ContaoManager\\Cose\\Algorithm\\Signature\\ECDSA\\ECSignature' => $vendorDir . '/web-auth/cose-lib/src/Algorithm/Signature/ECDSA/ECSignature.php',
    '_ContaoManager\\Cose\\Algorithm\\Signature\\ECDSA\\ES256' => $vendorDir . '/web-auth/cose-lib/src/Algorithm/Signature/ECDSA/ES256.php',
    '_ContaoManager\\Cose\\Algorithm\\Signature\\ECDSA\\ES256K' => $vendorDir . '/web-auth/cose-lib/src/Algorithm/Signature/ECDSA/ES256K.php',
    '_ContaoManager\\Cose\\Algorithm\\Signature\\ECDSA\\ES384' => $vendorDir . '/web-auth/cose-lib/src/Algorithm/Signature/ECDSA/ES384.php',
    '_ContaoManager\\Cose\\Algorithm\\Signature\\ECDSA\\ES512' => $vendorDir . '/web-auth/cose-lib/src/Algorithm/Signature/ECDSA/ES512.php',
    '_ContaoManager\\Cose\\Algorithm\\Signature\\EdDSA\\Ed25519' => $vendorDir . '/web-auth/cose-lib/src/Algorithm/Signature/EdDSA/Ed25519.php',
    '_ContaoManager\\Cose\\Algorithm\\Signature\\EdDSA\\Ed256' => $vendorDir . '/web-auth/cose-lib/src/Algorithm/Signature/EdDSA/Ed256.php',
    '_ContaoManager\\Cose\\Algorithm\\Signature\\EdDSA\\Ed512' => $vendorDir . '/web-auth/cose-lib/src/Algorithm/Signature/EdDSA/Ed512.php',
    '_ContaoManager\\Cose\\Algorithm\\Signature\\EdDSA\\EdDSA' => $vendorDir . '/web-auth/cose-lib/src/Algorithm/Signature/EdDSA/EdDSA.php',
    '_ContaoManager\\Cose\\Algorithm\\Signature\\RSA\\PS256' => $vendorDir . '/web-auth/cose-lib/src/Algorithm/Signature/RSA/PS256.php',
    '_ContaoManager\\Cose\\Algorithm\\Signature\\RSA\\PS384' => $vendorDir . '/web-auth/cose-lib/src/Algorithm/Signature/RSA/PS384.php',
    '_ContaoManager\\Cose\\Algorithm\\Signature\\RSA\\PS512' => $vendorDir . '/web-auth/cose-lib/src/Algorithm/Signature/RSA/PS512.php',
    '_ContaoManager\\Cose\\Algorithm\\Signature\\RSA\\PSSRSA' => $vendorDir . '/web-auth/cose-lib/src/Algorithm/Signature/RSA/PSSRSA.php',
    '_ContaoManager\\Cose\\Algorithm\\Signature\\RSA\\RS1' => $vendorDir . '/web-auth/cose-lib/src/Algorithm/Signature/RSA/RS1.php',
    '_ContaoManager\\Cose\\Algorithm\\Signature\\RSA\\RS256' => $vendorDir . '/web-auth/cose-lib/src/Algorithm/Signature/RSA/RS256.php',
    '_ContaoManager\\Cose\\Algorithm\\Signature\\RSA\\RS384' => $vendorDir . '/web-auth/cose-lib/src/Algorithm/Signature/RSA/RS384.php',
    '_ContaoManager\\Cose\\Algorithm\\Signature\\RSA\\RS512' => $vendorDir . '/web-auth/cose-lib/src/Algorithm/Signature/RSA/RS512.php',
    '_ContaoManager\\Cose\\Algorithm\\Signature\\RSA\\RSA' => $vendorDir . '/web-auth/cose-lib/src/Algorithm/Signature/RSA/RSA.php',
    '_ContaoManager\\Cose\\Algorithm\\Signature\\Signature' => $vendorDir . '/web-auth/cose-lib/src/Algorithm/Signature/Signature.php',
    '_ContaoManager\\Cose\\Algorithms' => $vendorDir . '/web-auth/cose-lib/src/Algorithms.php',
    '_ContaoManager\\Cose\\BigInteger' => $vendorDir . '/web-auth/cose-lib/src/BigInteger.php',
    '_ContaoManager\\Cose\\Encryption\\CoseEncrypt0Tag' => $vendorDir . '/web-auth/cose-lib/src/Encryption/CoseEncrypt0Tag.php',
    '_ContaoManager\\Cose\\Encryption\\CoseEncryptTag' => $vendorDir . '/web-auth/cose-lib/src/Encryption/CoseEncryptTag.php',
    '_ContaoManager\\Cose\\Hash' => $vendorDir . '/web-auth/cose-lib/src/Hash.php',
    '_ContaoManager\\Cose\\Key\\Ec2Key' => $vendorDir . '/web-auth/cose-lib/src/Key/Ec2Key.php',
    '_ContaoManager\\Cose\\Key\\Key' => $vendorDir . '/web-auth/cose-lib/src/Key/Key.php',
    '_ContaoManager\\Cose\\Key\\OkpKey' => $vendorDir . '/web-auth/cose-lib/src/Key/OkpKey.php',
    '_ContaoManager\\Cose\\Key\\RsaKey' => $vendorDir . '/web-auth/cose-lib/src/Key/RsaKey.php',
    '_ContaoManager\\Cose\\Key\\SymmetricKey' => $vendorDir . '/web-auth/cose-lib/src/Key/SymmetricKey.php',
    '_ContaoManager\\Cose\\Mac\\CoseMac0Tag' => $vendorDir . '/web-auth/cose-lib/src/Mac/CoseMac0Tag.php',
    '_ContaoManager\\Cose\\Mac\\CoseMacTag' => $vendorDir . '/web-auth/cose-lib/src/Mac/CoseMacTag.php',
    '_ContaoManager\\Cose\\Signature\\CoseSign1Tag' => $vendorDir . '/web-auth/cose-lib/src/Signature/CoseSign1Tag.php',
    '_ContaoManager\\Cose\\Signature\\CoseSignTag' => $vendorDir . '/web-auth/cose-lib/src/Signature/CoseSignTag.php',
    '_ContaoManager\\Cose\\Signature\\Signature1' => $vendorDir . '/web-auth/cose-lib/src/Signature/Signature1.php',
    '_ContaoManager\\Crell\\ApiProblem\\ApiProblem' => $vendorDir . '/crell/api-problem/src/ApiProblem.php',
    '_ContaoManager\\Crell\\ApiProblem\\HttpConverter' => $vendorDir . '/crell/api-problem/src/HttpConverter.php',
    '_ContaoManager\\Crell\\ApiProblem\\JsonEncodeException' => $vendorDir . '/crell/api-problem/src/JsonEncodeException.php',
    '_ContaoManager\\Crell\\ApiProblem\\JsonException' => $vendorDir . '/crell/api-problem/src/JsonException.php',
    '_ContaoManager\\Crell\\ApiProblem\\JsonParseException' => $vendorDir . '/crell/api-problem/src/JsonParseException.php',
    '_ContaoManager\\Doctrine\\Deprecations\\Deprecation' => $vendorDir . '/doctrine/deprecations/src/Deprecation.php',
    '_ContaoManager\\Doctrine\\Deprecations\\PHPUnit\\VerifyDeprecations' => $vendorDir . '/doctrine/deprecations/src/PHPUnit/VerifyDeprecations.php',
    '_ContaoManager\\Firebase\\JWT\\BeforeValidException' => $vendorDir . '/firebase/php-jwt/src/BeforeValidException.php',
    '_ContaoManager\\Firebase\\JWT\\CachedKeySet' => $vendorDir . '/firebase/php-jwt/src/CachedKeySet.php',
    '_ContaoManager\\Firebase\\JWT\\ExpiredException' => $vendorDir . '/firebase/php-jwt/src/ExpiredException.php',
    '_ContaoManager\\Firebase\\JWT\\JWK' => $vendorDir . '/firebase/php-jwt/src/JWK.php',
    '_ContaoManager\\Firebase\\JWT\\JWT' => $vendorDir . '/firebase/php-jwt/src/JWT.php',
    '_ContaoManager\\Firebase\\JWT\\JWTExceptionWithPayloadInterface' => $vendorDir . '/firebase/php-jwt/src/JWTExceptionWithPayloadInterface.php',
    '_ContaoManager\\Firebase\\JWT\\Key' => $vendorDir . '/firebase/php-jwt/src/Key.php',
    '_ContaoManager\\Firebase\\JWT\\SignatureInvalidException' => $vendorDir . '/firebase/php-jwt/src/SignatureInvalidException.php',
    '_ContaoManager\\JsonSchema\\ConstraintError' => $vendorDir . '/justinrainbow/json-schema/src/JsonSchema/ConstraintError.php',
    '_ContaoManager\\JsonSchema\\Constraints\\BaseConstraint' => $vendorDir . '/justinrainbow/json-schema/src/JsonSchema/Constraints/BaseConstraint.php',
    '_ContaoManager\\JsonSchema\\Constraints\\CollectionConstraint' => $vendorDir . '/justinrainbow/json-schema/src/JsonSchema/Constraints/CollectionConstraint.php',
    '_ContaoManager\\JsonSchema\\Constraints\\ConstConstraint' => $vendorDir . '/justinrainbow/json-schema/src/JsonSchema/Constraints/ConstConstraint.php',
    '_ContaoManager\\JsonSchema\\Constraints\\Constraint' => $vendorDir . '/justinrainbow/json-schema/src/JsonSchema/Constraints/Constraint.php',
    '_ContaoManager\\JsonSchema\\Constraints\\ConstraintInterface' => $vendorDir . '/justinrainbow/json-schema/src/JsonSchema/Constraints/ConstraintInterface.php',
    '_ContaoManager\\JsonSchema\\Constraints\\Drafts\\Draft06\\AdditionalItemsConstraint' => $vendorDir . '/justinrainbow/json-schema/src/JsonSchema/Constraints/Drafts/Draft06/AdditionalItemsConstraint.php',
    '_ContaoManager\\JsonSchema\\Constraints\\Drafts\\Draft06\\AdditionalPropertiesConstraint' => $vendorDir . '/justinrainbow/json-schema/src/JsonSchema/Constraints/Drafts/Draft06/AdditionalPropertiesConstraint.php',
    '_ContaoManager\\JsonSchema\\Constraints\\Drafts\\Draft06\\AllOfConstraint' => $vendorDir . '/justinrainbow/json-schema/src/JsonSchema/Constraints/Drafts/Draft06/AllOfConstraint.php',
    '_ContaoManager\\JsonSchema\\Constraints\\Drafts\\Draft06\\AnyOfConstraint' => $vendorDir . '/justinrainbow/json-schema/src/JsonSchema/Constraints/Drafts/Draft06/AnyOfConstraint.php',
    '_ContaoManager\\JsonSchema\\Constraints\\Drafts\\Draft06\\ConstConstraint' => $vendorDir . '/justinrainbow/json-schema/src/JsonSchema/Constraints/Drafts/Draft06/ConstConstraint.php',
    '_ContaoManager\\JsonSchema\\Constraints\\Drafts\\Draft06\\ContainsConstraint' => $vendorDir . '/justinrainbow/json-schema/src/JsonSchema/Constraints/Drafts/Draft06/ContainsConstraint.php',
    '_ContaoManager\\JsonSchema\\Constraints\\Drafts\\Draft06\\DependenciesConstraint' => $vendorDir . '/justinrainbow/json-schema/src/JsonSchema/Constraints/Drafts/Draft06/DependenciesConstraint.php',
    '_ContaoManager\\JsonSchema\\Constraints\\Drafts\\Draft06\\Draft06Constraint' => $vendorDir . '/justinrainbow/json-schema/src/JsonSchema/Constraints/Drafts/Draft06/Draft06Constraint.php',
    '_ContaoManager\\JsonSchema\\Constraints\\Drafts\\Draft06\\EnumConstraint' => $vendorDir . '/justinrainbow/json-schema/src/JsonSchema/Constraints/Drafts/Draft06/EnumConstraint.php',
    '_ContaoManager\\JsonSchema\\Constraints\\Drafts\\Draft06\\ExclusiveMaximumConstraint' => $vendorDir . '/justinrainbow/json-schema/src/JsonSchema/Constraints/Drafts/Draft06/ExclusiveMaximumConstraint.php',
    '_ContaoManager\\JsonSchema\\Constraints\\Drafts\\Draft06\\ExclusiveMinimumConstraint' => $vendorDir . '/justinrainbow/json-schema/src/JsonSchema/Constraints/Drafts/Draft06/ExclusiveMinimumConstraint.php',
    '_ContaoManager\\JsonSchema\\Constraints\\Drafts\\Draft06\\Factory' => $vendorDir . '/justinrainbow/json-schema/src/JsonSchema/Constraints/Drafts/Draft06/Factory.php',
    '_ContaoManager\\JsonSchema\\Constraints\\Drafts\\Draft06\\FormatConstraint' => $vendorDir . '/justinrainbow/json-schema/src/JsonSchema/Constraints/Drafts/Draft06/FormatConstraint.php',
    '_ContaoManager\\JsonSchema\\Constraints\\Drafts\\Draft06\\ItemsConstraint' => $vendorDir . '/justinrainbow/json-schema/src/JsonSchema/Constraints/Drafts/Draft06/ItemsConstraint.php',
    '_ContaoManager\\JsonSchema\\Constraints\\Drafts\\Draft06\\MaxItemsConstraint' => $vendorDir . '/justinrainbow/json-schema/src/JsonSchema/Constraints/Drafts/Draft06/MaxItemsConstraint.php',
    '_ContaoManager\\JsonSchema\\Constraints\\Drafts\\Draft06\\MaxLengthConstraint' => $vendorDir . '/justinrainbow/json-schema/src/JsonSchema/Constraints/Drafts/Draft06/MaxLengthConstraint.php',
    '_ContaoManager\\JsonSchema\\Constraints\\Drafts\\Draft06\\MaxPropertiesConstraint' => $vendorDir . '/justinrainbow/json-schema/src/JsonSchema/Constraints/Drafts/Draft06/MaxPropertiesConstraint.php',
    '_ContaoManager\\JsonSchema\\Constraints\\Drafts\\Draft06\\MaximumConstraint' => $vendorDir . '/justinrainbow/json-schema/src/JsonSchema/Constraints/Drafts/Draft06/MaximumConstraint.php',
    '_ContaoManager\\JsonSchema\\Constraints\\Drafts\\Draft06\\MinItemsConstraint' => $vendorDir . '/justinrainbow/json-schema/src/JsonSchema/Constraints/Drafts/Draft06/MinItemsConstraint.php',
    '_ContaoManager\\JsonSchema\\Constraints\\Drafts\\Draft06\\MinLengthConstraint' => $vendorDir . '/justinrainbow/json-schema/src/JsonSchema/Constraints/Drafts/Draft06/MinLengthConstraint.php',
    '_ContaoManager\\JsonSchema\\Constraints\\Drafts\\Draft06\\MinPropertiesConstraint' => $vendorDir . '/justinrainbow/json-schema/src/JsonSchema/Constraints/Drafts/Draft06/MinPropertiesConstraint.php',
    '_ContaoManager\\JsonSchema\\Constraints\\Drafts\\Draft06\\MinimumConstraint' => $vendorDir . '/justinrainbow/json-schema/src/JsonSchema/Constraints/Drafts/Draft06/MinimumConstraint.php',
    '_ContaoManager\\JsonSchema\\Constraints\\Drafts\\Draft06\\MultipleOfConstraint' => $vendorDir . '/justinrainbow/json-schema/src/JsonSchema/Constraints/Drafts/Draft06/MultipleOfConstraint.php',
    '_ContaoManager\\JsonSchema\\Constraints\\Drafts\\Draft06\\NotConstraint' => $vendorDir . '/justinrainbow/json-schema/src/JsonSchema/Constraints/Drafts/Draft06/NotConstraint.php',
    '_ContaoManager\\JsonSchema\\Constraints\\Drafts\\Draft06\\OneOfConstraint' => $vendorDir . '/justinrainbow/json-schema/src/JsonSchema/Constraints/Drafts/Draft06/OneOfConstraint.php',
    '_ContaoManager\\JsonSchema\\Constraints\\Drafts\\Draft06\\PatternConstraint' => $vendorDir . '/justinrainbow/json-schema/src/JsonSchema/Constraints/Drafts/Draft06/PatternConstraint.php',
    '_ContaoManager\\JsonSchema\\Constraints\\Drafts\\Draft06\\PatternPropertiesConstraint' => $vendorDir . '/justinrainbow/json-schema/src/JsonSchema/Constraints/Drafts/Draft06/PatternPropertiesConstraint.php',
    '_ContaoManager\\JsonSchema\\Constraints\\Drafts\\Draft06\\PropertiesConstraint' => $vendorDir . '/justinrainbow/json-schema/src/JsonSchema/Constraints/Drafts/Draft06/PropertiesConstraint.php',
    '_ContaoManager\\JsonSchema\\Constraints\\Drafts\\Draft06\\PropertiesNamesConstraint' => $vendorDir . '/justinrainbow/json-schema/src/JsonSchema/Constraints/Drafts/Draft06/PropertiesNamesConstraint.php',
    '_ContaoManager\\JsonSchema\\Constraints\\Drafts\\Draft06\\RefConstraint' => $vendorDir . '/justinrainbow/json-schema/src/JsonSchema/Constraints/Drafts/Draft06/RefConstraint.php',
    '_ContaoManager\\JsonSchema\\Constraints\\Drafts\\Draft06\\RequiredConstraint' => $vendorDir . '/justinrainbow/json-schema/src/JsonSchema/Constraints/Drafts/Draft06/RequiredConstraint.php',
    '_ContaoManager\\JsonSchema\\Constraints\\Drafts\\Draft06\\TypeConstraint' => $vendorDir . '/justinrainbow/json-schema/src/JsonSchema/Constraints/Drafts/Draft06/TypeConstraint.php',
    '_ContaoManager\\JsonSchema\\Constraints\\Drafts\\Draft06\\UniqueItemsConstraint' => $vendorDir . '/justinrainbow/json-schema/src/JsonSchema/Constraints/Drafts/Draft06/UniqueItemsConstraint.php',
    '_ContaoManager\\JsonSchema\\Constraints\\Drafts\\Draft07\\AdditionalItemsConstraint' => $vendorDir . '/justinrainbow/json-schema/src/JsonSchema/Constraints/Drafts/Draft07/AdditionalItemsConstraint.php',
    '_ContaoManager\\JsonSchema\\Constraints\\Drafts\\Draft07\\AdditionalPropertiesConstraint' => $vendorDir . '/justinrainbow/json-schema/src/JsonSchema/Constraints/Drafts/Draft07/AdditionalPropertiesConstraint.php',
    '_ContaoManager\\JsonSchema\\Constraints\\Drafts\\Draft07\\AllOfConstraint' => $vendorDir . '/justinrainbow/json-schema/src/JsonSchema/Constraints/Drafts/Draft07/AllOfConstraint.php',
    '_ContaoManager\\JsonSchema\\Constraints\\Drafts\\Draft07\\AnyOfConstraint' => $vendorDir . '/justinrainbow/json-schema/src/JsonSchema/Constraints/Drafts/Draft07/AnyOfConstraint.php',
    '_ContaoManager\\JsonSchema\\Constraints\\Drafts\\Draft07\\ConstConstraint' => $vendorDir . '/justinrainbow/json-schema/src/JsonSchema/Constraints/Drafts/Draft07/ConstConstraint.php',
    '_ContaoManager\\JsonSchema\\Constraints\\Drafts\\Draft07\\ContainsConstraint' => $vendorDir . '/justinrainbow/json-schema/src/JsonSchema/Constraints/Drafts/Draft07/ContainsConstraint.php',
    '_ContaoManager\\JsonSchema\\Constraints\\Drafts\\Draft07\\ContentConstraint' => $vendorDir . '/justinrainbow/json-schema/src/JsonSchema/Constraints/Drafts/Draft07/ContentConstraint.php',
    '_ContaoManager\\JsonSchema\\Constraints\\Drafts\\Draft07\\DependenciesConstraint' => $vendorDir . '/justinrainbow/json-schema/src/JsonSchema/Constraints/Drafts/Draft07/DependenciesConstraint.php',
    '_ContaoManager\\JsonSchema\\Constraints\\Drafts\\Draft07\\Draft07Constraint' => $vendorDir . '/justinrainbow/json-schema/src/JsonSchema/Constraints/Drafts/Draft07/Draft07Constraint.php',
    '_ContaoManager\\JsonSchema\\Constraints\\Drafts\\Draft07\\EnumConstraint' => $vendorDir . '/justinrainbow/json-schema/src/JsonSchema/Constraints/Drafts/Draft07/EnumConstraint.php',
    '_ContaoManager\\JsonSchema\\Constraints\\Drafts\\Draft07\\ExclusiveMaximumConstraint' => $vendorDir . '/justinrainbow/json-schema/src/JsonSchema/Constraints/Drafts/Draft07/ExclusiveMaximumConstraint.php',
    '_ContaoManager\\JsonSchema\\Constraints\\Drafts\\Draft07\\ExclusiveMinimumConstraint' => $vendorDir . '/justinrainbow/json-schema/src/JsonSchema/Constraints/Drafts/Draft07/ExclusiveMinimumConstraint.php',
    '_ContaoManager\\JsonSchema\\Constraints\\Drafts\\Draft07\\Factory' => $vendorDir . '/justinrainbow/json-schema/src/JsonSchema/Constraints/Drafts/Draft07/Factory.php',
    '_ContaoManager\\JsonSchema\\Constraints\\Drafts\\Draft07\\FormatConstraint' => $vendorDir . '/justinrainbow/json-schema/src/JsonSchema/Constraints/Drafts/Draft07/FormatConstraint.php',
    '_ContaoManager\\JsonSchema\\Constraints\\Drafts\\Draft07\\IfThenElseConstraint' => $vendorDir . '/justinrainbow/json-schema/src/JsonSchema/Constraints/Drafts/Draft07/IfThenElseConstraint.php',
    '_ContaoManager\\JsonSchema\\Constraints\\Drafts\\Draft07\\ItemsConstraint' => $vendorDir . '/justinrainbow/json-schema/src/JsonSchema/Constraints/Drafts/Draft07/ItemsConstraint.php',
    '_ContaoManager\\JsonSchema\\Constraints\\Drafts\\Draft07\\MaxItemsConstraint' => $vendorDir . '/justinrainbow/json-schema/src/JsonSchema/Constraints/Drafts/Draft07/MaxItemsConstraint.php',
    '_ContaoManager\\JsonSchema\\Constraints\\Drafts\\Draft07\\MaxLengthConstraint' => $vendorDir . '/justinrainbow/json-schema/src/JsonSchema/Constraints/Drafts/Draft07/MaxLengthConstraint.php',
    '_ContaoManager\\JsonSchema\\Constraints\\Drafts\\Draft07\\MaxPropertiesConstraint' => $vendorDir . '/justinrainbow/json-schema/src/JsonSchema/Constraints/Drafts/Draft07/MaxPropertiesConstraint.php',
    '_ContaoManager\\JsonSchema\\Constraints\\Drafts\\Draft07\\MaximumConstraint' => $vendorDir . '/justinrainbow/json-schema/src/JsonSchema/Constraints/Drafts/Draft07/MaximumConstraint.php',
    '_ContaoManager\\JsonSchema\\Constraints\\Drafts\\Draft07\\MinItemsConstraint' => $vendorDir . '/justinrainbow/json-schema/src/JsonSchema/Constraints/Drafts/Draft07/MinItemsConstraint.php',
    '_ContaoManager\\JsonSchema\\Constraints\\Drafts\\Draft07\\MinLengthConstraint' => $vendorDir . '/justinrainbow/json-schema/src/JsonSchema/Constraints/Drafts/Draft07/MinLengthConstraint.php',
    '_ContaoManager\\JsonSchema\\Constraints\\Drafts\\Draft07\\MinPropertiesConstraint' => $vendorDir . '/justinrainbow/json-schema/src/JsonSchema/Constraints/Drafts/Draft07/MinPropertiesConstraint.php',
    '_ContaoManager\\JsonSchema\\Constraints\\Drafts\\Draft07\\MinimumConstraint' => $vendorDir . '/justinrainbow/json-schema/src/JsonSchema/Constraints/Drafts/Draft07/MinimumConstraint.php',
    '_ContaoManager\\JsonSchema\\Constraints\\Drafts\\Draft07\\MultipleOfConstraint' => $vendorDir . '/justinrainbow/json-schema/src/JsonSchema/Constraints/Drafts/Draft07/MultipleOfConstraint.php',
    '_ContaoManager\\JsonSchema\\Constraints\\Drafts\\Draft07\\NotConstraint' => $vendorDir . '/justinrainbow/json-schema/src/JsonSchema/Constraints/Drafts/Draft07/NotConstraint.php',
    '_ContaoManager\\JsonSchema\\Constraints\\Drafts\\Draft07\\OneOfConstraint' => $vendorDir . '/justinrainbow/json-schema/src/JsonSchema/Constraints/Drafts/Draft07/OneOfConstraint.php',
    '_ContaoManager\\JsonSchema\\Constraints\\Drafts\\Draft07\\PatternConstraint' => $vendorDir . '/justinrainbow/json-schema/src/JsonSchema/Constraints/Drafts/Draft07/PatternConstraint.php',
    '_ContaoManager\\JsonSchema\\Constraints\\Drafts\\Draft07\\PatternPropertiesConstraint' => $vendorDir . '/justinrainbow/json-schema/src/JsonSchema/Constraints/Drafts/Draft07/PatternPropertiesConstraint.php',
    '_ContaoManager\\JsonSchema\\Constraints\\Drafts\\Draft07\\PropertiesConstraint' => $vendorDir . '/justinrainbow/json-schema/src/JsonSchema/Constraints/Drafts/Draft07/PropertiesConstraint.php',
    '_ContaoManager\\JsonSchema\\Constraints\\Drafts\\Draft07\\PropertiesNamesConstraint' => $vendorDir . '/justinrainbow/json-schema/src/JsonSchema/Constraints/Drafts/Draft07/PropertiesNamesConstraint.php',
    '_ContaoManager\\JsonSchema\\Constraints\\Drafts\\Draft07\\RefConstraint' => $vendorDir . '/justinrainbow/json-schema/src/JsonSchema/Constraints/Drafts/Draft07/RefConstraint.php',
    '_ContaoManager\\JsonSchema\\Constraints\\Drafts\\Draft07\\RequiredConstraint' => $vendorDir . '/justinrainbow/json-schema/src/JsonSchema/Constraints/Drafts/Draft07/RequiredConstraint.php',
    '_ContaoManager\\JsonSchema\\Constraints\\Drafts\\Draft07\\TypeConstraint' => $vendorDir . '/justinrainbow/json-schema/src/JsonSchema/Constraints/Drafts/Draft07/TypeConstraint.php',
    '_ContaoManager\\JsonSchema\\Constraints\\Drafts\\Draft07\\UniqueItemsConstraint' => $vendorDir . '/justinrainbow/json-schema/src/JsonSchema/Constraints/Drafts/Draft07/UniqueItemsConstraint.php',
    '_ContaoManager\\JsonSchema\\Constraints\\EnumConstraint' => $vendorDir . '/justinrainbow/json-schema/src/JsonSchema/Constraints/EnumConstraint.php',
    '_ContaoManager\\JsonSchema\\Constraints\\Factory' => $vendorDir . '/justinrainbow/json-schema/src/JsonSchema/Constraints/Factory.php',
    '_ContaoManager\\JsonSchema\\Constraints\\FormatConstraint' => $vendorDir . '/justinrainbow/json-schema/src/JsonSchema/Constraints/FormatConstraint.php',
    '_ContaoManager\\JsonSchema\\Constraints\\NumberConstraint' => $vendorDir . '/justinrainbow/json-schema/src/JsonSchema/Constraints/NumberConstraint.php',
    '_ContaoManager\\JsonSchema\\Constraints\\ObjectConstraint' => $vendorDir . '/justinrainbow/json-schema/src/JsonSchema/Constraints/ObjectConstraint.php',
    '_ContaoManager\\JsonSchema\\Constraints\\SchemaConstraint' => $vendorDir . '/justinrainbow/json-schema/src/JsonSchema/Constraints/SchemaConstraint.php',
    '_ContaoManager\\JsonSchema\\Constraints\\StringConstraint' => $vendorDir . '/justinrainbow/json-schema/src/JsonSchema/Constraints/StringConstraint.php',
    '_ContaoManager\\JsonSchema\\Constraints\\TypeCheck\\LooseTypeCheck' => $vendorDir . '/justinrainbow/json-schema/src/JsonSchema/Constraints/TypeCheck/LooseTypeCheck.php',
    '_ContaoManager\\JsonSchema\\Constraints\\TypeCheck\\StrictTypeCheck' => $vendorDir . '/justinrainbow/json-schema/src/JsonSchema/Constraints/TypeCheck/StrictTypeCheck.php',
    '_ContaoManager\\JsonSchema\\Constraints\\TypeCheck\\TypeCheckInterface' => $vendorDir . '/justinrainbow/json-schema/src/JsonSchema/Constraints/TypeCheck/TypeCheckInterface.php',
    '_ContaoManager\\JsonSchema\\Constraints\\TypeConstraint' => $vendorDir . '/justinrainbow/json-schema/src/JsonSchema/Constraints/TypeConstraint.php',
    '_ContaoManager\\JsonSchema\\Constraints\\UndefinedConstraint' => $vendorDir . '/justinrainbow/json-schema/src/JsonSchema/Constraints/UndefinedConstraint.php',
    '_ContaoManager\\JsonSchema\\DraftIdentifiers' => $vendorDir . '/justinrainbow/json-schema/src/JsonSchema/DraftIdentifiers.php',
    '_ContaoManager\\JsonSchema\\Entity\\ErrorBag' => $vendorDir . '/justinrainbow/json-schema/src/JsonSchema/Entity/ErrorBag.php',
    '_ContaoManager\\JsonSchema\\Entity\\ErrorBagProxy' => $vendorDir . '/justinrainbow/json-schema/src/JsonSchema/Entity/ErrorBagProxy.php',
    '_ContaoManager\\JsonSchema\\Entity\\JsonPointer' => $vendorDir . '/justinrainbow/json-schema/src/JsonSchema/Entity/JsonPointer.php',
    '_ContaoManager\\JsonSchema\\Enum' => $vendorDir . '/justinrainbow/json-schema/src/JsonSchema/Enum.php',
    '_ContaoManager\\JsonSchema\\Exception\\ExceptionInterface' => $vendorDir . '/justinrainbow/json-schema/src/JsonSchema/Exception/ExceptionInterface.php',
    '_ContaoManager\\JsonSchema\\Exception\\InvalidArgumentException' => $vendorDir . '/justinrainbow/json-schema/src/JsonSchema/Exception/InvalidArgumentException.php',
    '_ContaoManager\\JsonSchema\\Exception\\InvalidConfigException' => $vendorDir . '/justinrainbow/json-schema/src/JsonSchema/Exception/InvalidConfigException.php',
    '_ContaoManager\\JsonSchema\\Exception\\InvalidSchemaException' => $vendorDir . '/justinrainbow/json-schema/src/JsonSchema/Exception/InvalidSchemaException.php',
    '_ContaoManager\\JsonSchema\\Exception\\InvalidSchemaMediaTypeException' => $vendorDir . '/justinrainbow/json-schema/src/JsonSchema/Exception/InvalidSchemaMediaTypeException.php',
    '_ContaoManager\\JsonSchema\\Exception\\InvalidSourceUriException' => $vendorDir . '/justinrainbow/json-schema/src/JsonSchema/Exception/InvalidSourceUriException.php',
    '_ContaoManager\\JsonSchema\\Exception\\JsonDecodingException' => $vendorDir . '/justinrainbow/json-schema/src/JsonSchema/Exception/JsonDecodingException.php',
    '_ContaoManager\\JsonSchema\\Exception\\ResourceNotFoundException' => $vendorDir . '/justinrainbow/json-schema/src/JsonSchema/Exception/ResourceNotFoundException.php',
    '_ContaoManager\\JsonSchema\\Exception\\RuntimeException' => $vendorDir . '/justinrainbow/json-schema/src/JsonSchema/Exception/RuntimeException.php',
    '_ContaoManager\\JsonSchema\\Exception\\UnresolvableJsonPointerException' => $vendorDir . '/justinrainbow/json-schema/src/JsonSchema/Exception/UnresolvableJsonPointerException.php',
    '_ContaoManager\\JsonSchema\\Exception\\UriResolverException' => $vendorDir . '/justinrainbow/json-schema/src/JsonSchema/Exception/UriResolverException.php',
    '_ContaoManager\\JsonSchema\\Exception\\ValidationException' => $vendorDir . '/justinrainbow/json-schema/src/JsonSchema/Exception/ValidationException.php',
    '_ContaoManager\\JsonSchema\\Iterator\\ObjectIterator' => $vendorDir . '/justinrainbow/json-schema/src/JsonSchema/Iterator/ObjectIterator.php',
    '_ContaoManager\\JsonSchema\\Rfc3339' => $vendorDir . '/justinrainbow/json-schema/src/JsonSchema/Rfc3339.php',
    '_ContaoManager\\JsonSchema\\SchemaStorage' => $vendorDir . '/justinrainbow/json-schema/src/JsonSchema/SchemaStorage.php',
    '_ContaoManager\\JsonSchema\\SchemaStorageInterface' => $vendorDir . '/justinrainbow/json-schema/src/JsonSchema/SchemaStorageInterface.php',
    '_ContaoManager\\JsonSchema\\Tool\\DeepComparer' => $vendorDir . '/justinrainbow/json-schema/src/JsonSchema/Tool/DeepComparer.php',
    '_ContaoManager\\JsonSchema\\Tool\\DeepCopy' => $vendorDir . '/justinrainbow/json-schema/src/JsonSchema/Tool/DeepCopy.php',
    '_ContaoManager\\JsonSchema\\Tool\\Validator\\RelativeReferenceValidator' => $vendorDir . '/justinrainbow/json-schema/src/JsonSchema/Tool/Validator/RelativeReferenceValidator.php',
    '_ContaoManager\\JsonSchema\\Tool\\Validator\\UriValidator' => $vendorDir . '/justinrainbow/json-schema/src/JsonSchema/Tool/Validator/UriValidator.php',
    '_ContaoManager\\JsonSchema\\UriResolverInterface' => $vendorDir . '/justinrainbow/json-schema/src/JsonSchema/UriResolverInterface.php',
    '_ContaoManager\\JsonSchema\\UriRetrieverInterface' => $vendorDir . '/justinrainbow/json-schema/src/JsonSchema/UriRetrieverInterface.php',
    '_ContaoManager\\JsonSchema\\Uri\\Retrievers\\AbstractRetriever' => $vendorDir . '/justinrainbow/json-schema/src/JsonSchema/Uri/Retrievers/AbstractRetriever.php',
    '_ContaoManager\\JsonSchema\\Uri\\Retrievers\\Curl' => $vendorDir . '/justinrainbow/json-schema/src/JsonSchema/Uri/Retrievers/Curl.php',
    '_ContaoManager\\JsonSchema\\Uri\\Retrievers\\FileGetContents' => $vendorDir . '/justinrainbow/json-schema/src/JsonSchema/Uri/Retrievers/FileGetContents.php',
    '_ContaoManager\\JsonSchema\\Uri\\Retrievers\\PredefinedArray' => $vendorDir . '/justinrainbow/json-schema/src/JsonSchema/Uri/Retrievers/PredefinedArray.php',
    '_ContaoManager\\JsonSchema\\Uri\\Retrievers\\UriRetrieverInterface' => $vendorDir . '/justinrainbow/json-schema/src/JsonSchema/Uri/Retrievers/UriRetrieverInterface.php',
    '_ContaoManager\\JsonSchema\\Uri\\UriResolver' => $vendorDir . '/justinrainbow/json-schema/src/JsonSchema/Uri/UriResolver.php',
    '_ContaoManager\\JsonSchema\\Uri\\UriRetriever' => $vendorDir . '/justinrainbow/json-schema/src/JsonSchema/Uri/UriRetriever.php',
    '_ContaoManager\\JsonSchema\\Validator' => $vendorDir . '/justinrainbow/json-schema/src/JsonSchema/Validator.php',
    '_ContaoManager\\Lcobucci\\Clock\\Clock' => $vendorDir . '/lcobucci/clock/src/Clock.php',
    '_ContaoManager\\Lcobucci\\Clock\\FrozenClock' => $vendorDir . '/lcobucci/clock/src/FrozenClock.php',
    '_ContaoManager\\Lcobucci\\Clock\\SystemClock' => $vendorDir . '/lcobucci/clock/src/SystemClock.php',
    '_ContaoManager\\MabeEnum\\Enum' => $vendorDir . '/marc-mabe/php-enum/src/Enum.php',
    '_ContaoManager\\MabeEnum\\EnumMap' => $vendorDir . '/marc-mabe/php-enum/src/EnumMap.php',
    '_ContaoManager\\MabeEnum\\EnumSerializableTrait' => $vendorDir . '/marc-mabe/php-enum/src/EnumSerializableTrait.php',
    '_ContaoManager\\MabeEnum\\EnumSet' => $vendorDir . '/marc-mabe/php-enum/src/EnumSet.php',
    '_ContaoManager\\Monolog\\Attribute\\AsMonologProcessor' => $vendorDir . '/monolog/monolog/src/Monolog/Attribute/AsMonologProcessor.php',
    '_ContaoManager\\Monolog\\Attribute\\WithMonologChannel' => $vendorDir . '/monolog/monolog/src/Monolog/Attribute/WithMonologChannel.php',
    '_ContaoManager\\Monolog\\DateTimeImmutable' => $vendorDir . '/monolog/monolog/src/Monolog/DateTimeImmutable.php',
    '_ContaoManager\\Monolog\\ErrorHandler' => $vendorDir . '/monolog/monolog/src/Monolog/ErrorHandler.php',
    '_ContaoManager\\Monolog\\Formatter\\ChromePHPFormatter' => $vendorDir . '/monolog/monolog/src/Monolog/Formatter/ChromePHPFormatter.php',
    '_ContaoManager\\Monolog\\Formatter\\ElasticaFormatter' => $vendorDir . '/monolog/monolog/src/Monolog/Formatter/ElasticaFormatter.php',
    '_ContaoManager\\Monolog\\Formatter\\ElasticsearchFormatter' => $vendorDir . '/monolog/monolog/src/Monolog/Formatter/ElasticsearchFormatter.php',
    '_ContaoManager\\Monolog\\Formatter\\FlowdockFormatter' => $vendorDir . '/monolog/monolog/src/Monolog/Formatter/FlowdockFormatter.php',
    '_ContaoManager\\Monolog\\Formatter\\FluentdFormatter' => $vendorDir . '/monolog/monolog/src/Monolog/Formatter/FluentdFormatter.php',
    '_ContaoManager\\Monolog\\Formatter\\FormatterInterface' => $vendorDir . '/monolog/monolog/src/Monolog/Formatter/FormatterInterface.php',
    '_ContaoManager\\Monolog\\Formatter\\GelfMessageFormatter' => $vendorDir . '/monolog/monolog/src/Monolog/Formatter/GelfMessageFormatter.php',
    '_ContaoManager\\Monolog\\Formatter\\GoogleCloudLoggingFormatter' => $vendorDir . '/monolog/monolog/src/Monolog/Formatter/GoogleCloudLoggingFormatter.php',
    '_ContaoManager\\Monolog\\Formatter\\HtmlFormatter' => $vendorDir . '/monolog/monolog/src/Monolog/Formatter/HtmlFormatter.php',
    '_ContaoManager\\Monolog\\Formatter\\JsonFormatter' => $vendorDir . '/monolog/monolog/src/Monolog/Formatter/JsonFormatter.php',
    '_ContaoManager\\Monolog\\Formatter\\LineFormatter' => $vendorDir . '/monolog/monolog/src/Monolog/Formatter/LineFormatter.php',
    '_ContaoManager\\Monolog\\Formatter\\LogglyFormatter' => $vendorDir . '/monolog/monolog/src/Monolog/Formatter/LogglyFormatter.php',
    '_ContaoManager\\Monolog\\Formatter\\LogmaticFormatter' => $vendorDir . '/monolog/monolog/src/Monolog/Formatter/LogmaticFormatter.php',
    '_ContaoManager\\Monolog\\Formatter\\LogstashFormatter' => $vendorDir . '/monolog/monolog/src/Monolog/Formatter/LogstashFormatter.php',
    '_ContaoManager\\Monolog\\Formatter\\MongoDBFormatter' => $vendorDir . '/monolog/monolog/src/Monolog/Formatter/MongoDBFormatter.php',
    '_ContaoManager\\Monolog\\Formatter\\NormalizerFormatter' => $vendorDir . '/monolog/monolog/src/Monolog/Formatter/NormalizerFormatter.php',
    '_ContaoManager\\Monolog\\Formatter\\ScalarFormatter' => $vendorDir . '/monolog/monolog/src/Monolog/Formatter/ScalarFormatter.php',
    '_ContaoManager\\Monolog\\Formatter\\SyslogFormatter' => $vendorDir . '/monolog/monolog/src/Monolog/Formatter/SyslogFormatter.php',
    '_ContaoManager\\Monolog\\Formatter\\WildfireFormatter' => $vendorDir . '/monolog/monolog/src/Monolog/Formatter/WildfireFormatter.php',
    '_ContaoManager\\Monolog\\Handler\\AbstractHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/AbstractHandler.php',
    '_ContaoManager\\Monolog\\Handler\\AbstractProcessingHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/AbstractProcessingHandler.php',
    '_ContaoManager\\Monolog\\Handler\\AbstractSyslogHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/AbstractSyslogHandler.php',
    '_ContaoManager\\Monolog\\Handler\\AmqpHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/AmqpHandler.php',
    '_ContaoManager\\Monolog\\Handler\\BrowserConsoleHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/BrowserConsoleHandler.php',
    '_ContaoManager\\Monolog\\Handler\\BufferHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/BufferHandler.php',
    '_ContaoManager\\Monolog\\Handler\\ChromePHPHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/ChromePHPHandler.php',
    '_ContaoManager\\Monolog\\Handler\\CouchDBHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/CouchDBHandler.php',
    '_ContaoManager\\Monolog\\Handler\\CubeHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/CubeHandler.php',
    '_ContaoManager\\Monolog\\Handler\\Curl\\Util' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/Curl/Util.php',
    '_ContaoManager\\Monolog\\Handler\\DeduplicationHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/DeduplicationHandler.php',
    '_ContaoManager\\Monolog\\Handler\\DoctrineCouchDBHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/DoctrineCouchDBHandler.php',
    '_ContaoManager\\Monolog\\Handler\\DynamoDbHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/DynamoDbHandler.php',
    '_ContaoManager\\Monolog\\Handler\\ElasticaHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/ElasticaHandler.php',
    '_ContaoManager\\Monolog\\Handler\\ElasticsearchHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/ElasticsearchHandler.php',
    '_ContaoManager\\Monolog\\Handler\\ErrorLogHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/ErrorLogHandler.php',
    '_ContaoManager\\Monolog\\Handler\\FallbackGroupHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/FallbackGroupHandler.php',
    '_ContaoManager\\Monolog\\Handler\\FilterHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/FilterHandler.php',
    '_ContaoManager\\Monolog\\Handler\\FingersCrossedHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/FingersCrossedHandler.php',
    '_ContaoManager\\Monolog\\Handler\\FingersCrossed\\ActivationStrategyInterface' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/FingersCrossed/ActivationStrategyInterface.php',
    '_ContaoManager\\Monolog\\Handler\\FingersCrossed\\ChannelLevelActivationStrategy' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/FingersCrossed/ChannelLevelActivationStrategy.php',
    '_ContaoManager\\Monolog\\Handler\\FingersCrossed\\ErrorLevelActivationStrategy' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/FingersCrossed/ErrorLevelActivationStrategy.php',
    '_ContaoManager\\Monolog\\Handler\\FirePHPHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/FirePHPHandler.php',
    '_ContaoManager\\Monolog\\Handler\\FleepHookHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/FleepHookHandler.php',
    '_ContaoManager\\Monolog\\Handler\\FlowdockHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/FlowdockHandler.php',
    '_ContaoManager\\Monolog\\Handler\\FormattableHandlerInterface' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/FormattableHandlerInterface.php',
    '_ContaoManager\\Monolog\\Handler\\FormattableHandlerTrait' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/FormattableHandlerTrait.php',
    '_ContaoManager\\Monolog\\Handler\\GelfHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/GelfHandler.php',
    '_ContaoManager\\Monolog\\Handler\\GroupHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/GroupHandler.php',
    '_ContaoManager\\Monolog\\Handler\\Handler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/Handler.php',
    '_ContaoManager\\Monolog\\Handler\\HandlerInterface' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/HandlerInterface.php',
    '_ContaoManager\\Monolog\\Handler\\HandlerWrapper' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/HandlerWrapper.php',
    '_ContaoManager\\Monolog\\Handler\\IFTTTHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/IFTTTHandler.php',
    '_ContaoManager\\Monolog\\Handler\\InsightOpsHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/InsightOpsHandler.php',
    '_ContaoManager\\Monolog\\Handler\\LogEntriesHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/LogEntriesHandler.php',
    '_ContaoManager\\Monolog\\Handler\\LogglyHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/LogglyHandler.php',
    '_ContaoManager\\Monolog\\Handler\\LogmaticHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/LogmaticHandler.php',
    '_ContaoManager\\Monolog\\Handler\\MailHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/MailHandler.php',
    '_ContaoManager\\Monolog\\Handler\\MandrillHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/MandrillHandler.php',
    '_ContaoManager\\Monolog\\Handler\\MissingExtensionException' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/MissingExtensionException.php',
    '_ContaoManager\\Monolog\\Handler\\MongoDBHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/MongoDBHandler.php',
    '_ContaoManager\\Monolog\\Handler\\NativeMailerHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/NativeMailerHandler.php',
    '_ContaoManager\\Monolog\\Handler\\NewRelicHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/NewRelicHandler.php',
    '_ContaoManager\\Monolog\\Handler\\NoopHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/NoopHandler.php',
    '_ContaoManager\\Monolog\\Handler\\NullHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/NullHandler.php',
    '_ContaoManager\\Monolog\\Handler\\OverflowHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/OverflowHandler.php',
    '_ContaoManager\\Monolog\\Handler\\PHPConsoleHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/PHPConsoleHandler.php',
    '_ContaoManager\\Monolog\\Handler\\ProcessHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/ProcessHandler.php',
    '_ContaoManager\\Monolog\\Handler\\ProcessableHandlerInterface' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/ProcessableHandlerInterface.php',
    '_ContaoManager\\Monolog\\Handler\\ProcessableHandlerTrait' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/ProcessableHandlerTrait.php',
    '_ContaoManager\\Monolog\\Handler\\PsrHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/PsrHandler.php',
    '_ContaoManager\\Monolog\\Handler\\PushoverHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/PushoverHandler.php',
    '_ContaoManager\\Monolog\\Handler\\RedisHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/RedisHandler.php',
    '_ContaoManager\\Monolog\\Handler\\RedisPubSubHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/RedisPubSubHandler.php',
    '_ContaoManager\\Monolog\\Handler\\RollbarHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/RollbarHandler.php',
    '_ContaoManager\\Monolog\\Handler\\RotatingFileHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/RotatingFileHandler.php',
    '_ContaoManager\\Monolog\\Handler\\SamplingHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/SamplingHandler.php',
    '_ContaoManager\\Monolog\\Handler\\SendGridHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/SendGridHandler.php',
    '_ContaoManager\\Monolog\\Handler\\SlackHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/SlackHandler.php',
    '_ContaoManager\\Monolog\\Handler\\SlackWebhookHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/SlackWebhookHandler.php',
    '_ContaoManager\\Monolog\\Handler\\Slack\\SlackRecord' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/Slack/SlackRecord.php',
    '_ContaoManager\\Monolog\\Handler\\SocketHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/SocketHandler.php',
    '_ContaoManager\\Monolog\\Handler\\SqsHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/SqsHandler.php',
    '_ContaoManager\\Monolog\\Handler\\StreamHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/StreamHandler.php',
    '_ContaoManager\\Monolog\\Handler\\SymfonyMailerHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/SymfonyMailerHandler.php',
    '_ContaoManager\\Monolog\\Handler\\SyslogHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/SyslogHandler.php',
    '_ContaoManager\\Monolog\\Handler\\SyslogUdpHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/SyslogUdpHandler.php',
    '_ContaoManager\\Monolog\\Handler\\SyslogUdp\\UdpSocket' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/SyslogUdp/UdpSocket.php',
    '_ContaoManager\\Monolog\\Handler\\TelegramBotHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/TelegramBotHandler.php',
    '_ContaoManager\\Monolog\\Handler\\TestHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/TestHandler.php',
    '_ContaoManager\\Monolog\\Handler\\WebRequestRecognizerTrait' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/WebRequestRecognizerTrait.php',
    '_ContaoManager\\Monolog\\Handler\\WhatFailureGroupHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/WhatFailureGroupHandler.php',
    '_ContaoManager\\Monolog\\Handler\\ZendMonitorHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/ZendMonitorHandler.php',
    '_ContaoManager\\Monolog\\JsonSerializableDateTimeImmutable' => $vendorDir . '/monolog/monolog/src/Monolog/JsonSerializableDateTimeImmutable.php',
    '_ContaoManager\\Monolog\\Level' => $vendorDir . '/monolog/monolog/src/Monolog/Level.php',
    '_ContaoManager\\Monolog\\LogRecord' => $vendorDir . '/monolog/monolog/src/Monolog/LogRecord.php',
    '_ContaoManager\\Monolog\\Logger' => $vendorDir . '/monolog/monolog/src/Monolog/Logger.php',
    '_ContaoManager\\Monolog\\Processor\\ClosureContextProcessor' => $vendorDir . '/monolog/monolog/src/Monolog/Processor/ClosureContextProcessor.php',
    '_ContaoManager\\Monolog\\Processor\\GitProcessor' => $vendorDir . '/monolog/monolog/src/Monolog/Processor/GitProcessor.php',
    '_ContaoManager\\Monolog\\Processor\\HostnameProcessor' => $vendorDir . '/monolog/monolog/src/Monolog/Processor/HostnameProcessor.php',
    '_ContaoManager\\Monolog\\Processor\\IntrospectionProcessor' => $vendorDir . '/monolog/monolog/src/Monolog/Processor/IntrospectionProcessor.php',
    '_ContaoManager\\Monolog\\Processor\\LoadAverageProcessor' => $vendorDir . '/monolog/monolog/src/Monolog/Processor/LoadAverageProcessor.php',
    '_ContaoManager\\Monolog\\Processor\\MemoryPeakUsageProcessor' => $vendorDir . '/monolog/monolog/src/Monolog/Processor/MemoryPeakUsageProcessor.php',
    '_ContaoManager\\Monolog\\Processor\\MemoryProcessor' => $vendorDir . '/monolog/monolog/src/Monolog/Processor/MemoryProcessor.php',
    '_ContaoManager\\Monolog\\Processor\\MemoryUsageProcessor' => $vendorDir . '/monolog/monolog/src/Monolog/Processor/MemoryUsageProcessor.php',
    '_ContaoManager\\Monolog\\Processor\\MercurialProcessor' => $vendorDir . '/monolog/monolog/src/Monolog/Processor/MercurialProcessor.php',
    '_ContaoManager\\Monolog\\Processor\\ProcessIdProcessor' => $vendorDir . '/monolog/monolog/src/Monolog/Processor/ProcessIdProcessor.php',
    '_ContaoManager\\Monolog\\Processor\\ProcessorInterface' => $vendorDir . '/monolog/monolog/src/Monolog/Processor/ProcessorInterface.php',
    '_ContaoManager\\Monolog\\Processor\\PsrLogMessageProcessor' => $vendorDir . '/monolog/monolog/src/Monolog/Processor/PsrLogMessageProcessor.php',
    '_ContaoManager\\Monolog\\Processor\\TagProcessor' => $vendorDir . '/monolog/monolog/src/Monolog/Processor/TagProcessor.php',
    '_ContaoManager\\Monolog\\Processor\\UidProcessor' => $vendorDir . '/monolog/monolog/src/Monolog/Processor/UidProcessor.php',
    '_ContaoManager\\Monolog\\Processor\\WebProcessor' => $vendorDir . '/monolog/monolog/src/Monolog/Processor/WebProcessor.php',
    '_ContaoManager\\Monolog\\Registry' => $vendorDir . '/monolog/monolog/src/Monolog/Registry.php',
    '_ContaoManager\\Monolog\\ResettableInterface' => $vendorDir . '/monolog/monolog/src/Monolog/ResettableInterface.php',
    '_ContaoManager\\Monolog\\SignalHandler' => $vendorDir . '/monolog/monolog/src/Monolog/SignalHandler.php',
    '_ContaoManager\\Monolog\\Test\\MonologTestCase' => $vendorDir . '/monolog/monolog/src/Monolog/Test/MonologTestCase.php',
    '_ContaoManager\\Monolog\\Test\\TestCase' => $vendorDir . '/monolog/monolog/src/Monolog/Test/TestCase.php',
    '_ContaoManager\\Monolog\\Utils' => $vendorDir . '/monolog/monolog/src/Monolog/Utils.php',
    '_ContaoManager\\OTPHP\\Exception\\InvalidLabelException' => $vendorDir . '/spomky-labs/otphp/src/Exception/InvalidLabelException.php',
    '_ContaoManager\\OTPHP\\Exception\\InvalidParameterException' => $vendorDir . '/spomky-labs/otphp/src/Exception/InvalidParameterException.php',
    '_ContaoManager\\OTPHP\\Exception\\InvalidProvisioningUriException' => $vendorDir . '/spomky-labs/otphp/src/Exception/InvalidProvisioningUriException.php',
    '_ContaoManager\\OTPHP\\Exception\\OTPExceptionInterface' => $vendorDir . '/spomky-labs/otphp/src/Exception/OTPExceptionInterface.php',
    '_ContaoManager\\OTPHP\\Exception\\ParameterNotFoundException' => $vendorDir . '/spomky-labs/otphp/src/Exception/ParameterNotFoundException.php',
    '_ContaoManager\\OTPHP\\Exception\\SecretDecodingException' => $vendorDir . '/spomky-labs/otphp/src/Exception/SecretDecodingException.php',
    '_ContaoManager\\OTPHP\\Factory' => $vendorDir . '/spomky-labs/otphp/src/Factory.php',
    '_ContaoManager\\OTPHP\\FactoryInterface' => $vendorDir . '/spomky-labs/otphp/src/FactoryInterface.php',
    '_ContaoManager\\OTPHP\\HOTP' => $vendorDir . '/spomky-labs/otphp/src/HOTP.php',
    '_ContaoManager\\OTPHP\\HOTPInterface' => $vendorDir . '/spomky-labs/otphp/src/HOTPInterface.php',
    '_ContaoManager\\OTPHP\\InternalClock' => $vendorDir . '/spomky-labs/otphp/src/InternalClock.php',
    '_ContaoManager\\OTPHP\\OTP' => $vendorDir . '/spomky-labs/otphp/src/OTP.php',
    '_ContaoManager\\OTPHP\\OTPInterface' => $vendorDir . '/spomky-labs/otphp/src/OTPInterface.php',
    '_ContaoManager\\OTPHP\\TOTP' => $vendorDir . '/spomky-labs/otphp/src/TOTP.php',
    '_ContaoManager\\OTPHP\\TOTPInterface' => $vendorDir . '/spomky-labs/otphp/src/TOTPInterface.php',
    '_ContaoManager\\OTPHP\\Url' => $vendorDir . '/spomky-labs/otphp/src/Url.php',
    '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\AbstractNodeVisitor' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/AbstractNodeVisitor.php',
    '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\Attribute' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/Attribute.php',
    '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\Comment' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/Comment.php',
    '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\ConstExpr\\ConstExprArrayItemNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/ConstExpr/ConstExprArrayItemNode.php',
    '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\ConstExpr\\ConstExprArrayNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/ConstExpr/ConstExprArrayNode.php',
    '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\ConstExpr\\ConstExprFalseNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/ConstExpr/ConstExprFalseNode.php',
    '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\ConstExpr\\ConstExprFloatNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/ConstExpr/ConstExprFloatNode.php',
    '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\ConstExpr\\ConstExprIntegerNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/ConstExpr/ConstExprIntegerNode.php',
    '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\ConstExpr\\ConstExprNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/ConstExpr/ConstExprNode.php',
    '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\ConstExpr\\ConstExprNullNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/ConstExpr/ConstExprNullNode.php',
    '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\ConstExpr\\ConstExprStringNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/ConstExpr/ConstExprStringNode.php',
    '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\ConstExpr\\ConstExprTrueNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/ConstExpr/ConstExprTrueNode.php',
    '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\ConstExpr\\ConstFetchNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/ConstExpr/ConstFetchNode.php',
    '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\ConstExpr\\DoctrineConstExprStringNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/ConstExpr/DoctrineConstExprStringNode.php',
    '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\Node' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/Node.php',
    '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\NodeAttributes' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/NodeAttributes.php',
    '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\NodeTraverser' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/NodeTraverser.php',
    '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\NodeVisitor' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/NodeVisitor.php',
    '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\NodeVisitor\\CloningVisitor' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/NodeVisitor/CloningVisitor.php',
    '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\PhpDoc\\AssertTagMethodValueNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/AssertTagMethodValueNode.php',
    '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\PhpDoc\\AssertTagPropertyValueNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/AssertTagPropertyValueNode.php',
    '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\PhpDoc\\AssertTagValueNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/AssertTagValueNode.php',
    '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\PhpDoc\\DeprecatedTagValueNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/DeprecatedTagValueNode.php',
    '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\PhpDoc\\Doctrine\\DoctrineAnnotation' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/Doctrine/DoctrineAnnotation.php',
    '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\PhpDoc\\Doctrine\\DoctrineArgument' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/Doctrine/DoctrineArgument.php',
    '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\PhpDoc\\Doctrine\\DoctrineArray' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/Doctrine/DoctrineArray.php',
    '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\PhpDoc\\Doctrine\\DoctrineArrayItem' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/Doctrine/DoctrineArrayItem.php',
    '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\PhpDoc\\Doctrine\\DoctrineTagValueNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/Doctrine/DoctrineTagValueNode.php',
    '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\PhpDoc\\ExtendsTagValueNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/ExtendsTagValueNode.php',
    '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\PhpDoc\\GenericTagValueNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/GenericTagValueNode.php',
    '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\PhpDoc\\ImplementsTagValueNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/ImplementsTagValueNode.php',
    '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\PhpDoc\\InvalidTagValueNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/InvalidTagValueNode.php',
    '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\PhpDoc\\MethodTagValueNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/MethodTagValueNode.php',
    '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\PhpDoc\\MethodTagValueParameterNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/MethodTagValueParameterNode.php',
    '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\PhpDoc\\MixinTagValueNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/MixinTagValueNode.php',
    '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\PhpDoc\\ParamClosureThisTagValueNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/ParamClosureThisTagValueNode.php',
    '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\PhpDoc\\ParamImmediatelyInvokedCallableTagValueNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/ParamImmediatelyInvokedCallableTagValueNode.php',
    '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\PhpDoc\\ParamLaterInvokedCallableTagValueNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/ParamLaterInvokedCallableTagValueNode.php',
    '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\PhpDoc\\ParamOutTagValueNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/ParamOutTagValueNode.php',
    '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\PhpDoc\\ParamTagValueNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/ParamTagValueNode.php',
    '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\PhpDoc\\PhpDocChildNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/PhpDocChildNode.php',
    '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\PhpDoc\\PhpDocNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/PhpDocNode.php',
    '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\PhpDoc\\PhpDocTagNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/PhpDocTagNode.php',
    '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\PhpDoc\\PhpDocTagValueNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/PhpDocTagValueNode.php',
    '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\PhpDoc\\PhpDocTextNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/PhpDocTextNode.php',
    '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\PhpDoc\\PropertyTagValueNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/PropertyTagValueNode.php',
    '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\PhpDoc\\PureUnlessCallableIsImpureTagValueNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/PureUnlessCallableIsImpureTagValueNode.php',
    '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\PhpDoc\\RequireExtendsTagValueNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/RequireExtendsTagValueNode.php',
    '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\PhpDoc\\RequireImplementsTagValueNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/RequireImplementsTagValueNode.php',
    '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\PhpDoc\\ReturnTagValueNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/ReturnTagValueNode.php',
    '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\PhpDoc\\SealedTagValueNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/SealedTagValueNode.php',
    '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\PhpDoc\\SelfOutTagValueNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/SelfOutTagValueNode.php',
    '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\PhpDoc\\TemplateTagValueNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/TemplateTagValueNode.php',
    '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\PhpDoc\\ThrowsTagValueNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/ThrowsTagValueNode.php',
    '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\PhpDoc\\TypeAliasImportTagValueNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/TypeAliasImportTagValueNode.php',
    '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\PhpDoc\\TypeAliasTagValueNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/TypeAliasTagValueNode.php',
    '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\PhpDoc\\TypelessParamTagValueNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/TypelessParamTagValueNode.php',
    '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\PhpDoc\\UsesTagValueNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/UsesTagValueNode.php',
    '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\PhpDoc\\VarTagValueNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/VarTagValueNode.php',
    '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\Type\\ArrayShapeItemNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/Type/ArrayShapeItemNode.php',
    '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\Type\\ArrayShapeNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/Type/ArrayShapeNode.php',
    '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\Type\\ArrayShapeUnsealedTypeNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/Type/ArrayShapeUnsealedTypeNode.php',
    '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\Type\\ArrayTypeNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/Type/ArrayTypeNode.php',
    '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\Type\\CallableTypeNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/Type/CallableTypeNode.php',
    '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\Type\\CallableTypeParameterNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/Type/CallableTypeParameterNode.php',
    '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\Type\\ConditionalTypeForParameterNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/Type/ConditionalTypeForParameterNode.php',
    '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\Type\\ConditionalTypeNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/Type/ConditionalTypeNode.php',
    '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\Type\\ConstTypeNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/Type/ConstTypeNode.php',
    '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\Type\\GenericTypeNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/Type/GenericTypeNode.php',
    '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\Type\\IdentifierTypeNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/Type/IdentifierTypeNode.php',
    '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\Type\\IntersectionTypeNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/Type/IntersectionTypeNode.php',
    '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\Type\\InvalidTypeNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/Type/InvalidTypeNode.php',
    '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\Type\\NullableTypeNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/Type/NullableTypeNode.php',
    '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\Type\\ObjectShapeItemNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/Type/ObjectShapeItemNode.php',
    '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\Type\\ObjectShapeNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/Type/ObjectShapeNode.php',
    '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\Type\\OffsetAccessTypeNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/Type/OffsetAccessTypeNode.php',
    '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\Type\\ThisTypeNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/Type/ThisTypeNode.php',
    '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\Type\\TypeNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/Type/TypeNode.php',
    '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\Type\\UnionTypeNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/Type/UnionTypeNode.php',
    '_ContaoManager\\PHPStan\\PhpDocParser\\Lexer\\Lexer' => $vendorDir . '/phpstan/phpdoc-parser/src/Lexer/Lexer.php',
    '_ContaoManager\\PHPStan\\PhpDocParser\\ParserConfig' => $vendorDir . '/phpstan/phpdoc-parser/src/ParserConfig.php',
    '_ContaoManager\\PHPStan\\PhpDocParser\\Parser\\ConstExprParser' => $vendorDir . '/phpstan/phpdoc-parser/src/Parser/ConstExprParser.php',
    '_ContaoManager\\PHPStan\\PhpDocParser\\Parser\\ParserException' => $vendorDir . '/phpstan/phpdoc-parser/src/Parser/ParserException.php',
    '_ContaoManager\\PHPStan\\PhpDocParser\\Parser\\PhpDocParser' => $vendorDir . '/phpstan/phpdoc-parser/src/Parser/PhpDocParser.php',
    '_ContaoManager\\PHPStan\\PhpDocParser\\Parser\\StringUnescaper' => $vendorDir . '/phpstan/phpdoc-parser/src/Parser/StringUnescaper.php',
    '_ContaoManager\\PHPStan\\PhpDocParser\\Parser\\TokenIterator' => $vendorDir . '/phpstan/phpdoc-parser/src/Parser/TokenIterator.php',
    '_ContaoManager\\PHPStan\\PhpDocParser\\Parser\\TypeParser' => $vendorDir . '/phpstan/phpdoc-parser/src/Parser/TypeParser.php',
    '_ContaoManager\\PHPStan\\PhpDocParser\\Printer\\DiffElem' => $vendorDir . '/phpstan/phpdoc-parser/src/Printer/DiffElem.php',
    '_ContaoManager\\PHPStan\\PhpDocParser\\Printer\\Differ' => $vendorDir . '/phpstan/phpdoc-parser/src/Printer/Differ.php',
    '_ContaoManager\\PHPStan\\PhpDocParser\\Printer\\Printer' => $vendorDir . '/phpstan/phpdoc-parser/src/Printer/Printer.php',
    '_ContaoManager\\ParagonIE\\ConstantTime\\Base32' => $vendorDir . '/paragonie/constant_time_encoding/src/Base32.php',
    '_ContaoManager\\ParagonIE\\ConstantTime\\Base32Hex' => $vendorDir . '/paragonie/constant_time_encoding/src/Base32Hex.php',
    '_ContaoManager\\ParagonIE\\ConstantTime\\Base64' => $vendorDir . '/paragonie/constant_time_encoding/src/Base64.php',
    '_ContaoManager\\ParagonIE\\ConstantTime\\Base64DotSlash' => $vendorDir . '/paragonie/constant_time_encoding/src/Base64DotSlash.php',
    '_ContaoManager\\ParagonIE\\ConstantTime\\Base64DotSlashOrdered' => $vendorDir . '/paragonie/constant_time_encoding/src/Base64DotSlashOrdered.php',
    '_ContaoManager\\ParagonIE\\ConstantTime\\Base64UrlSafe' => $vendorDir . '/paragonie/constant_time_encoding/src/Base64UrlSafe.php',
    '_ContaoManager\\ParagonIE\\ConstantTime\\Binary' => $vendorDir . '/paragonie/constant_time_encoding/src/Binary.php',
    '_ContaoManager\\ParagonIE\\ConstantTime\\EncoderInterface' => $vendorDir . '/paragonie/constant_time_encoding/src/EncoderInterface.php',
    '_ContaoManager\\ParagonIE\\ConstantTime\\Encoding' => $vendorDir . '/paragonie/constant_time_encoding/src/Encoding.php',
    '_ContaoManager\\ParagonIE\\ConstantTime\\Hex' => $vendorDir . '/paragonie/constant_time_encoding/src/Hex.php',
    '_ContaoManager\\ParagonIE\\ConstantTime\\RFC4648' => $vendorDir . '/paragonie/constant_time_encoding/src/RFC4648.php',
    '_ContaoManager\\Psr\\Cache\\CacheException' => $vendorDir . '/psr/cache/src/CacheException.php',
    '_ContaoManager\\Psr\\Cache\\CacheItemInterface' => $vendorDir . '/psr/cache/src/CacheItemInterface.php',
    '_ContaoManager\\Psr\\Cache\\CacheItemPoolInterface' => $vendorDir . '/psr/cache/src/CacheItemPoolInterface.php',
    '_ContaoManager\\Psr\\Cache\\InvalidArgumentException' => $vendorDir . '/psr/cache/src/InvalidArgumentException.php',
    '_ContaoManager\\Psr\\Clock\\ClockInterface' => $vendorDir . '/psr/clock/src/ClockInterface.php',
    '_ContaoManager\\Psr\\Container\\ContainerExceptionInterface' => $vendorDir . '/psr/container/src/ContainerExceptionInterface.php',
    '_ContaoManager\\Psr\\Container\\ContainerInterface' => $vendorDir . '/psr/container/src/ContainerInterface.php',
    '_ContaoManager\\Psr\\Container\\NotFoundExceptionInterface' => $vendorDir . '/psr/container/src/NotFoundExceptionInterface.php',
    '_ContaoManager\\Psr\\EventDispatcher\\EventDispatcherInterface' => $vendorDir . '/psr/event-dispatcher/src/EventDispatcherInterface.php',
    '_ContaoManager\\Psr\\EventDispatcher\\ListenerProviderInterface' => $vendorDir . '/psr/event-dispatcher/src/ListenerProviderInterface.php',
    '_ContaoManager\\Psr\\EventDispatcher\\StoppableEventInterface' => $vendorDir . '/psr/event-dispatcher/src/StoppableEventInterface.php',
    '_ContaoManager\\Psr\\Http\\Client\\ClientExceptionInterface' => $vendorDir . '/psr/http-client/src/ClientExceptionInterface.php',
    '_ContaoManager\\Psr\\Http\\Client\\ClientInterface' => $vendorDir . '/psr/http-client/src/ClientInterface.php',
    '_ContaoManager\\Psr\\Http\\Client\\NetworkExceptionInterface' => $vendorDir . '/psr/http-client/src/NetworkExceptionInterface.php',
    '_ContaoManager\\Psr\\Http\\Client\\RequestExceptionInterface' => $vendorDir . '/psr/http-client/src/RequestExceptionInterface.php',
    '_ContaoManager\\Psr\\Http\\Message\\MessageInterface' => $vendorDir . '/psr/http-message/src/MessageInterface.php',
    '_ContaoManager\\Psr\\Http\\Message\\RequestFactoryInterface' => $vendorDir . '/psr/http-factory/src/RequestFactoryInterface.php',
    '_ContaoManager\\Psr\\Http\\Message\\RequestInterface' => $vendorDir . '/psr/http-message/src/RequestInterface.php',
    '_ContaoManager\\Psr\\Http\\Message\\ResponseFactoryInterface' => $vendorDir . '/psr/http-factory/src/ResponseFactoryInterface.php',
    '_ContaoManager\\Psr\\Http\\Message\\ResponseInterface' => $vendorDir . '/psr/http-message/src/ResponseInterface.php',
    '_ContaoManager\\Psr\\Http\\Message\\ServerRequestFactoryInterface' => $vendorDir . '/psr/http-factory/src/ServerRequestFactoryInterface.php',
    '_ContaoManager\\Psr\\Http\\Message\\ServerRequestInterface' => $vendorDir . '/psr/http-message/src/ServerRequestInterface.php',
    '_ContaoManager\\Psr\\Http\\Message\\StreamFactoryInterface' => $vendorDir . '/psr/http-factory/src/StreamFactoryInterface.php',
    '_ContaoManager\\Psr\\Http\\Message\\StreamInterface' => $vendorDir . '/psr/http-message/src/StreamInterface.php',
    '_ContaoManager\\Psr\\Http\\Message\\UploadedFileFactoryInterface' => $vendorDir . '/psr/http-factory/src/UploadedFileFactoryInterface.php',
    '_ContaoManager\\Psr\\Http\\Message\\UploadedFileInterface' => $vendorDir . '/psr/http-message/src/UploadedFileInterface.php',
    '_ContaoManager\\Psr\\Http\\Message\\UriFactoryInterface' => $vendorDir . '/psr/http-factory/src/UriFactoryInterface.php',
    '_ContaoManager\\Psr\\Http\\Message\\UriInterface' => $vendorDir . '/psr/http-message/src/UriInterface.php',
    '_ContaoManager\\Psr\\Log\\AbstractLogger' => $vendorDir . '/psr/log/src/AbstractLogger.php',
    '_ContaoManager\\Psr\\Log\\InvalidArgumentException' => $vendorDir . '/psr/log/src/InvalidArgumentException.php',
    '_ContaoManager\\Psr\\Log\\LogLevel' => $vendorDir . '/psr/log/src/LogLevel.php',
    '_ContaoManager\\Psr\\Log\\LoggerAwareInterface' => $vendorDir . '/psr/log/src/LoggerAwareInterface.php',
    '_ContaoManager\\Psr\\Log\\LoggerAwareTrait' => $vendorDir . '/psr/log/src/LoggerAwareTrait.php',
    '_ContaoManager\\Psr\\Log\\LoggerInterface' => $vendorDir . '/psr/log/src/LoggerInterface.php',
    '_ContaoManager\\Psr\\Log\\LoggerTrait' => $vendorDir . '/psr/log/src/LoggerTrait.php',
    '_ContaoManager\\Psr\\Log\\NullLogger' => $vendorDir . '/psr/log/src/NullLogger.php',
    '_ContaoManager\\Ramsey\\Collection\\AbstractArray' => $vendorDir . '/ramsey/collection/src/AbstractArray.php',
    '_ContaoManager\\Ramsey\\Collection\\AbstractCollection' => $vendorDir . '/ramsey/collection/src/AbstractCollection.php',
    '_ContaoManager\\Ramsey\\Collection\\AbstractSet' => $vendorDir . '/ramsey/collection/src/AbstractSet.php',
    '_ContaoManager\\Ramsey\\Collection\\ArrayInterface' => $vendorDir . '/ramsey/collection/src/ArrayInterface.php',
    '_ContaoManager\\Ramsey\\Collection\\Collection' => $vendorDir . '/ramsey/collection/src/Collection.php',
    '_ContaoManager\\Ramsey\\Collection\\CollectionInterface' => $vendorDir . '/ramsey/collection/src/CollectionInterface.php',
    '_ContaoManager\\Ramsey\\Collection\\DoubleEndedQueue' => $vendorDir . '/ramsey/collection/src/DoubleEndedQueue.php',
    '_ContaoManager\\Ramsey\\Collection\\DoubleEndedQueueInterface' => $vendorDir . '/ramsey/collection/src/DoubleEndedQueueInterface.php',
    '_ContaoManager\\Ramsey\\Collection\\Exception\\CollectionException' => $vendorDir . '/ramsey/collection/src/Exception/CollectionException.php',
    '_ContaoManager\\Ramsey\\Collection\\Exception\\CollectionMismatchException' => $vendorDir . '/ramsey/collection/src/Exception/CollectionMismatchException.php',
    '_ContaoManager\\Ramsey\\Collection\\Exception\\InvalidArgumentException' => $vendorDir . '/ramsey/collection/src/Exception/InvalidArgumentException.php',
    '_ContaoManager\\Ramsey\\Collection\\Exception\\InvalidPropertyOrMethod' => $vendorDir . '/ramsey/collection/src/Exception/InvalidPropertyOrMethod.php',
    '_ContaoManager\\Ramsey\\Collection\\Exception\\NoSuchElementException' => $vendorDir . '/ramsey/collection/src/Exception/NoSuchElementException.php',
    '_ContaoManager\\Ramsey\\Collection\\Exception\\OutOfBoundsException' => $vendorDir . '/ramsey/collection/src/Exception/OutOfBoundsException.php',
    '_ContaoManager\\Ramsey\\Collection\\Exception\\UnsupportedOperationException' => $vendorDir . '/ramsey/collection/src/Exception/UnsupportedOperationException.php',
    '_ContaoManager\\Ramsey\\Collection\\GenericArray' => $vendorDir . '/ramsey/collection/src/GenericArray.php',
    '_ContaoManager\\Ramsey\\Collection\\Map\\AbstractMap' => $vendorDir . '/ramsey/collection/src/Map/AbstractMap.php',
    '_ContaoManager\\Ramsey\\Collection\\Map\\AbstractTypedMap' => $vendorDir . '/ramsey/collection/src/Map/AbstractTypedMap.php',
    '_ContaoManager\\Ramsey\\Collection\\Map\\AssociativeArrayMap' => $vendorDir . '/ramsey/collection/src/Map/AssociativeArrayMap.php',
    '_ContaoManager\\Ramsey\\Collection\\Map\\MapInterface' => $vendorDir . '/ramsey/collection/src/Map/MapInterface.php',
    '_ContaoManager\\Ramsey\\Collection\\Map\\NamedParameterMap' => $vendorDir . '/ramsey/collection/src/Map/NamedParameterMap.php',
    '_ContaoManager\\Ramsey\\Collection\\Map\\TypedMap' => $vendorDir . '/ramsey/collection/src/Map/TypedMap.php',
    '_ContaoManager\\Ramsey\\Collection\\Map\\TypedMapInterface' => $vendorDir . '/ramsey/collection/src/Map/TypedMapInterface.php',
    '_ContaoManager\\Ramsey\\Collection\\Queue' => $vendorDir . '/ramsey/collection/src/Queue.php',
    '_ContaoManager\\Ramsey\\Collection\\QueueInterface' => $vendorDir . '/ramsey/collection/src/QueueInterface.php',
    '_ContaoManager\\Ramsey\\Collection\\Set' => $vendorDir . '/ramsey/collection/src/Set.php',
    '_ContaoManager\\Ramsey\\Collection\\Sort' => $vendorDir . '/ramsey/collection/src/Sort.php',
    '_ContaoManager\\Ramsey\\Collection\\Tool\\TypeTrait' => $vendorDir . '/ramsey/collection/src/Tool/TypeTrait.php',
    '_ContaoManager\\Ramsey\\Collection\\Tool\\ValueExtractorTrait' => $vendorDir . '/ramsey/collection/src/Tool/ValueExtractorTrait.php',
    '_ContaoManager\\Ramsey\\Collection\\Tool\\ValueToStringTrait' => $vendorDir . '/ramsey/collection/src/Tool/ValueToStringTrait.php',
    '_ContaoManager\\Ramsey\\Uuid\\BinaryUtils' => $vendorDir . '/ramsey/uuid/src/BinaryUtils.php',
    '_ContaoManager\\Ramsey\\Uuid\\Builder\\BuilderCollection' => $vendorDir . '/ramsey/uuid/src/Builder/BuilderCollection.php',
    '_ContaoManager\\Ramsey\\Uuid\\Builder\\DefaultUuidBuilder' => $vendorDir . '/ramsey/uuid/src/Builder/DefaultUuidBuilder.php',
    '_ContaoManager\\Ramsey\\Uuid\\Builder\\DegradedUuidBuilder' => $vendorDir . '/ramsey/uuid/src/Builder/DegradedUuidBuilder.php',
    '_ContaoManager\\Ramsey\\Uuid\\Builder\\FallbackBuilder' => $vendorDir . '/ramsey/uuid/src/Builder/FallbackBuilder.php',
    '_ContaoManager\\Ramsey\\Uuid\\Builder\\UuidBuilderInterface' => $vendorDir . '/ramsey/uuid/src/Builder/UuidBuilderInterface.php',
    '_ContaoManager\\Ramsey\\Uuid\\Codec\\CodecInterface' => $vendorDir . '/ramsey/uuid/src/Codec/CodecInterface.php',
    '_ContaoManager\\Ramsey\\Uuid\\Codec\\GuidStringCodec' => $vendorDir . '/ramsey/uuid/src/Codec/GuidStringCodec.php',
    '_ContaoManager\\Ramsey\\Uuid\\Codec\\OrderedTimeCodec' => $vendorDir . '/ramsey/uuid/src/Codec/OrderedTimeCodec.php',
    '_ContaoManager\\Ramsey\\Uuid\\Codec\\StringCodec' => $vendorDir . '/ramsey/uuid/src/Codec/StringCodec.php',
    '_ContaoManager\\Ramsey\\Uuid\\Codec\\TimestampFirstCombCodec' => $vendorDir . '/ramsey/uuid/src/Codec/TimestampFirstCombCodec.php',
    '_ContaoManager\\Ramsey\\Uuid\\Codec\\TimestampLastCombCodec' => $vendorDir . '/ramsey/uuid/src/Codec/TimestampLastCombCodec.php',
    '_ContaoManager\\Ramsey\\Uuid\\Converter\\NumberConverterInterface' => $vendorDir . '/ramsey/uuid/src/Converter/NumberConverterInterface.php',
    '_ContaoManager\\Ramsey\\Uuid\\Converter\\Number\\BigNumberConverter' => $vendorDir . '/ramsey/uuid/src/Converter/Number/BigNumberConverter.php',
    '_ContaoManager\\Ramsey\\Uuid\\Converter\\Number\\DegradedNumberConverter' => $vendorDir . '/ramsey/uuid/src/Converter/Number/DegradedNumberConverter.php',
    '_ContaoManager\\Ramsey\\Uuid\\Converter\\Number\\GenericNumberConverter' => $vendorDir . '/ramsey/uuid/src/Converter/Number/GenericNumberConverter.php',
    '_ContaoManager\\Ramsey\\Uuid\\Converter\\TimeConverterInterface' => $vendorDir . '/ramsey/uuid/src/Converter/TimeConverterInterface.php',
    '_ContaoManager\\Ramsey\\Uuid\\Converter\\Time\\BigNumberTimeConverter' => $vendorDir . '/ramsey/uuid/src/Converter/Time/BigNumberTimeConverter.php',
    '_ContaoManager\\Ramsey\\Uuid\\Converter\\Time\\DegradedTimeConverter' => $vendorDir . '/ramsey/uuid/src/Converter/Time/DegradedTimeConverter.php',
    '_ContaoManager\\Ramsey\\Uuid\\Converter\\Time\\GenericTimeConverter' => $vendorDir . '/ramsey/uuid/src/Converter/Time/GenericTimeConverter.php',
    '_ContaoManager\\Ramsey\\Uuid\\Converter\\Time\\PhpTimeConverter' => $vendorDir . '/ramsey/uuid/src/Converter/Time/PhpTimeConverter.php',
    '_ContaoManager\\Ramsey\\Uuid\\Converter\\Time\\UnixTimeConverter' => $vendorDir . '/ramsey/uuid/src/Converter/Time/UnixTimeConverter.php',
    '_ContaoManager\\Ramsey\\Uuid\\DegradedUuid' => $vendorDir . '/ramsey/uuid/src/DegradedUuid.php',
    '_ContaoManager\\Ramsey\\Uuid\\DeprecatedUuidInterface' => $vendorDir . '/ramsey/uuid/src/DeprecatedUuidInterface.php',
    '_ContaoManager\\Ramsey\\Uuid\\DeprecatedUuidMethodsTrait' => $vendorDir . '/ramsey/uuid/src/DeprecatedUuidMethodsTrait.php',
    '_ContaoManager\\Ramsey\\Uuid\\Exception\\BuilderNotFoundException' => $vendorDir . '/ramsey/uuid/src/Exception/BuilderNotFoundException.php',
    '_ContaoManager\\Ramsey\\Uuid\\Exception\\DateTimeException' => $vendorDir . '/ramsey/uuid/src/Exception/DateTimeException.php',
    '_ContaoManager\\Ramsey\\Uuid\\Exception\\DceSecurityException' => $vendorDir . '/ramsey/uuid/src/Exception/DceSecurityException.php',
    '_ContaoManager\\Ramsey\\Uuid\\Exception\\InvalidArgumentException' => $vendorDir . '/ramsey/uuid/src/Exception/InvalidArgumentException.php',
    '_ContaoManager\\Ramsey\\Uuid\\Exception\\InvalidBytesException' => $vendorDir . '/ramsey/uuid/src/Exception/InvalidBytesException.php',
    '_ContaoManager\\Ramsey\\Uuid\\Exception\\InvalidUuidStringException' => $vendorDir . '/ramsey/uuid/src/Exception/InvalidUuidStringException.php',
    '_ContaoManager\\Ramsey\\Uuid\\Exception\\NameException' => $vendorDir . '/ramsey/uuid/src/Exception/NameException.php',
    '_ContaoManager\\Ramsey\\Uuid\\Exception\\NodeException' => $vendorDir . '/ramsey/uuid/src/Exception/NodeException.php',
    '_ContaoManager\\Ramsey\\Uuid\\Exception\\RandomSourceException' => $vendorDir . '/ramsey/uuid/src/Exception/RandomSourceException.php',
    '_ContaoManager\\Ramsey\\Uuid\\Exception\\TimeSourceException' => $vendorDir . '/ramsey/uuid/src/Exception/TimeSourceException.php',
    '_ContaoManager\\Ramsey\\Uuid\\Exception\\UnableToBuildUuidException' => $vendorDir . '/ramsey/uuid/src/Exception/UnableToBuildUuidException.php',
    '_ContaoManager\\Ramsey\\Uuid\\Exception\\UnsupportedOperationException' => $vendorDir . '/ramsey/uuid/src/Exception/UnsupportedOperationException.php',
    '_ContaoManager\\Ramsey\\Uuid\\Exception\\UuidExceptionInterface' => $vendorDir . '/ramsey/uuid/src/Exception/UuidExceptionInterface.php',
    '_ContaoManager\\Ramsey\\Uuid\\FeatureSet' => $vendorDir . '/ramsey/uuid/src/FeatureSet.php',
    '_ContaoManager\\Ramsey\\Uuid\\Fields\\FieldsInterface' => $vendorDir . '/ramsey/uuid/src/Fields/FieldsInterface.php',
    '_ContaoManager\\Ramsey\\Uuid\\Fields\\SerializableFieldsTrait' => $vendorDir . '/ramsey/uuid/src/Fields/SerializableFieldsTrait.php',
    '_ContaoManager\\Ramsey\\Uuid\\Generator\\CombGenerator' => $vendorDir . '/ramsey/uuid/src/Generator/CombGenerator.php',
    '_ContaoManager\\Ramsey\\Uuid\\Generator\\DceSecurityGenerator' => $vendorDir . '/ramsey/uuid/src/Generator/DceSecurityGenerator.php',
    '_ContaoManager\\Ramsey\\Uuid\\Generator\\DceSecurityGeneratorInterface' => $vendorDir . '/ramsey/uuid/src/Generator/DceSecurityGeneratorInterface.php',
    '_ContaoManager\\Ramsey\\Uuid\\Generator\\DefaultNameGenerator' => $vendorDir . '/ramsey/uuid/src/Generator/DefaultNameGenerator.php',
    '_ContaoManager\\Ramsey\\Uuid\\Generator\\DefaultTimeGenerator' => $vendorDir . '/ramsey/uuid/src/Generator/DefaultTimeGenerator.php',
    '_ContaoManager\\Ramsey\\Uuid\\Generator\\NameGeneratorFactory' => $vendorDir . '/ramsey/uuid/src/Generator/NameGeneratorFactory.php',
    '_ContaoManager\\Ramsey\\Uuid\\Generator\\NameGeneratorInterface' => $vendorDir . '/ramsey/uuid/src/Generator/NameGeneratorInterface.php',
    '_ContaoManager\\Ramsey\\Uuid\\Generator\\PeclUuidNameGenerator' => $vendorDir . '/ramsey/uuid/src/Generator/PeclUuidNameGenerator.php',
    '_ContaoManager\\Ramsey\\Uuid\\Generator\\PeclUuidRandomGenerator' => $vendorDir . '/ramsey/uuid/src/Generator/PeclUuidRandomGenerator.php',
    '_ContaoManager\\Ramsey\\Uuid\\Generator\\PeclUuidTimeGenerator' => $vendorDir . '/ramsey/uuid/src/Generator/PeclUuidTimeGenerator.php',
    '_ContaoManager\\Ramsey\\Uuid\\Generator\\RandomBytesGenerator' => $vendorDir . '/ramsey/uuid/src/Generator/RandomBytesGenerator.php',
    '_ContaoManager\\Ramsey\\Uuid\\Generator\\RandomGeneratorFactory' => $vendorDir . '/ramsey/uuid/src/Generator/RandomGeneratorFactory.php',
    '_ContaoManager\\Ramsey\\Uuid\\Generator\\RandomGeneratorInterface' => $vendorDir . '/ramsey/uuid/src/Generator/RandomGeneratorInterface.php',
    '_ContaoManager\\Ramsey\\Uuid\\Generator\\RandomLibAdapter' => $vendorDir . '/ramsey/uuid/src/Generator/RandomLibAdapter.php',
    '_ContaoManager\\Ramsey\\Uuid\\Generator\\TimeGeneratorFactory' => $vendorDir . '/ramsey/uuid/src/Generator/TimeGeneratorFactory.php',
    '_ContaoManager\\Ramsey\\Uuid\\Generator\\TimeGeneratorInterface' => $vendorDir . '/ramsey/uuid/src/Generator/TimeGeneratorInterface.php',
    '_ContaoManager\\Ramsey\\Uuid\\Generator\\UnixTimeGenerator' => $vendorDir . '/ramsey/uuid/src/Generator/UnixTimeGenerator.php',
    '_ContaoManager\\Ramsey\\Uuid\\Guid\\Fields' => $vendorDir . '/ramsey/uuid/src/Guid/Fields.php',
    '_ContaoManager\\Ramsey\\Uuid\\Guid\\Guid' => $vendorDir . '/ramsey/uuid/src/Guid/Guid.php',
    '_ContaoManager\\Ramsey\\Uuid\\Guid\\GuidBuilder' => $vendorDir . '/ramsey/uuid/src/Guid/GuidBuilder.php',
    '_ContaoManager\\Ramsey\\Uuid\\Lazy\\LazyUuidFromString' => $vendorDir . '/ramsey/uuid/src/Lazy/LazyUuidFromString.php',
    '_ContaoManager\\Ramsey\\Uuid\\Math\\BrickMathCalculator' => $vendorDir . '/ramsey/uuid/src/Math/BrickMathCalculator.php',
    '_ContaoManager\\Ramsey\\Uuid\\Math\\CalculatorInterface' => $vendorDir . '/ramsey/uuid/src/Math/CalculatorInterface.php',
    '_ContaoManager\\Ramsey\\Uuid\\Math\\RoundingMode' => $vendorDir . '/ramsey/uuid/src/Math/RoundingMode.php',
    '_ContaoManager\\Ramsey\\Uuid\\Nonstandard\\Fields' => $vendorDir . '/ramsey/uuid/src/Nonstandard/Fields.php',
    '_ContaoManager\\Ramsey\\Uuid\\Nonstandard\\Uuid' => $vendorDir . '/ramsey/uuid/src/Nonstandard/Uuid.php',
    '_ContaoManager\\Ramsey\\Uuid\\Nonstandard\\UuidBuilder' => $vendorDir . '/ramsey/uuid/src/Nonstandard/UuidBuilder.php',
    '_ContaoManager\\Ramsey\\Uuid\\Nonstandard\\UuidV6' => $vendorDir . '/ramsey/uuid/src/Nonstandard/UuidV6.php',
    '_ContaoManager\\Ramsey\\Uuid\\Provider\\DceSecurityProviderInterface' => $vendorDir . '/ramsey/uuid/src/Provider/DceSecurityProviderInterface.php',
    '_ContaoManager\\Ramsey\\Uuid\\Provider\\Dce\\SystemDceSecurityProvider' => $vendorDir . '/ramsey/uuid/src/Provider/Dce/SystemDceSecurityProvider.php',
    '_ContaoManager\\Ramsey\\Uuid\\Provider\\NodeProviderInterface' => $vendorDir . '/ramsey/uuid/src/Provider/NodeProviderInterface.php',
    '_ContaoManager\\Ramsey\\Uuid\\Provider\\Node\\FallbackNodeProvider' => $vendorDir . '/ramsey/uuid/src/Provider/Node/FallbackNodeProvider.php',
    '_ContaoManager\\Ramsey\\Uuid\\Provider\\Node\\NodeProviderCollection' => $vendorDir . '/ramsey/uuid/src/Provider/Node/NodeProviderCollection.php',
    '_ContaoManager\\Ramsey\\Uuid\\Provider\\Node\\RandomNodeProvider' => $vendorDir . '/ramsey/uuid/src/Provider/Node/RandomNodeProvider.php',
    '_ContaoManager\\Ramsey\\Uuid\\Provider\\Node\\StaticNodeProvider' => $vendorDir . '/ramsey/uuid/src/Provider/Node/StaticNodeProvider.php',
    '_ContaoManager\\Ramsey\\Uuid\\Provider\\Node\\SystemNodeProvider' => $vendorDir . '/ramsey/uuid/src/Provider/Node/SystemNodeProvider.php',
    '_ContaoManager\\Ramsey\\Uuid\\Provider\\TimeProviderInterface' => $vendorDir . '/ramsey/uuid/src/Provider/TimeProviderInterface.php',
    '_ContaoManager\\Ramsey\\Uuid\\Provider\\Time\\FixedTimeProvider' => $vendorDir . '/ramsey/uuid/src/Provider/Time/FixedTimeProvider.php',
    '_ContaoManager\\Ramsey\\Uuid\\Provider\\Time\\SystemTimeProvider' => $vendorDir . '/ramsey/uuid/src/Provider/Time/SystemTimeProvider.php',
    '_ContaoManager\\Ramsey\\Uuid\\Rfc4122\\Fields' => $vendorDir . '/ramsey/uuid/src/Rfc4122/Fields.php',
    '_ContaoManager\\Ramsey\\Uuid\\Rfc4122\\FieldsInterface' => $vendorDir . '/ramsey/uuid/src/Rfc4122/FieldsInterface.php',
    '_ContaoManager\\Ramsey\\Uuid\\Rfc4122\\MaxTrait' => $vendorDir . '/ramsey/uuid/src/Rfc4122/MaxTrait.php',
    '_ContaoManager\\Ramsey\\Uuid\\Rfc4122\\MaxUuid' => $vendorDir . '/ramsey/uuid/src/Rfc4122/MaxUuid.php',
    '_ContaoManager\\Ramsey\\Uuid\\Rfc4122\\NilTrait' => $vendorDir . '/ramsey/uuid/src/Rfc4122/NilTrait.php',
    '_ContaoManager\\Ramsey\\Uuid\\Rfc4122\\NilUuid' => $vendorDir . '/ramsey/uuid/src/Rfc4122/NilUuid.php',
    '_ContaoManager\\Ramsey\\Uuid\\Rfc4122\\TimeTrait' => $vendorDir . '/ramsey/uuid/src/Rfc4122/TimeTrait.php',
    '_ContaoManager\\Ramsey\\Uuid\\Rfc4122\\UuidBuilder' => $vendorDir . '/ramsey/uuid/src/Rfc4122/UuidBuilder.php',
    '_ContaoManager\\Ramsey\\Uuid\\Rfc4122\\UuidInterface' => $vendorDir . '/ramsey/uuid/src/Rfc4122/UuidInterface.php',
    '_ContaoManager\\Ramsey\\Uuid\\Rfc4122\\UuidV1' => $vendorDir . '/ramsey/uuid/src/Rfc4122/UuidV1.php',
    '_ContaoManager\\Ramsey\\Uuid\\Rfc4122\\UuidV2' => $vendorDir . '/ramsey/uuid/src/Rfc4122/UuidV2.php',
    '_ContaoManager\\Ramsey\\Uuid\\Rfc4122\\UuidV3' => $vendorDir . '/ramsey/uuid/src/Rfc4122/UuidV3.php',
    '_ContaoManager\\Ramsey\\Uuid\\Rfc4122\\UuidV4' => $vendorDir . '/ramsey/uuid/src/Rfc4122/UuidV4.php',
    '_ContaoManager\\Ramsey\\Uuid\\Rfc4122\\UuidV5' => $vendorDir . '/ramsey/uuid/src/Rfc4122/UuidV5.php',
    '_ContaoManager\\Ramsey\\Uuid\\Rfc4122\\UuidV6' => $vendorDir . '/ramsey/uuid/src/Rfc4122/UuidV6.php',
    '_ContaoManager\\Ramsey\\Uuid\\Rfc4122\\UuidV7' => $vendorDir . '/ramsey/uuid/src/Rfc4122/UuidV7.php',
    '_ContaoManager\\Ramsey\\Uuid\\Rfc4122\\UuidV8' => $vendorDir . '/ramsey/uuid/src/Rfc4122/UuidV8.php',
    '_ContaoManager\\Ramsey\\Uuid\\Rfc4122\\Validator' => $vendorDir . '/ramsey/uuid/src/Rfc4122/Validator.php',
    '_ContaoManager\\Ramsey\\Uuid\\Rfc4122\\VariantTrait' => $vendorDir . '/ramsey/uuid/src/Rfc4122/VariantTrait.php',
    '_ContaoManager\\Ramsey\\Uuid\\Rfc4122\\VersionTrait' => $vendorDir . '/ramsey/uuid/src/Rfc4122/VersionTrait.php',
    '_ContaoManager\\Ramsey\\Uuid\\Type\\Decimal' => $vendorDir . '/ramsey/uuid/src/Type/Decimal.php',
    '_ContaoManager\\Ramsey\\Uuid\\Type\\Hexadecimal' => $vendorDir . '/ramsey/uuid/src/Type/Hexadecimal.php',
    '_ContaoManager\\Ramsey\\Uuid\\Type\\Integer' => $vendorDir . '/ramsey/uuid/src/Type/Integer.php',
    '_ContaoManager\\Ramsey\\Uuid\\Type\\NumberInterface' => $vendorDir . '/ramsey/uuid/src/Type/NumberInterface.php',
    '_ContaoManager\\Ramsey\\Uuid\\Type\\Time' => $vendorDir . '/ramsey/uuid/src/Type/Time.php',
    '_ContaoManager\\Ramsey\\Uuid\\Type\\TypeInterface' => $vendorDir . '/ramsey/uuid/src/Type/TypeInterface.php',
    '_ContaoManager\\Ramsey\\Uuid\\Uuid' => $vendorDir . '/ramsey/uuid/src/Uuid.php',
    '_ContaoManager\\Ramsey\\Uuid\\UuidFactory' => $vendorDir . '/ramsey/uuid/src/UuidFactory.php',
    '_ContaoManager\\Ramsey\\Uuid\\UuidFactoryInterface' => $vendorDir . '/ramsey/uuid/src/UuidFactoryInterface.php',
    '_ContaoManager\\Ramsey\\Uuid\\UuidInterface' => $vendorDir . '/ramsey/uuid/src/UuidInterface.php',
    '_ContaoManager\\Ramsey\\Uuid\\Validator\\GenericValidator' => $vendorDir . '/ramsey/uuid/src/Validator/GenericValidator.php',
    '_ContaoManager\\Ramsey\\Uuid\\Validator\\ValidatorInterface' => $vendorDir . '/ramsey/uuid/src/Validator/ValidatorInterface.php',
    '_ContaoManager\\SebastianBergmann\\Diff\\Chunk' => $vendorDir . '/sebastian/diff/src/Chunk.php',
    '_ContaoManager\\SebastianBergmann\\Diff\\ConfigurationException' => $vendorDir . '/sebastian/diff/src/Exception/ConfigurationException.php',
    '_ContaoManager\\SebastianBergmann\\Diff\\Diff' => $vendorDir . '/sebastian/diff/src/Diff.php',
    '_ContaoManager\\SebastianBergmann\\Diff\\Differ' => $vendorDir . '/sebastian/diff/src/Differ.php',
    '_ContaoManager\\SebastianBergmann\\Diff\\Exception' => $vendorDir . '/sebastian/diff/src/Exception/Exception.php',
    '_ContaoManager\\SebastianBergmann\\Diff\\InvalidArgumentException' => $vendorDir . '/sebastian/diff/src/Exception/InvalidArgumentException.php',
    '_ContaoManager\\SebastianBergmann\\Diff\\Line' => $vendorDir . '/sebastian/diff/src/Line.php',
    '_ContaoManager\\SebastianBergmann\\Diff\\LongestCommonSubsequenceCalculator' => $vendorDir . '/sebastian/diff/src/LongestCommonSubsequenceCalculator.php',
    '_ContaoManager\\SebastianBergmann\\Diff\\MemoryEfficientLongestCommonSubsequenceCalculator' => $vendorDir . '/sebastian/diff/src/MemoryEfficientLongestCommonSubsequenceCalculator.php',
    '_ContaoManager\\SebastianBergmann\\Diff\\Output\\AbstractChunkOutputBuilder' => $vendorDir . '/sebastian/diff/src/Output/AbstractChunkOutputBuilder.php',
    '_ContaoManager\\SebastianBergmann\\Diff\\Output\\DiffOnlyOutputBuilder' => $vendorDir . '/sebastian/diff/src/Output/DiffOnlyOutputBuilder.php',
    '_ContaoManager\\SebastianBergmann\\Diff\\Output\\DiffOutputBuilderInterface' => $vendorDir . '/sebastian/diff/src/Output/DiffOutputBuilderInterface.php',
    '_ContaoManager\\SebastianBergmann\\Diff\\Output\\StrictUnifiedDiffOutputBuilder' => $vendorDir . '/sebastian/diff/src/Output/StrictUnifiedDiffOutputBuilder.php',
    '_ContaoManager\\SebastianBergmann\\Diff\\Output\\UnifiedDiffOutputBuilder' => $vendorDir . '/sebastian/diff/src/Output/UnifiedDiffOutputBuilder.php',
    '_ContaoManager\\SebastianBergmann\\Diff\\Parser' => $vendorDir . '/sebastian/diff/src/Parser.php',
    '_ContaoManager\\SebastianBergmann\\Diff\\TimeEfficientLongestCommonSubsequenceCalculator' => $vendorDir . '/sebastian/diff/src/TimeEfficientLongestCommonSubsequenceCalculator.php',
    '_ContaoManager\\Seld\\JsonLint\\DuplicateKeyException' => $vendorDir . '/seld/jsonlint/src/Seld/JsonLint/DuplicateKeyException.php',
    '_ContaoManager\\Seld\\JsonLint\\JsonParser' => $vendorDir . '/seld/jsonlint/src/Seld/JsonLint/JsonParser.php',
    '_ContaoManager\\Seld\\JsonLint\\Lexer' => $vendorDir . '/seld/jsonlint/src/Seld/JsonLint/Lexer.php',
    '_ContaoManager\\Seld\\JsonLint\\ParsingException' => $vendorDir . '/seld/jsonlint/src/Seld/JsonLint/ParsingException.php',
    '_ContaoManager\\Seld\\JsonLint\\Undefined' => $vendorDir . '/seld/jsonlint/src/Seld/JsonLint/Undefined.php',
    '_ContaoManager\\Seld\\PharUtils\\Linter' => $vendorDir . '/seld/phar-utils/src/Linter.php',
    '_ContaoManager\\Seld\\PharUtils\\Timestamps' => $vendorDir . '/seld/phar-utils/src/Timestamps.php',
    '_ContaoManager\\Seld\\Signal\\SignalHandler' => $vendorDir . '/seld/signal-handler/src/SignalHandler.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\ASN1\\Component\\Identifier' => $vendorDir . '/spomky-labs/pki-framework/src/ASN1/Component/Identifier.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\ASN1\\Component\\Length' => $vendorDir . '/spomky-labs/pki-framework/src/ASN1/Component/Length.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\ASN1\\DERData' => $vendorDir . '/spomky-labs/pki-framework/src/ASN1/DERData.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\ASN1\\Element' => $vendorDir . '/spomky-labs/pki-framework/src/ASN1/Element.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\ASN1\\Exception\\DecodeException' => $vendorDir . '/spomky-labs/pki-framework/src/ASN1/Exception/DecodeException.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\ASN1\\Feature\\ElementBase' => $vendorDir . '/spomky-labs/pki-framework/src/ASN1/Feature/ElementBase.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\ASN1\\Feature\\Encodable' => $vendorDir . '/spomky-labs/pki-framework/src/ASN1/Feature/Encodable.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\ASN1\\Feature\\Stringable' => $vendorDir . '/spomky-labs/pki-framework/src/ASN1/Feature/Stringable.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\ASN1\\Type\\BaseString' => $vendorDir . '/spomky-labs/pki-framework/src/ASN1/Type/BaseString.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\ASN1\\Type\\BaseTime' => $vendorDir . '/spomky-labs/pki-framework/src/ASN1/Type/BaseTime.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\ASN1\\Type\\Constructed\\ConstructedString' => $vendorDir . '/spomky-labs/pki-framework/src/ASN1/Type/Constructed/ConstructedString.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\ASN1\\Type\\Constructed\\Sequence' => $vendorDir . '/spomky-labs/pki-framework/src/ASN1/Type/Constructed/Sequence.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\ASN1\\Type\\Constructed\\Set' => $vendorDir . '/spomky-labs/pki-framework/src/ASN1/Type/Constructed/Set.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\ASN1\\Type\\PrimitiveString' => $vendorDir . '/spomky-labs/pki-framework/src/ASN1/Type/PrimitiveString.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\ASN1\\Type\\PrimitiveType' => $vendorDir . '/spomky-labs/pki-framework/src/ASN1/Type/PrimitiveType.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\ASN1\\Type\\Primitive\\BMPString' => $vendorDir . '/spomky-labs/pki-framework/src/ASN1/Type/Primitive/BMPString.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\ASN1\\Type\\Primitive\\BitString' => $vendorDir . '/spomky-labs/pki-framework/src/ASN1/Type/Primitive/BitString.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\ASN1\\Type\\Primitive\\Boolean' => $vendorDir . '/spomky-labs/pki-framework/src/ASN1/Type/Primitive/Boolean.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\ASN1\\Type\\Primitive\\CharacterString' => $vendorDir . '/spomky-labs/pki-framework/src/ASN1/Type/Primitive/CharacterString.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\ASN1\\Type\\Primitive\\EOC' => $vendorDir . '/spomky-labs/pki-framework/src/ASN1/Type/Primitive/EOC.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\ASN1\\Type\\Primitive\\Enumerated' => $vendorDir . '/spomky-labs/pki-framework/src/ASN1/Type/Primitive/Enumerated.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\ASN1\\Type\\Primitive\\GeneralString' => $vendorDir . '/spomky-labs/pki-framework/src/ASN1/Type/Primitive/GeneralString.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\ASN1\\Type\\Primitive\\GeneralizedTime' => $vendorDir . '/spomky-labs/pki-framework/src/ASN1/Type/Primitive/GeneralizedTime.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\ASN1\\Type\\Primitive\\GraphicString' => $vendorDir . '/spomky-labs/pki-framework/src/ASN1/Type/Primitive/GraphicString.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\ASN1\\Type\\Primitive\\IA5String' => $vendorDir . '/spomky-labs/pki-framework/src/ASN1/Type/Primitive/IA5String.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\ASN1\\Type\\Primitive\\Integer' => $vendorDir . '/spomky-labs/pki-framework/src/ASN1/Type/Primitive/Integer.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\ASN1\\Type\\Primitive\\NullType' => $vendorDir . '/spomky-labs/pki-framework/src/ASN1/Type/Primitive/NullType.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\ASN1\\Type\\Primitive\\Number' => $vendorDir . '/spomky-labs/pki-framework/src/ASN1/Type/Primitive/Number.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\ASN1\\Type\\Primitive\\NumericString' => $vendorDir . '/spomky-labs/pki-framework/src/ASN1/Type/Primitive/NumericString.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\ASN1\\Type\\Primitive\\ObjectDescriptor' => $vendorDir . '/spomky-labs/pki-framework/src/ASN1/Type/Primitive/ObjectDescriptor.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\ASN1\\Type\\Primitive\\ObjectIdentifier' => $vendorDir . '/spomky-labs/pki-framework/src/ASN1/Type/Primitive/ObjectIdentifier.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\ASN1\\Type\\Primitive\\OctetString' => $vendorDir . '/spomky-labs/pki-framework/src/ASN1/Type/Primitive/OctetString.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\ASN1\\Type\\Primitive\\PrintableString' => $vendorDir . '/spomky-labs/pki-framework/src/ASN1/Type/Primitive/PrintableString.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\ASN1\\Type\\Primitive\\Real' => $vendorDir . '/spomky-labs/pki-framework/src/ASN1/Type/Primitive/Real.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\ASN1\\Type\\Primitive\\RelativeOID' => $vendorDir . '/spomky-labs/pki-framework/src/ASN1/Type/Primitive/RelativeOID.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\ASN1\\Type\\Primitive\\T61String' => $vendorDir . '/spomky-labs/pki-framework/src/ASN1/Type/Primitive/T61String.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\ASN1\\Type\\Primitive\\UTCTime' => $vendorDir . '/spomky-labs/pki-framework/src/ASN1/Type/Primitive/UTCTime.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\ASN1\\Type\\Primitive\\UTF8String' => $vendorDir . '/spomky-labs/pki-framework/src/ASN1/Type/Primitive/UTF8String.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\ASN1\\Type\\Primitive\\UniversalString' => $vendorDir . '/spomky-labs/pki-framework/src/ASN1/Type/Primitive/UniversalString.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\ASN1\\Type\\Primitive\\VideotexString' => $vendorDir . '/spomky-labs/pki-framework/src/ASN1/Type/Primitive/VideotexString.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\ASN1\\Type\\Primitive\\VisibleString' => $vendorDir . '/spomky-labs/pki-framework/src/ASN1/Type/Primitive/VisibleString.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\ASN1\\Type\\StringType' => $vendorDir . '/spomky-labs/pki-framework/src/ASN1/Type/StringType.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\ASN1\\Type\\Structure' => $vendorDir . '/spomky-labs/pki-framework/src/ASN1/Type/Structure.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\ASN1\\Type\\TaggedType' => $vendorDir . '/spomky-labs/pki-framework/src/ASN1/Type/TaggedType.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\ASN1\\Type\\Tagged\\ApplicationType' => $vendorDir . '/spomky-labs/pki-framework/src/ASN1/Type/Tagged/ApplicationType.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\ASN1\\Type\\Tagged\\ContextSpecificType' => $vendorDir . '/spomky-labs/pki-framework/src/ASN1/Type/Tagged/ContextSpecificType.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\ASN1\\Type\\Tagged\\DERTaggedType' => $vendorDir . '/spomky-labs/pki-framework/src/ASN1/Type/Tagged/DERTaggedType.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\ASN1\\Type\\Tagged\\ExplicitTagging' => $vendorDir . '/spomky-labs/pki-framework/src/ASN1/Type/Tagged/ExplicitTagging.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\ASN1\\Type\\Tagged\\ExplicitlyTaggedType' => $vendorDir . '/spomky-labs/pki-framework/src/ASN1/Type/Tagged/ExplicitlyTaggedType.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\ASN1\\Type\\Tagged\\ImplicitTagging' => $vendorDir . '/spomky-labs/pki-framework/src/ASN1/Type/Tagged/ImplicitTagging.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\ASN1\\Type\\Tagged\\ImplicitlyTaggedType' => $vendorDir . '/spomky-labs/pki-framework/src/ASN1/Type/Tagged/ImplicitlyTaggedType.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\ASN1\\Type\\Tagged\\PrivateType' => $vendorDir . '/spomky-labs/pki-framework/src/ASN1/Type/Tagged/PrivateType.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\ASN1\\Type\\Tagged\\TaggedTypeWrap' => $vendorDir . '/spomky-labs/pki-framework/src/ASN1/Type/Tagged/TaggedTypeWrap.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\ASN1\\Type\\TimeType' => $vendorDir . '/spomky-labs/pki-framework/src/ASN1/Type/TimeType.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\ASN1\\Type\\UniversalClass' => $vendorDir . '/spomky-labs/pki-framework/src/ASN1/Type/UniversalClass.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\ASN1\\Type\\UnspecifiedType' => $vendorDir . '/spomky-labs/pki-framework/src/ASN1/Type/UnspecifiedType.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\ASN1\\Util\\BigInt' => $vendorDir . '/spomky-labs/pki-framework/src/ASN1/Util/BigInt.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\ASN1\\Util\\Flags' => $vendorDir . '/spomky-labs/pki-framework/src/ASN1/Util/Flags.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\CryptoBridge\\Crypto' => $vendorDir . '/spomky-labs/pki-framework/src/CryptoBridge/Crypto.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\CryptoBridge\\Crypto\\OpenSSLCrypto' => $vendorDir . '/spomky-labs/pki-framework/src/CryptoBridge/Crypto/OpenSSLCrypto.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\CryptoEncoding\\PEM' => $vendorDir . '/spomky-labs/pki-framework/src/CryptoEncoding/PEM.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\CryptoEncoding\\PEMBundle' => $vendorDir . '/spomky-labs/pki-framework/src/CryptoEncoding/PEMBundle.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\AlgorithmIdentifier\\AlgorithmIdentifier' => $vendorDir . '/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/AlgorithmIdentifier.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\AlgorithmIdentifier\\AlgorithmIdentifierFactory' => $vendorDir . '/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/AlgorithmIdentifierFactory.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\AlgorithmIdentifier\\AlgorithmIdentifierProvider' => $vendorDir . '/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/AlgorithmIdentifierProvider.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\AlgorithmIdentifier\\Asymmetric\\ECPublicKeyAlgorithmIdentifier' => $vendorDir . '/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Asymmetric/ECPublicKeyAlgorithmIdentifier.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\AlgorithmIdentifier\\Asymmetric\\Ed25519AlgorithmIdentifier' => $vendorDir . '/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Asymmetric/Ed25519AlgorithmIdentifier.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\AlgorithmIdentifier\\Asymmetric\\Ed448AlgorithmIdentifier' => $vendorDir . '/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Asymmetric/Ed448AlgorithmIdentifier.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\AlgorithmIdentifier\\Asymmetric\\RFC8410EdAlgorithmIdentifier' => $vendorDir . '/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Asymmetric/RFC8410EdAlgorithmIdentifier.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\AlgorithmIdentifier\\Asymmetric\\RFC8410XAlgorithmIdentifier' => $vendorDir . '/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Asymmetric/RFC8410XAlgorithmIdentifier.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\AlgorithmIdentifier\\Asymmetric\\RSAEncryptionAlgorithmIdentifier' => $vendorDir . '/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Asymmetric/RSAEncryptionAlgorithmIdentifier.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\AlgorithmIdentifier\\Asymmetric\\RSAPSSSSAEncryptionAlgorithmIdentifier' => $vendorDir . '/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Asymmetric/RSAPSSSSAEncryptionAlgorithmIdentifier.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\AlgorithmIdentifier\\Asymmetric\\X25519AlgorithmIdentifier' => $vendorDir . '/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Asymmetric/X25519AlgorithmIdentifier.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\AlgorithmIdentifier\\Asymmetric\\X448AlgorithmIdentifier' => $vendorDir . '/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Asymmetric/X448AlgorithmIdentifier.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\AlgorithmIdentifier\\Cipher\\AES128CBCAlgorithmIdentifier' => $vendorDir . '/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Cipher/AES128CBCAlgorithmIdentifier.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\AlgorithmIdentifier\\Cipher\\AES192CBCAlgorithmIdentifier' => $vendorDir . '/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Cipher/AES192CBCAlgorithmIdentifier.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\AlgorithmIdentifier\\Cipher\\AES256CBCAlgorithmIdentifier' => $vendorDir . '/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Cipher/AES256CBCAlgorithmIdentifier.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\AlgorithmIdentifier\\Cipher\\AESCBCAlgorithmIdentifier' => $vendorDir . '/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Cipher/AESCBCAlgorithmIdentifier.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\AlgorithmIdentifier\\Cipher\\BlockCipherAlgorithmIdentifier' => $vendorDir . '/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Cipher/BlockCipherAlgorithmIdentifier.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\AlgorithmIdentifier\\Cipher\\CipherAlgorithmIdentifier' => $vendorDir . '/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Cipher/CipherAlgorithmIdentifier.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\AlgorithmIdentifier\\Cipher\\DESCBCAlgorithmIdentifier' => $vendorDir . '/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Cipher/DESCBCAlgorithmIdentifier.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\AlgorithmIdentifier\\Cipher\\DESEDE3CBCAlgorithmIdentifier' => $vendorDir . '/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Cipher/DESEDE3CBCAlgorithmIdentifier.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\AlgorithmIdentifier\\Cipher\\RC2CBCAlgorithmIdentifier' => $vendorDir . '/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Cipher/RC2CBCAlgorithmIdentifier.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\AlgorithmIdentifier\\Feature\\AlgorithmIdentifierType' => $vendorDir . '/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Feature/AlgorithmIdentifierType.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\AlgorithmIdentifier\\Feature\\AsymmetricCryptoAlgorithmIdentifier' => $vendorDir . '/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Feature/AsymmetricCryptoAlgorithmIdentifier.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\AlgorithmIdentifier\\Feature\\EncryptionAlgorithmIdentifier' => $vendorDir . '/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Feature/EncryptionAlgorithmIdentifier.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\AlgorithmIdentifier\\Feature\\HashAlgorithmIdentifier' => $vendorDir . '/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Feature/HashAlgorithmIdentifier.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\AlgorithmIdentifier\\Feature\\PRFAlgorithmIdentifier' => $vendorDir . '/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Feature/PRFAlgorithmIdentifier.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\AlgorithmIdentifier\\Feature\\SignatureAlgorithmIdentifier' => $vendorDir . '/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Feature/SignatureAlgorithmIdentifier.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\AlgorithmIdentifier\\GenericAlgorithmIdentifier' => $vendorDir . '/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/GenericAlgorithmIdentifier.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\AlgorithmIdentifier\\Hash\\HMACWithSHA1AlgorithmIdentifier' => $vendorDir . '/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Hash/HMACWithSHA1AlgorithmIdentifier.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\AlgorithmIdentifier\\Hash\\HMACWithSHA224AlgorithmIdentifier' => $vendorDir . '/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Hash/HMACWithSHA224AlgorithmIdentifier.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\AlgorithmIdentifier\\Hash\\HMACWithSHA256AlgorithmIdentifier' => $vendorDir . '/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Hash/HMACWithSHA256AlgorithmIdentifier.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\AlgorithmIdentifier\\Hash\\HMACWithSHA384AlgorithmIdentifier' => $vendorDir . '/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Hash/HMACWithSHA384AlgorithmIdentifier.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\AlgorithmIdentifier\\Hash\\HMACWithSHA512AlgorithmIdentifier' => $vendorDir . '/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Hash/HMACWithSHA512AlgorithmIdentifier.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\AlgorithmIdentifier\\Hash\\MD5AlgorithmIdentifier' => $vendorDir . '/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Hash/MD5AlgorithmIdentifier.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\AlgorithmIdentifier\\Hash\\RFC4231HMACAlgorithmIdentifier' => $vendorDir . '/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Hash/RFC4231HMACAlgorithmIdentifier.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\AlgorithmIdentifier\\Hash\\SHA1AlgorithmIdentifier' => $vendorDir . '/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Hash/SHA1AlgorithmIdentifier.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\AlgorithmIdentifier\\Hash\\SHA224AlgorithmIdentifier' => $vendorDir . '/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Hash/SHA224AlgorithmIdentifier.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\AlgorithmIdentifier\\Hash\\SHA256AlgorithmIdentifier' => $vendorDir . '/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Hash/SHA256AlgorithmIdentifier.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\AlgorithmIdentifier\\Hash\\SHA2AlgorithmIdentifier' => $vendorDir . '/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Hash/SHA2AlgorithmIdentifier.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\AlgorithmIdentifier\\Hash\\SHA384AlgorithmIdentifier' => $vendorDir . '/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Hash/SHA384AlgorithmIdentifier.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\AlgorithmIdentifier\\Hash\\SHA512AlgorithmIdentifier' => $vendorDir . '/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Hash/SHA512AlgorithmIdentifier.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\AlgorithmIdentifier\\Signature\\ECDSAWithSHA1AlgorithmIdentifier' => $vendorDir . '/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Signature/ECDSAWithSHA1AlgorithmIdentifier.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\AlgorithmIdentifier\\Signature\\ECDSAWithSHA224AlgorithmIdentifier' => $vendorDir . '/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Signature/ECDSAWithSHA224AlgorithmIdentifier.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\AlgorithmIdentifier\\Signature\\ECDSAWithSHA256AlgorithmIdentifier' => $vendorDir . '/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Signature/ECDSAWithSHA256AlgorithmIdentifier.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\AlgorithmIdentifier\\Signature\\ECDSAWithSHA384AlgorithmIdentifier' => $vendorDir . '/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Signature/ECDSAWithSHA384AlgorithmIdentifier.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\AlgorithmIdentifier\\Signature\\ECDSAWithSHA512AlgorithmIdentifier' => $vendorDir . '/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Signature/ECDSAWithSHA512AlgorithmIdentifier.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\AlgorithmIdentifier\\Signature\\ECSignatureAlgorithmIdentifier' => $vendorDir . '/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Signature/ECSignatureAlgorithmIdentifier.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\AlgorithmIdentifier\\Signature\\MD2WithRSAEncryptionAlgorithmIdentifier' => $vendorDir . '/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Signature/MD2WithRSAEncryptionAlgorithmIdentifier.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\AlgorithmIdentifier\\Signature\\MD4WithRSAEncryptionAlgorithmIdentifier' => $vendorDir . '/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Signature/MD4WithRSAEncryptionAlgorithmIdentifier.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\AlgorithmIdentifier\\Signature\\MD5WithRSAEncryptionAlgorithmIdentifier' => $vendorDir . '/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Signature/MD5WithRSAEncryptionAlgorithmIdentifier.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\AlgorithmIdentifier\\Signature\\RFC3279RSASignatureAlgorithmIdentifier' => $vendorDir . '/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Signature/RFC3279RSASignatureAlgorithmIdentifier.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\AlgorithmIdentifier\\Signature\\RFC4055RSASignatureAlgorithmIdentifier' => $vendorDir . '/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Signature/RFC4055RSASignatureAlgorithmIdentifier.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\AlgorithmIdentifier\\Signature\\RSASignatureAlgorithmIdentifier' => $vendorDir . '/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Signature/RSASignatureAlgorithmIdentifier.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\AlgorithmIdentifier\\Signature\\SHA1WithRSAEncryptionAlgorithmIdentifier' => $vendorDir . '/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Signature/SHA1WithRSAEncryptionAlgorithmIdentifier.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\AlgorithmIdentifier\\Signature\\SHA224WithRSAEncryptionAlgorithmIdentifier' => $vendorDir . '/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Signature/SHA224WithRSAEncryptionAlgorithmIdentifier.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\AlgorithmIdentifier\\Signature\\SHA256WithRSAEncryptionAlgorithmIdentifier' => $vendorDir . '/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Signature/SHA256WithRSAEncryptionAlgorithmIdentifier.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\AlgorithmIdentifier\\Signature\\SHA384WithRSAEncryptionAlgorithmIdentifier' => $vendorDir . '/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Signature/SHA384WithRSAEncryptionAlgorithmIdentifier.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\AlgorithmIdentifier\\Signature\\SHA512WithRSAEncryptionAlgorithmIdentifier' => $vendorDir . '/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Signature/SHA512WithRSAEncryptionAlgorithmIdentifier.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\AlgorithmIdentifier\\SpecificAlgorithmIdentifier' => $vendorDir . '/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/SpecificAlgorithmIdentifier.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\Asymmetric\\Attribute\\OneAsymmetricKeyAttributes' => $vendorDir . '/spomky-labs/pki-framework/src/CryptoTypes/Asymmetric/Attribute/OneAsymmetricKeyAttributes.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\Asymmetric\\EC\\ECConversion' => $vendorDir . '/spomky-labs/pki-framework/src/CryptoTypes/Asymmetric/EC/ECConversion.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\Asymmetric\\EC\\ECPrivateKey' => $vendorDir . '/spomky-labs/pki-framework/src/CryptoTypes/Asymmetric/EC/ECPrivateKey.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\Asymmetric\\EC\\ECPublicKey' => $vendorDir . '/spomky-labs/pki-framework/src/CryptoTypes/Asymmetric/EC/ECPublicKey.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\Asymmetric\\OneAsymmetricKey' => $vendorDir . '/spomky-labs/pki-framework/src/CryptoTypes/Asymmetric/OneAsymmetricKey.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\Asymmetric\\PrivateKey' => $vendorDir . '/spomky-labs/pki-framework/src/CryptoTypes/Asymmetric/PrivateKey.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\Asymmetric\\PrivateKeyInfo' => $vendorDir . '/spomky-labs/pki-framework/src/CryptoTypes/Asymmetric/PrivateKeyInfo.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\Asymmetric\\PublicKey' => $vendorDir . '/spomky-labs/pki-framework/src/CryptoTypes/Asymmetric/PublicKey.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\Asymmetric\\PublicKeyInfo' => $vendorDir . '/spomky-labs/pki-framework/src/CryptoTypes/Asymmetric/PublicKeyInfo.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\Asymmetric\\RFC8410\\Curve25519\\Curve25519PrivateKey' => $vendorDir . '/spomky-labs/pki-framework/src/CryptoTypes/Asymmetric/RFC8410/Curve25519/Curve25519PrivateKey.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\Asymmetric\\RFC8410\\Curve25519\\Curve25519PublicKey' => $vendorDir . '/spomky-labs/pki-framework/src/CryptoTypes/Asymmetric/RFC8410/Curve25519/Curve25519PublicKey.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\Asymmetric\\RFC8410\\Curve25519\\Ed25519PrivateKey' => $vendorDir . '/spomky-labs/pki-framework/src/CryptoTypes/Asymmetric/RFC8410/Curve25519/Ed25519PrivateKey.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\Asymmetric\\RFC8410\\Curve25519\\Ed25519PublicKey' => $vendorDir . '/spomky-labs/pki-framework/src/CryptoTypes/Asymmetric/RFC8410/Curve25519/Ed25519PublicKey.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\Asymmetric\\RFC8410\\Curve25519\\X25519PrivateKey' => $vendorDir . '/spomky-labs/pki-framework/src/CryptoTypes/Asymmetric/RFC8410/Curve25519/X25519PrivateKey.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\Asymmetric\\RFC8410\\Curve25519\\X25519PublicKey' => $vendorDir . '/spomky-labs/pki-framework/src/CryptoTypes/Asymmetric/RFC8410/Curve25519/X25519PublicKey.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\Asymmetric\\RFC8410\\Curve448\\Ed448PrivateKey' => $vendorDir . '/spomky-labs/pki-framework/src/CryptoTypes/Asymmetric/RFC8410/Curve448/Ed448PrivateKey.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\Asymmetric\\RFC8410\\Curve448\\Ed448PublicKey' => $vendorDir . '/spomky-labs/pki-framework/src/CryptoTypes/Asymmetric/RFC8410/Curve448/Ed448PublicKey.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\Asymmetric\\RFC8410\\Curve448\\X448PrivateKey' => $vendorDir . '/spomky-labs/pki-framework/src/CryptoTypes/Asymmetric/RFC8410/Curve448/X448PrivateKey.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\Asymmetric\\RFC8410\\Curve448\\X448PublicKey' => $vendorDir . '/spomky-labs/pki-framework/src/CryptoTypes/Asymmetric/RFC8410/Curve448/X448PublicKey.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\Asymmetric\\RFC8410\\RFC8410PrivateKey' => $vendorDir . '/spomky-labs/pki-framework/src/CryptoTypes/Asymmetric/RFC8410/RFC8410PrivateKey.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\Asymmetric\\RFC8410\\RFC8410PublicKey' => $vendorDir . '/spomky-labs/pki-framework/src/CryptoTypes/Asymmetric/RFC8410/RFC8410PublicKey.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\Asymmetric\\RSA\\RSAPrivateKey' => $vendorDir . '/spomky-labs/pki-framework/src/CryptoTypes/Asymmetric/RSA/RSAPrivateKey.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\Asymmetric\\RSA\\RSAPublicKey' => $vendorDir . '/spomky-labs/pki-framework/src/CryptoTypes/Asymmetric/RSA/RSAPublicKey.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\Asymmetric\\RSA\\RSASSAPSSPrivateKey' => $vendorDir . '/spomky-labs/pki-framework/src/CryptoTypes/Asymmetric/RSA/RSASSAPSSPrivateKey.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\Signature\\ECSignature' => $vendorDir . '/spomky-labs/pki-framework/src/CryptoTypes/Signature/ECSignature.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\Signature\\Ed25519Signature' => $vendorDir . '/spomky-labs/pki-framework/src/CryptoTypes/Signature/Ed25519Signature.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\Signature\\Ed448Signature' => $vendorDir . '/spomky-labs/pki-framework/src/CryptoTypes/Signature/Ed448Signature.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\Signature\\GenericSignature' => $vendorDir . '/spomky-labs/pki-framework/src/CryptoTypes/Signature/GenericSignature.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\Signature\\RSASignature' => $vendorDir . '/spomky-labs/pki-framework/src/CryptoTypes/Signature/RSASignature.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\Signature\\Signature' => $vendorDir . '/spomky-labs/pki-framework/src/CryptoTypes/Signature/Signature.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\X501\\ASN1\\Attribute' => $vendorDir . '/spomky-labs/pki-framework/src/X501/ASN1/Attribute.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\X501\\ASN1\\AttributeType' => $vendorDir . '/spomky-labs/pki-framework/src/X501/ASN1/AttributeType.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\X501\\ASN1\\AttributeTypeAndValue' => $vendorDir . '/spomky-labs/pki-framework/src/X501/ASN1/AttributeTypeAndValue.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\X501\\ASN1\\AttributeValue\\AttributeValue' => $vendorDir . '/spomky-labs/pki-framework/src/X501/ASN1/AttributeValue/AttributeValue.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\X501\\ASN1\\AttributeValue\\CommonNameValue' => $vendorDir . '/spomky-labs/pki-framework/src/X501/ASN1/AttributeValue/CommonNameValue.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\X501\\ASN1\\AttributeValue\\CountryNameValue' => $vendorDir . '/spomky-labs/pki-framework/src/X501/ASN1/AttributeValue/CountryNameValue.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\X501\\ASN1\\AttributeValue\\DescriptionValue' => $vendorDir . '/spomky-labs/pki-framework/src/X501/ASN1/AttributeValue/DescriptionValue.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\X501\\ASN1\\AttributeValue\\Feature\\DirectoryString' => $vendorDir . '/spomky-labs/pki-framework/src/X501/ASN1/AttributeValue/Feature/DirectoryString.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\X501\\ASN1\\AttributeValue\\Feature\\PrintableStringValue' => $vendorDir . '/spomky-labs/pki-framework/src/X501/ASN1/AttributeValue/Feature/PrintableStringValue.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\X501\\ASN1\\AttributeValue\\GivenNameValue' => $vendorDir . '/spomky-labs/pki-framework/src/X501/ASN1/AttributeValue/GivenNameValue.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\X501\\ASN1\\AttributeValue\\LocalityNameValue' => $vendorDir . '/spomky-labs/pki-framework/src/X501/ASN1/AttributeValue/LocalityNameValue.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\X501\\ASN1\\AttributeValue\\NameValue' => $vendorDir . '/spomky-labs/pki-framework/src/X501/ASN1/AttributeValue/NameValue.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\X501\\ASN1\\AttributeValue\\OrganizationNameValue' => $vendorDir . '/spomky-labs/pki-framework/src/X501/ASN1/AttributeValue/OrganizationNameValue.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\X501\\ASN1\\AttributeValue\\OrganizationalUnitNameValue' => $vendorDir . '/spomky-labs/pki-framework/src/X501/ASN1/AttributeValue/OrganizationalUnitNameValue.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\X501\\ASN1\\AttributeValue\\PseudonymValue' => $vendorDir . '/spomky-labs/pki-framework/src/X501/ASN1/AttributeValue/PseudonymValue.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\X501\\ASN1\\AttributeValue\\SerialNumberValue' => $vendorDir . '/spomky-labs/pki-framework/src/X501/ASN1/AttributeValue/SerialNumberValue.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\X501\\ASN1\\AttributeValue\\StateOrProvinceNameValue' => $vendorDir . '/spomky-labs/pki-framework/src/X501/ASN1/AttributeValue/StateOrProvinceNameValue.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\X501\\ASN1\\AttributeValue\\SurnameValue' => $vendorDir . '/spomky-labs/pki-framework/src/X501/ASN1/AttributeValue/SurnameValue.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\X501\\ASN1\\AttributeValue\\TitleValue' => $vendorDir . '/spomky-labs/pki-framework/src/X501/ASN1/AttributeValue/TitleValue.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\X501\\ASN1\\AttributeValue\\UnknownAttributeValue' => $vendorDir . '/spomky-labs/pki-framework/src/X501/ASN1/AttributeValue/UnknownAttributeValue.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\X501\\ASN1\\Collection\\AttributeCollection' => $vendorDir . '/spomky-labs/pki-framework/src/X501/ASN1/Collection/AttributeCollection.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\X501\\ASN1\\Collection\\SequenceOfAttributes' => $vendorDir . '/spomky-labs/pki-framework/src/X501/ASN1/Collection/SequenceOfAttributes.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\X501\\ASN1\\Collection\\SetOfAttributes' => $vendorDir . '/spomky-labs/pki-framework/src/X501/ASN1/Collection/SetOfAttributes.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\X501\\ASN1\\Name' => $vendorDir . '/spomky-labs/pki-framework/src/X501/ASN1/Name.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\X501\\ASN1\\RDN' => $vendorDir . '/spomky-labs/pki-framework/src/X501/ASN1/RDN.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\X501\\DN\\DNParser' => $vendorDir . '/spomky-labs/pki-framework/src/X501/DN/DNParser.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\X501\\MatchingRule\\BinaryMatch' => $vendorDir . '/spomky-labs/pki-framework/src/X501/MatchingRule/BinaryMatch.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\X501\\MatchingRule\\CaseExactMatch' => $vendorDir . '/spomky-labs/pki-framework/src/X501/MatchingRule/CaseExactMatch.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\X501\\MatchingRule\\CaseIgnoreMatch' => $vendorDir . '/spomky-labs/pki-framework/src/X501/MatchingRule/CaseIgnoreMatch.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\X501\\MatchingRule\\MatchingRule' => $vendorDir . '/spomky-labs/pki-framework/src/X501/MatchingRule/MatchingRule.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\X501\\MatchingRule\\StringPrepMatchingRule' => $vendorDir . '/spomky-labs/pki-framework/src/X501/MatchingRule/StringPrepMatchingRule.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\X501\\StringPrep\\CheckBidiStep' => $vendorDir . '/spomky-labs/pki-framework/src/X501/StringPrep/CheckBidiStep.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\X501\\StringPrep\\InsignificantNonSubstringSpaceStep' => $vendorDir . '/spomky-labs/pki-framework/src/X501/StringPrep/InsignificantNonSubstringSpaceStep.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\X501\\StringPrep\\MapStep' => $vendorDir . '/spomky-labs/pki-framework/src/X501/StringPrep/MapStep.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\X501\\StringPrep\\NormalizeStep' => $vendorDir . '/spomky-labs/pki-framework/src/X501/StringPrep/NormalizeStep.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\X501\\StringPrep\\PrepareStep' => $vendorDir . '/spomky-labs/pki-framework/src/X501/StringPrep/PrepareStep.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\X501\\StringPrep\\ProhibitStep' => $vendorDir . '/spomky-labs/pki-framework/src/X501/StringPrep/ProhibitStep.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\X501\\StringPrep\\StringPreparer' => $vendorDir . '/spomky-labs/pki-framework/src/X501/StringPrep/StringPreparer.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\X501\\StringPrep\\TranscodeStep' => $vendorDir . '/spomky-labs/pki-framework/src/X501/StringPrep/TranscodeStep.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\X509\\AttributeCertificate\\AttCertIssuer' => $vendorDir . '/spomky-labs/pki-framework/src/X509/AttributeCertificate/AttCertIssuer.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\X509\\AttributeCertificate\\AttCertValidityPeriod' => $vendorDir . '/spomky-labs/pki-framework/src/X509/AttributeCertificate/AttCertValidityPeriod.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\X509\\AttributeCertificate\\AttributeCertificate' => $vendorDir . '/spomky-labs/pki-framework/src/X509/AttributeCertificate/AttributeCertificate.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\X509\\AttributeCertificate\\AttributeCertificateInfo' => $vendorDir . '/spomky-labs/pki-framework/src/X509/AttributeCertificate/AttributeCertificateInfo.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\X509\\AttributeCertificate\\Attribute\\AccessIdentityAttributeValue' => $vendorDir . '/spomky-labs/pki-framework/src/X509/AttributeCertificate/Attribute/AccessIdentityAttributeValue.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\X509\\AttributeCertificate\\Attribute\\AuthenticationInfoAttributeValue' => $vendorDir . '/spomky-labs/pki-framework/src/X509/AttributeCertificate/Attribute/AuthenticationInfoAttributeValue.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\X509\\AttributeCertificate\\Attribute\\ChargingIdentityAttributeValue' => $vendorDir . '/spomky-labs/pki-framework/src/X509/AttributeCertificate/Attribute/ChargingIdentityAttributeValue.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\X509\\AttributeCertificate\\Attribute\\GroupAttributeValue' => $vendorDir . '/spomky-labs/pki-framework/src/X509/AttributeCertificate/Attribute/GroupAttributeValue.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\X509\\AttributeCertificate\\Attribute\\IetfAttrSyntax' => $vendorDir . '/spomky-labs/pki-framework/src/X509/AttributeCertificate/Attribute/IetfAttrSyntax.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\X509\\AttributeCertificate\\Attribute\\IetfAttrValue' => $vendorDir . '/spomky-labs/pki-framework/src/X509/AttributeCertificate/Attribute/IetfAttrValue.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\X509\\AttributeCertificate\\Attribute\\RoleAttributeValue' => $vendorDir . '/spomky-labs/pki-framework/src/X509/AttributeCertificate/Attribute/RoleAttributeValue.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\X509\\AttributeCertificate\\Attribute\\SvceAuthInfo' => $vendorDir . '/spomky-labs/pki-framework/src/X509/AttributeCertificate/Attribute/SvceAuthInfo.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\X509\\AttributeCertificate\\Attributes' => $vendorDir . '/spomky-labs/pki-framework/src/X509/AttributeCertificate/Attributes.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\X509\\AttributeCertificate\\Holder' => $vendorDir . '/spomky-labs/pki-framework/src/X509/AttributeCertificate/Holder.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\X509\\AttributeCertificate\\IssuerSerial' => $vendorDir . '/spomky-labs/pki-framework/src/X509/AttributeCertificate/IssuerSerial.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\X509\\AttributeCertificate\\ObjectDigestInfo' => $vendorDir . '/spomky-labs/pki-framework/src/X509/AttributeCertificate/ObjectDigestInfo.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\X509\\AttributeCertificate\\V2Form' => $vendorDir . '/spomky-labs/pki-framework/src/X509/AttributeCertificate/V2Form.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\X509\\AttributeCertificate\\Validation\\ACValidationConfig' => $vendorDir . '/spomky-labs/pki-framework/src/X509/AttributeCertificate/Validation/ACValidationConfig.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\X509\\AttributeCertificate\\Validation\\ACValidator' => $vendorDir . '/spomky-labs/pki-framework/src/X509/AttributeCertificate/Validation/ACValidator.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\X509\\AttributeCertificate\\Validation\\Exception\\ACValidationException' => $vendorDir . '/spomky-labs/pki-framework/src/X509/AttributeCertificate/Validation/Exception/ACValidationException.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\X509\\Certificate\\Certificate' => $vendorDir . '/spomky-labs/pki-framework/src/X509/Certificate/Certificate.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\X509\\Certificate\\CertificateBundle' => $vendorDir . '/spomky-labs/pki-framework/src/X509/Certificate/CertificateBundle.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\X509\\Certificate\\CertificateChain' => $vendorDir . '/spomky-labs/pki-framework/src/X509/Certificate/CertificateChain.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\X509\\Certificate\\Extension\\AAControlsExtension' => $vendorDir . '/spomky-labs/pki-framework/src/X509/Certificate/Extension/AAControlsExtension.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\X509\\Certificate\\Extension\\AccessDescription\\AccessDescription' => $vendorDir . '/spomky-labs/pki-framework/src/X509/Certificate/Extension/AccessDescription/AccessDescription.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\X509\\Certificate\\Extension\\AccessDescription\\AuthorityAccessDescription' => $vendorDir . '/spomky-labs/pki-framework/src/X509/Certificate/Extension/AccessDescription/AuthorityAccessDescription.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\X509\\Certificate\\Extension\\AccessDescription\\SubjectAccessDescription' => $vendorDir . '/spomky-labs/pki-framework/src/X509/Certificate/Extension/AccessDescription/SubjectAccessDescription.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\X509\\Certificate\\Extension\\AuthorityInformationAccessExtension' => $vendorDir . '/spomky-labs/pki-framework/src/X509/Certificate/Extension/AuthorityInformationAccessExtension.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\X509\\Certificate\\Extension\\AuthorityKeyIdentifierExtension' => $vendorDir . '/spomky-labs/pki-framework/src/X509/Certificate/Extension/AuthorityKeyIdentifierExtension.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\X509\\Certificate\\Extension\\BasicConstraintsExtension' => $vendorDir . '/spomky-labs/pki-framework/src/X509/Certificate/Extension/BasicConstraintsExtension.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\X509\\Certificate\\Extension\\CRLDistributionPointsExtension' => $vendorDir . '/spomky-labs/pki-framework/src/X509/Certificate/Extension/CRLDistributionPointsExtension.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\X509\\Certificate\\Extension\\CertificatePoliciesExtension' => $vendorDir . '/spomky-labs/pki-framework/src/X509/Certificate/Extension/CertificatePoliciesExtension.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\X509\\Certificate\\Extension\\CertificatePolicy\\CPSQualifier' => $vendorDir . '/spomky-labs/pki-framework/src/X509/Certificate/Extension/CertificatePolicy/CPSQualifier.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\X509\\Certificate\\Extension\\CertificatePolicy\\DisplayText' => $vendorDir . '/spomky-labs/pki-framework/src/X509/Certificate/Extension/CertificatePolicy/DisplayText.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\X509\\Certificate\\Extension\\CertificatePolicy\\NoticeReference' => $vendorDir . '/spomky-labs/pki-framework/src/X509/Certificate/Extension/CertificatePolicy/NoticeReference.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\X509\\Certificate\\Extension\\CertificatePolicy\\PolicyInformation' => $vendorDir . '/spomky-labs/pki-framework/src/X509/Certificate/Extension/CertificatePolicy/PolicyInformation.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\X509\\Certificate\\Extension\\CertificatePolicy\\PolicyQualifierInfo' => $vendorDir . '/spomky-labs/pki-framework/src/X509/Certificate/Extension/CertificatePolicy/PolicyQualifierInfo.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\X509\\Certificate\\Extension\\CertificatePolicy\\UserNoticeQualifier' => $vendorDir . '/spomky-labs/pki-framework/src/X509/Certificate/Extension/CertificatePolicy/UserNoticeQualifier.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\X509\\Certificate\\Extension\\DistributionPoint\\DistributionPoint' => $vendorDir . '/spomky-labs/pki-framework/src/X509/Certificate/Extension/DistributionPoint/DistributionPoint.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\X509\\Certificate\\Extension\\DistributionPoint\\DistributionPointName' => $vendorDir . '/spomky-labs/pki-framework/src/X509/Certificate/Extension/DistributionPoint/DistributionPointName.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\X509\\Certificate\\Extension\\DistributionPoint\\FullName' => $vendorDir . '/spomky-labs/pki-framework/src/X509/Certificate/Extension/DistributionPoint/FullName.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\X509\\Certificate\\Extension\\DistributionPoint\\ReasonFlags' => $vendorDir . '/spomky-labs/pki-framework/src/X509/Certificate/Extension/DistributionPoint/ReasonFlags.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\X509\\Certificate\\Extension\\DistributionPoint\\RelativeName' => $vendorDir . '/spomky-labs/pki-framework/src/X509/Certificate/Extension/DistributionPoint/RelativeName.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\X509\\Certificate\\Extension\\ExtendedKeyUsageExtension' => $vendorDir . '/spomky-labs/pki-framework/src/X509/Certificate/Extension/ExtendedKeyUsageExtension.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\X509\\Certificate\\Extension\\Extension' => $vendorDir . '/spomky-labs/pki-framework/src/X509/Certificate/Extension/Extension.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\X509\\Certificate\\Extension\\FreshestCRLExtension' => $vendorDir . '/spomky-labs/pki-framework/src/X509/Certificate/Extension/FreshestCRLExtension.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\X509\\Certificate\\Extension\\InhibitAnyPolicyExtension' => $vendorDir . '/spomky-labs/pki-framework/src/X509/Certificate/Extension/InhibitAnyPolicyExtension.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\X509\\Certificate\\Extension\\IssuerAlternativeNameExtension' => $vendorDir . '/spomky-labs/pki-framework/src/X509/Certificate/Extension/IssuerAlternativeNameExtension.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\X509\\Certificate\\Extension\\KeyUsageExtension' => $vendorDir . '/spomky-labs/pki-framework/src/X509/Certificate/Extension/KeyUsageExtension.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\X509\\Certificate\\Extension\\NameConstraintsExtension' => $vendorDir . '/spomky-labs/pki-framework/src/X509/Certificate/Extension/NameConstraintsExtension.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\X509\\Certificate\\Extension\\NameConstraints\\GeneralSubtree' => $vendorDir . '/spomky-labs/pki-framework/src/X509/Certificate/Extension/NameConstraints/GeneralSubtree.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\X509\\Certificate\\Extension\\NameConstraints\\GeneralSubtrees' => $vendorDir . '/spomky-labs/pki-framework/src/X509/Certificate/Extension/NameConstraints/GeneralSubtrees.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\X509\\Certificate\\Extension\\NoRevocationAvailableExtension' => $vendorDir . '/spomky-labs/pki-framework/src/X509/Certificate/Extension/NoRevocationAvailableExtension.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\X509\\Certificate\\Extension\\PolicyConstraintsExtension' => $vendorDir . '/spomky-labs/pki-framework/src/X509/Certificate/Extension/PolicyConstraintsExtension.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\X509\\Certificate\\Extension\\PolicyMappingsExtension' => $vendorDir . '/spomky-labs/pki-framework/src/X509/Certificate/Extension/PolicyMappingsExtension.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\X509\\Certificate\\Extension\\PolicyMappings\\PolicyMapping' => $vendorDir . '/spomky-labs/pki-framework/src/X509/Certificate/Extension/PolicyMappings/PolicyMapping.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\X509\\Certificate\\Extension\\SubjectAlternativeNameExtension' => $vendorDir . '/spomky-labs/pki-framework/src/X509/Certificate/Extension/SubjectAlternativeNameExtension.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\X509\\Certificate\\Extension\\SubjectDirectoryAttributesExtension' => $vendorDir . '/spomky-labs/pki-framework/src/X509/Certificate/Extension/SubjectDirectoryAttributesExtension.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\X509\\Certificate\\Extension\\SubjectInformationAccessExtension' => $vendorDir . '/spomky-labs/pki-framework/src/X509/Certificate/Extension/SubjectInformationAccessExtension.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\X509\\Certificate\\Extension\\SubjectKeyIdentifierExtension' => $vendorDir . '/spomky-labs/pki-framework/src/X509/Certificate/Extension/SubjectKeyIdentifierExtension.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\X509\\Certificate\\Extension\\TargetInformationExtension' => $vendorDir . '/spomky-labs/pki-framework/src/X509/Certificate/Extension/TargetInformationExtension.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\X509\\Certificate\\Extension\\Target\\Target' => $vendorDir . '/spomky-labs/pki-framework/src/X509/Certificate/Extension/Target/Target.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\X509\\Certificate\\Extension\\Target\\TargetGroup' => $vendorDir . '/spomky-labs/pki-framework/src/X509/Certificate/Extension/Target/TargetGroup.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\X509\\Certificate\\Extension\\Target\\TargetName' => $vendorDir . '/spomky-labs/pki-framework/src/X509/Certificate/Extension/Target/TargetName.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\X509\\Certificate\\Extension\\Target\\Targets' => $vendorDir . '/spomky-labs/pki-framework/src/X509/Certificate/Extension/Target/Targets.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\X509\\Certificate\\Extension\\UnknownExtension' => $vendorDir . '/spomky-labs/pki-framework/src/X509/Certificate/Extension/UnknownExtension.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\X509\\Certificate\\Extensions' => $vendorDir . '/spomky-labs/pki-framework/src/X509/Certificate/Extensions.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\X509\\Certificate\\TBSCertificate' => $vendorDir . '/spomky-labs/pki-framework/src/X509/Certificate/TBSCertificate.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\X509\\Certificate\\Time' => $vendorDir . '/spomky-labs/pki-framework/src/X509/Certificate/Time.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\X509\\Certificate\\UniqueIdentifier' => $vendorDir . '/spomky-labs/pki-framework/src/X509/Certificate/UniqueIdentifier.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\X509\\Certificate\\Validity' => $vendorDir . '/spomky-labs/pki-framework/src/X509/Certificate/Validity.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\X509\\CertificationPath\\CertificationPath' => $vendorDir . '/spomky-labs/pki-framework/src/X509/CertificationPath/CertificationPath.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\X509\\CertificationPath\\Exception\\PathBuildingException' => $vendorDir . '/spomky-labs/pki-framework/src/X509/CertificationPath/Exception/PathBuildingException.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\X509\\CertificationPath\\Exception\\PathValidationException' => $vendorDir . '/spomky-labs/pki-framework/src/X509/CertificationPath/Exception/PathValidationException.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\X509\\CertificationPath\\PathBuilding\\CertificationPathBuilder' => $vendorDir . '/spomky-labs/pki-framework/src/X509/CertificationPath/PathBuilding/CertificationPathBuilder.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\X509\\CertificationPath\\PathValidation\\PathValidationConfig' => $vendorDir . '/spomky-labs/pki-framework/src/X509/CertificationPath/PathValidation/PathValidationConfig.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\X509\\CertificationPath\\PathValidation\\PathValidationResult' => $vendorDir . '/spomky-labs/pki-framework/src/X509/CertificationPath/PathValidation/PathValidationResult.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\X509\\CertificationPath\\PathValidation\\PathValidator' => $vendorDir . '/spomky-labs/pki-framework/src/X509/CertificationPath/PathValidation/PathValidator.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\X509\\CertificationPath\\PathValidation\\ValidatorState' => $vendorDir . '/spomky-labs/pki-framework/src/X509/CertificationPath/PathValidation/ValidatorState.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\X509\\CertificationPath\\Policy\\PolicyNode' => $vendorDir . '/spomky-labs/pki-framework/src/X509/CertificationPath/Policy/PolicyNode.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\X509\\CertificationPath\\Policy\\PolicyTree' => $vendorDir . '/spomky-labs/pki-framework/src/X509/CertificationPath/Policy/PolicyTree.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\X509\\CertificationRequest\\Attribute\\ExtensionRequestValue' => $vendorDir . '/spomky-labs/pki-framework/src/X509/CertificationRequest/Attribute/ExtensionRequestValue.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\X509\\CertificationRequest\\Attributes' => $vendorDir . '/spomky-labs/pki-framework/src/X509/CertificationRequest/Attributes.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\X509\\CertificationRequest\\CertificationRequest' => $vendorDir . '/spomky-labs/pki-framework/src/X509/CertificationRequest/CertificationRequest.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\X509\\CertificationRequest\\CertificationRequestInfo' => $vendorDir . '/spomky-labs/pki-framework/src/X509/CertificationRequest/CertificationRequestInfo.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\X509\\Exception\\X509ValidationException' => $vendorDir . '/spomky-labs/pki-framework/src/X509/Exception/X509ValidationException.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\X509\\Feature\\DateTimeHelper' => $vendorDir . '/spomky-labs/pki-framework/src/X509/Feature/DateTimeHelper.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\X509\\GeneralName\\DNSName' => $vendorDir . '/spomky-labs/pki-framework/src/X509/GeneralName/DNSName.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\X509\\GeneralName\\DirectoryName' => $vendorDir . '/spomky-labs/pki-framework/src/X509/GeneralName/DirectoryName.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\X509\\GeneralName\\EDIPartyName' => $vendorDir . '/spomky-labs/pki-framework/src/X509/GeneralName/EDIPartyName.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\X509\\GeneralName\\GeneralName' => $vendorDir . '/spomky-labs/pki-framework/src/X509/GeneralName/GeneralName.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\X509\\GeneralName\\GeneralNames' => $vendorDir . '/spomky-labs/pki-framework/src/X509/GeneralName/GeneralNames.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\X509\\GeneralName\\IPAddress' => $vendorDir . '/spomky-labs/pki-framework/src/X509/GeneralName/IPAddress.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\X509\\GeneralName\\IPv4Address' => $vendorDir . '/spomky-labs/pki-framework/src/X509/GeneralName/IPv4Address.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\X509\\GeneralName\\IPv6Address' => $vendorDir . '/spomky-labs/pki-framework/src/X509/GeneralName/IPv6Address.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\X509\\GeneralName\\OtherName' => $vendorDir . '/spomky-labs/pki-framework/src/X509/GeneralName/OtherName.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\X509\\GeneralName\\RFC822Name' => $vendorDir . '/spomky-labs/pki-framework/src/X509/GeneralName/RFC822Name.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\X509\\GeneralName\\RegisteredID' => $vendorDir . '/spomky-labs/pki-framework/src/X509/GeneralName/RegisteredID.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\X509\\GeneralName\\UniformResourceIdentifier' => $vendorDir . '/spomky-labs/pki-framework/src/X509/GeneralName/UniformResourceIdentifier.php',
    '_ContaoManager\\SpomkyLabs\\Pki\\X509\\GeneralName\\X400Address' => $vendorDir . '/spomky-labs/pki-framework/src/X509/GeneralName/X400Address.php',
    '_ContaoManager\\Stringable' => $vendorDir . '/marc-mabe/php-enum/stubs/Stringable.php',
    '_ContaoManager\\Symfony\\Bridge\\Monolog\\Command\\ServerLogCommand' => $vendorDir . '/symfony/monolog-bridge/Command/ServerLogCommand.php',
    '_ContaoManager\\Symfony\\Bridge\\Monolog\\Formatter\\CompatibilityFormatter' => $vendorDir . '/symfony/monolog-bridge/Formatter/CompatibilityFormatter.php',
    '_ContaoManager\\Symfony\\Bridge\\Monolog\\Formatter\\ConsoleFormatter' => $vendorDir . '/symfony/monolog-bridge/Formatter/ConsoleFormatter.php',
    '_ContaoManager\\Symfony\\Bridge\\Monolog\\Formatter\\VarDumperFormatter' => $vendorDir . '/symfony/monolog-bridge/Formatter/VarDumperFormatter.php',
    '_ContaoManager\\Symfony\\Bridge\\Monolog\\Handler\\ChromePhpHandler' => $vendorDir . '/symfony/monolog-bridge/Handler/ChromePhpHandler.php',
    '_ContaoManager\\Symfony\\Bridge\\Monolog\\Handler\\CompatibilityHandler' => $vendorDir . '/symfony/monolog-bridge/Handler/CompatibilityHandler.php',
    '_ContaoManager\\Symfony\\Bridge\\Monolog\\Handler\\CompatibilityProcessingHandler' => $vendorDir . '/symfony/monolog-bridge/Handler/CompatibilityProcessingHandler.php',
    '_ContaoManager\\Symfony\\Bridge\\Monolog\\Handler\\ConsoleHandler' => $vendorDir . '/symfony/monolog-bridge/Handler/ConsoleHandler.php',
    '_ContaoManager\\Symfony\\Bridge\\Monolog\\Handler\\ElasticsearchLogstashHandler' => $vendorDir . '/symfony/monolog-bridge/Handler/ElasticsearchLogstashHandler.php',
    '_ContaoManager\\Symfony\\Bridge\\Monolog\\Handler\\FingersCrossed\\HttpCodeActivationStrategy' => $vendorDir . '/symfony/monolog-bridge/Handler/FingersCrossed/HttpCodeActivationStrategy.php',
    '_ContaoManager\\Symfony\\Bridge\\Monolog\\Handler\\FingersCrossed\\NotFoundActivationStrategy' => $vendorDir . '/symfony/monolog-bridge/Handler/FingersCrossed/NotFoundActivationStrategy.php',
    '_ContaoManager\\Symfony\\Bridge\\Monolog\\Handler\\FirePHPHandler' => $vendorDir . '/symfony/monolog-bridge/Handler/FirePHPHandler.php',
    '_ContaoManager\\Symfony\\Bridge\\Monolog\\Handler\\MailerHandler' => $vendorDir . '/symfony/monolog-bridge/Handler/MailerHandler.php',
    '_ContaoManager\\Symfony\\Bridge\\Monolog\\Handler\\NotifierHandler' => $vendorDir . '/symfony/monolog-bridge/Handler/NotifierHandler.php',
    '_ContaoManager\\Symfony\\Bridge\\Monolog\\Handler\\ServerLogHandler' => $vendorDir . '/symfony/monolog-bridge/Handler/ServerLogHandler.php',
    '_ContaoManager\\Symfony\\Bridge\\Monolog\\Logger' => $vendorDir . '/symfony/monolog-bridge/Logger.php',
    '_ContaoManager\\Symfony\\Bridge\\Monolog\\Processor\\AbstractTokenProcessor' => $vendorDir . '/symfony/monolog-bridge/Processor/AbstractTokenProcessor.php',
    '_ContaoManager\\Symfony\\Bridge\\Monolog\\Processor\\CompatibilityProcessor' => $vendorDir . '/symfony/monolog-bridge/Processor/CompatibilityProcessor.php',
    '_ContaoManager\\Symfony\\Bridge\\Monolog\\Processor\\ConsoleCommandProcessor' => $vendorDir . '/symfony/monolog-bridge/Processor/ConsoleCommandProcessor.php',
    '_ContaoManager\\Symfony\\Bridge\\Monolog\\Processor\\DebugProcessor' => $vendorDir . '/symfony/monolog-bridge/Processor/DebugProcessor.php',
    '_ContaoManager\\Symfony\\Bridge\\Monolog\\Processor\\RouteProcessor' => $vendorDir . '/symfony/monolog-bridge/Processor/RouteProcessor.php',
    '_ContaoManager\\Symfony\\Bridge\\Monolog\\Processor\\SwitchUserTokenProcessor' => $vendorDir . '/symfony/monolog-bridge/Processor/SwitchUserTokenProcessor.php',
    '_ContaoManager\\Symfony\\Bridge\\Monolog\\Processor\\TokenProcessor' => $vendorDir . '/symfony/monolog-bridge/Processor/TokenProcessor.php',
    '_ContaoManager\\Symfony\\Bridge\\Monolog\\Processor\\WebProcessor' => $vendorDir . '/symfony/monolog-bridge/Processor/WebProcessor.php',
    '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\CacheWarmer\\AbstractPhpFileCacheWarmer' => $vendorDir . '/symfony/framework-bundle/CacheWarmer/AbstractPhpFileCacheWarmer.php',
    '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\CacheWarmer\\AnnotationsCacheWarmer' => $vendorDir . '/symfony/framework-bundle/CacheWarmer/AnnotationsCacheWarmer.php',
    '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\CacheWarmer\\CachePoolClearerCacheWarmer' => $vendorDir . '/symfony/framework-bundle/CacheWarmer/CachePoolClearerCacheWarmer.php',
    '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\CacheWarmer\\ConfigBuilderCacheWarmer' => $vendorDir . '/symfony/framework-bundle/CacheWarmer/ConfigBuilderCacheWarmer.php',
    '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\CacheWarmer\\RouterCacheWarmer' => $vendorDir . '/symfony/framework-bundle/CacheWarmer/RouterCacheWarmer.php',
    '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\CacheWarmer\\SerializerCacheWarmer' => $vendorDir . '/symfony/framework-bundle/CacheWarmer/SerializerCacheWarmer.php',
    '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\CacheWarmer\\TranslationsCacheWarmer' => $vendorDir . '/symfony/framework-bundle/CacheWarmer/TranslationsCacheWarmer.php',
    '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\CacheWarmer\\ValidatorCacheWarmer' => $vendorDir . '/symfony/framework-bundle/CacheWarmer/ValidatorCacheWarmer.php',
    '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Command\\AboutCommand' => $vendorDir . '/symfony/framework-bundle/Command/AboutCommand.php',
    '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Command\\AbstractConfigCommand' => $vendorDir . '/symfony/framework-bundle/Command/AbstractConfigCommand.php',
    '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Command\\AssetsInstallCommand' => $vendorDir . '/symfony/framework-bundle/Command/AssetsInstallCommand.php',
    '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Command\\BuildDebugContainerTrait' => $vendorDir . '/symfony/framework-bundle/Command/BuildDebugContainerTrait.php',
    '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Command\\CacheClearCommand' => $vendorDir . '/symfony/framework-bundle/Command/CacheClearCommand.php',
    '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Command\\CachePoolClearCommand' => $vendorDir . '/symfony/framework-bundle/Command/CachePoolClearCommand.php',
    '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Command\\CachePoolDeleteCommand' => $vendorDir . '/symfony/framework-bundle/Command/CachePoolDeleteCommand.php',
    '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Command\\CachePoolInvalidateTagsCommand' => $vendorDir . '/symfony/framework-bundle/Command/CachePoolInvalidateTagsCommand.php',
    '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Command\\CachePoolListCommand' => $vendorDir . '/symfony/framework-bundle/Command/CachePoolListCommand.php',
    '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Command\\CachePoolPruneCommand' => $vendorDir . '/symfony/framework-bundle/Command/CachePoolPruneCommand.php',
    '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Command\\CacheWarmupCommand' => $vendorDir . '/symfony/framework-bundle/Command/CacheWarmupCommand.php',
    '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Command\\ConfigDebugCommand' => $vendorDir . '/symfony/framework-bundle/Command/ConfigDebugCommand.php',
    '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Command\\ConfigDumpReferenceCommand' => $vendorDir . '/symfony/framework-bundle/Command/ConfigDumpReferenceCommand.php',
    '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Command\\ContainerDebugCommand' => $vendorDir . '/symfony/framework-bundle/Command/ContainerDebugCommand.php',
    '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Command\\ContainerLintCommand' => $vendorDir . '/symfony/framework-bundle/Command/ContainerLintCommand.php',
    '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Command\\DebugAutowiringCommand' => $vendorDir . '/symfony/framework-bundle/Command/DebugAutowiringCommand.php',
    '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Command\\EventDispatcherDebugCommand' => $vendorDir . '/symfony/framework-bundle/Command/EventDispatcherDebugCommand.php',
    '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Command\\RouterDebugCommand' => $vendorDir . '/symfony/framework-bundle/Command/RouterDebugCommand.php',
    '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Command\\RouterMatchCommand' => $vendorDir . '/symfony/framework-bundle/Command/RouterMatchCommand.php',
    '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Command\\SecretsDecryptToLocalCommand' => $vendorDir . '/symfony/framework-bundle/Command/SecretsDecryptToLocalCommand.php',
    '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Command\\SecretsEncryptFromLocalCommand' => $vendorDir . '/symfony/framework-bundle/Command/SecretsEncryptFromLocalCommand.php',
    '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Command\\SecretsGenerateKeysCommand' => $vendorDir . '/symfony/framework-bundle/Command/SecretsGenerateKeysCommand.php',
    '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Command\\SecretsListCommand' => $vendorDir . '/symfony/framework-bundle/Command/SecretsListCommand.php',
    '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Command\\SecretsRemoveCommand' => $vendorDir . '/symfony/framework-bundle/Command/SecretsRemoveCommand.php',
    '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Command\\SecretsSetCommand' => $vendorDir . '/symfony/framework-bundle/Command/SecretsSetCommand.php',
    '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Command\\TranslationDebugCommand' => $vendorDir . '/symfony/framework-bundle/Command/TranslationDebugCommand.php',
    '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Command\\TranslationUpdateCommand' => $vendorDir . '/symfony/framework-bundle/Command/TranslationUpdateCommand.php',
    '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Command\\WorkflowDumpCommand' => $vendorDir . '/symfony/framework-bundle/Command/WorkflowDumpCommand.php',
    '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Command\\XliffLintCommand' => $vendorDir . '/symfony/framework-bundle/Command/XliffLintCommand.php',
    '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Command\\YamlLintCommand' => $vendorDir . '/symfony/framework-bundle/Command/YamlLintCommand.php',
    '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Console\\Application' => $vendorDir . '/symfony/framework-bundle/Console/Application.php',
    '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Console\\Descriptor\\Descriptor' => $vendorDir . '/symfony/framework-bundle/Console/Descriptor/Descriptor.php',
    '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Console\\Descriptor\\JsonDescriptor' => $vendorDir . '/symfony/framework-bundle/Console/Descriptor/JsonDescriptor.php',
    '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Console\\Descriptor\\MarkdownDescriptor' => $vendorDir . '/symfony/framework-bundle/Console/Descriptor/MarkdownDescriptor.php',
    '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Console\\Descriptor\\TextDescriptor' => $vendorDir . '/symfony/framework-bundle/Console/Descriptor/TextDescriptor.php',
    '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Console\\Descriptor\\XmlDescriptor' => $vendorDir . '/symfony/framework-bundle/Console/Descriptor/XmlDescriptor.php',
    '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Console\\Helper\\DescriptorHelper' => $vendorDir . '/symfony/framework-bundle/Console/Helper/DescriptorHelper.php',
    '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Controller\\AbstractController' => $vendorDir . '/symfony/framework-bundle/Controller/AbstractController.php',
    '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Controller\\ControllerResolver' => $vendorDir . '/symfony/framework-bundle/Controller/ControllerResolver.php',
    '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Controller\\RedirectController' => $vendorDir . '/symfony/framework-bundle/Controller/RedirectController.php',
    '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Controller\\TemplateController' => $vendorDir . '/symfony/framework-bundle/Controller/TemplateController.php',
    '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\DataCollector\\AbstractDataCollector' => $vendorDir . '/symfony/framework-bundle/DataCollector/AbstractDataCollector.php',
    '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\DataCollector\\RouterDataCollector' => $vendorDir . '/symfony/framework-bundle/DataCollector/RouterDataCollector.php',
    '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\DataCollector\\TemplateAwareDataCollectorInterface' => $vendorDir . '/symfony/framework-bundle/DataCollector/TemplateAwareDataCollectorInterface.php',
    '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\DependencyInjection\\Compiler\\AddAnnotationsCachedReaderPass' => $vendorDir . '/symfony/framework-bundle/DependencyInjection/Compiler/AddAnnotationsCachedReaderPass.php',
    '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\DependencyInjection\\Compiler\\AddDebugLogProcessorPass' => $vendorDir . '/symfony/framework-bundle/DependencyInjection/Compiler/AddDebugLogProcessorPass.php',
    '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\DependencyInjection\\Compiler\\AddExpressionLanguageProvidersPass' => $vendorDir . '/symfony/framework-bundle/DependencyInjection/Compiler/AddExpressionLanguageProvidersPass.php',
    '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\DependencyInjection\\Compiler\\AssetsContextPass' => $vendorDir . '/symfony/framework-bundle/DependencyInjection/Compiler/AssetsContextPass.php',
    '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\DependencyInjection\\Compiler\\ContainerBuilderDebugDumpPass' => $vendorDir . '/symfony/framework-bundle/DependencyInjection/Compiler/ContainerBuilderDebugDumpPass.php',
    '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\DependencyInjection\\Compiler\\DataCollectorTranslatorPass' => $vendorDir . '/symfony/framework-bundle/DependencyInjection/Compiler/DataCollectorTranslatorPass.php',
    '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\DependencyInjection\\Compiler\\EnableLoggerDebugModePass' => $vendorDir . '/symfony/framework-bundle/DependencyInjection/Compiler/EnableLoggerDebugModePass.php',
    '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\DependencyInjection\\Compiler\\ErrorLoggerCompilerPass' => $vendorDir . '/symfony/framework-bundle/DependencyInjection/Compiler/ErrorLoggerCompilerPass.php',
    '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\DependencyInjection\\Compiler\\LoggingTranslatorPass' => $vendorDir . '/symfony/framework-bundle/DependencyInjection/Compiler/LoggingTranslatorPass.php',
    '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\DependencyInjection\\Compiler\\ProfilerPass' => $vendorDir . '/symfony/framework-bundle/DependencyInjection/Compiler/ProfilerPass.php',
    '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\DependencyInjection\\Compiler\\RemoveUnusedSessionMarshallingHandlerPass' => $vendorDir . '/symfony/framework-bundle/DependencyInjection/Compiler/RemoveUnusedSessionMarshallingHandlerPass.php',
    '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\DependencyInjection\\Compiler\\TestServiceContainerRealRefPass' => $vendorDir . '/symfony/framework-bundle/DependencyInjection/Compiler/TestServiceContainerRealRefPass.php',
    '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\DependencyInjection\\Compiler\\TestServiceContainerWeakRefPass' => $vendorDir . '/symfony/framework-bundle/DependencyInjection/Compiler/TestServiceContainerWeakRefPass.php',
    '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\DependencyInjection\\Compiler\\TranslationUpdateCommandPass' => $vendorDir . '/symfony/framework-bundle/DependencyInjection/Compiler/TranslationUpdateCommandPass.php',
    '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\DependencyInjection\\Compiler\\UnusedTagsPass' => $vendorDir . '/symfony/framework-bundle/DependencyInjection/Compiler/UnusedTagsPass.php',
    '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\DependencyInjection\\Compiler\\WorkflowGuardListenerPass' => $vendorDir . '/symfony/framework-bundle/DependencyInjection/Compiler/WorkflowGuardListenerPass.php',
    '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\DependencyInjection\\Configuration' => $vendorDir . '/symfony/framework-bundle/DependencyInjection/Configuration.php',
    '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\DependencyInjection\\FrameworkExtension' => $vendorDir . '/symfony/framework-bundle/DependencyInjection/FrameworkExtension.php',
    '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\DependencyInjection\\VirtualRequestStackPass' => $vendorDir . '/symfony/framework-bundle/DependencyInjection/VirtualRequestStackPass.php',
    '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\EventListener\\ConsoleProfilerListener' => $vendorDir . '/symfony/framework-bundle/EventListener/ConsoleProfilerListener.php',
    '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\EventListener\\SuggestMissingPackageSubscriber' => $vendorDir . '/symfony/framework-bundle/EventListener/SuggestMissingPackageSubscriber.php',
    '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\FrameworkBundle' => $vendorDir . '/symfony/framework-bundle/FrameworkBundle.php',
    '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\HttpCache\\HttpCache' => $vendorDir . '/symfony/framework-bundle/HttpCache/HttpCache.php',
    '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\KernelBrowser' => $vendorDir . '/symfony/framework-bundle/KernelBrowser.php',
    '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Kernel\\MicroKernelTrait' => $vendorDir . '/symfony/framework-bundle/Kernel/MicroKernelTrait.php',
    '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Routing\\AnnotatedRouteControllerLoader' => $vendorDir . '/symfony/framework-bundle/Routing/AnnotatedRouteControllerLoader.php',
    '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Routing\\AttributeRouteControllerLoader' => $vendorDir . '/symfony/framework-bundle/Routing/AttributeRouteControllerLoader.php',
    '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Routing\\Attribute\\AsRoutingConditionService' => $vendorDir . '/symfony/framework-bundle/Routing/Attribute/AsRoutingConditionService.php',
    '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Routing\\DelegatingLoader' => $vendorDir . '/symfony/framework-bundle/Routing/DelegatingLoader.php',
    '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Routing\\RedirectableCompiledUrlMatcher' => $vendorDir . '/symfony/framework-bundle/Routing/RedirectableCompiledUrlMatcher.php',
    '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Routing\\RouteLoaderInterface' => $vendorDir . '/symfony/framework-bundle/Routing/RouteLoaderInterface.php',
    '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Routing\\Router' => $vendorDir . '/symfony/framework-bundle/Routing/Router.php',
    '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Secrets\\AbstractVault' => $vendorDir . '/symfony/framework-bundle/Secrets/AbstractVault.php',
    '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Secrets\\DotenvVault' => $vendorDir . '/symfony/framework-bundle/Secrets/DotenvVault.php',
    '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Secrets\\SodiumVault' => $vendorDir . '/symfony/framework-bundle/Secrets/SodiumVault.php',
    '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Test\\BrowserKitAssertionsTrait' => $vendorDir . '/symfony/framework-bundle/Test/BrowserKitAssertionsTrait.php',
    '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Test\\DomCrawlerAssertionsTrait' => $vendorDir . '/symfony/framework-bundle/Test/DomCrawlerAssertionsTrait.php',
    '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Test\\HttpClientAssertionsTrait' => $vendorDir . '/symfony/framework-bundle/Test/HttpClientAssertionsTrait.php',
    '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Test\\KernelTestCase' => $vendorDir . '/symfony/framework-bundle/Test/KernelTestCase.php',
    '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Test\\MailerAssertionsTrait' => $vendorDir . '/symfony/framework-bundle/Test/MailerAssertionsTrait.php',
    '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Test\\NotificationAssertionsTrait' => $vendorDir . '/symfony/framework-bundle/Test/NotificationAssertionsTrait.php',
    '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Test\\TestBrowserToken' => $vendorDir . '/symfony/framework-bundle/Test/TestBrowserToken.php',
    '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Test\\TestContainer' => $vendorDir . '/symfony/framework-bundle/Test/TestContainer.php',
    '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Test\\WebTestAssertionsTrait' => $vendorDir . '/symfony/framework-bundle/Test/WebTestAssertionsTrait.php',
    '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Test\\WebTestCase' => $vendorDir . '/symfony/framework-bundle/Test/WebTestCase.php',
    '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Translation\\Translator' => $vendorDir . '/symfony/framework-bundle/Translation/Translator.php',
    '_ContaoManager\\Symfony\\Bundle\\MonologBundle\\DependencyInjection\\Compiler\\AddProcessorsPass' => $vendorDir . '/symfony/monolog-bundle/src/DependencyInjection/Compiler/AddProcessorsPass.php',
    '_ContaoManager\\Symfony\\Bundle\\MonologBundle\\DependencyInjection\\Compiler\\AddSwiftMailerTransportPass' => $vendorDir . '/symfony/monolog-bundle/src/DependencyInjection/Compiler/AddSwiftMailerTransportPass.php',
    '_ContaoManager\\Symfony\\Bundle\\MonologBundle\\DependencyInjection\\Compiler\\DebugHandlerPass' => $vendorDir . '/symfony/monolog-bundle/src/DependencyInjection/Compiler/DebugHandlerPass.php',
    '_ContaoManager\\Symfony\\Bundle\\MonologBundle\\DependencyInjection\\Compiler\\FixEmptyLoggerPass' => $vendorDir . '/symfony/monolog-bundle/src/DependencyInjection/Compiler/FixEmptyLoggerPass.php',
    '_ContaoManager\\Symfony\\Bundle\\MonologBundle\\DependencyInjection\\Compiler\\LoggerChannelPass' => $vendorDir . '/symfony/monolog-bundle/src/DependencyInjection/Compiler/LoggerChannelPass.php',
    '_ContaoManager\\Symfony\\Bundle\\MonologBundle\\DependencyInjection\\Configuration' => $vendorDir . '/symfony/monolog-bundle/src/DependencyInjection/Configuration.php',
    '_ContaoManager\\Symfony\\Bundle\\MonologBundle\\DependencyInjection\\MonologExtension' => $vendorDir . '/symfony/monolog-bundle/src/DependencyInjection/MonologExtension.php',
    '_ContaoManager\\Symfony\\Bundle\\MonologBundle\\MonologBundle' => $vendorDir . '/symfony/monolog-bundle/src/MonologBundle.php',
    '_ContaoManager\\Symfony\\Bundle\\MonologBundle\\SwiftMailer\\MessageFactory' => $vendorDir . '/symfony/monolog-bundle/src/SwiftMailer/MessageFactory.php',
    '_ContaoManager\\Symfony\\Bundle\\SecurityBundle\\CacheWarmer\\ExpressionCacheWarmer' => $vendorDir . '/symfony/security-bundle/CacheWarmer/ExpressionCacheWarmer.php',
    '_ContaoManager\\Symfony\\Bundle\\SecurityBundle\\Command\\DebugFirewallCommand' => $vendorDir . '/symfony/security-bundle/Command/DebugFirewallCommand.php',
    '_ContaoManager\\Symfony\\Bundle\\SecurityBundle\\DataCollector\\SecurityDataCollector' => $vendorDir . '/symfony/security-bundle/DataCollector/SecurityDataCollector.php',
    '_ContaoManager\\Symfony\\Bundle\\SecurityBundle\\Debug\\TraceableFirewallListener' => $vendorDir . '/symfony/security-bundle/Debug/TraceableFirewallListener.php',
    '_ContaoManager\\Symfony\\Bundle\\SecurityBundle\\Debug\\TraceableListenerTrait' => $vendorDir . '/symfony/security-bundle/Debug/TraceableListenerTrait.php',
    '_ContaoManager\\Symfony\\Bundle\\SecurityBundle\\Debug\\WrappedLazyListener' => $vendorDir . '/symfony/security-bundle/Debug/WrappedLazyListener.php',
    '_ContaoManager\\Symfony\\Bundle\\SecurityBundle\\Debug\\WrappedListener' => $vendorDir . '/symfony/security-bundle/Debug/WrappedListener.php',
    '_ContaoManager\\Symfony\\Bundle\\SecurityBundle\\DependencyInjection\\Compiler\\AddExpressionLanguageProvidersPass' => $vendorDir . '/symfony/security-bundle/DependencyInjection/Compiler/AddExpressionLanguageProvidersPass.php',
    '_ContaoManager\\Symfony\\Bundle\\SecurityBundle\\DependencyInjection\\Compiler\\AddSecurityVotersPass' => $vendorDir . '/symfony/security-bundle/DependencyInjection/Compiler/AddSecurityVotersPass.php',
    '_ContaoManager\\Symfony\\Bundle\\SecurityBundle\\DependencyInjection\\Compiler\\AddSessionDomainConstraintPass' => $vendorDir . '/symfony/security-bundle/DependencyInjection/Compiler/AddSessionDomainConstraintPass.php',
    '_ContaoManager\\Symfony\\Bundle\\SecurityBundle\\DependencyInjection\\Compiler\\CleanRememberMeVerifierPass' => $vendorDir . '/symfony/security-bundle/DependencyInjection/Compiler/CleanRememberMeVerifierPass.php',
    '_ContaoManager\\Symfony\\Bundle\\SecurityBundle\\DependencyInjection\\Compiler\\MakeFirewallsEventDispatcherTraceablePass' => $vendorDir . '/symfony/security-bundle/DependencyInjection/Compiler/MakeFirewallsEventDispatcherTraceablePass.php',
    '_ContaoManager\\Symfony\\Bundle\\SecurityBundle\\DependencyInjection\\Compiler\\RegisterCsrfFeaturesPass' => $vendorDir . '/symfony/security-bundle/DependencyInjection/Compiler/RegisterCsrfFeaturesPass.php',
    '_ContaoManager\\Symfony\\Bundle\\SecurityBundle\\DependencyInjection\\Compiler\\RegisterEntryPointPass' => $vendorDir . '/symfony/security-bundle/DependencyInjection/Compiler/RegisterEntryPointPass.php',
    '_ContaoManager\\Symfony\\Bundle\\SecurityBundle\\DependencyInjection\\Compiler\\RegisterGlobalSecurityEventListenersPass' => $vendorDir . '/symfony/security-bundle/DependencyInjection/Compiler/RegisterGlobalSecurityEventListenersPass.php',
    '_ContaoManager\\Symfony\\Bundle\\SecurityBundle\\DependencyInjection\\Compiler\\RegisterLdapLocatorPass' => $vendorDir . '/symfony/security-bundle/DependencyInjection/Compiler/RegisterLdapLocatorPass.php',
    '_ContaoManager\\Symfony\\Bundle\\SecurityBundle\\DependencyInjection\\Compiler\\RegisterTokenUsageTrackingPass' => $vendorDir . '/symfony/security-bundle/DependencyInjection/Compiler/RegisterTokenUsageTrackingPass.php',
    '_ContaoManager\\Symfony\\Bundle\\SecurityBundle\\DependencyInjection\\Compiler\\ReplaceDecoratedRememberMeHandlerPass' => $vendorDir . '/symfony/security-bundle/DependencyInjection/Compiler/ReplaceDecoratedRememberMeHandlerPass.php',
    '_ContaoManager\\Symfony\\Bundle\\SecurityBundle\\DependencyInjection\\Compiler\\SortFirewallListenersPass' => $vendorDir . '/symfony/security-bundle/DependencyInjection/Compiler/SortFirewallListenersPass.php',
    '_ContaoManager\\Symfony\\Bundle\\SecurityBundle\\DependencyInjection\\MainConfiguration' => $vendorDir . '/symfony/security-bundle/DependencyInjection/MainConfiguration.php',
    '_ContaoManager\\Symfony\\Bundle\\SecurityBundle\\DependencyInjection\\SecurityExtension' => $vendorDir . '/symfony/security-bundle/DependencyInjection/SecurityExtension.php',
    '_ContaoManager\\Symfony\\Bundle\\SecurityBundle\\DependencyInjection\\Security\\AccessToken\\OidcTokenHandlerFactory' => $vendorDir . '/symfony/security-bundle/DependencyInjection/Security/AccessToken/OidcTokenHandlerFactory.php',
    '_ContaoManager\\Symfony\\Bundle\\SecurityBundle\\DependencyInjection\\Security\\AccessToken\\OidcUserInfoTokenHandlerFactory' => $vendorDir . '/symfony/security-bundle/DependencyInjection/Security/AccessToken/OidcUserInfoTokenHandlerFactory.php',
    '_ContaoManager\\Symfony\\Bundle\\SecurityBundle\\DependencyInjection\\Security\\AccessToken\\ServiceTokenHandlerFactory' => $vendorDir . '/symfony/security-bundle/DependencyInjection/Security/AccessToken/ServiceTokenHandlerFactory.php',
    '_ContaoManager\\Symfony\\Bundle\\SecurityBundle\\DependencyInjection\\Security\\AccessToken\\TokenHandlerFactoryInterface' => $vendorDir . '/symfony/security-bundle/DependencyInjection/Security/AccessToken/TokenHandlerFactoryInterface.php',
    '_ContaoManager\\Symfony\\Bundle\\SecurityBundle\\DependencyInjection\\Security\\Factory\\AbstractFactory' => $vendorDir . '/symfony/security-bundle/DependencyInjection/Security/Factory/AbstractFactory.php',
    '_ContaoManager\\Symfony\\Bundle\\SecurityBundle\\DependencyInjection\\Security\\Factory\\AccessTokenFactory' => $vendorDir . '/symfony/security-bundle/DependencyInjection/Security/Factory/AccessTokenFactory.php',
    '_ContaoManager\\Symfony\\Bundle\\SecurityBundle\\DependencyInjection\\Security\\Factory\\AuthenticatorFactoryInterface' => $vendorDir . '/symfony/security-bundle/DependencyInjection/Security/Factory/AuthenticatorFactoryInterface.php',
    '_ContaoManager\\Symfony\\Bundle\\SecurityBundle\\DependencyInjection\\Security\\Factory\\CustomAuthenticatorFactory' => $vendorDir . '/symfony/security-bundle/DependencyInjection/Security/Factory/CustomAuthenticatorFactory.php',
    '_ContaoManager\\Symfony\\Bundle\\SecurityBundle\\DependencyInjection\\Security\\Factory\\FirewallListenerFactoryInterface' => $vendorDir . '/symfony/security-bundle/DependencyInjection/Security/Factory/FirewallListenerFactoryInterface.php',
    '_ContaoManager\\Symfony\\Bundle\\SecurityBundle\\DependencyInjection\\Security\\Factory\\FormLoginFactory' => $vendorDir . '/symfony/security-bundle/DependencyInjection/Security/Factory/FormLoginFactory.php',
    '_ContaoManager\\Symfony\\Bundle\\SecurityBundle\\DependencyInjection\\Security\\Factory\\FormLoginLdapFactory' => $vendorDir . '/symfony/security-bundle/DependencyInjection/Security/Factory/FormLoginLdapFactory.php',
    '_ContaoManager\\Symfony\\Bundle\\SecurityBundle\\DependencyInjection\\Security\\Factory\\HttpBasicFactory' => $vendorDir . '/symfony/security-bundle/DependencyInjection/Security/Factory/HttpBasicFactory.php',
    '_ContaoManager\\Symfony\\Bundle\\SecurityBundle\\DependencyInjection\\Security\\Factory\\HttpBasicLdapFactory' => $vendorDir . '/symfony/security-bundle/DependencyInjection/Security/Factory/HttpBasicLdapFactory.php',
    '_ContaoManager\\Symfony\\Bundle\\SecurityBundle\\DependencyInjection\\Security\\Factory\\JsonLoginFactory' => $vendorDir . '/symfony/security-bundle/DependencyInjection/Security/Factory/JsonLoginFactory.php',
    '_ContaoManager\\Symfony\\Bundle\\SecurityBundle\\DependencyInjection\\Security\\Factory\\JsonLoginLdapFactory' => $vendorDir . '/symfony/security-bundle/DependencyInjection/Security/Factory/JsonLoginLdapFactory.php',
    '_ContaoManager\\Symfony\\Bundle\\SecurityBundle\\DependencyInjection\\Security\\Factory\\LdapFactoryTrait' => $vendorDir . '/symfony/security-bundle/DependencyInjection/Security/Factory/LdapFactoryTrait.php',
    '_ContaoManager\\Symfony\\Bundle\\SecurityBundle\\DependencyInjection\\Security\\Factory\\LoginLinkFactory' => $vendorDir . '/symfony/security-bundle/DependencyInjection/Security/Factory/LoginLinkFactory.php',
    '_ContaoManager\\Symfony\\Bundle\\SecurityBundle\\DependencyInjection\\Security\\Factory\\LoginThrottlingFactory' => $vendorDir . '/symfony/security-bundle/DependencyInjection/Security/Factory/LoginThrottlingFactory.php',
    '_ContaoManager\\Symfony\\Bundle\\SecurityBundle\\DependencyInjection\\Security\\Factory\\RememberMeFactory' => $vendorDir . '/symfony/security-bundle/DependencyInjection/Security/Factory/RememberMeFactory.php',
    '_ContaoManager\\Symfony\\Bundle\\SecurityBundle\\DependencyInjection\\Security\\Factory\\RemoteUserFactory' => $vendorDir . '/symfony/security-bundle/DependencyInjection/Security/Factory/RemoteUserFactory.php',
    '_ContaoManager\\Symfony\\Bundle\\SecurityBundle\\DependencyInjection\\Security\\Factory\\SignatureAlgorithmFactory' => $vendorDir . '/symfony/security-bundle/DependencyInjection/Security/Factory/SignatureAlgorithmFactory.php',
    '_ContaoManager\\Symfony\\Bundle\\SecurityBundle\\DependencyInjection\\Security\\Factory\\StatelessAuthenticatorFactoryInterface' => $vendorDir . '/symfony/security-bundle/DependencyInjection/Security/Factory/StatelessAuthenticatorFactoryInterface.php',
    '_ContaoManager\\Symfony\\Bundle\\SecurityBundle\\DependencyInjection\\Security\\Factory\\X509Factory' => $vendorDir . '/symfony/security-bundle/DependencyInjection/Security/Factory/X509Factory.php',
    '_ContaoManager\\Symfony\\Bundle\\SecurityBundle\\DependencyInjection\\Security\\UserProvider\\InMemoryFactory' => $vendorDir . '/symfony/security-bundle/DependencyInjection/Security/UserProvider/InMemoryFactory.php',
    '_ContaoManager\\Symfony\\Bundle\\SecurityBundle\\DependencyInjection\\Security\\UserProvider\\LdapFactory' => $vendorDir . '/symfony/security-bundle/DependencyInjection/Security/UserProvider/LdapFactory.php',
    '_ContaoManager\\Symfony\\Bundle\\SecurityBundle\\DependencyInjection\\Security\\UserProvider\\UserProviderFactoryInterface' => $vendorDir . '/symfony/security-bundle/DependencyInjection/Security/UserProvider/UserProviderFactoryInterface.php',
    '_ContaoManager\\Symfony\\Bundle\\SecurityBundle\\EventListener\\FirewallListener' => $vendorDir . '/symfony/security-bundle/EventListener/FirewallListener.php',
    '_ContaoManager\\Symfony\\Bundle\\SecurityBundle\\EventListener\\VoteListener' => $vendorDir . '/symfony/security-bundle/EventListener/VoteListener.php',
    '_ContaoManager\\Symfony\\Bundle\\SecurityBundle\\LoginLink\\FirewallAwareLoginLinkHandler' => $vendorDir . '/symfony/security-bundle/LoginLink/FirewallAwareLoginLinkHandler.php',
    '_ContaoManager\\Symfony\\Bundle\\SecurityBundle\\RememberMe\\DecoratedRememberMeHandler' => $vendorDir . '/symfony/security-bundle/RememberMe/DecoratedRememberMeHandler.php',
    '_ContaoManager\\Symfony\\Bundle\\SecurityBundle\\RememberMe\\FirewallAwareRememberMeHandler' => $vendorDir . '/symfony/security-bundle/RememberMe/FirewallAwareRememberMeHandler.php',
    '_ContaoManager\\Symfony\\Bundle\\SecurityBundle\\Routing\\LogoutRouteLoader' => $vendorDir . '/symfony/security-bundle/Routing/LogoutRouteLoader.php',
    '_ContaoManager\\Symfony\\Bundle\\SecurityBundle\\Security' => $vendorDir . '/symfony/security-bundle/Security.php',
    '_ContaoManager\\Symfony\\Bundle\\SecurityBundle\\SecurityBundle' => $vendorDir . '/symfony/security-bundle/SecurityBundle.php',
    '_ContaoManager\\Symfony\\Bundle\\SecurityBundle\\Security\\FirewallAwareTrait' => $vendorDir . '/symfony/security-bundle/Security/FirewallAwareTrait.php',
    '_ContaoManager\\Symfony\\Bundle\\SecurityBundle\\Security\\FirewallConfig' => $vendorDir . '/symfony/security-bundle/Security/FirewallConfig.php',
    '_ContaoManager\\Symfony\\Bundle\\SecurityBundle\\Security\\FirewallContext' => $vendorDir . '/symfony/security-bundle/Security/FirewallContext.php',
    '_ContaoManager\\Symfony\\Bundle\\SecurityBundle\\Security\\FirewallMap' => $vendorDir . '/symfony/security-bundle/Security/FirewallMap.php',
    '_ContaoManager\\Symfony\\Bundle\\SecurityBundle\\Security\\LazyFirewallContext' => $vendorDir . '/symfony/security-bundle/Security/LazyFirewallContext.php',
    '_ContaoManager\\Symfony\\Bundle\\SecurityBundle\\Security\\UserAuthenticator' => $vendorDir . '/symfony/security-bundle/Security/UserAuthenticator.php',
    '_ContaoManager\\Symfony\\Component\\Cache\\Adapter\\AbstractAdapter' => $vendorDir . '/symfony/cache/Adapter/AbstractAdapter.php',
    '_ContaoManager\\Symfony\\Component\\Cache\\Adapter\\AbstractTagAwareAdapter' => $vendorDir . '/symfony/cache/Adapter/AbstractTagAwareAdapter.php',
    '_ContaoManager\\Symfony\\Component\\Cache\\Adapter\\AdapterInterface' => $vendorDir . '/symfony/cache/Adapter/AdapterInterface.php',
    '_ContaoManager\\Symfony\\Component\\Cache\\Adapter\\ApcuAdapter' => $vendorDir . '/symfony/cache/Adapter/ApcuAdapter.php',
    '_ContaoManager\\Symfony\\Component\\Cache\\Adapter\\ArrayAdapter' => $vendorDir . '/symfony/cache/Adapter/ArrayAdapter.php',
    '_ContaoManager\\Symfony\\Component\\Cache\\Adapter\\ChainAdapter' => $vendorDir . '/symfony/cache/Adapter/ChainAdapter.php',
    '_ContaoManager\\Symfony\\Component\\Cache\\Adapter\\CouchbaseBucketAdapter' => $vendorDir . '/symfony/cache/Adapter/CouchbaseBucketAdapter.php',
    '_ContaoManager\\Symfony\\Component\\Cache\\Adapter\\CouchbaseCollectionAdapter' => $vendorDir . '/symfony/cache/Adapter/CouchbaseCollectionAdapter.php',
    '_ContaoManager\\Symfony\\Component\\Cache\\Adapter\\DoctrineDbalAdapter' => $vendorDir . '/symfony/cache/Adapter/DoctrineDbalAdapter.php',
    '_ContaoManager\\Symfony\\Component\\Cache\\Adapter\\FilesystemAdapter' => $vendorDir . '/symfony/cache/Adapter/FilesystemAdapter.php',
    '_ContaoManager\\Symfony\\Component\\Cache\\Adapter\\FilesystemTagAwareAdapter' => $vendorDir . '/symfony/cache/Adapter/FilesystemTagAwareAdapter.php',
    '_ContaoManager\\Symfony\\Component\\Cache\\Adapter\\MemcachedAdapter' => $vendorDir . '/symfony/cache/Adapter/MemcachedAdapter.php',
    '_ContaoManager\\Symfony\\Component\\Cache\\Adapter\\NullAdapter' => $vendorDir . '/symfony/cache/Adapter/NullAdapter.php',
    '_ContaoManager\\Symfony\\Component\\Cache\\Adapter\\ParameterNormalizer' => $vendorDir . '/symfony/cache/Adapter/ParameterNormalizer.php',
    '_ContaoManager\\Symfony\\Component\\Cache\\Adapter\\PdoAdapter' => $vendorDir . '/symfony/cache/Adapter/PdoAdapter.php',
    '_ContaoManager\\Symfony\\Component\\Cache\\Adapter\\PhpArrayAdapter' => $vendorDir . '/symfony/cache/Adapter/PhpArrayAdapter.php',
    '_ContaoManager\\Symfony\\Component\\Cache\\Adapter\\PhpFilesAdapter' => $vendorDir . '/symfony/cache/Adapter/PhpFilesAdapter.php',
    '_ContaoManager\\Symfony\\Component\\Cache\\Adapter\\ProxyAdapter' => $vendorDir . '/symfony/cache/Adapter/ProxyAdapter.php',
    '_ContaoManager\\Symfony\\Component\\Cache\\Adapter\\Psr16Adapter' => $vendorDir . '/symfony/cache/Adapter/Psr16Adapter.php',
    '_ContaoManager\\Symfony\\Component\\Cache\\Adapter\\RedisAdapter' => $vendorDir . '/symfony/cache/Adapter/RedisAdapter.php',
    '_ContaoManager\\Symfony\\Component\\Cache\\Adapter\\RedisTagAwareAdapter' => $vendorDir . '/symfony/cache/Adapter/RedisTagAwareAdapter.php',
    '_ContaoManager\\Symfony\\Component\\Cache\\Adapter\\TagAwareAdapter' => $vendorDir . '/symfony/cache/Adapter/TagAwareAdapter.php',
    '_ContaoManager\\Symfony\\Component\\Cache\\Adapter\\TagAwareAdapterInterface' => $vendorDir . '/symfony/cache/Adapter/TagAwareAdapterInterface.php',
    '_ContaoManager\\Symfony\\Component\\Cache\\Adapter\\TraceableAdapter' => $vendorDir . '/symfony/cache/Adapter/TraceableAdapter.php',
    '_ContaoManager\\Symfony\\Component\\Cache\\Adapter\\TraceableTagAwareAdapter' => $vendorDir . '/symfony/cache/Adapter/TraceableTagAwareAdapter.php',
    '_ContaoManager\\Symfony\\Component\\Cache\\CacheItem' => $vendorDir . '/symfony/cache/CacheItem.php',
    '_ContaoManager\\Symfony\\Component\\Cache\\DataCollector\\CacheDataCollector' => $vendorDir . '/symfony/cache/DataCollector/CacheDataCollector.php',
    '_ContaoManager\\Symfony\\Component\\Cache\\DependencyInjection\\CacheCollectorPass' => $vendorDir . '/symfony/cache/DependencyInjection/CacheCollectorPass.php',
    '_ContaoManager\\Symfony\\Component\\Cache\\DependencyInjection\\CachePoolClearerPass' => $vendorDir . '/symfony/cache/DependencyInjection/CachePoolClearerPass.php',
    '_ContaoManager\\Symfony\\Component\\Cache\\DependencyInjection\\CachePoolPass' => $vendorDir . '/symfony/cache/DependencyInjection/CachePoolPass.php',
    '_ContaoManager\\Symfony\\Component\\Cache\\DependencyInjection\\CachePoolPrunerPass' => $vendorDir . '/symfony/cache/DependencyInjection/CachePoolPrunerPass.php',
    '_ContaoManager\\Symfony\\Component\\Cache\\Exception\\CacheException' => $vendorDir . '/symfony/cache/Exception/CacheException.php',
    '_ContaoManager\\Symfony\\Component\\Cache\\Exception\\InvalidArgumentException' => $vendorDir . '/symfony/cache/Exception/InvalidArgumentException.php',
    '_ContaoManager\\Symfony\\Component\\Cache\\Exception\\LogicException' => $vendorDir . '/symfony/cache/Exception/LogicException.php',
    '_ContaoManager\\Symfony\\Component\\Cache\\LockRegistry' => $vendorDir . '/symfony/cache/LockRegistry.php',
    '_ContaoManager\\Symfony\\Component\\Cache\\Marshaller\\DefaultMarshaller' => $vendorDir . '/symfony/cache/Marshaller/DefaultMarshaller.php',
    '_ContaoManager\\Symfony\\Component\\Cache\\Marshaller\\DeflateMarshaller' => $vendorDir . '/symfony/cache/Marshaller/DeflateMarshaller.php',
    '_ContaoManager\\Symfony\\Component\\Cache\\Marshaller\\MarshallerInterface' => $vendorDir . '/symfony/cache/Marshaller/MarshallerInterface.php',
    '_ContaoManager\\Symfony\\Component\\Cache\\Marshaller\\SodiumMarshaller' => $vendorDir . '/symfony/cache/Marshaller/SodiumMarshaller.php',
    '_ContaoManager\\Symfony\\Component\\Cache\\Marshaller\\TagAwareMarshaller' => $vendorDir . '/symfony/cache/Marshaller/TagAwareMarshaller.php',
    '_ContaoManager\\Symfony\\Component\\Cache\\Messenger\\EarlyExpirationDispatcher' => $vendorDir . '/symfony/cache/Messenger/EarlyExpirationDispatcher.php',
    '_ContaoManager\\Symfony\\Component\\Cache\\Messenger\\EarlyExpirationHandler' => $vendorDir . '/symfony/cache/Messenger/EarlyExpirationHandler.php',
    '_ContaoManager\\Symfony\\Component\\Cache\\Messenger\\EarlyExpirationMessage' => $vendorDir . '/symfony/cache/Messenger/EarlyExpirationMessage.php',
    '_ContaoManager\\Symfony\\Component\\Cache\\PruneableInterface' => $vendorDir . '/symfony/cache/PruneableInterface.php',
    '_ContaoManager\\Symfony\\Component\\Cache\\Psr16Cache' => $vendorDir . '/symfony/cache/Psr16Cache.php',
    '_ContaoManager\\Symfony\\Component\\Cache\\ResettableInterface' => $vendorDir . '/symfony/cache/ResettableInterface.php',
    '_ContaoManager\\Symfony\\Component\\Cache\\Traits\\AbstractAdapterTrait' => $vendorDir . '/symfony/cache/Traits/AbstractAdapterTrait.php',
    '_ContaoManager\\Symfony\\Component\\Cache\\Traits\\CachedValueInterface' => $vendorDir . '/symfony/cache/Traits/CachedValueInterface.php',
    '_ContaoManager\\Symfony\\Component\\Cache\\Traits\\ContractsTrait' => $vendorDir . '/symfony/cache/Traits/ContractsTrait.php',
    '_ContaoManager\\Symfony\\Component\\Cache\\Traits\\FilesystemCommonTrait' => $vendorDir . '/symfony/cache/Traits/FilesystemCommonTrait.php',
    '_ContaoManager\\Symfony\\Component\\Cache\\Traits\\FilesystemTrait' => $vendorDir . '/symfony/cache/Traits/FilesystemTrait.php',
    '_ContaoManager\\Symfony\\Component\\Cache\\Traits\\ProxyTrait' => $vendorDir . '/symfony/cache/Traits/ProxyTrait.php',
    '_ContaoManager\\Symfony\\Component\\Cache\\Traits\\Redis5Proxy' => $vendorDir . '/symfony/cache/Traits/Redis5Proxy.php',
    '_ContaoManager\\Symfony\\Component\\Cache\\Traits\\Redis61ProxyTrait' => $vendorDir . '/symfony/cache/Traits/Redis61ProxyTrait.php',
    '_ContaoManager\\Symfony\\Component\\Cache\\Traits\\Redis62ProxyTrait' => $vendorDir . '/symfony/cache/Traits/Redis62ProxyTrait.php',
    '_ContaoManager\\Symfony\\Component\\Cache\\Traits\\Redis63ProxyTrait' => $vendorDir . '/symfony/cache/Traits/Redis63ProxyTrait.php',
    '_ContaoManager\\Symfony\\Component\\Cache\\Traits\\Redis6Proxy' => $vendorDir . '/symfony/cache/Traits/Redis6Proxy.php',
    '_ContaoManager\\Symfony\\Component\\Cache\\Traits\\RedisCluster5Proxy' => $vendorDir . '/symfony/cache/Traits/RedisCluster5Proxy.php',
    '_ContaoManager\\Symfony\\Component\\Cache\\Traits\\RedisCluster61ProxyTrait' => $vendorDir . '/symfony/cache/Traits/RedisCluster61ProxyTrait.php',
    '_ContaoManager\\Symfony\\Component\\Cache\\Traits\\RedisCluster62ProxyTrait' => $vendorDir . '/symfony/cache/Traits/RedisCluster62ProxyTrait.php',
    '_ContaoManager\\Symfony\\Component\\Cache\\Traits\\RedisCluster63ProxyTrait' => $vendorDir . '/symfony/cache/Traits/RedisCluster63ProxyTrait.php',
    '_ContaoManager\\Symfony\\Component\\Cache\\Traits\\RedisCluster6Proxy' => $vendorDir . '/symfony/cache/Traits/RedisCluster6Proxy.php',
    '_ContaoManager\\Symfony\\Component\\Cache\\Traits\\RedisClusterNodeProxy' => $vendorDir . '/symfony/cache/Traits/RedisClusterNodeProxy.php',
    '_ContaoManager\\Symfony\\Component\\Cache\\Traits\\RedisClusterProxy' => $vendorDir . '/symfony/cache/Traits/RedisClusterProxy.php',
    '_ContaoManager\\Symfony\\Component\\Cache\\Traits\\RedisProxy' => $vendorDir . '/symfony/cache/Traits/RedisProxy.php',
    '_ContaoManager\\Symfony\\Component\\Cache\\Traits\\RedisTrait' => $vendorDir . '/symfony/cache/Traits/RedisTrait.php',
    '_ContaoManager\\Symfony\\Component\\Cache\\Traits\\RelayProxy' => $vendorDir . '/symfony/cache/Traits/RelayProxy.php',
    '_ContaoManager\\Symfony\\Component\\Cache\\Traits\\RelayProxyTrait' => $vendorDir . '/symfony/cache/Traits/RelayProxyTrait.php',
    '_ContaoManager\\Symfony\\Component\\Cache\\Traits\\Relay\\BgsaveTrait' => $vendorDir . '/symfony/cache/Traits/Relay/BgsaveTrait.php',
    '_ContaoManager\\Symfony\\Component\\Cache\\Traits\\Relay\\CopyTrait' => $vendorDir . '/symfony/cache/Traits/Relay/CopyTrait.php',
    '_ContaoManager\\Symfony\\Component\\Cache\\Traits\\Relay\\FtTrait' => $vendorDir . '/symfony/cache/Traits/Relay/FtTrait.php',
    '_ContaoManager\\Symfony\\Component\\Cache\\Traits\\Relay\\GeosearchTrait' => $vendorDir . '/symfony/cache/Traits/Relay/GeosearchTrait.php',
    '_ContaoManager\\Symfony\\Component\\Cache\\Traits\\Relay\\GetWithMetaTrait' => $vendorDir . '/symfony/cache/Traits/Relay/GetWithMetaTrait.php',
    '_ContaoManager\\Symfony\\Component\\Cache\\Traits\\Relay\\GetrangeTrait' => $vendorDir . '/symfony/cache/Traits/Relay/GetrangeTrait.php',
    '_ContaoManager\\Symfony\\Component\\Cache\\Traits\\Relay\\HsetTrait' => $vendorDir . '/symfony/cache/Traits/Relay/HsetTrait.php',
    '_ContaoManager\\Symfony\\Component\\Cache\\Traits\\Relay\\IsTrackedTrait' => $vendorDir . '/symfony/cache/Traits/Relay/IsTrackedTrait.php',
    '_ContaoManager\\Symfony\\Component\\Cache\\Traits\\Relay\\MoveTrait' => $vendorDir . '/symfony/cache/Traits/Relay/MoveTrait.php',
    '_ContaoManager\\Symfony\\Component\\Cache\\Traits\\Relay\\NullableReturnTrait' => $vendorDir . '/symfony/cache/Traits/Relay/NullableReturnTrait.php',
    '_ContaoManager\\Symfony\\Component\\Cache\\Traits\\Relay\\PfcountTrait' => $vendorDir . '/symfony/cache/Traits/Relay/PfcountTrait.php',
    '_ContaoManager\\Symfony\\Component\\Cache\\Traits\\Relay\\Relay11Trait' => $vendorDir . '/symfony/cache/Traits/Relay/Relay11Trait.php',
    '_ContaoManager\\Symfony\\Component\\Cache\\Traits\\Relay\\Relay121Trait' => $vendorDir . '/symfony/cache/Traits/Relay/Relay121Trait.php',
    '_ContaoManager\\Symfony\\Component\\Cache\\Traits\\Relay\\Relay12Trait' => $vendorDir . '/symfony/cache/Traits/Relay/Relay12Trait.php',
    '_ContaoManager\\Symfony\\Component\\Cache\\Traits\\Relay\\Relay20Trait' => $vendorDir . '/symfony/cache/Traits/Relay/Relay20Trait.php',
    '_ContaoManager\\Symfony\\Component\\Cache\\Traits\\Relay\\Relay21Trait' => $vendorDir . '/symfony/cache/Traits/Relay/Relay21Trait.php',
    '_ContaoManager\\Symfony\\Component\\Cache\\Traits\\Relay\\SwapdbTrait' => $vendorDir . '/symfony/cache/Traits/Relay/SwapdbTrait.php',
    '_ContaoManager\\Symfony\\Component\\Clock\\Clock' => $vendorDir . '/symfony/clock/Clock.php',
    '_ContaoManager\\Symfony\\Component\\Clock\\ClockAwareTrait' => $vendorDir . '/symfony/clock/ClockAwareTrait.php',
    '_ContaoManager\\Symfony\\Component\\Clock\\ClockInterface' => $vendorDir . '/symfony/clock/ClockInterface.php',
    '_ContaoManager\\Symfony\\Component\\Clock\\DatePoint' => $vendorDir . '/symfony/clock/DatePoint.php',
    '_ContaoManager\\Symfony\\Component\\Clock\\MockClock' => $vendorDir . '/symfony/clock/MockClock.php',
    '_ContaoManager\\Symfony\\Component\\Clock\\MonotonicClock' => $vendorDir . '/symfony/clock/MonotonicClock.php',
    '_ContaoManager\\Symfony\\Component\\Clock\\NativeClock' => $vendorDir . '/symfony/clock/NativeClock.php',
    '_ContaoManager\\Symfony\\Component\\Clock\\Test\\ClockSensitiveTrait' => $vendorDir . '/symfony/clock/Test/ClockSensitiveTrait.php',
    '_ContaoManager\\Symfony\\Component\\Config\\Builder\\ClassBuilder' => $vendorDir . '/symfony/config/Builder/ClassBuilder.php',
    '_ContaoManager\\Symfony\\Component\\Config\\Builder\\ConfigBuilderGenerator' => $vendorDir . '/symfony/config/Builder/ConfigBuilderGenerator.php',
    '_ContaoManager\\Symfony\\Component\\Config\\Builder\\ConfigBuilderGeneratorInterface' => $vendorDir . '/symfony/config/Builder/ConfigBuilderGeneratorInterface.php',
    '_ContaoManager\\Symfony\\Component\\Config\\Builder\\ConfigBuilderInterface' => $vendorDir . '/symfony/config/Builder/ConfigBuilderInterface.php',
    '_ContaoManager\\Symfony\\Component\\Config\\Builder\\Method' => $vendorDir . '/symfony/config/Builder/Method.php',
    '_ContaoManager\\Symfony\\Component\\Config\\Builder\\Property' => $vendorDir . '/symfony/config/Builder/Property.php',
    '_ContaoManager\\Symfony\\Component\\Config\\ConfigCache' => $vendorDir . '/symfony/config/ConfigCache.php',
    '_ContaoManager\\Symfony\\Component\\Config\\ConfigCacheFactory' => $vendorDir . '/symfony/config/ConfigCacheFactory.php',
    '_ContaoManager\\Symfony\\Component\\Config\\ConfigCacheFactoryInterface' => $vendorDir . '/symfony/config/ConfigCacheFactoryInterface.php',
    '_ContaoManager\\Symfony\\Component\\Config\\ConfigCacheInterface' => $vendorDir . '/symfony/config/ConfigCacheInterface.php',
    '_ContaoManager\\Symfony\\Component\\Config\\Definition\\ArrayNode' => $vendorDir . '/symfony/config/Definition/ArrayNode.php',
    '_ContaoManager\\Symfony\\Component\\Config\\Definition\\BaseNode' => $vendorDir . '/symfony/config/Definition/BaseNode.php',
    '_ContaoManager\\Symfony\\Component\\Config\\Definition\\BooleanNode' => $vendorDir . '/symfony/config/Definition/BooleanNode.php',
    '_ContaoManager\\Symfony\\Component\\Config\\Definition\\Builder\\ArrayNodeDefinition' => $vendorDir . '/symfony/config/Definition/Builder/ArrayNodeDefinition.php',
    '_ContaoManager\\Symfony\\Component\\Config\\Definition\\Builder\\BooleanNodeDefinition' => $vendorDir . '/symfony/config/Definition/Builder/BooleanNodeDefinition.php',
    '_ContaoManager\\Symfony\\Component\\Config\\Definition\\Builder\\BuilderAwareInterface' => $vendorDir . '/symfony/config/Definition/Builder/BuilderAwareInterface.php',
    '_ContaoManager\\Symfony\\Component\\Config\\Definition\\Builder\\EnumNodeDefinition' => $vendorDir . '/symfony/config/Definition/Builder/EnumNodeDefinition.php',
    '_ContaoManager\\Symfony\\Component\\Config\\Definition\\Builder\\ExprBuilder' => $vendorDir . '/symfony/config/Definition/Builder/ExprBuilder.php',
    '_ContaoManager\\Symfony\\Component\\Config\\Definition\\Builder\\FloatNodeDefinition' => $vendorDir . '/symfony/config/Definition/Builder/FloatNodeDefinition.php',
    '_ContaoManager\\Symfony\\Component\\Config\\Definition\\Builder\\IntegerNodeDefinition' => $vendorDir . '/symfony/config/Definition/Builder/IntegerNodeDefinition.php',
    '_ContaoManager\\Symfony\\Component\\Config\\Definition\\Builder\\MergeBuilder' => $vendorDir . '/symfony/config/Definition/Builder/MergeBuilder.php',
    '_ContaoManager\\Symfony\\Component\\Config\\Definition\\Builder\\NodeBuilder' => $vendorDir . '/symfony/config/Definition/Builder/NodeBuilder.php',
    '_ContaoManager\\Symfony\\Component\\Config\\Definition\\Builder\\NodeDefinition' => $vendorDir . '/symfony/config/Definition/Builder/NodeDefinition.php',
    '_ContaoManager\\Symfony\\Component\\Config\\Definition\\Builder\\NodeParentInterface' => $vendorDir . '/symfony/config/Definition/Builder/NodeParentInterface.php',
    '_ContaoManager\\Symfony\\Component\\Config\\Definition\\Builder\\NormalizationBuilder' => $vendorDir . '/symfony/config/Definition/Builder/NormalizationBuilder.php',
    '_ContaoManager\\Symfony\\Component\\Config\\Definition\\Builder\\NumericNodeDefinition' => $vendorDir . '/symfony/config/Definition/Builder/NumericNodeDefinition.php',
    '_ContaoManager\\Symfony\\Component\\Config\\Definition\\Builder\\ParentNodeDefinitionInterface' => $vendorDir . '/symfony/config/Definition/Builder/ParentNodeDefinitionInterface.php',
    '_ContaoManager\\Symfony\\Component\\Config\\Definition\\Builder\\ScalarNodeDefinition' => $vendorDir . '/symfony/config/Definition/Builder/ScalarNodeDefinition.php',
    '_ContaoManager\\Symfony\\Component\\Config\\Definition\\Builder\\TreeBuilder' => $vendorDir . '/symfony/config/Definition/Builder/TreeBuilder.php',
    '_ContaoManager\\Symfony\\Component\\Config\\Definition\\Builder\\ValidationBuilder' => $vendorDir . '/symfony/config/Definition/Builder/ValidationBuilder.php',
    '_ContaoManager\\Symfony\\Component\\Config\\Definition\\Builder\\VariableNodeDefinition' => $vendorDir . '/symfony/config/Definition/Builder/VariableNodeDefinition.php',
    '_ContaoManager\\Symfony\\Component\\Config\\Definition\\ConfigurableInterface' => $vendorDir . '/symfony/config/Definition/ConfigurableInterface.php',
    '_ContaoManager\\Symfony\\Component\\Config\\Definition\\Configuration' => $vendorDir . '/symfony/config/Definition/Configuration.php',
    '_ContaoManager\\Symfony\\Component\\Config\\Definition\\ConfigurationInterface' => $vendorDir . '/symfony/config/Definition/ConfigurationInterface.php',
    '_ContaoManager\\Symfony\\Component\\Config\\Definition\\Configurator\\DefinitionConfigurator' => $vendorDir . '/symfony/config/Definition/Configurator/DefinitionConfigurator.php',
    '_ContaoManager\\Symfony\\Component\\Config\\Definition\\Dumper\\XmlReferenceDumper' => $vendorDir . '/symfony/config/Definition/Dumper/XmlReferenceDumper.php',
    '_ContaoManager\\Symfony\\Component\\Config\\Definition\\Dumper\\YamlReferenceDumper' => $vendorDir . '/symfony/config/Definition/Dumper/YamlReferenceDumper.php',
    '_ContaoManager\\Symfony\\Component\\Config\\Definition\\EnumNode' => $vendorDir . '/symfony/config/Definition/EnumNode.php',
    '_ContaoManager\\Symfony\\Component\\Config\\Definition\\Exception\\DuplicateKeyException' => $vendorDir . '/symfony/config/Definition/Exception/DuplicateKeyException.php',
    '_ContaoManager\\Symfony\\Component\\Config\\Definition\\Exception\\Exception' => $vendorDir . '/symfony/config/Definition/Exception/Exception.php',
    '_ContaoManager\\Symfony\\Component\\Config\\Definition\\Exception\\ForbiddenOverwriteException' => $vendorDir . '/symfony/config/Definition/Exception/ForbiddenOverwriteException.php',
    '_ContaoManager\\Symfony\\Component\\Config\\Definition\\Exception\\InvalidConfigurationException' => $vendorDir . '/symfony/config/Definition/Exception/InvalidConfigurationException.php',
    '_ContaoManager\\Symfony\\Component\\Config\\Definition\\Exception\\InvalidDefinitionException' => $vendorDir . '/symfony/config/Definition/Exception/InvalidDefinitionException.php',
    '_ContaoManager\\Symfony\\Component\\Config\\Definition\\Exception\\InvalidTypeException' => $vendorDir . '/symfony/config/Definition/Exception/InvalidTypeException.php',
    '_ContaoManager\\Symfony\\Component\\Config\\Definition\\Exception\\UnsetKeyException' => $vendorDir . '/symfony/config/Definition/Exception/UnsetKeyException.php',
    '_ContaoManager\\Symfony\\Component\\Config\\Definition\\FloatNode' => $vendorDir . '/symfony/config/Definition/FloatNode.php',
    '_ContaoManager\\Symfony\\Component\\Config\\Definition\\IntegerNode' => $vendorDir . '/symfony/config/Definition/IntegerNode.php',
    '_ContaoManager\\Symfony\\Component\\Config\\Definition\\Loader\\DefinitionFileLoader' => $vendorDir . '/symfony/config/Definition/Loader/DefinitionFileLoader.php',
    '_ContaoManager\\Symfony\\Component\\Config\\Definition\\NodeInterface' => $vendorDir . '/symfony/config/Definition/NodeInterface.php',
    '_ContaoManager\\Symfony\\Component\\Config\\Definition\\NumericNode' => $vendorDir . '/symfony/config/Definition/NumericNode.php',
    '_ContaoManager\\Symfony\\Component\\Config\\Definition\\Processor' => $vendorDir . '/symfony/config/Definition/Processor.php',
    '_ContaoManager\\Symfony\\Component\\Config\\Definition\\PrototypeNodeInterface' => $vendorDir . '/symfony/config/Definition/PrototypeNodeInterface.php',
    '_ContaoManager\\Symfony\\Component\\Config\\Definition\\PrototypedArrayNode' => $vendorDir . '/symfony/config/Definition/PrototypedArrayNode.php',
    '_ContaoManager\\Symfony\\Component\\Config\\Definition\\ScalarNode' => $vendorDir . '/symfony/config/Definition/ScalarNode.php',
    '_ContaoManager\\Symfony\\Component\\Config\\Definition\\VariableNode' => $vendorDir . '/symfony/config/Definition/VariableNode.php',
    '_ContaoManager\\Symfony\\Component\\Config\\Exception\\FileLoaderImportCircularReferenceException' => $vendorDir . '/symfony/config/Exception/FileLoaderImportCircularReferenceException.php',
    '_ContaoManager\\Symfony\\Component\\Config\\Exception\\FileLocatorFileNotFoundException' => $vendorDir . '/symfony/config/Exception/FileLocatorFileNotFoundException.php',
    '_ContaoManager\\Symfony\\Component\\Config\\Exception\\LoaderLoadException' => $vendorDir . '/symfony/config/Exception/LoaderLoadException.php',
    '_ContaoManager\\Symfony\\Component\\Config\\FileLocator' => $vendorDir . '/symfony/config/FileLocator.php',
    '_ContaoManager\\Symfony\\Component\\Config\\FileLocatorInterface' => $vendorDir . '/symfony/config/FileLocatorInterface.php',
    '_ContaoManager\\Symfony\\Component\\Config\\Loader\\DelegatingLoader' => $vendorDir . '/symfony/config/Loader/DelegatingLoader.php',
    '_ContaoManager\\Symfony\\Component\\Config\\Loader\\DirectoryAwareLoaderInterface' => $vendorDir . '/symfony/config/Loader/DirectoryAwareLoaderInterface.php',
    '_ContaoManager\\Symfony\\Component\\Config\\Loader\\FileLoader' => $vendorDir . '/symfony/config/Loader/FileLoader.php',
    '_ContaoManager\\Symfony\\Component\\Config\\Loader\\GlobFileLoader' => $vendorDir . '/symfony/config/Loader/GlobFileLoader.php',
    '_ContaoManager\\Symfony\\Component\\Config\\Loader\\Loader' => $vendorDir . '/symfony/config/Loader/Loader.php',
    '_ContaoManager\\Symfony\\Component\\Config\\Loader\\LoaderInterface' => $vendorDir . '/symfony/config/Loader/LoaderInterface.php',
    '_ContaoManager\\Symfony\\Component\\Config\\Loader\\LoaderResolver' => $vendorDir . '/symfony/config/Loader/LoaderResolver.php',
    '_ContaoManager\\Symfony\\Component\\Config\\Loader\\LoaderResolverInterface' => $vendorDir . '/symfony/config/Loader/LoaderResolverInterface.php',
    '_ContaoManager\\Symfony\\Component\\Config\\Loader\\ParamConfigurator' => $vendorDir . '/symfony/config/Loader/ParamConfigurator.php',
    '_ContaoManager\\Symfony\\Component\\Config\\ResourceCheckerConfigCache' => $vendorDir . '/symfony/config/ResourceCheckerConfigCache.php',
    '_ContaoManager\\Symfony\\Component\\Config\\ResourceCheckerConfigCacheFactory' => $vendorDir . '/symfony/config/ResourceCheckerConfigCacheFactory.php',
    '_ContaoManager\\Symfony\\Component\\Config\\ResourceCheckerInterface' => $vendorDir . '/symfony/config/ResourceCheckerInterface.php',
    '_ContaoManager\\Symfony\\Component\\Config\\Resource\\ClassExistenceResource' => $vendorDir . '/symfony/config/Resource/ClassExistenceResource.php',
    '_ContaoManager\\Symfony\\Component\\Config\\Resource\\ComposerResource' => $vendorDir . '/symfony/config/Resource/ComposerResource.php',
    '_ContaoManager\\Symfony\\Component\\Config\\Resource\\DirectoryResource' => $vendorDir . '/symfony/config/Resource/DirectoryResource.php',
    '_ContaoManager\\Symfony\\Component\\Config\\Resource\\FileExistenceResource' => $vendorDir . '/symfony/config/Resource/FileExistenceResource.php',
    '_ContaoManager\\Symfony\\Component\\Config\\Resource\\FileResource' => $vendorDir . '/symfony/config/Resource/FileResource.php',
    '_ContaoManager\\Symfony\\Component\\Config\\Resource\\GlobResource' => $vendorDir . '/symfony/config/Resource/GlobResource.php',
    '_ContaoManager\\Symfony\\Component\\Config\\Resource\\ReflectionClassResource' => $vendorDir . '/symfony/config/Resource/ReflectionClassResource.php',
    '_ContaoManager\\Symfony\\Component\\Config\\Resource\\ResourceInterface' => $vendorDir . '/symfony/config/Resource/ResourceInterface.php',
    '_ContaoManager\\Symfony\\Component\\Config\\Resource\\SelfCheckingResourceChecker' => $vendorDir . '/symfony/config/Resource/SelfCheckingResourceChecker.php',
    '_ContaoManager\\Symfony\\Component\\Config\\Resource\\SelfCheckingResourceInterface' => $vendorDir . '/symfony/config/Resource/SelfCheckingResourceInterface.php',
    '_ContaoManager\\Symfony\\Component\\Config\\Util\\Exception\\InvalidXmlException' => $vendorDir . '/symfony/config/Util/Exception/InvalidXmlException.php',
    '_ContaoManager\\Symfony\\Component\\Config\\Util\\Exception\\XmlParsingException' => $vendorDir . '/symfony/config/Util/Exception/XmlParsingException.php',
    '_ContaoManager\\Symfony\\Component\\Config\\Util\\XmlUtils' => $vendorDir . '/symfony/config/Util/XmlUtils.php',
    '_ContaoManager\\Symfony\\Component\\Console\\Application' => $vendorDir . '/symfony/console/Application.php',
    '_ContaoManager\\Symfony\\Component\\Console\\Attribute\\AsCommand' => $vendorDir . '/symfony/console/Attribute/AsCommand.php',
    '_ContaoManager\\Symfony\\Component\\Console\\CI\\GithubActionReporter' => $vendorDir . '/symfony/console/CI/GithubActionReporter.php',
    '_ContaoManager\\Symfony\\Component\\Console\\Color' => $vendorDir . '/symfony/console/Color.php',
    '_ContaoManager\\Symfony\\Component\\Console\\CommandLoader\\CommandLoaderInterface' => $vendorDir . '/symfony/console/CommandLoader/CommandLoaderInterface.php',
    '_ContaoManager\\Symfony\\Component\\Console\\CommandLoader\\ContainerCommandLoader' => $vendorDir . '/symfony/console/CommandLoader/ContainerCommandLoader.php',
    '_ContaoManager\\Symfony\\Component\\Console\\CommandLoader\\FactoryCommandLoader' => $vendorDir . '/symfony/console/CommandLoader/FactoryCommandLoader.php',
    '_ContaoManager\\Symfony\\Component\\Console\\Command\\Command' => $vendorDir . '/symfony/console/Command/Command.php',
    '_ContaoManager\\Symfony\\Component\\Console\\Command\\CompleteCommand' => $vendorDir . '/symfony/console/Command/CompleteCommand.php',
    '_ContaoManager\\Symfony\\Component\\Console\\Command\\DumpCompletionCommand' => $vendorDir . '/symfony/console/Command/DumpCompletionCommand.php',
    '_ContaoManager\\Symfony\\Component\\Console\\Command\\HelpCommand' => $vendorDir . '/symfony/console/Command/HelpCommand.php',
    '_ContaoManager\\Symfony\\Component\\Console\\Command\\LazyCommand' => $vendorDir . '/symfony/console/Command/LazyCommand.php',
    '_ContaoManager\\Symfony\\Component\\Console\\Command\\ListCommand' => $vendorDir . '/symfony/console/Command/ListCommand.php',
    '_ContaoManager\\Symfony\\Component\\Console\\Command\\LockableTrait' => $vendorDir . '/symfony/console/Command/LockableTrait.php',
    '_ContaoManager\\Symfony\\Component\\Console\\Command\\SignalableCommandInterface' => $vendorDir . '/symfony/console/Command/SignalableCommandInterface.php',
    '_ContaoManager\\Symfony\\Component\\Console\\Command\\TraceableCommand' => $vendorDir . '/symfony/console/Command/TraceableCommand.php',
    '_ContaoManager\\Symfony\\Component\\Console\\Completion\\CompletionInput' => $vendorDir . '/symfony/console/Completion/CompletionInput.php',
    '_ContaoManager\\Symfony\\Component\\Console\\Completion\\CompletionSuggestions' => $vendorDir . '/symfony/console/Completion/CompletionSuggestions.php',
    '_ContaoManager\\Symfony\\Component\\Console\\Completion\\Output\\BashCompletionOutput' => $vendorDir . '/symfony/console/Completion/Output/BashCompletionOutput.php',
    '_ContaoManager\\Symfony\\Component\\Console\\Completion\\Output\\CompletionOutputInterface' => $vendorDir . '/symfony/console/Completion/Output/CompletionOutputInterface.php',
    '_ContaoManager\\Symfony\\Component\\Console\\Completion\\Output\\FishCompletionOutput' => $vendorDir . '/symfony/console/Completion/Output/FishCompletionOutput.php',
    '_ContaoManager\\Symfony\\Component\\Console\\Completion\\Output\\ZshCompletionOutput' => $vendorDir . '/symfony/console/Completion/Output/ZshCompletionOutput.php',
    '_ContaoManager\\Symfony\\Component\\Console\\Completion\\Suggestion' => $vendorDir . '/symfony/console/Completion/Suggestion.php',
    '_ContaoManager\\Symfony\\Component\\Console\\ConsoleEvents' => $vendorDir . '/symfony/console/ConsoleEvents.php',
    '_ContaoManager\\Symfony\\Component\\Console\\Cursor' => $vendorDir . '/symfony/console/Cursor.php',
    '_ContaoManager\\Symfony\\Component\\Console\\DataCollector\\CommandDataCollector' => $vendorDir . '/symfony/console/DataCollector/CommandDataCollector.php',
    '_ContaoManager\\Symfony\\Component\\Console\\Debug\\CliRequest' => $vendorDir . '/symfony/console/Debug/CliRequest.php',
    '_ContaoManager\\Symfony\\Component\\Console\\DependencyInjection\\AddConsoleCommandPass' => $vendorDir . '/symfony/console/DependencyInjection/AddConsoleCommandPass.php',
    '_ContaoManager\\Symfony\\Component\\Console\\Descriptor\\ApplicationDescription' => $vendorDir . '/symfony/console/Descriptor/ApplicationDescription.php',
    '_ContaoManager\\Symfony\\Component\\Console\\Descriptor\\Descriptor' => $vendorDir . '/symfony/console/Descriptor/Descriptor.php',
    '_ContaoManager\\Symfony\\Component\\Console\\Descriptor\\DescriptorInterface' => $vendorDir . '/symfony/console/Descriptor/DescriptorInterface.php',
    '_ContaoManager\\Symfony\\Component\\Console\\Descriptor\\JsonDescriptor' => $vendorDir . '/symfony/console/Descriptor/JsonDescriptor.php',
    '_ContaoManager\\Symfony\\Component\\Console\\Descriptor\\MarkdownDescriptor' => $vendorDir . '/symfony/console/Descriptor/MarkdownDescriptor.php',
    '_ContaoManager\\Symfony\\Component\\Console\\Descriptor\\ReStructuredTextDescriptor' => $vendorDir . '/symfony/console/Descriptor/ReStructuredTextDescriptor.php',
    '_ContaoManager\\Symfony\\Component\\Console\\Descriptor\\TextDescriptor' => $vendorDir . '/symfony/console/Descriptor/TextDescriptor.php',
    '_ContaoManager\\Symfony\\Component\\Console\\Descriptor\\XmlDescriptor' => $vendorDir . '/symfony/console/Descriptor/XmlDescriptor.php',
    '_ContaoManager\\Symfony\\Component\\Console\\EventListener\\ErrorListener' => $vendorDir . '/symfony/console/EventListener/ErrorListener.php',
    '_ContaoManager\\Symfony\\Component\\Console\\Event\\ConsoleCommandEvent' => $vendorDir . '/symfony/console/Event/ConsoleCommandEvent.php',
    '_ContaoManager\\Symfony\\Component\\Console\\Event\\ConsoleErrorEvent' => $vendorDir . '/symfony/console/Event/ConsoleErrorEvent.php',
    '_ContaoManager\\Symfony\\Component\\Console\\Event\\ConsoleEvent' => $vendorDir . '/symfony/console/Event/ConsoleEvent.php',
    '_ContaoManager\\Symfony\\Component\\Console\\Event\\ConsoleSignalEvent' => $vendorDir . '/symfony/console/Event/ConsoleSignalEvent.php',
    '_ContaoManager\\Symfony\\Component\\Console\\Event\\ConsoleTerminateEvent' => $vendorDir . '/symfony/console/Event/ConsoleTerminateEvent.php',
    '_ContaoManager\\Symfony\\Component\\Console\\Exception\\CommandNotFoundException' => $vendorDir . '/symfony/console/Exception/CommandNotFoundException.php',
    '_ContaoManager\\Symfony\\Component\\Console\\Exception\\ExceptionInterface' => $vendorDir . '/symfony/console/Exception/ExceptionInterface.php',
    '_ContaoManager\\Symfony\\Component\\Console\\Exception\\InvalidArgumentException' => $vendorDir . '/symfony/console/Exception/InvalidArgumentException.php',
    '_ContaoManager\\Symfony\\Component\\Console\\Exception\\InvalidOptionException' => $vendorDir . '/symfony/console/Exception/InvalidOptionException.php',
    '_ContaoManager\\Symfony\\Component\\Console\\Exception\\LogicException' => $vendorDir . '/symfony/console/Exception/LogicException.php',
    '_ContaoManager\\Symfony\\Component\\Console\\Exception\\MissingInputException' => $vendorDir . '/symfony/console/Exception/MissingInputException.php',
    '_ContaoManager\\Symfony\\Component\\Console\\Exception\\NamespaceNotFoundException' => $vendorDir . '/symfony/console/Exception/NamespaceNotFoundException.php',
    '_ContaoManager\\Symfony\\Component\\Console\\Exception\\RunCommandFailedException' => $vendorDir . '/symfony/console/Exception/RunCommandFailedException.php',
    '_ContaoManager\\Symfony\\Component\\Console\\Exception\\RuntimeException' => $vendorDir . '/symfony/console/Exception/RuntimeException.php',
    '_ContaoManager\\Symfony\\Component\\Console\\Formatter\\NullOutputFormatter' => $vendorDir . '/symfony/console/Formatter/NullOutputFormatter.php',
    '_ContaoManager\\Symfony\\Component\\Console\\Formatter\\NullOutputFormatterStyle' => $vendorDir . '/symfony/console/Formatter/NullOutputFormatterStyle.php',
    '_ContaoManager\\Symfony\\Component\\Console\\Formatter\\OutputFormatter' => $vendorDir . '/symfony/console/Formatter/OutputFormatter.php',
    '_ContaoManager\\Symfony\\Component\\Console\\Formatter\\OutputFormatterInterface' => $vendorDir . '/symfony/console/Formatter/OutputFormatterInterface.php',
    '_ContaoManager\\Symfony\\Component\\Console\\Formatter\\OutputFormatterStyle' => $vendorDir . '/symfony/console/Formatter/OutputFormatterStyle.php',
    '_ContaoManager\\Symfony\\Component\\Console\\Formatter\\OutputFormatterStyleInterface' => $vendorDir . '/symfony/console/Formatter/OutputFormatterStyleInterface.php',
    '_ContaoManager\\Symfony\\Component\\Console\\Formatter\\OutputFormatterStyleStack' => $vendorDir . '/symfony/console/Formatter/OutputFormatterStyleStack.php',
    '_ContaoManager\\Symfony\\Component\\Console\\Formatter\\WrappableOutputFormatterInterface' => $vendorDir . '/symfony/console/Formatter/WrappableOutputFormatterInterface.php',
    '_ContaoManager\\Symfony\\Component\\Console\\Helper\\DebugFormatterHelper' => $vendorDir . '/symfony/console/Helper/DebugFormatterHelper.php',
    '_ContaoManager\\Symfony\\Component\\Console\\Helper\\DescriptorHelper' => $vendorDir . '/symfony/console/Helper/DescriptorHelper.php',
    '_ContaoManager\\Symfony\\Component\\Console\\Helper\\Dumper' => $vendorDir . '/symfony/console/Helper/Dumper.php',
    '_ContaoManager\\Symfony\\Component\\Console\\Helper\\FormatterHelper' => $vendorDir . '/symfony/console/Helper/FormatterHelper.php',
    '_ContaoManager\\Symfony\\Component\\Console\\Helper\\Helper' => $vendorDir . '/symfony/console/Helper/Helper.php',
    '_ContaoManager\\Symfony\\Component\\Console\\Helper\\HelperInterface' => $vendorDir . '/symfony/console/Helper/HelperInterface.php',
    '_ContaoManager\\Symfony\\Component\\Console\\Helper\\HelperSet' => $vendorDir . '/symfony/console/Helper/HelperSet.php',
    '_ContaoManager\\Symfony\\Component\\Console\\Helper\\InputAwareHelper' => $vendorDir . '/symfony/console/Helper/InputAwareHelper.php',
    '_ContaoManager\\Symfony\\Component\\Console\\Helper\\OutputWrapper' => $vendorDir . '/symfony/console/Helper/OutputWrapper.php',
    '_ContaoManager\\Symfony\\Component\\Console\\Helper\\ProcessHelper' => $vendorDir . '/symfony/console/Helper/ProcessHelper.php',
    '_ContaoManager\\Symfony\\Component\\Console\\Helper\\ProgressBar' => $vendorDir . '/symfony/console/Helper/ProgressBar.php',
    '_ContaoManager\\Symfony\\Component\\Console\\Helper\\ProgressIndicator' => $vendorDir . '/symfony/console/Helper/ProgressIndicator.php',
    '_ContaoManager\\Symfony\\Component\\Console\\Helper\\QuestionHelper' => $vendorDir . '/symfony/console/Helper/QuestionHelper.php',
    '_ContaoManager\\Symfony\\Component\\Console\\Helper\\SymfonyQuestionHelper' => $vendorDir . '/symfony/console/Helper/SymfonyQuestionHelper.php',
    '_ContaoManager\\Symfony\\Component\\Console\\Helper\\Table' => $vendorDir . '/symfony/console/Helper/Table.php',
    '_ContaoManager\\Symfony\\Component\\Console\\Helper\\TableCell' => $vendorDir . '/symfony/console/Helper/TableCell.php',
    '_ContaoManager\\Symfony\\Component\\Console\\Helper\\TableCellStyle' => $vendorDir . '/symfony/console/Helper/TableCellStyle.php',
    '_ContaoManager\\Symfony\\Component\\Console\\Helper\\TableRows' => $vendorDir . '/symfony/console/Helper/TableRows.php',
    '_ContaoManager\\Symfony\\Component\\Console\\Helper\\TableSeparator' => $vendorDir . '/symfony/console/Helper/TableSeparator.php',
    '_ContaoManager\\Symfony\\Component\\Console\\Helper\\TableStyle' => $vendorDir . '/symfony/console/Helper/TableStyle.php',
    '_ContaoManager\\Symfony\\Component\\Console\\Helper\\TerminalInputHelper' => $vendorDir . '/symfony/console/Helper/TerminalInputHelper.php',
    '_ContaoManager\\Symfony\\Component\\Console\\Input\\ArgvInput' => $vendorDir . '/symfony/console/Input/ArgvInput.php',
    '_ContaoManager\\Symfony\\Component\\Console\\Input\\ArrayInput' => $vendorDir . '/symfony/console/Input/ArrayInput.php',
    '_ContaoManager\\Symfony\\Component\\Console\\Input\\Input' => $vendorDir . '/symfony/console/Input/Input.php',
    '_ContaoManager\\Symfony\\Component\\Console\\Input\\InputArgument' => $vendorDir . '/symfony/console/Input/InputArgument.php',
    '_ContaoManager\\Symfony\\Component\\Console\\Input\\InputAwareInterface' => $vendorDir . '/symfony/console/Input/InputAwareInterface.php',
    '_ContaoManager\\Symfony\\Component\\Console\\Input\\InputDefinition' => $vendorDir . '/symfony/console/Input/InputDefinition.php',
    '_ContaoManager\\Symfony\\Component\\Console\\Input\\InputInterface' => $vendorDir . '/symfony/console/Input/InputInterface.php',
    '_ContaoManager\\Symfony\\Component\\Console\\Input\\InputOption' => $vendorDir . '/symfony/console/Input/InputOption.php',
    '_ContaoManager\\Symfony\\Component\\Console\\Input\\StreamableInputInterface' => $vendorDir . '/symfony/console/Input/StreamableInputInterface.php',
    '_ContaoManager\\Symfony\\Component\\Console\\Input\\StringInput' => $vendorDir . '/symfony/console/Input/StringInput.php',
    '_ContaoManager\\Symfony\\Component\\Console\\Logger\\ConsoleLogger' => $vendorDir . '/symfony/console/Logger/ConsoleLogger.php',
    '_ContaoManager\\Symfony\\Component\\Console\\Messenger\\RunCommandContext' => $vendorDir . '/symfony/console/Messenger/RunCommandContext.php',
    '_ContaoManager\\Symfony\\Component\\Console\\Messenger\\RunCommandMessage' => $vendorDir . '/symfony/console/Messenger/RunCommandMessage.php',
    '_ContaoManager\\Symfony\\Component\\Console\\Messenger\\RunCommandMessageHandler' => $vendorDir . '/symfony/console/Messenger/RunCommandMessageHandler.php',
    '_ContaoManager\\Symfony\\Component\\Console\\Output\\AnsiColorMode' => $vendorDir . '/symfony/console/Output/AnsiColorMode.php',
    '_ContaoManager\\Symfony\\Component\\Console\\Output\\BufferedOutput' => $vendorDir . '/symfony/console/Output/BufferedOutput.php',
    '_ContaoManager\\Symfony\\Component\\Console\\Output\\ConsoleOutput' => $vendorDir . '/symfony/console/Output/ConsoleOutput.php',
    '_ContaoManager\\Symfony\\Component\\Console\\Output\\ConsoleOutputInterface' => $vendorDir . '/symfony/console/Output/ConsoleOutputInterface.php',
    '_ContaoManager\\Symfony\\Component\\Console\\Output\\ConsoleSectionOutput' => $vendorDir . '/symfony/console/Output/ConsoleSectionOutput.php',
    '_ContaoManager\\Symfony\\Component\\Console\\Output\\NullOutput' => $vendorDir . '/symfony/console/Output/NullOutput.php',
    '_ContaoManager\\Symfony\\Component\\Console\\Output\\Output' => $vendorDir . '/symfony/console/Output/Output.php',
    '_ContaoManager\\Symfony\\Component\\Console\\Output\\OutputInterface' => $vendorDir . '/symfony/console/Output/OutputInterface.php',
    '_ContaoManager\\Symfony\\Component\\Console\\Output\\StreamOutput' => $vendorDir . '/symfony/console/Output/StreamOutput.php',
    '_ContaoManager\\Symfony\\Component\\Console\\Output\\TrimmedBufferOutput' => $vendorDir . '/symfony/console/Output/TrimmedBufferOutput.php',
    '_ContaoManager\\Symfony\\Component\\Console\\Question\\ChoiceQuestion' => $vendorDir . '/symfony/console/Question/ChoiceQuestion.php',
    '_ContaoManager\\Symfony\\Component\\Console\\Question\\ConfirmationQuestion' => $vendorDir . '/symfony/console/Question/ConfirmationQuestion.php',
    '_ContaoManager\\Symfony\\Component\\Console\\Question\\Question' => $vendorDir . '/symfony/console/Question/Question.php',
    '_ContaoManager\\Symfony\\Component\\Console\\SignalRegistry\\SignalMap' => $vendorDir . '/symfony/console/SignalRegistry/SignalMap.php',
    '_ContaoManager\\Symfony\\Component\\Console\\SignalRegistry\\SignalRegistry' => $vendorDir . '/symfony/console/SignalRegistry/SignalRegistry.php',
    '_ContaoManager\\Symfony\\Component\\Console\\SingleCommandApplication' => $vendorDir . '/symfony/console/SingleCommandApplication.php',
    '_ContaoManager\\Symfony\\Component\\Console\\Style\\OutputStyle' => $vendorDir . '/symfony/console/Style/OutputStyle.php',
    '_ContaoManager\\Symfony\\Component\\Console\\Style\\StyleInterface' => $vendorDir . '/symfony/console/Style/StyleInterface.php',
    '_ContaoManager\\Symfony\\Component\\Console\\Style\\SymfonyStyle' => $vendorDir . '/symfony/console/Style/SymfonyStyle.php',
    '_ContaoManager\\Symfony\\Component\\Console\\Terminal' => $vendorDir . '/symfony/console/Terminal.php',
    '_ContaoManager\\Symfony\\Component\\Console\\Tester\\ApplicationTester' => $vendorDir . '/symfony/console/Tester/ApplicationTester.php',
    '_ContaoManager\\Symfony\\Component\\Console\\Tester\\CommandCompletionTester' => $vendorDir . '/symfony/console/Tester/CommandCompletionTester.php',
    '_ContaoManager\\Symfony\\Component\\Console\\Tester\\CommandTester' => $vendorDir . '/symfony/console/Tester/CommandTester.php',
    '_ContaoManager\\Symfony\\Component\\Console\\Tester\\Constraint\\CommandIsSuccessful' => $vendorDir . '/symfony/console/Tester/Constraint/CommandIsSuccessful.php',
    '_ContaoManager\\Symfony\\Component\\Console\\Tester\\TesterTrait' => $vendorDir . '/symfony/console/Tester/TesterTrait.php',
    '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Alias' => $vendorDir . '/symfony/dependency-injection/Alias.php',
    '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Argument\\AbstractArgument' => $vendorDir . '/symfony/dependency-injection/Argument/AbstractArgument.php',
    '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Argument\\ArgumentInterface' => $vendorDir . '/symfony/dependency-injection/Argument/ArgumentInterface.php',
    '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Argument\\BoundArgument' => $vendorDir . '/symfony/dependency-injection/Argument/BoundArgument.php',
    '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Argument\\IteratorArgument' => $vendorDir . '/symfony/dependency-injection/Argument/IteratorArgument.php',
    '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Argument\\LazyClosure' => $vendorDir . '/symfony/dependency-injection/Argument/LazyClosure.php',
    '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Argument\\ReferenceSetArgumentTrait' => $vendorDir . '/symfony/dependency-injection/Argument/ReferenceSetArgumentTrait.php',
    '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Argument\\RewindableGenerator' => $vendorDir . '/symfony/dependency-injection/Argument/RewindableGenerator.php',
    '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Argument\\ServiceClosureArgument' => $vendorDir . '/symfony/dependency-injection/Argument/ServiceClosureArgument.php',
    '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Argument\\ServiceLocator' => $vendorDir . '/symfony/dependency-injection/Argument/ServiceLocator.php',
    '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Argument\\ServiceLocatorArgument' => $vendorDir . '/symfony/dependency-injection/Argument/ServiceLocatorArgument.php',
    '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Argument\\TaggedIteratorArgument' => $vendorDir . '/symfony/dependency-injection/Argument/TaggedIteratorArgument.php',
    '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Attribute\\AsAlias' => $vendorDir . '/symfony/dependency-injection/Attribute/AsAlias.php',
    '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Attribute\\AsDecorator' => $vendorDir . '/symfony/dependency-injection/Attribute/AsDecorator.php',
    '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Attribute\\AsTaggedItem' => $vendorDir . '/symfony/dependency-injection/Attribute/AsTaggedItem.php',
    '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Attribute\\Autoconfigure' => $vendorDir . '/symfony/dependency-injection/Attribute/Autoconfigure.php',
    '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Attribute\\AutoconfigureTag' => $vendorDir . '/symfony/dependency-injection/Attribute/AutoconfigureTag.php',
    '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Attribute\\Autowire' => $vendorDir . '/symfony/dependency-injection/Attribute/Autowire.php',
    '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Attribute\\AutowireCallable' => $vendorDir . '/symfony/dependency-injection/Attribute/AutowireCallable.php',
    '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Attribute\\AutowireDecorated' => $vendorDir . '/symfony/dependency-injection/Attribute/AutowireDecorated.php',
    '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Attribute\\AutowireIterator' => $vendorDir . '/symfony/dependency-injection/Attribute/AutowireIterator.php',
    '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Attribute\\AutowireLocator' => $vendorDir . '/symfony/dependency-injection/Attribute/AutowireLocator.php',
    '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Attribute\\AutowireServiceClosure' => $vendorDir . '/symfony/dependency-injection/Attribute/AutowireServiceClosure.php',
    '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Attribute\\Exclude' => $vendorDir . '/symfony/dependency-injection/Attribute/Exclude.php',
    '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Attribute\\MapDecorated' => $vendorDir . '/symfony/dependency-injection/Attribute/MapDecorated.php',
    '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Attribute\\TaggedIterator' => $vendorDir . '/symfony/dependency-injection/Attribute/TaggedIterator.php',
    '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Attribute\\TaggedLocator' => $vendorDir . '/symfony/dependency-injection/Attribute/TaggedLocator.php',
    '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Attribute\\Target' => $vendorDir . '/symfony/dependency-injection/Attribute/Target.php',
    '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Attribute\\When' => $vendorDir . '/symfony/dependency-injection/Attribute/When.php',
    '_ContaoManager\\Symfony\\Component\\DependencyInjection\\ChildDefinition' => $vendorDir . '/symfony/dependency-injection/ChildDefinition.php',
    '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Compiler\\AbstractRecursivePass' => $vendorDir . '/symfony/dependency-injection/Compiler/AbstractRecursivePass.php',
    '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Compiler\\AliasDeprecatedPublicServicesPass' => $vendorDir . '/symfony/dependency-injection/Compiler/AliasDeprecatedPublicServicesPass.php',
    '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Compiler\\AnalyzeServiceReferencesPass' => $vendorDir . '/symfony/dependency-injection/Compiler/AnalyzeServiceReferencesPass.php',
    '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Compiler\\AttributeAutoconfigurationPass' => $vendorDir . '/symfony/dependency-injection/Compiler/AttributeAutoconfigurationPass.php',
    '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Compiler\\AutoAliasServicePass' => $vendorDir . '/symfony/dependency-injection/Compiler/AutoAliasServicePass.php',
    '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Compiler\\AutowireAsDecoratorPass' => $vendorDir . '/symfony/dependency-injection/Compiler/AutowireAsDecoratorPass.php',
    '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Compiler\\AutowirePass' => $vendorDir . '/symfony/dependency-injection/Compiler/AutowirePass.php',
    '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Compiler\\AutowireRequiredMethodsPass' => $vendorDir . '/symfony/dependency-injection/Compiler/AutowireRequiredMethodsPass.php',
    '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Compiler\\AutowireRequiredPropertiesPass' => $vendorDir . '/symfony/dependency-injection/Compiler/AutowireRequiredPropertiesPass.php',
    '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Compiler\\CheckArgumentsValidityPass' => $vendorDir . '/symfony/dependency-injection/Compiler/CheckArgumentsValidityPass.php',
    '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Compiler\\CheckCircularReferencesPass' => $vendorDir . '/symfony/dependency-injection/Compiler/CheckCircularReferencesPass.php',
    '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Compiler\\CheckDefinitionValidityPass' => $vendorDir . '/symfony/dependency-injection/Compiler/CheckDefinitionValidityPass.php',
    '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Compiler\\CheckExceptionOnInvalidReferenceBehaviorPass' => $vendorDir . '/symfony/dependency-injection/Compiler/CheckExceptionOnInvalidReferenceBehaviorPass.php',
    '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Compiler\\CheckReferenceValidityPass' => $vendorDir . '/symfony/dependency-injection/Compiler/CheckReferenceValidityPass.php',
    '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Compiler\\CheckTypeDeclarationsPass' => $vendorDir . '/symfony/dependency-injection/Compiler/CheckTypeDeclarationsPass.php',
    '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Compiler\\Compiler' => $vendorDir . '/symfony/dependency-injection/Compiler/Compiler.php',
    '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Compiler\\CompilerPassInterface' => $vendorDir . '/symfony/dependency-injection/Compiler/CompilerPassInterface.php',
    '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Compiler\\DecoratorServicePass' => $vendorDir . '/symfony/dependency-injection/Compiler/DecoratorServicePass.php',
    '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Compiler\\DefinitionErrorExceptionPass' => $vendorDir . '/symfony/dependency-injection/Compiler/DefinitionErrorExceptionPass.php',
    '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Compiler\\ExtensionCompilerPass' => $vendorDir . '/symfony/dependency-injection/Compiler/ExtensionCompilerPass.php',
    '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Compiler\\InlineServiceDefinitionsPass' => $vendorDir . '/symfony/dependency-injection/Compiler/InlineServiceDefinitionsPass.php',
    '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Compiler\\MergeExtensionConfigurationPass' => $vendorDir . '/symfony/dependency-injection/Compiler/MergeExtensionConfigurationPass.php',
    '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Compiler\\PassConfig' => $vendorDir . '/symfony/dependency-injection/Compiler/PassConfig.php',
    '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Compiler\\PriorityTaggedServiceTrait' => $vendorDir . '/symfony/dependency-injection/Compiler/PriorityTaggedServiceTrait.php',
    '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Compiler\\RegisterAutoconfigureAttributesPass' => $vendorDir . '/symfony/dependency-injection/Compiler/RegisterAutoconfigureAttributesPass.php',
    '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Compiler\\RegisterEnvVarProcessorsPass' => $vendorDir . '/symfony/dependency-injection/Compiler/RegisterEnvVarProcessorsPass.php',
    '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Compiler\\RegisterReverseContainerPass' => $vendorDir . '/symfony/dependency-injection/Compiler/RegisterReverseContainerPass.php',
    '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Compiler\\RegisterServiceSubscribersPass' => $vendorDir . '/symfony/dependency-injection/Compiler/RegisterServiceSubscribersPass.php',
    '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Compiler\\RemoveAbstractDefinitionsPass' => $vendorDir . '/symfony/dependency-injection/Compiler/RemoveAbstractDefinitionsPass.php',
    '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Compiler\\RemoveBuildParametersPass' => $vendorDir . '/symfony/dependency-injection/Compiler/RemoveBuildParametersPass.php',
    '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Compiler\\RemovePrivateAliasesPass' => $vendorDir . '/symfony/dependency-injection/Compiler/RemovePrivateAliasesPass.php',
    '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Compiler\\RemoveUnusedDefinitionsPass' => $vendorDir . '/symfony/dependency-injection/Compiler/RemoveUnusedDefinitionsPass.php',
    '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Compiler\\ReplaceAliasByActualDefinitionPass' => $vendorDir . '/symfony/dependency-injection/Compiler/ReplaceAliasByActualDefinitionPass.php',
    '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Compiler\\ResolveBindingsPass' => $vendorDir . '/symfony/dependency-injection/Compiler/ResolveBindingsPass.php',
    '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Compiler\\ResolveChildDefinitionsPass' => $vendorDir . '/symfony/dependency-injection/Compiler/ResolveChildDefinitionsPass.php',
    '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Compiler\\ResolveClassPass' => $vendorDir . '/symfony/dependency-injection/Compiler/ResolveClassPass.php',
    '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Compiler\\ResolveDecoratorStackPass' => $vendorDir . '/symfony/dependency-injection/Compiler/ResolveDecoratorStackPass.php',
    '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Compiler\\ResolveEnvPlaceholdersPass' => $vendorDir . '/symfony/dependency-injection/Compiler/ResolveEnvPlaceholdersPass.php',
    '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Compiler\\ResolveFactoryClassPass' => $vendorDir . '/symfony/dependency-injection/Compiler/ResolveFactoryClassPass.php',
    '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Compiler\\ResolveHotPathPass' => $vendorDir . '/symfony/dependency-injection/Compiler/ResolveHotPathPass.php',
    '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Compiler\\ResolveInstanceofConditionalsPass' => $vendorDir . '/symfony/dependency-injection/Compiler/ResolveInstanceofConditionalsPass.php',
    '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Compiler\\ResolveInvalidReferencesPass' => $vendorDir . '/symfony/dependency-injection/Compiler/ResolveInvalidReferencesPass.php',
    '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Compiler\\ResolveNamedArgumentsPass' => $vendorDir . '/symfony/dependency-injection/Compiler/ResolveNamedArgumentsPass.php',
    '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Compiler\\ResolveNoPreloadPass' => $vendorDir . '/symfony/dependency-injection/Compiler/ResolveNoPreloadPass.php',
    '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Compiler\\ResolveParameterPlaceHoldersPass' => $vendorDir . '/symfony/dependency-injection/Compiler/ResolveParameterPlaceHoldersPass.php',
    '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Compiler\\ResolveReferencesToAliasesPass' => $vendorDir . '/symfony/dependency-injection/Compiler/ResolveReferencesToAliasesPass.php',
    '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Compiler\\ResolveServiceSubscribersPass' => $vendorDir . '/symfony/dependency-injection/Compiler/ResolveServiceSubscribersPass.php',
    '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Compiler\\ResolveTaggedIteratorArgumentPass' => $vendorDir . '/symfony/dependency-injection/Compiler/ResolveTaggedIteratorArgumentPass.php',
    '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Compiler\\ServiceLocatorTagPass' => $vendorDir . '/symfony/dependency-injection/Compiler/ServiceLocatorTagPass.php',
    '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Compiler\\ServiceReferenceGraph' => $vendorDir . '/symfony/dependency-injection/Compiler/ServiceReferenceGraph.php',
    '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Compiler\\ServiceReferenceGraphEdge' => $vendorDir . '/symfony/dependency-injection/Compiler/ServiceReferenceGraphEdge.php',
    '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Compiler\\ServiceReferenceGraphNode' => $vendorDir . '/symfony/dependency-injection/Compiler/ServiceReferenceGraphNode.php',
    '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Compiler\\ValidateEnvPlaceholdersPass' => $vendorDir . '/symfony/dependency-injection/Compiler/ValidateEnvPlaceholdersPass.php',
    '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Config\\ContainerParametersResource' => $vendorDir . '/symfony/dependency-injection/Config/ContainerParametersResource.php',
    '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Config\\ContainerParametersResourceChecker' => $vendorDir . '/symfony/dependency-injection/Config/ContainerParametersResourceChecker.php',
    '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Container' => $vendorDir . '/symfony/dependency-injection/Container.php',
    '_ContaoManager\\Symfony\\Component\\DependencyInjection\\ContainerAwareInterface' => $vendorDir . '/symfony/dependency-injection/ContainerAwareInterface.php',
    '_ContaoManager\\Symfony\\Component\\DependencyInjection\\ContainerAwareTrait' => $vendorDir . '/symfony/dependency-injection/ContainerAwareTrait.php',
    '_ContaoManager\\Symfony\\Component\\DependencyInjection\\ContainerBuilder' => $vendorDir . '/symfony/dependency-injection/ContainerBuilder.php',
    '_ContaoManager\\Symfony\\Component\\DependencyInjection\\ContainerInterface' => $vendorDir . '/symfony/dependency-injection/ContainerInterface.php',
    '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Definition' => $vendorDir . '/symfony/dependency-injection/Definition.php',
    '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Dumper\\Dumper' => $vendorDir . '/symfony/dependency-injection/Dumper/Dumper.php',
    '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Dumper\\DumperInterface' => $vendorDir . '/symfony/dependency-injection/Dumper/DumperInterface.php',
    '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Dumper\\GraphvizDumper' => $vendorDir . '/symfony/dependency-injection/Dumper/GraphvizDumper.php',
    '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Dumper\\PhpDumper' => $vendorDir . '/symfony/dependency-injection/Dumper/PhpDumper.php',
    '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Dumper\\Preloader' => $vendorDir . '/symfony/dependency-injection/Dumper/Preloader.php',
    '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Dumper\\XmlDumper' => $vendorDir . '/symfony/dependency-injection/Dumper/XmlDumper.php',
    '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Dumper\\YamlDumper' => $vendorDir . '/symfony/dependency-injection/Dumper/YamlDumper.php',
    '_ContaoManager\\Symfony\\Component\\DependencyInjection\\EnvVarLoaderInterface' => $vendorDir . '/symfony/dependency-injection/EnvVarLoaderInterface.php',
    '_ContaoManager\\Symfony\\Component\\DependencyInjection\\EnvVarProcessor' => $vendorDir . '/symfony/dependency-injection/EnvVarProcessor.php',
    '_ContaoManager\\Symfony\\Component\\DependencyInjection\\EnvVarProcessorInterface' => $vendorDir . '/symfony/dependency-injection/EnvVarProcessorInterface.php',
    '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Exception\\AutowiringFailedException' => $vendorDir . '/symfony/dependency-injection/Exception/AutowiringFailedException.php',
    '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Exception\\BadMethodCallException' => $vendorDir . '/symfony/dependency-injection/Exception/BadMethodCallException.php',
    '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Exception\\EnvNotFoundException' => $vendorDir . '/symfony/dependency-injection/Exception/EnvNotFoundException.php',
    '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Exception\\EnvParameterException' => $vendorDir . '/symfony/dependency-injection/Exception/EnvParameterException.php',
    '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Exception\\ExceptionInterface' => $vendorDir . '/symfony/dependency-injection/Exception/ExceptionInterface.php',
    '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Exception\\InvalidArgumentException' => $vendorDir . '/symfony/dependency-injection/Exception/InvalidArgumentException.php',
    '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Exception\\InvalidParameterTypeException' => $vendorDir . '/symfony/dependency-injection/Exception/InvalidParameterTypeException.php',
    '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Exception\\LogicException' => $vendorDir . '/symfony/dependency-injection/Exception/LogicException.php',
    '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Exception\\OutOfBoundsException' => $vendorDir . '/symfony/dependency-injection/Exception/OutOfBoundsException.php',
    '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Exception\\ParameterCircularReferenceException' => $vendorDir . '/symfony/dependency-injection/Exception/ParameterCircularReferenceException.php',
    '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Exception\\ParameterNotFoundException' => $vendorDir . '/symfony/dependency-injection/Exception/ParameterNotFoundException.php',
    '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Exception\\RuntimeException' => $vendorDir . '/symfony/dependency-injection/Exception/RuntimeException.php',
    '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Exception\\ServiceCircularReferenceException' => $vendorDir . '/symfony/dependency-injection/Exception/ServiceCircularReferenceException.php',
    '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Exception\\ServiceNotFoundException' => $vendorDir . '/symfony/dependency-injection/Exception/ServiceNotFoundException.php',
    '_ContaoManager\\Symfony\\Component\\DependencyInjection\\ExpressionLanguage' => $vendorDir . '/symfony/dependency-injection/ExpressionLanguage.php',
    '_ContaoManager\\Symfony\\Component\\DependencyInjection\\ExpressionLanguageProvider' => $vendorDir . '/symfony/dependency-injection/ExpressionLanguageProvider.php',
    '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Extension\\AbstractExtension' => $vendorDir . '/symfony/dependency-injection/Extension/AbstractExtension.php',
    '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Extension\\ConfigurableExtensionInterface' => $vendorDir . '/symfony/dependency-injection/Extension/ConfigurableExtensionInterface.php',
    '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Extension\\ConfigurationExtensionInterface' => $vendorDir . '/symfony/dependency-injection/Extension/ConfigurationExtensionInterface.php',
    '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Extension\\Extension' => $vendorDir . '/symfony/dependency-injection/Extension/Extension.php',
    '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Extension\\ExtensionInterface' => $vendorDir . '/symfony/dependency-injection/Extension/ExtensionInterface.php',
    '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Extension\\ExtensionTrait' => $vendorDir . '/symfony/dependency-injection/Extension/ExtensionTrait.php',
    '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Extension\\PrependExtensionInterface' => $vendorDir . '/symfony/dependency-injection/Extension/PrependExtensionInterface.php',
    '_ContaoManager\\Symfony\\Component\\DependencyInjection\\LazyProxy\\Instantiator\\InstantiatorInterface' => $vendorDir . '/symfony/dependency-injection/LazyProxy/Instantiator/InstantiatorInterface.php',
    '_ContaoManager\\Symfony\\Component\\DependencyInjection\\LazyProxy\\Instantiator\\LazyServiceInstantiator' => $vendorDir . '/symfony/dependency-injection/LazyProxy/Instantiator/LazyServiceInstantiator.php',
    '_ContaoManager\\Symfony\\Component\\DependencyInjection\\LazyProxy\\Instantiator\\RealServiceInstantiator' => $vendorDir . '/symfony/dependency-injection/LazyProxy/Instantiator/RealServiceInstantiator.php',
    '_ContaoManager\\Symfony\\Component\\DependencyInjection\\LazyProxy\\PhpDumper\\DumperInterface' => $vendorDir . '/symfony/dependency-injection/LazyProxy/PhpDumper/DumperInterface.php',
    '_ContaoManager\\Symfony\\Component\\DependencyInjection\\LazyProxy\\PhpDumper\\LazyServiceDumper' => $vendorDir . '/symfony/dependency-injection/LazyProxy/PhpDumper/LazyServiceDumper.php',
    '_ContaoManager\\Symfony\\Component\\DependencyInjection\\LazyProxy\\PhpDumper\\NullDumper' => $vendorDir . '/symfony/dependency-injection/LazyProxy/PhpDumper/NullDumper.php',
    '_ContaoManager\\Symfony\\Component\\DependencyInjection\\LazyProxy\\ProxyHelper' => $vendorDir . '/symfony/dependency-injection/LazyProxy/ProxyHelper.php',
    '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Loader\\ClosureLoader' => $vendorDir . '/symfony/dependency-injection/Loader/ClosureLoader.php',
    '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Loader\\Configurator\\AbstractConfigurator' => $vendorDir . '/symfony/dependency-injection/Loader/Configurator/AbstractConfigurator.php',
    '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Loader\\Configurator\\AbstractServiceConfigurator' => $vendorDir . '/symfony/dependency-injection/Loader/Configurator/AbstractServiceConfigurator.php',
    '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Loader\\Configurator\\AliasConfigurator' => $vendorDir . '/symfony/dependency-injection/Loader/Configurator/AliasConfigurator.php',
    '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Loader\\Configurator\\ClosureReferenceConfigurator' => $vendorDir . '/symfony/dependency-injection/Loader/Configurator/ClosureReferenceConfigurator.php',
    '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Loader\\Configurator\\ContainerConfigurator' => $vendorDir . '/symfony/dependency-injection/Loader/Configurator/ContainerConfigurator.php',
    '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Loader\\Configurator\\DefaultsConfigurator' => $vendorDir . '/symfony/dependency-injection/Loader/Configurator/DefaultsConfigurator.php',
    '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Loader\\Configurator\\EnvConfigurator' => $vendorDir . '/symfony/dependency-injection/Loader/Configurator/EnvConfigurator.php',
    '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Loader\\Configurator\\FromCallableConfigurator' => $vendorDir . '/symfony/dependency-injection/Loader/Configurator/FromCallableConfigurator.php',
    '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Loader\\Configurator\\InlineServiceConfigurator' => $vendorDir . '/symfony/dependency-injection/Loader/Configurator/InlineServiceConfigurator.php',
    '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Loader\\Configurator\\InstanceofConfigurator' => $vendorDir . '/symfony/dependency-injection/Loader/Configurator/InstanceofConfigurator.php',
    '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Loader\\Configurator\\ParametersConfigurator' => $vendorDir . '/symfony/dependency-injection/Loader/Configurator/ParametersConfigurator.php',
    '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Loader\\Configurator\\PrototypeConfigurator' => $vendorDir . '/symfony/dependency-injection/Loader/Configurator/PrototypeConfigurator.php',
    '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Loader\\Configurator\\ReferenceConfigurator' => $vendorDir . '/symfony/dependency-injection/Loader/Configurator/ReferenceConfigurator.php',
    '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Loader\\Configurator\\ServiceConfigurator' => $vendorDir . '/symfony/dependency-injection/Loader/Configurator/ServiceConfigurator.php',
    '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Loader\\Configurator\\ServicesConfigurator' => $vendorDir . '/symfony/dependency-injection/Loader/Configurator/ServicesConfigurator.php',
    '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Loader\\Configurator\\Traits\\AbstractTrait' => $vendorDir . '/symfony/dependency-injection/Loader/Configurator/Traits/AbstractTrait.php',
    '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Loader\\Configurator\\Traits\\ArgumentTrait' => $vendorDir . '/symfony/dependency-injection/Loader/Configurator/Traits/ArgumentTrait.php',
    '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Loader\\Configurator\\Traits\\AutoconfigureTrait' => $vendorDir . '/symfony/dependency-injection/Loader/Configurator/Traits/AutoconfigureTrait.php',
    '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Loader\\Configurator\\Traits\\AutowireTrait' => $vendorDir . '/symfony/dependency-injection/Loader/Configurator/Traits/AutowireTrait.php',
    '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Loader\\Configurator\\Traits\\BindTrait' => $vendorDir . '/symfony/dependency-injection/Loader/Configurator/Traits/BindTrait.php',
    '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Loader\\Configurator\\Traits\\CallTrait' => $vendorDir . '/symfony/dependency-injection/Loader/Configurator/Traits/CallTrait.php',
    '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Loader\\Configurator\\Traits\\ClassTrait' => $vendorDir . '/symfony/dependency-injection/Loader/Configurator/Traits/ClassTrait.php',
    '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Loader\\Configurator\\Traits\\ConfiguratorTrait' => $vendorDir . '/symfony/dependency-injection/Loader/Configurator/Traits/ConfiguratorTrait.php',
    '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Loader\\Configurator\\Traits\\ConstructorTrait' => $vendorDir . '/symfony/dependency-injection/Loader/Configurator/Traits/ConstructorTrait.php',
    '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Loader\\Configurator\\Traits\\DecorateTrait' => $vendorDir . '/symfony/dependency-injection/Loader/Configurator/Traits/DecorateTrait.php',
    '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Loader\\Configurator\\Traits\\DeprecateTrait' => $vendorDir . '/symfony/dependency-injection/Loader/Configurator/Traits/DeprecateTrait.php',
    '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Loader\\Configurator\\Traits\\FactoryTrait' => $vendorDir . '/symfony/dependency-injection/Loader/Configurator/Traits/FactoryTrait.php',
    '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Loader\\Configurator\\Traits\\FileTrait' => $vendorDir . '/symfony/dependency-injection/Loader/Configurator/Traits/FileTrait.php',
    '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Loader\\Configurator\\Traits\\FromCallableTrait' => $vendorDir . '/symfony/dependency-injection/Loader/Configurator/Traits/FromCallableTrait.php',
    '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Loader\\Configurator\\Traits\\LazyTrait' => $vendorDir . '/symfony/dependency-injection/Loader/Configurator/Traits/LazyTrait.php',
    '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Loader\\Configurator\\Traits\\ParentTrait' => $vendorDir . '/symfony/dependency-injection/Loader/Configurator/Traits/ParentTrait.php',
    '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Loader\\Configurator\\Traits\\PropertyTrait' => $vendorDir . '/symfony/dependency-injection/Loader/Configurator/Traits/PropertyTrait.php',
    '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Loader\\Configurator\\Traits\\PublicTrait' => $vendorDir . '/symfony/dependency-injection/Loader/Configurator/Traits/PublicTrait.php',
    '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Loader\\Configurator\\Traits\\ShareTrait' => $vendorDir . '/symfony/dependency-injection/Loader/Configurator/Traits/ShareTrait.php',
    '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Loader\\Configurator\\Traits\\SyntheticTrait' => $vendorDir . '/symfony/dependency-injection/Loader/Configurator/Traits/SyntheticTrait.php',
    '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Loader\\Configurator\\Traits\\TagTrait' => $vendorDir . '/symfony/dependency-injection/Loader/Configurator/Traits/TagTrait.php',
    '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Loader\\DirectoryLoader' => $vendorDir . '/symfony/dependency-injection/Loader/DirectoryLoader.php',
    '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Loader\\FileLoader' => $vendorDir . '/symfony/dependency-injection/Loader/FileLoader.php',
    '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Loader\\GlobFileLoader' => $vendorDir . '/symfony/dependency-injection/Loader/GlobFileLoader.php',
    '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Loader\\IniFileLoader' => $vendorDir . '/symfony/dependency-injection/Loader/IniFileLoader.php',
    '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Loader\\PhpFileLoader' => $vendorDir . '/symfony/dependency-injection/Loader/PhpFileLoader.php',
    '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Loader\\XmlFileLoader' => $vendorDir . '/symfony/dependency-injection/Loader/XmlFileLoader.php',
    '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Loader\\YamlFileLoader' => $vendorDir . '/symfony/dependency-injection/Loader/YamlFileLoader.php',
    '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Parameter' => $vendorDir . '/symfony/dependency-injection/Parameter.php',
    '_ContaoManager\\Symfony\\Component\\DependencyInjection\\ParameterBag\\ContainerBag' => $vendorDir . '/symfony/dependency-injection/ParameterBag/ContainerBag.php',
    '_ContaoManager\\Symfony\\Component\\DependencyInjection\\ParameterBag\\ContainerBagInterface' => $vendorDir . '/symfony/dependency-injection/ParameterBag/ContainerBagInterface.php',
    '_ContaoManager\\Symfony\\Component\\DependencyInjection\\ParameterBag\\EnvPlaceholderParameterBag' => $vendorDir . '/symfony/dependency-injection/ParameterBag/EnvPlaceholderParameterBag.php',
    '_ContaoManager\\Symfony\\Component\\DependencyInjection\\ParameterBag\\FrozenParameterBag' => $vendorDir . '/symfony/dependency-injection/ParameterBag/FrozenParameterBag.php',
    '_ContaoManager\\Symfony\\Component\\DependencyInjection\\ParameterBag\\ParameterBag' => $vendorDir . '/symfony/dependency-injection/ParameterBag/ParameterBag.php',
    '_ContaoManager\\Symfony\\Component\\DependencyInjection\\ParameterBag\\ParameterBagInterface' => $vendorDir . '/symfony/dependency-injection/ParameterBag/ParameterBagInterface.php',
    '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Reference' => $vendorDir . '/symfony/dependency-injection/Reference.php',
    '_ContaoManager\\Symfony\\Component\\DependencyInjection\\ReverseContainer' => $vendorDir . '/symfony/dependency-injection/ReverseContainer.php',
    '_ContaoManager\\Symfony\\Component\\DependencyInjection\\ServiceLocator' => $vendorDir . '/symfony/dependency-injection/ServiceLocator.php',
    '_ContaoManager\\Symfony\\Component\\DependencyInjection\\TaggedContainerInterface' => $vendorDir . '/symfony/dependency-injection/TaggedContainerInterface.php',
    '_ContaoManager\\Symfony\\Component\\DependencyInjection\\TypedReference' => $vendorDir . '/symfony/dependency-injection/TypedReference.php',
    '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Variable' => $vendorDir . '/symfony/dependency-injection/Variable.php',
    '_ContaoManager\\Symfony\\Component\\ErrorHandler\\BufferingLogger' => $vendorDir . '/symfony/error-handler/BufferingLogger.php',
    '_ContaoManager\\Symfony\\Component\\ErrorHandler\\Debug' => $vendorDir . '/symfony/error-handler/Debug.php',
    '_ContaoManager\\Symfony\\Component\\ErrorHandler\\DebugClassLoader' => $vendorDir . '/symfony/error-handler/DebugClassLoader.php',
    '_ContaoManager\\Symfony\\Component\\ErrorHandler\\ErrorEnhancer\\ClassNotFoundErrorEnhancer' => $vendorDir . '/symfony/error-handler/ErrorEnhancer/ClassNotFoundErrorEnhancer.php',
    '_ContaoManager\\Symfony\\Component\\ErrorHandler\\ErrorEnhancer\\ErrorEnhancerInterface' => $vendorDir . '/symfony/error-handler/ErrorEnhancer/ErrorEnhancerInterface.php',
    '_ContaoManager\\Symfony\\Component\\ErrorHandler\\ErrorEnhancer\\UndefinedFunctionErrorEnhancer' => $vendorDir . '/symfony/error-handler/ErrorEnhancer/UndefinedFunctionErrorEnhancer.php',
    '_ContaoManager\\Symfony\\Component\\ErrorHandler\\ErrorEnhancer\\UndefinedMethodErrorEnhancer' => $vendorDir . '/symfony/error-handler/ErrorEnhancer/UndefinedMethodErrorEnhancer.php',
    '_ContaoManager\\Symfony\\Component\\ErrorHandler\\ErrorHandler' => $vendorDir . '/symfony/error-handler/ErrorHandler.php',
    '_ContaoManager\\Symfony\\Component\\ErrorHandler\\ErrorRenderer\\CliErrorRenderer' => $vendorDir . '/symfony/error-handler/ErrorRenderer/CliErrorRenderer.php',
    '_ContaoManager\\Symfony\\Component\\ErrorHandler\\ErrorRenderer\\ErrorRendererInterface' => $vendorDir . '/symfony/error-handler/ErrorRenderer/ErrorRendererInterface.php',
    '_ContaoManager\\Symfony\\Component\\ErrorHandler\\ErrorRenderer\\FileLinkFormatter' => $vendorDir . '/symfony/error-handler/ErrorRenderer/FileLinkFormatter.php',
    '_ContaoManager\\Symfony\\Component\\ErrorHandler\\ErrorRenderer\\HtmlErrorRenderer' => $vendorDir . '/symfony/error-handler/ErrorRenderer/HtmlErrorRenderer.php',
    '_ContaoManager\\Symfony\\Component\\ErrorHandler\\ErrorRenderer\\SerializerErrorRenderer' => $vendorDir . '/symfony/error-handler/ErrorRenderer/SerializerErrorRenderer.php',
    '_ContaoManager\\Symfony\\Component\\ErrorHandler\\Error\\ClassNotFoundError' => $vendorDir . '/symfony/error-handler/Error/ClassNotFoundError.php',
    '_ContaoManager\\Symfony\\Component\\ErrorHandler\\Error\\FatalError' => $vendorDir . '/symfony/error-handler/Error/FatalError.php',
    '_ContaoManager\\Symfony\\Component\\ErrorHandler\\Error\\OutOfMemoryError' => $vendorDir . '/symfony/error-handler/Error/OutOfMemoryError.php',
    '_ContaoManager\\Symfony\\Component\\ErrorHandler\\Error\\UndefinedFunctionError' => $vendorDir . '/symfony/error-handler/Error/UndefinedFunctionError.php',
    '_ContaoManager\\Symfony\\Component\\ErrorHandler\\Error\\UndefinedMethodError' => $vendorDir . '/symfony/error-handler/Error/UndefinedMethodError.php',
    '_ContaoManager\\Symfony\\Component\\ErrorHandler\\Exception\\FlattenException' => $vendorDir . '/symfony/error-handler/Exception/FlattenException.php',
    '_ContaoManager\\Symfony\\Component\\ErrorHandler\\Exception\\SilencedErrorContext' => $vendorDir . '/symfony/error-handler/Exception/SilencedErrorContext.php',
    '_ContaoManager\\Symfony\\Component\\ErrorHandler\\Internal\\TentativeTypes' => $vendorDir . '/symfony/error-handler/Internal/TentativeTypes.php',
    '_ContaoManager\\Symfony\\Component\\ErrorHandler\\ThrowableUtils' => $vendorDir . '/symfony/error-handler/ThrowableUtils.php',
    '_ContaoManager\\Symfony\\Component\\EventDispatcher\\Attribute\\AsEventListener' => $vendorDir . '/symfony/event-dispatcher/Attribute/AsEventListener.php',
    '_ContaoManager\\Symfony\\Component\\EventDispatcher\\Debug\\TraceableEventDispatcher' => $vendorDir . '/symfony/event-dispatcher/Debug/TraceableEventDispatcher.php',
    '_ContaoManager\\Symfony\\Component\\EventDispatcher\\Debug\\WrappedListener' => $vendorDir . '/symfony/event-dispatcher/Debug/WrappedListener.php',
    '_ContaoManager\\Symfony\\Component\\EventDispatcher\\DependencyInjection\\AddEventAliasesPass' => $vendorDir . '/symfony/event-dispatcher/DependencyInjection/AddEventAliasesPass.php',
    '_ContaoManager\\Symfony\\Component\\EventDispatcher\\DependencyInjection\\RegisterListenersPass' => $vendorDir . '/symfony/event-dispatcher/DependencyInjection/RegisterListenersPass.php',
    '_ContaoManager\\Symfony\\Component\\EventDispatcher\\EventDispatcher' => $vendorDir . '/symfony/event-dispatcher/EventDispatcher.php',
    '_ContaoManager\\Symfony\\Component\\EventDispatcher\\EventDispatcherInterface' => $vendorDir . '/symfony/event-dispatcher/EventDispatcherInterface.php',
    '_ContaoManager\\Symfony\\Component\\EventDispatcher\\EventSubscriberInterface' => $vendorDir . '/symfony/event-dispatcher/EventSubscriberInterface.php',
    '_ContaoManager\\Symfony\\Component\\EventDispatcher\\GenericEvent' => $vendorDir . '/symfony/event-dispatcher/GenericEvent.php',
    '_ContaoManager\\Symfony\\Component\\EventDispatcher\\ImmutableEventDispatcher' => $vendorDir . '/symfony/event-dispatcher/ImmutableEventDispatcher.php',
    '_ContaoManager\\Symfony\\Component\\Filesystem\\Exception\\ExceptionInterface' => $vendorDir . '/symfony/filesystem/Exception/ExceptionInterface.php',
    '_ContaoManager\\Symfony\\Component\\Filesystem\\Exception\\FileNotFoundException' => $vendorDir . '/symfony/filesystem/Exception/FileNotFoundException.php',
    '_ContaoManager\\Symfony\\Component\\Filesystem\\Exception\\IOException' => $vendorDir . '/symfony/filesystem/Exception/IOException.php',
    '_ContaoManager\\Symfony\\Component\\Filesystem\\Exception\\IOExceptionInterface' => $vendorDir . '/symfony/filesystem/Exception/IOExceptionInterface.php',
    '_ContaoManager\\Symfony\\Component\\Filesystem\\Exception\\InvalidArgumentException' => $vendorDir . '/symfony/filesystem/Exception/InvalidArgumentException.php',
    '_ContaoManager\\Symfony\\Component\\Filesystem\\Exception\\RuntimeException' => $vendorDir . '/symfony/filesystem/Exception/RuntimeException.php',
    '_ContaoManager\\Symfony\\Component\\Filesystem\\Filesystem' => $vendorDir . '/symfony/filesystem/Filesystem.php',
    '_ContaoManager\\Symfony\\Component\\Filesystem\\Path' => $vendorDir . '/symfony/filesystem/Path.php',
    '_ContaoManager\\Symfony\\Component\\Finder\\Comparator\\Comparator' => $vendorDir . '/symfony/finder/Comparator/Comparator.php',
    '_ContaoManager\\Symfony\\Component\\Finder\\Comparator\\DateComparator' => $vendorDir . '/symfony/finder/Comparator/DateComparator.php',
    '_ContaoManager\\Symfony\\Component\\Finder\\Comparator\\NumberComparator' => $vendorDir . '/symfony/finder/Comparator/NumberComparator.php',
    '_ContaoManager\\Symfony\\Component\\Finder\\Exception\\AccessDeniedException' => $vendorDir . '/symfony/finder/Exception/AccessDeniedException.php',
    '_ContaoManager\\Symfony\\Component\\Finder\\Exception\\DirectoryNotFoundException' => $vendorDir . '/symfony/finder/Exception/DirectoryNotFoundException.php',
    '_ContaoManager\\Symfony\\Component\\Finder\\Finder' => $vendorDir . '/symfony/finder/Finder.php',
    '_ContaoManager\\Symfony\\Component\\Finder\\Gitignore' => $vendorDir . '/symfony/finder/Gitignore.php',
    '_ContaoManager\\Symfony\\Component\\Finder\\Glob' => $vendorDir . '/symfony/finder/Glob.php',
    '_ContaoManager\\Symfony\\Component\\Finder\\Iterator\\CustomFilterIterator' => $vendorDir . '/symfony/finder/Iterator/CustomFilterIterator.php',
    '_ContaoManager\\Symfony\\Component\\Finder\\Iterator\\DateRangeFilterIterator' => $vendorDir . '/symfony/finder/Iterator/DateRangeFilterIterator.php',
    '_ContaoManager\\Symfony\\Component\\Finder\\Iterator\\DepthRangeFilterIterator' => $vendorDir . '/symfony/finder/Iterator/DepthRangeFilterIterator.php',
    '_ContaoManager\\Symfony\\Component\\Finder\\Iterator\\ExcludeDirectoryFilterIterator' => $vendorDir . '/symfony/finder/Iterator/ExcludeDirectoryFilterIterator.php',
    '_ContaoManager\\Symfony\\Component\\Finder\\Iterator\\FileTypeFilterIterator' => $vendorDir . '/symfony/finder/Iterator/FileTypeFilterIterator.php',
    '_ContaoManager\\Symfony\\Component\\Finder\\Iterator\\FilecontentFilterIterator' => $vendorDir . '/symfony/finder/Iterator/FilecontentFilterIterator.php',
    '_ContaoManager\\Symfony\\Component\\Finder\\Iterator\\FilenameFilterIterator' => $vendorDir . '/symfony/finder/Iterator/FilenameFilterIterator.php',
    '_ContaoManager\\Symfony\\Component\\Finder\\Iterator\\LazyIterator' => $vendorDir . '/symfony/finder/Iterator/LazyIterator.php',
    '_ContaoManager\\Symfony\\Component\\Finder\\Iterator\\MultiplePcreFilterIterator' => $vendorDir . '/symfony/finder/Iterator/MultiplePcreFilterIterator.php',
    '_ContaoManager\\Symfony\\Component\\Finder\\Iterator\\PathFilterIterator' => $vendorDir . '/symfony/finder/Iterator/PathFilterIterator.php',
    '_ContaoManager\\Symfony\\Component\\Finder\\Iterator\\RecursiveDirectoryIterator' => $vendorDir . '/symfony/finder/Iterator/RecursiveDirectoryIterator.php',
    '_ContaoManager\\Symfony\\Component\\Finder\\Iterator\\SizeRangeFilterIterator' => $vendorDir . '/symfony/finder/Iterator/SizeRangeFilterIterator.php',
    '_ContaoManager\\Symfony\\Component\\Finder\\Iterator\\SortableIterator' => $vendorDir . '/symfony/finder/Iterator/SortableIterator.php',
    '_ContaoManager\\Symfony\\Component\\Finder\\Iterator\\VcsIgnoredFilterIterator' => $vendorDir . '/symfony/finder/Iterator/VcsIgnoredFilterIterator.php',
    '_ContaoManager\\Symfony\\Component\\Finder\\SplFileInfo' => $vendorDir . '/symfony/finder/SplFileInfo.php',
    '_ContaoManager\\Symfony\\Component\\HttpFoundation\\AcceptHeader' => $vendorDir . '/symfony/http-foundation/AcceptHeader.php',
    '_ContaoManager\\Symfony\\Component\\HttpFoundation\\AcceptHeaderItem' => $vendorDir . '/symfony/http-foundation/AcceptHeaderItem.php',
    '_ContaoManager\\Symfony\\Component\\HttpFoundation\\BinaryFileResponse' => $vendorDir . '/symfony/http-foundation/BinaryFileResponse.php',
    '_ContaoManager\\Symfony\\Component\\HttpFoundation\\ChainRequestMatcher' => $vendorDir . '/symfony/http-foundation/ChainRequestMatcher.php',
    '_ContaoManager\\Symfony\\Component\\HttpFoundation\\Cookie' => $vendorDir . '/symfony/http-foundation/Cookie.php',
    '_ContaoManager\\Symfony\\Component\\HttpFoundation\\Exception\\BadRequestException' => $vendorDir . '/symfony/http-foundation/Exception/BadRequestException.php',
    '_ContaoManager\\Symfony\\Component\\HttpFoundation\\Exception\\ConflictingHeadersException' => $vendorDir . '/symfony/http-foundation/Exception/ConflictingHeadersException.php',
    '_ContaoManager\\Symfony\\Component\\HttpFoundation\\Exception\\JsonException' => $vendorDir . '/symfony/http-foundation/Exception/JsonException.php',
    '_ContaoManager\\Symfony\\Component\\HttpFoundation\\Exception\\RequestExceptionInterface' => $vendorDir . '/symfony/http-foundation/Exception/RequestExceptionInterface.php',
    '_ContaoManager\\Symfony\\Component\\HttpFoundation\\Exception\\SessionNotFoundException' => $vendorDir . '/symfony/http-foundation/Exception/SessionNotFoundException.php',
    '_ContaoManager\\Symfony\\Component\\HttpFoundation\\Exception\\SuspiciousOperationException' => $vendorDir . '/symfony/http-foundation/Exception/SuspiciousOperationException.php',
    '_ContaoManager\\Symfony\\Component\\HttpFoundation\\Exception\\UnexpectedValueException' => $vendorDir . '/symfony/http-foundation/Exception/UnexpectedValueException.php',
    '_ContaoManager\\Symfony\\Component\\HttpFoundation\\ExpressionRequestMatcher' => $vendorDir . '/symfony/http-foundation/ExpressionRequestMatcher.php',
    '_ContaoManager\\Symfony\\Component\\HttpFoundation\\FileBag' => $vendorDir . '/symfony/http-foundation/FileBag.php',
    '_ContaoManager\\Symfony\\Component\\HttpFoundation\\File\\Exception\\AccessDeniedException' => $vendorDir . '/symfony/http-foundation/File/Exception/AccessDeniedException.php',
    '_ContaoManager\\Symfony\\Component\\HttpFoundation\\File\\Exception\\CannotWriteFileException' => $vendorDir . '/symfony/http-foundation/File/Exception/CannotWriteFileException.php',
    '_ContaoManager\\Symfony\\Component\\HttpFoundation\\File\\Exception\\ExtensionFileException' => $vendorDir . '/symfony/http-foundation/File/Exception/ExtensionFileException.php',
    '_ContaoManager\\Symfony\\Component\\HttpFoundation\\File\\Exception\\FileException' => $vendorDir . '/symfony/http-foundation/File/Exception/FileException.php',
    '_ContaoManager\\Symfony\\Component\\HttpFoundation\\File\\Exception\\FileNotFoundException' => $vendorDir . '/symfony/http-foundation/File/Exception/FileNotFoundException.php',
    '_ContaoManager\\Symfony\\Component\\HttpFoundation\\File\\Exception\\FormSizeFileException' => $vendorDir . '/symfony/http-foundation/File/Exception/FormSizeFileException.php',
    '_ContaoManager\\Symfony\\Component\\HttpFoundation\\File\\Exception\\IniSizeFileException' => $vendorDir . '/symfony/http-foundation/File/Exception/IniSizeFileException.php',
    '_ContaoManager\\Symfony\\Component\\HttpFoundation\\File\\Exception\\NoFileException' => $vendorDir . '/symfony/http-foundation/File/Exception/NoFileException.php',
    '_ContaoManager\\Symfony\\Component\\HttpFoundation\\File\\Exception\\NoTmpDirFileException' => $vendorDir . '/symfony/http-foundation/File/Exception/NoTmpDirFileException.php',
    '_ContaoManager\\Symfony\\Component\\HttpFoundation\\File\\Exception\\PartialFileException' => $vendorDir . '/symfony/http-foundation/File/Exception/PartialFileException.php',
    '_ContaoManager\\Symfony\\Component\\HttpFoundation\\File\\Exception\\UnexpectedTypeException' => $vendorDir . '/symfony/http-foundation/File/Exception/UnexpectedTypeException.php',
    '_ContaoManager\\Symfony\\Component\\HttpFoundation\\File\\Exception\\UploadException' => $vendorDir . '/symfony/http-foundation/File/Exception/UploadException.php',
    '_ContaoManager\\Symfony\\Component\\HttpFoundation\\File\\File' => $vendorDir . '/symfony/http-foundation/File/File.php',
    '_ContaoManager\\Symfony\\Component\\HttpFoundation\\File\\Stream' => $vendorDir . '/symfony/http-foundation/File/Stream.php',
    '_ContaoManager\\Symfony\\Component\\HttpFoundation\\File\\UploadedFile' => $vendorDir . '/symfony/http-foundation/File/UploadedFile.php',
    '_ContaoManager\\Symfony\\Component\\HttpFoundation\\HeaderBag' => $vendorDir . '/symfony/http-foundation/HeaderBag.php',
    '_ContaoManager\\Symfony\\Component\\HttpFoundation\\HeaderUtils' => $vendorDir . '/symfony/http-foundation/HeaderUtils.php',
    '_ContaoManager\\Symfony\\Component\\HttpFoundation\\InputBag' => $vendorDir . '/symfony/http-foundation/InputBag.php',
    '_ContaoManager\\Symfony\\Component\\HttpFoundation\\IpUtils' => $vendorDir . '/symfony/http-foundation/IpUtils.php',
    '_ContaoManager\\Symfony\\Component\\HttpFoundation\\JsonResponse' => $vendorDir . '/symfony/http-foundation/JsonResponse.php',
    '_ContaoManager\\Symfony\\Component\\HttpFoundation\\ParameterBag' => $vendorDir . '/symfony/http-foundation/ParameterBag.php',
    '_ContaoManager\\Symfony\\Component\\HttpFoundation\\RateLimiter\\AbstractRequestRateLimiter' => $vendorDir . '/symfony/http-foundation/RateLimiter/AbstractRequestRateLimiter.php',
    '_ContaoManager\\Symfony\\Component\\HttpFoundation\\RateLimiter\\PeekableRequestRateLimiterInterface' => $vendorDir . '/symfony/http-foundation/RateLimiter/PeekableRequestRateLimiterInterface.php',
    '_ContaoManager\\Symfony\\Component\\HttpFoundation\\RateLimiter\\RequestRateLimiterInterface' => $vendorDir . '/symfony/http-foundation/RateLimiter/RequestRateLimiterInterface.php',
    '_ContaoManager\\Symfony\\Component\\HttpFoundation\\RedirectResponse' => $vendorDir . '/symfony/http-foundation/RedirectResponse.php',
    '_ContaoManager\\Symfony\\Component\\HttpFoundation\\Request' => $vendorDir . '/symfony/http-foundation/Request.php',
    '_ContaoManager\\Symfony\\Component\\HttpFoundation\\RequestMatcher' => $vendorDir . '/symfony/http-foundation/RequestMatcher.php',
    '_ContaoManager\\Symfony\\Component\\HttpFoundation\\RequestMatcherInterface' => $vendorDir . '/symfony/http-foundation/RequestMatcherInterface.php',
    '_ContaoManager\\Symfony\\Component\\HttpFoundation\\RequestMatcher\\AttributesRequestMatcher' => $vendorDir . '/symfony/http-foundation/RequestMatcher/AttributesRequestMatcher.php',
    '_ContaoManager\\Symfony\\Component\\HttpFoundation\\RequestMatcher\\ExpressionRequestMatcher' => $vendorDir . '/symfony/http-foundation/RequestMatcher/ExpressionRequestMatcher.php',
    '_ContaoManager\\Symfony\\Component\\HttpFoundation\\RequestMatcher\\HostRequestMatcher' => $vendorDir . '/symfony/http-foundation/RequestMatcher/HostRequestMatcher.php',
    '_ContaoManager\\Symfony\\Component\\HttpFoundation\\RequestMatcher\\IpsRequestMatcher' => $vendorDir . '/symfony/http-foundation/RequestMatcher/IpsRequestMatcher.php',
    '_ContaoManager\\Symfony\\Component\\HttpFoundation\\RequestMatcher\\IsJsonRequestMatcher' => $vendorDir . '/symfony/http-foundation/RequestMatcher/IsJsonRequestMatcher.php',
    '_ContaoManager\\Symfony\\Component\\HttpFoundation\\RequestMatcher\\MethodRequestMatcher' => $vendorDir . '/symfony/http-foundation/RequestMatcher/MethodRequestMatcher.php',
    '_ContaoManager\\Symfony\\Component\\HttpFoundation\\RequestMatcher\\PathRequestMatcher' => $vendorDir . '/symfony/http-foundation/RequestMatcher/PathRequestMatcher.php',
    '_ContaoManager\\Symfony\\Component\\HttpFoundation\\RequestMatcher\\PortRequestMatcher' => $vendorDir . '/symfony/http-foundation/RequestMatcher/PortRequestMatcher.php',
    '_ContaoManager\\Symfony\\Component\\HttpFoundation\\RequestMatcher\\SchemeRequestMatcher' => $vendorDir . '/symfony/http-foundation/RequestMatcher/SchemeRequestMatcher.php',
    '_ContaoManager\\Symfony\\Component\\HttpFoundation\\RequestStack' => $vendorDir . '/symfony/http-foundation/RequestStack.php',
    '_ContaoManager\\Symfony\\Component\\HttpFoundation\\Response' => $vendorDir . '/symfony/http-foundation/Response.php',
    '_ContaoManager\\Symfony\\Component\\HttpFoundation\\ResponseHeaderBag' => $vendorDir . '/symfony/http-foundation/ResponseHeaderBag.php',
    '_ContaoManager\\Symfony\\Component\\HttpFoundation\\ServerBag' => $vendorDir . '/symfony/http-foundation/ServerBag.php',
    '_ContaoManager\\Symfony\\Component\\HttpFoundation\\Session\\Attribute\\AttributeBag' => $vendorDir . '/symfony/http-foundation/Session/Attribute/AttributeBag.php',
    '_ContaoManager\\Symfony\\Component\\HttpFoundation\\Session\\Attribute\\AttributeBagInterface' => $vendorDir . '/symfony/http-foundation/Session/Attribute/AttributeBagInterface.php',
    '_ContaoManager\\Symfony\\Component\\HttpFoundation\\Session\\FlashBagAwareSessionInterface' => $vendorDir . '/symfony/http-foundation/Session/FlashBagAwareSessionInterface.php',
    '_ContaoManager\\Symfony\\Component\\HttpFoundation\\Session\\Flash\\AutoExpireFlashBag' => $vendorDir . '/symfony/http-foundation/Session/Flash/AutoExpireFlashBag.php',
    '_ContaoManager\\Symfony\\Component\\HttpFoundation\\Session\\Flash\\FlashBag' => $vendorDir . '/symfony/http-foundation/Session/Flash/FlashBag.php',
    '_ContaoManager\\Symfony\\Component\\HttpFoundation\\Session\\Flash\\FlashBagInterface' => $vendorDir . '/symfony/http-foundation/Session/Flash/FlashBagInterface.php',
    '_ContaoManager\\Symfony\\Component\\HttpFoundation\\Session\\Session' => $vendorDir . '/symfony/http-foundation/Session/Session.php',
    '_ContaoManager\\Symfony\\Component\\HttpFoundation\\Session\\SessionBagInterface' => $vendorDir . '/symfony/http-foundation/Session/SessionBagInterface.php',
    '_ContaoManager\\Symfony\\Component\\HttpFoundation\\Session\\SessionBagProxy' => $vendorDir . '/symfony/http-foundation/Session/SessionBagProxy.php',
    '_ContaoManager\\Symfony\\Component\\HttpFoundation\\Session\\SessionFactory' => $vendorDir . '/symfony/http-foundation/Session/SessionFactory.php',
    '_ContaoManager\\Symfony\\Component\\HttpFoundation\\Session\\SessionFactoryInterface' => $vendorDir . '/symfony/http-foundation/Session/SessionFactoryInterface.php',
    '_ContaoManager\\Symfony\\Component\\HttpFoundation\\Session\\SessionInterface' => $vendorDir . '/symfony/http-foundation/Session/SessionInterface.php',
    '_ContaoManager\\Symfony\\Component\\HttpFoundation\\Session\\SessionUtils' => $vendorDir . '/symfony/http-foundation/Session/SessionUtils.php',
    '_ContaoManager\\Symfony\\Component\\HttpFoundation\\Session\\Storage\\Handler\\AbstractSessionHandler' => $vendorDir . '/symfony/http-foundation/Session/Storage/Handler/AbstractSessionHandler.php',
    '_ContaoManager\\Symfony\\Component\\HttpFoundation\\Session\\Storage\\Handler\\IdentityMarshaller' => $vendorDir . '/symfony/http-foundation/Session/Storage/Handler/IdentityMarshaller.php',
    '_ContaoManager\\Symfony\\Component\\HttpFoundation\\Session\\Storage\\Handler\\MarshallingSessionHandler' => $vendorDir . '/symfony/http-foundation/Session/Storage/Handler/MarshallingSessionHandler.php',
    '_ContaoManager\\Symfony\\Component\\HttpFoundation\\Session\\Storage\\Handler\\MemcachedSessionHandler' => $vendorDir . '/symfony/http-foundation/Session/Storage/Handler/MemcachedSessionHandler.php',
    '_ContaoManager\\Symfony\\Component\\HttpFoundation\\Session\\Storage\\Handler\\MigratingSessionHandler' => $vendorDir . '/symfony/http-foundation/Session/Storage/Handler/MigratingSessionHandler.php',
    '_ContaoManager\\Symfony\\Component\\HttpFoundation\\Session\\Storage\\Handler\\MongoDbSessionHandler' => $vendorDir . '/symfony/http-foundation/Session/Storage/Handler/MongoDbSessionHandler.php',
    '_ContaoManager\\Symfony\\Component\\HttpFoundation\\Session\\Storage\\Handler\\NativeFileSessionHandler' => $vendorDir . '/symfony/http-foundation/Session/Storage/Handler/NativeFileSessionHandler.php',
    '_ContaoManager\\Symfony\\Component\\HttpFoundation\\Session\\Storage\\Handler\\NullSessionHandler' => $vendorDir . '/symfony/http-foundation/Session/Storage/Handler/NullSessionHandler.php',
    '_ContaoManager\\Symfony\\Component\\HttpFoundation\\Session\\Storage\\Handler\\PdoSessionHandler' => $vendorDir . '/symfony/http-foundation/Session/Storage/Handler/PdoSessionHandler.php',
    '_ContaoManager\\Symfony\\Component\\HttpFoundation\\Session\\Storage\\Handler\\RedisSessionHandler' => $vendorDir . '/symfony/http-foundation/Session/Storage/Handler/RedisSessionHandler.php',
    '_ContaoManager\\Symfony\\Component\\HttpFoundation\\Session\\Storage\\Handler\\SessionHandlerFactory' => $vendorDir . '/symfony/http-foundation/Session/Storage/Handler/SessionHandlerFactory.php',
    '_ContaoManager\\Symfony\\Component\\HttpFoundation\\Session\\Storage\\Handler\\StrictSessionHandler' => $vendorDir . '/symfony/http-foundation/Session/Storage/Handler/StrictSessionHandler.php',
    '_ContaoManager\\Symfony\\Component\\HttpFoundation\\Session\\Storage\\MetadataBag' => $vendorDir . '/symfony/http-foundation/Session/Storage/MetadataBag.php',
    '_ContaoManager\\Symfony\\Component\\HttpFoundation\\Session\\Storage\\MockArraySessionStorage' => $vendorDir . '/symfony/http-foundation/Session/Storage/MockArraySessionStorage.php',
    '_ContaoManager\\Symfony\\Component\\HttpFoundation\\Session\\Storage\\MockFileSessionStorage' => $vendorDir . '/symfony/http-foundation/Session/Storage/MockFileSessionStorage.php',
    '_ContaoManager\\Symfony\\Component\\HttpFoundation\\Session\\Storage\\MockFileSessionStorageFactory' => $vendorDir . '/symfony/http-foundation/Session/Storage/MockFileSessionStorageFactory.php',
    '_ContaoManager\\Symfony\\Component\\HttpFoundation\\Session\\Storage\\NativeSessionStorage' => $vendorDir . '/symfony/http-foundation/Session/Storage/NativeSessionStorage.php',
    '_ContaoManager\\Symfony\\Component\\HttpFoundation\\Session\\Storage\\NativeSessionStorageFactory' => $vendorDir . '/symfony/http-foundation/Session/Storage/NativeSessionStorageFactory.php',
    '_ContaoManager\\Symfony\\Component\\HttpFoundation\\Session\\Storage\\PhpBridgeSessionStorage' => $vendorDir . '/symfony/http-foundation/Session/Storage/PhpBridgeSessionStorage.php',
    '_ContaoManager\\Symfony\\Component\\HttpFoundation\\Session\\Storage\\PhpBridgeSessionStorageFactory' => $vendorDir . '/symfony/http-foundation/Session/Storage/PhpBridgeSessionStorageFactory.php',
    '_ContaoManager\\Symfony\\Component\\HttpFoundation\\Session\\Storage\\Proxy\\AbstractProxy' => $vendorDir . '/symfony/http-foundation/Session/Storage/Proxy/AbstractProxy.php',
    '_ContaoManager\\Symfony\\Component\\HttpFoundation\\Session\\Storage\\Proxy\\SessionHandlerProxy' => $vendorDir . '/symfony/http-foundation/Session/Storage/Proxy/SessionHandlerProxy.php',
    '_ContaoManager\\Symfony\\Component\\HttpFoundation\\Session\\Storage\\SessionStorageFactoryInterface' => $vendorDir . '/symfony/http-foundation/Session/Storage/SessionStorageFactoryInterface.php',
    '_ContaoManager\\Symfony\\Component\\HttpFoundation\\Session\\Storage\\SessionStorageInterface' => $vendorDir . '/symfony/http-foundation/Session/Storage/SessionStorageInterface.php',
    '_ContaoManager\\Symfony\\Component\\HttpFoundation\\StreamedJsonResponse' => $vendorDir . '/symfony/http-foundation/StreamedJsonResponse.php',
    '_ContaoManager\\Symfony\\Component\\HttpFoundation\\StreamedResponse' => $vendorDir . '/symfony/http-foundation/StreamedResponse.php',
    '_ContaoManager\\Symfony\\Component\\HttpFoundation\\Test\\Constraint\\RequestAttributeValueSame' => $vendorDir . '/symfony/http-foundation/Test/Constraint/RequestAttributeValueSame.php',
    '_ContaoManager\\Symfony\\Component\\HttpFoundation\\Test\\Constraint\\ResponseCookieValueSame' => $vendorDir . '/symfony/http-foundation/Test/Constraint/ResponseCookieValueSame.php',
    '_ContaoManager\\Symfony\\Component\\HttpFoundation\\Test\\Constraint\\ResponseFormatSame' => $vendorDir . '/symfony/http-foundation/Test/Constraint/ResponseFormatSame.php',
    '_ContaoManager\\Symfony\\Component\\HttpFoundation\\Test\\Constraint\\ResponseHasCookie' => $vendorDir . '/symfony/http-foundation/Test/Constraint/ResponseHasCookie.php',
    '_ContaoManager\\Symfony\\Component\\HttpFoundation\\Test\\Constraint\\ResponseHasHeader' => $vendorDir . '/symfony/http-foundation/Test/Constraint/ResponseHasHeader.php',
    '_ContaoManager\\Symfony\\Component\\HttpFoundation\\Test\\Constraint\\ResponseHeaderLocationSame' => $vendorDir . '/symfony/http-foundation/Test/Constraint/ResponseHeaderLocationSame.php',
    '_ContaoManager\\Symfony\\Component\\HttpFoundation\\Test\\Constraint\\ResponseHeaderSame' => $vendorDir . '/symfony/http-foundation/Test/Constraint/ResponseHeaderSame.php',
    '_ContaoManager\\Symfony\\Component\\HttpFoundation\\Test\\Constraint\\ResponseIsRedirected' => $vendorDir . '/symfony/http-foundation/Test/Constraint/ResponseIsRedirected.php',
    '_ContaoManager\\Symfony\\Component\\HttpFoundation\\Test\\Constraint\\ResponseIsSuccessful' => $vendorDir . '/symfony/http-foundation/Test/Constraint/ResponseIsSuccessful.php',
    '_ContaoManager\\Symfony\\Component\\HttpFoundation\\Test\\Constraint\\ResponseIsUnprocessable' => $vendorDir . '/symfony/http-foundation/Test/Constraint/ResponseIsUnprocessable.php',
    '_ContaoManager\\Symfony\\Component\\HttpFoundation\\Test\\Constraint\\ResponseStatusCodeSame' => $vendorDir . '/symfony/http-foundation/Test/Constraint/ResponseStatusCodeSame.php',
    '_ContaoManager\\Symfony\\Component\\HttpFoundation\\UriSigner' => $vendorDir . '/symfony/http-foundation/UriSigner.php',
    '_ContaoManager\\Symfony\\Component\\HttpFoundation\\UrlHelper' => $vendorDir . '/symfony/http-foundation/UrlHelper.php',
    '_ContaoManager\\Symfony\\Component\\HttpKernel\\Attribute\\AsController' => $vendorDir . '/symfony/http-kernel/Attribute/AsController.php',
    '_ContaoManager\\Symfony\\Component\\HttpKernel\\Attribute\\AsTargetedValueResolver' => $vendorDir . '/symfony/http-kernel/Attribute/AsTargetedValueResolver.php',
    '_ContaoManager\\Symfony\\Component\\HttpKernel\\Attribute\\Cache' => $vendorDir . '/symfony/http-kernel/Attribute/Cache.php',
    '_ContaoManager\\Symfony\\Component\\HttpKernel\\Attribute\\MapDateTime' => $vendorDir . '/symfony/http-kernel/Attribute/MapDateTime.php',
    '_ContaoManager\\Symfony\\Component\\HttpKernel\\Attribute\\MapQueryParameter' => $vendorDir . '/symfony/http-kernel/Attribute/MapQueryParameter.php',
    '_ContaoManager\\Symfony\\Component\\HttpKernel\\Attribute\\MapQueryString' => $vendorDir . '/symfony/http-kernel/Attribute/MapQueryString.php',
    '_ContaoManager\\Symfony\\Component\\HttpKernel\\Attribute\\MapRequestPayload' => $vendorDir . '/symfony/http-kernel/Attribute/MapRequestPayload.php',
    '_ContaoManager\\Symfony\\Component\\HttpKernel\\Attribute\\ValueResolver' => $vendorDir . '/symfony/http-kernel/Attribute/ValueResolver.php',
    '_ContaoManager\\Symfony\\Component\\HttpKernel\\Attribute\\WithHttpStatus' => $vendorDir . '/symfony/http-kernel/Attribute/WithHttpStatus.php',
    '_ContaoManager\\Symfony\\Component\\HttpKernel\\Attribute\\WithLogLevel' => $vendorDir . '/symfony/http-kernel/Attribute/WithLogLevel.php',
    '_ContaoManager\\Symfony\\Component\\HttpKernel\\Bundle\\AbstractBundle' => $vendorDir . '/symfony/http-kernel/Bundle/AbstractBundle.php',
    '_ContaoManager\\Symfony\\Component\\HttpKernel\\Bundle\\Bundle' => $vendorDir . '/symfony/http-kernel/Bundle/Bundle.php',
    '_ContaoManager\\Symfony\\Component\\HttpKernel\\Bundle\\BundleExtension' => $vendorDir . '/symfony/http-kernel/Bundle/BundleExtension.php',
    '_ContaoManager\\Symfony\\Component\\HttpKernel\\Bundle\\BundleInterface' => $vendorDir . '/symfony/http-kernel/Bundle/BundleInterface.php',
    '_ContaoManager\\Symfony\\Component\\HttpKernel\\CacheClearer\\CacheClearerInterface' => $vendorDir . '/symfony/http-kernel/CacheClearer/CacheClearerInterface.php',
    '_ContaoManager\\Symfony\\Component\\HttpKernel\\CacheClearer\\ChainCacheClearer' => $vendorDir . '/symfony/http-kernel/CacheClearer/ChainCacheClearer.php',
    '_ContaoManager\\Symfony\\Component\\HttpKernel\\CacheClearer\\Psr6CacheClearer' => $vendorDir . '/symfony/http-kernel/CacheClearer/Psr6CacheClearer.php',
    '_ContaoManager\\Symfony\\Component\\HttpKernel\\CacheWarmer\\CacheWarmer' => $vendorDir . '/symfony/http-kernel/CacheWarmer/CacheWarmer.php',
    '_ContaoManager\\Symfony\\Component\\HttpKernel\\CacheWarmer\\CacheWarmerAggregate' => $vendorDir . '/symfony/http-kernel/CacheWarmer/CacheWarmerAggregate.php',
    '_ContaoManager\\Symfony\\Component\\HttpKernel\\CacheWarmer\\CacheWarmerInterface' => $vendorDir . '/symfony/http-kernel/CacheWarmer/CacheWarmerInterface.php',
    '_ContaoManager\\Symfony\\Component\\HttpKernel\\CacheWarmer\\WarmableInterface' => $vendorDir . '/symfony/http-kernel/CacheWarmer/WarmableInterface.php',
    '_ContaoManager\\Symfony\\Component\\HttpKernel\\Config\\FileLocator' => $vendorDir . '/symfony/http-kernel/Config/FileLocator.php',
    '_ContaoManager\\Symfony\\Component\\HttpKernel\\ControllerMetadata\\ArgumentMetadata' => $vendorDir . '/symfony/http-kernel/ControllerMetadata/ArgumentMetadata.php',
    '_ContaoManager\\Symfony\\Component\\HttpKernel\\ControllerMetadata\\ArgumentMetadataFactory' => $vendorDir . '/symfony/http-kernel/ControllerMetadata/ArgumentMetadataFactory.php',
    '_ContaoManager\\Symfony\\Component\\HttpKernel\\ControllerMetadata\\ArgumentMetadataFactoryInterface' => $vendorDir . '/symfony/http-kernel/ControllerMetadata/ArgumentMetadataFactoryInterface.php',
    '_ContaoManager\\Symfony\\Component\\HttpKernel\\Controller\\ArgumentResolver' => $vendorDir . '/symfony/http-kernel/Controller/ArgumentResolver.php',
    '_ContaoManager\\Symfony\\Component\\HttpKernel\\Controller\\ArgumentResolverInterface' => $vendorDir . '/symfony/http-kernel/Controller/ArgumentResolverInterface.php',
    '_ContaoManager\\Symfony\\Component\\HttpKernel\\Controller\\ArgumentResolver\\BackedEnumValueResolver' => $vendorDir . '/symfony/http-kernel/Controller/ArgumentResolver/BackedEnumValueResolver.php',
    '_ContaoManager\\Symfony\\Component\\HttpKernel\\Controller\\ArgumentResolver\\DateTimeValueResolver' => $vendorDir . '/symfony/http-kernel/Controller/ArgumentResolver/DateTimeValueResolver.php',
    '_ContaoManager\\Symfony\\Component\\HttpKernel\\Controller\\ArgumentResolver\\DefaultValueResolver' => $vendorDir . '/symfony/http-kernel/Controller/ArgumentResolver/DefaultValueResolver.php',
    '_ContaoManager\\Symfony\\Component\\HttpKernel\\Controller\\ArgumentResolver\\NotTaggedControllerValueResolver' => $vendorDir . '/symfony/http-kernel/Controller/ArgumentResolver/NotTaggedControllerValueResolver.php',
    '_ContaoManager\\Symfony\\Component\\HttpKernel\\Controller\\ArgumentResolver\\QueryParameterValueResolver' => $vendorDir . '/symfony/http-kernel/Controller/ArgumentResolver/QueryParameterValueResolver.php',
    '_ContaoManager\\Symfony\\Component\\HttpKernel\\Controller\\ArgumentResolver\\RequestAttributeValueResolver' => $vendorDir . '/symfony/http-kernel/Controller/ArgumentResolver/RequestAttributeValueResolver.php',
    '_ContaoManager\\Symfony\\Component\\HttpKernel\\Controller\\ArgumentResolver\\RequestPayloadValueResolver' => $vendorDir . '/symfony/http-kernel/Controller/ArgumentResolver/RequestPayloadValueResolver.php',
    '_ContaoManager\\Symfony\\Component\\HttpKernel\\Controller\\ArgumentResolver\\RequestValueResolver' => $vendorDir . '/symfony/http-kernel/Controller/ArgumentResolver/RequestValueResolver.php',
    '_ContaoManager\\Symfony\\Component\\HttpKernel\\Controller\\ArgumentResolver\\ServiceValueResolver' => $vendorDir . '/symfony/http-kernel/Controller/ArgumentResolver/ServiceValueResolver.php',
    '_ContaoManager\\Symfony\\Component\\HttpKernel\\Controller\\ArgumentResolver\\SessionValueResolver' => $vendorDir . '/symfony/http-kernel/Controller/ArgumentResolver/SessionValueResolver.php',
    '_ContaoManager\\Symfony\\Component\\HttpKernel\\Controller\\ArgumentResolver\\TraceableValueResolver' => $vendorDir . '/symfony/http-kernel/Controller/ArgumentResolver/TraceableValueResolver.php',
    '_ContaoManager\\Symfony\\Component\\HttpKernel\\Controller\\ArgumentResolver\\UidValueResolver' => $vendorDir . '/symfony/http-kernel/Controller/ArgumentResolver/UidValueResolver.php',
    '_ContaoManager\\Symfony\\Component\\HttpKernel\\Controller\\ArgumentResolver\\VariadicValueResolver' => $vendorDir . '/symfony/http-kernel/Controller/ArgumentResolver/VariadicValueResolver.php',
    '_ContaoManager\\Symfony\\Component\\HttpKernel\\Controller\\ArgumentValueResolverInterface' => $vendorDir . '/symfony/http-kernel/Controller/ArgumentValueResolverInterface.php',
    '_ContaoManager\\Symfony\\Component\\HttpKernel\\Controller\\ContainerControllerResolver' => $vendorDir . '/symfony/http-kernel/Controller/ContainerControllerResolver.php',
    '_ContaoManager\\Symfony\\Component\\HttpKernel\\Controller\\ControllerReference' => $vendorDir . '/symfony/http-kernel/Controller/ControllerReference.php',
    '_ContaoManager\\Symfony\\Component\\HttpKernel\\Controller\\ControllerResolver' => $vendorDir . '/symfony/http-kernel/Controller/ControllerResolver.php',
    '_ContaoManager\\Symfony\\Component\\HttpKernel\\Controller\\ControllerResolverInterface' => $vendorDir . '/symfony/http-kernel/Controller/ControllerResolverInterface.php',
    '_ContaoManager\\Symfony\\Component\\HttpKernel\\Controller\\ErrorController' => $vendorDir . '/symfony/http-kernel/Controller/ErrorController.php',
    '_ContaoManager\\Symfony\\Component\\HttpKernel\\Controller\\TraceableArgumentResolver' => $vendorDir . '/symfony/http-kernel/Controller/TraceableArgumentResolver.php',
    '_ContaoManager\\Symfony\\Component\\HttpKernel\\Controller\\TraceableControllerResolver' => $vendorDir . '/symfony/http-kernel/Controller/TraceableControllerResolver.php',
    '_ContaoManager\\Symfony\\Component\\HttpKernel\\Controller\\ValueResolverInterface' => $vendorDir . '/symfony/http-kernel/Controller/ValueResolverInterface.php',
    '_ContaoManager\\Symfony\\Component\\HttpKernel\\DataCollector\\AjaxDataCollector' => $vendorDir . '/symfony/http-kernel/DataCollector/AjaxDataCollector.php',
    '_ContaoManager\\Symfony\\Component\\HttpKernel\\DataCollector\\ConfigDataCollector' => $vendorDir . '/symfony/http-kernel/DataCollector/ConfigDataCollector.php',
    '_ContaoManager\\Symfony\\Component\\HttpKernel\\DataCollector\\DataCollector' => $vendorDir . '/symfony/http-kernel/DataCollector/DataCollector.php',
    '_ContaoManager\\Symfony\\Component\\HttpKernel\\DataCollector\\DataCollectorInterface' => $vendorDir . '/symfony/http-kernel/DataCollector/DataCollectorInterface.php',
    '_ContaoManager\\Symfony\\Component\\HttpKernel\\DataCollector\\DumpDataCollector' => $vendorDir . '/symfony/http-kernel/DataCollector/DumpDataCollector.php',
    '_ContaoManager\\Symfony\\Component\\HttpKernel\\DataCollector\\EventDataCollector' => $vendorDir . '/symfony/http-kernel/DataCollector/EventDataCollector.php',
    '_ContaoManager\\Symfony\\Component\\HttpKernel\\DataCollector\\ExceptionDataCollector' => $vendorDir . '/symfony/http-kernel/DataCollector/ExceptionDataCollector.php',
    '_ContaoManager\\Symfony\\Component\\HttpKernel\\DataCollector\\LateDataCollectorInterface' => $vendorDir . '/symfony/http-kernel/DataCollector/LateDataCollectorInterface.php',
    '_ContaoManager\\Symfony\\Component\\HttpKernel\\DataCollector\\LoggerDataCollector' => $vendorDir . '/symfony/http-kernel/DataCollector/LoggerDataCollector.php',
    '_ContaoManager\\Symfony\\Component\\HttpKernel\\DataCollector\\MemoryDataCollector' => $vendorDir . '/symfony/http-kernel/DataCollector/MemoryDataCollector.php',
    '_ContaoManager\\Symfony\\Component\\HttpKernel\\DataCollector\\RequestDataCollector' => $vendorDir . '/symfony/http-kernel/DataCollector/RequestDataCollector.php',
    '_ContaoManager\\Symfony\\Component\\HttpKernel\\DataCollector\\RouterDataCollector' => $vendorDir . '/symfony/http-kernel/DataCollector/RouterDataCollector.php',
    '_ContaoManager\\Symfony\\Component\\HttpKernel\\DataCollector\\TimeDataCollector' => $vendorDir . '/symfony/http-kernel/DataCollector/TimeDataCollector.php',
    '_ContaoManager\\Symfony\\Component\\HttpKernel\\Debug\\ErrorHandlerConfigurator' => $vendorDir . '/symfony/http-kernel/Debug/ErrorHandlerConfigurator.php',
    '_ContaoManager\\Symfony\\Component\\HttpKernel\\Debug\\FileLinkFormatter' => $vendorDir . '/symfony/http-kernel/Debug/FileLinkFormatter.php',
    '_ContaoManager\\Symfony\\Component\\HttpKernel\\Debug\\TraceableEventDispatcher' => $vendorDir . '/symfony/http-kernel/Debug/TraceableEventDispatcher.php',
    '_ContaoManager\\Symfony\\Component\\HttpKernel\\Debug\\VirtualRequestStack' => $vendorDir . '/symfony/http-kernel/Debug/VirtualRequestStack.php',
    '_ContaoManager\\Symfony\\Component\\HttpKernel\\DependencyInjection\\AddAnnotatedClassesToCachePass' => $vendorDir . '/symfony/http-kernel/DependencyInjection/AddAnnotatedClassesToCachePass.php',
    '_ContaoManager\\Symfony\\Component\\HttpKernel\\DependencyInjection\\ConfigurableExtension' => $vendorDir . '/symfony/http-kernel/DependencyInjection/ConfigurableExtension.php',
    '_ContaoManager\\Symfony\\Component\\HttpKernel\\DependencyInjection\\ControllerArgumentValueResolverPass' => $vendorDir . '/symfony/http-kernel/DependencyInjection/ControllerArgumentValueResolverPass.php',
    '_ContaoManager\\Symfony\\Component\\HttpKernel\\DependencyInjection\\Extension' => $vendorDir . '/symfony/http-kernel/DependencyInjection/Extension.php',
    '_ContaoManager\\Symfony\\Component\\HttpKernel\\DependencyInjection\\FragmentRendererPass' => $vendorDir . '/symfony/http-kernel/DependencyInjection/FragmentRendererPass.php',
    '_ContaoManager\\Symfony\\Component\\HttpKernel\\DependencyInjection\\LazyLoadingFragmentHandler' => $vendorDir . '/symfony/http-kernel/DependencyInjection/LazyLoadingFragmentHandler.php',
    '_ContaoManager\\Symfony\\Component\\HttpKernel\\DependencyInjection\\LoggerPass' => $vendorDir . '/symfony/http-kernel/DependencyInjection/LoggerPass.php',
    '_ContaoManager\\Symfony\\Component\\HttpKernel\\DependencyInjection\\MergeExtensionConfigurationPass' => $vendorDir . '/symfony/http-kernel/DependencyInjection/MergeExtensionConfigurationPass.php',
    '_ContaoManager\\Symfony\\Component\\HttpKernel\\DependencyInjection\\RegisterControllerArgumentLocatorsPass' => $vendorDir . '/symfony/http-kernel/DependencyInjection/RegisterControllerArgumentLocatorsPass.php',
    '_ContaoManager\\Symfony\\Component\\HttpKernel\\DependencyInjection\\RegisterLocaleAwareServicesPass' => $vendorDir . '/symfony/http-kernel/DependencyInjection/RegisterLocaleAwareServicesPass.php',
    '_ContaoManager\\Symfony\\Component\\HttpKernel\\DependencyInjection\\RemoveEmptyControllerArgumentLocatorsPass' => $vendorDir . '/symfony/http-kernel/DependencyInjection/RemoveEmptyControllerArgumentLocatorsPass.php',
    '_ContaoManager\\Symfony\\Component\\HttpKernel\\DependencyInjection\\ResettableServicePass' => $vendorDir . '/symfony/http-kernel/DependencyInjection/ResettableServicePass.php',
    '_ContaoManager\\Symfony\\Component\\HttpKernel\\DependencyInjection\\ServicesResetter' => $vendorDir . '/symfony/http-kernel/DependencyInjection/ServicesResetter.php',
    '_ContaoManager\\Symfony\\Component\\HttpKernel\\EventListener\\AbstractSessionListener' => $vendorDir . '/symfony/http-kernel/EventListener/AbstractSessionListener.php',
    '_ContaoManager\\Symfony\\Component\\HttpKernel\\EventListener\\AddRequestFormatsListener' => $vendorDir . '/symfony/http-kernel/EventListener/AddRequestFormatsListener.php',
    '_ContaoManager\\Symfony\\Component\\HttpKernel\\EventListener\\CacheAttributeListener' => $vendorDir . '/symfony/http-kernel/EventListener/CacheAttributeListener.php',
    '_ContaoManager\\Symfony\\Component\\HttpKernel\\EventListener\\DebugHandlersListener' => $vendorDir . '/symfony/http-kernel/EventListener/DebugHandlersListener.php',
    '_ContaoManager\\Symfony\\Component\\HttpKernel\\EventListener\\DisallowRobotsIndexingListener' => $vendorDir . '/symfony/http-kernel/EventListener/DisallowRobotsIndexingListener.php',
    '_ContaoManager\\Symfony\\Component\\HttpKernel\\EventListener\\DumpListener' => $vendorDir . '/symfony/http-kernel/EventListener/DumpListener.php',
    '_ContaoManager\\Symfony\\Component\\HttpKernel\\EventListener\\ErrorListener' => $vendorDir . '/symfony/http-kernel/EventListener/ErrorListener.php',
    '_ContaoManager\\Symfony\\Component\\HttpKernel\\EventListener\\FragmentListener' => $vendorDir . '/symfony/http-kernel/EventListener/FragmentListener.php',
    '_ContaoManager\\Symfony\\Component\\HttpKernel\\EventListener\\LocaleAwareListener' => $vendorDir . '/symfony/http-kernel/EventListener/LocaleAwareListener.php',
    '_ContaoManager\\Symfony\\Component\\HttpKernel\\EventListener\\LocaleListener' => $vendorDir . '/symfony/http-kernel/EventListener/LocaleListener.php',
    '_ContaoManager\\Symfony\\Component\\HttpKernel\\EventListener\\ProfilerListener' => $vendorDir . '/symfony/http-kernel/EventListener/ProfilerListener.php',
    '_ContaoManager\\Symfony\\Component\\HttpKernel\\EventListener\\ResponseListener' => $vendorDir . '/symfony/http-kernel/EventListener/ResponseListener.php',
    '_ContaoManager\\Symfony\\Component\\HttpKernel\\EventListener\\RouterListener' => $vendorDir . '/symfony/http-kernel/EventListener/RouterListener.php',
    '_ContaoManager\\Symfony\\Component\\HttpKernel\\EventListener\\SessionListener' => $vendorDir . '/symfony/http-kernel/EventListener/SessionListener.php',
    '_ContaoManager\\Symfony\\Component\\HttpKernel\\EventListener\\StreamedResponseListener' => $vendorDir . '/symfony/http-kernel/EventListener/StreamedResponseListener.php',
    '_ContaoManager\\Symfony\\Component\\HttpKernel\\EventListener\\SurrogateListener' => $vendorDir . '/symfony/http-kernel/EventListener/SurrogateListener.php',
    '_ContaoManager\\Symfony\\Component\\HttpKernel\\EventListener\\ValidateRequestListener' => $vendorDir . '/symfony/http-kernel/EventListener/ValidateRequestListener.php',
    '_ContaoManager\\Symfony\\Component\\HttpKernel\\Event\\ControllerArgumentsEvent' => $vendorDir . '/symfony/http-kernel/Event/ControllerArgumentsEvent.php',
    '_ContaoManager\\Symfony\\Component\\HttpKernel\\Event\\ControllerEvent' => $vendorDir . '/symfony/http-kernel/Event/ControllerEvent.php',
    '_ContaoManager\\Symfony\\Component\\HttpKernel\\Event\\ExceptionEvent' => $vendorDir . '/symfony/http-kernel/Event/ExceptionEvent.php',
    '_ContaoManager\\Symfony\\Component\\HttpKernel\\Event\\FinishRequestEvent' => $vendorDir . '/symfony/http-kernel/Event/FinishRequestEvent.php',
    '_ContaoManager\\Symfony\\Component\\HttpKernel\\Event\\KernelEvent' => $vendorDir . '/symfony/http-kernel/Event/KernelEvent.php',
    '_ContaoManager\\Symfony\\Component\\HttpKernel\\Event\\RequestEvent' => $vendorDir . '/symfony/http-kernel/Event/RequestEvent.php',
    '_ContaoManager\\Symfony\\Component\\HttpKernel\\Event\\ResponseEvent' => $vendorDir . '/symfony/http-kernel/Event/ResponseEvent.php',
    '_ContaoManager\\Symfony\\Component\\HttpKernel\\Event\\TerminateEvent' => $vendorDir . '/symfony/http-kernel/Event/TerminateEvent.php',
    '_ContaoManager\\Symfony\\Component\\HttpKernel\\Event\\ViewEvent' => $vendorDir . '/symfony/http-kernel/Event/ViewEvent.php',
    '_ContaoManager\\Symfony\\Component\\HttpKernel\\Exception\\AccessDeniedHttpException' => $vendorDir . '/symfony/http-kernel/Exception/AccessDeniedHttpException.php',
    '_ContaoManager\\Symfony\\Component\\HttpKernel\\Exception\\BadRequestHttpException' => $vendorDir . '/symfony/http-kernel/Exception/BadRequestHttpException.php',
    '_ContaoManager\\Symfony\\Component\\HttpKernel\\Exception\\ConflictHttpException' => $vendorDir . '/symfony/http-kernel/Exception/ConflictHttpException.php',
    '_ContaoManager\\Symfony\\Component\\HttpKernel\\Exception\\ControllerDoesNotReturnResponseException' => $vendorDir . '/symfony/http-kernel/Exception/ControllerDoesNotReturnResponseException.php',
    '_ContaoManager\\Symfony\\Component\\HttpKernel\\Exception\\GoneHttpException' => $vendorDir . '/symfony/http-kernel/Exception/GoneHttpException.php',
    '_ContaoManager\\Symfony\\Component\\HttpKernel\\Exception\\HttpException' => $vendorDir . '/symfony/http-kernel/Exception/HttpException.php',
    '_ContaoManager\\Symfony\\Component\\HttpKernel\\Exception\\HttpExceptionInterface' => $vendorDir . '/symfony/http-kernel/Exception/HttpExceptionInterface.php',
    '_ContaoManager\\Symfony\\Component\\HttpKernel\\Exception\\InvalidMetadataException' => $vendorDir . '/symfony/http-kernel/Exception/InvalidMetadataException.php',
    '_ContaoManager\\Symfony\\Component\\HttpKernel\\Exception\\LengthRequiredHttpException' => $vendorDir . '/symfony/http-kernel/Exception/LengthRequiredHttpException.php',
    '_ContaoManager\\Symfony\\Component\\HttpKernel\\Exception\\LockedHttpException' => $vendorDir . '/symfony/http-kernel/Exception/LockedHttpException.php',
    '_ContaoManager\\Symfony\\Component\\HttpKernel\\Exception\\MethodNotAllowedHttpException' => $vendorDir . '/symfony/http-kernel/Exception/MethodNotAllowedHttpException.php',
    '_ContaoManager\\Symfony\\Component\\HttpKernel\\Exception\\NotAcceptableHttpException' => $vendorDir . '/symfony/http-kernel/Exception/NotAcceptableHttpException.php',
    '_ContaoManager\\Symfony\\Component\\HttpKernel\\Exception\\NotFoundHttpException' => $vendorDir . '/symfony/http-kernel/Exception/NotFoundHttpException.php',
    '_ContaoManager\\Symfony\\Component\\HttpKernel\\Exception\\PreconditionFailedHttpException' => $vendorDir . '/symfony/http-kernel/Exception/PreconditionFailedHttpException.php',
    '_ContaoManager\\Symfony\\Component\\HttpKernel\\Exception\\PreconditionRequiredHttpException' => $vendorDir . '/symfony/http-kernel/Exception/PreconditionRequiredHttpException.php',
    '_ContaoManager\\Symfony\\Component\\HttpKernel\\Exception\\ResolverNotFoundException' => $vendorDir . '/symfony/http-kernel/Exception/ResolverNotFoundException.php',
    '_ContaoManager\\Symfony\\Component\\HttpKernel\\Exception\\ServiceUnavailableHttpException' => $vendorDir . '/symfony/http-kernel/Exception/ServiceUnavailableHttpException.php',
    '_ContaoManager\\Symfony\\Component\\HttpKernel\\Exception\\TooManyRequestsHttpException' => $vendorDir . '/symfony/http-kernel/Exception/TooManyRequestsHttpException.php',
    '_ContaoManager\\Symfony\\Component\\HttpKernel\\Exception\\UnauthorizedHttpException' => $vendorDir . '/symfony/http-kernel/Exception/UnauthorizedHttpException.php',
    '_ContaoManager\\Symfony\\Component\\HttpKernel\\Exception\\UnexpectedSessionUsageException' => $vendorDir . '/symfony/http-kernel/Exception/UnexpectedSessionUsageException.php',
    '_ContaoManager\\Symfony\\Component\\HttpKernel\\Exception\\UnprocessableEntityHttpException' => $vendorDir . '/symfony/http-kernel/Exception/UnprocessableEntityHttpException.php',
    '_ContaoManager\\Symfony\\Component\\HttpKernel\\Exception\\UnsupportedMediaTypeHttpException' => $vendorDir . '/symfony/http-kernel/Exception/UnsupportedMediaTypeHttpException.php',
    '_ContaoManager\\Symfony\\Component\\HttpKernel\\Fragment\\AbstractSurrogateFragmentRenderer' => $vendorDir . '/symfony/http-kernel/Fragment/AbstractSurrogateFragmentRenderer.php',
    '_ContaoManager\\Symfony\\Component\\HttpKernel\\Fragment\\EsiFragmentRenderer' => $vendorDir . '/symfony/http-kernel/Fragment/EsiFragmentRenderer.php',
    '_ContaoManager\\Symfony\\Component\\HttpKernel\\Fragment\\FragmentHandler' => $vendorDir . '/symfony/http-kernel/Fragment/FragmentHandler.php',
    '_ContaoManager\\Symfony\\Component\\HttpKernel\\Fragment\\FragmentRendererInterface' => $vendorDir . '/symfony/http-kernel/Fragment/FragmentRendererInterface.php',
    '_ContaoManager\\Symfony\\Component\\HttpKernel\\Fragment\\FragmentUriGenerator' => $vendorDir . '/symfony/http-kernel/Fragment/FragmentUriGenerator.php',
    '_ContaoManager\\Symfony\\Component\\HttpKernel\\Fragment\\FragmentUriGeneratorInterface' => $vendorDir . '/symfony/http-kernel/Fragment/FragmentUriGeneratorInterface.php',
    '_ContaoManager\\Symfony\\Component\\HttpKernel\\Fragment\\HIncludeFragmentRenderer' => $vendorDir . '/symfony/http-kernel/Fragment/HIncludeFragmentRenderer.php',
    '_ContaoManager\\Symfony\\Component\\HttpKernel\\Fragment\\InlineFragmentRenderer' => $vendorDir . '/symfony/http-kernel/Fragment/InlineFragmentRenderer.php',
    '_ContaoManager\\Symfony\\Component\\HttpKernel\\Fragment\\RoutableFragmentRenderer' => $vendorDir . '/symfony/http-kernel/Fragment/RoutableFragmentRenderer.php',
    '_ContaoManager\\Symfony\\Component\\HttpKernel\\Fragment\\SsiFragmentRenderer' => $vendorDir . '/symfony/http-kernel/Fragment/SsiFragmentRenderer.php',
    '_ContaoManager\\Symfony\\Component\\HttpKernel\\HttpCache\\AbstractSurrogate' => $vendorDir . '/symfony/http-kernel/HttpCache/AbstractSurrogate.php',
    '_ContaoManager\\Symfony\\Component\\HttpKernel\\HttpCache\\CacheWasLockedException' => $vendorDir . '/symfony/http-kernel/HttpCache/CacheWasLockedException.php',
    '_ContaoManager\\Symfony\\Component\\HttpKernel\\HttpCache\\Esi' => $vendorDir . '/symfony/http-kernel/HttpCache/Esi.php',
    '_ContaoManager\\Symfony\\Component\\HttpKernel\\HttpCache\\HttpCache' => $vendorDir . '/symfony/http-kernel/HttpCache/HttpCache.php',
    '_ContaoManager\\Symfony\\Component\\HttpKernel\\HttpCache\\ResponseCacheStrategy' => $vendorDir . '/symfony/http-kernel/HttpCache/ResponseCacheStrategy.php',
    '_ContaoManager\\Symfony\\Component\\HttpKernel\\HttpCache\\ResponseCacheStrategyInterface' => $vendorDir . '/symfony/http-kernel/HttpCache/ResponseCacheStrategyInterface.php',
    '_ContaoManager\\Symfony\\Component\\HttpKernel\\HttpCache\\Ssi' => $vendorDir . '/symfony/http-kernel/HttpCache/Ssi.php',
    '_ContaoManager\\Symfony\\Component\\HttpKernel\\HttpCache\\Store' => $vendorDir . '/symfony/http-kernel/HttpCache/Store.php',
    '_ContaoManager\\Symfony\\Component\\HttpKernel\\HttpCache\\StoreInterface' => $vendorDir . '/symfony/http-kernel/HttpCache/StoreInterface.php',
    '_ContaoManager\\Symfony\\Component\\HttpKernel\\HttpCache\\SubRequestHandler' => $vendorDir . '/symfony/http-kernel/HttpCache/SubRequestHandler.php',
    '_ContaoManager\\Symfony\\Component\\HttpKernel\\HttpCache\\SurrogateInterface' => $vendorDir . '/symfony/http-kernel/HttpCache/SurrogateInterface.php',
    '_ContaoManager\\Symfony\\Component\\HttpKernel\\HttpClientKernel' => $vendorDir . '/symfony/http-kernel/HttpClientKernel.php',
    '_ContaoManager\\Symfony\\Component\\HttpKernel\\HttpKernel' => $vendorDir . '/symfony/http-kernel/HttpKernel.php',
    '_ContaoManager\\Symfony\\Component\\HttpKernel\\HttpKernelBrowser' => $vendorDir . '/symfony/http-kernel/HttpKernelBrowser.php',
    '_ContaoManager\\Symfony\\Component\\HttpKernel\\HttpKernelInterface' => $vendorDir . '/symfony/http-kernel/HttpKernelInterface.php',
    '_ContaoManager\\Symfony\\Component\\HttpKernel\\Kernel' => $vendorDir . '/symfony/http-kernel/Kernel.php',
    '_ContaoManager\\Symfony\\Component\\HttpKernel\\KernelEvents' => $vendorDir . '/symfony/http-kernel/KernelEvents.php',
    '_ContaoManager\\Symfony\\Component\\HttpKernel\\KernelInterface' => $vendorDir . '/symfony/http-kernel/KernelInterface.php',
    '_ContaoManager\\Symfony\\Component\\HttpKernel\\Log\\DebugLoggerConfigurator' => $vendorDir . '/symfony/http-kernel/Log/DebugLoggerConfigurator.php',
    '_ContaoManager\\Symfony\\Component\\HttpKernel\\Log\\DebugLoggerInterface' => $vendorDir . '/symfony/http-kernel/Log/DebugLoggerInterface.php',
    '_ContaoManager\\Symfony\\Component\\HttpKernel\\Log\\Logger' => $vendorDir . '/symfony/http-kernel/Log/Logger.php',
    '_ContaoManager\\Symfony\\Component\\HttpKernel\\Profiler\\FileProfilerStorage' => $vendorDir . '/symfony/http-kernel/Profiler/FileProfilerStorage.php',
    '_ContaoManager\\Symfony\\Component\\HttpKernel\\Profiler\\Profile' => $vendorDir . '/symfony/http-kernel/Profiler/Profile.php',
    '_ContaoManager\\Symfony\\Component\\HttpKernel\\Profiler\\Profiler' => $vendorDir . '/symfony/http-kernel/Profiler/Profiler.php',
    '_ContaoManager\\Symfony\\Component\\HttpKernel\\Profiler\\ProfilerStorageInterface' => $vendorDir . '/symfony/http-kernel/Profiler/ProfilerStorageInterface.php',
    '_ContaoManager\\Symfony\\Component\\HttpKernel\\RebootableInterface' => $vendorDir . '/symfony/http-kernel/RebootableInterface.php',
    '_ContaoManager\\Symfony\\Component\\HttpKernel\\TerminableInterface' => $vendorDir . '/symfony/http-kernel/TerminableInterface.php',
    '_ContaoManager\\Symfony\\Component\\HttpKernel\\UriSigner' => $vendorDir . '/symfony/http-kernel/UriSigner.php',
    '_ContaoManager\\Symfony\\Component\\PasswordHasher\\Command\\UserPasswordHashCommand' => $vendorDir . '/symfony/password-hasher/Command/UserPasswordHashCommand.php',
    '_ContaoManager\\Symfony\\Component\\PasswordHasher\\Exception\\ExceptionInterface' => $vendorDir . '/symfony/password-hasher/Exception/ExceptionInterface.php',
    '_ContaoManager\\Symfony\\Component\\PasswordHasher\\Exception\\InvalidPasswordException' => $vendorDir . '/symfony/password-hasher/Exception/InvalidPasswordException.php',
    '_ContaoManager\\Symfony\\Component\\PasswordHasher\\Exception\\LogicException' => $vendorDir . '/symfony/password-hasher/Exception/LogicException.php',
    '_ContaoManager\\Symfony\\Component\\PasswordHasher\\Hasher\\CheckPasswordLengthTrait' => $vendorDir . '/symfony/password-hasher/Hasher/CheckPasswordLengthTrait.php',
    '_ContaoManager\\Symfony\\Component\\PasswordHasher\\Hasher\\MessageDigestPasswordHasher' => $vendorDir . '/symfony/password-hasher/Hasher/MessageDigestPasswordHasher.php',
    '_ContaoManager\\Symfony\\Component\\PasswordHasher\\Hasher\\MigratingPasswordHasher' => $vendorDir . '/symfony/password-hasher/Hasher/MigratingPasswordHasher.php',
    '_ContaoManager\\Symfony\\Component\\PasswordHasher\\Hasher\\NativePasswordHasher' => $vendorDir . '/symfony/password-hasher/Hasher/NativePasswordHasher.php',
    '_ContaoManager\\Symfony\\Component\\PasswordHasher\\Hasher\\PasswordHasherAwareInterface' => $vendorDir . '/symfony/password-hasher/Hasher/PasswordHasherAwareInterface.php',
    '_ContaoManager\\Symfony\\Component\\PasswordHasher\\Hasher\\PasswordHasherFactory' => $vendorDir . '/symfony/password-hasher/Hasher/PasswordHasherFactory.php',
    '_ContaoManager\\Symfony\\Component\\PasswordHasher\\Hasher\\PasswordHasherFactoryInterface' => $vendorDir . '/symfony/password-hasher/Hasher/PasswordHasherFactoryInterface.php',
    '_ContaoManager\\Symfony\\Component\\PasswordHasher\\Hasher\\Pbkdf2PasswordHasher' => $vendorDir . '/symfony/password-hasher/Hasher/Pbkdf2PasswordHasher.php',
    '_ContaoManager\\Symfony\\Component\\PasswordHasher\\Hasher\\PlaintextPasswordHasher' => $vendorDir . '/symfony/password-hasher/Hasher/PlaintextPasswordHasher.php',
    '_ContaoManager\\Symfony\\Component\\PasswordHasher\\Hasher\\SodiumPasswordHasher' => $vendorDir . '/symfony/password-hasher/Hasher/SodiumPasswordHasher.php',
    '_ContaoManager\\Symfony\\Component\\PasswordHasher\\Hasher\\UserPasswordHasher' => $vendorDir . '/symfony/password-hasher/Hasher/UserPasswordHasher.php',
    '_ContaoManager\\Symfony\\Component\\PasswordHasher\\Hasher\\UserPasswordHasherInterface' => $vendorDir . '/symfony/password-hasher/Hasher/UserPasswordHasherInterface.php',
    '_ContaoManager\\Symfony\\Component\\PasswordHasher\\LegacyPasswordHasherInterface' => $vendorDir . '/symfony/password-hasher/LegacyPasswordHasherInterface.php',
    '_ContaoManager\\Symfony\\Component\\PasswordHasher\\PasswordHasherInterface' => $vendorDir . '/symfony/password-hasher/PasswordHasherInterface.php',
    '_ContaoManager\\Symfony\\Component\\Process\\Exception\\ExceptionInterface' => $vendorDir . '/symfony/process/Exception/ExceptionInterface.php',
    '_ContaoManager\\Symfony\\Component\\Process\\Exception\\InvalidArgumentException' => $vendorDir . '/symfony/process/Exception/InvalidArgumentException.php',
    '_ContaoManager\\Symfony\\Component\\Process\\Exception\\LogicException' => $vendorDir . '/symfony/process/Exception/LogicException.php',
    '_ContaoManager\\Symfony\\Component\\Process\\Exception\\ProcessFailedException' => $vendorDir . '/symfony/process/Exception/ProcessFailedException.php',
    '_ContaoManager\\Symfony\\Component\\Process\\Exception\\ProcessSignaledException' => $vendorDir . '/symfony/process/Exception/ProcessSignaledException.php',
    '_ContaoManager\\Symfony\\Component\\Process\\Exception\\ProcessTimedOutException' => $vendorDir . '/symfony/process/Exception/ProcessTimedOutException.php',
    '_ContaoManager\\Symfony\\Component\\Process\\Exception\\RunProcessFailedException' => $vendorDir . '/symfony/process/Exception/RunProcessFailedException.php',
    '_ContaoManager\\Symfony\\Component\\Process\\Exception\\RuntimeException' => $vendorDir . '/symfony/process/Exception/RuntimeException.php',
    '_ContaoManager\\Symfony\\Component\\Process\\ExecutableFinder' => $vendorDir . '/symfony/process/ExecutableFinder.php',
    '_ContaoManager\\Symfony\\Component\\Process\\InputStream' => $vendorDir . '/symfony/process/InputStream.php',
    '_ContaoManager\\Symfony\\Component\\Process\\Messenger\\RunProcessContext' => $vendorDir . '/symfony/process/Messenger/RunProcessContext.php',
    '_ContaoManager\\Symfony\\Component\\Process\\Messenger\\RunProcessMessage' => $vendorDir . '/symfony/process/Messenger/RunProcessMessage.php',
    '_ContaoManager\\Symfony\\Component\\Process\\Messenger\\RunProcessMessageHandler' => $vendorDir . '/symfony/process/Messenger/RunProcessMessageHandler.php',
    '_ContaoManager\\Symfony\\Component\\Process\\PhpExecutableFinder' => $vendorDir . '/symfony/process/PhpExecutableFinder.php',
    '_ContaoManager\\Symfony\\Component\\Process\\PhpProcess' => $vendorDir . '/symfony/process/PhpProcess.php',
    '_ContaoManager\\Symfony\\Component\\Process\\PhpSubprocess' => $vendorDir . '/symfony/process/PhpSubprocess.php',
    '_ContaoManager\\Symfony\\Component\\Process\\Pipes\\AbstractPipes' => $vendorDir . '/symfony/process/Pipes/AbstractPipes.php',
    '_ContaoManager\\Symfony\\Component\\Process\\Pipes\\PipesInterface' => $vendorDir . '/symfony/process/Pipes/PipesInterface.php',
    '_ContaoManager\\Symfony\\Component\\Process\\Pipes\\UnixPipes' => $vendorDir . '/symfony/process/Pipes/UnixPipes.php',
    '_ContaoManager\\Symfony\\Component\\Process\\Pipes\\WindowsPipes' => $vendorDir . '/symfony/process/Pipes/WindowsPipes.php',
    '_ContaoManager\\Symfony\\Component\\Process\\Process' => $vendorDir . '/symfony/process/Process.php',
    '_ContaoManager\\Symfony\\Component\\Process\\ProcessUtils' => $vendorDir . '/symfony/process/ProcessUtils.php',
    '_ContaoManager\\Symfony\\Component\\PropertyAccess\\Exception\\AccessException' => $vendorDir . '/symfony/property-access/Exception/AccessException.php',
    '_ContaoManager\\Symfony\\Component\\PropertyAccess\\Exception\\ExceptionInterface' => $vendorDir . '/symfony/property-access/Exception/ExceptionInterface.php',
    '_ContaoManager\\Symfony\\Component\\PropertyAccess\\Exception\\InvalidArgumentException' => $vendorDir . '/symfony/property-access/Exception/InvalidArgumentException.php',
    '_ContaoManager\\Symfony\\Component\\PropertyAccess\\Exception\\InvalidPropertyPathException' => $vendorDir . '/symfony/property-access/Exception/InvalidPropertyPathException.php',
    '_ContaoManager\\Symfony\\Component\\PropertyAccess\\Exception\\NoSuchIndexException' => $vendorDir . '/symfony/property-access/Exception/NoSuchIndexException.php',
    '_ContaoManager\\Symfony\\Component\\PropertyAccess\\Exception\\NoSuchPropertyException' => $vendorDir . '/symfony/property-access/Exception/NoSuchPropertyException.php',
    '_ContaoManager\\Symfony\\Component\\PropertyAccess\\Exception\\OutOfBoundsException' => $vendorDir . '/symfony/property-access/Exception/OutOfBoundsException.php',
    '_ContaoManager\\Symfony\\Component\\PropertyAccess\\Exception\\RuntimeException' => $vendorDir . '/symfony/property-access/Exception/RuntimeException.php',
    '_ContaoManager\\Symfony\\Component\\PropertyAccess\\Exception\\UnexpectedTypeException' => $vendorDir . '/symfony/property-access/Exception/UnexpectedTypeException.php',
    '_ContaoManager\\Symfony\\Component\\PropertyAccess\\Exception\\UninitializedPropertyException' => $vendorDir . '/symfony/property-access/Exception/UninitializedPropertyException.php',
    '_ContaoManager\\Symfony\\Component\\PropertyAccess\\PropertyAccess' => $vendorDir . '/symfony/property-access/PropertyAccess.php',
    '_ContaoManager\\Symfony\\Component\\PropertyAccess\\PropertyAccessor' => $vendorDir . '/symfony/property-access/PropertyAccessor.php',
    '_ContaoManager\\Symfony\\Component\\PropertyAccess\\PropertyAccessorBuilder' => $vendorDir . '/symfony/property-access/PropertyAccessorBuilder.php',
    '_ContaoManager\\Symfony\\Component\\PropertyAccess\\PropertyAccessorInterface' => $vendorDir . '/symfony/property-access/PropertyAccessorInterface.php',
    '_ContaoManager\\Symfony\\Component\\PropertyAccess\\PropertyPath' => $vendorDir . '/symfony/property-access/PropertyPath.php',
    '_ContaoManager\\Symfony\\Component\\PropertyAccess\\PropertyPathBuilder' => $vendorDir . '/symfony/property-access/PropertyPathBuilder.php',
    '_ContaoManager\\Symfony\\Component\\PropertyAccess\\PropertyPathInterface' => $vendorDir . '/symfony/property-access/PropertyPathInterface.php',
    '_ContaoManager\\Symfony\\Component\\PropertyAccess\\PropertyPathIterator' => $vendorDir . '/symfony/property-access/PropertyPathIterator.php',
    '_ContaoManager\\Symfony\\Component\\PropertyAccess\\PropertyPathIteratorInterface' => $vendorDir . '/symfony/property-access/PropertyPathIteratorInterface.php',
    '_ContaoManager\\Symfony\\Component\\PropertyInfo\\DependencyInjection\\PropertyInfoConstructorPass' => $vendorDir . '/symfony/property-info/DependencyInjection/PropertyInfoConstructorPass.php',
    '_ContaoManager\\Symfony\\Component\\PropertyInfo\\DependencyInjection\\PropertyInfoPass' => $vendorDir . '/symfony/property-info/DependencyInjection/PropertyInfoPass.php',
    '_ContaoManager\\Symfony\\Component\\PropertyInfo\\Extractor\\ConstructorArgumentTypeExtractorInterface' => $vendorDir . '/symfony/property-info/Extractor/ConstructorArgumentTypeExtractorInterface.php',
    '_ContaoManager\\Symfony\\Component\\PropertyInfo\\Extractor\\ConstructorExtractor' => $vendorDir . '/symfony/property-info/Extractor/ConstructorExtractor.php',
    '_ContaoManager\\Symfony\\Component\\PropertyInfo\\Extractor\\PhpDocExtractor' => $vendorDir . '/symfony/property-info/Extractor/PhpDocExtractor.php',
    '_ContaoManager\\Symfony\\Component\\PropertyInfo\\Extractor\\PhpStanExtractor' => $vendorDir . '/symfony/property-info/Extractor/PhpStanExtractor.php',
    '_ContaoManager\\Symfony\\Component\\PropertyInfo\\Extractor\\ReflectionExtractor' => $vendorDir . '/symfony/property-info/Extractor/ReflectionExtractor.php',
    '_ContaoManager\\Symfony\\Component\\PropertyInfo\\Extractor\\SerializerExtractor' => $vendorDir . '/symfony/property-info/Extractor/SerializerExtractor.php',
    '_ContaoManager\\Symfony\\Component\\PropertyInfo\\PhpStan\\NameScope' => $vendorDir . '/symfony/property-info/PhpStan/NameScope.php',
    '_ContaoManager\\Symfony\\Component\\PropertyInfo\\PhpStan\\NameScopeFactory' => $vendorDir . '/symfony/property-info/PhpStan/NameScopeFactory.php',
    '_ContaoManager\\Symfony\\Component\\PropertyInfo\\PropertyAccessExtractorInterface' => $vendorDir . '/symfony/property-info/PropertyAccessExtractorInterface.php',
    '_ContaoManager\\Symfony\\Component\\PropertyInfo\\PropertyDescriptionExtractorInterface' => $vendorDir . '/symfony/property-info/PropertyDescriptionExtractorInterface.php',
    '_ContaoManager\\Symfony\\Component\\PropertyInfo\\PropertyInfoCacheExtractor' => $vendorDir . '/symfony/property-info/PropertyInfoCacheExtractor.php',
    '_ContaoManager\\Symfony\\Component\\PropertyInfo\\PropertyInfoExtractor' => $vendorDir . '/symfony/property-info/PropertyInfoExtractor.php',
    '_ContaoManager\\Symfony\\Component\\PropertyInfo\\PropertyInfoExtractorInterface' => $vendorDir . '/symfony/property-info/PropertyInfoExtractorInterface.php',
    '_ContaoManager\\Symfony\\Component\\PropertyInfo\\PropertyInitializableExtractorInterface' => $vendorDir . '/symfony/property-info/PropertyInitializableExtractorInterface.php',
    '_ContaoManager\\Symfony\\Component\\PropertyInfo\\PropertyListExtractorInterface' => $vendorDir . '/symfony/property-info/PropertyListExtractorInterface.php',
    '_ContaoManager\\Symfony\\Component\\PropertyInfo\\PropertyReadInfo' => $vendorDir . '/symfony/property-info/PropertyReadInfo.php',
    '_ContaoManager\\Symfony\\Component\\PropertyInfo\\PropertyReadInfoExtractorInterface' => $vendorDir . '/symfony/property-info/PropertyReadInfoExtractorInterface.php',
    '_ContaoManager\\Symfony\\Component\\PropertyInfo\\PropertyTypeExtractorInterface' => $vendorDir . '/symfony/property-info/PropertyTypeExtractorInterface.php',
    '_ContaoManager\\Symfony\\Component\\PropertyInfo\\PropertyWriteInfo' => $vendorDir . '/symfony/property-info/PropertyWriteInfo.php',
    '_ContaoManager\\Symfony\\Component\\PropertyInfo\\PropertyWriteInfoExtractorInterface' => $vendorDir . '/symfony/property-info/PropertyWriteInfoExtractorInterface.php',
    '_ContaoManager\\Symfony\\Component\\PropertyInfo\\Type' => $vendorDir . '/symfony/property-info/Type.php',
    '_ContaoManager\\Symfony\\Component\\PropertyInfo\\Util\\PhpDocTypeHelper' => $vendorDir . '/symfony/property-info/Util/PhpDocTypeHelper.php',
    '_ContaoManager\\Symfony\\Component\\PropertyInfo\\Util\\PhpStanTypeHelper' => $vendorDir . '/symfony/property-info/Util/PhpStanTypeHelper.php',
    '_ContaoManager\\Symfony\\Component\\Routing\\Alias' => $vendorDir . '/symfony/routing/Alias.php',
    '_ContaoManager\\Symfony\\Component\\Routing\\Annotation\\Route' => $vendorDir . '/symfony/routing/Annotation/Route.php',
    '_ContaoManager\\Symfony\\Component\\Routing\\Attribute\\Route' => $vendorDir . '/symfony/routing/Attribute/Route.php',
    '_ContaoManager\\Symfony\\Component\\Routing\\CompiledRoute' => $vendorDir . '/symfony/routing/CompiledRoute.php',
    '_ContaoManager\\Symfony\\Component\\Routing\\DependencyInjection\\AddExpressionLanguageProvidersPass' => $vendorDir . '/symfony/routing/DependencyInjection/AddExpressionLanguageProvidersPass.php',
    '_ContaoManager\\Symfony\\Component\\Routing\\DependencyInjection\\RoutingResolverPass' => $vendorDir . '/symfony/routing/DependencyInjection/RoutingResolverPass.php',
    '_ContaoManager\\Symfony\\Component\\Routing\\Exception\\ExceptionInterface' => $vendorDir . '/symfony/routing/Exception/ExceptionInterface.php',
    '_ContaoManager\\Symfony\\Component\\Routing\\Exception\\InvalidArgumentException' => $vendorDir . '/symfony/routing/Exception/InvalidArgumentException.php',
    '_ContaoManager\\Symfony\\Component\\Routing\\Exception\\InvalidParameterException' => $vendorDir . '/symfony/routing/Exception/InvalidParameterException.php',
    '_ContaoManager\\Symfony\\Component\\Routing\\Exception\\MethodNotAllowedException' => $vendorDir . '/symfony/routing/Exception/MethodNotAllowedException.php',
    '_ContaoManager\\Symfony\\Component\\Routing\\Exception\\MissingMandatoryParametersException' => $vendorDir . '/symfony/routing/Exception/MissingMandatoryParametersException.php',
    '_ContaoManager\\Symfony\\Component\\Routing\\Exception\\NoConfigurationException' => $vendorDir . '/symfony/routing/Exception/NoConfigurationException.php',
    '_ContaoManager\\Symfony\\Component\\Routing\\Exception\\ResourceNotFoundException' => $vendorDir . '/symfony/routing/Exception/ResourceNotFoundException.php',
    '_ContaoManager\\Symfony\\Component\\Routing\\Exception\\RouteCircularReferenceException' => $vendorDir . '/symfony/routing/Exception/RouteCircularReferenceException.php',
    '_ContaoManager\\Symfony\\Component\\Routing\\Exception\\RouteNotFoundException' => $vendorDir . '/symfony/routing/Exception/RouteNotFoundException.php',
    '_ContaoManager\\Symfony\\Component\\Routing\\Exception\\RuntimeException' => $vendorDir . '/symfony/routing/Exception/RuntimeException.php',
    '_ContaoManager\\Symfony\\Component\\Routing\\Generator\\CompiledUrlGenerator' => $vendorDir . '/symfony/routing/Generator/CompiledUrlGenerator.php',
    '_ContaoManager\\Symfony\\Component\\Routing\\Generator\\ConfigurableRequirementsInterface' => $vendorDir . '/symfony/routing/Generator/ConfigurableRequirementsInterface.php',
    '_ContaoManager\\Symfony\\Component\\Routing\\Generator\\Dumper\\CompiledUrlGeneratorDumper' => $vendorDir . '/symfony/routing/Generator/Dumper/CompiledUrlGeneratorDumper.php',
    '_ContaoManager\\Symfony\\Component\\Routing\\Generator\\Dumper\\GeneratorDumper' => $vendorDir . '/symfony/routing/Generator/Dumper/GeneratorDumper.php',
    '_ContaoManager\\Symfony\\Component\\Routing\\Generator\\Dumper\\GeneratorDumperInterface' => $vendorDir . '/symfony/routing/Generator/Dumper/GeneratorDumperInterface.php',
    '_ContaoManager\\Symfony\\Component\\Routing\\Generator\\UrlGenerator' => $vendorDir . '/symfony/routing/Generator/UrlGenerator.php',
    '_ContaoManager\\Symfony\\Component\\Routing\\Generator\\UrlGeneratorInterface' => $vendorDir . '/symfony/routing/Generator/UrlGeneratorInterface.php',
    '_ContaoManager\\Symfony\\Component\\Routing\\Loader\\AnnotationClassLoader' => $vendorDir . '/symfony/routing/Loader/AnnotationClassLoader.php',
    '_ContaoManager\\Symfony\\Component\\Routing\\Loader\\AnnotationDirectoryLoader' => $vendorDir . '/symfony/routing/Loader/AnnotationDirectoryLoader.php',
    '_ContaoManager\\Symfony\\Component\\Routing\\Loader\\AnnotationFileLoader' => $vendorDir . '/symfony/routing/Loader/AnnotationFileLoader.php',
    '_ContaoManager\\Symfony\\Component\\Routing\\Loader\\AttributeClassLoader' => $vendorDir . '/symfony/routing/Loader/AttributeClassLoader.php',
    '_ContaoManager\\Symfony\\Component\\Routing\\Loader\\AttributeDirectoryLoader' => $vendorDir . '/symfony/routing/Loader/AttributeDirectoryLoader.php',
    '_ContaoManager\\Symfony\\Component\\Routing\\Loader\\AttributeFileLoader' => $vendorDir . '/symfony/routing/Loader/AttributeFileLoader.php',
    '_ContaoManager\\Symfony\\Component\\Routing\\Loader\\ClosureLoader' => $vendorDir . '/symfony/routing/Loader/ClosureLoader.php',
    '_ContaoManager\\Symfony\\Component\\Routing\\Loader\\Configurator\\AliasConfigurator' => $vendorDir . '/symfony/routing/Loader/Configurator/AliasConfigurator.php',
    '_ContaoManager\\Symfony\\Component\\Routing\\Loader\\Configurator\\CollectionConfigurator' => $vendorDir . '/symfony/routing/Loader/Configurator/CollectionConfigurator.php',
    '_ContaoManager\\Symfony\\Component\\Routing\\Loader\\Configurator\\ImportConfigurator' => $vendorDir . '/symfony/routing/Loader/Configurator/ImportConfigurator.php',
    '_ContaoManager\\Symfony\\Component\\Routing\\Loader\\Configurator\\RouteConfigurator' => $vendorDir . '/symfony/routing/Loader/Configurator/RouteConfigurator.php',
    '_ContaoManager\\Symfony\\Component\\Routing\\Loader\\Configurator\\RoutingConfigurator' => $vendorDir . '/symfony/routing/Loader/Configurator/RoutingConfigurator.php',
    '_ContaoManager\\Symfony\\Component\\Routing\\Loader\\Configurator\\Traits\\AddTrait' => $vendorDir . '/symfony/routing/Loader/Configurator/Traits/AddTrait.php',
    '_ContaoManager\\Symfony\\Component\\Routing\\Loader\\Configurator\\Traits\\HostTrait' => $vendorDir . '/symfony/routing/Loader/Configurator/Traits/HostTrait.php',
    '_ContaoManager\\Symfony\\Component\\Routing\\Loader\\Configurator\\Traits\\LocalizedRouteTrait' => $vendorDir . '/symfony/routing/Loader/Configurator/Traits/LocalizedRouteTrait.php',
    '_ContaoManager\\Symfony\\Component\\Routing\\Loader\\Configurator\\Traits\\PrefixTrait' => $vendorDir . '/symfony/routing/Loader/Configurator/Traits/PrefixTrait.php',
    '_ContaoManager\\Symfony\\Component\\Routing\\Loader\\Configurator\\Traits\\RouteTrait' => $vendorDir . '/symfony/routing/Loader/Configurator/Traits/RouteTrait.php',
    '_ContaoManager\\Symfony\\Component\\Routing\\Loader\\ContainerLoader' => $vendorDir . '/symfony/routing/Loader/ContainerLoader.php',
    '_ContaoManager\\Symfony\\Component\\Routing\\Loader\\DirectoryLoader' => $vendorDir . '/symfony/routing/Loader/DirectoryLoader.php',
    '_ContaoManager\\Symfony\\Component\\Routing\\Loader\\GlobFileLoader' => $vendorDir . '/symfony/routing/Loader/GlobFileLoader.php',
    '_ContaoManager\\Symfony\\Component\\Routing\\Loader\\ObjectLoader' => $vendorDir . '/symfony/routing/Loader/ObjectLoader.php',
    '_ContaoManager\\Symfony\\Component\\Routing\\Loader\\PhpFileLoader' => $vendorDir . '/symfony/routing/Loader/PhpFileLoader.php',
    '_ContaoManager\\Symfony\\Component\\Routing\\Loader\\Psr4DirectoryLoader' => $vendorDir . '/symfony/routing/Loader/Psr4DirectoryLoader.php',
    '_ContaoManager\\Symfony\\Component\\Routing\\Loader\\XmlFileLoader' => $vendorDir . '/symfony/routing/Loader/XmlFileLoader.php',
    '_ContaoManager\\Symfony\\Component\\Routing\\Loader\\YamlFileLoader' => $vendorDir . '/symfony/routing/Loader/YamlFileLoader.php',
    '_ContaoManager\\Symfony\\Component\\Routing\\Matcher\\CompiledUrlMatcher' => $vendorDir . '/symfony/routing/Matcher/CompiledUrlMatcher.php',
    '_ContaoManager\\Symfony\\Component\\Routing\\Matcher\\Dumper\\CompiledUrlMatcherDumper' => $vendorDir . '/symfony/routing/Matcher/Dumper/CompiledUrlMatcherDumper.php',
    '_ContaoManager\\Symfony\\Component\\Routing\\Matcher\\Dumper\\CompiledUrlMatcherTrait' => $vendorDir . '/symfony/routing/Matcher/Dumper/CompiledUrlMatcherTrait.php',
    '_ContaoManager\\Symfony\\Component\\Routing\\Matcher\\Dumper\\MatcherDumper' => $vendorDir . '/symfony/routing/Matcher/Dumper/MatcherDumper.php',
    '_ContaoManager\\Symfony\\Component\\Routing\\Matcher\\Dumper\\MatcherDumperInterface' => $vendorDir . '/symfony/routing/Matcher/Dumper/MatcherDumperInterface.php',
    '_ContaoManager\\Symfony\\Component\\Routing\\Matcher\\Dumper\\StaticPrefixCollection' => $vendorDir . '/symfony/routing/Matcher/Dumper/StaticPrefixCollection.php',
    '_ContaoManager\\Symfony\\Component\\Routing\\Matcher\\ExpressionLanguageProvider' => $vendorDir . '/symfony/routing/Matcher/ExpressionLanguageProvider.php',
    '_ContaoManager\\Symfony\\Component\\Routing\\Matcher\\RedirectableUrlMatcher' => $vendorDir . '/symfony/routing/Matcher/RedirectableUrlMatcher.php',
    '_ContaoManager\\Symfony\\Component\\Routing\\Matcher\\RedirectableUrlMatcherInterface' => $vendorDir . '/symfony/routing/Matcher/RedirectableUrlMatcherInterface.php',
    '_ContaoManager\\Symfony\\Component\\Routing\\Matcher\\RequestMatcherInterface' => $vendorDir . '/symfony/routing/Matcher/RequestMatcherInterface.php',
    '_ContaoManager\\Symfony\\Component\\Routing\\Matcher\\TraceableUrlMatcher' => $vendorDir . '/symfony/routing/Matcher/TraceableUrlMatcher.php',
    '_ContaoManager\\Symfony\\Component\\Routing\\Matcher\\UrlMatcher' => $vendorDir . '/symfony/routing/Matcher/UrlMatcher.php',
    '_ContaoManager\\Symfony\\Component\\Routing\\Matcher\\UrlMatcherInterface' => $vendorDir . '/symfony/routing/Matcher/UrlMatcherInterface.php',
    '_ContaoManager\\Symfony\\Component\\Routing\\RequestContext' => $vendorDir . '/symfony/routing/RequestContext.php',
    '_ContaoManager\\Symfony\\Component\\Routing\\RequestContextAwareInterface' => $vendorDir . '/symfony/routing/RequestContextAwareInterface.php',
    '_ContaoManager\\Symfony\\Component\\Routing\\Requirement\\EnumRequirement' => $vendorDir . '/symfony/routing/Requirement/EnumRequirement.php',
    '_ContaoManager\\Symfony\\Component\\Routing\\Requirement\\Requirement' => $vendorDir . '/symfony/routing/Requirement/Requirement.php',
    '_ContaoManager\\Symfony\\Component\\Routing\\Route' => $vendorDir . '/symfony/routing/Route.php',
    '_ContaoManager\\Symfony\\Component\\Routing\\RouteCollection' => $vendorDir . '/symfony/routing/RouteCollection.php',
    '_ContaoManager\\Symfony\\Component\\Routing\\RouteCompiler' => $vendorDir . '/symfony/routing/RouteCompiler.php',
    '_ContaoManager\\Symfony\\Component\\Routing\\RouteCompilerInterface' => $vendorDir . '/symfony/routing/RouteCompilerInterface.php',
    '_ContaoManager\\Symfony\\Component\\Routing\\Router' => $vendorDir . '/symfony/routing/Router.php',
    '_ContaoManager\\Symfony\\Component\\Routing\\RouterInterface' => $vendorDir . '/symfony/routing/RouterInterface.php',
    '_ContaoManager\\Symfony\\Component\\Security\\Core\\AuthenticationEvents' => $vendorDir . '/symfony/security-core/AuthenticationEvents.php',
    '_ContaoManager\\Symfony\\Component\\Security\\Core\\Authentication\\AuthenticationTrustResolver' => $vendorDir . '/symfony/security-core/Authentication/AuthenticationTrustResolver.php',
    '_ContaoManager\\Symfony\\Component\\Security\\Core\\Authentication\\AuthenticationTrustResolverInterface' => $vendorDir . '/symfony/security-core/Authentication/AuthenticationTrustResolverInterface.php',
    '_ContaoManager\\Symfony\\Component\\Security\\Core\\Authentication\\RememberMe\\CacheTokenVerifier' => $vendorDir . '/symfony/security-core/Authentication/RememberMe/CacheTokenVerifier.php',
    '_ContaoManager\\Symfony\\Component\\Security\\Core\\Authentication\\RememberMe\\InMemoryTokenProvider' => $vendorDir . '/symfony/security-core/Authentication/RememberMe/InMemoryTokenProvider.php',
    '_ContaoManager\\Symfony\\Component\\Security\\Core\\Authentication\\RememberMe\\PersistentToken' => $vendorDir . '/symfony/security-core/Authentication/RememberMe/PersistentToken.php',
    '_ContaoManager\\Symfony\\Component\\Security\\Core\\Authentication\\RememberMe\\PersistentTokenInterface' => $vendorDir . '/symfony/security-core/Authentication/RememberMe/PersistentTokenInterface.php',
    '_ContaoManager\\Symfony\\Component\\Security\\Core\\Authentication\\RememberMe\\TokenProviderInterface' => $vendorDir . '/symfony/security-core/Authentication/RememberMe/TokenProviderInterface.php',
    '_ContaoManager\\Symfony\\Component\\Security\\Core\\Authentication\\RememberMe\\TokenVerifierInterface' => $vendorDir . '/symfony/security-core/Authentication/RememberMe/TokenVerifierInterface.php',
    '_ContaoManager\\Symfony\\Component\\Security\\Core\\Authentication\\Token\\AbstractToken' => $vendorDir . '/symfony/security-core/Authentication/Token/AbstractToken.php',
    '_ContaoManager\\Symfony\\Component\\Security\\Core\\Authentication\\Token\\NullToken' => $vendorDir . '/symfony/security-core/Authentication/Token/NullToken.php',
    '_ContaoManager\\Symfony\\Component\\Security\\Core\\Authentication\\Token\\PreAuthenticatedToken' => $vendorDir . '/symfony/security-core/Authentication/Token/PreAuthenticatedToken.php',
    '_ContaoManager\\Symfony\\Component\\Security\\Core\\Authentication\\Token\\RememberMeToken' => $vendorDir . '/symfony/security-core/Authentication/Token/RememberMeToken.php',
    '_ContaoManager\\Symfony\\Component\\Security\\Core\\Authentication\\Token\\Storage\\TokenStorage' => $vendorDir . '/symfony/security-core/Authentication/Token/Storage/TokenStorage.php',
    '_ContaoManager\\Symfony\\Component\\Security\\Core\\Authentication\\Token\\Storage\\TokenStorageInterface' => $vendorDir . '/symfony/security-core/Authentication/Token/Storage/TokenStorageInterface.php',
    '_ContaoManager\\Symfony\\Component\\Security\\Core\\Authentication\\Token\\Storage\\UsageTrackingTokenStorage' => $vendorDir . '/symfony/security-core/Authentication/Token/Storage/UsageTrackingTokenStorage.php',
    '_ContaoManager\\Symfony\\Component\\Security\\Core\\Authentication\\Token\\SwitchUserToken' => $vendorDir . '/symfony/security-core/Authentication/Token/SwitchUserToken.php',
    '_ContaoManager\\Symfony\\Component\\Security\\Core\\Authentication\\Token\\TokenInterface' => $vendorDir . '/symfony/security-core/Authentication/Token/TokenInterface.php',
    '_ContaoManager\\Symfony\\Component\\Security\\Core\\Authentication\\Token\\UsernamePasswordToken' => $vendorDir . '/symfony/security-core/Authentication/Token/UsernamePasswordToken.php',
    '_ContaoManager\\Symfony\\Component\\Security\\Core\\Authorization\\AccessDecisionManager' => $vendorDir . '/symfony/security-core/Authorization/AccessDecisionManager.php',
    '_ContaoManager\\Symfony\\Component\\Security\\Core\\Authorization\\AccessDecisionManagerInterface' => $vendorDir . '/symfony/security-core/Authorization/AccessDecisionManagerInterface.php',
    '_ContaoManager\\Symfony\\Component\\Security\\Core\\Authorization\\AuthorizationChecker' => $vendorDir . '/symfony/security-core/Authorization/AuthorizationChecker.php',
    '_ContaoManager\\Symfony\\Component\\Security\\Core\\Authorization\\AuthorizationCheckerInterface' => $vendorDir . '/symfony/security-core/Authorization/AuthorizationCheckerInterface.php',
    '_ContaoManager\\Symfony\\Component\\Security\\Core\\Authorization\\ExpressionLanguage' => $vendorDir . '/symfony/security-core/Authorization/ExpressionLanguage.php',
    '_ContaoManager\\Symfony\\Component\\Security\\Core\\Authorization\\ExpressionLanguageProvider' => $vendorDir . '/symfony/security-core/Authorization/ExpressionLanguageProvider.php',
    '_ContaoManager\\Symfony\\Component\\Security\\Core\\Authorization\\Strategy\\AccessDecisionStrategyInterface' => $vendorDir . '/symfony/security-core/Authorization/Strategy/AccessDecisionStrategyInterface.php',
    '_ContaoManager\\Symfony\\Component\\Security\\Core\\Authorization\\Strategy\\AffirmativeStrategy' => $vendorDir . '/symfony/security-core/Authorization/Strategy/AffirmativeStrategy.php',
    '_ContaoManager\\Symfony\\Component\\Security\\Core\\Authorization\\Strategy\\ConsensusStrategy' => $vendorDir . '/symfony/security-core/Authorization/Strategy/ConsensusStrategy.php',
    '_ContaoManager\\Symfony\\Component\\Security\\Core\\Authorization\\Strategy\\PriorityStrategy' => $vendorDir . '/symfony/security-core/Authorization/Strategy/PriorityStrategy.php',
    '_ContaoManager\\Symfony\\Component\\Security\\Core\\Authorization\\Strategy\\UnanimousStrategy' => $vendorDir . '/symfony/security-core/Authorization/Strategy/UnanimousStrategy.php',
    '_ContaoManager\\Symfony\\Component\\Security\\Core\\Authorization\\TraceableAccessDecisionManager' => $vendorDir . '/symfony/security-core/Authorization/TraceableAccessDecisionManager.php',
    '_ContaoManager\\Symfony\\Component\\Security\\Core\\Authorization\\Voter\\AuthenticatedVoter' => $vendorDir . '/symfony/security-core/Authorization/Voter/AuthenticatedVoter.php',
    '_ContaoManager\\Symfony\\Component\\Security\\Core\\Authorization\\Voter\\CacheableVoterInterface' => $vendorDir . '/symfony/security-core/Authorization/Voter/CacheableVoterInterface.php',
    '_ContaoManager\\Symfony\\Component\\Security\\Core\\Authorization\\Voter\\ExpressionVoter' => $vendorDir . '/symfony/security-core/Authorization/Voter/ExpressionVoter.php',
    '_ContaoManager\\Symfony\\Component\\Security\\Core\\Authorization\\Voter\\RoleHierarchyVoter' => $vendorDir . '/symfony/security-core/Authorization/Voter/RoleHierarchyVoter.php',
    '_ContaoManager\\Symfony\\Component\\Security\\Core\\Authorization\\Voter\\RoleVoter' => $vendorDir . '/symfony/security-core/Authorization/Voter/RoleVoter.php',
    '_ContaoManager\\Symfony\\Component\\Security\\Core\\Authorization\\Voter\\TraceableVoter' => $vendorDir . '/symfony/security-core/Authorization/Voter/TraceableVoter.php',
    '_ContaoManager\\Symfony\\Component\\Security\\Core\\Authorization\\Voter\\Voter' => $vendorDir . '/symfony/security-core/Authorization/Voter/Voter.php',
    '_ContaoManager\\Symfony\\Component\\Security\\Core\\Authorization\\Voter\\VoterInterface' => $vendorDir . '/symfony/security-core/Authorization/Voter/VoterInterface.php',
    '_ContaoManager\\Symfony\\Component\\Security\\Core\\Event\\AuthenticationEvent' => $vendorDir . '/symfony/security-core/Event/AuthenticationEvent.php',
    '_ContaoManager\\Symfony\\Component\\Security\\Core\\Event\\AuthenticationSuccessEvent' => $vendorDir . '/symfony/security-core/Event/AuthenticationSuccessEvent.php',
    '_ContaoManager\\Symfony\\Component\\Security\\Core\\Event\\VoteEvent' => $vendorDir . '/symfony/security-core/Event/VoteEvent.php',
    '_ContaoManager\\Symfony\\Component\\Security\\Core\\Exception\\AccessDeniedException' => $vendorDir . '/symfony/security-core/Exception/AccessDeniedException.php',
    '_ContaoManager\\Symfony\\Component\\Security\\Core\\Exception\\AccountExpiredException' => $vendorDir . '/symfony/security-core/Exception/AccountExpiredException.php',
    '_ContaoManager\\Symfony\\Component\\Security\\Core\\Exception\\AccountStatusException' => $vendorDir . '/symfony/security-core/Exception/AccountStatusException.php',
    '_ContaoManager\\Symfony\\Component\\Security\\Core\\Exception\\AuthenticationCredentialsNotFoundException' => $vendorDir . '/symfony/security-core/Exception/AuthenticationCredentialsNotFoundException.php',
    '_ContaoManager\\Symfony\\Component\\Security\\Core\\Exception\\AuthenticationException' => $vendorDir . '/symfony/security-core/Exception/AuthenticationException.php',
    '_ContaoManager\\Symfony\\Component\\Security\\Core\\Exception\\AuthenticationExpiredException' => $vendorDir . '/symfony/security-core/Exception/AuthenticationExpiredException.php',
    '_ContaoManager\\Symfony\\Component\\Security\\Core\\Exception\\AuthenticationServiceException' => $vendorDir . '/symfony/security-core/Exception/AuthenticationServiceException.php',
    '_ContaoManager\\Symfony\\Component\\Security\\Core\\Exception\\BadCredentialsException' => $vendorDir . '/symfony/security-core/Exception/BadCredentialsException.php',
    '_ContaoManager\\Symfony\\Component\\Security\\Core\\Exception\\CookieTheftException' => $vendorDir . '/symfony/security-core/Exception/CookieTheftException.php',
    '_ContaoManager\\Symfony\\Component\\Security\\Core\\Exception\\CredentialsExpiredException' => $vendorDir . '/symfony/security-core/Exception/CredentialsExpiredException.php',
    '_ContaoManager\\Symfony\\Component\\Security\\Core\\Exception\\CustomUserMessageAccountStatusException' => $vendorDir . '/symfony/security-core/Exception/CustomUserMessageAccountStatusException.php',
    '_ContaoManager\\Symfony\\Component\\Security\\Core\\Exception\\CustomUserMessageAuthenticationException' => $vendorDir . '/symfony/security-core/Exception/CustomUserMessageAuthenticationException.php',
    '_ContaoManager\\Symfony\\Component\\Security\\Core\\Exception\\DisabledException' => $vendorDir . '/symfony/security-core/Exception/DisabledException.php',
    '_ContaoManager\\Symfony\\Component\\Security\\Core\\Exception\\ExceptionInterface' => $vendorDir . '/symfony/security-core/Exception/ExceptionInterface.php',
    '_ContaoManager\\Symfony\\Component\\Security\\Core\\Exception\\InsufficientAuthenticationException' => $vendorDir . '/symfony/security-core/Exception/InsufficientAuthenticationException.php',
    '_ContaoManager\\Symfony\\Component\\Security\\Core\\Exception\\InvalidArgumentException' => $vendorDir . '/symfony/security-core/Exception/InvalidArgumentException.php',
    '_ContaoManager\\Symfony\\Component\\Security\\Core\\Exception\\InvalidCsrfTokenException' => $vendorDir . '/symfony/security-core/Exception/InvalidCsrfTokenException.php',
    '_ContaoManager\\Symfony\\Component\\Security\\Core\\Exception\\LazyResponseException' => $vendorDir . '/symfony/security-core/Exception/LazyResponseException.php',
    '_ContaoManager\\Symfony\\Component\\Security\\Core\\Exception\\LockedException' => $vendorDir . '/symfony/security-core/Exception/LockedException.php',
    '_ContaoManager\\Symfony\\Component\\Security\\Core\\Exception\\LogicException' => $vendorDir . '/symfony/security-core/Exception/LogicException.php',
    '_ContaoManager\\Symfony\\Component\\Security\\Core\\Exception\\LogoutException' => $vendorDir . '/symfony/security-core/Exception/LogoutException.php',
    '_ContaoManager\\Symfony\\Component\\Security\\Core\\Exception\\ProviderNotFoundException' => $vendorDir . '/symfony/security-core/Exception/ProviderNotFoundException.php',
    '_ContaoManager\\Symfony\\Component\\Security\\Core\\Exception\\RuntimeException' => $vendorDir . '/symfony/security-core/Exception/RuntimeException.php',
    '_ContaoManager\\Symfony\\Component\\Security\\Core\\Exception\\SessionUnavailableException' => $vendorDir . '/symfony/security-core/Exception/SessionUnavailableException.php',
    '_ContaoManager\\Symfony\\Component\\Security\\Core\\Exception\\TokenNotFoundException' => $vendorDir . '/symfony/security-core/Exception/TokenNotFoundException.php',
    '_ContaoManager\\Symfony\\Component\\Security\\Core\\Exception\\TooManyLoginAttemptsAuthenticationException' => $vendorDir . '/symfony/security-core/Exception/TooManyLoginAttemptsAuthenticationException.php',
    '_ContaoManager\\Symfony\\Component\\Security\\Core\\Exception\\UnsupportedUserException' => $vendorDir . '/symfony/security-core/Exception/UnsupportedUserException.php',
    '_ContaoManager\\Symfony\\Component\\Security\\Core\\Exception\\UserNotFoundException' => $vendorDir . '/symfony/security-core/Exception/UserNotFoundException.php',
    '_ContaoManager\\Symfony\\Component\\Security\\Core\\Role\\Role' => $vendorDir . '/symfony/security-core/Role/Role.php',
    '_ContaoManager\\Symfony\\Component\\Security\\Core\\Role\\RoleHierarchy' => $vendorDir . '/symfony/security-core/Role/RoleHierarchy.php',
    '_ContaoManager\\Symfony\\Component\\Security\\Core\\Role\\RoleHierarchyInterface' => $vendorDir . '/symfony/security-core/Role/RoleHierarchyInterface.php',
    '_ContaoManager\\Symfony\\Component\\Security\\Core\\Role\\SwitchUserRole' => $vendorDir . '/symfony/security-core/Role/SwitchUserRole.php',
    '_ContaoManager\\Symfony\\Component\\Security\\Core\\Security' => $vendorDir . '/symfony/security-core/Security.php',
    '_ContaoManager\\Symfony\\Component\\Security\\Core\\Signature\\Exception\\ExpiredSignatureException' => $vendorDir . '/symfony/security-core/Signature/Exception/ExpiredSignatureException.php',
    '_ContaoManager\\Symfony\\Component\\Security\\Core\\Signature\\Exception\\InvalidSignatureException' => $vendorDir . '/symfony/security-core/Signature/Exception/InvalidSignatureException.php',
    '_ContaoManager\\Symfony\\Component\\Security\\Core\\Signature\\ExpiredSignatureStorage' => $vendorDir . '/symfony/security-core/Signature/ExpiredSignatureStorage.php',
    '_ContaoManager\\Symfony\\Component\\Security\\Core\\Signature\\SignatureHasher' => $vendorDir . '/symfony/security-core/Signature/SignatureHasher.php',
    '_ContaoManager\\Symfony\\Component\\Security\\Core\\Test\\AccessDecisionStrategyTestCase' => $vendorDir . '/symfony/security-core/Test/AccessDecisionStrategyTestCase.php',
    '_ContaoManager\\Symfony\\Component\\Security\\Core\\User\\AttributesBasedUserProviderInterface' => $vendorDir . '/symfony/security-core/User/AttributesBasedUserProviderInterface.php',
    '_ContaoManager\\Symfony\\Component\\Security\\Core\\User\\ChainUserChecker' => $vendorDir . '/symfony/security-core/User/ChainUserChecker.php',
    '_ContaoManager\\Symfony\\Component\\Security\\Core\\User\\ChainUserProvider' => $vendorDir . '/symfony/security-core/User/ChainUserProvider.php',
    '_ContaoManager\\Symfony\\Component\\Security\\Core\\User\\EquatableInterface' => $vendorDir . '/symfony/security-core/User/EquatableInterface.php',
    '_ContaoManager\\Symfony\\Component\\Security\\Core\\User\\InMemoryUser' => $vendorDir . '/symfony/security-core/User/InMemoryUser.php',
    '_ContaoManager\\Symfony\\Component\\Security\\Core\\User\\InMemoryUserChecker' => $vendorDir . '/symfony/security-core/User/InMemoryUserChecker.php',
    '_ContaoManager\\Symfony\\Component\\Security\\Core\\User\\InMemoryUserProvider' => $vendorDir . '/symfony/security-core/User/InMemoryUserProvider.php',
    '_ContaoManager\\Symfony\\Component\\Security\\Core\\User\\LegacyPasswordAuthenticatedUserInterface' => $vendorDir . '/symfony/security-core/User/LegacyPasswordAuthenticatedUserInterface.php',
    '_ContaoManager\\Symfony\\Component\\Security\\Core\\User\\MissingUserProvider' => $vendorDir . '/symfony/security-core/User/MissingUserProvider.php',
    '_ContaoManager\\Symfony\\Component\\Security\\Core\\User\\OidcUser' => $vendorDir . '/symfony/security-core/User/OidcUser.php',
    '_ContaoManager\\Symfony\\Component\\Security\\Core\\User\\PasswordAuthenticatedUserInterface' => $vendorDir . '/symfony/security-core/User/PasswordAuthenticatedUserInterface.php',
    '_ContaoManager\\Symfony\\Component\\Security\\Core\\User\\PasswordUpgraderInterface' => $vendorDir . '/symfony/security-core/User/PasswordUpgraderInterface.php',
    '_ContaoManager\\Symfony\\Component\\Security\\Core\\User\\UserCheckerInterface' => $vendorDir . '/symfony/security-core/User/UserCheckerInterface.php',
    '_ContaoManager\\Symfony\\Component\\Security\\Core\\User\\UserInterface' => $vendorDir . '/symfony/security-core/User/UserInterface.php',
    '_ContaoManager\\Symfony\\Component\\Security\\Core\\User\\UserProviderInterface' => $vendorDir . '/symfony/security-core/User/UserProviderInterface.php',
    '_ContaoManager\\Symfony\\Component\\Security\\Core\\Validator\\Constraints\\UserPassword' => $vendorDir . '/symfony/security-core/Validator/Constraints/UserPassword.php',
    '_ContaoManager\\Symfony\\Component\\Security\\Core\\Validator\\Constraints\\UserPasswordValidator' => $vendorDir . '/symfony/security-core/Validator/Constraints/UserPasswordValidator.php',
    '_ContaoManager\\Symfony\\Component\\Security\\Csrf\\CsrfToken' => $vendorDir . '/symfony/security-csrf/CsrfToken.php',
    '_ContaoManager\\Symfony\\Component\\Security\\Csrf\\CsrfTokenManager' => $vendorDir . '/symfony/security-csrf/CsrfTokenManager.php',
    '_ContaoManager\\Symfony\\Component\\Security\\Csrf\\CsrfTokenManagerInterface' => $vendorDir . '/symfony/security-csrf/CsrfTokenManagerInterface.php',
    '_ContaoManager\\Symfony\\Component\\Security\\Csrf\\Exception\\TokenNotFoundException' => $vendorDir . '/symfony/security-csrf/Exception/TokenNotFoundException.php',
    '_ContaoManager\\Symfony\\Component\\Security\\Csrf\\TokenGenerator\\TokenGeneratorInterface' => $vendorDir . '/symfony/security-csrf/TokenGenerator/TokenGeneratorInterface.php',
    '_ContaoManager\\Symfony\\Component\\Security\\Csrf\\TokenGenerator\\UriSafeTokenGenerator' => $vendorDir . '/symfony/security-csrf/TokenGenerator/UriSafeTokenGenerator.php',
    '_ContaoManager\\Symfony\\Component\\Security\\Csrf\\TokenStorage\\ClearableTokenStorageInterface' => $vendorDir . '/symfony/security-csrf/TokenStorage/ClearableTokenStorageInterface.php',
    '_ContaoManager\\Symfony\\Component\\Security\\Csrf\\TokenStorage\\NativeSessionTokenStorage' => $vendorDir . '/symfony/security-csrf/TokenStorage/NativeSessionTokenStorage.php',
    '_ContaoManager\\Symfony\\Component\\Security\\Csrf\\TokenStorage\\SessionTokenStorage' => $vendorDir . '/symfony/security-csrf/TokenStorage/SessionTokenStorage.php',
    '_ContaoManager\\Symfony\\Component\\Security\\Csrf\\TokenStorage\\TokenStorageInterface' => $vendorDir . '/symfony/security-csrf/TokenStorage/TokenStorageInterface.php',
    '_ContaoManager\\Symfony\\Component\\Security\\Http\\AccessMap' => $vendorDir . '/symfony/security-http/AccessMap.php',
    '_ContaoManager\\Symfony\\Component\\Security\\Http\\AccessMapInterface' => $vendorDir . '/symfony/security-http/AccessMapInterface.php',
    '_ContaoManager\\Symfony\\Component\\Security\\Http\\AccessToken\\AccessTokenExtractorInterface' => $vendorDir . '/symfony/security-http/AccessToken/AccessTokenExtractorInterface.php',
    '_ContaoManager\\Symfony\\Component\\Security\\Http\\AccessToken\\AccessTokenHandlerInterface' => $vendorDir . '/symfony/security-http/AccessToken/AccessTokenHandlerInterface.php',
    '_ContaoManager\\Symfony\\Component\\Security\\Http\\AccessToken\\ChainAccessTokenExtractor' => $vendorDir . '/symfony/security-http/AccessToken/ChainAccessTokenExtractor.php',
    '_ContaoManager\\Symfony\\Component\\Security\\Http\\AccessToken\\FormEncodedBodyExtractor' => $vendorDir . '/symfony/security-http/AccessToken/FormEncodedBodyExtractor.php',
    '_ContaoManager\\Symfony\\Component\\Security\\Http\\AccessToken\\HeaderAccessTokenExtractor' => $vendorDir . '/symfony/security-http/AccessToken/HeaderAccessTokenExtractor.php',
    '_ContaoManager\\Symfony\\Component\\Security\\Http\\AccessToken\\Oidc\\Exception\\InvalidSignatureException' => $vendorDir . '/symfony/security-http/AccessToken/Oidc/Exception/InvalidSignatureException.php',
    '_ContaoManager\\Symfony\\Component\\Security\\Http\\AccessToken\\Oidc\\Exception\\MissingClaimException' => $vendorDir . '/symfony/security-http/AccessToken/Oidc/Exception/MissingClaimException.php',
    '_ContaoManager\\Symfony\\Component\\Security\\Http\\AccessToken\\Oidc\\OidcTokenHandler' => $vendorDir . '/symfony/security-http/AccessToken/Oidc/OidcTokenHandler.php',
    '_ContaoManager\\Symfony\\Component\\Security\\Http\\AccessToken\\Oidc\\OidcTrait' => $vendorDir . '/symfony/security-http/AccessToken/Oidc/OidcTrait.php',
    '_ContaoManager\\Symfony\\Component\\Security\\Http\\AccessToken\\Oidc\\OidcUserInfoTokenHandler' => $vendorDir . '/symfony/security-http/AccessToken/Oidc/OidcUserInfoTokenHandler.php',
    '_ContaoManager\\Symfony\\Component\\Security\\Http\\AccessToken\\QueryAccessTokenExtractor' => $vendorDir . '/symfony/security-http/AccessToken/QueryAccessTokenExtractor.php',
    '_ContaoManager\\Symfony\\Component\\Security\\Http\\Attribute\\CurrentUser' => $vendorDir . '/symfony/security-http/Attribute/CurrentUser.php',
    '_ContaoManager\\Symfony\\Component\\Security\\Http\\Attribute\\IsGranted' => $vendorDir . '/symfony/security-http/Attribute/IsGranted.php',
    '_ContaoManager\\Symfony\\Component\\Security\\Http\\Authentication\\AuthenticationFailureHandlerInterface' => $vendorDir . '/symfony/security-http/Authentication/AuthenticationFailureHandlerInterface.php',
    '_ContaoManager\\Symfony\\Component\\Security\\Http\\Authentication\\AuthenticationSuccessHandlerInterface' => $vendorDir . '/symfony/security-http/Authentication/AuthenticationSuccessHandlerInterface.php',
    '_ContaoManager\\Symfony\\Component\\Security\\Http\\Authentication\\AuthenticationUtils' => $vendorDir . '/symfony/security-http/Authentication/AuthenticationUtils.php',
    '_ContaoManager\\Symfony\\Component\\Security\\Http\\Authentication\\AuthenticatorManager' => $vendorDir . '/symfony/security-http/Authentication/AuthenticatorManager.php',
    '_ContaoManager\\Symfony\\Component\\Security\\Http\\Authentication\\AuthenticatorManagerInterface' => $vendorDir . '/symfony/security-http/Authentication/AuthenticatorManagerInterface.php',
    '_ContaoManager\\Symfony\\Component\\Security\\Http\\Authentication\\CustomAuthenticationFailureHandler' => $vendorDir . '/symfony/security-http/Authentication/CustomAuthenticationFailureHandler.php',
    '_ContaoManager\\Symfony\\Component\\Security\\Http\\Authentication\\CustomAuthenticationSuccessHandler' => $vendorDir . '/symfony/security-http/Authentication/CustomAuthenticationSuccessHandler.php',
    '_ContaoManager\\Symfony\\Component\\Security\\Http\\Authentication\\DefaultAuthenticationFailureHandler' => $vendorDir . '/symfony/security-http/Authentication/DefaultAuthenticationFailureHandler.php',
    '_ContaoManager\\Symfony\\Component\\Security\\Http\\Authentication\\DefaultAuthenticationSuccessHandler' => $vendorDir . '/symfony/security-http/Authentication/DefaultAuthenticationSuccessHandler.php',
    '_ContaoManager\\Symfony\\Component\\Security\\Http\\Authentication\\UserAuthenticatorInterface' => $vendorDir . '/symfony/security-http/Authentication/UserAuthenticatorInterface.php',
    '_ContaoManager\\Symfony\\Component\\Security\\Http\\Authenticator\\AbstractAuthenticator' => $vendorDir . '/symfony/security-http/Authenticator/AbstractAuthenticator.php',
    '_ContaoManager\\Symfony\\Component\\Security\\Http\\Authenticator\\AbstractLoginFormAuthenticator' => $vendorDir . '/symfony/security-http/Authenticator/AbstractLoginFormAuthenticator.php',
    '_ContaoManager\\Symfony\\Component\\Security\\Http\\Authenticator\\AbstractPreAuthenticatedAuthenticator' => $vendorDir . '/symfony/security-http/Authenticator/AbstractPreAuthenticatedAuthenticator.php',
    '_ContaoManager\\Symfony\\Component\\Security\\Http\\Authenticator\\AccessTokenAuthenticator' => $vendorDir . '/symfony/security-http/Authenticator/AccessTokenAuthenticator.php',
    '_ContaoManager\\Symfony\\Component\\Security\\Http\\Authenticator\\AuthenticatorInterface' => $vendorDir . '/symfony/security-http/Authenticator/AuthenticatorInterface.php',
    '_ContaoManager\\Symfony\\Component\\Security\\Http\\Authenticator\\Debug\\TraceableAuthenticator' => $vendorDir . '/symfony/security-http/Authenticator/Debug/TraceableAuthenticator.php',
    '_ContaoManager\\Symfony\\Component\\Security\\Http\\Authenticator\\Debug\\TraceableAuthenticatorManagerListener' => $vendorDir . '/symfony/security-http/Authenticator/Debug/TraceableAuthenticatorManagerListener.php',
    '_ContaoManager\\Symfony\\Component\\Security\\Http\\Authenticator\\FallbackUserLoader' => $vendorDir . '/symfony/security-http/Authenticator/FallbackUserLoader.php',
    '_ContaoManager\\Symfony\\Component\\Security\\Http\\Authenticator\\FormLoginAuthenticator' => $vendorDir . '/symfony/security-http/Authenticator/FormLoginAuthenticator.php',
    '_ContaoManager\\Symfony\\Component\\Security\\Http\\Authenticator\\HttpBasicAuthenticator' => $vendorDir . '/symfony/security-http/Authenticator/HttpBasicAuthenticator.php',
    '_ContaoManager\\Symfony\\Component\\Security\\Http\\Authenticator\\InteractiveAuthenticatorInterface' => $vendorDir . '/symfony/security-http/Authenticator/InteractiveAuthenticatorInterface.php',
    '_ContaoManager\\Symfony\\Component\\Security\\Http\\Authenticator\\JsonLoginAuthenticator' => $vendorDir . '/symfony/security-http/Authenticator/JsonLoginAuthenticator.php',
    '_ContaoManager\\Symfony\\Component\\Security\\Http\\Authenticator\\LoginLinkAuthenticator' => $vendorDir . '/symfony/security-http/Authenticator/LoginLinkAuthenticator.php',
    '_ContaoManager\\Symfony\\Component\\Security\\Http\\Authenticator\\Passport\\Badge\\BadgeInterface' => $vendorDir . '/symfony/security-http/Authenticator/Passport/Badge/BadgeInterface.php',
    '_ContaoManager\\Symfony\\Component\\Security\\Http\\Authenticator\\Passport\\Badge\\CsrfTokenBadge' => $vendorDir . '/symfony/security-http/Authenticator/Passport/Badge/CsrfTokenBadge.php',
    '_ContaoManager\\Symfony\\Component\\Security\\Http\\Authenticator\\Passport\\Badge\\PasswordUpgradeBadge' => $vendorDir . '/symfony/security-http/Authenticator/Passport/Badge/PasswordUpgradeBadge.php',
    '_ContaoManager\\Symfony\\Component\\Security\\Http\\Authenticator\\Passport\\Badge\\PreAuthenticatedUserBadge' => $vendorDir . '/symfony/security-http/Authenticator/Passport/Badge/PreAuthenticatedUserBadge.php',
    '_ContaoManager\\Symfony\\Component\\Security\\Http\\Authenticator\\Passport\\Badge\\RememberMeBadge' => $vendorDir . '/symfony/security-http/Authenticator/Passport/Badge/RememberMeBadge.php',
    '_ContaoManager\\Symfony\\Component\\Security\\Http\\Authenticator\\Passport\\Badge\\UserBadge' => $vendorDir . '/symfony/security-http/Authenticator/Passport/Badge/UserBadge.php',
    '_ContaoManager\\Symfony\\Component\\Security\\Http\\Authenticator\\Passport\\Credentials\\CredentialsInterface' => $vendorDir . '/symfony/security-http/Authenticator/Passport/Credentials/CredentialsInterface.php',
    '_ContaoManager\\Symfony\\Component\\Security\\Http\\Authenticator\\Passport\\Credentials\\CustomCredentials' => $vendorDir . '/symfony/security-http/Authenticator/Passport/Credentials/CustomCredentials.php',
    '_ContaoManager\\Symfony\\Component\\Security\\Http\\Authenticator\\Passport\\Credentials\\PasswordCredentials' => $vendorDir . '/symfony/security-http/Authenticator/Passport/Credentials/PasswordCredentials.php',
    '_ContaoManager\\Symfony\\Component\\Security\\Http\\Authenticator\\Passport\\Passport' => $vendorDir . '/symfony/security-http/Authenticator/Passport/Passport.php',
    '_ContaoManager\\Symfony\\Component\\Security\\Http\\Authenticator\\Passport\\SelfValidatingPassport' => $vendorDir . '/symfony/security-http/Authenticator/Passport/SelfValidatingPassport.php',
    '_ContaoManager\\Symfony\\Component\\Security\\Http\\Authenticator\\RememberMeAuthenticator' => $vendorDir . '/symfony/security-http/Authenticator/RememberMeAuthenticator.php',
    '_ContaoManager\\Symfony\\Component\\Security\\Http\\Authenticator\\RemoteUserAuthenticator' => $vendorDir . '/symfony/security-http/Authenticator/RemoteUserAuthenticator.php',
    '_ContaoManager\\Symfony\\Component\\Security\\Http\\Authenticator\\Token\\PostAuthenticationToken' => $vendorDir . '/symfony/security-http/Authenticator/Token/PostAuthenticationToken.php',
    '_ContaoManager\\Symfony\\Component\\Security\\Http\\Authenticator\\X509Authenticator' => $vendorDir . '/symfony/security-http/Authenticator/X509Authenticator.php',
    '_ContaoManager\\Symfony\\Component\\Security\\Http\\Authorization\\AccessDeniedHandlerInterface' => $vendorDir . '/symfony/security-http/Authorization/AccessDeniedHandlerInterface.php',
    '_ContaoManager\\Symfony\\Component\\Security\\Http\\Controller\\SecurityTokenValueResolver' => $vendorDir . '/symfony/security-http/Controller/SecurityTokenValueResolver.php',
    '_ContaoManager\\Symfony\\Component\\Security\\Http\\Controller\\UserValueResolver' => $vendorDir . '/symfony/security-http/Controller/UserValueResolver.php',
    '_ContaoManager\\Symfony\\Component\\Security\\Http\\EntryPoint\\AuthenticationEntryPointInterface' => $vendorDir . '/symfony/security-http/EntryPoint/AuthenticationEntryPointInterface.php',
    '_ContaoManager\\Symfony\\Component\\Security\\Http\\EntryPoint\\Exception\\NotAnEntryPointException' => $vendorDir . '/symfony/security-http/EntryPoint/Exception/NotAnEntryPointException.php',
    '_ContaoManager\\Symfony\\Component\\Security\\Http\\EventListener\\CheckCredentialsListener' => $vendorDir . '/symfony/security-http/EventListener/CheckCredentialsListener.php',
    '_ContaoManager\\Symfony\\Component\\Security\\Http\\EventListener\\CheckRememberMeConditionsListener' => $vendorDir . '/symfony/security-http/EventListener/CheckRememberMeConditionsListener.php',
    '_ContaoManager\\Symfony\\Component\\Security\\Http\\EventListener\\ClearSiteDataLogoutListener' => $vendorDir . '/symfony/security-http/EventListener/ClearSiteDataLogoutListener.php',
    '_ContaoManager\\Symfony\\Component\\Security\\Http\\EventListener\\CookieClearingLogoutListener' => $vendorDir . '/symfony/security-http/EventListener/CookieClearingLogoutListener.php',
    '_ContaoManager\\Symfony\\Component\\Security\\Http\\EventListener\\CsrfProtectionListener' => $vendorDir . '/symfony/security-http/EventListener/CsrfProtectionListener.php',
    '_ContaoManager\\Symfony\\Component\\Security\\Http\\EventListener\\CsrfTokenClearingLogoutListener' => $vendorDir . '/symfony/security-http/EventListener/CsrfTokenClearingLogoutListener.php',
    '_ContaoManager\\Symfony\\Component\\Security\\Http\\EventListener\\DefaultLogoutListener' => $vendorDir . '/symfony/security-http/EventListener/DefaultLogoutListener.php',
    '_ContaoManager\\Symfony\\Component\\Security\\Http\\EventListener\\IsGrantedAttributeListener' => $vendorDir . '/symfony/security-http/EventListener/IsGrantedAttributeListener.php',
    '_ContaoManager\\Symfony\\Component\\Security\\Http\\EventListener\\LoginThrottlingListener' => $vendorDir . '/symfony/security-http/EventListener/LoginThrottlingListener.php',
    '_ContaoManager\\Symfony\\Component\\Security\\Http\\EventListener\\PasswordMigratingListener' => $vendorDir . '/symfony/security-http/EventListener/PasswordMigratingListener.php',
    '_ContaoManager\\Symfony\\Component\\Security\\Http\\EventListener\\RememberMeListener' => $vendorDir . '/symfony/security-http/EventListener/RememberMeListener.php',
    '_ContaoManager\\Symfony\\Component\\Security\\Http\\EventListener\\SessionLogoutListener' => $vendorDir . '/symfony/security-http/EventListener/SessionLogoutListener.php',
    '_ContaoManager\\Symfony\\Component\\Security\\Http\\EventListener\\SessionStrategyListener' => $vendorDir . '/symfony/security-http/EventListener/SessionStrategyListener.php',
    '_ContaoManager\\Symfony\\Component\\Security\\Http\\EventListener\\UserCheckerListener' => $vendorDir . '/symfony/security-http/EventListener/UserCheckerListener.php',
    '_ContaoManager\\Symfony\\Component\\Security\\Http\\EventListener\\UserProviderListener' => $vendorDir . '/symfony/security-http/EventListener/UserProviderListener.php',
    '_ContaoManager\\Symfony\\Component\\Security\\Http\\Event\\AuthenticationTokenCreatedEvent' => $vendorDir . '/symfony/security-http/Event/AuthenticationTokenCreatedEvent.php',
    '_ContaoManager\\Symfony\\Component\\Security\\Http\\Event\\CheckPassportEvent' => $vendorDir . '/symfony/security-http/Event/CheckPassportEvent.php',
    '_ContaoManager\\Symfony\\Component\\Security\\Http\\Event\\InteractiveLoginEvent' => $vendorDir . '/symfony/security-http/Event/InteractiveLoginEvent.php',
    '_ContaoManager\\Symfony\\Component\\Security\\Http\\Event\\LazyResponseEvent' => $vendorDir . '/symfony/security-http/Event/LazyResponseEvent.php',
    '_ContaoManager\\Symfony\\Component\\Security\\Http\\Event\\LoginFailureEvent' => $vendorDir . '/symfony/security-http/Event/LoginFailureEvent.php',
    '_ContaoManager\\Symfony\\Component\\Security\\Http\\Event\\LoginSuccessEvent' => $vendorDir . '/symfony/security-http/Event/LoginSuccessEvent.php',
    '_ContaoManager\\Symfony\\Component\\Security\\Http\\Event\\LogoutEvent' => $vendorDir . '/symfony/security-http/Event/LogoutEvent.php',
    '_ContaoManager\\Symfony\\Component\\Security\\Http\\Event\\SwitchUserEvent' => $vendorDir . '/symfony/security-http/Event/SwitchUserEvent.php',
    '_ContaoManager\\Symfony\\Component\\Security\\Http\\Event\\TokenDeauthenticatedEvent' => $vendorDir . '/symfony/security-http/Event/TokenDeauthenticatedEvent.php',
    '_ContaoManager\\Symfony\\Component\\Security\\Http\\Firewall' => $vendorDir . '/symfony/security-http/Firewall.php',
    '_ContaoManager\\Symfony\\Component\\Security\\Http\\FirewallMap' => $vendorDir . '/symfony/security-http/FirewallMap.php',
    '_ContaoManager\\Symfony\\Component\\Security\\Http\\FirewallMapInterface' => $vendorDir . '/symfony/security-http/FirewallMapInterface.php',
    '_ContaoManager\\Symfony\\Component\\Security\\Http\\Firewall\\AbstractListener' => $vendorDir . '/symfony/security-http/Firewall/AbstractListener.php',
    '_ContaoManager\\Symfony\\Component\\Security\\Http\\Firewall\\AccessListener' => $vendorDir . '/symfony/security-http/Firewall/AccessListener.php',
    '_ContaoManager\\Symfony\\Component\\Security\\Http\\Firewall\\AuthenticatorManagerListener' => $vendorDir . '/symfony/security-http/Firewall/AuthenticatorManagerListener.php',
    '_ContaoManager\\Symfony\\Component\\Security\\Http\\Firewall\\ChannelListener' => $vendorDir . '/symfony/security-http/Firewall/ChannelListener.php',
    '_ContaoManager\\Symfony\\Component\\Security\\Http\\Firewall\\ContextListener' => $vendorDir . '/symfony/security-http/Firewall/ContextListener.php',
    '_ContaoManager\\Symfony\\Component\\Security\\Http\\Firewall\\ExceptionListener' => $vendorDir . '/symfony/security-http/Firewall/ExceptionListener.php',
    '_ContaoManager\\Symfony\\Component\\Security\\Http\\Firewall\\FirewallListenerInterface' => $vendorDir . '/symfony/security-http/Firewall/FirewallListenerInterface.php',
    '_ContaoManager\\Symfony\\Component\\Security\\Http\\Firewall\\LogoutListener' => $vendorDir . '/symfony/security-http/Firewall/LogoutListener.php',
    '_ContaoManager\\Symfony\\Component\\Security\\Http\\Firewall\\SwitchUserListener' => $vendorDir . '/symfony/security-http/Firewall/SwitchUserListener.php',
    '_ContaoManager\\Symfony\\Component\\Security\\Http\\HttpUtils' => $vendorDir . '/symfony/security-http/HttpUtils.php',
    '_ContaoManager\\Symfony\\Component\\Security\\Http\\Impersonate\\ImpersonateUrlGenerator' => $vendorDir . '/symfony/security-http/Impersonate/ImpersonateUrlGenerator.php',
    '_ContaoManager\\Symfony\\Component\\Security\\Http\\LoginLink\\Exception\\ExpiredLoginLinkException' => $vendorDir . '/symfony/security-http/LoginLink/Exception/ExpiredLoginLinkException.php',
    '_ContaoManager\\Symfony\\Component\\Security\\Http\\LoginLink\\Exception\\InvalidLoginLinkAuthenticationException' => $vendorDir . '/symfony/security-http/LoginLink/Exception/InvalidLoginLinkAuthenticationException.php',
    '_ContaoManager\\Symfony\\Component\\Security\\Http\\LoginLink\\Exception\\InvalidLoginLinkException' => $vendorDir . '/symfony/security-http/LoginLink/Exception/InvalidLoginLinkException.php',
    '_ContaoManager\\Symfony\\Component\\Security\\Http\\LoginLink\\Exception\\InvalidLoginLinkExceptionInterface' => $vendorDir . '/symfony/security-http/LoginLink/Exception/InvalidLoginLinkExceptionInterface.php',
    '_ContaoManager\\Symfony\\Component\\Security\\Http\\LoginLink\\LoginLinkDetails' => $vendorDir . '/symfony/security-http/LoginLink/LoginLinkDetails.php',
    '_ContaoManager\\Symfony\\Component\\Security\\Http\\LoginLink\\LoginLinkHandler' => $vendorDir . '/symfony/security-http/LoginLink/LoginLinkHandler.php',
    '_ContaoManager\\Symfony\\Component\\Security\\Http\\LoginLink\\LoginLinkHandlerInterface' => $vendorDir . '/symfony/security-http/LoginLink/LoginLinkHandlerInterface.php',
    '_ContaoManager\\Symfony\\Component\\Security\\Http\\LoginLink\\LoginLinkNotification' => $vendorDir . '/symfony/security-http/LoginLink/LoginLinkNotification.php',
    '_ContaoManager\\Symfony\\Component\\Security\\Http\\Logout\\LogoutUrlGenerator' => $vendorDir . '/symfony/security-http/Logout/LogoutUrlGenerator.php',
    '_ContaoManager\\Symfony\\Component\\Security\\Http\\ParameterBagUtils' => $vendorDir . '/symfony/security-http/ParameterBagUtils.php',
    '_ContaoManager\\Symfony\\Component\\Security\\Http\\RateLimiter\\DefaultLoginRateLimiter' => $vendorDir . '/symfony/security-http/RateLimiter/DefaultLoginRateLimiter.php',
    '_ContaoManager\\Symfony\\Component\\Security\\Http\\RememberMe\\AbstractRememberMeHandler' => $vendorDir . '/symfony/security-http/RememberMe/AbstractRememberMeHandler.php',
    '_ContaoManager\\Symfony\\Component\\Security\\Http\\RememberMe\\PersistentRememberMeHandler' => $vendorDir . '/symfony/security-http/RememberMe/PersistentRememberMeHandler.php',
    '_ContaoManager\\Symfony\\Component\\Security\\Http\\RememberMe\\RememberMeDetails' => $vendorDir . '/symfony/security-http/RememberMe/RememberMeDetails.php',
    '_ContaoManager\\Symfony\\Component\\Security\\Http\\RememberMe\\RememberMeHandlerInterface' => $vendorDir . '/symfony/security-http/RememberMe/RememberMeHandlerInterface.php',
    '_ContaoManager\\Symfony\\Component\\Security\\Http\\RememberMe\\ResponseListener' => $vendorDir . '/symfony/security-http/RememberMe/ResponseListener.php',
    '_ContaoManager\\Symfony\\Component\\Security\\Http\\RememberMe\\SignatureRememberMeHandler' => $vendorDir . '/symfony/security-http/RememberMe/SignatureRememberMeHandler.php',
    '_ContaoManager\\Symfony\\Component\\Security\\Http\\SecurityEvents' => $vendorDir . '/symfony/security-http/SecurityEvents.php',
    '_ContaoManager\\Symfony\\Component\\Security\\Http\\SecurityRequestAttributes' => $vendorDir . '/symfony/security-http/SecurityRequestAttributes.php',
    '_ContaoManager\\Symfony\\Component\\Security\\Http\\Session\\SessionAuthenticationStrategy' => $vendorDir . '/symfony/security-http/Session/SessionAuthenticationStrategy.php',
    '_ContaoManager\\Symfony\\Component\\Security\\Http\\Session\\SessionAuthenticationStrategyInterface' => $vendorDir . '/symfony/security-http/Session/SessionAuthenticationStrategyInterface.php',
    '_ContaoManager\\Symfony\\Component\\Security\\Http\\Util\\TargetPathTrait' => $vendorDir . '/symfony/security-http/Util/TargetPathTrait.php',
    '_ContaoManager\\Symfony\\Component\\Serializer\\Annotation\\Context' => $vendorDir . '/symfony/serializer/Annotation/Context.php',
    '_ContaoManager\\Symfony\\Component\\Serializer\\Annotation\\DiscriminatorMap' => $vendorDir . '/symfony/serializer/Annotation/DiscriminatorMap.php',
    '_ContaoManager\\Symfony\\Component\\Serializer\\Annotation\\Groups' => $vendorDir . '/symfony/serializer/Annotation/Groups.php',
    '_ContaoManager\\Symfony\\Component\\Serializer\\Annotation\\Ignore' => $vendorDir . '/symfony/serializer/Annotation/Ignore.php',
    '_ContaoManager\\Symfony\\Component\\Serializer\\Annotation\\MaxDepth' => $vendorDir . '/symfony/serializer/Annotation/MaxDepth.php',
    '_ContaoManager\\Symfony\\Component\\Serializer\\Annotation\\SerializedName' => $vendorDir . '/symfony/serializer/Annotation/SerializedName.php',
    '_ContaoManager\\Symfony\\Component\\Serializer\\Annotation\\SerializedPath' => $vendorDir . '/symfony/serializer/Annotation/SerializedPath.php',
    '_ContaoManager\\Symfony\\Component\\Serializer\\Attribute\\Context' => $vendorDir . '/symfony/serializer/Attribute/Context.php',
    '_ContaoManager\\Symfony\\Component\\Serializer\\Attribute\\DiscriminatorMap' => $vendorDir . '/symfony/serializer/Attribute/DiscriminatorMap.php',
    '_ContaoManager\\Symfony\\Component\\Serializer\\Attribute\\Groups' => $vendorDir . '/symfony/serializer/Attribute/Groups.php',
    '_ContaoManager\\Symfony\\Component\\Serializer\\Attribute\\Ignore' => $vendorDir . '/symfony/serializer/Attribute/Ignore.php',
    '_ContaoManager\\Symfony\\Component\\Serializer\\Attribute\\MaxDepth' => $vendorDir . '/symfony/serializer/Attribute/MaxDepth.php',
    '_ContaoManager\\Symfony\\Component\\Serializer\\Attribute\\SerializedName' => $vendorDir . '/symfony/serializer/Attribute/SerializedName.php',
    '_ContaoManager\\Symfony\\Component\\Serializer\\Attribute\\SerializedPath' => $vendorDir . '/symfony/serializer/Attribute/SerializedPath.php',
    '_ContaoManager\\Symfony\\Component\\Serializer\\CacheWarmer\\CompiledClassMetadataCacheWarmer' => $vendorDir . '/symfony/serializer/CacheWarmer/CompiledClassMetadataCacheWarmer.php',
    '_ContaoManager\\Symfony\\Component\\Serializer\\Command\\DebugCommand' => $vendorDir . '/symfony/serializer/Command/DebugCommand.php',
    '_ContaoManager\\Symfony\\Component\\Serializer\\Context\\ContextBuilderInterface' => $vendorDir . '/symfony/serializer/Context/ContextBuilderInterface.php',
    '_ContaoManager\\Symfony\\Component\\Serializer\\Context\\ContextBuilderTrait' => $vendorDir . '/symfony/serializer/Context/ContextBuilderTrait.php',
    '_ContaoManager\\Symfony\\Component\\Serializer\\Context\\Encoder\\CsvEncoderContextBuilder' => $vendorDir . '/symfony/serializer/Context/Encoder/CsvEncoderContextBuilder.php',
    '_ContaoManager\\Symfony\\Component\\Serializer\\Context\\Encoder\\JsonEncoderContextBuilder' => $vendorDir . '/symfony/serializer/Context/Encoder/JsonEncoderContextBuilder.php',
    '_ContaoManager\\Symfony\\Component\\Serializer\\Context\\Encoder\\XmlEncoderContextBuilder' => $vendorDir . '/symfony/serializer/Context/Encoder/XmlEncoderContextBuilder.php',
    '_ContaoManager\\Symfony\\Component\\Serializer\\Context\\Encoder\\YamlEncoderContextBuilder' => $vendorDir . '/symfony/serializer/Context/Encoder/YamlEncoderContextBuilder.php',
    '_ContaoManager\\Symfony\\Component\\Serializer\\Context\\Normalizer\\AbstractNormalizerContextBuilder' => $vendorDir . '/symfony/serializer/Context/Normalizer/AbstractNormalizerContextBuilder.php',
    '_ContaoManager\\Symfony\\Component\\Serializer\\Context\\Normalizer\\AbstractObjectNormalizerContextBuilder' => $vendorDir . '/symfony/serializer/Context/Normalizer/AbstractObjectNormalizerContextBuilder.php',
    '_ContaoManager\\Symfony\\Component\\Serializer\\Context\\Normalizer\\BackedEnumNormalizerContextBuilder' => $vendorDir . '/symfony/serializer/Context/Normalizer/BackedEnumNormalizerContextBuilder.php',
    '_ContaoManager\\Symfony\\Component\\Serializer\\Context\\Normalizer\\ConstraintViolationListNormalizerContextBuilder' => $vendorDir . '/symfony/serializer/Context/Normalizer/ConstraintViolationListNormalizerContextBuilder.php',
    '_ContaoManager\\Symfony\\Component\\Serializer\\Context\\Normalizer\\DateIntervalNormalizerContextBuilder' => $vendorDir . '/symfony/serializer/Context/Normalizer/DateIntervalNormalizerContextBuilder.php',
    '_ContaoManager\\Symfony\\Component\\Serializer\\Context\\Normalizer\\DateTimeNormalizerContextBuilder' => $vendorDir . '/symfony/serializer/Context/Normalizer/DateTimeNormalizerContextBuilder.php',
    '_ContaoManager\\Symfony\\Component\\Serializer\\Context\\Normalizer\\FormErrorNormalizerContextBuilder' => $vendorDir . '/symfony/serializer/Context/Normalizer/FormErrorNormalizerContextBuilder.php',
    '_ContaoManager\\Symfony\\Component\\Serializer\\Context\\Normalizer\\GetSetMethodNormalizerContextBuilder' => $vendorDir . '/symfony/serializer/Context/Normalizer/GetSetMethodNormalizerContextBuilder.php',
    '_ContaoManager\\Symfony\\Component\\Serializer\\Context\\Normalizer\\JsonSerializableNormalizerContextBuilder' => $vendorDir . '/symfony/serializer/Context/Normalizer/JsonSerializableNormalizerContextBuilder.php',
    '_ContaoManager\\Symfony\\Component\\Serializer\\Context\\Normalizer\\ObjectNormalizerContextBuilder' => $vendorDir . '/symfony/serializer/Context/Normalizer/ObjectNormalizerContextBuilder.php',
    '_ContaoManager\\Symfony\\Component\\Serializer\\Context\\Normalizer\\ProblemNormalizerContextBuilder' => $vendorDir . '/symfony/serializer/Context/Normalizer/ProblemNormalizerContextBuilder.php',
    '_ContaoManager\\Symfony\\Component\\Serializer\\Context\\Normalizer\\PropertyNormalizerContextBuilder' => $vendorDir . '/symfony/serializer/Context/Normalizer/PropertyNormalizerContextBuilder.php',
    '_ContaoManager\\Symfony\\Component\\Serializer\\Context\\Normalizer\\UidNormalizerContextBuilder' => $vendorDir . '/symfony/serializer/Context/Normalizer/UidNormalizerContextBuilder.php',
    '_ContaoManager\\Symfony\\Component\\Serializer\\Context\\Normalizer\\UnwrappingDenormalizerContextBuilder' => $vendorDir . '/symfony/serializer/Context/Normalizer/UnwrappingDenormalizerContextBuilder.php',
    '_ContaoManager\\Symfony\\Component\\Serializer\\Context\\SerializerContextBuilder' => $vendorDir . '/symfony/serializer/Context/SerializerContextBuilder.php',
    '_ContaoManager\\Symfony\\Component\\Serializer\\DataCollector\\SerializerDataCollector' => $vendorDir . '/symfony/serializer/DataCollector/SerializerDataCollector.php',
    '_ContaoManager\\Symfony\\Component\\Serializer\\Debug\\TraceableEncoder' => $vendorDir . '/symfony/serializer/Debug/TraceableEncoder.php',
    '_ContaoManager\\Symfony\\Component\\Serializer\\Debug\\TraceableNormalizer' => $vendorDir . '/symfony/serializer/Debug/TraceableNormalizer.php',
    '_ContaoManager\\Symfony\\Component\\Serializer\\Debug\\TraceableSerializer' => $vendorDir . '/symfony/serializer/Debug/TraceableSerializer.php',
    '_ContaoManager\\Symfony\\Component\\Serializer\\DependencyInjection\\SerializerPass' => $vendorDir . '/symfony/serializer/DependencyInjection/SerializerPass.php',
    '_ContaoManager\\Symfony\\Component\\Serializer\\Encoder\\ChainDecoder' => $vendorDir . '/symfony/serializer/Encoder/ChainDecoder.php',
    '_ContaoManager\\Symfony\\Component\\Serializer\\Encoder\\ChainEncoder' => $vendorDir . '/symfony/serializer/Encoder/ChainEncoder.php',
    '_ContaoManager\\Symfony\\Component\\Serializer\\Encoder\\ContextAwareDecoderInterface' => $vendorDir . '/symfony/serializer/Encoder/ContextAwareDecoderInterface.php',
    '_ContaoManager\\Symfony\\Component\\Serializer\\Encoder\\ContextAwareEncoderInterface' => $vendorDir . '/symfony/serializer/Encoder/ContextAwareEncoderInterface.php',
    '_ContaoManager\\Symfony\\Component\\Serializer\\Encoder\\CsvEncoder' => $vendorDir . '/symfony/serializer/Encoder/CsvEncoder.php',
    '_ContaoManager\\Symfony\\Component\\Serializer\\Encoder\\DecoderInterface' => $vendorDir . '/symfony/serializer/Encoder/DecoderInterface.php',
    '_ContaoManager\\Symfony\\Component\\Serializer\\Encoder\\EncoderInterface' => $vendorDir . '/symfony/serializer/Encoder/EncoderInterface.php',
    '_ContaoManager\\Symfony\\Component\\Serializer\\Encoder\\JsonDecode' => $vendorDir . '/symfony/serializer/Encoder/JsonDecode.php',
    '_ContaoManager\\Symfony\\Component\\Serializer\\Encoder\\JsonEncode' => $vendorDir . '/symfony/serializer/Encoder/JsonEncode.php',
    '_ContaoManager\\Symfony\\Component\\Serializer\\Encoder\\JsonEncoder' => $vendorDir . '/symfony/serializer/Encoder/JsonEncoder.php',
    '_ContaoManager\\Symfony\\Component\\Serializer\\Encoder\\NormalizationAwareInterface' => $vendorDir . '/symfony/serializer/Encoder/NormalizationAwareInterface.php',
    '_ContaoManager\\Symfony\\Component\\Serializer\\Encoder\\XmlEncoder' => $vendorDir . '/symfony/serializer/Encoder/XmlEncoder.php',
    '_ContaoManager\\Symfony\\Component\\Serializer\\Encoder\\YamlEncoder' => $vendorDir . '/symfony/serializer/Encoder/YamlEncoder.php',
    '_ContaoManager\\Symfony\\Component\\Serializer\\Exception\\BadMethodCallException' => $vendorDir . '/symfony/serializer/Exception/BadMethodCallException.php',
    '_ContaoManager\\Symfony\\Component\\Serializer\\Exception\\CircularReferenceException' => $vendorDir . '/symfony/serializer/Exception/CircularReferenceException.php',
    '_ContaoManager\\Symfony\\Component\\Serializer\\Exception\\ExceptionInterface' => $vendorDir . '/symfony/serializer/Exception/ExceptionInterface.php',
    '_ContaoManager\\Symfony\\Component\\Serializer\\Exception\\ExtraAttributesException' => $vendorDir . '/symfony/serializer/Exception/ExtraAttributesException.php',
    '_ContaoManager\\Symfony\\Component\\Serializer\\Exception\\InvalidArgumentException' => $vendorDir . '/symfony/serializer/Exception/InvalidArgumentException.php',
    '_ContaoManager\\Symfony\\Component\\Serializer\\Exception\\LogicException' => $vendorDir . '/symfony/serializer/Exception/LogicException.php',
    '_ContaoManager\\Symfony\\Component\\Serializer\\Exception\\MappingException' => $vendorDir . '/symfony/serializer/Exception/MappingException.php',
    '_ContaoManager\\Symfony\\Component\\Serializer\\Exception\\MissingConstructorArgumentsException' => $vendorDir . '/symfony/serializer/Exception/MissingConstructorArgumentsException.php',
    '_ContaoManager\\Symfony\\Component\\Serializer\\Exception\\NotEncodableValueException' => $vendorDir . '/symfony/serializer/Exception/NotEncodableValueException.php',
    '_ContaoManager\\Symfony\\Component\\Serializer\\Exception\\NotNormalizableValueException' => $vendorDir . '/symfony/serializer/Exception/NotNormalizableValueException.php',
    '_ContaoManager\\Symfony\\Component\\Serializer\\Exception\\PartialDenormalizationException' => $vendorDir . '/symfony/serializer/Exception/PartialDenormalizationException.php',
    '_ContaoManager\\Symfony\\Component\\Serializer\\Exception\\RuntimeException' => $vendorDir . '/symfony/serializer/Exception/RuntimeException.php',
    '_ContaoManager\\Symfony\\Component\\Serializer\\Exception\\UnexpectedValueException' => $vendorDir . '/symfony/serializer/Exception/UnexpectedValueException.php',
    '_ContaoManager\\Symfony\\Component\\Serializer\\Exception\\UnsupportedException' => $vendorDir . '/symfony/serializer/Exception/UnsupportedException.php',
    '_ContaoManager\\Symfony\\Component\\Serializer\\Exception\\UnsupportedFormatException' => $vendorDir . '/symfony/serializer/Exception/UnsupportedFormatException.php',
    '_ContaoManager\\Symfony\\Component\\Serializer\\Extractor\\ObjectPropertyListExtractor' => $vendorDir . '/symfony/serializer/Extractor/ObjectPropertyListExtractor.php',
    '_ContaoManager\\Symfony\\Component\\Serializer\\Extractor\\ObjectPropertyListExtractorInterface' => $vendorDir . '/symfony/serializer/Extractor/ObjectPropertyListExtractorInterface.php',
    '_ContaoManager\\Symfony\\Component\\Serializer\\Mapping\\AttributeMetadata' => $vendorDir . '/symfony/serializer/Mapping/AttributeMetadata.php',
    '_ContaoManager\\Symfony\\Component\\Serializer\\Mapping\\AttributeMetadataInterface' => $vendorDir . '/symfony/serializer/Mapping/AttributeMetadataInterface.php',
    '_ContaoManager\\Symfony\\Component\\Serializer\\Mapping\\ClassDiscriminatorFromClassMetadata' => $vendorDir . '/symfony/serializer/Mapping/ClassDiscriminatorFromClassMetadata.php',
    '_ContaoManager\\Symfony\\Component\\Serializer\\Mapping\\ClassDiscriminatorMapping' => $vendorDir . '/symfony/serializer/Mapping/ClassDiscriminatorMapping.php',
    '_ContaoManager\\Symfony\\Component\\Serializer\\Mapping\\ClassDiscriminatorResolverInterface' => $vendorDir . '/symfony/serializer/Mapping/ClassDiscriminatorResolverInterface.php',
    '_ContaoManager\\Symfony\\Component\\Serializer\\Mapping\\ClassMetadata' => $vendorDir . '/symfony/serializer/Mapping/ClassMetadata.php',
    '_ContaoManager\\Symfony\\Component\\Serializer\\Mapping\\ClassMetadataInterface' => $vendorDir . '/symfony/serializer/Mapping/ClassMetadataInterface.php',
    '_ContaoManager\\Symfony\\Component\\Serializer\\Mapping\\Factory\\CacheClassMetadataFactory' => $vendorDir . '/symfony/serializer/Mapping/Factory/CacheClassMetadataFactory.php',
    '_ContaoManager\\Symfony\\Component\\Serializer\\Mapping\\Factory\\ClassMetadataFactory' => $vendorDir . '/symfony/serializer/Mapping/Factory/ClassMetadataFactory.php',
    '_ContaoManager\\Symfony\\Component\\Serializer\\Mapping\\Factory\\ClassMetadataFactoryCompiler' => $vendorDir . '/symfony/serializer/Mapping/Factory/ClassMetadataFactoryCompiler.php',
    '_ContaoManager\\Symfony\\Component\\Serializer\\Mapping\\Factory\\ClassMetadataFactoryInterface' => $vendorDir . '/symfony/serializer/Mapping/Factory/ClassMetadataFactoryInterface.php',
    '_ContaoManager\\Symfony\\Component\\Serializer\\Mapping\\Factory\\ClassResolverTrait' => $vendorDir . '/symfony/serializer/Mapping/Factory/ClassResolverTrait.php',
    '_ContaoManager\\Symfony\\Component\\Serializer\\Mapping\\Factory\\CompiledClassMetadataFactory' => $vendorDir . '/symfony/serializer/Mapping/Factory/CompiledClassMetadataFactory.php',
    '_ContaoManager\\Symfony\\Component\\Serializer\\Mapping\\Loader\\AccessorCollisionResolverTrait' => $vendorDir . '/symfony/serializer/Mapping/Loader/AccessorCollisionResolverTrait.php',
    '_ContaoManager\\Symfony\\Component\\Serializer\\Mapping\\Loader\\AnnotationLoader' => $vendorDir . '/symfony/serializer/Mapping/Loader/AnnotationLoader.php',
    '_ContaoManager\\Symfony\\Component\\Serializer\\Mapping\\Loader\\AttributeLoader' => $vendorDir . '/symfony/serializer/Mapping/Loader/AttributeLoader.php',
    '_ContaoManager\\Symfony\\Component\\Serializer\\Mapping\\Loader\\FileLoader' => $vendorDir . '/symfony/serializer/Mapping/Loader/FileLoader.php',
    '_ContaoManager\\Symfony\\Component\\Serializer\\Mapping\\Loader\\LoaderChain' => $vendorDir . '/symfony/serializer/Mapping/Loader/LoaderChain.php',
    '_ContaoManager\\Symfony\\Component\\Serializer\\Mapping\\Loader\\LoaderInterface' => $vendorDir . '/symfony/serializer/Mapping/Loader/LoaderInterface.php',
    '_ContaoManager\\Symfony\\Component\\Serializer\\Mapping\\Loader\\XmlFileLoader' => $vendorDir . '/symfony/serializer/Mapping/Loader/XmlFileLoader.php',
    '_ContaoManager\\Symfony\\Component\\Serializer\\Mapping\\Loader\\YamlFileLoader' => $vendorDir . '/symfony/serializer/Mapping/Loader/YamlFileLoader.php',
    '_ContaoManager\\Symfony\\Component\\Serializer\\NameConverter\\AdvancedNameConverterInterface' => $vendorDir . '/symfony/serializer/NameConverter/AdvancedNameConverterInterface.php',
    '_ContaoManager\\Symfony\\Component\\Serializer\\NameConverter\\CamelCaseToSnakeCaseNameConverter' => $vendorDir . '/symfony/serializer/NameConverter/CamelCaseToSnakeCaseNameConverter.php',
    '_ContaoManager\\Symfony\\Component\\Serializer\\NameConverter\\MetadataAwareNameConverter' => $vendorDir . '/symfony/serializer/NameConverter/MetadataAwareNameConverter.php',
    '_ContaoManager\\Symfony\\Component\\Serializer\\NameConverter\\NameConverterInterface' => $vendorDir . '/symfony/serializer/NameConverter/NameConverterInterface.php',
    '_ContaoManager\\Symfony\\Component\\Serializer\\Normalizer\\AbstractNormalizer' => $vendorDir . '/symfony/serializer/Normalizer/AbstractNormalizer.php',
    '_ContaoManager\\Symfony\\Component\\Serializer\\Normalizer\\AbstractObjectNormalizer' => $vendorDir . '/symfony/serializer/Normalizer/AbstractObjectNormalizer.php',
    '_ContaoManager\\Symfony\\Component\\Serializer\\Normalizer\\ArrayDenormalizer' => $vendorDir . '/symfony/serializer/Normalizer/ArrayDenormalizer.php',
    '_ContaoManager\\Symfony\\Component\\Serializer\\Normalizer\\BackedEnumNormalizer' => $vendorDir . '/symfony/serializer/Normalizer/BackedEnumNormalizer.php',
    '_ContaoManager\\Symfony\\Component\\Serializer\\Normalizer\\CacheableSupportsMethodInterface' => $vendorDir . '/symfony/serializer/Normalizer/CacheableSupportsMethodInterface.php',
    '_ContaoManager\\Symfony\\Component\\Serializer\\Normalizer\\ConstraintViolationListNormalizer' => $vendorDir . '/symfony/serializer/Normalizer/ConstraintViolationListNormalizer.php',
    '_ContaoManager\\Symfony\\Component\\Serializer\\Normalizer\\ContextAwareDenormalizerInterface' => $vendorDir . '/symfony/serializer/Normalizer/ContextAwareDenormalizerInterface.php',
    '_ContaoManager\\Symfony\\Component\\Serializer\\Normalizer\\ContextAwareNormalizerInterface' => $vendorDir . '/symfony/serializer/Normalizer/ContextAwareNormalizerInterface.php',
    '_ContaoManager\\Symfony\\Component\\Serializer\\Normalizer\\CustomNormalizer' => $vendorDir . '/symfony/serializer/Normalizer/CustomNormalizer.php',
    '_ContaoManager\\Symfony\\Component\\Serializer\\Normalizer\\DataUriNormalizer' => $vendorDir . '/symfony/serializer/Normalizer/DataUriNormalizer.php',
    '_ContaoManager\\Symfony\\Component\\Serializer\\Normalizer\\DateIntervalNormalizer' => $vendorDir . '/symfony/serializer/Normalizer/DateIntervalNormalizer.php',
    '_ContaoManager\\Symfony\\Component\\Serializer\\Normalizer\\DateTimeNormalizer' => $vendorDir . '/symfony/serializer/Normalizer/DateTimeNormalizer.php',
    '_ContaoManager\\Symfony\\Component\\Serializer\\Normalizer\\DateTimeZoneNormalizer' => $vendorDir . '/symfony/serializer/Normalizer/DateTimeZoneNormalizer.php',
    '_ContaoManager\\Symfony\\Component\\Serializer\\Normalizer\\DenormalizableInterface' => $vendorDir . '/symfony/serializer/Normalizer/DenormalizableInterface.php',
    '_ContaoManager\\Symfony\\Component\\Serializer\\Normalizer\\DenormalizerAwareInterface' => $vendorDir . '/symfony/serializer/Normalizer/DenormalizerAwareInterface.php',
    '_ContaoManager\\Symfony\\Component\\Serializer\\Normalizer\\DenormalizerAwareTrait' => $vendorDir . '/symfony/serializer/Normalizer/DenormalizerAwareTrait.php',
    '_ContaoManager\\Symfony\\Component\\Serializer\\Normalizer\\DenormalizerInterface' => $vendorDir . '/symfony/serializer/Normalizer/DenormalizerInterface.php',
    '_ContaoManager\\Symfony\\Component\\Serializer\\Normalizer\\FormErrorNormalizer' => $vendorDir . '/symfony/serializer/Normalizer/FormErrorNormalizer.php',
    '_ContaoManager\\Symfony\\Component\\Serializer\\Normalizer\\GetSetMethodNormalizer' => $vendorDir . '/symfony/serializer/Normalizer/GetSetMethodNormalizer.php',
    '_ContaoManager\\Symfony\\Component\\Serializer\\Normalizer\\JsonSerializableNormalizer' => $vendorDir . '/symfony/serializer/Normalizer/JsonSerializableNormalizer.php',
    '_ContaoManager\\Symfony\\Component\\Serializer\\Normalizer\\MimeMessageNormalizer' => $vendorDir . '/symfony/serializer/Normalizer/MimeMessageNormalizer.php',
    '_ContaoManager\\Symfony\\Component\\Serializer\\Normalizer\\NormalizableInterface' => $vendorDir . '/symfony/serializer/Normalizer/NormalizableInterface.php',
    '_ContaoManager\\Symfony\\Component\\Serializer\\Normalizer\\NormalizerAwareInterface' => $vendorDir . '/symfony/serializer/Normalizer/NormalizerAwareInterface.php',
    '_ContaoManager\\Symfony\\Component\\Serializer\\Normalizer\\NormalizerAwareTrait' => $vendorDir . '/symfony/serializer/Normalizer/NormalizerAwareTrait.php',
    '_ContaoManager\\Symfony\\Component\\Serializer\\Normalizer\\NormalizerInterface' => $vendorDir . '/symfony/serializer/Normalizer/NormalizerInterface.php',
    '_ContaoManager\\Symfony\\Component\\Serializer\\Normalizer\\ObjectNormalizer' => $vendorDir . '/symfony/serializer/Normalizer/ObjectNormalizer.php',
    '_ContaoManager\\Symfony\\Component\\Serializer\\Normalizer\\ObjectToPopulateTrait' => $vendorDir . '/symfony/serializer/Normalizer/ObjectToPopulateTrait.php',
    '_ContaoManager\\Symfony\\Component\\Serializer\\Normalizer\\ProblemNormalizer' => $vendorDir . '/symfony/serializer/Normalizer/ProblemNormalizer.php',
    '_ContaoManager\\Symfony\\Component\\Serializer\\Normalizer\\PropertyNormalizer' => $vendorDir . '/symfony/serializer/Normalizer/PropertyNormalizer.php',
    '_ContaoManager\\Symfony\\Component\\Serializer\\Normalizer\\TranslatableNormalizer' => $vendorDir . '/symfony/serializer/Normalizer/TranslatableNormalizer.php',
    '_ContaoManager\\Symfony\\Component\\Serializer\\Normalizer\\UidNormalizer' => $vendorDir . '/symfony/serializer/Normalizer/UidNormalizer.php',
    '_ContaoManager\\Symfony\\Component\\Serializer\\Normalizer\\UnwrappingDenormalizer' => $vendorDir . '/symfony/serializer/Normalizer/UnwrappingDenormalizer.php',
    '_ContaoManager\\Symfony\\Component\\Serializer\\Serializer' => $vendorDir . '/symfony/serializer/Serializer.php',
    '_ContaoManager\\Symfony\\Component\\Serializer\\SerializerAwareInterface' => $vendorDir . '/symfony/serializer/SerializerAwareInterface.php',
    '_ContaoManager\\Symfony\\Component\\Serializer\\SerializerAwareTrait' => $vendorDir . '/symfony/serializer/SerializerAwareTrait.php',
    '_ContaoManager\\Symfony\\Component\\Serializer\\SerializerInterface' => $vendorDir . '/symfony/serializer/SerializerInterface.php',
    '_ContaoManager\\Symfony\\Component\\String\\AbstractString' => $vendorDir . '/symfony/string/AbstractString.php',
    '_ContaoManager\\Symfony\\Component\\String\\AbstractUnicodeString' => $vendorDir . '/symfony/string/AbstractUnicodeString.php',
    '_ContaoManager\\Symfony\\Component\\String\\ByteString' => $vendorDir . '/symfony/string/ByteString.php',
    '_ContaoManager\\Symfony\\Component\\String\\CodePointString' => $vendorDir . '/symfony/string/CodePointString.php',
    '_ContaoManager\\Symfony\\Component\\String\\Exception\\ExceptionInterface' => $vendorDir . '/symfony/string/Exception/ExceptionInterface.php',
    '_ContaoManager\\Symfony\\Component\\String\\Exception\\InvalidArgumentException' => $vendorDir . '/symfony/string/Exception/InvalidArgumentException.php',
    '_ContaoManager\\Symfony\\Component\\String\\Exception\\RuntimeException' => $vendorDir . '/symfony/string/Exception/RuntimeException.php',
    '_ContaoManager\\Symfony\\Component\\String\\Inflector\\EnglishInflector' => $vendorDir . '/symfony/string/Inflector/EnglishInflector.php',
    '_ContaoManager\\Symfony\\Component\\String\\Inflector\\FrenchInflector' => $vendorDir . '/symfony/string/Inflector/FrenchInflector.php',
    '_ContaoManager\\Symfony\\Component\\String\\Inflector\\InflectorInterface' => $vendorDir . '/symfony/string/Inflector/InflectorInterface.php',
    '_ContaoManager\\Symfony\\Component\\String\\LazyString' => $vendorDir . '/symfony/string/LazyString.php',
    '_ContaoManager\\Symfony\\Component\\String\\Slugger\\AsciiSlugger' => $vendorDir . '/symfony/string/Slugger/AsciiSlugger.php',
    '_ContaoManager\\Symfony\\Component\\String\\Slugger\\SluggerInterface' => $vendorDir . '/symfony/string/Slugger/SluggerInterface.php',
    '_ContaoManager\\Symfony\\Component\\String\\UnicodeString' => $vendorDir . '/symfony/string/UnicodeString.php',
    '_ContaoManager\\Symfony\\Component\\Uid\\AbstractUid' => $vendorDir . '/symfony/uid/AbstractUid.php',
    '_ContaoManager\\Symfony\\Component\\Uid\\BinaryUtil' => $vendorDir . '/symfony/uid/BinaryUtil.php',
    '_ContaoManager\\Symfony\\Component\\Uid\\Command\\GenerateUlidCommand' => $vendorDir . '/symfony/uid/Command/GenerateUlidCommand.php',
    '_ContaoManager\\Symfony\\Component\\Uid\\Command\\GenerateUuidCommand' => $vendorDir . '/symfony/uid/Command/GenerateUuidCommand.php',
    '_ContaoManager\\Symfony\\Component\\Uid\\Command\\InspectUlidCommand' => $vendorDir . '/symfony/uid/Command/InspectUlidCommand.php',
    '_ContaoManager\\Symfony\\Component\\Uid\\Command\\InspectUuidCommand' => $vendorDir . '/symfony/uid/Command/InspectUuidCommand.php',
    '_ContaoManager\\Symfony\\Component\\Uid\\Factory\\NameBasedUuidFactory' => $vendorDir . '/symfony/uid/Factory/NameBasedUuidFactory.php',
    '_ContaoManager\\Symfony\\Component\\Uid\\Factory\\RandomBasedUuidFactory' => $vendorDir . '/symfony/uid/Factory/RandomBasedUuidFactory.php',
    '_ContaoManager\\Symfony\\Component\\Uid\\Factory\\TimeBasedUuidFactory' => $vendorDir . '/symfony/uid/Factory/TimeBasedUuidFactory.php',
    '_ContaoManager\\Symfony\\Component\\Uid\\Factory\\UlidFactory' => $vendorDir . '/symfony/uid/Factory/UlidFactory.php',
    '_ContaoManager\\Symfony\\Component\\Uid\\Factory\\UuidFactory' => $vendorDir . '/symfony/uid/Factory/UuidFactory.php',
    '_ContaoManager\\Symfony\\Component\\Uid\\MaxUlid' => $vendorDir . '/symfony/uid/MaxUlid.php',
    '_ContaoManager\\Symfony\\Component\\Uid\\MaxUuid' => $vendorDir . '/symfony/uid/MaxUuid.php',
    '_ContaoManager\\Symfony\\Component\\Uid\\NilUlid' => $vendorDir . '/symfony/uid/NilUlid.php',
    '_ContaoManager\\Symfony\\Component\\Uid\\NilUuid' => $vendorDir . '/symfony/uid/NilUuid.php',
    '_ContaoManager\\Symfony\\Component\\Uid\\TimeBasedUidInterface' => $vendorDir . '/symfony/uid/TimeBasedUidInterface.php',
    '_ContaoManager\\Symfony\\Component\\Uid\\Ulid' => $vendorDir . '/symfony/uid/Ulid.php',
    '_ContaoManager\\Symfony\\Component\\Uid\\Uuid' => $vendorDir . '/symfony/uid/Uuid.php',
    '_ContaoManager\\Symfony\\Component\\Uid\\UuidV1' => $vendorDir . '/symfony/uid/UuidV1.php',
    '_ContaoManager\\Symfony\\Component\\Uid\\UuidV3' => $vendorDir . '/symfony/uid/UuidV3.php',
    '_ContaoManager\\Symfony\\Component\\Uid\\UuidV4' => $vendorDir . '/symfony/uid/UuidV4.php',
    '_ContaoManager\\Symfony\\Component\\Uid\\UuidV5' => $vendorDir . '/symfony/uid/UuidV5.php',
    '_ContaoManager\\Symfony\\Component\\Uid\\UuidV6' => $vendorDir . '/symfony/uid/UuidV6.php',
    '_ContaoManager\\Symfony\\Component\\Uid\\UuidV7' => $vendorDir . '/symfony/uid/UuidV7.php',
    '_ContaoManager\\Symfony\\Component\\Uid\\UuidV8' => $vendorDir . '/symfony/uid/UuidV8.php',
    '_ContaoManager\\Symfony\\Component\\VarDumper\\Caster\\AmqpCaster' => $vendorDir . '/symfony/var-dumper/Caster/AmqpCaster.php',
    '_ContaoManager\\Symfony\\Component\\VarDumper\\Caster\\ArgsStub' => $vendorDir . '/symfony/var-dumper/Caster/ArgsStub.php',
    '_ContaoManager\\Symfony\\Component\\VarDumper\\Caster\\Caster' => $vendorDir . '/symfony/var-dumper/Caster/Caster.php',
    '_ContaoManager\\Symfony\\Component\\VarDumper\\Caster\\ClassStub' => $vendorDir . '/symfony/var-dumper/Caster/ClassStub.php',
    '_ContaoManager\\Symfony\\Component\\VarDumper\\Caster\\ConstStub' => $vendorDir . '/symfony/var-dumper/Caster/ConstStub.php',
    '_ContaoManager\\Symfony\\Component\\VarDumper\\Caster\\CutArrayStub' => $vendorDir . '/symfony/var-dumper/Caster/CutArrayStub.php',
    '_ContaoManager\\Symfony\\Component\\VarDumper\\Caster\\CutStub' => $vendorDir . '/symfony/var-dumper/Caster/CutStub.php',
    '_ContaoManager\\Symfony\\Component\\VarDumper\\Caster\\DOMCaster' => $vendorDir . '/symfony/var-dumper/Caster/DOMCaster.php',
    '_ContaoManager\\Symfony\\Component\\VarDumper\\Caster\\DateCaster' => $vendorDir . '/symfony/var-dumper/Caster/DateCaster.php',
    '_ContaoManager\\Symfony\\Component\\VarDumper\\Caster\\DoctrineCaster' => $vendorDir . '/symfony/var-dumper/Caster/DoctrineCaster.php',
    '_ContaoManager\\Symfony\\Component\\VarDumper\\Caster\\DsCaster' => $vendorDir . '/symfony/var-dumper/Caster/DsCaster.php',
    '_ContaoManager\\Symfony\\Component\\VarDumper\\Caster\\DsPairStub' => $vendorDir . '/symfony/var-dumper/Caster/DsPairStub.php',
    '_ContaoManager\\Symfony\\Component\\VarDumper\\Caster\\EnumStub' => $vendorDir . '/symfony/var-dumper/Caster/EnumStub.php',
    '_ContaoManager\\Symfony\\Component\\VarDumper\\Caster\\ExceptionCaster' => $vendorDir . '/symfony/var-dumper/Caster/ExceptionCaster.php',
    '_ContaoManager\\Symfony\\Component\\VarDumper\\Caster\\FFICaster' => $vendorDir . '/symfony/var-dumper/Caster/FFICaster.php',
    '_ContaoManager\\Symfony\\Component\\VarDumper\\Caster\\FiberCaster' => $vendorDir . '/symfony/var-dumper/Caster/FiberCaster.php',
    '_ContaoManager\\Symfony\\Component\\VarDumper\\Caster\\FrameStub' => $vendorDir . '/symfony/var-dumper/Caster/FrameStub.php',
    '_ContaoManager\\Symfony\\Component\\VarDumper\\Caster\\GmpCaster' => $vendorDir . '/symfony/var-dumper/Caster/GmpCaster.php',
    '_ContaoManager\\Symfony\\Component\\VarDumper\\Caster\\ImagineCaster' => $vendorDir . '/symfony/var-dumper/Caster/ImagineCaster.php',
    '_ContaoManager\\Symfony\\Component\\VarDumper\\Caster\\ImgStub' => $vendorDir . '/symfony/var-dumper/Caster/ImgStub.php',
    '_ContaoManager\\Symfony\\Component\\VarDumper\\Caster\\IntlCaster' => $vendorDir . '/symfony/var-dumper/Caster/IntlCaster.php',
    '_ContaoManager\\Symfony\\Component\\VarDumper\\Caster\\LinkStub' => $vendorDir . '/symfony/var-dumper/Caster/LinkStub.php',
    '_ContaoManager\\Symfony\\Component\\VarDumper\\Caster\\MemcachedCaster' => $vendorDir . '/symfony/var-dumper/Caster/MemcachedCaster.php',
    '_ContaoManager\\Symfony\\Component\\VarDumper\\Caster\\MysqliCaster' => $vendorDir . '/symfony/var-dumper/Caster/MysqliCaster.php',
    '_ContaoManager\\Symfony\\Component\\VarDumper\\Caster\\PdoCaster' => $vendorDir . '/symfony/var-dumper/Caster/PdoCaster.php',
    '_ContaoManager\\Symfony\\Component\\VarDumper\\Caster\\PgSqlCaster' => $vendorDir . '/symfony/var-dumper/Caster/PgSqlCaster.php',
    '_ContaoManager\\Symfony\\Component\\VarDumper\\Caster\\ProxyManagerCaster' => $vendorDir . '/symfony/var-dumper/Caster/ProxyManagerCaster.php',
    '_ContaoManager\\Symfony\\Component\\VarDumper\\Caster\\RdKafkaCaster' => $vendorDir . '/symfony/var-dumper/Caster/RdKafkaCaster.php',
    '_ContaoManager\\Symfony\\Component\\VarDumper\\Caster\\RedisCaster' => $vendorDir . '/symfony/var-dumper/Caster/RedisCaster.php',
    '_ContaoManager\\Symfony\\Component\\VarDumper\\Caster\\ReflectionCaster' => $vendorDir . '/symfony/var-dumper/Caster/ReflectionCaster.php',
    '_ContaoManager\\Symfony\\Component\\VarDumper\\Caster\\ResourceCaster' => $vendorDir . '/symfony/var-dumper/Caster/ResourceCaster.php',
    '_ContaoManager\\Symfony\\Component\\VarDumper\\Caster\\ScalarStub' => $vendorDir . '/symfony/var-dumper/Caster/ScalarStub.php',
    '_ContaoManager\\Symfony\\Component\\VarDumper\\Caster\\SplCaster' => $vendorDir . '/symfony/var-dumper/Caster/SplCaster.php',
    '_ContaoManager\\Symfony\\Component\\VarDumper\\Caster\\StubCaster' => $vendorDir . '/symfony/var-dumper/Caster/StubCaster.php',
    '_ContaoManager\\Symfony\\Component\\VarDumper\\Caster\\SymfonyCaster' => $vendorDir . '/symfony/var-dumper/Caster/SymfonyCaster.php',
    '_ContaoManager\\Symfony\\Component\\VarDumper\\Caster\\TraceStub' => $vendorDir . '/symfony/var-dumper/Caster/TraceStub.php',
    '_ContaoManager\\Symfony\\Component\\VarDumper\\Caster\\UninitializedStub' => $vendorDir . '/symfony/var-dumper/Caster/UninitializedStub.php',
    '_ContaoManager\\Symfony\\Component\\VarDumper\\Caster\\UuidCaster' => $vendorDir . '/symfony/var-dumper/Caster/UuidCaster.php',
    '_ContaoManager\\Symfony\\Component\\VarDumper\\Caster\\XmlReaderCaster' => $vendorDir . '/symfony/var-dumper/Caster/XmlReaderCaster.php',
    '_ContaoManager\\Symfony\\Component\\VarDumper\\Caster\\XmlResourceCaster' => $vendorDir . '/symfony/var-dumper/Caster/XmlResourceCaster.php',
    '_ContaoManager\\Symfony\\Component\\VarDumper\\Cloner\\AbstractCloner' => $vendorDir . '/symfony/var-dumper/Cloner/AbstractCloner.php',
    '_ContaoManager\\Symfony\\Component\\VarDumper\\Cloner\\ClonerInterface' => $vendorDir . '/symfony/var-dumper/Cloner/ClonerInterface.php',
    '_ContaoManager\\Symfony\\Component\\VarDumper\\Cloner\\Cursor' => $vendorDir . '/symfony/var-dumper/Cloner/Cursor.php',
    '_ContaoManager\\Symfony\\Component\\VarDumper\\Cloner\\Data' => $vendorDir . '/symfony/var-dumper/Cloner/Data.php',
    '_ContaoManager\\Symfony\\Component\\VarDumper\\Cloner\\DumperInterface' => $vendorDir . '/symfony/var-dumper/Cloner/DumperInterface.php',
    '_ContaoManager\\Symfony\\Component\\VarDumper\\Cloner\\Stub' => $vendorDir . '/symfony/var-dumper/Cloner/Stub.php',
    '_ContaoManager\\Symfony\\Component\\VarDumper\\Cloner\\VarCloner' => $vendorDir . '/symfony/var-dumper/Cloner/VarCloner.php',
    '_ContaoManager\\Symfony\\Component\\VarDumper\\Command\\Descriptor\\CliDescriptor' => $vendorDir . '/symfony/var-dumper/Command/Descriptor/CliDescriptor.php',
    '_ContaoManager\\Symfony\\Component\\VarDumper\\Command\\Descriptor\\DumpDescriptorInterface' => $vendorDir . '/symfony/var-dumper/Command/Descriptor/DumpDescriptorInterface.php',
    '_ContaoManager\\Symfony\\Component\\VarDumper\\Command\\Descriptor\\HtmlDescriptor' => $vendorDir . '/symfony/var-dumper/Command/Descriptor/HtmlDescriptor.php',
    '_ContaoManager\\Symfony\\Component\\VarDumper\\Command\\ServerDumpCommand' => $vendorDir . '/symfony/var-dumper/Command/ServerDumpCommand.php',
    '_ContaoManager\\Symfony\\Component\\VarDumper\\Dumper\\AbstractDumper' => $vendorDir . '/symfony/var-dumper/Dumper/AbstractDumper.php',
    '_ContaoManager\\Symfony\\Component\\VarDumper\\Dumper\\CliDumper' => $vendorDir . '/symfony/var-dumper/Dumper/CliDumper.php',
    '_ContaoManager\\Symfony\\Component\\VarDumper\\Dumper\\ContextProvider\\CliContextProvider' => $vendorDir . '/symfony/var-dumper/Dumper/ContextProvider/CliContextProvider.php',
    '_ContaoManager\\Symfony\\Component\\VarDumper\\Dumper\\ContextProvider\\ContextProviderInterface' => $vendorDir . '/symfony/var-dumper/Dumper/ContextProvider/ContextProviderInterface.php',
    '_ContaoManager\\Symfony\\Component\\VarDumper\\Dumper\\ContextProvider\\RequestContextProvider' => $vendorDir . '/symfony/var-dumper/Dumper/ContextProvider/RequestContextProvider.php',
    '_ContaoManager\\Symfony\\Component\\VarDumper\\Dumper\\ContextProvider\\SourceContextProvider' => $vendorDir . '/symfony/var-dumper/Dumper/ContextProvider/SourceContextProvider.php',
    '_ContaoManager\\Symfony\\Component\\VarDumper\\Dumper\\ContextualizedDumper' => $vendorDir . '/symfony/var-dumper/Dumper/ContextualizedDumper.php',
    '_ContaoManager\\Symfony\\Component\\VarDumper\\Dumper\\DataDumperInterface' => $vendorDir . '/symfony/var-dumper/Dumper/DataDumperInterface.php',
    '_ContaoManager\\Symfony\\Component\\VarDumper\\Dumper\\HtmlDumper' => $vendorDir . '/symfony/var-dumper/Dumper/HtmlDumper.php',
    '_ContaoManager\\Symfony\\Component\\VarDumper\\Dumper\\ServerDumper' => $vendorDir . '/symfony/var-dumper/Dumper/ServerDumper.php',
    '_ContaoManager\\Symfony\\Component\\VarDumper\\Exception\\ThrowingCasterException' => $vendorDir . '/symfony/var-dumper/Exception/ThrowingCasterException.php',
    '_ContaoManager\\Symfony\\Component\\VarDumper\\Server\\Connection' => $vendorDir . '/symfony/var-dumper/Server/Connection.php',
    '_ContaoManager\\Symfony\\Component\\VarDumper\\Server\\DumpServer' => $vendorDir . '/symfony/var-dumper/Server/DumpServer.php',
    '_ContaoManager\\Symfony\\Component\\VarDumper\\Test\\VarDumperTestTrait' => $vendorDir . '/symfony/var-dumper/Test/VarDumperTestTrait.php',
    '_ContaoManager\\Symfony\\Component\\VarDumper\\VarDumper' => $vendorDir . '/symfony/var-dumper/VarDumper.php',
    '_ContaoManager\\Symfony\\Component\\VarExporter\\Exception\\ClassNotFoundException' => $vendorDir . '/symfony/var-exporter/Exception/ClassNotFoundException.php',
    '_ContaoManager\\Symfony\\Component\\VarExporter\\Exception\\ExceptionInterface' => $vendorDir . '/symfony/var-exporter/Exception/ExceptionInterface.php',
    '_ContaoManager\\Symfony\\Component\\VarExporter\\Exception\\LogicException' => $vendorDir . '/symfony/var-exporter/Exception/LogicException.php',
    '_ContaoManager\\Symfony\\Component\\VarExporter\\Exception\\NotInstantiableTypeException' => $vendorDir . '/symfony/var-exporter/Exception/NotInstantiableTypeException.php',
    '_ContaoManager\\Symfony\\Component\\VarExporter\\Hydrator' => $vendorDir . '/symfony/var-exporter/Hydrator.php',
    '_ContaoManager\\Symfony\\Component\\VarExporter\\Instantiator' => $vendorDir . '/symfony/var-exporter/Instantiator.php',
    '_ContaoManager\\Symfony\\Component\\VarExporter\\Internal\\Exporter' => $vendorDir . '/symfony/var-exporter/Internal/Exporter.php',
    '_ContaoManager\\Symfony\\Component\\VarExporter\\Internal\\Hydrator' => $vendorDir . '/symfony/var-exporter/Internal/Hydrator.php',
    '_ContaoManager\\Symfony\\Component\\VarExporter\\Internal\\LazyObjectRegistry' => $vendorDir . '/symfony/var-exporter/Internal/LazyObjectRegistry.php',
    '_ContaoManager\\Symfony\\Component\\VarExporter\\Internal\\LazyObjectState' => $vendorDir . '/symfony/var-exporter/Internal/LazyObjectState.php',
    '_ContaoManager\\Symfony\\Component\\VarExporter\\Internal\\LazyObjectTrait' => $vendorDir . '/symfony/var-exporter/Internal/LazyObjectTrait.php',
    '_ContaoManager\\Symfony\\Component\\VarExporter\\Internal\\Reference' => $vendorDir . '/symfony/var-exporter/Internal/Reference.php',
    '_ContaoManager\\Symfony\\Component\\VarExporter\\Internal\\Registry' => $vendorDir . '/symfony/var-exporter/Internal/Registry.php',
    '_ContaoManager\\Symfony\\Component\\VarExporter\\Internal\\Values' => $vendorDir . '/symfony/var-exporter/Internal/Values.php',
    '_ContaoManager\\Symfony\\Component\\VarExporter\\LazyGhostTrait' => $vendorDir . '/symfony/var-exporter/LazyGhostTrait.php',
    '_ContaoManager\\Symfony\\Component\\VarExporter\\LazyObjectInterface' => $vendorDir . '/symfony/var-exporter/LazyObjectInterface.php',
    '_ContaoManager\\Symfony\\Component\\VarExporter\\LazyProxyTrait' => $vendorDir . '/symfony/var-exporter/LazyProxyTrait.php',
    '_ContaoManager\\Symfony\\Component\\VarExporter\\ProxyHelper' => $vendorDir . '/symfony/var-exporter/ProxyHelper.php',
    '_ContaoManager\\Symfony\\Component\\VarExporter\\VarExporter' => $vendorDir . '/symfony/var-exporter/VarExporter.php',
    '_ContaoManager\\Symfony\\Component\\Yaml\\Command\\LintCommand' => $vendorDir . '/symfony/yaml/Command/LintCommand.php',
    '_ContaoManager\\Symfony\\Component\\Yaml\\Dumper' => $vendorDir . '/symfony/yaml/Dumper.php',
    '_ContaoManager\\Symfony\\Component\\Yaml\\Escaper' => $vendorDir . '/symfony/yaml/Escaper.php',
    '_ContaoManager\\Symfony\\Component\\Yaml\\Exception\\DumpException' => $vendorDir . '/symfony/yaml/Exception/DumpException.php',
    '_ContaoManager\\Symfony\\Component\\Yaml\\Exception\\ExceptionInterface' => $vendorDir . '/symfony/yaml/Exception/ExceptionInterface.php',
    '_ContaoManager\\Symfony\\Component\\Yaml\\Exception\\ParseException' => $vendorDir . '/symfony/yaml/Exception/ParseException.php',
    '_ContaoManager\\Symfony\\Component\\Yaml\\Exception\\RuntimeException' => $vendorDir . '/symfony/yaml/Exception/RuntimeException.php',
    '_ContaoManager\\Symfony\\Component\\Yaml\\Inline' => $vendorDir . '/symfony/yaml/Inline.php',
    '_ContaoManager\\Symfony\\Component\\Yaml\\Parser' => $vendorDir . '/symfony/yaml/Parser.php',
    '_ContaoManager\\Symfony\\Component\\Yaml\\Tag\\TaggedValue' => $vendorDir . '/symfony/yaml/Tag/TaggedValue.php',
    '_ContaoManager\\Symfony\\Component\\Yaml\\Unescaper' => $vendorDir . '/symfony/yaml/Unescaper.php',
    '_ContaoManager\\Symfony\\Component\\Yaml\\Yaml' => $vendorDir . '/symfony/yaml/Yaml.php',
    '_ContaoManager\\Symfony\\Contracts\\Cache\\CacheInterface' => $vendorDir . '/symfony/cache-contracts/CacheInterface.php',
    '_ContaoManager\\Symfony\\Contracts\\Cache\\CacheTrait' => $vendorDir . '/symfony/cache-contracts/CacheTrait.php',
    '_ContaoManager\\Symfony\\Contracts\\Cache\\CallbackInterface' => $vendorDir . '/symfony/cache-contracts/CallbackInterface.php',
    '_ContaoManager\\Symfony\\Contracts\\Cache\\ItemInterface' => $vendorDir . '/symfony/cache-contracts/ItemInterface.php',
    '_ContaoManager\\Symfony\\Contracts\\Cache\\NamespacedPoolInterface' => $vendorDir . '/symfony/cache-contracts/NamespacedPoolInterface.php',
    '_ContaoManager\\Symfony\\Contracts\\Cache\\TagAwareCacheInterface' => $vendorDir . '/symfony/cache-contracts/TagAwareCacheInterface.php',
    '_ContaoManager\\Symfony\\Contracts\\EventDispatcher\\Event' => $vendorDir . '/symfony/event-dispatcher-contracts/Event.php',
    '_ContaoManager\\Symfony\\Contracts\\EventDispatcher\\EventDispatcherInterface' => $vendorDir . '/symfony/event-dispatcher-contracts/EventDispatcherInterface.php',
    '_ContaoManager\\Symfony\\Contracts\\Service\\Attribute\\Required' => $vendorDir . '/symfony/service-contracts/Attribute/Required.php',
    '_ContaoManager\\Symfony\\Contracts\\Service\\Attribute\\SubscribedService' => $vendorDir . '/symfony/service-contracts/Attribute/SubscribedService.php',
    '_ContaoManager\\Symfony\\Contracts\\Service\\ResetInterface' => $vendorDir . '/symfony/service-contracts/ResetInterface.php',
    '_ContaoManager\\Symfony\\Contracts\\Service\\ServiceCollectionInterface' => $vendorDir . '/symfony/service-contracts/ServiceCollectionInterface.php',
    '_ContaoManager\\Symfony\\Contracts\\Service\\ServiceLocatorTrait' => $vendorDir . '/symfony/service-contracts/ServiceLocatorTrait.php',
    '_ContaoManager\\Symfony\\Contracts\\Service\\ServiceMethodsSubscriberTrait' => $vendorDir . '/symfony/service-contracts/ServiceMethodsSubscriberTrait.php',
    '_ContaoManager\\Symfony\\Contracts\\Service\\ServiceProviderInterface' => $vendorDir . '/symfony/service-contracts/ServiceProviderInterface.php',
    '_ContaoManager\\Symfony\\Contracts\\Service\\ServiceSubscriberInterface' => $vendorDir . '/symfony/service-contracts/ServiceSubscriberInterface.php',
    '_ContaoManager\\Symfony\\Contracts\\Service\\ServiceSubscriberTrait' => $vendorDir . '/symfony/service-contracts/ServiceSubscriberTrait.php',
    '_ContaoManager\\Terminal42\\ComposerLockValidator\\ValidationException' => $vendorDir . '/terminal42/composer-lock-validator/src/ValidationException.php',
    '_ContaoManager\\Terminal42\\ComposerLockValidator\\Validator' => $vendorDir . '/terminal42/composer-lock-validator/src/Validator.php',
    '_ContaoManager\\Webauthn\\AttestationStatement\\AndroidKeyAttestationStatementSupport' => $vendorDir . '/web-auth/webauthn-lib/src/AttestationStatement/AndroidKeyAttestationStatementSupport.php',
    '_ContaoManager\\Webauthn\\AttestationStatement\\AndroidSafetyNetAttestationStatementSupport' => $vendorDir . '/web-auth/webauthn-lib/src/AttestationStatement/AndroidSafetyNetAttestationStatementSupport.php',
    '_ContaoManager\\Webauthn\\AttestationStatement\\AppleAttestationStatementSupport' => $vendorDir . '/web-auth/webauthn-lib/src/AttestationStatement/AppleAttestationStatementSupport.php',
    '_ContaoManager\\Webauthn\\AttestationStatement\\AttestationObject' => $vendorDir . '/web-auth/webauthn-lib/src/AttestationStatement/AttestationObject.php',
    '_ContaoManager\\Webauthn\\AttestationStatement\\AttestationObjectLoader' => $vendorDir . '/web-auth/webauthn-lib/src/AttestationStatement/AttestationObjectLoader.php',
    '_ContaoManager\\Webauthn\\AttestationStatement\\AttestationStatement' => $vendorDir . '/web-auth/webauthn-lib/src/AttestationStatement/AttestationStatement.php',
    '_ContaoManager\\Webauthn\\AttestationStatement\\AttestationStatementSupport' => $vendorDir . '/web-auth/webauthn-lib/src/AttestationStatement/AttestationStatementSupport.php',
    '_ContaoManager\\Webauthn\\AttestationStatement\\AttestationStatementSupportManager' => $vendorDir . '/web-auth/webauthn-lib/src/AttestationStatement/AttestationStatementSupportManager.php',
    '_ContaoManager\\Webauthn\\AttestationStatement\\FidoU2FAttestationStatementSupport' => $vendorDir . '/web-auth/webauthn-lib/src/AttestationStatement/FidoU2FAttestationStatementSupport.php',
    '_ContaoManager\\Webauthn\\AttestationStatement\\NoneAttestationStatementSupport' => $vendorDir . '/web-auth/webauthn-lib/src/AttestationStatement/NoneAttestationStatementSupport.php',
    '_ContaoManager\\Webauthn\\AttestationStatement\\PackedAttestationStatementSupport' => $vendorDir . '/web-auth/webauthn-lib/src/AttestationStatement/PackedAttestationStatementSupport.php',
    '_ContaoManager\\Webauthn\\AttestationStatement\\TPMAttestationStatementSupport' => $vendorDir . '/web-auth/webauthn-lib/src/AttestationStatement/TPMAttestationStatementSupport.php',
    '_ContaoManager\\Webauthn\\AttestedCredentialData' => $vendorDir . '/web-auth/webauthn-lib/src/AttestedCredentialData.php',
    '_ContaoManager\\Webauthn\\AuthenticationExtensions\\AuthenticationExtension' => $vendorDir . '/web-auth/webauthn-lib/src/AuthenticationExtensions/AuthenticationExtension.php',
    '_ContaoManager\\Webauthn\\AuthenticationExtensions\\AuthenticationExtensions' => $vendorDir . '/web-auth/webauthn-lib/src/AuthenticationExtensions/AuthenticationExtensions.php',
    '_ContaoManager\\Webauthn\\AuthenticationExtensions\\AuthenticationExtensionsClientInputs' => $vendorDir . '/web-auth/webauthn-lib/src/AuthenticationExtensions/AuthenticationExtensionsClientInputs.php',
    '_ContaoManager\\Webauthn\\AuthenticationExtensions\\AuthenticationExtensionsClientOutputs' => $vendorDir . '/web-auth/webauthn-lib/src/AuthenticationExtensions/AuthenticationExtensionsClientOutputs.php',
    '_ContaoManager\\Webauthn\\AuthenticationExtensions\\AuthenticationExtensionsClientOutputsLoader' => $vendorDir . '/web-auth/webauthn-lib/src/AuthenticationExtensions/AuthenticationExtensionsClientOutputsLoader.php',
    '_ContaoManager\\Webauthn\\AuthenticationExtensions\\ExtensionOutputChecker' => $vendorDir . '/web-auth/webauthn-lib/src/AuthenticationExtensions/ExtensionOutputChecker.php',
    '_ContaoManager\\Webauthn\\AuthenticationExtensions\\ExtensionOutputCheckerHandler' => $vendorDir . '/web-auth/webauthn-lib/src/AuthenticationExtensions/ExtensionOutputCheckerHandler.php',
    '_ContaoManager\\Webauthn\\AuthenticationExtensions\\ExtensionOutputError' => $vendorDir . '/web-auth/webauthn-lib/src/AuthenticationExtensions/ExtensionOutputError.php',
    '_ContaoManager\\Webauthn\\AuthenticatorAssertionResponse' => $vendorDir . '/web-auth/webauthn-lib/src/AuthenticatorAssertionResponse.php',
    '_ContaoManager\\Webauthn\\AuthenticatorAssertionResponseValidator' => $vendorDir . '/web-auth/webauthn-lib/src/AuthenticatorAssertionResponseValidator.php',
    '_ContaoManager\\Webauthn\\AuthenticatorAttestationResponse' => $vendorDir . '/web-auth/webauthn-lib/src/AuthenticatorAttestationResponse.php',
    '_ContaoManager\\Webauthn\\AuthenticatorAttestationResponseValidator' => $vendorDir . '/web-auth/webauthn-lib/src/AuthenticatorAttestationResponseValidator.php',
    '_ContaoManager\\Webauthn\\AuthenticatorData' => $vendorDir . '/web-auth/webauthn-lib/src/AuthenticatorData.php',
    '_ContaoManager\\Webauthn\\AuthenticatorDataLoader' => $vendorDir . '/web-auth/webauthn-lib/src/AuthenticatorDataLoader.php',
    '_ContaoManager\\Webauthn\\AuthenticatorResponse' => $vendorDir . '/web-auth/webauthn-lib/src/AuthenticatorResponse.php',
    '_ContaoManager\\Webauthn\\AuthenticatorSelectionCriteria' => $vendorDir . '/web-auth/webauthn-lib/src/AuthenticatorSelectionCriteria.php',
    '_ContaoManager\\Webauthn\\CeremonyStep\\CeremonyStep' => $vendorDir . '/web-auth/webauthn-lib/src/CeremonyStep/CeremonyStep.php',
    '_ContaoManager\\Webauthn\\CeremonyStep\\CeremonyStepManager' => $vendorDir . '/web-auth/webauthn-lib/src/CeremonyStep/CeremonyStepManager.php',
    '_ContaoManager\\Webauthn\\CeremonyStep\\CeremonyStepManagerFactory' => $vendorDir . '/web-auth/webauthn-lib/src/CeremonyStep/CeremonyStepManagerFactory.php',
    '_ContaoManager\\Webauthn\\CeremonyStep\\CheckAlgorithm' => $vendorDir . '/web-auth/webauthn-lib/src/CeremonyStep/CheckAlgorithm.php',
    '_ContaoManager\\Webauthn\\CeremonyStep\\CheckAllowedCredentialList' => $vendorDir . '/web-auth/webauthn-lib/src/CeremonyStep/CheckAllowedCredentialList.php',
    '_ContaoManager\\Webauthn\\CeremonyStep\\CheckAttestationFormatIsKnownAndValid' => $vendorDir . '/web-auth/webauthn-lib/src/CeremonyStep/CheckAttestationFormatIsKnownAndValid.php',
    '_ContaoManager\\Webauthn\\CeremonyStep\\CheckBackupBitsAreConsistent' => $vendorDir . '/web-auth/webauthn-lib/src/CeremonyStep/CheckBackupBitsAreConsistent.php',
    '_ContaoManager\\Webauthn\\CeremonyStep\\CheckChallenge' => $vendorDir . '/web-auth/webauthn-lib/src/CeremonyStep/CheckChallenge.php',
    '_ContaoManager\\Webauthn\\CeremonyStep\\CheckClientDataCollectorType' => $vendorDir . '/web-auth/webauthn-lib/src/CeremonyStep/CheckClientDataCollectorType.php',
    '_ContaoManager\\Webauthn\\CeremonyStep\\CheckCounter' => $vendorDir . '/web-auth/webauthn-lib/src/CeremonyStep/CheckCounter.php',
    '_ContaoManager\\Webauthn\\CeremonyStep\\CheckCredentialId' => $vendorDir . '/web-auth/webauthn-lib/src/CeremonyStep/CheckCredentialId.php',
    '_ContaoManager\\Webauthn\\CeremonyStep\\CheckExtensions' => $vendorDir . '/web-auth/webauthn-lib/src/CeremonyStep/CheckExtensions.php',
    '_ContaoManager\\Webauthn\\CeremonyStep\\CheckHasAttestedCredentialData' => $vendorDir . '/web-auth/webauthn-lib/src/CeremonyStep/CheckHasAttestedCredentialData.php',
    '_ContaoManager\\Webauthn\\CeremonyStep\\CheckMetadataStatement' => $vendorDir . '/web-auth/webauthn-lib/src/CeremonyStep/CheckMetadataStatement.php',
    '_ContaoManager\\Webauthn\\CeremonyStep\\CheckOrigin' => $vendorDir . '/web-auth/webauthn-lib/src/CeremonyStep/CheckOrigin.php',
    '_ContaoManager\\Webauthn\\CeremonyStep\\CheckRelyingPartyIdIdHash' => $vendorDir . '/web-auth/webauthn-lib/src/CeremonyStep/CheckRelyingPartyIdIdHash.php',
    '_ContaoManager\\Webauthn\\CeremonyStep\\CheckSignature' => $vendorDir . '/web-auth/webauthn-lib/src/CeremonyStep/CheckSignature.php',
    '_ContaoManager\\Webauthn\\CeremonyStep\\CheckTopOrigin' => $vendorDir . '/web-auth/webauthn-lib/src/CeremonyStep/CheckTopOrigin.php',
    '_ContaoManager\\Webauthn\\CeremonyStep\\CheckUserHandle' => $vendorDir . '/web-auth/webauthn-lib/src/CeremonyStep/CheckUserHandle.php',
    '_ContaoManager\\Webauthn\\CeremonyStep\\CheckUserVerification' => $vendorDir . '/web-auth/webauthn-lib/src/CeremonyStep/CheckUserVerification.php',
    '_ContaoManager\\Webauthn\\CeremonyStep\\CheckUserWasPresent' => $vendorDir . '/web-auth/webauthn-lib/src/CeremonyStep/CheckUserWasPresent.php',
    '_ContaoManager\\Webauthn\\CeremonyStep\\HostTopOriginValidator' => $vendorDir . '/web-auth/webauthn-lib/src/CeremonyStep/HostTopOriginValidator.php',
    '_ContaoManager\\Webauthn\\CeremonyStep\\TopOriginValidator' => $vendorDir . '/web-auth/webauthn-lib/src/CeremonyStep/TopOriginValidator.php',
    '_ContaoManager\\Webauthn\\CertificateChainChecker\\CertificateChainChecker' => $vendorDir . '/web-auth/webauthn-lib/src/CertificateChainChecker/CertificateChainChecker.php',
    '_ContaoManager\\Webauthn\\CertificateChainChecker\\PhpCertificateChainChecker' => $vendorDir . '/web-auth/webauthn-lib/src/CertificateChainChecker/PhpCertificateChainChecker.php',
    '_ContaoManager\\Webauthn\\CertificateToolbox' => $vendorDir . '/web-auth/webauthn-lib/src/CertificateToolbox.php',
    '_ContaoManager\\Webauthn\\ClientDataCollector\\ClientDataCollector' => $vendorDir . '/web-auth/webauthn-lib/src/ClientDataCollector/ClientDataCollector.php',
    '_ContaoManager\\Webauthn\\ClientDataCollector\\ClientDataCollectorManager' => $vendorDir . '/web-auth/webauthn-lib/src/ClientDataCollector/ClientDataCollectorManager.php',
    '_ContaoManager\\Webauthn\\ClientDataCollector\\WebauthnAuthenticationCollector' => $vendorDir . '/web-auth/webauthn-lib/src/ClientDataCollector/WebauthnAuthenticationCollector.php',
    '_ContaoManager\\Webauthn\\CollectedClientData' => $vendorDir . '/web-auth/webauthn-lib/src/CollectedClientData.php',
    '_ContaoManager\\Webauthn\\Counter\\CounterChecker' => $vendorDir . '/web-auth/webauthn-lib/src/Counter/CounterChecker.php',
    '_ContaoManager\\Webauthn\\Counter\\ThrowExceptionIfInvalid' => $vendorDir . '/web-auth/webauthn-lib/src/Counter/ThrowExceptionIfInvalid.php',
    '_ContaoManager\\Webauthn\\Credential' => $vendorDir . '/web-auth/webauthn-lib/src/Credential.php',
    '_ContaoManager\\Webauthn\\Denormalizer\\AttestationObjectDenormalizer' => $vendorDir . '/web-auth/webauthn-lib/src/Denormalizer/AttestationObjectDenormalizer.php',
    '_ContaoManager\\Webauthn\\Denormalizer\\AttestationStatementDenormalizer' => $vendorDir . '/web-auth/webauthn-lib/src/Denormalizer/AttestationStatementDenormalizer.php',
    '_ContaoManager\\Webauthn\\Denormalizer\\AttestedCredentialDataNormalizer' => $vendorDir . '/web-auth/webauthn-lib/src/Denormalizer/AttestedCredentialDataNormalizer.php',
    '_ContaoManager\\Webauthn\\Denormalizer\\AuthenticationExtensionNormalizer' => $vendorDir . '/web-auth/webauthn-lib/src/Denormalizer/AuthenticationExtensionNormalizer.php',
    '_ContaoManager\\Webauthn\\Denormalizer\\AuthenticationExtensionsDenormalizer' => $vendorDir . '/web-auth/webauthn-lib/src/Denormalizer/AuthenticationExtensionsDenormalizer.php',
    '_ContaoManager\\Webauthn\\Denormalizer\\AuthenticatorAssertionResponseDenormalizer' => $vendorDir . '/web-auth/webauthn-lib/src/Denormalizer/AuthenticatorAssertionResponseDenormalizer.php',
    '_ContaoManager\\Webauthn\\Denormalizer\\AuthenticatorAttestationResponseDenormalizer' => $vendorDir . '/web-auth/webauthn-lib/src/Denormalizer/AuthenticatorAttestationResponseDenormalizer.php',
    '_ContaoManager\\Webauthn\\Denormalizer\\AuthenticatorDataDenormalizer' => $vendorDir . '/web-auth/webauthn-lib/src/Denormalizer/AuthenticatorDataDenormalizer.php',
    '_ContaoManager\\Webauthn\\Denormalizer\\AuthenticatorResponseDenormalizer' => $vendorDir . '/web-auth/webauthn-lib/src/Denormalizer/AuthenticatorResponseDenormalizer.php',
    '_ContaoManager\\Webauthn\\Denormalizer\\CollectedClientDataDenormalizer' => $vendorDir . '/web-auth/webauthn-lib/src/Denormalizer/CollectedClientDataDenormalizer.php',
    '_ContaoManager\\Webauthn\\Denormalizer\\ExtensionDescriptorDenormalizer' => $vendorDir . '/web-auth/webauthn-lib/src/Denormalizer/ExtensionDescriptorDenormalizer.php',
    '_ContaoManager\\Webauthn\\Denormalizer\\PublicKeyCredentialDenormalizer' => $vendorDir . '/web-auth/webauthn-lib/src/Denormalizer/PublicKeyCredentialDenormalizer.php',
    '_ContaoManager\\Webauthn\\Denormalizer\\PublicKeyCredentialDescriptorNormalizer' => $vendorDir . '/web-auth/webauthn-lib/src/Denormalizer/PublicKeyCredentialDescriptorNormalizer.php',
    '_ContaoManager\\Webauthn\\Denormalizer\\PublicKeyCredentialOptionsDenormalizer' => $vendorDir . '/web-auth/webauthn-lib/src/Denormalizer/PublicKeyCredentialOptionsDenormalizer.php',
    '_ContaoManager\\Webauthn\\Denormalizer\\PublicKeyCredentialParametersDenormalizer' => $vendorDir . '/web-auth/webauthn-lib/src/Denormalizer/PublicKeyCredentialParametersDenormalizer.php',
    '_ContaoManager\\Webauthn\\Denormalizer\\PublicKeyCredentialSourceDenormalizer' => $vendorDir . '/web-auth/webauthn-lib/src/Denormalizer/PublicKeyCredentialSourceDenormalizer.php',
    '_ContaoManager\\Webauthn\\Denormalizer\\PublicKeyCredentialUserEntityDenormalizer' => $vendorDir . '/web-auth/webauthn-lib/src/Denormalizer/PublicKeyCredentialUserEntityDenormalizer.php',
    '_ContaoManager\\Webauthn\\Denormalizer\\TrustPathDenormalizer' => $vendorDir . '/web-auth/webauthn-lib/src/Denormalizer/TrustPathDenormalizer.php',
    '_ContaoManager\\Webauthn\\Denormalizer\\VerificationMethodANDCombinationsDenormalizer' => $vendorDir . '/web-auth/webauthn-lib/src/Denormalizer/VerificationMethodANDCombinationsDenormalizer.php',
    '_ContaoManager\\Webauthn\\Denormalizer\\WebauthnSerializerFactory' => $vendorDir . '/web-auth/webauthn-lib/src/Denormalizer/WebauthnSerializerFactory.php',
    '_ContaoManager\\Webauthn\\Event\\AttestationObjectLoaded' => $vendorDir . '/web-auth/webauthn-lib/src/Event/AttestationObjectLoaded.php',
    '_ContaoManager\\Webauthn\\Event\\AttestationStatementLoaded' => $vendorDir . '/web-auth/webauthn-lib/src/Event/AttestationStatementLoaded.php',
    '_ContaoManager\\Webauthn\\Event\\AuthenticatorAssertionResponseValidationFailedEvent' => $vendorDir . '/web-auth/webauthn-lib/src/Event/AuthenticatorAssertionResponseValidationFailedEvent.php',
    '_ContaoManager\\Webauthn\\Event\\AuthenticatorAssertionResponseValidationSucceededEvent' => $vendorDir . '/web-auth/webauthn-lib/src/Event/AuthenticatorAssertionResponseValidationSucceededEvent.php',
    '_ContaoManager\\Webauthn\\Event\\AuthenticatorAttestationResponseValidationFailedEvent' => $vendorDir . '/web-auth/webauthn-lib/src/Event/AuthenticatorAttestationResponseValidationFailedEvent.php',
    '_ContaoManager\\Webauthn\\Event\\AuthenticatorAttestationResponseValidationSucceededEvent' => $vendorDir . '/web-auth/webauthn-lib/src/Event/AuthenticatorAttestationResponseValidationSucceededEvent.php',
    '_ContaoManager\\Webauthn\\Event\\BeforeCertificateChainValidation' => $vendorDir . '/web-auth/webauthn-lib/src/Event/BeforeCertificateChainValidation.php',
    '_ContaoManager\\Webauthn\\Event\\CanDispatchEvents' => $vendorDir . '/web-auth/webauthn-lib/src/Event/CanDispatchEvents.php',
    '_ContaoManager\\Webauthn\\Event\\CertificateChainValidationFailed' => $vendorDir . '/web-auth/webauthn-lib/src/Event/CertificateChainValidationFailed.php',
    '_ContaoManager\\Webauthn\\Event\\CertificateChainValidationSucceeded' => $vendorDir . '/web-auth/webauthn-lib/src/Event/CertificateChainValidationSucceeded.php',
    '_ContaoManager\\Webauthn\\Event\\MetadataStatementFound' => $vendorDir . '/web-auth/webauthn-lib/src/Event/MetadataStatementFound.php',
    '_ContaoManager\\Webauthn\\Event\\NullEventDispatcher' => $vendorDir . '/web-auth/webauthn-lib/src/Event/NullEventDispatcher.php',
    '_ContaoManager\\Webauthn\\Event\\WebauthnEvent' => $vendorDir . '/web-auth/webauthn-lib/src/Event/WebauthnEvent.php',
    '_ContaoManager\\Webauthn\\Exception\\AttestationStatementException' => $vendorDir . '/web-auth/webauthn-lib/src/Exception/AttestationStatementException.php',
    '_ContaoManager\\Webauthn\\Exception\\AttestationStatementLoadingException' => $vendorDir . '/web-auth/webauthn-lib/src/Exception/AttestationStatementLoadingException.php',
    '_ContaoManager\\Webauthn\\Exception\\AttestationStatementVerificationException' => $vendorDir . '/web-auth/webauthn-lib/src/Exception/AttestationStatementVerificationException.php',
    '_ContaoManager\\Webauthn\\Exception\\AuthenticationExtensionException' => $vendorDir . '/web-auth/webauthn-lib/src/Exception/AuthenticationExtensionException.php',
    '_ContaoManager\\Webauthn\\Exception\\AuthenticatorResponseVerificationException' => $vendorDir . '/web-auth/webauthn-lib/src/Exception/AuthenticatorResponseVerificationException.php',
    '_ContaoManager\\Webauthn\\Exception\\CertificateChainException' => $vendorDir . '/web-auth/webauthn-lib/src/Exception/CertificateChainException.php',
    '_ContaoManager\\Webauthn\\Exception\\CertificateException' => $vendorDir . '/web-auth/webauthn-lib/src/Exception/CertificateException.php',
    '_ContaoManager\\Webauthn\\Exception\\CertificateRevocationListException' => $vendorDir . '/web-auth/webauthn-lib/src/Exception/CertificateRevocationListException.php',
    '_ContaoManager\\Webauthn\\Exception\\CounterException' => $vendorDir . '/web-auth/webauthn-lib/src/Exception/CounterException.php',
    '_ContaoManager\\Webauthn\\Exception\\ExpiredCertificateException' => $vendorDir . '/web-auth/webauthn-lib/src/Exception/ExpiredCertificateException.php',
    '_ContaoManager\\Webauthn\\Exception\\InvalidAttestationStatementException' => $vendorDir . '/web-auth/webauthn-lib/src/Exception/InvalidAttestationStatementException.php',
    '_ContaoManager\\Webauthn\\Exception\\InvalidCertificateException' => $vendorDir . '/web-auth/webauthn-lib/src/Exception/InvalidCertificateException.php',
    '_ContaoManager\\Webauthn\\Exception\\InvalidDataException' => $vendorDir . '/web-auth/webauthn-lib/src/Exception/InvalidDataException.php',
    '_ContaoManager\\Webauthn\\Exception\\InvalidTrustPathException' => $vendorDir . '/web-auth/webauthn-lib/src/Exception/InvalidTrustPathException.php',
    '_ContaoManager\\Webauthn\\Exception\\InvalidUserHandleException' => $vendorDir . '/web-auth/webauthn-lib/src/Exception/InvalidUserHandleException.php',
    '_ContaoManager\\Webauthn\\Exception\\MetadataServiceException' => $vendorDir . '/web-auth/webauthn-lib/src/Exception/MetadataServiceException.php',
    '_ContaoManager\\Webauthn\\Exception\\MetadataStatementException' => $vendorDir . '/web-auth/webauthn-lib/src/Exception/MetadataStatementException.php',
    '_ContaoManager\\Webauthn\\Exception\\MetadataStatementLoadingException' => $vendorDir . '/web-auth/webauthn-lib/src/Exception/MetadataStatementLoadingException.php',
    '_ContaoManager\\Webauthn\\Exception\\MissingMetadataStatementException' => $vendorDir . '/web-auth/webauthn-lib/src/Exception/MissingMetadataStatementException.php',
    '_ContaoManager\\Webauthn\\Exception\\RevokedCertificateException' => $vendorDir . '/web-auth/webauthn-lib/src/Exception/RevokedCertificateException.php',
    '_ContaoManager\\Webauthn\\Exception\\UnsupportedFeatureException' => $vendorDir . '/web-auth/webauthn-lib/src/Exception/UnsupportedFeatureException.php',
    '_ContaoManager\\Webauthn\\Exception\\WebauthnException' => $vendorDir . '/web-auth/webauthn-lib/src/Exception/WebauthnException.php',
    '_ContaoManager\\Webauthn\\FakeCredentialGenerator' => $vendorDir . '/web-auth/webauthn-lib/src/FakeCredentialGenerator.php',
    '_ContaoManager\\Webauthn\\MetadataService\\CanLogData' => $vendorDir . '/web-auth/webauthn-lib/src/MetadataService/CanLogData.php',
    '_ContaoManager\\Webauthn\\MetadataService\\CertificateChain\\CertificateChainValidator' => $vendorDir . '/web-auth/webauthn-lib/src/MetadataService/CertificateChain/CertificateChainValidator.php',
    '_ContaoManager\\Webauthn\\MetadataService\\CertificateChain\\CertificateToolbox' => $vendorDir . '/web-auth/webauthn-lib/src/MetadataService/CertificateChain/CertificateToolbox.php',
    '_ContaoManager\\Webauthn\\MetadataService\\CertificateChain\\PhpCertificateChainValidator' => $vendorDir . '/web-auth/webauthn-lib/src/MetadataService/CertificateChain/PhpCertificateChainValidator.php',
    '_ContaoManager\\Webauthn\\MetadataService\\Denormalizer\\ExtensionDescriptorDenormalizer' => $vendorDir . '/web-auth/webauthn-lib/src/MetadataService/Denormalizer/ExtensionDescriptorDenormalizer.php',
    '_ContaoManager\\Webauthn\\MetadataService\\Denormalizer\\MetadataStatementSerializerFactory' => $vendorDir . '/web-auth/webauthn-lib/src/MetadataService/Denormalizer/MetadataStatementSerializerFactory.php',
    '_ContaoManager\\Webauthn\\MetadataService\\Event\\BeforeCertificateChainValidation' => $vendorDir . '/web-auth/webauthn-lib/src/MetadataService/Event/BeforeCertificateChainValidation.php',
    '_ContaoManager\\Webauthn\\MetadataService\\Event\\CanDispatchEvents' => $vendorDir . '/web-auth/webauthn-lib/src/MetadataService/Event/CanDispatchEvents.php',
    '_ContaoManager\\Webauthn\\MetadataService\\Event\\CertificateChainValidationFailed' => $vendorDir . '/web-auth/webauthn-lib/src/MetadataService/Event/CertificateChainValidationFailed.php',
    '_ContaoManager\\Webauthn\\MetadataService\\Event\\CertificateChainValidationSucceeded' => $vendorDir . '/web-auth/webauthn-lib/src/MetadataService/Event/CertificateChainValidationSucceeded.php',
    '_ContaoManager\\Webauthn\\MetadataService\\Event\\MetadataStatementFound' => $vendorDir . '/web-auth/webauthn-lib/src/MetadataService/Event/MetadataStatementFound.php',
    '_ContaoManager\\Webauthn\\MetadataService\\Event\\NullEventDispatcher' => $vendorDir . '/web-auth/webauthn-lib/src/MetadataService/Event/NullEventDispatcher.php',
    '_ContaoManager\\Webauthn\\MetadataService\\Event\\WebauthnEvent' => $vendorDir . '/web-auth/webauthn-lib/src/MetadataService/Event/WebauthnEvent.php',
    '_ContaoManager\\Webauthn\\MetadataService\\Exception\\CertificateChainException' => $vendorDir . '/web-auth/webauthn-lib/src/MetadataService/Exception/CertificateChainException.php',
    '_ContaoManager\\Webauthn\\MetadataService\\Exception\\CertificateException' => $vendorDir . '/web-auth/webauthn-lib/src/MetadataService/Exception/CertificateException.php',
    '_ContaoManager\\Webauthn\\MetadataService\\Exception\\CertificateRevocationListException' => $vendorDir . '/web-auth/webauthn-lib/src/MetadataService/Exception/CertificateRevocationListException.php',
    '_ContaoManager\\Webauthn\\MetadataService\\Exception\\ExpiredCertificateException' => $vendorDir . '/web-auth/webauthn-lib/src/MetadataService/Exception/ExpiredCertificateException.php',
    '_ContaoManager\\Webauthn\\MetadataService\\Exception\\InvalidCertificateException' => $vendorDir . '/web-auth/webauthn-lib/src/MetadataService/Exception/InvalidCertificateException.php',
    '_ContaoManager\\Webauthn\\MetadataService\\Exception\\MetadataServiceException' => $vendorDir . '/web-auth/webauthn-lib/src/MetadataService/Exception/MetadataServiceException.php',
    '_ContaoManager\\Webauthn\\MetadataService\\Exception\\MetadataStatementException' => $vendorDir . '/web-auth/webauthn-lib/src/MetadataService/Exception/MetadataStatementException.php',
    '_ContaoManager\\Webauthn\\MetadataService\\Exception\\MetadataStatementLoadingException' => $vendorDir . '/web-auth/webauthn-lib/src/MetadataService/Exception/MetadataStatementLoadingException.php',
    '_ContaoManager\\Webauthn\\MetadataService\\Exception\\MissingMetadataStatementException' => $vendorDir . '/web-auth/webauthn-lib/src/MetadataService/Exception/MissingMetadataStatementException.php',
    '_ContaoManager\\Webauthn\\MetadataService\\Exception\\RevokedCertificateException' => $vendorDir . '/web-auth/webauthn-lib/src/MetadataService/Exception/RevokedCertificateException.php',
    '_ContaoManager\\Webauthn\\MetadataService\\MetadataStatementRepository' => $vendorDir . '/web-auth/webauthn-lib/src/MetadataService/MetadataStatementRepository.php',
    '_ContaoManager\\Webauthn\\MetadataService\\Psr18HttpClient' => $vendorDir . '/web-auth/webauthn-lib/src/MetadataService/Psr18HttpClient.php',
    '_ContaoManager\\Webauthn\\MetadataService\\Service\\ChainedMetadataServices' => $vendorDir . '/web-auth/webauthn-lib/src/MetadataService/Service/ChainedMetadataServices.php',
    '_ContaoManager\\Webauthn\\MetadataService\\Service\\DistantResourceMetadataService' => $vendorDir . '/web-auth/webauthn-lib/src/MetadataService/Service/DistantResourceMetadataService.php',
    '_ContaoManager\\Webauthn\\MetadataService\\Service\\FidoAllianceCompliantMetadataService' => $vendorDir . '/web-auth/webauthn-lib/src/MetadataService/Service/FidoAllianceCompliantMetadataService.php',
    '_ContaoManager\\Webauthn\\MetadataService\\Service\\FolderResourceMetadataService' => $vendorDir . '/web-auth/webauthn-lib/src/MetadataService/Service/FolderResourceMetadataService.php',
    '_ContaoManager\\Webauthn\\MetadataService\\Service\\InMemoryMetadataService' => $vendorDir . '/web-auth/webauthn-lib/src/MetadataService/Service/InMemoryMetadataService.php',
    '_ContaoManager\\Webauthn\\MetadataService\\Service\\JsonMetadataService' => $vendorDir . '/web-auth/webauthn-lib/src/MetadataService/Service/JsonMetadataService.php',
    '_ContaoManager\\Webauthn\\MetadataService\\Service\\LocalResourceMetadataService' => $vendorDir . '/web-auth/webauthn-lib/src/MetadataService/Service/LocalResourceMetadataService.php',
    '_ContaoManager\\Webauthn\\MetadataService\\Service\\MetadataBLOBPayload' => $vendorDir . '/web-auth/webauthn-lib/src/MetadataService/Service/MetadataBLOBPayload.php',
    '_ContaoManager\\Webauthn\\MetadataService\\Service\\MetadataBLOBPayloadEntry' => $vendorDir . '/web-auth/webauthn-lib/src/MetadataService/Service/MetadataBLOBPayloadEntry.php',
    '_ContaoManager\\Webauthn\\MetadataService\\Service\\MetadataService' => $vendorDir . '/web-auth/webauthn-lib/src/MetadataService/Service/MetadataService.php',
    '_ContaoManager\\Webauthn\\MetadataService\\Service\\StringMetadataService' => $vendorDir . '/web-auth/webauthn-lib/src/MetadataService/Service/StringMetadataService.php',
    '_ContaoManager\\Webauthn\\MetadataService\\Statement\\AbstractDescriptor' => $vendorDir . '/web-auth/webauthn-lib/src/MetadataService/Statement/AbstractDescriptor.php',
    '_ContaoManager\\Webauthn\\MetadataService\\Statement\\AlternativeDescriptions' => $vendorDir . '/web-auth/webauthn-lib/src/MetadataService/Statement/AlternativeDescriptions.php',
    '_ContaoManager\\Webauthn\\MetadataService\\Statement\\AuthenticatorGetInfo' => $vendorDir . '/web-auth/webauthn-lib/src/MetadataService/Statement/AuthenticatorGetInfo.php',
    '_ContaoManager\\Webauthn\\MetadataService\\Statement\\AuthenticatorStatus' => $vendorDir . '/web-auth/webauthn-lib/src/MetadataService/Statement/AuthenticatorStatus.php',
    '_ContaoManager\\Webauthn\\MetadataService\\Statement\\BiometricAccuracyDescriptor' => $vendorDir . '/web-auth/webauthn-lib/src/MetadataService/Statement/BiometricAccuracyDescriptor.php',
    '_ContaoManager\\Webauthn\\MetadataService\\Statement\\BiometricStatusReport' => $vendorDir . '/web-auth/webauthn-lib/src/MetadataService/Statement/BiometricStatusReport.php',
    '_ContaoManager\\Webauthn\\MetadataService\\Statement\\CodeAccuracyDescriptor' => $vendorDir . '/web-auth/webauthn-lib/src/MetadataService/Statement/CodeAccuracyDescriptor.php',
    '_ContaoManager\\Webauthn\\MetadataService\\Statement\\DisplayPNGCharacteristicsDescriptor' => $vendorDir . '/web-auth/webauthn-lib/src/MetadataService/Statement/DisplayPNGCharacteristicsDescriptor.php',
    '_ContaoManager\\Webauthn\\MetadataService\\Statement\\EcdaaTrustAnchor' => $vendorDir . '/web-auth/webauthn-lib/src/MetadataService/Statement/EcdaaTrustAnchor.php',
    '_ContaoManager\\Webauthn\\MetadataService\\Statement\\ExtensionDescriptor' => $vendorDir . '/web-auth/webauthn-lib/src/MetadataService/Statement/ExtensionDescriptor.php',
    '_ContaoManager\\Webauthn\\MetadataService\\Statement\\MetadataStatement' => $vendorDir . '/web-auth/webauthn-lib/src/MetadataService/Statement/MetadataStatement.php',
    '_ContaoManager\\Webauthn\\MetadataService\\Statement\\PatternAccuracyDescriptor' => $vendorDir . '/web-auth/webauthn-lib/src/MetadataService/Statement/PatternAccuracyDescriptor.php',
    '_ContaoManager\\Webauthn\\MetadataService\\Statement\\RgbPaletteEntry' => $vendorDir . '/web-auth/webauthn-lib/src/MetadataService/Statement/RgbPaletteEntry.php',
    '_ContaoManager\\Webauthn\\MetadataService\\Statement\\RogueListEntry' => $vendorDir . '/web-auth/webauthn-lib/src/MetadataService/Statement/RogueListEntry.php',
    '_ContaoManager\\Webauthn\\MetadataService\\Statement\\StatusReport' => $vendorDir . '/web-auth/webauthn-lib/src/MetadataService/Statement/StatusReport.php',
    '_ContaoManager\\Webauthn\\MetadataService\\Statement\\VerificationMethodANDCombinations' => $vendorDir . '/web-auth/webauthn-lib/src/MetadataService/Statement/VerificationMethodANDCombinations.php',
    '_ContaoManager\\Webauthn\\MetadataService\\Statement\\VerificationMethodDescriptor' => $vendorDir . '/web-auth/webauthn-lib/src/MetadataService/Statement/VerificationMethodDescriptor.php',
    '_ContaoManager\\Webauthn\\MetadataService\\Statement\\Version' => $vendorDir . '/web-auth/webauthn-lib/src/MetadataService/Statement/Version.php',
    '_ContaoManager\\Webauthn\\MetadataService\\StatusReportRepository' => $vendorDir . '/web-auth/webauthn-lib/src/MetadataService/StatusReportRepository.php',
    '_ContaoManager\\Webauthn\\MetadataService\\ValueFilter' => $vendorDir . '/web-auth/webauthn-lib/src/MetadataService/ValueFilter.php',
    '_ContaoManager\\Webauthn\\PublicKeyCredential' => $vendorDir . '/web-auth/webauthn-lib/src/PublicKeyCredential.php',
    '_ContaoManager\\Webauthn\\PublicKeyCredentialCreationOptions' => $vendorDir . '/web-auth/webauthn-lib/src/PublicKeyCredentialCreationOptions.php',
    '_ContaoManager\\Webauthn\\PublicKeyCredentialDescriptor' => $vendorDir . '/web-auth/webauthn-lib/src/PublicKeyCredentialDescriptor.php',
    '_ContaoManager\\Webauthn\\PublicKeyCredentialDescriptorCollection' => $vendorDir . '/web-auth/webauthn-lib/src/PublicKeyCredentialDescriptorCollection.php',
    '_ContaoManager\\Webauthn\\PublicKeyCredentialEntity' => $vendorDir . '/web-auth/webauthn-lib/src/PublicKeyCredentialEntity.php',
    '_ContaoManager\\Webauthn\\PublicKeyCredentialLoader' => $vendorDir . '/web-auth/webauthn-lib/src/PublicKeyCredentialLoader.php',
    '_ContaoManager\\Webauthn\\PublicKeyCredentialOptions' => $vendorDir . '/web-auth/webauthn-lib/src/PublicKeyCredentialOptions.php',
    '_ContaoManager\\Webauthn\\PublicKeyCredentialParameters' => $vendorDir . '/web-auth/webauthn-lib/src/PublicKeyCredentialParameters.php',
    '_ContaoManager\\Webauthn\\PublicKeyCredentialRequestOptions' => $vendorDir . '/web-auth/webauthn-lib/src/PublicKeyCredentialRequestOptions.php',
    '_ContaoManager\\Webauthn\\PublicKeyCredentialRpEntity' => $vendorDir . '/web-auth/webauthn-lib/src/PublicKeyCredentialRpEntity.php',
    '_ContaoManager\\Webauthn\\PublicKeyCredentialSource' => $vendorDir . '/web-auth/webauthn-lib/src/PublicKeyCredentialSource.php',
    '_ContaoManager\\Webauthn\\PublicKeyCredentialSourceRepository' => $vendorDir . '/web-auth/webauthn-lib/src/PublicKeyCredentialSourceRepository.php',
    '_ContaoManager\\Webauthn\\PublicKeyCredentialUserEntity' => $vendorDir . '/web-auth/webauthn-lib/src/PublicKeyCredentialUserEntity.php',
    '_ContaoManager\\Webauthn\\SimpleFakeCredentialGenerator' => $vendorDir . '/web-auth/webauthn-lib/src/SimpleFakeCredentialGenerator.php',
    '_ContaoManager\\Webauthn\\StringStream' => $vendorDir . '/web-auth/webauthn-lib/src/StringStream.php',
    '_ContaoManager\\Webauthn\\TokenBinding\\IgnoreTokenBindingHandler' => $vendorDir . '/web-auth/webauthn-lib/src/TokenBinding/IgnoreTokenBindingHandler.php',
    '_ContaoManager\\Webauthn\\TokenBinding\\SecTokenBindingHandler' => $vendorDir . '/web-auth/webauthn-lib/src/TokenBinding/SecTokenBindingHandler.php',
    '_ContaoManager\\Webauthn\\TokenBinding\\TokenBinding' => $vendorDir . '/web-auth/webauthn-lib/src/TokenBinding/TokenBinding.php',
    '_ContaoManager\\Webauthn\\TokenBinding\\TokenBindingHandler' => $vendorDir . '/web-auth/webauthn-lib/src/TokenBinding/TokenBindingHandler.php',
    '_ContaoManager\\Webauthn\\TokenBinding\\TokenBindingNotSupportedHandler' => $vendorDir . '/web-auth/webauthn-lib/src/TokenBinding/TokenBindingNotSupportedHandler.php',
    '_ContaoManager\\Webauthn\\TrustPath\\CertificateTrustPath' => $vendorDir . '/web-auth/webauthn-lib/src/TrustPath/CertificateTrustPath.php',
    '_ContaoManager\\Webauthn\\TrustPath\\EcdaaKeyIdTrustPath' => $vendorDir . '/web-auth/webauthn-lib/src/TrustPath/EcdaaKeyIdTrustPath.php',
    '_ContaoManager\\Webauthn\\TrustPath\\EmptyTrustPath' => $vendorDir . '/web-auth/webauthn-lib/src/TrustPath/EmptyTrustPath.php',
    '_ContaoManager\\Webauthn\\TrustPath\\TrustPath' => $vendorDir . '/web-auth/webauthn-lib/src/TrustPath/TrustPath.php',
    '_ContaoManager\\Webauthn\\TrustPath\\TrustPathLoader' => $vendorDir . '/web-auth/webauthn-lib/src/TrustPath/TrustPathLoader.php',
    '_ContaoManager\\Webauthn\\U2FPublicKey' => $vendorDir . '/web-auth/webauthn-lib/src/U2FPublicKey.php',
    '_ContaoManager\\Webauthn\\Util\\Base64' => $vendorDir . '/web-auth/webauthn-lib/src/Util/Base64.php',
    '_ContaoManager\\Webauthn\\Util\\CoseSignatureFixer' => $vendorDir . '/web-auth/webauthn-lib/src/Util/CoseSignatureFixer.php',
    '_ContaoManager\\Webmozart\\Assert\\Assert' => $vendorDir . '/webmozart/assert/src/Assert.php',
    '_ContaoManager\\Webmozart\\Assert\\InvalidArgumentException' => $vendorDir . '/webmozart/assert/src/InvalidArgumentException.php',
    '_ContaoManager\\Webmozart\\Assert\\Mixin' => $vendorDir . '/webmozart/assert/src/Mixin.php',
    '_ContaoManager\\phpDocumentor\\Reflection\\DocBlock' => $vendorDir . '/phpdocumentor/reflection-docblock/src/DocBlock.php',
    '_ContaoManager\\phpDocumentor\\Reflection\\DocBlockFactory' => $vendorDir . '/phpdocumentor/reflection-docblock/src/DocBlockFactory.php',
    '_ContaoManager\\phpDocumentor\\Reflection\\DocBlockFactoryInterface' => $vendorDir . '/phpdocumentor/reflection-docblock/src/DocBlockFactoryInterface.php',
    '_ContaoManager\\phpDocumentor\\Reflection\\DocBlock\\Description' => $vendorDir . '/phpdocumentor/reflection-docblock/src/DocBlock/Description.php',
    '_ContaoManager\\phpDocumentor\\Reflection\\DocBlock\\DescriptionFactory' => $vendorDir . '/phpdocumentor/reflection-docblock/src/DocBlock/DescriptionFactory.php',
    '_ContaoManager\\phpDocumentor\\Reflection\\DocBlock\\ExampleFinder' => $vendorDir . '/phpdocumentor/reflection-docblock/src/DocBlock/ExampleFinder.php',
    '_ContaoManager\\phpDocumentor\\Reflection\\DocBlock\\Serializer' => $vendorDir . '/phpdocumentor/reflection-docblock/src/DocBlock/Serializer.php',
    '_ContaoManager\\phpDocumentor\\Reflection\\DocBlock\\StandardTagFactory' => $vendorDir . '/phpdocumentor/reflection-docblock/src/DocBlock/StandardTagFactory.php',
    '_ContaoManager\\phpDocumentor\\Reflection\\DocBlock\\Tag' => $vendorDir . '/phpdocumentor/reflection-docblock/src/DocBlock/Tag.php',
    '_ContaoManager\\phpDocumentor\\Reflection\\DocBlock\\TagFactory' => $vendorDir . '/phpdocumentor/reflection-docblock/src/DocBlock/TagFactory.php',
    '_ContaoManager\\phpDocumentor\\Reflection\\DocBlock\\Tags\\Author' => $vendorDir . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Author.php',
    '_ContaoManager\\phpDocumentor\\Reflection\\DocBlock\\Tags\\BaseTag' => $vendorDir . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/BaseTag.php',
    '_ContaoManager\\phpDocumentor\\Reflection\\DocBlock\\Tags\\Covers' => $vendorDir . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Covers.php',
    '_ContaoManager\\phpDocumentor\\Reflection\\DocBlock\\Tags\\Deprecated' => $vendorDir . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Deprecated.php',
    '_ContaoManager\\phpDocumentor\\Reflection\\DocBlock\\Tags\\Example' => $vendorDir . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Example.php',
    '_ContaoManager\\phpDocumentor\\Reflection\\DocBlock\\Tags\\Extends_' => $vendorDir . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Extends_.php',
    '_ContaoManager\\phpDocumentor\\Reflection\\DocBlock\\Tags\\Factory\\AbstractPHPStanFactory' => $vendorDir . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Factory/AbstractPHPStanFactory.php',
    '_ContaoManager\\phpDocumentor\\Reflection\\DocBlock\\Tags\\Factory\\ExtendsFactory' => $vendorDir . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Factory/ExtendsFactory.php',
    '_ContaoManager\\phpDocumentor\\Reflection\\DocBlock\\Tags\\Factory\\Factory' => $vendorDir . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Factory/Factory.php',
    '_ContaoManager\\phpDocumentor\\Reflection\\DocBlock\\Tags\\Factory\\ImplementsFactory' => $vendorDir . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Factory/ImplementsFactory.php',
    '_ContaoManager\\phpDocumentor\\Reflection\\DocBlock\\Tags\\Factory\\MethodFactory' => $vendorDir . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Factory/MethodFactory.php',
    '_ContaoManager\\phpDocumentor\\Reflection\\DocBlock\\Tags\\Factory\\MethodParameterFactory' => $vendorDir . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Factory/MethodParameterFactory.php',
    '_ContaoManager\\phpDocumentor\\Reflection\\DocBlock\\Tags\\Factory\\PHPStanFactory' => $vendorDir . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Factory/PHPStanFactory.php',
    '_ContaoManager\\phpDocumentor\\Reflection\\DocBlock\\Tags\\Factory\\ParamFactory' => $vendorDir . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Factory/ParamFactory.php',
    '_ContaoManager\\phpDocumentor\\Reflection\\DocBlock\\Tags\\Factory\\PropertyFactory' => $vendorDir . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Factory/PropertyFactory.php',
    '_ContaoManager\\phpDocumentor\\Reflection\\DocBlock\\Tags\\Factory\\PropertyReadFactory' => $vendorDir . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Factory/PropertyReadFactory.php',
    '_ContaoManager\\phpDocumentor\\Reflection\\DocBlock\\Tags\\Factory\\PropertyWriteFactory' => $vendorDir . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Factory/PropertyWriteFactory.php',
    '_ContaoManager\\phpDocumentor\\Reflection\\DocBlock\\Tags\\Factory\\ReturnFactory' => $vendorDir . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Factory/ReturnFactory.php',
    '_ContaoManager\\phpDocumentor\\Reflection\\DocBlock\\Tags\\Factory\\StaticMethod' => $vendorDir . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Factory/StaticMethod.php',
    '_ContaoManager\\phpDocumentor\\Reflection\\DocBlock\\Tags\\Factory\\TemplateExtendsFactory' => $vendorDir . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Factory/TemplateExtendsFactory.php',
    '_ContaoManager\\phpDocumentor\\Reflection\\DocBlock\\Tags\\Factory\\TemplateFactory' => $vendorDir . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Factory/TemplateFactory.php',
    '_ContaoManager\\phpDocumentor\\Reflection\\DocBlock\\Tags\\Factory\\TemplateImplementsFactory' => $vendorDir . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Factory/TemplateImplementsFactory.php',
    '_ContaoManager\\phpDocumentor\\Reflection\\DocBlock\\Tags\\Factory\\VarFactory' => $vendorDir . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Factory/VarFactory.php',
    '_ContaoManager\\phpDocumentor\\Reflection\\DocBlock\\Tags\\Formatter' => $vendorDir . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Formatter.php',
    '_ContaoManager\\phpDocumentor\\Reflection\\DocBlock\\Tags\\Formatter\\AlignFormatter' => $vendorDir . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Formatter/AlignFormatter.php',
    '_ContaoManager\\phpDocumentor\\Reflection\\DocBlock\\Tags\\Formatter\\PassthroughFormatter' => $vendorDir . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Formatter/PassthroughFormatter.php',
    '_ContaoManager\\phpDocumentor\\Reflection\\DocBlock\\Tags\\Generic' => $vendorDir . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Generic.php',
    '_ContaoManager\\phpDocumentor\\Reflection\\DocBlock\\Tags\\Implements_' => $vendorDir . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Implements_.php',
    '_ContaoManager\\phpDocumentor\\Reflection\\DocBlock\\Tags\\InvalidTag' => $vendorDir . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/InvalidTag.php',
    '_ContaoManager\\phpDocumentor\\Reflection\\DocBlock\\Tags\\Link' => $vendorDir . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Link.php',
    '_ContaoManager\\phpDocumentor\\Reflection\\DocBlock\\Tags\\Method' => $vendorDir . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Method.php',
    '_ContaoManager\\phpDocumentor\\Reflection\\DocBlock\\Tags\\MethodParameter' => $vendorDir . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/MethodParameter.php',
    '_ContaoManager\\phpDocumentor\\Reflection\\DocBlock\\Tags\\Mixin' => $vendorDir . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Mixin.php',
    '_ContaoManager\\phpDocumentor\\Reflection\\DocBlock\\Tags\\Param' => $vendorDir . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Param.php',
    '_ContaoManager\\phpDocumentor\\Reflection\\DocBlock\\Tags\\Property' => $vendorDir . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Property.php',
    '_ContaoManager\\phpDocumentor\\Reflection\\DocBlock\\Tags\\PropertyRead' => $vendorDir . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/PropertyRead.php',
    '_ContaoManager\\phpDocumentor\\Reflection\\DocBlock\\Tags\\PropertyWrite' => $vendorDir . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/PropertyWrite.php',
    '_ContaoManager\\phpDocumentor\\Reflection\\DocBlock\\Tags\\Reference\\Fqsen' => $vendorDir . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Reference/Fqsen.php',
    '_ContaoManager\\phpDocumentor\\Reflection\\DocBlock\\Tags\\Reference\\Reference' => $vendorDir . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Reference/Reference.php',
    '_ContaoManager\\phpDocumentor\\Reflection\\DocBlock\\Tags\\Reference\\Url' => $vendorDir . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Reference/Url.php',
    '_ContaoManager\\phpDocumentor\\Reflection\\DocBlock\\Tags\\Return_' => $vendorDir . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Return_.php',
    '_ContaoManager\\phpDocumentor\\Reflection\\DocBlock\\Tags\\See' => $vendorDir . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/See.php',
    '_ContaoManager\\phpDocumentor\\Reflection\\DocBlock\\Tags\\Since' => $vendorDir . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Since.php',
    '_ContaoManager\\phpDocumentor\\Reflection\\DocBlock\\Tags\\Source' => $vendorDir . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Source.php',
    '_ContaoManager\\phpDocumentor\\Reflection\\DocBlock\\Tags\\TagWithType' => $vendorDir . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/TagWithType.php',
    '_ContaoManager\\phpDocumentor\\Reflection\\DocBlock\\Tags\\Template' => $vendorDir . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Template.php',
    '_ContaoManager\\phpDocumentor\\Reflection\\DocBlock\\Tags\\TemplateCovariant' => $vendorDir . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/TemplateCovariant.php',
    '_ContaoManager\\phpDocumentor\\Reflection\\DocBlock\\Tags\\TemplateExtends' => $vendorDir . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/TemplateExtends.php',
    '_ContaoManager\\phpDocumentor\\Reflection\\DocBlock\\Tags\\TemplateImplements' => $vendorDir . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/TemplateImplements.php',
    '_ContaoManager\\phpDocumentor\\Reflection\\DocBlock\\Tags\\Throws' => $vendorDir . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Throws.php',
    '_ContaoManager\\phpDocumentor\\Reflection\\DocBlock\\Tags\\Uses' => $vendorDir . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Uses.php',
    '_ContaoManager\\phpDocumentor\\Reflection\\DocBlock\\Tags\\Var_' => $vendorDir . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Var_.php',
    '_ContaoManager\\phpDocumentor\\Reflection\\DocBlock\\Tags\\Version' => $vendorDir . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Version.php',
    '_ContaoManager\\phpDocumentor\\Reflection\\Element' => $vendorDir . '/phpdocumentor/reflection-common/src/Element.php',
    '_ContaoManager\\phpDocumentor\\Reflection\\Exception\\PcreException' => $vendorDir . '/phpdocumentor/reflection-docblock/src/Exception/PcreException.php',
    '_ContaoManager\\phpDocumentor\\Reflection\\File' => $vendorDir . '/phpdocumentor/reflection-common/src/File.php',
    '_ContaoManager\\phpDocumentor\\Reflection\\Fqsen' => $vendorDir . '/phpdocumentor/reflection-common/src/Fqsen.php',
    '_ContaoManager\\phpDocumentor\\Reflection\\FqsenResolver' => $vendorDir . '/phpdocumentor/type-resolver/src/FqsenResolver.php',
    '_ContaoManager\\phpDocumentor\\Reflection\\Location' => $vendorDir . '/phpdocumentor/reflection-common/src/Location.php',
    '_ContaoManager\\phpDocumentor\\Reflection\\Project' => $vendorDir . '/phpdocumentor/reflection-common/src/Project.php',
    '_ContaoManager\\phpDocumentor\\Reflection\\ProjectFactory' => $vendorDir . '/phpdocumentor/reflection-common/src/ProjectFactory.php',
    '_ContaoManager\\phpDocumentor\\Reflection\\PseudoType' => $vendorDir . '/phpdocumentor/type-resolver/src/PseudoType.php',
    '_ContaoManager\\phpDocumentor\\Reflection\\PseudoTypes\\ArrayShape' => $vendorDir . '/phpdocumentor/type-resolver/src/PseudoTypes/ArrayShape.php',
    '_ContaoManager\\phpDocumentor\\Reflection\\PseudoTypes\\ArrayShapeItem' => $vendorDir . '/phpdocumentor/type-resolver/src/PseudoTypes/ArrayShapeItem.php',
    '_ContaoManager\\phpDocumentor\\Reflection\\PseudoTypes\\CallableString' => $vendorDir . '/phpdocumentor/type-resolver/src/PseudoTypes/CallableString.php',
    '_ContaoManager\\phpDocumentor\\Reflection\\PseudoTypes\\Conditional' => $vendorDir . '/phpdocumentor/type-resolver/src/PseudoTypes/Conditional.php',
    '_ContaoManager\\phpDocumentor\\Reflection\\PseudoTypes\\ConditionalForParameter' => $vendorDir . '/phpdocumentor/type-resolver/src/PseudoTypes/ConditionalForParameter.php',
    '_ContaoManager\\phpDocumentor\\Reflection\\PseudoTypes\\ConstExpression' => $vendorDir . '/phpdocumentor/type-resolver/src/PseudoTypes/ConstExpression.php',
    '_ContaoManager\\phpDocumentor\\Reflection\\PseudoTypes\\False_' => $vendorDir . '/phpdocumentor/type-resolver/src/PseudoTypes/False_.php',
    '_ContaoManager\\phpDocumentor\\Reflection\\PseudoTypes\\FloatValue' => $vendorDir . '/phpdocumentor/type-resolver/src/PseudoTypes/FloatValue.php',
    '_ContaoManager\\phpDocumentor\\Reflection\\PseudoTypes\\HtmlEscapedString' => $vendorDir . '/phpdocumentor/type-resolver/src/PseudoTypes/HtmlEscapedString.php',
    '_ContaoManager\\phpDocumentor\\Reflection\\PseudoTypes\\IntMask' => $vendorDir . '/phpdocumentor/type-resolver/src/PseudoTypes/IntMask.php',
    '_ContaoManager\\phpDocumentor\\Reflection\\PseudoTypes\\IntMaskOf' => $vendorDir . '/phpdocumentor/type-resolver/src/PseudoTypes/IntMaskOf.php',
    '_ContaoManager\\phpDocumentor\\Reflection\\PseudoTypes\\IntegerRange' => $vendorDir . '/phpdocumentor/type-resolver/src/PseudoTypes/IntegerRange.php',
    '_ContaoManager\\phpDocumentor\\Reflection\\PseudoTypes\\IntegerValue' => $vendorDir . '/phpdocumentor/type-resolver/src/PseudoTypes/IntegerValue.php',
    '_ContaoManager\\phpDocumentor\\Reflection\\PseudoTypes\\KeyOf' => $vendorDir . '/phpdocumentor/type-resolver/src/PseudoTypes/KeyOf.php',
    '_ContaoManager\\phpDocumentor\\Reflection\\PseudoTypes\\ListShape' => $vendorDir . '/phpdocumentor/type-resolver/src/PseudoTypes/ListShape.php',
    '_ContaoManager\\phpDocumentor\\Reflection\\PseudoTypes\\ListShapeItem' => $vendorDir . '/phpdocumentor/type-resolver/src/PseudoTypes/ListShapeItem.php',
    '_ContaoManager\\phpDocumentor\\Reflection\\PseudoTypes\\List_' => $vendorDir . '/phpdocumentor/type-resolver/src/PseudoTypes/List_.php',
    '_ContaoManager\\phpDocumentor\\Reflection\\PseudoTypes\\LiteralString' => $vendorDir . '/phpdocumentor/type-resolver/src/PseudoTypes/LiteralString.php',
    '_ContaoManager\\phpDocumentor\\Reflection\\PseudoTypes\\LowercaseString' => $vendorDir . '/phpdocumentor/type-resolver/src/PseudoTypes/LowercaseString.php',
    '_ContaoManager\\phpDocumentor\\Reflection\\PseudoTypes\\NegativeInteger' => $vendorDir . '/phpdocumentor/type-resolver/src/PseudoTypes/NegativeInteger.php',
    '_ContaoManager\\phpDocumentor\\Reflection\\PseudoTypes\\NonEmptyArray' => $vendorDir . '/phpdocumentor/type-resolver/src/PseudoTypes/NonEmptyArray.php',
    '_ContaoManager\\phpDocumentor\\Reflection\\PseudoTypes\\NonEmptyList' => $vendorDir . '/phpdocumentor/type-resolver/src/PseudoTypes/NonEmptyList.php',
    '_ContaoManager\\phpDocumentor\\Reflection\\PseudoTypes\\NonEmptyLowercaseString' => $vendorDir . '/phpdocumentor/type-resolver/src/PseudoTypes/NonEmptyLowercaseString.php',
    '_ContaoManager\\phpDocumentor\\Reflection\\PseudoTypes\\NonEmptyString' => $vendorDir . '/phpdocumentor/type-resolver/src/PseudoTypes/NonEmptyString.php',
    '_ContaoManager\\phpDocumentor\\Reflection\\PseudoTypes\\NumericString' => $vendorDir . '/phpdocumentor/type-resolver/src/PseudoTypes/NumericString.php',
    '_ContaoManager\\phpDocumentor\\Reflection\\PseudoTypes\\Numeric_' => $vendorDir . '/phpdocumentor/type-resolver/src/PseudoTypes/Numeric_.php',
    '_ContaoManager\\phpDocumentor\\Reflection\\PseudoTypes\\ObjectShape' => $vendorDir . '/phpdocumentor/type-resolver/src/PseudoTypes/ObjectShape.php',
    '_ContaoManager\\phpDocumentor\\Reflection\\PseudoTypes\\ObjectShapeItem' => $vendorDir . '/phpdocumentor/type-resolver/src/PseudoTypes/ObjectShapeItem.php',
    '_ContaoManager\\phpDocumentor\\Reflection\\PseudoTypes\\OffsetAccess' => $vendorDir . '/phpdocumentor/type-resolver/src/PseudoTypes/OffsetAccess.php',
    '_ContaoManager\\phpDocumentor\\Reflection\\PseudoTypes\\PositiveInteger' => $vendorDir . '/phpdocumentor/type-resolver/src/PseudoTypes/PositiveInteger.php',
    '_ContaoManager\\phpDocumentor\\Reflection\\PseudoTypes\\ShapeItem' => $vendorDir . '/phpdocumentor/type-resolver/src/PseudoTypes/ShapeItem.php',
    '_ContaoManager\\phpDocumentor\\Reflection\\PseudoTypes\\StringValue' => $vendorDir . '/phpdocumentor/type-resolver/src/PseudoTypes/StringValue.php',
    '_ContaoManager\\phpDocumentor\\Reflection\\PseudoTypes\\TraitString' => $vendorDir . '/phpdocumentor/type-resolver/src/PseudoTypes/TraitString.php',
    '_ContaoManager\\phpDocumentor\\Reflection\\PseudoTypes\\True_' => $vendorDir . '/phpdocumentor/type-resolver/src/PseudoTypes/True_.php',
    '_ContaoManager\\phpDocumentor\\Reflection\\PseudoTypes\\ValueOf' => $vendorDir . '/phpdocumentor/type-resolver/src/PseudoTypes/ValueOf.php',
    '_ContaoManager\\phpDocumentor\\Reflection\\Type' => $vendorDir . '/phpdocumentor/type-resolver/src/Type.php',
    '_ContaoManager\\phpDocumentor\\Reflection\\TypeResolver' => $vendorDir . '/phpdocumentor/type-resolver/src/TypeResolver.php',
    '_ContaoManager\\phpDocumentor\\Reflection\\Types\\AbstractList' => $vendorDir . '/phpdocumentor/type-resolver/src/Types/AbstractList.php',
    '_ContaoManager\\phpDocumentor\\Reflection\\Types\\AggregatedType' => $vendorDir . '/phpdocumentor/type-resolver/src/Types/AggregatedType.php',
    '_ContaoManager\\phpDocumentor\\Reflection\\Types\\ArrayKey' => $vendorDir . '/phpdocumentor/type-resolver/src/Types/ArrayKey.php',
    '_ContaoManager\\phpDocumentor\\Reflection\\Types\\Array_' => $vendorDir . '/phpdocumentor/type-resolver/src/Types/Array_.php',
    '_ContaoManager\\phpDocumentor\\Reflection\\Types\\Boolean' => $vendorDir . '/phpdocumentor/type-resolver/src/Types/Boolean.php',
    '_ContaoManager\\phpDocumentor\\Reflection\\Types\\CallableParameter' => $vendorDir . '/phpdocumentor/type-resolver/src/Types/CallableParameter.php',
    '_ContaoManager\\phpDocumentor\\Reflection\\Types\\Callable_' => $vendorDir . '/phpdocumentor/type-resolver/src/Types/Callable_.php',
    '_ContaoManager\\phpDocumentor\\Reflection\\Types\\ClassString' => $vendorDir . '/phpdocumentor/type-resolver/src/Types/ClassString.php',
    '_ContaoManager\\phpDocumentor\\Reflection\\Types\\Collection' => $vendorDir . '/phpdocumentor/type-resolver/src/Types/Collection.php',
    '_ContaoManager\\phpDocumentor\\Reflection\\Types\\Compound' => $vendorDir . '/phpdocumentor/type-resolver/src/Types/Compound.php',
    '_ContaoManager\\phpDocumentor\\Reflection\\Types\\Context' => $vendorDir . '/phpdocumentor/type-resolver/src/Types/Context.php',
    '_ContaoManager\\phpDocumentor\\Reflection\\Types\\ContextFactory' => $vendorDir . '/phpdocumentor/type-resolver/src/Types/ContextFactory.php',
    '_ContaoManager\\phpDocumentor\\Reflection\\Types\\Expression' => $vendorDir . '/phpdocumentor/type-resolver/src/Types/Expression.php',
    '_ContaoManager\\phpDocumentor\\Reflection\\Types\\Float_' => $vendorDir . '/phpdocumentor/type-resolver/src/Types/Float_.php',
    '_ContaoManager\\phpDocumentor\\Reflection\\Types\\Integer' => $vendorDir . '/phpdocumentor/type-resolver/src/Types/Integer.php',
    '_ContaoManager\\phpDocumentor\\Reflection\\Types\\InterfaceString' => $vendorDir . '/phpdocumentor/type-resolver/src/Types/InterfaceString.php',
    '_ContaoManager\\phpDocumentor\\Reflection\\Types\\Intersection' => $vendorDir . '/phpdocumentor/type-resolver/src/Types/Intersection.php',
    '_ContaoManager\\phpDocumentor\\Reflection\\Types\\Iterable_' => $vendorDir . '/phpdocumentor/type-resolver/src/Types/Iterable_.php',
    '_ContaoManager\\phpDocumentor\\Reflection\\Types\\Mixed_' => $vendorDir . '/phpdocumentor/type-resolver/src/Types/Mixed_.php',
    '_ContaoManager\\phpDocumentor\\Reflection\\Types\\Never_' => $vendorDir . '/phpdocumentor/type-resolver/src/Types/Never_.php',
    '_ContaoManager\\phpDocumentor\\Reflection\\Types\\Null_' => $vendorDir . '/phpdocumentor/type-resolver/src/Types/Null_.php',
    '_ContaoManager\\phpDocumentor\\Reflection\\Types\\Nullable' => $vendorDir . '/phpdocumentor/type-resolver/src/Types/Nullable.php',
    '_ContaoManager\\phpDocumentor\\Reflection\\Types\\Object_' => $vendorDir . '/phpdocumentor/type-resolver/src/Types/Object_.php',
    '_ContaoManager\\phpDocumentor\\Reflection\\Types\\Parent_' => $vendorDir . '/phpdocumentor/type-resolver/src/Types/Parent_.php',
    '_ContaoManager\\phpDocumentor\\Reflection\\Types\\Resource_' => $vendorDir . '/phpdocumentor/type-resolver/src/Types/Resource_.php',
    '_ContaoManager\\phpDocumentor\\Reflection\\Types\\Scalar' => $vendorDir . '/phpdocumentor/type-resolver/src/Types/Scalar.php',
    '_ContaoManager\\phpDocumentor\\Reflection\\Types\\Self_' => $vendorDir . '/phpdocumentor/type-resolver/src/Types/Self_.php',
    '_ContaoManager\\phpDocumentor\\Reflection\\Types\\Static_' => $vendorDir . '/phpdocumentor/type-resolver/src/Types/Static_.php',
    '_ContaoManager\\phpDocumentor\\Reflection\\Types\\String_' => $vendorDir . '/phpdocumentor/type-resolver/src/Types/String_.php',
    '_ContaoManager\\phpDocumentor\\Reflection\\Types\\This' => $vendorDir . '/phpdocumentor/type-resolver/src/Types/This.php',
    '_ContaoManager\\phpDocumentor\\Reflection\\Types\\Void_' => $vendorDir . '/phpdocumentor/type-resolver/src/Types/Void_.php',
    '_ContaoManager\\phpDocumentor\\Reflection\\Utils' => $vendorDir . '/phpdocumentor/reflection-docblock/src/Utils.php',
    '_ContaoManager\\studio24\\Rotate\\Delete' => $vendorDir . '/studio24/rotate/src/Delete.php',
    '_ContaoManager\\studio24\\Rotate\\DirectoryIterator' => $vendorDir . '/studio24/rotate/src/DirectoryIterator.php',
    '_ContaoManager\\studio24\\Rotate\\FilenameFormat' => $vendorDir . '/studio24/rotate/src/FilenameFormat.php',
    '_ContaoManager\\studio24\\Rotate\\FilenameFormatException' => $vendorDir . '/studio24/rotate/src/FilenameFormatException.php',
    '_ContaoManager\\studio24\\Rotate\\Rotate' => $vendorDir . '/studio24/rotate/src/Rotate.php',
    '_ContaoManager\\studio24\\Rotate\\RotateAbstract' => $vendorDir . '/studio24/rotate/src/RotateAbstract.php',
    '_ContaoManager\\studio24\\Rotate\\RotateException' => $vendorDir . '/studio24/rotate/src/RotateException.php',
    '_ContaoManager\\' => $vendorDir . '/symfony/cache/Traits/ValueWrapper.php',
);
<?php

// platform_check.php @generated by Composer

$issues = array();

if (!(PHP_VERSION_ID >= 80100)) {
    $issues[] = 'Your Composer dependencies require a PHP version ">= 8.1.0". You are running ' . PHP_VERSION . '.';
}

if ($issues) {
    if (!headers_sent()) {
        header('HTTP/1.1 500 Internal Server Error');
    }
    if (!ini_get('display_errors')) {
        if (PHP_SAPI === 'cli' || PHP_SAPI === 'phpdbg') {
            fwrite(STDERR, 'Composer detected issues in your platform:' . PHP_EOL.PHP_EOL . implode(PHP_EOL, $issues) . PHP_EOL.PHP_EOL);
        } elseif (!headers_sent()) {
            echo 'Composer detected issues in your platform:' . PHP_EOL.PHP_EOL . str_replace('You are running '.PHP_VERSION.'.', '', implode(PHP_EOL, $issues)) . PHP_EOL.PHP_EOL;
        }
    }
    throw new \RuntimeException(
        'Composer detected issues in your platform: ' . implode(' ', $issues)
    );
}
<?php

// autoload_static.php @generated by Composer

namespace Composer\Autoload;

class ComposerStaticInit70603d6d4d667e5d8f93c56c4d3630ec
{
    public static $files = array (
        '6e3fae29631ef280660b3cdad06f25a8' => __DIR__ . '/..' . '/symfony/deprecation-contracts/function.php',
        '0e6d7bf4a5811bfa5cf40c5ccd6fae6a' => __DIR__ . '/..' . '/symfony/polyfill-mbstring/bootstrap.php',
        '320cde22f66dd4f5d3fd621d3e88b98f' => __DIR__ . '/..' . '/symfony/polyfill-ctype/bootstrap.php',
        '662a729f963d39afe703c9d9b7ab4a8c' => __DIR__ . '/..' . '/symfony/polyfill-php83/bootstrap.php',
        '667aeda72477189d0494fecd327c3641' => __DIR__ . '/..' . '/symfony/var-dumper/Resources/functions/dump.php',
        '8825ede83f2f289127722d4e842cf7e8' => __DIR__ . '/..' . '/symfony/polyfill-intl-grapheme/bootstrap.php',
        'e69f7f6ee287b969198c3c9d6777bd38' => __DIR__ . '/..' . '/symfony/polyfill-intl-normalizer/bootstrap.php',
        'b6b991a57620e2fb6b2f66f03fe9ddc2' => __DIR__ . '/..' . '/symfony/string/Resources/functions.php',
        '9d2b9fc6db0f153a0a149fefb182415e' => __DIR__ . '/..' . '/symfony/polyfill-php84/bootstrap.php',
        'ad155f8f1cf0d418fe49e248db8c661b' => __DIR__ . '/..' . '/react/promise/src/functions_include.php',
        '0d59ee240a4cd96ddbb4ff164fccea4d' => __DIR__ . '/..' . '/symfony/polyfill-php73/bootstrap.php',
        'a4a119a56e50fbb293281d9a48007e0e' => __DIR__ . '/..' . '/symfony/polyfill-php80/bootstrap.php',
        '23c18046f52bef3eea034657bafda50f' => __DIR__ . '/..' . '/symfony/polyfill-php81/bootstrap.php',
        '09f6b20656683369174dd6fa83b7e5fb' => __DIR__ . '/..' . '/symfony/polyfill-uuid/bootstrap.php',
        '2203a247e6fda86070a5e4e07aed533a' => __DIR__ . '/..' . '/symfony/clock/Resources/now.php',
        'e39a8b23c42d4e1452234d762b03835a' => __DIR__ . '/..' . '/ramsey/uuid/src/functions.php',
    );

    public static $prefixLengthsPsr4 = array (
        '_' =>
        array (
            '_ContaoManager\\studio24\\Rotate\\' => 31,
            '_ContaoManager\\phpDocumentor\\Reflection\\' => 40,
            '_ContaoManager\\Webmozart\\Assert\\' => 32,
            '_ContaoManager\\Webauthn\\' => 24,
            '_ContaoManager\\Terminal42\\ComposerLockValidator\\' => 48,
            '_ContaoManager\\Symfony\\Contracts\\Service\\' => 41,
            '_ContaoManager\\Symfony\\Contracts\\EventDispatcher\\' => 49,
            '_ContaoManager\\Symfony\\Contracts\\Cache\\' => 39,
            '_ContaoManager\\Symfony\\Component\\Yaml\\' => 38,
            '_ContaoManager\\Symfony\\Component\\VarExporter\\' => 45,
            '_ContaoManager\\Symfony\\Component\\VarDumper\\' => 43,
            '_ContaoManager\\Symfony\\Component\\Uid\\' => 37,
            '_ContaoManager\\Symfony\\Component\\String\\' => 40,
            '_ContaoManager\\Symfony\\Component\\Serializer\\' => 44,
            '_ContaoManager\\Symfony\\Component\\Security\\Http\\' => 47,
            '_ContaoManager\\Symfony\\Component\\Security\\Csrf\\' => 47,
            '_ContaoManager\\Symfony\\Component\\Security\\Core\\' => 47,
            '_ContaoManager\\Symfony\\Component\\Routing\\' => 41,
            '_ContaoManager\\Symfony\\Component\\PropertyInfo\\' => 46,
            '_ContaoManager\\Symfony\\Component\\PropertyAccess\\' => 48,
            '_ContaoManager\\Symfony\\Component\\Process\\' => 41,
            '_ContaoManager\\Symfony\\Component\\PasswordHasher\\' => 48,
            '_ContaoManager\\Symfony\\Component\\HttpKernel\\' => 44,
            '_ContaoManager\\Symfony\\Component\\HttpFoundation\\' => 48,
            '_ContaoManager\\Symfony\\Component\\Finder\\' => 40,
            '_ContaoManager\\Symfony\\Component\\Filesystem\\' => 44,
            '_ContaoManager\\Symfony\\Component\\EventDispatcher\\' => 49,
            '_ContaoManager\\Symfony\\Component\\ErrorHandler\\' => 46,
            '_ContaoManager\\Symfony\\Component\\DependencyInjection\\' => 53,
            '_ContaoManager\\Symfony\\Component\\Console\\' => 41,
            '_ContaoManager\\Symfony\\Component\\Config\\' => 40,
            '_ContaoManager\\Symfony\\Component\\Clock\\' => 39,
            '_ContaoManager\\Symfony\\Component\\Cache\\' => 39,
            '_ContaoManager\\Symfony\\Bundle\\SecurityBundle\\' => 45,
            '_ContaoManager\\Symfony\\Bundle\\MonologBundle\\' => 44,
            '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\' => 46,
            '_ContaoManager\\Symfony\\Bridge\\Monolog\\' => 38,
            '_ContaoManager\\SpomkyLabs\\Pki\\' => 30,
            '_ContaoManager\\Seld\\Signal\\' => 27,
            '_ContaoManager\\Seld\\PharUtils\\' => 30,
            '_ContaoManager\\Seld\\JsonLint\\' => 29,
            '_ContaoManager\\Ramsey\\Uuid\\' => 27,
            '_ContaoManager\\Ramsey\\Collection\\' => 33,
            '_ContaoManager\\Psr\\Log\\' => 23,
            '_ContaoManager\\Psr\\Http\\Message\\' => 32,
            '_ContaoManager\\Psr\\Http\\Client\\' => 31,
            '_ContaoManager\\Psr\\EventDispatcher\\' => 35,
            '_ContaoManager\\Psr\\Container\\' => 29,
            '_ContaoManager\\Psr\\Clock\\' => 25,
            '_ContaoManager\\Psr\\Cache\\' => 25,
            '_ContaoManager\\ParagonIE\\ConstantTime\\' => 38,
            '_ContaoManager\\PHPStan\\PhpDocParser\\' => 36,
            '_ContaoManager\\OTPHP\\' => 21,
            '_ContaoManager\\Monolog\\' => 23,
            '_ContaoManager\\MabeEnum\\' => 24,
            '_ContaoManager\\Lcobucci\\Clock\\' => 30,
            '_ContaoManager\\JsonSchema\\' => 26,
            '_ContaoManager\\Firebase\\JWT\\' => 28,
            '_ContaoManager\\Doctrine\\Deprecations\\' => 37,
            '_ContaoManager\\Crell\\ApiProblem\\' => 32,
            '_ContaoManager\\Cose\\' => 20,
            '_ContaoManager\\Contao\\ManagerApi\\' => 33,
            '_ContaoManager\\CBOR\\' => 20,
            '_ContaoManager\\Brick\\Math\\' => 26,
        ),
        'S' =>
        array (
            'Symfony\\Polyfill\\Uuid\\' => 22,
            'Symfony\\Polyfill\\Php84\\' => 23,
            'Symfony\\Polyfill\\Php83\\' => 23,
            'Symfony\\Polyfill\\Php81\\' => 23,
            'Symfony\\Polyfill\\Php80\\' => 23,
            'Symfony\\Polyfill\\Php73\\' => 23,
            'Symfony\\Polyfill\\Mbstring\\' => 26,
            'Symfony\\Polyfill\\Intl\\Normalizer\\' => 33,
            'Symfony\\Polyfill\\Intl\\Grapheme\\' => 31,
            'Symfony\\Polyfill\\Ctype\\' => 23,
        ),
        'R' =>
        array (
            'React\\Promise\\' => 14,
        ),
        'C' =>
        array (
            'Composer\\XdebugHandler\\' => 23,
            'Composer\\Spdx\\' => 14,
            'Composer\\Semver\\' => 16,
            'Composer\\Pcre\\' => 14,
            'Composer\\MetadataMinifier\\' => 26,
            'Composer\\ClassMapGenerator\\' => 27,
            'Composer\\CaBundle\\' => 18,
            'Composer\\' => 9,
        ),
    );

    public static $prefixDirsPsr4 = array (
        '_ContaoManager\\studio24\\Rotate\\' =>
        array (
            0 => __DIR__ . '/..' . '/studio24/rotate/src',
        ),
        '_ContaoManager\\phpDocumentor\\Reflection\\' =>
        array (
            0 => __DIR__ . '/..' . '/phpdocumentor/reflection-docblock/src',
            1 => __DIR__ . '/..' . '/phpdocumentor/type-resolver/src',
            2 => __DIR__ . '/..' . '/phpdocumentor/reflection-common/src',
        ),
        '_ContaoManager\\Webmozart\\Assert\\' =>
        array (
            0 => __DIR__ . '/..' . '/webmozart/assert/src',
        ),
        '_ContaoManager\\Webauthn\\' =>
        array (
            0 => __DIR__ . '/..' . '/web-auth/webauthn-lib/src',
        ),
        '_ContaoManager\\Terminal42\\ComposerLockValidator\\' =>
        array (
            0 => __DIR__ . '/..' . '/terminal42/composer-lock-validator/src',
        ),
        '_ContaoManager\\Symfony\\Contracts\\Service\\' =>
        array (
            0 => __DIR__ . '/..' . '/symfony/service-contracts',
        ),
        '_ContaoManager\\Symfony\\Contracts\\EventDispatcher\\' =>
        array (
            0 => __DIR__ . '/..' . '/symfony/event-dispatcher-contracts',
        ),
        '_ContaoManager\\Symfony\\Contracts\\Cache\\' =>
        array (
            0 => __DIR__ . '/..' . '/symfony/cache-contracts',
        ),
        '_ContaoManager\\Symfony\\Component\\Yaml\\' =>
        array (
            0 => __DIR__ . '/..' . '/symfony/yaml',
        ),
        '_ContaoManager\\Symfony\\Component\\VarExporter\\' =>
        array (
            0 => __DIR__ . '/..' . '/symfony/var-exporter',
        ),
        '_ContaoManager\\Symfony\\Component\\VarDumper\\' =>
        array (
            0 => __DIR__ . '/..' . '/symfony/var-dumper',
        ),
        '_ContaoManager\\Symfony\\Component\\Uid\\' =>
        array (
            0 => __DIR__ . '/..' . '/symfony/uid',
        ),
        '_ContaoManager\\Symfony\\Component\\String\\' =>
        array (
            0 => __DIR__ . '/..' . '/symfony/string',
        ),
        '_ContaoManager\\Symfony\\Component\\Serializer\\' =>
        array (
            0 => __DIR__ . '/..' . '/symfony/serializer',
        ),
        '_ContaoManager\\Symfony\\Component\\Security\\Http\\' =>
        array (
            0 => __DIR__ . '/..' . '/symfony/security-http',
        ),
        '_ContaoManager\\Symfony\\Component\\Security\\Csrf\\' =>
        array (
            0 => __DIR__ . '/..' . '/symfony/security-csrf',
        ),
        '_ContaoManager\\Symfony\\Component\\Security\\Core\\' =>
        array (
            0 => __DIR__ . '/..' . '/symfony/security-core',
        ),
        '_ContaoManager\\Symfony\\Component\\Routing\\' =>
        array (
            0 => __DIR__ . '/..' . '/symfony/routing',
        ),
        '_ContaoManager\\Symfony\\Component\\PropertyInfo\\' =>
        array (
            0 => __DIR__ . '/..' . '/symfony/property-info',
        ),
        '_ContaoManager\\Symfony\\Component\\PropertyAccess\\' =>
        array (
            0 => __DIR__ . '/..' . '/symfony/property-access',
        ),
        '_ContaoManager\\Symfony\\Component\\Process\\' =>
        array (
            0 => __DIR__ . '/..' . '/symfony/process',
        ),
        '_ContaoManager\\Symfony\\Component\\PasswordHasher\\' =>
        array (
            0 => __DIR__ . '/..' . '/symfony/password-hasher',
        ),
        '_ContaoManager\\Symfony\\Component\\HttpKernel\\' =>
        array (
            0 => __DIR__ . '/..' . '/symfony/http-kernel',
        ),
        '_ContaoManager\\Symfony\\Component\\HttpFoundation\\' =>
        array (
            0 => __DIR__ . '/..' . '/symfony/http-foundation',
        ),
        '_ContaoManager\\Symfony\\Component\\Finder\\' =>
        array (
            0 => __DIR__ . '/..' . '/symfony/finder',
        ),
        '_ContaoManager\\Symfony\\Component\\Filesystem\\' =>
        array (
            0 => __DIR__ . '/..' . '/symfony/filesystem',
        ),
        '_ContaoManager\\Symfony\\Component\\EventDispatcher\\' =>
        array (
            0 => __DIR__ . '/..' . '/symfony/event-dispatcher',
        ),
        '_ContaoManager\\Symfony\\Component\\ErrorHandler\\' =>
        array (
            0 => __DIR__ . '/..' . '/symfony/error-handler',
        ),
        '_ContaoManager\\Symfony\\Component\\DependencyInjection\\' =>
        array (
            0 => __DIR__ . '/..' . '/symfony/dependency-injection',
        ),
        '_ContaoManager\\Symfony\\Component\\Console\\' =>
        array (
            0 => __DIR__ . '/..' . '/symfony/console',
        ),
        '_ContaoManager\\Symfony\\Component\\Config\\' =>
        array (
            0 => __DIR__ . '/..' . '/symfony/config',
        ),
        '_ContaoManager\\Symfony\\Component\\Clock\\' =>
        array (
            0 => __DIR__ . '/..' . '/symfony/clock',
        ),
        '_ContaoManager\\Symfony\\Component\\Cache\\' =>
        array (
            0 => __DIR__ . '/..' . '/symfony/cache',
        ),
        '_ContaoManager\\Symfony\\Bundle\\SecurityBundle\\' =>
        array (
            0 => __DIR__ . '/..' . '/symfony/security-bundle',
        ),
        '_ContaoManager\\Symfony\\Bundle\\MonologBundle\\' =>
        array (
            0 => __DIR__ . '/..' . '/symfony/monolog-bundle/src',
        ),
        '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\' =>
        array (
            0 => __DIR__ . '/..' . '/symfony/framework-bundle',
        ),
        '_ContaoManager\\Symfony\\Bridge\\Monolog\\' =>
        array (
            0 => __DIR__ . '/..' . '/symfony/monolog-bridge',
        ),
        '_ContaoManager\\SpomkyLabs\\Pki\\' =>
        array (
            0 => __DIR__ . '/..' . '/spomky-labs/pki-framework/src',
        ),
        '_ContaoManager\\Seld\\Signal\\' =>
        array (
            0 => __DIR__ . '/..' . '/seld/signal-handler/src',
        ),
        '_ContaoManager\\Seld\\PharUtils\\' =>
        array (
            0 => __DIR__ . '/..' . '/seld/phar-utils/src',
        ),
        '_ContaoManager\\Seld\\JsonLint\\' =>
        array (
            0 => __DIR__ . '/..' . '/seld/jsonlint/src/Seld/JsonLint',
        ),
        '_ContaoManager\\Ramsey\\Uuid\\' =>
        array (
            0 => __DIR__ . '/..' . '/ramsey/uuid/src',
        ),
        '_ContaoManager\\Ramsey\\Collection\\' =>
        array (
            0 => __DIR__ . '/..' . '/ramsey/collection/src',
        ),
        '_ContaoManager\\Psr\\Log\\' =>
        array (
            0 => __DIR__ . '/..' . '/psr/log/src',
        ),
        '_ContaoManager\\Psr\\Http\\Message\\' =>
        array (
            0 => __DIR__ . '/..' . '/psr/http-factory/src',
            1 => __DIR__ . '/..' . '/psr/http-message/src',
        ),
        '_ContaoManager\\Psr\\Http\\Client\\' =>
        array (
            0 => __DIR__ . '/..' . '/psr/http-client/src',
        ),
        '_ContaoManager\\Psr\\EventDispatcher\\' =>
        array (
            0 => __DIR__ . '/..' . '/psr/event-dispatcher/src',
        ),
        '_ContaoManager\\Psr\\Container\\' =>
        array (
            0 => __DIR__ . '/..' . '/psr/container/src',
        ),
        '_ContaoManager\\Psr\\Clock\\' =>
        array (
            0 => __DIR__ . '/..' . '/psr/clock/src',
        ),
        '_ContaoManager\\Psr\\Cache\\' =>
        array (
            0 => __DIR__ . '/..' . '/psr/cache/src',
        ),
        '_ContaoManager\\ParagonIE\\ConstantTime\\' =>
        array (
            0 => __DIR__ . '/..' . '/paragonie/constant_time_encoding/src',
        ),
        '_ContaoManager\\PHPStan\\PhpDocParser\\' =>
        array (
            0 => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src',
        ),
        '_ContaoManager\\OTPHP\\' =>
        array (
            0 => __DIR__ . '/..' . '/spomky-labs/otphp/src',
        ),
        '_ContaoManager\\Monolog\\' =>
        array (
            0 => __DIR__ . '/..' . '/monolog/monolog/src/Monolog',
        ),
        '_ContaoManager\\MabeEnum\\' =>
        array (
            0 => __DIR__ . '/..' . '/marc-mabe/php-enum/src',
        ),
        '_ContaoManager\\Lcobucci\\Clock\\' =>
        array (
            0 => __DIR__ . '/..' . '/lcobucci/clock/src',
        ),
        '_ContaoManager\\JsonSchema\\' =>
        array (
            0 => __DIR__ . '/..' . '/justinrainbow/json-schema/src/JsonSchema',
        ),
        '_ContaoManager\\Firebase\\JWT\\' =>
        array (
            0 => __DIR__ . '/..' . '/firebase/php-jwt/src',
        ),
        '_ContaoManager\\Doctrine\\Deprecations\\' =>
        array (
            0 => __DIR__ . '/..' . '/doctrine/deprecations/src',
        ),
        '_ContaoManager\\Crell\\ApiProblem\\' =>
        array (
            0 => __DIR__ . '/..' . '/crell/api-problem/src',
        ),
        '_ContaoManager\\Cose\\' =>
        array (
            0 => __DIR__ . '/..' . '/web-auth/cose-lib/src',
        ),
        '_ContaoManager\\Contao\\ManagerApi\\' =>
        array (
            0 => __DIR__ . '/../..' . '/api',
        ),
        '_ContaoManager\\CBOR\\' =>
        array (
            0 => __DIR__ . '/..' . '/spomky-labs/cbor-php/src',
        ),
        '_ContaoManager\\Brick\\Math\\' =>
        array (
            0 => __DIR__ . '/..' . '/brick/math/src',
        ),
        'Symfony\\Polyfill\\Uuid\\' =>
        array (
            0 => __DIR__ . '/..' . '/symfony/polyfill-uuid',
        ),
        'Symfony\\Polyfill\\Php84\\' =>
        array (
            0 => __DIR__ . '/..' . '/symfony/polyfill-php84',
        ),
        'Symfony\\Polyfill\\Php83\\' =>
        array (
            0 => __DIR__ . '/..' . '/symfony/polyfill-php83',
        ),
        'Symfony\\Polyfill\\Php81\\' =>
        array (
            0 => __DIR__ . '/..' . '/symfony/polyfill-php81',
        ),
        'Symfony\\Polyfill\\Php80\\' =>
        array (
            0 => __DIR__ . '/..' . '/symfony/polyfill-php80',
        ),
        'Symfony\\Polyfill\\Php73\\' =>
        array (
            0 => __DIR__ . '/..' . '/symfony/polyfill-php73',
        ),
        'Symfony\\Polyfill\\Mbstring\\' =>
        array (
            0 => __DIR__ . '/..' . '/symfony/polyfill-mbstring',
        ),
        'Symfony\\Polyfill\\Intl\\Normalizer\\' =>
        array (
            0 => __DIR__ . '/..' . '/symfony/polyfill-intl-normalizer',
        ),
        'Symfony\\Polyfill\\Intl\\Grapheme\\' =>
        array (
            0 => __DIR__ . '/..' . '/symfony/polyfill-intl-grapheme',
        ),
        'Symfony\\Polyfill\\Ctype\\' =>
        array (
            0 => __DIR__ . '/..' . '/symfony/polyfill-ctype',
        ),
        'React\\Promise\\' =>
        array (
            0 => __DIR__ . '/..' . '/react/promise/src',
        ),
        'Composer\\XdebugHandler\\' =>
        array (
            0 => __DIR__ . '/..' . '/composer/xdebug-handler/src',
        ),
        'Composer\\Spdx\\' =>
        array (
            0 => __DIR__ . '/..' . '/composer/spdx-licenses/src',
        ),
        'Composer\\Semver\\' =>
        array (
            0 => __DIR__ . '/..' . '/composer/semver/src',
        ),
        'Composer\\Pcre\\' =>
        array (
            0 => __DIR__ . '/..' . '/composer/pcre/src',
        ),
        'Composer\\MetadataMinifier\\' =>
        array (
            0 => __DIR__ . '/..' . '/composer/metadata-minifier/src',
        ),
        'Composer\\ClassMapGenerator\\' =>
        array (
            0 => __DIR__ . '/..' . '/composer/class-map-generator/src',
        ),
        'Composer\\CaBundle\\' =>
        array (
            0 => __DIR__ . '/..' . '/composer/ca-bundle/src',
        ),
        'Composer\\' =>
        array (
            0 => __DIR__ . '/..' . '/composer/composer/src/Composer',
        ),
    );

    public static $classMap = array (
        'Attribute' => __DIR__ . '/..' . '/symfony/polyfill-php80/Resources/stubs/Attribute.php',
        'CURLStringFile' => __DIR__ . '/..' . '/symfony/polyfill-php81/Resources/stubs/CURLStringFile.php',
        'Composer\\Advisory\\AuditConfig' => __DIR__ . '/..' . '/composer/composer/src/Composer/Advisory/AuditConfig.php',
        'Composer\\Advisory\\Auditor' => __DIR__ . '/..' . '/composer/composer/src/Composer/Advisory/Auditor.php',
        'Composer\\Advisory\\IgnoredSecurityAdvisory' => __DIR__ . '/..' . '/composer/composer/src/Composer/Advisory/IgnoredSecurityAdvisory.php',
        'Composer\\Advisory\\PartialSecurityAdvisory' => __DIR__ . '/..' . '/composer/composer/src/Composer/Advisory/PartialSecurityAdvisory.php',
        'Composer\\Advisory\\SecurityAdvisory' => __DIR__ . '/..' . '/composer/composer/src/Composer/Advisory/SecurityAdvisory.php',
        'Composer\\Autoload\\AutoloadGenerator' => __DIR__ . '/..' . '/composer/composer/src/Composer/Autoload/AutoloadGenerator.php',
        'Composer\\Autoload\\ClassLoader' => __DIR__ . '/..' . '/composer/composer/src/Composer/Autoload/ClassLoader.php',
        'Composer\\Autoload\\ClassMapGenerator' => __DIR__ . '/..' . '/composer/composer/src/Composer/Autoload/ClassMapGenerator.php',
        'Composer\\CaBundle\\CaBundle' => __DIR__ . '/..' . '/composer/ca-bundle/src/CaBundle.php',
        'Composer\\Cache' => __DIR__ . '/..' . '/composer/composer/src/Composer/Cache.php',
        'Composer\\ClassMapGenerator\\ClassMap' => __DIR__ . '/..' . '/composer/class-map-generator/src/ClassMap.php',
        'Composer\\ClassMapGenerator\\ClassMapGenerator' => __DIR__ . '/..' . '/composer/class-map-generator/src/ClassMapGenerator.php',
        'Composer\\ClassMapGenerator\\FileList' => __DIR__ . '/..' . '/composer/class-map-generator/src/FileList.php',
        'Composer\\ClassMapGenerator\\PhpFileCleaner' => __DIR__ . '/..' . '/composer/class-map-generator/src/PhpFileCleaner.php',
        'Composer\\ClassMapGenerator\\PhpFileParser' => __DIR__ . '/..' . '/composer/class-map-generator/src/PhpFileParser.php',
        'Composer\\Command\\AboutCommand' => __DIR__ . '/..' . '/composer/composer/src/Composer/Command/AboutCommand.php',
        'Composer\\Command\\ArchiveCommand' => __DIR__ . '/..' . '/composer/composer/src/Composer/Command/ArchiveCommand.php',
        'Composer\\Command\\AuditCommand' => __DIR__ . '/..' . '/composer/composer/src/Composer/Command/AuditCommand.php',
        'Composer\\Command\\BaseCommand' => __DIR__ . '/..' . '/composer/composer/src/Composer/Command/BaseCommand.php',
        'Composer\\Command\\BaseConfigCommand' => __DIR__ . '/..' . '/composer/composer/src/Composer/Command/BaseConfigCommand.php',
        'Composer\\Command\\BaseDependencyCommand' => __DIR__ . '/..' . '/composer/composer/src/Composer/Command/BaseDependencyCommand.php',
        'Composer\\Command\\BumpCommand' => __DIR__ . '/..' . '/composer/composer/src/Composer/Command/BumpCommand.php',
        'Composer\\Command\\CheckPlatformReqsCommand' => __DIR__ . '/..' . '/composer/composer/src/Composer/Command/CheckPlatformReqsCommand.php',
        'Composer\\Command\\ClearCacheCommand' => __DIR__ . '/..' . '/composer/composer/src/Composer/Command/ClearCacheCommand.php',
        'Composer\\Command\\CompletionTrait' => __DIR__ . '/..' . '/composer/composer/src/Composer/Command/CompletionTrait.php',
        'Composer\\Command\\ConfigCommand' => __DIR__ . '/..' . '/composer/composer/src/Composer/Command/ConfigCommand.php',
        'Composer\\Command\\CreateProjectCommand' => __DIR__ . '/..' . '/composer/composer/src/Composer/Command/CreateProjectCommand.php',
        'Composer\\Command\\DependsCommand' => __DIR__ . '/..' . '/composer/composer/src/Composer/Command/DependsCommand.php',
        'Composer\\Command\\DiagnoseCommand' => __DIR__ . '/..' . '/composer/composer/src/Composer/Command/DiagnoseCommand.php',
        'Composer\\Command\\DumpAutoloadCommand' => __DIR__ . '/..' . '/composer/composer/src/Composer/Command/DumpAutoloadCommand.php',
        'Composer\\Command\\ExecCommand' => __DIR__ . '/..' . '/composer/composer/src/Composer/Command/ExecCommand.php',
        'Composer\\Command\\FundCommand' => __DIR__ . '/..' . '/composer/composer/src/Composer/Command/FundCommand.php',
        'Composer\\Command\\GlobalCommand' => __DIR__ . '/..' . '/composer/composer/src/Composer/Command/GlobalCommand.php',
        'Composer\\Command\\HomeCommand' => __DIR__ . '/..' . '/composer/composer/src/Composer/Command/HomeCommand.php',
        'Composer\\Command\\InitCommand' => __DIR__ . '/..' . '/composer/composer/src/Composer/Command/InitCommand.php',
        'Composer\\Command\\InstallCommand' => __DIR__ . '/..' . '/composer/composer/src/Composer/Command/InstallCommand.php',
        'Composer\\Command\\LicensesCommand' => __DIR__ . '/..' . '/composer/composer/src/Composer/Command/LicensesCommand.php',
        'Composer\\Command\\OutdatedCommand' => __DIR__ . '/..' . '/composer/composer/src/Composer/Command/OutdatedCommand.php',
        'Composer\\Command\\PackageDiscoveryTrait' => __DIR__ . '/..' . '/composer/composer/src/Composer/Command/PackageDiscoveryTrait.php',
        'Composer\\Command\\ProhibitsCommand' => __DIR__ . '/..' . '/composer/composer/src/Composer/Command/ProhibitsCommand.php',
        'Composer\\Command\\ReinstallCommand' => __DIR__ . '/..' . '/composer/composer/src/Composer/Command/ReinstallCommand.php',
        'Composer\\Command\\RemoveCommand' => __DIR__ . '/..' . '/composer/composer/src/Composer/Command/RemoveCommand.php',
        'Composer\\Command\\RepositoryCommand' => __DIR__ . '/..' . '/composer/composer/src/Composer/Command/RepositoryCommand.php',
        'Composer\\Command\\RequireCommand' => __DIR__ . '/..' . '/composer/composer/src/Composer/Command/RequireCommand.php',
        'Composer\\Command\\RunScriptCommand' => __DIR__ . '/..' . '/composer/composer/src/Composer/Command/RunScriptCommand.php',
        'Composer\\Command\\ScriptAliasCommand' => __DIR__ . '/..' . '/composer/composer/src/Composer/Command/ScriptAliasCommand.php',
        'Composer\\Command\\SearchCommand' => __DIR__ . '/..' . '/composer/composer/src/Composer/Command/SearchCommand.php',
        'Composer\\Command\\SelfUpdateCommand' => __DIR__ . '/..' . '/composer/composer/src/Composer/Command/SelfUpdateCommand.php',
        'Composer\\Command\\ShowCommand' => __DIR__ . '/..' . '/composer/composer/src/Composer/Command/ShowCommand.php',
        'Composer\\Command\\StatusCommand' => __DIR__ . '/..' . '/composer/composer/src/Composer/Command/StatusCommand.php',
        'Composer\\Command\\SuggestsCommand' => __DIR__ . '/..' . '/composer/composer/src/Composer/Command/SuggestsCommand.php',
        'Composer\\Command\\UpdateCommand' => __DIR__ . '/..' . '/composer/composer/src/Composer/Command/UpdateCommand.php',
        'Composer\\Command\\ValidateCommand' => __DIR__ . '/..' . '/composer/composer/src/Composer/Command/ValidateCommand.php',
        'Composer\\Compiler' => __DIR__ . '/..' . '/composer/composer/src/Composer/Compiler.php',
        'Composer\\Composer' => __DIR__ . '/..' . '/composer/composer/src/Composer/Composer.php',
        'Composer\\Config' => __DIR__ . '/..' . '/composer/composer/src/Composer/Config.php',
        'Composer\\Config\\ConfigSourceInterface' => __DIR__ . '/..' . '/composer/composer/src/Composer/Config/ConfigSourceInterface.php',
        'Composer\\Config\\JsonConfigSource' => __DIR__ . '/..' . '/composer/composer/src/Composer/Config/JsonConfigSource.php',
        'Composer\\Console\\Application' => __DIR__ . '/..' . '/composer/composer/src/Composer/Console/Application.php',
        'Composer\\Console\\GithubActionError' => __DIR__ . '/..' . '/composer/composer/src/Composer/Console/GithubActionError.php',
        'Composer\\Console\\HtmlOutputFormatter' => __DIR__ . '/..' . '/composer/composer/src/Composer/Console/HtmlOutputFormatter.php',
        'Composer\\Console\\Input\\InputArgument' => __DIR__ . '/..' . '/composer/composer/src/Composer/Console/Input/InputArgument.php',
        'Composer\\Console\\Input\\InputOption' => __DIR__ . '/..' . '/composer/composer/src/Composer/Console/Input/InputOption.php',
        'Composer\\DependencyResolver\\Decisions' => __DIR__ . '/..' . '/composer/composer/src/Composer/DependencyResolver/Decisions.php',
        'Composer\\DependencyResolver\\DefaultPolicy' => __DIR__ . '/..' . '/composer/composer/src/Composer/DependencyResolver/DefaultPolicy.php',
        'Composer\\DependencyResolver\\GenericRule' => __DIR__ . '/..' . '/composer/composer/src/Composer/DependencyResolver/GenericRule.php',
        'Composer\\DependencyResolver\\LocalRepoTransaction' => __DIR__ . '/..' . '/composer/composer/src/Composer/DependencyResolver/LocalRepoTransaction.php',
        'Composer\\DependencyResolver\\LockTransaction' => __DIR__ . '/..' . '/composer/composer/src/Composer/DependencyResolver/LockTransaction.php',
        'Composer\\DependencyResolver\\MultiConflictRule' => __DIR__ . '/..' . '/composer/composer/src/Composer/DependencyResolver/MultiConflictRule.php',
        'Composer\\DependencyResolver\\Operation\\InstallOperation' => __DIR__ . '/..' . '/composer/composer/src/Composer/DependencyResolver/Operation/InstallOperation.php',
        'Composer\\DependencyResolver\\Operation\\MarkAliasInstalledOperation' => __DIR__ . '/..' . '/composer/composer/src/Composer/DependencyResolver/Operation/MarkAliasInstalledOperation.php',
        'Composer\\DependencyResolver\\Operation\\MarkAliasUninstalledOperation' => __DIR__ . '/..' . '/composer/composer/src/Composer/DependencyResolver/Operation/MarkAliasUninstalledOperation.php',
        'Composer\\DependencyResolver\\Operation\\OperationInterface' => __DIR__ . '/..' . '/composer/composer/src/Composer/DependencyResolver/Operation/OperationInterface.php',
        'Composer\\DependencyResolver\\Operation\\SolverOperation' => __DIR__ . '/..' . '/composer/composer/src/Composer/DependencyResolver/Operation/SolverOperation.php',
        'Composer\\DependencyResolver\\Operation\\UninstallOperation' => __DIR__ . '/..' . '/composer/composer/src/Composer/DependencyResolver/Operation/UninstallOperation.php',
        'Composer\\DependencyResolver\\Operation\\UpdateOperation' => __DIR__ . '/..' . '/composer/composer/src/Composer/DependencyResolver/Operation/UpdateOperation.php',
        'Composer\\DependencyResolver\\PolicyInterface' => __DIR__ . '/..' . '/composer/composer/src/Composer/DependencyResolver/PolicyInterface.php',
        'Composer\\DependencyResolver\\Pool' => __DIR__ . '/..' . '/composer/composer/src/Composer/DependencyResolver/Pool.php',
        'Composer\\DependencyResolver\\PoolBuilder' => __DIR__ . '/..' . '/composer/composer/src/Composer/DependencyResolver/PoolBuilder.php',
        'Composer\\DependencyResolver\\PoolOptimizer' => __DIR__ . '/..' . '/composer/composer/src/Composer/DependencyResolver/PoolOptimizer.php',
        'Composer\\DependencyResolver\\Problem' => __DIR__ . '/..' . '/composer/composer/src/Composer/DependencyResolver/Problem.php',
        'Composer\\DependencyResolver\\Request' => __DIR__ . '/..' . '/composer/composer/src/Composer/DependencyResolver/Request.php',
        'Composer\\DependencyResolver\\Rule' => __DIR__ . '/..' . '/composer/composer/src/Composer/DependencyResolver/Rule.php',
        'Composer\\DependencyResolver\\Rule2Literals' => __DIR__ . '/..' . '/composer/composer/src/Composer/DependencyResolver/Rule2Literals.php',
        'Composer\\DependencyResolver\\RuleSet' => __DIR__ . '/..' . '/composer/composer/src/Composer/DependencyResolver/RuleSet.php',
        'Composer\\DependencyResolver\\RuleSetGenerator' => __DIR__ . '/..' . '/composer/composer/src/Composer/DependencyResolver/RuleSetGenerator.php',
        'Composer\\DependencyResolver\\RuleSetIterator' => __DIR__ . '/..' . '/composer/composer/src/Composer/DependencyResolver/RuleSetIterator.php',
        'Composer\\DependencyResolver\\RuleWatchChain' => __DIR__ . '/..' . '/composer/composer/src/Composer/DependencyResolver/RuleWatchChain.php',
        'Composer\\DependencyResolver\\RuleWatchGraph' => __DIR__ . '/..' . '/composer/composer/src/Composer/DependencyResolver/RuleWatchGraph.php',
        'Composer\\DependencyResolver\\RuleWatchNode' => __DIR__ . '/..' . '/composer/composer/src/Composer/DependencyResolver/RuleWatchNode.php',
        'Composer\\DependencyResolver\\SecurityAdvisoryPoolFilter' => __DIR__ . '/..' . '/composer/composer/src/Composer/DependencyResolver/SecurityAdvisoryPoolFilter.php',
        'Composer\\DependencyResolver\\Solver' => __DIR__ . '/..' . '/composer/composer/src/Composer/DependencyResolver/Solver.php',
        'Composer\\DependencyResolver\\SolverBugException' => __DIR__ . '/..' . '/composer/composer/src/Composer/DependencyResolver/SolverBugException.php',
        'Composer\\DependencyResolver\\SolverProblemsException' => __DIR__ . '/..' . '/composer/composer/src/Composer/DependencyResolver/SolverProblemsException.php',
        'Composer\\DependencyResolver\\Transaction' => __DIR__ . '/..' . '/composer/composer/src/Composer/DependencyResolver/Transaction.php',
        'Composer\\Downloader\\ArchiveDownloader' => __DIR__ . '/..' . '/composer/composer/src/Composer/Downloader/ArchiveDownloader.php',
        'Composer\\Downloader\\ChangeReportInterface' => __DIR__ . '/..' . '/composer/composer/src/Composer/Downloader/ChangeReportInterface.php',
        'Composer\\Downloader\\DownloadManager' => __DIR__ . '/..' . '/composer/composer/src/Composer/Downloader/DownloadManager.php',
        'Composer\\Downloader\\DownloaderInterface' => __DIR__ . '/..' . '/composer/composer/src/Composer/Downloader/DownloaderInterface.php',
        'Composer\\Downloader\\DvcsDownloaderInterface' => __DIR__ . '/..' . '/composer/composer/src/Composer/Downloader/DvcsDownloaderInterface.php',
        'Composer\\Downloader\\FileDownloader' => __DIR__ . '/..' . '/composer/composer/src/Composer/Downloader/FileDownloader.php',
        'Composer\\Downloader\\FilesystemException' => __DIR__ . '/..' . '/composer/composer/src/Composer/Downloader/FilesystemException.php',
        'Composer\\Downloader\\FossilDownloader' => __DIR__ . '/..' . '/composer/composer/src/Composer/Downloader/FossilDownloader.php',
        'Composer\\Downloader\\GitDownloader' => __DIR__ . '/..' . '/composer/composer/src/Composer/Downloader/GitDownloader.php',
        'Composer\\Downloader\\GzipDownloader' => __DIR__ . '/..' . '/composer/composer/src/Composer/Downloader/GzipDownloader.php',
        'Composer\\Downloader\\HgDownloader' => __DIR__ . '/..' . '/composer/composer/src/Composer/Downloader/HgDownloader.php',
        'Composer\\Downloader\\MaxFileSizeExceededException' => __DIR__ . '/..' . '/composer/composer/src/Composer/Downloader/MaxFileSizeExceededException.php',
        'Composer\\Downloader\\PathDownloader' => __DIR__ . '/..' . '/composer/composer/src/Composer/Downloader/PathDownloader.php',
        'Composer\\Downloader\\PerforceDownloader' => __DIR__ . '/..' . '/composer/composer/src/Composer/Downloader/PerforceDownloader.php',
        'Composer\\Downloader\\PharDownloader' => __DIR__ . '/..' . '/composer/composer/src/Composer/Downloader/PharDownloader.php',
        'Composer\\Downloader\\RarDownloader' => __DIR__ . '/..' . '/composer/composer/src/Composer/Downloader/RarDownloader.php',
        'Composer\\Downloader\\SvnDownloader' => __DIR__ . '/..' . '/composer/composer/src/Composer/Downloader/SvnDownloader.php',
        'Composer\\Downloader\\TarDownloader' => __DIR__ . '/..' . '/composer/composer/src/Composer/Downloader/TarDownloader.php',
        'Composer\\Downloader\\TransportException' => __DIR__ . '/..' . '/composer/composer/src/Composer/Downloader/TransportException.php',
        'Composer\\Downloader\\VcsCapableDownloaderInterface' => __DIR__ . '/..' . '/composer/composer/src/Composer/Downloader/VcsCapableDownloaderInterface.php',
        'Composer\\Downloader\\VcsDownloader' => __DIR__ . '/..' . '/composer/composer/src/Composer/Downloader/VcsDownloader.php',
        'Composer\\Downloader\\XzDownloader' => __DIR__ . '/..' . '/composer/composer/src/Composer/Downloader/XzDownloader.php',
        'Composer\\Downloader\\ZipDownloader' => __DIR__ . '/..' . '/composer/composer/src/Composer/Downloader/ZipDownloader.php',
        'Composer\\EventDispatcher\\Event' => __DIR__ . '/..' . '/composer/composer/src/Composer/EventDispatcher/Event.php',
        'Composer\\EventDispatcher\\EventDispatcher' => __DIR__ . '/..' . '/composer/composer/src/Composer/EventDispatcher/EventDispatcher.php',
        'Composer\\EventDispatcher\\EventSubscriberInterface' => __DIR__ . '/..' . '/composer/composer/src/Composer/EventDispatcher/EventSubscriberInterface.php',
        'Composer\\EventDispatcher\\ScriptExecutionException' => __DIR__ . '/..' . '/composer/composer/src/Composer/EventDispatcher/ScriptExecutionException.php',
        'Composer\\Exception\\IrrecoverableDownloadException' => __DIR__ . '/..' . '/composer/composer/src/Composer/Exception/IrrecoverableDownloadException.php',
        'Composer\\Exception\\NoSslException' => __DIR__ . '/..' . '/composer/composer/src/Composer/Exception/NoSslException.php',
        'Composer\\Factory' => __DIR__ . '/..' . '/composer/composer/src/Composer/Factory.php',
        'Composer\\Filter\\PlatformRequirementFilter\\IgnoreAllPlatformRequirementFilter' => __DIR__ . '/..' . '/composer/composer/src/Composer/Filter/PlatformRequirementFilter/IgnoreAllPlatformRequirementFilter.php',
        'Composer\\Filter\\PlatformRequirementFilter\\IgnoreListPlatformRequirementFilter' => __DIR__ . '/..' . '/composer/composer/src/Composer/Filter/PlatformRequirementFilter/IgnoreListPlatformRequirementFilter.php',
        'Composer\\Filter\\PlatformRequirementFilter\\IgnoreNothingPlatformRequirementFilter' => __DIR__ . '/..' . '/composer/composer/src/Composer/Filter/PlatformRequirementFilter/IgnoreNothingPlatformRequirementFilter.php',
        'Composer\\Filter\\PlatformRequirementFilter\\PlatformRequirementFilterFactory' => __DIR__ . '/..' . '/composer/composer/src/Composer/Filter/PlatformRequirementFilter/PlatformRequirementFilterFactory.php',
        'Composer\\Filter\\PlatformRequirementFilter\\PlatformRequirementFilterInterface' => __DIR__ . '/..' . '/composer/composer/src/Composer/Filter/PlatformRequirementFilter/PlatformRequirementFilterInterface.php',
        'Composer\\IO\\BaseIO' => __DIR__ . '/..' . '/composer/composer/src/Composer/IO/BaseIO.php',
        'Composer\\IO\\BufferIO' => __DIR__ . '/..' . '/composer/composer/src/Composer/IO/BufferIO.php',
        'Composer\\IO\\ConsoleIO' => __DIR__ . '/..' . '/composer/composer/src/Composer/IO/ConsoleIO.php',
        'Composer\\IO\\IOInterface' => __DIR__ . '/..' . '/composer/composer/src/Composer/IO/IOInterface.php',
        'Composer\\IO\\NullIO' => __DIR__ . '/..' . '/composer/composer/src/Composer/IO/NullIO.php',
        'Composer\\InstalledVersions' => __DIR__ . '/..' . '/composer/InstalledVersions.php',
        'Composer\\Installer' => __DIR__ . '/..' . '/composer/composer/src/Composer/Installer.php',
        'Composer\\Installer\\BinaryInstaller' => __DIR__ . '/..' . '/composer/composer/src/Composer/Installer/BinaryInstaller.php',
        'Composer\\Installer\\BinaryPresenceInterface' => __DIR__ . '/..' . '/composer/composer/src/Composer/Installer/BinaryPresenceInterface.php',
        'Composer\\Installer\\InstallationManager' => __DIR__ . '/..' . '/composer/composer/src/Composer/Installer/InstallationManager.php',
        'Composer\\Installer\\InstallerEvent' => __DIR__ . '/..' . '/composer/composer/src/Composer/Installer/InstallerEvent.php',
        'Composer\\Installer\\InstallerEvents' => __DIR__ . '/..' . '/composer/composer/src/Composer/Installer/InstallerEvents.php',
        'Composer\\Installer\\InstallerInterface' => __DIR__ . '/..' . '/composer/composer/src/Composer/Installer/InstallerInterface.php',
        'Composer\\Installer\\LibraryInstaller' => __DIR__ . '/..' . '/composer/composer/src/Composer/Installer/LibraryInstaller.php',
        'Composer\\Installer\\MetapackageInstaller' => __DIR__ . '/..' . '/composer/composer/src/Composer/Installer/MetapackageInstaller.php',
        'Composer\\Installer\\NoopInstaller' => __DIR__ . '/..' . '/composer/composer/src/Composer/Installer/NoopInstaller.php',
        'Composer\\Installer\\PackageEvent' => __DIR__ . '/..' . '/composer/composer/src/Composer/Installer/PackageEvent.php',
        'Composer\\Installer\\PackageEvents' => __DIR__ . '/..' . '/composer/composer/src/Composer/Installer/PackageEvents.php',
        'Composer\\Installer\\PluginInstaller' => __DIR__ . '/..' . '/composer/composer/src/Composer/Installer/PluginInstaller.php',
        'Composer\\Installer\\ProjectInstaller' => __DIR__ . '/..' . '/composer/composer/src/Composer/Installer/ProjectInstaller.php',
        'Composer\\Installer\\SuggestedPackagesReporter' => __DIR__ . '/..' . '/composer/composer/src/Composer/Installer/SuggestedPackagesReporter.php',
        'Composer\\Json\\JsonFile' => __DIR__ . '/..' . '/composer/composer/src/Composer/Json/JsonFile.php',
        'Composer\\Json\\JsonFormatter' => __DIR__ . '/..' . '/composer/composer/src/Composer/Json/JsonFormatter.php',
        'Composer\\Json\\JsonManipulator' => __DIR__ . '/..' . '/composer/composer/src/Composer/Json/JsonManipulator.php',
        'Composer\\Json\\JsonValidationException' => __DIR__ . '/..' . '/composer/composer/src/Composer/Json/JsonValidationException.php',
        'Composer\\MetadataMinifier\\MetadataMinifier' => __DIR__ . '/..' . '/composer/metadata-minifier/src/MetadataMinifier.php',
        'Composer\\PHPStan\\ConfigReturnTypeExtension' => __DIR__ . '/..' . '/composer/composer/src/Composer/PHPStan/ConfigReturnTypeExtension.php',
        'Composer\\PHPStan\\RuleReasonDataReturnTypeExtension' => __DIR__ . '/..' . '/composer/composer/src/Composer/PHPStan/RuleReasonDataReturnTypeExtension.php',
        'Composer\\Package\\AliasPackage' => __DIR__ . '/..' . '/composer/composer/src/Composer/Package/AliasPackage.php',
        'Composer\\Package\\Archiver\\ArchivableFilesFilter' => __DIR__ . '/..' . '/composer/composer/src/Composer/Package/Archiver/ArchivableFilesFilter.php',
        'Composer\\Package\\Archiver\\ArchivableFilesFinder' => __DIR__ . '/..' . '/composer/composer/src/Composer/Package/Archiver/ArchivableFilesFinder.php',
        'Composer\\Package\\Archiver\\ArchiveManager' => __DIR__ . '/..' . '/composer/composer/src/Composer/Package/Archiver/ArchiveManager.php',
        'Composer\\Package\\Archiver\\ArchiverInterface' => __DIR__ . '/..' . '/composer/composer/src/Composer/Package/Archiver/ArchiverInterface.php',
        'Composer\\Package\\Archiver\\BaseExcludeFilter' => __DIR__ . '/..' . '/composer/composer/src/Composer/Package/Archiver/BaseExcludeFilter.php',
        'Composer\\Package\\Archiver\\ComposerExcludeFilter' => __DIR__ . '/..' . '/composer/composer/src/Composer/Package/Archiver/ComposerExcludeFilter.php',
        'Composer\\Package\\Archiver\\GitExcludeFilter' => __DIR__ . '/..' . '/composer/composer/src/Composer/Package/Archiver/GitExcludeFilter.php',
        'Composer\\Package\\Archiver\\PharArchiver' => __DIR__ . '/..' . '/composer/composer/src/Composer/Package/Archiver/PharArchiver.php',
        'Composer\\Package\\Archiver\\ZipArchiver' => __DIR__ . '/..' . '/composer/composer/src/Composer/Package/Archiver/ZipArchiver.php',
        'Composer\\Package\\BasePackage' => __DIR__ . '/..' . '/composer/composer/src/Composer/Package/BasePackage.php',
        'Composer\\Package\\Comparer\\Comparer' => __DIR__ . '/..' . '/composer/composer/src/Composer/Package/Comparer/Comparer.php',
        'Composer\\Package\\CompleteAliasPackage' => __DIR__ . '/..' . '/composer/composer/src/Composer/Package/CompleteAliasPackage.php',
        'Composer\\Package\\CompletePackage' => __DIR__ . '/..' . '/composer/composer/src/Composer/Package/CompletePackage.php',
        'Composer\\Package\\CompletePackageInterface' => __DIR__ . '/..' . '/composer/composer/src/Composer/Package/CompletePackageInterface.php',
        'Composer\\Package\\Dumper\\ArrayDumper' => __DIR__ . '/..' . '/composer/composer/src/Composer/Package/Dumper/ArrayDumper.php',
        'Composer\\Package\\Link' => __DIR__ . '/..' . '/composer/composer/src/Composer/Package/Link.php',
        'Composer\\Package\\Loader\\ArrayLoader' => __DIR__ . '/..' . '/composer/composer/src/Composer/Package/Loader/ArrayLoader.php',
        'Composer\\Package\\Loader\\InvalidPackageException' => __DIR__ . '/..' . '/composer/composer/src/Composer/Package/Loader/InvalidPackageException.php',
        'Composer\\Package\\Loader\\JsonLoader' => __DIR__ . '/..' . '/composer/composer/src/Composer/Package/Loader/JsonLoader.php',
        'Composer\\Package\\Loader\\LoaderInterface' => __DIR__ . '/..' . '/composer/composer/src/Composer/Package/Loader/LoaderInterface.php',
        'Composer\\Package\\Loader\\RootPackageLoader' => __DIR__ . '/..' . '/composer/composer/src/Composer/Package/Loader/RootPackageLoader.php',
        'Composer\\Package\\Loader\\ValidatingArrayLoader' => __DIR__ . '/..' . '/composer/composer/src/Composer/Package/Loader/ValidatingArrayLoader.php',
        'Composer\\Package\\Locker' => __DIR__ . '/..' . '/composer/composer/src/Composer/Package/Locker.php',
        'Composer\\Package\\Package' => __DIR__ . '/..' . '/composer/composer/src/Composer/Package/Package.php',
        'Composer\\Package\\PackageInterface' => __DIR__ . '/..' . '/composer/composer/src/Composer/Package/PackageInterface.php',
        'Composer\\Package\\RootAliasPackage' => __DIR__ . '/..' . '/composer/composer/src/Composer/Package/RootAliasPackage.php',
        'Composer\\Package\\RootPackage' => __DIR__ . '/..' . '/composer/composer/src/Composer/Package/RootPackage.php',
        'Composer\\Package\\RootPackageInterface' => __DIR__ . '/..' . '/composer/composer/src/Composer/Package/RootPackageInterface.php',
        'Composer\\Package\\Version\\StabilityFilter' => __DIR__ . '/..' . '/composer/composer/src/Composer/Package/Version/StabilityFilter.php',
        'Composer\\Package\\Version\\VersionBumper' => __DIR__ . '/..' . '/composer/composer/src/Composer/Package/Version/VersionBumper.php',
        'Composer\\Package\\Version\\VersionGuesser' => __DIR__ . '/..' . '/composer/composer/src/Composer/Package/Version/VersionGuesser.php',
        'Composer\\Package\\Version\\VersionParser' => __DIR__ . '/..' . '/composer/composer/src/Composer/Package/Version/VersionParser.php',
        'Composer\\Package\\Version\\VersionSelector' => __DIR__ . '/..' . '/composer/composer/src/Composer/Package/Version/VersionSelector.php',
        'Composer\\PartialComposer' => __DIR__ . '/..' . '/composer/composer/src/Composer/PartialComposer.php',
        'Composer\\Pcre\\MatchAllResult' => __DIR__ . '/..' . '/composer/pcre/src/MatchAllResult.php',
        'Composer\\Pcre\\MatchAllStrictGroupsResult' => __DIR__ . '/..' . '/composer/pcre/src/MatchAllStrictGroupsResult.php',
        'Composer\\Pcre\\MatchAllWithOffsetsResult' => __DIR__ . '/..' . '/composer/pcre/src/MatchAllWithOffsetsResult.php',
        'Composer\\Pcre\\MatchResult' => __DIR__ . '/..' . '/composer/pcre/src/MatchResult.php',
        'Composer\\Pcre\\MatchStrictGroupsResult' => __DIR__ . '/..' . '/composer/pcre/src/MatchStrictGroupsResult.php',
        'Composer\\Pcre\\MatchWithOffsetsResult' => __DIR__ . '/..' . '/composer/pcre/src/MatchWithOffsetsResult.php',
        'Composer\\Pcre\\PHPStan\\InvalidRegexPatternRule' => __DIR__ . '/..' . '/composer/pcre/src/PHPStan/InvalidRegexPatternRule.php',
        'Composer\\Pcre\\PHPStan\\PregMatchFlags' => __DIR__ . '/..' . '/composer/pcre/src/PHPStan/PregMatchFlags.php',
        'Composer\\Pcre\\PHPStan\\PregMatchParameterOutTypeExtension' => __DIR__ . '/..' . '/composer/pcre/src/PHPStan/PregMatchParameterOutTypeExtension.php',
        'Composer\\Pcre\\PHPStan\\PregMatchTypeSpecifyingExtension' => __DIR__ . '/..' . '/composer/pcre/src/PHPStan/PregMatchTypeSpecifyingExtension.php',
        'Composer\\Pcre\\PHPStan\\PregReplaceCallbackClosureTypeExtension' => __DIR__ . '/..' . '/composer/pcre/src/PHPStan/PregReplaceCallbackClosureTypeExtension.php',
        'Composer\\Pcre\\PHPStan\\UnsafeStrictGroupsCallRule' => __DIR__ . '/..' . '/composer/pcre/src/PHPStan/UnsafeStrictGroupsCallRule.php',
        'Composer\\Pcre\\PcreException' => __DIR__ . '/..' . '/composer/pcre/src/PcreException.php',
        'Composer\\Pcre\\Preg' => __DIR__ . '/..' . '/composer/pcre/src/Preg.php',
        'Composer\\Pcre\\Regex' => __DIR__ . '/..' . '/composer/pcre/src/Regex.php',
        'Composer\\Pcre\\ReplaceResult' => __DIR__ . '/..' . '/composer/pcre/src/ReplaceResult.php',
        'Composer\\Pcre\\UnexpectedNullMatchException' => __DIR__ . '/..' . '/composer/pcre/src/UnexpectedNullMatchException.php',
        'Composer\\Platform\\HhvmDetector' => __DIR__ . '/..' . '/composer/composer/src/Composer/Platform/HhvmDetector.php',
        'Composer\\Platform\\Runtime' => __DIR__ . '/..' . '/composer/composer/src/Composer/Platform/Runtime.php',
        'Composer\\Platform\\Version' => __DIR__ . '/..' . '/composer/composer/src/Composer/Platform/Version.php',
        'Composer\\Plugin\\Capability\\Capability' => __DIR__ . '/..' . '/composer/composer/src/Composer/Plugin/Capability/Capability.php',
        'Composer\\Plugin\\Capability\\CommandProvider' => __DIR__ . '/..' . '/composer/composer/src/Composer/Plugin/Capability/CommandProvider.php',
        'Composer\\Plugin\\Capable' => __DIR__ . '/..' . '/composer/composer/src/Composer/Plugin/Capable.php',
        'Composer\\Plugin\\CommandEvent' => __DIR__ . '/..' . '/composer/composer/src/Composer/Plugin/CommandEvent.php',
        'Composer\\Plugin\\PluginBlockedException' => __DIR__ . '/..' . '/composer/composer/src/Composer/Plugin/PluginBlockedException.php',
        'Composer\\Plugin\\PluginEvents' => __DIR__ . '/..' . '/composer/composer/src/Composer/Plugin/PluginEvents.php',
        'Composer\\Plugin\\PluginInterface' => __DIR__ . '/..' . '/composer/composer/src/Composer/Plugin/PluginInterface.php',
        'Composer\\Plugin\\PluginManager' => __DIR__ . '/..' . '/composer/composer/src/Composer/Plugin/PluginManager.php',
        'Composer\\Plugin\\PostFileDownloadEvent' => __DIR__ . '/..' . '/composer/composer/src/Composer/Plugin/PostFileDownloadEvent.php',
        'Composer\\Plugin\\PreCommandRunEvent' => __DIR__ . '/..' . '/composer/composer/src/Composer/Plugin/PreCommandRunEvent.php',
        'Composer\\Plugin\\PreFileDownloadEvent' => __DIR__ . '/..' . '/composer/composer/src/Composer/Plugin/PreFileDownloadEvent.php',
        'Composer\\Plugin\\PrePoolCreateEvent' => __DIR__ . '/..' . '/composer/composer/src/Composer/Plugin/PrePoolCreateEvent.php',
        'Composer\\Question\\StrictConfirmationQuestion' => __DIR__ . '/..' . '/composer/composer/src/Composer/Question/StrictConfirmationQuestion.php',
        'Composer\\Repository\\AdvisoryProviderInterface' => __DIR__ . '/..' . '/composer/composer/src/Composer/Repository/AdvisoryProviderInterface.php',
        'Composer\\Repository\\ArrayRepository' => __DIR__ . '/..' . '/composer/composer/src/Composer/Repository/ArrayRepository.php',
        'Composer\\Repository\\ArtifactRepository' => __DIR__ . '/..' . '/composer/composer/src/Composer/Repository/ArtifactRepository.php',
        'Composer\\Repository\\CanonicalPackagesTrait' => __DIR__ . '/..' . '/composer/composer/src/Composer/Repository/CanonicalPackagesTrait.php',
        'Composer\\Repository\\ComposerRepository' => __DIR__ . '/..' . '/composer/composer/src/Composer/Repository/ComposerRepository.php',
        'Composer\\Repository\\CompositeRepository' => __DIR__ . '/..' . '/composer/composer/src/Composer/Repository/CompositeRepository.php',
        'Composer\\Repository\\ConfigurableRepositoryInterface' => __DIR__ . '/..' . '/composer/composer/src/Composer/Repository/ConfigurableRepositoryInterface.php',
        'Composer\\Repository\\FilesystemRepository' => __DIR__ . '/..' . '/composer/composer/src/Composer/Repository/FilesystemRepository.php',
        'Composer\\Repository\\FilterRepository' => __DIR__ . '/..' . '/composer/composer/src/Composer/Repository/FilterRepository.php',
        'Composer\\Repository\\InstalledArrayRepository' => __DIR__ . '/..' . '/composer/composer/src/Composer/Repository/InstalledArrayRepository.php',
        'Composer\\Repository\\InstalledFilesystemRepository' => __DIR__ . '/..' . '/composer/composer/src/Composer/Repository/InstalledFilesystemRepository.php',
        'Composer\\Repository\\InstalledRepository' => __DIR__ . '/..' . '/composer/composer/src/Composer/Repository/InstalledRepository.php',
        'Composer\\Repository\\InstalledRepositoryInterface' => __DIR__ . '/..' . '/composer/composer/src/Composer/Repository/InstalledRepositoryInterface.php',
        'Composer\\Repository\\InvalidRepositoryException' => __DIR__ . '/..' . '/composer/composer/src/Composer/Repository/InvalidRepositoryException.php',
        'Composer\\Repository\\LockArrayRepository' => __DIR__ . '/..' . '/composer/composer/src/Composer/Repository/LockArrayRepository.php',
        'Composer\\Repository\\PackageRepository' => __DIR__ . '/..' . '/composer/composer/src/Composer/Repository/PackageRepository.php',
        'Composer\\Repository\\PathRepository' => __DIR__ . '/..' . '/composer/composer/src/Composer/Repository/PathRepository.php',
        'Composer\\Repository\\PearRepository' => __DIR__ . '/..' . '/composer/composer/src/Composer/Repository/PearRepository.php',
        'Composer\\Repository\\PlatformRepository' => __DIR__ . '/..' . '/composer/composer/src/Composer/Repository/PlatformRepository.php',
        'Composer\\Repository\\RepositoryFactory' => __DIR__ . '/..' . '/composer/composer/src/Composer/Repository/RepositoryFactory.php',
        'Composer\\Repository\\RepositoryInterface' => __DIR__ . '/..' . '/composer/composer/src/Composer/Repository/RepositoryInterface.php',
        'Composer\\Repository\\RepositoryManager' => __DIR__ . '/..' . '/composer/composer/src/Composer/Repository/RepositoryManager.php',
        'Composer\\Repository\\RepositorySecurityException' => __DIR__ . '/..' . '/composer/composer/src/Composer/Repository/RepositorySecurityException.php',
        'Composer\\Repository\\RepositorySet' => __DIR__ . '/..' . '/composer/composer/src/Composer/Repository/RepositorySet.php',
        'Composer\\Repository\\RepositoryUtils' => __DIR__ . '/..' . '/composer/composer/src/Composer/Repository/RepositoryUtils.php',
        'Composer\\Repository\\RootPackageRepository' => __DIR__ . '/..' . '/composer/composer/src/Composer/Repository/RootPackageRepository.php',
        'Composer\\Repository\\VcsRepository' => __DIR__ . '/..' . '/composer/composer/src/Composer/Repository/VcsRepository.php',
        'Composer\\Repository\\Vcs\\ForgejoDriver' => __DIR__ . '/..' . '/composer/composer/src/Composer/Repository/Vcs/ForgejoDriver.php',
        'Composer\\Repository\\Vcs\\FossilDriver' => __DIR__ . '/..' . '/composer/composer/src/Composer/Repository/Vcs/FossilDriver.php',
        'Composer\\Repository\\Vcs\\GitBitbucketDriver' => __DIR__ . '/..' . '/composer/composer/src/Composer/Repository/Vcs/GitBitbucketDriver.php',
        'Composer\\Repository\\Vcs\\GitDriver' => __DIR__ . '/..' . '/composer/composer/src/Composer/Repository/Vcs/GitDriver.php',
        'Composer\\Repository\\Vcs\\GitHubDriver' => __DIR__ . '/..' . '/composer/composer/src/Composer/Repository/Vcs/GitHubDriver.php',
        'Composer\\Repository\\Vcs\\GitLabDriver' => __DIR__ . '/..' . '/composer/composer/src/Composer/Repository/Vcs/GitLabDriver.php',
        'Composer\\Repository\\Vcs\\HgDriver' => __DIR__ . '/..' . '/composer/composer/src/Composer/Repository/Vcs/HgDriver.php',
        'Composer\\Repository\\Vcs\\PerforceDriver' => __DIR__ . '/..' . '/composer/composer/src/Composer/Repository/Vcs/PerforceDriver.php',
        'Composer\\Repository\\Vcs\\SvnDriver' => __DIR__ . '/..' . '/composer/composer/src/Composer/Repository/Vcs/SvnDriver.php',
        'Composer\\Repository\\Vcs\\VcsDriver' => __DIR__ . '/..' . '/composer/composer/src/Composer/Repository/Vcs/VcsDriver.php',
        'Composer\\Repository\\Vcs\\VcsDriverInterface' => __DIR__ . '/..' . '/composer/composer/src/Composer/Repository/Vcs/VcsDriverInterface.php',
        'Composer\\Repository\\VersionCacheInterface' => __DIR__ . '/..' . '/composer/composer/src/Composer/Repository/VersionCacheInterface.php',
        'Composer\\Repository\\WritableArrayRepository' => __DIR__ . '/..' . '/composer/composer/src/Composer/Repository/WritableArrayRepository.php',
        'Composer\\Repository\\WritableRepositoryInterface' => __DIR__ . '/..' . '/composer/composer/src/Composer/Repository/WritableRepositoryInterface.php',
        'Composer\\Script\\Event' => __DIR__ . '/..' . '/composer/composer/src/Composer/Script/Event.php',
        'Composer\\Script\\ScriptEvents' => __DIR__ . '/..' . '/composer/composer/src/Composer/Script/ScriptEvents.php',
        'Composer\\SelfUpdate\\Keys' => __DIR__ . '/..' . '/composer/composer/src/Composer/SelfUpdate/Keys.php',
        'Composer\\SelfUpdate\\Versions' => __DIR__ . '/..' . '/composer/composer/src/Composer/SelfUpdate/Versions.php',
        'Composer\\Semver\\Comparator' => __DIR__ . '/..' . '/composer/semver/src/Comparator.php',
        'Composer\\Semver\\CompilingMatcher' => __DIR__ . '/..' . '/composer/semver/src/CompilingMatcher.php',
        'Composer\\Semver\\Constraint\\Bound' => __DIR__ . '/..' . '/composer/semver/src/Constraint/Bound.php',
        'Composer\\Semver\\Constraint\\Constraint' => __DIR__ . '/..' . '/composer/semver/src/Constraint/Constraint.php',
        'Composer\\Semver\\Constraint\\ConstraintInterface' => __DIR__ . '/..' . '/composer/semver/src/Constraint/ConstraintInterface.php',
        'Composer\\Semver\\Constraint\\MatchAllConstraint' => __DIR__ . '/..' . '/composer/semver/src/Constraint/MatchAllConstraint.php',
        'Composer\\Semver\\Constraint\\MatchNoneConstraint' => __DIR__ . '/..' . '/composer/semver/src/Constraint/MatchNoneConstraint.php',
        'Composer\\Semver\\Constraint\\MultiConstraint' => __DIR__ . '/..' . '/composer/semver/src/Constraint/MultiConstraint.php',
        'Composer\\Semver\\Interval' => __DIR__ . '/..' . '/composer/semver/src/Interval.php',
        'Composer\\Semver\\Intervals' => __DIR__ . '/..' . '/composer/semver/src/Intervals.php',
        'Composer\\Semver\\Semver' => __DIR__ . '/..' . '/composer/semver/src/Semver.php',
        'Composer\\Semver\\VersionParser' => __DIR__ . '/..' . '/composer/semver/src/VersionParser.php',
        'Composer\\Spdx\\SpdxLicenses' => __DIR__ . '/..' . '/composer/spdx-licenses/src/SpdxLicenses.php',
        'Composer\\Util\\AuthHelper' => __DIR__ . '/..' . '/composer/composer/src/Composer/Util/AuthHelper.php',
        'Composer\\Util\\Bitbucket' => __DIR__ . '/..' . '/composer/composer/src/Composer/Util/Bitbucket.php',
        'Composer\\Util\\ComposerMirror' => __DIR__ . '/..' . '/composer/composer/src/Composer/Util/ComposerMirror.php',
        'Composer\\Util\\ConfigValidator' => __DIR__ . '/..' . '/composer/composer/src/Composer/Util/ConfigValidator.php',
        'Composer\\Util\\ErrorHandler' => __DIR__ . '/..' . '/composer/composer/src/Composer/Util/ErrorHandler.php',
        'Composer\\Util\\Filesystem' => __DIR__ . '/..' . '/composer/composer/src/Composer/Util/Filesystem.php',
        'Composer\\Util\\Forgejo' => __DIR__ . '/..' . '/composer/composer/src/Composer/Util/Forgejo.php',
        'Composer\\Util\\ForgejoRepositoryData' => __DIR__ . '/..' . '/composer/composer/src/Composer/Util/ForgejoRepositoryData.php',
        'Composer\\Util\\ForgejoUrl' => __DIR__ . '/..' . '/composer/composer/src/Composer/Util/ForgejoUrl.php',
        'Composer\\Util\\Git' => __DIR__ . '/..' . '/composer/composer/src/Composer/Util/Git.php',
        'Composer\\Util\\GitHub' => __DIR__ . '/..' . '/composer/composer/src/Composer/Util/GitHub.php',
        'Composer\\Util\\GitLab' => __DIR__ . '/..' . '/composer/composer/src/Composer/Util/GitLab.php',
        'Composer\\Util\\Hg' => __DIR__ . '/..' . '/composer/composer/src/Composer/Util/Hg.php',
        'Composer\\Util\\HttpDownloader' => __DIR__ . '/..' . '/composer/composer/src/Composer/Util/HttpDownloader.php',
        'Composer\\Util\\Http\\CurlDownloader' => __DIR__ . '/..' . '/composer/composer/src/Composer/Util/Http/CurlDownloader.php',
        'Composer\\Util\\Http\\CurlResponse' => __DIR__ . '/..' . '/composer/composer/src/Composer/Util/Http/CurlResponse.php',
        'Composer\\Util\\Http\\ProxyItem' => __DIR__ . '/..' . '/composer/composer/src/Composer/Util/Http/ProxyItem.php',
        'Composer\\Util\\Http\\ProxyManager' => __DIR__ . '/..' . '/composer/composer/src/Composer/Util/Http/ProxyManager.php',
        'Composer\\Util\\Http\\RequestProxy' => __DIR__ . '/..' . '/composer/composer/src/Composer/Util/Http/RequestProxy.php',
        'Composer\\Util\\Http\\Response' => __DIR__ . '/..' . '/composer/composer/src/Composer/Util/Http/Response.php',
        'Composer\\Util\\IniHelper' => __DIR__ . '/..' . '/composer/composer/src/Composer/Util/IniHelper.php',
        'Composer\\Util\\Loop' => __DIR__ . '/..' . '/composer/composer/src/Composer/Util/Loop.php',
        'Composer\\Util\\MetadataMinifier' => __DIR__ . '/..' . '/composer/composer/src/Composer/Util/MetadataMinifier.php',
        'Composer\\Util\\NoProxyPattern' => __DIR__ . '/..' . '/composer/composer/src/Composer/Util/NoProxyPattern.php',
        'Composer\\Util\\PackageInfo' => __DIR__ . '/..' . '/composer/composer/src/Composer/Util/PackageInfo.php',
        'Composer\\Util\\PackageSorter' => __DIR__ . '/..' . '/composer/composer/src/Composer/Util/PackageSorter.php',
        'Composer\\Util\\Perforce' => __DIR__ . '/..' . '/composer/composer/src/Composer/Util/Perforce.php',
        'Composer\\Util\\Platform' => __DIR__ . '/..' . '/composer/composer/src/Composer/Util/Platform.php',
        'Composer\\Util\\ProcessExecutor' => __DIR__ . '/..' . '/composer/composer/src/Composer/Util/ProcessExecutor.php',
        'Composer\\Util\\RemoteFilesystem' => __DIR__ . '/..' . '/composer/composer/src/Composer/Util/RemoteFilesystem.php',
        'Composer\\Util\\Silencer' => __DIR__ . '/..' . '/composer/composer/src/Composer/Util/Silencer.php',
        'Composer\\Util\\StreamContextFactory' => __DIR__ . '/..' . '/composer/composer/src/Composer/Util/StreamContextFactory.php',
        'Composer\\Util\\Svn' => __DIR__ . '/..' . '/composer/composer/src/Composer/Util/Svn.php',
        'Composer\\Util\\SyncHelper' => __DIR__ . '/..' . '/composer/composer/src/Composer/Util/SyncHelper.php',
        'Composer\\Util\\Tar' => __DIR__ . '/..' . '/composer/composer/src/Composer/Util/Tar.php',
        'Composer\\Util\\TlsHelper' => __DIR__ . '/..' . '/composer/composer/src/Composer/Util/TlsHelper.php',
        'Composer\\Util\\Url' => __DIR__ . '/..' . '/composer/composer/src/Composer/Util/Url.php',
        'Composer\\Util\\Zip' => __DIR__ . '/..' . '/composer/composer/src/Composer/Util/Zip.php',
        'Composer\\XdebugHandler\\PhpConfig' => __DIR__ . '/..' . '/composer/xdebug-handler/src/PhpConfig.php',
        'Composer\\XdebugHandler\\Process' => __DIR__ . '/..' . '/composer/xdebug-handler/src/Process.php',
        'Composer\\XdebugHandler\\Status' => __DIR__ . '/..' . '/composer/xdebug-handler/src/Status.php',
        'Composer\\XdebugHandler\\XdebugHandler' => __DIR__ . '/..' . '/composer/xdebug-handler/src/XdebugHandler.php',
        'DateError' => __DIR__ . '/..' . '/symfony/polyfill-php83/Resources/stubs/DateError.php',
        'DateException' => __DIR__ . '/..' . '/symfony/polyfill-php83/Resources/stubs/DateException.php',
        'DateInvalidOperationException' => __DIR__ . '/..' . '/symfony/polyfill-php83/Resources/stubs/DateInvalidOperationException.php',
        'DateInvalidTimeZoneException' => __DIR__ . '/..' . '/symfony/polyfill-php83/Resources/stubs/DateInvalidTimeZoneException.php',
        'DateMalformedIntervalStringException' => __DIR__ . '/..' . '/symfony/polyfill-php83/Resources/stubs/DateMalformedIntervalStringException.php',
        'DateMalformedPeriodStringException' => __DIR__ . '/..' . '/symfony/polyfill-php83/Resources/stubs/DateMalformedPeriodStringException.php',
        'DateMalformedStringException' => __DIR__ . '/..' . '/symfony/polyfill-php83/Resources/stubs/DateMalformedStringException.php',
        'DateObjectError' => __DIR__ . '/..' . '/symfony/polyfill-php83/Resources/stubs/DateObjectError.php',
        'DateRangeError' => __DIR__ . '/..' . '/symfony/polyfill-php83/Resources/stubs/DateRangeError.php',
        'Deprecated' => __DIR__ . '/..' . '/symfony/polyfill-php84/Resources/stubs/Deprecated.php',
        'JsonException' => __DIR__ . '/..' . '/symfony/polyfill-php73/Resources/stubs/JsonException.php',
        'Normalizer' => __DIR__ . '/..' . '/symfony/polyfill-intl-normalizer/Resources/stubs/Normalizer.php',
        'Override' => __DIR__ . '/..' . '/symfony/polyfill-php83/Resources/stubs/Override.php',
        'Pdo\\Dblib' => __DIR__ . '/..' . '/symfony/polyfill-php84/Resources/stubs/Pdo/Dblib.php',
        'Pdo\\Firebird' => __DIR__ . '/..' . '/symfony/polyfill-php84/Resources/stubs/Pdo/Firebird.php',
        'Pdo\\Mysql' => __DIR__ . '/..' . '/symfony/polyfill-php84/Resources/stubs/Pdo/Mysql.php',
        'Pdo\\Odbc' => __DIR__ . '/..' . '/symfony/polyfill-php84/Resources/stubs/Pdo/Odbc.php',
        'Pdo\\Pgsql' => __DIR__ . '/..' . '/symfony/polyfill-php84/Resources/stubs/Pdo/Pgsql.php',
        'Pdo\\Sqlite' => __DIR__ . '/..' . '/symfony/polyfill-php84/Resources/stubs/Pdo/Sqlite.php',
        'PhpToken' => __DIR__ . '/..' . '/symfony/polyfill-php80/Resources/stubs/PhpToken.php',
        'React\\Promise\\Deferred' => __DIR__ . '/..' . '/react/promise/src/Deferred.php',
        'React\\Promise\\Exception\\CompositeException' => __DIR__ . '/..' . '/react/promise/src/Exception/CompositeException.php',
        'React\\Promise\\Exception\\LengthException' => __DIR__ . '/..' . '/react/promise/src/Exception/LengthException.php',
        'React\\Promise\\Internal\\CancellationQueue' => __DIR__ . '/..' . '/react/promise/src/Internal/CancellationQueue.php',
        'React\\Promise\\Internal\\FulfilledPromise' => __DIR__ . '/..' . '/react/promise/src/Internal/FulfilledPromise.php',
        'React\\Promise\\Internal\\RejectedPromise' => __DIR__ . '/..' . '/react/promise/src/Internal/RejectedPromise.php',
        'React\\Promise\\Promise' => __DIR__ . '/..' . '/react/promise/src/Promise.php',
        'React\\Promise\\PromiseInterface' => __DIR__ . '/..' . '/react/promise/src/PromiseInterface.php',
        'ReflectionConstant' => __DIR__ . '/..' . '/symfony/polyfill-php84/Resources/stubs/ReflectionConstant.php',
        'ReturnTypeWillChange' => __DIR__ . '/..' . '/symfony/polyfill-php81/Resources/stubs/ReturnTypeWillChange.php',
        'RoundingMode' => __DIR__ . '/..' . '/symfony/polyfill-php84/Resources/stubs/RoundingMode.php',
        'SQLite3Exception' => __DIR__ . '/..' . '/symfony/polyfill-php83/Resources/stubs/SQLite3Exception.php',
        'Stringable' => __DIR__ . '/..' . '/symfony/polyfill-php80/Resources/stubs/Stringable.php',
        'Symfony\\Polyfill\\Ctype\\Ctype' => __DIR__ . '/..' . '/symfony/polyfill-ctype/Ctype.php',
        'Symfony\\Polyfill\\Intl\\Grapheme\\Grapheme' => __DIR__ . '/..' . '/symfony/polyfill-intl-grapheme/Grapheme.php',
        'Symfony\\Polyfill\\Intl\\Normalizer\\Normalizer' => __DIR__ . '/..' . '/symfony/polyfill-intl-normalizer/Normalizer.php',
        'Symfony\\Polyfill\\Mbstring\\Mbstring' => __DIR__ . '/..' . '/symfony/polyfill-mbstring/Mbstring.php',
        'Symfony\\Polyfill\\Php73\\Php73' => __DIR__ . '/..' . '/symfony/polyfill-php73/Php73.php',
        'Symfony\\Polyfill\\Php80\\Php80' => __DIR__ . '/..' . '/symfony/polyfill-php80/Php80.php',
        'Symfony\\Polyfill\\Php80\\PhpToken' => __DIR__ . '/..' . '/symfony/polyfill-php80/PhpToken.php',
        'Symfony\\Polyfill\\Php81\\Php81' => __DIR__ . '/..' . '/symfony/polyfill-php81/Php81.php',
        'Symfony\\Polyfill\\Php83\\Php83' => __DIR__ . '/..' . '/symfony/polyfill-php83/Php83.php',
        'Symfony\\Polyfill\\Php84\\Php84' => __DIR__ . '/..' . '/symfony/polyfill-php84/Php84.php',
        'Symfony\\Polyfill\\Uuid\\Uuid' => __DIR__ . '/..' . '/symfony/polyfill-uuid/Uuid.php',
        'UnhandledMatchError' => __DIR__ . '/..' . '/symfony/polyfill-php80/Resources/stubs/UnhandledMatchError.php',
        'ValueError' => __DIR__ . '/..' . '/symfony/polyfill-php80/Resources/stubs/ValueError.php',
        '_ContaoManager\\Brick\\Math\\BigDecimal' => __DIR__ . '/..' . '/brick/math/src/BigDecimal.php',
        '_ContaoManager\\Brick\\Math\\BigInteger' => __DIR__ . '/..' . '/brick/math/src/BigInteger.php',
        '_ContaoManager\\Brick\\Math\\BigNumber' => __DIR__ . '/..' . '/brick/math/src/BigNumber.php',
        '_ContaoManager\\Brick\\Math\\BigRational' => __DIR__ . '/..' . '/brick/math/src/BigRational.php',
        '_ContaoManager\\Brick\\Math\\Exception\\DivisionByZeroException' => __DIR__ . '/..' . '/brick/math/src/Exception/DivisionByZeroException.php',
        '_ContaoManager\\Brick\\Math\\Exception\\IntegerOverflowException' => __DIR__ . '/..' . '/brick/math/src/Exception/IntegerOverflowException.php',
        '_ContaoManager\\Brick\\Math\\Exception\\MathException' => __DIR__ . '/..' . '/brick/math/src/Exception/MathException.php',
        '_ContaoManager\\Brick\\Math\\Exception\\NegativeNumberException' => __DIR__ . '/..' . '/brick/math/src/Exception/NegativeNumberException.php',
        '_ContaoManager\\Brick\\Math\\Exception\\NumberFormatException' => __DIR__ . '/..' . '/brick/math/src/Exception/NumberFormatException.php',
        '_ContaoManager\\Brick\\Math\\Exception\\RoundingNecessaryException' => __DIR__ . '/..' . '/brick/math/src/Exception/RoundingNecessaryException.php',
        '_ContaoManager\\Brick\\Math\\Internal\\Calculator' => __DIR__ . '/..' . '/brick/math/src/Internal/Calculator.php',
        '_ContaoManager\\Brick\\Math\\Internal\\Calculator\\BcMathCalculator' => __DIR__ . '/..' . '/brick/math/src/Internal/Calculator/BcMathCalculator.php',
        '_ContaoManager\\Brick\\Math\\Internal\\Calculator\\GmpCalculator' => __DIR__ . '/..' . '/brick/math/src/Internal/Calculator/GmpCalculator.php',
        '_ContaoManager\\Brick\\Math\\Internal\\Calculator\\NativeCalculator' => __DIR__ . '/..' . '/brick/math/src/Internal/Calculator/NativeCalculator.php',
        '_ContaoManager\\Brick\\Math\\RoundingMode' => __DIR__ . '/..' . '/brick/math/src/RoundingMode.php',
        '_ContaoManager\\CBOR\\AbstractCBORObject' => __DIR__ . '/..' . '/spomky-labs/cbor-php/src/AbstractCBORObject.php',
        '_ContaoManager\\CBOR\\ByteStringObject' => __DIR__ . '/..' . '/spomky-labs/cbor-php/src/ByteStringObject.php',
        '_ContaoManager\\CBOR\\CBORObject' => __DIR__ . '/..' . '/spomky-labs/cbor-php/src/CBORObject.php',
        '_ContaoManager\\CBOR\\Decoder' => __DIR__ . '/..' . '/spomky-labs/cbor-php/src/Decoder.php',
        '_ContaoManager\\CBOR\\DecoderInterface' => __DIR__ . '/..' . '/spomky-labs/cbor-php/src/DecoderInterface.php',
        '_ContaoManager\\CBOR\\Encoder' => __DIR__ . '/..' . '/spomky-labs/cbor-php/src/Encoder.php',
        '_ContaoManager\\CBOR\\EncoderInterface' => __DIR__ . '/..' . '/spomky-labs/cbor-php/src/EncoderInterface.php',
        '_ContaoManager\\CBOR\\IndefiniteLengthByteStringObject' => __DIR__ . '/..' . '/spomky-labs/cbor-php/src/IndefiniteLengthByteStringObject.php',
        '_ContaoManager\\CBOR\\IndefiniteLengthListObject' => __DIR__ . '/..' . '/spomky-labs/cbor-php/src/IndefiniteLengthListObject.php',
        '_ContaoManager\\CBOR\\IndefiniteLengthMapObject' => __DIR__ . '/..' . '/spomky-labs/cbor-php/src/IndefiniteLengthMapObject.php',
        '_ContaoManager\\CBOR\\IndefiniteLengthTextStringObject' => __DIR__ . '/..' . '/spomky-labs/cbor-php/src/IndefiniteLengthTextStringObject.php',
        '_ContaoManager\\CBOR\\LengthCalculator' => __DIR__ . '/..' . '/spomky-labs/cbor-php/src/LengthCalculator.php',
        '_ContaoManager\\CBOR\\ListObject' => __DIR__ . '/..' . '/spomky-labs/cbor-php/src/ListObject.php',
        '_ContaoManager\\CBOR\\MapItem' => __DIR__ . '/..' . '/spomky-labs/cbor-php/src/MapItem.php',
        '_ContaoManager\\CBOR\\MapObject' => __DIR__ . '/..' . '/spomky-labs/cbor-php/src/MapObject.php',
        '_ContaoManager\\CBOR\\NegativeIntegerObject' => __DIR__ . '/..' . '/spomky-labs/cbor-php/src/NegativeIntegerObject.php',
        '_ContaoManager\\CBOR\\Normalizable' => __DIR__ . '/..' . '/spomky-labs/cbor-php/src/Normalizable.php',
        '_ContaoManager\\CBOR\\OtherObject' => __DIR__ . '/..' . '/spomky-labs/cbor-php/src/OtherObject.php',
        '_ContaoManager\\CBOR\\OtherObject\\BreakObject' => __DIR__ . '/..' . '/spomky-labs/cbor-php/src/OtherObject/BreakObject.php',
        '_ContaoManager\\CBOR\\OtherObject\\DoublePrecisionFloatObject' => __DIR__ . '/..' . '/spomky-labs/cbor-php/src/OtherObject/DoublePrecisionFloatObject.php',
        '_ContaoManager\\CBOR\\OtherObject\\FalseObject' => __DIR__ . '/..' . '/spomky-labs/cbor-php/src/OtherObject/FalseObject.php',
        '_ContaoManager\\CBOR\\OtherObject\\GenericObject' => __DIR__ . '/..' . '/spomky-labs/cbor-php/src/OtherObject/GenericObject.php',
        '_ContaoManager\\CBOR\\OtherObject\\HalfPrecisionFloatObject' => __DIR__ . '/..' . '/spomky-labs/cbor-php/src/OtherObject/HalfPrecisionFloatObject.php',
        '_ContaoManager\\CBOR\\OtherObject\\NullObject' => __DIR__ . '/..' . '/spomky-labs/cbor-php/src/OtherObject/NullObject.php',
        '_ContaoManager\\CBOR\\OtherObject\\OtherObjectInterface' => __DIR__ . '/..' . '/spomky-labs/cbor-php/src/OtherObject/OtherObjectInterface.php',
        '_ContaoManager\\CBOR\\OtherObject\\OtherObjectManager' => __DIR__ . '/..' . '/spomky-labs/cbor-php/src/OtherObject/OtherObjectManager.php',
        '_ContaoManager\\CBOR\\OtherObject\\OtherObjectManagerInterface' => __DIR__ . '/..' . '/spomky-labs/cbor-php/src/OtherObject/OtherObjectManagerInterface.php',
        '_ContaoManager\\CBOR\\OtherObject\\SimpleObject' => __DIR__ . '/..' . '/spomky-labs/cbor-php/src/OtherObject/SimpleObject.php',
        '_ContaoManager\\CBOR\\OtherObject\\SinglePrecisionFloatObject' => __DIR__ . '/..' . '/spomky-labs/cbor-php/src/OtherObject/SinglePrecisionFloatObject.php',
        '_ContaoManager\\CBOR\\OtherObject\\TrueObject' => __DIR__ . '/..' . '/spomky-labs/cbor-php/src/OtherObject/TrueObject.php',
        '_ContaoManager\\CBOR\\OtherObject\\UndefinedObject' => __DIR__ . '/..' . '/spomky-labs/cbor-php/src/OtherObject/UndefinedObject.php',
        '_ContaoManager\\CBOR\\Stream' => __DIR__ . '/..' . '/spomky-labs/cbor-php/src/Stream.php',
        '_ContaoManager\\CBOR\\StringStream' => __DIR__ . '/..' . '/spomky-labs/cbor-php/src/StringStream.php',
        '_ContaoManager\\CBOR\\Tag' => __DIR__ . '/..' . '/spomky-labs/cbor-php/src/Tag.php',
        '_ContaoManager\\CBOR\\Tag\\Base16EncodingTag' => __DIR__ . '/..' . '/spomky-labs/cbor-php/src/Tag/Base16EncodingTag.php',
        '_ContaoManager\\CBOR\\Tag\\Base64EncodingTag' => __DIR__ . '/..' . '/spomky-labs/cbor-php/src/Tag/Base64EncodingTag.php',
        '_ContaoManager\\CBOR\\Tag\\Base64Tag' => __DIR__ . '/..' . '/spomky-labs/cbor-php/src/Tag/Base64Tag.php',
        '_ContaoManager\\CBOR\\Tag\\Base64UrlEncodingTag' => __DIR__ . '/..' . '/spomky-labs/cbor-php/src/Tag/Base64UrlEncodingTag.php',
        '_ContaoManager\\CBOR\\Tag\\Base64UrlTag' => __DIR__ . '/..' . '/spomky-labs/cbor-php/src/Tag/Base64UrlTag.php',
        '_ContaoManager\\CBOR\\Tag\\BigFloatTag' => __DIR__ . '/..' . '/spomky-labs/cbor-php/src/Tag/BigFloatTag.php',
        '_ContaoManager\\CBOR\\Tag\\CBOREncodingTag' => __DIR__ . '/..' . '/spomky-labs/cbor-php/src/Tag/CBOREncodingTag.php',
        '_ContaoManager\\CBOR\\Tag\\CBORTag' => __DIR__ . '/..' . '/spomky-labs/cbor-php/src/Tag/CBORTag.php',
        '_ContaoManager\\CBOR\\Tag\\DatetimeTag' => __DIR__ . '/..' . '/spomky-labs/cbor-php/src/Tag/DatetimeTag.php',
        '_ContaoManager\\CBOR\\Tag\\DecimalFractionTag' => __DIR__ . '/..' . '/spomky-labs/cbor-php/src/Tag/DecimalFractionTag.php',
        '_ContaoManager\\CBOR\\Tag\\GenericTag' => __DIR__ . '/..' . '/spomky-labs/cbor-php/src/Tag/GenericTag.php',
        '_ContaoManager\\CBOR\\Tag\\MimeTag' => __DIR__ . '/..' . '/spomky-labs/cbor-php/src/Tag/MimeTag.php',
        '_ContaoManager\\CBOR\\Tag\\NegativeBigIntegerTag' => __DIR__ . '/..' . '/spomky-labs/cbor-php/src/Tag/NegativeBigIntegerTag.php',
        '_ContaoManager\\CBOR\\Tag\\TagInterface' => __DIR__ . '/..' . '/spomky-labs/cbor-php/src/Tag/TagInterface.php',
        '_ContaoManager\\CBOR\\Tag\\TagManager' => __DIR__ . '/..' . '/spomky-labs/cbor-php/src/Tag/TagManager.php',
        '_ContaoManager\\CBOR\\Tag\\TagManagerInterface' => __DIR__ . '/..' . '/spomky-labs/cbor-php/src/Tag/TagManagerInterface.php',
        '_ContaoManager\\CBOR\\Tag\\TimestampTag' => __DIR__ . '/..' . '/spomky-labs/cbor-php/src/Tag/TimestampTag.php',
        '_ContaoManager\\CBOR\\Tag\\UnsignedBigIntegerTag' => __DIR__ . '/..' . '/spomky-labs/cbor-php/src/Tag/UnsignedBigIntegerTag.php',
        '_ContaoManager\\CBOR\\Tag\\UriTag' => __DIR__ . '/..' . '/spomky-labs/cbor-php/src/Tag/UriTag.php',
        '_ContaoManager\\CBOR\\TextStringObject' => __DIR__ . '/..' . '/spomky-labs/cbor-php/src/TextStringObject.php',
        '_ContaoManager\\CBOR\\UnsignedIntegerObject' => __DIR__ . '/..' . '/spomky-labs/cbor-php/src/UnsignedIntegerObject.php',
        '_ContaoManager\\CBOR\\Utils' => __DIR__ . '/..' . '/spomky-labs/cbor-php/src/Utils.php',
        '_ContaoManager\\Contao\\ManagerApi\\ApiApplication' => __DIR__ . '/../..' . '/api/ApiApplication.php',
        '_ContaoManager\\Contao\\ManagerApi\\ApiKernel' => __DIR__ . '/../..' . '/api/ApiKernel.php',
        '_ContaoManager\\Contao\\ManagerApi\\Command\\AboutCommand' => __DIR__ . '/../..' . '/api/Command/AboutCommand.php',
        '_ContaoManager\\Contao\\ManagerApi\\Command\\IntegrityCheckCommand' => __DIR__ . '/../..' . '/api/Command/IntegrityCheckCommand.php',
        '_ContaoManager\\Contao\\ManagerApi\\Command\\ProcessRunnerCommand' => __DIR__ . '/../..' . '/api/Command/ProcessRunnerCommand.php',
        '_ContaoManager\\Contao\\ManagerApi\\Command\\TaskAbortCommand' => __DIR__ . '/../..' . '/api/Command/TaskAbortCommand.php',
        '_ContaoManager\\Contao\\ManagerApi\\Command\\TaskDeleteCommand' => __DIR__ . '/../..' . '/api/Command/TaskDeleteCommand.php',
        '_ContaoManager\\Contao\\ManagerApi\\Command\\TaskUpdateCommand' => __DIR__ . '/../..' . '/api/Command/TaskUpdateCommand.php',
        '_ContaoManager\\Contao\\ManagerApi\\Command\\UpdateCommand' => __DIR__ . '/../..' . '/api/Command/UpdateCommand.php',
        '_ContaoManager\\Contao\\ManagerApi\\Composer\\CloudChanges' => __DIR__ . '/../..' . '/api/Composer/CloudChanges.php',
        '_ContaoManager\\Contao\\ManagerApi\\Composer\\CloudException' => __DIR__ . '/../..' . '/api/Composer/CloudException.php',
        '_ContaoManager\\Contao\\ManagerApi\\Composer\\CloudJob' => __DIR__ . '/../..' . '/api/Composer/CloudJob.php',
        '_ContaoManager\\Contao\\ManagerApi\\Composer\\CloudResolver' => __DIR__ . '/../..' . '/api/Composer/CloudResolver.php',
        '_ContaoManager\\Contao\\ManagerApi\\Composer\\Environment' => __DIR__ . '/../..' . '/api/Composer/Environment.php',
        '_ContaoManager\\Contao\\ManagerApi\\Config\\AbstractConfig' => __DIR__ . '/../..' . '/api/Config/AbstractConfig.php',
        '_ContaoManager\\Contao\\ManagerApi\\Config\\AuthConfig' => __DIR__ . '/../..' . '/api/Config/AuthConfig.php',
        '_ContaoManager\\Contao\\ManagerApi\\Config\\ComposerConfig' => __DIR__ . '/../..' . '/api/Config/ComposerConfig.php',
        '_ContaoManager\\Contao\\ManagerApi\\Config\\ManagerConfig' => __DIR__ . '/../..' . '/api/Config/ManagerConfig.php',
        '_ContaoManager\\Contao\\ManagerApi\\Config\\PartialConfig' => __DIR__ . '/../..' . '/api/Config/PartialConfig.php',
        '_ContaoManager\\Contao\\ManagerApi\\Config\\UploadsConfig' => __DIR__ . '/../..' . '/api/Config/UploadsConfig.php',
        '_ContaoManager\\Contao\\ManagerApi\\Config\\UserConfig' => __DIR__ . '/../..' . '/api/Config/UserConfig.php',
        '_ContaoManager\\Contao\\ManagerApi\\Controller\\Config\\AbstractConfigController' => __DIR__ . '/../..' . '/api/Controller/Config/AbstractConfigController.php',
        '_ContaoManager\\Contao\\ManagerApi\\Controller\\Config\\AuthController' => __DIR__ . '/../..' . '/api/Controller/Config/AuthController.php',
        '_ContaoManager\\Contao\\ManagerApi\\Controller\\Config\\ComposerController' => __DIR__ . '/../..' . '/api/Controller/Config/ComposerController.php',
        '_ContaoManager\\Contao\\ManagerApi\\Controller\\Config\\ManagerController' => __DIR__ . '/../..' . '/api/Controller/Config/ManagerController.php',
        '_ContaoManager\\Contao\\ManagerApi\\Controller\\ConstraintController' => __DIR__ . '/../..' . '/api/Controller/ConstraintController.php',
        '_ContaoManager\\Contao\\ManagerApi\\Controller\\Contao\\AccessKeyController' => __DIR__ . '/../..' . '/api/Controller/Contao/AccessKeyController.php',
        '_ContaoManager\\Contao\\ManagerApi\\Controller\\Contao\\BackupController' => __DIR__ . '/../..' . '/api/Controller/Contao/BackupController.php',
        '_ContaoManager\\Contao\\ManagerApi\\Controller\\Contao\\DatabaseMigrationController' => __DIR__ . '/../..' . '/api/Controller/Contao/DatabaseMigrationController.php',
        '_ContaoManager\\Contao\\ManagerApi\\Controller\\Contao\\InstallToolLockController' => __DIR__ . '/../..' . '/api/Controller/Contao/InstallToolLockController.php',
        '_ContaoManager\\Contao\\ManagerApi\\Controller\\Contao\\JwtCookieController' => __DIR__ . '/../..' . '/api/Controller/Contao/JwtCookieController.php',
        '_ContaoManager\\Contao\\ManagerApi\\Controller\\Contao\\MaintenanceModeController' => __DIR__ . '/../..' . '/api/Controller/Contao/MaintenanceModeController.php',
        '_ContaoManager\\Contao\\ManagerApi\\Controller\\FileController' => __DIR__ . '/../..' . '/api/Controller/FileController.php',
        '_ContaoManager\\Contao\\ManagerApi\\Controller\\LogController' => __DIR__ . '/../..' . '/api/Controller/LogController.php',
        '_ContaoManager\\Contao\\ManagerApi\\Controller\\Packages\\CloudController' => __DIR__ . '/../..' . '/api/Controller/Packages/CloudController.php',
        '_ContaoManager\\Contao\\ManagerApi\\Controller\\Packages\\LocalPackagesController' => __DIR__ . '/../..' . '/api/Controller/Packages/LocalPackagesController.php',
        '_ContaoManager\\Contao\\ManagerApi\\Controller\\Packages\\MissingPackagesController' => __DIR__ . '/../..' . '/api/Controller/Packages/MissingPackagesController.php',
        '_ContaoManager\\Contao\\ManagerApi\\Controller\\Packages\\RootPackageController' => __DIR__ . '/../..' . '/api/Controller/Packages/RootPackageController.php',
        '_ContaoManager\\Contao\\ManagerApi\\Controller\\Packages\\UploadPackagesController' => __DIR__ . '/../..' . '/api/Controller/Packages/UploadPackagesController.php',
        '_ContaoManager\\Contao\\ManagerApi\\Controller\\Server\\AdminUserController' => __DIR__ . '/../..' . '/api/Controller/Server/AdminUserController.php',
        '_ContaoManager\\Contao\\ManagerApi\\Controller\\Server\\ComposerController' => __DIR__ . '/../..' . '/api/Controller/Server/ComposerController.php',
        '_ContaoManager\\Contao\\ManagerApi\\Controller\\Server\\ConfigController' => __DIR__ . '/../..' . '/api/Controller/Server/ConfigController.php',
        '_ContaoManager\\Contao\\ManagerApi\\Controller\\Server\\ContaoController' => __DIR__ . '/../..' . '/api/Controller/Server/ContaoController.php',
        '_ContaoManager\\Contao\\ManagerApi\\Controller\\Server\\DatabaseController' => __DIR__ . '/../..' . '/api/Controller/Server/DatabaseController.php',
        '_ContaoManager\\Contao\\ManagerApi\\Controller\\Server\\OpcacheController' => __DIR__ . '/../..' . '/api/Controller/Server/OpcacheController.php',
        '_ContaoManager\\Contao\\ManagerApi\\Controller\\Server\\PhpCliController' => __DIR__ . '/../..' . '/api/Controller/Server/PhpCliController.php',
        '_ContaoManager\\Contao\\ManagerApi\\Controller\\Server\\PhpWebController' => __DIR__ . '/../..' . '/api/Controller/Server/PhpWebController.php',
        '_ContaoManager\\Contao\\ManagerApi\\Controller\\Server\\PhpinfoController' => __DIR__ . '/../..' . '/api/Controller/Server/PhpinfoController.php',
        '_ContaoManager\\Contao\\ManagerApi\\Controller\\Server\\SelfUpdateController' => __DIR__ . '/../..' . '/api/Controller/Server/SelfUpdateController.php',
        '_ContaoManager\\Contao\\ManagerApi\\Controller\\SessionController' => __DIR__ . '/../..' . '/api/Controller/SessionController.php',
        '_ContaoManager\\Contao\\ManagerApi\\Controller\\TaskController' => __DIR__ . '/../..' . '/api/Controller/TaskController.php',
        '_ContaoManager\\Contao\\ManagerApi\\Controller\\UserController' => __DIR__ . '/../..' . '/api/Controller/UserController.php',
        '_ContaoManager\\Contao\\ManagerApi\\EventListener\\CheckTotpListener' => __DIR__ . '/../..' . '/api/EventListener/CheckTotpListener.php',
        '_ContaoManager\\Contao\\ManagerApi\\EventListener\\ExceptionListener' => __DIR__ . '/../..' . '/api/EventListener/ExceptionListener.php',
        '_ContaoManager\\Contao\\ManagerApi\\EventListener\\JsonRequestListener' => __DIR__ . '/../..' . '/api/EventListener/JsonRequestListener.php',
        '_ContaoManager\\Contao\\ManagerApi\\EventListener\\LocaleListener' => __DIR__ . '/../..' . '/api/EventListener/LocaleListener.php',
        '_ContaoManager\\Contao\\ManagerApi\\EventListener\\SecurityListener' => __DIR__ . '/../..' . '/api/EventListener/SecurityListener.php',
        '_ContaoManager\\Contao\\ManagerApi\\Exception\\ApiProblemException' => __DIR__ . '/../..' . '/api/Exception/ApiProblemException.php',
        '_ContaoManager\\Contao\\ManagerApi\\Exception\\InvalidJsonException' => __DIR__ . '/../..' . '/api/Exception/InvalidJsonException.php',
        '_ContaoManager\\Contao\\ManagerApi\\Exception\\InvalidTotpException' => __DIR__ . '/../..' . '/api/Exception/InvalidTotpException.php',
        '_ContaoManager\\Contao\\ManagerApi\\Exception\\ProcessOutputException' => __DIR__ . '/../..' . '/api/Exception/ProcessOutputException.php',
        '_ContaoManager\\Contao\\ManagerApi\\Exception\\RequestException' => __DIR__ . '/../..' . '/api/Exception/RequestException.php',
        '_ContaoManager\\Contao\\ManagerApi\\HttpKernel\\ApiProblemResponse' => __DIR__ . '/../..' . '/api/HttpKernel/ApiProblemResponse.php',
        '_ContaoManager\\Contao\\ManagerApi\\I18n\\Translator' => __DIR__ . '/../..' . '/api/I18n/Translator.php',
        '_ContaoManager\\Contao\\ManagerApi\\IntegrityCheck\\AbstractIntegrityCheck' => __DIR__ . '/../..' . '/api/IntegrityCheck/AbstractIntegrityCheck.php',
        '_ContaoManager\\Contao\\ManagerApi\\IntegrityCheck\\AllowUrlFopenCheck' => __DIR__ . '/../..' . '/api/IntegrityCheck/AllowUrlFopenCheck.php',
        '_ContaoManager\\Contao\\ManagerApi\\IntegrityCheck\\GraphicsLibCheck' => __DIR__ . '/../..' . '/api/IntegrityCheck/GraphicsLibCheck.php',
        '_ContaoManager\\Contao\\ManagerApi\\IntegrityCheck\\IntegrityCheckFactory' => __DIR__ . '/../..' . '/api/IntegrityCheck/IntegrityCheckFactory.php',
        '_ContaoManager\\Contao\\ManagerApi\\IntegrityCheck\\IntegrityCheckInterface' => __DIR__ . '/../..' . '/api/IntegrityCheck/IntegrityCheckInterface.php',
        '_ContaoManager\\Contao\\ManagerApi\\IntegrityCheck\\MemoryLimitCheck' => __DIR__ . '/../..' . '/api/IntegrityCheck/MemoryLimitCheck.php',
        '_ContaoManager\\Contao\\ManagerApi\\IntegrityCheck\\PhpExtensionsCheck' => __DIR__ . '/../..' . '/api/IntegrityCheck/PhpExtensionsCheck.php',
        '_ContaoManager\\Contao\\ManagerApi\\IntegrityCheck\\ProcessCheck' => __DIR__ . '/../..' . '/api/IntegrityCheck/ProcessCheck.php',
        '_ContaoManager\\Contao\\ManagerApi\\IntegrityCheck\\SessionCheck' => __DIR__ . '/../..' . '/api/IntegrityCheck/SessionCheck.php',
        '_ContaoManager\\Contao\\ManagerApi\\IntegrityCheck\\SymlinkCheck' => __DIR__ . '/../..' . '/api/IntegrityCheck/SymlinkCheck.php',
        '_ContaoManager\\Contao\\ManagerApi\\IntegrityCheck\\SysTempDirCheck' => __DIR__ . '/../..' . '/api/IntegrityCheck/SysTempDirCheck.php',
        '_ContaoManager\\Contao\\ManagerApi\\IntegrityCheck\\ZipCheck' => __DIR__ . '/../..' . '/api/IntegrityCheck/ZipCheck.php',
        '_ContaoManager\\Contao\\ManagerApi\\Process\\AbstractProcess' => __DIR__ . '/../..' . '/api/Process/AbstractProcess.php',
        '_ContaoManager\\Contao\\ManagerApi\\Process\\ConsoleProcessFactory' => __DIR__ . '/../..' . '/api/Process/ConsoleProcessFactory.php',
        '_ContaoManager\\Contao\\ManagerApi\\Process\\ContaoApi' => __DIR__ . '/../..' . '/api/Process/ContaoApi.php',
        '_ContaoManager\\Contao\\ManagerApi\\Process\\ContaoConsole' => __DIR__ . '/../..' . '/api/Process/ContaoConsole.php',
        '_ContaoManager\\Contao\\ManagerApi\\Process\\Forker\\AbstractForker' => __DIR__ . '/../..' . '/api/Process/Forker/AbstractForker.php',
        '_ContaoManager\\Contao\\ManagerApi\\Process\\Forker\\DisownForker' => __DIR__ . '/../..' . '/api/Process/Forker/DisownForker.php',
        '_ContaoManager\\Contao\\ManagerApi\\Process\\Forker\\ForkerInterface' => __DIR__ . '/../..' . '/api/Process/Forker/ForkerInterface.php',
        '_ContaoManager\\Contao\\ManagerApi\\Process\\Forker\\InlineForker' => __DIR__ . '/../..' . '/api/Process/Forker/InlineForker.php',
        '_ContaoManager\\Contao\\ManagerApi\\Process\\Forker\\NohupForker' => __DIR__ . '/../..' . '/api/Process/Forker/NohupForker.php',
        '_ContaoManager\\Contao\\ManagerApi\\Process\\Forker\\WindowsStartForker' => __DIR__ . '/../..' . '/api/Process/Forker/WindowsStartForker.php',
        '_ContaoManager\\Contao\\ManagerApi\\Process\\PhpExecutableFinder' => __DIR__ . '/../..' . '/api/Process/PhpExecutableFinder.php',
        '_ContaoManager\\Contao\\ManagerApi\\Process\\ProcessController' => __DIR__ . '/../..' . '/api/Process/ProcessController.php',
        '_ContaoManager\\Contao\\ManagerApi\\Process\\ProcessRunner' => __DIR__ . '/../..' . '/api/Process/ProcessRunner.php',
        '_ContaoManager\\Contao\\ManagerApi\\Process\\Utf8Process' => __DIR__ . '/../..' . '/api/Process/Utf8Process.php',
        '_ContaoManager\\Contao\\ManagerApi\\Security\\AbstractBrowserAuthenticator' => __DIR__ . '/../..' . '/api/Security/AbstractBrowserAuthenticator.php',
        '_ContaoManager\\Contao\\ManagerApi\\Security\\AuthenticationTrustResolver' => __DIR__ . '/../..' . '/api/Security/AuthenticationTrustResolver.php',
        '_ContaoManager\\Contao\\ManagerApi\\Security\\JwtAuthenticator' => __DIR__ . '/../..' . '/api/Security/JwtAuthenticator.php',
        '_ContaoManager\\Contao\\ManagerApi\\Security\\JwtManager' => __DIR__ . '/../..' . '/api/Security/JwtManager.php',
        '_ContaoManager\\Contao\\ManagerApi\\Security\\LoginAuthenticator' => __DIR__ . '/../..' . '/api/Security/LoginAuthenticator.php',
        '_ContaoManager\\Contao\\ManagerApi\\Security\\PasswordlessAuthenticator' => __DIR__ . '/../..' . '/api/Security/PasswordlessAuthenticator.php',
        '_ContaoManager\\Contao\\ManagerApi\\Security\\TokenAuthenticator' => __DIR__ . '/../..' . '/api/Security/TokenAuthenticator.php',
        '_ContaoManager\\Contao\\ManagerApi\\Security\\TotpBadge' => __DIR__ . '/../..' . '/api/Security/TotpBadge.php',
        '_ContaoManager\\Contao\\ManagerApi\\Security\\User' => __DIR__ . '/../..' . '/api/Security/User.php',
        '_ContaoManager\\Contao\\ManagerApi\\Security\\UserProvider' => __DIR__ . '/../..' . '/api/Security/UserProvider.php',
        '_ContaoManager\\Contao\\ManagerApi\\Security\\WebauthnAuthenticator' => __DIR__ . '/../..' . '/api/Security/WebauthnAuthenticator.php',
        '_ContaoManager\\Contao\\ManagerApi\\System\\Request' => __DIR__ . '/../..' . '/api/System/Request.php',
        '_ContaoManager\\Contao\\ManagerApi\\System\\SelfUpdate' => __DIR__ . '/../..' . '/api/System/SelfUpdate.php',
        '_ContaoManager\\Contao\\ManagerApi\\System\\ServerInfo' => __DIR__ . '/../..' . '/api/System/ServerInfo.php',
        '_ContaoManager\\Contao\\ManagerApi\\TaskOperation\\AbstractInlineOperation' => __DIR__ . '/../..' . '/api/TaskOperation/AbstractInlineOperation.php',
        '_ContaoManager\\Contao\\ManagerApi\\TaskOperation\\AbstractProcessOperation' => __DIR__ . '/../..' . '/api/TaskOperation/AbstractProcessOperation.php',
        '_ContaoManager\\Contao\\ManagerApi\\TaskOperation\\Composer\\ClearCacheOperation' => __DIR__ . '/../..' . '/api/TaskOperation/Composer/ClearCacheOperation.php',
        '_ContaoManager\\Contao\\ManagerApi\\TaskOperation\\Composer\\CloudOperation' => __DIR__ . '/../..' . '/api/TaskOperation/Composer/CloudOperation.php',
        '_ContaoManager\\Contao\\ManagerApi\\TaskOperation\\Composer\\CreateProjectOperation' => __DIR__ . '/../..' . '/api/TaskOperation/Composer/CreateProjectOperation.php',
        '_ContaoManager\\Contao\\ManagerApi\\TaskOperation\\Composer\\DumpAutoloadOperation' => __DIR__ . '/../..' . '/api/TaskOperation/Composer/DumpAutoloadOperation.php',
        '_ContaoManager\\Contao\\ManagerApi\\TaskOperation\\Composer\\InstallOperation' => __DIR__ . '/../..' . '/api/TaskOperation/Composer/InstallOperation.php',
        '_ContaoManager\\Contao\\ManagerApi\\TaskOperation\\Composer\\RemoveOperation' => __DIR__ . '/../..' . '/api/TaskOperation/Composer/RemoveOperation.php',
        '_ContaoManager\\Contao\\ManagerApi\\TaskOperation\\Composer\\RequireOperation' => __DIR__ . '/../..' . '/api/TaskOperation/Composer/RequireOperation.php',
        '_ContaoManager\\Contao\\ManagerApi\\TaskOperation\\Composer\\UpdateOperation' => __DIR__ . '/../..' . '/api/TaskOperation/Composer/UpdateOperation.php',
        '_ContaoManager\\Contao\\ManagerApi\\TaskOperation\\ConsoleOutput' => __DIR__ . '/../..' . '/api/TaskOperation/ConsoleOutput.php',
        '_ContaoManager\\Contao\\ManagerApi\\TaskOperation\\Contao\\BackupCreateOperation' => __DIR__ . '/../..' . '/api/TaskOperation/Contao/BackupCreateOperation.php',
        '_ContaoManager\\Contao\\ManagerApi\\TaskOperation\\Contao\\BackupRestoreOperation' => __DIR__ . '/../..' . '/api/TaskOperation/Contao/BackupRestoreOperation.php',
        '_ContaoManager\\Contao\\ManagerApi\\TaskOperation\\Contao\\CacheClearOperation' => __DIR__ . '/../..' . '/api/TaskOperation/Contao/CacheClearOperation.php',
        '_ContaoManager\\Contao\\ManagerApi\\TaskOperation\\Contao\\CacheWarmupOperation' => __DIR__ . '/../..' . '/api/TaskOperation/Contao/CacheWarmupOperation.php',
        '_ContaoManager\\Contao\\ManagerApi\\TaskOperation\\Contao\\CreateContaoOperation' => __DIR__ . '/../..' . '/api/TaskOperation/Contao/CreateContaoOperation.php',
        '_ContaoManager\\Contao\\ManagerApi\\TaskOperation\\Contao\\MaintenanceModeOperation' => __DIR__ . '/../..' . '/api/TaskOperation/Contao/MaintenanceModeOperation.php',
        '_ContaoManager\\Contao\\ManagerApi\\TaskOperation\\Filesystem\\InstallUploadsOperation' => __DIR__ . '/../..' . '/api/TaskOperation/Filesystem/InstallUploadsOperation.php',
        '_ContaoManager\\Contao\\ManagerApi\\TaskOperation\\Filesystem\\RemoveArtifactsOperation' => __DIR__ . '/../..' . '/api/TaskOperation/Filesystem/RemoveArtifactsOperation.php',
        '_ContaoManager\\Contao\\ManagerApi\\TaskOperation\\Filesystem\\RemoveCacheOperation' => __DIR__ . '/../..' . '/api/TaskOperation/Filesystem/RemoveCacheOperation.php',
        '_ContaoManager\\Contao\\ManagerApi\\TaskOperation\\Filesystem\\RemoveUploadsOperation' => __DIR__ . '/../..' . '/api/TaskOperation/Filesystem/RemoveUploadsOperation.php',
        '_ContaoManager\\Contao\\ManagerApi\\TaskOperation\\Filesystem\\RemoveVendorOperation' => __DIR__ . '/../..' . '/api/TaskOperation/Filesystem/RemoveVendorOperation.php',
        '_ContaoManager\\Contao\\ManagerApi\\TaskOperation\\Manager\\SelfUpdateOperation' => __DIR__ . '/../..' . '/api/TaskOperation/Manager/SelfUpdateOperation.php',
        '_ContaoManager\\Contao\\ManagerApi\\TaskOperation\\SponsoredOperationInterface' => __DIR__ . '/../..' . '/api/TaskOperation/SponsoredOperationInterface.php',
        '_ContaoManager\\Contao\\ManagerApi\\TaskOperation\\TaskOperationInterface' => __DIR__ . '/../..' . '/api/TaskOperation/TaskOperationInterface.php',
        '_ContaoManager\\Contao\\ManagerApi\\Task\\AbstractTask' => __DIR__ . '/../..' . '/api/Task/AbstractTask.php',
        '_ContaoManager\\Contao\\ManagerApi\\Task\\Composer\\ClearCacheTask' => __DIR__ . '/../..' . '/api/Task/Composer/ClearCacheTask.php',
        '_ContaoManager\\Contao\\ManagerApi\\Task\\Composer\\DumpAutoloadTask' => __DIR__ . '/../..' . '/api/Task/Composer/DumpAutoloadTask.php',
        '_ContaoManager\\Contao\\ManagerApi\\Task\\Contao\\BackupCreateTask' => __DIR__ . '/../..' . '/api/Task/Contao/BackupCreateTask.php',
        '_ContaoManager\\Contao\\ManagerApi\\Task\\Contao\\BackupRestoreTask' => __DIR__ . '/../..' . '/api/Task/Contao/BackupRestoreTask.php',
        '_ContaoManager\\Contao\\ManagerApi\\Task\\Contao\\RebuildCacheTask' => __DIR__ . '/../..' . '/api/Task/Contao/RebuildCacheTask.php',
        '_ContaoManager\\Contao\\ManagerApi\\Task\\Manager\\SelfUpdateTask' => __DIR__ . '/../..' . '/api/Task/Manager/SelfUpdateTask.php',
        '_ContaoManager\\Contao\\ManagerApi\\Task\\Packages\\AbstractPackagesTask' => __DIR__ . '/../..' . '/api/Task/Packages/AbstractPackagesTask.php',
        '_ContaoManager\\Contao\\ManagerApi\\Task\\Packages\\InstallTask' => __DIR__ . '/../..' . '/api/Task/Packages/InstallTask.php',
        '_ContaoManager\\Contao\\ManagerApi\\Task\\Packages\\SetupTask' => __DIR__ . '/../..' . '/api/Task/Packages/SetupTask.php',
        '_ContaoManager\\Contao\\ManagerApi\\Task\\Packages\\UpdateTask' => __DIR__ . '/../..' . '/api/Task/Packages/UpdateTask.php',
        '_ContaoManager\\Contao\\ManagerApi\\Task\\TaskConfig' => __DIR__ . '/../..' . '/api/Task/TaskConfig.php',
        '_ContaoManager\\Contao\\ManagerApi\\Task\\TaskInterface' => __DIR__ . '/../..' . '/api/Task/TaskInterface.php',
        '_ContaoManager\\Contao\\ManagerApi\\Task\\TaskManager' => __DIR__ . '/../..' . '/api/Task/TaskManager.php',
        '_ContaoManager\\Contao\\ManagerApi\\Task\\TaskStatus' => __DIR__ . '/../..' . '/api/Task/TaskStatus.php',
        '_ContaoManager\\Contao\\ManagerApi\\Tests\\Composer\\CloudJobTest' => __DIR__ . '/../..' . '/api/Tests/Composer/CloudJobTest.php',
        '_ContaoManager\\Contao\\ManagerApi\\Tests\\Controller\\LogPatternTest' => __DIR__ . '/../..' . '/api/Tests/Controller/LogPatternTest.php',
        '_ContaoManager\\Cose\\Algorithm\\Algorithm' => __DIR__ . '/..' . '/web-auth/cose-lib/src/Algorithm/Algorithm.php',
        '_ContaoManager\\Cose\\Algorithm\\Mac\\HS256' => __DIR__ . '/..' . '/web-auth/cose-lib/src/Algorithm/Mac/HS256.php',
        '_ContaoManager\\Cose\\Algorithm\\Mac\\HS256Truncated64' => __DIR__ . '/..' . '/web-auth/cose-lib/src/Algorithm/Mac/HS256Truncated64.php',
        '_ContaoManager\\Cose\\Algorithm\\Mac\\HS384' => __DIR__ . '/..' . '/web-auth/cose-lib/src/Algorithm/Mac/HS384.php',
        '_ContaoManager\\Cose\\Algorithm\\Mac\\HS512' => __DIR__ . '/..' . '/web-auth/cose-lib/src/Algorithm/Mac/HS512.php',
        '_ContaoManager\\Cose\\Algorithm\\Mac\\Hmac' => __DIR__ . '/..' . '/web-auth/cose-lib/src/Algorithm/Mac/Hmac.php',
        '_ContaoManager\\Cose\\Algorithm\\Mac\\Mac' => __DIR__ . '/..' . '/web-auth/cose-lib/src/Algorithm/Mac/Mac.php',
        '_ContaoManager\\Cose\\Algorithm\\Manager' => __DIR__ . '/..' . '/web-auth/cose-lib/src/Algorithm/Manager.php',
        '_ContaoManager\\Cose\\Algorithm\\ManagerFactory' => __DIR__ . '/..' . '/web-auth/cose-lib/src/Algorithm/ManagerFactory.php',
        '_ContaoManager\\Cose\\Algorithm\\Signature\\ECDSA\\ECDSA' => __DIR__ . '/..' . '/web-auth/cose-lib/src/Algorithm/Signature/ECDSA/ECDSA.php',
        '_ContaoManager\\Cose\\Algorithm\\Signature\\ECDSA\\ECSignature' => __DIR__ . '/..' . '/web-auth/cose-lib/src/Algorithm/Signature/ECDSA/ECSignature.php',
        '_ContaoManager\\Cose\\Algorithm\\Signature\\ECDSA\\ES256' => __DIR__ . '/..' . '/web-auth/cose-lib/src/Algorithm/Signature/ECDSA/ES256.php',
        '_ContaoManager\\Cose\\Algorithm\\Signature\\ECDSA\\ES256K' => __DIR__ . '/..' . '/web-auth/cose-lib/src/Algorithm/Signature/ECDSA/ES256K.php',
        '_ContaoManager\\Cose\\Algorithm\\Signature\\ECDSA\\ES384' => __DIR__ . '/..' . '/web-auth/cose-lib/src/Algorithm/Signature/ECDSA/ES384.php',
        '_ContaoManager\\Cose\\Algorithm\\Signature\\ECDSA\\ES512' => __DIR__ . '/..' . '/web-auth/cose-lib/src/Algorithm/Signature/ECDSA/ES512.php',
        '_ContaoManager\\Cose\\Algorithm\\Signature\\EdDSA\\Ed25519' => __DIR__ . '/..' . '/web-auth/cose-lib/src/Algorithm/Signature/EdDSA/Ed25519.php',
        '_ContaoManager\\Cose\\Algorithm\\Signature\\EdDSA\\Ed256' => __DIR__ . '/..' . '/web-auth/cose-lib/src/Algorithm/Signature/EdDSA/Ed256.php',
        '_ContaoManager\\Cose\\Algorithm\\Signature\\EdDSA\\Ed512' => __DIR__ . '/..' . '/web-auth/cose-lib/src/Algorithm/Signature/EdDSA/Ed512.php',
        '_ContaoManager\\Cose\\Algorithm\\Signature\\EdDSA\\EdDSA' => __DIR__ . '/..' . '/web-auth/cose-lib/src/Algorithm/Signature/EdDSA/EdDSA.php',
        '_ContaoManager\\Cose\\Algorithm\\Signature\\RSA\\PS256' => __DIR__ . '/..' . '/web-auth/cose-lib/src/Algorithm/Signature/RSA/PS256.php',
        '_ContaoManager\\Cose\\Algorithm\\Signature\\RSA\\PS384' => __DIR__ . '/..' . '/web-auth/cose-lib/src/Algorithm/Signature/RSA/PS384.php',
        '_ContaoManager\\Cose\\Algorithm\\Signature\\RSA\\PS512' => __DIR__ . '/..' . '/web-auth/cose-lib/src/Algorithm/Signature/RSA/PS512.php',
        '_ContaoManager\\Cose\\Algorithm\\Signature\\RSA\\PSSRSA' => __DIR__ . '/..' . '/web-auth/cose-lib/src/Algorithm/Signature/RSA/PSSRSA.php',
        '_ContaoManager\\Cose\\Algorithm\\Signature\\RSA\\RS1' => __DIR__ . '/..' . '/web-auth/cose-lib/src/Algorithm/Signature/RSA/RS1.php',
        '_ContaoManager\\Cose\\Algorithm\\Signature\\RSA\\RS256' => __DIR__ . '/..' . '/web-auth/cose-lib/src/Algorithm/Signature/RSA/RS256.php',
        '_ContaoManager\\Cose\\Algorithm\\Signature\\RSA\\RS384' => __DIR__ . '/..' . '/web-auth/cose-lib/src/Algorithm/Signature/RSA/RS384.php',
        '_ContaoManager\\Cose\\Algorithm\\Signature\\RSA\\RS512' => __DIR__ . '/..' . '/web-auth/cose-lib/src/Algorithm/Signature/RSA/RS512.php',
        '_ContaoManager\\Cose\\Algorithm\\Signature\\RSA\\RSA' => __DIR__ . '/..' . '/web-auth/cose-lib/src/Algorithm/Signature/RSA/RSA.php',
        '_ContaoManager\\Cose\\Algorithm\\Signature\\Signature' => __DIR__ . '/..' . '/web-auth/cose-lib/src/Algorithm/Signature/Signature.php',
        '_ContaoManager\\Cose\\Algorithms' => __DIR__ . '/..' . '/web-auth/cose-lib/src/Algorithms.php',
        '_ContaoManager\\Cose\\BigInteger' => __DIR__ . '/..' . '/web-auth/cose-lib/src/BigInteger.php',
        '_ContaoManager\\Cose\\Encryption\\CoseEncrypt0Tag' => __DIR__ . '/..' . '/web-auth/cose-lib/src/Encryption/CoseEncrypt0Tag.php',
        '_ContaoManager\\Cose\\Encryption\\CoseEncryptTag' => __DIR__ . '/..' . '/web-auth/cose-lib/src/Encryption/CoseEncryptTag.php',
        '_ContaoManager\\Cose\\Hash' => __DIR__ . '/..' . '/web-auth/cose-lib/src/Hash.php',
        '_ContaoManager\\Cose\\Key\\Ec2Key' => __DIR__ . '/..' . '/web-auth/cose-lib/src/Key/Ec2Key.php',
        '_ContaoManager\\Cose\\Key\\Key' => __DIR__ . '/..' . '/web-auth/cose-lib/src/Key/Key.php',
        '_ContaoManager\\Cose\\Key\\OkpKey' => __DIR__ . '/..' . '/web-auth/cose-lib/src/Key/OkpKey.php',
        '_ContaoManager\\Cose\\Key\\RsaKey' => __DIR__ . '/..' . '/web-auth/cose-lib/src/Key/RsaKey.php',
        '_ContaoManager\\Cose\\Key\\SymmetricKey' => __DIR__ . '/..' . '/web-auth/cose-lib/src/Key/SymmetricKey.php',
        '_ContaoManager\\Cose\\Mac\\CoseMac0Tag' => __DIR__ . '/..' . '/web-auth/cose-lib/src/Mac/CoseMac0Tag.php',
        '_ContaoManager\\Cose\\Mac\\CoseMacTag' => __DIR__ . '/..' . '/web-auth/cose-lib/src/Mac/CoseMacTag.php',
        '_ContaoManager\\Cose\\Signature\\CoseSign1Tag' => __DIR__ . '/..' . '/web-auth/cose-lib/src/Signature/CoseSign1Tag.php',
        '_ContaoManager\\Cose\\Signature\\CoseSignTag' => __DIR__ . '/..' . '/web-auth/cose-lib/src/Signature/CoseSignTag.php',
        '_ContaoManager\\Cose\\Signature\\Signature1' => __DIR__ . '/..' . '/web-auth/cose-lib/src/Signature/Signature1.php',
        '_ContaoManager\\Crell\\ApiProblem\\ApiProblem' => __DIR__ . '/..' . '/crell/api-problem/src/ApiProblem.php',
        '_ContaoManager\\Crell\\ApiProblem\\HttpConverter' => __DIR__ . '/..' . '/crell/api-problem/src/HttpConverter.php',
        '_ContaoManager\\Crell\\ApiProblem\\JsonEncodeException' => __DIR__ . '/..' . '/crell/api-problem/src/JsonEncodeException.php',
        '_ContaoManager\\Crell\\ApiProblem\\JsonException' => __DIR__ . '/..' . '/crell/api-problem/src/JsonException.php',
        '_ContaoManager\\Crell\\ApiProblem\\JsonParseException' => __DIR__ . '/..' . '/crell/api-problem/src/JsonParseException.php',
        '_ContaoManager\\Doctrine\\Deprecations\\Deprecation' => __DIR__ . '/..' . '/doctrine/deprecations/src/Deprecation.php',
        '_ContaoManager\\Doctrine\\Deprecations\\PHPUnit\\VerifyDeprecations' => __DIR__ . '/..' . '/doctrine/deprecations/src/PHPUnit/VerifyDeprecations.php',
        '_ContaoManager\\Firebase\\JWT\\BeforeValidException' => __DIR__ . '/..' . '/firebase/php-jwt/src/BeforeValidException.php',
        '_ContaoManager\\Firebase\\JWT\\CachedKeySet' => __DIR__ . '/..' . '/firebase/php-jwt/src/CachedKeySet.php',
        '_ContaoManager\\Firebase\\JWT\\ExpiredException' => __DIR__ . '/..' . '/firebase/php-jwt/src/ExpiredException.php',
        '_ContaoManager\\Firebase\\JWT\\JWK' => __DIR__ . '/..' . '/firebase/php-jwt/src/JWK.php',
        '_ContaoManager\\Firebase\\JWT\\JWT' => __DIR__ . '/..' . '/firebase/php-jwt/src/JWT.php',
        '_ContaoManager\\Firebase\\JWT\\JWTExceptionWithPayloadInterface' => __DIR__ . '/..' . '/firebase/php-jwt/src/JWTExceptionWithPayloadInterface.php',
        '_ContaoManager\\Firebase\\JWT\\Key' => __DIR__ . '/..' . '/firebase/php-jwt/src/Key.php',
        '_ContaoManager\\Firebase\\JWT\\SignatureInvalidException' => __DIR__ . '/..' . '/firebase/php-jwt/src/SignatureInvalidException.php',
        '_ContaoManager\\JsonSchema\\ConstraintError' => __DIR__ . '/..' . '/justinrainbow/json-schema/src/JsonSchema/ConstraintError.php',
        '_ContaoManager\\JsonSchema\\Constraints\\BaseConstraint' => __DIR__ . '/..' . '/justinrainbow/json-schema/src/JsonSchema/Constraints/BaseConstraint.php',
        '_ContaoManager\\JsonSchema\\Constraints\\CollectionConstraint' => __DIR__ . '/..' . '/justinrainbow/json-schema/src/JsonSchema/Constraints/CollectionConstraint.php',
        '_ContaoManager\\JsonSchema\\Constraints\\ConstConstraint' => __DIR__ . '/..' . '/justinrainbow/json-schema/src/JsonSchema/Constraints/ConstConstraint.php',
        '_ContaoManager\\JsonSchema\\Constraints\\Constraint' => __DIR__ . '/..' . '/justinrainbow/json-schema/src/JsonSchema/Constraints/Constraint.php',
        '_ContaoManager\\JsonSchema\\Constraints\\ConstraintInterface' => __DIR__ . '/..' . '/justinrainbow/json-schema/src/JsonSchema/Constraints/ConstraintInterface.php',
        '_ContaoManager\\JsonSchema\\Constraints\\Drafts\\Draft06\\AdditionalItemsConstraint' => __DIR__ . '/..' . '/justinrainbow/json-schema/src/JsonSchema/Constraints/Drafts/Draft06/AdditionalItemsConstraint.php',
        '_ContaoManager\\JsonSchema\\Constraints\\Drafts\\Draft06\\AdditionalPropertiesConstraint' => __DIR__ . '/..' . '/justinrainbow/json-schema/src/JsonSchema/Constraints/Drafts/Draft06/AdditionalPropertiesConstraint.php',
        '_ContaoManager\\JsonSchema\\Constraints\\Drafts\\Draft06\\AllOfConstraint' => __DIR__ . '/..' . '/justinrainbow/json-schema/src/JsonSchema/Constraints/Drafts/Draft06/AllOfConstraint.php',
        '_ContaoManager\\JsonSchema\\Constraints\\Drafts\\Draft06\\AnyOfConstraint' => __DIR__ . '/..' . '/justinrainbow/json-schema/src/JsonSchema/Constraints/Drafts/Draft06/AnyOfConstraint.php',
        '_ContaoManager\\JsonSchema\\Constraints\\Drafts\\Draft06\\ConstConstraint' => __DIR__ . '/..' . '/justinrainbow/json-schema/src/JsonSchema/Constraints/Drafts/Draft06/ConstConstraint.php',
        '_ContaoManager\\JsonSchema\\Constraints\\Drafts\\Draft06\\ContainsConstraint' => __DIR__ . '/..' . '/justinrainbow/json-schema/src/JsonSchema/Constraints/Drafts/Draft06/ContainsConstraint.php',
        '_ContaoManager\\JsonSchema\\Constraints\\Drafts\\Draft06\\DependenciesConstraint' => __DIR__ . '/..' . '/justinrainbow/json-schema/src/JsonSchema/Constraints/Drafts/Draft06/DependenciesConstraint.php',
        '_ContaoManager\\JsonSchema\\Constraints\\Drafts\\Draft06\\Draft06Constraint' => __DIR__ . '/..' . '/justinrainbow/json-schema/src/JsonSchema/Constraints/Drafts/Draft06/Draft06Constraint.php',
        '_ContaoManager\\JsonSchema\\Constraints\\Drafts\\Draft06\\EnumConstraint' => __DIR__ . '/..' . '/justinrainbow/json-schema/src/JsonSchema/Constraints/Drafts/Draft06/EnumConstraint.php',
        '_ContaoManager\\JsonSchema\\Constraints\\Drafts\\Draft06\\ExclusiveMaximumConstraint' => __DIR__ . '/..' . '/justinrainbow/json-schema/src/JsonSchema/Constraints/Drafts/Draft06/ExclusiveMaximumConstraint.php',
        '_ContaoManager\\JsonSchema\\Constraints\\Drafts\\Draft06\\ExclusiveMinimumConstraint' => __DIR__ . '/..' . '/justinrainbow/json-schema/src/JsonSchema/Constraints/Drafts/Draft06/ExclusiveMinimumConstraint.php',
        '_ContaoManager\\JsonSchema\\Constraints\\Drafts\\Draft06\\Factory' => __DIR__ . '/..' . '/justinrainbow/json-schema/src/JsonSchema/Constraints/Drafts/Draft06/Factory.php',
        '_ContaoManager\\JsonSchema\\Constraints\\Drafts\\Draft06\\FormatConstraint' => __DIR__ . '/..' . '/justinrainbow/json-schema/src/JsonSchema/Constraints/Drafts/Draft06/FormatConstraint.php',
        '_ContaoManager\\JsonSchema\\Constraints\\Drafts\\Draft06\\ItemsConstraint' => __DIR__ . '/..' . '/justinrainbow/json-schema/src/JsonSchema/Constraints/Drafts/Draft06/ItemsConstraint.php',
        '_ContaoManager\\JsonSchema\\Constraints\\Drafts\\Draft06\\MaxItemsConstraint' => __DIR__ . '/..' . '/justinrainbow/json-schema/src/JsonSchema/Constraints/Drafts/Draft06/MaxItemsConstraint.php',
        '_ContaoManager\\JsonSchema\\Constraints\\Drafts\\Draft06\\MaxLengthConstraint' => __DIR__ . '/..' . '/justinrainbow/json-schema/src/JsonSchema/Constraints/Drafts/Draft06/MaxLengthConstraint.php',
        '_ContaoManager\\JsonSchema\\Constraints\\Drafts\\Draft06\\MaxPropertiesConstraint' => __DIR__ . '/..' . '/justinrainbow/json-schema/src/JsonSchema/Constraints/Drafts/Draft06/MaxPropertiesConstraint.php',
        '_ContaoManager\\JsonSchema\\Constraints\\Drafts\\Draft06\\MaximumConstraint' => __DIR__ . '/..' . '/justinrainbow/json-schema/src/JsonSchema/Constraints/Drafts/Draft06/MaximumConstraint.php',
        '_ContaoManager\\JsonSchema\\Constraints\\Drafts\\Draft06\\MinItemsConstraint' => __DIR__ . '/..' . '/justinrainbow/json-schema/src/JsonSchema/Constraints/Drafts/Draft06/MinItemsConstraint.php',
        '_ContaoManager\\JsonSchema\\Constraints\\Drafts\\Draft06\\MinLengthConstraint' => __DIR__ . '/..' . '/justinrainbow/json-schema/src/JsonSchema/Constraints/Drafts/Draft06/MinLengthConstraint.php',
        '_ContaoManager\\JsonSchema\\Constraints\\Drafts\\Draft06\\MinPropertiesConstraint' => __DIR__ . '/..' . '/justinrainbow/json-schema/src/JsonSchema/Constraints/Drafts/Draft06/MinPropertiesConstraint.php',
        '_ContaoManager\\JsonSchema\\Constraints\\Drafts\\Draft06\\MinimumConstraint' => __DIR__ . '/..' . '/justinrainbow/json-schema/src/JsonSchema/Constraints/Drafts/Draft06/MinimumConstraint.php',
        '_ContaoManager\\JsonSchema\\Constraints\\Drafts\\Draft06\\MultipleOfConstraint' => __DIR__ . '/..' . '/justinrainbow/json-schema/src/JsonSchema/Constraints/Drafts/Draft06/MultipleOfConstraint.php',
        '_ContaoManager\\JsonSchema\\Constraints\\Drafts\\Draft06\\NotConstraint' => __DIR__ . '/..' . '/justinrainbow/json-schema/src/JsonSchema/Constraints/Drafts/Draft06/NotConstraint.php',
        '_ContaoManager\\JsonSchema\\Constraints\\Drafts\\Draft06\\OneOfConstraint' => __DIR__ . '/..' . '/justinrainbow/json-schema/src/JsonSchema/Constraints/Drafts/Draft06/OneOfConstraint.php',
        '_ContaoManager\\JsonSchema\\Constraints\\Drafts\\Draft06\\PatternConstraint' => __DIR__ . '/..' . '/justinrainbow/json-schema/src/JsonSchema/Constraints/Drafts/Draft06/PatternConstraint.php',
        '_ContaoManager\\JsonSchema\\Constraints\\Drafts\\Draft06\\PatternPropertiesConstraint' => __DIR__ . '/..' . '/justinrainbow/json-schema/src/JsonSchema/Constraints/Drafts/Draft06/PatternPropertiesConstraint.php',
        '_ContaoManager\\JsonSchema\\Constraints\\Drafts\\Draft06\\PropertiesConstraint' => __DIR__ . '/..' . '/justinrainbow/json-schema/src/JsonSchema/Constraints/Drafts/Draft06/PropertiesConstraint.php',
        '_ContaoManager\\JsonSchema\\Constraints\\Drafts\\Draft06\\PropertiesNamesConstraint' => __DIR__ . '/..' . '/justinrainbow/json-schema/src/JsonSchema/Constraints/Drafts/Draft06/PropertiesNamesConstraint.php',
        '_ContaoManager\\JsonSchema\\Constraints\\Drafts\\Draft06\\RefConstraint' => __DIR__ . '/..' . '/justinrainbow/json-schema/src/JsonSchema/Constraints/Drafts/Draft06/RefConstraint.php',
        '_ContaoManager\\JsonSchema\\Constraints\\Drafts\\Draft06\\RequiredConstraint' => __DIR__ . '/..' . '/justinrainbow/json-schema/src/JsonSchema/Constraints/Drafts/Draft06/RequiredConstraint.php',
        '_ContaoManager\\JsonSchema\\Constraints\\Drafts\\Draft06\\TypeConstraint' => __DIR__ . '/..' . '/justinrainbow/json-schema/src/JsonSchema/Constraints/Drafts/Draft06/TypeConstraint.php',
        '_ContaoManager\\JsonSchema\\Constraints\\Drafts\\Draft06\\UniqueItemsConstraint' => __DIR__ . '/..' . '/justinrainbow/json-schema/src/JsonSchema/Constraints/Drafts/Draft06/UniqueItemsConstraint.php',
        '_ContaoManager\\JsonSchema\\Constraints\\Drafts\\Draft07\\AdditionalItemsConstraint' => __DIR__ . '/..' . '/justinrainbow/json-schema/src/JsonSchema/Constraints/Drafts/Draft07/AdditionalItemsConstraint.php',
        '_ContaoManager\\JsonSchema\\Constraints\\Drafts\\Draft07\\AdditionalPropertiesConstraint' => __DIR__ . '/..' . '/justinrainbow/json-schema/src/JsonSchema/Constraints/Drafts/Draft07/AdditionalPropertiesConstraint.php',
        '_ContaoManager\\JsonSchema\\Constraints\\Drafts\\Draft07\\AllOfConstraint' => __DIR__ . '/..' . '/justinrainbow/json-schema/src/JsonSchema/Constraints/Drafts/Draft07/AllOfConstraint.php',
        '_ContaoManager\\JsonSchema\\Constraints\\Drafts\\Draft07\\AnyOfConstraint' => __DIR__ . '/..' . '/justinrainbow/json-schema/src/JsonSchema/Constraints/Drafts/Draft07/AnyOfConstraint.php',
        '_ContaoManager\\JsonSchema\\Constraints\\Drafts\\Draft07\\ConstConstraint' => __DIR__ . '/..' . '/justinrainbow/json-schema/src/JsonSchema/Constraints/Drafts/Draft07/ConstConstraint.php',
        '_ContaoManager\\JsonSchema\\Constraints\\Drafts\\Draft07\\ContainsConstraint' => __DIR__ . '/..' . '/justinrainbow/json-schema/src/JsonSchema/Constraints/Drafts/Draft07/ContainsConstraint.php',
        '_ContaoManager\\JsonSchema\\Constraints\\Drafts\\Draft07\\ContentConstraint' => __DIR__ . '/..' . '/justinrainbow/json-schema/src/JsonSchema/Constraints/Drafts/Draft07/ContentConstraint.php',
        '_ContaoManager\\JsonSchema\\Constraints\\Drafts\\Draft07\\DependenciesConstraint' => __DIR__ . '/..' . '/justinrainbow/json-schema/src/JsonSchema/Constraints/Drafts/Draft07/DependenciesConstraint.php',
        '_ContaoManager\\JsonSchema\\Constraints\\Drafts\\Draft07\\Draft07Constraint' => __DIR__ . '/..' . '/justinrainbow/json-schema/src/JsonSchema/Constraints/Drafts/Draft07/Draft07Constraint.php',
        '_ContaoManager\\JsonSchema\\Constraints\\Drafts\\Draft07\\EnumConstraint' => __DIR__ . '/..' . '/justinrainbow/json-schema/src/JsonSchema/Constraints/Drafts/Draft07/EnumConstraint.php',
        '_ContaoManager\\JsonSchema\\Constraints\\Drafts\\Draft07\\ExclusiveMaximumConstraint' => __DIR__ . '/..' . '/justinrainbow/json-schema/src/JsonSchema/Constraints/Drafts/Draft07/ExclusiveMaximumConstraint.php',
        '_ContaoManager\\JsonSchema\\Constraints\\Drafts\\Draft07\\ExclusiveMinimumConstraint' => __DIR__ . '/..' . '/justinrainbow/json-schema/src/JsonSchema/Constraints/Drafts/Draft07/ExclusiveMinimumConstraint.php',
        '_ContaoManager\\JsonSchema\\Constraints\\Drafts\\Draft07\\Factory' => __DIR__ . '/..' . '/justinrainbow/json-schema/src/JsonSchema/Constraints/Drafts/Draft07/Factory.php',
        '_ContaoManager\\JsonSchema\\Constraints\\Drafts\\Draft07\\FormatConstraint' => __DIR__ . '/..' . '/justinrainbow/json-schema/src/JsonSchema/Constraints/Drafts/Draft07/FormatConstraint.php',
        '_ContaoManager\\JsonSchema\\Constraints\\Drafts\\Draft07\\IfThenElseConstraint' => __DIR__ . '/..' . '/justinrainbow/json-schema/src/JsonSchema/Constraints/Drafts/Draft07/IfThenElseConstraint.php',
        '_ContaoManager\\JsonSchema\\Constraints\\Drafts\\Draft07\\ItemsConstraint' => __DIR__ . '/..' . '/justinrainbow/json-schema/src/JsonSchema/Constraints/Drafts/Draft07/ItemsConstraint.php',
        '_ContaoManager\\JsonSchema\\Constraints\\Drafts\\Draft07\\MaxItemsConstraint' => __DIR__ . '/..' . '/justinrainbow/json-schema/src/JsonSchema/Constraints/Drafts/Draft07/MaxItemsConstraint.php',
        '_ContaoManager\\JsonSchema\\Constraints\\Drafts\\Draft07\\MaxLengthConstraint' => __DIR__ . '/..' . '/justinrainbow/json-schema/src/JsonSchema/Constraints/Drafts/Draft07/MaxLengthConstraint.php',
        '_ContaoManager\\JsonSchema\\Constraints\\Drafts\\Draft07\\MaxPropertiesConstraint' => __DIR__ . '/..' . '/justinrainbow/json-schema/src/JsonSchema/Constraints/Drafts/Draft07/MaxPropertiesConstraint.php',
        '_ContaoManager\\JsonSchema\\Constraints\\Drafts\\Draft07\\MaximumConstraint' => __DIR__ . '/..' . '/justinrainbow/json-schema/src/JsonSchema/Constraints/Drafts/Draft07/MaximumConstraint.php',
        '_ContaoManager\\JsonSchema\\Constraints\\Drafts\\Draft07\\MinItemsConstraint' => __DIR__ . '/..' . '/justinrainbow/json-schema/src/JsonSchema/Constraints/Drafts/Draft07/MinItemsConstraint.php',
        '_ContaoManager\\JsonSchema\\Constraints\\Drafts\\Draft07\\MinLengthConstraint' => __DIR__ . '/..' . '/justinrainbow/json-schema/src/JsonSchema/Constraints/Drafts/Draft07/MinLengthConstraint.php',
        '_ContaoManager\\JsonSchema\\Constraints\\Drafts\\Draft07\\MinPropertiesConstraint' => __DIR__ . '/..' . '/justinrainbow/json-schema/src/JsonSchema/Constraints/Drafts/Draft07/MinPropertiesConstraint.php',
        '_ContaoManager\\JsonSchema\\Constraints\\Drafts\\Draft07\\MinimumConstraint' => __DIR__ . '/..' . '/justinrainbow/json-schema/src/JsonSchema/Constraints/Drafts/Draft07/MinimumConstraint.php',
        '_ContaoManager\\JsonSchema\\Constraints\\Drafts\\Draft07\\MultipleOfConstraint' => __DIR__ . '/..' . '/justinrainbow/json-schema/src/JsonSchema/Constraints/Drafts/Draft07/MultipleOfConstraint.php',
        '_ContaoManager\\JsonSchema\\Constraints\\Drafts\\Draft07\\NotConstraint' => __DIR__ . '/..' . '/justinrainbow/json-schema/src/JsonSchema/Constraints/Drafts/Draft07/NotConstraint.php',
        '_ContaoManager\\JsonSchema\\Constraints\\Drafts\\Draft07\\OneOfConstraint' => __DIR__ . '/..' . '/justinrainbow/json-schema/src/JsonSchema/Constraints/Drafts/Draft07/OneOfConstraint.php',
        '_ContaoManager\\JsonSchema\\Constraints\\Drafts\\Draft07\\PatternConstraint' => __DIR__ . '/..' . '/justinrainbow/json-schema/src/JsonSchema/Constraints/Drafts/Draft07/PatternConstraint.php',
        '_ContaoManager\\JsonSchema\\Constraints\\Drafts\\Draft07\\PatternPropertiesConstraint' => __DIR__ . '/..' . '/justinrainbow/json-schema/src/JsonSchema/Constraints/Drafts/Draft07/PatternPropertiesConstraint.php',
        '_ContaoManager\\JsonSchema\\Constraints\\Drafts\\Draft07\\PropertiesConstraint' => __DIR__ . '/..' . '/justinrainbow/json-schema/src/JsonSchema/Constraints/Drafts/Draft07/PropertiesConstraint.php',
        '_ContaoManager\\JsonSchema\\Constraints\\Drafts\\Draft07\\PropertiesNamesConstraint' => __DIR__ . '/..' . '/justinrainbow/json-schema/src/JsonSchema/Constraints/Drafts/Draft07/PropertiesNamesConstraint.php',
        '_ContaoManager\\JsonSchema\\Constraints\\Drafts\\Draft07\\RefConstraint' => __DIR__ . '/..' . '/justinrainbow/json-schema/src/JsonSchema/Constraints/Drafts/Draft07/RefConstraint.php',
        '_ContaoManager\\JsonSchema\\Constraints\\Drafts\\Draft07\\RequiredConstraint' => __DIR__ . '/..' . '/justinrainbow/json-schema/src/JsonSchema/Constraints/Drafts/Draft07/RequiredConstraint.php',
        '_ContaoManager\\JsonSchema\\Constraints\\Drafts\\Draft07\\TypeConstraint' => __DIR__ . '/..' . '/justinrainbow/json-schema/src/JsonSchema/Constraints/Drafts/Draft07/TypeConstraint.php',
        '_ContaoManager\\JsonSchema\\Constraints\\Drafts\\Draft07\\UniqueItemsConstraint' => __DIR__ . '/..' . '/justinrainbow/json-schema/src/JsonSchema/Constraints/Drafts/Draft07/UniqueItemsConstraint.php',
        '_ContaoManager\\JsonSchema\\Constraints\\EnumConstraint' => __DIR__ . '/..' . '/justinrainbow/json-schema/src/JsonSchema/Constraints/EnumConstraint.php',
        '_ContaoManager\\JsonSchema\\Constraints\\Factory' => __DIR__ . '/..' . '/justinrainbow/json-schema/src/JsonSchema/Constraints/Factory.php',
        '_ContaoManager\\JsonSchema\\Constraints\\FormatConstraint' => __DIR__ . '/..' . '/justinrainbow/json-schema/src/JsonSchema/Constraints/FormatConstraint.php',
        '_ContaoManager\\JsonSchema\\Constraints\\NumberConstraint' => __DIR__ . '/..' . '/justinrainbow/json-schema/src/JsonSchema/Constraints/NumberConstraint.php',
        '_ContaoManager\\JsonSchema\\Constraints\\ObjectConstraint' => __DIR__ . '/..' . '/justinrainbow/json-schema/src/JsonSchema/Constraints/ObjectConstraint.php',
        '_ContaoManager\\JsonSchema\\Constraints\\SchemaConstraint' => __DIR__ . '/..' . '/justinrainbow/json-schema/src/JsonSchema/Constraints/SchemaConstraint.php',
        '_ContaoManager\\JsonSchema\\Constraints\\StringConstraint' => __DIR__ . '/..' . '/justinrainbow/json-schema/src/JsonSchema/Constraints/StringConstraint.php',
        '_ContaoManager\\JsonSchema\\Constraints\\TypeCheck\\LooseTypeCheck' => __DIR__ . '/..' . '/justinrainbow/json-schema/src/JsonSchema/Constraints/TypeCheck/LooseTypeCheck.php',
        '_ContaoManager\\JsonSchema\\Constraints\\TypeCheck\\StrictTypeCheck' => __DIR__ . '/..' . '/justinrainbow/json-schema/src/JsonSchema/Constraints/TypeCheck/StrictTypeCheck.php',
        '_ContaoManager\\JsonSchema\\Constraints\\TypeCheck\\TypeCheckInterface' => __DIR__ . '/..' . '/justinrainbow/json-schema/src/JsonSchema/Constraints/TypeCheck/TypeCheckInterface.php',
        '_ContaoManager\\JsonSchema\\Constraints\\TypeConstraint' => __DIR__ . '/..' . '/justinrainbow/json-schema/src/JsonSchema/Constraints/TypeConstraint.php',
        '_ContaoManager\\JsonSchema\\Constraints\\UndefinedConstraint' => __DIR__ . '/..' . '/justinrainbow/json-schema/src/JsonSchema/Constraints/UndefinedConstraint.php',
        '_ContaoManager\\JsonSchema\\DraftIdentifiers' => __DIR__ . '/..' . '/justinrainbow/json-schema/src/JsonSchema/DraftIdentifiers.php',
        '_ContaoManager\\JsonSchema\\Entity\\ErrorBag' => __DIR__ . '/..' . '/justinrainbow/json-schema/src/JsonSchema/Entity/ErrorBag.php',
        '_ContaoManager\\JsonSchema\\Entity\\ErrorBagProxy' => __DIR__ . '/..' . '/justinrainbow/json-schema/src/JsonSchema/Entity/ErrorBagProxy.php',
        '_ContaoManager\\JsonSchema\\Entity\\JsonPointer' => __DIR__ . '/..' . '/justinrainbow/json-schema/src/JsonSchema/Entity/JsonPointer.php',
        '_ContaoManager\\JsonSchema\\Enum' => __DIR__ . '/..' . '/justinrainbow/json-schema/src/JsonSchema/Enum.php',
        '_ContaoManager\\JsonSchema\\Exception\\ExceptionInterface' => __DIR__ . '/..' . '/justinrainbow/json-schema/src/JsonSchema/Exception/ExceptionInterface.php',
        '_ContaoManager\\JsonSchema\\Exception\\InvalidArgumentException' => __DIR__ . '/..' . '/justinrainbow/json-schema/src/JsonSchema/Exception/InvalidArgumentException.php',
        '_ContaoManager\\JsonSchema\\Exception\\InvalidConfigException' => __DIR__ . '/..' . '/justinrainbow/json-schema/src/JsonSchema/Exception/InvalidConfigException.php',
        '_ContaoManager\\JsonSchema\\Exception\\InvalidSchemaException' => __DIR__ . '/..' . '/justinrainbow/json-schema/src/JsonSchema/Exception/InvalidSchemaException.php',
        '_ContaoManager\\JsonSchema\\Exception\\InvalidSchemaMediaTypeException' => __DIR__ . '/..' . '/justinrainbow/json-schema/src/JsonSchema/Exception/InvalidSchemaMediaTypeException.php',
        '_ContaoManager\\JsonSchema\\Exception\\InvalidSourceUriException' => __DIR__ . '/..' . '/justinrainbow/json-schema/src/JsonSchema/Exception/InvalidSourceUriException.php',
        '_ContaoManager\\JsonSchema\\Exception\\JsonDecodingException' => __DIR__ . '/..' . '/justinrainbow/json-schema/src/JsonSchema/Exception/JsonDecodingException.php',
        '_ContaoManager\\JsonSchema\\Exception\\ResourceNotFoundException' => __DIR__ . '/..' . '/justinrainbow/json-schema/src/JsonSchema/Exception/ResourceNotFoundException.php',
        '_ContaoManager\\JsonSchema\\Exception\\RuntimeException' => __DIR__ . '/..' . '/justinrainbow/json-schema/src/JsonSchema/Exception/RuntimeException.php',
        '_ContaoManager\\JsonSchema\\Exception\\UnresolvableJsonPointerException' => __DIR__ . '/..' . '/justinrainbow/json-schema/src/JsonSchema/Exception/UnresolvableJsonPointerException.php',
        '_ContaoManager\\JsonSchema\\Exception\\UriResolverException' => __DIR__ . '/..' . '/justinrainbow/json-schema/src/JsonSchema/Exception/UriResolverException.php',
        '_ContaoManager\\JsonSchema\\Exception\\ValidationException' => __DIR__ . '/..' . '/justinrainbow/json-schema/src/JsonSchema/Exception/ValidationException.php',
        '_ContaoManager\\JsonSchema\\Iterator\\ObjectIterator' => __DIR__ . '/..' . '/justinrainbow/json-schema/src/JsonSchema/Iterator/ObjectIterator.php',
        '_ContaoManager\\JsonSchema\\Rfc3339' => __DIR__ . '/..' . '/justinrainbow/json-schema/src/JsonSchema/Rfc3339.php',
        '_ContaoManager\\JsonSchema\\SchemaStorage' => __DIR__ . '/..' . '/justinrainbow/json-schema/src/JsonSchema/SchemaStorage.php',
        '_ContaoManager\\JsonSchema\\SchemaStorageInterface' => __DIR__ . '/..' . '/justinrainbow/json-schema/src/JsonSchema/SchemaStorageInterface.php',
        '_ContaoManager\\JsonSchema\\Tool\\DeepComparer' => __DIR__ . '/..' . '/justinrainbow/json-schema/src/JsonSchema/Tool/DeepComparer.php',
        '_ContaoManager\\JsonSchema\\Tool\\DeepCopy' => __DIR__ . '/..' . '/justinrainbow/json-schema/src/JsonSchema/Tool/DeepCopy.php',
        '_ContaoManager\\JsonSchema\\Tool\\Validator\\RelativeReferenceValidator' => __DIR__ . '/..' . '/justinrainbow/json-schema/src/JsonSchema/Tool/Validator/RelativeReferenceValidator.php',
        '_ContaoManager\\JsonSchema\\Tool\\Validator\\UriValidator' => __DIR__ . '/..' . '/justinrainbow/json-schema/src/JsonSchema/Tool/Validator/UriValidator.php',
        '_ContaoManager\\JsonSchema\\UriResolverInterface' => __DIR__ . '/..' . '/justinrainbow/json-schema/src/JsonSchema/UriResolverInterface.php',
        '_ContaoManager\\JsonSchema\\UriRetrieverInterface' => __DIR__ . '/..' . '/justinrainbow/json-schema/src/JsonSchema/UriRetrieverInterface.php',
        '_ContaoManager\\JsonSchema\\Uri\\Retrievers\\AbstractRetriever' => __DIR__ . '/..' . '/justinrainbow/json-schema/src/JsonSchema/Uri/Retrievers/AbstractRetriever.php',
        '_ContaoManager\\JsonSchema\\Uri\\Retrievers\\Curl' => __DIR__ . '/..' . '/justinrainbow/json-schema/src/JsonSchema/Uri/Retrievers/Curl.php',
        '_ContaoManager\\JsonSchema\\Uri\\Retrievers\\FileGetContents' => __DIR__ . '/..' . '/justinrainbow/json-schema/src/JsonSchema/Uri/Retrievers/FileGetContents.php',
        '_ContaoManager\\JsonSchema\\Uri\\Retrievers\\PredefinedArray' => __DIR__ . '/..' . '/justinrainbow/json-schema/src/JsonSchema/Uri/Retrievers/PredefinedArray.php',
        '_ContaoManager\\JsonSchema\\Uri\\Retrievers\\UriRetrieverInterface' => __DIR__ . '/..' . '/justinrainbow/json-schema/src/JsonSchema/Uri/Retrievers/UriRetrieverInterface.php',
        '_ContaoManager\\JsonSchema\\Uri\\UriResolver' => __DIR__ . '/..' . '/justinrainbow/json-schema/src/JsonSchema/Uri/UriResolver.php',
        '_ContaoManager\\JsonSchema\\Uri\\UriRetriever' => __DIR__ . '/..' . '/justinrainbow/json-schema/src/JsonSchema/Uri/UriRetriever.php',
        '_ContaoManager\\JsonSchema\\Validator' => __DIR__ . '/..' . '/justinrainbow/json-schema/src/JsonSchema/Validator.php',
        '_ContaoManager\\Lcobucci\\Clock\\Clock' => __DIR__ . '/..' . '/lcobucci/clock/src/Clock.php',
        '_ContaoManager\\Lcobucci\\Clock\\FrozenClock' => __DIR__ . '/..' . '/lcobucci/clock/src/FrozenClock.php',
        '_ContaoManager\\Lcobucci\\Clock\\SystemClock' => __DIR__ . '/..' . '/lcobucci/clock/src/SystemClock.php',
        '_ContaoManager\\MabeEnum\\Enum' => __DIR__ . '/..' . '/marc-mabe/php-enum/src/Enum.php',
        '_ContaoManager\\MabeEnum\\EnumMap' => __DIR__ . '/..' . '/marc-mabe/php-enum/src/EnumMap.php',
        '_ContaoManager\\MabeEnum\\EnumSerializableTrait' => __DIR__ . '/..' . '/marc-mabe/php-enum/src/EnumSerializableTrait.php',
        '_ContaoManager\\MabeEnum\\EnumSet' => __DIR__ . '/..' . '/marc-mabe/php-enum/src/EnumSet.php',
        '_ContaoManager\\Monolog\\Attribute\\AsMonologProcessor' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Attribute/AsMonologProcessor.php',
        '_ContaoManager\\Monolog\\Attribute\\WithMonologChannel' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Attribute/WithMonologChannel.php',
        '_ContaoManager\\Monolog\\DateTimeImmutable' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/DateTimeImmutable.php',
        '_ContaoManager\\Monolog\\ErrorHandler' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/ErrorHandler.php',
        '_ContaoManager\\Monolog\\Formatter\\ChromePHPFormatter' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Formatter/ChromePHPFormatter.php',
        '_ContaoManager\\Monolog\\Formatter\\ElasticaFormatter' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Formatter/ElasticaFormatter.php',
        '_ContaoManager\\Monolog\\Formatter\\ElasticsearchFormatter' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Formatter/ElasticsearchFormatter.php',
        '_ContaoManager\\Monolog\\Formatter\\FlowdockFormatter' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Formatter/FlowdockFormatter.php',
        '_ContaoManager\\Monolog\\Formatter\\FluentdFormatter' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Formatter/FluentdFormatter.php',
        '_ContaoManager\\Monolog\\Formatter\\FormatterInterface' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Formatter/FormatterInterface.php',
        '_ContaoManager\\Monolog\\Formatter\\GelfMessageFormatter' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Formatter/GelfMessageFormatter.php',
        '_ContaoManager\\Monolog\\Formatter\\GoogleCloudLoggingFormatter' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Formatter/GoogleCloudLoggingFormatter.php',
        '_ContaoManager\\Monolog\\Formatter\\HtmlFormatter' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Formatter/HtmlFormatter.php',
        '_ContaoManager\\Monolog\\Formatter\\JsonFormatter' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Formatter/JsonFormatter.php',
        '_ContaoManager\\Monolog\\Formatter\\LineFormatter' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Formatter/LineFormatter.php',
        '_ContaoManager\\Monolog\\Formatter\\LogglyFormatter' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Formatter/LogglyFormatter.php',
        '_ContaoManager\\Monolog\\Formatter\\LogmaticFormatter' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Formatter/LogmaticFormatter.php',
        '_ContaoManager\\Monolog\\Formatter\\LogstashFormatter' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Formatter/LogstashFormatter.php',
        '_ContaoManager\\Monolog\\Formatter\\MongoDBFormatter' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Formatter/MongoDBFormatter.php',
        '_ContaoManager\\Monolog\\Formatter\\NormalizerFormatter' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Formatter/NormalizerFormatter.php',
        '_ContaoManager\\Monolog\\Formatter\\ScalarFormatter' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Formatter/ScalarFormatter.php',
        '_ContaoManager\\Monolog\\Formatter\\SyslogFormatter' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Formatter/SyslogFormatter.php',
        '_ContaoManager\\Monolog\\Formatter\\WildfireFormatter' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Formatter/WildfireFormatter.php',
        '_ContaoManager\\Monolog\\Handler\\AbstractHandler' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/AbstractHandler.php',
        '_ContaoManager\\Monolog\\Handler\\AbstractProcessingHandler' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/AbstractProcessingHandler.php',
        '_ContaoManager\\Monolog\\Handler\\AbstractSyslogHandler' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/AbstractSyslogHandler.php',
        '_ContaoManager\\Monolog\\Handler\\AmqpHandler' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/AmqpHandler.php',
        '_ContaoManager\\Monolog\\Handler\\BrowserConsoleHandler' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/BrowserConsoleHandler.php',
        '_ContaoManager\\Monolog\\Handler\\BufferHandler' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/BufferHandler.php',
        '_ContaoManager\\Monolog\\Handler\\ChromePHPHandler' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/ChromePHPHandler.php',
        '_ContaoManager\\Monolog\\Handler\\CouchDBHandler' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/CouchDBHandler.php',
        '_ContaoManager\\Monolog\\Handler\\CubeHandler' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/CubeHandler.php',
        '_ContaoManager\\Monolog\\Handler\\Curl\\Util' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/Curl/Util.php',
        '_ContaoManager\\Monolog\\Handler\\DeduplicationHandler' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/DeduplicationHandler.php',
        '_ContaoManager\\Monolog\\Handler\\DoctrineCouchDBHandler' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/DoctrineCouchDBHandler.php',
        '_ContaoManager\\Monolog\\Handler\\DynamoDbHandler' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/DynamoDbHandler.php',
        '_ContaoManager\\Monolog\\Handler\\ElasticaHandler' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/ElasticaHandler.php',
        '_ContaoManager\\Monolog\\Handler\\ElasticsearchHandler' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/ElasticsearchHandler.php',
        '_ContaoManager\\Monolog\\Handler\\ErrorLogHandler' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/ErrorLogHandler.php',
        '_ContaoManager\\Monolog\\Handler\\FallbackGroupHandler' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/FallbackGroupHandler.php',
        '_ContaoManager\\Monolog\\Handler\\FilterHandler' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/FilterHandler.php',
        '_ContaoManager\\Monolog\\Handler\\FingersCrossedHandler' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/FingersCrossedHandler.php',
        '_ContaoManager\\Monolog\\Handler\\FingersCrossed\\ActivationStrategyInterface' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/FingersCrossed/ActivationStrategyInterface.php',
        '_ContaoManager\\Monolog\\Handler\\FingersCrossed\\ChannelLevelActivationStrategy' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/FingersCrossed/ChannelLevelActivationStrategy.php',
        '_ContaoManager\\Monolog\\Handler\\FingersCrossed\\ErrorLevelActivationStrategy' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/FingersCrossed/ErrorLevelActivationStrategy.php',
        '_ContaoManager\\Monolog\\Handler\\FirePHPHandler' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/FirePHPHandler.php',
        '_ContaoManager\\Monolog\\Handler\\FleepHookHandler' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/FleepHookHandler.php',
        '_ContaoManager\\Monolog\\Handler\\FlowdockHandler' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/FlowdockHandler.php',
        '_ContaoManager\\Monolog\\Handler\\FormattableHandlerInterface' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/FormattableHandlerInterface.php',
        '_ContaoManager\\Monolog\\Handler\\FormattableHandlerTrait' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/FormattableHandlerTrait.php',
        '_ContaoManager\\Monolog\\Handler\\GelfHandler' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/GelfHandler.php',
        '_ContaoManager\\Monolog\\Handler\\GroupHandler' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/GroupHandler.php',
        '_ContaoManager\\Monolog\\Handler\\Handler' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/Handler.php',
        '_ContaoManager\\Monolog\\Handler\\HandlerInterface' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/HandlerInterface.php',
        '_ContaoManager\\Monolog\\Handler\\HandlerWrapper' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/HandlerWrapper.php',
        '_ContaoManager\\Monolog\\Handler\\IFTTTHandler' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/IFTTTHandler.php',
        '_ContaoManager\\Monolog\\Handler\\InsightOpsHandler' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/InsightOpsHandler.php',
        '_ContaoManager\\Monolog\\Handler\\LogEntriesHandler' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/LogEntriesHandler.php',
        '_ContaoManager\\Monolog\\Handler\\LogglyHandler' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/LogglyHandler.php',
        '_ContaoManager\\Monolog\\Handler\\LogmaticHandler' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/LogmaticHandler.php',
        '_ContaoManager\\Monolog\\Handler\\MailHandler' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/MailHandler.php',
        '_ContaoManager\\Monolog\\Handler\\MandrillHandler' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/MandrillHandler.php',
        '_ContaoManager\\Monolog\\Handler\\MissingExtensionException' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/MissingExtensionException.php',
        '_ContaoManager\\Monolog\\Handler\\MongoDBHandler' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/MongoDBHandler.php',
        '_ContaoManager\\Monolog\\Handler\\NativeMailerHandler' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/NativeMailerHandler.php',
        '_ContaoManager\\Monolog\\Handler\\NewRelicHandler' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/NewRelicHandler.php',
        '_ContaoManager\\Monolog\\Handler\\NoopHandler' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/NoopHandler.php',
        '_ContaoManager\\Monolog\\Handler\\NullHandler' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/NullHandler.php',
        '_ContaoManager\\Monolog\\Handler\\OverflowHandler' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/OverflowHandler.php',
        '_ContaoManager\\Monolog\\Handler\\PHPConsoleHandler' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/PHPConsoleHandler.php',
        '_ContaoManager\\Monolog\\Handler\\ProcessHandler' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/ProcessHandler.php',
        '_ContaoManager\\Monolog\\Handler\\ProcessableHandlerInterface' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/ProcessableHandlerInterface.php',
        '_ContaoManager\\Monolog\\Handler\\ProcessableHandlerTrait' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/ProcessableHandlerTrait.php',
        '_ContaoManager\\Monolog\\Handler\\PsrHandler' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/PsrHandler.php',
        '_ContaoManager\\Monolog\\Handler\\PushoverHandler' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/PushoverHandler.php',
        '_ContaoManager\\Monolog\\Handler\\RedisHandler' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/RedisHandler.php',
        '_ContaoManager\\Monolog\\Handler\\RedisPubSubHandler' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/RedisPubSubHandler.php',
        '_ContaoManager\\Monolog\\Handler\\RollbarHandler' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/RollbarHandler.php',
        '_ContaoManager\\Monolog\\Handler\\RotatingFileHandler' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/RotatingFileHandler.php',
        '_ContaoManager\\Monolog\\Handler\\SamplingHandler' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/SamplingHandler.php',
        '_ContaoManager\\Monolog\\Handler\\SendGridHandler' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/SendGridHandler.php',
        '_ContaoManager\\Monolog\\Handler\\SlackHandler' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/SlackHandler.php',
        '_ContaoManager\\Monolog\\Handler\\SlackWebhookHandler' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/SlackWebhookHandler.php',
        '_ContaoManager\\Monolog\\Handler\\Slack\\SlackRecord' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/Slack/SlackRecord.php',
        '_ContaoManager\\Monolog\\Handler\\SocketHandler' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/SocketHandler.php',
        '_ContaoManager\\Monolog\\Handler\\SqsHandler' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/SqsHandler.php',
        '_ContaoManager\\Monolog\\Handler\\StreamHandler' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/StreamHandler.php',
        '_ContaoManager\\Monolog\\Handler\\SymfonyMailerHandler' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/SymfonyMailerHandler.php',
        '_ContaoManager\\Monolog\\Handler\\SyslogHandler' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/SyslogHandler.php',
        '_ContaoManager\\Monolog\\Handler\\SyslogUdpHandler' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/SyslogUdpHandler.php',
        '_ContaoManager\\Monolog\\Handler\\SyslogUdp\\UdpSocket' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/SyslogUdp/UdpSocket.php',
        '_ContaoManager\\Monolog\\Handler\\TelegramBotHandler' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/TelegramBotHandler.php',
        '_ContaoManager\\Monolog\\Handler\\TestHandler' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/TestHandler.php',
        '_ContaoManager\\Monolog\\Handler\\WebRequestRecognizerTrait' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/WebRequestRecognizerTrait.php',
        '_ContaoManager\\Monolog\\Handler\\WhatFailureGroupHandler' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/WhatFailureGroupHandler.php',
        '_ContaoManager\\Monolog\\Handler\\ZendMonitorHandler' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/ZendMonitorHandler.php',
        '_ContaoManager\\Monolog\\JsonSerializableDateTimeImmutable' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/JsonSerializableDateTimeImmutable.php',
        '_ContaoManager\\Monolog\\Level' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Level.php',
        '_ContaoManager\\Monolog\\LogRecord' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/LogRecord.php',
        '_ContaoManager\\Monolog\\Logger' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Logger.php',
        '_ContaoManager\\Monolog\\Processor\\ClosureContextProcessor' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Processor/ClosureContextProcessor.php',
        '_ContaoManager\\Monolog\\Processor\\GitProcessor' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Processor/GitProcessor.php',
        '_ContaoManager\\Monolog\\Processor\\HostnameProcessor' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Processor/HostnameProcessor.php',
        '_ContaoManager\\Monolog\\Processor\\IntrospectionProcessor' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Processor/IntrospectionProcessor.php',
        '_ContaoManager\\Monolog\\Processor\\LoadAverageProcessor' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Processor/LoadAverageProcessor.php',
        '_ContaoManager\\Monolog\\Processor\\MemoryPeakUsageProcessor' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Processor/MemoryPeakUsageProcessor.php',
        '_ContaoManager\\Monolog\\Processor\\MemoryProcessor' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Processor/MemoryProcessor.php',
        '_ContaoManager\\Monolog\\Processor\\MemoryUsageProcessor' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Processor/MemoryUsageProcessor.php',
        '_ContaoManager\\Monolog\\Processor\\MercurialProcessor' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Processor/MercurialProcessor.php',
        '_ContaoManager\\Monolog\\Processor\\ProcessIdProcessor' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Processor/ProcessIdProcessor.php',
        '_ContaoManager\\Monolog\\Processor\\ProcessorInterface' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Processor/ProcessorInterface.php',
        '_ContaoManager\\Monolog\\Processor\\PsrLogMessageProcessor' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Processor/PsrLogMessageProcessor.php',
        '_ContaoManager\\Monolog\\Processor\\TagProcessor' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Processor/TagProcessor.php',
        '_ContaoManager\\Monolog\\Processor\\UidProcessor' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Processor/UidProcessor.php',
        '_ContaoManager\\Monolog\\Processor\\WebProcessor' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Processor/WebProcessor.php',
        '_ContaoManager\\Monolog\\Registry' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Registry.php',
        '_ContaoManager\\Monolog\\ResettableInterface' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/ResettableInterface.php',
        '_ContaoManager\\Monolog\\SignalHandler' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/SignalHandler.php',
        '_ContaoManager\\Monolog\\Test\\MonologTestCase' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Test/MonologTestCase.php',
        '_ContaoManager\\Monolog\\Test\\TestCase' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Test/TestCase.php',
        '_ContaoManager\\Monolog\\Utils' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Utils.php',
        '_ContaoManager\\OTPHP\\Exception\\InvalidLabelException' => __DIR__ . '/..' . '/spomky-labs/otphp/src/Exception/InvalidLabelException.php',
        '_ContaoManager\\OTPHP\\Exception\\InvalidParameterException' => __DIR__ . '/..' . '/spomky-labs/otphp/src/Exception/InvalidParameterException.php',
        '_ContaoManager\\OTPHP\\Exception\\InvalidProvisioningUriException' => __DIR__ . '/..' . '/spomky-labs/otphp/src/Exception/InvalidProvisioningUriException.php',
        '_ContaoManager\\OTPHP\\Exception\\OTPExceptionInterface' => __DIR__ . '/..' . '/spomky-labs/otphp/src/Exception/OTPExceptionInterface.php',
        '_ContaoManager\\OTPHP\\Exception\\ParameterNotFoundException' => __DIR__ . '/..' . '/spomky-labs/otphp/src/Exception/ParameterNotFoundException.php',
        '_ContaoManager\\OTPHP\\Exception\\SecretDecodingException' => __DIR__ . '/..' . '/spomky-labs/otphp/src/Exception/SecretDecodingException.php',
        '_ContaoManager\\OTPHP\\Factory' => __DIR__ . '/..' . '/spomky-labs/otphp/src/Factory.php',
        '_ContaoManager\\OTPHP\\FactoryInterface' => __DIR__ . '/..' . '/spomky-labs/otphp/src/FactoryInterface.php',
        '_ContaoManager\\OTPHP\\HOTP' => __DIR__ . '/..' . '/spomky-labs/otphp/src/HOTP.php',
        '_ContaoManager\\OTPHP\\HOTPInterface' => __DIR__ . '/..' . '/spomky-labs/otphp/src/HOTPInterface.php',
        '_ContaoManager\\OTPHP\\InternalClock' => __DIR__ . '/..' . '/spomky-labs/otphp/src/InternalClock.php',
        '_ContaoManager\\OTPHP\\OTP' => __DIR__ . '/..' . '/spomky-labs/otphp/src/OTP.php',
        '_ContaoManager\\OTPHP\\OTPInterface' => __DIR__ . '/..' . '/spomky-labs/otphp/src/OTPInterface.php',
        '_ContaoManager\\OTPHP\\TOTP' => __DIR__ . '/..' . '/spomky-labs/otphp/src/TOTP.php',
        '_ContaoManager\\OTPHP\\TOTPInterface' => __DIR__ . '/..' . '/spomky-labs/otphp/src/TOTPInterface.php',
        '_ContaoManager\\OTPHP\\Url' => __DIR__ . '/..' . '/spomky-labs/otphp/src/Url.php',
        '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\AbstractNodeVisitor' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/AbstractNodeVisitor.php',
        '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\Attribute' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/Attribute.php',
        '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\Comment' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/Comment.php',
        '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\ConstExpr\\ConstExprArrayItemNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/ConstExpr/ConstExprArrayItemNode.php',
        '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\ConstExpr\\ConstExprArrayNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/ConstExpr/ConstExprArrayNode.php',
        '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\ConstExpr\\ConstExprFalseNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/ConstExpr/ConstExprFalseNode.php',
        '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\ConstExpr\\ConstExprFloatNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/ConstExpr/ConstExprFloatNode.php',
        '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\ConstExpr\\ConstExprIntegerNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/ConstExpr/ConstExprIntegerNode.php',
        '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\ConstExpr\\ConstExprNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/ConstExpr/ConstExprNode.php',
        '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\ConstExpr\\ConstExprNullNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/ConstExpr/ConstExprNullNode.php',
        '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\ConstExpr\\ConstExprStringNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/ConstExpr/ConstExprStringNode.php',
        '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\ConstExpr\\ConstExprTrueNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/ConstExpr/ConstExprTrueNode.php',
        '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\ConstExpr\\ConstFetchNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/ConstExpr/ConstFetchNode.php',
        '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\ConstExpr\\DoctrineConstExprStringNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/ConstExpr/DoctrineConstExprStringNode.php',
        '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\Node' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/Node.php',
        '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\NodeAttributes' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/NodeAttributes.php',
        '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\NodeTraverser' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/NodeTraverser.php',
        '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\NodeVisitor' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/NodeVisitor.php',
        '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\NodeVisitor\\CloningVisitor' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/NodeVisitor/CloningVisitor.php',
        '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\PhpDoc\\AssertTagMethodValueNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/AssertTagMethodValueNode.php',
        '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\PhpDoc\\AssertTagPropertyValueNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/AssertTagPropertyValueNode.php',
        '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\PhpDoc\\AssertTagValueNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/AssertTagValueNode.php',
        '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\PhpDoc\\DeprecatedTagValueNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/DeprecatedTagValueNode.php',
        '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\PhpDoc\\Doctrine\\DoctrineAnnotation' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/Doctrine/DoctrineAnnotation.php',
        '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\PhpDoc\\Doctrine\\DoctrineArgument' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/Doctrine/DoctrineArgument.php',
        '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\PhpDoc\\Doctrine\\DoctrineArray' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/Doctrine/DoctrineArray.php',
        '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\PhpDoc\\Doctrine\\DoctrineArrayItem' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/Doctrine/DoctrineArrayItem.php',
        '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\PhpDoc\\Doctrine\\DoctrineTagValueNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/Doctrine/DoctrineTagValueNode.php',
        '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\PhpDoc\\ExtendsTagValueNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/ExtendsTagValueNode.php',
        '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\PhpDoc\\GenericTagValueNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/GenericTagValueNode.php',
        '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\PhpDoc\\ImplementsTagValueNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/ImplementsTagValueNode.php',
        '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\PhpDoc\\InvalidTagValueNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/InvalidTagValueNode.php',
        '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\PhpDoc\\MethodTagValueNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/MethodTagValueNode.php',
        '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\PhpDoc\\MethodTagValueParameterNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/MethodTagValueParameterNode.php',
        '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\PhpDoc\\MixinTagValueNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/MixinTagValueNode.php',
        '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\PhpDoc\\ParamClosureThisTagValueNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/ParamClosureThisTagValueNode.php',
        '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\PhpDoc\\ParamImmediatelyInvokedCallableTagValueNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/ParamImmediatelyInvokedCallableTagValueNode.php',
        '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\PhpDoc\\ParamLaterInvokedCallableTagValueNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/ParamLaterInvokedCallableTagValueNode.php',
        '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\PhpDoc\\ParamOutTagValueNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/ParamOutTagValueNode.php',
        '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\PhpDoc\\ParamTagValueNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/ParamTagValueNode.php',
        '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\PhpDoc\\PhpDocChildNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/PhpDocChildNode.php',
        '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\PhpDoc\\PhpDocNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/PhpDocNode.php',
        '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\PhpDoc\\PhpDocTagNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/PhpDocTagNode.php',
        '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\PhpDoc\\PhpDocTagValueNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/PhpDocTagValueNode.php',
        '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\PhpDoc\\PhpDocTextNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/PhpDocTextNode.php',
        '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\PhpDoc\\PropertyTagValueNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/PropertyTagValueNode.php',
        '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\PhpDoc\\PureUnlessCallableIsImpureTagValueNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/PureUnlessCallableIsImpureTagValueNode.php',
        '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\PhpDoc\\RequireExtendsTagValueNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/RequireExtendsTagValueNode.php',
        '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\PhpDoc\\RequireImplementsTagValueNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/RequireImplementsTagValueNode.php',
        '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\PhpDoc\\ReturnTagValueNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/ReturnTagValueNode.php',
        '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\PhpDoc\\SealedTagValueNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/SealedTagValueNode.php',
        '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\PhpDoc\\SelfOutTagValueNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/SelfOutTagValueNode.php',
        '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\PhpDoc\\TemplateTagValueNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/TemplateTagValueNode.php',
        '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\PhpDoc\\ThrowsTagValueNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/ThrowsTagValueNode.php',
        '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\PhpDoc\\TypeAliasImportTagValueNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/TypeAliasImportTagValueNode.php',
        '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\PhpDoc\\TypeAliasTagValueNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/TypeAliasTagValueNode.php',
        '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\PhpDoc\\TypelessParamTagValueNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/TypelessParamTagValueNode.php',
        '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\PhpDoc\\UsesTagValueNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/UsesTagValueNode.php',
        '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\PhpDoc\\VarTagValueNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/VarTagValueNode.php',
        '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\Type\\ArrayShapeItemNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/Type/ArrayShapeItemNode.php',
        '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\Type\\ArrayShapeNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/Type/ArrayShapeNode.php',
        '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\Type\\ArrayShapeUnsealedTypeNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/Type/ArrayShapeUnsealedTypeNode.php',
        '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\Type\\ArrayTypeNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/Type/ArrayTypeNode.php',
        '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\Type\\CallableTypeNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/Type/CallableTypeNode.php',
        '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\Type\\CallableTypeParameterNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/Type/CallableTypeParameterNode.php',
        '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\Type\\ConditionalTypeForParameterNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/Type/ConditionalTypeForParameterNode.php',
        '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\Type\\ConditionalTypeNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/Type/ConditionalTypeNode.php',
        '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\Type\\ConstTypeNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/Type/ConstTypeNode.php',
        '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\Type\\GenericTypeNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/Type/GenericTypeNode.php',
        '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\Type\\IdentifierTypeNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/Type/IdentifierTypeNode.php',
        '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\Type\\IntersectionTypeNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/Type/IntersectionTypeNode.php',
        '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\Type\\InvalidTypeNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/Type/InvalidTypeNode.php',
        '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\Type\\NullableTypeNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/Type/NullableTypeNode.php',
        '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\Type\\ObjectShapeItemNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/Type/ObjectShapeItemNode.php',
        '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\Type\\ObjectShapeNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/Type/ObjectShapeNode.php',
        '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\Type\\OffsetAccessTypeNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/Type/OffsetAccessTypeNode.php',
        '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\Type\\ThisTypeNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/Type/ThisTypeNode.php',
        '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\Type\\TypeNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/Type/TypeNode.php',
        '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\Type\\UnionTypeNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/Type/UnionTypeNode.php',
        '_ContaoManager\\PHPStan\\PhpDocParser\\Lexer\\Lexer' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Lexer/Lexer.php',
        '_ContaoManager\\PHPStan\\PhpDocParser\\ParserConfig' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/ParserConfig.php',
        '_ContaoManager\\PHPStan\\PhpDocParser\\Parser\\ConstExprParser' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Parser/ConstExprParser.php',
        '_ContaoManager\\PHPStan\\PhpDocParser\\Parser\\ParserException' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Parser/ParserException.php',
        '_ContaoManager\\PHPStan\\PhpDocParser\\Parser\\PhpDocParser' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Parser/PhpDocParser.php',
        '_ContaoManager\\PHPStan\\PhpDocParser\\Parser\\StringUnescaper' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Parser/StringUnescaper.php',
        '_ContaoManager\\PHPStan\\PhpDocParser\\Parser\\TokenIterator' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Parser/TokenIterator.php',
        '_ContaoManager\\PHPStan\\PhpDocParser\\Parser\\TypeParser' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Parser/TypeParser.php',
        '_ContaoManager\\PHPStan\\PhpDocParser\\Printer\\DiffElem' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Printer/DiffElem.php',
        '_ContaoManager\\PHPStan\\PhpDocParser\\Printer\\Differ' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Printer/Differ.php',
        '_ContaoManager\\PHPStan\\PhpDocParser\\Printer\\Printer' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Printer/Printer.php',
        '_ContaoManager\\ParagonIE\\ConstantTime\\Base32' => __DIR__ . '/..' . '/paragonie/constant_time_encoding/src/Base32.php',
        '_ContaoManager\\ParagonIE\\ConstantTime\\Base32Hex' => __DIR__ . '/..' . '/paragonie/constant_time_encoding/src/Base32Hex.php',
        '_ContaoManager\\ParagonIE\\ConstantTime\\Base64' => __DIR__ . '/..' . '/paragonie/constant_time_encoding/src/Base64.php',
        '_ContaoManager\\ParagonIE\\ConstantTime\\Base64DotSlash' => __DIR__ . '/..' . '/paragonie/constant_time_encoding/src/Base64DotSlash.php',
        '_ContaoManager\\ParagonIE\\ConstantTime\\Base64DotSlashOrdered' => __DIR__ . '/..' . '/paragonie/constant_time_encoding/src/Base64DotSlashOrdered.php',
        '_ContaoManager\\ParagonIE\\ConstantTime\\Base64UrlSafe' => __DIR__ . '/..' . '/paragonie/constant_time_encoding/src/Base64UrlSafe.php',
        '_ContaoManager\\ParagonIE\\ConstantTime\\Binary' => __DIR__ . '/..' . '/paragonie/constant_time_encoding/src/Binary.php',
        '_ContaoManager\\ParagonIE\\ConstantTime\\EncoderInterface' => __DIR__ . '/..' . '/paragonie/constant_time_encoding/src/EncoderInterface.php',
        '_ContaoManager\\ParagonIE\\ConstantTime\\Encoding' => __DIR__ . '/..' . '/paragonie/constant_time_encoding/src/Encoding.php',
        '_ContaoManager\\ParagonIE\\ConstantTime\\Hex' => __DIR__ . '/..' . '/paragonie/constant_time_encoding/src/Hex.php',
        '_ContaoManager\\ParagonIE\\ConstantTime\\RFC4648' => __DIR__ . '/..' . '/paragonie/constant_time_encoding/src/RFC4648.php',
        '_ContaoManager\\Psr\\Cache\\CacheException' => __DIR__ . '/..' . '/psr/cache/src/CacheException.php',
        '_ContaoManager\\Psr\\Cache\\CacheItemInterface' => __DIR__ . '/..' . '/psr/cache/src/CacheItemInterface.php',
        '_ContaoManager\\Psr\\Cache\\CacheItemPoolInterface' => __DIR__ . '/..' . '/psr/cache/src/CacheItemPoolInterface.php',
        '_ContaoManager\\Psr\\Cache\\InvalidArgumentException' => __DIR__ . '/..' . '/psr/cache/src/InvalidArgumentException.php',
        '_ContaoManager\\Psr\\Clock\\ClockInterface' => __DIR__ . '/..' . '/psr/clock/src/ClockInterface.php',
        '_ContaoManager\\Psr\\Container\\ContainerExceptionInterface' => __DIR__ . '/..' . '/psr/container/src/ContainerExceptionInterface.php',
        '_ContaoManager\\Psr\\Container\\ContainerInterface' => __DIR__ . '/..' . '/psr/container/src/ContainerInterface.php',
        '_ContaoManager\\Psr\\Container\\NotFoundExceptionInterface' => __DIR__ . '/..' . '/psr/container/src/NotFoundExceptionInterface.php',
        '_ContaoManager\\Psr\\EventDispatcher\\EventDispatcherInterface' => __DIR__ . '/..' . '/psr/event-dispatcher/src/EventDispatcherInterface.php',
        '_ContaoManager\\Psr\\EventDispatcher\\ListenerProviderInterface' => __DIR__ . '/..' . '/psr/event-dispatcher/src/ListenerProviderInterface.php',
        '_ContaoManager\\Psr\\EventDispatcher\\StoppableEventInterface' => __DIR__ . '/..' . '/psr/event-dispatcher/src/StoppableEventInterface.php',
        '_ContaoManager\\Psr\\Http\\Client\\ClientExceptionInterface' => __DIR__ . '/..' . '/psr/http-client/src/ClientExceptionInterface.php',
        '_ContaoManager\\Psr\\Http\\Client\\ClientInterface' => __DIR__ . '/..' . '/psr/http-client/src/ClientInterface.php',
        '_ContaoManager\\Psr\\Http\\Client\\NetworkExceptionInterface' => __DIR__ . '/..' . '/psr/http-client/src/NetworkExceptionInterface.php',
        '_ContaoManager\\Psr\\Http\\Client\\RequestExceptionInterface' => __DIR__ . '/..' . '/psr/http-client/src/RequestExceptionInterface.php',
        '_ContaoManager\\Psr\\Http\\Message\\MessageInterface' => __DIR__ . '/..' . '/psr/http-message/src/MessageInterface.php',
        '_ContaoManager\\Psr\\Http\\Message\\RequestFactoryInterface' => __DIR__ . '/..' . '/psr/http-factory/src/RequestFactoryInterface.php',
        '_ContaoManager\\Psr\\Http\\Message\\RequestInterface' => __DIR__ . '/..' . '/psr/http-message/src/RequestInterface.php',
        '_ContaoManager\\Psr\\Http\\Message\\ResponseFactoryInterface' => __DIR__ . '/..' . '/psr/http-factory/src/ResponseFactoryInterface.php',
        '_ContaoManager\\Psr\\Http\\Message\\ResponseInterface' => __DIR__ . '/..' . '/psr/http-message/src/ResponseInterface.php',
        '_ContaoManager\\Psr\\Http\\Message\\ServerRequestFactoryInterface' => __DIR__ . '/..' . '/psr/http-factory/src/ServerRequestFactoryInterface.php',
        '_ContaoManager\\Psr\\Http\\Message\\ServerRequestInterface' => __DIR__ . '/..' . '/psr/http-message/src/ServerRequestInterface.php',
        '_ContaoManager\\Psr\\Http\\Message\\StreamFactoryInterface' => __DIR__ . '/..' . '/psr/http-factory/src/StreamFactoryInterface.php',
        '_ContaoManager\\Psr\\Http\\Message\\StreamInterface' => __DIR__ . '/..' . '/psr/http-message/src/StreamInterface.php',
        '_ContaoManager\\Psr\\Http\\Message\\UploadedFileFactoryInterface' => __DIR__ . '/..' . '/psr/http-factory/src/UploadedFileFactoryInterface.php',
        '_ContaoManager\\Psr\\Http\\Message\\UploadedFileInterface' => __DIR__ . '/..' . '/psr/http-message/src/UploadedFileInterface.php',
        '_ContaoManager\\Psr\\Http\\Message\\UriFactoryInterface' => __DIR__ . '/..' . '/psr/http-factory/src/UriFactoryInterface.php',
        '_ContaoManager\\Psr\\Http\\Message\\UriInterface' => __DIR__ . '/..' . '/psr/http-message/src/UriInterface.php',
        '_ContaoManager\\Psr\\Log\\AbstractLogger' => __DIR__ . '/..' . '/psr/log/src/AbstractLogger.php',
        '_ContaoManager\\Psr\\Log\\InvalidArgumentException' => __DIR__ . '/..' . '/psr/log/src/InvalidArgumentException.php',
        '_ContaoManager\\Psr\\Log\\LogLevel' => __DIR__ . '/..' . '/psr/log/src/LogLevel.php',
        '_ContaoManager\\Psr\\Log\\LoggerAwareInterface' => __DIR__ . '/..' . '/psr/log/src/LoggerAwareInterface.php',
        '_ContaoManager\\Psr\\Log\\LoggerAwareTrait' => __DIR__ . '/..' . '/psr/log/src/LoggerAwareTrait.php',
        '_ContaoManager\\Psr\\Log\\LoggerInterface' => __DIR__ . '/..' . '/psr/log/src/LoggerInterface.php',
        '_ContaoManager\\Psr\\Log\\LoggerTrait' => __DIR__ . '/..' . '/psr/log/src/LoggerTrait.php',
        '_ContaoManager\\Psr\\Log\\NullLogger' => __DIR__ . '/..' . '/psr/log/src/NullLogger.php',
        '_ContaoManager\\Ramsey\\Collection\\AbstractArray' => __DIR__ . '/..' . '/ramsey/collection/src/AbstractArray.php',
        '_ContaoManager\\Ramsey\\Collection\\AbstractCollection' => __DIR__ . '/..' . '/ramsey/collection/src/AbstractCollection.php',
        '_ContaoManager\\Ramsey\\Collection\\AbstractSet' => __DIR__ . '/..' . '/ramsey/collection/src/AbstractSet.php',
        '_ContaoManager\\Ramsey\\Collection\\ArrayInterface' => __DIR__ . '/..' . '/ramsey/collection/src/ArrayInterface.php',
        '_ContaoManager\\Ramsey\\Collection\\Collection' => __DIR__ . '/..' . '/ramsey/collection/src/Collection.php',
        '_ContaoManager\\Ramsey\\Collection\\CollectionInterface' => __DIR__ . '/..' . '/ramsey/collection/src/CollectionInterface.php',
        '_ContaoManager\\Ramsey\\Collection\\DoubleEndedQueue' => __DIR__ . '/..' . '/ramsey/collection/src/DoubleEndedQueue.php',
        '_ContaoManager\\Ramsey\\Collection\\DoubleEndedQueueInterface' => __DIR__ . '/..' . '/ramsey/collection/src/DoubleEndedQueueInterface.php',
        '_ContaoManager\\Ramsey\\Collection\\Exception\\CollectionException' => __DIR__ . '/..' . '/ramsey/collection/src/Exception/CollectionException.php',
        '_ContaoManager\\Ramsey\\Collection\\Exception\\CollectionMismatchException' => __DIR__ . '/..' . '/ramsey/collection/src/Exception/CollectionMismatchException.php',
        '_ContaoManager\\Ramsey\\Collection\\Exception\\InvalidArgumentException' => __DIR__ . '/..' . '/ramsey/collection/src/Exception/InvalidArgumentException.php',
        '_ContaoManager\\Ramsey\\Collection\\Exception\\InvalidPropertyOrMethod' => __DIR__ . '/..' . '/ramsey/collection/src/Exception/InvalidPropertyOrMethod.php',
        '_ContaoManager\\Ramsey\\Collection\\Exception\\NoSuchElementException' => __DIR__ . '/..' . '/ramsey/collection/src/Exception/NoSuchElementException.php',
        '_ContaoManager\\Ramsey\\Collection\\Exception\\OutOfBoundsException' => __DIR__ . '/..' . '/ramsey/collection/src/Exception/OutOfBoundsException.php',
        '_ContaoManager\\Ramsey\\Collection\\Exception\\UnsupportedOperationException' => __DIR__ . '/..' . '/ramsey/collection/src/Exception/UnsupportedOperationException.php',
        '_ContaoManager\\Ramsey\\Collection\\GenericArray' => __DIR__ . '/..' . '/ramsey/collection/src/GenericArray.php',
        '_ContaoManager\\Ramsey\\Collection\\Map\\AbstractMap' => __DIR__ . '/..' . '/ramsey/collection/src/Map/AbstractMap.php',
        '_ContaoManager\\Ramsey\\Collection\\Map\\AbstractTypedMap' => __DIR__ . '/..' . '/ramsey/collection/src/Map/AbstractTypedMap.php',
        '_ContaoManager\\Ramsey\\Collection\\Map\\AssociativeArrayMap' => __DIR__ . '/..' . '/ramsey/collection/src/Map/AssociativeArrayMap.php',
        '_ContaoManager\\Ramsey\\Collection\\Map\\MapInterface' => __DIR__ . '/..' . '/ramsey/collection/src/Map/MapInterface.php',
        '_ContaoManager\\Ramsey\\Collection\\Map\\NamedParameterMap' => __DIR__ . '/..' . '/ramsey/collection/src/Map/NamedParameterMap.php',
        '_ContaoManager\\Ramsey\\Collection\\Map\\TypedMap' => __DIR__ . '/..' . '/ramsey/collection/src/Map/TypedMap.php',
        '_ContaoManager\\Ramsey\\Collection\\Map\\TypedMapInterface' => __DIR__ . '/..' . '/ramsey/collection/src/Map/TypedMapInterface.php',
        '_ContaoManager\\Ramsey\\Collection\\Queue' => __DIR__ . '/..' . '/ramsey/collection/src/Queue.php',
        '_ContaoManager\\Ramsey\\Collection\\QueueInterface' => __DIR__ . '/..' . '/ramsey/collection/src/QueueInterface.php',
        '_ContaoManager\\Ramsey\\Collection\\Set' => __DIR__ . '/..' . '/ramsey/collection/src/Set.php',
        '_ContaoManager\\Ramsey\\Collection\\Sort' => __DIR__ . '/..' . '/ramsey/collection/src/Sort.php',
        '_ContaoManager\\Ramsey\\Collection\\Tool\\TypeTrait' => __DIR__ . '/..' . '/ramsey/collection/src/Tool/TypeTrait.php',
        '_ContaoManager\\Ramsey\\Collection\\Tool\\ValueExtractorTrait' => __DIR__ . '/..' . '/ramsey/collection/src/Tool/ValueExtractorTrait.php',
        '_ContaoManager\\Ramsey\\Collection\\Tool\\ValueToStringTrait' => __DIR__ . '/..' . '/ramsey/collection/src/Tool/ValueToStringTrait.php',
        '_ContaoManager\\Ramsey\\Uuid\\BinaryUtils' => __DIR__ . '/..' . '/ramsey/uuid/src/BinaryUtils.php',
        '_ContaoManager\\Ramsey\\Uuid\\Builder\\BuilderCollection' => __DIR__ . '/..' . '/ramsey/uuid/src/Builder/BuilderCollection.php',
        '_ContaoManager\\Ramsey\\Uuid\\Builder\\DefaultUuidBuilder' => __DIR__ . '/..' . '/ramsey/uuid/src/Builder/DefaultUuidBuilder.php',
        '_ContaoManager\\Ramsey\\Uuid\\Builder\\DegradedUuidBuilder' => __DIR__ . '/..' . '/ramsey/uuid/src/Builder/DegradedUuidBuilder.php',
        '_ContaoManager\\Ramsey\\Uuid\\Builder\\FallbackBuilder' => __DIR__ . '/..' . '/ramsey/uuid/src/Builder/FallbackBuilder.php',
        '_ContaoManager\\Ramsey\\Uuid\\Builder\\UuidBuilderInterface' => __DIR__ . '/..' . '/ramsey/uuid/src/Builder/UuidBuilderInterface.php',
        '_ContaoManager\\Ramsey\\Uuid\\Codec\\CodecInterface' => __DIR__ . '/..' . '/ramsey/uuid/src/Codec/CodecInterface.php',
        '_ContaoManager\\Ramsey\\Uuid\\Codec\\GuidStringCodec' => __DIR__ . '/..' . '/ramsey/uuid/src/Codec/GuidStringCodec.php',
        '_ContaoManager\\Ramsey\\Uuid\\Codec\\OrderedTimeCodec' => __DIR__ . '/..' . '/ramsey/uuid/src/Codec/OrderedTimeCodec.php',
        '_ContaoManager\\Ramsey\\Uuid\\Codec\\StringCodec' => __DIR__ . '/..' . '/ramsey/uuid/src/Codec/StringCodec.php',
        '_ContaoManager\\Ramsey\\Uuid\\Codec\\TimestampFirstCombCodec' => __DIR__ . '/..' . '/ramsey/uuid/src/Codec/TimestampFirstCombCodec.php',
        '_ContaoManager\\Ramsey\\Uuid\\Codec\\TimestampLastCombCodec' => __DIR__ . '/..' . '/ramsey/uuid/src/Codec/TimestampLastCombCodec.php',
        '_ContaoManager\\Ramsey\\Uuid\\Converter\\NumberConverterInterface' => __DIR__ . '/..' . '/ramsey/uuid/src/Converter/NumberConverterInterface.php',
        '_ContaoManager\\Ramsey\\Uuid\\Converter\\Number\\BigNumberConverter' => __DIR__ . '/..' . '/ramsey/uuid/src/Converter/Number/BigNumberConverter.php',
        '_ContaoManager\\Ramsey\\Uuid\\Converter\\Number\\DegradedNumberConverter' => __DIR__ . '/..' . '/ramsey/uuid/src/Converter/Number/DegradedNumberConverter.php',
        '_ContaoManager\\Ramsey\\Uuid\\Converter\\Number\\GenericNumberConverter' => __DIR__ . '/..' . '/ramsey/uuid/src/Converter/Number/GenericNumberConverter.php',
        '_ContaoManager\\Ramsey\\Uuid\\Converter\\TimeConverterInterface' => __DIR__ . '/..' . '/ramsey/uuid/src/Converter/TimeConverterInterface.php',
        '_ContaoManager\\Ramsey\\Uuid\\Converter\\Time\\BigNumberTimeConverter' => __DIR__ . '/..' . '/ramsey/uuid/src/Converter/Time/BigNumberTimeConverter.php',
        '_ContaoManager\\Ramsey\\Uuid\\Converter\\Time\\DegradedTimeConverter' => __DIR__ . '/..' . '/ramsey/uuid/src/Converter/Time/DegradedTimeConverter.php',
        '_ContaoManager\\Ramsey\\Uuid\\Converter\\Time\\GenericTimeConverter' => __DIR__ . '/..' . '/ramsey/uuid/src/Converter/Time/GenericTimeConverter.php',
        '_ContaoManager\\Ramsey\\Uuid\\Converter\\Time\\PhpTimeConverter' => __DIR__ . '/..' . '/ramsey/uuid/src/Converter/Time/PhpTimeConverter.php',
        '_ContaoManager\\Ramsey\\Uuid\\Converter\\Time\\UnixTimeConverter' => __DIR__ . '/..' . '/ramsey/uuid/src/Converter/Time/UnixTimeConverter.php',
        '_ContaoManager\\Ramsey\\Uuid\\DegradedUuid' => __DIR__ . '/..' . '/ramsey/uuid/src/DegradedUuid.php',
        '_ContaoManager\\Ramsey\\Uuid\\DeprecatedUuidInterface' => __DIR__ . '/..' . '/ramsey/uuid/src/DeprecatedUuidInterface.php',
        '_ContaoManager\\Ramsey\\Uuid\\DeprecatedUuidMethodsTrait' => __DIR__ . '/..' . '/ramsey/uuid/src/DeprecatedUuidMethodsTrait.php',
        '_ContaoManager\\Ramsey\\Uuid\\Exception\\BuilderNotFoundException' => __DIR__ . '/..' . '/ramsey/uuid/src/Exception/BuilderNotFoundException.php',
        '_ContaoManager\\Ramsey\\Uuid\\Exception\\DateTimeException' => __DIR__ . '/..' . '/ramsey/uuid/src/Exception/DateTimeException.php',
        '_ContaoManager\\Ramsey\\Uuid\\Exception\\DceSecurityException' => __DIR__ . '/..' . '/ramsey/uuid/src/Exception/DceSecurityException.php',
        '_ContaoManager\\Ramsey\\Uuid\\Exception\\InvalidArgumentException' => __DIR__ . '/..' . '/ramsey/uuid/src/Exception/InvalidArgumentException.php',
        '_ContaoManager\\Ramsey\\Uuid\\Exception\\InvalidBytesException' => __DIR__ . '/..' . '/ramsey/uuid/src/Exception/InvalidBytesException.php',
        '_ContaoManager\\Ramsey\\Uuid\\Exception\\InvalidUuidStringException' => __DIR__ . '/..' . '/ramsey/uuid/src/Exception/InvalidUuidStringException.php',
        '_ContaoManager\\Ramsey\\Uuid\\Exception\\NameException' => __DIR__ . '/..' . '/ramsey/uuid/src/Exception/NameException.php',
        '_ContaoManager\\Ramsey\\Uuid\\Exception\\NodeException' => __DIR__ . '/..' . '/ramsey/uuid/src/Exception/NodeException.php',
        '_ContaoManager\\Ramsey\\Uuid\\Exception\\RandomSourceException' => __DIR__ . '/..' . '/ramsey/uuid/src/Exception/RandomSourceException.php',
        '_ContaoManager\\Ramsey\\Uuid\\Exception\\TimeSourceException' => __DIR__ . '/..' . '/ramsey/uuid/src/Exception/TimeSourceException.php',
        '_ContaoManager\\Ramsey\\Uuid\\Exception\\UnableToBuildUuidException' => __DIR__ . '/..' . '/ramsey/uuid/src/Exception/UnableToBuildUuidException.php',
        '_ContaoManager\\Ramsey\\Uuid\\Exception\\UnsupportedOperationException' => __DIR__ . '/..' . '/ramsey/uuid/src/Exception/UnsupportedOperationException.php',
        '_ContaoManager\\Ramsey\\Uuid\\Exception\\UuidExceptionInterface' => __DIR__ . '/..' . '/ramsey/uuid/src/Exception/UuidExceptionInterface.php',
        '_ContaoManager\\Ramsey\\Uuid\\FeatureSet' => __DIR__ . '/..' . '/ramsey/uuid/src/FeatureSet.php',
        '_ContaoManager\\Ramsey\\Uuid\\Fields\\FieldsInterface' => __DIR__ . '/..' . '/ramsey/uuid/src/Fields/FieldsInterface.php',
        '_ContaoManager\\Ramsey\\Uuid\\Fields\\SerializableFieldsTrait' => __DIR__ . '/..' . '/ramsey/uuid/src/Fields/SerializableFieldsTrait.php',
        '_ContaoManager\\Ramsey\\Uuid\\Generator\\CombGenerator' => __DIR__ . '/..' . '/ramsey/uuid/src/Generator/CombGenerator.php',
        '_ContaoManager\\Ramsey\\Uuid\\Generator\\DceSecurityGenerator' => __DIR__ . '/..' . '/ramsey/uuid/src/Generator/DceSecurityGenerator.php',
        '_ContaoManager\\Ramsey\\Uuid\\Generator\\DceSecurityGeneratorInterface' => __DIR__ . '/..' . '/ramsey/uuid/src/Generator/DceSecurityGeneratorInterface.php',
        '_ContaoManager\\Ramsey\\Uuid\\Generator\\DefaultNameGenerator' => __DIR__ . '/..' . '/ramsey/uuid/src/Generator/DefaultNameGenerator.php',
        '_ContaoManager\\Ramsey\\Uuid\\Generator\\DefaultTimeGenerator' => __DIR__ . '/..' . '/ramsey/uuid/src/Generator/DefaultTimeGenerator.php',
        '_ContaoManager\\Ramsey\\Uuid\\Generator\\NameGeneratorFactory' => __DIR__ . '/..' . '/ramsey/uuid/src/Generator/NameGeneratorFactory.php',
        '_ContaoManager\\Ramsey\\Uuid\\Generator\\NameGeneratorInterface' => __DIR__ . '/..' . '/ramsey/uuid/src/Generator/NameGeneratorInterface.php',
        '_ContaoManager\\Ramsey\\Uuid\\Generator\\PeclUuidNameGenerator' => __DIR__ . '/..' . '/ramsey/uuid/src/Generator/PeclUuidNameGenerator.php',
        '_ContaoManager\\Ramsey\\Uuid\\Generator\\PeclUuidRandomGenerator' => __DIR__ . '/..' . '/ramsey/uuid/src/Generator/PeclUuidRandomGenerator.php',
        '_ContaoManager\\Ramsey\\Uuid\\Generator\\PeclUuidTimeGenerator' => __DIR__ . '/..' . '/ramsey/uuid/src/Generator/PeclUuidTimeGenerator.php',
        '_ContaoManager\\Ramsey\\Uuid\\Generator\\RandomBytesGenerator' => __DIR__ . '/..' . '/ramsey/uuid/src/Generator/RandomBytesGenerator.php',
        '_ContaoManager\\Ramsey\\Uuid\\Generator\\RandomGeneratorFactory' => __DIR__ . '/..' . '/ramsey/uuid/src/Generator/RandomGeneratorFactory.php',
        '_ContaoManager\\Ramsey\\Uuid\\Generator\\RandomGeneratorInterface' => __DIR__ . '/..' . '/ramsey/uuid/src/Generator/RandomGeneratorInterface.php',
        '_ContaoManager\\Ramsey\\Uuid\\Generator\\RandomLibAdapter' => __DIR__ . '/..' . '/ramsey/uuid/src/Generator/RandomLibAdapter.php',
        '_ContaoManager\\Ramsey\\Uuid\\Generator\\TimeGeneratorFactory' => __DIR__ . '/..' . '/ramsey/uuid/src/Generator/TimeGeneratorFactory.php',
        '_ContaoManager\\Ramsey\\Uuid\\Generator\\TimeGeneratorInterface' => __DIR__ . '/..' . '/ramsey/uuid/src/Generator/TimeGeneratorInterface.php',
        '_ContaoManager\\Ramsey\\Uuid\\Generator\\UnixTimeGenerator' => __DIR__ . '/..' . '/ramsey/uuid/src/Generator/UnixTimeGenerator.php',
        '_ContaoManager\\Ramsey\\Uuid\\Guid\\Fields' => __DIR__ . '/..' . '/ramsey/uuid/src/Guid/Fields.php',
        '_ContaoManager\\Ramsey\\Uuid\\Guid\\Guid' => __DIR__ . '/..' . '/ramsey/uuid/src/Guid/Guid.php',
        '_ContaoManager\\Ramsey\\Uuid\\Guid\\GuidBuilder' => __DIR__ . '/..' . '/ramsey/uuid/src/Guid/GuidBuilder.php',
        '_ContaoManager\\Ramsey\\Uuid\\Lazy\\LazyUuidFromString' => __DIR__ . '/..' . '/ramsey/uuid/src/Lazy/LazyUuidFromString.php',
        '_ContaoManager\\Ramsey\\Uuid\\Math\\BrickMathCalculator' => __DIR__ . '/..' . '/ramsey/uuid/src/Math/BrickMathCalculator.php',
        '_ContaoManager\\Ramsey\\Uuid\\Math\\CalculatorInterface' => __DIR__ . '/..' . '/ramsey/uuid/src/Math/CalculatorInterface.php',
        '_ContaoManager\\Ramsey\\Uuid\\Math\\RoundingMode' => __DIR__ . '/..' . '/ramsey/uuid/src/Math/RoundingMode.php',
        '_ContaoManager\\Ramsey\\Uuid\\Nonstandard\\Fields' => __DIR__ . '/..' . '/ramsey/uuid/src/Nonstandard/Fields.php',
        '_ContaoManager\\Ramsey\\Uuid\\Nonstandard\\Uuid' => __DIR__ . '/..' . '/ramsey/uuid/src/Nonstandard/Uuid.php',
        '_ContaoManager\\Ramsey\\Uuid\\Nonstandard\\UuidBuilder' => __DIR__ . '/..' . '/ramsey/uuid/src/Nonstandard/UuidBuilder.php',
        '_ContaoManager\\Ramsey\\Uuid\\Nonstandard\\UuidV6' => __DIR__ . '/..' . '/ramsey/uuid/src/Nonstandard/UuidV6.php',
        '_ContaoManager\\Ramsey\\Uuid\\Provider\\DceSecurityProviderInterface' => __DIR__ . '/..' . '/ramsey/uuid/src/Provider/DceSecurityProviderInterface.php',
        '_ContaoManager\\Ramsey\\Uuid\\Provider\\Dce\\SystemDceSecurityProvider' => __DIR__ . '/..' . '/ramsey/uuid/src/Provider/Dce/SystemDceSecurityProvider.php',
        '_ContaoManager\\Ramsey\\Uuid\\Provider\\NodeProviderInterface' => __DIR__ . '/..' . '/ramsey/uuid/src/Provider/NodeProviderInterface.php',
        '_ContaoManager\\Ramsey\\Uuid\\Provider\\Node\\FallbackNodeProvider' => __DIR__ . '/..' . '/ramsey/uuid/src/Provider/Node/FallbackNodeProvider.php',
        '_ContaoManager\\Ramsey\\Uuid\\Provider\\Node\\NodeProviderCollection' => __DIR__ . '/..' . '/ramsey/uuid/src/Provider/Node/NodeProviderCollection.php',
        '_ContaoManager\\Ramsey\\Uuid\\Provider\\Node\\RandomNodeProvider' => __DIR__ . '/..' . '/ramsey/uuid/src/Provider/Node/RandomNodeProvider.php',
        '_ContaoManager\\Ramsey\\Uuid\\Provider\\Node\\StaticNodeProvider' => __DIR__ . '/..' . '/ramsey/uuid/src/Provider/Node/StaticNodeProvider.php',
        '_ContaoManager\\Ramsey\\Uuid\\Provider\\Node\\SystemNodeProvider' => __DIR__ . '/..' . '/ramsey/uuid/src/Provider/Node/SystemNodeProvider.php',
        '_ContaoManager\\Ramsey\\Uuid\\Provider\\TimeProviderInterface' => __DIR__ . '/..' . '/ramsey/uuid/src/Provider/TimeProviderInterface.php',
        '_ContaoManager\\Ramsey\\Uuid\\Provider\\Time\\FixedTimeProvider' => __DIR__ . '/..' . '/ramsey/uuid/src/Provider/Time/FixedTimeProvider.php',
        '_ContaoManager\\Ramsey\\Uuid\\Provider\\Time\\SystemTimeProvider' => __DIR__ . '/..' . '/ramsey/uuid/src/Provider/Time/SystemTimeProvider.php',
        '_ContaoManager\\Ramsey\\Uuid\\Rfc4122\\Fields' => __DIR__ . '/..' . '/ramsey/uuid/src/Rfc4122/Fields.php',
        '_ContaoManager\\Ramsey\\Uuid\\Rfc4122\\FieldsInterface' => __DIR__ . '/..' . '/ramsey/uuid/src/Rfc4122/FieldsInterface.php',
        '_ContaoManager\\Ramsey\\Uuid\\Rfc4122\\MaxTrait' => __DIR__ . '/..' . '/ramsey/uuid/src/Rfc4122/MaxTrait.php',
        '_ContaoManager\\Ramsey\\Uuid\\Rfc4122\\MaxUuid' => __DIR__ . '/..' . '/ramsey/uuid/src/Rfc4122/MaxUuid.php',
        '_ContaoManager\\Ramsey\\Uuid\\Rfc4122\\NilTrait' => __DIR__ . '/..' . '/ramsey/uuid/src/Rfc4122/NilTrait.php',
        '_ContaoManager\\Ramsey\\Uuid\\Rfc4122\\NilUuid' => __DIR__ . '/..' . '/ramsey/uuid/src/Rfc4122/NilUuid.php',
        '_ContaoManager\\Ramsey\\Uuid\\Rfc4122\\TimeTrait' => __DIR__ . '/..' . '/ramsey/uuid/src/Rfc4122/TimeTrait.php',
        '_ContaoManager\\Ramsey\\Uuid\\Rfc4122\\UuidBuilder' => __DIR__ . '/..' . '/ramsey/uuid/src/Rfc4122/UuidBuilder.php',
        '_ContaoManager\\Ramsey\\Uuid\\Rfc4122\\UuidInterface' => __DIR__ . '/..' . '/ramsey/uuid/src/Rfc4122/UuidInterface.php',
        '_ContaoManager\\Ramsey\\Uuid\\Rfc4122\\UuidV1' => __DIR__ . '/..' . '/ramsey/uuid/src/Rfc4122/UuidV1.php',
        '_ContaoManager\\Ramsey\\Uuid\\Rfc4122\\UuidV2' => __DIR__ . '/..' . '/ramsey/uuid/src/Rfc4122/UuidV2.php',
        '_ContaoManager\\Ramsey\\Uuid\\Rfc4122\\UuidV3' => __DIR__ . '/..' . '/ramsey/uuid/src/Rfc4122/UuidV3.php',
        '_ContaoManager\\Ramsey\\Uuid\\Rfc4122\\UuidV4' => __DIR__ . '/..' . '/ramsey/uuid/src/Rfc4122/UuidV4.php',
        '_ContaoManager\\Ramsey\\Uuid\\Rfc4122\\UuidV5' => __DIR__ . '/..' . '/ramsey/uuid/src/Rfc4122/UuidV5.php',
        '_ContaoManager\\Ramsey\\Uuid\\Rfc4122\\UuidV6' => __DIR__ . '/..' . '/ramsey/uuid/src/Rfc4122/UuidV6.php',
        '_ContaoManager\\Ramsey\\Uuid\\Rfc4122\\UuidV7' => __DIR__ . '/..' . '/ramsey/uuid/src/Rfc4122/UuidV7.php',
        '_ContaoManager\\Ramsey\\Uuid\\Rfc4122\\UuidV8' => __DIR__ . '/..' . '/ramsey/uuid/src/Rfc4122/UuidV8.php',
        '_ContaoManager\\Ramsey\\Uuid\\Rfc4122\\Validator' => __DIR__ . '/..' . '/ramsey/uuid/src/Rfc4122/Validator.php',
        '_ContaoManager\\Ramsey\\Uuid\\Rfc4122\\VariantTrait' => __DIR__ . '/..' . '/ramsey/uuid/src/Rfc4122/VariantTrait.php',
        '_ContaoManager\\Ramsey\\Uuid\\Rfc4122\\VersionTrait' => __DIR__ . '/..' . '/ramsey/uuid/src/Rfc4122/VersionTrait.php',
        '_ContaoManager\\Ramsey\\Uuid\\Type\\Decimal' => __DIR__ . '/..' . '/ramsey/uuid/src/Type/Decimal.php',
        '_ContaoManager\\Ramsey\\Uuid\\Type\\Hexadecimal' => __DIR__ . '/..' . '/ramsey/uuid/src/Type/Hexadecimal.php',
        '_ContaoManager\\Ramsey\\Uuid\\Type\\Integer' => __DIR__ . '/..' . '/ramsey/uuid/src/Type/Integer.php',
        '_ContaoManager\\Ramsey\\Uuid\\Type\\NumberInterface' => __DIR__ . '/..' . '/ramsey/uuid/src/Type/NumberInterface.php',
        '_ContaoManager\\Ramsey\\Uuid\\Type\\Time' => __DIR__ . '/..' . '/ramsey/uuid/src/Type/Time.php',
        '_ContaoManager\\Ramsey\\Uuid\\Type\\TypeInterface' => __DIR__ . '/..' . '/ramsey/uuid/src/Type/TypeInterface.php',
        '_ContaoManager\\Ramsey\\Uuid\\Uuid' => __DIR__ . '/..' . '/ramsey/uuid/src/Uuid.php',
        '_ContaoManager\\Ramsey\\Uuid\\UuidFactory' => __DIR__ . '/..' . '/ramsey/uuid/src/UuidFactory.php',
        '_ContaoManager\\Ramsey\\Uuid\\UuidFactoryInterface' => __DIR__ . '/..' . '/ramsey/uuid/src/UuidFactoryInterface.php',
        '_ContaoManager\\Ramsey\\Uuid\\UuidInterface' => __DIR__ . '/..' . '/ramsey/uuid/src/UuidInterface.php',
        '_ContaoManager\\Ramsey\\Uuid\\Validator\\GenericValidator' => __DIR__ . '/..' . '/ramsey/uuid/src/Validator/GenericValidator.php',
        '_ContaoManager\\Ramsey\\Uuid\\Validator\\ValidatorInterface' => __DIR__ . '/..' . '/ramsey/uuid/src/Validator/ValidatorInterface.php',
        '_ContaoManager\\SebastianBergmann\\Diff\\Chunk' => __DIR__ . '/..' . '/sebastian/diff/src/Chunk.php',
        '_ContaoManager\\SebastianBergmann\\Diff\\ConfigurationException' => __DIR__ . '/..' . '/sebastian/diff/src/Exception/ConfigurationException.php',
        '_ContaoManager\\SebastianBergmann\\Diff\\Diff' => __DIR__ . '/..' . '/sebastian/diff/src/Diff.php',
        '_ContaoManager\\SebastianBergmann\\Diff\\Differ' => __DIR__ . '/..' . '/sebastian/diff/src/Differ.php',
        '_ContaoManager\\SebastianBergmann\\Diff\\Exception' => __DIR__ . '/..' . '/sebastian/diff/src/Exception/Exception.php',
        '_ContaoManager\\SebastianBergmann\\Diff\\InvalidArgumentException' => __DIR__ . '/..' . '/sebastian/diff/src/Exception/InvalidArgumentException.php',
        '_ContaoManager\\SebastianBergmann\\Diff\\Line' => __DIR__ . '/..' . '/sebastian/diff/src/Line.php',
        '_ContaoManager\\SebastianBergmann\\Diff\\LongestCommonSubsequenceCalculator' => __DIR__ . '/..' . '/sebastian/diff/src/LongestCommonSubsequenceCalculator.php',
        '_ContaoManager\\SebastianBergmann\\Diff\\MemoryEfficientLongestCommonSubsequenceCalculator' => __DIR__ . '/..' . '/sebastian/diff/src/MemoryEfficientLongestCommonSubsequenceCalculator.php',
        '_ContaoManager\\SebastianBergmann\\Diff\\Output\\AbstractChunkOutputBuilder' => __DIR__ . '/..' . '/sebastian/diff/src/Output/AbstractChunkOutputBuilder.php',
        '_ContaoManager\\SebastianBergmann\\Diff\\Output\\DiffOnlyOutputBuilder' => __DIR__ . '/..' . '/sebastian/diff/src/Output/DiffOnlyOutputBuilder.php',
        '_ContaoManager\\SebastianBergmann\\Diff\\Output\\DiffOutputBuilderInterface' => __DIR__ . '/..' . '/sebastian/diff/src/Output/DiffOutputBuilderInterface.php',
        '_ContaoManager\\SebastianBergmann\\Diff\\Output\\StrictUnifiedDiffOutputBuilder' => __DIR__ . '/..' . '/sebastian/diff/src/Output/StrictUnifiedDiffOutputBuilder.php',
        '_ContaoManager\\SebastianBergmann\\Diff\\Output\\UnifiedDiffOutputBuilder' => __DIR__ . '/..' . '/sebastian/diff/src/Output/UnifiedDiffOutputBuilder.php',
        '_ContaoManager\\SebastianBergmann\\Diff\\Parser' => __DIR__ . '/..' . '/sebastian/diff/src/Parser.php',
        '_ContaoManager\\SebastianBergmann\\Diff\\TimeEfficientLongestCommonSubsequenceCalculator' => __DIR__ . '/..' . '/sebastian/diff/src/TimeEfficientLongestCommonSubsequenceCalculator.php',
        '_ContaoManager\\Seld\\JsonLint\\DuplicateKeyException' => __DIR__ . '/..' . '/seld/jsonlint/src/Seld/JsonLint/DuplicateKeyException.php',
        '_ContaoManager\\Seld\\JsonLint\\JsonParser' => __DIR__ . '/..' . '/seld/jsonlint/src/Seld/JsonLint/JsonParser.php',
        '_ContaoManager\\Seld\\JsonLint\\Lexer' => __DIR__ . '/..' . '/seld/jsonlint/src/Seld/JsonLint/Lexer.php',
        '_ContaoManager\\Seld\\JsonLint\\ParsingException' => __DIR__ . '/..' . '/seld/jsonlint/src/Seld/JsonLint/ParsingException.php',
        '_ContaoManager\\Seld\\JsonLint\\Undefined' => __DIR__ . '/..' . '/seld/jsonlint/src/Seld/JsonLint/Undefined.php',
        '_ContaoManager\\Seld\\PharUtils\\Linter' => __DIR__ . '/..' . '/seld/phar-utils/src/Linter.php',
        '_ContaoManager\\Seld\\PharUtils\\Timestamps' => __DIR__ . '/..' . '/seld/phar-utils/src/Timestamps.php',
        '_ContaoManager\\Seld\\Signal\\SignalHandler' => __DIR__ . '/..' . '/seld/signal-handler/src/SignalHandler.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\ASN1\\Component\\Identifier' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/ASN1/Component/Identifier.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\ASN1\\Component\\Length' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/ASN1/Component/Length.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\ASN1\\DERData' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/ASN1/DERData.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\ASN1\\Element' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/ASN1/Element.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\ASN1\\Exception\\DecodeException' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/ASN1/Exception/DecodeException.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\ASN1\\Feature\\ElementBase' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/ASN1/Feature/ElementBase.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\ASN1\\Feature\\Encodable' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/ASN1/Feature/Encodable.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\ASN1\\Feature\\Stringable' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/ASN1/Feature/Stringable.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\ASN1\\Type\\BaseString' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/ASN1/Type/BaseString.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\ASN1\\Type\\BaseTime' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/ASN1/Type/BaseTime.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\ASN1\\Type\\Constructed\\ConstructedString' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/ASN1/Type/Constructed/ConstructedString.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\ASN1\\Type\\Constructed\\Sequence' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/ASN1/Type/Constructed/Sequence.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\ASN1\\Type\\Constructed\\Set' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/ASN1/Type/Constructed/Set.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\ASN1\\Type\\PrimitiveString' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/ASN1/Type/PrimitiveString.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\ASN1\\Type\\PrimitiveType' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/ASN1/Type/PrimitiveType.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\ASN1\\Type\\Primitive\\BMPString' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/ASN1/Type/Primitive/BMPString.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\ASN1\\Type\\Primitive\\BitString' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/ASN1/Type/Primitive/BitString.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\ASN1\\Type\\Primitive\\Boolean' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/ASN1/Type/Primitive/Boolean.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\ASN1\\Type\\Primitive\\CharacterString' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/ASN1/Type/Primitive/CharacterString.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\ASN1\\Type\\Primitive\\EOC' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/ASN1/Type/Primitive/EOC.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\ASN1\\Type\\Primitive\\Enumerated' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/ASN1/Type/Primitive/Enumerated.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\ASN1\\Type\\Primitive\\GeneralString' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/ASN1/Type/Primitive/GeneralString.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\ASN1\\Type\\Primitive\\GeneralizedTime' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/ASN1/Type/Primitive/GeneralizedTime.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\ASN1\\Type\\Primitive\\GraphicString' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/ASN1/Type/Primitive/GraphicString.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\ASN1\\Type\\Primitive\\IA5String' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/ASN1/Type/Primitive/IA5String.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\ASN1\\Type\\Primitive\\Integer' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/ASN1/Type/Primitive/Integer.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\ASN1\\Type\\Primitive\\NullType' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/ASN1/Type/Primitive/NullType.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\ASN1\\Type\\Primitive\\Number' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/ASN1/Type/Primitive/Number.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\ASN1\\Type\\Primitive\\NumericString' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/ASN1/Type/Primitive/NumericString.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\ASN1\\Type\\Primitive\\ObjectDescriptor' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/ASN1/Type/Primitive/ObjectDescriptor.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\ASN1\\Type\\Primitive\\ObjectIdentifier' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/ASN1/Type/Primitive/ObjectIdentifier.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\ASN1\\Type\\Primitive\\OctetString' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/ASN1/Type/Primitive/OctetString.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\ASN1\\Type\\Primitive\\PrintableString' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/ASN1/Type/Primitive/PrintableString.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\ASN1\\Type\\Primitive\\Real' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/ASN1/Type/Primitive/Real.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\ASN1\\Type\\Primitive\\RelativeOID' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/ASN1/Type/Primitive/RelativeOID.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\ASN1\\Type\\Primitive\\T61String' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/ASN1/Type/Primitive/T61String.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\ASN1\\Type\\Primitive\\UTCTime' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/ASN1/Type/Primitive/UTCTime.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\ASN1\\Type\\Primitive\\UTF8String' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/ASN1/Type/Primitive/UTF8String.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\ASN1\\Type\\Primitive\\UniversalString' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/ASN1/Type/Primitive/UniversalString.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\ASN1\\Type\\Primitive\\VideotexString' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/ASN1/Type/Primitive/VideotexString.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\ASN1\\Type\\Primitive\\VisibleString' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/ASN1/Type/Primitive/VisibleString.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\ASN1\\Type\\StringType' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/ASN1/Type/StringType.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\ASN1\\Type\\Structure' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/ASN1/Type/Structure.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\ASN1\\Type\\TaggedType' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/ASN1/Type/TaggedType.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\ASN1\\Type\\Tagged\\ApplicationType' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/ASN1/Type/Tagged/ApplicationType.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\ASN1\\Type\\Tagged\\ContextSpecificType' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/ASN1/Type/Tagged/ContextSpecificType.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\ASN1\\Type\\Tagged\\DERTaggedType' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/ASN1/Type/Tagged/DERTaggedType.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\ASN1\\Type\\Tagged\\ExplicitTagging' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/ASN1/Type/Tagged/ExplicitTagging.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\ASN1\\Type\\Tagged\\ExplicitlyTaggedType' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/ASN1/Type/Tagged/ExplicitlyTaggedType.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\ASN1\\Type\\Tagged\\ImplicitTagging' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/ASN1/Type/Tagged/ImplicitTagging.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\ASN1\\Type\\Tagged\\ImplicitlyTaggedType' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/ASN1/Type/Tagged/ImplicitlyTaggedType.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\ASN1\\Type\\Tagged\\PrivateType' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/ASN1/Type/Tagged/PrivateType.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\ASN1\\Type\\Tagged\\TaggedTypeWrap' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/ASN1/Type/Tagged/TaggedTypeWrap.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\ASN1\\Type\\TimeType' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/ASN1/Type/TimeType.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\ASN1\\Type\\UniversalClass' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/ASN1/Type/UniversalClass.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\ASN1\\Type\\UnspecifiedType' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/ASN1/Type/UnspecifiedType.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\ASN1\\Util\\BigInt' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/ASN1/Util/BigInt.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\ASN1\\Util\\Flags' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/ASN1/Util/Flags.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\CryptoBridge\\Crypto' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/CryptoBridge/Crypto.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\CryptoBridge\\Crypto\\OpenSSLCrypto' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/CryptoBridge/Crypto/OpenSSLCrypto.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\CryptoEncoding\\PEM' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/CryptoEncoding/PEM.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\CryptoEncoding\\PEMBundle' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/CryptoEncoding/PEMBundle.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\AlgorithmIdentifier\\AlgorithmIdentifier' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/AlgorithmIdentifier.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\AlgorithmIdentifier\\AlgorithmIdentifierFactory' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/AlgorithmIdentifierFactory.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\AlgorithmIdentifier\\AlgorithmIdentifierProvider' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/AlgorithmIdentifierProvider.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\AlgorithmIdentifier\\Asymmetric\\ECPublicKeyAlgorithmIdentifier' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Asymmetric/ECPublicKeyAlgorithmIdentifier.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\AlgorithmIdentifier\\Asymmetric\\Ed25519AlgorithmIdentifier' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Asymmetric/Ed25519AlgorithmIdentifier.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\AlgorithmIdentifier\\Asymmetric\\Ed448AlgorithmIdentifier' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Asymmetric/Ed448AlgorithmIdentifier.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\AlgorithmIdentifier\\Asymmetric\\RFC8410EdAlgorithmIdentifier' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Asymmetric/RFC8410EdAlgorithmIdentifier.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\AlgorithmIdentifier\\Asymmetric\\RFC8410XAlgorithmIdentifier' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Asymmetric/RFC8410XAlgorithmIdentifier.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\AlgorithmIdentifier\\Asymmetric\\RSAEncryptionAlgorithmIdentifier' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Asymmetric/RSAEncryptionAlgorithmIdentifier.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\AlgorithmIdentifier\\Asymmetric\\RSAPSSSSAEncryptionAlgorithmIdentifier' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Asymmetric/RSAPSSSSAEncryptionAlgorithmIdentifier.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\AlgorithmIdentifier\\Asymmetric\\X25519AlgorithmIdentifier' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Asymmetric/X25519AlgorithmIdentifier.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\AlgorithmIdentifier\\Asymmetric\\X448AlgorithmIdentifier' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Asymmetric/X448AlgorithmIdentifier.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\AlgorithmIdentifier\\Cipher\\AES128CBCAlgorithmIdentifier' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Cipher/AES128CBCAlgorithmIdentifier.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\AlgorithmIdentifier\\Cipher\\AES192CBCAlgorithmIdentifier' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Cipher/AES192CBCAlgorithmIdentifier.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\AlgorithmIdentifier\\Cipher\\AES256CBCAlgorithmIdentifier' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Cipher/AES256CBCAlgorithmIdentifier.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\AlgorithmIdentifier\\Cipher\\AESCBCAlgorithmIdentifier' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Cipher/AESCBCAlgorithmIdentifier.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\AlgorithmIdentifier\\Cipher\\BlockCipherAlgorithmIdentifier' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Cipher/BlockCipherAlgorithmIdentifier.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\AlgorithmIdentifier\\Cipher\\CipherAlgorithmIdentifier' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Cipher/CipherAlgorithmIdentifier.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\AlgorithmIdentifier\\Cipher\\DESCBCAlgorithmIdentifier' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Cipher/DESCBCAlgorithmIdentifier.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\AlgorithmIdentifier\\Cipher\\DESEDE3CBCAlgorithmIdentifier' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Cipher/DESEDE3CBCAlgorithmIdentifier.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\AlgorithmIdentifier\\Cipher\\RC2CBCAlgorithmIdentifier' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Cipher/RC2CBCAlgorithmIdentifier.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\AlgorithmIdentifier\\Feature\\AlgorithmIdentifierType' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Feature/AlgorithmIdentifierType.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\AlgorithmIdentifier\\Feature\\AsymmetricCryptoAlgorithmIdentifier' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Feature/AsymmetricCryptoAlgorithmIdentifier.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\AlgorithmIdentifier\\Feature\\EncryptionAlgorithmIdentifier' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Feature/EncryptionAlgorithmIdentifier.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\AlgorithmIdentifier\\Feature\\HashAlgorithmIdentifier' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Feature/HashAlgorithmIdentifier.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\AlgorithmIdentifier\\Feature\\PRFAlgorithmIdentifier' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Feature/PRFAlgorithmIdentifier.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\AlgorithmIdentifier\\Feature\\SignatureAlgorithmIdentifier' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Feature/SignatureAlgorithmIdentifier.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\AlgorithmIdentifier\\GenericAlgorithmIdentifier' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/GenericAlgorithmIdentifier.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\AlgorithmIdentifier\\Hash\\HMACWithSHA1AlgorithmIdentifier' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Hash/HMACWithSHA1AlgorithmIdentifier.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\AlgorithmIdentifier\\Hash\\HMACWithSHA224AlgorithmIdentifier' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Hash/HMACWithSHA224AlgorithmIdentifier.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\AlgorithmIdentifier\\Hash\\HMACWithSHA256AlgorithmIdentifier' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Hash/HMACWithSHA256AlgorithmIdentifier.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\AlgorithmIdentifier\\Hash\\HMACWithSHA384AlgorithmIdentifier' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Hash/HMACWithSHA384AlgorithmIdentifier.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\AlgorithmIdentifier\\Hash\\HMACWithSHA512AlgorithmIdentifier' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Hash/HMACWithSHA512AlgorithmIdentifier.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\AlgorithmIdentifier\\Hash\\MD5AlgorithmIdentifier' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Hash/MD5AlgorithmIdentifier.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\AlgorithmIdentifier\\Hash\\RFC4231HMACAlgorithmIdentifier' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Hash/RFC4231HMACAlgorithmIdentifier.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\AlgorithmIdentifier\\Hash\\SHA1AlgorithmIdentifier' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Hash/SHA1AlgorithmIdentifier.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\AlgorithmIdentifier\\Hash\\SHA224AlgorithmIdentifier' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Hash/SHA224AlgorithmIdentifier.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\AlgorithmIdentifier\\Hash\\SHA256AlgorithmIdentifier' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Hash/SHA256AlgorithmIdentifier.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\AlgorithmIdentifier\\Hash\\SHA2AlgorithmIdentifier' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Hash/SHA2AlgorithmIdentifier.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\AlgorithmIdentifier\\Hash\\SHA384AlgorithmIdentifier' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Hash/SHA384AlgorithmIdentifier.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\AlgorithmIdentifier\\Hash\\SHA512AlgorithmIdentifier' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Hash/SHA512AlgorithmIdentifier.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\AlgorithmIdentifier\\Signature\\ECDSAWithSHA1AlgorithmIdentifier' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Signature/ECDSAWithSHA1AlgorithmIdentifier.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\AlgorithmIdentifier\\Signature\\ECDSAWithSHA224AlgorithmIdentifier' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Signature/ECDSAWithSHA224AlgorithmIdentifier.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\AlgorithmIdentifier\\Signature\\ECDSAWithSHA256AlgorithmIdentifier' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Signature/ECDSAWithSHA256AlgorithmIdentifier.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\AlgorithmIdentifier\\Signature\\ECDSAWithSHA384AlgorithmIdentifier' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Signature/ECDSAWithSHA384AlgorithmIdentifier.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\AlgorithmIdentifier\\Signature\\ECDSAWithSHA512AlgorithmIdentifier' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Signature/ECDSAWithSHA512AlgorithmIdentifier.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\AlgorithmIdentifier\\Signature\\ECSignatureAlgorithmIdentifier' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Signature/ECSignatureAlgorithmIdentifier.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\AlgorithmIdentifier\\Signature\\MD2WithRSAEncryptionAlgorithmIdentifier' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Signature/MD2WithRSAEncryptionAlgorithmIdentifier.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\AlgorithmIdentifier\\Signature\\MD4WithRSAEncryptionAlgorithmIdentifier' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Signature/MD4WithRSAEncryptionAlgorithmIdentifier.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\AlgorithmIdentifier\\Signature\\MD5WithRSAEncryptionAlgorithmIdentifier' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Signature/MD5WithRSAEncryptionAlgorithmIdentifier.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\AlgorithmIdentifier\\Signature\\RFC3279RSASignatureAlgorithmIdentifier' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Signature/RFC3279RSASignatureAlgorithmIdentifier.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\AlgorithmIdentifier\\Signature\\RFC4055RSASignatureAlgorithmIdentifier' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Signature/RFC4055RSASignatureAlgorithmIdentifier.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\AlgorithmIdentifier\\Signature\\RSASignatureAlgorithmIdentifier' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Signature/RSASignatureAlgorithmIdentifier.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\AlgorithmIdentifier\\Signature\\SHA1WithRSAEncryptionAlgorithmIdentifier' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Signature/SHA1WithRSAEncryptionAlgorithmIdentifier.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\AlgorithmIdentifier\\Signature\\SHA224WithRSAEncryptionAlgorithmIdentifier' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Signature/SHA224WithRSAEncryptionAlgorithmIdentifier.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\AlgorithmIdentifier\\Signature\\SHA256WithRSAEncryptionAlgorithmIdentifier' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Signature/SHA256WithRSAEncryptionAlgorithmIdentifier.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\AlgorithmIdentifier\\Signature\\SHA384WithRSAEncryptionAlgorithmIdentifier' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Signature/SHA384WithRSAEncryptionAlgorithmIdentifier.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\AlgorithmIdentifier\\Signature\\SHA512WithRSAEncryptionAlgorithmIdentifier' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Signature/SHA512WithRSAEncryptionAlgorithmIdentifier.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\AlgorithmIdentifier\\SpecificAlgorithmIdentifier' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/SpecificAlgorithmIdentifier.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\Asymmetric\\Attribute\\OneAsymmetricKeyAttributes' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/CryptoTypes/Asymmetric/Attribute/OneAsymmetricKeyAttributes.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\Asymmetric\\EC\\ECConversion' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/CryptoTypes/Asymmetric/EC/ECConversion.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\Asymmetric\\EC\\ECPrivateKey' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/CryptoTypes/Asymmetric/EC/ECPrivateKey.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\Asymmetric\\EC\\ECPublicKey' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/CryptoTypes/Asymmetric/EC/ECPublicKey.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\Asymmetric\\OneAsymmetricKey' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/CryptoTypes/Asymmetric/OneAsymmetricKey.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\Asymmetric\\PrivateKey' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/CryptoTypes/Asymmetric/PrivateKey.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\Asymmetric\\PrivateKeyInfo' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/CryptoTypes/Asymmetric/PrivateKeyInfo.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\Asymmetric\\PublicKey' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/CryptoTypes/Asymmetric/PublicKey.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\Asymmetric\\PublicKeyInfo' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/CryptoTypes/Asymmetric/PublicKeyInfo.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\Asymmetric\\RFC8410\\Curve25519\\Curve25519PrivateKey' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/CryptoTypes/Asymmetric/RFC8410/Curve25519/Curve25519PrivateKey.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\Asymmetric\\RFC8410\\Curve25519\\Curve25519PublicKey' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/CryptoTypes/Asymmetric/RFC8410/Curve25519/Curve25519PublicKey.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\Asymmetric\\RFC8410\\Curve25519\\Ed25519PrivateKey' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/CryptoTypes/Asymmetric/RFC8410/Curve25519/Ed25519PrivateKey.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\Asymmetric\\RFC8410\\Curve25519\\Ed25519PublicKey' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/CryptoTypes/Asymmetric/RFC8410/Curve25519/Ed25519PublicKey.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\Asymmetric\\RFC8410\\Curve25519\\X25519PrivateKey' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/CryptoTypes/Asymmetric/RFC8410/Curve25519/X25519PrivateKey.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\Asymmetric\\RFC8410\\Curve25519\\X25519PublicKey' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/CryptoTypes/Asymmetric/RFC8410/Curve25519/X25519PublicKey.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\Asymmetric\\RFC8410\\Curve448\\Ed448PrivateKey' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/CryptoTypes/Asymmetric/RFC8410/Curve448/Ed448PrivateKey.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\Asymmetric\\RFC8410\\Curve448\\Ed448PublicKey' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/CryptoTypes/Asymmetric/RFC8410/Curve448/Ed448PublicKey.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\Asymmetric\\RFC8410\\Curve448\\X448PrivateKey' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/CryptoTypes/Asymmetric/RFC8410/Curve448/X448PrivateKey.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\Asymmetric\\RFC8410\\Curve448\\X448PublicKey' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/CryptoTypes/Asymmetric/RFC8410/Curve448/X448PublicKey.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\Asymmetric\\RFC8410\\RFC8410PrivateKey' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/CryptoTypes/Asymmetric/RFC8410/RFC8410PrivateKey.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\Asymmetric\\RFC8410\\RFC8410PublicKey' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/CryptoTypes/Asymmetric/RFC8410/RFC8410PublicKey.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\Asymmetric\\RSA\\RSAPrivateKey' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/CryptoTypes/Asymmetric/RSA/RSAPrivateKey.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\Asymmetric\\RSA\\RSAPublicKey' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/CryptoTypes/Asymmetric/RSA/RSAPublicKey.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\Asymmetric\\RSA\\RSASSAPSSPrivateKey' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/CryptoTypes/Asymmetric/RSA/RSASSAPSSPrivateKey.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\Signature\\ECSignature' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/CryptoTypes/Signature/ECSignature.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\Signature\\Ed25519Signature' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/CryptoTypes/Signature/Ed25519Signature.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\Signature\\Ed448Signature' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/CryptoTypes/Signature/Ed448Signature.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\Signature\\GenericSignature' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/CryptoTypes/Signature/GenericSignature.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\Signature\\RSASignature' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/CryptoTypes/Signature/RSASignature.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\Signature\\Signature' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/CryptoTypes/Signature/Signature.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\X501\\ASN1\\Attribute' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/X501/ASN1/Attribute.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\X501\\ASN1\\AttributeType' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/X501/ASN1/AttributeType.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\X501\\ASN1\\AttributeTypeAndValue' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/X501/ASN1/AttributeTypeAndValue.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\X501\\ASN1\\AttributeValue\\AttributeValue' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/X501/ASN1/AttributeValue/AttributeValue.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\X501\\ASN1\\AttributeValue\\CommonNameValue' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/X501/ASN1/AttributeValue/CommonNameValue.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\X501\\ASN1\\AttributeValue\\CountryNameValue' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/X501/ASN1/AttributeValue/CountryNameValue.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\X501\\ASN1\\AttributeValue\\DescriptionValue' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/X501/ASN1/AttributeValue/DescriptionValue.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\X501\\ASN1\\AttributeValue\\Feature\\DirectoryString' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/X501/ASN1/AttributeValue/Feature/DirectoryString.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\X501\\ASN1\\AttributeValue\\Feature\\PrintableStringValue' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/X501/ASN1/AttributeValue/Feature/PrintableStringValue.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\X501\\ASN1\\AttributeValue\\GivenNameValue' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/X501/ASN1/AttributeValue/GivenNameValue.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\X501\\ASN1\\AttributeValue\\LocalityNameValue' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/X501/ASN1/AttributeValue/LocalityNameValue.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\X501\\ASN1\\AttributeValue\\NameValue' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/X501/ASN1/AttributeValue/NameValue.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\X501\\ASN1\\AttributeValue\\OrganizationNameValue' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/X501/ASN1/AttributeValue/OrganizationNameValue.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\X501\\ASN1\\AttributeValue\\OrganizationalUnitNameValue' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/X501/ASN1/AttributeValue/OrganizationalUnitNameValue.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\X501\\ASN1\\AttributeValue\\PseudonymValue' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/X501/ASN1/AttributeValue/PseudonymValue.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\X501\\ASN1\\AttributeValue\\SerialNumberValue' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/X501/ASN1/AttributeValue/SerialNumberValue.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\X501\\ASN1\\AttributeValue\\StateOrProvinceNameValue' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/X501/ASN1/AttributeValue/StateOrProvinceNameValue.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\X501\\ASN1\\AttributeValue\\SurnameValue' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/X501/ASN1/AttributeValue/SurnameValue.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\X501\\ASN1\\AttributeValue\\TitleValue' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/X501/ASN1/AttributeValue/TitleValue.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\X501\\ASN1\\AttributeValue\\UnknownAttributeValue' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/X501/ASN1/AttributeValue/UnknownAttributeValue.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\X501\\ASN1\\Collection\\AttributeCollection' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/X501/ASN1/Collection/AttributeCollection.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\X501\\ASN1\\Collection\\SequenceOfAttributes' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/X501/ASN1/Collection/SequenceOfAttributes.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\X501\\ASN1\\Collection\\SetOfAttributes' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/X501/ASN1/Collection/SetOfAttributes.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\X501\\ASN1\\Name' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/X501/ASN1/Name.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\X501\\ASN1\\RDN' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/X501/ASN1/RDN.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\X501\\DN\\DNParser' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/X501/DN/DNParser.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\X501\\MatchingRule\\BinaryMatch' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/X501/MatchingRule/BinaryMatch.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\X501\\MatchingRule\\CaseExactMatch' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/X501/MatchingRule/CaseExactMatch.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\X501\\MatchingRule\\CaseIgnoreMatch' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/X501/MatchingRule/CaseIgnoreMatch.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\X501\\MatchingRule\\MatchingRule' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/X501/MatchingRule/MatchingRule.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\X501\\MatchingRule\\StringPrepMatchingRule' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/X501/MatchingRule/StringPrepMatchingRule.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\X501\\StringPrep\\CheckBidiStep' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/X501/StringPrep/CheckBidiStep.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\X501\\StringPrep\\InsignificantNonSubstringSpaceStep' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/X501/StringPrep/InsignificantNonSubstringSpaceStep.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\X501\\StringPrep\\MapStep' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/X501/StringPrep/MapStep.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\X501\\StringPrep\\NormalizeStep' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/X501/StringPrep/NormalizeStep.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\X501\\StringPrep\\PrepareStep' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/X501/StringPrep/PrepareStep.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\X501\\StringPrep\\ProhibitStep' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/X501/StringPrep/ProhibitStep.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\X501\\StringPrep\\StringPreparer' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/X501/StringPrep/StringPreparer.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\X501\\StringPrep\\TranscodeStep' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/X501/StringPrep/TranscodeStep.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\X509\\AttributeCertificate\\AttCertIssuer' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/X509/AttributeCertificate/AttCertIssuer.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\X509\\AttributeCertificate\\AttCertValidityPeriod' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/X509/AttributeCertificate/AttCertValidityPeriod.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\X509\\AttributeCertificate\\AttributeCertificate' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/X509/AttributeCertificate/AttributeCertificate.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\X509\\AttributeCertificate\\AttributeCertificateInfo' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/X509/AttributeCertificate/AttributeCertificateInfo.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\X509\\AttributeCertificate\\Attribute\\AccessIdentityAttributeValue' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/X509/AttributeCertificate/Attribute/AccessIdentityAttributeValue.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\X509\\AttributeCertificate\\Attribute\\AuthenticationInfoAttributeValue' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/X509/AttributeCertificate/Attribute/AuthenticationInfoAttributeValue.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\X509\\AttributeCertificate\\Attribute\\ChargingIdentityAttributeValue' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/X509/AttributeCertificate/Attribute/ChargingIdentityAttributeValue.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\X509\\AttributeCertificate\\Attribute\\GroupAttributeValue' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/X509/AttributeCertificate/Attribute/GroupAttributeValue.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\X509\\AttributeCertificate\\Attribute\\IetfAttrSyntax' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/X509/AttributeCertificate/Attribute/IetfAttrSyntax.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\X509\\AttributeCertificate\\Attribute\\IetfAttrValue' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/X509/AttributeCertificate/Attribute/IetfAttrValue.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\X509\\AttributeCertificate\\Attribute\\RoleAttributeValue' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/X509/AttributeCertificate/Attribute/RoleAttributeValue.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\X509\\AttributeCertificate\\Attribute\\SvceAuthInfo' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/X509/AttributeCertificate/Attribute/SvceAuthInfo.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\X509\\AttributeCertificate\\Attributes' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/X509/AttributeCertificate/Attributes.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\X509\\AttributeCertificate\\Holder' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/X509/AttributeCertificate/Holder.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\X509\\AttributeCertificate\\IssuerSerial' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/X509/AttributeCertificate/IssuerSerial.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\X509\\AttributeCertificate\\ObjectDigestInfo' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/X509/AttributeCertificate/ObjectDigestInfo.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\X509\\AttributeCertificate\\V2Form' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/X509/AttributeCertificate/V2Form.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\X509\\AttributeCertificate\\Validation\\ACValidationConfig' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/X509/AttributeCertificate/Validation/ACValidationConfig.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\X509\\AttributeCertificate\\Validation\\ACValidator' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/X509/AttributeCertificate/Validation/ACValidator.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\X509\\AttributeCertificate\\Validation\\Exception\\ACValidationException' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/X509/AttributeCertificate/Validation/Exception/ACValidationException.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\X509\\Certificate\\Certificate' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/X509/Certificate/Certificate.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\X509\\Certificate\\CertificateBundle' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/X509/Certificate/CertificateBundle.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\X509\\Certificate\\CertificateChain' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/X509/Certificate/CertificateChain.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\X509\\Certificate\\Extension\\AAControlsExtension' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/X509/Certificate/Extension/AAControlsExtension.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\X509\\Certificate\\Extension\\AccessDescription\\AccessDescription' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/X509/Certificate/Extension/AccessDescription/AccessDescription.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\X509\\Certificate\\Extension\\AccessDescription\\AuthorityAccessDescription' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/X509/Certificate/Extension/AccessDescription/AuthorityAccessDescription.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\X509\\Certificate\\Extension\\AccessDescription\\SubjectAccessDescription' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/X509/Certificate/Extension/AccessDescription/SubjectAccessDescription.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\X509\\Certificate\\Extension\\AuthorityInformationAccessExtension' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/X509/Certificate/Extension/AuthorityInformationAccessExtension.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\X509\\Certificate\\Extension\\AuthorityKeyIdentifierExtension' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/X509/Certificate/Extension/AuthorityKeyIdentifierExtension.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\X509\\Certificate\\Extension\\BasicConstraintsExtension' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/X509/Certificate/Extension/BasicConstraintsExtension.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\X509\\Certificate\\Extension\\CRLDistributionPointsExtension' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/X509/Certificate/Extension/CRLDistributionPointsExtension.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\X509\\Certificate\\Extension\\CertificatePoliciesExtension' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/X509/Certificate/Extension/CertificatePoliciesExtension.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\X509\\Certificate\\Extension\\CertificatePolicy\\CPSQualifier' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/X509/Certificate/Extension/CertificatePolicy/CPSQualifier.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\X509\\Certificate\\Extension\\CertificatePolicy\\DisplayText' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/X509/Certificate/Extension/CertificatePolicy/DisplayText.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\X509\\Certificate\\Extension\\CertificatePolicy\\NoticeReference' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/X509/Certificate/Extension/CertificatePolicy/NoticeReference.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\X509\\Certificate\\Extension\\CertificatePolicy\\PolicyInformation' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/X509/Certificate/Extension/CertificatePolicy/PolicyInformation.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\X509\\Certificate\\Extension\\CertificatePolicy\\PolicyQualifierInfo' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/X509/Certificate/Extension/CertificatePolicy/PolicyQualifierInfo.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\X509\\Certificate\\Extension\\CertificatePolicy\\UserNoticeQualifier' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/X509/Certificate/Extension/CertificatePolicy/UserNoticeQualifier.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\X509\\Certificate\\Extension\\DistributionPoint\\DistributionPoint' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/X509/Certificate/Extension/DistributionPoint/DistributionPoint.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\X509\\Certificate\\Extension\\DistributionPoint\\DistributionPointName' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/X509/Certificate/Extension/DistributionPoint/DistributionPointName.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\X509\\Certificate\\Extension\\DistributionPoint\\FullName' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/X509/Certificate/Extension/DistributionPoint/FullName.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\X509\\Certificate\\Extension\\DistributionPoint\\ReasonFlags' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/X509/Certificate/Extension/DistributionPoint/ReasonFlags.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\X509\\Certificate\\Extension\\DistributionPoint\\RelativeName' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/X509/Certificate/Extension/DistributionPoint/RelativeName.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\X509\\Certificate\\Extension\\ExtendedKeyUsageExtension' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/X509/Certificate/Extension/ExtendedKeyUsageExtension.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\X509\\Certificate\\Extension\\Extension' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/X509/Certificate/Extension/Extension.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\X509\\Certificate\\Extension\\FreshestCRLExtension' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/X509/Certificate/Extension/FreshestCRLExtension.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\X509\\Certificate\\Extension\\InhibitAnyPolicyExtension' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/X509/Certificate/Extension/InhibitAnyPolicyExtension.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\X509\\Certificate\\Extension\\IssuerAlternativeNameExtension' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/X509/Certificate/Extension/IssuerAlternativeNameExtension.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\X509\\Certificate\\Extension\\KeyUsageExtension' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/X509/Certificate/Extension/KeyUsageExtension.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\X509\\Certificate\\Extension\\NameConstraintsExtension' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/X509/Certificate/Extension/NameConstraintsExtension.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\X509\\Certificate\\Extension\\NameConstraints\\GeneralSubtree' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/X509/Certificate/Extension/NameConstraints/GeneralSubtree.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\X509\\Certificate\\Extension\\NameConstraints\\GeneralSubtrees' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/X509/Certificate/Extension/NameConstraints/GeneralSubtrees.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\X509\\Certificate\\Extension\\NoRevocationAvailableExtension' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/X509/Certificate/Extension/NoRevocationAvailableExtension.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\X509\\Certificate\\Extension\\PolicyConstraintsExtension' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/X509/Certificate/Extension/PolicyConstraintsExtension.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\X509\\Certificate\\Extension\\PolicyMappingsExtension' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/X509/Certificate/Extension/PolicyMappingsExtension.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\X509\\Certificate\\Extension\\PolicyMappings\\PolicyMapping' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/X509/Certificate/Extension/PolicyMappings/PolicyMapping.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\X509\\Certificate\\Extension\\SubjectAlternativeNameExtension' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/X509/Certificate/Extension/SubjectAlternativeNameExtension.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\X509\\Certificate\\Extension\\SubjectDirectoryAttributesExtension' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/X509/Certificate/Extension/SubjectDirectoryAttributesExtension.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\X509\\Certificate\\Extension\\SubjectInformationAccessExtension' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/X509/Certificate/Extension/SubjectInformationAccessExtension.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\X509\\Certificate\\Extension\\SubjectKeyIdentifierExtension' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/X509/Certificate/Extension/SubjectKeyIdentifierExtension.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\X509\\Certificate\\Extension\\TargetInformationExtension' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/X509/Certificate/Extension/TargetInformationExtension.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\X509\\Certificate\\Extension\\Target\\Target' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/X509/Certificate/Extension/Target/Target.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\X509\\Certificate\\Extension\\Target\\TargetGroup' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/X509/Certificate/Extension/Target/TargetGroup.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\X509\\Certificate\\Extension\\Target\\TargetName' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/X509/Certificate/Extension/Target/TargetName.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\X509\\Certificate\\Extension\\Target\\Targets' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/X509/Certificate/Extension/Target/Targets.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\X509\\Certificate\\Extension\\UnknownExtension' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/X509/Certificate/Extension/UnknownExtension.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\X509\\Certificate\\Extensions' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/X509/Certificate/Extensions.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\X509\\Certificate\\TBSCertificate' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/X509/Certificate/TBSCertificate.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\X509\\Certificate\\Time' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/X509/Certificate/Time.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\X509\\Certificate\\UniqueIdentifier' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/X509/Certificate/UniqueIdentifier.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\X509\\Certificate\\Validity' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/X509/Certificate/Validity.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\X509\\CertificationPath\\CertificationPath' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/X509/CertificationPath/CertificationPath.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\X509\\CertificationPath\\Exception\\PathBuildingException' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/X509/CertificationPath/Exception/PathBuildingException.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\X509\\CertificationPath\\Exception\\PathValidationException' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/X509/CertificationPath/Exception/PathValidationException.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\X509\\CertificationPath\\PathBuilding\\CertificationPathBuilder' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/X509/CertificationPath/PathBuilding/CertificationPathBuilder.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\X509\\CertificationPath\\PathValidation\\PathValidationConfig' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/X509/CertificationPath/PathValidation/PathValidationConfig.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\X509\\CertificationPath\\PathValidation\\PathValidationResult' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/X509/CertificationPath/PathValidation/PathValidationResult.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\X509\\CertificationPath\\PathValidation\\PathValidator' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/X509/CertificationPath/PathValidation/PathValidator.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\X509\\CertificationPath\\PathValidation\\ValidatorState' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/X509/CertificationPath/PathValidation/ValidatorState.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\X509\\CertificationPath\\Policy\\PolicyNode' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/X509/CertificationPath/Policy/PolicyNode.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\X509\\CertificationPath\\Policy\\PolicyTree' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/X509/CertificationPath/Policy/PolicyTree.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\X509\\CertificationRequest\\Attribute\\ExtensionRequestValue' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/X509/CertificationRequest/Attribute/ExtensionRequestValue.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\X509\\CertificationRequest\\Attributes' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/X509/CertificationRequest/Attributes.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\X509\\CertificationRequest\\CertificationRequest' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/X509/CertificationRequest/CertificationRequest.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\X509\\CertificationRequest\\CertificationRequestInfo' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/X509/CertificationRequest/CertificationRequestInfo.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\X509\\Exception\\X509ValidationException' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/X509/Exception/X509ValidationException.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\X509\\Feature\\DateTimeHelper' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/X509/Feature/DateTimeHelper.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\X509\\GeneralName\\DNSName' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/X509/GeneralName/DNSName.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\X509\\GeneralName\\DirectoryName' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/X509/GeneralName/DirectoryName.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\X509\\GeneralName\\EDIPartyName' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/X509/GeneralName/EDIPartyName.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\X509\\GeneralName\\GeneralName' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/X509/GeneralName/GeneralName.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\X509\\GeneralName\\GeneralNames' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/X509/GeneralName/GeneralNames.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\X509\\GeneralName\\IPAddress' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/X509/GeneralName/IPAddress.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\X509\\GeneralName\\IPv4Address' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/X509/GeneralName/IPv4Address.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\X509\\GeneralName\\IPv6Address' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/X509/GeneralName/IPv6Address.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\X509\\GeneralName\\OtherName' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/X509/GeneralName/OtherName.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\X509\\GeneralName\\RFC822Name' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/X509/GeneralName/RFC822Name.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\X509\\GeneralName\\RegisteredID' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/X509/GeneralName/RegisteredID.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\X509\\GeneralName\\UniformResourceIdentifier' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/X509/GeneralName/UniformResourceIdentifier.php',
        '_ContaoManager\\SpomkyLabs\\Pki\\X509\\GeneralName\\X400Address' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/X509/GeneralName/X400Address.php',
        '_ContaoManager\\Stringable' => __DIR__ . '/..' . '/marc-mabe/php-enum/stubs/Stringable.php',
        '_ContaoManager\\Symfony\\Bridge\\Monolog\\Command\\ServerLogCommand' => __DIR__ . '/..' . '/symfony/monolog-bridge/Command/ServerLogCommand.php',
        '_ContaoManager\\Symfony\\Bridge\\Monolog\\Formatter\\CompatibilityFormatter' => __DIR__ . '/..' . '/symfony/monolog-bridge/Formatter/CompatibilityFormatter.php',
        '_ContaoManager\\Symfony\\Bridge\\Monolog\\Formatter\\ConsoleFormatter' => __DIR__ . '/..' . '/symfony/monolog-bridge/Formatter/ConsoleFormatter.php',
        '_ContaoManager\\Symfony\\Bridge\\Monolog\\Formatter\\VarDumperFormatter' => __DIR__ . '/..' . '/symfony/monolog-bridge/Formatter/VarDumperFormatter.php',
        '_ContaoManager\\Symfony\\Bridge\\Monolog\\Handler\\ChromePhpHandler' => __DIR__ . '/..' . '/symfony/monolog-bridge/Handler/ChromePhpHandler.php',
        '_ContaoManager\\Symfony\\Bridge\\Monolog\\Handler\\CompatibilityHandler' => __DIR__ . '/..' . '/symfony/monolog-bridge/Handler/CompatibilityHandler.php',
        '_ContaoManager\\Symfony\\Bridge\\Monolog\\Handler\\CompatibilityProcessingHandler' => __DIR__ . '/..' . '/symfony/monolog-bridge/Handler/CompatibilityProcessingHandler.php',
        '_ContaoManager\\Symfony\\Bridge\\Monolog\\Handler\\ConsoleHandler' => __DIR__ . '/..' . '/symfony/monolog-bridge/Handler/ConsoleHandler.php',
        '_ContaoManager\\Symfony\\Bridge\\Monolog\\Handler\\ElasticsearchLogstashHandler' => __DIR__ . '/..' . '/symfony/monolog-bridge/Handler/ElasticsearchLogstashHandler.php',
        '_ContaoManager\\Symfony\\Bridge\\Monolog\\Handler\\FingersCrossed\\HttpCodeActivationStrategy' => __DIR__ . '/..' . '/symfony/monolog-bridge/Handler/FingersCrossed/HttpCodeActivationStrategy.php',
        '_ContaoManager\\Symfony\\Bridge\\Monolog\\Handler\\FingersCrossed\\NotFoundActivationStrategy' => __DIR__ . '/..' . '/symfony/monolog-bridge/Handler/FingersCrossed/NotFoundActivationStrategy.php',
        '_ContaoManager\\Symfony\\Bridge\\Monolog\\Handler\\FirePHPHandler' => __DIR__ . '/..' . '/symfony/monolog-bridge/Handler/FirePHPHandler.php',
        '_ContaoManager\\Symfony\\Bridge\\Monolog\\Handler\\MailerHandler' => __DIR__ . '/..' . '/symfony/monolog-bridge/Handler/MailerHandler.php',
        '_ContaoManager\\Symfony\\Bridge\\Monolog\\Handler\\NotifierHandler' => __DIR__ . '/..' . '/symfony/monolog-bridge/Handler/NotifierHandler.php',
        '_ContaoManager\\Symfony\\Bridge\\Monolog\\Handler\\ServerLogHandler' => __DIR__ . '/..' . '/symfony/monolog-bridge/Handler/ServerLogHandler.php',
        '_ContaoManager\\Symfony\\Bridge\\Monolog\\Logger' => __DIR__ . '/..' . '/symfony/monolog-bridge/Logger.php',
        '_ContaoManager\\Symfony\\Bridge\\Monolog\\Processor\\AbstractTokenProcessor' => __DIR__ . '/..' . '/symfony/monolog-bridge/Processor/AbstractTokenProcessor.php',
        '_ContaoManager\\Symfony\\Bridge\\Monolog\\Processor\\CompatibilityProcessor' => __DIR__ . '/..' . '/symfony/monolog-bridge/Processor/CompatibilityProcessor.php',
        '_ContaoManager\\Symfony\\Bridge\\Monolog\\Processor\\ConsoleCommandProcessor' => __DIR__ . '/..' . '/symfony/monolog-bridge/Processor/ConsoleCommandProcessor.php',
        '_ContaoManager\\Symfony\\Bridge\\Monolog\\Processor\\DebugProcessor' => __DIR__ . '/..' . '/symfony/monolog-bridge/Processor/DebugProcessor.php',
        '_ContaoManager\\Symfony\\Bridge\\Monolog\\Processor\\RouteProcessor' => __DIR__ . '/..' . '/symfony/monolog-bridge/Processor/RouteProcessor.php',
        '_ContaoManager\\Symfony\\Bridge\\Monolog\\Processor\\SwitchUserTokenProcessor' => __DIR__ . '/..' . '/symfony/monolog-bridge/Processor/SwitchUserTokenProcessor.php',
        '_ContaoManager\\Symfony\\Bridge\\Monolog\\Processor\\TokenProcessor' => __DIR__ . '/..' . '/symfony/monolog-bridge/Processor/TokenProcessor.php',
        '_ContaoManager\\Symfony\\Bridge\\Monolog\\Processor\\WebProcessor' => __DIR__ . '/..' . '/symfony/monolog-bridge/Processor/WebProcessor.php',
        '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\CacheWarmer\\AbstractPhpFileCacheWarmer' => __DIR__ . '/..' . '/symfony/framework-bundle/CacheWarmer/AbstractPhpFileCacheWarmer.php',
        '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\CacheWarmer\\AnnotationsCacheWarmer' => __DIR__ . '/..' . '/symfony/framework-bundle/CacheWarmer/AnnotationsCacheWarmer.php',
        '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\CacheWarmer\\CachePoolClearerCacheWarmer' => __DIR__ . '/..' . '/symfony/framework-bundle/CacheWarmer/CachePoolClearerCacheWarmer.php',
        '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\CacheWarmer\\ConfigBuilderCacheWarmer' => __DIR__ . '/..' . '/symfony/framework-bundle/CacheWarmer/ConfigBuilderCacheWarmer.php',
        '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\CacheWarmer\\RouterCacheWarmer' => __DIR__ . '/..' . '/symfony/framework-bundle/CacheWarmer/RouterCacheWarmer.php',
        '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\CacheWarmer\\SerializerCacheWarmer' => __DIR__ . '/..' . '/symfony/framework-bundle/CacheWarmer/SerializerCacheWarmer.php',
        '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\CacheWarmer\\TranslationsCacheWarmer' => __DIR__ . '/..' . '/symfony/framework-bundle/CacheWarmer/TranslationsCacheWarmer.php',
        '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\CacheWarmer\\ValidatorCacheWarmer' => __DIR__ . '/..' . '/symfony/framework-bundle/CacheWarmer/ValidatorCacheWarmer.php',
        '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Command\\AboutCommand' => __DIR__ . '/..' . '/symfony/framework-bundle/Command/AboutCommand.php',
        '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Command\\AbstractConfigCommand' => __DIR__ . '/..' . '/symfony/framework-bundle/Command/AbstractConfigCommand.php',
        '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Command\\AssetsInstallCommand' => __DIR__ . '/..' . '/symfony/framework-bundle/Command/AssetsInstallCommand.php',
        '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Command\\BuildDebugContainerTrait' => __DIR__ . '/..' . '/symfony/framework-bundle/Command/BuildDebugContainerTrait.php',
        '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Command\\CacheClearCommand' => __DIR__ . '/..' . '/symfony/framework-bundle/Command/CacheClearCommand.php',
        '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Command\\CachePoolClearCommand' => __DIR__ . '/..' . '/symfony/framework-bundle/Command/CachePoolClearCommand.php',
        '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Command\\CachePoolDeleteCommand' => __DIR__ . '/..' . '/symfony/framework-bundle/Command/CachePoolDeleteCommand.php',
        '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Command\\CachePoolInvalidateTagsCommand' => __DIR__ . '/..' . '/symfony/framework-bundle/Command/CachePoolInvalidateTagsCommand.php',
        '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Command\\CachePoolListCommand' => __DIR__ . '/..' . '/symfony/framework-bundle/Command/CachePoolListCommand.php',
        '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Command\\CachePoolPruneCommand' => __DIR__ . '/..' . '/symfony/framework-bundle/Command/CachePoolPruneCommand.php',
        '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Command\\CacheWarmupCommand' => __DIR__ . '/..' . '/symfony/framework-bundle/Command/CacheWarmupCommand.php',
        '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Command\\ConfigDebugCommand' => __DIR__ . '/..' . '/symfony/framework-bundle/Command/ConfigDebugCommand.php',
        '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Command\\ConfigDumpReferenceCommand' => __DIR__ . '/..' . '/symfony/framework-bundle/Command/ConfigDumpReferenceCommand.php',
        '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Command\\ContainerDebugCommand' => __DIR__ . '/..' . '/symfony/framework-bundle/Command/ContainerDebugCommand.php',
        '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Command\\ContainerLintCommand' => __DIR__ . '/..' . '/symfony/framework-bundle/Command/ContainerLintCommand.php',
        '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Command\\DebugAutowiringCommand' => __DIR__ . '/..' . '/symfony/framework-bundle/Command/DebugAutowiringCommand.php',
        '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Command\\EventDispatcherDebugCommand' => __DIR__ . '/..' . '/symfony/framework-bundle/Command/EventDispatcherDebugCommand.php',
        '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Command\\RouterDebugCommand' => __DIR__ . '/..' . '/symfony/framework-bundle/Command/RouterDebugCommand.php',
        '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Command\\RouterMatchCommand' => __DIR__ . '/..' . '/symfony/framework-bundle/Command/RouterMatchCommand.php',
        '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Command\\SecretsDecryptToLocalCommand' => __DIR__ . '/..' . '/symfony/framework-bundle/Command/SecretsDecryptToLocalCommand.php',
        '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Command\\SecretsEncryptFromLocalCommand' => __DIR__ . '/..' . '/symfony/framework-bundle/Command/SecretsEncryptFromLocalCommand.php',
        '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Command\\SecretsGenerateKeysCommand' => __DIR__ . '/..' . '/symfony/framework-bundle/Command/SecretsGenerateKeysCommand.php',
        '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Command\\SecretsListCommand' => __DIR__ . '/..' . '/symfony/framework-bundle/Command/SecretsListCommand.php',
        '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Command\\SecretsRemoveCommand' => __DIR__ . '/..' . '/symfony/framework-bundle/Command/SecretsRemoveCommand.php',
        '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Command\\SecretsSetCommand' => __DIR__ . '/..' . '/symfony/framework-bundle/Command/SecretsSetCommand.php',
        '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Command\\TranslationDebugCommand' => __DIR__ . '/..' . '/symfony/framework-bundle/Command/TranslationDebugCommand.php',
        '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Command\\TranslationUpdateCommand' => __DIR__ . '/..' . '/symfony/framework-bundle/Command/TranslationUpdateCommand.php',
        '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Command\\WorkflowDumpCommand' => __DIR__ . '/..' . '/symfony/framework-bundle/Command/WorkflowDumpCommand.php',
        '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Command\\XliffLintCommand' => __DIR__ . '/..' . '/symfony/framework-bundle/Command/XliffLintCommand.php',
        '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Command\\YamlLintCommand' => __DIR__ . '/..' . '/symfony/framework-bundle/Command/YamlLintCommand.php',
        '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Console\\Application' => __DIR__ . '/..' . '/symfony/framework-bundle/Console/Application.php',
        '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Console\\Descriptor\\Descriptor' => __DIR__ . '/..' . '/symfony/framework-bundle/Console/Descriptor/Descriptor.php',
        '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Console\\Descriptor\\JsonDescriptor' => __DIR__ . '/..' . '/symfony/framework-bundle/Console/Descriptor/JsonDescriptor.php',
        '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Console\\Descriptor\\MarkdownDescriptor' => __DIR__ . '/..' . '/symfony/framework-bundle/Console/Descriptor/MarkdownDescriptor.php',
        '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Console\\Descriptor\\TextDescriptor' => __DIR__ . '/..' . '/symfony/framework-bundle/Console/Descriptor/TextDescriptor.php',
        '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Console\\Descriptor\\XmlDescriptor' => __DIR__ . '/..' . '/symfony/framework-bundle/Console/Descriptor/XmlDescriptor.php',
        '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Console\\Helper\\DescriptorHelper' => __DIR__ . '/..' . '/symfony/framework-bundle/Console/Helper/DescriptorHelper.php',
        '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Controller\\AbstractController' => __DIR__ . '/..' . '/symfony/framework-bundle/Controller/AbstractController.php',
        '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Controller\\ControllerResolver' => __DIR__ . '/..' . '/symfony/framework-bundle/Controller/ControllerResolver.php',
        '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Controller\\RedirectController' => __DIR__ . '/..' . '/symfony/framework-bundle/Controller/RedirectController.php',
        '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Controller\\TemplateController' => __DIR__ . '/..' . '/symfony/framework-bundle/Controller/TemplateController.php',
        '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\DataCollector\\AbstractDataCollector' => __DIR__ . '/..' . '/symfony/framework-bundle/DataCollector/AbstractDataCollector.php',
        '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\DataCollector\\RouterDataCollector' => __DIR__ . '/..' . '/symfony/framework-bundle/DataCollector/RouterDataCollector.php',
        '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\DataCollector\\TemplateAwareDataCollectorInterface' => __DIR__ . '/..' . '/symfony/framework-bundle/DataCollector/TemplateAwareDataCollectorInterface.php',
        '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\DependencyInjection\\Compiler\\AddAnnotationsCachedReaderPass' => __DIR__ . '/..' . '/symfony/framework-bundle/DependencyInjection/Compiler/AddAnnotationsCachedReaderPass.php',
        '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\DependencyInjection\\Compiler\\AddDebugLogProcessorPass' => __DIR__ . '/..' . '/symfony/framework-bundle/DependencyInjection/Compiler/AddDebugLogProcessorPass.php',
        '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\DependencyInjection\\Compiler\\AddExpressionLanguageProvidersPass' => __DIR__ . '/..' . '/symfony/framework-bundle/DependencyInjection/Compiler/AddExpressionLanguageProvidersPass.php',
        '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\DependencyInjection\\Compiler\\AssetsContextPass' => __DIR__ . '/..' . '/symfony/framework-bundle/DependencyInjection/Compiler/AssetsContextPass.php',
        '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\DependencyInjection\\Compiler\\ContainerBuilderDebugDumpPass' => __DIR__ . '/..' . '/symfony/framework-bundle/DependencyInjection/Compiler/ContainerBuilderDebugDumpPass.php',
        '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\DependencyInjection\\Compiler\\DataCollectorTranslatorPass' => __DIR__ . '/..' . '/symfony/framework-bundle/DependencyInjection/Compiler/DataCollectorTranslatorPass.php',
        '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\DependencyInjection\\Compiler\\EnableLoggerDebugModePass' => __DIR__ . '/..' . '/symfony/framework-bundle/DependencyInjection/Compiler/EnableLoggerDebugModePass.php',
        '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\DependencyInjection\\Compiler\\ErrorLoggerCompilerPass' => __DIR__ . '/..' . '/symfony/framework-bundle/DependencyInjection/Compiler/ErrorLoggerCompilerPass.php',
        '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\DependencyInjection\\Compiler\\LoggingTranslatorPass' => __DIR__ . '/..' . '/symfony/framework-bundle/DependencyInjection/Compiler/LoggingTranslatorPass.php',
        '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\DependencyInjection\\Compiler\\ProfilerPass' => __DIR__ . '/..' . '/symfony/framework-bundle/DependencyInjection/Compiler/ProfilerPass.php',
        '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\DependencyInjection\\Compiler\\RemoveUnusedSessionMarshallingHandlerPass' => __DIR__ . '/..' . '/symfony/framework-bundle/DependencyInjection/Compiler/RemoveUnusedSessionMarshallingHandlerPass.php',
        '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\DependencyInjection\\Compiler\\TestServiceContainerRealRefPass' => __DIR__ . '/..' . '/symfony/framework-bundle/DependencyInjection/Compiler/TestServiceContainerRealRefPass.php',
        '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\DependencyInjection\\Compiler\\TestServiceContainerWeakRefPass' => __DIR__ . '/..' . '/symfony/framework-bundle/DependencyInjection/Compiler/TestServiceContainerWeakRefPass.php',
        '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\DependencyInjection\\Compiler\\TranslationUpdateCommandPass' => __DIR__ . '/..' . '/symfony/framework-bundle/DependencyInjection/Compiler/TranslationUpdateCommandPass.php',
        '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\DependencyInjection\\Compiler\\UnusedTagsPass' => __DIR__ . '/..' . '/symfony/framework-bundle/DependencyInjection/Compiler/UnusedTagsPass.php',
        '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\DependencyInjection\\Compiler\\WorkflowGuardListenerPass' => __DIR__ . '/..' . '/symfony/framework-bundle/DependencyInjection/Compiler/WorkflowGuardListenerPass.php',
        '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\DependencyInjection\\Configuration' => __DIR__ . '/..' . '/symfony/framework-bundle/DependencyInjection/Configuration.php',
        '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\DependencyInjection\\FrameworkExtension' => __DIR__ . '/..' . '/symfony/framework-bundle/DependencyInjection/FrameworkExtension.php',
        '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\DependencyInjection\\VirtualRequestStackPass' => __DIR__ . '/..' . '/symfony/framework-bundle/DependencyInjection/VirtualRequestStackPass.php',
        '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\EventListener\\ConsoleProfilerListener' => __DIR__ . '/..' . '/symfony/framework-bundle/EventListener/ConsoleProfilerListener.php',
        '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\EventListener\\SuggestMissingPackageSubscriber' => __DIR__ . '/..' . '/symfony/framework-bundle/EventListener/SuggestMissingPackageSubscriber.php',
        '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\FrameworkBundle' => __DIR__ . '/..' . '/symfony/framework-bundle/FrameworkBundle.php',
        '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\HttpCache\\HttpCache' => __DIR__ . '/..' . '/symfony/framework-bundle/HttpCache/HttpCache.php',
        '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\KernelBrowser' => __DIR__ . '/..' . '/symfony/framework-bundle/KernelBrowser.php',
        '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Kernel\\MicroKernelTrait' => __DIR__ . '/..' . '/symfony/framework-bundle/Kernel/MicroKernelTrait.php',
        '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Routing\\AnnotatedRouteControllerLoader' => __DIR__ . '/..' . '/symfony/framework-bundle/Routing/AnnotatedRouteControllerLoader.php',
        '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Routing\\AttributeRouteControllerLoader' => __DIR__ . '/..' . '/symfony/framework-bundle/Routing/AttributeRouteControllerLoader.php',
        '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Routing\\Attribute\\AsRoutingConditionService' => __DIR__ . '/..' . '/symfony/framework-bundle/Routing/Attribute/AsRoutingConditionService.php',
        '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Routing\\DelegatingLoader' => __DIR__ . '/..' . '/symfony/framework-bundle/Routing/DelegatingLoader.php',
        '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Routing\\RedirectableCompiledUrlMatcher' => __DIR__ . '/..' . '/symfony/framework-bundle/Routing/RedirectableCompiledUrlMatcher.php',
        '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Routing\\RouteLoaderInterface' => __DIR__ . '/..' . '/symfony/framework-bundle/Routing/RouteLoaderInterface.php',
        '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Routing\\Router' => __DIR__ . '/..' . '/symfony/framework-bundle/Routing/Router.php',
        '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Secrets\\AbstractVault' => __DIR__ . '/..' . '/symfony/framework-bundle/Secrets/AbstractVault.php',
        '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Secrets\\DotenvVault' => __DIR__ . '/..' . '/symfony/framework-bundle/Secrets/DotenvVault.php',
        '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Secrets\\SodiumVault' => __DIR__ . '/..' . '/symfony/framework-bundle/Secrets/SodiumVault.php',
        '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Test\\BrowserKitAssertionsTrait' => __DIR__ . '/..' . '/symfony/framework-bundle/Test/BrowserKitAssertionsTrait.php',
        '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Test\\DomCrawlerAssertionsTrait' => __DIR__ . '/..' . '/symfony/framework-bundle/Test/DomCrawlerAssertionsTrait.php',
        '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Test\\HttpClientAssertionsTrait' => __DIR__ . '/..' . '/symfony/framework-bundle/Test/HttpClientAssertionsTrait.php',
        '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Test\\KernelTestCase' => __DIR__ . '/..' . '/symfony/framework-bundle/Test/KernelTestCase.php',
        '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Test\\MailerAssertionsTrait' => __DIR__ . '/..' . '/symfony/framework-bundle/Test/MailerAssertionsTrait.php',
        '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Test\\NotificationAssertionsTrait' => __DIR__ . '/..' . '/symfony/framework-bundle/Test/NotificationAssertionsTrait.php',
        '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Test\\TestBrowserToken' => __DIR__ . '/..' . '/symfony/framework-bundle/Test/TestBrowserToken.php',
        '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Test\\TestContainer' => __DIR__ . '/..' . '/symfony/framework-bundle/Test/TestContainer.php',
        '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Test\\WebTestAssertionsTrait' => __DIR__ . '/..' . '/symfony/framework-bundle/Test/WebTestAssertionsTrait.php',
        '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Test\\WebTestCase' => __DIR__ . '/..' . '/symfony/framework-bundle/Test/WebTestCase.php',
        '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Translation\\Translator' => __DIR__ . '/..' . '/symfony/framework-bundle/Translation/Translator.php',
        '_ContaoManager\\Symfony\\Bundle\\MonologBundle\\DependencyInjection\\Compiler\\AddProcessorsPass' => __DIR__ . '/..' . '/symfony/monolog-bundle/src/DependencyInjection/Compiler/AddProcessorsPass.php',
        '_ContaoManager\\Symfony\\Bundle\\MonologBundle\\DependencyInjection\\Compiler\\AddSwiftMailerTransportPass' => __DIR__ . '/..' . '/symfony/monolog-bundle/src/DependencyInjection/Compiler/AddSwiftMailerTransportPass.php',
        '_ContaoManager\\Symfony\\Bundle\\MonologBundle\\DependencyInjection\\Compiler\\DebugHandlerPass' => __DIR__ . '/..' . '/symfony/monolog-bundle/src/DependencyInjection/Compiler/DebugHandlerPass.php',
        '_ContaoManager\\Symfony\\Bundle\\MonologBundle\\DependencyInjection\\Compiler\\FixEmptyLoggerPass' => __DIR__ . '/..' . '/symfony/monolog-bundle/src/DependencyInjection/Compiler/FixEmptyLoggerPass.php',
        '_ContaoManager\\Symfony\\Bundle\\MonologBundle\\DependencyInjection\\Compiler\\LoggerChannelPass' => __DIR__ . '/..' . '/symfony/monolog-bundle/src/DependencyInjection/Compiler/LoggerChannelPass.php',
        '_ContaoManager\\Symfony\\Bundle\\MonologBundle\\DependencyInjection\\Configuration' => __DIR__ . '/..' . '/symfony/monolog-bundle/src/DependencyInjection/Configuration.php',
        '_ContaoManager\\Symfony\\Bundle\\MonologBundle\\DependencyInjection\\MonologExtension' => __DIR__ . '/..' . '/symfony/monolog-bundle/src/DependencyInjection/MonologExtension.php',
        '_ContaoManager\\Symfony\\Bundle\\MonologBundle\\MonologBundle' => __DIR__ . '/..' . '/symfony/monolog-bundle/src/MonologBundle.php',
        '_ContaoManager\\Symfony\\Bundle\\MonologBundle\\SwiftMailer\\MessageFactory' => __DIR__ . '/..' . '/symfony/monolog-bundle/src/SwiftMailer/MessageFactory.php',
        '_ContaoManager\\Symfony\\Bundle\\SecurityBundle\\CacheWarmer\\ExpressionCacheWarmer' => __DIR__ . '/..' . '/symfony/security-bundle/CacheWarmer/ExpressionCacheWarmer.php',
        '_ContaoManager\\Symfony\\Bundle\\SecurityBundle\\Command\\DebugFirewallCommand' => __DIR__ . '/..' . '/symfony/security-bundle/Command/DebugFirewallCommand.php',
        '_ContaoManager\\Symfony\\Bundle\\SecurityBundle\\DataCollector\\SecurityDataCollector' => __DIR__ . '/..' . '/symfony/security-bundle/DataCollector/SecurityDataCollector.php',
        '_ContaoManager\\Symfony\\Bundle\\SecurityBundle\\Debug\\TraceableFirewallListener' => __DIR__ . '/..' . '/symfony/security-bundle/Debug/TraceableFirewallListener.php',
        '_ContaoManager\\Symfony\\Bundle\\SecurityBundle\\Debug\\TraceableListenerTrait' => __DIR__ . '/..' . '/symfony/security-bundle/Debug/TraceableListenerTrait.php',
        '_ContaoManager\\Symfony\\Bundle\\SecurityBundle\\Debug\\WrappedLazyListener' => __DIR__ . '/..' . '/symfony/security-bundle/Debug/WrappedLazyListener.php',
        '_ContaoManager\\Symfony\\Bundle\\SecurityBundle\\Debug\\WrappedListener' => __DIR__ . '/..' . '/symfony/security-bundle/Debug/WrappedListener.php',
        '_ContaoManager\\Symfony\\Bundle\\SecurityBundle\\DependencyInjection\\Compiler\\AddExpressionLanguageProvidersPass' => __DIR__ . '/..' . '/symfony/security-bundle/DependencyInjection/Compiler/AddExpressionLanguageProvidersPass.php',
        '_ContaoManager\\Symfony\\Bundle\\SecurityBundle\\DependencyInjection\\Compiler\\AddSecurityVotersPass' => __DIR__ . '/..' . '/symfony/security-bundle/DependencyInjection/Compiler/AddSecurityVotersPass.php',
        '_ContaoManager\\Symfony\\Bundle\\SecurityBundle\\DependencyInjection\\Compiler\\AddSessionDomainConstraintPass' => __DIR__ . '/..' . '/symfony/security-bundle/DependencyInjection/Compiler/AddSessionDomainConstraintPass.php',
        '_ContaoManager\\Symfony\\Bundle\\SecurityBundle\\DependencyInjection\\Compiler\\CleanRememberMeVerifierPass' => __DIR__ . '/..' . '/symfony/security-bundle/DependencyInjection/Compiler/CleanRememberMeVerifierPass.php',
        '_ContaoManager\\Symfony\\Bundle\\SecurityBundle\\DependencyInjection\\Compiler\\MakeFirewallsEventDispatcherTraceablePass' => __DIR__ . '/..' . '/symfony/security-bundle/DependencyInjection/Compiler/MakeFirewallsEventDispatcherTraceablePass.php',
        '_ContaoManager\\Symfony\\Bundle\\SecurityBundle\\DependencyInjection\\Compiler\\RegisterCsrfFeaturesPass' => __DIR__ . '/..' . '/symfony/security-bundle/DependencyInjection/Compiler/RegisterCsrfFeaturesPass.php',
        '_ContaoManager\\Symfony\\Bundle\\SecurityBundle\\DependencyInjection\\Compiler\\RegisterEntryPointPass' => __DIR__ . '/..' . '/symfony/security-bundle/DependencyInjection/Compiler/RegisterEntryPointPass.php',
        '_ContaoManager\\Symfony\\Bundle\\SecurityBundle\\DependencyInjection\\Compiler\\RegisterGlobalSecurityEventListenersPass' => __DIR__ . '/..' . '/symfony/security-bundle/DependencyInjection/Compiler/RegisterGlobalSecurityEventListenersPass.php',
        '_ContaoManager\\Symfony\\Bundle\\SecurityBundle\\DependencyInjection\\Compiler\\RegisterLdapLocatorPass' => __DIR__ . '/..' . '/symfony/security-bundle/DependencyInjection/Compiler/RegisterLdapLocatorPass.php',
        '_ContaoManager\\Symfony\\Bundle\\SecurityBundle\\DependencyInjection\\Compiler\\RegisterTokenUsageTrackingPass' => __DIR__ . '/..' . '/symfony/security-bundle/DependencyInjection/Compiler/RegisterTokenUsageTrackingPass.php',
        '_ContaoManager\\Symfony\\Bundle\\SecurityBundle\\DependencyInjection\\Compiler\\ReplaceDecoratedRememberMeHandlerPass' => __DIR__ . '/..' . '/symfony/security-bundle/DependencyInjection/Compiler/ReplaceDecoratedRememberMeHandlerPass.php',
        '_ContaoManager\\Symfony\\Bundle\\SecurityBundle\\DependencyInjection\\Compiler\\SortFirewallListenersPass' => __DIR__ . '/..' . '/symfony/security-bundle/DependencyInjection/Compiler/SortFirewallListenersPass.php',
        '_ContaoManager\\Symfony\\Bundle\\SecurityBundle\\DependencyInjection\\MainConfiguration' => __DIR__ . '/..' . '/symfony/security-bundle/DependencyInjection/MainConfiguration.php',
        '_ContaoManager\\Symfony\\Bundle\\SecurityBundle\\DependencyInjection\\SecurityExtension' => __DIR__ . '/..' . '/symfony/security-bundle/DependencyInjection/SecurityExtension.php',
        '_ContaoManager\\Symfony\\Bundle\\SecurityBundle\\DependencyInjection\\Security\\AccessToken\\OidcTokenHandlerFactory' => __DIR__ . '/..' . '/symfony/security-bundle/DependencyInjection/Security/AccessToken/OidcTokenHandlerFactory.php',
        '_ContaoManager\\Symfony\\Bundle\\SecurityBundle\\DependencyInjection\\Security\\AccessToken\\OidcUserInfoTokenHandlerFactory' => __DIR__ . '/..' . '/symfony/security-bundle/DependencyInjection/Security/AccessToken/OidcUserInfoTokenHandlerFactory.php',
        '_ContaoManager\\Symfony\\Bundle\\SecurityBundle\\DependencyInjection\\Security\\AccessToken\\ServiceTokenHandlerFactory' => __DIR__ . '/..' . '/symfony/security-bundle/DependencyInjection/Security/AccessToken/ServiceTokenHandlerFactory.php',
        '_ContaoManager\\Symfony\\Bundle\\SecurityBundle\\DependencyInjection\\Security\\AccessToken\\TokenHandlerFactoryInterface' => __DIR__ . '/..' . '/symfony/security-bundle/DependencyInjection/Security/AccessToken/TokenHandlerFactoryInterface.php',
        '_ContaoManager\\Symfony\\Bundle\\SecurityBundle\\DependencyInjection\\Security\\Factory\\AbstractFactory' => __DIR__ . '/..' . '/symfony/security-bundle/DependencyInjection/Security/Factory/AbstractFactory.php',
        '_ContaoManager\\Symfony\\Bundle\\SecurityBundle\\DependencyInjection\\Security\\Factory\\AccessTokenFactory' => __DIR__ . '/..' . '/symfony/security-bundle/DependencyInjection/Security/Factory/AccessTokenFactory.php',
        '_ContaoManager\\Symfony\\Bundle\\SecurityBundle\\DependencyInjection\\Security\\Factory\\AuthenticatorFactoryInterface' => __DIR__ . '/..' . '/symfony/security-bundle/DependencyInjection/Security/Factory/AuthenticatorFactoryInterface.php',
        '_ContaoManager\\Symfony\\Bundle\\SecurityBundle\\DependencyInjection\\Security\\Factory\\CustomAuthenticatorFactory' => __DIR__ . '/..' . '/symfony/security-bundle/DependencyInjection/Security/Factory/CustomAuthenticatorFactory.php',
        '_ContaoManager\\Symfony\\Bundle\\SecurityBundle\\DependencyInjection\\Security\\Factory\\FirewallListenerFactoryInterface' => __DIR__ . '/..' . '/symfony/security-bundle/DependencyInjection/Security/Factory/FirewallListenerFactoryInterface.php',
        '_ContaoManager\\Symfony\\Bundle\\SecurityBundle\\DependencyInjection\\Security\\Factory\\FormLoginFactory' => __DIR__ . '/..' . '/symfony/security-bundle/DependencyInjection/Security/Factory/FormLoginFactory.php',
        '_ContaoManager\\Symfony\\Bundle\\SecurityBundle\\DependencyInjection\\Security\\Factory\\FormLoginLdapFactory' => __DIR__ . '/..' . '/symfony/security-bundle/DependencyInjection/Security/Factory/FormLoginLdapFactory.php',
        '_ContaoManager\\Symfony\\Bundle\\SecurityBundle\\DependencyInjection\\Security\\Factory\\HttpBasicFactory' => __DIR__ . '/..' . '/symfony/security-bundle/DependencyInjection/Security/Factory/HttpBasicFactory.php',
        '_ContaoManager\\Symfony\\Bundle\\SecurityBundle\\DependencyInjection\\Security\\Factory\\HttpBasicLdapFactory' => __DIR__ . '/..' . '/symfony/security-bundle/DependencyInjection/Security/Factory/HttpBasicLdapFactory.php',
        '_ContaoManager\\Symfony\\Bundle\\SecurityBundle\\DependencyInjection\\Security\\Factory\\JsonLoginFactory' => __DIR__ . '/..' . '/symfony/security-bundle/DependencyInjection/Security/Factory/JsonLoginFactory.php',
        '_ContaoManager\\Symfony\\Bundle\\SecurityBundle\\DependencyInjection\\Security\\Factory\\JsonLoginLdapFactory' => __DIR__ . '/..' . '/symfony/security-bundle/DependencyInjection/Security/Factory/JsonLoginLdapFactory.php',
        '_ContaoManager\\Symfony\\Bundle\\SecurityBundle\\DependencyInjection\\Security\\Factory\\LdapFactoryTrait' => __DIR__ . '/..' . '/symfony/security-bundle/DependencyInjection/Security/Factory/LdapFactoryTrait.php',
        '_ContaoManager\\Symfony\\Bundle\\SecurityBundle\\DependencyInjection\\Security\\Factory\\LoginLinkFactory' => __DIR__ . '/..' . '/symfony/security-bundle/DependencyInjection/Security/Factory/LoginLinkFactory.php',
        '_ContaoManager\\Symfony\\Bundle\\SecurityBundle\\DependencyInjection\\Security\\Factory\\LoginThrottlingFactory' => __DIR__ . '/..' . '/symfony/security-bundle/DependencyInjection/Security/Factory/LoginThrottlingFactory.php',
        '_ContaoManager\\Symfony\\Bundle\\SecurityBundle\\DependencyInjection\\Security\\Factory\\RememberMeFactory' => __DIR__ . '/..' . '/symfony/security-bundle/DependencyInjection/Security/Factory/RememberMeFactory.php',
        '_ContaoManager\\Symfony\\Bundle\\SecurityBundle\\DependencyInjection\\Security\\Factory\\RemoteUserFactory' => __DIR__ . '/..' . '/symfony/security-bundle/DependencyInjection/Security/Factory/RemoteUserFactory.php',
        '_ContaoManager\\Symfony\\Bundle\\SecurityBundle\\DependencyInjection\\Security\\Factory\\SignatureAlgorithmFactory' => __DIR__ . '/..' . '/symfony/security-bundle/DependencyInjection/Security/Factory/SignatureAlgorithmFactory.php',
        '_ContaoManager\\Symfony\\Bundle\\SecurityBundle\\DependencyInjection\\Security\\Factory\\StatelessAuthenticatorFactoryInterface' => __DIR__ . '/..' . '/symfony/security-bundle/DependencyInjection/Security/Factory/StatelessAuthenticatorFactoryInterface.php',
        '_ContaoManager\\Symfony\\Bundle\\SecurityBundle\\DependencyInjection\\Security\\Factory\\X509Factory' => __DIR__ . '/..' . '/symfony/security-bundle/DependencyInjection/Security/Factory/X509Factory.php',
        '_ContaoManager\\Symfony\\Bundle\\SecurityBundle\\DependencyInjection\\Security\\UserProvider\\InMemoryFactory' => __DIR__ . '/..' . '/symfony/security-bundle/DependencyInjection/Security/UserProvider/InMemoryFactory.php',
        '_ContaoManager\\Symfony\\Bundle\\SecurityBundle\\DependencyInjection\\Security\\UserProvider\\LdapFactory' => __DIR__ . '/..' . '/symfony/security-bundle/DependencyInjection/Security/UserProvider/LdapFactory.php',
        '_ContaoManager\\Symfony\\Bundle\\SecurityBundle\\DependencyInjection\\Security\\UserProvider\\UserProviderFactoryInterface' => __DIR__ . '/..' . '/symfony/security-bundle/DependencyInjection/Security/UserProvider/UserProviderFactoryInterface.php',
        '_ContaoManager\\Symfony\\Bundle\\SecurityBundle\\EventListener\\FirewallListener' => __DIR__ . '/..' . '/symfony/security-bundle/EventListener/FirewallListener.php',
        '_ContaoManager\\Symfony\\Bundle\\SecurityBundle\\EventListener\\VoteListener' => __DIR__ . '/..' . '/symfony/security-bundle/EventListener/VoteListener.php',
        '_ContaoManager\\Symfony\\Bundle\\SecurityBundle\\LoginLink\\FirewallAwareLoginLinkHandler' => __DIR__ . '/..' . '/symfony/security-bundle/LoginLink/FirewallAwareLoginLinkHandler.php',
        '_ContaoManager\\Symfony\\Bundle\\SecurityBundle\\RememberMe\\DecoratedRememberMeHandler' => __DIR__ . '/..' . '/symfony/security-bundle/RememberMe/DecoratedRememberMeHandler.php',
        '_ContaoManager\\Symfony\\Bundle\\SecurityBundle\\RememberMe\\FirewallAwareRememberMeHandler' => __DIR__ . '/..' . '/symfony/security-bundle/RememberMe/FirewallAwareRememberMeHandler.php',
        '_ContaoManager\\Symfony\\Bundle\\SecurityBundle\\Routing\\LogoutRouteLoader' => __DIR__ . '/..' . '/symfony/security-bundle/Routing/LogoutRouteLoader.php',
        '_ContaoManager\\Symfony\\Bundle\\SecurityBundle\\Security' => __DIR__ . '/..' . '/symfony/security-bundle/Security.php',
        '_ContaoManager\\Symfony\\Bundle\\SecurityBundle\\SecurityBundle' => __DIR__ . '/..' . '/symfony/security-bundle/SecurityBundle.php',
        '_ContaoManager\\Symfony\\Bundle\\SecurityBundle\\Security\\FirewallAwareTrait' => __DIR__ . '/..' . '/symfony/security-bundle/Security/FirewallAwareTrait.php',
        '_ContaoManager\\Symfony\\Bundle\\SecurityBundle\\Security\\FirewallConfig' => __DIR__ . '/..' . '/symfony/security-bundle/Security/FirewallConfig.php',
        '_ContaoManager\\Symfony\\Bundle\\SecurityBundle\\Security\\FirewallContext' => __DIR__ . '/..' . '/symfony/security-bundle/Security/FirewallContext.php',
        '_ContaoManager\\Symfony\\Bundle\\SecurityBundle\\Security\\FirewallMap' => __DIR__ . '/..' . '/symfony/security-bundle/Security/FirewallMap.php',
        '_ContaoManager\\Symfony\\Bundle\\SecurityBundle\\Security\\LazyFirewallContext' => __DIR__ . '/..' . '/symfony/security-bundle/Security/LazyFirewallContext.php',
        '_ContaoManager\\Symfony\\Bundle\\SecurityBundle\\Security\\UserAuthenticator' => __DIR__ . '/..' . '/symfony/security-bundle/Security/UserAuthenticator.php',
        '_ContaoManager\\Symfony\\Component\\Cache\\Adapter\\AbstractAdapter' => __DIR__ . '/..' . '/symfony/cache/Adapter/AbstractAdapter.php',
        '_ContaoManager\\Symfony\\Component\\Cache\\Adapter\\AbstractTagAwareAdapter' => __DIR__ . '/..' . '/symfony/cache/Adapter/AbstractTagAwareAdapter.php',
        '_ContaoManager\\Symfony\\Component\\Cache\\Adapter\\AdapterInterface' => __DIR__ . '/..' . '/symfony/cache/Adapter/AdapterInterface.php',
        '_ContaoManager\\Symfony\\Component\\Cache\\Adapter\\ApcuAdapter' => __DIR__ . '/..' . '/symfony/cache/Adapter/ApcuAdapter.php',
        '_ContaoManager\\Symfony\\Component\\Cache\\Adapter\\ArrayAdapter' => __DIR__ . '/..' . '/symfony/cache/Adapter/ArrayAdapter.php',
        '_ContaoManager\\Symfony\\Component\\Cache\\Adapter\\ChainAdapter' => __DIR__ . '/..' . '/symfony/cache/Adapter/ChainAdapter.php',
        '_ContaoManager\\Symfony\\Component\\Cache\\Adapter\\CouchbaseBucketAdapter' => __DIR__ . '/..' . '/symfony/cache/Adapter/CouchbaseBucketAdapter.php',
        '_ContaoManager\\Symfony\\Component\\Cache\\Adapter\\CouchbaseCollectionAdapter' => __DIR__ . '/..' . '/symfony/cache/Adapter/CouchbaseCollectionAdapter.php',
        '_ContaoManager\\Symfony\\Component\\Cache\\Adapter\\DoctrineDbalAdapter' => __DIR__ . '/..' . '/symfony/cache/Adapter/DoctrineDbalAdapter.php',
        '_ContaoManager\\Symfony\\Component\\Cache\\Adapter\\FilesystemAdapter' => __DIR__ . '/..' . '/symfony/cache/Adapter/FilesystemAdapter.php',
        '_ContaoManager\\Symfony\\Component\\Cache\\Adapter\\FilesystemTagAwareAdapter' => __DIR__ . '/..' . '/symfony/cache/Adapter/FilesystemTagAwareAdapter.php',
        '_ContaoManager\\Symfony\\Component\\Cache\\Adapter\\MemcachedAdapter' => __DIR__ . '/..' . '/symfony/cache/Adapter/MemcachedAdapter.php',
        '_ContaoManager\\Symfony\\Component\\Cache\\Adapter\\NullAdapter' => __DIR__ . '/..' . '/symfony/cache/Adapter/NullAdapter.php',
        '_ContaoManager\\Symfony\\Component\\Cache\\Adapter\\ParameterNormalizer' => __DIR__ . '/..' . '/symfony/cache/Adapter/ParameterNormalizer.php',
        '_ContaoManager\\Symfony\\Component\\Cache\\Adapter\\PdoAdapter' => __DIR__ . '/..' . '/symfony/cache/Adapter/PdoAdapter.php',
        '_ContaoManager\\Symfony\\Component\\Cache\\Adapter\\PhpArrayAdapter' => __DIR__ . '/..' . '/symfony/cache/Adapter/PhpArrayAdapter.php',
        '_ContaoManager\\Symfony\\Component\\Cache\\Adapter\\PhpFilesAdapter' => __DIR__ . '/..' . '/symfony/cache/Adapter/PhpFilesAdapter.php',
        '_ContaoManager\\Symfony\\Component\\Cache\\Adapter\\ProxyAdapter' => __DIR__ . '/..' . '/symfony/cache/Adapter/ProxyAdapter.php',
        '_ContaoManager\\Symfony\\Component\\Cache\\Adapter\\Psr16Adapter' => __DIR__ . '/..' . '/symfony/cache/Adapter/Psr16Adapter.php',
        '_ContaoManager\\Symfony\\Component\\Cache\\Adapter\\RedisAdapter' => __DIR__ . '/..' . '/symfony/cache/Adapter/RedisAdapter.php',
        '_ContaoManager\\Symfony\\Component\\Cache\\Adapter\\RedisTagAwareAdapter' => __DIR__ . '/..' . '/symfony/cache/Adapter/RedisTagAwareAdapter.php',
        '_ContaoManager\\Symfony\\Component\\Cache\\Adapter\\TagAwareAdapter' => __DIR__ . '/..' . '/symfony/cache/Adapter/TagAwareAdapter.php',
        '_ContaoManager\\Symfony\\Component\\Cache\\Adapter\\TagAwareAdapterInterface' => __DIR__ . '/..' . '/symfony/cache/Adapter/TagAwareAdapterInterface.php',
        '_ContaoManager\\Symfony\\Component\\Cache\\Adapter\\TraceableAdapter' => __DIR__ . '/..' . '/symfony/cache/Adapter/TraceableAdapter.php',
        '_ContaoManager\\Symfony\\Component\\Cache\\Adapter\\TraceableTagAwareAdapter' => __DIR__ . '/..' . '/symfony/cache/Adapter/TraceableTagAwareAdapter.php',
        '_ContaoManager\\Symfony\\Component\\Cache\\CacheItem' => __DIR__ . '/..' . '/symfony/cache/CacheItem.php',
        '_ContaoManager\\Symfony\\Component\\Cache\\DataCollector\\CacheDataCollector' => __DIR__ . '/..' . '/symfony/cache/DataCollector/CacheDataCollector.php',
        '_ContaoManager\\Symfony\\Component\\Cache\\DependencyInjection\\CacheCollectorPass' => __DIR__ . '/..' . '/symfony/cache/DependencyInjection/CacheCollectorPass.php',
        '_ContaoManager\\Symfony\\Component\\Cache\\DependencyInjection\\CachePoolClearerPass' => __DIR__ . '/..' . '/symfony/cache/DependencyInjection/CachePoolClearerPass.php',
        '_ContaoManager\\Symfony\\Component\\Cache\\DependencyInjection\\CachePoolPass' => __DIR__ . '/..' . '/symfony/cache/DependencyInjection/CachePoolPass.php',
        '_ContaoManager\\Symfony\\Component\\Cache\\DependencyInjection\\CachePoolPrunerPass' => __DIR__ . '/..' . '/symfony/cache/DependencyInjection/CachePoolPrunerPass.php',
        '_ContaoManager\\Symfony\\Component\\Cache\\Exception\\CacheException' => __DIR__ . '/..' . '/symfony/cache/Exception/CacheException.php',
        '_ContaoManager\\Symfony\\Component\\Cache\\Exception\\InvalidArgumentException' => __DIR__ . '/..' . '/symfony/cache/Exception/InvalidArgumentException.php',
        '_ContaoManager\\Symfony\\Component\\Cache\\Exception\\LogicException' => __DIR__ . '/..' . '/symfony/cache/Exception/LogicException.php',
        '_ContaoManager\\Symfony\\Component\\Cache\\LockRegistry' => __DIR__ . '/..' . '/symfony/cache/LockRegistry.php',
        '_ContaoManager\\Symfony\\Component\\Cache\\Marshaller\\DefaultMarshaller' => __DIR__ . '/..' . '/symfony/cache/Marshaller/DefaultMarshaller.php',
        '_ContaoManager\\Symfony\\Component\\Cache\\Marshaller\\DeflateMarshaller' => __DIR__ . '/..' . '/symfony/cache/Marshaller/DeflateMarshaller.php',
        '_ContaoManager\\Symfony\\Component\\Cache\\Marshaller\\MarshallerInterface' => __DIR__ . '/..' . '/symfony/cache/Marshaller/MarshallerInterface.php',
        '_ContaoManager\\Symfony\\Component\\Cache\\Marshaller\\SodiumMarshaller' => __DIR__ . '/..' . '/symfony/cache/Marshaller/SodiumMarshaller.php',
        '_ContaoManager\\Symfony\\Component\\Cache\\Marshaller\\TagAwareMarshaller' => __DIR__ . '/..' . '/symfony/cache/Marshaller/TagAwareMarshaller.php',
        '_ContaoManager\\Symfony\\Component\\Cache\\Messenger\\EarlyExpirationDispatcher' => __DIR__ . '/..' . '/symfony/cache/Messenger/EarlyExpirationDispatcher.php',
        '_ContaoManager\\Symfony\\Component\\Cache\\Messenger\\EarlyExpirationHandler' => __DIR__ . '/..' . '/symfony/cache/Messenger/EarlyExpirationHandler.php',
        '_ContaoManager\\Symfony\\Component\\Cache\\Messenger\\EarlyExpirationMessage' => __DIR__ . '/..' . '/symfony/cache/Messenger/EarlyExpirationMessage.php',
        '_ContaoManager\\Symfony\\Component\\Cache\\PruneableInterface' => __DIR__ . '/..' . '/symfony/cache/PruneableInterface.php',
        '_ContaoManager\\Symfony\\Component\\Cache\\Psr16Cache' => __DIR__ . '/..' . '/symfony/cache/Psr16Cache.php',
        '_ContaoManager\\Symfony\\Component\\Cache\\ResettableInterface' => __DIR__ . '/..' . '/symfony/cache/ResettableInterface.php',
        '_ContaoManager\\Symfony\\Component\\Cache\\Traits\\AbstractAdapterTrait' => __DIR__ . '/..' . '/symfony/cache/Traits/AbstractAdapterTrait.php',
        '_ContaoManager\\Symfony\\Component\\Cache\\Traits\\CachedValueInterface' => __DIR__ . '/..' . '/symfony/cache/Traits/CachedValueInterface.php',
        '_ContaoManager\\Symfony\\Component\\Cache\\Traits\\ContractsTrait' => __DIR__ . '/..' . '/symfony/cache/Traits/ContractsTrait.php',
        '_ContaoManager\\Symfony\\Component\\Cache\\Traits\\FilesystemCommonTrait' => __DIR__ . '/..' . '/symfony/cache/Traits/FilesystemCommonTrait.php',
        '_ContaoManager\\Symfony\\Component\\Cache\\Traits\\FilesystemTrait' => __DIR__ . '/..' . '/symfony/cache/Traits/FilesystemTrait.php',
        '_ContaoManager\\Symfony\\Component\\Cache\\Traits\\ProxyTrait' => __DIR__ . '/..' . '/symfony/cache/Traits/ProxyTrait.php',
        '_ContaoManager\\Symfony\\Component\\Cache\\Traits\\Redis5Proxy' => __DIR__ . '/..' . '/symfony/cache/Traits/Redis5Proxy.php',
        '_ContaoManager\\Symfony\\Component\\Cache\\Traits\\Redis61ProxyTrait' => __DIR__ . '/..' . '/symfony/cache/Traits/Redis61ProxyTrait.php',
        '_ContaoManager\\Symfony\\Component\\Cache\\Traits\\Redis62ProxyTrait' => __DIR__ . '/..' . '/symfony/cache/Traits/Redis62ProxyTrait.php',
        '_ContaoManager\\Symfony\\Component\\Cache\\Traits\\Redis63ProxyTrait' => __DIR__ . '/..' . '/symfony/cache/Traits/Redis63ProxyTrait.php',
        '_ContaoManager\\Symfony\\Component\\Cache\\Traits\\Redis6Proxy' => __DIR__ . '/..' . '/symfony/cache/Traits/Redis6Proxy.php',
        '_ContaoManager\\Symfony\\Component\\Cache\\Traits\\RedisCluster5Proxy' => __DIR__ . '/..' . '/symfony/cache/Traits/RedisCluster5Proxy.php',
        '_ContaoManager\\Symfony\\Component\\Cache\\Traits\\RedisCluster61ProxyTrait' => __DIR__ . '/..' . '/symfony/cache/Traits/RedisCluster61ProxyTrait.php',
        '_ContaoManager\\Symfony\\Component\\Cache\\Traits\\RedisCluster62ProxyTrait' => __DIR__ . '/..' . '/symfony/cache/Traits/RedisCluster62ProxyTrait.php',
        '_ContaoManager\\Symfony\\Component\\Cache\\Traits\\RedisCluster63ProxyTrait' => __DIR__ . '/..' . '/symfony/cache/Traits/RedisCluster63ProxyTrait.php',
        '_ContaoManager\\Symfony\\Component\\Cache\\Traits\\RedisCluster6Proxy' => __DIR__ . '/..' . '/symfony/cache/Traits/RedisCluster6Proxy.php',
        '_ContaoManager\\Symfony\\Component\\Cache\\Traits\\RedisClusterNodeProxy' => __DIR__ . '/..' . '/symfony/cache/Traits/RedisClusterNodeProxy.php',
        '_ContaoManager\\Symfony\\Component\\Cache\\Traits\\RedisClusterProxy' => __DIR__ . '/..' . '/symfony/cache/Traits/RedisClusterProxy.php',
        '_ContaoManager\\Symfony\\Component\\Cache\\Traits\\RedisProxy' => __DIR__ . '/..' . '/symfony/cache/Traits/RedisProxy.php',
        '_ContaoManager\\Symfony\\Component\\Cache\\Traits\\RedisTrait' => __DIR__ . '/..' . '/symfony/cache/Traits/RedisTrait.php',
        '_ContaoManager\\Symfony\\Component\\Cache\\Traits\\RelayProxy' => __DIR__ . '/..' . '/symfony/cache/Traits/RelayProxy.php',
        '_ContaoManager\\Symfony\\Component\\Cache\\Traits\\RelayProxyTrait' => __DIR__ . '/..' . '/symfony/cache/Traits/RelayProxyTrait.php',
        '_ContaoManager\\Symfony\\Component\\Cache\\Traits\\Relay\\BgsaveTrait' => __DIR__ . '/..' . '/symfony/cache/Traits/Relay/BgsaveTrait.php',
        '_ContaoManager\\Symfony\\Component\\Cache\\Traits\\Relay\\CopyTrait' => __DIR__ . '/..' . '/symfony/cache/Traits/Relay/CopyTrait.php',
        '_ContaoManager\\Symfony\\Component\\Cache\\Traits\\Relay\\FtTrait' => __DIR__ . '/..' . '/symfony/cache/Traits/Relay/FtTrait.php',
        '_ContaoManager\\Symfony\\Component\\Cache\\Traits\\Relay\\GeosearchTrait' => __DIR__ . '/..' . '/symfony/cache/Traits/Relay/GeosearchTrait.php',
        '_ContaoManager\\Symfony\\Component\\Cache\\Traits\\Relay\\GetWithMetaTrait' => __DIR__ . '/..' . '/symfony/cache/Traits/Relay/GetWithMetaTrait.php',
        '_ContaoManager\\Symfony\\Component\\Cache\\Traits\\Relay\\GetrangeTrait' => __DIR__ . '/..' . '/symfony/cache/Traits/Relay/GetrangeTrait.php',
        '_ContaoManager\\Symfony\\Component\\Cache\\Traits\\Relay\\HsetTrait' => __DIR__ . '/..' . '/symfony/cache/Traits/Relay/HsetTrait.php',
        '_ContaoManager\\Symfony\\Component\\Cache\\Traits\\Relay\\IsTrackedTrait' => __DIR__ . '/..' . '/symfony/cache/Traits/Relay/IsTrackedTrait.php',
        '_ContaoManager\\Symfony\\Component\\Cache\\Traits\\Relay\\MoveTrait' => __DIR__ . '/..' . '/symfony/cache/Traits/Relay/MoveTrait.php',
        '_ContaoManager\\Symfony\\Component\\Cache\\Traits\\Relay\\NullableReturnTrait' => __DIR__ . '/..' . '/symfony/cache/Traits/Relay/NullableReturnTrait.php',
        '_ContaoManager\\Symfony\\Component\\Cache\\Traits\\Relay\\PfcountTrait' => __DIR__ . '/..' . '/symfony/cache/Traits/Relay/PfcountTrait.php',
        '_ContaoManager\\Symfony\\Component\\Cache\\Traits\\Relay\\Relay11Trait' => __DIR__ . '/..' . '/symfony/cache/Traits/Relay/Relay11Trait.php',
        '_ContaoManager\\Symfony\\Component\\Cache\\Traits\\Relay\\Relay121Trait' => __DIR__ . '/..' . '/symfony/cache/Traits/Relay/Relay121Trait.php',
        '_ContaoManager\\Symfony\\Component\\Cache\\Traits\\Relay\\Relay12Trait' => __DIR__ . '/..' . '/symfony/cache/Traits/Relay/Relay12Trait.php',
        '_ContaoManager\\Symfony\\Component\\Cache\\Traits\\Relay\\Relay20Trait' => __DIR__ . '/..' . '/symfony/cache/Traits/Relay/Relay20Trait.php',
        '_ContaoManager\\Symfony\\Component\\Cache\\Traits\\Relay\\Relay21Trait' => __DIR__ . '/..' . '/symfony/cache/Traits/Relay/Relay21Trait.php',
        '_ContaoManager\\Symfony\\Component\\Cache\\Traits\\Relay\\SwapdbTrait' => __DIR__ . '/..' . '/symfony/cache/Traits/Relay/SwapdbTrait.php',
        '_ContaoManager\\Symfony\\Component\\Clock\\Clock' => __DIR__ . '/..' . '/symfony/clock/Clock.php',
        '_ContaoManager\\Symfony\\Component\\Clock\\ClockAwareTrait' => __DIR__ . '/..' . '/symfony/clock/ClockAwareTrait.php',
        '_ContaoManager\\Symfony\\Component\\Clock\\ClockInterface' => __DIR__ . '/..' . '/symfony/clock/ClockInterface.php',
        '_ContaoManager\\Symfony\\Component\\Clock\\DatePoint' => __DIR__ . '/..' . '/symfony/clock/DatePoint.php',
        '_ContaoManager\\Symfony\\Component\\Clock\\MockClock' => __DIR__ . '/..' . '/symfony/clock/MockClock.php',
        '_ContaoManager\\Symfony\\Component\\Clock\\MonotonicClock' => __DIR__ . '/..' . '/symfony/clock/MonotonicClock.php',
        '_ContaoManager\\Symfony\\Component\\Clock\\NativeClock' => __DIR__ . '/..' . '/symfony/clock/NativeClock.php',
        '_ContaoManager\\Symfony\\Component\\Clock\\Test\\ClockSensitiveTrait' => __DIR__ . '/..' . '/symfony/clock/Test/ClockSensitiveTrait.php',
        '_ContaoManager\\Symfony\\Component\\Config\\Builder\\ClassBuilder' => __DIR__ . '/..' . '/symfony/config/Builder/ClassBuilder.php',
        '_ContaoManager\\Symfony\\Component\\Config\\Builder\\ConfigBuilderGenerator' => __DIR__ . '/..' . '/symfony/config/Builder/ConfigBuilderGenerator.php',
        '_ContaoManager\\Symfony\\Component\\Config\\Builder\\ConfigBuilderGeneratorInterface' => __DIR__ . '/..' . '/symfony/config/Builder/ConfigBuilderGeneratorInterface.php',
        '_ContaoManager\\Symfony\\Component\\Config\\Builder\\ConfigBuilderInterface' => __DIR__ . '/..' . '/symfony/config/Builder/ConfigBuilderInterface.php',
        '_ContaoManager\\Symfony\\Component\\Config\\Builder\\Method' => __DIR__ . '/..' . '/symfony/config/Builder/Method.php',
        '_ContaoManager\\Symfony\\Component\\Config\\Builder\\Property' => __DIR__ . '/..' . '/symfony/config/Builder/Property.php',
        '_ContaoManager\\Symfony\\Component\\Config\\ConfigCache' => __DIR__ . '/..' . '/symfony/config/ConfigCache.php',
        '_ContaoManager\\Symfony\\Component\\Config\\ConfigCacheFactory' => __DIR__ . '/..' . '/symfony/config/ConfigCacheFactory.php',
        '_ContaoManager\\Symfony\\Component\\Config\\ConfigCacheFactoryInterface' => __DIR__ . '/..' . '/symfony/config/ConfigCacheFactoryInterface.php',
        '_ContaoManager\\Symfony\\Component\\Config\\ConfigCacheInterface' => __DIR__ . '/..' . '/symfony/config/ConfigCacheInterface.php',
        '_ContaoManager\\Symfony\\Component\\Config\\Definition\\ArrayNode' => __DIR__ . '/..' . '/symfony/config/Definition/ArrayNode.php',
        '_ContaoManager\\Symfony\\Component\\Config\\Definition\\BaseNode' => __DIR__ . '/..' . '/symfony/config/Definition/BaseNode.php',
        '_ContaoManager\\Symfony\\Component\\Config\\Definition\\BooleanNode' => __DIR__ . '/..' . '/symfony/config/Definition/BooleanNode.php',
        '_ContaoManager\\Symfony\\Component\\Config\\Definition\\Builder\\ArrayNodeDefinition' => __DIR__ . '/..' . '/symfony/config/Definition/Builder/ArrayNodeDefinition.php',
        '_ContaoManager\\Symfony\\Component\\Config\\Definition\\Builder\\BooleanNodeDefinition' => __DIR__ . '/..' . '/symfony/config/Definition/Builder/BooleanNodeDefinition.php',
        '_ContaoManager\\Symfony\\Component\\Config\\Definition\\Builder\\BuilderAwareInterface' => __DIR__ . '/..' . '/symfony/config/Definition/Builder/BuilderAwareInterface.php',
        '_ContaoManager\\Symfony\\Component\\Config\\Definition\\Builder\\EnumNodeDefinition' => __DIR__ . '/..' . '/symfony/config/Definition/Builder/EnumNodeDefinition.php',
        '_ContaoManager\\Symfony\\Component\\Config\\Definition\\Builder\\ExprBuilder' => __DIR__ . '/..' . '/symfony/config/Definition/Builder/ExprBuilder.php',
        '_ContaoManager\\Symfony\\Component\\Config\\Definition\\Builder\\FloatNodeDefinition' => __DIR__ . '/..' . '/symfony/config/Definition/Builder/FloatNodeDefinition.php',
        '_ContaoManager\\Symfony\\Component\\Config\\Definition\\Builder\\IntegerNodeDefinition' => __DIR__ . '/..' . '/symfony/config/Definition/Builder/IntegerNodeDefinition.php',
        '_ContaoManager\\Symfony\\Component\\Config\\Definition\\Builder\\MergeBuilder' => __DIR__ . '/..' . '/symfony/config/Definition/Builder/MergeBuilder.php',
        '_ContaoManager\\Symfony\\Component\\Config\\Definition\\Builder\\NodeBuilder' => __DIR__ . '/..' . '/symfony/config/Definition/Builder/NodeBuilder.php',
        '_ContaoManager\\Symfony\\Component\\Config\\Definition\\Builder\\NodeDefinition' => __DIR__ . '/..' . '/symfony/config/Definition/Builder/NodeDefinition.php',
        '_ContaoManager\\Symfony\\Component\\Config\\Definition\\Builder\\NodeParentInterface' => __DIR__ . '/..' . '/symfony/config/Definition/Builder/NodeParentInterface.php',
        '_ContaoManager\\Symfony\\Component\\Config\\Definition\\Builder\\NormalizationBuilder' => __DIR__ . '/..' . '/symfony/config/Definition/Builder/NormalizationBuilder.php',
        '_ContaoManager\\Symfony\\Component\\Config\\Definition\\Builder\\NumericNodeDefinition' => __DIR__ . '/..' . '/symfony/config/Definition/Builder/NumericNodeDefinition.php',
        '_ContaoManager\\Symfony\\Component\\Config\\Definition\\Builder\\ParentNodeDefinitionInterface' => __DIR__ . '/..' . '/symfony/config/Definition/Builder/ParentNodeDefinitionInterface.php',
        '_ContaoManager\\Symfony\\Component\\Config\\Definition\\Builder\\ScalarNodeDefinition' => __DIR__ . '/..' . '/symfony/config/Definition/Builder/ScalarNodeDefinition.php',
        '_ContaoManager\\Symfony\\Component\\Config\\Definition\\Builder\\TreeBuilder' => __DIR__ . '/..' . '/symfony/config/Definition/Builder/TreeBuilder.php',
        '_ContaoManager\\Symfony\\Component\\Config\\Definition\\Builder\\ValidationBuilder' => __DIR__ . '/..' . '/symfony/config/Definition/Builder/ValidationBuilder.php',
        '_ContaoManager\\Symfony\\Component\\Config\\Definition\\Builder\\VariableNodeDefinition' => __DIR__ . '/..' . '/symfony/config/Definition/Builder/VariableNodeDefinition.php',
        '_ContaoManager\\Symfony\\Component\\Config\\Definition\\ConfigurableInterface' => __DIR__ . '/..' . '/symfony/config/Definition/ConfigurableInterface.php',
        '_ContaoManager\\Symfony\\Component\\Config\\Definition\\Configuration' => __DIR__ . '/..' . '/symfony/config/Definition/Configuration.php',
        '_ContaoManager\\Symfony\\Component\\Config\\Definition\\ConfigurationInterface' => __DIR__ . '/..' . '/symfony/config/Definition/ConfigurationInterface.php',
        '_ContaoManager\\Symfony\\Component\\Config\\Definition\\Configurator\\DefinitionConfigurator' => __DIR__ . '/..' . '/symfony/config/Definition/Configurator/DefinitionConfigurator.php',
        '_ContaoManager\\Symfony\\Component\\Config\\Definition\\Dumper\\XmlReferenceDumper' => __DIR__ . '/..' . '/symfony/config/Definition/Dumper/XmlReferenceDumper.php',
        '_ContaoManager\\Symfony\\Component\\Config\\Definition\\Dumper\\YamlReferenceDumper' => __DIR__ . '/..' . '/symfony/config/Definition/Dumper/YamlReferenceDumper.php',
        '_ContaoManager\\Symfony\\Component\\Config\\Definition\\EnumNode' => __DIR__ . '/..' . '/symfony/config/Definition/EnumNode.php',
        '_ContaoManager\\Symfony\\Component\\Config\\Definition\\Exception\\DuplicateKeyException' => __DIR__ . '/..' . '/symfony/config/Definition/Exception/DuplicateKeyException.php',
        '_ContaoManager\\Symfony\\Component\\Config\\Definition\\Exception\\Exception' => __DIR__ . '/..' . '/symfony/config/Definition/Exception/Exception.php',
        '_ContaoManager\\Symfony\\Component\\Config\\Definition\\Exception\\ForbiddenOverwriteException' => __DIR__ . '/..' . '/symfony/config/Definition/Exception/ForbiddenOverwriteException.php',
        '_ContaoManager\\Symfony\\Component\\Config\\Definition\\Exception\\InvalidConfigurationException' => __DIR__ . '/..' . '/symfony/config/Definition/Exception/InvalidConfigurationException.php',
        '_ContaoManager\\Symfony\\Component\\Config\\Definition\\Exception\\InvalidDefinitionException' => __DIR__ . '/..' . '/symfony/config/Definition/Exception/InvalidDefinitionException.php',
        '_ContaoManager\\Symfony\\Component\\Config\\Definition\\Exception\\InvalidTypeException' => __DIR__ . '/..' . '/symfony/config/Definition/Exception/InvalidTypeException.php',
        '_ContaoManager\\Symfony\\Component\\Config\\Definition\\Exception\\UnsetKeyException' => __DIR__ . '/..' . '/symfony/config/Definition/Exception/UnsetKeyException.php',
        '_ContaoManager\\Symfony\\Component\\Config\\Definition\\FloatNode' => __DIR__ . '/..' . '/symfony/config/Definition/FloatNode.php',
        '_ContaoManager\\Symfony\\Component\\Config\\Definition\\IntegerNode' => __DIR__ . '/..' . '/symfony/config/Definition/IntegerNode.php',
        '_ContaoManager\\Symfony\\Component\\Config\\Definition\\Loader\\DefinitionFileLoader' => __DIR__ . '/..' . '/symfony/config/Definition/Loader/DefinitionFileLoader.php',
        '_ContaoManager\\Symfony\\Component\\Config\\Definition\\NodeInterface' => __DIR__ . '/..' . '/symfony/config/Definition/NodeInterface.php',
        '_ContaoManager\\Symfony\\Component\\Config\\Definition\\NumericNode' => __DIR__ . '/..' . '/symfony/config/Definition/NumericNode.php',
        '_ContaoManager\\Symfony\\Component\\Config\\Definition\\Processor' => __DIR__ . '/..' . '/symfony/config/Definition/Processor.php',
        '_ContaoManager\\Symfony\\Component\\Config\\Definition\\PrototypeNodeInterface' => __DIR__ . '/..' . '/symfony/config/Definition/PrototypeNodeInterface.php',
        '_ContaoManager\\Symfony\\Component\\Config\\Definition\\PrototypedArrayNode' => __DIR__ . '/..' . '/symfony/config/Definition/PrototypedArrayNode.php',
        '_ContaoManager\\Symfony\\Component\\Config\\Definition\\ScalarNode' => __DIR__ . '/..' . '/symfony/config/Definition/ScalarNode.php',
        '_ContaoManager\\Symfony\\Component\\Config\\Definition\\VariableNode' => __DIR__ . '/..' . '/symfony/config/Definition/VariableNode.php',
        '_ContaoManager\\Symfony\\Component\\Config\\Exception\\FileLoaderImportCircularReferenceException' => __DIR__ . '/..' . '/symfony/config/Exception/FileLoaderImportCircularReferenceException.php',
        '_ContaoManager\\Symfony\\Component\\Config\\Exception\\FileLocatorFileNotFoundException' => __DIR__ . '/..' . '/symfony/config/Exception/FileLocatorFileNotFoundException.php',
        '_ContaoManager\\Symfony\\Component\\Config\\Exception\\LoaderLoadException' => __DIR__ . '/..' . '/symfony/config/Exception/LoaderLoadException.php',
        '_ContaoManager\\Symfony\\Component\\Config\\FileLocator' => __DIR__ . '/..' . '/symfony/config/FileLocator.php',
        '_ContaoManager\\Symfony\\Component\\Config\\FileLocatorInterface' => __DIR__ . '/..' . '/symfony/config/FileLocatorInterface.php',
        '_ContaoManager\\Symfony\\Component\\Config\\Loader\\DelegatingLoader' => __DIR__ . '/..' . '/symfony/config/Loader/DelegatingLoader.php',
        '_ContaoManager\\Symfony\\Component\\Config\\Loader\\DirectoryAwareLoaderInterface' => __DIR__ . '/..' . '/symfony/config/Loader/DirectoryAwareLoaderInterface.php',
        '_ContaoManager\\Symfony\\Component\\Config\\Loader\\FileLoader' => __DIR__ . '/..' . '/symfony/config/Loader/FileLoader.php',
        '_ContaoManager\\Symfony\\Component\\Config\\Loader\\GlobFileLoader' => __DIR__ . '/..' . '/symfony/config/Loader/GlobFileLoader.php',
        '_ContaoManager\\Symfony\\Component\\Config\\Loader\\Loader' => __DIR__ . '/..' . '/symfony/config/Loader/Loader.php',
        '_ContaoManager\\Symfony\\Component\\Config\\Loader\\LoaderInterface' => __DIR__ . '/..' . '/symfony/config/Loader/LoaderInterface.php',
        '_ContaoManager\\Symfony\\Component\\Config\\Loader\\LoaderResolver' => __DIR__ . '/..' . '/symfony/config/Loader/LoaderResolver.php',
        '_ContaoManager\\Symfony\\Component\\Config\\Loader\\LoaderResolverInterface' => __DIR__ . '/..' . '/symfony/config/Loader/LoaderResolverInterface.php',
        '_ContaoManager\\Symfony\\Component\\Config\\Loader\\ParamConfigurator' => __DIR__ . '/..' . '/symfony/config/Loader/ParamConfigurator.php',
        '_ContaoManager\\Symfony\\Component\\Config\\ResourceCheckerConfigCache' => __DIR__ . '/..' . '/symfony/config/ResourceCheckerConfigCache.php',
        '_ContaoManager\\Symfony\\Component\\Config\\ResourceCheckerConfigCacheFactory' => __DIR__ . '/..' . '/symfony/config/ResourceCheckerConfigCacheFactory.php',
        '_ContaoManager\\Symfony\\Component\\Config\\ResourceCheckerInterface' => __DIR__ . '/..' . '/symfony/config/ResourceCheckerInterface.php',
        '_ContaoManager\\Symfony\\Component\\Config\\Resource\\ClassExistenceResource' => __DIR__ . '/..' . '/symfony/config/Resource/ClassExistenceResource.php',
        '_ContaoManager\\Symfony\\Component\\Config\\Resource\\ComposerResource' => __DIR__ . '/..' . '/symfony/config/Resource/ComposerResource.php',
        '_ContaoManager\\Symfony\\Component\\Config\\Resource\\DirectoryResource' => __DIR__ . '/..' . '/symfony/config/Resource/DirectoryResource.php',
        '_ContaoManager\\Symfony\\Component\\Config\\Resource\\FileExistenceResource' => __DIR__ . '/..' . '/symfony/config/Resource/FileExistenceResource.php',
        '_ContaoManager\\Symfony\\Component\\Config\\Resource\\FileResource' => __DIR__ . '/..' . '/symfony/config/Resource/FileResource.php',
        '_ContaoManager\\Symfony\\Component\\Config\\Resource\\GlobResource' => __DIR__ . '/..' . '/symfony/config/Resource/GlobResource.php',
        '_ContaoManager\\Symfony\\Component\\Config\\Resource\\ReflectionClassResource' => __DIR__ . '/..' . '/symfony/config/Resource/ReflectionClassResource.php',
        '_ContaoManager\\Symfony\\Component\\Config\\Resource\\ResourceInterface' => __DIR__ . '/..' . '/symfony/config/Resource/ResourceInterface.php',
        '_ContaoManager\\Symfony\\Component\\Config\\Resource\\SelfCheckingResourceChecker' => __DIR__ . '/..' . '/symfony/config/Resource/SelfCheckingResourceChecker.php',
        '_ContaoManager\\Symfony\\Component\\Config\\Resource\\SelfCheckingResourceInterface' => __DIR__ . '/..' . '/symfony/config/Resource/SelfCheckingResourceInterface.php',
        '_ContaoManager\\Symfony\\Component\\Config\\Util\\Exception\\InvalidXmlException' => __DIR__ . '/..' . '/symfony/config/Util/Exception/InvalidXmlException.php',
        '_ContaoManager\\Symfony\\Component\\Config\\Util\\Exception\\XmlParsingException' => __DIR__ . '/..' . '/symfony/config/Util/Exception/XmlParsingException.php',
        '_ContaoManager\\Symfony\\Component\\Config\\Util\\XmlUtils' => __DIR__ . '/..' . '/symfony/config/Util/XmlUtils.php',
        '_ContaoManager\\Symfony\\Component\\Console\\Application' => __DIR__ . '/..' . '/symfony/console/Application.php',
        '_ContaoManager\\Symfony\\Component\\Console\\Attribute\\AsCommand' => __DIR__ . '/..' . '/symfony/console/Attribute/AsCommand.php',
        '_ContaoManager\\Symfony\\Component\\Console\\CI\\GithubActionReporter' => __DIR__ . '/..' . '/symfony/console/CI/GithubActionReporter.php',
        '_ContaoManager\\Symfony\\Component\\Console\\Color' => __DIR__ . '/..' . '/symfony/console/Color.php',
        '_ContaoManager\\Symfony\\Component\\Console\\CommandLoader\\CommandLoaderInterface' => __DIR__ . '/..' . '/symfony/console/CommandLoader/CommandLoaderInterface.php',
        '_ContaoManager\\Symfony\\Component\\Console\\CommandLoader\\ContainerCommandLoader' => __DIR__ . '/..' . '/symfony/console/CommandLoader/ContainerCommandLoader.php',
        '_ContaoManager\\Symfony\\Component\\Console\\CommandLoader\\FactoryCommandLoader' => __DIR__ . '/..' . '/symfony/console/CommandLoader/FactoryCommandLoader.php',
        '_ContaoManager\\Symfony\\Component\\Console\\Command\\Command' => __DIR__ . '/..' . '/symfony/console/Command/Command.php',
        '_ContaoManager\\Symfony\\Component\\Console\\Command\\CompleteCommand' => __DIR__ . '/..' . '/symfony/console/Command/CompleteCommand.php',
        '_ContaoManager\\Symfony\\Component\\Console\\Command\\DumpCompletionCommand' => __DIR__ . '/..' . '/symfony/console/Command/DumpCompletionCommand.php',
        '_ContaoManager\\Symfony\\Component\\Console\\Command\\HelpCommand' => __DIR__ . '/..' . '/symfony/console/Command/HelpCommand.php',
        '_ContaoManager\\Symfony\\Component\\Console\\Command\\LazyCommand' => __DIR__ . '/..' . '/symfony/console/Command/LazyCommand.php',
        '_ContaoManager\\Symfony\\Component\\Console\\Command\\ListCommand' => __DIR__ . '/..' . '/symfony/console/Command/ListCommand.php',
        '_ContaoManager\\Symfony\\Component\\Console\\Command\\LockableTrait' => __DIR__ . '/..' . '/symfony/console/Command/LockableTrait.php',
        '_ContaoManager\\Symfony\\Component\\Console\\Command\\SignalableCommandInterface' => __DIR__ . '/..' . '/symfony/console/Command/SignalableCommandInterface.php',
        '_ContaoManager\\Symfony\\Component\\Console\\Command\\TraceableCommand' => __DIR__ . '/..' . '/symfony/console/Command/TraceableCommand.php',
        '_ContaoManager\\Symfony\\Component\\Console\\Completion\\CompletionInput' => __DIR__ . '/..' . '/symfony/console/Completion/CompletionInput.php',
        '_ContaoManager\\Symfony\\Component\\Console\\Completion\\CompletionSuggestions' => __DIR__ . '/..' . '/symfony/console/Completion/CompletionSuggestions.php',
        '_ContaoManager\\Symfony\\Component\\Console\\Completion\\Output\\BashCompletionOutput' => __DIR__ . '/..' . '/symfony/console/Completion/Output/BashCompletionOutput.php',
        '_ContaoManager\\Symfony\\Component\\Console\\Completion\\Output\\CompletionOutputInterface' => __DIR__ . '/..' . '/symfony/console/Completion/Output/CompletionOutputInterface.php',
        '_ContaoManager\\Symfony\\Component\\Console\\Completion\\Output\\FishCompletionOutput' => __DIR__ . '/..' . '/symfony/console/Completion/Output/FishCompletionOutput.php',
        '_ContaoManager\\Symfony\\Component\\Console\\Completion\\Output\\ZshCompletionOutput' => __DIR__ . '/..' . '/symfony/console/Completion/Output/ZshCompletionOutput.php',
        '_ContaoManager\\Symfony\\Component\\Console\\Completion\\Suggestion' => __DIR__ . '/..' . '/symfony/console/Completion/Suggestion.php',
        '_ContaoManager\\Symfony\\Component\\Console\\ConsoleEvents' => __DIR__ . '/..' . '/symfony/console/ConsoleEvents.php',
        '_ContaoManager\\Symfony\\Component\\Console\\Cursor' => __DIR__ . '/..' . '/symfony/console/Cursor.php',
        '_ContaoManager\\Symfony\\Component\\Console\\DataCollector\\CommandDataCollector' => __DIR__ . '/..' . '/symfony/console/DataCollector/CommandDataCollector.php',
        '_ContaoManager\\Symfony\\Component\\Console\\Debug\\CliRequest' => __DIR__ . '/..' . '/symfony/console/Debug/CliRequest.php',
        '_ContaoManager\\Symfony\\Component\\Console\\DependencyInjection\\AddConsoleCommandPass' => __DIR__ . '/..' . '/symfony/console/DependencyInjection/AddConsoleCommandPass.php',
        '_ContaoManager\\Symfony\\Component\\Console\\Descriptor\\ApplicationDescription' => __DIR__ . '/..' . '/symfony/console/Descriptor/ApplicationDescription.php',
        '_ContaoManager\\Symfony\\Component\\Console\\Descriptor\\Descriptor' => __DIR__ . '/..' . '/symfony/console/Descriptor/Descriptor.php',
        '_ContaoManager\\Symfony\\Component\\Console\\Descriptor\\DescriptorInterface' => __DIR__ . '/..' . '/symfony/console/Descriptor/DescriptorInterface.php',
        '_ContaoManager\\Symfony\\Component\\Console\\Descriptor\\JsonDescriptor' => __DIR__ . '/..' . '/symfony/console/Descriptor/JsonDescriptor.php',
        '_ContaoManager\\Symfony\\Component\\Console\\Descriptor\\MarkdownDescriptor' => __DIR__ . '/..' . '/symfony/console/Descriptor/MarkdownDescriptor.php',
        '_ContaoManager\\Symfony\\Component\\Console\\Descriptor\\ReStructuredTextDescriptor' => __DIR__ . '/..' . '/symfony/console/Descriptor/ReStructuredTextDescriptor.php',
        '_ContaoManager\\Symfony\\Component\\Console\\Descriptor\\TextDescriptor' => __DIR__ . '/..' . '/symfony/console/Descriptor/TextDescriptor.php',
        '_ContaoManager\\Symfony\\Component\\Console\\Descriptor\\XmlDescriptor' => __DIR__ . '/..' . '/symfony/console/Descriptor/XmlDescriptor.php',
        '_ContaoManager\\Symfony\\Component\\Console\\EventListener\\ErrorListener' => __DIR__ . '/..' . '/symfony/console/EventListener/ErrorListener.php',
        '_ContaoManager\\Symfony\\Component\\Console\\Event\\ConsoleCommandEvent' => __DIR__ . '/..' . '/symfony/console/Event/ConsoleCommandEvent.php',
        '_ContaoManager\\Symfony\\Component\\Console\\Event\\ConsoleErrorEvent' => __DIR__ . '/..' . '/symfony/console/Event/ConsoleErrorEvent.php',
        '_ContaoManager\\Symfony\\Component\\Console\\Event\\ConsoleEvent' => __DIR__ . '/..' . '/symfony/console/Event/ConsoleEvent.php',
        '_ContaoManager\\Symfony\\Component\\Console\\Event\\ConsoleSignalEvent' => __DIR__ . '/..' . '/symfony/console/Event/ConsoleSignalEvent.php',
        '_ContaoManager\\Symfony\\Component\\Console\\Event\\ConsoleTerminateEvent' => __DIR__ . '/..' . '/symfony/console/Event/ConsoleTerminateEvent.php',
        '_ContaoManager\\Symfony\\Component\\Console\\Exception\\CommandNotFoundException' => __DIR__ . '/..' . '/symfony/console/Exception/CommandNotFoundException.php',
        '_ContaoManager\\Symfony\\Component\\Console\\Exception\\ExceptionInterface' => __DIR__ . '/..' . '/symfony/console/Exception/ExceptionInterface.php',
        '_ContaoManager\\Symfony\\Component\\Console\\Exception\\InvalidArgumentException' => __DIR__ . '/..' . '/symfony/console/Exception/InvalidArgumentException.php',
        '_ContaoManager\\Symfony\\Component\\Console\\Exception\\InvalidOptionException' => __DIR__ . '/..' . '/symfony/console/Exception/InvalidOptionException.php',
        '_ContaoManager\\Symfony\\Component\\Console\\Exception\\LogicException' => __DIR__ . '/..' . '/symfony/console/Exception/LogicException.php',
        '_ContaoManager\\Symfony\\Component\\Console\\Exception\\MissingInputException' => __DIR__ . '/..' . '/symfony/console/Exception/MissingInputException.php',
        '_ContaoManager\\Symfony\\Component\\Console\\Exception\\NamespaceNotFoundException' => __DIR__ . '/..' . '/symfony/console/Exception/NamespaceNotFoundException.php',
        '_ContaoManager\\Symfony\\Component\\Console\\Exception\\RunCommandFailedException' => __DIR__ . '/..' . '/symfony/console/Exception/RunCommandFailedException.php',
        '_ContaoManager\\Symfony\\Component\\Console\\Exception\\RuntimeException' => __DIR__ . '/..' . '/symfony/console/Exception/RuntimeException.php',
        '_ContaoManager\\Symfony\\Component\\Console\\Formatter\\NullOutputFormatter' => __DIR__ . '/..' . '/symfony/console/Formatter/NullOutputFormatter.php',
        '_ContaoManager\\Symfony\\Component\\Console\\Formatter\\NullOutputFormatterStyle' => __DIR__ . '/..' . '/symfony/console/Formatter/NullOutputFormatterStyle.php',
        '_ContaoManager\\Symfony\\Component\\Console\\Formatter\\OutputFormatter' => __DIR__ . '/..' . '/symfony/console/Formatter/OutputFormatter.php',
        '_ContaoManager\\Symfony\\Component\\Console\\Formatter\\OutputFormatterInterface' => __DIR__ . '/..' . '/symfony/console/Formatter/OutputFormatterInterface.php',
        '_ContaoManager\\Symfony\\Component\\Console\\Formatter\\OutputFormatterStyle' => __DIR__ . '/..' . '/symfony/console/Formatter/OutputFormatterStyle.php',
        '_ContaoManager\\Symfony\\Component\\Console\\Formatter\\OutputFormatterStyleInterface' => __DIR__ . '/..' . '/symfony/console/Formatter/OutputFormatterStyleInterface.php',
        '_ContaoManager\\Symfony\\Component\\Console\\Formatter\\OutputFormatterStyleStack' => __DIR__ . '/..' . '/symfony/console/Formatter/OutputFormatterStyleStack.php',
        '_ContaoManager\\Symfony\\Component\\Console\\Formatter\\WrappableOutputFormatterInterface' => __DIR__ . '/..' . '/symfony/console/Formatter/WrappableOutputFormatterInterface.php',
        '_ContaoManager\\Symfony\\Component\\Console\\Helper\\DebugFormatterHelper' => __DIR__ . '/..' . '/symfony/console/Helper/DebugFormatterHelper.php',
        '_ContaoManager\\Symfony\\Component\\Console\\Helper\\DescriptorHelper' => __DIR__ . '/..' . '/symfony/console/Helper/DescriptorHelper.php',
        '_ContaoManager\\Symfony\\Component\\Console\\Helper\\Dumper' => __DIR__ . '/..' . '/symfony/console/Helper/Dumper.php',
        '_ContaoManager\\Symfony\\Component\\Console\\Helper\\FormatterHelper' => __DIR__ . '/..' . '/symfony/console/Helper/FormatterHelper.php',
        '_ContaoManager\\Symfony\\Component\\Console\\Helper\\Helper' => __DIR__ . '/..' . '/symfony/console/Helper/Helper.php',
        '_ContaoManager\\Symfony\\Component\\Console\\Helper\\HelperInterface' => __DIR__ . '/..' . '/symfony/console/Helper/HelperInterface.php',
        '_ContaoManager\\Symfony\\Component\\Console\\Helper\\HelperSet' => __DIR__ . '/..' . '/symfony/console/Helper/HelperSet.php',
        '_ContaoManager\\Symfony\\Component\\Console\\Helper\\InputAwareHelper' => __DIR__ . '/..' . '/symfony/console/Helper/InputAwareHelper.php',
        '_ContaoManager\\Symfony\\Component\\Console\\Helper\\OutputWrapper' => __DIR__ . '/..' . '/symfony/console/Helper/OutputWrapper.php',
        '_ContaoManager\\Symfony\\Component\\Console\\Helper\\ProcessHelper' => __DIR__ . '/..' . '/symfony/console/Helper/ProcessHelper.php',
        '_ContaoManager\\Symfony\\Component\\Console\\Helper\\ProgressBar' => __DIR__ . '/..' . '/symfony/console/Helper/ProgressBar.php',
        '_ContaoManager\\Symfony\\Component\\Console\\Helper\\ProgressIndicator' => __DIR__ . '/..' . '/symfony/console/Helper/ProgressIndicator.php',
        '_ContaoManager\\Symfony\\Component\\Console\\Helper\\QuestionHelper' => __DIR__ . '/..' . '/symfony/console/Helper/QuestionHelper.php',
        '_ContaoManager\\Symfony\\Component\\Console\\Helper\\SymfonyQuestionHelper' => __DIR__ . '/..' . '/symfony/console/Helper/SymfonyQuestionHelper.php',
        '_ContaoManager\\Symfony\\Component\\Console\\Helper\\Table' => __DIR__ . '/..' . '/symfony/console/Helper/Table.php',
        '_ContaoManager\\Symfony\\Component\\Console\\Helper\\TableCell' => __DIR__ . '/..' . '/symfony/console/Helper/TableCell.php',
        '_ContaoManager\\Symfony\\Component\\Console\\Helper\\TableCellStyle' => __DIR__ . '/..' . '/symfony/console/Helper/TableCellStyle.php',
        '_ContaoManager\\Symfony\\Component\\Console\\Helper\\TableRows' => __DIR__ . '/..' . '/symfony/console/Helper/TableRows.php',
        '_ContaoManager\\Symfony\\Component\\Console\\Helper\\TableSeparator' => __DIR__ . '/..' . '/symfony/console/Helper/TableSeparator.php',
        '_ContaoManager\\Symfony\\Component\\Console\\Helper\\TableStyle' => __DIR__ . '/..' . '/symfony/console/Helper/TableStyle.php',
        '_ContaoManager\\Symfony\\Component\\Console\\Helper\\TerminalInputHelper' => __DIR__ . '/..' . '/symfony/console/Helper/TerminalInputHelper.php',
        '_ContaoManager\\Symfony\\Component\\Console\\Input\\ArgvInput' => __DIR__ . '/..' . '/symfony/console/Input/ArgvInput.php',
        '_ContaoManager\\Symfony\\Component\\Console\\Input\\ArrayInput' => __DIR__ . '/..' . '/symfony/console/Input/ArrayInput.php',
        '_ContaoManager\\Symfony\\Component\\Console\\Input\\Input' => __DIR__ . '/..' . '/symfony/console/Input/Input.php',
        '_ContaoManager\\Symfony\\Component\\Console\\Input\\InputArgument' => __DIR__ . '/..' . '/symfony/console/Input/InputArgument.php',
        '_ContaoManager\\Symfony\\Component\\Console\\Input\\InputAwareInterface' => __DIR__ . '/..' . '/symfony/console/Input/InputAwareInterface.php',
        '_ContaoManager\\Symfony\\Component\\Console\\Input\\InputDefinition' => __DIR__ . '/..' . '/symfony/console/Input/InputDefinition.php',
        '_ContaoManager\\Symfony\\Component\\Console\\Input\\InputInterface' => __DIR__ . '/..' . '/symfony/console/Input/InputInterface.php',
        '_ContaoManager\\Symfony\\Component\\Console\\Input\\InputOption' => __DIR__ . '/..' . '/symfony/console/Input/InputOption.php',
        '_ContaoManager\\Symfony\\Component\\Console\\Input\\StreamableInputInterface' => __DIR__ . '/..' . '/symfony/console/Input/StreamableInputInterface.php',
        '_ContaoManager\\Symfony\\Component\\Console\\Input\\StringInput' => __DIR__ . '/..' . '/symfony/console/Input/StringInput.php',
        '_ContaoManager\\Symfony\\Component\\Console\\Logger\\ConsoleLogger' => __DIR__ . '/..' . '/symfony/console/Logger/ConsoleLogger.php',
        '_ContaoManager\\Symfony\\Component\\Console\\Messenger\\RunCommandContext' => __DIR__ . '/..' . '/symfony/console/Messenger/RunCommandContext.php',
        '_ContaoManager\\Symfony\\Component\\Console\\Messenger\\RunCommandMessage' => __DIR__ . '/..' . '/symfony/console/Messenger/RunCommandMessage.php',
        '_ContaoManager\\Symfony\\Component\\Console\\Messenger\\RunCommandMessageHandler' => __DIR__ . '/..' . '/symfony/console/Messenger/RunCommandMessageHandler.php',
        '_ContaoManager\\Symfony\\Component\\Console\\Output\\AnsiColorMode' => __DIR__ . '/..' . '/symfony/console/Output/AnsiColorMode.php',
        '_ContaoManager\\Symfony\\Component\\Console\\Output\\BufferedOutput' => __DIR__ . '/..' . '/symfony/console/Output/BufferedOutput.php',
        '_ContaoManager\\Symfony\\Component\\Console\\Output\\ConsoleOutput' => __DIR__ . '/..' . '/symfony/console/Output/ConsoleOutput.php',
        '_ContaoManager\\Symfony\\Component\\Console\\Output\\ConsoleOutputInterface' => __DIR__ . '/..' . '/symfony/console/Output/ConsoleOutputInterface.php',
        '_ContaoManager\\Symfony\\Component\\Console\\Output\\ConsoleSectionOutput' => __DIR__ . '/..' . '/symfony/console/Output/ConsoleSectionOutput.php',
        '_ContaoManager\\Symfony\\Component\\Console\\Output\\NullOutput' => __DIR__ . '/..' . '/symfony/console/Output/NullOutput.php',
        '_ContaoManager\\Symfony\\Component\\Console\\Output\\Output' => __DIR__ . '/..' . '/symfony/console/Output/Output.php',
        '_ContaoManager\\Symfony\\Component\\Console\\Output\\OutputInterface' => __DIR__ . '/..' . '/symfony/console/Output/OutputInterface.php',
        '_ContaoManager\\Symfony\\Component\\Console\\Output\\StreamOutput' => __DIR__ . '/..' . '/symfony/console/Output/StreamOutput.php',
        '_ContaoManager\\Symfony\\Component\\Console\\Output\\TrimmedBufferOutput' => __DIR__ . '/..' . '/symfony/console/Output/TrimmedBufferOutput.php',
        '_ContaoManager\\Symfony\\Component\\Console\\Question\\ChoiceQuestion' => __DIR__ . '/..' . '/symfony/console/Question/ChoiceQuestion.php',
        '_ContaoManager\\Symfony\\Component\\Console\\Question\\ConfirmationQuestion' => __DIR__ . '/..' . '/symfony/console/Question/ConfirmationQuestion.php',
        '_ContaoManager\\Symfony\\Component\\Console\\Question\\Question' => __DIR__ . '/..' . '/symfony/console/Question/Question.php',
        '_ContaoManager\\Symfony\\Component\\Console\\SignalRegistry\\SignalMap' => __DIR__ . '/..' . '/symfony/console/SignalRegistry/SignalMap.php',
        '_ContaoManager\\Symfony\\Component\\Console\\SignalRegistry\\SignalRegistry' => __DIR__ . '/..' . '/symfony/console/SignalRegistry/SignalRegistry.php',
        '_ContaoManager\\Symfony\\Component\\Console\\SingleCommandApplication' => __DIR__ . '/..' . '/symfony/console/SingleCommandApplication.php',
        '_ContaoManager\\Symfony\\Component\\Console\\Style\\OutputStyle' => __DIR__ . '/..' . '/symfony/console/Style/OutputStyle.php',
        '_ContaoManager\\Symfony\\Component\\Console\\Style\\StyleInterface' => __DIR__ . '/..' . '/symfony/console/Style/StyleInterface.php',
        '_ContaoManager\\Symfony\\Component\\Console\\Style\\SymfonyStyle' => __DIR__ . '/..' . '/symfony/console/Style/SymfonyStyle.php',
        '_ContaoManager\\Symfony\\Component\\Console\\Terminal' => __DIR__ . '/..' . '/symfony/console/Terminal.php',
        '_ContaoManager\\Symfony\\Component\\Console\\Tester\\ApplicationTester' => __DIR__ . '/..' . '/symfony/console/Tester/ApplicationTester.php',
        '_ContaoManager\\Symfony\\Component\\Console\\Tester\\CommandCompletionTester' => __DIR__ . '/..' . '/symfony/console/Tester/CommandCompletionTester.php',
        '_ContaoManager\\Symfony\\Component\\Console\\Tester\\CommandTester' => __DIR__ . '/..' . '/symfony/console/Tester/CommandTester.php',
        '_ContaoManager\\Symfony\\Component\\Console\\Tester\\Constraint\\CommandIsSuccessful' => __DIR__ . '/..' . '/symfony/console/Tester/Constraint/CommandIsSuccessful.php',
        '_ContaoManager\\Symfony\\Component\\Console\\Tester\\TesterTrait' => __DIR__ . '/..' . '/symfony/console/Tester/TesterTrait.php',
        '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Alias' => __DIR__ . '/..' . '/symfony/dependency-injection/Alias.php',
        '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Argument\\AbstractArgument' => __DIR__ . '/..' . '/symfony/dependency-injection/Argument/AbstractArgument.php',
        '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Argument\\ArgumentInterface' => __DIR__ . '/..' . '/symfony/dependency-injection/Argument/ArgumentInterface.php',
        '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Argument\\BoundArgument' => __DIR__ . '/..' . '/symfony/dependency-injection/Argument/BoundArgument.php',
        '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Argument\\IteratorArgument' => __DIR__ . '/..' . '/symfony/dependency-injection/Argument/IteratorArgument.php',
        '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Argument\\LazyClosure' => __DIR__ . '/..' . '/symfony/dependency-injection/Argument/LazyClosure.php',
        '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Argument\\ReferenceSetArgumentTrait' => __DIR__ . '/..' . '/symfony/dependency-injection/Argument/ReferenceSetArgumentTrait.php',
        '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Argument\\RewindableGenerator' => __DIR__ . '/..' . '/symfony/dependency-injection/Argument/RewindableGenerator.php',
        '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Argument\\ServiceClosureArgument' => __DIR__ . '/..' . '/symfony/dependency-injection/Argument/ServiceClosureArgument.php',
        '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Argument\\ServiceLocator' => __DIR__ . '/..' . '/symfony/dependency-injection/Argument/ServiceLocator.php',
        '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Argument\\ServiceLocatorArgument' => __DIR__ . '/..' . '/symfony/dependency-injection/Argument/ServiceLocatorArgument.php',
        '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Argument\\TaggedIteratorArgument' => __DIR__ . '/..' . '/symfony/dependency-injection/Argument/TaggedIteratorArgument.php',
        '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Attribute\\AsAlias' => __DIR__ . '/..' . '/symfony/dependency-injection/Attribute/AsAlias.php',
        '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Attribute\\AsDecorator' => __DIR__ . '/..' . '/symfony/dependency-injection/Attribute/AsDecorator.php',
        '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Attribute\\AsTaggedItem' => __DIR__ . '/..' . '/symfony/dependency-injection/Attribute/AsTaggedItem.php',
        '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Attribute\\Autoconfigure' => __DIR__ . '/..' . '/symfony/dependency-injection/Attribute/Autoconfigure.php',
        '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Attribute\\AutoconfigureTag' => __DIR__ . '/..' . '/symfony/dependency-injection/Attribute/AutoconfigureTag.php',
        '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Attribute\\Autowire' => __DIR__ . '/..' . '/symfony/dependency-injection/Attribute/Autowire.php',
        '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Attribute\\AutowireCallable' => __DIR__ . '/..' . '/symfony/dependency-injection/Attribute/AutowireCallable.php',
        '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Attribute\\AutowireDecorated' => __DIR__ . '/..' . '/symfony/dependency-injection/Attribute/AutowireDecorated.php',
        '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Attribute\\AutowireIterator' => __DIR__ . '/..' . '/symfony/dependency-injection/Attribute/AutowireIterator.php',
        '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Attribute\\AutowireLocator' => __DIR__ . '/..' . '/symfony/dependency-injection/Attribute/AutowireLocator.php',
        '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Attribute\\AutowireServiceClosure' => __DIR__ . '/..' . '/symfony/dependency-injection/Attribute/AutowireServiceClosure.php',
        '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Attribute\\Exclude' => __DIR__ . '/..' . '/symfony/dependency-injection/Attribute/Exclude.php',
        '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Attribute\\MapDecorated' => __DIR__ . '/..' . '/symfony/dependency-injection/Attribute/MapDecorated.php',
        '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Attribute\\TaggedIterator' => __DIR__ . '/..' . '/symfony/dependency-injection/Attribute/TaggedIterator.php',
        '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Attribute\\TaggedLocator' => __DIR__ . '/..' . '/symfony/dependency-injection/Attribute/TaggedLocator.php',
        '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Attribute\\Target' => __DIR__ . '/..' . '/symfony/dependency-injection/Attribute/Target.php',
        '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Attribute\\When' => __DIR__ . '/..' . '/symfony/dependency-injection/Attribute/When.php',
        '_ContaoManager\\Symfony\\Component\\DependencyInjection\\ChildDefinition' => __DIR__ . '/..' . '/symfony/dependency-injection/ChildDefinition.php',
        '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Compiler\\AbstractRecursivePass' => __DIR__ . '/..' . '/symfony/dependency-injection/Compiler/AbstractRecursivePass.php',
        '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Compiler\\AliasDeprecatedPublicServicesPass' => __DIR__ . '/..' . '/symfony/dependency-injection/Compiler/AliasDeprecatedPublicServicesPass.php',
        '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Compiler\\AnalyzeServiceReferencesPass' => __DIR__ . '/..' . '/symfony/dependency-injection/Compiler/AnalyzeServiceReferencesPass.php',
        '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Compiler\\AttributeAutoconfigurationPass' => __DIR__ . '/..' . '/symfony/dependency-injection/Compiler/AttributeAutoconfigurationPass.php',
        '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Compiler\\AutoAliasServicePass' => __DIR__ . '/..' . '/symfony/dependency-injection/Compiler/AutoAliasServicePass.php',
        '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Compiler\\AutowireAsDecoratorPass' => __DIR__ . '/..' . '/symfony/dependency-injection/Compiler/AutowireAsDecoratorPass.php',
        '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Compiler\\AutowirePass' => __DIR__ . '/..' . '/symfony/dependency-injection/Compiler/AutowirePass.php',
        '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Compiler\\AutowireRequiredMethodsPass' => __DIR__ . '/..' . '/symfony/dependency-injection/Compiler/AutowireRequiredMethodsPass.php',
        '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Compiler\\AutowireRequiredPropertiesPass' => __DIR__ . '/..' . '/symfony/dependency-injection/Compiler/AutowireRequiredPropertiesPass.php',
        '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Compiler\\CheckArgumentsValidityPass' => __DIR__ . '/..' . '/symfony/dependency-injection/Compiler/CheckArgumentsValidityPass.php',
        '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Compiler\\CheckCircularReferencesPass' => __DIR__ . '/..' . '/symfony/dependency-injection/Compiler/CheckCircularReferencesPass.php',
        '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Compiler\\CheckDefinitionValidityPass' => __DIR__ . '/..' . '/symfony/dependency-injection/Compiler/CheckDefinitionValidityPass.php',
        '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Compiler\\CheckExceptionOnInvalidReferenceBehaviorPass' => __DIR__ . '/..' . '/symfony/dependency-injection/Compiler/CheckExceptionOnInvalidReferenceBehaviorPass.php',
        '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Compiler\\CheckReferenceValidityPass' => __DIR__ . '/..' . '/symfony/dependency-injection/Compiler/CheckReferenceValidityPass.php',
        '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Compiler\\CheckTypeDeclarationsPass' => __DIR__ . '/..' . '/symfony/dependency-injection/Compiler/CheckTypeDeclarationsPass.php',
        '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Compiler\\Compiler' => __DIR__ . '/..' . '/symfony/dependency-injection/Compiler/Compiler.php',
        '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Compiler\\CompilerPassInterface' => __DIR__ . '/..' . '/symfony/dependency-injection/Compiler/CompilerPassInterface.php',
        '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Compiler\\DecoratorServicePass' => __DIR__ . '/..' . '/symfony/dependency-injection/Compiler/DecoratorServicePass.php',
        '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Compiler\\DefinitionErrorExceptionPass' => __DIR__ . '/..' . '/symfony/dependency-injection/Compiler/DefinitionErrorExceptionPass.php',
        '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Compiler\\ExtensionCompilerPass' => __DIR__ . '/..' . '/symfony/dependency-injection/Compiler/ExtensionCompilerPass.php',
        '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Compiler\\InlineServiceDefinitionsPass' => __DIR__ . '/..' . '/symfony/dependency-injection/Compiler/InlineServiceDefinitionsPass.php',
        '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Compiler\\MergeExtensionConfigurationPass' => __DIR__ . '/..' . '/symfony/dependency-injection/Compiler/MergeExtensionConfigurationPass.php',
        '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Compiler\\PassConfig' => __DIR__ . '/..' . '/symfony/dependency-injection/Compiler/PassConfig.php',
        '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Compiler\\PriorityTaggedServiceTrait' => __DIR__ . '/..' . '/symfony/dependency-injection/Compiler/PriorityTaggedServiceTrait.php',
        '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Compiler\\RegisterAutoconfigureAttributesPass' => __DIR__ . '/..' . '/symfony/dependency-injection/Compiler/RegisterAutoconfigureAttributesPass.php',
        '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Compiler\\RegisterEnvVarProcessorsPass' => __DIR__ . '/..' . '/symfony/dependency-injection/Compiler/RegisterEnvVarProcessorsPass.php',
        '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Compiler\\RegisterReverseContainerPass' => __DIR__ . '/..' . '/symfony/dependency-injection/Compiler/RegisterReverseContainerPass.php',
        '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Compiler\\RegisterServiceSubscribersPass' => __DIR__ . '/..' . '/symfony/dependency-injection/Compiler/RegisterServiceSubscribersPass.php',
        '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Compiler\\RemoveAbstractDefinitionsPass' => __DIR__ . '/..' . '/symfony/dependency-injection/Compiler/RemoveAbstractDefinitionsPass.php',
        '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Compiler\\RemoveBuildParametersPass' => __DIR__ . '/..' . '/symfony/dependency-injection/Compiler/RemoveBuildParametersPass.php',
        '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Compiler\\RemovePrivateAliasesPass' => __DIR__ . '/..' . '/symfony/dependency-injection/Compiler/RemovePrivateAliasesPass.php',
        '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Compiler\\RemoveUnusedDefinitionsPass' => __DIR__ . '/..' . '/symfony/dependency-injection/Compiler/RemoveUnusedDefinitionsPass.php',
        '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Compiler\\ReplaceAliasByActualDefinitionPass' => __DIR__ . '/..' . '/symfony/dependency-injection/Compiler/ReplaceAliasByActualDefinitionPass.php',
        '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Compiler\\ResolveBindingsPass' => __DIR__ . '/..' . '/symfony/dependency-injection/Compiler/ResolveBindingsPass.php',
        '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Compiler\\ResolveChildDefinitionsPass' => __DIR__ . '/..' . '/symfony/dependency-injection/Compiler/ResolveChildDefinitionsPass.php',
        '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Compiler\\ResolveClassPass' => __DIR__ . '/..' . '/symfony/dependency-injection/Compiler/ResolveClassPass.php',
        '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Compiler\\ResolveDecoratorStackPass' => __DIR__ . '/..' . '/symfony/dependency-injection/Compiler/ResolveDecoratorStackPass.php',
        '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Compiler\\ResolveEnvPlaceholdersPass' => __DIR__ . '/..' . '/symfony/dependency-injection/Compiler/ResolveEnvPlaceholdersPass.php',
        '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Compiler\\ResolveFactoryClassPass' => __DIR__ . '/..' . '/symfony/dependency-injection/Compiler/ResolveFactoryClassPass.php',
        '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Compiler\\ResolveHotPathPass' => __DIR__ . '/..' . '/symfony/dependency-injection/Compiler/ResolveHotPathPass.php',
        '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Compiler\\ResolveInstanceofConditionalsPass' => __DIR__ . '/..' . '/symfony/dependency-injection/Compiler/ResolveInstanceofConditionalsPass.php',
        '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Compiler\\ResolveInvalidReferencesPass' => __DIR__ . '/..' . '/symfony/dependency-injection/Compiler/ResolveInvalidReferencesPass.php',
        '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Compiler\\ResolveNamedArgumentsPass' => __DIR__ . '/..' . '/symfony/dependency-injection/Compiler/ResolveNamedArgumentsPass.php',
        '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Compiler\\ResolveNoPreloadPass' => __DIR__ . '/..' . '/symfony/dependency-injection/Compiler/ResolveNoPreloadPass.php',
        '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Compiler\\ResolveParameterPlaceHoldersPass' => __DIR__ . '/..' . '/symfony/dependency-injection/Compiler/ResolveParameterPlaceHoldersPass.php',
        '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Compiler\\ResolveReferencesToAliasesPass' => __DIR__ . '/..' . '/symfony/dependency-injection/Compiler/ResolveReferencesToAliasesPass.php',
        '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Compiler\\ResolveServiceSubscribersPass' => __DIR__ . '/..' . '/symfony/dependency-injection/Compiler/ResolveServiceSubscribersPass.php',
        '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Compiler\\ResolveTaggedIteratorArgumentPass' => __DIR__ . '/..' . '/symfony/dependency-injection/Compiler/ResolveTaggedIteratorArgumentPass.php',
        '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Compiler\\ServiceLocatorTagPass' => __DIR__ . '/..' . '/symfony/dependency-injection/Compiler/ServiceLocatorTagPass.php',
        '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Compiler\\ServiceReferenceGraph' => __DIR__ . '/..' . '/symfony/dependency-injection/Compiler/ServiceReferenceGraph.php',
        '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Compiler\\ServiceReferenceGraphEdge' => __DIR__ . '/..' . '/symfony/dependency-injection/Compiler/ServiceReferenceGraphEdge.php',
        '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Compiler\\ServiceReferenceGraphNode' => __DIR__ . '/..' . '/symfony/dependency-injection/Compiler/ServiceReferenceGraphNode.php',
        '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Compiler\\ValidateEnvPlaceholdersPass' => __DIR__ . '/..' . '/symfony/dependency-injection/Compiler/ValidateEnvPlaceholdersPass.php',
        '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Config\\ContainerParametersResource' => __DIR__ . '/..' . '/symfony/dependency-injection/Config/ContainerParametersResource.php',
        '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Config\\ContainerParametersResourceChecker' => __DIR__ . '/..' . '/symfony/dependency-injection/Config/ContainerParametersResourceChecker.php',
        '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Container' => __DIR__ . '/..' . '/symfony/dependency-injection/Container.php',
        '_ContaoManager\\Symfony\\Component\\DependencyInjection\\ContainerAwareInterface' => __DIR__ . '/..' . '/symfony/dependency-injection/ContainerAwareInterface.php',
        '_ContaoManager\\Symfony\\Component\\DependencyInjection\\ContainerAwareTrait' => __DIR__ . '/..' . '/symfony/dependency-injection/ContainerAwareTrait.php',
        '_ContaoManager\\Symfony\\Component\\DependencyInjection\\ContainerBuilder' => __DIR__ . '/..' . '/symfony/dependency-injection/ContainerBuilder.php',
        '_ContaoManager\\Symfony\\Component\\DependencyInjection\\ContainerInterface' => __DIR__ . '/..' . '/symfony/dependency-injection/ContainerInterface.php',
        '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Definition' => __DIR__ . '/..' . '/symfony/dependency-injection/Definition.php',
        '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Dumper\\Dumper' => __DIR__ . '/..' . '/symfony/dependency-injection/Dumper/Dumper.php',
        '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Dumper\\DumperInterface' => __DIR__ . '/..' . '/symfony/dependency-injection/Dumper/DumperInterface.php',
        '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Dumper\\GraphvizDumper' => __DIR__ . '/..' . '/symfony/dependency-injection/Dumper/GraphvizDumper.php',
        '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Dumper\\PhpDumper' => __DIR__ . '/..' . '/symfony/dependency-injection/Dumper/PhpDumper.php',
        '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Dumper\\Preloader' => __DIR__ . '/..' . '/symfony/dependency-injection/Dumper/Preloader.php',
        '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Dumper\\XmlDumper' => __DIR__ . '/..' . '/symfony/dependency-injection/Dumper/XmlDumper.php',
        '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Dumper\\YamlDumper' => __DIR__ . '/..' . '/symfony/dependency-injection/Dumper/YamlDumper.php',
        '_ContaoManager\\Symfony\\Component\\DependencyInjection\\EnvVarLoaderInterface' => __DIR__ . '/..' . '/symfony/dependency-injection/EnvVarLoaderInterface.php',
        '_ContaoManager\\Symfony\\Component\\DependencyInjection\\EnvVarProcessor' => __DIR__ . '/..' . '/symfony/dependency-injection/EnvVarProcessor.php',
        '_ContaoManager\\Symfony\\Component\\DependencyInjection\\EnvVarProcessorInterface' => __DIR__ . '/..' . '/symfony/dependency-injection/EnvVarProcessorInterface.php',
        '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Exception\\AutowiringFailedException' => __DIR__ . '/..' . '/symfony/dependency-injection/Exception/AutowiringFailedException.php',
        '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Exception\\BadMethodCallException' => __DIR__ . '/..' . '/symfony/dependency-injection/Exception/BadMethodCallException.php',
        '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Exception\\EnvNotFoundException' => __DIR__ . '/..' . '/symfony/dependency-injection/Exception/EnvNotFoundException.php',
        '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Exception\\EnvParameterException' => __DIR__ . '/..' . '/symfony/dependency-injection/Exception/EnvParameterException.php',
        '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Exception\\ExceptionInterface' => __DIR__ . '/..' . '/symfony/dependency-injection/Exception/ExceptionInterface.php',
        '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Exception\\InvalidArgumentException' => __DIR__ . '/..' . '/symfony/dependency-injection/Exception/InvalidArgumentException.php',
        '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Exception\\InvalidParameterTypeException' => __DIR__ . '/..' . '/symfony/dependency-injection/Exception/InvalidParameterTypeException.php',
        '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Exception\\LogicException' => __DIR__ . '/..' . '/symfony/dependency-injection/Exception/LogicException.php',
        '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Exception\\OutOfBoundsException' => __DIR__ . '/..' . '/symfony/dependency-injection/Exception/OutOfBoundsException.php',
        '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Exception\\ParameterCircularReferenceException' => __DIR__ . '/..' . '/symfony/dependency-injection/Exception/ParameterCircularReferenceException.php',
        '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Exception\\ParameterNotFoundException' => __DIR__ . '/..' . '/symfony/dependency-injection/Exception/ParameterNotFoundException.php',
        '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Exception\\RuntimeException' => __DIR__ . '/..' . '/symfony/dependency-injection/Exception/RuntimeException.php',
        '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Exception\\ServiceCircularReferenceException' => __DIR__ . '/..' . '/symfony/dependency-injection/Exception/ServiceCircularReferenceException.php',
        '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Exception\\ServiceNotFoundException' => __DIR__ . '/..' . '/symfony/dependency-injection/Exception/ServiceNotFoundException.php',
        '_ContaoManager\\Symfony\\Component\\DependencyInjection\\ExpressionLanguage' => __DIR__ . '/..' . '/symfony/dependency-injection/ExpressionLanguage.php',
        '_ContaoManager\\Symfony\\Component\\DependencyInjection\\ExpressionLanguageProvider' => __DIR__ . '/..' . '/symfony/dependency-injection/ExpressionLanguageProvider.php',
        '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Extension\\AbstractExtension' => __DIR__ . '/..' . '/symfony/dependency-injection/Extension/AbstractExtension.php',
        '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Extension\\ConfigurableExtensionInterface' => __DIR__ . '/..' . '/symfony/dependency-injection/Extension/ConfigurableExtensionInterface.php',
        '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Extension\\ConfigurationExtensionInterface' => __DIR__ . '/..' . '/symfony/dependency-injection/Extension/ConfigurationExtensionInterface.php',
        '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Extension\\Extension' => __DIR__ . '/..' . '/symfony/dependency-injection/Extension/Extension.php',
        '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Extension\\ExtensionInterface' => __DIR__ . '/..' . '/symfony/dependency-injection/Extension/ExtensionInterface.php',
        '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Extension\\ExtensionTrait' => __DIR__ . '/..' . '/symfony/dependency-injection/Extension/ExtensionTrait.php',
        '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Extension\\PrependExtensionInterface' => __DIR__ . '/..' . '/symfony/dependency-injection/Extension/PrependExtensionInterface.php',
        '_ContaoManager\\Symfony\\Component\\DependencyInjection\\LazyProxy\\Instantiator\\InstantiatorInterface' => __DIR__ . '/..' . '/symfony/dependency-injection/LazyProxy/Instantiator/InstantiatorInterface.php',
        '_ContaoManager\\Symfony\\Component\\DependencyInjection\\LazyProxy\\Instantiator\\LazyServiceInstantiator' => __DIR__ . '/..' . '/symfony/dependency-injection/LazyProxy/Instantiator/LazyServiceInstantiator.php',
        '_ContaoManager\\Symfony\\Component\\DependencyInjection\\LazyProxy\\Instantiator\\RealServiceInstantiator' => __DIR__ . '/..' . '/symfony/dependency-injection/LazyProxy/Instantiator/RealServiceInstantiator.php',
        '_ContaoManager\\Symfony\\Component\\DependencyInjection\\LazyProxy\\PhpDumper\\DumperInterface' => __DIR__ . '/..' . '/symfony/dependency-injection/LazyProxy/PhpDumper/DumperInterface.php',
        '_ContaoManager\\Symfony\\Component\\DependencyInjection\\LazyProxy\\PhpDumper\\LazyServiceDumper' => __DIR__ . '/..' . '/symfony/dependency-injection/LazyProxy/PhpDumper/LazyServiceDumper.php',
        '_ContaoManager\\Symfony\\Component\\DependencyInjection\\LazyProxy\\PhpDumper\\NullDumper' => __DIR__ . '/..' . '/symfony/dependency-injection/LazyProxy/PhpDumper/NullDumper.php',
        '_ContaoManager\\Symfony\\Component\\DependencyInjection\\LazyProxy\\ProxyHelper' => __DIR__ . '/..' . '/symfony/dependency-injection/LazyProxy/ProxyHelper.php',
        '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Loader\\ClosureLoader' => __DIR__ . '/..' . '/symfony/dependency-injection/Loader/ClosureLoader.php',
        '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Loader\\Configurator\\AbstractConfigurator' => __DIR__ . '/..' . '/symfony/dependency-injection/Loader/Configurator/AbstractConfigurator.php',
        '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Loader\\Configurator\\AbstractServiceConfigurator' => __DIR__ . '/..' . '/symfony/dependency-injection/Loader/Configurator/AbstractServiceConfigurator.php',
        '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Loader\\Configurator\\AliasConfigurator' => __DIR__ . '/..' . '/symfony/dependency-injection/Loader/Configurator/AliasConfigurator.php',
        '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Loader\\Configurator\\ClosureReferenceConfigurator' => __DIR__ . '/..' . '/symfony/dependency-injection/Loader/Configurator/ClosureReferenceConfigurator.php',
        '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Loader\\Configurator\\ContainerConfigurator' => __DIR__ . '/..' . '/symfony/dependency-injection/Loader/Configurator/ContainerConfigurator.php',
        '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Loader\\Configurator\\DefaultsConfigurator' => __DIR__ . '/..' . '/symfony/dependency-injection/Loader/Configurator/DefaultsConfigurator.php',
        '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Loader\\Configurator\\EnvConfigurator' => __DIR__ . '/..' . '/symfony/dependency-injection/Loader/Configurator/EnvConfigurator.php',
        '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Loader\\Configurator\\FromCallableConfigurator' => __DIR__ . '/..' . '/symfony/dependency-injection/Loader/Configurator/FromCallableConfigurator.php',
        '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Loader\\Configurator\\InlineServiceConfigurator' => __DIR__ . '/..' . '/symfony/dependency-injection/Loader/Configurator/InlineServiceConfigurator.php',
        '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Loader\\Configurator\\InstanceofConfigurator' => __DIR__ . '/..' . '/symfony/dependency-injection/Loader/Configurator/InstanceofConfigurator.php',
        '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Loader\\Configurator\\ParametersConfigurator' => __DIR__ . '/..' . '/symfony/dependency-injection/Loader/Configurator/ParametersConfigurator.php',
        '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Loader\\Configurator\\PrototypeConfigurator' => __DIR__ . '/..' . '/symfony/dependency-injection/Loader/Configurator/PrototypeConfigurator.php',
        '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Loader\\Configurator\\ReferenceConfigurator' => __DIR__ . '/..' . '/symfony/dependency-injection/Loader/Configurator/ReferenceConfigurator.php',
        '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Loader\\Configurator\\ServiceConfigurator' => __DIR__ . '/..' . '/symfony/dependency-injection/Loader/Configurator/ServiceConfigurator.php',
        '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Loader\\Configurator\\ServicesConfigurator' => __DIR__ . '/..' . '/symfony/dependency-injection/Loader/Configurator/ServicesConfigurator.php',
        '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Loader\\Configurator\\Traits\\AbstractTrait' => __DIR__ . '/..' . '/symfony/dependency-injection/Loader/Configurator/Traits/AbstractTrait.php',
        '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Loader\\Configurator\\Traits\\ArgumentTrait' => __DIR__ . '/..' . '/symfony/dependency-injection/Loader/Configurator/Traits/ArgumentTrait.php',
        '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Loader\\Configurator\\Traits\\AutoconfigureTrait' => __DIR__ . '/..' . '/symfony/dependency-injection/Loader/Configurator/Traits/AutoconfigureTrait.php',
        '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Loader\\Configurator\\Traits\\AutowireTrait' => __DIR__ . '/..' . '/symfony/dependency-injection/Loader/Configurator/Traits/AutowireTrait.php',
        '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Loader\\Configurator\\Traits\\BindTrait' => __DIR__ . '/..' . '/symfony/dependency-injection/Loader/Configurator/Traits/BindTrait.php',
        '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Loader\\Configurator\\Traits\\CallTrait' => __DIR__ . '/..' . '/symfony/dependency-injection/Loader/Configurator/Traits/CallTrait.php',
        '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Loader\\Configurator\\Traits\\ClassTrait' => __DIR__ . '/..' . '/symfony/dependency-injection/Loader/Configurator/Traits/ClassTrait.php',
        '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Loader\\Configurator\\Traits\\ConfiguratorTrait' => __DIR__ . '/..' . '/symfony/dependency-injection/Loader/Configurator/Traits/ConfiguratorTrait.php',
        '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Loader\\Configurator\\Traits\\ConstructorTrait' => __DIR__ . '/..' . '/symfony/dependency-injection/Loader/Configurator/Traits/ConstructorTrait.php',
        '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Loader\\Configurator\\Traits\\DecorateTrait' => __DIR__ . '/..' . '/symfony/dependency-injection/Loader/Configurator/Traits/DecorateTrait.php',
        '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Loader\\Configurator\\Traits\\DeprecateTrait' => __DIR__ . '/..' . '/symfony/dependency-injection/Loader/Configurator/Traits/DeprecateTrait.php',
        '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Loader\\Configurator\\Traits\\FactoryTrait' => __DIR__ . '/..' . '/symfony/dependency-injection/Loader/Configurator/Traits/FactoryTrait.php',
        '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Loader\\Configurator\\Traits\\FileTrait' => __DIR__ . '/..' . '/symfony/dependency-injection/Loader/Configurator/Traits/FileTrait.php',
        '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Loader\\Configurator\\Traits\\FromCallableTrait' => __DIR__ . '/..' . '/symfony/dependency-injection/Loader/Configurator/Traits/FromCallableTrait.php',
        '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Loader\\Configurator\\Traits\\LazyTrait' => __DIR__ . '/..' . '/symfony/dependency-injection/Loader/Configurator/Traits/LazyTrait.php',
        '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Loader\\Configurator\\Traits\\ParentTrait' => __DIR__ . '/..' . '/symfony/dependency-injection/Loader/Configurator/Traits/ParentTrait.php',
        '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Loader\\Configurator\\Traits\\PropertyTrait' => __DIR__ . '/..' . '/symfony/dependency-injection/Loader/Configurator/Traits/PropertyTrait.php',
        '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Loader\\Configurator\\Traits\\PublicTrait' => __DIR__ . '/..' . '/symfony/dependency-injection/Loader/Configurator/Traits/PublicTrait.php',
        '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Loader\\Configurator\\Traits\\ShareTrait' => __DIR__ . '/..' . '/symfony/dependency-injection/Loader/Configurator/Traits/ShareTrait.php',
        '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Loader\\Configurator\\Traits\\SyntheticTrait' => __DIR__ . '/..' . '/symfony/dependency-injection/Loader/Configurator/Traits/SyntheticTrait.php',
        '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Loader\\Configurator\\Traits\\TagTrait' => __DIR__ . '/..' . '/symfony/dependency-injection/Loader/Configurator/Traits/TagTrait.php',
        '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Loader\\DirectoryLoader' => __DIR__ . '/..' . '/symfony/dependency-injection/Loader/DirectoryLoader.php',
        '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Loader\\FileLoader' => __DIR__ . '/..' . '/symfony/dependency-injection/Loader/FileLoader.php',
        '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Loader\\GlobFileLoader' => __DIR__ . '/..' . '/symfony/dependency-injection/Loader/GlobFileLoader.php',
        '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Loader\\IniFileLoader' => __DIR__ . '/..' . '/symfony/dependency-injection/Loader/IniFileLoader.php',
        '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Loader\\PhpFileLoader' => __DIR__ . '/..' . '/symfony/dependency-injection/Loader/PhpFileLoader.php',
        '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Loader\\XmlFileLoader' => __DIR__ . '/..' . '/symfony/dependency-injection/Loader/XmlFileLoader.php',
        '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Loader\\YamlFileLoader' => __DIR__ . '/..' . '/symfony/dependency-injection/Loader/YamlFileLoader.php',
        '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Parameter' => __DIR__ . '/..' . '/symfony/dependency-injection/Parameter.php',
        '_ContaoManager\\Symfony\\Component\\DependencyInjection\\ParameterBag\\ContainerBag' => __DIR__ . '/..' . '/symfony/dependency-injection/ParameterBag/ContainerBag.php',
        '_ContaoManager\\Symfony\\Component\\DependencyInjection\\ParameterBag\\ContainerBagInterface' => __DIR__ . '/..' . '/symfony/dependency-injection/ParameterBag/ContainerBagInterface.php',
        '_ContaoManager\\Symfony\\Component\\DependencyInjection\\ParameterBag\\EnvPlaceholderParameterBag' => __DIR__ . '/..' . '/symfony/dependency-injection/ParameterBag/EnvPlaceholderParameterBag.php',
        '_ContaoManager\\Symfony\\Component\\DependencyInjection\\ParameterBag\\FrozenParameterBag' => __DIR__ . '/..' . '/symfony/dependency-injection/ParameterBag/FrozenParameterBag.php',
        '_ContaoManager\\Symfony\\Component\\DependencyInjection\\ParameterBag\\ParameterBag' => __DIR__ . '/..' . '/symfony/dependency-injection/ParameterBag/ParameterBag.php',
        '_ContaoManager\\Symfony\\Component\\DependencyInjection\\ParameterBag\\ParameterBagInterface' => __DIR__ . '/..' . '/symfony/dependency-injection/ParameterBag/ParameterBagInterface.php',
        '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Reference' => __DIR__ . '/..' . '/symfony/dependency-injection/Reference.php',
        '_ContaoManager\\Symfony\\Component\\DependencyInjection\\ReverseContainer' => __DIR__ . '/..' . '/symfony/dependency-injection/ReverseContainer.php',
        '_ContaoManager\\Symfony\\Component\\DependencyInjection\\ServiceLocator' => __DIR__ . '/..' . '/symfony/dependency-injection/ServiceLocator.php',
        '_ContaoManager\\Symfony\\Component\\DependencyInjection\\TaggedContainerInterface' => __DIR__ . '/..' . '/symfony/dependency-injection/TaggedContainerInterface.php',
        '_ContaoManager\\Symfony\\Component\\DependencyInjection\\TypedReference' => __DIR__ . '/..' . '/symfony/dependency-injection/TypedReference.php',
        '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Variable' => __DIR__ . '/..' . '/symfony/dependency-injection/Variable.php',
        '_ContaoManager\\Symfony\\Component\\ErrorHandler\\BufferingLogger' => __DIR__ . '/..' . '/symfony/error-handler/BufferingLogger.php',
        '_ContaoManager\\Symfony\\Component\\ErrorHandler\\Debug' => __DIR__ . '/..' . '/symfony/error-handler/Debug.php',
        '_ContaoManager\\Symfony\\Component\\ErrorHandler\\DebugClassLoader' => __DIR__ . '/..' . '/symfony/error-handler/DebugClassLoader.php',
        '_ContaoManager\\Symfony\\Component\\ErrorHandler\\ErrorEnhancer\\ClassNotFoundErrorEnhancer' => __DIR__ . '/..' . '/symfony/error-handler/ErrorEnhancer/ClassNotFoundErrorEnhancer.php',
        '_ContaoManager\\Symfony\\Component\\ErrorHandler\\ErrorEnhancer\\ErrorEnhancerInterface' => __DIR__ . '/..' . '/symfony/error-handler/ErrorEnhancer/ErrorEnhancerInterface.php',
        '_ContaoManager\\Symfony\\Component\\ErrorHandler\\ErrorEnhancer\\UndefinedFunctionErrorEnhancer' => __DIR__ . '/..' . '/symfony/error-handler/ErrorEnhancer/UndefinedFunctionErrorEnhancer.php',
        '_ContaoManager\\Symfony\\Component\\ErrorHandler\\ErrorEnhancer\\UndefinedMethodErrorEnhancer' => __DIR__ . '/..' . '/symfony/error-handler/ErrorEnhancer/UndefinedMethodErrorEnhancer.php',
        '_ContaoManager\\Symfony\\Component\\ErrorHandler\\ErrorHandler' => __DIR__ . '/..' . '/symfony/error-handler/ErrorHandler.php',
        '_ContaoManager\\Symfony\\Component\\ErrorHandler\\ErrorRenderer\\CliErrorRenderer' => __DIR__ . '/..' . '/symfony/error-handler/ErrorRenderer/CliErrorRenderer.php',
        '_ContaoManager\\Symfony\\Component\\ErrorHandler\\ErrorRenderer\\ErrorRendererInterface' => __DIR__ . '/..' . '/symfony/error-handler/ErrorRenderer/ErrorRendererInterface.php',
        '_ContaoManager\\Symfony\\Component\\ErrorHandler\\ErrorRenderer\\FileLinkFormatter' => __DIR__ . '/..' . '/symfony/error-handler/ErrorRenderer/FileLinkFormatter.php',
        '_ContaoManager\\Symfony\\Component\\ErrorHandler\\ErrorRenderer\\HtmlErrorRenderer' => __DIR__ . '/..' . '/symfony/error-handler/ErrorRenderer/HtmlErrorRenderer.php',
        '_ContaoManager\\Symfony\\Component\\ErrorHandler\\ErrorRenderer\\SerializerErrorRenderer' => __DIR__ . '/..' . '/symfony/error-handler/ErrorRenderer/SerializerErrorRenderer.php',
        '_ContaoManager\\Symfony\\Component\\ErrorHandler\\Error\\ClassNotFoundError' => __DIR__ . '/..' . '/symfony/error-handler/Error/ClassNotFoundError.php',
        '_ContaoManager\\Symfony\\Component\\ErrorHandler\\Error\\FatalError' => __DIR__ . '/..' . '/symfony/error-handler/Error/FatalError.php',
        '_ContaoManager\\Symfony\\Component\\ErrorHandler\\Error\\OutOfMemoryError' => __DIR__ . '/..' . '/symfony/error-handler/Error/OutOfMemoryError.php',
        '_ContaoManager\\Symfony\\Component\\ErrorHandler\\Error\\UndefinedFunctionError' => __DIR__ . '/..' . '/symfony/error-handler/Error/UndefinedFunctionError.php',
        '_ContaoManager\\Symfony\\Component\\ErrorHandler\\Error\\UndefinedMethodError' => __DIR__ . '/..' . '/symfony/error-handler/Error/UndefinedMethodError.php',
        '_ContaoManager\\Symfony\\Component\\ErrorHandler\\Exception\\FlattenException' => __DIR__ . '/..' . '/symfony/error-handler/Exception/FlattenException.php',
        '_ContaoManager\\Symfony\\Component\\ErrorHandler\\Exception\\SilencedErrorContext' => __DIR__ . '/..' . '/symfony/error-handler/Exception/SilencedErrorContext.php',
        '_ContaoManager\\Symfony\\Component\\ErrorHandler\\Internal\\TentativeTypes' => __DIR__ . '/..' . '/symfony/error-handler/Internal/TentativeTypes.php',
        '_ContaoManager\\Symfony\\Component\\ErrorHandler\\ThrowableUtils' => __DIR__ . '/..' . '/symfony/error-handler/ThrowableUtils.php',
        '_ContaoManager\\Symfony\\Component\\EventDispatcher\\Attribute\\AsEventListener' => __DIR__ . '/..' . '/symfony/event-dispatcher/Attribute/AsEventListener.php',
        '_ContaoManager\\Symfony\\Component\\EventDispatcher\\Debug\\TraceableEventDispatcher' => __DIR__ . '/..' . '/symfony/event-dispatcher/Debug/TraceableEventDispatcher.php',
        '_ContaoManager\\Symfony\\Component\\EventDispatcher\\Debug\\WrappedListener' => __DIR__ . '/..' . '/symfony/event-dispatcher/Debug/WrappedListener.php',
        '_ContaoManager\\Symfony\\Component\\EventDispatcher\\DependencyInjection\\AddEventAliasesPass' => __DIR__ . '/..' . '/symfony/event-dispatcher/DependencyInjection/AddEventAliasesPass.php',
        '_ContaoManager\\Symfony\\Component\\EventDispatcher\\DependencyInjection\\RegisterListenersPass' => __DIR__ . '/..' . '/symfony/event-dispatcher/DependencyInjection/RegisterListenersPass.php',
        '_ContaoManager\\Symfony\\Component\\EventDispatcher\\EventDispatcher' => __DIR__ . '/..' . '/symfony/event-dispatcher/EventDispatcher.php',
        '_ContaoManager\\Symfony\\Component\\EventDispatcher\\EventDispatcherInterface' => __DIR__ . '/..' . '/symfony/event-dispatcher/EventDispatcherInterface.php',
        '_ContaoManager\\Symfony\\Component\\EventDispatcher\\EventSubscriberInterface' => __DIR__ . '/..' . '/symfony/event-dispatcher/EventSubscriberInterface.php',
        '_ContaoManager\\Symfony\\Component\\EventDispatcher\\GenericEvent' => __DIR__ . '/..' . '/symfony/event-dispatcher/GenericEvent.php',
        '_ContaoManager\\Symfony\\Component\\EventDispatcher\\ImmutableEventDispatcher' => __DIR__ . '/..' . '/symfony/event-dispatcher/ImmutableEventDispatcher.php',
        '_ContaoManager\\Symfony\\Component\\Filesystem\\Exception\\ExceptionInterface' => __DIR__ . '/..' . '/symfony/filesystem/Exception/ExceptionInterface.php',
        '_ContaoManager\\Symfony\\Component\\Filesystem\\Exception\\FileNotFoundException' => __DIR__ . '/..' . '/symfony/filesystem/Exception/FileNotFoundException.php',
        '_ContaoManager\\Symfony\\Component\\Filesystem\\Exception\\IOException' => __DIR__ . '/..' . '/symfony/filesystem/Exception/IOException.php',
        '_ContaoManager\\Symfony\\Component\\Filesystem\\Exception\\IOExceptionInterface' => __DIR__ . '/..' . '/symfony/filesystem/Exception/IOExceptionInterface.php',
        '_ContaoManager\\Symfony\\Component\\Filesystem\\Exception\\InvalidArgumentException' => __DIR__ . '/..' . '/symfony/filesystem/Exception/InvalidArgumentException.php',
        '_ContaoManager\\Symfony\\Component\\Filesystem\\Exception\\RuntimeException' => __DIR__ . '/..' . '/symfony/filesystem/Exception/RuntimeException.php',
        '_ContaoManager\\Symfony\\Component\\Filesystem\\Filesystem' => __DIR__ . '/..' . '/symfony/filesystem/Filesystem.php',
        '_ContaoManager\\Symfony\\Component\\Filesystem\\Path' => __DIR__ . '/..' . '/symfony/filesystem/Path.php',
        '_ContaoManager\\Symfony\\Component\\Finder\\Comparator\\Comparator' => __DIR__ . '/..' . '/symfony/finder/Comparator/Comparator.php',
        '_ContaoManager\\Symfony\\Component\\Finder\\Comparator\\DateComparator' => __DIR__ . '/..' . '/symfony/finder/Comparator/DateComparator.php',
        '_ContaoManager\\Symfony\\Component\\Finder\\Comparator\\NumberComparator' => __DIR__ . '/..' . '/symfony/finder/Comparator/NumberComparator.php',
        '_ContaoManager\\Symfony\\Component\\Finder\\Exception\\AccessDeniedException' => __DIR__ . '/..' . '/symfony/finder/Exception/AccessDeniedException.php',
        '_ContaoManager\\Symfony\\Component\\Finder\\Exception\\DirectoryNotFoundException' => __DIR__ . '/..' . '/symfony/finder/Exception/DirectoryNotFoundException.php',
        '_ContaoManager\\Symfony\\Component\\Finder\\Finder' => __DIR__ . '/..' . '/symfony/finder/Finder.php',
        '_ContaoManager\\Symfony\\Component\\Finder\\Gitignore' => __DIR__ . '/..' . '/symfony/finder/Gitignore.php',
        '_ContaoManager\\Symfony\\Component\\Finder\\Glob' => __DIR__ . '/..' . '/symfony/finder/Glob.php',
        '_ContaoManager\\Symfony\\Component\\Finder\\Iterator\\CustomFilterIterator' => __DIR__ . '/..' . '/symfony/finder/Iterator/CustomFilterIterator.php',
        '_ContaoManager\\Symfony\\Component\\Finder\\Iterator\\DateRangeFilterIterator' => __DIR__ . '/..' . '/symfony/finder/Iterator/DateRangeFilterIterator.php',
        '_ContaoManager\\Symfony\\Component\\Finder\\Iterator\\DepthRangeFilterIterator' => __DIR__ . '/..' . '/symfony/finder/Iterator/DepthRangeFilterIterator.php',
        '_ContaoManager\\Symfony\\Component\\Finder\\Iterator\\ExcludeDirectoryFilterIterator' => __DIR__ . '/..' . '/symfony/finder/Iterator/ExcludeDirectoryFilterIterator.php',
        '_ContaoManager\\Symfony\\Component\\Finder\\Iterator\\FileTypeFilterIterator' => __DIR__ . '/..' . '/symfony/finder/Iterator/FileTypeFilterIterator.php',
        '_ContaoManager\\Symfony\\Component\\Finder\\Iterator\\FilecontentFilterIterator' => __DIR__ . '/..' . '/symfony/finder/Iterator/FilecontentFilterIterator.php',
        '_ContaoManager\\Symfony\\Component\\Finder\\Iterator\\FilenameFilterIterator' => __DIR__ . '/..' . '/symfony/finder/Iterator/FilenameFilterIterator.php',
        '_ContaoManager\\Symfony\\Component\\Finder\\Iterator\\LazyIterator' => __DIR__ . '/..' . '/symfony/finder/Iterator/LazyIterator.php',
        '_ContaoManager\\Symfony\\Component\\Finder\\Iterator\\MultiplePcreFilterIterator' => __DIR__ . '/..' . '/symfony/finder/Iterator/MultiplePcreFilterIterator.php',
        '_ContaoManager\\Symfony\\Component\\Finder\\Iterator\\PathFilterIterator' => __DIR__ . '/..' . '/symfony/finder/Iterator/PathFilterIterator.php',
        '_ContaoManager\\Symfony\\Component\\Finder\\Iterator\\RecursiveDirectoryIterator' => __DIR__ . '/..' . '/symfony/finder/Iterator/RecursiveDirectoryIterator.php',
        '_ContaoManager\\Symfony\\Component\\Finder\\Iterator\\SizeRangeFilterIterator' => __DIR__ . '/..' . '/symfony/finder/Iterator/SizeRangeFilterIterator.php',
        '_ContaoManager\\Symfony\\Component\\Finder\\Iterator\\SortableIterator' => __DIR__ . '/..' . '/symfony/finder/Iterator/SortableIterator.php',
        '_ContaoManager\\Symfony\\Component\\Finder\\Iterator\\VcsIgnoredFilterIterator' => __DIR__ . '/..' . '/symfony/finder/Iterator/VcsIgnoredFilterIterator.php',
        '_ContaoManager\\Symfony\\Component\\Finder\\SplFileInfo' => __DIR__ . '/..' . '/symfony/finder/SplFileInfo.php',
        '_ContaoManager\\Symfony\\Component\\HttpFoundation\\AcceptHeader' => __DIR__ . '/..' . '/symfony/http-foundation/AcceptHeader.php',
        '_ContaoManager\\Symfony\\Component\\HttpFoundation\\AcceptHeaderItem' => __DIR__ . '/..' . '/symfony/http-foundation/AcceptHeaderItem.php',
        '_ContaoManager\\Symfony\\Component\\HttpFoundation\\BinaryFileResponse' => __DIR__ . '/..' . '/symfony/http-foundation/BinaryFileResponse.php',
        '_ContaoManager\\Symfony\\Component\\HttpFoundation\\ChainRequestMatcher' => __DIR__ . '/..' . '/symfony/http-foundation/ChainRequestMatcher.php',
        '_ContaoManager\\Symfony\\Component\\HttpFoundation\\Cookie' => __DIR__ . '/..' . '/symfony/http-foundation/Cookie.php',
        '_ContaoManager\\Symfony\\Component\\HttpFoundation\\Exception\\BadRequestException' => __DIR__ . '/..' . '/symfony/http-foundation/Exception/BadRequestException.php',
        '_ContaoManager\\Symfony\\Component\\HttpFoundation\\Exception\\ConflictingHeadersException' => __DIR__ . '/..' . '/symfony/http-foundation/Exception/ConflictingHeadersException.php',
        '_ContaoManager\\Symfony\\Component\\HttpFoundation\\Exception\\JsonException' => __DIR__ . '/..' . '/symfony/http-foundation/Exception/JsonException.php',
        '_ContaoManager\\Symfony\\Component\\HttpFoundation\\Exception\\RequestExceptionInterface' => __DIR__ . '/..' . '/symfony/http-foundation/Exception/RequestExceptionInterface.php',
        '_ContaoManager\\Symfony\\Component\\HttpFoundation\\Exception\\SessionNotFoundException' => __DIR__ . '/..' . '/symfony/http-foundation/Exception/SessionNotFoundException.php',
        '_ContaoManager\\Symfony\\Component\\HttpFoundation\\Exception\\SuspiciousOperationException' => __DIR__ . '/..' . '/symfony/http-foundation/Exception/SuspiciousOperationException.php',
        '_ContaoManager\\Symfony\\Component\\HttpFoundation\\Exception\\UnexpectedValueException' => __DIR__ . '/..' . '/symfony/http-foundation/Exception/UnexpectedValueException.php',
        '_ContaoManager\\Symfony\\Component\\HttpFoundation\\ExpressionRequestMatcher' => __DIR__ . '/..' . '/symfony/http-foundation/ExpressionRequestMatcher.php',
        '_ContaoManager\\Symfony\\Component\\HttpFoundation\\FileBag' => __DIR__ . '/..' . '/symfony/http-foundation/FileBag.php',
        '_ContaoManager\\Symfony\\Component\\HttpFoundation\\File\\Exception\\AccessDeniedException' => __DIR__ . '/..' . '/symfony/http-foundation/File/Exception/AccessDeniedException.php',
        '_ContaoManager\\Symfony\\Component\\HttpFoundation\\File\\Exception\\CannotWriteFileException' => __DIR__ . '/..' . '/symfony/http-foundation/File/Exception/CannotWriteFileException.php',
        '_ContaoManager\\Symfony\\Component\\HttpFoundation\\File\\Exception\\ExtensionFileException' => __DIR__ . '/..' . '/symfony/http-foundation/File/Exception/ExtensionFileException.php',
        '_ContaoManager\\Symfony\\Component\\HttpFoundation\\File\\Exception\\FileException' => __DIR__ . '/..' . '/symfony/http-foundation/File/Exception/FileException.php',
        '_ContaoManager\\Symfony\\Component\\HttpFoundation\\File\\Exception\\FileNotFoundException' => __DIR__ . '/..' . '/symfony/http-foundation/File/Exception/FileNotFoundException.php',
        '_ContaoManager\\Symfony\\Component\\HttpFoundation\\File\\Exception\\FormSizeFileException' => __DIR__ . '/..' . '/symfony/http-foundation/File/Exception/FormSizeFileException.php',
        '_ContaoManager\\Symfony\\Component\\HttpFoundation\\File\\Exception\\IniSizeFileException' => __DIR__ . '/..' . '/symfony/http-foundation/File/Exception/IniSizeFileException.php',
        '_ContaoManager\\Symfony\\Component\\HttpFoundation\\File\\Exception\\NoFileException' => __DIR__ . '/..' . '/symfony/http-foundation/File/Exception/NoFileException.php',
        '_ContaoManager\\Symfony\\Component\\HttpFoundation\\File\\Exception\\NoTmpDirFileException' => __DIR__ . '/..' . '/symfony/http-foundation/File/Exception/NoTmpDirFileException.php',
        '_ContaoManager\\Symfony\\Component\\HttpFoundation\\File\\Exception\\PartialFileException' => __DIR__ . '/..' . '/symfony/http-foundation/File/Exception/PartialFileException.php',
        '_ContaoManager\\Symfony\\Component\\HttpFoundation\\File\\Exception\\UnexpectedTypeException' => __DIR__ . '/..' . '/symfony/http-foundation/File/Exception/UnexpectedTypeException.php',
        '_ContaoManager\\Symfony\\Component\\HttpFoundation\\File\\Exception\\UploadException' => __DIR__ . '/..' . '/symfony/http-foundation/File/Exception/UploadException.php',
        '_ContaoManager\\Symfony\\Component\\HttpFoundation\\File\\File' => __DIR__ . '/..' . '/symfony/http-foundation/File/File.php',
        '_ContaoManager\\Symfony\\Component\\HttpFoundation\\File\\Stream' => __DIR__ . '/..' . '/symfony/http-foundation/File/Stream.php',
        '_ContaoManager\\Symfony\\Component\\HttpFoundation\\File\\UploadedFile' => __DIR__ . '/..' . '/symfony/http-foundation/File/UploadedFile.php',
        '_ContaoManager\\Symfony\\Component\\HttpFoundation\\HeaderBag' => __DIR__ . '/..' . '/symfony/http-foundation/HeaderBag.php',
        '_ContaoManager\\Symfony\\Component\\HttpFoundation\\HeaderUtils' => __DIR__ . '/..' . '/symfony/http-foundation/HeaderUtils.php',
        '_ContaoManager\\Symfony\\Component\\HttpFoundation\\InputBag' => __DIR__ . '/..' . '/symfony/http-foundation/InputBag.php',
        '_ContaoManager\\Symfony\\Component\\HttpFoundation\\IpUtils' => __DIR__ . '/..' . '/symfony/http-foundation/IpUtils.php',
        '_ContaoManager\\Symfony\\Component\\HttpFoundation\\JsonResponse' => __DIR__ . '/..' . '/symfony/http-foundation/JsonResponse.php',
        '_ContaoManager\\Symfony\\Component\\HttpFoundation\\ParameterBag' => __DIR__ . '/..' . '/symfony/http-foundation/ParameterBag.php',
        '_ContaoManager\\Symfony\\Component\\HttpFoundation\\RateLimiter\\AbstractRequestRateLimiter' => __DIR__ . '/..' . '/symfony/http-foundation/RateLimiter/AbstractRequestRateLimiter.php',
        '_ContaoManager\\Symfony\\Component\\HttpFoundation\\RateLimiter\\PeekableRequestRateLimiterInterface' => __DIR__ . '/..' . '/symfony/http-foundation/RateLimiter/PeekableRequestRateLimiterInterface.php',
        '_ContaoManager\\Symfony\\Component\\HttpFoundation\\RateLimiter\\RequestRateLimiterInterface' => __DIR__ . '/..' . '/symfony/http-foundation/RateLimiter/RequestRateLimiterInterface.php',
        '_ContaoManager\\Symfony\\Component\\HttpFoundation\\RedirectResponse' => __DIR__ . '/..' . '/symfony/http-foundation/RedirectResponse.php',
        '_ContaoManager\\Symfony\\Component\\HttpFoundation\\Request' => __DIR__ . '/..' . '/symfony/http-foundation/Request.php',
        '_ContaoManager\\Symfony\\Component\\HttpFoundation\\RequestMatcher' => __DIR__ . '/..' . '/symfony/http-foundation/RequestMatcher.php',
        '_ContaoManager\\Symfony\\Component\\HttpFoundation\\RequestMatcherInterface' => __DIR__ . '/..' . '/symfony/http-foundation/RequestMatcherInterface.php',
        '_ContaoManager\\Symfony\\Component\\HttpFoundation\\RequestMatcher\\AttributesRequestMatcher' => __DIR__ . '/..' . '/symfony/http-foundation/RequestMatcher/AttributesRequestMatcher.php',
        '_ContaoManager\\Symfony\\Component\\HttpFoundation\\RequestMatcher\\ExpressionRequestMatcher' => __DIR__ . '/..' . '/symfony/http-foundation/RequestMatcher/ExpressionRequestMatcher.php',
        '_ContaoManager\\Symfony\\Component\\HttpFoundation\\RequestMatcher\\HostRequestMatcher' => __DIR__ . '/..' . '/symfony/http-foundation/RequestMatcher/HostRequestMatcher.php',
        '_ContaoManager\\Symfony\\Component\\HttpFoundation\\RequestMatcher\\IpsRequestMatcher' => __DIR__ . '/..' . '/symfony/http-foundation/RequestMatcher/IpsRequestMatcher.php',
        '_ContaoManager\\Symfony\\Component\\HttpFoundation\\RequestMatcher\\IsJsonRequestMatcher' => __DIR__ . '/..' . '/symfony/http-foundation/RequestMatcher/IsJsonRequestMatcher.php',
        '_ContaoManager\\Symfony\\Component\\HttpFoundation\\RequestMatcher\\MethodRequestMatcher' => __DIR__ . '/..' . '/symfony/http-foundation/RequestMatcher/MethodRequestMatcher.php',
        '_ContaoManager\\Symfony\\Component\\HttpFoundation\\RequestMatcher\\PathRequestMatcher' => __DIR__ . '/..' . '/symfony/http-foundation/RequestMatcher/PathRequestMatcher.php',
        '_ContaoManager\\Symfony\\Component\\HttpFoundation\\RequestMatcher\\PortRequestMatcher' => __DIR__ . '/..' . '/symfony/http-foundation/RequestMatcher/PortRequestMatcher.php',
        '_ContaoManager\\Symfony\\Component\\HttpFoundation\\RequestMatcher\\SchemeRequestMatcher' => __DIR__ . '/..' . '/symfony/http-foundation/RequestMatcher/SchemeRequestMatcher.php',
        '_ContaoManager\\Symfony\\Component\\HttpFoundation\\RequestStack' => __DIR__ . '/..' . '/symfony/http-foundation/RequestStack.php',
        '_ContaoManager\\Symfony\\Component\\HttpFoundation\\Response' => __DIR__ . '/..' . '/symfony/http-foundation/Response.php',
        '_ContaoManager\\Symfony\\Component\\HttpFoundation\\ResponseHeaderBag' => __DIR__ . '/..' . '/symfony/http-foundation/ResponseHeaderBag.php',
        '_ContaoManager\\Symfony\\Component\\HttpFoundation\\ServerBag' => __DIR__ . '/..' . '/symfony/http-foundation/ServerBag.php',
        '_ContaoManager\\Symfony\\Component\\HttpFoundation\\Session\\Attribute\\AttributeBag' => __DIR__ . '/..' . '/symfony/http-foundation/Session/Attribute/AttributeBag.php',
        '_ContaoManager\\Symfony\\Component\\HttpFoundation\\Session\\Attribute\\AttributeBagInterface' => __DIR__ . '/..' . '/symfony/http-foundation/Session/Attribute/AttributeBagInterface.php',
        '_ContaoManager\\Symfony\\Component\\HttpFoundation\\Session\\FlashBagAwareSessionInterface' => __DIR__ . '/..' . '/symfony/http-foundation/Session/FlashBagAwareSessionInterface.php',
        '_ContaoManager\\Symfony\\Component\\HttpFoundation\\Session\\Flash\\AutoExpireFlashBag' => __DIR__ . '/..' . '/symfony/http-foundation/Session/Flash/AutoExpireFlashBag.php',
        '_ContaoManager\\Symfony\\Component\\HttpFoundation\\Session\\Flash\\FlashBag' => __DIR__ . '/..' . '/symfony/http-foundation/Session/Flash/FlashBag.php',
        '_ContaoManager\\Symfony\\Component\\HttpFoundation\\Session\\Flash\\FlashBagInterface' => __DIR__ . '/..' . '/symfony/http-foundation/Session/Flash/FlashBagInterface.php',
        '_ContaoManager\\Symfony\\Component\\HttpFoundation\\Session\\Session' => __DIR__ . '/..' . '/symfony/http-foundation/Session/Session.php',
        '_ContaoManager\\Symfony\\Component\\HttpFoundation\\Session\\SessionBagInterface' => __DIR__ . '/..' . '/symfony/http-foundation/Session/SessionBagInterface.php',
        '_ContaoManager\\Symfony\\Component\\HttpFoundation\\Session\\SessionBagProxy' => __DIR__ . '/..' . '/symfony/http-foundation/Session/SessionBagProxy.php',
        '_ContaoManager\\Symfony\\Component\\HttpFoundation\\Session\\SessionFactory' => __DIR__ . '/..' . '/symfony/http-foundation/Session/SessionFactory.php',
        '_ContaoManager\\Symfony\\Component\\HttpFoundation\\Session\\SessionFactoryInterface' => __DIR__ . '/..' . '/symfony/http-foundation/Session/SessionFactoryInterface.php',
        '_ContaoManager\\Symfony\\Component\\HttpFoundation\\Session\\SessionInterface' => __DIR__ . '/..' . '/symfony/http-foundation/Session/SessionInterface.php',
        '_ContaoManager\\Symfony\\Component\\HttpFoundation\\Session\\SessionUtils' => __DIR__ . '/..' . '/symfony/http-foundation/Session/SessionUtils.php',
        '_ContaoManager\\Symfony\\Component\\HttpFoundation\\Session\\Storage\\Handler\\AbstractSessionHandler' => __DIR__ . '/..' . '/symfony/http-foundation/Session/Storage/Handler/AbstractSessionHandler.php',
        '_ContaoManager\\Symfony\\Component\\HttpFoundation\\Session\\Storage\\Handler\\IdentityMarshaller' => __DIR__ . '/..' . '/symfony/http-foundation/Session/Storage/Handler/IdentityMarshaller.php',
        '_ContaoManager\\Symfony\\Component\\HttpFoundation\\Session\\Storage\\Handler\\MarshallingSessionHandler' => __DIR__ . '/..' . '/symfony/http-foundation/Session/Storage/Handler/MarshallingSessionHandler.php',
        '_ContaoManager\\Symfony\\Component\\HttpFoundation\\Session\\Storage\\Handler\\MemcachedSessionHandler' => __DIR__ . '/..' . '/symfony/http-foundation/Session/Storage/Handler/MemcachedSessionHandler.php',
        '_ContaoManager\\Symfony\\Component\\HttpFoundation\\Session\\Storage\\Handler\\MigratingSessionHandler' => __DIR__ . '/..' . '/symfony/http-foundation/Session/Storage/Handler/MigratingSessionHandler.php',
        '_ContaoManager\\Symfony\\Component\\HttpFoundation\\Session\\Storage\\Handler\\MongoDbSessionHandler' => __DIR__ . '/..' . '/symfony/http-foundation/Session/Storage/Handler/MongoDbSessionHandler.php',
        '_ContaoManager\\Symfony\\Component\\HttpFoundation\\Session\\Storage\\Handler\\NativeFileSessionHandler' => __DIR__ . '/..' . '/symfony/http-foundation/Session/Storage/Handler/NativeFileSessionHandler.php',
        '_ContaoManager\\Symfony\\Component\\HttpFoundation\\Session\\Storage\\Handler\\NullSessionHandler' => __DIR__ . '/..' . '/symfony/http-foundation/Session/Storage/Handler/NullSessionHandler.php',
        '_ContaoManager\\Symfony\\Component\\HttpFoundation\\Session\\Storage\\Handler\\PdoSessionHandler' => __DIR__ . '/..' . '/symfony/http-foundation/Session/Storage/Handler/PdoSessionHandler.php',
        '_ContaoManager\\Symfony\\Component\\HttpFoundation\\Session\\Storage\\Handler\\RedisSessionHandler' => __DIR__ . '/..' . '/symfony/http-foundation/Session/Storage/Handler/RedisSessionHandler.php',
        '_ContaoManager\\Symfony\\Component\\HttpFoundation\\Session\\Storage\\Handler\\SessionHandlerFactory' => __DIR__ . '/..' . '/symfony/http-foundation/Session/Storage/Handler/SessionHandlerFactory.php',
        '_ContaoManager\\Symfony\\Component\\HttpFoundation\\Session\\Storage\\Handler\\StrictSessionHandler' => __DIR__ . '/..' . '/symfony/http-foundation/Session/Storage/Handler/StrictSessionHandler.php',
        '_ContaoManager\\Symfony\\Component\\HttpFoundation\\Session\\Storage\\MetadataBag' => __DIR__ . '/..' . '/symfony/http-foundation/Session/Storage/MetadataBag.php',
        '_ContaoManager\\Symfony\\Component\\HttpFoundation\\Session\\Storage\\MockArraySessionStorage' => __DIR__ . '/..' . '/symfony/http-foundation/Session/Storage/MockArraySessionStorage.php',
        '_ContaoManager\\Symfony\\Component\\HttpFoundation\\Session\\Storage\\MockFileSessionStorage' => __DIR__ . '/..' . '/symfony/http-foundation/Session/Storage/MockFileSessionStorage.php',
        '_ContaoManager\\Symfony\\Component\\HttpFoundation\\Session\\Storage\\MockFileSessionStorageFactory' => __DIR__ . '/..' . '/symfony/http-foundation/Session/Storage/MockFileSessionStorageFactory.php',
        '_ContaoManager\\Symfony\\Component\\HttpFoundation\\Session\\Storage\\NativeSessionStorage' => __DIR__ . '/..' . '/symfony/http-foundation/Session/Storage/NativeSessionStorage.php',
        '_ContaoManager\\Symfony\\Component\\HttpFoundation\\Session\\Storage\\NativeSessionStorageFactory' => __DIR__ . '/..' . '/symfony/http-foundation/Session/Storage/NativeSessionStorageFactory.php',
        '_ContaoManager\\Symfony\\Component\\HttpFoundation\\Session\\Storage\\PhpBridgeSessionStorage' => __DIR__ . '/..' . '/symfony/http-foundation/Session/Storage/PhpBridgeSessionStorage.php',
        '_ContaoManager\\Symfony\\Component\\HttpFoundation\\Session\\Storage\\PhpBridgeSessionStorageFactory' => __DIR__ . '/..' . '/symfony/http-foundation/Session/Storage/PhpBridgeSessionStorageFactory.php',
        '_ContaoManager\\Symfony\\Component\\HttpFoundation\\Session\\Storage\\Proxy\\AbstractProxy' => __DIR__ . '/..' . '/symfony/http-foundation/Session/Storage/Proxy/AbstractProxy.php',
        '_ContaoManager\\Symfony\\Component\\HttpFoundation\\Session\\Storage\\Proxy\\SessionHandlerProxy' => __DIR__ . '/..' . '/symfony/http-foundation/Session/Storage/Proxy/SessionHandlerProxy.php',
        '_ContaoManager\\Symfony\\Component\\HttpFoundation\\Session\\Storage\\SessionStorageFactoryInterface' => __DIR__ . '/..' . '/symfony/http-foundation/Session/Storage/SessionStorageFactoryInterface.php',
        '_ContaoManager\\Symfony\\Component\\HttpFoundation\\Session\\Storage\\SessionStorageInterface' => __DIR__ . '/..' . '/symfony/http-foundation/Session/Storage/SessionStorageInterface.php',
        '_ContaoManager\\Symfony\\Component\\HttpFoundation\\StreamedJsonResponse' => __DIR__ . '/..' . '/symfony/http-foundation/StreamedJsonResponse.php',
        '_ContaoManager\\Symfony\\Component\\HttpFoundation\\StreamedResponse' => __DIR__ . '/..' . '/symfony/http-foundation/StreamedResponse.php',
        '_ContaoManager\\Symfony\\Component\\HttpFoundation\\Test\\Constraint\\RequestAttributeValueSame' => __DIR__ . '/..' . '/symfony/http-foundation/Test/Constraint/RequestAttributeValueSame.php',
        '_ContaoManager\\Symfony\\Component\\HttpFoundation\\Test\\Constraint\\ResponseCookieValueSame' => __DIR__ . '/..' . '/symfony/http-foundation/Test/Constraint/ResponseCookieValueSame.php',
        '_ContaoManager\\Symfony\\Component\\HttpFoundation\\Test\\Constraint\\ResponseFormatSame' => __DIR__ . '/..' . '/symfony/http-foundation/Test/Constraint/ResponseFormatSame.php',
        '_ContaoManager\\Symfony\\Component\\HttpFoundation\\Test\\Constraint\\ResponseHasCookie' => __DIR__ . '/..' . '/symfony/http-foundation/Test/Constraint/ResponseHasCookie.php',
        '_ContaoManager\\Symfony\\Component\\HttpFoundation\\Test\\Constraint\\ResponseHasHeader' => __DIR__ . '/..' . '/symfony/http-foundation/Test/Constraint/ResponseHasHeader.php',
        '_ContaoManager\\Symfony\\Component\\HttpFoundation\\Test\\Constraint\\ResponseHeaderLocationSame' => __DIR__ . '/..' . '/symfony/http-foundation/Test/Constraint/ResponseHeaderLocationSame.php',
        '_ContaoManager\\Symfony\\Component\\HttpFoundation\\Test\\Constraint\\ResponseHeaderSame' => __DIR__ . '/..' . '/symfony/http-foundation/Test/Constraint/ResponseHeaderSame.php',
        '_ContaoManager\\Symfony\\Component\\HttpFoundation\\Test\\Constraint\\ResponseIsRedirected' => __DIR__ . '/..' . '/symfony/http-foundation/Test/Constraint/ResponseIsRedirected.php',
        '_ContaoManager\\Symfony\\Component\\HttpFoundation\\Test\\Constraint\\ResponseIsSuccessful' => __DIR__ . '/..' . '/symfony/http-foundation/Test/Constraint/ResponseIsSuccessful.php',
        '_ContaoManager\\Symfony\\Component\\HttpFoundation\\Test\\Constraint\\ResponseIsUnprocessable' => __DIR__ . '/..' . '/symfony/http-foundation/Test/Constraint/ResponseIsUnprocessable.php',
        '_ContaoManager\\Symfony\\Component\\HttpFoundation\\Test\\Constraint\\ResponseStatusCodeSame' => __DIR__ . '/..' . '/symfony/http-foundation/Test/Constraint/ResponseStatusCodeSame.php',
        '_ContaoManager\\Symfony\\Component\\HttpFoundation\\UriSigner' => __DIR__ . '/..' . '/symfony/http-foundation/UriSigner.php',
        '_ContaoManager\\Symfony\\Component\\HttpFoundation\\UrlHelper' => __DIR__ . '/..' . '/symfony/http-foundation/UrlHelper.php',
        '_ContaoManager\\Symfony\\Component\\HttpKernel\\Attribute\\AsController' => __DIR__ . '/..' . '/symfony/http-kernel/Attribute/AsController.php',
        '_ContaoManager\\Symfony\\Component\\HttpKernel\\Attribute\\AsTargetedValueResolver' => __DIR__ . '/..' . '/symfony/http-kernel/Attribute/AsTargetedValueResolver.php',
        '_ContaoManager\\Symfony\\Component\\HttpKernel\\Attribute\\Cache' => __DIR__ . '/..' . '/symfony/http-kernel/Attribute/Cache.php',
        '_ContaoManager\\Symfony\\Component\\HttpKernel\\Attribute\\MapDateTime' => __DIR__ . '/..' . '/symfony/http-kernel/Attribute/MapDateTime.php',
        '_ContaoManager\\Symfony\\Component\\HttpKernel\\Attribute\\MapQueryParameter' => __DIR__ . '/..' . '/symfony/http-kernel/Attribute/MapQueryParameter.php',
        '_ContaoManager\\Symfony\\Component\\HttpKernel\\Attribute\\MapQueryString' => __DIR__ . '/..' . '/symfony/http-kernel/Attribute/MapQueryString.php',
        '_ContaoManager\\Symfony\\Component\\HttpKernel\\Attribute\\MapRequestPayload' => __DIR__ . '/..' . '/symfony/http-kernel/Attribute/MapRequestPayload.php',
        '_ContaoManager\\Symfony\\Component\\HttpKernel\\Attribute\\ValueResolver' => __DIR__ . '/..' . '/symfony/http-kernel/Attribute/ValueResolver.php',
        '_ContaoManager\\Symfony\\Component\\HttpKernel\\Attribute\\WithHttpStatus' => __DIR__ . '/..' . '/symfony/http-kernel/Attribute/WithHttpStatus.php',
        '_ContaoManager\\Symfony\\Component\\HttpKernel\\Attribute\\WithLogLevel' => __DIR__ . '/..' . '/symfony/http-kernel/Attribute/WithLogLevel.php',
        '_ContaoManager\\Symfony\\Component\\HttpKernel\\Bundle\\AbstractBundle' => __DIR__ . '/..' . '/symfony/http-kernel/Bundle/AbstractBundle.php',
        '_ContaoManager\\Symfony\\Component\\HttpKernel\\Bundle\\Bundle' => __DIR__ . '/..' . '/symfony/http-kernel/Bundle/Bundle.php',
        '_ContaoManager\\Symfony\\Component\\HttpKernel\\Bundle\\BundleExtension' => __DIR__ . '/..' . '/symfony/http-kernel/Bundle/BundleExtension.php',
        '_ContaoManager\\Symfony\\Component\\HttpKernel\\Bundle\\BundleInterface' => __DIR__ . '/..' . '/symfony/http-kernel/Bundle/BundleInterface.php',
        '_ContaoManager\\Symfony\\Component\\HttpKernel\\CacheClearer\\CacheClearerInterface' => __DIR__ . '/..' . '/symfony/http-kernel/CacheClearer/CacheClearerInterface.php',
        '_ContaoManager\\Symfony\\Component\\HttpKernel\\CacheClearer\\ChainCacheClearer' => __DIR__ . '/..' . '/symfony/http-kernel/CacheClearer/ChainCacheClearer.php',
        '_ContaoManager\\Symfony\\Component\\HttpKernel\\CacheClearer\\Psr6CacheClearer' => __DIR__ . '/..' . '/symfony/http-kernel/CacheClearer/Psr6CacheClearer.php',
        '_ContaoManager\\Symfony\\Component\\HttpKernel\\CacheWarmer\\CacheWarmer' => __DIR__ . '/..' . '/symfony/http-kernel/CacheWarmer/CacheWarmer.php',
        '_ContaoManager\\Symfony\\Component\\HttpKernel\\CacheWarmer\\CacheWarmerAggregate' => __DIR__ . '/..' . '/symfony/http-kernel/CacheWarmer/CacheWarmerAggregate.php',
        '_ContaoManager\\Symfony\\Component\\HttpKernel\\CacheWarmer\\CacheWarmerInterface' => __DIR__ . '/..' . '/symfony/http-kernel/CacheWarmer/CacheWarmerInterface.php',
        '_ContaoManager\\Symfony\\Component\\HttpKernel\\CacheWarmer\\WarmableInterface' => __DIR__ . '/..' . '/symfony/http-kernel/CacheWarmer/WarmableInterface.php',
        '_ContaoManager\\Symfony\\Component\\HttpKernel\\Config\\FileLocator' => __DIR__ . '/..' . '/symfony/http-kernel/Config/FileLocator.php',
        '_ContaoManager\\Symfony\\Component\\HttpKernel\\ControllerMetadata\\ArgumentMetadata' => __DIR__ . '/..' . '/symfony/http-kernel/ControllerMetadata/ArgumentMetadata.php',
        '_ContaoManager\\Symfony\\Component\\HttpKernel\\ControllerMetadata\\ArgumentMetadataFactory' => __DIR__ . '/..' . '/symfony/http-kernel/ControllerMetadata/ArgumentMetadataFactory.php',
        '_ContaoManager\\Symfony\\Component\\HttpKernel\\ControllerMetadata\\ArgumentMetadataFactoryInterface' => __DIR__ . '/..' . '/symfony/http-kernel/ControllerMetadata/ArgumentMetadataFactoryInterface.php',
        '_ContaoManager\\Symfony\\Component\\HttpKernel\\Controller\\ArgumentResolver' => __DIR__ . '/..' . '/symfony/http-kernel/Controller/ArgumentResolver.php',
        '_ContaoManager\\Symfony\\Component\\HttpKernel\\Controller\\ArgumentResolverInterface' => __DIR__ . '/..' . '/symfony/http-kernel/Controller/ArgumentResolverInterface.php',
        '_ContaoManager\\Symfony\\Component\\HttpKernel\\Controller\\ArgumentResolver\\BackedEnumValueResolver' => __DIR__ . '/..' . '/symfony/http-kernel/Controller/ArgumentResolver/BackedEnumValueResolver.php',
        '_ContaoManager\\Symfony\\Component\\HttpKernel\\Controller\\ArgumentResolver\\DateTimeValueResolver' => __DIR__ . '/..' . '/symfony/http-kernel/Controller/ArgumentResolver/DateTimeValueResolver.php',
        '_ContaoManager\\Symfony\\Component\\HttpKernel\\Controller\\ArgumentResolver\\DefaultValueResolver' => __DIR__ . '/..' . '/symfony/http-kernel/Controller/ArgumentResolver/DefaultValueResolver.php',
        '_ContaoManager\\Symfony\\Component\\HttpKernel\\Controller\\ArgumentResolver\\NotTaggedControllerValueResolver' => __DIR__ . '/..' . '/symfony/http-kernel/Controller/ArgumentResolver/NotTaggedControllerValueResolver.php',
        '_ContaoManager\\Symfony\\Component\\HttpKernel\\Controller\\ArgumentResolver\\QueryParameterValueResolver' => __DIR__ . '/..' . '/symfony/http-kernel/Controller/ArgumentResolver/QueryParameterValueResolver.php',
        '_ContaoManager\\Symfony\\Component\\HttpKernel\\Controller\\ArgumentResolver\\RequestAttributeValueResolver' => __DIR__ . '/..' . '/symfony/http-kernel/Controller/ArgumentResolver/RequestAttributeValueResolver.php',
        '_ContaoManager\\Symfony\\Component\\HttpKernel\\Controller\\ArgumentResolver\\RequestPayloadValueResolver' => __DIR__ . '/..' . '/symfony/http-kernel/Controller/ArgumentResolver/RequestPayloadValueResolver.php',
        '_ContaoManager\\Symfony\\Component\\HttpKernel\\Controller\\ArgumentResolver\\RequestValueResolver' => __DIR__ . '/..' . '/symfony/http-kernel/Controller/ArgumentResolver/RequestValueResolver.php',
        '_ContaoManager\\Symfony\\Component\\HttpKernel\\Controller\\ArgumentResolver\\ServiceValueResolver' => __DIR__ . '/..' . '/symfony/http-kernel/Controller/ArgumentResolver/ServiceValueResolver.php',
        '_ContaoManager\\Symfony\\Component\\HttpKernel\\Controller\\ArgumentResolver\\SessionValueResolver' => __DIR__ . '/..' . '/symfony/http-kernel/Controller/ArgumentResolver/SessionValueResolver.php',
        '_ContaoManager\\Symfony\\Component\\HttpKernel\\Controller\\ArgumentResolver\\TraceableValueResolver' => __DIR__ . '/..' . '/symfony/http-kernel/Controller/ArgumentResolver/TraceableValueResolver.php',
        '_ContaoManager\\Symfony\\Component\\HttpKernel\\Controller\\ArgumentResolver\\UidValueResolver' => __DIR__ . '/..' . '/symfony/http-kernel/Controller/ArgumentResolver/UidValueResolver.php',
        '_ContaoManager\\Symfony\\Component\\HttpKernel\\Controller\\ArgumentResolver\\VariadicValueResolver' => __DIR__ . '/..' . '/symfony/http-kernel/Controller/ArgumentResolver/VariadicValueResolver.php',
        '_ContaoManager\\Symfony\\Component\\HttpKernel\\Controller\\ArgumentValueResolverInterface' => __DIR__ . '/..' . '/symfony/http-kernel/Controller/ArgumentValueResolverInterface.php',
        '_ContaoManager\\Symfony\\Component\\HttpKernel\\Controller\\ContainerControllerResolver' => __DIR__ . '/..' . '/symfony/http-kernel/Controller/ContainerControllerResolver.php',
        '_ContaoManager\\Symfony\\Component\\HttpKernel\\Controller\\ControllerReference' => __DIR__ . '/..' . '/symfony/http-kernel/Controller/ControllerReference.php',
        '_ContaoManager\\Symfony\\Component\\HttpKernel\\Controller\\ControllerResolver' => __DIR__ . '/..' . '/symfony/http-kernel/Controller/ControllerResolver.php',
        '_ContaoManager\\Symfony\\Component\\HttpKernel\\Controller\\ControllerResolverInterface' => __DIR__ . '/..' . '/symfony/http-kernel/Controller/ControllerResolverInterface.php',
        '_ContaoManager\\Symfony\\Component\\HttpKernel\\Controller\\ErrorController' => __DIR__ . '/..' . '/symfony/http-kernel/Controller/ErrorController.php',
        '_ContaoManager\\Symfony\\Component\\HttpKernel\\Controller\\TraceableArgumentResolver' => __DIR__ . '/..' . '/symfony/http-kernel/Controller/TraceableArgumentResolver.php',
        '_ContaoManager\\Symfony\\Component\\HttpKernel\\Controller\\TraceableControllerResolver' => __DIR__ . '/..' . '/symfony/http-kernel/Controller/TraceableControllerResolver.php',
        '_ContaoManager\\Symfony\\Component\\HttpKernel\\Controller\\ValueResolverInterface' => __DIR__ . '/..' . '/symfony/http-kernel/Controller/ValueResolverInterface.php',
        '_ContaoManager\\Symfony\\Component\\HttpKernel\\DataCollector\\AjaxDataCollector' => __DIR__ . '/..' . '/symfony/http-kernel/DataCollector/AjaxDataCollector.php',
        '_ContaoManager\\Symfony\\Component\\HttpKernel\\DataCollector\\ConfigDataCollector' => __DIR__ . '/..' . '/symfony/http-kernel/DataCollector/ConfigDataCollector.php',
        '_ContaoManager\\Symfony\\Component\\HttpKernel\\DataCollector\\DataCollector' => __DIR__ . '/..' . '/symfony/http-kernel/DataCollector/DataCollector.php',
        '_ContaoManager\\Symfony\\Component\\HttpKernel\\DataCollector\\DataCollectorInterface' => __DIR__ . '/..' . '/symfony/http-kernel/DataCollector/DataCollectorInterface.php',
        '_ContaoManager\\Symfony\\Component\\HttpKernel\\DataCollector\\DumpDataCollector' => __DIR__ . '/..' . '/symfony/http-kernel/DataCollector/DumpDataCollector.php',
        '_ContaoManager\\Symfony\\Component\\HttpKernel\\DataCollector\\EventDataCollector' => __DIR__ . '/..' . '/symfony/http-kernel/DataCollector/EventDataCollector.php',
        '_ContaoManager\\Symfony\\Component\\HttpKernel\\DataCollector\\ExceptionDataCollector' => __DIR__ . '/..' . '/symfony/http-kernel/DataCollector/ExceptionDataCollector.php',
        '_ContaoManager\\Symfony\\Component\\HttpKernel\\DataCollector\\LateDataCollectorInterface' => __DIR__ . '/..' . '/symfony/http-kernel/DataCollector/LateDataCollectorInterface.php',
        '_ContaoManager\\Symfony\\Component\\HttpKernel\\DataCollector\\LoggerDataCollector' => __DIR__ . '/..' . '/symfony/http-kernel/DataCollector/LoggerDataCollector.php',
        '_ContaoManager\\Symfony\\Component\\HttpKernel\\DataCollector\\MemoryDataCollector' => __DIR__ . '/..' . '/symfony/http-kernel/DataCollector/MemoryDataCollector.php',
        '_ContaoManager\\Symfony\\Component\\HttpKernel\\DataCollector\\RequestDataCollector' => __DIR__ . '/..' . '/symfony/http-kernel/DataCollector/RequestDataCollector.php',
        '_ContaoManager\\Symfony\\Component\\HttpKernel\\DataCollector\\RouterDataCollector' => __DIR__ . '/..' . '/symfony/http-kernel/DataCollector/RouterDataCollector.php',
        '_ContaoManager\\Symfony\\Component\\HttpKernel\\DataCollector\\TimeDataCollector' => __DIR__ . '/..' . '/symfony/http-kernel/DataCollector/TimeDataCollector.php',
        '_ContaoManager\\Symfony\\Component\\HttpKernel\\Debug\\ErrorHandlerConfigurator' => __DIR__ . '/..' . '/symfony/http-kernel/Debug/ErrorHandlerConfigurator.php',
        '_ContaoManager\\Symfony\\Component\\HttpKernel\\Debug\\FileLinkFormatter' => __DIR__ . '/..' . '/symfony/http-kernel/Debug/FileLinkFormatter.php',
        '_ContaoManager\\Symfony\\Component\\HttpKernel\\Debug\\TraceableEventDispatcher' => __DIR__ . '/..' . '/symfony/http-kernel/Debug/TraceableEventDispatcher.php',
        '_ContaoManager\\Symfony\\Component\\HttpKernel\\Debug\\VirtualRequestStack' => __DIR__ . '/..' . '/symfony/http-kernel/Debug/VirtualRequestStack.php',
        '_ContaoManager\\Symfony\\Component\\HttpKernel\\DependencyInjection\\AddAnnotatedClassesToCachePass' => __DIR__ . '/..' . '/symfony/http-kernel/DependencyInjection/AddAnnotatedClassesToCachePass.php',
        '_ContaoManager\\Symfony\\Component\\HttpKernel\\DependencyInjection\\ConfigurableExtension' => __DIR__ . '/..' . '/symfony/http-kernel/DependencyInjection/ConfigurableExtension.php',
        '_ContaoManager\\Symfony\\Component\\HttpKernel\\DependencyInjection\\ControllerArgumentValueResolverPass' => __DIR__ . '/..' . '/symfony/http-kernel/DependencyInjection/ControllerArgumentValueResolverPass.php',
        '_ContaoManager\\Symfony\\Component\\HttpKernel\\DependencyInjection\\Extension' => __DIR__ . '/..' . '/symfony/http-kernel/DependencyInjection/Extension.php',
        '_ContaoManager\\Symfony\\Component\\HttpKernel\\DependencyInjection\\FragmentRendererPass' => __DIR__ . '/..' . '/symfony/http-kernel/DependencyInjection/FragmentRendererPass.php',
        '_ContaoManager\\Symfony\\Component\\HttpKernel\\DependencyInjection\\LazyLoadingFragmentHandler' => __DIR__ . '/..' . '/symfony/http-kernel/DependencyInjection/LazyLoadingFragmentHandler.php',
        '_ContaoManager\\Symfony\\Component\\HttpKernel\\DependencyInjection\\LoggerPass' => __DIR__ . '/..' . '/symfony/http-kernel/DependencyInjection/LoggerPass.php',
        '_ContaoManager\\Symfony\\Component\\HttpKernel\\DependencyInjection\\MergeExtensionConfigurationPass' => __DIR__ . '/..' . '/symfony/http-kernel/DependencyInjection/MergeExtensionConfigurationPass.php',
        '_ContaoManager\\Symfony\\Component\\HttpKernel\\DependencyInjection\\RegisterControllerArgumentLocatorsPass' => __DIR__ . '/..' . '/symfony/http-kernel/DependencyInjection/RegisterControllerArgumentLocatorsPass.php',
        '_ContaoManager\\Symfony\\Component\\HttpKernel\\DependencyInjection\\RegisterLocaleAwareServicesPass' => __DIR__ . '/..' . '/symfony/http-kernel/DependencyInjection/RegisterLocaleAwareServicesPass.php',
        '_ContaoManager\\Symfony\\Component\\HttpKernel\\DependencyInjection\\RemoveEmptyControllerArgumentLocatorsPass' => __DIR__ . '/..' . '/symfony/http-kernel/DependencyInjection/RemoveEmptyControllerArgumentLocatorsPass.php',
        '_ContaoManager\\Symfony\\Component\\HttpKernel\\DependencyInjection\\ResettableServicePass' => __DIR__ . '/..' . '/symfony/http-kernel/DependencyInjection/ResettableServicePass.php',
        '_ContaoManager\\Symfony\\Component\\HttpKernel\\DependencyInjection\\ServicesResetter' => __DIR__ . '/..' . '/symfony/http-kernel/DependencyInjection/ServicesResetter.php',
        '_ContaoManager\\Symfony\\Component\\HttpKernel\\EventListener\\AbstractSessionListener' => __DIR__ . '/..' . '/symfony/http-kernel/EventListener/AbstractSessionListener.php',
        '_ContaoManager\\Symfony\\Component\\HttpKernel\\EventListener\\AddRequestFormatsListener' => __DIR__ . '/..' . '/symfony/http-kernel/EventListener/AddRequestFormatsListener.php',
        '_ContaoManager\\Symfony\\Component\\HttpKernel\\EventListener\\CacheAttributeListener' => __DIR__ . '/..' . '/symfony/http-kernel/EventListener/CacheAttributeListener.php',
        '_ContaoManager\\Symfony\\Component\\HttpKernel\\EventListener\\DebugHandlersListener' => __DIR__ . '/..' . '/symfony/http-kernel/EventListener/DebugHandlersListener.php',
        '_ContaoManager\\Symfony\\Component\\HttpKernel\\EventListener\\DisallowRobotsIndexingListener' => __DIR__ . '/..' . '/symfony/http-kernel/EventListener/DisallowRobotsIndexingListener.php',
        '_ContaoManager\\Symfony\\Component\\HttpKernel\\EventListener\\DumpListener' => __DIR__ . '/..' . '/symfony/http-kernel/EventListener/DumpListener.php',
        '_ContaoManager\\Symfony\\Component\\HttpKernel\\EventListener\\ErrorListener' => __DIR__ . '/..' . '/symfony/http-kernel/EventListener/ErrorListener.php',
        '_ContaoManager\\Symfony\\Component\\HttpKernel\\EventListener\\FragmentListener' => __DIR__ . '/..' . '/symfony/http-kernel/EventListener/FragmentListener.php',
        '_ContaoManager\\Symfony\\Component\\HttpKernel\\EventListener\\LocaleAwareListener' => __DIR__ . '/..' . '/symfony/http-kernel/EventListener/LocaleAwareListener.php',
        '_ContaoManager\\Symfony\\Component\\HttpKernel\\EventListener\\LocaleListener' => __DIR__ . '/..' . '/symfony/http-kernel/EventListener/LocaleListener.php',
        '_ContaoManager\\Symfony\\Component\\HttpKernel\\EventListener\\ProfilerListener' => __DIR__ . '/..' . '/symfony/http-kernel/EventListener/ProfilerListener.php',
        '_ContaoManager\\Symfony\\Component\\HttpKernel\\EventListener\\ResponseListener' => __DIR__ . '/..' . '/symfony/http-kernel/EventListener/ResponseListener.php',
        '_ContaoManager\\Symfony\\Component\\HttpKernel\\EventListener\\RouterListener' => __DIR__ . '/..' . '/symfony/http-kernel/EventListener/RouterListener.php',
        '_ContaoManager\\Symfony\\Component\\HttpKernel\\EventListener\\SessionListener' => __DIR__ . '/..' . '/symfony/http-kernel/EventListener/SessionListener.php',
        '_ContaoManager\\Symfony\\Component\\HttpKernel\\EventListener\\StreamedResponseListener' => __DIR__ . '/..' . '/symfony/http-kernel/EventListener/StreamedResponseListener.php',
        '_ContaoManager\\Symfony\\Component\\HttpKernel\\EventListener\\SurrogateListener' => __DIR__ . '/..' . '/symfony/http-kernel/EventListener/SurrogateListener.php',
        '_ContaoManager\\Symfony\\Component\\HttpKernel\\EventListener\\ValidateRequestListener' => __DIR__ . '/..' . '/symfony/http-kernel/EventListener/ValidateRequestListener.php',
        '_ContaoManager\\Symfony\\Component\\HttpKernel\\Event\\ControllerArgumentsEvent' => __DIR__ . '/..' . '/symfony/http-kernel/Event/ControllerArgumentsEvent.php',
        '_ContaoManager\\Symfony\\Component\\HttpKernel\\Event\\ControllerEvent' => __DIR__ . '/..' . '/symfony/http-kernel/Event/ControllerEvent.php',
        '_ContaoManager\\Symfony\\Component\\HttpKernel\\Event\\ExceptionEvent' => __DIR__ . '/..' . '/symfony/http-kernel/Event/ExceptionEvent.php',
        '_ContaoManager\\Symfony\\Component\\HttpKernel\\Event\\FinishRequestEvent' => __DIR__ . '/..' . '/symfony/http-kernel/Event/FinishRequestEvent.php',
        '_ContaoManager\\Symfony\\Component\\HttpKernel\\Event\\KernelEvent' => __DIR__ . '/..' . '/symfony/http-kernel/Event/KernelEvent.php',
        '_ContaoManager\\Symfony\\Component\\HttpKernel\\Event\\RequestEvent' => __DIR__ . '/..' . '/symfony/http-kernel/Event/RequestEvent.php',
        '_ContaoManager\\Symfony\\Component\\HttpKernel\\Event\\ResponseEvent' => __DIR__ . '/..' . '/symfony/http-kernel/Event/ResponseEvent.php',
        '_ContaoManager\\Symfony\\Component\\HttpKernel\\Event\\TerminateEvent' => __DIR__ . '/..' . '/symfony/http-kernel/Event/TerminateEvent.php',
        '_ContaoManager\\Symfony\\Component\\HttpKernel\\Event\\ViewEvent' => __DIR__ . '/..' . '/symfony/http-kernel/Event/ViewEvent.php',
        '_ContaoManager\\Symfony\\Component\\HttpKernel\\Exception\\AccessDeniedHttpException' => __DIR__ . '/..' . '/symfony/http-kernel/Exception/AccessDeniedHttpException.php',
        '_ContaoManager\\Symfony\\Component\\HttpKernel\\Exception\\BadRequestHttpException' => __DIR__ . '/..' . '/symfony/http-kernel/Exception/BadRequestHttpException.php',
        '_ContaoManager\\Symfony\\Component\\HttpKernel\\Exception\\ConflictHttpException' => __DIR__ . '/..' . '/symfony/http-kernel/Exception/ConflictHttpException.php',
        '_ContaoManager\\Symfony\\Component\\HttpKernel\\Exception\\ControllerDoesNotReturnResponseException' => __DIR__ . '/..' . '/symfony/http-kernel/Exception/ControllerDoesNotReturnResponseException.php',
        '_ContaoManager\\Symfony\\Component\\HttpKernel\\Exception\\GoneHttpException' => __DIR__ . '/..' . '/symfony/http-kernel/Exception/GoneHttpException.php',
        '_ContaoManager\\Symfony\\Component\\HttpKernel\\Exception\\HttpException' => __DIR__ . '/..' . '/symfony/http-kernel/Exception/HttpException.php',
        '_ContaoManager\\Symfony\\Component\\HttpKernel\\Exception\\HttpExceptionInterface' => __DIR__ . '/..' . '/symfony/http-kernel/Exception/HttpExceptionInterface.php',
        '_ContaoManager\\Symfony\\Component\\HttpKernel\\Exception\\InvalidMetadataException' => __DIR__ . '/..' . '/symfony/http-kernel/Exception/InvalidMetadataException.php',
        '_ContaoManager\\Symfony\\Component\\HttpKernel\\Exception\\LengthRequiredHttpException' => __DIR__ . '/..' . '/symfony/http-kernel/Exception/LengthRequiredHttpException.php',
        '_ContaoManager\\Symfony\\Component\\HttpKernel\\Exception\\LockedHttpException' => __DIR__ . '/..' . '/symfony/http-kernel/Exception/LockedHttpException.php',
        '_ContaoManager\\Symfony\\Component\\HttpKernel\\Exception\\MethodNotAllowedHttpException' => __DIR__ . '/..' . '/symfony/http-kernel/Exception/MethodNotAllowedHttpException.php',
        '_ContaoManager\\Symfony\\Component\\HttpKernel\\Exception\\NotAcceptableHttpException' => __DIR__ . '/..' . '/symfony/http-kernel/Exception/NotAcceptableHttpException.php',
        '_ContaoManager\\Symfony\\Component\\HttpKernel\\Exception\\NotFoundHttpException' => __DIR__ . '/..' . '/symfony/http-kernel/Exception/NotFoundHttpException.php',
        '_ContaoManager\\Symfony\\Component\\HttpKernel\\Exception\\PreconditionFailedHttpException' => __DIR__ . '/..' . '/symfony/http-kernel/Exception/PreconditionFailedHttpException.php',
        '_ContaoManager\\Symfony\\Component\\HttpKernel\\Exception\\PreconditionRequiredHttpException' => __DIR__ . '/..' . '/symfony/http-kernel/Exception/PreconditionRequiredHttpException.php',
        '_ContaoManager\\Symfony\\Component\\HttpKernel\\Exception\\ResolverNotFoundException' => __DIR__ . '/..' . '/symfony/http-kernel/Exception/ResolverNotFoundException.php',
        '_ContaoManager\\Symfony\\Component\\HttpKernel\\Exception\\ServiceUnavailableHttpException' => __DIR__ . '/..' . '/symfony/http-kernel/Exception/ServiceUnavailableHttpException.php',
        '_ContaoManager\\Symfony\\Component\\HttpKernel\\Exception\\TooManyRequestsHttpException' => __DIR__ . '/..' . '/symfony/http-kernel/Exception/TooManyRequestsHttpException.php',
        '_ContaoManager\\Symfony\\Component\\HttpKernel\\Exception\\UnauthorizedHttpException' => __DIR__ . '/..' . '/symfony/http-kernel/Exception/UnauthorizedHttpException.php',
        '_ContaoManager\\Symfony\\Component\\HttpKernel\\Exception\\UnexpectedSessionUsageException' => __DIR__ . '/..' . '/symfony/http-kernel/Exception/UnexpectedSessionUsageException.php',
        '_ContaoManager\\Symfony\\Component\\HttpKernel\\Exception\\UnprocessableEntityHttpException' => __DIR__ . '/..' . '/symfony/http-kernel/Exception/UnprocessableEntityHttpException.php',
        '_ContaoManager\\Symfony\\Component\\HttpKernel\\Exception\\UnsupportedMediaTypeHttpException' => __DIR__ . '/..' . '/symfony/http-kernel/Exception/UnsupportedMediaTypeHttpException.php',
        '_ContaoManager\\Symfony\\Component\\HttpKernel\\Fragment\\AbstractSurrogateFragmentRenderer' => __DIR__ . '/..' . '/symfony/http-kernel/Fragment/AbstractSurrogateFragmentRenderer.php',
        '_ContaoManager\\Symfony\\Component\\HttpKernel\\Fragment\\EsiFragmentRenderer' => __DIR__ . '/..' . '/symfony/http-kernel/Fragment/EsiFragmentRenderer.php',
        '_ContaoManager\\Symfony\\Component\\HttpKernel\\Fragment\\FragmentHandler' => __DIR__ . '/..' . '/symfony/http-kernel/Fragment/FragmentHandler.php',
        '_ContaoManager\\Symfony\\Component\\HttpKernel\\Fragment\\FragmentRendererInterface' => __DIR__ . '/..' . '/symfony/http-kernel/Fragment/FragmentRendererInterface.php',
        '_ContaoManager\\Symfony\\Component\\HttpKernel\\Fragment\\FragmentUriGenerator' => __DIR__ . '/..' . '/symfony/http-kernel/Fragment/FragmentUriGenerator.php',
        '_ContaoManager\\Symfony\\Component\\HttpKernel\\Fragment\\FragmentUriGeneratorInterface' => __DIR__ . '/..' . '/symfony/http-kernel/Fragment/FragmentUriGeneratorInterface.php',
        '_ContaoManager\\Symfony\\Component\\HttpKernel\\Fragment\\HIncludeFragmentRenderer' => __DIR__ . '/..' . '/symfony/http-kernel/Fragment/HIncludeFragmentRenderer.php',
        '_ContaoManager\\Symfony\\Component\\HttpKernel\\Fragment\\InlineFragmentRenderer' => __DIR__ . '/..' . '/symfony/http-kernel/Fragment/InlineFragmentRenderer.php',
        '_ContaoManager\\Symfony\\Component\\HttpKernel\\Fragment\\RoutableFragmentRenderer' => __DIR__ . '/..' . '/symfony/http-kernel/Fragment/RoutableFragmentRenderer.php',
        '_ContaoManager\\Symfony\\Component\\HttpKernel\\Fragment\\SsiFragmentRenderer' => __DIR__ . '/..' . '/symfony/http-kernel/Fragment/SsiFragmentRenderer.php',
        '_ContaoManager\\Symfony\\Component\\HttpKernel\\HttpCache\\AbstractSurrogate' => __DIR__ . '/..' . '/symfony/http-kernel/HttpCache/AbstractSurrogate.php',
        '_ContaoManager\\Symfony\\Component\\HttpKernel\\HttpCache\\CacheWasLockedException' => __DIR__ . '/..' . '/symfony/http-kernel/HttpCache/CacheWasLockedException.php',
        '_ContaoManager\\Symfony\\Component\\HttpKernel\\HttpCache\\Esi' => __DIR__ . '/..' . '/symfony/http-kernel/HttpCache/Esi.php',
        '_ContaoManager\\Symfony\\Component\\HttpKernel\\HttpCache\\HttpCache' => __DIR__ . '/..' . '/symfony/http-kernel/HttpCache/HttpCache.php',
        '_ContaoManager\\Symfony\\Component\\HttpKernel\\HttpCache\\ResponseCacheStrategy' => __DIR__ . '/..' . '/symfony/http-kernel/HttpCache/ResponseCacheStrategy.php',
        '_ContaoManager\\Symfony\\Component\\HttpKernel\\HttpCache\\ResponseCacheStrategyInterface' => __DIR__ . '/..' . '/symfony/http-kernel/HttpCache/ResponseCacheStrategyInterface.php',
        '_ContaoManager\\Symfony\\Component\\HttpKernel\\HttpCache\\Ssi' => __DIR__ . '/..' . '/symfony/http-kernel/HttpCache/Ssi.php',
        '_ContaoManager\\Symfony\\Component\\HttpKernel\\HttpCache\\Store' => __DIR__ . '/..' . '/symfony/http-kernel/HttpCache/Store.php',
        '_ContaoManager\\Symfony\\Component\\HttpKernel\\HttpCache\\StoreInterface' => __DIR__ . '/..' . '/symfony/http-kernel/HttpCache/StoreInterface.php',
        '_ContaoManager\\Symfony\\Component\\HttpKernel\\HttpCache\\SubRequestHandler' => __DIR__ . '/..' . '/symfony/http-kernel/HttpCache/SubRequestHandler.php',
        '_ContaoManager\\Symfony\\Component\\HttpKernel\\HttpCache\\SurrogateInterface' => __DIR__ . '/..' . '/symfony/http-kernel/HttpCache/SurrogateInterface.php',
        '_ContaoManager\\Symfony\\Component\\HttpKernel\\HttpClientKernel' => __DIR__ . '/..' . '/symfony/http-kernel/HttpClientKernel.php',
        '_ContaoManager\\Symfony\\Component\\HttpKernel\\HttpKernel' => __DIR__ . '/..' . '/symfony/http-kernel/HttpKernel.php',
        '_ContaoManager\\Symfony\\Component\\HttpKernel\\HttpKernelBrowser' => __DIR__ . '/..' . '/symfony/http-kernel/HttpKernelBrowser.php',
        '_ContaoManager\\Symfony\\Component\\HttpKernel\\HttpKernelInterface' => __DIR__ . '/..' . '/symfony/http-kernel/HttpKernelInterface.php',
        '_ContaoManager\\Symfony\\Component\\HttpKernel\\Kernel' => __DIR__ . '/..' . '/symfony/http-kernel/Kernel.php',
        '_ContaoManager\\Symfony\\Component\\HttpKernel\\KernelEvents' => __DIR__ . '/..' . '/symfony/http-kernel/KernelEvents.php',
        '_ContaoManager\\Symfony\\Component\\HttpKernel\\KernelInterface' => __DIR__ . '/..' . '/symfony/http-kernel/KernelInterface.php',
        '_ContaoManager\\Symfony\\Component\\HttpKernel\\Log\\DebugLoggerConfigurator' => __DIR__ . '/..' . '/symfony/http-kernel/Log/DebugLoggerConfigurator.php',
        '_ContaoManager\\Symfony\\Component\\HttpKernel\\Log\\DebugLoggerInterface' => __DIR__ . '/..' . '/symfony/http-kernel/Log/DebugLoggerInterface.php',
        '_ContaoManager\\Symfony\\Component\\HttpKernel\\Log\\Logger' => __DIR__ . '/..' . '/symfony/http-kernel/Log/Logger.php',
        '_ContaoManager\\Symfony\\Component\\HttpKernel\\Profiler\\FileProfilerStorage' => __DIR__ . '/..' . '/symfony/http-kernel/Profiler/FileProfilerStorage.php',
        '_ContaoManager\\Symfony\\Component\\HttpKernel\\Profiler\\Profile' => __DIR__ . '/..' . '/symfony/http-kernel/Profiler/Profile.php',
        '_ContaoManager\\Symfony\\Component\\HttpKernel\\Profiler\\Profiler' => __DIR__ . '/..' . '/symfony/http-kernel/Profiler/Profiler.php',
        '_ContaoManager\\Symfony\\Component\\HttpKernel\\Profiler\\ProfilerStorageInterface' => __DIR__ . '/..' . '/symfony/http-kernel/Profiler/ProfilerStorageInterface.php',
        '_ContaoManager\\Symfony\\Component\\HttpKernel\\RebootableInterface' => __DIR__ . '/..' . '/symfony/http-kernel/RebootableInterface.php',
        '_ContaoManager\\Symfony\\Component\\HttpKernel\\TerminableInterface' => __DIR__ . '/..' . '/symfony/http-kernel/TerminableInterface.php',
        '_ContaoManager\\Symfony\\Component\\HttpKernel\\UriSigner' => __DIR__ . '/..' . '/symfony/http-kernel/UriSigner.php',
        '_ContaoManager\\Symfony\\Component\\PasswordHasher\\Command\\UserPasswordHashCommand' => __DIR__ . '/..' . '/symfony/password-hasher/Command/UserPasswordHashCommand.php',
        '_ContaoManager\\Symfony\\Component\\PasswordHasher\\Exception\\ExceptionInterface' => __DIR__ . '/..' . '/symfony/password-hasher/Exception/ExceptionInterface.php',
        '_ContaoManager\\Symfony\\Component\\PasswordHasher\\Exception\\InvalidPasswordException' => __DIR__ . '/..' . '/symfony/password-hasher/Exception/InvalidPasswordException.php',
        '_ContaoManager\\Symfony\\Component\\PasswordHasher\\Exception\\LogicException' => __DIR__ . '/..' . '/symfony/password-hasher/Exception/LogicException.php',
        '_ContaoManager\\Symfony\\Component\\PasswordHasher\\Hasher\\CheckPasswordLengthTrait' => __DIR__ . '/..' . '/symfony/password-hasher/Hasher/CheckPasswordLengthTrait.php',
        '_ContaoManager\\Symfony\\Component\\PasswordHasher\\Hasher\\MessageDigestPasswordHasher' => __DIR__ . '/..' . '/symfony/password-hasher/Hasher/MessageDigestPasswordHasher.php',
        '_ContaoManager\\Symfony\\Component\\PasswordHasher\\Hasher\\MigratingPasswordHasher' => __DIR__ . '/..' . '/symfony/password-hasher/Hasher/MigratingPasswordHasher.php',
        '_ContaoManager\\Symfony\\Component\\PasswordHasher\\Hasher\\NativePasswordHasher' => __DIR__ . '/..' . '/symfony/password-hasher/Hasher/NativePasswordHasher.php',
        '_ContaoManager\\Symfony\\Component\\PasswordHasher\\Hasher\\PasswordHasherAwareInterface' => __DIR__ . '/..' . '/symfony/password-hasher/Hasher/PasswordHasherAwareInterface.php',
        '_ContaoManager\\Symfony\\Component\\PasswordHasher\\Hasher\\PasswordHasherFactory' => __DIR__ . '/..' . '/symfony/password-hasher/Hasher/PasswordHasherFactory.php',
        '_ContaoManager\\Symfony\\Component\\PasswordHasher\\Hasher\\PasswordHasherFactoryInterface' => __DIR__ . '/..' . '/symfony/password-hasher/Hasher/PasswordHasherFactoryInterface.php',
        '_ContaoManager\\Symfony\\Component\\PasswordHasher\\Hasher\\Pbkdf2PasswordHasher' => __DIR__ . '/..' . '/symfony/password-hasher/Hasher/Pbkdf2PasswordHasher.php',
        '_ContaoManager\\Symfony\\Component\\PasswordHasher\\Hasher\\PlaintextPasswordHasher' => __DIR__ . '/..' . '/symfony/password-hasher/Hasher/PlaintextPasswordHasher.php',
        '_ContaoManager\\Symfony\\Component\\PasswordHasher\\Hasher\\SodiumPasswordHasher' => __DIR__ . '/..' . '/symfony/password-hasher/Hasher/SodiumPasswordHasher.php',
        '_ContaoManager\\Symfony\\Component\\PasswordHasher\\Hasher\\UserPasswordHasher' => __DIR__ . '/..' . '/symfony/password-hasher/Hasher/UserPasswordHasher.php',
        '_ContaoManager\\Symfony\\Component\\PasswordHasher\\Hasher\\UserPasswordHasherInterface' => __DIR__ . '/..' . '/symfony/password-hasher/Hasher/UserPasswordHasherInterface.php',
        '_ContaoManager\\Symfony\\Component\\PasswordHasher\\LegacyPasswordHasherInterface' => __DIR__ . '/..' . '/symfony/password-hasher/LegacyPasswordHasherInterface.php',
        '_ContaoManager\\Symfony\\Component\\PasswordHasher\\PasswordHasherInterface' => __DIR__ . '/..' . '/symfony/password-hasher/PasswordHasherInterface.php',
        '_ContaoManager\\Symfony\\Component\\Process\\Exception\\ExceptionInterface' => __DIR__ . '/..' . '/symfony/process/Exception/ExceptionInterface.php',
        '_ContaoManager\\Symfony\\Component\\Process\\Exception\\InvalidArgumentException' => __DIR__ . '/..' . '/symfony/process/Exception/InvalidArgumentException.php',
        '_ContaoManager\\Symfony\\Component\\Process\\Exception\\LogicException' => __DIR__ . '/..' . '/symfony/process/Exception/LogicException.php',
        '_ContaoManager\\Symfony\\Component\\Process\\Exception\\ProcessFailedException' => __DIR__ . '/..' . '/symfony/process/Exception/ProcessFailedException.php',
        '_ContaoManager\\Symfony\\Component\\Process\\Exception\\ProcessSignaledException' => __DIR__ . '/..' . '/symfony/process/Exception/ProcessSignaledException.php',
        '_ContaoManager\\Symfony\\Component\\Process\\Exception\\ProcessTimedOutException' => __DIR__ . '/..' . '/symfony/process/Exception/ProcessTimedOutException.php',
        '_ContaoManager\\Symfony\\Component\\Process\\Exception\\RunProcessFailedException' => __DIR__ . '/..' . '/symfony/process/Exception/RunProcessFailedException.php',
        '_ContaoManager\\Symfony\\Component\\Process\\Exception\\RuntimeException' => __DIR__ . '/..' . '/symfony/process/Exception/RuntimeException.php',
        '_ContaoManager\\Symfony\\Component\\Process\\ExecutableFinder' => __DIR__ . '/..' . '/symfony/process/ExecutableFinder.php',
        '_ContaoManager\\Symfony\\Component\\Process\\InputStream' => __DIR__ . '/..' . '/symfony/process/InputStream.php',
        '_ContaoManager\\Symfony\\Component\\Process\\Messenger\\RunProcessContext' => __DIR__ . '/..' . '/symfony/process/Messenger/RunProcessContext.php',
        '_ContaoManager\\Symfony\\Component\\Process\\Messenger\\RunProcessMessage' => __DIR__ . '/..' . '/symfony/process/Messenger/RunProcessMessage.php',
        '_ContaoManager\\Symfony\\Component\\Process\\Messenger\\RunProcessMessageHandler' => __DIR__ . '/..' . '/symfony/process/Messenger/RunProcessMessageHandler.php',
        '_ContaoManager\\Symfony\\Component\\Process\\PhpExecutableFinder' => __DIR__ . '/..' . '/symfony/process/PhpExecutableFinder.php',
        '_ContaoManager\\Symfony\\Component\\Process\\PhpProcess' => __DIR__ . '/..' . '/symfony/process/PhpProcess.php',
        '_ContaoManager\\Symfony\\Component\\Process\\PhpSubprocess' => __DIR__ . '/..' . '/symfony/process/PhpSubprocess.php',
        '_ContaoManager\\Symfony\\Component\\Process\\Pipes\\AbstractPipes' => __DIR__ . '/..' . '/symfony/process/Pipes/AbstractPipes.php',
        '_ContaoManager\\Symfony\\Component\\Process\\Pipes\\PipesInterface' => __DIR__ . '/..' . '/symfony/process/Pipes/PipesInterface.php',
        '_ContaoManager\\Symfony\\Component\\Process\\Pipes\\UnixPipes' => __DIR__ . '/..' . '/symfony/process/Pipes/UnixPipes.php',
        '_ContaoManager\\Symfony\\Component\\Process\\Pipes\\WindowsPipes' => __DIR__ . '/..' . '/symfony/process/Pipes/WindowsPipes.php',
        '_ContaoManager\\Symfony\\Component\\Process\\Process' => __DIR__ . '/..' . '/symfony/process/Process.php',
        '_ContaoManager\\Symfony\\Component\\Process\\ProcessUtils' => __DIR__ . '/..' . '/symfony/process/ProcessUtils.php',
        '_ContaoManager\\Symfony\\Component\\PropertyAccess\\Exception\\AccessException' => __DIR__ . '/..' . '/symfony/property-access/Exception/AccessException.php',
        '_ContaoManager\\Symfony\\Component\\PropertyAccess\\Exception\\ExceptionInterface' => __DIR__ . '/..' . '/symfony/property-access/Exception/ExceptionInterface.php',
        '_ContaoManager\\Symfony\\Component\\PropertyAccess\\Exception\\InvalidArgumentException' => __DIR__ . '/..' . '/symfony/property-access/Exception/InvalidArgumentException.php',
        '_ContaoManager\\Symfony\\Component\\PropertyAccess\\Exception\\InvalidPropertyPathException' => __DIR__ . '/..' . '/symfony/property-access/Exception/InvalidPropertyPathException.php',
        '_ContaoManager\\Symfony\\Component\\PropertyAccess\\Exception\\NoSuchIndexException' => __DIR__ . '/..' . '/symfony/property-access/Exception/NoSuchIndexException.php',
        '_ContaoManager\\Symfony\\Component\\PropertyAccess\\Exception\\NoSuchPropertyException' => __DIR__ . '/..' . '/symfony/property-access/Exception/NoSuchPropertyException.php',
        '_ContaoManager\\Symfony\\Component\\PropertyAccess\\Exception\\OutOfBoundsException' => __DIR__ . '/..' . '/symfony/property-access/Exception/OutOfBoundsException.php',
        '_ContaoManager\\Symfony\\Component\\PropertyAccess\\Exception\\RuntimeException' => __DIR__ . '/..' . '/symfony/property-access/Exception/RuntimeException.php',
        '_ContaoManager\\Symfony\\Component\\PropertyAccess\\Exception\\UnexpectedTypeException' => __DIR__ . '/..' . '/symfony/property-access/Exception/UnexpectedTypeException.php',
        '_ContaoManager\\Symfony\\Component\\PropertyAccess\\Exception\\UninitializedPropertyException' => __DIR__ . '/..' . '/symfony/property-access/Exception/UninitializedPropertyException.php',
        '_ContaoManager\\Symfony\\Component\\PropertyAccess\\PropertyAccess' => __DIR__ . '/..' . '/symfony/property-access/PropertyAccess.php',
        '_ContaoManager\\Symfony\\Component\\PropertyAccess\\PropertyAccessor' => __DIR__ . '/..' . '/symfony/property-access/PropertyAccessor.php',
        '_ContaoManager\\Symfony\\Component\\PropertyAccess\\PropertyAccessorBuilder' => __DIR__ . '/..' . '/symfony/property-access/PropertyAccessorBuilder.php',
        '_ContaoManager\\Symfony\\Component\\PropertyAccess\\PropertyAccessorInterface' => __DIR__ . '/..' . '/symfony/property-access/PropertyAccessorInterface.php',
        '_ContaoManager\\Symfony\\Component\\PropertyAccess\\PropertyPath' => __DIR__ . '/..' . '/symfony/property-access/PropertyPath.php',
        '_ContaoManager\\Symfony\\Component\\PropertyAccess\\PropertyPathBuilder' => __DIR__ . '/..' . '/symfony/property-access/PropertyPathBuilder.php',
        '_ContaoManager\\Symfony\\Component\\PropertyAccess\\PropertyPathInterface' => __DIR__ . '/..' . '/symfony/property-access/PropertyPathInterface.php',
        '_ContaoManager\\Symfony\\Component\\PropertyAccess\\PropertyPathIterator' => __DIR__ . '/..' . '/symfony/property-access/PropertyPathIterator.php',
        '_ContaoManager\\Symfony\\Component\\PropertyAccess\\PropertyPathIteratorInterface' => __DIR__ . '/..' . '/symfony/property-access/PropertyPathIteratorInterface.php',
        '_ContaoManager\\Symfony\\Component\\PropertyInfo\\DependencyInjection\\PropertyInfoConstructorPass' => __DIR__ . '/..' . '/symfony/property-info/DependencyInjection/PropertyInfoConstructorPass.php',
        '_ContaoManager\\Symfony\\Component\\PropertyInfo\\DependencyInjection\\PropertyInfoPass' => __DIR__ . '/..' . '/symfony/property-info/DependencyInjection/PropertyInfoPass.php',
        '_ContaoManager\\Symfony\\Component\\PropertyInfo\\Extractor\\ConstructorArgumentTypeExtractorInterface' => __DIR__ . '/..' . '/symfony/property-info/Extractor/ConstructorArgumentTypeExtractorInterface.php',
        '_ContaoManager\\Symfony\\Component\\PropertyInfo\\Extractor\\ConstructorExtractor' => __DIR__ . '/..' . '/symfony/property-info/Extractor/ConstructorExtractor.php',
        '_ContaoManager\\Symfony\\Component\\PropertyInfo\\Extractor\\PhpDocExtractor' => __DIR__ . '/..' . '/symfony/property-info/Extractor/PhpDocExtractor.php',
        '_ContaoManager\\Symfony\\Component\\PropertyInfo\\Extractor\\PhpStanExtractor' => __DIR__ . '/..' . '/symfony/property-info/Extractor/PhpStanExtractor.php',
        '_ContaoManager\\Symfony\\Component\\PropertyInfo\\Extractor\\ReflectionExtractor' => __DIR__ . '/..' . '/symfony/property-info/Extractor/ReflectionExtractor.php',
        '_ContaoManager\\Symfony\\Component\\PropertyInfo\\Extractor\\SerializerExtractor' => __DIR__ . '/..' . '/symfony/property-info/Extractor/SerializerExtractor.php',
        '_ContaoManager\\Symfony\\Component\\PropertyInfo\\PhpStan\\NameScope' => __DIR__ . '/..' . '/symfony/property-info/PhpStan/NameScope.php',
        '_ContaoManager\\Symfony\\Component\\PropertyInfo\\PhpStan\\NameScopeFactory' => __DIR__ . '/..' . '/symfony/property-info/PhpStan/NameScopeFactory.php',
        '_ContaoManager\\Symfony\\Component\\PropertyInfo\\PropertyAccessExtractorInterface' => __DIR__ . '/..' . '/symfony/property-info/PropertyAccessExtractorInterface.php',
        '_ContaoManager\\Symfony\\Component\\PropertyInfo\\PropertyDescriptionExtractorInterface' => __DIR__ . '/..' . '/symfony/property-info/PropertyDescriptionExtractorInterface.php',
        '_ContaoManager\\Symfony\\Component\\PropertyInfo\\PropertyInfoCacheExtractor' => __DIR__ . '/..' . '/symfony/property-info/PropertyInfoCacheExtractor.php',
        '_ContaoManager\\Symfony\\Component\\PropertyInfo\\PropertyInfoExtractor' => __DIR__ . '/..' . '/symfony/property-info/PropertyInfoExtractor.php',
        '_ContaoManager\\Symfony\\Component\\PropertyInfo\\PropertyInfoExtractorInterface' => __DIR__ . '/..' . '/symfony/property-info/PropertyInfoExtractorInterface.php',
        '_ContaoManager\\Symfony\\Component\\PropertyInfo\\PropertyInitializableExtractorInterface' => __DIR__ . '/..' . '/symfony/property-info/PropertyInitializableExtractorInterface.php',
        '_ContaoManager\\Symfony\\Component\\PropertyInfo\\PropertyListExtractorInterface' => __DIR__ . '/..' . '/symfony/property-info/PropertyListExtractorInterface.php',
        '_ContaoManager\\Symfony\\Component\\PropertyInfo\\PropertyReadInfo' => __DIR__ . '/..' . '/symfony/property-info/PropertyReadInfo.php',
        '_ContaoManager\\Symfony\\Component\\PropertyInfo\\PropertyReadInfoExtractorInterface' => __DIR__ . '/..' . '/symfony/property-info/PropertyReadInfoExtractorInterface.php',
        '_ContaoManager\\Symfony\\Component\\PropertyInfo\\PropertyTypeExtractorInterface' => __DIR__ . '/..' . '/symfony/property-info/PropertyTypeExtractorInterface.php',
        '_ContaoManager\\Symfony\\Component\\PropertyInfo\\PropertyWriteInfo' => __DIR__ . '/..' . '/symfony/property-info/PropertyWriteInfo.php',
        '_ContaoManager\\Symfony\\Component\\PropertyInfo\\PropertyWriteInfoExtractorInterface' => __DIR__ . '/..' . '/symfony/property-info/PropertyWriteInfoExtractorInterface.php',
        '_ContaoManager\\Symfony\\Component\\PropertyInfo\\Type' => __DIR__ . '/..' . '/symfony/property-info/Type.php',
        '_ContaoManager\\Symfony\\Component\\PropertyInfo\\Util\\PhpDocTypeHelper' => __DIR__ . '/..' . '/symfony/property-info/Util/PhpDocTypeHelper.php',
        '_ContaoManager\\Symfony\\Component\\PropertyInfo\\Util\\PhpStanTypeHelper' => __DIR__ . '/..' . '/symfony/property-info/Util/PhpStanTypeHelper.php',
        '_ContaoManager\\Symfony\\Component\\Routing\\Alias' => __DIR__ . '/..' . '/symfony/routing/Alias.php',
        '_ContaoManager\\Symfony\\Component\\Routing\\Annotation\\Route' => __DIR__ . '/..' . '/symfony/routing/Annotation/Route.php',
        '_ContaoManager\\Symfony\\Component\\Routing\\Attribute\\Route' => __DIR__ . '/..' . '/symfony/routing/Attribute/Route.php',
        '_ContaoManager\\Symfony\\Component\\Routing\\CompiledRoute' => __DIR__ . '/..' . '/symfony/routing/CompiledRoute.php',
        '_ContaoManager\\Symfony\\Component\\Routing\\DependencyInjection\\AddExpressionLanguageProvidersPass' => __DIR__ . '/..' . '/symfony/routing/DependencyInjection/AddExpressionLanguageProvidersPass.php',
        '_ContaoManager\\Symfony\\Component\\Routing\\DependencyInjection\\RoutingResolverPass' => __DIR__ . '/..' . '/symfony/routing/DependencyInjection/RoutingResolverPass.php',
        '_ContaoManager\\Symfony\\Component\\Routing\\Exception\\ExceptionInterface' => __DIR__ . '/..' . '/symfony/routing/Exception/ExceptionInterface.php',
        '_ContaoManager\\Symfony\\Component\\Routing\\Exception\\InvalidArgumentException' => __DIR__ . '/..' . '/symfony/routing/Exception/InvalidArgumentException.php',
        '_ContaoManager\\Symfony\\Component\\Routing\\Exception\\InvalidParameterException' => __DIR__ . '/..' . '/symfony/routing/Exception/InvalidParameterException.php',
        '_ContaoManager\\Symfony\\Component\\Routing\\Exception\\MethodNotAllowedException' => __DIR__ . '/..' . '/symfony/routing/Exception/MethodNotAllowedException.php',
        '_ContaoManager\\Symfony\\Component\\Routing\\Exception\\MissingMandatoryParametersException' => __DIR__ . '/..' . '/symfony/routing/Exception/MissingMandatoryParametersException.php',
        '_ContaoManager\\Symfony\\Component\\Routing\\Exception\\NoConfigurationException' => __DIR__ . '/..' . '/symfony/routing/Exception/NoConfigurationException.php',
        '_ContaoManager\\Symfony\\Component\\Routing\\Exception\\ResourceNotFoundException' => __DIR__ . '/..' . '/symfony/routing/Exception/ResourceNotFoundException.php',
        '_ContaoManager\\Symfony\\Component\\Routing\\Exception\\RouteCircularReferenceException' => __DIR__ . '/..' . '/symfony/routing/Exception/RouteCircularReferenceException.php',
        '_ContaoManager\\Symfony\\Component\\Routing\\Exception\\RouteNotFoundException' => __DIR__ . '/..' . '/symfony/routing/Exception/RouteNotFoundException.php',
        '_ContaoManager\\Symfony\\Component\\Routing\\Exception\\RuntimeException' => __DIR__ . '/..' . '/symfony/routing/Exception/RuntimeException.php',
        '_ContaoManager\\Symfony\\Component\\Routing\\Generator\\CompiledUrlGenerator' => __DIR__ . '/..' . '/symfony/routing/Generator/CompiledUrlGenerator.php',
        '_ContaoManager\\Symfony\\Component\\Routing\\Generator\\ConfigurableRequirementsInterface' => __DIR__ . '/..' . '/symfony/routing/Generator/ConfigurableRequirementsInterface.php',
        '_ContaoManager\\Symfony\\Component\\Routing\\Generator\\Dumper\\CompiledUrlGeneratorDumper' => __DIR__ . '/..' . '/symfony/routing/Generator/Dumper/CompiledUrlGeneratorDumper.php',
        '_ContaoManager\\Symfony\\Component\\Routing\\Generator\\Dumper\\GeneratorDumper' => __DIR__ . '/..' . '/symfony/routing/Generator/Dumper/GeneratorDumper.php',
        '_ContaoManager\\Symfony\\Component\\Routing\\Generator\\Dumper\\GeneratorDumperInterface' => __DIR__ . '/..' . '/symfony/routing/Generator/Dumper/GeneratorDumperInterface.php',
        '_ContaoManager\\Symfony\\Component\\Routing\\Generator\\UrlGenerator' => __DIR__ . '/..' . '/symfony/routing/Generator/UrlGenerator.php',
        '_ContaoManager\\Symfony\\Component\\Routing\\Generator\\UrlGeneratorInterface' => __DIR__ . '/..' . '/symfony/routing/Generator/UrlGeneratorInterface.php',
        '_ContaoManager\\Symfony\\Component\\Routing\\Loader\\AnnotationClassLoader' => __DIR__ . '/..' . '/symfony/routing/Loader/AnnotationClassLoader.php',
        '_ContaoManager\\Symfony\\Component\\Routing\\Loader\\AnnotationDirectoryLoader' => __DIR__ . '/..' . '/symfony/routing/Loader/AnnotationDirectoryLoader.php',
        '_ContaoManager\\Symfony\\Component\\Routing\\Loader\\AnnotationFileLoader' => __DIR__ . '/..' . '/symfony/routing/Loader/AnnotationFileLoader.php',
        '_ContaoManager\\Symfony\\Component\\Routing\\Loader\\AttributeClassLoader' => __DIR__ . '/..' . '/symfony/routing/Loader/AttributeClassLoader.php',
        '_ContaoManager\\Symfony\\Component\\Routing\\Loader\\AttributeDirectoryLoader' => __DIR__ . '/..' . '/symfony/routing/Loader/AttributeDirectoryLoader.php',
        '_ContaoManager\\Symfony\\Component\\Routing\\Loader\\AttributeFileLoader' => __DIR__ . '/..' . '/symfony/routing/Loader/AttributeFileLoader.php',
        '_ContaoManager\\Symfony\\Component\\Routing\\Loader\\ClosureLoader' => __DIR__ . '/..' . '/symfony/routing/Loader/ClosureLoader.php',
        '_ContaoManager\\Symfony\\Component\\Routing\\Loader\\Configurator\\AliasConfigurator' => __DIR__ . '/..' . '/symfony/routing/Loader/Configurator/AliasConfigurator.php',
        '_ContaoManager\\Symfony\\Component\\Routing\\Loader\\Configurator\\CollectionConfigurator' => __DIR__ . '/..' . '/symfony/routing/Loader/Configurator/CollectionConfigurator.php',
        '_ContaoManager\\Symfony\\Component\\Routing\\Loader\\Configurator\\ImportConfigurator' => __DIR__ . '/..' . '/symfony/routing/Loader/Configurator/ImportConfigurator.php',
        '_ContaoManager\\Symfony\\Component\\Routing\\Loader\\Configurator\\RouteConfigurator' => __DIR__ . '/..' . '/symfony/routing/Loader/Configurator/RouteConfigurator.php',
        '_ContaoManager\\Symfony\\Component\\Routing\\Loader\\Configurator\\RoutingConfigurator' => __DIR__ . '/..' . '/symfony/routing/Loader/Configurator/RoutingConfigurator.php',
        '_ContaoManager\\Symfony\\Component\\Routing\\Loader\\Configurator\\Traits\\AddTrait' => __DIR__ . '/..' . '/symfony/routing/Loader/Configurator/Traits/AddTrait.php',
        '_ContaoManager\\Symfony\\Component\\Routing\\Loader\\Configurator\\Traits\\HostTrait' => __DIR__ . '/..' . '/symfony/routing/Loader/Configurator/Traits/HostTrait.php',
        '_ContaoManager\\Symfony\\Component\\Routing\\Loader\\Configurator\\Traits\\LocalizedRouteTrait' => __DIR__ . '/..' . '/symfony/routing/Loader/Configurator/Traits/LocalizedRouteTrait.php',
        '_ContaoManager\\Symfony\\Component\\Routing\\Loader\\Configurator\\Traits\\PrefixTrait' => __DIR__ . '/..' . '/symfony/routing/Loader/Configurator/Traits/PrefixTrait.php',
        '_ContaoManager\\Symfony\\Component\\Routing\\Loader\\Configurator\\Traits\\RouteTrait' => __DIR__ . '/..' . '/symfony/routing/Loader/Configurator/Traits/RouteTrait.php',
        '_ContaoManager\\Symfony\\Component\\Routing\\Loader\\ContainerLoader' => __DIR__ . '/..' . '/symfony/routing/Loader/ContainerLoader.php',
        '_ContaoManager\\Symfony\\Component\\Routing\\Loader\\DirectoryLoader' => __DIR__ . '/..' . '/symfony/routing/Loader/DirectoryLoader.php',
        '_ContaoManager\\Symfony\\Component\\Routing\\Loader\\GlobFileLoader' => __DIR__ . '/..' . '/symfony/routing/Loader/GlobFileLoader.php',
        '_ContaoManager\\Symfony\\Component\\Routing\\Loader\\ObjectLoader' => __DIR__ . '/..' . '/symfony/routing/Loader/ObjectLoader.php',
        '_ContaoManager\\Symfony\\Component\\Routing\\Loader\\PhpFileLoader' => __DIR__ . '/..' . '/symfony/routing/Loader/PhpFileLoader.php',
        '_ContaoManager\\Symfony\\Component\\Routing\\Loader\\Psr4DirectoryLoader' => __DIR__ . '/..' . '/symfony/routing/Loader/Psr4DirectoryLoader.php',
        '_ContaoManager\\Symfony\\Component\\Routing\\Loader\\XmlFileLoader' => __DIR__ . '/..' . '/symfony/routing/Loader/XmlFileLoader.php',
        '_ContaoManager\\Symfony\\Component\\Routing\\Loader\\YamlFileLoader' => __DIR__ . '/..' . '/symfony/routing/Loader/YamlFileLoader.php',
        '_ContaoManager\\Symfony\\Component\\Routing\\Matcher\\CompiledUrlMatcher' => __DIR__ . '/..' . '/symfony/routing/Matcher/CompiledUrlMatcher.php',
        '_ContaoManager\\Symfony\\Component\\Routing\\Matcher\\Dumper\\CompiledUrlMatcherDumper' => __DIR__ . '/..' . '/symfony/routing/Matcher/Dumper/CompiledUrlMatcherDumper.php',
        '_ContaoManager\\Symfony\\Component\\Routing\\Matcher\\Dumper\\CompiledUrlMatcherTrait' => __DIR__ . '/..' . '/symfony/routing/Matcher/Dumper/CompiledUrlMatcherTrait.php',
        '_ContaoManager\\Symfony\\Component\\Routing\\Matcher\\Dumper\\MatcherDumper' => __DIR__ . '/..' . '/symfony/routing/Matcher/Dumper/MatcherDumper.php',
        '_ContaoManager\\Symfony\\Component\\Routing\\Matcher\\Dumper\\MatcherDumperInterface' => __DIR__ . '/..' . '/symfony/routing/Matcher/Dumper/MatcherDumperInterface.php',
        '_ContaoManager\\Symfony\\Component\\Routing\\Matcher\\Dumper\\StaticPrefixCollection' => __DIR__ . '/..' . '/symfony/routing/Matcher/Dumper/StaticPrefixCollection.php',
        '_ContaoManager\\Symfony\\Component\\Routing\\Matcher\\ExpressionLanguageProvider' => __DIR__ . '/..' . '/symfony/routing/Matcher/ExpressionLanguageProvider.php',
        '_ContaoManager\\Symfony\\Component\\Routing\\Matcher\\RedirectableUrlMatcher' => __DIR__ . '/..' . '/symfony/routing/Matcher/RedirectableUrlMatcher.php',
        '_ContaoManager\\Symfony\\Component\\Routing\\Matcher\\RedirectableUrlMatcherInterface' => __DIR__ . '/..' . '/symfony/routing/Matcher/RedirectableUrlMatcherInterface.php',
        '_ContaoManager\\Symfony\\Component\\Routing\\Matcher\\RequestMatcherInterface' => __DIR__ . '/..' . '/symfony/routing/Matcher/RequestMatcherInterface.php',
        '_ContaoManager\\Symfony\\Component\\Routing\\Matcher\\TraceableUrlMatcher' => __DIR__ . '/..' . '/symfony/routing/Matcher/TraceableUrlMatcher.php',
        '_ContaoManager\\Symfony\\Component\\Routing\\Matcher\\UrlMatcher' => __DIR__ . '/..' . '/symfony/routing/Matcher/UrlMatcher.php',
        '_ContaoManager\\Symfony\\Component\\Routing\\Matcher\\UrlMatcherInterface' => __DIR__ . '/..' . '/symfony/routing/Matcher/UrlMatcherInterface.php',
        '_ContaoManager\\Symfony\\Component\\Routing\\RequestContext' => __DIR__ . '/..' . '/symfony/routing/RequestContext.php',
        '_ContaoManager\\Symfony\\Component\\Routing\\RequestContextAwareInterface' => __DIR__ . '/..' . '/symfony/routing/RequestContextAwareInterface.php',
        '_ContaoManager\\Symfony\\Component\\Routing\\Requirement\\EnumRequirement' => __DIR__ . '/..' . '/symfony/routing/Requirement/EnumRequirement.php',
        '_ContaoManager\\Symfony\\Component\\Routing\\Requirement\\Requirement' => __DIR__ . '/..' . '/symfony/routing/Requirement/Requirement.php',
        '_ContaoManager\\Symfony\\Component\\Routing\\Route' => __DIR__ . '/..' . '/symfony/routing/Route.php',
        '_ContaoManager\\Symfony\\Component\\Routing\\RouteCollection' => __DIR__ . '/..' . '/symfony/routing/RouteCollection.php',
        '_ContaoManager\\Symfony\\Component\\Routing\\RouteCompiler' => __DIR__ . '/..' . '/symfony/routing/RouteCompiler.php',
        '_ContaoManager\\Symfony\\Component\\Routing\\RouteCompilerInterface' => __DIR__ . '/..' . '/symfony/routing/RouteCompilerInterface.php',
        '_ContaoManager\\Symfony\\Component\\Routing\\Router' => __DIR__ . '/..' . '/symfony/routing/Router.php',
        '_ContaoManager\\Symfony\\Component\\Routing\\RouterInterface' => __DIR__ . '/..' . '/symfony/routing/RouterInterface.php',
        '_ContaoManager\\Symfony\\Component\\Security\\Core\\AuthenticationEvents' => __DIR__ . '/..' . '/symfony/security-core/AuthenticationEvents.php',
        '_ContaoManager\\Symfony\\Component\\Security\\Core\\Authentication\\AuthenticationTrustResolver' => __DIR__ . '/..' . '/symfony/security-core/Authentication/AuthenticationTrustResolver.php',
        '_ContaoManager\\Symfony\\Component\\Security\\Core\\Authentication\\AuthenticationTrustResolverInterface' => __DIR__ . '/..' . '/symfony/security-core/Authentication/AuthenticationTrustResolverInterface.php',
        '_ContaoManager\\Symfony\\Component\\Security\\Core\\Authentication\\RememberMe\\CacheTokenVerifier' => __DIR__ . '/..' . '/symfony/security-core/Authentication/RememberMe/CacheTokenVerifier.php',
        '_ContaoManager\\Symfony\\Component\\Security\\Core\\Authentication\\RememberMe\\InMemoryTokenProvider' => __DIR__ . '/..' . '/symfony/security-core/Authentication/RememberMe/InMemoryTokenProvider.php',
        '_ContaoManager\\Symfony\\Component\\Security\\Core\\Authentication\\RememberMe\\PersistentToken' => __DIR__ . '/..' . '/symfony/security-core/Authentication/RememberMe/PersistentToken.php',
        '_ContaoManager\\Symfony\\Component\\Security\\Core\\Authentication\\RememberMe\\PersistentTokenInterface' => __DIR__ . '/..' . '/symfony/security-core/Authentication/RememberMe/PersistentTokenInterface.php',
        '_ContaoManager\\Symfony\\Component\\Security\\Core\\Authentication\\RememberMe\\TokenProviderInterface' => __DIR__ . '/..' . '/symfony/security-core/Authentication/RememberMe/TokenProviderInterface.php',
        '_ContaoManager\\Symfony\\Component\\Security\\Core\\Authentication\\RememberMe\\TokenVerifierInterface' => __DIR__ . '/..' . '/symfony/security-core/Authentication/RememberMe/TokenVerifierInterface.php',
        '_ContaoManager\\Symfony\\Component\\Security\\Core\\Authentication\\Token\\AbstractToken' => __DIR__ . '/..' . '/symfony/security-core/Authentication/Token/AbstractToken.php',
        '_ContaoManager\\Symfony\\Component\\Security\\Core\\Authentication\\Token\\NullToken' => __DIR__ . '/..' . '/symfony/security-core/Authentication/Token/NullToken.php',
        '_ContaoManager\\Symfony\\Component\\Security\\Core\\Authentication\\Token\\PreAuthenticatedToken' => __DIR__ . '/..' . '/symfony/security-core/Authentication/Token/PreAuthenticatedToken.php',
        '_ContaoManager\\Symfony\\Component\\Security\\Core\\Authentication\\Token\\RememberMeToken' => __DIR__ . '/..' . '/symfony/security-core/Authentication/Token/RememberMeToken.php',
        '_ContaoManager\\Symfony\\Component\\Security\\Core\\Authentication\\Token\\Storage\\TokenStorage' => __DIR__ . '/..' . '/symfony/security-core/Authentication/Token/Storage/TokenStorage.php',
        '_ContaoManager\\Symfony\\Component\\Security\\Core\\Authentication\\Token\\Storage\\TokenStorageInterface' => __DIR__ . '/..' . '/symfony/security-core/Authentication/Token/Storage/TokenStorageInterface.php',
        '_ContaoManager\\Symfony\\Component\\Security\\Core\\Authentication\\Token\\Storage\\UsageTrackingTokenStorage' => __DIR__ . '/..' . '/symfony/security-core/Authentication/Token/Storage/UsageTrackingTokenStorage.php',
        '_ContaoManager\\Symfony\\Component\\Security\\Core\\Authentication\\Token\\SwitchUserToken' => __DIR__ . '/..' . '/symfony/security-core/Authentication/Token/SwitchUserToken.php',
        '_ContaoManager\\Symfony\\Component\\Security\\Core\\Authentication\\Token\\TokenInterface' => __DIR__ . '/..' . '/symfony/security-core/Authentication/Token/TokenInterface.php',
        '_ContaoManager\\Symfony\\Component\\Security\\Core\\Authentication\\Token\\UsernamePasswordToken' => __DIR__ . '/..' . '/symfony/security-core/Authentication/Token/UsernamePasswordToken.php',
        '_ContaoManager\\Symfony\\Component\\Security\\Core\\Authorization\\AccessDecisionManager' => __DIR__ . '/..' . '/symfony/security-core/Authorization/AccessDecisionManager.php',
        '_ContaoManager\\Symfony\\Component\\Security\\Core\\Authorization\\AccessDecisionManagerInterface' => __DIR__ . '/..' . '/symfony/security-core/Authorization/AccessDecisionManagerInterface.php',
        '_ContaoManager\\Symfony\\Component\\Security\\Core\\Authorization\\AuthorizationChecker' => __DIR__ . '/..' . '/symfony/security-core/Authorization/AuthorizationChecker.php',
        '_ContaoManager\\Symfony\\Component\\Security\\Core\\Authorization\\AuthorizationCheckerInterface' => __DIR__ . '/..' . '/symfony/security-core/Authorization/AuthorizationCheckerInterface.php',
        '_ContaoManager\\Symfony\\Component\\Security\\Core\\Authorization\\ExpressionLanguage' => __DIR__ . '/..' . '/symfony/security-core/Authorization/ExpressionLanguage.php',
        '_ContaoManager\\Symfony\\Component\\Security\\Core\\Authorization\\ExpressionLanguageProvider' => __DIR__ . '/..' . '/symfony/security-core/Authorization/ExpressionLanguageProvider.php',
        '_ContaoManager\\Symfony\\Component\\Security\\Core\\Authorization\\Strategy\\AccessDecisionStrategyInterface' => __DIR__ . '/..' . '/symfony/security-core/Authorization/Strategy/AccessDecisionStrategyInterface.php',
        '_ContaoManager\\Symfony\\Component\\Security\\Core\\Authorization\\Strategy\\AffirmativeStrategy' => __DIR__ . '/..' . '/symfony/security-core/Authorization/Strategy/AffirmativeStrategy.php',
        '_ContaoManager\\Symfony\\Component\\Security\\Core\\Authorization\\Strategy\\ConsensusStrategy' => __DIR__ . '/..' . '/symfony/security-core/Authorization/Strategy/ConsensusStrategy.php',
        '_ContaoManager\\Symfony\\Component\\Security\\Core\\Authorization\\Strategy\\PriorityStrategy' => __DIR__ . '/..' . '/symfony/security-core/Authorization/Strategy/PriorityStrategy.php',
        '_ContaoManager\\Symfony\\Component\\Security\\Core\\Authorization\\Strategy\\UnanimousStrategy' => __DIR__ . '/..' . '/symfony/security-core/Authorization/Strategy/UnanimousStrategy.php',
        '_ContaoManager\\Symfony\\Component\\Security\\Core\\Authorization\\TraceableAccessDecisionManager' => __DIR__ . '/..' . '/symfony/security-core/Authorization/TraceableAccessDecisionManager.php',
        '_ContaoManager\\Symfony\\Component\\Security\\Core\\Authorization\\Voter\\AuthenticatedVoter' => __DIR__ . '/..' . '/symfony/security-core/Authorization/Voter/AuthenticatedVoter.php',
        '_ContaoManager\\Symfony\\Component\\Security\\Core\\Authorization\\Voter\\CacheableVoterInterface' => __DIR__ . '/..' . '/symfony/security-core/Authorization/Voter/CacheableVoterInterface.php',
        '_ContaoManager\\Symfony\\Component\\Security\\Core\\Authorization\\Voter\\ExpressionVoter' => __DIR__ . '/..' . '/symfony/security-core/Authorization/Voter/ExpressionVoter.php',
        '_ContaoManager\\Symfony\\Component\\Security\\Core\\Authorization\\Voter\\RoleHierarchyVoter' => __DIR__ . '/..' . '/symfony/security-core/Authorization/Voter/RoleHierarchyVoter.php',
        '_ContaoManager\\Symfony\\Component\\Security\\Core\\Authorization\\Voter\\RoleVoter' => __DIR__ . '/..' . '/symfony/security-core/Authorization/Voter/RoleVoter.php',
        '_ContaoManager\\Symfony\\Component\\Security\\Core\\Authorization\\Voter\\TraceableVoter' => __DIR__ . '/..' . '/symfony/security-core/Authorization/Voter/TraceableVoter.php',
        '_ContaoManager\\Symfony\\Component\\Security\\Core\\Authorization\\Voter\\Voter' => __DIR__ . '/..' . '/symfony/security-core/Authorization/Voter/Voter.php',
        '_ContaoManager\\Symfony\\Component\\Security\\Core\\Authorization\\Voter\\VoterInterface' => __DIR__ . '/..' . '/symfony/security-core/Authorization/Voter/VoterInterface.php',
        '_ContaoManager\\Symfony\\Component\\Security\\Core\\Event\\AuthenticationEvent' => __DIR__ . '/..' . '/symfony/security-core/Event/AuthenticationEvent.php',
        '_ContaoManager\\Symfony\\Component\\Security\\Core\\Event\\AuthenticationSuccessEvent' => __DIR__ . '/..' . '/symfony/security-core/Event/AuthenticationSuccessEvent.php',
        '_ContaoManager\\Symfony\\Component\\Security\\Core\\Event\\VoteEvent' => __DIR__ . '/..' . '/symfony/security-core/Event/VoteEvent.php',
        '_ContaoManager\\Symfony\\Component\\Security\\Core\\Exception\\AccessDeniedException' => __DIR__ . '/..' . '/symfony/security-core/Exception/AccessDeniedException.php',
        '_ContaoManager\\Symfony\\Component\\Security\\Core\\Exception\\AccountExpiredException' => __DIR__ . '/..' . '/symfony/security-core/Exception/AccountExpiredException.php',
        '_ContaoManager\\Symfony\\Component\\Security\\Core\\Exception\\AccountStatusException' => __DIR__ . '/..' . '/symfony/security-core/Exception/AccountStatusException.php',
        '_ContaoManager\\Symfony\\Component\\Security\\Core\\Exception\\AuthenticationCredentialsNotFoundException' => __DIR__ . '/..' . '/symfony/security-core/Exception/AuthenticationCredentialsNotFoundException.php',
        '_ContaoManager\\Symfony\\Component\\Security\\Core\\Exception\\AuthenticationException' => __DIR__ . '/..' . '/symfony/security-core/Exception/AuthenticationException.php',
        '_ContaoManager\\Symfony\\Component\\Security\\Core\\Exception\\AuthenticationExpiredException' => __DIR__ . '/..' . '/symfony/security-core/Exception/AuthenticationExpiredException.php',
        '_ContaoManager\\Symfony\\Component\\Security\\Core\\Exception\\AuthenticationServiceException' => __DIR__ . '/..' . '/symfony/security-core/Exception/AuthenticationServiceException.php',
        '_ContaoManager\\Symfony\\Component\\Security\\Core\\Exception\\BadCredentialsException' => __DIR__ . '/..' . '/symfony/security-core/Exception/BadCredentialsException.php',
        '_ContaoManager\\Symfony\\Component\\Security\\Core\\Exception\\CookieTheftException' => __DIR__ . '/..' . '/symfony/security-core/Exception/CookieTheftException.php',
        '_ContaoManager\\Symfony\\Component\\Security\\Core\\Exception\\CredentialsExpiredException' => __DIR__ . '/..' . '/symfony/security-core/Exception/CredentialsExpiredException.php',
        '_ContaoManager\\Symfony\\Component\\Security\\Core\\Exception\\CustomUserMessageAccountStatusException' => __DIR__ . '/..' . '/symfony/security-core/Exception/CustomUserMessageAccountStatusException.php',
        '_ContaoManager\\Symfony\\Component\\Security\\Core\\Exception\\CustomUserMessageAuthenticationException' => __DIR__ . '/..' . '/symfony/security-core/Exception/CustomUserMessageAuthenticationException.php',
        '_ContaoManager\\Symfony\\Component\\Security\\Core\\Exception\\DisabledException' => __DIR__ . '/..' . '/symfony/security-core/Exception/DisabledException.php',
        '_ContaoManager\\Symfony\\Component\\Security\\Core\\Exception\\ExceptionInterface' => __DIR__ . '/..' . '/symfony/security-core/Exception/ExceptionInterface.php',
        '_ContaoManager\\Symfony\\Component\\Security\\Core\\Exception\\InsufficientAuthenticationException' => __DIR__ . '/..' . '/symfony/security-core/Exception/InsufficientAuthenticationException.php',
        '_ContaoManager\\Symfony\\Component\\Security\\Core\\Exception\\InvalidArgumentException' => __DIR__ . '/..' . '/symfony/security-core/Exception/InvalidArgumentException.php',
        '_ContaoManager\\Symfony\\Component\\Security\\Core\\Exception\\InvalidCsrfTokenException' => __DIR__ . '/..' . '/symfony/security-core/Exception/InvalidCsrfTokenException.php',
        '_ContaoManager\\Symfony\\Component\\Security\\Core\\Exception\\LazyResponseException' => __DIR__ . '/..' . '/symfony/security-core/Exception/LazyResponseException.php',
        '_ContaoManager\\Symfony\\Component\\Security\\Core\\Exception\\LockedException' => __DIR__ . '/..' . '/symfony/security-core/Exception/LockedException.php',
        '_ContaoManager\\Symfony\\Component\\Security\\Core\\Exception\\LogicException' => __DIR__ . '/..' . '/symfony/security-core/Exception/LogicException.php',
        '_ContaoManager\\Symfony\\Component\\Security\\Core\\Exception\\LogoutException' => __DIR__ . '/..' . '/symfony/security-core/Exception/LogoutException.php',
        '_ContaoManager\\Symfony\\Component\\Security\\Core\\Exception\\ProviderNotFoundException' => __DIR__ . '/..' . '/symfony/security-core/Exception/ProviderNotFoundException.php',
        '_ContaoManager\\Symfony\\Component\\Security\\Core\\Exception\\RuntimeException' => __DIR__ . '/..' . '/symfony/security-core/Exception/RuntimeException.php',
        '_ContaoManager\\Symfony\\Component\\Security\\Core\\Exception\\SessionUnavailableException' => __DIR__ . '/..' . '/symfony/security-core/Exception/SessionUnavailableException.php',
        '_ContaoManager\\Symfony\\Component\\Security\\Core\\Exception\\TokenNotFoundException' => __DIR__ . '/..' . '/symfony/security-core/Exception/TokenNotFoundException.php',
        '_ContaoManager\\Symfony\\Component\\Security\\Core\\Exception\\TooManyLoginAttemptsAuthenticationException' => __DIR__ . '/..' . '/symfony/security-core/Exception/TooManyLoginAttemptsAuthenticationException.php',
        '_ContaoManager\\Symfony\\Component\\Security\\Core\\Exception\\UnsupportedUserException' => __DIR__ . '/..' . '/symfony/security-core/Exception/UnsupportedUserException.php',
        '_ContaoManager\\Symfony\\Component\\Security\\Core\\Exception\\UserNotFoundException' => __DIR__ . '/..' . '/symfony/security-core/Exception/UserNotFoundException.php',
        '_ContaoManager\\Symfony\\Component\\Security\\Core\\Role\\Role' => __DIR__ . '/..' . '/symfony/security-core/Role/Role.php',
        '_ContaoManager\\Symfony\\Component\\Security\\Core\\Role\\RoleHierarchy' => __DIR__ . '/..' . '/symfony/security-core/Role/RoleHierarchy.php',
        '_ContaoManager\\Symfony\\Component\\Security\\Core\\Role\\RoleHierarchyInterface' => __DIR__ . '/..' . '/symfony/security-core/Role/RoleHierarchyInterface.php',
        '_ContaoManager\\Symfony\\Component\\Security\\Core\\Role\\SwitchUserRole' => __DIR__ . '/..' . '/symfony/security-core/Role/SwitchUserRole.php',
        '_ContaoManager\\Symfony\\Component\\Security\\Core\\Security' => __DIR__ . '/..' . '/symfony/security-core/Security.php',
        '_ContaoManager\\Symfony\\Component\\Security\\Core\\Signature\\Exception\\ExpiredSignatureException' => __DIR__ . '/..' . '/symfony/security-core/Signature/Exception/ExpiredSignatureException.php',
        '_ContaoManager\\Symfony\\Component\\Security\\Core\\Signature\\Exception\\InvalidSignatureException' => __DIR__ . '/..' . '/symfony/security-core/Signature/Exception/InvalidSignatureException.php',
        '_ContaoManager\\Symfony\\Component\\Security\\Core\\Signature\\ExpiredSignatureStorage' => __DIR__ . '/..' . '/symfony/security-core/Signature/ExpiredSignatureStorage.php',
        '_ContaoManager\\Symfony\\Component\\Security\\Core\\Signature\\SignatureHasher' => __DIR__ . '/..' . '/symfony/security-core/Signature/SignatureHasher.php',
        '_ContaoManager\\Symfony\\Component\\Security\\Core\\Test\\AccessDecisionStrategyTestCase' => __DIR__ . '/..' . '/symfony/security-core/Test/AccessDecisionStrategyTestCase.php',
        '_ContaoManager\\Symfony\\Component\\Security\\Core\\User\\AttributesBasedUserProviderInterface' => __DIR__ . '/..' . '/symfony/security-core/User/AttributesBasedUserProviderInterface.php',
        '_ContaoManager\\Symfony\\Component\\Security\\Core\\User\\ChainUserChecker' => __DIR__ . '/..' . '/symfony/security-core/User/ChainUserChecker.php',
        '_ContaoManager\\Symfony\\Component\\Security\\Core\\User\\ChainUserProvider' => __DIR__ . '/..' . '/symfony/security-core/User/ChainUserProvider.php',
        '_ContaoManager\\Symfony\\Component\\Security\\Core\\User\\EquatableInterface' => __DIR__ . '/..' . '/symfony/security-core/User/EquatableInterface.php',
        '_ContaoManager\\Symfony\\Component\\Security\\Core\\User\\InMemoryUser' => __DIR__ . '/..' . '/symfony/security-core/User/InMemoryUser.php',
        '_ContaoManager\\Symfony\\Component\\Security\\Core\\User\\InMemoryUserChecker' => __DIR__ . '/..' . '/symfony/security-core/User/InMemoryUserChecker.php',
        '_ContaoManager\\Symfony\\Component\\Security\\Core\\User\\InMemoryUserProvider' => __DIR__ . '/..' . '/symfony/security-core/User/InMemoryUserProvider.php',
        '_ContaoManager\\Symfony\\Component\\Security\\Core\\User\\LegacyPasswordAuthenticatedUserInterface' => __DIR__ . '/..' . '/symfony/security-core/User/LegacyPasswordAuthenticatedUserInterface.php',
        '_ContaoManager\\Symfony\\Component\\Security\\Core\\User\\MissingUserProvider' => __DIR__ . '/..' . '/symfony/security-core/User/MissingUserProvider.php',
        '_ContaoManager\\Symfony\\Component\\Security\\Core\\User\\OidcUser' => __DIR__ . '/..' . '/symfony/security-core/User/OidcUser.php',
        '_ContaoManager\\Symfony\\Component\\Security\\Core\\User\\PasswordAuthenticatedUserInterface' => __DIR__ . '/..' . '/symfony/security-core/User/PasswordAuthenticatedUserInterface.php',
        '_ContaoManager\\Symfony\\Component\\Security\\Core\\User\\PasswordUpgraderInterface' => __DIR__ . '/..' . '/symfony/security-core/User/PasswordUpgraderInterface.php',
        '_ContaoManager\\Symfony\\Component\\Security\\Core\\User\\UserCheckerInterface' => __DIR__ . '/..' . '/symfony/security-core/User/UserCheckerInterface.php',
        '_ContaoManager\\Symfony\\Component\\Security\\Core\\User\\UserInterface' => __DIR__ . '/..' . '/symfony/security-core/User/UserInterface.php',
        '_ContaoManager\\Symfony\\Component\\Security\\Core\\User\\UserProviderInterface' => __DIR__ . '/..' . '/symfony/security-core/User/UserProviderInterface.php',
        '_ContaoManager\\Symfony\\Component\\Security\\Core\\Validator\\Constraints\\UserPassword' => __DIR__ . '/..' . '/symfony/security-core/Validator/Constraints/UserPassword.php',
        '_ContaoManager\\Symfony\\Component\\Security\\Core\\Validator\\Constraints\\UserPasswordValidator' => __DIR__ . '/..' . '/symfony/security-core/Validator/Constraints/UserPasswordValidator.php',
        '_ContaoManager\\Symfony\\Component\\Security\\Csrf\\CsrfToken' => __DIR__ . '/..' . '/symfony/security-csrf/CsrfToken.php',
        '_ContaoManager\\Symfony\\Component\\Security\\Csrf\\CsrfTokenManager' => __DIR__ . '/..' . '/symfony/security-csrf/CsrfTokenManager.php',
        '_ContaoManager\\Symfony\\Component\\Security\\Csrf\\CsrfTokenManagerInterface' => __DIR__ . '/..' . '/symfony/security-csrf/CsrfTokenManagerInterface.php',
        '_ContaoManager\\Symfony\\Component\\Security\\Csrf\\Exception\\TokenNotFoundException' => __DIR__ . '/..' . '/symfony/security-csrf/Exception/TokenNotFoundException.php',
        '_ContaoManager\\Symfony\\Component\\Security\\Csrf\\TokenGenerator\\TokenGeneratorInterface' => __DIR__ . '/..' . '/symfony/security-csrf/TokenGenerator/TokenGeneratorInterface.php',
        '_ContaoManager\\Symfony\\Component\\Security\\Csrf\\TokenGenerator\\UriSafeTokenGenerator' => __DIR__ . '/..' . '/symfony/security-csrf/TokenGenerator/UriSafeTokenGenerator.php',
        '_ContaoManager\\Symfony\\Component\\Security\\Csrf\\TokenStorage\\ClearableTokenStorageInterface' => __DIR__ . '/..' . '/symfony/security-csrf/TokenStorage/ClearableTokenStorageInterface.php',
        '_ContaoManager\\Symfony\\Component\\Security\\Csrf\\TokenStorage\\NativeSessionTokenStorage' => __DIR__ . '/..' . '/symfony/security-csrf/TokenStorage/NativeSessionTokenStorage.php',
        '_ContaoManager\\Symfony\\Component\\Security\\Csrf\\TokenStorage\\SessionTokenStorage' => __DIR__ . '/..' . '/symfony/security-csrf/TokenStorage/SessionTokenStorage.php',
        '_ContaoManager\\Symfony\\Component\\Security\\Csrf\\TokenStorage\\TokenStorageInterface' => __DIR__ . '/..' . '/symfony/security-csrf/TokenStorage/TokenStorageInterface.php',
        '_ContaoManager\\Symfony\\Component\\Security\\Http\\AccessMap' => __DIR__ . '/..' . '/symfony/security-http/AccessMap.php',
        '_ContaoManager\\Symfony\\Component\\Security\\Http\\AccessMapInterface' => __DIR__ . '/..' . '/symfony/security-http/AccessMapInterface.php',
        '_ContaoManager\\Symfony\\Component\\Security\\Http\\AccessToken\\AccessTokenExtractorInterface' => __DIR__ . '/..' . '/symfony/security-http/AccessToken/AccessTokenExtractorInterface.php',
        '_ContaoManager\\Symfony\\Component\\Security\\Http\\AccessToken\\AccessTokenHandlerInterface' => __DIR__ . '/..' . '/symfony/security-http/AccessToken/AccessTokenHandlerInterface.php',
        '_ContaoManager\\Symfony\\Component\\Security\\Http\\AccessToken\\ChainAccessTokenExtractor' => __DIR__ . '/..' . '/symfony/security-http/AccessToken/ChainAccessTokenExtractor.php',
        '_ContaoManager\\Symfony\\Component\\Security\\Http\\AccessToken\\FormEncodedBodyExtractor' => __DIR__ . '/..' . '/symfony/security-http/AccessToken/FormEncodedBodyExtractor.php',
        '_ContaoManager\\Symfony\\Component\\Security\\Http\\AccessToken\\HeaderAccessTokenExtractor' => __DIR__ . '/..' . '/symfony/security-http/AccessToken/HeaderAccessTokenExtractor.php',
        '_ContaoManager\\Symfony\\Component\\Security\\Http\\AccessToken\\Oidc\\Exception\\InvalidSignatureException' => __DIR__ . '/..' . '/symfony/security-http/AccessToken/Oidc/Exception/InvalidSignatureException.php',
        '_ContaoManager\\Symfony\\Component\\Security\\Http\\AccessToken\\Oidc\\Exception\\MissingClaimException' => __DIR__ . '/..' . '/symfony/security-http/AccessToken/Oidc/Exception/MissingClaimException.php',
        '_ContaoManager\\Symfony\\Component\\Security\\Http\\AccessToken\\Oidc\\OidcTokenHandler' => __DIR__ . '/..' . '/symfony/security-http/AccessToken/Oidc/OidcTokenHandler.php',
        '_ContaoManager\\Symfony\\Component\\Security\\Http\\AccessToken\\Oidc\\OidcTrait' => __DIR__ . '/..' . '/symfony/security-http/AccessToken/Oidc/OidcTrait.php',
        '_ContaoManager\\Symfony\\Component\\Security\\Http\\AccessToken\\Oidc\\OidcUserInfoTokenHandler' => __DIR__ . '/..' . '/symfony/security-http/AccessToken/Oidc/OidcUserInfoTokenHandler.php',
        '_ContaoManager\\Symfony\\Component\\Security\\Http\\AccessToken\\QueryAccessTokenExtractor' => __DIR__ . '/..' . '/symfony/security-http/AccessToken/QueryAccessTokenExtractor.php',
        '_ContaoManager\\Symfony\\Component\\Security\\Http\\Attribute\\CurrentUser' => __DIR__ . '/..' . '/symfony/security-http/Attribute/CurrentUser.php',
        '_ContaoManager\\Symfony\\Component\\Security\\Http\\Attribute\\IsGranted' => __DIR__ . '/..' . '/symfony/security-http/Attribute/IsGranted.php',
        '_ContaoManager\\Symfony\\Component\\Security\\Http\\Authentication\\AuthenticationFailureHandlerInterface' => __DIR__ . '/..' . '/symfony/security-http/Authentication/AuthenticationFailureHandlerInterface.php',
        '_ContaoManager\\Symfony\\Component\\Security\\Http\\Authentication\\AuthenticationSuccessHandlerInterface' => __DIR__ . '/..' . '/symfony/security-http/Authentication/AuthenticationSuccessHandlerInterface.php',
        '_ContaoManager\\Symfony\\Component\\Security\\Http\\Authentication\\AuthenticationUtils' => __DIR__ . '/..' . '/symfony/security-http/Authentication/AuthenticationUtils.php',
        '_ContaoManager\\Symfony\\Component\\Security\\Http\\Authentication\\AuthenticatorManager' => __DIR__ . '/..' . '/symfony/security-http/Authentication/AuthenticatorManager.php',
        '_ContaoManager\\Symfony\\Component\\Security\\Http\\Authentication\\AuthenticatorManagerInterface' => __DIR__ . '/..' . '/symfony/security-http/Authentication/AuthenticatorManagerInterface.php',
        '_ContaoManager\\Symfony\\Component\\Security\\Http\\Authentication\\CustomAuthenticationFailureHandler' => __DIR__ . '/..' . '/symfony/security-http/Authentication/CustomAuthenticationFailureHandler.php',
        '_ContaoManager\\Symfony\\Component\\Security\\Http\\Authentication\\CustomAuthenticationSuccessHandler' => __DIR__ . '/..' . '/symfony/security-http/Authentication/CustomAuthenticationSuccessHandler.php',
        '_ContaoManager\\Symfony\\Component\\Security\\Http\\Authentication\\DefaultAuthenticationFailureHandler' => __DIR__ . '/..' . '/symfony/security-http/Authentication/DefaultAuthenticationFailureHandler.php',
        '_ContaoManager\\Symfony\\Component\\Security\\Http\\Authentication\\DefaultAuthenticationSuccessHandler' => __DIR__ . '/..' . '/symfony/security-http/Authentication/DefaultAuthenticationSuccessHandler.php',
        '_ContaoManager\\Symfony\\Component\\Security\\Http\\Authentication\\UserAuthenticatorInterface' => __DIR__ . '/..' . '/symfony/security-http/Authentication/UserAuthenticatorInterface.php',
        '_ContaoManager\\Symfony\\Component\\Security\\Http\\Authenticator\\AbstractAuthenticator' => __DIR__ . '/..' . '/symfony/security-http/Authenticator/AbstractAuthenticator.php',
        '_ContaoManager\\Symfony\\Component\\Security\\Http\\Authenticator\\AbstractLoginFormAuthenticator' => __DIR__ . '/..' . '/symfony/security-http/Authenticator/AbstractLoginFormAuthenticator.php',
        '_ContaoManager\\Symfony\\Component\\Security\\Http\\Authenticator\\AbstractPreAuthenticatedAuthenticator' => __DIR__ . '/..' . '/symfony/security-http/Authenticator/AbstractPreAuthenticatedAuthenticator.php',
        '_ContaoManager\\Symfony\\Component\\Security\\Http\\Authenticator\\AccessTokenAuthenticator' => __DIR__ . '/..' . '/symfony/security-http/Authenticator/AccessTokenAuthenticator.php',
        '_ContaoManager\\Symfony\\Component\\Security\\Http\\Authenticator\\AuthenticatorInterface' => __DIR__ . '/..' . '/symfony/security-http/Authenticator/AuthenticatorInterface.php',
        '_ContaoManager\\Symfony\\Component\\Security\\Http\\Authenticator\\Debug\\TraceableAuthenticator' => __DIR__ . '/..' . '/symfony/security-http/Authenticator/Debug/TraceableAuthenticator.php',
        '_ContaoManager\\Symfony\\Component\\Security\\Http\\Authenticator\\Debug\\TraceableAuthenticatorManagerListener' => __DIR__ . '/..' . '/symfony/security-http/Authenticator/Debug/TraceableAuthenticatorManagerListener.php',
        '_ContaoManager\\Symfony\\Component\\Security\\Http\\Authenticator\\FallbackUserLoader' => __DIR__ . '/..' . '/symfony/security-http/Authenticator/FallbackUserLoader.php',
        '_ContaoManager\\Symfony\\Component\\Security\\Http\\Authenticator\\FormLoginAuthenticator' => __DIR__ . '/..' . '/symfony/security-http/Authenticator/FormLoginAuthenticator.php',
        '_ContaoManager\\Symfony\\Component\\Security\\Http\\Authenticator\\HttpBasicAuthenticator' => __DIR__ . '/..' . '/symfony/security-http/Authenticator/HttpBasicAuthenticator.php',
        '_ContaoManager\\Symfony\\Component\\Security\\Http\\Authenticator\\InteractiveAuthenticatorInterface' => __DIR__ . '/..' . '/symfony/security-http/Authenticator/InteractiveAuthenticatorInterface.php',
        '_ContaoManager\\Symfony\\Component\\Security\\Http\\Authenticator\\JsonLoginAuthenticator' => __DIR__ . '/..' . '/symfony/security-http/Authenticator/JsonLoginAuthenticator.php',
        '_ContaoManager\\Symfony\\Component\\Security\\Http\\Authenticator\\LoginLinkAuthenticator' => __DIR__ . '/..' . '/symfony/security-http/Authenticator/LoginLinkAuthenticator.php',
        '_ContaoManager\\Symfony\\Component\\Security\\Http\\Authenticator\\Passport\\Badge\\BadgeInterface' => __DIR__ . '/..' . '/symfony/security-http/Authenticator/Passport/Badge/BadgeInterface.php',
        '_ContaoManager\\Symfony\\Component\\Security\\Http\\Authenticator\\Passport\\Badge\\CsrfTokenBadge' => __DIR__ . '/..' . '/symfony/security-http/Authenticator/Passport/Badge/CsrfTokenBadge.php',
        '_ContaoManager\\Symfony\\Component\\Security\\Http\\Authenticator\\Passport\\Badge\\PasswordUpgradeBadge' => __DIR__ . '/..' . '/symfony/security-http/Authenticator/Passport/Badge/PasswordUpgradeBadge.php',
        '_ContaoManager\\Symfony\\Component\\Security\\Http\\Authenticator\\Passport\\Badge\\PreAuthenticatedUserBadge' => __DIR__ . '/..' . '/symfony/security-http/Authenticator/Passport/Badge/PreAuthenticatedUserBadge.php',
        '_ContaoManager\\Symfony\\Component\\Security\\Http\\Authenticator\\Passport\\Badge\\RememberMeBadge' => __DIR__ . '/..' . '/symfony/security-http/Authenticator/Passport/Badge/RememberMeBadge.php',
        '_ContaoManager\\Symfony\\Component\\Security\\Http\\Authenticator\\Passport\\Badge\\UserBadge' => __DIR__ . '/..' . '/symfony/security-http/Authenticator/Passport/Badge/UserBadge.php',
        '_ContaoManager\\Symfony\\Component\\Security\\Http\\Authenticator\\Passport\\Credentials\\CredentialsInterface' => __DIR__ . '/..' . '/symfony/security-http/Authenticator/Passport/Credentials/CredentialsInterface.php',
        '_ContaoManager\\Symfony\\Component\\Security\\Http\\Authenticator\\Passport\\Credentials\\CustomCredentials' => __DIR__ . '/..' . '/symfony/security-http/Authenticator/Passport/Credentials/CustomCredentials.php',
        '_ContaoManager\\Symfony\\Component\\Security\\Http\\Authenticator\\Passport\\Credentials\\PasswordCredentials' => __DIR__ . '/..' . '/symfony/security-http/Authenticator/Passport/Credentials/PasswordCredentials.php',
        '_ContaoManager\\Symfony\\Component\\Security\\Http\\Authenticator\\Passport\\Passport' => __DIR__ . '/..' . '/symfony/security-http/Authenticator/Passport/Passport.php',
        '_ContaoManager\\Symfony\\Component\\Security\\Http\\Authenticator\\Passport\\SelfValidatingPassport' => __DIR__ . '/..' . '/symfony/security-http/Authenticator/Passport/SelfValidatingPassport.php',
        '_ContaoManager\\Symfony\\Component\\Security\\Http\\Authenticator\\RememberMeAuthenticator' => __DIR__ . '/..' . '/symfony/security-http/Authenticator/RememberMeAuthenticator.php',
        '_ContaoManager\\Symfony\\Component\\Security\\Http\\Authenticator\\RemoteUserAuthenticator' => __DIR__ . '/..' . '/symfony/security-http/Authenticator/RemoteUserAuthenticator.php',
        '_ContaoManager\\Symfony\\Component\\Security\\Http\\Authenticator\\Token\\PostAuthenticationToken' => __DIR__ . '/..' . '/symfony/security-http/Authenticator/Token/PostAuthenticationToken.php',
        '_ContaoManager\\Symfony\\Component\\Security\\Http\\Authenticator\\X509Authenticator' => __DIR__ . '/..' . '/symfony/security-http/Authenticator/X509Authenticator.php',
        '_ContaoManager\\Symfony\\Component\\Security\\Http\\Authorization\\AccessDeniedHandlerInterface' => __DIR__ . '/..' . '/symfony/security-http/Authorization/AccessDeniedHandlerInterface.php',
        '_ContaoManager\\Symfony\\Component\\Security\\Http\\Controller\\SecurityTokenValueResolver' => __DIR__ . '/..' . '/symfony/security-http/Controller/SecurityTokenValueResolver.php',
        '_ContaoManager\\Symfony\\Component\\Security\\Http\\Controller\\UserValueResolver' => __DIR__ . '/..' . '/symfony/security-http/Controller/UserValueResolver.php',
        '_ContaoManager\\Symfony\\Component\\Security\\Http\\EntryPoint\\AuthenticationEntryPointInterface' => __DIR__ . '/..' . '/symfony/security-http/EntryPoint/AuthenticationEntryPointInterface.php',
        '_ContaoManager\\Symfony\\Component\\Security\\Http\\EntryPoint\\Exception\\NotAnEntryPointException' => __DIR__ . '/..' . '/symfony/security-http/EntryPoint/Exception/NotAnEntryPointException.php',
        '_ContaoManager\\Symfony\\Component\\Security\\Http\\EventListener\\CheckCredentialsListener' => __DIR__ . '/..' . '/symfony/security-http/EventListener/CheckCredentialsListener.php',
        '_ContaoManager\\Symfony\\Component\\Security\\Http\\EventListener\\CheckRememberMeConditionsListener' => __DIR__ . '/..' . '/symfony/security-http/EventListener/CheckRememberMeConditionsListener.php',
        '_ContaoManager\\Symfony\\Component\\Security\\Http\\EventListener\\ClearSiteDataLogoutListener' => __DIR__ . '/..' . '/symfony/security-http/EventListener/ClearSiteDataLogoutListener.php',
        '_ContaoManager\\Symfony\\Component\\Security\\Http\\EventListener\\CookieClearingLogoutListener' => __DIR__ . '/..' . '/symfony/security-http/EventListener/CookieClearingLogoutListener.php',
        '_ContaoManager\\Symfony\\Component\\Security\\Http\\EventListener\\CsrfProtectionListener' => __DIR__ . '/..' . '/symfony/security-http/EventListener/CsrfProtectionListener.php',
        '_ContaoManager\\Symfony\\Component\\Security\\Http\\EventListener\\CsrfTokenClearingLogoutListener' => __DIR__ . '/..' . '/symfony/security-http/EventListener/CsrfTokenClearingLogoutListener.php',
        '_ContaoManager\\Symfony\\Component\\Security\\Http\\EventListener\\DefaultLogoutListener' => __DIR__ . '/..' . '/symfony/security-http/EventListener/DefaultLogoutListener.php',
        '_ContaoManager\\Symfony\\Component\\Security\\Http\\EventListener\\IsGrantedAttributeListener' => __DIR__ . '/..' . '/symfony/security-http/EventListener/IsGrantedAttributeListener.php',
        '_ContaoManager\\Symfony\\Component\\Security\\Http\\EventListener\\LoginThrottlingListener' => __DIR__ . '/..' . '/symfony/security-http/EventListener/LoginThrottlingListener.php',
        '_ContaoManager\\Symfony\\Component\\Security\\Http\\EventListener\\PasswordMigratingListener' => __DIR__ . '/..' . '/symfony/security-http/EventListener/PasswordMigratingListener.php',
        '_ContaoManager\\Symfony\\Component\\Security\\Http\\EventListener\\RememberMeListener' => __DIR__ . '/..' . '/symfony/security-http/EventListener/RememberMeListener.php',
        '_ContaoManager\\Symfony\\Component\\Security\\Http\\EventListener\\SessionLogoutListener' => __DIR__ . '/..' . '/symfony/security-http/EventListener/SessionLogoutListener.php',
        '_ContaoManager\\Symfony\\Component\\Security\\Http\\EventListener\\SessionStrategyListener' => __DIR__ . '/..' . '/symfony/security-http/EventListener/SessionStrategyListener.php',
        '_ContaoManager\\Symfony\\Component\\Security\\Http\\EventListener\\UserCheckerListener' => __DIR__ . '/..' . '/symfony/security-http/EventListener/UserCheckerListener.php',
        '_ContaoManager\\Symfony\\Component\\Security\\Http\\EventListener\\UserProviderListener' => __DIR__ . '/..' . '/symfony/security-http/EventListener/UserProviderListener.php',
        '_ContaoManager\\Symfony\\Component\\Security\\Http\\Event\\AuthenticationTokenCreatedEvent' => __DIR__ . '/..' . '/symfony/security-http/Event/AuthenticationTokenCreatedEvent.php',
        '_ContaoManager\\Symfony\\Component\\Security\\Http\\Event\\CheckPassportEvent' => __DIR__ . '/..' . '/symfony/security-http/Event/CheckPassportEvent.php',
        '_ContaoManager\\Symfony\\Component\\Security\\Http\\Event\\InteractiveLoginEvent' => __DIR__ . '/..' . '/symfony/security-http/Event/InteractiveLoginEvent.php',
        '_ContaoManager\\Symfony\\Component\\Security\\Http\\Event\\LazyResponseEvent' => __DIR__ . '/..' . '/symfony/security-http/Event/LazyResponseEvent.php',
        '_ContaoManager\\Symfony\\Component\\Security\\Http\\Event\\LoginFailureEvent' => __DIR__ . '/..' . '/symfony/security-http/Event/LoginFailureEvent.php',
        '_ContaoManager\\Symfony\\Component\\Security\\Http\\Event\\LoginSuccessEvent' => __DIR__ . '/..' . '/symfony/security-http/Event/LoginSuccessEvent.php',
        '_ContaoManager\\Symfony\\Component\\Security\\Http\\Event\\LogoutEvent' => __DIR__ . '/..' . '/symfony/security-http/Event/LogoutEvent.php',
        '_ContaoManager\\Symfony\\Component\\Security\\Http\\Event\\SwitchUserEvent' => __DIR__ . '/..' . '/symfony/security-http/Event/SwitchUserEvent.php',
        '_ContaoManager\\Symfony\\Component\\Security\\Http\\Event\\TokenDeauthenticatedEvent' => __DIR__ . '/..' . '/symfony/security-http/Event/TokenDeauthenticatedEvent.php',
        '_ContaoManager\\Symfony\\Component\\Security\\Http\\Firewall' => __DIR__ . '/..' . '/symfony/security-http/Firewall.php',
        '_ContaoManager\\Symfony\\Component\\Security\\Http\\FirewallMap' => __DIR__ . '/..' . '/symfony/security-http/FirewallMap.php',
        '_ContaoManager\\Symfony\\Component\\Security\\Http\\FirewallMapInterface' => __DIR__ . '/..' . '/symfony/security-http/FirewallMapInterface.php',
        '_ContaoManager\\Symfony\\Component\\Security\\Http\\Firewall\\AbstractListener' => __DIR__ . '/..' . '/symfony/security-http/Firewall/AbstractListener.php',
        '_ContaoManager\\Symfony\\Component\\Security\\Http\\Firewall\\AccessListener' => __DIR__ . '/..' . '/symfony/security-http/Firewall/AccessListener.php',
        '_ContaoManager\\Symfony\\Component\\Security\\Http\\Firewall\\AuthenticatorManagerListener' => __DIR__ . '/..' . '/symfony/security-http/Firewall/AuthenticatorManagerListener.php',
        '_ContaoManager\\Symfony\\Component\\Security\\Http\\Firewall\\ChannelListener' => __DIR__ . '/..' . '/symfony/security-http/Firewall/ChannelListener.php',
        '_ContaoManager\\Symfony\\Component\\Security\\Http\\Firewall\\ContextListener' => __DIR__ . '/..' . '/symfony/security-http/Firewall/ContextListener.php',
        '_ContaoManager\\Symfony\\Component\\Security\\Http\\Firewall\\ExceptionListener' => __DIR__ . '/..' . '/symfony/security-http/Firewall/ExceptionListener.php',
        '_ContaoManager\\Symfony\\Component\\Security\\Http\\Firewall\\FirewallListenerInterface' => __DIR__ . '/..' . '/symfony/security-http/Firewall/FirewallListenerInterface.php',
        '_ContaoManager\\Symfony\\Component\\Security\\Http\\Firewall\\LogoutListener' => __DIR__ . '/..' . '/symfony/security-http/Firewall/LogoutListener.php',
        '_ContaoManager\\Symfony\\Component\\Security\\Http\\Firewall\\SwitchUserListener' => __DIR__ . '/..' . '/symfony/security-http/Firewall/SwitchUserListener.php',
        '_ContaoManager\\Symfony\\Component\\Security\\Http\\HttpUtils' => __DIR__ . '/..' . '/symfony/security-http/HttpUtils.php',
        '_ContaoManager\\Symfony\\Component\\Security\\Http\\Impersonate\\ImpersonateUrlGenerator' => __DIR__ . '/..' . '/symfony/security-http/Impersonate/ImpersonateUrlGenerator.php',
        '_ContaoManager\\Symfony\\Component\\Security\\Http\\LoginLink\\Exception\\ExpiredLoginLinkException' => __DIR__ . '/..' . '/symfony/security-http/LoginLink/Exception/ExpiredLoginLinkException.php',
        '_ContaoManager\\Symfony\\Component\\Security\\Http\\LoginLink\\Exception\\InvalidLoginLinkAuthenticationException' => __DIR__ . '/..' . '/symfony/security-http/LoginLink/Exception/InvalidLoginLinkAuthenticationException.php',
        '_ContaoManager\\Symfony\\Component\\Security\\Http\\LoginLink\\Exception\\InvalidLoginLinkException' => __DIR__ . '/..' . '/symfony/security-http/LoginLink/Exception/InvalidLoginLinkException.php',
        '_ContaoManager\\Symfony\\Component\\Security\\Http\\LoginLink\\Exception\\InvalidLoginLinkExceptionInterface' => __DIR__ . '/..' . '/symfony/security-http/LoginLink/Exception/InvalidLoginLinkExceptionInterface.php',
        '_ContaoManager\\Symfony\\Component\\Security\\Http\\LoginLink\\LoginLinkDetails' => __DIR__ . '/..' . '/symfony/security-http/LoginLink/LoginLinkDetails.php',
        '_ContaoManager\\Symfony\\Component\\Security\\Http\\LoginLink\\LoginLinkHandler' => __DIR__ . '/..' . '/symfony/security-http/LoginLink/LoginLinkHandler.php',
        '_ContaoManager\\Symfony\\Component\\Security\\Http\\LoginLink\\LoginLinkHandlerInterface' => __DIR__ . '/..' . '/symfony/security-http/LoginLink/LoginLinkHandlerInterface.php',
        '_ContaoManager\\Symfony\\Component\\Security\\Http\\LoginLink\\LoginLinkNotification' => __DIR__ . '/..' . '/symfony/security-http/LoginLink/LoginLinkNotification.php',
        '_ContaoManager\\Symfony\\Component\\Security\\Http\\Logout\\LogoutUrlGenerator' => __DIR__ . '/..' . '/symfony/security-http/Logout/LogoutUrlGenerator.php',
        '_ContaoManager\\Symfony\\Component\\Security\\Http\\ParameterBagUtils' => __DIR__ . '/..' . '/symfony/security-http/ParameterBagUtils.php',
        '_ContaoManager\\Symfony\\Component\\Security\\Http\\RateLimiter\\DefaultLoginRateLimiter' => __DIR__ . '/..' . '/symfony/security-http/RateLimiter/DefaultLoginRateLimiter.php',
        '_ContaoManager\\Symfony\\Component\\Security\\Http\\RememberMe\\AbstractRememberMeHandler' => __DIR__ . '/..' . '/symfony/security-http/RememberMe/AbstractRememberMeHandler.php',
        '_ContaoManager\\Symfony\\Component\\Security\\Http\\RememberMe\\PersistentRememberMeHandler' => __DIR__ . '/..' . '/symfony/security-http/RememberMe/PersistentRememberMeHandler.php',
        '_ContaoManager\\Symfony\\Component\\Security\\Http\\RememberMe\\RememberMeDetails' => __DIR__ . '/..' . '/symfony/security-http/RememberMe/RememberMeDetails.php',
        '_ContaoManager\\Symfony\\Component\\Security\\Http\\RememberMe\\RememberMeHandlerInterface' => __DIR__ . '/..' . '/symfony/security-http/RememberMe/RememberMeHandlerInterface.php',
        '_ContaoManager\\Symfony\\Component\\Security\\Http\\RememberMe\\ResponseListener' => __DIR__ . '/..' . '/symfony/security-http/RememberMe/ResponseListener.php',
        '_ContaoManager\\Symfony\\Component\\Security\\Http\\RememberMe\\SignatureRememberMeHandler' => __DIR__ . '/..' . '/symfony/security-http/RememberMe/SignatureRememberMeHandler.php',
        '_ContaoManager\\Symfony\\Component\\Security\\Http\\SecurityEvents' => __DIR__ . '/..' . '/symfony/security-http/SecurityEvents.php',
        '_ContaoManager\\Symfony\\Component\\Security\\Http\\SecurityRequestAttributes' => __DIR__ . '/..' . '/symfony/security-http/SecurityRequestAttributes.php',
        '_ContaoManager\\Symfony\\Component\\Security\\Http\\Session\\SessionAuthenticationStrategy' => __DIR__ . '/..' . '/symfony/security-http/Session/SessionAuthenticationStrategy.php',
        '_ContaoManager\\Symfony\\Component\\Security\\Http\\Session\\SessionAuthenticationStrategyInterface' => __DIR__ . '/..' . '/symfony/security-http/Session/SessionAuthenticationStrategyInterface.php',
        '_ContaoManager\\Symfony\\Component\\Security\\Http\\Util\\TargetPathTrait' => __DIR__ . '/..' . '/symfony/security-http/Util/TargetPathTrait.php',
        '_ContaoManager\\Symfony\\Component\\Serializer\\Annotation\\Context' => __DIR__ . '/..' . '/symfony/serializer/Annotation/Context.php',
        '_ContaoManager\\Symfony\\Component\\Serializer\\Annotation\\DiscriminatorMap' => __DIR__ . '/..' . '/symfony/serializer/Annotation/DiscriminatorMap.php',
        '_ContaoManager\\Symfony\\Component\\Serializer\\Annotation\\Groups' => __DIR__ . '/..' . '/symfony/serializer/Annotation/Groups.php',
        '_ContaoManager\\Symfony\\Component\\Serializer\\Annotation\\Ignore' => __DIR__ . '/..' . '/symfony/serializer/Annotation/Ignore.php',
        '_ContaoManager\\Symfony\\Component\\Serializer\\Annotation\\MaxDepth' => __DIR__ . '/..' . '/symfony/serializer/Annotation/MaxDepth.php',
        '_ContaoManager\\Symfony\\Component\\Serializer\\Annotation\\SerializedName' => __DIR__ . '/..' . '/symfony/serializer/Annotation/SerializedName.php',
        '_ContaoManager\\Symfony\\Component\\Serializer\\Annotation\\SerializedPath' => __DIR__ . '/..' . '/symfony/serializer/Annotation/SerializedPath.php',
        '_ContaoManager\\Symfony\\Component\\Serializer\\Attribute\\Context' => __DIR__ . '/..' . '/symfony/serializer/Attribute/Context.php',
        '_ContaoManager\\Symfony\\Component\\Serializer\\Attribute\\DiscriminatorMap' => __DIR__ . '/..' . '/symfony/serializer/Attribute/DiscriminatorMap.php',
        '_ContaoManager\\Symfony\\Component\\Serializer\\Attribute\\Groups' => __DIR__ . '/..' . '/symfony/serializer/Attribute/Groups.php',
        '_ContaoManager\\Symfony\\Component\\Serializer\\Attribute\\Ignore' => __DIR__ . '/..' . '/symfony/serializer/Attribute/Ignore.php',
        '_ContaoManager\\Symfony\\Component\\Serializer\\Attribute\\MaxDepth' => __DIR__ . '/..' . '/symfony/serializer/Attribute/MaxDepth.php',
        '_ContaoManager\\Symfony\\Component\\Serializer\\Attribute\\SerializedName' => __DIR__ . '/..' . '/symfony/serializer/Attribute/SerializedName.php',
        '_ContaoManager\\Symfony\\Component\\Serializer\\Attribute\\SerializedPath' => __DIR__ . '/..' . '/symfony/serializer/Attribute/SerializedPath.php',
        '_ContaoManager\\Symfony\\Component\\Serializer\\CacheWarmer\\CompiledClassMetadataCacheWarmer' => __DIR__ . '/..' . '/symfony/serializer/CacheWarmer/CompiledClassMetadataCacheWarmer.php',
        '_ContaoManager\\Symfony\\Component\\Serializer\\Command\\DebugCommand' => __DIR__ . '/..' . '/symfony/serializer/Command/DebugCommand.php',
        '_ContaoManager\\Symfony\\Component\\Serializer\\Context\\ContextBuilderInterface' => __DIR__ . '/..' . '/symfony/serializer/Context/ContextBuilderInterface.php',
        '_ContaoManager\\Symfony\\Component\\Serializer\\Context\\ContextBuilderTrait' => __DIR__ . '/..' . '/symfony/serializer/Context/ContextBuilderTrait.php',
        '_ContaoManager\\Symfony\\Component\\Serializer\\Context\\Encoder\\CsvEncoderContextBuilder' => __DIR__ . '/..' . '/symfony/serializer/Context/Encoder/CsvEncoderContextBuilder.php',
        '_ContaoManager\\Symfony\\Component\\Serializer\\Context\\Encoder\\JsonEncoderContextBuilder' => __DIR__ . '/..' . '/symfony/serializer/Context/Encoder/JsonEncoderContextBuilder.php',
        '_ContaoManager\\Symfony\\Component\\Serializer\\Context\\Encoder\\XmlEncoderContextBuilder' => __DIR__ . '/..' . '/symfony/serializer/Context/Encoder/XmlEncoderContextBuilder.php',
        '_ContaoManager\\Symfony\\Component\\Serializer\\Context\\Encoder\\YamlEncoderContextBuilder' => __DIR__ . '/..' . '/symfony/serializer/Context/Encoder/YamlEncoderContextBuilder.php',
        '_ContaoManager\\Symfony\\Component\\Serializer\\Context\\Normalizer\\AbstractNormalizerContextBuilder' => __DIR__ . '/..' . '/symfony/serializer/Context/Normalizer/AbstractNormalizerContextBuilder.php',
        '_ContaoManager\\Symfony\\Component\\Serializer\\Context\\Normalizer\\AbstractObjectNormalizerContextBuilder' => __DIR__ . '/..' . '/symfony/serializer/Context/Normalizer/AbstractObjectNormalizerContextBuilder.php',
        '_ContaoManager\\Symfony\\Component\\Serializer\\Context\\Normalizer\\BackedEnumNormalizerContextBuilder' => __DIR__ . '/..' . '/symfony/serializer/Context/Normalizer/BackedEnumNormalizerContextBuilder.php',
        '_ContaoManager\\Symfony\\Component\\Serializer\\Context\\Normalizer\\ConstraintViolationListNormalizerContextBuilder' => __DIR__ . '/..' . '/symfony/serializer/Context/Normalizer/ConstraintViolationListNormalizerContextBuilder.php',
        '_ContaoManager\\Symfony\\Component\\Serializer\\Context\\Normalizer\\DateIntervalNormalizerContextBuilder' => __DIR__ . '/..' . '/symfony/serializer/Context/Normalizer/DateIntervalNormalizerContextBuilder.php',
        '_ContaoManager\\Symfony\\Component\\Serializer\\Context\\Normalizer\\DateTimeNormalizerContextBuilder' => __DIR__ . '/..' . '/symfony/serializer/Context/Normalizer/DateTimeNormalizerContextBuilder.php',
        '_ContaoManager\\Symfony\\Component\\Serializer\\Context\\Normalizer\\FormErrorNormalizerContextBuilder' => __DIR__ . '/..' . '/symfony/serializer/Context/Normalizer/FormErrorNormalizerContextBuilder.php',
        '_ContaoManager\\Symfony\\Component\\Serializer\\Context\\Normalizer\\GetSetMethodNormalizerContextBuilder' => __DIR__ . '/..' . '/symfony/serializer/Context/Normalizer/GetSetMethodNormalizerContextBuilder.php',
        '_ContaoManager\\Symfony\\Component\\Serializer\\Context\\Normalizer\\JsonSerializableNormalizerContextBuilder' => __DIR__ . '/..' . '/symfony/serializer/Context/Normalizer/JsonSerializableNormalizerContextBuilder.php',
        '_ContaoManager\\Symfony\\Component\\Serializer\\Context\\Normalizer\\ObjectNormalizerContextBuilder' => __DIR__ . '/..' . '/symfony/serializer/Context/Normalizer/ObjectNormalizerContextBuilder.php',
        '_ContaoManager\\Symfony\\Component\\Serializer\\Context\\Normalizer\\ProblemNormalizerContextBuilder' => __DIR__ . '/..' . '/symfony/serializer/Context/Normalizer/ProblemNormalizerContextBuilder.php',
        '_ContaoManager\\Symfony\\Component\\Serializer\\Context\\Normalizer\\PropertyNormalizerContextBuilder' => __DIR__ . '/..' . '/symfony/serializer/Context/Normalizer/PropertyNormalizerContextBuilder.php',
        '_ContaoManager\\Symfony\\Component\\Serializer\\Context\\Normalizer\\UidNormalizerContextBuilder' => __DIR__ . '/..' . '/symfony/serializer/Context/Normalizer/UidNormalizerContextBuilder.php',
        '_ContaoManager\\Symfony\\Component\\Serializer\\Context\\Normalizer\\UnwrappingDenormalizerContextBuilder' => __DIR__ . '/..' . '/symfony/serializer/Context/Normalizer/UnwrappingDenormalizerContextBuilder.php',
        '_ContaoManager\\Symfony\\Component\\Serializer\\Context\\SerializerContextBuilder' => __DIR__ . '/..' . '/symfony/serializer/Context/SerializerContextBuilder.php',
        '_ContaoManager\\Symfony\\Component\\Serializer\\DataCollector\\SerializerDataCollector' => __DIR__ . '/..' . '/symfony/serializer/DataCollector/SerializerDataCollector.php',
        '_ContaoManager\\Symfony\\Component\\Serializer\\Debug\\TraceableEncoder' => __DIR__ . '/..' . '/symfony/serializer/Debug/TraceableEncoder.php',
        '_ContaoManager\\Symfony\\Component\\Serializer\\Debug\\TraceableNormalizer' => __DIR__ . '/..' . '/symfony/serializer/Debug/TraceableNormalizer.php',
        '_ContaoManager\\Symfony\\Component\\Serializer\\Debug\\TraceableSerializer' => __DIR__ . '/..' . '/symfony/serializer/Debug/TraceableSerializer.php',
        '_ContaoManager\\Symfony\\Component\\Serializer\\DependencyInjection\\SerializerPass' => __DIR__ . '/..' . '/symfony/serializer/DependencyInjection/SerializerPass.php',
        '_ContaoManager\\Symfony\\Component\\Serializer\\Encoder\\ChainDecoder' => __DIR__ . '/..' . '/symfony/serializer/Encoder/ChainDecoder.php',
        '_ContaoManager\\Symfony\\Component\\Serializer\\Encoder\\ChainEncoder' => __DIR__ . '/..' . '/symfony/serializer/Encoder/ChainEncoder.php',
        '_ContaoManager\\Symfony\\Component\\Serializer\\Encoder\\ContextAwareDecoderInterface' => __DIR__ . '/..' . '/symfony/serializer/Encoder/ContextAwareDecoderInterface.php',
        '_ContaoManager\\Symfony\\Component\\Serializer\\Encoder\\ContextAwareEncoderInterface' => __DIR__ . '/..' . '/symfony/serializer/Encoder/ContextAwareEncoderInterface.php',
        '_ContaoManager\\Symfony\\Component\\Serializer\\Encoder\\CsvEncoder' => __DIR__ . '/..' . '/symfony/serializer/Encoder/CsvEncoder.php',
        '_ContaoManager\\Symfony\\Component\\Serializer\\Encoder\\DecoderInterface' => __DIR__ . '/..' . '/symfony/serializer/Encoder/DecoderInterface.php',
        '_ContaoManager\\Symfony\\Component\\Serializer\\Encoder\\EncoderInterface' => __DIR__ . '/..' . '/symfony/serializer/Encoder/EncoderInterface.php',
        '_ContaoManager\\Symfony\\Component\\Serializer\\Encoder\\JsonDecode' => __DIR__ . '/..' . '/symfony/serializer/Encoder/JsonDecode.php',
        '_ContaoManager\\Symfony\\Component\\Serializer\\Encoder\\JsonEncode' => __DIR__ . '/..' . '/symfony/serializer/Encoder/JsonEncode.php',
        '_ContaoManager\\Symfony\\Component\\Serializer\\Encoder\\JsonEncoder' => __DIR__ . '/..' . '/symfony/serializer/Encoder/JsonEncoder.php',
        '_ContaoManager\\Symfony\\Component\\Serializer\\Encoder\\NormalizationAwareInterface' => __DIR__ . '/..' . '/symfony/serializer/Encoder/NormalizationAwareInterface.php',
        '_ContaoManager\\Symfony\\Component\\Serializer\\Encoder\\XmlEncoder' => __DIR__ . '/..' . '/symfony/serializer/Encoder/XmlEncoder.php',
        '_ContaoManager\\Symfony\\Component\\Serializer\\Encoder\\YamlEncoder' => __DIR__ . '/..' . '/symfony/serializer/Encoder/YamlEncoder.php',
        '_ContaoManager\\Symfony\\Component\\Serializer\\Exception\\BadMethodCallException' => __DIR__ . '/..' . '/symfony/serializer/Exception/BadMethodCallException.php',
        '_ContaoManager\\Symfony\\Component\\Serializer\\Exception\\CircularReferenceException' => __DIR__ . '/..' . '/symfony/serializer/Exception/CircularReferenceException.php',
        '_ContaoManager\\Symfony\\Component\\Serializer\\Exception\\ExceptionInterface' => __DIR__ . '/..' . '/symfony/serializer/Exception/ExceptionInterface.php',
        '_ContaoManager\\Symfony\\Component\\Serializer\\Exception\\ExtraAttributesException' => __DIR__ . '/..' . '/symfony/serializer/Exception/ExtraAttributesException.php',
        '_ContaoManager\\Symfony\\Component\\Serializer\\Exception\\InvalidArgumentException' => __DIR__ . '/..' . '/symfony/serializer/Exception/InvalidArgumentException.php',
        '_ContaoManager\\Symfony\\Component\\Serializer\\Exception\\LogicException' => __DIR__ . '/..' . '/symfony/serializer/Exception/LogicException.php',
        '_ContaoManager\\Symfony\\Component\\Serializer\\Exception\\MappingException' => __DIR__ . '/..' . '/symfony/serializer/Exception/MappingException.php',
        '_ContaoManager\\Symfony\\Component\\Serializer\\Exception\\MissingConstructorArgumentsException' => __DIR__ . '/..' . '/symfony/serializer/Exception/MissingConstructorArgumentsException.php',
        '_ContaoManager\\Symfony\\Component\\Serializer\\Exception\\NotEncodableValueException' => __DIR__ . '/..' . '/symfony/serializer/Exception/NotEncodableValueException.php',
        '_ContaoManager\\Symfony\\Component\\Serializer\\Exception\\NotNormalizableValueException' => __DIR__ . '/..' . '/symfony/serializer/Exception/NotNormalizableValueException.php',
        '_ContaoManager\\Symfony\\Component\\Serializer\\Exception\\PartialDenormalizationException' => __DIR__ . '/..' . '/symfony/serializer/Exception/PartialDenormalizationException.php',
        '_ContaoManager\\Symfony\\Component\\Serializer\\Exception\\RuntimeException' => __DIR__ . '/..' . '/symfony/serializer/Exception/RuntimeException.php',
        '_ContaoManager\\Symfony\\Component\\Serializer\\Exception\\UnexpectedValueException' => __DIR__ . '/..' . '/symfony/serializer/Exception/UnexpectedValueException.php',
        '_ContaoManager\\Symfony\\Component\\Serializer\\Exception\\UnsupportedException' => __DIR__ . '/..' . '/symfony/serializer/Exception/UnsupportedException.php',
        '_ContaoManager\\Symfony\\Component\\Serializer\\Exception\\UnsupportedFormatException' => __DIR__ . '/..' . '/symfony/serializer/Exception/UnsupportedFormatException.php',
        '_ContaoManager\\Symfony\\Component\\Serializer\\Extractor\\ObjectPropertyListExtractor' => __DIR__ . '/..' . '/symfony/serializer/Extractor/ObjectPropertyListExtractor.php',
        '_ContaoManager\\Symfony\\Component\\Serializer\\Extractor\\ObjectPropertyListExtractorInterface' => __DIR__ . '/..' . '/symfony/serializer/Extractor/ObjectPropertyListExtractorInterface.php',
        '_ContaoManager\\Symfony\\Component\\Serializer\\Mapping\\AttributeMetadata' => __DIR__ . '/..' . '/symfony/serializer/Mapping/AttributeMetadata.php',
        '_ContaoManager\\Symfony\\Component\\Serializer\\Mapping\\AttributeMetadataInterface' => __DIR__ . '/..' . '/symfony/serializer/Mapping/AttributeMetadataInterface.php',
        '_ContaoManager\\Symfony\\Component\\Serializer\\Mapping\\ClassDiscriminatorFromClassMetadata' => __DIR__ . '/..' . '/symfony/serializer/Mapping/ClassDiscriminatorFromClassMetadata.php',
        '_ContaoManager\\Symfony\\Component\\Serializer\\Mapping\\ClassDiscriminatorMapping' => __DIR__ . '/..' . '/symfony/serializer/Mapping/ClassDiscriminatorMapping.php',
        '_ContaoManager\\Symfony\\Component\\Serializer\\Mapping\\ClassDiscriminatorResolverInterface' => __DIR__ . '/..' . '/symfony/serializer/Mapping/ClassDiscriminatorResolverInterface.php',
        '_ContaoManager\\Symfony\\Component\\Serializer\\Mapping\\ClassMetadata' => __DIR__ . '/..' . '/symfony/serializer/Mapping/ClassMetadata.php',
        '_ContaoManager\\Symfony\\Component\\Serializer\\Mapping\\ClassMetadataInterface' => __DIR__ . '/..' . '/symfony/serializer/Mapping/ClassMetadataInterface.php',
        '_ContaoManager\\Symfony\\Component\\Serializer\\Mapping\\Factory\\CacheClassMetadataFactory' => __DIR__ . '/..' . '/symfony/serializer/Mapping/Factory/CacheClassMetadataFactory.php',
        '_ContaoManager\\Symfony\\Component\\Serializer\\Mapping\\Factory\\ClassMetadataFactory' => __DIR__ . '/..' . '/symfony/serializer/Mapping/Factory/ClassMetadataFactory.php',
        '_ContaoManager\\Symfony\\Component\\Serializer\\Mapping\\Factory\\ClassMetadataFactoryCompiler' => __DIR__ . '/..' . '/symfony/serializer/Mapping/Factory/ClassMetadataFactoryCompiler.php',
        '_ContaoManager\\Symfony\\Component\\Serializer\\Mapping\\Factory\\ClassMetadataFactoryInterface' => __DIR__ . '/..' . '/symfony/serializer/Mapping/Factory/ClassMetadataFactoryInterface.php',
        '_ContaoManager\\Symfony\\Component\\Serializer\\Mapping\\Factory\\ClassResolverTrait' => __DIR__ . '/..' . '/symfony/serializer/Mapping/Factory/ClassResolverTrait.php',
        '_ContaoManager\\Symfony\\Component\\Serializer\\Mapping\\Factory\\CompiledClassMetadataFactory' => __DIR__ . '/..' . '/symfony/serializer/Mapping/Factory/CompiledClassMetadataFactory.php',
        '_ContaoManager\\Symfony\\Component\\Serializer\\Mapping\\Loader\\AccessorCollisionResolverTrait' => __DIR__ . '/..' . '/symfony/serializer/Mapping/Loader/AccessorCollisionResolverTrait.php',
        '_ContaoManager\\Symfony\\Component\\Serializer\\Mapping\\Loader\\AnnotationLoader' => __DIR__ . '/..' . '/symfony/serializer/Mapping/Loader/AnnotationLoader.php',
        '_ContaoManager\\Symfony\\Component\\Serializer\\Mapping\\Loader\\AttributeLoader' => __DIR__ . '/..' . '/symfony/serializer/Mapping/Loader/AttributeLoader.php',
        '_ContaoManager\\Symfony\\Component\\Serializer\\Mapping\\Loader\\FileLoader' => __DIR__ . '/..' . '/symfony/serializer/Mapping/Loader/FileLoader.php',
        '_ContaoManager\\Symfony\\Component\\Serializer\\Mapping\\Loader\\LoaderChain' => __DIR__ . '/..' . '/symfony/serializer/Mapping/Loader/LoaderChain.php',
        '_ContaoManager\\Symfony\\Component\\Serializer\\Mapping\\Loader\\LoaderInterface' => __DIR__ . '/..' . '/symfony/serializer/Mapping/Loader/LoaderInterface.php',
        '_ContaoManager\\Symfony\\Component\\Serializer\\Mapping\\Loader\\XmlFileLoader' => __DIR__ . '/..' . '/symfony/serializer/Mapping/Loader/XmlFileLoader.php',
        '_ContaoManager\\Symfony\\Component\\Serializer\\Mapping\\Loader\\YamlFileLoader' => __DIR__ . '/..' . '/symfony/serializer/Mapping/Loader/YamlFileLoader.php',
        '_ContaoManager\\Symfony\\Component\\Serializer\\NameConverter\\AdvancedNameConverterInterface' => __DIR__ . '/..' . '/symfony/serializer/NameConverter/AdvancedNameConverterInterface.php',
        '_ContaoManager\\Symfony\\Component\\Serializer\\NameConverter\\CamelCaseToSnakeCaseNameConverter' => __DIR__ . '/..' . '/symfony/serializer/NameConverter/CamelCaseToSnakeCaseNameConverter.php',
        '_ContaoManager\\Symfony\\Component\\Serializer\\NameConverter\\MetadataAwareNameConverter' => __DIR__ . '/..' . '/symfony/serializer/NameConverter/MetadataAwareNameConverter.php',
        '_ContaoManager\\Symfony\\Component\\Serializer\\NameConverter\\NameConverterInterface' => __DIR__ . '/..' . '/symfony/serializer/NameConverter/NameConverterInterface.php',
        '_ContaoManager\\Symfony\\Component\\Serializer\\Normalizer\\AbstractNormalizer' => __DIR__ . '/..' . '/symfony/serializer/Normalizer/AbstractNormalizer.php',
        '_ContaoManager\\Symfony\\Component\\Serializer\\Normalizer\\AbstractObjectNormalizer' => __DIR__ . '/..' . '/symfony/serializer/Normalizer/AbstractObjectNormalizer.php',
        '_ContaoManager\\Symfony\\Component\\Serializer\\Normalizer\\ArrayDenormalizer' => __DIR__ . '/..' . '/symfony/serializer/Normalizer/ArrayDenormalizer.php',
        '_ContaoManager\\Symfony\\Component\\Serializer\\Normalizer\\BackedEnumNormalizer' => __DIR__ . '/..' . '/symfony/serializer/Normalizer/BackedEnumNormalizer.php',
        '_ContaoManager\\Symfony\\Component\\Serializer\\Normalizer\\CacheableSupportsMethodInterface' => __DIR__ . '/..' . '/symfony/serializer/Normalizer/CacheableSupportsMethodInterface.php',
        '_ContaoManager\\Symfony\\Component\\Serializer\\Normalizer\\ConstraintViolationListNormalizer' => __DIR__ . '/..' . '/symfony/serializer/Normalizer/ConstraintViolationListNormalizer.php',
        '_ContaoManager\\Symfony\\Component\\Serializer\\Normalizer\\ContextAwareDenormalizerInterface' => __DIR__ . '/..' . '/symfony/serializer/Normalizer/ContextAwareDenormalizerInterface.php',
        '_ContaoManager\\Symfony\\Component\\Serializer\\Normalizer\\ContextAwareNormalizerInterface' => __DIR__ . '/..' . '/symfony/serializer/Normalizer/ContextAwareNormalizerInterface.php',
        '_ContaoManager\\Symfony\\Component\\Serializer\\Normalizer\\CustomNormalizer' => __DIR__ . '/..' . '/symfony/serializer/Normalizer/CustomNormalizer.php',
        '_ContaoManager\\Symfony\\Component\\Serializer\\Normalizer\\DataUriNormalizer' => __DIR__ . '/..' . '/symfony/serializer/Normalizer/DataUriNormalizer.php',
        '_ContaoManager\\Symfony\\Component\\Serializer\\Normalizer\\DateIntervalNormalizer' => __DIR__ . '/..' . '/symfony/serializer/Normalizer/DateIntervalNormalizer.php',
        '_ContaoManager\\Symfony\\Component\\Serializer\\Normalizer\\DateTimeNormalizer' => __DIR__ . '/..' . '/symfony/serializer/Normalizer/DateTimeNormalizer.php',
        '_ContaoManager\\Symfony\\Component\\Serializer\\Normalizer\\DateTimeZoneNormalizer' => __DIR__ . '/..' . '/symfony/serializer/Normalizer/DateTimeZoneNormalizer.php',
        '_ContaoManager\\Symfony\\Component\\Serializer\\Normalizer\\DenormalizableInterface' => __DIR__ . '/..' . '/symfony/serializer/Normalizer/DenormalizableInterface.php',
        '_ContaoManager\\Symfony\\Component\\Serializer\\Normalizer\\DenormalizerAwareInterface' => __DIR__ . '/..' . '/symfony/serializer/Normalizer/DenormalizerAwareInterface.php',
        '_ContaoManager\\Symfony\\Component\\Serializer\\Normalizer\\DenormalizerAwareTrait' => __DIR__ . '/..' . '/symfony/serializer/Normalizer/DenormalizerAwareTrait.php',
        '_ContaoManager\\Symfony\\Component\\Serializer\\Normalizer\\DenormalizerInterface' => __DIR__ . '/..' . '/symfony/serializer/Normalizer/DenormalizerInterface.php',
        '_ContaoManager\\Symfony\\Component\\Serializer\\Normalizer\\FormErrorNormalizer' => __DIR__ . '/..' . '/symfony/serializer/Normalizer/FormErrorNormalizer.php',
        '_ContaoManager\\Symfony\\Component\\Serializer\\Normalizer\\GetSetMethodNormalizer' => __DIR__ . '/..' . '/symfony/serializer/Normalizer/GetSetMethodNormalizer.php',
        '_ContaoManager\\Symfony\\Component\\Serializer\\Normalizer\\JsonSerializableNormalizer' => __DIR__ . '/..' . '/symfony/serializer/Normalizer/JsonSerializableNormalizer.php',
        '_ContaoManager\\Symfony\\Component\\Serializer\\Normalizer\\MimeMessageNormalizer' => __DIR__ . '/..' . '/symfony/serializer/Normalizer/MimeMessageNormalizer.php',
        '_ContaoManager\\Symfony\\Component\\Serializer\\Normalizer\\NormalizableInterface' => __DIR__ . '/..' . '/symfony/serializer/Normalizer/NormalizableInterface.php',
        '_ContaoManager\\Symfony\\Component\\Serializer\\Normalizer\\NormalizerAwareInterface' => __DIR__ . '/..' . '/symfony/serializer/Normalizer/NormalizerAwareInterface.php',
        '_ContaoManager\\Symfony\\Component\\Serializer\\Normalizer\\NormalizerAwareTrait' => __DIR__ . '/..' . '/symfony/serializer/Normalizer/NormalizerAwareTrait.php',
        '_ContaoManager\\Symfony\\Component\\Serializer\\Normalizer\\NormalizerInterface' => __DIR__ . '/..' . '/symfony/serializer/Normalizer/NormalizerInterface.php',
        '_ContaoManager\\Symfony\\Component\\Serializer\\Normalizer\\ObjectNormalizer' => __DIR__ . '/..' . '/symfony/serializer/Normalizer/ObjectNormalizer.php',
        '_ContaoManager\\Symfony\\Component\\Serializer\\Normalizer\\ObjectToPopulateTrait' => __DIR__ . '/..' . '/symfony/serializer/Normalizer/ObjectToPopulateTrait.php',
        '_ContaoManager\\Symfony\\Component\\Serializer\\Normalizer\\ProblemNormalizer' => __DIR__ . '/..' . '/symfony/serializer/Normalizer/ProblemNormalizer.php',
        '_ContaoManager\\Symfony\\Component\\Serializer\\Normalizer\\PropertyNormalizer' => __DIR__ . '/..' . '/symfony/serializer/Normalizer/PropertyNormalizer.php',
        '_ContaoManager\\Symfony\\Component\\Serializer\\Normalizer\\TranslatableNormalizer' => __DIR__ . '/..' . '/symfony/serializer/Normalizer/TranslatableNormalizer.php',
        '_ContaoManager\\Symfony\\Component\\Serializer\\Normalizer\\UidNormalizer' => __DIR__ . '/..' . '/symfony/serializer/Normalizer/UidNormalizer.php',
        '_ContaoManager\\Symfony\\Component\\Serializer\\Normalizer\\UnwrappingDenormalizer' => __DIR__ . '/..' . '/symfony/serializer/Normalizer/UnwrappingDenormalizer.php',
        '_ContaoManager\\Symfony\\Component\\Serializer\\Serializer' => __DIR__ . '/..' . '/symfony/serializer/Serializer.php',
        '_ContaoManager\\Symfony\\Component\\Serializer\\SerializerAwareInterface' => __DIR__ . '/..' . '/symfony/serializer/SerializerAwareInterface.php',
        '_ContaoManager\\Symfony\\Component\\Serializer\\SerializerAwareTrait' => __DIR__ . '/..' . '/symfony/serializer/SerializerAwareTrait.php',
        '_ContaoManager\\Symfony\\Component\\Serializer\\SerializerInterface' => __DIR__ . '/..' . '/symfony/serializer/SerializerInterface.php',
        '_ContaoManager\\Symfony\\Component\\String\\AbstractString' => __DIR__ . '/..' . '/symfony/string/AbstractString.php',
        '_ContaoManager\\Symfony\\Component\\String\\AbstractUnicodeString' => __DIR__ . '/..' . '/symfony/string/AbstractUnicodeString.php',
        '_ContaoManager\\Symfony\\Component\\String\\ByteString' => __DIR__ . '/..' . '/symfony/string/ByteString.php',
        '_ContaoManager\\Symfony\\Component\\String\\CodePointString' => __DIR__ . '/..' . '/symfony/string/CodePointString.php',
        '_ContaoManager\\Symfony\\Component\\String\\Exception\\ExceptionInterface' => __DIR__ . '/..' . '/symfony/string/Exception/ExceptionInterface.php',
        '_ContaoManager\\Symfony\\Component\\String\\Exception\\InvalidArgumentException' => __DIR__ . '/..' . '/symfony/string/Exception/InvalidArgumentException.php',
        '_ContaoManager\\Symfony\\Component\\String\\Exception\\RuntimeException' => __DIR__ . '/..' . '/symfony/string/Exception/RuntimeException.php',
        '_ContaoManager\\Symfony\\Component\\String\\Inflector\\EnglishInflector' => __DIR__ . '/..' . '/symfony/string/Inflector/EnglishInflector.php',
        '_ContaoManager\\Symfony\\Component\\String\\Inflector\\FrenchInflector' => __DIR__ . '/..' . '/symfony/string/Inflector/FrenchInflector.php',
        '_ContaoManager\\Symfony\\Component\\String\\Inflector\\InflectorInterface' => __DIR__ . '/..' . '/symfony/string/Inflector/InflectorInterface.php',
        '_ContaoManager\\Symfony\\Component\\String\\LazyString' => __DIR__ . '/..' . '/symfony/string/LazyString.php',
        '_ContaoManager\\Symfony\\Component\\String\\Slugger\\AsciiSlugger' => __DIR__ . '/..' . '/symfony/string/Slugger/AsciiSlugger.php',
        '_ContaoManager\\Symfony\\Component\\String\\Slugger\\SluggerInterface' => __DIR__ . '/..' . '/symfony/string/Slugger/SluggerInterface.php',
        '_ContaoManager\\Symfony\\Component\\String\\UnicodeString' => __DIR__ . '/..' . '/symfony/string/UnicodeString.php',
        '_ContaoManager\\Symfony\\Component\\Uid\\AbstractUid' => __DIR__ . '/..' . '/symfony/uid/AbstractUid.php',
        '_ContaoManager\\Symfony\\Component\\Uid\\BinaryUtil' => __DIR__ . '/..' . '/symfony/uid/BinaryUtil.php',
        '_ContaoManager\\Symfony\\Component\\Uid\\Command\\GenerateUlidCommand' => __DIR__ . '/..' . '/symfony/uid/Command/GenerateUlidCommand.php',
        '_ContaoManager\\Symfony\\Component\\Uid\\Command\\GenerateUuidCommand' => __DIR__ . '/..' . '/symfony/uid/Command/GenerateUuidCommand.php',
        '_ContaoManager\\Symfony\\Component\\Uid\\Command\\InspectUlidCommand' => __DIR__ . '/..' . '/symfony/uid/Command/InspectUlidCommand.php',
        '_ContaoManager\\Symfony\\Component\\Uid\\Command\\InspectUuidCommand' => __DIR__ . '/..' . '/symfony/uid/Command/InspectUuidCommand.php',
        '_ContaoManager\\Symfony\\Component\\Uid\\Factory\\NameBasedUuidFactory' => __DIR__ . '/..' . '/symfony/uid/Factory/NameBasedUuidFactory.php',
        '_ContaoManager\\Symfony\\Component\\Uid\\Factory\\RandomBasedUuidFactory' => __DIR__ . '/..' . '/symfony/uid/Factory/RandomBasedUuidFactory.php',
        '_ContaoManager\\Symfony\\Component\\Uid\\Factory\\TimeBasedUuidFactory' => __DIR__ . '/..' . '/symfony/uid/Factory/TimeBasedUuidFactory.php',
        '_ContaoManager\\Symfony\\Component\\Uid\\Factory\\UlidFactory' => __DIR__ . '/..' . '/symfony/uid/Factory/UlidFactory.php',
        '_ContaoManager\\Symfony\\Component\\Uid\\Factory\\UuidFactory' => __DIR__ . '/..' . '/symfony/uid/Factory/UuidFactory.php',
        '_ContaoManager\\Symfony\\Component\\Uid\\MaxUlid' => __DIR__ . '/..' . '/symfony/uid/MaxUlid.php',
        '_ContaoManager\\Symfony\\Component\\Uid\\MaxUuid' => __DIR__ . '/..' . '/symfony/uid/MaxUuid.php',
        '_ContaoManager\\Symfony\\Component\\Uid\\NilUlid' => __DIR__ . '/..' . '/symfony/uid/NilUlid.php',
        '_ContaoManager\\Symfony\\Component\\Uid\\NilUuid' => __DIR__ . '/..' . '/symfony/uid/NilUuid.php',
        '_ContaoManager\\Symfony\\Component\\Uid\\TimeBasedUidInterface' => __DIR__ . '/..' . '/symfony/uid/TimeBasedUidInterface.php',
        '_ContaoManager\\Symfony\\Component\\Uid\\Ulid' => __DIR__ . '/..' . '/symfony/uid/Ulid.php',
        '_ContaoManager\\Symfony\\Component\\Uid\\Uuid' => __DIR__ . '/..' . '/symfony/uid/Uuid.php',
        '_ContaoManager\\Symfony\\Component\\Uid\\UuidV1' => __DIR__ . '/..' . '/symfony/uid/UuidV1.php',
        '_ContaoManager\\Symfony\\Component\\Uid\\UuidV3' => __DIR__ . '/..' . '/symfony/uid/UuidV3.php',
        '_ContaoManager\\Symfony\\Component\\Uid\\UuidV4' => __DIR__ . '/..' . '/symfony/uid/UuidV4.php',
        '_ContaoManager\\Symfony\\Component\\Uid\\UuidV5' => __DIR__ . '/..' . '/symfony/uid/UuidV5.php',
        '_ContaoManager\\Symfony\\Component\\Uid\\UuidV6' => __DIR__ . '/..' . '/symfony/uid/UuidV6.php',
        '_ContaoManager\\Symfony\\Component\\Uid\\UuidV7' => __DIR__ . '/..' . '/symfony/uid/UuidV7.php',
        '_ContaoManager\\Symfony\\Component\\Uid\\UuidV8' => __DIR__ . '/..' . '/symfony/uid/UuidV8.php',
        '_ContaoManager\\Symfony\\Component\\VarDumper\\Caster\\AmqpCaster' => __DIR__ . '/..' . '/symfony/var-dumper/Caster/AmqpCaster.php',
        '_ContaoManager\\Symfony\\Component\\VarDumper\\Caster\\ArgsStub' => __DIR__ . '/..' . '/symfony/var-dumper/Caster/ArgsStub.php',
        '_ContaoManager\\Symfony\\Component\\VarDumper\\Caster\\Caster' => __DIR__ . '/..' . '/symfony/var-dumper/Caster/Caster.php',
        '_ContaoManager\\Symfony\\Component\\VarDumper\\Caster\\ClassStub' => __DIR__ . '/..' . '/symfony/var-dumper/Caster/ClassStub.php',
        '_ContaoManager\\Symfony\\Component\\VarDumper\\Caster\\ConstStub' => __DIR__ . '/..' . '/symfony/var-dumper/Caster/ConstStub.php',
        '_ContaoManager\\Symfony\\Component\\VarDumper\\Caster\\CutArrayStub' => __DIR__ . '/..' . '/symfony/var-dumper/Caster/CutArrayStub.php',
        '_ContaoManager\\Symfony\\Component\\VarDumper\\Caster\\CutStub' => __DIR__ . '/..' . '/symfony/var-dumper/Caster/CutStub.php',
        '_ContaoManager\\Symfony\\Component\\VarDumper\\Caster\\DOMCaster' => __DIR__ . '/..' . '/symfony/var-dumper/Caster/DOMCaster.php',
        '_ContaoManager\\Symfony\\Component\\VarDumper\\Caster\\DateCaster' => __DIR__ . '/..' . '/symfony/var-dumper/Caster/DateCaster.php',
        '_ContaoManager\\Symfony\\Component\\VarDumper\\Caster\\DoctrineCaster' => __DIR__ . '/..' . '/symfony/var-dumper/Caster/DoctrineCaster.php',
        '_ContaoManager\\Symfony\\Component\\VarDumper\\Caster\\DsCaster' => __DIR__ . '/..' . '/symfony/var-dumper/Caster/DsCaster.php',
        '_ContaoManager\\Symfony\\Component\\VarDumper\\Caster\\DsPairStub' => __DIR__ . '/..' . '/symfony/var-dumper/Caster/DsPairStub.php',
        '_ContaoManager\\Symfony\\Component\\VarDumper\\Caster\\EnumStub' => __DIR__ . '/..' . '/symfony/var-dumper/Caster/EnumStub.php',
        '_ContaoManager\\Symfony\\Component\\VarDumper\\Caster\\ExceptionCaster' => __DIR__ . '/..' . '/symfony/var-dumper/Caster/ExceptionCaster.php',
        '_ContaoManager\\Symfony\\Component\\VarDumper\\Caster\\FFICaster' => __DIR__ . '/..' . '/symfony/var-dumper/Caster/FFICaster.php',
        '_ContaoManager\\Symfony\\Component\\VarDumper\\Caster\\FiberCaster' => __DIR__ . '/..' . '/symfony/var-dumper/Caster/FiberCaster.php',
        '_ContaoManager\\Symfony\\Component\\VarDumper\\Caster\\FrameStub' => __DIR__ . '/..' . '/symfony/var-dumper/Caster/FrameStub.php',
        '_ContaoManager\\Symfony\\Component\\VarDumper\\Caster\\GmpCaster' => __DIR__ . '/..' . '/symfony/var-dumper/Caster/GmpCaster.php',
        '_ContaoManager\\Symfony\\Component\\VarDumper\\Caster\\ImagineCaster' => __DIR__ . '/..' . '/symfony/var-dumper/Caster/ImagineCaster.php',
        '_ContaoManager\\Symfony\\Component\\VarDumper\\Caster\\ImgStub' => __DIR__ . '/..' . '/symfony/var-dumper/Caster/ImgStub.php',
        '_ContaoManager\\Symfony\\Component\\VarDumper\\Caster\\IntlCaster' => __DIR__ . '/..' . '/symfony/var-dumper/Caster/IntlCaster.php',
        '_ContaoManager\\Symfony\\Component\\VarDumper\\Caster\\LinkStub' => __DIR__ . '/..' . '/symfony/var-dumper/Caster/LinkStub.php',
        '_ContaoManager\\Symfony\\Component\\VarDumper\\Caster\\MemcachedCaster' => __DIR__ . '/..' . '/symfony/var-dumper/Caster/MemcachedCaster.php',
        '_ContaoManager\\Symfony\\Component\\VarDumper\\Caster\\MysqliCaster' => __DIR__ . '/..' . '/symfony/var-dumper/Caster/MysqliCaster.php',
        '_ContaoManager\\Symfony\\Component\\VarDumper\\Caster\\PdoCaster' => __DIR__ . '/..' . '/symfony/var-dumper/Caster/PdoCaster.php',
        '_ContaoManager\\Symfony\\Component\\VarDumper\\Caster\\PgSqlCaster' => __DIR__ . '/..' . '/symfony/var-dumper/Caster/PgSqlCaster.php',
        '_ContaoManager\\Symfony\\Component\\VarDumper\\Caster\\ProxyManagerCaster' => __DIR__ . '/..' . '/symfony/var-dumper/Caster/ProxyManagerCaster.php',
        '_ContaoManager\\Symfony\\Component\\VarDumper\\Caster\\RdKafkaCaster' => __DIR__ . '/..' . '/symfony/var-dumper/Caster/RdKafkaCaster.php',
        '_ContaoManager\\Symfony\\Component\\VarDumper\\Caster\\RedisCaster' => __DIR__ . '/..' . '/symfony/var-dumper/Caster/RedisCaster.php',
        '_ContaoManager\\Symfony\\Component\\VarDumper\\Caster\\ReflectionCaster' => __DIR__ . '/..' . '/symfony/var-dumper/Caster/ReflectionCaster.php',
        '_ContaoManager\\Symfony\\Component\\VarDumper\\Caster\\ResourceCaster' => __DIR__ . '/..' . '/symfony/var-dumper/Caster/ResourceCaster.php',
        '_ContaoManager\\Symfony\\Component\\VarDumper\\Caster\\ScalarStub' => __DIR__ . '/..' . '/symfony/var-dumper/Caster/ScalarStub.php',
        '_ContaoManager\\Symfony\\Component\\VarDumper\\Caster\\SplCaster' => __DIR__ . '/..' . '/symfony/var-dumper/Caster/SplCaster.php',
        '_ContaoManager\\Symfony\\Component\\VarDumper\\Caster\\StubCaster' => __DIR__ . '/..' . '/symfony/var-dumper/Caster/StubCaster.php',
        '_ContaoManager\\Symfony\\Component\\VarDumper\\Caster\\SymfonyCaster' => __DIR__ . '/..' . '/symfony/var-dumper/Caster/SymfonyCaster.php',
        '_ContaoManager\\Symfony\\Component\\VarDumper\\Caster\\TraceStub' => __DIR__ . '/..' . '/symfony/var-dumper/Caster/TraceStub.php',
        '_ContaoManager\\Symfony\\Component\\VarDumper\\Caster\\UninitializedStub' => __DIR__ . '/..' . '/symfony/var-dumper/Caster/UninitializedStub.php',
        '_ContaoManager\\Symfony\\Component\\VarDumper\\Caster\\UuidCaster' => __DIR__ . '/..' . '/symfony/var-dumper/Caster/UuidCaster.php',
        '_ContaoManager\\Symfony\\Component\\VarDumper\\Caster\\XmlReaderCaster' => __DIR__ . '/..' . '/symfony/var-dumper/Caster/XmlReaderCaster.php',
        '_ContaoManager\\Symfony\\Component\\VarDumper\\Caster\\XmlResourceCaster' => __DIR__ . '/..' . '/symfony/var-dumper/Caster/XmlResourceCaster.php',
        '_ContaoManager\\Symfony\\Component\\VarDumper\\Cloner\\AbstractCloner' => __DIR__ . '/..' . '/symfony/var-dumper/Cloner/AbstractCloner.php',
        '_ContaoManager\\Symfony\\Component\\VarDumper\\Cloner\\ClonerInterface' => __DIR__ . '/..' . '/symfony/var-dumper/Cloner/ClonerInterface.php',
        '_ContaoManager\\Symfony\\Component\\VarDumper\\Cloner\\Cursor' => __DIR__ . '/..' . '/symfony/var-dumper/Cloner/Cursor.php',
        '_ContaoManager\\Symfony\\Component\\VarDumper\\Cloner\\Data' => __DIR__ . '/..' . '/symfony/var-dumper/Cloner/Data.php',
        '_ContaoManager\\Symfony\\Component\\VarDumper\\Cloner\\DumperInterface' => __DIR__ . '/..' . '/symfony/var-dumper/Cloner/DumperInterface.php',
        '_ContaoManager\\Symfony\\Component\\VarDumper\\Cloner\\Stub' => __DIR__ . '/..' . '/symfony/var-dumper/Cloner/Stub.php',
        '_ContaoManager\\Symfony\\Component\\VarDumper\\Cloner\\VarCloner' => __DIR__ . '/..' . '/symfony/var-dumper/Cloner/VarCloner.php',
        '_ContaoManager\\Symfony\\Component\\VarDumper\\Command\\Descriptor\\CliDescriptor' => __DIR__ . '/..' . '/symfony/var-dumper/Command/Descriptor/CliDescriptor.php',
        '_ContaoManager\\Symfony\\Component\\VarDumper\\Command\\Descriptor\\DumpDescriptorInterface' => __DIR__ . '/..' . '/symfony/var-dumper/Command/Descriptor/DumpDescriptorInterface.php',
        '_ContaoManager\\Symfony\\Component\\VarDumper\\Command\\Descriptor\\HtmlDescriptor' => __DIR__ . '/..' . '/symfony/var-dumper/Command/Descriptor/HtmlDescriptor.php',
        '_ContaoManager\\Symfony\\Component\\VarDumper\\Command\\ServerDumpCommand' => __DIR__ . '/..' . '/symfony/var-dumper/Command/ServerDumpCommand.php',
        '_ContaoManager\\Symfony\\Component\\VarDumper\\Dumper\\AbstractDumper' => __DIR__ . '/..' . '/symfony/var-dumper/Dumper/AbstractDumper.php',
        '_ContaoManager\\Symfony\\Component\\VarDumper\\Dumper\\CliDumper' => __DIR__ . '/..' . '/symfony/var-dumper/Dumper/CliDumper.php',
        '_ContaoManager\\Symfony\\Component\\VarDumper\\Dumper\\ContextProvider\\CliContextProvider' => __DIR__ . '/..' . '/symfony/var-dumper/Dumper/ContextProvider/CliContextProvider.php',
        '_ContaoManager\\Symfony\\Component\\VarDumper\\Dumper\\ContextProvider\\ContextProviderInterface' => __DIR__ . '/..' . '/symfony/var-dumper/Dumper/ContextProvider/ContextProviderInterface.php',
        '_ContaoManager\\Symfony\\Component\\VarDumper\\Dumper\\ContextProvider\\RequestContextProvider' => __DIR__ . '/..' . '/symfony/var-dumper/Dumper/ContextProvider/RequestContextProvider.php',
        '_ContaoManager\\Symfony\\Component\\VarDumper\\Dumper\\ContextProvider\\SourceContextProvider' => __DIR__ . '/..' . '/symfony/var-dumper/Dumper/ContextProvider/SourceContextProvider.php',
        '_ContaoManager\\Symfony\\Component\\VarDumper\\Dumper\\ContextualizedDumper' => __DIR__ . '/..' . '/symfony/var-dumper/Dumper/ContextualizedDumper.php',
        '_ContaoManager\\Symfony\\Component\\VarDumper\\Dumper\\DataDumperInterface' => __DIR__ . '/..' . '/symfony/var-dumper/Dumper/DataDumperInterface.php',
        '_ContaoManager\\Symfony\\Component\\VarDumper\\Dumper\\HtmlDumper' => __DIR__ . '/..' . '/symfony/var-dumper/Dumper/HtmlDumper.php',
        '_ContaoManager\\Symfony\\Component\\VarDumper\\Dumper\\ServerDumper' => __DIR__ . '/..' . '/symfony/var-dumper/Dumper/ServerDumper.php',
        '_ContaoManager\\Symfony\\Component\\VarDumper\\Exception\\ThrowingCasterException' => __DIR__ . '/..' . '/symfony/var-dumper/Exception/ThrowingCasterException.php',
        '_ContaoManager\\Symfony\\Component\\VarDumper\\Server\\Connection' => __DIR__ . '/..' . '/symfony/var-dumper/Server/Connection.php',
        '_ContaoManager\\Symfony\\Component\\VarDumper\\Server\\DumpServer' => __DIR__ . '/..' . '/symfony/var-dumper/Server/DumpServer.php',
        '_ContaoManager\\Symfony\\Component\\VarDumper\\Test\\VarDumperTestTrait' => __DIR__ . '/..' . '/symfony/var-dumper/Test/VarDumperTestTrait.php',
        '_ContaoManager\\Symfony\\Component\\VarDumper\\VarDumper' => __DIR__ . '/..' . '/symfony/var-dumper/VarDumper.php',
        '_ContaoManager\\Symfony\\Component\\VarExporter\\Exception\\ClassNotFoundException' => __DIR__ . '/..' . '/symfony/var-exporter/Exception/ClassNotFoundException.php',
        '_ContaoManager\\Symfony\\Component\\VarExporter\\Exception\\ExceptionInterface' => __DIR__ . '/..' . '/symfony/var-exporter/Exception/ExceptionInterface.php',
        '_ContaoManager\\Symfony\\Component\\VarExporter\\Exception\\LogicException' => __DIR__ . '/..' . '/symfony/var-exporter/Exception/LogicException.php',
        '_ContaoManager\\Symfony\\Component\\VarExporter\\Exception\\NotInstantiableTypeException' => __DIR__ . '/..' . '/symfony/var-exporter/Exception/NotInstantiableTypeException.php',
        '_ContaoManager\\Symfony\\Component\\VarExporter\\Hydrator' => __DIR__ . '/..' . '/symfony/var-exporter/Hydrator.php',
        '_ContaoManager\\Symfony\\Component\\VarExporter\\Instantiator' => __DIR__ . '/..' . '/symfony/var-exporter/Instantiator.php',
        '_ContaoManager\\Symfony\\Component\\VarExporter\\Internal\\Exporter' => __DIR__ . '/..' . '/symfony/var-exporter/Internal/Exporter.php',
        '_ContaoManager\\Symfony\\Component\\VarExporter\\Internal\\Hydrator' => __DIR__ . '/..' . '/symfony/var-exporter/Internal/Hydrator.php',
        '_ContaoManager\\Symfony\\Component\\VarExporter\\Internal\\LazyObjectRegistry' => __DIR__ . '/..' . '/symfony/var-exporter/Internal/LazyObjectRegistry.php',
        '_ContaoManager\\Symfony\\Component\\VarExporter\\Internal\\LazyObjectState' => __DIR__ . '/..' . '/symfony/var-exporter/Internal/LazyObjectState.php',
        '_ContaoManager\\Symfony\\Component\\VarExporter\\Internal\\LazyObjectTrait' => __DIR__ . '/..' . '/symfony/var-exporter/Internal/LazyObjectTrait.php',
        '_ContaoManager\\Symfony\\Component\\VarExporter\\Internal\\Reference' => __DIR__ . '/..' . '/symfony/var-exporter/Internal/Reference.php',
        '_ContaoManager\\Symfony\\Component\\VarExporter\\Internal\\Registry' => __DIR__ . '/..' . '/symfony/var-exporter/Internal/Registry.php',
        '_ContaoManager\\Symfony\\Component\\VarExporter\\Internal\\Values' => __DIR__ . '/..' . '/symfony/var-exporter/Internal/Values.php',
        '_ContaoManager\\Symfony\\Component\\VarExporter\\LazyGhostTrait' => __DIR__ . '/..' . '/symfony/var-exporter/LazyGhostTrait.php',
        '_ContaoManager\\Symfony\\Component\\VarExporter\\LazyObjectInterface' => __DIR__ . '/..' . '/symfony/var-exporter/LazyObjectInterface.php',
        '_ContaoManager\\Symfony\\Component\\VarExporter\\LazyProxyTrait' => __DIR__ . '/..' . '/symfony/var-exporter/LazyProxyTrait.php',
        '_ContaoManager\\Symfony\\Component\\VarExporter\\ProxyHelper' => __DIR__ . '/..' . '/symfony/var-exporter/ProxyHelper.php',
        '_ContaoManager\\Symfony\\Component\\VarExporter\\VarExporter' => __DIR__ . '/..' . '/symfony/var-exporter/VarExporter.php',
        '_ContaoManager\\Symfony\\Component\\Yaml\\Command\\LintCommand' => __DIR__ . '/..' . '/symfony/yaml/Command/LintCommand.php',
        '_ContaoManager\\Symfony\\Component\\Yaml\\Dumper' => __DIR__ . '/..' . '/symfony/yaml/Dumper.php',
        '_ContaoManager\\Symfony\\Component\\Yaml\\Escaper' => __DIR__ . '/..' . '/symfony/yaml/Escaper.php',
        '_ContaoManager\\Symfony\\Component\\Yaml\\Exception\\DumpException' => __DIR__ . '/..' . '/symfony/yaml/Exception/DumpException.php',
        '_ContaoManager\\Symfony\\Component\\Yaml\\Exception\\ExceptionInterface' => __DIR__ . '/..' . '/symfony/yaml/Exception/ExceptionInterface.php',
        '_ContaoManager\\Symfony\\Component\\Yaml\\Exception\\ParseException' => __DIR__ . '/..' . '/symfony/yaml/Exception/ParseException.php',
        '_ContaoManager\\Symfony\\Component\\Yaml\\Exception\\RuntimeException' => __DIR__ . '/..' . '/symfony/yaml/Exception/RuntimeException.php',
        '_ContaoManager\\Symfony\\Component\\Yaml\\Inline' => __DIR__ . '/..' . '/symfony/yaml/Inline.php',
        '_ContaoManager\\Symfony\\Component\\Yaml\\Parser' => __DIR__ . '/..' . '/symfony/yaml/Parser.php',
        '_ContaoManager\\Symfony\\Component\\Yaml\\Tag\\TaggedValue' => __DIR__ . '/..' . '/symfony/yaml/Tag/TaggedValue.php',
        '_ContaoManager\\Symfony\\Component\\Yaml\\Unescaper' => __DIR__ . '/..' . '/symfony/yaml/Unescaper.php',
        '_ContaoManager\\Symfony\\Component\\Yaml\\Yaml' => __DIR__ . '/..' . '/symfony/yaml/Yaml.php',
        '_ContaoManager\\Symfony\\Contracts\\Cache\\CacheInterface' => __DIR__ . '/..' . '/symfony/cache-contracts/CacheInterface.php',
        '_ContaoManager\\Symfony\\Contracts\\Cache\\CacheTrait' => __DIR__ . '/..' . '/symfony/cache-contracts/CacheTrait.php',
        '_ContaoManager\\Symfony\\Contracts\\Cache\\CallbackInterface' => __DIR__ . '/..' . '/symfony/cache-contracts/CallbackInterface.php',
        '_ContaoManager\\Symfony\\Contracts\\Cache\\ItemInterface' => __DIR__ . '/..' . '/symfony/cache-contracts/ItemInterface.php',
        '_ContaoManager\\Symfony\\Contracts\\Cache\\NamespacedPoolInterface' => __DIR__ . '/..' . '/symfony/cache-contracts/NamespacedPoolInterface.php',
        '_ContaoManager\\Symfony\\Contracts\\Cache\\TagAwareCacheInterface' => __DIR__ . '/..' . '/symfony/cache-contracts/TagAwareCacheInterface.php',
        '_ContaoManager\\Symfony\\Contracts\\EventDispatcher\\Event' => __DIR__ . '/..' . '/symfony/event-dispatcher-contracts/Event.php',
        '_ContaoManager\\Symfony\\Contracts\\EventDispatcher\\EventDispatcherInterface' => __DIR__ . '/..' . '/symfony/event-dispatcher-contracts/EventDispatcherInterface.php',
        '_ContaoManager\\Symfony\\Contracts\\Service\\Attribute\\Required' => __DIR__ . '/..' . '/symfony/service-contracts/Attribute/Required.php',
        '_ContaoManager\\Symfony\\Contracts\\Service\\Attribute\\SubscribedService' => __DIR__ . '/..' . '/symfony/service-contracts/Attribute/SubscribedService.php',
        '_ContaoManager\\Symfony\\Contracts\\Service\\ResetInterface' => __DIR__ . '/..' . '/symfony/service-contracts/ResetInterface.php',
        '_ContaoManager\\Symfony\\Contracts\\Service\\ServiceCollectionInterface' => __DIR__ . '/..' . '/symfony/service-contracts/ServiceCollectionInterface.php',
        '_ContaoManager\\Symfony\\Contracts\\Service\\ServiceLocatorTrait' => __DIR__ . '/..' . '/symfony/service-contracts/ServiceLocatorTrait.php',
        '_ContaoManager\\Symfony\\Contracts\\Service\\ServiceMethodsSubscriberTrait' => __DIR__ . '/..' . '/symfony/service-contracts/ServiceMethodsSubscriberTrait.php',
        '_ContaoManager\\Symfony\\Contracts\\Service\\ServiceProviderInterface' => __DIR__ . '/..' . '/symfony/service-contracts/ServiceProviderInterface.php',
        '_ContaoManager\\Symfony\\Contracts\\Service\\ServiceSubscriberInterface' => __DIR__ . '/..' . '/symfony/service-contracts/ServiceSubscriberInterface.php',
        '_ContaoManager\\Symfony\\Contracts\\Service\\ServiceSubscriberTrait' => __DIR__ . '/..' . '/symfony/service-contracts/ServiceSubscriberTrait.php',
        '_ContaoManager\\Terminal42\\ComposerLockValidator\\ValidationException' => __DIR__ . '/..' . '/terminal42/composer-lock-validator/src/ValidationException.php',
        '_ContaoManager\\Terminal42\\ComposerLockValidator\\Validator' => __DIR__ . '/..' . '/terminal42/composer-lock-validator/src/Validator.php',
        '_ContaoManager\\Webauthn\\AttestationStatement\\AndroidKeyAttestationStatementSupport' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/AttestationStatement/AndroidKeyAttestationStatementSupport.php',
        '_ContaoManager\\Webauthn\\AttestationStatement\\AndroidSafetyNetAttestationStatementSupport' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/AttestationStatement/AndroidSafetyNetAttestationStatementSupport.php',
        '_ContaoManager\\Webauthn\\AttestationStatement\\AppleAttestationStatementSupport' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/AttestationStatement/AppleAttestationStatementSupport.php',
        '_ContaoManager\\Webauthn\\AttestationStatement\\AttestationObject' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/AttestationStatement/AttestationObject.php',
        '_ContaoManager\\Webauthn\\AttestationStatement\\AttestationObjectLoader' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/AttestationStatement/AttestationObjectLoader.php',
        '_ContaoManager\\Webauthn\\AttestationStatement\\AttestationStatement' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/AttestationStatement/AttestationStatement.php',
        '_ContaoManager\\Webauthn\\AttestationStatement\\AttestationStatementSupport' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/AttestationStatement/AttestationStatementSupport.php',
        '_ContaoManager\\Webauthn\\AttestationStatement\\AttestationStatementSupportManager' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/AttestationStatement/AttestationStatementSupportManager.php',
        '_ContaoManager\\Webauthn\\AttestationStatement\\FidoU2FAttestationStatementSupport' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/AttestationStatement/FidoU2FAttestationStatementSupport.php',
        '_ContaoManager\\Webauthn\\AttestationStatement\\NoneAttestationStatementSupport' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/AttestationStatement/NoneAttestationStatementSupport.php',
        '_ContaoManager\\Webauthn\\AttestationStatement\\PackedAttestationStatementSupport' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/AttestationStatement/PackedAttestationStatementSupport.php',
        '_ContaoManager\\Webauthn\\AttestationStatement\\TPMAttestationStatementSupport' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/AttestationStatement/TPMAttestationStatementSupport.php',
        '_ContaoManager\\Webauthn\\AttestedCredentialData' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/AttestedCredentialData.php',
        '_ContaoManager\\Webauthn\\AuthenticationExtensions\\AuthenticationExtension' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/AuthenticationExtensions/AuthenticationExtension.php',
        '_ContaoManager\\Webauthn\\AuthenticationExtensions\\AuthenticationExtensions' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/AuthenticationExtensions/AuthenticationExtensions.php',
        '_ContaoManager\\Webauthn\\AuthenticationExtensions\\AuthenticationExtensionsClientInputs' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/AuthenticationExtensions/AuthenticationExtensionsClientInputs.php',
        '_ContaoManager\\Webauthn\\AuthenticationExtensions\\AuthenticationExtensionsClientOutputs' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/AuthenticationExtensions/AuthenticationExtensionsClientOutputs.php',
        '_ContaoManager\\Webauthn\\AuthenticationExtensions\\AuthenticationExtensionsClientOutputsLoader' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/AuthenticationExtensions/AuthenticationExtensionsClientOutputsLoader.php',
        '_ContaoManager\\Webauthn\\AuthenticationExtensions\\ExtensionOutputChecker' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/AuthenticationExtensions/ExtensionOutputChecker.php',
        '_ContaoManager\\Webauthn\\AuthenticationExtensions\\ExtensionOutputCheckerHandler' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/AuthenticationExtensions/ExtensionOutputCheckerHandler.php',
        '_ContaoManager\\Webauthn\\AuthenticationExtensions\\ExtensionOutputError' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/AuthenticationExtensions/ExtensionOutputError.php',
        '_ContaoManager\\Webauthn\\AuthenticatorAssertionResponse' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/AuthenticatorAssertionResponse.php',
        '_ContaoManager\\Webauthn\\AuthenticatorAssertionResponseValidator' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/AuthenticatorAssertionResponseValidator.php',
        '_ContaoManager\\Webauthn\\AuthenticatorAttestationResponse' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/AuthenticatorAttestationResponse.php',
        '_ContaoManager\\Webauthn\\AuthenticatorAttestationResponseValidator' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/AuthenticatorAttestationResponseValidator.php',
        '_ContaoManager\\Webauthn\\AuthenticatorData' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/AuthenticatorData.php',
        '_ContaoManager\\Webauthn\\AuthenticatorDataLoader' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/AuthenticatorDataLoader.php',
        '_ContaoManager\\Webauthn\\AuthenticatorResponse' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/AuthenticatorResponse.php',
        '_ContaoManager\\Webauthn\\AuthenticatorSelectionCriteria' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/AuthenticatorSelectionCriteria.php',
        '_ContaoManager\\Webauthn\\CeremonyStep\\CeremonyStep' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/CeremonyStep/CeremonyStep.php',
        '_ContaoManager\\Webauthn\\CeremonyStep\\CeremonyStepManager' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/CeremonyStep/CeremonyStepManager.php',
        '_ContaoManager\\Webauthn\\CeremonyStep\\CeremonyStepManagerFactory' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/CeremonyStep/CeremonyStepManagerFactory.php',
        '_ContaoManager\\Webauthn\\CeremonyStep\\CheckAlgorithm' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/CeremonyStep/CheckAlgorithm.php',
        '_ContaoManager\\Webauthn\\CeremonyStep\\CheckAllowedCredentialList' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/CeremonyStep/CheckAllowedCredentialList.php',
        '_ContaoManager\\Webauthn\\CeremonyStep\\CheckAttestationFormatIsKnownAndValid' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/CeremonyStep/CheckAttestationFormatIsKnownAndValid.php',
        '_ContaoManager\\Webauthn\\CeremonyStep\\CheckBackupBitsAreConsistent' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/CeremonyStep/CheckBackupBitsAreConsistent.php',
        '_ContaoManager\\Webauthn\\CeremonyStep\\CheckChallenge' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/CeremonyStep/CheckChallenge.php',
        '_ContaoManager\\Webauthn\\CeremonyStep\\CheckClientDataCollectorType' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/CeremonyStep/CheckClientDataCollectorType.php',
        '_ContaoManager\\Webauthn\\CeremonyStep\\CheckCounter' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/CeremonyStep/CheckCounter.php',
        '_ContaoManager\\Webauthn\\CeremonyStep\\CheckCredentialId' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/CeremonyStep/CheckCredentialId.php',
        '_ContaoManager\\Webauthn\\CeremonyStep\\CheckExtensions' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/CeremonyStep/CheckExtensions.php',
        '_ContaoManager\\Webauthn\\CeremonyStep\\CheckHasAttestedCredentialData' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/CeremonyStep/CheckHasAttestedCredentialData.php',
        '_ContaoManager\\Webauthn\\CeremonyStep\\CheckMetadataStatement' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/CeremonyStep/CheckMetadataStatement.php',
        '_ContaoManager\\Webauthn\\CeremonyStep\\CheckOrigin' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/CeremonyStep/CheckOrigin.php',
        '_ContaoManager\\Webauthn\\CeremonyStep\\CheckRelyingPartyIdIdHash' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/CeremonyStep/CheckRelyingPartyIdIdHash.php',
        '_ContaoManager\\Webauthn\\CeremonyStep\\CheckSignature' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/CeremonyStep/CheckSignature.php',
        '_ContaoManager\\Webauthn\\CeremonyStep\\CheckTopOrigin' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/CeremonyStep/CheckTopOrigin.php',
        '_ContaoManager\\Webauthn\\CeremonyStep\\CheckUserHandle' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/CeremonyStep/CheckUserHandle.php',
        '_ContaoManager\\Webauthn\\CeremonyStep\\CheckUserVerification' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/CeremonyStep/CheckUserVerification.php',
        '_ContaoManager\\Webauthn\\CeremonyStep\\CheckUserWasPresent' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/CeremonyStep/CheckUserWasPresent.php',
        '_ContaoManager\\Webauthn\\CeremonyStep\\HostTopOriginValidator' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/CeremonyStep/HostTopOriginValidator.php',
        '_ContaoManager\\Webauthn\\CeremonyStep\\TopOriginValidator' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/CeremonyStep/TopOriginValidator.php',
        '_ContaoManager\\Webauthn\\CertificateChainChecker\\CertificateChainChecker' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/CertificateChainChecker/CertificateChainChecker.php',
        '_ContaoManager\\Webauthn\\CertificateChainChecker\\PhpCertificateChainChecker' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/CertificateChainChecker/PhpCertificateChainChecker.php',
        '_ContaoManager\\Webauthn\\CertificateToolbox' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/CertificateToolbox.php',
        '_ContaoManager\\Webauthn\\ClientDataCollector\\ClientDataCollector' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/ClientDataCollector/ClientDataCollector.php',
        '_ContaoManager\\Webauthn\\ClientDataCollector\\ClientDataCollectorManager' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/ClientDataCollector/ClientDataCollectorManager.php',
        '_ContaoManager\\Webauthn\\ClientDataCollector\\WebauthnAuthenticationCollector' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/ClientDataCollector/WebauthnAuthenticationCollector.php',
        '_ContaoManager\\Webauthn\\CollectedClientData' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/CollectedClientData.php',
        '_ContaoManager\\Webauthn\\Counter\\CounterChecker' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/Counter/CounterChecker.php',
        '_ContaoManager\\Webauthn\\Counter\\ThrowExceptionIfInvalid' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/Counter/ThrowExceptionIfInvalid.php',
        '_ContaoManager\\Webauthn\\Credential' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/Credential.php',
        '_ContaoManager\\Webauthn\\Denormalizer\\AttestationObjectDenormalizer' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/Denormalizer/AttestationObjectDenormalizer.php',
        '_ContaoManager\\Webauthn\\Denormalizer\\AttestationStatementDenormalizer' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/Denormalizer/AttestationStatementDenormalizer.php',
        '_ContaoManager\\Webauthn\\Denormalizer\\AttestedCredentialDataNormalizer' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/Denormalizer/AttestedCredentialDataNormalizer.php',
        '_ContaoManager\\Webauthn\\Denormalizer\\AuthenticationExtensionNormalizer' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/Denormalizer/AuthenticationExtensionNormalizer.php',
        '_ContaoManager\\Webauthn\\Denormalizer\\AuthenticationExtensionsDenormalizer' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/Denormalizer/AuthenticationExtensionsDenormalizer.php',
        '_ContaoManager\\Webauthn\\Denormalizer\\AuthenticatorAssertionResponseDenormalizer' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/Denormalizer/AuthenticatorAssertionResponseDenormalizer.php',
        '_ContaoManager\\Webauthn\\Denormalizer\\AuthenticatorAttestationResponseDenormalizer' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/Denormalizer/AuthenticatorAttestationResponseDenormalizer.php',
        '_ContaoManager\\Webauthn\\Denormalizer\\AuthenticatorDataDenormalizer' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/Denormalizer/AuthenticatorDataDenormalizer.php',
        '_ContaoManager\\Webauthn\\Denormalizer\\AuthenticatorResponseDenormalizer' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/Denormalizer/AuthenticatorResponseDenormalizer.php',
        '_ContaoManager\\Webauthn\\Denormalizer\\CollectedClientDataDenormalizer' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/Denormalizer/CollectedClientDataDenormalizer.php',
        '_ContaoManager\\Webauthn\\Denormalizer\\ExtensionDescriptorDenormalizer' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/Denormalizer/ExtensionDescriptorDenormalizer.php',
        '_ContaoManager\\Webauthn\\Denormalizer\\PublicKeyCredentialDenormalizer' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/Denormalizer/PublicKeyCredentialDenormalizer.php',
        '_ContaoManager\\Webauthn\\Denormalizer\\PublicKeyCredentialDescriptorNormalizer' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/Denormalizer/PublicKeyCredentialDescriptorNormalizer.php',
        '_ContaoManager\\Webauthn\\Denormalizer\\PublicKeyCredentialOptionsDenormalizer' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/Denormalizer/PublicKeyCredentialOptionsDenormalizer.php',
        '_ContaoManager\\Webauthn\\Denormalizer\\PublicKeyCredentialParametersDenormalizer' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/Denormalizer/PublicKeyCredentialParametersDenormalizer.php',
        '_ContaoManager\\Webauthn\\Denormalizer\\PublicKeyCredentialSourceDenormalizer' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/Denormalizer/PublicKeyCredentialSourceDenormalizer.php',
        '_ContaoManager\\Webauthn\\Denormalizer\\PublicKeyCredentialUserEntityDenormalizer' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/Denormalizer/PublicKeyCredentialUserEntityDenormalizer.php',
        '_ContaoManager\\Webauthn\\Denormalizer\\TrustPathDenormalizer' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/Denormalizer/TrustPathDenormalizer.php',
        '_ContaoManager\\Webauthn\\Denormalizer\\VerificationMethodANDCombinationsDenormalizer' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/Denormalizer/VerificationMethodANDCombinationsDenormalizer.php',
        '_ContaoManager\\Webauthn\\Denormalizer\\WebauthnSerializerFactory' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/Denormalizer/WebauthnSerializerFactory.php',
        '_ContaoManager\\Webauthn\\Event\\AttestationObjectLoaded' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/Event/AttestationObjectLoaded.php',
        '_ContaoManager\\Webauthn\\Event\\AttestationStatementLoaded' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/Event/AttestationStatementLoaded.php',
        '_ContaoManager\\Webauthn\\Event\\AuthenticatorAssertionResponseValidationFailedEvent' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/Event/AuthenticatorAssertionResponseValidationFailedEvent.php',
        '_ContaoManager\\Webauthn\\Event\\AuthenticatorAssertionResponseValidationSucceededEvent' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/Event/AuthenticatorAssertionResponseValidationSucceededEvent.php',
        '_ContaoManager\\Webauthn\\Event\\AuthenticatorAttestationResponseValidationFailedEvent' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/Event/AuthenticatorAttestationResponseValidationFailedEvent.php',
        '_ContaoManager\\Webauthn\\Event\\AuthenticatorAttestationResponseValidationSucceededEvent' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/Event/AuthenticatorAttestationResponseValidationSucceededEvent.php',
        '_ContaoManager\\Webauthn\\Event\\BeforeCertificateChainValidation' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/Event/BeforeCertificateChainValidation.php',
        '_ContaoManager\\Webauthn\\Event\\CanDispatchEvents' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/Event/CanDispatchEvents.php',
        '_ContaoManager\\Webauthn\\Event\\CertificateChainValidationFailed' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/Event/CertificateChainValidationFailed.php',
        '_ContaoManager\\Webauthn\\Event\\CertificateChainValidationSucceeded' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/Event/CertificateChainValidationSucceeded.php',
        '_ContaoManager\\Webauthn\\Event\\MetadataStatementFound' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/Event/MetadataStatementFound.php',
        '_ContaoManager\\Webauthn\\Event\\NullEventDispatcher' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/Event/NullEventDispatcher.php',
        '_ContaoManager\\Webauthn\\Event\\WebauthnEvent' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/Event/WebauthnEvent.php',
        '_ContaoManager\\Webauthn\\Exception\\AttestationStatementException' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/Exception/AttestationStatementException.php',
        '_ContaoManager\\Webauthn\\Exception\\AttestationStatementLoadingException' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/Exception/AttestationStatementLoadingException.php',
        '_ContaoManager\\Webauthn\\Exception\\AttestationStatementVerificationException' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/Exception/AttestationStatementVerificationException.php',
        '_ContaoManager\\Webauthn\\Exception\\AuthenticationExtensionException' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/Exception/AuthenticationExtensionException.php',
        '_ContaoManager\\Webauthn\\Exception\\AuthenticatorResponseVerificationException' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/Exception/AuthenticatorResponseVerificationException.php',
        '_ContaoManager\\Webauthn\\Exception\\CertificateChainException' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/Exception/CertificateChainException.php',
        '_ContaoManager\\Webauthn\\Exception\\CertificateException' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/Exception/CertificateException.php',
        '_ContaoManager\\Webauthn\\Exception\\CertificateRevocationListException' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/Exception/CertificateRevocationListException.php',
        '_ContaoManager\\Webauthn\\Exception\\CounterException' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/Exception/CounterException.php',
        '_ContaoManager\\Webauthn\\Exception\\ExpiredCertificateException' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/Exception/ExpiredCertificateException.php',
        '_ContaoManager\\Webauthn\\Exception\\InvalidAttestationStatementException' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/Exception/InvalidAttestationStatementException.php',
        '_ContaoManager\\Webauthn\\Exception\\InvalidCertificateException' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/Exception/InvalidCertificateException.php',
        '_ContaoManager\\Webauthn\\Exception\\InvalidDataException' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/Exception/InvalidDataException.php',
        '_ContaoManager\\Webauthn\\Exception\\InvalidTrustPathException' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/Exception/InvalidTrustPathException.php',
        '_ContaoManager\\Webauthn\\Exception\\InvalidUserHandleException' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/Exception/InvalidUserHandleException.php',
        '_ContaoManager\\Webauthn\\Exception\\MetadataServiceException' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/Exception/MetadataServiceException.php',
        '_ContaoManager\\Webauthn\\Exception\\MetadataStatementException' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/Exception/MetadataStatementException.php',
        '_ContaoManager\\Webauthn\\Exception\\MetadataStatementLoadingException' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/Exception/MetadataStatementLoadingException.php',
        '_ContaoManager\\Webauthn\\Exception\\MissingMetadataStatementException' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/Exception/MissingMetadataStatementException.php',
        '_ContaoManager\\Webauthn\\Exception\\RevokedCertificateException' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/Exception/RevokedCertificateException.php',
        '_ContaoManager\\Webauthn\\Exception\\UnsupportedFeatureException' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/Exception/UnsupportedFeatureException.php',
        '_ContaoManager\\Webauthn\\Exception\\WebauthnException' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/Exception/WebauthnException.php',
        '_ContaoManager\\Webauthn\\FakeCredentialGenerator' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/FakeCredentialGenerator.php',
        '_ContaoManager\\Webauthn\\MetadataService\\CanLogData' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/MetadataService/CanLogData.php',
        '_ContaoManager\\Webauthn\\MetadataService\\CertificateChain\\CertificateChainValidator' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/MetadataService/CertificateChain/CertificateChainValidator.php',
        '_ContaoManager\\Webauthn\\MetadataService\\CertificateChain\\CertificateToolbox' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/MetadataService/CertificateChain/CertificateToolbox.php',
        '_ContaoManager\\Webauthn\\MetadataService\\CertificateChain\\PhpCertificateChainValidator' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/MetadataService/CertificateChain/PhpCertificateChainValidator.php',
        '_ContaoManager\\Webauthn\\MetadataService\\Denormalizer\\ExtensionDescriptorDenormalizer' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/MetadataService/Denormalizer/ExtensionDescriptorDenormalizer.php',
        '_ContaoManager\\Webauthn\\MetadataService\\Denormalizer\\MetadataStatementSerializerFactory' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/MetadataService/Denormalizer/MetadataStatementSerializerFactory.php',
        '_ContaoManager\\Webauthn\\MetadataService\\Event\\BeforeCertificateChainValidation' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/MetadataService/Event/BeforeCertificateChainValidation.php',
        '_ContaoManager\\Webauthn\\MetadataService\\Event\\CanDispatchEvents' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/MetadataService/Event/CanDispatchEvents.php',
        '_ContaoManager\\Webauthn\\MetadataService\\Event\\CertificateChainValidationFailed' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/MetadataService/Event/CertificateChainValidationFailed.php',
        '_ContaoManager\\Webauthn\\MetadataService\\Event\\CertificateChainValidationSucceeded' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/MetadataService/Event/CertificateChainValidationSucceeded.php',
        '_ContaoManager\\Webauthn\\MetadataService\\Event\\MetadataStatementFound' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/MetadataService/Event/MetadataStatementFound.php',
        '_ContaoManager\\Webauthn\\MetadataService\\Event\\NullEventDispatcher' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/MetadataService/Event/NullEventDispatcher.php',
        '_ContaoManager\\Webauthn\\MetadataService\\Event\\WebauthnEvent' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/MetadataService/Event/WebauthnEvent.php',
        '_ContaoManager\\Webauthn\\MetadataService\\Exception\\CertificateChainException' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/MetadataService/Exception/CertificateChainException.php',
        '_ContaoManager\\Webauthn\\MetadataService\\Exception\\CertificateException' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/MetadataService/Exception/CertificateException.php',
        '_ContaoManager\\Webauthn\\MetadataService\\Exception\\CertificateRevocationListException' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/MetadataService/Exception/CertificateRevocationListException.php',
        '_ContaoManager\\Webauthn\\MetadataService\\Exception\\ExpiredCertificateException' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/MetadataService/Exception/ExpiredCertificateException.php',
        '_ContaoManager\\Webauthn\\MetadataService\\Exception\\InvalidCertificateException' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/MetadataService/Exception/InvalidCertificateException.php',
        '_ContaoManager\\Webauthn\\MetadataService\\Exception\\MetadataServiceException' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/MetadataService/Exception/MetadataServiceException.php',
        '_ContaoManager\\Webauthn\\MetadataService\\Exception\\MetadataStatementException' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/MetadataService/Exception/MetadataStatementException.php',
        '_ContaoManager\\Webauthn\\MetadataService\\Exception\\MetadataStatementLoadingException' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/MetadataService/Exception/MetadataStatementLoadingException.php',
        '_ContaoManager\\Webauthn\\MetadataService\\Exception\\MissingMetadataStatementException' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/MetadataService/Exception/MissingMetadataStatementException.php',
        '_ContaoManager\\Webauthn\\MetadataService\\Exception\\RevokedCertificateException' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/MetadataService/Exception/RevokedCertificateException.php',
        '_ContaoManager\\Webauthn\\MetadataService\\MetadataStatementRepository' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/MetadataService/MetadataStatementRepository.php',
        '_ContaoManager\\Webauthn\\MetadataService\\Psr18HttpClient' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/MetadataService/Psr18HttpClient.php',
        '_ContaoManager\\Webauthn\\MetadataService\\Service\\ChainedMetadataServices' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/MetadataService/Service/ChainedMetadataServices.php',
        '_ContaoManager\\Webauthn\\MetadataService\\Service\\DistantResourceMetadataService' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/MetadataService/Service/DistantResourceMetadataService.php',
        '_ContaoManager\\Webauthn\\MetadataService\\Service\\FidoAllianceCompliantMetadataService' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/MetadataService/Service/FidoAllianceCompliantMetadataService.php',
        '_ContaoManager\\Webauthn\\MetadataService\\Service\\FolderResourceMetadataService' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/MetadataService/Service/FolderResourceMetadataService.php',
        '_ContaoManager\\Webauthn\\MetadataService\\Service\\InMemoryMetadataService' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/MetadataService/Service/InMemoryMetadataService.php',
        '_ContaoManager\\Webauthn\\MetadataService\\Service\\JsonMetadataService' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/MetadataService/Service/JsonMetadataService.php',
        '_ContaoManager\\Webauthn\\MetadataService\\Service\\LocalResourceMetadataService' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/MetadataService/Service/LocalResourceMetadataService.php',
        '_ContaoManager\\Webauthn\\MetadataService\\Service\\MetadataBLOBPayload' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/MetadataService/Service/MetadataBLOBPayload.php',
        '_ContaoManager\\Webauthn\\MetadataService\\Service\\MetadataBLOBPayloadEntry' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/MetadataService/Service/MetadataBLOBPayloadEntry.php',
        '_ContaoManager\\Webauthn\\MetadataService\\Service\\MetadataService' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/MetadataService/Service/MetadataService.php',
        '_ContaoManager\\Webauthn\\MetadataService\\Service\\StringMetadataService' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/MetadataService/Service/StringMetadataService.php',
        '_ContaoManager\\Webauthn\\MetadataService\\Statement\\AbstractDescriptor' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/MetadataService/Statement/AbstractDescriptor.php',
        '_ContaoManager\\Webauthn\\MetadataService\\Statement\\AlternativeDescriptions' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/MetadataService/Statement/AlternativeDescriptions.php',
        '_ContaoManager\\Webauthn\\MetadataService\\Statement\\AuthenticatorGetInfo' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/MetadataService/Statement/AuthenticatorGetInfo.php',
        '_ContaoManager\\Webauthn\\MetadataService\\Statement\\AuthenticatorStatus' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/MetadataService/Statement/AuthenticatorStatus.php',
        '_ContaoManager\\Webauthn\\MetadataService\\Statement\\BiometricAccuracyDescriptor' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/MetadataService/Statement/BiometricAccuracyDescriptor.php',
        '_ContaoManager\\Webauthn\\MetadataService\\Statement\\BiometricStatusReport' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/MetadataService/Statement/BiometricStatusReport.php',
        '_ContaoManager\\Webauthn\\MetadataService\\Statement\\CodeAccuracyDescriptor' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/MetadataService/Statement/CodeAccuracyDescriptor.php',
        '_ContaoManager\\Webauthn\\MetadataService\\Statement\\DisplayPNGCharacteristicsDescriptor' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/MetadataService/Statement/DisplayPNGCharacteristicsDescriptor.php',
        '_ContaoManager\\Webauthn\\MetadataService\\Statement\\EcdaaTrustAnchor' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/MetadataService/Statement/EcdaaTrustAnchor.php',
        '_ContaoManager\\Webauthn\\MetadataService\\Statement\\ExtensionDescriptor' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/MetadataService/Statement/ExtensionDescriptor.php',
        '_ContaoManager\\Webauthn\\MetadataService\\Statement\\MetadataStatement' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/MetadataService/Statement/MetadataStatement.php',
        '_ContaoManager\\Webauthn\\MetadataService\\Statement\\PatternAccuracyDescriptor' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/MetadataService/Statement/PatternAccuracyDescriptor.php',
        '_ContaoManager\\Webauthn\\MetadataService\\Statement\\RgbPaletteEntry' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/MetadataService/Statement/RgbPaletteEntry.php',
        '_ContaoManager\\Webauthn\\MetadataService\\Statement\\RogueListEntry' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/MetadataService/Statement/RogueListEntry.php',
        '_ContaoManager\\Webauthn\\MetadataService\\Statement\\StatusReport' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/MetadataService/Statement/StatusReport.php',
        '_ContaoManager\\Webauthn\\MetadataService\\Statement\\VerificationMethodANDCombinations' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/MetadataService/Statement/VerificationMethodANDCombinations.php',
        '_ContaoManager\\Webauthn\\MetadataService\\Statement\\VerificationMethodDescriptor' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/MetadataService/Statement/VerificationMethodDescriptor.php',
        '_ContaoManager\\Webauthn\\MetadataService\\Statement\\Version' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/MetadataService/Statement/Version.php',
        '_ContaoManager\\Webauthn\\MetadataService\\StatusReportRepository' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/MetadataService/StatusReportRepository.php',
        '_ContaoManager\\Webauthn\\MetadataService\\ValueFilter' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/MetadataService/ValueFilter.php',
        '_ContaoManager\\Webauthn\\PublicKeyCredential' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/PublicKeyCredential.php',
        '_ContaoManager\\Webauthn\\PublicKeyCredentialCreationOptions' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/PublicKeyCredentialCreationOptions.php',
        '_ContaoManager\\Webauthn\\PublicKeyCredentialDescriptor' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/PublicKeyCredentialDescriptor.php',
        '_ContaoManager\\Webauthn\\PublicKeyCredentialDescriptorCollection' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/PublicKeyCredentialDescriptorCollection.php',
        '_ContaoManager\\Webauthn\\PublicKeyCredentialEntity' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/PublicKeyCredentialEntity.php',
        '_ContaoManager\\Webauthn\\PublicKeyCredentialLoader' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/PublicKeyCredentialLoader.php',
        '_ContaoManager\\Webauthn\\PublicKeyCredentialOptions' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/PublicKeyCredentialOptions.php',
        '_ContaoManager\\Webauthn\\PublicKeyCredentialParameters' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/PublicKeyCredentialParameters.php',
        '_ContaoManager\\Webauthn\\PublicKeyCredentialRequestOptions' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/PublicKeyCredentialRequestOptions.php',
        '_ContaoManager\\Webauthn\\PublicKeyCredentialRpEntity' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/PublicKeyCredentialRpEntity.php',
        '_ContaoManager\\Webauthn\\PublicKeyCredentialSource' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/PublicKeyCredentialSource.php',
        '_ContaoManager\\Webauthn\\PublicKeyCredentialSourceRepository' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/PublicKeyCredentialSourceRepository.php',
        '_ContaoManager\\Webauthn\\PublicKeyCredentialUserEntity' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/PublicKeyCredentialUserEntity.php',
        '_ContaoManager\\Webauthn\\SimpleFakeCredentialGenerator' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/SimpleFakeCredentialGenerator.php',
        '_ContaoManager\\Webauthn\\StringStream' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/StringStream.php',
        '_ContaoManager\\Webauthn\\TokenBinding\\IgnoreTokenBindingHandler' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/TokenBinding/IgnoreTokenBindingHandler.php',
        '_ContaoManager\\Webauthn\\TokenBinding\\SecTokenBindingHandler' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/TokenBinding/SecTokenBindingHandler.php',
        '_ContaoManager\\Webauthn\\TokenBinding\\TokenBinding' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/TokenBinding/TokenBinding.php',
        '_ContaoManager\\Webauthn\\TokenBinding\\TokenBindingHandler' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/TokenBinding/TokenBindingHandler.php',
        '_ContaoManager\\Webauthn\\TokenBinding\\TokenBindingNotSupportedHandler' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/TokenBinding/TokenBindingNotSupportedHandler.php',
        '_ContaoManager\\Webauthn\\TrustPath\\CertificateTrustPath' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/TrustPath/CertificateTrustPath.php',
        '_ContaoManager\\Webauthn\\TrustPath\\EcdaaKeyIdTrustPath' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/TrustPath/EcdaaKeyIdTrustPath.php',
        '_ContaoManager\\Webauthn\\TrustPath\\EmptyTrustPath' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/TrustPath/EmptyTrustPath.php',
        '_ContaoManager\\Webauthn\\TrustPath\\TrustPath' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/TrustPath/TrustPath.php',
        '_ContaoManager\\Webauthn\\TrustPath\\TrustPathLoader' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/TrustPath/TrustPathLoader.php',
        '_ContaoManager\\Webauthn\\U2FPublicKey' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/U2FPublicKey.php',
        '_ContaoManager\\Webauthn\\Util\\Base64' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/Util/Base64.php',
        '_ContaoManager\\Webauthn\\Util\\CoseSignatureFixer' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/Util/CoseSignatureFixer.php',
        '_ContaoManager\\Webmozart\\Assert\\Assert' => __DIR__ . '/..' . '/webmozart/assert/src/Assert.php',
        '_ContaoManager\\Webmozart\\Assert\\InvalidArgumentException' => __DIR__ . '/..' . '/webmozart/assert/src/InvalidArgumentException.php',
        '_ContaoManager\\Webmozart\\Assert\\Mixin' => __DIR__ . '/..' . '/webmozart/assert/src/Mixin.php',
        '_ContaoManager\\phpDocumentor\\Reflection\\DocBlock' => __DIR__ . '/..' . '/phpdocumentor/reflection-docblock/src/DocBlock.php',
        '_ContaoManager\\phpDocumentor\\Reflection\\DocBlockFactory' => __DIR__ . '/..' . '/phpdocumentor/reflection-docblock/src/DocBlockFactory.php',
        '_ContaoManager\\phpDocumentor\\Reflection\\DocBlockFactoryInterface' => __DIR__ . '/..' . '/phpdocumentor/reflection-docblock/src/DocBlockFactoryInterface.php',
        '_ContaoManager\\phpDocumentor\\Reflection\\DocBlock\\Description' => __DIR__ . '/..' . '/phpdocumentor/reflection-docblock/src/DocBlock/Description.php',
        '_ContaoManager\\phpDocumentor\\Reflection\\DocBlock\\DescriptionFactory' => __DIR__ . '/..' . '/phpdocumentor/reflection-docblock/src/DocBlock/DescriptionFactory.php',
        '_ContaoManager\\phpDocumentor\\Reflection\\DocBlock\\ExampleFinder' => __DIR__ . '/..' . '/phpdocumentor/reflection-docblock/src/DocBlock/ExampleFinder.php',
        '_ContaoManager\\phpDocumentor\\Reflection\\DocBlock\\Serializer' => __DIR__ . '/..' . '/phpdocumentor/reflection-docblock/src/DocBlock/Serializer.php',
        '_ContaoManager\\phpDocumentor\\Reflection\\DocBlock\\StandardTagFactory' => __DIR__ . '/..' . '/phpdocumentor/reflection-docblock/src/DocBlock/StandardTagFactory.php',
        '_ContaoManager\\phpDocumentor\\Reflection\\DocBlock\\Tag' => __DIR__ . '/..' . '/phpdocumentor/reflection-docblock/src/DocBlock/Tag.php',
        '_ContaoManager\\phpDocumentor\\Reflection\\DocBlock\\TagFactory' => __DIR__ . '/..' . '/phpdocumentor/reflection-docblock/src/DocBlock/TagFactory.php',
        '_ContaoManager\\phpDocumentor\\Reflection\\DocBlock\\Tags\\Author' => __DIR__ . '/..' . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Author.php',
        '_ContaoManager\\phpDocumentor\\Reflection\\DocBlock\\Tags\\BaseTag' => __DIR__ . '/..' . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/BaseTag.php',
        '_ContaoManager\\phpDocumentor\\Reflection\\DocBlock\\Tags\\Covers' => __DIR__ . '/..' . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Covers.php',
        '_ContaoManager\\phpDocumentor\\Reflection\\DocBlock\\Tags\\Deprecated' => __DIR__ . '/..' . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Deprecated.php',
        '_ContaoManager\\phpDocumentor\\Reflection\\DocBlock\\Tags\\Example' => __DIR__ . '/..' . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Example.php',
        '_ContaoManager\\phpDocumentor\\Reflection\\DocBlock\\Tags\\Extends_' => __DIR__ . '/..' . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Extends_.php',
        '_ContaoManager\\phpDocumentor\\Reflection\\DocBlock\\Tags\\Factory\\AbstractPHPStanFactory' => __DIR__ . '/..' . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Factory/AbstractPHPStanFactory.php',
        '_ContaoManager\\phpDocumentor\\Reflection\\DocBlock\\Tags\\Factory\\ExtendsFactory' => __DIR__ . '/..' . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Factory/ExtendsFactory.php',
        '_ContaoManager\\phpDocumentor\\Reflection\\DocBlock\\Tags\\Factory\\Factory' => __DIR__ . '/..' . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Factory/Factory.php',
        '_ContaoManager\\phpDocumentor\\Reflection\\DocBlock\\Tags\\Factory\\ImplementsFactory' => __DIR__ . '/..' . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Factory/ImplementsFactory.php',
        '_ContaoManager\\phpDocumentor\\Reflection\\DocBlock\\Tags\\Factory\\MethodFactory' => __DIR__ . '/..' . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Factory/MethodFactory.php',
        '_ContaoManager\\phpDocumentor\\Reflection\\DocBlock\\Tags\\Factory\\MethodParameterFactory' => __DIR__ . '/..' . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Factory/MethodParameterFactory.php',
        '_ContaoManager\\phpDocumentor\\Reflection\\DocBlock\\Tags\\Factory\\PHPStanFactory' => __DIR__ . '/..' . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Factory/PHPStanFactory.php',
        '_ContaoManager\\phpDocumentor\\Reflection\\DocBlock\\Tags\\Factory\\ParamFactory' => __DIR__ . '/..' . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Factory/ParamFactory.php',
        '_ContaoManager\\phpDocumentor\\Reflection\\DocBlock\\Tags\\Factory\\PropertyFactory' => __DIR__ . '/..' . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Factory/PropertyFactory.php',
        '_ContaoManager\\phpDocumentor\\Reflection\\DocBlock\\Tags\\Factory\\PropertyReadFactory' => __DIR__ . '/..' . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Factory/PropertyReadFactory.php',
        '_ContaoManager\\phpDocumentor\\Reflection\\DocBlock\\Tags\\Factory\\PropertyWriteFactory' => __DIR__ . '/..' . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Factory/PropertyWriteFactory.php',
        '_ContaoManager\\phpDocumentor\\Reflection\\DocBlock\\Tags\\Factory\\ReturnFactory' => __DIR__ . '/..' . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Factory/ReturnFactory.php',
        '_ContaoManager\\phpDocumentor\\Reflection\\DocBlock\\Tags\\Factory\\StaticMethod' => __DIR__ . '/..' . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Factory/StaticMethod.php',
        '_ContaoManager\\phpDocumentor\\Reflection\\DocBlock\\Tags\\Factory\\TemplateExtendsFactory' => __DIR__ . '/..' . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Factory/TemplateExtendsFactory.php',
        '_ContaoManager\\phpDocumentor\\Reflection\\DocBlock\\Tags\\Factory\\TemplateFactory' => __DIR__ . '/..' . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Factory/TemplateFactory.php',
        '_ContaoManager\\phpDocumentor\\Reflection\\DocBlock\\Tags\\Factory\\TemplateImplementsFactory' => __DIR__ . '/..' . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Factory/TemplateImplementsFactory.php',
        '_ContaoManager\\phpDocumentor\\Reflection\\DocBlock\\Tags\\Factory\\VarFactory' => __DIR__ . '/..' . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Factory/VarFactory.php',
        '_ContaoManager\\phpDocumentor\\Reflection\\DocBlock\\Tags\\Formatter' => __DIR__ . '/..' . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Formatter.php',
        '_ContaoManager\\phpDocumentor\\Reflection\\DocBlock\\Tags\\Formatter\\AlignFormatter' => __DIR__ . '/..' . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Formatter/AlignFormatter.php',
        '_ContaoManager\\phpDocumentor\\Reflection\\DocBlock\\Tags\\Formatter\\PassthroughFormatter' => __DIR__ . '/..' . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Formatter/PassthroughFormatter.php',
        '_ContaoManager\\phpDocumentor\\Reflection\\DocBlock\\Tags\\Generic' => __DIR__ . '/..' . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Generic.php',
        '_ContaoManager\\phpDocumentor\\Reflection\\DocBlock\\Tags\\Implements_' => __DIR__ . '/..' . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Implements_.php',
        '_ContaoManager\\phpDocumentor\\Reflection\\DocBlock\\Tags\\InvalidTag' => __DIR__ . '/..' . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/InvalidTag.php',
        '_ContaoManager\\phpDocumentor\\Reflection\\DocBlock\\Tags\\Link' => __DIR__ . '/..' . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Link.php',
        '_ContaoManager\\phpDocumentor\\Reflection\\DocBlock\\Tags\\Method' => __DIR__ . '/..' . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Method.php',
        '_ContaoManager\\phpDocumentor\\Reflection\\DocBlock\\Tags\\MethodParameter' => __DIR__ . '/..' . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/MethodParameter.php',
        '_ContaoManager\\phpDocumentor\\Reflection\\DocBlock\\Tags\\Mixin' => __DIR__ . '/..' . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Mixin.php',
        '_ContaoManager\\phpDocumentor\\Reflection\\DocBlock\\Tags\\Param' => __DIR__ . '/..' . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Param.php',
        '_ContaoManager\\phpDocumentor\\Reflection\\DocBlock\\Tags\\Property' => __DIR__ . '/..' . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Property.php',
        '_ContaoManager\\phpDocumentor\\Reflection\\DocBlock\\Tags\\PropertyRead' => __DIR__ . '/..' . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/PropertyRead.php',
        '_ContaoManager\\phpDocumentor\\Reflection\\DocBlock\\Tags\\PropertyWrite' => __DIR__ . '/..' . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/PropertyWrite.php',
        '_ContaoManager\\phpDocumentor\\Reflection\\DocBlock\\Tags\\Reference\\Fqsen' => __DIR__ . '/..' . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Reference/Fqsen.php',
        '_ContaoManager\\phpDocumentor\\Reflection\\DocBlock\\Tags\\Reference\\Reference' => __DIR__ . '/..' . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Reference/Reference.php',
        '_ContaoManager\\phpDocumentor\\Reflection\\DocBlock\\Tags\\Reference\\Url' => __DIR__ . '/..' . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Reference/Url.php',
        '_ContaoManager\\phpDocumentor\\Reflection\\DocBlock\\Tags\\Return_' => __DIR__ . '/..' . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Return_.php',
        '_ContaoManager\\phpDocumentor\\Reflection\\DocBlock\\Tags\\See' => __DIR__ . '/..' . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/See.php',
        '_ContaoManager\\phpDocumentor\\Reflection\\DocBlock\\Tags\\Since' => __DIR__ . '/..' . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Since.php',
        '_ContaoManager\\phpDocumentor\\Reflection\\DocBlock\\Tags\\Source' => __DIR__ . '/..' . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Source.php',
        '_ContaoManager\\phpDocumentor\\Reflection\\DocBlock\\Tags\\TagWithType' => __DIR__ . '/..' . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/TagWithType.php',
        '_ContaoManager\\phpDocumentor\\Reflection\\DocBlock\\Tags\\Template' => __DIR__ . '/..' . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Template.php',
        '_ContaoManager\\phpDocumentor\\Reflection\\DocBlock\\Tags\\TemplateCovariant' => __DIR__ . '/..' . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/TemplateCovariant.php',
        '_ContaoManager\\phpDocumentor\\Reflection\\DocBlock\\Tags\\TemplateExtends' => __DIR__ . '/..' . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/TemplateExtends.php',
        '_ContaoManager\\phpDocumentor\\Reflection\\DocBlock\\Tags\\TemplateImplements' => __DIR__ . '/..' . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/TemplateImplements.php',
        '_ContaoManager\\phpDocumentor\\Reflection\\DocBlock\\Tags\\Throws' => __DIR__ . '/..' . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Throws.php',
        '_ContaoManager\\phpDocumentor\\Reflection\\DocBlock\\Tags\\Uses' => __DIR__ . '/..' . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Uses.php',
        '_ContaoManager\\phpDocumentor\\Reflection\\DocBlock\\Tags\\Var_' => __DIR__ . '/..' . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Var_.php',
        '_ContaoManager\\phpDocumentor\\Reflection\\DocBlock\\Tags\\Version' => __DIR__ . '/..' . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Version.php',
        '_ContaoManager\\phpDocumentor\\Reflection\\Element' => __DIR__ . '/..' . '/phpdocumentor/reflection-common/src/Element.php',
        '_ContaoManager\\phpDocumentor\\Reflection\\Exception\\PcreException' => __DIR__ . '/..' . '/phpdocumentor/reflection-docblock/src/Exception/PcreException.php',
        '_ContaoManager\\phpDocumentor\\Reflection\\File' => __DIR__ . '/..' . '/phpdocumentor/reflection-common/src/File.php',
        '_ContaoManager\\phpDocumentor\\Reflection\\Fqsen' => __DIR__ . '/..' . '/phpdocumentor/reflection-common/src/Fqsen.php',
        '_ContaoManager\\phpDocumentor\\Reflection\\FqsenResolver' => __DIR__ . '/..' . '/phpdocumentor/type-resolver/src/FqsenResolver.php',
        '_ContaoManager\\phpDocumentor\\Reflection\\Location' => __DIR__ . '/..' . '/phpdocumentor/reflection-common/src/Location.php',
        '_ContaoManager\\phpDocumentor\\Reflection\\Project' => __DIR__ . '/..' . '/phpdocumentor/reflection-common/src/Project.php',
        '_ContaoManager\\phpDocumentor\\Reflection\\ProjectFactory' => __DIR__ . '/..' . '/phpdocumentor/reflection-common/src/ProjectFactory.php',
        '_ContaoManager\\phpDocumentor\\Reflection\\PseudoType' => __DIR__ . '/..' . '/phpdocumentor/type-resolver/src/PseudoType.php',
        '_ContaoManager\\phpDocumentor\\Reflection\\PseudoTypes\\ArrayShape' => __DIR__ . '/..' . '/phpdocumentor/type-resolver/src/PseudoTypes/ArrayShape.php',
        '_ContaoManager\\phpDocumentor\\Reflection\\PseudoTypes\\ArrayShapeItem' => __DIR__ . '/..' . '/phpdocumentor/type-resolver/src/PseudoTypes/ArrayShapeItem.php',
        '_ContaoManager\\phpDocumentor\\Reflection\\PseudoTypes\\CallableString' => __DIR__ . '/..' . '/phpdocumentor/type-resolver/src/PseudoTypes/CallableString.php',
        '_ContaoManager\\phpDocumentor\\Reflection\\PseudoTypes\\Conditional' => __DIR__ . '/..' . '/phpdocumentor/type-resolver/src/PseudoTypes/Conditional.php',
        '_ContaoManager\\phpDocumentor\\Reflection\\PseudoTypes\\ConditionalForParameter' => __DIR__ . '/..' . '/phpdocumentor/type-resolver/src/PseudoTypes/ConditionalForParameter.php',
        '_ContaoManager\\phpDocumentor\\Reflection\\PseudoTypes\\ConstExpression' => __DIR__ . '/..' . '/phpdocumentor/type-resolver/src/PseudoTypes/ConstExpression.php',
        '_ContaoManager\\phpDocumentor\\Reflection\\PseudoTypes\\False_' => __DIR__ . '/..' . '/phpdocumentor/type-resolver/src/PseudoTypes/False_.php',
        '_ContaoManager\\phpDocumentor\\Reflection\\PseudoTypes\\FloatValue' => __DIR__ . '/..' . '/phpdocumentor/type-resolver/src/PseudoTypes/FloatValue.php',
        '_ContaoManager\\phpDocumentor\\Reflection\\PseudoTypes\\HtmlEscapedString' => __DIR__ . '/..' . '/phpdocumentor/type-resolver/src/PseudoTypes/HtmlEscapedString.php',
        '_ContaoManager\\phpDocumentor\\Reflection\\PseudoTypes\\IntMask' => __DIR__ . '/..' . '/phpdocumentor/type-resolver/src/PseudoTypes/IntMask.php',
        '_ContaoManager\\phpDocumentor\\Reflection\\PseudoTypes\\IntMaskOf' => __DIR__ . '/..' . '/phpdocumentor/type-resolver/src/PseudoTypes/IntMaskOf.php',
        '_ContaoManager\\phpDocumentor\\Reflection\\PseudoTypes\\IntegerRange' => __DIR__ . '/..' . '/phpdocumentor/type-resolver/src/PseudoTypes/IntegerRange.php',
        '_ContaoManager\\phpDocumentor\\Reflection\\PseudoTypes\\IntegerValue' => __DIR__ . '/..' . '/phpdocumentor/type-resolver/src/PseudoTypes/IntegerValue.php',
        '_ContaoManager\\phpDocumentor\\Reflection\\PseudoTypes\\KeyOf' => __DIR__ . '/..' . '/phpdocumentor/type-resolver/src/PseudoTypes/KeyOf.php',
        '_ContaoManager\\phpDocumentor\\Reflection\\PseudoTypes\\ListShape' => __DIR__ . '/..' . '/phpdocumentor/type-resolver/src/PseudoTypes/ListShape.php',
        '_ContaoManager\\phpDocumentor\\Reflection\\PseudoTypes\\ListShapeItem' => __DIR__ . '/..' . '/phpdocumentor/type-resolver/src/PseudoTypes/ListShapeItem.php',
        '_ContaoManager\\phpDocumentor\\Reflection\\PseudoTypes\\List_' => __DIR__ . '/..' . '/phpdocumentor/type-resolver/src/PseudoTypes/List_.php',
        '_ContaoManager\\phpDocumentor\\Reflection\\PseudoTypes\\LiteralString' => __DIR__ . '/..' . '/phpdocumentor/type-resolver/src/PseudoTypes/LiteralString.php',
        '_ContaoManager\\phpDocumentor\\Reflection\\PseudoTypes\\LowercaseString' => __DIR__ . '/..' . '/phpdocumentor/type-resolver/src/PseudoTypes/LowercaseString.php',
        '_ContaoManager\\phpDocumentor\\Reflection\\PseudoTypes\\NegativeInteger' => __DIR__ . '/..' . '/phpdocumentor/type-resolver/src/PseudoTypes/NegativeInteger.php',
        '_ContaoManager\\phpDocumentor\\Reflection\\PseudoTypes\\NonEmptyArray' => __DIR__ . '/..' . '/phpdocumentor/type-resolver/src/PseudoTypes/NonEmptyArray.php',
        '_ContaoManager\\phpDocumentor\\Reflection\\PseudoTypes\\NonEmptyList' => __DIR__ . '/..' . '/phpdocumentor/type-resolver/src/PseudoTypes/NonEmptyList.php',
        '_ContaoManager\\phpDocumentor\\Reflection\\PseudoTypes\\NonEmptyLowercaseString' => __DIR__ . '/..' . '/phpdocumentor/type-resolver/src/PseudoTypes/NonEmptyLowercaseString.php',
        '_ContaoManager\\phpDocumentor\\Reflection\\PseudoTypes\\NonEmptyString' => __DIR__ . '/..' . '/phpdocumentor/type-resolver/src/PseudoTypes/NonEmptyString.php',
        '_ContaoManager\\phpDocumentor\\Reflection\\PseudoTypes\\NumericString' => __DIR__ . '/..' . '/phpdocumentor/type-resolver/src/PseudoTypes/NumericString.php',
        '_ContaoManager\\phpDocumentor\\Reflection\\PseudoTypes\\Numeric_' => __DIR__ . '/..' . '/phpdocumentor/type-resolver/src/PseudoTypes/Numeric_.php',
        '_ContaoManager\\phpDocumentor\\Reflection\\PseudoTypes\\ObjectShape' => __DIR__ . '/..' . '/phpdocumentor/type-resolver/src/PseudoTypes/ObjectShape.php',
        '_ContaoManager\\phpDocumentor\\Reflection\\PseudoTypes\\ObjectShapeItem' => __DIR__ . '/..' . '/phpdocumentor/type-resolver/src/PseudoTypes/ObjectShapeItem.php',
        '_ContaoManager\\phpDocumentor\\Reflection\\PseudoTypes\\OffsetAccess' => __DIR__ . '/..' . '/phpdocumentor/type-resolver/src/PseudoTypes/OffsetAccess.php',
        '_ContaoManager\\phpDocumentor\\Reflection\\PseudoTypes\\PositiveInteger' => __DIR__ . '/..' . '/phpdocumentor/type-resolver/src/PseudoTypes/PositiveInteger.php',
        '_ContaoManager\\phpDocumentor\\Reflection\\PseudoTypes\\ShapeItem' => __DIR__ . '/..' . '/phpdocumentor/type-resolver/src/PseudoTypes/ShapeItem.php',
        '_ContaoManager\\phpDocumentor\\Reflection\\PseudoTypes\\StringValue' => __DIR__ . '/..' . '/phpdocumentor/type-resolver/src/PseudoTypes/StringValue.php',
        '_ContaoManager\\phpDocumentor\\Reflection\\PseudoTypes\\TraitString' => __DIR__ . '/..' . '/phpdocumentor/type-resolver/src/PseudoTypes/TraitString.php',
        '_ContaoManager\\phpDocumentor\\Reflection\\PseudoTypes\\True_' => __DIR__ . '/..' . '/phpdocumentor/type-resolver/src/PseudoTypes/True_.php',
        '_ContaoManager\\phpDocumentor\\Reflection\\PseudoTypes\\ValueOf' => __DIR__ . '/..' . '/phpdocumentor/type-resolver/src/PseudoTypes/ValueOf.php',
        '_ContaoManager\\phpDocumentor\\Reflection\\Type' => __DIR__ . '/..' . '/phpdocumentor/type-resolver/src/Type.php',
        '_ContaoManager\\phpDocumentor\\Reflection\\TypeResolver' => __DIR__ . '/..' . '/phpdocumentor/type-resolver/src/TypeResolver.php',
        '_ContaoManager\\phpDocumentor\\Reflection\\Types\\AbstractList' => __DIR__ . '/..' . '/phpdocumentor/type-resolver/src/Types/AbstractList.php',
        '_ContaoManager\\phpDocumentor\\Reflection\\Types\\AggregatedType' => __DIR__ . '/..' . '/phpdocumentor/type-resolver/src/Types/AggregatedType.php',
        '_ContaoManager\\phpDocumentor\\Reflection\\Types\\ArrayKey' => __DIR__ . '/..' . '/phpdocumentor/type-resolver/src/Types/ArrayKey.php',
        '_ContaoManager\\phpDocumentor\\Reflection\\Types\\Array_' => __DIR__ . '/..' . '/phpdocumentor/type-resolver/src/Types/Array_.php',
        '_ContaoManager\\phpDocumentor\\Reflection\\Types\\Boolean' => __DIR__ . '/..' . '/phpdocumentor/type-resolver/src/Types/Boolean.php',
        '_ContaoManager\\phpDocumentor\\Reflection\\Types\\CallableParameter' => __DIR__ . '/..' . '/phpdocumentor/type-resolver/src/Types/CallableParameter.php',
        '_ContaoManager\\phpDocumentor\\Reflection\\Types\\Callable_' => __DIR__ . '/..' . '/phpdocumentor/type-resolver/src/Types/Callable_.php',
        '_ContaoManager\\phpDocumentor\\Reflection\\Types\\ClassString' => __DIR__ . '/..' . '/phpdocumentor/type-resolver/src/Types/ClassString.php',
        '_ContaoManager\\phpDocumentor\\Reflection\\Types\\Collection' => __DIR__ . '/..' . '/phpdocumentor/type-resolver/src/Types/Collection.php',
        '_ContaoManager\\phpDocumentor\\Reflection\\Types\\Compound' => __DIR__ . '/..' . '/phpdocumentor/type-resolver/src/Types/Compound.php',
        '_ContaoManager\\phpDocumentor\\Reflection\\Types\\Context' => __DIR__ . '/..' . '/phpdocumentor/type-resolver/src/Types/Context.php',
        '_ContaoManager\\phpDocumentor\\Reflection\\Types\\ContextFactory' => __DIR__ . '/..' . '/phpdocumentor/type-resolver/src/Types/ContextFactory.php',
        '_ContaoManager\\phpDocumentor\\Reflection\\Types\\Expression' => __DIR__ . '/..' . '/phpdocumentor/type-resolver/src/Types/Expression.php',
        '_ContaoManager\\phpDocumentor\\Reflection\\Types\\Float_' => __DIR__ . '/..' . '/phpdocumentor/type-resolver/src/Types/Float_.php',
        '_ContaoManager\\phpDocumentor\\Reflection\\Types\\Integer' => __DIR__ . '/..' . '/phpdocumentor/type-resolver/src/Types/Integer.php',
        '_ContaoManager\\phpDocumentor\\Reflection\\Types\\InterfaceString' => __DIR__ . '/..' . '/phpdocumentor/type-resolver/src/Types/InterfaceString.php',
        '_ContaoManager\\phpDocumentor\\Reflection\\Types\\Intersection' => __DIR__ . '/..' . '/phpdocumentor/type-resolver/src/Types/Intersection.php',
        '_ContaoManager\\phpDocumentor\\Reflection\\Types\\Iterable_' => __DIR__ . '/..' . '/phpdocumentor/type-resolver/src/Types/Iterable_.php',
        '_ContaoManager\\phpDocumentor\\Reflection\\Types\\Mixed_' => __DIR__ . '/..' . '/phpdocumentor/type-resolver/src/Types/Mixed_.php',
        '_ContaoManager\\phpDocumentor\\Reflection\\Types\\Never_' => __DIR__ . '/..' . '/phpdocumentor/type-resolver/src/Types/Never_.php',
        '_ContaoManager\\phpDocumentor\\Reflection\\Types\\Null_' => __DIR__ . '/..' . '/phpdocumentor/type-resolver/src/Types/Null_.php',
        '_ContaoManager\\phpDocumentor\\Reflection\\Types\\Nullable' => __DIR__ . '/..' . '/phpdocumentor/type-resolver/src/Types/Nullable.php',
        '_ContaoManager\\phpDocumentor\\Reflection\\Types\\Object_' => __DIR__ . '/..' . '/phpdocumentor/type-resolver/src/Types/Object_.php',
        '_ContaoManager\\phpDocumentor\\Reflection\\Types\\Parent_' => __DIR__ . '/..' . '/phpdocumentor/type-resolver/src/Types/Parent_.php',
        '_ContaoManager\\phpDocumentor\\Reflection\\Types\\Resource_' => __DIR__ . '/..' . '/phpdocumentor/type-resolver/src/Types/Resource_.php',
        '_ContaoManager\\phpDocumentor\\Reflection\\Types\\Scalar' => __DIR__ . '/..' . '/phpdocumentor/type-resolver/src/Types/Scalar.php',
        '_ContaoManager\\phpDocumentor\\Reflection\\Types\\Self_' => __DIR__ . '/..' . '/phpdocumentor/type-resolver/src/Types/Self_.php',
        '_ContaoManager\\phpDocumentor\\Reflection\\Types\\Static_' => __DIR__ . '/..' . '/phpdocumentor/type-resolver/src/Types/Static_.php',
        '_ContaoManager\\phpDocumentor\\Reflection\\Types\\String_' => __DIR__ . '/..' . '/phpdocumentor/type-resolver/src/Types/String_.php',
        '_ContaoManager\\phpDocumentor\\Reflection\\Types\\This' => __DIR__ . '/..' . '/phpdocumentor/type-resolver/src/Types/This.php',
        '_ContaoManager\\phpDocumentor\\Reflection\\Types\\Void_' => __DIR__ . '/..' . '/phpdocumentor/type-resolver/src/Types/Void_.php',
        '_ContaoManager\\phpDocumentor\\Reflection\\Utils' => __DIR__ . '/..' . '/phpdocumentor/reflection-docblock/src/Utils.php',
        '_ContaoManager\\studio24\\Rotate\\Delete' => __DIR__ . '/..' . '/studio24/rotate/src/Delete.php',
        '_ContaoManager\\studio24\\Rotate\\DirectoryIterator' => __DIR__ . '/..' . '/studio24/rotate/src/DirectoryIterator.php',
        '_ContaoManager\\studio24\\Rotate\\FilenameFormat' => __DIR__ . '/..' . '/studio24/rotate/src/FilenameFormat.php',
        '_ContaoManager\\studio24\\Rotate\\FilenameFormatException' => __DIR__ . '/..' . '/studio24/rotate/src/FilenameFormatException.php',
        '_ContaoManager\\studio24\\Rotate\\Rotate' => __DIR__ . '/..' . '/studio24/rotate/src/Rotate.php',
        '_ContaoManager\\studio24\\Rotate\\RotateAbstract' => __DIR__ . '/..' . '/studio24/rotate/src/RotateAbstract.php',
        '_ContaoManager\\studio24\\Rotate\\RotateException' => __DIR__ . '/..' . '/studio24/rotate/src/RotateException.php',
        '_ContaoManager\\' => __DIR__ . '/..' . '/symfony/cache/Traits/ValueWrapper.php',
    );

    public static function getInitializer(ClassLoader $loader)
    {
        return \Closure::bind(function () use ($loader) {
            $loader->prefixLengthsPsr4 = ComposerStaticInit70603d6d4d667e5d8f93c56c4d3630ec::$prefixLengthsPsr4;
            $loader->prefixDirsPsr4 = ComposerStaticInit70603d6d4d667e5d8f93c56c4d3630ec::$prefixDirsPsr4;
            $loader->classMap = ComposerStaticInit70603d6d4d667e5d8f93c56c4d3630ec::$classMap;

        }, null, ClassLoader::class);
    }
}
<?php

// autoload_real.php @generated by Composer

class ComposerAutoloaderInit70603d6d4d667e5d8f93c56c4d3630ec
{
    private static $loader;

    public static function loadClassLoader($class)
    {
        if ('Composer\Autoload\ClassLoader' === $class) {
            require __DIR__ . '/ClassLoader.php';
        }
    }

    /**
     * @return \Composer\Autoload\ClassLoader
     */
    public static function getLoader()
    {
        if (null !== self::$loader) {
            return self::$loader;
        }

        require __DIR__ . '/platform_check.php';

        spl_autoload_register(array('ComposerAutoloaderInit70603d6d4d667e5d8f93c56c4d3630ec', 'loadClassLoader'), true, true);
        self::$loader = $loader = new \Composer\Autoload\ClassLoader(\dirname(__DIR__));
        spl_autoload_unregister(array('ComposerAutoloaderInit70603d6d4d667e5d8f93c56c4d3630ec', 'loadClassLoader'));

        require __DIR__ . '/autoload_static.php';
        call_user_func(\Composer\Autoload\ComposerStaticInit70603d6d4d667e5d8f93c56c4d3630ec::getInitializer($loader));

        $loader->setClassMapAuthoritative(true);
        $loader->register(true);

        $filesToLoad = \Composer\Autoload\ComposerStaticInit70603d6d4d667e5d8f93c56c4d3630ec::$files;
        $requireFile = \Closure::bind(static function ($fileIdentifier, $file) {
            if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) {
                $GLOBALS['__composer_autoload_files'][$fileIdentifier] = true;

                require $file;
            }
        }, null, null);
        foreach ($filesToLoad as $fileIdentifier => $file) {
            $requireFile($fileIdentifier, $file);
        }

        return $loader;
    }
}
Copyright (C) 2015 Composer

Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
# Change Log

All notable changes to this project will be documented in this file.
This project adheres to [Semantic Versioning](http://semver.org/).

### [3.4.3] 2024-09-19

  * Fixed some type annotations

### [3.4.2] 2024-07-12

  * Fixed PHP 5.3 syntax error

### [3.4.1] 2024-07-12

  * Fixed normalizeStability's return type to enforce valid stabilities

### [3.4.0] 2023-08-31

  * Support larger major version numbers (#149)

### [3.3.2] 2022-04-01

  * Fixed handling of non-string values (#134)

### [3.3.1] 2022-03-16

  * Fixed possible cache key clash in the CompilingMatcher memoization (#132)

### [3.3.0] 2022-03-15

  * Improved performance of CompilingMatcher by memoizing more (#131)
  * Added CompilingMatcher::clear to clear all memoization caches

### [3.2.9] 2022-02-04

  * Revert #129 (Fixed MultiConstraint with MatchAllConstraint) which caused regressions

### [3.2.8] 2022-02-04

  * Updates to latest phpstan / CI by @Seldaek in https://github.com/composer/semver/pull/130
  * Fixed MultiConstraint with MatchAllConstraint by @Toflar in https://github.com/composer/semver/pull/129

### [3.2.7] 2022-01-04

  * Fixed: typo in type definition of Intervals class causing issues with Psalm scanning vendors

### [3.2.6] 2021-10-25

  * Fixed: type improvements to parseStability

### [3.2.5] 2021-05-24

  * Fixed: issue comparing disjunctive MultiConstraints to conjunctive ones (#127)
  * Fixed: added complete type information using phpstan annotations

### [3.2.4] 2020-11-13

  * Fixed: code clean-up

### [3.2.3] 2020-11-12

  * Fixed: constraints in the form of `X || Y, >=Y.1` and other such complex constructs were in some cases being optimized into a more restrictive constraint

### [3.2.2] 2020-10-14

  * Fixed: internal code cleanups

### [3.2.1] 2020-09-27

  * Fixed: accidental validation of broken constraints combining ^/~ and wildcards, and -dev suffix allowing weird cases
  * Fixed: normalization of beta0 and such which was dropping the 0

### [3.2.0] 2020-09-09

  * Added: support for `x || @dev`, not very useful but seen in the wild and failed to validate with 1.5.2/1.6.0
  * Added: support for `foobar-dev` being equal to `dev-foobar`, dev-foobar is the official way to write it but we need to support the other for BC and convenience

### [3.1.0] 2020-09-08

  * Added: support for constraints like `^2.x-dev` and `~2.x-dev`, not very useful but seen in the wild and failed to validate with 3.0.1
  * Fixed: invalid aliases will no longer throw, unless explicitly validated by Composer in the root package

### [3.0.1] 2020-09-08

  * Fixed: handling of some invalid -dev versions which were seen as valid

### [3.0.0] 2020-05-26

  * Break: Renamed `EmptyConstraint`, replace it with `MatchAllConstraint`
  * Break: Unlikely to affect anyone but strictly speaking a breaking change, `*.*` and such variants will not match all `dev-*` versions anymore, only `*` does
  * Break: ConstraintInterface is now considered internal/private and not meant to be implemented by third parties anymore
  * Added `Intervals` class to check if a constraint is a subsets of another one, and allow compacting complex MultiConstraints into simpler ones
  * Added `CompilingMatcher` class to speed up constraint matching against simple Constraint instances
  * Added `MatchAllConstraint` and `MatchNoneConstraint` which match everything and nothing
  * Added more advanced optimization of contiguous constraints inside MultiConstraint
  * Added tentative support for PHP 8
  * Fixed ConstraintInterface::matches to be commutative in all cases

### [2.0.0] 2020-04-21

  * Break: `dev-master`, `dev-trunk` and `dev-default` now normalize to `dev-master`, `dev-trunk` and `dev-default` instead of `9999999-dev` in 1.x
  * Break: Removed the deprecated `AbstractConstraint`
  * Added `getUpperBound` and `getLowerBound` to ConstraintInterface. They return `Composer\Semver\Constraint\Bound` instances
  * Added `MultiConstraint::create` to create the most-optimal form of ConstraintInterface from an array of constraint strings

### [1.7.2] 2020-12-03

  * Fixed: Allow installing on php 8

### [1.7.1] 2020-09-27

  * Fixed: accidental validation of broken constraints combining ^/~ and wildcards, and -dev suffix allowing weird cases
  * Fixed: normalization of beta0 and such which was dropping the 0

### [1.7.0] 2020-09-09

  * Added: support for `x || @dev`, not very useful but seen in the wild and failed to validate with 1.5.2/1.6.0
  * Added: support for `foobar-dev` being equal to `dev-foobar`, dev-foobar is the official way to write it but we need to support the other for BC and convenience

### [1.6.0] 2020-09-08

  * Added: support for constraints like `^2.x-dev` and `~2.x-dev`, not very useful but seen in the wild and failed to validate with 1.5.2
  * Fixed: invalid aliases will no longer throw, unless explicitly validated by Composer in the root package

### [1.5.2] 2020-09-08

  * Fixed: handling of some invalid -dev versions which were seen as valid
  * Fixed: some doctypes

### [1.5.1] 2020-01-13

  * Fixed: Parsing of aliased version was not validating the alias to be a valid version

### [1.5.0] 2019-03-19

  * Added: some support for date versions (e.g. 201903) in `~` operator
  * Fixed: support for stabilities in `~` operator was inconsistent

### [1.4.2] 2016-08-30

  * Fixed: collapsing of complex constraints lead to buggy constraints

### [1.4.1] 2016-06-02

  * Changed: branch-like requirements no longer strip build metadata - [composer/semver#38](https://github.com/composer/semver/pull/38).

### [1.4.0] 2016-03-30

  * Added: getters on MultiConstraint - [composer/semver#35](https://github.com/composer/semver/pull/35).

### [1.3.0] 2016-02-25

  * Fixed: stability parsing - [composer/composer#1234](https://github.com/composer/composer/issues/4889).
  * Changed: collapse contiguous constraints when possible.

### [1.2.0] 2015-11-10

  * Changed: allow multiple numerical identifiers in 'pre-release' version part.
  * Changed: add more 'v' prefix support.

### [1.1.0] 2015-11-03

  * Changed: dropped redundant `test` namespace.
  * Changed: minor adjustment in datetime parsing normalization.
  * Changed: `ConstraintInterface` relaxed, setPrettyString is not required anymore.
  * Changed: `AbstractConstraint` marked deprecated, will be removed in 2.0.
  * Changed: `Constraint` is now extensible.

### [1.0.0] 2015-09-21

  * Break: `VersionConstraint` renamed to `Constraint`.
  * Break: `SpecificConstraint` renamed to `AbstractConstraint`.
  * Break: `LinkConstraintInterface` renamed to `ConstraintInterface`.
  * Break: `VersionParser::parseNameVersionPairs` was removed.
  * Changed: `VersionParser::parseConstraints` allows (but ignores) build metadata now.
  * Changed: `VersionParser::parseConstraints` allows (but ignores) prefixing numeric versions with a 'v' now.
  * Changed: Fixed namespace(s) of test files.
  * Changed: `Comparator::compare` no longer throws `InvalidArgumentException`.
  * Changed: `Constraint` now throws `InvalidArgumentException`.

### [0.1.0] 2015-07-23

  * Added: `Composer\Semver\Comparator`, various methods to compare versions.
  * Added: various documents such as README.md, LICENSE, etc.
  * Added: configuration files for Git, Travis, php-cs-fixer, phpunit.
  * Break: the following namespaces were renamed:
    - Namespace: `Composer\Package\Version` -> `Composer\Semver`
    - Namespace: `Composer\Package\LinkConstraint` -> `Composer\Semver\Constraint`
    - Namespace: `Composer\Test\Package\Version` -> `Composer\Test\Semver`
    - Namespace: `Composer\Test\Package\LinkConstraint` -> `Composer\Test\Semver\Constraint`
  * Changed: code style using php-cs-fixer.

[3.4.3]: https://github.com/composer/semver/compare/3.4.2...3.4.3
[3.4.2]: https://github.com/composer/semver/compare/3.4.1...3.4.2
[3.4.1]: https://github.com/composer/semver/compare/3.4.0...3.4.1
[3.4.0]: https://github.com/composer/semver/compare/3.3.2...3.4.0
[3.3.2]: https://github.com/composer/semver/compare/3.3.1...3.3.2
[3.3.1]: https://github.com/composer/semver/compare/3.3.0...3.3.1
[3.3.0]: https://github.com/composer/semver/compare/3.2.9...3.3.0
[3.2.9]: https://github.com/composer/semver/compare/3.2.8...3.2.9
[3.2.8]: https://github.com/composer/semver/compare/3.2.7...3.2.8
[3.2.7]: https://github.com/composer/semver/compare/3.2.6...3.2.7
[3.2.6]: https://github.com/composer/semver/compare/3.2.5...3.2.6
[3.2.5]: https://github.com/composer/semver/compare/3.2.4...3.2.5
[3.2.4]: https://github.com/composer/semver/compare/3.2.3...3.2.4
[3.2.3]: https://github.com/composer/semver/compare/3.2.2...3.2.3
[3.2.2]: https://github.com/composer/semver/compare/3.2.1...3.2.2
[3.2.1]: https://github.com/composer/semver/compare/3.2.0...3.2.1
[3.2.0]: https://github.com/composer/semver/compare/3.1.0...3.2.0
[3.1.0]: https://github.com/composer/semver/compare/3.0.1...3.1.0
[3.0.1]: https://github.com/composer/semver/compare/3.0.0...3.0.1
[3.0.0]: https://github.com/composer/semver/compare/2.0.0...3.0.0
[2.0.0]: https://github.com/composer/semver/compare/1.5.1...2.0.0
[1.7.2]: https://github.com/composer/semver/compare/1.7.1...1.7.2
[1.7.1]: https://github.com/composer/semver/compare/1.7.0...1.7.1
[1.7.0]: https://github.com/composer/semver/compare/1.6.0...1.7.0
[1.6.0]: https://github.com/composer/semver/compare/1.5.2...1.6.0
[1.5.2]: https://github.com/composer/semver/compare/1.5.1...1.5.2
[1.5.1]: https://github.com/composer/semver/compare/1.5.0...1.5.1
[1.5.0]: https://github.com/composer/semver/compare/1.4.2...1.5.0
[1.4.2]: https://github.com/composer/semver/compare/1.4.1...1.4.2
[1.4.1]: https://github.com/composer/semver/compare/1.4.0...1.4.1
[1.4.0]: https://github.com/composer/semver/compare/1.3.0...1.4.0
[1.3.0]: https://github.com/composer/semver/compare/1.2.0...1.3.0
[1.2.0]: https://github.com/composer/semver/compare/1.1.0...1.2.0
[1.1.0]: https://github.com/composer/semver/compare/1.0.0...1.1.0
[1.0.0]: https://github.com/composer/semver/compare/0.1.0...1.0.0
[0.1.0]: https://github.com/composer/semver/compare/5e0b9a4da...0.1.0
composer/semver
===============

Semver (Semantic Versioning) library that offers utilities, version constraint parsing and validation.

Originally written as part of [composer/composer](https://github.com/composer/composer),
now extracted and made available as a stand-alone library.

[![Continuous Integration](https://github.com/composer/semver/actions/workflows/continuous-integration.yml/badge.svg?branch=main)](https://github.com/composer/semver/actions/workflows/continuous-integration.yml)
[![PHP Lint](https://github.com/composer/semver/actions/workflows/lint.yml/badge.svg?branch=main)](https://github.com/composer/semver/actions/workflows/lint.yml)
[![PHPStan](https://github.com/composer/semver/actions/workflows/phpstan.yml/badge.svg?branch=main)](https://github.com/composer/semver/actions/workflows/phpstan.yml)

Installation
------------

Install the latest version with:

```bash
composer require composer/semver
```


Requirements
------------

* PHP 5.3.2 is required but using the latest version of PHP is highly recommended.


Version Comparison
------------------

For details on how versions are compared, refer to the [Versions](https://getcomposer.org/doc/articles/versions.md)
article in the documentation section of the [getcomposer.org](https://getcomposer.org) website.


Basic usage
-----------

### Comparator

The [`Composer\Semver\Comparator`](https://github.com/composer/semver/blob/main/src/Comparator.php) class provides the following methods for comparing versions:

* greaterThan($v1, $v2)
* greaterThanOrEqualTo($v1, $v2)
* lessThan($v1, $v2)
* lessThanOrEqualTo($v1, $v2)
* equalTo($v1, $v2)
* notEqualTo($v1, $v2)

Each function takes two version strings as arguments and returns a boolean. For example:

```php
use Composer\Semver\Comparator;

Comparator::greaterThan('1.25.0', '1.24.0'); // 1.25.0 > 1.24.0
```

### Semver

The [`Composer\Semver\Semver`](https://github.com/composer/semver/blob/main/src/Semver.php) class provides the following methods:

* satisfies($version, $constraints)
* satisfiedBy(array $versions, $constraint)
* sort($versions)
* rsort($versions)

### Intervals

The [`Composer\Semver\Intervals`](https://github.com/composer/semver/blob/main/src/Intervals.php) static class provides
a few utilities to work with complex constraints or read version intervals from a constraint:

```php
use Composer\Semver\Intervals;

// Checks whether $candidate is a subset of $constraint
Intervals::isSubsetOf(ConstraintInterface $candidate, ConstraintInterface $constraint);

// Checks whether $a and $b have any intersection, equivalent to $a->matches($b)
Intervals::haveIntersections(ConstraintInterface $a, ConstraintInterface $b);

// Optimizes a complex multi constraint by merging all intervals down to the smallest
// possible multi constraint. The drawbacks are this is not very fast, and the resulting
// multi constraint will have no human readable prettyConstraint configured on it
Intervals::compactConstraint(ConstraintInterface $constraint);

// Creates an array of numeric intervals and branch constraints representing a given constraint
Intervals::get(ConstraintInterface $constraint);

// Clears the memoization cache when you are done processing constraints
Intervals::clear()
```

See the class docblocks for more details.


License
-------

composer/semver is licensed under the MIT License, see the LICENSE file for details.
{
    "name": "composer\/semver",
    "description": "Semver library that offers utilities, version constraint parsing and validation.",
    "type": "library",
    "license": "MIT",
    "keywords": [
        "semver",
        "semantic",
        "versioning",
        "validation"
    ],
    "authors": [
        {
            "name": "Nils Adermann",
            "email": "naderman@naderman.de",
            "homepage": "http:\/\/www.naderman.de"
        },
        {
            "name": "Jordi Boggiano",
            "email": "j.boggiano@seld.be",
            "homepage": "http:\/\/seld.be"
        },
        {
            "name": "Rob Bast",
            "email": "rob.bast@gmail.com",
            "homepage": "http:\/\/robbast.nl"
        }
    ],
    "support": {
        "irc": "ircs:\/\/irc.libera.chat:6697\/composer",
        "issues": "https:\/\/github.com\/composer\/semver\/issues"
    },
    "require": {
        "php": "^5.3.2 || ^7.0 || ^8.0"
    },
    "require-dev": {
        "symfony\/phpunit-bridge": "^3 || ^7",
        "phpstan\/phpstan": "^1.11"
    },
    "autoload": {
        "psr-4": {
            "Composer\\Semver\\": "src"
        }
    },
    "autoload-dev": {
        "psr-4": {
            "Composer\\Semver\\": "tests"
        }
    },
    "extra": {
        "branch-alias": {
            "dev-main": "3.x-dev"
        }
    },
    "scripts": {
        "test": "SYMFONY_PHPUNIT_REMOVE_RETURN_TYPEHINT=1 vendor\/bin\/simple-phpunit",
        "phpstan": "@php vendor\/bin\/phpstan analyse"
    }
}<?php

/*
 * This file is part of composer/semver.
 *
 * (c) Composer <https://github.com/composer>
 *
 * For the full copyright and license information, please view
 * the LICENSE file that was distributed with this source code.
 */
namespace Composer\Semver;

use Composer\Semver\Constraint\Constraint;
use Composer\Semver\Constraint\ConstraintInterface;
/**
 * Helper class to evaluate constraint by compiling and reusing the code to evaluate
 */
class CompilingMatcher
{
    /**
     * @var array
     * @phpstan-var array<string, callable>
     */
    private static $compiledCheckerCache = array();
    /**
     * @var array
     * @phpstan-var array<string, bool>
     */
    private static $resultCache = array();
    /** @var bool */
    private static $enabled;
    /**
     * @phpstan-var array<Constraint::OP_*, Constraint::STR_OP_*>
     */
    private static $transOpInt = array(Constraint::OP_EQ => Constraint::STR_OP_EQ, Constraint::OP_LT => Constraint::STR_OP_LT, Constraint::OP_LE => Constraint::STR_OP_LE, Constraint::OP_GT => Constraint::STR_OP_GT, Constraint::OP_GE => Constraint::STR_OP_GE, Constraint::OP_NE => Constraint::STR_OP_NE);
    /**
     * Clears the memoization cache once you are done
     *
     * @return void
     */
    public static function clear()
    {
        self::$resultCache = array();
        self::$compiledCheckerCache = array();
    }
    /**
     * Evaluates the expression: $constraint match $operator $version
     *
     * @param ConstraintInterface $constraint
     * @param int                 $operator
     * @phpstan-param Constraint::OP_*  $operator
     * @param string              $version
     *
     * @return bool
     */
    public static function match(ConstraintInterface $constraint, $operator, $version)
    {
        $resultCacheKey = $operator . $constraint . ';' . $version;
        if (isset(self::$resultCache[$resultCacheKey])) {
            return self::$resultCache[$resultCacheKey];
        }
        if (self::$enabled === null) {
            self::$enabled = !\in_array('eval', explode(',', (string) ini_get('disable_functions')), \true);
        }
        if (!self::$enabled) {
            return self::$resultCache[$resultCacheKey] = $constraint->matches(new Constraint(self::$transOpInt[$operator], $version));
        }
        $cacheKey = $operator . $constraint;
        if (!isset(self::$compiledCheckerCache[$cacheKey])) {
            $code = $constraint->compile($operator);
            self::$compiledCheckerCache[$cacheKey] = $function = eval('return function($v, $b){return ' . $code . ';};');
        } else {
            $function = self::$compiledCheckerCache[$cacheKey];
        }
        return self::$resultCache[$resultCacheKey] = $function($version, strpos($version, 'dev-') === 0);
    }
}
<?php

/*
 * This file is part of composer/semver.
 *
 * (c) Composer <https://github.com/composer>
 *
 * For the full copyright and license information, please view
 * the LICENSE file that was distributed with this source code.
 */
namespace Composer\Semver;

use Composer\Semver\Constraint\Constraint;
class Interval
{
    /** @var Constraint */
    private $start;
    /** @var Constraint */
    private $end;
    public function __construct(Constraint $start, Constraint $end)
    {
        $this->start = $start;
        $this->end = $end;
    }
    /**
     * @return Constraint
     */
    public function getStart()
    {
        return $this->start;
    }
    /**
     * @return Constraint
     */
    public function getEnd()
    {
        return $this->end;
    }
    /**
     * @return Constraint
     */
    public static function fromZero()
    {
        static $zero;
        if (null === $zero) {
            $zero = new Constraint('>=', '0.0.0.0-dev');
        }
        return $zero;
    }
    /**
     * @return Constraint
     */
    public static function untilPositiveInfinity()
    {
        static $positiveInfinity;
        if (null === $positiveInfinity) {
            $positiveInfinity = new Constraint('<', \PHP_INT_MAX . '.0.0.0');
        }
        return $positiveInfinity;
    }
    /**
     * @return self
     */
    public static function any()
    {
        return new self(self::fromZero(), self::untilPositiveInfinity());
    }
    /**
     * @return array{'names': string[], 'exclude': bool}
     */
    public static function anyDev()
    {
        // any == exclude nothing
        return array('names' => array(), 'exclude' => \true);
    }
    /**
     * @return array{'names': string[], 'exclude': bool}
     */
    public static function noDev()
    {
        // nothing == no names included
        return array('names' => array(), 'exclude' => \false);
    }
}
<?php

/*
 * This file is part of composer/semver.
 *
 * (c) Composer <https://github.com/composer>
 *
 * For the full copyright and license information, please view
 * the LICENSE file that was distributed with this source code.
 */
namespace Composer\Semver;

use Composer\Semver\Constraint\Constraint;
class Comparator
{
    /**
     * Evaluates the expression: $version1 > $version2.
     *
     * @param string $version1
     * @param string $version2
     *
     * @return bool
     */
    public static function greaterThan($version1, $version2)
    {
        return self::compare($version1, '>', $version2);
    }
    /**
     * Evaluates the expression: $version1 >= $version2.
     *
     * @param string $version1
     * @param string $version2
     *
     * @return bool
     */
    public static function greaterThanOrEqualTo($version1, $version2)
    {
        return self::compare($version1, '>=', $version2);
    }
    /**
     * Evaluates the expression: $version1 < $version2.
     *
     * @param string $version1
     * @param string $version2
     *
     * @return bool
     */
    public static function lessThan($version1, $version2)
    {
        return self::compare($version1, '<', $version2);
    }
    /**
     * Evaluates the expression: $version1 <= $version2.
     *
     * @param string $version1
     * @param string $version2
     *
     * @return bool
     */
    public static function lessThanOrEqualTo($version1, $version2)
    {
        return self::compare($version1, '<=', $version2);
    }
    /**
     * Evaluates the expression: $version1 == $version2.
     *
     * @param string $version1
     * @param string $version2
     *
     * @return bool
     */
    public static function equalTo($version1, $version2)
    {
        return self::compare($version1, '==', $version2);
    }
    /**
     * Evaluates the expression: $version1 != $version2.
     *
     * @param string $version1
     * @param string $version2
     *
     * @return bool
     */
    public static function notEqualTo($version1, $version2)
    {
        return self::compare($version1, '!=', $version2);
    }
    /**
     * Evaluates the expression: $version1 $operator $version2.
     *
     * @param string $version1
     * @param string $operator
     * @param string $version2
     *
     * @return bool
     *
     * @phpstan-param Constraint::STR_OP_*  $operator
     */
    public static function compare($version1, $operator, $version2)
    {
        $constraint = new Constraint($operator, $version2);
        return $constraint->matchSpecific(new Constraint('==', $version1), \true);
    }
}
<?php

/*
 * This file is part of composer/semver.
 *
 * (c) Composer <https://github.com/composer>
 *
 * For the full copyright and license information, please view
 * the LICENSE file that was distributed with this source code.
 */
namespace Composer\Semver;

use Composer\Semver\Constraint\Constraint;
use Composer\Semver\Constraint\ConstraintInterface;
use Composer\Semver\Constraint\MatchAllConstraint;
use Composer\Semver\Constraint\MatchNoneConstraint;
use Composer\Semver\Constraint\MultiConstraint;
/**
 * Helper class generating intervals from constraints
 *
 * This contains utilities for:
 *
 *  - compacting an existing constraint which can be used to combine several into one
 * by creating a MultiConstraint out of the many constraints you have.
 *
 *  - checking whether one subset is a subset of another.
 *
 * Note: You should call clear to free memoization memory  usage when you are done using this class
 */
class Intervals
{
    /**
     * @phpstan-var array<string, array{'numeric': Interval[], 'branches': array{'names': string[], 'exclude': bool}}>
     */
    private static $intervalsCache = array();
    /**
     * @phpstan-var array<string, int>
     */
    private static $opSortOrder = array('>=' => -3, '<' => -2, '>' => 2, '<=' => 3);
    /**
     * Clears the memoization cache once you are done
     *
     * @return void
     */
    public static function clear()
    {
        self::$intervalsCache = array();
    }
    /**
     * Checks whether $candidate is a subset of $constraint
     *
     * @return bool
     */
    public static function isSubsetOf(ConstraintInterface $candidate, ConstraintInterface $constraint)
    {
        if ($constraint instanceof MatchAllConstraint) {
            return \true;
        }
        if ($candidate instanceof MatchNoneConstraint || $constraint instanceof MatchNoneConstraint) {
            return \false;
        }
        $intersectionIntervals = self::get(new MultiConstraint(array($candidate, $constraint), \true));
        $candidateIntervals = self::get($candidate);
        if (\count($intersectionIntervals['numeric']) !== \count($candidateIntervals['numeric'])) {
            return \false;
        }
        foreach ($intersectionIntervals['numeric'] as $index => $interval) {
            if (!isset($candidateIntervals['numeric'][$index])) {
                return \false;
            }
            if ((string) $candidateIntervals['numeric'][$index]->getStart() !== (string) $interval->getStart()) {
                return \false;
            }
            if ((string) $candidateIntervals['numeric'][$index]->getEnd() !== (string) $interval->getEnd()) {
                return \false;
            }
        }
        if ($intersectionIntervals['branches']['exclude'] !== $candidateIntervals['branches']['exclude']) {
            return \false;
        }
        if (\count($intersectionIntervals['branches']['names']) !== \count($candidateIntervals['branches']['names'])) {
            return \false;
        }
        foreach ($intersectionIntervals['branches']['names'] as $index => $name) {
            if ($name !== $candidateIntervals['branches']['names'][$index]) {
                return \false;
            }
        }
        return \true;
    }
    /**
     * Checks whether $a and $b have any intersection, equivalent to $a->matches($b)
     *
     * @return bool
     */
    public static function haveIntersections(ConstraintInterface $a, ConstraintInterface $b)
    {
        if ($a instanceof MatchAllConstraint || $b instanceof MatchAllConstraint) {
            return \true;
        }
        if ($a instanceof MatchNoneConstraint || $b instanceof MatchNoneConstraint) {
            return \false;
        }
        $intersectionIntervals = self::generateIntervals(new MultiConstraint(array($a, $b), \true), \true);
        return \count($intersectionIntervals['numeric']) > 0 || $intersectionIntervals['branches']['exclude'] || \count($intersectionIntervals['branches']['names']) > 0;
    }
    /**
     * Attempts to optimize a MultiConstraint
     *
     * When merging MultiConstraints together they can get very large, this will
     * compact it by looking at the real intervals covered by all the constraints
     * and then creates a new constraint containing only the smallest amount of rules
     * to match the same intervals.
     *
     * @return ConstraintInterface
     */
    public static function compactConstraint(ConstraintInterface $constraint)
    {
        if (!$constraint instanceof MultiConstraint) {
            return $constraint;
        }
        $intervals = self::generateIntervals($constraint);
        $constraints = array();
        $hasNumericMatchAll = \false;
        if (\count($intervals['numeric']) === 1 && (string) $intervals['numeric'][0]->getStart() === (string) \Composer\Semver\Interval::fromZero() && (string) $intervals['numeric'][0]->getEnd() === (string) \Composer\Semver\Interval::untilPositiveInfinity()) {
            $constraints[] = $intervals['numeric'][0]->getStart();
            $hasNumericMatchAll = \true;
        } else {
            $unEqualConstraints = array();
            for ($i = 0, $count = \count($intervals['numeric']); $i < $count; $i++) {
                $interval = $intervals['numeric'][$i];
                // if current interval ends with < N and next interval begins with > N we can swap this out for != N
                // but this needs to happen as a conjunctive expression together with the start of the current interval
                // and end of next interval, so [>=M, <N] || [>N, <P] => [>=M, !=N, <P] but M/P can be skipped if
                // they are zero/+inf
                if ($interval->getEnd()->getOperator() === '<' && $i + 1 < $count) {
                    $nextInterval = $intervals['numeric'][$i + 1];
                    if ($interval->getEnd()->getVersion() === $nextInterval->getStart()->getVersion() && $nextInterval->getStart()->getOperator() === '>') {
                        // only add a start if we didn't already do so, can be skipped if we're looking at second
                        // interval in [>=M, <N] || [>N, <P] || [>P, <Q] where unEqualConstraints currently contains
                        // [>=M, !=N] already and we only want to add !=P right now
                        if (\count($unEqualConstraints) === 0 && (string) $interval->getStart() !== (string) \Composer\Semver\Interval::fromZero()) {
                            $unEqualConstraints[] = $interval->getStart();
                        }
                        $unEqualConstraints[] = new Constraint('!=', $interval->getEnd()->getVersion());
                        continue;
                    }
                }
                if (\count($unEqualConstraints) > 0) {
                    // this is where the end of the following interval of a != constraint is added as explained above
                    if ((string) $interval->getEnd() !== (string) \Composer\Semver\Interval::untilPositiveInfinity()) {
                        $unEqualConstraints[] = $interval->getEnd();
                    }
                    // count is 1 if entire constraint is just one != expression
                    if (\count($unEqualConstraints) > 1) {
                        $constraints[] = new MultiConstraint($unEqualConstraints, \true);
                    } else {
                        $constraints[] = $unEqualConstraints[0];
                    }
                    $unEqualConstraints = array();
                    continue;
                }
                // convert back >= x - <= x intervals to == x
                if ($interval->getStart()->getVersion() === $interval->getEnd()->getVersion() && $interval->getStart()->getOperator() === '>=' && $interval->getEnd()->getOperator() === '<=') {
                    $constraints[] = new Constraint('==', $interval->getStart()->getVersion());
                    continue;
                }
                if ((string) $interval->getStart() === (string) \Composer\Semver\Interval::fromZero()) {
                    $constraints[] = $interval->getEnd();
                } elseif ((string) $interval->getEnd() === (string) \Composer\Semver\Interval::untilPositiveInfinity()) {
                    $constraints[] = $interval->getStart();
                } else {
                    $constraints[] = new MultiConstraint(array($interval->getStart(), $interval->getEnd()), \true);
                }
            }
        }
        $devConstraints = array();
        if (0 === \count($intervals['branches']['names'])) {
            if ($intervals['branches']['exclude']) {
                if ($hasNumericMatchAll) {
                    return new MatchAllConstraint();
                }
                // otherwise constraint should contain a != operator and already cover this
            }
        } else {
            foreach ($intervals['branches']['names'] as $branchName) {
                if ($intervals['branches']['exclude']) {
                    $devConstraints[] = new Constraint('!=', $branchName);
                } else {
                    $devConstraints[] = new Constraint('==', $branchName);
                }
            }
            // excluded branches, e.g. != dev-foo are conjunctive with the interval, so
            // > 2.0 != dev-foo must return a conjunctive constraint
            if ($intervals['branches']['exclude']) {
                if (\count($constraints) > 1) {
                    return new MultiConstraint(array_merge(array(new MultiConstraint($constraints, \false)), $devConstraints), \true);
                }
                if (\count($constraints) === 1 && (string) $constraints[0] === (string) \Composer\Semver\Interval::fromZero()) {
                    if (\count($devConstraints) > 1) {
                        return new MultiConstraint($devConstraints, \true);
                    }
                    return $devConstraints[0];
                }
                return new MultiConstraint(array_merge($constraints, $devConstraints), \true);
            }
            // otherwise devConstraints contains a list of == operators for branches which are disjunctive with the
            // rest of the constraint
            $constraints = array_merge($constraints, $devConstraints);
        }
        if (\count($constraints) > 1) {
            return new MultiConstraint($constraints, \false);
        }
        if (\count($constraints) === 1) {
            return $constraints[0];
        }
        return new MatchNoneConstraint();
    }
    /**
     * Creates an array of numeric intervals and branch constraints representing a given constraint
     *
     * if the returned numeric array is empty it means the constraint matches nothing in the numeric range (0 - +inf)
     * if the returned branches array is empty it means no dev-* versions are matched
     * if a constraint matches all possible dev-* versions, branches will contain Interval::anyDev()
     *
     * @return array
     * @phpstan-return array{'numeric': Interval[], 'branches': array{'names': string[], 'exclude': bool}}
     */
    public static function get(ConstraintInterface $constraint)
    {
        $key = (string) $constraint;
        if (!isset(self::$intervalsCache[$key])) {
            self::$intervalsCache[$key] = self::generateIntervals($constraint);
        }
        return self::$intervalsCache[$key];
    }
    /**
     * @param bool $stopOnFirstValidInterval
     *
     * @phpstan-return array{'numeric': Interval[], 'branches': array{'names': string[], 'exclude': bool}}
     */
    private static function generateIntervals(ConstraintInterface $constraint, $stopOnFirstValidInterval = \false)
    {
        if ($constraint instanceof MatchAllConstraint) {
            return array('numeric' => array(new \Composer\Semver\Interval(\Composer\Semver\Interval::fromZero(), \Composer\Semver\Interval::untilPositiveInfinity())), 'branches' => \Composer\Semver\Interval::anyDev());
        }
        if ($constraint instanceof MatchNoneConstraint) {
            return array('numeric' => array(), 'branches' => array('names' => array(), 'exclude' => \false));
        }
        if ($constraint instanceof Constraint) {
            return self::generateSingleConstraintIntervals($constraint);
        }
        if (!$constraint instanceof MultiConstraint) {
            throw new \UnexpectedValueException('The constraint passed in should be an MatchAllConstraint, Constraint or MultiConstraint instance, got ' . \get_class($constraint) . '.');
        }
        $constraints = $constraint->getConstraints();
        $numericGroups = array();
        $constraintBranches = array();
        foreach ($constraints as $c) {
            $res = self::get($c);
            $numericGroups[] = $res['numeric'];
            $constraintBranches[] = $res['branches'];
        }
        if ($constraint->isDisjunctive()) {
            $branches = \Composer\Semver\Interval::noDev();
            foreach ($constraintBranches as $b) {
                if ($b['exclude']) {
                    if ($branches['exclude']) {
                        // disjunctive constraint, so only exclude what's excluded in all constraints
                        // !=a,!=b || !=b,!=c => !=b
                        $branches['names'] = array_intersect($branches['names'], $b['names']);
                    } else {
                        // disjunctive constraint so exclude all names which are not explicitly included in the alternative
                        // (==b || ==c) || !=a,!=b => !=a
                        $branches['exclude'] = \true;
                        $branches['names'] = array_diff($b['names'], $branches['names']);
                    }
                } else if ($branches['exclude']) {
                    // disjunctive constraint so exclude all names which are not explicitly included in the alternative
                    // !=a,!=b || (==b || ==c) => !=a
                    $branches['names'] = array_diff($branches['names'], $b['names']);
                } else {
                    // disjunctive constraint, so just add all the other branches
                    // (==a || ==b) || ==c => ==a || ==b || ==c
                    $branches['names'] = array_merge($branches['names'], $b['names']);
                }
            }
        } else {
            $branches = \Composer\Semver\Interval::anyDev();
            foreach ($constraintBranches as $b) {
                if ($b['exclude']) {
                    if ($branches['exclude']) {
                        // conjunctive, so just add all branch names to be excluded
                        // !=a && !=b => !=a,!=b
                        $branches['names'] = array_merge($branches['names'], $b['names']);
                    } else {
                        // conjunctive, so only keep included names which are not excluded
                        // (==a||==c) && !=a,!=b => ==c
                        $branches['names'] = array_diff($branches['names'], $b['names']);
                    }
                } else if ($branches['exclude']) {
                    // conjunctive, so only keep included names which are not excluded
                    // !=a,!=b && (==a||==c) => ==c
                    $branches['names'] = array_diff($b['names'], $branches['names']);
                    $branches['exclude'] = \false;
                } else {
                    // conjunctive, so only keep names that are included in both
                    // (==a||==b) && (==a||==c) => ==a
                    $branches['names'] = array_intersect($branches['names'], $b['names']);
                }
            }
        }
        $branches['names'] = array_unique($branches['names']);
        if (\count($numericGroups) === 1) {
            return array('numeric' => $numericGroups[0], 'branches' => $branches);
        }
        $borders = array();
        foreach ($numericGroups as $group) {
            foreach ($group as $interval) {
                $borders[] = array('version' => $interval->getStart()->getVersion(), 'operator' => $interval->getStart()->getOperator(), 'side' => 'start');
                $borders[] = array('version' => $interval->getEnd()->getVersion(), 'operator' => $interval->getEnd()->getOperator(), 'side' => 'end');
            }
        }
        $opSortOrder = self::$opSortOrder;
        usort($borders, function ($a, $b) use ($opSortOrder) {
            $order = version_compare($a['version'], $b['version']);
            if ($order === 0) {
                return $opSortOrder[$a['operator']] - $opSortOrder[$b['operator']];
            }
            return $order;
        });
        $activeIntervals = 0;
        $intervals = array();
        $index = 0;
        $activationThreshold = $constraint->isConjunctive() ? \count($numericGroups) : 1;
        $start = null;
        foreach ($borders as $border) {
            if ($border['side'] === 'start') {
                $activeIntervals++;
            } else {
                $activeIntervals--;
            }
            if (!$start && $activeIntervals >= $activationThreshold) {
                $start = new Constraint($border['operator'], $border['version']);
            } elseif ($start && $activeIntervals < $activationThreshold) {
                // filter out invalid intervals like > x - <= x, or >= x - < x
                if (version_compare($start->getVersion(), $border['version'], '=') && ($start->getOperator() === '>' && $border['operator'] === '<=' || $start->getOperator() === '>=' && $border['operator'] === '<')) {
                    unset($intervals[$index]);
                } else {
                    $intervals[$index] = new \Composer\Semver\Interval($start, new Constraint($border['operator'], $border['version']));
                    $index++;
                    if ($stopOnFirstValidInterval) {
                        break;
                    }
                }
                $start = null;
            }
        }
        return array('numeric' => $intervals, 'branches' => $branches);
    }
    /**
     * @phpstan-return array{'numeric': Interval[], 'branches': array{'names': string[], 'exclude': bool}}
     */
    private static function generateSingleConstraintIntervals(Constraint $constraint)
    {
        $op = $constraint->getOperator();
        // handle branch constraints first
        if (strpos($constraint->getVersion(), 'dev-') === 0) {
            $intervals = array();
            $branches = array('names' => array(), 'exclude' => \false);
            // != dev-foo means any numeric version may match, we treat >/< like != they are not really defined for branches
            if ($op === '!=') {
                $intervals[] = new \Composer\Semver\Interval(\Composer\Semver\Interval::fromZero(), \Composer\Semver\Interval::untilPositiveInfinity());
                $branches = array('names' => array($constraint->getVersion()), 'exclude' => \true);
            } elseif ($op === '==') {
                $branches['names'][] = $constraint->getVersion();
            }
            return array('numeric' => $intervals, 'branches' => $branches);
        }
        if ($op[0] === '>') {
            // > & >=
            return array('numeric' => array(new \Composer\Semver\Interval($constraint, \Composer\Semver\Interval::untilPositiveInfinity())), 'branches' => \Composer\Semver\Interval::noDev());
        }
        if ($op[0] === '<') {
            // < & <=
            return array('numeric' => array(new \Composer\Semver\Interval(\Composer\Semver\Interval::fromZero(), $constraint)), 'branches' => \Composer\Semver\Interval::noDev());
        }
        if ($op === '!=') {
            // convert !=x to intervals of 0 - <x && >x - +inf + dev*
            return array('numeric' => array(new \Composer\Semver\Interval(\Composer\Semver\Interval::fromZero(), new Constraint('<', $constraint->getVersion())), new \Composer\Semver\Interval(new Constraint('>', $constraint->getVersion()), \Composer\Semver\Interval::untilPositiveInfinity())), 'branches' => \Composer\Semver\Interval::anyDev());
        }
        // convert ==x to an interval of >=x - <=x
        return array('numeric' => array(new \Composer\Semver\Interval(new Constraint('>=', $constraint->getVersion()), new Constraint('<=', $constraint->getVersion()))), 'branches' => \Composer\Semver\Interval::noDev());
    }
}
<?php

/*
 * This file is part of composer/semver.
 *
 * (c) Composer <https://github.com/composer>
 *
 * For the full copyright and license information, please view
 * the LICENSE file that was distributed with this source code.
 */
namespace Composer\Semver;

use Composer\Semver\Constraint\Constraint;
class Semver
{
    const SORT_ASC = 1;
    const SORT_DESC = -1;
    /** @var VersionParser */
    private static $versionParser;
    /**
     * Determine if given version satisfies given constraints.
     *
     * @param string $version
     * @param string $constraints
     *
     * @return bool
     */
    public static function satisfies($version, $constraints)
    {
        if (null === self::$versionParser) {
            self::$versionParser = new \Composer\Semver\VersionParser();
        }
        $versionParser = self::$versionParser;
        $provider = new Constraint('==', $versionParser->normalize($version));
        $parsedConstraints = $versionParser->parseConstraints($constraints);
        return $parsedConstraints->matches($provider);
    }
    /**
     * Return all versions that satisfy given constraints.
     *
     * @param string[] $versions
     * @param string   $constraints
     *
     * @return list<string>
     */
    public static function satisfiedBy(array $versions, $constraints)
    {
        $versions = array_filter($versions, function ($version) use ($constraints) {
            return \Composer\Semver\Semver::satisfies($version, $constraints);
        });
        return array_values($versions);
    }
    /**
     * Sort given array of versions.
     *
     * @param string[] $versions
     *
     * @return list<string>
     */
    public static function sort(array $versions)
    {
        return self::usort($versions, self::SORT_ASC);
    }
    /**
     * Sort given array of versions in reverse.
     *
     * @param string[] $versions
     *
     * @return list<string>
     */
    public static function rsort(array $versions)
    {
        return self::usort($versions, self::SORT_DESC);
    }
    /**
     * @param string[] $versions
     * @param int      $direction
     *
     * @return list<string>
     */
    private static function usort(array $versions, $direction)
    {
        if (null === self::$versionParser) {
            self::$versionParser = new \Composer\Semver\VersionParser();
        }
        $versionParser = self::$versionParser;
        $normalized = array();
        // Normalize outside of usort() scope for minor performance increase.
        // Creates an array of arrays: [[normalized, key], ...]
        foreach ($versions as $key => $version) {
            $normalizedVersion = $versionParser->normalize($version);
            $normalizedVersion = $versionParser->normalizeDefaultBranch($normalizedVersion);
            $normalized[] = array($normalizedVersion, $key);
        }
        usort($normalized, function (array $left, array $right) use ($direction) {
            if ($left[0] === $right[0]) {
                return 0;
            }
            if (\Composer\Semver\Comparator::lessThan($left[0], $right[0])) {
                return -$direction;
            }
            return $direction;
        });
        // Recreate input array, using the original indexes which are now in sorted order.
        $sorted = array();
        foreach ($normalized as $item) {
            $sorted[] = $versions[$item[1]];
        }
        return $sorted;
    }
}
<?php

/*
 * This file is part of composer/semver.
 *
 * (c) Composer <https://github.com/composer>
 *
 * For the full copyright and license information, please view
 * the LICENSE file that was distributed with this source code.
 */
namespace Composer\Semver;

use Composer\Semver\Constraint\ConstraintInterface;
use Composer\Semver\Constraint\MatchAllConstraint;
use Composer\Semver\Constraint\MultiConstraint;
use Composer\Semver\Constraint\Constraint;
/**
 * Version parser.
 *
 * @author Jordi Boggiano <j.boggiano@seld.be>
 */
class VersionParser
{
    /**
     * Regex to match pre-release data (sort of).
     *
     * Due to backwards compatibility:
     *   - Instead of enforcing hyphen, an underscore, dot or nothing at all are also accepted.
     *   - Only stabilities as recognized by Composer are allowed to precede a numerical identifier.
     *   - Numerical-only pre-release identifiers are not supported, see tests.
     *
     *                        |--------------|
     * [major].[minor].[patch] -[pre-release] +[build-metadata]
     *
     * @var string
     */
    private static $modifierRegex = '[._-]?(?:(stable|beta|b|RC|alpha|a|patch|pl|p)((?:[.-]?\d+)*+)?)?([.-]?dev)?';
    /** @var string */
    private static $stabilitiesRegex = 'stable|RC|beta|alpha|dev';
    /**
     * Returns the stability of a version.
     *
     * @param string $version
     *
     * @return string
     * @phpstan-return 'stable'|'RC'|'beta'|'alpha'|'dev'
     */
    public static function parseStability($version)
    {
        $version = (string) preg_replace('{#.+$}', '', (string) $version);
        if (strpos($version, 'dev-') === 0 || '-dev' === substr($version, -4)) {
            return 'dev';
        }
        preg_match('{' . self::$modifierRegex . '(?:\+.*)?$}i', strtolower($version), $match);
        if (!empty($match[3])) {
            return 'dev';
        }
        if (!empty($match[1])) {
            if ('beta' === $match[1] || 'b' === $match[1]) {
                return 'beta';
            }
            if ('alpha' === $match[1] || 'a' === $match[1]) {
                return 'alpha';
            }
            if ('rc' === $match[1]) {
                return 'RC';
            }
        }
        return 'stable';
    }
    /**
     * @param string $stability
     *
     * @return string
     * @phpstan-return 'stable'|'RC'|'beta'|'alpha'|'dev'
     */
    public static function normalizeStability($stability)
    {
        $stability = strtolower((string) $stability);
        if (!in_array($stability, array('stable', 'rc', 'beta', 'alpha', 'dev'), \true)) {
            throw new \InvalidArgumentException('Invalid stability string "' . $stability . '", expected one of stable, RC, beta, alpha or dev');
        }
        return $stability === 'rc' ? 'RC' : $stability;
    }
    /**
     * Normalizes a version string to be able to perform comparisons on it.
     *
     * @param string $version
     * @param ?string $fullVersion optional complete version string to give more context
     *
     * @throws \UnexpectedValueException
     *
     * @return string
     */
    public function normalize($version, $fullVersion = null)
    {
        $version = trim((string) $version);
        $origVersion = $version;
        if (null === $fullVersion) {
            $fullVersion = $version;
        }
        // strip off aliasing
        if (preg_match('{^([^,\s]++) ++as ++([^,\s]++)$}', $version, $match)) {
            $version = $match[1];
        }
        // strip off stability flag
        if (preg_match('{@(?:' . self::$stabilitiesRegex . ')$}i', $version, $match)) {
            $version = substr($version, 0, strlen($version) - strlen($match[0]));
        }
        // normalize master/trunk/default branches to dev-name for BC with 1.x as these used to be valid constraints
        if (\in_array($version, array('master', 'trunk', 'default'), \true)) {
            $version = 'dev-' . $version;
        }
        // if requirement is branch-like, use full name
        if (stripos($version, 'dev-') === 0) {
            return 'dev-' . substr($version, 4);
        }
        // strip off build metadata
        if (preg_match('{^([^,\s+]++)\+[^\s]++$}', $version, $match)) {
            $version = $match[1];
        }
        // match classical versioning
        if (preg_match('{^v?(\d{1,5}+)(\.\d++)?(\.\d++)?(\.\d++)?' . self::$modifierRegex . '$}i', $version, $matches)) {
            $version = $matches[1] . (!empty($matches[2]) ? $matches[2] : '.0') . (!empty($matches[3]) ? $matches[3] : '.0') . (!empty($matches[4]) ? $matches[4] : '.0');
            $index = 5;
            // match date(time) based versioning
        } elseif (preg_match('{^v?(\d{4}(?:[.:-]?\d{2}){1,6}(?:[.:-]?\d{1,3}){0,2})' . self::$modifierRegex . '$}i', $version, $matches)) {
            $version = (string) preg_replace('{\D}', '.', $matches[1]);
            $index = 2;
        }
        // add version modifiers if a version was matched
        if (isset($index)) {
            if (!empty($matches[$index])) {
                if ('stable' === $matches[$index]) {
                    return $version;
                }
                $version .= '-' . $this->expandStability($matches[$index]) . (isset($matches[$index + 1]) && '' !== $matches[$index + 1] ? ltrim($matches[$index + 1], '.-') : '');
            }
            if (!empty($matches[$index + 2])) {
                $version .= '-dev';
            }
            return $version;
        }
        // match dev branches
        if (preg_match('{(.*?)[.-]?dev$}i', $version, $match)) {
            try {
                $normalized = $this->normalizeBranch($match[1]);
                // a branch ending with -dev is only valid if it is numeric
                // if it gets prefixed with dev- it means the branch name should
                // have had a dev- prefix already when passed to normalize
                if (strpos($normalized, 'dev-') === \false) {
                    return $normalized;
                }
            } catch (\Exception $e) {
            }
        }
        $extraMessage = '';
        if (preg_match('{ +as +' . preg_quote($version) . '(?:@(?:' . self::$stabilitiesRegex . '))?$}', $fullVersion)) {
            $extraMessage = ' in "' . $fullVersion . '", the alias must be an exact version';
        } elseif (preg_match('{^' . preg_quote($version) . '(?:@(?:' . self::$stabilitiesRegex . '))? +as +}', $fullVersion)) {
            $extraMessage = ' in "' . $fullVersion . '", the alias source must be an exact version, if it is a branch name you should prefix it with dev-';
        }
        throw new \UnexpectedValueException('Invalid version string "' . $origVersion . '"' . $extraMessage);
    }
    /**
     * Extract numeric prefix from alias, if it is in numeric format, suitable for version comparison.
     *
     * @param string $branch Branch name (e.g. 2.1.x-dev)
     *
     * @return string|false Numeric prefix if present (e.g. 2.1.) or false
     */
    public function parseNumericAliasPrefix($branch)
    {
        if (preg_match('{^(?P<version>(\d++\.)*\d++)(?:\.x)?-dev$}i', (string) $branch, $matches)) {
            return $matches['version'] . '.';
        }
        return \false;
    }
    /**
     * Normalizes a branch name to be able to perform comparisons on it.
     *
     * @param string $name
     *
     * @return string
     */
    public function normalizeBranch($name)
    {
        $name = trim((string) $name);
        if (preg_match('{^v?(\d++)(\.(?:\d++|[xX*]))?(\.(?:\d++|[xX*]))?(\.(?:\d++|[xX*]))?$}i', $name, $matches)) {
            $version = '';
            for ($i = 1; $i < 5; ++$i) {
                $version .= isset($matches[$i]) ? str_replace(array('*', 'X'), 'x', $matches[$i]) : '.x';
            }
            return str_replace('x', '9999999', $version) . '-dev';
        }
        return 'dev-' . $name;
    }
    /**
     * Normalizes a default branch name (i.e. master on git) to 9999999-dev.
     *
     * @param string $name
     *
     * @return string
     *
     * @deprecated No need to use this anymore in theory, Composer 2 does not normalize any branch names to 9999999-dev anymore
     */
    public function normalizeDefaultBranch($name)
    {
        if ($name === 'dev-master' || $name === 'dev-default' || $name === 'dev-trunk') {
            return '9999999-dev';
        }
        return (string) $name;
    }
    /**
     * Parses a constraint string into MultiConstraint and/or Constraint objects.
     *
     * @param string $constraints
     *
     * @return ConstraintInterface
     */
    public function parseConstraints($constraints)
    {
        $prettyConstraint = (string) $constraints;
        $orConstraints = preg_split('{\s*\|\|?\s*}', trim((string) $constraints));
        if (\false === $orConstraints) {
            throw new \RuntimeException('Failed to preg_split string: ' . $constraints);
        }
        $orGroups = array();
        foreach ($orConstraints as $orConstraint) {
            $andConstraints = preg_split('{(?<!^|as|[=>< ,]) *(?<!-)[, ](?!-) *(?!,|as|$)}', $orConstraint);
            if (\false === $andConstraints) {
                throw new \RuntimeException('Failed to preg_split string: ' . $orConstraint);
            }
            if (\count($andConstraints) > 1) {
                $constraintObjects = array();
                foreach ($andConstraints as $andConstraint) {
                    foreach ($this->parseConstraint($andConstraint) as $parsedAndConstraint) {
                        $constraintObjects[] = $parsedAndConstraint;
                    }
                }
            } else {
                $constraintObjects = $this->parseConstraint($andConstraints[0]);
            }
            if (1 === \count($constraintObjects)) {
                $constraint = $constraintObjects[0];
            } else {
                $constraint = new MultiConstraint($constraintObjects);
            }
            $orGroups[] = $constraint;
        }
        $parsedConstraint = MultiConstraint::create($orGroups, \false);
        $parsedConstraint->setPrettyString($prettyConstraint);
        return $parsedConstraint;
    }
    /**
     * @param string $constraint
     *
     * @throws \UnexpectedValueException
     *
     * @return array
     *
     * @phpstan-return non-empty-array<ConstraintInterface>
     */
    private function parseConstraint($constraint)
    {
        // strip off aliasing
        if (preg_match('{^([^,\s]++) ++as ++([^,\s]++)$}', $constraint, $match)) {
            $constraint = $match[1];
        }
        // strip @stability flags, and keep it for later use
        if (preg_match('{^([^,\s]*?)@(' . self::$stabilitiesRegex . ')$}i', $constraint, $match)) {
            $constraint = '' !== $match[1] ? $match[1] : '*';
            if ($match[2] !== 'stable') {
                $stabilityModifier = $match[2];
            }
        }
        // get rid of #refs as those are used by composer only
        if (preg_match('{^(dev-[^,\s@]+?|[^,\s@]+?\.x-dev)#.+$}i', $constraint, $match)) {
            $constraint = $match[1];
        }
        if (preg_match('{^(v)?[xX*](\.[xX*])*$}i', $constraint, $match)) {
            if (!empty($match[1]) || !empty($match[2])) {
                return array(new Constraint('>=', '0.0.0.0-dev'));
            }
            return array(new MatchAllConstraint());
        }
        $versionRegex = 'v?(\d++)(?:\.(\d++))?(?:\.(\d++))?(?:\.(\d++))?(?:' . self::$modifierRegex . '|\.([xX*][.-]?dev))(?:\+[^\s]+)?';
        // Tilde Range
        //
        // Like wildcard constraints, unsuffixed tilde constraints say that they must be greater than the previous
        // version, to ensure that unstable instances of the current version are allowed. However, if a stability
        // suffix is added to the constraint, then a >= match on the current version is used instead.
        if (preg_match('{^~>?' . $versionRegex . '$}i', $constraint, $matches)) {
            if (strpos($constraint, '~>') === 0) {
                throw new \UnexpectedValueException('Could not parse version constraint ' . $constraint . ': ' . 'Invalid operator "~>", you probably meant to use the "~" operator');
            }
            // Work out which position in the version we are operating at
            if (isset($matches[4]) && '' !== $matches[4] && null !== $matches[4]) {
                $position = 4;
            } elseif (isset($matches[3]) && '' !== $matches[3] && null !== $matches[3]) {
                $position = 3;
            } elseif (isset($matches[2]) && '' !== $matches[2] && null !== $matches[2]) {
                $position = 2;
            } else {
                $position = 1;
            }
            // when matching 2.x-dev or 3.0.x-dev we have to shift the second or third number, despite no second/third number matching above
            if (!empty($matches[8])) {
                $position++;
            }
            // Calculate the stability suffix
            $stabilitySuffix = '';
            if (empty($matches[5]) && empty($matches[7]) && empty($matches[8])) {
                $stabilitySuffix .= '-dev';
            }
            $lowVersion = $this->normalize(substr($constraint . $stabilitySuffix, 1));
            $lowerBound = new Constraint('>=', $lowVersion);
            // For upper bound, we increment the position of one more significance,
            // but highPosition = 0 would be illegal
            $highPosition = max(1, $position - 1);
            $highVersion = $this->manipulateVersionString($matches, $highPosition, 1) . '-dev';
            $upperBound = new Constraint('<', $highVersion);
            return array($lowerBound, $upperBound);
        }
        // Caret Range
        //
        // Allows changes that do not modify the left-most non-zero digit in the [major, minor, patch] tuple.
        // In other words, this allows patch and minor updates for versions 1.0.0 and above, patch updates for
        // versions 0.X >=0.1.0, and no updates for versions 0.0.X
        if (preg_match('{^\^' . $versionRegex . '($)}i', $constraint, $matches)) {
            // Work out which position in the version we are operating at
            if ('0' !== $matches[1] || '' === $matches[2] || null === $matches[2]) {
                $position = 1;
            } elseif ('0' !== $matches[2] || '' === $matches[3] || null === $matches[3]) {
                $position = 2;
            } else {
                $position = 3;
            }
            // Calculate the stability suffix
            $stabilitySuffix = '';
            if (empty($matches[5]) && empty($matches[7]) && empty($matches[8])) {
                $stabilitySuffix .= '-dev';
            }
            $lowVersion = $this->normalize(substr($constraint . $stabilitySuffix, 1));
            $lowerBound = new Constraint('>=', $lowVersion);
            // For upper bound, we increment the position of one more significance,
            // but highPosition = 0 would be illegal
            $highVersion = $this->manipulateVersionString($matches, $position, 1) . '-dev';
            $upperBound = new Constraint('<', $highVersion);
            return array($lowerBound, $upperBound);
        }
        // X Range
        //
        // Any of X, x, or * may be used to "stand in" for one of the numeric values in the [major, minor, patch] tuple.
        // A partial version range is treated as an X-Range, so the special character is in fact optional.
        if (preg_match('{^v?(\d++)(?:\.(\d++))?(?:\.(\d++))?(?:\.[xX*])++$}', $constraint, $matches)) {
            if (isset($matches[3]) && '' !== $matches[3] && null !== $matches[3]) {
                $position = 3;
            } elseif (isset($matches[2]) && '' !== $matches[2] && null !== $matches[2]) {
                $position = 2;
            } else {
                $position = 1;
            }
            $lowVersion = $this->manipulateVersionString($matches, $position) . '-dev';
            $highVersion = $this->manipulateVersionString($matches, $position, 1) . '-dev';
            if ($lowVersion === '0.0.0.0-dev') {
                return array(new Constraint('<', $highVersion));
            }
            return array(new Constraint('>=', $lowVersion), new Constraint('<', $highVersion));
        }
        // Hyphen Range
        //
        // Specifies an inclusive set. If a partial version is provided as the first version in the inclusive range,
        // then the missing pieces are replaced with zeroes. If a partial version is provided as the second version in
        // the inclusive range, then all versions that start with the supplied parts of the tuple are accepted, but
        // nothing that would be greater than the provided tuple parts.
        if (preg_match('{^(?P<from>' . $versionRegex . ') +- +(?P<to>' . $versionRegex . ')($)}i', $constraint, $matches)) {
            // Calculate the stability suffix
            $lowStabilitySuffix = '';
            if (empty($matches[6]) && empty($matches[8]) && empty($matches[9])) {
                $lowStabilitySuffix = '-dev';
            }
            $lowVersion = $this->normalize($matches['from']);
            $lowerBound = new Constraint('>=', $lowVersion . $lowStabilitySuffix);
            $empty = function ($x) {
                return $x === 0 || $x === '0' ? \false : empty($x);
            };
            if (!$empty($matches[12]) && !$empty($matches[13]) || !empty($matches[15]) || !empty($matches[17]) || !empty($matches[18])) {
                $highVersion = $this->normalize($matches['to']);
                $upperBound = new Constraint('<=', $highVersion);
            } else {
                $highMatch = array('', $matches[11], $matches[12], $matches[13], $matches[14]);
                // validate to version
                $this->normalize($matches['to']);
                $highVersion = $this->manipulateVersionString($highMatch, $empty($matches[12]) ? 1 : 2, 1) . '-dev';
                $upperBound = new Constraint('<', $highVersion);
            }
            return array($lowerBound, $upperBound);
        }
        // Basic Comparators
        if (preg_match('{^(<>|!=|>=?|<=?|==?)?\s*(.*)}', $constraint, $matches)) {
            try {
                try {
                    $version = $this->normalize($matches[2]);
                } catch (\UnexpectedValueException $e) {
                    // recover from an invalid constraint like foobar-dev which should be dev-foobar
                    // except if the constraint uses a known operator, in which case it must be a parse error
                    if (substr($matches[2], -4) === '-dev' && preg_match('{^[0-9a-zA-Z-./]+$}', $matches[2])) {
                        $version = $this->normalize('dev-' . substr($matches[2], 0, -4));
                    } else {
                        throw $e;
                    }
                }
                $op = $matches[1] ?: '=';
                if ($op !== '==' && $op !== '=' && !empty($stabilityModifier) && self::parseStability($version) === 'stable') {
                    $version .= '-' . $stabilityModifier;
                } elseif ('<' === $op || '>=' === $op) {
                    if (!preg_match('/-' . self::$modifierRegex . '$/', strtolower($matches[2]))) {
                        if (strpos($matches[2], 'dev-') !== 0) {
                            $version .= '-dev';
                        }
                    }
                }
                return array(new Constraint($matches[1] ?: '=', $version));
            } catch (\Exception $e) {
            }
        }
        $message = 'Could not parse version constraint ' . $constraint;
        if (isset($e)) {
            $message .= ': ' . $e->getMessage();
        }
        throw new \UnexpectedValueException($message);
    }
    /**
     * Increment, decrement, or simply pad a version number.
     *
     * Support function for {@link parseConstraint()}
     *
     * @param array  $matches   Array with version parts in array indexes 1,2,3,4
     * @param int    $position  1,2,3,4 - which segment of the version to increment/decrement
     * @param int    $increment
     * @param string $pad       The string to pad version parts after $position
     *
     * @return string|null The new version
     *
     * @phpstan-param string[] $matches
     */
    private function manipulateVersionString(array $matches, $position, $increment = 0, $pad = '0')
    {
        for ($i = 4; $i > 0; --$i) {
            if ($i > $position) {
                $matches[$i] = $pad;
            } elseif ($i === $position && $increment) {
                $matches[$i] += $increment;
                // If $matches[$i] was 0, carry the decrement
                if ($matches[$i] < 0) {
                    $matches[$i] = $pad;
                    --$position;
                    // Return null on a carry overflow
                    if ($i === 1) {
                        return null;
                    }
                }
            }
        }
        return $matches[1] . '.' . $matches[2] . '.' . $matches[3] . '.' . $matches[4];
    }
    /**
     * Expand shorthand stability string to long version.
     *
     * @param string $stability
     *
     * @return string
     */
    private function expandStability($stability)
    {
        $stability = strtolower($stability);
        switch ($stability) {
            case 'a':
                return 'alpha';
            case 'b':
                return 'beta';
            case 'p':
            case 'pl':
                return 'patch';
            case 'rc':
                return 'RC';
            default:
                return $stability;
        }
    }
}
<?php

/*
 * This file is part of composer/semver.
 *
 * (c) Composer <https://github.com/composer>
 *
 * For the full copyright and license information, please view
 * the LICENSE file that was distributed with this source code.
 */
namespace Composer\Semver\Constraint;

/**
 * DO NOT IMPLEMENT this interface. It is only meant for usage as a type hint
 * in libraries relying on composer/semver but creating your own constraint class
 * that implements this interface is not a supported use case and will cause the
 * composer/semver components to return unexpected results.
 */
interface ConstraintInterface
{
    /**
     * Checks whether the given constraint intersects in any way with this constraint
     *
     * @param ConstraintInterface $provider
     *
     * @return bool
     */
    public function matches(\Composer\Semver\Constraint\ConstraintInterface $provider);
    /**
     * Provides a compiled version of the constraint for the given operator
     * The compiled version must be a PHP expression.
     * Executor of compile version must provide 2 variables:
     * - $v = the string version to compare with
     * - $b = whether or not the version is a non-comparable branch (starts with "dev-")
     *
     * @see Constraint::OP_* for the list of available operators.
     * @example return '!$b && version_compare($v, '1.0', '>')';
     *
     * @param int $otherOperator one Constraint::OP_*
     *
     * @return string
     *
     * @phpstan-param Constraint::OP_* $otherOperator
     */
    public function compile($otherOperator);
    /**
     * @return Bound
     */
    public function getUpperBound();
    /**
     * @return Bound
     */
    public function getLowerBound();
    /**
     * @return string
     */
    public function getPrettyString();
    /**
     * @param string|null $prettyString
     *
     * @return void
     */
    public function setPrettyString($prettyString);
    /**
     * @return string
     */
    public function __toString();
}
<?php

/*
 * This file is part of composer/semver.
 *
 * (c) Composer <https://github.com/composer>
 *
 * For the full copyright and license information, please view
 * the LICENSE file that was distributed with this source code.
 */
namespace Composer\Semver\Constraint;

/**
 * Defines a conjunctive or disjunctive set of constraints.
 */
class MultiConstraint implements \Composer\Semver\Constraint\ConstraintInterface
{
    /**
     * @var ConstraintInterface[]
     * @phpstan-var non-empty-array<ConstraintInterface>
     */
    protected $constraints;
    /** @var string|null */
    protected $prettyString;
    /** @var string|null */
    protected $string;
    /** @var bool */
    protected $conjunctive;
    /** @var Bound|null */
    protected $lowerBound;
    /** @var Bound|null */
    protected $upperBound;
    /**
     * @param ConstraintInterface[] $constraints A set of constraints
     * @param bool                  $conjunctive Whether the constraints should be treated as conjunctive or disjunctive
     *
     * @throws \InvalidArgumentException If less than 2 constraints are passed
     */
    public function __construct(array $constraints, $conjunctive = \true)
    {
        if (\count($constraints) < 2) {
            throw new \InvalidArgumentException('Must provide at least two constraints for a MultiConstraint. Use ' . 'the regular Constraint class for one constraint only or MatchAllConstraint for none. You may use ' . 'MultiConstraint::create() which optimizes and handles those cases automatically.');
        }
        $this->constraints = $constraints;
        $this->conjunctive = $conjunctive;
    }
    /**
     * @return ConstraintInterface[]
     */
    public function getConstraints()
    {
        return $this->constraints;
    }
    /**
     * @return bool
     */
    public function isConjunctive()
    {
        return $this->conjunctive;
    }
    /**
     * @return bool
     */
    public function isDisjunctive()
    {
        return !$this->conjunctive;
    }
    /**
     * {@inheritDoc}
     */
    public function compile($otherOperator)
    {
        $parts = array();
        foreach ($this->constraints as $constraint) {
            $code = $constraint->compile($otherOperator);
            if ($code === 'true') {
                if (!$this->conjunctive) {
                    return 'true';
                }
            } elseif ($code === 'false') {
                if ($this->conjunctive) {
                    return 'false';
                }
            } else {
                $parts[] = '(' . $code . ')';
            }
        }
        if (!$parts) {
            return $this->conjunctive ? 'true' : 'false';
        }
        return $this->conjunctive ? implode('&&', $parts) : implode('||', $parts);
    }
    /**
     * @param ConstraintInterface $provider
     *
     * @return bool
     */
    public function matches(\Composer\Semver\Constraint\ConstraintInterface $provider)
    {
        if (\false === $this->conjunctive) {
            foreach ($this->constraints as $constraint) {
                if ($provider->matches($constraint)) {
                    return \true;
                }
            }
            return \false;
        }
        // when matching a conjunctive and a disjunctive multi constraint we have to iterate over the disjunctive one
        // otherwise we'd return true if different parts of the disjunctive constraint match the conjunctive one
        // which would lead to incorrect results, e.g. [>1 and <2] would match [<1 or >2] although they do not intersect
        if ($provider instanceof \Composer\Semver\Constraint\MultiConstraint && $provider->isDisjunctive()) {
            return $provider->matches($this);
        }
        foreach ($this->constraints as $constraint) {
            if (!$provider->matches($constraint)) {
                return \false;
            }
        }
        return \true;
    }
    /**
     * {@inheritDoc}
     */
    public function setPrettyString($prettyString)
    {
        $this->prettyString = $prettyString;
    }
    /**
     * {@inheritDoc}
     */
    public function getPrettyString()
    {
        if ($this->prettyString) {
            return $this->prettyString;
        }
        return (string) $this;
    }
    /**
     * {@inheritDoc}
     */
    public function __toString()
    {
        if ($this->string !== null) {
            return $this->string;
        }
        $constraints = array();
        foreach ($this->constraints as $constraint) {
            $constraints[] = (string) $constraint;
        }
        return $this->string = '[' . implode($this->conjunctive ? ' ' : ' || ', $constraints) . ']';
    }
    /**
     * {@inheritDoc}
     */
    public function getLowerBound()
    {
        $this->extractBounds();
        if (null === $this->lowerBound) {
            throw new \LogicException('extractBounds should have populated the lowerBound property');
        }
        return $this->lowerBound;
    }
    /**
     * {@inheritDoc}
     */
    public function getUpperBound()
    {
        $this->extractBounds();
        if (null === $this->upperBound) {
            throw new \LogicException('extractBounds should have populated the upperBound property');
        }
        return $this->upperBound;
    }
    /**
     * Tries to optimize the constraints as much as possible, meaning
     * reducing/collapsing congruent constraints etc.
     * Does not necessarily return a MultiConstraint instance if
     * things can be reduced to a simple constraint
     *
     * @param ConstraintInterface[] $constraints A set of constraints
     * @param bool                  $conjunctive Whether the constraints should be treated as conjunctive or disjunctive
     *
     * @return ConstraintInterface
     */
    public static function create(array $constraints, $conjunctive = \true)
    {
        if (0 === \count($constraints)) {
            return new \Composer\Semver\Constraint\MatchAllConstraint();
        }
        if (1 === \count($constraints)) {
            return $constraints[0];
        }
        $optimized = self::optimizeConstraints($constraints, $conjunctive);
        if ($optimized !== null) {
            list($constraints, $conjunctive) = $optimized;
            if (\count($constraints) === 1) {
                return $constraints[0];
            }
        }
        return new self($constraints, $conjunctive);
    }
    /**
     * @param  ConstraintInterface[] $constraints
     * @param  bool                  $conjunctive
     * @return ?array
     *
     * @phpstan-return array{0: list<ConstraintInterface>, 1: bool}|null
     */
    private static function optimizeConstraints(array $constraints, $conjunctive)
    {
        // parse the two OR groups and if they are contiguous we collapse
        // them into one constraint
        // [>= 1 < 2] || [>= 2 < 3] || [>= 3 < 4] => [>= 1 < 4]
        if (!$conjunctive) {
            $left = $constraints[0];
            $mergedConstraints = array();
            $optimized = \false;
            for ($i = 1, $l = \count($constraints); $i < $l; $i++) {
                $right = $constraints[$i];
                if ($left instanceof self && $left->conjunctive && $right instanceof self && $right->conjunctive && \count($left->constraints) === 2 && \count($right->constraints) === 2 && ($left0 = (string) $left->constraints[0]) && $left0[0] === '>' && $left0[1] === '=' && ($left1 = (string) $left->constraints[1]) && $left1[0] === '<' && ($right0 = (string) $right->constraints[0]) && $right0[0] === '>' && $right0[1] === '=' && ($right1 = (string) $right->constraints[1]) && $right1[0] === '<' && substr($left1, 2) === substr($right0, 3)) {
                    $optimized = \true;
                    $left = new \Composer\Semver\Constraint\MultiConstraint(array($left->constraints[0], $right->constraints[1]), \true);
                } else {
                    $mergedConstraints[] = $left;
                    $left = $right;
                }
            }
            if ($optimized) {
                $mergedConstraints[] = $left;
                return array($mergedConstraints, \false);
            }
        }
        // TODO: Here's the place to put more optimizations
        return null;
    }
    /**
     * @return void
     */
    private function extractBounds()
    {
        if (null !== $this->lowerBound) {
            return;
        }
        foreach ($this->constraints as $constraint) {
            if (null === $this->lowerBound || null === $this->upperBound) {
                $this->lowerBound = $constraint->getLowerBound();
                $this->upperBound = $constraint->getUpperBound();
                continue;
            }
            if ($constraint->getLowerBound()->compareTo($this->lowerBound, $this->isConjunctive() ? '>' : '<')) {
                $this->lowerBound = $constraint->getLowerBound();
            }
            if ($constraint->getUpperBound()->compareTo($this->upperBound, $this->isConjunctive() ? '<' : '>')) {
                $this->upperBound = $constraint->getUpperBound();
            }
        }
    }
}
<?php

/*
 * This file is part of composer/semver.
 *
 * (c) Composer <https://github.com/composer>
 *
 * For the full copyright and license information, please view
 * the LICENSE file that was distributed with this source code.
 */
namespace Composer\Semver\Constraint;

/**
 * Defines a constraint.
 */
class Constraint implements \Composer\Semver\Constraint\ConstraintInterface
{
    /* operator integer values */
    const OP_EQ = 0;
    const OP_LT = 1;
    const OP_LE = 2;
    const OP_GT = 3;
    const OP_GE = 4;
    const OP_NE = 5;
    /* operator string values */
    const STR_OP_EQ = '==';
    const STR_OP_EQ_ALT = '=';
    const STR_OP_LT = '<';
    const STR_OP_LE = '<=';
    const STR_OP_GT = '>';
    const STR_OP_GE = '>=';
    const STR_OP_NE = '!=';
    const STR_OP_NE_ALT = '<>';
    /**
     * Operator to integer translation table.
     *
     * @var array
     * @phpstan-var array<self::STR_OP_*, self::OP_*>
     */
    private static $transOpStr = array('=' => self::OP_EQ, '==' => self::OP_EQ, '<' => self::OP_LT, '<=' => self::OP_LE, '>' => self::OP_GT, '>=' => self::OP_GE, '<>' => self::OP_NE, '!=' => self::OP_NE);
    /**
     * Integer to operator translation table.
     *
     * @var array
     * @phpstan-var array<self::OP_*, self::STR_OP_*>
     */
    private static $transOpInt = array(self::OP_EQ => '==', self::OP_LT => '<', self::OP_LE => '<=', self::OP_GT => '>', self::OP_GE => '>=', self::OP_NE => '!=');
    /**
     * @var int
     * @phpstan-var self::OP_*
     */
    protected $operator;
    /** @var string */
    protected $version;
    /** @var string|null */
    protected $prettyString;
    /** @var Bound */
    protected $lowerBound;
    /** @var Bound */
    protected $upperBound;
    /**
     * Sets operator and version to compare with.
     *
     * @param string $operator
     * @param string $version
     *
     * @throws \InvalidArgumentException if invalid operator is given.
     *
     * @phpstan-param self::STR_OP_* $operator
     */
    public function __construct($operator, $version)
    {
        if (!isset(self::$transOpStr[$operator])) {
            throw new \InvalidArgumentException(sprintf('Invalid operator "%s" given, expected one of: %s', $operator, implode(', ', self::getSupportedOperators())));
        }
        $this->operator = self::$transOpStr[$operator];
        $this->version = $version;
    }
    /**
     * @return string
     */
    public function getVersion()
    {
        return $this->version;
    }
    /**
     * @return string
     *
     * @phpstan-return self::STR_OP_*
     */
    public function getOperator()
    {
        return self::$transOpInt[$this->operator];
    }
    /**
     * @param ConstraintInterface $provider
     *
     * @return bool
     */
    public function matches(\Composer\Semver\Constraint\ConstraintInterface $provider)
    {
        if ($provider instanceof self) {
            return $this->matchSpecific($provider);
        }
        // turn matching around to find a match
        return $provider->matches($this);
    }
    /**
     * {@inheritDoc}
     */
    public function setPrettyString($prettyString)
    {
        $this->prettyString = $prettyString;
    }
    /**
     * {@inheritDoc}
     */
    public function getPrettyString()
    {
        if ($this->prettyString) {
            return $this->prettyString;
        }
        return $this->__toString();
    }
    /**
     * Get all supported comparison operators.
     *
     * @return array
     *
     * @phpstan-return list<self::STR_OP_*>
     */
    public static function getSupportedOperators()
    {
        return array_keys(self::$transOpStr);
    }
    /**
     * @param  string $operator
     * @return int
     *
     * @phpstan-param  self::STR_OP_* $operator
     * @phpstan-return self::OP_*
     */
    public static function getOperatorConstant($operator)
    {
        return self::$transOpStr[$operator];
    }
    /**
     * @param string $a
     * @param string $b
     * @param string $operator
     * @param bool   $compareBranches
     *
     * @throws \InvalidArgumentException if invalid operator is given.
     *
     * @return bool
     *
     * @phpstan-param self::STR_OP_* $operator
     */
    public function versionCompare($a, $b, $operator, $compareBranches = \false)
    {
        if (!isset(self::$transOpStr[$operator])) {
            throw new \InvalidArgumentException(sprintf('Invalid operator "%s" given, expected one of: %s', $operator, implode(', ', self::getSupportedOperators())));
        }
        $aIsBranch = strpos($a, 'dev-') === 0;
        $bIsBranch = strpos($b, 'dev-') === 0;
        if ($operator === '!=' && ($aIsBranch || $bIsBranch)) {
            return $a !== $b;
        }
        if ($aIsBranch && $bIsBranch) {
            return $operator === '==' && $a === $b;
        }
        // when branches are not comparable, we make sure dev branches never match anything
        if (!$compareBranches && ($aIsBranch || $bIsBranch)) {
            return \false;
        }
        return \version_compare($a, $b, $operator);
    }
    /**
     * {@inheritDoc}
     */
    public function compile($otherOperator)
    {
        if (strpos($this->version, 'dev-') === 0) {
            if (self::OP_EQ === $this->operator) {
                if (self::OP_EQ === $otherOperator) {
                    return sprintf('$b && $v === %s', \var_export($this->version, \true));
                }
                if (self::OP_NE === $otherOperator) {
                    return sprintf('!$b || $v !== %s', \var_export($this->version, \true));
                }
                return 'false';
            }
            if (self::OP_NE === $this->operator) {
                if (self::OP_EQ === $otherOperator) {
                    return sprintf('!$b || $v !== %s', \var_export($this->version, \true));
                }
                if (self::OP_NE === $otherOperator) {
                    return 'true';
                }
                return '!$b';
            }
            return 'false';
        }
        if (self::OP_EQ === $this->operator) {
            if (self::OP_EQ === $otherOperator) {
                return sprintf('\version_compare($v, %s, \'==\')', \var_export($this->version, \true));
            }
            if (self::OP_NE === $otherOperator) {
                return sprintf('$b || \version_compare($v, %s, \'!=\')', \var_export($this->version, \true));
            }
            return sprintf('!$b && \version_compare(%s, $v, \'%s\')', \var_export($this->version, \true), self::$transOpInt[$otherOperator]);
        }
        if (self::OP_NE === $this->operator) {
            if (self::OP_EQ === $otherOperator) {
                return sprintf('$b || (!$b && \version_compare($v, %s, \'!=\'))', \var_export($this->version, \true));
            }
            if (self::OP_NE === $otherOperator) {
                return 'true';
            }
            return '!$b';
        }
        if (self::OP_LT === $this->operator || self::OP_LE === $this->operator) {
            if (self::OP_LT === $otherOperator || self::OP_LE === $otherOperator) {
                return '!$b';
            }
        } else if (self::OP_GT === $otherOperator || self::OP_GE === $otherOperator) {
            return '!$b';
        }
        if (self::OP_NE === $otherOperator) {
            return 'true';
        }
        $codeComparison = sprintf('\version_compare($v, %s, \'%s\')', \var_export($this->version, \true), self::$transOpInt[$this->operator]);
        if ($this->operator === self::OP_LE) {
            if ($otherOperator === self::OP_GT) {
                return sprintf('!$b && \version_compare($v, %s, \'!=\') && ', \var_export($this->version, \true)) . $codeComparison;
            }
        } elseif ($this->operator === self::OP_GE) {
            if ($otherOperator === self::OP_LT) {
                return sprintf('!$b && \version_compare($v, %s, \'!=\') && ', \var_export($this->version, \true)) . $codeComparison;
            }
        }
        return sprintf('!$b && %s', $codeComparison);
    }
    /**
     * @param Constraint $provider
     * @param bool       $compareBranches
     *
     * @return bool
     */
    public function matchSpecific(\Composer\Semver\Constraint\Constraint $provider, $compareBranches = \false)
    {
        $noEqualOp = str_replace('=', '', self::$transOpInt[$this->operator]);
        $providerNoEqualOp = str_replace('=', '', self::$transOpInt[$provider->operator]);
        $isEqualOp = self::OP_EQ === $this->operator;
        $isNonEqualOp = self::OP_NE === $this->operator;
        $isProviderEqualOp = self::OP_EQ === $provider->operator;
        $isProviderNonEqualOp = self::OP_NE === $provider->operator;
        // '!=' operator is match when other operator is not '==' operator or version is not match
        // these kinds of comparisons always have a solution
        if ($isNonEqualOp || $isProviderNonEqualOp) {
            if ($isNonEqualOp && !$isProviderNonEqualOp && !$isProviderEqualOp && strpos($provider->version, 'dev-') === 0) {
                return \false;
            }
            if ($isProviderNonEqualOp && !$isNonEqualOp && !$isEqualOp && strpos($this->version, 'dev-') === 0) {
                return \false;
            }
            if (!$isEqualOp && !$isProviderEqualOp) {
                return \true;
            }
            return $this->versionCompare($provider->version, $this->version, '!=', $compareBranches);
        }
        // an example for the condition is <= 2.0 & < 1.0
        // these kinds of comparisons always have a solution
        if ($this->operator !== self::OP_EQ && $noEqualOp === $providerNoEqualOp) {
            return !(strpos($this->version, 'dev-') === 0 || strpos($provider->version, 'dev-') === 0);
        }
        $version1 = $isEqualOp ? $this->version : $provider->version;
        $version2 = $isEqualOp ? $provider->version : $this->version;
        $operator = $isEqualOp ? $provider->operator : $this->operator;
        if ($this->versionCompare($version1, $version2, self::$transOpInt[$operator], $compareBranches)) {
            // special case, e.g. require >= 1.0 and provide < 1.0
            // 1.0 >= 1.0 but 1.0 is outside of the provided interval
            return !(self::$transOpInt[$provider->operator] === $providerNoEqualOp && self::$transOpInt[$this->operator] !== $noEqualOp && \version_compare($provider->version, $this->version, '=='));
        }
        return \false;
    }
    /**
     * @return string
     */
    public function __toString()
    {
        return self::$transOpInt[$this->operator] . ' ' . $this->version;
    }
    /**
     * {@inheritDoc}
     */
    public function getLowerBound()
    {
        $this->extractBounds();
        return $this->lowerBound;
    }
    /**
     * {@inheritDoc}
     */
    public function getUpperBound()
    {
        $this->extractBounds();
        return $this->upperBound;
    }
    /**
     * @return void
     */
    private function extractBounds()
    {
        if (null !== $this->lowerBound) {
            return;
        }
        // Branches
        if (strpos($this->version, 'dev-') === 0) {
            $this->lowerBound = \Composer\Semver\Constraint\Bound::zero();
            $this->upperBound = \Composer\Semver\Constraint\Bound::positiveInfinity();
            return;
        }
        switch ($this->operator) {
            case self::OP_EQ:
                $this->lowerBound = new \Composer\Semver\Constraint\Bound($this->version, \true);
                $this->upperBound = new \Composer\Semver\Constraint\Bound($this->version, \true);
                break;
            case self::OP_LT:
                $this->lowerBound = \Composer\Semver\Constraint\Bound::zero();
                $this->upperBound = new \Composer\Semver\Constraint\Bound($this->version, \false);
                break;
            case self::OP_LE:
                $this->lowerBound = \Composer\Semver\Constraint\Bound::zero();
                $this->upperBound = new \Composer\Semver\Constraint\Bound($this->version, \true);
                break;
            case self::OP_GT:
                $this->lowerBound = new \Composer\Semver\Constraint\Bound($this->version, \false);
                $this->upperBound = \Composer\Semver\Constraint\Bound::positiveInfinity();
                break;
            case self::OP_GE:
                $this->lowerBound = new \Composer\Semver\Constraint\Bound($this->version, \true);
                $this->upperBound = \Composer\Semver\Constraint\Bound::positiveInfinity();
                break;
            case self::OP_NE:
                $this->lowerBound = \Composer\Semver\Constraint\Bound::zero();
                $this->upperBound = \Composer\Semver\Constraint\Bound::positiveInfinity();
                break;
        }
    }
}
<?php

/*
 * This file is part of composer/semver.
 *
 * (c) Composer <https://github.com/composer>
 *
 * For the full copyright and license information, please view
 * the LICENSE file that was distributed with this source code.
 */
namespace Composer\Semver\Constraint;

/**
 * Defines the absence of a constraint.
 *
 * This constraint matches everything.
 */
class MatchAllConstraint implements \Composer\Semver\Constraint\ConstraintInterface
{
    /** @var string|null */
    protected $prettyString;
    /**
     * @param ConstraintInterface $provider
     *
     * @return bool
     */
    public function matches(\Composer\Semver\Constraint\ConstraintInterface $provider)
    {
        return \true;
    }
    /**
     * {@inheritDoc}
     */
    public function compile($otherOperator)
    {
        return 'true';
    }
    /**
     * {@inheritDoc}
     */
    public function setPrettyString($prettyString)
    {
        $this->prettyString = $prettyString;
    }
    /**
     * {@inheritDoc}
     */
    public function getPrettyString()
    {
        if ($this->prettyString) {
            return $this->prettyString;
        }
        return (string) $this;
    }
    /**
     * {@inheritDoc}
     */
    public function __toString()
    {
        return '*';
    }
    /**
     * {@inheritDoc}
     */
    public function getUpperBound()
    {
        return \Composer\Semver\Constraint\Bound::positiveInfinity();
    }
    /**
     * {@inheritDoc}
     */
    public function getLowerBound()
    {
        return \Composer\Semver\Constraint\Bound::zero();
    }
}
<?php

/*
 * This file is part of composer/semver.
 *
 * (c) Composer <https://github.com/composer>
 *
 * For the full copyright and license information, please view
 * the LICENSE file that was distributed with this source code.
 */
namespace Composer\Semver\Constraint;

/**
 * Blackhole of constraints, nothing escapes it
 */
class MatchNoneConstraint implements \Composer\Semver\Constraint\ConstraintInterface
{
    /** @var string|null */
    protected $prettyString;
    /**
     * @param ConstraintInterface $provider
     *
     * @return bool
     */
    public function matches(\Composer\Semver\Constraint\ConstraintInterface $provider)
    {
        return \false;
    }
    /**
     * {@inheritDoc}
     */
    public function compile($otherOperator)
    {
        return 'false';
    }
    /**
     * {@inheritDoc}
     */
    public function setPrettyString($prettyString)
    {
        $this->prettyString = $prettyString;
    }
    /**
     * {@inheritDoc}
     */
    public function getPrettyString()
    {
        if ($this->prettyString) {
            return $this->prettyString;
        }
        return (string) $this;
    }
    /**
     * {@inheritDoc}
     */
    public function __toString()
    {
        return '[]';
    }
    /**
     * {@inheritDoc}
     */
    public function getUpperBound()
    {
        return new \Composer\Semver\Constraint\Bound('0.0.0.0-dev', \false);
    }
    /**
     * {@inheritDoc}
     */
    public function getLowerBound()
    {
        return new \Composer\Semver\Constraint\Bound('0.0.0.0-dev', \false);
    }
}
<?php

/*
 * This file is part of composer/semver.
 *
 * (c) Composer <https://github.com/composer>
 *
 * For the full copyright and license information, please view
 * the LICENSE file that was distributed with this source code.
 */
namespace Composer\Semver\Constraint;

class Bound
{
    /**
     * @var string
     */
    private $version;
    /**
     * @var bool
     */
    private $isInclusive;
    /**
     * @param string $version
     * @param bool   $isInclusive
     */
    public function __construct($version, $isInclusive)
    {
        $this->version = $version;
        $this->isInclusive = $isInclusive;
    }
    /**
     * @return string
     */
    public function getVersion()
    {
        return $this->version;
    }
    /**
     * @return bool
     */
    public function isInclusive()
    {
        return $this->isInclusive;
    }
    /**
     * @return bool
     */
    public function isZero()
    {
        return $this->getVersion() === '0.0.0.0-dev' && $this->isInclusive();
    }
    /**
     * @return bool
     */
    public function isPositiveInfinity()
    {
        return $this->getVersion() === \PHP_INT_MAX . '.0.0.0' && !$this->isInclusive();
    }
    /**
     * Compares a bound to another with a given operator.
     *
     * @param Bound  $other
     * @param string $operator
     *
     * @return bool
     */
    public function compareTo(\Composer\Semver\Constraint\Bound $other, $operator)
    {
        if (!\in_array($operator, array('<', '>'), \true)) {
            throw new \InvalidArgumentException('Does not support any other operator other than > or <.');
        }
        // If they are the same it doesn't matter
        if ($this == $other) {
            return \false;
        }
        $compareResult = version_compare($this->getVersion(), $other->getVersion());
        // Not the same version means we don't need to check if the bounds are inclusive or not
        if (0 !== $compareResult) {
            return ('>' === $operator ? 1 : -1) === $compareResult;
        }
        // Question we're answering here is "am I higher than $other?"
        return '>' === $operator ? $other->isInclusive() : !$other->isInclusive();
    }
    public function __toString()
    {
        return sprintf('%s [%s]', $this->getVersion(), $this->isInclusive() ? 'inclusive' : 'exclusive');
    }
    /**
     * @return self
     */
    public static function zero()
    {
        return new \Composer\Semver\Constraint\Bound('0.0.0.0-dev', \true);
    }
    /**
     * @return self
     */
    public static function positiveInfinity()
    {
        return new \Composer\Semver\Constraint\Bound(\PHP_INT_MAX . '.0.0.0', \false);
    }
}
<?php

// autoload_files.php @generated by Composer

$vendorDir = dirname(__DIR__);
$baseDir = dirname($vendorDir);

return array(
    '6e3fae29631ef280660b3cdad06f25a8' => $vendorDir . '/symfony/deprecation-contracts/function.php',
    '0e6d7bf4a5811bfa5cf40c5ccd6fae6a' => $vendorDir . '/symfony/polyfill-mbstring/bootstrap.php',
    '320cde22f66dd4f5d3fd621d3e88b98f' => $vendorDir . '/symfony/polyfill-ctype/bootstrap.php',
    '662a729f963d39afe703c9d9b7ab4a8c' => $vendorDir . '/symfony/polyfill-php83/bootstrap.php',
    '667aeda72477189d0494fecd327c3641' => $vendorDir . '/symfony/var-dumper/Resources/functions/dump.php',
    '8825ede83f2f289127722d4e842cf7e8' => $vendorDir . '/symfony/polyfill-intl-grapheme/bootstrap.php',
    'e69f7f6ee287b969198c3c9d6777bd38' => $vendorDir . '/symfony/polyfill-intl-normalizer/bootstrap.php',
    'b6b991a57620e2fb6b2f66f03fe9ddc2' => $vendorDir . '/symfony/string/Resources/functions.php',
    '9d2b9fc6db0f153a0a149fefb182415e' => $vendorDir . '/symfony/polyfill-php84/bootstrap.php',
    'ad155f8f1cf0d418fe49e248db8c661b' => $vendorDir . '/react/promise/src/functions_include.php',
    '0d59ee240a4cd96ddbb4ff164fccea4d' => $vendorDir . '/symfony/polyfill-php73/bootstrap.php',
    'a4a119a56e50fbb293281d9a48007e0e' => $vendorDir . '/symfony/polyfill-php80/bootstrap.php',
    '23c18046f52bef3eea034657bafda50f' => $vendorDir . '/symfony/polyfill-php81/bootstrap.php',
    '09f6b20656683369174dd6fa83b7e5fb' => $vendorDir . '/symfony/polyfill-uuid/bootstrap.php',
    '2203a247e6fda86070a5e4e07aed533a' => $vendorDir . '/symfony/clock/Resources/now.php',
    'e39a8b23c42d4e1452234d762b03835a' => $vendorDir . '/ramsey/uuid/src/functions.php',
);
<?php

/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer;

use Composer\Autoload\ClassLoader;
use Composer\Semver\VersionParser;
/**
 * This class is copied in every Composer installed project and available to all
 *
 * See also https://getcomposer.org/doc/07-runtime.md#installed-versions
 *
 * To require its presence, you can require `composer-runtime-api ^2.0`
 *
 * @final
 */
class InstalledVersions
{
    /**
     * @var string|null if set (by reflection by Composer), this should be set to the path where this class is being copied to
     * @internal
     */
    private static $selfDir = null;
    /**
     * @var mixed[]|null
     * @psalm-var array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>}|array{}|null
     */
    private static $installed;
    /**
     * @var bool
     */
    private static $installedIsLocalDir;
    /**
     * @var bool|null
     */
    private static $canGetVendors;
    /**
     * @var array[]
     * @psalm-var array<string, array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>}>
     */
    private static $installedByVendor = array();
    /**
     * Returns a list of all package names which are present, either by being installed, replaced or provided
     *
     * @return string[]
     * @psalm-return list<string>
     */
    public static function getInstalledPackages()
    {
        $packages = array();
        foreach (self::getInstalled() as $installed) {
            $packages[] = array_keys($installed['versions']);
        }
        if (1 === \count($packages)) {
            return $packages[0];
        }
        return array_keys(array_flip(\call_user_func_array('array_merge', $packages)));
    }
    /**
     * Returns a list of all package names with a specific type e.g. 'library'
     *
     * @param  string   $type
     * @return string[]
     * @psalm-return list<string>
     */
    public static function getInstalledPackagesByType($type)
    {
        $packagesByType = array();
        foreach (self::getInstalled() as $installed) {
            foreach ($installed['versions'] as $name => $package) {
                if (isset($package['type']) && $package['type'] === $type) {
                    $packagesByType[] = $name;
                }
            }
        }
        return $packagesByType;
    }
    /**
     * Checks whether the given package is installed
     *
     * This also returns true if the package name is provided or replaced by another package
     *
     * @param  string $packageName
     * @param  bool   $includeDevRequirements
     * @return bool
     */
    public static function isInstalled($packageName, $includeDevRequirements = \true)
    {
        foreach (self::getInstalled() as $installed) {
            if (isset($installed['versions'][$packageName])) {
                return $includeDevRequirements || !isset($installed['versions'][$packageName]['dev_requirement']) || $installed['versions'][$packageName]['dev_requirement'] === \false;
            }
        }
        return \false;
    }
    /**
     * Checks whether the given package satisfies a version constraint
     *
     * e.g. If you want to know whether version 2.3+ of package foo/bar is installed, you would call:
     *
     *   Composer\InstalledVersions::satisfies(new VersionParser, 'foo/bar', '^2.3')
     *
     * @param  VersionParser $parser      Install composer/semver to have access to this class and functionality
     * @param  string        $packageName
     * @param  string|null   $constraint  A version constraint to check for, if you pass one you have to make sure composer/semver is required by your package
     * @return bool
     */
    public static function satisfies(VersionParser $parser, $packageName, $constraint)
    {
        $constraint = $parser->parseConstraints((string) $constraint);
        $provided = $parser->parseConstraints(self::getVersionRanges($packageName));
        return $provided->matches($constraint);
    }
    /**
     * Returns a version constraint representing all the range(s) which are installed for a given package
     *
     * It is easier to use this via isInstalled() with the $constraint argument if you need to check
     * whether a given version of a package is installed, and not just whether it exists
     *
     * @param  string $packageName
     * @return string Version constraint usable with composer/semver
     */
    public static function getVersionRanges($packageName)
    {
        foreach (self::getInstalled() as $installed) {
            if (!isset($installed['versions'][$packageName])) {
                continue;
            }
            $ranges = array();
            if (isset($installed['versions'][$packageName]['pretty_version'])) {
                $ranges[] = $installed['versions'][$packageName]['pretty_version'];
            }
            if (array_key_exists('aliases', $installed['versions'][$packageName])) {
                $ranges = array_merge($ranges, $installed['versions'][$packageName]['aliases']);
            }
            if (array_key_exists('replaced', $installed['versions'][$packageName])) {
                $ranges = array_merge($ranges, $installed['versions'][$packageName]['replaced']);
            }
            if (array_key_exists('provided', $installed['versions'][$packageName])) {
                $ranges = array_merge($ranges, $installed['versions'][$packageName]['provided']);
            }
            return implode(' || ', $ranges);
        }
        throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
    }
    /**
     * @param  string      $packageName
     * @return string|null If the package is being replaced or provided but is not really installed, null will be returned as version, use satisfies or getVersionRanges if you need to know if a given version is present
     */
    public static function getVersion($packageName)
    {
        foreach (self::getInstalled() as $installed) {
            if (!isset($installed['versions'][$packageName])) {
                continue;
            }
            if (!isset($installed['versions'][$packageName]['version'])) {
                return null;
            }
            return $installed['versions'][$packageName]['version'];
        }
        throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
    }
    /**
     * @param  string      $packageName
     * @return string|null If the package is being replaced or provided but is not really installed, null will be returned as version, use satisfies or getVersionRanges if you need to know if a given version is present
     */
    public static function getPrettyVersion($packageName)
    {
        foreach (self::getInstalled() as $installed) {
            if (!isset($installed['versions'][$packageName])) {
                continue;
            }
            if (!isset($installed['versions'][$packageName]['pretty_version'])) {
                return null;
            }
            return $installed['versions'][$packageName]['pretty_version'];
        }
        throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
    }
    /**
     * @param  string      $packageName
     * @return string|null If the package is being replaced or provided but is not really installed, null will be returned as reference
     */
    public static function getReference($packageName)
    {
        foreach (self::getInstalled() as $installed) {
            if (!isset($installed['versions'][$packageName])) {
                continue;
            }
            if (!isset($installed['versions'][$packageName]['reference'])) {
                return null;
            }
            return $installed['versions'][$packageName]['reference'];
        }
        throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
    }
    /**
     * @param  string      $packageName
     * @return string|null If the package is being replaced or provided but is not really installed, null will be returned as install path. Packages of type metapackages also have a null install path.
     */
    public static function getInstallPath($packageName)
    {
        foreach (self::getInstalled() as $installed) {
            if (!isset($installed['versions'][$packageName])) {
                continue;
            }
            return isset($installed['versions'][$packageName]['install_path']) ? $installed['versions'][$packageName]['install_path'] : null;
        }
        throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
    }
    /**
     * @return array
     * @psalm-return array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}
     */
    public static function getRootPackage()
    {
        $installed = self::getInstalled();
        return $installed[0]['root'];
    }
    /**
     * Returns the raw installed.php data for custom implementations
     *
     * @deprecated Use getAllRawData() instead which returns all datasets for all autoloaders present in the process. getRawData only returns the first dataset loaded, which may not be what you expect.
     * @return array[]
     * @psalm-return array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>}
     */
    public static function getRawData()
    {
        @trigger_error('getRawData only returns the first dataset loaded, which may not be what you expect. Use getAllRawData() instead which returns all datasets for all autoloaders present in the process.', \E_USER_DEPRECATED);
        if (null === self::$installed) {
            // only require the installed.php file if this file is loaded from its dumped location,
            // and not from its source location in the composer/composer package, see https://github.com/composer/composer/issues/9937
            if (substr(__DIR__, -8, 1) !== 'C') {
                self::$installed = include __DIR__ . '/installed.php';
            } else {
                self::$installed = array();
            }
        }
        return self::$installed;
    }
    /**
     * Returns the raw data of all installed.php which are currently loaded for custom implementations
     *
     * @return array[]
     * @psalm-return list<array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>}>
     */
    public static function getAllRawData()
    {
        return self::getInstalled();
    }
    /**
     * Lets you reload the static array from another file
     *
     * This is only useful for complex integrations in which a project needs to use
     * this class but then also needs to execute another project's autoloader in process,
     * and wants to ensure both projects have access to their version of installed.php.
     *
     * A typical case would be PHPUnit, where it would need to make sure it reads all
     * the data it needs from this class, then call reload() with
     * `require $CWD/vendor/composer/installed.php` (or similar) as input to make sure
     * the project in which it runs can then also use this class safely, without
     * interference between PHPUnit's dependencies and the project's dependencies.
     *
     * @param  array[] $data A vendor/composer/installed.php data set
     * @return void
     *
     * @psalm-param array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>} $data
     */
    public static function reload($data)
    {
        self::$installed = $data;
        self::$installedByVendor = array();
        // when using reload, we disable the duplicate protection to ensure that self::$installed data is
        // always returned, but we cannot know whether it comes from the installed.php in __DIR__ or not,
        // so we have to assume it does not, and that may result in duplicate data being returned when listing
        // all installed packages for example
        self::$installedIsLocalDir = \false;
    }
    /**
     * @return string
     */
    private static function getSelfDir()
    {
        if (self::$selfDir === null) {
            self::$selfDir = strtr(__DIR__, '\\', '/');
        }
        return self::$selfDir;
    }
    /**
     * @return array[]
     * @psalm-return list<array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>}>
     */
    private static function getInstalled()
    {
        if (null === self::$canGetVendors) {
            self::$canGetVendors = method_exists('Composer\Autoload\ClassLoader', 'getRegisteredLoaders');
        }
        $installed = array();
        $copiedLocalDir = \false;
        if (self::$canGetVendors) {
            $selfDir = self::getSelfDir();
            foreach (ClassLoader::getRegisteredLoaders() as $vendorDir => $loader) {
                $vendorDir = strtr($vendorDir, '\\', '/');
                if (isset(self::$installedByVendor[$vendorDir])) {
                    $installed[] = self::$installedByVendor[$vendorDir];
                } elseif (is_file($vendorDir . '/composer/installed.php')) {
                    /** @var array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>} $required */
                    $required = require $vendorDir . '/composer/installed.php';
                    self::$installedByVendor[$vendorDir] = $required;
                    $installed[] = $required;
                    if (self::$installed === null && $vendorDir . '/composer' === $selfDir) {
                        self::$installed = $required;
                        self::$installedIsLocalDir = \true;
                    }
                }
                if (self::$installedIsLocalDir && $vendorDir . '/composer' === $selfDir) {
                    $copiedLocalDir = \true;
                }
            }
        }
        if (null === self::$installed) {
            // only require the installed.php file if this file is loaded from its dumped location,
            // and not from its source location in the composer/composer package, see https://github.com/composer/composer/issues/9937
            if (substr(__DIR__, -8, 1) !== 'C') {
                /** @var array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>} $required */
                $required = require __DIR__ . '/installed.php';
                self::$installed = $required;
            } else {
                self::$installed = array();
            }
        }
        if (self::$installed !== array() && !$copiedLocalDir) {
            $installed[] = self::$installed;
        }
        return $installed;
    }
}
<?php

namespace _ContaoManager;

return array('root' => array('name' => 'contao/contao-manager', 'pretty_version' => '1.10.13', 'version' => '1.10.13.0', 'reference' => '13a0185cc2f53ee7b895dbb21a73bc48e0fe23a2', 'type' => 'project', 'install_path' => __DIR__ . '/../../', 'aliases' => array(), 'dev' => \false), 'versions' => array('brick/math' => array('pretty_version' => '0.13.1', 'version' => '0.13.1.0', 'reference' => 'fc7ed316430118cc7836bf45faff18d5dfc8de04', 'type' => 'library', 'install_path' => __DIR__ . '/../brick/math', 'aliases' => array(), 'dev_requirement' => \false), 'composer/ca-bundle' => array('pretty_version' => '1.5.11', 'version' => '1.5.11.0', 'reference' => '68ff39175e8e94a4bb1d259407ce51a6a60f09e6', 'type' => 'library', 'install_path' => __DIR__ . '/./ca-bundle', 'aliases' => array(), 'dev_requirement' => \false), 'composer/class-map-generator' => array('pretty_version' => '1.7.2', 'version' => '1.7.2.0', 'reference' => '6a9c2f0970022ab00dc58c07d0685dd712f2231b', 'type' => 'library', 'install_path' => __DIR__ . '/./class-map-generator', 'aliases' => array(), 'dev_requirement' => \false), 'composer/composer' => array('pretty_version' => '2.9.7', 'version' => '2.9.7.0', 'reference' => '82a2fbd1372a98d7915cfb092acf05207d9b4113', 'type' => 'library', 'install_path' => __DIR__ . '/./composer', 'aliases' => array(), 'dev_requirement' => \false), 'composer/metadata-minifier' => array('pretty_version' => '1.0.0', 'version' => '1.0.0.0', 'reference' => 'c549d23829536f0d0e984aaabbf02af91f443207', 'type' => 'library', 'install_path' => __DIR__ . '/./metadata-minifier', 'aliases' => array(), 'dev_requirement' => \false), 'composer/pcre' => array('pretty_version' => '3.3.2', 'version' => '3.3.2.0', 'reference' => 'b2bed4734f0cc156ee1fe9c0da2550420d99a21e', 'type' => 'library', 'install_path' => __DIR__ . '/./pcre', 'aliases' => array(), 'dev_requirement' => \false), 'composer/semver' => array('pretty_version' => '3.4.4', 'version' => '3.4.4.0', 'reference' => '198166618906cb2de69b95d7d47e5fa8aa1b2b95', 'type' => 'library', 'install_path' => __DIR__ . '/./semver', 'aliases' => array(), 'dev_requirement' => \false), 'composer/spdx-licenses' => array('pretty_version' => '1.6.0', 'version' => '1.6.0.0', 'reference' => '5ecd0cb4177696f9fd48f1605dda81db3dee7889', 'type' => 'library', 'install_path' => __DIR__ . '/./spdx-licenses', 'aliases' => array(), 'dev_requirement' => \false), 'composer/xdebug-handler' => array('pretty_version' => '3.0.5', 'version' => '3.0.5.0', 'reference' => '6c1925561632e83d60a44492e0b344cf48ab85ef', 'type' => 'library', 'install_path' => __DIR__ . '/./xdebug-handler', 'aliases' => array(), 'dev_requirement' => \false), 'contao/contao-manager' => array('pretty_version' => '1.10.13', 'version' => '1.10.13.0', 'reference' => '13a0185cc2f53ee7b895dbb21a73bc48e0fe23a2', 'type' => 'project', 'install_path' => __DIR__ . '/../../', 'aliases' => array(), 'dev_requirement' => \false), 'crell/api-problem' => array('pretty_version' => '3.7.1', 'version' => '3.7.1.0', 'reference' => '3b52858d05736b68f08dd1e48e4235362de22831', 'type' => 'library', 'install_path' => __DIR__ . '/../crell/api-problem', 'aliases' => array(), 'dev_requirement' => \false), 'doctrine/deprecations' => array('pretty_version' => '1.1.6', 'version' => '1.1.6.0', 'reference' => 'd4fe3e6fd9bb9e72557a19674f44d8ac7db4c6ca', 'type' => 'library', 'install_path' => __DIR__ . '/../doctrine/deprecations', 'aliases' => array(), 'dev_requirement' => \false), 'firebase/php-jwt' => array('pretty_version' => 'v7.0.5', 'version' => '7.0.5.0', 'reference' => '47ad26bab5e7c70ae8a6f08ed25ff83631121380', 'type' => 'library', 'install_path' => __DIR__ . '/../firebase/php-jwt', 'aliases' => array(), 'dev_requirement' => \false), 'justinrainbow/json-schema' => array('pretty_version' => '6.8.0', 'version' => '6.8.0.0', 'reference' => '89ac92bcfe5d0a8a4433c7b89d394553ae7250cc', 'type' => 'library', 'install_path' => __DIR__ . '/../justinrainbow/json-schema', 'aliases' => array(), 'dev_requirement' => \false), 'lcobucci/clock' => array('pretty_version' => '3.0.0', 'version' => '3.0.0.0', 'reference' => '039ef98c6b57b101d10bd11d8fdfda12cbd996dc', 'type' => 'library', 'install_path' => __DIR__ . '/../lcobucci/clock', 'aliases' => array(), 'dev_requirement' => \false), 'marc-mabe/php-enum' => array('pretty_version' => 'v4.7.2', 'version' => '4.7.2.0', 'reference' => 'bb426fcdd65c60fb3638ef741e8782508fda7eef', 'type' => 'library', 'install_path' => __DIR__ . '/../marc-mabe/php-enum', 'aliases' => array(), 'dev_requirement' => \false), 'monolog/monolog' => array('pretty_version' => '3.10.0', 'version' => '3.10.0.0', 'reference' => 'b321dd6749f0bf7189444158a3ce785cc16d69b0', 'type' => 'library', 'install_path' => __DIR__ . '/../monolog/monolog', 'aliases' => array(), 'dev_requirement' => \false), 'paragonie/constant_time_encoding' => array('pretty_version' => 'v3.1.3', 'version' => '3.1.3.0', 'reference' => 'd5b01a39b3415c2cd581d3bd3a3575c1ebbd8e77', 'type' => 'library', 'install_path' => __DIR__ . '/../paragonie/constant_time_encoding', 'aliases' => array(), 'dev_requirement' => \false), 'phpdocumentor/reflection-common' => array('pretty_version' => '2.2.0', 'version' => '2.2.0.0', 'reference' => '1d01c49d4ed62f25aa84a747ad35d5a16924662b', 'type' => 'library', 'install_path' => __DIR__ . '/../phpdocumentor/reflection-common', 'aliases' => array(), 'dev_requirement' => \false), 'phpdocumentor/reflection-docblock' => array('pretty_version' => '5.6.7', 'version' => '5.6.7.0', 'reference' => '31a105931bc8ffa3a123383829772e832fd8d903', 'type' => 'library', 'install_path' => __DIR__ . '/../phpdocumentor/reflection-docblock', 'aliases' => array(), 'dev_requirement' => \false), 'phpdocumentor/type-resolver' => array('pretty_version' => '1.12.0', 'version' => '1.12.0.0', 'reference' => '92a98ada2b93d9b201a613cb5a33584dde25f195', 'type' => 'library', 'install_path' => __DIR__ . '/../phpdocumentor/type-resolver', 'aliases' => array(), 'dev_requirement' => \false), 'phpstan/phpdoc-parser' => array('pretty_version' => '2.3.2', 'version' => '2.3.2.0', 'reference' => 'a004701b11273a26cd7955a61d67a7f1e525a45a', 'type' => 'library', 'install_path' => __DIR__ . '/../phpstan/phpdoc-parser', 'aliases' => array(), 'dev_requirement' => \false), 'psr/cache' => array('pretty_version' => '3.0.0', 'version' => '3.0.0.0', 'reference' => 'aa5030cfa5405eccfdcb1083ce040c2cb8d253bf', 'type' => 'library', 'install_path' => __DIR__ . '/../psr/cache', 'aliases' => array(), 'dev_requirement' => \false), 'psr/cache-implementation' => array('dev_requirement' => \false, 'provided' => array(0 => '2.0|3.0')), 'psr/clock' => array('pretty_version' => '1.0.0', 'version' => '1.0.0.0', 'reference' => 'e41a24703d4560fd0acb709162f73b8adfc3aa0d', 'type' => 'library', 'install_path' => __DIR__ . '/../psr/clock', 'aliases' => array(), 'dev_requirement' => \false), 'psr/clock-implementation' => array('dev_requirement' => \false, 'provided' => array(0 => '1.0')), 'psr/container' => array('pretty_version' => '2.0.2', 'version' => '2.0.2.0', 'reference' => 'c71ecc56dfe541dbd90c5360474fbc405f8d5963', 'type' => 'library', 'install_path' => __DIR__ . '/../psr/container', 'aliases' => array(), 'dev_requirement' => \false), 'psr/container-implementation' => array('dev_requirement' => \false, 'provided' => array(0 => '1.1|2.0')), 'psr/event-dispatcher' => array('pretty_version' => '1.0.0', 'version' => '1.0.0.0', 'reference' => 'dbefd12671e8a14ec7f180cab83036ed26714bb0', 'type' => 'library', 'install_path' => __DIR__ . '/../psr/event-dispatcher', 'aliases' => array(), 'dev_requirement' => \false), 'psr/event-dispatcher-implementation' => array('dev_requirement' => \false, 'provided' => array(0 => '1.0')), 'psr/http-client' => array('pretty_version' => '1.0.3', 'version' => '1.0.3.0', 'reference' => 'bb5906edc1c324c9a05aa0873d40117941e5fa90', 'type' => 'library', 'install_path' => __DIR__ . '/../psr/http-client', 'aliases' => array(), 'dev_requirement' => \false), 'psr/http-factory' => array('pretty_version' => '1.1.0', 'version' => '1.1.0.0', 'reference' => '2b4765fddfe3b508ac62f829e852b1501d3f6e8a', 'type' => 'library', 'install_path' => __DIR__ . '/../psr/http-factory', 'aliases' => array(), 'dev_requirement' => \false), 'psr/http-message' => array('pretty_version' => '2.0', 'version' => '2.0.0.0', 'reference' => '402d35bcb92c70c026d1a6a9883f06b2ead23d71', 'type' => 'library', 'install_path' => __DIR__ . '/../psr/http-message', 'aliases' => array(), 'dev_requirement' => \false), 'psr/log' => array('pretty_version' => '3.0.2', 'version' => '3.0.2.0', 'reference' => 'f16e1d5863e37f8d8c2a01719f5b34baa2b714d3', 'type' => 'library', 'install_path' => __DIR__ . '/../psr/log', 'aliases' => array(), 'dev_requirement' => \false), 'psr/log-implementation' => array('dev_requirement' => \false, 'provided' => array(0 => '1.0|2.0|3.0', 1 => '3.0.0')), 'psr/simple-cache-implementation' => array('dev_requirement' => \false, 'provided' => array(0 => '1.0|2.0|3.0')), 'ramsey/collection' => array('pretty_version' => '2.1.1', 'version' => '2.1.1.0', 'reference' => '344572933ad0181accbf4ba763e85a0306a8c5e2', 'type' => 'library', 'install_path' => __DIR__ . '/../ramsey/collection', 'aliases' => array(), 'dev_requirement' => \false), 'ramsey/uuid' => array('pretty_version' => '4.9.2', 'version' => '4.9.2.0', 'reference' => '8429c78ca35a09f27565311b98101e2826affde0', 'type' => 'library', 'install_path' => __DIR__ . '/../ramsey/uuid', 'aliases' => array(), 'dev_requirement' => \false), 'react/promise' => array('pretty_version' => 'v3.3.0', 'version' => '3.3.0.0', 'reference' => '23444f53a813a3296c1368bb104793ce8d88f04a', 'type' => 'library', 'install_path' => __DIR__ . '/../react/promise', 'aliases' => array(), 'dev_requirement' => \false), 'rhumsaa/uuid' => array('dev_requirement' => \false, 'replaced' => array(0 => '4.9.2')), 'sebastian/diff' => array('pretty_version' => '5.1.1', 'version' => '5.1.1.0', 'reference' => 'c41e007b4b62af48218231d6c2275e4c9b975b2e', 'type' => 'library', 'install_path' => __DIR__ . '/../sebastian/diff', 'aliases' => array(), 'dev_requirement' => \false), 'seld/jsonlint' => array('pretty_version' => '1.11.0', 'version' => '1.11.0.0', 'reference' => '1748aaf847fc731cfad7725aec413ee46f0cc3a2', 'type' => 'library', 'install_path' => __DIR__ . '/../seld/jsonlint', 'aliases' => array(), 'dev_requirement' => \false), 'seld/phar-utils' => array('pretty_version' => '1.2.1', 'version' => '1.2.1.0', 'reference' => 'ea2f4014f163c1be4c601b9b7bd6af81ba8d701c', 'type' => 'library', 'install_path' => __DIR__ . '/../seld/phar-utils', 'aliases' => array(), 'dev_requirement' => \false), 'seld/signal-handler' => array('pretty_version' => '2.0.2', 'version' => '2.0.2.0', 'reference' => '04a6112e883ad76c0ada8e4a9f7520bbfdb6bb98', 'type' => 'library', 'install_path' => __DIR__ . '/../seld/signal-handler', 'aliases' => array(), 'dev_requirement' => \false), 'spomky-labs/cbor-php' => array('pretty_version' => '3.2.3', 'version' => '3.2.3.0', 'reference' => 'dd6eb84e6d92f7b8bd0da56b4b4dd7235aed0c32', 'type' => 'library', 'install_path' => __DIR__ . '/../spomky-labs/cbor-php', 'aliases' => array(), 'dev_requirement' => \false), 'spomky-labs/otphp' => array('pretty_version' => '11.4.2', 'version' => '11.4.2.0', 'reference' => '2a1b503fd1c1a5c751ab3c5cd37f2d2d26ab74ad', 'type' => 'library', 'install_path' => __DIR__ . '/../spomky-labs/otphp', 'aliases' => array(), 'dev_requirement' => \false), 'spomky-labs/pki-framework' => array('pretty_version' => '1.4.2', 'version' => '1.4.2.0', 'reference' => 'aa576cbd07128075bef97ac2f8af9854e67513d8', 'type' => 'library', 'install_path' => __DIR__ . '/../spomky-labs/pki-framework', 'aliases' => array(), 'dev_requirement' => \false), 'studio24/rotate' => array('pretty_version' => 'v1.0.1', 'version' => '1.0.1.0', 'reference' => '9d99d364bcf619bd9dd48f09ccf292f077c492e8', 'type' => 'library', 'install_path' => __DIR__ . '/../studio24/rotate', 'aliases' => array(), 'dev_requirement' => \false), 'symfony/cache' => array('pretty_version' => 'v6.4.36', 'version' => '6.4.36.0', 'reference' => '5b94fba945d1f9e7929cffd50e7a17f1ac36f10b', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/cache', 'aliases' => array(), 'dev_requirement' => \false), 'symfony/cache-contracts' => array('pretty_version' => 'v3.6.0', 'version' => '3.6.0.0', 'reference' => '5d68a57d66910405e5c0b63d6f0af941e66fc868', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/cache-contracts', 'aliases' => array(), 'dev_requirement' => \false), 'symfony/cache-implementation' => array('dev_requirement' => \false, 'provided' => array(0 => '1.1|2.0|3.0')), 'symfony/clock' => array('pretty_version' => 'v6.4.30', 'version' => '6.4.30.0', 'reference' => 'fb2df4bc9e3037c4765ba7fd29e00167001a9b68', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/clock', 'aliases' => array(), 'dev_requirement' => \false), 'symfony/config' => array('pretty_version' => 'v6.4.34', 'version' => '6.4.34.0', 'reference' => 'ce9cb0c0d281aaf188b802d4968e42bfb60701e9', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/config', 'aliases' => array(), 'dev_requirement' => \false), 'symfony/console' => array('pretty_version' => 'v6.4.36', 'version' => '6.4.36.0', 'reference' => '9f481cfb580db8bcecc9b2d4c63f3e13df022ad5', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/console', 'aliases' => array(), 'dev_requirement' => \false), 'symfony/dependency-injection' => array('pretty_version' => 'v6.4.36', 'version' => '6.4.36.0', 'reference' => 'cd7881a6dc84b780411199cd0584e1a53a3b9ba7', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/dependency-injection', 'aliases' => array(), 'dev_requirement' => \false), 'symfony/deprecation-contracts' => array('pretty_version' => 'v3.6.0', 'version' => '3.6.0.0', 'reference' => '63afe740e99a13ba87ec199bb07bbdee937a5b62', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/deprecation-contracts', 'aliases' => array(), 'dev_requirement' => \false), 'symfony/error-handler' => array('pretty_version' => 'v6.4.36', 'version' => '6.4.36.0', 'reference' => '2ea68f0e1835ad6a126f93bbc14cd236c10ab361', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/error-handler', 'aliases' => array(), 'dev_requirement' => \false), 'symfony/event-dispatcher' => array('pretty_version' => 'v6.4.36', 'version' => '6.4.36.0', 'reference' => 'fc828863e26ceec86e2513b5e46aa0b149d76b69', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/event-dispatcher', 'aliases' => array(), 'dev_requirement' => \false), 'symfony/event-dispatcher-contracts' => array('pretty_version' => 'v3.6.0', 'version' => '3.6.0.0', 'reference' => '59eb412e93815df44f05f342958efa9f46b1e586', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/event-dispatcher-contracts', 'aliases' => array(), 'dev_requirement' => \false), 'symfony/event-dispatcher-implementation' => array('dev_requirement' => \false, 'provided' => array(0 => '2.0|3.0')), 'symfony/filesystem' => array('pretty_version' => 'v6.4.34', 'version' => '6.4.34.0', 'reference' => '01ffe0411b842f93c571e5c391f289c3fdd498c3', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/filesystem', 'aliases' => array(), 'dev_requirement' => \false), 'symfony/finder' => array('pretty_version' => 'v6.4.34', 'version' => '6.4.34.0', 'reference' => '9590e86be1d1c57bfbb16d0dd040345378c20896', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/finder', 'aliases' => array(), 'dev_requirement' => \false), 'symfony/framework-bundle' => array('pretty_version' => 'v6.4.36', 'version' => '6.4.36.0', 'reference' => '147b02cfa45dcc74a290462551f5ee5c7fa8ab17', 'type' => 'symfony-bundle', 'install_path' => __DIR__ . '/../symfony/framework-bundle', 'aliases' => array(), 'dev_requirement' => \false), 'symfony/http-foundation' => array('pretty_version' => 'v6.4.35', 'version' => '6.4.35.0', 'reference' => 'cffffd0a2c037117b742b4f8b379a22a2a33f6d2', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/http-foundation', 'aliases' => array(), 'dev_requirement' => \false), 'symfony/http-kernel' => array('pretty_version' => 'v6.4.36', 'version' => '6.4.36.0', 'reference' => '4087ec02119de450e9ebb60806d69c6bb8c6e468', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/http-kernel', 'aliases' => array(), 'dev_requirement' => \false), 'symfony/monolog-bridge' => array('pretty_version' => 'v6.4.36', 'version' => '6.4.36.0', 'reference' => 'f517ebb675534e0f018708e00037867b268ad5b6', 'type' => 'symfony-bridge', 'install_path' => __DIR__ . '/../symfony/monolog-bridge', 'aliases' => array(), 'dev_requirement' => \false), 'symfony/monolog-bundle' => array('pretty_version' => 'v3.11.2', 'version' => '3.11.2.0', 'reference' => 'd87468010570b2ec766152184918ee8d267c7411', 'type' => 'symfony-bundle', 'install_path' => __DIR__ . '/../symfony/monolog-bundle', 'aliases' => array(), 'dev_requirement' => \false), 'symfony/password-hasher' => array('pretty_version' => 'v6.4.32', 'version' => '6.4.32.0', 'reference' => 'fbdfa5a2ca218ec8bb9029517426df2d780bdba9', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/password-hasher', 'aliases' => array(), 'dev_requirement' => \false), 'symfony/polyfill-ctype' => array('pretty_version' => 'v1.35.0', 'version' => '1.35.0.0', 'reference' => '141046a8f9477948ff284fa65be2095baafb94f2', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/polyfill-ctype', 'aliases' => array(), 'dev_requirement' => \false), 'symfony/polyfill-intl-grapheme' => array('pretty_version' => 'v1.35.0', 'version' => '1.35.0.0', 'reference' => 'ad1b7b9092976d6c948b8a187cec9faaea9ec1df', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/polyfill-intl-grapheme', 'aliases' => array(), 'dev_requirement' => \false), 'symfony/polyfill-intl-normalizer' => array('pretty_version' => 'v1.35.0', 'version' => '1.35.0.0', 'reference' => '3833d7255cc303546435cb650316bff708a1c75c', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/polyfill-intl-normalizer', 'aliases' => array(), 'dev_requirement' => \false), 'symfony/polyfill-mbstring' => array('pretty_version' => 'v1.35.0', 'version' => '1.35.0.0', 'reference' => '6a21eb99c6973357967f6ce3708cd55a6bec6315', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/polyfill-mbstring', 'aliases' => array(), 'dev_requirement' => \false), 'symfony/polyfill-php73' => array('pretty_version' => 'v1.35.0', 'version' => '1.35.0.0', 'reference' => '0f68c03565dcaaf25a890667542e8bd75fe7e5bb', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/polyfill-php73', 'aliases' => array(), 'dev_requirement' => \false), 'symfony/polyfill-php80' => array('pretty_version' => 'v1.35.0', 'version' => '1.35.0.0', 'reference' => 'dfb55726c3a76ea3b6459fcfda1ec2d80a682411', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/polyfill-php80', 'aliases' => array(), 'dev_requirement' => \false), 'symfony/polyfill-php81' => array('pretty_version' => 'v1.35.0', 'version' => '1.35.0.0', 'reference' => '4a4cfc2d253c21a5ad0e53071df248ed48c6ce5c', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/polyfill-php81', 'aliases' => array(), 'dev_requirement' => \false), 'symfony/polyfill-php83' => array('pretty_version' => 'v1.35.0', 'version' => '1.35.0.0', 'reference' => '3600c2cb22399e25bb226e4a135ce91eeb2a6149', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/polyfill-php83', 'aliases' => array(), 'dev_requirement' => \false), 'symfony/polyfill-php84' => array('pretty_version' => 'v1.35.0', 'version' => '1.35.0.0', 'reference' => '88486db2c389b290bf87ff1de7ebc1e13e42bb06', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/polyfill-php84', 'aliases' => array(), 'dev_requirement' => \false), 'symfony/polyfill-uuid' => array('pretty_version' => 'v1.35.0', 'version' => '1.35.0.0', 'reference' => '26dfec253c4cf3e51b541b52ddf7e42cb0908e94', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/polyfill-uuid', 'aliases' => array(), 'dev_requirement' => \false), 'symfony/process' => array('pretty_version' => 'v6.4.33', 'version' => '6.4.33.0', 'reference' => 'c46e854e79b52d07666e43924a20cb6dc546644e', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/process', 'aliases' => array(), 'dev_requirement' => \false), 'symfony/property-access' => array('pretty_version' => 'v6.4.32', 'version' => '6.4.32.0', 'reference' => '6dfa655ac9e9860c05cabb287f34da86b18c237e', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/property-access', 'aliases' => array(), 'dev_requirement' => \false), 'symfony/property-info' => array('pretty_version' => 'v6.4.34', 'version' => '6.4.34.0', 'reference' => '916455e4c9dcddbebfd101f29d7983841c3564e0', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/property-info', 'aliases' => array(), 'dev_requirement' => \false), 'symfony/routing' => array('pretty_version' => 'v6.4.34', 'version' => '6.4.34.0', 'reference' => '5ab3a3e1a03535ec5ca6ce2d39e4369a1096ae47', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/routing', 'aliases' => array(), 'dev_requirement' => \false), 'symfony/security-bundle' => array('pretty_version' => 'v6.4.36', 'version' => '6.4.36.0', 'reference' => '00ce7236da125b39a24784958861678f7d09ce4c', 'type' => 'symfony-bundle', 'install_path' => __DIR__ . '/../symfony/security-bundle', 'aliases' => array(), 'dev_requirement' => \false), 'symfony/security-core' => array('pretty_version' => 'v6.4.36', 'version' => '6.4.36.0', 'reference' => '1b7db28bcc3655543abfe58764025aef563705cd', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/security-core', 'aliases' => array(), 'dev_requirement' => \false), 'symfony/security-csrf' => array('pretty_version' => 'v6.4.31', 'version' => '6.4.31.0', 'reference' => '52f62836fcb19cd351ef3a2aa9cf61a489e8990f', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/security-csrf', 'aliases' => array(), 'dev_requirement' => \false), 'symfony/security-http' => array('pretty_version' => 'v6.4.34', 'version' => '6.4.34.0', 'reference' => '894bb42b39bfb240a1f82c9a46a1ce9402a31a6f', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/security-http', 'aliases' => array(), 'dev_requirement' => \false), 'symfony/serializer' => array('pretty_version' => 'v6.4.36', 'version' => '6.4.36.0', 'reference' => '90e4e0187dca57331ea301506545aa26895b7787', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/serializer', 'aliases' => array(), 'dev_requirement' => \false), 'symfony/service-contracts' => array('pretty_version' => 'v3.6.1', 'version' => '3.6.1.0', 'reference' => '45112560a3ba2d715666a509a0bc9521d10b6c43', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/service-contracts', 'aliases' => array(), 'dev_requirement' => \false), 'symfony/service-implementation' => array('dev_requirement' => \false, 'provided' => array(0 => '1.1|2.0|3.0')), 'symfony/string' => array('pretty_version' => 'v6.4.34', 'version' => '6.4.34.0', 'reference' => '2adaf4106f2ef4c67271971bde6d3fe0a6936432', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/string', 'aliases' => array(), 'dev_requirement' => \false), 'symfony/uid' => array('pretty_version' => 'v6.4.32', 'version' => '6.4.32.0', 'reference' => '6b973c385f00341b246f697d82dc01a09107acdd', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/uid', 'aliases' => array(), 'dev_requirement' => \false), 'symfony/var-dumper' => array('pretty_version' => 'v6.4.36', 'version' => '6.4.36.0', 'reference' => '7c8ad9ce4faf6c8a99948e70ce02b601a0439782', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/var-dumper', 'aliases' => array(), 'dev_requirement' => \false), 'symfony/var-exporter' => array('pretty_version' => 'v6.4.36', 'version' => '6.4.36.0', 'reference' => 'f9c4a9695a9e2bbc65c920e147d8d7ae28f8d79a', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/var-exporter', 'aliases' => array(), 'dev_requirement' => \false), 'symfony/yaml' => array('pretty_version' => 'v6.4.34', 'version' => '6.4.34.0', 'reference' => '7bca30dabed7900a08c5ad4f1d6483f881a64d0f', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/yaml', 'aliases' => array(), 'dev_requirement' => \false), 'terminal42/composer-lock-validator' => array('pretty_version' => '1.1.2', 'version' => '1.1.2.0', 'reference' => '1253aa654b08cc299d1d4d8c65298ec209b99c10', 'type' => 'library', 'install_path' => __DIR__ . '/../terminal42/composer-lock-validator', 'aliases' => array(), 'dev_requirement' => \false), 'web-auth/cose-lib' => array('pretty_version' => '4.5.1', 'version' => '4.5.1.0', 'reference' => '3185af4df10dc537b65c140c315b88d15ae15b80', 'type' => 'library', 'install_path' => __DIR__ . '/../web-auth/cose-lib', 'aliases' => array(), 'dev_requirement' => \false), 'web-auth/webauthn-lib' => array('pretty_version' => '4.9.3', 'version' => '4.9.3.0', 'reference' => '129fbaccd22163429a39bf85e320fb9eddad035c', 'type' => 'library', 'install_path' => __DIR__ . '/../web-auth/webauthn-lib', 'aliases' => array(), 'dev_requirement' => \false), 'webmozart/assert' => array('pretty_version' => '1.12.1', 'version' => '1.12.1.0', 'reference' => '9be6926d8b485f55b9229203f962b51ed377ba68', 'type' => 'library', 'install_path' => __DIR__ . '/../webmozart/assert', 'aliases' => array(), 'dev_requirement' => \false)));
Copyright (C) 2021 Composer

Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
composer/pcre
=============

PCRE wrapping library that offers type-safe `preg_*` replacements.

This library gives you a way to ensure `preg_*` functions do not fail silently, returning
unexpected `null`s that may not be handled.

As of 3.0 this library enforces [`PREG_UNMATCHED_AS_NULL`](#preg_unmatched_as_null) usage
for all matching and replaceCallback functions, [read more below](#preg_unmatched_as_null)
to understand the implications.

It thus makes it easier to work with static analysis tools like PHPStan or Psalm as it
simplifies and reduces the possible return values from all the `preg_*` functions which
are quite packed with edge cases. As of v2.2.0 / v3.2.0 the library also comes with a
[PHPStan extension](#phpstan-extension) for parsing regular expressions and giving you even better output types.

This library is a thin wrapper around `preg_*` functions with [some limitations](#restrictions--limitations).
If you are looking for a richer API to handle regular expressions have a look at
[rawr/t-regx](https://packagist.org/packages/rawr/t-regx) instead.

[![Continuous Integration](https://github.com/composer/pcre/workflows/Continuous%20Integration/badge.svg?branch=main)](https://github.com/composer/pcre/actions)


Installation
------------

Install the latest version with:

```bash
$ composer require composer/pcre
```


Requirements
------------

* PHP 7.4.0 is required for 3.x versions
* PHP 7.2.0 is required for 2.x versions
* PHP 5.3.2 is required for 1.x versions


Basic usage
-----------

Instead of:

```php
if (preg_match('{fo+}', $string, $matches)) { ... }
if (preg_match('{fo+}', $string, $matches, PREG_OFFSET_CAPTURE)) { ... }
if (preg_match_all('{fo+}', $string, $matches)) { ... }
$newString = preg_replace('{fo+}', 'bar', $string);
$newString = preg_replace_callback('{fo+}', function ($match) { return strtoupper($match[0]); }, $string);
$newString = preg_replace_callback_array(['{fo+}' => fn ($match) => strtoupper($match[0])], $string);
$filtered = preg_grep('{[a-z]}', $elements);
$array = preg_split('{[a-z]+}', $string);
```

You can now call these on the `Preg` class:

```php
use Composer\Pcre\Preg;

if (Preg::match('{fo+}', $string, $matches)) { ... }
if (Preg::matchWithOffsets('{fo+}', $string, $matches)) { ... }
if (Preg::matchAll('{fo+}', $string, $matches)) { ... }
$newString = Preg::replace('{fo+}', 'bar', $string);
$newString = Preg::replaceCallback('{fo+}', function ($match) { return strtoupper($match[0]); }, $string);
$newString = Preg::replaceCallbackArray(['{fo+}' => fn ($match) => strtoupper($match[0])], $string);
$filtered = Preg::grep('{[a-z]}', $elements);
$array = Preg::split('{[a-z]+}', $string);
```

The main difference is if anything fails to match/replace/.., it will throw a `Composer\Pcre\PcreException`
instead of returning `null` (or false in some cases), so you can now use the return values safely relying on
the fact that they can only be strings (for replace), ints (for match) or arrays (for grep/split).

Additionally the `Preg` class provides match methods that return `bool` rather than `int`, for stricter type safety
when the number of pattern matches is not useful:

```php
use Composer\Pcre\Preg;

if (Preg::isMatch('{fo+}', $string, $matches)) // bool
if (Preg::isMatchAll('{fo+}', $string, $matches)) // bool
```

Finally the `Preg` class provides a few `*StrictGroups` method variants that ensure match groups
are always present and thus non-nullable, making it easier to write type-safe code:

```php
use Composer\Pcre\Preg;

// $matches is guaranteed to be an array of strings, if a subpattern does not match and produces a null it will throw
if (Preg::matchStrictGroups('{fo+}', $string, $matches))
if (Preg::matchAllStrictGroups('{fo+}', $string, $matches))
```

**Note:** This is generally safe to use as long as you do not have optional subpatterns (i.e. `(something)?`
or `(something)*` or branches with a `|` that result in some groups not being matched at all).
A subpattern that can match an empty string like `(.*)` is **not** optional, it will be present as an
empty string in the matches. A non-matching subpattern, even if optional like `(?:foo)?` will anyway not be present in
matches so it is also not a problem to use these with `*StrictGroups` methods.

If you would prefer a slightly more verbose usage, replacing by-ref arguments by result objects, you can use the `Regex` class:

```php
use Composer\Pcre\Regex;

// this is useful when you are just interested in knowing if something matched
// as it returns a bool instead of int(1/0) for match
$bool = Regex::isMatch('{fo+}', $string);

$result = Regex::match('{fo+}', $string);
if ($result->matched) { something($result->matches); }

$result = Regex::matchWithOffsets('{fo+}', $string);
if ($result->matched) { something($result->matches); }

$result = Regex::matchAll('{fo+}', $string);
if ($result->matched && $result->count > 3) { something($result->matches); }

$newString = Regex::replace('{fo+}', 'bar', $string)->result;
$newString = Regex::replaceCallback('{fo+}', function ($match) { return strtoupper($match[0]); }, $string)->result;
$newString = Regex::replaceCallbackArray(['{fo+}' => fn ($match) => strtoupper($match[0])], $string)->result;
```

Note that `preg_grep` and `preg_split` are only callable via the `Preg` class as they do not have
complex return types warranting a specific result object.

See the [MatchResult](src/MatchResult.php), [MatchWithOffsetsResult](src/MatchWithOffsetsResult.php), [MatchAllResult](src/MatchAllResult.php),
[MatchAllWithOffsetsResult](src/MatchAllWithOffsetsResult.php), and [ReplaceResult](src/ReplaceResult.php) class sources for more details.

Restrictions / Limitations
--------------------------

Due to type safety requirements a few restrictions are in place.

- matching using `PREG_OFFSET_CAPTURE` is made available via `matchWithOffsets` and `matchAllWithOffsets`.
  You cannot pass the flag to `match`/`matchAll`.
- `Preg::split` will also reject `PREG_SPLIT_OFFSET_CAPTURE` and you should use `splitWithOffsets`
  instead.
- `matchAll` rejects `PREG_SET_ORDER` as it also changes the shape of the returned matches. There
  is no alternative provided as you can fairly easily code around it.
- `preg_filter` is not supported as it has a rather crazy API, most likely you should rather
  use `Preg::grep` in combination with some loop and `Preg::replace`.
- `replace`, `replaceCallback` and `replaceCallbackArray` do not support an array `$subject`,
  only simple strings.
- As of 2.0, the library always uses `PREG_UNMATCHED_AS_NULL` for matching, which offers [much
  saner/more predictable results](#preg_unmatched_as_null). As of 3.0 the flag is also set for
  `replaceCallback` and `replaceCallbackArray`.

#### PREG_UNMATCHED_AS_NULL

As of 2.0, this library always uses PREG_UNMATCHED_AS_NULL for all `match*` and `isMatch*`
functions. As of 3.0 it is also done for `replaceCallback` and `replaceCallbackArray`.

This means your matches will always contain all matching groups, either as null if unmatched
or as string if it matched.

The advantages in clarity and predictability are clearer if you compare the two outputs of
running this with and without PREG_UNMATCHED_AS_NULL in $flags:

```php
preg_match('/(a)(b)*(c)(d)*/', 'ac', $matches, $flags);
```

| no flag | PREG_UNMATCHED_AS_NULL |
| --- | --- |
| array (size=4)              | array (size=5) |
| 0 => string 'ac' (length=2) |   0 => string 'ac' (length=2) |
| 1 => string 'a' (length=1)  |   1 => string 'a' (length=1) |
| 2 => string '' (length=0)   |   2 => null |
| 3 => string 'c' (length=1)  |   3 => string 'c' (length=1) |
|                             |   4 => null |
| group 2 (any unmatched group preceding one that matched) is set to `''`. You cannot tell if it matched an empty string or did not match at all | group 2 is `null` when unmatched and a string if it matched, easy to check for |
| group 4 (any optional group without a matching one following) is missing altogether. So you have to check with `isset()`, but really you want `isset($m[4]) && $m[4] !== ''` for safety unless you are very careful to check that a non-optional group follows it | group 4 is always set, and null in this case as there was no match, easy to check for with `$m[4] !== null` |

PHPStan Extension
-----------------

To use the PHPStan extension if you do not use `phpstan/extension-installer` you can include `vendor/composer/pcre/extension.neon` in your PHPStan config.

The extension provides much better type information for $matches as well as regex validation where possible.

License
-------

composer/pcre is licensed under the MIT License, see the LICENSE file for details.
# composer/pcre PHPStan extensions
#
# These can be reused by third party packages by including 'vendor/composer/pcre/extension.neon'
# in your phpstan config

services:
    -
        class: Composer\Pcre\PHPStan\PregMatchParameterOutTypeExtension
        tags:
            - phpstan.staticMethodParameterOutTypeExtension
    -
        class: Composer\Pcre\PHPStan\PregMatchTypeSpecifyingExtension
        tags:
            - phpstan.typeSpecifier.staticMethodTypeSpecifyingExtension
    -
        class: Composer\Pcre\PHPStan\PregReplaceCallbackClosureTypeExtension
        tags:
            - phpstan.staticMethodParameterClosureTypeExtension

rules:
    - Composer\Pcre\PHPStan\UnsafeStrictGroupsCallRule
    - Composer\Pcre\PHPStan\InvalidRegexPatternRule
{
    "name": "composer\/pcre",
    "description": "PCRE wrapping library that offers type-safe preg_* replacements.",
    "type": "library",
    "license": "MIT",
    "keywords": [
        "pcre",
        "regex",
        "preg",
        "regular expression"
    ],
    "authors": [
        {
            "name": "Jordi Boggiano",
            "email": "j.boggiano@seld.be",
            "homepage": "http:\/\/seld.be"
        }
    ],
    "require": {
        "php": "^7.4 || ^8.0"
    },
    "require-dev": {
        "phpunit\/phpunit": "^8 || ^9",
        "phpstan\/phpstan": "^1.12 || ^2",
        "phpstan\/phpstan-strict-rules": "^1 || ^2"
    },
    "conflict": {
        "phpstan\/phpstan": "<1.11.10"
    },
    "autoload": {
        "psr-4": {
            "Composer\\Pcre\\": "src"
        }
    },
    "autoload-dev": {
        "psr-4": {
            "Composer\\Pcre\\": "tests"
        }
    },
    "extra": {
        "branch-alias": {
            "dev-main": "3.x-dev"
        },
        "phpstan": {
            "includes": [
                "extension.neon"
            ]
        }
    },
    "scripts": {
        "test": "@php vendor\/bin\/phpunit",
        "phpstan": "@php phpstan analyse"
    }
}<?php

declare (strict_types=1);
namespace Composer\Pcre\PHPStan;

use Composer\Pcre\Preg;
use _ContaoManager\PhpParser\Node\Expr\StaticCall;
use _ContaoManager\PHPStan\Analyser\Scope;
use _ContaoManager\PHPStan\Analyser\SpecifiedTypes;
use _ContaoManager\PHPStan\Analyser\TypeSpecifier;
use _ContaoManager\PHPStan\Analyser\TypeSpecifierAwareExtension;
use _ContaoManager\PHPStan\Analyser\TypeSpecifierContext;
use _ContaoManager\PHPStan\Reflection\MethodReflection;
use _ContaoManager\PHPStan\TrinaryLogic;
use _ContaoManager\PHPStan\Type\Constant\ConstantArrayType;
use _ContaoManager\PHPStan\Type\Php\RegexArrayShapeMatcher;
use _ContaoManager\PHPStan\Type\StaticMethodTypeSpecifyingExtension;
use _ContaoManager\PHPStan\Type\TypeCombinator;
use _ContaoManager\PHPStan\Type\Type;
final class PregMatchTypeSpecifyingExtension implements StaticMethodTypeSpecifyingExtension, TypeSpecifierAwareExtension
{
    /**
     * @var TypeSpecifier
     */
    private $typeSpecifier;
    /**
     * @var RegexArrayShapeMatcher
     */
    private $regexShapeMatcher;
    public function __construct(RegexArrayShapeMatcher $regexShapeMatcher)
    {
        $this->regexShapeMatcher = $regexShapeMatcher;
    }
    public function setTypeSpecifier(TypeSpecifier $typeSpecifier): void
    {
        $this->typeSpecifier = $typeSpecifier;
    }
    public function getClass(): string
    {
        return Preg::class;
    }
    public function isStaticMethodSupported(MethodReflection $methodReflection, StaticCall $node, TypeSpecifierContext $context): bool
    {
        return in_array($methodReflection->getName(), ['match', 'isMatch', 'matchStrictGroups', 'isMatchStrictGroups', 'matchAll', 'isMatchAll', 'matchAllStrictGroups', 'isMatchAllStrictGroups'], \true) && !$context->null();
    }
    public function specifyTypes(MethodReflection $methodReflection, StaticCall $node, Scope $scope, TypeSpecifierContext $context): SpecifiedTypes
    {
        $args = $node->getArgs();
        $patternArg = $args[0] ?? null;
        $matchesArg = $args[2] ?? null;
        $flagsArg = $args[3] ?? null;
        if ($patternArg === null || $matchesArg === null) {
            return new SpecifiedTypes();
        }
        $flagsType = \Composer\Pcre\PHPStan\PregMatchFlags::getType($flagsArg, $scope);
        if ($flagsType === null) {
            return new SpecifiedTypes();
        }
        if (stripos($methodReflection->getName(), 'matchAll') !== \false) {
            $matchedType = $this->regexShapeMatcher->matchAllExpr($patternArg->value, $flagsType, TrinaryLogic::createFromBoolean($context->true()), $scope);
        } else {
            $matchedType = $this->regexShapeMatcher->matchExpr($patternArg->value, $flagsType, TrinaryLogic::createFromBoolean($context->true()), $scope);
        }
        if ($matchedType === null) {
            return new SpecifiedTypes();
        }
        if (in_array($methodReflection->getName(), ['matchStrictGroups', 'isMatchStrictGroups', 'matchAllStrictGroups', 'isMatchAllStrictGroups'], \true)) {
            $matchedType = \Composer\Pcre\PHPStan\PregMatchFlags::removeNullFromMatches($matchedType);
        }
        $overwrite = \false;
        if ($context->false()) {
            $overwrite = \true;
            $context = $context->negate();
        }
        // @phpstan-ignore function.alreadyNarrowedType
        if (method_exists('_ContaoManager\PHPStan\Analyser\SpecifiedTypes', 'setRootExpr')) {
            $typeSpecifier = $this->typeSpecifier->create($matchesArg->value, $matchedType, $context, $scope)->setRootExpr($node);
            return $overwrite ? $typeSpecifier->setAlwaysOverwriteTypes() : $typeSpecifier;
        }
        // @phpstan-ignore arguments.count
        return $this->typeSpecifier->create(
            $matchesArg->value,
            $matchedType,
            $context,
            // @phpstan-ignore argument.type
            $overwrite,
            $scope,
            $node
        );
    }
}
<?php

declare (strict_types=1);
namespace Composer\Pcre\PHPStan;

use Composer\Pcre\Preg;
use Composer\Pcre\Regex;
use _ContaoManager\PhpParser\Node\Expr\StaticCall;
use _ContaoManager\PHPStan\Analyser\Scope;
use _ContaoManager\PHPStan\Reflection\MethodReflection;
use _ContaoManager\PHPStan\Reflection\Native\NativeParameterReflection;
use _ContaoManager\PHPStan\Reflection\ParameterReflection;
use _ContaoManager\PHPStan\TrinaryLogic;
use _ContaoManager\PHPStan\Type\ClosureType;
use _ContaoManager\PHPStan\Type\Constant\ConstantArrayType;
use _ContaoManager\PHPStan\Type\Php\RegexArrayShapeMatcher;
use _ContaoManager\PHPStan\Type\StaticMethodParameterClosureTypeExtension;
use _ContaoManager\PHPStan\Type\StringType;
use _ContaoManager\PHPStan\Type\TypeCombinator;
use _ContaoManager\PHPStan\Type\Type;
final class PregReplaceCallbackClosureTypeExtension implements StaticMethodParameterClosureTypeExtension
{
    /**
     * @var RegexArrayShapeMatcher
     */
    private $regexShapeMatcher;
    public function __construct(RegexArrayShapeMatcher $regexShapeMatcher)
    {
        $this->regexShapeMatcher = $regexShapeMatcher;
    }
    public function isStaticMethodSupported(MethodReflection $methodReflection, ParameterReflection $parameter): bool
    {
        return in_array($methodReflection->getDeclaringClass()->getName(), [Preg::class, Regex::class], \true) && in_array($methodReflection->getName(), ['replaceCallback', 'replaceCallbackStrictGroups'], \true) && $parameter->getName() === 'replacement';
    }
    public function getTypeFromStaticMethodCall(MethodReflection $methodReflection, StaticCall $methodCall, ParameterReflection $parameter, Scope $scope): ?Type
    {
        $args = $methodCall->getArgs();
        $patternArg = $args[0] ?? null;
        $flagsArg = $args[5] ?? null;
        if ($patternArg === null) {
            return null;
        }
        $flagsType = \Composer\Pcre\PHPStan\PregMatchFlags::getType($flagsArg, $scope);
        $matchesType = $this->regexShapeMatcher->matchExpr($patternArg->value, $flagsType, TrinaryLogic::createYes(), $scope);
        if ($matchesType === null) {
            return null;
        }
        if ($methodReflection->getName() === 'replaceCallbackStrictGroups' && count($matchesType->getConstantArrays()) === 1) {
            $matchesType = $matchesType->getConstantArrays()[0];
            $matchesType = new ConstantArrayType($matchesType->getKeyTypes(), array_map(static function (Type $valueType): Type {
                if (count($valueType->getConstantArrays()) === 1) {
                    $valueTypeArray = $valueType->getConstantArrays()[0];
                    return new ConstantArrayType($valueTypeArray->getKeyTypes(), array_map(static function (Type $valueType): Type {
                        return TypeCombinator::removeNull($valueType);
                    }, $valueTypeArray->getValueTypes()), $valueTypeArray->getNextAutoIndexes(), [], $valueTypeArray->isList());
                }
                return TypeCombinator::removeNull($valueType);
            }, $matchesType->getValueTypes()), $matchesType->getNextAutoIndexes(), [], $matchesType->isList());
        }
        return new ClosureType([new NativeParameterReflection($parameter->getName(), $parameter->isOptional(), $matchesType, $parameter->passedByReference(), $parameter->isVariadic(), $parameter->getDefaultValue())], new StringType());
    }
}
<?php

declare (strict_types=1);
namespace Composer\Pcre\PHPStan;

use Composer\Pcre\Preg;
use _ContaoManager\PhpParser\Node\Expr\StaticCall;
use _ContaoManager\PHPStan\Analyser\Scope;
use _ContaoManager\PHPStan\Reflection\MethodReflection;
use _ContaoManager\PHPStan\Reflection\ParameterReflection;
use _ContaoManager\PHPStan\TrinaryLogic;
use _ContaoManager\PHPStan\Type\Php\RegexArrayShapeMatcher;
use _ContaoManager\PHPStan\Type\StaticMethodParameterOutTypeExtension;
use _ContaoManager\PHPStan\Type\Type;
final class PregMatchParameterOutTypeExtension implements StaticMethodParameterOutTypeExtension
{
    /**
     * @var RegexArrayShapeMatcher
     */
    private $regexShapeMatcher;
    public function __construct(RegexArrayShapeMatcher $regexShapeMatcher)
    {
        $this->regexShapeMatcher = $regexShapeMatcher;
    }
    public function isStaticMethodSupported(MethodReflection $methodReflection, ParameterReflection $parameter): bool
    {
        return $methodReflection->getDeclaringClass()->getName() === Preg::class && in_array($methodReflection->getName(), ['match', 'isMatch', 'matchStrictGroups', 'isMatchStrictGroups', 'matchAll', 'isMatchAll', 'matchAllStrictGroups', 'isMatchAllStrictGroups'], \true) && $parameter->getName() === 'matches';
    }
    public function getParameterOutTypeFromStaticMethodCall(MethodReflection $methodReflection, StaticCall $methodCall, ParameterReflection $parameter, Scope $scope): ?Type
    {
        $args = $methodCall->getArgs();
        $patternArg = $args[0] ?? null;
        $matchesArg = $args[2] ?? null;
        $flagsArg = $args[3] ?? null;
        if ($patternArg === null || $matchesArg === null) {
            return null;
        }
        $flagsType = \Composer\Pcre\PHPStan\PregMatchFlags::getType($flagsArg, $scope);
        if ($flagsType === null) {
            return null;
        }
        if (stripos($methodReflection->getName(), 'matchAll') !== \false) {
            return $this->regexShapeMatcher->matchAllExpr($patternArg->value, $flagsType, TrinaryLogic::createMaybe(), $scope);
        }
        return $this->regexShapeMatcher->matchExpr($patternArg->value, $flagsType, TrinaryLogic::createMaybe(), $scope);
    }
}
<?php

declare (strict_types=1);
namespace Composer\Pcre\PHPStan;

use Composer\Pcre\Preg;
use Composer\Pcre\Regex;
use Composer\Pcre\PcreException;
use _ContaoManager\Nette\Utils\RegexpException;
use _ContaoManager\Nette\Utils\Strings;
use _ContaoManager\PhpParser\Node;
use _ContaoManager\PhpParser\Node\Expr\StaticCall;
use _ContaoManager\PhpParser\Node\Name\FullyQualified;
use _ContaoManager\PHPStan\Analyser\Scope;
use _ContaoManager\PHPStan\Rules\Rule;
use _ContaoManager\PHPStan\Rules\RuleErrorBuilder;
use function in_array;
use function sprintf;
/**
 * Copy of PHPStan's RegularExpressionPatternRule
 *
 * @implements Rule<StaticCall>
 */
class InvalidRegexPatternRule implements Rule
{
    public function getNodeType(): string
    {
        return StaticCall::class;
    }
    public function processNode(Node $node, Scope $scope): array
    {
        $patterns = $this->extractPatterns($node, $scope);
        $errors = [];
        foreach ($patterns as $pattern) {
            $errorMessage = $this->validatePattern($pattern);
            if ($errorMessage === null) {
                continue;
            }
            $errors[] = RuleErrorBuilder::message(sprintf('Regex pattern is invalid: %s', $errorMessage))->identifier('regexp.pattern')->build();
        }
        return $errors;
    }
    /**
     * @return string[]
     */
    private function extractPatterns(StaticCall $node, Scope $scope): array
    {
        if (!$node->class instanceof FullyQualified) {
            return [];
        }
        $isRegex = $node->class->toString() === Regex::class;
        $isPreg = $node->class->toString() === Preg::class;
        if (!$isRegex && !$isPreg) {
            return [];
        }
        if (!$node->name instanceof Node\Identifier || !Preg::isMatch('{^(match|isMatch|grep|replace|split)}', $node->name->name)) {
            return [];
        }
        $functionName = $node->name->name;
        if (!isset($node->getArgs()[0])) {
            return [];
        }
        $patternNode = $node->getArgs()[0]->value;
        $patternType = $scope->getType($patternNode);
        $patternStrings = [];
        foreach ($patternType->getConstantStrings() as $constantStringType) {
            if ($functionName === 'replaceCallbackArray') {
                continue;
            }
            $patternStrings[] = $constantStringType->getValue();
        }
        foreach ($patternType->getConstantArrays() as $constantArrayType) {
            if (in_array($functionName, ['replace', 'replaceCallback'], \true)) {
                foreach ($constantArrayType->getValueTypes() as $arrayKeyType) {
                    foreach ($arrayKeyType->getConstantStrings() as $constantString) {
                        $patternStrings[] = $constantString->getValue();
                    }
                }
            }
            if ($functionName !== 'replaceCallbackArray') {
                continue;
            }
            foreach ($constantArrayType->getKeyTypes() as $arrayKeyType) {
                foreach ($arrayKeyType->getConstantStrings() as $constantString) {
                    $patternStrings[] = $constantString->getValue();
                }
            }
        }
        return $patternStrings;
    }
    private function validatePattern(string $pattern): ?string
    {
        try {
            $msg = null;
            $prev = set_error_handler(function (int $severity, string $message, string $file) use (&$msg): bool {
                $msg = preg_replace("#^preg_match(_all)?\\(.*?\\): #", '', $message);
                return \true;
            });
            if ($pattern === '') {
                return 'Empty string is not a valid regular expression';
            }
            Preg::match($pattern, '');
            if ($msg !== null) {
                return $msg;
            }
        } catch (PcreException $e) {
            if ($e->getCode() === \PREG_INTERNAL_ERROR && $msg !== null) {
                return $msg;
            }
            return preg_replace('{.*? failed executing ".*": }', '', $e->getMessage());
        } finally {
            restore_error_handler();
        }
        return null;
    }
}
<?php

declare (strict_types=1);
namespace Composer\Pcre\PHPStan;

use _ContaoManager\PHPStan\Analyser\Scope;
use _ContaoManager\PHPStan\Type\ArrayType;
use _ContaoManager\PHPStan\Type\Constant\ConstantArrayType;
use _ContaoManager\PHPStan\Type\Constant\ConstantIntegerType;
use _ContaoManager\PHPStan\Type\IntersectionType;
use _ContaoManager\PHPStan\Type\TypeCombinator;
use _ContaoManager\PHPStan\Type\Type;
use _ContaoManager\PhpParser\Node\Arg;
use _ContaoManager\PHPStan\Type\Php\RegexArrayShapeMatcher;
use _ContaoManager\PHPStan\Type\TypeTraverser;
use _ContaoManager\PHPStan\Type\UnionType;
final class PregMatchFlags
{
    public static function getType(?Arg $flagsArg, Scope $scope): ?Type
    {
        if ($flagsArg === null) {
            return new ConstantIntegerType(\PREG_UNMATCHED_AS_NULL);
        }
        $flagsType = $scope->getType($flagsArg->value);
        $constantScalars = $flagsType->getConstantScalarValues();
        if ($constantScalars === []) {
            return null;
        }
        $internalFlagsTypes = [];
        foreach ($flagsType->getConstantScalarValues() as $constantScalarValue) {
            if (!is_int($constantScalarValue)) {
                return null;
            }
            $internalFlagsTypes[] = new ConstantIntegerType($constantScalarValue | \PREG_UNMATCHED_AS_NULL);
        }
        return TypeCombinator::union(...$internalFlagsTypes);
    }
    public static function removeNullFromMatches(Type $matchesType): Type
    {
        return TypeTraverser::map($matchesType, static function (Type $type, callable $traverse): Type {
            if ($type instanceof UnionType || $type instanceof IntersectionType) {
                return $traverse($type);
            }
            if ($type instanceof ConstantArrayType) {
                return new ConstantArrayType($type->getKeyTypes(), array_map(static function (Type $valueType) use ($traverse): Type {
                    return $traverse($valueType);
                }, $type->getValueTypes()), $type->getNextAutoIndexes(), [], $type->isList());
            }
            if ($type instanceof ArrayType) {
                return new ArrayType($type->getKeyType(), $traverse($type->getItemType()));
            }
            return TypeCombinator::removeNull($type);
        });
    }
}
<?php

declare (strict_types=1);
namespace Composer\Pcre\PHPStan;

use Composer\Pcre\Preg;
use Composer\Pcre\Regex;
use _ContaoManager\PhpParser\Node;
use _ContaoManager\PhpParser\Node\Expr\StaticCall;
use _ContaoManager\PhpParser\Node\Name\FullyQualified;
use _ContaoManager\PHPStan\Analyser\Scope;
use _ContaoManager\PHPStan\Analyser\SpecifiedTypes;
use _ContaoManager\PHPStan\Rules\Rule;
use _ContaoManager\PHPStan\Rules\RuleErrorBuilder;
use _ContaoManager\PHPStan\TrinaryLogic;
use _ContaoManager\PHPStan\Type\ObjectType;
use _ContaoManager\PHPStan\Type\Type;
use _ContaoManager\PHPStan\Type\TypeCombinator;
use _ContaoManager\PHPStan\Type\Php\RegexArrayShapeMatcher;
use function sprintf;
/**
 * @implements Rule<StaticCall>
 */
final class UnsafeStrictGroupsCallRule implements Rule
{
    /**
     * @var RegexArrayShapeMatcher
     */
    private $regexShapeMatcher;
    public function __construct(RegexArrayShapeMatcher $regexShapeMatcher)
    {
        $this->regexShapeMatcher = $regexShapeMatcher;
    }
    public function getNodeType(): string
    {
        return StaticCall::class;
    }
    public function processNode(Node $node, Scope $scope): array
    {
        if (!$node->class instanceof FullyQualified) {
            return [];
        }
        $isRegex = $node->class->toString() === Regex::class;
        $isPreg = $node->class->toString() === Preg::class;
        if (!$isRegex && !$isPreg) {
            return [];
        }
        if (!$node->name instanceof Node\Identifier || !in_array($node->name->name, ['matchStrictGroups', 'isMatchStrictGroups', 'matchAllStrictGroups', 'isMatchAllStrictGroups'], \true)) {
            return [];
        }
        $args = $node->getArgs();
        if (!isset($args[0])) {
            return [];
        }
        $patternArg = $args[0] ?? null;
        if ($isPreg) {
            if (!isset($args[2])) {
                // no matches set, skip as the matches won't be used anyway
                return [];
            }
            $flagsArg = $args[3] ?? null;
        } else {
            $flagsArg = $args[2] ?? null;
        }
        if ($patternArg === null) {
            return [];
        }
        $flagsType = \Composer\Pcre\PHPStan\PregMatchFlags::getType($flagsArg, $scope);
        if ($flagsType === null) {
            return [];
        }
        $matchedType = $this->regexShapeMatcher->matchExpr($patternArg->value, $flagsType, TrinaryLogic::createYes(), $scope);
        if ($matchedType === null) {
            return [RuleErrorBuilder::message(sprintf('The %s call is potentially unsafe as $matches\' type could not be inferred.', $node->name->name))->identifier('composerPcre.maybeUnsafeStrictGroups')->build()];
        }
        if (count($matchedType->getConstantArrays()) === 1) {
            $matchedType = $matchedType->getConstantArrays()[0];
            $nullableGroups = [];
            foreach ($matchedType->getValueTypes() as $index => $type) {
                if (TypeCombinator::containsNull($type)) {
                    $nullableGroups[] = $matchedType->getKeyTypes()[$index]->getValue();
                }
            }
            if (\count($nullableGroups) > 0) {
                return [RuleErrorBuilder::message(sprintf('The %s call is unsafe as match group%s "%s" %s optional and may be null.', $node->name->name, \count($nullableGroups) > 1 ? 's' : '', implode('", "', $nullableGroups), \count($nullableGroups) > 1 ? 'are' : 'is'))->identifier('composerPcre.unsafeStrictGroups')->build()];
            }
        }
        return [];
    }
}
<?php

/*
 * This file is part of composer/pcre.
 *
 * (c) Composer <https://github.com/composer>
 *
 * For the full copyright and license information, please view
 * the LICENSE file that was distributed with this source code.
 */
namespace Composer\Pcre;

final class MatchResult
{
    /**
     * An array of match group => string matched
     *
     * @readonly
     * @var array<int|string, string|null>
     */
    public $matches;
    /**
     * @readonly
     * @var bool
     */
    public $matched;
    /**
     * @param 0|positive-int $count
     * @param array<string|null> $matches
     */
    public function __construct(int $count, array $matches)
    {
        $this->matches = $matches;
        $this->matched = (bool) $count;
    }
}
<?php

/*
 * This file is part of composer/pcre.
 *
 * (c) Composer <https://github.com/composer>
 *
 * For the full copyright and license information, please view
 * the LICENSE file that was distributed with this source code.
 */
namespace Composer\Pcre;

class Regex
{
    /**
     * @param non-empty-string $pattern
     */
    public static function isMatch(string $pattern, string $subject, int $offset = 0): bool
    {
        return (bool) \Composer\Pcre\Preg::match($pattern, $subject, $matches, 0, $offset);
    }
    /**
     * @param non-empty-string $pattern
     * @param int-mask<PREG_UNMATCHED_AS_NULL> $flags PREG_UNMATCHED_AS_NULL is always set, no other flags are supported
     */
    public static function match(string $pattern, string $subject, int $flags = 0, int $offset = 0): \Composer\Pcre\MatchResult
    {
        self::checkOffsetCapture($flags, 'matchWithOffsets');
        $count = \Composer\Pcre\Preg::match($pattern, $subject, $matches, $flags, $offset);
        return new \Composer\Pcre\MatchResult($count, $matches);
    }
    /**
     * Variant of `match()` which returns non-null matches (or throws)
     *
     * @param non-empty-string $pattern
     * @param int-mask<PREG_UNMATCHED_AS_NULL> $flags PREG_UNMATCHED_AS_NULL is always set, no other flags are supported
     * @throws UnexpectedNullMatchException
     */
    public static function matchStrictGroups(string $pattern, string $subject, int $flags = 0, int $offset = 0): \Composer\Pcre\MatchStrictGroupsResult
    {
        // @phpstan-ignore composerPcre.maybeUnsafeStrictGroups
        $count = \Composer\Pcre\Preg::matchStrictGroups($pattern, $subject, $matches, $flags, $offset);
        return new \Composer\Pcre\MatchStrictGroupsResult($count, $matches);
    }
    /**
     * Runs preg_match with PREG_OFFSET_CAPTURE
     *
     * @param non-empty-string $pattern
     * @param int-mask<PREG_UNMATCHED_AS_NULL|PREG_OFFSET_CAPTURE> $flags PREG_UNMATCHED_AS_NULL and PREG_MATCH_OFFSET are always set, no other flags are supported
     */
    public static function matchWithOffsets(string $pattern, string $subject, int $flags = 0, int $offset = 0): \Composer\Pcre\MatchWithOffsetsResult
    {
        $count = \Composer\Pcre\Preg::matchWithOffsets($pattern, $subject, $matches, $flags, $offset);
        return new \Composer\Pcre\MatchWithOffsetsResult($count, $matches);
    }
    /**
     * @param non-empty-string $pattern
     * @param int-mask<PREG_UNMATCHED_AS_NULL> $flags PREG_UNMATCHED_AS_NULL is always set, no other flags are supported
     */
    public static function matchAll(string $pattern, string $subject, int $flags = 0, int $offset = 0): \Composer\Pcre\MatchAllResult
    {
        self::checkOffsetCapture($flags, 'matchAllWithOffsets');
        self::checkSetOrder($flags);
        $count = \Composer\Pcre\Preg::matchAll($pattern, $subject, $matches, $flags, $offset);
        return new \Composer\Pcre\MatchAllResult($count, $matches);
    }
    /**
     * Variant of `matchAll()` which returns non-null matches (or throws)
     *
     * @param non-empty-string $pattern
     * @param int-mask<PREG_UNMATCHED_AS_NULL> $flags PREG_UNMATCHED_AS_NULL is always set, no other flags are supported
     * @throws UnexpectedNullMatchException
     */
    public static function matchAllStrictGroups(string $pattern, string $subject, int $flags = 0, int $offset = 0): \Composer\Pcre\MatchAllStrictGroupsResult
    {
        self::checkOffsetCapture($flags, 'matchAllWithOffsets');
        self::checkSetOrder($flags);
        // @phpstan-ignore composerPcre.maybeUnsafeStrictGroups
        $count = \Composer\Pcre\Preg::matchAllStrictGroups($pattern, $subject, $matches, $flags, $offset);
        return new \Composer\Pcre\MatchAllStrictGroupsResult($count, $matches);
    }
    /**
     * Runs preg_match_all with PREG_OFFSET_CAPTURE
     *
     * @param non-empty-string $pattern
     * @param int-mask<PREG_UNMATCHED_AS_NULL|PREG_OFFSET_CAPTURE> $flags PREG_UNMATCHED_AS_NULL and PREG_MATCH_OFFSET are always set, no other flags are supported
     */
    public static function matchAllWithOffsets(string $pattern, string $subject, int $flags = 0, int $offset = 0): \Composer\Pcre\MatchAllWithOffsetsResult
    {
        self::checkSetOrder($flags);
        $count = \Composer\Pcre\Preg::matchAllWithOffsets($pattern, $subject, $matches, $flags, $offset);
        return new \Composer\Pcre\MatchAllWithOffsetsResult($count, $matches);
    }
    /**
     * @param string|string[] $pattern
     * @param string|string[] $replacement
     * @param string          $subject
     */
    public static function replace($pattern, $replacement, $subject, int $limit = -1): \Composer\Pcre\ReplaceResult
    {
        $result = \Composer\Pcre\Preg::replace($pattern, $replacement, $subject, $limit, $count);
        return new \Composer\Pcre\ReplaceResult($count, $result);
    }
    /**
     * @param string|string[] $pattern
     * @param ($flags is PREG_OFFSET_CAPTURE ? (callable(array<int|string, array{string|null, int<-1, max>}>): string) : callable(array<int|string, string|null>): string) $replacement
     * @param string          $subject
     * @param int-mask<PREG_UNMATCHED_AS_NULL|PREG_OFFSET_CAPTURE> $flags PREG_OFFSET_CAPTURE is supported, PREG_UNMATCHED_AS_NULL is always set
     */
    public static function replaceCallback($pattern, callable $replacement, $subject, int $limit = -1, int $flags = 0): \Composer\Pcre\ReplaceResult
    {
        $result = \Composer\Pcre\Preg::replaceCallback($pattern, $replacement, $subject, $limit, $count, $flags);
        return new \Composer\Pcre\ReplaceResult($count, $result);
    }
    /**
     * Variant of `replaceCallback()` which outputs non-null matches (or throws)
     *
     * @param string $pattern
     * @param ($flags is PREG_OFFSET_CAPTURE ? (callable(array<int|string, array{string, int<0, max>}>): string) : callable(array<int|string, string>): string) $replacement
     * @param string          $subject
     * @param int-mask<PREG_UNMATCHED_AS_NULL|PREG_OFFSET_CAPTURE> $flags PREG_OFFSET_CAPTURE is supported, PREG_UNMATCHED_AS_NULL is always set
     */
    public static function replaceCallbackStrictGroups($pattern, callable $replacement, $subject, int $limit = -1, int $flags = 0): \Composer\Pcre\ReplaceResult
    {
        $result = \Composer\Pcre\Preg::replaceCallbackStrictGroups($pattern, $replacement, $subject, $limit, $count, $flags);
        return new \Composer\Pcre\ReplaceResult($count, $result);
    }
    /**
     * @param ($flags is PREG_OFFSET_CAPTURE ? (array<string, callable(array<int|string, array{string|null, int<-1, max>}>): string>) : array<string, callable(array<int|string, string|null>): string>) $pattern
     * @param string $subject
     * @param int-mask<PREG_UNMATCHED_AS_NULL|PREG_OFFSET_CAPTURE> $flags PREG_OFFSET_CAPTURE is supported, PREG_UNMATCHED_AS_NULL is always set
     */
    public static function replaceCallbackArray(array $pattern, $subject, int $limit = -1, int $flags = 0): \Composer\Pcre\ReplaceResult
    {
        $result = \Composer\Pcre\Preg::replaceCallbackArray($pattern, $subject, $limit, $count, $flags);
        return new \Composer\Pcre\ReplaceResult($count, $result);
    }
    private static function checkOffsetCapture(int $flags, string $useFunctionName): void
    {
        if (($flags & \PREG_OFFSET_CAPTURE) !== 0) {
            throw new \InvalidArgumentException('PREG_OFFSET_CAPTURE is not supported as it changes the return type, use ' . $useFunctionName . '() instead');
        }
    }
    private static function checkSetOrder(int $flags): void
    {
        if (($flags & \PREG_SET_ORDER) !== 0) {
            throw new \InvalidArgumentException('PREG_SET_ORDER is not supported as it changes the return type');
        }
    }
}
<?php

/*
 * This file is part of composer/pcre.
 *
 * (c) Composer <https://github.com/composer>
 *
 * For the full copyright and license information, please view
 * the LICENSE file that was distributed with this source code.
 */
namespace Composer\Pcre;

final class MatchAllWithOffsetsResult
{
    /**
     * An array of match group => list of matches, every match being a pair of string matched + offset in bytes (or -1 if no match)
     *
     * @readonly
     * @var array<int|string, list<array{string|null, int}>>
     * @phpstan-var array<int|string, list<array{string|null, int<-1, max>}>>
     */
    public $matches;
    /**
     * @readonly
     * @var 0|positive-int
     */
    public $count;
    /**
     * @readonly
     * @var bool
     */
    public $matched;
    /**
     * @param 0|positive-int $count
     * @param array<int|string, list<array{string|null, int}>> $matches
     * @phpstan-param array<int|string, list<array{string|null, int<-1, max>}>> $matches
     */
    public function __construct(int $count, array $matches)
    {
        $this->matches = $matches;
        $this->matched = (bool) $count;
        $this->count = $count;
    }
}
<?php

/*
 * This file is part of composer/pcre.
 *
 * (c) Composer <https://github.com/composer>
 *
 * For the full copyright and license information, please view
 * the LICENSE file that was distributed with this source code.
 */
namespace Composer\Pcre;

final class MatchWithOffsetsResult
{
    /**
     * An array of match group => pair of string matched + offset in bytes (or -1 if no match)
     *
     * @readonly
     * @var array<int|string, array{string|null, int}>
     * @phpstan-var array<int|string, array{string|null, int<-1, max>}>
     */
    public $matches;
    /**
     * @readonly
     * @var bool
     */
    public $matched;
    /**
     * @param 0|positive-int $count
     * @param array<array{string|null, int}> $matches
     * @phpstan-param array<int|string, array{string|null, int<-1, max>}> $matches
     */
    public function __construct(int $count, array $matches)
    {
        $this->matches = $matches;
        $this->matched = (bool) $count;
    }
}
<?php

/*
 * This file is part of composer/pcre.
 *
 * (c) Composer <https://github.com/composer>
 *
 * For the full copyright and license information, please view
 * the LICENSE file that was distributed with this source code.
 */
namespace Composer\Pcre;

final class MatchAllStrictGroupsResult
{
    /**
     * An array of match group => list of matched strings
     *
     * @readonly
     * @var array<int|string, list<string>>
     */
    public $matches;
    /**
     * @readonly
     * @var 0|positive-int
     */
    public $count;
    /**
     * @readonly
     * @var bool
     */
    public $matched;
    /**
     * @param 0|positive-int $count
     * @param array<list<string>> $matches
     */
    public function __construct(int $count, array $matches)
    {
        $this->matches = $matches;
        $this->matched = (bool) $count;
        $this->count = $count;
    }
}
<?php

/*
 * This file is part of composer/pcre.
 *
 * (c) Composer <https://github.com/composer>
 *
 * For the full copyright and license information, please view
 * the LICENSE file that was distributed with this source code.
 */
namespace Composer\Pcre;

class UnexpectedNullMatchException extends \Composer\Pcre\PcreException
{
    public static function fromFunction($function, $pattern)
    {
        throw new \LogicException('fromFunction should not be called on ' . self::class . ', use ' . \Composer\Pcre\PcreException::class);
    }
}
<?php

/*
 * This file is part of composer/pcre.
 *
 * (c) Composer <https://github.com/composer>
 *
 * For the full copyright and license information, please view
 * the LICENSE file that was distributed with this source code.
 */
namespace Composer\Pcre;

final class MatchStrictGroupsResult
{
    /**
     * An array of match group => string matched
     *
     * @readonly
     * @var array<int|string, string>
     */
    public $matches;
    /**
     * @readonly
     * @var bool
     */
    public $matched;
    /**
     * @param 0|positive-int $count
     * @param array<string> $matches
     */
    public function __construct(int $count, array $matches)
    {
        $this->matches = $matches;
        $this->matched = (bool) $count;
    }
}
<?php

/*
 * This file is part of composer/pcre.
 *
 * (c) Composer <https://github.com/composer>
 *
 * For the full copyright and license information, please view
 * the LICENSE file that was distributed with this source code.
 */
namespace Composer\Pcre;

final class MatchAllResult
{
    /**
     * An array of match group => list of matched strings
     *
     * @readonly
     * @var array<int|string, list<string|null>>
     */
    public $matches;
    /**
     * @readonly
     * @var 0|positive-int
     */
    public $count;
    /**
     * @readonly
     * @var bool
     */
    public $matched;
    /**
     * @param 0|positive-int $count
     * @param array<int|string, list<string|null>> $matches
     */
    public function __construct(int $count, array $matches)
    {
        $this->matches = $matches;
        $this->matched = (bool) $count;
        $this->count = $count;
    }
}
<?php

/*
 * This file is part of composer/pcre.
 *
 * (c) Composer <https://github.com/composer>
 *
 * For the full copyright and license information, please view
 * the LICENSE file that was distributed with this source code.
 */
namespace Composer\Pcre;

final class ReplaceResult
{
    /**
     * @readonly
     * @var string
     */
    public $result;
    /**
     * @readonly
     * @var 0|positive-int
     */
    public $count;
    /**
     * @readonly
     * @var bool
     */
    public $matched;
    /**
     * @param 0|positive-int $count
     */
    public function __construct(int $count, string $result)
    {
        $this->count = $count;
        $this->matched = (bool) $count;
        $this->result = $result;
    }
}
<?php

/*
 * This file is part of composer/pcre.
 *
 * (c) Composer <https://github.com/composer>
 *
 * For the full copyright and license information, please view
 * the LICENSE file that was distributed with this source code.
 */
namespace Composer\Pcre;

class Preg
{
    /** @internal */
    public const ARRAY_MSG = '$subject as an array is not supported. You can use \'foreach\' instead.';
    /** @internal */
    public const INVALID_TYPE_MSG = '$subject must be a string, %s given.';
    /**
     * @param non-empty-string   $pattern
     * @param array<mixed> $matches Set by method
     * @param int-mask<PREG_UNMATCHED_AS_NULL> $flags PREG_UNMATCHED_AS_NULL is always set, no other flags are supported
     * @return 0|1
     *
     * @param-out array<int|string, string|null> $matches
     */
    public static function match(string $pattern, string $subject, ?array &$matches = null, int $flags = 0, int $offset = 0): int
    {
        self::checkOffsetCapture($flags, 'matchWithOffsets');
        $result = preg_match($pattern, $subject, $matches, $flags | \PREG_UNMATCHED_AS_NULL, $offset);
        if ($result === \false) {
            throw \Composer\Pcre\PcreException::fromFunction('preg_match', $pattern);
        }
        return $result;
    }
    /**
     * Variant of `match()` which outputs non-null matches (or throws)
     *
     * @param non-empty-string $pattern
     * @param array<mixed> $matches Set by method
     * @param int-mask<PREG_UNMATCHED_AS_NULL> $flags PREG_UNMATCHED_AS_NULL is always set, no other flags are supported
     * @return 0|1
     * @throws UnexpectedNullMatchException
     *
     * @param-out array<int|string, string> $matches
     */
    public static function matchStrictGroups(string $pattern, string $subject, ?array &$matches = null, int $flags = 0, int $offset = 0): int
    {
        $result = self::match($pattern, $subject, $matchesInternal, $flags, $offset);
        $matches = self::enforceNonNullMatches($pattern, $matchesInternal, 'match');
        return $result;
    }
    /**
     * Runs preg_match with PREG_OFFSET_CAPTURE
     *
     * @param non-empty-string   $pattern
     * @param array<mixed> $matches Set by method
     * @param int-mask<PREG_UNMATCHED_AS_NULL|PREG_OFFSET_CAPTURE> $flags PREG_UNMATCHED_AS_NULL and PREG_OFFSET_CAPTURE are always set, no other flags are supported
     * @return 0|1
     *
     * @param-out array<int|string, array{string|null, int<-1, max>}> $matches
     */
    public static function matchWithOffsets(string $pattern, string $subject, ?array &$matches, int $flags = 0, int $offset = 0): int
    {
        $result = preg_match($pattern, $subject, $matches, $flags | \PREG_UNMATCHED_AS_NULL | \PREG_OFFSET_CAPTURE, $offset);
        if ($result === \false) {
            throw \Composer\Pcre\PcreException::fromFunction('preg_match', $pattern);
        }
        return $result;
    }
    /**
     * @param non-empty-string   $pattern
     * @param array<mixed> $matches Set by method
     * @param int-mask<PREG_UNMATCHED_AS_NULL> $flags PREG_UNMATCHED_AS_NULL is always set, no other flags are supported
     * @return 0|positive-int
     *
     * @param-out array<int|string, list<string|null>> $matches
     */
    public static function matchAll(string $pattern, string $subject, ?array &$matches = null, int $flags = 0, int $offset = 0): int
    {
        self::checkOffsetCapture($flags, 'matchAllWithOffsets');
        self::checkSetOrder($flags);
        $result = preg_match_all($pattern, $subject, $matches, $flags | \PREG_UNMATCHED_AS_NULL, $offset);
        if (!is_int($result)) {
            // PHP < 8 may return null, 8+ returns int|false
            throw \Composer\Pcre\PcreException::fromFunction('preg_match_all', $pattern);
        }
        return $result;
    }
    /**
     * Variant of `match()` which outputs non-null matches (or throws)
     *
     * @param non-empty-string   $pattern
     * @param array<mixed> $matches Set by method
     * @param int-mask<PREG_UNMATCHED_AS_NULL> $flags PREG_UNMATCHED_AS_NULL is always set, no other flags are supported
     * @return 0|positive-int
     * @throws UnexpectedNullMatchException
     *
     * @param-out array<int|string, list<string>> $matches
     */
    public static function matchAllStrictGroups(string $pattern, string $subject, ?array &$matches = null, int $flags = 0, int $offset = 0): int
    {
        $result = self::matchAll($pattern, $subject, $matchesInternal, $flags, $offset);
        $matches = self::enforceNonNullMatchAll($pattern, $matchesInternal, 'matchAll');
        return $result;
    }
    /**
     * Runs preg_match_all with PREG_OFFSET_CAPTURE
     *
     * @param non-empty-string   $pattern
     * @param array<mixed> $matches Set by method
     * @param int-mask<PREG_UNMATCHED_AS_NULL|PREG_OFFSET_CAPTURE> $flags PREG_UNMATCHED_AS_NULL and PREG_MATCH_OFFSET are always set, no other flags are supported
     * @return 0|positive-int
     *
     * @param-out array<int|string, list<array{string|null, int<-1, max>}>> $matches
     */
    public static function matchAllWithOffsets(string $pattern, string $subject, ?array &$matches, int $flags = 0, int $offset = 0): int
    {
        self::checkSetOrder($flags);
        $result = preg_match_all($pattern, $subject, $matches, $flags | \PREG_UNMATCHED_AS_NULL | \PREG_OFFSET_CAPTURE, $offset);
        if (!is_int($result)) {
            // PHP < 8 may return null, 8+ returns int|false
            throw \Composer\Pcre\PcreException::fromFunction('preg_match_all', $pattern);
        }
        return $result;
    }
    /**
     * @param string|string[] $pattern
     * @param string|string[] $replacement
     * @param string $subject
     * @param int             $count Set by method
     *
     * @param-out int<0, max> $count
     */
    public static function replace($pattern, $replacement, $subject, int $limit = -1, ?int &$count = null): string
    {
        if (!is_scalar($subject)) {
            if (is_array($subject)) {
                throw new \InvalidArgumentException(static::ARRAY_MSG);
            }
            throw new \TypeError(sprintf(static::INVALID_TYPE_MSG, gettype($subject)));
        }
        $result = preg_replace($pattern, $replacement, $subject, $limit, $count);
        if ($result === null) {
            throw \Composer\Pcre\PcreException::fromFunction('preg_replace', $pattern);
        }
        return $result;
    }
    /**
     * @param string|string[] $pattern
     * @param ($flags is PREG_OFFSET_CAPTURE ? (callable(array<int|string, array{string|null, int<-1, max>}>): string) : callable(array<int|string, string|null>): string) $replacement
     * @param string $subject
     * @param int             $count Set by method
     * @param int-mask<PREG_UNMATCHED_AS_NULL|PREG_OFFSET_CAPTURE> $flags PREG_OFFSET_CAPTURE is supported, PREG_UNMATCHED_AS_NULL is always set
     *
     * @param-out int<0, max> $count
     */
    public static function replaceCallback($pattern, callable $replacement, $subject, int $limit = -1, ?int &$count = null, int $flags = 0): string
    {
        if (!is_scalar($subject)) {
            if (is_array($subject)) {
                throw new \InvalidArgumentException(static::ARRAY_MSG);
            }
            throw new \TypeError(sprintf(static::INVALID_TYPE_MSG, gettype($subject)));
        }
        $result = preg_replace_callback($pattern, $replacement, $subject, $limit, $count, $flags | \PREG_UNMATCHED_AS_NULL);
        if ($result === null) {
            throw \Composer\Pcre\PcreException::fromFunction('preg_replace_callback', $pattern);
        }
        return $result;
    }
    /**
     * Variant of `replaceCallback()` which outputs non-null matches (or throws)
     *
     * @param string $pattern
     * @param ($flags is PREG_OFFSET_CAPTURE ? (callable(array<int|string, array{string, int<0, max>}>): string) : callable(array<int|string, string>): string) $replacement
     * @param string $subject
     * @param int $count Set by method
     * @param int-mask<PREG_UNMATCHED_AS_NULL|PREG_OFFSET_CAPTURE> $flags PREG_OFFSET_CAPTURE is supported, PREG_UNMATCHED_AS_NULL is always set
     *
     * @param-out int<0, max> $count
     */
    public static function replaceCallbackStrictGroups(string $pattern, callable $replacement, $subject, int $limit = -1, ?int &$count = null, int $flags = 0): string
    {
        return self::replaceCallback($pattern, function (array $matches) use ($pattern, $replacement) {
            return $replacement(self::enforceNonNullMatches($pattern, $matches, 'replaceCallback'));
        }, $subject, $limit, $count, $flags);
    }
    /**
     * @param ($flags is PREG_OFFSET_CAPTURE ? (array<string, callable(array<int|string, array{string|null, int<-1, max>}>): string>) : array<string, callable(array<int|string, string|null>): string>) $pattern
     * @param string $subject
     * @param int    $count Set by method
     * @param int-mask<PREG_UNMATCHED_AS_NULL|PREG_OFFSET_CAPTURE> $flags PREG_OFFSET_CAPTURE is supported, PREG_UNMATCHED_AS_NULL is always set
     *
     * @param-out int<0, max> $count
     */
    public static function replaceCallbackArray(array $pattern, $subject, int $limit = -1, ?int &$count = null, int $flags = 0): string
    {
        if (!is_scalar($subject)) {
            if (is_array($subject)) {
                throw new \InvalidArgumentException(static::ARRAY_MSG);
            }
            throw new \TypeError(sprintf(static::INVALID_TYPE_MSG, gettype($subject)));
        }
        $result = preg_replace_callback_array($pattern, $subject, $limit, $count, $flags | \PREG_UNMATCHED_AS_NULL);
        if ($result === null) {
            $pattern = array_keys($pattern);
            throw \Composer\Pcre\PcreException::fromFunction('preg_replace_callback_array', $pattern);
        }
        return $result;
    }
    /**
     * @param int-mask<PREG_SPLIT_NO_EMPTY|PREG_SPLIT_DELIM_CAPTURE|PREG_SPLIT_OFFSET_CAPTURE> $flags PREG_SPLIT_NO_EMPTY or PREG_SPLIT_DELIM_CAPTURE
     * @return list<string>
     */
    public static function split(string $pattern, string $subject, int $limit = -1, int $flags = 0): array
    {
        if (($flags & \PREG_SPLIT_OFFSET_CAPTURE) !== 0) {
            throw new \InvalidArgumentException('PREG_SPLIT_OFFSET_CAPTURE is not supported as it changes the type of $matches, use splitWithOffsets() instead');
        }
        $result = preg_split($pattern, $subject, $limit, $flags);
        if ($result === \false) {
            throw \Composer\Pcre\PcreException::fromFunction('preg_split', $pattern);
        }
        return $result;
    }
    /**
     * @param int-mask<PREG_SPLIT_NO_EMPTY|PREG_SPLIT_DELIM_CAPTURE|PREG_SPLIT_OFFSET_CAPTURE> $flags PREG_SPLIT_NO_EMPTY or PREG_SPLIT_DELIM_CAPTURE, PREG_SPLIT_OFFSET_CAPTURE is always set
     * @return list<array{string, int}>
     * @phpstan-return list<array{string, int<0, max>}>
     */
    public static function splitWithOffsets(string $pattern, string $subject, int $limit = -1, int $flags = 0): array
    {
        $result = preg_split($pattern, $subject, $limit, $flags | \PREG_SPLIT_OFFSET_CAPTURE);
        if ($result === \false) {
            throw \Composer\Pcre\PcreException::fromFunction('preg_split', $pattern);
        }
        return $result;
    }
    /**
     * @template T of string|\Stringable
     * @param string   $pattern
     * @param array<T> $array
     * @param int-mask<PREG_GREP_INVERT> $flags PREG_GREP_INVERT
     * @return array<T>
     */
    public static function grep(string $pattern, array $array, int $flags = 0): array
    {
        $result = preg_grep($pattern, $array, $flags);
        if ($result === \false) {
            throw \Composer\Pcre\PcreException::fromFunction('preg_grep', $pattern);
        }
        return $result;
    }
    /**
     * Variant of match() which returns a bool instead of int
     *
     * @param non-empty-string   $pattern
     * @param array<mixed> $matches Set by method
     * @param int-mask<PREG_UNMATCHED_AS_NULL> $flags PREG_UNMATCHED_AS_NULL is always set, no other flags are supported
     *
     * @param-out array<int|string, string|null> $matches
     */
    public static function isMatch(string $pattern, string $subject, ?array &$matches = null, int $flags = 0, int $offset = 0): bool
    {
        return (bool) static::match($pattern, $subject, $matches, $flags, $offset);
    }
    /**
     * Variant of `isMatch()` which outputs non-null matches (or throws)
     *
     * @param non-empty-string $pattern
     * @param array<mixed> $matches Set by method
     * @param int-mask<PREG_UNMATCHED_AS_NULL> $flags PREG_UNMATCHED_AS_NULL is always set, no other flags are supported
     * @throws UnexpectedNullMatchException
     *
     * @param-out array<int|string, string> $matches
     */
    public static function isMatchStrictGroups(string $pattern, string $subject, ?array &$matches = null, int $flags = 0, int $offset = 0): bool
    {
        return (bool) self::matchStrictGroups($pattern, $subject, $matches, $flags, $offset);
    }
    /**
     * Variant of matchAll() which returns a bool instead of int
     *
     * @param non-empty-string   $pattern
     * @param array<mixed> $matches Set by method
     * @param int-mask<PREG_UNMATCHED_AS_NULL> $flags PREG_UNMATCHED_AS_NULL is always set, no other flags are supported
     *
     * @param-out array<int|string, list<string|null>> $matches
     */
    public static function isMatchAll(string $pattern, string $subject, ?array &$matches = null, int $flags = 0, int $offset = 0): bool
    {
        return (bool) static::matchAll($pattern, $subject, $matches, $flags, $offset);
    }
    /**
     * Variant of `isMatchAll()` which outputs non-null matches (or throws)
     *
     * @param non-empty-string $pattern
     * @param array<mixed> $matches Set by method
     * @param int-mask<PREG_UNMATCHED_AS_NULL> $flags PREG_UNMATCHED_AS_NULL is always set, no other flags are supported
     *
     * @param-out array<int|string, list<string>> $matches
     */
    public static function isMatchAllStrictGroups(string $pattern, string $subject, ?array &$matches = null, int $flags = 0, int $offset = 0): bool
    {
        return (bool) self::matchAllStrictGroups($pattern, $subject, $matches, $flags, $offset);
    }
    /**
     * Variant of matchWithOffsets() which returns a bool instead of int
     *
     * Runs preg_match with PREG_OFFSET_CAPTURE
     *
     * @param non-empty-string   $pattern
     * @param array<mixed> $matches Set by method
     * @param int-mask<PREG_UNMATCHED_AS_NULL> $flags PREG_UNMATCHED_AS_NULL is always set, no other flags are supported
     *
     * @param-out array<int|string, array{string|null, int<-1, max>}> $matches
     */
    public static function isMatchWithOffsets(string $pattern, string $subject, ?array &$matches, int $flags = 0, int $offset = 0): bool
    {
        return (bool) static::matchWithOffsets($pattern, $subject, $matches, $flags, $offset);
    }
    /**
     * Variant of matchAllWithOffsets() which returns a bool instead of int
     *
     * Runs preg_match_all with PREG_OFFSET_CAPTURE
     *
     * @param non-empty-string   $pattern
     * @param array<mixed> $matches Set by method
     * @param int-mask<PREG_UNMATCHED_AS_NULL> $flags PREG_UNMATCHED_AS_NULL is always set, no other flags are supported
     *
     * @param-out array<int|string, list<array{string|null, int<-1, max>}>> $matches
     */
    public static function isMatchAllWithOffsets(string $pattern, string $subject, ?array &$matches, int $flags = 0, int $offset = 0): bool
    {
        return (bool) static::matchAllWithOffsets($pattern, $subject, $matches, $flags, $offset);
    }
    private static function checkOffsetCapture(int $flags, string $useFunctionName): void
    {
        if (($flags & \PREG_OFFSET_CAPTURE) !== 0) {
            throw new \InvalidArgumentException('PREG_OFFSET_CAPTURE is not supported as it changes the type of $matches, use ' . $useFunctionName . '() instead');
        }
    }
    private static function checkSetOrder(int $flags): void
    {
        if (($flags & \PREG_SET_ORDER) !== 0) {
            throw new \InvalidArgumentException('PREG_SET_ORDER is not supported as it changes the type of $matches');
        }
    }
    /**
     * @param array<int|string, string|null|array{string|null, int}> $matches
     * @return array<int|string, string>
     * @throws UnexpectedNullMatchException
     */
    private static function enforceNonNullMatches(string $pattern, array $matches, string $variantMethod)
    {
        foreach ($matches as $group => $match) {
            if (is_string($match) || is_array($match) && is_string($match[0])) {
                continue;
            }
            throw new \Composer\Pcre\UnexpectedNullMatchException('Pattern "' . $pattern . '" had an unexpected unmatched group "' . $group . '", make sure the pattern always matches or use ' . $variantMethod . '() instead.');
        }
        /** @var array<string> */
        return $matches;
    }
    /**
     * @param array<int|string, list<string|null>> $matches
     * @return array<int|string, list<string>>
     * @throws UnexpectedNullMatchException
     */
    private static function enforceNonNullMatchAll(string $pattern, array $matches, string $variantMethod)
    {
        foreach ($matches as $group => $groupMatches) {
            foreach ($groupMatches as $match) {
                if (null === $match) {
                    throw new \Composer\Pcre\UnexpectedNullMatchException('Pattern "' . $pattern . '" had an unexpected unmatched group "' . $group . '", make sure the pattern always matches or use ' . $variantMethod . '() instead.');
                }
            }
        }
        /** @var array<int|string, list<string>> */
        return $matches;
    }
}
<?php

/*
 * This file is part of composer/pcre.
 *
 * (c) Composer <https://github.com/composer>
 *
 * For the full copyright and license information, please view
 * the LICENSE file that was distributed with this source code.
 */
namespace Composer\Pcre;

class PcreException extends \RuntimeException
{
    /**
     * @param  string $function
     * @param  string|string[] $pattern
     * @return self
     */
    public static function fromFunction($function, $pattern)
    {
        $code = preg_last_error();
        if (is_array($pattern)) {
            $pattern = implode(', ', $pattern);
        }
        return new \Composer\Pcre\PcreException($function . '(): failed executing "' . $pattern . '": ' . self::pcreLastErrorMessage($code), $code);
    }
    /**
     * @param  int $code
     * @return string
     */
    private static function pcreLastErrorMessage($code)
    {
        if (function_exists('preg_last_error_msg')) {
            return preg_last_error_msg();
        }
        $constants = get_defined_constants(\true);
        if (!isset($constants['pcre']) || !is_array($constants['pcre'])) {
            return 'UNDEFINED_ERROR';
        }
        foreach ($constants['pcre'] as $const => $val) {
            if ($val === $code && substr($const, -6) === '_ERROR') {
                return $const;
            }
        }
        return 'UNDEFINED_ERROR';
    }
}
Copyright (C) 2021 Composer

Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
composer/metadata-minifier
==========================

Small utility library that handles metadata minification and expansion.

This is used by [Composer](https://github.com/composer/composer)'s 2.x repository metadata protocol.


Installation
------------

Install the latest version with:

```bash
$ composer require composer/metadata-minifier
```


Requirements
------------

* PHP 5.3.2 is required but using the latest version of PHP is highly recommended.


Basic usage
-----------

### `Composer\MetadataMinifier\MetadataMinifier`

- `MetadataMinifier::expand()`: Expands an array of minified versions back to their original format
- `MetadataMinifier::minify()`: Minifies an array of versions into a set of version diffs


License
-------

composer/metadata-minifier is licensed under the MIT License, see the LICENSE file for details.
parameters:
    level: 8
    paths:
        - src
        - tests
{
    "name": "composer\/metadata-minifier",
    "description": "Small utility library that handles metadata minification and expansion.",
    "type": "library",
    "license": "MIT",
    "keywords": [
        "compression",
        "composer"
    ],
    "authors": [
        {
            "name": "Jordi Boggiano",
            "email": "j.boggiano@seld.be",
            "homepage": "http:\/\/seld.be"
        }
    ],
    "support": {
        "issues": "https:\/\/github.com\/composer\/metadata-minifier\/issues"
    },
    "require": {
        "php": "^5.3.2 || ^7.0 || ^8.0"
    },
    "require-dev": {
        "symfony\/phpunit-bridge": "^4.2 || ^5",
        "phpstan\/phpstan": "^0.12.55",
        "composer\/composer": "^2"
    },
    "autoload": {
        "psr-4": {
            "Composer\\MetadataMinifier\\": "src"
        }
    },
    "autoload-dev": {
        "psr-4": {
            "Composer\\Test\\MetadataMinifier\\": "tests"
        }
    },
    "extra": {
        "branch-alias": {
            "dev-main": "1.x-dev"
        }
    },
    "scripts": {
        "test": "SYMFONY_PHPUNIT_REMOVE_RETURN_TYPEHINT=1 vendor\/bin\/simple-phpunit",
        "phpstan": "vendor\/bin\/phpstan analyse"
    }
}<?php

/*
 * This file is part of composer/metadata-minifier.
 *
 * (c) Composer <https://github.com/composer>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Composer\MetadataMinifier;

class MetadataMinifier
{
    /**
     * Expands an array of minified versions back to their original format
     *
     * @param array[] $versions A list of minified version arrays
     * @return array[] A list of version arrays
     */
    public static function expand(array $versions)
    {
        $expanded = array();
        $expandedVersion = null;
        foreach ($versions as $versionData) {
            if (!$expandedVersion) {
                $expandedVersion = $versionData;
                $expanded[] = $expandedVersion;
                continue;
            }
            // add any changes from the previous version to the expanded one
            foreach ($versionData as $key => $val) {
                if ($val === '__unset') {
                    unset($expandedVersion[$key]);
                } else {
                    $expandedVersion[$key] = $val;
                }
            }
            $expanded[] = $expandedVersion;
        }
        return $expanded;
    }
    /**
     * Minifies an array of versions into a set of version diffs
     *
     * @param array[] $versions A list of version arrays
     * @return array[] A list of versions minified with each array only containing the differences to the previous one
     */
    public static function minify(array $versions)
    {
        $minifiedVersions = array();
        $lastKnownVersionData = null;
        foreach ($versions as $version) {
            if (!$lastKnownVersionData) {
                $lastKnownVersionData = $version;
                $minifiedVersions[] = $version;
                continue;
            }
            $minifiedVersion = array();
            // add any changes from the previous version
            foreach ($version as $key => $val) {
                if (!isset($lastKnownVersionData[$key]) || $lastKnownVersionData[$key] !== $val) {
                    $minifiedVersion[$key] = $val;
                    $lastKnownVersionData[$key] = $val;
                }
            }
            // store any deletions from the previous version for keys missing in current one
            foreach ($lastKnownVersionData as $key => $val) {
                if (!isset($version[$key])) {
                    $minifiedVersion[$key] = "__unset";
                    unset($lastKnownVersionData[$key]);
                }
            }
            $minifiedVersions[] = $minifiedVersion;
        }
        return $minifiedVersions;
    }
}
{
    "389-exception": [
        "389 Directory Server Exception"
    ],
    "Asterisk-exception": [
        "Asterisk exception"
    ],
    "Asterisk-linking-protocols-exception": [
        "Asterisk linking protocols exception"
    ],
    "Autoconf-exception-2.0": [
        "Autoconf exception 2.0"
    ],
    "Autoconf-exception-3.0": [
        "Autoconf exception 3.0"
    ],
    "Autoconf-exception-generic": [
        "Autoconf generic exception"
    ],
    "Autoconf-exception-generic-3.0": [
        "Autoconf generic exception for GPL-3.0"
    ],
    "Autoconf-exception-macro": [
        "Autoconf macro exception"
    ],
    "Bison-exception-1.24": [
        "Bison exception 1.24"
    ],
    "Bison-exception-2.2": [
        "Bison exception 2.2"
    ],
    "Bootloader-exception": [
        "Bootloader Distribution Exception"
    ],
    "CGAL-linking-exception": [
        "CGAL Linking Exception"
    ],
    "Classpath-exception-2.0": [
        "Classpath exception 2.0"
    ],
    "Classpath-exception-2.0-short": [
        "Classpath exception 2.0 - short"
    ],
    "CLISP-exception-2.0": [
        "CLISP exception 2.0"
    ],
    "cryptsetup-OpenSSL-exception": [
        "cryptsetup OpenSSL exception"
    ],
    "Digia-Qt-LGPL-exception-1.1": [
        "Digia Qt LGPL Exception version 1.1"
    ],
    "DigiRule-FOSS-exception": [
        "DigiRule FOSS License Exception"
    ],
    "eCos-exception-2.0": [
        "eCos exception 2.0"
    ],
    "erlang-otp-linking-exception": [
        "Erlang/OTP Linking Exception"
    ],
    "Fawkes-Runtime-exception": [
        "Fawkes Runtime Exception"
    ],
    "FLTK-exception": [
        "FLTK exception"
    ],
    "fmt-exception": [
        "fmt exception"
    ],
    "Font-exception-2.0": [
        "Font exception 2.0"
    ],
    "freertos-exception-2.0": [
        "FreeRTOS Exception 2.0"
    ],
    "GCC-exception-2.0": [
        "GCC Runtime Library exception 2.0"
    ],
    "GCC-exception-2.0-note": [
        "GCC    Runtime Library exception 2.0 - note variant"
    ],
    "GCC-exception-3.1": [
        "GCC Runtime Library exception 3.1"
    ],
    "Gmsh-exception": [
        "Gmsh exception"
    ],
    "GNAT-exception": [
        "GNAT exception"
    ],
    "GNOME-examples-exception": [
        "GNOME examples exception"
    ],
    "GNU-compiler-exception": [
        "GNU Compiler Exception"
    ],
    "gnu-javamail-exception": [
        "GNU JavaMail exception"
    ],
    "GPL-3.0-389-ds-base-exception": [
        "GPL-3.0 389 DS Base Exception"
    ],
    "GPL-3.0-interface-exception": [
        "GPL-3.0 Interface Exception"
    ],
    "GPL-3.0-linking-exception": [
        "GPL-3.0 Linking Exception"
    ],
    "GPL-3.0-linking-source-exception": [
        "GPL-3.0 Linking Exception (with Corresponding Source)"
    ],
    "GPL-CC-1.0": [
        "GPL Cooperation Commitment 1.0"
    ],
    "GStreamer-exception-2005": [
        "GStreamer Exception (2005)"
    ],
    "GStreamer-exception-2008": [
        "GStreamer Exception (2008)"
    ],
    "harbour-exception": [
        "harbour exception"
    ],
    "i2p-gpl-java-exception": [
        "i2p GPL+Java Exception"
    ],
    "Independent-modules-exception": [
        "Independent Module Linking exception"
    ],
    "KiCad-libraries-exception": [
        "KiCad Libraries Exception"
    ],
    "kvirc-openssl-exception": [
        "kvirc OpenSSL Exception"
    ],
    "LGPL-3.0-linking-exception": [
        "LGPL-3.0 Linking Exception"
    ],
    "libpri-OpenH323-exception": [
        "libpri OpenH323 exception"
    ],
    "Libtool-exception": [
        "Libtool Exception"
    ],
    "Linux-syscall-note": [
        "Linux Syscall Note"
    ],
    "LLGPL": [
        "LLGPL Preamble"
    ],
    "LLVM-exception": [
        "LLVM Exception"
    ],
    "LZMA-exception": [
        "LZMA exception"
    ],
    "mif-exception": [
        "Macros and Inline Functions Exception"
    ],
    "mxml-exception": [
        "mxml Exception"
    ],
    "Nokia-Qt-exception-1.1": [
        "Nokia Qt LGPL exception 1.1"
    ],
    "OCaml-LGPL-linking-exception": [
        "OCaml LGPL Linking Exception"
    ],
    "OCCT-exception-1.0": [
        "Open CASCADE Exception 1.0"
    ],
    "OpenJDK-assembly-exception-1.0": [
        "OpenJDK Assembly exception 1.0"
    ],
    "openvpn-openssl-exception": [
        "OpenVPN OpenSSL Exception"
    ],
    "PCRE2-exception": [
        "PCRE2 exception"
    ],
    "polyparse-exception": [
        "Polyparse Exception"
    ],
    "PS-or-PDF-font-exception-20170817": [
        "PS/PDF font exception (2017-08-17)"
    ],
    "QPL-1.0-INRIA-2004-exception": [
        "INRIA QPL 1.0 2004 variant exception"
    ],
    "Qt-GPL-exception-1.0": [
        "Qt GPL exception 1.0"
    ],
    "Qt-LGPL-exception-1.1": [
        "Qt LGPL exception 1.1"
    ],
    "Qwt-exception-1.0": [
        "Qwt exception 1.0"
    ],
    "romic-exception": [
        "Romic Exception"
    ],
    "RRDtool-FLOSS-exception-2.0": [
        "RRDtool FLOSS exception 2.0"
    ],
    "rsync-linking-exception": [
        "rsync Linking Exception"
    ],
    "SANE-exception": [
        "SANE Exception"
    ],
    "SHL-2.0": [
        "Solderpad Hardware License v2.0"
    ],
    "SHL-2.1": [
        "Solderpad Hardware License v2.1"
    ],
    "Simple-Library-Usage-exception": [
        "Simple Library Usage Exception"
    ],
    "sqlitestudio-OpenSSL-exception": [
        "sqlitestudio OpenSSL exception"
    ],
    "stunnel-exception": [
        "stunnel Exception"
    ],
    "SWI-exception": [
        "SWI exception"
    ],
    "Swift-exception": [
        "Swift Exception"
    ],
    "Texinfo-exception": [
        "Texinfo exception"
    ],
    "u-boot-exception-2.0": [
        "U-Boot exception 2.0"
    ],
    "UBDL-exception": [
        "Unmodified Binary Distribution exception"
    ],
    "Universal-FOSS-exception-1.0": [
        "Universal FOSS Exception, Version 1.0"
    ],
    "vsftpd-openssl-exception": [
        "vsftpd OpenSSL exception"
    ],
    "WxWindows-exception-3.1": [
        "WxWindows Library Exception 3.1"
    ],
    "x11vnc-openssl-exception": [
        "x11vnc OpenSSL Exception"
    ]
}{
    "0BSD": [
        "BSD Zero Clause License",
        true,
        false
    ],
    "3D-Slicer-1.0": [
        "3D Slicer License v1.0",
        false,
        false
    ],
    "AAL": [
        "Attribution Assurance License",
        true,
        false
    ],
    "Abstyles": [
        "Abstyles License",
        false,
        false
    ],
    "AdaCore-doc": [
        "AdaCore Doc License",
        false,
        false
    ],
    "Adobe-2006": [
        "Adobe Systems Incorporated Source Code License Agreement",
        false,
        false
    ],
    "Adobe-Display-PostScript": [
        "Adobe Display PostScript License",
        false,
        false
    ],
    "Adobe-Glyph": [
        "Adobe Glyph List License",
        false,
        false
    ],
    "Adobe-Utopia": [
        "Adobe Utopia Font License",
        false,
        false
    ],
    "ADSL": [
        "Amazon Digital Services License",
        false,
        false
    ],
    "Advanced-Cryptics-Dictionary": [
        "Advanced Cryptics Dictionary License",
        false,
        false
    ],
    "AFL-1.1": [
        "Academic Free License v1.1",
        true,
        false
    ],
    "AFL-1.2": [
        "Academic Free License v1.2",
        true,
        false
    ],
    "AFL-2.0": [
        "Academic Free License v2.0",
        true,
        false
    ],
    "AFL-2.1": [
        "Academic Free License v2.1",
        true,
        false
    ],
    "AFL-3.0": [
        "Academic Free License v3.0",
        true,
        false
    ],
    "Afmparse": [
        "Afmparse License",
        false,
        false
    ],
    "AGPL-1.0": [
        "Affero General Public License v1.0",
        false,
        true
    ],
    "AGPL-1.0-only": [
        "Affero General Public License v1.0 only",
        false,
        false
    ],
    "AGPL-1.0-or-later": [
        "Affero General Public License v1.0 or later",
        false,
        false
    ],
    "AGPL-3.0": [
        "GNU Affero General Public License v3.0",
        true,
        true
    ],
    "AGPL-3.0-only": [
        "GNU Affero General Public License v3.0 only",
        true,
        false
    ],
    "AGPL-3.0-or-later": [
        "GNU Affero General Public License v3.0 or later",
        true,
        false
    ],
    "Aladdin": [
        "Aladdin Free Public License",
        false,
        false
    ],
    "ALGLIB-Documentation": [
        "ALGLIB Documentation License",
        true,
        false
    ],
    "AMD-newlib": [
        "AMD newlib License",
        false,
        false
    ],
    "AMDPLPA": [
        "AMD's plpa_map.c License",
        false,
        false
    ],
    "AML": [
        "Apple MIT License",
        false,
        false
    ],
    "AML-glslang": [
        "AML glslang variant License",
        false,
        false
    ],
    "AMPAS": [
        "Academy of Motion Picture Arts and Sciences BSD",
        false,
        false
    ],
    "ANTLR-PD": [
        "ANTLR Software Rights Notice",
        false,
        false
    ],
    "ANTLR-PD-fallback": [
        "ANTLR Software Rights Notice with license fallback",
        false,
        false
    ],
    "any-OSI": [
        "Any OSI License",
        false,
        false
    ],
    "any-OSI-perl-modules": [
        "Any OSI License - Perl Modules",
        false,
        false
    ],
    "Apache-1.0": [
        "Apache License 1.0",
        false,
        false
    ],
    "Apache-1.1": [
        "Apache License 1.1",
        true,
        false
    ],
    "Apache-2.0": [
        "Apache License 2.0",
        true,
        false
    ],
    "APAFML": [
        "Adobe Postscript AFM License",
        false,
        false
    ],
    "APL-1.0": [
        "Adaptive Public License 1.0",
        true,
        false
    ],
    "App-s2p": [
        "App::s2p License",
        false,
        false
    ],
    "APSL-1.0": [
        "Apple Public Source License 1.0",
        true,
        false
    ],
    "APSL-1.1": [
        "Apple Public Source License 1.1",
        true,
        false
    ],
    "APSL-1.2": [
        "Apple Public Source License 1.2",
        true,
        false
    ],
    "APSL-2.0": [
        "Apple Public Source License 2.0",
        true,
        false
    ],
    "Arphic-1999": [
        "Arphic Public License",
        false,
        false
    ],
    "Artistic-1.0": [
        "Artistic License 1.0",
        true,
        false
    ],
    "Artistic-1.0-cl8": [
        "Artistic License 1.0 w/clause 8",
        true,
        false
    ],
    "Artistic-1.0-Perl": [
        "Artistic License 1.0 (Perl)",
        true,
        false
    ],
    "Artistic-2.0": [
        "Artistic License 2.0",
        true,
        false
    ],
    "Artistic-dist": [
        "Artistic License 1.0 (dist)",
        false,
        false
    ],
    "Aspell-RU": [
        "Aspell Russian License",
        false,
        false
    ],
    "ASWF-Digital-Assets-1.0": [
        "ASWF Digital Assets License version 1.0",
        false,
        false
    ],
    "ASWF-Digital-Assets-1.1": [
        "ASWF Digital Assets License 1.1",
        false,
        false
    ],
    "Baekmuk": [
        "Baekmuk License",
        false,
        false
    ],
    "Bahyph": [
        "Bahyph License",
        false,
        false
    ],
    "Barr": [
        "Barr License",
        false,
        false
    ],
    "bcrypt-Solar-Designer": [
        "bcrypt Solar Designer License",
        false,
        false
    ],
    "Beerware": [
        "Beerware License",
        false,
        false
    ],
    "Bitstream-Charter": [
        "Bitstream Charter Font License",
        false,
        false
    ],
    "Bitstream-Vera": [
        "Bitstream Vera Font License",
        false,
        false
    ],
    "BitTorrent-1.0": [
        "BitTorrent Open Source License v1.0",
        false,
        false
    ],
    "BitTorrent-1.1": [
        "BitTorrent Open Source License v1.1",
        false,
        false
    ],
    "blessing": [
        "SQLite Blessing",
        false,
        false
    ],
    "BlueOak-1.0.0": [
        "Blue Oak Model License 1.0.0",
        true,
        false
    ],
    "Boehm-GC": [
        "Boehm-Demers-Weiser GC License",
        false,
        false
    ],
    "Boehm-GC-without-fee": [
        "Boehm-Demers-Weiser GC License (without fee)",
        false,
        false
    ],
    "BOLA-1.1": [
        "Buena Onda License Agreement v1.1",
        false,
        false
    ],
    "Borceux": [
        "Borceux license",
        false,
        false
    ],
    "Brian-Gladman-2-Clause": [
        "Brian Gladman 2-Clause License",
        false,
        false
    ],
    "Brian-Gladman-3-Clause": [
        "Brian Gladman 3-Clause License",
        false,
        false
    ],
    "BSD-1-Clause": [
        "BSD 1-Clause License",
        true,
        false
    ],
    "BSD-2-Clause": [
        "BSD 2-Clause \"Simplified\" License",
        true,
        false
    ],
    "BSD-2-Clause-Darwin": [
        "BSD 2-Clause - Ian Darwin variant",
        false,
        false
    ],
    "BSD-2-Clause-first-lines": [
        "BSD 2-Clause - first lines requirement",
        false,
        false
    ],
    "BSD-2-Clause-FreeBSD": [
        "BSD 2-Clause FreeBSD License",
        false,
        true
    ],
    "BSD-2-Clause-NetBSD": [
        "BSD 2-Clause NetBSD License",
        false,
        true
    ],
    "BSD-2-Clause-Patent": [
        "BSD-2-Clause Plus Patent License",
        true,
        false
    ],
    "BSD-2-Clause-pkgconf-disclaimer": [
        "BSD 2-Clause pkgconf disclaimer variant",
        false,
        false
    ],
    "BSD-2-Clause-Views": [
        "BSD 2-Clause with views sentence",
        false,
        false
    ],
    "BSD-3-Clause": [
        "BSD 3-Clause \"New\" or \"Revised\" License",
        true,
        false
    ],
    "BSD-3-Clause-acpica": [
        "BSD 3-Clause acpica variant",
        false,
        false
    ],
    "BSD-3-Clause-Attribution": [
        "BSD with attribution",
        false,
        false
    ],
    "BSD-3-Clause-Clear": [
        "BSD 3-Clause Clear License",
        false,
        false
    ],
    "BSD-3-Clause-flex": [
        "BSD 3-Clause Flex variant",
        false,
        false
    ],
    "BSD-3-Clause-HP": [
        "Hewlett-Packard BSD variant license",
        false,
        false
    ],
    "BSD-3-Clause-LBNL": [
        "Lawrence Berkeley National Labs BSD variant license",
        true,
        false
    ],
    "BSD-3-Clause-Modification": [
        "BSD 3-Clause Modification",
        false,
        false
    ],
    "BSD-3-Clause-No-Military-License": [
        "BSD 3-Clause No Military License",
        false,
        false
    ],
    "BSD-3-Clause-No-Nuclear-License": [
        "BSD 3-Clause No Nuclear License",
        false,
        false
    ],
    "BSD-3-Clause-No-Nuclear-License-2014": [
        "BSD 3-Clause No Nuclear License 2014",
        false,
        false
    ],
    "BSD-3-Clause-No-Nuclear-Warranty": [
        "BSD 3-Clause No Nuclear Warranty",
        false,
        false
    ],
    "BSD-3-Clause-Open-MPI": [
        "BSD 3-Clause Open MPI variant",
        true,
        false
    ],
    "BSD-3-Clause-Sun": [
        "BSD 3-Clause Sun Microsystems",
        false,
        false
    ],
    "BSD-3-Clause-Tso": [
        "BSD 3-Clause Tso variant",
        false,
        false
    ],
    "BSD-4-Clause": [
        "BSD 4-Clause \"Original\" or \"Old\" License",
        false,
        false
    ],
    "BSD-4-Clause-Shortened": [
        "BSD 4 Clause Shortened",
        false,
        false
    ],
    "BSD-4-Clause-UC": [
        "BSD-4-Clause (University of California-Specific)",
        false,
        false
    ],
    "BSD-4.3RENO": [
        "BSD 4.3 RENO License",
        false,
        false
    ],
    "BSD-4.3TAHOE": [
        "BSD 4.3 TAHOE License",
        false,
        false
    ],
    "BSD-Advertising-Acknowledgement": [
        "BSD Advertising Acknowledgement License",
        false,
        false
    ],
    "BSD-Attribution-HPND-disclaimer": [
        "BSD with Attribution and HPND disclaimer",
        false,
        false
    ],
    "BSD-Inferno-Nettverk": [
        "BSD-Inferno-Nettverk",
        false,
        false
    ],
    "BSD-Mark-Modifications": [
        "BSD Mark Modifications License",
        false,
        false
    ],
    "BSD-Protection": [
        "BSD Protection License",
        false,
        false
    ],
    "BSD-Source-beginning-file": [
        "BSD Source Code Attribution - beginning of file variant",
        false,
        false
    ],
    "BSD-Source-Code": [
        "BSD Source Code Attribution",
        false,
        false
    ],
    "BSD-Systemics": [
        "Systemics BSD variant license",
        false,
        false
    ],
    "BSD-Systemics-W3Works": [
        "Systemics W3Works BSD variant license",
        false,
        false
    ],
    "BSL-1.0": [
        "Boost Software License 1.0",
        true,
        false
    ],
    "Buddy": [
        "Buddy License",
        false,
        false
    ],
    "BUSL-1.1": [
        "Business Source License 1.1",
        false,
        false
    ],
    "bzip2-1.0.5": [
        "bzip2 and libbzip2 License v1.0.5",
        false,
        true
    ],
    "bzip2-1.0.6": [
        "bzip2 and libbzip2 License v1.0.6",
        false,
        false
    ],
    "C-UDA-1.0": [
        "Computational Use of Data Agreement v1.0",
        false,
        false
    ],
    "CAL-1.0": [
        "Cryptographic Autonomy License 1.0",
        true,
        false
    ],
    "CAL-1.0-Combined-Work-Exception": [
        "Cryptographic Autonomy License 1.0 (Combined Work Exception)",
        true,
        false
    ],
    "Caldera": [
        "Caldera License",
        false,
        false
    ],
    "Caldera-no-preamble": [
        "Caldera License (without preamble)",
        false,
        false
    ],
    "CAPEC-tou": [
        "Common Attack    Pattern Enumeration and Classification License",
        false,
        false
    ],
    "Catharon": [
        "Catharon License",
        false,
        false
    ],
    "CATOSL-1.1": [
        "Computer Associates Trusted Open Source License 1.1",
        true,
        false
    ],
    "CC-BY-1.0": [
        "Creative Commons Attribution 1.0 Generic",
        false,
        false
    ],
    "CC-BY-2.0": [
        "Creative Commons Attribution 2.0 Generic",
        false,
        false
    ],
    "CC-BY-2.5": [
        "Creative Commons Attribution 2.5 Generic",
        false,
        false
    ],
    "CC-BY-2.5-AU": [
        "Creative Commons Attribution 2.5 Australia",
        false,
        false
    ],
    "CC-BY-3.0": [
        "Creative Commons Attribution 3.0 Unported",
        false,
        false
    ],
    "CC-BY-3.0-AT": [
        "Creative Commons Attribution 3.0 Austria",
        false,
        false
    ],
    "CC-BY-3.0-AU": [
        "Creative Commons Attribution 3.0 Australia",
        false,
        false
    ],
    "CC-BY-3.0-DE": [
        "Creative Commons Attribution 3.0 Germany",
        false,
        false
    ],
    "CC-BY-3.0-IGO": [
        "Creative Commons Attribution 3.0 IGO",
        false,
        false
    ],
    "CC-BY-3.0-NL": [
        "Creative Commons Attribution 3.0 Netherlands",
        false,
        false
    ],
    "CC-BY-3.0-US": [
        "Creative Commons Attribution 3.0 United States",
        false,
        false
    ],
    "CC-BY-4.0": [
        "Creative Commons Attribution 4.0 International",
        false,
        false
    ],
    "CC-BY-NC-1.0": [
        "Creative Commons Attribution Non Commercial 1.0 Generic",
        false,
        false
    ],
    "CC-BY-NC-2.0": [
        "Creative Commons Attribution Non Commercial 2.0 Generic",
        false,
        false
    ],
    "CC-BY-NC-2.5": [
        "Creative Commons Attribution Non Commercial 2.5 Generic",
        false,
        false
    ],
    "CC-BY-NC-3.0": [
        "Creative Commons Attribution Non Commercial 3.0 Unported",
        false,
        false
    ],
    "CC-BY-NC-3.0-DE": [
        "Creative Commons Attribution Non Commercial 3.0 Germany",
        false,
        false
    ],
    "CC-BY-NC-4.0": [
        "Creative Commons Attribution Non Commercial 4.0 International",
        false,
        false
    ],
    "CC-BY-NC-ND-1.0": [
        "Creative Commons Attribution Non Commercial No Derivatives 1.0 Generic",
        false,
        false
    ],
    "CC-BY-NC-ND-2.0": [
        "Creative Commons Attribution Non Commercial No Derivatives 2.0 Generic",
        false,
        false
    ],
    "CC-BY-NC-ND-2.5": [
        "Creative Commons Attribution Non Commercial No Derivatives 2.5 Generic",
        false,
        false
    ],
    "CC-BY-NC-ND-3.0": [
        "Creative Commons Attribution Non Commercial No Derivatives 3.0 Unported",
        false,
        false
    ],
    "CC-BY-NC-ND-3.0-DE": [
        "Creative Commons Attribution Non Commercial No Derivatives 3.0 Germany",
        false,
        false
    ],
    "CC-BY-NC-ND-3.0-IGO": [
        "Creative Commons Attribution Non Commercial No Derivatives 3.0 IGO",
        false,
        false
    ],
    "CC-BY-NC-ND-4.0": [
        "Creative Commons Attribution Non Commercial No Derivatives 4.0 International",
        false,
        false
    ],
    "CC-BY-NC-SA-1.0": [
        "Creative Commons Attribution Non Commercial Share Alike 1.0 Generic",
        false,
        false
    ],
    "CC-BY-NC-SA-2.0": [
        "Creative Commons Attribution Non Commercial Share Alike 2.0 Generic",
        false,
        false
    ],
    "CC-BY-NC-SA-2.0-DE": [
        "Creative Commons Attribution Non Commercial Share Alike 2.0 Germany",
        false,
        false
    ],
    "CC-BY-NC-SA-2.0-FR": [
        "Creative Commons Attribution-NonCommercial-ShareAlike 2.0 France",
        false,
        false
    ],
    "CC-BY-NC-SA-2.0-UK": [
        "Creative Commons Attribution Non Commercial Share Alike 2.0 England and Wales",
        false,
        false
    ],
    "CC-BY-NC-SA-2.5": [
        "Creative Commons Attribution Non Commercial Share Alike 2.5 Generic",
        false,
        false
    ],
    "CC-BY-NC-SA-3.0": [
        "Creative Commons Attribution Non Commercial Share Alike 3.0 Unported",
        false,
        false
    ],
    "CC-BY-NC-SA-3.0-DE": [
        "Creative Commons Attribution Non Commercial Share Alike 3.0 Germany",
        false,
        false
    ],
    "CC-BY-NC-SA-3.0-IGO": [
        "Creative Commons Attribution Non Commercial Share Alike 3.0 IGO",
        false,
        false
    ],
    "CC-BY-NC-SA-4.0": [
        "Creative Commons Attribution Non Commercial Share Alike 4.0 International",
        false,
        false
    ],
    "CC-BY-ND-1.0": [
        "Creative Commons Attribution No Derivatives 1.0 Generic",
        false,
        false
    ],
    "CC-BY-ND-2.0": [
        "Creative Commons Attribution No Derivatives 2.0 Generic",
        false,
        false
    ],
    "CC-BY-ND-2.5": [
        "Creative Commons Attribution No Derivatives 2.5 Generic",
        false,
        false
    ],
    "CC-BY-ND-3.0": [
        "Creative Commons Attribution No Derivatives 3.0 Unported",
        false,
        false
    ],
    "CC-BY-ND-3.0-DE": [
        "Creative Commons Attribution No Derivatives 3.0 Germany",
        false,
        false
    ],
    "CC-BY-ND-4.0": [
        "Creative Commons Attribution No Derivatives 4.0 International",
        false,
        false
    ],
    "CC-BY-SA-1.0": [
        "Creative Commons Attribution Share Alike 1.0 Generic",
        false,
        false
    ],
    "CC-BY-SA-2.0": [
        "Creative Commons Attribution Share Alike 2.0 Generic",
        false,
        false
    ],
    "CC-BY-SA-2.0-UK": [
        "Creative Commons Attribution Share Alike 2.0 England and Wales",
        false,
        false
    ],
    "CC-BY-SA-2.1-JP": [
        "Creative Commons Attribution Share Alike 2.1 Japan",
        false,
        false
    ],
    "CC-BY-SA-2.5": [
        "Creative Commons Attribution Share Alike 2.5 Generic",
        false,
        false
    ],
    "CC-BY-SA-3.0": [
        "Creative Commons Attribution Share Alike 3.0 Unported",
        false,
        false
    ],
    "CC-BY-SA-3.0-AT": [
        "Creative Commons Attribution Share Alike 3.0 Austria",
        false,
        false
    ],
    "CC-BY-SA-3.0-DE": [
        "Creative Commons Attribution Share Alike 3.0 Germany",
        false,
        false
    ],
    "CC-BY-SA-3.0-IGO": [
        "Creative Commons Attribution-ShareAlike 3.0 IGO",
        false,
        false
    ],
    "CC-BY-SA-4.0": [
        "Creative Commons Attribution Share Alike 4.0 International",
        false,
        false
    ],
    "CC-PDDC": [
        "Creative Commons Public Domain Dedication and Certification",
        false,
        false
    ],
    "CC-PDM-1.0": [
        "Creative    Commons Public Domain Mark 1.0 Universal",
        false,
        false
    ],
    "CC-SA-1.0": [
        "Creative Commons Share Alike 1.0 Generic",
        false,
        false
    ],
    "CC0-1.0": [
        "Creative Commons Zero v1.0 Universal",
        false,
        false
    ],
    "CDDL-1.0": [
        "Common Development and Distribution License 1.0",
        true,
        false
    ],
    "CDDL-1.1": [
        "Common Development and Distribution License 1.1",
        false,
        false
    ],
    "CDL-1.0": [
        "Common Documentation License 1.0",
        false,
        false
    ],
    "CDLA-Permissive-1.0": [
        "Community Data License Agreement Permissive 1.0",
        false,
        false
    ],
    "CDLA-Permissive-2.0": [
        "Community Data License Agreement Permissive 2.0",
        false,
        false
    ],
    "CDLA-Sharing-1.0": [
        "Community Data License Agreement Sharing 1.0",
        false,
        false
    ],
    "CECILL-1.0": [
        "CeCILL Free Software License Agreement v1.0",
        false,
        false
    ],
    "CECILL-1.1": [
        "CeCILL Free Software License Agreement v1.1",
        false,
        false
    ],
    "CECILL-2.0": [
        "CeCILL Free Software License Agreement v2.0",
        false,
        false
    ],
    "CECILL-2.1": [
        "CeCILL Free Software License Agreement v2.1",
        true,
        false
    ],
    "CECILL-B": [
        "CeCILL-B Free Software License Agreement",
        false,
        false
    ],
    "CECILL-C": [
        "CeCILL-C Free Software License Agreement",
        false,
        false
    ],
    "CERN-OHL-1.1": [
        "CERN Open Hardware Licence v1.1",
        false,
        false
    ],
    "CERN-OHL-1.2": [
        "CERN Open Hardware Licence v1.2",
        false,
        false
    ],
    "CERN-OHL-P-2.0": [
        "CERN Open Hardware Licence Version 2 - Permissive",
        true,
        false
    ],
    "CERN-OHL-S-2.0": [
        "CERN Open Hardware Licence Version 2 - Strongly Reciprocal",
        true,
        false
    ],
    "CERN-OHL-W-2.0": [
        "CERN Open Hardware Licence Version 2 - Weakly Reciprocal",
        true,
        false
    ],
    "CFITSIO": [
        "CFITSIO License",
        false,
        false
    ],
    "check-cvs": [
        "check-cvs License",
        false,
        false
    ],
    "checkmk": [
        "Checkmk License",
        false,
        false
    ],
    "ClArtistic": [
        "Clarified Artistic License",
        false,
        false
    ],
    "Clips": [
        "Clips License",
        false,
        false
    ],
    "CMU-Mach": [
        "CMU Mach License",
        false,
        false
    ],
    "CMU-Mach-nodoc": [
        "CMU    Mach - no notices-in-documentation variant",
        false,
        false
    ],
    "CNRI-Jython": [
        "CNRI Jython License",
        false,
        false
    ],
    "CNRI-Python": [
        "CNRI Python License",
        true,
        false
    ],
    "CNRI-Python-GPL-Compatible": [
        "CNRI Python Open Source GPL Compatible License Agreement",
        false,
        false
    ],
    "COIL-1.0": [
        "Copyfree Open Innovation License",
        false,
        false
    ],
    "Community-Spec-1.0": [
        "Community Specification License 1.0",
        false,
        false
    ],
    "Condor-1.1": [
        "Condor Public License v1.1",
        false,
        false
    ],
    "copyleft-next-0.3.0": [
        "copyleft-next 0.3.0",
        false,
        false
    ],
    "copyleft-next-0.3.1": [
        "copyleft-next 0.3.1",
        false,
        false
    ],
    "Cornell-Lossless-JPEG": [
        "Cornell Lossless JPEG License",
        false,
        false
    ],
    "CPAL-1.0": [
        "Common Public Attribution License 1.0",
        true,
        false
    ],
    "CPL-1.0": [
        "Common Public License 1.0",
        true,
        false
    ],
    "CPOL-1.02": [
        "Code Project Open License 1.02",
        false,
        false
    ],
    "Cronyx": [
        "Cronyx License",
        false,
        false
    ],
    "Crossword": [
        "Crossword License",
        false,
        false
    ],
    "CryptoSwift": [
        "CryptoSwift License",
        false,
        false
    ],
    "CrystalStacker": [
        "CrystalStacker License",
        false,
        false
    ],
    "CUA-OPL-1.0": [
        "CUA Office Public License v1.0",
        true,
        false
    ],
    "Cube": [
        "Cube License",
        false,
        false
    ],
    "curl": [
        "curl License",
        false,
        false
    ],
    "cve-tou": [
        "Common Vulnerability Enumeration ToU License",
        false,
        false
    ],
    "D-FSL-1.0": [
        "Deutsche Freie Software Lizenz",
        false,
        false
    ],
    "DEC-3-Clause": [
        "DEC 3-Clause License",
        false,
        false
    ],
    "diffmark": [
        "diffmark license",
        false,
        false
    ],
    "DL-DE-BY-2.0": [
        "Data licence Germany \u2013 attribution \u2013 version 2.0",
        false,
        false
    ],
    "DL-DE-ZERO-2.0": [
        "Data licence Germany \u2013 zero \u2013 version 2.0",
        false,
        false
    ],
    "DOC": [
        "DOC License",
        false,
        false
    ],
    "DocBook-DTD": [
        "DocBook DTD License",
        false,
        false
    ],
    "DocBook-Schema": [
        "DocBook Schema License",
        false,
        false
    ],
    "DocBook-Stylesheet": [
        "DocBook Stylesheet License",
        false,
        false
    ],
    "DocBook-XML": [
        "DocBook XML License",
        false,
        false
    ],
    "Dotseqn": [
        "Dotseqn License",
        false,
        false
    ],
    "DRL-1.0": [
        "Detection Rule License 1.0",
        false,
        false
    ],
    "DRL-1.1": [
        "Detection Rule License 1.1",
        false,
        false
    ],
    "DSDP": [
        "DSDP License",
        false,
        false
    ],
    "dtoa": [
        "David M. Gay dtoa License",
        false,
        false
    ],
    "dvipdfm": [
        "dvipdfm License",
        false,
        false
    ],
    "ECL-1.0": [
        "Educational Community License v1.0",
        true,
        false
    ],
    "ECL-2.0": [
        "Educational Community License v2.0",
        true,
        false
    ],
    "eCos-2.0": [
        "eCos license version 2.0",
        false,
        true
    ],
    "EFL-1.0": [
        "Eiffel Forum License v1.0",
        true,
        false
    ],
    "EFL-2.0": [
        "Eiffel Forum License v2.0",
        true,
        false
    ],
    "eGenix": [
        "eGenix.com Public License 1.1.0",
        false,
        false
    ],
    "Elastic-2.0": [
        "Elastic License 2.0",
        false,
        false
    ],
    "Entessa": [
        "Entessa Public License v1.0",
        true,
        false
    ],
    "EPICS": [
        "EPICS Open License",
        false,
        false
    ],
    "EPL-1.0": [
        "Eclipse Public License 1.0",
        true,
        false
    ],
    "EPL-2.0": [
        "Eclipse Public License 2.0",
        true,
        false
    ],
    "ErlPL-1.1": [
        "Erlang Public License v1.1",
        false,
        false
    ],
    "ESA-PL-permissive-2.4": [
        "European Space Agency Public License \u2013 v2.4 \u2013 Permissive (Type 3)",
        false,
        false
    ],
    "ESA-PL-strong-copyleft-2.4": [
        "European Space Agency Public License (ESA-PL) - V2.4 - Strong Copyleft (Type 1)",
        false,
        false
    ],
    "ESA-PL-weak-copyleft-2.4": [
        "European Space Agency Public License \u2013 v2.4 \u2013 Weak Copyleft (Type 2)",
        false,
        false
    ],
    "etalab-2.0": [
        "Etalab Open License 2.0",
        false,
        false
    ],
    "EUDatagrid": [
        "EU DataGrid Software License",
        true,
        false
    ],
    "EUPL-1.0": [
        "European Union Public License 1.0",
        false,
        false
    ],
    "EUPL-1.1": [
        "European Union Public License 1.1",
        true,
        false
    ],
    "EUPL-1.2": [
        "European Union Public License 1.2",
        true,
        false
    ],
    "Eurosym": [
        "Eurosym License",
        false,
        false
    ],
    "Fair": [
        "Fair License",
        true,
        false
    ],
    "FBM": [
        "Fuzzy Bitmap License",
        false,
        false
    ],
    "FDK-AAC": [
        "Fraunhofer FDK AAC Codec Library",
        false,
        false
    ],
    "Ferguson-Twofish": [
        "Ferguson Twofish License",
        false,
        false
    ],
    "Frameworx-1.0": [
        "Frameworx Open License 1.0",
        true,
        false
    ],
    "FreeBSD-DOC": [
        "FreeBSD Documentation License",
        false,
        false
    ],
    "FreeImage": [
        "FreeImage Public License v1.0",
        false,
        false
    ],
    "FSFAP": [
        "FSF All Permissive License",
        false,
        false
    ],
    "FSFAP-no-warranty-disclaimer": [
        "FSF All Permissive License (without Warranty)",
        false,
        false
    ],
    "FSFUL": [
        "FSF Unlimited License",
        false,
        false
    ],
    "FSFULLR": [
        "FSF Unlimited License (with License Retention)",
        false,
        false
    ],
    "FSFULLRSD": [
        "FSF Unlimited License (with License Retention and Short Disclaimer)",
        false,
        false
    ],
    "FSFULLRWD": [
        "FSF Unlimited License (With License Retention and Warranty Disclaimer)",
        false,
        false
    ],
    "FSL-1.1-ALv2": [
        "Functional Source License, Version 1.1, ALv2 Future License",
        false,
        false
    ],
    "FSL-1.1-MIT": [
        "Functional Source License, Version 1.1, MIT Future License",
        false,
        false
    ],
    "FTL": [
        "Freetype Project License",
        false,
        false
    ],
    "Furuseth": [
        "Furuseth License",
        false,
        false
    ],
    "fwlw": [
        "fwlw License",
        false,
        false
    ],
    "Game-Programming-Gems": [
        "Game Programming Gems License",
        false,
        false
    ],
    "GCR-docs": [
        "Gnome GCR Documentation License",
        false,
        false
    ],
    "GD": [
        "GD License",
        false,
        false
    ],
    "generic-xts": [
        "Generic XTS License",
        false,
        false
    ],
    "GFDL-1.1": [
        "GNU Free Documentation License v1.1",
        false,
        true
    ],
    "GFDL-1.1-invariants-only": [
        "GNU Free Documentation License v1.1 only - invariants",
        false,
        false
    ],
    "GFDL-1.1-invariants-or-later": [
        "GNU Free Documentation License v1.1 or later - invariants",
        false,
        false
    ],
    "GFDL-1.1-no-invariants-only": [
        "GNU Free Documentation License v1.1 only - no invariants",
        false,
        false
    ],
    "GFDL-1.1-no-invariants-or-later": [
        "GNU Free Documentation License v1.1 or later - no invariants",
        false,
        false
    ],
    "GFDL-1.1-only": [
        "GNU Free Documentation License v1.1 only",
        false,
        false
    ],
    "GFDL-1.1-or-later": [
        "GNU Free Documentation License v1.1 or later",
        false,
        false
    ],
    "GFDL-1.2": [
        "GNU Free Documentation License v1.2",
        false,
        true
    ],
    "GFDL-1.2-invariants-only": [
        "GNU Free Documentation License v1.2 only - invariants",
        false,
        false
    ],
    "GFDL-1.2-invariants-or-later": [
        "GNU Free Documentation License v1.2 or later - invariants",
        false,
        false
    ],
    "GFDL-1.2-no-invariants-only": [
        "GNU Free Documentation License v1.2 only - no invariants",
        false,
        false
    ],
    "GFDL-1.2-no-invariants-or-later": [
        "GNU Free Documentation License v1.2 or later - no invariants",
        false,
        false
    ],
    "GFDL-1.2-only": [
        "GNU Free Documentation License v1.2 only",
        false,
        false
    ],
    "GFDL-1.2-or-later": [
        "GNU Free Documentation License v1.2 or later",
        false,
        false
    ],
    "GFDL-1.3": [
        "GNU Free Documentation License v1.3",
        false,
        true
    ],
    "GFDL-1.3-invariants-only": [
        "GNU Free Documentation License v1.3 only - invariants",
        false,
        false
    ],
    "GFDL-1.3-invariants-or-later": [
        "GNU Free Documentation License v1.3 or later - invariants",
        false,
        false
    ],
    "GFDL-1.3-no-invariants-only": [
        "GNU Free Documentation License v1.3 only - no invariants",
        false,
        false
    ],
    "GFDL-1.3-no-invariants-or-later": [
        "GNU Free Documentation License v1.3 or later - no invariants",
        false,
        false
    ],
    "GFDL-1.3-only": [
        "GNU Free Documentation License v1.3 only",
        false,
        false
    ],
    "GFDL-1.3-or-later": [
        "GNU Free Documentation License v1.3 or later",
        false,
        false
    ],
    "Giftware": [
        "Giftware License",
        false,
        false
    ],
    "GL2PS": [
        "GL2PS License",
        false,
        false
    ],
    "Glide": [
        "3dfx Glide License",
        false,
        false
    ],
    "Glulxe": [
        "Glulxe License",
        false,
        false
    ],
    "GLWTPL": [
        "Good Luck With That Public License",
        false,
        false
    ],
    "gnuplot": [
        "gnuplot License",
        false,
        false
    ],
    "GPL-1.0": [
        "GNU General Public License v1.0 only",
        false,
        true
    ],
    "GPL-1.0+": [
        "GNU General Public License v1.0 or later",
        false,
        true
    ],
    "GPL-1.0-only": [
        "GNU General Public License v1.0 only",
        false,
        false
    ],
    "GPL-1.0-or-later": [
        "GNU General Public License v1.0 or later",
        false,
        false
    ],
    "GPL-2.0": [
        "GNU General Public License v2.0 only",
        true,
        true
    ],
    "GPL-2.0+": [
        "GNU General Public License v2.0 or later",
        true,
        true
    ],
    "GPL-2.0-only": [
        "GNU General Public License v2.0 only",
        true,
        false
    ],
    "GPL-2.0-or-later": [
        "GNU General Public License v2.0 or later",
        true,
        false
    ],
    "GPL-2.0-with-autoconf-exception": [
        "GNU General Public License v2.0 w/Autoconf exception",
        false,
        true
    ],
    "GPL-2.0-with-bison-exception": [
        "GNU General Public License v2.0 w/Bison exception",
        false,
        true
    ],
    "GPL-2.0-with-classpath-exception": [
        "GNU General Public License v2.0 w/Classpath exception",
        false,
        true
    ],
    "GPL-2.0-with-font-exception": [
        "GNU General Public License v2.0 w/Font exception",
        false,
        true
    ],
    "GPL-2.0-with-GCC-exception": [
        "GNU General Public License v2.0 w/GCC Runtime Library exception",
        false,
        true
    ],
    "GPL-3.0": [
        "GNU General Public License v3.0 only",
        true,
        true
    ],
    "GPL-3.0+": [
        "GNU General Public License v3.0 or later",
        true,
        true
    ],
    "GPL-3.0-only": [
        "GNU General Public License v3.0 only",
        true,
        false
    ],
    "GPL-3.0-or-later": [
        "GNU General Public License v3.0 or later",
        true,
        false
    ],
    "GPL-3.0-with-autoconf-exception": [
        "GNU General Public License v3.0 w/Autoconf exception",
        false,
        true
    ],
    "GPL-3.0-with-GCC-exception": [
        "GNU General Public License v3.0 w/GCC Runtime Library exception",
        true,
        true
    ],
    "Graphics-Gems": [
        "Graphics Gems License",
        false,
        false
    ],
    "gSOAP-1.3b": [
        "gSOAP Public License v1.3b",
        false,
        false
    ],
    "gtkbook": [
        "gtkbook License",
        false,
        false
    ],
    "Gutmann": [
        "Gutmann License",
        false,
        false
    ],
    "HaskellReport": [
        "Haskell Language Report License",
        false,
        false
    ],
    "HDF5": [
        "HDF5 License",
        false,
        false
    ],
    "hdparm": [
        "hdparm License",
        false,
        false
    ],
    "HIDAPI": [
        "HIDAPI License",
        false,
        false
    ],
    "Hippocratic-2.1": [
        "Hippocratic License 2.1",
        false,
        false
    ],
    "HP-1986": [
        "Hewlett-Packard 1986 License",
        false,
        false
    ],
    "HP-1989": [
        "Hewlett-Packard 1989 License",
        false,
        false
    ],
    "HPND": [
        "Historical Permission Notice and Disclaimer",
        true,
        false
    ],
    "HPND-DEC": [
        "Historical Permission Notice and Disclaimer - DEC variant",
        false,
        false
    ],
    "HPND-doc": [
        "Historical Permission Notice and Disclaimer - documentation variant",
        false,
        false
    ],
    "HPND-doc-sell": [
        "Historical Permission Notice and Disclaimer - documentation sell variant",
        false,
        false
    ],
    "HPND-export-US": [
        "HPND with US Government export control warning",
        false,
        false
    ],
    "HPND-export-US-acknowledgement": [
        "HPND with US Government export control warning and acknowledgment",
        false,
        false
    ],
    "HPND-export-US-modify": [
        "HPND with US Government export control warning and modification rqmt",
        false,
        false
    ],
    "HPND-export2-US": [
        "HPND with US Government export control and 2 disclaimers",
        false,
        false
    ],
    "HPND-Fenneberg-Livingston": [
        "Historical Permission Notice and Disclaimer - Fenneberg-Livingston variant",
        false,
        false
    ],
    "HPND-INRIA-IMAG": [
        "Historical Permission Notice and Disclaimer    - INRIA-IMAG variant",
        false,
        false
    ],
    "HPND-Intel": [
        "Historical Permission Notice and Disclaimer - Intel variant",
        false,
        false
    ],
    "HPND-Kevlin-Henney": [
        "Historical Permission Notice and Disclaimer - Kevlin Henney variant",
        false,
        false
    ],
    "HPND-Markus-Kuhn": [
        "Historical Permission Notice and Disclaimer - Markus Kuhn variant",
        false,
        false
    ],
    "HPND-merchantability-variant": [
        "Historical Permission Notice and Disclaimer - merchantability variant",
        false,
        false
    ],
    "HPND-MIT-disclaimer": [
        "Historical Permission Notice and Disclaimer with MIT disclaimer",
        false,
        false
    ],
    "HPND-Netrek": [
        "Historical Permission Notice and Disclaimer - Netrek variant",
        false,
        false
    ],
    "HPND-Pbmplus": [
        "Historical Permission Notice and Disclaimer - Pbmplus variant",
        false,
        false
    ],
    "HPND-sell-MIT-disclaimer-xserver": [
        "Historical Permission Notice and Disclaimer - sell xserver variant with MIT disclaimer",
        false,
        false
    ],
    "HPND-sell-regexpr": [
        "Historical Permission Notice and Disclaimer - sell regexpr variant",
        false,
        false
    ],
    "HPND-sell-variant": [
        "Historical Permission Notice and Disclaimer - sell variant",
        false,
        false
    ],
    "HPND-sell-variant-critical-systems": [
        "HPND - sell variant with safety critical systems clause",
        false,
        false
    ],
    "HPND-sell-variant-MIT-disclaimer": [
        "HPND sell variant with MIT disclaimer",
        false,
        false
    ],
    "HPND-sell-variant-MIT-disclaimer-rev": [
        "HPND sell variant with MIT disclaimer - reverse",
        false,
        false
    ],
    "HPND-SMC": [
        "Historical Permission Notice and Disclaimer - SMC variant",
        false,
        false
    ],
    "HPND-UC": [
        "Historical Permission Notice and Disclaimer - University of California variant",
        false,
        false
    ],
    "HPND-UC-export-US": [
        "Historical Permission Notice and Disclaimer - University of California, US export warning",
        false,
        false
    ],
    "HTMLTIDY": [
        "HTML Tidy License",
        false,
        false
    ],
    "hyphen-bulgarian": [
        "hyphen-bulgarian License",
        false,
        false
    ],
    "IBM-pibs": [
        "IBM PowerPC Initialization and Boot Software",
        false,
        false
    ],
    "ICU": [
        "ICU License",
        true,
        false
    ],
    "IEC-Code-Components-EULA": [
        "IEC    Code Components End-user licence agreement",
        false,
        false
    ],
    "IJG": [
        "Independent JPEG Group License",
        false,
        false
    ],
    "IJG-short": [
        "Independent JPEG Group License - short",
        false,
        false
    ],
    "ImageMagick": [
        "ImageMagick License",
        false,
        false
    ],
    "iMatix": [
        "iMatix Standard Function Library Agreement",
        false,
        false
    ],
    "Imlib2": [
        "Imlib2 License",
        false,
        false
    ],
    "Info-ZIP": [
        "Info-ZIP License",
        false,
        false
    ],
    "Inner-Net-2.0": [
        "Inner Net License v2.0",
        false,
        false
    ],
    "InnoSetup": [
        "Inno Setup License",
        false,
        false
    ],
    "Intel": [
        "Intel Open Source License",
        true,
        false
    ],
    "Intel-ACPI": [
        "Intel ACPI Software License Agreement",
        false,
        false
    ],
    "Interbase-1.0": [
        "Interbase Public License v1.0",
        false,
        false
    ],
    "IPA": [
        "IPA Font License",
        true,
        false
    ],
    "IPL-1.0": [
        "IBM Public License v1.0",
        true,
        false
    ],
    "ISC": [
        "ISC License",
        true,
        false
    ],
    "ISC-Veillard": [
        "ISC Veillard variant",
        false,
        false
    ],
    "ISO-permission": [
        "ISO permission notice",
        false,
        false
    ],
    "Jam": [
        "Jam License",
        true,
        false
    ],
    "JasPer-2.0": [
        "JasPer License",
        false,
        false
    ],
    "jove": [
        "Jove License",
        false,
        false
    ],
    "JPL-image": [
        "JPL Image Use Policy",
        false,
        false
    ],
    "JPNIC": [
        "Japan Network Information Center License",
        false,
        false
    ],
    "JSON": [
        "JSON License",
        false,
        false
    ],
    "Kastrup": [
        "Kastrup License",
        false,
        false
    ],
    "Kazlib": [
        "Kazlib License",
        false,
        false
    ],
    "Knuth-CTAN": [
        "Knuth CTAN License",
        false,
        false
    ],
    "LAL-1.2": [
        "Licence Art Libre 1.2",
        false,
        false
    ],
    "LAL-1.3": [
        "Licence Art Libre 1.3",
        false,
        false
    ],
    "Latex2e": [
        "Latex2e License",
        false,
        false
    ],
    "Latex2e-translated-notice": [
        "Latex2e with translated notice permission",
        false,
        false
    ],
    "Leptonica": [
        "Leptonica License",
        false,
        false
    ],
    "LGPL-2.0": [
        "GNU Library General Public License v2 only",
        true,
        true
    ],
    "LGPL-2.0+": [
        "GNU Library General Public License v2 or later",
        true,
        true
    ],
    "LGPL-2.0-only": [
        "GNU Library General Public License v2 only",
        true,
        false
    ],
    "LGPL-2.0-or-later": [
        "GNU Library General Public License v2 or later",
        true,
        false
    ],
    "LGPL-2.1": [
        "GNU Lesser General Public License v2.1 only",
        true,
        true
    ],
    "LGPL-2.1+": [
        "GNU Lesser General Public License v2.1 or later",
        true,
        true
    ],
    "LGPL-2.1-only": [
        "GNU Lesser General Public License v2.1 only",
        true,
        false
    ],
    "LGPL-2.1-or-later": [
        "GNU Lesser General Public License v2.1 or later",
        true,
        false
    ],
    "LGPL-3.0": [
        "GNU Lesser General Public License v3.0 only",
        true,
        true
    ],
    "LGPL-3.0+": [
        "GNU Lesser General Public License v3.0 or later",
        true,
        true
    ],
    "LGPL-3.0-only": [
        "GNU Lesser General Public License v3.0 only",
        true,
        false
    ],
    "LGPL-3.0-or-later": [
        "GNU Lesser General Public License v3.0 or later",
        true,
        false
    ],
    "LGPLLR": [
        "Lesser General Public License For Linguistic Resources",
        false,
        false
    ],
    "Libpng": [
        "libpng License",
        false,
        false
    ],
    "libpng-1.6.35": [
        "PNG Reference Library License v1 (for libpng 0.5 through 1.6.35)",
        false,
        false
    ],
    "libpng-2.0": [
        "PNG Reference Library version 2",
        false,
        false
    ],
    "libselinux-1.0": [
        "libselinux public domain notice",
        false,
        false
    ],
    "libtiff": [
        "libtiff License",
        false,
        false
    ],
    "libutil-David-Nugent": [
        "libutil David Nugent License",
        false,
        false
    ],
    "LiLiQ-P-1.1": [
        "Licence Libre du Qu\u00e9bec \u2013 Permissive version 1.1",
        true,
        false
    ],
    "LiLiQ-R-1.1": [
        "Licence Libre du Qu\u00e9bec \u2013 R\u00e9ciprocit\u00e9 version 1.1",
        true,
        false
    ],
    "LiLiQ-Rplus-1.1": [
        "Licence Libre du Qu\u00e9bec \u2013 R\u00e9ciprocit\u00e9 forte version 1.1",
        true,
        false
    ],
    "Linux-man-pages-1-para": [
        "Linux man-pages - 1 paragraph",
        false,
        false
    ],
    "Linux-man-pages-copyleft": [
        "Linux man-pages Copyleft",
        false,
        false
    ],
    "Linux-man-pages-copyleft-2-para": [
        "Linux man-pages Copyleft - 2 paragraphs",
        false,
        false
    ],
    "Linux-man-pages-copyleft-var": [
        "Linux man-pages Copyleft Variant",
        false,
        false
    ],
    "Linux-OpenIB": [
        "Linux Kernel Variant of OpenIB.org license",
        false,
        false
    ],
    "LOOP": [
        "Common Lisp LOOP License",
        false,
        false
    ],
    "LPD-document": [
        "LPD Documentation License",
        false,
        false
    ],
    "LPL-1.0": [
        "Lucent Public License Version 1.0",
        true,
        false
    ],
    "LPL-1.02": [
        "Lucent Public License v1.02",
        true,
        false
    ],
    "LPPL-1.0": [
        "LaTeX Project Public License v1.0",
        false,
        false
    ],
    "LPPL-1.1": [
        "LaTeX Project Public License v1.1",
        false,
        false
    ],
    "LPPL-1.2": [
        "LaTeX Project Public License v1.2",
        false,
        false
    ],
    "LPPL-1.3a": [
        "LaTeX Project Public License v1.3a",
        false,
        false
    ],
    "LPPL-1.3c": [
        "LaTeX Project Public License v1.3c",
        true,
        false
    ],
    "lsof": [
        "lsof License",
        false,
        false
    ],
    "Lucida-Bitmap-Fonts": [
        "Lucida Bitmap Fonts License",
        false,
        false
    ],
    "LZMA-SDK-9.11-to-9.20": [
        "LZMA SDK License (versions 9.11 to 9.20)",
        false,
        false
    ],
    "LZMA-SDK-9.22": [
        "LZMA SDK License (versions 9.22 and beyond)",
        false,
        false
    ],
    "Mackerras-3-Clause": [
        "Mackerras 3-Clause License",
        false,
        false
    ],
    "Mackerras-3-Clause-acknowledgment": [
        "Mackerras 3-Clause - acknowledgment variant",
        false,
        false
    ],
    "magaz": [
        "magaz License",
        false,
        false
    ],
    "mailprio": [
        "mailprio License",
        false,
        false
    ],
    "MakeIndex": [
        "MakeIndex License",
        false,
        false
    ],
    "man2html": [
        "man2html License",
        false,
        false
    ],
    "Martin-Birgmeier": [
        "Martin Birgmeier License",
        false,
        false
    ],
    "McPhee-slideshow": [
        "McPhee Slideshow License",
        false,
        false
    ],
    "metamail": [
        "metamail License",
        false,
        false
    ],
    "Minpack": [
        "Minpack License",
        false,
        false
    ],
    "MIPS": [
        "MIPS License",
        false,
        false
    ],
    "MirOS": [
        "The MirOS Licence",
        true,
        false
    ],
    "MIT": [
        "MIT License",
        true,
        false
    ],
    "MIT-0": [
        "MIT No Attribution",
        true,
        false
    ],
    "MIT-advertising": [
        "Enlightenment License (e16)",
        false,
        false
    ],
    "MIT-Click": [
        "MIT Click License",
        false,
        false
    ],
    "MIT-CMU": [
        "CMU License",
        false,
        false
    ],
    "MIT-enna": [
        "enna License",
        false,
        false
    ],
    "MIT-feh": [
        "feh License",
        false,
        false
    ],
    "MIT-Festival": [
        "MIT Festival Variant",
        false,
        false
    ],
    "MIT-Khronos-old": [
        "MIT Khronos - old variant",
        false,
        false
    ],
    "MIT-Modern-Variant": [
        "MIT License Modern Variant",
        true,
        false
    ],
    "MIT-open-group": [
        "MIT Open Group variant",
        false,
        false
    ],
    "MIT-STK": [
        "MIT-STK License",
        false,
        false
    ],
    "MIT-testregex": [
        "MIT testregex Variant",
        false,
        false
    ],
    "MIT-Wu": [
        "MIT Tom Wu Variant",
        false,
        false
    ],
    "MITNFA": [
        "MIT +no-false-attribs license",
        false,
        false
    ],
    "MMIXware": [
        "MMIXware License",
        false,
        false
    ],
    "MMPL-1.0.1": [
        "Minecraft Mod Public License v1.0.1",
        false,
        false
    ],
    "Motosoto": [
        "Motosoto License",
        true,
        false
    ],
    "MPEG-SSG": [
        "MPEG Software Simulation",
        false,
        false
    ],
    "mpi-permissive": [
        "mpi Permissive License",
        false,
        false
    ],
    "mpich2": [
        "mpich2 License",
        false,
        false
    ],
    "MPL-1.0": [
        "Mozilla Public License 1.0",
        true,
        false
    ],
    "MPL-1.1": [
        "Mozilla Public License 1.1",
        true,
        false
    ],
    "MPL-2.0": [
        "Mozilla Public License 2.0",
        true,
        false
    ],
    "MPL-2.0-no-copyleft-exception": [
        "Mozilla Public License 2.0 (no copyleft exception)",
        true,
        false
    ],
    "mplus": [
        "mplus Font License",
        false,
        false
    ],
    "MS-LPL": [
        "Microsoft Limited Public License",
        false,
        false
    ],
    "MS-PL": [
        "Microsoft Public License",
        true,
        false
    ],
    "MS-RL": [
        "Microsoft Reciprocal License",
        true,
        false
    ],
    "MTLL": [
        "Matrix Template Library License",
        false,
        false
    ],
    "MulanPSL-1.0": [
        "Mulan Permissive Software License, Version 1",
        false,
        false
    ],
    "MulanPSL-2.0": [
        "Mulan Permissive Software License, Version 2",
        true,
        false
    ],
    "Multics": [
        "Multics License",
        true,
        false
    ],
    "Mup": [
        "Mup License",
        false,
        false
    ],
    "NAIST-2003": [
        "Nara Institute of Science and Technology License (2003)",
        false,
        false
    ],
    "NASA-1.3": [
        "NASA Open Source Agreement 1.3",
        true,
        false
    ],
    "Naumen": [
        "Naumen Public License",
        true,
        false
    ],
    "NBPL-1.0": [
        "Net Boolean Public License v1",
        false,
        false
    ],
    "NCBI-PD": [
        "NCBI Public Domain Notice",
        false,
        false
    ],
    "NCGL-UK-2.0": [
        "Non-Commercial Government Licence",
        false,
        false
    ],
    "NCL": [
        "NCL Source Code License",
        false,
        false
    ],
    "NCSA": [
        "University of Illinois/NCSA Open Source License",
        true,
        false
    ],
    "Net-SNMP": [
        "Net-SNMP License",
        false,
        true
    ],
    "NetCDF": [
        "NetCDF license",
        false,
        false
    ],
    "Newsletr": [
        "Newsletr License",
        false,
        false
    ],
    "NGPL": [
        "Nethack General Public License",
        true,
        false
    ],
    "ngrep": [
        "ngrep License",
        false,
        false
    ],
    "NICTA-1.0": [
        "NICTA Public Software License, Version 1.0",
        false,
        false
    ],
    "NIST-PD": [
        "NIST Public Domain Notice",
        false,
        false
    ],
    "NIST-PD-fallback": [
        "NIST Public Domain Notice with license fallback",
        false,
        false
    ],
    "NIST-PD-TNT": [
        "NIST    Public Domain Notice TNT variant",
        false,
        false
    ],
    "NIST-Software": [
        "NIST Software License",
        false,
        false
    ],
    "NLOD-1.0": [
        "Norwegian Licence for Open Government Data (NLOD) 1.0",
        false,
        false
    ],
    "NLOD-2.0": [
        "Norwegian Licence for Open Government Data (NLOD) 2.0",
        false,
        false
    ],
    "NLPL": [
        "No Limit Public License",
        false,
        false
    ],
    "Nokia": [
        "Nokia Open Source License",
        true,
        false
    ],
    "NOSL": [
        "Netizen Open Source License",
        false,
        false
    ],
    "Noweb": [
        "Noweb License",
        false,
        false
    ],
    "NPL-1.0": [
        "Netscape Public License v1.0",
        false,
        false
    ],
    "NPL-1.1": [
        "Netscape Public License v1.1",
        false,
        false
    ],
    "NPOSL-3.0": [
        "Non-Profit Open Software License 3.0",
        true,
        false
    ],
    "NRL": [
        "NRL License",
        false,
        false
    ],
    "NTIA-PD": [
        "NTIA Public Domain Notice",
        false,
        false
    ],
    "NTP": [
        "NTP License",
        true,
        false
    ],
    "NTP-0": [
        "NTP No Attribution",
        false,
        false
    ],
    "Nunit": [
        "Nunit License",
        false,
        true
    ],
    "O-UDA-1.0": [
        "Open Use of Data Agreement v1.0",
        false,
        false
    ],
    "OAR": [
        "OAR License",
        false,
        false
    ],
    "OCCT-PL": [
        "Open CASCADE Technology Public License",
        false,
        false
    ],
    "OCLC-2.0": [
        "OCLC Research Public License 2.0",
        true,
        false
    ],
    "ODbL-1.0": [
        "Open Data Commons Open Database License v1.0",
        false,
        false
    ],
    "ODC-By-1.0": [
        "Open Data Commons Attribution License v1.0",
        false,
        false
    ],
    "OFFIS": [
        "OFFIS License",
        false,
        false
    ],
    "OFL-1.0": [
        "SIL Open Font License 1.0",
        false,
        false
    ],
    "OFL-1.0-no-RFN": [
        "SIL Open Font License 1.0 with no Reserved Font Name",
        false,
        false
    ],
    "OFL-1.0-RFN": [
        "SIL Open Font License 1.0 with Reserved Font Name",
        false,
        false
    ],
    "OFL-1.1": [
        "SIL Open Font License 1.1",
        true,
        false
    ],
    "OFL-1.1-no-RFN": [
        "SIL Open Font License 1.1 with no Reserved Font Name",
        true,
        false
    ],
    "OFL-1.1-RFN": [
        "SIL Open Font License 1.1 with Reserved Font Name",
        true,
        false
    ],
    "OGC-1.0": [
        "OGC Software License, Version 1.0",
        false,
        false
    ],
    "OGDL-Taiwan-1.0": [
        "Taiwan Open Government Data License, version 1.0",
        false,
        false
    ],
    "OGL-Canada-2.0": [
        "Open Government Licence - Canada",
        false,
        false
    ],
    "OGL-UK-1.0": [
        "Open Government Licence v1.0",
        false,
        false
    ],
    "OGL-UK-2.0": [
        "Open Government Licence v2.0",
        false,
        false
    ],
    "OGL-UK-3.0": [
        "Open Government Licence v3.0",
        false,
        false
    ],
    "OGTSL": [
        "Open Group Test Suite License",
        true,
        false
    ],
    "OLDAP-1.1": [
        "Open LDAP Public License v1.1",
        false,
        false
    ],
    "OLDAP-1.2": [
        "Open LDAP Public License v1.2",
        false,
        false
    ],
    "OLDAP-1.3": [
        "Open LDAP Public License v1.3",
        false,
        false
    ],
    "OLDAP-1.4": [
        "Open LDAP Public License v1.4",
        false,
        false
    ],
    "OLDAP-2.0": [
        "Open LDAP Public License v2.0 (or possibly 2.0A and 2.0B)",
        false,
        false
    ],
    "OLDAP-2.0.1": [
        "Open LDAP Public License v2.0.1",
        false,
        false
    ],
    "OLDAP-2.1": [
        "Open LDAP Public License v2.1",
        false,
        false
    ],
    "OLDAP-2.2": [
        "Open LDAP Public License v2.2",
        false,
        false
    ],
    "OLDAP-2.2.1": [
        "Open LDAP Public License v2.2.1",
        false,
        false
    ],
    "OLDAP-2.2.2": [
        "Open LDAP Public License 2.2.2",
        false,
        false
    ],
    "OLDAP-2.3": [
        "Open LDAP Public License v2.3",
        false,
        false
    ],
    "OLDAP-2.4": [
        "Open LDAP Public License v2.4",
        false,
        false
    ],
    "OLDAP-2.5": [
        "Open LDAP Public License v2.5",
        false,
        false
    ],
    "OLDAP-2.6": [
        "Open LDAP Public License v2.6",
        false,
        false
    ],
    "OLDAP-2.7": [
        "Open LDAP Public License v2.7",
        false,
        false
    ],
    "OLDAP-2.8": [
        "Open LDAP Public License v2.8",
        true,
        false
    ],
    "OLFL-1.3": [
        "Open Logistics Foundation License Version 1.3",
        true,
        false
    ],
    "OML": [
        "Open Market License",
        false,
        false
    ],
    "OpenMDW-1.0": [
        "OpenMDW License Agreement v1.0",
        false,
        false
    ],
    "OpenPBS-2.3": [
        "OpenPBS v2.3 Software License",
        false,
        false
    ],
    "OpenSSL": [
        "OpenSSL License",
        false,
        false
    ],
    "OpenSSL-standalone": [
        "OpenSSL License - standalone",
        false,
        false
    ],
    "OpenVision": [
        "OpenVision License",
        false,
        false
    ],
    "OPL-1.0": [
        "Open Public License v1.0",
        false,
        false
    ],
    "OPL-UK-3.0": [
        "United    Kingdom Open Parliament Licence v3.0",
        false,
        false
    ],
    "OPUBL-1.0": [
        "Open Publication License v1.0",
        false,
        false
    ],
    "OSC-1.0": [
        "OSC License 1.0",
        true,
        false
    ],
    "OSET-PL-2.1": [
        "OSET Public License version 2.1",
        true,
        false
    ],
    "OSL-1.0": [
        "Open Software License 1.0",
        true,
        false
    ],
    "OSL-1.1": [
        "Open Software License 1.1",
        false,
        false
    ],
    "OSL-2.0": [
        "Open Software License 2.0",
        true,
        false
    ],
    "OSL-2.1": [
        "Open Software License 2.1",
        true,
        false
    ],
    "OSL-3.0": [
        "Open Software License 3.0",
        true,
        false
    ],
    "OSSP": [
        "OSSP License",
        false,
        false
    ],
    "PADL": [
        "PADL License",
        false,
        false
    ],
    "ParaType-Free-Font-1.3": [
        "ParaType Free Font Licensing Agreement v1.3",
        false,
        false
    ],
    "Parity-6.0.0": [
        "The Parity Public License 6.0.0",
        false,
        false
    ],
    "Parity-7.0.0": [
        "The Parity Public License 7.0.0",
        false,
        false
    ],
    "PDDL-1.0": [
        "Open Data Commons Public Domain Dedication & License 1.0",
        false,
        false
    ],
    "PHP-3.0": [
        "PHP License v3.0",
        true,
        false
    ],
    "PHP-3.01": [
        "PHP License v3.01",
        true,
        false
    ],
    "Pixar": [
        "Pixar License",
        false,
        false
    ],
    "pkgconf": [
        "pkgconf License",
        false,
        false
    ],
    "Plexus": [
        "Plexus Classworlds License",
        false,
        false
    ],
    "pnmstitch": [
        "pnmstitch License",
        false,
        false
    ],
    "PolyForm-Noncommercial-1.0.0": [
        "PolyForm Noncommercial License 1.0.0",
        false,
        false
    ],
    "PolyForm-Small-Business-1.0.0": [
        "PolyForm Small Business License 1.0.0",
        false,
        false
    ],
    "PostgreSQL": [
        "PostgreSQL License",
        true,
        false
    ],
    "PPL": [
        "Peer Production License",
        false,
        false
    ],
    "PSF-2.0": [
        "Python Software Foundation License 2.0",
        false,
        false
    ],
    "psfrag": [
        "psfrag License",
        false,
        false
    ],
    "psutils": [
        "psutils License",
        false,
        false
    ],
    "Python-2.0": [
        "Python License 2.0",
        true,
        false
    ],
    "Python-2.0.1": [
        "Python License 2.0.1",
        false,
        false
    ],
    "python-ldap": [
        "Python ldap License",
        false,
        false
    ],
    "Qhull": [
        "Qhull License",
        false,
        false
    ],
    "QPL-1.0": [
        "Q Public License 1.0",
        true,
        false
    ],
    "QPL-1.0-INRIA-2004": [
        "Q Public License 1.0 - INRIA 2004 variant",
        false,
        false
    ],
    "radvd": [
        "radvd License",
        false,
        false
    ],
    "Rdisc": [
        "Rdisc License",
        false,
        false
    ],
    "RHeCos-1.1": [
        "Red Hat eCos Public License v1.1",
        false,
        false
    ],
    "RPL-1.1": [
        "Reciprocal Public License 1.1",
        true,
        false
    ],
    "RPL-1.5": [
        "Reciprocal Public License 1.5",
        true,
        false
    ],
    "RPSL-1.0": [
        "RealNetworks Public Source License v1.0",
        true,
        false
    ],
    "RSA-MD": [
        "RSA Message-Digest License",
        false,
        false
    ],
    "RSCPL": [
        "Ricoh Source Code Public License",
        true,
        false
    ],
    "Ruby": [
        "Ruby License",
        false,
        false
    ],
    "Ruby-pty": [
        "Ruby pty extension license",
        false,
        false
    ],
    "SAX-PD": [
        "Sax Public Domain Notice",
        false,
        false
    ],
    "SAX-PD-2.0": [
        "Sax Public Domain Notice 2.0",
        false,
        false
    ],
    "Saxpath": [
        "Saxpath License",
        false,
        false
    ],
    "SCEA": [
        "SCEA Shared Source License",
        false,
        false
    ],
    "SchemeReport": [
        "Scheme Language Report License",
        false,
        false
    ],
    "Sendmail": [
        "Sendmail License",
        false,
        false
    ],
    "Sendmail-8.23": [
        "Sendmail License 8.23",
        false,
        false
    ],
    "Sendmail-Open-Source-1.1": [
        "Sendmail Open Source License v1.1",
        false,
        false
    ],
    "SGI-B-1.0": [
        "SGI Free Software License B v1.0",
        false,
        false
    ],
    "SGI-B-1.1": [
        "SGI Free Software License B v1.1",
        false,
        false
    ],
    "SGI-B-2.0": [
        "SGI Free Software License B v2.0",
        false,
        false
    ],
    "SGI-OpenGL": [
        "SGI OpenGL License",
        false,
        false
    ],
    "SGMLUG-PM": [
        "SGMLUG Parser Materials License",
        false,
        false
    ],
    "SGP4": [
        "SGP4 Permission Notice",
        false,
        false
    ],
    "SHL-0.5": [
        "Solderpad Hardware License v0.5",
        false,
        false
    ],
    "SHL-0.51": [
        "Solderpad Hardware License, Version 0.51",
        false,
        false
    ],
    "SimPL-2.0": [
        "Simple Public License 2.0",
        true,
        false
    ],
    "SISSL": [
        "Sun Industry Standards Source License v1.1",
        true,
        false
    ],
    "SISSL-1.2": [
        "Sun Industry Standards Source License v1.2",
        false,
        false
    ],
    "SL": [
        "SL License",
        false,
        false
    ],
    "Sleepycat": [
        "Sleepycat License",
        true,
        false
    ],
    "SMAIL-GPL": [
        "SMAIL General Public License",
        false,
        false
    ],
    "SMLNJ": [
        "Standard ML of New Jersey License",
        false,
        false
    ],
    "SMPPL": [
        "Secure Messaging Protocol Public License",
        false,
        false
    ],
    "SNIA": [
        "SNIA Public License 1.1",
        false,
        false
    ],
    "snprintf": [
        "snprintf License",
        false,
        false
    ],
    "SOFA": [
        "SOFA Software License",
        false,
        false
    ],
    "softSurfer": [
        "softSurfer License",
        false,
        false
    ],
    "Soundex": [
        "Soundex License",
        false,
        false
    ],
    "Spencer-86": [
        "Spencer License 86",
        false,
        false
    ],
    "Spencer-94": [
        "Spencer License 94",
        false,
        false
    ],
    "Spencer-99": [
        "Spencer License 99",
        false,
        false
    ],
    "SPL-1.0": [
        "Sun Public License v1.0",
        true,
        false
    ],
    "ssh-keyscan": [
        "ssh-keyscan License",
        false,
        false
    ],
    "SSH-OpenSSH": [
        "SSH OpenSSH license",
        false,
        false
    ],
    "SSH-short": [
        "SSH short notice",
        false,
        false
    ],
    "SSLeay-standalone": [
        "SSLeay License - standalone",
        false,
        false
    ],
    "SSPL-1.0": [
        "Server Side Public License, v 1",
        false,
        false
    ],
    "StandardML-NJ": [
        "Standard ML of New Jersey License",
        false,
        true
    ],
    "SugarCRM-1.1.3": [
        "SugarCRM Public License v1.1.3",
        false,
        false
    ],
    "SUL-1.0": [
        "Sustainable Use License v1.0",
        false,
        false
    ],
    "Sun-PPP": [
        "Sun PPP License",
        false,
        false
    ],
    "Sun-PPP-2000": [
        "Sun PPP License (2000)",
        false,
        false
    ],
    "SunPro": [
        "SunPro License",
        false,
        false
    ],
    "SWL": [
        "Scheme Widget Library (SWL) Software License Agreement",
        false,
        false
    ],
    "swrule": [
        "swrule License",
        false,
        false
    ],
    "Symlinks": [
        "Symlinks License",
        false,
        false
    ],
    "TAPR-OHL-1.0": [
        "TAPR Open Hardware License v1.0",
        false,
        false
    ],
    "TCL": [
        "TCL/TK License",
        false,
        false
    ],
    "TCP-wrappers": [
        "TCP Wrappers License",
        false,
        false
    ],
    "TekHVC": [
        "TekHVC License",
        false,
        false
    ],
    "TermReadKey": [
        "TermReadKey License",
        false,
        false
    ],
    "TGPPL-1.0": [
        "Transitive Grace Period Public Licence 1.0",
        false,
        false
    ],
    "ThirdEye": [
        "ThirdEye License",
        false,
        false
    ],
    "threeparttable": [
        "threeparttable License",
        false,
        false
    ],
    "TMate": [
        "TMate Open Source License",
        false,
        false
    ],
    "TORQUE-1.1": [
        "TORQUE v2.5+ Software License v1.1",
        false,
        false
    ],
    "TOSL": [
        "Trusster Open Source License",
        false,
        false
    ],
    "TPDL": [
        "Time::ParseDate License",
        false,
        false
    ],
    "TPL-1.0": [
        "THOR Public License 1.0",
        false,
        false
    ],
    "TrustedQSL": [
        "TrustedQSL License",
        false,
        false
    ],
    "TTWL": [
        "Text-Tabs+Wrap License",
        false,
        false
    ],
    "TTYP0": [
        "TTYP0 License",
        false,
        false
    ],
    "TU-Berlin-1.0": [
        "Technische Universitaet Berlin License 1.0",
        false,
        false
    ],
    "TU-Berlin-2.0": [
        "Technische Universitaet Berlin License 2.0",
        false,
        false
    ],
    "Ubuntu-font-1.0": [
        "Ubuntu Font Licence v1.0",
        false,
        false
    ],
    "UCAR": [
        "UCAR License",
        false,
        false
    ],
    "UCL-1.0": [
        "Upstream Compatibility License v1.0",
        true,
        false
    ],
    "ulem": [
        "ulem License",
        false,
        false
    ],
    "UMich-Merit": [
        "Michigan/Merit Networks License",
        false,
        false
    ],
    "Unicode-3.0": [
        "Unicode License v3",
        true,
        false
    ],
    "Unicode-DFS-2015": [
        "Unicode License Agreement - Data Files and Software (2015)",
        false,
        false
    ],
    "Unicode-DFS-2016": [
        "Unicode License Agreement - Data Files and Software (2016)",
        true,
        false
    ],
    "Unicode-TOU": [
        "Unicode Terms of Use",
        false,
        false
    ],
    "UnixCrypt": [
        "UnixCrypt License",
        false,
        false
    ],
    "Unlicense": [
        "The Unlicense",
        true,
        false
    ],
    "Unlicense-libtelnet": [
        "Unlicense - libtelnet variant",
        false,
        false
    ],
    "Unlicense-libwhirlpool": [
        "Unlicense - libwhirlpool variant",
        false,
        false
    ],
    "UnRAR": [
        "UnRAR License",
        false,
        false
    ],
    "UPL-1.0": [
        "Universal Permissive License v1.0",
        true,
        false
    ],
    "URT-RLE": [
        "Utah Raster Toolkit Run Length Encoded License",
        false,
        false
    ],
    "Vim": [
        "Vim License",
        false,
        false
    ],
    "Vixie-Cron": [
        "Vixie Cron License",
        false,
        false
    ],
    "VOSTROM": [
        "VOSTROM Public License for Open Source",
        false,
        false
    ],
    "VSL-1.0": [
        "Vovida Software License v1.0",
        true,
        false
    ],
    "W3C": [
        "W3C Software Notice and License (2002-12-31)",
        true,
        false
    ],
    "W3C-19980720": [
        "W3C Software Notice and License (1998-07-20)",
        false,
        false
    ],
    "W3C-20150513": [
        "W3C Software Notice and Document License (2015-05-13)",
        true,
        false
    ],
    "w3m": [
        "w3m License",
        false,
        false
    ],
    "Watcom-1.0": [
        "Sybase Open Watcom Public License 1.0",
        true,
        false
    ],
    "Widget-Workshop": [
        "Widget Workshop License",
        false,
        false
    ],
    "WordNet": [
        "WordNet License",
        true,
        false
    ],
    "Wsuipa": [
        "Wsuipa License",
        false,
        false
    ],
    "WTFNMFPL": [
        "Do What The F*ck You Want To But It's Not My Fault Public License",
        false,
        false
    ],
    "WTFPL": [
        "Do What The F*ck You Want To Public License",
        false,
        false
    ],
    "wwl": [
        "WWL License",
        false,
        false
    ],
    "wxWindows": [
        "wxWindows Library License",
        true,
        true
    ],
    "X11": [
        "X11 License",
        false,
        false
    ],
    "X11-distribute-modifications-variant": [
        "X11 License Distribution Modification Variant",
        false,
        false
    ],
    "X11-no-permit-persons": [
        "X11 no permit persons clause",
        false,
        false
    ],
    "X11-swapped": [
        "X11 swapped final paragraphs",
        false,
        false
    ],
    "Xdebug-1.03": [
        "Xdebug License v 1.03",
        false,
        false
    ],
    "Xerox": [
        "Xerox License",
        false,
        false
    ],
    "Xfig": [
        "Xfig License",
        false,
        false
    ],
    "XFree86-1.1": [
        "XFree86 License 1.1",
        false,
        false
    ],
    "xinetd": [
        "xinetd License",
        false,
        false
    ],
    "xkeyboard-config-Zinoviev": [
        "xkeyboard-config Zinoviev License",
        false,
        false
    ],
    "xlock": [
        "xlock License",
        false,
        false
    ],
    "Xnet": [
        "X.Net License",
        true,
        false
    ],
    "xpp": [
        "XPP License",
        false,
        false
    ],
    "XSkat": [
        "XSkat License",
        false,
        false
    ],
    "xzoom": [
        "xzoom License",
        false,
        false
    ],
    "YPL-1.0": [
        "Yahoo! Public License v1.0",
        false,
        false
    ],
    "YPL-1.1": [
        "Yahoo! Public License v1.1",
        false,
        false
    ],
    "Zed": [
        "Zed License",
        false,
        false
    ],
    "Zeeff": [
        "Zeeff License",
        false,
        false
    ],
    "Zend-2.0": [
        "Zend License v2.0",
        false,
        false
    ],
    "Zimbra-1.3": [
        "Zimbra Public License v1.3",
        false,
        false
    ],
    "Zimbra-1.4": [
        "Zimbra Public License v1.4",
        false,
        false
    ],
    "Zlib": [
        "zlib License",
        true,
        false
    ],
    "zlib-acknowledgement": [
        "zlib/libpng License with Acknowledgement",
        false,
        false
    ],
    "ZPL-1.1": [
        "Zope Public License 1.1",
        false,
        false
    ],
    "ZPL-2.0": [
        "Zope Public License 2.0",
        true,
        false
    ],
    "ZPL-2.1": [
        "Zope Public License 2.1",
        true,
        false
    ]
}Copyright (C) 2015 Composer

Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
composer/spdx-licenses
======================

SPDX (Software Package Data Exchange) licenses list and validation library.

Originally written as part of [composer/composer](https://github.com/composer/composer),
now extracted and made available as a stand-alone library.

[![Continuous Integration](https://github.com/composer/spdx-licenses/workflows/Continuous%20Integration/badge.svg?branch=main)](https://github.com/composer/spdx-licenses/actions)

Installation
------------

Install the latest version with:

```bash
$ composer require composer/spdx-licenses
```

Basic Usage
-----------

```php
<?php

use Composer\Spdx\SpdxLicenses;

$licenses = new SpdxLicenses();

// get a license by identifier
$licenses->getLicenseByIdentifier('MIT');

// get a license exception by identifier
$licenses->getExceptionByIdentifier('Autoconf-exception-3.0');

// get a license identifier by name
$licenses->getIdentifierByName('MIT License');

// check if a license is OSI approved by identifier
$licenses->isOsiApprovedByIdentifier('MIT');

// check if a license identifier is deprecated
$licenses->isDeprecatedByIdentifier('MIT');

// check if input is a valid SPDX license expression
$licenses->validate($input);
```

> Read the [specifications](https://spdx.org/specifications)
> to find out more about valid license expressions.

Requirements
------------

* PHP 5.3.2 is required but using the latest version of PHP is highly recommended.

License
-------

composer/spdx-licenses is licensed under the MIT License, see the LICENSE file for details.

Source
------

License information is curated by [SPDX](https://spdx.org/). The data is pulled from the
[License List Data](https://github.com/spdx/license-list-data) repository.

* [Licenses](https://spdx.org/licenses/index.html)
* [License Exceptions](https://spdx.org/licenses/exceptions-index.html)
{
    "name": "composer\/spdx-licenses",
    "description": "SPDX licenses list and validation library.",
    "type": "library",
    "license": "MIT",
    "keywords": [
        "spdx",
        "license",
        "validator"
    ],
    "authors": [
        {
            "name": "Nils Adermann",
            "email": "naderman@naderman.de",
            "homepage": "http:\/\/www.naderman.de"
        },
        {
            "name": "Jordi Boggiano",
            "email": "j.boggiano@seld.be",
            "homepage": "http:\/\/seld.be"
        },
        {
            "name": "Rob Bast",
            "email": "rob.bast@gmail.com",
            "homepage": "http:\/\/robbast.nl"
        }
    ],
    "support": {
        "irc": "ircs:\/\/irc.libera.chat:6697\/composer",
        "issues": "https:\/\/github.com\/composer\/spdx-licenses\/issues"
    },
    "require": {
        "php": "^7.2 || ^8.0"
    },
    "require-dev": {
        "symfony\/phpunit-bridge": "^6.4.25 || ^7.3.3 || ^8.0",
        "phpstan\/phpstan": "^1.11"
    },
    "autoload": {
        "psr-4": {
            "Composer\\Spdx\\": "src"
        }
    },
    "autoload-dev": {
        "psr-4": {
            "Composer\\Spdx\\": "tests"
        }
    },
    "extra": {
        "branch-alias": {
            "dev-main": "1.x-dev"
        }
    },
    "scripts": {
        "test": "SYMFONY_PHPUNIT_REMOVE_RETURN_TYPEHINT=1 vendor\/bin\/simple-phpunit",
        "phpstan": "vendor\/bin\/phpstan analyse",
        "sync-licenses": "bin\/update-spdx-licenses"
    }
}<?php

declare (strict_types=1);
/*
 * This file is part of composer/spdx-licenses.
 *
 * (c) Composer <https://github.com/composer>
 *
 * For the full copyright and license information, please view
 * the LICENSE file that was distributed with this source code.
 */
namespace Composer\Spdx;

class SpdxLicenses
{
    /** @var string */
    public const LICENSES_FILE = 'spdx-licenses.json';
    /** @var string */
    public const EXCEPTIONS_FILE = 'spdx-exceptions.json';
    /**
     * Contains all the licenses.
     *
     * The array is indexed by license identifiers, which contain
     * a numerically indexed array with license details.
     *
     *  [ lowercased license identifier =>
     *      [ 0 => identifier (string), 1 => full name (string), 2 => osi certified (bool), 3 => deprecated (bool) ]
     *    , ...
     *  ]
     *
     * @var array<string, array{0: string, 1: string, 2: bool, 3: bool}>
     */
    private $licenses;
    /**
     * @var string
     */
    private $licensesExpression;
    /**
     * Contains all the license exceptions.
     *
     * The array is indexed by license exception identifiers, which contain
     * a numerically indexed array with license exception details.
     *
     *  [ lowercased exception identifier =>
     *      [ 0 => exception identifier (string), 1 => full name (string) ]
     *    , ...
     *  ]
     *
     * @var array<string, array{0: string, 1: string}>
     */
    private $exceptions;
    /**
     * @var string
     */
    private $exceptionsExpression;
    public function __construct()
    {
        $this->loadLicenses();
        $this->loadExceptions();
    }
    /**
     * Returns license metadata by license identifier.
     *
     * This function adds a link to the full license text to the license metadata.
     * The array returned is in the form of:
     *
     *  [ 0 => full name (string), 1 => osi certified, 2 => link to license text (string), 3 => deprecation status (bool) ]
     *
     * @param string $identifier
     *
     * @return array{0: string, 1: bool, 2: string, 3: bool}|null
     */
    public function getLicenseByIdentifier($identifier)
    {
        $key = strtolower($identifier);
        if (!isset($this->licenses[$key])) {
            return null;
        }
        [$identifier, $name, $isOsiApproved, $isDeprecatedLicenseId] = $this->licenses[$key];
        return [$name, $isOsiApproved, 'https://spdx.org/licenses/' . $identifier . '.html#licenseText', $isDeprecatedLicenseId];
    }
    /**
     * Returns all licenses information, keyed by the lowercased license identifier.
     *
     * @return array{0: string, 1: string, 2: bool, 3: bool}[] Each item is [ 0 => identifier (string), 1 => full name (string), 2 => osi certified (bool), 3 => deprecated (bool) ]
     */
    public function getLicenses()
    {
        return $this->licenses;
    }
    /**
     * Returns license exception metadata by license exception identifier.
     *
     * This function adds a link to the full license exception text to the license exception metadata.
     * The array returned is in the form of:
     *
     *  [ 0 => full name (string), 1 => link to license text (string) ]
     *
     * @param string $identifier
     *
     * @return array{0: string, 1: string}|null
     */
    public function getExceptionByIdentifier($identifier)
    {
        $key = strtolower($identifier);
        if (!isset($this->exceptions[$key])) {
            return null;
        }
        [$identifier, $name] = $this->exceptions[$key];
        return [$name, 'https://spdx.org/licenses/' . $identifier . '.html#licenseExceptionText'];
    }
    /**
     * Returns the short identifier of a license (or license exception) by full name.
     *
     * @param string $name
     *
     * @return string|null
     */
    public function getIdentifierByName($name)
    {
        foreach ($this->licenses as $licenseData) {
            if ($licenseData[1] === $name) {
                return $licenseData[0];
            }
        }
        foreach ($this->exceptions as $licenseData) {
            if ($licenseData[1] === $name) {
                return $licenseData[0];
            }
        }
        return null;
    }
    /**
     * Returns the OSI Approved status for a license by identifier.
     *
     * @param string $identifier
     *
     * @return bool
     */
    public function isOsiApprovedByIdentifier($identifier)
    {
        return $this->licenses[strtolower($identifier)][2];
    }
    /**
     * Returns the deprecation status for a license by identifier.
     *
     * @param string $identifier
     *
     * @return bool
     */
    public function isDeprecatedByIdentifier($identifier)
    {
        return $this->licenses[strtolower($identifier)][3];
    }
    /**
     * @param string[]|string $license
     *
     * @throws \InvalidArgumentException
     *
     * @return bool
     */
    public function validate($license)
    {
        if (is_array($license)) {
            $count = count($license);
            if ($count !== count(array_filter($license, 'is_string'))) {
                throw new \InvalidArgumentException('Array of strings expected.');
            }
            $license = $count > 1 ? '(' . implode(' OR ', $license) . ')' : (string) reset($license);
        }
        if (!is_string($license)) {
            throw new \InvalidArgumentException(sprintf('Array or String expected, %s given.', gettype($license)));
        }
        return $this->isValidLicenseString($license);
    }
    /**
     * @return string
     */
    public static function getResourcesDir()
    {
        return dirname(__DIR__) . '/res';
    }
    /**
     * @return void
     */
    private function loadLicenses()
    {
        if (null !== $this->licenses) {
            return;
        }
        $json = file_get_contents(self::getResourcesDir() . '/' . self::LICENSES_FILE);
        if (\false === $json) {
            throw new \RuntimeException('Missing license file in ' . self::getResourcesDir() . '/' . self::LICENSES_FILE);
        }
        $this->licenses = [];
        foreach (json_decode($json, \true) as $identifier => $license) {
            $this->licenses[strtolower($identifier)] = [$identifier, $license[0], $license[1], $license[2]];
        }
    }
    /**
     * @return void
     */
    private function loadExceptions()
    {
        if (null !== $this->exceptions) {
            return;
        }
        $json = file_get_contents(self::getResourcesDir() . '/' . self::EXCEPTIONS_FILE);
        if (\false === $json) {
            throw new \RuntimeException('Missing exceptions file in ' . self::getResourcesDir() . '/' . self::EXCEPTIONS_FILE);
        }
        $this->exceptions = [];
        foreach (json_decode($json, \true) as $identifier => $exception) {
            $this->exceptions[strtolower($identifier)] = [$identifier, $exception[0]];
        }
    }
    /**
     * @return string
     */
    private function getLicensesExpression()
    {
        if (null === $this->licensesExpression) {
            $licenses = array_map('preg_quote', array_keys($this->licenses));
            rsort($licenses);
            $licenses = implode('|', $licenses);
            $this->licensesExpression = $licenses;
        }
        return $this->licensesExpression;
    }
    /**
     * @return string
     */
    private function getExceptionsExpression()
    {
        if (null === $this->exceptionsExpression) {
            $exceptions = array_map('preg_quote', array_keys($this->exceptions));
            rsort($exceptions);
            $exceptions = implode('|', $exceptions);
            $this->exceptionsExpression = $exceptions;
        }
        return $this->exceptionsExpression;
    }
    /**
     * @param string $license
     *
     * @throws \RuntimeException
     *
     * @return bool
     */
    private function isValidLicenseString($license)
    {
        if (isset($this->licenses[strtolower($license)])) {
            return \true;
        }
        $licenses = $this->getLicensesExpression();
        $exceptions = $this->getExceptionsExpression();
        $regex = <<<REGEX
{
(?(DEFINE)
    # idstring: 1*( ALPHA / DIGIT / - / . )
    (?<idstring>[\\pL\\pN.-]{1,})

    # license-id: taken from list
    (?<licenseid>{$licenses})

    # license-exception-id: taken from list
    (?<licenseexceptionid>{$exceptions})

    # license-ref: [DocumentRef-1*(idstring):]LicenseRef-1*(idstring)
    (?<licenseref>(?:DocumentRef-(?&idstring):)?LicenseRef-(?&idstring))

    # simple-expresssion: license-id / license-id+ / license-ref
    (?<simple_expression>(?&licenseid)\\+? | (?&licenseid) | (?&licenseref))

    # compound-expression: 1*(
    #   simple-expression /
    #   simple-expression WITH license-exception-id /
    #   compound-expression AND compound-expression /
    #   compound-expression OR compound-expression
    # ) / ( compound-expression ) )
    (?<compound_head>
        (?&simple_expression) ( \\s+ WITH \\s+ (?&licenseexceptionid))?
            | \\( \\s* (?&compound_expression) \\s* \\)
    )
    (?<compound_expression>
        (?&compound_head) (?: \\s+ (?:AND|OR) \\s+ (?&compound_expression))?
    )

    # license-expression: 1*1(simple-expression / compound-expression)
    (?<license_expression>(?&compound_expression) | (?&simple_expression))
) # end of define

^(NONE | NOASSERTION | (?&license_expression))\$
}xi
REGEX;
        $match = preg_match($regex, $license);
        if (0 === $match) {
            return \false;
        }
        if (\false === $match) {
            throw new \RuntimeException('Regex failed to compile/run.');
        }
        return \true;
    }
}
The MIT License (MIT)

Copyright (c) 2015 phpDocumentor

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
![Qa workflow](https://github.com/phpDocumentor/ReflectionCommon/workflows/Qa%20workflow/badge.svg)
[![Coveralls Coverage](https://img.shields.io/coveralls/github/phpDocumentor/ReflectionCommon.svg)](https://coveralls.io/github/phpDocumentor/ReflectionCommon?branch=master)
[![Scrutinizer Code Coverage](https://img.shields.io/scrutinizer/coverage/g/phpDocumentor/ReflectionCommon.svg)](https://scrutinizer-ci.com/g/phpDocumentor/ReflectionCommon/?branch=master)
[![Scrutinizer Code Quality](https://img.shields.io/scrutinizer/g/phpDocumentor/ReflectionCommon.svg)](https://scrutinizer-ci.com/g/phpDocumentor/ReflectionCommon/?branch=master)
[![Stable Version](https://img.shields.io/packagist/v/phpDocumentor/Reflection-Common.svg)](https://packagist.org/packages/phpDocumentor/Reflection-Common)
[![Unstable Version](https://img.shields.io/packagist/vpre/phpDocumentor/Reflection-Common.svg)](https://packagist.org/packages/phpDocumentor/Reflection-Common)


ReflectionCommon
================
{
    "name": "phpdocumentor\/reflection-common",
    "keywords": [
        "phpdoc",
        "phpDocumentor",
        "reflection",
        "static analysis",
        "FQSEN"
    ],
    "homepage": "http:\/\/www.phpdoc.org",
    "description": "Common reflection classes used by phpdocumentor to reflect the code structure",
    "license": "MIT",
    "authors": [
        {
            "name": "Jaap van Otterdijk",
            "email": "opensource@ijaap.nl"
        }
    ],
    "require": {
        "php": "^7.2 || ^8.0"
    },
    "autoload": {
        "psr-4": {
            "_ContaoManager\\phpDocumentor\\Reflection\\": "src\/"
        }
    },
    "require-dev": {},
    "extra": {
        "branch-alias": {
            "dev-2.x": "2.x-dev"
        }
    }
}<?php

declare (strict_types=1);
/**
 * phpDocumentor
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @link      http://phpdoc.org
 */
namespace _ContaoManager\phpDocumentor\Reflection;

/**
 * Interface for Api Elements
 */
interface Element
{
    /**
     * Returns the Fqsen of the element.
     */
    public function getFqsen(): Fqsen;
    /**
     * Returns the name of the element.
     */
    public function getName(): string;
}
<?php

declare (strict_types=1);
/**
 * phpDocumentor
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @link      http://phpdoc.org
 */
namespace _ContaoManager\phpDocumentor\Reflection;

/**
 * Interface for project factories. A project factory shall convert a set of files
 * into an object implementing the Project interface.
 */
interface ProjectFactory
{
    /**
     * Creates a project from the set of files.
     *
     * @param File[] $files
     */
    public function create(string $name, array $files): Project;
}
<?php

declare (strict_types=1);
/**
 * This file is part of phpDocumentor.
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @link      http://phpdoc.org
 */
namespace _ContaoManager\phpDocumentor\Reflection;

/**
 * Interface for files processed by the ProjectFactory
 */
interface File
{
    /**
     * Returns the content of the file as a string.
     */
    public function getContents(): string;
    /**
     * Returns md5 hash of the file.
     */
    public function md5(): string;
    /**
     * Returns an relative path to the file.
     */
    public function path(): string;
}
<?php

declare (strict_types=1);
/**
 * phpDocumentor
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @link      http://phpdoc.org
 */
namespace _ContaoManager\phpDocumentor\Reflection;

/**
 * Interface for project. Since the definition of a project can be different per factory this interface will be small.
 */
interface Project
{
    /**
     * Returns the name of the project.
     */
    public function getName(): string;
}
<?php

declare (strict_types=1);
/**
 * phpDocumentor
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @link      http://phpdoc.org
 */
namespace _ContaoManager\phpDocumentor\Reflection;

use InvalidArgumentException;
use function assert;
use function end;
use function explode;
use function is_string;
use function preg_match;
use function sprintf;
use function trim;
/**
 * Value Object for Fqsen.
 *
 * @link https://github.com/phpDocumentor/fig-standards/blob/master/proposed/phpdoc-meta.md
 *
 * @psalm-immutable
 */
final class Fqsen
{
    /** @var string full quallified class name */
    private $fqsen;
    /** @var string name of the element without path. */
    private $name;
    /**
     * Initializes the object.
     *
     * @throws InvalidArgumentException when $fqsen is not matching the format.
     */
    public function __construct(string $fqsen)
    {
        $matches = [];
        $result = preg_match(
            //phpcs:ignore Generic.Files.LineLength.TooLong
            '/^\\\\([a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff\\\\]*)?(?:[:]{2}\$?([a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*))?(?:\(\))?$/',
            $fqsen,
            $matches
        );
        if ($result === 0) {
            throw new InvalidArgumentException(sprintf('"%s" is not a valid Fqsen.', $fqsen));
        }
        $this->fqsen = $fqsen;
        if (isset($matches[2])) {
            $this->name = $matches[2];
        } else {
            $matches = explode('\\', $fqsen);
            $name = end($matches);
            assert(is_string($name));
            $this->name = trim($name, '()');
        }
    }
    /**
     * converts this class to string.
     */
    public function __toString(): string
    {
        return $this->fqsen;
    }
    /**
     * Returns the name of the element without path.
     */
    public function getName(): string
    {
        return $this->name;
    }
}
<?php

declare (strict_types=1);
/**
 * This file is part of phpDocumentor.
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @link      http://phpdoc.org
 */
namespace _ContaoManager\phpDocumentor\Reflection;

/**
 * The location where an element occurs within a file.
 *
 * @psalm-immutable
 */
final class Location
{
    /** @var int */
    private $lineNumber = 0;
    /** @var int */
    private $columnNumber = 0;
    /**
     * Initializes the location for an element using its line number in the file and optionally the column number.
     */
    public function __construct(int $lineNumber, int $columnNumber = 0)
    {
        $this->lineNumber = $lineNumber;
        $this->columnNumber = $columnNumber;
    }
    /**
     * Returns the line number that is covered by this location.
     */
    public function getLineNumber(): int
    {
        return $this->lineNumber;
    }
    /**
     * Returns the column number (character position on a line) for this location object.
     */
    public function getColumnNumber(): int
    {
        return $this->columnNumber;
    }
}
The MIT License (MIT)

Copyright (c) 2010 Mike van Riel

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
<?xml version="1.0" encoding="UTF-8" ?>
<phpdocumentor
        configVersion="3"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns="https://www.phpdoc.org"
        xsi:noNamespaceSchemaLocation="data/xsd/phpdoc.xsd"
>
    <title>Type Resolver</title>
    <paths>
        <output>build/docs</output>
    </paths>
    <version number="0.2.0">
        <folder>latest</folder>
        <api>
            <source dsn="./">
                <path>src/</path>
            </source>
            <output>api</output>
            <ignore hidden="true" symlinks="true">
                <path>tests/**/*</path>
                <path>build/**/*</path>
                <path>var/**/*</path>
                <path>vendor/**/*</path>
            </ignore>
            <extensions>
                <extension>php</extension>
            </extensions>
            <ignore-tags>
                <ignore-tag>template</ignore-tag>
                <ignore-tag>template-extends</ignore-tag>
                <ignore-tag>template-implements</ignore-tag>
                <ignore-tag>extends</ignore-tag>
                <ignore-tag>implements</ignore-tag>
            </ignore-tags>
            <default-package-name>phpDocumentor</default-package-name>
        </api>
        <guide>
            <source dsn=".">
                <path>docs</path>
            </source>
            <output>guides</output>
        </guide>
    </version>
    <setting name="guides.enabled" value="true"/>
    <template name="default" />
</phpdocumentor>
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
![](https://github.com/phpdocumentor/typeresolver/workflows/Qa%20workflow/badge.svg?branch=1.x)
[![Coveralls Coverage](https://img.shields.io/coveralls/github/phpDocumentor/TypeResolver.svg)](https://coveralls.io/github/phpDocumentor/TypeResolver?branch=1.x)
[![Scrutinizer Code Coverage](https://img.shields.io/scrutinizer/coverage/g/phpDocumentor/TypeResolver.svg)](https://scrutinizer-ci.com/g/phpDocumentor/TypeResolver/?branch=1.x)
[![Scrutinizer Code Quality](https://img.shields.io/scrutinizer/g/phpDocumentor/TypeResolver.svg)](https://scrutinizer-ci.com/g/phpDocumentor/TypeResolver/?branch=1.x)
![Packagist Version](https://img.shields.io/packagist/v/phpdocumentor/type-resolver?label=Packagist%20stable)
![Packagist Version](https://img.shields.io/packagist/vpre/phpdocumentor/type-resolver?label=Packagist%20unstable)

TypeResolver and FqsenResolver
==============================

The specification on types in DocBlocks (PSR-5) describes various keywords and special constructs
but also how to statically resolve the partial name of a Class into a Fully Qualified Class Name (FQCN).

PSR-5 also introduces an additional way to describe deeper elements than Classes, Interfaces and Traits 
called the Fully Qualified Structural Element Name (FQSEN). Using this it is possible to refer to methods,
properties and class constants but also functions and global constants.

This package provides two Resolvers that are capable of 

1. Returning a series of Value Object for given expression while resolving any partial class names, and 
2. Returning an FQSEN object after resolving any partial Structural Element Names into Fully Qualified Structural 
   Element names.

## Installing

The easiest way to install this library is with [Composer](https://getcomposer.org) using the following command:

    $ composer require phpdocumentor/type-resolver

## Examples

Ready to dive in and don't want to read through all that text below? Just consult the [examples](examples) folder and check which type of action that your want to accomplish.

## On Types and Element Names

This component can be used in one of two ways
 
1. To resolve a Type or
2. To resolve a Fully Qualified Structural Element Name
 
The big difference between these two is in the number of things it can resolve. 

The TypeResolver can resolve:

- a php primitive or pseudo-primitive such as a string or void (`@var string` or `@return void`).
- a composite such as an array of string (`@var string[]`).
- a compound such as a string or integer (`@var string|integer`).
- an array expression (`@var (string|TypeResolver)[]`)
- an object or interface such as the TypeResolver class (`@var TypeResolver` 
  or `@var \phpDocumentor\Reflection\TypeResolver`)

  > please note that if you want to pass partial class names that additional steps are necessary, see the 
  > chapter `Resolving partial classes and FQSENs` for more information.

Where the FqsenResolver can resolve:

- Constant expressions (i.e. `@see \MyNamespace\MY_CONSTANT`)
- Function expressions (i.e. `@see \MyNamespace\myFunction()`)
- Class expressions (i.e. `@see \MyNamespace\MyClass`)
- Interface expressions (i.e. `@see \MyNamespace\MyInterface`)
- Trait expressions (i.e. `@see \MyNamespace\MyTrait`)
- Class constant expressions (i.e. `@see \MyNamespace\MyClass::MY_CONSTANT`)
- Property expressions (i.e. `@see \MyNamespace\MyClass::$myProperty`)
- Method expressions (i.e. `@see \MyNamespace\MyClass::myMethod()`)

## Resolving a type

In order to resolve a type you will have to instantiate the class `\phpDocumentor\Reflection\TypeResolver` and call its `resolve` method like this:

```php
$typeResolver = new \phpDocumentor\Reflection\TypeResolver();
$type = $typeResolver->resolve('string|integer');
```

In this example you will receive a Value Object of class `\phpDocumentor\Reflection\Types\Compound` that has two 
elements, one of type `\phpDocumentor\Reflection\Types\String_` and one of type 
`\phpDocumentor\Reflection\Types\Integer`.

The real power of this resolver is in its capability to expand partial class names into fully qualified class names; but in order to do that we need an additional `\phpDocumentor\Reflection\Types\Context` class that will inform the resolver in which namespace the given expression occurs and which namespace aliases (or imports) apply.

### Resolving nullable types

Php 7.1 introduced nullable types e.g. `?string`. Type resolver will resolve the original type without the nullable notation `?`
just like it would do without the `?`. After that the type is wrapped in a `\phpDocumentor\Reflection\Types\Nullable` object.
The `Nullable` type has a method to fetch the actual type. 

## Resolving an FQSEN

A Fully Qualified Structural Element Name is a reference to another element in your code bases and can be resolved using the `\phpDocumentor\Reflection\FqsenResolver` class' `resolve` method, like this:

```php
$fqsenResolver = new \phpDocumentor\Reflection\FqsenResolver();
$fqsen = $fqsenResolver->resolve('\phpDocumentor\Reflection\FqsenResolver::resolve()');
```

In this example we resolve a Fully Qualified Structural Element Name (meaning that it includes the full namespace, class name and element name) and receive a Value Object of type `\phpDocumentor\Reflection\Fqsen`.

The real power of this resolver is in its capability to expand partial element names into Fully Qualified Structural Element Names; but in order to do that we need an additional `\phpDocumentor\Reflection\Types\Context` class that will inform the resolver in which namespace the given expression occurs and which namespace aliases (or imports) apply.

## Resolving partial Classes and Structural Element Names

Perhaps the best feature of this library is that it knows how to resolve partial class names into fully qualified class names.

For example, you have this file:

```php
namespace My\Example;

use phpDocumentor\Reflection\Types;

class Classy
{
    /**
     * @var Types\Context
     * @see Classy::otherFunction()
     */
    public function __construct($context) {}
    
    public function otherFunction(){}
}
```

Suppose that you would want to resolve (and expand) the type in the `@var` tag and the element name in the `@see` tag.

For the resolvers to know how to expand partial names you have to provide a bit of _Context_ for them by instantiating a new class named `\phpDocumentor\Reflection\Types\Context` with the name of the namespace and the aliases that are in play.

### Creating a Context

You can do this by manually creating a Context like this:

```php
$context = new \phpDocumentor\Reflection\Types\Context(
    '\My\Example', 
    [ 'Types' => '\phpDocumentor\Reflection\Types']
);
```

Or by using the `\phpDocumentor\Reflection\Types\ContextFactory` to instantiate a new context based on a Reflector object or by providing the namespace that you'd like to extract and the source code of the file in which the given type expression occurs.

```php
$contextFactory = new \phpDocumentor\Reflection\Types\ContextFactory();
$context = $contextFactory->createFromReflector(new ReflectionMethod('\My\Example\Classy', '__construct'));
```

or

```php
$contextFactory = new \phpDocumentor\Reflection\Types\ContextFactory();
$context = $contextFactory->createForNamespace('\My\Example', file_get_contents('My/Example/Classy.php'));
```

### Using the Context

After you have obtained a Context it is just a matter of passing it along with the `resolve` method of either Resolver class as second argument and the Resolvers will take this into account when resolving partial names.

To obtain the resolved class name for the `@var` tag in the example above you can do:

```php
$typeResolver = new \phpDocumentor\Reflection\TypeResolver();
$type = $typeResolver->resolve('Types\Context', $context);
```

When you do this you will receive an object of class `\phpDocumentor\Reflection\Types\Object_` for which you can call the `getFqsen` method to receive a Value Object that represents the complete FQSEN. So that would be `phpDocumentor\Reflection\Types\Context`.

> Why is the FQSEN wrapped in another object `Object_`?
> 
> The resolve method of the TypeResolver only returns object with the interface `Type` and the FQSEN is a common type that does not represent a Type. Also: in some cases a type can represent an "Untyped Object", meaning that it is an object (signified by the `object` keyword) but does not refer to a specific element using an FQSEN.

Another example is on how to resolve the FQSEN of a method as can be seen with the `@see` tag in the example above. To resolve that you can do the following:

```php
$fqsenResolver = new \phpDocumentor\Reflection\FqsenResolver();
$type = $fqsenResolver->resolve('Classy::otherFunction()', $context);
```

Because Classy is a Class in the current namespace its FQSEN will have the `My\Example` namespace and by calling the `resolve` method of the FQSEN Resolver you will receive an `Fqsen` object that refers to `\My\Example\Classy::otherFunction()`.
{
    "name": "phpdocumentor\/type-resolver",
    "description": "A PSR-5 based resolver of Class names, Types and Structural Element Names",
    "type": "library",
    "license": "MIT",
    "authors": [
        {
            "name": "Mike van Riel",
            "email": "me@mikevanriel.com"
        }
    ],
    "require": {
        "php": "^7.3 || ^8.0",
        "phpdocumentor\/reflection-common": "^2.0",
        "phpstan\/phpdoc-parser": "^1.18|^2.0",
        "doctrine\/deprecations": "^1.0"
    },
    "require-dev": {
        "ext-tokenizer": "*",
        "phpunit\/phpunit": "^9.5",
        "phpstan\/phpstan": "^1.8",
        "phpstan\/phpstan-phpunit": "^1.1",
        "phpstan\/extension-installer": "^1.1",
        "vimeo\/psalm": "^4.25",
        "rector\/rector": "^0.13.9",
        "phpbench\/phpbench": "^1.2"
    },
    "autoload": {
        "psr-4": {
            "_ContaoManager\\phpDocumentor\\Reflection\\": "src"
        }
    },
    "autoload-dev": {
        "psr-4": {
            "_ContaoManager\\phpDocumentor\\Reflection\\": [
                "tests\/unit",
                "tests\/benchmark"
            ]
        }
    },
    "extra": {
        "branch-alias": {
            "dev-1.x": "1.x-dev"
        }
    },
    "config": {
        "platform": {
            "php": "7.3.0"
        },
        "allow-plugins": {
            "phpstan\/extension-installer": true
        }
    }
}<?php

declare (strict_types=1);
/**
 * This file is part of phpDocumentor.
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @link      http://phpdoc.org
 */
namespace _ContaoManager\phpDocumentor\Reflection;

use _ContaoManager\Doctrine\Deprecations\Deprecation;
use InvalidArgumentException;
use _ContaoManager\phpDocumentor\Reflection\PseudoTypes\ArrayShape;
use _ContaoManager\phpDocumentor\Reflection\PseudoTypes\ArrayShapeItem;
use _ContaoManager\phpDocumentor\Reflection\PseudoTypes\CallableString;
use _ContaoManager\phpDocumentor\Reflection\PseudoTypes\Conditional;
use _ContaoManager\phpDocumentor\Reflection\PseudoTypes\ConditionalForParameter;
use _ContaoManager\phpDocumentor\Reflection\PseudoTypes\ConstExpression;
use _ContaoManager\phpDocumentor\Reflection\PseudoTypes\False_;
use _ContaoManager\phpDocumentor\Reflection\PseudoTypes\FloatValue;
use _ContaoManager\phpDocumentor\Reflection\PseudoTypes\HtmlEscapedString;
use _ContaoManager\phpDocumentor\Reflection\PseudoTypes\IntegerRange;
use _ContaoManager\phpDocumentor\Reflection\PseudoTypes\IntegerValue;
use _ContaoManager\phpDocumentor\Reflection\PseudoTypes\IntMask;
use _ContaoManager\phpDocumentor\Reflection\PseudoTypes\IntMaskOf;
use _ContaoManager\phpDocumentor\Reflection\PseudoTypes\KeyOf;
use _ContaoManager\phpDocumentor\Reflection\PseudoTypes\List_;
use _ContaoManager\phpDocumentor\Reflection\PseudoTypes\ListShape;
use _ContaoManager\phpDocumentor\Reflection\PseudoTypes\ListShapeItem;
use _ContaoManager\phpDocumentor\Reflection\PseudoTypes\LiteralString;
use _ContaoManager\phpDocumentor\Reflection\PseudoTypes\LowercaseString;
use _ContaoManager\phpDocumentor\Reflection\PseudoTypes\NegativeInteger;
use _ContaoManager\phpDocumentor\Reflection\PseudoTypes\NonEmptyArray;
use _ContaoManager\phpDocumentor\Reflection\PseudoTypes\NonEmptyList;
use _ContaoManager\phpDocumentor\Reflection\PseudoTypes\NonEmptyLowercaseString;
use _ContaoManager\phpDocumentor\Reflection\PseudoTypes\NonEmptyString;
use _ContaoManager\phpDocumentor\Reflection\PseudoTypes\Numeric_;
use _ContaoManager\phpDocumentor\Reflection\PseudoTypes\NumericString;
use _ContaoManager\phpDocumentor\Reflection\PseudoTypes\ObjectShape;
use _ContaoManager\phpDocumentor\Reflection\PseudoTypes\ObjectShapeItem;
use _ContaoManager\phpDocumentor\Reflection\PseudoTypes\OffsetAccess;
use _ContaoManager\phpDocumentor\Reflection\PseudoTypes\PositiveInteger;
use _ContaoManager\phpDocumentor\Reflection\PseudoTypes\StringValue;
use _ContaoManager\phpDocumentor\Reflection\PseudoTypes\TraitString;
use _ContaoManager\phpDocumentor\Reflection\PseudoTypes\True_;
use _ContaoManager\phpDocumentor\Reflection\PseudoTypes\ValueOf;
use _ContaoManager\phpDocumentor\Reflection\Types\AggregatedType;
use _ContaoManager\phpDocumentor\Reflection\Types\Array_;
use _ContaoManager\phpDocumentor\Reflection\Types\ArrayKey;
use _ContaoManager\phpDocumentor\Reflection\Types\Boolean;
use _ContaoManager\phpDocumentor\Reflection\Types\Callable_;
use _ContaoManager\phpDocumentor\Reflection\Types\CallableParameter;
use _ContaoManager\phpDocumentor\Reflection\Types\ClassString;
use _ContaoManager\phpDocumentor\Reflection\Types\Collection;
use _ContaoManager\phpDocumentor\Reflection\Types\Compound;
use _ContaoManager\phpDocumentor\Reflection\Types\Context;
use _ContaoManager\phpDocumentor\Reflection\Types\Expression;
use _ContaoManager\phpDocumentor\Reflection\Types\Float_;
use _ContaoManager\phpDocumentor\Reflection\Types\Integer;
use _ContaoManager\phpDocumentor\Reflection\Types\InterfaceString;
use _ContaoManager\phpDocumentor\Reflection\Types\Intersection;
use _ContaoManager\phpDocumentor\Reflection\Types\Iterable_;
use _ContaoManager\phpDocumentor\Reflection\Types\Mixed_;
use _ContaoManager\phpDocumentor\Reflection\Types\Never_;
use _ContaoManager\phpDocumentor\Reflection\Types\Null_;
use _ContaoManager\phpDocumentor\Reflection\Types\Nullable;
use _ContaoManager\phpDocumentor\Reflection\Types\Object_;
use _ContaoManager\phpDocumentor\Reflection\Types\Parent_;
use _ContaoManager\phpDocumentor\Reflection\Types\Resource_;
use _ContaoManager\phpDocumentor\Reflection\Types\Scalar;
use _ContaoManager\phpDocumentor\Reflection\Types\Self_;
use _ContaoManager\phpDocumentor\Reflection\Types\Static_;
use _ContaoManager\phpDocumentor\Reflection\Types\String_;
use _ContaoManager\phpDocumentor\Reflection\Types\This;
use _ContaoManager\phpDocumentor\Reflection\Types\Void_;
use _ContaoManager\PHPStan\PhpDocParser\Ast\ConstExpr\ConstExprFloatNode;
use _ContaoManager\PHPStan\PhpDocParser\Ast\ConstExpr\ConstExprIntegerNode;
use _ContaoManager\PHPStan\PhpDocParser\Ast\ConstExpr\ConstExprStringNode;
use _ContaoManager\PHPStan\PhpDocParser\Ast\ConstExpr\ConstFetchNode;
use _ContaoManager\PHPStan\PhpDocParser\Ast\Type\ArrayShapeItemNode;
use _ContaoManager\PHPStan\PhpDocParser\Ast\Type\ArrayShapeNode;
use _ContaoManager\PHPStan\PhpDocParser\Ast\Type\ArrayTypeNode;
use _ContaoManager\PHPStan\PhpDocParser\Ast\Type\CallableTypeNode;
use _ContaoManager\PHPStan\PhpDocParser\Ast\Type\CallableTypeParameterNode;
use _ContaoManager\PHPStan\PhpDocParser\Ast\Type\ConditionalTypeForParameterNode;
use _ContaoManager\PHPStan\PhpDocParser\Ast\Type\ConditionalTypeNode;
use _ContaoManager\PHPStan\PhpDocParser\Ast\Type\ConstTypeNode;
use _ContaoManager\PHPStan\PhpDocParser\Ast\Type\GenericTypeNode;
use _ContaoManager\PHPStan\PhpDocParser\Ast\Type\IdentifierTypeNode;
use _ContaoManager\PHPStan\PhpDocParser\Ast\Type\IntersectionTypeNode;
use _ContaoManager\PHPStan\PhpDocParser\Ast\Type\NullableTypeNode;
use _ContaoManager\PHPStan\PhpDocParser\Ast\Type\ObjectShapeItemNode;
use _ContaoManager\PHPStan\PhpDocParser\Ast\Type\ObjectShapeNode;
use _ContaoManager\PHPStan\PhpDocParser\Ast\Type\OffsetAccessTypeNode;
use _ContaoManager\PHPStan\PhpDocParser\Ast\Type\ThisTypeNode;
use _ContaoManager\PHPStan\PhpDocParser\Ast\Type\TypeNode;
use _ContaoManager\PHPStan\PhpDocParser\Ast\Type\UnionTypeNode;
use _ContaoManager\PHPStan\PhpDocParser\Lexer\Lexer;
use _ContaoManager\PHPStan\PhpDocParser\Parser\ConstExprParser;
use _ContaoManager\PHPStan\PhpDocParser\Parser\ParserException;
use _ContaoManager\PHPStan\PhpDocParser\Parser\TokenIterator;
use _ContaoManager\PHPStan\PhpDocParser\Parser\TypeParser;
use _ContaoManager\PHPStan\PhpDocParser\ParserConfig;
use RuntimeException;
use function array_filter;
use function array_key_exists;
use function array_map;
use function array_reverse;
use function class_exists;
use function class_implements;
use function get_class;
use function in_array;
use function sprintf;
use function strpos;
use function strtolower;
use function substr;
use function trim;
final class TypeResolver
{
    /** @var string Definition of the NAMESPACE operator in PHP */
    private const OPERATOR_NAMESPACE = '\\';
    /**
     * @var array<string, string> List of recognized keywords and unto which Value Object they map
     * @psalm-var array<string, class-string<Type>>
     */
    private $keywords = ['string' => String_::class, 'class-string' => ClassString::class, 'interface-string' => InterfaceString::class, 'html-escaped-string' => HtmlEscapedString::class, 'lowercase-string' => LowercaseString::class, 'non-empty-lowercase-string' => NonEmptyLowercaseString::class, 'non-empty-string' => NonEmptyString::class, 'numeric-string' => NumericString::class, 'numeric' => Numeric_::class, 'trait-string' => TraitString::class, 'int' => Integer::class, 'integer' => Integer::class, 'positive-int' => PositiveInteger::class, 'negative-int' => NegativeInteger::class, 'bool' => Boolean::class, 'boolean' => Boolean::class, 'real' => Float_::class, 'float' => Float_::class, 'double' => Float_::class, 'object' => Object_::class, 'mixed' => Mixed_::class, 'array' => Array_::class, 'array-key' => ArrayKey::class, 'non-empty-array' => NonEmptyArray::class, 'resource' => Resource_::class, 'void' => Void_::class, 'null' => Null_::class, 'scalar' => Scalar::class, 'callback' => Callable_::class, 'callable' => Callable_::class, 'callable-string' => CallableString::class, 'false' => False_::class, 'true' => True_::class, 'literal-string' => LiteralString::class, 'self' => Self_::class, '$this' => This::class, 'static' => Static_::class, 'parent' => Parent_::class, 'iterable' => Iterable_::class, 'never' => Never_::class, 'list' => List_::class, 'non-empty-list' => NonEmptyList::class];
    /**
     * @psalm-readonly
     * @var FqsenResolver
     */
    private $fqsenResolver;
    /**
     * @psalm-readonly
     * @var TypeParser
     */
    private $typeParser;
    /**
     * @psalm-readonly
     * @var Lexer
     */
    private $lexer;
    /**
     * Initializes this TypeResolver with the means to create and resolve Fqsen objects.
     */
    public function __construct(?FqsenResolver $fqsenResolver = null)
    {
        $this->fqsenResolver = $fqsenResolver ?: new FqsenResolver();
        if (class_exists(ParserConfig::class)) {
            $this->typeParser = new TypeParser(new ParserConfig([]), new ConstExprParser(new ParserConfig([])));
            $this->lexer = new Lexer(new ParserConfig([]));
        } else {
            $this->typeParser = new TypeParser(new ConstExprParser());
            $this->lexer = new Lexer();
        }
    }
    /**
     * Analyzes the given type and returns the FQCN variant.
     *
     * When a type is provided this method checks whether it is not a keyword or
     * Fully Qualified Class Name. If so it will use the given namespace and
     * aliases to expand the type to a FQCN representation.
     *
     * This method only works as expected if the namespace and aliases are set;
     * no dynamic reflection is being performed here.
     *
     * @uses Context::getNamespace()        to determine with what to prefix the type name.
     * @uses Context::getNamespaceAliases() to check whether the first part of the relative type name should not be
     * replaced with another namespace.
     *
     * @param string $type The relative or absolute type.
     */
    public function resolve(string $type, ?Context $context = null): Type
    {
        $type = trim($type);
        if (!$type) {
            throw new InvalidArgumentException('Attempted to resolve "' . $type . '" but it appears to be empty');
        }
        if ($context === null) {
            $context = new Context('');
        }
        $tokens = $this->lexer->tokenize($type);
        $tokenIterator = new TokenIterator($tokens);
        $ast = $this->parse($tokenIterator);
        $type = $this->createType($ast, $context);
        return $this->tryParseRemainingCompoundTypes($tokenIterator, $context, $type);
    }
    public function createType(?TypeNode $type, Context $context): Type
    {
        if ($type === null) {
            return new Mixed_();
        }
        switch (get_class($type)) {
            case ArrayTypeNode::class:
                return new Array_($this->createType($type->type, $context));
            case ArrayShapeNode::class:
                switch ($type->kind) {
                    case ArrayShapeNode::KIND_ARRAY:
                        return new ArrayShape(...array_map(function (ArrayShapeItemNode $item) use ($context): ArrayShapeItem {
                            return new ArrayShapeItem($item->keyName !== null ? (string) $item->keyName : null, $this->createType($item->valueType, $context), $item->optional);
                        }, $type->items));
                    case ArrayShapeNode::KIND_LIST:
                        return new ListShape(...array_map(function (ArrayShapeItemNode $item) use ($context): ListShapeItem {
                            return new ListShapeItem(null, $this->createType($item->valueType, $context), $item->optional);
                        }, $type->items));
                    default:
                        throw new RuntimeException('Unsupported array shape kind');
                }
            case ObjectShapeNode::class:
                return new ObjectShape(...array_map(function (ObjectShapeItemNode $item) use ($context): ObjectShapeItem {
                    return new ObjectShapeItem((string) $item->keyName, $this->createType($item->valueType, $context), $item->optional);
                }, $type->items));
            case CallableTypeNode::class:
                return $this->createFromCallable($type, $context);
            case ConstTypeNode::class:
                return $this->createFromConst($type, $context);
            case GenericTypeNode::class:
                return $this->createFromGeneric($type, $context);
            case IdentifierTypeNode::class:
                return $this->resolveSingleType($type->name, $context);
            case IntersectionTypeNode::class:
                return new Intersection(array_filter(array_map(function (TypeNode $nestedType) use ($context): Type {
                    $type = $this->createType($nestedType, $context);
                    if ($type instanceof AggregatedType) {
                        return new Expression($type);
                    }
                    return $type;
                }, $type->types)));
            case NullableTypeNode::class:
                $nestedType = $this->createType($type->type, $context);
                return new Nullable($nestedType);
            case UnionTypeNode::class:
                return new Compound(array_filter(array_map(function (TypeNode $nestedType) use ($context): Type {
                    $type = $this->createType($nestedType, $context);
                    if ($type instanceof AggregatedType) {
                        return new Expression($type);
                    }
                    return $type;
                }, $type->types)));
            case ThisTypeNode::class:
                return new This();
            case ConditionalTypeNode::class:
                return new Conditional($type->negated, $this->createType($type->subjectType, $context), $this->createType($type->targetType, $context), $this->createType($type->if, $context), $this->createType($type->else, $context));
            case ConditionalTypeForParameterNode::class:
                return new ConditionalForParameter($type->negated, substr($type->parameterName, 1), $this->createType($type->targetType, $context), $this->createType($type->if, $context), $this->createType($type->else, $context));
            case OffsetAccessTypeNode::class:
                return new OffsetAccess($this->createType($type->type, $context), $this->createType($type->offset, $context));
            default:
                return new Mixed_();
        }
    }
    private function createFromGeneric(GenericTypeNode $type, Context $context): Type
    {
        switch (strtolower($type->type->name)) {
            case 'array':
                return $this->createArray($type->genericTypes, $context);
            case 'class-string':
                $subType = $this->createType($type->genericTypes[0], $context);
                if (!$subType instanceof Object_ || $subType->getFqsen() === null) {
                    throw new RuntimeException($subType . ' is not a class string');
                }
                return new ClassString($subType->getFqsen());
            case 'interface-string':
                $subType = $this->createType($type->genericTypes[0], $context);
                if (!$subType instanceof Object_ || $subType->getFqsen() === null) {
                    throw new RuntimeException($subType . ' is not a class string');
                }
                return new InterfaceString($subType->getFqsen());
            case 'list':
                return new List_($this->createType($type->genericTypes[0], $context));
            case 'non-empty-list':
                return new NonEmptyList($this->createType($type->genericTypes[0], $context));
            case 'int':
                if (isset($type->genericTypes[1]) === \false) {
                    throw new RuntimeException('int<min,max> has not the correct format');
                }
                return new IntegerRange((string) $type->genericTypes[0], (string) $type->genericTypes[1]);
            case 'iterable':
                return new Iterable_(...array_reverse($this->createTypesByTypeNodes($type->genericTypes, $context)));
            case 'key-of':
                return new KeyOf($this->createType($type->genericTypes[0], $context));
            case 'value-of':
                return new ValueOf($this->createType($type->genericTypes[0], $context));
            case 'int-mask':
                return new IntMask(...$this->createTypesByTypeNodes($type->genericTypes, $context));
            case 'int-mask-of':
                return new IntMaskOf($this->createType($type->genericTypes[0], $context));
            case 'static':
                return new Static_(...$this->createTypesByTypeNodes($type->genericTypes, $context));
            case 'self':
                return new Self_(...$this->createTypesByTypeNodes($type->genericTypes, $context));
            default:
                $collectionType = $this->createType($type->type, $context);
                if ($collectionType instanceof Object_ === \false) {
                    throw new RuntimeException(sprintf('%s is not a collection', (string) $collectionType));
                }
                return new Collection($collectionType->getFqsen(), ...array_reverse($this->createTypesByTypeNodes($type->genericTypes, $context)));
        }
    }
    private function createFromCallable(CallableTypeNode $type, Context $context): Callable_
    {
        return new Callable_(array_map(function (CallableTypeParameterNode $param) use ($context): CallableParameter {
            return new CallableParameter($this->createType($param->type, $context), $param->parameterName !== '' ? trim($param->parameterName, '$') : null, $param->isReference, $param->isVariadic, $param->isOptional);
        }, $type->parameters), $this->createType($type->returnType, $context));
    }
    private function createFromConst(ConstTypeNode $type, Context $context): Type
    {
        switch (\true) {
            case $type->constExpr instanceof ConstExprIntegerNode:
                return new IntegerValue((int) $type->constExpr->value);
            case $type->constExpr instanceof ConstExprFloatNode:
                return new FloatValue((float) $type->constExpr->value);
            case $type->constExpr instanceof ConstExprStringNode:
                return new StringValue($type->constExpr->value);
            case $type->constExpr instanceof ConstFetchNode:
                return new ConstExpression($this->resolve($type->constExpr->className, $context), $type->constExpr->name);
            default:
                throw new RuntimeException(sprintf('Unsupported constant type %s', get_class($type)));
        }
    }
    /**
     * resolve the given type into a type object
     *
     * @param string $type the type string, representing a single type
     *
     * @return Type|Array_|Object_
     *
     * @psalm-mutation-free
     */
    private function resolveSingleType(string $type, Context $context): object
    {
        switch (\true) {
            case $this->isKeyword($type):
                return $this->resolveKeyword($type);
            case $this->isFqsen($type):
                return $this->resolveTypedObject($type);
            case $this->isPartialStructuralElementName($type):
                return $this->resolveTypedObject($type, $context);
            // @codeCoverageIgnoreStart
            default:
                // I haven't got the foggiest how the logic would come here but added this as a defense.
                throw new RuntimeException('Unable to resolve type "' . $type . '", there is no known method to resolve it');
        }
        // @codeCoverageIgnoreEnd
    }
    /**
     * Adds a keyword to the list of Keywords and associates it with a specific Value Object.
     *
     * @psalm-param class-string<Type> $typeClassName
     */
    public function addKeyword(string $keyword, string $typeClassName): void
    {
        if (!class_exists($typeClassName)) {
            throw new InvalidArgumentException('The Value Object that needs to be created with a keyword "' . $keyword . '" must be an existing class' . ' but we could not find the class ' . $typeClassName);
        }
        $interfaces = class_implements($typeClassName);
        if ($interfaces === \false) {
            throw new InvalidArgumentException('The Value Object that needs to be created with a keyword "' . $keyword . '" must be an existing class' . ' but we could not find the class ' . $typeClassName);
        }
        if (!in_array(Type::class, $interfaces, \true)) {
            throw new InvalidArgumentException('The class "' . $typeClassName . '" must implement the interface "phpDocumentor\Reflection\Type"');
        }
        $this->keywords[$keyword] = $typeClassName;
    }
    /**
     * Detects whether the given type represents a PHPDoc keyword.
     *
     * @param string $type A relative or absolute type as defined in the phpDocumentor documentation.
     *
     * @psalm-mutation-free
     */
    private function isKeyword(string $type): bool
    {
        return array_key_exists(strtolower($type), $this->keywords);
    }
    /**
     * Detects whether the given type represents a relative structural element name.
     *
     * @param string $type A relative or absolute type as defined in the phpDocumentor documentation.
     *
     * @psalm-mutation-free
     */
    private function isPartialStructuralElementName(string $type): bool
    {
        return isset($type[0]) && $type[0] !== self::OPERATOR_NAMESPACE && !$this->isKeyword($type);
    }
    /**
     * Tests whether the given type is a Fully Qualified Structural Element Name.
     *
     * @psalm-mutation-free
     */
    private function isFqsen(string $type): bool
    {
        return strpos($type, self::OPERATOR_NAMESPACE) === 0;
    }
    /**
     * Resolves the given keyword (such as `string`) into a Type object representing that keyword.
     *
     * @psalm-mutation-free
     */
    private function resolveKeyword(string $type): Type
    {
        $className = $this->keywords[strtolower($type)];
        return new $className();
    }
    /**
     * Resolves the given FQSEN string into an FQSEN object.
     *
     * @psalm-mutation-free
     */
    private function resolveTypedObject(string $type, ?Context $context = null): Object_
    {
        return new Object_($this->fqsenResolver->resolve($type, $context));
    }
    /** @param TypeNode[] $typeNodes */
    private function createArray(array $typeNodes, Context $context): Array_
    {
        $types = array_reverse($this->createTypesByTypeNodes($typeNodes, $context));
        if (isset($types[1]) === \false) {
            return new Array_(...$types);
        }
        if ($this->validArrayKeyType($types[1]) || $types[1] instanceof ArrayKey) {
            return new Array_(...$types);
        }
        if ($types[1] instanceof Compound && $types[1]->getIterator()->count() === 2) {
            if ($this->validArrayKeyType($types[1]->get(0)) && $this->validArrayKeyType($types[1]->get(1))) {
                return new Array_(...$types);
            }
        }
        throw new RuntimeException('An array can have only integers or strings as keys');
    }
    private function validArrayKeyType(?Type $type): bool
    {
        return $type instanceof String_ || $type instanceof Integer;
    }
    private function parse(TokenIterator $tokenIterator): TypeNode
    {
        try {
            $ast = $this->typeParser->parse($tokenIterator);
        } catch (ParserException $e) {
            throw new RuntimeException($e->getMessage(), 0, $e);
        }
        return $ast;
    }
    /**
     * Will try to parse unsupported type notations by phpstan
     *
     * The phpstan parser doesn't support the illegal nullable combinations like this library does.
     * This method will warn the user about those notations but for bc purposes we will still have it here.
     */
    private function tryParseRemainingCompoundTypes(TokenIterator $tokenIterator, Context $context, Type $type): Type
    {
        if ($tokenIterator->isCurrentTokenType(Lexer::TOKEN_UNION) || $tokenIterator->isCurrentTokenType(Lexer::TOKEN_INTERSECTION)) {
            Deprecation::trigger('phpdocumentor/type-resolver', 'https://github.com/phpDocumentor/TypeResolver/issues/184', 'Legacy nullable type detected, please update your code as
                you are using nullable types in a docblock. support will be removed in v2.0.0');
        }
        $continue = \true;
        while ($continue) {
            $continue = \false;
            while ($tokenIterator->tryConsumeTokenType(Lexer::TOKEN_UNION)) {
                $ast = $this->parse($tokenIterator);
                $type2 = $this->createType($ast, $context);
                $type = new Compound([$type, $type2]);
                $continue = \true;
            }
            while ($tokenIterator->tryConsumeTokenType(Lexer::TOKEN_INTERSECTION)) {
                $ast = $this->typeParser->parse($tokenIterator);
                $type2 = $this->createType($ast, $context);
                $type = new Intersection([$type, $type2]);
                $continue = \true;
            }
        }
        return $type;
    }
    /**
     * @param TypeNode[] $nodes
     *
     * @return Type[]
     */
    private function createTypesByTypeNodes(array $nodes, Context $context): array
    {
        return array_map(function (TypeNode $node) use ($context): Type {
            return $this->createType($node, $context);
        }, $nodes);
    }
}
<?php

declare (strict_types=1);
/**
 * This file is part of phpDocumentor.
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @link      http://phpdoc.org
 */
namespace _ContaoManager\phpDocumentor\Reflection\Types;

use _ContaoManager\phpDocumentor\Reflection\Type;
/**
 * Represents an expression type as described in the PSR-5, the PHPDoc Standard.
 *
 * @psalm-immutable
 */
final class Expression implements Type
{
    /** @var Type */
    protected $valueType;
    /**
     * Initializes this representation of an array with the given Type.
     */
    public function __construct(Type $valueType)
    {
        $this->valueType = $valueType;
    }
    /**
     * Returns the value for the keys of this array.
     */
    public function getValueType(): Type
    {
        return $this->valueType;
    }
    /**
     * Returns a rendered output of the Type as it would be used in a DocBlock.
     */
    public function __toString(): string
    {
        return '(' . $this->valueType . ')';
    }
}
<?php

declare (strict_types=1);
/**
 * This file is part of phpDocumentor.
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @link      http://phpdoc.org
 */
namespace _ContaoManager\phpDocumentor\Reflection\Types;

use _ContaoManager\phpDocumentor\Reflection\Type;
/**
 * Value Object representing a Boolean type.
 *
 * @psalm-immutable
 */
class Boolean implements Type
{
    /**
     * Returns a rendered output of the Type as it would be used in a DocBlock.
     */
    public function __toString(): string
    {
        return 'bool';
    }
}
<?php

declare (strict_types=1);
/**
 * This file is part of phpDocumentor.
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @link      http://phpdoc.org
 */
namespace _ContaoManager\phpDocumentor\Reflection\Types;

use _ContaoManager\phpDocumentor\Reflection\Type;
/**
 * Value object representing Integer type
 *
 * @psalm-immutable
 */
class Integer implements Type
{
    /**
     * Returns a rendered output of the Type as it would be used in a DocBlock.
     */
    public function __toString(): string
    {
        return 'int';
    }
}
<?php

declare (strict_types=1);
/**
 * This file is part of phpDocumentor.
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @link      http://phpdoc.org
 */
namespace _ContaoManager\phpDocumentor\Reflection\Types;

use _ContaoManager\phpDocumentor\Reflection\Type;
use function implode;
/**
 * Value Object representing the 'self' type.
 *
 * Self, as a Type, represents the class in which the associated element was defined.
 *
 * @psalm-immutable
 */
final class Self_ implements Type
{
    /** @var Type[] */
    private $genericTypes;
    public function __construct(Type ...$genericTypes)
    {
        $this->genericTypes = $genericTypes;
    }
    /**
     * @return Type[]
     */
    public function getGenericTypes(): array
    {
        return $this->genericTypes;
    }
    /**
     * Returns a rendered output of the Type as it would be used in a DocBlock.
     */
    public function __toString(): string
    {
        if ($this->genericTypes) {
            return 'self<' . implode(', ', $this->genericTypes) . '>';
        }
        return 'self';
    }
}
<?php

declare (strict_types=1);
/**
 * This file is part of phpDocumentor.
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @link      http://phpdoc.org
 */
namespace _ContaoManager\phpDocumentor\Reflection\Types;

use _ContaoManager\phpDocumentor\Reflection\Type;
/**
 * Value Object representing the return-type 'void'.
 *
 * Void is generally only used when working with return types as it signifies that the method intentionally does not
 * return any value.
 *
 * @psalm-immutable
 */
final class Void_ implements Type
{
    /**
     * Returns a rendered output of the Type as it would be used in a DocBlock.
     */
    public function __toString(): string
    {
        return 'void';
    }
}
<?php

declare (strict_types=1);
/**
 * This file is part of phpDocumentor.
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @link      http://phpdoc.org
 */
namespace _ContaoManager\phpDocumentor\Reflection\Types;

use _ContaoManager\phpDocumentor\Reflection\Type;
/**
 * Value Object representing a null value or type.
 *
 * @psalm-immutable
 */
final class Null_ implements Type
{
    /**
     * Returns a rendered output of the Type as it would be used in a DocBlock.
     */
    public function __toString(): string
    {
        return 'null';
    }
}
<?php

declare (strict_types=1);
/**
 * This file is part of phpDocumentor.
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @link      http://phpdoc.org
 */
namespace _ContaoManager\phpDocumentor\Reflection\Types;

use _ContaoManager\phpDocumentor\Reflection\Type;
/**
 * Value Object representing the 'resource' Type.
 *
 * @psalm-immutable
 */
final class Resource_ implements Type
{
    /**
     * Returns a rendered output of the Type as it would be used in a DocBlock.
     */
    public function __toString(): string
    {
        return 'resource';
    }
}
<?php

declare (strict_types=1);
/**
 * This file is part of phpDocumentor.
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @link      http://phpdoc.org
 */
namespace _ContaoManager\phpDocumentor\Reflection\Types;

use _ContaoManager\phpDocumentor\Reflection\Type;
/**
 * Value Object representing a Float.
 *
 * @psalm-immutable
 */
class Float_ implements Type
{
    /**
     * Returns a rendered output of the Type as it would be used in a DocBlock.
     */
    public function __toString(): string
    {
        return 'float';
    }
}
<?php

declare (strict_types=1);
/**
 * This file is part of phpDocumentor.
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @link      http://phpdoc.org
 */
namespace _ContaoManager\phpDocumentor\Reflection\Types;

use InvalidArgumentException;
use _ContaoManager\phpDocumentor\Reflection\Fqsen;
use _ContaoManager\phpDocumentor\Reflection\Type;
use function strpos;
/**
 * Value Object representing an object.
 *
 * An object can be either typed or untyped. When an object is typed it means that it has an identifier, the FQSEN,
 * pointing to an element in PHP. Object types that are untyped do not refer to a specific class but represent objects
 * in general.
 *
 * @psalm-immutable
 */
final class Object_ implements Type
{
    /** @var Fqsen|null */
    private $fqsen;
    /**
     * Initializes this object with an optional FQSEN, if not provided this object is considered 'untyped'.
     *
     * @throws InvalidArgumentException When provided $fqsen is not a valid type.
     */
    public function __construct(?Fqsen $fqsen = null)
    {
        if (strpos((string) $fqsen, '::') !== \false || strpos((string) $fqsen, '()') !== \false) {
            throw new InvalidArgumentException('Object types can only refer to a class, interface or trait but a method, function, constant or ' . 'property was received: ' . (string) $fqsen);
        }
        $this->fqsen = $fqsen;
    }
    /**
     * Returns the FQSEN associated with this object.
     */
    public function getFqsen(): ?Fqsen
    {
        return $this->fqsen;
    }
    public function __toString(): string
    {
        if ($this->fqsen) {
            return (string) $this->fqsen;
        }
        return 'object';
    }
}
<?php

declare (strict_types=1);
/**
 * This file is part of phpDocumentor.
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @link      http://phpdoc.org
 */
namespace _ContaoManager\phpDocumentor\Reflection\Types;

use _ContaoManager\phpDocumentor\Reflection\Type;
/**
 * Value Object representing the type 'string'.
 *
 * @psalm-immutable
 */
class String_ implements Type
{
    /**
     * Returns a rendered output of the Type as it would be used in a DocBlock.
     */
    public function __toString(): string
    {
        return 'string';
    }
}
<?php

declare (strict_types=1);
/**
 * This file is part of phpDocumentor.
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @link      http://phpdoc.org
 */
namespace _ContaoManager\phpDocumentor\Reflection\Types;

use _ContaoManager\phpDocumentor\Reflection\Type;
/**
 * Value Object representing a nullable type. The real type is wrapped.
 *
 * @psalm-immutable
 */
final class Nullable implements Type
{
    /** @var Type The actual type that is wrapped */
    private $realType;
    /**
     * Initialises this nullable type using the real type embedded
     */
    public function __construct(Type $realType)
    {
        $this->realType = $realType;
    }
    /**
     * Provide access to the actual type directly, if needed.
     */
    public function getActualType(): Type
    {
        return $this->realType;
    }
    /**
     * Returns a rendered output of the Type as it would be used in a DocBlock.
     */
    public function __toString(): string
    {
        return '?' . $this->realType->__toString();
    }
}
<?php

declare (strict_types=1);
/**
 * This file is part of phpDocumentor.
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @link      http://phpdoc.org
 */
namespace _ContaoManager\phpDocumentor\Reflection\Types;

use _ContaoManager\phpDocumentor\Reflection\Type;
/**
 * Value Object representing a Callable type.
 *
 * @psalm-immutable
 */
final class Callable_ implements Type
{
    /** @var Type|null */
    private $returnType;
    /** @var CallableParameter[] */
    private $parameters;
    /**
     * @param CallableParameter[] $parameters
     */
    public function __construct(array $parameters = [], ?Type $returnType = null)
    {
        $this->parameters = $parameters;
        $this->returnType = $returnType;
    }
    /** @return CallableParameter[] */
    public function getParameters(): array
    {
        return $this->parameters;
    }
    public function getReturnType(): ?Type
    {
        return $this->returnType;
    }
    /**
     * Returns a rendered output of the Type as it would be used in a DocBlock.
     */
    public function __toString(): string
    {
        return 'callable';
    }
}
<?php

declare (strict_types=1);
/**
 * This file is part of phpDocumentor.
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @link      http://phpdoc.org
 */
namespace _ContaoManager\phpDocumentor\Reflection\Types;

use _ContaoManager\phpDocumentor\Reflection\Fqsen;
use _ContaoManager\phpDocumentor\Reflection\Type;
/**
 * Value Object representing the type 'string'.
 *
 * @psalm-immutable
 */
final class InterfaceString implements Type
{
    /** @var Fqsen|null */
    private $fqsen;
    /**
     * Initializes this representation of a class string with the given Fqsen.
     */
    public function __construct(?Fqsen $fqsen = null)
    {
        $this->fqsen = $fqsen;
    }
    /**
     * Returns the FQSEN associated with this object.
     */
    public function getFqsen(): ?Fqsen
    {
        return $this->fqsen;
    }
    /**
     * Returns a rendered output of the Type as it would be used in a DocBlock.
     */
    public function __toString(): string
    {
        if ($this->fqsen === null) {
            return 'interface-string';
        }
        return 'interface-string<' . (string) $this->fqsen . '>';
    }
}
<?php

declare (strict_types=1);
/**
 * This file is part of phpDocumentor.
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @link      http://phpdoc.org
 */
namespace _ContaoManager\phpDocumentor\Reflection\Types;

/**
 * Value Object representing iterable type
 *
 * @psalm-immutable
 */
final class Iterable_ extends AbstractList
{
    /**
     * Returns a rendered output of the Type as it would be used in a DocBlock.
     */
    public function __toString(): string
    {
        if ($this->keyType) {
            return 'iterable<' . $this->keyType . ',' . $this->valueType . '>';
        }
        if ($this->valueType instanceof Mixed_) {
            return 'iterable';
        }
        return 'iterable<' . $this->valueType . '>';
    }
}
<?php

/**
 * This file is part of phpDocumentor.
 *
 *  For the full copyright and license information, please view the LICENSE
 *  file that was distributed with this source code.
 *
 *  @link      http://phpdoc.org
 */
declare (strict_types=1);
namespace _ContaoManager\phpDocumentor\Reflection\Types;

use _ContaoManager\phpDocumentor\Reflection\Type;
/**
 * Value Object representing a Callable parameters.
 *
 * @psalm-immutable
 */
final class CallableParameter
{
    /** @var Type */
    private $type;
    /** @var bool */
    private $isReference;
    /** @var bool */
    private $isVariadic;
    /** @var bool */
    private $isOptional;
    /** @var string|null */
    private $name;
    public function __construct(Type $type, ?string $name = null, bool $isReference = \false, bool $isVariadic = \false, bool $isOptional = \false)
    {
        $this->type = $type;
        $this->isReference = $isReference;
        $this->isVariadic = $isVariadic;
        $this->isOptional = $isOptional;
        $this->name = $name;
    }
    public function getName(): ?string
    {
        return $this->name;
    }
    public function getType(): Type
    {
        return $this->type;
    }
    public function isReference(): bool
    {
        return $this->isReference;
    }
    public function isVariadic(): bool
    {
        return $this->isVariadic;
    }
    public function isOptional(): bool
    {
        return $this->isOptional;
    }
}
<?php

declare (strict_types=1);
/**
 * This file is part of phpDocumentor.
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @link      http://phpdoc.org
 */
namespace _ContaoManager\phpDocumentor\Reflection\Types;

use _ContaoManager\phpDocumentor\Reflection\PseudoType;
use _ContaoManager\phpDocumentor\Reflection\Type;
/**
 * Value Object representing a array-key Type.
 *
 * A array-key Type is the supertype (but not a union) of int and string.
 *
 * @psalm-immutable
 */
class ArrayKey extends AggregatedType implements PseudoType
{
    public function __construct()
    {
        parent::__construct([new String_(), new Integer()], '|');
    }
    public function underlyingType(): Type
    {
        return new Compound([new String_(), new Integer()]);
    }
    public function __toString(): string
    {
        return 'array-key';
    }
}
<?php

declare (strict_types=1);
/**
 * This file is part of phpDocumentor.
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @link      http://phpdoc.org
 */
namespace _ContaoManager\phpDocumentor\Reflection\Types;

use _ContaoManager\phpDocumentor\Reflection\Type;
/**
 * Value Object representing the return-type 'never'.
 *
 * Never is generally only used when working with return types as it signifies that the method that only
 * ever throw or exit.
 *
 * @psalm-immutable
 */
final class Never_ implements Type
{
    /**
     * Returns a rendered output of the Type as it would be used in a DocBlock.
     */
    public function __toString(): string
    {
        return 'never';
    }
}
<?php

declare (strict_types=1);
/**
 * This file is part of phpDocumentor.
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @link      http://phpdoc.org
 */
namespace _ContaoManager\phpDocumentor\Reflection\Types;

use _ContaoManager\phpDocumentor\Reflection\Type;
use function implode;
/**
 * Value Object representing the 'static' type.
 *
 * Self, as a Type, represents the class in which the associated element was called. This differs from self as self does
 * not take inheritance into account but static means that the return type is always that of the class of the called
 * element.
 *
 * See the documentation on late static binding in the PHP Documentation for more information on the difference between
 * static and self.
 *
 * @psalm-immutable
 */
final class Static_ implements Type
{
    /** @var Type[] */
    private $genericTypes;
    public function __construct(Type ...$genericTypes)
    {
        $this->genericTypes = $genericTypes;
    }
    /**
     * @return Type[]
     */
    public function getGenericTypes(): array
    {
        return $this->genericTypes;
    }
    /**
     * Returns a rendered output of the Type as it would be used in a DocBlock.
     */
    public function __toString(): string
    {
        if ($this->genericTypes) {
            return 'static<' . implode(', ', $this->genericTypes) . '>';
        }
        return 'static';
    }
}
<?php

declare (strict_types=1);
/**
 * This file is part of phpDocumentor.
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @link      http://phpdoc.org
 */
namespace _ContaoManager\phpDocumentor\Reflection\Types;

use _ContaoManager\phpDocumentor\Reflection\Fqsen;
use _ContaoManager\phpDocumentor\Reflection\PseudoType;
use _ContaoManager\phpDocumentor\Reflection\Type;
/**
 * Value Object representing the type 'string'.
 *
 * @psalm-immutable
 */
final class ClassString extends String_ implements PseudoType
{
    /** @var Fqsen|null */
    private $fqsen;
    /**
     * Initializes this representation of a class string with the given Fqsen.
     */
    public function __construct(?Fqsen $fqsen = null)
    {
        $this->fqsen = $fqsen;
    }
    public function underlyingType(): Type
    {
        return new String_();
    }
    /**
     * Returns the FQSEN associated with this object.
     */
    public function getFqsen(): ?Fqsen
    {
        return $this->fqsen;
    }
    /**
     * Returns a rendered output of the Type as it would be used in a DocBlock.
     */
    public function __toString(): string
    {
        if ($this->fqsen === null) {
            return 'class-string';
        }
        return 'class-string<' . (string) $this->fqsen . '>';
    }
}
<?php

declare (strict_types=1);
/**
 * This file is part of phpDocumentor.
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @link      http://phpdoc.org
 */
namespace _ContaoManager\phpDocumentor\Reflection\Types;

use _ContaoManager\phpDocumentor\Reflection\Type;
/**
 * Value Object representing the 'parent' type.
 *
 * Parent, as a Type, represents the parent class of class in which the associated element was defined.
 *
 * @psalm-immutable
 */
final class Parent_ implements Type
{
    /**
     * Returns a rendered output of the Type as it would be used in a DocBlock.
     */
    public function __toString(): string
    {
        return 'parent';
    }
}
<?php

declare (strict_types=1);
/**
 * This file is part of phpDocumentor.
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @link      http://phpdoc.org
 */
namespace _ContaoManager\phpDocumentor\Reflection\Types;

use _ContaoManager\phpDocumentor\Reflection\Type;
/**
 * Value Object representing the 'scalar' pseudo-type, which is either a string, integer, float or boolean.
 *
 * @psalm-immutable
 */
final class Scalar implements Type
{
    /**
     * Returns a rendered output of the Type as it would be used in a DocBlock.
     */
    public function __toString(): string
    {
        return 'scalar';
    }
}
<?php

declare (strict_types=1);
/**
 * This file is part of phpDocumentor.
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @link      http://phpdoc.org
 */
namespace _ContaoManager\phpDocumentor\Reflection\Types;

use function strlen;
use function substr;
use function trim;
/**
 * Provides information about the Context in which the DocBlock occurs that receives this context.
 *
 * A DocBlock does not know of its own accord in which namespace it occurs and which namespace aliases are applicable
 * for the block of code in which it is in. This information is however necessary to resolve Class names in tags since
 * you can provide a short form or make use of namespace aliases.
 *
 * The phpDocumentor Reflection component knows how to create this class but if you use the DocBlock parser from your
 * own application it is possible to generate a Context class using the ContextFactory; this will analyze the file in
 * which an associated class resides for its namespace and imports.
 *
 * @see ContextFactory::createFromReflector()
 * @see ContextFactory::createForNamespace()
 *
 * @psalm-immutable
 */
final class Context
{
    /** @var string The current namespace. */
    private $namespace;
    /**
     * @var string[] List of namespace aliases => Fully Qualified Namespace.
     * @psalm-var array<string, string>
     */
    private $namespaceAliases;
    /**
     * Initializes the new context and normalizes all passed namespaces to be in Qualified Namespace Name (QNN)
     * format (without a preceding `\`).
     *
     * @param string   $namespace        The namespace where this DocBlock resides in.
     * @param string[] $namespaceAliases List of namespace aliases => Fully Qualified Namespace.
     * @psalm-param array<string, string> $namespaceAliases
     */
    public function __construct(string $namespace, array $namespaceAliases = [])
    {
        $this->namespace = $namespace !== 'global' && $namespace !== 'default' ? trim($namespace, '\\') : '';
        foreach ($namespaceAliases as $alias => $fqnn) {
            if ($fqnn[0] === '\\') {
                $fqnn = substr($fqnn, 1);
            }
            if ($fqnn[strlen($fqnn) - 1] === '\\') {
                $fqnn = substr($fqnn, 0, -1);
            }
            $namespaceAliases[$alias] = $fqnn;
        }
        $this->namespaceAliases = $namespaceAliases;
    }
    /**
     * Returns the Qualified Namespace Name (thus without `\` in front) where the associated element is in.
     */
    public function getNamespace(): string
    {
        return $this->namespace;
    }
    /**
     * Returns a list of Qualified Namespace Names (thus without `\` in front) that are imported, the keys represent
     * the alias for the imported Namespace.
     *
     * @return string[]
     * @psalm-return array<string, string>
     */
    public function getNamespaceAliases(): array
    {
        return $this->namespaceAliases;
    }
}
<?php

declare (strict_types=1);
/**
 * This file is part of phpDocumentor.
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @link      http://phpdoc.org
 */
namespace _ContaoManager\phpDocumentor\Reflection\Types;

use _ContaoManager\phpDocumentor\Reflection\Type;
/**
 * Represents a list of values. This is an abstract class for Array_ and Collection.
 *
 * @psalm-immutable
 */
abstract class AbstractList implements Type
{
    /** @var Type */
    protected $valueType;
    /** @var Type|null */
    protected $keyType;
    /** @var Type */
    protected $defaultKeyType;
    /**
     * Initializes this representation of an array with the given Type.
     */
    public function __construct(?Type $valueType = null, ?Type $keyType = null)
    {
        if ($valueType === null) {
            $valueType = new Mixed_();
        }
        $this->valueType = $valueType;
        $this->defaultKeyType = new Compound([new String_(), new Integer()]);
        $this->keyType = $keyType;
    }
    public function getOriginalKeyType(): ?Type
    {
        return $this->keyType;
    }
    /**
     * Returns the type for the keys of this array.
     */
    public function getKeyType(): Type
    {
        return $this->keyType ?? $this->defaultKeyType;
    }
    /**
     * Returns the type for the values of this array.
     */
    public function getValueType(): Type
    {
        return $this->valueType;
    }
    /**
     * Returns a rendered output of the Type as it would be used in a DocBlock.
     */
    public function __toString(): string
    {
        if ($this->keyType) {
            return 'array<' . $this->keyType . ',' . $this->valueType . '>';
        }
        if ($this->valueType instanceof Mixed_) {
            return 'array';
        }
        if ($this->valueType instanceof Compound) {
            return '(' . $this->valueType . ')[]';
        }
        return $this->valueType . '[]';
    }
}
<?php

declare (strict_types=1);
/**
 * This file is part of phpDocumentor.
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @link      http://phpdoc.org
 */
namespace _ContaoManager\phpDocumentor\Reflection\Types;

use _ContaoManager\phpDocumentor\Reflection\Fqsen;
use _ContaoManager\phpDocumentor\Reflection\Type;
/**
 * Represents a collection type as described in the PSR-5, the PHPDoc Standard.
 *
 * A collection can be represented in two forms:
 *
 * 1. `ACollectionObject<aValueType>`
 * 2. `ACollectionObject<aValueType,aKeyType>`
 *
 * - ACollectionObject can be 'array' or an object that can act as an array
 * - aValueType and aKeyType can be any type expression
 *
 * @psalm-immutable
 */
final class Collection extends AbstractList
{
    /** @var Fqsen|null */
    private $fqsen;
    /**
     * Initializes this representation of an array with the given Type or Fqsen.
     */
    public function __construct(?Fqsen $fqsen, Type $valueType, ?Type $keyType = null)
    {
        parent::__construct($valueType, $keyType);
        $this->fqsen = $fqsen;
    }
    /**
     * Returns the FQSEN associated with this object.
     */
    public function getFqsen(): ?Fqsen
    {
        return $this->fqsen;
    }
    /**
     * Returns a rendered output of the Type as it would be used in a DocBlock.
     */
    public function __toString(): string
    {
        $objectType = (string) ($this->fqsen ?? 'object');
        if ($this->keyType === null) {
            return $objectType . '<' . $this->valueType . '>';
        }
        return $objectType . '<' . $this->keyType . ',' . $this->valueType . '>';
    }
}
<?php

/**
 * This file is part of phpDocumentor.
 *
 *  For the full copyright and license information, please view the LICENSE
 *  file that was distributed with this source code.
 *
 *  @link      http://phpdoc.org
 */
declare (strict_types=1);
namespace _ContaoManager\phpDocumentor\Reflection\Types;

use _ContaoManager\phpDocumentor\Reflection\Type;
/**
 * Value Object representing a Compound Type.
 *
 * A Intersection Type is not so much a special keyword or object reference but is a series of Types that are separated
 * using an AND operator (`&`). This combination of types signifies that whatever is associated with this Intersection
 * type may contain a value with any of the given types.
 *
 * @psalm-immutable
 */
final class Intersection extends AggregatedType
{
    /**
     * Initializes a intersection type (i.e. `\A&\B`) and tests if the provided types all implement the Type interface.
     *
     * @param array<Type> $types
     */
    public function __construct(array $types)
    {
        parent::__construct($types, '&');
    }
}
<?php

declare (strict_types=1);
/**
 * This file is part of phpDocumentor.
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @link      http://phpdoc.org
 */
namespace _ContaoManager\phpDocumentor\Reflection\Types;

use ArrayIterator;
use InvalidArgumentException;
use ReflectionClass;
use ReflectionClassConstant;
use ReflectionMethod;
use ReflectionParameter;
use ReflectionProperty;
use Reflector;
use RuntimeException;
use UnexpectedValueException;
use function define;
use function defined;
use function file_exists;
use function file_get_contents;
use function get_class;
use function in_array;
use function is_string;
use function strrpos;
use function substr;
use function token_get_all;
use function trim;
use const T_AS;
use const T_CLASS;
use const T_CURLY_OPEN;
use const T_DOLLAR_OPEN_CURLY_BRACES;
use const T_NAME_FULLY_QUALIFIED;
use const T_NAME_QUALIFIED;
use const T_NAMESPACE;
use const T_NS_SEPARATOR;
use const T_STRING;
use const T_TRAIT;
use const T_USE;
if (!defined('T_NAME_QUALIFIED')) {
    define('T_NAME_QUALIFIED', 10001);
}
if (!defined('T_NAME_FULLY_QUALIFIED')) {
    define('T_NAME_FULLY_QUALIFIED', 10002);
}
/**
 * Convenience class to create a Context for DocBlocks when not using the Reflection Component of phpDocumentor.
 *
 * For a DocBlock to be able to resolve types that use partial namespace names or rely on namespace imports we need to
 * provide a bit of context so that the DocBlock can read that and based on it decide how to resolve the types to
 * Fully Qualified names.
 *
 * @see Context for more information.
 */
final class ContextFactory
{
    /** The literal used at the end of a use statement. */
    private const T_LITERAL_END_OF_USE = ';';
    /** The literal used between sets of use statements */
    private const T_LITERAL_USE_SEPARATOR = ',';
    /**
     * Build a Context given a Class Reflection.
     *
     * @see Context for more information on Contexts.
     */
    public function createFromReflector(Reflector $reflector): Context
    {
        if ($reflector instanceof ReflectionClass) {
            //phpcs:ignore SlevomatCodingStandard.Commenting.InlineDocCommentDeclaration.MissingVariable
            /** @var ReflectionClass<object> $reflector */
            return $this->createFromReflectionClass($reflector);
        }
        if ($reflector instanceof ReflectionParameter) {
            return $this->createFromReflectionParameter($reflector);
        }
        if ($reflector instanceof ReflectionMethod) {
            return $this->createFromReflectionMethod($reflector);
        }
        if ($reflector instanceof ReflectionProperty) {
            return $this->createFromReflectionProperty($reflector);
        }
        if ($reflector instanceof ReflectionClassConstant) {
            return $this->createFromReflectionClassConstant($reflector);
        }
        throw new UnexpectedValueException('Unhandled \Reflector instance given:  ' . get_class($reflector));
    }
    private function createFromReflectionParameter(ReflectionParameter $parameter): Context
    {
        $class = $parameter->getDeclaringClass();
        if (!$class) {
            throw new InvalidArgumentException('Unable to get class of ' . $parameter->getName());
        }
        return $this->createFromReflectionClass($class);
    }
    private function createFromReflectionMethod(ReflectionMethod $method): Context
    {
        $class = $method->getDeclaringClass();
        return $this->createFromReflectionClass($class);
    }
    private function createFromReflectionProperty(ReflectionProperty $property): Context
    {
        $class = $property->getDeclaringClass();
        return $this->createFromReflectionClass($class);
    }
    private function createFromReflectionClassConstant(ReflectionClassConstant $constant): Context
    {
        //phpcs:ignore SlevomatCodingStandard.Commenting.InlineDocCommentDeclaration.MissingVariable
        /** @phpstan-var ReflectionClass<object> $class */
        $class = $constant->getDeclaringClass();
        return $this->createFromReflectionClass($class);
    }
    /**
     * @phpstan-param ReflectionClass<object> $class
     */
    private function createFromReflectionClass(ReflectionClass $class): Context
    {
        $fileName = $class->getFileName();
        $namespace = $class->getNamespaceName();
        if (is_string($fileName) && file_exists($fileName)) {
            $contents = file_get_contents($fileName);
            if ($contents === \false) {
                throw new RuntimeException('Unable to read file "' . $fileName . '"');
            }
            return $this->createForNamespace($namespace, $contents);
        }
        return new Context($namespace, []);
    }
    /**
     * Build a Context for a namespace in the provided file contents.
     *
     * @see Context for more information on Contexts.
     *
     * @param string $namespace    It does not matter if a `\` precedes the namespace name,
     * this method first normalizes.
     * @param string $fileContents The file's contents to retrieve the aliases from with the given namespace.
     */
    public function createForNamespace(string $namespace, string $fileContents): Context
    {
        $namespace = trim($namespace, '\\');
        $useStatements = [];
        $currentNamespace = '';
        $tokens = new ArrayIterator(token_get_all($fileContents));
        while ($tokens->valid()) {
            $currentToken = $tokens->current();
            switch ($currentToken[0]) {
                case T_NAMESPACE:
                    $currentNamespace = $this->parseNamespace($tokens);
                    break;
                case T_CLASS:
                case T_TRAIT:
                    // Fast-forward the iterator through the class so that any
                    // T_USE tokens found within are skipped - these are not
                    // valid namespace use statements so should be ignored.
                    $braceLevel = 0;
                    $firstBraceFound = \false;
                    while ($tokens->valid() && ($braceLevel > 0 || !$firstBraceFound)) {
                        $currentToken = $tokens->current();
                        if ($currentToken === '{' || in_array($currentToken[0], [T_CURLY_OPEN, T_DOLLAR_OPEN_CURLY_BRACES], \true)) {
                            if (!$firstBraceFound) {
                                $firstBraceFound = \true;
                            }
                            ++$braceLevel;
                        }
                        if ($currentToken === '}') {
                            --$braceLevel;
                        }
                        $tokens->next();
                    }
                    break;
                case T_USE:
                    if ($currentNamespace === $namespace) {
                        $useStatements += $this->parseUseStatement($tokens);
                    }
                    break;
            }
            $tokens->next();
        }
        return new Context($namespace, $useStatements);
    }
    /**
     * Deduce the name from tokens when we are at the T_NAMESPACE token.
     *
     * @param ArrayIterator<int, string|array{0:int,1:string,2:int}> $tokens
     */
    private function parseNamespace(ArrayIterator $tokens): string
    {
        // skip to the first string or namespace separator
        $this->skipToNextStringOrNamespaceSeparator($tokens);
        $name = '';
        $acceptedTokens = [T_STRING, T_NS_SEPARATOR, T_NAME_QUALIFIED];
        while ($tokens->valid() && in_array($tokens->current()[0], $acceptedTokens, \true)) {
            $name .= $tokens->current()[1];
            $tokens->next();
        }
        return $name;
    }
    /**
     * Deduce the names of all imports when we are at the T_USE token.
     *
     * @param ArrayIterator<int, string|array{0:int,1:string,2:int}> $tokens
     *
     * @return string[]
     * @psalm-return array<string, string>
     */
    private function parseUseStatement(ArrayIterator $tokens): array
    {
        $uses = [];
        while ($tokens->valid()) {
            $this->skipToNextStringOrNamespaceSeparator($tokens);
            $uses += $this->extractUseStatements($tokens);
            $currentToken = $tokens->current();
            if ($currentToken[0] === self::T_LITERAL_END_OF_USE) {
                return $uses;
            }
        }
        return $uses;
    }
    /**
     * Fast-forwards the iterator as longs as we don't encounter a T_STRING or T_NS_SEPARATOR token.
     *
     * @param ArrayIterator<int, string|array{0:int,1:string,2:int}> $tokens
     */
    private function skipToNextStringOrNamespaceSeparator(ArrayIterator $tokens): void
    {
        while ($tokens->valid()) {
            $currentToken = $tokens->current();
            if (in_array($currentToken[0], [T_STRING, T_NS_SEPARATOR], \true)) {
                break;
            }
            if ($currentToken[0] === T_NAME_QUALIFIED) {
                break;
            }
            if (defined('T_NAME_FULLY_QUALIFIED') && $currentToken[0] === T_NAME_FULLY_QUALIFIED) {
                break;
            }
            $tokens->next();
        }
    }
    /**
     * Deduce the namespace name and alias of an import when we are at the T_USE token or have not reached the end of
     * a USE statement yet. This will return a key/value array of the alias => namespace.
     *
     * @param ArrayIterator<int, string|array{0:int,1:string,2:int}> $tokens
     *
     * @return string[]
     * @psalm-return array<string, string>
     *
     * @psalm-suppress TypeDoesNotContainType
     */
    private function extractUseStatements(ArrayIterator $tokens): array
    {
        $extractedUseStatements = [];
        $groupedNs = '';
        $currentNs = '';
        $currentAlias = '';
        $state = 'start';
        while ($tokens->valid()) {
            $currentToken = $tokens->current();
            $tokenId = is_string($currentToken) ? $currentToken : $currentToken[0];
            $tokenValue = is_string($currentToken) ? null : $currentToken[1];
            switch ($state) {
                case 'start':
                    switch ($tokenId) {
                        case T_STRING:
                        case T_NS_SEPARATOR:
                            $currentNs .= (string) $tokenValue;
                            $currentAlias = $tokenValue;
                            break;
                        case T_NAME_QUALIFIED:
                        case T_NAME_FULLY_QUALIFIED:
                            $currentNs .= (string) $tokenValue;
                            $currentAlias = substr((string) $tokenValue, (int) strrpos((string) $tokenValue, '\\') + 1);
                            break;
                        case T_CURLY_OPEN:
                        case '{':
                            $state = 'grouped';
                            $groupedNs = $currentNs;
                            break;
                        case T_AS:
                            $state = 'start-alias';
                            break;
                        case self::T_LITERAL_USE_SEPARATOR:
                        case self::T_LITERAL_END_OF_USE:
                            $state = 'end';
                            break;
                        default:
                            break;
                    }
                    break;
                case 'start-alias':
                    switch ($tokenId) {
                        case T_STRING:
                            $currentAlias = $tokenValue;
                            break;
                        case self::T_LITERAL_USE_SEPARATOR:
                        case self::T_LITERAL_END_OF_USE:
                            $state = 'end';
                            break;
                        default:
                            break;
                    }
                    break;
                case 'grouped':
                    switch ($tokenId) {
                        case T_STRING:
                        case T_NS_SEPARATOR:
                            $currentNs .= (string) $tokenValue;
                            $currentAlias = $tokenValue;
                            break;
                        case T_AS:
                            $state = 'grouped-alias';
                            break;
                        case self::T_LITERAL_USE_SEPARATOR:
                            $state = 'grouped';
                            $extractedUseStatements[(string) $currentAlias] = $currentNs;
                            $currentNs = $groupedNs;
                            $currentAlias = '';
                            break;
                        case self::T_LITERAL_END_OF_USE:
                            $state = 'end';
                            break;
                        default:
                            break;
                    }
                    break;
                case 'grouped-alias':
                    switch ($tokenId) {
                        case T_STRING:
                            $currentAlias = $tokenValue;
                            break;
                        case self::T_LITERAL_USE_SEPARATOR:
                            $state = 'grouped';
                            $extractedUseStatements[(string) $currentAlias] = $currentNs;
                            $currentNs = $groupedNs;
                            $currentAlias = '';
                            break;
                        case self::T_LITERAL_END_OF_USE:
                            $state = 'end';
                            break;
                        default:
                            break;
                    }
            }
            if ($state === 'end') {
                break;
            }
            $tokens->next();
        }
        if ($groupedNs !== $currentNs) {
            $extractedUseStatements[(string) $currentAlias] = $currentNs;
        }
        return $extractedUseStatements;
    }
}
<?php

/**
 * This file is part of phpDocumentor.
 *
 *  For the full copyright and license information, please view the LICENSE
 *  file that was distributed with this source code.
 *
 * @link      http://phpdoc.org
 */
declare (strict_types=1);
namespace _ContaoManager\phpDocumentor\Reflection\Types;

use ArrayIterator;
use IteratorAggregate;
use _ContaoManager\phpDocumentor\Reflection\Type;
use function array_key_exists;
use function implode;
/**
 * Base class for aggregated types like Compound and Intersection
 *
 * A Aggregated Type is not so much a special keyword or object reference but is a series of Types that are separated
 * using separator.
 *
 * @psalm-immutable
 * @template-implements IteratorAggregate<int, Type>
 */
abstract class AggregatedType implements Type, IteratorAggregate
{
    /**
     * @psalm-allow-private-mutation
     * @var array<int, Type>
     */
    private $types = [];
    /** @var string */
    private $token;
    /**
     * @param array<Type> $types
     */
    public function __construct(array $types, string $token)
    {
        foreach ($types as $type) {
            $this->add($type);
        }
        $this->token = $token;
    }
    /**
     * Returns the type at the given index.
     */
    public function get(int $index): ?Type
    {
        if (!$this->has($index)) {
            return null;
        }
        return $this->types[$index];
    }
    /**
     * Tests if this compound type has a type with the given index.
     */
    public function has(int $index): bool
    {
        return array_key_exists($index, $this->types);
    }
    /**
     * Tests if this compound type contains the given type.
     */
    public function contains(Type $type): bool
    {
        foreach ($this->types as $typePart) {
            // if the type is duplicate; do not add it
            if ((string) $typePart === (string) $type) {
                return \true;
            }
        }
        return \false;
    }
    /**
     * Returns a rendered output of the Type as it would be used in a DocBlock.
     */
    public function __toString(): string
    {
        return implode($this->token, $this->types);
    }
    /**
     * @return ArrayIterator<int, Type>
     */
    public function getIterator(): ArrayIterator
    {
        return new ArrayIterator($this->types);
    }
    /**
     * @psalm-suppress ImpureMethodCall
     */
    private function add(Type $type): void
    {
        if ($type instanceof static) {
            foreach ($type->getIterator() as $subType) {
                $this->add($subType);
            }
            return;
        }
        // if the type is duplicate; do not add it
        if ($this->contains($type)) {
            return;
        }
        $this->types[] = $type;
    }
}
<?php

declare (strict_types=1);
/**
 * This file is part of phpDocumentor.
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @link      http://phpdoc.org
 */
namespace _ContaoManager\phpDocumentor\Reflection\Types;

use _ContaoManager\phpDocumentor\Reflection\Type;
/**
 * Value Object representing a Compound Type.
 *
 * A Compound Type is not so much a special keyword or object reference but is a series of Types that are separated
 * using an OR operator (`|`). This combination of types signifies that whatever is associated with this compound type
 * may contain a value with any of the given types.
 *
 * @psalm-immutable
 */
final class Compound extends AggregatedType
{
    /**
     * Initializes a compound type (i.e. `string|int`) and tests if the provided types all implement the Type interface.
     *
     * @param array<Type> $types
     */
    public function __construct(array $types)
    {
        parent::__construct($types, '|');
    }
}
<?php

declare (strict_types=1);
/**
 * This file is part of phpDocumentor.
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @link      http://phpdoc.org
 */
namespace _ContaoManager\phpDocumentor\Reflection\Types;

use _ContaoManager\phpDocumentor\Reflection\Type;
/**
 * Value Object representing the '$this' pseudo-type.
 *
 * $this, as a Type, represents the instance of the class associated with the element as it was called. $this is
 * commonly used when documenting fluent interfaces since it represents that the same object is returned.
 *
 * @psalm-immutable
 */
final class This implements Type
{
    /**
     * Returns a rendered output of the Type as it would be used in a DocBlock.
     */
    public function __toString(): string
    {
        return '$this';
    }
}
<?php

declare (strict_types=1);
/**
 * This file is part of phpDocumentor.
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @link      http://phpdoc.org
 */
namespace _ContaoManager\phpDocumentor\Reflection\Types;

/**
 * Represents an array type as described in the PSR-5, the PHPDoc Standard.
 *
 * An array can be represented in two forms:
 *
 * 1. Untyped (`array`), where the key and value type is unknown and hence classified as 'Mixed_'.
 * 2. Types (`string[]`), where the value type is provided by preceding an opening and closing square bracket with a
 *    type name.
 *
 * @psalm-immutable
 */
class Array_ extends AbstractList
{
}
<?php

declare (strict_types=1);
/**
 * This file is part of phpDocumentor.
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @link      http://phpdoc.org
 */
namespace _ContaoManager\phpDocumentor\Reflection\Types;

use _ContaoManager\phpDocumentor\Reflection\Type;
/**
 * Value Object representing an unknown, or mixed, type.
 *
 * @psalm-immutable
 */
class Mixed_ implements Type
{
    /**
     * Returns a rendered output of the Type as it would be used in a DocBlock.
     */
    public function __toString(): string
    {
        return 'mixed';
    }
}
<?php

declare (strict_types=1);
/**
 * This file is part of phpDocumentor.
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @link      http://phpdoc.org
 */
namespace _ContaoManager\phpDocumentor\Reflection;

/**
 * @psalm-immutable
 */
interface Type
{
    /**
     * Returns a rendered output of the Type as it would be used in a DocBlock.
     */
    public function __toString(): string;
}
<?php

declare (strict_types=1);
/**
 * This file is part of phpDocumentor.
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @link      http://phpdoc.org
 */
namespace _ContaoManager\phpDocumentor\Reflection;

use InvalidArgumentException;
use _ContaoManager\phpDocumentor\Reflection\Types\Context;
use function explode;
use function implode;
use function strpos;
/**
 * Resolver for Fqsen using Context information
 *
 * @psalm-immutable
 */
class FqsenResolver
{
    /** @var string Definition of the NAMESPACE operator in PHP */
    private const OPERATOR_NAMESPACE = '\\';
    public function resolve(string $fqsen, ?Context $context = null): Fqsen
    {
        if ($context === null) {
            $context = new Context('');
        }
        if ($this->isFqsen($fqsen)) {
            return new Fqsen($fqsen);
        }
        return $this->resolvePartialStructuralElementName($fqsen, $context);
    }
    /**
     * Tests whether the given type is a Fully Qualified Structural Element Name.
     */
    private function isFqsen(string $type): bool
    {
        return strpos($type, self::OPERATOR_NAMESPACE) === 0;
    }
    /**
     * Resolves a partial Structural Element Name (i.e. `Reflection\DocBlock`) to its FQSEN representation
     * (i.e. `\phpDocumentor\Reflection\DocBlock`) based on the Namespace and aliases mentioned in the Context.
     *
     * @throws InvalidArgumentException When type is not a valid FQSEN.
     */
    private function resolvePartialStructuralElementName(string $type, Context $context): Fqsen
    {
        $typeParts = explode(self::OPERATOR_NAMESPACE, $type, 2);
        $namespaceAliases = $context->getNamespaceAliases();
        // if the first segment is not an alias; prepend namespace name and return
        if (!isset($namespaceAliases[$typeParts[0]])) {
            $namespace = $context->getNamespace();
            if ($namespace !== '') {
                $namespace .= self::OPERATOR_NAMESPACE;
            }
            return new Fqsen(self::OPERATOR_NAMESPACE . $namespace . $type);
        }
        $typeParts[0] = $namespaceAliases[$typeParts[0]];
        return new Fqsen(self::OPERATOR_NAMESPACE . implode(self::OPERATOR_NAMESPACE, $typeParts));
    }
}
<?php

/*
 * This file is part of phpDocumentor.
 *
 *  For the full copyright and license information, please view the LICENSE
 *  file that was distributed with this source code.
 *
 *  @link      http://phpdoc.org
 *
 */
declare (strict_types=1);
namespace _ContaoManager\phpDocumentor\Reflection\PseudoTypes;

use _ContaoManager\phpDocumentor\Reflection\PseudoType;
use _ContaoManager\phpDocumentor\Reflection\Type;
use _ContaoManager\phpDocumentor\Reflection\Types\String_;
use function sprintf;
/** @psalm-immutable */
class StringValue implements PseudoType
{
    /** @var string */
    private $value;
    public function __construct(string $value)
    {
        $this->value = $value;
    }
    public function getValue(): string
    {
        return $this->value;
    }
    public function underlyingType(): Type
    {
        return new String_();
    }
    public function __toString(): string
    {
        return sprintf('"%s"', $this->value);
    }
}
<?php

declare (strict_types=1);
/**
 * This file is part of phpDocumentor.
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @link      http://phpdoc.org
 */
namespace _ContaoManager\phpDocumentor\Reflection\PseudoTypes;

use _ContaoManager\phpDocumentor\Reflection\PseudoType;
use _ContaoManager\phpDocumentor\Reflection\Type;
use _ContaoManager\phpDocumentor\Reflection\Types\Array_;
use _ContaoManager\phpDocumentor\Reflection\Types\Integer;
use _ContaoManager\phpDocumentor\Reflection\Types\Mixed_;
/**
 * Value Object representing the type 'list'.
 *
 * @psalm-immutable
 */
final class List_ extends Array_ implements PseudoType
{
    public function underlyingType(): Type
    {
        return new Array_();
    }
    public function __construct(?Type $valueType = null)
    {
        parent::__construct($valueType, new Integer());
    }
    /**
     * Returns a rendered output of the Type as it would be used in a DocBlock.
     */
    public function __toString(): string
    {
        if ($this->valueType instanceof Mixed_) {
            return 'list';
        }
        return 'list<' . $this->valueType . '>';
    }
}
<?php

/*
 * This file is part of phpDocumentor.
 *
 *  For the full copyright and license information, please view the LICENSE
 *  file that was distributed with this source code.
 *
 *  @link      http://phpdoc.org
 *
 */
declare (strict_types=1);
namespace _ContaoManager\phpDocumentor\Reflection\PseudoTypes;

use _ContaoManager\phpDocumentor\Reflection\PseudoType;
use _ContaoManager\phpDocumentor\Reflection\Type;
use _ContaoManager\phpDocumentor\Reflection\Types\Integer;
/**
 * Value Object representing the `int-mask-of` type.
 *
 * @psalm-immutable
 */
final class IntMaskOf extends Integer implements PseudoType
{
    /** @var Type */
    private $type;
    public function __construct(Type $type)
    {
        $this->type = $type;
    }
    public function getType(): Type
    {
        return $this->type;
    }
    public function underlyingType(): Type
    {
        return new Integer();
    }
    public function __toString(): string
    {
        return 'int-mask-of<' . $this->type . '>';
    }
}
<?php

declare (strict_types=1);
/**
 * This file is part of phpDocumentor.
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @link      http://phpdoc.org
 */
namespace _ContaoManager\phpDocumentor\Reflection\PseudoTypes;

use _ContaoManager\phpDocumentor\Reflection\PseudoType;
use _ContaoManager\phpDocumentor\Reflection\Type;
use _ContaoManager\phpDocumentor\Reflection\Types\String_;
/**
 * Value Object representing the type 'string'.
 *
 * @psalm-immutable
 */
final class NonEmptyString extends String_ implements PseudoType
{
    public function underlyingType(): Type
    {
        return new String_();
    }
    /**
     * Returns a rendered output of the Type as it would be used in a DocBlock.
     */
    public function __toString(): string
    {
        return 'non-empty-string';
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\phpDocumentor\Reflection\PseudoTypes;

use _ContaoManager\phpDocumentor\Reflection\Type;
use _ContaoManager\phpDocumentor\Reflection\Types\Mixed_;
use function sprintf;
abstract class ShapeItem
{
    /** @var string|null */
    private $key;
    /** @var Type */
    private $value;
    /** @var bool */
    private $optional;
    public function __construct(?string $key, ?Type $value, bool $optional)
    {
        $this->key = $key;
        $this->value = $value ?? new Mixed_();
        $this->optional = $optional;
    }
    public function getKey(): ?string
    {
        return $this->key;
    }
    public function getValue(): Type
    {
        return $this->value;
    }
    public function isOptional(): bool
    {
        return $this->optional;
    }
    public function __toString(): string
    {
        if ($this->key !== null && $this->key !== '') {
            return sprintf('%s%s: %s', $this->key, $this->optional ? '?' : '', (string) $this->value);
        }
        return (string) $this->value;
    }
}
<?php

/*
 * This file is part of phpDocumentor.
 *
 *  For the full copyright and license information, please view the LICENSE
 *  file that was distributed with this source code.
 *
 *  @link      http://phpdoc.org
 *
 */
declare (strict_types=1);
namespace _ContaoManager\phpDocumentor\Reflection\PseudoTypes;

use _ContaoManager\phpDocumentor\Reflection\PseudoType;
use _ContaoManager\phpDocumentor\Reflection\Type;
use _ContaoManager\phpDocumentor\Reflection\Types\ArrayKey;
/**
 * Value Object representing the `key-of` type.
 *
 * @psalm-immutable
 */
final class KeyOf extends ArrayKey implements PseudoType
{
    /** @var Type */
    private $type;
    public function __construct(Type $type)
    {
        $this->type = $type;
    }
    public function getType(): Type
    {
        return $this->type;
    }
    public function underlyingType(): Type
    {
        return new ArrayKey();
    }
    public function __toString(): string
    {
        return 'key-of<' . $this->type . '>';
    }
}
<?php

declare (strict_types=1);
/**
 * This file is part of phpDocumentor.
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @link      http://phpdoc.org
 */
namespace _ContaoManager\phpDocumentor\Reflection\PseudoTypes;

use _ContaoManager\phpDocumentor\Reflection\PseudoType;
use _ContaoManager\phpDocumentor\Reflection\Type;
use _ContaoManager\phpDocumentor\Reflection\Types\Integer;
/**
 * Value Object representing the type 'int'.
 *
 * @psalm-immutable
 */
final class IntegerRange extends Integer implements PseudoType
{
    /** @var string */
    private $minValue;
    /** @var string */
    private $maxValue;
    public function __construct(string $minValue, string $maxValue)
    {
        $this->minValue = $minValue;
        $this->maxValue = $maxValue;
    }
    public function underlyingType(): Type
    {
        return new Integer();
    }
    public function getMinValue(): string
    {
        return $this->minValue;
    }
    public function getMaxValue(): string
    {
        return $this->maxValue;
    }
    /**
     * Returns a rendered output of the Type as it would be used in a DocBlock.
     */
    public function __toString(): string
    {
        return 'int<' . $this->minValue . ', ' . $this->maxValue . '>';
    }
}
<?php

/*
 * This file is part of phpDocumentor.
 *
 *  For the full copyright and license information, please view the LICENSE
 *  file that was distributed with this source code.
 *
 *  @link      http://phpdoc.org
 *
 */
declare (strict_types=1);
namespace _ContaoManager\phpDocumentor\Reflection\PseudoTypes;

use _ContaoManager\phpDocumentor\Reflection\PseudoType;
use _ContaoManager\phpDocumentor\Reflection\Type;
use _ContaoManager\phpDocumentor\Reflection\Types\Callable_;
use _ContaoManager\phpDocumentor\Reflection\Types\Mixed_;
use _ContaoManager\phpDocumentor\Reflection\Types\Nullable;
/**
 * Value Object representing the offset access type.
 *
 * @psalm-immutable
 */
final class OffsetAccess extends Mixed_ implements PseudoType
{
    /** @var Type */
    private $type;
    /** @var Type */
    private $offset;
    public function __construct(Type $type, Type $offset)
    {
        $this->type = $type;
        $this->offset = $offset;
    }
    public function getType(): Type
    {
        return $this->type;
    }
    public function getOffset(): Type
    {
        return $this->offset;
    }
    public function underlyingType(): Type
    {
        return new Mixed_();
    }
    public function __toString(): string
    {
        if ($this->type instanceof Callable_ || $this->type instanceof ConstExpression || $this->type instanceof Nullable) {
            return '(' . $this->type . ')[' . $this->offset . ']';
        }
        return $this->type . '[' . $this->offset . ']';
    }
}
<?php

declare (strict_types=1);
/**
 * This file is part of phpDocumentor.
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @link      http://phpdoc.org
 */
namespace _ContaoManager\phpDocumentor\Reflection\PseudoTypes;

use _ContaoManager\phpDocumentor\Reflection\PseudoType;
use _ContaoManager\phpDocumentor\Reflection\Type;
use _ContaoManager\phpDocumentor\Reflection\Types\String_;
/**
 * Value Object representing the type 'string'.
 *
 * @psalm-immutable
 */
final class CallableString extends String_ implements PseudoType
{
    public function underlyingType(): Type
    {
        return new String_();
    }
    /**
     * Returns a rendered output of the Type as it would be used in a DocBlock.
     */
    public function __toString(): string
    {
        return 'callable-string';
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\phpDocumentor\Reflection\PseudoTypes;

final class ListShapeItem extends ArrayShapeItem
{
}
<?php

/*
 * This file is part of phpDocumentor.
 *
 *  For the full copyright and license information, please view the LICENSE
 *  file that was distributed with this source code.
 *
 *  @link      http://phpdoc.org
 *
 */
declare (strict_types=1);
namespace _ContaoManager\phpDocumentor\Reflection\PseudoTypes;

use _ContaoManager\phpDocumentor\Reflection\PseudoType;
use _ContaoManager\phpDocumentor\Reflection\Type;
use _ContaoManager\phpDocumentor\Reflection\Types\Integer;
use function implode;
/**
 * Value Object representing the `int-mask` type.
 *
 * @psalm-immutable
 */
final class IntMask extends Integer implements PseudoType
{
    /** @var Type[] */
    private $types;
    public function __construct(Type ...$types)
    {
        $this->types = $types;
    }
    /**
     * @return Type[]
     */
    public function getTypes(): array
    {
        return $this->types;
    }
    public function underlyingType(): Type
    {
        return new Integer();
    }
    public function __toString(): string
    {
        return 'int-mask<' . implode(', ', $this->types) . '>';
    }
}
<?php

/*
 * This file is part of phpDocumentor.
 *
 *  For the full copyright and license information, please view the LICENSE
 *  file that was distributed with this source code.
 *
 *  @link      http://phpdoc.org
 *
 */
declare (strict_types=1);
namespace _ContaoManager\phpDocumentor\Reflection\PseudoTypes;

use _ContaoManager\phpDocumentor\Reflection\PseudoType;
use _ContaoManager\phpDocumentor\Reflection\Type;
use _ContaoManager\phpDocumentor\Reflection\Types\Mixed_;
/**
 * Value Object representing the `value-of` type.
 *
 * @psalm-immutable
 */
final class ValueOf extends Mixed_ implements PseudoType
{
    /** @var Type */
    private $type;
    public function __construct(Type $type)
    {
        $this->type = $type;
    }
    public function getType(): Type
    {
        return $this->type;
    }
    public function underlyingType(): Type
    {
        return new Mixed_();
    }
    public function __toString(): string
    {
        return 'value-of<' . $this->type . '>';
    }
}
<?php

declare (strict_types=1);
/**
 * This file is part of phpDocumentor.
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @link      http://phpdoc.org
 */
namespace _ContaoManager\phpDocumentor\Reflection\PseudoTypes;

use _ContaoManager\phpDocumentor\Reflection\PseudoType;
use _ContaoManager\phpDocumentor\Reflection\Type;
use _ContaoManager\phpDocumentor\Reflection\Types\AggregatedType;
use _ContaoManager\phpDocumentor\Reflection\Types\Compound;
use _ContaoManager\phpDocumentor\Reflection\Types\Float_;
use _ContaoManager\phpDocumentor\Reflection\Types\Integer;
/**
 * Value Object representing the 'numeric' pseudo-type, which is either a numeric-string, integer or float.
 *
 * @psalm-immutable
 */
final class Numeric_ extends AggregatedType implements PseudoType
{
    public function __construct()
    {
        AggregatedType::__construct([new NumericString(), new Integer(), new Float_()], '|');
    }
    public function underlyingType(): Type
    {
        return new Compound([new NumericString(), new Integer(), new Float_()]);
    }
    /**
     * Returns a rendered output of the Type as it would be used in a DocBlock.
     */
    public function __toString(): string
    {
        return 'numeric';
    }
}
<?php

declare (strict_types=1);
/**
 * This file is part of phpDocumentor.
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @link https://phpdoc.org
 */
namespace _ContaoManager\phpDocumentor\Reflection\PseudoTypes;

use _ContaoManager\phpDocumentor\Reflection\PseudoType;
use _ContaoManager\phpDocumentor\Reflection\Type;
use _ContaoManager\phpDocumentor\Reflection\Types\Boolean;
use function class_alias;
/**
 * Value Object representing the PseudoType 'False', which is a Boolean type.
 *
 * @psalm-immutable
 */
final class False_ extends Boolean implements PseudoType
{
    public function underlyingType(): Type
    {
        return new Boolean();
    }
    public function __toString(): string
    {
        return 'false';
    }
}
class_alias(False_::class, '_ContaoManager\phpDocumentor\Reflection\Types\False_', \false);
<?php

declare (strict_types=1);
namespace _ContaoManager\phpDocumentor\Reflection\PseudoTypes;

final class ObjectShapeItem extends ShapeItem
{
}
<?php

declare (strict_types=1);
/**
 * This file is part of phpDocumentor.
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @link      http://phpdoc.org
 */
namespace _ContaoManager\phpDocumentor\Reflection\PseudoTypes;

use _ContaoManager\phpDocumentor\Reflection\PseudoType;
use _ContaoManager\phpDocumentor\Reflection\Type;
use _ContaoManager\phpDocumentor\Reflection\Types\String_;
/**
 * Value Object representing the type 'string'.
 *
 * @psalm-immutable
 */
final class TraitString extends String_ implements PseudoType
{
    public function underlyingType(): Type
    {
        return new String_();
    }
    /**
     * Returns a rendered output of the Type as it would be used in a DocBlock.
     */
    public function __toString(): string
    {
        return 'trait-string';
    }
}
<?php

/*
 * This file is part of phpDocumentor.
 *
 *  For the full copyright and license information, please view the LICENSE
 *  file that was distributed with this source code.
 *
 *  @link      http://phpdoc.org
 *
 */
declare (strict_types=1);
namespace _ContaoManager\phpDocumentor\Reflection\PseudoTypes;

use _ContaoManager\phpDocumentor\Reflection\PseudoType;
use _ContaoManager\phpDocumentor\Reflection\Type;
use _ContaoManager\phpDocumentor\Reflection\Types\Float_;
/** @psalm-immutable */
class FloatValue implements PseudoType
{
    /** @var float */
    private $value;
    public function __construct(float $value)
    {
        $this->value = $value;
    }
    public function getValue(): float
    {
        return $this->value;
    }
    public function underlyingType(): Type
    {
        return new Float_();
    }
    public function __toString(): string
    {
        return (string) $this->value;
    }
}
<?php

declare (strict_types=1);
/**
 * This file is part of phpDocumentor.
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @link      http://phpdoc.org
 */
namespace _ContaoManager\phpDocumentor\Reflection\PseudoTypes;

use _ContaoManager\phpDocumentor\Reflection\PseudoType;
use _ContaoManager\phpDocumentor\Reflection\Type;
use _ContaoManager\phpDocumentor\Reflection\Types\String_;
/**
 * Value Object representing the type 'string'.
 *
 * @psalm-immutable
 */
final class NumericString extends String_ implements PseudoType
{
    public function underlyingType(): Type
    {
        return new String_();
    }
    /**
     * Returns a rendered output of the Type as it would be used in a DocBlock.
     */
    public function __toString(): string
    {
        return 'numeric-string';
    }
}
<?php

declare (strict_types=1);
/**
 * This file is part of phpDocumentor.
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @link      http://phpdoc.org
 */
namespace _ContaoManager\phpDocumentor\Reflection\PseudoTypes;

use _ContaoManager\phpDocumentor\Reflection\PseudoType;
use _ContaoManager\phpDocumentor\Reflection\Type;
use _ContaoManager\phpDocumentor\Reflection\Types\String_;
/**
 * Value Object representing the type 'string'.
 *
 * @psalm-immutable
 */
final class HtmlEscapedString extends String_ implements PseudoType
{
    public function underlyingType(): Type
    {
        return new String_();
    }
    /**
     * Returns a rendered output of the Type as it would be used in a DocBlock.
     */
    public function __toString(): string
    {
        return 'html-escaped-string';
    }
}
<?php

/*
 * This file is part of phpDocumentor.
 *
 *  For the full copyright and license information, please view the LICENSE
 *  file that was distributed with this source code.
 *
 *  @link      http://phpdoc.org
 *
 */
declare (strict_types=1);
namespace _ContaoManager\phpDocumentor\Reflection\PseudoTypes;

use _ContaoManager\phpDocumentor\Reflection\PseudoType;
use _ContaoManager\phpDocumentor\Reflection\Type;
use _ContaoManager\phpDocumentor\Reflection\Types\Integer;
/** @psalm-immutable */
final class IntegerValue implements PseudoType
{
    /** @var int */
    private $value;
    public function __construct(int $value)
    {
        $this->value = $value;
    }
    public function getValue(): int
    {
        return $this->value;
    }
    public function underlyingType(): Type
    {
        return new Integer();
    }
    public function __toString(): string
    {
        return (string) $this->value;
    }
}
<?php

declare (strict_types=1);
/**
 * This file is part of phpDocumentor.
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @link      http://phpdoc.org
 */
namespace _ContaoManager\phpDocumentor\Reflection\PseudoTypes;

use _ContaoManager\phpDocumentor\Reflection\PseudoType;
use _ContaoManager\phpDocumentor\Reflection\Type;
use _ContaoManager\phpDocumentor\Reflection\Types\String_;
/**
 * Value Object representing the type 'string'.
 *
 * @psalm-immutable
 */
final class LiteralString extends String_ implements PseudoType
{
    public function underlyingType(): Type
    {
        return new String_();
    }
    /**
     * Returns a rendered output of the Type as it would be used in a DocBlock.
     */
    public function __toString(): string
    {
        return 'literal-string';
    }
}
<?php

declare (strict_types=1);
/**
 * This file is part of phpDocumentor.
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @link      http://phpdoc.org
 */
namespace _ContaoManager\phpDocumentor\Reflection\PseudoTypes;

use _ContaoManager\phpDocumentor\Reflection\PseudoType;
use _ContaoManager\phpDocumentor\Reflection\Type;
use _ContaoManager\phpDocumentor\Reflection\Types\Array_;
use _ContaoManager\phpDocumentor\Reflection\Types\Integer;
use _ContaoManager\phpDocumentor\Reflection\Types\Mixed_;
/**
 * Value Object representing the type 'non-empty-list'.
 *
 * @psalm-immutable
 */
final class NonEmptyList extends Array_ implements PseudoType
{
    public function underlyingType(): Type
    {
        return new Array_($this->valueType, $this->keyType);
    }
    public function __construct(?Type $valueType = null)
    {
        parent::__construct($valueType, new Integer());
    }
    /**
     * Returns a rendered output of the Type as it would be used in a DocBlock.
     */
    public function __toString(): string
    {
        if ($this->valueType instanceof Mixed_) {
            return 'non-empty-list';
        }
        return 'non-empty-list<' . $this->valueType . '>';
    }
}
<?php

/*
 * This file is part of phpDocumentor.
 *
 *  For the full copyright and license information, please view the LICENSE
 *  file that was distributed with this source code.
 *
 *  @link      http://phpdoc.org
 *
 */
declare (strict_types=1);
namespace _ContaoManager\phpDocumentor\Reflection\PseudoTypes;

use _ContaoManager\phpDocumentor\Reflection\PseudoType;
use _ContaoManager\phpDocumentor\Reflection\Type;
use _ContaoManager\phpDocumentor\Reflection\Types\Mixed_;
use function sprintf;
/** @psalm-immutable */
final class ConstExpression implements PseudoType
{
    /** @var Type */
    private $owner;
    /** @var string */
    private $expression;
    public function __construct(Type $owner, string $expression)
    {
        $this->owner = $owner;
        $this->expression = $expression;
    }
    public function getOwner(): Type
    {
        return $this->owner;
    }
    public function getExpression(): string
    {
        return $this->expression;
    }
    public function underlyingType(): Type
    {
        return new Mixed_();
    }
    public function __toString(): string
    {
        return sprintf('%s::%s', (string) $this->owner, $this->expression);
    }
}
<?php

/*
 * This file is part of phpDocumentor.
 *
 *  For the full copyright and license information, please view the LICENSE
 *  file that was distributed with this source code.
 *
 *  @link      http://phpdoc.org
 *
 */
declare (strict_types=1);
namespace _ContaoManager\phpDocumentor\Reflection\PseudoTypes;

use _ContaoManager\phpDocumentor\Reflection\PseudoType;
use _ContaoManager\phpDocumentor\Reflection\Type;
use _ContaoManager\phpDocumentor\Reflection\Types\Array_;
use _ContaoManager\phpDocumentor\Reflection\Types\ArrayKey;
use _ContaoManager\phpDocumentor\Reflection\Types\Mixed_;
use function implode;
/** @psalm-immutable */
class ArrayShape implements PseudoType
{
    /** @var ArrayShapeItem[] */
    private $items;
    public function __construct(ArrayShapeItem ...$items)
    {
        $this->items = $items;
    }
    /**
     * @return ArrayShapeItem[]
     */
    public function getItems(): array
    {
        return $this->items;
    }
    public function underlyingType(): Type
    {
        return new Array_(new Mixed_(), new ArrayKey());
    }
    public function __toString(): string
    {
        return 'array{' . implode(', ', $this->items) . '}';
    }
}
<?php

/*
 * This file is part of phpDocumentor.
 *
 *  For the full copyright and license information, please view the LICENSE
 *  file that was distributed with this source code.
 *
 *  @link      http://phpdoc.org
 *
 */
declare (strict_types=1);
namespace _ContaoManager\phpDocumentor\Reflection\PseudoTypes;

use _ContaoManager\phpDocumentor\Reflection\PseudoType;
use _ContaoManager\phpDocumentor\Reflection\Type;
use _ContaoManager\phpDocumentor\Reflection\Types\Mixed_;
use function sprintf;
/**
 * Value Object representing the conditional type for parameter.
 *
 * @psalm-immutable
 */
final class ConditionalForParameter extends Mixed_ implements PseudoType
{
    /** @var bool */
    private $negated;
    /** @var string */
    private $parameterName;
    /** @var Type */
    private $targetType;
    /** @var Type */
    private $if;
    /** @var Type */
    private $else;
    public function __construct(bool $negated, string $parameterName, Type $targetType, Type $if, Type $else)
    {
        $this->negated = $negated;
        $this->parameterName = $parameterName;
        $this->targetType = $targetType;
        $this->if = $if;
        $this->else = $else;
    }
    public function isNegated(): bool
    {
        return $this->negated;
    }
    public function getParameterName(): string
    {
        return $this->parameterName;
    }
    public function getTargetType(): Type
    {
        return $this->targetType;
    }
    public function getIf(): Type
    {
        return $this->if;
    }
    public function getElse(): Type
    {
        return $this->else;
    }
    public function underlyingType(): Type
    {
        return new Mixed_();
    }
    public function __toString(): string
    {
        return sprintf('(%s %s %s ? %s : %s)', '$' . $this->parameterName, $this->negated ? 'is not' : 'is', (string) $this->targetType, (string) $this->if, (string) $this->else);
    }
}
<?php

declare (strict_types=1);
/**
 * This file is part of phpDocumentor.
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @link      http://phpdoc.org
 */
namespace _ContaoManager\phpDocumentor\Reflection\PseudoTypes;

use _ContaoManager\phpDocumentor\Reflection\PseudoType;
use _ContaoManager\phpDocumentor\Reflection\Type;
use _ContaoManager\phpDocumentor\Reflection\Types\String_;
/**
 * Value Object representing the type 'string'.
 *
 * @psalm-immutable
 */
final class NonEmptyLowercaseString extends String_ implements PseudoType
{
    public function underlyingType(): Type
    {
        return new String_();
    }
    /**
     * Returns a rendered output of the Type as it would be used in a DocBlock.
     */
    public function __toString(): string
    {
        return 'non-empty-lowercase-string';
    }
}
<?php

declare (strict_types=1);
/**
 * This file is part of phpDocumentor.
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @link      http://phpdoc.org
 */
namespace _ContaoManager\phpDocumentor\Reflection\PseudoTypes;

use _ContaoManager\phpDocumentor\Reflection\PseudoType;
use _ContaoManager\phpDocumentor\Reflection\Type;
use _ContaoManager\phpDocumentor\Reflection\Types\Array_;
use _ContaoManager\phpDocumentor\Reflection\Types\Mixed_;
/**
 * Value Object representing the type 'non-empty-array'.
 *
 * @psalm-immutable
 */
final class NonEmptyArray extends Array_ implements PseudoType
{
    public function underlyingType(): Type
    {
        return new Array_($this->valueType, $this->keyType);
    }
    /**
     * Returns a rendered output of the Type as it would be used in a DocBlock.
     */
    public function __toString(): string
    {
        if ($this->keyType) {
            return 'non-empty-array<' . $this->keyType . ',' . $this->valueType . '>';
        }
        if ($this->valueType instanceof Mixed_) {
            return 'non-empty-array';
        }
        return 'non-empty-array<' . $this->valueType . '>';
    }
}
<?php

declare (strict_types=1);
/**
 * This file is part of phpDocumentor.
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @link      http://phpdoc.org
 */
namespace _ContaoManager\phpDocumentor\Reflection\PseudoTypes;

use _ContaoManager\phpDocumentor\Reflection\PseudoType;
use _ContaoManager\phpDocumentor\Reflection\Type;
use _ContaoManager\phpDocumentor\Reflection\Types\String_;
/**
 * Value Object representing the type 'string'.
 *
 * @psalm-immutable
 */
final class LowercaseString extends String_ implements PseudoType
{
    public function underlyingType(): Type
    {
        return new String_();
    }
    /**
     * Returns a rendered output of the Type as it would be used in a DocBlock.
     */
    public function __toString(): string
    {
        return 'lowercase-string';
    }
}
<?php

declare (strict_types=1);
/**
 * This file is part of phpDocumentor.
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @link https://phpdoc.org
 */
namespace _ContaoManager\phpDocumentor\Reflection\PseudoTypes;

use _ContaoManager\phpDocumentor\Reflection\PseudoType;
use _ContaoManager\phpDocumentor\Reflection\Type;
use _ContaoManager\phpDocumentor\Reflection\Types\Boolean;
use function class_alias;
/**
 * Value Object representing the PseudoType 'False', which is a Boolean type.
 *
 * @psalm-immutable
 */
final class True_ extends Boolean implements PseudoType
{
    public function underlyingType(): Type
    {
        return new Boolean();
    }
    public function __toString(): string
    {
        return 'true';
    }
}
class_alias(True_::class, '_ContaoManager\phpDocumentor\Reflection\Types\True_', \false);
<?php

declare (strict_types=1);
namespace _ContaoManager\phpDocumentor\Reflection\PseudoTypes;

use function implode;
/** @psalm-immutable */
final class ListShape extends ArrayShape
{
    public function __toString(): string
    {
        return 'list{' . implode(', ', $this->getItems()) . '}';
    }
}
<?php

declare (strict_types=1);
/**
 * This file is part of phpDocumentor.
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @link      http://phpdoc.org
 */
namespace _ContaoManager\phpDocumentor\Reflection\PseudoTypes;

use _ContaoManager\phpDocumentor\Reflection\PseudoType;
use _ContaoManager\phpDocumentor\Reflection\Type;
use _ContaoManager\phpDocumentor\Reflection\Types\Integer;
/**
 * Value Object representing the type 'int'.
 *
 * @psalm-immutable
 */
final class NegativeInteger extends Integer implements PseudoType
{
    public function underlyingType(): Type
    {
        return new Integer();
    }
    /**
     * Returns a rendered output of the Type as it would be used in a DocBlock.
     */
    public function __toString(): string
    {
        return 'negative-int';
    }
}
<?php

/*
 * This file is part of phpDocumentor.
 *
 *  For the full copyright and license information, please view the LICENSE
 *  file that was distributed with this source code.
 *
 *  @link      http://phpdoc.org
 *
 */
declare (strict_types=1);
namespace _ContaoManager\phpDocumentor\Reflection\PseudoTypes;

class ArrayShapeItem extends ShapeItem
{
}
<?php

declare (strict_types=1);
namespace _ContaoManager\phpDocumentor\Reflection\PseudoTypes;

use _ContaoManager\phpDocumentor\Reflection\PseudoType;
use _ContaoManager\phpDocumentor\Reflection\Type;
use _ContaoManager\phpDocumentor\Reflection\Types\Object_;
use function implode;
/** @psalm-immutable */
final class ObjectShape implements PseudoType
{
    /** @var ObjectShapeItem[] */
    private $items;
    public function __construct(ObjectShapeItem ...$items)
    {
        $this->items = $items;
    }
    /**
     * @return ObjectShapeItem[]
     */
    public function getItems(): array
    {
        return $this->items;
    }
    public function underlyingType(): Type
    {
        return new Object_();
    }
    public function __toString(): string
    {
        return 'object{' . implode(', ', $this->items) . '}';
    }
}
<?php

declare (strict_types=1);
/**
 * This file is part of phpDocumentor.
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @link      http://phpdoc.org
 */
namespace _ContaoManager\phpDocumentor\Reflection\PseudoTypes;

use _ContaoManager\phpDocumentor\Reflection\PseudoType;
use _ContaoManager\phpDocumentor\Reflection\Type;
use _ContaoManager\phpDocumentor\Reflection\Types\Integer;
/**
 * Value Object representing the type 'int'.
 *
 * @psalm-immutable
 */
final class PositiveInteger extends Integer implements PseudoType
{
    public function underlyingType(): Type
    {
        return new Integer();
    }
    /**
     * Returns a rendered output of the Type as it would be used in a DocBlock.
     */
    public function __toString(): string
    {
        return 'positive-int';
    }
}
<?php

/*
 * This file is part of phpDocumentor.
 *
 *  For the full copyright and license information, please view the LICENSE
 *  file that was distributed with this source code.
 *
 *  @link      http://phpdoc.org
 *
 */
declare (strict_types=1);
namespace _ContaoManager\phpDocumentor\Reflection\PseudoTypes;

use _ContaoManager\phpDocumentor\Reflection\PseudoType;
use _ContaoManager\phpDocumentor\Reflection\Type;
use _ContaoManager\phpDocumentor\Reflection\Types\Mixed_;
use function sprintf;
/**
 * Value Object representing the conditional type.
 *
 * @psalm-immutable
 */
final class Conditional extends Mixed_ implements PseudoType
{
    /** @var bool */
    private $negated;
    /** @var Type */
    private $subjectType;
    /** @var Type */
    private $targetType;
    /** @var Type */
    private $if;
    /** @var Type */
    private $else;
    public function __construct(bool $negated, Type $subjectType, Type $targetType, Type $if, Type $else)
    {
        $this->negated = $negated;
        $this->subjectType = $subjectType;
        $this->targetType = $targetType;
        $this->if = $if;
        $this->else = $else;
    }
    public function isNegated(): bool
    {
        return $this->negated;
    }
    public function getSubjectType(): Type
    {
        return $this->subjectType;
    }
    public function getTargetType(): Type
    {
        return $this->targetType;
    }
    public function getIf(): Type
    {
        return $this->if;
    }
    public function getElse(): Type
    {
        return $this->else;
    }
    public function underlyingType(): Type
    {
        return new Mixed_();
    }
    public function __toString(): string
    {
        return sprintf('(%s %s %s ? %s : %s)', (string) $this->subjectType, $this->negated ? 'is not' : 'is', (string) $this->targetType, (string) $this->if, (string) $this->else);
    }
}
<?php

declare (strict_types=1);
/**
 * This file is part of phpDocumentor.
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @link      http://phpdoc.org
 */
namespace _ContaoManager\phpDocumentor\Reflection;

interface PseudoType extends Type
{
    public function underlyingType(): Type;
}
The MIT License (MIT)

Copyright (c) 2010 Mike van Riel

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
[![Integrate](https://github.com/phpDocumentor/ReflectionDocBlock/actions/workflows/integrate.yaml/badge.svg)](https://github.com/phpDocumentor/ReflectionDocBlock/actions/workflows/integrate.yaml)
[![Scrutinizer Code Coverage](https://img.shields.io/scrutinizer/coverage/g/phpDocumentor/ReflectionDocBlock.svg)](https://scrutinizer-ci.com/g/phpDocumentor/ReflectionDocBlock/?branch=master)
[![Scrutinizer Code Quality](https://img.shields.io/scrutinizer/g/phpDocumentor/ReflectionDocBlock.svg)](https://scrutinizer-ci.com/g/phpDocumentor/ReflectionDocBlock/?branch=master)
[![Stable Version](https://img.shields.io/packagist/v/phpdocumentor/reflection-docblock.svg?label=stable)](https://packagist.org/packages/phpdocumentor/reflection-docblock)
[![Unstable Version](https://img.shields.io/packagist/v/phpdocumentor/reflection-docblock.svg?include_prereleases&label=unstable)](https://packagist.org/packages/phpdocumentor/reflection-docblock)

ReflectionDocBlock 
==================

Introduction
------------

The ReflectionDocBlock component of phpDocumentor provides a DocBlock parser
that is 100% compatible with the [PHPDoc standard](http://phpdoc.org/docs/latest).

With this component, a library can provide support for annotations via DocBlocks
or otherwise retrieve information that is embedded in a DocBlock.

Installation
------------

```bash
composer require phpdocumentor/reflection-docblock
```

Usage
-----

In order to parse the DocBlock one needs a DocBlockFactory that can be
instantiated using its `createInstance` factory method like this:

```php
$factory  = \phpDocumentor\Reflection\DocBlockFactory::createInstance();
```

Then we can use the `create` method of the factory to interpret the DocBlock.
Please note that it is also possible to provide a class that has the
`getDocComment()` method, such as an object of type `ReflectionClass`, the
create method will read that if it exists.

```php
$docComment = <<<DOCCOMMENT
/**
 * This is an example of a summary.
 *
 * This is a Description. A Summary and Description are separated by either
 * two subsequent newlines (thus a whiteline in between as can be seen in this
 * example), or when the Summary ends with a dot (`.`) and some form of
 * whitespace.
 */
DOCCOMMENT;

$docblock = $factory->create($docComment);
```

The `create` method will yield an object of type `\phpDocumentor\Reflection\DocBlock`
whose methods can be queried:

```php
// Contains the summary for this DocBlock
$summary = $docblock->getSummary();

// Contains \phpDocumentor\Reflection\DocBlock\Description object
$description = $docblock->getDescription();

// You can either cast it to string
$description = (string) $docblock->getDescription();

// Or use the render method to get a string representation of the Description.
$description = $docblock->getDescription()->render();
```

> For more examples it would be best to review the scripts in the [`/examples` folder](/examples).
{
    "name": "phpdocumentor\/reflection-docblock",
    "description": "With this component, a library can provide support for annotations via DocBlocks or otherwise retrieve information that is embedded in a DocBlock.",
    "type": "library",
    "license": "MIT",
    "authors": [
        {
            "name": "Mike van Riel",
            "email": "me@mikevanriel.com"
        },
        {
            "name": "Jaap van Otterdijk",
            "email": "opensource@ijaap.nl"
        }
    ],
    "require": {
        "php": "^7.4 || ^8.0",
        "phpdocumentor\/type-resolver": "^1.7",
        "webmozart\/assert": "^1.9.1 || ^2",
        "phpdocumentor\/reflection-common": "^2.2",
        "ext-filter": "*",
        "phpstan\/phpdoc-parser": "^1.7|^2.0",
        "doctrine\/deprecations": "^1.1"
    },
    "require-dev": {
        "mockery\/mockery": "~1.3.5 || ~1.6.0",
        "phpunit\/phpunit": "^9.5",
        "phpstan\/phpstan": "^1.8",
        "phpstan\/phpstan-mockery": "^1.1",
        "phpstan\/extension-installer": "^1.1",
        "phpstan\/phpstan-webmozart-assert": "^1.2",
        "psalm\/phar": "^5.26"
    },
    "autoload": {
        "psr-4": {
            "_ContaoManager\\phpDocumentor\\Reflection\\": "src"
        }
    },
    "autoload-dev": {
        "psr-4": {
            "_ContaoManager\\phpDocumentor\\Reflection\\": [
                "tests\/unit",
                "tests\/integration"
            ]
        }
    },
    "config": {
        "platform": {
            "php": "7.4.0"
        },
        "allow-plugins": {
            "phpstan\/extension-installer": true
        }
    },
    "extra": {
        "branch-alias": {
            "dev-master": "5.x-dev"
        }
    }
}<?php

declare (strict_types=1);
/**
 * This file is part of phpDocumentor.
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @link      http://phpdoc.org
 */
namespace _ContaoManager\phpDocumentor\Reflection;

use InvalidArgumentException;
use LogicException;
use _ContaoManager\phpDocumentor\Reflection\DocBlock\DescriptionFactory;
use _ContaoManager\phpDocumentor\Reflection\DocBlock\StandardTagFactory;
use _ContaoManager\phpDocumentor\Reflection\DocBlock\Tag;
use _ContaoManager\phpDocumentor\Reflection\DocBlock\TagFactory;
use _ContaoManager\phpDocumentor\Reflection\DocBlock\Tags\Factory\AbstractPHPStanFactory;
use _ContaoManager\phpDocumentor\Reflection\DocBlock\Tags\Factory\ExtendsFactory;
use _ContaoManager\phpDocumentor\Reflection\DocBlock\Tags\Factory\Factory;
use _ContaoManager\phpDocumentor\Reflection\DocBlock\Tags\Factory\ImplementsFactory;
use _ContaoManager\phpDocumentor\Reflection\DocBlock\Tags\Factory\MethodFactory;
use _ContaoManager\phpDocumentor\Reflection\DocBlock\Tags\Factory\ParamFactory;
use _ContaoManager\phpDocumentor\Reflection\DocBlock\Tags\Factory\PropertyFactory;
use _ContaoManager\phpDocumentor\Reflection\DocBlock\Tags\Factory\PropertyReadFactory;
use _ContaoManager\phpDocumentor\Reflection\DocBlock\Tags\Factory\PropertyWriteFactory;
use _ContaoManager\phpDocumentor\Reflection\DocBlock\Tags\Factory\ReturnFactory;
use _ContaoManager\phpDocumentor\Reflection\DocBlock\Tags\Factory\TemplateExtendsFactory;
use _ContaoManager\phpDocumentor\Reflection\DocBlock\Tags\Factory\TemplateFactory;
use _ContaoManager\phpDocumentor\Reflection\DocBlock\Tags\Factory\TemplateImplementsFactory;
use _ContaoManager\phpDocumentor\Reflection\DocBlock\Tags\Factory\VarFactory;
use _ContaoManager\Webmozart\Assert\Assert;
use function array_shift;
use function count;
use function explode;
use function is_object;
use function method_exists;
use function preg_match;
use function preg_replace;
use function str_replace;
use function strpos;
use function substr;
use function trim;
final class DocBlockFactory implements DocBlockFactoryInterface
{
    private DocBlock\DescriptionFactory $descriptionFactory;
    private TagFactory $tagFactory;
    /**
     * Initializes this factory with the required subcontractors.
     */
    public function __construct(DescriptionFactory $descriptionFactory, TagFactory $tagFactory)
    {
        $this->descriptionFactory = $descriptionFactory;
        $this->tagFactory = $tagFactory;
    }
    /**
     * Factory method for easy instantiation.
     *
     * @param array<string, class-string<Tag>|Factory> $additionalTags
     */
    public static function createInstance(array $additionalTags = []): DocBlockFactoryInterface
    {
        $fqsenResolver = new FqsenResolver();
        $tagFactory = new StandardTagFactory($fqsenResolver);
        $descriptionFactory = new DescriptionFactory($tagFactory);
        $typeResolver = new TypeResolver($fqsenResolver);
        $phpstanTagFactory = new AbstractPHPStanFactory(new ParamFactory($typeResolver, $descriptionFactory), new VarFactory($typeResolver, $descriptionFactory), new ReturnFactory($typeResolver, $descriptionFactory), new PropertyFactory($typeResolver, $descriptionFactory), new PropertyReadFactory($typeResolver, $descriptionFactory), new PropertyWriteFactory($typeResolver, $descriptionFactory), new MethodFactory($typeResolver, $descriptionFactory), new ImplementsFactory($typeResolver, $descriptionFactory), new ExtendsFactory($typeResolver, $descriptionFactory), new TemplateFactory($typeResolver, $descriptionFactory), new TemplateImplementsFactory($typeResolver, $descriptionFactory), new TemplateExtendsFactory($typeResolver, $descriptionFactory));
        $tagFactory->addService($descriptionFactory);
        $tagFactory->addService($typeResolver);
        $tagFactory->registerTagHandler('param', $phpstanTagFactory);
        $tagFactory->registerTagHandler('var', $phpstanTagFactory);
        $tagFactory->registerTagHandler('return', $phpstanTagFactory);
        $tagFactory->registerTagHandler('property', $phpstanTagFactory);
        $tagFactory->registerTagHandler('property-read', $phpstanTagFactory);
        $tagFactory->registerTagHandler('property-write', $phpstanTagFactory);
        $tagFactory->registerTagHandler('method', $phpstanTagFactory);
        $tagFactory->registerTagHandler('extends', $phpstanTagFactory);
        $tagFactory->registerTagHandler('implements', $phpstanTagFactory);
        $tagFactory->registerTagHandler('template', $phpstanTagFactory);
        $tagFactory->registerTagHandler('template-extends', $phpstanTagFactory);
        $tagFactory->registerTagHandler('template-implements', $phpstanTagFactory);
        $docBlockFactory = new self($descriptionFactory, $tagFactory);
        foreach ($additionalTags as $tagName => $tagHandler) {
            $docBlockFactory->registerTagHandler($tagName, $tagHandler);
        }
        return $docBlockFactory;
    }
    /**
     * @param object|string $docblock A string containing the DocBlock to parse or an object supporting the
     *                                getDocComment method (such as a ReflectionClass object).
     */
    public function create($docblock, ?Types\Context $context = null, ?Location $location = null): DocBlock
    {
        if (is_object($docblock)) {
            if (!method_exists($docblock, 'getDocComment')) {
                $exceptionMessage = 'Invalid object passed; the given object must support the getDocComment method';
                throw new InvalidArgumentException($exceptionMessage);
            }
            $docblock = $docblock->getDocComment();
            Assert::string($docblock);
        }
        Assert::stringNotEmpty($docblock);
        if ($context === null) {
            $context = new Types\Context('');
        }
        $parts = $this->splitDocBlock($this->stripDocComment($docblock));
        [$templateMarker, $summary, $description, $tags] = $parts;
        return new DocBlock($summary, $description ? $this->descriptionFactory->create($description, $context) : null, $this->parseTagBlock($tags, $context), $context, $location, $templateMarker === '#@+', $templateMarker === '#@-');
    }
    /**
     * @param class-string<Tag>|Factory $handler
     */
    public function registerTagHandler(string $tagName, $handler): void
    {
        $this->tagFactory->registerTagHandler($tagName, $handler);
    }
    /**
     * Strips the asterisks from the DocBlock comment.
     *
     * @param string $comment String containing the comment text.
     */
    private function stripDocComment(string $comment): string
    {
        $comment = preg_replace('#[ \t]*(?:\/\*\*|\*\/|\*)?[ \t]?(.*)?#u', '$1', $comment);
        Assert::string($comment);
        $comment = trim($comment);
        // reg ex above is not able to remove */ from a single line docblock
        if (substr($comment, -2) === '*/') {
            $comment = trim(substr($comment, 0, -2));
        }
        return str_replace(["\r\n", "\r"], "\n", $comment);
    }
    // phpcs:disable
    /**
     * Splits the DocBlock into a template marker, summary, description and block of tags.
     *
     * @param string $comment Comment to split into the sub-parts.
     *
     * @return string[] containing the template marker (if any), summary, description and a string containing the tags.
     *
     * @author Mike van Riel <me@mikevanriel.com> for extending the regex with template marker support.
     *
     * @author Richard van Velzen (@_richardJ) Special thanks to Richard for the regex responsible for the split.
     */
    private function splitDocBlock(string $comment): array
    {
        // phpcs:enable
        // Performance improvement cheat: if the first character is an @ then only tags are in this DocBlock. This
        // method does not split tags so we return this verbatim as the fourth result (tags). This saves us the
        // performance impact of running a regular expression
        if (strpos($comment, '@') === 0) {
            return ['', '', '', $comment];
        }
        // clears all extra horizontal whitespace from the line endings to prevent parsing issues
        $comment = preg_replace('/\h*$/Sum', '', $comment);
        Assert::string($comment);
        /*
         * Splits the docblock into a template marker, summary, description and tags section.
         *
         * - The template marker is empty, #@+ or #@- if the DocBlock starts with either of those (a newline may
         *   occur after it and will be stripped).
         * - The short description is started from the first character until a dot is encountered followed by a
         *   newline OR two consecutive newlines (horizontal whitespace is taken into account to consider spacing
         *   errors). This is optional.
         * - The long description, any character until a new line is encountered followed by an @ and word
         *   characters (a tag). This is optional.
         * - Tags; the remaining characters
         *
         * Big thanks to RichardJ for contributing this Regular Expression
         */
        preg_match('/
            \A
            # 1. Extract the template marker
            (?:(\#\@\+|\#\@\-)\n?)?

            # 2. Extract the summary
            (?:
              (?! @\pL ) # The summary may not start with an @
              (
                [^\n.]+
                (?:
                  (?! \. \n | \n{2} )     # End summary upon a dot followed by newline or two newlines
                  [\n.]* (?! [ \t]* @\pL ) # End summary when an @ is found as first character on a new line
                  [^\n.]+                 # Include anything else
                )*
                \.?
              )?
            )

            # 3. Extract the description
            (?:
              \s*        # Some form of whitespace _must_ precede a description because a summary must be there
              (?! @\pL ) # The description may not start with an @
              (
                [^\n]+
                (?: \n+
                  (?! [ \t]* @\pL ) # End description when an @ is found as first character on a new line
                  [^\n]+            # Include anything else
                )*
              )
            )?

            # 4. Extract the tags (anything that follows)
            (\s+ [\s\S]*)? # everything that follows
            /ux', $comment, $matches);
        array_shift($matches);
        while (count($matches) < 4) {
            $matches[] = '';
        }
        return $matches;
    }
    /**
     * Creates the tag objects.
     *
     * @param string $tags Tag block to parse.
     * @param Types\Context $context Context of the parsed Tag
     *
     * @return DocBlock\Tag[]
     */
    private function parseTagBlock(string $tags, Types\Context $context): array
    {
        $tags = $this->filterTagBlock($tags);
        if ($tags === null) {
            return [];
        }
        $result = [];
        $lines = $this->splitTagBlockIntoTagLines($tags);
        foreach ($lines as $key => $tagLine) {
            $result[$key] = $this->tagFactory->create(trim($tagLine), $context);
        }
        return $result;
    }
    /**
     * @return string[]
     */
    private function splitTagBlockIntoTagLines(string $tags): array
    {
        $result = [];
        foreach (explode("\n", $tags) as $tagLine) {
            if ($tagLine !== '' && strpos($tagLine, '@') === 0) {
                $result[] = $tagLine;
            } else {
                $result[count($result) - 1] .= "\n" . $tagLine;
            }
        }
        return $result;
    }
    private function filterTagBlock(string $tags): ?string
    {
        $tags = trim($tags);
        if (!$tags) {
            return null;
        }
        if ($tags[0] !== '@') {
            // @codeCoverageIgnoreStart
            // Can't simulate this; this only happens if there is an error with the parsing of the DocBlock that
            // we didn't foresee.
            throw new LogicException('A tag block started with text instead of an at-sign(@): ' . $tags);
            // @codeCoverageIgnoreEnd
        }
        return $tags;
    }
}
<?php

declare (strict_types=1);
/**
 * This file is part of phpDocumentor.
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @link http://phpdoc.org
 */
namespace _ContaoManager\phpDocumentor\Reflection\DocBlock;

use _ContaoManager\phpDocumentor\Reflection\DocBlock;
use _ContaoManager\phpDocumentor\Reflection\DocBlock\Tags\Formatter;
use _ContaoManager\phpDocumentor\Reflection\DocBlock\Tags\Formatter\PassthroughFormatter;
use function sprintf;
use function str_repeat;
use function str_replace;
use function strlen;
use function wordwrap;
/**
 * Converts a DocBlock back from an object to a complete DocComment including Asterisks.
 */
class Serializer
{
    /** @var string The string to indent the comment with. */
    protected string $indentString = ' ';
    /** @var int The number of times the indent string is repeated. */
    protected int $indent = 0;
    /** @var bool Whether to indent the first line with the given indent amount and string. */
    protected bool $isFirstLineIndented = \true;
    /** @var int|null The max length of a line. */
    protected ?int $lineLength = null;
    /** @var Formatter A custom tag formatter. */
    protected Formatter $tagFormatter;
    private string $lineEnding;
    /**
     * Create a Serializer instance.
     *
     * @param int       $indent          The number of times the indent string is repeated.
     * @param string    $indentString    The string to indent the comment with.
     * @param bool      $indentFirstLine Whether to indent the first line.
     * @param int|null  $lineLength      The max length of a line or NULL to disable line wrapping.
     * @param Formatter $tagFormatter    A custom tag formatter, defaults to PassthroughFormatter.
     * @param string    $lineEnding      Line ending used in the output, by default \n is used.
     */
    public function __construct(int $indent = 0, string $indentString = ' ', bool $indentFirstLine = \true, ?int $lineLength = null, ?Formatter $tagFormatter = null, string $lineEnding = "\n")
    {
        $this->indent = $indent;
        $this->indentString = $indentString;
        $this->isFirstLineIndented = $indentFirstLine;
        $this->lineLength = $lineLength;
        $this->tagFormatter = $tagFormatter ?: new PassthroughFormatter();
        $this->lineEnding = $lineEnding;
    }
    /**
     * Generate a DocBlock comment.
     *
     * @param DocBlock $docblock The DocBlock to serialize.
     *
     * @return string The serialized doc block.
     */
    public function getDocComment(DocBlock $docblock): string
    {
        $indent = str_repeat($this->indentString, $this->indent);
        $firstIndent = $this->isFirstLineIndented ? $indent : '';
        // 3 === strlen(' * ')
        $wrapLength = $this->lineLength !== null ? $this->lineLength - strlen($indent) - 3 : null;
        $text = $this->removeTrailingSpaces($indent, $this->addAsterisksForEachLine($indent, $this->getSummaryAndDescriptionTextBlock($docblock, $wrapLength)));
        $comment = $firstIndent . "/**\n";
        if ($text) {
            $comment .= $indent . ' * ' . $text . "\n";
            $comment .= $indent . " *\n";
        }
        $comment = $this->addTagBlock($docblock, $wrapLength, $indent, $comment);
        return str_replace("\n", $this->lineEnding, $comment . $indent . ' */');
    }
    private function removeTrailingSpaces(string $indent, string $text): string
    {
        return str_replace(sprintf("\n%s * \n", $indent), sprintf("\n%s *\n", $indent), $text);
    }
    private function addAsterisksForEachLine(string $indent, string $text): string
    {
        return str_replace("\n", sprintf("\n%s * ", $indent), $text);
    }
    private function getSummaryAndDescriptionTextBlock(DocBlock $docblock, ?int $wrapLength): string
    {
        $text = $docblock->getSummary() . ((string) $docblock->getDescription() ? "\n\n" . $docblock->getDescription() : '');
        if ($wrapLength !== null) {
            $text = wordwrap($text, $wrapLength);
            return $text;
        }
        return $text;
    }
    private function addTagBlock(DocBlock $docblock, ?int $wrapLength, string $indent, string $comment): string
    {
        foreach ($docblock->getTags() as $tag) {
            $tagText = $this->tagFormatter->format($tag);
            if ($wrapLength !== null) {
                $tagText = wordwrap($tagText, $wrapLength);
            }
            $tagText = str_replace("\n", sprintf("\n%s * ", $indent), $tagText);
            $comment .= sprintf("%s * %s\n", $indent, $tagText);
        }
        return $comment;
    }
}
<?php

declare (strict_types=1);
/**
 * This file is part of phpDocumentor.
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @link      http://phpdoc.org
 */
namespace _ContaoManager\phpDocumentor\Reflection\DocBlock;

use _ContaoManager\phpDocumentor\Reflection\DocBlock\Tags\Example;
use function array_slice;
use function file;
use function getcwd;
use function implode;
use function is_readable;
use function rtrim;
use function sprintf;
use function trim;
use const DIRECTORY_SEPARATOR;
/**
 * Class used to find an example file's location based on a given ExampleDescriptor.
 */
class ExampleFinder
{
    private string $sourceDirectory = '';
    /** @var string[] */
    private array $exampleDirectories = [];
    /**
     * Attempts to find the example contents for the given descriptor.
     */
    public function find(Example $example): string
    {
        $filename = $example->getFilePath();
        $file = $this->getExampleFileContents($filename);
        if ($file === null) {
            return sprintf('** File not found : %s **', $filename);
        }
        return implode('', array_slice($file, $example->getStartingLine() - 1, $example->getLineCount()));
    }
    /**
     * Registers the project's root directory where an 'examples' folder can be expected.
     */
    public function setSourceDirectory(string $directory = ''): void
    {
        $this->sourceDirectory = $directory;
    }
    /**
     * Returns the project's root directory where an 'examples' folder can be expected.
     */
    public function getSourceDirectory(): string
    {
        return $this->sourceDirectory;
    }
    /**
     * Registers a series of directories that may contain examples.
     *
     * @param string[] $directories
     */
    public function setExampleDirectories(array $directories): void
    {
        $this->exampleDirectories = $directories;
    }
    /**
     * Returns a series of directories that may contain examples.
     *
     * @return string[]
     */
    public function getExampleDirectories(): array
    {
        return $this->exampleDirectories;
    }
    /**
     * Attempts to find the requested example file and returns its contents or null if no file was found.
     *
     * This method will try several methods in search of the given example file, the first one it encounters is
     * returned:
     *
     * 1. Iterates through all examples folders for the given filename
     * 2. Checks the source folder for the given filename
     * 3. Checks the 'examples' folder in the current working directory for examples
     * 4. Checks the path relative to the current working directory for the given filename
     *
     * @return string[] all lines of the example file
     */
    private function getExampleFileContents(string $filename): ?array
    {
        $normalizedPath = null;
        foreach ($this->exampleDirectories as $directory) {
            $exampleFileFromConfig = $this->constructExamplePath($directory, $filename);
            if (is_readable($exampleFileFromConfig)) {
                $normalizedPath = $exampleFileFromConfig;
                break;
            }
        }
        if ($normalizedPath === null) {
            if (is_readable($this->getExamplePathFromSource($filename))) {
                $normalizedPath = $this->getExamplePathFromSource($filename);
            } elseif (is_readable($this->getExamplePathFromExampleDirectory($filename))) {
                $normalizedPath = $this->getExamplePathFromExampleDirectory($filename);
            } elseif (is_readable($filename)) {
                $normalizedPath = $filename;
            }
        }
        $lines = $normalizedPath !== null && is_readable($normalizedPath) ? file($normalizedPath) : \false;
        return $lines !== \false ? $lines : null;
    }
    /**
     * Get example filepath based on the example directory inside your project.
     */
    private function getExamplePathFromExampleDirectory(string $file): string
    {
        return getcwd() . DIRECTORY_SEPARATOR . 'examples' . DIRECTORY_SEPARATOR . $file;
    }
    /**
     * Returns a path to the example file in the given directory..
     */
    private function constructExamplePath(string $directory, string $file): string
    {
        return rtrim($directory, '\/') . DIRECTORY_SEPARATOR . $file;
    }
    /**
     * Get example filepath based on sourcecode.
     */
    private function getExamplePathFromSource(string $file): string
    {
        return sprintf('%s%s%s', trim($this->getSourceDirectory(), '\/'), DIRECTORY_SEPARATOR, trim($file, '"'));
    }
}
<?php

declare (strict_types=1);
/**
 * This file is part of phpDocumentor.
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @link      http://phpdoc.org
 */
namespace _ContaoManager\phpDocumentor\Reflection\DocBlock;

use _ContaoManager\phpDocumentor\Reflection\DocBlock\Tags\Formatter;
interface Tag
{
    public function getName(): string;
    /**
     * @return Tag|mixed Class that implements Tag
     * @phpstan-return ?Tag
     */
    public static function create(string $body);
    public function render(?Formatter $formatter = null): string;
    public function __toString(): string;
}
<?php

declare (strict_types=1);
/**
 * This file is part of phpDocumentor.
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @link http://phpdoc.org
 */
namespace _ContaoManager\phpDocumentor\Reflection\DocBlock;

use InvalidArgumentException;
use _ContaoManager\phpDocumentor\Reflection\DocBlock\Tags\Factory\Factory;
interface TagFactory extends Factory
{
    /**
     * Adds a parameter to the service locator that can be injected in a tag's factory method.
     *
     * When calling a tag's "create" method we always check the signature for dependencies to inject. One way is to
     * typehint a parameter in the signature so that we can use that interface or class name to inject a dependency
     * (see {@see addService()} for more information on that).
     *
     * Another way is to check the name of the argument against the names in the Service Locator. With this method
     * you can add a variable that will be inserted when a tag's create method is not typehinted and has a matching
     * name.
     *
     * Be aware that there are two reserved names:
     *
     * - name, representing the name of the tag.
     * - body, representing the complete body of the tag.
     *
     * These parameters are injected at the last moment and will override any existing parameter with those names.
     *
     * @param mixed $value
     */
    public function addParameter(string $name, $value): void;
    /**
     * Registers a service with the Service Locator using the FQCN of the class or the alias, if provided.
     *
     * When calling a tag's "create" method we always check the signature for dependencies to inject. If a parameter
     * has a typehint then the ServiceLocator is queried to see if a Service is registered for that typehint.
     *
     * Because interfaces are regularly used as type-hints this method provides an alias parameter; if the FQCN of the
     * interface is passed as alias then every time that interface is requested the provided service will be returned.
     */
    public function addService(object $service): void;
    /**
     * Registers a handler for tags.
     *
     * If you want to use your own tags then you can use this method to instruct the TagFactory
     * to register the name of a tag with the FQCN of a 'Tag Handler'. The Tag handler should implement
     * the {@see Tag} interface (and thus the create method).
     *
     * @param string                    $tagName Name of tag to register a handler for. When registering a namespaced
     *                                   tag, the full name, along with a prefixing slash MUST be provided.
     * @param class-string<Tag>|Factory $handler FQCN of handler.
     *
     * @throws InvalidArgumentException If the tag name is not a string.
     * @throws InvalidArgumentException If the tag name is namespaced (contains backslashes) but
     *                                   does not start with a backslash.
     * @throws InvalidArgumentException If the handler is not a string.
     * @throws InvalidArgumentException If the handler is not an existing class.
     * @throws InvalidArgumentException If the handler does not implement the {@see Tag} interface.
     */
    public function registerTagHandler(string $tagName, $handler): void;
}
<?php

declare (strict_types=1);
/**
 * This file is part of phpDocumentor.
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @link      http://phpdoc.org
 */
namespace _ContaoManager\phpDocumentor\Reflection\DocBlock;

use _ContaoManager\phpDocumentor\Reflection\DocBlock\Tags\Factory\Factory;
use _ContaoManager\phpDocumentor\Reflection\Types\Context as TypeContext;
use _ContaoManager\phpDocumentor\Reflection\Utils;
use function count;
use function implode;
use function ltrim;
use function min;
use function str_replace;
use function strlen;
use function strpos;
use function substr;
use function trim;
use const PREG_SPLIT_DELIM_CAPTURE;
/**
 * Creates a new Description object given a body of text.
 *
 * Descriptions in phpDocumentor are somewhat complex entities as they can contain one or more tags inside their
 * body that can be replaced with a readable output. The replacing is done by passing a Formatter object to the
 * Description object's `render` method.
 *
 * In addition to the above does a Description support two types of escape sequences:
 *
 * 1. `{@}` to escape the `@` character to prevent it from being interpreted as part of a tag, i.e. `{{@}link}`
 * 2. `{}` to escape the `}` character, this can be used if you want to use the `}` character in the description
 *    of an inline tag.
 *
 * If a body consists of multiple lines then this factory will also remove any superfluous whitespace at the beginning
 * of each line while maintaining any indentation that is used. This will prevent formatting parsers from tripping
 * over unexpected spaces as can be observed with tag descriptions.
 */
class DescriptionFactory
{
    private Factory $tagFactory;
    /**
     * Initializes this factory with the means to construct (inline) tags.
     */
    public function __construct(Factory $tagFactory)
    {
        $this->tagFactory = $tagFactory;
    }
    /**
     * Returns the parsed text of this description.
     */
    public function create(string $contents, ?TypeContext $context = null): Description
    {
        $tokens = $this->lex($contents);
        $count = count($tokens);
        $tagCount = 0;
        $tags = [];
        for ($i = 1; $i < $count; $i += 2) {
            $tags[] = $this->tagFactory->create($tokens[$i], $context);
            $tokens[$i] = '%' . ++$tagCount . '$s';
        }
        //In order to allow "literal" inline tags, the otherwise invalid
        //sequence "{@}" is changed to "@", and "{}" is changed to "}".
        //"%" is escaped to "%%" because of vsprintf.
        //See unit tests for examples.
        for ($i = 0; $i < $count; $i += 2) {
            $tokens[$i] = str_replace(['{@}', '{}', '%'], ['@', '}', '%%'], $tokens[$i]);
        }
        return new Description(implode('', $tokens), $tags);
    }
    /**
     * Strips the contents from superfluous whitespace and splits the description into a series of tokens.
     *
     * @return string[] A series of tokens of which the description text is composed.
     */
    private function lex(string $contents): array
    {
        $contents = $this->removeSuperfluousStartingWhitespace($contents);
        // performance optimalization; if there is no inline tag, don't bother splitting it up.
        if (strpos($contents, '{@') === \false) {
            return [$contents];
        }
        return Utils::pregSplit('/\{
                # "{@}" and "{@*}" are not a valid inline tags. This ensures that we do not treat them as one, but treat
                # them literally.
                (?!(?:@\}|@\*\}) )
                # We want to capture the whole tag line, but without the inline tag delimiters.
                (\@
                    # Match everything up to the next delimiter.
                    [^{}]*
                    # Nested inline tag content should not be captured, or it will appear in the result separately.
                    (?:
                        # Match nested inline tags.
                        (?:
                            # Because we did not catch the tag delimiters earlier, we must be explicit with them here.
                            # Notice that this also matches "{}", as a way to later introduce it as an escape sequence.
                            \{(?1)?\}
                            |
                            # Make sure we match hanging "{".
                            \{
                        )
                        # Match content after the nested inline tag.
                        [^{}]*
                    )* # If there are more inline tags, match them as well. We use "*" since there may not be any
                       # nested inline tags.
                )
            \}/Sux', $contents, 0, PREG_SPLIT_DELIM_CAPTURE);
    }
    /**
     * Removes the superfluous from a multi-line description.
     *
     * When a description has more than one line then it can happen that the second and subsequent lines have an
     * additional indentation. This is commonly in use with tags like this:
     *
     *     {@}since 1.1.0 This is an example
     *         description where we have an
     *         indentation in the second and
     *         subsequent lines.
     *
     * If we do not normalize the indentation then we have superfluous whitespace on the second and subsequent
     * lines and this may cause rendering issues when, for example, using a Markdown converter.
     */
    private function removeSuperfluousStartingWhitespace(string $contents): string
    {
        $lines = Utils::pregSplit("/\r\n?|\n/", $contents);
        // if there is only one line then we don't have lines with superfluous whitespace and
        // can use the contents as-is
        if (count($lines) <= 1) {
            return $contents;
        }
        // determine how many whitespace characters need to be stripped
        $startingSpaceCount = 9999999;
        for ($i = 1, $iMax = count($lines); $i < $iMax; ++$i) {
            // lines with a no length do not count as they are not indented at all
            if (trim($lines[$i]) === '') {
                continue;
            }
            // determine the number of prefixing spaces by checking the difference in line length before and after
            // an ltrim
            $startingSpaceCount = min($startingSpaceCount, strlen($lines[$i]) - strlen(ltrim($lines[$i])));
        }
        // strip the number of spaces from each line
        if ($startingSpaceCount > 0) {
            for ($i = 1, $iMax = count($lines); $i < $iMax; ++$i) {
                $lines[$i] = substr($lines[$i], $startingSpaceCount);
            }
        }
        return implode("\n", $lines);
    }
}
<?php

declare (strict_types=1);
/**
 * This file is part of phpDocumentor.
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @link      http://phpdoc.org
 */
namespace _ContaoManager\phpDocumentor\Reflection\DocBlock\Tags;

use _ContaoManager\phpDocumentor\Reflection\DocBlock\Description;
use _ContaoManager\phpDocumentor\Reflection\DocBlock\DescriptionFactory;
use _ContaoManager\phpDocumentor\Reflection\Types\Context as TypeContext;
use _ContaoManager\Webmozart\Assert\Assert;
use function preg_match;
/**
 * Reflection class for a {@}since tag in a Docblock.
 */
final class Since extends BaseTag implements Factory\StaticMethod
{
    protected string $name = 'since';
    /**
     * PCRE regular expression matching a version vector.
     * Assumes the "x" modifier.
     */
    public const REGEX_VECTOR = '(?:
        # Normal release vectors.
        \d\S*
        |
        # VCS version vectors. Per PHPCS, they are expected to
        # follow the form of the VCS name, followed by ":", followed
        # by the version vector itself.
        # By convention, popular VCSes like CVS, SVN and GIT use "$"
        # around the actual version vector.
        [^\s\:]+\:\s*\$[^\$]+\$
    )';
    /** @var string|null The version vector. */
    private ?string $version = null;
    public function __construct(?string $version = null, ?Description $description = null)
    {
        Assert::nullOrNotEmpty($version);
        $this->version = $version;
        $this->description = $description;
    }
    public static function create(?string $body, ?DescriptionFactory $descriptionFactory = null, ?TypeContext $context = null): ?self
    {
        if ($body === null || $body === '') {
            return new static();
        }
        $matches = [];
        if (!preg_match('/^(' . self::REGEX_VECTOR . ')\s*(.+)?$/sux', $body, $matches)) {
            return null;
        }
        Assert::notNull($descriptionFactory);
        return new static($matches[1], $descriptionFactory->create($matches[2] ?? '', $context));
    }
    /**
     * Gets the version section of the tag.
     */
    public function getVersion(): ?string
    {
        return $this->version;
    }
    /**
     * Returns a string representation for this tag.
     */
    public function __toString(): string
    {
        if ($this->description !== null) {
            $description = $this->description->render();
        } else {
            $description = '';
        }
        $version = (string) $this->version;
        return $version . ($description !== '' ? ($version !== '' ? ' ' : '') . $description : '');
    }
}
<?php

declare (strict_types=1);
/**
 * This file is part of phpDocumentor.
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @link      http://phpdoc.org
 */
namespace _ContaoManager\phpDocumentor\Reflection\DocBlock\Tags;

use _ContaoManager\Doctrine\Deprecations\Deprecation;
use _ContaoManager\phpDocumentor\Reflection\DocBlock\Description;
use _ContaoManager\phpDocumentor\Reflection\DocBlock\DescriptionFactory;
use _ContaoManager\phpDocumentor\Reflection\Type;
use _ContaoManager\phpDocumentor\Reflection\TypeResolver;
use _ContaoManager\phpDocumentor\Reflection\Types\Context as TypeContext;
use _ContaoManager\phpDocumentor\Reflection\Utils;
use _ContaoManager\Webmozart\Assert\Assert;
use function array_shift;
use function array_unshift;
use function implode;
use function strpos;
use function substr;
use const PREG_SPLIT_DELIM_CAPTURE;
/**
 * Reflection class for a {@}property-write tag in a Docblock.
 */
final class PropertyWrite extends TagWithType implements Factory\StaticMethod
{
    protected string $variableName;
    public function __construct(?string $variableName, ?Type $type = null, ?Description $description = null)
    {
        Assert::string($variableName);
        $this->name = 'property-write';
        $this->variableName = $variableName;
        $this->type = $type;
        $this->description = $description;
    }
    /**
     * @deprecated Create using static factory is deprecated,
     *  this method should not be called directly by library consumers
     */
    public static function create(string $body, ?TypeResolver $typeResolver = null, ?DescriptionFactory $descriptionFactory = null, ?TypeContext $context = null): self
    {
        Deprecation::triggerIfCalledFromOutside('phpdocumentor/reflection-docblock', 'https://github.com/phpDocumentor/ReflectionDocBlock/issues/361', 'Create using static factory is deprecated, this method should not be called directly
             by library consumers');
        Assert::stringNotEmpty($body);
        Assert::notNull($typeResolver);
        Assert::notNull($descriptionFactory);
        [$firstPart, $body] = self::extractTypeFromBody($body);
        $type = null;
        $parts = Utils::pregSplit('/(\s+)/Su', $body, 2, PREG_SPLIT_DELIM_CAPTURE);
        $variableName = '';
        // if the first item that is encountered is not a variable; it is a type
        if ($firstPart && $firstPart[0] !== '$') {
            $type = $typeResolver->resolve($firstPart, $context);
        } else {
            // first part is not a type; we should prepend it to the parts array for further processing
            array_unshift($parts, $firstPart);
        }
        // if the next item starts with a $ it must be the variable name
        if (isset($parts[0]) && strpos($parts[0], '$') === 0) {
            $variableName = array_shift($parts);
            if ($type) {
                array_shift($parts);
            }
            Assert::notNull($variableName);
            $variableName = substr($variableName, 1);
        }
        $description = $descriptionFactory->create(implode('', $parts), $context);
        return new static($variableName, $type, $description);
    }
    /**
     * Returns the variable's name.
     */
    public function getVariableName(): ?string
    {
        return $this->variableName;
    }
    /**
     * Returns a string representation for this tag.
     */
    public function __toString(): string
    {
        if ($this->description) {
            $description = $this->description->render();
        } else {
            $description = '';
        }
        if ($this->variableName) {
            $variableName = '$' . $this->variableName;
        } else {
            $variableName = '';
        }
        $type = (string) $this->type;
        return $type . ($variableName !== '' ? ($type !== '' ? ' ' : '') . $variableName : '') . ($description !== '' ? ($type !== '' || $variableName !== '' ? ' ' : '') . $description : '');
    }
}
<?php

/**
 * This file is part of phpDocumentor.
 *
 *  For the full copyright and license information, please view the LICENSE
 *  file that was distributed with this source code.
 *
 *  @link      http://phpdoc.org
 */
declare (strict_types=1);
namespace _ContaoManager\phpDocumentor\Reflection\DocBlock\Tags;

use _ContaoManager\phpDocumentor\Reflection\DocBlock\Tags\Factory\MethodParameterFactory;
use _ContaoManager\phpDocumentor\Reflection\Type;
final class MethodParameter
{
    private Type $type;
    private bool $isReference;
    private bool $isVariadic;
    private string $name;
    /** @var mixed */
    private $defaultValue;
    public const NO_DEFAULT_VALUE = '__NO_VALUE__';
    /**
     * @param mixed $defaultValue
     */
    public function __construct(string $name, Type $type, bool $isReference = \false, bool $isVariadic = \false, $defaultValue = self::NO_DEFAULT_VALUE)
    {
        $this->type = $type;
        $this->isReference = $isReference;
        $this->isVariadic = $isVariadic;
        $this->name = $name;
        $this->defaultValue = $defaultValue;
    }
    public function getName(): string
    {
        return $this->name;
    }
    public function getType(): Type
    {
        return $this->type;
    }
    public function isReference(): bool
    {
        return $this->isReference;
    }
    public function isVariadic(): bool
    {
        return $this->isVariadic;
    }
    public function getDefaultValue(): ?string
    {
        if ($this->defaultValue === self::NO_DEFAULT_VALUE) {
            return null;
        }
        return (new MethodParameterFactory())->format($this->defaultValue);
    }
    public function __toString(): string
    {
        return $this->getType() . ' ' . ($this->isReference() ? '&' : '') . ($this->isVariadic() ? '...' : '') . '$' . $this->getName() . ($this->defaultValue !== self::NO_DEFAULT_VALUE ? (new MethodParameterFactory())->format($this->defaultValue) : '');
    }
}
<?php

declare (strict_types=1);
/**
 * This file is part of phpDocumentor.
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @link http://phpdoc.org
 */
namespace _ContaoManager\phpDocumentor\Reflection\DocBlock\Tags;

use _ContaoManager\phpDocumentor\Reflection\DocBlock\Description;
use _ContaoManager\phpDocumentor\Reflection\DocBlock\DescriptionFactory;
use _ContaoManager\phpDocumentor\Reflection\Types\Context as TypeContext;
use _ContaoManager\phpDocumentor\Reflection\Utils;
use _ContaoManager\Webmozart\Assert\Assert;
/**
 * Reflection class for a {@}link tag in a Docblock.
 */
final class Link extends BaseTag implements Factory\StaticMethod
{
    protected string $name = 'link';
    private string $link;
    /**
     * Initializes a link to a URL.
     */
    public function __construct(string $link, ?Description $description = null)
    {
        $this->link = $link;
        $this->description = $description;
    }
    public static function create(string $body, ?DescriptionFactory $descriptionFactory = null, ?TypeContext $context = null): self
    {
        Assert::notNull($descriptionFactory);
        $parts = Utils::pregSplit('/\s+/Su', $body, 2);
        $description = isset($parts[1]) ? $descriptionFactory->create($parts[1], $context) : null;
        return new static($parts[0], $description);
    }
    /**
     * Gets the link
     */
    public function getLink(): string
    {
        return $this->link;
    }
    /**
     * Returns a string representation for this tag.
     */
    public function __toString(): string
    {
        if ($this->description) {
            $description = $this->description->render();
        } else {
            $description = '';
        }
        $link = $this->link;
        return $link . ($description !== '' ? ($link !== '' ? ' ' : '') . $description : '');
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\phpDocumentor\Reflection\DocBlock\Tags;

use Closure;
use Exception;
use _ContaoManager\phpDocumentor\Reflection\DocBlock\Tag;
use ReflectionClass;
use ReflectionException;
use ReflectionFunction;
use Throwable;
use function array_map;
use function get_class;
use function get_resource_type;
use function is_array;
use function is_object;
use function is_resource;
use function sprintf;
use const PHP_VERSION_ID;
/**
 * This class represents an exception during the tag creation
 *
 * Since the internals of the library are relaying on the correct syntax of a docblock
 * we cannot simply throw exceptions at all time because the exceptions will break the creation of a
 * docklock. Just silently ignore the exceptions is not an option because the user as an issue to fix.
 *
 * This tag holds that error information until a using application is able to display it. The object will just behave
 * like any normal tag. So the normal application flow will not break.
 */
final class InvalidTag implements Tag
{
    private string $name;
    private string $body;
    private ?Throwable $throwable = null;
    private function __construct(string $name, string $body)
    {
        $this->name = $name;
        $this->body = $body;
    }
    public function getException(): ?Throwable
    {
        return $this->throwable;
    }
    public function getName(): string
    {
        return $this->name;
    }
    public static function create(string $body, string $name = ''): self
    {
        return new self($name, $body);
    }
    public function withError(Throwable $exception): self
    {
        $this->flattenExceptionBacktrace($exception);
        $tag = new self($this->name, $this->body);
        $tag->throwable = $exception;
        return $tag;
    }
    /**
     * Removes all complex types from backtrace
     *
     * Not all objects are serializable. So we need to remove them from the
     * stored exception to be sure that we do not break existing library usage.
     */
    private function flattenExceptionBacktrace(Throwable $exception): void
    {
        $traceProperty = (new ReflectionClass(Exception::class))->getProperty('trace');
        if (PHP_VERSION_ID < 80100) {
            $traceProperty->setAccessible(\true);
        }
        do {
            $trace = $exception->getTrace();
            if (isset($trace[0]['args'])) {
                $trace = array_map(function (array $call): array {
                    $call['args'] = array_map([$this, 'flattenArguments'], $call['args'] ?? []);
                    return $call;
                }, $trace);
            }
            $traceProperty->setValue($exception, $trace);
            $exception = $exception->getPrevious();
        } while ($exception !== null);
        if (PHP_VERSION_ID >= 80100) {
            return;
        }
        $traceProperty->setAccessible(\false);
    }
    /**
     * @param mixed $value
     *
     * @return mixed
     *
     * @throws ReflectionException
     */
    private function flattenArguments($value)
    {
        if ($value instanceof Closure) {
            $closureReflection = new ReflectionFunction($value);
            $value = sprintf('(Closure at %s:%s)', $closureReflection->getFileName(), $closureReflection->getStartLine());
        } elseif (is_object($value)) {
            $value = sprintf('object(%s)', get_class($value));
        } elseif (is_resource($value)) {
            $value = sprintf('resource(%s)', get_resource_type($value));
        } elseif (is_array($value)) {
            $value = array_map([$this, 'flattenArguments'], $value);
        }
        return $value;
    }
    public function render(?Formatter $formatter = null): string
    {
        if ($formatter === null) {
            $formatter = new Formatter\PassthroughFormatter();
        }
        return $formatter->format($this);
    }
    public function __toString(): string
    {
        return $this->body;
    }
}
<?php

declare (strict_types=1);
/**
 * This file is part of phpDocumentor.
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @link http://phpdoc.org
 */
namespace _ContaoManager\phpDocumentor\Reflection\DocBlock\Tags;

use _ContaoManager\phpDocumentor\Reflection\DocBlock;
use _ContaoManager\phpDocumentor\Reflection\DocBlock\Description;
/**
 * Parses a tag definition for a DocBlock.
 */
abstract class BaseTag implements DocBlock\Tag
{
    /** @var string Name of the tag */
    protected string $name = '';
    /** @var Description|null Description of the tag. */
    protected ?Description $description = null;
    /**
     * Gets the name of this tag.
     *
     * @return string The name of this tag.
     */
    public function getName(): string
    {
        return $this->name;
    }
    public function getDescription(): ?Description
    {
        return $this->description;
    }
    public function render(?Formatter $formatter = null): string
    {
        if ($formatter === null) {
            $formatter = new Formatter\PassthroughFormatter();
        }
        return $formatter->format($this);
    }
}
<?php

declare (strict_types=1);
/**
 * This file is part of phpDocumentor.
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @link      http://phpdoc.org
 */
namespace _ContaoManager\phpDocumentor\Reflection\DocBlock\Tags;

use _ContaoManager\Doctrine\Deprecations\Deprecation;
use _ContaoManager\phpDocumentor\Reflection\DocBlock\Description;
use _ContaoManager\phpDocumentor\Reflection\DocBlock\DescriptionFactory;
use _ContaoManager\phpDocumentor\Reflection\Type;
use _ContaoManager\phpDocumentor\Reflection\TypeResolver;
use _ContaoManager\phpDocumentor\Reflection\Types\Context as TypeContext;
use _ContaoManager\phpDocumentor\Reflection\Utils;
use _ContaoManager\Webmozart\Assert\Assert;
use function array_shift;
use function array_unshift;
use function implode;
use function strpos;
use function substr;
use const PREG_SPLIT_DELIM_CAPTURE;
/**
 * Reflection class for a {@}var tag in a Docblock.
 */
final class Var_ extends TagWithType implements Factory\StaticMethod
{
    protected ?string $variableName = '';
    public function __construct(?string $variableName, ?Type $type = null, ?Description $description = null)
    {
        Assert::string($variableName);
        $this->name = 'var';
        $this->variableName = $variableName;
        $this->type = $type;
        $this->description = $description;
    }
    /**
     * @deprecated Create using static factory is deprecated,
     *  this method should not be called directly by library consumers
     */
    public static function create(string $body, ?TypeResolver $typeResolver = null, ?DescriptionFactory $descriptionFactory = null, ?TypeContext $context = null): self
    {
        Deprecation::triggerIfCalledFromOutside('phpdocumentor/reflection-docblock', 'https://github.com/phpDocumentor/ReflectionDocBlock/issues/361', 'Create using static factory is deprecated, this method should not be called directly
             by library consumers');
        Assert::stringNotEmpty($body);
        Assert::notNull($typeResolver);
        Assert::notNull($descriptionFactory);
        [$firstPart, $body] = self::extractTypeFromBody($body);
        $parts = Utils::pregSplit('/(\s+)/Su', $body, 2, PREG_SPLIT_DELIM_CAPTURE);
        $type = null;
        $variableName = '';
        // if the first item that is encountered is not a variable; it is a type
        if ($firstPart && $firstPart[0] !== '$') {
            $type = $typeResolver->resolve($firstPart, $context);
        } else {
            // first part is not a type; we should prepend it to the parts array for further processing
            array_unshift($parts, $firstPart);
        }
        // if the next item starts with a $ it must be the variable name
        if (isset($parts[0]) && strpos($parts[0], '$') === 0) {
            $variableName = array_shift($parts);
            if ($type) {
                array_shift($parts);
            }
            Assert::notNull($variableName);
            $variableName = substr($variableName, 1);
        }
        $description = $descriptionFactory->create(implode('', $parts), $context);
        return new static($variableName, $type, $description);
    }
    /**
     * Returns the variable's name.
     */
    public function getVariableName(): ?string
    {
        return $this->variableName;
    }
    /**
     * Returns a string representation for this tag.
     */
    public function __toString(): string
    {
        if ($this->description !== null) {
            $description = $this->description->render();
        } else {
            $description = '';
        }
        if ($this->variableName !== null && $this->variableName !== '') {
            $variableName = '$' . $this->variableName;
        } else {
            $variableName = '';
        }
        $type = (string) $this->type;
        return $type . ($variableName !== '' ? ($type !== '' ? ' ' : '') . $variableName : '') . ($description !== '' ? ($type !== '' || $variableName !== '' ? ' ' : '') . $description : '');
    }
}
<?php

declare (strict_types=1);
/**
 * This file is part of phpDocumentor.
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @link      http://phpdoc.org
 */
namespace _ContaoManager\phpDocumentor\Reflection\DocBlock\Tags;

use _ContaoManager\Doctrine\Deprecations\Deprecation;
use _ContaoManager\phpDocumentor\Reflection\DocBlock\Description;
use _ContaoManager\phpDocumentor\Reflection\DocBlock\DescriptionFactory;
use _ContaoManager\phpDocumentor\Reflection\Type;
use _ContaoManager\phpDocumentor\Reflection\TypeResolver;
use _ContaoManager\phpDocumentor\Reflection\Types\Context as TypeContext;
use _ContaoManager\phpDocumentor\Reflection\Utils;
use _ContaoManager\Webmozart\Assert\Assert;
use function array_shift;
use function array_unshift;
use function implode;
use function strpos;
use function substr;
use const PREG_SPLIT_DELIM_CAPTURE;
/**
 * Reflection class for the {@}param tag in a Docblock.
 */
final class Param extends TagWithType implements Factory\StaticMethod
{
    private ?string $variableName = null;
    /** @var bool determines whether this is a variadic argument */
    private bool $isVariadic;
    /** @var bool determines whether this is passed by reference */
    private bool $isReference;
    public function __construct(?string $variableName, ?Type $type = null, bool $isVariadic = \false, ?Description $description = null, bool $isReference = \false)
    {
        $this->name = 'param';
        $this->variableName = $variableName;
        $this->type = $type;
        $this->isVariadic = $isVariadic;
        $this->description = $description;
        $this->isReference = $isReference;
    }
    /**
     * @deprecated Create using static factory is deprecated,
     *  this method should not be called directly by library consumers
     */
    public static function create(string $body, ?TypeResolver $typeResolver = null, ?DescriptionFactory $descriptionFactory = null, ?TypeContext $context = null): self
    {
        Deprecation::triggerIfCalledFromOutside('phpdocumentor/reflection-docblock', 'https://github.com/phpDocumentor/ReflectionDocBlock/issues/361', 'Create using static factory is deprecated, this method should not be called directly
             by library consumers');
        Assert::stringNotEmpty($body);
        Assert::notNull($typeResolver);
        Assert::notNull($descriptionFactory);
        [$firstPart, $body] = self::extractTypeFromBody($body);
        $type = null;
        $parts = Utils::pregSplit('/(\s+)/Su', $body, 2, PREG_SPLIT_DELIM_CAPTURE);
        $variableName = '';
        $isVariadic = \false;
        $isReference = \false;
        // if the first item that is encountered is not a variable; it is a type
        if ($firstPart && !self::strStartsWithVariable($firstPart)) {
            $type = $typeResolver->resolve($firstPart, $context);
        } else {
            // first part is not a type; we should prepend it to the parts array for further processing
            array_unshift($parts, $firstPart);
        }
        // if the next item starts with a $ or ...$ or &$ or &...$ it must be the variable name
        if (isset($parts[0]) && self::strStartsWithVariable($parts[0])) {
            $variableName = array_shift($parts);
            if ($type) {
                array_shift($parts);
            }
            Assert::notNull($variableName);
            if (strpos($variableName, '$') === 0) {
                $variableName = substr($variableName, 1);
            } elseif (strpos($variableName, '&$') === 0) {
                $isReference = \true;
                $variableName = substr($variableName, 2);
            } elseif (strpos($variableName, '...$') === 0) {
                $isVariadic = \true;
                $variableName = substr($variableName, 4);
            } elseif (strpos($variableName, '&...$') === 0) {
                $isVariadic = \true;
                $isReference = \true;
                $variableName = substr($variableName, 5);
            }
        }
        $description = $descriptionFactory->create(implode('', $parts), $context);
        return new static($variableName, $type, $isVariadic, $description, $isReference);
    }
    /**
     * Returns the variable's name.
     */
    public function getVariableName(): ?string
    {
        return $this->variableName;
    }
    /**
     * Returns whether this tag is variadic.
     */
    public function isVariadic(): bool
    {
        return $this->isVariadic;
    }
    /**
     * Returns whether this tag is passed by reference.
     */
    public function isReference(): bool
    {
        return $this->isReference;
    }
    /**
     * Returns a string representation for this tag.
     */
    public function __toString(): string
    {
        if ($this->description) {
            $description = $this->description->render();
        } else {
            $description = '';
        }
        $variableName = '';
        if ($this->variableName !== null && $this->variableName !== '') {
            $variableName .= ($this->isReference ? '&' : '') . ($this->isVariadic ? '...' : '');
            $variableName .= '$' . $this->variableName;
        }
        $type = (string) $this->type;
        return $type . ($variableName !== '' ? ($type !== '' ? ' ' : '') . $variableName : '') . ($description !== '' ? ($type !== '' || $variableName !== '' ? ' ' : '') . $description : '');
    }
    private static function strStartsWithVariable(string $str): bool
    {
        return strpos($str, '$') === 0 || strpos($str, '...$') === 0 || strpos($str, '&$') === 0 || strpos($str, '&...$') === 0;
    }
}
<?php

declare (strict_types=1);
/**
 * This file is part of phpDocumentor.
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @link      http://phpdoc.org
 */
namespace _ContaoManager\phpDocumentor\Reflection\DocBlock\Tags;

use _ContaoManager\phpDocumentor\Reflection\DocBlock\Description;
use _ContaoManager\phpDocumentor\Reflection\DocBlock\DescriptionFactory;
use _ContaoManager\phpDocumentor\Reflection\Type;
use _ContaoManager\phpDocumentor\Reflection\TypeResolver;
use _ContaoManager\phpDocumentor\Reflection\Types\Context as TypeContext;
use _ContaoManager\Webmozart\Assert\Assert;
/**
 * Reflection class for a {@}mixin tag in a Docblock.
 */
final class Mixin extends TagWithType implements Factory\StaticMethod
{
    public function __construct(Type $type, ?Description $description = null)
    {
        $this->name = 'mixin';
        $this->type = $type;
        $this->description = $description;
    }
    public static function create(string $body, ?TypeResolver $typeResolver = null, ?DescriptionFactory $descriptionFactory = null, ?TypeContext $context = null): self
    {
        Assert::notNull($typeResolver);
        Assert::notNull($descriptionFactory);
        [$type, $description] = self::extractTypeFromBody($body);
        $type = $typeResolver->resolve($type, $context);
        $description = $descriptionFactory->create($description, $context);
        return new static($type, $description);
    }
}
<?php

declare (strict_types=1);
/**
 * This file is part of phpDocumentor.
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @link      http://phpdoc.org
 */
namespace _ContaoManager\phpDocumentor\Reflection\DocBlock\Tags;

use _ContaoManager\phpDocumentor\Reflection\DocBlock\Description;
use _ContaoManager\phpDocumentor\Reflection\DocBlock\DescriptionFactory;
use _ContaoManager\phpDocumentor\Reflection\Type;
use _ContaoManager\phpDocumentor\Reflection\TypeResolver;
use _ContaoManager\phpDocumentor\Reflection\Types\Context as TypeContext;
use _ContaoManager\Webmozart\Assert\Assert;
/**
 * Reflection class for a {@}template-covariant tag in a Docblock.
 */
final class TemplateCovariant extends TagWithType implements Factory\StaticMethod
{
    public function __construct(Type $type, ?Description $description = null)
    {
        $this->name = 'template-covariant';
        $this->type = $type;
        $this->description = $description;
    }
    public static function create(string $body, ?TypeResolver $typeResolver = null, ?DescriptionFactory $descriptionFactory = null, ?TypeContext $context = null): self
    {
        Assert::notNull($typeResolver);
        Assert::notNull($descriptionFactory);
        [$type, $description] = self::extractTypeFromBody($body);
        $type = $typeResolver->resolve($type, $context);
        $description = $descriptionFactory->create($description, $context);
        return new static($type, $description);
    }
}
<?php

declare (strict_types=1);
/**
 * This file is part of phpDocumentor.
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @link http://phpdoc.org
 */
namespace _ContaoManager\phpDocumentor\Reflection\DocBlock\Tags;

use InvalidArgumentException;
use _ContaoManager\phpDocumentor\Reflection\DocBlock\Description;
use _ContaoManager\phpDocumentor\Reflection\DocBlock\DescriptionFactory;
use _ContaoManager\phpDocumentor\Reflection\Type;
use _ContaoManager\phpDocumentor\Reflection\TypeResolver;
use _ContaoManager\phpDocumentor\Reflection\Types\Context as TypeContext;
use _ContaoManager\phpDocumentor\Reflection\Types\Mixed_;
use _ContaoManager\phpDocumentor\Reflection\Types\Void_;
use _ContaoManager\Webmozart\Assert\Assert;
use function array_keys;
use function array_map;
use function explode;
use function implode;
use function is_string;
use function preg_match;
use function sort;
use function strpos;
use function substr;
use function trigger_error;
use function trim;
use function var_export;
use const E_USER_DEPRECATED;
/**
 * Reflection class for an {@}method in a Docblock.
 */
final class Method extends BaseTag implements Factory\StaticMethod
{
    protected string $name = 'method';
    private string $methodName;
    private bool $isStatic;
    private Type $returnType;
    private bool $returnsReference;
    /** @var MethodParameter[] */
    private array $parameters;
    /**
     * @param array<int, array<string, Type|string>> $arguments
     * @param MethodParameter[] $parameters
     * @phpstan-param array<int, array{name: string, type: Type}|string> $arguments
     */
    public function __construct(string $methodName, array $arguments = [], ?Type $returnType = null, bool $static = \false, ?Description $description = null, bool $returnsReference = \false, ?array $parameters = null)
    {
        Assert::stringNotEmpty($methodName);
        if ($returnType === null) {
            $returnType = new Void_();
        }
        $arguments = $this->filterArguments($arguments);
        $this->methodName = $methodName;
        $this->returnType = $returnType;
        $this->isStatic = $static;
        $this->description = $description;
        $this->returnsReference = $returnsReference;
        $this->parameters = $parameters ?? $this->fromLegacyArguments($arguments);
    }
    /**
     * @deprecated Create using static factory is deprecated,
     *  this method should not be called directly by library consumers
     */
    public static function create(string $body, ?TypeResolver $typeResolver = null, ?DescriptionFactory $descriptionFactory = null, ?TypeContext $context = null): ?self
    {
        trigger_error('Create using static factory is deprecated, this method should not be called directly
             by library consumers', E_USER_DEPRECATED);
        Assert::stringNotEmpty($body);
        Assert::notNull($typeResolver);
        Assert::notNull($descriptionFactory);
        // 1. none or more whitespace
        // 2. optionally the keyword "static" followed by whitespace
        // 3. optionally a word with underscores followed by whitespace : as
        //    type for the return value
        // 4. optionally an ampersand followed or not by whitespace : as
        //    a reference
        // 5. then optionally a word with underscores followed by () and
        //    whitespace : as method name as used by phpDocumentor
        // 6. then a word with underscores, followed by ( and any character
        //    until a ) and whitespace : as method name with signature
        // 7. any remaining text : as description
        if (!preg_match('/^
                # Static keyword
                # Declares a static method ONLY if type is also present
                (?:
                    (static)
                    \s+
                )?
                # Return type
                (?:
                    (
                        (?:[\w\|_\\\\]*\$this[\w\|_\\\\]*)
                        |
                        (?:
                            (?:[\w\|_\\\\]+)
                            # array notation
                            (?:\[\])*
                        )*+
                    )
                    \s+
                )?
                # Returns reference
                (?:
                    (&)
                    \s*
                )?
                # Method name
                ([\w_]+)
                # Arguments
                (?:
                    \(([^\)]*)\)
                )?
                \s*
                # Description
                (.*)
            $/sux', $body, $matches)) {
            return null;
        }
        [, $static, $returnType, $returnsReference, $methodName, $argumentLines, $description] = $matches;
        $static = $static === 'static';
        if ($returnType === '') {
            $returnType = 'void';
        }
        $returnsReference = $returnsReference === '&';
        $returnType = $typeResolver->resolve($returnType, $context);
        $description = $descriptionFactory->create($description, $context);
        /** @phpstan-var array<int, array{name: string, type: Type}> $arguments */
        $arguments = [];
        if ($argumentLines !== '') {
            $argumentsExploded = explode(',', $argumentLines);
            foreach ($argumentsExploded as $argument) {
                $argument = explode(' ', self::stripRestArg(trim($argument)), 2);
                if (strpos($argument[0], '$') === 0) {
                    $argumentName = substr($argument[0], 1);
                    $argumentType = new Mixed_();
                } else {
                    $argumentType = $typeResolver->resolve($argument[0], $context);
                    $argumentName = '';
                    if (isset($argument[1])) {
                        $argument[1] = self::stripRestArg($argument[1]);
                        $argumentName = substr($argument[1], 1);
                    }
                }
                $arguments[] = ['name' => $argumentName, 'type' => $argumentType];
            }
        }
        return new static($methodName, $arguments, $returnType, $static, $description, $returnsReference);
    }
    /**
     * Retrieves the method name.
     */
    public function getMethodName(): string
    {
        return $this->methodName;
    }
    /**
     * @deprecated Method deprecated, use {@see self::getParameters()}
     *
     * @return array<int, array<string, Type|string>>
     * @phpstan-return array<int, array{name: string, type: Type}>
     */
    public function getArguments(): array
    {
        trigger_error('Method deprecated, use ::getParameters()', E_USER_DEPRECATED);
        return array_map(static function (MethodParameter $methodParameter) {
            return ['name' => $methodParameter->getName(), 'type' => $methodParameter->getType()];
        }, $this->parameters);
    }
    /** @return MethodParameter[] */
    public function getParameters(): array
    {
        return $this->parameters;
    }
    /**
     * Checks whether the method tag describes a static method or not.
     *
     * @return bool TRUE if the method declaration is for a static method, FALSE otherwise.
     */
    public function isStatic(): bool
    {
        return $this->isStatic;
    }
    public function getReturnType(): Type
    {
        return $this->returnType;
    }
    public function returnsReference(): bool
    {
        return $this->returnsReference;
    }
    public function __toString(): string
    {
        $arguments = [];
        foreach ($this->parameters as $parameter) {
            $arguments[] = (string) $parameter;
        }
        $argumentStr = '(' . implode(', ', $arguments) . ')';
        if ($this->description) {
            $description = $this->description->render();
        } else {
            $description = '';
        }
        $static = $this->isStatic ? 'static' : '';
        $returnType = (string) $this->returnType;
        $methodName = $this->methodName;
        $reference = $this->returnsReference ? '&' : '';
        return $static . ($returnType !== '' ? ($static !== '' ? ' ' : '') . $returnType : '') . ($methodName !== '' ? ($static !== '' || $returnType !== '' ? ' ' : '') . $reference . $methodName : '') . $argumentStr . ($description !== '' ? ' ' . $description : '');
    }
    /**
     * @param mixed[][]|string[] $arguments
     * @phpstan-param array<int, array{name: string, type: Type}|string> $arguments
     *
     * @return mixed[][]
     * @phpstan-return array<int, array{name: string, type: Type}>
     */
    private function filterArguments(array $arguments = []): array
    {
        $result = [];
        foreach ($arguments as $argument) {
            if (is_string($argument)) {
                $argument = ['name' => $argument];
            }
            if (!isset($argument['type'])) {
                $argument['type'] = new Mixed_();
            }
            $keys = array_keys($argument);
            sort($keys);
            if ($keys !== ['name', 'type']) {
                throw new InvalidArgumentException('Arguments can only have the "name" and "type" fields, found: ' . var_export($keys, \true));
            }
            $result[] = $argument;
        }
        return $result;
    }
    private static function stripRestArg(string $argument): string
    {
        if (strpos($argument, '...') === 0) {
            $argument = trim(substr($argument, 3));
        }
        return $argument;
    }
    /**
     * @param array{name: string, type: Type} $arguments
     * @phpstan-param array<int, array{name: string, type: Type}> $arguments
     *
     * @return MethodParameter[]
     */
    private function fromLegacyArguments(array $arguments): array
    {
        trigger_error('Create method parameters via legacy format is deprecated add parameters via the constructor', E_USER_DEPRECATED);
        return array_map(static function ($arg) {
            return new MethodParameter($arg['name'], $arg['type']);
        }, $arguments);
    }
}
<?php

declare (strict_types=1);
/**
 * This file is part of phpDocumentor.
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @link      http://phpdoc.org
 */
namespace _ContaoManager\phpDocumentor\Reflection\DocBlock\Tags;

use _ContaoManager\phpDocumentor\Reflection\DocBlock\Tag;
interface Formatter
{
    /**
     * Formats a tag into a string representation according to a specific format, such as Markdown.
     */
    public function format(Tag $tag): string;
}
<?php

declare (strict_types=1);
/**
 * This file is part of phpDocumentor.
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @link http://phpdoc.org
 */
namespace _ContaoManager\phpDocumentor\Reflection\DocBlock\Tags;

use _ContaoManager\phpDocumentor\Reflection\DocBlock\Description;
use _ContaoManager\phpDocumentor\Reflection\DocBlock\DescriptionFactory;
use _ContaoManager\phpDocumentor\Reflection\Fqsen;
use _ContaoManager\phpDocumentor\Reflection\FqsenResolver;
use _ContaoManager\phpDocumentor\Reflection\Types\Context as TypeContext;
use _ContaoManager\phpDocumentor\Reflection\Utils;
use _ContaoManager\Webmozart\Assert\Assert;
use function array_key_exists;
use function explode;
/**
 * Reflection class for a {@}uses tag in a Docblock.
 */
final class Uses extends BaseTag implements Factory\StaticMethod
{
    protected string $name = 'uses';
    protected Fqsen $refers;
    /**
     * Initializes this tag.
     */
    public function __construct(Fqsen $refers, ?Description $description = null)
    {
        $this->refers = $refers;
        $this->description = $description;
    }
    public static function create(string $body, ?FqsenResolver $resolver = null, ?DescriptionFactory $descriptionFactory = null, ?TypeContext $context = null): self
    {
        Assert::notNull($resolver);
        Assert::notNull($descriptionFactory);
        $parts = Utils::pregSplit('/\s+/Su', $body, 2);
        return new static(self::resolveFqsen($parts[0], $resolver, $context), $descriptionFactory->create($parts[1] ?? '', $context));
    }
    private static function resolveFqsen(string $parts, ?FqsenResolver $fqsenResolver, ?TypeContext $context): Fqsen
    {
        Assert::notNull($fqsenResolver);
        $fqsenParts = explode('::', $parts);
        $resolved = $fqsenResolver->resolve($fqsenParts[0], $context);
        if (!array_key_exists(1, $fqsenParts)) {
            return $resolved;
        }
        return new Fqsen($resolved . '::' . $fqsenParts[1]);
    }
    /**
     * Returns the structural element this tag refers to.
     */
    public function getReference(): Fqsen
    {
        return $this->refers;
    }
    /**
     * Returns a string representation of this tag.
     */
    public function __toString(): string
    {
        if ($this->description) {
            $description = $this->description->render();
        } else {
            $description = '';
        }
        $refers = (string) $this->refers;
        return $refers . ($description !== '' ? ($refers !== '' ? ' ' : '') . $description : '');
    }
}
<?php

declare (strict_types=1);
/**
 * This file is part of phpDocumentor.
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @link      http://phpdoc.org
 */
namespace _ContaoManager\phpDocumentor\Reflection\DocBlock\Tags;

use _ContaoManager\Doctrine\Deprecations\Deprecation;
use _ContaoManager\phpDocumentor\Reflection\DocBlock\Description;
use _ContaoManager\phpDocumentor\Reflection\DocBlock\DescriptionFactory;
use _ContaoManager\phpDocumentor\Reflection\Type;
use _ContaoManager\phpDocumentor\Reflection\TypeResolver;
use _ContaoManager\phpDocumentor\Reflection\Types\Context as TypeContext;
use _ContaoManager\Webmozart\Assert\Assert;
/**
 * Reflection class for a {@}return tag in a Docblock.
 */
final class Return_ extends TagWithType implements Factory\StaticMethod
{
    public function __construct(Type $type, ?Description $description = null)
    {
        $this->name = 'return';
        $this->type = $type;
        $this->description = $description;
    }
    /**
     * @deprecated Create using static factory is deprecated,
     *  this method should not be called directly by library consumers
     */
    public static function create(string $body, ?TypeResolver $typeResolver = null, ?DescriptionFactory $descriptionFactory = null, ?TypeContext $context = null): self
    {
        Deprecation::triggerIfCalledFromOutside('phpdocumentor/reflection-docblock', 'https://github.com/phpDocumentor/ReflectionDocBlock/issues/361', 'Create using static factory is deprecated, this method should not be called directly
             by library consumers');
        Assert::notNull($typeResolver);
        Assert::notNull($descriptionFactory);
        [$type, $description] = self::extractTypeFromBody($body);
        $type = $typeResolver->resolve($type, $context);
        $description = $descriptionFactory->create($description, $context);
        return new static($type, $description);
    }
}
<?php

declare (strict_types=1);
/**
 * This file is part of phpDocumentor.
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @link      http://phpdoc.org
 */
namespace _ContaoManager\phpDocumentor\Reflection\DocBlock\Tags\Formatter;

use _ContaoManager\phpDocumentor\Reflection\DocBlock\Tag;
use _ContaoManager\phpDocumentor\Reflection\DocBlock\Tags\Formatter;
use function trim;
class PassthroughFormatter implements Formatter
{
    /**
     * Formats the given tag to return a simple plain text version.
     */
    public function format(Tag $tag): string
    {
        return trim('@' . $tag->getName() . ' ' . $tag);
    }
}
<?php

declare (strict_types=1);
/**
 * This file is part of phpDocumentor.
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @link      http://phpdoc.org
 */
namespace _ContaoManager\phpDocumentor\Reflection\DocBlock\Tags\Formatter;

use _ContaoManager\phpDocumentor\Reflection\DocBlock\Tag;
use _ContaoManager\phpDocumentor\Reflection\DocBlock\Tags\Formatter;
use function max;
use function str_repeat;
use function strlen;
class AlignFormatter implements Formatter
{
    /** @var int The maximum tag name length. */
    protected int $maxLen = 0;
    /**
     * @param Tag[] $tags All tags that should later be aligned with the formatter.
     */
    public function __construct(array $tags)
    {
        foreach ($tags as $tag) {
            $this->maxLen = max($this->maxLen, strlen($tag->getName()));
        }
    }
    /**
     * Formats the given tag to return a simple plain text version.
     */
    public function format(Tag $tag): string
    {
        return '@' . $tag->getName() . str_repeat(' ', $this->maxLen - strlen($tag->getName()) + 1) . $tag;
    }
}
<?php

declare (strict_types=1);
/**
 * This file is part of phpDocumentor.
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @link http://phpdoc.org
 */
namespace _ContaoManager\phpDocumentor\Reflection\DocBlock\Tags;

use _ContaoManager\phpDocumentor\Reflection\DocBlock\Description;
use _ContaoManager\phpDocumentor\Reflection\Type;
/**
 * Reflection class for a {@}template-implements tag in a Docblock.
 */
final class TemplateImplements extends Implements_
{
    public function __construct(Type $type, ?Description $description = null)
    {
        parent::__construct($type, $description);
        $this->name = 'template-implements';
    }
}
<?php

declare (strict_types=1);
/**
 * This file is part of phpDocumentor.
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @link      http://phpdoc.org
 */
namespace _ContaoManager\phpDocumentor\Reflection\DocBlock\Tags;

use _ContaoManager\Doctrine\Deprecations\Deprecation;
use _ContaoManager\phpDocumentor\Reflection\DocBlock\Description;
use _ContaoManager\phpDocumentor\Reflection\DocBlock\DescriptionFactory;
use _ContaoManager\phpDocumentor\Reflection\Type;
use _ContaoManager\phpDocumentor\Reflection\TypeResolver;
use _ContaoManager\phpDocumentor\Reflection\Types\Context as TypeContext;
use _ContaoManager\phpDocumentor\Reflection\Utils;
use _ContaoManager\Webmozart\Assert\Assert;
use function array_shift;
use function array_unshift;
use function implode;
use function strpos;
use function substr;
use const PREG_SPLIT_DELIM_CAPTURE;
/**
 * Reflection class for a {@}property-read tag in a Docblock.
 */
final class PropertyRead extends TagWithType implements Factory\StaticMethod
{
    protected ?string $variableName = null;
    public function __construct(?string $variableName, ?Type $type = null, ?Description $description = null)
    {
        Assert::string($variableName);
        $this->name = 'property-read';
        $this->variableName = $variableName;
        $this->type = $type;
        $this->description = $description;
    }
    /**
     * @deprecated Create using static factory is deprecated,
     *  this method should not be called directly by library consumers
     */
    public static function create(string $body, ?TypeResolver $typeResolver = null, ?DescriptionFactory $descriptionFactory = null, ?TypeContext $context = null): self
    {
        Deprecation::triggerIfCalledFromOutside('phpdocumentor/reflection-docblock', 'https://github.com/phpDocumentor/ReflectionDocBlock/issues/361', 'Create using static factory is deprecated, this method should not be called directly
             by library consumers');
        Assert::stringNotEmpty($body);
        Assert::notNull($typeResolver);
        Assert::notNull($descriptionFactory);
        [$firstPart, $body] = self::extractTypeFromBody($body);
        $type = null;
        $parts = Utils::pregSplit('/(\s+)/Su', $body, 2, PREG_SPLIT_DELIM_CAPTURE);
        $variableName = '';
        // if the first item that is encountered is not a variable; it is a type
        if ($firstPart && $firstPart[0] !== '$') {
            $type = $typeResolver->resolve($firstPart, $context);
        } else {
            // first part is not a type; we should prepend it to the parts array for further processing
            array_unshift($parts, $firstPart);
        }
        // if the next item starts with a $ it must be the variable name
        if (isset($parts[0]) && strpos($parts[0], '$') === 0) {
            $variableName = array_shift($parts);
            if ($type) {
                array_shift($parts);
            }
            Assert::notNull($variableName);
            $variableName = substr($variableName, 1);
        }
        $description = $descriptionFactory->create(implode('', $parts), $context);
        return new static($variableName, $type, $description);
    }
    /**
     * Returns the variable's name.
     */
    public function getVariableName(): ?string
    {
        return $this->variableName;
    }
    /**
     * Returns a string representation for this tag.
     */
    public function __toString(): string
    {
        if ($this->description !== null) {
            $description = $this->description->render();
        } else {
            $description = '';
        }
        if ($this->variableName !== null && $this->variableName !== '') {
            $variableName = '$' . $this->variableName;
        } else {
            $variableName = '';
        }
        $type = (string) $this->type;
        return $type . ($variableName !== '' ? ($type !== '' ? ' ' : '') . $variableName : '') . ($description !== '' ? ($type !== '' || $variableName !== '' ? ' ' : '') . $description : '');
    }
}
<?php

declare (strict_types=1);
/**
 * This file is part of phpDocumentor.
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @link      http://phpdoc.org
 */
namespace _ContaoManager\phpDocumentor\Reflection\DocBlock\Tags;

use _ContaoManager\Doctrine\Deprecations\Deprecation;
use _ContaoManager\phpDocumentor\Reflection\DocBlock\Description;
use _ContaoManager\phpDocumentor\Reflection\DocBlock\DescriptionFactory;
use _ContaoManager\phpDocumentor\Reflection\Type;
use _ContaoManager\phpDocumentor\Reflection\TypeResolver;
use _ContaoManager\phpDocumentor\Reflection\Types\Context as TypeContext;
use _ContaoManager\phpDocumentor\Reflection\Utils;
use _ContaoManager\Webmozart\Assert\Assert;
use function array_shift;
use function array_unshift;
use function implode;
use function strpos;
use function substr;
use const PREG_SPLIT_DELIM_CAPTURE;
/**
 * Reflection class for a {@}property tag in a Docblock.
 */
final class Property extends TagWithType implements Factory\StaticMethod
{
    protected ?string $variableName = null;
    public function __construct(?string $variableName, ?Type $type = null, ?Description $description = null)
    {
        Assert::string($variableName);
        $this->name = 'property';
        $this->variableName = $variableName;
        $this->type = $type;
        $this->description = $description;
    }
    /**
     * @deprecated Create using static factory is deprecated,
     *  this method should not be called directly by library consumers
     */
    public static function create(string $body, ?TypeResolver $typeResolver = null, ?DescriptionFactory $descriptionFactory = null, ?TypeContext $context = null): self
    {
        Deprecation::triggerIfCalledFromOutside('phpdocumentor/reflection-docblock', 'https://github.com/phpDocumentor/ReflectionDocBlock/issues/361', 'Create using static factory is deprecated, this method should not be called directly
             by library consumers');
        Assert::stringNotEmpty($body);
        Assert::notNull($typeResolver);
        Assert::notNull($descriptionFactory);
        [$firstPart, $body] = self::extractTypeFromBody($body);
        $type = null;
        $parts = Utils::pregSplit('/(\s+)/Su', $body, 2, PREG_SPLIT_DELIM_CAPTURE);
        $variableName = '';
        // if the first item that is encountered is not a variable; it is a type
        if ($firstPart && $firstPart[0] !== '$') {
            $type = $typeResolver->resolve($firstPart, $context);
        } else {
            // first part is not a type; we should prepend it to the parts array for further processing
            array_unshift($parts, $firstPart);
        }
        // if the next item starts with a $ it must be the variable name
        if (isset($parts[0]) && strpos($parts[0], '$') === 0) {
            $variableName = array_shift($parts);
            if ($type) {
                array_shift($parts);
            }
            Assert::notNull($variableName);
            $variableName = substr($variableName, 1);
        }
        $description = $descriptionFactory->create(implode('', $parts), $context);
        return new static($variableName, $type, $description);
    }
    /**
     * Returns the variable's name.
     */
    public function getVariableName(): ?string
    {
        return $this->variableName;
    }
    /**
     * Returns a string representation for this tag.
     */
    public function __toString(): string
    {
        if ($this->description !== null) {
            $description = $this->description->render();
        } else {
            $description = '';
        }
        if ($this->variableName !== null && $this->variableName !== '') {
            $variableName = '$' . $this->variableName;
        } else {
            $variableName = '';
        }
        $type = (string) $this->type;
        return $type . ($variableName !== '' ? ($type !== '' ? ' ' : '') . $variableName : '') . ($description !== '' ? ($type !== '' || $variableName !== '' ? ' ' : '') . $description : '');
    }
}
<?php

declare (strict_types=1);
/**
 * This file is part of phpDocumentor.
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @link http://phpdoc.org
 */
namespace _ContaoManager\phpDocumentor\Reflection\DocBlock\Tags;

use _ContaoManager\phpDocumentor\Reflection\DocBlock\Description;
use _ContaoManager\phpDocumentor\Reflection\DocBlock\DescriptionFactory;
use _ContaoManager\phpDocumentor\Reflection\Types\Context as TypeContext;
use _ContaoManager\Webmozart\Assert\Assert;
use function preg_match;
/**
 * Reflection class for a {@}version tag in a Docblock.
 */
final class Version extends BaseTag implements Factory\StaticMethod
{
    protected string $name = 'version';
    /**
     * PCRE regular expression matching a version vector.
     * Assumes the "x" modifier.
     */
    public const REGEX_VECTOR = '(?:
        # Normal release vectors.
        \d\S*
        |
        # VCS version vectors. Per PHPCS, they are expected to
        # follow the form of the VCS name, followed by ":", followed
        # by the version vector itself.
        # By convention, popular VCSes like CVS, SVN and GIT use "$"
        # around the actual version vector.
        [^\s\:]+\:\s*\$[^\$]+\$
    )';
    /** @var string|null The version vector. */
    private ?string $version = null;
    public function __construct(?string $version = null, ?Description $description = null)
    {
        Assert::nullOrStringNotEmpty($version);
        $this->version = $version;
        $this->description = $description;
    }
    public static function create(?string $body, ?DescriptionFactory $descriptionFactory = null, ?TypeContext $context = null): ?self
    {
        if ($body === null || $body === '') {
            return new static();
        }
        $matches = [];
        if (!preg_match('/^(' . self::REGEX_VECTOR . ')\s*(.+)?$/sux', $body, $matches)) {
            return null;
        }
        $description = null;
        if ($descriptionFactory !== null) {
            $description = $descriptionFactory->create($matches[2] ?? '', $context);
        }
        return new static($matches[1], $description);
    }
    /**
     * Gets the version section of the tag.
     */
    public function getVersion(): ?string
    {
        return $this->version;
    }
    /**
     * Returns a string representation for this tag.
     */
    public function __toString(): string
    {
        if ($this->description) {
            $description = $this->description->render();
        } else {
            $description = '';
        }
        $version = (string) $this->version;
        return $version . ($description !== '' ? ($version !== '' ? ' ' : '') . $description : '');
    }
}
<?php

declare (strict_types=1);
/**
 * This file is part of phpDocumentor.
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @link http://phpdoc.org
 */
namespace _ContaoManager\phpDocumentor\Reflection\DocBlock\Tags;

use _ContaoManager\phpDocumentor\Reflection\DocBlock\Description;
use _ContaoManager\phpDocumentor\Reflection\DocBlock\DescriptionFactory;
use _ContaoManager\phpDocumentor\Reflection\DocBlock\Tags\Reference\Fqsen as FqsenRef;
use _ContaoManager\phpDocumentor\Reflection\DocBlock\Tags\Reference\Reference;
use _ContaoManager\phpDocumentor\Reflection\DocBlock\Tags\Reference\Url;
use _ContaoManager\phpDocumentor\Reflection\Fqsen;
use _ContaoManager\phpDocumentor\Reflection\FqsenResolver;
use _ContaoManager\phpDocumentor\Reflection\Types\Context as TypeContext;
use _ContaoManager\phpDocumentor\Reflection\Utils;
use _ContaoManager\Webmozart\Assert\Assert;
use function array_key_exists;
use function explode;
use function preg_match;
/**
 * Reflection class for an {@}see tag in a Docblock.
 */
final class See extends BaseTag implements Factory\StaticMethod
{
    protected string $name = 'see';
    protected Reference $refers;
    /**
     * Initializes this tag.
     */
    public function __construct(Reference $refers, ?Description $description = null)
    {
        $this->refers = $refers;
        $this->description = $description;
    }
    public static function create(string $body, ?FqsenResolver $typeResolver = null, ?DescriptionFactory $descriptionFactory = null, ?TypeContext $context = null): self
    {
        Assert::notNull($descriptionFactory);
        $parts = Utils::pregSplit('/\s+/Su', $body, 2);
        $description = isset($parts[1]) ? $descriptionFactory->create($parts[1], $context) : null;
        // https://tools.ietf.org/html/rfc2396#section-3
        if (preg_match('#\w://\w#', $parts[0])) {
            return new static(new Url($parts[0]), $description);
        }
        return new static(new FqsenRef(self::resolveFqsen($parts[0], $typeResolver, $context)), $description);
    }
    private static function resolveFqsen(string $parts, ?FqsenResolver $fqsenResolver, ?TypeContext $context): Fqsen
    {
        Assert::notNull($fqsenResolver);
        $fqsenParts = explode('::', $parts);
        $resolved = $fqsenResolver->resolve($fqsenParts[0], $context);
        if (!array_key_exists(1, $fqsenParts)) {
            return $resolved;
        }
        return new Fqsen($resolved . '::' . $fqsenParts[1]);
    }
    /**
     * Returns the ref of this tag.
     */
    public function getReference(): Reference
    {
        return $this->refers;
    }
    /**
     * Returns a string representation of this tag.
     */
    public function __toString(): string
    {
        if ($this->description) {
            $description = $this->description->render();
        } else {
            $description = '';
        }
        $refers = (string) $this->refers;
        return $refers . ($description !== '' ? ($refers !== '' ? ' ' : '') . $description : '');
    }
}
<?php

declare (strict_types=1);
/**
 * This file is part of phpDocumentor.
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @link http://phpdoc.org
 */
namespace _ContaoManager\phpDocumentor\Reflection\DocBlock\Tags;

use _ContaoManager\Doctrine\Deprecations\Deprecation;
use _ContaoManager\phpDocumentor\Reflection\DocBlock\Description;
use _ContaoManager\phpDocumentor\Reflection\DocBlock\Tag;
use _ContaoManager\phpDocumentor\Reflection\Type;
/**
 * Reflection class for a {@}extends tag in a Docblock.
 */
class Extends_ extends TagWithType
{
    public function __construct(Type $type, ?Description $description = null)
    {
        $this->name = 'extends';
        $this->type = $type;
        $this->description = $description;
    }
    /**
     * @deprecated Create using static factory is deprecated,
     *  this method should not be called directly by library consumers
     */
    public static function create(string $body): ?Tag
    {
        Deprecation::trigger('phpdocumentor/reflection-docblock', 'https://github.com/phpDocumentor/ReflectionDocBlock/issues/361', 'Create using static factory is deprecated, this method should not be called directly
             by library consumers');
        return null;
    }
}
<?php

declare (strict_types=1);
/**
 * This file is part of phpDocumentor.
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @link      http://phpdoc.org
 */
namespace _ContaoManager\phpDocumentor\Reflection\DocBlock\Tags;

use InvalidArgumentException;
use _ContaoManager\phpDocumentor\Reflection\DocBlock\Description;
use _ContaoManager\phpDocumentor\Reflection\DocBlock\DescriptionFactory;
use _ContaoManager\phpDocumentor\Reflection\DocBlock\StandardTagFactory;
use _ContaoManager\phpDocumentor\Reflection\Types\Context as TypeContext;
use _ContaoManager\Webmozart\Assert\Assert;
use function preg_match;
/**
 * Parses a tag definition for a DocBlock.
 */
final class Generic extends BaseTag implements Factory\StaticMethod
{
    /**
     * Parses a tag and populates the member variables.
     *
     * @param string      $name        Name of the tag.
     * @param Description $description The contents of the given tag.
     */
    public function __construct(string $name, ?Description $description = null)
    {
        $this->validateTagName($name);
        $this->name = $name;
        $this->description = $description;
    }
    /**
     * Creates a new tag that represents any unknown tag type.
     *
     * @return static
     */
    public static function create(string $body, string $name = '', ?DescriptionFactory $descriptionFactory = null, ?TypeContext $context = null): self
    {
        Assert::stringNotEmpty($name);
        Assert::notNull($descriptionFactory);
        $description = $body !== '' ? $descriptionFactory->create($body, $context) : null;
        return new static($name, $description);
    }
    /**
     * Returns the tag as a serialized string
     */
    public function __toString(): string
    {
        if ($this->description) {
            $description = $this->description->render();
        } else {
            $description = '';
        }
        return $description;
    }
    /**
     * Validates if the tag name matches the expected format, otherwise throws an exception.
     */
    private function validateTagName(string $name): void
    {
        if (!preg_match('/^' . StandardTagFactory::REGEX_TAGNAME . '$/u', $name)) {
            throw new InvalidArgumentException('The tag name "' . $name . '" is not wellformed. Tags may only consist of letters, underscores, ' . 'hyphens and backslashes.');
        }
    }
}
<?php

declare (strict_types=1);
/**
 * This file is part of phpDocumentor.
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @link      http://phpdoc.org
 */
namespace _ContaoManager\phpDocumentor\Reflection\DocBlock\Tags;

use InvalidArgumentException;
use _ContaoManager\phpDocumentor\Reflection\Type;
use function in_array;
use function sprintf;
use function strlen;
use function substr;
use function trim;
abstract class TagWithType extends BaseTag
{
    /** @var ?Type */
    protected ?Type $type = null;
    /**
     * Returns the type section of the variable.
     */
    public function getType(): ?Type
    {
        return $this->type;
    }
    /**
     * @return string[]
     */
    protected static function extractTypeFromBody(string $body): array
    {
        $type = '';
        $nestingLevel = 0;
        for ($i = 0, $iMax = strlen($body); $i < $iMax; $i++) {
            $character = $body[$i];
            if ($nestingLevel === 0 && trim($character) === '') {
                break;
            }
            $type .= $character;
            if (in_array($character, ['<', '(', '[', '{'])) {
                $nestingLevel++;
                continue;
            }
            if (in_array($character, ['>', ')', ']', '}'])) {
                $nestingLevel--;
                continue;
            }
        }
        if ($nestingLevel < 0 || $nestingLevel > 0) {
            throw new InvalidArgumentException(sprintf('Could not find type in %s, please check for malformed notations', $body));
        }
        $description = trim(substr($body, strlen($type)));
        return [$type, $description];
    }
    public function __toString(): string
    {
        if ($this->description) {
            $description = $this->description->render();
        } else {
            $description = '';
        }
        $type = (string) $this->type;
        return $type . ($description !== '' ? ($type !== '' ? ' ' : '') . $description : '');
    }
}
<?php

declare (strict_types=1);
/**
 * This file is part of phpDocumentor.
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @link      http://phpdoc.org
 */
namespace _ContaoManager\phpDocumentor\Reflection\DocBlock\Tags;

use _ContaoManager\phpDocumentor\Reflection\DocBlock\Description;
use _ContaoManager\phpDocumentor\Reflection\DocBlock\DescriptionFactory;
use _ContaoManager\phpDocumentor\Reflection\Types\Context as TypeContext;
use _ContaoManager\Webmozart\Assert\Assert;
use function preg_match;
/**
 * Reflection class for a {@}source tag in a Docblock.
 */
final class Source extends BaseTag implements Factory\StaticMethod
{
    protected string $name = 'source';
    /** @var int The starting line, relative to the structural element's location. */
    private int $startingLine;
    /** @var int|null The number of lines, relative to the starting line. NULL means "to the end". */
    private ?int $lineCount = null;
    /**
     * @param int|string      $startingLine should be a to int convertible value
     * @param int|string|null $lineCount    should be a to int convertible value
     */
    public function __construct($startingLine, $lineCount = null, ?Description $description = null)
    {
        Assert::integerish($startingLine);
        Assert::nullOrIntegerish($lineCount);
        $this->startingLine = (int) $startingLine;
        $this->lineCount = $lineCount !== null ? (int) $lineCount : null;
        $this->description = $description;
    }
    public static function create(string $body, ?DescriptionFactory $descriptionFactory = null, ?TypeContext $context = null): self
    {
        Assert::stringNotEmpty($body);
        Assert::notNull($descriptionFactory);
        $startingLine = 1;
        $lineCount = null;
        $description = null;
        // Starting line / Number of lines / Description
        if (preg_match('/^([1-9]\d*)\s*(?:((?1))\s+)?(.*)$/sux', $body, $matches)) {
            $startingLine = (int) $matches[1];
            if (isset($matches[2]) && $matches[2] !== '') {
                $lineCount = (int) $matches[2];
            }
            $description = $matches[3];
        }
        return new static($startingLine, $lineCount, $descriptionFactory->create($description ?? '', $context));
    }
    /**
     * Gets the starting line.
     *
     * @return int The starting line, relative to the structural element's
     *     location.
     */
    public function getStartingLine(): int
    {
        return $this->startingLine;
    }
    /**
     * Returns the number of lines.
     *
     * @return int|null The number of lines, relative to the starting line. NULL
     *     means "to the end".
     */
    public function getLineCount(): ?int
    {
        return $this->lineCount;
    }
    public function __toString(): string
    {
        if ($this->description) {
            $description = $this->description->render();
        } else {
            $description = '';
        }
        $startingLine = (string) $this->startingLine;
        $lineCount = $this->lineCount !== null ? ' ' . $this->lineCount : '';
        return $startingLine . $lineCount . ($description !== '' ? ' ' . $description : '');
    }
}
<?php

declare (strict_types=1);
/**
 * This file is part of phpDocumentor.
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @link http://phpdoc.org
 */
namespace _ContaoManager\phpDocumentor\Reflection\DocBlock\Tags;

use _ContaoManager\Doctrine\Deprecations\Deprecation;
use _ContaoManager\phpDocumentor\Reflection\DocBlock\Description;
use _ContaoManager\phpDocumentor\Reflection\DocBlock\Tag;
use _ContaoManager\phpDocumentor\Reflection\Type;
/**
 * Reflection class for a {@}template tag in a Docblock.
 */
final class Template extends BaseTag
{
    /** @var non-empty-string */
    private string $templateName;
    /** @var ?Type The real type */
    private ?Type $bound;
    private ?Type $default;
    /** @param non-empty-string $templateName */
    public function __construct(string $templateName, ?Type $bound = null, ?Type $default = null, ?Description $description = null)
    {
        $this->name = 'template';
        $this->templateName = $templateName;
        $this->bound = $bound;
        $this->default = $default;
        $this->description = $description;
    }
    /**
     * @deprecated Create using static factory is deprecated,
     *  this method should not be called directly by library consumers
     */
    public static function create(string $body): ?Tag
    {
        Deprecation::trigger('phpdocumentor/reflection-docblock', 'https://github.com/phpDocumentor/ReflectionDocBlock/issues/361', 'Create using static factory is deprecated, this method should not be called directly
             by library consumers');
        return null;
    }
    public function getTemplateName(): string
    {
        return $this->templateName;
    }
    public function getBound(): ?Type
    {
        return $this->bound;
    }
    public function getDefault(): ?Type
    {
        return $this->default;
    }
    public function __toString(): string
    {
        $bound = $this->bound !== null ? ' of ' . $this->bound : '';
        $default = $this->default !== null ? ' = ' . $this->default : '';
        if ($this->description) {
            $description = $this->description->render();
        } else {
            $description = '';
        }
        return $this->templateName . $bound . $default . ($description !== '' ? ' ' . $description : '');
    }
}
<?php

declare (strict_types=1);
/**
 * This file is part of phpDocumentor.
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @link http://phpdoc.org
 */
namespace _ContaoManager\phpDocumentor\Reflection\DocBlock\Tags;

use _ContaoManager\Doctrine\Deprecations\Deprecation;
use _ContaoManager\phpDocumentor\Reflection\DocBlock\Description;
use _ContaoManager\phpDocumentor\Reflection\DocBlock\Tag;
use _ContaoManager\phpDocumentor\Reflection\Type;
/**
 * Reflection class for a {@}implements tag in a Docblock.
 */
class Implements_ extends TagWithType
{
    public function __construct(Type $type, ?Description $description = null)
    {
        $this->name = 'implements';
        $this->type = $type;
        $this->description = $description;
    }
    /**
     * @deprecated Create using static factory is deprecated,
     *  this method should not be called directly by library consumers
     */
    public static function create(string $body): ?Tag
    {
        Deprecation::trigger('phpdocumentor/reflection-docblock', 'https://github.com/phpDocumentor/ReflectionDocBlock/issues/361', 'Create using static factory is deprecated, this method should not be called directly
             by library consumers');
        return null;
    }
}
<?php

declare (strict_types=1);
/**
 * This file is part of phpDocumentor.
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @link http://phpdoc.org
 */
namespace _ContaoManager\phpDocumentor\Reflection\DocBlock\Tags;

use InvalidArgumentException;
use function filter_var;
use function preg_match;
use function trim;
use const FILTER_VALIDATE_EMAIL;
/**
 * Reflection class for an {@}author tag in a Docblock.
 */
final class Author extends BaseTag implements Factory\StaticMethod
{
    /** @var string register that this is the author tag. */
    protected string $name = 'author';
    /** @var string The name of the author */
    private string $authorName;
    /** @var string The email of the author */
    private string $authorEmail;
    /**
     * Initializes this tag with the author name and e-mail.
     */
    public function __construct(string $authorName, string $authorEmail)
    {
        if ($authorEmail && !filter_var($authorEmail, FILTER_VALIDATE_EMAIL)) {
            throw new InvalidArgumentException('The author tag does not have a valid e-mail address');
        }
        $this->authorName = $authorName;
        $this->authorEmail = $authorEmail;
    }
    /**
     * Gets the author's name.
     *
     * @return string The author's name.
     */
    public function getAuthorName(): string
    {
        return $this->authorName;
    }
    /**
     * Returns the author's email.
     *
     * @return string The author's email.
     */
    public function getEmail(): string
    {
        return $this->authorEmail;
    }
    /**
     * Returns this tag in string form.
     */
    public function __toString(): string
    {
        if ($this->authorEmail) {
            $authorEmail = '<' . $this->authorEmail . '>';
        } else {
            $authorEmail = '';
        }
        $authorName = $this->authorName;
        return $authorName . ($authorEmail !== '' ? ($authorName !== '' ? ' ' : '') . $authorEmail : '');
    }
    /**
     * Attempts to create a new Author object based on the tag body.
     */
    public static function create(string $body): ?self
    {
        $splitTagContent = preg_match('/^([^\<]*)(?:\<([^\>]*)\>)?$/u', $body, $matches);
        if (!$splitTagContent) {
            return null;
        }
        $authorName = trim($matches[1]);
        $email = isset($matches[2]) ? trim($matches[2]) : '';
        return new static($authorName, $email);
    }
}
<?php

declare (strict_types=1);
/**
 * This file is part of phpDocumentor.
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @link      http://phpdoc.org
 */
namespace _ContaoManager\phpDocumentor\Reflection\DocBlock\Tags;

use _ContaoManager\phpDocumentor\Reflection\DocBlock\Description;
use _ContaoManager\phpDocumentor\Reflection\DocBlock\DescriptionFactory;
use _ContaoManager\phpDocumentor\Reflection\Type;
use _ContaoManager\phpDocumentor\Reflection\TypeResolver;
use _ContaoManager\phpDocumentor\Reflection\Types\Context as TypeContext;
use _ContaoManager\Webmozart\Assert\Assert;
/**
 * Reflection class for a {@}throws tag in a Docblock.
 */
final class Throws extends TagWithType implements Factory\StaticMethod
{
    public function __construct(Type $type, ?Description $description = null)
    {
        $this->name = 'throws';
        $this->type = $type;
        $this->description = $description;
    }
    public static function create(string $body, ?TypeResolver $typeResolver = null, ?DescriptionFactory $descriptionFactory = null, ?TypeContext $context = null): self
    {
        Assert::notNull($typeResolver);
        Assert::notNull($descriptionFactory);
        [$type, $description] = self::extractTypeFromBody($body);
        $type = $typeResolver->resolve($type, $context);
        $description = $descriptionFactory->create($description, $context);
        return new static($type, $description);
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\phpDocumentor\Reflection\DocBlock\Tags\Factory;

use _ContaoManager\phpDocumentor\Reflection\DocBlock\DescriptionFactory;
use _ContaoManager\phpDocumentor\Reflection\DocBlock\Tag;
use _ContaoManager\phpDocumentor\Reflection\DocBlock\Tags\Implements_;
use _ContaoManager\phpDocumentor\Reflection\TypeResolver;
use _ContaoManager\phpDocumentor\Reflection\Types\Context;
use _ContaoManager\PHPStan\PhpDocParser\Ast\PhpDoc\ImplementsTagValueNode;
use _ContaoManager\PHPStan\PhpDocParser\Ast\PhpDoc\PhpDocTagNode;
use _ContaoManager\Webmozart\Assert\Assert;
use function is_string;
/**
 * @internal This class is not part of the BC promise of this library.
 */
final class ImplementsFactory implements PHPStanFactory
{
    private DescriptionFactory $descriptionFactory;
    private TypeResolver $typeResolver;
    public function __construct(TypeResolver $typeResolver, DescriptionFactory $descriptionFactory)
    {
        $this->descriptionFactory = $descriptionFactory;
        $this->typeResolver = $typeResolver;
    }
    public function supports(PhpDocTagNode $node, Context $context): bool
    {
        return $node->value instanceof ImplementsTagValueNode && $node->name === '@implements';
    }
    public function create(PhpDocTagNode $node, Context $context): Tag
    {
        $tagValue = $node->value;
        Assert::isInstanceOf($tagValue, ImplementsTagValueNode::class);
        $description = $tagValue->getAttribute('description');
        if (is_string($description) === \false) {
            $description = $tagValue->description;
        }
        return new Implements_($this->typeResolver->createType($tagValue->type, $context), $this->descriptionFactory->create($description, $context));
    }
}
<?php

/*
 * This file is part of phpDocumentor.
 *
 *  For the full copyright and license information, please view the LICENSE
 *  file that was distributed with this source code.
 *
 *  @link      http://phpdoc.org
 *
 */
declare (strict_types=1);
/**
 * This file is part of phpDocumentor.
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @link http://phpdoc.org
 */
namespace _ContaoManager\phpDocumentor\Reflection\DocBlock\Tags\Factory;

use InvalidArgumentException;
use _ContaoManager\phpDocumentor\Reflection\DocBlock\Tag;
use _ContaoManager\phpDocumentor\Reflection\Types\Context as TypeContext;
interface Factory
{
    /**
     * Factory method responsible for instantiating the correct sub type.
     *
     * @param string $tagLine The text for this tag, including description.
     *
     * @return Tag A new tag object.
     *
     * @throws InvalidArgumentException If an invalid tag line was presented.
     */
    public function create(string $tagLine, ?TypeContext $context = null): Tag;
}
<?php

declare (strict_types=1);
namespace _ContaoManager\phpDocumentor\Reflection\DocBlock\Tags\Factory;

use _ContaoManager\phpDocumentor\Reflection\DocBlock\DescriptionFactory;
use _ContaoManager\phpDocumentor\Reflection\DocBlock\Tag;
use _ContaoManager\phpDocumentor\Reflection\DocBlock\Tags\PropertyRead;
use _ContaoManager\phpDocumentor\Reflection\TypeResolver;
use _ContaoManager\phpDocumentor\Reflection\Types\Context;
use _ContaoManager\PHPStan\PhpDocParser\Ast\PhpDoc\PhpDocTagNode;
use _ContaoManager\PHPStan\PhpDocParser\Ast\PhpDoc\PropertyTagValueNode;
use _ContaoManager\Webmozart\Assert\Assert;
use function is_string;
use function trim;
/**
 * @internal This class is not part of the BC promise of this library.
 */
final class PropertyReadFactory implements PHPStanFactory
{
    private DescriptionFactory $descriptionFactory;
    private TypeResolver $typeResolver;
    public function __construct(TypeResolver $typeResolver, DescriptionFactory $descriptionFactory)
    {
        $this->typeResolver = $typeResolver;
        $this->descriptionFactory = $descriptionFactory;
    }
    public function create(PhpDocTagNode $node, Context $context): Tag
    {
        $tagValue = $node->value;
        Assert::isInstanceOf($tagValue, PropertyTagValueNode::class);
        $description = $tagValue->getAttribute('description');
        if (is_string($description) === \false) {
            $description = $tagValue->description;
        }
        return new PropertyRead(trim($tagValue->propertyName, '$'), $this->typeResolver->createType($tagValue->type, $context), $this->descriptionFactory->create($description, $context));
    }
    public function supports(PhpDocTagNode $node, Context $context): bool
    {
        return $node->value instanceof PropertyTagValueNode && $node->name === '@property-read';
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\phpDocumentor\Reflection\DocBlock\Tags\Factory;

use _ContaoManager\phpDocumentor\Reflection\DocBlock\DescriptionFactory;
use _ContaoManager\phpDocumentor\Reflection\DocBlock\Tag;
use _ContaoManager\phpDocumentor\Reflection\DocBlock\Tags\Extends_;
use _ContaoManager\phpDocumentor\Reflection\TypeResolver;
use _ContaoManager\phpDocumentor\Reflection\Types\Context;
use _ContaoManager\PHPStan\PhpDocParser\Ast\PhpDoc\ExtendsTagValueNode;
use _ContaoManager\PHPStan\PhpDocParser\Ast\PhpDoc\PhpDocTagNode;
use _ContaoManager\Webmozart\Assert\Assert;
use function is_string;
/**
 * @internal This class is not part of the BC promise of this library.
 */
final class ExtendsFactory implements PHPStanFactory
{
    private DescriptionFactory $descriptionFactory;
    private TypeResolver $typeResolver;
    public function __construct(TypeResolver $typeResolver, DescriptionFactory $descriptionFactory)
    {
        $this->descriptionFactory = $descriptionFactory;
        $this->typeResolver = $typeResolver;
    }
    public function supports(PhpDocTagNode $node, Context $context): bool
    {
        return $node->value instanceof ExtendsTagValueNode && $node->name === '@extends';
    }
    public function create(PhpDocTagNode $node, Context $context): Tag
    {
        $tagValue = $node->value;
        Assert::isInstanceOf($tagValue, ExtendsTagValueNode::class);
        $description = $tagValue->getAttribute('description');
        if (is_string($description) === \false) {
            $description = $tagValue->description;
        }
        return new Extends_($this->typeResolver->createType($tagValue->type, $context), $this->descriptionFactory->create($description, $context));
    }
}
<?php

declare (strict_types=1);
/**
 * This file is part of phpDocumentor.
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @link      http://phpdoc.org
 */
namespace _ContaoManager\phpDocumentor\Reflection\DocBlock\Tags\Factory;

/**
 * @deprecated This contract is totally covered by Tag contract. Every class using StaticMethod also use Tag
 */
interface StaticMethod
{
    /**
     * @return mixed
     */
    public static function create(string $body);
}
<?php

/*
 * This file is part of phpDocumentor.
 *
 *  For the full copyright and license information, please view the LICENSE
 *  file that was distributed with this source code.
 *
 *  @link      http://phpdoc.org
 *
 */
declare (strict_types=1);
namespace _ContaoManager\phpDocumentor\Reflection\DocBlock\Tags\Factory;

use _ContaoManager\phpDocumentor\Reflection\DocBlock\Tag;
use _ContaoManager\phpDocumentor\Reflection\DocBlock\Tags\InvalidTag;
use _ContaoManager\phpDocumentor\Reflection\Types\Context as TypeContext;
use _ContaoManager\PHPStan\PhpDocParser\Lexer\Lexer;
use _ContaoManager\PHPStan\PhpDocParser\Parser\ConstExprParser;
use _ContaoManager\PHPStan\PhpDocParser\Parser\PhpDocParser;
use _ContaoManager\PHPStan\PhpDocParser\Parser\TokenIterator;
use _ContaoManager\PHPStan\PhpDocParser\Parser\TypeParser;
use _ContaoManager\PHPStan\PhpDocParser\ParserConfig;
use RuntimeException;
use function class_exists;
use function ltrim;
use function property_exists;
use function rtrim;
/**
 * Factory class creating tags using phpstan's parser
 *
 * This class uses {@see PHPStanFactory} implementations to create tags
 * from the ast of the phpstan docblock parser.
 *
 * @internal This class is not part of the BC promise of this library.
 */
class AbstractPHPStanFactory implements Factory
{
    private PhpDocParser $parser;
    private Lexer $lexer;
    /** @var PHPStanFactory[] */
    private array $factories;
    public function __construct(PHPStanFactory ...$factories)
    {
        if (class_exists(ParserConfig::class)) {
            $config = new ParserConfig(['indexes' => \true, 'lines' => \true]);
            $this->lexer = new Lexer($config);
            $constParser = new ConstExprParser($config);
            $this->parser = new PhpDocParser($config, new TypeParser($config, $constParser), $constParser);
        } else {
            $this->lexer = new Lexer(\true);
            $constParser = new ConstExprParser(\true, \true, ['lines' => \true, 'indexes' => \true]);
            $this->parser = new PhpDocParser(new TypeParser($constParser, \true, ['lines' => \true, 'indexes' => \true]), $constParser, \true, \true, ['lines' => \true, 'indexes' => \true], \true);
        }
        $this->factories = $factories;
    }
    public function create(string $tagLine, ?TypeContext $context = null): Tag
    {
        $tokens = $this->tokenizeLine($tagLine . "\n");
        $ast = $this->parser->parseTag($tokens);
        if (property_exists($ast->value, 'description') === \true) {
            $ast->value->setAttribute('description', rtrim($ast->value->description . $tokens->joinUntil(Lexer::TOKEN_END), "\n"));
        }
        if ($context === null) {
            $context = new TypeContext('');
        }
        try {
            foreach ($this->factories as $factory) {
                if ($factory->supports($ast, $context)) {
                    return $factory->create($ast, $context);
                }
            }
        } catch (RuntimeException $e) {
            return InvalidTag::create((string) $ast->value, 'method')->withError($e);
        }
        return InvalidTag::create((string) $ast->value, $ast->name);
    }
    /**
     * Solve the issue with the lexer not tokenizing the line correctly
     *
     * This method is a workaround for the lexer that includes newline tokens with spaces. For
     * phpstan this isn't an issue, as it doesn't do a lot of things with the indentation of descriptions.
     * But for us is important to keep the indentation of the descriptions, so we need to fix the lexer output.
     */
    private function tokenizeLine(string $tagLine): TokenIterator
    {
        $tokens = $this->lexer->tokenize($tagLine);
        $fixed = [];
        foreach ($tokens as $token) {
            if ($token[1] === Lexer::TOKEN_PHPDOC_EOL && rtrim($token[0], " \t") !== $token[0]) {
                $fixed[] = [rtrim($token[Lexer::VALUE_OFFSET], " \t"), Lexer::TOKEN_PHPDOC_EOL, $token[2] ?? 0];
                $fixed[] = [ltrim($token[Lexer::VALUE_OFFSET], "\n\r"), Lexer::TOKEN_HORIZONTAL_WS, ($token[2] ?? 0) + 1];
                continue;
            }
            $fixed[] = $token;
        }
        return new TokenIterator($fixed);
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\phpDocumentor\Reflection\DocBlock\Tags\Factory;

use _ContaoManager\phpDocumentor\Reflection\DocBlock\DescriptionFactory;
use _ContaoManager\phpDocumentor\Reflection\DocBlock\Tag;
use _ContaoManager\phpDocumentor\Reflection\DocBlock\Tags\PropertyWrite;
use _ContaoManager\phpDocumentor\Reflection\TypeResolver;
use _ContaoManager\phpDocumentor\Reflection\Types\Context;
use _ContaoManager\PHPStan\PhpDocParser\Ast\PhpDoc\PhpDocTagNode;
use _ContaoManager\PHPStan\PhpDocParser\Ast\PhpDoc\PropertyTagValueNode;
use _ContaoManager\Webmozart\Assert\Assert;
use function is_string;
use function trim;
/**
 * @internal This class is not part of the BC promise of this library.
 */
final class PropertyWriteFactory implements PHPStanFactory
{
    private DescriptionFactory $descriptionFactory;
    private TypeResolver $typeResolver;
    public function __construct(TypeResolver $typeResolver, DescriptionFactory $descriptionFactory)
    {
        $this->descriptionFactory = $descriptionFactory;
        $this->typeResolver = $typeResolver;
    }
    public function create(PhpDocTagNode $node, Context $context): Tag
    {
        $tagValue = $node->value;
        Assert::isInstanceOf($tagValue, PropertyTagValueNode::class);
        $description = $tagValue->getAttribute('description');
        if (is_string($description) === \false) {
            $description = $tagValue->description;
        }
        return new PropertyWrite(trim($tagValue->propertyName, '$'), $this->typeResolver->createType($tagValue->type, $context), $this->descriptionFactory->create($description, $context));
    }
    public function supports(PhpDocTagNode $node, Context $context): bool
    {
        return $node->value instanceof PropertyTagValueNode && $node->name === '@property-write';
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\phpDocumentor\Reflection\DocBlock\Tags\Factory;

use _ContaoManager\phpDocumentor\Reflection\DocBlock\DescriptionFactory;
use _ContaoManager\phpDocumentor\Reflection\DocBlock\Tag;
use _ContaoManager\phpDocumentor\Reflection\DocBlock\Tags\Var_;
use _ContaoManager\phpDocumentor\Reflection\TypeResolver;
use _ContaoManager\phpDocumentor\Reflection\Types\Context;
use _ContaoManager\PHPStan\PhpDocParser\Ast\PhpDoc\PhpDocTagNode;
use _ContaoManager\PHPStan\PhpDocParser\Ast\PhpDoc\VarTagValueNode;
use _ContaoManager\Webmozart\Assert\Assert;
use function is_string;
use function trim;
/**
 * @internal This class is not part of the BC promise of this library.
 */
final class VarFactory implements PHPStanFactory
{
    private DescriptionFactory $descriptionFactory;
    private TypeResolver $typeResolver;
    public function __construct(TypeResolver $typeResolver, DescriptionFactory $descriptionFactory)
    {
        $this->descriptionFactory = $descriptionFactory;
        $this->typeResolver = $typeResolver;
    }
    public function create(PhpDocTagNode $node, Context $context): Tag
    {
        $tagValue = $node->value;
        Assert::isInstanceOf($tagValue, VarTagValueNode::class);
        $description = $tagValue->getAttribute('description');
        if (is_string($description) === \false) {
            $description = $tagValue->description;
        }
        return new Var_(trim($tagValue->variableName, '$'), $this->typeResolver->createType($tagValue->type, $context), $this->descriptionFactory->create($description, $context));
    }
    public function supports(PhpDocTagNode $node, Context $context): bool
    {
        return $node->value instanceof VarTagValueNode;
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\phpDocumentor\Reflection\DocBlock\Tags\Factory;

use _ContaoManager\phpDocumentor\Reflection\DocBlock\DescriptionFactory;
use _ContaoManager\phpDocumentor\Reflection\DocBlock\Tag;
use _ContaoManager\phpDocumentor\Reflection\DocBlock\Tags\Method;
use _ContaoManager\phpDocumentor\Reflection\DocBlock\Tags\MethodParameter;
use _ContaoManager\phpDocumentor\Reflection\Type;
use _ContaoManager\phpDocumentor\Reflection\TypeResolver;
use _ContaoManager\phpDocumentor\Reflection\Types\Context;
use _ContaoManager\phpDocumentor\Reflection\Types\Mixed_;
use _ContaoManager\phpDocumentor\Reflection\Types\Void_;
use _ContaoManager\PHPStan\PhpDocParser\Ast\PhpDoc\MethodTagValueNode;
use _ContaoManager\PHPStan\PhpDocParser\Ast\PhpDoc\MethodTagValueParameterNode;
use _ContaoManager\PHPStan\PhpDocParser\Ast\PhpDoc\PhpDocTagNode;
use _ContaoManager\Webmozart\Assert\Assert;
use function array_map;
use function trim;
/**
 * @internal This class is not part of the BC promise of this library.
 */
final class MethodFactory implements PHPStanFactory
{
    private DescriptionFactory $descriptionFactory;
    private TypeResolver $typeResolver;
    public function __construct(TypeResolver $typeResolver, DescriptionFactory $descriptionFactory)
    {
        $this->descriptionFactory = $descriptionFactory;
        $this->typeResolver = $typeResolver;
    }
    public function create(PhpDocTagNode $node, Context $context): Tag
    {
        $tagValue = $node->value;
        Assert::isInstanceOf($tagValue, MethodTagValueNode::class);
        return new Method($tagValue->methodName, [], $this->createReturnType($tagValue, $context), $tagValue->isStatic, $this->descriptionFactory->create($tagValue->description, $context), \false, array_map(function (MethodTagValueParameterNode $param) use ($context) {
            return new MethodParameter(trim($param->parameterName, '$'), $param->type === null ? new Mixed_() : $this->typeResolver->createType($param->type, $context), $param->isReference, $param->isVariadic, $param->defaultValue === null ? MethodParameter::NO_DEFAULT_VALUE : (string) $param->defaultValue);
        }, $tagValue->parameters));
    }
    public function supports(PhpDocTagNode $node, Context $context): bool
    {
        return $node->value instanceof MethodTagValueNode;
    }
    private function createReturnType(MethodTagValueNode $tagValue, Context $context): Type
    {
        if ($tagValue->returnType === null) {
            return new Void_();
        }
        return $this->typeResolver->createType($tagValue->returnType, $context);
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\phpDocumentor\Reflection\DocBlock\Tags\Factory;

use _ContaoManager\phpDocumentor\Reflection\DocBlock\DescriptionFactory;
use _ContaoManager\phpDocumentor\Reflection\DocBlock\Tag;
use _ContaoManager\phpDocumentor\Reflection\DocBlock\Tags\Template;
use _ContaoManager\phpDocumentor\Reflection\TypeResolver;
use _ContaoManager\phpDocumentor\Reflection\Types\Context;
use _ContaoManager\PHPStan\PhpDocParser\Ast\PhpDoc\PhpDocTagNode;
use _ContaoManager\PHPStan\PhpDocParser\Ast\PhpDoc\TemplateTagValueNode;
use _ContaoManager\Webmozart\Assert\Assert;
use function is_string;
/**
 * @internal This class is not part of the BC promise of this library.
 */
final class TemplateFactory implements PHPStanFactory
{
    private DescriptionFactory $descriptionFactory;
    private TypeResolver $typeResolver;
    public function __construct(TypeResolver $typeResolver, DescriptionFactory $descriptionFactory)
    {
        $this->descriptionFactory = $descriptionFactory;
        $this->typeResolver = $typeResolver;
    }
    public function create(PhpDocTagNode $node, Context $context): Tag
    {
        $tagValue = $node->value;
        Assert::isInstanceOf($tagValue, TemplateTagValueNode::class);
        $name = $tagValue->name;
        $description = $tagValue->getAttribute('description');
        if (is_string($description) === \false) {
            $description = $tagValue->description;
        }
        return new Template($name, $this->typeResolver->createType($tagValue->bound, $context), $this->typeResolver->createType($tagValue->default, $context), $this->descriptionFactory->create($description, $context));
    }
    public function supports(PhpDocTagNode $node, Context $context): bool
    {
        return $node->value instanceof TemplateTagValueNode && $node->name === '@template';
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\phpDocumentor\Reflection\DocBlock\Tags\Factory;

use _ContaoManager\phpDocumentor\Reflection\DocBlock\DescriptionFactory;
use _ContaoManager\phpDocumentor\Reflection\DocBlock\Tag;
use _ContaoManager\phpDocumentor\Reflection\DocBlock\Tags\TemplateImplements;
use _ContaoManager\phpDocumentor\Reflection\TypeResolver;
use _ContaoManager\phpDocumentor\Reflection\Types\Context;
use _ContaoManager\PHPStan\PhpDocParser\Ast\PhpDoc\ImplementsTagValueNode;
use _ContaoManager\PHPStan\PhpDocParser\Ast\PhpDoc\PhpDocTagNode;
use _ContaoManager\Webmozart\Assert\Assert;
use function is_string;
/**
 * @internal This class is not part of the BC promise of this library.
 */
final class TemplateImplementsFactory implements PHPStanFactory
{
    private DescriptionFactory $descriptionFactory;
    private TypeResolver $typeResolver;
    public function __construct(TypeResolver $typeResolver, DescriptionFactory $descriptionFactory)
    {
        $this->descriptionFactory = $descriptionFactory;
        $this->typeResolver = $typeResolver;
    }
    public function supports(PhpDocTagNode $node, Context $context): bool
    {
        return $node->value instanceof ImplementsTagValueNode && $node->name === '@template-implements';
    }
    public function create(PhpDocTagNode $node, Context $context): Tag
    {
        $tagValue = $node->value;
        Assert::isInstanceOf($tagValue, ImplementsTagValueNode::class);
        $description = $tagValue->getAttribute('description');
        if (is_string($description) === \false) {
            $description = $tagValue->description;
        }
        return new TemplateImplements($this->typeResolver->createType($tagValue->type, $context), $this->descriptionFactory->create($description, $context));
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\phpDocumentor\Reflection\DocBlock\Tags\Factory;

use _ContaoManager\Doctrine\Deprecations\Deprecation;
use _ContaoManager\phpDocumentor\Reflection\DocBlock\DescriptionFactory;
use _ContaoManager\phpDocumentor\Reflection\DocBlock\Tag;
use _ContaoManager\phpDocumentor\Reflection\DocBlock\Tags\InvalidTag;
use _ContaoManager\phpDocumentor\Reflection\DocBlock\Tags\Param;
use _ContaoManager\phpDocumentor\Reflection\TypeResolver;
use _ContaoManager\phpDocumentor\Reflection\Types\Context;
use _ContaoManager\PHPStan\PhpDocParser\Ast\PhpDoc\InvalidTagValueNode;
use _ContaoManager\PHPStan\PhpDocParser\Ast\PhpDoc\ParamTagValueNode;
use _ContaoManager\PHPStan\PhpDocParser\Ast\PhpDoc\PhpDocTagNode;
use _ContaoManager\PHPStan\PhpDocParser\Ast\PhpDoc\TypelessParamTagValueNode;
use _ContaoManager\PHPStan\PhpDocParser\Ast\Type\IdentifierTypeNode;
use _ContaoManager\PHPStan\PhpDocParser\Ast\Type\OffsetAccessTypeNode;
use _ContaoManager\Webmozart\Assert\Assert;
use function is_string;
use function sprintf;
use function trim;
/**
 * @internal This class is not part of the BC promise of this library.
 */
final class ParamFactory implements PHPStanFactory
{
    private DescriptionFactory $descriptionFactory;
    private TypeResolver $typeResolver;
    public function __construct(TypeResolver $typeResolver, DescriptionFactory $descriptionFactory)
    {
        $this->descriptionFactory = $descriptionFactory;
        $this->typeResolver = $typeResolver;
    }
    public function create(PhpDocTagNode $node, Context $context): Tag
    {
        $tagValue = $node->value;
        if ($tagValue instanceof InvalidTagValueNode) {
            Deprecation::trigger('phpdocumentor/reflection-docblock', 'https://github.com/phpDocumentor/ReflectionDocBlock/issues/362', sprintf('Param tag value "%s" is invalid, falling back to legacy parsing. Please update your docblocks.', $tagValue->value));
            return Param::create($tagValue->value, $this->typeResolver, $this->descriptionFactory, $context);
        }
        Assert::isInstanceOfAny($tagValue, [ParamTagValueNode::class, TypelessParamTagValueNode::class]);
        if (($tagValue->type ?? null) instanceof OffsetAccessTypeNode) {
            return InvalidTag::create((string) $tagValue, 'param');
        }
        $description = $tagValue->getAttribute('description');
        if (is_string($description) === \false) {
            $description = $tagValue->description;
        }
        return new Param(trim($tagValue->parameterName, '$'), $this->typeResolver->createType($tagValue->type ?? new IdentifierTypeNode('mixed'), $context), $tagValue->isVariadic, $this->descriptionFactory->create($description, $context), $tagValue->isReference);
    }
    public function supports(PhpDocTagNode $node, Context $context): bool
    {
        return $node->value instanceof ParamTagValueNode || $node->value instanceof TypelessParamTagValueNode || $node->name === '@param';
    }
}
<?php

declare (strict_types=1);
/**
 * This file is part of phpDocumentor.
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @link      http://phpdoc.org
 */
namespace _ContaoManager\phpDocumentor\Reflection\DocBlock\Tags\Factory;

use function array_key_last;
use function get_class;
use function gettype;
use function method_exists;
use function ucfirst;
use function var_export;
/**
 * @internal This class is not part of the BC promise of this library.
 */
final class MethodParameterFactory
{
    /**
     * Formats the given default value to a string-able mixin
     *
     * @param mixed $defaultValue
     */
    public function format($defaultValue): string
    {
        $method = 'format' . ucfirst(gettype($defaultValue));
        if (method_exists($this, $method)) {
            return ' = ' . $this->{$method}($defaultValue);
        }
        return '';
    }
    private function formatDouble(float $defaultValue): string
    {
        return var_export($defaultValue, \true);
    }
    /**
     * @param mixed $defaultValue
     */
    private function formatNull($defaultValue): string
    {
        return 'null';
    }
    private function formatInteger(int $defaultValue): string
    {
        return var_export($defaultValue, \true);
    }
    private function formatString(string $defaultValue): string
    {
        return var_export($defaultValue, \true);
    }
    private function formatBoolean(bool $defaultValue): string
    {
        return var_export($defaultValue, \true);
    }
    /**
     * @param array<(array<mixed>|int|float|bool|string|object|null)> $defaultValue
     */
    private function formatArray(array $defaultValue): string
    {
        $formatedValue = '[';
        foreach ($defaultValue as $key => $value) {
            $method = 'format' . ucfirst(gettype($value));
            if (!method_exists($this, $method)) {
                continue;
            }
            $formatedValue .= $this->{$method}($value);
            if ($key === array_key_last($defaultValue)) {
                continue;
            }
            $formatedValue .= ',';
        }
        return $formatedValue . ']';
    }
    private function formatObject(object $defaultValue): string
    {
        return 'new ' . get_class($defaultValue) . '()';
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\phpDocumentor\Reflection\DocBlock\Tags\Factory;

use _ContaoManager\phpDocumentor\Reflection\DocBlock\Tag;
use _ContaoManager\phpDocumentor\Reflection\Types\Context;
use _ContaoManager\PHPStan\PhpDocParser\Ast\PhpDoc\PhpDocTagNode;
interface PHPStanFactory
{
    public function create(PhpDocTagNode $node, Context $context): Tag;
    public function supports(PhpDocTagNode $node, Context $context): bool;
}
<?php

declare (strict_types=1);
namespace _ContaoManager\phpDocumentor\Reflection\DocBlock\Tags\Factory;

use _ContaoManager\phpDocumentor\Reflection\DocBlock\DescriptionFactory;
use _ContaoManager\phpDocumentor\Reflection\DocBlock\Tag;
use _ContaoManager\phpDocumentor\Reflection\DocBlock\Tags\TemplateExtends;
use _ContaoManager\phpDocumentor\Reflection\TypeResolver;
use _ContaoManager\phpDocumentor\Reflection\Types\Context;
use _ContaoManager\PHPStan\PhpDocParser\Ast\PhpDoc\ExtendsTagValueNode;
use _ContaoManager\PHPStan\PhpDocParser\Ast\PhpDoc\PhpDocTagNode;
use _ContaoManager\Webmozart\Assert\Assert;
use function is_string;
/**
 * @internal This class is not part of the BC promise of this library.
 */
final class TemplateExtendsFactory implements PHPStanFactory
{
    private DescriptionFactory $descriptionFactory;
    private TypeResolver $typeResolver;
    public function __construct(TypeResolver $typeResolver, DescriptionFactory $descriptionFactory)
    {
        $this->descriptionFactory = $descriptionFactory;
        $this->typeResolver = $typeResolver;
    }
    public function supports(PhpDocTagNode $node, Context $context): bool
    {
        return $node->value instanceof ExtendsTagValueNode && $node->name === '@template-extends';
    }
    public function create(PhpDocTagNode $node, Context $context): Tag
    {
        $tagValue = $node->value;
        Assert::isInstanceOf($tagValue, ExtendsTagValueNode::class);
        $description = $tagValue->getAttribute('description');
        if (is_string($description) === \false) {
            $description = $tagValue->description;
        }
        return new TemplateExtends($this->typeResolver->createType($tagValue->type, $context), $this->descriptionFactory->create($description, $context));
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\phpDocumentor\Reflection\DocBlock\Tags\Factory;

use _ContaoManager\phpDocumentor\Reflection\DocBlock\DescriptionFactory;
use _ContaoManager\phpDocumentor\Reflection\DocBlock\Tag;
use _ContaoManager\phpDocumentor\Reflection\DocBlock\Tags\Property;
use _ContaoManager\phpDocumentor\Reflection\TypeResolver;
use _ContaoManager\phpDocumentor\Reflection\Types\Context;
use _ContaoManager\PHPStan\PhpDocParser\Ast\PhpDoc\PhpDocTagNode;
use _ContaoManager\PHPStan\PhpDocParser\Ast\PhpDoc\PropertyTagValueNode;
use _ContaoManager\Webmozart\Assert\Assert;
use function is_string;
use function trim;
/**
 * @internal This class is not part of the BC promise of this library.
 */
final class PropertyFactory implements PHPStanFactory
{
    private DescriptionFactory $descriptionFactory;
    private TypeResolver $typeResolver;
    public function __construct(TypeResolver $typeResolver, DescriptionFactory $descriptionFactory)
    {
        $this->descriptionFactory = $descriptionFactory;
        $this->typeResolver = $typeResolver;
    }
    public function create(PhpDocTagNode $node, Context $context): Tag
    {
        $tagValue = $node->value;
        Assert::isInstanceOf($tagValue, PropertyTagValueNode::class);
        $description = $tagValue->getAttribute('description');
        if (is_string($description) === \false) {
            $description = $tagValue->description;
        }
        return new Property(trim($tagValue->propertyName, '$'), $this->typeResolver->createType($tagValue->type, $context), $this->descriptionFactory->create($description, $context));
    }
    public function supports(PhpDocTagNode $node, Context $context): bool
    {
        return $node->value instanceof PropertyTagValueNode && $node->name === '@property';
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\phpDocumentor\Reflection\DocBlock\Tags\Factory;

use _ContaoManager\phpDocumentor\Reflection\DocBlock\DescriptionFactory;
use _ContaoManager\phpDocumentor\Reflection\DocBlock\Tag;
use _ContaoManager\phpDocumentor\Reflection\DocBlock\Tags\Return_;
use _ContaoManager\phpDocumentor\Reflection\TypeResolver;
use _ContaoManager\phpDocumentor\Reflection\Types\Context;
use _ContaoManager\PHPStan\PhpDocParser\Ast\PhpDoc\PhpDocTagNode;
use _ContaoManager\PHPStan\PhpDocParser\Ast\PhpDoc\ReturnTagValueNode;
use _ContaoManager\Webmozart\Assert\Assert;
use function is_string;
/**
 * @internal This class is not part of the BC promise of this library.
 */
final class ReturnFactory implements PHPStanFactory
{
    private DescriptionFactory $descriptionFactory;
    private TypeResolver $typeResolver;
    public function __construct(TypeResolver $typeResolver, DescriptionFactory $descriptionFactory)
    {
        $this->descriptionFactory = $descriptionFactory;
        $this->typeResolver = $typeResolver;
    }
    public function create(PhpDocTagNode $node, Context $context): Tag
    {
        $tagValue = $node->value;
        Assert::isInstanceOf($tagValue, ReturnTagValueNode::class);
        $description = $tagValue->getAttribute('description');
        if (is_string($description) === \false) {
            $description = $tagValue->description;
        }
        return new Return_($this->typeResolver->createType($tagValue->type, $context), $this->descriptionFactory->create($description, $context));
    }
    public function supports(PhpDocTagNode $node, Context $context): bool
    {
        return $node->value instanceof ReturnTagValueNode;
    }
}
<?php

declare (strict_types=1);
/**
 * This file is part of phpDocumentor.
 *
 *  For the full copyright and license information, please view the LICENSE
 *  file that was distributed with this source code.
 *
 * @link http://phpdoc.org
 */
namespace _ContaoManager\phpDocumentor\Reflection\DocBlock\Tags\Reference;

/**
 * Interface for references in {@see \phpDocumentor\Reflection\DocBlock\Tags\See}
 */
interface Reference
{
    public function __toString(): string;
}
<?php

declare (strict_types=1);
/**
 * This file is part of phpDocumentor.
 *
 *  For the full copyright and license information, please view the LICENSE
 *  file that was distributed with this source code.
 *
 * @link http://phpdoc.org
 */
namespace _ContaoManager\phpDocumentor\Reflection\DocBlock\Tags\Reference;

use _ContaoManager\Webmozart\Assert\Assert;
/**
 * Url reference used by {@see \phpDocumentor\Reflection\DocBlock\Tags\See}
 */
final class Url implements Reference
{
    private string $uri;
    public function __construct(string $uri)
    {
        Assert::stringNotEmpty($uri);
        $this->uri = $uri;
    }
    public function __toString(): string
    {
        return $this->uri;
    }
}
<?php

declare (strict_types=1);
/**
 * This file is part of phpDocumentor.
 *
 *  For the full copyright and license information, please view the LICENSE
 *  file that was distributed with this source code.
 *
 * @link http://phpdoc.org
 */
namespace _ContaoManager\phpDocumentor\Reflection\DocBlock\Tags\Reference;

use _ContaoManager\phpDocumentor\Reflection\Fqsen as RealFqsen;
/**
 * Fqsen reference used by {@see \phpDocumentor\Reflection\DocBlock\Tags\See}
 */
final class Fqsen implements Reference
{
    private RealFqsen $fqsen;
    public function __construct(RealFqsen $fqsen)
    {
        $this->fqsen = $fqsen;
    }
    /**
     * @return string string representation of the referenced fqsen
     */
    public function __toString(): string
    {
        return (string) $this->fqsen;
    }
}
<?php

declare (strict_types=1);
/**
 * This file is part of phpDocumentor.
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @link http://phpdoc.org
 */
namespace _ContaoManager\phpDocumentor\Reflection\DocBlock\Tags;

use _ContaoManager\phpDocumentor\Reflection\DocBlock\Description;
use _ContaoManager\phpDocumentor\Reflection\Type;
/**
 * Reflection class for a {@}template-extends tag in a Docblock.
 */
final class TemplateExtends extends Extends_
{
    public function __construct(Type $type, ?Description $description = null)
    {
        parent::__construct($type, $description);
        $this->name = 'template-extends';
    }
}
<?php

declare (strict_types=1);
/**
 * This file is part of phpDocumentor.
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @link      http://phpdoc.org
 */
namespace _ContaoManager\phpDocumentor\Reflection\DocBlock\Tags;

use _ContaoManager\phpDocumentor\Reflection\DocBlock\Tag;
use _ContaoManager\Webmozart\Assert\Assert;
use function array_key_exists;
use function preg_match;
use function rawurlencode;
use function str_replace;
use function strpos;
use function trim;
/**
 * Reflection class for a {@}example tag in a Docblock.
 */
final class Example implements Tag, Factory\StaticMethod
{
    /** @var string Path to a file to use as an example. May also be an absolute URI. */
    private string $filePath;
    /**
     * @var bool Whether the file path component represents an URI. This determines how the file portion
     *     appears at {@link getContent()}.
     */
    private bool $isURI;
    private int $startingLine;
    private int $lineCount;
    private ?string $content = null;
    public function __construct(string $filePath, bool $isURI, int $startingLine, int $lineCount, ?string $content)
    {
        Assert::stringNotEmpty($filePath);
        Assert::greaterThanEq($startingLine, 1);
        Assert::greaterThanEq($lineCount, 0);
        $this->filePath = $filePath;
        $this->startingLine = $startingLine;
        $this->lineCount = $lineCount;
        if ($content !== null) {
            $this->content = trim($content);
        }
        $this->isURI = $isURI;
    }
    public function getContent(): string
    {
        if ($this->content === null || $this->content === '') {
            $filePath = $this->filePath;
            if ($this->isURI) {
                $filePath = $this->isUriRelative($this->filePath) ? str_replace('%2F', '/', rawurlencode($this->filePath)) : $this->filePath;
            }
            return trim($filePath);
        }
        return $this->content;
    }
    public function getDescription(): ?string
    {
        return $this->content;
    }
    public static function create(string $body): ?Tag
    {
        // File component: File path in quotes or File URI / Source information
        if (!preg_match('/^\s*(?:(\"[^\"]+\")|(\S+))(?:\s+(.*))?$/sux', $body, $matches)) {
            return null;
        }
        $filePath = null;
        $fileUri = null;
        if (array_key_exists(1, $matches) && $matches[1] !== '') {
            $filePath = $matches[1];
        } else {
            $fileUri = array_key_exists(2, $matches) ? $matches[2] : '';
        }
        $startingLine = 1;
        $lineCount = 0;
        $description = null;
        if (array_key_exists(3, $matches)) {
            $description = $matches[3];
            // Starting line / Number of lines / Description
            if (preg_match('/^([1-9]\d*)(?:\s+((?1))\s*)?(.*)$/sux', $matches[3], $contentMatches)) {
                $startingLine = (int) $contentMatches[1];
                if (isset($contentMatches[2])) {
                    $lineCount = (int) $contentMatches[2];
                }
                if (array_key_exists(3, $contentMatches)) {
                    $description = $contentMatches[3];
                }
            }
        }
        return new static($filePath ?? $fileUri ?? '', $fileUri !== null, $startingLine, $lineCount, $description);
    }
    /**
     * Returns the file path.
     *
     * @return string Path to a file to use as an example.
     *     May also be an absolute URI.
     */
    public function getFilePath(): string
    {
        return trim($this->filePath, '"');
    }
    /**
     * Returns a string representation for this tag.
     */
    public function __toString(): string
    {
        $filePath = $this->filePath;
        $isDefaultLine = $this->startingLine === 1 && $this->lineCount === 0;
        $startingLine = !$isDefaultLine ? (string) $this->startingLine : '';
        $lineCount = !$isDefaultLine ? (string) $this->lineCount : '';
        $content = (string) $this->content;
        return $filePath . ($startingLine !== '' ? ($filePath !== '' ? ' ' : '') . $startingLine : '') . ($lineCount !== '' ? ($filePath !== '' || $startingLine !== '' ? ' ' : '') . $lineCount : '') . ($content !== '' ? ($filePath !== '' || $startingLine !== '' || $lineCount !== '' ? ' ' : '') . $content : '');
    }
    /**
     * Returns true if the provided URI is relative or contains a complete scheme (and thus is absolute).
     */
    private function isUriRelative(string $uri): bool
    {
        return strpos($uri, ':') === \false;
    }
    public function getStartingLine(): int
    {
        return $this->startingLine;
    }
    public function getLineCount(): int
    {
        return $this->lineCount;
    }
    public function getName(): string
    {
        return 'example';
    }
    public function render(?Formatter $formatter = null): string
    {
        if ($formatter === null) {
            $formatter = new Formatter\PassthroughFormatter();
        }
        return $formatter->format($this);
    }
}
<?php

declare (strict_types=1);
/**
 * This file is part of phpDocumentor.
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @link      http://phpdoc.org
 */
namespace _ContaoManager\phpDocumentor\Reflection\DocBlock\Tags;

use _ContaoManager\phpDocumentor\Reflection\DocBlock\Description;
use _ContaoManager\phpDocumentor\Reflection\DocBlock\DescriptionFactory;
use _ContaoManager\phpDocumentor\Reflection\Types\Context as TypeContext;
use _ContaoManager\Webmozart\Assert\Assert;
use function preg_match;
/**
 * Reflection class for a {@}deprecated tag in a Docblock.
 */
final class Deprecated extends BaseTag implements Factory\StaticMethod
{
    protected string $name = 'deprecated';
    /**
     * PCRE regular expression matching a version vector.
     * Assumes the "x" modifier.
     */
    public const REGEX_VECTOR = '(?:
        # Normal release vectors.
        \d\S*
        |
        # VCS version vectors. Per PHPCS, they are expected to
        # follow the form of the VCS name, followed by ":", followed
        # by the version vector itself.
        # By convention, popular VCSes like CVS, SVN and GIT use "$"
        # around the actual version vector.
        [^\s\:]+\:\s*\$[^\$]+\$
    )';
    /** @var string|null The version vector. */
    private ?string $version = null;
    public function __construct(?string $version = null, ?Description $description = null)
    {
        Assert::nullOrNotEmpty($version);
        $this->version = $version;
        $this->description = $description;
    }
    /**
     * @return static
     */
    public static function create(?string $body, ?DescriptionFactory $descriptionFactory = null, ?TypeContext $context = null): self
    {
        if ($body === null || $body === '') {
            return new static();
        }
        $matches = [];
        if (!preg_match('/^(' . self::REGEX_VECTOR . ')\s*(.+)?$/sux', $body, $matches)) {
            return new static(null, $descriptionFactory !== null ? $descriptionFactory->create($body, $context) : null);
        }
        Assert::notNull($descriptionFactory);
        return new static($matches[1], $descriptionFactory->create($matches[2] ?? '', $context));
    }
    /**
     * Gets the version section of the tag.
     */
    public function getVersion(): ?string
    {
        return $this->version;
    }
    /**
     * Returns a string representation for this tag.
     */
    public function __toString(): string
    {
        if ($this->description) {
            $description = $this->description->render();
        } else {
            $description = '';
        }
        $version = (string) $this->version;
        return $version . ($description !== '' ? ($version !== '' ? ' ' : '') . $description : '');
    }
}
<?php

declare (strict_types=1);
/**
 * This file is part of phpDocumentor.
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @link http://phpdoc.org
 */
namespace _ContaoManager\phpDocumentor\Reflection\DocBlock\Tags;

use _ContaoManager\phpDocumentor\Reflection\DocBlock\Description;
use _ContaoManager\phpDocumentor\Reflection\DocBlock\DescriptionFactory;
use _ContaoManager\phpDocumentor\Reflection\Fqsen;
use _ContaoManager\phpDocumentor\Reflection\FqsenResolver;
use _ContaoManager\phpDocumentor\Reflection\Types\Context as TypeContext;
use _ContaoManager\phpDocumentor\Reflection\Utils;
use _ContaoManager\Webmozart\Assert\Assert;
use function array_key_exists;
use function explode;
/**
 * Reflection class for a @covers tag in a Docblock.
 */
final class Covers extends BaseTag implements Factory\StaticMethod
{
    protected string $name = 'covers';
    private Fqsen $refers;
    /**
     * Initializes this tag.
     */
    public function __construct(Fqsen $refers, ?Description $description = null)
    {
        $this->refers = $refers;
        $this->description = $description;
    }
    public static function create(string $body, ?DescriptionFactory $descriptionFactory = null, ?FqsenResolver $resolver = null, ?TypeContext $context = null): self
    {
        Assert::stringNotEmpty($body);
        Assert::notNull($descriptionFactory);
        Assert::notNull($resolver);
        $parts = Utils::pregSplit('/\s+/Su', $body, 2);
        return new static(self::resolveFqsen($parts[0], $resolver, $context), $descriptionFactory->create($parts[1] ?? '', $context));
    }
    private static function resolveFqsen(string $parts, ?FqsenResolver $fqsenResolver, ?TypeContext $context): Fqsen
    {
        Assert::notNull($fqsenResolver);
        $fqsenParts = explode('::', $parts);
        $resolved = $fqsenResolver->resolve($fqsenParts[0], $context);
        if (!array_key_exists(1, $fqsenParts)) {
            return $resolved;
        }
        return new Fqsen($resolved . '::' . $fqsenParts[1]);
    }
    /**
     * Returns the structural element this tag refers to.
     */
    public function getReference(): Fqsen
    {
        return $this->refers;
    }
    /**
     * Returns a string representation of this tag.
     */
    public function __toString(): string
    {
        if ($this->description) {
            $description = $this->description->render();
        } else {
            $description = '';
        }
        $refers = (string) $this->refers;
        return $refers . ($description !== '' ? ($refers !== '' ? ' ' : '') . $description : '');
    }
}
<?php

declare (strict_types=1);
/**
 * This file is part of phpDocumentor.
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @link http://phpdoc.org
 */
namespace _ContaoManager\phpDocumentor\Reflection\DocBlock;

use InvalidArgumentException;
use _ContaoManager\phpDocumentor\Reflection\DocBlock\Tags\Author;
use _ContaoManager\phpDocumentor\Reflection\DocBlock\Tags\Covers;
use _ContaoManager\phpDocumentor\Reflection\DocBlock\Tags\Deprecated;
use _ContaoManager\phpDocumentor\Reflection\DocBlock\Tags\Factory\Factory;
use _ContaoManager\phpDocumentor\Reflection\DocBlock\Tags\Generic;
use _ContaoManager\phpDocumentor\Reflection\DocBlock\Tags\InvalidTag;
use _ContaoManager\phpDocumentor\Reflection\DocBlock\Tags\Link as LinkTag;
use _ContaoManager\phpDocumentor\Reflection\DocBlock\Tags\Method;
use _ContaoManager\phpDocumentor\Reflection\DocBlock\Tags\Mixin;
use _ContaoManager\phpDocumentor\Reflection\DocBlock\Tags\Param;
use _ContaoManager\phpDocumentor\Reflection\DocBlock\Tags\Property;
use _ContaoManager\phpDocumentor\Reflection\DocBlock\Tags\PropertyRead;
use _ContaoManager\phpDocumentor\Reflection\DocBlock\Tags\PropertyWrite;
use _ContaoManager\phpDocumentor\Reflection\DocBlock\Tags\Return_;
use _ContaoManager\phpDocumentor\Reflection\DocBlock\Tags\See as SeeTag;
use _ContaoManager\phpDocumentor\Reflection\DocBlock\Tags\Since;
use _ContaoManager\phpDocumentor\Reflection\DocBlock\Tags\Source;
use _ContaoManager\phpDocumentor\Reflection\DocBlock\Tags\TemplateCovariant;
use _ContaoManager\phpDocumentor\Reflection\DocBlock\Tags\Throws;
use _ContaoManager\phpDocumentor\Reflection\DocBlock\Tags\Uses;
use _ContaoManager\phpDocumentor\Reflection\DocBlock\Tags\Var_;
use _ContaoManager\phpDocumentor\Reflection\DocBlock\Tags\Version;
use _ContaoManager\phpDocumentor\Reflection\FqsenResolver;
use _ContaoManager\phpDocumentor\Reflection\Types\Context as TypeContext;
use ReflectionMethod;
use ReflectionNamedType;
use ReflectionParameter;
use _ContaoManager\Webmozart\Assert\Assert;
use function array_key_exists;
use function array_merge;
use function array_slice;
use function call_user_func_array;
use function get_class;
use function is_object;
use function preg_match;
use function sprintf;
use function strpos;
use function trim;
/**
 * Creates a Tag object given the contents of a tag.
 *
 * This Factory is capable of determining the appropriate class for a tag and instantiate it using its `create`
 * factory method. The `create` factory method of a Tag can have a variable number of arguments; this way you can
 * pass the dependencies that you need to construct a tag object.
 *
 * > Important: each parameter in addition to the body variable for the `create` method must default to null, otherwise
 * > it violates the constraint with the interface; it is recommended to use the {@see Assert::notNull()} method to
 * > verify that a dependency is actually passed.
 *
 * This Factory also features a Service Locator component that is used to pass the right dependencies to the
 * `create` method of a tag; each dependency should be registered as a service or as a parameter.
 *
 * When you want to use a Tag of your own with custom handling you need to call the `registerTagHandler` method, pass
 * the name of the tag and a Fully Qualified Class Name pointing to a class that implements the Tag interface.
 */
final class StandardTagFactory implements TagFactory
{
    /** PCRE regular expression matching a tag name. */
    public const REGEX_TAGNAME = '[\w\-\_\\\\:]+';
    /**
     * @var array<class-string<Tag>|Factory> An array with a tag as a key, and an
     *                               FQCN to a class that handles it as an array value.
     */
    private array $tagHandlerMappings = [
        'author' => Author::class,
        'covers' => Covers::class,
        'deprecated' => Deprecated::class,
        // 'example'         => '\phpDocumentor\Reflection\DocBlock\Tags\Example',
        'link' => LinkTag::class,
        'mixin' => Mixin::class,
        'method' => Method::class,
        'param' => Param::class,
        'property-read' => PropertyRead::class,
        'property' => Property::class,
        'property-write' => PropertyWrite::class,
        'return' => Return_::class,
        'see' => SeeTag::class,
        'since' => Since::class,
        'source' => Source::class,
        'template-covariant' => TemplateCovariant::class,
        'throw' => Throws::class,
        'throws' => Throws::class,
        'uses' => Uses::class,
        'var' => Var_::class,
        'version' => Version::class,
    ];
    /**
     * @var array<class-string<Tag>> An array with an annotation as a key, and an
     *      FQCN to a class that handles it as an array value.
     */
    private array $annotationMappings = [];
    /**
     * @var ReflectionParameter[][] a lazy-loading cache containing parameters
     *      for each tagHandler that has been used.
     */
    private array $tagHandlerParameterCache = [];
    private FqsenResolver $fqsenResolver;
    /**
     * @var mixed[] an array representing a simple Service Locator where we can store parameters and
     *     services that can be inserted into the Factory Methods of Tag Handlers.
     */
    private array $serviceLocator = [];
    /**
     * Initialize this tag factory with the means to resolve an FQSEN and optionally a list of tag handlers.
     *
     * If no tag handlers are provided than the default list in the {@see self::$tagHandlerMappings} property
     * is used.
     *
     * @see self::registerTagHandler() to add a new tag handler to the existing default list.
     *
     * @param array<class-string<Tag>> $tagHandlers
     */
    public function __construct(FqsenResolver $fqsenResolver, ?array $tagHandlers = null)
    {
        $this->fqsenResolver = $fqsenResolver;
        if ($tagHandlers !== null) {
            $this->tagHandlerMappings = $tagHandlers;
        }
        $this->addService($fqsenResolver, FqsenResolver::class);
    }
    public function create(string $tagLine, ?TypeContext $context = null): Tag
    {
        if (!$context) {
            $context = new TypeContext('');
        }
        [$tagName, $tagBody] = $this->extractTagParts($tagLine);
        return $this->createTag(trim($tagBody), $tagName, $context);
    }
    /**
     * @param mixed $value
     */
    public function addParameter(string $name, $value): void
    {
        $this->serviceLocator[$name] = $value;
    }
    public function addService(object $service, ?string $alias = null): void
    {
        $this->serviceLocator[$alias ?? get_class($service)] = $service;
    }
    /** {@inheritDoc} */
    public function registerTagHandler(string $tagName, $handler): void
    {
        Assert::stringNotEmpty($tagName);
        if (strpos($tagName, '\\') !== \false && $tagName[0] !== '\\') {
            throw new InvalidArgumentException('A namespaced tag must have a leading backslash as it must be fully qualified');
        }
        if (is_object($handler)) {
            Assert::isInstanceOf($handler, Factory::class);
            $this->tagHandlerMappings[$tagName] = $handler;
            return;
        }
        Assert::classExists($handler);
        Assert::implementsInterface($handler, Tag::class);
        $this->tagHandlerMappings[$tagName] = $handler;
    }
    /**
     * Extracts all components for a tag.
     *
     * @return string[]
     */
    private function extractTagParts(string $tagLine): array
    {
        $matches = [];
        if (!preg_match('/^@(' . self::REGEX_TAGNAME . ')((?:[\s\(\{])\s*([^\s].*)|$)/us', $tagLine, $matches)) {
            throw new InvalidArgumentException('The tag "' . $tagLine . '" does not seem to be wellformed, please check it for errors');
        }
        return array_slice($matches, 1);
    }
    /**
     * Creates a new tag object with the given name and body or returns null if the tag name was recognized but the
     * body was invalid.
     */
    private function createTag(string $body, string $name, TypeContext $context): Tag
    {
        $handlerClassName = $this->findHandlerClassName($name, $context);
        $arguments = $this->getArgumentsForParametersFromWiring($this->fetchParametersForHandlerFactoryMethod($handlerClassName), $this->getServiceLocatorWithDynamicParameters($context, $name, $body));
        if (array_key_exists('tagLine', $arguments)) {
            $arguments['tagLine'] = sprintf('@%s %s', $name, $body);
        }
        try {
            $callable = [$handlerClassName, 'create'];
            Assert::isCallable($callable);
            /** @phpstan-var callable(string): ?Tag $callable */
            $tag = call_user_func_array($callable, $arguments);
            return $tag ?? InvalidTag::create($body, $name);
        } catch (InvalidArgumentException $e) {
            return InvalidTag::create($body, $name)->withError($e);
        }
    }
    /**
     * Determines the Fully Qualified Class Name of the Factory or Tag (containing a Factory Method `create`).
     *
     * @return class-string<Tag>|Factory
     */
    private function findHandlerClassName(string $tagName, TypeContext $context)
    {
        $handlerClassName = Generic::class;
        if (isset($this->tagHandlerMappings[$tagName])) {
            $handlerClassName = $this->tagHandlerMappings[$tagName];
        } elseif ($this->isAnnotation($tagName)) {
            // TODO: Annotation support is planned for a later stage and as such is disabled for now
            $tagName = (string) $this->fqsenResolver->resolve($tagName, $context);
            if (isset($this->annotationMappings[$tagName])) {
                $handlerClassName = $this->annotationMappings[$tagName];
            }
        }
        return $handlerClassName;
    }
    /**
     * Retrieves the arguments that need to be passed to the Factory Method with the given Parameters.
     *
     * @param ReflectionParameter[] $parameters
     * @param mixed[]               $locator
     *
     * @return mixed[] A series of values that can be passed to the Factory Method of the tag whose parameters
     *     is provided with this method.
     */
    private function getArgumentsForParametersFromWiring(array $parameters, array $locator): array
    {
        $arguments = [];
        foreach ($parameters as $parameter) {
            $type = $parameter->getType();
            $typeHint = null;
            if ($type instanceof ReflectionNamedType) {
                $typeHint = $type->getName();
                if ($typeHint === 'self') {
                    $declaringClass = $parameter->getDeclaringClass();
                    if ($declaringClass !== null) {
                        $typeHint = $declaringClass->getName();
                    }
                }
            }
            $parameterName = $parameter->getName();
            if (isset($locator[$typeHint ?? ''])) {
                $arguments[$parameterName] = $locator[$typeHint ?? ''];
                continue;
            }
            if (isset($locator[$parameterName])) {
                $arguments[$parameterName] = $locator[$parameterName];
                continue;
            }
            $arguments[$parameterName] = null;
        }
        return $arguments;
    }
    /**
     * Retrieves a series of ReflectionParameter objects for the static 'create' method of the given
     * tag handler class name.
     *
     * @param class-string|Factory $handler
     *
     * @return ReflectionParameter[]
     */
    private function fetchParametersForHandlerFactoryMethod($handler): array
    {
        $handlerClassName = is_object($handler) ? get_class($handler) : $handler;
        if (!isset($this->tagHandlerParameterCache[$handlerClassName])) {
            $methodReflection = new ReflectionMethod($handlerClassName, 'create');
            $this->tagHandlerParameterCache[$handlerClassName] = $methodReflection->getParameters();
        }
        return $this->tagHandlerParameterCache[$handlerClassName];
    }
    /**
     * Returns a copy of this class' Service Locator with added dynamic parameters,
     * such as the tag's name, body and Context.
     *
     * @param TypeContext $context The Context (namespace and aliases) that may be
     *  passed and is used to resolve FQSENs.
     * @param string      $tagName The name of the tag that may be
     *  passed onto the factory method of the Tag class.
     * @param string      $tagBody The body of the tag that may be
     *  passed onto the factory method of the Tag class.
     *
     * @return mixed[]
     */
    private function getServiceLocatorWithDynamicParameters(TypeContext $context, string $tagName, string $tagBody): array
    {
        return array_merge($this->serviceLocator, ['name' => $tagName, 'body' => $tagBody, TypeContext::class => $context]);
    }
    /**
     * Returns whether the given tag belongs to an annotation.
     *
     * @todo this method should be populated once we implement Annotation notation support.
     */
    private function isAnnotation(string $tagContent): bool
    {
        // 1. Contains a namespace separator
        // 2. Contains parenthesis
        // 3. Is present in a list of known annotations (make the algorithm smart by first checking is the last part
        //    of the annotation class name matches the found tag name
        return \false;
    }
}
<?php

declare (strict_types=1);
/**
 * This file is part of phpDocumentor.
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @link      http://phpdoc.org
 */
namespace _ContaoManager\phpDocumentor\Reflection\DocBlock;

use _ContaoManager\phpDocumentor\Reflection\DocBlock\Tags\Formatter;
use _ContaoManager\phpDocumentor\Reflection\DocBlock\Tags\Formatter\PassthroughFormatter;
use function vsprintf;
/**
 * Object representing to description for a DocBlock.
 *
 * A Description object can consist of plain text but can also include tags. A Description Formatter can then combine
 * a body template with sprintf-style placeholders together with formatted tags in order to reconstitute a complete
 * description text using the format that you would prefer.
 *
 * Because parsing a Description text can be a verbose process this is handled by the {@see DescriptionFactory}. It is
 * thus recommended to use that to create a Description object, like this:
 *
 *     $description = $descriptionFactory->create('This is a {@see Description}', $context);
 *
 * The description factory will interpret the given body and create a body template and list of tags from them, and pass
 * that onto the constructor if this class.
 *
 * > The $context variable is a class of type {@see \phpDocumentor\Reflection\Types\Context} and contains the namespace
 * > and the namespace aliases that apply to this DocBlock. These are used by the Factory to resolve and expand partial
 * > type names and FQSENs.
 *
 * If you do not want to use the DescriptionFactory you can pass a body template and tag listing like this:
 *
 *     $description = new Description(
 *         'This is a %1$s',
 *         [ new See(new Fqsen('\phpDocumentor\Reflection\DocBlock\Description')) ]
 *     );
 *
 * It is generally recommended to use the Factory as that will also apply escaping rules, while the Description object
 * is mainly responsible for rendering.
 *
 * @see DescriptionFactory to create a new Description.
 * @see Tags\Formatter for the formatting of the body and tags.
 */
class Description
{
    private string $bodyTemplate;
    /** @var Tag[] */
    private array $tags;
    /**
     * Initializes a Description with its body (template) and a listing of the tags used in the body template.
     *
     * @param Tag[] $tags
     */
    public function __construct(string $bodyTemplate, array $tags = [])
    {
        $this->bodyTemplate = $bodyTemplate;
        $this->tags = $tags;
    }
    /**
     * Returns the body template.
     */
    public function getBodyTemplate(): string
    {
        return $this->bodyTemplate;
    }
    /**
     * Returns the tags for this DocBlock.
     *
     * @return Tag[]
     */
    public function getTags(): array
    {
        return $this->tags;
    }
    /**
     * Renders this description as a string where the provided formatter will format the tags in the expected string
     * format.
     */
    public function render(?Formatter $formatter = null): string
    {
        if ($this->tags === []) {
            return vsprintf($this->bodyTemplate, []);
        }
        if ($formatter === null) {
            $formatter = new PassthroughFormatter();
        }
        $tags = [];
        foreach ($this->tags as $tag) {
            $tags[] = '{' . $formatter->format($tag) . '}';
        }
        return vsprintf($this->bodyTemplate, $tags);
    }
    /**
     * Returns a plain string representation of this description.
     */
    public function __toString(): string
    {
        return $this->render();
    }
}
<?php

declare (strict_types=1);
/**
 * This file is part of phpDocumentor.
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @link      http://phpdoc.org
 */
namespace _ContaoManager\phpDocumentor\Reflection;

use _ContaoManager\phpDocumentor\Reflection\Exception\PcreException;
use _ContaoManager\Webmozart\Assert\Assert;
use function preg_last_error;
use function preg_split as php_preg_split;
abstract class Utils
{
    /**
     * Wrapper function for phps preg_split
     *
     * This function is inspired by {@link https://github.com/thecodingmachine/safe/blob/master/generated/pcre.php}. But
     * since this library is all about performance we decided to strip everything we don't need. Reducing the amount
     * of files that have to be loaded, etc.
     *
     * @param string $pattern The pattern to search for, as a string.
     * @param string $subject The input string.
     * @param int $limit If specified, then only substrings up to limit are returned with the
     *      rest of the string being placed in the last substring. A limit of -1 or 0 means "no limit".
     * @param int $flags flags can be any combination of the following flags (combined with the | bitwise operator):
     * *PREG_SPLIT_NO_EMPTY*
     *      If this flag is set, only non-empty pieces will be returned by preg_split().
     * *PREG_SPLIT_DELIM_CAPTURE*
     *      If this flag is set, parenthesized expression in the delimiter pattern will be captured
     *      and returned as well.
     * *PREG_SPLIT_OFFSET_CAPTURE*
     *      If this flag is set, for every occurring match the appendant string offset will also be returned.
     *      Note that this changes the return value in an array where every element is an array consisting of the
     *      matched string at offset 0 and its string offset into subject at offset 1.
     *
     * @return string[] Returns an array containing substrings of subject
     *                                                      split along boundaries matched by pattern
     *
     * @throws PcreException
     */
    public static function pregSplit(string $pattern, string $subject, int $limit = -1, int $flags = 0): array
    {
        $parts = php_preg_split($pattern, $subject, $limit, $flags);
        if ($parts === \false) {
            throw PcreException::createFromPhpError(preg_last_error());
        }
        Assert::allString($parts);
        return $parts;
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\phpDocumentor\Reflection;

use _ContaoManager\phpDocumentor\Reflection\DocBlock\Tag;
// phpcs:ignore SlevomatCodingStandard.Classes.SuperfluousInterfaceNaming.SuperfluousSuffix
interface DocBlockFactoryInterface
{
    /**
     * Factory method for easy instantiation.
     *
     * @param array<string, class-string<Tag>> $additionalTags
     */
    public static function createInstance(array $additionalTags = []): self;
    /**
     * @param string|object $docblock
     */
    public function create($docblock, ?Types\Context $context = null, ?Location $location = null): DocBlock;
}
<?php

declare (strict_types=1);
/**
 * This file is part of phpDocumentor.
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @link      http://phpdoc.org
 */
namespace _ContaoManager\phpDocumentor\Reflection;

use _ContaoManager\phpDocumentor\Reflection\DocBlock\Tag;
use _ContaoManager\phpDocumentor\Reflection\DocBlock\Tags\TagWithType;
use _ContaoManager\Webmozart\Assert\Assert;
final class DocBlock
{
    /** @var string The opening line for this docblock. */
    private string $summary;
    /** @var DocBlock\Description The actual description for this docblock. */
    private DocBlock\Description $description;
    /** @var Tag[] An array containing all the tags in this docblock; except inline. */
    private array $tags = [];
    /** @var Types\Context|null Information about the context of this DocBlock. */
    private ?Types\Context $context = null;
    /** @var Location|null Information about the location of this DocBlock. */
    private ?Location $location = null;
    /** @var bool Is this DocBlock (the start of) a template? */
    private bool $isTemplateStart;
    /** @var bool Does this DocBlock signify the end of a DocBlock template? */
    private bool $isTemplateEnd;
    /**
     * @param DocBlock\Tag[] $tags
     * @param Types\Context  $context  The context in which the DocBlock occurs.
     * @param Location       $location The location within the file that this DocBlock occurs in.
     */
    public function __construct(string $summary = '', ?DocBlock\Description $description = null, array $tags = [], ?Types\Context $context = null, ?Location $location = null, bool $isTemplateStart = \false, bool $isTemplateEnd = \false)
    {
        Assert::allIsInstanceOf($tags, Tag::class);
        $this->summary = $summary;
        $this->description = $description ?: new DocBlock\Description('');
        foreach ($tags as $tag) {
            $this->addTag($tag);
        }
        $this->context = $context;
        $this->location = $location;
        $this->isTemplateEnd = $isTemplateEnd;
        $this->isTemplateStart = $isTemplateStart;
    }
    public function getSummary(): string
    {
        return $this->summary;
    }
    public function getDescription(): DocBlock\Description
    {
        return $this->description;
    }
    /**
     * Returns the current context.
     */
    public function getContext(): ?Types\Context
    {
        return $this->context;
    }
    /**
     * Returns the current location.
     */
    public function getLocation(): ?Location
    {
        return $this->location;
    }
    /**
     * Returns whether this DocBlock is the start of a Template section.
     *
     * A Docblock may serve as template for a series of subsequent DocBlocks. This is indicated by a special marker
     * (`#@+`) that is appended directly after the opening `/**` of a DocBlock.
     *
     * An example of such an opening is:
     *
     * ```
     * /**#@+
     *  * My DocBlock
     *  * /
     * ```
     *
     * The description and tags (not the summary!) are copied onto all subsequent DocBlocks and also applied to all
     * elements that follow until another DocBlock is found that contains the closing marker (`#@-`).
     *
     * @see self::isTemplateEnd() for the check whether a closing marker was provided.
     */
    public function isTemplateStart(): bool
    {
        return $this->isTemplateStart;
    }
    /**
     * Returns whether this DocBlock is the end of a Template section.
     *
     * @see self::isTemplateStart() for a more complete description of the Docblock Template functionality.
     */
    public function isTemplateEnd(): bool
    {
        return $this->isTemplateEnd;
    }
    /**
     * Returns the tags for this DocBlock.
     *
     * @return Tag[]
     */
    public function getTags(): array
    {
        return $this->tags;
    }
    /**
     * Returns an array of tags matching the given name. If no tags are found
     * an empty array is returned.
     *
     * @param string $name String to search by.
     *
     * @return Tag[]
     */
    public function getTagsByName(string $name): array
    {
        $result = [];
        foreach ($this->getTags() as $tag) {
            if ($tag->getName() !== $name) {
                continue;
            }
            $result[] = $tag;
        }
        return $result;
    }
    /**
     * Returns an array of tags with type matching the given name. If no tags are found
     * an empty array is returned.
     *
     * @param string $name String to search by.
     *
     * @return TagWithType[]
     */
    public function getTagsWithTypeByName(string $name): array
    {
        $result = [];
        foreach ($this->getTagsByName($name) as $tag) {
            if (!$tag instanceof TagWithType) {
                continue;
            }
            $result[] = $tag;
        }
        return $result;
    }
    /**
     * Checks if a tag of a certain type is present in this DocBlock.
     *
     * @param string $name Tag name to check for.
     */
    public function hasTag(string $name): bool
    {
        foreach ($this->getTags() as $tag) {
            if ($tag->getName() === $name) {
                return \true;
            }
        }
        return \false;
    }
    /**
     * Remove a tag from this DocBlock.
     *
     * @param Tag $tagToRemove The tag to remove.
     */
    public function removeTag(Tag $tagToRemove): void
    {
        foreach ($this->tags as $key => $tag) {
            if ($tag === $tagToRemove) {
                unset($this->tags[$key]);
                break;
            }
        }
    }
    /**
     * Adds a tag to this DocBlock.
     *
     * @param Tag $tag The tag to add.
     */
    private function addTag(Tag $tag): void
    {
        $this->tags[] = $tag;
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\phpDocumentor\Reflection\Exception;

use InvalidArgumentException;
use const PREG_BACKTRACK_LIMIT_ERROR;
use const PREG_BAD_UTF8_ERROR;
use const PREG_BAD_UTF8_OFFSET_ERROR;
use const PREG_INTERNAL_ERROR;
use const PREG_JIT_STACKLIMIT_ERROR;
use const PREG_NO_ERROR;
use const PREG_RECURSION_LIMIT_ERROR;
final class PcreException extends InvalidArgumentException
{
    public static function createFromPhpError(int $errorCode): self
    {
        switch ($errorCode) {
            case PREG_BACKTRACK_LIMIT_ERROR:
                return new self('Backtrack limit error');
            case PREG_RECURSION_LIMIT_ERROR:
                return new self('Recursion limit error');
            case PREG_BAD_UTF8_ERROR:
                return new self('Bad UTF8 error');
            case PREG_BAD_UTF8_OFFSET_ERROR:
                return new self('Bad UTF8 offset error');
            case PREG_JIT_STACKLIMIT_ERROR:
                return new self('Jit stacklimit error');
            case PREG_NO_ERROR:
            case PREG_INTERNAL_ERROR:
            default:
        }
        return new self('Unknown Pcre error');
    }
}
# Constant-Time Encoding

[![Build Status](https://github.com/paragonie/constant_time_encoding/actions/workflows/ci.yml/badge.svg)](https://github.com/paragonie/constant_time_encoding/actions)
[![Static Analysis](https://github.com/paragonie/constant_time_encoding/actions/workflows/psalm.yml/badge.svg)](https://github.com/paragonie/constant_time_encoding/actions)
[![Latest Stable Version](https://poser.pugx.org/paragonie/constant_time_encoding/v/stable)](https://packagist.org/packages/paragonie/constant_time_encoding)
[![Latest Unstable Version](https://poser.pugx.org/paragonie/constant_time_encoding/v/unstable)](https://packagist.org/packages/paragonie/constant_time_encoding)
[![License](https://poser.pugx.org/paragonie/constant_time_encoding/license)](https://packagist.org/packages/paragonie/constant_time_encoding)
[![Downloads](https://img.shields.io/packagist/dt/paragonie/constant_time_encoding.svg)](https://packagist.org/packages/paragonie/constant_time_encoding)

Based on the [constant-time base64 implementation made by Steve "Sc00bz" Thomas](https://github.com/Sc00bz/ConstTimeEncoding),
this library aims to offer character encoding functions that do not leak
information about what you are encoding/decoding via processor cache 
misses. Further reading on [cache-timing attacks](http://blog.ircmaxell.com/2014/11/its-all-about-time.html).

Our fork offers the following enhancements:

* `mbstring.func_overload` resistance
* Unit tests
* Composer- and Packagist-ready
* Base16 encoding
* Base32 encoding
* Uses `pack()` and `unpack()` instead of `chr()` and `ord()`

## PHP Version Requirements

Version 3 of this library should work on **PHP 8** or newer.

Version 2 of this library should work on **PHP 7** or newer. See [the v2.x branch](https://github.com/paragonie/constant_time_encoding/tree/v2.x).

For PHP 5 support, see [the v1.x branch](https://github.com/paragonie/constant_time_encoding/tree/v1.x).

If you are adding this as a dependency to a project intended to work on PHP 5 through 8.4, please set the required version to `^1|^2|^3`.

## How to Install

```sh
composer require paragonie/constant_time_encoding
```

## How to Use

```php
use ParagonIE\ConstantTime\Encoding;

// possibly (if applicable): 
// require 'vendor/autoload.php';

$data = random_bytes(32);
echo Encoding::base64Encode($data), "\n";
echo Encoding::base32EncodeUpper($data), "\n";
echo Encoding::base32Encode($data), "\n";
echo Encoding::hexEncode($data), "\n";
echo Encoding::hexEncodeUpper($data), "\n";
```

Example output:
 
```
1VilPkeVqirlPifk5scbzcTTbMT2clp+Zkyv9VFFasE=
2VMKKPSHSWVCVZJ6E7SONRY3ZXCNG3GE6ZZFU7TGJSX7KUKFNLAQ====
2vmkkpshswvcvzj6e7sonry3zxcng3ge6zzfu7tgjsx7kukfnlaq====
d558a53e4795aa2ae53e27e4e6c71bcdc4d36cc4f6725a7e664caff551456ac1
D558A53E4795AA2AE53E27E4E6C71BDCC4D36CC4F6725A7E664CAFF551456AC1
```

If you only need a particular variant, you can just reference the 
required class like so:

```php
use ParagonIE\ConstantTime\Base64;
use ParagonIE\ConstantTime\Base32;

$data = random_bytes(32);
echo Base64::encode($data), "\n";
echo Base32::encode($data), "\n";
```

Example output:

```
1VilPkeVqirlPifk5scbzcTTbMT2clp+Zkyv9VFFasE=
2vmkkpshswvcvzj6e7sonry3zxcng3ge6zzfu7tgjsx7kukfnlaq====
```

## Support Contracts

If your company uses this library in their products or services, you may be
interested in [purchasing a support contract from Paragon Initiative Enterprises](https://paragonie.com/enterprise).
The MIT License (MIT)

Copyright (c) 2016 - 2022 Paragon Initiative Enterprises

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

------------------------------------------------------------------------------
This library was based on the work of Steve "Sc00bz" Thomas.
------------------------------------------------------------------------------

The MIT License (MIT)

Copyright (c) 2014 Steve Thomas

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

{
    "name": "paragonie\/constant_time_encoding",
    "description": "Constant-time Implementations of RFC 4648 Encoding (Base-64, Base-32, Base-16)",
    "keywords": [
        "base64",
        "encoding",
        "rfc4648",
        "base32",
        "base16",
        "hex",
        "bin2hex",
        "hex2bin",
        "base64_encode",
        "base64_decode",
        "base32_encode",
        "base32_decode"
    ],
    "license": "MIT",
    "type": "library",
    "authors": [
        {
            "name": "Paragon Initiative Enterprises",
            "email": "security@paragonie.com",
            "homepage": "https:\/\/paragonie.com",
            "role": "Maintainer"
        },
        {
            "name": "Steve 'Sc00bz' Thomas",
            "email": "steve@tobtu.com",
            "homepage": "https:\/\/www.tobtu.com",
            "role": "Original Developer"
        }
    ],
    "support": {
        "issues": "https:\/\/github.com\/paragonie\/constant_time_encoding\/issues",
        "email": "info@paragonie.com",
        "source": "https:\/\/github.com\/paragonie\/constant_time_encoding"
    },
    "require": {
        "php": "^8"
    },
    "require-dev": {
        "infection\/infection": "^0",
        "nikic\/php-fuzzer": "^0",
        "phpunit\/phpunit": "^9|^10|^11",
        "vimeo\/psalm": "^4|^5|^6"
    },
    "autoload": {
        "psr-4": {
            "_ContaoManager\\ParagonIE\\ConstantTime\\": "src\/"
        }
    },
    "autoload-dev": {
        "psr-4": {
            "_ContaoManager\\ParagonIE\\ConstantTime\\Tests\\": "tests\/"
        }
    },
    "scripts": {
        "mutation-test": "infection"
    },
    "config": {
        "process-timeout": 0,
        "allow-plugins": {
            "infection\/extension-installer": true
        }
    }
}<?php

declare (strict_types=1);
namespace _ContaoManager\ParagonIE\ConstantTime;

use Override;
/**
 *  Copyright (c) 2016 - 2022 Paragon Initiative Enterprises.
 *  Copyright (c) 2014 Steve "Sc00bz" Thomas (steve at tobtu dot com)
 *
 *  Permission is hereby granted, free of charge, to any person obtaining a copy
 *  of this software and associated documentation files (the "Software"), to deal
 *  in the Software without restriction, including without limitation the rights
 *  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 *  copies of the Software, and to permit persons to whom the Software is
 *  furnished to do so, subject to the following conditions:
 *
 *  The above copyright notice and this permission notice shall be included in all
 *  copies or substantial portions of the Software.
 *
 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 *  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 *  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 *  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 *  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 *  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 *  SOFTWARE.
 */
/**
 * Class Base64UrlSafe
 * [A-Z][a-z][0-9]\-_
 *
 * @package ParagonIE\ConstantTime
 */
abstract class Base64UrlSafe extends Base64
{
    /**
     * Uses bitwise operators instead of table-lookups to turn 6-bit integers
     * into 8-bit integers.
     *
     * Base64 character set:
     * [A-Z]      [a-z]      [0-9]      -     _
     * 0x41-0x5a, 0x61-0x7a, 0x30-0x39, 0x2d, 0x5f
     *
     * @param int $src
     * @return int
     */
    #[Override]
    protected static function decode6Bits(int $src): int
    {
        $ret = -1;
        // if ($src > 0x40 && $src < 0x5b) $ret += $src - 0x41 + 1; // -64
        $ret += (0x40 - $src & $src - 0x5b) >> 8 & $src - 64;
        // if ($src > 0x60 && $src < 0x7b) $ret += $src - 0x61 + 26 + 1; // -70
        $ret += (0x60 - $src & $src - 0x7b) >> 8 & $src - 70;
        // if ($src > 0x2f && $src < 0x3a) $ret += $src - 0x30 + 52 + 1; // 5
        $ret += (0x2f - $src & $src - 0x3a) >> 8 & $src + 5;
        // if ($src == 0x2c) $ret += 62 + 1;
        $ret += (0x2c - $src & $src - 0x2e) >> 8 & 63;
        // if ($src == 0x5f) ret += 63 + 1;
        $ret += (0x5e - $src & $src - 0x60) >> 8 & 64;
        return $ret;
    }
    /**
     * Uses bitwise operators instead of table-lookups to turn 8-bit integers
     * into 6-bit integers.
     *
     * @param int $src
     * @return string
     */
    #[Override]
    protected static function encode6Bits(int $src): string
    {
        $diff = 0x41;
        // if ($src > 25) $diff += 0x61 - 0x41 - 26; // 6
        $diff += 25 - $src >> 8 & 6;
        // if ($src > 51) $diff += 0x30 - 0x61 - 26; // -75
        $diff -= 51 - $src >> 8 & 75;
        // if ($src > 61) $diff += 0x2d - 0x30 - 10; // -13
        $diff -= 61 - $src >> 8 & 13;
        // if ($src > 62) $diff += 0x5f - 0x2b - 1; // 3
        $diff += 62 - $src >> 8 & 49;
        return \pack('C', $src + $diff);
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\ParagonIE\ConstantTime;

use Override;
use function pack;
/**
 *  Copyright (c) 2016 - 2022 Paragon Initiative Enterprises.
 *  Copyright (c) 2014 Steve "Sc00bz" Thomas (steve at tobtu dot com)
 *
 *  Permission is hereby granted, free of charge, to any person obtaining a copy
 *  of this software and associated documentation files (the "Software"), to deal
 *  in the Software without restriction, including without limitation the rights
 *  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 *  copies of the Software, and to permit persons to whom the Software is
 *  furnished to do so, subject to the following conditions:
 *
 *  The above copyright notice and this permission notice shall be included in all
 *  copies or substantial portions of the Software.
 *
 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 *  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 *  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 *  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 *  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 *  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 *  SOFTWARE.
 */
/**
 * Class Base32Hex
 * [0-9][A-V]
 *
 * @package ParagonIE\ConstantTime
 */
abstract class Base32Hex extends Base32
{
    /**
     * Uses bitwise operators instead of table-lookups to turn 5-bit integers
     * into 8-bit integers.
     *
     * @param int $src
     * @return int
     */
    #[Override]
    protected static function decode5Bits(int $src): int
    {
        $ret = -1;
        // if ($src > 0x30 && $src < 0x3a) ret += $src - 0x2e + 1; // -47
        $ret += (0x2f - $src & $src - 0x3a) >> 8 & $src - 47;
        // if ($src > 0x60 && $src < 0x77) ret += $src - 0x61 + 10 + 1; // -86
        $ret += (0x60 - $src & $src - 0x77) >> 8 & $src - 86;
        return $ret;
    }
    /**
     * Uses bitwise operators instead of table-lookups to turn 5-bit integers
     * into 8-bit integers.
     *
     * @param int $src
     * @return int
     */
    #[Override]
    protected static function decode5BitsUpper(int $src): int
    {
        $ret = -1;
        // if ($src > 0x30 && $src < 0x3a) ret += $src - 0x2e + 1; // -47
        $ret += (0x2f - $src & $src - 0x3a) >> 8 & $src - 47;
        // if ($src > 0x40 && $src < 0x57) ret += $src - 0x41 + 10 + 1; // -54
        $ret += (0x40 - $src & $src - 0x57) >> 8 & $src - 54;
        return $ret;
    }
    /**
     * Uses bitwise operators instead of table-lookups to turn 8-bit integers
     * into 5-bit integers.
     *
     * @param int $src
     * @return string
     */
    #[Override]
    protected static function encode5Bits(int $src): string
    {
        $src += 0x30;
        // if ($src > 0x39) $src += 0x61 - 0x3a; // 39
        $src += 0x39 - $src >> 8 & 39;
        return pack('C', $src);
    }
    /**
     * Uses bitwise operators instead of table-lookups to turn 8-bit integers
     * into 5-bit integers.
     *
     * Uppercase variant.
     *
     * @param int $src
     * @return string
     */
    #[Override]
    protected static function encode5BitsUpper(int $src): string
    {
        $src += 0x30;
        // if ($src > 0x39) $src += 0x41 - 0x3a; // 7
        $src += 0x39 - $src >> 8 & 7;
        return pack('C', $src);
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\ParagonIE\ConstantTime;

use Override;
/**
 *  Copyright (c) 2016 - 2022 Paragon Initiative Enterprises.
 *  Copyright (c) 2014 Steve "Sc00bz" Thomas (steve at tobtu dot com)
 *
 *  Permission is hereby granted, free of charge, to any person obtaining a copy
 *  of this software and associated documentation files (the "Software"), to deal
 *  in the Software without restriction, including without limitation the rights
 *  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 *  copies of the Software, and to permit persons to whom the Software is
 *  furnished to do so, subject to the following conditions:
 *
 *  The above copyright notice and this permission notice shall be included in all
 *  copies or substantial portions of the Software.
 *
 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 *  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 *  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 *  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 *  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 *  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 *  SOFTWARE.
 */
/**
 * Class Base64DotSlash
 * ./[A-Z][a-z][0-9]
 *
 * @package ParagonIE\ConstantTime
 */
abstract class Base64DotSlash extends Base64
{
    /**
     * Uses bitwise operators instead of table-lookups to turn 6-bit integers
     * into 8-bit integers.
     *
     * Base64 character set:
     * ./         [A-Z]      [a-z]     [0-9]
     * 0x2e-0x2f, 0x41-0x5a, 0x61-0x7a, 0x30-0x39
     *
     * @param int $src
     * @return int
     */
    #[Override]
    protected static function decode6Bits(int $src): int
    {
        $ret = -1;
        // if ($src > 0x2d && $src < 0x30) ret += $src - 0x2e + 1; // -45
        $ret += (0x2d - $src & $src - 0x30) >> 8 & $src - 45;
        // if ($src > 0x40 && $src < 0x5b) ret += $src - 0x41 + 2 + 1; // -62
        $ret += (0x40 - $src & $src - 0x5b) >> 8 & $src - 62;
        // if ($src > 0x60 && $src < 0x7b) ret += $src - 0x61 + 28 + 1; // -68
        $ret += (0x60 - $src & $src - 0x7b) >> 8 & $src - 68;
        // if ($src > 0x2f && $src < 0x3a) ret += $src - 0x30 + 54 + 1; // 7
        $ret += (0x2f - $src & $src - 0x3a) >> 8 & $src + 7;
        return $ret;
    }
    /**
     * Uses bitwise operators instead of table-lookups to turn 8-bit integers
     * into 6-bit integers.
     *
     * @param int $src
     * @return string
     */
    #[Override]
    protected static function encode6Bits(int $src): string
    {
        $src += 0x2e;
        // if ($src > 0x2f) $src += 0x41 - 0x30; // 17
        $src += 0x2f - $src >> 8 & 17;
        // if ($src > 0x5a) $src += 0x61 - 0x5b; // 6
        $src += 0x5a - $src >> 8 & 6;
        // if ($src > 0x7a) $src += 0x30 - 0x7b; // -75
        $src -= 0x7a - $src >> 8 & 75;
        return \pack('C', $src);
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\ParagonIE\ConstantTime;

use RangeException;
use SensitiveParameter;
use TypeError;
/**
 *  Copyright (c) 2016 - 2022 Paragon Initiative Enterprises.
 *  Copyright (c) 2014 Steve "Sc00bz" Thomas (steve at tobtu dot com)
 *
 *  Permission is hereby granted, free of charge, to any person obtaining a copy
 *  of this software and associated documentation files (the "Software"), to deal
 *  in the Software without restriction, including without limitation the rights
 *  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 *  copies of the Software, and to permit persons to whom the Software is
 *  furnished to do so, subject to the following conditions:
 *
 *  The above copyright notice and this permission notice shall be included in all
 *  copies or substantial portions of the Software.
 *
 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 *  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 *  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 *  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 *  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 *  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 *  SOFTWARE.
 */
/**
 * Class Encoding
 * @package ParagonIE\ConstantTime
 * @api
 */
abstract class Encoding
{
    /**
     * RFC 4648 Base32 encoding
     *
     * @param string $str
     * @return string
     * @throws TypeError
     */
    public static function base32Encode(
        #[SensitiveParameter]
        string $str
    ): string
    {
        return Base32::encode($str);
    }
    /**
     * RFC 4648 Base32 encoding
     *
     * @param string $str
     * @return string
     * @throws TypeError
     */
    public static function base32EncodeUpper(
        #[SensitiveParameter]
        string $str
    ): string
    {
        return Base32::encodeUpper($str);
    }
    /**
     * RFC 4648 Base32 decoding
     *
     * @param string $str
     * @return string
     * @throws TypeError
     */
    public static function base32Decode(
        #[SensitiveParameter]
        string $str
    ): string
    {
        return Base32::decode($str);
    }
    /**
     * RFC 4648 Base32 decoding
     *
     * @param string $str
     * @return string
     * @throws TypeError
     */
    public static function base32DecodeUpper(
        #[SensitiveParameter]
        string $str
    ): string
    {
        return Base32::decodeUpper($str);
    }
    /**
     * RFC 4648 Base32 encoding
     *
     * @param string $str
     * @return string
     * @throws TypeError
     */
    public static function base32HexEncode(
        #[SensitiveParameter]
        string $str
    ): string
    {
        return Base32Hex::encode($str);
    }
    /**
     * RFC 4648 Base32Hex encoding
     *
     * @param string $str
     * @return string
     * @throws TypeError
     */
    public static function base32HexEncodeUpper(
        #[SensitiveParameter]
        string $str
    ): string
    {
        return Base32Hex::encodeUpper($str);
    }
    /**
     * RFC 4648 Base32Hex decoding
     *
     * @param string $str
     * @return string
     * @throws TypeError
     */
    public static function base32HexDecode(
        #[SensitiveParameter]
        string $str
    ): string
    {
        return Base32Hex::decode($str);
    }
    /**
     * RFC 4648 Base32Hex decoding
     *
     * @param string $str
     * @return string
     * @throws TypeError
     */
    public static function base32HexDecodeUpper(
        #[SensitiveParameter]
        string $str
    ): string
    {
        return Base32Hex::decodeUpper($str);
    }
    /**
     * RFC 4648 Base64 encoding
     *
     * @param string $str
     * @return string
     * @throws TypeError
     */
    public static function base64Encode(
        #[SensitiveParameter]
        string $str
    ): string
    {
        return Base64::encode($str);
    }
    /**
     * RFC 4648 Base64 decoding
     *
     * @param string $str
     * @return string
     * @throws TypeError
     */
    public static function base64Decode(
        #[SensitiveParameter]
        string $str
    ): string
    {
        return Base64::decode($str);
    }
    /**
     * Encode into Base64
     *
     * Base64 character set "./[A-Z][a-z][0-9]"
     * @param string $str
     * @return string
     * @throws TypeError
     */
    public static function base64EncodeDotSlash(
        #[SensitiveParameter]
        string $str
    ): string
    {
        return Base64DotSlash::encode($str);
    }
    /**
     * Decode from base64 to raw binary
     *
     * Base64 character set "./[A-Z][a-z][0-9]"
     *
     * @param string $str
     * @return string
     * @throws RangeException
     * @throws TypeError
     */
    public static function base64DecodeDotSlash(
        #[SensitiveParameter]
        string $str
    ): string
    {
        return Base64DotSlash::decode($str);
    }
    /**
     * Encode into Base64
     *
     * Base64 character set "[.-9][A-Z][a-z]" or "./[0-9][A-Z][a-z]"
     * @param string $str
     * @return string
     * @throws TypeError
     */
    public static function base64EncodeDotSlashOrdered(
        #[SensitiveParameter]
        string $str
    ): string
    {
        return Base64DotSlashOrdered::encode($str);
    }
    /**
     * Decode from base64 to raw binary
     *
     * Base64 character set "[.-9][A-Z][a-z]" or "./[0-9][A-Z][a-z]"
     *
     * @param string $str
     * @return string
     * @throws RangeException
     * @throws TypeError
     */
    public static function base64DecodeDotSlashOrdered(
        #[SensitiveParameter]
        string $str
    ): string
    {
        return Base64DotSlashOrdered::decode($str);
    }
    /**
     * Convert a binary string into a hexadecimal string without cache-timing
     * leaks
     *
     * @param string $bin_string (raw binary)
     * @return string
     * @throws TypeError
     */
    public static function hexEncode(
        #[SensitiveParameter]
        string $bin_string
    ): string
    {
        return Hex::encode($bin_string);
    }
    /**
     * Convert a hexadecimal string into a binary string without cache-timing
     * leaks
     *
     * @param string $hex_string
     * @return string (raw binary)
     * @throws RangeException
     */
    public static function hexDecode(
        #[SensitiveParameter]
        string $hex_string
    ): string
    {
        return Hex::decode($hex_string);
    }
    /**
     * Convert a binary string into a hexadecimal string without cache-timing
     * leaks
     *
     * @param string $bin_string (raw binary)
     * @return string
     * @throws TypeError
     */
    public static function hexEncodeUpper(
        #[SensitiveParameter]
        string $bin_string
    ): string
    {
        return Hex::encodeUpper($bin_string);
    }
    /**
     * Convert a binary string into a hexadecimal string without cache-timing
     * leaks
     *
     * @param string $bin_string (raw binary)
     * @return string
     */
    public static function hexDecodeUpper(
        #[SensitiveParameter]
        string $bin_string
    ): string
    {
        return Hex::decode($bin_string);
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\ParagonIE\ConstantTime;

use SensitiveParameter;
/**
 *  Copyright (c) 2016 - 2022 Paragon Initiative Enterprises.
 *  Copyright (c) 2014 Steve "Sc00bz" Thomas (steve at tobtu dot com)
 *
 *  Permission is hereby granted, free of charge, to any person obtaining a copy
 *  of this software and associated documentation files (the "Software"), to deal
 *  in the Software without restriction, including without limitation the rights
 *  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 *  copies of the Software, and to permit persons to whom the Software is
 *  furnished to do so, subject to the following conditions:
 *
 *  The above copyright notice and this permission notice shall be included in all
 *  copies or substantial portions of the Software.
 *
 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 *  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 *  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 *  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 *  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 *  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 *  SOFTWARE.
 */
/**
 * Interface EncoderInterface
 * @package ParagonIE\ConstantTime
 */
interface EncoderInterface
{
    /**
     * Convert a binary string into a hexadecimal string without cache-timing
     * leaks
     *
     * @param string $binString (raw binary)
     * @return string
     */
    public static function encode(
        #[SensitiveParameter]
        string $binString
    ): string;
    /**
     * Convert a binary string into a hexadecimal string without cache-timing
     * leaks
     *
     * @param string $encodedString
     * @param bool $strictPadding Error on invalid padding
     * @return string (raw binary)
     */
    public static function decode(
        #[SensitiveParameter]
        string $encodedString,
        bool $strictPadding = \false
    ): string;
}
<?php

declare (strict_types=1);
namespace _ContaoManager\ParagonIE\ConstantTime;

use InvalidArgumentException;
use Override;
use RangeException;
use SensitiveParameter;
use TypeError;
use function pack;
use function rtrim;
use function strlen;
use function substr;
use function unpack;
/**
 *  Copyright (c) 2016 - 2022 Paragon Initiative Enterprises.
 *  Copyright (c) 2014 Steve "Sc00bz" Thomas (steve at tobtu dot com)
 *
 *  Permission is hereby granted, free of charge, to any person obtaining a copy
 *  of this software and associated documentation files (the "Software"), to deal
 *  in the Software without restriction, including without limitation the rights
 *  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 *  copies of the Software, and to permit persons to whom the Software is
 *  furnished to do so, subject to the following conditions:
 *
 *  The above copyright notice and this permission notice shall be included in all
 *  copies or substantial portions of the Software.
 *
 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 *  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 *  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 *  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 *  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 *  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 *  SOFTWARE.
 */
/**
 * Class Base32
 * [A-Z][2-7]
 *
 * @package ParagonIE\ConstantTime
 */
abstract class Base32 implements EncoderInterface
{
    /**
     * Decode a Base32-encoded string into raw binary
     *
     * @param string $encodedString
     * @param bool $strictPadding
     * @return string
     */
    #[Override]
    public static function decode(
        #[SensitiveParameter]
        string $encodedString,
        bool $strictPadding = \false
    ): string
    {
        return static::doDecode($encodedString, \false, $strictPadding);
    }
    /**
     * Decode an uppercase Base32-encoded string into raw binary
     *
     * @param string $src
     * @param bool $strictPadding
     * @return string
     */
    public static function decodeUpper(
        #[SensitiveParameter]
        string $src,
        bool $strictPadding = \false
    ): string
    {
        return static::doDecode($src, \true, $strictPadding);
    }
    /**
     * Encode into Base32 (RFC 4648)
     *
     * @param string $binString
     * @return string
     * @throws TypeError
     */
    #[Override]
    public static function encode(
        #[SensitiveParameter]
        string $binString
    ): string
    {
        return static::doEncode($binString, \false, \true);
    }
    /**
     * Encode into Base32 (RFC 4648)
     *
     * @param string $src
     * @return string
     * @throws TypeError
     * @api
     */
    public static function encodeUnpadded(
        #[SensitiveParameter]
        string $src
    ): string
    {
        return static::doEncode($src, \false, \false);
    }
    /**
     * Encode into uppercase Base32 (RFC 4648)
     *
     * @param string $src
     * @return string
     * @throws TypeError
     * @api
     */
    public static function encodeUpper(
        #[SensitiveParameter]
        string $src
    ): string
    {
        return static::doEncode($src, \true, \true);
    }
    /**
     * Encode into uppercase Base32 (RFC 4648)
     *
     * @param string $src
     * @return string
     * @throws TypeError
     * @api
     */
    public static function encodeUpperUnpadded(
        #[SensitiveParameter]
        string $src
    ): string
    {
        return static::doEncode($src, \true, \false);
    }
    /**
     * Uses bitwise operators instead of table-lookups to turn 5-bit integers
     * into 8-bit integers.
     *
     * @param int $src
     * @return int
     * @api
     */
    protected static function decode5Bits(int $src): int
    {
        $ret = -1;
        // if ($src > 96 && $src < 123) $ret += $src - 97 + 1; // -64
        $ret += (0x60 - $src & $src - 0x7b) >> 8 & $src - 96;
        // if ($src > 0x31 && $src < 0x38) $ret += $src - 24 + 1; // -23
        $ret += (0x31 - $src & $src - 0x38) >> 8 & $src - 23;
        return $ret;
    }
    /**
     * Uses bitwise operators instead of table-lookups to turn 5-bit integers
     * into 8-bit integers.
     *
     * Uppercase variant.
     *
     * @param int $src
     * @return int
     * @api
     */
    protected static function decode5BitsUpper(int $src): int
    {
        $ret = -1;
        // if ($src > 64 && $src < 91) $ret += $src - 65 + 1; // -64
        $ret += (0x40 - $src & $src - 0x5b) >> 8 & $src - 64;
        // if ($src > 0x31 && $src < 0x38) $ret += $src - 24 + 1; // -23
        $ret += (0x31 - $src & $src - 0x38) >> 8 & $src - 23;
        return $ret;
    }
    /**
     * Uses bitwise operators instead of table-lookups to turn 8-bit integers
     * into 5-bit integers.
     *
     * @param int $src
     * @return string
     * @api
     */
    protected static function encode5Bits(int $src): string
    {
        $diff = 0x61;
        // if ($src > 25) $ret -= 72;
        $diff -= 25 - $src >> 8 & 73;
        return pack('C', $src + $diff);
    }
    /**
     * Uses bitwise operators instead of table-lookups to turn 8-bit integers
     * into 5-bit integers.
     *
     * Uppercase variant.
     *
     * @param int $src
     * @return string
     * @api
     */
    protected static function encode5BitsUpper(int $src): string
    {
        $diff = 0x41;
        // if ($src > 25) $ret -= 40;
        $diff -= 25 - $src >> 8 & 41;
        return pack('C', $src + $diff);
    }
    /**
     * @param string $encodedString
     * @param bool $upper
     * @return string
     * @api
     */
    public static function decodeNoPadding(
        #[SensitiveParameter]
        string $encodedString,
        bool $upper = \false
    ): string
    {
        $srcLen = strlen($encodedString);
        if ($srcLen === 0) {
            return '';
        }
        if (($srcLen & 7) === 0) {
            for ($j = 0; $j < 7 && $j < $srcLen; ++$j) {
                if ($encodedString[$srcLen - $j - 1] === '=') {
                    throw new InvalidArgumentException("decodeNoPadding() doesn't tolerate padding");
                }
            }
        }
        return static::doDecode($encodedString, $upper, \true);
    }
    /**
     * Base32 decoding
     *
     * @param string $src
     * @param bool $upper
     * @param bool $strictPadding
     * @return string
     *
     * @throws TypeError
     */
    protected static function doDecode(
        #[SensitiveParameter]
        string $src,
        bool $upper = \false,
        bool $strictPadding = \false
    ): string
    {
        // We do this to reduce code duplication:
        $method = $upper ? 'decode5BitsUpper' : 'decode5Bits';
        // Remove padding
        $srcLen = strlen($src);
        if ($srcLen === 0) {
            return '';
        }
        if ($strictPadding) {
            if (($srcLen & 7) === 0) {
                for ($j = 0; $j < 7; ++$j) {
                    if ($src[$srcLen - 1] === '=') {
                        $srcLen--;
                    } else {
                        break;
                    }
                }
            }
            if (($srcLen & 7) === 1) {
                throw new RangeException('Incorrect padding');
            }
        } else {
            $src = rtrim($src, '=');
            $srcLen = strlen($src);
        }
        $err = 0;
        $dest = '';
        // Main loop (no padding):
        for ($i = 0; $i + 8 <= $srcLen; $i += 8) {
            /** @var array<int, int> $chunk */
            $chunk = unpack('C*', substr($src, $i, 8));
            /** @var int $c0 */
            $c0 = static::$method($chunk[1]);
            /** @var int $c1 */
            $c1 = static::$method($chunk[2]);
            /** @var int $c2 */
            $c2 = static::$method($chunk[3]);
            /** @var int $c3 */
            $c3 = static::$method($chunk[4]);
            /** @var int $c4 */
            $c4 = static::$method($chunk[5]);
            /** @var int $c5 */
            $c5 = static::$method($chunk[6]);
            /** @var int $c6 */
            $c6 = static::$method($chunk[7]);
            /** @var int $c7 */
            $c7 = static::$method($chunk[8]);
            $dest .= pack('CCCCC', ($c0 << 3 | $c1 >> 2) & 0xff, ($c1 << 6 | $c2 << 1 | $c3 >> 4) & 0xff, ($c3 << 4 | $c4 >> 1) & 0xff, ($c4 << 7 | $c5 << 2 | $c6 >> 3) & 0xff, ($c6 << 5 | $c7) & 0xff);
            $err |= ($c0 | $c1 | $c2 | $c3 | $c4 | $c5 | $c6 | $c7) >> 8;
        }
        // The last chunk, which may have padding:
        if ($i < $srcLen) {
            /** @var array<int, int> $chunk */
            $chunk = unpack('C*', substr($src, $i, $srcLen - $i));
            /** @var int $c0 */
            $c0 = static::$method($chunk[1]);
            if ($i + 6 < $srcLen) {
                /** @var int $c1 */
                $c1 = static::$method($chunk[2]);
                /** @var int $c2 */
                $c2 = static::$method($chunk[3]);
                /** @var int $c3 */
                $c3 = static::$method($chunk[4]);
                /** @var int $c4 */
                $c4 = static::$method($chunk[5]);
                /** @var int $c5 */
                $c5 = static::$method($chunk[6]);
                /** @var int $c6 */
                $c6 = static::$method($chunk[7]);
                $dest .= pack('CCCC', ($c0 << 3 | $c1 >> 2) & 0xff, ($c1 << 6 | $c2 << 1 | $c3 >> 4) & 0xff, ($c3 << 4 | $c4 >> 1) & 0xff, ($c4 << 7 | $c5 << 2 | $c6 >> 3) & 0xff);
                $err |= ($c0 | $c1 | $c2 | $c3 | $c4 | $c5 | $c6) >> 8;
                if ($strictPadding) {
                    $err |= $c6 << 5 & 0xff;
                }
            } elseif ($i + 5 < $srcLen) {
                /** @var int $c1 */
                $c1 = static::$method($chunk[2]);
                /** @var int $c2 */
                $c2 = static::$method($chunk[3]);
                /** @var int $c3 */
                $c3 = static::$method($chunk[4]);
                /** @var int $c4 */
                $c4 = static::$method($chunk[5]);
                /** @var int $c5 */
                $c5 = static::$method($chunk[6]);
                $dest .= pack('CCCC', ($c0 << 3 | $c1 >> 2) & 0xff, ($c1 << 6 | $c2 << 1 | $c3 >> 4) & 0xff, ($c3 << 4 | $c4 >> 1) & 0xff, ($c4 << 7 | $c5 << 2) & 0xff);
                $err |= ($c0 | $c1 | $c2 | $c3 | $c4 | $c5) >> 8;
            } elseif ($i + 4 < $srcLen) {
                /** @var int $c1 */
                $c1 = static::$method($chunk[2]);
                /** @var int $c2 */
                $c2 = static::$method($chunk[3]);
                /** @var int $c3 */
                $c3 = static::$method($chunk[4]);
                /** @var int $c4 */
                $c4 = static::$method($chunk[5]);
                $dest .= pack('CCC', ($c0 << 3 | $c1 >> 2) & 0xff, ($c1 << 6 | $c2 << 1 | $c3 >> 4) & 0xff, ($c3 << 4 | $c4 >> 1) & 0xff);
                $err |= ($c0 | $c1 | $c2 | $c3 | $c4) >> 8;
                if ($strictPadding) {
                    $err |= $c4 << 7 & 0xff;
                }
            } elseif ($i + 3 < $srcLen) {
                /** @var int $c1 */
                $c1 = static::$method($chunk[2]);
                /** @var int $c2 */
                $c2 = static::$method($chunk[3]);
                /** @var int $c3 */
                $c3 = static::$method($chunk[4]);
                $dest .= pack('CC', ($c0 << 3 | $c1 >> 2) & 0xff, ($c1 << 6 | $c2 << 1 | $c3 >> 4) & 0xff);
                $err |= ($c0 | $c1 | $c2 | $c3) >> 8;
                if ($strictPadding) {
                    $err |= $c3 << 4 & 0xff;
                }
            } elseif ($i + 2 < $srcLen) {
                /** @var int $c1 */
                $c1 = static::$method($chunk[2]);
                /** @var int $c2 */
                $c2 = static::$method($chunk[3]);
                $dest .= pack('CC', ($c0 << 3 | $c1 >> 2) & 0xff, ($c1 << 6 | $c2 << 1) & 0xff);
                $err |= ($c0 | $c1 | $c2) >> 8;
                if ($strictPadding) {
                    $err |= $c2 << 6 & 0xff;
                }
            } elseif ($i + 1 < $srcLen) {
                /** @var int $c1 */
                $c1 = static::$method($chunk[2]);
                $dest .= pack('C', ($c0 << 3 | $c1 >> 2) & 0xff);
                $err |= ($c0 | $c1) >> 8;
                if ($strictPadding) {
                    $err |= $c1 << 6 & 0xff;
                }
            } else {
                $dest .= pack('C', $c0 << 3 & 0xff);
                $err |= $c0 >> 8;
            }
        }
        $check = $err === 0;
        if (!$check) {
            throw new RangeException('Base32::doDecode() only expects characters in the correct base32 alphabet');
        }
        return $dest;
    }
    /**
     * Base32 Encoding
     *
     * @param string $src
     * @param bool $upper
     * @param bool $pad
     * @return string
     * @throws TypeError
     */
    protected static function doEncode(
        #[SensitiveParameter]
        string $src,
        bool $upper = \false,
        bool $pad = \true
    ): string
    {
        // We do this to reduce code duplication:
        $method = $upper ? 'encode5BitsUpper' : 'encode5Bits';
        $dest = '';
        $srcLen = strlen($src);
        // Main loop (no padding):
        for ($i = 0; $i + 5 <= $srcLen; $i += 5) {
            /** @var array<int, int> $chunk */
            $chunk = unpack('C*', substr($src, $i, 5));
            $b0 = $chunk[1];
            $b1 = $chunk[2];
            $b2 = $chunk[3];
            $b3 = $chunk[4];
            $b4 = $chunk[5];
            $dest .= static::$method($b0 >> 3 & 31) . static::$method(($b0 << 2 | $b1 >> 6) & 31) . static::$method($b1 >> 1 & 31) . static::$method(($b1 << 4 | $b2 >> 4) & 31) . static::$method(($b2 << 1 | $b3 >> 7) & 31) . static::$method($b3 >> 2 & 31) . static::$method(($b3 << 3 | $b4 >> 5) & 31) . static::$method($b4 & 31);
        }
        // The last chunk, which may have padding:
        if ($i < $srcLen) {
            /** @var array<int, int> $chunk */
            $chunk = unpack('C*', substr($src, $i, $srcLen - $i));
            $b0 = $chunk[1];
            if ($i + 3 < $srcLen) {
                $b1 = $chunk[2];
                $b2 = $chunk[3];
                $b3 = $chunk[4];
                $dest .= static::$method($b0 >> 3 & 31) . static::$method(($b0 << 2 | $b1 >> 6) & 31) . static::$method($b1 >> 1 & 31) . static::$method(($b1 << 4 | $b2 >> 4) & 31) . static::$method(($b2 << 1 | $b3 >> 7) & 31) . static::$method($b3 >> 2 & 31) . static::$method($b3 << 3 & 31);
                if ($pad) {
                    $dest .= '=';
                }
            } elseif ($i + 2 < $srcLen) {
                $b1 = $chunk[2];
                $b2 = $chunk[3];
                $dest .= static::$method($b0 >> 3 & 31) . static::$method(($b0 << 2 | $b1 >> 6) & 31) . static::$method($b1 >> 1 & 31) . static::$method(($b1 << 4 | $b2 >> 4) & 31) . static::$method($b2 << 1 & 31);
                if ($pad) {
                    $dest .= '===';
                }
            } elseif ($i + 1 < $srcLen) {
                $b1 = $chunk[2];
                $dest .= static::$method($b0 >> 3 & 31) . static::$method(($b0 << 2 | $b1 >> 6) & 31) . static::$method($b1 >> 1 & 31) . static::$method($b1 << 4 & 31);
                if ($pad) {
                    $dest .= '====';
                }
            } else {
                $dest .= static::$method($b0 >> 3 & 31) . static::$method($b0 << 2 & 31);
                if ($pad) {
                    $dest .= '======';
                }
            }
        }
        return $dest;
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\ParagonIE\ConstantTime;

use Override;
use RangeException;
use SensitiveParameter;
use SodiumException;
use TypeError;
use function extension_loaded;
use function pack;
use function sodium_bin2hex;
use function sodium_hex2bin;
use function strlen;
use function unpack;
/**
 *  Copyright (c) 2016 - 2025 Paragon Initiative Enterprises.
 *  Copyright (c) 2014 Steve "Sc00bz" Thomas (steve at tobtu dot com)
 *
 *  Permission is hereby granted, free of charge, to any person obtaining a copy
 *  of this software and associated documentation files (the "Software"), to deal
 *  in the Software without restriction, including without limitation the rights
 *  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 *  copies of the Software, and to permit persons to whom the Software is
 *  furnished to do so, subject to the following conditions:
 *
 *  The above copyright notice and this permission notice shall be included in all
 *  copies or substantial portions of the Software.
 *
 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 *  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 *  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 *  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 *  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 *  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 *  SOFTWARE.
 */
/**
 * Class Hex
 * @package ParagonIE\ConstantTime
 */
abstract class Hex implements EncoderInterface
{
    /**
     * Convert a binary string into a hexadecimal string without cache-timing
     * leaks
     *
     * @param string $binString (raw binary)
     * @return string
     * @throws TypeError
     */
    #[Override]
    public static function encode(
        #[SensitiveParameter]
        string $binString
    ): string
    {
        if (extension_loaded('sodium')) {
            try {
                return sodium_bin2hex($binString);
            } catch (SodiumException $ex) {
                throw new RangeException($ex->getMessage(), $ex->getCode(), $ex);
            }
        }
        $hex = '';
        $len = strlen($binString);
        for ($i = 0; $i < $len; ++$i) {
            /** @var array<int, int> $chunk */
            $chunk = unpack('C', $binString[$i]);
            $c = $chunk[1] & 0xf;
            $b = $chunk[1] >> 4;
            $hex .= pack('CC', 87 + $b + ($b - 10 >> 8 & ~38), 87 + $c + ($c - 10 >> 8 & ~38));
        }
        return $hex;
    }
    /**
     * Convert a binary string into a hexadecimal string without cache-timing
     * leaks, returning uppercase letters (as per RFC 4648)
     *
     * @param string $binString (raw binary)
     * @return string
     * @throws TypeError
     */
    public static function encodeUpper(
        #[SensitiveParameter]
        string $binString
    ): string
    {
        $hex = '';
        $len = strlen($binString);
        for ($i = 0; $i < $len; ++$i) {
            /** @var array<int, int> $chunk */
            $chunk = unpack('C', $binString[$i]);
            $c = $chunk[1] & 0xf;
            $b = $chunk[1] >> 4;
            $hex .= pack('CC', 55 + $b + ($b - 10 >> 8 & ~6), 55 + $c + ($c - 10 >> 8 & ~6));
        }
        return $hex;
    }
    /**
     * Convert a hexadecimal string into a binary string without cache-timing
     * leaks
     *
     * @param string $encodedString
     * @param bool $strictPadding
     * @return string (raw binary)
     * @throws RangeException
     */
    #[Override]
    public static function decode(
        #[SensitiveParameter]
        string $encodedString,
        bool $strictPadding = \false
    ): string
    {
        if (extension_loaded('sodium') && $strictPadding) {
            try {
                return sodium_hex2bin($encodedString);
            } catch (SodiumException $ex) {
                throw new RangeException($ex->getMessage(), $ex->getCode(), $ex);
            }
        }
        $hex_pos = 0;
        $bin = '';
        $c_acc = 0;
        $hex_len = strlen($encodedString);
        $state = 0;
        if (($hex_len & 1) !== 0) {
            if ($strictPadding) {
                throw new RangeException('Expected an even number of hexadecimal characters');
            } else {
                $encodedString = '0' . $encodedString;
                ++$hex_len;
            }
        }
        /** @var array<int, int> $chunk */
        $chunk = unpack('C*', $encodedString);
        while ($hex_pos < $hex_len) {
            ++$hex_pos;
            $c = $chunk[$hex_pos];
            $c_num = $c ^ 48;
            $c_num0 = $c_num - 10 >> 8;
            $c_alpha = ($c & ~32) - 55;
            $c_alpha0 = ($c_alpha - 10 ^ $c_alpha - 16) >> 8;
            if (($c_num0 | $c_alpha0) === 0) {
                throw new RangeException('Expected hexadecimal character');
            }
            $c_val = $c_num0 & $c_num | $c_alpha & $c_alpha0;
            if ($state === 0) {
                $c_acc = $c_val * 16;
            } else {
                $bin .= pack('C', $c_acc | $c_val);
            }
            $state ^= 1;
        }
        return $bin;
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\ParagonIE\ConstantTime;

use Override;
/**
 *  Copyright (c) 2016 - 2022 Paragon Initiative Enterprises.
 *  Copyright (c) 2014 Steve "Sc00bz" Thomas (steve at tobtu dot com)
 *
 *  Permission is hereby granted, free of charge, to any person obtaining a copy
 *  of this software and associated documentation files (the "Software"), to deal
 *  in the Software without restriction, including without limitation the rights
 *  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 *  copies of the Software, and to permit persons to whom the Software is
 *  furnished to do so, subject to the following conditions:
 *
 *  The above copyright notice and this permission notice shall be included in all
 *  copies or substantial portions of the Software.
 *
 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 *  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 *  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 *  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 *  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 *  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 *  SOFTWARE.
 */
/**
 * Class Base64DotSlashOrdered
 * ./[0-9][A-Z][a-z]
 *
 * @package ParagonIE\ConstantTime
 */
abstract class Base64DotSlashOrdered extends Base64
{
    /**
     * Uses bitwise operators instead of table-lookups to turn 6-bit integers
     * into 8-bit integers.
     *
     * Base64 character set:
     * [.-9]      [A-Z]      [a-z]
     * 0x2e-0x39, 0x41-0x5a, 0x61-0x7a
     *
     * @param int $src
     * @return int
     */
    #[Override]
    protected static function decode6Bits(int $src): int
    {
        $ret = -1;
        // if ($src > 0x2d && $src < 0x3a) ret += $src - 0x2e + 1; // -45
        $ret += (0x2d - $src & $src - 0x3a) >> 8 & $src - 45;
        // if ($src > 0x40 && $src < 0x5b) ret += $src - 0x41 + 12 + 1; // -52
        $ret += (0x40 - $src & $src - 0x5b) >> 8 & $src - 52;
        // if ($src > 0x60 && $src < 0x7b) ret += $src - 0x61 + 38 + 1; // -58
        $ret += (0x60 - $src & $src - 0x7b) >> 8 & $src - 58;
        return $ret;
    }
    /**
     * Uses bitwise operators instead of table-lookups to turn 8-bit integers
     * into 6-bit integers.
     *
     * @param int $src
     * @return string
     */
    #[Override]
    protected static function encode6Bits(int $src): string
    {
        $src += 0x2e;
        // if ($src > 0x39) $src += 0x41 - 0x3a; // 7
        $src += 0x39 - $src >> 8 & 7;
        // if ($src > 0x5a) $src += 0x61 - 0x5b; // 6
        $src += 0x5a - $src >> 8 & 6;
        return \pack('C', $src);
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\ParagonIE\ConstantTime;

use SensitiveParameter;
use TypeError;
use function strlen;
use function substr;
/**
 *  Copyright (c) 2016 - 2022 Paragon Initiative Enterprises.
 *  Copyright (c) 2014 Steve "Sc00bz" Thomas (steve at tobtu dot com)
 *
 *  Permission is hereby granted, free of charge, to any person obtaining a copy
 *  of this software and associated documentation files (the "Software"), to deal
 *  in the Software without restriction, including without limitation the rights
 *  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 *  copies of the Software, and to permit persons to whom the Software is
 *  furnished to do so, subject to the following conditions:
 *
 *  The above copyright notice and this permission notice shall be included in all
 *  copies or substantial portions of the Software.
 *
 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 *  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 *  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 *  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 *  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 *  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 *  SOFTWARE.
 */
/**
 * Class Binary
 *
 * Binary string operators that don't choke on
 * mbstring.func_overload
 *
 * @package ParagonIE\ConstantTime
 */
abstract class Binary
{
    /**
     * Safe string length
     *
     * @ref mbstring.func_overload
     *
     * @param string $str
     * @return int
     */
    public static function safeStrlen(
        #[SensitiveParameter]
        string $str
    ): int
    {
        return strlen($str);
    }
    /**
     * Safe substring
     *
     * @ref mbstring.func_overload
     *
     * @staticvar boolean $exists
     * @param string $str
     * @param int $start
     * @param ?int $length
     * @return string
     *
     * @throws TypeError
     */
    public static function safeSubstr(
        #[SensitiveParameter]
        string $str,
        int $start = 0,
        ?int $length = null
    ): string
    {
        if ($length === 0) {
            return '';
        }
        // Unlike mb_substr(), substr() doesn't accept NULL for length
        if ($length !== null) {
            return substr($str, $start, $length);
        } else {
            return substr($str, $start);
        }
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\ParagonIE\ConstantTime;

use SensitiveParameter;
use TypeError;
/**
 *  Copyright (c) 2016 - 2022 Paragon Initiative Enterprises.
 *  Copyright (c) 2014 Steve "Sc00bz" Thomas (steve at tobtu dot com)
 *
 *  Permission is hereby granted, free of charge, to any person obtaining a copy
 *  of this software and associated documentation files (the "Software"), to deal
 *  in the Software without restriction, including without limitation the rights
 *  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 *  copies of the Software, and to permit persons to whom the Software is
 *  furnished to do so, subject to the following conditions:
 *
 *  The above copyright notice and this permission notice shall be included in all
 *  copies or substantial portions of the Software.
 *
 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 *  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 *  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 *  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 *  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 *  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 *  SOFTWARE.
 */
/**
 * Class RFC4648
 *
 * This class conforms strictly to the RFC
 *
 * @package ParagonIE\ConstantTime
 * @api
 */
abstract class RFC4648
{
    /**
     * RFC 4648 Base64 encoding
     *
     * "foo" -> "Zm9v"
     *
     * @param string $str
     * @return string
     *
     * @throws TypeError
     */
    public static function base64Encode(
        #[SensitiveParameter]
        string $str
    ): string
    {
        return Base64::encode($str);
    }
    /**
     * RFC 4648 Base64 decoding
     *
     * "Zm9v" -> "foo"
     *
     * @param string $str
     * @return string
     *
     * @throws TypeError
     */
    public static function base64Decode(
        #[SensitiveParameter]
        string $str
    ): string
    {
        return Base64::decode($str, \true);
    }
    /**
     * RFC 4648 Base64 (URL Safe) encoding
     *
     * "foo" -> "Zm9v"
     *
     * @param string $str
     * @return string
     *
     * @throws TypeError
     */
    public static function base64UrlSafeEncode(
        #[SensitiveParameter]
        string $str
    ): string
    {
        return Base64UrlSafe::encode($str);
    }
    /**
     * RFC 4648 Base64 (URL Safe) decoding
     *
     * "Zm9v" -> "foo"
     *
     * @param string $str
     * @return string
     *
     * @throws TypeError
     */
    public static function base64UrlSafeDecode(
        #[SensitiveParameter]
        string $str
    ): string
    {
        return Base64UrlSafe::decode($str, \true);
    }
    /**
     * RFC 4648 Base32 encoding
     *
     * "foo" -> "MZXW6==="
     *
     * @param string $str
     * @return string
     *
     * @throws TypeError
     */
    public static function base32Encode(
        #[SensitiveParameter]
        string $str
    ): string
    {
        return Base32::encodeUpper($str);
    }
    /**
     * RFC 4648 Base32 encoding
     *
     * "MZXW6===" -> "foo"
     *
     * @param string $str
     * @return string
     *
     * @throws TypeError
     */
    public static function base32Decode(
        #[SensitiveParameter]
        string $str
    ): string
    {
        return Base32::decodeUpper($str, \true);
    }
    /**
     * RFC 4648 Base32-Hex encoding
     *
     * "foo" -> "CPNMU==="
     *
     * @param string $str
     * @return string
     *
     * @throws TypeError
     */
    public static function base32HexEncode(
        #[SensitiveParameter]
        string $str
    ): string
    {
        return Base32::encodeUpper($str);
    }
    /**
     * RFC 4648 Base32-Hex decoding
     *
     * "CPNMU===" -> "foo"
     *
     * @param string $str
     * @return string
     *
     * @throws TypeError
     */
    public static function base32HexDecode(
        #[SensitiveParameter]
        string $str
    ): string
    {
        return Base32::decodeUpper($str, \true);
    }
    /**
     * RFC 4648 Base16 decoding
     *
     * "foo" -> "666F6F"
     *
     * @param string $str
     * @return string
     *
     * @throws TypeError
     */
    public static function base16Encode(
        #[SensitiveParameter]
        string $str
    ): string
    {
        return Hex::encodeUpper($str);
    }
    /**
     * RFC 4648 Base16 decoding
     *
     * "666F6F" -> "foo"
     *
     * @param string $str
     * @return string
     */
    public static function base16Decode(
        #[SensitiveParameter]
        string $str
    ): string
    {
        return Hex::decode($str, \true);
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\ParagonIE\ConstantTime;

use InvalidArgumentException;
use Override;
use RangeException;
use SensitiveParameter;
use SodiumException;
use TypeError;
use function extension_loaded;
use function pack;
use function rtrim;
use function sodium_base642bin;
use function sodium_bin2base64;
use function strlen;
use function substr;
use function unpack;
use const SODIUM_BASE64_VARIANT_ORIGINAL;
use const SODIUM_BASE64_VARIANT_ORIGINAL_NO_PADDING;
use const SODIUM_BASE64_VARIANT_URLSAFE;
use const SODIUM_BASE64_VARIANT_URLSAFE_NO_PADDING;
/**
 *  Copyright (c) 2016 - 2022 Paragon Initiative Enterprises.
 *  Copyright (c) 2014 Steve "Sc00bz" Thomas (steve at tobtu dot com)
 *
 *  Permission is hereby granted, free of charge, to any person obtaining a copy
 *  of this software and associated documentation files (the "Software"), to deal
 *  in the Software without restriction, including without limitation the rights
 *  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 *  copies of the Software, and to permit persons to whom the Software is
 *  furnished to do so, subject to the following conditions:
 *
 *  The above copyright notice and this permission notice shall be included in all
 *  copies or substantial portions of the Software.
 *
 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 *  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 *  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 *  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 *  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 *  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 *  SOFTWARE.
 */
/**
 * Class Base64
 * [A-Z][a-z][0-9]+/
 *
 * @package ParagonIE\ConstantTime
 */
abstract class Base64 implements EncoderInterface
{
    /**
     * Encode into Base64
     *
     * Base64 character set "[A-Z][a-z][0-9]+/"
     *
     * @param string $binString
     * @return string
     *
     * @throws TypeError
     */
    #[Override]
    public static function encode(
        #[SensitiveParameter]
        string $binString
    ): string
    {
        if (extension_loaded('sodium')) {
            $variant = match (static::class) {
                Base64::class => SODIUM_BASE64_VARIANT_ORIGINAL,
                Base64UrlSafe::class => SODIUM_BASE64_VARIANT_URLSAFE,
                default => 0,
            };
            if ($variant > 0) {
                try {
                    return sodium_bin2base64($binString, $variant);
                } catch (SodiumException $ex) {
                    throw new RangeException($ex->getMessage(), $ex->getCode(), $ex);
                }
            }
        }
        return static::doEncode($binString, \true);
    }
    /**
     * Encode into Base64, no = padding
     *
     * Base64 character set "[A-Z][a-z][0-9]+/"
     *
     * @param string $src
     * @return string
     *
     * @throws TypeError
     * @api
     */
    public static function encodeUnpadded(
        #[SensitiveParameter]
        string $src
    ): string
    {
        if (extension_loaded('sodium')) {
            $variant = match (static::class) {
                Base64::class => SODIUM_BASE64_VARIANT_ORIGINAL_NO_PADDING,
                Base64UrlSafe::class => SODIUM_BASE64_VARIANT_URLSAFE_NO_PADDING,
                default => 0,
            };
            if ($variant > 0) {
                try {
                    return sodium_bin2base64($src, $variant);
                } catch (SodiumException $ex) {
                    throw new RangeException($ex->getMessage(), $ex->getCode(), $ex);
                }
            }
        }
        return static::doEncode($src, \false);
    }
    /**
     * @param string $src
     * @param bool $pad   Include = padding?
     * @return string
     *
     * @throws TypeError
     */
    protected static function doEncode(
        #[SensitiveParameter]
        string $src,
        bool $pad = \true
    ): string
    {
        $dest = '';
        $srcLen = strlen($src);
        // Main loop (no padding):
        for ($i = 0; $i + 3 <= $srcLen; $i += 3) {
            /** @var array<int, int> $chunk */
            $chunk = unpack('C*', substr($src, $i, 3));
            $b0 = $chunk[1];
            $b1 = $chunk[2];
            $b2 = $chunk[3];
            $dest .= static::encode6Bits($b0 >> 2) . static::encode6Bits(($b0 << 4 | $b1 >> 4) & 63) . static::encode6Bits(($b1 << 2 | $b2 >> 6) & 63) . static::encode6Bits($b2 & 63);
        }
        // The last chunk, which may have padding:
        if ($i < $srcLen) {
            /** @var array<int, int> $chunk */
            $chunk = unpack('C*', substr($src, $i, $srcLen - $i));
            $b0 = $chunk[1];
            if ($i + 1 < $srcLen) {
                $b1 = $chunk[2];
                $dest .= static::encode6Bits($b0 >> 2) . static::encode6Bits(($b0 << 4 | $b1 >> 4) & 63) . static::encode6Bits($b1 << 2 & 63);
                if ($pad) {
                    $dest .= '=';
                }
            } else {
                $dest .= static::encode6Bits($b0 >> 2) . static::encode6Bits($b0 << 4 & 63);
                if ($pad) {
                    $dest .= '==';
                }
            }
        }
        return $dest;
    }
    /**
     * decode from base64 into binary
     *
     * Base64 character set "./[A-Z][a-z][0-9]"
     *
     * @param string $encodedString
     * @param bool $strictPadding
     * @return string
     *
     * @throws RangeException
     * @throws TypeError
     */
    #[Override]
    public static function decode(
        #[SensitiveParameter]
        string $encodedString,
        bool $strictPadding = \false
    ): string
    {
        // Remove padding
        $srcLen = strlen($encodedString);
        if ($srcLen === 0) {
            return '';
        }
        if ($strictPadding) {
            if (($srcLen & 3) === 0) {
                if ($encodedString[$srcLen - 1] === '=') {
                    $srcLen--;
                    if ($encodedString[$srcLen - 1] === '=') {
                        $srcLen--;
                    }
                }
            }
            if (($srcLen & 3) === 1) {
                throw new RangeException('Incorrect padding');
            }
            if ($encodedString[$srcLen - 1] === '=') {
                throw new RangeException('Incorrect padding');
            }
            if (extension_loaded('sodium')) {
                $variant = match (static::class) {
                    Base64::class => SODIUM_BASE64_VARIANT_ORIGINAL_NO_PADDING,
                    Base64UrlSafe::class => SODIUM_BASE64_VARIANT_URLSAFE_NO_PADDING,
                    default => 0,
                };
                if ($variant > 0) {
                    try {
                        return sodium_base642bin(substr($encodedString, 0, $srcLen), $variant);
                    } catch (SodiumException $ex) {
                        throw new RangeException($ex->getMessage(), $ex->getCode(), $ex);
                    }
                }
            }
        } else {
            // Just remove all padding.
            $encodedString = rtrim($encodedString, '=');
            $srcLen = strlen($encodedString);
        }
        $err = 0;
        $dest = '';
        // Main loop (no padding):
        for ($i = 0; $i + 4 <= $srcLen; $i += 4) {
            /** @var array<int, int> $chunk */
            $chunk = unpack('C*', substr($encodedString, $i, 4));
            $c0 = static::decode6Bits($chunk[1]);
            $c1 = static::decode6Bits($chunk[2]);
            $c2 = static::decode6Bits($chunk[3]);
            $c3 = static::decode6Bits($chunk[4]);
            $dest .= pack('CCC', ($c0 << 2 | $c1 >> 4) & 0xff, ($c1 << 4 | $c2 >> 2) & 0xff, ($c2 << 6 | $c3) & 0xff);
            $err |= ($c0 | $c1 | $c2 | $c3) >> 8;
        }
        // The last chunk, which may have padding:
        if ($i < $srcLen) {
            /** @var array<int, int> $chunk */
            $chunk = unpack('C*', substr($encodedString, $i, $srcLen - $i));
            $c0 = static::decode6Bits($chunk[1]);
            if ($i + 2 < $srcLen) {
                $c1 = static::decode6Bits($chunk[2]);
                $c2 = static::decode6Bits($chunk[3]);
                $dest .= pack('CC', ($c0 << 2 | $c1 >> 4) & 0xff, ($c1 << 4 | $c2 >> 2) & 0xff);
                $err |= ($c0 | $c1 | $c2) >> 8;
                if ($strictPadding) {
                    $err |= $c2 << 6 & 0xff;
                }
            } elseif ($i + 1 < $srcLen) {
                $c1 = static::decode6Bits($chunk[2]);
                $dest .= pack('C', ($c0 << 2 | $c1 >> 4) & 0xff);
                $err |= ($c0 | $c1) >> 8;
                if ($strictPadding) {
                    $err |= $c1 << 4 & 0xff;
                }
            } elseif ($strictPadding) {
                $err |= 1;
            }
        }
        $check = $err === 0;
        if (!$check) {
            throw new RangeException('Base64::decode() only expects characters in the correct base64 alphabet');
        }
        return $dest;
    }
    /**
     * @param string $encodedString
     * @return string
     * @api
     */
    public static function decodeNoPadding(
        #[SensitiveParameter]
        string $encodedString
    ): string
    {
        $srcLen = strlen($encodedString);
        if ($srcLen === 0) {
            return '';
        }
        if (($srcLen & 3) === 0) {
            // If $strLen is not zero, and it is divisible by 4, then it's at least 4.
            if ($encodedString[$srcLen - 1] === '=' || $encodedString[$srcLen - 2] === '=') {
                throw new InvalidArgumentException("decodeNoPadding() doesn't tolerate padding");
            }
        }
        return static::decode($encodedString, \true);
    }
    /**
     * Uses bitwise operators instead of table-lookups to turn 6-bit integers
     * into 8-bit integers.
     *
     * Base64 character set:
     * [A-Z]      [a-z]      [0-9]      +     /
     * 0x41-0x5a, 0x61-0x7a, 0x30-0x39, 0x2b, 0x2f
     *
     * @param int $src
     * @return int
     */
    protected static function decode6Bits(int $src): int
    {
        $ret = -1;
        // if ($src > 0x40 && $src < 0x5b) $ret += $src - 0x41 + 1; // -64
        $ret += (0x40 - $src & $src - 0x5b) >> 8 & $src - 64;
        // if ($src > 0x60 && $src < 0x7b) $ret += $src - 0x61 + 26 + 1; // -70
        $ret += (0x60 - $src & $src - 0x7b) >> 8 & $src - 70;
        // if ($src > 0x2f && $src < 0x3a) $ret += $src - 0x30 + 52 + 1; // 5
        $ret += (0x2f - $src & $src - 0x3a) >> 8 & $src + 5;
        // if ($src == 0x2b) $ret += 62 + 1;
        $ret += (0x2a - $src & $src - 0x2c) >> 8 & 63;
        // if ($src == 0x2f) ret += 63 + 1;
        $ret += (0x2e - $src & $src - 0x30) >> 8 & 64;
        return $ret;
    }
    /**
     * Uses bitwise operators instead of table-lookups to turn 8-bit integers
     * into 6-bit integers.
     *
     * @param int $src
     * @return string
     */
    protected static function encode6Bits(int $src): string
    {
        $diff = 0x41;
        // if ($src > 25) $diff += 0x61 - 0x41 - 26; // 6
        $diff += 25 - $src >> 8 & 6;
        // if ($src > 51) $diff += 0x30 - 0x61 - 26; // -75
        $diff -= 51 - $src >> 8 & 75;
        // if ($src > 61) $diff += 0x2b - 0x30 - 10; // -15
        $diff -= 61 - $src >> 8 & 15;
        // if ($src > 62) $diff += 0x2f - 0x2b - 1; // 3
        $diff += 62 - $src >> 8 & 3;
        return pack('C', $src + $diff);
    }
}
# Contributor Covenant Code of Conduct

## Our Pledge

In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation.

## Our Standards

Examples of behavior that contributes to creating a positive environment include:

* Using welcoming and inclusive language
* Being respectful of differing viewpoints and experiences
* Gracefully accepting constructive criticism
* Focusing on what is best for the community
* Showing empathy towards other community members

Examples of unacceptable behavior by participants include:

* The use of sexualized language or imagery and unwelcome sexual attention or advances
* Trolling, insulting/derogatory comments, and personal or political attacks
* Public or private harassment
* Publishing others' private information, such as a physical or electronic address, without explicit permission
* Other conduct which could reasonably be considered inappropriate in a professional setting

## Our Responsibilities

Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior.

Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful.

## Scope

This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers.

## Enforcement

Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at contact@spomky-labs.com. The project team will review and investigate all complaints, and will respond in a way that it deems appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately.

Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership.

## Attribution

This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [http://contributor-covenant.org/version/1/4][version]

[homepage]: http://contributor-covenant.org
[version]: http://contributor-covenant.org/version/1/4/
# Versioning and Release

This document describes the versioning and release process of the Webauthn Framework.
This document is a living document, contents will be updated according to each release.

## Releases

Webauthn Framework releases will be versioned using dotted triples, similar to [Semantic Version](http://semver.org/).
For this specific document, we will refer to the respective components of this triple as `<major>.<minor>.<patch>`.
The version number may have additional information, such as "-rc1,-rc2,-rc3" to mark release candidate builds for earlier access.
Such releases will be considered as "pre-releases".

## Minor Release Support Matrix

| Version | Supported          |
|---------|--------------------|
| 3.2.x   | :white_check_mark: |
| < 3.2.x | :x:                |
MIT License

Copyright (c) 2018 Spomky-Labs

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
CBOR for PHP
============

![Build Status](https://github.com/Spomky-Labs/cbor-php/workflows/Integrate/badge.svg)

[![Latest Stable Version](https://poser.pugx.org/Spomky-Labs/cbor-php/v)](//packagist.org/packages/Spomky-Labs/cbor-php)
[![Total Downloads](https://poser.pugx.org/Spomky-Labs/cbor-php/downloads)](//packagist.org/packages/Spomky-Labs/cbor-php)
[![Latest Unstable Version](https://poser.pugx.org/Spomky-Labs/cbor-php/v/unstable)](//packagist.org/packages/Spomky-Labs/cbor-php)
[![License](https://poser.pugx.org/Spomky-Labs/cbor-php/license)](//packagist.org/packages/Spomky-Labs/cbor-php)

# Scope

This library will help you to decode and create objects using the Concise Binary Object Representation (CBOR - [RFC8949](https://tools.ietf.org/html/rfc8949)).

# Installation

Install the library with Composer: `composer require spomky-labs/cbor-php`.

This project follows the [semantic versioning](http://semver.org/) strictly.

# Support

I bring solutions to your problems and answer your questions.

If you really love that project, and the work I have done or if you want I prioritize your issues, then you can help me out for a couple of :beers: or more!

[Become a sponsor](https://github.com/sponsors/Spomky)

Or

[![Become a Patreon](https://c5.patreon.com/external/logo/become_a_patron_button.png)](https://www.patreon.com/FlorentMorselli)

# Documentation

## Object Creation

This library supports all Major Types defined in the RFC8949 and has capabilities to support any kind of Tags (Major Type 6) and Other Objects (Major Type 7).

Each object have at least:

* a static method `create`. This method will correctly instantiate the object.
* can be converted into a binary string: `$object->__toString();` or `(string) $object`.

### Positive Integer (Major Type 0)

```php
<?php

use CBOR\UnsignedIntegerObject;

$object = UnsignedIntegerObject::create(10);
$object = UnsignedIntegerObject::create(1000);
$object = UnsignedIntegerObject::create(10000);
$object = UnsignedIntegerObject::createFromHex('0AFFEBFF');

echo bin2hex((string)$object); // 1a0affebff
```

### Negative Integer (Major Type 1)

```php
<?php

use CBOR\NegativeIntegerObject;

$object = NegativeIntegerObject::create(-10);
$object = NegativeIntegerObject::create(-1000);
$object = NegativeIntegerObject::create(-10000);
```

### Byte String / Indefinite Length Byte String (Major Type 2)

Byte String and Indefinite Length Byte String objects have the same major type but are handled by two different classes in this library.

```php
<?php

use CBOR\ByteStringObject; // Byte String
use CBOR\IndefiniteLengthByteStringObject; // Indefinite Length Byte String

// Create a Byte String with value "Hello"
$object = ByteStringObject::create('Hello');

// Create an Indefinite Length Byte String with value "Hello" ("He" + "" + "ll" + "o")
$object = IndefiniteLengthByteStringObject::create()
    ->append('He')
    ->append('')
    ->append('ll')
    ->append('o')
;
```

### Text String / Indefinite Length Text String (Major Type 3)

Text String and Indefinite Length Text String objects have the same major type but are handled by two different classes in this library.

```php
<?php

use CBOR\TextStringObject; // Text String
use CBOR\IndefiniteLengthTextStringObject; // Indefinite Length Text String

// Create a Text String with value "(｡◕‿◕｡)⚡"
$object = TextStringObject::create('(｡◕‿◕｡)⚡');

// Create an Indefinite Length Text String with value "(｡◕‿◕｡)⚡" ("(｡◕" + "" + "‿◕" + "｡)⚡")
$object = IndefiniteLengthTextStringObject::create()
    ->append('(｡◕')
    ->append('')
    ->append('‿◕')
    ->append('｡)⚡')
;
```

### List / Indefinite Length List (Major Type 4)

List and Indefinite Length List objects have the same major type but are handled by two different classes in this library.
Items in the List object can be any of CBOR Object type.

```php
<?php

use CBOR\ListObject; // List
use CBOR\IndefiniteLengthListObject; // Infinite List
use CBOR\TextStringObject;
use CBOR\UnsignedIntegerObject;

// Create a List with a single item
$object = ListObject::create()
    ->add(TextStringObject::create('(｡◕‿◕｡)⚡'))
;

// Create an Infinite List with several items
$object = IndefiniteLengthListObject::create()
    ->add(TextStringObject::create('(｡◕‿◕｡)⚡'))
    ->add(UnsignedIntegerObject::create(25))
;
```

### Map / Indefinite Length Map (Major Type 5)

Map and Indefinite Length Map objects have the same major type but are handled by two different classes in this library.
Keys and values in the Map object can be any of CBOR Object type.

**However, be really careful with keys. Please follow the recommendation hereunder:**

* Keys should not be duplicated
* Keys should be of type Positive or Negative Integer, (Indefinite Length)Byte String or (Indefinite Length)Text String. Other types may cause errors.

```php
<?php

use CBOR\MapObject; // Map
use CBOR\IndefiniteLengthMapObject; // Infinite Map
use CBOR\ByteStringObject;
use CBOR\TextStringObject;
use CBOR\UnsignedIntegerObject;
use CBOR\NegativeIntegerObject;

// Create a Map with a single item
$object = MapObject::create()
    ->add(UnsignedIntegerObject::create(25), TextStringObject::create('(｡◕‿◕｡)⚡'))
;

// Create an Infinite Map with several items
$object = IndefiniteLengthMapObject::create()
    ->append(ByteStringObject::create('A'), NegativeIntegerObject::create(-652))
    ->append(UnsignedIntegerObject::create(25), TextStringObject::create('(｡◕‿◕｡)⚡'))
;
```

### Tags (Major Type 6)

This library can support any kind of tags.
It comes with some of the thew described in the specification:

* Base 16 encoding
* Base 64 encoding
* Base 64 Url Safe encoding
* Big Float
* Decimal Fraction
* Epoch
* Timestamp
* Positive Big Integer
* Negative Big Integer

You can easily create your own tag by extending the abstract class `CBOR\TagObject`.
This library provides a `CBOR\Tag\GenericTag` class that can be used for any other unknown/unsupported tags.

```php
<?php

use CBOR\Tag\TimestampTag;
use CBOR\UnsignedIntegerObject;

// Create an unsigned object that represents the current timestamp
$object = UnsignedIntegerObject::create(time()); // e.g. 1525873787

//We tag the object with the Timestamp Tag
$taggedObject = TimestampTag::create($object); // Returns a \DateTimeImmutable object with timestamp at 1525873787
```

### Other Objects (Major Type 7)

This library can support any kind of "other objects".
It comes with some of the thew described in the specification:

* False
* True
* Null
* Undefined
* Half Precision Float
* Single Precision Float
* Double Precision Float
* Simple Value

You can easily create your own object by extending the abstract class `CBOR\OtherObject`.
This library provides a `CBOR\OtherObject\GenericTag` class that can be used for any other unknown/unsupported objects.

**Because PHP does not support an 'undefined' object, the normalization method will return `'undefined'`.**

```php
<?php

use CBOR\OtherObject\FalseObject;
use CBOR\OtherObject\NullObject;
use CBOR\OtherObject\UndefinedObject;

$object = FalseObject::create();
$object = NullObject::create();
$object = UndefinedObject::create();
```

## Example

```php
<?php

use CBOR\MapObject;
use CBOR\OtherObject\UndefinedObject;
use CBOR\TextStringObject;
use CBOR\ListObject;
use CBOR\NegativeIntegerObject;
use CBOR\UnsignedIntegerObject;
use CBOR\OtherObject\TrueObject;
use CBOR\OtherObject\FalseObject;
use CBOR\OtherObject\NullObject;
use CBOR\Tag\DecimalFractionTag;
use CBOR\Tag\TimestampTag;

$object = MapObject::create()
    ->add(
        TextStringObject::create('(｡◕‿◕｡)⚡'),
        ListObject::create([
            TrueObject::create(),
            FalseObject::create(),
            UndefinedObject::create(),
            DecimalFractionTag::createFromExponentAndMantissa(
                NegativeIntegerObject::create(-2),
                UnsignedIntegerObject::create(1234)
            ),
        ])
    )
    ->add(
        UnsignedIntegerObject::create(2000),
        NullObject::create()
    )
    ->add(
        TextStringObject::create('date'),
        TimestampTag::create(UnsignedIntegerObject::create(1577836800))
    )
;
```

The encoded result will be `0xa37428efbda1e29795e280bfe29795efbda129e29aa183f5f4c482211904d21907d0f66464617465c11a5e0be100`.

## Object Loading

If you want to load a CBOR encoded string, you just have to instantiate a `CBOR\Decoder` class.
This class does not need any argument.

```php
<?php

use CBOR\Decoder;

$decoder = Decoder::create();
```

If needed, you can define custom sets of Tag and Other Object support managers.

```php
<?php

use CBOR\Decoder;
use CBOR\OtherObject;
use CBOR\Tag;

$otherObjectManager = OtherObject\OtherObjectManager::create()
    ->add(OtherObject\SimpleObject::class)
    ->add(OtherObject\FalseObject::class)
    ->add(OtherObject\TrueObject::class)
    ->add(OtherObject\NullObject::class)
    ->add(OtherObject\UndefinedObject::class)
    ->add(OtherObject\HalfPrecisionFloatObject::class)
    ->add(OtherObject\SinglePrecisionFloatObject::class)
    ->add(OtherObject\DoublePrecisionFloatObject::class)
;

$tagManager = Tag\TagManager::create()
    ->add(Tag\DatetimeTag::class)
    ->add(Tag\TimestampTag::class)
    ->add(Tag\UnsignedBigIntegerTag::class)
    ->add(Tag\NegativeBigIntegerTag::class)
    ->add(Tag\DecimalFractionTag::class)
    ->add(Tag\BigFloatTag::class)
    ->add(Tag\Base64UrlEncodingTag::class)
    ->add(Tag\Base64EncodingTag::class)
    ->add(Tag\Base16EncodingTag::class)
;

$decoder = Decoder::create($tagManager, $otherObjectManager);
```

Then, the decoder will read the data you want to load.
The data has to be handled by an object that implements the `CBOR\Stream` interface.
This library provides a `CBOR\StringStream` class to stream the string.

```php
<?php

use CBOR\StringStream;

// CBOR object (in hex for the example)
$data = hex2bin('fb3fd5555555555555');

// String Stream
$stream = StringStream::create($data);

// Load the data
$object = $decoder->decode($stream); // Return a CBOR\OtherObject\DoublePrecisionFloatObject class with normalized value ~0.3333 (1/3)
```

# Contributing

Requests for new features, bug fixed and all other ideas to make this project useful are welcome.
The best contribution you could provide is by fixing the [opened issues where help is wanted](https://github.com/Spomky-Labs/cbor-php/issues?q=is%3Aissue+is%3Aopen+label%3A%22help+wanted%22).

Please report all issues in [the main repository](https://github.com/Spomky-Labs/cbor-php/issues).

Please make sure to [follow these best practices](.github/CONTRIBUTING.md).

# Licence

This project is release under [MIT licence](LICENSE).
{
    "name": "spomky-labs\/cbor-php",
    "type": "library",
    "license": "MIT",
    "keywords": [
        "CBOR",
        "Concise Binary Object Representation",
        "RFC7049"
    ],
    "description": "CBOR Encoder\/Decoder for PHP",
    "authors": [
        {
            "name": "Florent Morselli",
            "homepage": "https:\/\/github.com\/Spomky"
        },
        {
            "name": "All contributors",
            "homepage": "https:\/\/github.com\/Spomky-Labs\/cbor-php\/contributors"
        }
    ],
    "autoload": {
        "psr-4": {
            "_ContaoManager\\CBOR\\": "src\/"
        }
    },
    "autoload-dev": {
        "psr-4": {
            "_ContaoManager\\CBOR\\Test\\": "tests\/"
        }
    },
    "require": {
        "php": ">=8.0",
        "ext-mbstring": "*",
        "brick\/math": "^0.9|^0.10|^0.11|^0.12|^0.13|^0.14|^0.15|^0.16|^0.17"
    },
    "require-dev": {
        "ext-json": "*",
        "roave\/security-advisories": "dev-latest",
        "symfony\/error-handler": "^6.4|^7.1|^8.0",
        "symfony\/var-dumper": "^6.4|^7.1|^8.0"
    },
    "config": {
        "sort-packages": true,
        "allow-plugins": {
            "phpstan\/extension-installer": true,
            "infection\/extension-installer": true
        }
    },
    "suggest": {
        "ext-gmp": "GMP or BCMath extensions will drastically improve the library performance",
        "ext-bcmath": "GMP or BCMath extensions will drastically improve the library performance. BCMath extension needed to handle the Big Float and Decimal Fraction Tags"
    }
}# Security Release Process

Webauthn Framework is devoted in providing the best experience for all developers who want to implement Webauthn in their applications.
Spomky-Labs has adopted this security disclosure and response policy to ensure we responsibly handle critical issues.

## Supported Versions

The Webauthn Framework project maintains release branches for the three most recent minor releases.
Applicable fixes, including security fixes, may be backported to those three release branches, depending on severity and feasibility. Please refer to [RELEASES.md](RELEASES.md) for details.

## Reporting a Vulnerability - Private Disclosure Process

Security is of the highest importance and all security vulnerabilities or suspected security vulnerabilities should be reported to Webauthn Framework privately, to minimize attacks against current users of the Webauthn Framework before they are fixed.
Vulnerabilities will be investigated and patched on the next patch (or minor) release as soon as possible.
This information could be kept entirely internal to the project.

If you know of a publicly disclosed security vulnerability for the Webauthn Framework, please **IMMEDIATELY** contact security@spomky-labs.com to inform the Webauthn Framework Security Team.

**IMPORTANT: Do not file public issues on GitHub for security vulnerabilities**

To report a vulnerability or a security-related issue, please email the private address security@spomky-labs.com with the details of the vulnerability.
The email will be fielded by the Webauthn Framework Security Team, which is made up of the Webauthn Framework maintainers who have committer and release permissions.
Do not report non-security-impacting bugs through this channel. Use [GitHub issues](https://github.com/web-auth/webauthn-framework/issues/new/choose) instead.

Emails can be encrypted if you wish to share the vulnerability details securely.
The Webauthn Framework Security Team's PGP is key is available on the [PGP keyservers](https://keys.openpgp.org/search?q=security%40spomky-labs.com).

### Proposed Email Content

Provide a descriptive subject line and in the body of the email include the following information:

-   Basic identity information, such as your name and your affiliation or company.
-   Detailed steps to reproduce the vulnerability (POC scripts, screenshots, and compressed packet captures are all helpful to us).
-   Description of the effects of the vulnerability on Webauthn Framework and the related hardware and software configurations, so that the Webauthn Framework Security Team can reproduce it.
-   How the vulnerability affects Webauthn Framework usage and an estimation of the attack surface, if there is one.
-   List other projects or dependencies that were used in conjunction with Webauthn Framework to produce the vulnerability.

## When to report a vulnerability

-   When you think Webauthn Framework has a potential security vulnerability.
-   When you suspect a potential vulnerability, but you are unsure that it impacts Webauthn Framework.
-   When you know of or suspect a potential vulnerability on another project that is used by Webauthn Framework. For example Webauthn Framework has a dependency on Docker, PGSql, Redis, Notary, Trivy, etc.

## Patch, Release, and Disclosure

The Webauthn Framework Security Team will respond to vulnerability reports as follows:

1.  The Security Team will investigate the vulnerability and determine its effects and criticality.
2.  If the issue is not deemed to be a vulnerability, the Security Team will follow up with a detailed reason for rejection.
3.  The Security Team will initiate a conversation with the reporter as soon as possible.
4.  If a vulnerability is acknowledged and the timeline for a fix is determined, the Security Team will work on a plan to communicate with the appropriate community, including identifying mitigating steps that affected users can take to protect themselves until the fix is rolled out.
5.  The Security Team will work on fixing the vulnerability and perform internal testing before preparing to roll out the fix.
6.  A public disclosure date is negotiated by the Webauthn Framework Security Team and the bug submitter. We prefer to fully disclose the bug as soon as possible once a user mitigation or patch is available. It is reasonable to delay disclosure when the bug or the fix is not yet fully understood, the solution is not well-tested, or for distributor coordination. The timeframe for disclosure is from immediate (especially if it’s already publicly known) to a few weeks. For a critical vulnerability with a straightforward mitigation, we expect report date to public disclosure date to be on the order of 14 business days. The Webauthn Framework Security Team holds the final say when setting a public disclosure date.
7.  Once the fix is confirmed, the Security Team will patch the vulnerability in the next patch or minor release, and backport a patch release into all earlier supported releases. Upon release of the patched version of Webauthn Framework, we will follow the **Public Disclosure Process**.

### Public Disclosure Process

The Security Team publishes a public [advisory](https://github.com/web-auth/webauthn-framework/security/advisories) to the Webauthn Framework community via GitHub. In most cases, additional communication via Twitter, blog and other channels will assist in educating Webauthn Framework users and rolling out the patched release to affected users.

The Security Team will also publish any mitigating steps users can take until the fix can be applied to their Webauthn Framework instances. Webauthn Framework distributors will handle creating and publishing their own security advisories.

## Mailing lists

-   Use security@spomky-labs.com to report security concerns to the Webauthn Framework Security Team, who uses the list to privately discuss security issues and fixes prior to disclosure.

## Early Disclosure to Webauthn Framework Distributors List

This private list is intended to be used primarily to provide actionable information to multiple distributor projects at once. This list is not intended to inform individuals about security issues.

## Confidentiality, integrity and availability

We consider vulnerabilities leading to the compromise of data confidentiality, elevation of privilege, or integrity to be our highest priority concerns.
Availability, in particular in areas relating to DoS and resource exhaustion, is also a serious security concern.
The Webauthn Framework Security Team takes all vulnerabilities, potential vulnerabilities, and suspected vulnerabilities seriously and will investigate them in an urgent and expeditious manner.
<?php

declare (strict_types=1);
namespace _ContaoManager\CBOR;

use InvalidArgumentException;
use RuntimeException;
use function sprintf;
use function strlen;
final class StringStream implements Stream
{
    /**
     * @var resource
     */
    private $resource;
    public function __construct(string $data)
    {
        $resource = fopen('php://memory', 'rb+');
        if ($resource === \false) {
            throw new RuntimeException('Unable to open the memory');
        }
        $result = fwrite($resource, $data);
        if ($result === \false) {
            throw new RuntimeException('Unable to write the memory');
        }
        $result = rewind($resource);
        if ($result === \false) {
            throw new RuntimeException('Unable to rewind the memory');
        }
        $this->resource = $resource;
    }
    public static function create(string $data): self
    {
        return new self($data);
    }
    public function read(int $length): string
    {
        if ($length === 0) {
            return '';
        }
        $alreadyRead = 0;
        $data = '';
        while ($alreadyRead < $length) {
            $left = $length - $alreadyRead;
            $sizeToRead = $left < 1024 && $left > 0 ? $left : 1024;
            $newData = fread($this->resource, $sizeToRead);
            $alreadyRead += $sizeToRead;
            if ($newData === \false) {
                throw new RuntimeException('Unable to read the memory');
            }
            if (strlen($newData) < $sizeToRead) {
                throw new InvalidArgumentException(sprintf('Out of range. Expected: %d, read: %d.', $length, strlen($data)));
            }
            $data .= $newData;
        }
        if (strlen($data) !== $length) {
            throw new InvalidArgumentException(sprintf('Out of range. Expected: %d, read: %d.', $length, strlen($data)));
        }
        return $data;
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\CBOR;

use _ContaoManager\CBOR\OtherObject\DoublePrecisionFloatObject;
use _ContaoManager\CBOR\OtherObject\FalseObject;
use _ContaoManager\CBOR\OtherObject\NullObject;
use _ContaoManager\CBOR\OtherObject\SinglePrecisionFloatObject;
use _ContaoManager\CBOR\OtherObject\TrueObject;
use InvalidArgumentException;
use function is_array;
use function is_float;
use function is_int;
use function is_string;
final class Encoder implements EncoderInterface
{
    public const FLOAT_FORMAT_SINGLE_PRECISION = 0b1;
    public const INDEFINITE_BYTE_STRING_LENGTH = 0b10;
    public const INDEFINITE_TEXT_STRING_LENGTH = 0b100;
    public const INDEFINITE_LIST_LENGTH = 0b1000;
    public const INDEFINITE_MAP_LENGTH = 0b10000;
    public function encode(mixed $data, int $options = 0): string
    {
        return (string) $this->processData($data, $options);
    }
    private function processData(mixed $data, int $option): CBORObject
    {
        return match (\true) {
            $data instanceof CBORObject => $data,
            is_string($data) => preg_match('//u', $data) === 1 ? $this->processTextString($data, $option) : $this->processByteString($data, $option),
            is_array($data) => array_is_list($data) ? $this->processList($data, $option) : $this->processMap($data, $option),
            is_int($data) => $data < 0 ? NegativeIntegerObject::create($data) : UnsignedIntegerObject::create($data),
            is_float($data) => $this->processFloat($data, $option),
            $data === null => NullObject::create(),
            $data === \false => FalseObject::create(),
            $data === \true => TrueObject::create(),
            default => throw new InvalidArgumentException('Unsupported data type'),
        };
    }
    /**
     * @param array<array-key, mixed> $data
     */
    private function processList(array $data, int $option): ListObject|IndefiniteLengthListObject
    {
        $isIndefinite = 0 !== ($option & self::INDEFINITE_LIST_LENGTH);
        $list = $isIndefinite ? IndefiniteLengthListObject::create() : ListObject::create();
        foreach ($data as $item) {
            $list->add($this->processData($item, $option));
        }
        return $list;
    }
    /**
     * @param array<array-key, mixed> $data
     */
    private function processMap(array $data, int $option): MapObject|IndefiniteLengthMapObject
    {
        $isIndefinite = 0 !== ($option & self::INDEFINITE_MAP_LENGTH);
        $map = $isIndefinite ? IndefiniteLengthMapObject::create() : MapObject::create();
        foreach ($data as $key => $value) {
            $map->add($this->processData($key, $option), $this->processData($value, $option));
        }
        return $map;
    }
    private function processFloat(float $data, int $option): SinglePrecisionFloatObject|DoublePrecisionFloatObject
    {
        $isSinglePrecisionFloat = 0 !== ($option & self::FLOAT_FORMAT_SINGLE_PRECISION);
        return match (\true) {
            $isSinglePrecisionFloat => SinglePrecisionFloatObject::createFromFloat($data),
            default => DoublePrecisionFloatObject::createFromFloat($data),
        };
    }
    private function processTextString(string $data, int $option): TextStringObject|IndefiniteLengthTextStringObject
    {
        $isIndefinite = 0 !== ($option & self::INDEFINITE_TEXT_STRING_LENGTH);
        $cbor = TextStringObject::create($data);
        if (!$isIndefinite) {
            return $cbor;
        }
        return IndefiniteLengthTextStringObject::create()->add($cbor);
    }
    private function processByteString(string $data, int $option): ByteStringObject|IndefiniteLengthByteStringObject
    {
        $isIndefinite = 0 !== ($option & self::INDEFINITE_BYTE_STRING_LENGTH);
        $cbor = ByteStringObject::create($data);
        if (!$isIndefinite) {
            return $cbor;
        }
        return IndefiniteLengthByteStringObject::create()->add($cbor);
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\CBOR\OtherObject;

use _ContaoManager\CBOR\Normalizable;
use _ContaoManager\CBOR\OtherObject as Base;
final class TrueObject extends Base implements Normalizable
{
    public function __construct()
    {
        parent::__construct(self::OBJECT_TRUE, null);
    }
    public static function create(): self
    {
        return new self();
    }
    public static function supportedAdditionalInformation(): array
    {
        return [self::OBJECT_TRUE];
    }
    public static function createFromLoadedData(int $additionalInformation, ?string $data): Base
    {
        return new self();
    }
    public function normalize(): bool
    {
        return \true;
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\CBOR\OtherObject;

use _ContaoManager\CBOR\OtherObject as Base;
final class BreakObject extends Base
{
    public function __construct()
    {
        parent::__construct(self::OBJECT_BREAK, null);
    }
    public static function create(): self
    {
        return new self();
    }
    public static function supportedAdditionalInformation(): array
    {
        return [self::OBJECT_BREAK];
    }
    public static function createFromLoadedData(int $additionalInformation, ?string $data): Base
    {
        return new self();
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\CBOR\OtherObject;

use _ContaoManager\CBOR\CBORObject;
interface OtherObjectInterface extends CBORObject
{
    /**
     * @return int[]
     */
    public static function supportedAdditionalInformation(): array;
    public static function createFromLoadedData(int $additionalInformation, ?string $data): self;
}
<?php

declare (strict_types=1);
namespace _ContaoManager\CBOR\OtherObject;

use _ContaoManager\Brick\Math\BigInteger;
use _ContaoManager\CBOR\OtherObject as Base;
use _ContaoManager\CBOR\Utils;
use const INF;
use InvalidArgumentException;
use const NAN;
use function strlen;
final class SinglePrecisionFloatObject extends Base
{
    public static function supportedAdditionalInformation(): array
    {
        return [self::OBJECT_SINGLE_PRECISION_FLOAT];
    }
    public static function createFromFloat(float $number): self
    {
        $value = match (\true) {
            is_nan($number) => hex2bin('7FC00000'),
            is_infinite($number) && $number > 0 => hex2bin('7F800000'),
            is_infinite($number) && $number < 0 => hex2bin('FF800000'),
            default => (fn(): string => unpack('S', "\x01\x00")[1] === 1 ? strrev(pack('f', $number)) : pack('f', $number))(),
        };
        return new self(self::OBJECT_SINGLE_PRECISION_FLOAT, $value);
    }
    public static function createFromLoadedData(int $additionalInformation, ?string $data): Base
    {
        return new self($additionalInformation, $data);
    }
    public static function create(string $value): self
    {
        if (strlen($value) !== 4) {
            throw new InvalidArgumentException('The value is not a valid single precision floating point');
        }
        return new self(self::OBJECT_SINGLE_PRECISION_FLOAT, $value);
    }
    public function normalize(): float|int
    {
        $exponent = $this->getExponent();
        $mantissa = $this->getMantissa();
        $sign = $this->getSign();
        if ($exponent === 0) {
            $val = $mantissa * 2 ** -(126 + 23);
        } elseif ($exponent !== 0b11111111) {
            $val = ($mantissa + (1 << 23)) * 2 ** ($exponent - (127 + 23));
        } else {
            $val = $mantissa === 0 ? INF : NAN;
        }
        return $sign * $val;
    }
    public function getExponent(): int
    {
        $data = $this->data;
        Utils::assertString($data, 'Invalid data');
        return Utils::binToBigInteger($data)->shiftedRight(23)->and(Utils::hexToBigInteger('ff'))->toInt();
    }
    public function getMantissa(): int
    {
        $data = $this->data;
        Utils::assertString($data, 'Invalid data');
        return Utils::binToBigInteger($data)->and(Utils::hexToBigInteger('7fffff'))->toInt();
    }
    public function getSign(): int
    {
        $data = $this->data;
        Utils::assertString($data, 'Invalid data');
        $sign = Utils::binToBigInteger($data)->shiftedRight(31);
        return $sign->isEqualTo(BigInteger::one()) ? -1 : 1;
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\CBOR\OtherObject;

use _ContaoManager\CBOR\OtherObject as Base;
use InvalidArgumentException;
use function ord;
final class GenericObject extends Base
{
    public static function supportedAdditionalInformation(): array
    {
        return [];
    }
    public static function createFromLoadedData(int $additionalInformation, ?string $data): Base
    {
        if ($data !== null && ord($data) < 32) {
            throw new InvalidArgumentException('Invalid simple value. Content data should not be present.');
        }
        return new self($additionalInformation, $data);
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\CBOR\OtherObject;

use _ContaoManager\CBOR\Normalizable;
use _ContaoManager\CBOR\OtherObject as Base;
final class FalseObject extends Base implements Normalizable
{
    public function __construct()
    {
        parent::__construct(self::OBJECT_FALSE, null);
    }
    public static function create(): self
    {
        return new self();
    }
    public static function supportedAdditionalInformation(): array
    {
        return [self::OBJECT_FALSE];
    }
    public static function createFromLoadedData(int $additionalInformation, ?string $data): Base
    {
        return new self();
    }
    public function normalize(): bool
    {
        return \false;
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\CBOR\OtherObject;

use _ContaoManager\CBOR\OtherObject as Base;
final class UndefinedObject extends Base
{
    public function __construct()
    {
        parent::__construct(self::OBJECT_UNDEFINED, null);
    }
    public static function create(): self
    {
        return new self();
    }
    public static function supportedAdditionalInformation(): array
    {
        return [self::OBJECT_UNDEFINED];
    }
    public static function createFromLoadedData(int $additionalInformation, ?string $data): Base
    {
        return new self();
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\CBOR\OtherObject;

use _ContaoManager\Brick\Math\BigInteger;
use _ContaoManager\CBOR\Normalizable;
use _ContaoManager\CBOR\OtherObject as Base;
use _ContaoManager\CBOR\Utils;
use const INF;
use InvalidArgumentException;
use const NAN;
use function strlen;
final class DoublePrecisionFloatObject extends Base implements Normalizable
{
    public static function supportedAdditionalInformation(): array
    {
        return [self::OBJECT_DOUBLE_PRECISION_FLOAT];
    }
    public static function createFromFloat(float $number): self
    {
        $value = match (\true) {
            is_nan($number) => hex2bin('7FF8000000000000'),
            is_infinite($number) && $number > 0 => hex2bin('7FF0000000000000'),
            is_infinite($number) && $number < 0 => hex2bin('FFF0000000000000'),
            default => (fn(): string => unpack('S', "\x01\x00")[1] === 1 ? strrev(pack('d', $number)) : pack('d', $number))(),
        };
        return new self(self::OBJECT_DOUBLE_PRECISION_FLOAT, $value);
    }
    public static function createFromLoadedData(int $additionalInformation, ?string $data): Base
    {
        return new self($additionalInformation, $data);
    }
    public static function create(string $value): self
    {
        if (strlen($value) !== 8) {
            throw new InvalidArgumentException('The value is not a valid double precision floating point');
        }
        return new self(self::OBJECT_DOUBLE_PRECISION_FLOAT, $value);
    }
    public function normalize(): float|int
    {
        $exponent = $this->getExponent();
        $mantissa = $this->getMantissa();
        $sign = $this->getSign();
        if ($exponent === 0) {
            $val = $mantissa * 2 ** -(1022 + 52);
        } elseif ($exponent !== 0b11111111111) {
            $val = ($mantissa + (1 << 52)) * 2 ** ($exponent - (1023 + 52));
        } else {
            $val = $mantissa === 0 ? INF : NAN;
        }
        return $sign * $val;
    }
    public function getExponent(): int
    {
        $data = $this->data;
        Utils::assertString($data, 'Invalid data');
        return Utils::binToBigInteger($data)->shiftedRight(52)->and(Utils::hexToBigInteger('7ff'))->toInt();
    }
    public function getMantissa(): int
    {
        $data = $this->data;
        Utils::assertString($data, 'Invalid data');
        return Utils::binToBigInteger($data)->and(Utils::hexToBigInteger('fffffffffffff'))->toInt();
    }
    public function getSign(): int
    {
        $data = $this->data;
        Utils::assertString($data, 'Invalid data');
        $sign = Utils::binToBigInteger($data)->shiftedRight(63);
        return $sign->isEqualTo(BigInteger::one()) ? -1 : 1;
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\CBOR\OtherObject;

interface OtherObjectManagerInterface
{
    public function createObjectForValue(int $value, ?string $data): OtherObjectInterface;
}
<?php

declare (strict_types=1);
namespace _ContaoManager\CBOR\OtherObject;

use _ContaoManager\Brick\Math\BigInteger;
use _ContaoManager\CBOR\Normalizable;
use _ContaoManager\CBOR\OtherObject as Base;
use _ContaoManager\CBOR\Utils;
use const INF;
use InvalidArgumentException;
use const NAN;
use function strlen;
final class HalfPrecisionFloatObject extends Base implements Normalizable
{
    public static function supportedAdditionalInformation(): array
    {
        return [self::OBJECT_HALF_PRECISION_FLOAT];
    }
    public static function createFromLoadedData(int $additionalInformation, ?string $data): Base
    {
        return new self($additionalInformation, $data);
    }
    public static function create(string $value): self
    {
        if (strlen($value) !== 2) {
            throw new InvalidArgumentException('The value is not a valid half precision floating point');
        }
        return new self(self::OBJECT_HALF_PRECISION_FLOAT, $value);
    }
    public function normalize(): float|int
    {
        $exponent = $this->getExponent();
        $mantissa = $this->getMantissa();
        $sign = $this->getSign();
        if ($exponent === 0) {
            $val = $mantissa * 2 ** -24;
        } elseif ($exponent !== 0b11111) {
            $val = ($mantissa + (1 << 10)) * 2 ** ($exponent - 25);
        } else {
            $val = $mantissa === 0 ? INF : NAN;
        }
        return $sign * $val;
    }
    public function getExponent(): int
    {
        $data = $this->data;
        Utils::assertString($data, 'Invalid data');
        return Utils::binToBigInteger($data)->shiftedRight(10)->and(Utils::hexToBigInteger('1f'))->toInt();
    }
    public function getMantissa(): int
    {
        $data = $this->data;
        Utils::assertString($data, 'Invalid data');
        return Utils::binToBigInteger($data)->and(Utils::hexToBigInteger('3ff'))->toInt();
    }
    public function getSign(): int
    {
        $data = $this->data;
        Utils::assertString($data, 'Invalid data');
        $sign = Utils::binToBigInteger($data)->shiftedRight(15);
        return $sign->isEqualTo(BigInteger::one()) ? -1 : 1;
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\CBOR\OtherObject;

use _ContaoManager\CBOR\Normalizable;
use _ContaoManager\CBOR\OtherObject as Base;
use _ContaoManager\CBOR\Utils;
use function chr;
use InvalidArgumentException;
use function ord;
use function strlen;
final class SimpleObject extends Base implements Normalizable
{
    public static function supportedAdditionalInformation(): array
    {
        return [...range(0, 19), 24];
    }
    public static function create(int $value): self|FalseObject|TrueObject|NullObject|UndefinedObject
    {
        switch (\true) {
            case $value >= 0 && $value <= 19:
                return new self($value, null);
            case $value === 20:
                return FalseObject::create();
            case $value === 21:
                return TrueObject::create();
            case $value === 22:
                return NullObject::create();
            case $value === 23:
                return UndefinedObject::create();
            case $value <= 31:
                throw new InvalidArgumentException('Invalid simple value. Shall be between 32 and 255.');
            case $value <= 255:
                return new self(24, chr($value));
            default:
                throw new InvalidArgumentException('The value is not a valid simple value.');
        }
    }
    public static function createFromLoadedData(int $additionalInformation, ?string $data): Base
    {
        if ($additionalInformation === 24) {
            if ($data === null) {
                throw new InvalidArgumentException('Invalid simple value. Content data is missing.');
            }
            if (strlen($data) !== 1) {
                throw new InvalidArgumentException('Invalid simple value. Content data is too long.');
            }
            if (ord($data) < 32) {
                throw new InvalidArgumentException('Invalid simple value. Content data must be between 32 and 255.');
            }
        } elseif ($additionalInformation < 20) {
            if ($data !== null) {
                throw new InvalidArgumentException('Invalid simple value. Content data should not be present.');
            }
        }
        return new self($additionalInformation, $data);
    }
    public function normalize(): int
    {
        if ($this->data === null) {
            return $this->getAdditionalInformation();
        }
        return Utils::binToInt($this->data);
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\CBOR\OtherObject;

use _ContaoManager\CBOR\Normalizable;
use _ContaoManager\CBOR\OtherObject as Base;
final class NullObject extends Base implements Normalizable
{
    public function __construct()
    {
        parent::__construct(self::OBJECT_NULL, null);
    }
    public static function create(): self
    {
        return new self();
    }
    public static function supportedAdditionalInformation(): array
    {
        return [self::OBJECT_NULL];
    }
    public static function createFromLoadedData(int $additionalInformation, ?string $data): Base
    {
        return new self();
    }
    public function normalize(): ?string
    {
        return null;
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\CBOR\OtherObject;

use function array_key_exists;
use InvalidArgumentException;
final class OtherObjectManager implements OtherObjectManagerInterface
{
    /**
     * @param  class-string<OtherObjectInterface>[] $classes
     */
    public function __construct(private array $classes = [])
    {
    }
    /**
     * @param  class-string<OtherObjectInterface>[] $classes
     */
    public static function create(array $classes = []): self
    {
        return new self($classes);
    }
    /**
     * @param class-string<OtherObjectInterface> $class
     */
    public function add(string $class): self
    {
        foreach ($class::supportedAdditionalInformation() as $ai) {
            if ($ai < 0) {
                throw new InvalidArgumentException('Invalid additional information.');
            }
            $this->classes[$ai] = $class;
        }
        return $this;
    }
    /**
     * @return class-string<OtherObjectInterface>
     */
    public function getClassForValue(int $value): string
    {
        return array_key_exists($value, $this->classes) ? $this->classes[$value] : GenericObject::class;
    }
    public function createObjectForValue(int $value, ?string $data): OtherObjectInterface
    {
        $class = $this->getClassForValue($value);
        return $class::createFromLoadedData($value, $data);
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\CBOR;

interface DecoderInterface
{
    public function decode(Stream $stream): CBORObject;
}
<?php

declare (strict_types=1);
namespace _ContaoManager\CBOR;

use function strlen;
/**
 * @see \CBOR\Test\ByteStringObjectTest
 */
final class ByteStringObject extends AbstractCBORObject implements Normalizable
{
    private const MAJOR_TYPE = self::MAJOR_TYPE_BYTE_STRING;
    private string $value;
    private ?string $length;
    public function __construct(string $data)
    {
        [$additionalInformation, $length] = LengthCalculator::getLengthOfString($data);
        parent::__construct(self::MAJOR_TYPE, $additionalInformation);
        $this->length = $length;
        $this->value = $data;
    }
    public function __toString(): string
    {
        $result = parent::__toString();
        $result .= $this->length ?? '';
        return $result . $this->value;
    }
    public static function create(string $data): self
    {
        return new self($data);
    }
    public function getValue(): string
    {
        return $this->value;
    }
    public function getLength(): int
    {
        return strlen($this->value);
    }
    public function normalize(): string
    {
        return $this->value;
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\CBOR;

/**
 * @see \CBOR\Test\IndefiniteLengthTextStringObjectTest
 */
final class IndefiniteLengthTextStringObject extends AbstractCBORObject implements Normalizable
{
    private const MAJOR_TYPE = self::MAJOR_TYPE_TEXT_STRING;
    private const ADDITIONAL_INFORMATION = self::LENGTH_INDEFINITE;
    /**
     * @var TextStringObject[]
     */
    private array $data = [];
    public function __construct()
    {
        parent::__construct(self::MAJOR_TYPE, self::ADDITIONAL_INFORMATION);
    }
    public function __toString(): string
    {
        $result = parent::__toString();
        foreach ($this->data as $object) {
            $result .= (string) $object;
        }
        return $result . "\xff";
    }
    public static function create(string ...$chunks): self
    {
        $object = new self();
        foreach ($chunks as $chunk) {
            $object->append($chunk);
        }
        return $object;
    }
    public function add(TextStringObject $chunk): self
    {
        $this->data[] = $chunk;
        return $this;
    }
    public function append(string $chunk): self
    {
        $this->add(TextStringObject::create($chunk));
        return $this;
    }
    public function getValue(): string
    {
        $result = '';
        foreach ($this->data as $object) {
            $result .= $object->getValue();
        }
        return $result;
    }
    public function getLength(): int
    {
        $length = 0;
        foreach ($this->data as $object) {
            $length += $object->getLength();
        }
        return $length;
    }
    public function normalize(): string
    {
        $result = '';
        foreach ($this->data as $object) {
            $result .= $object->normalize();
        }
        return $result;
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\CBOR;

use _ContaoManager\CBOR\Tag\TagInterface;
use InvalidArgumentException;
abstract class Tag extends AbstractCBORObject implements TagInterface
{
    private const MAJOR_TYPE = self::MAJOR_TYPE_TAG;
    public function __construct(int $additionalInformation, protected ?string $data, protected CBORObject $object)
    {
        parent::__construct(self::MAJOR_TYPE, $additionalInformation);
    }
    public function __toString(): string
    {
        $result = parent::__toString();
        if ($this->data !== null) {
            $result .= $this->data;
        }
        return $result . $this->object;
    }
    public function getData(): ?string
    {
        return $this->data;
    }
    public function getValue(): CBORObject
    {
        return $this->object;
    }
    /**
     * @return array{int, null|string}
     */
    protected static function determineComponents(int $tag): array
    {
        switch (\true) {
            case $tag < 0:
                throw new InvalidArgumentException('The value must be a positive integer.');
            case $tag < 24:
                return [$tag, null];
            case $tag < 0xff:
                return [24, self::hex2bin(dechex($tag))];
            case $tag < 0xffff:
                return [25, self::hex2bin(dechex($tag))];
            case $tag < 0xffffffff:
                return [26, self::hex2bin(dechex($tag))];
            default:
                throw new InvalidArgumentException('Out of range. Please use PositiveBigIntegerTag tag with ByteStringObject object instead.');
        }
    }
    private static function hex2bin(string $data): string
    {
        $result = hex2bin($data);
        if ($result === \false) {
            throw new InvalidArgumentException('Unable to convert the data');
        }
        return $result;
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\CBOR;

use _ContaoManager\CBOR\OtherObject\BreakObject;
use _ContaoManager\CBOR\OtherObject\DoublePrecisionFloatObject;
use _ContaoManager\CBOR\OtherObject\FalseObject;
use _ContaoManager\CBOR\OtherObject\HalfPrecisionFloatObject;
use _ContaoManager\CBOR\OtherObject\NullObject;
use _ContaoManager\CBOR\OtherObject\OtherObjectManager;
use _ContaoManager\CBOR\OtherObject\OtherObjectManagerInterface;
use _ContaoManager\CBOR\OtherObject\SimpleObject;
use _ContaoManager\CBOR\OtherObject\SinglePrecisionFloatObject;
use _ContaoManager\CBOR\OtherObject\TrueObject;
use _ContaoManager\CBOR\OtherObject\UndefinedObject;
use _ContaoManager\CBOR\Tag\Base16EncodingTag;
use _ContaoManager\CBOR\Tag\Base64EncodingTag;
use _ContaoManager\CBOR\Tag\Base64Tag;
use _ContaoManager\CBOR\Tag\Base64UrlEncodingTag;
use _ContaoManager\CBOR\Tag\Base64UrlTag;
use _ContaoManager\CBOR\Tag\BigFloatTag;
use _ContaoManager\CBOR\Tag\CBOREncodingTag;
use _ContaoManager\CBOR\Tag\CBORTag;
use _ContaoManager\CBOR\Tag\DatetimeTag;
use _ContaoManager\CBOR\Tag\DecimalFractionTag;
use _ContaoManager\CBOR\Tag\MimeTag;
use _ContaoManager\CBOR\Tag\NegativeBigIntegerTag;
use _ContaoManager\CBOR\Tag\TagManager;
use _ContaoManager\CBOR\Tag\TagManagerInterface;
use _ContaoManager\CBOR\Tag\TimestampTag;
use _ContaoManager\CBOR\Tag\UnsignedBigIntegerTag;
use _ContaoManager\CBOR\Tag\UriTag;
use InvalidArgumentException;
use function ord;
use RuntimeException;
use function sprintf;
use const STR_PAD_LEFT;
final class Decoder implements DecoderInterface
{
    private TagManagerInterface $tagObjectManager;
    private OtherObjectManagerInterface $otherTypeManager;
    public function __construct(?TagManagerInterface $tagObjectManager = null, ?OtherObjectManagerInterface $otherTypeManager = null)
    {
        $this->tagObjectManager = $tagObjectManager ?? $this->generateTagManager();
        $this->otherTypeManager = $otherTypeManager ?? $this->generateOtherObjectManager();
    }
    public static function create(?TagManagerInterface $tagObjectManager = null, ?OtherObjectManagerInterface $otherTypeManager = null): self
    {
        return new self($tagObjectManager, $otherTypeManager);
    }
    public function decode(Stream $stream): CBORObject
    {
        return $this->process($stream, \false);
    }
    private function process(Stream $stream, bool $breakable): CBORObject
    {
        $ib = ord($stream->read(1));
        $mt = $ib >> 5;
        $ai = $ib & 0b11111;
        $val = null;
        switch ($ai) {
            case CBORObject::LENGTH_1_BYTE:
            //24
            case CBORObject::LENGTH_2_BYTES:
            //25
            case CBORObject::LENGTH_4_BYTES:
            //26
            case CBORObject::LENGTH_8_BYTES:
                //27
                $val = $stream->read(2 ** ($ai & 0b111));
                break;
            case CBORObject::FUTURE_USE_1:
            //28
            case CBORObject::FUTURE_USE_2:
            //29
            case CBORObject::FUTURE_USE_3:
                //30
                throw new InvalidArgumentException(sprintf('Cannot parse the data. Found invalid Additional Information "%s" (%d).', str_pad(decbin($ai), 8, '0', STR_PAD_LEFT), $ai));
            case CBORObject::LENGTH_INDEFINITE:
                //31
                return $this->processInfinite($stream, $mt, $breakable);
        }
        return $this->processFinite($stream, $mt, $ai, $val);
    }
    private function processFinite(Stream $stream, int $mt, int $ai, ?string $val): CBORObject
    {
        switch ($mt) {
            case CBORObject::MAJOR_TYPE_UNSIGNED_INTEGER:
                //0
                return UnsignedIntegerObject::createObjectForValue($ai, $val);
            case CBORObject::MAJOR_TYPE_NEGATIVE_INTEGER:
                //1
                return NegativeIntegerObject::createObjectForValue($ai, $val);
            case CBORObject::MAJOR_TYPE_BYTE_STRING:
                //2
                $length = $val === null ? $ai : Utils::binToInt($val);
                return ByteStringObject::create($stream->read($length));
            case CBORObject::MAJOR_TYPE_TEXT_STRING:
                //3
                $length = $val === null ? $ai : Utils::binToInt($val);
                return TextStringObject::create($stream->read($length));
            case CBORObject::MAJOR_TYPE_LIST:
                //4
                $object = ListObject::create();
                $nbItems = $val === null ? $ai : Utils::binToInt($val);
                for ($i = 0; $i < $nbItems; ++$i) {
                    $object->add($this->process($stream, \false));
                }
                return $object;
            case CBORObject::MAJOR_TYPE_MAP:
                //5
                $object = MapObject::create();
                $nbItems = $val === null ? $ai : Utils::binToInt($val);
                for ($i = 0; $i < $nbItems; ++$i) {
                    $object->add($this->process($stream, \false), $this->process($stream, \false));
                }
                return $object;
            case CBORObject::MAJOR_TYPE_TAG:
                //6
                return $this->tagObjectManager->createObjectForValue($ai, $val, $this->process($stream, \false));
            case CBORObject::MAJOR_TYPE_OTHER_TYPE:
                //7
                return $this->otherTypeManager->createObjectForValue($ai, $val);
            default:
                throw new RuntimeException(sprintf('Unsupported major type "%s" (%d).', str_pad(decbin($mt), 5, '0', STR_PAD_LEFT), $mt));
        }
    }
    private function processInfinite(Stream $stream, int $mt, bool $breakable): CBORObject
    {
        switch ($mt) {
            case CBORObject::MAJOR_TYPE_BYTE_STRING:
                //2
                $object = IndefiniteLengthByteStringObject::create();
                while (!($it = $this->process($stream, \true)) instanceof BreakObject) {
                    if (!$it instanceof ByteStringObject) {
                        throw new RuntimeException('Unable to parse the data. Infinite Byte String object can only get Byte String objects.');
                    }
                    $object->add($it);
                }
                return $object;
            case CBORObject::MAJOR_TYPE_TEXT_STRING:
                //3
                $object = IndefiniteLengthTextStringObject::create();
                while (!($it = $this->process($stream, \true)) instanceof BreakObject) {
                    if (!$it instanceof TextStringObject) {
                        throw new RuntimeException('Unable to parse the data. Infinite Text String object can only get Text String objects.');
                    }
                    $object->add($it);
                }
                return $object;
            case CBORObject::MAJOR_TYPE_LIST:
                //4
                $object = IndefiniteLengthListObject::create();
                $it = $this->process($stream, \true);
                while (!$it instanceof BreakObject) {
                    $object->add($it);
                    $it = $this->process($stream, \true);
                }
                return $object;
            case CBORObject::MAJOR_TYPE_MAP:
                //5
                $object = IndefiniteLengthMapObject::create();
                while (!($it = $this->process($stream, \true)) instanceof BreakObject) {
                    $object->add($it, $this->process($stream, \false));
                }
                return $object;
            case CBORObject::MAJOR_TYPE_OTHER_TYPE:
                //7
                if (!$breakable) {
                    throw new InvalidArgumentException('Cannot parse the data. No enclosing indefinite.');
                }
                return BreakObject::create();
            case CBORObject::MAJOR_TYPE_UNSIGNED_INTEGER:
            //0
            case CBORObject::MAJOR_TYPE_NEGATIVE_INTEGER:
            //1
            case CBORObject::MAJOR_TYPE_TAG:
            //6
            default:
                throw new InvalidArgumentException(sprintf('Cannot parse the data. Found infinite length for Major Type "%s" (%d).', str_pad(decbin($mt), 5, '0', STR_PAD_LEFT), $mt));
        }
    }
    private function generateTagManager(): TagManagerInterface
    {
        return TagManager::create([DatetimeTag::class, TimestampTag::class, UnsignedBigIntegerTag::class, NegativeBigIntegerTag::class, DecimalFractionTag::class, BigFloatTag::class, Base64UrlEncodingTag::class, Base64EncodingTag::class, Base16EncodingTag::class, CBOREncodingTag::class, UriTag::class, Base64UrlTag::class, Base64Tag::class, MimeTag::class, CBORTag::class]);
    }
    private function generateOtherObjectManager(): OtherObjectManagerInterface
    {
        return OtherObjectManager::create()->add(BreakObject::class)->add(SimpleObject::class)->add(FalseObject::class)->add(TrueObject::class)->add(NullObject::class)->add(UndefinedObject::class)->add(HalfPrecisionFloatObject::class)->add(SinglePrecisionFloatObject::class)->add(DoublePrecisionFloatObject::class);
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\CBOR;

interface EncoderInterface
{
    public function encode(mixed $data, int $options = 0): string;
}
<?php

declare (strict_types=1);
namespace _ContaoManager\CBOR;

use function assert;
use _ContaoManager\Brick\Math\BigInteger;
use InvalidArgumentException;
use const STR_PAD_LEFT;
final class UnsignedIntegerObject extends AbstractCBORObject implements Normalizable
{
    private const MAJOR_TYPE = self::MAJOR_TYPE_UNSIGNED_INTEGER;
    public function __construct(int $additionalInformation, private ?string $data)
    {
        parent::__construct(self::MAJOR_TYPE, $additionalInformation);
    }
    public function __toString(): string
    {
        $result = parent::__toString();
        if ($this->data !== null) {
            $result .= $this->data;
        }
        return $result;
    }
    public static function createObjectForValue(int $additionalInformation, ?string $data): self
    {
        return new self($additionalInformation, $data);
    }
    public static function create(int $value): self
    {
        return self::createFromString((string) $value);
    }
    public static function createFromHex(string $value): self
    {
        assert($value !== '', 'Value must not be empty');
        $integer = BigInteger::fromBase($value, 16);
        return self::createBigInteger($integer);
    }
    public static function createFromString(string $value): self
    {
        $integer = BigInteger::of($value);
        return self::createBigInteger($integer);
    }
    public function getMajorType(): int
    {
        return self::MAJOR_TYPE;
    }
    /**
     * @return numeric-string
     */
    public function getValue(): string
    {
        if ($this->data === null) {
            return (string) $this->additionalInformation;
        }
        $hex = bin2hex($this->data);
        assert($hex !== '', 'Value must not be empty');
        return BigInteger::fromBase($hex, 16)->toBase(10);
    }
    /**
     * @return numeric-string
     */
    public function normalize(): string
    {
        return $this->getValue();
    }
    private static function createBigInteger(BigInteger $integer): self
    {
        if ($integer->isLessThan(BigInteger::zero())) {
            throw new InvalidArgumentException('The value must be a positive integer.');
        }
        switch (\true) {
            case $integer->isLessThan(BigInteger::of(24)):
                $ai = $integer->toInt();
                $data = null;
                break;
            case $integer->isLessThan(BigInteger::fromBase('FF', 16)):
                $ai = 24;
                $data = self::hex2bin(str_pad($integer->toBase(16), 2, '0', STR_PAD_LEFT));
                break;
            case $integer->isLessThan(BigInteger::fromBase('FFFF', 16)):
                $ai = 25;
                $data = self::hex2bin(str_pad($integer->toBase(16), 4, '0', STR_PAD_LEFT));
                break;
            case $integer->isLessThan(BigInteger::fromBase('FFFFFFFF', 16)):
                $ai = 26;
                $data = self::hex2bin(str_pad($integer->toBase(16), 8, '0', STR_PAD_LEFT));
                break;
            default:
                throw new InvalidArgumentException('Out of range. Please use PositiveBigIntegerTag tag with ByteStringObject object instead.');
        }
        return new self($ai, $data);
    }
    private static function hex2bin(string $data): string
    {
        $result = hex2bin($data);
        if ($result === \false) {
            throw new InvalidArgumentException('Unable to convert the data');
        }
        return $result;
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\CBOR;

use function chr;
abstract class AbstractCBORObject implements CBORObject
{
    public function __construct(private int $majorType, protected int $additionalInformation)
    {
    }
    public function __toString(): string
    {
        return chr($this->majorType << 5 | $this->additionalInformation);
    }
    public function getMajorType(): int
    {
        return $this->majorType;
    }
    public function getAdditionalInformation(): int
    {
        return $this->additionalInformation;
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\CBOR;

interface Normalizable
{
    /**
     * @return mixed|null
     */
    public function normalize();
}
<?php

declare (strict_types=1);
namespace _ContaoManager\CBOR;

use _ContaoManager\Brick\Math\BigInteger;
use function chr;
use function count;
use InvalidArgumentException;
use const STR_PAD_LEFT;
use function strlen;
final class LengthCalculator
{
    /**
     * @return array{int, null|string}
     */
    public static function getLengthOfString(string $data): array
    {
        $length = strlen($data);
        return self::computeLength($length);
    }
    /**
     * @param array<int|string, mixed> $data
     *
     * @return array{int, null|string}
     */
    public static function getLengthOfArray(array $data): array
    {
        $length = count($data);
        return self::computeLength($length);
    }
    /**
     * @return array{int, null|string}
     */
    private static function computeLength(int $length): array
    {
        return match (\true) {
            $length <= 23 => [$length, null],
            $length <= 0xff => [24, chr($length)],
            $length <= 0xffff => [25, self::hex2bin(dechex($length))],
            $length <= 0xffffffff => [26, self::hex2bin(dechex($length))],
            BigInteger::of($length)->isLessThan(BigInteger::fromBase('FFFFFFFFFFFFFFFF', 16)) => [27, self::hex2bin(dechex($length))],
            default => [31, null],
        };
    }
    private static function hex2bin(string $data): string
    {
        $data = str_pad($data, (int) 2 ** ceil(log(strlen($data), 2)), '0', STR_PAD_LEFT);
        $result = hex2bin($data);
        if ($result === \false) {
            throw new InvalidArgumentException('Unable to convert the data');
        }
        return $result;
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\CBOR;

use _ContaoManager\CBOR\OtherObject\OtherObjectInterface;
abstract class OtherObject extends AbstractCBORObject implements OtherObjectInterface
{
    private const MAJOR_TYPE = self::MAJOR_TYPE_OTHER_TYPE;
    public function __construct(int $additionalInformation, protected ?string $data)
    {
        parent::__construct(self::MAJOR_TYPE, $additionalInformation);
    }
    public function __toString(): string
    {
        $result = parent::__toString();
        if ($this->data !== null) {
            $result .= $this->data;
        }
        return $result;
    }
    public function getContent(): ?string
    {
        return $this->data;
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\CBOR;

interface Stream
{
    public function read(int $length): string;
}
<?php

declare (strict_types=1);
namespace _ContaoManager\CBOR;

/**
 * @see \CBOR\Test\TextStringObjectTest
 */
final class TextStringObject extends AbstractCBORObject implements Normalizable
{
    private const MAJOR_TYPE = self::MAJOR_TYPE_TEXT_STRING;
    private ?string $length = null;
    private string $data;
    public function __construct(string $data)
    {
        [$additionalInformation, $length] = LengthCalculator::getLengthOfString($data);
        parent::__construct(self::MAJOR_TYPE, $additionalInformation);
        $this->data = $data;
        $this->length = $length;
    }
    public function __toString(): string
    {
        $result = parent::__toString();
        $result .= $this->length ?? '';
        return $result . $this->data;
    }
    public static function create(string $data): self
    {
        return new self($data);
    }
    public function getValue(): string
    {
        return $this->data;
    }
    public function getLength(): int
    {
        return mb_strlen($this->data, 'utf8');
    }
    public function normalize(): string
    {
        return $this->data;
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\CBOR;

/**
 * @see \CBOR\Test\IndefiniteLengthByteStringObjectTest
 */
final class IndefiniteLengthByteStringObject extends AbstractCBORObject implements Normalizable
{
    private const MAJOR_TYPE = self::MAJOR_TYPE_BYTE_STRING;
    private const ADDITIONAL_INFORMATION = self::LENGTH_INDEFINITE;
    /**
     * @var ByteStringObject[]
     */
    private array $chunks = [];
    public function __construct()
    {
        parent::__construct(self::MAJOR_TYPE, self::ADDITIONAL_INFORMATION);
    }
    public function __toString(): string
    {
        $result = parent::__toString();
        foreach ($this->chunks as $chunk) {
            $result .= (string) $chunk;
        }
        return $result . "\xff";
    }
    public static function create(string ...$chunks): self
    {
        $object = new self();
        foreach ($chunks as $chunk) {
            $object->append($chunk);
        }
        return $object;
    }
    public function add(ByteStringObject $chunk): self
    {
        $this->chunks[] = $chunk;
        return $this;
    }
    public function append(string $chunk): self
    {
        $this->add(ByteStringObject::create($chunk));
        return $this;
    }
    public function getValue(): string
    {
        $result = '';
        foreach ($this->chunks as $chunk) {
            $result .= $chunk->getValue();
        }
        return $result;
    }
    public function getLength(): int
    {
        $length = 0;
        foreach ($this->chunks as $chunk) {
            $length += $chunk->getLength();
        }
        return $length;
    }
    public function normalize(): string
    {
        $result = '';
        foreach ($this->chunks as $chunk) {
            $result .= $chunk->normalize();
        }
        return $result;
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\CBOR;

use function array_key_exists;
use ArrayAccess;
use ArrayIterator;
use InvalidArgumentException;
use Iterator;
use IteratorAggregate;
/**
 * @phpstan-implements ArrayAccess<int, CBORObject>
 * @phpstan-implements IteratorAggregate<int, CBORObject>
 * @final
 */
class IndefiniteLengthListObject extends AbstractCBORObject implements IteratorAggregate, Normalizable, ArrayAccess
{
    private const MAJOR_TYPE = self::MAJOR_TYPE_LIST;
    private const ADDITIONAL_INFORMATION = self::LENGTH_INDEFINITE;
    /**
     * @var CBORObject[]
     */
    private array $data = [];
    public function __construct()
    {
        parent::__construct(self::MAJOR_TYPE, self::ADDITIONAL_INFORMATION);
    }
    public function __toString(): string
    {
        $result = parent::__toString();
        foreach ($this->data as $object) {
            $result .= (string) $object;
        }
        return $result . "\xff";
    }
    public static function create(CBORObject ...$items): self
    {
        $object = new self();
        foreach ($items as $item) {
            $object->add($item);
        }
        return $object;
    }
    /**
     * @return mixed[]
     */
    public function normalize(): array
    {
        return array_map(static fn(CBORObject $object) => $object instanceof Normalizable ? $object->normalize() : $object, $this->data);
    }
    public function add(CBORObject $item): self
    {
        $this->data[] = $item;
        return $this;
    }
    public function has(int $index): bool
    {
        return array_key_exists($index, $this->data);
    }
    public function remove(int $index): self
    {
        if (!$this->has($index)) {
            return $this;
        }
        unset($this->data[$index]);
        $this->data = array_values($this->data);
        return $this;
    }
    public function get(int $index): CBORObject
    {
        if (!$this->has($index)) {
            throw new InvalidArgumentException('Index not found.');
        }
        return $this->data[$index];
    }
    public function set(int $index, CBORObject $object): self
    {
        if (!$this->has($index)) {
            throw new InvalidArgumentException('Index not found.');
        }
        $this->data[$index] = $object;
        return $this;
    }
    /**
     * @return Iterator<int, CBORObject>
     */
    public function getIterator(): Iterator
    {
        return new ArrayIterator($this->data);
    }
    public function offsetExists($offset): bool
    {
        return $this->has($offset);
    }
    public function offsetGet($offset): CBORObject
    {
        return $this->get($offset);
    }
    public function offsetSet($offset, $value): void
    {
        if ($offset === null) {
            $this->add($value);
            return;
        }
        $this->set($offset, $value);
    }
    public function offsetUnset($offset): void
    {
        $this->remove($offset);
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\CBOR;

use function array_key_exists;
use ArrayAccess;
use ArrayIterator;
use InvalidArgumentException;
use Iterator;
use IteratorAggregate;
/**
 * @phpstan-implements ArrayAccess<int, CBORObject>
 * @phpstan-implements IteratorAggregate<int, MapItem>
 * @final
 */
class IndefiniteLengthMapObject extends AbstractCBORObject implements IteratorAggregate, Normalizable, ArrayAccess
{
    private const MAJOR_TYPE = self::MAJOR_TYPE_MAP;
    private const ADDITIONAL_INFORMATION = self::LENGTH_INDEFINITE;
    /**
     * @var MapItem[]
     */
    private array $data = [];
    public function __construct()
    {
        parent::__construct(self::MAJOR_TYPE, self::ADDITIONAL_INFORMATION);
    }
    public function __toString(): string
    {
        $result = parent::__toString();
        foreach ($this->data as $object) {
            $result .= (string) $object->getKey();
            $result .= (string) $object->getValue();
        }
        return $result . "\xff";
    }
    public static function create(): self
    {
        return new self();
    }
    public function add(CBORObject $key, CBORObject $value): self
    {
        if (!$key instanceof Normalizable) {
            throw new InvalidArgumentException('Invalid key. Shall be normalizable');
        }
        $this->data[$key->normalize()] = MapItem::create($key, $value);
        return $this;
    }
    public function has(int|string $key): bool
    {
        return array_key_exists($key, $this->data);
    }
    public function remove(int|string $index): self
    {
        if (!$this->has($index)) {
            return $this;
        }
        unset($this->data[$index]);
        $this->data = array_values($this->data);
        return $this;
    }
    public function get(int|string $index): CBORObject
    {
        if (!$this->has($index)) {
            throw new InvalidArgumentException('Index not found.');
        }
        return $this->data[$index]->getValue();
    }
    public function set(MapItem $object): self
    {
        $key = $object->getKey();
        if (!$key instanceof Normalizable) {
            throw new InvalidArgumentException('Invalid key. Shall be normalizable');
        }
        $this->data[$key->normalize()] = $object;
        return $this;
    }
    /**
     * @return Iterator<int, MapItem>
     */
    public function getIterator(): Iterator
    {
        return new ArrayIterator($this->data);
    }
    /**
     * @return mixed[]
     */
    public function normalize(): array
    {
        return array_reduce($this->data, static function (array $carry, MapItem $item): array {
            $key = $item->getKey();
            if (!$key instanceof Normalizable) {
                throw new InvalidArgumentException('Invalid key. Shall be normalizable');
            }
            $valueObject = $item->getValue();
            $carry[$key->normalize()] = $valueObject instanceof Normalizable ? $valueObject->normalize() : $valueObject;
            return $carry;
        }, []);
    }
    public function offsetExists($offset): bool
    {
        return $this->has($offset);
    }
    public function offsetGet($offset): CBORObject
    {
        return $this->get($offset);
    }
    public function offsetSet($offset, $value): void
    {
        if (!$offset instanceof CBORObject) {
            throw new InvalidArgumentException('Invalid key');
        }
        if (!$value instanceof CBORObject) {
            throw new InvalidArgumentException('Invalid value');
        }
        $this->set(MapItem::create($offset, $value));
    }
    public function offsetUnset($offset): void
    {
        $this->remove($offset);
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\CBOR;

class MapItem
{
    public function __construct(private CBORObject $key, private CBORObject $value)
    {
    }
    public static function create(CBORObject $key, CBORObject $value): self
    {
        return new self($key, $value);
    }
    public function getKey(): CBORObject
    {
        return $this->key;
    }
    public function getValue(): CBORObject
    {
        return $this->value;
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\CBOR;

use function assert;
use _ContaoManager\Brick\Math\BigInteger;
use InvalidArgumentException;
use function is_string;
/**
 * @internal
 */
abstract class Utils
{
    public static function binToInt(string $value): int
    {
        return self::binToBigInteger($value)->toInt();
    }
    public static function binToBigInteger(string $value): BigInteger
    {
        return self::hexToBigInteger(bin2hex($value));
    }
    public static function hexToInt(string $value): int
    {
        return self::hexToBigInteger($value)->toInt();
    }
    public static function hexToBigInteger(string $value): BigInteger
    {
        assert($value !== '', 'Value must not be empty');
        return BigInteger::fromBase($value, 16);
    }
    public static function hexToString(string $value): string
    {
        $hex = bin2hex($value);
        assert($hex !== '', 'Value must not be empty');
        return BigInteger::fromBase($hex, 16)->toBase(10);
    }
    public static function decode(string $data): string
    {
        $decoded = base64_decode(strtr($data, '-_', '+/'), \true);
        if ($decoded === \false) {
            throw new InvalidArgumentException('Invalid data provided');
        }
        return $decoded;
    }
    /**
     * @param mixed|null $data
     */
    public static function assertString($data, ?string $message = null): void
    {
        if (!is_string($data)) {
            throw new InvalidArgumentException($message ?? '');
        }
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\CBOR;

use function array_key_exists;
use ArrayAccess;
use ArrayIterator;
use function count;
use Countable;
use InvalidArgumentException;
use Iterator;
use IteratorAggregate;
/**
 * @phpstan-implements ArrayAccess<int, CBORObject>
 * @phpstan-implements IteratorAggregate<int, CBORObject>
 * @see \CBOR\Test\ListObjectTest
 */
class ListObject extends AbstractCBORObject implements Countable, IteratorAggregate, Normalizable, ArrayAccess
{
    private const MAJOR_TYPE = self::MAJOR_TYPE_LIST;
    /**
     * @var CBORObject[]
     */
    private array $data;
    private ?string $length = null;
    /**
     * @param CBORObject[] $data
     */
    public function __construct(array $data = [])
    {
        [$additionalInformation, $length] = LengthCalculator::getLengthOfArray($data);
        array_map(static function ($item): void {
        }, $data);
        parent::__construct(self::MAJOR_TYPE, $additionalInformation);
        $this->data = array_values($data);
        $this->length = $length;
    }
    public function __toString(): string
    {
        $result = parent::__toString();
        $result .= $this->length ?? '';
        foreach ($this->data as $object) {
            $result .= (string) $object;
        }
        return $result;
    }
    /**
     * @param CBORObject[] $data
     */
    public static function create(array $data = []): self
    {
        return new self($data);
    }
    public function add(CBORObject $object): self
    {
        $this->data[] = $object;
        [$this->additionalInformation, $this->length] = LengthCalculator::getLengthOfArray($this->data);
        return $this;
    }
    public function has(int $index): bool
    {
        return array_key_exists($index, $this->data);
    }
    public function remove(int $index): self
    {
        if (!$this->has($index)) {
            return $this;
        }
        unset($this->data[$index]);
        $this->data = array_values($this->data);
        [$this->additionalInformation, $this->length] = LengthCalculator::getLengthOfArray($this->data);
        return $this;
    }
    public function get(int $index): CBORObject
    {
        if (!$this->has($index)) {
            throw new InvalidArgumentException('Index not found.');
        }
        return $this->data[$index];
    }
    public function set(int $index, CBORObject $object): self
    {
        if (!$this->has($index)) {
            throw new InvalidArgumentException('Index not found.');
        }
        $this->data[$index] = $object;
        [$this->additionalInformation, $this->length] = LengthCalculator::getLengthOfArray($this->data);
        return $this;
    }
    /**
     * @return array<int, mixed>
     */
    public function normalize(): array
    {
        return array_map(static fn(CBORObject $object) => $object instanceof Normalizable ? $object->normalize() : $object, $this->data);
    }
    public function count(): int
    {
        return count($this->data);
    }
    /**
     * @return Iterator<int, CBORObject>
     */
    public function getIterator(): Iterator
    {
        return new ArrayIterator($this->data);
    }
    public function offsetExists($offset): bool
    {
        return $this->has($offset);
    }
    public function offsetGet($offset): CBORObject
    {
        return $this->get($offset);
    }
    public function offsetSet($offset, $value): void
    {
        if ($offset === null) {
            $this->add($value);
            return;
        }
        $this->set($offset, $value);
    }
    public function offsetUnset($offset): void
    {
        $this->remove($offset);
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\CBOR;

use function array_key_exists;
use ArrayAccess;
use ArrayIterator;
use function count;
use Countable;
use InvalidArgumentException;
use Iterator;
use IteratorAggregate;
/**
 * @phpstan-implements ArrayAccess<int, CBORObject>
 * @phpstan-implements IteratorAggregate<int, MapItem>
 */
final class MapObject extends AbstractCBORObject implements Countable, IteratorAggregate, Normalizable, ArrayAccess
{
    private const MAJOR_TYPE = self::MAJOR_TYPE_MAP;
    /**
     * @var MapItem[]
     */
    private array $data;
    private ?string $length;
    /**
     * @param MapItem[] $data
     */
    public function __construct(array $data = [])
    {
        [$additionalInformation, $length] = LengthCalculator::getLengthOfArray($data);
        parent::__construct(self::MAJOR_TYPE, $additionalInformation);
        $this->data = $data;
        $this->length = $length;
    }
    public function __toString(): string
    {
        $result = parent::__toString();
        $result .= $this->length ?? '';
        foreach ($this->data as $object) {
            $result .= (string) $object->getKey();
            $result .= (string) $object->getValue();
        }
        return $result;
    }
    /**
     * @param MapItem[] $data
     */
    public static function create(array $data = []): self
    {
        return new self($data);
    }
    public function add(CBORObject $key, CBORObject $value): self
    {
        if (!$key instanceof Normalizable) {
            throw new InvalidArgumentException('Invalid key. Shall be normalizable');
        }
        $this->data[$key->normalize()] = MapItem::create($key, $value);
        [$this->additionalInformation, $this->length] = LengthCalculator::getLengthOfArray($this->data);
        return $this;
    }
    public function has(int|string $key): bool
    {
        return array_key_exists($key, $this->data);
    }
    public function remove(int|string $index): self
    {
        if (!$this->has($index)) {
            return $this;
        }
        unset($this->data[$index]);
        $this->data = array_values($this->data);
        [$this->additionalInformation, $this->length] = LengthCalculator::getLengthOfArray($this->data);
        return $this;
    }
    public function get(int|string $index): CBORObject
    {
        if (!$this->has($index)) {
            throw new InvalidArgumentException('Index not found.');
        }
        return $this->data[$index]->getValue();
    }
    public function set(MapItem $object): self
    {
        $key = $object->getKey();
        if (!$key instanceof Normalizable) {
            throw new InvalidArgumentException('Invalid key. Shall be normalizable');
        }
        $this->data[$key->normalize()] = $object;
        [$this->additionalInformation, $this->length] = LengthCalculator::getLengthOfArray($this->data);
        return $this;
    }
    public function count(): int
    {
        return count($this->data);
    }
    /**
     * @return Iterator<int, MapItem>
     */
    public function getIterator(): Iterator
    {
        return new ArrayIterator($this->data);
    }
    /**
     * @return array<int|string, mixed>
     */
    public function normalize(): array
    {
        return array_reduce($this->data, static function (array $carry, MapItem $item): array {
            $key = $item->getKey();
            if (!$key instanceof Normalizable) {
                throw new InvalidArgumentException('Invalid key. Shall be normalizable');
            }
            $valueObject = $item->getValue();
            $carry[$key->normalize()] = $valueObject instanceof Normalizable ? $valueObject->normalize() : $valueObject;
            return $carry;
        }, []);
    }
    public function offsetExists($offset): bool
    {
        return $this->has($offset);
    }
    public function offsetGet($offset): CBORObject
    {
        return $this->get($offset);
    }
    public function offsetSet($offset, $value): void
    {
        if (!$offset instanceof CBORObject) {
            throw new InvalidArgumentException('Invalid key');
        }
        if (!$value instanceof CBORObject) {
            throw new InvalidArgumentException('Invalid value');
        }
        $this->set(MapItem::create($offset, $value));
    }
    public function offsetUnset($offset): void
    {
        $this->remove($offset);
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\CBOR;

use Stringable;
interface CBORObject extends Stringable
{
    public const MAJOR_TYPE_UNSIGNED_INTEGER = 0b0;
    public const MAJOR_TYPE_NEGATIVE_INTEGER = 0b1;
    public const MAJOR_TYPE_BYTE_STRING = 0b10;
    public const MAJOR_TYPE_TEXT_STRING = 0b11;
    public const MAJOR_TYPE_LIST = 0b100;
    public const MAJOR_TYPE_MAP = 0b101;
    public const MAJOR_TYPE_TAG = 0b110;
    public const MAJOR_TYPE_OTHER_TYPE = 0b111;
    public const LENGTH_1_BYTE = 0b11000;
    public const LENGTH_2_BYTES = 0b11001;
    public const LENGTH_4_BYTES = 0b11010;
    public const LENGTH_8_BYTES = 0b11011;
    public const LENGTH_INDEFINITE = 0b11111;
    public const FUTURE_USE_1 = 0b11100;
    public const FUTURE_USE_2 = 0b11101;
    public const FUTURE_USE_3 = 0b11110;
    public const OBJECT_FALSE = 20;
    public const OBJECT_TRUE = 21;
    public const OBJECT_NULL = 22;
    public const OBJECT_UNDEFINED = 23;
    public const OBJECT_SIMPLE_VALUE = 24;
    public const OBJECT_HALF_PRECISION_FLOAT = 25;
    public const OBJECT_SINGLE_PRECISION_FLOAT = 26;
    public const OBJECT_DOUBLE_PRECISION_FLOAT = 27;
    public const OBJECT_BREAK = 0b11111;
    public const TAG_STANDARD_DATETIME = 0;
    public const TAG_EPOCH_DATETIME = 1;
    public const TAG_UNSIGNED_BIG_NUM = 2;
    public const TAG_NEGATIVE_BIG_NUM = 3;
    public const TAG_DECIMAL_FRACTION = 4;
    public const TAG_BIG_FLOAT = 5;
    public const TAG_ENCODED_BASE64_URL = 21;
    public const TAG_ENCODED_BASE64 = 22;
    public const TAG_ENCODED_BASE16 = 23;
    public const TAG_ENCODED_CBOR = 24;
    public const TAG_URI = 32;
    public const TAG_BASE64_URL = 33;
    public const TAG_BASE64 = 34;
    public const TAG_MIME = 36;
    public const TAG_CBOR = 55799;
    public function getMajorType(): int;
    public function getAdditionalInformation(): int;
}
<?php

declare (strict_types=1);
namespace _ContaoManager\CBOR\Tag;

use _ContaoManager\CBOR\CBORObject;
use _ContaoManager\CBOR\IndefiniteLengthTextStringObject;
use _ContaoManager\CBOR\Normalizable;
use _ContaoManager\CBOR\Tag;
use _ContaoManager\CBOR\TextStringObject;
use InvalidArgumentException;
final class UriTag extends Tag implements Normalizable
{
    public function __construct(int $additionalInformation, ?string $data, CBORObject $object)
    {
        if (!$object instanceof TextStringObject && !$object instanceof IndefiniteLengthTextStringObject) {
            throw new InvalidArgumentException('This tag only accepts a Text String object.');
        }
        parent::__construct($additionalInformation, $data, $object);
    }
    public static function getTagId(): int
    {
        return self::TAG_URI;
    }
    public static function createFromLoadedData(int $additionalInformation, ?string $data, CBORObject $object): Tag
    {
        return new self($additionalInformation, $data, $object);
    }
    public static function create(CBORObject $object): Tag
    {
        [$ai, $data] = self::determineComponents(self::TAG_URI);
        return new self($ai, $data, $object);
    }
    public function normalize(): string
    {
        /** @var TextStringObject|IndefiniteLengthTextStringObject $object */
        $object = $this->object;
        return $object->normalize();
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\CBOR\Tag;

use _ContaoManager\CBOR\CBORObject;
use _ContaoManager\CBOR\Tag;
final class Base64UrlEncodingTag extends Tag
{
    public static function getTagId(): int
    {
        return self::TAG_ENCODED_BASE64_URL;
    }
    public static function createFromLoadedData(int $additionalInformation, ?string $data, CBORObject $object): Tag
    {
        return new self($additionalInformation, $data, $object);
    }
    public static function create(CBORObject $object): Tag
    {
        [$ai, $data] = self::determineComponents(self::TAG_ENCODED_BASE64_URL);
        return new self($ai, $data, $object);
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\CBOR\Tag;

use function assert;
use _ContaoManager\Brick\Math\BigInteger;
use _ContaoManager\CBOR\ByteStringObject;
use _ContaoManager\CBOR\CBORObject;
use _ContaoManager\CBOR\IndefiniteLengthByteStringObject;
use _ContaoManager\CBOR\Normalizable;
use _ContaoManager\CBOR\Tag;
use InvalidArgumentException;
final class NegativeBigIntegerTag extends Tag implements Normalizable
{
    public function __construct(int $additionalInformation, ?string $data, CBORObject $object)
    {
        if (!$object instanceof ByteStringObject && !$object instanceof IndefiniteLengthByteStringObject) {
            throw new InvalidArgumentException('This tag only accepts a Byte String object.');
        }
        parent::__construct($additionalInformation, $data, $object);
    }
    public static function getTagId(): int
    {
        return self::TAG_NEGATIVE_BIG_NUM;
    }
    public static function createFromLoadedData(int $additionalInformation, ?string $data, CBORObject $object): Tag
    {
        return new self($additionalInformation, $data, $object);
    }
    public static function create(CBORObject $object): Tag
    {
        [$ai, $data] = self::determineComponents(self::TAG_NEGATIVE_BIG_NUM);
        return new self($ai, $data, $object);
    }
    public function normalize(): string
    {
        /** @var ByteStringObject|IndefiniteLengthByteStringObject $object */
        $object = $this->object;
        $hex = bin2hex($object->getValue());
        assert($hex !== '', 'Value must not be empty');
        $integer = BigInteger::fromBase($hex, 16);
        $minusOne = BigInteger::of(-1);
        return $minusOne->minus($integer)->toBase(10);
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\CBOR\Tag;

use _ContaoManager\CBOR\CBORObject;
use _ContaoManager\CBOR\ListObject;
use _ContaoManager\CBOR\NegativeIntegerObject;
use _ContaoManager\CBOR\Normalizable;
use _ContaoManager\CBOR\Tag;
use _ContaoManager\CBOR\UnsignedIntegerObject;
use function count;
use function extension_loaded;
use InvalidArgumentException;
use RuntimeException;
final class DecimalFractionTag extends Tag implements Normalizable
{
    public function __construct(int $additionalInformation, ?string $data, CBORObject $object)
    {
        if (!extension_loaded('bcmath')) {
            throw new RuntimeException('The extension "bcmath" is required to use this tag');
        }
        if (!$object instanceof ListObject || count($object) !== 2) {
            throw new InvalidArgumentException('This tag only accepts a ListObject object that contains an exponent and a mantissa.');
        }
        $e = $object->get(0);
        if (!$e instanceof UnsignedIntegerObject && !$e instanceof NegativeIntegerObject) {
            throw new InvalidArgumentException('The exponent must be a Signed Integer or an Unsigned Integer object.');
        }
        $m = $object->get(1);
        if (!$m instanceof UnsignedIntegerObject && !$m instanceof NegativeIntegerObject && !$m instanceof NegativeBigIntegerTag && !$m instanceof UnsignedBigIntegerTag) {
            throw new InvalidArgumentException('The mantissa must be a Positive or Negative Signed Integer or an Unsigned Integer object.');
        }
        parent::__construct($additionalInformation, $data, $object);
    }
    public static function create(CBORObject $object): self
    {
        [$ai, $data] = self::determineComponents(self::TAG_DECIMAL_FRACTION);
        return new self($ai, $data, $object);
    }
    public static function getTagId(): int
    {
        return self::TAG_DECIMAL_FRACTION;
    }
    public static function createFromLoadedData(int $additionalInformation, ?string $data, CBORObject $object): Tag
    {
        return new self($additionalInformation, $data, $object);
    }
    public static function createFromExponentAndMantissa(CBORObject $e, CBORObject $m): Tag
    {
        $object = ListObject::create()->add($e)->add($m);
        return self::create($object);
    }
    public function normalize()
    {
        /** @var ListObject $object */
        $object = $this->object;
        /** @var UnsignedIntegerObject|NegativeIntegerObject $e */
        $e = $object->get(0);
        /** @var UnsignedIntegerObject|NegativeIntegerObject|NegativeBigIntegerTag|UnsignedBigIntegerTag $m */
        $m = $object->get(1);
        return rtrim(bcmul((string) $m->normalize(), bcpow('10', (string) $e->normalize(), 100), 100), '0');
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\CBOR\Tag;

use _ContaoManager\CBOR\CBORObject;
interface TagManagerInterface
{
    public function createObjectForValue(int $additionalInformation, ?string $data, CBORObject $object): TagInterface;
}
<?php

declare (strict_types=1);
namespace _ContaoManager\CBOR\Tag;

use _ContaoManager\CBOR\CBORObject;
interface TagInterface extends CBORObject
{
    public static function getTagId(): int;
    public function getValue(): CBORObject;
    public static function createFromLoadedData(int $additionalInformation, ?string $data, CBORObject $object): self;
}
<?php

declare (strict_types=1);
namespace _ContaoManager\CBOR\Tag;

use _ContaoManager\CBOR\CBORObject;
use _ContaoManager\CBOR\IndefiniteLengthTextStringObject;
use _ContaoManager\CBOR\Tag;
use _ContaoManager\CBOR\TextStringObject;
use InvalidArgumentException;
final class Base64UrlTag extends Tag
{
    public function __construct(int $additionalInformation, ?string $data, CBORObject $object)
    {
        if (!$object instanceof TextStringObject && !$object instanceof IndefiniteLengthTextStringObject) {
            throw new InvalidArgumentException('This tag only accepts a Text String object.');
        }
        parent::__construct($additionalInformation, $data, $object);
    }
    public static function getTagId(): int
    {
        return self::TAG_BASE64_URL;
    }
    public static function createFromLoadedData(int $additionalInformation, ?string $data, CBORObject $object): Tag
    {
        return new self($additionalInformation, $data, $object);
    }
    public static function create(CBORObject $object): Tag
    {
        [$ai, $data] = self::determineComponents(self::TAG_BASE64_URL);
        return new self($ai, $data, $object);
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\CBOR\Tag;

use _ContaoManager\CBOR\CBORObject;
use _ContaoManager\CBOR\ListObject;
use _ContaoManager\CBOR\NegativeIntegerObject;
use _ContaoManager\CBOR\Normalizable;
use _ContaoManager\CBOR\Tag;
use _ContaoManager\CBOR\UnsignedIntegerObject;
use function count;
use function extension_loaded;
use InvalidArgumentException;
use RuntimeException;
final class BigFloatTag extends Tag implements Normalizable
{
    public function __construct(int $additionalInformation, ?string $data, CBORObject $object)
    {
        if (!extension_loaded('bcmath')) {
            throw new RuntimeException('The extension "bcmath" is required to use this tag');
        }
        if (!$object instanceof ListObject || count($object) !== 2) {
            throw new InvalidArgumentException('This tag only accepts a ListObject object that contains an exponent and a mantissa.');
        }
        $e = $object->get(0);
        if (!$e instanceof UnsignedIntegerObject && !$e instanceof NegativeIntegerObject) {
            throw new InvalidArgumentException('The exponent must be a Signed Integer or an Unsigned Integer object.');
        }
        $m = $object->get(1);
        if (!$m instanceof UnsignedIntegerObject && !$m instanceof NegativeIntegerObject && !$m instanceof NegativeBigIntegerTag && !$m instanceof UnsignedBigIntegerTag) {
            throw new InvalidArgumentException('The mantissa must be a Positive or Negative Signed Integer or an Unsigned Integer object.');
        }
        parent::__construct($additionalInformation, $data, $object);
    }
    public static function getTagId(): int
    {
        return self::TAG_BIG_FLOAT;
    }
    public static function createFromLoadedData(int $additionalInformation, ?string $data, CBORObject $object): Tag
    {
        return new self($additionalInformation, $data, $object);
    }
    public static function create(CBORObject $object): Tag
    {
        [$ai, $data] = self::determineComponents(self::TAG_BIG_FLOAT);
        return new self($ai, $data, $object);
    }
    public static function createFromExponentAndMantissa(CBORObject $e, CBORObject $m): Tag
    {
        $object = ListObject::create()->add($e)->add($m);
        return self::create($object);
    }
    public function normalize()
    {
        /** @var ListObject $object */
        $object = $this->object;
        /** @var UnsignedIntegerObject|NegativeIntegerObject $e */
        $e = $object->get(0);
        /** @var UnsignedIntegerObject|NegativeIntegerObject|NegativeBigIntegerTag|UnsignedBigIntegerTag $m */
        $m = $object->get(1);
        return rtrim(bcmul((string) $m->normalize(), bcpow('2', (string) $e->normalize(), 100), 100), '0');
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\CBOR\Tag;

use _ContaoManager\CBOR\CBORObject;
use _ContaoManager\CBOR\Normalizable;
use _ContaoManager\CBOR\Tag;
final class CBORTag extends Tag implements Normalizable
{
    public static function getTagId(): int
    {
        return self::TAG_CBOR;
    }
    public static function createFromLoadedData(int $additionalInformation, ?string $data, CBORObject $object): Tag
    {
        return new self($additionalInformation, $data, $object);
    }
    public static function create(CBORObject $object): Tag
    {
        [$ai, $data] = self::determineComponents(self::TAG_CBOR);
        return new self($ai, $data, $object);
    }
    /**
     * @return mixed|CBORObject|null
     */
    public function normalize()
    {
        return $this->object instanceof Normalizable ? $this->object->normalize() : $this->object;
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\CBOR\Tag;

use _ContaoManager\CBOR\CBORObject;
use _ContaoManager\CBOR\IndefiniteLengthTextStringObject;
use _ContaoManager\CBOR\Normalizable;
use _ContaoManager\CBOR\Tag;
use _ContaoManager\CBOR\TextStringObject;
use InvalidArgumentException;
/**
 * @see \CBOR\Test\Tag\MimeTagTest
 */
final class MimeTag extends Tag implements Normalizable
{
    public function __construct(int $additionalInformation, ?string $data, CBORObject $object)
    {
        if (!$object instanceof TextStringObject && !$object instanceof IndefiniteLengthTextStringObject) {
            throw new InvalidArgumentException('This tag only accepts a Byte String object.');
        }
        parent::__construct($additionalInformation, $data, $object);
    }
    public static function getTagId(): int
    {
        return self::TAG_MIME;
    }
    public static function createFromLoadedData(int $additionalInformation, ?string $data, CBORObject $object): Tag
    {
        return new self($additionalInformation, $data, $object);
    }
    public static function create(CBORObject $object): Tag
    {
        [$ai, $data] = self::determineComponents(self::TAG_MIME);
        return new self($ai, $data, $object);
    }
    public function normalize(): string
    {
        /** @var TextStringObject|IndefiniteLengthTextStringObject $object */
        $object = $this->object;
        return $object->normalize();
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\CBOR\Tag;

use _ContaoManager\CBOR\CBORObject;
use _ContaoManager\CBOR\IndefiniteLengthTextStringObject;
use _ContaoManager\CBOR\Normalizable;
use _ContaoManager\CBOR\Tag;
use _ContaoManager\CBOR\TextStringObject;
use const DATE_RFC3339;
use DateTimeImmutable;
use DateTimeInterface;
use InvalidArgumentException;
/**
 * @see \CBOR\Test\Tag\DatetimeTagTest
 */
final class DatetimeTag extends Tag implements Normalizable
{
    public function __construct(int $additionalInformation, ?string $data, CBORObject $object)
    {
        if (!$object instanceof TextStringObject && !$object instanceof IndefiniteLengthTextStringObject) {
            throw new InvalidArgumentException('This tag only accepts a Byte String object.');
        }
        parent::__construct($additionalInformation, $data, $object);
    }
    public static function getTagId(): int
    {
        return self::TAG_STANDARD_DATETIME;
    }
    public static function createFromLoadedData(int $additionalInformation, ?string $data, CBORObject $object): Tag
    {
        return new self($additionalInformation, $data, $object);
    }
    public static function create(CBORObject $object): Tag
    {
        [$ai, $data] = self::determineComponents(self::TAG_STANDARD_DATETIME);
        return new self($ai, $data, $object);
    }
    public function normalize(): DateTimeInterface
    {
        /** @var TextStringObject|IndefiniteLengthTextStringObject $object */
        $object = $this->object;
        $result = DateTimeImmutable::createFromFormat(DATE_RFC3339, $object->normalize());
        if ($result !== \false) {
            return $result;
        }
        $formatted = DateTimeImmutable::createFromFormat('Y-m-d\TH:i:s.uP', $object->normalize());
        if ($formatted === \false) {
            throw new InvalidArgumentException('Invalid data. Cannot be converted into a datetime object');
        }
        return $formatted;
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\CBOR\Tag;

use _ContaoManager\CBOR\ByteStringObject;
use _ContaoManager\CBOR\CBORObject;
use _ContaoManager\CBOR\IndefiniteLengthByteStringObject;
use _ContaoManager\CBOR\Tag;
use InvalidArgumentException;
final class CBOREncodingTag extends Tag
{
    public function __construct(int $additionalInformation, ?string $data, CBORObject $object)
    {
        if (!$object instanceof ByteStringObject && !$object instanceof IndefiniteLengthByteStringObject) {
            throw new InvalidArgumentException('This tag only accepts a Byte String object.');
        }
        parent::__construct($additionalInformation, $data, $object);
    }
    public static function getTagId(): int
    {
        return self::TAG_ENCODED_CBOR;
    }
    public static function createFromLoadedData(int $additionalInformation, ?string $data, CBORObject $object): Tag
    {
        return new self($additionalInformation, $data, $object);
    }
    public static function create(CBORObject $object): Tag
    {
        [$ai, $data] = self::determineComponents(self::TAG_ENCODED_CBOR);
        return new self($ai, $data, $object);
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\CBOR\Tag;

use _ContaoManager\CBOR\CBORObject;
use _ContaoManager\CBOR\IndefiniteLengthTextStringObject;
use _ContaoManager\CBOR\Tag;
use _ContaoManager\CBOR\TextStringObject;
use InvalidArgumentException;
final class Base64Tag extends Tag
{
    public function __construct(int $additionalInformation, ?string $data, CBORObject $object)
    {
        if (!$object instanceof TextStringObject && !$object instanceof IndefiniteLengthTextStringObject) {
            throw new InvalidArgumentException('This tag only accepts a Text String object.');
        }
        parent::__construct($additionalInformation, $data, $object);
    }
    public static function getTagId(): int
    {
        return self::TAG_BASE64;
    }
    public static function createFromLoadedData(int $additionalInformation, ?string $data, CBORObject $object): Tag
    {
        return new self($additionalInformation, $data, $object);
    }
    public static function create(CBORObject $object): Tag
    {
        [$ai, $data] = self::determineComponents(self::TAG_BASE64);
        return new self($ai, $data, $object);
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\CBOR\Tag;

use _ContaoManager\CBOR\CBORObject;
use _ContaoManager\CBOR\Tag;
final class Base16EncodingTag extends Tag
{
    public static function getTagId(): int
    {
        return self::TAG_ENCODED_BASE16;
    }
    public static function createFromLoadedData(int $additionalInformation, ?string $data, CBORObject $object): Tag
    {
        return new self($additionalInformation, $data, $object);
    }
    public static function create(CBORObject $object): Tag
    {
        [$ai, $data] = self::determineComponents(self::TAG_ENCODED_BASE16);
        return new self($ai, $data, $object);
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\CBOR\Tag;

use _ContaoManager\CBOR\ByteStringObject;
use _ContaoManager\CBOR\CBORObject;
use _ContaoManager\CBOR\IndefiniteLengthByteStringObject;
use _ContaoManager\CBOR\Normalizable;
use _ContaoManager\CBOR\Tag;
use _ContaoManager\CBOR\Utils;
use InvalidArgumentException;
final class UnsignedBigIntegerTag extends Tag implements Normalizable
{
    public function __construct(int $additionalInformation, ?string $data, CBORObject $object)
    {
        if (!$object instanceof ByteStringObject && !$object instanceof IndefiniteLengthByteStringObject) {
            throw new InvalidArgumentException('This tag only accepts a Byte String object.');
        }
        parent::__construct($additionalInformation, $data, $object);
    }
    public static function getTagId(): int
    {
        return self::TAG_UNSIGNED_BIG_NUM;
    }
    public static function createFromLoadedData(int $additionalInformation, ?string $data, CBORObject $object): Tag
    {
        return new self($additionalInformation, $data, $object);
    }
    public static function create(CBORObject $object): Tag
    {
        [$ai, $data] = self::determineComponents(self::TAG_UNSIGNED_BIG_NUM);
        return new self($ai, $data, $object);
    }
    public function normalize(): string
    {
        /** @var ByteStringObject|IndefiniteLengthByteStringObject $object */
        $object = $this->object;
        return Utils::hexToString($object->normalize());
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\CBOR\Tag;

use function array_key_exists;
use _ContaoManager\CBOR\CBORObject;
use _ContaoManager\CBOR\Utils;
use InvalidArgumentException;
final class TagManager implements TagManagerInterface
{
    /**
     * @param class-string<TagInterface>[] $classes
     */
    public function __construct(private array $classes = [])
    {
    }
    /**
     * @param array<class-string<TagInterface>> $classes
     */
    public static function create(array $classes = []): self
    {
        return new self($classes);
    }
    /**
     * @param class-string<TagInterface> $class
     */
    public function add(string $class): self
    {
        if ($class::getTagId() < 0) {
            throw new InvalidArgumentException('Invalid tag ID.');
        }
        $this->classes[$class::getTagId()] = $class;
        return $this;
    }
    /**
     * @return class-string<TagInterface>
     */
    public function getClassForValue(int $value): string
    {
        return array_key_exists($value, $this->classes) ? $this->classes[$value] : GenericTag::class;
    }
    public function createObjectForValue(int $additionalInformation, ?string $data, CBORObject $object): TagInterface
    {
        $value = $additionalInformation;
        if ($additionalInformation >= 24) {
            Utils::assertString($data, 'Invalid data');
            $value = Utils::binToInt($data);
        }
        $class = $this->getClassForValue($value);
        return $class::createFromLoadedData($additionalInformation, $data, $object);
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\CBOR\Tag;

use _ContaoManager\CBOR\CBORObject;
use _ContaoManager\CBOR\NegativeIntegerObject;
use _ContaoManager\CBOR\Normalizable;
use _ContaoManager\CBOR\OtherObject\DoublePrecisionFloatObject;
use _ContaoManager\CBOR\OtherObject\HalfPrecisionFloatObject;
use _ContaoManager\CBOR\OtherObject\SinglePrecisionFloatObject;
use _ContaoManager\CBOR\Tag;
use _ContaoManager\CBOR\UnsignedIntegerObject;
use DateTimeImmutable;
use DateTimeInterface;
use InvalidArgumentException;
use const STR_PAD_RIGHT;
use function strlen;
final class TimestampTag extends Tag implements Normalizable
{
    public function __construct(int $additionalInformation, ?string $data, CBORObject $object)
    {
        if (!$object instanceof UnsignedIntegerObject && !$object instanceof NegativeIntegerObject && !$object instanceof HalfPrecisionFloatObject && !$object instanceof SinglePrecisionFloatObject && !$object instanceof DoublePrecisionFloatObject) {
            throw new InvalidArgumentException('This tag only accepts integer-based or float-based objects.');
        }
        parent::__construct($additionalInformation, $data, $object);
    }
    public static function getTagId(): int
    {
        return self::TAG_EPOCH_DATETIME;
    }
    public static function createFromLoadedData(int $additionalInformation, ?string $data, CBORObject $object): Tag
    {
        return new self($additionalInformation, $data, $object);
    }
    public static function create(CBORObject $object): Tag
    {
        [$ai, $data] = self::determineComponents(self::TAG_EPOCH_DATETIME);
        return new self($ai, $data, $object);
    }
    public function normalize(): DateTimeInterface
    {
        $object = $this->object;
        switch (\true) {
            case $object instanceof UnsignedIntegerObject:
            case $object instanceof NegativeIntegerObject:
                $formatted = DateTimeImmutable::createFromFormat('U', $object->normalize());
                break;
            case $object instanceof HalfPrecisionFloatObject:
            case $object instanceof SinglePrecisionFloatObject:
            case $object instanceof DoublePrecisionFloatObject:
                $value = (string) $object->normalize();
                $parts = explode('.', $value);
                if (isset($parts[1])) {
                    if (strlen($parts[1]) > 6) {
                        $parts[1] = substr($parts[1], 0, 6);
                    } else {
                        $parts[1] = str_pad($parts[1], 6, '0', STR_PAD_RIGHT);
                    }
                }
                $formatted = DateTimeImmutable::createFromFormat('U.u', implode('.', $parts));
                break;
            default:
                throw new InvalidArgumentException('Unable to normalize the object');
        }
        if ($formatted === \false) {
            throw new InvalidArgumentException('Invalid data. Cannot be converted into a datetime object');
        }
        return $formatted;
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\CBOR\Tag;

use _ContaoManager\CBOR\CBORObject;
use _ContaoManager\CBOR\Tag;
final class GenericTag extends Tag
{
    public static function getTagId(): int
    {
        return -1;
    }
    public static function createFromLoadedData(int $additionalInformation, ?string $data, CBORObject $object): Tag
    {
        return new self($additionalInformation, $data, $object);
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\CBOR\Tag;

use _ContaoManager\CBOR\CBORObject;
use _ContaoManager\CBOR\Tag;
final class Base64EncodingTag extends Tag
{
    public static function getTagId(): int
    {
        return self::TAG_ENCODED_BASE64;
    }
    public static function createFromLoadedData(int $additionalInformation, ?string $data, CBORObject $object): Tag
    {
        return new self($additionalInformation, $data, $object);
    }
    public static function create(CBORObject $object): Tag
    {
        [$ai, $data] = self::determineComponents(self::TAG_ENCODED_BASE64);
        return new self($ai, $data, $object);
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\CBOR;

use _ContaoManager\Brick\Math\BigInteger;
use InvalidArgumentException;
use const STR_PAD_LEFT;
final class NegativeIntegerObject extends AbstractCBORObject implements Normalizable
{
    private const MAJOR_TYPE = self::MAJOR_TYPE_NEGATIVE_INTEGER;
    public function __construct(int $additionalInformation, private ?string $data)
    {
        parent::__construct(self::MAJOR_TYPE, $additionalInformation);
    }
    public function __toString(): string
    {
        $result = parent::__toString();
        if ($this->data !== null) {
            $result .= $this->data;
        }
        return $result;
    }
    public static function createObjectForValue(int $additionalInformation, ?string $data): self
    {
        return new self($additionalInformation, $data);
    }
    public static function create(int $value): self
    {
        return self::createFromString((string) $value);
    }
    public static function createFromString(string $value): self
    {
        $integer = BigInteger::of($value);
        return self::createBigInteger($integer);
    }
    /**
     * @return numeric-string
     */
    public function getValue(): string
    {
        if ($this->data === null) {
            return (string) (-1 - $this->additionalInformation);
        }
        $result = Utils::binToBigInteger($this->data);
        $minusOne = BigInteger::of(-1);
        return $minusOne->minus($result)->toBase(10);
    }
    /**
     * @return numeric-string
     */
    public function normalize(): string
    {
        return $this->getValue();
    }
    private static function createBigInteger(BigInteger $integer): self
    {
        if ($integer->isGreaterThanOrEqualTo(BigInteger::zero())) {
            throw new InvalidArgumentException('The value must be a negative integer.');
        }
        $minusOne = BigInteger::of(-1);
        $computed_value = $minusOne->minus($integer);
        switch (\true) {
            case $computed_value->isLessThan(BigInteger::of(24)):
                $ai = $computed_value->toInt();
                $data = null;
                break;
            case $computed_value->isLessThan(BigInteger::fromBase('FF', 16)):
                $ai = 24;
                $data = self::hex2bin(str_pad($computed_value->toBase(16), 2, '0', STR_PAD_LEFT));
                break;
            case $computed_value->isLessThan(BigInteger::fromBase('FFFF', 16)):
                $ai = 25;
                $data = self::hex2bin(str_pad($computed_value->toBase(16), 4, '0', STR_PAD_LEFT));
                break;
            case $computed_value->isLessThan(BigInteger::fromBase('FFFFFFFF', 16)):
                $ai = 26;
                $data = self::hex2bin(str_pad($computed_value->toBase(16), 8, '0', STR_PAD_LEFT));
                break;
            default:
                throw new InvalidArgumentException('Out of range. Please use NegativeBigIntegerTag tag with ByteStringObject object instead.');
        }
        return new self($ai, $data);
    }
    private static function hex2bin(string $data): string
    {
        $result = hex2bin($data);
        if ($result === \false) {
            throw new InvalidArgumentException('Unable to convert the data');
        }
        return $result;
    }
}
MIT License

Copyright (c) 2016-2019 Joni Eskelinen
Copyright (c) 2022 Spomky-Labs

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
# Public Key Infrastructure

> **Note**
> The code in this framework is the same as the one available in https://github.com/sop,
> but modified to fulfil with the Spomky-Labs requirements.
> All credits go to the original developer

A PHP Framework

* X.509 public key certificates, attribute certificates,
* X.690 Abstract Syntax Notation One (ASN.1) Distinguished Encoding Rules (DER) encoding and decoding
* X.501 ASN.1 types, X.520 attributes and DN parsing.
* [RFC 7468](https://tools.ietf.org/html/rfc7468) textual encodings of cryptographic structures _(PEM)_.
* Various ASN.1 types for cryptographic applications.
* Cryptography support for various PKCS applications.

## Requirements

- PHP >=8.1
- `mbstring`

The extension `gmp` or `bcmath` is highly recommended

## Installation

This library is available on [Github](https://github.com/Spomky-Labs/pki-framework).

```sh
composer require spomky-labs/pki-framework
```

## License

This project is licensed under the MIT License.
{
    "name": "spomky-labs\/pki-framework",
    "description": "A PHP framework for managing Public Key Infrastructures. It comprises X.509 public key certificates, attribute certificates, certification requests and certification path validation.",
    "homepage": "https:\/\/github.com\/spomky-labs\/pki-framework",
    "license": "MIT",
    "type": "library",
    "keywords": [
        "x509",
        "x.509",
        "certificate",
        "attribute certificate",
        "ac",
        "certification request",
        "csr",
        "pem",
        "public key",
        "private key",
        "certificate",
        "cryptography",
        "asn1",
        "algorithm identifier",
        "rsa",
        "ec",
        "public key",
        "private key",
        "signature",
        "pkcs",
        "cryptography",
        "encrypt",
        "decrypt",
        "sign",
        "verify",
        "asn1",
        "asn.1",
        "x690",
        "x.690",
        "der"
    ],
    "authors": [
        {
            "name": "Joni Eskelinen",
            "email": "jonieske@gmail.com",
            "role": "Original developer"
        },
        {
            "name": "Florent Morselli",
            "email": "florent.morselli@spomky-labs.com",
            "role": "Spomky-Labs PKI Framework developer"
        }
    ],
    "require": {
        "php": ">=8.1",
        "ext-mbstring": "*",
        "brick\/math": "^0.10|^0.11|^0.12|^0.13|^0.14|^0.15|^0.16|^0.17",
        "psr\/clock": "^1.0"
    },
    "require-dev": {
        "ext-gmp": "*",
        "ext-openssl": "*",
        "ekino\/phpstan-banned-code": "^1.0|^2.0|^3.0",
        "infection\/infection": "^0.28|^0.29|^0.31|^0.32",
        "php-parallel-lint\/php-parallel-lint": "^1.3",
        "phpstan\/extension-installer": "^1.3|^2.0",
        "phpstan\/phpstan": "^1.8|^2.0",
        "phpstan\/phpstan-deprecation-rules": "^1.0|^2.0",
        "phpstan\/phpstan-phpunit": "^1.1|^2.0",
        "phpstan\/phpstan-strict-rules": "^1.3|^2.0",
        "rector\/rector": "^1.0|^2.0",
        "roave\/security-advisories": "dev-latest",
        "symfony\/string": "^6.4|^7.0|^8.0",
        "symfony\/var-dumper": "^6.4|^7.0|^8.0",
        "symplify\/easy-coding-standard": "^12.0|^13.0",
        "phpunit\/phpunit": "^10.1|^11.0|^12.0|^13.0"
    },
    "suggest": {
        "ext-openssl": "For OpenSSL based cyphering",
        "ext-gmp": "For better performance (or BCMath)",
        "ext-bcmath": "For better performance (or GMP)"
    },
    "autoload": {
        "psr-4": {
            "_ContaoManager\\SpomkyLabs\\Pki\\": "src\/"
        }
    },
    "autoload-dev": {
        "psr-4": {
            "_ContaoManager\\SpomkyLabs\\Pki\\Test\\": "tests\/"
        }
    },
    "config": {
        "allow-plugins": {
            "infection\/extension-installer": true,
            "phpstan\/extension-installer": true
        }
    }
}# Security Policy

## Supported Versions

| Version | Supported          |
|---------| ------------------ |
| 1.0.x   | :white_check_mark: |
| < 1.0.0 | :x:                |

## Reporting a Vulnerability

If you think you have found a security issue, DO NOT open an issue. You MUST email your issue: security AT
spomky-labs.com.
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\ASN1;

use function array_key_exists;
use function mb_strlen;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Component\Identifier;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Component\Length;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Feature\ElementBase;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Constructed;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Constructed\ConstructedString;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Constructed\Sequence;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Constructed\Set;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Primitive\BitString;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Primitive\BMPString;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Primitive\Boolean;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Primitive\CharacterString;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Primitive\Enumerated;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Primitive\EOC;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Primitive\GeneralizedTime;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Primitive\GeneralString;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Primitive\GraphicString;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Primitive\IA5String;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Primitive\Integer;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Primitive\NullType;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Primitive\NumericString;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Primitive\ObjectDescriptor;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Primitive\ObjectIdentifier;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Primitive\OctetString;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Primitive\PrintableString;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Primitive\Real;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Primitive\RelativeOID;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Primitive\T61String;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Primitive\UniversalString;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Primitive\UTCTime;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Primitive\UTF8String;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Primitive\VideotexString;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Primitive\VisibleString;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\StringType;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Tagged\ApplicationType;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Tagged\ContextSpecificType;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Tagged\PrivateType;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\TaggedType;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\TimeType;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\UnspecifiedType;
use function sprintf;
use UnexpectedValueException;
/**
 * Base class for all ASN.1 type elements.
 * @see \SpomkyLabs\Pki\Test\ASN1\ElementTest
 */
abstract class Element implements ElementBase
{
    // Universal type tags
    public const TYPE_EOC = 0x0;
    public const TYPE_BOOLEAN = 0x1;
    public const TYPE_INTEGER = 0x2;
    public const TYPE_BIT_STRING = 0x3;
    public const TYPE_OCTET_STRING = 0x4;
    public const TYPE_NULL = 0x5;
    public const TYPE_OBJECT_IDENTIFIER = 0x6;
    public const TYPE_OBJECT_DESCRIPTOR = 0x7;
    public const TYPE_EXTERNAL = 0x8;
    public const TYPE_REAL = 0x9;
    public const TYPE_ENUMERATED = 0xa;
    public const TYPE_EMBEDDED_PDV = 0xb;
    public const TYPE_UTF8_STRING = 0xc;
    public const TYPE_RELATIVE_OID = 0xd;
    public const TYPE_SEQUENCE = 0x10;
    public const TYPE_SET = 0x11;
    public const TYPE_NUMERIC_STRING = 0x12;
    public const TYPE_PRINTABLE_STRING = 0x13;
    public const TYPE_T61_STRING = 0x14;
    public const TYPE_VIDEOTEX_STRING = 0x15;
    public const TYPE_IA5_STRING = 0x16;
    public const TYPE_UTC_TIME = 0x17;
    public const TYPE_GENERALIZED_TIME = 0x18;
    public const TYPE_GRAPHIC_STRING = 0x19;
    public const TYPE_VISIBLE_STRING = 0x1a;
    public const TYPE_GENERAL_STRING = 0x1b;
    public const TYPE_UNIVERSAL_STRING = 0x1c;
    public const TYPE_CHARACTER_STRING = 0x1d;
    public const TYPE_BMP_STRING = 0x1e;
    /**
     * Pseudotype for all string types.
     *
     * May be used as an expectation parameter.
     *
     * @var int
     */
    public const TYPE_STRING = -1;
    /**
     * Pseudotype for all time types.
     *
     * May be used as an expectation parameter.
     *
     * @var int
     */
    public const TYPE_TIME = -2;
    /**
     * Pseudotype for constructed strings.
     *
     * May be used as an expectation parameter.
     *
     * @var int
     */
    public const TYPE_CONSTRUCTED_STRING = -3;
    /**
     * Mapping from universal type tag to implementation class name.
     *
     * @internal
     *
     * @var array<int, string>
     */
    private const MAP_TAG_TO_CLASS = [self::TYPE_EOC => EOC::class, self::TYPE_BOOLEAN => Boolean::class, self::TYPE_INTEGER => Integer::class, self::TYPE_BIT_STRING => BitString::class, self::TYPE_OCTET_STRING => OctetString::class, self::TYPE_NULL => NullType::class, self::TYPE_OBJECT_IDENTIFIER => ObjectIdentifier::class, self::TYPE_OBJECT_DESCRIPTOR => ObjectDescriptor::class, self::TYPE_REAL => Real::class, self::TYPE_ENUMERATED => Enumerated::class, self::TYPE_UTF8_STRING => UTF8String::class, self::TYPE_RELATIVE_OID => RelativeOID::class, self::TYPE_SEQUENCE => Sequence::class, self::TYPE_SET => Set::class, self::TYPE_NUMERIC_STRING => NumericString::class, self::TYPE_PRINTABLE_STRING => PrintableString::class, self::TYPE_T61_STRING => T61String::class, self::TYPE_VIDEOTEX_STRING => VideotexString::class, self::TYPE_IA5_STRING => IA5String::class, self::TYPE_UTC_TIME => UTCTime::class, self::TYPE_GENERALIZED_TIME => GeneralizedTime::class, self::TYPE_GRAPHIC_STRING => GraphicString::class, self::TYPE_VISIBLE_STRING => VisibleString::class, self::TYPE_GENERAL_STRING => GeneralString::class, self::TYPE_UNIVERSAL_STRING => UniversalString::class, self::TYPE_CHARACTER_STRING => CharacterString::class, self::TYPE_BMP_STRING => BMPString::class];
    /**
     * Mapping from universal type tag to human-readable name.
     *
     * @internal
     *
     * @var array<int, string>
     */
    private const MAP_TYPE_TO_NAME = [self::TYPE_EOC => 'EOC', self::TYPE_BOOLEAN => 'BOOLEAN', self::TYPE_INTEGER => 'INTEGER', self::TYPE_BIT_STRING => 'BIT STRING', self::TYPE_OCTET_STRING => 'OCTET STRING', self::TYPE_NULL => 'NULL', self::TYPE_OBJECT_IDENTIFIER => 'OBJECT IDENTIFIER', self::TYPE_OBJECT_DESCRIPTOR => 'ObjectDescriptor', self::TYPE_EXTERNAL => 'EXTERNAL', self::TYPE_REAL => 'REAL', self::TYPE_ENUMERATED => 'ENUMERATED', self::TYPE_EMBEDDED_PDV => 'EMBEDDED PDV', self::TYPE_UTF8_STRING => 'UTF8String', self::TYPE_RELATIVE_OID => 'RELATIVE-OID', self::TYPE_SEQUENCE => 'SEQUENCE', self::TYPE_SET => 'SET', self::TYPE_NUMERIC_STRING => 'NumericString', self::TYPE_PRINTABLE_STRING => 'PrintableString', self::TYPE_T61_STRING => 'T61String', self::TYPE_VIDEOTEX_STRING => 'VideotexString', self::TYPE_IA5_STRING => 'IA5String', self::TYPE_UTC_TIME => 'UTCTime', self::TYPE_GENERALIZED_TIME => 'GeneralizedTime', self::TYPE_GRAPHIC_STRING => 'GraphicString', self::TYPE_VISIBLE_STRING => 'VisibleString', self::TYPE_GENERAL_STRING => 'GeneralString', self::TYPE_UNIVERSAL_STRING => 'UniversalString', self::TYPE_CHARACTER_STRING => 'CHARACTER STRING', self::TYPE_BMP_STRING => 'BMPString', self::TYPE_STRING => 'Any String', self::TYPE_TIME => 'Any Time', self::TYPE_CONSTRUCTED_STRING => 'Constructed String'];
    /**
     * @param bool $indefiniteLength Whether type shall be encoded with indefinite length.
     */
    protected function __construct(protected readonly int $typeTag, protected bool $indefiniteLength = \false)
    {
    }
    abstract public function typeClass(): int;
    abstract public function isConstructed(): bool;
    /**
     * Decode element from DER data.
     *
     * @param string $data DER encoded data
     * @param null|int $offset Reference to the variable that contains offset
     * into the data where to start parsing.
     * Variable is updated to the offset next to the
     * parsed element. If null, start from offset 0.
     */
    public static function fromDER(string $data, ?int &$offset = null): static
    {
        $idx = $offset ?? 0;
        // decode identifier
        $identifier = Identifier::fromDER($data, $idx);
        // determine class that implements type specific decoding
        $cls = self::determineImplClass($identifier);
        // decode remaining element
        $element = $cls::decodeFromDER($identifier, $data, $idx);
        // if called in the context of a concrete class, check
        // that decoded type matches the type of calling class
        $called_class = static::class;
        if ($called_class !== self::class) {
            if (!$element instanceof $called_class) {
                throw new UnexpectedValueException(sprintf('%s expected, got %s.', $called_class, $element::class));
            }
        }
        // update offset for the caller
        if (isset($offset)) {
            $offset = $idx;
        }
        return $element;
    }
    public function toDER(): string
    {
        $identifier = Identifier::create($this->typeClass(), $this->isConstructed() ? Identifier::CONSTRUCTED : Identifier::PRIMITIVE, $this->typeTag);
        $content = $this->encodedAsDER();
        if ($this->indefiniteLength) {
            $length = Length::create(0, \true);
            $eoc = EOC::create();
            return $identifier->toDER() . $length->toDER() . $content . $eoc->toDER();
        }
        $length = Length::create(mb_strlen($content, '8bit'));
        return $identifier->toDER() . $length->toDER() . $content;
    }
    public function tag(): int
    {
        return $this->typeTag;
    }
    public function isType(int $tag): bool
    {
        // if element is context specific
        if ($this->typeClass() === Identifier::CLASS_CONTEXT_SPECIFIC) {
            return \false;
        }
        // negative tags identify an abstract pseudotype
        if ($tag < 0) {
            return $this->isPseudoType($tag);
        }
        return $this->isConcreteType($tag);
    }
    public function expectType(int $tag): ElementBase
    {
        if (!$this->isType($tag)) {
            throw new UnexpectedValueException(sprintf('%s expected, got %s.', self::tagToName($tag), $this->typeDescriptorString()));
        }
        return $this;
    }
    public function isTagged(): bool
    {
        return $this instanceof TaggedType;
    }
    public function expectTagged(?int $tag = null): TaggedType
    {
        if (!$this->isTagged()) {
            throw new UnexpectedValueException(sprintf('Context specific element expected, got %s.', Identifier::classToName($this->typeClass())));
        }
        if (isset($tag) && $this->tag() !== $tag) {
            throw new UnexpectedValueException(sprintf('Tag %d expected, got %d.', $tag, $this->tag()));
        }
        return $this;
    }
    /**
     * Whether element has indefinite length.
     */
    public function hasIndefiniteLength(): bool
    {
        return $this->indefiniteLength;
    }
    /**
     * Get self with indefinite length encoding set.
     *
     * @param bool $indefinite True for indefinite length, false for definite length
     */
    public function withIndefiniteLength(bool $indefinite = \true): self
    {
        $obj = clone $this;
        $obj->indefiniteLength = $indefinite;
        return $obj;
    }
    final public function asElement(): self
    {
        return $this;
    }
    /**
     * Get element decorated with `UnspecifiedType` object.
     */
    public function asUnspecified(): UnspecifiedType
    {
        return UnspecifiedType::create($this);
    }
    /**
     * Get human readable name for an universal tag.
     */
    public static function tagToName(int $tag): string
    {
        if (!array_key_exists($tag, self::MAP_TYPE_TO_NAME)) {
            return "TAG {$tag}";
        }
        return self::MAP_TYPE_TO_NAME[$tag];
    }
    /**
     * Get the content encoded in DER.
     *
     * Returns the DER encoded content without identifier and length header octets.
     */
    abstract protected function encodedAsDER(): string;
    /**
     * Decode type-specific element from DER.
     *
     * @param Identifier $identifier Pre-parsed identifier
     * @param string $data DER data
     * @param int $offset Offset in data to the next byte after identifier
     */
    abstract protected static function decodeFromDER(Identifier $identifier, string $data, int &$offset): ElementBase;
    /**
     * Determine the class that implements the type.
     *
     * @return string Class name
     */
    protected static function determineImplClass(Identifier $identifier): string
    {
        switch ($identifier->typeClass()) {
            case Identifier::CLASS_UNIVERSAL:
                $cls = self::determineUniversalImplClass($identifier->intTag());
                // constructed strings may be present in BER
                if ($identifier->isConstructed() && is_subclass_of($cls, StringType::class)) {
                    $cls = ConstructedString::class;
                }
                return $cls;
            case Identifier::CLASS_CONTEXT_SPECIFIC:
                return ContextSpecificType::class;
            case Identifier::CLASS_APPLICATION:
                return ApplicationType::class;
            case Identifier::CLASS_PRIVATE:
                return PrivateType::class;
        }
        throw new UnexpectedValueException(sprintf('%s %d not implemented.', Identifier::classToName($identifier->typeClass()), $identifier->tag()));
    }
    /**
     * Determine the class that implements an universal type of the given tag.
     *
     * @return string Class name
     */
    protected static function determineUniversalImplClass(int $tag): string
    {
        if (!array_key_exists($tag, self::MAP_TAG_TO_CLASS)) {
            throw new UnexpectedValueException("Universal tag {$tag} not implemented.");
        }
        return self::MAP_TAG_TO_CLASS[$tag];
    }
    /**
     * Get textual description of the type for debugging purposes.
     */
    protected function typeDescriptorString(): string
    {
        if ($this->typeClass() === Identifier::CLASS_UNIVERSAL) {
            return self::tagToName($this->typeTag);
        }
        return sprintf('%s TAG %d', Identifier::classToName($this->typeClass()), $this->typeTag);
    }
    /**
     * Check whether the element is a concrete type of given tag.
     */
    private function isConcreteType(int $tag): bool
    {
        // if tag doesn't match
        if ($this->tag() !== $tag) {
            return \false;
        }
        // if type is universal check that instance is of a correct class
        if ($this->typeClass() === Identifier::CLASS_UNIVERSAL) {
            $cls = self::determineUniversalImplClass($tag);
            if (!$this instanceof $cls) {
                return \false;
            }
        }
        return \true;
    }
    /**
     * Check whether the element is a pseudotype.
     */
    private function isPseudoType(int $tag): bool
    {
        return match ($tag) {
            self::TYPE_STRING => $this instanceof StringType,
            self::TYPE_TIME => $this instanceof TimeType,
            self::TYPE_CONSTRUCTED_STRING => $this instanceof ConstructedString,
            default => \false,
        };
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\ASN1\Util;

use _ContaoManager\Brick\Math\BigInteger;
use InvalidArgumentException;
use Stringable;
use Throwable;
/**
 * Class to wrap an integer of arbirtary length.
 * @see \SpomkyLabs\Pki\Test\ASN1\Util\BigIntTest
 */
final class BigInt implements Stringable
{
    /**
     * Number as a BigInteger object.
     */
    private readonly BigInteger $value;
    /**
     * Number as a base 10 integer string.
     *
     * @internal Lazily initialized
     */
    private ?string $number = null;
    /**
     * Number as an integer type.
     *
     * @internal Lazily initialized
     */
    private ?int $_intNum = null;
    private function __construct(BigInteger|int|string $num)
    {
        // convert to BigInteger object
        if (!$num instanceof BigInteger) {
            try {
                $num = BigInteger::of($num);
            } catch (Throwable) {
                throw new InvalidArgumentException('Unable to convert to integer.');
            }
        }
        $this->value = $num;
    }
    public function __toString(): string
    {
        return $this->base10();
    }
    public static function create(BigInteger|int|string $num): self
    {
        return new self($num);
    }
    /**
     * Initialize from an arbitrary length of octets as an unsigned integer.
     */
    public static function fromUnsignedOctets(string $octets): self
    {
        if ($octets === '') {
            throw new InvalidArgumentException('Empty octets.');
        }
        return self::create(BigInteger::fromBytes($octets, \false));
    }
    /**
     * Initialize from an arbitrary length of octets as an signed integer having two's complement encoding.
     */
    public static function fromSignedOctets(string $octets): self
    {
        if ($octets === '') {
            throw new InvalidArgumentException('Empty octets.');
        }
        return self::create(BigInteger::fromBytes($octets));
    }
    /**
     * Get the number as a base 10 integer string.
     */
    public function base10(): string
    {
        if ($this->number === null) {
            $this->number = $this->value->toBase(10);
        }
        return $this->number;
    }
    /**
     * Get the number as an integer.
     */
    public function toInt(): int
    {
        if (!isset($this->_intNum)) {
            $this->_intNum = $this->value->toInt();
        }
        return $this->_intNum;
    }
    public function getValue(): BigInteger
    {
        return $this->value;
    }
    /**
     * Get the number as an unsigned integer encoded in binary.
     */
    public function unsignedOctets(): string
    {
        return $this->value->toBytes(\false);
    }
    /**
     * Get the number as a signed integer encoded in two's complement binary.
     */
    public function signedOctets(): string
    {
        return $this->value->toBytes();
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\ASN1\Util;

use function assert;
use _ContaoManager\Brick\Math\BigInteger;
use function count;
use function is_array;
use function ord;
use OutOfBoundsException;
use RuntimeException;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Primitive\BitString;
/**
 * Class to handle a bit string as a field of flags.
 * @see \SpomkyLabs\Pki\Test\ASN1\Util\FlagsTest
 */
final class Flags
{
    /**
     * Flag octets.
     */
    private string $_flags;
    /**
     * @param BigInteger|int|string $flags Flags
     * @param int $_width The number of flags. If width is larger than
     * number of bits in $flags, zeroes are prepended
     * to flag field.
     */
    private function __construct(BigInteger|int|string $flags, private readonly int $_width)
    {
        if ($_width === 0) {
            $this->_flags = '';
            return;
        }
        // calculate number of unused bits in last octet
        $last_octet_bits = $_width % 8;
        $unused_bits = $last_octet_bits !== 0 ? 8 - $last_octet_bits : 0;
        // mask bits outside bitfield width
        $num = BigInteger::of($flags);
        $mask = BigInteger::of(1)->shiftedLeft($_width)->minus(1);
        $num = $num->and($mask);
        // shift towards MSB if needed
        $data = $num->shiftedLeft($unused_bits)->toBytes(\false);
        $octets = unpack('C*', $data);
        assert(is_array($octets), new RuntimeException('unpack() failed'));
        $bits = count($octets) * 8;
        // pad with zeroes
        while ($bits < $_width) {
            array_unshift($octets, 0);
            $bits += 8;
        }
        $this->_flags = pack('C*', ...$octets);
    }
    public static function create(BigInteger|int|string $flags, int $_width): self
    {
        return new self($flags, $_width);
    }
    /**
     * Initialize from `BitString`.
     */
    public static function fromBitString(BitString $bs, int $width): self
    {
        $num_bits = $bs->numBits();
        $data = $bs->string();
        $num = $data === '' ? BigInteger::of(0) : BigInteger::fromBytes($data, \false);
        $num = $num->shiftedRight($bs->unusedBits());
        if ($num_bits < $width) {
            $num = $num->shiftedLeft($width - $num_bits);
        }
        return self::create($num, $width);
    }
    /**
     * Check whether a bit at given index is set.
     *
     * Index 0 is the leftmost bit.
     */
    public function test(int $idx): bool
    {
        if ($idx >= $this->_width) {
            throw new OutOfBoundsException('Index is out of bounds.');
        }
        // octet index
        $oi = (int) floor($idx / 8);
        $byte = $this->_flags[$oi];
        // bit index
        $bi = $idx % 8;
        // index 0 is the most significant bit in byte
        $mask = 0x1 << 7 - $bi;
        return (ord($byte) & $mask) > 0;
    }
    /**
     * Get flags as an octet string.
     *
     * Zeroes are appended to the last octet if width is not divisible by 8.
     */
    public function string(): string
    {
        return $this->_flags;
    }
    /**
     * Get flags as a base 10 integer.
     *
     * @return string Integer as a string
     */
    public function number(): string
    {
        $num = $this->_flags === '' ? BigInteger::of(0) : BigInteger::fromBytes($this->_flags, \false);
        $last_octet_bits = $this->_width % 8;
        $unused_bits = $last_octet_bits !== 0 ? 8 - $last_octet_bits : 0;
        $num = $num->shiftedRight($unused_bits);
        return $num->toBase(10);
    }
    /**
     * Get flags as an integer.
     */
    public function intNumber(): int
    {
        $num = BigInt::create($this->number());
        return $num->toInt();
    }
    /**
     * Get flags as a `BitString` object.
     *
     * Unused bits are set accordingly. Trailing zeroes are not stripped.
     */
    public function bitString(): BitString
    {
        $last_octet_bits = $this->_width % 8;
        $unused_bits = $last_octet_bits !== 0 ? 8 - $last_octet_bits : 0;
        return BitString::create($this->_flags, $unused_bits);
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\ASN1\Component;

use function array_key_exists;
use _ContaoManager\Brick\Math\BigInteger;
use function mb_strlen;
use function ord;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Exception\DecodeException;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Feature\Encodable;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Util\BigInt;
/**
 * Class to represent BER/DER identifier octets.
 * @see \SpomkyLabs\Pki\Test\ASN1\Component\IdentifierTest
 */
final class Identifier implements Encodable
{
    // Type class enumerations
    final public const CLASS_UNIVERSAL = 0b0;
    final public const CLASS_APPLICATION = 0b1;
    final public const CLASS_CONTEXT_SPECIFIC = 0b10;
    final public const CLASS_PRIVATE = 0b11;
    // P/C enumerations
    final public const PRIMITIVE = 0b0;
    final public const CONSTRUCTED = 0b1;
    /**
     * Mapping from type class to human readable name.
     *
     * @internal
     *
     * @var array<int, string>
     */
    private const MAP_CLASS_TO_NAME = [self::CLASS_UNIVERSAL => 'UNIVERSAL', self::CLASS_APPLICATION => 'APPLICATION', self::CLASS_CONTEXT_SPECIFIC => 'CONTEXT SPECIFIC', self::CLASS_PRIVATE => 'PRIVATE'];
    /**
     * Type class.
     */
    private int $_class;
    /**
     * Primitive or Constructed.
     */
    private readonly int $_pc;
    /**
     * Content type tag.
     */
    private BigInt $_tag;
    /**
     * @param int $class Type class
     * @param int $pc Primitive / Constructed
     * @param BigInteger|int $tag Type tag number
     */
    private function __construct(int $class, int $pc, BigInteger|int $tag)
    {
        $this->_class = 0b11 & $class;
        $this->_pc = 0b1 & $pc;
        $this->_tag = BigInt::create($tag);
    }
    public static function create(int $class, int $pc, BigInteger|int $tag): self
    {
        return new self($class, $pc, $tag);
    }
    /**
     * Decode identifier component from DER data.
     *
     * @param string $data DER encoded data
     * @param null|int $offset Reference to the variable that contains offset
     * into the data where to start parsing.
     * Variable is updated to the offset next to the
     * parsed identifier. If null, start from offset 0.
     */
    public static function fromDER(string $data, ?int &$offset = null): self
    {
        $idx = $offset ?? 0;
        $datalen = mb_strlen($data, '8bit');
        if ($idx >= $datalen) {
            throw new DecodeException('Invalid offset.');
        }
        $byte = ord($data[$idx++]);
        // bits 8 and 7 (class)
        // 0 = universal, 1 = application, 2 = context-specific, 3 = private
        $class = (0b11000000 & $byte) >> 6;
        // bit 6 (0 = primitive / 1 = constructed)
        $pc = (0b100000 & $byte) >> 5;
        // bits 5 to 1 (tag number)
        $tag = 0b11111 & $byte;
        // long-form identifier
        if ($tag === 0x1f) {
            $tag = self::decodeLongFormTag($data, $idx);
        }
        if (isset($offset)) {
            $offset = $idx;
        }
        return self::create($class, $pc, $tag);
    }
    public function toDER(): string
    {
        $bytes = [];
        $byte = $this->_class << 6 | $this->_pc << 5;
        $tag = $this->_tag->getValue();
        if ($tag->isLessThan(0x1f)) {
            $bytes[] = $byte | $tag->toInt();
        } else {
            $bytes[] = $byte | 0x1f;
            $octets = [];
            for (; $tag->isGreaterThan(0); $tag = $tag->shiftedRight(7)) {
                $octets[] = 0x80 | $tag->and(0x7f)->toInt();
            }
            // last octet has bit 8 set to zero
            $octets[0] &= 0x7f;
            foreach (array_reverse($octets) as $octet) {
                $bytes[] = $octet;
            }
        }
        return pack('C*', ...$bytes);
    }
    /**
     * Get class of the type.
     */
    public function typeClass(): int
    {
        return $this->_class;
    }
    public function pc(): int
    {
        return $this->_pc;
    }
    /**
     * Get the tag number.
     *
     * @return string Base 10 integer string
     */
    public function tag(): string
    {
        return $this->_tag->base10();
    }
    /**
     * Get the tag as an integer.
     */
    public function intTag(): int
    {
        return $this->_tag->toInt();
    }
    /**
     * Check whether type is of an universal class.
     */
    public function isUniversal(): bool
    {
        return $this->_class === self::CLASS_UNIVERSAL;
    }
    /**
     * Check whether type is of an application class.
     */
    public function isApplication(): bool
    {
        return $this->_class === self::CLASS_APPLICATION;
    }
    /**
     * Check whether type is of a context specific class.
     */
    public function isContextSpecific(): bool
    {
        return $this->_class === self::CLASS_CONTEXT_SPECIFIC;
    }
    /**
     * Check whether type is of a private class.
     */
    public function isPrivate(): bool
    {
        return $this->_class === self::CLASS_PRIVATE;
    }
    /**
     * Check whether content is primitive type.
     */
    public function isPrimitive(): bool
    {
        return $this->_pc === self::PRIMITIVE;
    }
    /**
     * Check hether content is constructed type.
     */
    public function isConstructed(): bool
    {
        return $this->_pc === self::CONSTRUCTED;
    }
    /**
     * Get self with given type class.
     *
     * @param int $class One of `CLASS_*` enumerations
     */
    public function withClass(int $class): self
    {
        $obj = clone $this;
        $obj->_class = 0b11 & $class;
        return $obj;
    }
    /**
     * Get self with given type tag.
     *
     * @param int $tag Tag number
     */
    public function withTag(int $tag): self
    {
        $obj = clone $this;
        $obj->_tag = BigInt::create($tag);
        return $obj;
    }
    /**
     * Get human readable name of the type class.
     */
    public static function classToName(int $class): string
    {
        if (!array_key_exists($class, self::MAP_CLASS_TO_NAME)) {
            return "CLASS {$class}";
        }
        return self::MAP_CLASS_TO_NAME[$class];
    }
    /**
     * Parse long form tag.
     *
     * @param string $data DER data
     * @param int $offset Reference to the variable containing offset to data
     *
     * @return BigInteger Tag number
     */
    private static function decodeLongFormTag(string $data, int &$offset): BigInteger
    {
        $datalen = mb_strlen($data, '8bit');
        $tag = BigInteger::of(0);
        while (\true) {
            if ($offset >= $datalen) {
                throw new DecodeException('Unexpected end of data while decoding long form identifier.');
            }
            $byte = ord($data[$offset++]);
            $tag = $tag->shiftedLeft(7);
            $tag = $tag->or(0x7f & $byte);
            // last byte has bit 8 set to zero
            if ((0x80 & $byte) === 0) {
                break;
            }
        }
        return $tag;
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\ASN1\Component;

use _ContaoManager\Brick\Math\BigInteger;
use function count;
use DomainException;
use LogicException;
use function mb_strlen;
use function ord;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Exception\DecodeException;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Feature\Encodable;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Util\BigInt;
use function sprintf;
/**
 * Class to represent BER/DER length octets.
 */
final class Length implements Encodable
{
    /**
     * Length.
     */
    private readonly BigInt $_length;
    /**
     * @param BigInteger|int $length Length
     * @param bool $_indefinite Whether length is indefinite
     */
    private function __construct(BigInteger|int $length, private readonly bool $_indefinite = \false)
    {
        $this->_length = BigInt::create($length);
    }
    public static function create(BigInteger|int $length, bool $_indefinite = \false): self
    {
        return new self($length, $_indefinite);
    }
    /**
     * Decode length component from DER data.
     *
     * @param string $data DER encoded data
     * @param null|int $offset Reference to the variable that contains offset
     * into the data where to start parsing.
     * Variable is updated to the offset next to the
     * parsed length component. If null, start from offset 0.
     */
    public static function fromDER(string $data, ?int &$offset = null): self
    {
        $idx = $offset ?? 0;
        $datalen = mb_strlen($data, '8bit');
        if ($idx >= $datalen) {
            throw new DecodeException('Unexpected end of data while decoding length.');
        }
        $indefinite = \false;
        $byte = ord($data[$idx++]);
        // bits 7 to 1
        $length = 0x7f & $byte;
        // long form
        if ((0x80 & $byte) !== 0) {
            if ($length === 0) {
                $indefinite = \true;
            } else {
                if ($idx + $length > $datalen) {
                    throw new DecodeException('Unexpected end of data while decoding long form length.');
                }
                $length = self::decodeLongFormLength($length, $data, $idx);
            }
        }
        if (isset($offset)) {
            $offset = $idx;
        }
        return self::create($length, $indefinite);
    }
    /**
     * Decode length from DER.
     *
     * Throws an exception if length doesn't match with expected or if data doesn't contain enough bytes.
     *
     * Requirement of definite length is relaxed contrary to the specification (sect. 10.1).
     *
     * @param string $data DER data
     * @param int $offset Reference to the offset variable
     * @param null|int $expected Expected length, null to bypass checking
     * @see self::fromDER
     */
    public static function expectFromDER(string $data, int &$offset, ?int $expected = null): self
    {
        $idx = $offset;
        $length = self::fromDER($data, $idx);
        // if certain length was expected
        if (isset($expected)) {
            if ($length->isIndefinite()) {
                throw new DecodeException(sprintf('Expected length %d, got indefinite.', $expected));
            }
            if ($expected !== $length->intLength()) {
                throw new DecodeException(sprintf('Expected length %d, got %d.', $expected, $length->intLength()));
            }
        }
        // check that enough data is available
        if (!$length->isIndefinite() && mb_strlen($data, '8bit') < $idx + $length->intLength()) {
            throw new DecodeException(sprintf('Length %d overflows data, %d bytes left.', $length->intLength(), mb_strlen($data, '8bit') - $idx));
        }
        $offset = $idx;
        return $length;
    }
    public function toDER(): string
    {
        $bytes = [];
        if ($this->_indefinite) {
            $bytes[] = 0x80;
        } else {
            $num = $this->_length->getValue();
            // long form
            if ($num->isGreaterThan(127)) {
                $octets = [];
                for (; $num->isGreaterThan(0); $num = $num->shiftedRight(8)) {
                    $octets[] = BigInteger::of(0xff)->and($num)->toInt();
                }
                $count = count($octets);
                // first octet must not be 0xff
                if ($count >= 127) {
                    throw new DomainException('Too many length octets.');
                }
                $bytes[] = 0x80 | $count;
                foreach (array_reverse($octets) as $octet) {
                    $bytes[] = $octet;
                }
            } else {
                $bytes[] = $num->toInt();
            }
        }
        return pack('C*', ...$bytes);
    }
    /**
     * Get the length.
     *
     * @return string Length as an integer string
     */
    public function length(): string
    {
        if ($this->_indefinite) {
            throw new LogicException('Length is indefinite.');
        }
        return $this->_length->base10();
    }
    /**
     * Get the length as an integer.
     */
    public function intLength(): int
    {
        if ($this->_indefinite) {
            throw new LogicException('Length is indefinite.');
        }
        return $this->_length->toInt();
    }
    /**
     * Whether length is indefinite.
     */
    public function isIndefinite(): bool
    {
        return $this->_indefinite;
    }
    /**
     * Decode long form length.
     *
     * @param int $length Number of octets
     * @param string $data Data
     * @param int $offset reference to the variable containing offset to the data
     */
    private static function decodeLongFormLength(int $length, string $data, int &$offset): BigInteger
    {
        // first octet must not be 0xff (spec 8.1.3.5c)
        if ($length === 127) {
            throw new DecodeException('Invalid number of length octets.');
        }
        $num = BigInteger::of(0);
        while (--$length >= 0) {
            $byte = ord($data[$offset++]);
            $num = $num->shiftedLeft(8)->or($byte);
        }
        return $num;
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\ASN1\Type;

/**
 * Trait for primitive types.
 */
trait PrimitiveType
{
    /**
     * @see \Sop\ASN1\Feature\ElementBase::isConstructed()
     */
    public function isConstructed(): bool
    {
        return \false;
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\ASN1\Type;

use InvalidArgumentException;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Element;
use function sprintf;
use Stringable;
/**
 * Base class for all string types.
 */
abstract class BaseString extends Element implements StringType, Stringable
{
    /**
     * String value.
     */
    private readonly string $string;
    protected function __construct(int $typeTag, string $string)
    {
        parent::__construct($typeTag);
        if (!$this->validateString($string)) {
            throw new InvalidArgumentException(sprintf('Not a valid %s string.', self::tagToName($this->typeTag)));
        }
        $this->string = $string;
    }
    public function __toString(): string
    {
        return $this->string();
    }
    /**
     * Get the string value.
     */
    public function string(): string
    {
        return $this->string;
    }
    protected function encodedAsDER(): string
    {
        return $this->string;
    }
    /**
     * Check whether string is valid for the concrete type.
     */
    protected function validateString(string $string): bool
    {
        // Override in derived classes
        return \true;
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Primitive;

use function mb_strlen;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\PrimitiveString;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\UniversalClass;
/**
 * Implements *BMPString* type.
 *
 * BMP stands for Basic Multilingual Plane. This is generally an Unicode string with UCS-2 encoding.
 */
final class BMPString extends PrimitiveString
{
    use UniversalClass;
    private function __construct(string $string)
    {
        parent::__construct(self::TYPE_BMP_STRING, $string);
    }
    public static function create(string $string): self
    {
        return new self($string);
    }
    protected function validateString(string $string): bool
    {
        // UCS-2 has fixed with of 2 octets (16 bits)
        return mb_strlen($string, '8bit') % 2 === 0;
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Primitive;

use function chr;
use function ord;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Component\Identifier;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Component\Length;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Element;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Exception\DecodeException;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Feature\ElementBase;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\PrimitiveType;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\UniversalClass;
/**
 * Implements *BOOLEAN* type.
 */
final class Boolean extends Element
{
    use UniversalClass;
    use PrimitiveType;
    private function __construct(private readonly bool $_bool)
    {
        parent::__construct(self::TYPE_BOOLEAN);
    }
    public static function create(bool $_bool): self
    {
        return new self($_bool);
    }
    /**
     * Get the value.
     */
    public function value(): bool
    {
        return $this->_bool;
    }
    protected function encodedAsDER(): string
    {
        return $this->_bool ? chr(0xff) : chr(0);
    }
    protected static function decodeFromDER(Identifier $identifier, string $data, int &$offset): ElementBase
    {
        $idx = $offset;
        Length::expectFromDER($data, $idx, 1);
        $byte = ord($data[$idx++]);
        if ($byte !== 0) {
            if ($byte !== 0xff) {
                throw new DecodeException('DER encoded boolean true must have all bits set to 1.');
            }
        }
        $offset = $idx;
        return self::create($byte !== 0);
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Primitive;

use _ContaoManager\Brick\Math\BigInteger;
use function gettype;
use InvalidArgumentException;
use function is_int;
use function is_scalar;
use function is_string;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Component\Identifier;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Component\Length;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Element;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Feature\ElementBase;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\PrimitiveType;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\UniversalClass;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Util\BigInt;
/**
 * Implements *INTEGER* type.
 */
class Integer extends Element
{
    use UniversalClass;
    use PrimitiveType;
    /**
     * The number.
     */
    private readonly BigInt $_number;
    /**
     * @param BigInteger|int|string $number Base 10 integer
     */
    final protected function __construct(BigInteger|int|string $number, int $typeTag)
    {
        parent::__construct($typeTag);
        if (!self::validateNumber($number)) {
            $var = is_scalar($number) ? (string) $number : gettype($number);
            throw new InvalidArgumentException("'{$var}' is not a valid number.");
        }
        $this->_number = BigInt::create($number);
    }
    public static function create(BigInteger|int|string $number): static
    {
        return new static($number, self::TYPE_INTEGER);
    }
    /**
     * Get the number as a base 10.
     *
     * @return string Integer as a string
     */
    public function number(): string
    {
        return $this->_number->base10();
    }
    public function getValue(): BigInteger
    {
        return $this->_number->getValue();
    }
    /**
     * Get the number as an integer type.
     */
    public function intNumber(): int
    {
        return $this->_number->toInt();
    }
    protected function encodedAsDER(): string
    {
        return $this->_number->signedOctets();
    }
    protected static function decodeFromDER(Identifier $identifier, string $data, int &$offset): ElementBase
    {
        $idx = $offset;
        $length = Length::expectFromDER($data, $idx)->intLength();
        $bytes = mb_substr($data, $idx, $length, '8bit');
        $idx += $length;
        $num = BigInt::fromSignedOctets($bytes)->getValue();
        $offset = $idx;
        // late static binding since enumerated extends integer type
        return static::create($num);
    }
    /**
     * Test that number is valid for this context.
     */
    private static function validateNumber(mixed $num): bool
    {
        if (is_int($num)) {
            return \true;
        }
        if (is_string($num) && preg_match('/-?\d+/', $num) === 1) {
            return \true;
        }
        if ($num instanceof BigInteger) {
            return \true;
        }
        return \false;
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Primitive;

use _ContaoManager\Brick\Math\BigInteger;
use function chr;
use function is_int;
use function ord;
use RuntimeException;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Component\Identifier;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Component\Length;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Element;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Exception\DecodeException;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Feature\ElementBase;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\PrimitiveType;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\UniversalClass;
use function sprintf;
use Throwable;
use UnexpectedValueException;
/**
 * Implements *RELATIVE-OID* type.
 */
final class RelativeOID extends Element
{
    use UniversalClass;
    use PrimitiveType;
    /**
     * Object identifier split to sub ID's.
     *
     * @var BigInteger[]
     */
    private readonly array $subids;
    /**
     * @param string $oid OID in dotted format
     */
    private function __construct(private readonly string $oid)
    {
        parent::__construct(self::TYPE_RELATIVE_OID);
        $this->subids = self::explodeDottedOID($oid);
    }
    public static function create(string $oid): self
    {
        return new self($oid);
    }
    /**
     * Get OID in dotted format.
     */
    public function oid(): string
    {
        return $this->oid;
    }
    protected function encodedAsDER(): string
    {
        return self::encodeSubIDs(...$this->subids);
    }
    protected static function decodeFromDER(Identifier $identifier, string $data, int &$offset): ElementBase
    {
        $idx = $offset;
        $len = Length::expectFromDER($data, $idx)->intLength();
        $subids = self::decodeSubIDs(mb_substr($data, $idx, $len, '8bit'));
        $offset = $idx + $len;
        return self::create(self::implodeSubIDs(...$subids));
    }
    /**
     * Explode dotted OID to an array of sub ID's.
     *
     * @param string $oid OID in dotted format
     *
     * @return BigInteger[] Array of BigInteger numbers
     */
    protected static function explodeDottedOID(string $oid): array
    {
        $subids = [];
        if ($oid !== '') {
            foreach (explode('.', $oid) as $subid) {
                try {
                    $n = BigInteger::of($subid);
                    $subids[] = $n;
                } catch (Throwable $e) {
                    throw new UnexpectedValueException(sprintf('"%s" is not a number.', $subid), 0, $e);
                }
            }
        }
        return $subids;
    }
    /**
     * Implode an array of sub IDs to dotted OID format.
     */
    protected static function implodeSubIDs(BigInteger ...$subids): string
    {
        return implode('.', array_map(static fn($num) => $num->toBase(10), $subids));
    }
    /**
     * Encode sub ID's to DER.
     */
    protected static function encodeSubIDs(BigInteger ...$subids): string
    {
        $data = '';
        foreach ($subids as $subid) {
            // if number fits to one base 128 byte
            if ($subid->isLessThan(128)) {
                $data .= chr($subid->toInt());
            } else {
                // encode to multiple bytes
                $bytes = [];
                do {
                    array_unshift($bytes, 0x7f & $subid->toInt());
                    $subid = $subid->shiftedRight(7);
                } while ($subid->isGreaterThan(0));
                // all bytes except last must have bit 8 set to one
                foreach (array_splice($bytes, 0, -1) as $byte) {
                    $data .= chr(0x80 | $byte);
                }
                $byte = reset($bytes);
                if (!is_int($byte)) {
                    throw new RuntimeException('Encoding failed');
                }
                $data .= chr($byte);
            }
        }
        return $data;
    }
    /**
     * Decode sub ID's from DER data.
     *
     * @return BigInteger[] Array of BigInteger numbers
     */
    protected static function decodeSubIDs(string $data): array
    {
        $subids = [];
        $idx = 0;
        $end = mb_strlen($data, '8bit');
        while ($idx < $end) {
            $num = BigInteger::of(0);
            while (\true) {
                if ($idx >= $end) {
                    throw new DecodeException('Unexpected end of data.');
                }
                $byte = ord($data[$idx++]);
                $num = $num->or($byte & 0x7f);
                // bit 8 of the last octet is zero
                if (0 === ($byte & 0x80)) {
                    break;
                }
                $num = $num->shiftedLeft(7);
            }
            $subids[] = $num;
        }
        return $subids;
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Primitive;

use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\PrimitiveString;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\UniversalClass;
/**
 * Implements *VisibleString* type.
 */
final class VisibleString extends PrimitiveString
{
    use UniversalClass;
    private function __construct(string $string)
    {
        parent::__construct(self::TYPE_VISIBLE_STRING, $string);
    }
    public static function create(string $string): self
    {
        return new self($string);
    }
    protected function validateString(string $string): bool
    {
        return preg_match('/[^\x20-\x7e]/', $string) !== 1;
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Primitive;

use _ContaoManager\Brick\Math\BigInteger;
use function gettype;
use InvalidArgumentException;
use function is_int;
use function is_scalar;
use function is_string;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Element;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\PrimitiveType;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\UniversalClass;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Util\BigInt;
use function sprintf;
use function strval;
abstract class Number extends Element
{
    use UniversalClass;
    use PrimitiveType;
    /**
     * The number.
     */
    private readonly BigInt $number;
    /**
     * @param BigInteger|int|string $number Base 10 integer
     */
    protected function __construct(int $tag, BigInteger|int|string $number)
    {
        parent::__construct($tag);
        if (!self::validateNumber($number)) {
            $var = is_scalar($number) ? strval($number) : gettype($number);
            throw new InvalidArgumentException(sprintf('"%s" is not a valid number.', $var));
        }
        $this->number = BigInt::create($number);
    }
    abstract public static function create(BigInteger|int|string $number): self;
    /**
     * Get the number as a base 10.
     *
     * @return string Integer as a string
     */
    public function number(): string
    {
        return $this->number->base10();
    }
    public function getValue(): BigInteger
    {
        return $this->number->getValue();
    }
    /**
     * Get the number as an integer type.
     */
    public function intNumber(): int
    {
        return $this->number->toInt();
    }
    protected function encodedAsDER(): string
    {
        return $this->number->signedOctets();
    }
    /**
     * Test that number is valid for this context.
     */
    private static function validateNumber(mixed $num): bool
    {
        if (is_int($num)) {
            return \true;
        }
        if (is_string($num) && preg_match('/-?\d+/', $num) === 1) {
            return \true;
        }
        if ($num instanceof BigInteger) {
            return \true;
        }
        return \false;
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Primitive;

use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\PrimitiveString;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\UniversalClass;
/**
 * Implements *UTF8String* type.
 *
 * UTF8String* is an Unicode string with UTF-8 encoding.
 */
final class UTF8String extends PrimitiveString
{
    use UniversalClass;
    private function __construct(string $string)
    {
        parent::__construct(self::TYPE_UTF8_STRING, $string);
    }
    public static function create(string $string): self
    {
        return new self($string);
    }
    protected function validateString(string $string): bool
    {
        return mb_check_encoding($string, 'UTF-8');
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Primitive;

use _ContaoManager\Brick\Math\BigInteger;
use function chr;
use function mb_strlen;
use function ord;
use OutOfBoundsException;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Component\Identifier;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Component\Length;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Exception\DecodeException;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Feature\ElementBase;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\BaseString;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\PrimitiveType;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\UniversalClass;
/**
 * Implements *BIT STRING* type.
 */
final class BitString extends BaseString
{
    use UniversalClass;
    use PrimitiveType;
    /**
     * @param string $string Content octets
     * @param int $unusedBits Number of unused bits in the last octet
     */
    private function __construct(string $string, private readonly int $unusedBits = 0)
    {
        parent::__construct(self::TYPE_BIT_STRING, $string);
    }
    public static function create(string $string, int $_unusedBits = 0): self
    {
        return new self($string, $_unusedBits);
    }
    /**
     * Get the number of bits in the string.
     */
    public function numBits(): int
    {
        return mb_strlen($this->string(), '8bit') * 8 - $this->unusedBits;
    }
    /**
     * Get the number of unused bits in the last octet of the string.
     */
    public function unusedBits(): int
    {
        return $this->unusedBits;
    }
    /**
     * Test whether bit is set.
     *
     * @param int $idx Bit index. Most significant bit of the first octet is index 0.
     */
    public function testBit(int $idx): bool
    {
        // octet index
        $oi = (int) floor($idx / 8);
        // if octet is outside range
        if ($oi < 0 || $oi >= mb_strlen($this->string(), '8bit')) {
            throw new OutOfBoundsException('Index is out of bounds.');
        }
        // bit index
        $bi = $idx % 8;
        // if tested bit is last octet's unused bit
        if ($oi === mb_strlen($this->string(), '8bit') - 1) {
            if ($bi >= 8 - $this->unusedBits) {
                throw new OutOfBoundsException('Index refers to an unused bit.');
            }
        }
        $byte = $this->string()[$oi];
        // index 0 is the most significant bit in byte
        $mask = 0x1 << 7 - $bi;
        return (ord($byte) & $mask) > 0;
    }
    /**
     * Get range of bits.
     *
     * @param int $start Index of first bit
     * @param int $length Number of bits in range
     *
     * @return string Integer of $length bits
     */
    public function range(int $start, int $length): string
    {
        if ($length === 0) {
            return '0';
        }
        if ($start + $length > $this->numBits()) {
            throw new OutOfBoundsException('Not enough bits.');
        }
        $bits = BigInteger::of(0);
        $idx = $start;
        $end = $start + $length;
        while (\true) {
            $bit = $this->testBit($idx) ? 1 : 0;
            $bits = $bits->or($bit);
            if (++$idx >= $end) {
                break;
            }
            $bits = $bits->shiftedLeft(1);
        }
        return $bits->toBase(10);
    }
    /**
     * Get a copy of the bit string with trailing zeroes removed.
     */
    public function withoutTrailingZeroes(): self
    {
        // if bit string was empty
        if ($this->string() === '') {
            return self::create('');
        }
        $bits = $this->string();
        // count number of empty trailing octets
        $unused_octets = 0;
        for ($idx = mb_strlen($bits, '8bit') - 1; $idx >= 0; --$idx, ++$unused_octets) {
            if ($bits[$idx] !== "\x00") {
                break;
            }
        }
        // strip trailing octets
        if ($unused_octets !== 0) {
            $bits = mb_substr($bits, 0, -$unused_octets, '8bit');
        }
        // if bit string was full of zeroes
        if ($bits === '') {
            return self::create('');
        }
        // count number of trailing zeroes in the last octet
        $unused_bits = 0;
        $byte = ord($bits[mb_strlen($bits, '8bit') - 1]);
        while (0 === ($byte & 0x1)) {
            ++$unused_bits;
            $byte >>= 1;
        }
        return self::create($bits, $unused_bits);
    }
    protected function encodedAsDER(): string
    {
        $der = chr($this->unusedBits);
        $der .= $this->string();
        if ($this->unusedBits !== 0) {
            $octet = $der[mb_strlen($der, '8bit') - 1];
            // set unused bits to zero
            $octet &= chr(0xff & ~((1 << $this->unusedBits) - 1));
            $der[mb_strlen($der, '8bit') - 1] = $octet;
        }
        return $der;
    }
    protected static function decodeFromDER(Identifier $identifier, string $data, int &$offset): ElementBase
    {
        $idx = $offset;
        $length = Length::expectFromDER($data, $idx);
        if ($length->intLength() < 1) {
            throw new DecodeException('Bit string length must be at least 1.');
        }
        $unused_bits = ord($data[$idx++]);
        if ($unused_bits > 7) {
            throw new DecodeException('Unused bits in a bit string must be less than 8.');
        }
        $str_len = $length->intLength() - 1;
        if ($str_len !== 0) {
            $str = mb_substr($data, $idx, $str_len, '8bit');
            if ($unused_bits !== 0) {
                $mask = (1 << $unused_bits) - 1;
                if (($mask & ord($str[mb_strlen($str, '8bit') - 1])) !== 0) {
                    throw new DecodeException('DER encoded bit string must have zero padding.');
                }
            }
        } else {
            $str = '';
        }
        $offset = $idx + $str_len;
        return self::create($str, $unused_bits);
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Primitive;

use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\PrimitiveString;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\UniversalClass;
/**
 * Implements *IA5String* type.
 */
final class IA5String extends PrimitiveString
{
    use UniversalClass;
    private function __construct(string $string)
    {
        parent::__construct(self::TYPE_IA5_STRING, $string);
    }
    public static function create(string $string): self
    {
        return new self($string);
    }
    protected function validateString(string $string): bool
    {
        return preg_match('/[^\x00-\x7f]/', $string) !== 1;
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Primitive;

use function mb_strlen;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\PrimitiveString;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\UniversalClass;
/**
 * Implements *UniversalString* type.
 *
 * Universal string is an Unicode string with UCS-4 encoding.
 */
final class UniversalString extends PrimitiveString
{
    use UniversalClass;
    private function __construct(string $string)
    {
        parent::__construct(self::TYPE_UNIVERSAL_STRING, $string);
    }
    public static function create(string $string): self
    {
        return new self($string);
    }
    protected function validateString(string $string): bool
    {
        // UCS-4 has fixed with of 4 octets (32 bits)
        if (mb_strlen($string, '8bit') % 4 !== 0) {
            return \false;
        }
        return \true;
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Primitive;

use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\PrimitiveString;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\UniversalClass;
/**
 * Implements *GraphicString* type.
 */
final class GraphicString extends PrimitiveString
{
    use UniversalClass;
    private function __construct(string $string)
    {
        parent::__construct(self::TYPE_GRAPHIC_STRING, $string);
    }
    public static function create(string $string): self
    {
        return new self($string);
    }
    protected function validateString(string $string): bool
    {
        // allow everything
        return \true;
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Primitive;

use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\PrimitiveString;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\UniversalClass;
/**
 * Implements *ObjectDescriptor* type.
 */
final class ObjectDescriptor extends PrimitiveString
{
    use UniversalClass;
    private function __construct(string $descriptor)
    {
        parent::__construct(self::TYPE_OBJECT_DESCRIPTOR, $descriptor);
    }
    public static function create(string $descriptor): self
    {
        return new self($descriptor);
    }
    /**
     * Get the object descriptor.
     */
    public function descriptor(): string
    {
        return $this->string();
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Primitive;

use function assert;
use _ContaoManager\Brick\Math\BigInteger;
use function chr;
use function count;
use function in_array;
use const INF;
use LogicException;
use function mb_strlen;
use function ord;
use RangeException;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Component\Identifier;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Component\Length;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Element;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Exception\DecodeException;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Feature\ElementBase;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\PrimitiveType;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\UniversalClass;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Util\BigInt;
use function sprintf;
use Stringable;
use UnexpectedValueException;
/**
 * Implements *REAL* type.
 */
final class Real extends Element implements Stringable
{
    use UniversalClass;
    use PrimitiveType;
    /**
     * Regex pattern to parse NR1 form number.
     *
     * @var string
     */
    final public const NR1_REGEX = '/^\s*' . '(?<s>[+\-])?' . '(?<i>\d+)' . '$/';
    /**
     * Regex pattern to parse NR2 form number.
     *
     * @var string
     */
    final public const NR2_REGEX = '/^\s*' . '(?<s>[+\-])?' . '(?<d>(?:\d+[\.,]\d*)|(?:\d*[\.,]\d+))' . '$/';
    /**
     * Regex pattern to parse NR3 form number.
     *
     * @var string
     */
    final public const NR3_REGEX = '/^\s*' . '(?<ms>[+\-])?' . '(?<m>(?:\d+[\.,]\d*)|(?:\d*[\.,]\d+))' . '[Ee](?<es>[+\-])?' . '(?<e>\d+)' . '$/';
    /**
     * Regex pattern to parse PHP exponent number format.
     *
     * @see http://php.net/manual/en/language.types.float.php
     *
     * @var string
     */
    final public const PHP_EXPONENT_DNUM = '/^' . '(?<ms>[+\-])?' . '(?<m>' . '\d+' . '|' . '(?:\d*\.\d+|\d+\.\d*)' . ')[eE]' . '(?<es>[+\-])?(?<e>\d+)' . '$/';
    /**
     * Exponent when value is positive or negative infinite.
     *
     * @var int
     */
    final public const INF_EXPONENT = 2047;
    /**
     * Exponent bias for IEEE 754 double precision float.
     *
     * @var int
     */
    final public const EXP_BIAS = -1023;
    /**
     * Signed integer mantissa.
     */
    private readonly BigInt $_mantissa;
    /**
     * Signed integer exponent.
     */
    private readonly BigInt $_exponent;
    /**
     * Abstract value base.
     *
     * Must be 2 or 10.
     */
    private readonly int $_base;
    /**
     * Whether to encode strictly in DER.
     */
    private bool $_strictDer;
    /**
     * Number as a native float.
     *
     * @internal Lazily initialized
     */
    private ?float $_float = null;
    /**
     * @param BigInteger|int|string $mantissa Integer mantissa
     * @param BigInteger|int|string $exponent Integer exponent
     * @param int $base Base, 2 or 10
     */
    private function __construct(BigInteger|int|string $mantissa, BigInteger|int|string $exponent, int $base = 10)
    {
        if ($base !== 10 && $base !== 2) {
            throw new UnexpectedValueException('Base must be 2 or 10.');
        }
        parent::__construct(self::TYPE_REAL);
        $this->_strictDer = \true;
        $this->_mantissa = BigInt::create($mantissa);
        $this->_exponent = BigInt::create($exponent);
        $this->_base = $base;
    }
    public function __toString(): string
    {
        return sprintf('%g', $this->floatVal());
    }
    public static function create(BigInteger|int|string $mantissa, BigInteger|int|string $exponent, int $base = 10): self
    {
        return new self($mantissa, $exponent, $base);
    }
    /**
     * Create base 2 real number from float.
     */
    public static function fromFloat(float $number): self
    {
        if (is_infinite($number)) {
            return self::fromInfinite($number);
        }
        if (is_nan($number)) {
            throw new UnexpectedValueException('NaN values not supported.');
        }
        [$m, $e] = self::parse754Double(pack('E', $number));
        return self::create($m, $e, 2);
    }
    /**
     * Create base 10 real number from string.
     *
     * @param string $number Real number in base-10 textual form
     */
    public static function fromString(string $number): self
    {
        [$m, $e] = self::parseString($number);
        return self::create($m, $e, 10);
    }
    /**
     * Get self with strict DER flag set or unset.
     *
     * @param bool $strict whether to encode strictly in DER
     */
    public function withStrictDER(bool $strict): self
    {
        $obj = clone $this;
        $obj->_strictDer = $strict;
        return $obj;
    }
    /**
     * Get the mantissa.
     */
    public function mantissa(): BigInt
    {
        return $this->_mantissa;
    }
    /**
     * Get the exponent.
     */
    public function exponent(): BigInt
    {
        return $this->_exponent;
    }
    /**
     * Get the base.
     */
    public function base(): int
    {
        return $this->_base;
    }
    /**
     * Get number as a float.
     */
    public function floatVal(): float
    {
        if (!isset($this->_float)) {
            $m = $this->_mantissa->toInt();
            $e = $this->_exponent->toInt();
            $this->_float = (float) ($m * $this->_base ** $e);
        }
        return $this->_float;
    }
    /**
     * Get number as a NR3 form string conforming to DER rules.
     */
    public function nr3Val(): string
    {
        // convert to base 10
        if ($this->_base === 2) {
            [$m, $e] = self::parseString(sprintf('%15E', $this->floatVal()));
        } else {
            $m = $this->_mantissa->getValue();
            $e = $this->_exponent->getValue();
        }
        $zero = BigInteger::of(0);
        $ten = BigInteger::of(10);
        // shift trailing zeroes from the mantissa to the exponent
        // (X.690 07-2002, section 11.3.2.4)
        while (!$m->isEqualTo($zero) && $m->mod($ten)->isEqualTo($zero)) {
            $m = $m->dividedBy($ten);
            $e = $e->plus(1);
        }
        // if exponent is zero, it must be prefixed with a "+" sign
        // (X.690 07-2002, section 11.3.2.6)
        if ($e->isEqualTo(0)) {
            $es = '+';
        } else {
            $es = $e->isLessThan(0) ? '-' : '';
        }
        return sprintf('%s.E%s%s', $m->toBase(10), $es, $e->abs()->toBase(10));
    }
    protected function encodedAsDER(): string
    {
        $infExponent = BigInteger::of(self::INF_EXPONENT);
        if ($this->_exponent->getValue()->isEqualTo($infExponent)) {
            return $this->encodeSpecial();
        }
        // if the real value is the value zero, there shall be no contents
        // octets in the encoding. (X.690 07-2002, section 8.5.2)
        if ($this->_mantissa->getValue()->toBase(10) === '0') {
            return '';
        }
        if ($this->_base === 10) {
            return $this->encodeDecimal();
        }
        return $this->encodeBinary();
    }
    /**
     * Encode in binary format.
     */
    protected function encodeBinary(): string
    {
        /** @var BigInteger $m */
        /** @var BigInteger $e */
        /** @var int $sign */
        [$base, $sign, $m, $e] = $this->prepareBinaryEncoding();
        $zero = BigInteger::of(0);
        $byte = 0x80;
        if ($sign < 0) {
            $byte |= 0x40;
        }
        // normalization: mantissa must be 0 or odd
        if ($base === 2) {
            // while last bit is zero
            while ($m->isGreaterThan(0) && $m->and(0x1)->isEqualTo($zero)) {
                $m = $m->shiftedRight(1);
                $e = $e->plus(1);
            }
        } elseif ($base === 8) {
            $byte |= 0x10;
            // while last 3 bits are zero
            while ($m->isGreaterThan(0) && $m->and(0x7)->isEqualTo($zero)) {
                $m = $m->shiftedRight(3);
                $e = $e->plus(1);
            }
        } else {
            // base === 16
            $byte |= 0x20;
            // while last 4 bits are zero
            while ($m->isGreaterThan(0) && $m->and(0xf)->isEqualTo($zero)) {
                $m = $m->shiftedRight(4);
                $e = $e->plus(1);
            }
        }
        // scale factor
        $scale = 0;
        while ($m->isGreaterThan(0) && $m->and(0x1)->isEqualTo($zero)) {
            $m = $m->shiftedRight(1);
            ++$scale;
        }
        $byte |= ($scale & 0x3) << 2;
        // encode exponent
        $exp_bytes = BigInt::create($e)->signedOctets();
        $exp_len = mb_strlen($exp_bytes, '8bit');
        if ($exp_len > 0xff) {
            throw new RangeException('Exponent encoding is too long.');
        }
        if ($exp_len <= 3) {
            $byte |= $exp_len - 1 & 0x3;
            $bytes = chr($byte);
        } else {
            $byte |= 0x3;
            $bytes = chr($byte) . chr($exp_len);
        }
        $bytes .= $exp_bytes;
        // encode mantissa
        $bytes .= BigInt::create($m)->unsignedOctets();
        return $bytes;
    }
    /**
     * Encode in decimal format.
     */
    protected function encodeDecimal(): string
    {
        // encode in NR3 decimal encoding
        return chr(0x3) . $this->nr3Val();
    }
    /**
     * Encode special value.
     */
    protected function encodeSpecial(): string
    {
        return match ($this->_mantissa->toInt()) {
            1 => chr(0x40),
            -1 => chr(0x41),
            default => throw new LogicException('Invalid special value.'),
        };
    }
    protected static function decodeFromDER(Identifier $identifier, string $data, int &$offset): ElementBase
    {
        $idx = $offset;
        $length = Length::expectFromDER($data, $idx)->intLength();
        // if length is zero, value is zero (spec 8.5.2)
        if ($length === 0) {
            $obj = self::create(0, 0, 10);
        } else {
            $bytes = mb_substr($data, $idx, $length, '8bit');
            $byte = ord($bytes[0]);
            if ((0x80 & $byte) !== 0) {
                // bit 8 = 1
                $obj = self::decodeBinaryEncoding($bytes);
            } elseif ($byte >> 6 === 0x0) {
                // bit 8 = 0, bit 7 = 0
                $obj = self::decodeDecimalEncoding($bytes);
            } else {
                // bit 8 = 0, bit 7 = 1
                $obj = self::decodeSpecialRealValue($bytes);
            }
        }
        $offset = $idx + $length;
        return $obj;
    }
    /**
     * Decode binary encoding.
     */
    protected static function decodeBinaryEncoding(string $data): self
    {
        $byte = ord($data[0]);
        // bit 7 is set if mantissa is negative
        $neg = (bool) (0x40 & $byte);
        $base = match ($byte >> 4 & 0x3) {
            0b0 => 2,
            0b1 => 8,
            0b10 => 16,
            default => throw new DecodeException('Reserved REAL binary encoding base not supported.'),
        };
        // scaling factor in bits 4 and 3
        $scale = $byte >> 2 & 0x3;
        $idx = 1;
        // content length in bits 2 and 1
        $len = ($byte & 0x3) + 1;
        // if both bits are set, the next octet encodes the length
        if ($len > 3) {
            if (mb_strlen($data, '8bit') < 2) {
                throw new DecodeException('Unexpected end of data while decoding REAL exponent length.');
            }
            $len = ord($data[1]);
            $idx = 2;
        }
        if (mb_strlen($data, '8bit') < $idx + $len) {
            throw new DecodeException('Unexpected end of data while decoding REAL exponent.');
        }
        // decode exponent
        $octets = mb_substr($data, $idx, $len, '8bit');
        $exp = BigInt::fromSignedOctets($octets)->getValue();
        if ($base === 8) {
            $exp = $exp->multipliedBy(3);
        } elseif ($base === 16) {
            $exp = $exp->multipliedBy(4);
        }
        if (mb_strlen($data, '8bit') <= $idx + $len) {
            throw new DecodeException('Unexpected end of data while decoding REAL mantissa.');
        }
        // decode mantissa
        $octets = mb_substr($data, $idx + $len, null, '8bit');
        $n = BigInt::fromUnsignedOctets($octets)->getValue();
        $n = $n->multipliedBy(2 ** $scale);
        if ($neg) {
            $n = $n->negated();
        }
        return self::create($n, $exp, 2);
    }
    /**
     * Decode decimal encoding.
     */
    protected static function decodeDecimalEncoding(string $data): self
    {
        $nr = ord($data[0]) & 0x3f;
        if (!in_array($nr, [1, 2, 3], \true)) {
            throw new DecodeException('Unsupported decimal encoding form.');
        }
        $str = mb_substr($data, 1, null, '8bit');
        return self::fromString($str);
    }
    /**
     * Decode special encoding.
     */
    protected static function decodeSpecialRealValue(string $data): self
    {
        if (mb_strlen($data, '8bit') !== 1) {
            throw new DecodeException('SpecialRealValue must have one content octet.');
        }
        $byte = ord($data[0]);
        if ($byte === 0x40) {
            // positive infinity
            return self::fromInfinite(INF);
        }
        if ($byte === 0x41) {
            // negative infinity
            return self::fromInfinite(-INF);
        }
        throw new DecodeException('Invalid SpecialRealValue encoding.');
    }
    /**
     * Prepare value for binary encoding.
     *
     * @return array<int|BigInteger> (int) base, (int) sign, (BigInteger) mantissa and (BigInteger) exponent
     */
    protected function prepareBinaryEncoding(): array
    {
        $base = 2;
        $m = $this->_mantissa->getValue();
        $ms = $m->getSign();
        $m = BigInteger::of($m->abs());
        $e = $this->_exponent->getValue();
        $es = $e->getSign();
        $e = BigInteger::of($e->abs());
        $zero = BigInteger::of(0);
        $three = BigInteger::of(3);
        $four = BigInteger::of(4);
        // DER uses only base 2 binary encoding
        if (!$this->_strictDer) {
            if ($e->mod($four)->isEqualTo($zero)) {
                $base = 16;
                $e = $e->dividedBy(4);
            } elseif ($e->mod($three)->isEqualTo($zero)) {
                $base = 8;
                $e = $e->dividedBy(3);
            }
        }
        return [$base, $ms, $m, $e->multipliedBy($es)];
    }
    /**
     * Initialize from INF or -INF.
     */
    private static function fromInfinite(float $inf): self
    {
        return self::create($inf === -INF ? -1 : 1, self::INF_EXPONENT, 2);
    }
    /**
     * Parse IEEE 754 big endian formatted double precision float to base 2 mantissa and exponent.
     *
     * @param string $octets 64 bits
     *
     * @return BigInteger[] Tuple of mantissa and exponent
     */
    private static function parse754Double(string $octets): array
    {
        assert($octets !== '');
        $n = BigInteger::fromBytes($octets, \false);
        // sign bit
        $neg = $n->shiftedRight(63)->isOdd();
        // 11 bits of biased exponent
        $exponentMask = BigInteger::fromBase('7ff0000000000000', 16);
        $exp = $n->and($exponentMask)->shiftedRight(52)->plus(self::EXP_BIAS);
        // 52 bits of mantissa
        $mantissaMask = BigInteger::fromBase('fffffffffffff', 16);
        $man = $n->and($mantissaMask);
        // zero, ASN.1 doesn't differentiate -0 from +0
        $zero = BigInteger::of(0);
        if ($exp->isEqualTo(self::EXP_BIAS) && $man->isEqualTo($zero)) {
            return [BigInteger::of(0), BigInteger::of(0)];
        }
        // denormalized value, shift binary point
        if ($exp->isEqualTo(self::EXP_BIAS)) {
            $exp = $exp->plus(1);
        } else {
            $man = $man->or(BigInteger::of(1)->shiftedLeft(52));
        }
        // find the last fraction bit that is set
        $last = 0;
        while (!$man->shiftedRight($last)->isOdd() && $last !== 52) {
            $last++;
        }
        $bits_for_fraction = 52 - $last;
        // adjust mantissa and exponent so that we have integer values
        $man = $man->shiftedRight($last);
        $exp = $exp->minus($bits_for_fraction);
        // negate mantissa if number was negative
        if ($neg) {
            $man = $man->negated();
        }
        return [$man, $exp];
    }
    /**
     * Parse textual REAL number to base 10 mantissa and exponent.
     *
     * @param string $str Number
     *
     * @return BigInteger[] Tuple of mantissa and exponent
     */
    private static function parseString(string $str): array
    {
        // PHP exponent format
        if (preg_match(self::PHP_EXPONENT_DNUM, $str, $match) === 1) {
            [$m, $e] = self::parsePHPExponentMatch($match);
        } elseif (preg_match(self::NR3_REGEX, $str, $match) === 1) {
            [$m, $e] = self::parseNR3Match($match);
        } elseif (preg_match(self::NR2_REGEX, $str, $match) === 1) {
            [$m, $e] = self::parseNR2Match($match);
        } elseif (preg_match(self::NR1_REGEX, $str, $match) === 1) {
            [$m, $e] = self::parseNR1Match($match);
        } else {
            throw new UnexpectedValueException("{$str} could not be parsed to REAL.");
        }
        // normalize so that mantissa has no trailing zeroes
        $zero = BigInteger::of(0);
        $ten = BigInteger::of(10);
        while (!$m->isEqualTo($zero) && $m->mod($ten)->isEqualTo($zero)) {
            $m = $m->dividedBy($ten);
            $e = $e->plus(1);
        }
        return [$m, $e];
    }
    /**
     * Parse PHP form float to base 10 mantissa and exponent.
     *
     * @param array<string> $match Regexp match
     *
     * @return BigInteger[] Tuple of mantissa and exponent
     */
    private static function parsePHPExponentMatch(array $match): array
    {
        // mantissa sign
        $ms = $match['ms'] === '-' ? -1 : 1;
        $m_parts = explode('.', $match['m']);
        // integer part of the mantissa
        $int = ltrim($m_parts[0], '0');
        // exponent sign
        $es = $match['es'] === '-' ? -1 : 1;
        // signed exponent
        $e = BigInteger::of($match['e'])->multipliedBy($es);
        // if mantissa had fractional part
        if (count($m_parts) === 2) {
            $frac = rtrim($m_parts[1], '0');
            $e = $e->minus(mb_strlen($frac, '8bit'));
            $int .= $frac;
        }
        $m = BigInteger::of($int)->multipliedBy($ms);
        return [$m, $e];
    }
    /**
     * Parse NR3 form number to base 10 mantissa and exponent.
     *
     * @param array<string> $match Regexp match
     *
     * @return BigInteger[] Tuple of mantissa and exponent
     */
    private static function parseNR3Match(array $match): array
    {
        // mantissa sign
        $ms = $match['ms'] === '-' ? -1 : 1;
        // explode mantissa to integer and fraction parts
        [$int, $frac] = explode('.', str_replace(',', '.', $match['m']));
        $int = ltrim($int, '0');
        $frac = rtrim($frac, '0');
        // exponent sign
        $es = $match['es'] === '-' ? -1 : 1;
        // signed exponent
        $e = BigInteger::of($match['e'])->multipliedBy($es);
        // shift exponent by the number of base 10 fractions
        $e = $e->minus(mb_strlen($frac, '8bit'));
        // insert fractions to integer part and produce signed mantissa
        $int .= $frac;
        if ($int === '') {
            $int = '0';
        }
        $m = BigInteger::of($int)->multipliedBy($ms);
        return [$m, $e];
    }
    /**
     * Parse NR2 form number to base 10 mantissa and exponent.
     *
     * @param array<string> $match Regexp match
     *
     * @return BigInteger[] Tuple of mantissa and exponent
     */
    private static function parseNR2Match(array $match): array
    {
        $sign = $match['s'] === '-' ? -1 : 1;
        // explode decimal number to integer and fraction parts
        [$int, $frac] = explode('.', str_replace(',', '.', $match['d']));
        $int = ltrim($int, '0');
        $frac = rtrim($frac, '0');
        // shift exponent by the number of base 10 fractions
        $e = BigInteger::of(0);
        $e = $e->minus(mb_strlen($frac, '8bit'));
        // insert fractions to integer part and produce signed mantissa
        $int .= $frac;
        if ($int === '') {
            $int = '0';
        }
        $m = BigInteger::of($int)->multipliedBy($sign);
        return [$m, $e];
    }
    /**
     * Parse NR1 form number to base 10 mantissa and exponent.
     *
     * @param array<string> $match Regexp match
     *
     * @return BigInteger[] Tuple of mantissa and exponent
     */
    private static function parseNR1Match(array $match): array
    {
        $sign = $match['s'] === '-' ? -1 : 1;
        $int = ltrim($match['i'], '0');
        if ($int === '') {
            $int = '0';
        }
        $m = BigInteger::of($int)->multipliedBy($sign);
        return [$m, BigInteger::of(0)];
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Primitive;

use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\PrimitiveString;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\UniversalClass;
/**
 * Implements *PrintableString* type.
 */
final class PrintableString extends PrimitiveString
{
    use UniversalClass;
    private function __construct(string $string)
    {
        parent::__construct(self::TYPE_PRINTABLE_STRING, $string);
    }
    public static function create(string $string): self
    {
        return new self($string);
    }
    protected function validateString(string $string): bool
    {
        $chars = preg_quote(" '()+,-./:=?]", '/');
        return preg_match('/[^A-Za-z0-9' . $chars . ']/', $string) !== 1;
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Primitive;

use _ContaoManager\SpomkyLabs\Pki\ASN1\Component\Identifier;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Component\Length;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Element;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Exception\DecodeException;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Feature\ElementBase;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\PrimitiveType;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\UniversalClass;
/**
 * Implements *End-of-contents* type.
 */
final class EOC extends Element
{
    use UniversalClass;
    use PrimitiveType;
    private function __construct()
    {
        parent::__construct(self::TYPE_EOC);
    }
    public static function create(): self
    {
        return new self();
    }
    protected function encodedAsDER(): string
    {
        return '';
    }
    protected static function decodeFromDER(Identifier $identifier, string $data, int &$offset): ElementBase
    {
        $idx = $offset;
        if (!$identifier->isPrimitive()) {
            throw new DecodeException('EOC value must be primitive.');
        }
        // EOC type has always zero length
        Length::expectFromDER($data, $idx, 0);
        $offset = $idx;
        return self::create();
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Primitive;

use _ContaoManager\SpomkyLabs\Pki\ASN1\Component\Identifier;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Component\Length;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Element;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Exception\DecodeException;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Feature\ElementBase;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\PrimitiveType;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\UniversalClass;
/**
 * Implements *NULL* type.
 */
final class NullType extends Element
{
    use UniversalClass;
    use PrimitiveType;
    private function __construct()
    {
        parent::__construct(self::TYPE_NULL);
    }
    public static function create(): self
    {
        return new self();
    }
    protected function encodedAsDER(): string
    {
        return '';
    }
    protected static function decodeFromDER(Identifier $identifier, string $data, int &$offset): ElementBase
    {
        $idx = $offset;
        if (!$identifier->isPrimitive()) {
            throw new DecodeException('Null value must be primitive.');
        }
        // null type has always zero length
        Length::expectFromDER($data, $idx, 0);
        $offset = $idx;
        return self::create();
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Primitive;

use _ContaoManager\Brick\Math\BigInteger;
use function chr;
use function count;
use function is_int;
use function mb_strlen;
use function ord;
use RuntimeException;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Component\Identifier;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Component\Length;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Element;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Exception\DecodeException;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Feature\ElementBase;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\PrimitiveType;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\UniversalClass;
use function sprintf;
use Throwable;
use UnexpectedValueException;
/**
 * Implements *OBJECT IDENTIFIER* type.
 */
final class ObjectIdentifier extends Element
{
    use UniversalClass;
    use PrimitiveType;
    /**
     * Object identifier split to sub ID's.
     *
     * @var BigInteger[]
     */
    private readonly array $subids;
    /**
     * @param string $oid OID in dotted format
     */
    private function __construct(private readonly string $oid, ?int $typeTag)
    {
        $this->subids = self::explodeDottedOID($oid);
        // if OID is non-empty
        if (count($this->subids) > 0) {
            // check that at least two nodes are set
            if (count($this->subids) < 2) {
                throw new UnexpectedValueException('OID must have at least two nodes.');
            }
            // check that root arc is in 0..2 range
            if ($this->subids[0]->isGreaterThan(2)) {
                throw new UnexpectedValueException('Root arc must be in range of 0..2.');
            }
            // if root arc is 0 or 1, second node must be in 0..39 range
            if ($this->subids[0]->isLessThan(2) && $this->subids[1]->isGreaterThanOrEqualTo(40)) {
                throw new UnexpectedValueException('Second node must be in 0..39 range for root arcs 0 and 1.');
            }
        }
        parent::__construct($typeTag ?? self::TYPE_OBJECT_IDENTIFIER);
    }
    public static function create(string $oid, ?int $typeTag = null): self
    {
        return new self($oid, $typeTag);
    }
    /**
     * Get OID in dotted format.
     */
    public function oid(): string
    {
        return $this->oid;
    }
    protected function encodedAsDER(): string
    {
        $subids = $this->subids;
        // encode first two subids to one according to spec section 8.19.4
        if (count($subids) >= 2) {
            $num = $subids[0]->multipliedBy(40)->plus($subids[1]);
            array_splice($subids, 0, 2, [$num]);
        }
        return self::encodeSubIDs(...$subids);
    }
    protected static function decodeFromDER(Identifier $identifier, string $data, int &$offset): ElementBase
    {
        $idx = $offset;
        $len = Length::expectFromDER($data, $idx)->intLength();
        $subids = self::decodeSubIDs(mb_substr($data, $idx, $len, '8bit'));
        $idx += $len;
        // decode first subidentifier according to spec section 8.19.4
        if (isset($subids[0])) {
            if ($subids[0]->isLessThan(80)) {
                [$x, $y] = $subids[0]->quotientAndRemainder(40);
            } else {
                $x = BigInteger::of(2);
                $y = $subids[0]->minus(80);
            }
            array_splice($subids, 0, 1, [$x, $y]);
        }
        $offset = $idx;
        return self::create(self::implodeSubIDs(...$subids));
    }
    /**
     * Explode dotted OID to an array of sub ID's.
     *
     * @param string $oid OID in dotted format
     *
     * @return BigInteger[] Array of BigInteger numbers
     */
    protected static function explodeDottedOID(string $oid): array
    {
        $subids = [];
        if ($oid !== '') {
            foreach (explode('.', $oid) as $subid) {
                try {
                    $n = BigInteger::of($subid);
                    $subids[] = $n;
                } catch (Throwable $e) {
                    throw new UnexpectedValueException(sprintf('"%s" is not a number.', $subid), 0, $e);
                }
            }
        }
        return $subids;
    }
    /**
     * Implode an array of sub IDs to dotted OID format.
     */
    protected static function implodeSubIDs(BigInteger ...$subids): string
    {
        return implode('.', array_map(static fn($num) => $num->toBase(10), $subids));
    }
    /**
     * Encode sub ID's to DER.
     */
    protected static function encodeSubIDs(BigInteger ...$subids): string
    {
        $data = '';
        foreach ($subids as $subid) {
            // if number fits to one base 128 byte
            if ($subid->isLessThan(128)) {
                $data .= chr($subid->toInt());
            } else {
                // encode to multiple bytes
                $bytes = [];
                do {
                    array_unshift($bytes, 0x7f & $subid->toInt());
                    $subid = $subid->shiftedRight(7);
                } while ($subid->isGreaterThan(0));
                // all bytes except last must have bit 8 set to one
                foreach (array_splice($bytes, 0, -1) as $byte) {
                    $data .= chr(0x80 | $byte);
                }
                $byte = reset($bytes);
                if (!is_int($byte)) {
                    throw new RuntimeException('Encoding failed');
                }
                $data .= chr($byte);
            }
        }
        return $data;
    }
    /**
     * Decode sub ID's from DER data.
     *
     * @return BigInteger[] Array of BigInteger numbers
     */
    protected static function decodeSubIDs(string $data): array
    {
        $subids = [];
        $idx = 0;
        $end = mb_strlen($data, '8bit');
        while ($idx < $end) {
            $num = BigInteger::of(0);
            while (\true) {
                if ($idx >= $end) {
                    throw new DecodeException('Unexpected end of data.');
                }
                $byte = ord($data[$idx++]);
                $num = $num->or($byte & 0x7f);
                // bit 8 of the last octet is zero
                if (0 === ($byte & 0x80)) {
                    break;
                }
                $num = $num->shiftedLeft(7);
            }
            $subids[] = $num;
        }
        return $subids;
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Primitive;

use _ContaoManager\Brick\Math\BigInteger;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Component\Identifier;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Component\Length;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Feature\ElementBase;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Util\BigInt;
/**
 * Implements *ENUMERATED* type.
 */
final class Enumerated extends Integer
{
    public static function create(BigInteger|int|string $number): static
    {
        return new static($number, self::TYPE_ENUMERATED);
    }
    protected static function decodeFromDER(Identifier $identifier, string $data, int &$offset): ElementBase
    {
        $idx = $offset;
        $length = Length::expectFromDER($data, $idx)->intLength();
        $bytes = mb_substr($data, $idx, $length, '8bit');
        $idx += $length;
        $num = BigInt::fromSignedOctets($bytes)->getValue();
        $offset = $idx;
        // late static binding since enumerated extends integer type
        return self::create($num);
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Primitive;

use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\PrimitiveString;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\UniversalClass;
/**
 * Implements *NumericString* type.
 */
final class NumericString extends PrimitiveString
{
    use UniversalClass;
    private function __construct(string $string)
    {
        parent::__construct(self::TYPE_NUMERIC_STRING, $string);
    }
    public static function create(string $string): self
    {
        return new self($string);
    }
    protected function validateString(string $string): bool
    {
        return preg_match('/[^\d ]/', $string) !== 1;
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Primitive;

use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\PrimitiveString;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\UniversalClass;
/**
 * Implements *OCTET STRING* type.
 */
final class OctetString extends PrimitiveString
{
    use UniversalClass;
    private function __construct(string $string)
    {
        parent::__construct(self::TYPE_OCTET_STRING, $string);
    }
    public static function create(string $string): self
    {
        return new self($string);
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Primitive;

use DateTimeImmutable;
use DateTimeZone;
use function intval;
use function mb_strlen;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Component\Identifier;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Component\Length;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Exception\DecodeException;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Feature\ElementBase;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\BaseTime;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\PrimitiveType;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\UniversalClass;
use Throwable;
use UnexpectedValueException;
/**
 * Implements *GeneralizedTime* type.
 */
final class GeneralizedTime extends BaseTime
{
    use UniversalClass;
    use PrimitiveType;
    /**
     * Regular expression to parse date.
     *
     * DER restricts format to UTC timezone (Z suffix).
     *
     * @var string
     */
    final public const REGEX = '#^' . '(\d\d\d\d)' . '(\d\d)' . '(\d\d)' . '(\d\d)' . '(\d\d)' . '(\d\d)' . '(?:\.(\d+))?' . 'Z' . '$#';
    /**
     * Cached formatted date.
     */
    private ?string $_formatted = null;
    private function __construct(DateTimeImmutable $dt)
    {
        parent::__construct(self::TYPE_GENERALIZED_TIME, $dt);
    }
    /**
     * Clear cached variables on clone.
     */
    public function __clone()
    {
        $this->_formatted = null;
    }
    public static function create(DateTimeImmutable $dt): self
    {
        return new self($dt);
    }
    public static function fromString(string $time, ?string $tz = null): static
    {
        return new static(new DateTimeImmutable($time, self::createTimeZone($tz)));
    }
    protected function encodedAsDER(): string
    {
        if (!isset($this->_formatted)) {
            $dt = $this->dateTime->setTimezone(new DateTimeZone('UTC'));
            $this->_formatted = $dt->format('YmdHis');
            // if fractions were used
            $frac = $dt->format('u');
            if (intval($frac) !== 0) {
                $frac = rtrim($frac, '0');
                $this->_formatted .= ".{$frac}";
            }
            // timezone
            $this->_formatted .= 'Z';
        }
        return $this->_formatted;
    }
    protected static function decodeFromDER(Identifier $identifier, string $data, int &$offset): ElementBase
    {
        $idx = $offset;
        $length = Length::expectFromDER($data, $idx)->intLength();
        $str = mb_substr($data, $idx, $length, '8bit');
        $idx += $length;
        if (preg_match(self::REGEX, $str, $match) !== 1) {
            throw new DecodeException('Invalid GeneralizedTime format.');
        }
        [, $year, $month, $day, $hour, $minute, $second] = $match;
        // if fractions match, there's at least one digit
        if (isset($match[7])) {
            $frac = $match[7];
            // DER restricts trailing zeroes in fractional seconds component
            if ($frac[mb_strlen($frac, '8bit') - 1] === '0') {
                throw new DecodeException('Fractional seconds must omit trailing zeroes.');
            }
        } else {
            $frac = '0';
        }
        $time = $year . $month . $day . $hour . $minute . $second . '.' . $frac . self::TZ_UTC;
        $dt = DateTimeImmutable::createFromFormat('!YmdHis.uT', $time, new DateTimeZone('UTC'));
        if ($dt === \false) {
            throw new DecodeException('Failed to decode GeneralizedTime');
        }
        $offset = $idx;
        return self::create($dt);
    }
    /**
     * Create `DateTimeZone` object from string.
     */
    private static function createTimeZone(?string $tz): DateTimeZone
    {
        try {
            return new DateTimeZone($tz ?? 'UTC');
        } catch (Throwable $e) {
            throw new UnexpectedValueException('Invalid timezone.', 0, $e);
        }
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Primitive;

use DateTimeImmutable;
use DateTimeZone;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Component\Identifier;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Component\Length;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Exception\DecodeException;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Feature\ElementBase;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\BaseTime;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\PrimitiveType;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\UniversalClass;
/**
 * Implements *UTCTime* type.
 */
final class UTCTime extends BaseTime
{
    use UniversalClass;
    use PrimitiveType;
    /**
     * Regular expression to parse date.
     *
     * DER restricts format to UTC timezone (Z suffix).
     *
     * @var string
     */
    final public const REGEX = '#^' . '(\d\d)' . '(\d\d)' . '(\d\d)' . '(\d\d)' . '(\d\d)' . '(\d\d)' . 'Z' . '$#';
    private function __construct(DateTimeImmutable $dt)
    {
        parent::__construct(self::TYPE_UTC_TIME, $dt);
    }
    public static function create(DateTimeImmutable $dt): self
    {
        return new self($dt);
    }
    public static function fromString(string $time): static
    {
        return new static(new DateTimeImmutable($time, new DateTimeZone('UTC')));
    }
    protected function encodedAsDER(): string
    {
        $dt = $this->dateTime->setTimezone(new DateTimeZone('UTC'));
        return $dt->format('_ContaoManager\ymdHis\Z');
    }
    protected static function decodeFromDER(Identifier $identifier, string $data, int &$offset): ElementBase
    {
        $idx = $offset;
        $length = Length::expectFromDER($data, $idx)->intLength();
        $str = mb_substr($data, $idx, $length, '8bit');
        $idx += $length;
        if (preg_match(self::REGEX, $str, $match) !== 1) {
            throw new DecodeException('Invalid UTCTime format.');
        }
        [, $year, $month, $day, $hour, $minute, $second] = $match;
        $time = $year . $month . $day . $hour . $minute . $second . self::TZ_UTC;
        $dt = DateTimeImmutable::createFromFormat('!ymdHisT', $time, new DateTimeZone('UTC'));
        if ($dt === \false) {
            throw new DecodeException('Failed to decode UTCTime');
        }
        $offset = $idx;
        return self::create($dt);
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Primitive;

use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\PrimitiveString;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\UniversalClass;
/**
 * Implements *VideotexString* type.
 */
final class VideotexString extends PrimitiveString
{
    use UniversalClass;
    private function __construct(string $string)
    {
        parent::__construct(self::TYPE_VIDEOTEX_STRING, $string);
    }
    public static function create(string $string): self
    {
        return new self($string);
    }
    protected function validateString(string $string): bool
    {
        // allow everything
        return \true;
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Primitive;

use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\PrimitiveString;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\UniversalClass;
/**
 * Implements *CHARACTER STRING* type.
 */
final class CharacterString extends PrimitiveString
{
    use UniversalClass;
    private function __construct(string $string)
    {
        parent::__construct(self::TYPE_CHARACTER_STRING, $string);
    }
    public static function create(string $string): self
    {
        return new self($string);
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Primitive;

use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\PrimitiveString;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\UniversalClass;
/**
 * Implements *T61String* type.
 */
final class T61String extends PrimitiveString
{
    use UniversalClass;
    private function __construct(string $string)
    {
        parent::__construct(self::TYPE_T61_STRING, $string);
    }
    public static function create(string $string): self
    {
        return new self($string);
    }
    protected function validateString(string $string): bool
    {
        // allow everything since there's literally
        // thousands of allowed characters (16 bit composed characters)
        return \true;
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Primitive;

use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\PrimitiveString;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\UniversalClass;
/**
 * Implements *GeneralString* type.
 */
final class GeneralString extends PrimitiveString
{
    use UniversalClass;
    private function __construct(string $string)
    {
        parent::__construct(self::TYPE_GENERAL_STRING, $string);
    }
    public static function create(string $string): self
    {
        return new self($string);
    }
    protected function validateString(string $string): bool
    {
        // allow everything
        return \true;
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\ASN1\Type;

use DateTimeImmutable;
/**
 * Interface to mark types that encode a time as a string.
 */
interface TimeType extends StringType
{
    /**
     * Get the date and time.
     */
    public function dateTime(): DateTimeImmutable;
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Tagged;

use _ContaoManager\SpomkyLabs\Pki\ASN1\Component\Identifier;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Feature\ElementBase;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\UnspecifiedType;
/**
 * Interface for classes providing implicit tagging.
 */
interface ImplicitTagging extends ElementBase
{
    /**
     * Get implicitly tagged wrapped element.
     *
     * @param int $tag Tag of the element
     * @param int $class Expected type class of the element
     */
    public function implicit(int $tag, int $class = Identifier::CLASS_UNIVERSAL): UnspecifiedType;
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Tagged;

/**
 * Intermediate class to store DER data of context specific type.
 */
final class ContextSpecificType extends DERTaggedType
{
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Tagged;

use BadMethodCallException;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Component\Identifier;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Element;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Feature\ElementBase;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\UnspecifiedType;
/**
 * Implements explicit tagging mode.
 *
 * Explicit tagging wraps a type by prepending a tag. Underlying DER encoding is not changed.
 */
final class ExplicitlyTaggedType extends TaggedTypeWrap implements ExplicitTagging
{
    public static function create(int $tag, Element $element, int $class = Identifier::CLASS_CONTEXT_SPECIFIC): self
    {
        return new self($element, $class, $tag);
    }
    public function isConstructed(): bool
    {
        return \true;
    }
    public function explicit(): UnspecifiedType
    {
        return $this->element->asUnspecified();
    }
    protected function encodedAsDER(): string
    {
        // get the full encoding of the wrapped element
        return $this->element->toDER();
    }
    protected static function decodeFromDER(Identifier $identifier, string $data, int &$offset): ElementBase
    {
        throw new BadMethodCallException(__METHOD__ . ' must be implemented in derived class.');
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Tagged;

/**
 * Intermediate class to store DER data of a private tagging type.
 */
final class PrivateType extends DERTaggedType
{
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Tagged;

/**
 * Intermediate class to store DER data of an application specific type.
 */
final class ApplicationType extends DERTaggedType
{
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Tagged;

use BadMethodCallException;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Component\Identifier;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Element;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Feature\ElementBase;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\UnspecifiedType;
use function sprintf;
use UnexpectedValueException;
/**
 * Implements implicit tagging mode.
 *
 * Implicit tagging changes the tag of the tagged type. This changes the DER encoding of the type, and hence the
 * abstract syntax must be known when decoding the data.
 */
final class ImplicitlyTaggedType extends TaggedTypeWrap implements ImplicitTagging
{
    public static function create(int $tag, Element $element, int $class = Identifier::CLASS_CONTEXT_SPECIFIC): self
    {
        return new self($element, $class, $tag);
    }
    public function isConstructed(): bool
    {
        // depends on the underlying type
        return $this->element->isConstructed();
    }
    public function implicit(int $tag, int $class = Identifier::CLASS_UNIVERSAL): UnspecifiedType
    {
        $this->element->expectType($tag);
        if ($this->element->typeClass() !== $class) {
            throw new UnexpectedValueException(sprintf('Type class %s expected, got %s.', Identifier::classToName($class), Identifier::classToName($this->element->typeClass())));
        }
        return $this->element->asUnspecified();
    }
    protected function encodedAsDER(): string
    {
        // get only the content of the wrapped element.
        return $this->element->encodedAsDER();
    }
    protected static function decodeFromDER(Identifier $identifier, string $data, int &$offset): ElementBase
    {
        throw new BadMethodCallException(__METHOD__ . ' must be implemented in derived class.');
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Tagged;

use _ContaoManager\SpomkyLabs\Pki\ASN1\Component\Identifier;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Component\Length;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Element;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Exception\DecodeException;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Feature\ElementBase;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\TaggedType;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\UnspecifiedType;
/**
 * Intermediate class to store tagged DER data.
 *
 * `implicit($tag)` or `explicit()` method is used to decode the actual element, which is only known by the abstract
 * syntax of data structure.
 *
 * May be encoded back to complete DER encoding.
 */
class DERTaggedType extends TaggedType implements ExplicitTagging, ImplicitTagging
{
    /**
     * @param Identifier $_identifier Pre-parsed identifier
     * @param string $_data DER data
     * @param int $_offset Offset to next byte after identifier
     * @param int $_valueOffset Offset to content
     * @param int $_valueLength Content length
     */
    final private function __construct(private readonly Identifier $_identifier, private readonly string $_data, private readonly int $_offset, private readonly int $_valueOffset, private readonly int $_valueLength, bool $indefinite_length)
    {
        parent::__construct($_identifier->intTag(), $indefinite_length);
    }
    public static function create(Identifier $_identifier, string $_data, int $_offset, int $_valueOffset, int $_valueLength, bool $indefinite_length): static
    {
        return new static($_identifier, $_data, $_offset, $_valueOffset, $_valueLength, $indefinite_length);
    }
    public function typeClass(): int
    {
        return $this->_identifier->typeClass();
    }
    public function isConstructed(): bool
    {
        return $this->_identifier->isConstructed();
    }
    public function implicit(int $tag, int $class = Identifier::CLASS_UNIVERSAL): UnspecifiedType
    {
        $identifier = $this->_identifier->withClass($class)->withTag($tag);
        $cls = self::determineImplClass($identifier);
        $idx = $this->_offset;
        /** @var ElementBase $element */
        $element = $cls::decodeFromDER($identifier, $this->_data, $idx);
        return $element->asUnspecified();
    }
    public function explicit(): UnspecifiedType
    {
        $idx = $this->_valueOffset;
        return Element::fromDER($this->_data, $idx)->asUnspecified();
    }
    protected static function decodeFromDER(Identifier $identifier, string $data, int &$offset): ElementBase
    {
        $idx = $offset;
        $length = Length::expectFromDER($data, $idx);
        // offset to inner value
        $value_offset = $idx;
        if ($length->isIndefinite()) {
            if ($identifier->isPrimitive()) {
                throw new DecodeException('Primitive type with indefinite length is not supported.');
            }
            // EOC consists of two octets.
            $value_length = $idx - $value_offset - 2;
        } else {
            $value_length = $length->intLength();
            $idx += $value_length;
        }
        // late static binding since ApplicationType and PrivateType extend this class
        $type = static::create($identifier, $data, $offset, $value_offset, $value_length, $length->isIndefinite());
        $offset = $idx;
        return $type;
    }
    protected function encodedAsDER(): string
    {
        return mb_substr($this->_data, $this->_valueOffset, $this->_valueLength, '8bit');
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Tagged;

use _ContaoManager\SpomkyLabs\Pki\ASN1\Element;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\TaggedType;
/**
 * Base class to wrap inner element for tagging.
 */
abstract class TaggedTypeWrap extends TaggedType
{
    protected function __construct(protected readonly Element $element, private readonly int $class, int $typeTag)
    {
        parent::__construct($typeTag);
    }
    public function typeClass(): int
    {
        return $this->class;
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Tagged;

use _ContaoManager\SpomkyLabs\Pki\ASN1\Feature\ElementBase;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\UnspecifiedType;
/**
 * Interface for classes providing explicit tagging.
 */
interface ExplicitTagging extends ElementBase
{
    /**
     * Get explicitly tagged wrapped element.
     */
    public function explicit(): UnspecifiedType;
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Constructed;

use _ContaoManager\SpomkyLabs\Pki\ASN1\Component\Identifier;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Component\Length;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Element;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Exception\DecodeException;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Structure;
/**
 * Implements *SEQUENCE* and *SEQUENCE OF* types.
 */
final class Sequence extends Structure
{
    /**
     * @param Element ...$elements Any number of elements
     */
    public static function create(Element ...$elements): self
    {
        return new self(self::TYPE_SEQUENCE, ...$elements);
    }
    protected static function decodeFromDER(Identifier $identifier, string $data, int &$offset): self
    {
        if (!$identifier->isConstructed()) {
            throw new DecodeException('Structured element must have constructed bit set.');
        }
        $idx = $offset;
        $length = Length::expectFromDER($data, $idx);
        if ($length->isIndefinite()) {
            $type = self::decodeIndefiniteLength($data, $idx);
        } else {
            $type = self::decodeDefiniteLength($data, $idx, $length->intLength());
        }
        $offset = $idx;
        return $type;
    }
    /**
     * Decode elements for a definite length.
     *
     * @param string $data DER data
     * @param int $offset Offset to data
     * @param int $length Number of bytes to decode
     */
    protected static function decodeDefiniteLength(string $data, int &$offset, int $length): self
    {
        $idx = $offset;
        $end = $idx + $length;
        $elements = [];
        while ($idx < $end) {
            $elements[] = Element::fromDER($data, $idx);
            // check that element didn't overflow length
            if ($idx > $end) {
                throw new DecodeException("Structure's content overflows length.");
            }
        }
        $offset = $idx;
        // return instance by static late binding
        return self::create(...$elements);
    }
    /**
     * Decode elements for an indefinite length.
     *
     * @param string $data DER data
     * @param int $offset Offset to data
     */
    protected static function decodeIndefiniteLength(string $data, int &$offset): self
    {
        $idx = $offset;
        $elements = [];
        $end = mb_strlen($data, '8bit');
        while (\true) {
            if ($idx >= $end) {
                throw new DecodeException('Unexpected end of data while decoding indefinite length structure.');
            }
            $el = Element::fromDER($data, $idx);
            if ($el->isType(self::TYPE_EOC)) {
                break;
            }
            $elements[] = $el;
        }
        $offset = $idx;
        $type = self::create(...$elements);
        $type->indefiniteLength = \true;
        return $type;
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Constructed;

use _ContaoManager\SpomkyLabs\Pki\ASN1\Component\Identifier;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Component\Length;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Element;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Exception\DecodeException;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Feature\ElementBase;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Structure;
/**
 * Implements *SET* and *SET OF* types.
 */
final class Set extends Structure
{
    /**
     * @param Element ...$elements Any number of elements
     */
    public static function create(Element ...$elements): self
    {
        return new self(self::TYPE_SET, ...$elements);
    }
    /**
     * Sort by canonical ascending order.
     *
     * Used for DER encoding of *SET* type.
     */
    public function sortedSet(): self
    {
        $obj = clone $this;
        usort($obj->elements, function (Element $a, Element $b) {
            if ($a->typeClass() !== $b->typeClass()) {
                return $a->typeClass() < $b->typeClass() ? -1 : 1;
            }
            return $a->tag() <=> $b->tag();
        });
        return $obj;
    }
    /**
     * Sort by encoding ascending order.
     *
     * Used for DER encoding of *SET OF* type.
     */
    public function sortedSetOf(): self
    {
        $obj = clone $this;
        usort($obj->elements, function (Element $a, Element $b) {
            $a_der = $a->toDER();
            $b_der = $b->toDER();
            return strcmp($a_der, $b_der);
        });
        return $obj;
    }
    /**
     * @return self
     */
    protected static function decodeFromDER(Identifier $identifier, string $data, int &$offset): ElementBase
    {
        if (!$identifier->isConstructed()) {
            throw new DecodeException('Structured element must have constructed bit set.');
        }
        $idx = $offset;
        $length = Length::expectFromDER($data, $idx);
        if ($length->isIndefinite()) {
            $type = self::decodeIndefiniteLength($data, $idx);
        } else {
            $type = self::decodeDefiniteLength($data, $idx, $length->intLength());
        }
        $offset = $idx;
        return $type;
    }
    /**
     * Decode elements for a definite length.
     *
     * @param string $data DER data
     * @param int $offset Offset to data
     * @param int $length Number of bytes to decode
     */
    protected static function decodeDefiniteLength(string $data, int &$offset, int $length): ElementBase
    {
        $idx = $offset;
        $end = $idx + $length;
        $elements = [];
        while ($idx < $end) {
            $elements[] = Element::fromDER($data, $idx);
            // check that element didn't overflow length
            if ($idx > $end) {
                throw new DecodeException("Structure's content overflows length.");
            }
        }
        $offset = $idx;
        // return instance by static late binding
        return self::create(...$elements);
    }
    /**
     * Decode elements for an indefinite length.
     *
     * @param string $data DER data
     * @param int $offset Offset to data
     */
    protected static function decodeIndefiniteLength(string $data, int &$offset): ElementBase
    {
        $idx = $offset;
        $elements = [];
        $end = mb_strlen($data, '8bit');
        while (\true) {
            if ($idx >= $end) {
                throw new DecodeException('Unexpected end of data while decoding indefinite length structure.');
            }
            $el = Element::fromDER($data, $idx);
            if ($el->isType(self::TYPE_EOC)) {
                break;
            }
            $elements[] = $el;
        }
        $offset = $idx;
        $type = self::create(...$elements);
        $type->indefiniteLength = \true;
        return $type;
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Constructed;

use function count;
use LogicException;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Component\Identifier;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Component\Length;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Element;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Exception\DecodeException;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\StringType;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Structure;
use Stringable;
/**
 * Implements constructed type of simple strings.
 *
 * Constructed strings only exist in BER encodings, and often with indefinite length. Generally constructed string must
 * contain only elements that have the same type tag as the constructing element. For example: ``` OCTET STRING (cons) {
 * OCTET STRING (prim) "ABC" OCTET STRING (prim) "DEF" } ``` Canonically this corresponds to a payload of "ABCDEF"
 * string.
 *
 * From API standpoint this can also be seen as a string type (as it implements `StringType`), and thus
 * `UnspecifiedType::asString()` method may return `ConstructedString` instances.
 */
final class ConstructedString extends Structure implements StringType, Stringable
{
    public function __toString(): string
    {
        return $this->string();
    }
    /**
     * Create from a list of string type elements.
     *
     * All strings must have the same type.
     */
    public static function create(StringType ...$elements): self
    {
        if (count($elements) === 0) {
            throw new LogicException('No elements, unable to determine type tag.');
        }
        $tag = $elements[0]->tag();
        return self::createWithTag($tag, ...$elements);
    }
    /**
     * Create from strings with a given type tag.
     *
     * Does not perform any validation on types.
     *
     * @param int $tag Type tag for the constructed string element
     * @param StringType ...$elements Any number of elements
     */
    public static function createWithTag(int $tag, StringType ...$elements): self
    {
        foreach ($elements as $el) {
            if ($el->tag() !== $tag) {
                throw new LogicException('All elements in constructed string must have the same type.');
            }
        }
        return new self($tag, ...$elements);
    }
    /**
     * Get a list of strings in this structure.
     *
     * @return string[]
     */
    public function strings(): array
    {
        return array_map(static fn(Element $el): string => $el->string(), $this->elements);
    }
    /**
     * Get the contained strings concatenated together.
     *
     * NOTE: It's unclear how bit strings with unused bits should be concatenated.
     */
    public function string(): string
    {
        return implode('', $this->strings());
    }
    protected static function decodeFromDER(Identifier $identifier, string $data, int &$offset): self
    {
        if (!$identifier->isConstructed()) {
            throw new DecodeException('Structured element must have constructed bit set.');
        }
        $idx = $offset;
        $length = Length::expectFromDER($data, $idx);
        if ($length->isIndefinite()) {
            $type = self::decodeIndefiniteLength($identifier->intTag(), $data, $idx);
        } else {
            $type = self::decodeDefiniteLength($identifier->intTag(), $data, $idx, $length->intLength());
        }
        $offset = $idx;
        return $type;
    }
    /**
     * Decode elements for a definite length.
     *
     * @param string $data DER data
     * @param int $offset Offset to data
     * @param int $length Number of bytes to decode
     */
    protected static function decodeDefiniteLength(int $typeTag, string $data, int &$offset, int $length): self
    {
        $idx = $offset;
        $end = $idx + $length;
        $elements = [];
        while ($idx < $end) {
            $elements[] = Element::fromDER($data, $idx);
            // check that element didn't overflow length
            if ($idx > $end) {
                throw new DecodeException("Structure's content overflows length.");
            }
        }
        $offset = $idx;
        // return instance by static late binding
        return self::createWithTag($typeTag, ...$elements);
    }
    /**
     * Decode elements for an indefinite length.
     *
     * @param string $data DER data
     * @param int $offset Offset to data
     */
    protected static function decodeIndefiniteLength(int $typeTag, string $data, int &$offset): self
    {
        $idx = $offset;
        $elements = [];
        $end = mb_strlen($data, '8bit');
        while (\true) {
            if ($idx >= $end) {
                throw new DecodeException('Unexpected end of data while decoding indefinite length structure.');
            }
            $el = Element::fromDER($data, $idx);
            if ($el->isType(self::TYPE_EOC)) {
                break;
            }
            $elements[] = $el;
        }
        $offset = $idx;
        $type = self::createWithTag($typeTag, ...$elements);
        $type->indefiniteLength = \true;
        return $type;
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\ASN1\Type;

use InvalidArgumentException;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Component\Identifier;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Component\Length;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Exception\DecodeException;
/**
 * Base class for primitive strings.
 *
 * Used by types that don't require special processing of the encoded string data.
 *
 * @internal
 */
abstract class PrimitiveString extends BaseString
{
    use PrimitiveType;
    abstract public static function create(string $string): self;
    protected static function decodeFromDER(Identifier $identifier, string $data, int &$offset): static
    {
        $idx = $offset;
        if (!$identifier->isPrimitive()) {
            throw new DecodeException('DER encoded string must be primitive.');
        }
        $length = Length::expectFromDER($data, $idx)->intLength();
        $str = $length === 0 ? '' : mb_substr($data, $idx, $length, '8bit');
        $offset = $idx + $length;
        try {
            return static::create($str);
        } catch (InvalidArgumentException $e) {
            throw new DecodeException($e->getMessage(), 0, $e);
        }
    }
}
<?php

/** @noinspection ALL */
declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\ASN1\Type;

use ArrayIterator;
use function count;
use Countable;
use IteratorAggregate;
use LogicException;
use OutOfBoundsException;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Component\Identifier;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Component\Length;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Element;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Exception\DecodeException;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Feature\ElementBase;
/**
 * Base class for the constructed types.
 */
abstract class Structure extends Element implements Countable, IteratorAggregate
{
    use UniversalClass;
    /**
     * Array of elements in the structure.
     *
     * @var Element[]
     */
    protected array $elements;
    /**
     * Lookup table for the tagged elements.
     *
     * @var null|Element[]
     */
    private ?array $taggedMap = null;
    /**
     * Cache variable of elements wrapped into `UnspecifiedType` objects.
     *
     * @var null|UnspecifiedType[]
     */
    private ?array $unspecifiedTypes = null;
    /**
     * @param ElementBase ...$elements Any number of elements
     */
    protected function __construct(int $typeTag, ElementBase ...$elements)
    {
        parent::__construct($typeTag);
        $this->elements = array_map(static fn(ElementBase $el) => $el->asElement(), $elements);
    }
    /**
     * Clone magic method.
     */
    public function __clone()
    {
        // clear cache-variables
        $this->taggedMap = null;
        $this->unspecifiedTypes = null;
    }
    public function isConstructed(): bool
    {
        return \true;
    }
    /**
     * Explode DER structure to DER encoded components that it contains.
     *
     * @return string[]
     */
    public static function explodeDER(string $data): array
    {
        $offset = 0;
        $identifier = Identifier::fromDER($data, $offset);
        if (!$identifier->isConstructed()) {
            throw new DecodeException('Element is not constructed.');
        }
        $length = Length::expectFromDER($data, $offset);
        if ($length->isIndefinite()) {
            throw new DecodeException('Explode not implemented for indefinite length encoding.');
        }
        $end = $offset + $length->intLength();
        $parts = [];
        while ($offset < $end) {
            // start of the element
            $idx = $offset;
            // skip identifier
            Identifier::fromDER($data, $offset);
            // decode element length
            $length = Length::expectFromDER($data, $offset)->intLength();
            // extract der encoding of the element
            $parts[] = mb_substr($data, $idx, $offset - $idx + $length, '8bit');
            // update offset over content
            $offset += $length;
        }
        return $parts;
    }
    /**
     * Get self with an element at the given index replaced by another.
     *
     * @param int $idx Element index
     * @param Element $el New element to insert into the structure
     */
    public function withReplaced(int $idx, Element $el): self
    {
        if (!isset($this->elements[$idx])) {
            throw new OutOfBoundsException("Structure doesn't have element at index {$idx}.");
        }
        $obj = clone $this;
        $obj->elements[$idx] = $el;
        return $obj;
    }
    /**
     * Get self with an element inserted before the given index.
     *
     * @param int $idx Element index
     * @param Element $el New element to insert into the structure
     */
    public function withInserted(int $idx, Element $el): self
    {
        if (count($this->elements) < $idx || $idx < 0) {
            throw new OutOfBoundsException("Index {$idx} is out of bounds.");
        }
        $obj = clone $this;
        array_splice($obj->elements, $idx, 0, [$el]);
        return $obj;
    }
    /**
     * Get self with an element appended to the end.
     *
     * @param Element $el Element to insert into the structure
     */
    public function withAppended(Element $el): self
    {
        $obj = clone $this;
        array_push($obj->elements, $el);
        return $obj;
    }
    /**
     * Get self with an element prepended in the beginning.
     *
     * @param Element $el Element to insert into the structure
     */
    public function withPrepended(Element $el): self
    {
        $obj = clone $this;
        array_unshift($obj->elements, $el);
        return $obj;
    }
    /**
     * Get self with an element at the given index removed.
     *
     * @param int $idx Element index
     */
    public function withoutElement(int $idx): self
    {
        if (!isset($this->elements[$idx])) {
            throw new OutOfBoundsException("Structure doesn't have element at index {$idx}.");
        }
        $obj = clone $this;
        array_splice($obj->elements, $idx, 1);
        return $obj;
    }
    /**
     * Get elements in the structure.
     *
     * @return UnspecifiedType[]
     */
    public function elements(): array
    {
        if (!isset($this->unspecifiedTypes)) {
            $this->unspecifiedTypes = array_map(UnspecifiedType::create(...), $this->elements);
        }
        return $this->unspecifiedTypes;
    }
    /**
     * Check whether the structure has an element at the given index, optionally satisfying given tag expectation.
     *
     * @param int $idx Index 0..n
     * @param null|int $expectedTag Optional type tag expectation
     */
    public function has(int $idx, ?int $expectedTag = null): bool
    {
        if (!isset($this->elements[$idx])) {
            return \false;
        }
        if (isset($expectedTag)) {
            if (!$this->elements[$idx]->isType($expectedTag)) {
                return \false;
            }
        }
        return \true;
    }
    /**
     * Get the element at the given index, optionally checking that the element has a given tag.
     *
     * @param int $idx Index 0..n
     */
    public function at(int $idx): UnspecifiedType
    {
        if (!isset($this->elements[$idx])) {
            throw new OutOfBoundsException("Structure doesn't have an element at index {$idx}.");
        }
        return UnspecifiedType::create($this->elements[$idx]);
    }
    /**
     * Check whether the structure contains a context specific element with a given tag.
     *
     * @param int $tag Tag number
     */
    public function hasTagged(int $tag): bool
    {
        // lazily build lookup map
        if (!isset($this->taggedMap)) {
            $this->taggedMap = [];
            foreach ($this->elements as $element) {
                if ($element->isTagged()) {
                    $this->taggedMap[$element->tag()] = $element;
                }
            }
        }
        return isset($this->taggedMap[$tag]);
    }
    /**
     * Get a context specific element tagged with a given tag.
     */
    public function getTagged(int $tag): TaggedType
    {
        if (!$this->hasTagged($tag)) {
            throw new LogicException("No tagged element for tag {$tag}.");
        }
        return $this->taggedMap[$tag];
    }
    /**
     * @see \Countable::count()
     */
    public function count(): int
    {
        return count($this->elements);
    }
    /**
     * Get an iterator for the `UnspecifiedElement` objects.
     *
     * @see \IteratorAggregate::getIterator()
     */
    public function getIterator(): ArrayIterator
    {
        return new ArrayIterator($this->elements());
    }
    protected function encodedAsDER(): string
    {
        $data = '';
        foreach ($this->elements as $element) {
            $data .= $element->toDER();
        }
        return $data;
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\ASN1\Type;

use DateTimeImmutable;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Element;
use Stringable;
/**
 * Base class for all types representing a point in time.
 */
abstract class BaseTime extends Element implements TimeType, Stringable
{
    /**
     * UTC timezone.
     *
     * @var string
     */
    public const TZ_UTC = 'UTC';
    protected function __construct(int $typeTag, protected readonly DateTimeImmutable $dateTime)
    {
        parent::__construct($typeTag);
    }
    public function __toString(): string
    {
        return $this->string();
    }
    /**
     * Initialize from datetime string.
     *
     * @see http://php.net/manual/en/datetime.formats.php
     *
     * @param string $time Time string
     */
    abstract public static function fromString(string $time): static;
    /**
     * Get the date and time.
     */
    public function dateTime(): DateTimeImmutable
    {
        return $this->dateTime;
    }
    /**
     * Get the date and time as a type specific string.
     */
    public function string(): string
    {
        return $this->encodedAsDER();
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\ASN1\Type;

use _ContaoManager\SpomkyLabs\Pki\ASN1\Component\Identifier;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Element;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Feature\ElementBase;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Constructed\ConstructedString;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Constructed\Sequence;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Constructed\Set;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Primitive\BitString;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Primitive\BMPString;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Primitive\Boolean;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Primitive\CharacterString;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Primitive\Enumerated;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Primitive\GeneralizedTime;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Primitive\GeneralString;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Primitive\GraphicString;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Primitive\IA5String;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Primitive\Integer;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Primitive\NullType;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Primitive\NumericString;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Primitive\ObjectDescriptor;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Primitive\ObjectIdentifier;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Primitive\OctetString;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Primitive\PrintableString;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Primitive\Real;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Primitive\RelativeOID;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Primitive\T61String;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Primitive\UniversalString;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Primitive\UTCTime;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Primitive\UTF8String;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Primitive\VideotexString;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Primitive\VisibleString;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Tagged\ApplicationType;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Tagged\PrivateType;
use function sprintf;
use UnexpectedValueException;
/**
 * Decorator class to wrap an element without already knowing the specific underlying type.
 *
 * Provides accessor methods to test the underlying type and return a type hinted instance of the concrete element.
 * @see \SpomkyLabs\Pki\Test\ASN1\Type\UnspecifiedTypeTest
 */
final class UnspecifiedType implements ElementBase
{
    private function __construct(private readonly Element $element)
    {
    }
    public static function create(Element $element): self
    {
        return new self($element);
    }
    /**
     * Initialize from DER data.
     *
     * @param string $data DER encoded data
     */
    public static function fromDER(string $data): self
    {
        return Element::fromDER($data)->asUnspecified();
    }
    /**
     * Initialize from `ElementBase` interface.
     */
    public static function fromElementBase(ElementBase $el): self
    {
        // if element is already wrapped
        if ($el instanceof self) {
            return $el;
        }
        return self::create($el->asElement());
    }
    /**
     * Get the wrapped element as a context specific tagged type.
     */
    public function asTagged(): TaggedType
    {
        if (!$this->element instanceof TaggedType) {
            throw new UnexpectedValueException('Tagged element expected, got ' . $this->typeDescriptorString());
        }
        return $this->element;
    }
    /**
     * Get the wrapped element as an application specific type.
     */
    public function asApplication(): ApplicationType
    {
        if (!$this->element instanceof ApplicationType) {
            throw new UnexpectedValueException('Application type expected, got ' . $this->typeDescriptorString());
        }
        return $this->element;
    }
    /**
     * Get the wrapped element as a private tagged type.
     */
    public function asPrivate(): PrivateType
    {
        if (!$this->element instanceof PrivateType) {
            throw new UnexpectedValueException('Private type expected, got ' . $this->typeDescriptorString());
        }
        return $this->element;
    }
    /**
     * Get the wrapped element as a boolean type.
     */
    public function asBoolean(): Boolean
    {
        if (!$this->element instanceof Boolean) {
            throw new UnexpectedValueException($this->generateExceptionMessage(Element::TYPE_BOOLEAN));
        }
        return $this->element;
    }
    /**
     * Get the wrapped element as an integer type.
     */
    public function asInteger(): Integer
    {
        if (!$this->element instanceof Integer) {
            throw new UnexpectedValueException($this->generateExceptionMessage(Element::TYPE_INTEGER));
        }
        return $this->element;
    }
    /**
     * Get the wrapped element as a bit string type.
     */
    public function asBitString(): BitString
    {
        if (!$this->element instanceof BitString) {
            throw new UnexpectedValueException($this->generateExceptionMessage(Element::TYPE_BIT_STRING));
        }
        return $this->element;
    }
    /**
     * Get the wrapped element as an octet string type.
     */
    public function asOctetString(): OctetString
    {
        if (!$this->element instanceof OctetString) {
            throw new UnexpectedValueException($this->generateExceptionMessage(Element::TYPE_OCTET_STRING));
        }
        return $this->element;
    }
    /**
     * Get the wrapped element as a null type.
     */
    public function asNull(): NullType
    {
        if (!$this->element instanceof NullType) {
            throw new UnexpectedValueException($this->generateExceptionMessage(Element::TYPE_NULL));
        }
        return $this->element;
    }
    /**
     * Get the wrapped element as an object identifier type.
     */
    public function asObjectIdentifier(): ObjectIdentifier
    {
        if (!$this->element instanceof ObjectIdentifier) {
            throw new UnexpectedValueException($this->generateExceptionMessage(Element::TYPE_OBJECT_IDENTIFIER));
        }
        return $this->element;
    }
    /**
     * Get the wrapped element as an object descriptor type.
     */
    public function asObjectDescriptor(): ObjectDescriptor
    {
        if (!$this->element instanceof ObjectDescriptor) {
            throw new UnexpectedValueException($this->generateExceptionMessage(Element::TYPE_OBJECT_DESCRIPTOR));
        }
        return $this->element;
    }
    /**
     * Get the wrapped element as a real type.
     */
    public function asReal(): Real
    {
        if (!$this->element instanceof Real) {
            throw new UnexpectedValueException($this->generateExceptionMessage(Element::TYPE_REAL));
        }
        return $this->element;
    }
    /**
     * Get the wrapped element as an enumerated type.
     */
    public function asEnumerated(): Enumerated
    {
        if (!$this->element instanceof Enumerated) {
            throw new UnexpectedValueException($this->generateExceptionMessage(Element::TYPE_ENUMERATED));
        }
        return $this->element;
    }
    /**
     * Get the wrapped element as a UTF8 string type.
     */
    public function asUTF8String(): UTF8String
    {
        if (!$this->element instanceof UTF8String) {
            throw new UnexpectedValueException($this->generateExceptionMessage(Element::TYPE_UTF8_STRING));
        }
        return $this->element;
    }
    /**
     * Get the wrapped element as a relative OID type.
     */
    public function asRelativeOID(): RelativeOID
    {
        if (!$this->element instanceof RelativeOID) {
            throw new UnexpectedValueException($this->generateExceptionMessage(Element::TYPE_RELATIVE_OID));
        }
        return $this->element;
    }
    /**
     * Get the wrapped element as a sequence type.
     */
    public function asSequence(): Sequence
    {
        if (!$this->element instanceof Sequence) {
            throw new UnexpectedValueException($this->generateExceptionMessage(Element::TYPE_SEQUENCE));
        }
        return $this->element;
    }
    /**
     * Get the wrapped element as a set type.
     */
    public function asSet(): Set
    {
        if (!$this->element instanceof Set) {
            throw new UnexpectedValueException($this->generateExceptionMessage(Element::TYPE_SET));
        }
        return $this->element;
    }
    /**
     * Get the wrapped element as a numeric string type.
     */
    public function asNumericString(): NumericString
    {
        if (!$this->element instanceof NumericString) {
            throw new UnexpectedValueException($this->generateExceptionMessage(Element::TYPE_NUMERIC_STRING));
        }
        return $this->element;
    }
    /**
     * Get the wrapped element as a printable string type.
     */
    public function asPrintableString(): PrintableString
    {
        if (!$this->element instanceof PrintableString) {
            throw new UnexpectedValueException($this->generateExceptionMessage(Element::TYPE_PRINTABLE_STRING));
        }
        return $this->element;
    }
    /**
     * Get the wrapped element as a T61 string type.
     */
    public function asT61String(): T61String
    {
        if (!$this->element instanceof T61String) {
            throw new UnexpectedValueException($this->generateExceptionMessage(Element::TYPE_T61_STRING));
        }
        return $this->element;
    }
    /**
     * Get the wrapped element as a videotex string type.
     */
    public function asVideotexString(): VideotexString
    {
        if (!$this->element instanceof VideotexString) {
            throw new UnexpectedValueException($this->generateExceptionMessage(Element::TYPE_VIDEOTEX_STRING));
        }
        return $this->element;
    }
    /**
     * Get the wrapped element as a IA5 string type.
     */
    public function asIA5String(): IA5String
    {
        if (!$this->element instanceof IA5String) {
            throw new UnexpectedValueException($this->generateExceptionMessage(Element::TYPE_IA5_STRING));
        }
        return $this->element;
    }
    /**
     * Get the wrapped element as an UTC time type.
     */
    public function asUTCTime(): UTCTime
    {
        if (!$this->element instanceof UTCTime) {
            throw new UnexpectedValueException($this->generateExceptionMessage(Element::TYPE_UTC_TIME));
        }
        return $this->element;
    }
    /**
     * Get the wrapped element as a generalized time type.
     */
    public function asGeneralizedTime(): GeneralizedTime
    {
        if (!$this->element instanceof GeneralizedTime) {
            throw new UnexpectedValueException($this->generateExceptionMessage(Element::TYPE_GENERALIZED_TIME));
        }
        return $this->element;
    }
    /**
     * Get the wrapped element as a graphic string type.
     */
    public function asGraphicString(): GraphicString
    {
        if (!$this->element instanceof GraphicString) {
            throw new UnexpectedValueException($this->generateExceptionMessage(Element::TYPE_GRAPHIC_STRING));
        }
        return $this->element;
    }
    /**
     * Get the wrapped element as a visible string type.
     */
    public function asVisibleString(): VisibleString
    {
        if (!$this->element instanceof VisibleString) {
            throw new UnexpectedValueException($this->generateExceptionMessage(Element::TYPE_VISIBLE_STRING));
        }
        return $this->element;
    }
    /**
     * Get the wrapped element as a general string type.
     */
    public function asGeneralString(): GeneralString
    {
        if (!$this->element instanceof GeneralString) {
            throw new UnexpectedValueException($this->generateExceptionMessage(Element::TYPE_GENERAL_STRING));
        }
        return $this->element;
    }
    /**
     * Get the wrapped element as a universal string type.
     */
    public function asUniversalString(): UniversalString
    {
        if (!$this->element instanceof UniversalString) {
            throw new UnexpectedValueException($this->generateExceptionMessage(Element::TYPE_UNIVERSAL_STRING));
        }
        return $this->element;
    }
    /**
     * Get the wrapped element as a character string type.
     */
    public function asCharacterString(): CharacterString
    {
        if (!$this->element instanceof CharacterString) {
            throw new UnexpectedValueException($this->generateExceptionMessage(Element::TYPE_CHARACTER_STRING));
        }
        return $this->element;
    }
    /**
     * Get the wrapped element as a BMP string type.
     */
    public function asBMPString(): BMPString
    {
        if (!$this->element instanceof BMPString) {
            throw new UnexpectedValueException($this->generateExceptionMessage(Element::TYPE_BMP_STRING));
        }
        return $this->element;
    }
    /**
     * Get the wrapped element as a constructed string type.
     */
    public function asConstructedString(): ConstructedString
    {
        if (!$this->element instanceof ConstructedString) {
            throw new UnexpectedValueException($this->generateExceptionMessage(Element::TYPE_CONSTRUCTED_STRING));
        }
        return $this->element;
    }
    /**
     * Get the wrapped element as any string type.
     */
    public function asString(): StringType
    {
        if (!$this->element instanceof StringType) {
            throw new UnexpectedValueException($this->generateExceptionMessage(Element::TYPE_STRING));
        }
        return $this->element;
    }
    /**
     * Get the wrapped element as any time type.
     */
    public function asTime(): TimeType
    {
        if (!$this->element instanceof TimeType) {
            throw new UnexpectedValueException($this->generateExceptionMessage(Element::TYPE_TIME));
        }
        return $this->element;
    }
    public function asElement(): Element
    {
        return $this->element;
    }
    public function asUnspecified(): self
    {
        return $this;
    }
    public function toDER(): string
    {
        return $this->element->toDER();
    }
    public function typeClass(): int
    {
        return $this->element->typeClass();
    }
    public function tag(): int
    {
        return $this->element->tag();
    }
    public function isConstructed(): bool
    {
        return $this->element->isConstructed();
    }
    public function isType(int $tag): bool
    {
        return $this->element->isType($tag);
    }
    public function isTagged(): bool
    {
        return $this->element->isTagged();
    }
    /**
     * {@inheritdoc}
     *
     * Consider using any of the `as*` accessor methods instead.
     */
    public function expectType(int $tag): ElementBase
    {
        return $this->element->expectType($tag);
    }
    /**
     * {@inheritdoc}
     *
     * Consider using `asTagged()` method instead and chaining
     * with `TaggedType::asExplicit()` or `TaggedType::asImplicit()`.
     */
    public function expectTagged(?int $tag = null): TaggedType
    {
        return $this->element->expectTagged($tag);
    }
    /**
     * Generate message for exceptions thrown by `as*` methods.
     *
     * @param int $tag Type tag of the expected element
     */
    private function generateExceptionMessage(int $tag): string
    {
        return sprintf('%s expected, got %s.', Element::tagToName($tag), $this->typeDescriptorString());
    }
    /**
     * Get textual description of the wrapped element for debugging purposes.
     */
    private function typeDescriptorString(): string
    {
        $type_cls = $this->element->typeClass();
        $tag = $this->element->tag();
        $str = $this->element->isConstructed() ? 'constructed ' : 'primitive ';
        if ($type_cls === Identifier::CLASS_UNIVERSAL) {
            $str .= Element::tagToName($tag);
        } else {
            $str .= Identifier::classToName($type_cls) . " TAG {$tag}";
        }
        return $str;
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\ASN1\Type;

use _ContaoManager\SpomkyLabs\Pki\ASN1\Component\Identifier;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Element;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Tagged\ExplicitTagging;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Tagged\ImplicitTagging;
use UnexpectedValueException;
/**
 * Base class for context-specific types.
 */
abstract class TaggedType extends Element
{
    /**
     * Check whether element supports explicit tagging.
     *
     * @param null|int $expectedTag Optional outer tag expectation
     */
    public function expectExplicit(?int $expectedTag = null): ExplicitTagging
    {
        $el = $this;
        if (!$el instanceof ExplicitTagging) {
            throw new UnexpectedValueException("Element doesn't implement explicit tagging.");
        }
        if (isset($expectedTag)) {
            $el->expectTagged($expectedTag);
        }
        return $el;
    }
    /**
     * Get the wrapped inner element employing explicit tagging.
     *
     * @param null|int $expectedTag Optional outer tag expectation
     */
    public function asExplicit(?int $expectedTag = null): UnspecifiedType
    {
        return $this->expectExplicit($expectedTag)->explicit();
    }
    /**
     * Check whether element supports implicit tagging.
     *
     * @param null|int $expectedTag Optional outer tag expectation
     */
    public function expectImplicit(?int $expectedTag = null): ImplicitTagging
    {
        $el = $this;
        if (!$el instanceof ImplicitTagging) {
            throw new UnexpectedValueException("Element doesn't implement implicit tagging.");
        }
        if (isset($expectedTag)) {
            $el->expectTagged($expectedTag);
        }
        return $el;
    }
    /**
     * Get the wrapped inner element employing implicit tagging.
     *
     * @param int $tag Type tag of the inner element
     * @param null|int $expectedTag Optional outer tag expectation
     * @param int $expectedClass Optional inner type class expectation
     */
    public function asImplicit(int $tag, ?int $expectedTag = null, int $expectedClass = Identifier::CLASS_UNIVERSAL): UnspecifiedType
    {
        return $this->expectImplicit($expectedTag)->implicit($tag, $expectedClass);
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\ASN1\Type;

use _ContaoManager\SpomkyLabs\Pki\ASN1\Feature\ElementBase;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Feature\Stringable;
/**
 * Interface to mark types that correspond to ASN.1 specification's character strings. That being all simple strings and
 * time types.
 */
interface StringType extends ElementBase, Stringable
{
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\ASN1\Type;

use _ContaoManager\SpomkyLabs\Pki\ASN1\Component\Identifier;
/**
 * Trait for types of universal class.
 */
trait UniversalClass
{
    /**
     * @see \Sop\ASN1\Feature\ElementBase::typeClass()
     */
    public function typeClass(): int
    {
        return Identifier::CLASS_UNIVERSAL;
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\ASN1;

use BadMethodCallException;
use function mb_strlen;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Component\Identifier;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Component\Length;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Feature\ElementBase;
/**
 * Container for raw DER encoded data.
 *
 * May be inserted into structure without decoding first.
 * @see \SpomkyLabs\Pki\Test\ASN1\DERDataTest
 */
final class DERData extends Element
{
    /**
     * DER encoded data.
     */
    private readonly string $der;
    /**
     * Identifier of the underlying type.
     */
    private readonly Identifier $identifier;
    /**
     * Offset to the content in DER data.
     */
    private int $contentOffset = 0;
    /**
     * @param string $data DER encoded data
     */
    private function __construct(string $data)
    {
        $this->identifier = Identifier::fromDER($data, $this->contentOffset);
        // check that length encoding is valid
        Length::expectFromDER($data, $this->contentOffset);
        $this->der = $data;
        parent::__construct($this->identifier->intTag());
    }
    public static function create(string $data): self
    {
        return new self($data);
    }
    public function typeClass(): int
    {
        return $this->identifier->typeClass();
    }
    public function isConstructed(): bool
    {
        return $this->identifier->isConstructed();
    }
    public function toDER(): string
    {
        return $this->der;
    }
    protected function encodedAsDER(): string
    {
        // if there's no content payload
        if (mb_strlen($this->der, '8bit') === $this->contentOffset) {
            return '';
        }
        return mb_substr($this->der, $this->contentOffset, null, '8bit');
    }
    protected static function decodeFromDER(Identifier $identifier, string $data, int &$offset): ElementBase
    {
        throw new BadMethodCallException(__METHOD__ . ' must be implemented in derived class.');
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\ASN1\Feature;

use _ContaoManager\SpomkyLabs\Pki\ASN1\Element;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\TaggedType;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\UnspecifiedType;
/**
 * Base interface for ASN.1 type elements.
 */
interface ElementBase extends Encodable
{
    /**
     * Get the class of the ASN.1 type.
     *
     * One of `Identifier::CLASS_*` constants.
     */
    public function typeClass(): int;
    /**
     * Check whether the element is constructed.
     *
     * Otherwise it's primitive.
     */
    public function isConstructed(): bool;
    /**
     * Get the tag of the element.
     *
     * Interpretation of the tag depends on the context. For example, it may represent a universal type tag or a tag of
     * an implicitly or explicitly tagged type.
     */
    public function tag(): int;
    /**
     * Check whether the element is a type of given tag.
     *
     * @param int $tag Type tag
     */
    public function isType(int $tag): bool;
    /**
     * Check whether the element is a type of a given tag.
     *
     * Throws an exception if expectation fails.
     *
     * @param int $tag Type tag
     */
    public function expectType(int $tag): self;
    /**
     * Check whether the element is tagged (context specific).
     */
    public function isTagged(): bool;
    /**
     * Check whether the element is tagged (context specific) and optionally has a given tag.
     *
     * Throws an exception if the element is not tagged or tag differs from the expected.
     *
     * @param null|int $tag Optional type tag
     */
    public function expectTagged(?int $tag = null): TaggedType;
    /**
     * Get the object as an abstract `Element` instance.
     */
    public function asElement(): Element;
    /**
     * Get the object as an `UnspecifiedType` instance.
     */
    public function asUnspecified(): UnspecifiedType;
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\ASN1\Feature;

/**
 * Interface for classes that may be cast to string.
 */
interface Stringable
{
    /**
     * Convert object to string.
     */
    public function __toString(): string;
    /**
     * Get the string representation of the type.
     */
    public function string(): string;
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\ASN1\Feature;

/**
 * Interface for classes that may be encoded to DER.
 */
interface Encodable
{
    /**
     * Encode object to DER.
     */
    public function toDER(): string;
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\ASN1\Exception;

use RuntimeException;
/**
 * Exception thrown on decoding errors.
 */
final class DecodeException extends RuntimeException
{
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\CryptoEncoding;

use function is_string;
use RuntimeException;
use Stringable;
use UnexpectedValueException;
/**
 * Implements PEM file encoding and decoding.
 *
 * @see https://tools.ietf.org/html/rfc7468
 */
final class PEM implements Stringable
{
    // well-known PEM types
    final public const TYPE_CERTIFICATE = 'CERTIFICATE';
    final public const TYPE_CRL = 'X509 CRL';
    final public const TYPE_CERTIFICATE_REQUEST = 'CERTIFICATE REQUEST';
    final public const TYPE_ATTRIBUTE_CERTIFICATE = 'ATTRIBUTE CERTIFICATE';
    final public const TYPE_PRIVATE_KEY = 'PRIVATE KEY';
    final public const TYPE_PUBLIC_KEY = 'PUBLIC KEY';
    final public const TYPE_ENCRYPTED_PRIVATE_KEY = 'ENCRYPTED PRIVATE KEY';
    final public const TYPE_RSA_PRIVATE_KEY = 'RSA PRIVATE KEY';
    final public const TYPE_RSA_PUBLIC_KEY = 'RSA PUBLIC KEY';
    final public const TYPE_EC_PRIVATE_KEY = 'EC PRIVATE KEY';
    final public const TYPE_PKCS7 = 'PKCS7';
    final public const TYPE_CMS = 'CMS';
    /**
     * Regular expression to match PEM block.
     *
     * @var string
     */
    final public const PEM_REGEX = '/' . '(?:^|[\r\n])' . '-----BEGIN (.+?)-----[\r\n]+' . '(.+?)' . '[\r\n]+-----END \1-----' . '/ms';
    /**
     * @param string $type Content type
     * @param string $data Payload
     */
    private function __construct(private readonly string $type, private readonly string $data)
    {
    }
    public function __toString(): string
    {
        return $this->string();
    }
    public static function create(string $_type, string $_data): self
    {
        return new self($_type, $_data);
    }
    /**
     * Initialize from a PEM-formatted string.
     */
    public static function fromString(string $str): self
    {
        if (preg_match(self::PEM_REGEX, $str, $match) !== 1) {
            throw new UnexpectedValueException('Not a PEM formatted string.');
        }
        $payload = preg_replace('/\s+/', '', $match[2]);
        if (!is_string($payload)) {
            throw new UnexpectedValueException('Failed to decode PEM data.');
        }
        $data = base64_decode($payload, \true);
        if ($data === \false) {
            throw new UnexpectedValueException('Failed to decode PEM data.');
        }
        return self::create($match[1], $data);
    }
    /**
     * Initialize from a file.
     *
     * @param string $filename Path to file
     */
    public static function fromFile(string $filename): self
    {
        if (!is_readable($filename)) {
            throw new RuntimeException("Failed to read {$filename}.");
        }
        $str = file_get_contents($filename);
        if ($str === \false) {
            throw new RuntimeException("Failed to read {$filename}.");
        }
        return self::fromString($str);
    }
    /**
     * Get content type.
     */
    public function type(): string
    {
        return $this->type;
    }
    public function data(): string
    {
        return $this->data;
    }
    /**
     * Encode to PEM string.
     */
    public function string(): string
    {
        return "-----BEGIN {$this->type}-----\n" . trim(chunk_split(base64_encode($this->data), 64, "\n")) . "\n" . "-----END {$this->type}-----";
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\CryptoEncoding;

use ArrayIterator;
use function count;
use Countable;
use function is_string;
use IteratorAggregate;
use LogicException;
use const PREG_SET_ORDER;
use RuntimeException;
use Stringable;
use UnexpectedValueException;
/**
 * Container for multiple PEM objects.
 *
 * The order of PEMs shall be retained, eg. when read from a file.
 */
final class PEMBundle implements Countable, IteratorAggregate, Stringable
{
    /**
     * Array of PEM objects.
     *
     * @var PEM[]
     */
    private array $pems;
    private function __construct(PEM ...$pems)
    {
        $this->pems = $pems;
    }
    public function __toString(): string
    {
        return $this->string();
    }
    public static function create(PEM ...$pems): self
    {
        return new self(...$pems);
    }
    /**
     * Initialize from a string.
     */
    public static function fromString(string $str): self
    {
        $hasMatches = preg_match_all(PEM::PEM_REGEX, $str, $matches, PREG_SET_ORDER);
        if ($hasMatches === \false || $hasMatches === 0) {
            throw new UnexpectedValueException('No PEM blocks.');
        }
        $pems = array_map(static function ($match) {
            $payload = preg_replace('/\s+/', '', $match[2]);
            if (!is_string($payload)) {
                throw new UnexpectedValueException('Failed to decode PEM data.');
            }
            $data = base64_decode($payload, \true);
            if ($data === \false) {
                throw new UnexpectedValueException('Failed to decode PEM data.');
            }
            return PEM::create($match[1], $data);
        }, $matches);
        return self::create(...$pems);
    }
    /**
     * Initialize from a file.
     */
    public static function fromFile(string $filename): self
    {
        if (!is_readable($filename)) {
            throw new RuntimeException("Failed to read {$filename}.");
        }
        $str = file_get_contents($filename);
        if ($str === \false) {
            throw new RuntimeException("Failed to read {$filename}.");
        }
        return self::fromString($str);
    }
    /**
     * Get self with PEM objects appended.
     */
    public function withPEMs(PEM ...$pems): self
    {
        $obj = clone $this;
        $obj->pems = array_merge($obj->pems, $pems);
        return $obj;
    }
    /**
     * Get all PEMs in a bundle.
     *
     * @return PEM[]
     */
    public function all(): array
    {
        return $this->pems;
    }
    /**
     * Get the first PEM in a bundle.
     */
    public function first(): PEM
    {
        if (count($this->pems) === 0) {
            throw new LogicException('No PEMs.');
        }
        return $this->pems[0];
    }
    /**
     * Get the last PEM in a bundle.
     */
    public function last(): PEM
    {
        if (count($this->pems) === 0) {
            throw new LogicException('No PEMs.');
        }
        return $this->pems[count($this->pems) - 1];
    }
    /**
     * @see \Countable::count()
     */
    public function count(): int
    {
        return count($this->pems);
    }
    /**
     * Get iterator for PEMs.
     *
     * @see \IteratorAggregate::getIterator()
     */
    public function getIterator(): ArrayIterator
    {
        return new ArrayIterator($this->pems);
    }
    /**
     * Encode bundle to a string of contiguous PEM blocks.
     */
    public function string(): string
    {
        return implode("\n", array_map(static fn(PEM $pem) => $pem->string(), $this->pems));
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\CryptoBridge\Crypto;

use function array_key_exists;
use function mb_strlen;
use const OPENSSL_ALGO_MD4;
use const OPENSSL_ALGO_MD5;
use const OPENSSL_ALGO_SHA1;
use const OPENSSL_ALGO_SHA224;
use const OPENSSL_ALGO_SHA256;
use const OPENSSL_ALGO_SHA384;
use const OPENSSL_ALGO_SHA512;
use const OPENSSL_RAW_DATA;
use const OPENSSL_ZERO_PADDING;
use RuntimeException;
use _ContaoManager\SpomkyLabs\Pki\CryptoBridge\Crypto;
use _ContaoManager\SpomkyLabs\Pki\CryptoTypes\AlgorithmIdentifier\AlgorithmIdentifier;
use _ContaoManager\SpomkyLabs\Pki\CryptoTypes\AlgorithmIdentifier\Cipher\BlockCipherAlgorithmIdentifier;
use _ContaoManager\SpomkyLabs\Pki\CryptoTypes\AlgorithmIdentifier\Cipher\CipherAlgorithmIdentifier;
use _ContaoManager\SpomkyLabs\Pki\CryptoTypes\AlgorithmIdentifier\Cipher\RC2CBCAlgorithmIdentifier;
use _ContaoManager\SpomkyLabs\Pki\CryptoTypes\AlgorithmIdentifier\Feature\SignatureAlgorithmIdentifier;
use _ContaoManager\SpomkyLabs\Pki\CryptoTypes\Asymmetric\PrivateKeyInfo;
use _ContaoManager\SpomkyLabs\Pki\CryptoTypes\Asymmetric\PublicKeyInfo;
use _ContaoManager\SpomkyLabs\Pki\CryptoTypes\Signature\Signature;
use function sprintf;
use UnexpectedValueException;
/**
 * Crypto engine using OpenSSL extension.
 */
final class OpenSSLCrypto extends Crypto
{
    /**
     * Mapping from algorithm OID to OpenSSL signature method identifier.
     *
     * @internal
     *
     * @var array<string, int>
     */
    private const MAP_DIGEST_OID = [AlgorithmIdentifier::OID_MD4_WITH_RSA_ENCRYPTION => OPENSSL_ALGO_MD4, AlgorithmIdentifier::OID_MD5_WITH_RSA_ENCRYPTION => OPENSSL_ALGO_MD5, AlgorithmIdentifier::OID_SHA1_WITH_RSA_ENCRYPTION => OPENSSL_ALGO_SHA1, AlgorithmIdentifier::OID_SHA224_WITH_RSA_ENCRYPTION => OPENSSL_ALGO_SHA224, AlgorithmIdentifier::OID_SHA256_WITH_RSA_ENCRYPTION => OPENSSL_ALGO_SHA256, AlgorithmIdentifier::OID_SHA384_WITH_RSA_ENCRYPTION => OPENSSL_ALGO_SHA384, AlgorithmIdentifier::OID_SHA512_WITH_RSA_ENCRYPTION => OPENSSL_ALGO_SHA512, AlgorithmIdentifier::OID_ECDSA_WITH_SHA1 => OPENSSL_ALGO_SHA1, AlgorithmIdentifier::OID_ECDSA_WITH_SHA224 => OPENSSL_ALGO_SHA224, AlgorithmIdentifier::OID_ECDSA_WITH_SHA256 => OPENSSL_ALGO_SHA256, AlgorithmIdentifier::OID_ECDSA_WITH_SHA384 => OPENSSL_ALGO_SHA384, AlgorithmIdentifier::OID_ECDSA_WITH_SHA512 => OPENSSL_ALGO_SHA512];
    /**
     * Mapping from algorithm OID to OpenSSL cipher method name.
     *
     * @internal
     *
     * @var array<string, string>
     */
    private const MAP_CIPHER_OID = [AlgorithmIdentifier::OID_DES_CBC => 'des-cbc', AlgorithmIdentifier::OID_DES_EDE3_CBC => 'des-ede3-cbc', AlgorithmIdentifier::OID_AES_128_CBC => 'aes-128-cbc', AlgorithmIdentifier::OID_AES_192_CBC => 'aes-192-cbc', AlgorithmIdentifier::OID_AES_256_CBC => 'aes-256-cbc'];
    public function sign(string $data, PrivateKeyInfo $privkey_info, SignatureAlgorithmIdentifier $algo): Signature
    {
        $this->_checkSignatureAlgoAndKey($algo, $privkey_info->algorithmIdentifier());
        $result = openssl_sign($data, $signature, (string) $privkey_info->toPEM(), $this->_algoToDigest($algo));
        if ($result === \false) {
            throw new RuntimeException('openssl_sign() failed: ' . $this->_getLastError());
        }
        return Signature::fromSignatureData($signature, $algo);
    }
    public function verify(string $data, Signature $signature, PublicKeyInfo $pubkey_info, SignatureAlgorithmIdentifier $algo): bool
    {
        $this->_checkSignatureAlgoAndKey($algo, $pubkey_info->algorithmIdentifier());
        $result = openssl_verify($data, $signature->bitString()->string(), (string) $pubkey_info->toPEM(), $this->_algoToDigest($algo));
        if ($result === -1) {
            throw new RuntimeException('openssl_verify() failed: ' . $this->_getLastError());
        }
        return $result === 1;
    }
    public function encrypt(string $data, string $key, CipherAlgorithmIdentifier $algo): string
    {
        $this->_checkCipherKeySize($algo, $key);
        $iv = $algo->initializationVector();
        $result = openssl_encrypt($data, $this->_algoToCipher($algo), $key, OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING, $iv);
        if ($result === \false) {
            throw new RuntimeException('openssl_encrypt() failed: ' . $this->_getLastError());
        }
        return $result;
    }
    public function decrypt(string $data, string $key, CipherAlgorithmIdentifier $algo): string
    {
        $this->_checkCipherKeySize($algo, $key);
        $iv = $algo->initializationVector();
        $result = openssl_decrypt($data, $this->_algoToCipher($algo), $key, OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING, $iv);
        if ($result === \false) {
            throw new RuntimeException('openssl_decrypt() failed: ' . $this->_getLastError());
        }
        return $result;
    }
    /**
     * Validate cipher algorithm key size.
     */
    protected function _checkCipherKeySize(CipherAlgorithmIdentifier $algo, string $key): void
    {
        if ($algo instanceof BlockCipherAlgorithmIdentifier) {
            if (mb_strlen($key, '8bit') !== $algo->keySize()) {
                throw new UnexpectedValueException(sprintf('Key length for %s must be %d, %d given.', $algo->name(), $algo->keySize(), mb_strlen($key, '8bit')));
            }
        }
    }
    /**
     * Get last OpenSSL error message.
     */
    protected function _getLastError(): ?string
    {
        // pump error message queue
        $msg = null;
        while (\false !== $err = openssl_error_string()) {
            $msg = $err;
        }
        return $msg;
    }
    /**
     * Check that given signature algorithm supports key of given type.
     *
     * @param SignatureAlgorithmIdentifier $sig_algo Signature algorithm
     * @param AlgorithmIdentifier $key_algo Key algorithm
     */
    protected function _checkSignatureAlgoAndKey(SignatureAlgorithmIdentifier $sig_algo, AlgorithmIdentifier $key_algo): void
    {
        if (!$sig_algo->supportsKeyAlgorithm($key_algo)) {
            throw new UnexpectedValueException(sprintf('Signature algorithm %s does not support key algorithm %s.', $sig_algo->name(), $key_algo->name()));
        }
    }
    /**
     * Get OpenSSL digest method for given signature algorithm identifier.
     */
    protected function _algoToDigest(SignatureAlgorithmIdentifier $algo): int
    {
        $oid = $algo->oid();
        if (!array_key_exists($oid, self::MAP_DIGEST_OID)) {
            throw new UnexpectedValueException(sprintf('Digest method %s not supported.', $algo->name()));
        }
        return self::MAP_DIGEST_OID[$oid];
    }
    /**
     * Get OpenSSL cipher method for given cipher algorithm identifier.
     */
    protected function _algoToCipher(CipherAlgorithmIdentifier $algo): string
    {
        $oid = $algo->oid();
        if (array_key_exists($oid, self::MAP_CIPHER_OID)) {
            return self::MAP_CIPHER_OID[$oid];
        }
        if ($oid === AlgorithmIdentifier::OID_RC2_CBC) {
            if (!$algo instanceof RC2CBCAlgorithmIdentifier) {
                throw new UnexpectedValueException('Not an RC2-CBC algorithm.');
            }
            return $this->_rc2AlgoToCipher($algo);
        }
        throw new UnexpectedValueException(sprintf('Cipher method %s not supported.', $algo->name()));
    }
    /**
     * Get OpenSSL cipher method for given RC2 algorithm identifier.
     */
    protected function _rc2AlgoToCipher(RC2CBCAlgorithmIdentifier $algo): string
    {
        return match ($algo->effectiveKeyBits()) {
            128 => 'rc2-cbc',
            64 => 'rc2-64-cbc',
            40 => 'rc2-40-cbc',
            default => throw new UnexpectedValueException($algo->effectiveKeyBits() . ' bit RC2 not supported.'),
        };
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\CryptoBridge;

use function defined;
use RuntimeException;
use _ContaoManager\SpomkyLabs\Pki\CryptoBridge\Crypto\OpenSSLCrypto;
use _ContaoManager\SpomkyLabs\Pki\CryptoTypes\AlgorithmIdentifier\Cipher\CipherAlgorithmIdentifier;
use _ContaoManager\SpomkyLabs\Pki\CryptoTypes\AlgorithmIdentifier\Feature\SignatureAlgorithmIdentifier;
use _ContaoManager\SpomkyLabs\Pki\CryptoTypes\Asymmetric\PrivateKeyInfo;
use _ContaoManager\SpomkyLabs\Pki\CryptoTypes\Asymmetric\PublicKeyInfo;
use _ContaoManager\SpomkyLabs\Pki\CryptoTypes\Signature\Signature;
/**
 * Base class for crypto engine implementations.
 */
abstract class Crypto
{
    /**
     * Sign data with given algorithm using given private key.
     *
     * @param string $data Data to sign
     * @param PrivateKeyInfo $privkey_info Private key
     * @param SignatureAlgorithmIdentifier $algo Signature algorithm
     */
    abstract public function sign(string $data, PrivateKeyInfo $privkey_info, SignatureAlgorithmIdentifier $algo): Signature;
    /**
     * Verify signature with given algorithm using given public key.
     *
     * @param string $data Data to verify
     * @param Signature $signature Signature
     * @param PublicKeyInfo $pubkey_info Public key
     * @param SignatureAlgorithmIdentifier $algo Signature algorithm
     *
     * @return bool True if signature matches
     */
    abstract public function verify(string $data, Signature $signature, PublicKeyInfo $pubkey_info, SignatureAlgorithmIdentifier $algo): bool;
    /**
     * Encrypt data with given algorithm using given key.
     *
     * Padding must be added by the caller. Initialization vector is taken from the algorithm identifier if available.
     *
     * @param string $data Plaintext
     * @param string $key Encryption key
     * @param CipherAlgorithmIdentifier $algo Encryption algorithm
     *
     * @return string Ciphertext
     */
    abstract public function encrypt(string $data, string $key, CipherAlgorithmIdentifier $algo): string;
    /**
     * Decrypt data with given algorithm using given key.
     *
     * Possible padding is not removed and must be handled by the caller. Initialization vector is taken from the
     * algorithm identifier if available.
     *
     * @param string $data Ciphertext
     * @param string $key Encryption key
     * @param CipherAlgorithmIdentifier $algo Encryption algorithm
     *
     * @return string Plaintext
     */
    abstract public function decrypt(string $data, string $key, CipherAlgorithmIdentifier $algo): string;
    /**
     * Get default supported crypto implementation.
     */
    public static function getDefault(): self
    {
        if (defined('OPENSSL_VERSION_NUMBER')) {
            return new OpenSSLCrypto();
        }
        // @codeCoverageIgnoreStart
        throw new RuntimeException('No crypto implementation available.');
        // @codeCoverageIgnoreEnd
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\X509\Certificate;

use DateTimeImmutable;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Element;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Primitive\GeneralizedTime;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Primitive\UTCTime;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\TimeType;
use _ContaoManager\SpomkyLabs\Pki\X509\Feature\DateTimeHelper;
use UnexpectedValueException;
/**
 * Implements *Time* ASN.1 type.
 *
 * @see https://tools.ietf.org/html/rfc5280#section-4.1
 */
final class Time
{
    use DateTimeHelper;
    /**
     * Time ASN.1 type tag.
     */
    private readonly int $type;
    private function __construct(protected DateTimeImmutable $dt, ?int $type)
    {
        $this->type = $type ?? self::determineType($dt);
    }
    public static function create(DateTimeImmutable $dt, ?int $time = null): self
    {
        return new self($dt, $time);
    }
    /**
     * Initialize from ASN.1.
     */
    public static function fromASN1(TimeType $el): self
    {
        // Pass the type of the original ASN.1 primitive
        if ($el instanceof UTCTime) {
            return self::create($el->dateTime(), Element::TYPE_UTC_TIME);
        }
        if ($el instanceof GeneralizedTime) {
            return self::create($el->dateTime(), Element::TYPE_GENERALIZED_TIME);
        }
        return self::create($el->dateTime());
        // TODO: should never happen?
    }
    /**
     * Initialize from date string.
     */
    public static function fromString(?string $time, ?string $tz = null): self
    {
        return self::create(self::createDateTime($time, $tz));
    }
    public function dateTime(): DateTimeImmutable
    {
        return $this->dt;
    }
    /**
     * Generate ASN.1.
     */
    public function toASN1(): TimeType
    {
        $dt = $this->dt;
        switch ($this->type) {
            case Element::TYPE_UTC_TIME:
                return UTCTime::create($dt);
            case Element::TYPE_GENERALIZED_TIME:
                // GeneralizedTime must not contain fractional seconds
                // (rfc5280 4.1.2.5.2)
                if ((int) $dt->format('u') !== 0) {
                    // remove fractional seconds (round down)
                    $dt = self::roundDownFractionalSeconds($dt);
                }
                return GeneralizedTime::create($dt);
        }
        throw new UnexpectedValueException('Time type ' . Element::tagToName($this->type) . ' not supported.');
    }
    /**
     * Determine whether to use UTCTime or GeneralizedTime ASN.1 type.
     *
     * @return int Type tag
     */
    protected static function determineType(DateTimeImmutable $dt): int
    {
        if ($dt->format('Y') >= 2050) {
            return Element::TYPE_GENERALIZED_TIME;
        }
        return Element::TYPE_UTC_TIME;
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\X509\Certificate\Extension;

use ArrayIterator;
use function count;
use Countable;
use IteratorAggregate;
use LogicException;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Element;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Constructed\Sequence;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\UnspecifiedType;
use _ContaoManager\SpomkyLabs\Pki\X509\Certificate\Extension\DistributionPoint\DistributionPoint;
use UnexpectedValueException;
/**
 * Implements 'CRL Distribution Points' certificate extension.
 *
 * @see https://tools.ietf.org/html/rfc5280#section-4.2.1.13
 */
class CRLDistributionPointsExtension extends Extension implements Countable, IteratorAggregate
{
    /**
     * Distribution points.
     *
     * @var DistributionPoint[]
     */
    protected array $distributionPoints;
    protected function __construct(string $oid, bool $critical, DistributionPoint ...$distributionPoints)
    {
        parent::__construct($oid, $critical);
        $this->distributionPoints = $distributionPoints;
    }
    public static function create(bool $critical, DistributionPoint ...$distribution_points): self
    {
        return new self(self::OID_CRL_DISTRIBUTION_POINTS, $critical, ...$distribution_points);
    }
    /**
     * Get distribution points.
     *
     * @return DistributionPoint[]
     */
    public function distributionPoints(): array
    {
        return $this->distributionPoints;
    }
    /**
     * Get the number of distribution points.
     *
     * @see \Countable::count()
     */
    public function count(): int
    {
        return count($this->distributionPoints);
    }
    /**
     * Get iterator for distribution points.
     *
     * @see \IteratorAggregate::getIterator()
     */
    public function getIterator(): ArrayIterator
    {
        return new ArrayIterator($this->distributionPoints);
    }
    protected static function fromDER(string $data, bool $critical): static
    {
        $dps = array_map(static fn(UnspecifiedType $el) => DistributionPoint::fromASN1($el->asSequence()), UnspecifiedType::fromDER($data)->asSequence()->elements());
        if (count($dps) === 0) {
            throw new UnexpectedValueException('CRLDistributionPoints must have at least one DistributionPoint.');
        }
        // late static bound, extended by Freshest CRL extension
        return static::create($critical, ...$dps);
    }
    protected function valueASN1(): Element
    {
        if (count($this->distributionPoints) === 0) {
            throw new LogicException('No distribution points.');
        }
        $elements = array_map(static fn(DistributionPoint $dp) => $dp->toASN1(), $this->distributionPoints);
        return Sequence::create(...$elements);
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\X509\Certificate\Extension;

use ArrayIterator;
use function count;
use Countable;
use IteratorAggregate;
use LogicException;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Element;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\UnspecifiedType;
use _ContaoManager\SpomkyLabs\Pki\X501\ASN1\Attribute;
use _ContaoManager\SpomkyLabs\Pki\X501\ASN1\Collection\SequenceOfAttributes;
use UnexpectedValueException;
/**
 * Implements 'Subject Directory Attributes' certificate extension.
 *
 * @see https://tools.ietf.org/html/rfc5280#section-4.2.1.8
 */
final class SubjectDirectoryAttributesExtension extends Extension implements Countable, IteratorAggregate
{
    /**
     * Attributes.
     */
    private readonly SequenceOfAttributes $attributes;
    /**
     * @param Attribute ...$attribs One or more Attribute objects
     */
    private function __construct(bool $critical, Attribute ...$attribs)
    {
        parent::__construct(self::OID_SUBJECT_DIRECTORY_ATTRIBUTES, $critical);
        $this->attributes = SequenceOfAttributes::create(...$attribs);
    }
    public static function create(bool $critical, Attribute ...$attribs): self
    {
        return new self($critical, ...$attribs);
    }
    /**
     * Check whether attribute is present.
     *
     * @param string $name OID or attribute name
     */
    public function has(string $name): bool
    {
        return $this->attributes->has($name);
    }
    /**
     * Get first attribute by OID or attribute name.
     *
     * @param string $name OID or attribute name
     */
    public function firstOf(string $name): Attribute
    {
        return $this->attributes->firstOf($name);
    }
    /**
     * Get all attributes of given name.
     *
     * @param string $name OID or attribute name
     *
     * @return Attribute[]
     */
    public function allOf(string $name): array
    {
        return $this->attributes->allOf($name);
    }
    /**
     * Get all attributes.
     *
     * @return Attribute[]
     */
    public function all(): array
    {
        return $this->attributes->all();
    }
    /**
     * Get number of attributes.
     */
    public function count(): int
    {
        return count($this->attributes);
    }
    /**
     * Get iterator for attributes.
     *
     * @return ArrayIterator|Attribute[]
     */
    public function getIterator(): ArrayIterator
    {
        return $this->attributes->getIterator();
    }
    protected static function fromDER(string $data, bool $critical): static
    {
        $attribs = SequenceOfAttributes::fromASN1(UnspecifiedType::fromDER($data)->asSequence());
        if (count($attribs) === 0) {
            throw new UnexpectedValueException('SubjectDirectoryAttributes must have at least one Attribute.');
        }
        return self::create($critical, ...$attribs->all());
    }
    protected function valueASN1(): Element
    {
        if (count($this->attributes) === 0) {
            throw new LogicException('No attributes');
        }
        return $this->attributes->toASN1();
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\X509\Certificate\Extension\AccessDescription;

use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Constructed\Sequence;
use _ContaoManager\SpomkyLabs\Pki\X509\GeneralName\GeneralName;
/**
 * @see https://tools.ietf.org/html/rfc5280#section-4.2.2.2
 */
final class SubjectAccessDescription extends AccessDescription
{
    /**
     * Access method OID's.
     *
     * @var string
     */
    final public const OID_METHOD_TIME_STAMPING = '1.3.6.1.5.5.7.48.3';
    final public const OID_METHOD_CA_REPOSITORY = '1.3.6.1.5.5.7.48.5';
    public static function create(string $accessMethod, GeneralName $accessLocation): self
    {
        return new self($accessMethod, $accessLocation);
    }
    /**
     * Initialize from ASN.1.
     */
    public static function fromASN1(Sequence $seq): static
    {
        return new static($seq->at(0)->asObjectIdentifier()->oid(), GeneralName::fromASN1($seq->at(1)->asTagged()));
    }
    /**
     * Check whether access method is time stamping.
     */
    public function isTimeStampingMethod(): bool
    {
        return $this->accessMethod === self::OID_METHOD_TIME_STAMPING;
    }
    /**
     * Check whether access method is CA repository.
     */
    public function isCARepositoryMethod(): bool
    {
        return $this->accessMethod === self::OID_METHOD_CA_REPOSITORY;
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\X509\Certificate\Extension\AccessDescription;

use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Constructed\Sequence;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Primitive\ObjectIdentifier;
use _ContaoManager\SpomkyLabs\Pki\X509\GeneralName\GeneralName;
/**
 * Base class implementing *AccessDescription* ASN.1 type for 'Authority Information Access' and 'Subject Information
 * Access' certificate extensions.
 *
 * @see https://tools.ietf.org/html/rfc5280#section-4.2.2.1
 */
abstract class AccessDescription
{
    /**
     * @param string $accessMethod Access method OID
     * @param GeneralName $accessLocation Access location
     */
    protected function __construct(protected readonly string $accessMethod, protected readonly GeneralName $accessLocation)
    {
    }
    /**
     * Initialize from ASN.1.
     */
    abstract public static function fromASN1(Sequence $seq): static;
    /**
     * Get the access method OID.
     */
    public function accessMethod(): string
    {
        return $this->accessMethod;
    }
    /**
     * Get the access location.
     */
    public function accessLocation(): GeneralName
    {
        return $this->accessLocation;
    }
    /**
     * Generate ASN.1 structure.
     */
    public function toASN1(): Sequence
    {
        return Sequence::create(ObjectIdentifier::create($this->accessMethod), $this->accessLocation->toASN1());
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\X509\Certificate\Extension\AccessDescription;

use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Constructed\Sequence;
use _ContaoManager\SpomkyLabs\Pki\X509\GeneralName\GeneralName;
/**
 * @see https://tools.ietf.org/html/rfc5280#section-4.2.2.1
 */
final class AuthorityAccessDescription extends AccessDescription
{
    /**
     * Access method OID's.
     *
     * @var string
     */
    final public const OID_METHOD_OSCP = '1.3.6.1.5.5.7.48.1';
    final public const OID_METHOD_CA_ISSUERS = '1.3.6.1.5.5.7.48.2';
    public static function create(string $accessMethod, GeneralName $accessLocation): self
    {
        return new self($accessMethod, $accessLocation);
    }
    /**
     * Initialize from ASN.1.
     */
    public static function fromASN1(Sequence $seq): static
    {
        return new static($seq->at(0)->asObjectIdentifier()->oid(), GeneralName::fromASN1($seq->at(1)->asTagged()));
    }
    /**
     * Check whether access method is OSCP.
     */
    public function isOSCPMethod(): bool
    {
        return $this->accessMethod === self::OID_METHOD_OSCP;
    }
    /**
     * Check whether access method is CA issuers.
     */
    public function isCAIssuersMethod(): bool
    {
        return $this->accessMethod === self::OID_METHOD_CA_ISSUERS;
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\X509\Certificate\Extension;

use _ContaoManager\SpomkyLabs\Pki\ASN1\Element;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Primitive\NullType;
/**
 * Implements 'No Revocation Available' certificate extension.
 *
 * @see https://tools.ietf.org/html/rfc5755#section-4.3.6
 */
final class NoRevocationAvailableExtension extends Extension
{
    private function __construct(bool $critical)
    {
        parent::__construct(self::OID_NO_REV_AVAIL, $critical);
    }
    public static function create(bool $critical): self
    {
        return new self($critical);
    }
    protected static function fromDER(string $data, bool $critical): static
    {
        NullType::fromDER($data);
        return self::create($critical);
    }
    protected function valueASN1(): Element
    {
        return NullType::create();
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\X509\Certificate\Extension;

use LogicException;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Element;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Constructed\Sequence;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Primitive\Integer;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Tagged\ImplicitlyTaggedType;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\UnspecifiedType;
/**
 * Implements 'Policy Constraints' certificate extensions.
 *
 * @see https://tools.ietf.org/html/rfc5280#section-4.2.1.11
 */
final class PolicyConstraintsExtension extends Extension
{
    private function __construct(bool $critical, private readonly ?int $requireExplicitPolicy, private readonly ?int $inhibitPolicyMapping)
    {
        parent::__construct(self::OID_POLICY_CONSTRAINTS, $critical);
    }
    public static function create(bool $critical, ?int $requireExplicitPolicy = null, ?int $inhibitPolicyMapping = null): self
    {
        return new self($critical, $requireExplicitPolicy, $inhibitPolicyMapping);
    }
    /**
     * Whether requireExplicitPolicy is present.
     */
    public function hasRequireExplicitPolicy(): bool
    {
        return isset($this->requireExplicitPolicy);
    }
    public function requireExplicitPolicy(): int
    {
        if (!$this->hasRequireExplicitPolicy()) {
            throw new LogicException('requireExplicitPolicy not set.');
        }
        return $this->requireExplicitPolicy;
    }
    /**
     * Whether inhibitPolicyMapping is present.
     */
    public function hasInhibitPolicyMapping(): bool
    {
        return isset($this->inhibitPolicyMapping);
    }
    public function inhibitPolicyMapping(): int
    {
        if (!$this->hasInhibitPolicyMapping()) {
            throw new LogicException('inhibitPolicyMapping not set.');
        }
        return $this->inhibitPolicyMapping;
    }
    protected static function fromDER(string $data, bool $critical): static
    {
        $seq = UnspecifiedType::fromDER($data)->asSequence();
        $require_explicit_policy = null;
        $inhibit_policy_mapping = null;
        if ($seq->hasTagged(0)) {
            $require_explicit_policy = $seq->getTagged(0)->asImplicit(Element::TYPE_INTEGER)->asInteger()->intNumber();
        }
        if ($seq->hasTagged(1)) {
            $inhibit_policy_mapping = $seq->getTagged(1)->asImplicit(Element::TYPE_INTEGER)->asInteger()->intNumber();
        }
        return self::create($critical, $require_explicit_policy, $inhibit_policy_mapping);
    }
    protected function valueASN1(): Element
    {
        $elements = [];
        if (isset($this->requireExplicitPolicy)) {
            $elements[] = ImplicitlyTaggedType::create(0, Integer::create($this->requireExplicitPolicy));
        }
        if (isset($this->inhibitPolicyMapping)) {
            $elements[] = ImplicitlyTaggedType::create(1, Integer::create($this->inhibitPolicyMapping));
        }
        return Sequence::create(...$elements);
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\X509\Certificate\Extension;

use ArrayIterator;
use function count;
use Countable;
use IteratorAggregate;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Element;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Constructed\Sequence;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\UnspecifiedType;
use _ContaoManager\SpomkyLabs\Pki\X509\Certificate\Extension\AccessDescription\AccessDescription;
use _ContaoManager\SpomkyLabs\Pki\X509\Certificate\Extension\AccessDescription\AuthorityAccessDescription;
/**
 * Implements 'Authority Information Access' extension.
 *
 * @see https://tools.ietf.org/html/rfc5280#section-4.2.2.1
 */
final class AuthorityInformationAccessExtension extends Extension implements Countable, IteratorAggregate
{
    /**
     * Access descriptions.
     *
     * @var AuthorityAccessDescription[]
     */
    private readonly array $accessDescriptions;
    private function __construct(bool $critical, AuthorityAccessDescription ...$access)
    {
        parent::__construct(self::OID_AUTHORITY_INFORMATION_ACCESS, $critical);
        $this->accessDescriptions = $access;
    }
    public static function create(bool $critical, AuthorityAccessDescription ...$access): self
    {
        return new self($critical, ...$access);
    }
    /**
     * Get the access descriptions.
     *
     * @return AuthorityAccessDescription[]
     */
    public function accessDescriptions(): array
    {
        return $this->accessDescriptions;
    }
    /**
     * Get the number of access descriptions.
     *
     * @see \Countable::count()
     */
    public function count(): int
    {
        return count($this->accessDescriptions);
    }
    /**
     * Get iterator for access descriptions.
     *
     * @return ArrayIterator List of AuthorityAccessDescription objects
     * @see \IteratorAggregate::getIterator()
     */
    public function getIterator(): ArrayIterator
    {
        return new ArrayIterator($this->accessDescriptions);
    }
    protected static function fromDER(string $data, bool $critical): static
    {
        $access = array_map(static fn(UnspecifiedType $el) => AuthorityAccessDescription::fromASN1($el->asSequence()), UnspecifiedType::fromDER($data)->asSequence()->elements());
        return self::create($critical, ...$access);
    }
    protected function valueASN1(): Element
    {
        $elements = array_map(static fn(AccessDescription $access) => $access->toASN1(), $this->accessDescriptions);
        return Sequence::create(...$elements);
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\X509\Certificate\Extension;

use ArrayIterator;
use function count;
use Countable;
use IteratorAggregate;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Element;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Constructed\Sequence;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\UnspecifiedType;
use _ContaoManager\SpomkyLabs\Pki\X509\Certificate\Extension\AccessDescription\AccessDescription;
use _ContaoManager\SpomkyLabs\Pki\X509\Certificate\Extension\AccessDescription\SubjectAccessDescription;
/**
 * Implements 'Subject Information Access' extension.
 *
 * @see https://tools.ietf.org/html/rfc5280#section-4.2.2.2
 */
final class SubjectInformationAccessExtension extends Extension implements Countable, IteratorAggregate
{
    /**
     * Access descriptions.
     *
     * @var SubjectAccessDescription[]
     */
    private readonly array $accessDescriptions;
    private function __construct(bool $critical, SubjectAccessDescription ...$accessDescriptions)
    {
        parent::__construct(self::OID_SUBJECT_INFORMATION_ACCESS, $critical);
        $this->accessDescriptions = $accessDescriptions;
    }
    public static function create(bool $critical, SubjectAccessDescription ...$accessDescriptions): self
    {
        return new self($critical, ...$accessDescriptions);
    }
    /**
     * Get the access descriptions.
     *
     * @return SubjectAccessDescription[]
     */
    public function accessDescriptions(): array
    {
        return $this->accessDescriptions;
    }
    /**
     * Get the number of access descriptions.
     *
     * @see \Countable::count()
     */
    public function count(): int
    {
        return count($this->accessDescriptions);
    }
    /**
     * Get iterator for access descriptions.
     *
     * @return ArrayIterator List of SubjectAccessDescription objects
     * @see \IteratorAggregate::getIterator()
     */
    public function getIterator(): ArrayIterator
    {
        return new ArrayIterator($this->accessDescriptions);
    }
    protected static function fromDER(string $data, bool $critical): static
    {
        $access = array_map(static fn(UnspecifiedType $el) => SubjectAccessDescription::fromASN1($el->asSequence()), UnspecifiedType::fromDER($data)->asSequence()->elements());
        return self::create($critical, ...$access);
    }
    protected function valueASN1(): Element
    {
        $elements = array_map(static fn(AccessDescription $access) => $access->toASN1(), $this->accessDescriptions);
        return Sequence::create(...$elements);
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\X509\Certificate\Extension;

use ArrayIterator;
use function count;
use Countable;
use IteratorAggregate;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Element;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Constructed\Sequence;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\UnspecifiedType;
use _ContaoManager\SpomkyLabs\Pki\X509\Certificate\Extension\Target\Target;
use _ContaoManager\SpomkyLabs\Pki\X509\Certificate\Extension\Target\Targets;
/**
 * Implements 'AC Targeting' certificate extension.
 *
 * NOTE**: Syntax is *SEQUENCE OF Targets*, but only one *Targets* element must be used. Multiple *Targets* elements
 * shall be merged into single *Targets*.
 *
 * @see https://tools.ietf.org/html/rfc5755#section-4.3.2
 */
final class TargetInformationExtension extends Extension implements Countable, IteratorAggregate
{
    /**
     * Targets elements.
     *
     * @var Targets[]
     */
    protected array $targets;
    /**
     * Targets[] merged to single Targets.
     */
    private ?Targets $merged = null;
    private function __construct(bool $critical, Targets ...$targets)
    {
        parent::__construct(self::OID_TARGET_INFORMATION, $critical);
        $this->targets = $targets;
    }
    /**
     * Reset internal state on clone.
     */
    public function __clone()
    {
        $this->merged = null;
    }
    public static function create(bool $critical, Targets ...$targets): self
    {
        return new self($critical, ...$targets);
    }
    /**
     * Initialize from one or more Target objects.
     *
     * Extension criticality shall be set to true as specified by RFC 5755.
     */
    public static function fromTargets(Target ...$target): self
    {
        return self::create(\true, Targets::create(...$target));
    }
    /**
     * Get all targets.
     */
    public function targets(): Targets
    {
        if ($this->merged === null) {
            $a = [];
            foreach ($this->targets as $targets) {
                $a = array_merge($a, $targets->all());
            }
            $this->merged = Targets::create(...$a);
        }
        return $this->merged;
    }
    /**
     * Get all name targets.
     *
     * @return Target[]
     */
    public function names(): array
    {
        return $this->targets()->nameTargets();
    }
    /**
     * Get all group targets.
     *
     * @return Target[]
     */
    public function groups(): array
    {
        return $this->targets()->groupTargets();
    }
    /**
     * @see \Countable::count()
     */
    public function count(): int
    {
        return count($this->targets());
    }
    /**
     * Get iterator for targets.
     *
     * @see \IteratorAggregate::getIterator()
     */
    public function getIterator(): ArrayIterator
    {
        return new ArrayIterator($this->targets()->all());
    }
    protected static function fromDER(string $data, bool $critical): static
    {
        $targets = array_map(static fn(UnspecifiedType $el) => Targets::fromASN1($el->asSequence()), UnspecifiedType::fromDER($data)->asSequence()->elements());
        return self::create($critical, ...$targets);
    }
    protected function valueASN1(): Element
    {
        $elements = array_map(static fn(Targets $targets) => $targets->toASN1(), $this->targets);
        return Sequence::create(...$elements);
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\X509\Certificate\Extension;

use _ContaoManager\SpomkyLabs\Pki\ASN1\Element;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\UnspecifiedType;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Util\Flags;
/**
 * Implements 'Key Usage' certificate extension.
 *
 * @see https://tools.ietf.org/html/rfc5280#section-4.2.1.3
 */
final class KeyUsageExtension extends Extension
{
    final public const DIGITAL_SIGNATURE = 0x100;
    final public const NON_REPUDIATION = 0x80;
    final public const KEY_ENCIPHERMENT = 0x40;
    final public const DATA_ENCIPHERMENT = 0x20;
    final public const KEY_AGREEMENT = 0x10;
    final public const KEY_CERT_SIGN = 0x8;
    final public const CRL_SIGN = 0x4;
    final public const ENCIPHER_ONLY = 0x2;
    final public const DECIPHER_ONLY = 0x1;
    private function __construct(bool $critical, private readonly int $keyUsage)
    {
        parent::__construct(self::OID_KEY_USAGE, $critical);
    }
    public static function create(bool $critical, int $keyUsage): self
    {
        return new self($critical, $keyUsage);
    }
    /**
     * Check whether digitalSignature flag is set.
     */
    public function isDigitalSignature(): bool
    {
        return $this->_flagSet(self::DIGITAL_SIGNATURE);
    }
    /**
     * Check whether nonRepudiation/contentCommitment flag is set.
     */
    public function isNonRepudiation(): bool
    {
        return $this->_flagSet(self::NON_REPUDIATION);
    }
    /**
     * Check whether keyEncipherment flag is set.
     */
    public function isKeyEncipherment(): bool
    {
        return $this->_flagSet(self::KEY_ENCIPHERMENT);
    }
    /**
     * Check whether dataEncipherment flag is set.
     */
    public function isDataEncipherment(): bool
    {
        return $this->_flagSet(self::DATA_ENCIPHERMENT);
    }
    /**
     * Check whether keyAgreement flag is set.
     */
    public function isKeyAgreement(): bool
    {
        return $this->_flagSet(self::KEY_AGREEMENT);
    }
    /**
     * Check whether keyCertSign flag is set.
     */
    public function isKeyCertSign(): bool
    {
        return $this->_flagSet(self::KEY_CERT_SIGN);
    }
    /**
     * Check whether cRLSign flag is set.
     */
    public function isCRLSign(): bool
    {
        return $this->_flagSet(self::CRL_SIGN);
    }
    /**
     * Check whether encipherOnly flag is set.
     */
    public function isEncipherOnly(): bool
    {
        return $this->_flagSet(self::ENCIPHER_ONLY);
    }
    /**
     * Check whether decipherOnly flag is set.
     */
    public function isDecipherOnly(): bool
    {
        return $this->_flagSet(self::DECIPHER_ONLY);
    }
    /**
     * Check whether given flag is set.
     */
    protected function _flagSet(int $flag): bool
    {
        return (bool) ($this->keyUsage & $flag);
    }
    protected static function fromDER(string $data, bool $critical): static
    {
        return self::create($critical, Flags::fromBitString(UnspecifiedType::fromDER($data)->asBitString(), 9)->intNumber());
    }
    protected function valueASN1(): Element
    {
        $flags = Flags::create($this->keyUsage, 9);
        return $flags->bitString()->withoutTrailingZeroes();
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\X509\Certificate\Extension\Target;

use _ContaoManager\SpomkyLabs\Pki\ASN1\Element;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Tagged\ExplicitlyTaggedType;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\TaggedType;
use _ContaoManager\SpomkyLabs\Pki\X509\GeneralName\GeneralName;
/**
 * Implements 'targetName' CHOICE of the *Target* ASN.1 type.
 *
 * @see https://tools.ietf.org/html/rfc5755#section-4.3.2
 */
final class TargetName extends Target
{
    private function __construct(private readonly GeneralName $name)
    {
        parent::__construct(self::TYPE_NAME);
    }
    public static function create(GeneralName $name): self
    {
        return new self($name);
    }
    /**
     * @return self
     */
    public static function fromChosenASN1(TaggedType $el): Target
    {
        return self::create(GeneralName::fromASN1($el));
    }
    public function string(): string
    {
        return $this->name->string();
    }
    public function name(): GeneralName
    {
        return $this->name;
    }
    public function toASN1(): Element
    {
        return ExplicitlyTaggedType::create($this->type, $this->name->toASN1());
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\X509\Certificate\Extension\Target;

use ArrayIterator;
use function count;
use Countable;
use IteratorAggregate;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Constructed\Sequence;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\UnspecifiedType;
/**
 * Implements *Targets* ASN.1 type as a *SEQUENCE OF Target*.
 *
 * @see https://tools.ietf.org/html/rfc5755#section-4.3.2
 */
final class Targets implements Countable, IteratorAggregate
{
    /**
     * Target elements.
     *
     * @var Target[]
     */
    private readonly array $targets;
    private function __construct(Target ...$targets)
    {
        $this->targets = $targets;
    }
    public static function create(Target ...$targets): self
    {
        return new self(...$targets);
    }
    /**
     * Initialize from ASN.1.
     */
    public static function fromASN1(Sequence $seq): self
    {
        $targets = array_map(static fn(UnspecifiedType $el) => Target::fromASN1($el->asTagged()), $seq->elements());
        return self::create(...$targets);
    }
    /**
     * Get all targets.
     *
     * @return Target[]
     */
    public function all(): array
    {
        return $this->targets;
    }
    /**
     * Get all name targets.
     *
     * @return Target[]
     */
    public function nameTargets(): array
    {
        return $this->allOfType(Target::TYPE_NAME);
    }
    /**
     * Get all group targets.
     *
     * @return Target[]
     */
    public function groupTargets(): array
    {
        return $this->allOfType(Target::TYPE_GROUP);
    }
    /**
     * Check whether given target is present.
     */
    public function hasTarget(Target $target): bool
    {
        foreach ($this->allOfType($target->type()) as $t) {
            if ($target->equals($t)) {
                return \true;
            }
        }
        return \false;
    }
    /**
     * Generate ASN.1 structure.
     */
    public function toASN1(): Sequence
    {
        $elements = array_map(static fn(Target $target) => $target->toASN1(), $this->targets);
        return Sequence::create(...$elements);
    }
    /**
     * @see \Countable::count()
     */
    public function count(): int
    {
        return count($this->targets);
    }
    /**
     * Get iterator for targets.
     *
     * @see \IteratorAggregate::getIterator()
     */
    public function getIterator(): ArrayIterator
    {
        return new ArrayIterator($this->targets);
    }
    /**
     * Get all targets of given type.
     *
     * @return Target[]
     */
    private function allOfType(int $type): array
    {
        return array_values(array_filter($this->targets, static fn(Target $target) => $target->type() === $type));
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\X509\Certificate\Extension\Target;

use RuntimeException;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Element;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\TaggedType;
use UnexpectedValueException;
/**
 * Base class for *Target* ASN.1 CHOICE type.
 *
 * @see https://tools.ietf.org/html/rfc5755#section-4.3.2
 */
abstract class Target
{
    public const TYPE_NAME = 0;
    public const TYPE_GROUP = 1;
    public const TYPE_CERT = 2;
    protected function __construct(protected int $type)
    {
    }
    /**
     * Generate ASN.1 element.
     */
    abstract public function toASN1(): Element;
    /**
     * Get string value of the target.
     */
    abstract public function string(): string;
    /**
     * Initialize concrete object from the chosen ASN.1 element.
     */
    abstract public static function fromChosenASN1(TaggedType $el): self;
    /**
     * Parse from ASN.1.
     */
    public static function fromASN1(TaggedType $el): self
    {
        return match ($el->tag()) {
            self::TYPE_NAME => TargetName::fromChosenASN1($el->asExplicit()->asTagged()),
            self::TYPE_GROUP => TargetGroup::fromChosenASN1($el->asExplicit()->asTagged()),
            self::TYPE_CERT => throw new RuntimeException('targetCert not supported.'),
            default => throw new UnexpectedValueException('Target type ' . $el->tag() . ' not supported.'),
        };
    }
    /**
     * Get type tag.
     */
    public function type(): int
    {
        return $this->type;
    }
    /**
     * Check whether target is equal to another.
     */
    public function equals(self $other): bool
    {
        if ($this->type !== $other->type) {
            return \false;
        }
        if ($this->toASN1()->toDER() !== $other->toASN1()->toDER()) {
            return \false;
        }
        return \true;
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\X509\Certificate\Extension\Target;

use _ContaoManager\SpomkyLabs\Pki\ASN1\Element;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Tagged\ExplicitlyTaggedType;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\TaggedType;
use _ContaoManager\SpomkyLabs\Pki\X509\GeneralName\GeneralName;
/**
 * Implements 'targetGroup' CHOICE of the *Target* ASN.1 type.
 *
 * @see https://tools.ietf.org/html/rfc5755#section-4.3.2
 */
final class TargetGroup extends Target
{
    private function __construct(private readonly GeneralName $name)
    {
        parent::__construct(self::TYPE_GROUP);
    }
    public static function create(GeneralName $name): self
    {
        return new self($name);
    }
    /**
     * @return self
     */
    public static function fromChosenASN1(TaggedType $el): Target
    {
        return self::create(GeneralName::fromASN1($el));
    }
    public function string(): string
    {
        return $this->name->string();
    }
    /**
     * Get group name.
     */
    public function name(): GeneralName
    {
        return $this->name;
    }
    public function toASN1(): Element
    {
        return ExplicitlyTaggedType::create($this->type, $this->name->toASN1());
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\X509\Certificate\Extension\PolicyMappings;

use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Constructed\Sequence;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Primitive\ObjectIdentifier;
/**
 * Implements ASN.1 type containing policy mapping values to be used in 'Policy Mappings' certificate extension.
 *
 * @see https://tools.ietf.org/html/rfc5280#section-4.2.1.5
 */
final class PolicyMapping
{
    /**
     * @param string $issuerDomainPolicy OID of the issuer policy
     * @param string $subjectDomainPolicy OID of the subject policy
     */
    private function __construct(private readonly string $issuerDomainPolicy, private readonly string $subjectDomainPolicy)
    {
    }
    public static function create(string $issuerDomainPolicy, string $subjectDomainPolicy): self
    {
        return new self($issuerDomainPolicy, $subjectDomainPolicy);
    }
    /**
     * Initialize from ASN.1.
     */
    public static function fromASN1(Sequence $seq): self
    {
        $issuer_policy = $seq->at(0)->asObjectIdentifier()->oid();
        $subject_policy = $seq->at(1)->asObjectIdentifier()->oid();
        return self::create($issuer_policy, $subject_policy);
    }
    /**
     * Get issuer domain policy.
     *
     * @return string OID in dotted format
     */
    public function issuerDomainPolicy(): string
    {
        return $this->issuerDomainPolicy;
    }
    /**
     * Get subject domain policy.
     *
     * @return string OID in dotted format
     */
    public function subjectDomainPolicy(): string
    {
        return $this->subjectDomainPolicy;
    }
    /**
     * Generate ASN.1 structure.
     */
    public function toASN1(): Sequence
    {
        return Sequence::create(ObjectIdentifier::create($this->issuerDomainPolicy), ObjectIdentifier::create($this->subjectDomainPolicy));
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\X509\Certificate\Extension;

use LogicException;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Element;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Constructed\Sequence;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Tagged\ImplicitlyTaggedType;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\UnspecifiedType;
use _ContaoManager\SpomkyLabs\Pki\X509\Certificate\Extension\NameConstraints\GeneralSubtrees;
/**
 * Implements 'Name Constraints' certificate extension.
 *
 * @see https://tools.ietf.org/html/rfc5280#section-4.2.1.10
 */
final class NameConstraintsExtension extends Extension
{
    private function __construct(bool $critical, private readonly ?GeneralSubtrees $permitted, private readonly ?GeneralSubtrees $excluded)
    {
        parent::__construct(self::OID_NAME_CONSTRAINTS, $critical);
    }
    public static function create(bool $critical, ?GeneralSubtrees $permitted = null, ?GeneralSubtrees $excluded = null): self
    {
        return new self($critical, $permitted, $excluded);
    }
    /**
     * Whether permitted subtrees are present.
     */
    public function hasPermittedSubtrees(): bool
    {
        return isset($this->permitted);
    }
    /**
     * Get permitted subtrees.
     */
    public function permittedSubtrees(): GeneralSubtrees
    {
        if (!$this->hasPermittedSubtrees()) {
            throw new LogicException('No permitted subtrees.');
        }
        return $this->permitted;
    }
    /**
     * Whether excluded subtrees are present.
     */
    public function hasExcludedSubtrees(): bool
    {
        return isset($this->excluded);
    }
    /**
     * Get excluded subtrees.
     */
    public function excludedSubtrees(): GeneralSubtrees
    {
        if (!$this->hasExcludedSubtrees()) {
            throw new LogicException('No excluded subtrees.');
        }
        return $this->excluded;
    }
    protected static function fromDER(string $data, bool $critical): static
    {
        $seq = UnspecifiedType::fromDER($data)->asSequence();
        $permitted = null;
        $excluded = null;
        if ($seq->hasTagged(0)) {
            $permitted = GeneralSubtrees::fromASN1($seq->getTagged(0)->asImplicit(Element::TYPE_SEQUENCE)->asSequence());
        }
        if ($seq->hasTagged(1)) {
            $excluded = GeneralSubtrees::fromASN1($seq->getTagged(1)->asImplicit(Element::TYPE_SEQUENCE)->asSequence());
        }
        return self::create($critical, $permitted, $excluded);
    }
    protected function valueASN1(): Element
    {
        $elements = [];
        if (isset($this->permitted)) {
            $elements[] = ImplicitlyTaggedType::create(0, $this->permitted->toASN1());
        }
        if (isset($this->excluded)) {
            $elements[] = ImplicitlyTaggedType::create(1, $this->excluded->toASN1());
        }
        return Sequence::create(...$elements);
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\X509\Certificate\Extension;

use _ContaoManager\SpomkyLabs\Pki\X509\Certificate\Extension\DistributionPoint\DistributionPoint;
/**
 * Implements 'Freshest CRL' certificate extension.
 *
 * @see https://tools.ietf.org/html/rfc5280#section-4.2.1.15
 */
final class FreshestCRLExtension extends CRLDistributionPointsExtension
{
    public static function create(bool $critical, DistributionPoint ...$distribution_points): self
    {
        return new self(self::OID_FRESHEST_CRL, $critical, ...$distribution_points);
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\X509\Certificate\Extension;

use BadMethodCallException;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Element;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Primitive\NullType;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Primitive\OctetString;
/**
 * Class to park payload of an unknown extension.
 */
final class UnknownExtension extends Extension
{
    private function __construct(string $oid, bool $critical, private readonly Element $element, private readonly string $data)
    {
        parent::__construct($oid, $critical);
    }
    public static function create(string $oid, bool $critical, Element $element): self
    {
        return new self($oid, $critical, $element, $element->toDER());
    }
    /**
     * Create instance from a raw encoded extension value.
     */
    public static function fromRawString(string $oid, bool $critical, string $data): self
    {
        return new self($oid, $critical, NullType::create(), $data);
    }
    /**
     * Get the encoded extension value.
     */
    public function extensionValue(): string
    {
        return $this->data;
    }
    protected function extnValue(): OctetString
    {
        return OctetString::create($this->data);
    }
    protected function valueASN1(): Element
    {
        return $this->element;
    }
    protected static function fromDER(string $data, bool $critical): static
    {
        throw new BadMethodCallException(__FUNCTION__ . ' must be implemented in derived class.');
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\X509\Certificate\Extension;

use _ContaoManager\SpomkyLabs\Pki\ASN1\Element;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\UnspecifiedType;
use _ContaoManager\SpomkyLabs\Pki\X509\GeneralName\GeneralNames;
/**
 * Implements 'Issuer Alternative Name' certificate extension.
 *
 * @see https://tools.ietf.org/html/rfc5280#section-4.2.1.7
 */
final class IssuerAlternativeNameExtension extends Extension
{
    private function __construct(bool $critical, private readonly GeneralNames $names)
    {
        parent::__construct(self::OID_ISSUER_ALT_NAME, $critical);
    }
    public static function create(bool $critical, GeneralNames $names): self
    {
        return new self($critical, $names);
    }
    public function names(): GeneralNames
    {
        return $this->names;
    }
    protected static function fromDER(string $data, bool $critical): static
    {
        return self::create($critical, GeneralNames::fromASN1(UnspecifiedType::fromDER($data)->asSequence()));
    }
    protected function valueASN1(): Element
    {
        return $this->names->toASN1();
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\X509\Certificate\Extension;

use ArrayIterator;
use function count;
use Countable;
use IteratorAggregate;
use LogicException;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Element;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Constructed\Sequence;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\UnspecifiedType;
use _ContaoManager\SpomkyLabs\Pki\X509\Certificate\Extension\CertificatePolicy\PolicyInformation;
use UnexpectedValueException;
/**
 * Implements 'Certificate Policies' certificate extension.
 *
 * @see https://tools.ietf.org/html/rfc5280#section-4.2.1.4
 */
final class CertificatePoliciesExtension extends Extension implements Countable, IteratorAggregate
{
    /**
     * Policy information terms.
     *
     * @var PolicyInformation[]
     */
    protected array $_policies;
    private function __construct(bool $critical, PolicyInformation ...$policies)
    {
        parent::__construct(Extension::OID_CERTIFICATE_POLICIES, $critical);
        $this->_policies = [];
        foreach ($policies as $policy) {
            $this->_policies[$policy->oid()] = $policy;
        }
    }
    public static function create(bool $critical, PolicyInformation ...$policies): self
    {
        return new self($critical, ...$policies);
    }
    /**
     * Check whether policy information by OID is present.
     */
    public function has(string $oid): bool
    {
        return isset($this->_policies[$oid]);
    }
    /**
     * Get policy information by OID.
     */
    public function get(string $oid): PolicyInformation
    {
        if (!$this->has($oid)) {
            throw new LogicException("Not certificate policy by OID {$oid}.");
        }
        return $this->_policies[$oid];
    }
    /**
     * Check whether anyPolicy is present.
     */
    public function hasAnyPolicy(): bool
    {
        return $this->has(PolicyInformation::OID_ANY_POLICY);
    }
    /**
     * Get anyPolicy information.
     */
    public function anyPolicy(): PolicyInformation
    {
        if (!$this->hasAnyPolicy()) {
            throw new LogicException('No anyPolicy.');
        }
        return $this->get(PolicyInformation::OID_ANY_POLICY);
    }
    /**
     * Get the number of policies.
     *
     * @see \Countable::count()
     */
    public function count(): int
    {
        return count($this->_policies);
    }
    /**
     * Get iterator for policy information terms.
     *
     * @see \IteratorAggregate::getIterator()
     */
    public function getIterator(): ArrayIterator
    {
        return new ArrayIterator($this->_policies);
    }
    protected static function fromDER(string $data, bool $critical): static
    {
        $policies = array_map(static fn(UnspecifiedType $el) => PolicyInformation::fromASN1($el->asSequence()), UnspecifiedType::fromDER($data)->asSequence()->elements());
        if (count($policies) === 0) {
            throw new UnexpectedValueException('certificatePolicies must contain at least one PolicyInformation.');
        }
        return self::create($critical, ...$policies);
    }
    protected function valueASN1(): Element
    {
        if (count($this->_policies) === 0) {
            throw new LogicException('No policies.');
        }
        $elements = array_map(static fn(PolicyInformation $pi) => $pi->toASN1(), array_values($this->_policies));
        return Sequence::create(...$elements);
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\X509\Certificate\Extension;

use _ContaoManager\SpomkyLabs\Pki\ASN1\Element;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Primitive\Integer;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\UnspecifiedType;
/**
 * Implements 'Inhibit anyPolicy' extension.
 *
 * @see https://tools.ietf.org/html/rfc5280#section-4.2.1.14
 */
final class InhibitAnyPolicyExtension extends Extension
{
    private function __construct(bool $critical, private readonly int $skipCerts)
    {
        parent::__construct(self::OID_INHIBIT_ANY_POLICY, $critical);
    }
    public static function create(bool $critical, int $skipCerts): self
    {
        return new self($critical, $skipCerts);
    }
    public function skipCerts(): int
    {
        return $this->skipCerts;
    }
    protected static function fromDER(string $data, bool $critical): static
    {
        return self::create($critical, UnspecifiedType::fromDER($data)->asInteger()->intNumber());
    }
    protected function valueASN1(): Element
    {
        return Integer::create($this->skipCerts);
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\X509\Certificate\Extension\DistributionPoint;

use _ContaoManager\SpomkyLabs\Pki\ASN1\Element;
use _ContaoManager\SpomkyLabs\Pki\X501\ASN1\RDN;
/**
 * Implements 'nameRelativeToCRLIssuer' ASN.1 CHOICE type of *DistributionPointName* used by 'CRL Distribution Points'
 * certificate extension.
 *
 * @see https://tools.ietf.org/html/rfc5280#section-4.2.1.13
 */
final class RelativeName extends DistributionPointName
{
    private function __construct(private readonly RDN $rdn)
    {
        parent::__construct(self::TAG_RDN);
    }
    public static function create(RDN $rdn): self
    {
        return new self($rdn);
    }
    public function rdn(): RDN
    {
        return $this->rdn;
    }
    protected function _valueASN1(): Element
    {
        return $this->rdn->toASN1();
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\X509\Certificate\Extension\DistributionPoint;

use LogicException;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Element;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Constructed\Sequence;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Tagged\ExplicitlyTaggedType;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Tagged\ImplicitlyTaggedType;
use _ContaoManager\SpomkyLabs\Pki\X509\GeneralName\GeneralNames;
/**
 * Implements *DistributionPoint* ASN.1 type used by 'CRL Distribution Points' certificate extension.
 *
 * @see https://tools.ietf.org/html/rfc5280#section-4.2.1.13
 */
final class DistributionPoint
{
    private function __construct(private readonly ?DistributionPointName $distributionPoint, private readonly ?ReasonFlags $reasons, private readonly ?GeneralNames $issuer)
    {
    }
    public static function create(?DistributionPointName $distributionPoint = null, ?ReasonFlags $reasons = null, ?GeneralNames $issuer = null): self
    {
        return new self($distributionPoint, $reasons, $issuer);
    }
    /**
     * Initialize from ASN.1.
     */
    public static function fromASN1(Sequence $seq): self
    {
        $name = null;
        $reasons = null;
        $issuer = null;
        if ($seq->hasTagged(0)) {
            // promoted to explicit tagging because underlying type is CHOICE
            $name = DistributionPointName::fromTaggedType($seq->getTagged(0)->asExplicit()->asTagged());
        }
        if ($seq->hasTagged(1)) {
            $reasons = ReasonFlags::fromASN1($seq->getTagged(1)->asImplicit(Element::TYPE_BIT_STRING)->asBitString());
        }
        if ($seq->hasTagged(2)) {
            $issuer = GeneralNames::fromASN1($seq->getTagged(2)->asImplicit(Element::TYPE_SEQUENCE)->asSequence());
        }
        return self::create($name, $reasons, $issuer);
    }
    /**
     * Check whether distribution point name is set.
     */
    public function hasDistributionPointName(): bool
    {
        return isset($this->distributionPoint);
    }
    /**
     * Get distribution point name.
     */
    public function distributionPointName(): DistributionPointName
    {
        if (!$this->hasDistributionPointName()) {
            throw new LogicException('distributionPoint not set.');
        }
        return $this->distributionPoint;
    }
    /**
     * Check whether distribution point name is set, and it's a full name.
     */
    public function hasFullName(): bool
    {
        return $this->distributionPointName()->tag() === DistributionPointName::TAG_FULL_NAME;
    }
    /**
     * Get full distribution point name.
     */
    public function fullName(): FullName
    {
        if (!$this->distributionPoint instanceof FullName || !$this->hasFullName()) {
            throw new LogicException('fullName not set.');
        }
        return $this->distributionPoint;
    }
    /**
     * Check whether distribution point name is set and it's a relative name.
     */
    public function hasRelativeName(): bool
    {
        return $this->distributionPointName()->tag() === DistributionPointName::TAG_RDN;
    }
    /**
     * Get relative distribution point name.
     */
    public function relativeName(): RelativeName
    {
        if (!$this->distributionPoint instanceof RelativeName || !$this->hasRelativeName()) {
            throw new LogicException('nameRelativeToCRLIssuer not set.');
        }
        return $this->distributionPoint;
    }
    /**
     * Check whether reasons flags is set.
     */
    public function hasReasons(): bool
    {
        return isset($this->reasons);
    }
    /**
     * Get revocation reason flags.
     */
    public function reasons(): ReasonFlags
    {
        if (!$this->hasReasons()) {
            throw new LogicException('reasons not set.');
        }
        return $this->reasons;
    }
    /**
     * Check whether cRLIssuer is set.
     */
    public function hasCRLIssuer(): bool
    {
        return isset($this->issuer);
    }
    /**
     * Get CRL issuer.
     */
    public function crlIssuer(): GeneralNames
    {
        if (!$this->hasCRLIssuer()) {
            throw new LogicException('crlIssuer not set.');
        }
        return $this->issuer;
    }
    /**
     * Generate ASN.1 structure.
     */
    public function toASN1(): Sequence
    {
        $elements = [];
        if (isset($this->distributionPoint)) {
            $elements[] = ExplicitlyTaggedType::create(0, $this->distributionPoint->toASN1());
        }
        if (isset($this->reasons)) {
            $elements[] = ImplicitlyTaggedType::create(1, $this->reasons->toASN1());
        }
        if (isset($this->issuer)) {
            $elements[] = ImplicitlyTaggedType::create(2, $this->issuer->toASN1());
        }
        return Sequence::create(...$elements);
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\X509\Certificate\Extension\DistributionPoint;

use _ContaoManager\SpomkyLabs\Pki\ASN1\Element;
use _ContaoManager\SpomkyLabs\Pki\X509\GeneralName\GeneralNames;
use _ContaoManager\SpomkyLabs\Pki\X509\GeneralName\UniformResourceIdentifier;
/**
 * Implements 'fullName' ASN.1 CHOICE type of *DistributionPointName* used by 'CRL Distribution Points' certificate
 * extension.
 *
 * @see https://tools.ietf.org/html/rfc5280#section-4.2.1.13
 */
final class FullName extends DistributionPointName
{
    private function __construct(private readonly GeneralNames $names)
    {
        parent::__construct(self::TAG_FULL_NAME);
    }
    public static function create(GeneralNames $names): self
    {
        return new self($names);
    }
    /**
     * Initialize with a single URI.
     */
    public static function fromURI(string $uri): self
    {
        return self::create(GeneralNames::create(UniformResourceIdentifier::create($uri)));
    }
    public function names(): GeneralNames
    {
        return $this->names;
    }
    protected function _valueASN1(): Element
    {
        return $this->names->toASN1();
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\X509\Certificate\Extension\DistributionPoint;

use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Primitive\BitString;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Util\Flags;
/**
 * Implements *ReasonFlags* ASN.1 type used by 'CRL Distribution Points' certificate extension.
 *
 * @see https://tools.ietf.org/html/rfc5280#section-4.2.1.13
 */
final class ReasonFlags
{
    // const UNUSED = 0x100;
    final public const KEY_COMPROMISE = 0x80;
    final public const CA_COMPROMISE = 0x40;
    final public const AFFILIATION_CHANGED = 0x20;
    final public const SUPERSEDED = 0x10;
    final public const CESSATION_OF_OPERATION = 0x8;
    final public const CERTIFICATE_HOLD = 0x4;
    final public const PRIVILEGE_WITHDRAWN = 0x2;
    final public const AA_COMPROMISE = 0x1;
    private function __construct(private readonly int $flags)
    {
    }
    public static function create(int $flags): self
    {
        return new self($flags);
    }
    /**
     * Initialize from ASN.1.
     */
    public static function fromASN1(BitString $bs): self
    {
        return self::create(Flags::fromBitString($bs, 9)->intNumber());
    }
    /**
     * Check whether keyCompromise flag is set.
     */
    public function isKeyCompromise(): bool
    {
        return $this->flagSet(self::KEY_COMPROMISE);
    }
    /**
     * Check whether cACompromise flag is set.
     */
    public function isCACompromise(): bool
    {
        return $this->flagSet(self::CA_COMPROMISE);
    }
    /**
     * Check whether affiliationChanged flag is set.
     */
    public function isAffiliationChanged(): bool
    {
        return $this->flagSet(self::AFFILIATION_CHANGED);
    }
    /**
     * Check whether superseded flag is set.
     */
    public function isSuperseded(): bool
    {
        return $this->flagSet(self::SUPERSEDED);
    }
    /**
     * Check whether cessationOfOperation flag is set.
     */
    public function isCessationOfOperation(): bool
    {
        return $this->flagSet(self::CESSATION_OF_OPERATION);
    }
    /**
     * Check whether certificateHold flag is set.
     */
    public function isCertificateHold(): bool
    {
        return $this->flagSet(self::CERTIFICATE_HOLD);
    }
    /**
     * Check whether privilegeWithdrawn flag is set.
     */
    public function isPrivilegeWithdrawn(): bool
    {
        return $this->flagSet(self::PRIVILEGE_WITHDRAWN);
    }
    /**
     * Check whether aACompromise flag is set.
     */
    public function isAACompromise(): bool
    {
        return $this->flagSet(self::AA_COMPROMISE);
    }
    /**
     * Generate ASN.1 element.
     */
    public function toASN1(): BitString
    {
        $flags = Flags::create($this->flags, 9);
        return $flags->bitString()->withoutTrailingZeroes();
    }
    /**
     * Check whether given flag is set.
     */
    private function flagSet(int $flag): bool
    {
        return (bool) ($this->flags & $flag);
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\X509\Certificate\Extension\DistributionPoint;

use _ContaoManager\SpomkyLabs\Pki\ASN1\Element;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Tagged\ImplicitlyTaggedType;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\TaggedType;
use _ContaoManager\SpomkyLabs\Pki\X501\ASN1\RDN;
use _ContaoManager\SpomkyLabs\Pki\X509\GeneralName\GeneralNames;
use UnexpectedValueException;
/**
 * Base class for *DistributionPointName* ASN.1 CHOICE type used by 'CRL Distribution Points' certificate extension.
 *
 * @see https://tools.ietf.org/html/rfc5280#section-4.2.1.13
 */
abstract class DistributionPointName
{
    public const TAG_FULL_NAME = 0;
    public const TAG_RDN = 1;
    protected function __construct(protected int $tag)
    {
    }
    /**
     * Initialize from TaggedType.
     */
    public static function fromTaggedType(TaggedType $el): self
    {
        return match ($el->tag()) {
            self::TAG_FULL_NAME => FullName::create(GeneralNames::fromASN1($el->asImplicit(Element::TYPE_SEQUENCE)->asSequence())),
            self::TAG_RDN => RelativeName::create(RDN::fromASN1($el->asImplicit(Element::TYPE_SET)->asSet())),
            default => throw new UnexpectedValueException('DistributionPointName tag ' . $el->tag() . ' not supported.'),
        };
    }
    /**
     * Get type tag.
     */
    public function tag(): int
    {
        return $this->tag;
    }
    /**
     * Generate ASN.1 structure.
     */
    public function toASN1(): ImplicitlyTaggedType
    {
        return ImplicitlyTaggedType::create($this->tag, $this->_valueASN1());
    }
    /**
     * Generate ASN.1 element.
     */
    abstract protected function _valueASN1(): Element;
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\X509\Certificate\Extension\NameConstraints;

use ArrayIterator;
use function count;
use Countable;
use IteratorAggregate;
use LogicException;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Constructed\Sequence;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\UnspecifiedType;
use UnexpectedValueException;
/**
 * Implements *GeneralSubtrees* ASN.1 type used by 'Name Constraints' certificate extension.
 *
 * @see @link https://tools.ietf.org/html/rfc5280#section-4.2.1.10
 */
final class GeneralSubtrees implements Countable, IteratorAggregate
{
    /**
     * Subtrees.
     *
     * @var GeneralSubtree[]
     */
    private readonly array $subtrees;
    private function __construct(GeneralSubtree ...$subtrees)
    {
        $this->subtrees = $subtrees;
    }
    public static function create(GeneralSubtree ...$subtrees): self
    {
        return new self(...$subtrees);
    }
    /**
     * Initialize from ASN.1.
     */
    public static function fromASN1(Sequence $seq): self
    {
        $subtrees = array_map(static fn(UnspecifiedType $el) => GeneralSubtree::fromASN1($el->asSequence()), $seq->elements());
        if (count($subtrees) === 0) {
            throw new UnexpectedValueException('GeneralSubtrees must contain at least one GeneralSubtree.');
        }
        return self::create(...$subtrees);
    }
    /**
     * Get all subtrees.
     *
     * @return GeneralSubtree[]
     */
    public function all(): array
    {
        return $this->subtrees;
    }
    /**
     * Generate ASN.1 structure.
     */
    public function toASN1(): Sequence
    {
        if (count($this->subtrees) === 0) {
            throw new LogicException('No subtrees.');
        }
        $elements = array_map(static fn(GeneralSubtree $gs) => $gs->toASN1(), $this->subtrees);
        return Sequence::create(...$elements);
    }
    /**
     * @see \Countable::count()
     */
    public function count(): int
    {
        return count($this->subtrees);
    }
    /**
     * Get iterator for subtrees.
     *
     * @see \IteratorAggregate::getIterator()
     */
    public function getIterator(): ArrayIterator
    {
        return new ArrayIterator($this->subtrees);
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\X509\Certificate\Extension\NameConstraints;

use function count;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Element;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Constructed\Sequence;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Primitive\Integer;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Tagged\ImplicitlyTaggedType;
use _ContaoManager\SpomkyLabs\Pki\X509\GeneralName\GeneralName;
/**
 * Implements *GeneralSubtree* ASN.1 type used by 'Name Constraints' certificate extension.
 *
 * @see https://tools.ietf.org/html/rfc5280#section-4.2.1.10
 */
final class GeneralSubtree
{
    private function __construct(private readonly GeneralName $base, private readonly int $min, private readonly ?int $max)
    {
    }
    public static function create(GeneralName $base, int $min = 0, ?int $max = null): self
    {
        return new self($base, $min, $max);
    }
    public function getBase(): GeneralName
    {
        return $this->base;
    }
    public function getMin(): int
    {
        return $this->min;
    }
    public function getMax(): ?int
    {
        return $this->max;
    }
    /**
     * Initialize from ASN.1.
     */
    public static function fromASN1(Sequence $seq): self
    {
        $base = GeneralName::fromASN1($seq->at(0)->asTagged());
        $min = 0;
        $max = null;
        // GeneralName is a CHOICE, which may be tagged as otherName [0]
        // or rfc822Name [1]. As minimum and maximum are also implicitly tagged,
        // we have to iterate the remaining elements instead of just checking
        // for tagged types.
        $count = count($seq);
        for ($i = 1; $i < $count; ++$i) {
            $el = $seq->at($i)->expectTagged();
            switch ($el->tag()) {
                case 0:
                    $min = $el->asImplicit(Element::TYPE_INTEGER)->asInteger()->intNumber();
                    break;
                case 1:
                    $max = $el->asImplicit(Element::TYPE_INTEGER)->asInteger()->intNumber();
                    break;
            }
        }
        return self::create($base, $min, $max);
    }
    public function base(): GeneralName
    {
        return $this->base;
    }
    /**
     * Generate ASN.1 structure.
     */
    public function toASN1(): Sequence
    {
        $elements = [$this->base->toASN1()];
        if ($this->min !== 0) {
            $elements[] = ImplicitlyTaggedType::create(0, Integer::create($this->min));
        }
        if (isset($this->max)) {
            $elements[] = ImplicitlyTaggedType::create(1, Integer::create($this->max));
        }
        return Sequence::create(...$elements);
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\X509\Certificate\Extension;

use ArrayIterator;
use function count;
use Countable;
use function in_array;
use IteratorAggregate;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Element;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Constructed\Sequence;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Primitive\ObjectIdentifier;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\UnspecifiedType;
/**
 * Implements 'Extended Key Usage' certificate extension.
 *
 * @see https://tools.ietf.org/html/rfc5280#section-4.2.1.12
 */
final class ExtendedKeyUsageExtension extends Extension implements Countable, IteratorAggregate
{
    final public const OID_SERVER_AUTH = '1.3.6.1.5.5.7.3.1';
    final public const OID_CLIENT_AUTH = '1.3.6.1.5.5.7.3.2';
    final public const OID_CODE_SIGNING = '1.3.6.1.5.5.7.3.3';
    final public const OID_EMAIL_PROTECTION = '1.3.6.1.5.5.7.3.4';
    final public const OID_IPSEC_END_SYSTEM = '1.3.6.1.5.5.7.3.5';
    final public const OID_IPSEC_TUNNEL = '1.3.6.1.5.5.7.3.6';
    final public const OID_IPSEC_USER = '1.3.6.1.5.5.7.3.7';
    final public const OID_TIME_STAMPING = '1.3.6.1.5.5.7.3.8';
    final public const OID_OCSP_SIGNING = '1.3.6.1.5.5.7.3.9';
    final public const OID_DVCS = '1.3.6.1.5.5.7.3.10';
    final public const OID_SBGP_CERT_AA_SERVER_AUTH = '1.3.6.1.5.5.7.3.11';
    final public const OID_SCVP_RESPONDER = '1.3.6.1.5.5.7.3.12';
    final public const OID_EAP_OVER_PPP = '1.3.6.1.5.5.7.3.13';
    final public const OID_EAP_OVER_LAN = '1.3.6.1.5.5.7.3.14';
    final public const OID_SCVP_SERVER = '1.3.6.1.5.5.7.3.15';
    final public const OID_SCVP_CLIENT = '1.3.6.1.5.5.7.3.16';
    final public const OID_IPSEC_IKE = '1.3.6.1.5.5.7.3.17';
    final public const OID_CAPWAP_AC = '1.3.6.1.5.5.7.3.18';
    final public const OID_CAPWAP_WTP = '1.3.6.1.5.5.7.3.19';
    final public const OID_SIP_DOMAIN = '1.3.6.1.5.5.7.3.20';
    final public const OID_SECURE_SHELL_CLIENT = '1.3.6.1.5.5.7.3.21';
    final public const OID_SECURE_SHELL_SERVER = '1.3.6.1.5.5.7.3.22';
    final public const OID_SEND_ROUTER = '1.3.6.1.5.5.7.3.23';
    final public const OID_SEND_PROXY = '1.3.6.1.5.5.7.3.24';
    final public const OID_SEND_OWNER = '1.3.6.1.5.5.7.3.25';
    final public const OID_SEND_PROXIED_OWNER = '1.3.6.1.5.5.7.3.26';
    final public const OID_CMC_CA = '1.3.6.1.5.5.7.3.27';
    final public const OID_CMC_RA = '1.3.6.1.5.5.7.3.28';
    final public const OID_CMC_ARCHIVE = '1.3.6.1.5.5.7.3.29';
    /**
     * Purpose OID's.
     *
     * @var string[]
     */
    private readonly array $purposes;
    private function __construct(bool $critical, string ...$purposes)
    {
        parent::__construct(self::OID_EXT_KEY_USAGE, $critical);
        $this->purposes = $purposes;
    }
    public static function create(bool $critical, string ...$purposes): self
    {
        return new self($critical, ...$purposes);
    }
    /**
     * Whether purposes are present.
     *
     * If multiple purposes are checked, all must be present.
     */
    public function has(string ...$oids): bool
    {
        foreach ($oids as $oid) {
            if (!in_array($oid, $this->purposes, \true)) {
                return \false;
            }
        }
        return \true;
    }
    /**
     * Get key usage purpose OID's.
     *
     * @return string[]
     */
    public function purposes(): array
    {
        return $this->purposes;
    }
    /**
     * Get the number of purposes.
     *
     * @see \Countable::count()
     */
    public function count(): int
    {
        return count($this->purposes);
    }
    /**
     * Get iterator for usage purposes.
     *
     * @see \IteratorAggregate::getIterator()
     */
    public function getIterator(): ArrayIterator
    {
        return new ArrayIterator($this->purposes);
    }
    protected static function fromDER(string $data, bool $critical): static
    {
        $purposes = array_map(static fn(UnspecifiedType $el) => $el->asObjectIdentifier()->oid(), UnspecifiedType::fromDER($data)->asSequence()->elements());
        return self::create($critical, ...$purposes);
    }
    protected function valueASN1(): Element
    {
        $elements = array_map(ObjectIdentifier::create(...), $this->purposes);
        return Sequence::create(...$elements);
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\X509\Certificate\Extension;

use LogicException;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Element;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Constructed\Sequence;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Primitive\Boolean;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Primitive\Integer;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Primitive\ObjectIdentifier;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Tagged\ImplicitlyTaggedType;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\UnspecifiedType;
/**
 * Implements 'AA Controls' certificate extension.
 *
 * @see https://tools.ietf.org/html/rfc5755#section-7.4
 */
final class AAControlsExtension extends Extension
{
    /**
     * @param null|string[] $permittedAttrs
     * @param null|string[] $excludedAttrs
     */
    private function __construct(bool $critical, private readonly ?int $pathLenConstraint, private readonly ?array $permittedAttrs, private readonly ?array $excludedAttrs, private readonly bool $permitUnSpecified)
    {
        parent::__construct(self::OID_AA_CONTROLS, $critical);
    }
    /**
     * @param bool $critical Path length contraint.
     * @param null|string[] $permittedAttrs Permitted attributes.
     * @param null|string[] $excludedAttrs Excluded attributes.
     * @param bool $permitUnSpecified Whether to permit unspecified attributes.
     */
    public static function create(bool $critical, ?int $pathLenConstraint = null, ?array $permittedAttrs = null, ?array $excludedAttrs = null, bool $permitUnSpecified = \true): self
    {
        return new self($critical, $pathLenConstraint, $permittedAttrs, $excludedAttrs, $permitUnSpecified);
    }
    /**
     * Check whether path length constraint is present.
     */
    public function hasPathLen(): bool
    {
        return isset($this->pathLenConstraint);
    }
    /**
     * Get path length constraint.
     */
    public function pathLen(): int
    {
        if (!$this->hasPathLen()) {
            throw new LogicException('pathLen not set.');
        }
        return $this->pathLenConstraint;
    }
    /**
     * Check whether permitted attributes are present.
     */
    public function hasPermittedAttrs(): bool
    {
        return isset($this->permittedAttrs);
    }
    /**
     * Get OID's of permitted attributes.
     *
     * @return string[]
     */
    public function permittedAttrs(): array
    {
        if (!$this->hasPermittedAttrs()) {
            throw new LogicException('permittedAttrs not set.');
        }
        return $this->permittedAttrs;
    }
    /**
     * Check whether excluded attributes are present.
     */
    public function hasExcludedAttrs(): bool
    {
        return isset($this->excludedAttrs);
    }
    /**
     * Get OID's of excluded attributes.
     *
     * @return string[]
     */
    public function excludedAttrs(): array
    {
        if (!$this->hasExcludedAttrs()) {
            throw new LogicException('excludedAttrs not set.');
        }
        return $this->excludedAttrs;
    }
    /**
     * Whether to permit attributes that are not explicitly specified in neither permitted nor excluded list.
     */
    public function permitUnspecified(): bool
    {
        return $this->permitUnSpecified;
    }
    protected static function fromDER(string $data, bool $critical): static
    {
        $seq = UnspecifiedType::fromDER($data)->asSequence();
        $path_len = null;
        $permitted = null;
        $excluded = null;
        $permit_unspecified = \true;
        $idx = 0;
        if ($seq->has($idx, Element::TYPE_INTEGER)) {
            $path_len = $seq->at($idx++)->asInteger()->intNumber();
        }
        if ($seq->hasTagged(0)) {
            $attr_seq = $seq->getTagged(0)->asImplicit(Element::TYPE_SEQUENCE)->asSequence();
            $permitted = array_map(static fn(UnspecifiedType $el) => $el->asObjectIdentifier()->oid(), $attr_seq->elements());
            ++$idx;
        }
        if ($seq->hasTagged(1)) {
            $attr_seq = $seq->getTagged(1)->asImplicit(Element::TYPE_SEQUENCE)->asSequence();
            $excluded = array_map(static fn(UnspecifiedType $el) => $el->asObjectIdentifier()->oid(), $attr_seq->elements());
            ++$idx;
        }
        if ($seq->has($idx, Element::TYPE_BOOLEAN)) {
            $permit_unspecified = $seq->at($idx++)->asBoolean()->value();
        }
        return self::create($critical, $path_len, $permitted, $excluded, $permit_unspecified);
    }
    protected function valueASN1(): Element
    {
        $elements = [];
        if (isset($this->pathLenConstraint)) {
            $elements[] = Integer::create($this->pathLenConstraint);
        }
        if (isset($this->permittedAttrs)) {
            $oids = array_map(ObjectIdentifier::create(...), $this->permittedAttrs);
            $elements[] = ImplicitlyTaggedType::create(0, Sequence::create(...$oids));
        }
        if (isset($this->excludedAttrs)) {
            $oids = array_map(ObjectIdentifier::create(...), $this->excludedAttrs);
            $elements[] = ImplicitlyTaggedType::create(1, Sequence::create(...$oids));
        }
        if ($this->permitUnSpecified !== \true) {
            $elements[] = Boolean::create(\false);
        }
        return Sequence::create(...$elements);
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\X509\Certificate\Extension\CertificatePolicy;

use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Constructed\Sequence;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Primitive\Integer;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\UnspecifiedType;
/**
 * Implements *NoticeReference* ASN.1 type used by 'Certificate Policies' certificate extension.
 *
 * @see https://tools.ietf.org/html/rfc5280#section-4.2.1.4
 */
final class NoticeReference
{
    /**
     * Notification reference numbers.
     *
     * @var int[]
     */
    private readonly array $numbers;
    private function __construct(private readonly DisplayText $organization, int ...$numbers)
    {
        $this->numbers = $numbers;
    }
    public static function create(DisplayText $organization, int ...$numbers): self
    {
        return new self($organization, ...$numbers);
    }
    /**
     * Initialize from ASN.1.
     */
    public static function fromASN1(Sequence $seq): self
    {
        $org = DisplayText::fromASN1($seq->at(0)->asString());
        $numbers = array_map(static fn(UnspecifiedType $el) => $el->asInteger()->intNumber(), $seq->at(1)->asSequence()->elements());
        return self::create($org, ...$numbers);
    }
    /**
     * Get reference organization.
     */
    public function organization(): DisplayText
    {
        return $this->organization;
    }
    /**
     * Get reference numbers.
     *
     * @return int[]
     */
    public function numbers(): array
    {
        return $this->numbers;
    }
    /**
     * Generate ASN.1 structure.
     */
    public function toASN1(): Sequence
    {
        $org = $this->organization->toASN1();
        $nums = array_map(Integer::create(...), $this->numbers);
        return Sequence::create($org, Sequence::create(...$nums));
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\X509\Certificate\Extension\CertificatePolicy;

use _ContaoManager\SpomkyLabs\Pki\ASN1\Element;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Constructed\Sequence;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Primitive\ObjectIdentifier;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\UnspecifiedType;
use UnexpectedValueException;
/**
 * Base class for *PolicyQualifierInfo* ASN.1 types used by 'Certificate Policies' certificate extension.
 *
 * @see https://tools.ietf.org/html/rfc5280#section-4.2.1.4
 */
abstract class PolicyQualifierInfo
{
    /**
     * OID for the CPS Pointer qualifier.
     *
     * @var string
     */
    public const OID_CPS = '1.3.6.1.5.5.7.2.1';
    /**
     * OID for the user notice qualifier.
     *
     * @var string
     */
    public const OID_UNOTICE = '1.3.6.1.5.5.7.2.2';
    protected function __construct(protected string $oid)
    {
    }
    /**
     * Initialize from qualifier ASN.1 element.
     */
    abstract public static function fromQualifierASN1(UnspecifiedType $el): self;
    /**
     * Initialize from ASN.1.
     */
    public static function fromASN1(Sequence $seq): self
    {
        $oid = $seq->at(0)->asObjectIdentifier()->oid();
        return match ($oid) {
            self::OID_CPS => CPSQualifier::fromQualifierASN1($seq->at(1)),
            self::OID_UNOTICE => UserNoticeQualifier::fromQualifierASN1($seq->at(1)),
            default => throw new UnexpectedValueException("Qualifier {$oid} not supported."),
        };
    }
    /**
     * Get qualifier identifier.
     */
    public function oid(): string
    {
        return $this->oid;
    }
    /**
     * Generate ASN.1 structure.
     */
    public function toASN1(): Sequence
    {
        return Sequence::create(ObjectIdentifier::create($this->oid), $this->qualifierASN1());
    }
    /**
     * Generate ASN.1 for the 'qualifier' field.
     */
    abstract protected function qualifierASN1(): Element;
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\X509\Certificate\Extension\CertificatePolicy;

use LogicException;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Element;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Constructed\Sequence;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\UnspecifiedType;
/**
 * Implements *UserNotice* ASN.1 type used by 'Certificate Policies' certificate extension.
 *
 * @see https://tools.ietf.org/html/rfc5280#section-4.2.1.4
 */
final class UserNoticeQualifier extends PolicyQualifierInfo
{
    private function __construct(private readonly ?DisplayText $text, private readonly ?NoticeReference $ref)
    {
        parent::__construct(self::OID_UNOTICE);
    }
    public static function create(?DisplayText $text = null, ?NoticeReference $ref = null): self
    {
        return new self($text, $ref);
    }
    /**
     * @return self
     */
    public static function fromQualifierASN1(UnspecifiedType $el): PolicyQualifierInfo
    {
        $seq = $el->asSequence();
        $ref = null;
        $text = null;
        $idx = 0;
        if ($seq->has($idx, Element::TYPE_SEQUENCE)) {
            $ref = NoticeReference::fromASN1($seq->at($idx++)->asSequence());
        }
        if ($seq->has($idx, Element::TYPE_STRING)) {
            $text = DisplayText::fromASN1($seq->at($idx)->asString());
        }
        return self::create($text, $ref);
    }
    /**
     * Whether explicit text is present.
     */
    public function hasExplicitText(): bool
    {
        return isset($this->text);
    }
    /**
     * Get explicit text.
     */
    public function explicitText(): DisplayText
    {
        if (!$this->hasExplicitText()) {
            throw new LogicException('explicitText not set.');
        }
        return $this->text;
    }
    /**
     * Whether notice reference is present.
     */
    public function hasNoticeRef(): bool
    {
        return isset($this->ref);
    }
    /**
     * Get notice reference.
     */
    public function noticeRef(): NoticeReference
    {
        if (!$this->hasNoticeRef()) {
            throw new LogicException('noticeRef not set.');
        }
        return $this->ref;
    }
    protected function qualifierASN1(): Element
    {
        $elements = [];
        if (isset($this->ref)) {
            $elements[] = $this->ref->toASN1();
        }
        if (isset($this->text)) {
            $elements[] = $this->text->toASN1();
        }
        return Sequence::create(...$elements);
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\X509\Certificate\Extension\CertificatePolicy;

use ArrayIterator;
use function count;
use Countable;
use IteratorAggregate;
use LogicException;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Constructed\Sequence;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Primitive\ObjectIdentifier;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\UnspecifiedType;
/**
 * Implements *PolicyInformation* ASN.1 type used by 'Certificate Policies' certificate extension.
 *
 * @see https://tools.ietf.org/html/rfc5280#section-4.2.1.4
 */
final class PolicyInformation implements Countable, IteratorAggregate
{
    /**
     * Wildcard policy.
     *
     * @var string
     */
    final public const OID_ANY_POLICY = '2.5.29.32.0';
    /**
     * Policy qualifiers.
     *
     * @var PolicyQualifierInfo[]
     */
    private array $qualifiers;
    private function __construct(private readonly string $oid, PolicyQualifierInfo ...$qualifiers)
    {
        $this->qualifiers = [];
        foreach ($qualifiers as $qualifier) {
            $this->qualifiers[$qualifier->oid()] = $qualifier;
        }
    }
    public static function create(string $oid, PolicyQualifierInfo ...$qualifiers): self
    {
        return new self($oid, ...$qualifiers);
    }
    /**
     * Initialize from ASN.1.
     */
    public static function fromASN1(Sequence $seq): self
    {
        $oid = $seq->at(0)->asObjectIdentifier()->oid();
        $qualifiers = [];
        if (count($seq) > 1) {
            $qualifiers = array_map(static fn(UnspecifiedType $el) => PolicyQualifierInfo::fromASN1($el->asSequence()), $seq->at(1)->asSequence()->elements());
        }
        return self::create($oid, ...$qualifiers);
    }
    /**
     * Get policy identifier.
     */
    public function oid(): string
    {
        return $this->oid;
    }
    /**
     * Check whether this policy is anyPolicy.
     */
    public function isAnyPolicy(): bool
    {
        return $this->oid === self::OID_ANY_POLICY;
    }
    /**
     * Get policy qualifiers.
     *
     * @return PolicyQualifierInfo[]
     */
    public function qualifiers(): array
    {
        return array_values($this->qualifiers);
    }
    /**
     * Check whether qualifier is present.
     */
    public function has(string $oid): bool
    {
        return isset($this->qualifiers[$oid]);
    }
    /**
     * Get qualifier by OID.
     */
    public function get(string $oid): PolicyQualifierInfo
    {
        if (!$this->has($oid)) {
            throw new LogicException("No {$oid} qualifier.");
        }
        return $this->qualifiers[$oid];
    }
    /**
     * Check whether CPS qualifier is present.
     */
    public function hasCPSQualifier(): bool
    {
        return $this->has(PolicyQualifierInfo::OID_CPS);
    }
    /**
     * Get CPS qualifier.
     */
    public function CPSQualifier(): CPSQualifier
    {
        if (!$this->hasCPSQualifier()) {
            throw new LogicException('CPS qualifier not set.');
        }
        return $this->get(PolicyQualifierInfo::OID_CPS);
    }
    /**
     * Check whether user notice qualifier is present.
     */
    public function hasUserNoticeQualifier(): bool
    {
        return $this->has(PolicyQualifierInfo::OID_UNOTICE);
    }
    /**
     * Get user notice qualifier.
     */
    public function userNoticeQualifier(): UserNoticeQualifier
    {
        if (!$this->hasUserNoticeQualifier()) {
            throw new LogicException('User notice qualifier not set.');
        }
        return $this->get(PolicyQualifierInfo::OID_UNOTICE);
    }
    /**
     * Get ASN.1 structure.
     */
    public function toASN1(): Sequence
    {
        $elements = [ObjectIdentifier::create($this->oid)];
        if (count($this->qualifiers) !== 0) {
            $qualifiers = array_map(static fn(PolicyQualifierInfo $pqi) => $pqi->toASN1(), array_values($this->qualifiers));
            $elements[] = Sequence::create(...$qualifiers);
        }
        return Sequence::create(...$elements);
    }
    /**
     * Get number of qualifiers.
     *
     * @see \Countable::count()
     */
    public function count(): int
    {
        return count($this->qualifiers);
    }
    /**
     * Get iterator for qualifiers.
     *
     * @see \IteratorAggregate::getIterator()
     */
    public function getIterator(): ArrayIterator
    {
        return new ArrayIterator($this->qualifiers);
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\X509\Certificate\Extension\CertificatePolicy;

use _ContaoManager\SpomkyLabs\Pki\ASN1\Element;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Primitive\BMPString;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Primitive\IA5String;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Primitive\UTF8String;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Primitive\VisibleString;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\StringType;
use Stringable;
use UnexpectedValueException;
/**
 * Implements *DisplayText* ASN.1 CHOICE type used by 'Certificate Policies' certificate extension.
 *
 * @see https://tools.ietf.org/html/rfc5280#section-4.2.1.4
 */
final class DisplayText implements Stringable
{
    private function __construct(private readonly string $text, private readonly int $tag)
    {
    }
    public function __toString(): string
    {
        return $this->string();
    }
    public static function create(string $text, int $tag): self
    {
        return new self($text, $tag);
    }
    /**
     * Initialize from ASN.1.
     */
    public static function fromASN1(StringType $el): self
    {
        return self::create($el->string(), $el->tag());
    }
    /**
     * Initialize from a UTF-8 string.
     */
    public static function fromString(string $str): self
    {
        return self::create($str, Element::TYPE_UTF8_STRING);
    }
    /**
     * Get the text.
     */
    public function string(): string
    {
        return $this->text;
    }
    /**
     * Generate ASN.1 element.
     */
    public function toASN1(): StringType
    {
        return match ($this->tag) {
            Element::TYPE_IA5_STRING => IA5String::create($this->text),
            Element::TYPE_VISIBLE_STRING => VisibleString::create($this->text),
            Element::TYPE_BMP_STRING => BMPString::create($this->text),
            Element::TYPE_UTF8_STRING => UTF8String::create($this->text),
            default => throw new UnexpectedValueException('Type ' . Element::tagToName($this->tag) . ' not supported.'),
        };
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\X509\Certificate\Extension\CertificatePolicy;

use _ContaoManager\SpomkyLabs\Pki\ASN1\Element;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Primitive\IA5String;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\UnspecifiedType;
/**
 * Implements *CPSuri* ASN.1 type used by 'Certificate Policies' certificate extension.
 *
 * @see https://tools.ietf.org/html/rfc5280#section-4.2.1.4
 */
final class CPSQualifier extends PolicyQualifierInfo
{
    private function __construct(private readonly string $uri)
    {
        parent::__construct(self::OID_CPS);
    }
    public static function create(string $uri): self
    {
        return new self($uri);
    }
    /**
     * @return self
     */
    public static function fromQualifierASN1(UnspecifiedType $el): PolicyQualifierInfo
    {
        return self::create($el->asString()->string());
    }
    public function uri(): string
    {
        return $this->uri;
    }
    protected function qualifierASN1(): Element
    {
        return IA5String::create($this->uri);
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\X509\Certificate\Extension;

use ArrayIterator;
use function count;
use Countable;
use IteratorAggregate;
use LogicException;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Element;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Constructed\Sequence;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\UnspecifiedType;
use _ContaoManager\SpomkyLabs\Pki\X509\Certificate\Extension\CertificatePolicy\PolicyInformation;
use _ContaoManager\SpomkyLabs\Pki\X509\Certificate\Extension\PolicyMappings\PolicyMapping;
use UnexpectedValueException;
/**
 * Implements 'Policy Mappings' certificate extension.
 *
 * @see https://tools.ietf.org/html/rfc5280#section-4.2.1.5
 */
final class PolicyMappingsExtension extends Extension implements Countable, IteratorAggregate
{
    /**
     * Policy mappings.
     *
     * @var PolicyMapping[]
     */
    private readonly array $mappings;
    /**
     * @param PolicyMapping ...$mappings One or more PolicyMapping objects
     */
    private function __construct(bool $critical, PolicyMapping ...$mappings)
    {
        parent::__construct(self::OID_POLICY_MAPPINGS, $critical);
        $this->mappings = $mappings;
    }
    public static function create(bool $critical, PolicyMapping ...$mappings): self
    {
        return new self($critical, ...$mappings);
    }
    /**
     * Get all mappings.
     *
     * @return PolicyMapping[]
     */
    public function mappings(): array
    {
        return $this->mappings;
    }
    /**
     * Get mappings flattened into a single array of arrays of subject domains keyed by issuer domain.
     *
     * Eg. if policy mappings contains multiple mappings with the same issuer domain policy, their corresponding subject
     * domain policies are placed under the same key.
     *
     * @return (string[])[]
     */
    public function flattenedMappings(): array
    {
        $mappings = [];
        foreach ($this->mappings as $mapping) {
            $idp = $mapping->issuerDomainPolicy();
            if (!isset($mappings[$idp])) {
                $mappings[$idp] = [];
            }
            array_push($mappings[$idp], $mapping->subjectDomainPolicy());
        }
        return $mappings;
    }
    /**
     * Get all subject domain policy OIDs that are mapped to given issuer domain policy OID.
     *
     * @param string $oid Issuer domain policy
     *
     * @return string[] List of OIDs in dotted format
     */
    public function issuerMappings(string $oid): array
    {
        $oids = [];
        foreach ($this->mappings as $mapping) {
            if ($mapping->issuerDomainPolicy() === $oid) {
                $oids[] = $mapping->subjectDomainPolicy();
            }
        }
        return $oids;
    }
    /**
     * Get all mapped issuer domain policy OIDs.
     *
     * @return string[]
     */
    public function issuerDomainPolicies(): array
    {
        $idps = array_map(static fn(PolicyMapping $mapping) => $mapping->issuerDomainPolicy(), $this->mappings);
        return array_values(array_unique($idps));
    }
    /**
     * Check whether policy mappings have anyPolicy mapped.
     *
     * RFC 5280 section 4.2.1.5 states that "Policies MUST NOT be mapped either to or from the special value anyPolicy".
     */
    public function hasAnyPolicyMapping(): bool
    {
        foreach ($this->mappings as $mapping) {
            if ($mapping->issuerDomainPolicy() === PolicyInformation::OID_ANY_POLICY) {
                return \true;
            }
            if ($mapping->subjectDomainPolicy() === PolicyInformation::OID_ANY_POLICY) {
                return \true;
            }
        }
        return \false;
    }
    /**
     * Get the number of mappings.
     *
     * @see \Countable::count()
     */
    public function count(): int
    {
        return count($this->mappings);
    }
    /**
     * Get iterator for policy mappings.
     *
     * @see \IteratorAggregate::getIterator()
     */
    public function getIterator(): ArrayIterator
    {
        return new ArrayIterator($this->mappings);
    }
    protected static function fromDER(string $data, bool $critical): static
    {
        $mappings = array_map(static fn(UnspecifiedType $el) => PolicyMapping::fromASN1($el->asSequence()), UnspecifiedType::fromDER($data)->asSequence()->elements());
        if (count($mappings) === 0) {
            throw new UnexpectedValueException('PolicyMappings must have at least one mapping.');
        }
        return self::create($critical, ...$mappings);
    }
    protected function valueASN1(): Element
    {
        if (count($this->mappings) === 0) {
            throw new LogicException('No mappings.');
        }
        $elements = array_map(static fn(PolicyMapping $mapping) => $mapping->toASN1(), $this->mappings);
        return Sequence::create(...$elements);
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\X509\Certificate\Extension;

use function array_key_exists;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Element;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Constructed\Sequence;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Primitive\Boolean;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Primitive\ObjectIdentifier;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Primitive\OctetString;
use Stringable;
/**
 * Base class for certificate extensions.
 *
 * @see https://tools.ietf.org/html/rfc5280#section-4.2
 * @see https://tools.ietf.org/html/rfc5280#section-4.1
 */
abstract class Extension implements Stringable
{
    // OID's from standard certificate extensions
    public const OID_OBSOLETE_AUTHORITY_KEY_IDENTIFIER = '2.5.29.1';
    public const OID_OBSOLETE_KEY_ATTRIBUTES = '2.5.29.2';
    public const OID_OBSOLETE_CERTIFICATE_POLICIES = '2.5.29.3';
    public const OID_OBSOLETE_KEY_USAGE_RESTRICTION = '2.5.29.4';
    public const OID_OBSOLETE_POLICY_MAPPING = '2.5.29.5';
    public const OID_OBSOLETE_SUBTREES_CONSTRAINT = '2.5.29.6';
    public const OID_OBSOLETE_SUBJECT_ALT_NAME = '2.5.29.7';
    public const OID_OBSOLETE_ISSUER_ALT_NAME = '2.5.29.8';
    public const OID_SUBJECT_DIRECTORY_ATTRIBUTES = '2.5.29.9';
    public const OID_OBSOLETE_BASIC_CONSTRAINTS = '2.5.29.10';
    public const OID_SUBJECT_KEY_IDENTIFIER = '2.5.29.14';
    public const OID_KEY_USAGE = '2.5.29.15';
    public const OID_PRIVATE_KEY_USAGE_PERIOD = '2.5.29.16';
    public const OID_SUBJECT_ALT_NAME = '2.5.29.17';
    public const OID_ISSUER_ALT_NAME = '2.5.29.18';
    public const OID_BASIC_CONSTRAINTS = '2.5.29.19';
    public const OID_CRL_NUMBER = '2.5.29.20';
    public const OID_REASON_CODE = '2.5.29.21';
    public const OID_OBSOLETE_EXPIRATION_DATE = '2.5.29.22';
    public const OID_INSTRUCTION_CODE = '2.5.29.23';
    public const OID_INVALIDITY_DATE = '2.5.29.24';
    public const OID_OBSOLETE_CRL_DISTRIBUTION_POINTS = '2.5.29.25';
    public const OID_OBSOLETE_ISSUING_DISTRIBUTION_POINT = '2.5.29.26';
    public const OID_DELTA_CRL_INDICATOR = '2.5.29.27';
    public const OID_ISSUING_DISTRIBUTION_POINT = '2.5.29.28';
    public const OID_CERTIFICATE_ISSUER = '2.5.29.29';
    public const OID_NAME_CONSTRAINTS = '2.5.29.30';
    public const OID_CRL_DISTRIBUTION_POINTS = '2.5.29.31';
    public const OID_CERTIFICATE_POLICIES = '2.5.29.32';
    public const OID_POLICY_MAPPINGS = '2.5.29.33';
    public const OID_OBSOLETE_POLICY_CONSTRAINTS = '2.5.29.34';
    public const OID_AUTHORITY_KEY_IDENTIFIER = '2.5.29.35';
    public const OID_POLICY_CONSTRAINTS = '2.5.29.36';
    public const OID_EXT_KEY_USAGE = '2.5.29.37';
    public const OID_AUTHORITY_ATTRIBUTE_IDENTIFIER = '2.5.29.38';
    public const OID_ROLE_SPEC_CERT_IDENTIFIER = '2.5.29.39';
    public const OID_CRL_STREAM_IDENTIFIER = '2.5.29.40';
    public const OID_BASIC_ATT_CONSTRAINTS = '2.5.29.41';
    public const OID_DELEGATED_NAME_CONSTRAINTS = '2.5.29.42';
    public const OID_TIME_SPECIFICATION = '2.5.29.43';
    public const OID_CRL_SCOPE = '2.5.29.44';
    public const OID_STATUS_REFERRALS = '2.5.29.45';
    public const OID_FRESHEST_CRL = '2.5.29.46';
    public const OID_ORDERED_LIST = '2.5.29.47';
    public const OID_ATTRIBUTE_DESCRIPTOR = '2.5.29.48';
    public const OID_USER_NOTICE = '2.5.29.49';
    public const OID_SOA_IDENTIFIER = '2.5.29.50';
    public const OID_BASE_UPDATE_TIME = '2.5.29.51';
    public const OID_ACCEPTABLE_CERT_POLICIES = '2.5.29.52';
    public const OID_DELTA_INFO = '2.5.29.53';
    public const OID_INHIBIT_ANY_POLICY = '2.5.29.54';
    public const OID_TARGET_INFORMATION = '2.5.29.55';
    public const OID_NO_REV_AVAIL = '2.5.29.56';
    public const OID_ACCEPTABLE_PRIVILEGE_POLICIES = '2.5.29.57';
    public const OID_TO_BE_REVOKED = '2.5.29.58';
    public const OID_REVOKED_GROUPS = '2.5.29.59';
    public const OID_EXPIRED_CERTS_ON_CRL = '2.5.29.60';
    public const OID_INDIRECT_ISSUER = '2.5.29.61';
    public const OID_NO_ASSERTION = '2.5.29.62';
    public const OID_AA_ISSUING_DISTRIBUTION_POINT = '2.5.29.63';
    public const OID_ISSUED_ON_BEHALF_OF = '2.5.29.64';
    public const OID_SINGLE_USE = '2.5.29.65';
    public const OID_GROUP_AC = '2.5.29.66';
    public const OID_ALLOWED_ATT_ASS = '2.5.29.67';
    public const OID_ATTRIBUTE_MAPPINGS = '2.5.29.68';
    public const OID_HOLDER_NAME_CONSTRAINTS = '2.5.29.69';
    // OID's from private certificate extensions arc
    public const OID_AUTHORITY_INFORMATION_ACCESS = '1.3.6.1.5.5.7.1.1';
    public const OID_AA_CONTROLS = '1.3.6.1.5.5.7.1.6';
    public const OID_SUBJECT_INFORMATION_ACCESS = '1.3.6.1.5.5.7.1.11';
    public const OID_LOGOTYPE = '1.3.6.1.5.5.7.1.12';
    /**
     * Mapping from extension ID to implementation class name.
     *
     * @internal
     *
     * @var array<string, string>
     */
    private const MAP_OID_TO_CLASS = [self::OID_AUTHORITY_KEY_IDENTIFIER => AuthorityKeyIdentifierExtension::class, self::OID_SUBJECT_KEY_IDENTIFIER => SubjectKeyIdentifierExtension::class, self::OID_KEY_USAGE => KeyUsageExtension::class, self::OID_CERTIFICATE_POLICIES => CertificatePoliciesExtension::class, self::OID_POLICY_MAPPINGS => PolicyMappingsExtension::class, self::OID_SUBJECT_ALT_NAME => SubjectAlternativeNameExtension::class, self::OID_ISSUER_ALT_NAME => IssuerAlternativeNameExtension::class, self::OID_SUBJECT_DIRECTORY_ATTRIBUTES => SubjectDirectoryAttributesExtension::class, self::OID_BASIC_CONSTRAINTS => BasicConstraintsExtension::class, self::OID_NAME_CONSTRAINTS => NameConstraintsExtension::class, self::OID_POLICY_CONSTRAINTS => PolicyConstraintsExtension::class, self::OID_EXT_KEY_USAGE => ExtendedKeyUsageExtension::class, self::OID_CRL_DISTRIBUTION_POINTS => CRLDistributionPointsExtension::class, self::OID_INHIBIT_ANY_POLICY => InhibitAnyPolicyExtension::class, self::OID_FRESHEST_CRL => FreshestCRLExtension::class, self::OID_NO_REV_AVAIL => NoRevocationAvailableExtension::class, self::OID_TARGET_INFORMATION => TargetInformationExtension::class, self::OID_AUTHORITY_INFORMATION_ACCESS => AuthorityInformationAccessExtension::class, self::OID_AA_CONTROLS => AAControlsExtension::class, self::OID_SUBJECT_INFORMATION_ACCESS => SubjectInformationAccessExtension::class];
    /**
     * Mapping from extensions ID to short name.
     *
     * @internal
     *
     * @var array<string, string>
     */
    private const MAP_OID_TO_NAME = [self::OID_AUTHORITY_KEY_IDENTIFIER => 'authorityKeyIdentifier', self::OID_SUBJECT_KEY_IDENTIFIER => 'subjectKeyIdentifier', self::OID_KEY_USAGE => 'keyUsage', self::OID_PRIVATE_KEY_USAGE_PERIOD => 'privateKeyUsagePeriod', self::OID_CERTIFICATE_POLICIES => 'certificatePolicies', self::OID_POLICY_MAPPINGS => 'policyMappings', self::OID_SUBJECT_ALT_NAME => 'subjectAltName', self::OID_ISSUER_ALT_NAME => 'issuerAltName', self::OID_SUBJECT_DIRECTORY_ATTRIBUTES => 'subjectDirectoryAttributes', self::OID_BASIC_CONSTRAINTS => 'basicConstraints', self::OID_NAME_CONSTRAINTS => 'nameConstraints', self::OID_POLICY_CONSTRAINTS => 'policyConstraints', self::OID_EXT_KEY_USAGE => 'extKeyUsage', self::OID_CRL_DISTRIBUTION_POINTS => 'cRLDistributionPoints', self::OID_INHIBIT_ANY_POLICY => 'inhibitAnyPolicy', self::OID_FRESHEST_CRL => 'freshestCRL', self::OID_NO_REV_AVAIL => 'noRevAvail', self::OID_TARGET_INFORMATION => 'targetInformation', self::OID_AUTHORITY_INFORMATION_ACCESS => 'authorityInfoAccess', self::OID_AA_CONTROLS => 'aaControls', self::OID_SUBJECT_INFORMATION_ACCESS => 'subjectInfoAccess', self::OID_LOGOTYPE => 'logotype'];
    /**
     * @param string $oid Extension OID
     * @param bool $critical Whether extension is critical
     */
    protected function __construct(private readonly string $oid, private readonly bool $critical)
    {
    }
    public function __toString(): string
    {
        return $this->extensionName();
    }
    /**
     * Initialize from ASN.1.
     */
    public static function fromASN1(Sequence $seq): self
    {
        $idx = 0;
        $extnID = $seq->at($idx++)->asObjectIdentifier()->oid();
        $critical = \false;
        if ($seq->has($idx, Element::TYPE_BOOLEAN)) {
            $critical = $seq->at($idx++)->asBoolean()->value();
        }
        $data = $seq->at($idx)->asOctetString()->string();
        if (array_key_exists($extnID, self::MAP_OID_TO_CLASS)) {
            $cls = self::MAP_OID_TO_CLASS[$extnID];
            return $cls::fromDER($data, $critical);
        }
        return UnknownExtension::fromRawString($extnID, $critical, $data);
    }
    /**
     * Get extension OID.
     */
    public function oid(): string
    {
        return $this->oid;
    }
    /**
     * Check whether extension is critical.
     */
    public function isCritical(): bool
    {
        return $this->critical;
    }
    /**
     * Generate ASN.1 structure.
     */
    public function toASN1(): Sequence
    {
        $elements = [ObjectIdentifier::create($this->oid)];
        if ($this->critical) {
            $elements[] = Boolean::create(\true);
        }
        $elements[] = $this->extnValue();
        return Sequence::create(...$elements);
    }
    /**
     * Get short name of the extension.
     */
    public function extensionName(): string
    {
        if (array_key_exists($this->oid, self::MAP_OID_TO_NAME)) {
            return self::MAP_OID_TO_NAME[$this->oid];
        }
        return $this->oid();
    }
    /**
     * Get ASN.1 structure of the extension value.
     */
    abstract protected function valueASN1(): Element;
    /**
     * Parse extension value from DER.
     *
     * @param string $data DER data
     * @param bool $critical Whether extension is critical
     */
    abstract protected static function fromDER(string $data, bool $critical): static;
    /**
     * Get the extnValue element.
     */
    protected function extnValue(): OctetString
    {
        return OctetString::create($this->valueASN1()->toDER());
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\X509\Certificate\Extension;

use LogicException;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Element;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Constructed\Sequence;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Primitive\Integer;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Primitive\OctetString;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Tagged\ImplicitlyTaggedType;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\UnspecifiedType;
use _ContaoManager\SpomkyLabs\Pki\CryptoTypes\Asymmetric\PublicKeyInfo;
use _ContaoManager\SpomkyLabs\Pki\X509\GeneralName\GeneralNames;
use UnexpectedValueException;
/**
 * Implements 'Authority Key Identifier' certificate extension.
 *
 * @see https://tools.ietf.org/html/rfc5280#section-4.2.1.1
 */
final class AuthorityKeyIdentifierExtension extends Extension
{
    private function __construct(bool $critical, private readonly ?string $keyIdentifier, private readonly ?GeneralNames $authorityCertIssuer, private readonly null|string $authorityCertSerialNumber)
    {
        parent::__construct(self::OID_AUTHORITY_KEY_IDENTIFIER, $critical);
    }
    /**
     * @param bool $critical Conforming CA's must mark as non-critical (false)
     * @param null|string $keyIdentifier Key identifier
     * @param null|GeneralNames $authorityCertIssuer Issuer name
     */
    public static function create(bool $critical, ?string $keyIdentifier, ?GeneralNames $authorityCertIssuer = null, null|string $authorityCertSerialNumber = null): self
    {
        return new self($critical, $keyIdentifier, $authorityCertIssuer, $authorityCertSerialNumber);
    }
    /**
     * Create from public key info.
     */
    public static function fromPublicKeyInfo(PublicKeyInfo $pki): self
    {
        return self::create(\false, $pki->keyIdentifier());
    }
    /**
     * Whether key identifier is present.
     */
    public function hasKeyIdentifier(): bool
    {
        return isset($this->keyIdentifier);
    }
    /**
     * Get key identifier.
     */
    public function keyIdentifier(): string
    {
        if (!$this->hasKeyIdentifier()) {
            throw new LogicException('keyIdentifier not set.');
        }
        return $this->keyIdentifier;
    }
    /**
     * Whether issuer is present.
     */
    public function hasIssuer(): bool
    {
        return isset($this->authorityCertIssuer);
    }
    public function issuer(): GeneralNames
    {
        if (!$this->hasIssuer()) {
            throw new LogicException('authorityCertIssuer not set.');
        }
        return $this->authorityCertIssuer;
    }
    /**
     * Whether serial is present.
     */
    public function hasSerial(): bool
    {
        return isset($this->authorityCertSerialNumber);
    }
    /**
     * Get serial number.
     *
     * @return string Base 10 integer string
     */
    public function serial(): string
    {
        if (!$this->hasSerial()) {
            throw new LogicException('authorityCertSerialNumber not set.');
        }
        return $this->authorityCertSerialNumber;
    }
    protected static function fromDER(string $data, bool $critical): static
    {
        $seq = UnspecifiedType::fromDER($data)->asSequence();
        $keyIdentifier = null;
        $issuer = null;
        $serial = null;
        if ($seq->hasTagged(0)) {
            $keyIdentifier = $seq->getTagged(0)->asImplicit(Element::TYPE_OCTET_STRING)->asOctetString()->string();
        }
        if ($seq->hasTagged(1) || $seq->hasTagged(2)) {
            if (!$seq->hasTagged(1) || !$seq->hasTagged(2)) {
                throw new UnexpectedValueException('AuthorityKeyIdentifier must have both' . ' authorityCertIssuer and authorityCertSerialNumber' . ' present or both absent.');
            }
            $issuer = GeneralNames::fromASN1($seq->getTagged(1)->asImplicit(Element::TYPE_SEQUENCE)->asSequence());
            $serial = $seq->getTagged(2)->asImplicit(Element::TYPE_INTEGER)->asInteger()->number();
        }
        return self::create($critical, $keyIdentifier, $issuer, $serial);
    }
    protected function valueASN1(): Element
    {
        $elements = [];
        if (isset($this->keyIdentifier)) {
            $elements[] = ImplicitlyTaggedType::create(0, OctetString::create($this->keyIdentifier));
        }
        // if either issuer or serial is set, both must be set
        if (isset($this->authorityCertIssuer) || isset($this->authorityCertSerialNumber)) {
            if (!isset($this->authorityCertIssuer, $this->authorityCertSerialNumber)) {
                throw new LogicException('AuthorityKeyIdentifier must have both' . ' authorityCertIssuer and authorityCertSerialNumber' . ' present or both absent.');
            }
            $elements[] = ImplicitlyTaggedType::create(1, $this->authorityCertIssuer->toASN1());
            $elements[] = ImplicitlyTaggedType::create(2, Integer::create($this->authorityCertSerialNumber));
        }
        return Sequence::create(...$elements);
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\X509\Certificate\Extension;

use _ContaoManager\SpomkyLabs\Pki\ASN1\Element;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\UnspecifiedType;
use _ContaoManager\SpomkyLabs\Pki\X509\GeneralName\GeneralNames;
/**
 * Implements 'Subject Alternative Name' certificate extension.
 *
 * @see https://tools.ietf.org/html/rfc5280#section-4.2.1.6
 */
final class SubjectAlternativeNameExtension extends Extension
{
    private function __construct(bool $critical, private readonly GeneralNames $names)
    {
        parent::__construct(self::OID_SUBJECT_ALT_NAME, $critical);
    }
    public static function create(bool $critical, GeneralNames $names): self
    {
        return new self($critical, $names);
    }
    public function names(): GeneralNames
    {
        return $this->names;
    }
    protected static function fromDER(string $data, bool $critical): static
    {
        return self::create($critical, GeneralNames::fromASN1(UnspecifiedType::fromDER($data)->asSequence()));
    }
    protected function valueASN1(): Element
    {
        return $this->names->toASN1();
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\X509\Certificate\Extension;

use LogicException;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Element;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Constructed\Sequence;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Primitive\Boolean;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Primitive\Integer;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\UnspecifiedType;
/**
 * Implements 'Basic Constraints' certificate extension.
 *
 * @see https://tools.ietf.org/html/rfc5280#section-4.2.1.9
 */
final class BasicConstraintsExtension extends Extension
{
    /**
     * @param bool $ca Whether certificate is a CA.
     * @param int|null $pathLen Maximum certification path length.
     */
    private function __construct(bool $critical, private readonly bool $ca, private readonly ?int $pathLen)
    {
        parent::__construct(self::OID_BASIC_CONSTRAINTS, $critical);
    }
    public static function create(bool $critical, bool $ca, ?int $pathLen = null): self
    {
        return new self($critical, $ca, $pathLen);
    }
    /**
     * Whether certificate is a CA.
     */
    public function isCA(): bool
    {
        return $this->ca;
    }
    /**
     * Whether path length is present.
     */
    public function hasPathLen(): bool
    {
        return isset($this->pathLen);
    }
    /**
     * Get path length.
     */
    public function pathLen(): int
    {
        if (!$this->hasPathLen()) {
            throw new LogicException('pathLenConstraint not set.');
        }
        return $this->pathLen;
    }
    protected static function fromDER(string $data, bool $critical): static
    {
        $seq = UnspecifiedType::fromDER($data)->asSequence();
        $ca = \false;
        $path_len = null;
        $idx = 0;
        if ($seq->has($idx, Element::TYPE_BOOLEAN)) {
            $ca = $seq->at($idx++)->asBoolean()->value();
        }
        if ($seq->has($idx, Element::TYPE_INTEGER)) {
            $path_len = $seq->at($idx)->asInteger()->intNumber();
        }
        return self::create($critical, $ca, $path_len);
    }
    protected function valueASN1(): Element
    {
        $elements = [];
        if ($this->ca) {
            $elements[] = Boolean::create(\true);
        }
        if (isset($this->pathLen)) {
            $elements[] = Integer::create($this->pathLen);
        }
        return Sequence::create(...$elements);
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\X509\Certificate\Extension;

use _ContaoManager\SpomkyLabs\Pki\ASN1\Element;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Primitive\OctetString;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\UnspecifiedType;
/**
 * Implements 'Subject Key Identifier' certificate extension.
 *
 * @see https://tools.ietf.org/html/rfc5280#section-4.2.1.2
 */
final class SubjectKeyIdentifierExtension extends Extension
{
    private function __construct(bool $critical, private readonly string $keyIdentifier)
    {
        parent::__construct(self::OID_SUBJECT_KEY_IDENTIFIER, $critical);
    }
    public static function create(bool $critical, string $keyIdentifier): self
    {
        return new self($critical, $keyIdentifier);
    }
    /**
     * Get key identifier.
     */
    public function keyIdentifier(): string
    {
        return $this->keyIdentifier;
    }
    protected static function fromDER(string $data, bool $critical): static
    {
        return self::create($critical, UnspecifiedType::fromDER($data)->asOctetString()->string());
    }
    protected function valueASN1(): Element
    {
        return OctetString::create($this->keyIdentifier);
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\X509\Certificate;

use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Constructed\Sequence;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\UnspecifiedType;
use _ContaoManager\SpomkyLabs\Pki\CryptoBridge\Crypto;
use _ContaoManager\SpomkyLabs\Pki\CryptoEncoding\PEM;
use _ContaoManager\SpomkyLabs\Pki\CryptoTypes\AlgorithmIdentifier\AlgorithmIdentifier;
use _ContaoManager\SpomkyLabs\Pki\CryptoTypes\AlgorithmIdentifier\Feature\SignatureAlgorithmIdentifier;
use _ContaoManager\SpomkyLabs\Pki\CryptoTypes\Asymmetric\PublicKeyInfo;
use _ContaoManager\SpomkyLabs\Pki\CryptoTypes\Signature\Signature;
use Stringable;
use UnexpectedValueException;
/**
 * Implements *Certificate* ASN.1 type.
 *
 * @see https://tools.ietf.org/html/rfc5280#section-4.1
 */
final class Certificate implements Stringable
{
    /**
     * @param TBSCertificate $tbsCertificate "To be signed" certificate information.
     * @param SignatureAlgorithmIdentifier $signatureAlgorithm Signature algorithm.
     * @param Signature $signatureValue Signature value.
     */
    private function __construct(private readonly TBSCertificate $tbsCertificate, private readonly SignatureAlgorithmIdentifier $signatureAlgorithm, private readonly Signature $signatureValue)
    {
    }
    /**
     * Get certificate as a PEM formatted string.
     */
    public function __toString(): string
    {
        return $this->toPEM()->string();
    }
    public static function create(TBSCertificate $tbsCertificate, SignatureAlgorithmIdentifier $signatureAlgorithm, Signature $signatureValue): self
    {
        return new self($tbsCertificate, $signatureAlgorithm, $signatureValue);
    }
    /**
     * Initialize from ASN.1.
     */
    public static function fromASN1(Sequence $seq): self
    {
        $tbsCert = TBSCertificate::fromASN1($seq->at(0)->asSequence());
        $algo = AlgorithmIdentifier::fromASN1($seq->at(1)->asSequence());
        if (!$algo instanceof SignatureAlgorithmIdentifier) {
            throw new UnexpectedValueException('Unsupported signature algorithm ' . $algo->oid() . '.');
        }
        $signature = Signature::fromSignatureData($seq->at(2)->asBitString()->string(), $algo);
        return self::create($tbsCert, $algo, $signature);
    }
    /**
     * Initialize from DER.
     */
    public static function fromDER(string $data): self
    {
        return self::fromASN1(UnspecifiedType::fromDER($data)->asSequence());
    }
    /**
     * Initialize from PEM.
     */
    public static function fromPEM(PEM $pem): self
    {
        if ($pem->type() !== PEM::TYPE_CERTIFICATE) {
            throw new UnexpectedValueException('Invalid PEM type.');
        }
        return self::fromDER($pem->data());
    }
    /**
     * Get certificate information.
     */
    public function tbsCertificate(): TBSCertificate
    {
        return $this->tbsCertificate;
    }
    /**
     * Get signature algorithm.
     */
    public function signatureAlgorithm(): SignatureAlgorithmIdentifier
    {
        return $this->signatureAlgorithm;
    }
    /**
     * Get signature value.
     */
    public function signatureValue(): Signature
    {
        return $this->signatureValue;
    }
    /**
     * Check whether certificate is self-issued.
     */
    public function isSelfIssued(): bool
    {
        return $this->tbsCertificate->subject()->equals($this->tbsCertificate->issuer());
    }
    /**
     * Check whether certificate is semantically equal to another.
     *
     * @param Certificate $cert Certificate to compare to
     */
    public function equals(self $cert): bool
    {
        return $this->_hasEqualSerialNumber($cert) && $this->_hasEqualPublicKey($cert) && $this->_hasEqualSubject($cert);
    }
    /**
     * Generate ASN.1 structure.
     */
    public function toASN1(): Sequence
    {
        return Sequence::create($this->tbsCertificate->toASN1(), $this->signatureAlgorithm->toASN1(), $this->signatureValue->bitString());
    }
    /**
     * Get certificate as a DER.
     */
    public function toDER(): string
    {
        return $this->toASN1()->toDER();
    }
    /**
     * Get certificate as a PEM.
     */
    public function toPEM(): PEM
    {
        return PEM::create(PEM::TYPE_CERTIFICATE, $this->toDER());
    }
    /**
     * Verify certificate signature.
     *
     * @param PublicKeyInfo $pubkey_info Issuer's public key
     * @param null|Crypto $crypto Crypto engine, use default if not set
     *
     * @return bool True if certificate signature is valid
     */
    public function verify(PublicKeyInfo $pubkey_info, ?Crypto $crypto = null): bool
    {
        $crypto ??= Crypto::getDefault();
        $data = $this->tbsCertificate->toASN1()->toDER();
        return $crypto->verify($data, $this->signatureValue, $pubkey_info, $this->signatureAlgorithm);
    }
    /**
     * Check whether certificate has serial number equal to another.
     */
    private function _hasEqualSerialNumber(self $cert): bool
    {
        $sn1 = $this->tbsCertificate->serialNumber();
        $sn2 = $cert->tbsCertificate->serialNumber();
        return $sn1 === $sn2;
    }
    /**
     * Check whether certificate has public key equal to another.
     */
    private function _hasEqualPublicKey(self $cert): bool
    {
        $kid1 = $this->tbsCertificate->subjectPublicKeyInfo()->keyIdentifier();
        $kid2 = $cert->tbsCertificate->subjectPublicKeyInfo()->keyIdentifier();
        return $kid1 === $kid2;
    }
    /**
     * Check whether certificate has subject equal to another.
     */
    private function _hasEqualSubject(self $cert): bool
    {
        $dn1 = $this->tbsCertificate->subject();
        $dn2 = $cert->tbsCertificate->subject();
        return $dn1->equals($dn2);
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\X509\Certificate;

use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Primitive\BitString;
/**
 * Implements *UniqueIdentifier* ASN.1 type.
 *
 * @see https://tools.ietf.org/html/rfc5280#section-4.1.2.8
 */
final class UniqueIdentifier
{
    private function __construct(private readonly BitString $uid)
    {
    }
    public static function create(BitString $uid): self
    {
        return new self($uid);
    }
    /**
     * Initialize from ASN.1.
     */
    public static function fromASN1(BitString $bs): self
    {
        return self::create($bs);
    }
    /**
     * Initialize from string.
     */
    public static function fromString(string $str): self
    {
        return self::create(BitString::create($str));
    }
    /**
     * Get unique identifier as a string.
     */
    public function string(): string
    {
        return $this->uid->string();
    }
    /**
     * Get unique identifier as a bit string.
     */
    public function bitString(): BitString
    {
        return $this->uid;
    }
    /**
     * Get ASN.1 element.
     */
    public function toASN1(): BitString
    {
        return $this->uid;
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\X509\Certificate;

use ArrayIterator;
use function count;
use Countable;
use IteratorAggregate;
use LogicException;
use _ContaoManager\SpomkyLabs\Pki\CryptoEncoding\PEM;
use _ContaoManager\SpomkyLabs\Pki\CryptoEncoding\PEMBundle;
use _ContaoManager\SpomkyLabs\Pki\X509\CertificationPath\CertificationPath;
/**
 * Ordered list of certificates from the end-entity to the trust anchor.
 */
final class CertificateChain implements Countable, IteratorAggregate
{
    /**
     * List of certificates in a chain.
     *
     * @var Certificate[]
     */
    private readonly array $certs;
    /**
     * @param Certificate ...$certs List of certificates, end-entity first
     */
    private function __construct(Certificate ...$certs)
    {
        $this->certs = $certs;
    }
    public static function create(Certificate ...$certs): self
    {
        return new self(...$certs);
    }
    /**
     * Initialize from a list of PEMs.
     */
    public static function fromPEMs(PEM ...$pems): self
    {
        $certs = array_map(Certificate::fromPEM(...), $pems);
        return self::create(...$certs);
    }
    /**
     * Initialize from a string containing multiple PEM blocks.
     */
    public static function fromPEMString(string $str): self
    {
        $pems = PEMBundle::fromString($str)->all();
        return self::fromPEMs(...$pems);
    }
    /**
     * Get all certificates in a chain ordered from the end-entity certificate to the trust anchor.
     *
     * @return Certificate[]
     */
    public function certificates(): array
    {
        return $this->certs;
    }
    /**
     * Get the end-entity certificate.
     */
    public function endEntityCertificate(): Certificate
    {
        if (count($this->certs) === 0) {
            throw new LogicException('No certificates.');
        }
        return $this->certs[0];
    }
    /**
     * Get the trust anchor certificate.
     */
    public function trustAnchorCertificate(): Certificate
    {
        if (count($this->certs) === 0) {
            throw new LogicException('No certificates.');
        }
        return $this->certs[count($this->certs) - 1];
    }
    /**
     * Convert certificate chain to certification path.
     */
    public function certificationPath(): CertificationPath
    {
        return CertificationPath::fromCertificateChain($this);
    }
    /**
     * Convert certificate chain to string of PEM blocks.
     */
    public function toPEMString(): string
    {
        return implode("\n", array_map(static fn(Certificate $cert) => $cert->toPEM()->string(), $this->certs));
    }
    /**
     * @see \Countable::count()
     */
    public function count(): int
    {
        return count($this->certs);
    }
    /**
     * Get iterator for certificates.
     *
     * @see \IteratorAggregate::getIterator()
     */
    public function getIterator(): ArrayIterator
    {
        return new ArrayIterator($this->certs);
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\X509\Certificate;

use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Constructed\Sequence;
/**
 * Implements *Validity* ASN.1 type.
 *
 * @see https://tools.ietf.org/html/rfc5280#section-4.1.2.5
 */
final class Validity
{
    private function __construct(private readonly Time $notBefore, private readonly Time $notAfter)
    {
    }
    public static function create(Time $notBefore, Time $notAfter): self
    {
        return new self($notBefore, $notAfter);
    }
    /**
     * Initialize from ASN.1.
     */
    public static function fromASN1(Sequence $seq): self
    {
        $nb = Time::fromASN1($seq->at(0)->asTime());
        $na = Time::fromASN1($seq->at(1)->asTime());
        return self::create($nb, $na);
    }
    /**
     * Initialize from date strings.
     *
     * @param null|string $nb_date Not before date
     * @param null|string $na_date Not after date
     * @param null|string $tz Timezone string
     */
    public static function fromStrings(?string $nb_date, ?string $na_date, ?string $tz = null): self
    {
        return self::create(Time::fromString($nb_date, $tz), Time::fromString($na_date, $tz));
    }
    /**
     * Get not before time.
     */
    public function notBefore(): Time
    {
        return $this->notBefore;
    }
    /**
     * Get not after time.
     */
    public function notAfter(): Time
    {
        return $this->notAfter;
    }
    /**
     * Generate ASN.1 structure.
     */
    public function toASN1(): Sequence
    {
        return Sequence::create($this->notBefore->toASN1(), $this->notAfter->toASN1());
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\X509\Certificate;

use ArrayIterator;
use function count;
use Countable;
use IteratorAggregate;
use _ContaoManager\SpomkyLabs\Pki\CryptoEncoding\PEM;
use _ContaoManager\SpomkyLabs\Pki\CryptoEncoding\PEMBundle;
/**
 * Implements a list of certificates.
 */
final class CertificateBundle implements Countable, IteratorAggregate
{
    /**
     * Certificates.
     *
     * @var Certificate[]
     */
    private array $certs;
    /**
     * Mapping from public key id to array of certificates.
     *
     * @var null|(Certificate[])[]
     */
    private ?array $keyIdMap = null;
    /**
     * @param Certificate ...$certs Certificate objects
     */
    private function __construct(Certificate ...$certs)
    {
        $this->certs = $certs;
    }
    /**
     * Reset internal cached variables on clone.
     */
    public function __clone()
    {
        $this->keyIdMap = null;
    }
    public static function create(Certificate ...$certs): self
    {
        return new self(...$certs);
    }
    /**
     * Initialize from PEMs.
     *
     * @param PEM ...$pems PEM objects
     */
    public static function fromPEMs(PEM ...$pems): self
    {
        $certs = array_map(Certificate::fromPEM(...), $pems);
        return self::create(...$certs);
    }
    /**
     * Initialize from PEM bundle.
     */
    public static function fromPEMBundle(PEMBundle $pem_bundle): self
    {
        return self::fromPEMs(...$pem_bundle->all());
    }
    /**
     * Get self with certificates added.
     */
    public function withCertificates(Certificate ...$cert): self
    {
        $obj = clone $this;
        $obj->certs = array_merge($obj->certs, $cert);
        return $obj;
    }
    /**
     * Get self with certificates from PEMBundle added.
     */
    public function withPEMBundle(PEMBundle $pem_bundle): self
    {
        $certs = $this->certs;
        foreach ($pem_bundle as $pem) {
            $certs[] = Certificate::fromPEM($pem);
        }
        return self::create(...$certs);
    }
    /**
     * Get self with single certificate from PEM added.
     */
    public function withPEM(PEM $pem): self
    {
        $certs = $this->certs;
        $certs[] = Certificate::fromPEM($pem);
        return self::create(...$certs);
    }
    /**
     * Check whether bundle contains a given certificate.
     */
    public function contains(Certificate $cert): bool
    {
        $id = self::_getCertKeyId($cert);
        $map = $this->_getKeyIdMap();
        if (!isset($map[$id])) {
            return \false;
        }
        foreach ($map[$id] as $c) {
            /** @var Certificate $c */
            if ($cert->equals($c)) {
                return \true;
            }
        }
        return \false;
    }
    /**
     * Get all certificates that have given subject key identifier.
     *
     * @return Certificate[]
     */
    public function allBySubjectKeyIdentifier(string $id): array
    {
        $map = $this->_getKeyIdMap();
        if (!isset($map[$id])) {
            return [];
        }
        return $map[$id];
    }
    /**
     * Get all certificates in a bundle.
     *
     * @return Certificate[]
     */
    public function all(): array
    {
        return $this->certs;
    }
    /**
     * @see \Countable::count()
     */
    public function count(): int
    {
        return count($this->certs);
    }
    /**
     * Get iterator for certificates.
     *
     * @see \IteratorAggregate::getIterator()
     */
    public function getIterator(): ArrayIterator
    {
        return new ArrayIterator($this->certs);
    }
    /**
     * Get certificate mapping by public key id.
     *
     * @return (Certificate[])[]
     */
    private function _getKeyIdMap(): array
    {
        // lazily build mapping
        if (!isset($this->keyIdMap)) {
            $this->keyIdMap = [];
            foreach ($this->certs as $cert) {
                $id = self::_getCertKeyId($cert);
                if (!isset($this->keyIdMap[$id])) {
                    $this->keyIdMap[$id] = [];
                }
                array_push($this->keyIdMap[$id], $cert);
            }
        }
        return $this->keyIdMap;
    }
    /**
     * Get public key id for the certificate.
     */
    private static function _getCertKeyId(Certificate $cert): string
    {
        $exts = $cert->tbsCertificate()->extensions();
        if ($exts->hasSubjectKeyIdentifier()) {
            return $exts->subjectKeyIdentifier()->keyIdentifier();
        }
        return $cert->tbsCertificate()->subjectPublicKeyInfo()->keyIdentifier();
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\X509\Certificate;

use _ContaoManager\Brick\Math\BigInteger;
use function count;
use LogicException;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Element;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Constructed\Sequence;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Primitive\Integer;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Tagged\ExplicitlyTaggedType;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Tagged\ImplicitlyTaggedType;
use _ContaoManager\SpomkyLabs\Pki\CryptoBridge\Crypto;
use _ContaoManager\SpomkyLabs\Pki\CryptoTypes\AlgorithmIdentifier\AlgorithmIdentifier;
use _ContaoManager\SpomkyLabs\Pki\CryptoTypes\AlgorithmIdentifier\Feature\SignatureAlgorithmIdentifier;
use _ContaoManager\SpomkyLabs\Pki\CryptoTypes\Asymmetric\PrivateKeyInfo;
use _ContaoManager\SpomkyLabs\Pki\CryptoTypes\Asymmetric\PublicKeyInfo;
use _ContaoManager\SpomkyLabs\Pki\X501\ASN1\Name;
use _ContaoManager\SpomkyLabs\Pki\X509\Certificate\Extension\AuthorityKeyIdentifierExtension;
use _ContaoManager\SpomkyLabs\Pki\X509\Certificate\Extension\Extension;
use _ContaoManager\SpomkyLabs\Pki\X509\Certificate\Extension\SubjectKeyIdentifierExtension;
use _ContaoManager\SpomkyLabs\Pki\X509\CertificationRequest\CertificationRequest;
use function strval;
use UnexpectedValueException;
/**
 * Implements *TBSCertificate* ASN.1 type.
 *
 * @see https://tools.ietf.org/html/rfc5280#section-4.1.2
 */
final class TBSCertificate
{
    // Certificate version enumerations
    final public const VERSION_1 = 0;
    final public const VERSION_2 = 1;
    final public const VERSION_3 = 2;
    /**
     * Certificate version.
     */
    private ?int $version = null;
    /**
     * Serial number.
     */
    private ?string $serialNumber = null;
    /**
     * Signature algorithm.
     */
    private ?SignatureAlgorithmIdentifier $signature = null;
    /**
     * Issuer unique identifier.
     */
    private ?UniqueIdentifier $issuerUniqueID = null;
    /**
     * Subject unique identifier.
     */
    private ?UniqueIdentifier $subjectUniqueID = null;
    /**
     * Extensions.
     */
    private Extensions $extensions;
    /**
     * @param Name $subject Certificate subject
     * @param PublicKeyInfo $subjectPublicKeyInfo Subject public key
     * @param Name $issuer Certificate issuer
     * @param Validity $validity Validity period
     */
    private function __construct(private Name $subject, private PublicKeyInfo $subjectPublicKeyInfo, private Name $issuer, private Validity $validity)
    {
        $this->extensions = Extensions::create();
    }
    public static function create(Name $subject, PublicKeyInfo $subjectPublicKeyInfo, Name $issuer, Validity $validity): self
    {
        return new self($subject, $subjectPublicKeyInfo, $issuer, $validity);
    }
    /**
     * Initialize from ASN.1.
     */
    public static function fromASN1(Sequence $seq): self
    {
        $idx = 0;
        if ($seq->hasTagged(0)) {
            ++$idx;
            $version = $seq->getTagged(0)->asExplicit()->asInteger()->intNumber();
        } else {
            $version = self::VERSION_1;
        }
        $serial = $seq->at($idx++)->asInteger()->number();
        $algo = AlgorithmIdentifier::fromASN1($seq->at($idx++)->asSequence());
        if (!$algo instanceof SignatureAlgorithmIdentifier) {
            throw new UnexpectedValueException('Unsupported signature algorithm ' . $algo->name() . '.');
        }
        $issuer = Name::fromASN1($seq->at($idx++)->asSequence());
        $validity = Validity::fromASN1($seq->at($idx++)->asSequence());
        $subject = Name::fromASN1($seq->at($idx++)->asSequence());
        $pki = PublicKeyInfo::fromASN1($seq->at($idx++)->asSequence());
        $tbs_cert = self::create($subject, $pki, $issuer, $validity)->withVersion($version)->withSerialNumber($serial)->withSignature($algo);
        if ($seq->hasTagged(1)) {
            $tbs_cert = $tbs_cert->withIssuerUniqueID(UniqueIdentifier::fromASN1($seq->getTagged(1)->asImplicit(Element::TYPE_BIT_STRING)->asBitString()));
        }
        if ($seq->hasTagged(2)) {
            $tbs_cert = $tbs_cert->withSubjectUniqueID(UniqueIdentifier::fromASN1($seq->getTagged(2)->asImplicit(Element::TYPE_BIT_STRING)->asBitString()));
        }
        if ($seq->hasTagged(3)) {
            $tbs_cert = $tbs_cert->withExtensions(Extensions::fromASN1($seq->getTagged(3)->asExplicit()->asSequence()));
        }
        return $tbs_cert;
    }
    /**
     * Initialize from certification request.
     *
     * Note that signature is not verified and must be done by the caller.
     */
    public static function fromCSR(CertificationRequest $cr): self
    {
        $cri = $cr->certificationRequestInfo();
        $tbs_cert = self::create($cri->subject(), $cri->subjectPKInfo(), Name::create(), Validity::fromStrings(null, null));
        // if CSR has Extension Request attribute
        if ($cri->hasAttributes()) {
            $attribs = $cri->attributes();
            if ($attribs->hasExtensionRequest()) {
                $tbs_cert = $tbs_cert->withExtensions($attribs->extensionRequest()->extensions());
            }
        }
        // add Subject Key Identifier extension
        return $tbs_cert->withAdditionalExtensions(SubjectKeyIdentifierExtension::create(\false, $cri->subjectPKInfo()->keyIdentifier()));
    }
    /**
     * Get self with fields set from the issuer's certificate.
     *
     * Issuer shall be set to issuing certificate's subject. Authority key identifier extensions shall be added with a
     * key identifier set to issuing certificate's public key identifier.
     *
     * @param Certificate $cert Issuing party's certificate
     */
    public function withIssuerCertificate(Certificate $cert): self
    {
        $obj = clone $this;
        // set issuer DN from cert's subject
        $obj->issuer = $cert->tbsCertificate()->subject();
        // add authority key identifier extension
        $key_id = $cert->tbsCertificate()->subjectPublicKeyInfo()->keyIdentifier();
        $obj->extensions = $obj->extensions->withExtensions(AuthorityKeyIdentifierExtension::create(\false, $key_id));
        return $obj;
    }
    /**
     * Get self with given version.
     *
     * If version is not set, appropriate version is automatically determined during signing.
     */
    public function withVersion(int $version): self
    {
        $obj = clone $this;
        $obj->version = $version;
        return $obj;
    }
    /**
     * Get self with given serial number.
     *
     * @param int|string $serial Base 10 number
     */
    public function withSerialNumber(int|string $serial): self
    {
        $obj = clone $this;
        $obj->serialNumber = strval($serial);
        return $obj;
    }
    /**
     * Get self with random positive serial number.
     *
     * @param int $size Number of random bytes
     */
    public function withRandomSerialNumber(int $size): self
    {
        // ensure that first byte is always non-zero and having first bit unset
        $num = BigInteger::of(random_int(1, 0x7f));
        for ($i = 1; $i < $size; ++$i) {
            $num = $num->shiftedLeft(8);
            $num = $num->plus(random_int(0, 0xff));
        }
        return $this->withSerialNumber($num->toBase(10));
    }
    /**
     * Get self with given signature algorithm.
     */
    public function withSignature(SignatureAlgorithmIdentifier $algo): self
    {
        $obj = clone $this;
        $obj->signature = $algo;
        return $obj;
    }
    /**
     * Get self with given issuer.
     */
    public function withIssuer(Name $issuer): self
    {
        $obj = clone $this;
        $obj->issuer = $issuer;
        return $obj;
    }
    /**
     * Get self with given validity.
     */
    public function withValidity(Validity $validity): self
    {
        $obj = clone $this;
        $obj->validity = $validity;
        return $obj;
    }
    /**
     * Get self with given subject.
     */
    public function withSubject(Name $subject): self
    {
        $obj = clone $this;
        $obj->subject = $subject;
        return $obj;
    }
    /**
     * Get self with given subject public key info.
     */
    public function withSubjectPublicKeyInfo(PublicKeyInfo $pub_key_info): self
    {
        $obj = clone $this;
        $obj->subjectPublicKeyInfo = $pub_key_info;
        return $obj;
    }
    /**
     * Get self with issuer unique ID.
     */
    public function withIssuerUniqueID(UniqueIdentifier $id): self
    {
        $obj = clone $this;
        $obj->issuerUniqueID = $id;
        return $obj;
    }
    /**
     * Get self with subject unique ID.
     */
    public function withSubjectUniqueID(UniqueIdentifier $id): self
    {
        $obj = clone $this;
        $obj->subjectUniqueID = $id;
        return $obj;
    }
    /**
     * Get self with given extensions.
     */
    public function withExtensions(Extensions $extensions): self
    {
        $obj = clone $this;
        $obj->extensions = $extensions;
        return $obj;
    }
    /**
     * Get self with extensions added.
     *
     * @param Extension ...$exts One or more Extension objects
     */
    public function withAdditionalExtensions(Extension ...$exts): self
    {
        $obj = clone $this;
        $obj->extensions = $obj->extensions->withExtensions(...$exts);
        return $obj;
    }
    /**
     * Check whether version is set.
     */
    public function hasVersion(): bool
    {
        return isset($this->version);
    }
    /**
     * Get certificate version.
     */
    public function version(): int
    {
        if (!$this->hasVersion()) {
            throw new LogicException('version not set.');
        }
        return $this->version;
    }
    /**
     * Check whether serial number is set.
     */
    public function hasSerialNumber(): bool
    {
        return isset($this->serialNumber);
    }
    /**
     * Get serial number.
     *
     * @return string Base 10 integer
     */
    public function serialNumber(): string
    {
        if (!$this->hasSerialNumber()) {
            throw new LogicException('serialNumber not set.');
        }
        return $this->serialNumber;
    }
    /**
     * Check whether signature algorithm is set.
     */
    public function hasSignature(): bool
    {
        return isset($this->signature);
    }
    /**
     * Get signature algorithm.
     */
    public function signature(): SignatureAlgorithmIdentifier
    {
        if (!$this->hasSignature()) {
            throw new LogicException('signature not set.');
        }
        return $this->signature;
    }
    public function issuer(): Name
    {
        return $this->issuer;
    }
    /**
     * Get validity period.
     */
    public function validity(): Validity
    {
        return $this->validity;
    }
    public function subject(): Name
    {
        return $this->subject;
    }
    /**
     * Get subject public key.
     */
    public function subjectPublicKeyInfo(): PublicKeyInfo
    {
        return $this->subjectPublicKeyInfo;
    }
    /**
     * Whether issuer unique identifier is present.
     */
    public function hasIssuerUniqueID(): bool
    {
        return isset($this->issuerUniqueID);
    }
    public function issuerUniqueID(): UniqueIdentifier
    {
        if (!$this->hasIssuerUniqueID()) {
            throw new LogicException('issuerUniqueID not set.');
        }
        return $this->issuerUniqueID;
    }
    /**
     * Whether subject unique identifier is present.
     */
    public function hasSubjectUniqueID(): bool
    {
        return isset($this->subjectUniqueID);
    }
    public function subjectUniqueID(): UniqueIdentifier
    {
        if (!$this->hasSubjectUniqueID()) {
            throw new LogicException('subjectUniqueID not set.');
        }
        return $this->subjectUniqueID;
    }
    public function extensions(): Extensions
    {
        return $this->extensions;
    }
    /**
     * Generate ASN.1 structure.
     */
    public function toASN1(): Sequence
    {
        $elements = [];
        $version = $this->version();
        // if version is not default
        if ($version !== self::VERSION_1) {
            $elements[] = ExplicitlyTaggedType::create(0, Integer::create($version));
        }
        $serial = $this->serialNumber();
        $signature = $this->signature();
        // add required elements
        array_push($elements, Integer::create($serial), $signature->toASN1(), $this->issuer->toASN1(), $this->validity->toASN1(), $this->subject->toASN1(), $this->subjectPublicKeyInfo->toASN1());
        if (isset($this->issuerUniqueID)) {
            $elements[] = ImplicitlyTaggedType::create(1, $this->issuerUniqueID->toASN1());
        }
        if (isset($this->subjectUniqueID)) {
            $elements[] = ImplicitlyTaggedType::create(2, $this->subjectUniqueID->toASN1());
        }
        if (count($this->extensions) !== 0) {
            $elements[] = ExplicitlyTaggedType::create(3, $this->extensions->toASN1());
        }
        return Sequence::create(...$elements);
    }
    /**
     * Create signed certificate.
     *
     * @param SignatureAlgorithmIdentifier $algo Algorithm used for signing
     * @param PrivateKeyInfo $privkey_info Private key used for signing
     * @param null|Crypto $crypto Crypto engine, use default if not set
     */
    public function sign(SignatureAlgorithmIdentifier $algo, PrivateKeyInfo $privkey_info, ?Crypto $crypto = null): Certificate
    {
        $crypto ??= Crypto::getDefault();
        $tbs_cert = clone $this;
        if (!isset($tbs_cert->version)) {
            $tbs_cert->version = $tbs_cert->_determineVersion();
        }
        if (!isset($tbs_cert->serialNumber)) {
            $tbs_cert->serialNumber = '0';
        }
        $tbs_cert->signature = $algo;
        $data = $tbs_cert->toASN1()->toDER();
        $signature = $crypto->sign($data, $privkey_info, $algo);
        return Certificate::create($tbs_cert, $algo, $signature);
    }
    /**
     * Determine minimum version for the certificate.
     */
    private function _determineVersion(): int
    {
        // if extensions are present
        if (count($this->extensions) !== 0) {
            return self::VERSION_3;
        }
        // if UniqueIdentifier is present
        if (isset($this->issuerUniqueID) || isset($this->subjectUniqueID)) {
            return self::VERSION_2;
        }
        return self::VERSION_1;
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\X509\Certificate;

use ArrayIterator;
use function count;
use Countable;
use IteratorAggregate;
use LogicException;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Constructed\Sequence;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\UnspecifiedType;
use _ContaoManager\SpomkyLabs\Pki\X509\Certificate\Extension\AuthorityKeyIdentifierExtension;
use _ContaoManager\SpomkyLabs\Pki\X509\Certificate\Extension\BasicConstraintsExtension;
use _ContaoManager\SpomkyLabs\Pki\X509\Certificate\Extension\CertificatePoliciesExtension;
use _ContaoManager\SpomkyLabs\Pki\X509\Certificate\Extension\CRLDistributionPointsExtension;
use _ContaoManager\SpomkyLabs\Pki\X509\Certificate\Extension\ExtendedKeyUsageExtension;
use _ContaoManager\SpomkyLabs\Pki\X509\Certificate\Extension\Extension;
use _ContaoManager\SpomkyLabs\Pki\X509\Certificate\Extension\InhibitAnyPolicyExtension;
use _ContaoManager\SpomkyLabs\Pki\X509\Certificate\Extension\IssuerAlternativeNameExtension;
use _ContaoManager\SpomkyLabs\Pki\X509\Certificate\Extension\KeyUsageExtension;
use _ContaoManager\SpomkyLabs\Pki\X509\Certificate\Extension\NameConstraintsExtension;
use _ContaoManager\SpomkyLabs\Pki\X509\Certificate\Extension\PolicyConstraintsExtension;
use _ContaoManager\SpomkyLabs\Pki\X509\Certificate\Extension\PolicyMappingsExtension;
use _ContaoManager\SpomkyLabs\Pki\X509\Certificate\Extension\SubjectAlternativeNameExtension;
use _ContaoManager\SpomkyLabs\Pki\X509\Certificate\Extension\SubjectKeyIdentifierExtension;
use Traversable;
/**
 * Implements *Extensions* ASN.1 type.
 *
 * Several convenience methods are provided to fetch commonly used standard extensions. Others can be accessed using
 * `get($oid)`.
 *
 * @see https://tools.ietf.org/html/rfc5280#section-4.1.2.9
 */
final class Extensions implements Countable, IteratorAggregate
{
    /**
     * Extensions.
     *
     * @var Extension[]
     */
    private array $extensions;
    /**
     * @param Extension ...$extensions Extension objects
     */
    private function __construct(Extension ...$extensions)
    {
        $this->extensions = [];
        foreach ($extensions as $ext) {
            $this->extensions[$ext->oid()] = $ext;
        }
    }
    public static function create(Extension ...$extensions): self
    {
        return new self(...$extensions);
    }
    /**
     * Initialize from ASN.1.
     */
    public static function fromASN1(Sequence $seq): self
    {
        $extensions = array_map(static fn(UnspecifiedType $el) => Extension::fromASN1($el->asSequence()), $seq->elements());
        return self::create(...$extensions);
    }
    /**
     * Generate ASN.1 structure.
     */
    public function toASN1(): Sequence
    {
        $elements = array_values(array_map(static fn($ext) => $ext->toASN1(), $this->extensions));
        return Sequence::create(...$elements);
    }
    /**
     * Get self with extensions added.
     *
     * @param Extension ...$exts One or more extensions to add
     */
    public function withExtensions(Extension ...$exts): self
    {
        $obj = clone $this;
        foreach ($exts as $ext) {
            $obj->extensions[$ext->oid()] = $ext;
        }
        return $obj;
    }
    /**
     * Check whether extension is present.
     *
     * @param string $oid Extensions OID
     */
    public function has(string $oid): bool
    {
        return isset($this->extensions[$oid]);
    }
    /**
     * Get extension by OID.
     */
    public function get(string $oid): Extension
    {
        if (!$this->has($oid)) {
            throw new LogicException("No extension by OID {$oid}.");
        }
        return $this->extensions[$oid];
    }
    /**
     * Check whether 'Authority Key Identifier' extension is present.
     */
    public function hasAuthorityKeyIdentifier(): bool
    {
        return $this->has(Extension::OID_AUTHORITY_KEY_IDENTIFIER);
    }
    /**
     * Get 'Authority Key Identifier' extension.
     */
    public function authorityKeyIdentifier(): AuthorityKeyIdentifierExtension
    {
        return $this->get(Extension::OID_AUTHORITY_KEY_IDENTIFIER);
    }
    /**
     * Check whether 'Subject Key Identifier' extension is present.
     */
    public function hasSubjectKeyIdentifier(): bool
    {
        return $this->has(Extension::OID_SUBJECT_KEY_IDENTIFIER);
    }
    /**
     * Get 'Subject Key Identifier' extension.
     */
    public function subjectKeyIdentifier(): SubjectKeyIdentifierExtension
    {
        return $this->get(Extension::OID_SUBJECT_KEY_IDENTIFIER);
    }
    /**
     * Check whether 'Key Usage' extension is present.
     */
    public function hasKeyUsage(): bool
    {
        return $this->has(Extension::OID_KEY_USAGE);
    }
    /**
     * Get 'Key Usage' extension.
     */
    public function keyUsage(): KeyUsageExtension
    {
        return $this->get(Extension::OID_KEY_USAGE);
    }
    /**
     * Check whether 'Certificate Policies' extension is present.
     */
    public function hasCertificatePolicies(): bool
    {
        return $this->has(Extension::OID_CERTIFICATE_POLICIES);
    }
    /**
     * Get 'Certificate Policies' extension.
     */
    public function certificatePolicies(): CertificatePoliciesExtension
    {
        return $this->get(Extension::OID_CERTIFICATE_POLICIES);
    }
    /**
     * Check whether 'Policy Mappings' extension is present.
     */
    public function hasPolicyMappings(): bool
    {
        return $this->has(Extension::OID_POLICY_MAPPINGS);
    }
    /**
     * Get 'Policy Mappings' extension.
     */
    public function policyMappings(): PolicyMappingsExtension
    {
        return $this->get(Extension::OID_POLICY_MAPPINGS);
    }
    /**
     * Check whether 'Subject Alternative Name' extension is present.
     */
    public function hasSubjectAlternativeName(): bool
    {
        return $this->has(Extension::OID_SUBJECT_ALT_NAME);
    }
    /**
     * Get 'Subject Alternative Name' extension.
     */
    public function subjectAlternativeName(): SubjectAlternativeNameExtension
    {
        return $this->get(Extension::OID_SUBJECT_ALT_NAME);
    }
    /**
     * Check whether 'Issuer Alternative Name' extension is present.
     */
    public function hasIssuerAlternativeName(): bool
    {
        return $this->has(Extension::OID_ISSUER_ALT_NAME);
    }
    /**
     * Get 'Issuer Alternative Name' extension.
     */
    public function issuerAlternativeName(): IssuerAlternativeNameExtension
    {
        return $this->get(Extension::OID_ISSUER_ALT_NAME);
    }
    /**
     * Check whether 'Basic Constraints' extension is present.
     */
    public function hasBasicConstraints(): bool
    {
        return $this->has(Extension::OID_BASIC_CONSTRAINTS);
    }
    /**
     * Get 'Basic Constraints' extension.
     */
    public function basicConstraints(): BasicConstraintsExtension
    {
        return $this->get(Extension::OID_BASIC_CONSTRAINTS);
    }
    /**
     * Check whether 'Name Constraints' extension is present.
     */
    public function hasNameConstraints(): bool
    {
        return $this->has(Extension::OID_NAME_CONSTRAINTS);
    }
    /**
     * Get 'Name Constraints' extension.
     */
    public function nameConstraints(): NameConstraintsExtension
    {
        return $this->get(Extension::OID_NAME_CONSTRAINTS);
    }
    /**
     * Check whether 'Policy Constraints' extension is present.
     */
    public function hasPolicyConstraints(): bool
    {
        return $this->has(Extension::OID_POLICY_CONSTRAINTS);
    }
    /**
     * Get 'Policy Constraints' extension.
     */
    public function policyConstraints(): PolicyConstraintsExtension
    {
        return $this->get(Extension::OID_POLICY_CONSTRAINTS);
    }
    /**
     * Check whether 'Extended Key Usage' extension is present.
     */
    public function hasExtendedKeyUsage(): bool
    {
        return $this->has(Extension::OID_EXT_KEY_USAGE);
    }
    /**
     * Get 'Extended Key Usage' extension.
     */
    public function extendedKeyUsage(): ExtendedKeyUsageExtension
    {
        return $this->get(Extension::OID_EXT_KEY_USAGE);
    }
    /**
     * Check whether 'CRL Distribution Points' extension is present.
     */
    public function hasCRLDistributionPoints(): bool
    {
        return $this->has(Extension::OID_CRL_DISTRIBUTION_POINTS);
    }
    /**
     * Get 'CRL Distribution Points' extension.
     */
    public function crlDistributionPoints(): CRLDistributionPointsExtension
    {
        return $this->get(Extension::OID_CRL_DISTRIBUTION_POINTS);
    }
    /**
     * Check whether 'Inhibit anyPolicy' extension is present.
     */
    public function hasInhibitAnyPolicy(): bool
    {
        return $this->has(Extension::OID_INHIBIT_ANY_POLICY);
    }
    /**
     * Get 'Inhibit anyPolicy' extension.
     */
    public function inhibitAnyPolicy(): InhibitAnyPolicyExtension
    {
        return $this->get(Extension::OID_INHIBIT_ANY_POLICY);
    }
    /**
     * @see \Countable::count()
     */
    public function count(): int
    {
        return count($this->extensions);
    }
    /**
     * Get iterator for extensions.
     *
     * @see \IteratorAggregate::getIterator()
     */
    public function getIterator(): Traversable
    {
        return new ArrayIterator($this->extensions);
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\X509\GeneralName;

use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Primitive\ObjectIdentifier;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Tagged\ImplicitlyTaggedType;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\TaggedType;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\UnspecifiedType;
/**
 * Implements *registeredID* CHOICE type of *GeneralName*.
 *
 * @see https://tools.ietf.org/html/rfc5280#section-4.2.1.6
 */
final class RegisteredID extends GeneralName
{
    /**
     * @param string $oid OID in dotted format
     */
    private function __construct(private readonly string $oid)
    {
        parent::__construct(self::TAG_REGISTERED_ID);
    }
    public static function create(string $oid): self
    {
        return new self($oid);
    }
    /**
     * @return self
     */
    public static function fromChosenASN1(UnspecifiedType $el): GeneralName
    {
        return self::create($el->asObjectIdentifier()->oid());
    }
    public function string(): string
    {
        return $this->oid;
    }
    /**
     * Get object identifier in dotted format.
     *
     * @return string OID
     */
    public function oid(): string
    {
        return $this->oid;
    }
    protected function choiceASN1(): TaggedType
    {
        return ImplicitlyTaggedType::create($this->tag, ObjectIdentifier::create($this->oid));
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\X509\GeneralName;

use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Tagged\ExplicitlyTaggedType;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\TaggedType;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\UnspecifiedType;
use _ContaoManager\SpomkyLabs\Pki\X501\ASN1\Name;
/**
 * Implements *directoryName* CHOICE type of *GeneralName*.
 *
 * @see https://tools.ietf.org/html/rfc5280#section-4.2.1.6
 */
final class DirectoryName extends GeneralName
{
    private function __construct(private readonly Name $directoryName)
    {
        parent::__construct(self::TAG_DIRECTORY_NAME);
    }
    public static function create(Name $directoryName): self
    {
        return new self($directoryName);
    }
    /**
     * @return self
     */
    public static function fromChosenASN1(UnspecifiedType $el): GeneralName
    {
        return self::create(Name::fromASN1($el->asSequence()));
    }
    /**
     * Initialize from distinguished name string.
     */
    public static function fromDNString(string $str): self
    {
        return self::create(Name::fromString($str));
    }
    public function string(): string
    {
        return $this->directoryName->toString();
    }
    /**
     * Get directory name.
     */
    public function dn(): Name
    {
        return $this->directoryName;
    }
    protected function choiceASN1(): TaggedType
    {
        // Name type is itself a CHOICE, so explicit tagging must be
        // employed to avoid ambiguities
        return ExplicitlyTaggedType::create($this->tag, $this->directoryName->toASN1());
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\X509\GeneralName;

use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Constructed\Sequence;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Tagged\ImplicitlyTaggedType;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\TaggedType;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\UnspecifiedType;
/**
 * Implements *ediPartyName* CHOICE type of *GeneralName*.
 *
 * Currently acts as a parking object for decoding.
 *
 * @see https://tools.ietf.org/html/rfc5280#section-4.2.1.6
 *
 * @todo Implement EDIPartyName type
 */
final class EDIPartyName extends GeneralName
{
    private function __construct(protected Sequence $element)
    {
        parent::__construct(self::TAG_EDI_PARTY_NAME);
    }
    public static function create(Sequence $element): self
    {
        return new self($element);
    }
    /**
     * @return self
     */
    public static function fromChosenASN1(UnspecifiedType $el): GeneralName
    {
        return self::create($el->asSequence());
    }
    public function string(): string
    {
        return bin2hex($this->element->toDER());
    }
    protected function choiceASN1(): TaggedType
    {
        return ImplicitlyTaggedType::create($this->tag, $this->element);
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\X509\GeneralName;

use _ContaoManager\SpomkyLabs\Pki\ASN1\Element;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Constructed\Sequence;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Primitive\ObjectIdentifier;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Tagged\ExplicitlyTaggedType;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Tagged\ImplicitlyTaggedType;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\TaggedType;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\UnspecifiedType;
/**
 * Implements *otherName* CHOICE type of *GeneralName*.
 *
 * @see https://tools.ietf.org/html/rfc5280#section-4.2.1.6
 */
final class OtherName extends GeneralName
{
    /**
     * @param string $type OID
     */
    private function __construct(private readonly string $type, private readonly Element $element)
    {
        parent::__construct(self::TAG_OTHER_NAME);
    }
    public static function create(string $type, Element $element): self
    {
        return new self($type, $element);
    }
    /**
     * @return self
     */
    public static function fromChosenASN1(UnspecifiedType $el): GeneralName
    {
        $seq = $el->asSequence();
        $type_id = $seq->at(0)->asObjectIdentifier()->oid();
        $value = $seq->getTagged(0)->asExplicit()->asElement();
        return self::create($type_id, $value);
    }
    public function string(): string
    {
        return $this->type . '/#' . bin2hex($this->element->toDER());
    }
    /**
     * Get type OID.
     */
    public function type(): string
    {
        return $this->type;
    }
    /**
     * Get value element.
     */
    public function value(): Element
    {
        return $this->element;
    }
    protected function choiceASN1(): TaggedType
    {
        return ImplicitlyTaggedType::create($this->tag, Sequence::create(ObjectIdentifier::create($this->type), ExplicitlyTaggedType::create(0, $this->element)));
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\X509\GeneralName;

use LogicException;
use function mb_strlen;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Primitive\OctetString;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Tagged\ImplicitlyTaggedType;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\TaggedType;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\UnspecifiedType;
use UnexpectedValueException;
/**
 * Implements *iPAddress* CHOICE type of *GeneralName*.
 *
 * Concrete classes `IPv4Address` and `IPv6Address` furthermore implement the parsing semantics.
 *
 * @see https://tools.ietf.org/html/rfc5280#section-4.2.1.6
 */
abstract class IPAddress extends GeneralName
{
    protected function __construct(protected string $ip, protected ?string $mask = null)
    {
        parent::__construct(self::TAG_IP_ADDRESS);
    }
    /**
     * @return self
     */
    public static function fromChosenASN1(UnspecifiedType $el): GeneralName
    {
        $octets = $el->asOctetString()->string();
        return match (mb_strlen($octets, '8bit')) {
            4, 8 => IPv4Address::fromOctets($octets),
            16, 32 => IPv6Address::fromOctets($octets),
            default => throw new UnexpectedValueException('Invalid octet length for IP address.'),
        };
    }
    public function string(): string
    {
        return $this->ip . (isset($this->mask) ? '/' . $this->mask : '');
    }
    /**
     * Get IP address as a string.
     */
    public function address(): string
    {
        return $this->ip;
    }
    /**
     * Check whether mask is present.
     */
    public function hasMask(): bool
    {
        return isset($this->mask);
    }
    /**
     * Get subnet mask as a string.
     */
    public function mask(): string
    {
        if (!$this->hasMask()) {
            throw new LogicException('mask is not set.');
        }
        return $this->mask;
    }
    /**
     * Get octet representation of the IP address.
     */
    abstract protected function octets(): string;
    protected function choiceASN1(): TaggedType
    {
        return ImplicitlyTaggedType::create($this->tag, OctetString::create($this->octets()));
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\X509\GeneralName;

use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Constructed\Sequence;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Tagged\ImplicitlyTaggedType;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\TaggedType;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\UnspecifiedType;
/**
 * Implements *x400Address* CHOICE type of *GeneralName*.
 *
 * Currently acts as a parking object for decoding.
 *
 * @see https://tools.ietf.org/html/rfc5280#section-4.2.1.6
 *
 * @todo Implement ORAddress type
 */
final class X400Address extends GeneralName
{
    protected function __construct(private readonly Sequence $element)
    {
        parent::__construct(self::TAG_X400_ADDRESS);
    }
    public static function create(Sequence $element): self
    {
        return new self($element);
    }
    public static function fromChosenASN1(UnspecifiedType $el): self
    {
        return self::create($el->asSequence());
    }
    public function string(): string
    {
        return bin2hex($this->element->toDER());
    }
    protected function choiceASN1(): TaggedType
    {
        return ImplicitlyTaggedType::create($this->tag, $this->element);
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\X509\GeneralName;

use function array_slice;
use function count;
use UnexpectedValueException;
final class IPv4Address extends IPAddress
{
    public static function create(string $ip, ?string $mask = null): self
    {
        return new self($ip, $mask);
    }
    /**
     * Initialize from octets.
     */
    public static function fromOctets(string $octets): self
    {
        $mask = null;
        $bytes = unpack('C*', $octets);
        /** @var array<int, int> $bytes */
        $bytes = $bytes === \false ? [] : $bytes;
        switch (count($bytes)) {
            case 4:
                $ip = implode('.', array_map(static fn(int $v): string => (string) $v, $bytes));
                break;
            case 8:
                $ip = implode('.', array_map(static fn(int $v): string => (string) $v, array_slice($bytes, 0, 4)));
                $mask = implode('.', array_map(static fn(int $v): string => (string) $v, array_slice($bytes, 4, 4)));
                break;
            default:
                throw new UnexpectedValueException('Invalid IPv4 octet length.');
        }
        return self::create($ip, $mask);
    }
    protected function octets(): string
    {
        $bytes = array_map(intval(...), explode('.', $this->ip));
        if (isset($this->mask)) {
            $bytes = array_merge($bytes, array_map(intval(...), explode('.', $this->mask)));
        }
        return pack('C*', ...$bytes);
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\X509\GeneralName;

use ArrayIterator;
use function count;
use Countable;
use IteratorAggregate;
use LogicException;
use RuntimeException;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Constructed\Sequence;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\UnspecifiedType;
use _ContaoManager\SpomkyLabs\Pki\X501\ASN1\Name;
use UnexpectedValueException;
/**
 * Implements *GeneralNames* ASN.1 type.
 *
 * Provides convenience methods to retrieve the first value of commonly used CHOICE types.
 *
 * @see https://tools.ietf.org/html/rfc5280#section-4.2.1.6
 */
final class GeneralNames implements Countable, IteratorAggregate
{
    /**
     * GeneralName objects.
     *
     * @var GeneralName[]
     */
    private readonly array $_names;
    /**
     * @param GeneralName ...$names One or more GeneralName objects
     */
    private function __construct(GeneralName ...$names)
    {
        $this->_names = $names;
    }
    public static function create(GeneralName ...$names): self
    {
        return new self(...$names);
    }
    /**
     * Initialize from ASN.1.
     */
    public static function fromASN1(Sequence $seq): self
    {
        if (count($seq) === 0) {
            throw new UnexpectedValueException('GeneralNames must have at least one GeneralName.');
        }
        $names = array_map(static fn(UnspecifiedType $el) => GeneralName::fromASN1($el->asTagged()), $seq->elements());
        return self::create(...$names);
    }
    /**
     * Check whether GeneralNames contains a GeneralName of given type.
     *
     * @param int $tag One of `GeneralName::TAG_*` enumerations
     */
    public function has(int $tag): bool
    {
        return $this->findFirst($tag) !== null;
    }
    /**
     * Get first GeneralName of given type.
     *
     * @param int $tag One of `GeneralName::TAG_*` enumerations
     */
    public function firstOf(int $tag): GeneralName
    {
        $name = $this->findFirst($tag);
        if ($name === null) {
            throw new UnexpectedValueException("No GeneralName by tag {$tag}.");
        }
        return $name;
    }
    /**
     * Get all GeneralName objects of given type.
     *
     * @param int $tag One of `GeneralName::TAG_*` enumerations
     *
     * @return GeneralName[]
     */
    public function allOf(int $tag): array
    {
        $names = array_filter($this->_names, fn(GeneralName $name) => $name->tag() === $tag);
        return array_values($names);
    }
    /**
     * Get value of the first 'dNSName' type.
     */
    public function firstDNS(): string
    {
        $gn = $this->firstOf(GeneralName::TAG_DNS_NAME);
        if (!$gn instanceof DNSName) {
            throw new RuntimeException(DNSName::class . ' expected, got ' . $gn::class);
        }
        return $gn->name();
    }
    /**
     * Get value of the first 'directoryName' type.
     */
    public function firstDN(): Name
    {
        $gn = $this->firstOf(GeneralName::TAG_DIRECTORY_NAME);
        if (!$gn instanceof DirectoryName) {
            throw new RuntimeException(DirectoryName::class . ' expected, got ' . $gn::class);
        }
        return $gn->dn();
    }
    /**
     * Get value of the first 'uniformResourceIdentifier' type.
     */
    public function firstURI(): string
    {
        $gn = $this->firstOf(GeneralName::TAG_URI);
        if (!$gn instanceof UniformResourceIdentifier) {
            throw new RuntimeException(UniformResourceIdentifier::class . ' expected, got ' . $gn::class);
        }
        return $gn->uri();
    }
    /**
     * Generate ASN.1 structure.
     */
    public function toASN1(): Sequence
    {
        if (count($this->_names) === 0) {
            throw new LogicException('GeneralNames must have at least one GeneralName.');
        }
        $elements = array_map(static fn(GeneralName $name) => $name->toASN1(), $this->_names);
        return Sequence::create(...$elements);
    }
    /**
     * @see \Countable::count()
     */
    public function count(): int
    {
        return count($this->_names);
    }
    /**
     * Get iterator for GeneralName objects.
     *
     * @see \IteratorAggregate::getIterator()
     */
    public function getIterator(): ArrayIterator
    {
        return new ArrayIterator($this->_names);
    }
    /**
     * Find first GeneralName by given tag.
     */
    private function findFirst(int $tag): ?GeneralName
    {
        foreach ($this->_names as $name) {
            if ($name->tag() === $tag) {
                return $name;
            }
        }
        return null;
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\X509\GeneralName;

use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Primitive\IA5String;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Tagged\ImplicitlyTaggedType;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\TaggedType;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\UnspecifiedType;
/**
 * Implements *uniformResourceIdentifier* CHOICE type of *GeneralName*.
 *
 * @see https://tools.ietf.org/html/rfc5280#section-4.2.1.6
 */
final class UniformResourceIdentifier extends GeneralName
{
    private function __construct(private readonly string $uri)
    {
        parent::__construct(self::TAG_URI);
    }
    public static function create(string $uri): self
    {
        return new self($uri);
    }
    /**
     * @return self
     */
    public static function fromChosenASN1(UnspecifiedType $el): GeneralName
    {
        return self::create($el->asIA5String()->string());
    }
    public function string(): string
    {
        return $this->uri;
    }
    public function uri(): string
    {
        return $this->uri;
    }
    protected function choiceASN1(): TaggedType
    {
        return ImplicitlyTaggedType::create($this->tag, IA5String::create($this->uri));
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\X509\GeneralName;

use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Primitive\IA5String;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Tagged\ImplicitlyTaggedType;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\TaggedType;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\UnspecifiedType;
/**
 * Implements *rfc822Name* CHOICE type of *GeneralName*.
 *
 * @see https://tools.ietf.org/html/rfc5280#section-4.2.1.6
 */
final class RFC822Name extends GeneralName
{
    private function __construct(private readonly string $email)
    {
        parent::__construct(self::TAG_RFC822_NAME);
    }
    public static function create(string $email): self
    {
        return new self($email);
    }
    /**
     * @return self
     */
    public static function fromChosenASN1(UnspecifiedType $el): GeneralName
    {
        return self::create($el->asIA5String()->string());
    }
    public function string(): string
    {
        return $this->email;
    }
    public function email(): string
    {
        return $this->email;
    }
    protected function choiceASN1(): TaggedType
    {
        return ImplicitlyTaggedType::create($this->tag, IA5String::create($this->email));
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\X509\GeneralName;

use _ContaoManager\SpomkyLabs\Pki\ASN1\Element;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\TaggedType;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\UnspecifiedType;
use Stringable;
use UnexpectedValueException;
/**
 * Implements *GeneralName* CHOICE with implicit tagging.
 *
 * @see https://tools.ietf.org/html/rfc5280#section-4.2.1.6
 */
abstract class GeneralName implements Stringable
{
    // GeneralName CHOICE tags
    public const TAG_OTHER_NAME = 0;
    public const TAG_RFC822_NAME = 1;
    public const TAG_DNS_NAME = 2;
    public const TAG_X400_ADDRESS = 3;
    public const TAG_DIRECTORY_NAME = 4;
    public const TAG_EDI_PARTY_NAME = 5;
    public const TAG_URI = 6;
    public const TAG_IP_ADDRESS = 7;
    public const TAG_REGISTERED_ID = 8;
    protected function __construct(protected int $tag)
    {
    }
    /**
     * Get general name as a string.
     */
    public function __toString(): string
    {
        return $this->string();
    }
    /**
     * Get string value of the type.
     */
    abstract public function string(): string;
    /**
     * Initialize concrete object from the chosen ASN.1 element.
     */
    abstract public static function fromChosenASN1(UnspecifiedType $el): self;
    /**
     * Initialize from ASN.1.
     */
    public static function fromASN1(TaggedType $el): self
    {
        return match ($el->tag()) {
            self::TAG_OTHER_NAME => OtherName::fromChosenASN1($el->asImplicit(Element::TYPE_SEQUENCE)),
            self::TAG_RFC822_NAME => RFC822Name::fromChosenASN1($el->asImplicit(Element::TYPE_IA5_STRING)),
            self::TAG_DNS_NAME => DNSName::fromChosenASN1($el->asImplicit(Element::TYPE_IA5_STRING)),
            self::TAG_X400_ADDRESS => X400Address::fromChosenASN1($el->asImplicit(Element::TYPE_SEQUENCE)),
            self::TAG_DIRECTORY_NAME => DirectoryName::fromChosenASN1($el->asExplicit()),
            self::TAG_EDI_PARTY_NAME => EDIPartyName::fromChosenASN1($el->asImplicit(Element::TYPE_SEQUENCE)),
            self::TAG_URI => UniformResourceIdentifier::fromChosenASN1($el->asImplicit(Element::TYPE_IA5_STRING)),
            self::TAG_IP_ADDRESS => IPAddress::fromChosenASN1($el->asImplicit(Element::TYPE_OCTET_STRING)),
            self::TAG_REGISTERED_ID => RegisteredID::fromChosenASN1($el->asImplicit(Element::TYPE_OBJECT_IDENTIFIER)),
            default => throw new UnexpectedValueException('GeneralName type ' . $el->tag() . ' not supported.'),
        };
    }
    /**
     * Get type tag.
     */
    public function tag(): int
    {
        return $this->tag;
    }
    /**
     * Generate ASN.1 element.
     */
    public function toASN1(): Element
    {
        return $this->choiceASN1();
    }
    /**
     * Check whether GeneralName is equal to others.
     *
     * @param GeneralName $other GeneralName to compare to
     *
     * @return bool True if names are equal
     */
    public function equals(self $other): bool
    {
        if ($this->tag !== $other->tag) {
            return \false;
        }
        if ($this->choiceASN1()->toDER() !== $other->choiceASN1()->toDER()) {
            return \false;
        }
        return \true;
    }
    /**
     * Get ASN.1 value in GeneralName CHOICE context.
     */
    abstract protected function choiceASN1(): TaggedType;
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\X509\GeneralName;

use function array_slice;
use function count;
use function sprintf;
use UnexpectedValueException;
final class IPv6Address extends IPAddress
{
    public static function create(string $ip, ?string $mask = null): self
    {
        return new self($ip, $mask);
    }
    /**
     * Initialize from octets.
     */
    public static function fromOctets(string $octets): self
    {
        $mask = null;
        $words = unpack('n*', $octets);
        $words = $words === \false ? [] : $words;
        switch (count($words)) {
            case 8:
                $ip = self::wordsToIPv6String($words);
                break;
            case 16:
                $ip = self::wordsToIPv6String(array_slice($words, 0, 8));
                $mask = self::wordsToIPv6String(array_slice($words, 8, 8));
                break;
            default:
                throw new UnexpectedValueException('Invalid IPv6 octet length.');
        }
        return self::create($ip, $mask);
    }
    /**
     * Convert an array of 16 bit words to an IPv6 string representation.
     *
     * @param int[] $words
     */
    protected static function wordsToIPv6String(array $words): string
    {
        $groups = array_map(static fn($word) => sprintf('%04x', $word), $words);
        return implode(':', $groups);
    }
    protected function octets(): string
    {
        $words = array_map(hexdec(...), explode(':', $this->ip));
        if (isset($this->mask)) {
            $words = array_merge($words, array_map(hexdec(...), explode(':', $this->mask)));
        }
        return pack('n*', ...$words);
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\X509\GeneralName;

use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Primitive\IA5String;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Tagged\ImplicitlyTaggedType;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\TaggedType;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\UnspecifiedType;
/**
 * Implements *dNSName* CHOICE type of *GeneralName*.
 *
 * @see https://tools.ietf.org/html/rfc5280#section-4.2.1.6
 */
final class DNSName extends GeneralName
{
    /**
     * @param string $name Domain name
     */
    private function __construct(private readonly string $name)
    {
        parent::__construct(self::TAG_DNS_NAME);
    }
    public static function create(string $name): self
    {
        return new self($name);
    }
    /**
     * @return self
     */
    public static function fromChosenASN1(UnspecifiedType $el): GeneralName
    {
        return self::create($el->asIA5String()->string());
    }
    public function string(): string
    {
        return $this->name;
    }
    /**
     * Get DNS name.
     */
    public function name(): string
    {
        return $this->name;
    }
    protected function choiceASN1(): TaggedType
    {
        return ImplicitlyTaggedType::create($this->tag, IA5String::create($this->name));
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\X509\Feature;

use DateTimeImmutable;
use DateTimeZone;
use Exception;
use RuntimeException;
use UnexpectedValueException;
/**
 * Helper trait for classes employing date and time handling.
 */
trait DateTimeHelper
{
    /**
     * Create DateTime object from time string and timezone.
     *
     * @param null|string $time Time string, default to 'now'
     * @param null|string $tz Timezone, default if omitted
     */
    private static function createDateTime(?string $time = null, ?string $tz = null): DateTimeImmutable
    {
        if (!isset($time)) {
            $time = 'now';
        }
        if (!isset($tz)) {
            $tz = date_default_timezone_get();
        }
        try {
            $dt = new DateTimeImmutable($time, self::createTimeZone($tz));
            return self::roundDownFractionalSeconds($dt);
        } catch (Exception $e) {
            throw new RuntimeException('Failed to create DateTime:', 0, $e);
        }
    }
    /**
     * Rounds a \DateTimeImmutable value such that fractional seconds are removed.
     */
    private static function roundDownFractionalSeconds(DateTimeImmutable $dt): DateTimeImmutable
    {
        return DateTimeImmutable::createFromFormat('Y-m-d H:i:s', $dt->format('Y-m-d H:i:s'), $dt->getTimezone());
    }
    /**
     * Create DateTimeZone object from string.
     */
    private static function createTimeZone(string $tz): DateTimeZone
    {
        try {
            return new DateTimeZone($tz);
        } catch (Exception $e) {
            throw new UnexpectedValueException('Invalid timezone.', 0, $e);
        }
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\X509\CertificationPath\PathValidation;

use DateTimeImmutable;
use LogicException;
use _ContaoManager\Psr\Clock\ClockInterface;
use _ContaoManager\SpomkyLabs\Pki\X509\Certificate\Certificate;
use _ContaoManager\SpomkyLabs\Pki\X509\Certificate\Extension\CertificatePolicy\PolicyInformation;
/**
 * Configuration for the certification path validation process.
 *
 * @see https://tools.ietf.org/html/rfc5280#section-6.1.1
 */
final class PathValidationConfig
{
    /**
     * List of acceptable policy identifiers.
     *
     * @var string[]
     */
    private array $policySet;
    /**
     * Trust anchor certificate.
     *
     * If not set, path validation uses the first certificate of the path.
     */
    private ?Certificate $trustAnchor = null;
    /**
     * Whether policy mapping in inhibited.
     *
     * Setting this to true disallows policy mapping.
     */
    private bool $policyMappingInhibit;
    /**
     * Whether the path must be valid for at least one policy in the initial policy set.
     */
    private bool $explicitPolicy;
    /**
     * Whether anyPolicy OID processing should be inhibited.
     *
     * Setting this to true disallows the usage of anyPolicy.
     */
    private bool $anyPolicyInhibit;
    /**
     * @param DateTimeImmutable $dateTime Reference date and time
     * @param int $maxLength Maximum certification path length
     */
    private function __construct(private DateTimeImmutable $dateTime, private int $maxLength)
    {
        $this->policySet = [PolicyInformation::OID_ANY_POLICY];
        $this->policyMappingInhibit = \false;
        $this->explicitPolicy = \false;
        $this->anyPolicyInhibit = \false;
    }
    public static function create(DateTimeImmutable $dateTime, int $maxLength): self
    {
        return new self($dateTime, $maxLength);
    }
    /**
     * Get default configuration.
     */
    public static function defaultConfig(?ClockInterface $clock = null): self
    {
        $dateTime = $clock !== null ? $clock->now() : new DateTimeImmutable();
        return self::create($dateTime, 3);
    }
    /**
     * Get self with maximum path length.
     */
    public function withMaxLength(int $length): self
    {
        $obj = clone $this;
        $obj->maxLength = $length;
        return $obj;
    }
    /**
     * Get self with reference date and time.
     */
    public function withDateTime(DateTimeImmutable $dt): self
    {
        $obj = clone $this;
        $obj->dateTime = $dt;
        return $obj;
    }
    /**
     * Get self with trust anchor certificate.
     */
    public function withTrustAnchor(Certificate $ca): self
    {
        $obj = clone $this;
        $obj->trustAnchor = $ca;
        return $obj;
    }
    /**
     * Get self with initial-policy-mapping-inhibit set.
     */
    public function withPolicyMappingInhibit(bool $flag): self
    {
        $obj = clone $this;
        $obj->policyMappingInhibit = $flag;
        return $obj;
    }
    /**
     * Get self with initial-explicit-policy set.
     */
    public function withExplicitPolicy(bool $flag): self
    {
        $obj = clone $this;
        $obj->explicitPolicy = $flag;
        return $obj;
    }
    /**
     * Get self with initial-any-policy-inhibit set.
     */
    public function withAnyPolicyInhibit(bool $flag): self
    {
        $obj = clone $this;
        $obj->anyPolicyInhibit = $flag;
        return $obj;
    }
    /**
     * Get self with user-initial-policy-set set to policy OIDs.
     *
     * @param string ...$policies List of policy OIDs
     */
    public function withPolicySet(string ...$policies): self
    {
        $obj = clone $this;
        $obj->policySet = $policies;
        return $obj;
    }
    /**
     * Get maximum certification path length.
     */
    public function maxLength(): int
    {
        return $this->maxLength;
    }
    /**
     * Get reference date and time.
     */
    public function dateTime(): DateTimeImmutable
    {
        return $this->dateTime;
    }
    /**
     * Get user-initial-policy-set.
     *
     * @return string[] Array of OID's
     */
    public function policySet(): array
    {
        return $this->policySet;
    }
    /**
     * Check whether trust anchor certificate is set.
     */
    public function hasTrustAnchor(): bool
    {
        return isset($this->trustAnchor);
    }
    /**
     * Get trust anchor certificate.
     */
    public function trustAnchor(): Certificate
    {
        if (!$this->hasTrustAnchor()) {
            throw new LogicException('No trust anchor.');
        }
        return $this->trustAnchor;
    }
    public function policyMappingInhibit(): bool
    {
        return $this->policyMappingInhibit;
    }
    public function explicitPolicy(): bool
    {
        return $this->explicitPolicy;
    }
    public function anyPolicyInhibit(): bool
    {
        return $this->anyPolicyInhibit;
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\X509\CertificationPath\PathValidation;

use function count;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Element;
use _ContaoManager\SpomkyLabs\Pki\CryptoTypes\AlgorithmIdentifier\Feature\AlgorithmIdentifierType;
use _ContaoManager\SpomkyLabs\Pki\CryptoTypes\Asymmetric\PublicKeyInfo;
use _ContaoManager\SpomkyLabs\Pki\X509\Certificate\Certificate;
use _ContaoManager\SpomkyLabs\Pki\X509\Certificate\Extension\CertificatePolicy\PolicyInformation;
use _ContaoManager\SpomkyLabs\Pki\X509\CertificationPath\Policy\PolicyTree;
/**
 * Result of the path validation process.
 *
 * @see https://tools.ietf.org/html/rfc5280#section-6.1.6
 */
final class PathValidationResult
{
    /**
     * Certificates in a certification path.
     *
     * @var Certificate[]
     */
    private readonly array $certificates;
    /**
     * @param Certificate[] $certificates
     */
    private function __construct(array $certificates, private readonly ?PolicyTree $policyTree, private readonly PublicKeyInfo $publicKeyInfo, private readonly AlgorithmIdentifierType $publicKeyAlgo, private readonly ?Element $publicKeyParameters)
    {
        $this->certificates = array_values($certificates);
    }
    /**
     * @param Certificate[] $certificates Certificates in a certification path
     * @param null|PolicyTree $policyTree Valid policy tree
     * @param PublicKeyInfo $publicKeyInfo Public key of the end-entity certificate
     * @param AlgorithmIdentifierType $publicKeyAlgo Public key algorithm of the end-entity certificate
     * @param null|Element $publicKeyParameters Algorithm parameters
     */
    public static function create(array $certificates, ?PolicyTree $policyTree, PublicKeyInfo $publicKeyInfo, AlgorithmIdentifierType $publicKeyAlgo, ?Element $publicKeyParameters = null): self
    {
        return new self($certificates, $policyTree, $publicKeyInfo, $publicKeyAlgo, $publicKeyParameters);
    }
    public function getPolicyTree(): ?PolicyTree
    {
        return $this->policyTree;
    }
    public function getPublicKeyInfo(): PublicKeyInfo
    {
        return $this->publicKeyInfo;
    }
    public function getPublicKeyAlgo(): AlgorithmIdentifierType
    {
        return $this->publicKeyAlgo;
    }
    public function getPublicKeyParameters(): ?Element
    {
        return $this->publicKeyParameters;
    }
    /**
     * Get end-entity certificate.
     */
    public function certificate(): Certificate
    {
        return $this->certificates[count($this->certificates) - 1];
    }
    /**
     * Get certificate policies of the end-entity certificate.
     *
     * @return PolicyInformation[]
     */
    public function policies(): array
    {
        if ($this->policyTree === null) {
            return [];
        }
        return $this->policyTree->policiesAtDepth(count($this->certificates));
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\X509\CertificationPath\PathValidation;

use LogicException;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Element;
use _ContaoManager\SpomkyLabs\Pki\CryptoTypes\AlgorithmIdentifier\Feature\AlgorithmIdentifierType;
use _ContaoManager\SpomkyLabs\Pki\CryptoTypes\AlgorithmIdentifier\Feature\SignatureAlgorithmIdentifier;
use _ContaoManager\SpomkyLabs\Pki\CryptoTypes\Asymmetric\PublicKeyInfo;
use _ContaoManager\SpomkyLabs\Pki\X501\ASN1\Name;
use _ContaoManager\SpomkyLabs\Pki\X509\Certificate\Certificate;
use _ContaoManager\SpomkyLabs\Pki\X509\CertificationPath\Policy\PolicyNode;
use _ContaoManager\SpomkyLabs\Pki\X509\CertificationPath\Policy\PolicyTree;
/**
 * State class for the certification path validation process.
 *
 * @see https://tools.ietf.org/html/rfc5280#section-6.1.1
 * @see https://tools.ietf.org/html/rfc5280#section-6.1.2
 */
final class ValidatorState
{
    /**
     * Length of the certification path (n).
     */
    private ?int $_pathLength = null;
    /**
     * Current index in the certification path in the range of 1..n (i).
     */
    private ?int $_index = null;
    /**
     * Valid policy tree (valid_policy_tree).
     *
     * A tree of certificate policies with their optional qualifiers. Each of the leaves of the tree represents a valid
     * policy at this stage in the certification path validation. Once the tree is set to NULL, policy processing
     * ceases.
     */
    private ?PolicyTree $_validPolicyTree = null;
    /**
     * Permitted subtrees (permitted_subtrees).
     *
     * A set of root names for each name type defining a set of subtrees within which all subject names in subsequent
     * certificates in the certification path must fall.
     */
    private mixed $_permittedSubtrees = null;
    /**
     * Excluded subtrees (excluded_subtrees).
     *
     * A set of root names for each name type defining a set of subtrees within which no subject name in subsequent
     * certificates in the certification path may fall.
     */
    private mixed $_excludedSubtrees = null;
    /**
     * Explicit policy (explicit_policy).
     *
     * An integer that indicates if a non-NULL valid_policy_tree is required.
     */
    private ?int $_explicitPolicy = null;
    /**
     * Inhibit anyPolicy (inhibit_anyPolicy).
     *
     * An integer that indicates whether the anyPolicy policy identifier is considered a match.
     */
    private ?int $_inhibitAnyPolicy = null;
    /**
     * Policy mapping (policy_mapping).
     *
     * An integer that indicates if policy mapping is permitted.
     */
    private ?int $_policyMapping = null;
    /**
     * Working public key algorithm (working_public_key_algorithm).
     *
     * The digital signature algorithm used to verify the signature of a certificate.
     */
    private SignatureAlgorithmIdentifier|AlgorithmIdentifierType|null $_workingPublicKeyAlgorithm = null;
    /**
     * Working public key (working_public_key).
     *
     * The public key used to verify the signature of a certificate.
     */
    private ?PublicKeyInfo $_workingPublicKey = null;
    /**
     * Working public key parameters (working_public_key_parameters).
     *
     * Parameters associated with the current public key that may be required to verify a signature.
     */
    private ?Element $_workingPublicKeyParameters = null;
    /**
     * Working issuer name (working_issuer_name).
     *
     * The issuer distinguished name expected in the next certificate in the chain.
     */
    private ?Name $_workingIssuerName = null;
    /**
     * Maximum certification path length (max_path_length).
     */
    private ?int $_maxPathLength = null;
    private function __construct()
    {
    }
    /**
     * Initialize variables according to RFC 5280 6.1.2.
     *
     * @see https://tools.ietf.org/html/rfc5280#section-6.1.2
     *
     * @param Certificate $trust_anchor Trust anchor certificate
     * @param int $n Number of certificates
     * in the certification path
     */
    public static function initialize(PathValidationConfig $config, Certificate $trust_anchor, int $n): self
    {
        $state = new self();
        $state->_pathLength = $n;
        $state->_index = 1;
        $state->_validPolicyTree = PolicyTree::create(PolicyNode::anyPolicyNode());
        $state->_permittedSubtrees = null;
        $state->_excludedSubtrees = null;
        $state->_explicitPolicy = $config->explicitPolicy() ? 0 : $n + 1;
        $state->_inhibitAnyPolicy = $config->anyPolicyInhibit() ? 0 : $n + 1;
        $state->_policyMapping = $config->policyMappingInhibit() ? 0 : $n + 1;
        $state->_workingPublicKeyAlgorithm = $trust_anchor->signatureAlgorithm();
        $tbsCert = $trust_anchor->tbsCertificate();
        $state->_workingPublicKey = $tbsCert->subjectPublicKeyInfo();
        $state->_workingPublicKeyParameters = self::getAlgorithmParameters($state->_workingPublicKey->algorithmIdentifier());
        $state->_workingIssuerName = $tbsCert->subject();
        $state->_maxPathLength = $config->maxLength();
        return $state;
    }
    /**
     * Get self with current certification path index set.
     */
    public function withIndex(int $index): self
    {
        $state = clone $this;
        $state->_index = $index;
        return $state;
    }
    /**
     * Get self with valid_policy_tree.
     */
    public function withValidPolicyTree(PolicyTree $policy_tree): self
    {
        $state = clone $this;
        $state->_validPolicyTree = $policy_tree;
        return $state;
    }
    /**
     * Get self with valid_policy_tree set to null.
     */
    public function withoutValidPolicyTree(): self
    {
        $state = clone $this;
        $state->_validPolicyTree = null;
        return $state;
    }
    /**
     * Get self with explicit_policy.
     */
    public function withExplicitPolicy(int $num): self
    {
        $state = clone $this;
        $state->_explicitPolicy = $num;
        return $state;
    }
    /**
     * Get self with inhibit_anyPolicy.
     */
    public function withInhibitAnyPolicy(int $num): self
    {
        $state = clone $this;
        $state->_inhibitAnyPolicy = $num;
        return $state;
    }
    /**
     * Get self with policy_mapping.
     */
    public function withPolicyMapping(int $num): self
    {
        $state = clone $this;
        $state->_policyMapping = $num;
        return $state;
    }
    /**
     * Get self with working_public_key_algorithm.
     */
    public function withWorkingPublicKeyAlgorithm(AlgorithmIdentifierType $algo): self
    {
        $state = clone $this;
        $state->_workingPublicKeyAlgorithm = $algo;
        return $state;
    }
    /**
     * Get self with working_public_key.
     */
    public function withWorkingPublicKey(PublicKeyInfo $pubkey_info): self
    {
        $state = clone $this;
        $state->_workingPublicKey = $pubkey_info;
        return $state;
    }
    /**
     * Get self with working_public_key_parameters.
     */
    public function withWorkingPublicKeyParameters(?Element $params = null): self
    {
        $state = clone $this;
        $state->_workingPublicKeyParameters = $params;
        return $state;
    }
    /**
     * Get self with working_issuer_name.
     */
    public function withWorkingIssuerName(Name $issuer): self
    {
        $state = clone $this;
        $state->_workingIssuerName = $issuer;
        return $state;
    }
    /**
     * Get self with max_path_length.
     */
    public function withMaxPathLength(int $length): self
    {
        $state = clone $this;
        $state->_maxPathLength = $length;
        return $state;
    }
    /**
     * Get the certification path length (n).
     */
    public function pathLength(): int
    {
        return $this->_pathLength;
    }
    /**
     * Get the current index in certification path in the range of 1..n.
     */
    public function index(): int
    {
        return $this->_index;
    }
    /**
     * Check whether valid_policy_tree is present.
     */
    public function hasValidPolicyTree(): bool
    {
        return isset($this->_validPolicyTree);
    }
    public function validPolicyTree(): PolicyTree
    {
        if (!$this->hasValidPolicyTree()) {
            throw new LogicException('valid_policy_tree not set.');
        }
        return $this->_validPolicyTree;
    }
    public function permittedSubtrees(): mixed
    {
        return $this->_permittedSubtrees;
    }
    public function excludedSubtrees(): mixed
    {
        return $this->_excludedSubtrees;
    }
    public function explicitPolicy(): int
    {
        return $this->_explicitPolicy;
    }
    public function inhibitAnyPolicy(): int
    {
        return $this->_inhibitAnyPolicy;
    }
    public function policyMapping(): int
    {
        return $this->_policyMapping;
    }
    public function workingPublicKeyAlgorithm(): AlgorithmIdentifierType
    {
        return $this->_workingPublicKeyAlgorithm;
    }
    public function workingPublicKey(): PublicKeyInfo
    {
        return $this->_workingPublicKey;
    }
    public function workingPublicKeyParameters(): ?Element
    {
        return $this->_workingPublicKeyParameters;
    }
    public function workingIssuerName(): Name
    {
        return $this->_workingIssuerName;
    }
    /**
     * Get maximum certification path length.
     */
    public function maxPathLength(): int
    {
        return $this->_maxPathLength;
    }
    /**
     * Check whether processing the final certificate of the certification path.
     */
    public function isFinal(): bool
    {
        return $this->_index === $this->_pathLength;
    }
    /**
     * Get the path validation result.
     *
     * @param Certificate[] $certificates Certificates in a certification path
     */
    public function getResult(array $certificates): PathValidationResult
    {
        return PathValidationResult::create($certificates, $this->_validPolicyTree, $this->_workingPublicKey, $this->_workingPublicKeyAlgorithm, $this->_workingPublicKeyParameters);
    }
    /**
     * Get ASN.1 parameters from algorithm identifier.
     *
     * @return null|Element ASN.1 element or null if parameters are omitted
     */
    public static function getAlgorithmParameters(AlgorithmIdentifierType $algo): ?Element
    {
        $seq = $algo->toASN1();
        return $seq->has(1) ? $seq->at(1)->asElement() : null;
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\X509\CertificationPath\PathValidation;

use function count;
use function in_array;
use LogicException;
use RuntimeException;
use _ContaoManager\SpomkyLabs\Pki\CryptoBridge\Crypto;
use _ContaoManager\SpomkyLabs\Pki\X509\Certificate\Certificate;
use _ContaoManager\SpomkyLabs\Pki\X509\Certificate\Extension\CertificatePolicy\PolicyInformation;
use _ContaoManager\SpomkyLabs\Pki\X509\Certificate\TBSCertificate;
use _ContaoManager\SpomkyLabs\Pki\X509\CertificationPath\Exception\PathValidationException;
/**
 * Implements certification path validation.
 *
 * @see https://tools.ietf.org/html/rfc5280#section-6
 */
final class PathValidator
{
    /**
     * Certification path.
     *
     * @var Certificate[]
     */
    private readonly array $certificates;
    /**
     * Certification path trust anchor.
     */
    private ?Certificate $trustAnchor = null;
    /**
     * @param Crypto $crypto Crypto engine
     * @param PathValidationConfig $config Validation config
     * @param Certificate ...$certificates Certificates from the trust anchor to
     * the end-entity certificate
     */
    private function __construct(private readonly Crypto $crypto, private readonly PathValidationConfig $config, Certificate ...$certificates)
    {
        if (count($certificates) === 0) {
            throw new LogicException('No certificates.');
        }
        $this->certificates = $certificates;
        // if trust anchor is explicitly given in configuration
        if ($config->hasTrustAnchor()) {
            $this->trustAnchor = $config->trustAnchor();
        } else {
            $this->trustAnchor = $certificates[0];
        }
    }
    public static function create(Crypto $crypto, PathValidationConfig $config, Certificate ...$certificates): self
    {
        return new self($crypto, $config, ...$certificates);
    }
    /**
     * Validate certification path.
     */
    public function validate(): PathValidationResult
    {
        $n = count($this->certificates);
        $state = ValidatorState::initialize($this->config, $this->trustAnchor, $n);
        foreach ($this->certificates as $i => $iValue) {
            $state = $state->withIndex($i + 1);
            $cert = $iValue;
            // process certificate (section 6.1.3.)
            $state = $this->processCertificate($state, $cert);
            if (!$state->isFinal()) {
                // prepare next certificate (section 6.1.4.)
                $state = $this->prepareNext($state, $cert);
            }
        }
        if (!isset($cert)) {
            throw new LogicException('No certificates.');
        }
        // wrap-up (section 6.1.5.)
        $state = $this->wrapUp($state, $cert);
        // return outputs
        return $state->getResult($this->certificates);
    }
    /**
     * Apply basic certificate processing according to RFC 5280 section 6.1.3.
     *
     * @see https://tools.ietf.org/html/rfc5280#section-6.1.3
     */
    private function processCertificate(ValidatorState $state, Certificate $cert): ValidatorState
    {
        // (a.1) verify signature
        $this->verifySignature($state, $cert);
        // (a.2) check validity period
        $this->checkValidity($cert);
        // (a.3) check that certificate is not revoked
        $this->checkRevocation();
        // (a.4) check issuer
        $this->checkIssuer($state, $cert);
        // (b)(c) if certificate is self-issued and it is not
        // the final certificate in the path, skip this step
        if (!($cert->isSelfIssued() && !$state->isFinal())) {
            // (b) check permitted subtrees
            $this->checkPermittedSubtrees($state);
            // (c) check excluded subtrees
            $this->checkExcludedSubtrees($state);
        }
        $extensions = $cert->tbsCertificate()->extensions();
        if ($extensions->hasCertificatePolicies()) {
            // (d) process policy information
            if ($state->hasValidPolicyTree()) {
                $state = $state->validPolicyTree()->processPolicies($state, $cert);
            }
        } else {
            // (e) certificate policies extension not present,
            // set the valid_policy_tree to NULL
            $state = $state->withoutValidPolicyTree();
        }
        // (f) check that explicit_policy > 0 or valid_policy_tree is set
        if (!($state->explicitPolicy() > 0 || $state->hasValidPolicyTree())) {
            throw new PathValidationException('No valid policies.');
        }
        return $state;
    }
    /**
     * Apply preparation for the certificate i+1 according to rfc5280 section 6.1.4.
     *
     * @see https://tools.ietf.org/html/rfc5280#section-6.1.4
     */
    private function prepareNext(ValidatorState $state, Certificate $cert): ValidatorState
    {
        // (a)(b) if policy mappings extension is present
        $state = $this->preparePolicyMappings($state, $cert);
        // (c) assign working_issuer_name
        $state = $state->withWorkingIssuerName($cert->tbsCertificate()->subject());
        // (d)(e)(f)
        $state = $this->setPublicKeyState($state, $cert);
        // (g) if name constraints extension is present
        $state = $this->prepareNameConstraints($state, $cert);
        // (h) if certificate is not self-issued
        if (!$cert->isSelfIssued()) {
            $state = $this->prepareNonSelfIssued($state);
        }
        // (i) if policy constraints extension is present
        $state = $this->preparePolicyConstraints($state, $cert);
        // (j) if inhibit any policy extension is present
        $state = $this->prepareInhibitAnyPolicy($state, $cert);
        // (k) check basic constraints
        $this->processBasicContraints($cert);
        // (l) verify max_path_length
        $state = $this->verifyMaxPathLength($state, $cert);
        // (m) check pathLenContraint
        $state = $this->processPathLengthContraint($state, $cert);
        // (n) check key usage
        $this->checkKeyUsage($cert);
        // (o) process relevant extensions
        return $this->processExtensions($state);
    }
    /**
     * Apply wrap-up procedure according to RFC 5280 section 6.1.5.
     *
     * @see https://tools.ietf.org/html/rfc5280#section-6.1.5
     */
    private function wrapUp(ValidatorState $state, Certificate $cert): ValidatorState
    {
        $tbs_cert = $cert->tbsCertificate();
        $extensions = $tbs_cert->extensions();
        // (a)
        if ($state->explicitPolicy() > 0) {
            $state = $state->withExplicitPolicy($state->explicitPolicy() - 1);
        }
        // (b)
        if ($extensions->hasPolicyConstraints()) {
            $ext = $extensions->policyConstraints();
            if ($ext->hasRequireExplicitPolicy() && $ext->requireExplicitPolicy() === 0) {
                $state = $state->withExplicitPolicy(0);
            }
        }
        // (c)(d)(e)
        $state = $this->setPublicKeyState($state, $cert);
        // (f) process relevant extensions
        $state = $this->processExtensions($state);
        // (g) intersection of valid_policy_tree and the initial-policy-set
        $state = $this->calculatePolicyIntersection($state);
        // check that explicit_policy > 0 or valid_policy_tree is set
        if (!($state->explicitPolicy() > 0 || $state->hasValidPolicyTree())) {
            throw new PathValidationException('No valid policies.');
        }
        // path validation succeeded
        return $state;
    }
    /**
     * Update working_public_key, working_public_key_parameters and working_public_key_algorithm state variables from
     * certificate.
     */
    private function setPublicKeyState(ValidatorState $state, Certificate $cert): ValidatorState
    {
        $pk_info = $cert->tbsCertificate()->subjectPublicKeyInfo();
        // assign working_public_key
        $state = $state->withWorkingPublicKey($pk_info);
        // assign working_public_key_parameters
        $params = ValidatorState::getAlgorithmParameters($pk_info->algorithmIdentifier());
        if ($params !== null) {
            $state = $state->withWorkingPublicKeyParameters($params);
        } else if ($pk_info->algorithmIdentifier()->oid() !== $state->workingPublicKeyAlgorithm()->oid()) {
            $state = $state->withWorkingPublicKeyParameters();
        }
        // assign working_public_key_algorithm
        return $state->withWorkingPublicKeyAlgorithm($pk_info->algorithmIdentifier());
    }
    /**
     * Verify certificate signature.
     */
    private function verifySignature(ValidatorState $state, Certificate $cert): void
    {
        try {
            $valid = $cert->verify($state->workingPublicKey(), $this->crypto);
        } catch (RuntimeException $e) {
            throw new PathValidationException('Failed to verify signature: ' . $e->getMessage(), 0, $e);
        }
        if (!$valid) {
            throw new PathValidationException("Certificate signature doesn't match.");
        }
    }
    /**
     * Check certificate validity.
     */
    private function checkValidity(Certificate $cert): void
    {
        $refdt = $this->config->dateTime();
        $validity = $cert->tbsCertificate()->validity();
        if ($validity->notBefore()->dateTime()->diff($refdt)->invert !== 0) {
            throw new PathValidationException('Certificate validity period has not started.');
        }
        if ($refdt->diff($validity->notAfter()->dateTime())->invert !== 0) {
            throw new PathValidationException('Certificate has expired.');
        }
    }
    /**
     * Check certificate revocation.
     */
    private function checkRevocation(): void
    {
        // @todo Implement CRL handling
    }
    /**
     * Check certificate issuer.
     */
    private function checkIssuer(ValidatorState $state, Certificate $cert): void
    {
        if (!$cert->tbsCertificate()->issuer()->equals($state->workingIssuerName())) {
            throw new PathValidationException('Certification issuer mismatch.');
        }
    }
    private function checkPermittedSubtrees(ValidatorState $state): void
    {
        // @todo Implement
        $state->permittedSubtrees();
    }
    private function checkExcludedSubtrees(ValidatorState $state): void
    {
        // @todo Implement
        $state->excludedSubtrees();
    }
    /**
     * Apply policy mappings handling for the preparation step.
     */
    private function preparePolicyMappings(ValidatorState $state, Certificate $cert): ValidatorState
    {
        $extensions = $cert->tbsCertificate()->extensions();
        if ($extensions->hasPolicyMappings()) {
            // (a) verify that anyPolicy mapping is not used
            if ($extensions->policyMappings()->hasAnyPolicyMapping()) {
                throw new PathValidationException('anyPolicy mapping found.');
            }
            // (b) process policy mappings
            if ($state->hasValidPolicyTree()) {
                $state = $state->validPolicyTree()->processMappings($state, $cert);
            }
        }
        return $state;
    }
    /**
     * Apply name constraints handling for the preparation step.
     */
    private function prepareNameConstraints(ValidatorState $state, Certificate $cert): ValidatorState
    {
        $extensions = $cert->tbsCertificate()->extensions();
        if ($extensions->hasNameConstraints()) {
            $state = $this->processNameConstraints($state);
        }
        return $state;
    }
    /**
     * Apply preparation for a non-self-signed certificate.
     */
    private function prepareNonSelfIssued(ValidatorState $state): ValidatorState
    {
        // (h.1)
        if ($state->explicitPolicy() > 0) {
            $state = $state->withExplicitPolicy($state->explicitPolicy() - 1);
        }
        // (h.2)
        if ($state->policyMapping() > 0) {
            $state = $state->withPolicyMapping($state->policyMapping() - 1);
        }
        // (h.3)
        if ($state->inhibitAnyPolicy() > 0) {
            $state = $state->withInhibitAnyPolicy($state->inhibitAnyPolicy() - 1);
        }
        return $state;
    }
    /**
     * Apply policy constraints handling for the preparation step.
     */
    private function preparePolicyConstraints(ValidatorState $state, Certificate $cert): ValidatorState
    {
        $extensions = $cert->tbsCertificate()->extensions();
        if (!$extensions->hasPolicyConstraints()) {
            return $state;
        }
        $ext = $extensions->policyConstraints();
        // (i.1)
        if ($ext->hasRequireExplicitPolicy() && $ext->requireExplicitPolicy() < $state->explicitPolicy()) {
            $state = $state->withExplicitPolicy($ext->requireExplicitPolicy());
        }
        // (i.2)
        if ($ext->hasInhibitPolicyMapping() && $ext->inhibitPolicyMapping() < $state->policyMapping()) {
            $state = $state->withPolicyMapping($ext->inhibitPolicyMapping());
        }
        return $state;
    }
    /**
     * Apply inhibit any-policy handling for the preparation step.
     */
    private function prepareInhibitAnyPolicy(ValidatorState $state, Certificate $cert): ValidatorState
    {
        $extensions = $cert->tbsCertificate()->extensions();
        if ($extensions->hasInhibitAnyPolicy()) {
            $ext = $extensions->inhibitAnyPolicy();
            if ($ext->skipCerts() < $state->inhibitAnyPolicy()) {
                $state = $state->withInhibitAnyPolicy($ext->skipCerts());
            }
        }
        return $state;
    }
    /**
     * Verify maximum certification path length for the preparation step.
     */
    private function verifyMaxPathLength(ValidatorState $state, Certificate $cert): ValidatorState
    {
        if (!$cert->isSelfIssued()) {
            if ($state->maxPathLength() <= 0) {
                throw new PathValidationException('Certification path length exceeded.');
            }
            $state = $state->withMaxPathLength($state->maxPathLength() - 1);
        }
        return $state;
    }
    /**
     * Check key usage extension for the preparation step.
     */
    private function checkKeyUsage(Certificate $cert): void
    {
        $extensions = $cert->tbsCertificate()->extensions();
        if ($extensions->hasKeyUsage()) {
            $ext = $extensions->keyUsage();
            if (!$ext->isKeyCertSign()) {
                throw new PathValidationException('keyCertSign usage not set.');
            }
        }
    }
    private function processNameConstraints(ValidatorState $state): ValidatorState
    {
        // @todo Implement
        return $state;
    }
    /**
     * Process basic constraints extension.
     */
    private function processBasicContraints(Certificate $cert): void
    {
        if ($cert->tbsCertificate()->version() === TBSCertificate::VERSION_3) {
            $extensions = $cert->tbsCertificate()->extensions();
            if (!$extensions->hasBasicConstraints()) {
                throw new PathValidationException('v3 certificate must have basicConstraints extension.');
            }
            // verify that cA is set to TRUE
            if (!$extensions->basicConstraints()->isCA()) {
                throw new PathValidationException('Certificate is not a CA certificate.');
            }
        }
    }
    /**
     * Process pathLenConstraint.
     */
    private function processPathLengthContraint(ValidatorState $state, Certificate $cert): ValidatorState
    {
        $extensions = $cert->tbsCertificate()->extensions();
        if ($extensions->hasBasicConstraints()) {
            $ext = $extensions->basicConstraints();
            if ($ext->hasPathLen()) {
                if ($ext->pathLen() < $state->maxPathLength()) {
                    $state = $state->withMaxPathLength($ext->pathLen());
                }
            }
        }
        return $state;
    }
    private function processExtensions(ValidatorState $state): ValidatorState
    {
        // @todo Implement
        return $state;
    }
    private function calculatePolicyIntersection(ValidatorState $state): ValidatorState
    {
        // (i) If the valid_policy_tree is NULL, the intersection is NULL
        if (!$state->hasValidPolicyTree()) {
            return $state;
        }
        // (ii) If the valid_policy_tree is not NULL and
        // the user-initial-policy-set is any-policy, the intersection
        // is the entire valid_policy_tree
        $initial_policies = $this->config->policySet();
        if (in_array(PolicyInformation::OID_ANY_POLICY, $initial_policies, \true)) {
            return $state;
        }
        // (iii) If the valid_policy_tree is not NULL and the
        // user-initial-policy-set is not any-policy, calculate
        // the intersection of the valid_policy_tree and the
        // user-initial-policy-set as follows
        return $state->validPolicyTree()->calculateIntersection($state, $initial_policies);
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\X509\CertificationPath\PathBuilding;

use function count;
use _ContaoManager\SpomkyLabs\Pki\X509\Certificate\Certificate;
use _ContaoManager\SpomkyLabs\Pki\X509\Certificate\CertificateBundle;
use _ContaoManager\SpomkyLabs\Pki\X509\CertificationPath\CertificationPath;
use _ContaoManager\SpomkyLabs\Pki\X509\CertificationPath\Exception\PathBuildingException;
/**
 * Class for resolving certification paths.
 *
 * @see https://tools.ietf.org/html/rfc4158
 */
final class CertificationPathBuilder
{
    /**
     * @param CertificateBundle $trustList List of trust anchors
     */
    private function __construct(private readonly CertificateBundle $trustList)
    {
    }
    public static function create(CertificateBundle $trustList): self
    {
        return new self($trustList);
    }
    /**
     * Get all certification paths to given target certificate from any trust anchor.
     *
     * @param Certificate $target Target certificate
     * @param null|CertificateBundle $intermediate Optional intermediate certificates
     *
     * @return CertificationPath[]
     */
    public function allPathsToTarget(Certificate $target, ?CertificateBundle $intermediate = null): array
    {
        $paths = $this->resolvePathsToTarget($target, $intermediate);
        // map paths to CertificationPath objects
        return array_map(static fn($certs) => CertificationPath::create(...$certs), $paths);
    }
    /**
     * Get the shortest path to given target certificate from any trust anchor.
     *
     * @param Certificate $target Target certificate
     * @param null|CertificateBundle $intermediate Optional intermediate certificates
     */
    public function shortestPathToTarget(Certificate $target, ?CertificateBundle $intermediate = null): CertificationPath
    {
        $paths = $this->allPathsToTarget($target, $intermediate);
        if (count($paths) === 0) {
            throw new PathBuildingException('No certification paths.');
        }
        usort($paths, fn($a, $b) => count($a) < count($b) ? -1 : 1);
        return reset($paths);
    }
    /**
     * Find all issuers of the target certificate from a given bundle.
     *
     * @param Certificate $target Target certificate
     * @param CertificateBundle $bundle Certificates to search
     *
     * @return Certificate[]
     */
    private function findIssuers(Certificate $target, CertificateBundle $bundle): array
    {
        $issuers = [];
        $issuer_name = $target->tbsCertificate()->issuer();
        $extensions = $target->tbsCertificate()->extensions();
        // find by authority key identifier
        if ($extensions->hasAuthorityKeyIdentifier()) {
            $ext = $extensions->authorityKeyIdentifier();
            if ($ext->hasKeyIdentifier()) {
                foreach ($bundle->allBySubjectKeyIdentifier($ext->keyIdentifier()) as $issuer) {
                    // check that issuer name matches
                    if ($issuer->tbsCertificate()->subject()->equals($issuer_name)) {
                        $issuers[] = $issuer;
                    }
                }
            }
        }
        return $issuers;
    }
    /**
     * Resolve all possible certification paths from any trust anchor to the target certificate, using optional
     * intermediate certificates.
     *
     * Helper method for allPathsToTarget to be called recursively.
     *
     * @return array<int, array<Certificate>> Array of arrays containing path certificates
     * @todo Implement loop detection
     */
    private function resolvePathsToTarget(Certificate $target, ?CertificateBundle $intermediate = null): array
    {
        // array of possible paths
        $paths = [];
        // signed by certificate in the trust list
        foreach ($this->findIssuers($target, $this->trustList) as $issuer) {
            // if target is self-signed, path consists of only
            // the target certificate
            if ($target->equals($issuer)) {
                $paths[] = [$target];
            } else {
                $paths[] = [$issuer, $target];
            }
        }
        if (isset($intermediate)) {
            // signed by intermediate certificate
            foreach ($this->findIssuers($target, $intermediate) as $issuer) {
                // intermediate certificate must not be self-signed
                if ($issuer->isSelfIssued()) {
                    continue;
                }
                // resolve paths to issuer
                $subpaths = $this->resolvePathsToTarget($issuer, $intermediate);
                foreach ($subpaths as $path) {
                    $paths[] = array_merge($path, [$target]);
                }
            }
        }
        return $paths;
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\X509\CertificationPath\Exception;

use RuntimeException;
/**
 * Exception thrown on certification path building errors.
 */
final class PathBuildingException extends RuntimeException
{
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\X509\CertificationPath\Exception;

use _ContaoManager\SpomkyLabs\Pki\X509\Exception\X509ValidationException;
/**
 * Exception thrown on certification path validation errors.
 */
final class PathValidationException extends X509ValidationException
{
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\X509\CertificationPath\Policy;

use ArrayIterator;
use function count;
use Countable;
use function in_array;
use IteratorAggregate;
use _ContaoManager\SpomkyLabs\Pki\X509\Certificate\Extension\CertificatePolicy\PolicyInformation;
use _ContaoManager\SpomkyLabs\Pki\X509\Certificate\Extension\CertificatePolicy\PolicyQualifierInfo;
/**
 * Policy node class for certification path validation.
 *
 * @internal Mutable class used by PolicyTree
 *
 * @see https://tools.ietf.org/html/rfc5280#section-6.1.2
 */
final class PolicyNode implements IteratorAggregate, Countable
{
    /**
     * List of child nodes.
     *
     * @var PolicyNode[]
     */
    private array $children;
    /**
     * Reference to the parent node.
     */
    private PolicyNode|null $parent = null;
    /**
     * @param PolicyQualifierInfo[] $qualifiers
     * @param string[] $expectedPolicies
     */
    private function __construct(private readonly string $validPolicy, private readonly array $qualifiers, private array $expectedPolicies)
    {
        $this->children = [];
    }
    /**
     * @param PolicyQualifierInfo[] $qualifiers
     * @param string[] $expectedPolicies
     */
    public static function create(string $validPolicy, array $qualifiers, array $expectedPolicies): self
    {
        return new self($validPolicy, $qualifiers, $expectedPolicies);
    }
    /**
     * Create initial node for the policy tree.
     */
    public static function anyPolicyNode(): self
    {
        return self::create(PolicyInformation::OID_ANY_POLICY, [], [PolicyInformation::OID_ANY_POLICY]);
    }
    /**
     * Get the valid policy OID.
     */
    public function validPolicy(): string
    {
        return $this->validPolicy;
    }
    /**
     * Check whether node has anyPolicy as a valid policy.
     */
    public function isAnyPolicy(): bool
    {
        return $this->validPolicy === PolicyInformation::OID_ANY_POLICY;
    }
    /**
     * Get the qualifier set.
     *
     * @return PolicyQualifierInfo[]
     */
    public function qualifiers(): array
    {
        return $this->qualifiers;
    }
    /**
     * Check whether node has OID as an expected policy.
     */
    public function hasExpectedPolicy(string $oid): bool
    {
        return in_array($oid, $this->expectedPolicies, \true);
    }
    /**
     * Get the expected policy set.
     *
     * @return string[]
     */
    public function expectedPolicies(): array
    {
        return $this->expectedPolicies;
    }
    /**
     * Set expected policies.
     *
     * @param string ...$oids Policy OIDs
     */
    public function setExpectedPolicies(string ...$oids): void
    {
        $this->expectedPolicies = $oids;
    }
    /**
     * Check whether node has a child node with given valid policy OID.
     */
    public function hasChildWithValidPolicy(string $oid): bool
    {
        foreach ($this->children as $node) {
            if ($node->validPolicy() === $oid) {
                return \true;
            }
        }
        return \false;
    }
    /**
     * Add child node.
     */
    public function addChild(self $node): self
    {
        $id = spl_object_hash($node);
        $node->parent = $this;
        $this->children[$id] = $node;
        return $this;
    }
    /**
     * Get the child nodes.
     *
     * @return PolicyNode[]
     */
    public function children(): array
    {
        return array_values($this->children);
    }
    /**
     * Remove this node from the tree.
     *
     * @return self The removed node
     */
    public function remove(): self
    {
        if ($this->parent !== null) {
            $id = spl_object_hash($this);
            unset($this->parent->children[$id], $this->parent);
        }
        return $this;
    }
    /**
     * Check whether node has a parent.
     */
    public function hasParent(): bool
    {
        return isset($this->parent);
    }
    /**
     * Get the parent node.
     */
    public function parent(): ?self
    {
        return $this->parent;
    }
    /**
     * Get chain of parent nodes from this node's parent to the root node.
     *
     * @return PolicyNode[]
     */
    public function parents(): array
    {
        if ($this->parent === null) {
            return [];
        }
        $nodes = $this->parent->parents();
        $nodes[] = $this->parent;
        return array_reverse($nodes);
    }
    /**
     * Walk tree from this node, applying a callback for each node.
     *
     * Nodes are traversed depth-first and callback shall be applied post-order.
     */
    public function walkNodes(callable $fn): void
    {
        foreach ($this->children as $node) {
            $node->walkNodes($fn);
        }
        $fn($this);
    }
    /**
     * Get the total number of nodes in a tree.
     */
    public function nodeCount(): int
    {
        $c = 1;
        foreach ($this->children as $child) {
            $c += $child->nodeCount();
        }
        return $c;
    }
    /**
     * Get the number of child nodes.
     *
     * @see \Countable::count()
     */
    public function count(): int
    {
        return count($this->children);
    }
    /**
     * Get iterator for the child nodes.
     *
     * @see \IteratorAggregate::getIterator()
     */
    public function getIterator(): ArrayIterator
    {
        return new ArrayIterator($this->children);
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\X509\CertificationPath\Policy;

use function count;
use function in_array;
use LogicException;
use _ContaoManager\SpomkyLabs\Pki\X509\Certificate\Certificate;
use _ContaoManager\SpomkyLabs\Pki\X509\Certificate\Extension\CertificatePolicy\PolicyInformation;
use _ContaoManager\SpomkyLabs\Pki\X509\CertificationPath\PathValidation\ValidatorState;
final class PolicyTree
{
    /**
     * @param PolicyNode $root Initial root node
     */
    private function __construct(private ?PolicyNode $root)
    {
    }
    public static function create(?PolicyNode $root): self
    {
        return new self($root);
    }
    /**
     * Process policy information from the certificate.
     *
     * Certificate policies extension must be present.
     */
    public function processPolicies(ValidatorState $state, Certificate $cert): ValidatorState
    {
        $policies = $cert->tbsCertificate()->extensions()->certificatePolicies();
        $tree = clone $this;
        // (d.1) for each policy P not equal to anyPolicy
        foreach ($policies as $policy) {
            /** @var PolicyInformation $policy */
            if ($policy->isAnyPolicy()) {
                $tree->processAnyPolicy($policy, $cert, $state);
            } else {
                $tree->processPolicy($policy, $state);
            }
        }
        // if whole tree is pruned
        if ($tree->pruneTree($state->index() - 1) === 0) {
            return $state->withoutValidPolicyTree();
        }
        return $state->withValidPolicyTree($tree);
    }
    /**
     * Process policy mappings from the certificate.
     */
    public function processMappings(ValidatorState $state, Certificate $cert): ValidatorState
    {
        $tree = clone $this;
        if ($state->policyMapping() > 0) {
            $tree->_applyMappings($cert, $state);
        } elseif ($state->policyMapping() === 0) {
            $tree->_deleteMappings($cert, $state);
        }
        // if whole tree is pruned
        if ($tree->root === null) {
            return $state->withoutValidPolicyTree();
        }
        return $state->withValidPolicyTree($tree);
    }
    /**
     * Calculate policy intersection as specified in Wrap-Up Procedure 6.1.5.g.
     *
     * @param array<string> $policies
     */
    public function calculateIntersection(ValidatorState $state, array $policies): ValidatorState
    {
        $tree = clone $this;
        $valid_policy_node_set = $tree->validPolicyNodeSet();
        // 2. If the valid_policy of any node in the valid_policy_node_set
        // is not in the user-initial-policy-set and is not anyPolicy,
        // delete this node and all its children.
        $valid_policy_node_set = array_filter($valid_policy_node_set, function (PolicyNode $node) use ($policies) {
            if ($node->isAnyPolicy()) {
                return \true;
            }
            if (in_array($node->validPolicy(), $policies, \true)) {
                return \true;
            }
            $node->remove();
            return \false;
        });
        // array of valid policy OIDs
        $valid_policy_set = array_map(static fn(PolicyNode $node) => $node->validPolicy(), $valid_policy_node_set);
        // 3. If the valid_policy_tree includes a node of depth n with
        // the valid_policy anyPolicy and the user-initial-policy-set
        // is not any-policy
        foreach ($tree->nodesAtDepth($state->index()) as $node) {
            if ($node->hasParent() && $node->isAnyPolicy()) {
                // a. Set P-Q to the qualifier_set in the node of depth n
                // with valid_policy anyPolicy.
                $pq = $node->qualifiers();
                // b. For each P-OID in the user-initial-policy-set that is not
                // the valid_policy of a node in the valid_policy_node_set,
                // create a child node whose parent is the node of depth n-1
                // with the valid_policy anyPolicy.
                $poids = array_diff($policies, $valid_policy_set);
                foreach ($tree->nodesAtDepth($state->index() - 1) as $parent) {
                    if ($parent->isAnyPolicy()) {
                        // Set the values in the child node as follows:
                        // set the valid_policy to P-OID, set the qualifier_set
                        // to P-Q, and set the expected_policy_set to {P-OID}.
                        foreach ($poids as $poid) {
                            $parent->addChild(PolicyNode::create($poid, $pq, [$poid]));
                        }
                        break;
                    }
                }
                // c. Delete the node of depth n with the
                // valid_policy anyPolicy.
                $node->remove();
            }
        }
        // 4. If there is a node in the valid_policy_tree of depth n-1 or less
        // without any child nodes, delete that node. Repeat this step until
        // there are no nodes of depth n-1 or less without children.
        if ($tree->pruneTree($state->index() - 1) === 0) {
            return $state->withoutValidPolicyTree();
        }
        return $state->withValidPolicyTree($tree);
    }
    /**
     * Get policies at given policy tree depth.
     *
     * @param int $i Depth in range 1..n
     *
     * @return PolicyInformation[]
     */
    public function policiesAtDepth(int $i): array
    {
        $policies = [];
        foreach ($this->nodesAtDepth($i) as $node) {
            $policies[] = PolicyInformation::create($node->validPolicy(), ...$node->qualifiers());
        }
        return $policies;
    }
    /**
     * Process single policy information.
     */
    private function processPolicy(PolicyInformation $policy, ValidatorState $state): void
    {
        $p_oid = $policy->oid();
        $i = $state->index();
        $match_count = 0;
        // (d.1.i) for each node of depth i-1 in the valid_policy_tree...
        foreach ($this->nodesAtDepth($i - 1) as $node) {
            // ...where P-OID is in the expected_policy_set
            if ($node->hasExpectedPolicy($p_oid)) {
                $node->addChild(PolicyNode::create($p_oid, $policy->qualifiers(), [$p_oid]));
                ++$match_count;
            }
        }
        // (d.1.ii) if there was no match in step (i)...
        if ($match_count === 0) {
            // ...and the valid_policy_tree includes a node of depth i-1 with
            // the valid_policy anyPolicy
            foreach ($this->nodesAtDepth($i - 1) as $node) {
                if ($node->isAnyPolicy()) {
                    $node->addChild(PolicyNode::create($p_oid, $policy->qualifiers(), [$p_oid]));
                }
            }
        }
    }
    /**
     * Process anyPolicy policy information.
     */
    private function processAnyPolicy(PolicyInformation $policy, Certificate $cert, ValidatorState $state): void
    {
        $i = $state->index();
        // if (a) inhibit_anyPolicy is greater than 0 or
        // (b) i<n and the certificate is self-issued
        if (!($state->inhibitAnyPolicy() > 0 || $i < $state->pathLength() && $cert->isSelfIssued())) {
            return;
        }
        // for each node in the valid_policy_tree of depth i-1
        foreach ($this->nodesAtDepth($i - 1) as $node) {
            // for each value in the expected_policy_set
            foreach ($node->expectedPolicies() as $p_oid) {
                // that does not appear in a child node
                if (!$node->hasChildWithValidPolicy($p_oid)) {
                    $node->addChild(PolicyNode::create($p_oid, $policy->qualifiers(), [$p_oid]));
                }
            }
        }
    }
    /**
     * Apply policy mappings to the policy tree.
     */
    private function _applyMappings(Certificate $cert, ValidatorState $state): void
    {
        $policy_mappings = $cert->tbsCertificate()->extensions()->policyMappings();
        // (6.1.4. b.1.) for each node in the valid_policy_tree of depth i...
        foreach ($policy_mappings->flattenedMappings() as $idp => $sdps) {
            $match_count = 0;
            foreach ($this->nodesAtDepth($state->index()) as $node) {
                // ...where ID-P is the valid_policy
                if ($node->validPolicy() === $idp) {
                    // set expected_policy_set to the set of subjectDomainPolicy
                    // values that are specified as equivalent to ID-P by
                    // the policy mappings extension
                    $node->setExpectedPolicies(...$sdps);
                    ++$match_count;
                }
            }
            // if no node of depth i in the valid_policy_tree has
            // a valid_policy of ID-P...
            if ($match_count === 0) {
                $this->_applyAnyPolicyMapping($cert, $state, $idp, $sdps);
            }
        }
    }
    /**
     * Apply anyPolicy mapping to the policy tree as specified in 6.1.4 (b)(1).
     *
     * @param string $idp OID of the issuer domain policy
     * @param array<string> $sdps Array of subject domain policy OIDs
     */
    private function _applyAnyPolicyMapping(Certificate $cert, ValidatorState $state, string $idp, array $sdps): void
    {
        // (6.1.4. b.1.) ...but there is a node of depth i with
        // a valid_policy of anyPolicy
        foreach ($this->nodesAtDepth($state->index()) as $node) {
            if ($node->isAnyPolicy()) {
                // then generate a child node of the node of depth i-1
                // that has a valid_policy of anyPolicy as follows...
                foreach ($this->nodesAtDepth($state->index() - 1) as $subnode) {
                    if ($subnode->isAnyPolicy()) {
                        // try to fetch qualifiers of anyPolicy certificate policy
                        try {
                            $qualifiers = $cert->tbsCertificate()->extensions()->certificatePolicies()->anyPolicy()->qualifiers();
                        } catch (LogicException) {
                            // if there's no policies or no qualifiers
                            $qualifiers = [];
                        }
                        $subnode->addChild(PolicyNode::create($idp, $qualifiers, $sdps));
                        // bail after first anyPolicy has been processed
                        break;
                    }
                }
                // bail after first anyPolicy has been processed
                break;
            }
        }
    }
    /**
     * Delete nodes as specified in 6.1.4 (b)(2).
     */
    private function _deleteMappings(Certificate $cert, ValidatorState $state): void
    {
        $idps = $cert->tbsCertificate()->extensions()->policyMappings()->issuerDomainPolicies();
        // delete each node of depth i in the valid_policy_tree
        // where ID-P is the valid_policy
        foreach ($this->nodesAtDepth($state->index()) as $node) {
            if (in_array($node->validPolicy(), $idps, \true)) {
                $node->remove();
            }
        }
        $this->pruneTree($state->index() - 1);
    }
    /**
     * Prune tree starting from given depth.
     *
     * @return int The number of nodes left in a tree
     */
    private function pruneTree(int $depth): int
    {
        if ($this->root === null) {
            return 0;
        }
        for ($i = $depth; $i > 0; --$i) {
            foreach ($this->nodesAtDepth($i) as $node) {
                if (count($node) === 0) {
                    $node->remove();
                }
            }
        }
        // if root has no children left
        if (count($this->root) === 0) {
            $this->root = null;
            return 0;
        }
        return $this->root->nodeCount();
    }
    /**
     * Get all nodes at given depth.
     *
     * @return PolicyNode[]
     */
    private function nodesAtDepth(int $i): array
    {
        if ($this->root === null) {
            return [];
        }
        $depth = 0;
        $nodes = [$this->root];
        while ($depth < $i) {
            $nodes = self::gatherChildren(...$nodes);
            if (count($nodes) === 0) {
                break;
            }
            ++$depth;
        }
        return $nodes;
    }
    /**
     * Get the valid policy node set as specified in spec 6.1.5.(g)(iii)1.
     *
     * @return PolicyNode[]
     */
    private function validPolicyNodeSet(): array
    {
        // 1. Determine the set of policy nodes whose parent nodes have
        // a valid_policy of anyPolicy. This is the valid_policy_node_set.
        $set = [];
        if ($this->root === null) {
            return $set;
        }
        // for each node in a tree
        $this->root->walkNodes(function (PolicyNode $node) use (&$set) {
            $parents = $node->parents();
            // node has parents
            if (count($parents) !== 0) {
                // check that each ancestor is an anyPolicy node
                foreach ($parents as $ancestor) {
                    if (!$ancestor->isAnyPolicy()) {
                        return;
                    }
                }
                $set[] = $node;
            }
        });
        return $set;
    }
    /**
     * Gather all children of given nodes to a flattened array.
     *
     * @return PolicyNode[]
     */
    private static function gatherChildren(PolicyNode ...$nodes): array
    {
        $children = [];
        foreach ($nodes as $node) {
            $children = array_merge($children, $node->children());
        }
        return $children;
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\X509\CertificationPath;

use ArrayIterator;
use function count;
use Countable;
use IteratorAggregate;
use LogicException;
use _ContaoManager\SpomkyLabs\Pki\CryptoBridge\Crypto;
use _ContaoManager\SpomkyLabs\Pki\X509\Certificate\Certificate;
use _ContaoManager\SpomkyLabs\Pki\X509\Certificate\CertificateBundle;
use _ContaoManager\SpomkyLabs\Pki\X509\Certificate\CertificateChain;
use _ContaoManager\SpomkyLabs\Pki\X509\CertificationPath\PathBuilding\CertificationPathBuilder;
use _ContaoManager\SpomkyLabs\Pki\X509\CertificationPath\PathValidation\PathValidationConfig;
use _ContaoManager\SpomkyLabs\Pki\X509\CertificationPath\PathValidation\PathValidationResult;
use _ContaoManager\SpomkyLabs\Pki\X509\CertificationPath\PathValidation\PathValidator;
/**
 * Implements certification path structure.
 *
 * Certification path is a list of certificates from the trust anchor to the end entity certificate, possibly spanning
 * over multiple intermediate certificates.
 *
 * @see https://tools.ietf.org/html/rfc5280#section-3.2
 */
final class CertificationPath implements Countable, IteratorAggregate
{
    /**
     * Certification path.
     *
     * @var Certificate[]
     */
    private readonly array $certificates;
    /**
     * @param Certificate ...$certificates Certificates from the trust anchor
     * to the target end-entity certificate
     */
    private function __construct(Certificate ...$certificates)
    {
        $this->certificates = $certificates;
    }
    public static function create(Certificate ...$certificates): self
    {
        return new self(...$certificates);
    }
    /**
     * Initialize from a certificate chain.
     */
    public static function fromCertificateChain(CertificateChain $chain): self
    {
        return self::create(...array_reverse($chain->certificates(), \false));
    }
    /**
     * Build certification path to given target.
     *
     * @param Certificate $target Target end-entity certificate
     * @param CertificateBundle $trust_anchors List of trust anchors
     * @param null|CertificateBundle $intermediate Optional intermediate certificates
     */
    public static function toTarget(Certificate $target, CertificateBundle $trust_anchors, ?CertificateBundle $intermediate = null): self
    {
        return CertificationPathBuilder::create($trust_anchors)->shortestPathToTarget($target, $intermediate);
    }
    /**
     * Build certification path from given trust anchor to target certificate, using intermediate certificates from
     * given bundle.
     *
     * @param Certificate $trust_anchor Trust anchor certificate
     * @param Certificate $target Target end-entity certificate
     * @param null|CertificateBundle $intermediate Optional intermediate certificates
     */
    public static function fromTrustAnchorToTarget(Certificate $trust_anchor, Certificate $target, ?CertificateBundle $intermediate = null): self
    {
        return self::toTarget($target, CertificateBundle::create($trust_anchor), $intermediate);
    }
    /**
     * Get certificates.
     *
     * @return Certificate[]
     */
    public function certificates(): array
    {
        return $this->certificates;
    }
    /**
     * Get the trust anchor certificate from the path.
     */
    public function trustAnchorCertificate(): Certificate
    {
        if (count($this->certificates) === 0) {
            throw new LogicException('No certificates.');
        }
        return $this->certificates[0];
    }
    /**
     * Get the end-entity certificate from the path.
     */
    public function endEntityCertificate(): Certificate
    {
        if (count($this->certificates) === 0) {
            throw new LogicException('No certificates.');
        }
        return $this->certificates[count($this->certificates) - 1];
    }
    /**
     * Get certification path as a certificate chain.
     */
    public function certificateChain(): CertificateChain
    {
        return CertificateChain::create(...array_reverse($this->certificates, \false));
    }
    /**
     * Check whether certification path starts with one ore more given certificates in parameter order.
     *
     * @param Certificate ...$certs Certificates
     */
    public function startsWith(Certificate ...$certs): bool
    {
        $n = count($certs);
        if ($n > count($this->certificates)) {
            return \false;
        }
        for ($i = 0; $i < $n; ++$i) {
            if (!$certs[$i]->equals($this->certificates[$i])) {
                return \false;
            }
        }
        return \true;
    }
    /**
     * Validate certification path.
     *
     * @param null|Crypto $crypto Crypto engine, use default if not set
     */
    public function validate(PathValidationConfig $config, ?Crypto $crypto = null): PathValidationResult
    {
        $crypto ??= Crypto::getDefault();
        return PathValidator::create($crypto, $config, ...$this->certificates)->validate();
    }
    /**
     * @see \Countable::count()
     */
    public function count(): int
    {
        return count($this->certificates);
    }
    /**
     * Get iterator for certificates.
     *
     * @see \IteratorAggregate::getIterator()
     */
    public function getIterator(): ArrayIterator
    {
        return new ArrayIterator($this->certificates);
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\X509\Exception;

use RuntimeException;
class X509ValidationException extends RuntimeException
{
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\X509\AttributeCertificate\Attribute;

use _ContaoManager\SpomkyLabs\Pki\ASN1\Element;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\UnspecifiedType;
use _ContaoManager\SpomkyLabs\Pki\X509\GeneralName\GeneralName;
/**
 * Implements value for 'Access Identity' attribute.
 *
 * @see https://tools.ietf.org/html/rfc5755#section-4.4.2
 */
final class AccessIdentityAttributeValue extends SvceAuthInfo
{
    final public const OID = '1.3.6.1.5.5.7.10.2';
    private function __construct(GeneralName $service, GeneralName $ident, ?string $authInfo)
    {
        parent::__construct(self::OID, $service, $ident, $authInfo);
    }
    public static function create(GeneralName $service, GeneralName $ident, ?string $_authInfo = null): self
    {
        return new self($service, $ident, $_authInfo);
    }
    public static function fromASN1(UnspecifiedType $el): static
    {
        $seq = $el->asSequence();
        $service = GeneralName::fromASN1($seq->at(0)->asTagged());
        $ident = GeneralName::fromASN1($seq->at(1)->asTagged());
        $auth_info = null;
        if ($seq->has(2, Element::TYPE_OCTET_STRING)) {
            $auth_info = $seq->at(2)->asString()->string();
        }
        return static::create($service, $ident, $auth_info);
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\X509\AttributeCertificate\Attribute;

use LogicException;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Element;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Primitive\ObjectIdentifier;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Primitive\OctetString;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Primitive\UTF8String;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\UnspecifiedType;
use Stringable;
use UnexpectedValueException;
/**
 * Implements *IetfAttrSyntax.values* ASN.1 CHOICE type.
 *
 * @see https://tools.ietf.org/html/rfc5755#section-4.4
 */
final class IetfAttrValue implements Stringable
{
    private function __construct(private readonly string $value, private readonly int $type)
    {
    }
    public function __toString(): string
    {
        return $this->value;
    }
    public static function create(string $value, int $type): self
    {
        return new self($value, $type);
    }
    /**
     * Initialize from ASN.1.
     */
    public static function fromASN1(UnspecifiedType $el): self
    {
        return match ($el->tag()) {
            Element::TYPE_OCTET_STRING, Element::TYPE_UTF8_STRING => self::create($el->asString()->string(), $el->tag()),
            Element::TYPE_OBJECT_IDENTIFIER => self::create($el->asObjectIdentifier()->oid(), $el->tag()),
            default => throw new UnexpectedValueException('Type ' . Element::tagToName($el->tag()) . ' not supported.'),
        };
    }
    /**
     * Initialize from octet string.
     */
    public static function fromOctets(string $octets): self
    {
        return self::create($octets, Element::TYPE_OCTET_STRING);
    }
    /**
     * Initialize from UTF-8 string.
     */
    public static function fromString(string $str): self
    {
        return self::create($str, Element::TYPE_UTF8_STRING);
    }
    /**
     * Initialize from OID.
     */
    public static function fromOID(string $oid): self
    {
        return self::create($oid, Element::TYPE_OBJECT_IDENTIFIER);
    }
    /**
     * Get type tag.
     */
    public function type(): int
    {
        return $this->type;
    }
    /**
     * Whether value type is octets.
     */
    public function isOctets(): bool
    {
        return $this->type === Element::TYPE_OCTET_STRING;
    }
    /**
     * Whether value type is OID.
     */
    public function isOID(): bool
    {
        return $this->type === Element::TYPE_OBJECT_IDENTIFIER;
    }
    /**
     * Whether value type is string.
     */
    public function isString(): bool
    {
        return $this->type === Element::TYPE_UTF8_STRING;
    }
    public function value(): string
    {
        return $this->value;
    }
    /**
     * Generate ASN.1 structure.
     */
    public function toASN1(): Element
    {
        return match ($this->type) {
            Element::TYPE_OCTET_STRING => OctetString::create($this->value),
            Element::TYPE_UTF8_STRING => UTF8String::create($this->value),
            Element::TYPE_OBJECT_IDENTIFIER => ObjectIdentifier::create($this->value),
            default => throw new LogicException('Type ' . Element::tagToName($this->type) . ' not supported.'),
        };
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\X509\AttributeCertificate\Attribute;

use LogicException;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Element;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Constructed\Sequence;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Primitive\OctetString;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\UnspecifiedType;
use _ContaoManager\SpomkyLabs\Pki\X501\ASN1\AttributeValue\AttributeValue;
use _ContaoManager\SpomkyLabs\Pki\X501\MatchingRule\BinaryMatch;
use _ContaoManager\SpomkyLabs\Pki\X501\MatchingRule\MatchingRule;
use _ContaoManager\SpomkyLabs\Pki\X509\GeneralName\GeneralName;
/**
 * Base class implementing *SvceAuthInfo* ASN.1 type used by attribute certificate attribute values.
 *
 * @see https://tools.ietf.org/html/rfc5755#section-4.4.1
 */
abstract class SvceAuthInfo extends AttributeValue
{
    protected function __construct(string $oid, private readonly GeneralName $service, private readonly GeneralName $ident, private readonly ?string $authInfo = null)
    {
        parent::__construct($oid);
    }
    abstract public static function fromASN1(UnspecifiedType $el): static;
    /**
     * Get service name.
     */
    public function service(): GeneralName
    {
        return $this->service;
    }
    public function ident(): GeneralName
    {
        return $this->ident;
    }
    /**
     * Check whether authentication info is present.
     */
    public function hasAuthInfo(): bool
    {
        return isset($this->authInfo);
    }
    /**
     * Get authentication info.
     */
    public function authInfo(): string
    {
        if (!$this->hasAuthInfo()) {
            throw new LogicException('authInfo not set.');
        }
        return $this->authInfo;
    }
    public function toASN1(): Element
    {
        $elements = [$this->service->toASN1(), $this->ident->toASN1()];
        if (isset($this->authInfo)) {
            $elements[] = OctetString::create($this->authInfo);
        }
        return Sequence::create(...$elements);
    }
    public function stringValue(): string
    {
        return '#' . bin2hex($this->toASN1()->toDER());
    }
    public function equalityMatchingRule(): MatchingRule
    {
        return new BinaryMatch();
    }
    public function rfc2253String(): string
    {
        return $this->stringValue();
    }
    protected function _transcodedString(): string
    {
        return $this->stringValue();
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\X509\AttributeCertificate\Attribute;

use _ContaoManager\SpomkyLabs\Pki\ASN1\Element;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\UnspecifiedType;
use _ContaoManager\SpomkyLabs\Pki\X509\GeneralName\GeneralName;
/**
 * Implements value for 'Service Authentication Information' attribute.
 *
 * @see https://tools.ietf.org/html/rfc5755#section-4.4.1
 */
final class AuthenticationInfoAttributeValue extends SvceAuthInfo
{
    final public const OID = '1.3.6.1.5.5.7.10.1';
    private function __construct(GeneralName $service, GeneralName $ident, ?string $auth_info)
    {
        parent::__construct(self::OID, $service, $ident, $auth_info);
    }
    public static function create(GeneralName $service, GeneralName $ident, ?string $auth_info = null): self
    {
        return new self($service, $ident, $auth_info);
    }
    public static function fromASN1(UnspecifiedType $el): static
    {
        $seq = $el->asSequence();
        $service = GeneralName::fromASN1($seq->at(0)->asTagged());
        $ident = GeneralName::fromASN1($seq->at(1)->asTagged());
        $auth_info = null;
        if ($seq->has(2, Element::TYPE_OCTET_STRING)) {
            $auth_info = $seq->at(2)->asString()->string();
        }
        return static::create($service, $ident, $auth_info);
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\X509\AttributeCertificate\Attribute;

/**
 * Implements value for 'Charging Identity' attribute.
 *
 * @see https://tools.ietf.org/html/rfc5755#section-4.4.3
 */
final class ChargingIdentityAttributeValue extends IetfAttrSyntax
{
    final public const OID = '1.3.6.1.5.5.7.10.3';
    public static function create(IetfAttrValue ...$values): self
    {
        return new self(self::OID, ...$values);
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\X509\AttributeCertificate\Attribute;

/**
 * Implements value for 'Group' attribute.
 *
 * @see https://tools.ietf.org/html/rfc5755#section-4.4.4
 */
final class GroupAttributeValue extends IetfAttrSyntax
{
    final public const OID = '1.3.6.1.5.5.7.10.4';
    public static function create(IetfAttrValue ...$values): self
    {
        return new self(self::OID, ...$values);
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\X509\AttributeCertificate\Attribute;

use ArrayIterator;
use function count;
use Countable;
use IteratorAggregate;
use LogicException;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Element;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Constructed\Sequence;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Tagged\ImplicitlyTaggedType;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\UnspecifiedType;
use _ContaoManager\SpomkyLabs\Pki\X501\ASN1\AttributeValue\AttributeValue;
use _ContaoManager\SpomkyLabs\Pki\X501\MatchingRule\BinaryMatch;
use _ContaoManager\SpomkyLabs\Pki\X501\MatchingRule\MatchingRule;
use _ContaoManager\SpomkyLabs\Pki\X509\GeneralName\GeneralNames;
/**
 * Base class implementing *IetfAttrSyntax* ASN.1 type used by attribute certificate attribute values.
 *
 * @see https://tools.ietf.org/html/rfc5755#section-4.4
 */
abstract class IetfAttrSyntax extends AttributeValue implements Countable, IteratorAggregate
{
    /**
     * Policy authority.
     */
    protected ?GeneralNames $_policyAuthority;
    /**
     * Values.
     *
     * @var IetfAttrValue[]
     */
    protected array $_values;
    protected function __construct(string $oid, IetfAttrValue ...$values)
    {
        parent::__construct($oid);
        $this->_policyAuthority = null;
        $this->_values = $values;
    }
    abstract public static function create(IetfAttrValue ...$values): self;
    /**
     * @return self
     */
    public static function fromASN1(UnspecifiedType $el): AttributeValue
    {
        $seq = $el->asSequence();
        $authority = null;
        $idx = 0;
        if ($seq->hasTagged(0)) {
            $authority = GeneralNames::fromASN1($seq->getTagged(0)->asImplicit(Element::TYPE_SEQUENCE)->asSequence());
            ++$idx;
        }
        $values = array_map(IetfAttrValue::fromASN1(...), $seq->at($idx)->asSequence()->elements());
        $obj = static::create(...$values);
        $obj->_policyAuthority = $authority;
        return $obj;
    }
    /**
     * Get self with policy authority.
     */
    public function withPolicyAuthority(GeneralNames $names): self
    {
        $obj = clone $this;
        $obj->_policyAuthority = $names;
        return $obj;
    }
    /**
     * Check whether policy authority is present.
     */
    public function hasPolicyAuthority(): bool
    {
        return isset($this->_policyAuthority);
    }
    /**
     * Get policy authority.
     */
    public function policyAuthority(): GeneralNames
    {
        if (!$this->hasPolicyAuthority()) {
            throw new LogicException('policyAuthority not set.');
        }
        return $this->_policyAuthority;
    }
    /**
     * Get values.
     *
     * @return IetfAttrValue[]
     */
    public function values(): array
    {
        return $this->_values;
    }
    /**
     * Get first value.
     */
    public function first(): IetfAttrValue
    {
        if (count($this->_values) === 0) {
            throw new LogicException('No values.');
        }
        return $this->_values[0];
    }
    public function toASN1(): Element
    {
        $elements = [];
        if (isset($this->_policyAuthority)) {
            $elements[] = ImplicitlyTaggedType::create(0, $this->_policyAuthority->toASN1());
        }
        $values = array_map(static fn(IetfAttrValue $val) => $val->toASN1(), $this->_values);
        $elements[] = Sequence::create(...$values);
        return Sequence::create(...$elements);
    }
    public function stringValue(): string
    {
        return '#' . bin2hex($this->toASN1()->toDER());
    }
    public function equalityMatchingRule(): MatchingRule
    {
        return new BinaryMatch();
    }
    public function rfc2253String(): string
    {
        return $this->stringValue();
    }
    /**
     * Get number of values.
     *
     * @see \Countable::count()
     */
    public function count(): int
    {
        return count($this->_values);
    }
    /**
     * Get iterator for values.
     *
     * @see \IteratorAggregate::getIterator()
     */
    public function getIterator(): ArrayIterator
    {
        return new ArrayIterator($this->_values);
    }
    protected function _transcodedString(): string
    {
        return $this->stringValue();
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\X509\AttributeCertificate\Attribute;

use LogicException;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Element;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Constructed\Sequence;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Tagged\ExplicitlyTaggedType;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Tagged\ImplicitlyTaggedType;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\UnspecifiedType;
use _ContaoManager\SpomkyLabs\Pki\X501\ASN1\AttributeType;
use _ContaoManager\SpomkyLabs\Pki\X501\ASN1\AttributeValue\AttributeValue;
use _ContaoManager\SpomkyLabs\Pki\X501\MatchingRule\BinaryMatch;
use _ContaoManager\SpomkyLabs\Pki\X501\MatchingRule\MatchingRule;
use _ContaoManager\SpomkyLabs\Pki\X509\GeneralName\GeneralName;
use _ContaoManager\SpomkyLabs\Pki\X509\GeneralName\GeneralNames;
use _ContaoManager\SpomkyLabs\Pki\X509\GeneralName\UniformResourceIdentifier;
/**
 * Implements value for 'Role' attribute.
 *
 * @see https://tools.ietf.org/html/rfc5755#section-4.4.5
 */
final class RoleAttributeValue extends AttributeValue
{
    /**
     * @param GeneralName $roleName Role name
     * @param null|GeneralNames $roleAuthority Issuing authority
     */
    private function __construct(private readonly GeneralName $roleName, private readonly ?GeneralNames $roleAuthority)
    {
        parent::__construct(AttributeType::OID_ROLE);
    }
    public static function create(GeneralName $roleName, ?GeneralNames $roleAuthority = null): self
    {
        return new self($roleName, $roleAuthority);
    }
    /**
     * Initialize from a role string.
     *
     * @param string $role_name Role name in URI format
     * @param null|GeneralNames $authority Issuing authority
     */
    public static function fromString(string $role_name, ?GeneralNames $authority = null): self
    {
        return self::create(UniformResourceIdentifier::create($role_name), $authority);
    }
    /**
     * @return self
     */
    public static function fromASN1(UnspecifiedType $el): AttributeValue
    {
        $seq = $el->asSequence();
        $authority = null;
        if ($seq->hasTagged(0)) {
            $authority = GeneralNames::fromASN1($seq->getTagged(0)->asImplicit(Element::TYPE_SEQUENCE)->asSequence());
        }
        $name = GeneralName::fromASN1($seq->getTagged(1)->asExplicit()->asTagged());
        return self::create($name, $authority);
    }
    /**
     * Check whether issuing authority is present.
     */
    public function hasRoleAuthority(): bool
    {
        return isset($this->roleAuthority);
    }
    /**
     * Get issuing authority.
     */
    public function roleAuthority(): GeneralNames
    {
        if (!$this->hasRoleAuthority()) {
            throw new LogicException('roleAuthority not set.');
        }
        return $this->roleAuthority;
    }
    /**
     * Get role name.
     */
    public function roleName(): GeneralName
    {
        return $this->roleName;
    }
    public function toASN1(): Element
    {
        $elements = [];
        if (isset($this->roleAuthority)) {
            $elements[] = ImplicitlyTaggedType::create(0, $this->roleAuthority->toASN1());
        }
        $elements[] = ExplicitlyTaggedType::create(1, $this->roleName->toASN1());
        return Sequence::create(...$elements);
    }
    public function stringValue(): string
    {
        return '#' . bin2hex($this->toASN1()->toDER());
    }
    public function equalityMatchingRule(): MatchingRule
    {
        return new BinaryMatch();
    }
    public function rfc2253String(): string
    {
        return $this->stringValue();
    }
    protected function _transcodedString(): string
    {
        return $this->stringValue();
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\X509\AttributeCertificate;

use _ContaoManager\SpomkyLabs\Pki\X501\ASN1\Attribute;
use _ContaoManager\SpomkyLabs\Pki\X501\ASN1\AttributeType;
use _ContaoManager\SpomkyLabs\Pki\X501\ASN1\AttributeValue\AttributeValue;
use _ContaoManager\SpomkyLabs\Pki\X501\ASN1\Collection\SequenceOfAttributes;
use _ContaoManager\SpomkyLabs\Pki\X509\AttributeCertificate\Attribute\AccessIdentityAttributeValue;
use _ContaoManager\SpomkyLabs\Pki\X509\AttributeCertificate\Attribute\AuthenticationInfoAttributeValue;
use _ContaoManager\SpomkyLabs\Pki\X509\AttributeCertificate\Attribute\ChargingIdentityAttributeValue;
use _ContaoManager\SpomkyLabs\Pki\X509\AttributeCertificate\Attribute\GroupAttributeValue;
use _ContaoManager\SpomkyLabs\Pki\X509\AttributeCertificate\Attribute\RoleAttributeValue;
/**
 * Implements *Attributes* ASN.1 type of *AttributeCertificateInfo*.
 *
 * @see https://tools.ietf.org/html/rfc5755#section-4.1
 * @see https://tools.ietf.org/html/rfc5755#section-4.2.7
 */
final class Attributes extends SequenceOfAttributes
{
    /**
     * Mapping from OID to attribute value class name.
     *
     * @internal
     *
     * @var array<string, string>
     */
    private const MAP_OID_TO_CLASS = [AccessIdentityAttributeValue::OID => AccessIdentityAttributeValue::class, AuthenticationInfoAttributeValue::OID => AuthenticationInfoAttributeValue::class, ChargingIdentityAttributeValue::OID => ChargingIdentityAttributeValue::class, GroupAttributeValue::OID => GroupAttributeValue::class, AttributeType::OID_ROLE => RoleAttributeValue::class];
    /**
     * Initialize from attribute values.
     *
     * @param AttributeValue ...$values List of attribute values
     */
    public static function fromAttributeValues(AttributeValue ...$values): static
    {
        return static::create(...array_map(static fn(AttributeValue $value) => $value->toAttribute(), $values));
    }
    /**
     * Check whether 'Access Identity' attribute is present.
     */
    public function hasAccessIdentity(): bool
    {
        return $this->has(AccessIdentityAttributeValue::OID);
    }
    /**
     * Get the first 'Access Identity' attribute value.
     */
    public function accessIdentity(): AccessIdentityAttributeValue
    {
        return $this->firstOf(AccessIdentityAttributeValue::OID)->first();
    }
    /**
     * Check whether 'Service Authentication Information' attribute is present.
     */
    public function hasAuthenticationInformation(): bool
    {
        return $this->has(AuthenticationInfoAttributeValue::OID);
    }
    /**
     * Get the first 'Service Authentication Information' attribute value.
     */
    public function authenticationInformation(): AuthenticationInfoAttributeValue
    {
        return $this->firstOf(AuthenticationInfoAttributeValue::OID)->first();
    }
    /**
     * Check whether 'Charging Identity' attribute is present.
     */
    public function hasChargingIdentity(): bool
    {
        return $this->has(ChargingIdentityAttributeValue::OID);
    }
    /**
     * Get the first 'Charging Identity' attribute value.
     */
    public function chargingIdentity(): ChargingIdentityAttributeValue
    {
        return $this->firstOf(ChargingIdentityAttributeValue::OID)->first();
    }
    /**
     * Check whether 'Group' attribute is present.
     */
    public function hasGroup(): bool
    {
        return $this->has(GroupAttributeValue::OID);
    }
    /**
     * Get the first 'Group' attribute value.
     */
    public function group(): GroupAttributeValue
    {
        return $this->firstOf(GroupAttributeValue::OID)->first();
    }
    /**
     * Check whether 'Role' attribute is present.
     */
    public function hasRole(): bool
    {
        return $this->has(AttributeType::OID_ROLE);
    }
    /**
     * Get the first 'Role' attribute value.
     */
    public function role(): RoleAttributeValue
    {
        return $this->firstOf(AttributeType::OID_ROLE)->first();
    }
    /**
     * Get all 'Role' attribute values.
     *
     * @return RoleAttributeValue[]
     */
    public function roles(): array
    {
        return array_merge([], ...array_map(static fn(Attribute $attr) => $attr->values(), $this->allOf(AttributeType::OID_ROLE)));
    }
    protected static function _castAttributeValues(Attribute $attribute): Attribute
    {
        $oid = $attribute->oid();
        if (isset(self::MAP_OID_TO_CLASS[$oid])) {
            return $attribute->castValues(self::MAP_OID_TO_CLASS[$oid]);
        }
        return $attribute;
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\X509\AttributeCertificate;

use LogicException;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Element;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Constructed\Sequence;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Primitive\Integer;
use _ContaoManager\SpomkyLabs\Pki\X509\Certificate\Certificate;
use _ContaoManager\SpomkyLabs\Pki\X509\Certificate\UniqueIdentifier;
use _ContaoManager\SpomkyLabs\Pki\X509\GeneralName\DirectoryName;
use _ContaoManager\SpomkyLabs\Pki\X509\GeneralName\GeneralNames;
/**
 * Implements *IssuerSerial* ASN.1 type.
 *
 * @see https://tools.ietf.org/html/rfc5755#section-4.1
 */
final class IssuerSerial
{
    private function __construct(private readonly GeneralNames $issuer, private readonly string $serial, private readonly ?UniqueIdentifier $issuerUID)
    {
    }
    public static function create(GeneralNames $issuer, string $serial, ?UniqueIdentifier $issuerUID = null): self
    {
        return new self($issuer, $serial, $issuerUID);
    }
    /**
     * Initialize from ASN.1.
     */
    public static function fromASN1(Sequence $seq): self
    {
        $issuer = GeneralNames::fromASN1($seq->at(0)->asSequence());
        $serial = $seq->at(1)->asInteger()->number();
        $uid = null;
        if ($seq->has(2, Element::TYPE_BIT_STRING)) {
            $uid = UniqueIdentifier::fromASN1($seq->at(2)->asBitString());
        }
        return self::create($issuer, $serial, $uid);
    }
    /**
     * Initialize from a public key certificate.
     */
    public static function fromPKC(Certificate $cert): self
    {
        $tbsCert = $cert->tbsCertificate();
        $issuer = GeneralNames::create(DirectoryName::create($tbsCert->issuer()));
        $serial = $tbsCert->serialNumber();
        $uid = $tbsCert->hasIssuerUniqueID() ? $tbsCert->issuerUniqueID() : null;
        return self::create($issuer, $serial, $uid);
    }
    /**
     * Get issuer name.
     */
    public function issuer(): GeneralNames
    {
        return $this->issuer;
    }
    /**
     * Get serial number.
     */
    public function serial(): string
    {
        return $this->serial;
    }
    /**
     * Check whether issuer unique identifier is present.
     */
    public function hasIssuerUID(): bool
    {
        return isset($this->issuerUID);
    }
    /**
     * Get issuer unique identifier.
     */
    public function issuerUID(): UniqueIdentifier
    {
        if (!$this->hasIssuerUID()) {
            throw new LogicException('issuerUID not set.');
        }
        return $this->issuerUID;
    }
    /**
     * Generate ASN.1 structure.
     */
    public function toASN1(): Sequence
    {
        $elements = [$this->issuer->toASN1(), Integer::create($this->serial)];
        if (isset($this->issuerUID)) {
            $elements[] = $this->issuerUID->toASN1();
        }
        return Sequence::create(...$elements);
    }
    /**
     * Check whether this IssuerSerial identifies given certificate.
     */
    public function identifiesPKC(Certificate $cert): bool
    {
        $tbs = $cert->tbsCertificate();
        if (!$tbs->issuer()->equals($this->issuer->firstDN())) {
            return \false;
        }
        if ($tbs->serialNumber() !== $this->serial) {
            return \false;
        }
        if ($this->issuerUID !== null && !$this->_checkUniqueID($cert)) {
            return \false;
        }
        return \true;
    }
    /**
     * Check whether issuerUID matches given certificate.
     */
    private function _checkUniqueID(Certificate $cert): bool
    {
        if (!$cert->tbsCertificate()->hasIssuerUniqueID()) {
            return \false;
        }
        $uid = $cert->tbsCertificate()->issuerUniqueID()->string();
        return $this->issuerUID?->string() === $uid;
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\X509\AttributeCertificate;

use LogicException;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Element;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Constructed\Sequence;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Tagged\ImplicitlyTaggedType;
use _ContaoManager\SpomkyLabs\Pki\X509\Certificate\Certificate;
use _ContaoManager\SpomkyLabs\Pki\X509\GeneralName\DirectoryName;
use _ContaoManager\SpomkyLabs\Pki\X509\GeneralName\GeneralName;
use _ContaoManager\SpomkyLabs\Pki\X509\GeneralName\GeneralNames;
/**
 * Implements *Holder* ASN.1 type.
 *
 * @see https://tools.ietf.org/html/rfc5755#section-4.1
 */
final class Holder
{
    /**
     * Linked object.
     */
    private ?ObjectDigestInfo $objectDigestInfo = null;
    private function __construct(private ?IssuerSerial $baseCertificateID, private ?GeneralNames $entityName)
    {
    }
    public static function create(?IssuerSerial $baseCertificateID = null, ?GeneralNames $entityName = null): self
    {
        return new self($baseCertificateID, $entityName);
    }
    /**
     * Initialize from a holder's public key certificate.
     */
    public static function fromPKC(Certificate $cert): self
    {
        return self::create(IssuerSerial::fromPKC($cert));
    }
    /**
     * Initialize from ASN.1.
     */
    public static function fromASN1(Sequence $seq): self
    {
        $cert_id = null;
        $entity_name = null;
        $digest_info = null;
        if ($seq->hasTagged(0)) {
            $cert_id = IssuerSerial::fromASN1($seq->getTagged(0)->asImplicit(Element::TYPE_SEQUENCE)->asSequence());
        }
        if ($seq->hasTagged(1)) {
            $entity_name = GeneralNames::fromASN1($seq->getTagged(1)->asImplicit(Element::TYPE_SEQUENCE)->asSequence());
        }
        if ($seq->hasTagged(2)) {
            $digest_info = ObjectDigestInfo::fromASN1($seq->getTagged(2)->asImplicit(Element::TYPE_SEQUENCE)->asSequence());
        }
        return self::create($cert_id, $entity_name)->withObjectDigestInfo($digest_info);
    }
    /**
     * Get self with base certificate ID.
     */
    public function withBaseCertificateID(IssuerSerial $issuer): self
    {
        $obj = clone $this;
        $obj->baseCertificateID = $issuer;
        return $obj;
    }
    /**
     * Get self with entity name.
     */
    public function withEntityName(GeneralNames $names): self
    {
        $obj = clone $this;
        $obj->entityName = $names;
        return $obj;
    }
    /**
     * Get self with object digest info.
     */
    public function withObjectDigestInfo(?ObjectDigestInfo $odi): self
    {
        $obj = clone $this;
        $obj->objectDigestInfo = $odi;
        return $obj;
    }
    /**
     * Check whether base certificate ID is present.
     */
    public function hasBaseCertificateID(): bool
    {
        return isset($this->baseCertificateID);
    }
    /**
     * Get base certificate ID.
     */
    public function baseCertificateID(): IssuerSerial
    {
        if (!$this->hasBaseCertificateID()) {
            throw new LogicException('baseCertificateID not set.');
        }
        return $this->baseCertificateID;
    }
    /**
     * Check whether entity name is present.
     */
    public function hasEntityName(): bool
    {
        return isset($this->entityName);
    }
    /**
     * Get entity name.
     */
    public function entityName(): GeneralNames
    {
        if (!$this->hasEntityName()) {
            throw new LogicException('entityName not set.');
        }
        return $this->entityName;
    }
    /**
     * Check whether object digest info is present.
     */
    public function hasObjectDigestInfo(): bool
    {
        return isset($this->objectDigestInfo);
    }
    /**
     * Get object digest info.
     */
    public function objectDigestInfo(): ObjectDigestInfo
    {
        if (!$this->hasObjectDigestInfo()) {
            throw new LogicException('objectDigestInfo not set.');
        }
        return $this->objectDigestInfo;
    }
    /**
     * Generate ASN.1 structure.
     */
    public function toASN1(): Sequence
    {
        $elements = [];
        if (isset($this->baseCertificateID)) {
            $elements[] = ImplicitlyTaggedType::create(0, $this->baseCertificateID->toASN1());
        }
        if (isset($this->entityName)) {
            $elements[] = ImplicitlyTaggedType::create(1, $this->entityName->toASN1());
        }
        if (isset($this->objectDigestInfo)) {
            $elements[] = ImplicitlyTaggedType::create(2, $this->objectDigestInfo->toASN1());
        }
        return Sequence::create(...$elements);
    }
    /**
     * Check whether Holder identifies given certificate.
     */
    public function identifiesPKC(Certificate $cert): bool
    {
        // if neither baseCertificateID nor entityName are present
        if ($this->baseCertificateID === null && $this->entityName === null) {
            return \false;
        }
        // if baseCertificateID is present, but doesn't match
        if ($this->baseCertificateID !== null && !$this->baseCertificateID->identifiesPKC($cert)) {
            return \false;
        }
        // if entityName is present, but doesn't match
        if ($this->entityName !== null && !$this->_checkEntityName($cert)) {
            return \false;
        }
        return \true;
    }
    /**
     * Check whether entityName matches the given certificate.
     */
    private function _checkEntityName(Certificate $cert): bool
    {
        $name = $this->entityName?->firstDN();
        if ($name !== null && $cert->tbsCertificate()->subject()->equals($name)) {
            return \true;
        }
        $exts = $cert->tbsCertificate()->extensions();
        if ($exts->hasSubjectAlternativeName()) {
            $ext = $exts->subjectAlternativeName();
            if ($this->_checkEntityAlternativeNames($ext->names())) {
                return \true;
            }
        }
        return \false;
    }
    /**
     * Check whether any of the subject alternative names match entityName.
     */
    private function _checkEntityAlternativeNames(GeneralNames $san): bool
    {
        // only directory names supported for now
        $name = $this->entityName?->firstDN();
        if ($name === null) {
            return \false;
        }
        foreach ($san->allOf(GeneralName::TAG_DIRECTORY_NAME) as $dn) {
            if ($dn instanceof DirectoryName && $dn->dn()->equals($name)) {
                return \true;
            }
        }
        return \false;
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\X509\AttributeCertificate;

use LogicException;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Element;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Constructed\Sequence;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Tagged\ImplicitlyTaggedType;
use _ContaoManager\SpomkyLabs\Pki\X501\ASN1\Name;
use _ContaoManager\SpomkyLabs\Pki\X509\Certificate\Certificate;
use _ContaoManager\SpomkyLabs\Pki\X509\GeneralName\GeneralNames;
/**
 * Implements *V2Form* ASN.1 type used as a attribute certificate issuer.
 *
 * @see https://tools.ietf.org/html/rfc5755#section-4.1
 */
final class V2Form extends AttCertIssuer
{
    private function __construct(private readonly ?GeneralNames $issuerName, private readonly ?IssuerSerial $baseCertificateID, private readonly ?ObjectDigestInfo $objectDigestInfo)
    {
    }
    public static function create(?GeneralNames $issuerName = null, ?IssuerSerial $baseCertificateID = null, ?ObjectDigestInfo $objectDigestInfo = null): self
    {
        return new self($issuerName, $baseCertificateID, $objectDigestInfo);
    }
    /**
     * Initialize from ASN.1.
     */
    public static function fromV2ASN1(Sequence $seq): self
    {
        $issuer = null;
        $cert_id = null;
        $digest_info = null;
        if ($seq->has(0, Element::TYPE_SEQUENCE)) {
            $issuer = GeneralNames::fromASN1($seq->at(0)->asSequence());
        }
        if ($seq->hasTagged(0)) {
            $cert_id = IssuerSerial::fromASN1($seq->getTagged(0)->asImplicit(Element::TYPE_SEQUENCE)->asSequence());
        }
        if ($seq->hasTagged(1)) {
            $digest_info = ObjectDigestInfo::fromASN1($seq->getTagged(1)->asImplicit(Element::TYPE_SEQUENCE)->asSequence());
        }
        return self::create($issuer, $cert_id, $digest_info);
    }
    /**
     * Check whether issuer name is set.
     */
    public function hasIssuerName(): bool
    {
        return isset($this->issuerName);
    }
    /**
     * Get issuer name.
     */
    public function issuerName(): GeneralNames
    {
        if (!$this->hasIssuerName()) {
            throw new LogicException('issuerName not set.');
        }
        return $this->issuerName;
    }
    /**
     * Get DN of the issuer.
     *
     * This is a convenience method conforming to RFC 5755, which states that Issuer must contain only one non-empty
     * distinguished name.
     */
    public function name(): Name
    {
        return $this->issuerName()->firstDN();
    }
    public function toASN1(): Element
    {
        $elements = [];
        if (isset($this->issuerName)) {
            $elements[] = $this->issuerName->toASN1();
        }
        if (isset($this->baseCertificateID)) {
            $elements[] = ImplicitlyTaggedType::create(0, $this->baseCertificateID->toASN1());
        }
        if (isset($this->objectDigestInfo)) {
            $elements[] = ImplicitlyTaggedType::create(1, $this->objectDigestInfo->toASN1());
        }
        return ImplicitlyTaggedType::create(0, Sequence::create(...$elements));
    }
    public function identifiesPKC(Certificate $cert): bool
    {
        $name = $this->issuerName?->firstDN();
        return !($name === null || !$cert->tbsCertificate()->subject()->equals($name));
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\X509\AttributeCertificate;

use _ContaoManager\Brick\Math\BigInteger;
use function count;
use LogicException;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Element;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Constructed\Sequence;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Primitive\Integer;
use _ContaoManager\SpomkyLabs\Pki\CryptoBridge\Crypto;
use _ContaoManager\SpomkyLabs\Pki\CryptoTypes\AlgorithmIdentifier\AlgorithmIdentifier;
use _ContaoManager\SpomkyLabs\Pki\CryptoTypes\AlgorithmIdentifier\Feature\SignatureAlgorithmIdentifier;
use _ContaoManager\SpomkyLabs\Pki\CryptoTypes\Asymmetric\PrivateKeyInfo;
use _ContaoManager\SpomkyLabs\Pki\X509\Certificate\Extension\Extension;
use _ContaoManager\SpomkyLabs\Pki\X509\Certificate\Extensions;
use _ContaoManager\SpomkyLabs\Pki\X509\Certificate\UniqueIdentifier;
use function strval;
use UnexpectedValueException;
/**
 * Implements *AttributeCertificateInfo* ASN.1 type.
 *
 * @see https://tools.ietf.org/html/rfc5755#section-4.1
 */
final class AttributeCertificateInfo
{
    final public const VERSION_2 = 1;
    /**
     * AC version.
     */
    private readonly int $version;
    /**
     * Signature algorithm identifier.
     */
    private ?SignatureAlgorithmIdentifier $signature = null;
    /**
     * AC serial number as a base 10 integer.
     */
    private ?string $serialNumber = null;
    /**
     * Issuer unique identifier.
     */
    private ?UniqueIdentifier $issuerUniqueID = null;
    /**
     * Extensions.
     */
    private Extensions $extensions;
    /**
     * @param Holder $holder AC holder
     * @param AttCertIssuer $issuer AC issuer
     * @param AttCertValidityPeriod $attrCertValidityPeriod Validity
     * @param Attributes $attributes Attributes
     */
    private function __construct(private Holder $holder, private AttCertIssuer $issuer, private AttCertValidityPeriod $attrCertValidityPeriod, private Attributes $attributes)
    {
        $this->version = self::VERSION_2;
        $this->extensions = Extensions::create();
    }
    public static function create(Holder $holder, AttCertIssuer $issuer, AttCertValidityPeriod $attrCertValidityPeriod, Attributes $attributes): self
    {
        return new self($holder, $issuer, $attrCertValidityPeriod, $attributes);
    }
    /**
     * Initialize from ASN.1.
     */
    public static function fromASN1(Sequence $seq): self
    {
        $idx = 0;
        $version = $seq->at($idx++)->asInteger()->intNumber();
        if ($version !== self::VERSION_2) {
            throw new UnexpectedValueException('Version must be 2.');
        }
        $holder = Holder::fromASN1($seq->at($idx++)->asSequence());
        $issuer = AttCertIssuer::fromASN1($seq->at($idx++));
        $signature = AlgorithmIdentifier::fromASN1($seq->at($idx++)->asSequence());
        if (!$signature instanceof SignatureAlgorithmIdentifier) {
            throw new UnexpectedValueException('Unsupported signature algorithm ' . $signature->oid() . '.');
        }
        $serial = $seq->at($idx++)->asInteger()->number();
        $validity = AttCertValidityPeriod::fromASN1($seq->at($idx++)->asSequence());
        $attribs = Attributes::fromASN1($seq->at($idx++)->asSequence());
        $obj = self::create($holder, $issuer, $validity, $attribs);
        $obj->signature = $signature;
        $obj->serialNumber = $serial;
        if ($seq->has($idx, Element::TYPE_BIT_STRING)) {
            $obj->issuerUniqueID = UniqueIdentifier::fromASN1($seq->at($idx++)->asBitString());
        }
        if ($seq->has($idx, Element::TYPE_SEQUENCE)) {
            $obj->extensions = Extensions::fromASN1($seq->at($idx++)->asSequence());
        }
        return $obj;
    }
    /**
     * Get self with holder.
     */
    public function withHolder(Holder $holder): self
    {
        $obj = clone $this;
        $obj->holder = $holder;
        return $obj;
    }
    /**
     * Get self with issuer.
     */
    public function withIssuer(AttCertIssuer $issuer): self
    {
        $obj = clone $this;
        $obj->issuer = $issuer;
        return $obj;
    }
    /**
     * Get self with signature algorithm identifier.
     */
    public function withSignature(SignatureAlgorithmIdentifier $algo): self
    {
        $obj = clone $this;
        $obj->signature = $algo;
        return $obj;
    }
    /**
     * Get self with serial number.
     *
     * @param int|string $serial Base 10 serial number
     */
    public function withSerialNumber(int|string $serial): self
    {
        $obj = clone $this;
        $obj->serialNumber = strval($serial);
        return $obj;
    }
    /**
     * Get self with random positive serial number.
     *
     * @param int $size Number of random bytes
     */
    public function withRandomSerialNumber(int $size): self
    {
        // ensure that first byte is always non-zero and having first bit unset
        $num = BigInteger::of(random_int(1, 0x7f));
        for ($i = 1; $i < $size; ++$i) {
            $num = $num->shiftedLeft(8);
            $num = $num->plus(random_int(0, 0xff));
        }
        return $this->withSerialNumber($num->toBase(10));
    }
    /**
     * Get self with validity period.
     */
    public function withValidity(AttCertValidityPeriod $validity): self
    {
        $obj = clone $this;
        $obj->attrCertValidityPeriod = $validity;
        return $obj;
    }
    /**
     * Get self with attributes.
     */
    public function withAttributes(Attributes $attribs): self
    {
        $obj = clone $this;
        $obj->attributes = $attribs;
        return $obj;
    }
    /**
     * Get self with issuer unique identifier.
     */
    public function withIssuerUniqueID(UniqueIdentifier $uid): self
    {
        $obj = clone $this;
        $obj->issuerUniqueID = $uid;
        return $obj;
    }
    /**
     * Get self with extensions.
     */
    public function withExtensions(Extensions $extensions): self
    {
        $obj = clone $this;
        $obj->extensions = $extensions;
        return $obj;
    }
    /**
     * Get self with extensions added.
     *
     * @param Extension ...$exts One or more Extension objects
     */
    public function withAdditionalExtensions(Extension ...$exts): self
    {
        $obj = clone $this;
        $obj->extensions = $obj->extensions->withExtensions(...$exts);
        return $obj;
    }
    public function version(): int
    {
        return $this->version;
    }
    /**
     * Get AC holder.
     */
    public function holder(): Holder
    {
        return $this->holder;
    }
    /**
     * Get AC issuer.
     */
    public function issuer(): AttCertIssuer
    {
        return $this->issuer;
    }
    /**
     * Check whether signature is set.
     */
    public function hasSignature(): bool
    {
        return $this->signature !== null;
    }
    /**
     * Get signature algorithm identifier.
     */
    public function signature(): SignatureAlgorithmIdentifier
    {
        if (!$this->hasSignature()) {
            throw new LogicException('signature not set.');
        }
        return $this->signature;
    }
    /**
     * Check whether serial number is present.
     */
    public function hasSerialNumber(): bool
    {
        return isset($this->serialNumber);
    }
    /**
     * Get AC serial number as a base 10 integer.
     */
    public function serialNumber(): string
    {
        if (!$this->hasSerialNumber()) {
            throw new LogicException('serialNumber not set.');
        }
        return $this->serialNumber;
    }
    /**
     * Get validity period.
     */
    public function validityPeriod(): AttCertValidityPeriod
    {
        return $this->attrCertValidityPeriod;
    }
    public function attributes(): Attributes
    {
        return $this->attributes;
    }
    /**
     * Check whether issuer unique identifier is present.
     */
    public function hasIssuerUniqueID(): bool
    {
        return isset($this->issuerUniqueID);
    }
    /**
     * Get issuer unique identifier.
     */
    public function issuerUniqueID(): UniqueIdentifier
    {
        if (!$this->hasIssuerUniqueID()) {
            throw new LogicException('issuerUniqueID not set.');
        }
        return $this->issuerUniqueID;
    }
    public function extensions(): Extensions
    {
        return $this->extensions;
    }
    /**
     * Get ASN.1 structure.
     */
    public function toASN1(): Sequence
    {
        $elements = [Integer::create($this->version), $this->holder->toASN1(), $this->issuer->toASN1(), $this->signature()->toASN1(), Integer::create($this->serialNumber()), $this->attrCertValidityPeriod->toASN1(), $this->attributes->toASN1()];
        if (isset($this->issuerUniqueID)) {
            $elements[] = $this->issuerUniqueID->toASN1();
        }
        if (count($this->extensions) !== 0) {
            $elements[] = $this->extensions->toASN1();
        }
        return Sequence::create(...$elements);
    }
    /**
     * Create signed attribute certificate.
     *
     * @param SignatureAlgorithmIdentifier $algo Signature algorithm
     * @param PrivateKeyInfo $privkey_info Private key
     * @param null|Crypto $crypto Crypto engine, use default if not set
     */
    public function sign(SignatureAlgorithmIdentifier $algo, PrivateKeyInfo $privkey_info, ?Crypto $crypto = null): AttributeCertificate
    {
        $crypto ??= Crypto::getDefault();
        $aci = clone $this;
        if (!isset($aci->serialNumber)) {
            $aci->serialNumber = '0';
        }
        $aci->signature = $algo;
        $data = $aci->toASN1()->toDER();
        $signature = $crypto->sign($data, $privkey_info, $algo);
        return AttributeCertificate::create($aci, $algo, $signature);
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\X509\AttributeCertificate;

use _ContaoManager\SpomkyLabs\Pki\ASN1\Element;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Constructed\Sequence;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Primitive\BitString;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Primitive\Enumerated;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Primitive\ObjectIdentifier;
use _ContaoManager\SpomkyLabs\Pki\CryptoTypes\AlgorithmIdentifier\AlgorithmIdentifier;
use _ContaoManager\SpomkyLabs\Pki\CryptoTypes\AlgorithmIdentifier\Feature\AlgorithmIdentifierType;
/**
 * Implements *ObjectDigestInfo* ASN.1 type.
 *
 * @see https://tools.ietf.org/html/rfc5755#section-4.1
 * @see https://tools.ietf.org/html/rfc5755#section-7.3
 */
final class ObjectDigestInfo
{
    final public const TYPE_PUBLIC_KEY = 0;
    final public const TYPE_PUBLIC_KEY_CERT = 1;
    final public const TYPE_OTHER_OBJECT_TYPES = 2;
    private function __construct(private readonly int $digestedObjectType, private readonly AlgorithmIdentifierType $digestAlgorithm, private readonly BitString $objectDigest, private readonly ?string $otherObjectTypeID)
    {
    }
    public static function create(int $digestedObjectType, AlgorithmIdentifierType $digestAlgorithm, BitString $objectDigest, ?string $otherObjectTypeID = null): self
    {
        return new self($digestedObjectType, $digestAlgorithm, $objectDigest, $otherObjectTypeID);
    }
    /**
     * Initialize from ASN.1.
     */
    public static function fromASN1(Sequence $seq): self
    {
        $idx = 0;
        $oid = null;
        $type = $seq->at($idx++)->asEnumerated()->intNumber();
        if ($seq->has($idx, Element::TYPE_OBJECT_IDENTIFIER)) {
            $oid = $seq->at($idx++)->asObjectIdentifier()->oid();
        }
        $algo = AlgorithmIdentifier::fromASN1($seq->at($idx++)->asSequence());
        $digest = $seq->at($idx)->asBitString();
        return self::create($type, $algo, $digest, $oid);
    }
    /**
     * Generate ASN.1 structure.
     */
    public function toASN1(): Sequence
    {
        $elements = [Enumerated::create($this->digestedObjectType)];
        if (isset($this->otherObjectTypeID)) {
            $elements[] = ObjectIdentifier::create($this->otherObjectTypeID);
        }
        $elements[] = $this->digestAlgorithm->toASN1();
        $elements[] = $this->objectDigest;
        return Sequence::create(...$elements);
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\X509\AttributeCertificate;

use _ContaoManager\SpomkyLabs\Pki\ASN1\Element;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\UnspecifiedType;
use _ContaoManager\SpomkyLabs\Pki\X501\ASN1\Name;
use _ContaoManager\SpomkyLabs\Pki\X509\Certificate\Certificate;
use _ContaoManager\SpomkyLabs\Pki\X509\GeneralName\DirectoryName;
use _ContaoManager\SpomkyLabs\Pki\X509\GeneralName\GeneralNames;
use UnexpectedValueException;
/**
 * Base class implementing *AttCertIssuer* ASN.1 CHOICE type.
 *
 * @see https://tools.ietf.org/html/rfc5755#section-4.1
 */
abstract class AttCertIssuer
{
    /**
     * Generate ASN.1 element.
     */
    abstract public function toASN1(): Element;
    /**
     * Check whether AttCertIssuer identifies given certificate.
     */
    abstract public function identifiesPKC(Certificate $cert): bool;
    /**
     * Initialize from distinguished name.
     *
     * This conforms to RFC 5755 which states that only v2Form must be used, and issuerName must contain exactly one
     * GeneralName of DirectoryName type.
     *
     * @see https://tools.ietf.org/html/rfc5755#section-4.2.3
     */
    public static function fromName(Name $name): self
    {
        return V2Form::create(GeneralNames::create(DirectoryName::create($name)));
    }
    /**
     * Initialize from an issuer's public key certificate.
     */
    public static function fromPKC(Certificate $cert): self
    {
        return self::fromName($cert->tbsCertificate()->subject());
    }
    /**
     * Initialize from ASN.1.
     *
     * @param UnspecifiedType $el CHOICE
     */
    public static function fromASN1(UnspecifiedType $el): self
    {
        if (!$el->isTagged()) {
            throw new UnexpectedValueException('v1Form issuer not supported.');
        }
        $tagged = $el->asTagged();
        return match ($tagged->tag()) {
            0 => V2Form::fromV2ASN1($tagged->asImplicit(Element::TYPE_SEQUENCE)->asSequence()),
            default => throw new UnexpectedValueException('Unsupported issuer type.'),
        };
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\X509\AttributeCertificate;

use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Constructed\Sequence;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\UnspecifiedType;
use _ContaoManager\SpomkyLabs\Pki\CryptoBridge\Crypto;
use _ContaoManager\SpomkyLabs\Pki\CryptoEncoding\PEM;
use _ContaoManager\SpomkyLabs\Pki\CryptoTypes\AlgorithmIdentifier\AlgorithmIdentifier;
use _ContaoManager\SpomkyLabs\Pki\CryptoTypes\AlgorithmIdentifier\Feature\SignatureAlgorithmIdentifier;
use _ContaoManager\SpomkyLabs\Pki\CryptoTypes\Asymmetric\PublicKeyInfo;
use _ContaoManager\SpomkyLabs\Pki\CryptoTypes\Signature\Signature;
use _ContaoManager\SpomkyLabs\Pki\X509\Certificate\Certificate;
use Stringable;
use UnexpectedValueException;
/**
 * Implements *AttributeCertificate* ASN.1 type.
 *
 * @see https://tools.ietf.org/html/rfc5755#section-4.1
 */
final class AttributeCertificate implements Stringable
{
    private function __construct(private readonly AttributeCertificateInfo $acInfo, private readonly SignatureAlgorithmIdentifier $signatureAlgorithm, private readonly Signature $signatureValue)
    {
    }
    /**
     * Get attribute certificate as a PEM formatted string.
     */
    public function __toString(): string
    {
        return $this->toPEM()->string();
    }
    public static function create(AttributeCertificateInfo $acInfo, SignatureAlgorithmIdentifier $signatureAlgorithm, Signature $signatureValue): self
    {
        return new self($acInfo, $signatureAlgorithm, $signatureValue);
    }
    /**
     * Initialize from ASN.1.
     */
    public static function fromASN1(Sequence $seq): self
    {
        $acinfo = AttributeCertificateInfo::fromASN1($seq->at(0)->asSequence());
        $algo = AlgorithmIdentifier::fromASN1($seq->at(1)->asSequence());
        if (!$algo instanceof SignatureAlgorithmIdentifier) {
            throw new UnexpectedValueException('Unsupported signature algorithm ' . $algo->oid() . '.');
        }
        $signature = Signature::fromSignatureData($seq->at(2)->asBitString()->string(), $algo);
        return self::create($acinfo, $algo, $signature);
    }
    /**
     * Initialize from DER data.
     */
    public static function fromDER(string $data): self
    {
        return self::fromASN1(UnspecifiedType::fromDER($data)->asSequence());
    }
    /**
     * Initialize from PEM.
     */
    public static function fromPEM(PEM $pem): self
    {
        if ($pem->type() !== PEM::TYPE_ATTRIBUTE_CERTIFICATE) {
            throw new UnexpectedValueException('Invalid PEM type.');
        }
        return self::fromDER($pem->data());
    }
    /**
     * Get attribute certificate info.
     */
    public function acinfo(): AttributeCertificateInfo
    {
        return $this->acInfo;
    }
    /**
     * Get signature algorithm identifier.
     */
    public function signatureAlgorithm(): SignatureAlgorithmIdentifier
    {
        return $this->signatureAlgorithm;
    }
    /**
     * Get signature value.
     */
    public function signatureValue(): Signature
    {
        return $this->signatureValue;
    }
    /**
     * Get ASN.1 structure.
     */
    public function toASN1(): Sequence
    {
        return Sequence::create($this->acInfo->toASN1(), $this->signatureAlgorithm->toASN1(), $this->signatureValue->bitString());
    }
    /**
     * Get attribute certificate as a DER.
     */
    public function toDER(): string
    {
        return $this->toASN1()->toDER();
    }
    /**
     * Get attribute certificate as a PEM.
     */
    public function toPEM(): PEM
    {
        return PEM::create(PEM::TYPE_ATTRIBUTE_CERTIFICATE, $this->toDER());
    }
    /**
     * Check whether attribute certificate is issued to the subject identified by given public key certificate.
     *
     * @param Certificate $cert Certificate
     */
    public function isHeldBy(Certificate $cert): bool
    {
        if (!$this->acInfo->holder()->identifiesPKC($cert)) {
            return \false;
        }
        return \true;
    }
    /**
     * Check whether attribute certificate is issued by given public key certificate.
     *
     * @param Certificate $cert Certificate
     */
    public function isIssuedBy(Certificate $cert): bool
    {
        if (!$this->acInfo->issuer()->identifiesPKC($cert)) {
            return \false;
        }
        return \true;
    }
    /**
     * Verify signature.
     *
     * @param PublicKeyInfo $pubkey_info Signer's public key
     * @param null|Crypto $crypto Crypto engine, use default if not set
     */
    public function verify(PublicKeyInfo $pubkey_info, ?Crypto $crypto = null): bool
    {
        $crypto ??= Crypto::getDefault();
        $data = $this->acInfo->toASN1()->toDER();
        return $crypto->verify($data, $this->signatureValue, $pubkey_info, $this->signatureAlgorithm);
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\X509\AttributeCertificate;

use DateTimeImmutable;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Constructed\Sequence;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Primitive\GeneralizedTime;
use _ContaoManager\SpomkyLabs\Pki\X509\Feature\DateTimeHelper;
/**
 * Implements *AttCertValidityPeriod* ASN.1 type.
 *
 * @see https://tools.ietf.org/html/rfc5755#section-4.1
 */
final class AttCertValidityPeriod
{
    use DateTimeHelper;
    private function __construct(private readonly DateTimeImmutable $notBeforeTime, private readonly DateTimeImmutable $notAfterTime)
    {
    }
    public static function create(DateTimeImmutable $notBeforeTime, DateTimeImmutable $notAfterTime): self
    {
        return new self($notBeforeTime, $notAfterTime);
    }
    /**
     * Initialize from ASN.1.
     */
    public static function fromASN1(Sequence $seq): self
    {
        $nb = $seq->at(0)->asGeneralizedTime()->dateTime();
        $na = $seq->at(1)->asGeneralizedTime()->dateTime();
        return self::create($nb, $na);
    }
    /**
     * Initialize from date strings.
     *
     * @param null|string $nb_date Not before date
     * @param null|string $na_date Not after date
     * @param null|string $tz Timezone string
     */
    public static function fromStrings(?string $nb_date, ?string $na_date, ?string $tz = null): self
    {
        $nb = self::createDateTime($nb_date, $tz);
        $na = self::createDateTime($na_date, $tz);
        return self::create($nb, $na);
    }
    /**
     * Get not before time.
     */
    public function notBeforeTime(): DateTimeImmutable
    {
        return $this->notBeforeTime;
    }
    /**
     * Get not after time.
     */
    public function notAfterTime(): DateTimeImmutable
    {
        return $this->notAfterTime;
    }
    /**
     * Generate ASN.1 structure.
     */
    public function toASN1(): Sequence
    {
        return Sequence::create(GeneralizedTime::create($this->notBeforeTime), GeneralizedTime::create($this->notAfterTime));
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\X509\AttributeCertificate\Validation;

use function count;
use _ContaoManager\SpomkyLabs\Pki\CryptoBridge\Crypto;
use _ContaoManager\SpomkyLabs\Pki\X509\AttributeCertificate\AttributeCertificate;
use _ContaoManager\SpomkyLabs\Pki\X509\AttributeCertificate\Validation\Exception\ACValidationException;
use _ContaoManager\SpomkyLabs\Pki\X509\Certificate\Certificate;
use _ContaoManager\SpomkyLabs\Pki\X509\Certificate\Extension\Extension;
use _ContaoManager\SpomkyLabs\Pki\X509\Certificate\Extension\Target\Targets;
use _ContaoManager\SpomkyLabs\Pki\X509\Certificate\Extension\TargetInformationExtension;
use _ContaoManager\SpomkyLabs\Pki\X509\CertificationPath\Exception\PathValidationException;
use _ContaoManager\SpomkyLabs\Pki\X509\CertificationPath\PathValidation\PathValidationConfig;
/**
 * Implements attribute certificate validation conforming to RFC 5755.
 *
 * @see https://tools.ietf.org/html/rfc5755#section-5
 */
final class ACValidator
{
    /**
     * Crypto engine.
     */
    private readonly Crypto $crypto;
    /**
     * @param AttributeCertificate $ac Attribute certificate to validate
     * @param ACValidationConfig $config Validation configuration
     * @param null|Crypto $crypto Crypto engine, use default if not set
     */
    private function __construct(private readonly AttributeCertificate $ac, private readonly ACValidationConfig $config, ?Crypto $crypto)
    {
        $this->crypto = $crypto ?? Crypto::getDefault();
    }
    public static function create(AttributeCertificate $ac, ACValidationConfig $config, ?Crypto $crypto = null): self
    {
        return new self($ac, $config, $crypto);
    }
    /**
     * Validate attribute certificate.
     *
     * @return AttributeCertificate Validated AC
     */
    public function validate(): AttributeCertificate
    {
        $this->validateHolder();
        $issuer = $this->verifyIssuer();
        $this->validateIssuerProfile($issuer);
        $this->validateTime();
        $this->validateTargeting();
        return $this->ac;
    }
    /**
     * Validate AC holder's certification.
     *
     * @return Certificate Certificate of the AC's holder
     */
    private function validateHolder(): Certificate
    {
        $path = $this->config->holderPath();
        $config = PathValidationConfig::defaultConfig()->withMaxLength(count($path))->withDateTime($this->config->evaluationTime());
        try {
            $holder = $path->validate($config, $this->crypto)->certificate();
        } catch (PathValidationException $e) {
            throw new ACValidationException("Failed to validate holder PKC's certification path.", 0, $e);
        }
        if (!$this->ac->isHeldBy($holder)) {
            throw new ACValidationException("Name mismatch of AC's holder PKC.");
        }
        return $holder;
    }
    /**
     * Verify AC's signature and issuer's certification.
     *
     * @return Certificate Certificate of the AC's issuer
     */
    private function verifyIssuer(): Certificate
    {
        $path = $this->config->issuerPath();
        $config = PathValidationConfig::defaultConfig()->withMaxLength(count($path))->withDateTime($this->config->evaluationTime());
        try {
            $issuer = $path->validate($config, $this->crypto)->certificate();
        } catch (PathValidationException $e) {
            throw new ACValidationException("Failed to validate issuer PKC's certification path.", 0, $e);
        }
        if (!$this->ac->isIssuedBy($issuer)) {
            throw new ACValidationException("Name mismatch of AC's issuer PKC.");
        }
        $pubkey_info = $issuer->tbsCertificate()->subjectPublicKeyInfo();
        if (!$this->ac->verify($pubkey_info, $this->crypto)) {
            throw new ACValidationException('Failed to verify signature.');
        }
        return $issuer;
    }
    /**
     * Validate AC issuer's profile.
     *
     * @see https://tools.ietf.org/html/rfc5755#section-4.5
     */
    private function validateIssuerProfile(Certificate $cert): void
    {
        $exts = $cert->tbsCertificate()->extensions();
        if ($exts->hasKeyUsage() && !$exts->keyUsage()->isDigitalSignature()) {
            throw new ACValidationException("Issuer PKC's Key Usage extension doesn't permit" . ' verification of digital signatures.');
        }
        if ($exts->hasBasicConstraints() && $exts->basicConstraints()->isCA()) {
            throw new ACValidationException('Issuer PKC must not be a CA.');
        }
    }
    /**
     * Validate AC's validity period.
     */
    private function validateTime(): void
    {
        $t = $this->config->evaluationTime();
        $validity = $this->ac->acinfo()->validityPeriod();
        if ($validity->notBeforeTime()->diff($t)->invert === 1) {
            throw new ACValidationException('Validity period has not started.');
        }
        if ($t->diff($validity->notAfterTime())->invert === 1) {
            throw new ACValidationException('Attribute certificate has expired.');
        }
    }
    /**
     * Validate AC's target information.
     */
    private function validateTargeting(): void
    {
        $exts = $this->ac->acinfo()->extensions();
        // if target information extension is not present
        if (!$exts->has(Extension::OID_TARGET_INFORMATION)) {
            return;
        }
        $ext = $exts->get(Extension::OID_TARGET_INFORMATION);
        if ($ext instanceof TargetInformationExtension && !$this->_hasMatchingTarget($ext->targets())) {
            throw new ACValidationException("Attribute certificate doesn't have a matching target.");
        }
    }
    /**
     * Check whether validation configuration has matching targets.
     *
     * @param Targets $targets Set of eligible targets
     */
    private function _hasMatchingTarget(Targets $targets): bool
    {
        foreach ($this->config->targets() as $target) {
            if ($targets->hasTarget($target)) {
                return \true;
            }
        }
        return \false;
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\X509\AttributeCertificate\Validation\Exception;

use _ContaoManager\SpomkyLabs\Pki\X509\Exception\X509ValidationException;
final class ACValidationException extends X509ValidationException
{
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\X509\AttributeCertificate\Validation;

use DateTimeImmutable;
use _ContaoManager\Psr\Clock\ClockInterface;
use _ContaoManager\SpomkyLabs\Pki\X509\Certificate\Extension\Target\Target;
use _ContaoManager\SpomkyLabs\Pki\X509\CertificationPath\CertificationPath;
/**
 * Provides configuration context for the attribute certificate validation.
 */
final class ACValidationConfig
{
    /**
     * Evaluation reference time.
     */
    private DateTimeImmutable $evalTime;
    /**
     * Permitted targets.
     *
     * @var Target[]
     */
    private array $targets;
    /**
     * @param CertificationPath $holderPath Certification path of the AC holder
     * @param CertificationPath $issuerPath Certification path of the AC issuer
     */
    private function __construct(private readonly CertificationPath $holderPath, private readonly CertificationPath $issuerPath, ?ClockInterface $clock = null)
    {
        $this->evalTime = $clock !== null ? $clock->now() : new DateTimeImmutable();
        $this->targets = [];
    }
    public static function create(CertificationPath $holderPath, CertificationPath $issuerPath, ?ClockInterface $clock = null): self
    {
        return new self($holderPath, $issuerPath, $clock);
    }
    /**
     * Get certification path of the AC's holder.
     */
    public function holderPath(): CertificationPath
    {
        return $this->holderPath;
    }
    /**
     * Get certification path of the AC's issuer.
     */
    public function issuerPath(): CertificationPath
    {
        return $this->issuerPath;
    }
    /**
     * Get self with given evaluation reference time.
     */
    public function withEvaluationTime(DateTimeImmutable $dt): self
    {
        $obj = clone $this;
        $obj->evalTime = $dt;
        return $obj;
    }
    /**
     * Get the evaluation reference time.
     */
    public function evaluationTime(): DateTimeImmutable
    {
        return $this->evalTime;
    }
    /**
     * Get self with permitted targets.
     */
    public function withTargets(Target ...$targets): self
    {
        $obj = clone $this;
        $obj->targets = $targets;
        return $obj;
    }
    /**
     * Get array of permitted targets.
     *
     * @return Target[]
     */
    public function targets(): array
    {
        return $this->targets;
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\X509\CertificationRequest;

use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Constructed\Sequence;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\UnspecifiedType;
use _ContaoManager\SpomkyLabs\Pki\CryptoBridge\Crypto;
use _ContaoManager\SpomkyLabs\Pki\CryptoEncoding\PEM;
use _ContaoManager\SpomkyLabs\Pki\CryptoTypes\AlgorithmIdentifier\AlgorithmIdentifier;
use _ContaoManager\SpomkyLabs\Pki\CryptoTypes\AlgorithmIdentifier\Feature\SignatureAlgorithmIdentifier;
use _ContaoManager\SpomkyLabs\Pki\CryptoTypes\Signature\Signature;
use Stringable;
use UnexpectedValueException;
/**
 * Implements *CertificationRequest* ASN.1 type.
 *
 * @see https://tools.ietf.org/html/rfc2986#section-4
 */
final class CertificationRequest implements Stringable
{
    private function __construct(private readonly CertificationRequestInfo $certificationRequestInfo, private readonly SignatureAlgorithmIdentifier $signatureAlgorithm, private readonly Signature $signature)
    {
    }
    /**
     * Get certification request as a PEM formatted string.
     */
    public function __toString(): string
    {
        return $this->toPEM()->string();
    }
    public static function create(CertificationRequestInfo $_certificationRequestInfo, SignatureAlgorithmIdentifier $_signatureAlgorithm, Signature $_signature): self
    {
        return new self($_certificationRequestInfo, $_signatureAlgorithm, $_signature);
    }
    /**
     * Initialize from ASN.1.
     */
    public static function fromASN1(Sequence $seq): self
    {
        $info = CertificationRequestInfo::fromASN1($seq->at(0)->asSequence());
        $algo = AlgorithmIdentifier::fromASN1($seq->at(1)->asSequence());
        if (!$algo instanceof SignatureAlgorithmIdentifier) {
            throw new UnexpectedValueException('Unsupported signature algorithm ' . $algo->oid() . '.');
        }
        $signature = Signature::fromSignatureData($seq->at(2)->asBitString()->string(), $algo);
        return self::create($info, $algo, $signature);
    }
    /**
     * Initialize from DER.
     */
    public static function fromDER(string $data): self
    {
        return self::fromASN1(UnspecifiedType::fromDER($data)->asSequence());
    }
    /**
     * Initialize from PEM.
     */
    public static function fromPEM(PEM $pem): self
    {
        if ($pem->type() !== PEM::TYPE_CERTIFICATE_REQUEST) {
            throw new UnexpectedValueException('Invalid PEM type.');
        }
        return self::fromDER($pem->data());
    }
    /**
     * Get certification request info.
     */
    public function certificationRequestInfo(): CertificationRequestInfo
    {
        return $this->certificationRequestInfo;
    }
    /**
     * Get signature algorithm.
     */
    public function signatureAlgorithm(): SignatureAlgorithmIdentifier
    {
        return $this->signatureAlgorithm;
    }
    public function signature(): Signature
    {
        return $this->signature;
    }
    /**
     * Generate ASN.1 structure.
     */
    public function toASN1(): Sequence
    {
        return Sequence::create($this->certificationRequestInfo->toASN1(), $this->signatureAlgorithm->toASN1(), $this->signature->bitString());
    }
    /**
     * Get certification request as a DER.
     */
    public function toDER(): string
    {
        return $this->toASN1()->toDER();
    }
    /**
     * Get certification request as a PEM.
     */
    public function toPEM(): PEM
    {
        return PEM::create(PEM::TYPE_CERTIFICATE_REQUEST, $this->toDER());
    }
    /**
     * Verify certification request signature.
     *
     * @param null|Crypto $crypto Crypto engine, use default if not set
     *
     * @return bool True if signature matches
     */
    public function verify(?Crypto $crypto = null): bool
    {
        $crypto ??= Crypto::getDefault();
        $data = $this->certificationRequestInfo->toASN1()->toDER();
        $pk_info = $this->certificationRequestInfo->subjectPKInfo();
        return $crypto->verify($data, $this->signature, $pk_info, $this->signatureAlgorithm);
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\X509\CertificationRequest\Attribute;

use _ContaoManager\SpomkyLabs\Pki\ASN1\Element;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\UnspecifiedType;
use _ContaoManager\SpomkyLabs\Pki\X501\ASN1\AttributeValue\AttributeValue;
use _ContaoManager\SpomkyLabs\Pki\X501\MatchingRule\BinaryMatch;
use _ContaoManager\SpomkyLabs\Pki\X501\MatchingRule\MatchingRule;
use _ContaoManager\SpomkyLabs\Pki\X509\Certificate\Extensions;
/**
 * Implements value for 'Extension request' attribute.
 *
 * @see https://tools.ietf.org/html/rfc2985#page-17
 */
final class ExtensionRequestValue extends AttributeValue
{
    final public const OID = '1.2.840.113549.1.9.14';
    /**
     * @param Extensions $extensions Extensions.
     */
    private function __construct(protected Extensions $extensions)
    {
        parent::__construct(self::OID);
    }
    public static function create(Extensions $extensions): self
    {
        return new self($extensions);
    }
    /**
     * @return self
     */
    public static function fromASN1(UnspecifiedType $el): AttributeValue
    {
        return self::create(Extensions::fromASN1($el->asSequence()));
    }
    /**
     * Get requested extensions.
     */
    public function extensions(): Extensions
    {
        return $this->extensions;
    }
    public function toASN1(): Element
    {
        return $this->extensions->toASN1();
    }
    public function stringValue(): string
    {
        return '#' . bin2hex($this->toASN1()->toDER());
    }
    public function equalityMatchingRule(): MatchingRule
    {
        return new BinaryMatch();
    }
    public function rfc2253String(): string
    {
        return $this->stringValue();
    }
    protected function _transcodedString(): string
    {
        return $this->stringValue();
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\X509\CertificationRequest;

use LogicException;
use _ContaoManager\SpomkyLabs\Pki\X501\ASN1\Attribute;
use _ContaoManager\SpomkyLabs\Pki\X501\ASN1\AttributeValue\AttributeValue;
use _ContaoManager\SpomkyLabs\Pki\X501\ASN1\Collection\SetOfAttributes;
use _ContaoManager\SpomkyLabs\Pki\X509\CertificationRequest\Attribute\ExtensionRequestValue;
/**
 * Implements *Attributes* ASN.1 type of *CertificationRequestInfo*.
 *
 * @see https://tools.ietf.org/html/rfc2986#section-4
 */
final class Attributes extends SetOfAttributes
{
    /**
     * Mapping from OID to attribute value class name.
     *
     * @internal
     *
     * @var array<string, string>
     */
    private const MAP_OID_TO_CLASS = [ExtensionRequestValue::OID => ExtensionRequestValue::class];
    /**
     * Initialize from attribute values.
     *
     * @param AttributeValue ...$values List of attribute values
     */
    public static function fromAttributeValues(AttributeValue ...$values): static
    {
        return static::create(...array_map(static fn(AttributeValue $value) => $value->toAttribute(), $values));
    }
    /**
     * Check whether extension request attribute is present.
     */
    public function hasExtensionRequest(): bool
    {
        return $this->has(ExtensionRequestValue::OID);
    }
    /**
     * Get extension request attribute value.
     */
    public function extensionRequest(): ExtensionRequestValue
    {
        if (!$this->hasExtensionRequest()) {
            throw new LogicException('No extension request attribute.');
        }
        return $this->firstOf(ExtensionRequestValue::OID)->first();
    }
    protected static function _castAttributeValues(Attribute $attribute): Attribute
    {
        $oid = $attribute->oid();
        if (isset(self::MAP_OID_TO_CLASS[$oid])) {
            return $attribute->castValues(self::MAP_OID_TO_CLASS[$oid]);
        }
        return $attribute;
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\X509\CertificationRequest;

use LogicException;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Element;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Constructed\Sequence;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Primitive\Integer;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Tagged\ImplicitlyTaggedType;
use _ContaoManager\SpomkyLabs\Pki\CryptoBridge\Crypto;
use _ContaoManager\SpomkyLabs\Pki\CryptoTypes\AlgorithmIdentifier\Feature\SignatureAlgorithmIdentifier;
use _ContaoManager\SpomkyLabs\Pki\CryptoTypes\Asymmetric\PrivateKeyInfo;
use _ContaoManager\SpomkyLabs\Pki\CryptoTypes\Asymmetric\PublicKeyInfo;
use _ContaoManager\SpomkyLabs\Pki\X501\ASN1\Attribute;
use _ContaoManager\SpomkyLabs\Pki\X501\ASN1\Name;
use _ContaoManager\SpomkyLabs\Pki\X509\Certificate\Extensions;
use _ContaoManager\SpomkyLabs\Pki\X509\CertificationRequest\Attribute\ExtensionRequestValue;
use UnexpectedValueException;
/**
 * Implements *CertificationRequestInfo* ASN.1 type.
 *
 * @see https://tools.ietf.org/html/rfc2986#section-4
 */
final class CertificationRequestInfo
{
    final public const VERSION_1 = 0;
    /**
     * Version.
     */
    private readonly int $version;
    /**
     * Attributes.
     */
    private ?Attributes $attributes = null;
    /**
     * @param Name $subject Subject
     * @param PublicKeyInfo $subjectPKInfo Public key info
     */
    private function __construct(private Name $subject, private readonly PublicKeyInfo $subjectPKInfo)
    {
        $this->version = self::VERSION_1;
    }
    public static function create(Name $subject, PublicKeyInfo $subjectPKInfo): self
    {
        return new self($subject, $subjectPKInfo);
    }
    /**
     * Initialize from ASN.1.
     */
    public static function fromASN1(Sequence $seq): self
    {
        $version = $seq->at(0)->asInteger()->intNumber();
        if ($version !== self::VERSION_1) {
            throw new UnexpectedValueException("Version {$version} not supported.");
        }
        $subject = Name::fromASN1($seq->at(1)->asSequence());
        $pkinfo = PublicKeyInfo::fromASN1($seq->at(2)->asSequence());
        $obj = self::create($subject, $pkinfo);
        if ($seq->hasTagged(0)) {
            $obj = $obj->withAttributes(Attributes::fromASN1($seq->getTagged(0)->asImplicit(Element::TYPE_SET)->asSet()));
        }
        return $obj;
    }
    public function version(): int
    {
        return $this->version;
    }
    /**
     * Get self with subject.
     */
    public function withSubject(Name $subject): self
    {
        $obj = clone $this;
        $obj->subject = $subject;
        return $obj;
    }
    public function subject(): Name
    {
        return $this->subject;
    }
    /**
     * Get subject public key info.
     */
    public function subjectPKInfo(): PublicKeyInfo
    {
        return $this->subjectPKInfo;
    }
    /**
     * Whether certification request info has attributes.
     */
    public function hasAttributes(): bool
    {
        return isset($this->attributes);
    }
    public function attributes(): Attributes
    {
        if (!$this->hasAttributes()) {
            throw new LogicException('No attributes.');
        }
        return $this->attributes;
    }
    /**
     * Get instance of self with attributes.
     */
    public function withAttributes(Attributes $attribs): self
    {
        $obj = clone $this;
        $obj->attributes = $attribs;
        return $obj;
    }
    /**
     * Get self with extension request attribute.
     *
     * @param Extensions $extensions Extensions to request
     */
    public function withExtensionRequest(Extensions $extensions): self
    {
        $obj = clone $this;
        if (!isset($obj->attributes)) {
            $obj->attributes = Attributes::create();
        }
        $obj->attributes = $obj->attributes->withUnique(Attribute::fromAttributeValues(ExtensionRequestValue::create($extensions)));
        return $obj;
    }
    /**
     * Generate ASN.1 structure.
     */
    public function toASN1(): Sequence
    {
        $elements = [Integer::create($this->version), $this->subject->toASN1(), $this->subjectPKInfo->toASN1()];
        if (isset($this->attributes)) {
            $elements[] = ImplicitlyTaggedType::create(0, $this->attributes->toASN1());
        }
        return Sequence::create(...$elements);
    }
    /**
     * Create signed CertificationRequest.
     *
     * @param SignatureAlgorithmIdentifier $algo Algorithm used for signing
     * @param PrivateKeyInfo $privkey_info Private key used for signing
     * @param null|Crypto $crypto Crypto engine, use default if not set
     */
    public function sign(SignatureAlgorithmIdentifier $algo, PrivateKeyInfo $privkey_info, ?Crypto $crypto = null): CertificationRequest
    {
        $crypto ??= Crypto::getDefault();
        $data = $this->toASN1()->toDER();
        $signature = $crypto->sign($data, $privkey_info, $algo);
        return CertificationRequest::create($this, $algo, $signature);
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\X501\ASN1;

use ArrayIterator;
use function count;
use Countable;
use IteratorAggregate;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Constructed\Set;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\UnspecifiedType;
use _ContaoManager\SpomkyLabs\Pki\X501\ASN1\AttributeValue\AttributeValue;
use Stringable;
use UnexpectedValueException;
/**
 * Implements *RelativeDistinguishedName* ASN.1 type.
 *
 * @see https://www.itu.int/ITU-T/formal-language/itu-t/x/x501/2012/InformationFramework.html#InformationFramework.RelativeDistinguishedName
 */
final class RDN implements Countable, IteratorAggregate, Stringable
{
    /**
     * Attributes.
     *
     * @var AttributeTypeAndValue[]
     */
    private readonly array $_attribs;
    /**
     * @param AttributeTypeAndValue ...$attribs One or more attributes
     */
    private function __construct(AttributeTypeAndValue ...$attribs)
    {
        if (count($attribs) === 0) {
            throw new UnexpectedValueException('RDN must have at least one AttributeTypeAndValue.');
        }
        $this->_attribs = $attribs;
    }
    public function __toString(): string
    {
        return $this->toString();
    }
    public static function create(AttributeTypeAndValue ...$attribs): self
    {
        return new self(...$attribs);
    }
    /**
     * Convenience method to initialize RDN from AttributeValue objects.
     *
     * @param AttributeValue ...$values One or more attributes
     */
    public static function fromAttributeValues(AttributeValue ...$values): self
    {
        $attribs = array_map(static fn(AttributeValue $value) => AttributeTypeAndValue::create(AttributeType::create($value->oid()), $value), $values);
        return self::create(...$attribs);
    }
    /**
     * Initialize from ASN.1.
     */
    public static function fromASN1(Set $set): self
    {
        $attribs = array_map(static fn(UnspecifiedType $el) => AttributeTypeAndValue::fromASN1($el->asSequence()), $set->elements());
        return self::create(...$attribs);
    }
    /**
     * Generate ASN.1 structure.
     */
    public function toASN1(): Set
    {
        $elements = array_map(static fn(AttributeTypeAndValue $tv) => $tv->toASN1(), $this->_attribs);
        return Set::create(...$elements)->sortedSetOf();
    }
    /**
     * Get name-component string conforming to RFC 2253.
     *
     * @see https://tools.ietf.org/html/rfc2253#section-2.2
     */
    public function toString(): string
    {
        $parts = array_map(static fn(AttributeTypeAndValue $tv) => $tv->toString(), $this->_attribs);
        return implode('+', $parts);
    }
    /**
     * Check whether RDN is semantically equal to other.
     *
     * @param RDN $other Object to compare to
     */
    public function equals(self $other): bool
    {
        // if attribute count doesn't match
        if (count($this) !== count($other)) {
            return \false;
        }
        $attribs1 = $this->_attribs;
        $attribs2 = $other->_attribs;
        // if there's multiple attributes, sort using SET OF rules
        if (count($attribs1) > 1) {
            $attribs1 = self::fromASN1($this->toASN1())->_attribs;
            $attribs2 = self::fromASN1($other->toASN1())->_attribs;
        }
        for ($i = count($attribs1) - 1; $i >= 0; --$i) {
            $tv1 = $attribs1[$i];
            $tv2 = $attribs2[$i];
            if (!$tv1->equals($tv2)) {
                return \false;
            }
        }
        return \true;
    }
    /**
     * Get all AttributeTypeAndValue objects.
     *
     * @return AttributeTypeAndValue[]
     */
    public function all(): array
    {
        return $this->_attribs;
    }
    /**
     * Get all AttributeTypeAndValue objects of the given attribute type.
     *
     * @param string $name Attribute OID or name
     *
     * @return AttributeTypeAndValue[]
     */
    public function allOf(string $name): array
    {
        $oid = AttributeType::attrNameToOID($name);
        $attribs = array_filter($this->_attribs, static fn(AttributeTypeAndValue $tv) => $tv->oid() === $oid);
        return array_values($attribs);
    }
    /**
     * @see \Countable::count()
     */
    public function count(): int
    {
        return count($this->_attribs);
    }
    /**
     * @see \IteratorAggregate::getIterator()
     */
    public function getIterator(): ArrayIterator
    {
        return new ArrayIterator($this->_attribs);
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\X501\ASN1;

use function array_key_exists;
use OutOfBoundsException;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Element;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Primitive\ObjectIdentifier;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Primitive\PrintableString;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Primitive\UTF8String;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\StringType;
/**
 * Implements *AttributeType* ASN.1 type.
 *
 * @see https://www.itu.int/ITU-T/formal-language/itu-t/x/x501/2012/InformationFramework.html#InformationFramework.AttributeType
 */
final class AttributeType
{
    // OID's from 2.5.4 arc
    final public const OID_OBJECT_CLASS = '2.5.4.0';
    final public const OID_ALIASED_ENTRY_NAME = '2.5.4.1';
    final public const OID_KNOWLEDGE_INFORMATION = '2.5.4.2';
    final public const OID_COMMON_NAME = '2.5.4.3';
    final public const OID_SURNAME = '2.5.4.4';
    final public const OID_SERIAL_NUMBER = '2.5.4.5';
    final public const OID_COUNTRY_NAME = '2.5.4.6';
    final public const OID_LOCALITY_NAME = '2.5.4.7';
    final public const OID_STATE_OR_PROVINCE_NAME = '2.5.4.8';
    final public const OID_STREET_ADDRESS = '2.5.4.9';
    final public const OID_ORGANIZATION_NAME = '2.5.4.10';
    final public const OID_ORGANIZATIONAL_UNIT_NAME = '2.5.4.11';
    final public const OID_TITLE = '2.5.4.12';
    final public const OID_DESCRIPTION = '2.5.4.13';
    final public const OID_SEARCH_GUIDE = '2.5.4.14';
    final public const OID_BUSINESS_CATEGORY = '2.5.4.15';
    final public const OID_POSTAL_ADDRESS = '2.5.4.16';
    final public const OID_POSTAL_CODE = '2.5.4.17';
    final public const OID_POST_OFFICE_BOX = '2.5.4.18';
    final public const OID_PHYSICAL_DELIVERY_OFFICE_NAME = '2.5.4.19';
    final public const OID_TELEPHONE_NUMBER = '2.5.4.20';
    final public const OID_TELEX_NUMBER = '2.5.4.21';
    final public const OID_TELETEX_TERMINAL_IDENTIFIER = '2.5.4.22';
    final public const OID_FACSIMILE_TELEPHONE_NUMBER = '2.5.4.23';
    final public const OID_X121_ADDRESS = '2.5.4.24';
    final public const OID_INTERNATIONAL_ISDN_NUMBER = '2.5.4.25';
    final public const OID_REGISTERED_ADDRESS = '2.5.4.26';
    final public const OID_DESTINATION_INDICATOR = '2.5.4.27';
    final public const OID_PREFERRED_DELIVERY_METHOD = '2.5.4.28';
    final public const OID_PRESENTATION_ADDRESS = '2.5.4.29';
    final public const OID_SUPPORTED_APPLICATION_CONTEXT = '2.5.4.30';
    final public const OID_MEMBER = '2.5.4.31';
    final public const OID_OWNER = '2.5.4.32';
    final public const OID_ROLE_OCCUPANT = '2.5.4.33';
    final public const OID_SEE_ALSO = '2.5.4.34';
    final public const OID_USER_PASSWORD = '2.5.4.35';
    final public const OID_USER_CERTIFICATE = '2.5.4.36';
    final public const OID_CA_CERTIFICATE = '2.5.4.37';
    final public const OID_AUTHORITY_REVOCATION_LIST = '2.5.4.38';
    final public const OID_CERTIFICATE_REVOCATION_LIST = '2.5.4.39';
    final public const OID_CROSS_CERTIFICATE_PAIR = '2.5.4.40';
    final public const OID_NAME = '2.5.4.41';
    final public const OID_GIVEN_NAME = '2.5.4.42';
    final public const OID_INITIALS = '2.5.4.43';
    final public const OID_GENERATION_QUALIFIER = '2.5.4.44';
    final public const OID_UNIQUE_IDENTIFIER = '2.5.4.45';
    final public const OID_DN_QUALIFIER = '2.5.4.46';
    final public const OID_ENHANCED_SEARCH_GUIDE = '2.5.4.47';
    final public const OID_PROTOCOL_INFORMATION = '2.5.4.48';
    final public const OID_DISTINGUISHED_NAME = '2.5.4.49';
    final public const OID_UNIQUE_MEMBER = '2.5.4.50';
    final public const OID_HOUSE_IDENTIFIER = '2.5.4.51';
    final public const OID_SUPPORTED_ALGORITHMS = '2.5.4.52';
    final public const OID_DELTA_REVOCATION_LIST = '2.5.4.53';
    final public const OID_DMD_NAME = '2.5.4.54';
    final public const OID_CLEARANCE = '2.5.4.55';
    final public const OID_DEFAULT_DIR_QOP = '2.5.4.56';
    final public const OID_ATTRIBUTE_INTEGRITY_INFO = '2.5.4.57';
    final public const OID_ATTRIBUTE_CERTIFICATE = '2.5.4.58';
    final public const OID_ATTRIBUTE_CERTIFICATE_REVOCATION_LIST = '2.5.4.59';
    final public const OID_CONF_KEY_INFO = '2.5.4.60';
    final public const OID_AA_CERTIFICATE = '2.5.4.61';
    final public const OID_ATTRIBUTE_DESCRIPTOR_CERTIFICATE = '2.5.4.62';
    final public const OID_ATTRIBUTE_AUTHORITY_REVOCATION_LIST = '2.5.4.63';
    final public const OID_FAMILY_INFORMATION = '2.5.4.64';
    final public const OID_PSEUDONYM = '2.5.4.65';
    final public const OID_COMMUNICATIONS_SERVICE = '2.5.4.66';
    final public const OID_COMMUNICATIONS_NETWORK = '2.5.4.67';
    final public const OID_CERTIFICATION_PRACTICE_STMT = '2.5.4.68';
    final public const OID_CERTIFICATE_POLICY = '2.5.4.69';
    final public const OID_PKI_PATH = '2.5.4.70';
    final public const OID_PRIV_POLICY = '2.5.4.71';
    final public const OID_ROLE = '2.5.4.72';
    final public const OID_DELEGATION_PATH = '2.5.4.73';
    final public const OID_PROT_PRIV_POLICY = '2.5.4.74';
    final public const OID_XML_PRIVILEGE_INFO = '2.5.4.75';
    final public const OID_XML_PRIV_POLICY = '2.5.4.76';
    final public const OID_UUID_PAIR = '2.5.4.77';
    final public const OID_TAG_OID = '2.5.4.78';
    final public const OID_UII_FORMAT = '2.5.4.79';
    final public const OID_UII_IN_URH = '2.5.4.80';
    final public const OID_CONTENT_URL = '2.5.4.81';
    final public const OID_PERMISSION = '2.5.4.82';
    final public const OID_URI = '2.5.4.83';
    final public const OID_PWD_ATTRIBUTE = '2.5.4.84';
    final public const OID_USER_PWD = '2.5.4.85';
    final public const OID_URN = '2.5.4.86';
    final public const OID_URL = '2.5.4.87';
    final public const OID_UTM_COORDINATES = '2.5.4.88';
    final public const OID_URNC = '2.5.4.89';
    final public const OID_UII = '2.5.4.90';
    final public const OID_EPC = '2.5.4.91';
    final public const OID_TAG_AFI = '2.5.4.92';
    final public const OID_EPC_FORMAT = '2.5.4.93';
    final public const OID_EPC_IN_URN = '2.5.4.94';
    final public const OID_LDAP_URL = '2.5.4.95';
    final public const OID_TAG_LOCATION = '2.5.4.96';
    final public const OID_ORGANIZATION_IDENTIFIER = '2.5.4.97';
    // Miscellany attribute OID's
    final public const OID_CLEARANCE_X501 = '2.5.1.5.55';
    /**
     * Default ASN.1 string types for attributes.
     *
     * Attributes not mapped here shall use UTF8String as a default type.
     *
     * @internal
     *
     * @var array<string, int>
     */
    private const MAP_ATTR_TO_STR_TYPE = [self::OID_DN_QUALIFIER => Element::TYPE_PRINTABLE_STRING, self::OID_COUNTRY_NAME => Element::TYPE_PRINTABLE_STRING, self::OID_SERIAL_NUMBER => Element::TYPE_PRINTABLE_STRING];
    /**
     * OID to attribute names mapping.
     *
     * First name is the primary name. If there's more than one name, others may be used as an alias.
     *
     * Generated using ldap-attribs.py.
     *
     * @internal
     *
     * @var array<string, array<string>>
     */
    private const MAP_OID_TO_NAME = ['0.9.2342.19200300.100.1.1' => ['uid', 'userid'], '0.9.2342.19200300.100.1.2' => ['textEncodedORAddress'], '0.9.2342.19200300.100.1.3' => ['mail', 'rfc822Mailbox'], '0.9.2342.19200300.100.1.4' => ['info'], '0.9.2342.19200300.100.1.5' => ['drink', 'favouriteDrink'], '0.9.2342.19200300.100.1.6' => ['roomNumber'], '0.9.2342.19200300.100.1.7' => ['photo'], '0.9.2342.19200300.100.1.8' => ['userClass'], '0.9.2342.19200300.100.1.9' => ['host'], '0.9.2342.19200300.100.1.10' => ['manager'], '0.9.2342.19200300.100.1.11' => ['documentIdentifier'], '0.9.2342.19200300.100.1.12' => ['documentTitle'], '0.9.2342.19200300.100.1.13' => ['documentVersion'], '0.9.2342.19200300.100.1.14' => ['documentAuthor'], '0.9.2342.19200300.100.1.15' => ['documentLocation'], '0.9.2342.19200300.100.1.20' => ['homePhone', 'homeTelephoneNumber'], '0.9.2342.19200300.100.1.21' => ['secretary'], '0.9.2342.19200300.100.1.22' => ['otherMailbox'], '0.9.2342.19200300.100.1.25' => ['dc', 'domainComponent'], '0.9.2342.19200300.100.1.26' => ['aRecord'], '0.9.2342.19200300.100.1.27' => ['mDRecord'], '0.9.2342.19200300.100.1.28' => ['mXRecord'], '0.9.2342.19200300.100.1.29' => ['nSRecord'], '0.9.2342.19200300.100.1.30' => ['sOARecord'], '0.9.2342.19200300.100.1.31' => ['cNAMERecord'], '0.9.2342.19200300.100.1.37' => ['associatedDomain'], '0.9.2342.19200300.100.1.38' => ['associatedName'], '0.9.2342.19200300.100.1.39' => ['homePostalAddress'], '0.9.2342.19200300.100.1.40' => ['personalTitle'], '0.9.2342.19200300.100.1.41' => ['mobile', 'mobileTelephoneNumber'], '0.9.2342.19200300.100.1.42' => ['pager', 'pagerTelephoneNumber'], '0.9.2342.19200300.100.1.43' => ['co', 'friendlyCountryName'], '0.9.2342.19200300.100.1.44' => ['uniqueIdentifier'], '0.9.2342.19200300.100.1.45' => ['organizationalStatus'], '0.9.2342.19200300.100.1.46' => ['janetMailbox'], '0.9.2342.19200300.100.1.47' => ['mailPreferenceOption'], '0.9.2342.19200300.100.1.48' => ['buildingName'], '0.9.2342.19200300.100.1.49' => ['dSAQuality'], '0.9.2342.19200300.100.1.50' => ['singleLevelQuality'], '0.9.2342.19200300.100.1.51' => ['subtreeMinimumQuality'], '0.9.2342.19200300.100.1.52' => ['subtreeMaximumQuality'], '0.9.2342.19200300.100.1.53' => ['personalSignature'], '0.9.2342.19200300.100.1.54' => ['dITRedirect'], '0.9.2342.19200300.100.1.55' => ['audio'], '0.9.2342.19200300.100.1.56' => ['documentPublisher'], '0.9.2342.19200300.100.1.60' => ['jpegPhoto'], '1.2.840.113549.1.9.1' => ['email', 'emailAddress', 'pkcs9email'], '1.2.840.113556.1.2.102' => ['memberOf'], '1.3.6.1.1.1.1.0' => ['uidNumber'], '1.3.6.1.1.1.1.1' => ['gidNumber'], '1.3.6.1.1.1.1.2' => ['gecos'], '1.3.6.1.1.1.1.3' => ['homeDirectory'], '1.3.6.1.1.1.1.4' => ['loginShell'], '1.3.6.1.1.1.1.5' => ['shadowLastChange'], '1.3.6.1.1.1.1.6' => ['shadowMin'], '1.3.6.1.1.1.1.7' => ['shadowMax'], '1.3.6.1.1.1.1.8' => ['shadowWarning'], '1.3.6.1.1.1.1.9' => ['shadowInactive'], '1.3.6.1.1.1.1.10' => ['shadowExpire'], '1.3.6.1.1.1.1.11' => ['shadowFlag'], '1.3.6.1.1.1.1.12' => ['memberUid'], '1.3.6.1.1.1.1.13' => ['memberNisNetgroup'], '1.3.6.1.1.1.1.14' => ['nisNetgroupTriple'], '1.3.6.1.1.1.1.15' => ['ipServicePort'], '1.3.6.1.1.1.1.16' => ['ipServiceProtocol'], '1.3.6.1.1.1.1.17' => ['ipProtocolNumber'], '1.3.6.1.1.1.1.18' => ['oncRpcNumber'], '1.3.6.1.1.1.1.19' => ['ipHostNumber'], '1.3.6.1.1.1.1.20' => ['ipNetworkNumber'], '1.3.6.1.1.1.1.21' => ['ipNetmaskNumber'], '1.3.6.1.1.1.1.22' => ['macAddress'], '1.3.6.1.1.1.1.23' => ['bootParameter'], '1.3.6.1.1.1.1.24' => ['bootFile'], '1.3.6.1.1.1.1.26' => ['nisMapName'], '1.3.6.1.1.1.1.27' => ['nisMapEntry'], '1.3.6.1.1.4' => ['vendorName'], '1.3.6.1.1.5' => ['vendorVersion'], '1.3.6.1.1.16.4' => ['entryUUID'], '1.3.6.1.1.20' => ['entryDN'], '2.5.4.0' => ['objectClass'], '2.5.4.1' => ['aliasedObjectName', 'aliasedEntryName'], '2.5.4.2' => ['knowledgeInformation'], '2.5.4.3' => ['cn', 'commonName'], '2.5.4.4' => ['sn', 'surname'], '2.5.4.5' => ['serialNumber'], '2.5.4.6' => ['c', 'countryName'], '2.5.4.7' => ['l', 'localityName'], '2.5.4.8' => ['st', 'stateOrProvinceName'], '2.5.4.9' => ['street', 'streetAddress'], '2.5.4.10' => ['o', 'organizationName'], '2.5.4.11' => ['ou', 'organizationalUnitName'], '2.5.4.12' => ['title'], '2.5.4.13' => ['description'], '2.5.4.14' => ['searchGuide'], '2.5.4.15' => ['businessCategory'], '2.5.4.16' => ['postalAddress'], '2.5.4.17' => ['postalCode'], '2.5.4.18' => ['postOfficeBox'], '2.5.4.19' => ['physicalDeliveryOfficeName'], '2.5.4.20' => ['telephoneNumber'], '2.5.4.21' => ['telexNumber'], '2.5.4.22' => ['teletexTerminalIdentifier'], '2.5.4.23' => ['facsimileTelephoneNumber', 'fax'], '2.5.4.24' => ['x121Address'], '2.5.4.25' => ['internationaliSDNNumber'], '2.5.4.26' => ['registeredAddress'], '2.5.4.27' => ['destinationIndicator'], '2.5.4.28' => ['preferredDeliveryMethod'], '2.5.4.29' => ['presentationAddress'], '2.5.4.30' => ['supportedApplicationContext'], '2.5.4.31' => ['member'], '2.5.4.32' => ['owner'], '2.5.4.33' => ['roleOccupant'], '2.5.4.34' => ['seeAlso'], '2.5.4.35' => ['userPassword'], '2.5.4.36' => ['userCertificate'], '2.5.4.37' => ['cACertificate'], '2.5.4.38' => ['authorityRevocationList'], '2.5.4.39' => ['certificateRevocationList'], '2.5.4.40' => ['crossCertificatePair'], '2.5.4.41' => ['name'], '2.5.4.42' => ['givenName', 'gn'], '2.5.4.43' => ['initials'], '2.5.4.44' => ['generationQualifier'], '2.5.4.45' => ['x500UniqueIdentifier'], '2.5.4.46' => ['dnQualifier'], '2.5.4.47' => ['enhancedSearchGuide'], '2.5.4.48' => ['protocolInformation'], '2.5.4.49' => ['distinguishedName'], '2.5.4.50' => ['uniqueMember'], '2.5.4.51' => ['houseIdentifier'], '2.5.4.52' => ['supportedAlgorithms'], '2.5.4.53' => ['deltaRevocationList'], '2.5.4.54' => ['dmdName'], '2.5.4.65' => ['pseudonym'], '2.5.18.1' => ['createTimestamp'], '2.5.18.2' => ['modifyTimestamp'], '2.5.18.3' => ['creatorsName'], '2.5.18.4' => ['modifiersName'], '2.5.18.5' => ['administrativeRole'], '2.5.18.6' => ['subtreeSpecification'], '2.5.18.9' => ['hasSubordinates'], '2.5.18.10' => ['subschemaSubentry'], '2.5.21.1' => ['dITStructureRules'], '2.5.21.2' => ['dITContentRules'], '2.5.21.4' => ['matchingRules'], '2.5.21.5' => ['attributeTypes'], '2.5.21.6' => ['objectClasses'], '2.5.21.7' => ['nameForms'], '2.5.21.8' => ['matchingRuleUse'], '2.5.21.9' => ['structuralObjectClass'], '2.16.840.1.113730.3.1.1' => ['carLicense'], '2.16.840.1.113730.3.1.2' => ['departmentNumber'], '2.16.840.1.113730.3.1.3' => ['employeeNumber'], '2.16.840.1.113730.3.1.4' => ['employeeType'], '2.16.840.1.113730.3.1.34' => ['ref'], '2.16.840.1.113730.3.1.39' => ['preferredLanguage'], '2.16.840.1.113730.3.1.40' => ['userSMIMECertificate'], '2.16.840.1.113730.3.1.216' => ['userPKCS12'], '2.16.840.1.113730.3.1.241' => ['displayName']];
    /**
     * @param string $_oid OID in dotted format
     */
    private function __construct(private readonly string $_oid)
    {
    }
    public static function create(string $oid): self
    {
        return new self($oid);
    }
    /**
     * Initialize from ASN.1.
     */
    public static function fromASN1(ObjectIdentifier $oi): self
    {
        return self::create($oi->oid());
    }
    /**
     * Initialize from attribute name.
     */
    public static function fromName(string $name): self
    {
        $oid = self::attrNameToOID($name);
        return self::create($oid);
    }
    /**
     * Get OID of the attribute.
     *
     * @return string OID in dotted format
     */
    public function oid(): string
    {
        return $this->_oid;
    }
    /**
     * Get name of the attribute.
     */
    public function typeName(): string
    {
        if (array_key_exists($this->_oid, self::MAP_OID_TO_NAME)) {
            return self::MAP_OID_TO_NAME[$this->_oid][0];
        }
        return $this->_oid;
    }
    /**
     * Generate ASN.1 element.
     */
    public function toASN1(): ObjectIdentifier
    {
        return ObjectIdentifier::create($this->_oid);
    }
    /**
     * Convert attribute name to OID.
     *
     * @param string $name Primary attribute name or an alias
     *
     * @return string OID in dotted format
     */
    public static function attrNameToOID(string $name): string
    {
        // if already in OID form
        if (preg_match('/^[0-9]+(?:\.[0-9]+)*$/', $name) === 1) {
            return $name;
        }
        $map = self::_oidReverseMap();
        $k = mb_strtolower($name, '8bit');
        if (!isset($map[$k])) {
            throw new OutOfBoundsException("No OID for {$name}.");
        }
        return $map[$k];
    }
    /**
     * Get ASN.1 string for given attribute type.
     *
     * @param string $oid Attribute OID
     * @param string $str String
     */
    public static function asn1StringForType(string $oid, string $str): StringType
    {
        if (!array_key_exists($oid, self::MAP_ATTR_TO_STR_TYPE)) {
            return UTF8String::create($str);
        }
        return PrintableString::create($str);
    }
    /**
     * Get name to OID lookup map.
     *
     * @return array<string>
     */
    private static function _oidReverseMap(): array
    {
        static $map;
        if (!isset($map)) {
            $map = [];
            // for each attribute type
            foreach (self::MAP_OID_TO_NAME as $oid => $names) {
                // for primary name and aliases
                foreach ($names as $name) {
                    $map[mb_strtolower($name, '8bit')] = $oid;
                }
            }
        }
        return $map;
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\X501\ASN1\Collection;

use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Constructed\Sequence;
use _ContaoManager\SpomkyLabs\Pki\X501\ASN1\Attribute;
use _ContaoManager\SpomkyLabs\Pki\X501\ASN1\AttributeValue\AttributeValue;
/**
 * Implements *Attributes* ASN.1 type as a *SEQUENCE OF Attribute*.
 *
 * Used in *AttributeCertificateInfo*.
 *
 * @see https://tools.ietf.org/html/rfc5755#section-4.1
 * @see https://tools.ietf.org/html/rfc5755#section-4.2.7
 */
class SequenceOfAttributes extends AttributeCollection
{
    /**
     * Initialize from ASN.1.
     */
    public static function fromASN1(Sequence $seq): self
    {
        return static::_fromASN1Structure($seq);
    }
    /**
     * Initialize from attribute values.
     *
     * @param AttributeValue ...$values List of attribute values
     */
    public static function fromAttributeValues(AttributeValue ...$values): static
    {
        return static::create(...array_map(static fn(AttributeValue $value) => $value->toAttribute(), $values));
    }
    /**
     * Generate ASN.1 structure.
     */
    public function toASN1(): Sequence
    {
        return Sequence::create(...array_map(static fn(Attribute $attr) => $attr->toASN1(), $this->_attributes));
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\X501\ASN1\Collection;

use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Constructed\Set;
use _ContaoManager\SpomkyLabs\Pki\X501\ASN1\Attribute;
use _ContaoManager\SpomkyLabs\Pki\X501\ASN1\AttributeValue\AttributeValue;
/**
 * Implements *Attributes* ASN.1 type as a *SET OF Attribute*.
 *
 * Used in *CertificationRequestInfo* and *OneAsymmetricKey*.
 *
 * @see https://tools.ietf.org/html/rfc2986#section-4
 * @see https://tools.ietf.org/html/rfc5958#section-2
 */
class SetOfAttributes extends AttributeCollection
{
    /**
     * Initialize from ASN.1.
     */
    public static function fromASN1(Set $set): static
    {
        return static::_fromASN1Structure($set);
    }
    /**
     * Initialize from attribute values.
     *
     * @param AttributeValue ...$values List of attribute values
     */
    public static function fromAttributeValues(AttributeValue ...$values): static
    {
        return static::create(...array_map(static fn(AttributeValue $value) => $value->toAttribute(), $values));
    }
    /**
     * Generate ASN.1 structure.
     */
    public function toASN1(): Set
    {
        $set = Set::create(...array_map(static fn(Attribute $attr) => $attr->toASN1(), $this->_attributes));
        return $set->sortedSetOf();
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\X501\ASN1\Collection;

use ArrayIterator;
use function count;
use Countable;
use IteratorAggregate;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Structure;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\UnspecifiedType;
use _ContaoManager\SpomkyLabs\Pki\X501\ASN1\Attribute;
use _ContaoManager\SpomkyLabs\Pki\X501\ASN1\AttributeType;
use UnexpectedValueException;
/**
 * Base class for X.501 attribute containers.
 *
 * Implements methods for Countable and IteratorAggregate interfaces.
 */
abstract class AttributeCollection implements Countable, IteratorAggregate
{
    /**
     * Array of attributes.
     *
     * Always with consecutive indices.
     *
     * @var Attribute[]
     */
    protected array $_attributes;
    /**
     * @param Attribute ...$attribs List of attributes
     */
    final private function __construct(Attribute ...$attribs)
    {
        $this->_attributes = $attribs;
    }
    public static function create(Attribute ...$attribs): static
    {
        return new static(...$attribs);
    }
    /**
     * Check whether attribute is present.
     *
     * @param string $name OID or attribute name
     */
    public function has(string $name): bool
    {
        return $this->_findFirst($name) !== null;
    }
    /**
     * Get first attribute by OID or attribute name.
     *
     * @param string $name OID or attribute name
     */
    public function firstOf(string $name): Attribute
    {
        $attr = $this->_findFirst($name);
        if ($attr === null) {
            throw new UnexpectedValueException("No {$name} attribute.");
        }
        return $attr;
    }
    /**
     * Get all attributes of given name.
     *
     * @param string $name OID or attribute name
     *
     * @return Attribute[]
     */
    public function allOf(string $name): array
    {
        $oid = AttributeType::attrNameToOID($name);
        return array_values(array_filter($this->_attributes, fn(Attribute $attr) => $attr->oid() === $oid));
    }
    /**
     * Get all attributes.
     *
     * @return Attribute[]
     */
    public function all(): array
    {
        return $this->_attributes;
    }
    /**
     * Get self with additional attributes added.
     *
     * @param Attribute ...$attribs List of attributes to add
     */
    public function withAdditional(Attribute ...$attribs): self
    {
        $obj = clone $this;
        foreach ($attribs as $attr) {
            $obj->_attributes[] = $attr;
        }
        return $obj;
    }
    /**
     * Get self with single unique attribute added.
     *
     * All previous attributes of the same type are removed.
     *
     * @param Attribute $attr Attribute to add
     */
    public function withUnique(Attribute $attr): static
    {
        $attribs = array_values(array_filter($this->_attributes, fn(Attribute $a) => $a->oid() !== $attr->oid()));
        $attribs[] = $attr;
        $obj = clone $this;
        $obj->_attributes = $attribs;
        return $obj;
    }
    /**
     * Get number of attributes.
     *
     * @see \Countable::count()
     */
    public function count(): int
    {
        return count($this->_attributes);
    }
    /**
     * Get iterator for attributes.
     *
     * @return ArrayIterator|Attribute[]
     * @see \IteratorAggregate::getIterator()
     */
    public function getIterator(): ArrayIterator
    {
        return new ArrayIterator($this->_attributes);
    }
    /**
     * Find first attribute of given name or OID.
     *
     * @param string $name OID or attribute name
     */
    protected function _findFirst(string $name): ?Attribute
    {
        $oid = AttributeType::attrNameToOID($name);
        foreach ($this->_attributes as $attr) {
            if ($attr->oid() === $oid) {
                return $attr;
            }
        }
        return null;
    }
    /**
     * Initialize from ASN.1 constructed element.
     *
     * @param Structure $struct ASN.1 structure
     */
    protected static function _fromASN1Structure(Structure $struct): static
    {
        return static::create(...array_map(static fn(UnspecifiedType $el) => static::_castAttributeValues(Attribute::fromASN1($el->asSequence())), $struct->elements()));
    }
    /**
     * Cast Attribute's AttributeValues to implementation specific objects.
     *
     * Overridden in derived classes.
     *
     * @param Attribute $attribute Attribute to cast
     */
    protected static function _castAttributeValues(Attribute $attribute): Attribute
    {
        // pass through by default
        return $attribute;
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\X501\ASN1;

use ArrayIterator;
use function count;
use Countable;
use IteratorAggregate;
use LogicException;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Constructed\Sequence;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Constructed\Set;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\UnspecifiedType;
use _ContaoManager\SpomkyLabs\Pki\X501\ASN1\AttributeValue\AttributeValue;
use function sprintf;
/**
 * Implements *Attribute* ASN.1 type.
 *
 * @see https://www.itu.int/ITU-T/formal-language/itu-t/x/x501/2012/InformationFramework.html#InformationFramework.Attribute
 */
final class Attribute implements Countable, IteratorAggregate
{
    /**
     * Attribute type.
     */
    private readonly AttributeType $type;
    /**
     * Attribute values.
     *
     * @var AttributeValue[]
     */
    private readonly array $values;
    /**
     * @param AttributeType $type Attribute type
     * @param AttributeValue ...$values Attribute values
     */
    private function __construct(AttributeType $type, AttributeValue ...$values)
    {
        // check that attribute values have correct oid
        foreach ($values as $value) {
            if ($value->oid() !== $type->oid()) {
                throw new LogicException('Attribute OID mismatch.');
            }
        }
        $this->type = $type;
        $this->values = $values;
    }
    public static function create(AttributeType $type, AttributeValue ...$values): self
    {
        return new self($type, ...$values);
    }
    /**
     * Initialize from ASN.1.
     */
    public static function fromASN1(Sequence $seq): self
    {
        $type = AttributeType::fromASN1($seq->at(0)->asObjectIdentifier());
        $values = array_map(static fn(UnspecifiedType $el) => AttributeValue::fromASN1ByOID($type->oid(), $el), $seq->at(1)->asSet()->elements());
        return self::create($type, ...$values);
    }
    /**
     * Convenience method to initialize from attribute values.
     *
     * @param AttributeValue ...$values One or more values
     */
    public static function fromAttributeValues(AttributeValue ...$values): self
    {
        // we need at least one value to determine OID
        if (count($values) === 0) {
            throw new LogicException('No values.');
        }
        $oid = reset($values)->oid();
        return self::create(AttributeType::create($oid), ...$values);
    }
    /**
     * Get first value of the attribute.
     */
    public function first(): AttributeValue
    {
        if (count($this->values) === 0) {
            throw new LogicException('Attribute contains no values.');
        }
        return $this->values[0];
    }
    /**
     * Get all values.
     *
     * @return AttributeValue[]
     */
    public function values(): array
    {
        return $this->values;
    }
    /**
     * Generate ASN.1 structure.
     */
    public function toASN1(): Sequence
    {
        $values = array_map(static fn(AttributeValue $value) => $value->toASN1(), $this->values);
        $valueset = Set::create(...$values);
        return Sequence::create($this->type->toASN1(), $valueset->sortedSetOf());
    }
    /**
     * Cast attribute values to another AttributeValue class.
     *
     * This method is generally used to cast UnknownAttributeValue values to specific objects when class is declared
     * outside this package.
     *
     * The new class must be derived from AttributeValue and have the same OID as current attribute values.
     *
     * @param string $cls AttributeValue class name
     */
    public function castValues(string $cls): self
    {
        // check that target class derives from AttributeValue
        if (!is_subclass_of($cls, AttributeValue::class)) {
            throw new LogicException(sprintf('%s must be derived from %s.', $cls, AttributeValue::class));
        }
        $values = array_map(function (AttributeValue $value) use ($cls) {
            /** @var AttributeValue $cls Class name as a string */
            $value = $cls::fromSelf($value);
            if ($value->oid() !== $this->oid()) {
                throw new LogicException('Attribute OID mismatch.');
            }
            return $value;
        }, $this->values);
        return self::fromAttributeValues(...$values);
    }
    /**
     * @see \Countable::count()
     */
    public function count(): int
    {
        return count($this->values);
    }
    /**
     * @see \IteratorAggregate::getIterator()
     */
    public function getIterator(): ArrayIterator
    {
        return new ArrayIterator($this->values);
    }
    /**
     * Get attribute type.
     */
    public function type(): AttributeType
    {
        return $this->type;
    }
    /**
     * Get OID of the attribute.
     */
    public function oid(): string
    {
        return $this->type->oid();
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\X501\ASN1\AttributeValue;

use _ContaoManager\SpomkyLabs\Pki\X501\ASN1\AttributeType;
use _ContaoManager\SpomkyLabs\Pki\X501\ASN1\AttributeValue\Feature\DirectoryString;
/**
 * 'localityName' attribute value.
 *
 * @see https://www.itu.int/ITU-T/formal-language/itu-t/x/x520/2012/SelectedAttributeTypes.html#SelectedAttributeTypes.localityName
 */
final class LocalityNameValue extends DirectoryString
{
    public static function create(string $value, int $string_tag = DirectoryString::UTF8): static
    {
        return new static(AttributeType::OID_LOCALITY_NAME, $value, $string_tag);
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\X501\ASN1\AttributeValue;

use _ContaoManager\SpomkyLabs\Pki\X501\ASN1\AttributeType;
use _ContaoManager\SpomkyLabs\Pki\X501\ASN1\AttributeValue\Feature\DirectoryString;
/**
 * 'givenName' attribute value.
 *
 * @see https://www.itu.int/ITU-T/formal-language/itu-t/x/x520/2012/SelectedAttributeTypes.html#SelectedAttributeTypes.givenName
 */
final class GivenNameValue extends DirectoryString
{
    public static function create(string $value, int $string_tag = DirectoryString::UTF8): static
    {
        return new static(AttributeType::OID_GIVEN_NAME, $value, $string_tag);
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\X501\ASN1\AttributeValue;

use _ContaoManager\SpomkyLabs\Pki\X501\ASN1\AttributeType;
use _ContaoManager\SpomkyLabs\Pki\X501\ASN1\AttributeValue\Feature\DirectoryString;
/**
 * 'organizationName' attribute value.
 *
 * @see https://www.itu.int/ITU-T/formal-language/itu-t/x/x520/2012/SelectedAttributeTypes.html#SelectedAttributeTypes.organizationName
 */
final class OrganizationNameValue extends DirectoryString
{
    public static function create(string $value, int $string_tag = DirectoryString::UTF8): static
    {
        return new static(AttributeType::OID_ORGANIZATION_NAME, $value, $string_tag);
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\X501\ASN1\AttributeValue;

use _ContaoManager\SpomkyLabs\Pki\X501\ASN1\AttributeType;
use _ContaoManager\SpomkyLabs\Pki\X501\ASN1\AttributeValue\Feature\DirectoryString;
/**
 * 'title' attribute value.
 *
 * @see https://www.itu.int/ITU-T/formal-language/itu-t/x/x520/2012/SelectedAttributeTypes.html#SelectedAttributeTypes.title
 */
final class TitleValue extends DirectoryString
{
    public static function create(string $value, int $string_tag = DirectoryString::UTF8): static
    {
        return new static(AttributeType::OID_TITLE, $value, $string_tag);
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\X501\ASN1\AttributeValue;

use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\UnspecifiedType;
use _ContaoManager\SpomkyLabs\Pki\X501\ASN1\AttributeType;
use _ContaoManager\SpomkyLabs\Pki\X501\ASN1\AttributeValue\Feature\PrintableStringValue;
/**
 * 'serialNumber' attribute value.
 *
 * @see https://www.itu.int/ITU-T/formal-language/itu-t/x/x520/2012/SelectedAttributeTypes.html#SelectedAttributeTypes.serialNumber
 */
final class SerialNumberValue extends PrintableStringValue
{
    /**
     * @param string $value String value
     */
    protected function __construct(string $value)
    {
        parent::__construct(AttributeType::OID_SERIAL_NUMBER, $value);
    }
    public static function create(string $value): self
    {
        return new self($value);
    }
    public static function fromASN1(UnspecifiedType $el): self
    {
        return self::create($el->asPrintableString()->string());
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\X501\ASN1\AttributeValue;

use function array_key_exists;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Element;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\UnspecifiedType;
use _ContaoManager\SpomkyLabs\Pki\X501\ASN1\Attribute;
use _ContaoManager\SpomkyLabs\Pki\X501\ASN1\AttributeType;
use _ContaoManager\SpomkyLabs\Pki\X501\ASN1\AttributeTypeAndValue;
use _ContaoManager\SpomkyLabs\Pki\X501\MatchingRule\MatchingRule;
use Stringable;
/**
 * Base class for attribute values.
 *
 * @see https://www.itu.int/ITU-T/formal-language/itu-t/x/x501/2012/InformationFramework.html#InformationFramework.AttributeValue
 */
abstract class AttributeValue implements Stringable
{
    /**
     * Mapping from attribute type OID to attribute value class name.
     *
     * @internal
     *
     * @var array<string, string>
     */
    private const MAP_OID_TO_CLASS = [AttributeType::OID_COMMON_NAME => CommonNameValue::class, AttributeType::OID_SURNAME => SurnameValue::class, AttributeType::OID_SERIAL_NUMBER => SerialNumberValue::class, AttributeType::OID_COUNTRY_NAME => CountryNameValue::class, AttributeType::OID_LOCALITY_NAME => LocalityNameValue::class, AttributeType::OID_STATE_OR_PROVINCE_NAME => StateOrProvinceNameValue::class, AttributeType::OID_ORGANIZATION_NAME => OrganizationNameValue::class, AttributeType::OID_ORGANIZATIONAL_UNIT_NAME => OrganizationalUnitNameValue::class, AttributeType::OID_TITLE => TitleValue::class, AttributeType::OID_DESCRIPTION => DescriptionValue::class, AttributeType::OID_NAME => NameValue::class, AttributeType::OID_GIVEN_NAME => GivenNameValue::class, AttributeType::OID_PSEUDONYM => PseudonymValue::class];
    /**
     * @param string $oid OID of the attribute type.
     */
    protected function __construct(protected string $oid)
    {
    }
    /**
     * Get attribute value as an UTF-8 encoded string.
     */
    public function __toString(): string
    {
        return $this->_transcodedString();
    }
    /**
     * Generate ASN.1 element.
     */
    abstract public function toASN1(): Element;
    /**
     * Get attribute value as a string.
     */
    abstract public function stringValue(): string;
    /**
     * Get matching rule for equality comparison.
     */
    abstract public function equalityMatchingRule(): MatchingRule;
    /**
     * Get attribute value as a string conforming to RFC 2253.
     *
     * @see https://tools.ietf.org/html/rfc2253#section-2.4
     */
    abstract public function rfc2253String(): string;
    /**
     * Initialize from ASN.1.
     */
    abstract public static function fromASN1(UnspecifiedType $el): self;
    /**
     * Initialize from ASN.1 with given OID hint.
     *
     * @param string $oid Attribute's OID
     */
    public static function fromASN1ByOID(string $oid, UnspecifiedType $el): self
    {
        if (!array_key_exists($oid, self::MAP_OID_TO_CLASS)) {
            return new UnknownAttributeValue($oid, $el->asElement());
        }
        $cls = self::MAP_OID_TO_CLASS[$oid];
        return $cls::fromASN1($el);
    }
    /**
     * Initialize from another AttributeValue.
     *
     * This method is generally used to cast UnknownAttributeValue to specific object when class is declared outside
     * this package.
     *
     * @param self $obj Instance of AttributeValue
     */
    public static function fromSelf(self $obj): self
    {
        return static::fromASN1($obj->toASN1()->asUnspecified());
    }
    /**
     * Get attribute type's OID.
     */
    public function oid(): string
    {
        return $this->oid;
    }
    /**
     * Get Attribute object with this as a single value.
     */
    public function toAttribute(): Attribute
    {
        return Attribute::fromAttributeValues($this);
    }
    /**
     * Get AttributeTypeAndValue object with this as a value.
     */
    public function toAttributeTypeAndValue(): AttributeTypeAndValue
    {
        return AttributeTypeAndValue::fromAttributeValue($this);
    }
    /**
     * Get attribute value as an UTF-8 string conforming to RFC 4518.
     *
     * @see https://tools.ietf.org/html/rfc4518#section-2.1
     */
    abstract protected function _transcodedString(): string;
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\X501\ASN1\AttributeValue;

use _ContaoManager\SpomkyLabs\Pki\X501\ASN1\AttributeType;
use _ContaoManager\SpomkyLabs\Pki\X501\ASN1\AttributeValue\Feature\DirectoryString;
/**
 * 'description' attribute value.
 *
 * @see https://www.itu.int/ITU-T/formal-language/itu-t/x/x520/2012/SelectedAttributeTypes.html#SelectedAttributeTypes.description
 */
final class DescriptionValue extends DirectoryString
{
    public static function create(string $value, int $string_tag = DirectoryString::UTF8): static
    {
        return new static(AttributeType::OID_DESCRIPTION, $value, $string_tag);
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\X501\ASN1\AttributeValue;

use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\UnspecifiedType;
use _ContaoManager\SpomkyLabs\Pki\X501\ASN1\AttributeType;
use _ContaoManager\SpomkyLabs\Pki\X501\ASN1\AttributeValue\Feature\PrintableStringValue;
/**
 * 'countryName' attribute value.
 *
 * @see https://www.itu.int/ITU-T/formal-language/itu-t/x/x520/2012/SelectedAttributeTypes.html#SelectedAttributeTypes.countryName
 */
final class CountryNameValue extends PrintableStringValue
{
    /**
     * @param string $value String value
     */
    protected function __construct(string $value)
    {
        parent::__construct(AttributeType::OID_COUNTRY_NAME, $value);
    }
    public static function create(string $value): self
    {
        return new self($value);
    }
    public static function fromASN1(UnspecifiedType $el): self
    {
        return self::create($el->asPrintableString()->string());
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\X501\ASN1\AttributeValue;

use _ContaoManager\SpomkyLabs\Pki\X501\ASN1\AttributeType;
use _ContaoManager\SpomkyLabs\Pki\X501\ASN1\AttributeValue\Feature\DirectoryString;
/**
 * 'commonName' attribute value.
 *
 * @see https://www.itu.int/ITU-T/formal-language/itu-t/x/x520/2012/SelectedAttributeTypes.html#SelectedAttributeTypes.commonName
 */
final class CommonNameValue extends DirectoryString
{
    public static function create(string $value, int $string_tag = DirectoryString::UTF8): static
    {
        return new static(AttributeType::OID_COMMON_NAME, $value, $string_tag);
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\X501\ASN1\AttributeValue;

use _ContaoManager\SpomkyLabs\Pki\X501\ASN1\AttributeType;
use _ContaoManager\SpomkyLabs\Pki\X501\ASN1\AttributeValue\Feature\DirectoryString;
/**
 * 'surname' attribute value.
 *
 * @see https://www.itu.int/ITU-T/formal-language/itu-t/x/x520/2012/SelectedAttributeTypes.html#SelectedAttributeTypes.surname
 */
final class SurnameValue extends DirectoryString
{
    public static function create(string $value, int $string_tag = DirectoryString::UTF8): static
    {
        return new static(AttributeType::OID_SURNAME, $value, $string_tag);
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\X501\ASN1\AttributeValue;

use _ContaoManager\SpomkyLabs\Pki\X501\ASN1\AttributeType;
use _ContaoManager\SpomkyLabs\Pki\X501\ASN1\AttributeValue\Feature\DirectoryString;
/**
 * 'pseudonym' attribute value.
 *
 * @see https://www.itu.int/ITU-T/formal-language/itu-t/x/x520/2012/SelectedAttributeTypes.html#SelectedAttributeTypes.pseudonym
 */
final class PseudonymValue extends DirectoryString
{
    public static function create(string $value, int $string_tag = DirectoryString::UTF8): static
    {
        return new static(AttributeType::OID_PSEUDONYM, $value, $string_tag);
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\X501\ASN1\AttributeValue;

use _ContaoManager\SpomkyLabs\Pki\X501\ASN1\AttributeType;
use _ContaoManager\SpomkyLabs\Pki\X501\ASN1\AttributeValue\Feature\DirectoryString;
/**
 * 'stateOrProvinceName' attribute value.
 *
 * @see https://www.itu.int/ITU-T/formal-language/itu-t/x/x520/2012/SelectedAttributeTypes.html#SelectedAttributeTypes.stateOrProvinceName
 */
final class StateOrProvinceNameValue extends DirectoryString
{
    public static function create(string $value, int $string_tag = DirectoryString::UTF8): static
    {
        return new static(AttributeType::OID_STATE_OR_PROVINCE_NAME, $value, $string_tag);
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\X501\ASN1\AttributeValue\Feature;

use _ContaoManager\SpomkyLabs\Pki\ASN1\Element;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Primitive\PrintableString;
use _ContaoManager\SpomkyLabs\Pki\X501\ASN1\AttributeValue\AttributeValue;
use _ContaoManager\SpomkyLabs\Pki\X501\DN\DNParser;
use _ContaoManager\SpomkyLabs\Pki\X501\MatchingRule\CaseIgnoreMatch;
use _ContaoManager\SpomkyLabs\Pki\X501\MatchingRule\MatchingRule;
/**
 * Base class for attribute values having *PrintableString* syntax.
 */
abstract class PrintableStringValue extends AttributeValue
{
    /**
     * @param string $_string String value
     */
    protected function __construct(string $oid, protected string $_string)
    {
        parent::__construct($oid);
    }
    public function toASN1(): Element
    {
        return PrintableString::create($this->_string);
    }
    public function stringValue(): string
    {
        return $this->_string;
    }
    public function equalityMatchingRule(): MatchingRule
    {
        // default to caseIgnoreMatch
        return CaseIgnoreMatch::create(Element::TYPE_PRINTABLE_STRING);
    }
    public function rfc2253String(): string
    {
        return DNParser::escapeString($this->_transcodedString());
    }
    protected function _transcodedString(): string
    {
        // PrintableString maps directly to UTF-8
        return $this->_string;
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\X501\ASN1\AttributeValue\Feature;

use function array_key_exists;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Element;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Primitive\BMPString;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Primitive\PrintableString;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Primitive\T61String;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Primitive\UniversalString;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Primitive\UTF8String;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\UnspecifiedType;
use _ContaoManager\SpomkyLabs\Pki\X501\ASN1\AttributeValue\AttributeValue;
use _ContaoManager\SpomkyLabs\Pki\X501\DN\DNParser;
use _ContaoManager\SpomkyLabs\Pki\X501\MatchingRule\CaseIgnoreMatch;
use _ContaoManager\SpomkyLabs\Pki\X501\MatchingRule\MatchingRule;
use _ContaoManager\SpomkyLabs\Pki\X501\StringPrep\TranscodeStep;
use function sprintf;
use UnexpectedValueException;
/**
 * Base class for attribute values having *(Unbounded)DirectoryString* as a syntax.
 *
 * @see https://www.itu.int/ITU-T/formal-language/itu-t/x/x520/2012/SelectedAttributeTypes.html#SelectedAttributeTypes.UnboundedDirectoryString
 */
abstract class DirectoryString extends AttributeValue
{
    /**
     * Teletex string syntax.
     *
     * @var int
     */
    final public const TELETEX = Element::TYPE_T61_STRING;
    /**
     * Printable string syntax.
     *
     * @var int
     */
    final public const PRINTABLE = Element::TYPE_PRINTABLE_STRING;
    /**
     * BMP string syntax.
     *
     * @var int
     */
    final public const BMP = Element::TYPE_BMP_STRING;
    /**
     * Universal string syntax.
     *
     * @var int
     */
    final public const UNIVERSAL = Element::TYPE_UNIVERSAL_STRING;
    /**
     * UTF-8 string syntax.
     *
     * @var int
     */
    final public const UTF8 = Element::TYPE_UTF8_STRING;
    /**
     * Mapping from syntax enumeration to ASN.1 class name.
     *
     * @internal
     *
     * @var array<int, string>
     */
    private const MAP_TAG_TO_CLASS = [self::TELETEX => T61String::class, self::PRINTABLE => PrintableString::class, self::UNIVERSAL => UniversalString::class, self::UTF8 => UTF8String::class, self::BMP => BMPString::class];
    /**
     * @param string $_string String value
     * @param int $_stringTag Syntax choice
     */
    final protected function __construct(string $oid, protected string $_string, protected int $_stringTag)
    {
        parent::__construct($oid);
    }
    abstract public static function create(string $value, int $string_tag = self::UTF8): static;
    /**
     * @return self
     */
    public static function fromASN1(UnspecifiedType $el): AttributeValue
    {
        $tag = $el->tag();
        // validate tag
        self::_tagToASN1Class($tag);
        return static::create($el->asString()->string(), $tag);
    }
    public function toASN1(): Element
    {
        $cls = self::_tagToASN1Class($this->_stringTag);
        return $cls::create($this->_string);
    }
    public function stringValue(): string
    {
        return $this->_string;
    }
    public function equalityMatchingRule(): MatchingRule
    {
        return CaseIgnoreMatch::create($this->_stringTag);
    }
    public function rfc2253String(): string
    {
        // TeletexString is encoded as binary
        if ($this->_stringTag === self::TELETEX) {
            return $this->_transcodedString();
        }
        return DNParser::escapeString($this->_transcodedString());
    }
    protected function _transcodedString(): string
    {
        return TranscodeStep::create($this->_stringTag)->apply($this->_string);
    }
    /**
     * Get ASN.1 class name for given DirectoryString type tag.
     */
    private static function _tagToASN1Class(int $tag): string
    {
        if (!array_key_exists($tag, self::MAP_TAG_TO_CLASS)) {
            throw new UnexpectedValueException(sprintf('Type %s is not valid DirectoryString.', Element::tagToName($tag)));
        }
        return self::MAP_TAG_TO_CLASS[$tag];
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\X501\ASN1\AttributeValue;

use BadMethodCallException;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Element;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\UnspecifiedType;
use _ContaoManager\SpomkyLabs\Pki\X501\DN\DNParser;
use _ContaoManager\SpomkyLabs\Pki\X501\MatchingRule\BinaryMatch;
use _ContaoManager\SpomkyLabs\Pki\X501\MatchingRule\MatchingRule;
use _ContaoManager\SpomkyLabs\Pki\X501\StringPrep\TranscodeStep;
/**
 * Class to hold ASN.1 structure of an unimplemented attribute value.
 */
final class UnknownAttributeValue extends AttributeValue
{
    /**
     * @param Element $_element ASN.1 element.
     */
    protected function __construct(string $oid, protected Element $_element)
    {
        parent::__construct($oid);
        $this->oid = $oid;
    }
    public static function create(string $oid, Element $_element): self
    {
        return new self($oid, $_element);
    }
    public function toASN1(): Element
    {
        return $this->_element;
    }
    public function stringValue(): string
    {
        // if value is encoded as a string type
        if ($this->_element->isType(Element::TYPE_STRING)) {
            return $this->_element->asUnspecified()->asString()->string();
        }
        // return DER encoding as a hexstring (see RFC2253 section 2.4)
        return '#' . bin2hex($this->_element->toDER());
    }
    public function equalityMatchingRule(): MatchingRule
    {
        return new BinaryMatch();
    }
    public function rfc2253String(): string
    {
        $str = $this->_transcodedString();
        // if value has a string representation
        if ($this->_element->isType(Element::TYPE_STRING)) {
            $str = DNParser::escapeString($str);
        }
        return $str;
    }
    public static function fromASN1(UnspecifiedType $el): AttributeValue
    {
        throw new BadMethodCallException('ASN.1 parsing must be implemented in a concrete class.');
    }
    protected function _transcodedString(): string
    {
        // if transcoding is defined for the value type
        if (TranscodeStep::isTypeSupported($this->_element->tag())) {
            $step = TranscodeStep::create($this->_element->tag());
            return $step->apply($this->stringValue());
        }
        return $this->stringValue();
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\X501\ASN1\AttributeValue;

use _ContaoManager\SpomkyLabs\Pki\X501\ASN1\AttributeType;
use _ContaoManager\SpomkyLabs\Pki\X501\ASN1\AttributeValue\Feature\DirectoryString;
/**
 * 'organizationalUnitName' attribute value.
 *
 * @see https://www.itu.int/ITU-T/formal-language/itu-t/x/x520/2012/SelectedAttributeTypes.html#SelectedAttributeTypes.organizationalUnitName
 */
final class OrganizationalUnitNameValue extends DirectoryString
{
    public static function create(string $value, int $string_tag = DirectoryString::UTF8): static
    {
        return new static(AttributeType::OID_ORGANIZATIONAL_UNIT_NAME, $value, $string_tag);
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\X501\ASN1\AttributeValue;

use _ContaoManager\SpomkyLabs\Pki\X501\ASN1\AttributeType;
use _ContaoManager\SpomkyLabs\Pki\X501\ASN1\AttributeValue\Feature\DirectoryString;
/**
 * 'name' attribute value.
 *
 * @see https://www.itu.int/ITU-T/formal-language/itu-t/x/x520/2012/SelectedAttributeTypes.html#SelectedAttributeTypes.name
 */
final class NameValue extends DirectoryString
{
    public static function create(string $value, int $string_tag = DirectoryString::UTF8): static
    {
        return new static(AttributeType::OID_NAME, $value, $string_tag);
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\X501\ASN1;

use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Constructed\Sequence;
use _ContaoManager\SpomkyLabs\Pki\X501\ASN1\AttributeValue\AttributeValue;
use Stringable;
/**
 * Implements *AttributeTypeAndValue* ASN.1 type.
 *
 * @see https://www.itu.int/ITU-T/formal-language/itu-t/x/x501/2012/InformationFramework.html#InformationFramework.AttributeTypeAndValue
 */
final class AttributeTypeAndValue implements Stringable
{
    /**
     * @param AttributeType $type Attribute type
     * @param AttributeValue $value Attribute value
     */
    private function __construct(private readonly AttributeType $type, private readonly AttributeValue $value)
    {
    }
    public function __toString(): string
    {
        return $this->toString();
    }
    public static function create(AttributeType $type, AttributeValue $value): self
    {
        return new self($type, $value);
    }
    /**
     * Initialize from ASN.1.
     */
    public static function fromASN1(Sequence $seq): self
    {
        $type = AttributeType::fromASN1($seq->at(0)->asObjectIdentifier());
        $value = AttributeValue::fromASN1ByOID($type->oid(), $seq->at(1));
        return self::create($type, $value);
    }
    /**
     * Convenience method to initialize from attribute value.
     *
     * @param AttributeValue $value Attribute value
     */
    public static function fromAttributeValue(AttributeValue $value): self
    {
        return self::create(AttributeType::create($value->oid()), $value);
    }
    /**
     * Get attribute value.
     */
    public function value(): AttributeValue
    {
        return $this->value;
    }
    /**
     * Generate ASN.1 structure.
     */
    public function toASN1(): Sequence
    {
        return Sequence::create($this->type->toASN1(), $this->value->toASN1());
    }
    /**
     * Get attributeTypeAndValue string conforming to RFC 2253.
     *
     * @see https://tools.ietf.org/html/rfc2253#section-2.3
     */
    public function toString(): string
    {
        return $this->type->typeName() . '=' . $this->value->rfc2253String();
    }
    /**
     * Check whether attribute is semantically equal to other.
     *
     * @param AttributeTypeAndValue $other Object to compare to
     */
    public function equals(self $other): bool
    {
        // check that attribute types match
        if ($this->oid() !== $other->oid()) {
            return \false;
        }
        $matcher = $this->value->equalityMatchingRule();
        return $matcher->compare($this->value->stringValue(), $other->value->stringValue()) === \true;
    }
    /**
     * Get attribute type.
     */
    public function type(): AttributeType
    {
        return $this->type;
    }
    /**
     * Get OID of the attribute.
     */
    public function oid(): string
    {
        return $this->type->oid();
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\X501\ASN1;

use ArrayIterator;
use function count;
use Countable;
use IteratorAggregate;
use RangeException;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Element;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Constructed\Sequence;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\UnspecifiedType;
use _ContaoManager\SpomkyLabs\Pki\X501\ASN1\AttributeValue\AttributeValue;
use _ContaoManager\SpomkyLabs\Pki\X501\DN\DNParser;
use Stringable;
/**
 * Implements *Name* ASN.1 type.
 *
 * Since *Name* is a CHOICE only supporting *RDNSequence* type, this class implements *RDNSequence* semantics as well.
 *
 * @see https://www.itu.int/ITU-T/formal-language/itu-t/x/x501/2012/InformationFramework.html#InformationFramework.Name
 */
final class Name implements Countable, IteratorAggregate, Stringable
{
    /**
     * Relative distinguished name components.
     *
     * @var RDN[]
     */
    private readonly array $rdns;
    /**
     * @param RDN ...$rdns RDN components
     */
    private function __construct(RDN ...$rdns)
    {
        $this->rdns = $rdns;
    }
    public function __toString(): string
    {
        return $this->toString();
    }
    public static function create(RDN ...$rdns): self
    {
        return new self(...$rdns);
    }
    /**
     * Initialize from ASN.1.
     */
    public static function fromASN1(Sequence $seq): self
    {
        $rdns = array_map(static fn(UnspecifiedType $el) => RDN::fromASN1($el->asSet()), $seq->elements());
        return self::create(...$rdns);
    }
    /**
     * Initialize from distinguished name string.
     *
     * @see https://tools.ietf.org/html/rfc1779
     */
    public static function fromString(string $str): self
    {
        $rdns = [];
        foreach (DNParser::parseString($str) as $nameComponent) {
            $attribs = [];
            foreach ($nameComponent as [$name, $val]) {
                $type = AttributeType::fromName($name);
                // hexstrings are parsed to ASN.1 elements
                if ($val instanceof Element) {
                    $el = $val;
                } else {
                    $el = AttributeType::asn1StringForType($type->oid(), $val);
                }
                $value = AttributeValue::fromASN1ByOID($type->oid(), $el->asUnspecified());
                $attribs[] = AttributeTypeAndValue::create($type, $value);
            }
            $rdns[] = RDN::create(...$attribs);
        }
        return self::create(...$rdns);
    }
    /**
     * Generate ASN.1 structure.
     */
    public function toASN1(): Sequence
    {
        $elements = array_map(static fn(RDN $rdn) => $rdn->toASN1(), $this->rdns);
        return Sequence::create(...$elements);
    }
    /**
     * Get distinguised name string conforming to RFC 2253.
     *
     * @see https://tools.ietf.org/html/rfc2253#section-2.1
     */
    public function toString(): string
    {
        $parts = array_map(static fn(RDN $rdn) => $rdn->toString(), array_reverse($this->rdns));
        return implode(',', $parts);
    }
    /**
     * Whether name is semantically equal to other.
     *
     * Comparison conforms to RFC 4518 string preparation algorithm.
     *
     * @see https://tools.ietf.org/html/rfc4518
     *
     * @param Name $other Object to compare to
     */
    public function equals(self $other): bool
    {
        // if RDN count doesn't match
        if (count($this) !== count($other)) {
            return \false;
        }
        for ($i = count($this) - 1; $i >= 0; --$i) {
            $rdn1 = $this->rdns[$i];
            $rdn2 = $other->rdns[$i];
            if (!$rdn1->equals($rdn2)) {
                return \false;
            }
        }
        return \true;
    }
    /**
     * Get all RDN objects.
     *
     * @return RDN[]
     */
    public function all(): array
    {
        return $this->rdns;
    }
    /**
     * Get the first AttributeValue of given type.
     *
     * Relative name components shall be traversed in encoding order, which is reversed in regards to the string
     * representation. Multi-valued RDN with multiple attributes of the requested type is ambiguous and shall throw an
     * exception.
     *
     * @param string $name Attribute OID or name
     */
    public function firstValueOf(string $name): AttributeValue
    {
        $oid = AttributeType::attrNameToOID($name);
        foreach ($this->rdns as $rdn) {
            $tvs = $rdn->allOf($oid);
            if (count($tvs) > 1) {
                throw new RangeException("RDN with multiple {$name} attributes.");
            }
            if (count($tvs) === 1) {
                return $tvs[0]->value();
            }
        }
        throw new RangeException("Attribute {$name} not found.");
    }
    /**
     * @see \Countable::count()
     */
    public function count(): int
    {
        return count($this->rdns);
    }
    /**
     * Get the number of attributes of given type.
     *
     * @param string $name Attribute OID or name
     */
    public function countOfType(string $name): int
    {
        $oid = AttributeType::attrNameToOID($name);
        return array_sum(array_map(static fn(RDN $rdn): int => count($rdn->allOf($oid)), $this->rdns));
    }
    /**
     * @see \IteratorAggregate::getIterator()
     */
    public function getIterator(): ArrayIterator
    {
        return new ArrayIterator($this->rdns);
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\X501\DN;

use function mb_strlen;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Element;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Exception\DecodeException;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Feature\ElementBase;
use function sprintf;
use UnexpectedValueException;
/**
 * Distinguished Name parsing conforming to RFC 2253 and RFC 1779.
 *
 * @see https://tools.ietf.org/html/rfc1779
 * @see https://tools.ietf.org/html/rfc2253
 */
final class DNParser
{
    /**
     * RFC 2253 special characters.
     *
     * @var string
     */
    final public const SPECIAL_CHARS = ',=+<>#;';
    /**
     * DN string length.
     */
    private readonly int $_len;
    /**
     * @param string $_dn Distinguised name
     */
    private function __construct(private readonly string $_dn)
    {
        $this->_len = mb_strlen($_dn, '8bit');
    }
    /**
     * Parse distinguished name string to name-components.
     *
     * @return array<array<string>>
     */
    public static function parseString(string $dn): array
    {
        $parser = new self($dn);
        return $parser->parse();
    }
    /**
     * Escape a AttributeValue string conforming to RFC 2253.
     *
     * @see https://tools.ietf.org/html/rfc2253#section-2.4
     */
    public static function escapeString(string $str): string
    {
        // one of the characters ",", "+", """, "\", "<", ">" or ";"
        $str = preg_replace('/([,\+"\\\\<\>;])/u', '\\\\$1', $str);
        // a space character occurring at the end of the string
        $str = preg_replace('/( )$/u', '\\\\$1', (string) $str);
        // a space or "#" character occurring at the beginning of the string
        $str = preg_replace('/^([ #])/u', '\\\\$1', (string) $str);
        // implementation specific special characters
        $str = preg_replace_callback('/([\pC])/u', function ($m) {
            $octets = mb_str_split(bin2hex($m[1]), 2, '8bit');
            return implode('', array_map(static fn($octet) => '\\' . mb_strtoupper($octet, '8bit'), $octets));
        }, (string) $str);
        return $str;
    }
    /**
     * Parse DN to name-components.
     *
     * @return array<array<string>>
     */
    private function parse(): array
    {
        $offset = 0;
        $name = $this->_parseName($offset);
        if ($offset < $this->_len) {
            $remains = mb_substr($this->_dn, $offset, null, '8bit');
            throw new UnexpectedValueException(sprintf('Parser finished before the end of string, remaining: %s', $remains));
        }
        return $name;
    }
    /**
     * Parse 'name'.
     *
     * name-component *("," name-component)
     *
     * @return array<array<string>> Array of name-components
     */
    private function _parseName(int &$offset): array
    {
        $idx = $offset;
        $names = [];
        while ($idx < $this->_len) {
            $names[] = $this->_parseNameComponent($idx);
            if ($idx >= $this->_len) {
                break;
            }
            $this->_skipWs($idx);
            if ($this->_dn[$idx] !== ',' && $this->_dn[$idx] !== ';') {
                break;
            }
            ++$idx;
            $this->_skipWs($idx);
        }
        $offset = $idx;
        return array_reverse($names);
    }
    /**
     * Parse 'name-component'.
     *
     * attributeTypeAndValue *("+" attributeTypeAndValue)
     *
     * @return array<array<string, string|ElementBase>> Array of [type, value] tuples
     */
    private function _parseNameComponent(int &$offset): array
    {
        $idx = $offset;
        $tvpairs = [];
        while ($idx < $this->_len) {
            $tvpairs[] = $this->_parseAttrTypeAndValue($idx);
            $this->_skipWs($idx);
            if ($idx >= $this->_len || $this->_dn[$idx] !== '+') {
                break;
            }
            ++$idx;
            $this->_skipWs($idx);
        }
        $offset = $idx;
        return $tvpairs;
    }
    /**
     * Parse 'attributeTypeAndValue'.
     *
     * attributeType "=" attributeValue
     *
     * @return array<string, string|ElementBase> A tuple of [type, value]. Value may be either a string or
     * an Element, if it's encoded as hexstring.
     */
    private function _parseAttrTypeAndValue(int &$offset): array
    {
        $idx = $offset;
        $type = $this->_parseAttrType($idx);
        $this->_skipWs($idx);
        if ($idx >= $this->_len || $this->_dn[$idx++] !== '=') {
            throw new UnexpectedValueException('Invalid type and value pair.');
        }
        $this->_skipWs($idx);
        // hexstring
        if ($idx < $this->_len && $this->_dn[$idx] === '#') {
            ++$idx;
            $data = $this->_parseAttrHexValue($idx);
            try {
                $value = Element::fromDER($data);
            } catch (DecodeException $e) {
                throw new UnexpectedValueException('Invalid DER encoding from hexstring.', 0, $e);
            }
        } else {
            $value = $this->_parseAttrStringValue($idx);
        }
        $offset = $idx;
        return [$type, $value];
    }
    /**
     * Parse 'attributeType'.
     *
     * (ALPHA 1*keychar) / oid
     */
    private function _parseAttrType(int &$offset): string
    {
        $idx = $offset;
        // dotted OID
        $type = $this->_regexMatch('/^(?:oid\.)?([0-9]+(?:\.[0-9]+)*)/i', $idx);
        if ($type === null) {
            // name
            $type = $this->_regexMatch('/^[a-z][a-z0-9\-]*/i', $idx);
            if ($type === null) {
                throw new UnexpectedValueException('Invalid attribute type.');
            }
        }
        $offset = $idx;
        return $type;
    }
    /**
     * Parse 'attributeValue' of string type.
     */
    private function _parseAttrStringValue(int &$offset): string
    {
        $idx = $offset;
        if ($idx >= $this->_len) {
            return '';
        }
        if ($this->_dn[$idx] === '"') {
            // quoted string
            $val = $this->_parseQuotedAttrString($idx);
        } else {
            // string
            $val = $this->_parseAttrString($idx);
        }
        $offset = $idx;
        return $val;
    }
    /**
     * Parse plain 'attributeValue' string.
     */
    private function _parseAttrString(int &$offset): string
    {
        $idx = $offset;
        $val = '';
        $wsidx = null;
        while ($idx < $this->_len) {
            $c = $this->_dn[$idx];
            // pair (escape sequence)
            if ($c === '\\') {
                ++$idx;
                $val .= $this->_parsePairAfterSlash($idx);
                $wsidx = null;
                continue;
            }
            if ($c === '"') {
                throw new UnexpectedValueException('Unexpected quotation.');
            }
            if (mb_strpos(self::SPECIAL_CHARS, $c, 0, '8bit') !== \false) {
                break;
            }
            // keep track of the first consecutive whitespace
            if ($c === ' ') {
                if ($wsidx === null) {
                    $wsidx = $idx;
                }
            } else {
                $wsidx = null;
            }
            // stringchar
            $val .= $c;
            ++$idx;
        }
        // if there was non-escaped whitespace in the end of the value
        if ($wsidx !== null) {
            $val = mb_substr($val, 0, -($idx - $wsidx), '8bit');
        }
        $offset = $idx;
        return $val;
    }
    /**
     * Parse quoted 'attributeValue' string.
     *
     * @param int $offset Offset to starting quote
     */
    private function _parseQuotedAttrString(int &$offset): string
    {
        $idx = $offset + 1;
        $val = '';
        while ($idx < $this->_len) {
            $c = $this->_dn[$idx];
            if ($c === '\\') {
                // pair
                ++$idx;
                $val .= $this->_parsePairAfterSlash($idx);
                continue;
            }
            if ($c === '"') {
                ++$idx;
                break;
            }
            $val .= $c;
            ++$idx;
        }
        $offset = $idx;
        return $val;
    }
    /**
     * Parse 'attributeValue' of binary type.
     */
    private function _parseAttrHexValue(int &$offset): string
    {
        $idx = $offset;
        $hexstr = $this->_regexMatch('/^(?:[0-9a-f]{2})+/i', $idx);
        if ($hexstr === null) {
            throw new UnexpectedValueException('Invalid hexstring.');
        }
        $data = hex2bin($hexstr);
        $offset = $idx;
        return $data;
    }
    /**
     * Parse 'pair' after leading slash.
     */
    private function _parsePairAfterSlash(int &$offset): string
    {
        $idx = $offset;
        if ($idx >= $this->_len) {
            throw new UnexpectedValueException('Unexpected end of escape sequence.');
        }
        $c = $this->_dn[$idx++];
        // special | \ | " | SPACE
        if (mb_strpos(self::SPECIAL_CHARS . '\" ', $c, 0, '8bit') !== \false) {
            $val = $c;
        } else {
            // hexpair
            if ($idx >= $this->_len) {
                throw new UnexpectedValueException('Unexpected end of hexpair.');
            }
            $val = @hex2bin($c . $this->_dn[$idx++]);
            if ($val === \false) {
                throw new UnexpectedValueException('Invalid hexpair.');
            }
        }
        $offset = $idx;
        return $val;
    }
    /**
     * Match DN to pattern and extract the last capture group.
     *
     * Updates offset to fully matched pattern.
     *
     * @return null|string Null if pattern doesn't match
     */
    private function _regexMatch(string $pattern, int &$offset): ?string
    {
        $idx = $offset;
        if (preg_match($pattern, mb_substr($this->_dn, $idx, null, '8bit'), $match) !== 1) {
            return null;
        }
        $idx += mb_strlen($match[0], '8bit');
        $offset = $idx;
        return end($match);
    }
    /**
     * Skip consecutive spaces.
     */
    private function _skipWs(int &$offset): void
    {
        $idx = $offset;
        while ($idx < $this->_len) {
            if ($this->_dn[$idx] !== ' ') {
                break;
            }
            ++$idx;
        }
        $offset = $idx;
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\X501\MatchingRule;

/**
 * Base class for attribute matching rules.
 *
 * @see https://tools.ietf.org/html/rfc4517#section-4
 */
abstract class MatchingRule
{
    /**
     * Compare attribute value to assertion.
     *
     * @param string $assertion Value to assert
     * @param string $value Attribute value
     *
     * @return null|bool True if value matches. Null shall be returned if match
     * evaluates to Undefined.
     */
    abstract public function compare(string $assertion, string $value): ?bool;
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\X501\MatchingRule;

use _ContaoManager\SpomkyLabs\Pki\X501\StringPrep\StringPreparer;
/**
 * Implements 'caseIgnoreMatch' matching rule.
 *
 * @see https://tools.ietf.org/html/rfc4517#section-4.2.11
 */
final class CaseIgnoreMatch extends StringPrepMatchingRule
{
    /**
     * @param int $stringType ASN.1 string type tag
     */
    private function __construct(int $stringType)
    {
        parent::__construct(StringPreparer::forStringType($stringType)->withCaseFolding(\true));
    }
    public static function create(int $stringType): self
    {
        return new self($stringType);
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\X501\MatchingRule;

use _ContaoManager\SpomkyLabs\Pki\X501\StringPrep\StringPreparer;
/**
 * Implements 'caseExactMatch' matching rule.
 *
 * @see https://tools.ietf.org/html/rfc4517#section-4.2.4
 */
final class CaseExactMatch extends StringPrepMatchingRule
{
    /**
     * @param int $stringType ASN.1 string type tag
     */
    private function __construct(int $stringType)
    {
        parent::__construct(StringPreparer::forStringType($stringType));
    }
    public static function create(int $stringType): self
    {
        return new self($stringType);
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\X501\MatchingRule;

use _ContaoManager\SpomkyLabs\Pki\X501\StringPrep\StringPreparer;
/**
 * Base class for matching rules employing string preparement semantics.
 */
abstract class StringPrepMatchingRule extends MatchingRule
{
    protected function __construct(private readonly StringPreparer $preparer)
    {
    }
    public function compare(string $assertion, string $value): ?bool
    {
        $assertion = $this->preparer->prepare($assertion);
        $value = $this->preparer->prepare($value);
        return strcmp($assertion, $value) === 0;
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\X501\MatchingRule;

/**
 * Implements binary matching rule.
 *
 * Generally used only by UnknownAttribute and custom attributes.
 */
final class BinaryMatch extends MatchingRule
{
    public function compare(string $assertion, string $value): bool
    {
        return strcmp($assertion, $value) === 0;
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\X501\StringPrep;

use const MB_CASE_LOWER;
/**
 * Implements 'Map' step of the Internationalized String Preparation as specified by RFC 4518.
 *
 * @see https://tools.ietf.org/html/rfc4518#section-2.2
 */
final class MapStep implements PrepareStep
{
    /**
     * @param bool $fold Whether to apply case folding
     */
    private function __construct(private readonly bool $fold)
    {
    }
    public static function create(bool $fold = \false): self
    {
        return new self($fold);
    }
    /**
     * @param string $string UTF-8 encoded string
     */
    public function apply(string $string): string
    {
        // @todo Implement character mappings
        if ($this->fold) {
            $string = mb_convert_case($string, MB_CASE_LOWER, 'UTF-8');
        }
        return $string;
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\X501\StringPrep;

use Normalizer;
/**
 * Implements 'Normalize' step of the Internationalized String Preparation as specified by RFC 4518.
 *
 * @see https://tools.ietf.org/html/rfc4518#section-2.3
 */
final class NormalizeStep implements PrepareStep
{
    /**
     * @param string $string UTF-8 encoded string
     */
    public function apply(string $string): string
    {
        return normalizer_normalize($string, Normalizer::NFKC);
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\X501\StringPrep;

/**
 * Interface for string preparation steps of Internationalized String Preparation algorithm specified by RFC 4518.
 *
 * @see https://tools.ietf.org/html/rfc4518#section-2
 */
interface PrepareStep
{
    /**
     * Apply string preparation step.
     *
     * @param string $string String to prepare
     *
     * @return string Prepared string
     */
    public function apply(string $string): string;
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\X501\StringPrep;

use function in_array;
use LogicException;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Element;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Primitive\T61String;
use function sprintf;
/**
 * Implements 'Transcode' step of the Internationalized String Preparation as specified by RFC 4518.
 *
 * @see https://tools.ietf.org/html/rfc4518#section-2.1
 */
final class TranscodeStep implements PrepareStep
{
    /**
     * Supported ASN.1 types.
     *
     * @var array<int>
     */
    private const SUPPORTED_TYPES = [Element::TYPE_UTF8_STRING, Element::TYPE_PRINTABLE_STRING, Element::TYPE_BMP_STRING, Element::TYPE_UNIVERSAL_STRING, Element::TYPE_T61_STRING];
    /**
     * @param int $_type ASN.1 type tag of the string
     */
    private function __construct(private readonly int $_type)
    {
    }
    public static function create(int $_type): self
    {
        return new self($_type);
    }
    /**
     * Check whether transcoding from given ASN.1 type tag is supported.
     *
     * @param int $type ASN.1 type tag
     */
    public static function isTypeSupported(int $type): bool
    {
        return in_array($type, self::SUPPORTED_TYPES, \true);
    }
    /**
     * @param string $string String to prepare
     *
     * @return string UTF-8 encoded string
     */
    public function apply(string $string): string
    {
        switch ($this->_type) {
            // UTF-8 string as is
            case Element::TYPE_UTF8_STRING:
            // PrintableString maps directly to UTF-8
            case Element::TYPE_PRINTABLE_STRING:
                return $string;
            // UCS-2 to UTF-8
            case Element::TYPE_BMP_STRING:
                return mb_convert_encoding($string, 'UTF-8', 'UCS-2BE');
            // UCS-4 to UTF-8
            case Element::TYPE_UNIVERSAL_STRING:
                return mb_convert_encoding($string, 'UTF-8', 'UCS-4BE');
            // TeletexString mapping is a local matter.
            // We take a shortcut here and encode it as a hexstring.
            case Element::TYPE_T61_STRING:
                $el = T61String::create($string);
                return '#' . bin2hex($el->toDER());
        }
        throw new LogicException(sprintf('Unsupported string type %s.', Element::tagToName($this->_type)));
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\X501\StringPrep;

/**
 * Implements 'Check bidi' step of the Internationalized String Preparation as specified by RFC 4518.
 *
 * @see https://tools.ietf.org/html/rfc4518#section-2.5
 */
final class CheckBidiStep implements PrepareStep
{
    /**
     * @param string $string UTF-8 encoded string
     */
    public function apply(string $string): string
    {
        // @todo Implement
        return $string;
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\X501\StringPrep;

/**
 * Implement Internationalized String Preparation as specified by RFC 4518.
 *
 * @see https://tools.ietf.org/html/rfc4518
 */
final class StringPreparer
{
    final public const STEP_TRANSCODE = 1;
    final public const STEP_MAP = 2;
    final public const STEP_NORMALIZE = 3;
    final public const STEP_PROHIBIT = 4;
    final public const STEP_CHECK_BIDI = 5;
    final public const STEP_INSIGNIFICANT_CHARS = 6;
    /**
     * @param PrepareStep[] $_steps Preparation steps to apply
     */
    private function __construct(
        /**
         * Preparation steps.
         */
        private array $_steps
    )
    {
    }
    /**
     * Get default instance for given string type.
     *
     * @param int $string_type ASN.1 string type tag.
     */
    public static function forStringType(int $string_type): self
    {
        $steps = [
            self::STEP_TRANSCODE => TranscodeStep::create($string_type),
            self::STEP_MAP => MapStep::create(),
            self::STEP_NORMALIZE => new NormalizeStep(),
            self::STEP_PROHIBIT => new ProhibitStep(),
            self::STEP_CHECK_BIDI => new CheckBidiStep(),
            // @todo Vary by string type
            self::STEP_INSIGNIFICANT_CHARS => new InsignificantNonSubstringSpaceStep(),
        ];
        return new self($steps);
    }
    /**
     * Get self with case folding set.
     *
     * @param bool $fold True to apply case folding
     */
    public function withCaseFolding(bool $fold): self
    {
        $obj = clone $this;
        $obj->_steps[self::STEP_MAP] = MapStep::create($fold);
        return $obj;
    }
    /**
     * Prepare string.
     */
    public function prepare(string $string): string
    {
        foreach ($this->_steps as $step) {
            $string = $step->apply($string);
        }
        return $string;
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\X501\StringPrep;

/**
 * Implements 'Prohibit' step of the Internationalized String Preparation as specified by RFC 4518.
 *
 * @see https://tools.ietf.org/html/rfc4518#section-2.4
 */
final class ProhibitStep implements PrepareStep
{
    /**
     * @param string $string UTF-8 encoded string
     */
    public function apply(string $string): string
    {
        // @todo Implement
        return $string;
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\X501\StringPrep;

/**
 * Implements 'Insignificant Space Handling' step of the Internationalized String Preparation as specified by RFC 4518.
 *
 * This variant handles input strings that are non-substring assertion values.
 *
 * @see https://tools.ietf.org/html/rfc4518#section-2.6.1
 */
final class InsignificantNonSubstringSpaceStep implements PrepareStep
{
    /**
     * @param string $string UTF-8 encoded string
     */
    public function apply(string $string): string
    {
        // if value contains no non-space characters
        if (preg_match('/^\p{Zs}*$/u', $string) === 1) {
            return '  ';
        }
        // trim leading and trailing spaces
        $string = preg_replace('/^\p{Zs}+/u', '', $string);
        $string = preg_replace('/\p{Zs}+$/u', '', (string) $string);
        // convert inner space sequences to two U+0020 characters
        $string = preg_replace('/\p{Zs}+/u', '  ', (string) $string);
        return " {$string} ";
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\CryptoTypes\Signature;

use InvalidArgumentException;
use function mb_strlen;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Primitive\BitString;
/**
 * Implements Ed25519 signature value.
 *
 * @todo Implement signature parsing
 *
 * @see https://tools.ietf.org/html/rfc8032#section-5.1.6
 */
final class Ed25519Signature extends Signature
{
    /**
     * Signature value.
     */
    private readonly string $signature;
    private function __construct(string $signature)
    {
        if (mb_strlen($signature, '8bit') !== 64) {
            throw new InvalidArgumentException('Ed25519 signature must be 64 octets.');
        }
        $this->signature = $signature;
    }
    public static function create(string $signature): self
    {
        return new self($signature);
    }
    public function bitString(): BitString
    {
        return BitString::create($this->signature);
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\CryptoTypes\Signature;

use InvalidArgumentException;
use function mb_strlen;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Primitive\BitString;
/**
 * Implements Ed448 signature value.
 *
 * @todo Implement signature parsing
 *
 * @see https://tools.ietf.org/html/rfc8032#section-5.2.6
 */
final class Ed448Signature extends Signature
{
    /**
     * Signature value.
     */
    private readonly string $signature;
    private function __construct(string $signature)
    {
        if (mb_strlen($signature, '8bit') !== 114) {
            throw new InvalidArgumentException('Ed448 signature must be 114 octets.');
        }
        $this->signature = $signature;
    }
    public static function create(string $signature): self
    {
        return new self($signature);
    }
    public function bitString(): BitString
    {
        return BitString::create($this->signature);
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\CryptoTypes\Signature;

use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Primitive\BitString;
use _ContaoManager\SpomkyLabs\Pki\CryptoTypes\AlgorithmIdentifier\Feature\AlgorithmIdentifierType;
/**
 * Generic signature value container.
 */
final class GenericSignature extends Signature
{
    /**
     * @param BitString $signature Signature value
     * @param AlgorithmIdentifierType $signatureAlgorithm Algorithm identifier
     */
    private function __construct(private readonly BitString $signature, private readonly AlgorithmIdentifierType $signatureAlgorithm)
    {
    }
    public static function create(BitString $signature, AlgorithmIdentifierType $signatureAlgorithm): self
    {
        return new self($signature, $signatureAlgorithm);
    }
    /**
     * Get the signature algorithm.
     */
    public function signatureAlgorithm(): AlgorithmIdentifierType
    {
        return $this->signatureAlgorithm;
    }
    public function bitString(): BitString
    {
        return $this->signature;
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\CryptoTypes\Signature;

use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Constructed\Sequence;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Primitive\BitString;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Primitive\Integer;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\UnspecifiedType;
/**
 * Implements ECDSA signature value.
 *
 * ECDSA signature is represented as a `ECDSA-Sig-Value` ASN.1 type.
 *
 * @see https://tools.ietf.org/html/rfc3278#section-8.2
 */
final class ECSignature extends Signature
{
    private function __construct(private readonly string $r, private readonly string $s)
    {
    }
    public static function create(string $r, string $s): self
    {
        return new self($r, $s);
    }
    /**
     * Initialize from ASN.1.
     */
    public static function fromASN1(Sequence $seq): self
    {
        $r = $seq->at(0)->asInteger()->number();
        $s = $seq->at(1)->asInteger()->number();
        return self::create($r, $s);
    }
    /**
     * Initialize from DER.
     */
    public static function fromDER(string $data): self
    {
        return self::fromASN1(UnspecifiedType::fromDER($data)->asSequence());
    }
    /**
     * Get the r-value.
     *
     * @return string Base 10 integer string
     */
    public function r(): string
    {
        return $this->r;
    }
    /**
     * Get the s-value.
     *
     * @return string Base 10 integer string
     */
    public function s(): string
    {
        return $this->s;
    }
    /**
     * Generate ASN.1 structure.
     */
    public function toASN1(): Sequence
    {
        return Sequence::create(Integer::create($this->r), Integer::create($this->s));
    }
    /**
     * Get DER encoding of the signature.
     */
    public function toDER(): string
    {
        return $this->toASN1()->toDER();
    }
    public function bitString(): BitString
    {
        return BitString::create($this->toDER());
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\CryptoTypes\Signature;

use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Primitive\BitString;
use function strval;
/**
 * Implements RSA signature value.
 *
 * @todo Implement signature parsing
 *
 * @see https://tools.ietf.org/html/rfc2313#section-10
 */
final class RSASignature extends Signature
{
    /**
     * Signature value *S*.
     */
    private ?string $_signature = null;
    /**
     * Initialize from RSA signature *S*.
     *
     * Signature value *S* is the result of last step in RSA signature process defined in PKCS #1.
     *
     * @see https://tools.ietf.org/html/rfc2313#section-10.1.4
     *
     * @param string $signature Signature bits
     *
     * @return self
     */
    public static function fromSignatureString(string $signature): Signature
    {
        $obj = new self();
        $obj->_signature = strval($signature);
        return $obj;
    }
    public function bitString(): BitString
    {
        return BitString::create($this->_signature);
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\CryptoTypes\Signature;

use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Primitive\BitString;
use _ContaoManager\SpomkyLabs\Pki\CryptoTypes\AlgorithmIdentifier\Asymmetric\Ed25519AlgorithmIdentifier;
use _ContaoManager\SpomkyLabs\Pki\CryptoTypes\AlgorithmIdentifier\Asymmetric\Ed448AlgorithmIdentifier;
use _ContaoManager\SpomkyLabs\Pki\CryptoTypes\AlgorithmIdentifier\Feature\AlgorithmIdentifierType;
use _ContaoManager\SpomkyLabs\Pki\CryptoTypes\AlgorithmIdentifier\Signature\ECSignatureAlgorithmIdentifier;
use _ContaoManager\SpomkyLabs\Pki\CryptoTypes\AlgorithmIdentifier\Signature\RSASignatureAlgorithmIdentifier;
/**
 * Base class for signature values.
 */
abstract class Signature
{
    /**
     * Get the signature as a BitString.
     */
    abstract public function bitString(): BitString;
    /**
     * Get signature object by signature data and used algorithm.
     *
     * @param string $data Signature value
     * @param AlgorithmIdentifierType $algo Algorithm identifier
     */
    public static function fromSignatureData(string $data, AlgorithmIdentifierType $algo): self
    {
        if ($algo instanceof RSASignatureAlgorithmIdentifier) {
            return RSASignature::fromSignatureString($data);
        }
        if ($algo instanceof ECSignatureAlgorithmIdentifier) {
            return ECSignature::fromDER($data);
        }
        if ($algo instanceof Ed25519AlgorithmIdentifier) {
            return Ed25519Signature::create($data);
        }
        if ($algo instanceof Ed448AlgorithmIdentifier) {
            return Ed448Signature::create($data);
        }
        return GenericSignature::create(BitString::create($data), $algo);
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\CryptoTypes\Asymmetric;

use function in_array;
use LogicException;
use RuntimeException;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Element;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Constructed\Sequence;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Primitive\BitString;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Primitive\Integer;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Primitive\OctetString;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Tagged\ImplicitlyTaggedType;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\UnspecifiedType;
use _ContaoManager\SpomkyLabs\Pki\CryptoEncoding\PEM;
use _ContaoManager\SpomkyLabs\Pki\CryptoTypes\AlgorithmIdentifier\AlgorithmIdentifier;
use _ContaoManager\SpomkyLabs\Pki\CryptoTypes\AlgorithmIdentifier\Asymmetric\ECPublicKeyAlgorithmIdentifier;
use _ContaoManager\SpomkyLabs\Pki\CryptoTypes\AlgorithmIdentifier\Feature\AlgorithmIdentifierType;
use _ContaoManager\SpomkyLabs\Pki\CryptoTypes\Asymmetric\Attribute\OneAsymmetricKeyAttributes;
use _ContaoManager\SpomkyLabs\Pki\CryptoTypes\Asymmetric\EC\ECPrivateKey;
use _ContaoManager\SpomkyLabs\Pki\CryptoTypes\Asymmetric\RFC8410\Curve25519\Ed25519PrivateKey;
use _ContaoManager\SpomkyLabs\Pki\CryptoTypes\Asymmetric\RFC8410\Curve25519\X25519PrivateKey;
use _ContaoManager\SpomkyLabs\Pki\CryptoTypes\Asymmetric\RFC8410\Curve448\Ed448PrivateKey;
use _ContaoManager\SpomkyLabs\Pki\CryptoTypes\Asymmetric\RFC8410\Curve448\X448PrivateKey;
use _ContaoManager\SpomkyLabs\Pki\CryptoTypes\Asymmetric\RSA\RSAPrivateKey;
use _ContaoManager\SpomkyLabs\Pki\CryptoTypes\Asymmetric\RSA\RSASSAPSSPrivateKey;
use UnexpectedValueException;
/**
 * Implements PKCS #8 PrivateKeyInfo / OneAsymmetricKey ASN.1 type.
 *
 * @see https://tools.ietf.org/html/rfc5208#section-5
 * @see https://tools.ietf.org/html/rfc5958#section-2
 */
class OneAsymmetricKey
{
    /**
     * Version number for PrivateKeyInfo.
     *
     * @var int
     */
    final public const VERSION_1 = 0;
    /**
     * Version number for OneAsymmetricKey.
     *
     * @var int
     */
    final public const VERSION_2 = 1;
    /**
     * Version number.
     */
    private int $version;
    /**
     * @param AlgorithmIdentifierType $algo Algorithm
     * @param string $privateKeyData Private key data
     * @param null|OneAsymmetricKeyAttributes $attributes Optional attributes
     * @param null|BitString $publicKeyData Optional public key
     */
    protected function __construct(protected AlgorithmIdentifierType $algo, protected string $privateKeyData, protected ?OneAsymmetricKeyAttributes $attributes = null, protected ?BitString $publicKeyData = null, ?int $version = null)
    {
        $this->version = $version ?? self::VERSION_2;
    }
    public static function create(AlgorithmIdentifierType $algo, string $privateKeyData, ?OneAsymmetricKeyAttributes $attributes = null, ?BitString $publicKeyData = null): self
    {
        return new self($algo, $privateKeyData, $attributes, $publicKeyData);
    }
    /**
     * Get self with version number.
     */
    public function withVersion(int $version): self
    {
        $obj = clone $this;
        $obj->version = $version;
        return $obj;
    }
    /**
     * Initialize from ASN.1.
     */
    public static function fromASN1(Sequence $seq): static
    {
        $version = $seq->at(0)->asInteger()->intNumber();
        if (!in_array($version, [self::VERSION_1, self::VERSION_2], \true)) {
            throw new UnexpectedValueException("Version {$version} not supported.");
        }
        $algo = AlgorithmIdentifier::fromASN1($seq->at(1)->asSequence());
        $key = $seq->at(2)->asOctetString()->string();
        $attribs = null;
        if ($seq->hasTagged(0)) {
            $attribs = OneAsymmetricKeyAttributes::fromASN1($seq->getTagged(0)->asImplicit(Element::TYPE_SET)->asSet());
        }
        $pubkey = null;
        if ($seq->hasTagged(1)) {
            $pubkey = $seq->getTagged(1)->asImplicit(Element::TYPE_BIT_STRING)->asBitString();
        }
        return static::create($algo, $key, $attribs, $pubkey)->withVersion($version);
    }
    /**
     * Initialize from DER data.
     */
    public static function fromDER(string $data): static
    {
        return static::fromASN1(UnspecifiedType::fromDER($data)->asSequence());
    }
    /**
     * Initialize from a `PrivateKey`.
     *
     * Note that `OneAsymmetricKey` <-> `PrivateKey` conversions may not be bidirectional with all key types, since
     * `OneAsymmetricKey` may include attributes as well the public key that are not conveyed in a specific `PrivateKey`
     * object.
     */
    public static function fromPrivateKey(PrivateKey $private_key): static
    {
        return static::create($private_key->algorithmIdentifier(), $private_key->privateKeyData());
    }
    /**
     * Initialize from PEM.
     */
    public static function fromPEM(PEM $pem): self
    {
        return match ($pem->type()) {
            PEM::TYPE_PRIVATE_KEY => self::fromDER($pem->data()),
            PEM::TYPE_RSA_PRIVATE_KEY => self::fromPrivateKey(RSAPrivateKey::fromDER($pem->data())),
            PEM::TYPE_EC_PRIVATE_KEY => self::fromPrivateKey(ECPrivateKey::fromDER($pem->data())),
            default => throw new UnexpectedValueException('Invalid PEM type.'),
        };
    }
    /**
     * Get version number.
     */
    public function version(): int
    {
        return $this->version;
    }
    /**
     * Get algorithm identifier.
     */
    public function algorithmIdentifier(): AlgorithmIdentifierType
    {
        return $this->algo;
    }
    /**
     * Get private key data.
     */
    public function privateKeyData(): string
    {
        return $this->privateKeyData;
    }
    /**
     * Get private key.
     */
    public function privateKey(): PrivateKey
    {
        $algo = $this->algorithmIdentifier();
        switch ($algo->oid()) {
            // RSA
            case AlgorithmIdentifier::OID_RSA_ENCRYPTION:
                return RSAPrivateKey::fromDER($this->privateKeyData);
            // RSASSA-PSS
            case AlgorithmIdentifier::OID_RSASSA_PSS_ENCRYPTION:
                return RSASSAPSSPrivateKey::fromDER($this->privateKeyData);
            // elliptic curve
            case AlgorithmIdentifier::OID_EC_PUBLIC_KEY:
                $pk = ECPrivateKey::fromDER($this->privateKeyData);
                // NOTE: OpenSSL strips named curve from ECPrivateKey structure
                // when serializing into PrivateKeyInfo. However, RFC 5915 dictates
                // that parameters (NamedCurve) must always be included.
                // If private key doesn't encode named curve, assign from parameters.
                if (!$pk->hasNamedCurve()) {
                    if (!$algo instanceof ECPublicKeyAlgorithmIdentifier) {
                        throw new UnexpectedValueException('Not an EC algorithm.');
                    }
                    $pk = $pk->withNamedCurve($algo->namedCurve());
                }
                return $pk;
            // Ed25519
            case AlgorithmIdentifier::OID_ED25519:
                $pubkey = $this->publicKeyData?->string();
                // RFC 8410 defines `CurvePrivateKey ::= OCTET STRING` that
                // is encoded into private key data. So Ed25519 private key
                // is doubly wrapped into octet string encodings.
                return Ed25519PrivateKey::fromOctetString(OctetString::fromDER($this->privateKeyData), $pubkey)->withVersion($this->version)->withAttributes($this->attributes);
            // X25519
            case AlgorithmIdentifier::OID_X25519:
                $pubkey = $this->publicKeyData?->string();
                return X25519PrivateKey::fromOctetString(OctetString::fromDER($this->privateKeyData), $pubkey)->withVersion($this->version)->withAttributes($this->attributes);
            // Ed448
            case AlgorithmIdentifier::OID_ED448:
                $pubkey = $this->publicKeyData?->string();
                return Ed448PrivateKey::fromOctetString(OctetString::fromDER($this->privateKeyData), $pubkey)->withVersion($this->version)->withAttributes($this->attributes);
            // X448
            case AlgorithmIdentifier::OID_X448:
                $pubkey = $this->publicKeyData?->string();
                return X448PrivateKey::fromOctetString(OctetString::fromDER($this->privateKeyData), $pubkey)->withVersion($this->version)->withAttributes($this->attributes);
            default:
                throw new RuntimeException('Private key ' . $algo->name() . ' not supported.');
        }
    }
    /**
     * Get public key info corresponding to the private key.
     */
    public function publicKeyInfo(): PublicKeyInfo
    {
        // if public key is explicitly defined
        if ($this->hasPublicKeyData()) {
            return PublicKeyInfo::create($this->algo, $this->publicKeyData);
        }
        // else derive from private key
        return $this->privateKey()->publicKey()->publicKeyInfo();
    }
    /**
     * Whether attributes are present.
     */
    public function hasAttributes(): bool
    {
        return isset($this->attributes);
    }
    public function attributes(): OneAsymmetricKeyAttributes
    {
        if (!$this->hasAttributes()) {
            throw new LogicException('Attributes not set.');
        }
        return $this->attributes;
    }
    /**
     * Whether explicit public key data is present.
     */
    public function hasPublicKeyData(): bool
    {
        return isset($this->publicKeyData);
    }
    /**
     * Get the explicit public key data.
     */
    public function publicKeyData(): BitString
    {
        if (!$this->hasPublicKeyData()) {
            throw new LogicException('No explicit public key.');
        }
        return $this->publicKeyData;
    }
    /**
     * Generate ASN.1 structure.
     */
    public function toASN1(): Sequence
    {
        $elements = [Integer::create($this->version), $this->algo->toASN1(), OctetString::create($this->privateKeyData)];
        if ($this->attributes !== null) {
            $elements[] = ImplicitlyTaggedType::create(0, $this->attributes->toASN1());
        }
        if ($this->publicKeyData !== null) {
            $elements[] = ImplicitlyTaggedType::create(1, $this->publicKeyData);
        }
        return Sequence::create(...$elements);
    }
    /**
     * Generate DER encoding.
     */
    public function toDER(): string
    {
        return $this->toASN1()->toDER();
    }
    /**
     * Generate PEM.
     */
    public function toPEM(): PEM
    {
        return PEM::create(PEM::TYPE_PRIVATE_KEY, $this->toDER());
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\CryptoTypes\Asymmetric\Attribute;

use _ContaoManager\SpomkyLabs\Pki\X501\ASN1\AttributeValue\AttributeValue;
use _ContaoManager\SpomkyLabs\Pki\X501\ASN1\Collection\SetOfAttributes;
/**
 * Implements *OneAsymmetricKey*'s *Attribute* ASN.1 type.
 */
final class OneAsymmetricKeyAttributes extends SetOfAttributes
{
    /**
     * Initialize from attribute values.
     *
     * @param AttributeValue ...$values List of attribute values
     */
    public static function fromAttributeValues(AttributeValue ...$values): static
    {
        return static::create(...array_map(static fn(AttributeValue $value) => $value->toAttribute(), $values));
    }
    // Nothing yet. Extended from base class for future extensions.
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\CryptoTypes\Asymmetric\RSA;

use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Constructed\Sequence;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Primitive\Integer;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\UnspecifiedType;
use _ContaoManager\SpomkyLabs\Pki\CryptoEncoding\PEM;
use _ContaoManager\SpomkyLabs\Pki\CryptoTypes\AlgorithmIdentifier\AlgorithmIdentifier;
use _ContaoManager\SpomkyLabs\Pki\CryptoTypes\AlgorithmIdentifier\Asymmetric\RSAEncryptionAlgorithmIdentifier;
use _ContaoManager\SpomkyLabs\Pki\CryptoTypes\AlgorithmIdentifier\Feature\AlgorithmIdentifierType;
use _ContaoManager\SpomkyLabs\Pki\CryptoTypes\Asymmetric\PublicKey;
use _ContaoManager\SpomkyLabs\Pki\CryptoTypes\Asymmetric\PublicKeyInfo;
use UnexpectedValueException;
/**
 * Implements PKCS #1 RSAPublicKey ASN.1 type.
 *
 * @see https://tools.ietf.org/html/rfc2437#section-11.1.1
 */
final class RSAPublicKey extends PublicKey
{
    private function __construct(private readonly string $modulus, private readonly string $publicExponent)
    {
    }
    public static function create(string $modulus, string $publicExponent): self
    {
        return new self($modulus, $publicExponent);
    }
    /**
     * Initialize from ASN.1.
     */
    public static function fromASN1(Sequence $seq): self
    {
        $n = $seq->at(0)->asInteger()->number();
        $e = $seq->at(1)->asInteger()->number();
        return self::create($n, $e);
    }
    /**
     * Initialize from DER data.
     */
    public static function fromDER(string $data): self
    {
        return self::fromASN1(UnspecifiedType::fromDER($data)->asSequence());
    }
    /**
     * @see PublicKey::fromPEM()
     */
    public static function fromPEM(PEM $pem): self
    {
        switch ($pem->type()) {
            case PEM::TYPE_RSA_PUBLIC_KEY:
                return self::fromDER($pem->data());
            case PEM::TYPE_PUBLIC_KEY:
                $pki = PublicKeyInfo::fromDER($pem->data());
                if ($pki->algorithmIdentifier()->oid() !== AlgorithmIdentifier::OID_RSA_ENCRYPTION) {
                    throw new UnexpectedValueException('Not an RSA public key.');
                }
                return self::fromDER($pki->publicKeyData()->string());
        }
        throw new UnexpectedValueException('Invalid PEM type ' . $pem->type());
    }
    /**
     * Get modulus.
     *
     * @return string Base 10 integer
     */
    public function modulus(): string
    {
        return $this->modulus;
    }
    /**
     * Get public exponent.
     *
     * @return string Base 10 integer
     */
    public function publicExponent(): string
    {
        return $this->publicExponent;
    }
    public function algorithmIdentifier(): AlgorithmIdentifierType
    {
        return RSAEncryptionAlgorithmIdentifier::create();
    }
    /**
     * Generate ASN.1 structure.
     */
    public function toASN1(): Sequence
    {
        return Sequence::create(Integer::create($this->modulus), Integer::create($this->publicExponent));
    }
    public function toDER(): string
    {
        return $this->toASN1()->toDER();
    }
    /**
     * Generate PEM.
     */
    public function toPEM(): PEM
    {
        return PEM::create(PEM::TYPE_RSA_PUBLIC_KEY, $this->toDER());
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\CryptoTypes\Asymmetric\RSA;

use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Constructed\Sequence;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Primitive\Integer;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\UnspecifiedType;
use _ContaoManager\SpomkyLabs\Pki\CryptoEncoding\PEM;
use _ContaoManager\SpomkyLabs\Pki\CryptoTypes\AlgorithmIdentifier\Asymmetric\RSAEncryptionAlgorithmIdentifier;
use _ContaoManager\SpomkyLabs\Pki\CryptoTypes\AlgorithmIdentifier\Feature\AlgorithmIdentifierType;
use _ContaoManager\SpomkyLabs\Pki\CryptoTypes\Asymmetric\PrivateKey;
use _ContaoManager\SpomkyLabs\Pki\CryptoTypes\Asymmetric\PublicKey;
use UnexpectedValueException;
/**
 * Implements PKCS #1 RSAPrivateKey ASN.1 type.
 *
 * @see https://tools.ietf.org/html/rfc2437#section-11.1.2
 */
final class RSAPrivateKey extends PrivateKey
{
    /**
     * @param string $modulus Modulus
     * @param string $publicExponent Public exponent
     * @param string $privateExponent Private exponent
     * @param string $prime1 First prime factor
     * @param string $prime2 Second prime factor
     * @param string $exponent1 First factor exponent
     * @param string $exponent2 Second factor exponent
     * @param string $coefficient CRT coefficient of the second factor
     */
    private function __construct(private readonly string $modulus, private readonly string $publicExponent, private readonly string $privateExponent, private readonly string $prime1, private readonly string $prime2, private readonly string $exponent1, private readonly string $exponent2, private readonly string $coefficient)
    {
    }
    public static function create(string $n, string $e, string $d, string $p, string $q, string $dp, string $dq, string $qi): self
    {
        return new self($n, $e, $d, $p, $q, $dp, $dq, $qi);
    }
    /**
     * Initialize from ASN.1.
     */
    public static function fromASN1(Sequence $seq): self
    {
        $version = $seq->at(0)->asInteger()->intNumber();
        if ($version !== 0) {
            throw new UnexpectedValueException('Version must be 0.');
        }
        // helper function get integer from given index
        $get_int = static fn($idx) => $seq->at($idx)->asInteger()->number();
        $n = $get_int(1);
        $e = $get_int(2);
        $d = $get_int(3);
        $p = $get_int(4);
        $q = $get_int(5);
        $dp = $get_int(6);
        $dq = $get_int(7);
        $qi = $get_int(8);
        return self::create($n, $e, $d, $p, $q, $dp, $dq, $qi);
    }
    /**
     * Initialize from DER data.
     */
    public static function fromDER(string $data): self
    {
        return self::fromASN1(UnspecifiedType::fromDER($data)->asSequence());
    }
    /**
     * @see PrivateKey::fromPEM()
     */
    public static function fromPEM(PEM $pem): self
    {
        $pk = parent::fromPEM($pem);
        if (!$pk instanceof self) {
            throw new UnexpectedValueException('Not an RSA private key.');
        }
        return $pk;
    }
    /**
     * Get modulus.
     *
     * @return string Base 10 integer
     */
    public function modulus(): string
    {
        return $this->modulus;
    }
    /**
     * Get public exponent.
     *
     * @return string Base 10 integer
     */
    public function publicExponent(): string
    {
        return $this->publicExponent;
    }
    /**
     * Get private exponent.
     *
     * @return string Base 10 integer
     */
    public function privateExponent(): string
    {
        return $this->privateExponent;
    }
    /**
     * Get first prime factor.
     *
     * @return string Base 10 integer
     */
    public function prime1(): string
    {
        return $this->prime1;
    }
    /**
     * Get second prime factor.
     *
     * @return string Base 10 integer
     */
    public function prime2(): string
    {
        return $this->prime2;
    }
    /**
     * Get first factor exponent.
     *
     * @return string Base 10 integer
     */
    public function exponent1(): string
    {
        return $this->exponent1;
    }
    /**
     * Get second factor exponent.
     *
     * @return string Base 10 integer
     */
    public function exponent2(): string
    {
        return $this->exponent2;
    }
    /**
     * Get CRT coefficient of the second factor.
     *
     * @return string Base 10 integer
     */
    public function coefficient(): string
    {
        return $this->coefficient;
    }
    public function algorithmIdentifier(): AlgorithmIdentifierType
    {
        return RSAEncryptionAlgorithmIdentifier::create();
    }
    /**
     * @return RSAPublicKey
     */
    public function publicKey(): PublicKey
    {
        return RSAPublicKey::create($this->modulus, $this->publicExponent);
    }
    /**
     * Generate ASN.1 structure.
     */
    public function toASN1(): Sequence
    {
        return Sequence::create(Integer::create(0), Integer::create($this->modulus), Integer::create($this->publicExponent), Integer::create($this->privateExponent), Integer::create($this->prime1), Integer::create($this->prime2), Integer::create($this->exponent1), Integer::create($this->exponent2), Integer::create($this->coefficient));
    }
    public function toDER(): string
    {
        return $this->toASN1()->toDER();
    }
    public function toPEM(): PEM
    {
        return PEM::create(PEM::TYPE_RSA_PRIVATE_KEY, $this->toDER());
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\CryptoTypes\Asymmetric\RSA;

use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Constructed\Sequence;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Primitive\Integer;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\UnspecifiedType;
use _ContaoManager\SpomkyLabs\Pki\CryptoEncoding\PEM;
use _ContaoManager\SpomkyLabs\Pki\CryptoTypes\AlgorithmIdentifier\Asymmetric\RSAPSSSSAEncryptionAlgorithmIdentifier;
use _ContaoManager\SpomkyLabs\Pki\CryptoTypes\AlgorithmIdentifier\Feature\AlgorithmIdentifierType;
use _ContaoManager\SpomkyLabs\Pki\CryptoTypes\Asymmetric\PrivateKey;
use _ContaoManager\SpomkyLabs\Pki\CryptoTypes\Asymmetric\PublicKey;
use UnexpectedValueException;
/**
 * Implements PKCS #1 RSASSAPSSPrivateKey ASN.1 type.
 *
 * @see https://datatracker.ietf.org/doc/html/rfc8017#section-8.1
 */
final class RSASSAPSSPrivateKey extends PrivateKey
{
    /**
     * @param string $modulus Modulus
     * @param string $publicExponent Public exponent
     * @param string $privateExponent Private exponent
     * @param string $prime1 First prime factor
     * @param string $prime2 Second prime factor
     * @param string $exponent1 First factor exponent
     * @param string $exponent2 Second factor exponent
     * @param string $coefficient CRT coefficient of the second factor
     */
    private function __construct(private readonly string $modulus, private readonly string $publicExponent, private readonly string $privateExponent, private readonly string $prime1, private readonly string $prime2, private readonly string $exponent1, private readonly string $exponent2, private readonly string $coefficient)
    {
    }
    public static function create(string $n, string $e, string $d, string $p, string $q, string $dp, string $dq, string $qi): self
    {
        return new self($n, $e, $d, $p, $q, $dp, $dq, $qi);
    }
    /**
     * Initialize from ASN.1.
     */
    public static function fromASN1(Sequence $seq): self
    {
        $version = $seq->at(0)->asInteger()->intNumber();
        if ($version !== 0) {
            throw new UnexpectedValueException('Version must be 0.');
        }
        // helper function get integer from given index
        $get_int = static fn($idx) => $seq->at($idx)->asInteger()->number();
        $n = $get_int(1);
        $e = $get_int(2);
        $d = $get_int(3);
        $p = $get_int(4);
        $q = $get_int(5);
        $dp = $get_int(6);
        $dq = $get_int(7);
        $qi = $get_int(8);
        return self::create($n, $e, $d, $p, $q, $dp, $dq, $qi);
    }
    /**
     * Initialize from DER data.
     */
    public static function fromDER(string $data): self
    {
        return self::fromASN1(UnspecifiedType::fromDER($data)->asSequence());
    }
    /**
     * @see PrivateKey::fromPEM()
     */
    public static function fromPEM(PEM $pem): self
    {
        $pk = parent::fromPEM($pem);
        if (!$pk instanceof self) {
            throw new UnexpectedValueException('Not an RSA private key.');
        }
        return $pk;
    }
    /**
     * Get modulus.
     *
     * @return string Base 10 integer
     */
    public function modulus(): string
    {
        return $this->modulus;
    }
    /**
     * Get public exponent.
     *
     * @return string Base 10 integer
     */
    public function publicExponent(): string
    {
        return $this->publicExponent;
    }
    /**
     * Get private exponent.
     *
     * @return string Base 10 integer
     */
    public function privateExponent(): string
    {
        return $this->privateExponent;
    }
    /**
     * Get first prime factor.
     *
     * @return string Base 10 integer
     */
    public function prime1(): string
    {
        return $this->prime1;
    }
    /**
     * Get second prime factor.
     *
     * @return string Base 10 integer
     */
    public function prime2(): string
    {
        return $this->prime2;
    }
    /**
     * Get first factor exponent.
     *
     * @return string Base 10 integer
     */
    public function exponent1(): string
    {
        return $this->exponent1;
    }
    /**
     * Get second factor exponent.
     *
     * @return string Base 10 integer
     */
    public function exponent2(): string
    {
        return $this->exponent2;
    }
    /**
     * Get CRT coefficient of the second factor.
     *
     * @return string Base 10 integer
     */
    public function coefficient(): string
    {
        return $this->coefficient;
    }
    public function algorithmIdentifier(): AlgorithmIdentifierType
    {
        return RSAPSSSSAEncryptionAlgorithmIdentifier::create();
    }
    /**
     * @return RSAPublicKey
     */
    public function publicKey(): PublicKey
    {
        return RSAPublicKey::create($this->modulus, $this->publicExponent);
    }
    /**
     * Generate ASN.1 structure.
     */
    public function toASN1(): Sequence
    {
        return Sequence::create(Integer::create(0), Integer::create($this->modulus), Integer::create($this->publicExponent), Integer::create($this->privateExponent), Integer::create($this->prime1), Integer::create($this->prime2), Integer::create($this->exponent1), Integer::create($this->exponent2), Integer::create($this->coefficient));
    }
    public function toDER(): string
    {
        return $this->toASN1()->toDER();
    }
    public function toPEM(): PEM
    {
        return PEM::create(PEM::TYPE_PRIVATE_KEY, $this->toDER());
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\CryptoTypes\Asymmetric\EC;

use function array_key_exists;
use function in_array;
use InvalidArgumentException;
use LogicException;
use function mb_strlen;
use function ord;
use RuntimeException;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Primitive\BitString;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Primitive\Integer;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Primitive\OctetString;
use _ContaoManager\SpomkyLabs\Pki\CryptoEncoding\PEM;
use _ContaoManager\SpomkyLabs\Pki\CryptoTypes\AlgorithmIdentifier\AlgorithmIdentifier;
use _ContaoManager\SpomkyLabs\Pki\CryptoTypes\AlgorithmIdentifier\Asymmetric\ECPublicKeyAlgorithmIdentifier;
use _ContaoManager\SpomkyLabs\Pki\CryptoTypes\AlgorithmIdentifier\Feature\AlgorithmIdentifierType;
use _ContaoManager\SpomkyLabs\Pki\CryptoTypes\Asymmetric\PublicKey;
use _ContaoManager\SpomkyLabs\Pki\CryptoTypes\Asymmetric\PublicKeyInfo;
use UnexpectedValueException;
/**
 * Implements elliptic curve public key type as specified by RFC 5480.
 *
 * @see https://tools.ietf.org/html/rfc5480#section-2.2
 */
final class ECPublicKey extends PublicKey
{
    /**
     * Elliptic curve public key.
     */
    private readonly string $ecPoint;
    /**
     * @param string $ecPoint ECPoint
     * @param null|string $namedCurve Named curve OID
     */
    private function __construct(string $ecPoint, private readonly ?string $namedCurve)
    {
        // first octet must be 0x04 for uncompressed form, and 0x02 or 0x03
        // for compressed form.
        if ($ecPoint === '' || !in_array(ord($ecPoint[0]), [2, 3, 4], \true)) {
            throw new InvalidArgumentException('Invalid ECPoint.');
        }
        $this->ecPoint = $ecPoint;
    }
    public static function create(string $ecPoint, ?string $namedCurve = null): self
    {
        return new self($ecPoint, $namedCurve);
    }
    /**
     * Initialize from curve point coordinates.
     *
     * @param int|string $x X coordinate as a base10 number
     * @param int|string $y Y coordinate as a base10 number
     * @param null|string $named_curve Named curve OID
     * @param null|int $bits Size of *p* in bits
     */
    public static function fromCoordinates(int|string $x, int|string $y, ?string $named_curve = null, ?int $bits = null): self
    {
        // if bitsize is not explicitly set, check from supported curves
        if (!isset($bits) && isset($named_curve)) {
            $bits = self::_curveSize($named_curve);
        }
        $mlen = null;
        if (isset($bits)) {
            $mlen = (int) ceil($bits / 8);
        }
        $x_os = ECConversion::integerToOctetString(Integer::create($x), $mlen)->string();
        $y_os = ECConversion::integerToOctetString(Integer::create($y), $mlen)->string();
        $ec_point = "\x04{$x_os}{$y_os}";
        return self::create($ec_point, $named_curve);
    }
    /**
     * @see PublicKey::fromPEM()
     */
    public static function fromPEM(PEM $pem): self
    {
        if ($pem->type() !== PEM::TYPE_PUBLIC_KEY) {
            throw new UnexpectedValueException('Not a public key.');
        }
        $pki = PublicKeyInfo::fromDER($pem->data());
        $algo = $pki->algorithmIdentifier();
        if ($algo->oid() !== AlgorithmIdentifier::OID_EC_PUBLIC_KEY || !$algo instanceof ECPublicKeyAlgorithmIdentifier) {
            throw new UnexpectedValueException('Not an elliptic curve key.');
        }
        // ECPoint is directly mapped into public key data
        return self::create($pki->publicKeyData()->string(), $algo->namedCurve());
    }
    /**
     * Get ECPoint value.
     */
    public function ECPoint(): string
    {
        return $this->ecPoint;
    }
    /**
     * Get curve point coordinates.
     *
     * @return string[] Tuple of X and Y coordinates as base-10 numbers
     */
    public function curvePoint(): array
    {
        return array_map(ECConversion::octetsToNumber(...), $this->curvePointOctets());
    }
    /**
     * Get curve point coordinates in octet string representation.
     *
     * @return string[] tuple of X and Y field elements as a string
     */
    public function curvePointOctets(): array
    {
        if ($this->isCompressed()) {
            throw new RuntimeException('EC point compression not supported.');
        }
        $str = mb_substr($this->ecPoint, 1, null, '8bit');
        $length = (int) floor(mb_strlen($str, '8bit') / 2);
        if ($length < 1) {
            throw new RuntimeException('Invalid EC point.');
        }
        [$x, $y] = mb_str_split($str, $length, '8bit');
        return [$x, $y];
    }
    /**
     * Whether ECPoint is in compressed form.
     */
    public function isCompressed(): bool
    {
        $c = ord($this->ecPoint[0]);
        return $c !== 4;
    }
    /**
     * Whether named curve is present.
     */
    public function hasNamedCurve(): bool
    {
        return isset($this->namedCurve);
    }
    /**
     * Get named curve OID.
     */
    public function namedCurve(): string
    {
        if (!$this->hasNamedCurve()) {
            throw new LogicException('namedCurve not set.');
        }
        return $this->namedCurve;
    }
    public function algorithmIdentifier(): AlgorithmIdentifierType
    {
        return ECPublicKeyAlgorithmIdentifier::create($this->namedCurve());
    }
    /**
     * Generate ASN.1 element.
     */
    public function toASN1(): OctetString
    {
        return OctetString::create($this->ecPoint);
    }
    public function toDER(): string
    {
        return $this->toASN1()->toDER();
    }
    /**
     * @see https://tools.ietf.org/html/rfc5480#section-2.2
     */
    public function subjectPublicKey(): BitString
    {
        // ECPoint is directly mapped to subjectPublicKey
        return BitString::create($this->ecPoint);
    }
    /**
     * Get the curve size *p* in bits.
     *
     * @param string $oid Curve OID
     */
    private static function _curveSize(string $oid): ?int
    {
        if (!array_key_exists($oid, ECPublicKeyAlgorithmIdentifier::MAP_CURVE_TO_SIZE)) {
            return null;
        }
        return ECPublicKeyAlgorithmIdentifier::MAP_CURVE_TO_SIZE[$oid];
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\CryptoTypes\Asymmetric\EC;

use LogicException;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Constructed\Sequence;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Primitive\BitString;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Primitive\Integer;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Primitive\ObjectIdentifier;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Primitive\OctetString;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Tagged\ExplicitlyTaggedType;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\UnspecifiedType;
use _ContaoManager\SpomkyLabs\Pki\CryptoEncoding\PEM;
use _ContaoManager\SpomkyLabs\Pki\CryptoTypes\AlgorithmIdentifier\Asymmetric\ECPublicKeyAlgorithmIdentifier;
use _ContaoManager\SpomkyLabs\Pki\CryptoTypes\AlgorithmIdentifier\Feature\AlgorithmIdentifierType;
use _ContaoManager\SpomkyLabs\Pki\CryptoTypes\Asymmetric\PrivateKey;
use _ContaoManager\SpomkyLabs\Pki\CryptoTypes\Asymmetric\PublicKey;
use UnexpectedValueException;
/**
 * Implements elliptic curve private key type as specified by RFC 5915.
 *
 * @see https://tools.ietf.org/html/rfc5915#section-3
 */
final class ECPrivateKey extends PrivateKey
{
    /**
     * @param string $privateKey Private key
     * @param null|string $namedCurve OID of the named curve
     * @param null|string $publicKey ECPoint value
     */
    private function __construct(private readonly string $privateKey, private ?string $namedCurve, private readonly ?string $publicKey)
    {
    }
    public static function create(string $privateKey, ?string $namedCurve = null, ?string $publicKey = null): self
    {
        return new self($privateKey, $namedCurve, $publicKey);
    }
    /**
     * Initialize from ASN.1.
     */
    public static function fromASN1(Sequence $seq): self
    {
        $version = $seq->at(0)->asInteger()->intNumber();
        if ($version !== 1) {
            throw new UnexpectedValueException('Version must be 1.');
        }
        $private_key = $seq->at(1)->asOctetString()->string();
        $named_curve = null;
        if ($seq->hasTagged(0)) {
            $params = $seq->getTagged(0)->asExplicit();
            $named_curve = $params->asObjectIdentifier()->oid();
        }
        $public_key = null;
        if ($seq->hasTagged(1)) {
            $public_key = $seq->getTagged(1)->asExplicit()->asBitString()->string();
        }
        return self::create($private_key, $named_curve, $public_key);
    }
    /**
     * Initialize from DER data.
     */
    public static function fromDER(string $data): self
    {
        return self::fromASN1(UnspecifiedType::fromDER($data)->asSequence());
    }
    /**
     * @see PrivateKey::fromPEM()
     */
    public static function fromPEM(PEM $pem): self
    {
        $pk = parent::fromPEM($pem);
        if (!$pk instanceof self) {
            throw new UnexpectedValueException('Not an EC private key.');
        }
        return $pk;
    }
    /**
     * Get the EC private key value.
     *
     * @return string Octets of the private key
     */
    public function privateKeyOctets(): string
    {
        return $this->privateKey;
    }
    /**
     * Whether named curve is present.
     */
    public function hasNamedCurve(): bool
    {
        return isset($this->namedCurve);
    }
    /**
     * Get named curve OID.
     */
    public function namedCurve(): string
    {
        if (!$this->hasNamedCurve()) {
            throw new LogicException('namedCurve not set.');
        }
        return $this->namedCurve;
    }
    /**
     * Get self with named curve.
     *
     * @param null|string $named_curve Named curve OID
     */
    public function withNamedCurve(?string $named_curve): self
    {
        $obj = clone $this;
        $obj->namedCurve = $named_curve;
        return $obj;
    }
    public function algorithmIdentifier(): AlgorithmIdentifierType
    {
        return ECPublicKeyAlgorithmIdentifier::create($this->namedCurve());
    }
    /**
     * Whether public key is present.
     */
    public function hasPublicKey(): bool
    {
        return isset($this->publicKey);
    }
    /**
     * @return ECPublicKey
     */
    public function publicKey(): PublicKey
    {
        if (!$this->hasPublicKey()) {
            throw new LogicException('publicKey not set.');
        }
        return ECPublicKey::create($this->publicKey, $this->namedCurve());
    }
    /**
     * Generate ASN.1 structure.
     */
    public function toASN1(): Sequence
    {
        $elements = [Integer::create(1), OctetString::create($this->privateKey)];
        if (isset($this->namedCurve)) {
            $elements[] = ExplicitlyTaggedType::create(0, ObjectIdentifier::create($this->namedCurve));
        }
        if (isset($this->publicKey)) {
            $elements[] = ExplicitlyTaggedType::create(1, BitString::create($this->publicKey));
        }
        return Sequence::create(...$elements);
    }
    public function toDER(): string
    {
        return $this->toASN1()->toDER();
    }
    public function toPEM(): PEM
    {
        return PEM::create(PEM::TYPE_EC_PRIVATE_KEY, $this->toDER());
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\CryptoTypes\Asymmetric\EC;

use function assert;
use _ContaoManager\Brick\Math\BigInteger;
use function mb_strlen;
use RangeException;
use RuntimeException;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Primitive\BitString;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Primitive\Integer;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Primitive\OctetString;
/**
 * Implements data type conversions from SEC 1: Elliptic Curve Cryptography.
 *
 * @see http://www.secg.org/sec1-v2.pdf
 */
final class ECConversion
{
    /**
     * Perform Bit-String-to-Octet-String Conversion.
     *
     * Defined in SEC 1 section 2.3.1.
     */
    public static function bitStringToOctetString(BitString $bs): OctetString
    {
        $str = $bs->string();
        if ($bs->unusedBits() !== 0) {
            // @todo pad string
            throw new RuntimeException('Unaligned bitstrings to supported');
        }
        return OctetString::create($str);
    }
    /**
     * Perform Octet-String-to-Bit-String Conversion.
     *
     * Defined in SEC 1 section 2.3.2.
     */
    public static function octetStringToBitString(OctetString $os): BitString
    {
        return BitString::create($os->string());
    }
    /**
     * Perform Integer-to-Octet-String Conversion.
     *
     * Defined in SEC 1 section 2.3.7.
     *
     * @param null|int $mlen Optional desired output length
     */
    public static function integerToOctetString(Integer $num, ?int $mlen = null): OctetString
    {
        $bigInteger = BigInteger::of($num->getValue());
        $str = $bigInteger->toBytes(\false);
        if ($mlen !== null) {
            $len = mb_strlen($str, '8bit');
            if ($len > $mlen) {
                throw new RangeException('Number is too large.');
            }
            // pad with zeroes
            if ($len < $mlen) {
                $str = str_repeat("\x00", $mlen - $len) . $str;
            }
        }
        return OctetString::create($str);
    }
    /**
     * Perform Octet-String-to-Integer Conversion.
     *
     * Defined in SEC 1 section 2.3.8.
     */
    public static function octetStringToInteger(OctetString $os): Integer
    {
        $str = $os->string();
        assert($str !== '');
        $num = BigInteger::fromBytes($str, \false);
        return Integer::create($num);
    }
    /**
     * Convert a base-10 number to octets.
     *
     * This is a convenicence method for integer <-> octet string conversion without the need for external ASN.1
     * dependencies.
     *
     * @param int|string $num Number in base-10
     * @param null|int $mlen Optional desired output length
     */
    public static function numberToOctets(int|string $num, ?int $mlen = null): string
    {
        return self::integerToOctetString(Integer::create($num), $mlen)->string();
    }
    /**
     * Convert octets to a base-10 number.
     *
     * This is a convenicence method for integer <-> octet string conversion without the need for external ASN.1
     * dependencies.
     *
     * @return string Number in base-10
     */
    public static function octetsToNumber(string $str): string
    {
        return self::octetStringToInteger(OctetString::create($str))->number();
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\CryptoTypes\Asymmetric;

use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Primitive\BitString;
use _ContaoManager\SpomkyLabs\Pki\CryptoEncoding\PEM;
use _ContaoManager\SpomkyLabs\Pki\CryptoTypes\AlgorithmIdentifier\Feature\AlgorithmIdentifierType;
use _ContaoManager\SpomkyLabs\Pki\CryptoTypes\Asymmetric\RSA\RSAPublicKey;
use UnexpectedValueException;
/**
 * Base class for public keys.
 */
abstract class PublicKey
{
    /**
     * Get the public key algorithm identifier.
     */
    abstract public function algorithmIdentifier(): AlgorithmIdentifierType;
    /**
     * Get DER encoding of the public key.
     */
    abstract public function toDER(): string;
    /**
     * Get the public key data for subjectPublicKey in PublicKeyInfo.
     */
    public function subjectPublicKey(): BitString
    {
        return BitString::create($this->toDER());
    }
    /**
     * Get the public key as a PublicKeyInfo type.
     */
    public function publicKeyInfo(): PublicKeyInfo
    {
        return PublicKeyInfo::fromPublicKey($this);
    }
    /**
     * Initialize public key from PEM.
     *
     * @return PublicKey
     */
    public static function fromPEM(PEM $pem)
    {
        return match ($pem->type()) {
            PEM::TYPE_RSA_PUBLIC_KEY => RSAPublicKey::fromDER($pem->data()),
            PEM::TYPE_PUBLIC_KEY => PublicKeyInfo::fromPEM($pem)->publicKey(),
            default => throw new UnexpectedValueException('PEM type ' . $pem->type() . ' is not a valid public key.'),
        };
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\CryptoTypes\Asymmetric;

use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Primitive\BitString;
use _ContaoManager\SpomkyLabs\Pki\CryptoTypes\AlgorithmIdentifier\Feature\AlgorithmIdentifierType;
use _ContaoManager\SpomkyLabs\Pki\CryptoTypes\Asymmetric\Attribute\OneAsymmetricKeyAttributes;
/**
 * PrivateKeyInfo was first introduced in RFC 5208, but later refined as OneAsymmetricKey in RFC 5958 with backwards
 * compatibility.
 *
 * Thus `PrivateKeyInfo ::= OneAsymmetricKey`
 *
 * @see https://tools.ietf.org/html/rfc5208#section-5
 * @see https://tools.ietf.org/html/rfc5958#section-2
 */
final class PrivateKeyInfo extends OneAsymmetricKey
{
    // PrivateKeyInfo has version 1 by default
    public static function create(AlgorithmIdentifierType $algo, string $key, ?OneAsymmetricKeyAttributes $attributes = null, ?BitString $public_key = null): self
    {
        return new self($algo, $key, $attributes, $public_key, parent::VERSION_1);
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\CryptoTypes\Asymmetric\RFC8410;

use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Primitive\BitString;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Primitive\OctetString;
use _ContaoManager\SpomkyLabs\Pki\CryptoEncoding\PEM;
use _ContaoManager\SpomkyLabs\Pki\CryptoTypes\Asymmetric\Attribute\OneAsymmetricKeyAttributes;
use _ContaoManager\SpomkyLabs\Pki\CryptoTypes\Asymmetric\OneAsymmetricKey;
use _ContaoManager\SpomkyLabs\Pki\CryptoTypes\Asymmetric\PrivateKey;
/**
 * Implements an intermediary object to store a private key using Curve25519 or Curve448 as defined by RFC 8410.
 *
 * Private keys described in RFC 8410 may only be encoded as `OneAsymmetricKey` and thus version and attributes are also
 * stored in this type.
 *
 * @see https://tools.ietf.org/html/rfc8410
 */
abstract class RFC8410PrivateKey extends PrivateKey
{
    /**
     * Version for OneAsymmetricKey.
     */
    protected int $_version;
    /**
     * Attributes from OneAsymmetricKey.
     */
    protected ?OneAsymmetricKeyAttributes $_attributes;
    /**
     * @param string $_privateKeyData Private key data
     * @param null|string $_publicKeyData Public key data
     */
    protected function __construct(protected string $_privateKeyData, protected ?string $_publicKeyData = null)
    {
        $this->_version = OneAsymmetricKey::VERSION_2;
        $this->_attributes = null;
    }
    /**
     * Get self with version number.
     */
    public function withVersion(int $version): self
    {
        $obj = clone $this;
        $obj->_version = $version;
        return $obj;
    }
    /**
     * Get self with attributes.
     */
    public function withAttributes(?OneAsymmetricKeyAttributes $attribs): self
    {
        $obj = clone $this;
        $obj->_attributes = $attribs;
        return $obj;
    }
    public function privateKeyData(): string
    {
        return $this->_privateKeyData;
    }
    /**
     * Whether public key is set.
     */
    public function hasPublicKey(): bool
    {
        return isset($this->_publicKeyData);
    }
    /**
     * Generate ASN.1 structure.
     */
    public function toASN1(): OctetString
    {
        return OctetString::create($this->_privateKeyData);
    }
    public function toDER(): string
    {
        return $this->toASN1()->toDER();
    }
    public function toPEM(): PEM
    {
        $pub = $this->_publicKeyData === null ? null : BitString::create($this->_publicKeyData);
        return OneAsymmetricKey::create($this->algorithmIdentifier(), $this->toDER(), $this->_attributes, $pub)->withVersion($this->_version)->toPEM();
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\CryptoTypes\Asymmetric\RFC8410;

use LogicException;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Primitive\BitString;
use _ContaoManager\SpomkyLabs\Pki\CryptoTypes\Asymmetric\PublicKey;
/**
 * Implements an intermediary object to store a public key using Curve25519 or Curve448 as defined by RFC 8410.
 *
 * Public keys described in RFC 8410 may only be encoded as `SubjectPublicKeyInfo`.
 *
 * @see https://tools.ietf.org/html/rfc8410
 */
abstract class RFC8410PublicKey extends PublicKey
{
    /**
     * @param string $publicKey Public key data
     */
    protected function __construct(private readonly string $publicKey)
    {
    }
    public function toDER(): string
    {
        throw new LogicException("RFC 8410 public key doesn't have a DER encoding.");
    }
    public function subjectPublicKey(): BitString
    {
        return BitString::create($this->publicKey);
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\CryptoTypes\Asymmetric\RFC8410\Curve448;

use function mb_strlen;
use _ContaoManager\SpomkyLabs\Pki\CryptoTypes\AlgorithmIdentifier\Asymmetric\X448AlgorithmIdentifier;
use _ContaoManager\SpomkyLabs\Pki\CryptoTypes\AlgorithmIdentifier\Feature\AlgorithmIdentifierType;
use _ContaoManager\SpomkyLabs\Pki\CryptoTypes\Asymmetric\RFC8410\RFC8410PublicKey;
use UnexpectedValueException;
/**
 * Implements an intermediary class to store X448 public key.
 *
 * @see https://tools.ietf.org/html/rfc8410
 */
final class X448PublicKey extends RFC8410PublicKey
{
    /**
     * @param string $publicKey Public key data
     */
    private function __construct(string $publicKey)
    {
        if (mb_strlen($publicKey, '8bit') !== 56) {
            throw new UnexpectedValueException('X448 public key must be exactly 56 bytes.');
        }
        parent::__construct($publicKey);
    }
    public static function create(string $publicKey): self
    {
        return new self($publicKey);
    }
    public function algorithmIdentifier(): AlgorithmIdentifierType
    {
        return X448AlgorithmIdentifier::create();
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\CryptoTypes\Asymmetric\RFC8410\Curve448;

use function mb_strlen;
use _ContaoManager\SpomkyLabs\Pki\CryptoTypes\AlgorithmIdentifier\Asymmetric\Ed448AlgorithmIdentifier;
use _ContaoManager\SpomkyLabs\Pki\CryptoTypes\AlgorithmIdentifier\Feature\AlgorithmIdentifierType;
use _ContaoManager\SpomkyLabs\Pki\CryptoTypes\Asymmetric\RFC8410\RFC8410PublicKey;
use UnexpectedValueException;
/**
 * Implements an intermediary class to store Ed448 public key.
 *
 * @see https://tools.ietf.org/html/rfc8410
 */
final class Ed448PublicKey extends RFC8410PublicKey
{
    /**
     * @param string $publicKey Public key data
     */
    private function __construct(string $publicKey)
    {
        if (mb_strlen($publicKey, '8bit') !== 57) {
            throw new UnexpectedValueException('Ed448 public key must be exactly 57 bytes.');
        }
        parent::__construct($publicKey);
    }
    public static function create(string $publicKey): self
    {
        return new self($publicKey);
    }
    public function algorithmIdentifier(): AlgorithmIdentifierType
    {
        return Ed448AlgorithmIdentifier::create();
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\CryptoTypes\Asymmetric\RFC8410\Curve448;

use LogicException;
use function mb_strlen;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Primitive\OctetString;
use _ContaoManager\SpomkyLabs\Pki\CryptoTypes\AlgorithmIdentifier\Asymmetric\X448AlgorithmIdentifier;
use _ContaoManager\SpomkyLabs\Pki\CryptoTypes\AlgorithmIdentifier\Feature\AlgorithmIdentifierType;
use _ContaoManager\SpomkyLabs\Pki\CryptoTypes\Asymmetric\PublicKey;
use _ContaoManager\SpomkyLabs\Pki\CryptoTypes\Asymmetric\RFC8410\RFC8410PrivateKey;
use UnexpectedValueException;
/**
 * Implements an intermediary class to store X448 private key.
 *
 * @see https://tools.ietf.org/html/rfc8410
 */
final class X448PrivateKey extends RFC8410PrivateKey
{
    /**
     * @param string $private_key Private key data
     * @param null|string $public_key Public key data
     */
    protected function __construct(string $private_key, ?string $public_key = null)
    {
        if (mb_strlen($private_key, '8bit') !== 56) {
            throw new UnexpectedValueException('X448 private key must be exactly 56 bytes.');
        }
        if (isset($public_key) && mb_strlen($public_key, '8bit') !== 56) {
            throw new UnexpectedValueException('X448 public key must be exactly 56 bytes.');
        }
        parent::__construct($private_key, $public_key);
    }
    public static function create(string $private_key, ?string $public_key = null): self
    {
        return new self($private_key, $public_key);
    }
    /**
     * Initialize from `CurvePrivateKey` OctetString.
     *
     * @param OctetString $str Private key data wrapped into OctetString
     * @param null|string $public_key Optional public key data
     */
    public static function fromOctetString(OctetString $str, ?string $public_key = null): self
    {
        return self::create($str->string(), $public_key);
    }
    public function algorithmIdentifier(): AlgorithmIdentifierType
    {
        return X448AlgorithmIdentifier::create();
    }
    public function publicKey(): PublicKey
    {
        if (!$this->hasPublicKey()) {
            throw new LogicException('Public key not set.');
        }
        return X448PublicKey::create($this->_publicKeyData);
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\CryptoTypes\Asymmetric\RFC8410\Curve448;

use LogicException;
use function mb_strlen;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Primitive\OctetString;
use _ContaoManager\SpomkyLabs\Pki\CryptoTypes\AlgorithmIdentifier\Asymmetric\Ed448AlgorithmIdentifier;
use _ContaoManager\SpomkyLabs\Pki\CryptoTypes\AlgorithmIdentifier\Feature\AlgorithmIdentifierType;
use _ContaoManager\SpomkyLabs\Pki\CryptoTypes\Asymmetric\PublicKey;
use _ContaoManager\SpomkyLabs\Pki\CryptoTypes\Asymmetric\RFC8410\RFC8410PrivateKey;
use UnexpectedValueException;
/**
 * Implements an intermediary class to store Ed448 private key.
 *
 * @see https://tools.ietf.org/html/rfc8410
 */
final class Ed448PrivateKey extends RFC8410PrivateKey
{
    /**
     * @param string $private_key Private key data
     * @param null|string $public_key Public key data
     */
    protected function __construct(string $private_key, ?string $public_key = null)
    {
        if (mb_strlen($private_key, '8bit') !== 57) {
            throw new UnexpectedValueException('Ed448 private key must be exactly 57 bytes.');
        }
        if (isset($public_key) && mb_strlen($public_key, '8bit') !== 57) {
            throw new UnexpectedValueException('Ed448 public key must be exactly 57 bytes.');
        }
        parent::__construct($private_key, $public_key);
    }
    public static function create(string $private_key, ?string $public_key = null): self
    {
        return new self($private_key, $public_key);
    }
    /**
     * Initialize from `CurvePrivateKey` OctetString.
     *
     * @param OctetString $str Private key data wrapped into OctetString
     * @param null|string $public_key Optional public key data
     */
    public static function fromOctetString(OctetString $str, ?string $public_key = null): self
    {
        return self::create($str->string(), $public_key);
    }
    public function algorithmIdentifier(): AlgorithmIdentifierType
    {
        return Ed448AlgorithmIdentifier::create();
    }
    public function publicKey(): PublicKey
    {
        if (!$this->hasPublicKey()) {
            throw new LogicException('Public key not set.');
        }
        return Ed448PublicKey::create($this->_publicKeyData);
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\CryptoTypes\Asymmetric\RFC8410\Curve25519;

use _ContaoManager\SpomkyLabs\Pki\CryptoTypes\AlgorithmIdentifier\Asymmetric\X25519AlgorithmIdentifier;
use _ContaoManager\SpomkyLabs\Pki\CryptoTypes\AlgorithmIdentifier\Feature\AlgorithmIdentifierType;
/**
 * Implements an intermediary object to store X25519 public key.
 *
 * @see https://tools.ietf.org/html/rfc8410
 */
final class X25519PublicKey extends Curve25519PublicKey
{
    public static function create(string $publicKey): self
    {
        return new self($publicKey);
    }
    public function algorithmIdentifier(): AlgorithmIdentifierType
    {
        return X25519AlgorithmIdentifier::create();
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\CryptoTypes\Asymmetric\RFC8410\Curve25519;

use function mb_strlen;
use _ContaoManager\SpomkyLabs\Pki\CryptoTypes\Asymmetric\RFC8410\RFC8410PublicKey;
use UnexpectedValueException;
/**
 * Implements an intermediary object to store a public key using Curve25519.
 *
 * @see https://tools.ietf.org/html/rfc8410
 */
abstract class Curve25519PublicKey extends RFC8410PublicKey
{
    /**
     * @param string $publicKey Public key data
     */
    protected function __construct(string $publicKey)
    {
        if (mb_strlen($publicKey, '8bit') !== 32) {
            throw new UnexpectedValueException('Curve25519 public key must be exactly 32 bytes.');
        }
        parent::__construct($publicKey);
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\CryptoTypes\Asymmetric\RFC8410\Curve25519;

use LogicException;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Primitive\OctetString;
use _ContaoManager\SpomkyLabs\Pki\CryptoTypes\AlgorithmIdentifier\Asymmetric\X25519AlgorithmIdentifier;
use _ContaoManager\SpomkyLabs\Pki\CryptoTypes\AlgorithmIdentifier\Feature\AlgorithmIdentifierType;
use _ContaoManager\SpomkyLabs\Pki\CryptoTypes\Asymmetric\PublicKey;
/**
 * Implements an intermediary object to store X25519 private key.
 *
 * @see https://tools.ietf.org/html/rfc8410
 */
final class X25519PrivateKey extends Curve25519PrivateKey
{
    public static function create(string $private_key, ?string $public_key = null): self
    {
        return new self($private_key, $public_key);
    }
    /**
     * Initialize from `CurvePrivateKey` OctetString.
     *
     * @param OctetString $str Private key data wrapped into OctetString
     * @param null|string $public_key Optional public key data
     */
    public static function fromOctetString(OctetString $str, ?string $public_key = null): self
    {
        return self::create($str->string(), $public_key);
    }
    public function algorithmIdentifier(): AlgorithmIdentifierType
    {
        return X25519AlgorithmIdentifier::create();
    }
    public function publicKey(): PublicKey
    {
        if (!$this->hasPublicKey()) {
            throw new LogicException('Public key not set.');
        }
        return X25519PublicKey::create($this->_publicKeyData);
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\CryptoTypes\Asymmetric\RFC8410\Curve25519;

use function mb_strlen;
use _ContaoManager\SpomkyLabs\Pki\CryptoTypes\Asymmetric\RFC8410\RFC8410PrivateKey;
use UnexpectedValueException;
/**
 * Implements an intermediary object to store a private key using Curve25519.
 *
 * @see https://tools.ietf.org/html/rfc8410
 */
abstract class Curve25519PrivateKey extends RFC8410PrivateKey
{
    /**
     * @param string $private_key Private key data
     * @param null|string $public_key Public key data
     */
    protected function __construct(string $private_key, ?string $public_key = null)
    {
        if (mb_strlen($private_key, '8bit') !== 32) {
            throw new UnexpectedValueException('Curve25519 private key must be exactly 32 bytes.');
        }
        if (isset($public_key) && mb_strlen($public_key, '8bit') !== 32) {
            throw new UnexpectedValueException('Curve25519 public key must be exactly 32 bytes.');
        }
        parent::__construct($private_key, $public_key);
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\CryptoTypes\Asymmetric\RFC8410\Curve25519;

use _ContaoManager\SpomkyLabs\Pki\CryptoTypes\AlgorithmIdentifier\Asymmetric\Ed25519AlgorithmIdentifier;
use _ContaoManager\SpomkyLabs\Pki\CryptoTypes\AlgorithmIdentifier\Feature\AlgorithmIdentifierType;
/**
 * Implements an intermediary object to store Ed25519 public key.
 *
 * @see https://tools.ietf.org/html/rfc8410
 */
final class Ed25519PublicKey extends Curve25519PublicKey
{
    public static function create(string $publicKey): self
    {
        return new self($publicKey);
    }
    public function algorithmIdentifier(): AlgorithmIdentifierType
    {
        return Ed25519AlgorithmIdentifier::create();
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\CryptoTypes\Asymmetric\RFC8410\Curve25519;

use LogicException;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Primitive\OctetString;
use _ContaoManager\SpomkyLabs\Pki\CryptoTypes\AlgorithmIdentifier\Asymmetric\Ed25519AlgorithmIdentifier;
use _ContaoManager\SpomkyLabs\Pki\CryptoTypes\AlgorithmIdentifier\Feature\AlgorithmIdentifierType;
use _ContaoManager\SpomkyLabs\Pki\CryptoTypes\Asymmetric\PublicKey;
/**
 * Implements an intermediary object to store Ed25519 private key.
 *
 * @see https://tools.ietf.org/html/rfc8410
 */
final class Ed25519PrivateKey extends Curve25519PrivateKey
{
    public static function create(string $private_key, ?string $public_key = null): self
    {
        return new self($private_key, $public_key);
    }
    /**
     * Initialize from `CurvePrivateKey` OctetString.
     *
     * @param OctetString $str Private key data wrapped into OctetString
     * @param null|string $public_key Optional public key data
     */
    public static function fromOctetString(OctetString $str, ?string $public_key = null): self
    {
        return self::create($str->string(), $public_key);
    }
    public function algorithmIdentifier(): AlgorithmIdentifierType
    {
        return Ed25519AlgorithmIdentifier::create();
    }
    public function publicKey(): PublicKey
    {
        if (!$this->hasPublicKey()) {
            throw new LogicException('Public key not set.');
        }
        return Ed25519PublicKey::create($this->_publicKeyData);
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\CryptoTypes\Asymmetric;

use function chr;
use function ord;
use RuntimeException;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Constructed\Sequence;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Primitive\BitString;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\UnspecifiedType;
use _ContaoManager\SpomkyLabs\Pki\CryptoEncoding\PEM;
use _ContaoManager\SpomkyLabs\Pki\CryptoTypes\AlgorithmIdentifier\AlgorithmIdentifier;
use _ContaoManager\SpomkyLabs\Pki\CryptoTypes\AlgorithmIdentifier\Asymmetric\ECPublicKeyAlgorithmIdentifier;
use _ContaoManager\SpomkyLabs\Pki\CryptoTypes\AlgorithmIdentifier\Feature\AlgorithmIdentifierType;
use _ContaoManager\SpomkyLabs\Pki\CryptoTypes\Asymmetric\EC\ECPublicKey;
use _ContaoManager\SpomkyLabs\Pki\CryptoTypes\Asymmetric\RFC8410\Curve25519\Ed25519PublicKey;
use _ContaoManager\SpomkyLabs\Pki\CryptoTypes\Asymmetric\RFC8410\Curve25519\X25519PublicKey;
use _ContaoManager\SpomkyLabs\Pki\CryptoTypes\Asymmetric\RFC8410\Curve448\Ed448PublicKey;
use _ContaoManager\SpomkyLabs\Pki\CryptoTypes\Asymmetric\RFC8410\Curve448\X448PublicKey;
use _ContaoManager\SpomkyLabs\Pki\CryptoTypes\Asymmetric\RSA\RSAPublicKey;
use UnexpectedValueException;
/**
 * Implements X.509 SubjectPublicKeyInfo ASN.1 type.
 *
 * @see https://tools.ietf.org/html/rfc5280#section-4.1
 */
final class PublicKeyInfo
{
    /**
     * @param AlgorithmIdentifierType $algo Algorithm
     * @param BitString $publicKey Public key data
     */
    private function __construct(private readonly AlgorithmIdentifierType $algo, private readonly BitString $publicKey)
    {
    }
    public static function create(AlgorithmIdentifierType $algo, BitString $publicKey): self
    {
        return new self($algo, $publicKey);
    }
    /**
     * Initialize from ASN.1.
     */
    public static function fromASN1(Sequence $seq): self
    {
        $algo = AlgorithmIdentifier::fromASN1($seq->at(0)->asSequence());
        $key = $seq->at(1)->asBitString();
        return self::create($algo, $key);
    }
    /**
     * Initialize from a PublicKey.
     */
    public static function fromPublicKey(PublicKey $key): self
    {
        return self::create($key->algorithmIdentifier(), $key->subjectPublicKey());
    }
    /**
     * Initialize from PEM.
     */
    public static function fromPEM(PEM $pem): self
    {
        return match ($pem->type()) {
            PEM::TYPE_PUBLIC_KEY => self::fromDER($pem->data()),
            PEM::TYPE_RSA_PUBLIC_KEY => RSAPublicKey::fromDER($pem->data())->publicKeyInfo(),
            default => throw new UnexpectedValueException('Invalid PEM type.'),
        };
    }
    /**
     * Initialize from DER data.
     */
    public static function fromDER(string $data): self
    {
        return self::fromASN1(UnspecifiedType::fromDER($data)->asSequence());
    }
    /**
     * Get algorithm identifier.
     */
    public function algorithmIdentifier(): AlgorithmIdentifierType
    {
        return $this->algo;
    }
    /**
     * Get public key data.
     */
    public function publicKeyData(): BitString
    {
        return $this->publicKey;
    }
    /**
     * Get public key.
     */
    public function publicKey(): PublicKey
    {
        $algo = $this->algorithmIdentifier();
        switch ($algo->oid()) {
            // RSA
            case AlgorithmIdentifier::OID_RSA_ENCRYPTION:
                return RSAPublicKey::fromDER($this->publicKey->string());
            // Elliptic Curve
            case AlgorithmIdentifier::OID_EC_PUBLIC_KEY:
                if (!$algo instanceof ECPublicKeyAlgorithmIdentifier) {
                    throw new UnexpectedValueException('Not an EC algorithm.');
                }
                // ECPoint is directly mapped into public key data
                return ECPublicKey::create($this->publicKey->string(), $algo->namedCurve());
            // Ed25519
            case AlgorithmIdentifier::OID_ED25519:
                return Ed25519PublicKey::create($this->publicKey->string());
            // X25519
            case AlgorithmIdentifier::OID_X25519:
                return X25519PublicKey::create($this->publicKey->string());
            // Ed448
            case AlgorithmIdentifier::OID_ED448:
                return Ed448PublicKey::create($this->publicKey->string());
            // X448
            case AlgorithmIdentifier::OID_X448:
                return X448PublicKey::create($this->publicKey->string());
        }
        throw new RuntimeException('Public key ' . $algo->name() . ' not supported.');
    }
    /**
     * Get key identifier using method 1 as described by RFC 5280.
     *
     * @see https://tools.ietf.org/html/rfc5280#section-4.2.1.2
     *
     * @return string 20 bytes (160 bits) long identifier
     */
    public function keyIdentifier(): string
    {
        return sha1($this->publicKey->string(), \true);
    }
    /**
     * Get key identifier using method 2 as described by RFC 5280.
     *
     * @see https://tools.ietf.org/html/rfc5280#section-4.2.1.2
     *
     * @return string 8 bytes (64 bits) long identifier
     */
    public function keyIdentifier64(): string
    {
        $id = mb_substr($this->keyIdentifier(), -8, null, '8bit');
        $c = ord($id[0]) & 0xf | 0x40;
        $id[0] = chr($c);
        return $id;
    }
    /**
     * Generate ASN.1 structure.
     */
    public function toASN1(): Sequence
    {
        return Sequence::create($this->algo->toASN1(), $this->publicKey);
    }
    /**
     * Generate DER encoding.
     */
    public function toDER(): string
    {
        return $this->toASN1()->toDER();
    }
    /**
     * Generate PEM.
     */
    public function toPEM(): PEM
    {
        return PEM::create(PEM::TYPE_PUBLIC_KEY, $this->toDER());
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\CryptoTypes\Asymmetric;

use _ContaoManager\SpomkyLabs\Pki\CryptoEncoding\PEM;
use _ContaoManager\SpomkyLabs\Pki\CryptoTypes\AlgorithmIdentifier\Feature\AlgorithmIdentifierType;
use _ContaoManager\SpomkyLabs\Pki\CryptoTypes\Asymmetric\EC\ECPrivateKey;
use _ContaoManager\SpomkyLabs\Pki\CryptoTypes\Asymmetric\RSA\RSAPrivateKey;
use UnexpectedValueException;
/**
 * Base class for private keys.
 */
abstract class PrivateKey
{
    /**
     * Get the private key algorithm identifier.
     */
    abstract public function algorithmIdentifier(): AlgorithmIdentifierType;
    /**
     * Get public key component of the asymmetric key pair.
     */
    abstract public function publicKey(): PublicKey;
    /**
     * Get DER encoding of the private key.
     */
    abstract public function toDER(): string;
    /**
     * Get the private key as a PEM.
     */
    abstract public function toPEM(): PEM;
    /**
     * Get the private key data in type specific encoding.
     */
    public function privateKeyData(): string
    {
        // By default encode in DER. This is the case with RSA and EC keys.
        // Other keys may have more specific encoding schemes, so this
        // method must be overridden by derived classes.
        return $this->toDER();
    }
    /**
     * Get the private key as a PrivateKeyInfo type.
     */
    public function privateKeyInfo(): PrivateKeyInfo
    {
        return PrivateKeyInfo::fromPrivateKey($this);
    }
    /**
     * Initialize private key from PEM.
     *
     * @return PrivateKey
     */
    public static function fromPEM(PEM $pem)
    {
        return match ($pem->type()) {
            PEM::TYPE_RSA_PRIVATE_KEY => RSAPrivateKey::fromDER($pem->data()),
            PEM::TYPE_EC_PRIVATE_KEY => ECPrivateKey::fromDER($pem->data()),
            PEM::TYPE_PRIVATE_KEY => PrivateKeyInfo::fromDER($pem->data())->privateKey(),
            default => throw new UnexpectedValueException('PEM type ' . $pem->type() . ' is not a valid private key.'),
        };
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\CryptoTypes\AlgorithmIdentifier;

use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\UnspecifiedType;
/**
 * Base class for algorithm identifiers implementing specific functionality and parameter handling.
 */
abstract class SpecificAlgorithmIdentifier extends AlgorithmIdentifier
{
    /**
     * Initialize object from algorithm identifier parameters.
     *
     * @param null|UnspecifiedType $params Parameters or null if none
     */
    abstract public static function fromASN1Params(?UnspecifiedType $params = null): self;
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\CryptoTypes\AlgorithmIdentifier;

use _ContaoManager\SpomkyLabs\Pki\ASN1\Element;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Constructed\Sequence;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Primitive\ObjectIdentifier;
use _ContaoManager\SpomkyLabs\Pki\CryptoTypes\AlgorithmIdentifier\Feature\AlgorithmIdentifierType;
/**
 * Implements AlgorithmIdentifier ASN.1 type.
 *
 * @see https://tools.ietf.org/html/rfc2898#appendix-C
 * @see https://tools.ietf.org/html/rfc3447#appendix-C
 */
abstract class AlgorithmIdentifier implements AlgorithmIdentifierType
{
    // RSA encryption
    final public const OID_RSA_ENCRYPTION = '1.2.840.113549.1.1.1';
    // RSA signature algorithms
    final public const OID_MD2_WITH_RSA_ENCRYPTION = '1.2.840.113549.1.1.2';
    final public const OID_MD4_WITH_RSA_ENCRYPTION = '1.2.840.113549.1.1.3';
    final public const OID_MD5_WITH_RSA_ENCRYPTION = '1.2.840.113549.1.1.4';
    final public const OID_SHA1_WITH_RSA_ENCRYPTION = '1.2.840.113549.1.1.5';
    final public const OID_RSASSA_PSS_ENCRYPTION = '1.2.840.113549.1.1.10';
    final public const OID_SHA256_WITH_RSA_ENCRYPTION = '1.2.840.113549.1.1.11';
    final public const OID_SHA384_WITH_RSA_ENCRYPTION = '1.2.840.113549.1.1.12';
    final public const OID_SHA512_WITH_RSA_ENCRYPTION = '1.2.840.113549.1.1.13';
    final public const OID_SHA224_WITH_RSA_ENCRYPTION = '1.2.840.113549.1.1.14';
    // Elliptic Curve signature algorithms
    final public const OID_ECDSA_WITH_SHA1 = '1.2.840.10045.4.1';
    final public const OID_ECDSA_WITH_SHA224 = '1.2.840.10045.4.3.1';
    final public const OID_ECDSA_WITH_SHA256 = '1.2.840.10045.4.3.2';
    final public const OID_ECDSA_WITH_SHA384 = '1.2.840.10045.4.3.3';
    final public const OID_ECDSA_WITH_SHA512 = '1.2.840.10045.4.3.4';
    // Elliptic Curve public key
    final public const OID_EC_PUBLIC_KEY = '1.2.840.10045.2.1';
    // Elliptic curve / algorithm pairs from RFC 8410
    final public const OID_X25519 = '1.3.101.110';
    final public const OID_X448 = '1.3.101.111';
    final public const OID_ED25519 = '1.3.101.112';
    final public const OID_ED448 = '1.3.101.113';
    // Cipher algorithms
    final public const OID_DES_CBC = '1.3.14.3.2.7';
    final public const OID_RC2_CBC = '1.2.840.113549.3.2';
    final public const OID_DES_EDE3_CBC = '1.2.840.113549.3.7';
    final public const OID_AES_128_CBC = '2.16.840.1.101.3.4.1.2';
    final public const OID_AES_192_CBC = '2.16.840.1.101.3.4.1.22';
    final public const OID_AES_256_CBC = '2.16.840.1.101.3.4.1.42';
    // HMAC-SHA-1 from RFC 8018
    final public const OID_HMAC_WITH_SHA1 = '1.2.840.113549.2.7';
    // HMAC algorithms from RFC 4231
    final public const OID_HMAC_WITH_SHA224 = '1.2.840.113549.2.8';
    final public const OID_HMAC_WITH_SHA256 = '1.2.840.113549.2.9';
    final public const OID_HMAC_WITH_SHA384 = '1.2.840.113549.2.10';
    final public const OID_HMAC_WITH_SHA512 = '1.2.840.113549.2.11';
    // Message digest algorithms
    final public const OID_MD5 = '1.2.840.113549.2.5';
    final public const OID_SHA1 = '1.3.14.3.2.26';
    final public const OID_SHA224 = '2.16.840.1.101.3.4.2.4';
    final public const OID_SHA256 = '2.16.840.1.101.3.4.2.1';
    final public const OID_SHA384 = '2.16.840.1.101.3.4.2.2';
    final public const OID_SHA512 = '2.16.840.1.101.3.4.2.3';
    protected function __construct(protected readonly string $oid)
    {
    }
    /**
     * Initialize from ASN.1.
     */
    public static function fromASN1(Sequence $seq): self
    {
        return AlgorithmIdentifierFactory::create()->parse($seq);
    }
    public function oid(): string
    {
        return $this->oid;
    }
    public function toASN1(): Sequence
    {
        $elements = [ObjectIdentifier::create($this->oid)];
        $params = $this->paramsASN1();
        if (isset($params)) {
            $elements[] = $params;
        }
        return Sequence::create(...$elements);
    }
    /**
     * Get algorithm identifier parameters as ASN.1.
     *
     * If type allows parameters to be omitted, return null.
     */
    abstract protected function paramsASN1(): ?Element;
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\CryptoTypes\AlgorithmIdentifier\Signature;

use _ContaoManager\SpomkyLabs\Pki\ASN1\Element;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\UnspecifiedType;
/**
 * RSA with SHA-384 signature algorithm identifier.
 *
 * @see https://tools.ietf.org/html/rfc4055#section-5
 */
final class SHA384WithRSAEncryptionAlgorithmIdentifier extends RFC4055RSASignatureAlgorithmIdentifier
{
    protected function __construct(null|Element $params)
    {
        parent::__construct(self::OID_SHA384_WITH_RSA_ENCRYPTION, $params);
    }
    public static function create(null|Element $params = null): self
    {
        return new self($params);
    }
    public static function fromASN1Params(?UnspecifiedType $params = null): self
    {
        // store parameters so re-encoding doesn't change
        return self::create($params?->asElement());
    }
    public function name(): string
    {
        return 'sha384WithRSAEncryption';
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\CryptoTypes\AlgorithmIdentifier\Signature;

use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\UnspecifiedType;
use UnexpectedValueException;
/**
 * RSA with MD2 signature algorithm identifier.
 *
 * @see https://tools.ietf.org/html/rfc3279#section-2.2.1
 */
final class MD2WithRSAEncryptionAlgorithmIdentifier extends RFC3279RSASignatureAlgorithmIdentifier
{
    private function __construct()
    {
        parent::__construct(self::OID_MD2_WITH_RSA_ENCRYPTION);
    }
    public static function create(): self
    {
        return new self();
    }
    public static function fromASN1Params(?UnspecifiedType $params = null): self
    {
        if (!isset($params)) {
            throw new UnexpectedValueException('No parameters.');
        }
        return self::create();
    }
    public function name(): string
    {
        return 'md2WithRSAEncryption';
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\CryptoTypes\AlgorithmIdentifier\Signature;

use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\UnspecifiedType;
use UnexpectedValueException;
/**
 * ECDSA with SHA-256 signature algorithm identifier.
 *
 * @see https://tools.ietf.org/html/rfc5758#section-3.2
 */
final class ECDSAWithSHA256AlgorithmIdentifier extends ECSignatureAlgorithmIdentifier
{
    private function __construct()
    {
        parent::__construct(self::OID_ECDSA_WITH_SHA256);
    }
    public static function create(): self
    {
        return new self();
    }
    public function name(): string
    {
        return 'ecdsa-with-SHA256';
    }
    public static function fromASN1Params(?UnspecifiedType $params = null): self
    {
        if ($params !== null) {
            throw new UnexpectedValueException('Parameters must be omitted.');
        }
        return self::create();
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\CryptoTypes\AlgorithmIdentifier\Signature;

use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\UnspecifiedType;
use UnexpectedValueException;
/**
 * ECDSA with SHA-224 signature algorithm identifier.
 *
 * @see https://tools.ietf.org/html/rfc5758#section-3.2
 */
final class ECDSAWithSHA224AlgorithmIdentifier extends ECSignatureAlgorithmIdentifier
{
    private function __construct()
    {
        parent::__construct(self::OID_ECDSA_WITH_SHA224);
    }
    public static function create(): self
    {
        return new self();
    }
    public function name(): string
    {
        return 'ecdsa-with-SHA224';
    }
    public static function fromASN1Params(?UnspecifiedType $params = null): self
    {
        if ($params !== null) {
            throw new UnexpectedValueException('Parameters must be omitted.');
        }
        return self::create();
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\CryptoTypes\AlgorithmIdentifier\Signature;

use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\UnspecifiedType;
use UnexpectedValueException;
/**
 * RSA with MD5 signature algorithm identifier.
 *
 * @see https://tools.ietf.org/html/rfc3279#section-2.2.1
 */
final class MD5WithRSAEncryptionAlgorithmIdentifier extends RFC3279RSASignatureAlgorithmIdentifier
{
    private function __construct()
    {
        parent::__construct(self::OID_MD5_WITH_RSA_ENCRYPTION);
    }
    public static function create(): self
    {
        return new self();
    }
    public static function fromASN1Params(?UnspecifiedType $params = null): self
    {
        if (!isset($params)) {
            throw new UnexpectedValueException('No parameters.');
        }
        return self::create();
    }
    public function name(): string
    {
        return 'md5WithRSAEncryption';
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\CryptoTypes\AlgorithmIdentifier\Signature;

use _ContaoManager\SpomkyLabs\Pki\ASN1\Element;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Primitive\NullType;
/*
 * From RFC 3279 - 2.2.1  RSA Signature Algorithm:
 * When any of these three OIDs appears within the ASN.1 type
 * AlgorithmIdentifier, the parameters component of that type SHALL be
 * the ASN.1 type NULL.
 */
/**
 * Base class for RSA signature algorithms specified in RFC 3279.
 *
 * @see https://tools.ietf.org/html/rfc3279#section-2.2.1
 */
abstract class RFC3279RSASignatureAlgorithmIdentifier extends RSASignatureAlgorithmIdentifier
{
    protected function paramsASN1(): ?Element
    {
        return NullType::create();
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\CryptoTypes\AlgorithmIdentifier\Signature;

use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\UnspecifiedType;
use UnexpectedValueException;
/**
 * RSA with MD4 signature algorithm identifier.
 *
 * @see https://tools.ietf.org/html/rfc2313#section-11
 */
final class MD4WithRSAEncryptionAlgorithmIdentifier extends RFC3279RSASignatureAlgorithmIdentifier
{
    private function __construct()
    {
        parent::__construct(self::OID_MD4_WITH_RSA_ENCRYPTION);
    }
    public static function create(): self
    {
        return new self();
    }
    public static function fromASN1Params(?UnspecifiedType $params = null): self
    {
        if (!isset($params)) {
            throw new UnexpectedValueException('No parameters.');
        }
        return self::create();
    }
    public function name(): string
    {
        return 'md4withRSAEncryption';
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\CryptoTypes\AlgorithmIdentifier\Signature;

use _ContaoManager\SpomkyLabs\Pki\ASN1\Element;
/*
 * From RFC 4055 - 5.  PKCS #1 Version 1.5 Signature Algorithm
 * When any of these four object identifiers appears within an
 * AlgorithmIdentifier, the parameters MUST be NULL.  Implementations
 * MUST accept the parameters being absent as well as present.
 */
/**
 * Base class for RSA signature algorithms specified in RFC 4055.
 *
 * @see https://tools.ietf.org/html/rfc4055#section-5
 */
abstract class RFC4055RSASignatureAlgorithmIdentifier extends RSASignatureAlgorithmIdentifier
{
    protected function __construct(string $oid, protected null|Element $params)
    {
        parent::__construct($oid);
    }
    protected function paramsASN1(): ?Element
    {
        return $this->params;
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\CryptoTypes\AlgorithmIdentifier\Signature;

use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\UnspecifiedType;
use UnexpectedValueException;
/**
 * ECDSA with SHA-512 signature algorithm identifier.
 *
 * @see https://tools.ietf.org/html/rfc5758#section-3.2
 */
final class ECDSAWithSHA512AlgorithmIdentifier extends ECSignatureAlgorithmIdentifier
{
    private function __construct()
    {
        parent::__construct(self::OID_ECDSA_WITH_SHA512);
    }
    public static function create(): self
    {
        return new self();
    }
    public static function fromASN1Params(?UnspecifiedType $params = null): self
    {
        if ($params !== null) {
            throw new UnexpectedValueException('Parameters must be omitted.');
        }
        return self::create();
    }
    public function name(): string
    {
        return 'ecdsa-with-SHA512';
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\CryptoTypes\AlgorithmIdentifier\Signature;

use _ContaoManager\SpomkyLabs\Pki\CryptoTypes\AlgorithmIdentifier\AlgorithmIdentifier;
use _ContaoManager\SpomkyLabs\Pki\CryptoTypes\AlgorithmIdentifier\Feature\SignatureAlgorithmIdentifier;
use _ContaoManager\SpomkyLabs\Pki\CryptoTypes\AlgorithmIdentifier\SpecificAlgorithmIdentifier;
/**
 * Base class for signature algorithms employing RSASSA.
 */
abstract class RSASignatureAlgorithmIdentifier extends SpecificAlgorithmIdentifier implements SignatureAlgorithmIdentifier
{
    public function supportsKeyAlgorithm(AlgorithmIdentifier $algo): bool
    {
        return $algo->oid() === self::OID_RSA_ENCRYPTION;
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\CryptoTypes\AlgorithmIdentifier\Signature;

use _ContaoManager\SpomkyLabs\Pki\ASN1\Element;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\UnspecifiedType;
/**
 * RSA with SHA-256 signature algorithm identifier.
 *
 * @see https://tools.ietf.org/html/rfc4055#section-5
 */
final class SHA256WithRSAEncryptionAlgorithmIdentifier extends RFC4055RSASignatureAlgorithmIdentifier
{
    private function __construct(null|Element $params)
    {
        parent::__construct(self::OID_SHA256_WITH_RSA_ENCRYPTION, $params);
    }
    public static function create(null|Element $params = null): self
    {
        return new self($params);
    }
    public static function fromASN1Params(?UnspecifiedType $params = null): self
    {
        // store parameters so re-encoding doesn't change
        return self::create($params?->asElement());
    }
    public function name(): string
    {
        return 'sha256WithRSAEncryption';
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\CryptoTypes\AlgorithmIdentifier\Signature;

use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\UnspecifiedType;
use UnexpectedValueException;
/**
 * ECDSA with SHA-1 signature algorithm identifier.
 *
 * @see https://tools.ietf.org/html/rfc3279#section-2.2.3
 */
final class ECDSAWithSHA1AlgorithmIdentifier extends ECSignatureAlgorithmIdentifier
{
    private function __construct()
    {
        parent::__construct(self::OID_ECDSA_WITH_SHA1);
    }
    public static function create(): self
    {
        return new self();
    }
    public function name(): string
    {
        return 'ecdsa-with-SHA1';
    }
    public static function fromASN1Params(?UnspecifiedType $params = null): self
    {
        if ($params !== null) {
            throw new UnexpectedValueException('Parameters must be omitted.');
        }
        return self::create();
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\CryptoTypes\AlgorithmIdentifier\Signature;

use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\UnspecifiedType;
use UnexpectedValueException;
/**
 * ECDSA with SHA-384 signature algorithm identifier.
 *
 * @see https://tools.ietf.org/html/rfc5758#section-3.2
 */
final class ECDSAWithSHA384AlgorithmIdentifier extends ECSignatureAlgorithmIdentifier
{
    private function __construct()
    {
        parent::__construct(self::OID_ECDSA_WITH_SHA384);
    }
    public static function create(): self
    {
        return new self();
    }
    public function name(): string
    {
        return 'ecdsa-with-SHA384';
    }
    public static function fromASN1Params(?UnspecifiedType $params = null): self
    {
        if ($params !== null) {
            throw new UnexpectedValueException('Parameters must be omitted.');
        }
        return self::create();
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\CryptoTypes\AlgorithmIdentifier\Signature;

use _ContaoManager\SpomkyLabs\Pki\ASN1\Element;
use _ContaoManager\SpomkyLabs\Pki\CryptoTypes\AlgorithmIdentifier\AlgorithmIdentifier;
use _ContaoManager\SpomkyLabs\Pki\CryptoTypes\AlgorithmIdentifier\Feature\SignatureAlgorithmIdentifier;
use _ContaoManager\SpomkyLabs\Pki\CryptoTypes\AlgorithmIdentifier\SpecificAlgorithmIdentifier;
/*
 * From RFC 5758 - 3.2.  ECDSA Signature Algorithm
 * When the ecdsa-with-SHA224, ecdsa-with-SHA256, ecdsa-with-SHA384, or
 * ecdsa-with-SHA512 algorithm identifier appears in the algorithm field
 * as an AlgorithmIdentifier, the encoding MUST omit the parameters
 * field.
 */
/**
 * Base class for ECDSA signature algorithm identifiers.
 *
 * @see https://tools.ietf.org/html/rfc5758#section-3.2
 * @see https://tools.ietf.org/html/rfc5480#appendix-A
 */
abstract class ECSignatureAlgorithmIdentifier extends SpecificAlgorithmIdentifier implements SignatureAlgorithmIdentifier
{
    public function supportsKeyAlgorithm(AlgorithmIdentifier $algo): bool
    {
        return $algo->oid() === self::OID_EC_PUBLIC_KEY;
    }
    protected function paramsASN1(): ?Element
    {
        return null;
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\CryptoTypes\AlgorithmIdentifier\Signature;

use _ContaoManager\SpomkyLabs\Pki\ASN1\Element;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\UnspecifiedType;
/**
 * RSA with SHA-512 signature algorithm identifier.
 *
 * @see https://tools.ietf.org/html/rfc4055#section-5
 */
final class SHA512WithRSAEncryptionAlgorithmIdentifier extends RFC4055RSASignatureAlgorithmIdentifier
{
    private function __construct(null|Element $params)
    {
        parent::__construct(self::OID_SHA512_WITH_RSA_ENCRYPTION, $params);
    }
    public static function create(null|Element $params = null): self
    {
        return new self($params);
    }
    public static function fromASN1Params(?UnspecifiedType $params = null): self
    {
        // store parameters so re-encoding doesn't change
        return self::create($params?->asElement());
    }
    public function name(): string
    {
        return 'sha512WithRSAEncryption';
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\CryptoTypes\AlgorithmIdentifier\Signature;

use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\UnspecifiedType;
use UnexpectedValueException;
/**
 * RSA with SHA-1 signature algorithm identifier.
 *
 * @see https://tools.ietf.org/html/rfc3279#section-2.2.1
 */
final class SHA1WithRSAEncryptionAlgorithmIdentifier extends RFC3279RSASignatureAlgorithmIdentifier
{
    private function __construct()
    {
        parent::__construct(self::OID_SHA1_WITH_RSA_ENCRYPTION);
    }
    public static function create(): self
    {
        return new self();
    }
    public static function fromASN1Params(?UnspecifiedType $params = null): self
    {
        if (!isset($params)) {
            throw new UnexpectedValueException('No parameters.');
        }
        $params->asNull();
        return self::create();
    }
    public function name(): string
    {
        return 'sha1-with-rsa-signature';
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\CryptoTypes\AlgorithmIdentifier\Signature;

use _ContaoManager\SpomkyLabs\Pki\ASN1\Element;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\UnspecifiedType;
/**
 * RSA with SHA-224 signature algorithm identifier.
 *
 * @see https://tools.ietf.org/html/rfc4055#section-5
 */
final class SHA224WithRSAEncryptionAlgorithmIdentifier extends RFC4055RSASignatureAlgorithmIdentifier
{
    private function __construct(null|Element $params)
    {
        parent::__construct(self::OID_SHA224_WITH_RSA_ENCRYPTION, $params);
    }
    public static function create(null|Element $params = null): self
    {
        return new self($params);
    }
    public static function fromASN1Params(?UnspecifiedType $params = null): self
    {
        // store parameters so re-encoding doesn't change
        return self::create($params?->asElement());
    }
    public function name(): string
    {
        return 'sha224WithRSAEncryption';
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\CryptoTypes\AlgorithmIdentifier\Hash;

use _ContaoManager\SpomkyLabs\Pki\ASN1\Element;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\UnspecifiedType;
/**
 * HMAC with SHA-224 algorithm identifier.
 *
 * @see https://tools.ietf.org/html/rfc4231#section-3.1
 */
final class HMACWithSHA224AlgorithmIdentifier extends RFC4231HMACAlgorithmIdentifier
{
    private function __construct(?Element $params)
    {
        parent::__construct(self::OID_HMAC_WITH_SHA224, $params);
    }
    public static function create(?Element $params = null): self
    {
        return new self($params);
    }
    public static function fromASN1Params(?UnspecifiedType $params = null): self
    {
        /*
         * RFC 4231 states that the "parameter" component SHOULD be present
         * but have type NULL.
         */
        return self::create($params?->asNull());
    }
    public function name(): string
    {
        return 'hmacWithSHA224';
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\CryptoTypes\AlgorithmIdentifier\Hash;

use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\UnspecifiedType;
use _ContaoManager\SpomkyLabs\Pki\CryptoTypes\AlgorithmIdentifier\SpecificAlgorithmIdentifier;
/**
 * SHA-224 algorithm identifier.
 *
 * @see http://oid-info.com/get/2.16.840.1.101.3.4.2.4
 * @see https://tools.ietf.org/html/rfc3874#section-4
 * @see https://tools.ietf.org/html/rfc4055#section-2.1
 * @see https://tools.ietf.org/html/rfc5754#section-2.1
 */
final class SHA224AlgorithmIdentifier extends SHA2AlgorithmIdentifier
{
    private function __construct()
    {
        parent::__construct(self::OID_SHA224);
    }
    public static function create(): self
    {
        return new self();
    }
    /**
     * @return self
     */
    public static function fromASN1Params(?UnspecifiedType $params = null): SpecificAlgorithmIdentifier
    {
        $obj = new static();
        // if parameters field is present, it must be null type
        if (isset($params)) {
            $obj->_params = $params->asNull();
        }
        return $obj;
    }
    public function name(): string
    {
        return 'sha224';
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\CryptoTypes\AlgorithmIdentifier\Hash;

use _ContaoManager\SpomkyLabs\Pki\ASN1\Element;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\UnspecifiedType;
/**
 * HMAC with SHA-256 algorithm identifier.
 *
 * @see https://tools.ietf.org/html/rfc4231#section-3.1
 */
final class HMACWithSHA256AlgorithmIdentifier extends RFC4231HMACAlgorithmIdentifier
{
    private function __construct(?Element $params)
    {
        parent::__construct(self::OID_HMAC_WITH_SHA256, $params);
    }
    public static function create(?Element $params = null): self
    {
        return new self($params);
    }
    public static function fromASN1Params(?UnspecifiedType $params = null): self
    {
        /*
         * RFC 4231 states that the "parameter" component SHOULD be present
         * but have type NULL.
         */
        return self::create($params?->asNull());
    }
    public function name(): string
    {
        return 'hmacWithSHA256';
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\CryptoTypes\AlgorithmIdentifier\Hash;

use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\UnspecifiedType;
use _ContaoManager\SpomkyLabs\Pki\CryptoTypes\AlgorithmIdentifier\SpecificAlgorithmIdentifier;
/**
 * SHA-256 algorithm identifier.
 *
 * @see http://oid-info.com/get/2.16.840.1.101.3.4.2.1
 * @see https://tools.ietf.org/html/rfc4055#section-2.1
 * @see https://tools.ietf.org/html/rfc5754#section-2.2
 */
final class SHA256AlgorithmIdentifier extends SHA2AlgorithmIdentifier
{
    private function __construct()
    {
        parent::__construct(self::OID_SHA256);
    }
    public static function create(): self
    {
        return new self();
    }
    /**
     * @return self
     */
    public static function fromASN1Params(?UnspecifiedType $params = null): SpecificAlgorithmIdentifier
    {
        $obj = new static();
        // if parameters field is present, it must be null type
        if (isset($params)) {
            $obj->_params = $params->asNull();
        }
        return $obj;
    }
    public function name(): string
    {
        return 'sha256';
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\CryptoTypes\AlgorithmIdentifier\Hash;

use _ContaoManager\SpomkyLabs\Pki\ASN1\Element;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Primitive\NullType;
use _ContaoManager\SpomkyLabs\Pki\CryptoTypes\AlgorithmIdentifier\Feature\HashAlgorithmIdentifier;
use _ContaoManager\SpomkyLabs\Pki\CryptoTypes\AlgorithmIdentifier\Feature\PRFAlgorithmIdentifier;
use _ContaoManager\SpomkyLabs\Pki\CryptoTypes\AlgorithmIdentifier\SpecificAlgorithmIdentifier;
/**
 * Base class for HMAC algorithm identifiers specified in RFC 4231.
 *
 * @see https://tools.ietf.org/html/rfc4231#section-3.1
 */
abstract class RFC4231HMACAlgorithmIdentifier extends SpecificAlgorithmIdentifier implements HashAlgorithmIdentifier, PRFAlgorithmIdentifier
{
    /**
     * @param Element|null $params Parameters stored for re-encoding.
     */
    protected function __construct(string $oid, protected ?Element $params)
    {
        parent::__construct($oid);
    }
    /**
     * @return null|NullType
     */
    protected function paramsASN1(): ?Element
    {
        return $this->params;
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\CryptoTypes\AlgorithmIdentifier\Hash;

use _ContaoManager\SpomkyLabs\Pki\ASN1\Element;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\UnspecifiedType;
/**
 * HMAC with SHA-512 algorithm identifier.
 *
 * @see https://tools.ietf.org/html/rfc4231#section-3.1
 */
final class HMACWithSHA512AlgorithmIdentifier extends RFC4231HMACAlgorithmIdentifier
{
    private function __construct(?Element $params)
    {
        parent::__construct(self::OID_HMAC_WITH_SHA512, $params);
    }
    public static function create(?Element $params = null): self
    {
        return new self($params);
    }
    public static function fromASN1Params(?UnspecifiedType $params = null): self
    {
        /*
         * RFC 4231 states that the "parameter" component SHOULD be present
         * but have type NULL.
         */
        return self::create($params?->asNull());
    }
    public function name(): string
    {
        return 'hmacWithSHA512';
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\CryptoTypes\AlgorithmIdentifier\Hash;

use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\UnspecifiedType;
use _ContaoManager\SpomkyLabs\Pki\CryptoTypes\AlgorithmIdentifier\SpecificAlgorithmIdentifier;
/**
 * SHA-512 algorithm identifier.
 *
 * @see http://oid-info.com/get/2.16.840.1.101.3.4.2.3
 * @see https://tools.ietf.org/html/rfc4055#section-2.1
 * @see https://tools.ietf.org/html/rfc5754#section-2.4
 */
final class SHA512AlgorithmIdentifier extends SHA2AlgorithmIdentifier
{
    private function __construct()
    {
        parent::__construct(self::OID_SHA512);
    }
    public static function create(): self
    {
        return new self();
    }
    /**
     * @return self
     */
    public static function fromASN1Params(?UnspecifiedType $params = null): SpecificAlgorithmIdentifier
    {
        $obj = new static();
        // if parameters field is present, it must be null type
        if (isset($params)) {
            $obj->_params = $params->asNull();
        }
        return $obj;
    }
    public function name(): string
    {
        return 'sha512';
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\CryptoTypes\AlgorithmIdentifier\Hash;

use _ContaoManager\SpomkyLabs\Pki\ASN1\Element;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\UnspecifiedType;
use _ContaoManager\SpomkyLabs\Pki\CryptoTypes\AlgorithmIdentifier\Feature\HashAlgorithmIdentifier;
use _ContaoManager\SpomkyLabs\Pki\CryptoTypes\AlgorithmIdentifier\Feature\PRFAlgorithmIdentifier;
use _ContaoManager\SpomkyLabs\Pki\CryptoTypes\AlgorithmIdentifier\SpecificAlgorithmIdentifier;
use UnexpectedValueException;
/*
 * Per RFC 2898 this algorithm identifier has no parameters:
 * algid-hmacWithSHA1 AlgorithmIdentifier {{PBKDF2-PRFs}} ::=
 * {algorithm id-hmacWithSHA1, parameters NULL : NULL}
 */
/**
 * HMAC-SHA-1 algorithm identifier.
 *
 * @see http://www.alvestrand.no/objectid/1.2.840.113549.2.7.html
 * @see http://www.oid-info.com/get/1.2.840.113549.2.7
 * @see https://tools.ietf.org/html/rfc2898#appendix-C
 */
final class HMACWithSHA1AlgorithmIdentifier extends SpecificAlgorithmIdentifier implements HashAlgorithmIdentifier, PRFAlgorithmIdentifier
{
    private function __construct()
    {
        parent::__construct(self::OID_HMAC_WITH_SHA1);
    }
    public static function create(): self
    {
        return new self();
    }
    public function name(): string
    {
        return 'hmacWithSHA1';
    }
    /**
     * @return self
     */
    public static function fromASN1Params(?UnspecifiedType $params = null): SpecificAlgorithmIdentifier
    {
        if (isset($params)) {
            throw new UnexpectedValueException('Parameters must be omitted.');
        }
        return self::create();
    }
    protected function paramsASN1(): ?Element
    {
        return null;
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\CryptoTypes\AlgorithmIdentifier\Hash;

use _ContaoManager\SpomkyLabs\Pki\ASN1\Element;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Primitive\NullType;
use _ContaoManager\SpomkyLabs\Pki\CryptoTypes\AlgorithmIdentifier\Feature\HashAlgorithmIdentifier;
use _ContaoManager\SpomkyLabs\Pki\CryptoTypes\AlgorithmIdentifier\SpecificAlgorithmIdentifier;
/*
 * From RFC 5754 - 2. Message Digest Algorithms
 * The AlgorithmIdentifier parameters field is OPTIONAL.
 * Implementations MUST accept SHA2 AlgorithmIdentifiers with absent
 * parameters.  Implementations MUST accept SHA2 AlgorithmIdentifiers
 * with NULL parameters.  Implementations MUST generate SHA2
 * AlgorithmIdentifiers with absent parameters.
 */
/**
 * Base class for SHA2 algorithm identifiers.
 *
 * @see https://tools.ietf.org/html/rfc4055#section-2.1
 * @see https://tools.ietf.org/html/rfc5754#section-2
 */
abstract class SHA2AlgorithmIdentifier extends SpecificAlgorithmIdentifier implements HashAlgorithmIdentifier
{
    protected ?NullType $_params = null;
    /**
     * @return null|NullType
     */
    protected function paramsASN1(): ?Element
    {
        return $this->_params;
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\CryptoTypes\AlgorithmIdentifier\Hash;

use _ContaoManager\SpomkyLabs\Pki\ASN1\Element;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Primitive\NullType;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\UnspecifiedType;
use _ContaoManager\SpomkyLabs\Pki\CryptoTypes\AlgorithmIdentifier\Feature\HashAlgorithmIdentifier;
use _ContaoManager\SpomkyLabs\Pki\CryptoTypes\AlgorithmIdentifier\SpecificAlgorithmIdentifier;
/*
 * From RFC 1321 - 1. Executive Summary
 * In the X.509 type AlgorithmIdentifier, the parameters for MD5
 * should have type NULL.
 * From RFC 3370 - 2.2 MD5
 * The AlgorithmIdentifier parameters field MUST be present, and the
 * parameters field MUST contain NULL.  Implementations MAY accept the
 * MD5 AlgorithmIdentifiers with absent parameters as well as NULL
 * parameters.
 */
/**
 * MD5 algorithm identifier.
 *
 * @see http://oid-info.com/get/1.2.840.113549.2.5
 * @see https://tools.ietf.org/html/rfc1321#section-1
 * @see https://tools.ietf.org/html/rfc3370#section-2.2
 */
final class MD5AlgorithmIdentifier extends SpecificAlgorithmIdentifier implements HashAlgorithmIdentifier
{
    /**
     * Parameters.
     */
    private ?NullType $params;
    private function __construct()
    {
        parent::__construct(self::OID_MD5);
        $this->params = NullType::create();
    }
    public static function create(): self
    {
        return new self();
    }
    public function name(): string
    {
        return 'md5';
    }
    public static function fromASN1Params(?UnspecifiedType $params = null): static
    {
        $obj = static::create();
        // if parameters field is present, it must be null type
        if (isset($params)) {
            $obj->params = $params->asNull();
        }
        return $obj;
    }
    /**
     * @return null|NullType
     */
    protected function paramsASN1(): ?Element
    {
        return $this->params;
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\CryptoTypes\AlgorithmIdentifier\Hash;

use _ContaoManager\SpomkyLabs\Pki\ASN1\Element;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Primitive\NullType;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\UnspecifiedType;
use _ContaoManager\SpomkyLabs\Pki\CryptoTypes\AlgorithmIdentifier\Feature\HashAlgorithmIdentifier;
use _ContaoManager\SpomkyLabs\Pki\CryptoTypes\AlgorithmIdentifier\SpecificAlgorithmIdentifier;
/*
 * From RFC 3370 - 2.1 SHA-1
 * The AlgorithmIdentifier parameters field is OPTIONAL.  If present,
 * the parameters field MUST contain a NULL.  Implementations MUST
 * accept SHA-1 AlgorithmIdentifiers with absent parameters.
 * Implementations MUST accept SHA-1 AlgorithmIdentifiers with NULL
 * parameters.  Implementations SHOULD generate SHA-1
 * AlgorithmIdentifiers with absent parameters.
 */
/**
 * SHA-1 algorithm identifier.
 *
 * @see http://oid-info.com/get/1.3.14.3.2.26
 * @see https://tools.ietf.org/html/rfc3370#section-2.1
 */
final class SHA1AlgorithmIdentifier extends SpecificAlgorithmIdentifier implements HashAlgorithmIdentifier
{
    /**
     * Parameters.
     */
    private ?NullType $params;
    private function __construct()
    {
        parent::__construct(self::OID_SHA1);
        $this->params = null;
    }
    public static function create(): self
    {
        return new self();
    }
    public function name(): string
    {
        return 'sha1';
    }
    public static function fromASN1Params(?UnspecifiedType $params = null): static
    {
        $obj = static::create();
        // if parameters field is present, it must be null type
        if (isset($params)) {
            $obj->params = $params->asNull();
        }
        return $obj;
    }
    /**
     * @return null|NullType
     */
    protected function paramsASN1(): ?Element
    {
        return $this->params;
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\CryptoTypes\AlgorithmIdentifier\Hash;

use _ContaoManager\SpomkyLabs\Pki\ASN1\Element;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\UnspecifiedType;
/**
 * HMAC with SHA-384 algorithm identifier.
 *
 * @see https://tools.ietf.org/html/rfc4231#section-3.1
 */
final class HMACWithSHA384AlgorithmIdentifier extends RFC4231HMACAlgorithmIdentifier
{
    private function __construct(?Element $params)
    {
        parent::__construct(self::OID_HMAC_WITH_SHA384, $params);
    }
    public static function create(?Element $params = null): self
    {
        return new self($params);
    }
    public static function fromASN1Params(?UnspecifiedType $params = null): self
    {
        /*
         * RFC 4231 states that the "parameter" component SHOULD be present
         * but have type NULL.
         */
        return new self($params?->asNull());
    }
    public function name(): string
    {
        return 'hmacWithSHA384';
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\CryptoTypes\AlgorithmIdentifier\Hash;

use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\UnspecifiedType;
use _ContaoManager\SpomkyLabs\Pki\CryptoTypes\AlgorithmIdentifier\SpecificAlgorithmIdentifier;
/**
 * SHA-384 algorithm identifier.
 *
 * @see http://oid-info.com/get/2.16.840.1.101.3.4.2.2
 * @see https://tools.ietf.org/html/rfc4055#section-2.1
 * @see https://tools.ietf.org/html/rfc5754#section-2.3
 */
final class SHA384AlgorithmIdentifier extends SHA2AlgorithmIdentifier
{
    private function __construct()
    {
        parent::__construct(self::OID_SHA384);
    }
    public static function create(): self
    {
        return new self();
    }
    /**
     * @return self
     */
    public static function fromASN1Params(?UnspecifiedType $params = null): SpecificAlgorithmIdentifier
    {
        $obj = new static();
        // if parameters field is present, it must be null type
        if (isset($params)) {
            $obj->_params = $params->asNull();
        }
        return $obj;
    }
    public function name(): string
    {
        return 'sha384';
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\CryptoTypes\AlgorithmIdentifier\Cipher;

use LogicException;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Element;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Constructed\Sequence;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Primitive\Integer;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Primitive\OctetString;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\UnspecifiedType;
use _ContaoManager\SpomkyLabs\Pki\CryptoTypes\AlgorithmIdentifier\SpecificAlgorithmIdentifier;
use UnexpectedValueException;
/*
 * Parameters may be seen in various forms. This implementation attemts
 * to take them all into consideration.
 * # RFC 2268 - A Description of the RC2(r) Encryption Algorithm
 * RC2-CBCParameter ::= CHOICE {
 * iv IV,
 * params SEQUENCE {
 * version RC2Version,
 * iv IV
 * }
 * }
 * # RFC 2898 - PKCS #5: Password-Based Cryptography Specification Version 2.0
 * RC2-CBC-Parameter ::= SEQUENCE {
 * rc2ParameterVersion INTEGER OPTIONAL,
 * iv OCTET STRING (SIZE(8))
 * }
 * # RFC 3370 - Cryptographic Message Syntax (CMS) Algorithms
 * RC2CBCParameter ::= SEQUENCE {
 * rc2ParameterVersion INTEGER,
 * iv OCTET STRING  }  -- exactly 8 octets
 */
/**
 * Algorithm identifier for RC2 cipher in CBC mode.
 *
 * @see http://www.alvestrand.no/objectid/1.2.840.113549.3.2.html
 * @see http://www.oid-info.com/get/1.2.840.113549.3.2
 * @see https://tools.ietf.org/html/rfc2268#section-6
 * @see https://tools.ietf.org/html/rfc3370#section-5.2
 * @see https://tools.ietf.org/html/rfc2898#appendix-C
 */
final class RC2CBCAlgorithmIdentifier extends BlockCipherAlgorithmIdentifier
{
    /**
     * RFC 2268 translation table for effective key bits.
     *
     * This table maps effective key bytes from 0..255 to version number.
     *
     * @var array<int> ekb => version
     */
    private const EKB_TABLE = [0xbd, 0x56, 0xea, 0xf2, 0xa2, 0xf1, 0xac, 0x2a, 0xb0, 0x93, 0xd1, 0x9c, 0x1b, 0x33, 0xfd, 0xd0, 0x30, 0x4, 0xb6, 0xdc, 0x7d, 0xdf, 0x32, 0x4b, 0xf7, 0xcb, 0x45, 0x9b, 0x31, 0xbb, 0x21, 0x5a, 0x41, 0x9f, 0xe1, 0xd9, 0x4a, 0x4d, 0x9e, 0xda, 0xa0, 0x68, 0x2c, 0xc3, 0x27, 0x5f, 0x80, 0x36, 0x3e, 0xee, 0xfb, 0x95, 0x1a, 0xfe, 0xce, 0xa8, 0x34, 0xa9, 0x13, 0xf0, 0xa6, 0x3f, 0xd8, 0xc, 0x78, 0x24, 0xaf, 0x23, 0x52, 0xc1, 0x67, 0x17, 0xf5, 0x66, 0x90, 0xe7, 0xe8, 0x7, 0xb8, 0x60, 0x48, 0xe6, 0x1e, 0x53, 0xf3, 0x92, 0xa4, 0x72, 0x8c, 0x8, 0x15, 0x6e, 0x86, 0x0, 0x84, 0xfa, 0xf4, 0x7f, 0x8a, 0x42, 0x19, 0xf6, 0xdb, 0xcd, 0x14, 0x8d, 0x50, 0x12, 0xba, 0x3c, 0x6, 0x4e, 0xec, 0xb3, 0x35, 0x11, 0xa1, 0x88, 0x8e, 0x2b, 0x94, 0x99, 0xb7, 0x71, 0x74, 0xd3, 0xe4, 0xbf, 0x3a, 0xde, 0x96, 0xe, 0xbc, 0xa, 0xed, 0x77, 0xfc, 0x37, 0x6b, 0x3, 0x79, 0x89, 0x62, 0xc6, 0xd7, 0xc0, 0xd2, 0x7c, 0x6a, 0x8b, 0x22, 0xa3, 0x5b, 0x5, 0x5d, 0x2, 0x75, 0xd5, 0x61, 0xe3, 0x18, 0x8f, 0x55, 0x51, 0xad, 0x1f, 0xb, 0x5e, 0x85, 0xe5, 0xc2, 0x57, 0x63, 0xca, 0x3d, 0x6c, 0xb4, 0xc5, 0xcc, 0x70, 0xb2, 0x91, 0x59, 0xd, 0x47, 0x20, 0xc8, 0x4f, 0x58, 0xe0, 0x1, 0xe2, 0x16, 0x38, 0xc4, 0x6f, 0x3b, 0xf, 0x65, 0x46, 0xbe, 0x7e, 0x2d, 0x7b, 0x82, 0xf9, 0x40, 0xb5, 0x1d, 0x73, 0xf8, 0xeb, 0x26, 0xc7, 0x87, 0x97, 0x25, 0x54, 0xb1, 0x28, 0xaa, 0x98, 0x9d, 0xa5, 0x64, 0x6d, 0x7a, 0xd4, 0x10, 0x81, 0x44, 0xef, 0x49, 0xd6, 0xae, 0x2e, 0xdd, 0x76, 0x5c, 0x2f, 0xa7, 0x1c, 0xc9, 0x9, 0x69, 0x9a, 0x83, 0xcf, 0x29, 0x39, 0xb9, 0xe9, 0x4c, 0xff, 0x43, 0xab];
    /**
     * @param int $effectiveKeyBits Number of effective key bits
     * @param null|string $iv Initialization vector
     */
    private function __construct(private readonly int $effectiveKeyBits, ?string $iv)
    {
        parent::__construct(self::OID_RC2_CBC, $iv);
        $this->_checkIVSize($iv);
    }
    public static function create(int $_effectiveKeyBits = 64, ?string $iv = null): self
    {
        return new self($_effectiveKeyBits, $iv);
    }
    public function name(): string
    {
        return 'rc2-cbc';
    }
    /**
     * @return self
     */
    public static function fromASN1Params(?UnspecifiedType $params = null): SpecificAlgorithmIdentifier
    {
        if (!isset($params)) {
            throw new UnexpectedValueException('No parameters.');
        }
        $key_bits = 32;
        // rfc2268 a choice containing only IV
        if ($params->isType(Element::TYPE_OCTET_STRING)) {
            $iv = $params->asOctetString()->string();
        } else {
            $seq = $params->asSequence();
            $idx = 0;
            // version is optional in rfc2898
            if ($seq->has($idx, Element::TYPE_INTEGER)) {
                $version = $seq->at($idx++)->asInteger()->intNumber();
                $key_bits = self::_versionToEKB($version);
            }
            // IV is present in all variants
            $iv = $seq->at($idx)->asOctetString()->string();
        }
        return self::create($key_bits, $iv);
    }
    /**
     * Get number of effective key bits.
     */
    public function effectiveKeyBits(): int
    {
        return $this->effectiveKeyBits;
    }
    public function blockSize(): int
    {
        return 8;
    }
    public function keySize(): int
    {
        return (int) round($this->effectiveKeyBits / 8);
    }
    public function ivSize(): int
    {
        return 8;
    }
    /**
     * @return Sequence
     */
    protected function paramsASN1(): Element
    {
        if ($this->effectiveKeyBits >= 256) {
            $version = $this->effectiveKeyBits;
        } else {
            $version = self::EKB_TABLE[$this->effectiveKeyBits];
        }
        if (!isset($this->initializationVector)) {
            throw new LogicException('IV not set.');
        }
        return Sequence::create(Integer::create($version), OctetString::create($this->initializationVector));
    }
    /**
     * Translate version number to number of effective key bits.
     */
    private static function _versionToEKB(int $version): int
    {
        static $lut;
        if ($version > 255) {
            return $version;
        }
        if (!isset($lut)) {
            $lut = array_flip(self::EKB_TABLE);
        }
        return $lut[$version];
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\CryptoTypes\AlgorithmIdentifier\Cipher;

use LogicException;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Element;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Primitive\OctetString;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\UnspecifiedType;
use _ContaoManager\SpomkyLabs\Pki\CryptoTypes\AlgorithmIdentifier\SpecificAlgorithmIdentifier;
use UnexpectedValueException;
/*
 * RFC 2898 defines parameters as follows:
 * {OCTET STRING (SIZE(8)) IDENTIFIED BY des-EDE3-CBC}
 */
/**
 * Algorithm identifier for Triple-DES cipher in CBC mode.
 *
 * @see http://www.alvestrand.no/objectid/1.2.840.113549.3.7.html
 * @see http://oid-info.com/get/1.2.840.113549.3.7
 * @see https://tools.ietf.org/html/rfc2898#appendix-C
 * @see https://tools.ietf.org/html/rfc2630#section-12.4.1
 */
final class DESEDE3CBCAlgorithmIdentifier extends BlockCipherAlgorithmIdentifier
{
    /**
     * @param null|string $iv Initialization vector
     */
    private function __construct(?string $iv)
    {
        parent::__construct(self::OID_DES_EDE3_CBC, $iv);
        $this->_checkIVSize($iv);
    }
    public static function create(?string $iv = null): self
    {
        return new self($iv);
    }
    public function name(): string
    {
        return 'des-EDE3-CBC';
    }
    /**
     * @return self
     */
    public static function fromASN1Params(?UnspecifiedType $params = null): SpecificAlgorithmIdentifier
    {
        if (!isset($params)) {
            throw new UnexpectedValueException('No parameters.');
        }
        $iv = $params->asOctetString()->string();
        return self::create($iv);
    }
    public function blockSize(): int
    {
        return 8;
    }
    public function keySize(): int
    {
        return 24;
    }
    public function ivSize(): int
    {
        return 8;
    }
    /**
     * @return OctetString
     */
    protected function paramsASN1(): Element
    {
        if (!isset($this->initializationVector)) {
            throw new LogicException('IV not set.');
        }
        return OctetString::create($this->initializationVector);
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\CryptoTypes\AlgorithmIdentifier\Cipher;

use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\UnspecifiedType;
use _ContaoManager\SpomkyLabs\Pki\CryptoTypes\AlgorithmIdentifier\SpecificAlgorithmIdentifier;
use UnexpectedValueException;
/**
 * Algorithm identifier for AES with 192-bit key in CBC mode.
 *
 * @see https://tools.ietf.org/html/rfc3565.html#section-4.1
 * @see http://www.alvestrand.no/objectid/2.16.840.1.101.3.4.1.22.html
 * @see http://www.oid-info.com/get/2.16.840.1.101.3.4.1.22
 */
final class AES192CBCAlgorithmIdentifier extends AESCBCAlgorithmIdentifier
{
    /**
     * @param null|string $iv Initialization vector
     */
    protected function __construct(?string $iv = null)
    {
        parent::__construct(self::OID_AES_192_CBC, $iv);
    }
    public static function create(?string $iv = null): self
    {
        return new self($iv);
    }
    /**
     * @return self
     */
    public static function fromASN1Params(?UnspecifiedType $params = null): SpecificAlgorithmIdentifier
    {
        if (!isset($params)) {
            throw new UnexpectedValueException('No parameters.');
        }
        $iv = $params->asOctetString()->string();
        return self::create($iv);
    }
    public function name(): string
    {
        return 'aes192-CBC';
    }
    public function keySize(): int
    {
        return 24;
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\CryptoTypes\AlgorithmIdentifier\Cipher;

use LogicException;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Primitive\OctetString;
/*
 * From RFC 3565 - 4.1. AES Algorithm Identifiers and Parameters:
 * The AlgorithmIdentifier parameters field MUST be present, and the parameter field MUST contain a AES-IV:
 * AES-IV ::= OCTET STRING (SIZE(16))
 */
/**
 * Base class for AES-CBC algorithm identifiers.
 *
 * @see https://tools.ietf.org/html/rfc3565.html#section-4.1
 */
abstract class AESCBCAlgorithmIdentifier extends BlockCipherAlgorithmIdentifier
{
    public function blockSize(): int
    {
        return 16;
    }
    public function ivSize(): int
    {
        return 16;
    }
    protected function paramsASN1(): OctetString
    {
        if (!isset($this->initializationVector)) {
            throw new LogicException('IV not set.');
        }
        return OctetString::create($this->initializationVector);
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\CryptoTypes\AlgorithmIdentifier\Cipher;

use function mb_strlen;
use _ContaoManager\SpomkyLabs\Pki\CryptoTypes\AlgorithmIdentifier\SpecificAlgorithmIdentifier;
use UnexpectedValueException;
/**
 * Base class for cipher algorithm identifiers.
 */
abstract class CipherAlgorithmIdentifier extends SpecificAlgorithmIdentifier
{
    protected function __construct(string $oid, protected string $initializationVector)
    {
        $this->_checkIVSize($initializationVector);
        parent::__construct($oid);
    }
    /**
     * Get key size in bytes.
     */
    abstract public function keySize(): int;
    /**
     * Get the initialization vector size in bytes.
     */
    abstract public function ivSize(): int;
    /**
     * Get initialization vector.
     */
    public function initializationVector(): string
    {
        return $this->initializationVector;
    }
    /**
     * Get copy of the object with given initialization vector.
     *
     * @param string $iv Initialization vector or null to remove
     */
    public function withInitializationVector(string $iv): self
    {
        $this->_checkIVSize($iv);
        $obj = clone $this;
        $obj->initializationVector = $iv;
        return $obj;
    }
    /**
     * Check that initialization vector size is valid for the cipher.
     */
    protected function _checkIVSize(string $iv): void
    {
        if (mb_strlen($iv, '8bit') !== $this->ivSize()) {
            throw new UnexpectedValueException('Invalid IV size.');
        }
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\CryptoTypes\AlgorithmIdentifier\Cipher;

use LogicException;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Element;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Primitive\OctetString;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\UnspecifiedType;
use _ContaoManager\SpomkyLabs\Pki\CryptoTypes\AlgorithmIdentifier\SpecificAlgorithmIdentifier;
use UnexpectedValueException;
/*
 * RFC 2898 defines parameters as follows:
 * {OCTET STRING (SIZE(8)) IDENTIFIED BY desCBC}
 */
/**
 * Algorithm identifier for DES cipher in CBC mode.
 *
 * @see http://www.alvestrand.no/objectid/1.3.14.3.2.7.html
 * @see http://www.oid-info.com/get/1.3.14.3.2.7
 * @see https://tools.ietf.org/html/rfc2898#appendix-C
 */
final class DESCBCAlgorithmIdentifier extends BlockCipherAlgorithmIdentifier
{
    /**
     * @param null|string $iv Initialization vector
     */
    private function __construct(?string $iv)
    {
        $this->_checkIVSize($iv);
        parent::__construct(self::OID_DES_CBC, $iv);
    }
    public static function create(?string $iv = null): self
    {
        return new self($iv);
    }
    public function name(): string
    {
        return 'desCBC';
    }
    /**
     * @return self
     */
    public static function fromASN1Params(?UnspecifiedType $params = null): SpecificAlgorithmIdentifier
    {
        if (!isset($params)) {
            throw new UnexpectedValueException('No parameters.');
        }
        $iv = $params->asOctetString()->string();
        return self::create($iv);
    }
    public function blockSize(): int
    {
        return 8;
    }
    public function keySize(): int
    {
        return 8;
    }
    public function ivSize(): int
    {
        return 8;
    }
    /**
     * @return OctetString
     */
    protected function paramsASN1(): Element
    {
        if (!isset($this->initializationVector)) {
            throw new LogicException('IV not set.');
        }
        return OctetString::create($this->initializationVector);
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\CryptoTypes\AlgorithmIdentifier\Cipher;

/**
 * Base class for block cipher algorithm identifiers.
 */
abstract class BlockCipherAlgorithmIdentifier extends CipherAlgorithmIdentifier
{
    /**
     * Get block size in bytes.
     */
    abstract public function blockSize(): int;
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\CryptoTypes\AlgorithmIdentifier\Cipher;

use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\UnspecifiedType;
use _ContaoManager\SpomkyLabs\Pki\CryptoTypes\AlgorithmIdentifier\SpecificAlgorithmIdentifier;
use UnexpectedValueException;
/**
 * Algorithm identifier for AES with 128-bit key in CBC mode.
 *
 * @see https://tools.ietf.org/html/rfc3565.html#section-4.1
 * @see http://www.alvestrand.no/objectid/2.16.840.1.101.3.4.1.2.html
 * @see http://www.oid-info.com/get/2.16.840.1.101.3.4.1.2
 */
final class AES128CBCAlgorithmIdentifier extends AESCBCAlgorithmIdentifier
{
    /**
     * @param string $iv Initialization vector
     */
    protected function __construct(string $iv)
    {
        parent::__construct(self::OID_AES_128_CBC, $iv);
    }
    public static function create(string $iv): self
    {
        return new self($iv);
    }
    /**
     * @return self
     */
    public static function fromASN1Params(?UnspecifiedType $params = null): SpecificAlgorithmIdentifier
    {
        if (!isset($params)) {
            throw new UnexpectedValueException('No parameters.');
        }
        $iv = $params->asOctetString()->string();
        return self::create($iv);
    }
    public function name(): string
    {
        return 'aes128-CBC';
    }
    public function keySize(): int
    {
        return 16;
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\CryptoTypes\AlgorithmIdentifier\Cipher;

use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\UnspecifiedType;
use _ContaoManager\SpomkyLabs\Pki\CryptoTypes\AlgorithmIdentifier\SpecificAlgorithmIdentifier;
use UnexpectedValueException;
/**
 * Algorithm identifier for AES with 256-bit key in CBC mode.
 *
 * @see https://tools.ietf.org/html/rfc3565.html#section-4.1
 * @see http://www.alvestrand.no/objectid/2.16.840.1.101.3.4.1.42.html
 * @see http://www.oid-info.com/get/2.16.840.1.101.3.4.1.42
 */
final class AES256CBCAlgorithmIdentifier extends AESCBCAlgorithmIdentifier
{
    /**
     * @param null|string $iv Initialization vector
     */
    protected function __construct(?string $iv = null)
    {
        parent::__construct(self::OID_AES_256_CBC, $iv);
    }
    public static function create(?string $iv = null): self
    {
        return new self($iv);
    }
    /**
     * @return self
     */
    public static function fromASN1Params(?UnspecifiedType $params = null): SpecificAlgorithmIdentifier
    {
        if (!isset($params)) {
            throw new UnexpectedValueException('No parameters.');
        }
        $iv = $params->asOctetString()->string();
        return new static($iv);
    }
    public function name(): string
    {
        return 'aes256-CBC';
    }
    public function keySize(): int
    {
        return 32;
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\CryptoTypes\AlgorithmIdentifier\Asymmetric;

use _ContaoManager\SpomkyLabs\Pki\ASN1\Element;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Primitive\ObjectIdentifier;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\UnspecifiedType;
use _ContaoManager\SpomkyLabs\Pki\CryptoTypes\AlgorithmIdentifier\Feature\AsymmetricCryptoAlgorithmIdentifier;
use _ContaoManager\SpomkyLabs\Pki\CryptoTypes\AlgorithmIdentifier\SpecificAlgorithmIdentifier;
use UnexpectedValueException;
/*
 * From RFC 5480 - 2.1.1.  Unrestricted Algorithm Identifier and Parameters:
 * The parameter for id-ecPublicKey is as follows and MUST always be
 * present:
 * ECParameters ::= CHOICE {
 * namedCurve         OBJECT IDENTIFIER
 * -- implicitCurve   NULL
 * -- specifiedCurve  SpecifiedECDomain
 * }
 */
/**
 * Algorithm identifier for the elliptic curve public key.
 *
 * @see https://tools.ietf.org/html/rfc5480#section-2.1.1
 */
final class ECPublicKeyAlgorithmIdentifier extends SpecificAlgorithmIdentifier implements AsymmetricCryptoAlgorithmIdentifier
{
    /**
     * prime192v1/secp192r1 curve OID.
     *
     * @see http://oid-info.com/get/1.2.840.10045.3.1.1
     *
     * @var string
     */
    final public const CURVE_PRIME192V1 = '1.2.840.10045.3.1.1';
    /**
     * prime192v2 curve OID.
     *
     * @see http://oid-info.com/get/1.2.840.10045.3.1.2
     *
     * @var string
     */
    final public const CURVE_PRIME192V2 = '1.2.840.10045.3.1.2';
    /**
     * prime192v3 curve OID.
     *
     * @see http://oid-info.com/get/1.2.840.10045.3.1.3
     *
     * @var string
     */
    final public const CURVE_PRIME192V3 = '1.2.840.10045.3.1.3';
    /**
     * prime239v1 curve OID.
     *
     * @see http://oid-info.com/get/1.2.840.10045.3.1.4
     *
     * @var string
     */
    final public const CURVE_PRIME239V1 = '1.2.840.10045.3.1.4';
    /**
     * prime239v2 curve OID.
     *
     * @see http://oid-info.com/get/1.2.840.10045.3.1.5
     *
     * @var string
     */
    final public const CURVE_PRIME239V2 = '1.2.840.10045.3.1.5';
    /**
     * prime239v3 curve OID.
     *
     * @see http://oid-info.com/get/1.2.840.10045.3.1.6
     *
     * @var string
     */
    final public const CURVE_PRIME239V3 = '1.2.840.10045.3.1.6';
    /**
     * prime256v1/secp256r1 curve OID.
     *
     * @see http://oid-info.com/get/1.2.840.10045.3.1.7
     *
     * @var string
     */
    final public const CURVE_PRIME256V1 = '1.2.840.10045.3.1.7';
    /**
     * "SEC 2" recommended elliptic curve domain - secp112r1.
     *
     * @see http://www.oid-info.com/get/1.3.132.0.6
     *
     * @var string
     */
    final public const CURVE_SECP112R1 = '1.3.132.0.6';
    /**
     * "SEC 2" recommended elliptic curve domain - secp112r2.
     *
     * @see http://oid-info.com/get/1.3.132.0.7
     *
     * @var string
     */
    final public const CURVE_SECP112R2 = '1.3.132.0.7';
    /**
     * "SEC 2" recommended elliptic curve domain - secp128r1.
     *
     * @see http://oid-info.com/get/1.3.132.0.28
     *
     * @var string
     */
    final public const CURVE_SECP128R1 = '1.3.132.0.28';
    /**
     * "SEC 2" recommended elliptic curve domain - secp128r2.
     *
     * @see http://oid-info.com/get/1.3.132.0.29
     *
     * @var string
     */
    final public const CURVE_SECP128R2 = '1.3.132.0.29';
    /**
     * "SEC 2" recommended elliptic curve domain - secp160k1.
     *
     * @see http://oid-info.com/get/1.3.132.0.9
     *
     * @var string
     */
    final public const CURVE_SECP160K1 = '1.3.132.0.9';
    /**
     * "SEC 2" recommended elliptic curve domain - secp160r1.
     *
     * @see http://oid-info.com/get/1.3.132.0.8
     *
     * @var string
     */
    final public const CURVE_SECP160R1 = '1.3.132.0.8';
    /**
     * "SEC 2" recommended elliptic curve domain - secp160r2.
     *
     * @see http://oid-info.com/get/1.3.132.0.30
     *
     * @var string
     */
    final public const CURVE_SECP160R2 = '1.3.132.0.30';
    /**
     * "SEC 2" recommended elliptic curve domain - secp192k1.
     *
     * @see http://oid-info.com/get/1.3.132.0.31
     *
     * @var string
     */
    final public const CURVE_SECP192K1 = '1.3.132.0.31';
    /**
     * "SEC 2" recommended elliptic curve domain - secp224k1.
     *
     * @see http://oid-info.com/get/1.3.132.0.32
     *
     * @var string
     */
    final public const CURVE_SECP224K1 = '1.3.132.0.32';
    /**
     * "SEC 2" recommended elliptic curve domain - secp224r1.
     *
     * @see http://oid-info.com/get/1.3.132.0.33
     *
     * @var string
     */
    final public const CURVE_SECP224R1 = '1.3.132.0.33';
    /**
     * "SEC 2" recommended elliptic curve domain - secp256k1.
     *
     * @see http://oid-info.com/get/1.3.132.0.10
     *
     * @var string
     */
    final public const CURVE_SECP256K1 = '1.3.132.0.10';
    /**
     * National Institute of Standards and Technology (NIST) 384-bit elliptic curve.
     *
     * @see http://oid-info.com/get/1.3.132.0.34
     *
     * @var string
     */
    final public const CURVE_SECP384R1 = '1.3.132.0.34';
    /**
     * National Institute of Standards and Technology (NIST) 512-bit elliptic curve.
     *
     * @see http://oid-info.com/get/1.3.132.0.35
     *
     * @var string
     */
    final public const CURVE_SECP521R1 = '1.3.132.0.35';
    /**
     * Mapping from curve OID to field bit size.
     *
     * @internal
     *
     * @var array<string, int>
     */
    final public const MAP_CURVE_TO_SIZE = [self::CURVE_PRIME192V1 => 192, self::CURVE_PRIME192V2 => 192, self::CURVE_PRIME192V3 => 192, self::CURVE_PRIME239V1 => 239, self::CURVE_PRIME239V2 => 239, self::CURVE_PRIME239V3 => 239, self::CURVE_PRIME256V1 => 256, self::CURVE_SECP112R1 => 112, self::CURVE_SECP112R2 => 112, self::CURVE_SECP128R1 => 128, self::CURVE_SECP128R2 => 128, self::CURVE_SECP160K1 => 160, self::CURVE_SECP160R1 => 160, self::CURVE_SECP160R2 => 160, self::CURVE_SECP192K1 => 192, self::CURVE_SECP224K1 => 224, self::CURVE_SECP224R1 => 224, self::CURVE_SECP256K1 => 256, self::CURVE_SECP384R1 => 384, self::CURVE_SECP521R1 => 521];
    /**
     * @param string $namedCurve Curve identifier
     */
    private function __construct(private readonly string $namedCurve)
    {
        parent::__construct(self::OID_EC_PUBLIC_KEY);
    }
    public static function create(string $namedCurve): self
    {
        return new self($namedCurve);
    }
    public function name(): string
    {
        return 'ecPublicKey';
    }
    /**
     * @return self
     */
    public static function fromASN1Params(?UnspecifiedType $params = null): SpecificAlgorithmIdentifier
    {
        if (!isset($params)) {
            throw new UnexpectedValueException('No parameters.');
        }
        $named_curve = $params->asObjectIdentifier()->oid();
        return self::create($named_curve);
    }
    /**
     * Get OID of the named curve.
     */
    public function namedCurve(): string
    {
        return $this->namedCurve;
    }
    /**
     * @return ObjectIdentifier
     */
    protected function paramsASN1(): Element
    {
        return ObjectIdentifier::create($this->namedCurve);
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\CryptoTypes\AlgorithmIdentifier\Asymmetric;

use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\UnspecifiedType;
use _ContaoManager\SpomkyLabs\Pki\CryptoTypes\AlgorithmIdentifier\SpecificAlgorithmIdentifier;
use UnexpectedValueException;
/**
 * Algorithm identifier for the Diffie-Hellman operation with curve25519.
 *
 * @see http://oid-info.com/get/1.3.101.110
 */
final class X25519AlgorithmIdentifier extends RFC8410XAlgorithmIdentifier
{
    private function __construct()
    {
        parent::__construct(self::OID_X25519);
    }
    public static function create(): self
    {
        return new self();
    }
    /**
     * @return self
     */
    public static function fromASN1Params(?UnspecifiedType $params = null): SpecificAlgorithmIdentifier
    {
        if ($params !== null) {
            throw new UnexpectedValueException('Parameters must be absent.');
        }
        return self::create();
    }
    public function name(): string
    {
        return 'id-X25519';
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\CryptoTypes\AlgorithmIdentifier\Asymmetric;

use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\UnspecifiedType;
use _ContaoManager\SpomkyLabs\Pki\CryptoTypes\AlgorithmIdentifier\SpecificAlgorithmIdentifier;
use UnexpectedValueException;
/**
 * Algorithm identifier for the Diffie-Hellman operation with curve448.
 *
 * @see http://oid-info.com/get/1.3.101.111
 */
final class X448AlgorithmIdentifier extends RFC8410XAlgorithmIdentifier
{
    private function __construct()
    {
        parent::__construct(self::OID_X448);
    }
    public static function create(): self
    {
        return new self();
    }
    /**
     * @return self
     */
    public static function fromASN1Params(?UnspecifiedType $params = null): SpecificAlgorithmIdentifier
    {
        if ($params !== null) {
            throw new UnexpectedValueException('Parameters must be absent.');
        }
        return self::create();
    }
    public function name(): string
    {
        return 'id-X448';
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\CryptoTypes\AlgorithmIdentifier\Asymmetric;

use _ContaoManager\SpomkyLabs\Pki\ASN1\Element;
use _ContaoManager\SpomkyLabs\Pki\CryptoTypes\AlgorithmIdentifier\Feature\AsymmetricCryptoAlgorithmIdentifier;
use _ContaoManager\SpomkyLabs\Pki\CryptoTypes\AlgorithmIdentifier\Feature\SignatureAlgorithmIdentifier;
use _ContaoManager\SpomkyLabs\Pki\CryptoTypes\AlgorithmIdentifier\SpecificAlgorithmIdentifier;
/*
 * From RFC 8410:
 * For all of the OIDs, the parameters MUST be absent.
 * It is possible to find systems that require the parameters to be
 * present.  This can be due to either a defect in the original 1997
 * syntax or a programming error where developers never got input where
 * this was not true.  The optimal solution is to fix these systems;
 * where this is not possible, the problem needs to be restricted to
 * that subsystem and not propagated to the Internet.
 */
/**
 * Algorithm identifier for the Edwards-curve Digital Signature Algorithm (EdDSA) identifiers specified by RFC 8410.
 *
 * Same algorithm identifier is used for public and private keys as well as for signatures.
 *
 * @see https://tools.ietf.org/html/rfc8410#section-3
 * @see https://tools.ietf.org/html/rfc8410#section-6
 */
abstract class RFC8410EdAlgorithmIdentifier extends SpecificAlgorithmIdentifier implements AsymmetricCryptoAlgorithmIdentifier, SignatureAlgorithmIdentifier
{
    protected function paramsASN1(): ?Element
    {
        return null;
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\CryptoTypes\AlgorithmIdentifier\Asymmetric;

use _ContaoManager\SpomkyLabs\Pki\ASN1\Element;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Primitive\NullType;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\UnspecifiedType;
use _ContaoManager\SpomkyLabs\Pki\CryptoTypes\AlgorithmIdentifier\Feature\AsymmetricCryptoAlgorithmIdentifier;
use _ContaoManager\SpomkyLabs\Pki\CryptoTypes\AlgorithmIdentifier\SpecificAlgorithmIdentifier;
use UnexpectedValueException;
/*
 * From RFC 3447:
 * When rsaEncryption is used in an AlgorithmIdentifier the
 * parameters MUST be present and MUST be NULL.
 */
/**
 * Algorithm identifier for RSA encryption.
 *
 * @see http://www.oid-info.com/get/1.2.840.113549.1.1.1
 * @see https://tools.ietf.org/html/rfc3447#appendix-C
 */
final class RSAEncryptionAlgorithmIdentifier extends SpecificAlgorithmIdentifier implements AsymmetricCryptoAlgorithmIdentifier
{
    private function __construct()
    {
        parent::__construct(self::OID_RSA_ENCRYPTION);
    }
    public static function create(): self
    {
        return new self();
    }
    public function name(): string
    {
        return 'rsaEncryption';
    }
    /**
     * @return self
     */
    public static function fromASN1Params(?UnspecifiedType $params = null): SpecificAlgorithmIdentifier
    {
        if (!isset($params)) {
            throw new UnexpectedValueException('No parameters.');
        }
        $params->asNull();
        return self::create();
    }
    /**
     * @return NullType
     */
    protected function paramsASN1(): Element
    {
        return NullType::create();
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\CryptoTypes\AlgorithmIdentifier\Asymmetric;

use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\UnspecifiedType;
use _ContaoManager\SpomkyLabs\Pki\CryptoTypes\AlgorithmIdentifier\AlgorithmIdentifier;
use _ContaoManager\SpomkyLabs\Pki\CryptoTypes\AlgorithmIdentifier\SpecificAlgorithmIdentifier;
use UnexpectedValueException;
/**
 * Algorithm identifier for the Edwards-curve Digital Signature Algorithm (EdDSA) with curve448.
 *
 * Same algorithm identifier is used for public and private keys as well as for signatures.
 *
 * @see http://oid-info.com/get/1.3.101.113
 * @see https://tools.ietf.org/html/rfc8420#appendix-A.2
 */
final class Ed448AlgorithmIdentifier extends RFC8410EdAlgorithmIdentifier
{
    protected function __construct()
    {
        parent::__construct(self::OID_ED448);
    }
    public static function create(): self
    {
        return new self();
    }
    /**
     * @return self
     */
    public static function fromASN1Params(?UnspecifiedType $params = null): SpecificAlgorithmIdentifier
    {
        if ($params !== null) {
            throw new UnexpectedValueException('Parameters must be absent.');
        }
        return self::create();
    }
    public function name(): string
    {
        return 'id-Ed448';
    }
    public function supportsKeyAlgorithm(AlgorithmIdentifier $algo): bool
    {
        return $algo->oid() === self::OID_ED448;
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\CryptoTypes\AlgorithmIdentifier\Asymmetric;

use _ContaoManager\SpomkyLabs\Pki\ASN1\Element;
use _ContaoManager\SpomkyLabs\Pki\CryptoTypes\AlgorithmIdentifier\Feature\AsymmetricCryptoAlgorithmIdentifier;
use _ContaoManager\SpomkyLabs\Pki\CryptoTypes\AlgorithmIdentifier\SpecificAlgorithmIdentifier;
/*
 * From RFC 8410:
 * For all of the OIDs, the parameters MUST be absent.
 * It is possible to find systems that require the parameters to be
 * present.  This can be due to either a defect in the original 1997
 * syntax or a programming error where developers never got input where
 * this was not true.  The optimal solution is to fix these systems;
 * where this is not possible, the problem needs to be restricted to
 * that subsystem and not propagated to the Internet.
 */
/**
 * Algorithm identifier for the Diffie-Hellman operations specified by RFC 8410.
 *
 * @see https://tools.ietf.org/html/rfc8410#section-3
 */
abstract class RFC8410XAlgorithmIdentifier extends SpecificAlgorithmIdentifier implements AsymmetricCryptoAlgorithmIdentifier
{
    protected function paramsASN1(): ?Element
    {
        return null;
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\CryptoTypes\AlgorithmIdentifier\Asymmetric;

use _ContaoManager\SpomkyLabs\Pki\ASN1\Element;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Primitive\NullType;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\UnspecifiedType;
use _ContaoManager\SpomkyLabs\Pki\CryptoTypes\AlgorithmIdentifier\Feature\AsymmetricCryptoAlgorithmIdentifier;
use _ContaoManager\SpomkyLabs\Pki\CryptoTypes\AlgorithmIdentifier\SpecificAlgorithmIdentifier;
use UnexpectedValueException;
/*
 * From RFC 3447:
 * When rsaEncryption is used in an AlgorithmIdentifier the
 * parameters MUST be present and MUST be NULL.
 */
/**
 * Algorithm identifier for RSA encryption.
 *
 * @see http://www.oid-info.com/get/1.2.840.113549.1.1.10
 * @see https://datatracker.ietf.org/doc/html/rfc8017#section-8.1
 */
final class RSAPSSSSAEncryptionAlgorithmIdentifier extends SpecificAlgorithmIdentifier implements AsymmetricCryptoAlgorithmIdentifier
{
    private function __construct()
    {
        parent::__construct(self::OID_RSASSA_PSS_ENCRYPTION);
    }
    public static function create(): self
    {
        return new self();
    }
    public function name(): string
    {
        return 'rsassa-pss';
    }
    /**
     * @return self
     */
    public static function fromASN1Params(?UnspecifiedType $params = null): SpecificAlgorithmIdentifier
    {
        if (!isset($params)) {
            throw new UnexpectedValueException('No parameters.');
        }
        $params->asNull();
        return self::create();
    }
    /**
     * @return NullType
     */
    protected function paramsASN1(): Element
    {
        return NullType::create();
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\CryptoTypes\AlgorithmIdentifier\Asymmetric;

use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\UnspecifiedType;
use _ContaoManager\SpomkyLabs\Pki\CryptoTypes\AlgorithmIdentifier\AlgorithmIdentifier;
use _ContaoManager\SpomkyLabs\Pki\CryptoTypes\AlgorithmIdentifier\SpecificAlgorithmIdentifier;
use UnexpectedValueException;
/**
 * Algorithm identifier for the Edwards-curve Digital Signature Algorithm (EdDSA) with curve25519.
 *
 * Same algorithm identifier is used for public and private keys as well as for signatures.
 *
 * @see http://oid-info.com/get/1.3.101.112
 * @see https://tools.ietf.org/html/rfc8420#appendix-A.1
 */
final class Ed25519AlgorithmIdentifier extends RFC8410EdAlgorithmIdentifier
{
    protected function __construct()
    {
        parent::__construct(self::OID_ED25519);
    }
    public static function create(): self
    {
        return new self();
    }
    /**
     * @return self
     */
    public static function fromASN1Params(?UnspecifiedType $params = null): SpecificAlgorithmIdentifier
    {
        if ($params !== null) {
            throw new UnexpectedValueException('Parameters must be absent.');
        }
        return self::create();
    }
    public function name(): string
    {
        return 'id-Ed25519';
    }
    public function supportsKeyAlgorithm(AlgorithmIdentifier $algo): bool
    {
        return $algo->oid() === self::OID_ED25519;
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\CryptoTypes\AlgorithmIdentifier;

use function array_key_exists;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Constructed\Sequence;
use _ContaoManager\SpomkyLabs\Pki\CryptoTypes\AlgorithmIdentifier\Asymmetric\ECPublicKeyAlgorithmIdentifier;
use _ContaoManager\SpomkyLabs\Pki\CryptoTypes\AlgorithmIdentifier\Asymmetric\Ed25519AlgorithmIdentifier;
use _ContaoManager\SpomkyLabs\Pki\CryptoTypes\AlgorithmIdentifier\Asymmetric\Ed448AlgorithmIdentifier;
use _ContaoManager\SpomkyLabs\Pki\CryptoTypes\AlgorithmIdentifier\Asymmetric\RSAEncryptionAlgorithmIdentifier;
use _ContaoManager\SpomkyLabs\Pki\CryptoTypes\AlgorithmIdentifier\Asymmetric\X25519AlgorithmIdentifier;
use _ContaoManager\SpomkyLabs\Pki\CryptoTypes\AlgorithmIdentifier\Asymmetric\X448AlgorithmIdentifier;
use _ContaoManager\SpomkyLabs\Pki\CryptoTypes\AlgorithmIdentifier\Cipher\AES128CBCAlgorithmIdentifier;
use _ContaoManager\SpomkyLabs\Pki\CryptoTypes\AlgorithmIdentifier\Cipher\AES192CBCAlgorithmIdentifier;
use _ContaoManager\SpomkyLabs\Pki\CryptoTypes\AlgorithmIdentifier\Cipher\AES256CBCAlgorithmIdentifier;
use _ContaoManager\SpomkyLabs\Pki\CryptoTypes\AlgorithmIdentifier\Cipher\DESCBCAlgorithmIdentifier;
use _ContaoManager\SpomkyLabs\Pki\CryptoTypes\AlgorithmIdentifier\Cipher\DESEDE3CBCAlgorithmIdentifier;
use _ContaoManager\SpomkyLabs\Pki\CryptoTypes\AlgorithmIdentifier\Cipher\RC2CBCAlgorithmIdentifier;
use _ContaoManager\SpomkyLabs\Pki\CryptoTypes\AlgorithmIdentifier\Hash\HMACWithSHA1AlgorithmIdentifier;
use _ContaoManager\SpomkyLabs\Pki\CryptoTypes\AlgorithmIdentifier\Hash\HMACWithSHA224AlgorithmIdentifier;
use _ContaoManager\SpomkyLabs\Pki\CryptoTypes\AlgorithmIdentifier\Hash\HMACWithSHA256AlgorithmIdentifier;
use _ContaoManager\SpomkyLabs\Pki\CryptoTypes\AlgorithmIdentifier\Hash\HMACWithSHA384AlgorithmIdentifier;
use _ContaoManager\SpomkyLabs\Pki\CryptoTypes\AlgorithmIdentifier\Hash\HMACWithSHA512AlgorithmIdentifier;
use _ContaoManager\SpomkyLabs\Pki\CryptoTypes\AlgorithmIdentifier\Hash\MD5AlgorithmIdentifier;
use _ContaoManager\SpomkyLabs\Pki\CryptoTypes\AlgorithmIdentifier\Hash\SHA1AlgorithmIdentifier;
use _ContaoManager\SpomkyLabs\Pki\CryptoTypes\AlgorithmIdentifier\Hash\SHA224AlgorithmIdentifier;
use _ContaoManager\SpomkyLabs\Pki\CryptoTypes\AlgorithmIdentifier\Hash\SHA256AlgorithmIdentifier;
use _ContaoManager\SpomkyLabs\Pki\CryptoTypes\AlgorithmIdentifier\Hash\SHA384AlgorithmIdentifier;
use _ContaoManager\SpomkyLabs\Pki\CryptoTypes\AlgorithmIdentifier\Hash\SHA512AlgorithmIdentifier;
use _ContaoManager\SpomkyLabs\Pki\CryptoTypes\AlgorithmIdentifier\Signature\ECDSAWithSHA1AlgorithmIdentifier;
use _ContaoManager\SpomkyLabs\Pki\CryptoTypes\AlgorithmIdentifier\Signature\ECDSAWithSHA224AlgorithmIdentifier;
use _ContaoManager\SpomkyLabs\Pki\CryptoTypes\AlgorithmIdentifier\Signature\ECDSAWithSHA256AlgorithmIdentifier;
use _ContaoManager\SpomkyLabs\Pki\CryptoTypes\AlgorithmIdentifier\Signature\ECDSAWithSHA384AlgorithmIdentifier;
use _ContaoManager\SpomkyLabs\Pki\CryptoTypes\AlgorithmIdentifier\Signature\ECDSAWithSHA512AlgorithmIdentifier;
use _ContaoManager\SpomkyLabs\Pki\CryptoTypes\AlgorithmIdentifier\Signature\MD2WithRSAEncryptionAlgorithmIdentifier;
use _ContaoManager\SpomkyLabs\Pki\CryptoTypes\AlgorithmIdentifier\Signature\MD4WithRSAEncryptionAlgorithmIdentifier;
use _ContaoManager\SpomkyLabs\Pki\CryptoTypes\AlgorithmIdentifier\Signature\MD5WithRSAEncryptionAlgorithmIdentifier;
use _ContaoManager\SpomkyLabs\Pki\CryptoTypes\AlgorithmIdentifier\Signature\SHA1WithRSAEncryptionAlgorithmIdentifier;
use _ContaoManager\SpomkyLabs\Pki\CryptoTypes\AlgorithmIdentifier\Signature\SHA224WithRSAEncryptionAlgorithmIdentifier;
use _ContaoManager\SpomkyLabs\Pki\CryptoTypes\AlgorithmIdentifier\Signature\SHA256WithRSAEncryptionAlgorithmIdentifier;
use _ContaoManager\SpomkyLabs\Pki\CryptoTypes\AlgorithmIdentifier\Signature\SHA384WithRSAEncryptionAlgorithmIdentifier;
use _ContaoManager\SpomkyLabs\Pki\CryptoTypes\AlgorithmIdentifier\Signature\SHA512WithRSAEncryptionAlgorithmIdentifier;
/**
 * Factory class to parse AlgorithmIdentifier ASN.1 types to specific algorithm identifier objects.
 *
 * Additional providers may be added to the process to support algorithm identifiers that are implemented in external
 * libraries.
 */
final class AlgorithmIdentifierFactory
{
    /**
     * Mapping for algorithm identifiers provided by this library.
     *
     * @internal
     *
     * @var array<string, string>
     */
    private const MAP_OID_TO_CLASS = [AlgorithmIdentifier::OID_RSA_ENCRYPTION => RSAEncryptionAlgorithmIdentifier::class, AlgorithmIdentifier::OID_EC_PUBLIC_KEY => ECPublicKeyAlgorithmIdentifier::class, AlgorithmIdentifier::OID_X25519 => X25519AlgorithmIdentifier::class, AlgorithmIdentifier::OID_X448 => X448AlgorithmIdentifier::class, AlgorithmIdentifier::OID_ED25519 => Ed25519AlgorithmIdentifier::class, AlgorithmIdentifier::OID_ED448 => Ed448AlgorithmIdentifier::class, AlgorithmIdentifier::OID_DES_CBC => DESCBCAlgorithmIdentifier::class, AlgorithmIdentifier::OID_DES_EDE3_CBC => DESEDE3CBCAlgorithmIdentifier::class, AlgorithmIdentifier::OID_RC2_CBC => RC2CBCAlgorithmIdentifier::class, AlgorithmIdentifier::OID_AES_128_CBC => AES128CBCAlgorithmIdentifier::class, AlgorithmIdentifier::OID_AES_192_CBC => AES192CBCAlgorithmIdentifier::class, AlgorithmIdentifier::OID_AES_256_CBC => AES256CBCAlgorithmIdentifier::class, AlgorithmIdentifier::OID_HMAC_WITH_SHA1 => HMACWithSHA1AlgorithmIdentifier::class, AlgorithmIdentifier::OID_HMAC_WITH_SHA224 => HMACWithSHA224AlgorithmIdentifier::class, AlgorithmIdentifier::OID_HMAC_WITH_SHA256 => HMACWithSHA256AlgorithmIdentifier::class, AlgorithmIdentifier::OID_HMAC_WITH_SHA384 => HMACWithSHA384AlgorithmIdentifier::class, AlgorithmIdentifier::OID_HMAC_WITH_SHA512 => HMACWithSHA512AlgorithmIdentifier::class, AlgorithmIdentifier::OID_MD5 => MD5AlgorithmIdentifier::class, AlgorithmIdentifier::OID_SHA1 => SHA1AlgorithmIdentifier::class, AlgorithmIdentifier::OID_SHA224 => SHA224AlgorithmIdentifier::class, AlgorithmIdentifier::OID_SHA256 => SHA256AlgorithmIdentifier::class, AlgorithmIdentifier::OID_SHA384 => SHA384AlgorithmIdentifier::class, AlgorithmIdentifier::OID_SHA512 => SHA512AlgorithmIdentifier::class, AlgorithmIdentifier::OID_MD2_WITH_RSA_ENCRYPTION => MD2WithRSAEncryptionAlgorithmIdentifier::class, AlgorithmIdentifier::OID_MD4_WITH_RSA_ENCRYPTION => MD4WithRSAEncryptionAlgorithmIdentifier::class, AlgorithmIdentifier::OID_MD5_WITH_RSA_ENCRYPTION => MD5WithRSAEncryptionAlgorithmIdentifier::class, AlgorithmIdentifier::OID_SHA1_WITH_RSA_ENCRYPTION => SHA1WithRSAEncryptionAlgorithmIdentifier::class, AlgorithmIdentifier::OID_SHA224_WITH_RSA_ENCRYPTION => SHA224WithRSAEncryptionAlgorithmIdentifier::class, AlgorithmIdentifier::OID_SHA256_WITH_RSA_ENCRYPTION => SHA256WithRSAEncryptionAlgorithmIdentifier::class, AlgorithmIdentifier::OID_SHA384_WITH_RSA_ENCRYPTION => SHA384WithRSAEncryptionAlgorithmIdentifier::class, AlgorithmIdentifier::OID_SHA512_WITH_RSA_ENCRYPTION => SHA512WithRSAEncryptionAlgorithmIdentifier::class, AlgorithmIdentifier::OID_ECDSA_WITH_SHA1 => ECDSAWithSHA1AlgorithmIdentifier::class, AlgorithmIdentifier::OID_ECDSA_WITH_SHA224 => ECDSAWithSHA224AlgorithmIdentifier::class, AlgorithmIdentifier::OID_ECDSA_WITH_SHA256 => ECDSAWithSHA256AlgorithmIdentifier::class, AlgorithmIdentifier::OID_ECDSA_WITH_SHA384 => ECDSAWithSHA384AlgorithmIdentifier::class, AlgorithmIdentifier::OID_ECDSA_WITH_SHA512 => ECDSAWithSHA512AlgorithmIdentifier::class];
    /**
     * Additional algorithm identifier providers.
     *
     * @var AlgorithmIdentifierProvider[]
     */
    private readonly array $_additionalProviders;
    /**
     * @param AlgorithmIdentifierProvider ...$providers Additional providers
     */
    private function __construct(AlgorithmIdentifierProvider ...$providers)
    {
        $this->_additionalProviders = $providers;
    }
    public static function create(AlgorithmIdentifierProvider ...$providers): self
    {
        return new self(...$providers);
    }
    /**
     * Get the name of a class that implements algorithm identifier for given OID.
     *
     * @param string $oid Object identifier in dotted format
     *
     * @return null|string Fully qualified class name or null if not supported
     */
    public function getClass(string $oid): ?string
    {
        // if OID is provided by this factory
        if (array_key_exists($oid, self::MAP_OID_TO_CLASS)) {
            return self::MAP_OID_TO_CLASS[$oid];
        }
        // try additional providers
        foreach ($this->_additionalProviders as $provider) {
            if ($provider->supportsOID($oid)) {
                return $provider->getClassByOID($oid);
            }
        }
        return null;
    }
    /**
     * Parse AlgorithmIdentifier from an ASN.1 sequence.
     */
    public function parse(Sequence $seq): AlgorithmIdentifier
    {
        $oid = $seq->at(0)->asObjectIdentifier()->oid();
        $params = $seq->has(1) ? $seq->at(1) : null;
        $cls = $this->getClass($oid);
        if ($cls !== null) {
            return $cls::fromASN1Params($params);
        }
        return GenericAlgorithmIdentifier::create($oid, $params);
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\CryptoTypes\AlgorithmIdentifier\Feature;

use _ContaoManager\SpomkyLabs\Pki\CryptoTypes\AlgorithmIdentifier\AlgorithmIdentifier;
/**
 * Algorithm identifier for signature algorithms.
 */
interface SignatureAlgorithmIdentifier extends AlgorithmIdentifierType
{
    /**
     * Check whether signature algorithm supports given key algorithm.
     */
    public function supportsKeyAlgorithm(AlgorithmIdentifier $algo): bool;
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\CryptoTypes\AlgorithmIdentifier\Feature;

/**
 * Algorithm identifier for pseudorandom functions.
 */
interface PRFAlgorithmIdentifier extends AlgorithmIdentifierType
{
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\CryptoTypes\AlgorithmIdentifier\Feature;

/**
 * Algorithm identifier for asymmetric cryptography algorithms.
 */
interface AsymmetricCryptoAlgorithmIdentifier extends AlgorithmIdentifierType
{
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\CryptoTypes\AlgorithmIdentifier\Feature;

/**
 * Algorithm identifier for hash functions.
 */
interface HashAlgorithmIdentifier extends AlgorithmIdentifierType
{
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\CryptoTypes\AlgorithmIdentifier\Feature;

/**
 * Algorithm identifier for encryption algorithms.
 */
interface EncryptionAlgorithmIdentifier extends AlgorithmIdentifierType
{
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\CryptoTypes\AlgorithmIdentifier\Feature;

use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\Constructed\Sequence;
/**
 * Base interface for algorithm identifiers.
 */
interface AlgorithmIdentifierType
{
    /**
     * Get the object identifier of the algorithm.
     *
     * @return string Object identifier in dotted format
     */
    public function oid(): string;
    /**
     * Get a human-readable name of the algorithm.
     */
    public function name(): string;
    /**
     * Generate ASN.1 structure.
     */
    public function toASN1(): Sequence;
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\CryptoTypes\AlgorithmIdentifier;

/**
 * Interface to provide lookup from OID to class name of specific algorithm identifier type implementations.
 *
 * This allows AlgorithmIdentifier types to be implemented in external libraries and to use AlgorithmIdentifierFactory
 * to resolve them.
 */
interface AlgorithmIdentifierProvider
{
    /**
     * Check whether this provider supports algorithm identifier of given OID.
     *
     * @param string $oid Object identifier in dotted format
     */
    public function supportsOID(string $oid): bool;
    /**
     * Get the name of a class that implements algorithm identifier for given OID.
     *
     * @param string $oid Object identifier in dotted format
     *
     * @return string Fully qualified name of a class that extends
     * SpecificAlgorithmIdentifier
     */
    public function getClassByOID(string $oid): string;
}
<?php

declare (strict_types=1);
namespace _ContaoManager\SpomkyLabs\Pki\CryptoTypes\AlgorithmIdentifier;

use _ContaoManager\SpomkyLabs\Pki\ASN1\Element;
use _ContaoManager\SpomkyLabs\Pki\ASN1\Type\UnspecifiedType;
/**
 * Generic algorithm identifier to hold parameters as ASN.1 objects.
 */
final class GenericAlgorithmIdentifier extends AlgorithmIdentifier
{
    /**
     * @param string $oid Algorithm OID
     * @param null|UnspecifiedType $params Parameters
     */
    private function __construct(string $oid, private readonly ?UnspecifiedType $params)
    {
        parent::__construct($oid);
    }
    public static function create(string $oid, ?UnspecifiedType $params = null): self
    {
        return new self($oid, $params);
    }
    public function name(): string
    {
        return $this->oid;
    }
    public function parameters(): ?UnspecifiedType
    {
        return $this->params;
    }
    protected function paramsASN1(): ?Element
    {
        return $this->params?->asElement();
    }
}
# Contributor Covenant Code of Conduct

## Our Pledge

In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation.

## Our Standards

Examples of behavior that contributes to creating a positive environment include:

* Using welcoming and inclusive language
* Being respectful of differing viewpoints and experiences
* Gracefully accepting constructive criticism
* Focusing on what is best for the community
* Showing empathy towards other community members

Examples of unacceptable behavior by participants include:

* The use of sexualized language or imagery and unwelcome sexual attention or advances
* Trolling, insulting/derogatory comments, and personal or political attacks
* Public or private harassment
* Publishing others' private information, such as a physical or electronic address, without explicit permission
* Other conduct which could reasonably be considered inappropriate in a professional setting

## Our Responsibilities

Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior.

Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful.

## Scope

This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers.

## Enforcement

Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at contact@spomky-labs.com. The project team will review and investigate all complaints, and will respond in a way that it deems appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately.

Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership.

## Attribution

This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [http://contributor-covenant.org/version/1/4][version]

[homepage]: http://contributor-covenant.org
[version]: http://contributor-covenant.org/version/1/4/
# Versioning and Release

This document describes the versioning and release process of OTPHP.
This document is a living document, contents will be updated according to each release.

## Releases

OTPHP releases will be versioned using dotted triples, similar to [Semantic Version](http://semver.org/).
For this specific document, we will refer to the respective components of this triple as `<major>.<minor>.<patch>`.
The version number may have additional information, such as "-rc1,-rc2,-rc3" to mark release candidate builds for earlier access.
Such releases will be considered as "pre-releases".

## Minor Release Support Matrix

| Version  | Supported          |
|----------|--------------------|
| 11.4.x   | :white_check_mark: |
| < 11.4.x | :x:                |
The MIT License (MIT)

Copyright (c) 2014-2016 Florent Morselli

Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
TOTP / HOTP library in PHP
==========================

![Build Status](https://github.com/spomky-labs/otphp/workflows/Integrate/badge.svg)
![Build Status](https://github.com/spomky-labs/otphp/workflows/Infection/badge.svg)

[![Latest Stable Version](https://poser.pugx.org/spomky-labs/otphp/v/stable.png)](https://packagist.org/packages/spomky-labs/otphp)
[![Total Downloads](https://poser.pugx.org/spomky-labs/otphp/downloads.png)](https://packagist.org/packages/spomky-labs/otphp)
[![Latest Unstable Version](https://poser.pugx.org/spomky-labs/otphp/v/unstable.png)](https://packagist.org/packages/spomky-labs/otphp)
[![License](https://poser.pugx.org/spomky-labs/otphp/license.png)](https://packagist.org/packages/spomky-labs/otphp)

A php library for generating one-time passwords according to [RFC 4226](https://datatracker.ietf.org/doc/html/rfc4226) (HOTP Algorithm) and [RFC 6238](https://datatracker.ietf.org/doc/html/rfc6238) (TOTP Algorithm)

This library is compatible with Google Authenticator apps available for Android and iPhone.
It is also compatible with other applications such as [FreeOTP](https://play.google.com/store/apps/details?id=org.fedorahosted.freeotp) for example.

# Documentation

The documentation of this project is available in the [*doc* folder](doc/index.md).

# Support

I bring solutions to your problems and answer your questions.

If you really love that project, and the work I have done or if you want I prioritize your issues, then you can help me out for a couple of :beers: or more!

[Become a sponsor](https://github.com/sponsors/Spomky)

Or

[![Become a Patreon](https://c5.patreon.com/external/logo/become_a_patron_button.png)](https://www.patreon.com/FlorentMorselli)

## Contributing

Requests for new features, bug fixes and all other ideas to make this project useful are welcome.

Please report all issues in [the repository bug tracker](https://github.com/Spomky-Labs/otphp/issues).

Also make sure to [follow these best practices](.github/CONTRIBUTING.md).

## Licence

This software is release under the [MIT licence](LICENSE).
{
    "name": "spomky-labs\/otphp",
    "type": "library",
    "description": "A PHP library for generating one time passwords according to RFC 4226 (HOTP Algorithm) and the RFC 6238 (TOTP Algorithm) and compatible with Google Authenticator",
    "license": "MIT",
    "keywords": [
        "otp",
        "hotp",
        "totp",
        "RFC 4226",
        "RFC 6238",
        "Google Authenticator",
        "FreeOTP"
    ],
    "homepage": "https:\/\/github.com\/Spomky-Labs\/otphp",
    "authors": [
        {
            "name": "Florent Morselli",
            "homepage": "https:\/\/github.com\/Spomky"
        },
        {
            "name": "All contributors",
            "homepage": "https:\/\/github.com\/Spomky-Labs\/otphp\/contributors"
        }
    ],
    "require": {
        "php": ">=8.1",
        "paragonie\/constant_time_encoding": "^2.0 || ^3.0",
        "psr\/clock": "^1.0",
        "symfony\/deprecation-contracts": "^3.2"
    },
    "require-dev": {
        "symfony\/error-handler": "^6.4|^7.0|^8.0"
    },
    "autoload": {
        "psr-4": {
            "_ContaoManager\\OTPHP\\": "src\/"
        }
    },
    "autoload-dev": {
        "psr-4": {
            "_ContaoManager\\OTPHP\\Test\\": "tests\/"
        }
    },
    "config": {
        "allow-plugins": {
            "phpstan\/extension-installer": true,
            "infection\/extension-installer": true,
            "composer\/package-versions-deprecated": true,
            "symfony\/flex": true,
            "symfony\/runtime": true
        },
        "optimize-autoloader": true,
        "preferred-install": {
            "*": "dist"
        },
        "sort-packages": true
    }
}# Security Release Process

OTPHP is devoted to providing the best experience for all developers who want to implement OTP authentication in their applications.
Spomky-Labs has adopted this security disclosure and response policy to ensure we responsibly handle critical issues.

## Supported Versions

The OTPHP project maintains release branches for the three most recent minor releases.
Applicable fixes, including security fixes, may be backported to those three release branches, depending on severity and feasibility. Please refer to [RELEASES.md](RELEASES.md) for details.

## Reporting a Vulnerability - Private Disclosure Process

Security is of the highest importance and all security vulnerabilities or suspected security vulnerabilities should be reported to OTPHP privately, to minimize attacks against current users of OTPHP before they are fixed.
Vulnerabilities will be investigated and patched on the next patch (or minor) release as soon as possible.
This information could be kept entirely internal to the project.

If you know of a publicly disclosed security vulnerability for OTPHP, please **IMMEDIATELY** contact security@spomky-labs.com to inform the OTPHP Security Team.

**IMPORTANT: Do not file public issues on GitHub for security vulnerabilities**

To report a vulnerability or a security-related issue, please email the private address security@spomky-labs.com with the details of the vulnerability.
The email will be fielded by the OTPHP Security Team, which is made up of the OTPHP maintainers who have committer and release permissions.
Do not report non-security-impacting bugs through this channel. Use [GitHub issues](https://github.com/Spomky-Labs/otphp/issues/new/choose) instead.

Emails can be encrypted if you wish to share the vulnerability details securely.
The OTPHP Security Team's PGP key is available on the [PGP keyservers](https://keys.openpgp.org/search?q=security%40spomky-labs.com).

### Proposed Email Content

Provide a descriptive subject line and in the body of the email include the following information:

-   Basic identity information, such as your name and your affiliation or company.
-   Detailed steps to reproduce the vulnerability (POC scripts, screenshots, and compressed packet captures are all helpful to us).
-   Description of the effects of the vulnerability on OTPHP and the related hardware and software configurations, so that the OTPHP Security Team can reproduce it.
-   How the vulnerability affects OTPHP usage and an estimation of the attack surface, if there is one.
-   List other projects or dependencies that were used in conjunction with OTPHP to produce the vulnerability.

## When to report a vulnerability

-   When you think OTPHP has a potential security vulnerability.
-   When you suspect a potential vulnerability, but you are unsure that it impacts OTPHP.
-   When you know of or suspect a potential vulnerability on another project that is used by OTPHP.

## Patch, Release, and Disclosure

The OTPHP Security Team will respond to vulnerability reports as follows:

1.  The Security Team will investigate the vulnerability and determine its effects and criticality.
2.  If the issue is not deemed to be a vulnerability, the Security Team will follow up with a detailed reason for rejection.
3.  The Security Team will initiate a conversation with the reporter as soon as possible.
4.  If a vulnerability is acknowledged and the timeline for a fix is determined, the Security Team will work on a plan to communicate with the appropriate community, including identifying mitigating steps that affected users can take to protect themselves until the fix is rolled out.
5.  The Security Team will work on fixing the vulnerability and perform internal testing before preparing to roll out the fix.
6.  A public disclosure date is negotiated by the OTPHP Security Team and the bug submitter. We prefer to fully disclose the bug as soon as possible once a user mitigation or patch is available. It is reasonable to delay disclosure when the bug or the fix is not yet fully understood, the solution is not well-tested, or for distributor coordination. The timeframe for disclosure is from immediate (especially if it's already publicly known) to a few weeks. For a critical vulnerability with a straightforward mitigation, we expect report date to public disclosure date to be on the order of 14 business days. The OTPHP Security Team holds the final say when setting a public disclosure date.
7.  Once the fix is confirmed, the Security Team will patch the vulnerability in the next patch or minor release, and backport a patch release into all earlier supported releases. Upon release of the patched version of OTPHP, we will follow the **Public Disclosure Process**.

### Public Disclosure Process

The Security Team publishes a public [advisory](https://github.com/Spomky-Labs/otphp/security/advisories) to the OTPHP community via GitHub. In most cases, additional communication via Twitter, blog and other channels will assist in educating OTPHP users and rolling out the patched release to affected users.

The Security Team will also publish any mitigating steps users can take until the fix can be applied to their OTPHP instances. OTPHP distributors will handle creating and publishing their own security advisories.

## Mailing lists

-   Use security@spomky-labs.com to report security concerns to the OTPHP Security Team, who uses the list to privately discuss security issues and fixes prior to disclosure.

## Early Disclosure to OTPHP Distributors List

This private list is intended to be used primarily to provide actionable information to multiple distributor projects at once. This list is not intended to inform individuals about security issues.

## Confidentiality, integrity and availability

We consider vulnerabilities leading to the compromise of data confidentiality, elevation of privilege, or integrity to be our highest priority concerns.
Availability, in particular in areas relating to DoS and resource exhaustion, is also a serious security concern.
The OTPHP Security Team takes all vulnerabilities, potential vulnerabilities, and suspected vulnerabilities seriously and will investigate them in an urgent and expeditious manner.
<?php

declare (strict_types=1);
namespace _ContaoManager\OTPHP;

use _ContaoManager\OTPHP\Exception\InvalidParameterException;
use _ContaoManager\Psr\Clock\ClockInterface;
use function is_int;
/**
 * @readonly
 *
 * @see \OTPHP\Test\TOTPTest
 */
final class TOTP extends OTP implements TOTPInterface
{
    private readonly ClockInterface $clock;
    public function __construct(string $secret, ?ClockInterface $clock = null)
    {
        parent::__construct($secret);
        if ($clock === null) {
            trigger_deprecation('spomky-labs/otphp', '11.3.0', 'The parameter "$clock" will become mandatory in 12.0.0. Please set a valid PSR Clock implementation instead of "null".');
            $clock = new InternalClock();
        }
        $this->clock = $clock;
    }
    public static function create(null|string $secret = null, int $period = self::DEFAULT_PERIOD, string $digest = self::DEFAULT_DIGEST, int $digits = self::DEFAULT_DIGITS, int $epoch = self::DEFAULT_EPOCH, ?ClockInterface $clock = null, ?int $secretSize = null): self
    {
        $totp = $secret !== null ? self::createFromSecret($secret, $clock) : self::generate($clock, $secretSize);
        $totp->setPeriod($period);
        $totp->setDigest($digest);
        $totp->setDigits($digits);
        $totp->setEpoch($epoch);
        return $totp;
    }
    public static function createFromSecret(string $secret, ?ClockInterface $clock = null): self
    {
        $totp = new self($secret, $clock);
        $totp->setPeriod(self::DEFAULT_PERIOD);
        $totp->setDigest(self::DEFAULT_DIGEST);
        $totp->setDigits(self::DEFAULT_DIGITS);
        $totp->setEpoch(self::DEFAULT_EPOCH);
        return $totp;
    }
    /**
     * @param positive-int|null $secretSize
     */
    public static function generate(?ClockInterface $clock = null, ?int $secretSize = null): self
    {
        return self::createFromSecret(self::generateSecret($secretSize), $clock);
    }
    public function getPeriod(): int
    {
        $value = $this->getParameter('period');
        is_int($value) && $value > 0 || throw new InvalidParameterException('Invalid "period" parameter.', 'period', $value);
        return $value;
    }
    public function getEpoch(): int
    {
        $value = $this->getParameter('epoch');
        is_int($value) && $value >= 0 || throw new InvalidParameterException('Invalid "epoch" parameter.', 'epoch', $value);
        return $value;
    }
    public function expiresIn(): int
    {
        $period = $this->getPeriod();
        return $period - ($this->clock->now()->getTimestamp() - $this->getEpoch()) % $period;
    }
    /**
     * The OTP at the specified input.
     *
     * @param 0|positive-int $input
     */
    public function at(int $input): string
    {
        return $this->generateOTP($this->timecode($input));
    }
    public function now(): string
    {
        $timestamp = $this->clock->now()->getTimestamp();
        $timestamp >= 0 || throw new InvalidParameterException('The timestamp must return a positive integer.', 'timestamp', $timestamp);
        return $this->at($timestamp);
    }
    /**
     * If no timestamp is provided, the OTP is verified at the actual timestamp. When used, the leeway parameter will
     * allow time drift. The passed value is in seconds.
     *
     * @param 0|positive-int $timestamp
     * @param null|0|positive-int $leeway
     */
    public function verify(string $otp, null|int $timestamp = null, null|int $leeway = null): bool
    {
        $timestamp ??= $this->clock->now()->getTimestamp();
        $timestamp >= 0 || throw new InvalidParameterException('Timestamp must be at least 0.', 'timestamp', $timestamp);
        if ($leeway === null) {
            return $this->compareOTP($this->at($timestamp), $otp);
        }
        $leeway = abs($leeway);
        $leeway < $this->getPeriod() || throw new InvalidParameterException('The leeway must be lower than the TOTP period', 'leeway', $leeway);
        $timestampMinusLeeway = $timestamp - $leeway;
        $timestampMinusLeeway >= 0 || throw new InvalidParameterException('The timestamp must be greater than or equal to the leeway.', 'timestamp', $timestamp);
        return $this->compareOTP($this->at($timestampMinusLeeway), $otp) || $this->compareOTP($this->at($timestamp), $otp) || $this->compareOTP($this->at($timestamp + $leeway), $otp);
    }
    public function getProvisioningUri(): string
    {
        $params = [];
        if ($this->getPeriod() !== 30) {
            $params['period'] = $this->getPeriod();
        }
        if ($this->getEpoch() !== 0) {
            $params['epoch'] = $this->getEpoch();
        }
        return $this->generateURI('totp', $params);
    }
    public function setPeriod(int $period): void
    {
        $this->setParameter('period', $period);
    }
    public function withPeriod(int $period): self
    {
        $otp = clone $this;
        $otp->setParameter('period', $period);
        return $otp;
    }
    public function setEpoch(int $epoch): void
    {
        $this->setParameter('epoch', $epoch);
    }
    public function withEpoch(int $epoch): self
    {
        $otp = clone $this;
        $otp->setParameter('epoch', $epoch);
        return $otp;
    }
    /**
     * @return array<non-empty-string, callable>
     */
    protected function getParameterMap(): array
    {
        return [...parent::getParameterMap(), 'period' => static function ($value): int {
            (int) $value > 0 || throw new InvalidParameterException('Period must be at least 1.', 'period', $value);
            return (int) $value;
        }, 'epoch' => static function ($value): int {
            (int) $value >= 0 || throw new InvalidParameterException('Epoch must be greater than or equal to 0.', 'epoch', $value);
            return (int) $value;
        }];
    }
    /**
     * @param array<non-empty-string, mixed> $options
     */
    protected function filterOptions(array &$options): void
    {
        parent::filterOptions($options);
        if (isset($options['epoch']) && $options['epoch'] === 0) {
            unset($options['epoch']);
        }
        ksort($options);
    }
    /**
     * @param 0|positive-int $timestamp
     *
     * @return 0|positive-int
     */
    private function timecode(int $timestamp): int
    {
        $timecode = (int) floor(($timestamp - $this->getEpoch()) / $this->getPeriod());
        $timecode >= 0 || throw new InvalidParameterException('Timecode must be at least 0. The timestamp must be greater than or equal to the epoch.', 'timecode', $timecode);
        return $timecode;
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\OTPHP;

use _ContaoManager\OTPHP\Exception\InvalidProvisioningUriException;
use _ContaoManager\Psr\Clock\ClockInterface;
use Throwable;
use function count;
use function sprintf;
/**
 * This class is used to load OTP object from a provisioning Uri.
 *
 * @readonly
 *
 * @see \OTPHP\Test\FactoryTest
 */
final class Factory implements FactoryInterface
{
    public static function loadFromProvisioningUri(string $uri, ?ClockInterface $clock = null): OTPInterface
    {
        try {
            $parsed_url = Url::fromString($uri);
            $parsed_url->getScheme() === 'otpauth' || throw new InvalidProvisioningUriException('Invalid scheme.');
        } catch (Throwable $throwable) {
            throw new InvalidProvisioningUriException('Not a valid OTP provisioning URI', $throwable->getCode(), $throwable);
        }
        if ($clock === null) {
            trigger_deprecation('spomky-labs/otphp', '11.3.0', 'The parameter "$clock" will become mandatory in 12.0.0. Please set a valid PSR Clock implementation instead of "null".');
            $clock = new InternalClock();
        }
        $otp = self::createOTP($parsed_url, $clock);
        self::populateOTP($otp, $parsed_url);
        return $otp;
    }
    private static function populateParameters(OTPInterface $otp, Url $data): void
    {
        foreach ($data->getQuery() as $key => $value) {
            $otp->setParameter($key, $value);
        }
    }
    private static function populateOTP(OTPInterface $otp, Url $data): void
    {
        self::populateParameters($otp, $data);
        $result = explode(':', rawurldecode(substr($data->getPath(), 1)));
        if (count($result) < 2) {
            $otp->setIssuerIncludedAsParameter(\false);
            return;
        }
        $issuerFromLabel = $result[0];
        $issuerFromParameter = $otp->getIssuer();
        if ($issuerFromParameter !== null) {
            // Issuer parameter takes precedence over issuer in label
            // According to Google Authenticator spec: "they should be equal" but not required to be
            $otp->setIssuerIncludedAsParameter(\true);
        } else {
            // No issuer parameter, use the issuer from label
            $issuerFromLabel !== '' || throw new InvalidProvisioningUriException('Issuer from label must not be empty.');
            $otp->setIssuer($issuerFromLabel);
        }
    }
    private static function createOTP(Url $parsed_url, ClockInterface $clock): OTPInterface
    {
        switch ($parsed_url->getHost()) {
            case 'totp':
                $totp = TOTP::createFromSecret($parsed_url->getSecret(), $clock);
                $totp->setLabel(self::getLabel($parsed_url->getPath()));
                return $totp;
            case 'hotp':
                $hotp = HOTP::createFromSecret($parsed_url->getSecret());
                $hotp->setLabel(self::getLabel($parsed_url->getPath()));
                return $hotp;
            default:
                throw new InvalidProvisioningUriException(sprintf('Unsupported "%s" OTP type', $parsed_url->getHost()));
        }
    }
    /**
     * @param non-empty-string $data
     * @return non-empty-string
     */
    private static function getLabel(string $data): string
    {
        $result = explode(':', rawurldecode(substr($data, 1)));
        $label = count($result) === 2 ? $result[1] : $result[0];
        $label !== '' || throw new InvalidProvisioningUriException('Label must not be empty.');
        return $label;
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\OTPHP;

interface OTPInterface
{
    public const DEFAULT_DIGITS = 6;
    public const DEFAULT_DIGEST = 'sha1';
    /**
     * Create a OTP object from an existing secret.
     *
     * @param non-empty-string $secret
     */
    public static function createFromSecret(string $secret): self;
    /**
     * Create a new OTP object. A random 64 bytes secret will be generated.
     */
    public static function generate(): self;
    /**
     * @param non-empty-string $secret
     *
     * @deprecated Deprecated since v11.4, use {@see self::withSecret()} instead
     */
    public function setSecret(string $secret): void;
    /**
     * @param non-empty-string $secret
     */
    public function withSecret(string $secret): self;
    /**
     * @deprecated Deprecated since v11.4, use {@see self::withDigits()} instead
     */
    public function setDigits(int $digits): void;
    public function withDigits(int $digits): self;
    /**
     * @param non-empty-string $digest
     *
     * @deprecated Deprecated since v11.4, use {@see self::withDigest()} instead
     */
    public function setDigest(string $digest): void;
    /**
     * @param non-empty-string $digest
     */
    public function withDigest(string $digest): self;
    /**
     * Generate the OTP at the specified input.
     *
     * @param 0|positive-int $input
     *
     * @return non-empty-string Return the OTP at the specified timestamp
     */
    public function at(int $input): string;
    /**
     * Verify that the OTP is valid with the specified input. If no input is provided, the input is set to a default
     * value or false is returned.
     *
     * @param non-empty-string $otp
     * @param null|0|positive-int $input
     * @param null|0|positive-int $window
     */
    public function verify(string $otp, null|int $input = null, null|int $window = null): bool;
    /**
     * @return non-empty-string The secret of the OTP
     */
    public function getSecret(): string;
    /**
     * @param non-empty-string $label The label of the OTP
     *
     * @deprecated Deprecated since v11.4, use {@see self::withLabel()} instead
     */
    public function setLabel(string $label): void;
    /**
     * @param non-empty-string $label The label of the OTP
     */
    public function withLabel(string $label): self;
    /**
     * @return non-empty-string|null The label of the OTP
     */
    public function getLabel(): null|string;
    /**
     * @return non-empty-string|null The issuer
     */
    public function getIssuer(): ?string;
    /**
     * @param non-empty-string $issuer
     *
     * @deprecated Deprecated since v11.4, use {@see self::withIssuer()} instead
     */
    public function setIssuer(string $issuer): void;
    /**
     * @param non-empty-string $issuer
     */
    public function withIssuer(string $issuer): self;
    /**
     * @return bool If true, the issuer will be added as a parameter in the provisioning URI
     */
    public function isIssuerIncludedAsParameter(): bool;
    /**
     * @deprecated Deprecated since v11.4, use {@see self::withIssuerIncludedAsParameter()} instead
     */
    public function setIssuerIncludedAsParameter(bool $issuer_included_as_parameter): void;
    public function withIssuerIncludedAsParameter(bool $issuer_included_as_parameter): self;
    /**
     * @return positive-int Number of digits in the OTP
     */
    public function getDigits(): int;
    /**
     * @return non-empty-string Digest algorithm used to calculate the OTP. Possible values are 'md5', 'sha1', 'sha256' and 'sha512'
     */
    public function getDigest(): string;
    /**
     * @param non-empty-string $parameter
     */
    public function getParameter(string $parameter): mixed;
    /**
     * @param non-empty-string $parameter
     */
    public function hasParameter(string $parameter): bool;
    /**
     * @return array<non-empty-string, mixed>
     */
    public function getParameters(): array;
    /**
     * @param non-empty-string $parameter
     *
     * @deprecated Deprecated since v11.4, use {@see self::withParameter()} instead
     */
    public function setParameter(string $parameter, mixed $value): void;
    /**
     * @param non-empty-string $parameter
     */
    public function withParameter(string $parameter, mixed $value): self;
    /**
     * Get the provisioning URI.
     *
     * @return non-empty-string
     */
    public function getProvisioningUri(): string;
    /**
     * Get the provisioning URI.
     *
     * @param non-empty-string $uri         The Uri of the QRCode generator with all parameters. This Uri MUST contain a placeholder that will be replaced by the method.
     * @param non-empty-string $placeholder the placeholder to be replaced in the QR Code generator URI
     */
    public function getQrCodeUri(string $uri, string $placeholder): string;
}
<?php

declare (strict_types=1);
namespace _ContaoManager\OTPHP;

interface TOTPInterface extends OTPInterface
{
    public const DEFAULT_PERIOD = 30;
    public const DEFAULT_EPOCH = 0;
    /**
     * Create a new TOTP object.
     *
     * If the secret is null, a random 64 bytes secret will be generated.
     *
     * @param null|non-empty-string $secret
     * @param positive-int $period
     * @param non-empty-string $digest
     * @param positive-int $digits
     *
     * @deprecated Deprecated since v11.1, use ::createFromSecret or ::generate instead
     */
    public static function create(null|string $secret = null, int $period = self::DEFAULT_PERIOD, string $digest = self::DEFAULT_DIGEST, int $digits = self::DEFAULT_DIGITS): self;
    /**
     * @deprecated Deprecated since v11.4, use {@see self::withPeriod()} instead
     */
    public function setPeriod(int $period): void;
    public function withPeriod(int $period): self;
    /**
     * @deprecated Deprecated since v11.4, use {@see self::withEpoch()} instead
     */
    public function setEpoch(int $epoch): void;
    public function withEpoch(int $epoch): self;
    /**
     * Return the TOTP at the current time.
     *
     * @return non-empty-string
     */
    public function now(): string;
    /**
     * Get the period of time for OTP generation (a non-null positive integer, in second).
     */
    public function getPeriod(): int;
    public function expiresIn(): int;
    public function getEpoch(): int;
}
<?php

declare (strict_types=1);
namespace _ContaoManager\OTPHP;

use Exception;
use _ContaoManager\OTPHP\Exception\InvalidLabelException;
use _ContaoManager\OTPHP\Exception\InvalidParameterException;
use _ContaoManager\OTPHP\Exception\ParameterNotFoundException;
use _ContaoManager\OTPHP\Exception\SecretDecodingException;
use _ContaoManager\ParagonIE\ConstantTime\Base32;
use function array_key_exists;
use function chr;
use function count;
use function in_array;
use function is_int;
use function is_string;
use function sprintf;
use const STR_PAD_LEFT;
/**
 * @readonly
 */
abstract class OTP implements OTPInterface
{
    private const DEFAULT_SECRET_SIZE = 64;
    /**
     * @var array<non-empty-string, mixed>
     */
    private array $parameters = [];
    /**
     * @var non-empty-string|null
     */
    private null|string $issuer = null;
    /**
     * @var non-empty-string|null
     */
    private null|string $label = null;
    private bool $issuer_included_as_parameter = \true;
    /**
     * @param non-empty-string $secret
     */
    protected function __construct(string $secret)
    {
        $this->setSecret($secret);
    }
    public function getQrCodeUri(string $uri, string $placeholder): string
    {
        $provisioning_uri = urlencode($this->getProvisioningUri());
        return str_replace($placeholder, $provisioning_uri, $uri);
    }
    /**
     * @param 0|positive-int $input
     */
    public function at(int $input): string
    {
        return $this->generateOTP($input);
    }
    /**
     * @return array<non-empty-string, mixed>
     */
    public function getParameters(): array
    {
        $parameters = $this->parameters;
        if ($this->getIssuer() !== null && $this->isIssuerIncludedAsParameter() === \true) {
            $parameters['issuer'] = $this->getIssuer();
        }
        return $parameters;
    }
    public function getSecret(): string
    {
        $value = $this->getParameter('secret');
        is_string($value) && $value !== '' || throw new InvalidParameterException('Invalid "secret" parameter.', 'secret', $value);
        return $value;
    }
    public function getLabel(): null|string
    {
        return $this->label;
    }
    public function setLabel(string $label): void
    {
        $this->setParameter('label', $label);
    }
    public function withLabel(string $label): static
    {
        $otp = clone $this;
        $otp->setParameter('label', $label);
        return $otp;
    }
    public function getIssuer(): null|string
    {
        return $this->issuer;
    }
    public function setIssuer(string $issuer): void
    {
        $this->setParameter('issuer', $issuer);
    }
    public function withIssuer(string $issuer): static
    {
        $otp = clone $this;
        $otp->setParameter('issuer', $issuer);
        return $otp;
    }
    public function isIssuerIncludedAsParameter(): bool
    {
        return $this->issuer_included_as_parameter;
    }
    public function setIssuerIncludedAsParameter(bool $issuer_included_as_parameter): void
    {
        $this->issuer_included_as_parameter = $issuer_included_as_parameter;
    }
    public function withIssuerIncludedAsParameter(bool $issuer_included_as_parameter): static
    {
        $otp = clone $this;
        $otp->issuer_included_as_parameter = $issuer_included_as_parameter;
        return $otp;
    }
    public function getDigits(): int
    {
        $value = $this->getParameter('digits');
        is_int($value) && $value > 0 || throw new InvalidParameterException('Invalid "digits" parameter.', 'digits', $value);
        return $value;
    }
    public function getDigest(): string
    {
        $value = $this->getParameter('algorithm');
        is_string($value) && $value !== '' || throw new InvalidParameterException('Invalid "algorithm" parameter.', 'algorithm', $value);
        return $value;
    }
    public function hasParameter(string $parameter): bool
    {
        return array_key_exists($parameter, $this->parameters);
    }
    public function getParameter(string $parameter): mixed
    {
        if ($this->hasParameter($parameter)) {
            return $this->getParameters()[$parameter];
        }
        throw new ParameterNotFoundException(sprintf('Parameter "%s" does not exist', $parameter), $parameter);
    }
    public function setParameter(string $parameter, mixed $value): void
    {
        $map = $this->getParameterMap();
        if (array_key_exists($parameter, $map) === \true) {
            $callback = $map[$parameter];
            $value = $callback($value);
        }
        if (property_exists($this, $parameter)) {
            $this->{$parameter} = $value;
        } else {
            $this->parameters[$parameter] = $value;
        }
    }
    public function withParameter(string $parameter, mixed $value): static
    {
        $otp = clone $this;
        $otp->setParameter($parameter, $value);
        return $otp;
    }
    public function setSecret(string $secret): void
    {
        $this->setParameter('secret', $secret);
    }
    public function withSecret(string $secret): static
    {
        $otp = clone $this;
        $otp->setParameter('secret', $secret);
        return $otp;
    }
    public function setDigits(int $digits): void
    {
        $this->setParameter('digits', $digits);
    }
    public function withDigits(int $digits): static
    {
        $otp = clone $this;
        $otp->setParameter('digits', $digits);
        return $otp;
    }
    public function setDigest(string $digest): void
    {
        $this->setParameter('algorithm', $digest);
    }
    public function withDigest(string $digest): static
    {
        $otp = clone $this;
        $otp->setParameter('algorithm', $digest);
        return $otp;
    }
    /**
     * @param positive-int|null $secretSize
     *
     * @return non-empty-string
     */
    final protected static function generateSecret(?int $secretSize = null): string
    {
        $secretSize ??= self::DEFAULT_SECRET_SIZE;
        $secretSize > 0 || throw new InvalidParameterException('Secret size must be at least 1.', 'secretSize', $secretSize);
        return Base32::encodeUpper(random_bytes($secretSize));
    }
    /**
     * The OTP at the specified input.
     *
     * @param 0|positive-int $input
     *
     * @return non-empty-string
     */
    protected function generateOTP(int $input): string
    {
        $hash = hash_hmac($this->getDigest(), $this->intToByteString($input), $this->getDecodedSecret(), \true);
        $unpacked = unpack('C*', $hash);
        $unpacked !== \false || throw new InvalidParameterException('Invalid data.', 'hash', $hash);
        $hmac = array_values($unpacked);
        $offset = $hmac[count($hmac) - 1] & 0xf;
        $code = ($hmac[$offset] & 0x7f) << 24 | ($hmac[$offset + 1] & 0xff) << 16 | ($hmac[$offset + 2] & 0xff) << 8 | $hmac[$offset + 3] & 0xff;
        $otp = $code % 10 ** $this->getDigits();
        return str_pad((string) $otp, $this->getDigits(), '0', STR_PAD_LEFT);
    }
    /**
     * @param array<non-empty-string, mixed> $options
     */
    protected function filterOptions(array &$options): void
    {
        foreach (['algorithm' => 'sha1', 'period' => 30, 'digits' => 6] as $key => $default) {
            if (isset($options[$key]) && $default === $options[$key]) {
                unset($options[$key]);
            }
        }
        ksort($options);
    }
    /**
     * @param non-empty-string $type
     * @param array<non-empty-string, mixed> $options
     *
     * @return non-empty-string
     */
    protected function generateURI(string $type, array $options): string
    {
        $options = [...$options, ...$this->getParameters()];
        $this->filterOptions($options);
        $params = str_replace(['+', '%7E'], ['%20', '~'], http_build_query($options, '', '&'));
        return sprintf('otpauth://%s/%s?%s', $type, rawurlencode($this->buildProvisioningUriLabel()), $params);
    }
    /**
     * @param non-empty-string $safe
     * @param non-empty-string $user
     */
    protected function compareOTP(string $safe, string $user): bool
    {
        return hash_equals($safe, $user);
    }
    /**
     * @return array<non-empty-string, callable>
     */
    protected function getParameterMap(): array
    {
        return ['label' => function (string $value): string {
            $value !== '' || throw new InvalidLabelException('Label must not be empty.', 'label', $value);
            $this->validateLabel($value);
            return $value;
        }, 'secret' => static fn(string $value): string => strtoupper(trim($value, '=')), 'algorithm' => static function (string $value): string {
            $value = strtolower($value);
            in_array($value, hash_algos(), \true) || throw new InvalidParameterException(sprintf('The "%s" digest is not supported.', $value), 'algorithm', $value);
            return $value;
        }, 'digits' => static function ($value): int {
            $value > 0 || throw new InvalidParameterException('Digits must be at least 1.', 'digits', $value);
            return (int) $value;
        }, 'issuer' => function (string $value): string {
            $value !== '' || throw new InvalidLabelException('Issuer must not be empty.', 'issuer', $value);
            $this->hasColon($value) === \false || throw new InvalidLabelException('Issuer must not contain a colon.', 'issuer', $value);
            return $value;
        }];
    }
    /**
     * @return non-empty-string
     */
    private function getDecodedSecret(): string
    {
        try {
            $decoded = Base32::decodeUpper($this->getSecret());
        } catch (Exception) {
            throw new SecretDecodingException('Unable to decode the secret. Is it correctly base32 encoded?');
        }
        $decoded !== '' || throw new SecretDecodingException('The decoded secret must not be empty.');
        return $decoded;
    }
    private function intToByteString(int $int): string
    {
        $result = [];
        while ($int !== 0) {
            $result[] = chr($int & 0xff);
            $int >>= 8;
        }
        return str_pad(implode('', array_reverse($result)), 8, "\x00", STR_PAD_LEFT);
    }
    /**
     * @return non-empty-string
     */
    private function buildProvisioningUriLabel(): string
    {
        $issuer = $this->getIssuer();
        $label = $this->getLabel();
        return match (\true) {
            $issuer === null && $label === null => throw new InvalidLabelException('The label is not set. Either label or issuer must be set.', 'label'),
            $label !== null && $this->hasColon($label) => throw new InvalidLabelException('Label must not contain a colon.', 'label', $label),
            $issuer !== null && $label !== null => $issuer . ':' . $label,
            $issuer !== null => $issuer,
            default => $label,
        };
    }
    /**
     * Validates a label according to Google Authenticator spec:
     * label = accountname / issuer (":" / "%3A") *"%20" accountname
     * Neither issuer nor account name may themselves contain a colon.
     *
     * Valid examples:
     * - alice@gmail.com
     * - Provider1:Alice%20Smith
     * - Big%20Corporation%3A%20alice%40bigco.com
     *
     * @param non-empty-string $value
     */
    private function validateLabel(string $value): void
    {
        // Check for colon separators (literal or URL-encoded)
        $hasLiteralColon = str_contains($value, ':');
        $hasEncodedColon = str_contains($value, '%3A') || str_contains($value, '%3a');
        if (!$hasLiteralColon && !$hasEncodedColon) {
            // Simple label (account name only) - no colons allowed anywhere
            return;
        }
        // Label contains a separator - validate issuer:account format
        // Split by literal or encoded colon
        $parts = match (\true) {
            $hasLiteralColon => explode(':', $value, 2),
            default => preg_split('/%3[Aa]/', $value, 2),
        };
        if ($parts === \false || count($parts) !== 2) {
            throw new InvalidLabelException('Label must not contain a colon.', 'label', $value);
        }
        [$issuerPart, $accountPart] = $parts;
        // Remove leading %20 (spaces) from account part per spec: *"%20" accountname
        $accountPart = ltrim($accountPart, '%20');
        // Validate that neither part contains additional colons
        if ($this->hasColon($issuerPart) || $this->hasColon($accountPart)) {
            throw new InvalidLabelException('Neither issuer nor account name in label may contain a colon.', 'label', $value);
        }
    }
    /**
     * @param non-empty-string $value
     */
    private function hasColon(string $value): bool
    {
        $colons = [':', '%3A', '%3a'];
        foreach ($colons as $colon) {
            if (str_contains($value, $colon)) {
                return \true;
            }
        }
        return \false;
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\OTPHP;

use _ContaoManager\OTPHP\Exception\InvalidParameterException;
use function is_int;
/**
 * Note: This class is not marked as readonly because the verify() method
 * updates the counter state on successful verification, which is an intentional
 * side-effect to prevent OTP reuse.
 *
 * @see \OTPHP\Test\HOTPTest
 */
final class HOTP extends OTP implements HOTPInterface
{
    private const DEFAULT_WINDOW = 0;
    public static function create(null|string $secret = null, int $counter = self::DEFAULT_COUNTER, string $digest = self::DEFAULT_DIGEST, int $digits = self::DEFAULT_DIGITS, ?int $secretSize = null): self
    {
        $htop = $secret !== null ? self::createFromSecret($secret) : self::generate($secretSize);
        $htop->setCounter($counter);
        $htop->setDigest($digest);
        $htop->setDigits($digits);
        return $htop;
    }
    public static function createFromSecret(string $secret): self
    {
        $htop = new self($secret);
        $htop->setCounter(self::DEFAULT_COUNTER);
        $htop->setDigest(self::DEFAULT_DIGEST);
        $htop->setDigits(self::DEFAULT_DIGITS);
        return $htop;
    }
    /**
     * @param positive-int|null $secretSize
     */
    public static function generate(?int $secretSize = null): self
    {
        return self::createFromSecret(self::generateSecret($secretSize));
    }
    /**
     * @return 0|positive-int
     */
    public function getCounter(): int
    {
        $value = $this->getParameter('counter');
        is_int($value) && $value >= 0 || throw new InvalidParameterException('Invalid "counter" parameter.', 'counter', $value);
        return $value;
    }
    public function getProvisioningUri(): string
    {
        return $this->generateURI('hotp', ['counter' => $this->getCounter()]);
    }
    /**
     * If the counter is not provided, the OTP is verified at the actual counter.
     *
     * @param null|0|positive-int $counter
     */
    public function verify(string $otp, null|int $counter = null, null|int $window = null): bool
    {
        $counter >= 0 || throw new InvalidParameterException('The counter must be at least 0.', 'counter', $counter);
        if ($counter === null) {
            $counter = $this->getCounter();
        } elseif ($counter < $this->getCounter()) {
            return \false;
        }
        return $this->verifyOtpWithWindow($otp, $counter, $window);
    }
    public function setCounter(int $counter): void
    {
        $this->setParameter('counter', $counter);
    }
    public function withCounter(int $counter): self
    {
        $otp = clone $this;
        $otp->setParameter('counter', $counter);
        return $otp;
    }
    /**
     * @return array<non-empty-string, callable>
     */
    protected function getParameterMap(): array
    {
        return [...parent::getParameterMap(), ...['counter' => static function (mixed $value): int {
            $value = (int) $value;
            $value >= 0 || throw new InvalidParameterException('Counter must be at least 0.', 'counter', $value);
            return $value;
        }]];
    }
    private function updateCounter(int $counter): void
    {
        $this->setCounter($counter);
    }
    /**
     * @param null|0|positive-int $window
     */
    private function getWindow(null|int $window): int
    {
        return abs($window ?? self::DEFAULT_WINDOW);
    }
    /**
     * @param non-empty-string $otp
     * @param 0|positive-int $counter
     * @param null|0|positive-int $window
     */
    private function verifyOtpWithWindow(string $otp, int $counter, null|int $window): bool
    {
        $window = $this->getWindow($window);
        for ($i = $counter; $i <= $counter + $window; ++$i) {
            if ($this->compareOTP($this->at($i), $otp)) {
                $this->updateCounter($i + 1);
                return \true;
            }
        }
        return \false;
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\OTPHP;

interface HOTPInterface extends OTPInterface
{
    public const DEFAULT_COUNTER = 0;
    /**
     * The initial counter (a positive integer).
     */
    public function getCounter(): int;
    /**
     * Create a new HOTP object.
     *
     * If the secret is null, a random 64 bytes secret will be generated.
     *
     * @param null|non-empty-string $secret
     * @param 0|positive-int $counter
     * @param non-empty-string $digest
     * @param positive-int $digits
     *
     * @deprecated Deprecated since v11.1, use ::createFromSecret or ::generate instead
     */
    public static function create(null|string $secret = null, int $counter = 0, string $digest = 'sha1', int $digits = 6): self;
    /**
     * @deprecated Deprecated since v11.4, use {@see self::withCounter()} instead
     */
    public function setCounter(int $counter): void;
    public function withCounter(int $counter): self;
}
<?php

declare (strict_types=1);
namespace _ContaoManager\OTPHP;

use _ContaoManager\Psr\Clock\ClockInterface;
interface FactoryInterface
{
    /**
     * This method is the unique public method of the class. It can load a provisioning Uri and convert it into an OTP
     * object.
     *
     * @param non-empty-string $uri
     */
    public static function loadFromProvisioningUri(string $uri, ?ClockInterface $clock = null): OTPInterface;
}
<?php

declare (strict_types=1);
namespace _ContaoManager\OTPHP;

use _ContaoManager\OTPHP\Exception\InvalidProvisioningUriException;
use function array_key_exists;
use function is_string;
/**
 * @readonly
 *
 * @internal
 */
final class Url
{
    /**
     * @param non-empty-string $scheme
     * @param non-empty-string $host
     * @param non-empty-string $path
     * @param non-empty-string $secret
     * @param array<non-empty-string, mixed> $query
     */
    public function __construct(private readonly string $scheme, private readonly string $host, private readonly string $path, private readonly string $secret, private readonly array $query)
    {
    }
    /**
     * @return non-empty-string
     */
    public function getScheme(): string
    {
        return $this->scheme;
    }
    /**
     * @return non-empty-string
     */
    public function getHost(): string
    {
        return $this->host;
    }
    /**
     * @return non-empty-string
     */
    public function getPath(): string
    {
        return $this->path;
    }
    /**
     * @return non-empty-string
     */
    public function getSecret(): string
    {
        return $this->secret;
    }
    /**
     * @return array<non-empty-string, mixed>
     */
    public function getQuery(): array
    {
        return $this->query;
    }
    /**
     * @param non-empty-string $uri
     */
    public static function fromString(string $uri): self
    {
        $parsed_url = parse_url($uri);
        $parsed_url !== \false || throw new InvalidProvisioningUriException('Invalid URI.');
        foreach (['scheme', 'host', 'path', 'query'] as $key) {
            array_key_exists($key, $parsed_url) || throw new InvalidProvisioningUriException('Not a valid OTP provisioning URI');
        }
        $scheme = $parsed_url['scheme'] ?? null;
        $host = $parsed_url['host'] ?? null;
        $path = $parsed_url['path'] ?? null;
        $query = $parsed_url['query'] ?? null;
        $scheme === 'otpauth' || throw new InvalidProvisioningUriException('Not a valid OTP provisioning URI');
        is_string($host) || throw new InvalidProvisioningUriException('Invalid URI.');
        is_string($path) || throw new InvalidProvisioningUriException('Invalid URI.');
        is_string($query) || throw new InvalidProvisioningUriException('Invalid URI.');
        $parsedQuery = [];
        parse_str($query, $parsedQuery);
        array_key_exists('secret', $parsedQuery) || throw new InvalidProvisioningUriException('Not a valid OTP provisioning URI');
        $secret = $parsedQuery['secret'];
        unset($parsedQuery['secret']);
        return new self($scheme, $host, $path, $secret, $parsedQuery);
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\OTPHP\Exception;

use Throwable;
/**
 * Marker interface for all OTPHP exceptions.
 * This allows catching all OTPHP-specific exceptions while maintaining
 * backward compatibility with PHP's built-in exception types.
 */
interface OTPExceptionInterface extends Throwable
{
}
<?php

declare (strict_types=1);
namespace _ContaoManager\OTPHP\Exception;

use InvalidArgumentException;
use Throwable;
/**
 * Exception thrown when attempting to access a parameter that doesn't exist.
 */
final class ParameterNotFoundException extends InvalidArgumentException implements OTPExceptionInterface
{
    public function __construct(string $message, public readonly string $parameterName = '', int $code = 0, ?Throwable $previous = null)
    {
        parent::__construct($message, $code, $previous);
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\OTPHP\Exception;

use RuntimeException;
/**
 * Exception thrown when a secret cannot be decoded from Base32.
 */
final class SecretDecodingException extends RuntimeException implements OTPExceptionInterface
{
}
<?php

declare (strict_types=1);
namespace _ContaoManager\OTPHP\Exception;

use InvalidArgumentException;
use Throwable;
/**
 * Exception thrown when a label or issuer format is invalid.
 * This includes violations of the Google Authenticator label specification.
 */
final class InvalidLabelException extends InvalidArgumentException implements OTPExceptionInterface
{
    public function __construct(string $message, public readonly string $labelName = '', public readonly mixed $labelValue = null, int $code = 0, ?Throwable $previous = null)
    {
        parent::__construct($message, $code, $previous);
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\OTPHP\Exception;

use InvalidArgumentException;
/**
 * Exception thrown when a provisioning URI cannot be parsed or is invalid.
 * This includes: invalid format, wrong scheme, missing required parameters, unsupported OTP type.
 */
final class InvalidProvisioningUriException extends InvalidArgumentException implements OTPExceptionInterface
{
}
<?php

declare (strict_types=1);
namespace _ContaoManager\OTPHP\Exception;

use InvalidArgumentException;
use Throwable;
/**
 * Exception thrown when an OTP parameter has an invalid value.
 * This includes: secret, digits, algorithm, period, epoch, counter, secret size.
 */
final class InvalidParameterException extends InvalidArgumentException implements OTPExceptionInterface
{
    public function __construct(string $message, public readonly string $parameterName = '', public readonly mixed $parameterValue = null, int $code = 0, ?Throwable $previous = null)
    {
        parent::__construct($message, $code, $previous);
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\OTPHP;

use DateTimeImmutable;
use _ContaoManager\Psr\Clock\ClockInterface;
/**
 * @readonly
 *
 * @internal
 */
final class InternalClock implements ClockInterface
{
    public function now(): DateTimeImmutable
    {
        return new DateTimeImmutable();
    }
}
Copyright (c) 2020-2021 Doctrine Project

Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
# Doctrine Deprecations

A small (side-effect free by default) layer on top of
`trigger_error(E_USER_DEPRECATED)` or PSR-3 logging.

- no side-effects by default, making it a perfect fit for libraries that don't know how the error handler works they operate under
- options to avoid having to rely on error handlers global state by using PSR-3 logging
- deduplicate deprecation messages to avoid excessive triggering and reduce overhead

We recommend to collect Deprecations using a PSR logger instead of relying on
the global error handler.

## Usage from consumer perspective:

Enable Doctrine deprecations to be sent to a PSR3 logger:

```php
\Doctrine\Deprecations\Deprecation::enableWithPsrLogger($logger);
```

Enable Doctrine deprecations to be sent as `@trigger_error($message, E_USER_DEPRECATED)`
messages by setting the `DOCTRINE_DEPRECATIONS` environment variable to `trigger`.
Alternatively, call:

```php
\Doctrine\Deprecations\Deprecation::enableWithTriggerError();
```

If you only want to enable deprecation tracking, without logging or calling `trigger_error`
then set the `DOCTRINE_DEPRECATIONS` environment variable to `track`.
Alternatively, call:

```php
\Doctrine\Deprecations\Deprecation::enableTrackingDeprecations();
```

Tracking is enabled with all three modes and provides access to all triggered
deprecations and their individual count:

```php
$deprecations = \Doctrine\Deprecations\Deprecation::getTriggeredDeprecations();

foreach ($deprecations as $identifier => $count) {
    echo $identifier . " was triggered " . $count . " times\n";
}
```

### Suppressing Specific Deprecations

Disable triggering about specific deprecations:

```php
\Doctrine\Deprecations\Deprecation::ignoreDeprecations("https://link/to/deprecations-description-identifier");
```

Disable all deprecations from a package

```php
\Doctrine\Deprecations\Deprecation::ignorePackage("doctrine/orm");
```

### Other Operations

When used within PHPUnit or other tools that could collect multiple instances of the same deprecations
the deduplication can be disabled:

```php
\Doctrine\Deprecations\Deprecation::withoutDeduplication();
```

Disable deprecation tracking again:

```php
\Doctrine\Deprecations\Deprecation::disable();
```

## Usage from a library/producer perspective:

When you want to unconditionally trigger a deprecation even when called
from the library itself then the `trigger` method is the way to go:

```php
\Doctrine\Deprecations\Deprecation::trigger(
    "doctrine/orm",
    "https://link/to/deprecations-description",
    "message"
);
```

If variable arguments are provided at the end, they are used with `sprintf` on
the message.

```php
\Doctrine\Deprecations\Deprecation::trigger(
    "doctrine/orm",
    "https://github.com/doctrine/orm/issue/1234",
    "message %s %d",
    "foo",
    1234
);
```

When you want to trigger a deprecation only when it is called by a function
outside of the current package, but not trigger when the package itself is the cause,
then use:

```php
\Doctrine\Deprecations\Deprecation::triggerIfCalledFromOutside(
    "doctrine/orm",
    "https://link/to/deprecations-description",
    "message"
);
```

Based on the issue link each deprecation message is only triggered once per
request.

A limited stacktrace is included in the deprecation message to find the
offending location.

Note: A producer/library should never call `Deprecation::enableWith` methods
and leave the decision how to handle deprecations to application and
frameworks.

## Usage in PHPUnit tests

There is a `VerifyDeprecations` trait that you can use to make assertions on
the occurrence of deprecations within a test.

```php
use Doctrine\Deprecations\PHPUnit\VerifyDeprecations;

class MyTest extends TestCase
{
    use VerifyDeprecations;

    public function testSomethingDeprecation()
    {
        $this->expectDeprecationWithIdentifier('https://github.com/doctrine/orm/issue/1234');

        triggerTheCodeWithDeprecation();
    }

    public function testSomethingDeprecationFixed()
    {
        $this->expectNoDeprecationWithIdentifier('https://github.com/doctrine/orm/issue/1234');

        triggerTheCodeWithoutDeprecation();
    }
}
```

## Displaying deprecations after running a PHPUnit test suite

It is possible to integrate this library with PHPUnit to display all
deprecations triggered during the test suite execution.

```xml
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:noNamespaceSchemaLocation="vendor/phpunit/phpunit/phpunit.xsd"
         colors="true"
         bootstrap="vendor/autoload.php"
         displayDetailsOnTestsThatTriggerDeprecations="true"
         failOnDeprecation="true"
    >
    <!-- one attribute to display the deprecations, the other to fail the test suite -->

    <php>
        <!-- ensures native PHP deprecations are used -->
        <server name="DOCTRINE_DEPRECATIONS" value="trigger"/>
    </php>

    <!-- ensures the @ operator in @trigger_error is ignored -->
    <source ignoreSuppressionOfDeprecations="true">
        <include>
            <directory>src</directory>
        </include>
    </source>
</phpunit>
```

Note that you can still trigger Deprecations in your code, provided you use the
`#[IgnoreDeprecations]` to ignore them for tests that call it.

At the moment, it is not possible to disable deduplication with an environment
variable, but you can use a bootstrap file to achieve that:

```php
// tests/bootstrap.php
<?php

declare(strict_types=1);

require dirname(__DIR__) . '/vendor/autoload.php';

use Doctrine\Deprecations\Deprecation;

Deprecation::withoutDeduplication();
```

Then, reference that file in your PHPUnit configuration:

```xml
<phpunit …
        bootstrap="tests/bootstrap.php"
        …
    >
    …
</phpunit>
```

## What is a deprecation identifier?

An identifier for deprecations is just a link to any resource, most often a
Github Issue or Pull Request explaining the deprecation and potentially its
alternative.
{
    "name": "doctrine\/deprecations",
    "description": "A small layer on top of trigger_error(E_USER_DEPRECATED) or PSR-3 logging with options to disable all deprecations or selectively for packages.",
    "license": "MIT",
    "type": "library",
    "homepage": "https:\/\/www.doctrine-project.org\/",
    "require": {
        "php": "^7.1 || ^8.0"
    },
    "require-dev": {
        "doctrine\/coding-standard": "^9 || ^12 || ^14",
        "phpstan\/phpstan": "1.4.10 || 2.1.30",
        "phpstan\/phpstan-phpunit": "^1.0 || ^2",
        "phpunit\/phpunit": "^7.5 || ^8.5 || ^9.6 || ^10.5 || ^11.5 || ^12.4 || ^13.0",
        "psr\/log": "^1 || ^2 || ^3"
    },
    "conflict": {
        "phpunit\/phpunit": "<=7.5 || >=14"
    },
    "suggest": {
        "psr\/log": "Allows logging deprecations via PSR-3 logger implementation"
    },
    "autoload": {
        "psr-4": {
            "_ContaoManager\\Doctrine\\Deprecations\\": "src"
        }
    },
    "autoload-dev": {
        "psr-4": {
            "_ContaoManager\\DeprecationTests\\": "test_fixtures\/src",
            "_ContaoManager\\Doctrine\\Foo\\": "test_fixtures\/vendor\/doctrine\/foo"
        }
    },
    "config": {
        "allow-plugins": {
            "dealerdirect\/phpcodesniffer-composer-installer": true
        }
    }
}<?php

declare (strict_types=1);
namespace _ContaoManager\Doctrine\Deprecations\PHPUnit;

use _ContaoManager\Doctrine\Deprecations\Deprecation;
use _ContaoManager\PHPUnit\Framework\Attributes\After;
use _ContaoManager\PHPUnit\Framework\Attributes\Before;
use function sprintf;
trait VerifyDeprecations
{
    /** @var array<string,int> */
    private $doctrineDeprecationsExpectations = [];
    /** @var array<string,int> */
    private $doctrineNoDeprecationsExpectations = [];
    public function expectDeprecationWithIdentifier(string $identifier): void
    {
        $this->doctrineDeprecationsExpectations[$identifier] = Deprecation::getTriggeredDeprecations()[$identifier] ?? 0;
    }
    public function expectNoDeprecationWithIdentifier(string $identifier): void
    {
        $this->doctrineNoDeprecationsExpectations[$identifier] = Deprecation::getTriggeredDeprecations()[$identifier] ?? 0;
    }
    /** @before */
    #[Before]
    public function enableDeprecationTracking(): void
    {
        Deprecation::enableTrackingDeprecations();
    }
    /** @after */
    #[After]
    public function verifyDeprecationsAreTriggered(): void
    {
        foreach ($this->doctrineDeprecationsExpectations as $identifier => $expectation) {
            $actualCount = Deprecation::getTriggeredDeprecations()[$identifier] ?? 0;
            $this->assertTrue($actualCount > $expectation, sprintf("Expected deprecation with identifier '%s' was not triggered by code executed in test.", $identifier));
        }
        foreach ($this->doctrineNoDeprecationsExpectations as $identifier => $expectation) {
            $actualCount = Deprecation::getTriggeredDeprecations()[$identifier] ?? 0;
            $this->assertTrue($actualCount === $expectation, sprintf("Deprecation with identifier '%s' was triggered by code executed in test, but expected not to.", $identifier));
        }
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\Doctrine\Deprecations;

use _ContaoManager\Psr\Log\LoggerInterface;
use function array_key_exists;
use function array_reduce;
use function assert;
use function debug_backtrace;
use function sprintf;
use function str_replace;
use function strpos;
use function strrpos;
use function substr;
use function trigger_error;
use const DEBUG_BACKTRACE_IGNORE_ARGS;
use const DIRECTORY_SEPARATOR;
use const E_USER_DEPRECATED;
/**
 * Manages Deprecation logging in different ways.
 *
 * By default triggered exceptions are not logged.
 *
 * To enable different deprecation logging mechanisms you can call the
 * following methods:
 *
 *  - Minimal collection of deprecations via getTriggeredDeprecations()
 *    \Doctrine\Deprecations\Deprecation::enableTrackingDeprecations();
 *
 *  - Uses @trigger_error with E_USER_DEPRECATED
 *    \Doctrine\Deprecations\Deprecation::enableWithTriggerError();
 *
 *  - Sends deprecation messages via a PSR-3 logger
 *    \Doctrine\Deprecations\Deprecation::enableWithPsrLogger($logger);
 *
 * Packages that trigger deprecations should use the `trigger()` or
 * `triggerIfCalledFromOutside()` methods.
 */
class Deprecation
{
    private const TYPE_NONE = 0;
    private const TYPE_TRACK_DEPRECATIONS = 1;
    private const TYPE_TRIGGER_ERROR = 2;
    private const TYPE_PSR_LOGGER = 4;
    /** @var int-mask-of<self::TYPE_*>|null */
    private static $type;
    /** @var LoggerInterface|null */
    private static $logger;
    /** @var array<string,bool> */
    private static $ignoredPackages = [];
    /** @var array<string,int> */
    private static $triggeredDeprecations = [];
    /** @var array<string,bool> */
    private static $ignoredLinks = [];
    /** @var bool */
    private static $deduplication = \true;
    /**
     * Trigger a deprecation for the given package and identfier.
     *
     * The link should point to a Github issue or Wiki entry detailing the
     * deprecation. It is additionally used to de-duplicate the trigger of the
     * same deprecation during a request.
     *
     * @param float|int|string $args
     */
    public static function trigger(string $package, string $link, string $message, ...$args): void
    {
        $type = self::$type ?? self::getTypeFromEnv();
        if ($type === self::TYPE_NONE) {
            return;
        }
        if (isset(self::$ignoredLinks[$link])) {
            return;
        }
        if (array_key_exists($link, self::$triggeredDeprecations)) {
            self::$triggeredDeprecations[$link]++;
        } else {
            self::$triggeredDeprecations[$link] = 1;
        }
        if (self::$deduplication === \true && self::$triggeredDeprecations[$link] > 1) {
            return;
        }
        if (isset(self::$ignoredPackages[$package])) {
            return;
        }
        $backtrace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 2);
        $message = sprintf($message, ...$args);
        self::delegateTriggerToBackend($message, $backtrace, $link, $package);
    }
    /**
     * Trigger a deprecation for the given package and identifier when called from outside.
     *
     * "Outside" means we assume that $package is currently installed as a
     * dependency and the caller is not a file in that package. When $package
     * is installed as a root package then deprecations triggered from the
     * tests folder are also considered "outside".
     *
     * This deprecation method assumes that you are using Composer to install
     * the dependency and are using the default /vendor/ folder and not a
     * Composer plugin to change the install location. The assumption is also
     * that $package is the exact composer packge name.
     *
     * Compared to {@link trigger()} this method causes some overhead when
     * deprecation tracking is enabled even during deduplication, because it
     * needs to call {@link debug_backtrace()}
     *
     * @param float|int|string $args
     */
    public static function triggerIfCalledFromOutside(string $package, string $link, string $message, ...$args): void
    {
        $type = self::$type ?? self::getTypeFromEnv();
        if ($type === self::TYPE_NONE) {
            return;
        }
        $backtrace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 2);
        // first check that the caller is not from a tests folder, in which case we always let deprecations pass
        if (isset($backtrace[1]['file'], $backtrace[0]['file']) && strpos($backtrace[1]['file'], DIRECTORY_SEPARATOR . 'tests' . DIRECTORY_SEPARATOR) === \false) {
            $path = DIRECTORY_SEPARATOR . 'vendor' . DIRECTORY_SEPARATOR . str_replace('/', DIRECTORY_SEPARATOR, $package) . DIRECTORY_SEPARATOR;
            if (strpos($backtrace[0]['file'], $path) === \false) {
                return;
            }
            if (strpos($backtrace[1]['file'], $path) !== \false) {
                return;
            }
        }
        if (isset(self::$ignoredLinks[$link])) {
            return;
        }
        if (array_key_exists($link, self::$triggeredDeprecations)) {
            self::$triggeredDeprecations[$link]++;
        } else {
            self::$triggeredDeprecations[$link] = 1;
        }
        if (self::$deduplication === \true && self::$triggeredDeprecations[$link] > 1) {
            return;
        }
        if (isset(self::$ignoredPackages[$package])) {
            return;
        }
        $message = sprintf($message, ...$args);
        self::delegateTriggerToBackend($message, $backtrace, $link, $package);
    }
    /** @param list<array{function: string, line?: int, file?: string, class?: class-string, type?: string, args?: mixed[], object?: object}> $backtrace */
    private static function delegateTriggerToBackend(string $message, array $backtrace, string $link, string $package): void
    {
        $type = self::$type ?? self::getTypeFromEnv();
        if (($type & self::TYPE_PSR_LOGGER) > 0) {
            $context = ['file' => $backtrace[0]['file'] ?? null, 'line' => $backtrace[0]['line'] ?? null, 'package' => $package, 'link' => $link];
            assert(self::$logger !== null);
            self::$logger->notice($message, $context);
        }
        if (!(($type & self::TYPE_TRIGGER_ERROR) > 0)) {
            return;
        }
        $message .= sprintf(' (%s:%d called by %s:%d, %s, package %s)', self::basename($backtrace[0]['file'] ?? 'native code'), $backtrace[0]['line'] ?? 0, self::basename($backtrace[1]['file'] ?? 'native code'), $backtrace[1]['line'] ?? 0, $link, $package);
        @trigger_error($message, E_USER_DEPRECATED);
    }
    /**
     * A non-local-aware version of PHPs basename function.
     */
    private static function basename(string $filename): string
    {
        $pos = strrpos($filename, DIRECTORY_SEPARATOR);
        if ($pos === \false) {
            return $filename;
        }
        return substr($filename, $pos + 1);
    }
    public static function enableTrackingDeprecations(): void
    {
        self::$type = self::$type ?? self::getTypeFromEnv();
        self::$type |= self::TYPE_TRACK_DEPRECATIONS;
    }
    public static function enableWithTriggerError(): void
    {
        self::$type = self::$type ?? self::getTypeFromEnv();
        self::$type |= self::TYPE_TRIGGER_ERROR;
    }
    public static function enableWithPsrLogger(LoggerInterface $logger): void
    {
        self::$type = self::$type ?? self::getTypeFromEnv();
        self::$type |= self::TYPE_PSR_LOGGER;
        self::$logger = $logger;
    }
    public static function withoutDeduplication(): void
    {
        self::$deduplication = \false;
    }
    public static function disable(): void
    {
        self::$type = self::TYPE_NONE;
        self::$logger = null;
        self::$deduplication = \true;
        self::$ignoredLinks = [];
        foreach (self::$triggeredDeprecations as $link => $count) {
            self::$triggeredDeprecations[$link] = 0;
        }
    }
    public static function ignorePackage(string $packageName): void
    {
        self::$ignoredPackages[$packageName] = \true;
    }
    public static function ignoreDeprecations(string ...$links): void
    {
        foreach ($links as $link) {
            self::$ignoredLinks[$link] = \true;
        }
    }
    public static function getUniqueTriggeredDeprecationsCount(): int
    {
        return array_reduce(self::$triggeredDeprecations, static function (int $carry, int $count) {
            return $carry + $count;
        }, 0);
    }
    /**
     * Returns each triggered deprecation link identifier and the amount of occurrences.
     *
     * @return array<string,int>
     */
    public static function getTriggeredDeprecations(): array
    {
        return self::$triggeredDeprecations;
    }
    /** @return int-mask-of<self::TYPE_*> */
    private static function getTypeFromEnv(): int
    {
        switch ($_SERVER['DOCTRINE_DEPRECATIONS'] ?? $_ENV['DOCTRINE_DEPRECATIONS'] ?? null) {
            case 'trigger':
                self::$type = self::TYPE_TRIGGER_ERROR;
                break;
            case 'track':
                self::$type = self::TYPE_TRACK_DEPRECATIONS;
                break;
            default:
                self::$type = self::TYPE_NONE;
                break;
        }
        return self::$type;
    }
}
Copyright (c) 2011, Neuman Vong

All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

    * Redistributions of source code must retain the above copyright
      notice, this list of conditions and the following disclaimer.

    * Redistributions in binary form must reproduce the above
      copyright notice, this list of conditions and the following
      disclaimer in the documentation and/or other materials provided
      with the distribution.

    * Neither the name of the copyright holder nor the names of other
      contributors may be used to endorse or promote products derived
      from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
# Changelog

## [7.0.5](https://github.com/firebase/php-jwt/compare/v7.0.4...v7.0.5) (2026-03-31)


### Bug Fixes

* RSA from JWK sometimes returns empty Instance ([#628](https://github.com/firebase/php-jwt/issues/628)) ([b4c78aa](https://github.com/firebase/php-jwt/commit/b4c78aa731664122198ad36c0033aa29e807397a))

## [7.0.4](https://github.com/firebase/php-jwt/compare/v7.0.3...v7.0.4) (2026-03-27)


### Bug Fixes

* readme examples, add tests for all examples ([#626](https://github.com/firebase/php-jwt/issues/626)) ([510a00c](https://github.com/firebase/php-jwt/commit/510a00c0e6353bc7d68412fab67e57a13954cb46))
* use urlsafeB64Decode everywhere ([#627](https://github.com/firebase/php-jwt/issues/627)) ([b889495](https://github.com/firebase/php-jwt/commit/b889495c83ddc3f3885ca3f0b65b41b1cb37a3b1))

## [7.0.3](https://github.com/firebase/php-jwt/compare/v7.0.2...v7.0.3) (2026-02-18)


### Miscellaneous Chores

* add environment for Release Please job ([#619](https://github.com/firebase/php-jwt/issues/619)) ([300fd02](https://github.com/firebase/php-jwt/commit/300fd02c883f096c9067df652dbd23f62cb5e2a7))

## [7.0.2](https://github.com/firebase/php-jwt/compare/v7.0.1...v7.0.2) (2025-12-16)


### Bug Fixes

* add key length validation for ec keys ([#615](https://github.com/firebase/php-jwt/issues/615)) ([7044f9a](https://github.com/firebase/php-jwt/commit/7044f9ae7e7d175d28cca71714feb236f1c0e252))

## [7.0.0](https://github.com/firebase/php-jwt/compare/v6.11.1...v7.0.0) (2025-12-15)


### ⚠️ ⚠️ ⚠️  Security Fixes ⚠️ ⚠️ ⚠️ 
 * add key size validation ([#613](https://github.com/firebase/php-jwt/issues/613)) ([6b80341](https://github.com/firebase/php-jwt/commit/6b80341bf57838ea2d011487917337901cd71576))
 **NOTE**: This fix will cause keys with a size below the minimally allowed size to break. 

### Features

* add SensitiveParameter attribute to security-critical parameters ([#603](https://github.com/firebase/php-jwt/issues/603)) ([4dbfac0](https://github.com/firebase/php-jwt/commit/4dbfac0260eeb0e9e643063c99998e3219cc539b))
* store timestamp in `ExpiredException` ([#604](https://github.com/firebase/php-jwt/issues/604)) ([f174826](https://github.com/firebase/php-jwt/commit/f1748260d218a856b6a0c23715ac7fae1d7ca95b))


### Bug Fixes

* validate iat and nbf on payload ([#568](https://github.com/firebase/php-jwt/issues/568)) ([953b2c8](https://github.com/firebase/php-jwt/commit/953b2c88bb445b7e3bb82a5141928f13d7343afd))

## [6.11.1](https://github.com/firebase/php-jwt/compare/v6.11.0...v6.11.1) (2025-04-09)


### Bug Fixes

* update error text for consistency ([#528](https://github.com/firebase/php-jwt/issues/528)) ([c11113a](https://github.com/firebase/php-jwt/commit/c11113afa13265e016a669e75494b9203b8a7775))

## [6.11.0](https://github.com/firebase/php-jwt/compare/v6.10.2...v6.11.0) (2025-01-23)


### Features

* support octet typed JWK ([#587](https://github.com/firebase/php-jwt/issues/587)) ([7cb8a26](https://github.com/firebase/php-jwt/commit/7cb8a265fa81edf2fa6ef8098f5bc5ae573c33ad))


### Bug Fixes

* refactor constructor Key to use PHP 8.0 syntax ([#577](https://github.com/firebase/php-jwt/issues/577)) ([29fa2ce](https://github.com/firebase/php-jwt/commit/29fa2ce9e0582cd397711eec1e80c05ce20fabca))

## [6.10.2](https://github.com/firebase/php-jwt/compare/v6.10.1...v6.10.2) (2024-11-24)


### Bug Fixes

* Mitigate PHP8.4 deprecation warnings ([#570](https://github.com/firebase/php-jwt/issues/570)) ([76808fa](https://github.com/firebase/php-jwt/commit/76808fa227f3811aa5cdb3bf81233714b799a5b5))
* support php 8.4 ([#583](https://github.com/firebase/php-jwt/issues/583)) ([e3d68b0](https://github.com/firebase/php-jwt/commit/e3d68b044421339443c74199edd020e03fb1887e))

## [6.10.1](https://github.com/firebase/php-jwt/compare/v6.10.0...v6.10.1) (2024-05-18)


### Bug Fixes

* ensure ratelimit expiry is set every time ([#556](https://github.com/firebase/php-jwt/issues/556)) ([09cb208](https://github.com/firebase/php-jwt/commit/09cb2081c2c3bc0f61e2f2a5fbea5741f7498648))
* ratelimit cache expiration ([#550](https://github.com/firebase/php-jwt/issues/550)) ([dda7250](https://github.com/firebase/php-jwt/commit/dda725033585ece30ff8cae8937320d7e9f18bae))

## [6.10.0](https://github.com/firebase/php-jwt/compare/v6.9.0...v6.10.0) (2023-11-28)


### Features

* allow typ header override ([#546](https://github.com/firebase/php-jwt/issues/546)) ([79cb30b](https://github.com/firebase/php-jwt/commit/79cb30b729a22931b2fbd6b53f20629a83031ba9))

## [6.9.0](https://github.com/firebase/php-jwt/compare/v6.8.1...v6.9.0) (2023-10-04)


### Features

* add payload to jwt exception ([#521](https://github.com/firebase/php-jwt/issues/521)) ([175edf9](https://github.com/firebase/php-jwt/commit/175edf958bb61922ec135b2333acf5622f2238a2))

## [6.8.1](https://github.com/firebase/php-jwt/compare/v6.8.0...v6.8.1) (2023-07-14)


### Bug Fixes

* accept float claims but round down to ignore them ([#492](https://github.com/firebase/php-jwt/issues/492)) ([3936842](https://github.com/firebase/php-jwt/commit/39368423beeaacb3002afa7dcb75baebf204fe7e))
* different BeforeValidException messages for nbf and iat ([#526](https://github.com/firebase/php-jwt/issues/526)) ([0a53cf2](https://github.com/firebase/php-jwt/commit/0a53cf2986e45c2bcbf1a269f313ebf56a154ee4))

## [6.8.0](https://github.com/firebase/php-jwt/compare/v6.7.0...v6.8.0) (2023-06-14)


### Features

* add support for P-384 curve ([#515](https://github.com/firebase/php-jwt/issues/515)) ([5de4323](https://github.com/firebase/php-jwt/commit/5de4323f4baf4d70bca8663bd87682a69c656c3d))


### Bug Fixes

* handle invalid http responses ([#508](https://github.com/firebase/php-jwt/issues/508)) ([91c39c7](https://github.com/firebase/php-jwt/commit/91c39c72b22fc3e1191e574089552c1f2041c718))

## [6.7.0](https://github.com/firebase/php-jwt/compare/v6.6.0...v6.7.0) (2023-06-14)


### Features

* add ed25519 support to JWK (public keys) ([#452](https://github.com/firebase/php-jwt/issues/452)) ([e53979a](https://github.com/firebase/php-jwt/commit/e53979abae927de916a75b9d239cfda8ce32be2a))

## [6.6.0](https://github.com/firebase/php-jwt/compare/v6.5.0...v6.6.0) (2023-06-13)


### Features

* allow get headers when decoding token ([#442](https://github.com/firebase/php-jwt/issues/442)) ([fb85f47](https://github.com/firebase/php-jwt/commit/fb85f47cfaeffdd94faf8defdf07164abcdad6c3))


### Bug Fixes

* only check iat if nbf is not used ([#493](https://github.com/firebase/php-jwt/issues/493)) ([398ccd2](https://github.com/firebase/php-jwt/commit/398ccd25ea12fa84b9e4f1085d5ff448c21ec797))

## [6.5.0](https://github.com/firebase/php-jwt/compare/v6.4.0...v6.5.0) (2023-05-12)


### Bug Fixes

* allow KID of '0' ([#505](https://github.com/firebase/php-jwt/issues/505)) ([9dc46a9](https://github.com/firebase/php-jwt/commit/9dc46a9c3e5801294249cfd2554c5363c9f9326a))


### Miscellaneous Chores

* drop support for PHP 7.3 ([#495](https://github.com/firebase/php-jwt/issues/495))

## [6.4.0](https://github.com/firebase/php-jwt/compare/v6.3.2...v6.4.0) (2023-02-08)


### Features

* add support for W3C ES256K ([#462](https://github.com/firebase/php-jwt/issues/462)) ([213924f](https://github.com/firebase/php-jwt/commit/213924f51936291fbbca99158b11bd4ae56c2c95))
* improve caching by only decoding jwks when necessary ([#486](https://github.com/firebase/php-jwt/issues/486)) ([78d3ed1](https://github.com/firebase/php-jwt/commit/78d3ed1073553f7d0bbffa6c2010009a0d483d5c))

## [6.3.2](https://github.com/firebase/php-jwt/compare/v6.3.1...v6.3.2) (2022-11-01)


### Bug Fixes

* check kid before using as array index ([bad1b04](https://github.com/firebase/php-jwt/commit/bad1b040d0c736bbf86814c6b5ae614f517cf7bd))

## [6.3.1](https://github.com/firebase/php-jwt/compare/v6.3.0...v6.3.1) (2022-11-01)


### Bug Fixes

* casing of GET for PSR compat ([#451](https://github.com/firebase/php-jwt/issues/451)) ([60b52b7](https://github.com/firebase/php-jwt/commit/60b52b71978790eafcf3b95cfbd83db0439e8d22))
* string interpolation format for php 8.2 ([#446](https://github.com/firebase/php-jwt/issues/446)) ([2e07d8a](https://github.com/firebase/php-jwt/commit/2e07d8a1524d12b69b110ad649f17461d068b8f2))

## 6.3.0 / 2022-07-15

 - Added ES256 support to JWK parsing ([#399](https://github.com/firebase/php-jwt/pull/399))
 - Fixed potential caching error in `CachedKeySet` by caching jwks as strings ([#435](https://github.com/firebase/php-jwt/pull/435))

## 6.2.0 / 2022-05-14

 - Added `CachedKeySet` ([#397](https://github.com/firebase/php-jwt/pull/397))
 - Added `$defaultAlg` parameter to `JWT::parseKey` and `JWT::parseKeySet` ([#426](https://github.com/firebase/php-jwt/pull/426)).

## 6.1.0 / 2022-03-23

 - Drop support for PHP 5.3, 5.4, 5.5, 5.6, and 7.0
 - Add parameter typing and return types where possible

## 6.0.0 / 2022-01-24

 - **Backwards-Compatibility Breaking Changes**: See the [Release Notes](https://github.com/firebase/php-jwt/releases/tag/v6.0.0) for more information.
 - New Key object to prevent key/algorithm type confusion (#365)
 - Add JWK support (#273)
 - Add ES256 support (#256)
 - Add ES384 support (#324)
 - Add Ed25519 support (#343)

## 5.0.0 / 2017-06-26
- Support RS384 and RS512.
  See [#117](https://github.com/firebase/php-jwt/pull/117). Thanks [@joostfaassen](https://github.com/joostfaassen)!
- Add an example for RS256 openssl.
  See [#125](https://github.com/firebase/php-jwt/pull/125). Thanks [@akeeman](https://github.com/akeeman)!
- Detect invalid Base64 encoding in signature.
  See [#162](https://github.com/firebase/php-jwt/pull/162). Thanks [@psignoret](https://github.com/psignoret)!
- Update `JWT::verify` to handle OpenSSL errors.
  See [#159](https://github.com/firebase/php-jwt/pull/159). Thanks [@bshaffer](https://github.com/bshaffer)!
- Add `array` type hinting to `decode` method
  See [#101](https://github.com/firebase/php-jwt/pull/101). Thanks [@hywak](https://github.com/hywak)!
- Add all JSON error types.
  See [#110](https://github.com/firebase/php-jwt/pull/110). Thanks [@gbalduzzi](https://github.com/gbalduzzi)!
- Bugfix 'kid' not in given key list.
  See [#129](https://github.com/firebase/php-jwt/pull/129). Thanks [@stampycode](https://github.com/stampycode)!
- Miscellaneous cleanup, documentation and test fixes.
  See [#107](https://github.com/firebase/php-jwt/pull/107), [#115](https://github.com/firebase/php-jwt/pull/115),
  [#160](https://github.com/firebase/php-jwt/pull/160), [#161](https://github.com/firebase/php-jwt/pull/161), and
  [#165](https://github.com/firebase/php-jwt/pull/165). Thanks [@akeeman](https://github.com/akeeman),
  [@chinedufn](https://github.com/chinedufn), and [@bshaffer](https://github.com/bshaffer)!

## 4.0.0 / 2016-07-17
- Add support for late static binding. See [#88](https://github.com/firebase/php-jwt/pull/88) for details. Thanks to [@chappy84](https://github.com/chappy84)!
- Use static `$timestamp` instead of `time()` to improve unit testing. See [#93](https://github.com/firebase/php-jwt/pull/93) for details. Thanks to [@josephmcdermott](https://github.com/josephmcdermott)!
- Fixes to exceptions classes. See [#81](https://github.com/firebase/php-jwt/pull/81) for details. Thanks to [@Maks3w](https://github.com/Maks3w)!
- Fixes to PHPDoc. See [#76](https://github.com/firebase/php-jwt/pull/76) for details. Thanks to [@akeeman](https://github.com/akeeman)!

## 3.0.0 / 2015-07-22
- Minimum PHP version updated from `5.2.0` to `5.3.0`.
- Add `\Firebase\JWT` namespace. See
[#59](https://github.com/firebase/php-jwt/pull/59) for details. Thanks to
[@Dashron](https://github.com/Dashron)!
- Require a non-empty key to decode and verify a JWT. See
[#60](https://github.com/firebase/php-jwt/pull/60) for details. Thanks to
[@sjones608](https://github.com/sjones608)!
- Cleaner documentation blocks in the code. See
[#62](https://github.com/firebase/php-jwt/pull/62) for details. Thanks to
[@johanderuijter](https://github.com/johanderuijter)!

## 2.2.0 / 2015-06-22
- Add support for adding custom, optional JWT headers to `JWT::encode()`. See
[#53](https://github.com/firebase/php-jwt/pull/53/files) for details. Thanks to
[@mcocaro](https://github.com/mcocaro)!

## 2.1.0 / 2015-05-20
- Add support for adding a leeway to `JWT:decode()` that accounts for clock skew
between signing and verifying entities. Thanks to [@lcabral](https://github.com/lcabral)!
- Add support for passing an object implementing the `ArrayAccess` interface for
`$keys` argument in `JWT::decode()`. Thanks to [@aztech-dev](https://github.com/aztech-dev)!

## 2.0.0 / 2015-04-01
- **Note**: It is strongly recommended that you update to > v2.0.0 to address
  known security vulnerabilities in prior versions when both symmetric and
  asymmetric keys are used together.
- Update signature for `JWT::decode(...)` to require an array of supported
  algorithms to use when verifying token signatures.
![Build Status](https://github.com/firebase/php-jwt/actions/workflows/tests.yml/badge.svg)
[![Latest Stable Version](https://poser.pugx.org/firebase/php-jwt/v/stable)](https://packagist.org/packages/firebase/php-jwt)
[![Total Downloads](https://poser.pugx.org/firebase/php-jwt/downloads)](https://packagist.org/packages/firebase/php-jwt)
[![License](https://poser.pugx.org/firebase/php-jwt/license)](https://packagist.org/packages/firebase/php-jwt)

PHP-JWT
=======
A simple library to encode and decode JSON Web Tokens (JWT) in PHP, conforming to [RFC 7519](https://tools.ietf.org/html/rfc7519).

Installation
------------

Use composer to manage your dependencies and download PHP-JWT:

```bash
composer require firebase/php-jwt
```

Optionally, install the `paragonie/sodium_compat` package from composer if your
php env does not have libsodium installed:

```bash
composer require paragonie/sodium_compat
```

## Example

```php
use Firebase\JWT\JWT;
use Firebase\JWT\Key;

$key = 'example_key_of_sufficient_length';
$payload = [
    'iss' => 'example.org',
    'aud' => 'example.com',
    'iat' => 1356999524,
    'nbf' => 1357000000
];

/**
 * IMPORTANT:
 * You must specify supported algorithms for your application. See
 * https://tools.ietf.org/html/draft-ietf-jose-json-web-algorithms-40
 * for a list of spec-compliant algorithms.
 */
$jwt = JWT::encode($payload, $key, 'HS256');
$decoded = JWT::decode($jwt, new Key($key, 'HS256'));
print_r($decoded);

// Pass a stdClass in as the third parameter to get the decoded header values
$headers = new stdClass();
$decoded = JWT::decode($jwt, new Key($key, 'HS256'), $headers);
print_r($headers);

/*
 NOTE: This will now be an object instead of an associative array. To get
 an associative array, you will need to cast it as such:
*/

$decoded_array = (array) $decoded;

/**
 * You can add a leeway to account for when there is a clock skew times between
 * the signing and verifying servers. It is recommended that this leeway should
 * not be bigger than a few minutes.
 *
 * Source: http://self-issued.info/docs/draft-ietf-oauth-json-web-token.html#nbfDef
 */
JWT::$leeway = 60; // $leeway in seconds
$decoded = JWT::decode($jwt, new Key($key, 'HS256'));
```

## Example encode/decode headers

Decoding the JWT headers without verifying the JWT first is NOT recommended, and is not supported by
this library. This is because without verifying the JWT, the header values could have been tampered with.
Any value pulled from an unverified header should be treated as if it could be any string sent in from an
attacker.  If this is something you still want to do in your application for whatever reason, it's possible to
decode the header values manually simply by calling `json_decode` and `base64_decode` on the JWT
header part:
```php
use Firebase\JWT\JWT;

$key = 'example_key_of_sufficient_length';
$payload = [
    'iss' => 'example.org',
    'aud' => 'example.com',
    'iat' => 1356999524,
    'nbf' => 1357000000
];

$headers = [
    'x-forwarded-for' => 'www.google.com'
];

// Encode headers in the JWT string
$jwt = JWT::encode($payload, $key, 'HS256', null, $headers);

// Decode headers from the JWT string WITHOUT validation
// **IMPORTANT**: This operation is vulnerable to attacks, as the JWT has not yet been verified.
// These headers could be any value sent by an attacker.
list($headersB64, $payloadB64, $sig) = explode('.', $jwt);
$decoded = json_decode(base64_decode($headersB64), true);

print_r($decoded);
```

## Example with RS256 (openssl)

```php
use Firebase\JWT\JWT;
use Firebase\JWT\Key;

$privateKey = <<<EOD
-----BEGIN RSA PRIVATE KEY-----
MIIEowIBAAKCAQEAuzWHNM5f+amCjQztc5QTfJfzCC5J4nuW+L/aOxZ4f8J3Frew
M2c/dufrnmedsApb0By7WhaHlcqCh/ScAPyJhzkPYLae7bTVro3hok0zDITR8F6S
JGL42JAEUk+ILkPI+DONM0+3vzk6Kvfe548tu4czCuqU8BGVOlnp6IqBHhAswNMM
78pos/2z0CjPM4tbeXqSTTbNkXRboxjU29vSopcT51koWOgiTf3C7nJUoMWZHZI5
HqnIhPAG9yv8HAgNk6CMk2CadVHDo4IxjxTzTTqo1SCSH2pooJl9O8at6kkRYsrZ
WwsKlOFE2LUce7ObnXsYihStBUDoeBQlGG/BwQIDAQABAoIBAFtGaOqNKGwggn9k
6yzr6GhZ6Wt2rh1Xpq8XUz514UBhPxD7dFRLpbzCrLVpzY80LbmVGJ9+1pJozyWc
VKeCeUdNwbqkr240Oe7GTFmGjDoxU+5/HX/SJYPpC8JZ9oqgEA87iz+WQX9hVoP2
oF6EB4ckDvXmk8FMwVZW2l2/kd5mrEVbDaXKxhvUDf52iVD+sGIlTif7mBgR99/b
c3qiCnxCMmfYUnT2eh7Vv2LhCR/G9S6C3R4lA71rEyiU3KgsGfg0d82/XWXbegJW
h3QbWNtQLxTuIvLq5aAryV3PfaHlPgdgK0ft6ocU2de2FagFka3nfVEyC7IUsNTK
bq6nhAECgYEA7d/0DPOIaItl/8BWKyCuAHMss47j0wlGbBSHdJIiS55akMvnAG0M
39y22Qqfzh1at9kBFeYeFIIU82ZLF3xOcE3z6pJZ4Dyvx4BYdXH77odo9uVK9s1l
3T3BlMcqd1hvZLMS7dviyH79jZo4CXSHiKzc7pQ2YfK5eKxKqONeXuECgYEAyXlG
vonaus/YTb1IBei9HwaccnQ/1HRn6MvfDjb7JJDIBhNClGPt6xRlzBbSZ73c2QEC
6Fu9h36K/HZ2qcLd2bXiNyhIV7b6tVKk+0Psoj0dL9EbhsD1OsmE1nTPyAc9XZbb
OPYxy+dpBCUA8/1U9+uiFoCa7mIbWcSQ+39gHuECgYAz82pQfct30aH4JiBrkNqP
nJfRq05UY70uk5k1u0ikLTRoVS/hJu/d4E1Kv4hBMqYCavFSwAwnvHUo51lVCr/y
xQOVYlsgnwBg2MX4+GjmIkqpSVCC8D7j/73MaWb746OIYZervQ8dbKahi2HbpsiG
8AHcVSA/agxZr38qvWV54QKBgCD5TlDE8x18AuTGQ9FjxAAd7uD0kbXNz2vUYg9L
hFL5tyL3aAAtUrUUw4xhd9IuysRhW/53dU+FsG2dXdJu6CxHjlyEpUJl2iZu/j15
YnMzGWHIEX8+eWRDsw/+Ujtko/B7TinGcWPz3cYl4EAOiCeDUyXnqnO1btCEUU44
DJ1BAoGBAJuPD27ErTSVtId90+M4zFPNibFP50KprVdc8CR37BE7r8vuGgNYXmnI
RLnGP9p3pVgFCktORuYS2J/6t84I3+A17nEoB4xvhTLeAinAW/uTQOUmNicOP4Ek
2MsLL2kHgL8bLTmvXV4FX+PXphrDKg1XxzOYn0otuoqdAQrkK4og
-----END RSA PRIVATE KEY-----
EOD;

$publicKey = <<<EOD
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAuzWHNM5f+amCjQztc5QT
fJfzCC5J4nuW+L/aOxZ4f8J3FrewM2c/dufrnmedsApb0By7WhaHlcqCh/ScAPyJ
hzkPYLae7bTVro3hok0zDITR8F6SJGL42JAEUk+ILkPI+DONM0+3vzk6Kvfe548t
u4czCuqU8BGVOlnp6IqBHhAswNMM78pos/2z0CjPM4tbeXqSTTbNkXRboxjU29vS
opcT51koWOgiTf3C7nJUoMWZHZI5HqnIhPAG9yv8HAgNk6CMk2CadVHDo4IxjxTz
TTqo1SCSH2pooJl9O8at6kkRYsrZWwsKlOFE2LUce7ObnXsYihStBUDoeBQlGG/B
wQIDAQAB
-----END PUBLIC KEY-----
EOD;

$payload = [
    'iss' => 'example.org',
    'aud' => 'example.com',
    'iat' => 1356999524,
    'nbf' => 1357000000
];

$jwt = JWT::encode($payload, $privateKey, 'RS256');
echo "Encode:\n" . print_r($jwt, true) . "\n";

$decoded = JWT::decode($jwt, new Key($publicKey, 'RS256'));

/*
 NOTE: This will now be an object instead of an associative array. To get
 an associative array, you will need to cast it as such:
*/

$decoded_array = (array) $decoded;
echo "Decode:\n" . print_r($decoded_array, true) . "\n";
```

## Example with a passphrase

```php
use Firebase\JWT\JWT;
use Firebase\JWT\Key;

// Your passphrase
$passphrase = '[YOUR_PASSPHRASE]';

// Your private key file with passphrase
// Can be generated with "ssh-keygen -t rsa -m pem"
$privateKeyFile = '/path/to/key-with-passphrase.pem';

/** @var OpenSSLAsymmetricKey $privateKey */
$privateKey = openssl_pkey_get_private(
    file_get_contents($privateKeyFile),
    $passphrase
);

$payload = [
    'iss' => 'example.org',
    'aud' => 'example.com',
    'iat' => 1356999524,
    'nbf' => 1357000000
];

$jwt = JWT::encode($payload, $privateKey, 'RS256');
echo "Encode:\n" . print_r($jwt, true) . "\n";

// Get public key from the private key, or pull from from a file.
$publicKey = openssl_pkey_get_details($privateKey)['key'];

$decoded = JWT::decode($jwt, new Key($publicKey, 'RS256'));
echo "Decode:\n" . print_r((array) $decoded, true) . "\n";
```

## Example with EdDSA (libsodium and Ed25519 signature)

```php
use Firebase\JWT\JWT;
use Firebase\JWT\Key;

// Public and private keys are expected to be Base64 encoded. The last
// non-empty line is used so that keys can be generated with
// sodium_crypto_sign_keypair(). The secret keys generated by other tools may
// need to be adjusted to match the input expected by libsodium.

$keyPair = sodium_crypto_sign_keypair();

$privateKey = base64_encode(sodium_crypto_sign_secretkey($keyPair));

$publicKey = base64_encode(sodium_crypto_sign_publickey($keyPair));

$payload = [
    'iss' => 'example.org',
    'aud' => 'example.com',
    'iat' => 1356999524,
    'nbf' => 1357000000
];

$jwt = JWT::encode($payload, $privateKey, 'EdDSA');
echo "Encode:\n" . print_r($jwt, true) . "\n";

$decoded = JWT::decode($jwt, new Key($publicKey, 'EdDSA'));
echo "Decode:\n" . print_r((array) $decoded, true) . "\n";
```

## Example with multiple keys

```php
use Firebase\JWT\JWT;
use Firebase\JWT\Key;

// Example RSA keys from previous example
// $privateRsKey = '...';
// $publicRsKey = '...';

// Example EdDSA keys from previous example
// $privateEcKey = '...';
// $publicEcKey = '...';

$payload = [
    'iss' => 'example.org',
    'aud' => 'example.com',
    'iat' => 1356999524,
    'nbf' => 1357000000
];

$jwt1 = JWT::encode($payload, $privateRsKey, 'RS256', 'kid1');
$jwt2 = JWT::encode($payload, $privateEcKey, 'EdDSA', 'kid2');
echo "Encode 1:\n" . print_r($jwt1, true) . "\n";
echo "Encode 2:\n" . print_r($jwt2, true) . "\n";

$keys = [
    'kid1' => new Key($publicRsKey, 'RS256'),
    'kid2' => new Key($publicEcKey, 'EdDSA'),
];

$decoded1 = JWT::decode($jwt1, $keys);
$decoded2 = JWT::decode($jwt2, $keys);

echo "Decode 1:\n" . print_r((array) $decoded1, true) . "\n";
echo "Decode 2:\n" . print_r((array) $decoded2, true) . "\n";
```

## Using JWKs

```php
use Firebase\JWT\JWK;
use Firebase\JWT\JWT;

// Set of keys. The "keys" key is required. For example, the JSON response to
// this endpoint: https://www.gstatic.com/iap/verify/public_key-jwk
$jwks = ['keys' => []];

// JWK::parseKeySet($jwks) returns an associative array of **kid** to Firebase\JWT\Key
// objects. Pass this as the second parameter to JWT::decode.
$decoded = JWT::decode($jwt, JWK::parseKeySet($jwks));
print_r($decoded);
```

## Using Cached Key Sets

The `CachedKeySet` class can be used to fetch and cache JWKS (JSON Web Key Sets) from a public URI.
This has the following advantages:

1. The results are cached for performance.
2. If an unrecognized key is requested, the cache is refreshed, to accomodate for key rotation.
3. If rate limiting is enabled, the JWKS URI will not make more than 10 requests a second.

```php
use Firebase\JWT\CachedKeySet;
use Firebase\JWT\JWT;

// The URI for the JWKS you wish to cache the results from
$jwksUri = 'https://www.gstatic.com/iap/verify/public_key-jwk';

// Create an HTTP client (can be any PSR-7 compatible HTTP client)
$httpClient = new GuzzleHttp\Client();

// Create an HTTP request factory (can be any PSR-17 compatible HTTP request factory)
$httpFactory = new GuzzleHttp\Psr7\HttpFactory();

// Create a cache item pool (can be any PSR-6 compatible cache item pool)
$cacheItemPool = Phpfastcache\CacheManager::getInstance('files');

$keySet = new CachedKeySet(
    $jwksUri,
    $httpClient,
    $httpFactory,
    $cacheItemPool,
    null, // $expiresAfter int seconds to set the JWKS to expire
    true  // $rateLimit    true to enable rate limit of 10 RPS on lookup of invalid keys
);

$jwt = 'eyJhbGci...'; // Some JWT signed by a key from the $jwkUri above
$decoded = JWT::decode($jwt, $keySet);
```

Miscellaneous
-------------

#### Exception Handling

When a call to `JWT::decode` is invalid, it will throw one of the following exceptions:

```php
use Firebase\JWT\JWT;
use Firebase\JWT\SignatureInvalidException;
use Firebase\JWT\BeforeValidException;
use Firebase\JWT\ExpiredException;
use DomainException;
use InvalidArgumentException;
use UnexpectedValueException;

try {
    $decoded = JWT::decode($jwt, $keys);
} catch (InvalidArgumentException $e) {
    // provided key/key-array is empty or malformed.
} catch (DomainException $e) {
    // provided algorithm is unsupported OR
    // provided key is invalid OR
    // unknown error thrown in openSSL or libsodium OR
    // libsodium is required but not available.
} catch (SignatureInvalidException $e) {
    // provided JWT signature verification failed.
} catch (BeforeValidException $e) {
    // provided JWT is trying to be used before "nbf" claim OR
    // provided JWT is trying to be used before "iat" claim.
} catch (ExpiredException $e) {
    // provided JWT is trying to be used after "exp" claim.
} catch (UnexpectedValueException $e) {
    // provided JWT is malformed OR
    // provided JWT is missing an algorithm / using an unsupported algorithm OR
    // provided JWT algorithm does not match provided key OR
    // provided key ID in key/key-array is empty or invalid.
}
```

All exceptions in the `Firebase\JWT` namespace extend `UnexpectedValueException`, and can be simplified
like this:

```php
use Firebase\JWT\JWT;
use UnexpectedValueException;
try {
    $decoded = JWT::decode($jwt, $keys);
} catch (LogicException $e) {
    // errors having to do with environmental setup or malformed JWT Keys
} catch (UnexpectedValueException $e) {
    // errors having to do with JWT signature and claims
}
```

#### Casting to array

The return value of `JWT::decode` is the generic PHP object `stdClass`. If you'd like to handle with arrays
instead, you can do the following:

```php
// return type is stdClass
$decoded = JWT::decode($jwt, $keys);

// cast to array
$decoded = json_decode(json_encode($decoded), true);
```

Tests
-----
Run the tests using phpunit:

```bash
$ composer update
$ vendor/bin/phpunit -c phpunit.xml.dist
PHPUnit 3.7.10 by Sebastian Bergmann.
.....
Time: 0 seconds, Memory: 2.50Mb
OK (5 tests, 5 assertions)
```

New Lines in private keys
-----

If your private key contains `\n` characters, be sure to wrap it in double quotes `""`
and not single quotes `''` in order to properly interpret the escaped characters.

License
-------
[3-Clause BSD](http://opensource.org/licenses/BSD-3-Clause).
{
    "name": "firebase\/php-jwt",
    "description": "A simple library to encode and decode JSON Web Tokens (JWT) in PHP. Should conform to the current spec.",
    "homepage": "https:\/\/github.com\/firebase\/php-jwt",
    "keywords": [
        "php",
        "jwt"
    ],
    "authors": [
        {
            "name": "Neuman Vong",
            "email": "neuman+pear@twilio.com",
            "role": "Developer"
        },
        {
            "name": "Anant Narayanan",
            "email": "anant@php.net",
            "role": "Developer"
        }
    ],
    "license": "BSD-3-Clause",
    "require": {
        "php": "^8.0"
    },
    "suggest": {
        "paragonie\/sodium_compat": "Support EdDSA (Ed25519) signatures when libsodium is not present",
        "ext-sodium": "Support EdDSA (Ed25519) signatures"
    },
    "autoload": {
        "psr-4": {
            "_ContaoManager\\Firebase\\JWT\\": "src"
        }
    },
    "require-dev": {
        "guzzlehttp\/guzzle": "^7.4",
        "phpspec\/prophecy-phpunit": "^2.0",
        "phpunit\/phpunit": "^9.5",
        "psr\/cache": "^2.0||^3.0",
        "psr\/http-client": "^1.0",
        "psr\/http-factory": "^1.0",
        "phpfastcache\/phpfastcache": "^9.2"
    }
}<?php

namespace _ContaoManager\Firebase\JWT;

class SignatureInvalidException extends \UnexpectedValueException
{
}
<?php

namespace _ContaoManager\Firebase\JWT;

class BeforeValidException extends \UnexpectedValueException implements JWTExceptionWithPayloadInterface
{
    private object $payload;
    public function setPayload(object $payload): void
    {
        $this->payload = $payload;
    }
    public function getPayload(): object
    {
        return $this->payload;
    }
}
<?php

namespace _ContaoManager\Firebase\JWT;

use ArrayAccess;
use InvalidArgumentException;
use LogicException;
use OutOfBoundsException;
use _ContaoManager\Psr\Cache\CacheItemInterface;
use _ContaoManager\Psr\Cache\CacheItemPoolInterface;
use _ContaoManager\Psr\Http\Client\ClientInterface;
use _ContaoManager\Psr\Http\Message\RequestFactoryInterface;
use RuntimeException;
use UnexpectedValueException;
/**
 * @implements ArrayAccess<string, Key>
 */
class CachedKeySet implements ArrayAccess
{
    /**
     * @var string
     */
    private $jwksUri;
    /**
     * @var ClientInterface
     */
    private $httpClient;
    /**
     * @var RequestFactoryInterface
     */
    private $httpFactory;
    /**
     * @var CacheItemPoolInterface
     */
    private $cache;
    /**
     * @var ?int
     */
    private $expiresAfter;
    /**
     * @var ?CacheItemInterface
     */
    private $cacheItem;
    /**
     * @var array<string, array<mixed>>
     */
    private $keySet;
    /**
     * @var string
     */
    private $cacheKey;
    /**
     * @var string
     */
    private $cacheKeyPrefix = 'jwks';
    /**
     * @var int
     */
    private $maxKeyLength = 64;
    /**
     * @var bool
     */
    private $rateLimit;
    /**
     * @var string
     */
    private $rateLimitCacheKey;
    /**
     * @var int
     */
    private $maxCallsPerMinute = 10;
    /**
     * @var string|null
     */
    private $defaultAlg;
    public function __construct(string $jwksUri, ClientInterface $httpClient, RequestFactoryInterface $httpFactory, CacheItemPoolInterface $cache, ?int $expiresAfter = null, bool $rateLimit = \false, ?string $defaultAlg = null)
    {
        $this->jwksUri = $jwksUri;
        $this->httpClient = $httpClient;
        $this->httpFactory = $httpFactory;
        $this->cache = $cache;
        $this->expiresAfter = $expiresAfter;
        $this->rateLimit = $rateLimit;
        $this->defaultAlg = $defaultAlg;
        $this->setCacheKeys();
    }
    /**
     * @param string $keyId
     * @return Key
     */
    public function offsetGet($keyId): Key
    {
        if (!$this->keyIdExists($keyId)) {
            throw new OutOfBoundsException('Key ID not found');
        }
        return JWK::parseKey($this->keySet[$keyId], $this->defaultAlg);
    }
    /**
     * @param string $keyId
     * @return bool
     */
    public function offsetExists($keyId): bool
    {
        return $this->keyIdExists($keyId);
    }
    /**
     * @param string $offset
     * @param Key $value
     */
    public function offsetSet($offset, $value): void
    {
        throw new LogicException('Method not implemented');
    }
    /**
     * @param string $offset
     */
    public function offsetUnset($offset): void
    {
        throw new LogicException('Method not implemented');
    }
    /**
     * @return array<mixed>
     */
    private function formatJwksForCache(string $jwks): array
    {
        $jwks = json_decode($jwks, \true);
        if (!isset($jwks['keys'])) {
            throw new UnexpectedValueException('"keys" member must exist in the JWK Set');
        }
        if (empty($jwks['keys'])) {
            throw new InvalidArgumentException('JWK Set did not contain any keys');
        }
        $keys = [];
        foreach ($jwks['keys'] as $k => $v) {
            $kid = isset($v['kid']) ? $v['kid'] : $k;
            $keys[(string) $kid] = $v;
        }
        return $keys;
    }
    private function keyIdExists(string $keyId): bool
    {
        if (null === $this->keySet) {
            $item = $this->getCacheItem();
            // Try to load keys from cache
            if ($item->isHit()) {
                // item found! retrieve it
                $this->keySet = $item->get();
                // If the cached item is a string, the JWKS response was cached (previous behavior).
                // Parse this into expected format array<kid, jwk> instead.
                if (\is_string($this->keySet)) {
                    $this->keySet = $this->formatJwksForCache($this->keySet);
                }
            }
        }
        if (!isset($this->keySet[$keyId])) {
            if ($this->rateLimitExceeded()) {
                return \false;
            }
            $request = $this->httpFactory->createRequest('GET', $this->jwksUri);
            $jwksResponse = $this->httpClient->sendRequest($request);
            if ($jwksResponse->getStatusCode() !== 200) {
                throw new UnexpectedValueException(\sprintf('HTTP Error: %d %s for URI "%s"', $jwksResponse->getStatusCode(), $jwksResponse->getReasonPhrase(), $this->jwksUri), $jwksResponse->getStatusCode());
            }
            $this->keySet = $this->formatJwksForCache((string) $jwksResponse->getBody());
            if (!isset($this->keySet[$keyId])) {
                return \false;
            }
            $item = $this->getCacheItem();
            $item->set($this->keySet);
            if ($this->expiresAfter) {
                $item->expiresAfter($this->expiresAfter);
            }
            $this->cache->save($item);
        }
        return \true;
    }
    private function rateLimitExceeded(): bool
    {
        if (!$this->rateLimit) {
            return \false;
        }
        $cacheItem = $this->cache->getItem($this->rateLimitCacheKey);
        $cacheItemData = [];
        if ($cacheItem->isHit() && \is_array($data = $cacheItem->get())) {
            $cacheItemData = $data;
        }
        $callsPerMinute = $cacheItemData['callsPerMinute'] ?? 0;
        $expiry = $cacheItemData['expiry'] ?? new \DateTime('+60 seconds', new \DateTimeZone('UTC'));
        if (++$callsPerMinute > $this->maxCallsPerMinute) {
            return \true;
        }
        $cacheItem->set(['expiry' => $expiry, 'callsPerMinute' => $callsPerMinute]);
        $cacheItem->expiresAt($expiry);
        $this->cache->save($cacheItem);
        return \false;
    }
    private function getCacheItem(): CacheItemInterface
    {
        if (\is_null($this->cacheItem)) {
            $this->cacheItem = $this->cache->getItem($this->cacheKey);
        }
        return $this->cacheItem;
    }
    private function setCacheKeys(): void
    {
        if (empty($this->jwksUri)) {
            throw new RuntimeException('JWKS URI is empty');
        }
        // ensure we do not have illegal characters
        $key = preg_replace('|[^a-zA-Z0-9_\.!]|', '', $this->jwksUri);
        // add prefix
        $key = $this->cacheKeyPrefix . $key;
        // Hash keys if they exceed $maxKeyLength of 64
        if (\strlen($key) > $this->maxKeyLength) {
            $key = substr(hash('sha256', $key), 0, $this->maxKeyLength);
        }
        $this->cacheKey = $key;
        if ($this->rateLimit) {
            // add prefix
            $rateLimitKey = $this->cacheKeyPrefix . 'ratelimit' . $key;
            // Hash keys if they exceed $maxKeyLength of 64
            if (\strlen($rateLimitKey) > $this->maxKeyLength) {
                $rateLimitKey = substr(hash('sha256', $rateLimitKey), 0, $this->maxKeyLength);
            }
            $this->rateLimitCacheKey = $rateLimitKey;
        }
    }
}
<?php

namespace _ContaoManager\Firebase\JWT;

use InvalidArgumentException;
use OpenSSLAsymmetricKey;
use OpenSSLCertificate;
use TypeError;
class Key
{
    /**
     * @param string|OpenSSLAsymmetricKey|OpenSSLCertificate $keyMaterial
     * @param string $algorithm
     */
    public function __construct(
        #[\SensitiveParameter]
        private $keyMaterial,
        private string $algorithm
    )
    {
        if (!\is_string($keyMaterial) && !$keyMaterial instanceof OpenSSLAsymmetricKey && !$keyMaterial instanceof OpenSSLCertificate) {
            throw new TypeError('Key material must be a string, OpenSSLCertificate, or OpenSSLAsymmetricKey');
        }
        if (empty($keyMaterial)) {
            throw new InvalidArgumentException('Key material must not be empty');
        }
        if (empty($algorithm)) {
            throw new InvalidArgumentException('Algorithm must not be empty');
        }
    }
    /**
     * Return the algorithm valid for this key
     *
     * @return string
     */
    public function getAlgorithm(): string
    {
        return $this->algorithm;
    }
    /**
     * @return string|OpenSSLAsymmetricKey|OpenSSLCertificate
     */
    public function getKeyMaterial()
    {
        return $this->keyMaterial;
    }
}
<?php

namespace _ContaoManager\Firebase\JWT;

use DomainException;
use InvalidArgumentException;
use UnexpectedValueException;
/**
 * JSON Web Key implementation, based on this spec:
 * https://tools.ietf.org/html/draft-ietf-jose-json-web-key-41
 *
 * PHP version 5
 *
 * @category Authentication
 * @package  Authentication_JWT
 * @author   Bui Sy Nguyen <nguyenbs@gmail.com>
 * @license  http://opensource.org/licenses/BSD-3-Clause 3-clause BSD
 * @link     https://github.com/firebase/php-jwt
 */
class JWK
{
    private const OID = '1.2.840.10045.2.1';
    private const ASN1_OBJECT_IDENTIFIER = 0x6;
    private const ASN1_SEQUENCE = 0x10;
    // also defined in JWT
    private const ASN1_BIT_STRING = 0x3;
    private const EC_CURVES = [
        'P-256' => '1.2.840.10045.3.1.7',
        // Len: 64
        'secp256k1' => '1.3.132.0.10',
        // Len: 64
        'P-384' => '1.3.132.0.34',
    ];
    // For keys with "kty" equal to "OKP" (Octet Key Pair), the "crv" parameter must contain the key subtype.
    // This library supports the following subtypes:
    private const OKP_SUBTYPES = ['Ed25519' => \true];
    /**
     * Parse a set of JWK keys
     *
     * @param array<mixed> $jwks The JSON Web Key Set as an associative array
     * @param string       $defaultAlg The algorithm for the Key object if "alg" is not set in the
     *                                 JSON Web Key Set
     *
     * @return array<string, Key> An associative array of key IDs (kid) to Key objects
     *
     * @throws InvalidArgumentException     Provided JWK Set is empty
     * @throws UnexpectedValueException     Provided JWK Set was invalid
     * @throws DomainException              OpenSSL failure
     *
     * @uses parseKey
     */
    public static function parseKeySet(
        #[\SensitiveParameter]
        array $jwks,
        ?string $defaultAlg = null
    ): array
    {
        $keys = [];
        if (!isset($jwks['keys'])) {
            throw new UnexpectedValueException('"keys" member must exist in the JWK Set');
        }
        if (empty($jwks['keys'])) {
            throw new InvalidArgumentException('JWK Set did not contain any keys');
        }
        foreach ($jwks['keys'] as $k => $v) {
            $kid = isset($v['kid']) ? $v['kid'] : $k;
            if ($key = self::parseKey($v, $defaultAlg)) {
                $keys[(string) $kid] = $key;
            }
        }
        if (0 === \count($keys)) {
            throw new UnexpectedValueException('No supported algorithms found in JWK Set');
        }
        return $keys;
    }
    /**
     * Parse a JWK key
     *
     * @param array<mixed> $jwk An individual JWK
     * @param string       $defaultAlg The algorithm for the Key object if "alg" is not set in the
     *                                 JSON Web Key Set
     *
     * @return Key The key object for the JWK
     *
     * @throws InvalidArgumentException     Provided JWK is empty
     * @throws UnexpectedValueException     Provided JWK was invalid
     * @throws DomainException              OpenSSL failure
     *
     * @uses createPemFromModulusAndExponent
     */
    public static function parseKey(
        #[\SensitiveParameter]
        array $jwk,
        ?string $defaultAlg = null
    ): ?Key
    {
        if (empty($jwk)) {
            throw new InvalidArgumentException('JWK must not be empty');
        }
        if (!isset($jwk['kty'])) {
            throw new UnexpectedValueException('JWK must contain a "kty" parameter');
        }
        if (!isset($jwk['alg'])) {
            if (\is_null($defaultAlg)) {
                // The "alg" parameter is optional in a KTY, but an algorithm is required
                // for parsing in this library. Use the $defaultAlg parameter when parsing the
                // key set in order to prevent this error.
                // @see https://datatracker.ietf.org/doc/html/rfc7517#section-4.4
                throw new UnexpectedValueException('JWK must contain an "alg" parameter');
            }
            $jwk['alg'] = $defaultAlg;
        }
        switch ($jwk['kty']) {
            case 'RSA':
                if (!empty($jwk['d'])) {
                    throw new UnexpectedValueException('RSA private keys are not supported');
                }
                if (!isset($jwk['n']) || !isset($jwk['e'])) {
                    throw new UnexpectedValueException('RSA keys must contain values for both "n" and "e"');
                }
                $pem = self::createPemFromModulusAndExponent($jwk['n'], $jwk['e']);
                $publicKey = \openssl_pkey_get_public($pem);
                if (\false === $publicKey) {
                    throw new DomainException('OpenSSL error: ' . \openssl_error_string());
                }
                return new Key($publicKey, $jwk['alg']);
            case 'EC':
                if (isset($jwk['d'])) {
                    // The key is actually a private key
                    throw new UnexpectedValueException('Key data must be for a public key');
                }
                if (empty($jwk['crv'])) {
                    throw new UnexpectedValueException('crv not set');
                }
                if (!isset(self::EC_CURVES[$jwk['crv']])) {
                    throw new DomainException('Unrecognised or unsupported EC curve');
                }
                if (empty($jwk['x']) || empty($jwk['y'])) {
                    throw new UnexpectedValueException('x and y not set');
                }
                $publicKey = self::createPemFromCrvAndXYCoordinates($jwk['crv'], $jwk['x'], $jwk['y']);
                return new Key($publicKey, $jwk['alg']);
            case 'OKP':
                if (isset($jwk['d'])) {
                    // The key is actually a private key
                    throw new UnexpectedValueException('Key data must be for a public key');
                }
                if (!isset($jwk['crv'])) {
                    throw new UnexpectedValueException('crv not set');
                }
                if (empty(self::OKP_SUBTYPES[$jwk['crv']])) {
                    throw new DomainException('Unrecognised or unsupported OKP key subtype');
                }
                if (empty($jwk['x'])) {
                    throw new UnexpectedValueException('x not set');
                }
                // This library works internally with EdDSA keys (Ed25519) encoded in standard base64.
                $publicKey = JWT::convertBase64urlToBase64($jwk['x']);
                return new Key($publicKey, $jwk['alg']);
            case 'oct':
                if (!isset($jwk['k'])) {
                    throw new UnexpectedValueException('k not set');
                }
                return new Key(JWT::urlsafeB64Decode($jwk['k']), $jwk['alg']);
            default:
                break;
        }
        return null;
    }
    /**
     * Converts the EC JWK values to pem format.
     *
     * @param   string  $crv The EC curve (only P-256 & P-384 is supported)
     * @param   string  $x   The EC x-coordinate
     * @param   string  $y   The EC y-coordinate
     *
     * @return  string
     */
    private static function createPemFromCrvAndXYCoordinates(string $crv, string $x, string $y): string
    {
        $pem = self::encodeDER(self::ASN1_SEQUENCE, self::encodeDER(self::ASN1_SEQUENCE, self::encodeDER(self::ASN1_OBJECT_IDENTIFIER, self::encodeOID(self::OID)) . self::encodeDER(self::ASN1_OBJECT_IDENTIFIER, self::encodeOID(self::EC_CURVES[$crv]))) . self::encodeDER(self::ASN1_BIT_STRING, \chr(0x0) . \chr(0x4) . JWT::urlsafeB64Decode($x) . JWT::urlsafeB64Decode($y)));
        return \sprintf("-----BEGIN PUBLIC KEY-----\n%s\n-----END PUBLIC KEY-----\n", wordwrap(base64_encode($pem), 64, "\n", \true));
    }
    /**
     * Create a public key represented in PEM format from RSA modulus and exponent information
     *
     * @param string $n The RSA modulus encoded in Base64
     * @param string $e The RSA exponent encoded in Base64
     *
     * @return string The RSA public key represented in PEM format
     *
     * @uses encodeLength
     */
    private static function createPemFromModulusAndExponent(string $n, string $e): string
    {
        $mod = JWT::urlsafeB64Decode($n);
        $exp = JWT::urlsafeB64Decode($e);
        // Correct encoding for ASN1, as ints are represented as unsigned in jwk
        // but signed in ASN1. Prepending null byte makes it unsigned.
        if (\strlen($mod) > 0 && \ord($mod[0]) >= 128) {
            $mod = \chr(0) . $mod;
        }
        if (\strlen($exp) > 0 && \ord($exp[0]) >= 128) {
            $exp = \chr(0) . $exp;
        }
        $modulus = \pack('Ca*a*', 2, self::encodeLength(\strlen($mod)), $mod);
        $publicExponent = \pack('Ca*a*', 2, self::encodeLength(\strlen($exp)), $exp);
        $rsaPublicKey = \pack('Ca*a*a*', 48, self::encodeLength(\strlen($modulus) + \strlen($publicExponent)), $modulus, $publicExponent);
        // sequence(oid(1.2.840.113549.1.1.1), null)) = rsaEncryption.
        $rsaOID = \pack('H*', '300d06092a864886f70d0101010500');
        // hex version of MA0GCSqGSIb3DQEBAQUA
        $rsaPublicKey = \chr(0) . $rsaPublicKey;
        $rsaPublicKey = \chr(3) . self::encodeLength(\strlen($rsaPublicKey)) . $rsaPublicKey;
        $rsaPublicKey = \pack('Ca*a*', 48, self::encodeLength(\strlen($rsaOID . $rsaPublicKey)), $rsaOID . $rsaPublicKey);
        return "-----BEGIN PUBLIC KEY-----\r\n" . \chunk_split(\base64_encode($rsaPublicKey), 64) . '-----END PUBLIC KEY-----';
    }
    /**
     * DER-encode the length
     *
     * DER supports lengths up to (2**8)**127, however, we'll only support lengths up to (2**8)**4.  See
     * {@link http://itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf#p=13 X.690 paragraph 8.1.3} for more information.
     *
     * @param int $length
     * @return string
     */
    private static function encodeLength(int $length): string
    {
        if ($length <= 0x7f) {
            return \chr($length);
        }
        $temp = \ltrim(\pack('N', $length), \chr(0));
        return \pack('Ca*', 0x80 | \strlen($temp), $temp);
    }
    /**
     * Encodes a value into a DER object.
     * Also defined in Firebase\JWT\JWT
     *
     * @param   int     $type DER tag
     * @param   string  $value the value to encode
     * @return  string  the encoded object
     */
    private static function encodeDER(int $type, string $value): string
    {
        $tag_header = 0;
        if ($type === self::ASN1_SEQUENCE) {
            $tag_header |= 0x20;
        }
        // Type
        $der = \chr($tag_header | $type);
        // Length
        $der .= \chr(\strlen($value));
        return $der . $value;
    }
    /**
     * Encodes a string into a DER-encoded OID.
     *
     * @param   string $oid the OID string
     * @return  string the binary DER-encoded OID
     */
    private static function encodeOID(string $oid): string
    {
        $octets = explode('.', $oid);
        // Get the first octet
        $first = (int) array_shift($octets);
        $second = (int) array_shift($octets);
        $oid = \chr($first * 40 + $second);
        // Iterate over subsequent octets
        foreach ($octets as $octet) {
            if ($octet == 0) {
                $oid .= \chr(0x0);
                continue;
            }
            $bin = '';
            while ($octet) {
                $bin .= \chr(0x80 | $octet & 0x7f);
                $octet >>= 7;
            }
            $bin[0] = $bin[0] & \chr(0x7f);
            // Convert to big endian if necessary
            if (pack('V', 65534) == pack('L', 65534)) {
                $oid .= strrev($bin);
            } else {
                $oid .= $bin;
            }
        }
        return $oid;
    }
}
<?php

namespace _ContaoManager\Firebase\JWT;

interface JWTExceptionWithPayloadInterface
{
    /**
     * Get the payload that caused this exception.
     *
     * @return object
     */
    public function getPayload(): object;
    /**
     * Get the payload that caused this exception.
     *
     * @param object $payload
     * @return void
     */
    public function setPayload(object $payload): void;
}
<?php

namespace _ContaoManager\Firebase\JWT;

class ExpiredException extends \UnexpectedValueException implements JWTExceptionWithPayloadInterface
{
    private object $payload;
    private ?int $timestamp = null;
    public function setPayload(object $payload): void
    {
        $this->payload = $payload;
    }
    public function getPayload(): object
    {
        return $this->payload;
    }
    public function setTimestamp(int $timestamp): void
    {
        $this->timestamp = $timestamp;
    }
    public function getTimestamp(): ?int
    {
        return $this->timestamp;
    }
}
<?php

namespace _ContaoManager\Firebase\JWT;

use ArrayAccess;
use DateTime;
use DomainException;
use Exception;
use InvalidArgumentException;
use OpenSSLAsymmetricKey;
use OpenSSLCertificate;
use stdClass;
use UnexpectedValueException;
/**
 * JSON Web Token implementation, based on this spec:
 * https://tools.ietf.org/html/rfc7519
 *
 * PHP version 5
 *
 * @category Authentication
 * @package  Authentication_JWT
 * @author   Neuman Vong <neuman@twilio.com>
 * @author   Anant Narayanan <anant@php.net>
 * @license  http://opensource.org/licenses/BSD-3-Clause 3-clause BSD
 * @link     https://github.com/firebase/php-jwt
 */
class JWT
{
    private const ASN1_INTEGER = 0x2;
    private const ASN1_SEQUENCE = 0x10;
    private const ASN1_BIT_STRING = 0x3;
    private const RSA_KEY_MIN_LENGTH = 2048;
    /**
     * When checking nbf, iat or expiration times,
     * we want to provide some extra leeway time to
     * account for clock skew.
     *
     * @var int
     */
    public static $leeway = 0;
    /**
     * Allow the current timestamp to be specified.
     * Useful for fixing a value within unit testing.
     * Will default to PHP time() value if null.
     *
     * @var ?int
     */
    public static $timestamp = null;
    /**
     * @var array<string, string[]>
     */
    public static $supported_algs = ['ES384' => ['openssl', 'SHA384'], 'ES256' => ['openssl', 'SHA256'], 'ES256K' => ['openssl', 'SHA256'], 'HS256' => ['hash_hmac', 'SHA256'], 'HS384' => ['hash_hmac', 'SHA384'], 'HS512' => ['hash_hmac', 'SHA512'], 'RS256' => ['openssl', 'SHA256'], 'RS384' => ['openssl', 'SHA384'], 'RS512' => ['openssl', 'SHA512'], 'EdDSA' => ['sodium_crypto', 'EdDSA']];
    /**
     * Decodes a JWT string into a PHP object.
     *
     * @param string                 $jwt            The JWT
     * @param Key|ArrayAccess<string,Key>|array<string,Key> $keyOrKeyArray  The Key or associative array of key IDs
     *                                                                      (kid) to Key objects.
     *                                                                      If the algorithm used is asymmetric, this is
     *                                                                      the public key.
     *                                                                      Each Key object contains an algorithm and
     *                                                                      matching key.
     *                                                                      Supported algorithms are 'ES384','ES256',
     *                                                                      'HS256', 'HS384', 'HS512', 'RS256', 'RS384'
     *                                                                      and 'RS512'.
     * @param stdClass               $headers                               Optional. Populates stdClass with headers.
     *
     * @return stdClass The JWT's payload as a PHP object
     *
     * @throws InvalidArgumentException     Provided key/key-array was empty or malformed
     * @throws DomainException              Provided JWT is malformed
     * @throws UnexpectedValueException     Provided JWT was invalid
     * @throws SignatureInvalidException    Provided JWT was invalid because the signature verification failed
     * @throws BeforeValidException         Provided JWT is trying to be used before it's eligible as defined by 'nbf'
     * @throws BeforeValidException         Provided JWT is trying to be used before it's been created as defined by 'iat'
     * @throws ExpiredException             Provided JWT has since expired, as defined by the 'exp' claim
     *
     * @uses jsonDecode
     * @uses urlsafeB64Decode
     */
    public static function decode(
        string $jwt,
        #[\SensitiveParameter]
        $keyOrKeyArray,
        ?stdClass &$headers = null
    ): stdClass
    {
        // Validate JWT
        $timestamp = \is_null(static::$timestamp) ? \time() : static::$timestamp;
        if (empty($keyOrKeyArray)) {
            throw new InvalidArgumentException('Key may not be empty');
        }
        $tks = \explode('.', $jwt);
        if (\count($tks) !== 3) {
            throw new UnexpectedValueException('Wrong number of segments');
        }
        list($headb64, $bodyb64, $cryptob64) = $tks;
        $headerRaw = static::urlsafeB64Decode($headb64);
        if (null === $header = static::jsonDecode($headerRaw)) {
            throw new UnexpectedValueException('Invalid header encoding');
        }
        if ($headers !== null) {
            $headers = $header;
        }
        $payloadRaw = static::urlsafeB64Decode($bodyb64);
        if (null === $payload = static::jsonDecode($payloadRaw)) {
            throw new UnexpectedValueException('Invalid claims encoding');
        }
        if (\is_array($payload)) {
            // prevent PHP Fatal Error in edge-cases when payload is empty array
            $payload = (object) $payload;
        }
        if (!$payload instanceof stdClass) {
            throw new UnexpectedValueException('Payload must be a JSON object');
        }
        if (isset($payload->iat) && !\is_numeric($payload->iat)) {
            throw new UnexpectedValueException('Payload iat must be a number');
        }
        if (isset($payload->nbf) && !\is_numeric($payload->nbf)) {
            throw new UnexpectedValueException('Payload nbf must be a number');
        }
        if (isset($payload->exp) && !\is_numeric($payload->exp)) {
            throw new UnexpectedValueException('Payload exp must be a number');
        }
        $sig = static::urlsafeB64Decode($cryptob64);
        if (empty($header->alg)) {
            throw new UnexpectedValueException('Empty algorithm');
        }
        if (empty(static::$supported_algs[$header->alg])) {
            throw new UnexpectedValueException('Algorithm not supported');
        }
        $key = self::getKey($keyOrKeyArray, property_exists($header, 'kid') ? $header->kid : null);
        // Check the algorithm
        if (!self::constantTimeEquals($key->getAlgorithm(), $header->alg)) {
            // See issue #351
            throw new UnexpectedValueException('Incorrect key for this algorithm');
        }
        if (\in_array($header->alg, ['ES256', 'ES256K', 'ES384'], \true)) {
            // OpenSSL expects an ASN.1 DER sequence for ES256/ES256K/ES384 signatures
            $sig = self::signatureToDER($sig);
        }
        if (!self::verify("{$headb64}.{$bodyb64}", $sig, $key->getKeyMaterial(), $header->alg)) {
            throw new SignatureInvalidException('Signature verification failed');
        }
        // Check the nbf if it is defined. This is the time that the
        // token can actually be used. If it's not yet that time, abort.
        if (isset($payload->nbf) && floor($payload->nbf) > $timestamp + static::$leeway) {
            $ex = new BeforeValidException('Cannot handle token with nbf prior to ' . \date(DateTime::ATOM, (int) floor($payload->nbf)));
            $ex->setPayload($payload);
            throw $ex;
        }
        // Check that this token has been created before 'now'. This prevents
        // using tokens that have been created for later use (and haven't
        // correctly used the nbf claim).
        if (!isset($payload->nbf) && isset($payload->iat) && floor($payload->iat) > $timestamp + static::$leeway) {
            $ex = new BeforeValidException('Cannot handle token with iat prior to ' . \date(DateTime::ATOM, (int) floor($payload->iat)));
            $ex->setPayload($payload);
            throw $ex;
        }
        // Check if this token has expired.
        if (isset($payload->exp) && $timestamp - static::$leeway >= $payload->exp) {
            $ex = new ExpiredException('Expired token');
            $ex->setPayload($payload);
            $ex->setTimestamp($timestamp);
            throw $ex;
        }
        return $payload;
    }
    /**
     * Converts and signs a PHP array into a JWT string.
     *
     * @param array<mixed>          $payload PHP array
     * @param string|OpenSSLAsymmetricKey|OpenSSLCertificate $key The secret key.
     * @param string                $alg     Supported algorithms are 'ES384','ES256', 'ES256K', 'HS256',
     *                                       'HS384', 'HS512', 'RS256', 'RS384', and 'RS512'
     * @param string                $keyId
     * @param array<string, string|string[]> $head  An array with header elements to attach
     *
     * @return string A signed JWT
     *
     * @uses jsonEncode
     * @uses urlsafeB64Encode
     */
    public static function encode(
        array $payload,
        #[\SensitiveParameter]
        $key,
        string $alg,
        ?string $keyId = null,
        ?array $head = null
    ): string
    {
        $header = ['typ' => 'JWT'];
        if (isset($head)) {
            $header = \array_merge($header, $head);
        }
        $header['alg'] = $alg;
        if ($keyId !== null) {
            $header['kid'] = $keyId;
        }
        $segments = [];
        $segments[] = static::urlsafeB64Encode((string) static::jsonEncode($header));
        $segments[] = static::urlsafeB64Encode((string) static::jsonEncode($payload));
        $signing_input = \implode('.', $segments);
        $signature = static::sign($signing_input, $key, $alg);
        $segments[] = static::urlsafeB64Encode($signature);
        return \implode('.', $segments);
    }
    /**
     * Sign a string with a given key and algorithm.
     *
     * @param string $msg  The message to sign
     * @param string|OpenSSLAsymmetricKey|OpenSSLCertificate  $key  The secret key.
     * @param string $alg  Supported algorithms are 'EdDSA', 'ES384', 'ES256', 'ES256K', 'HS256',
     *                    'HS384', 'HS512', 'RS256', 'RS384', and 'RS512'
     *
     * @return string An encrypted message
     *
     * @throws DomainException Unsupported algorithm or bad key was specified
     */
    public static function sign(
        string $msg,
        #[\SensitiveParameter]
        $key,
        string $alg
    ): string
    {
        if (empty(static::$supported_algs[$alg])) {
            throw new DomainException('Algorithm not supported');
        }
        list($function, $algorithm) = static::$supported_algs[$alg];
        switch ($function) {
            case 'hash_hmac':
                if (!\is_string($key)) {
                    throw new InvalidArgumentException('key must be a string when using hmac');
                }
                self::validateHmacKeyLength($key, $algorithm);
                return \hash_hmac($algorithm, $msg, $key, \true);
            case 'openssl':
                $signature = '';
                if (!$key = openssl_pkey_get_private($key)) {
                    throw new DomainException('OpenSSL unable to validate key');
                }
                if (str_starts_with($alg, 'RS')) {
                    self::validateRsaKeyLength($key);
                } elseif (str_starts_with($alg, 'ES')) {
                    self::validateEcKeyLength($key, $alg);
                }
                $success = \openssl_sign($msg, $signature, $key, $algorithm);
                if (!$success) {
                    throw new DomainException('OpenSSL unable to sign data');
                }
                if ($alg === 'ES256' || $alg === 'ES256K') {
                    $signature = self::signatureFromDER($signature, 256);
                } elseif ($alg === 'ES384') {
                    $signature = self::signatureFromDER($signature, 384);
                }
                return $signature;
            case 'sodium_crypto':
                try {
                    return sodium_crypto_sign_detached($msg, self::validateEdDSAKey($key));
                } catch (Exception $e) {
                    throw new DomainException($e->getMessage(), 0, $e);
                }
        }
        throw new DomainException('Algorithm not supported');
    }
    /**
     * Verify a signature with the message, key and method. Not all methods
     * are symmetric, so we must have a separate verify and sign method.
     *
     * @param string $msg         The original message (header and body)
     * @param string $signature   The original signature
     * @param string|OpenSSLAsymmetricKey|OpenSSLCertificate  $keyMaterial For Ed*, ES*, HS*, a string key works. for RS*, must be an instance of OpenSSLAsymmetricKey
     * @param string $alg         The algorithm
     *
     * @return bool
     *
     * @throws DomainException Invalid Algorithm, bad key, or OpenSSL failure
     */
    private static function verify(
        string $msg,
        string $signature,
        #[\SensitiveParameter]
        $keyMaterial,
        string $alg
    ): bool
    {
        if (empty(static::$supported_algs[$alg])) {
            throw new DomainException('Algorithm not supported');
        }
        list($function, $algorithm) = static::$supported_algs[$alg];
        switch ($function) {
            case 'openssl':
                if (!$key = openssl_pkey_get_public($keyMaterial)) {
                    throw new DomainException('OpenSSL unable to validate key');
                }
                if (str_starts_with($alg, 'RS')) {
                    self::validateRsaKeyLength($key);
                } elseif (str_starts_with($alg, 'ES')) {
                    self::validateEcKeyLength($key, $alg);
                }
                $success = \openssl_verify($msg, $signature, $keyMaterial, $algorithm);
                if ($success === 1) {
                    return \true;
                }
                if ($success === 0) {
                    return \false;
                }
                // returns 1 on success, 0 on failure, -1 on error.
                throw new DomainException('OpenSSL error: ' . \openssl_error_string());
            case 'sodium_crypto':
                try {
                    $key = self::validateEdDSAKey($keyMaterial);
                    if (\strlen($signature) === 0) {
                        throw new DomainException('Signature cannot be empty string');
                    }
                    return sodium_crypto_sign_verify_detached($signature, $msg, $key);
                } catch (Exception $e) {
                    throw new DomainException($e->getMessage(), 0, $e);
                }
            case 'hash_hmac':
            default:
                if (!\is_string($keyMaterial)) {
                    throw new InvalidArgumentException('key must be a string when using hmac');
                }
                self::validateHmacKeyLength($keyMaterial, $algorithm);
                $hash = \hash_hmac($algorithm, $msg, $keyMaterial, \true);
                return self::constantTimeEquals($hash, $signature);
        }
    }
    /**
     * Decode a JSON string into a PHP object.
     *
     * @param string $input JSON string
     *
     * @return mixed The decoded JSON string
     *
     * @throws DomainException Provided string was invalid JSON
     */
    public static function jsonDecode(string $input)
    {
        $obj = \json_decode($input, \false, 512, \JSON_BIGINT_AS_STRING);
        if ($errno = \json_last_error()) {
            self::handleJsonError($errno);
        } elseif ($obj === null && $input !== 'null') {
            throw new DomainException('Null result with non-null input');
        }
        return $obj;
    }
    /**
     * Encode a PHP array into a JSON string.
     *
     * @param array<mixed> $input A PHP array
     *
     * @return string JSON representation of the PHP array
     *
     * @throws DomainException Provided object could not be encoded to valid JSON
     */
    public static function jsonEncode(array $input): string
    {
        $json = \json_encode($input, \JSON_UNESCAPED_SLASHES);
        if ($errno = \json_last_error()) {
            self::handleJsonError($errno);
        } elseif ($json === 'null') {
            throw new DomainException('Null result with non-null input');
        }
        if ($json === \false) {
            throw new DomainException('Provided object could not be encoded to valid JSON');
        }
        return $json;
    }
    /**
     * Decode a string with URL-safe Base64.
     *
     * @param string $input A Base64 encoded string
     *
     * @return string A decoded string
     *
     * @throws InvalidArgumentException invalid base64 characters
     */
    public static function urlsafeB64Decode(string $input): string
    {
        return \base64_decode(self::convertBase64UrlToBase64($input));
    }
    /**
     * Convert a string in the base64url (URL-safe Base64) encoding to standard base64.
     *
     * @param string $input A Base64 encoded string with URL-safe characters (-_ and no padding)
     *
     * @return string A Base64 encoded string with standard characters (+/) and padding (=), when
     * needed.
     *
     * @see https://www.rfc-editor.org/rfc/rfc4648
     */
    public static function convertBase64UrlToBase64(string $input): string
    {
        $remainder = \strlen($input) % 4;
        if ($remainder) {
            $padlen = 4 - $remainder;
            $input .= \str_repeat('=', $padlen);
        }
        return \strtr($input, '-_', '+/');
    }
    /**
     * Encode a string with URL-safe Base64.
     *
     * @param string $input The string you want encoded
     *
     * @return string The base64 encode of what you passed in
     */
    public static function urlsafeB64Encode(string $input): string
    {
        return \str_replace('=', '', \strtr(\base64_encode($input), '+/', '-_'));
    }
    /**
     * Determine if an algorithm has been provided for each Key
     *
     * @param Key|ArrayAccess<string,Key>|array<string,Key> $keyOrKeyArray
     * @param string|null            $kid
     *
     * @throws UnexpectedValueException
     *
     * @return Key
     */
    private static function getKey(
        #[\SensitiveParameter]
        $keyOrKeyArray,
        ?string $kid
    ): Key
    {
        if ($keyOrKeyArray instanceof Key) {
            return $keyOrKeyArray;
        }
        if (empty($kid) && $kid !== '0') {
            throw new UnexpectedValueException('"kid" empty, unable to lookup correct key');
        }
        if ($keyOrKeyArray instanceof CachedKeySet) {
            // Skip "isset" check, as this will automatically refresh if not set
            return $keyOrKeyArray[$kid];
        }
        if (!isset($keyOrKeyArray[$kid])) {
            throw new UnexpectedValueException('"kid" invalid, unable to lookup correct key');
        }
        return $keyOrKeyArray[$kid];
    }
    /**
     * @param string $left  The string of known length to compare against
     * @param string $right The user-supplied string
     * @return bool
     */
    public static function constantTimeEquals(string $left, string $right): bool
    {
        if (\function_exists('hash_equals')) {
            return \hash_equals($left, $right);
        }
        $len = \min(self::safeStrlen($left), self::safeStrlen($right));
        $status = 0;
        for ($i = 0; $i < $len; $i++) {
            $status |= \ord($left[$i]) ^ \ord($right[$i]);
        }
        $status |= self::safeStrlen($left) ^ self::safeStrlen($right);
        return $status === 0;
    }
    /**
     * Helper method to create a JSON error.
     *
     * @param int $errno An error number from json_last_error()
     *
     * @throws DomainException
     *
     * @return void
     */
    private static function handleJsonError(int $errno): void
    {
        $messages = [\JSON_ERROR_DEPTH => 'Maximum stack depth exceeded', \JSON_ERROR_STATE_MISMATCH => 'Invalid or malformed JSON', \JSON_ERROR_CTRL_CHAR => 'Unexpected control character found', \JSON_ERROR_SYNTAX => 'Syntax error, malformed JSON', \JSON_ERROR_UTF8 => 'Malformed UTF-8 characters'];
        throw new DomainException(isset($messages[$errno]) ? $messages[$errno] : 'Unknown JSON error: ' . $errno);
    }
    /**
     * Get the number of bytes in cryptographic strings.
     *
     * @param string $str
     *
     * @return int
     */
    private static function safeStrlen(string $str): int
    {
        if (\function_exists('mb_strlen')) {
            return \mb_strlen($str, '8bit');
        }
        return \strlen($str);
    }
    /**
     * Convert an ECDSA signature to an ASN.1 DER sequence
     *
     * @param   string $sig The ECDSA signature to convert
     * @return  string The encoded DER object
     */
    private static function signatureToDER(string $sig): string
    {
        // Separate the signature into r-value and s-value
        $length = max(1, (int) (\strlen($sig) / 2));
        list($r, $s) = \str_split($sig, $length);
        // Trim leading zeros
        $r = \ltrim($r, "\x00");
        $s = \ltrim($s, "\x00");
        // Convert r-value and s-value from unsigned big-endian integers to
        // signed two's complement
        if (\ord($r[0]) > 0x7f) {
            $r = "\x00" . $r;
        }
        if (\ord($s[0]) > 0x7f) {
            $s = "\x00" . $s;
        }
        return self::encodeDER(self::ASN1_SEQUENCE, self::encodeDER(self::ASN1_INTEGER, $r) . self::encodeDER(self::ASN1_INTEGER, $s));
    }
    /**
     * Encodes a value into a DER object.
     *
     * @param   int     $type DER tag
     * @param   string  $value the value to encode
     *
     * @return  string  the encoded object
     */
    private static function encodeDER(int $type, string $value): string
    {
        $tag_header = 0;
        if ($type === self::ASN1_SEQUENCE) {
            $tag_header |= 0x20;
        }
        // Type
        $der = \chr($tag_header | $type);
        // Length
        $der .= \chr(\strlen($value));
        return $der . $value;
    }
    /**
     * Encodes signature from a DER object.
     *
     * @param   string  $der binary signature in DER format
     * @param   int     $keySize the number of bits in the key
     *
     * @return  string  the signature
     */
    private static function signatureFromDER(string $der, int $keySize): string
    {
        // OpenSSL returns the ECDSA signatures as a binary ASN.1 DER SEQUENCE
        list($offset, $_) = self::readDER($der);
        list($offset, $r) = self::readDER($der, $offset);
        list($offset, $s) = self::readDER($der, $offset);
        // Convert r-value and s-value from signed two's compliment to unsigned
        // big-endian integers
        $r = \ltrim($r, "\x00");
        $s = \ltrim($s, "\x00");
        // Pad out r and s so that they are $keySize bits long
        $r = \str_pad($r, $keySize / 8, "\x00", \STR_PAD_LEFT);
        $s = \str_pad($s, $keySize / 8, "\x00", \STR_PAD_LEFT);
        return $r . $s;
    }
    /**
     * Reads binary DER-encoded data and decodes into a single object
     *
     * @param string $der the binary data in DER format
     * @param int $offset the offset of the data stream containing the object
     * to decode
     *
     * @return array{int, string|null} the new offset and the decoded object
     */
    private static function readDER(string $der, int $offset = 0): array
    {
        $pos = $offset;
        $size = \strlen($der);
        $constructed = \ord($der[$pos]) >> 5 & 0x1;
        $type = \ord($der[$pos++]) & 0x1f;
        // Length
        $len = \ord($der[$pos++]);
        if ($len & 0x80) {
            $n = $len & 0x1f;
            $len = 0;
            while ($n-- && $pos < $size) {
                $len = $len << 8 | \ord($der[$pos++]);
            }
        }
        // Value
        if ($type === self::ASN1_BIT_STRING) {
            $pos++;
            // Skip the first contents octet (padding indicator)
            $data = \substr($der, $pos, $len - 1);
            $pos += $len - 1;
        } elseif (!$constructed) {
            $data = \substr($der, $pos, $len);
            $pos += $len;
        } else {
            $data = null;
        }
        return [$pos, $data];
    }
    /**
     * Validate HMAC key length
     *
     * @param string $key HMAC key material
     * @param string $algorithm The algorithm
     *
     * @throws DomainException Provided key is too short
     */
    private static function validateHmacKeyLength(string $key, string $algorithm): void
    {
        $keyLength = \strlen($key) * 8;
        $minKeyLength = (int) \str_replace('SHA', '', $algorithm);
        if ($keyLength < $minKeyLength) {
            throw new DomainException('Provided key is too short');
        }
    }
    /**
     * Validate RSA key length
     *
     * @param OpenSSLAsymmetricKey $key RSA key material
     * @throws DomainException Provided key is too short
     */
    private static function validateRsaKeyLength(
        #[\SensitiveParameter]
        OpenSSLAsymmetricKey $key
    ): void
    {
        if (!$keyDetails = openssl_pkey_get_details($key)) {
            throw new DomainException('Unable to validate key');
        }
        if ($keyDetails['bits'] < self::RSA_KEY_MIN_LENGTH) {
            throw new DomainException('Provided key is too short');
        }
    }
    /**
     * Validate RSA key length
     *
     * @param OpenSSLAsymmetricKey $key RSA key material
     * @param string $algorithm The algorithm
     * @throws DomainException Provided key is too short
     */
    private static function validateEcKeyLength(
        #[\SensitiveParameter]
        OpenSSLAsymmetricKey $key,
        string $algorithm
    ): void
    {
        if (!$keyDetails = openssl_pkey_get_details($key)) {
            throw new DomainException('Unable to validate key');
        }
        $minKeyLength = (int) \str_replace('ES', '', $algorithm);
        if ($keyDetails['bits'] < $minKeyLength) {
            throw new DomainException('Provided key is too short');
        }
    }
    /**
     * @param string|OpenSSLAsymmetricKey|OpenSSLCertificate  $keyMaterial
     * @return non-empty-string
     */
    private static function validateEdDSAKey(
        #[\SensitiveParameter]
        $keyMaterial
    ): string
    {
        if (!\function_exists('sodium_crypto_sign_verify_detached') && !\function_exists('_ContaoManager\sodium_crypto_sign_verify_detached')) {
            throw new DomainException('libsodium is not available');
        }
        if (!\is_string($keyMaterial)) {
            throw new InvalidArgumentException('key must be a string when using EdDSA');
        }
        // The last non-empty line is used as the key.
        $lines = array_filter(explode("\n", $keyMaterial));
        $key = self::urlsafeB64Decode((string) end($lines));
        if (\strlen($key) === 0) {
            throw new DomainException('Key cannot be empty string');
        }
        return $key;
    }
}
The MIT License (MIT)

Copyright (c) 2013-present Benjamin Morel

Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
# Changelog

All notable changes to this project will be documented in this file.

## [0.13.1](https://github.com/brick/math/releases/tag/0.13.1) - 2025-03-29

✨ **Improvements**

- `__toString()` methods of `BigInteger` and `BigDecimal` are now type-hinted as returning `numeric-string` instead of `string` (#90 by @vudaltsov)

## [0.13.0](https://github.com/brick/math/releases/tag/0.13.0) - 2025-03-03

💥 **Breaking changes**

- `BigDecimal::ofUnscaledValue()` no longer throws an exception if the scale is negative
- `MathException` now extends `RuntimeException` instead of `Exception`; this reverts the change introduced in version `0.11.0` (#82)

✨ **New features**

- `BigDecimal::ofUnscaledValue()` allows a negative scale (and converts the values to create a zero scale number)

## [0.12.3](https://github.com/brick/math/releases/tag/0.12.3) - 2025-02-28

✨ **New features**

- `BigDecimal::getPrecision()` Returns the number of significant digits in a decimal number

## [0.12.2](https://github.com/brick/math/releases/tag/0.12.2) - 2025-02-26

⚡️ **Performance improvements**

- Division in `NativeCalculator` is now faster for small divisors, thanks to [@Izumi-kun](https://github.com/Izumi-kun) in [#87](https://github.com/brick/math/pull/87).

👌 **Improvements**

- Add missing `RoundingNecessaryException` to the `@throws` annotation of `BigNumber::of()`

## [0.12.1](https://github.com/brick/math/releases/tag/0.12.1) - 2023-11-29

⚡️ **Performance improvements**

- `BigNumber::of()` is now faster, thanks to [@SebastienDug](https://github.com/SebastienDug) in [#77](https://github.com/brick/math/pull/77).

## [0.12.0](https://github.com/brick/math/releases/tag/0.12.0) - 2023-11-26

💥 **Breaking changes**

- Minimum PHP version is now 8.1
- `RoundingMode` is now an `enum`; if you're type-hinting rounding modes, you need to type-hint against `RoundingMode` instead of `int` now
- `BigNumber` classes do not implement the `Serializable` interface anymore (they use the [new custom object serialization mechanism](https://wiki.php.net/rfc/custom_object_serialization))
- The following breaking changes only affect you if you're creating your own `BigNumber` subclasses:
  - the return type of `BigNumber::of()` is now `static`
  - `BigNumber` has a new abstract method `from()`
  - all `public` and `protected` functions of `BigNumber` are now `final`

## [0.11.0](https://github.com/brick/math/releases/tag/0.11.0) - 2023-01-16

💥 **Breaking changes**

- Minimum PHP version is now 8.0
- Methods accepting a union of types are now strongly typed<sup>*</sup>
- `MathException` now extends `Exception` instead of `RuntimeException`

<sup>* You may now run into type errors if you were passing `Stringable` objects to `of()` or any of the methods
internally calling `of()`, with `strict_types` enabled. You can fix this by casting `Stringable` objects to `string`
first.</sup>

## [0.10.2](https://github.com/brick/math/releases/tag/0.10.2) - 2022-08-11

👌 **Improvements**

- `BigRational::toFloat()` now simplifies the fraction before performing division (#73) thanks to @olsavmic

## [0.10.1](https://github.com/brick/math/releases/tag/0.10.1) - 2022-08-02

✨ **New features**

- `BigInteger::gcdMultiple()` returns the GCD of multiple `BigInteger` numbers

## [0.10.0](https://github.com/brick/math/releases/tag/0.10.0) - 2022-06-18

💥 **Breaking changes**

- Minimum PHP version is now 7.4

## [0.9.3](https://github.com/brick/math/releases/tag/0.9.3) - 2021-08-15

🚀 **Compatibility with PHP 8.1**

- Support for custom object serialization; this removes a warning on PHP 8.1 due to the `Serializable` interface being deprecated (#60) thanks @TRowbotham

## [0.9.2](https://github.com/brick/math/releases/tag/0.9.2) - 2021-01-20

🐛 **Bug fix**

- Incorrect results could be returned when using the BCMath calculator, with a default scale set with `bcscale()`, on PHP >= 7.2 (#55).

## [0.9.1](https://github.com/brick/math/releases/tag/0.9.1) - 2020-08-19

✨ **New features**

- `BigInteger::not()` returns the bitwise `NOT` value

🐛 **Bug fixes**

- `BigInteger::toBytes()` could return an incorrect binary representation for some numbers
- The bitwise operations `and()`, `or()`, `xor()` on `BigInteger` could return an incorrect result when the GMP extension is not available

## [0.9.0](https://github.com/brick/math/releases/tag/0.9.0) - 2020-08-18

👌 **Improvements**

- `BigNumber::of()` now accepts `.123` and `123.` formats, both of which return a `BigDecimal`

💥 **Breaking changes**

- Deprecated method `BigInteger::powerMod()` has been removed - use `modPow()` instead
- Deprecated method `BigInteger::parse()` has been removed - use `fromBase()` instead

## [0.8.17](https://github.com/brick/math/releases/tag/0.8.17) - 2020-08-19

🐛 **Bug fix**

- `BigInteger::toBytes()` could return an incorrect binary representation for some numbers
- The bitwise operations `and()`, `or()`, `xor()` on `BigInteger` could return an incorrect result when the GMP extension is not available

## [0.8.16](https://github.com/brick/math/releases/tag/0.8.16) - 2020-08-18

🚑 **Critical fix**

- This version reintroduces the deprecated `BigInteger::parse()` method, that has been removed by mistake in version `0.8.9` and should have lasted for the whole `0.8` release cycle.

✨ **New features**

- `BigInteger::modInverse()` calculates a modular multiplicative inverse
- `BigInteger::fromBytes()` creates a `BigInteger` from a byte string
- `BigInteger::toBytes()` converts a `BigInteger` to a byte string
- `BigInteger::randomBits()` creates a pseudo-random `BigInteger` of a given bit length
- `BigInteger::randomRange()` creates a pseudo-random `BigInteger` between two bounds

💩 **Deprecations**

- `BigInteger::powerMod()` is now deprecated in favour of `modPow()`

## [0.8.15](https://github.com/brick/math/releases/tag/0.8.15) - 2020-04-15

🐛 **Fixes**

- added missing `ext-json` requirement, due to `BigNumber` implementing `JsonSerializable`

⚡️ **Optimizations**

- additional optimization in `BigInteger::remainder()`

## [0.8.14](https://github.com/brick/math/releases/tag/0.8.14) - 2020-02-18

✨ **New features**

- `BigInteger::getLowestSetBit()` returns the index of the rightmost one bit

## [0.8.13](https://github.com/brick/math/releases/tag/0.8.13) - 2020-02-16

✨ **New features**

- `BigInteger::isEven()` tests whether the number is even
- `BigInteger::isOdd()` tests whether the number is odd
- `BigInteger::testBit()` tests if a bit is set
- `BigInteger::getBitLength()` returns the number of bits in the minimal representation of the number

## [0.8.12](https://github.com/brick/math/releases/tag/0.8.12) - 2020-02-03

🛠️ **Maintenance release**

Classes are now annotated for better static analysis with [psalm](https://psalm.dev/).

This is a maintenance release: no bug fixes, no new features, no breaking changes.

## [0.8.11](https://github.com/brick/math/releases/tag/0.8.11) - 2020-01-23

✨ **New feature**

`BigInteger::powerMod()` performs a power-with-modulo operation. Useful for crypto.

## [0.8.10](https://github.com/brick/math/releases/tag/0.8.10) - 2020-01-21

✨ **New feature**

`BigInteger::mod()` returns the **modulo** of two numbers. The *modulo* differs from the *remainder* when the signs of the operands are different.

## [0.8.9](https://github.com/brick/math/releases/tag/0.8.9) - 2020-01-08

⚡️ **Performance improvements**

A few additional optimizations in `BigInteger` and `BigDecimal` when one of the operands can be returned as is. Thanks to @tomtomsen in #24.

## [0.8.8](https://github.com/brick/math/releases/tag/0.8.8) - 2019-04-25

🐛 **Bug fixes**

- `BigInteger::toBase()` could return an empty string for zero values (BCMath & Native calculators only, GMP calculator unaffected)

✨ **New features**

- `BigInteger::toArbitraryBase()` converts a number to an arbitrary base, using a custom alphabet
- `BigInteger::fromArbitraryBase()` converts a string in an arbitrary base, using a custom alphabet, back to a number

These methods can be used as the foundation to convert strings between different bases/alphabets, using BigInteger as an intermediate representation.

💩 **Deprecations**

- `BigInteger::parse()` is now deprecated in favour of `fromBase()`

`BigInteger::fromBase()` works the same way as `parse()`, with 2 minor differences:

- the `$base` parameter is required, it does not default to `10`
- it throws a `NumberFormatException` instead of an `InvalidArgumentException` when the number is malformed

## [0.8.7](https://github.com/brick/math/releases/tag/0.8.7) - 2019-04-20

**Improvements**

- Safer conversion from `float` when using custom locales
- **Much faster** `NativeCalculator` implementation 🚀

You can expect **at least a 3x performance improvement** for common arithmetic operations when using the library on systems without GMP or BCMath; it gets exponentially faster on multiplications with a high number of digits. This is due to calculations now being performed on whole blocks of digits (the block size depending on the platform, 32-bit or 64-bit) instead of digit-by-digit as before.

## [0.8.6](https://github.com/brick/math/releases/tag/0.8.6) - 2019-04-11

**New method**

`BigNumber::sum()` returns the sum of one or more numbers.

## [0.8.5](https://github.com/brick/math/releases/tag/0.8.5) - 2019-02-12

**Bug fix**: `of()` factory methods could fail when passing a `float` in environments using a `LC_NUMERIC` locale with a decimal separator other than `'.'` (#20).

Thanks @manowark 👍

## [0.8.4](https://github.com/brick/math/releases/tag/0.8.4) - 2018-12-07

**New method**

`BigDecimal::sqrt()` calculates the square root of a decimal number, to a given scale.

## [0.8.3](https://github.com/brick/math/releases/tag/0.8.3) - 2018-12-06

**New method**

`BigInteger::sqrt()` calculates the square root of a number (thanks @peter279k).

**New exception**

`NegativeNumberException` is thrown when calling `sqrt()` on a negative number.

## [0.8.2](https://github.com/brick/math/releases/tag/0.8.2) - 2018-11-08

**Performance update**

- Further improvement of `toInt()` performance
- `NativeCalculator` can now perform some multiplications more efficiently

## [0.8.1](https://github.com/brick/math/releases/tag/0.8.1) - 2018-11-07

Performance optimization of `toInt()` methods.

## [0.8.0](https://github.com/brick/math/releases/tag/0.8.0) - 2018-10-13

**Breaking changes**

The following deprecated methods have been removed. Use the new method name instead:

| Method removed | Replacement method |
| --- | --- |
| `BigDecimal::getIntegral()` | `BigDecimal::getIntegralPart()` |
| `BigDecimal::getFraction()` | `BigDecimal::getFractionalPart()` |

---

**New features**

`BigInteger` has been augmented with 5 new methods for bitwise operations:

| New method | Description |
| --- | --- |
| `and()` | performs a bitwise `AND` operation on two numbers |
| `or()` | performs a bitwise `OR` operation on two numbers |
| `xor()` | performs a bitwise `XOR` operation on two numbers |
| `shiftedLeft()` | returns the number shifted left by a number of bits |
| `shiftedRight()` | returns the number shifted right by a number of bits |

Thanks to @DASPRiD 👍

## [0.7.3](https://github.com/brick/math/releases/tag/0.7.3) - 2018-08-20

**New method:** `BigDecimal::hasNonZeroFractionalPart()`

**Renamed/deprecated methods:**

- `BigDecimal::getIntegral()` has been renamed to `getIntegralPart()` and is now deprecated
- `BigDecimal::getFraction()` has been renamed to `getFractionalPart()` and is now deprecated

## [0.7.2](https://github.com/brick/math/releases/tag/0.7.2) - 2018-07-21

**Performance update**

`BigInteger::parse()` and `toBase()` now use GMP's built-in base conversion features when available.

## [0.7.1](https://github.com/brick/math/releases/tag/0.7.1) - 2018-03-01

This is a maintenance release, no code has been changed.

- When installed with `--no-dev`, the autoloader does not autoload tests anymore
- Tests and other files unnecessary for production are excluded from the dist package

This will help make installations more compact.

## [0.7.0](https://github.com/brick/math/releases/tag/0.7.0) - 2017-10-02

Methods renamed:

- `BigNumber:sign()` has been renamed to `getSign()`
- `BigDecimal::unscaledValue()` has been renamed to `getUnscaledValue()`
- `BigDecimal::scale()` has been renamed to `getScale()`
- `BigDecimal::integral()` has been renamed to `getIntegral()`
- `BigDecimal::fraction()` has been renamed to `getFraction()`
- `BigRational::numerator()` has been renamed to `getNumerator()`
- `BigRational::denominator()` has been renamed to `getDenominator()`

Classes renamed:

- `ArithmeticException` has been renamed to `MathException`

## [0.6.2](https://github.com/brick/math/releases/tag/0.6.2) - 2017-10-02

The base class for all exceptions is now `MathException`.
`ArithmeticException` has been deprecated, and will be removed in 0.7.0.

## [0.6.1](https://github.com/brick/math/releases/tag/0.6.1) - 2017-10-02

A number of methods have been renamed:

- `BigNumber:sign()` is deprecated; use `getSign()` instead
- `BigDecimal::unscaledValue()` is deprecated; use `getUnscaledValue()` instead
- `BigDecimal::scale()` is deprecated; use `getScale()` instead
- `BigDecimal::integral()` is deprecated; use `getIntegral()` instead
- `BigDecimal::fraction()` is deprecated; use `getFraction()` instead
- `BigRational::numerator()` is deprecated; use `getNumerator()` instead
- `BigRational::denominator()` is deprecated; use `getDenominator()` instead

The old methods will be removed in version 0.7.0.

## [0.6.0](https://github.com/brick/math/releases/tag/0.6.0) - 2017-08-25

- Minimum PHP version is now [7.1](https://gophp71.org/); for PHP 5.6 and PHP 7.0 support, use version `0.5`
- Deprecated method `BigDecimal::withScale()` has been removed; use `toScale()` instead
- Method `BigNumber::toInteger()` has been renamed to `toInt()`

## [0.5.4](https://github.com/brick/math/releases/tag/0.5.4) - 2016-10-17

`BigNumber` classes now implement [JsonSerializable](http://php.net/manual/en/class.jsonserializable.php).
The JSON output is always a string.

## [0.5.3](https://github.com/brick/math/releases/tag/0.5.3) - 2016-03-31

This is a bugfix release. Dividing by a negative power of 1 with the same scale as the dividend could trigger an incorrect optimization which resulted in a wrong result. See #6.

## [0.5.2](https://github.com/brick/math/releases/tag/0.5.2) - 2015-08-06

The `$scale` parameter of `BigDecimal::dividedBy()` is now optional again.

## [0.5.1](https://github.com/brick/math/releases/tag/0.5.1) - 2015-07-05

**New method: `BigNumber::toScale()`**

This allows to convert any `BigNumber` to a `BigDecimal` with a given scale, using rounding if necessary.

## [0.5.0](https://github.com/brick/math/releases/tag/0.5.0) - 2015-07-04

**New features**
- Common `BigNumber` interface for all classes, with the following methods:
  - `sign()` and derived methods (`isZero()`, `isPositive()`, ...)
  - `compareTo()` and derived methods (`isEqualTo()`, `isGreaterThan()`, ...) that work across different `BigNumber` types
  - `toBigInteger()`, `toBigDecimal()`, `toBigRational`() conversion methods
  - `toInteger()` and `toFloat()` conversion methods to native types
- Unified `of()` behaviour: every class now accepts any type of number, provided that it can be safely converted to the current type
- New method: `BigDecimal::exactlyDividedBy()`; this method automatically computes the scale of the result, provided that the division yields a finite number of digits
- New methods: `BigRational::quotient()` and `remainder()`
- Fine-grained exceptions: `DivisionByZeroException`, `RoundingNecessaryException`, `NumberFormatException`
- Factory methods `zero()`, `one()` and `ten()` available in all classes
- Rounding mode reintroduced in `BigInteger::dividedBy()`

This release also comes with many performance improvements.

---

**Breaking changes**
- `BigInteger`:
  - `getSign()` is renamed to `sign()`
  - `toString()` is renamed to `toBase()`
  - `BigInteger::dividedBy()` now throws an exception by default if the remainder is not zero; use `quotient()` to get the previous behaviour
- `BigDecimal`:
  - `getSign()` is renamed to `sign()`
  - `getUnscaledValue()` is renamed to `unscaledValue()`
  - `getScale()` is renamed to `scale()`
  - `getIntegral()` is renamed to `integral()`
  - `getFraction()` is renamed to `fraction()`
  - `divideAndRemainder()` is renamed to `quotientAndRemainder()`
  - `dividedBy()` now takes a **mandatory** `$scale` parameter **before** the rounding mode
  - `toBigInteger()` does not accept a `$roundingMode` parameter anymore
  - `toBigRational()` does not simplify the fraction anymore; explicitly add `->simplified()` to get the previous behaviour
- `BigRational`:
  - `getSign()` is renamed to `sign()`
  - `getNumerator()` is renamed to  `numerator()`
  - `getDenominator()` is renamed to  `denominator()`
  - `of()` is renamed to `nd()`, while `parse()` is renamed to `of()`
- Miscellaneous:
  - `ArithmeticException` is moved to an `Exception\` sub-namespace
  - `of()` factory methods now throw `NumberFormatException` instead of `InvalidArgumentException`

## [0.4.3](https://github.com/brick/math/releases/tag/0.4.3) - 2016-03-31

Backport of two bug fixes from the 0.5 branch:
- `BigInteger::parse()` did not always throw `InvalidArgumentException` as expected
- Dividing by a negative power of 1 with the same scale as the dividend could trigger an incorrect optimization which resulted in a wrong result. See #6.

## [0.4.2](https://github.com/brick/math/releases/tag/0.4.2) - 2015-06-16

New method: `BigDecimal::stripTrailingZeros()`

## [0.4.1](https://github.com/brick/math/releases/tag/0.4.1) - 2015-06-12

Introducing a `BigRational` class, to perform calculations on fractions of any size.

## [0.4.0](https://github.com/brick/math/releases/tag/0.4.0) - 2015-06-12

Rounding modes have been removed from `BigInteger`, and are now a concept specific to `BigDecimal`.

`BigInteger::dividedBy()` now always returns the quotient of the division.

## [0.3.5](https://github.com/brick/math/releases/tag/0.3.5) - 2016-03-31

Backport of two bug fixes from the 0.5 branch:

- `BigInteger::parse()` did not always throw `InvalidArgumentException` as expected
- Dividing by a negative power of 1 with the same scale as the dividend could trigger an incorrect optimization which resulted in a wrong result. See #6.

## [0.3.4](https://github.com/brick/math/releases/tag/0.3.4) - 2015-06-11

New methods:
- `BigInteger::remainder()` returns the remainder of a division only
- `BigInteger::gcd()` returns the greatest common divisor of two numbers

## [0.3.3](https://github.com/brick/math/releases/tag/0.3.3) - 2015-06-07

Fix `toString()` not handling negative numbers.

## [0.3.2](https://github.com/brick/math/releases/tag/0.3.2) - 2015-06-07

`BigInteger` and `BigDecimal` now have a `getSign()` method that returns:
- `-1` if the number is negative
- `0` if the number is zero
- `1` if the number is positive

## [0.3.1](https://github.com/brick/math/releases/tag/0.3.1) - 2015-06-05

Minor performance improvements

## [0.3.0](https://github.com/brick/math/releases/tag/0.3.0) - 2015-06-04

The `$roundingMode` and `$scale` parameters have been swapped in `BigDecimal::dividedBy()`.

## [0.2.2](https://github.com/brick/math/releases/tag/0.2.2) - 2015-06-04

Stronger immutability guarantee for `BigInteger` and `BigDecimal`.

So far, it would have been possible to break immutability of these classes by calling the `unserialize()` internal function. This release fixes that.

## [0.2.1](https://github.com/brick/math/releases/tag/0.2.1) - 2015-06-02

Added `BigDecimal::divideAndRemainder()`

## [0.2.0](https://github.com/brick/math/releases/tag/0.2.0) - 2015-05-22

- `min()` and `max()` do not accept an `array` anymore, but a variable number of parameters
- **minimum PHP version is now 5.6**
- continuous integration with PHP 7

## [0.1.1](https://github.com/brick/math/releases/tag/0.1.1) - 2014-09-01

- Added `BigInteger::power()`
- Added HHVM support

## [0.1.0](https://github.com/brick/math/releases/tag/0.1.0) - 2014-08-31

First beta release.

<?xml version="1.0" encoding="UTF-8"?>
<files psalm-version="6.8.8@1361cd33008feb3ae2b4a93f1860e14e538ec8c2">
  <file src="src/BigInteger.php">
    <FalsableReturnStatement>
      <code><![CDATA[\hex2bin($hex)]]></code>
    </FalsableReturnStatement>
    <InvalidFalsableReturnType>
      <code><![CDATA[string]]></code>
    </InvalidFalsableReturnType>
  </file>
  <file src="src/Exception/DivisionByZeroException.php">
    <ClassMustBeFinal>
      <code><![CDATA[DivisionByZeroException]]></code>
    </ClassMustBeFinal>
  </file>
  <file src="src/Exception/IntegerOverflowException.php">
    <ClassMustBeFinal>
      <code><![CDATA[IntegerOverflowException]]></code>
    </ClassMustBeFinal>
  </file>
  <file src="src/Exception/NegativeNumberException.php">
    <ClassMustBeFinal>
      <code><![CDATA[NegativeNumberException]]></code>
    </ClassMustBeFinal>
  </file>
  <file src="src/Exception/NumberFormatException.php">
    <ClassMustBeFinal>
      <code><![CDATA[NumberFormatException]]></code>
    </ClassMustBeFinal>
  </file>
  <file src="src/Exception/RoundingNecessaryException.php">
    <ClassMustBeFinal>
      <code><![CDATA[RoundingNecessaryException]]></code>
    </ClassMustBeFinal>
  </file>
  <file src="src/Internal/Calculator/BcMathCalculator.php">
    <ClassMustBeFinal>
      <code><![CDATA[BcMathCalculator]]></code>
    </ClassMustBeFinal>
  </file>
  <file src="src/Internal/Calculator/GmpCalculator.php">
    <ClassMustBeFinal>
      <code><![CDATA[GmpCalculator]]></code>
    </ClassMustBeFinal>
  </file>
  <file src="src/Internal/Calculator/NativeCalculator.php">
    <ClassMustBeFinal>
      <code><![CDATA[NativeCalculator]]></code>
    </ClassMustBeFinal>
    <InvalidOperand>
      <code><![CDATA[$a * $b]]></code>
      <code><![CDATA[$a * 1]]></code>
      <code><![CDATA[$a + $b]]></code>
      <code><![CDATA[$b * 1]]></code>
      <code><![CDATA[$b * 1]]></code>
      <code><![CDATA[$blockA * $blockB + $carry]]></code>
      <code><![CDATA[$blockA + $blockB]]></code>
      <code><![CDATA[$blockA + $blockB + $carry]]></code>
      <code><![CDATA[$blockA - $blockB]]></code>
      <code><![CDATA[$blockA - $blockB - $carry]]></code>
      <code><![CDATA[$carry]]></code>
      <code><![CDATA[$mul % $complement]]></code>
      <code><![CDATA[$mul - $value]]></code>
      <code><![CDATA[$nb - 1]]></code>
      <code><![CDATA[$sum += $complement]]></code>
      <code><![CDATA[($mul - $value) / $complement]]></code>
      <code><![CDATA[($nb - 1) * 10]]></code>
    </InvalidOperand>
  </file>
</files>
{
    "name": "brick\/math",
    "description": "Arbitrary-precision arithmetic library",
    "type": "library",
    "keywords": [
        "Brick",
        "Math",
        "Mathematics",
        "Arbitrary-precision",
        "Arithmetic",
        "BigInteger",
        "BigDecimal",
        "BigRational",
        "BigNumber",
        "Bignum",
        "Decimal",
        "Rational",
        "Integer"
    ],
    "license": "MIT",
    "require": {
        "php": "^8.1"
    },
    "require-dev": {
        "phpunit\/phpunit": "^10.1",
        "php-coveralls\/php-coveralls": "^2.2",
        "vimeo\/psalm": "6.8.8"
    },
    "autoload": {
        "psr-4": {
            "_ContaoManager\\Brick\\Math\\": "src\/"
        }
    },
    "autoload-dev": {
        "psr-4": {
            "_ContaoManager\\Brick\\Math\\Tests\\": "tests\/"
        }
    }
}<?php

declare (strict_types=1);
namespace _ContaoManager\Brick\Math;

/**
 * Specifies a rounding behavior for numerical operations capable of discarding precision.
 *
 * Each rounding mode indicates how the least significant returned digit of a rounded result
 * is to be calculated. If fewer digits are returned than the digits needed to represent the
 * exact numerical result, the discarded digits will be referred to as the discarded fraction
 * regardless the digits' contribution to the value of the number. In other words, considered
 * as a numerical value, the discarded fraction could have an absolute value greater than one.
 */
enum RoundingMode
{
    /**
     * Asserts that the requested operation has an exact result, hence no rounding is necessary.
     *
     * If this rounding mode is specified on an operation that yields a result that
     * cannot be represented at the requested scale, a RoundingNecessaryException is thrown.
     */
    case UNNECESSARY;
    /**
     * Rounds away from zero.
     *
     * Always increments the digit prior to a nonzero discarded fraction.
     * Note that this rounding mode never decreases the magnitude of the calculated value.
     */
    case UP;
    /**
     * Rounds towards zero.
     *
     * Never increments the digit prior to a discarded fraction (i.e., truncates).
     * Note that this rounding mode never increases the magnitude of the calculated value.
     */
    case DOWN;
    /**
     * Rounds towards positive infinity.
     *
     * If the result is positive, behaves as for UP; if negative, behaves as for DOWN.
     * Note that this rounding mode never decreases the calculated value.
     */
    case CEILING;
    /**
     * Rounds towards negative infinity.
     *
     * If the result is positive, behave as for DOWN; if negative, behave as for UP.
     * Note that this rounding mode never increases the calculated value.
     */
    case FLOOR;
    /**
     * Rounds towards "nearest neighbor" unless both neighbors are equidistant, in which case round up.
     *
     * Behaves as for UP if the discarded fraction is >= 0.5; otherwise, behaves as for DOWN.
     * Note that this is the rounding mode commonly taught at school.
     */
    case HALF_UP;
    /**
     * Rounds towards "nearest neighbor" unless both neighbors are equidistant, in which case round down.
     *
     * Behaves as for UP if the discarded fraction is > 0.5; otherwise, behaves as for DOWN.
     */
    case HALF_DOWN;
    /**
     * Rounds towards "nearest neighbor" unless both neighbors are equidistant, in which case round towards positive infinity.
     *
     * If the result is positive, behaves as for HALF_UP; if negative, behaves as for HALF_DOWN.
     */
    case HALF_CEILING;
    /**
     * Rounds towards "nearest neighbor" unless both neighbors are equidistant, in which case round towards negative infinity.
     *
     * If the result is positive, behaves as for HALF_DOWN; if negative, behaves as for HALF_UP.
     */
    case HALF_FLOOR;
    /**
     * Rounds towards the "nearest neighbor" unless both neighbors are equidistant, in which case rounds towards the even neighbor.
     *
     * Behaves as for HALF_UP if the digit to the left of the discarded fraction is odd;
     * behaves as for HALF_DOWN if it's even.
     *
     * Note that this is the rounding mode that statistically minimizes
     * cumulative error when applied repeatedly over a sequence of calculations.
     * It is sometimes known as "Banker's rounding", and is chiefly used in the USA.
     */
    case HALF_EVEN;
}
<?php

declare (strict_types=1);
namespace _ContaoManager\Brick\Math\Internal\Calculator;

use _ContaoManager\Brick\Math\Internal\Calculator;
use Override;
/**
 * Calculator implementation built around the GMP library.
 *
 * @internal
 *
 * @psalm-immutable
 */
class GmpCalculator extends Calculator
{
    #[Override]
    public function add(string $a, string $b): string
    {
        return \gmp_strval(\gmp_add($a, $b));
    }
    #[Override]
    public function sub(string $a, string $b): string
    {
        return \gmp_strval(\gmp_sub($a, $b));
    }
    #[Override]
    public function mul(string $a, string $b): string
    {
        return \gmp_strval(\gmp_mul($a, $b));
    }
    #[Override]
    public function divQ(string $a, string $b): string
    {
        return \gmp_strval(\gmp_div_q($a, $b));
    }
    #[Override]
    public function divR(string $a, string $b): string
    {
        return \gmp_strval(\gmp_div_r($a, $b));
    }
    #[Override]
    public function divQR(string $a, string $b): array
    {
        [$q, $r] = \gmp_div_qr($a, $b);
        return [\gmp_strval($q), \gmp_strval($r)];
    }
    #[Override]
    public function pow(string $a, int $e): string
    {
        return \gmp_strval(\gmp_pow($a, $e));
    }
    #[Override]
    public function modInverse(string $x, string $m): ?string
    {
        $result = \gmp_invert($x, $m);
        if ($result === \false) {
            return null;
        }
        return \gmp_strval($result);
    }
    #[Override]
    public function modPow(string $base, string $exp, string $mod): string
    {
        return \gmp_strval(\gmp_powm($base, $exp, $mod));
    }
    #[Override]
    public function gcd(string $a, string $b): string
    {
        return \gmp_strval(\gmp_gcd($a, $b));
    }
    #[Override]
    public function fromBase(string $number, int $base): string
    {
        return \gmp_strval(\gmp_init($number, $base));
    }
    #[Override]
    public function toBase(string $number, int $base): string
    {
        return \gmp_strval($number, $base);
    }
    #[Override]
    public function and(string $a, string $b): string
    {
        return \gmp_strval(\gmp_and($a, $b));
    }
    #[Override]
    public function or(string $a, string $b): string
    {
        return \gmp_strval(\gmp_or($a, $b));
    }
    #[Override]
    public function xor(string $a, string $b): string
    {
        return \gmp_strval(\gmp_xor($a, $b));
    }
    #[Override]
    public function sqrt(string $n): string
    {
        return \gmp_strval(\gmp_sqrt($n));
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\Brick\Math\Internal\Calculator;

use _ContaoManager\Brick\Math\Internal\Calculator;
use Override;
/**
 * Calculator implementation built around the bcmath library.
 *
 * @internal
 *
 * @psalm-immutable
 */
class BcMathCalculator extends Calculator
{
    #[Override]
    public function add(string $a, string $b): string
    {
        return \bcadd($a, $b, 0);
    }
    #[Override]
    public function sub(string $a, string $b): string
    {
        return \bcsub($a, $b, 0);
    }
    #[Override]
    public function mul(string $a, string $b): string
    {
        return \bcmul($a, $b, 0);
    }
    #[Override]
    public function divQ(string $a, string $b): string
    {
        return \bcdiv($a, $b, 0);
    }
    #[Override]
    public function divR(string $a, string $b): string
    {
        return \bcmod($a, $b, 0);
    }
    #[Override]
    public function divQR(string $a, string $b): array
    {
        $q = \bcdiv($a, $b, 0);
        $r = \bcmod($a, $b, 0);
        return [$q, $r];
    }
    #[Override]
    public function pow(string $a, int $e): string
    {
        return \bcpow($a, (string) $e, 0);
    }
    #[Override]
    public function modPow(string $base, string $exp, string $mod): string
    {
        return \bcpowmod($base, $exp, $mod, 0);
    }
    #[Override]
    public function sqrt(string $n): string
    {
        return \bcsqrt($n, 0);
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\Brick\Math\Internal\Calculator;

use _ContaoManager\Brick\Math\Internal\Calculator;
use Override;
/**
 * Calculator implementation using only native PHP code.
 *
 * @internal
 *
 * @psalm-immutable
 */
class NativeCalculator extends Calculator
{
    /**
     * The max number of digits the platform can natively add, subtract, multiply or divide without overflow.
     * For multiplication, this represents the max sum of the lengths of both operands.
     *
     * In addition, it is assumed that an extra digit can hold a carry (1) without overflowing.
     * Example: 32-bit: max number 1,999,999,999 (9 digits + carry)
     *          64-bit: max number 1,999,999,999,999,999,999 (18 digits + carry)
     */
    private readonly int $maxDigits;
    /**
     * @codeCoverageIgnore
     */
    public function __construct()
    {
        $this->maxDigits = match (\PHP_INT_SIZE) {
            4 => 9,
            8 => 18,
            default => throw new \RuntimeException('The platform is not 32-bit or 64-bit as expected.'),
        };
    }
    #[Override]
    public function add(string $a, string $b): string
    {
        /**
         * @psalm-var numeric-string $a
         * @psalm-var numeric-string $b
         */
        $result = $a + $b;
        if (is_int($result)) {
            return (string) $result;
        }
        if ($a === '0') {
            return $b;
        }
        if ($b === '0') {
            return $a;
        }
        [$aNeg, $bNeg, $aDig, $bDig] = $this->init($a, $b);
        $result = $aNeg === $bNeg ? $this->doAdd($aDig, $bDig) : $this->doSub($aDig, $bDig);
        if ($aNeg) {
            $result = $this->neg($result);
        }
        return $result;
    }
    #[Override]
    public function sub(string $a, string $b): string
    {
        return $this->add($a, $this->neg($b));
    }
    #[Override]
    public function mul(string $a, string $b): string
    {
        /**
         * @psalm-var numeric-string $a
         * @psalm-var numeric-string $b
         */
        $result = $a * $b;
        if (is_int($result)) {
            return (string) $result;
        }
        if ($a === '0' || $b === '0') {
            return '0';
        }
        if ($a === '1') {
            return $b;
        }
        if ($b === '1') {
            return $a;
        }
        if ($a === '-1') {
            return $this->neg($b);
        }
        if ($b === '-1') {
            return $this->neg($a);
        }
        [$aNeg, $bNeg, $aDig, $bDig] = $this->init($a, $b);
        $result = $this->doMul($aDig, $bDig);
        if ($aNeg !== $bNeg) {
            $result = $this->neg($result);
        }
        return $result;
    }
    #[Override]
    public function divQ(string $a, string $b): string
    {
        return $this->divQR($a, $b)[0];
    }
    #[Override]
    public function divR(string $a, string $b): string
    {
        return $this->divQR($a, $b)[1];
    }
    #[Override]
    public function divQR(string $a, string $b): array
    {
        if ($a === '0') {
            return ['0', '0'];
        }
        if ($a === $b) {
            return ['1', '0'];
        }
        if ($b === '1') {
            return [$a, '0'];
        }
        if ($b === '-1') {
            return [$this->neg($a), '0'];
        }
        /** @psalm-var numeric-string $a */
        $na = $a * 1;
        // cast to number
        if (is_int($na)) {
            /** @psalm-var numeric-string $b */
            $nb = $b * 1;
            if (is_int($nb)) {
                // the only division that may overflow is PHP_INT_MIN / -1,
                // which cannot happen here as we've already handled a divisor of -1 above.
                $q = intdiv($na, $nb);
                $r = $na % $nb;
                return [(string) $q, (string) $r];
            }
        }
        [$aNeg, $bNeg, $aDig, $bDig] = $this->init($a, $b);
        [$q, $r] = $this->doDiv($aDig, $bDig);
        if ($aNeg !== $bNeg) {
            $q = $this->neg($q);
        }
        if ($aNeg) {
            $r = $this->neg($r);
        }
        return [$q, $r];
    }
    #[Override]
    public function pow(string $a, int $e): string
    {
        if ($e === 0) {
            return '1';
        }
        if ($e === 1) {
            return $a;
        }
        $odd = $e % 2;
        $e -= $odd;
        $aa = $this->mul($a, $a);
        /** @psalm-suppress PossiblyInvalidArgument We're sure that $e / 2 is an int now */
        $result = $this->pow($aa, $e / 2);
        if ($odd === 1) {
            $result = $this->mul($result, $a);
        }
        return $result;
    }
    /**
     * Algorithm from: https://www.geeksforgeeks.org/modular-exponentiation-power-in-modular-arithmetic/
     */
    #[Override]
    public function modPow(string $base, string $exp, string $mod): string
    {
        // special case: the algorithm below fails with 0 power 0 mod 1 (returns 1 instead of 0)
        if ($base === '0' && $exp === '0' && $mod === '1') {
            return '0';
        }
        // special case: the algorithm below fails with power 0 mod 1 (returns 1 instead of 0)
        if ($exp === '0' && $mod === '1') {
            return '0';
        }
        $x = $base;
        $res = '1';
        // numbers are positive, so we can use remainder instead of modulo
        $x = $this->divR($x, $mod);
        while ($exp !== '0') {
            if (in_array($exp[-1], ['1', '3', '5', '7', '9'])) {
                // odd
                $res = $this->divR($this->mul($res, $x), $mod);
            }
            $exp = $this->divQ($exp, '2');
            $x = $this->divR($this->mul($x, $x), $mod);
        }
        return $res;
    }
    /**
     * Adapted from https://cp-algorithms.com/num_methods/roots_newton.html
     */
    #[Override]
    public function sqrt(string $n): string
    {
        if ($n === '0') {
            return '0';
        }
        // initial approximation
        $x = \str_repeat('9', \intdiv(\strlen($n), 2) ?: 1);
        $decreased = \false;
        for (;;) {
            $nx = $this->divQ($this->add($x, $this->divQ($n, $x)), '2');
            if ($x === $nx || $this->cmp($nx, $x) > 0 && $decreased) {
                break;
            }
            $decreased = $this->cmp($nx, $x) < 0;
            $x = $nx;
        }
        return $x;
    }
    /**
     * Performs the addition of two non-signed large integers.
     */
    private function doAdd(string $a, string $b): string
    {
        [$a, $b, $length] = $this->pad($a, $b);
        $carry = 0;
        $result = '';
        for ($i = $length - $this->maxDigits;; $i -= $this->maxDigits) {
            $blockLength = $this->maxDigits;
            if ($i < 0) {
                $blockLength += $i;
                /** @psalm-suppress LoopInvalidation */
                $i = 0;
            }
            /** @psalm-var numeric-string $blockA */
            $blockA = \substr($a, $i, $blockLength);
            /** @psalm-var numeric-string $blockB */
            $blockB = \substr($b, $i, $blockLength);
            $sum = (string) ($blockA + $blockB + $carry);
            $sumLength = \strlen($sum);
            if ($sumLength > $blockLength) {
                $sum = \substr($sum, 1);
                $carry = 1;
            } else {
                if ($sumLength < $blockLength) {
                    $sum = \str_repeat('0', $blockLength - $sumLength) . $sum;
                }
                $carry = 0;
            }
            $result = $sum . $result;
            if ($i === 0) {
                break;
            }
        }
        if ($carry === 1) {
            $result = '1' . $result;
        }
        return $result;
    }
    /**
     * Performs the subtraction of two non-signed large integers.
     */
    private function doSub(string $a, string $b): string
    {
        if ($a === $b) {
            return '0';
        }
        // Ensure that we always subtract to a positive result: biggest minus smallest.
        $cmp = $this->doCmp($a, $b);
        $invert = $cmp === -1;
        if ($invert) {
            $c = $a;
            $a = $b;
            $b = $c;
        }
        [$a, $b, $length] = $this->pad($a, $b);
        $carry = 0;
        $result = '';
        $complement = 10 ** $this->maxDigits;
        for ($i = $length - $this->maxDigits;; $i -= $this->maxDigits) {
            $blockLength = $this->maxDigits;
            if ($i < 0) {
                $blockLength += $i;
                /** @psalm-suppress LoopInvalidation */
                $i = 0;
            }
            /** @psalm-var numeric-string $blockA */
            $blockA = \substr($a, $i, $blockLength);
            /** @psalm-var numeric-string $blockB */
            $blockB = \substr($b, $i, $blockLength);
            $sum = $blockA - $blockB - $carry;
            if ($sum < 0) {
                $sum += $complement;
                $carry = 1;
            } else {
                $carry = 0;
            }
            $sum = (string) $sum;
            $sumLength = \strlen($sum);
            if ($sumLength < $blockLength) {
                $sum = \str_repeat('0', $blockLength - $sumLength) . $sum;
            }
            $result = $sum . $result;
            if ($i === 0) {
                break;
            }
        }
        // Carry cannot be 1 when the loop ends, as a > b
        assert($carry === 0);
        $result = \ltrim($result, '0');
        if ($invert) {
            $result = $this->neg($result);
        }
        return $result;
    }
    /**
     * Performs the multiplication of two non-signed large integers.
     */
    private function doMul(string $a, string $b): string
    {
        $x = \strlen($a);
        $y = \strlen($b);
        $maxDigits = \intdiv($this->maxDigits, 2);
        $complement = 10 ** $maxDigits;
        $result = '0';
        for ($i = $x - $maxDigits;; $i -= $maxDigits) {
            $blockALength = $maxDigits;
            if ($i < 0) {
                $blockALength += $i;
                /** @psalm-suppress LoopInvalidation */
                $i = 0;
            }
            $blockA = (int) \substr($a, $i, $blockALength);
            $line = '';
            $carry = 0;
            for ($j = $y - $maxDigits;; $j -= $maxDigits) {
                $blockBLength = $maxDigits;
                if ($j < 0) {
                    $blockBLength += $j;
                    /** @psalm-suppress LoopInvalidation */
                    $j = 0;
                }
                $blockB = (int) \substr($b, $j, $blockBLength);
                $mul = $blockA * $blockB + $carry;
                $value = $mul % $complement;
                $carry = ($mul - $value) / $complement;
                $value = (string) $value;
                $value = \str_pad($value, $maxDigits, '0', \STR_PAD_LEFT);
                $line = $value . $line;
                if ($j === 0) {
                    break;
                }
            }
            if ($carry !== 0) {
                $line = $carry . $line;
            }
            $line = \ltrim($line, '0');
            if ($line !== '') {
                $line .= \str_repeat('0', $x - $blockALength - $i);
                $result = $this->add($result, $line);
            }
            if ($i === 0) {
                break;
            }
        }
        return $result;
    }
    /**
     * Performs the division of two non-signed large integers.
     *
     * @return string[] The quotient and remainder.
     */
    private function doDiv(string $a, string $b): array
    {
        $cmp = $this->doCmp($a, $b);
        if ($cmp === -1) {
            return ['0', $a];
        }
        $x = \strlen($a);
        $y = \strlen($b);
        // we now know that a >= b && x >= y
        $q = '0';
        // quotient
        $r = $a;
        // remainder
        $z = $y;
        // focus length, always $y or $y+1
        /** @psalm-var numeric-string $b */
        $nb = $b * 1;
        // cast to number
        // performance optimization in cases where the remainder will never cause int overflow
        if (is_int(($nb - 1) * 10 + 9)) {
            $r = (int) \substr($a, 0, $z - 1);
            for ($i = $z - 1; $i < $x; $i++) {
                $n = $r * 10 + (int) $a[$i];
                /** @psalm-var int $nb */
                $q .= \intdiv($n, $nb);
                $r = $n % $nb;
            }
            return [\ltrim($q, '0') ?: '0', (string) $r];
        }
        for (;;) {
            $focus = \substr($a, 0, $z);
            $cmp = $this->doCmp($focus, $b);
            if ($cmp === -1) {
                if ($z === $x) {
                    // remainder < dividend
                    break;
                }
                $z++;
            }
            $zeros = \str_repeat('0', $x - $z);
            $q = $this->add($q, '1' . $zeros);
            $a = $this->sub($a, $b . $zeros);
            $r = $a;
            if ($r === '0') {
                // remainder == 0
                break;
            }
            $x = \strlen($a);
            if ($x < $y) {
                // remainder < dividend
                break;
            }
            $z = $y;
        }
        return [$q, $r];
    }
    /**
     * Compares two non-signed large numbers.
     *
     * @psalm-return -1|0|1
     */
    private function doCmp(string $a, string $b): int
    {
        $x = \strlen($a);
        $y = \strlen($b);
        $cmp = $x <=> $y;
        if ($cmp !== 0) {
            return $cmp;
        }
        return \strcmp($a, $b) <=> 0;
        // enforce -1|0|1
    }
    /**
     * Pads the left of one of the given numbers with zeros if necessary to make both numbers the same length.
     *
     * The numbers must only consist of digits, without leading minus sign.
     *
     * @return array{string, string, int}
     */
    private function pad(string $a, string $b): array
    {
        $x = \strlen($a);
        $y = \strlen($b);
        if ($x > $y) {
            $b = \str_repeat('0', $x - $y) . $b;
            return [$a, $b, $x];
        }
        if ($x < $y) {
            $a = \str_repeat('0', $y - $x) . $a;
            return [$a, $b, $y];
        }
        return [$a, $b, $x];
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\Brick\Math\Internal;

use _ContaoManager\Brick\Math\Exception\RoundingNecessaryException;
use _ContaoManager\Brick\Math\RoundingMode;
/**
 * Performs basic operations on arbitrary size integers.
 *
 * Unless otherwise specified, all parameters must be validated as non-empty strings of digits,
 * without leading zero, and with an optional leading minus sign if the number is not zero.
 *
 * Any other parameter format will lead to undefined behaviour.
 * All methods must return strings respecting this format, unless specified otherwise.
 *
 * @internal
 *
 * @psalm-immutable
 */
abstract class Calculator
{
    /**
     * The maximum exponent value allowed for the pow() method.
     */
    public const MAX_POWER = 1000000;
    /**
     * The alphabet for converting from and to base 2 to 36, lowercase.
     */
    public const ALPHABET = '0123456789abcdefghijklmnopqrstuvwxyz';
    /**
     * The Calculator instance in use.
     */
    private static ?Calculator $instance = null;
    /**
     * Sets the Calculator instance to use.
     *
     * An instance is typically set only in unit tests: the autodetect is usually the best option.
     *
     * @param Calculator|null $calculator The calculator instance, or NULL to revert to autodetect.
     */
    final public static function set(?Calculator $calculator): void
    {
        self::$instance = $calculator;
    }
    /**
     * Returns the Calculator instance to use.
     *
     * If none has been explicitly set, the fastest available implementation will be returned.
     *
     * @psalm-pure
     * @psalm-suppress ImpureStaticProperty
     */
    final public static function get(): Calculator
    {
        if (self::$instance === null) {
            /** @psalm-suppress ImpureMethodCall */
            self::$instance = self::detect();
        }
        return self::$instance;
    }
    /**
     * Returns the fastest available Calculator implementation.
     *
     * @codeCoverageIgnore
     */
    private static function detect(): Calculator
    {
        if (\extension_loaded('gmp')) {
            return new Calculator\GmpCalculator();
        }
        if (\extension_loaded('bcmath')) {
            return new Calculator\BcMathCalculator();
        }
        return new Calculator\NativeCalculator();
    }
    /**
     * Extracts the sign & digits of the operands.
     *
     * @return array{bool, bool, string, string} Whether $a and $b are negative, followed by their digits.
     */
    final protected function init(string $a, string $b): array
    {
        return [$aNeg = $a[0] === '-', $bNeg = $b[0] === '-', $aNeg ? \substr($a, 1) : $a, $bNeg ? \substr($b, 1) : $b];
    }
    /**
     * Returns the absolute value of a number.
     */
    final public function abs(string $n): string
    {
        return $n[0] === '-' ? \substr($n, 1) : $n;
    }
    /**
     * Negates a number.
     */
    final public function neg(string $n): string
    {
        if ($n === '0') {
            return '0';
        }
        if ($n[0] === '-') {
            return \substr($n, 1);
        }
        return '-' . $n;
    }
    /**
     * Compares two numbers.
     *
     * @psalm-return -1|0|1
     *
     * @return int -1 if the first number is less than, 0 if equal to, 1 if greater than the second number.
     */
    final public function cmp(string $a, string $b): int
    {
        [$aNeg, $bNeg, $aDig, $bDig] = $this->init($a, $b);
        if ($aNeg && !$bNeg) {
            return -1;
        }
        if ($bNeg && !$aNeg) {
            return 1;
        }
        $aLen = \strlen($aDig);
        $bLen = \strlen($bDig);
        if ($aLen < $bLen) {
            $result = -1;
        } elseif ($aLen > $bLen) {
            $result = 1;
        } else {
            $result = $aDig <=> $bDig;
        }
        return $aNeg ? -$result : $result;
    }
    /**
     * Adds two numbers.
     */
    abstract public function add(string $a, string $b): string;
    /**
     * Subtracts two numbers.
     */
    abstract public function sub(string $a, string $b): string;
    /**
     * Multiplies two numbers.
     */
    abstract public function mul(string $a, string $b): string;
    /**
     * Returns the quotient of the division of two numbers.
     *
     * @param string $a The dividend.
     * @param string $b The divisor, must not be zero.
     *
     * @return string The quotient.
     */
    abstract public function divQ(string $a, string $b): string;
    /**
     * Returns the remainder of the division of two numbers.
     *
     * @param string $a The dividend.
     * @param string $b The divisor, must not be zero.
     *
     * @return string The remainder.
     */
    abstract public function divR(string $a, string $b): string;
    /**
     * Returns the quotient and remainder of the division of two numbers.
     *
     * @param string $a The dividend.
     * @param string $b The divisor, must not be zero.
     *
     * @return array{string, string} An array containing the quotient and remainder.
     */
    abstract public function divQR(string $a, string $b): array;
    /**
     * Exponentiates a number.
     *
     * @param string $a The base number.
     * @param int    $e The exponent, validated as an integer between 0 and MAX_POWER.
     *
     * @return string The power.
     */
    abstract public function pow(string $a, int $e): string;
    /**
     * @param string $b The modulus; must not be zero.
     */
    public function mod(string $a, string $b): string
    {
        return $this->divR($this->add($this->divR($a, $b), $b), $b);
    }
    /**
     * Returns the modular multiplicative inverse of $x modulo $m.
     *
     * If $x has no multiplicative inverse mod m, this method must return null.
     *
     * This method can be overridden by the concrete implementation if the underlying library has built-in support.
     *
     * @param string $m The modulus; must not be negative or zero.
     */
    public function modInverse(string $x, string $m): ?string
    {
        if ($m === '1') {
            return '0';
        }
        $modVal = $x;
        if ($x[0] === '-' || $this->cmp($this->abs($x), $m) >= 0) {
            $modVal = $this->mod($x, $m);
        }
        [$g, $x] = $this->gcdExtended($modVal, $m);
        if ($g !== '1') {
            return null;
        }
        return $this->mod($this->add($this->mod($x, $m), $m), $m);
    }
    /**
     * Raises a number into power with modulo.
     *
     * @param string $base The base number; must be positive or zero.
     * @param string $exp  The exponent; must be positive or zero.
     * @param string $mod  The modulus; must be strictly positive.
     */
    abstract public function modPow(string $base, string $exp, string $mod): string;
    /**
     * Returns the greatest common divisor of the two numbers.
     *
     * This method can be overridden by the concrete implementation if the underlying library
     * has built-in support for GCD calculations.
     *
     * @return string The GCD, always positive, or zero if both arguments are zero.
     */
    public function gcd(string $a, string $b): string
    {
        if ($a === '0') {
            return $this->abs($b);
        }
        if ($b === '0') {
            return $this->abs($a);
        }
        return $this->gcd($b, $this->divR($a, $b));
    }
    /**
     * @return array{string, string, string} GCD, X, Y
     */
    private function gcdExtended(string $a, string $b): array
    {
        if ($a === '0') {
            return [$b, '0', '1'];
        }
        [$gcd, $x1, $y1] = $this->gcdExtended($this->mod($b, $a), $a);
        $x = $this->sub($y1, $this->mul($this->divQ($b, $a), $x1));
        $y = $x1;
        return [$gcd, $x, $y];
    }
    /**
     * Returns the square root of the given number, rounded down.
     *
     * The result is the largest x such that x² ≤ n.
     * The input MUST NOT be negative.
     */
    abstract public function sqrt(string $n): string;
    /**
     * Converts a number from an arbitrary base.
     *
     * This method can be overridden by the concrete implementation if the underlying library
     * has built-in support for base conversion.
     *
     * @param string $number The number, positive or zero, non-empty, case-insensitively validated for the given base.
     * @param int    $base   The base of the number, validated from 2 to 36.
     *
     * @return string The converted number, following the Calculator conventions.
     */
    public function fromBase(string $number, int $base): string
    {
        return $this->fromArbitraryBase(\strtolower($number), self::ALPHABET, $base);
    }
    /**
     * Converts a number to an arbitrary base.
     *
     * This method can be overridden by the concrete implementation if the underlying library
     * has built-in support for base conversion.
     *
     * @param string $number The number to convert, following the Calculator conventions.
     * @param int    $base   The base to convert to, validated from 2 to 36.
     *
     * @return string The converted number, lowercase.
     */
    public function toBase(string $number, int $base): string
    {
        $negative = $number[0] === '-';
        if ($negative) {
            $number = \substr($number, 1);
        }
        $number = $this->toArbitraryBase($number, self::ALPHABET, $base);
        if ($negative) {
            return '-' . $number;
        }
        return $number;
    }
    /**
     * Converts a non-negative number in an arbitrary base using a custom alphabet, to base 10.
     *
     * @param string $number   The number to convert, validated as a non-empty string,
     *                         containing only chars in the given alphabet/base.
     * @param string $alphabet The alphabet that contains every digit, validated as 2 chars minimum.
     * @param int    $base     The base of the number, validated from 2 to alphabet length.
     *
     * @return string The number in base 10, following the Calculator conventions.
     */
    final public function fromArbitraryBase(string $number, string $alphabet, int $base): string
    {
        // remove leading "zeros"
        $number = \ltrim($number, $alphabet[0]);
        if ($number === '') {
            return '0';
        }
        // optimize for "one"
        if ($number === $alphabet[1]) {
            return '1';
        }
        $result = '0';
        $power = '1';
        $base = (string) $base;
        for ($i = \strlen($number) - 1; $i >= 0; $i--) {
            $index = \strpos($alphabet, $number[$i]);
            if ($index !== 0) {
                $result = $this->add($result, $index === 1 ? $power : $this->mul($power, (string) $index));
            }
            if ($i !== 0) {
                $power = $this->mul($power, $base);
            }
        }
        return $result;
    }
    /**
     * Converts a non-negative number to an arbitrary base using a custom alphabet.
     *
     * @param string $number   The number to convert, positive or zero, following the Calculator conventions.
     * @param string $alphabet The alphabet that contains every digit, validated as 2 chars minimum.
     * @param int    $base     The base to convert to, validated from 2 to alphabet length.
     *
     * @return string The converted number in the given alphabet.
     */
    final public function toArbitraryBase(string $number, string $alphabet, int $base): string
    {
        if ($number === '0') {
            return $alphabet[0];
        }
        $base = (string) $base;
        $result = '';
        while ($number !== '0') {
            [$number, $remainder] = $this->divQR($number, $base);
            $remainder = (int) $remainder;
            $result .= $alphabet[$remainder];
        }
        return \strrev($result);
    }
    /**
     * Performs a rounded division.
     *
     * Rounding is performed when the remainder of the division is not zero.
     *
     * @param string       $a            The dividend.
     * @param string       $b            The divisor, must not be zero.
     * @param RoundingMode $roundingMode The rounding mode.
     *
     * @throws \InvalidArgumentException  If the rounding mode is invalid.
     * @throws RoundingNecessaryException If RoundingMode::UNNECESSARY is provided but rounding is necessary.
     *
     * @psalm-suppress ImpureFunctionCall
     */
    final public function divRound(string $a, string $b, RoundingMode $roundingMode): string
    {
        [$quotient, $remainder] = $this->divQR($a, $b);
        $hasDiscardedFraction = $remainder !== '0';
        $isPositiveOrZero = ($a[0] === '-') === ($b[0] === '-');
        $discardedFractionSign = function () use ($remainder, $b): int {
            $r = $this->abs($this->mul($remainder, '2'));
            $b = $this->abs($b);
            return $this->cmp($r, $b);
        };
        $increment = \false;
        switch ($roundingMode) {
            case RoundingMode::UNNECESSARY:
                if ($hasDiscardedFraction) {
                    throw RoundingNecessaryException::roundingNecessary();
                }
                break;
            case RoundingMode::UP:
                $increment = $hasDiscardedFraction;
                break;
            case RoundingMode::DOWN:
                break;
            case RoundingMode::CEILING:
                $increment = $hasDiscardedFraction && $isPositiveOrZero;
                break;
            case RoundingMode::FLOOR:
                $increment = $hasDiscardedFraction && !$isPositiveOrZero;
                break;
            case RoundingMode::HALF_UP:
                $increment = $discardedFractionSign() >= 0;
                break;
            case RoundingMode::HALF_DOWN:
                $increment = $discardedFractionSign() > 0;
                break;
            case RoundingMode::HALF_CEILING:
                $increment = $isPositiveOrZero ? $discardedFractionSign() >= 0 : $discardedFractionSign() > 0;
                break;
            case RoundingMode::HALF_FLOOR:
                $increment = $isPositiveOrZero ? $discardedFractionSign() > 0 : $discardedFractionSign() >= 0;
                break;
            case RoundingMode::HALF_EVEN:
                $lastDigit = (int) $quotient[-1];
                $lastDigitIsEven = $lastDigit % 2 === 0;
                $increment = $lastDigitIsEven ? $discardedFractionSign() > 0 : $discardedFractionSign() >= 0;
                break;
            default:
                throw new \InvalidArgumentException('Invalid rounding mode.');
        }
        if ($increment) {
            return $this->add($quotient, $isPositiveOrZero ? '1' : '-1');
        }
        return $quotient;
    }
    /**
     * Calculates bitwise AND of two numbers.
     *
     * This method can be overridden by the concrete implementation if the underlying library
     * has built-in support for bitwise operations.
     */
    public function and(string $a, string $b): string
    {
        return $this->bitwise('and', $a, $b);
    }
    /**
     * Calculates bitwise OR of two numbers.
     *
     * This method can be overridden by the concrete implementation if the underlying library
     * has built-in support for bitwise operations.
     */
    public function or(string $a, string $b): string
    {
        return $this->bitwise('or', $a, $b);
    }
    /**
     * Calculates bitwise XOR of two numbers.
     *
     * This method can be overridden by the concrete implementation if the underlying library
     * has built-in support for bitwise operations.
     */
    public function xor(string $a, string $b): string
    {
        return $this->bitwise('xor', $a, $b);
    }
    /**
     * Performs a bitwise operation on a decimal number.
     *
     * @param 'and'|'or'|'xor' $operator The operator to use.
     * @param string           $a        The left operand.
     * @param string           $b        The right operand.
     */
    private function bitwise(string $operator, string $a, string $b): string
    {
        [$aNeg, $bNeg, $aDig, $bDig] = $this->init($a, $b);
        $aBin = $this->toBinary($aDig);
        $bBin = $this->toBinary($bDig);
        $aLen = \strlen($aBin);
        $bLen = \strlen($bBin);
        if ($aLen > $bLen) {
            $bBin = \str_repeat("\x00", $aLen - $bLen) . $bBin;
        } elseif ($bLen > $aLen) {
            $aBin = \str_repeat("\x00", $bLen - $aLen) . $aBin;
        }
        if ($aNeg) {
            $aBin = $this->twosComplement($aBin);
        }
        if ($bNeg) {
            $bBin = $this->twosComplement($bBin);
        }
        $value = match ($operator) {
            'and' => $aBin & $bBin,
            'or' => $aBin | $bBin,
            'xor' => $aBin ^ $bBin,
        };
        $negative = match ($operator) {
            'and' => $aNeg and $bNeg,
            'or' => $aNeg or $bNeg,
            'xor' => $aNeg xor $bNeg,
        };
        if ($negative) {
            $value = $this->twosComplement($value);
        }
        $result = $this->toDecimal($value);
        return $negative ? $this->neg($result) : $result;
    }
    /**
     * @param string $number A positive, binary number.
     */
    private function twosComplement(string $number): string
    {
        $xor = \str_repeat("\xff", \strlen($number));
        $number ^= $xor;
        for ($i = \strlen($number) - 1; $i >= 0; $i--) {
            $byte = \ord($number[$i]);
            if (++$byte !== 256) {
                $number[$i] = \chr($byte);
                break;
            }
            $number[$i] = "\x00";
            if ($i === 0) {
                $number = "\x01" . $number;
            }
        }
        return $number;
    }
    /**
     * Converts a decimal number to a binary string.
     *
     * @param string $number The number to convert, positive or zero, only digits.
     */
    private function toBinary(string $number): string
    {
        $result = '';
        while ($number !== '0') {
            [$number, $remainder] = $this->divQR($number, '256');
            $result .= \chr((int) $remainder);
        }
        return \strrev($result);
    }
    /**
     * Returns the positive decimal representation of a binary number.
     *
     * @param string $bytes The bytes representing the number.
     */
    private function toDecimal(string $bytes): string
    {
        $result = '0';
        $power = '1';
        for ($i = \strlen($bytes) - 1; $i >= 0; $i--) {
            $index = \ord($bytes[$i]);
            if ($index !== 0) {
                $result = $this->add($result, $index === 1 ? $power : $this->mul($power, (string) $index));
            }
            if ($i !== 0) {
                $power = $this->mul($power, '256');
            }
        }
        return $result;
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\Brick\Math;

use _ContaoManager\Brick\Math\Exception\DivisionByZeroException;
use _ContaoManager\Brick\Math\Exception\IntegerOverflowException;
use _ContaoManager\Brick\Math\Exception\MathException;
use _ContaoManager\Brick\Math\Exception\NegativeNumberException;
use _ContaoManager\Brick\Math\Exception\NumberFormatException;
use _ContaoManager\Brick\Math\Internal\Calculator;
use Override;
/**
 * An arbitrary-size integer.
 *
 * All methods accepting a number as a parameter accept either a BigInteger instance,
 * an integer, or a string representing an arbitrary size integer.
 *
 * @psalm-immutable
 */
final class BigInteger extends BigNumber
{
    /**
     * The value, as a string of digits with optional leading minus sign.
     *
     * No leading zeros must be present.
     * No leading minus sign must be present if the number is zero.
     */
    private readonly string $value;
    /**
     * Protected constructor. Use a factory method to obtain an instance.
     *
     * @param string $value A string of digits, with optional leading minus sign.
     */
    protected function __construct(string $value)
    {
        $this->value = $value;
    }
    /**
     * @psalm-pure
     */
    #[Override]
    protected static function from(BigNumber $number): static
    {
        return $number->toBigInteger();
    }
    /**
     * Creates a number from a string in a given base.
     *
     * The string can optionally be prefixed with the `+` or `-` sign.
     *
     * Bases greater than 36 are not supported by this method, as there is no clear consensus on which of the lowercase
     * or uppercase characters should come first. Instead, this method accepts any base up to 36, and does not
     * differentiate lowercase and uppercase characters, which are considered equal.
     *
     * For bases greater than 36, and/or custom alphabets, use the fromArbitraryBase() method.
     *
     * @param string $number The number to convert, in the given base.
     * @param int    $base   The base of the number, between 2 and 36.
     *
     * @throws NumberFormatException     If the number is empty, or contains invalid chars for the given base.
     * @throws \InvalidArgumentException If the base is out of range.
     *
     * @psalm-pure
     */
    public static function fromBase(string $number, int $base): BigInteger
    {
        if ($number === '') {
            throw new NumberFormatException('The number cannot be empty.');
        }
        if ($base < 2 || $base > 36) {
            throw new \InvalidArgumentException(\sprintf('Base %d is not in range 2 to 36.', $base));
        }
        if ($number[0] === '-') {
            $sign = '-';
            $number = \substr($number, 1);
        } elseif ($number[0] === '+') {
            $sign = '';
            $number = \substr($number, 1);
        } else {
            $sign = '';
        }
        if ($number === '') {
            throw new NumberFormatException('The number cannot be empty.');
        }
        $number = \ltrim($number, '0');
        if ($number === '') {
            // The result will be the same in any base, avoid further calculation.
            return BigInteger::zero();
        }
        if ($number === '1') {
            // The result will be the same in any base, avoid further calculation.
            return new BigInteger($sign . '1');
        }
        $pattern = '/[^' . \substr(Calculator::ALPHABET, 0, $base) . ']/';
        if (\preg_match($pattern, \strtolower($number), $matches) === 1) {
            throw new NumberFormatException(\sprintf('"%s" is not a valid character in base %d.', $matches[0], $base));
        }
        if ($base === 10) {
            // The number is usable as is, avoid further calculation.
            return new BigInteger($sign . $number);
        }
        $result = Calculator::get()->fromBase($number, $base);
        return new BigInteger($sign . $result);
    }
    /**
     * Parses a string containing an integer in an arbitrary base, using a custom alphabet.
     *
     * Because this method accepts an alphabet with any character, including dash, it does not handle negative numbers.
     *
     * @param string $number   The number to parse.
     * @param string $alphabet The alphabet, for example '01' for base 2, or '01234567' for base 8.
     *
     * @throws NumberFormatException     If the given number is empty or contains invalid chars for the given alphabet.
     * @throws \InvalidArgumentException If the alphabet does not contain at least 2 chars.
     *
     * @psalm-pure
     */
    public static function fromArbitraryBase(string $number, string $alphabet): BigInteger
    {
        if ($number === '') {
            throw new NumberFormatException('The number cannot be empty.');
        }
        $base = \strlen($alphabet);
        if ($base < 2) {
            throw new \InvalidArgumentException('The alphabet must contain at least 2 chars.');
        }
        $pattern = '/[^' . \preg_quote($alphabet, '/') . ']/';
        if (\preg_match($pattern, $number, $matches) === 1) {
            throw NumberFormatException::charNotInAlphabet($matches[0]);
        }
        $number = Calculator::get()->fromArbitraryBase($number, $alphabet, $base);
        return new BigInteger($number);
    }
    /**
     * Translates a string of bytes containing the binary representation of a BigInteger into a BigInteger.
     *
     * The input string is assumed to be in big-endian byte-order: the most significant byte is in the zeroth element.
     *
     * If `$signed` is true, the input is assumed to be in two's-complement representation, and the leading bit is
     * interpreted as a sign bit. If `$signed` is false, the input is interpreted as an unsigned number, and the
     * resulting BigInteger will always be positive or zero.
     *
     * This method can be used to retrieve a number exported by `toBytes()`, as long as the `$signed` flags match.
     *
     * @param string $value  The byte string.
     * @param bool   $signed Whether to interpret as a signed number in two's-complement representation with a leading
     *                       sign bit.
     *
     * @throws NumberFormatException If the string is empty.
     */
    public static function fromBytes(string $value, bool $signed = \true): BigInteger
    {
        if ($value === '') {
            throw new NumberFormatException('The byte string must not be empty.');
        }
        $twosComplement = \false;
        if ($signed) {
            $x = \ord($value[0]);
            if ($twosComplement = $x >= 0x80) {
                $value = ~$value;
            }
        }
        $number = self::fromBase(\bin2hex($value), 16);
        if ($twosComplement) {
            return $number->plus(1)->negated();
        }
        return $number;
    }
    /**
     * Generates a pseudo-random number in the range 0 to 2^numBits - 1.
     *
     * Using the default random bytes generator, this method is suitable for cryptographic use.
     *
     * @psalm-param (callable(int): string)|null $randomBytesGenerator
     *
     * @param int           $numBits              The number of bits.
     * @param callable|null $randomBytesGenerator A function that accepts a number of bytes as an integer, and returns a
     *                                            string of random bytes of the given length. Defaults to the
     *                                            `random_bytes()` function.
     *
     * @throws \InvalidArgumentException If $numBits is negative.
     */
    public static function randomBits(int $numBits, ?callable $randomBytesGenerator = null): BigInteger
    {
        if ($numBits < 0) {
            throw new \InvalidArgumentException('The number of bits cannot be negative.');
        }
        if ($numBits === 0) {
            return BigInteger::zero();
        }
        if ($randomBytesGenerator === null) {
            $randomBytesGenerator = random_bytes(...);
        }
        /** @var int<1, max> $byteLength */
        $byteLength = \intdiv($numBits - 1, 8) + 1;
        $extraBits = $byteLength * 8 - $numBits;
        $bitmask = \chr(0xff >> $extraBits);
        $randomBytes = $randomBytesGenerator($byteLength);
        $randomBytes[0] = $randomBytes[0] & $bitmask;
        return self::fromBytes($randomBytes, \false);
    }
    /**
     * Generates a pseudo-random number between `$min` and `$max`.
     *
     * Using the default random bytes generator, this method is suitable for cryptographic use.
     *
     * @psalm-param (callable(int): string)|null $randomBytesGenerator
     *
     * @param BigNumber|int|float|string $min                  The lower bound. Must be convertible to a BigInteger.
     * @param BigNumber|int|float|string $max                  The upper bound. Must be convertible to a BigInteger.
     * @param callable|null              $randomBytesGenerator A function that accepts a number of bytes as an integer,
     *                                                         and returns a string of random bytes of the given length.
     *                                                         Defaults to the `random_bytes()` function.
     *
     * @throws MathException If one of the parameters cannot be converted to a BigInteger,
     *                       or `$min` is greater than `$max`.
     */
    public static function randomRange(BigNumber|int|float|string $min, BigNumber|int|float|string $max, ?callable $randomBytesGenerator = null): BigInteger
    {
        $min = BigInteger::of($min);
        $max = BigInteger::of($max);
        if ($min->isGreaterThan($max)) {
            throw new MathException('$min cannot be greater than $max.');
        }
        if ($min->isEqualTo($max)) {
            return $min;
        }
        $diff = $max->minus($min);
        $bitLength = $diff->getBitLength();
        // try until the number is in range (50% to 100% chance of success)
        do {
            $randomNumber = self::randomBits($bitLength, $randomBytesGenerator);
        } while ($randomNumber->isGreaterThan($diff));
        return $randomNumber->plus($min);
    }
    /**
     * Returns a BigInteger representing zero.
     *
     * @psalm-pure
     */
    public static function zero(): BigInteger
    {
        /**
         * @psalm-suppress ImpureStaticVariable
         * @var BigInteger|null $zero
         */
        static $zero;
        if ($zero === null) {
            $zero = new BigInteger('0');
        }
        return $zero;
    }
    /**
     * Returns a BigInteger representing one.
     *
     * @psalm-pure
     */
    public static function one(): BigInteger
    {
        /**
         * @psalm-suppress ImpureStaticVariable
         * @var BigInteger|null $one
         */
        static $one;
        if ($one === null) {
            $one = new BigInteger('1');
        }
        return $one;
    }
    /**
     * Returns a BigInteger representing ten.
     *
     * @psalm-pure
     */
    public static function ten(): BigInteger
    {
        /**
         * @psalm-suppress ImpureStaticVariable
         * @var BigInteger|null $ten
         */
        static $ten;
        if ($ten === null) {
            $ten = new BigInteger('10');
        }
        return $ten;
    }
    public static function gcdMultiple(BigInteger $a, BigInteger ...$n): BigInteger
    {
        $result = $a;
        foreach ($n as $next) {
            $result = $result->gcd($next);
            if ($result->isEqualTo(1)) {
                return $result;
            }
        }
        return $result;
    }
    /**
     * Returns the sum of this number and the given one.
     *
     * @param BigNumber|int|float|string $that The number to add. Must be convertible to a BigInteger.
     *
     * @throws MathException If the number is not valid, or is not convertible to a BigInteger.
     */
    public function plus(BigNumber|int|float|string $that): BigInteger
    {
        $that = BigInteger::of($that);
        if ($that->value === '0') {
            return $this;
        }
        if ($this->value === '0') {
            return $that;
        }
        $value = Calculator::get()->add($this->value, $that->value);
        return new BigInteger($value);
    }
    /**
     * Returns the difference of this number and the given one.
     *
     * @param BigNumber|int|float|string $that The number to subtract. Must be convertible to a BigInteger.
     *
     * @throws MathException If the number is not valid, or is not convertible to a BigInteger.
     */
    public function minus(BigNumber|int|float|string $that): BigInteger
    {
        $that = BigInteger::of($that);
        if ($that->value === '0') {
            return $this;
        }
        $value = Calculator::get()->sub($this->value, $that->value);
        return new BigInteger($value);
    }
    /**
     * Returns the product of this number and the given one.
     *
     * @param BigNumber|int|float|string $that The multiplier. Must be convertible to a BigInteger.
     *
     * @throws MathException If the multiplier is not a valid number, or is not convertible to a BigInteger.
     */
    public function multipliedBy(BigNumber|int|float|string $that): BigInteger
    {
        $that = BigInteger::of($that);
        if ($that->value === '1') {
            return $this;
        }
        if ($this->value === '1') {
            return $that;
        }
        $value = Calculator::get()->mul($this->value, $that->value);
        return new BigInteger($value);
    }
    /**
     * Returns the result of the division of this number by the given one.
     *
     * @param BigNumber|int|float|string $that         The divisor. Must be convertible to a BigInteger.
     * @param RoundingMode               $roundingMode An optional rounding mode, defaults to UNNECESSARY.
     *
     * @throws MathException If the divisor is not a valid number, is not convertible to a BigInteger, is zero,
     *                       or RoundingMode::UNNECESSARY is used and the remainder is not zero.
     */
    public function dividedBy(BigNumber|int|float|string $that, RoundingMode $roundingMode = RoundingMode::UNNECESSARY): BigInteger
    {
        $that = BigInteger::of($that);
        if ($that->value === '1') {
            return $this;
        }
        if ($that->value === '0') {
            throw DivisionByZeroException::divisionByZero();
        }
        $result = Calculator::get()->divRound($this->value, $that->value, $roundingMode);
        return new BigInteger($result);
    }
    /**
     * Returns this number exponentiated to the given value.
     *
     * @throws \InvalidArgumentException If the exponent is not in the range 0 to 1,000,000.
     */
    public function power(int $exponent): BigInteger
    {
        if ($exponent === 0) {
            return BigInteger::one();
        }
        if ($exponent === 1) {
            return $this;
        }
        if ($exponent < 0 || $exponent > Calculator::MAX_POWER) {
            throw new \InvalidArgumentException(\sprintf('The exponent %d is not in the range 0 to %d.', $exponent, Calculator::MAX_POWER));
        }
        return new BigInteger(Calculator::get()->pow($this->value, $exponent));
    }
    /**
     * Returns the quotient of the division of this number by the given one.
     *
     * @param BigNumber|int|float|string $that The divisor. Must be convertible to a BigInteger.
     *
     * @throws DivisionByZeroException If the divisor is zero.
     */
    public function quotient(BigNumber|int|float|string $that): BigInteger
    {
        $that = BigInteger::of($that);
        if ($that->value === '1') {
            return $this;
        }
        if ($that->value === '0') {
            throw DivisionByZeroException::divisionByZero();
        }
        $quotient = Calculator::get()->divQ($this->value, $that->value);
        return new BigInteger($quotient);
    }
    /**
     * Returns the remainder of the division of this number by the given one.
     *
     * The remainder, when non-zero, has the same sign as the dividend.
     *
     * @param BigNumber|int|float|string $that The divisor. Must be convertible to a BigInteger.
     *
     * @throws DivisionByZeroException If the divisor is zero.
     */
    public function remainder(BigNumber|int|float|string $that): BigInteger
    {
        $that = BigInteger::of($that);
        if ($that->value === '1') {
            return BigInteger::zero();
        }
        if ($that->value === '0') {
            throw DivisionByZeroException::divisionByZero();
        }
        $remainder = Calculator::get()->divR($this->value, $that->value);
        return new BigInteger($remainder);
    }
    /**
     * Returns the quotient and remainder of the division of this number by the given one.
     *
     * @param BigNumber|int|float|string $that The divisor. Must be convertible to a BigInteger.
     *
     * @return BigInteger[] An array containing the quotient and the remainder.
     *
     * @psalm-return array{BigInteger, BigInteger}
     *
     * @throws DivisionByZeroException If the divisor is zero.
     */
    public function quotientAndRemainder(BigNumber|int|float|string $that): array
    {
        $that = BigInteger::of($that);
        if ($that->value === '0') {
            throw DivisionByZeroException::divisionByZero();
        }
        [$quotient, $remainder] = Calculator::get()->divQR($this->value, $that->value);
        return [new BigInteger($quotient), new BigInteger($remainder)];
    }
    /**
     * Returns the modulo of this number and the given one.
     *
     * The modulo operation yields the same result as the remainder operation when both operands are of the same sign,
     * and may differ when signs are different.
     *
     * The result of the modulo operation, when non-zero, has the same sign as the divisor.
     *
     * @param BigNumber|int|float|string $that The divisor. Must be convertible to a BigInteger.
     *
     * @throws DivisionByZeroException If the divisor is zero.
     */
    public function mod(BigNumber|int|float|string $that): BigInteger
    {
        $that = BigInteger::of($that);
        if ($that->value === '0') {
            throw DivisionByZeroException::modulusMustNotBeZero();
        }
        $value = Calculator::get()->mod($this->value, $that->value);
        return new BigInteger($value);
    }
    /**
     * Returns the modular multiplicative inverse of this BigInteger modulo $m.
     *
     * @throws DivisionByZeroException If $m is zero.
     * @throws NegativeNumberException If $m is negative.
     * @throws MathException           If this BigInteger has no multiplicative inverse mod m (that is, this BigInteger
     *                                 is not relatively prime to m).
     */
    public function modInverse(BigInteger $m): BigInteger
    {
        if ($m->value === '0') {
            throw DivisionByZeroException::modulusMustNotBeZero();
        }
        if ($m->isNegative()) {
            throw new NegativeNumberException('Modulus must not be negative.');
        }
        if ($m->value === '1') {
            return BigInteger::zero();
        }
        $value = Calculator::get()->modInverse($this->value, $m->value);
        if ($value === null) {
            throw new MathException('Unable to compute the modInverse for the given modulus.');
        }
        return new BigInteger($value);
    }
    /**
     * Returns this number raised into power with modulo.
     *
     * This operation only works on positive numbers.
     *
     * @param BigNumber|int|float|string $exp The exponent. Must be positive or zero.
     * @param BigNumber|int|float|string $mod The modulus. Must be strictly positive.
     *
     * @throws NegativeNumberException If any of the operands is negative.
     * @throws DivisionByZeroException If the modulus is zero.
     */
    public function modPow(BigNumber|int|float|string $exp, BigNumber|int|float|string $mod): BigInteger
    {
        $exp = BigInteger::of($exp);
        $mod = BigInteger::of($mod);
        if ($this->isNegative() || $exp->isNegative() || $mod->isNegative()) {
            throw new NegativeNumberException('The operands cannot be negative.');
        }
        if ($mod->isZero()) {
            throw DivisionByZeroException::modulusMustNotBeZero();
        }
        $result = Calculator::get()->modPow($this->value, $exp->value, $mod->value);
        return new BigInteger($result);
    }
    /**
     * Returns the greatest common divisor of this number and the given one.
     *
     * The GCD is always positive, unless both operands are zero, in which case it is zero.
     *
     * @param BigNumber|int|float|string $that The operand. Must be convertible to an integer number.
     */
    public function gcd(BigNumber|int|float|string $that): BigInteger
    {
        $that = BigInteger::of($that);
        if ($that->value === '0' && $this->value[0] !== '-') {
            return $this;
        }
        if ($this->value === '0' && $that->value[0] !== '-') {
            return $that;
        }
        $value = Calculator::get()->gcd($this->value, $that->value);
        return new BigInteger($value);
    }
    /**
     * Returns the integer square root number of this number, rounded down.
     *
     * The result is the largest x such that x² ≤ n.
     *
     * @throws NegativeNumberException If this number is negative.
     */
    public function sqrt(): BigInteger
    {
        if ($this->value[0] === '-') {
            throw new NegativeNumberException('Cannot calculate the square root of a negative number.');
        }
        $value = Calculator::get()->sqrt($this->value);
        return new BigInteger($value);
    }
    /**
     * Returns the absolute value of this number.
     */
    public function abs(): BigInteger
    {
        return $this->isNegative() ? $this->negated() : $this;
    }
    /**
     * Returns the inverse of this number.
     */
    public function negated(): BigInteger
    {
        return new BigInteger(Calculator::get()->neg($this->value));
    }
    /**
     * Returns the integer bitwise-and combined with another integer.
     *
     * This method returns a negative BigInteger if and only if both operands are negative.
     *
     * @param BigNumber|int|float|string $that The operand. Must be convertible to an integer number.
     */
    public function and(BigNumber|int|float|string $that): BigInteger
    {
        $that = BigInteger::of($that);
        return new BigInteger(Calculator::get()->and($this->value, $that->value));
    }
    /**
     * Returns the integer bitwise-or combined with another integer.
     *
     * This method returns a negative BigInteger if and only if either of the operands is negative.
     *
     * @param BigNumber|int|float|string $that The operand. Must be convertible to an integer number.
     */
    public function or(BigNumber|int|float|string $that): BigInteger
    {
        $that = BigInteger::of($that);
        return new BigInteger(Calculator::get()->or($this->value, $that->value));
    }
    /**
     * Returns the integer bitwise-xor combined with another integer.
     *
     * This method returns a negative BigInteger if and only if exactly one of the operands is negative.
     *
     * @param BigNumber|int|float|string $that The operand. Must be convertible to an integer number.
     */
    public function xor(BigNumber|int|float|string $that): BigInteger
    {
        $that = BigInteger::of($that);
        return new BigInteger(Calculator::get()->xor($this->value, $that->value));
    }
    /**
     * Returns the bitwise-not of this BigInteger.
     */
    public function not(): BigInteger
    {
        return $this->negated()->minus(1);
    }
    /**
     * Returns the integer left shifted by a given number of bits.
     */
    public function shiftedLeft(int $distance): BigInteger
    {
        if ($distance === 0) {
            return $this;
        }
        if ($distance < 0) {
            return $this->shiftedRight(-$distance);
        }
        return $this->multipliedBy(BigInteger::of(2)->power($distance));
    }
    /**
     * Returns the integer right shifted by a given number of bits.
     */
    public function shiftedRight(int $distance): BigInteger
    {
        if ($distance === 0) {
            return $this;
        }
        if ($distance < 0) {
            return $this->shiftedLeft(-$distance);
        }
        $operand = BigInteger::of(2)->power($distance);
        if ($this->isPositiveOrZero()) {
            return $this->quotient($operand);
        }
        return $this->dividedBy($operand, RoundingMode::UP);
    }
    /**
     * Returns the number of bits in the minimal two's-complement representation of this BigInteger, excluding a sign bit.
     *
     * For positive BigIntegers, this is equivalent to the number of bits in the ordinary binary representation.
     * Computes (ceil(log2(this < 0 ? -this : this+1))).
     */
    public function getBitLength(): int
    {
        if ($this->value === '0') {
            return 0;
        }
        if ($this->isNegative()) {
            return $this->abs()->minus(1)->getBitLength();
        }
        return \strlen($this->toBase(2));
    }
    /**
     * Returns the index of the rightmost (lowest-order) one bit in this BigInteger.
     *
     * Returns -1 if this BigInteger contains no one bits.
     */
    public function getLowestSetBit(): int
    {
        $n = $this;
        $bitLength = $this->getBitLength();
        for ($i = 0; $i <= $bitLength; $i++) {
            if ($n->isOdd()) {
                return $i;
            }
            $n = $n->shiftedRight(1);
        }
        return -1;
    }
    /**
     * Returns whether this number is even.
     */
    public function isEven(): bool
    {
        return \in_array($this->value[-1], ['0', '2', '4', '6', '8'], \true);
    }
    /**
     * Returns whether this number is odd.
     */
    public function isOdd(): bool
    {
        return \in_array($this->value[-1], ['1', '3', '5', '7', '9'], \true);
    }
    /**
     * Returns true if and only if the designated bit is set.
     *
     * Computes ((this & (1<<n)) != 0).
     *
     * @param int $n The bit to test, 0-based.
     *
     * @throws \InvalidArgumentException If the bit to test is negative.
     */
    public function testBit(int $n): bool
    {
        if ($n < 0) {
            throw new \InvalidArgumentException('The bit to test cannot be negative.');
        }
        return $this->shiftedRight($n)->isOdd();
    }
    #[Override]
    public function compareTo(BigNumber|int|float|string $that): int
    {
        $that = BigNumber::of($that);
        if ($that instanceof BigInteger) {
            return Calculator::get()->cmp($this->value, $that->value);
        }
        return -$that->compareTo($this);
    }
    #[Override]
    public function getSign(): int
    {
        return $this->value === '0' ? 0 : ($this->value[0] === '-' ? -1 : 1);
    }
    #[Override]
    public function toBigInteger(): BigInteger
    {
        return $this;
    }
    #[Override]
    public function toBigDecimal(): BigDecimal
    {
        return self::newBigDecimal($this->value);
    }
    #[Override]
    public function toBigRational(): BigRational
    {
        return self::newBigRational($this, BigInteger::one(), \false);
    }
    #[Override]
    public function toScale(int $scale, RoundingMode $roundingMode = RoundingMode::UNNECESSARY): BigDecimal
    {
        return $this->toBigDecimal()->toScale($scale, $roundingMode);
    }
    #[Override]
    public function toInt(): int
    {
        $intValue = (int) $this->value;
        if ($this->value !== (string) $intValue) {
            throw IntegerOverflowException::toIntOverflow($this);
        }
        return $intValue;
    }
    #[Override]
    public function toFloat(): float
    {
        return (float) $this->value;
    }
    /**
     * Returns a string representation of this number in the given base.
     *
     * The output will always be lowercase for bases greater than 10.
     *
     * @throws \InvalidArgumentException If the base is out of range.
     */
    public function toBase(int $base): string
    {
        if ($base === 10) {
            return $this->value;
        }
        if ($base < 2 || $base > 36) {
            throw new \InvalidArgumentException(\sprintf('Base %d is out of range [2, 36]', $base));
        }
        return Calculator::get()->toBase($this->value, $base);
    }
    /**
     * Returns a string representation of this number in an arbitrary base with a custom alphabet.
     *
     * Because this method accepts an alphabet with any character, including dash, it does not handle negative numbers;
     * a NegativeNumberException will be thrown when attempting to call this method on a negative number.
     *
     * @param string $alphabet The alphabet, for example '01' for base 2, or '01234567' for base 8.
     *
     * @throws NegativeNumberException   If this number is negative.
     * @throws \InvalidArgumentException If the given alphabet does not contain at least 2 chars.
     */
    public function toArbitraryBase(string $alphabet): string
    {
        $base = \strlen($alphabet);
        if ($base < 2) {
            throw new \InvalidArgumentException('The alphabet must contain at least 2 chars.');
        }
        if ($this->value[0] === '-') {
            throw new NegativeNumberException(__FUNCTION__ . '() does not support negative numbers.');
        }
        return Calculator::get()->toArbitraryBase($this->value, $alphabet, $base);
    }
    /**
     * Returns a string of bytes containing the binary representation of this BigInteger.
     *
     * The string is in big-endian byte-order: the most significant byte is in the zeroth element.
     *
     * If `$signed` is true, the output will be in two's-complement representation, and a sign bit will be prepended to
     * the output. If `$signed` is false, no sign bit will be prepended, and this method will throw an exception if the
     * number is negative.
     *
     * The string will contain the minimum number of bytes required to represent this BigInteger, including a sign bit
     * if `$signed` is true.
     *
     * This representation is compatible with the `fromBytes()` factory method, as long as the `$signed` flags match.
     *
     * @param bool $signed Whether to output a signed number in two's-complement representation with a leading sign bit.
     *
     * @throws NegativeNumberException If $signed is false, and the number is negative.
     */
    public function toBytes(bool $signed = \true): string
    {
        if (!$signed && $this->isNegative()) {
            throw new NegativeNumberException('Cannot convert a negative number to a byte string when $signed is false.');
        }
        $hex = $this->abs()->toBase(16);
        if (\strlen($hex) % 2 !== 0) {
            $hex = '0' . $hex;
        }
        $baseHexLength = \strlen($hex);
        if ($signed) {
            if ($this->isNegative()) {
                $bin = \hex2bin($hex);
                assert($bin !== \false);
                $hex = \bin2hex(~$bin);
                $hex = self::fromBase($hex, 16)->plus(1)->toBase(16);
                $hexLength = \strlen($hex);
                if ($hexLength < $baseHexLength) {
                    $hex = \str_repeat('0', $baseHexLength - $hexLength) . $hex;
                }
                if ($hex[0] < '8') {
                    $hex = 'FF' . $hex;
                }
            } else if ($hex[0] >= '8') {
                $hex = '00' . $hex;
            }
        }
        return \hex2bin($hex);
    }
    /**
     * @return numeric-string
     */
    #[Override]
    public function __toString(): string
    {
        /** @var numeric-string */
        return $this->value;
    }
    /**
     * This method is required for serializing the object and SHOULD NOT be accessed directly.
     *
     * @internal
     *
     * @return array{value: string}
     */
    public function __serialize(): array
    {
        return ['value' => $this->value];
    }
    /**
     * This method is only here to allow unserializing the object and cannot be accessed directly.
     *
     * @internal
     * @psalm-suppress RedundantPropertyInitializationCheck
     *
     * @param array{value: string} $data
     *
     * @throws \LogicException
     */
    public function __unserialize(array $data): void
    {
        if (isset($this->value)) {
            throw new \LogicException('__unserialize() is an internal function, it must not be called directly.');
        }
        $this->value = $data['value'];
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\Brick\Math;

use _ContaoManager\Brick\Math\Exception\DivisionByZeroException;
use _ContaoManager\Brick\Math\Exception\MathException;
use _ContaoManager\Brick\Math\Exception\NumberFormatException;
use _ContaoManager\Brick\Math\Exception\RoundingNecessaryException;
use Override;
/**
 * Common interface for arbitrary-precision rational numbers.
 *
 * @psalm-immutable
 */
abstract class BigNumber implements \JsonSerializable
{
    /**
     * The regular expression used to parse integer or decimal numbers.
     */
    private const PARSE_REGEXP_NUMERICAL = '/^' . '(?<sign>[\-\+])?' . '(?<integral>[0-9]+)?' . '(?<point>\.)?' . '(?<fractional>[0-9]+)?' . '(?:[eE](?<exponent>[\-\+]?[0-9]+))?' . '$/';
    /**
     * The regular expression used to parse rational numbers.
     */
    private const PARSE_REGEXP_RATIONAL = '/^' . '(?<sign>[\-\+])?' . '(?<numerator>[0-9]+)' . '\/?' . '(?<denominator>[0-9]+)' . '$/';
    /**
     * Creates a BigNumber of the given value.
     *
     * The concrete return type is dependent on the given value, with the following rules:
     *
     * - BigNumber instances are returned as is
     * - integer numbers are returned as BigInteger
     * - floating point numbers are converted to a string then parsed as such
     * - strings containing a `/` character are returned as BigRational
     * - strings containing a `.` character or using an exponential notation are returned as BigDecimal
     * - strings containing only digits with an optional leading `+` or `-` sign are returned as BigInteger
     *
     * @throws NumberFormatException If the format of the number is not valid.
     * @throws DivisionByZeroException If the value represents a rational number with a denominator of zero.
     * @throws RoundingNecessaryException If the value cannot be converted to an instance of the subclass without rounding.
     *
     * @psalm-pure
     */
    final public static function of(BigNumber|int|float|string $value): static
    {
        $value = self::_of($value);
        if (static::class === BigNumber::class) {
            // https://github.com/vimeo/psalm/issues/10309
            assert($value instanceof static);
            return $value;
        }
        return static::from($value);
    }
    /**
     * @throws NumberFormatException If the format of the number is not valid.
     * @throws DivisionByZeroException If the value represents a rational number with a denominator of zero.
     *
     * @psalm-pure
     */
    private static function _of(BigNumber|int|float|string $value): BigNumber
    {
        if ($value instanceof BigNumber) {
            return $value;
        }
        if (\is_int($value)) {
            return new BigInteger((string) $value);
        }
        if (is_float($value)) {
            $value = (string) $value;
        }
        if (str_contains($value, '/')) {
            // Rational number
            if (\preg_match(self::PARSE_REGEXP_RATIONAL, $value, $matches, \PREG_UNMATCHED_AS_NULL) !== 1) {
                throw NumberFormatException::invalidFormat($value);
            }
            $sign = $matches['sign'];
            $numerator = $matches['numerator'];
            $denominator = $matches['denominator'];
            assert($numerator !== null);
            assert($denominator !== null);
            $numerator = self::cleanUp($sign, $numerator);
            $denominator = self::cleanUp(null, $denominator);
            if ($denominator === '0') {
                throw DivisionByZeroException::denominatorMustNotBeZero();
            }
            return new BigRational(new BigInteger($numerator), new BigInteger($denominator), \false);
        } else {
            // Integer or decimal number
            if (\preg_match(self::PARSE_REGEXP_NUMERICAL, $value, $matches, \PREG_UNMATCHED_AS_NULL) !== 1) {
                throw NumberFormatException::invalidFormat($value);
            }
            $sign = $matches['sign'];
            $point = $matches['point'];
            $integral = $matches['integral'];
            $fractional = $matches['fractional'];
            $exponent = $matches['exponent'];
            if ($integral === null && $fractional === null) {
                throw NumberFormatException::invalidFormat($value);
            }
            if ($integral === null) {
                $integral = '0';
            }
            if ($point !== null || $exponent !== null) {
                $fractional = $fractional ?? '';
                $exponent = $exponent !== null ? (int) $exponent : 0;
                if ($exponent === \PHP_INT_MIN || $exponent === \PHP_INT_MAX) {
                    throw new NumberFormatException('Exponent too large.');
                }
                $unscaledValue = self::cleanUp($sign, $integral . $fractional);
                $scale = \strlen($fractional) - $exponent;
                if ($scale < 0) {
                    if ($unscaledValue !== '0') {
                        $unscaledValue .= \str_repeat('0', -$scale);
                    }
                    $scale = 0;
                }
                return new BigDecimal($unscaledValue, $scale);
            }
            $integral = self::cleanUp($sign, $integral);
            return new BigInteger($integral);
        }
    }
    /**
     * Overridden by subclasses to convert a BigNumber to an instance of the subclass.
     *
     * @throws RoundingNecessaryException If the value cannot be converted.
     *
     * @psalm-pure
     */
    abstract protected static function from(BigNumber $number): static;
    /**
     * Proxy method to access BigInteger's protected constructor from sibling classes.
     *
     * @internal
     * @psalm-pure
     */
    final protected function newBigInteger(string $value): BigInteger
    {
        return new BigInteger($value);
    }
    /**
     * Proxy method to access BigDecimal's protected constructor from sibling classes.
     *
     * @internal
     * @psalm-pure
     */
    final protected function newBigDecimal(string $value, int $scale = 0): BigDecimal
    {
        return new BigDecimal($value, $scale);
    }
    /**
     * Proxy method to access BigRational's protected constructor from sibling classes.
     *
     * @internal
     * @psalm-pure
     */
    final protected function newBigRational(BigInteger $numerator, BigInteger $denominator, bool $checkDenominator): BigRational
    {
        return new BigRational($numerator, $denominator, $checkDenominator);
    }
    /**
     * Returns the minimum of the given values.
     *
     * @param BigNumber|int|float|string ...$values The numbers to compare. All the numbers need to be convertible
     *                                              to an instance of the class this method is called on.
     *
     * @throws \InvalidArgumentException If no values are given.
     * @throws MathException             If an argument is not valid.
     *
     * @psalm-pure
     */
    final public static function min(BigNumber|int|float|string ...$values): static
    {
        $min = null;
        foreach ($values as $value) {
            $value = static::of($value);
            if ($min === null || $value->isLessThan($min)) {
                $min = $value;
            }
        }
        if ($min === null) {
            throw new \InvalidArgumentException(__METHOD__ . '() expects at least one value.');
        }
        return $min;
    }
    /**
     * Returns the maximum of the given values.
     *
     * @param BigNumber|int|float|string ...$values The numbers to compare. All the numbers need to be convertible
     *                                              to an instance of the class this method is called on.
     *
     * @throws \InvalidArgumentException If no values are given.
     * @throws MathException             If an argument is not valid.
     *
     * @psalm-pure
     */
    final public static function max(BigNumber|int|float|string ...$values): static
    {
        $max = null;
        foreach ($values as $value) {
            $value = static::of($value);
            if ($max === null || $value->isGreaterThan($max)) {
                $max = $value;
            }
        }
        if ($max === null) {
            throw new \InvalidArgumentException(__METHOD__ . '() expects at least one value.');
        }
        return $max;
    }
    /**
     * Returns the sum of the given values.
     *
     * @param BigNumber|int|float|string ...$values The numbers to add. All the numbers need to be convertible
     *                                              to an instance of the class this method is called on.
     *
     * @throws \InvalidArgumentException If no values are given.
     * @throws MathException             If an argument is not valid.
     *
     * @psalm-pure
     */
    final public static function sum(BigNumber|int|float|string ...$values): static
    {
        /** @var static|null $sum */
        $sum = null;
        foreach ($values as $value) {
            $value = static::of($value);
            $sum = $sum === null ? $value : self::add($sum, $value);
        }
        if ($sum === null) {
            throw new \InvalidArgumentException(__METHOD__ . '() expects at least one value.');
        }
        return $sum;
    }
    /**
     * Adds two BigNumber instances in the correct order to avoid a RoundingNecessaryException.
     *
     * @todo This could be better resolved by creating an abstract protected method in BigNumber, and leaving to
     *       concrete classes the responsibility to perform the addition themselves or delegate it to the given number,
     *       depending on their ability to perform the operation. This will also require a version bump because we're
     *       potentially breaking custom BigNumber implementations (if any...)
     *
     * @psalm-pure
     */
    private static function add(BigNumber $a, BigNumber $b): BigNumber
    {
        if ($a instanceof BigRational) {
            return $a->plus($b);
        }
        if ($b instanceof BigRational) {
            return $b->plus($a);
        }
        if ($a instanceof BigDecimal) {
            return $a->plus($b);
        }
        if ($b instanceof BigDecimal) {
            return $b->plus($a);
        }
        /** @var BigInteger $a */
        return $a->plus($b);
    }
    /**
     * Removes optional leading zeros and applies sign.
     *
     * @param string|null $sign   The sign, '+' or '-', optional. Null is allowed for convenience and treated as '+'.
     * @param string      $number The number, validated as a non-empty string of digits.
     *
     * @psalm-pure
     */
    private static function cleanUp(string|null $sign, string $number): string
    {
        $number = \ltrim($number, '0');
        if ($number === '') {
            return '0';
        }
        return $sign === '-' ? '-' . $number : $number;
    }
    /**
     * Checks if this number is equal to the given one.
     */
    final public function isEqualTo(BigNumber|int|float|string $that): bool
    {
        return $this->compareTo($that) === 0;
    }
    /**
     * Checks if this number is strictly lower than the given one.
     */
    final public function isLessThan(BigNumber|int|float|string $that): bool
    {
        return $this->compareTo($that) < 0;
    }
    /**
     * Checks if this number is lower than or equal to the given one.
     */
    final public function isLessThanOrEqualTo(BigNumber|int|float|string $that): bool
    {
        return $this->compareTo($that) <= 0;
    }
    /**
     * Checks if this number is strictly greater than the given one.
     */
    final public function isGreaterThan(BigNumber|int|float|string $that): bool
    {
        return $this->compareTo($that) > 0;
    }
    /**
     * Checks if this number is greater than or equal to the given one.
     */
    final public function isGreaterThanOrEqualTo(BigNumber|int|float|string $that): bool
    {
        return $this->compareTo($that) >= 0;
    }
    /**
     * Checks if this number equals zero.
     */
    final public function isZero(): bool
    {
        return $this->getSign() === 0;
    }
    /**
     * Checks if this number is strictly negative.
     */
    final public function isNegative(): bool
    {
        return $this->getSign() < 0;
    }
    /**
     * Checks if this number is negative or zero.
     */
    final public function isNegativeOrZero(): bool
    {
        return $this->getSign() <= 0;
    }
    /**
     * Checks if this number is strictly positive.
     */
    final public function isPositive(): bool
    {
        return $this->getSign() > 0;
    }
    /**
     * Checks if this number is positive or zero.
     */
    final public function isPositiveOrZero(): bool
    {
        return $this->getSign() >= 0;
    }
    /**
     * Returns the sign of this number.
     *
     * @psalm-return -1|0|1
     *
     * @return int -1 if the number is negative, 0 if zero, 1 if positive.
     */
    abstract public function getSign(): int;
    /**
     * Compares this number to the given one.
     *
     * @psalm-return -1|0|1
     *
     * @return int -1 if `$this` is lower than, 0 if equal to, 1 if greater than `$that`.
     *
     * @throws MathException If the number is not valid.
     */
    abstract public function compareTo(BigNumber|int|float|string $that): int;
    /**
     * Converts this number to a BigInteger.
     *
     * @throws RoundingNecessaryException If this number cannot be converted to a BigInteger without rounding.
     */
    abstract public function toBigInteger(): BigInteger;
    /**
     * Converts this number to a BigDecimal.
     *
     * @throws RoundingNecessaryException If this number cannot be converted to a BigDecimal without rounding.
     */
    abstract public function toBigDecimal(): BigDecimal;
    /**
     * Converts this number to a BigRational.
     */
    abstract public function toBigRational(): BigRational;
    /**
     * Converts this number to a BigDecimal with the given scale, using rounding if necessary.
     *
     * @param int          $scale        The scale of the resulting `BigDecimal`.
     * @param RoundingMode $roundingMode An optional rounding mode, defaults to UNNECESSARY.
     *
     * @throws RoundingNecessaryException If this number cannot be converted to the given scale without rounding.
     *                                    This only applies when RoundingMode::UNNECESSARY is used.
     */
    abstract public function toScale(int $scale, RoundingMode $roundingMode = RoundingMode::UNNECESSARY): BigDecimal;
    /**
     * Returns the exact value of this number as a native integer.
     *
     * If this number cannot be converted to a native integer without losing precision, an exception is thrown.
     * Note that the acceptable range for an integer depends on the platform and differs for 32-bit and 64-bit.
     *
     * @throws MathException If this number cannot be exactly converted to a native integer.
     */
    abstract public function toInt(): int;
    /**
     * Returns an approximation of this number as a floating-point value.
     *
     * Note that this method can discard information as the precision of a floating-point value
     * is inherently limited.
     *
     * If the number is greater than the largest representable floating point number, positive infinity is returned.
     * If the number is less than the smallest representable floating point number, negative infinity is returned.
     */
    abstract public function toFloat(): float;
    /**
     * Returns a string representation of this number.
     *
     * The output of this method can be parsed by the `of()` factory method;
     * this will yield an object equal to this one, without any information loss.
     */
    abstract public function __toString(): string;
    #[Override]
    final public function jsonSerialize(): string
    {
        return $this->__toString();
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\Brick\Math;

use _ContaoManager\Brick\Math\Exception\DivisionByZeroException;
use _ContaoManager\Brick\Math\Exception\MathException;
use _ContaoManager\Brick\Math\Exception\NegativeNumberException;
use _ContaoManager\Brick\Math\Internal\Calculator;
use Override;
/**
 * Immutable, arbitrary-precision signed decimal numbers.
 *
 * @psalm-immutable
 */
final class BigDecimal extends BigNumber
{
    /**
     * The unscaled value of this decimal number.
     *
     * This is a string of digits with an optional leading minus sign.
     * No leading zero must be present.
     * No leading minus sign must be present if the value is 0.
     */
    private readonly string $value;
    /**
     * The scale (number of digits after the decimal point) of this decimal number.
     *
     * This must be zero or more.
     */
    private readonly int $scale;
    /**
     * Protected constructor. Use a factory method to obtain an instance.
     *
     * @param string $value The unscaled value, validated.
     * @param int    $scale The scale, validated.
     */
    protected function __construct(string $value, int $scale = 0)
    {
        $this->value = $value;
        $this->scale = $scale;
    }
    /**
     * @psalm-pure
     */
    #[Override]
    protected static function from(BigNumber $number): static
    {
        return $number->toBigDecimal();
    }
    /**
     * Creates a BigDecimal from an unscaled value and a scale.
     *
     * Example: `(12345, 3)` will result in the BigDecimal `12.345`.
     *
     * @param BigNumber|int|float|string $value The unscaled value. Must be convertible to a BigInteger.
     * @param int                        $scale The scale of the number. If negative, the scale will be set to zero
     *                                          and the unscaled value will be adjusted accordingly.
     *
     * @psalm-pure
     */
    public static function ofUnscaledValue(BigNumber|int|float|string $value, int $scale = 0): BigDecimal
    {
        $value = (string) BigInteger::of($value);
        if ($scale < 0) {
            if ($value !== '0') {
                $value .= \str_repeat('0', -$scale);
            }
            $scale = 0;
        }
        return new BigDecimal($value, $scale);
    }
    /**
     * Returns a BigDecimal representing zero, with a scale of zero.
     *
     * @psalm-pure
     */
    public static function zero(): BigDecimal
    {
        /**
         * @psalm-suppress ImpureStaticVariable
         * @var BigDecimal|null $zero
         */
        static $zero;
        if ($zero === null) {
            $zero = new BigDecimal('0');
        }
        return $zero;
    }
    /**
     * Returns a BigDecimal representing one, with a scale of zero.
     *
     * @psalm-pure
     */
    public static function one(): BigDecimal
    {
        /**
         * @psalm-suppress ImpureStaticVariable
         * @var BigDecimal|null $one
         */
        static $one;
        if ($one === null) {
            $one = new BigDecimal('1');
        }
        return $one;
    }
    /**
     * Returns a BigDecimal representing ten, with a scale of zero.
     *
     * @psalm-pure
     */
    public static function ten(): BigDecimal
    {
        /**
         * @psalm-suppress ImpureStaticVariable
         * @var BigDecimal|null $ten
         */
        static $ten;
        if ($ten === null) {
            $ten = new BigDecimal('10');
        }
        return $ten;
    }
    /**
     * Returns the sum of this number and the given one.
     *
     * The result has a scale of `max($this->scale, $that->scale)`.
     *
     * @param BigNumber|int|float|string $that The number to add. Must be convertible to a BigDecimal.
     *
     * @throws MathException If the number is not valid, or is not convertible to a BigDecimal.
     */
    public function plus(BigNumber|int|float|string $that): BigDecimal
    {
        $that = BigDecimal::of($that);
        if ($that->value === '0' && $that->scale <= $this->scale) {
            return $this;
        }
        if ($this->value === '0' && $this->scale <= $that->scale) {
            return $that;
        }
        [$a, $b] = $this->scaleValues($this, $that);
        $value = Calculator::get()->add($a, $b);
        $scale = $this->scale > $that->scale ? $this->scale : $that->scale;
        return new BigDecimal($value, $scale);
    }
    /**
     * Returns the difference of this number and the given one.
     *
     * The result has a scale of `max($this->scale, $that->scale)`.
     *
     * @param BigNumber|int|float|string $that The number to subtract. Must be convertible to a BigDecimal.
     *
     * @throws MathException If the number is not valid, or is not convertible to a BigDecimal.
     */
    public function minus(BigNumber|int|float|string $that): BigDecimal
    {
        $that = BigDecimal::of($that);
        if ($that->value === '0' && $that->scale <= $this->scale) {
            return $this;
        }
        [$a, $b] = $this->scaleValues($this, $that);
        $value = Calculator::get()->sub($a, $b);
        $scale = $this->scale > $that->scale ? $this->scale : $that->scale;
        return new BigDecimal($value, $scale);
    }
    /**
     * Returns the product of this number and the given one.
     *
     * The result has a scale of `$this->scale + $that->scale`.
     *
     * @param BigNumber|int|float|string $that The multiplier. Must be convertible to a BigDecimal.
     *
     * @throws MathException If the multiplier is not a valid number, or is not convertible to a BigDecimal.
     */
    public function multipliedBy(BigNumber|int|float|string $that): BigDecimal
    {
        $that = BigDecimal::of($that);
        if ($that->value === '1' && $that->scale === 0) {
            return $this;
        }
        if ($this->value === '1' && $this->scale === 0) {
            return $that;
        }
        $value = Calculator::get()->mul($this->value, $that->value);
        $scale = $this->scale + $that->scale;
        return new BigDecimal($value, $scale);
    }
    /**
     * Returns the result of the division of this number by the given one, at the given scale.
     *
     * @param BigNumber|int|float|string $that         The divisor.
     * @param int|null                   $scale        The desired scale, or null to use the scale of this number.
     * @param RoundingMode               $roundingMode An optional rounding mode, defaults to UNNECESSARY.
     *
     * @throws \InvalidArgumentException If the scale or rounding mode is invalid.
     * @throws MathException             If the number is invalid, is zero, or rounding was necessary.
     */
    public function dividedBy(BigNumber|int|float|string $that, ?int $scale = null, RoundingMode $roundingMode = RoundingMode::UNNECESSARY): BigDecimal
    {
        $that = BigDecimal::of($that);
        if ($that->isZero()) {
            throw DivisionByZeroException::divisionByZero();
        }
        if ($scale === null) {
            $scale = $this->scale;
        } elseif ($scale < 0) {
            throw new \InvalidArgumentException('Scale cannot be negative.');
        }
        if ($that->value === '1' && $that->scale === 0 && $scale === $this->scale) {
            return $this;
        }
        $p = $this->valueWithMinScale($that->scale + $scale);
        $q = $that->valueWithMinScale($this->scale - $scale);
        $result = Calculator::get()->divRound($p, $q, $roundingMode);
        return new BigDecimal($result, $scale);
    }
    /**
     * Returns the exact result of the division of this number by the given one.
     *
     * The scale of the result is automatically calculated to fit all the fraction digits.
     *
     * @param BigNumber|int|float|string $that The divisor. Must be convertible to a BigDecimal.
     *
     * @throws MathException If the divisor is not a valid number, is not convertible to a BigDecimal, is zero,
     *                       or the result yields an infinite number of digits.
     */
    public function exactlyDividedBy(BigNumber|int|float|string $that): BigDecimal
    {
        $that = BigDecimal::of($that);
        if ($that->value === '0') {
            throw DivisionByZeroException::divisionByZero();
        }
        [, $b] = $this->scaleValues($this, $that);
        $d = \rtrim($b, '0');
        $scale = \strlen($b) - \strlen($d);
        $calculator = Calculator::get();
        foreach ([5, 2] as $prime) {
            for (;;) {
                $lastDigit = (int) $d[-1];
                if ($lastDigit % $prime !== 0) {
                    break;
                }
                $d = $calculator->divQ($d, (string) $prime);
                $scale++;
            }
        }
        return $this->dividedBy($that, $scale)->stripTrailingZeros();
    }
    /**
     * Returns this number exponentiated to the given value.
     *
     * The result has a scale of `$this->scale * $exponent`.
     *
     * @throws \InvalidArgumentException If the exponent is not in the range 0 to 1,000,000.
     */
    public function power(int $exponent): BigDecimal
    {
        if ($exponent === 0) {
            return BigDecimal::one();
        }
        if ($exponent === 1) {
            return $this;
        }
        if ($exponent < 0 || $exponent > Calculator::MAX_POWER) {
            throw new \InvalidArgumentException(\sprintf('The exponent %d is not in the range 0 to %d.', $exponent, Calculator::MAX_POWER));
        }
        return new BigDecimal(Calculator::get()->pow($this->value, $exponent), $this->scale * $exponent);
    }
    /**
     * Returns the quotient of the division of this number by the given one.
     *
     * The quotient has a scale of `0`.
     *
     * @param BigNumber|int|float|string $that The divisor. Must be convertible to a BigDecimal.
     *
     * @throws MathException If the divisor is not a valid decimal number, or is zero.
     */
    public function quotient(BigNumber|int|float|string $that): BigDecimal
    {
        $that = BigDecimal::of($that);
        if ($that->isZero()) {
            throw DivisionByZeroException::divisionByZero();
        }
        $p = $this->valueWithMinScale($that->scale);
        $q = $that->valueWithMinScale($this->scale);
        $quotient = Calculator::get()->divQ($p, $q);
        return new BigDecimal($quotient, 0);
    }
    /**
     * Returns the remainder of the division of this number by the given one.
     *
     * The remainder has a scale of `max($this->scale, $that->scale)`.
     *
     * @param BigNumber|int|float|string $that The divisor. Must be convertible to a BigDecimal.
     *
     * @throws MathException If the divisor is not a valid decimal number, or is zero.
     */
    public function remainder(BigNumber|int|float|string $that): BigDecimal
    {
        $that = BigDecimal::of($that);
        if ($that->isZero()) {
            throw DivisionByZeroException::divisionByZero();
        }
        $p = $this->valueWithMinScale($that->scale);
        $q = $that->valueWithMinScale($this->scale);
        $remainder = Calculator::get()->divR($p, $q);
        $scale = $this->scale > $that->scale ? $this->scale : $that->scale;
        return new BigDecimal($remainder, $scale);
    }
    /**
     * Returns the quotient and remainder of the division of this number by the given one.
     *
     * The quotient has a scale of `0`, and the remainder has a scale of `max($this->scale, $that->scale)`.
     *
     * @param BigNumber|int|float|string $that The divisor. Must be convertible to a BigDecimal.
     *
     * @return BigDecimal[] An array containing the quotient and the remainder.
     *
     * @psalm-return array{BigDecimal, BigDecimal}
     *
     * @throws MathException If the divisor is not a valid decimal number, or is zero.
     */
    public function quotientAndRemainder(BigNumber|int|float|string $that): array
    {
        $that = BigDecimal::of($that);
        if ($that->isZero()) {
            throw DivisionByZeroException::divisionByZero();
        }
        $p = $this->valueWithMinScale($that->scale);
        $q = $that->valueWithMinScale($this->scale);
        [$quotient, $remainder] = Calculator::get()->divQR($p, $q);
        $scale = $this->scale > $that->scale ? $this->scale : $that->scale;
        $quotient = new BigDecimal($quotient, 0);
        $remainder = new BigDecimal($remainder, $scale);
        return [$quotient, $remainder];
    }
    /**
     * Returns the square root of this number, rounded down to the given number of decimals.
     *
     * @throws \InvalidArgumentException If the scale is negative.
     * @throws NegativeNumberException If this number is negative.
     */
    public function sqrt(int $scale): BigDecimal
    {
        if ($scale < 0) {
            throw new \InvalidArgumentException('Scale cannot be negative.');
        }
        if ($this->value === '0') {
            return new BigDecimal('0', $scale);
        }
        if ($this->value[0] === '-') {
            throw new NegativeNumberException('Cannot calculate the square root of a negative number.');
        }
        $value = $this->value;
        $addDigits = 2 * $scale - $this->scale;
        if ($addDigits > 0) {
            // add zeros
            $value .= \str_repeat('0', $addDigits);
        } elseif ($addDigits < 0) {
            // trim digits
            if (-$addDigits >= \strlen($this->value)) {
                // requesting a scale too low, will always yield a zero result
                return new BigDecimal('0', $scale);
            }
            $value = \substr($value, 0, $addDigits);
        }
        $value = Calculator::get()->sqrt($value);
        return new BigDecimal($value, $scale);
    }
    /**
     * Returns a copy of this BigDecimal with the decimal point moved $n places to the left.
     */
    public function withPointMovedLeft(int $n): BigDecimal
    {
        if ($n === 0) {
            return $this;
        }
        if ($n < 0) {
            return $this->withPointMovedRight(-$n);
        }
        return new BigDecimal($this->value, $this->scale + $n);
    }
    /**
     * Returns a copy of this BigDecimal with the decimal point moved $n places to the right.
     */
    public function withPointMovedRight(int $n): BigDecimal
    {
        if ($n === 0) {
            return $this;
        }
        if ($n < 0) {
            return $this->withPointMovedLeft(-$n);
        }
        $value = $this->value;
        $scale = $this->scale - $n;
        if ($scale < 0) {
            if ($value !== '0') {
                $value .= \str_repeat('0', -$scale);
            }
            $scale = 0;
        }
        return new BigDecimal($value, $scale);
    }
    /**
     * Returns a copy of this BigDecimal with any trailing zeros removed from the fractional part.
     */
    public function stripTrailingZeros(): BigDecimal
    {
        if ($this->scale === 0) {
            return $this;
        }
        $trimmedValue = \rtrim($this->value, '0');
        if ($trimmedValue === '') {
            return BigDecimal::zero();
        }
        $trimmableZeros = \strlen($this->value) - \strlen($trimmedValue);
        if ($trimmableZeros === 0) {
            return $this;
        }
        if ($trimmableZeros > $this->scale) {
            $trimmableZeros = $this->scale;
        }
        $value = \substr($this->value, 0, -$trimmableZeros);
        $scale = $this->scale - $trimmableZeros;
        return new BigDecimal($value, $scale);
    }
    /**
     * Returns the absolute value of this number.
     */
    public function abs(): BigDecimal
    {
        return $this->isNegative() ? $this->negated() : $this;
    }
    /**
     * Returns the negated value of this number.
     */
    public function negated(): BigDecimal
    {
        return new BigDecimal(Calculator::get()->neg($this->value), $this->scale);
    }
    #[Override]
    public function compareTo(BigNumber|int|float|string $that): int
    {
        $that = BigNumber::of($that);
        if ($that instanceof BigInteger) {
            $that = $that->toBigDecimal();
        }
        if ($that instanceof BigDecimal) {
            [$a, $b] = $this->scaleValues($this, $that);
            return Calculator::get()->cmp($a, $b);
        }
        return -$that->compareTo($this);
    }
    #[Override]
    public function getSign(): int
    {
        return $this->value === '0' ? 0 : ($this->value[0] === '-' ? -1 : 1);
    }
    public function getUnscaledValue(): BigInteger
    {
        return self::newBigInteger($this->value);
    }
    public function getScale(): int
    {
        return $this->scale;
    }
    /**
     * Returns the number of significant digits in the number.
     *
     * This is the number of digits to both sides of the decimal point, stripped of leading zeros.
     * The sign has no impact on the result.
     *
     * Examples:
     *   0 => 0
     *   0.0 => 0
     *   123 => 3
     *   123.456 => 6
     *   0.00123 => 3
     *   0.0012300 => 5
     */
    public function getPrecision(): int
    {
        $value = $this->value;
        if ($value === '0') {
            return 0;
        }
        $length = \strlen($value);
        return $value[0] === '-' ? $length - 1 : $length;
    }
    /**
     * Returns a string representing the integral part of this decimal number.
     *
     * Example: `-123.456` => `-123`.
     */
    public function getIntegralPart(): string
    {
        if ($this->scale === 0) {
            return $this->value;
        }
        $value = $this->getUnscaledValueWithLeadingZeros();
        return \substr($value, 0, -$this->scale);
    }
    /**
     * Returns a string representing the fractional part of this decimal number.
     *
     * If the scale is zero, an empty string is returned.
     *
     * Examples: `-123.456` => '456', `123` => ''.
     */
    public function getFractionalPart(): string
    {
        if ($this->scale === 0) {
            return '';
        }
        $value = $this->getUnscaledValueWithLeadingZeros();
        return \substr($value, -$this->scale);
    }
    /**
     * Returns whether this decimal number has a non-zero fractional part.
     */
    public function hasNonZeroFractionalPart(): bool
    {
        return $this->getFractionalPart() !== \str_repeat('0', $this->scale);
    }
    #[Override]
    public function toBigInteger(): BigInteger
    {
        $zeroScaleDecimal = $this->scale === 0 ? $this : $this->dividedBy(1, 0);
        return self::newBigInteger($zeroScaleDecimal->value);
    }
    #[Override]
    public function toBigDecimal(): BigDecimal
    {
        return $this;
    }
    #[Override]
    public function toBigRational(): BigRational
    {
        $numerator = self::newBigInteger($this->value);
        $denominator = self::newBigInteger('1' . \str_repeat('0', $this->scale));
        return self::newBigRational($numerator, $denominator, \false);
    }
    #[Override]
    public function toScale(int $scale, RoundingMode $roundingMode = RoundingMode::UNNECESSARY): BigDecimal
    {
        if ($scale === $this->scale) {
            return $this;
        }
        return $this->dividedBy(BigDecimal::one(), $scale, $roundingMode);
    }
    #[Override]
    public function toInt(): int
    {
        return $this->toBigInteger()->toInt();
    }
    #[Override]
    public function toFloat(): float
    {
        return (float) (string) $this;
    }
    /**
     * @return numeric-string
     */
    #[Override]
    public function __toString(): string
    {
        if ($this->scale === 0) {
            /** @var numeric-string */
            return $this->value;
        }
        $value = $this->getUnscaledValueWithLeadingZeros();
        /** @var numeric-string */
        return \substr($value, 0, -$this->scale) . '.' . \substr($value, -$this->scale);
    }
    /**
     * This method is required for serializing the object and SHOULD NOT be accessed directly.
     *
     * @internal
     *
     * @return array{value: string, scale: int}
     */
    public function __serialize(): array
    {
        return ['value' => $this->value, 'scale' => $this->scale];
    }
    /**
     * This method is only here to allow unserializing the object and cannot be accessed directly.
     *
     * @internal
     * @psalm-suppress RedundantPropertyInitializationCheck
     *
     * @param array{value: string, scale: int} $data
     *
     * @throws \LogicException
     */
    public function __unserialize(array $data): void
    {
        if (isset($this->value)) {
            throw new \LogicException('__unserialize() is an internal function, it must not be called directly.');
        }
        $this->value = $data['value'];
        $this->scale = $data['scale'];
    }
    /**
     * Puts the internal values of the given decimal numbers on the same scale.
     *
     * @return array{string, string} The scaled integer values of $x and $y.
     */
    private function scaleValues(BigDecimal $x, BigDecimal $y): array
    {
        $a = $x->value;
        $b = $y->value;
        if ($b !== '0' && $x->scale > $y->scale) {
            $b .= \str_repeat('0', $x->scale - $y->scale);
        } elseif ($a !== '0' && $x->scale < $y->scale) {
            $a .= \str_repeat('0', $y->scale - $x->scale);
        }
        return [$a, $b];
    }
    private function valueWithMinScale(int $scale): string
    {
        $value = $this->value;
        if ($this->value !== '0' && $scale > $this->scale) {
            $value .= \str_repeat('0', $scale - $this->scale);
        }
        return $value;
    }
    /**
     * Adds leading zeros if necessary to the unscaled value to represent the full decimal number.
     */
    private function getUnscaledValueWithLeadingZeros(): string
    {
        $value = $this->value;
        $targetLength = $this->scale + 1;
        $negative = $value[0] === '-';
        $length = \strlen($value);
        if ($negative) {
            $length--;
        }
        if ($length >= $targetLength) {
            return $this->value;
        }
        if ($negative) {
            $value = \substr($value, 1);
        }
        $value = \str_pad($value, $targetLength, '0', \STR_PAD_LEFT);
        if ($negative) {
            $value = '-' . $value;
        }
        return $value;
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\Brick\Math\Exception;

/**
 * Base class for all math exceptions.
 */
class MathException extends \RuntimeException
{
}
<?php

declare (strict_types=1);
namespace _ContaoManager\Brick\Math\Exception;

/**
 * Exception thrown when attempting to create a number from a string with an invalid format.
 */
class NumberFormatException extends MathException
{
    public static function invalidFormat(string $value): self
    {
        return new self(\sprintf('The given value "%s" does not represent a valid number.', $value));
    }
    /**
     * @param string $char The failing character.
     *
     * @psalm-pure
     */
    public static function charNotInAlphabet(string $char): self
    {
        $ord = \ord($char);
        if ($ord < 32 || $ord > 126) {
            $char = \strtoupper(\dechex($ord));
            if ($ord < 10) {
                $char = '0' . $char;
            }
        } else {
            $char = '"' . $char . '"';
        }
        return new self(\sprintf('Char %s is not a valid character in the given alphabet.', $char));
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\Brick\Math\Exception;

/**
 * Exception thrown when attempting to perform an unsupported operation, such as a square root, on a negative number.
 */
class NegativeNumberException extends MathException
{
}
<?php

declare (strict_types=1);
namespace _ContaoManager\Brick\Math\Exception;

/**
 * Exception thrown when a division by zero occurs.
 */
class DivisionByZeroException extends MathException
{
    /**
     * @psalm-pure
     */
    public static function divisionByZero(): DivisionByZeroException
    {
        return new self('Division by zero.');
    }
    /**
     * @psalm-pure
     */
    public static function modulusMustNotBeZero(): DivisionByZeroException
    {
        return new self('The modulus must not be zero.');
    }
    /**
     * @psalm-pure
     */
    public static function denominatorMustNotBeZero(): DivisionByZeroException
    {
        return new self('The denominator of a rational number cannot be zero.');
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\Brick\Math\Exception;

use _ContaoManager\Brick\Math\BigInteger;
/**
 * Exception thrown when an integer overflow occurs.
 */
class IntegerOverflowException extends MathException
{
    /**
     * @psalm-pure
     */
    public static function toIntOverflow(BigInteger $value): IntegerOverflowException
    {
        $message = '%s is out of range %d to %d and cannot be represented as an integer.';
        return new self(\sprintf($message, (string) $value, \PHP_INT_MIN, \PHP_INT_MAX));
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\Brick\Math\Exception;

/**
 * Exception thrown when a number cannot be represented at the requested scale without rounding.
 */
class RoundingNecessaryException extends MathException
{
    /**
     * @psalm-pure
     */
    public static function roundingNecessary(): RoundingNecessaryException
    {
        return new self('Rounding is necessary to represent the result of the operation at this scale.');
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\Brick\Math;

use _ContaoManager\Brick\Math\Exception\DivisionByZeroException;
use _ContaoManager\Brick\Math\Exception\MathException;
use _ContaoManager\Brick\Math\Exception\NumberFormatException;
use _ContaoManager\Brick\Math\Exception\RoundingNecessaryException;
use Override;
/**
 * An arbitrarily large rational number.
 *
 * This class is immutable.
 *
 * @psalm-immutable
 */
final class BigRational extends BigNumber
{
    /**
     * The numerator.
     */
    private readonly BigInteger $numerator;
    /**
     * The denominator. Always strictly positive.
     */
    private readonly BigInteger $denominator;
    /**
     * Protected constructor. Use a factory method to obtain an instance.
     *
     * @param BigInteger $numerator        The numerator.
     * @param BigInteger $denominator      The denominator.
     * @param bool       $checkDenominator Whether to check the denominator for negative and zero.
     *
     * @throws DivisionByZeroException If the denominator is zero.
     */
    protected function __construct(BigInteger $numerator, BigInteger $denominator, bool $checkDenominator)
    {
        if ($checkDenominator) {
            if ($denominator->isZero()) {
                throw DivisionByZeroException::denominatorMustNotBeZero();
            }
            if ($denominator->isNegative()) {
                $numerator = $numerator->negated();
                $denominator = $denominator->negated();
            }
        }
        $this->numerator = $numerator;
        $this->denominator = $denominator;
    }
    /**
     * @psalm-pure
     */
    #[Override]
    protected static function from(BigNumber $number): static
    {
        return $number->toBigRational();
    }
    /**
     * Creates a BigRational out of a numerator and a denominator.
     *
     * If the denominator is negative, the signs of both the numerator and the denominator
     * will be inverted to ensure that the denominator is always positive.
     *
     * @param BigNumber|int|float|string $numerator   The numerator. Must be convertible to a BigInteger.
     * @param BigNumber|int|float|string $denominator The denominator. Must be convertible to a BigInteger.
     *
     * @throws NumberFormatException      If an argument does not represent a valid number.
     * @throws RoundingNecessaryException If an argument represents a non-integer number.
     * @throws DivisionByZeroException    If the denominator is zero.
     *
     * @psalm-pure
     */
    public static function nd(BigNumber|int|float|string $numerator, BigNumber|int|float|string $denominator): BigRational
    {
        $numerator = BigInteger::of($numerator);
        $denominator = BigInteger::of($denominator);
        return new BigRational($numerator, $denominator, \true);
    }
    /**
     * Returns a BigRational representing zero.
     *
     * @psalm-pure
     */
    public static function zero(): BigRational
    {
        /**
         * @psalm-suppress ImpureStaticVariable
         * @var BigRational|null $zero
         */
        static $zero;
        if ($zero === null) {
            $zero = new BigRational(BigInteger::zero(), BigInteger::one(), \false);
        }
        return $zero;
    }
    /**
     * Returns a BigRational representing one.
     *
     * @psalm-pure
     */
    public static function one(): BigRational
    {
        /**
         * @psalm-suppress ImpureStaticVariable
         * @var BigRational|null $one
         */
        static $one;
        if ($one === null) {
            $one = new BigRational(BigInteger::one(), BigInteger::one(), \false);
        }
        return $one;
    }
    /**
     * Returns a BigRational representing ten.
     *
     * @psalm-pure
     */
    public static function ten(): BigRational
    {
        /**
         * @psalm-suppress ImpureStaticVariable
         * @var BigRational|null $ten
         */
        static $ten;
        if ($ten === null) {
            $ten = new BigRational(BigInteger::ten(), BigInteger::one(), \false);
        }
        return $ten;
    }
    public function getNumerator(): BigInteger
    {
        return $this->numerator;
    }
    public function getDenominator(): BigInteger
    {
        return $this->denominator;
    }
    /**
     * Returns the quotient of the division of the numerator by the denominator.
     */
    public function quotient(): BigInteger
    {
        return $this->numerator->quotient($this->denominator);
    }
    /**
     * Returns the remainder of the division of the numerator by the denominator.
     */
    public function remainder(): BigInteger
    {
        return $this->numerator->remainder($this->denominator);
    }
    /**
     * Returns the quotient and remainder of the division of the numerator by the denominator.
     *
     * @return BigInteger[]
     *
     * @psalm-return array{BigInteger, BigInteger}
     */
    public function quotientAndRemainder(): array
    {
        return $this->numerator->quotientAndRemainder($this->denominator);
    }
    /**
     * Returns the sum of this number and the given one.
     *
     * @param BigNumber|int|float|string $that The number to add.
     *
     * @throws MathException If the number is not valid.
     */
    public function plus(BigNumber|int|float|string $that): BigRational
    {
        $that = BigRational::of($that);
        $numerator = $this->numerator->multipliedBy($that->denominator);
        $numerator = $numerator->plus($that->numerator->multipliedBy($this->denominator));
        $denominator = $this->denominator->multipliedBy($that->denominator);
        return new BigRational($numerator, $denominator, \false);
    }
    /**
     * Returns the difference of this number and the given one.
     *
     * @param BigNumber|int|float|string $that The number to subtract.
     *
     * @throws MathException If the number is not valid.
     */
    public function minus(BigNumber|int|float|string $that): BigRational
    {
        $that = BigRational::of($that);
        $numerator = $this->numerator->multipliedBy($that->denominator);
        $numerator = $numerator->minus($that->numerator->multipliedBy($this->denominator));
        $denominator = $this->denominator->multipliedBy($that->denominator);
        return new BigRational($numerator, $denominator, \false);
    }
    /**
     * Returns the product of this number and the given one.
     *
     * @param BigNumber|int|float|string $that The multiplier.
     *
     * @throws MathException If the multiplier is not a valid number.
     */
    public function multipliedBy(BigNumber|int|float|string $that): BigRational
    {
        $that = BigRational::of($that);
        $numerator = $this->numerator->multipliedBy($that->numerator);
        $denominator = $this->denominator->multipliedBy($that->denominator);
        return new BigRational($numerator, $denominator, \false);
    }
    /**
     * Returns the result of the division of this number by the given one.
     *
     * @param BigNumber|int|float|string $that The divisor.
     *
     * @throws MathException If the divisor is not a valid number, or is zero.
     */
    public function dividedBy(BigNumber|int|float|string $that): BigRational
    {
        $that = BigRational::of($that);
        $numerator = $this->numerator->multipliedBy($that->denominator);
        $denominator = $this->denominator->multipliedBy($that->numerator);
        return new BigRational($numerator, $denominator, \true);
    }
    /**
     * Returns this number exponentiated to the given value.
     *
     * @throws \InvalidArgumentException If the exponent is not in the range 0 to 1,000,000.
     */
    public function power(int $exponent): BigRational
    {
        if ($exponent === 0) {
            $one = BigInteger::one();
            return new BigRational($one, $one, \false);
        }
        if ($exponent === 1) {
            return $this;
        }
        return new BigRational($this->numerator->power($exponent), $this->denominator->power($exponent), \false);
    }
    /**
     * Returns the reciprocal of this BigRational.
     *
     * The reciprocal has the numerator and denominator swapped.
     *
     * @throws DivisionByZeroException If the numerator is zero.
     */
    public function reciprocal(): BigRational
    {
        return new BigRational($this->denominator, $this->numerator, \true);
    }
    /**
     * Returns the absolute value of this BigRational.
     */
    public function abs(): BigRational
    {
        return new BigRational($this->numerator->abs(), $this->denominator, \false);
    }
    /**
     * Returns the negated value of this BigRational.
     */
    public function negated(): BigRational
    {
        return new BigRational($this->numerator->negated(), $this->denominator, \false);
    }
    /**
     * Returns the simplified value of this BigRational.
     */
    public function simplified(): BigRational
    {
        $gcd = $this->numerator->gcd($this->denominator);
        $numerator = $this->numerator->quotient($gcd);
        $denominator = $this->denominator->quotient($gcd);
        return new BigRational($numerator, $denominator, \false);
    }
    #[Override]
    public function compareTo(BigNumber|int|float|string $that): int
    {
        return $this->minus($that)->getSign();
    }
    #[Override]
    public function getSign(): int
    {
        return $this->numerator->getSign();
    }
    #[Override]
    public function toBigInteger(): BigInteger
    {
        $simplified = $this->simplified();
        if (!$simplified->denominator->isEqualTo(1)) {
            throw new RoundingNecessaryException('This rational number cannot be represented as an integer value without rounding.');
        }
        return $simplified->numerator;
    }
    #[Override]
    public function toBigDecimal(): BigDecimal
    {
        return $this->numerator->toBigDecimal()->exactlyDividedBy($this->denominator);
    }
    #[Override]
    public function toBigRational(): BigRational
    {
        return $this;
    }
    #[Override]
    public function toScale(int $scale, RoundingMode $roundingMode = RoundingMode::UNNECESSARY): BigDecimal
    {
        return $this->numerator->toBigDecimal()->dividedBy($this->denominator, $scale, $roundingMode);
    }
    #[Override]
    public function toInt(): int
    {
        return $this->toBigInteger()->toInt();
    }
    #[Override]
    public function toFloat(): float
    {
        $simplified = $this->simplified();
        return $simplified->numerator->toFloat() / $simplified->denominator->toFloat();
    }
    #[Override]
    public function __toString(): string
    {
        $numerator = (string) $this->numerator;
        $denominator = (string) $this->denominator;
        if ($denominator === '1') {
            return $numerator;
        }
        return $numerator . '/' . $denominator;
    }
    /**
     * This method is required for serializing the object and SHOULD NOT be accessed directly.
     *
     * @internal
     *
     * @return array{numerator: BigInteger, denominator: BigInteger}
     */
    public function __serialize(): array
    {
        return ['numerator' => $this->numerator, 'denominator' => $this->denominator];
    }
    /**
     * This method is only here to allow unserializing the object and cannot be accessed directly.
     *
     * @internal
     * @psalm-suppress RedundantPropertyInitializationCheck
     *
     * @param array{numerator: BigInteger, denominator: BigInteger} $data
     *
     * @throws \LogicException
     */
    public function __unserialize(array $data): void
    {
        if (isset($this->numerator)) {
            throw new \LogicException('__unserialize() is an internal function, it must not be called directly.');
        }
        $this->numerator = $data['numerator'];
        $this->denominator = $data['denominator'];
    }
}
MIT License

Copyright (c) 2016

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
#!/usr/bin/env bash
set -e

# Script to extract release notes for a specific version from CHANGELOG.md
# Usage: ./bin/extract-release-notes.sh "6.7.0"
#
# Arguments:
#   $1 - Version number (e.g., "6.7.0")
#
# This script extracts all the content between the specified version header
# and the next version header

if [ $# -lt 1 ]; then
  echo "Usage: $0 <version>"
  echo ""
  echo "Example: $0 '6.7.0'"
  exit 1
fi

VERSION="$1"

if ! [[ "$VERSION" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
    echo "Error: Version must be in format X.Y.Z (e.g., 6.7.0)"
    exit 1
fi

# Check if CHANGELOG.md exists
if [ ! -f CHANGELOG.md ]; then
  echo "Error: CHANGELOG.md not found in current directory"
  exit 1
fi

# Use awk to extract the release notes for the specified version
awk -v version="$VERSION" '
BEGIN { in_version = 0; found = 0 }

# Match the version header
$0 ~ "^## \\[" version "\\]" {
  in_version = 1
  found = 1
  next
}

# Match any other version header
/^## \[/ {
  if (in_version) {
    exit
  }
  next
}

# Print content when in the correct version section
in_version {
  print
}

END {
  if (!found) {
    print "Error: Version " version " not found in CHANGELOG.md" > "/dev/stderr"
    exit 1
  }
}
' CHANGELOG.md
#!/usr/bin/env bash
set -e

# Script to prepare a release by updating CHANGELOG.md
# Usage: ./bin/prepare-release.sh "6.7.0"
#
# Arguments:
#   $1 - Version number (e.g., "6.7.0")
#
# This script:
#   1. Moves all entries from [Unreleased] to a new version section
#   2. Adds the release date
#   3. Leaves an empty [Unreleased] section

if [ $# -lt 1 ]; then
  echo "Usage: $0 <version>"
  echo ""
  echo "Example: $0 '6.7.0'"
  exit 1
fi

VERSION="$1"
RELEASE_DATE=$(date +%Y-%m-%d)

if ! [[ "$VERSION" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
    echo "Error: Version must be in format X.Y.Z (e.g., 6.7.0)"
    exit 1
fi

echo "Preparing release for version: $VERSION"
echo "Release date: $RELEASE_DATE"

# Check if CHANGELOG.md exists
if [ ! -f CHANGELOG.md ]; then
  echo "Error: CHANGELOG.md not found in current directory"
  exit 1
fi

# Check if there is content in the Unreleased section
# Extract content between [Unreleased] and the next version header
UNRELEASED_CONTENT=$(awk '/^## \[Unreleased\]/ {flag=1; next} /^## \[/ {flag=0} flag' CHANGELOG.md)
if ! echo "$UNRELEASED_CONTENT" | grep -q "^### "; then
  echo "Error: No changes found in [Unreleased] section"
  exit 1
fi

# Use awk to process the changelog
awk -v version="$VERSION" -v date="$RELEASE_DATE" '
BEGIN {
  in_unreleased = 0
  buf = ""
}

/^## \[Unreleased\]/ {
  print
  print ""
  print "## [" version "] - " date
  in_unreleased = 1
  next
}

/^## \[/ {
  if (in_unreleased) {
    print buf
    in_unreleased = 0
  }
  print
  next
}

in_unreleased {
  buf = buf $0 "\n"
  next
}

{ print }

END {
  if (in_unreleased) {
    print buf
  }
}
' CHANGELOG.md > CHANGELOG.md.tmp

if [ ! -s CHANGELOG.md.tmp ]; then
  echo "Error: Failed to update CHANGELOG.md"
  rm -f CHANGELOG.md.tmp
  exit 1
fi

mv CHANGELOG.md.tmp CHANGELOG.md

echo "CHANGELOG.md updated successfully"
echo "Created release section for version $VERSION"
#!/usr/bin/env php
<?php 
namespace _ContaoManager;

/**
 * JSON schema validator
 *
 * @author Christian Weiske <christian.weiske@netresearch.de>
 */
// support running this tool from git checkout
$projectDirectory = \dirname(__DIR__);
if (\is_dir($projectDirectory . \DIRECTORY_SEPARATOR . 'vendor')) {
    \set_include_path($projectDirectory . \PATH_SEPARATOR . \get_include_path());
}
// autoload composer classes
$composerAutoload = \stream_resolve_include_path('vendor/autoload.php');
if (!$composerAutoload) {
    echo "Cannot load json-schema library\n";
    exit(1);
}
require $composerAutoload;
$arOptions = [];
$arArgs = [];
\array_shift($argv);
//script itself
foreach ($argv as $arg) {
    if ($arg[0] == '-') {
        $arOptions[$arg] = \true;
    } else {
        $arArgs[] = $arg;
    }
}
if (\count($arArgs) == 0 || isset($arOptions['--help']) || isset($arOptions['-h'])) {
    echo <<<HLP
Validate schema
Usage: validate-json data.json
   or: validate-json data.json schema.json

Options:
      --dump-schema     Output full schema and exit
      --dump-schema-url Output URL of schema
      --verbose         Show additional output
      --quiet           Suppress all output
   -h --help            Show this help

HLP;
    exit(1);
}
if (\count($arArgs) == 1) {
    $pathData = $arArgs[0];
    $pathSchema = null;
} else {
    $pathData = $arArgs[0];
    $pathSchema = getUrlFromPath($arArgs[1]);
}
/**
 * Show the json parse error that happened last
 */
function showJsonError(): void
{
    $constants = \get_defined_constants(\true);
    $json_errors = [];
    foreach ($constants['json'] as $name => $value) {
        if (!\strncmp($name, 'JSON_ERROR_', 11)) {
            $json_errors[$value] = $name;
        }
    }
    output('JSON parse error: ' . $json_errors[\json_last_error()] . "\n");
}
function getUrlFromPath($path)
{
    if (\parse_url($path, \PHP_URL_SCHEME) !== null) {
        //already an URL
        return $path;
    }
    if ($path[0] == '/') {
        //absolute path
        return 'file://' . $path;
    }
    //relative path: make absolute
    return 'file://' . \getcwd() . '/' . $path;
}
/**
 * Take a HTTP header value and split it up into parts.
 *
 * @param $headerValue
 * @return array Key "_value" contains the main value, all others
 *               as given in the header value
 */
function parseHeaderValue($headerValue)
{
    if (\strpos($headerValue, ';') === \false) {
        return ['_value' => $headerValue];
    }
    $parts = \explode(';', $headerValue);
    $arData = ['_value' => \array_shift($parts)];
    foreach ($parts as $part) {
        list($name, $value) = \explode('=', $part);
        $arData[$name] = \trim($value, ' "\'');
    }
    return $arData;
}
/**
 * Send a string to the output stream, but only if --quiet is not enabled
 *
 * @param $str string A string output
 */
function output($str)
{
    global $arOptions;
    if (!isset($arOptions['--quiet'])) {
        echo $str;
    }
}
$urlData = getUrlFromPath($pathData);
$context = \stream_context_create(['http' => ['header' => ['Accept: */*', 'Connection: Close'], 'max_redirects' => 5]]);
$dataString = \file_get_contents($pathData, \false, $context);
if ($dataString == '') {
    output("Data file is not readable or empty.\n");
    exit(3);
}
$data = \json_decode($dataString);
unset($dataString);
if ($data === null) {
    output("Error loading JSON data file\n");
    showJsonError();
    exit(5);
}
if ($pathSchema === null) {
    if (isset($http_response_header)) {
        \array_shift($http_response_header);
        //HTTP/1.0 line
        foreach ($http_response_header as $headerLine) {
            list($hName, $hValue) = \explode(':', $headerLine, 2);
            $hName = \strtolower($hName);
            if ($hName == 'link') {
                //Link: <http://example.org/schema#>; rel="describedBy"
                $hParts = parseHeaderValue($hValue);
                if (isset($hParts['rel']) && $hParts['rel'] == 'describedBy') {
                    $pathSchema = \trim($hParts['_value'], ' <>');
                }
            } else if ($hName == 'content-type') {
                //Content-Type: application/my-media-type+json;
                //              profile=http://example.org/schema#
                $hParts = parseHeaderValue($hValue);
                if (isset($hParts['profile'])) {
                    $pathSchema = $hParts['profile'];
                }
            }
        }
    }
    if (\is_object($data) && \property_exists($data, '$schema')) {
        $pathSchema = $data->{'$schema'};
    }
    //autodetect schema
    if ($pathSchema === null) {
        output("JSON data must be an object and have a \$schema property.\n");
        output("You can pass the schema file on the command line as well.\n");
        output("Schema autodetection failed.\n");
        exit(6);
    }
}
if ($pathSchema[0] == '/') {
    $pathSchema = 'file://' . $pathSchema;
}
$resolver = new JsonSchema\Uri\UriResolver();
$retriever = new JsonSchema\Uri\UriRetriever();
try {
    $urlSchema = $resolver->resolve($pathSchema, $urlData);
    if (isset($arOptions['--dump-schema-url'])) {
        echo $urlSchema . "\n";
        exit;
    }
} catch (\Exception $e) {
    output("Error loading JSON schema file\n");
    output($urlSchema . "\n");
    output($e->getMessage() . "\n");
    exit(2);
}
$refResolver = new JsonSchema\SchemaStorage($retriever, $resolver);
$schema = $refResolver->resolveRef($urlSchema);
if (isset($arOptions['--dump-schema'])) {
    $options = \defined('JSON_PRETTY_PRINT') ? \JSON_PRETTY_PRINT : 0;
    echo \json_encode($schema, $options) . "\n";
    exit;
}
try {
    $validator = new JsonSchema\Validator();
    $validator->validate($data, $schema);
    if ($validator->isValid()) {
        if (isset($arOptions['--verbose'])) {
            output("OK. The supplied JSON validates against the schema.\n");
        }
    } else {
        output("JSON does not validate. Violations:\n");
        foreach ($validator->getErrors() as $error) {
            output(\sprintf("[%s] %s\n", $error['property'], $error['message']));
        }
        exit(23);
    }
} catch (\Exception $e) {
    output("JSON does not validate. Error:\n");
    output($e->getMessage() . "\n");
    output("Error code: " . $e->getCode() . "\n");
    exit(24);
}
#!/usr/bin/env bash
set -e

# Script to update CHANGELOG.md with a new entry
# Usage: ./bin/update-changelog.sh "PR Title" "123" "Fixed"
#
# Arguments:
#   $1 - PR title (the changelog entry text)
#   $2 - PR number
#   $3 - Category (Added, Changed, Fixed, Deprecated, Removed, Security)
#
# Example:
#   ./bin/update-changelog.sh "Fix bug in validation" "456" "Fixed"

if [ $# -lt 3 ]; then
  echo "Usage: $0 <pr_title> <pr_number> <category>"
  echo ""
  echo "Categories: Added, Changed, Fixed, Deprecated, Removed, Security"
  echo ""
  echo "Example: $0 'Fix bug in validation' '456' 'Fixed'"
  exit 1
fi

PR_TITLE="$1"
PR_NUMBER="$2"
CATEGORY="$3"
REPO_URL="${GITHUB_REPOSITORY_URL:-https://github.com/jsonrainbow/json-schema}"

# Remove trailing .git if present
REPO_URL="${REPO_URL%.git}"

# Create the changelog entry
ENTRY="- ${PR_TITLE} ([#${PR_NUMBER}](${REPO_URL}/pull/${PR_NUMBER}))"

echo "Adding entry: $ENTRY"
echo "Under category: ### $CATEGORY"

# Check if CHANGELOG.md exists
if [ ! -f CHANGELOG.md ]; then
  echo "Error: CHANGELOG.md not found in current directory"
  exit 1
fi

# Use awk to insert the entry under the correct category in the Unreleased section
if ! awk -v entry="$ENTRY" -v category="### $CATEGORY" '
BEGIN { in_unreleased=0; found_category=0; added=0 }

# Detect Unreleased section
/^## \[Unreleased\]/ { in_unreleased=1; print; next }

# Detect next version section (end of Unreleased)
/^## \[/ {
  if (in_unreleased && !added) {
    # If we are leaving Unreleased and haven'\''t added entry yet
    # Add category and entry before this line
    if (!found_category) {
      print category
    }
    print entry
    print ""
    added=1
  }
  in_unreleased=0
  found_category=0
  print
  next
}

# If in Unreleased section, look for matching category
in_unreleased && $0 == category {
  found_category=1
  print
  # Add entry right after category header
  print entry
  added=1
  next
}

# Always print the current line
{ print }

# At end of file, if still in unreleased and not added
END {
  if (in_unreleased && !added) {
    if (!found_category) {
      print category
    }
    print entry
  }
}
' CHANGELOG.md > CHANGELOG.md.tmp; then
  echo "Error: Failed to update CHANGELOG.md"
  rm -f CHANGELOG.md.tmp
  exit 1
fi

mv CHANGELOG.md.tmp CHANGELOG.md

echo "CHANGELOG.md updated successfully"
# CHANGELOG

All notable changes to this project will be documented in this file.

The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [Unreleased]

## [6.8.0] - 2026-04-02

### Added
- Bump actions/checkout from v4 to v5 ([#902](https://github.com/jsonrainbow/json-schema/pull/902))
- Update readme for draft 7 ([#899](https://github.com/jsonrainbow/json-schema/pull/899))
- ci: Add Copilot setup steps ([#892](https://github.com/jsonrainbow/json-schema/pull/892))

### Fixed
- Fix shell injection in update-changelog workflow for PR titles with backticks ([#897](https://github.com/jsonrainbow/json-schema/pull/897))
- Remove `v` prefix from release tags and GitHub releases ([#895](https://github.com/jsonrainbow/json-schema/pull/895))

### Deprecated
- Deprecate `Constraint::CHECK_MODE_NONE` ([#896](https://github.com/jsonrainbow/json-schema/pull/896))


## [6.7.2] - 2026-02-15

### Fixed
- Fix idn_to_ascii deprecation warning by using INTL_IDNA_VARIANT_UTS46 ([#887](https://github.com/jsonrainbow/json-schema/pull/887))


## [6.7.1] - 2026-02-13

### Fixed
- Fix TypeError in pattern property validation with integer keys ([#880](https://github.com/jsonrainbow/json-schema/pull/880))


## [6.7.0] - 2026-02-13
### Fixed
- Enforce RFC 1035 hostname label length limits in draft 3/4 ([#878](https://github.com/jsonrainbow/json-schema/pull/878))
- UriRetriever: Include actual media type in InvalidSchemaMediaTypeException message ([#872](https://github.com/jsonrainbow/json-schema/pull/872))
- docs: Correct trailing spaces in Markdown ([#873](https://github.com/jsonrainbow/json-schema/pull/873))

### Added
- Feat: Add Draft-07 support ([#847](https://github.com/jsonrainbow/json-schema/pull/847))
- Automate changelog updates on PR merge ([#874](https://github.com/jsonrainbow/json-schema/pull/874))

### Changed
- Add automated release workflow with changelog integration ([#879](https://github.com/jsonrainbow/json-schema/pull/879))
- Fix welcome workflow permission errors from forked PRs ([#875](https://github.com/jsonrainbow/json-schema/pull/875))


## [6.6.4] - 2025-12-19
### Changed
- ci: Run workflows against 5.x.x branches ([#859](https://github.com/jsonrainbow/json-schema/pull/859))
### Fixed
- UriValidator: Allow `file:/` and `file:///` ([#856](https://github.com/jsonrainbow/json-schema/discussions/856))
- Fix .php-cs-fixer.dist.php export-ignore ([#861](https://github.com/jsonrainbow/json-schema/discussions/861))

## [6.6.3] - 2025-12-02
### Changed
- Restricted `mark-mabe/php-enum` dependency to `^4.4` due to lower versions emitting a warning on PHP 8 ([#854](https://github.com/jsonrainbow/json-schema/pull/854))

## [6.6.2] - 2025-11-28
### Changed
- Move PHP 8.5 to default add PHP 8.6 as experimental ([#852](https://github.com/jsonrainbow/json-schema/pull/852))
### Fixed
- Allow underscore and tilde in URI hostnames as per RFC 3986 ([#853](https://github.com/jsonrainbow/json-schema/pull/853))

## [6.6.1] - 2025-11-07
### Changed
- Rename master to main ([#848](https://github.com/jsonrainbow/json-schema/pull/848))
### Fixed
- Don't skip ref expanding for property called enum when child of property called properties ([#851](https://github.com/jsonrainbow/json-schema/pull/851))

## [6.6.0] - 2025-10-10
### Added
- Add lint check for class autoloading PSR compliance ([#845](https://github.com/jsonrainbow/json-schema/pull/845))
- add implementation for strict fully validating using draft-06 schema ([#843](https://github.com/jsonrainbow/json-schema/pull/835))

## [6.5.2] - 2025-09-09
### Fixed
- Fix issue when http headers are already present ([#843](https://github.com/jsonrainbow/json-schema/pull/843))

## [6.5.1] - 2025-08-29
### Changed
- ci: Add PHP 8.5 to pipeline, ignoring dependencies and as experimental ([#842](https://github.com/jsonrainbow/json-schema/pull/842))

## [6.5.0] - 2025-08-29
### Changed
- Update test case to current (PHP) standards ([#831](https://github.com/jsonrainbow/json-schema/pull/831))
- Upgrade test suite to use generators ([#834](https://github.com/jsonrainbow/json-schema/pull/834))
- update to latest json schema test suite ([#821](https://github.com/jsonrainbow/json-schema/pull/821))
### Fixed
- Fix PHP 8.5 $http_response_header deprecation ([#840](https://github.com/jsonrainbow/json-schema/pull/840))

## [6.4.2] - 2025-06-03
### Fixed
- Fix objects are non-unique despite key order ([#819](https://github.com/jsonrainbow/json-schema/pull/819))
- Id's not being resolved and id property affects sibling ref which it should not do ([#828](https://github.com/jsonrainbow/json-schema/pull/828))

### Changed
- Added extra breaking change to UPDATE-6.0.md regarding BaseConstraint::addError signature change ([#823](https://github.com/jsonrainbow/json-schema/pull/823))
- Update constraint class to PHP 7.2 language level ([#824](https://github.com/jsonrainbow/json-schema/pull/824))
- Update base constraint class to PHP 7.2 language level ([#826](https://github.com/jsonrainbow/json-schema/pull/826))

### Added
- Introduce 32 bits CI workflow on latest php version ([#825](https://github.com/jsonrainbow/json-schema/pull/825))

## [6.4.1] - 2025-04-04
### Fixed
- Fix support for 32bits PHP ([#817](https://github.com/jsonrainbow/json-schema/pull/817))

## [6.4.0] - 2025-04-01
### Added
- Run PHPStan using the lowest and highest php version ([#811](https://github.com/jsonrainbow/json-schema/pull/811))
### Fixed
- Use parallel-lint and cs2pr for improved feedback on linting errors ([#812](https://github.com/jsonrainbow/json-schema/pull/812))
- Array with number values with mathematical equality are considered valid ([#813](https://github.com/jsonrainbow/json-schema/pull/813))
### Changed
- Correct PHPStan findings in validator ([#808](https://github.com/jsonrainbow/json-schema/pull/808))
- Add cs2pr handling for php-cs-fixer; avoid doing composer install ([#814](https://github.com/jsonrainbow/json-schema/pull/814))
- prepare PHP 8.5 in CI ([#815](https://github.com/jsonrainbow/json-schema/pull/815))

## [6.3.1] - 2025-03-18
### Fixed
- ensure numeric issues in const are correctly evaluated ([#805](https://github.com/jsonrainbow/json-schema/pull/805))
- fix 6.3.0 regression with comparison of null values during validation ([#806](https://github.com/jsonrainbow/json-schema/issues/806))

## [6.3.0] - 2025-03-14
### Fixed
- only check minProperties or maxProperties on objects ([#802](https://github.com/jsonrainbow/json-schema/pull/802))
- replace filter_var for uri and uri-reference to userland code to be RFC 3986 compliant ([#800](https://github.com/jsonrainbow/json-schema/pull/800))
- avoid duplicate workflow runs ([#804](https://github.com/jsonrainbow/json-schema/pull/804))

## Changed
- replace icecave/parity with custom deep comparator ([#803](https://github.com/jsonrainbow/json-schema/pull/803))

## [6.2.1] - 2025-03-06
### Fixed
- allow items: true to pass validation ([#801](https://github.com/jsonrainbow/json-schema/pull/801))

### Changed
- Include actual count in collection constraint errors ([#797](https://github.com/jsonrainbow/json-schema/pull/797))

## [6.2.0] - 2025-02-26
### Added
- Welcome first time contributors ([#782](https://github.com/jsonrainbow/json-schema/pull/782))

### Fixed
- Add required permissions for welcome action ([#789](https://github.com/jsonrainbow/json-schema/pull/789))
- Upgrade php cs fixer to latest ([#783](https://github.com/jsonrainbow/json-schema/pull/783))
- Create deep copy before checking each sub schema in oneOf ([#791](https://github.com/jsonrainbow/json-schema/pull/791))
- Create deep copy before checking each sub schema in anyOf ([#792](https://github.com/jsonrainbow/json-schema/pull/792))
- Correctly set the schema ID when passing it as assoc array ([#794](https://github.com/jsonrainbow/json-schema/pull/794))
- Create deep copy before checking each sub schema in oneOf when only check_mode_apply_defaults is set ([#795](https://github.com/jsonrainbow/json-schema/pull/795))
- Additional property casted into int when actually is numeric string ([#784](https://github.com/jsonrainbow/json-schema/pull/784))

### Changed
- Used PHPStan's int-mask-of<T> type where applicable ([#779](https://github.com/jsonrainbow/json-schema/pull/779))
- Fixed some PHPStan errors ([#781](https://github.com/jsonrainbow/json-schema/pull/781))
- Cleanup redundant checks ([#796](https://github.com/jsonrainbow/json-schema/pull/796))

## [6.1.0] - 2025-02-04
### Added
- Add return types in the test suite ([#748](https://github.com/jsonrainbow/json-schema/pull/748))
- Add test case for validating array of strings with objects ([#704](https://github.com/jsonrainbow/json-schema/pull/704))
- Add contributing information, contributor recognition and security information ([#771](https://github.com/jsonrainbow/json-schema/pull/771))

### Fixed
- Correct misconfigured mocks in JsonSchema\Tests\Uri\UriRetrieverTest ([#741](https://github.com/jsonrainbow/json-schema/pull/741))
- Fix pugx badges in README ([#742](https://github.com/jsonrainbow/json-schema/pull/742))
- Add missing property in UriResolverTest ([#743](https://github.com/jsonrainbow/json-schema/pull/743))
- Correct casing of paths used in tests ([#745](https://github.com/jsonrainbow/json-schema/pull/745))
- Resolve deprecations of optional parameter ([#752](https://github.com/jsonrainbow/json-schema/pull/752))
- Fix wrong combined paths when traversing upward, fixes #557 ([#652](https://github.com/jsonrainbow/json-schema/pull/652))
- Correct PHPStan baseline ([#764](https://github.com/jsonrainbow/json-schema/pull/764))
- Correct spacing issue in `README.md` ([#763](https://github.com/jsonrainbow/json-schema/pull/763))
- Format attribute: do not validate data instances that aren't the instance type to validate ([#773](https://github.com/jsonrainbow/json-schema/pull/773))

### Changed
- Bump to minimum PHP 7.2 ([#746](https://github.com/jsonrainbow/json-schema/pull/746))
- Replace traditional syntax array with short syntax array ([#747](https://github.com/jsonrainbow/json-schema/pull/747))
- Increase phpstan level to 8 with baseline to swallow existing errors ([#673](https://github.com/jsonrainbow/json-schema/pull/673))
- Add ext-json to composer.json to ensure JSON extension available  ([#759](https://github.com/jsonrainbow/json-schema/pull/759))
- Add visibility modifiers to class constants ([#757](https://github.com/jsonrainbow/json-schema/pull/757))
- Include PHP 8.4 in workflow ([#765](https://github.com/jsonrainbow/json-schema/pull/765))
- Add `strict_types=1` to all classes in ./src ([#758](https://github.com/jsonrainbow/json-schema/pull/758))
- Raise minimum level of marc-mabe/php-enum ([#766](https://github.com/jsonrainbow/json-schema/pull/766))
- Cleanup test from @param annotations ([#768](https://github.com/jsonrainbow/json-schema/pull/768))
- Remove obsolete PHP 7.1 version check ([#772](https://github.com/jsonrainbow/json-schema/pull/772))

## [6.0.0] - 2024-07-30
### Added
- Add URI translation, package:// URI scheme & bundle spec schemas ([#362](https://github.com/jsonrainbow/json-schema/pull/362))
- Add quiet option ([#382](https://github.com/jsonrainbow/json-schema/pull/382))
- Add option to disable validation of "format" constraint ([#383](https://github.com/jsonrainbow/json-schema/pull/383))
- Add more unit tests ([#366](https://github.com/jsonrainbow/json-schema/pull/366))
- Reset errors prior to validation ([#386](https://github.com/jsonrainbow/json-schema/pull/386))
- Allow the schema to be an associative array ([#389](https://github.com/jsonrainbow/json-schema/pull/389))
- Enable FILTER_FLAG_EMAIL_UNICODE for email format if present ([#398](https://github.com/jsonrainbow/json-schema/pull/398))
- Add enum wrapper ([#375](https://github.com/jsonrainbow/json-schema/pull/375))
- Add option to validate the schema ([#357](https://github.com/jsonrainbow/json-schema/pull/357))
- Add support for "const" ([#507](https://github.com/jsonrainbow/json-schema/pull/507))
- Added note about supported Draft versions ([#620](https://github.com/jsonrainbow/json-schema/pull/620))
- Add linting GH action
### Changed
- Centralize errors ([#364](https://github.com/jsonrainbow/json-schema/pull/364))
- Revert "An email is a string, not much else." ([#373](https://github.com/jsonrainbow/json-schema/pull/373))
- Improvements to type coercion ([#384](https://github.com/jsonrainbow/json-schema/pull/384))
- Don't add a file:// prefix to URI that already have a scheme ([#455](https://github.com/jsonrainbow/json-schema/pull/455))
- Enhancement: Normalize` composer.json` ([#505](https://github.com/jsonrainbow/json-schema/pull/505))
- Correct echo `sprintf` for `printf` ([#634](https://github.com/jsonrainbow/json-schema/pull/634))
- Streamline validation of Regex ([#650](https://github.com/jsonrainbow/json-schema/pull/650))
- Streamline validation of patternProperties Regex ([#653](https://github.com/jsonrainbow/json-schema/pull/653))
- Switch to GH Actions ([#670](https://github.com/jsonrainbow/json-schema/pull/670))
- Updated PHPStan
- Remove unwanted whitespace ([#700](https://github.com/jsonrainbow/json-schema/pull/700))
- Bump to v4 versions of GitHub actions ([#722](https://github.com/jsonrainbow/json-schema/pull/722))
- Update references to jsonrainbow ([#725](https://github.com/jsonrainbow/json-schema/pull/725))
### Deprecated
- Mark check() and coerce() as deprecated ([#476](https://github.com/jsonrainbow/json-schema/pull/476))
### Removed
- Remove stale files from #357 (obviated by #362) ([#400](https://github.com/jsonrainbow/json-schema/pull/400))
- Remove unnecessary fallbacks when args accept null
- Removed unused variable in UndefinedConstraint ([#698](https://github.com/jsonrainbow/json-schema/pull/698))
- Remove dead block of code ([#710](https://github.com/jsonrainbow/json-schema/pull/710))
### Fixed
- Add use line for InvalidArgumentException ([#370](https://github.com/jsonrainbow/json-schema/pull/370))
- Add use line for InvalidArgumentException & adjust scope ([#372](https://github.com/jsonrainbow/json-schema/pull/372))
- Add provided schema under a dummy / internal URI (fixes #376) ([#378](https://github.com/jsonrainbow/json-schema/pull/378))
- Don't throw exceptions until after checking anyOf / oneOf ([#394](https://github.com/jsonrainbow/json-schema/pull/394))
- Fix infinite recursion on some schemas when setting defaults (#359) ([#365](https://github.com/jsonrainbow/json-schema/pull/365))
- Fix autoload to work properly with composer dependencies ([#401](https://github.com/jsonrainbow/json-schema/pull/401))
- Ignore $ref siblings & abort on infinite-loop references ([#437](https://github.com/jsonrainbow/json-schema/pull/437))
- Don't cast multipleOf to be an integer for the error message ([#471](https://github.com/jsonrainbow/json-schema/pull/471))
- Strict Enum/Const Object Checking ([#518](https://github.com/jsonrainbow/json-schema/pull/518))
- Return original value when no cast ([#535](https://github.com/jsonrainbow/json-schema/pull/535))
- Allow `marc-mabe/php-enum` v2.x and v3.x. ([#464](https://github.com/jsonrainbow/json-schema/pull/464))
- Deprecated warning message on composer install command ([#614](https://github.com/jsonrainbow/json-schema/pull/614))
- Allow `marc-mabe/php-enum` v4.x ([#629](https://github.com/jsonrainbow/json-schema/pull/629))
- Fixed method convertJsonPointerIntoPropertyPath in wrong class ([#655](https://github.com/jsonrainbow/json-schema/pull/655))
- Fix type validation failing for "any" and false-y type wording ([#686](https://github.com/jsonrainbow/json-schema/pull/686))
- Correct code style
- Fix: Clean up `.gitattributes` ([#687](https://github.com/jsonrainbow/json-schema/pull/687))
- Fix: Order `friendsofphp/php-cs-fixer` rules ([#688](https://github.com/jsonrainbow/json-schema/pull/688))
- HTTP to HTTPS redirection breaks remote reference resolution ([#709](https://github.com/jsonrainbow/json-schema/pull/709))
- Corrected several typos and code style issues
{
    "$schema": "http://json-schema.org/draft-03/schema#",
    "id": "http://json-schema.org/draft-03/schema#",
    "type": "object",
    
    "properties": {
        "type": {
            "type": [ "string", "array" ],
            "items": {
                "type": [ "string", { "$ref": "#" } ]
            },
            "uniqueItems": true,
            "default": "any"
        },
        
        "properties": {
            "type": "object",
            "additionalProperties": { "$ref": "#" },
            "default": {}
        },
        
        "patternProperties": {
            "type": "object",
            "additionalProperties": { "$ref": "#" },
            "default": {}
        },
        
        "additionalProperties": {
            "type": [ { "$ref": "#" }, "boolean" ],
            "default": {}
        },
        
        "items": {
            "type": [ { "$ref": "#" }, "array" ],
            "items": { "$ref": "#" },
            "default": {}
        },
        
        "additionalItems": {
            "type": [ { "$ref": "#" }, "boolean" ],
            "default": {}
        },
        
        "required": {
            "type": "boolean",
            "default": false
        },
        
        "dependencies": {
            "type": "object",
            "additionalProperties": {
                "type": [ "string", "array", { "$ref": "#" } ],
                "items": {
                    "type": "string"
                }
            },
            "default": {}
        },
        
        "minimum": {
            "type": "number"
        },
        
        "maximum": {
            "type": "number"
        },
        
        "exclusiveMinimum": {
            "type": "boolean",
            "default": false
        },
        
        "exclusiveMaximum": {
            "type": "boolean",
            "default": false
        },
        
        "minItems": {
            "type": "integer",
            "minimum": 0,
            "default": 0
        },
        
        "maxItems": {
            "type": "integer",
            "minimum": 0
        },
        
        "uniqueItems": {
            "type": "boolean",
            "default": false
        },
        
        "pattern": {
            "type": "string",
            "format": "regex"
        },
        
        "minLength": {
            "type": "integer",
            "minimum": 0,
            "default": 0
        },
        
        "maxLength": {
            "type": "integer"
        },
        
        "enum": {
            "type": "array",
            "minItems": 1,
            "uniqueItems": true
        },
        
        "default": {
            "type": "any"
        },
        
        "title": {
            "type": "string"
        },
        
        "description": {
            "type": "string"
        },
        
        "format": {
            "type": "string"
        },
        
        "divisibleBy": {
            "type": "number",
            "minimum": 0,
            "exclusiveMinimum": true,
            "default": 1
        },
        
        "disallow": {
            "type": [ "string", "array" ],
            "items": {
                "type": [ "string", { "$ref": "#" } ]
            },
            "uniqueItems": true
        },
        
        "extends": {
            "type": [ { "$ref": "#" }, "array" ],
            "items": { "$ref": "#" },
            "default": {}
        },
        
        "id": {
            "type": "string",
            "format": "uri"
        },
        
        "$ref": {
            "type": "string",
            "format": "uri"
        },
        
        "$schema": {
            "type": "string",
            "format": "uri"
        }
    },
    
    "dependencies": {
        "exclusiveMinimum": "minimum",
        "exclusiveMaximum": "maximum"
    },
    
    "default": {}
}
{
    "id": "http://json-schema.org/draft-04/schema#",
    "$schema": "http://json-schema.org/draft-04/schema#",
    "description": "Core schema meta-schema",
    "definitions": {
        "schemaArray": {
            "type": "array",
            "minItems": 1,
            "items": { "$ref": "#" }
        },
        "positiveInteger": {
            "type": "integer",
            "minimum": 0
        },
        "positiveIntegerDefault0": {
            "allOf": [ { "$ref": "#/definitions/positiveInteger" }, { "default": 0 } ]
        },
        "simpleTypes": {
            "enum": [ "array", "boolean", "integer", "null", "number", "object", "string" ]
        },
        "stringArray": {
            "type": "array",
            "items": { "type": "string" },
            "minItems": 1,
            "uniqueItems": true
        }
    },
    "type": "object",
    "properties": {
        "id": {
            "type": "string",
            "format": "uri"
        },
        "$schema": {
            "type": "string",
            "format": "uri"
        },
        "title": {
            "type": "string"
        },
        "description": {
            "type": "string"
        },
        "default": {},
        "multipleOf": {
            "type": "number",
            "minimum": 0,
            "exclusiveMinimum": true
        },
        "maximum": {
            "type": "number"
        },
        "exclusiveMaximum": {
            "type": "boolean",
            "default": false
        },
        "minimum": {
            "type": "number"
        },
        "exclusiveMinimum": {
            "type": "boolean",
            "default": false
        },
        "maxLength": { "$ref": "#/definitions/positiveInteger" },
        "minLength": { "$ref": "#/definitions/positiveIntegerDefault0" },
        "pattern": {
            "type": "string",
            "format": "regex"
        },
        "additionalItems": {
            "anyOf": [
                { "type": "boolean" },
                { "$ref": "#" }
            ],
            "default": {}
        },
        "items": {
            "anyOf": [
                { "$ref": "#" },
                { "$ref": "#/definitions/schemaArray" }
            ],
            "default": {}
        },
        "maxItems": { "$ref": "#/definitions/positiveInteger" },
        "minItems": { "$ref": "#/definitions/positiveIntegerDefault0" },
        "uniqueItems": {
            "type": "boolean",
            "default": false
        },
        "maxProperties": { "$ref": "#/definitions/positiveInteger" },
        "minProperties": { "$ref": "#/definitions/positiveIntegerDefault0" },
        "required": { "$ref": "#/definitions/stringArray" },
        "additionalProperties": {
            "anyOf": [
                { "type": "boolean" },
                { "$ref": "#" }
            ],
            "default": {}
        },
        "definitions": {
            "type": "object",
            "additionalProperties": { "$ref": "#" },
            "default": {}
        },
        "properties": {
            "type": "object",
            "additionalProperties": { "$ref": "#" },
            "default": {}
        },
        "patternProperties": {
            "type": "object",
            "additionalProperties": { "$ref": "#" },
            "default": {}
        },
        "dependencies": {
            "type": "object",
            "additionalProperties": {
                "anyOf": [
                    { "$ref": "#" },
                    { "$ref": "#/definitions/stringArray" }
                ]
            }
        },
        "enum": {
            "type": "array",
            "minItems": 1,
            "uniqueItems": true
        },
        "type": {
            "anyOf": [
                { "$ref": "#/definitions/simpleTypes" },
                {
                    "type": "array",
                    "items": { "$ref": "#/definitions/simpleTypes" },
                    "minItems": 1,
                    "uniqueItems": true
                }
            ]
        },
        "allOf": { "$ref": "#/definitions/schemaArray" },
        "anyOf": { "$ref": "#/definitions/schemaArray" },
        "oneOf": { "$ref": "#/definitions/schemaArray" },
        "not": { "$ref": "#" }
    },
    "dependencies": {
        "exclusiveMaximum": [ "maximum" ],
        "exclusiveMinimum": [ "minimum" ]
    },
    "default": {}
}
{
    "$schema": "http://json-schema.org/draft-07/schema#",
    "$id": "http://json-schema.org/draft-07/schema#",
    "title": "Core schema meta-schema",
    "definitions": {
        "schemaArray": {
            "type": "array",
            "minItems": 1,
            "items": {
                "$ref": "#"
            }
        },
        "nonNegativeInteger": {
            "type": "integer",
            "minimum": 0
        },
        "nonNegativeIntegerDefault0": {
            "allOf": [
                {
                    "$ref": "#/definitions/nonNegativeInteger"
                },
                {
                    "default": 0
                }
            ]
        },
        "simpleTypes": {
            "enum": [
                "array",
                "boolean",
                "integer",
                "null",
                "number",
                "object",
                "string"
            ]
        },
        "stringArray": {
            "type": "array",
            "items": {
                "type": "string"
            },
            "uniqueItems": true,
            "default": []
        }
    },
    "type": [
        "object",
        "boolean"
    ],
    "properties": {
        "$id": {
            "type": "string",
            "format": "uri-reference"
        },
        "$schema": {
            "type": "string",
            "format": "uri"
        },
        "$ref": {
            "type": "string",
            "format": "uri-reference"
        },
        "$comment": {
            "type": "string"
        },
        "title": {
            "type": "string"
        },
        "description": {
            "type": "string"
        },
        "default": true,
        "readOnly": {
            "type": "boolean",
            "default": false
        },
        "writeOnly": {
            "type": "boolean",
            "default": false
        },
        "examples": {
            "type": "array",
            "items": true
        },
        "multipleOf": {
            "type": "number",
            "exclusiveMinimum": 0
        },
        "maximum": {
            "type": "number"
        },
        "exclusiveMaximum": {
            "type": "number"
        },
        "minimum": {
            "type": "number"
        },
        "exclusiveMinimum": {
            "type": "number"
        },
        "maxLength": {
            "$ref": "#/definitions/nonNegativeInteger"
        },
        "minLength": {
            "$ref": "#/definitions/nonNegativeIntegerDefault0"
        },
        "pattern": {
            "type": "string",
            "format": "regex"
        },
        "additionalItems": {
            "$ref": "#"
        },
        "items": {
            "anyOf": [
                {
                    "$ref": "#"
                },
                {
                    "$ref": "#/definitions/schemaArray"
                }
            ],
            "default": true
        },
        "maxItems": {
            "$ref": "#/definitions/nonNegativeInteger"
        },
        "minItems": {
            "$ref": "#/definitions/nonNegativeIntegerDefault0"
        },
        "uniqueItems": {
            "type": "boolean",
            "default": false
        },
        "contains": {
            "$ref": "#"
        },
        "maxProperties": {
            "$ref": "#/definitions/nonNegativeInteger"
        },
        "minProperties": {
            "$ref": "#/definitions/nonNegativeIntegerDefault0"
        },
        "required": {
            "$ref": "#/definitions/stringArray"
        },
        "additionalProperties": {
            "$ref": "#"
        },
        "definitions": {
            "type": "object",
            "additionalProperties": {
                "$ref": "#"
            },
            "default": {}
        },
        "properties": {
            "type": "object",
            "additionalProperties": {
                "$ref": "#"
            },
            "default": {}
        },
        "patternProperties": {
            "type": "object",
            "additionalProperties": {
                "$ref": "#"
            },
            "propertyNames": {
                "format": "regex"
            },
            "default": {}
        },
        "dependencies": {
            "type": "object",
            "additionalProperties": {
                "anyOf": [
                    {
                        "$ref": "#"
                    },
                    {
                        "$ref": "#/definitions/stringArray"
                    }
                ]
            }
        },
        "propertyNames": {
            "$ref": "#"
        },
        "const": true,
        "enum": {
            "type": "array",
            "items": true,
            "minItems": 1,
            "uniqueItems": true
        },
        "type": {
            "anyOf": [
                {
                    "$ref": "#/definitions/simpleTypes"
                },
                {
                    "type": "array",
                    "items": {
                        "$ref": "#/definitions/simpleTypes"
                    },
                    "minItems": 1,
                    "uniqueItems": true
                }
            ]
        },
        "format": {
            "type": "string"
        },
        "contentMediaType": {
            "type": "string"
        },
        "contentEncoding": {
            "type": "string"
        },
        "if": {
            "$ref": "#"
        },
        "then": {
            "$ref": "#"
        },
        "else": {
            "$ref": "#"
        },
        "allOf": {
            "$ref": "#/definitions/schemaArray"
        },
        "anyOf": {
            "$ref": "#/definitions/schemaArray"
        },
        "oneOf": {
            "$ref": "#/definitions/schemaArray"
        },
        "not": {
            "$ref": "#"
        }
    },
    "default": true
}
{
    "$schema": "http://json-schema.org/draft-06/schema#",
    "$id": "http://json-schema.org/draft-06/schema#",
    "title": "Core schema meta-schema",
    "definitions": {
        "schemaArray": {
            "type": "array",
            "minItems": 1,
            "items": { "$ref": "#" }
        },
        "nonNegativeInteger": {
            "type": "integer",
            "minimum": 0
        },
        "nonNegativeIntegerDefault0": {
            "allOf": [
                { "$ref": "#/definitions/nonNegativeInteger" },
                { "default": 0 }
            ]
        },
        "simpleTypes": {
            "enum": [
                "array",
                "boolean",
                "integer",
                "null",
                "number",
                "object",
                "string"
            ]
        },
        "stringArray": {
            "type": "array",
            "items": { "type": "string" },
            "uniqueItems": true,
            "default": []
        }
    },
    "type": ["object", "boolean"],
    "properties": {
        "$id": {
            "type": "string",
            "format": "uri-reference"
        },
        "$schema": {
            "type": "string",
            "format": "uri"
        },
        "$ref": {
            "type": "string",
            "format": "uri-reference"
        },
        "title": {
            "type": "string"
        },
        "description": {
            "type": "string"
        },
        "default": {},
        "examples": {
            "type": "array",
            "items": {}
        },
        "multipleOf": {
            "type": "number",
            "exclusiveMinimum": 0
        },
        "maximum": {
            "type": "number"
        },
        "exclusiveMaximum": {
            "type": "number"
        },
        "minimum": {
            "type": "number"
        },
        "exclusiveMinimum": {
            "type": "number"
        },
        "maxLength": { "$ref": "#/definitions/nonNegativeInteger" },
        "minLength": { "$ref": "#/definitions/nonNegativeIntegerDefault0" },
        "pattern": {
            "type": "string",
            "format": "regex"
        },
        "additionalItems": { "$ref": "#" },
        "items": {
            "anyOf": [
                { "$ref": "#" },
                { "$ref": "#/definitions/schemaArray" }
            ],
            "default": {}
        },
        "maxItems": { "$ref": "#/definitions/nonNegativeInteger" },
        "minItems": { "$ref": "#/definitions/nonNegativeIntegerDefault0" },
        "uniqueItems": {
            "type": "boolean",
            "default": false
        },
        "contains": { "$ref": "#" },
        "maxProperties": { "$ref": "#/definitions/nonNegativeInteger" },
        "minProperties": { "$ref": "#/definitions/nonNegativeIntegerDefault0" },
        "required": { "$ref": "#/definitions/stringArray" },
        "additionalProperties": { "$ref": "#" },
        "definitions": {
            "type": "object",
            "additionalProperties": { "$ref": "#" },
            "default": {}
        },
        "properties": {
            "type": "object",
            "additionalProperties": { "$ref": "#" },
            "default": {}
        },
        "patternProperties": {
            "type": "object",
            "additionalProperties": { "$ref": "#" },
            "propertyNames": { "format": "regex" },
            "default": {}
        },
        "dependencies": {
            "type": "object",
            "additionalProperties": {
                "anyOf": [
                    { "$ref": "#" },
                    { "$ref": "#/definitions/stringArray" }
                ]
            }
        },
        "propertyNames": { "$ref": "#" },
        "const": {},
        "enum": {
            "type": "array",
            "minItems": 1,
            "uniqueItems": true
        },
        "type": {
            "anyOf": [
                { "$ref": "#/definitions/simpleTypes" },
                {
                    "type": "array",
                    "items": { "$ref": "#/definitions/simpleTypes" },
                    "minItems": 1,
                    "uniqueItems": true
                }
            ]
        },
        "format": { "type": "string" },
        "allOf": { "$ref": "#/definitions/schemaArray" },
        "anyOf": { "$ref": "#/definitions/schemaArray" },
        "oneOf": { "$ref": "#/definitions/schemaArray" },
        "not": { "$ref": "#" }
    },
    "default": {}
}
# JSON Schema for PHP

[![Build Status](https://github.com/jsonrainbow/json-schema/actions/workflows/continuous-integration.yml/badge.svg)](https://github.com/jsonrainbow/json-schema/actions)
[![Latest Stable Version](https://poser.pugx.org/justinrainbow/json-schema/v/stable)](https://packagist.org/packages/justinrainbow/json-schema)
[![Total Downloads](https://poser.pugx.org/justinrainbow/json-schema/downloads)](https://packagist.org/packages/justinrainbow/json-schema/stats)
![Supported Dialects](https://img.shields.io/endpoint?url=https%3A%2F%2Fbowtie.report%2Fbadges%2Fphp-justinrainbow-json-schema%2Fsupported_versions.json)

A PHP Implementation for validating `JSON` Structures against a given `Schema` with support for `Schemas` of Draft-3,
Draft-4, Draft-6 or Draft-7.

Features of newer Drafts might not be supported. See [Table of All Versions of Everything](https://json-schema.org/specification-links.html#table-of-all-versions-of-everything) to get an overview
of all existing Drafts. See [json-schema](http://json-schema.org/) for more details about the JSON Schema specification

# Compliance
![Draft 3](https://img.shields.io/endpoint?url=https%3A%2F%2Fbowtie.report%2Fbadges%2Fphp-justinrainbow-json-schema%2Fcompliance%2Fdraft3.json)
![Draft 4](https://img.shields.io/endpoint?url=https%3A%2F%2Fbowtie.report%2Fbadges%2Fphp-justinrainbow-json-schema%2Fcompliance%2Fdraft4.json)
![Draft 6](https://img.shields.io/endpoint?url=https%3A%2F%2Fbowtie.report%2Fbadges%2Fphp-justinrainbow-json-schema%2Fcompliance%2Fdraft6.json)
![Draft 7](https://img.shields.io/endpoint?url=https%3A%2F%2Fbowtie.report%2Fbadges%2Fphp-justinrainbow-json-schema%2Fcompliance%2Fdraft7.json)


## Installation

### Library

```bash
git clone https://github.com/jsonrainbow/json-schema.git
```

### Composer

[Install PHP Composer](https://getcomposer.org/doc/00-intro.md)

```bash
composer require justinrainbow/json-schema
```

## Usage

For a complete reference see [Understanding JSON Schema](https://json-schema.org/understanding-json-schema/).

__Note:__ Not all drafts might be supported, check the [Bowtie report](https://bowtie.report/#/implementations/php-justinrainbow-json-schema) on the current state of draft implementations.

### Basic usage

```php
<?php

$data = json_decode(file_get_contents('data.json'), false);

// Validate
$validator = new JsonSchema\Validator();
$validator->validate($data, (object)['$ref' => 'file://' . realpath('schema.json')]);

if ($validator->isValid()) {
    echo "The supplied JSON validates against the schema.\n";
} else {
    echo "JSON does not validate. Violations:\n";
    foreach ($validator->getErrors() as $error) {
        printf("[%s] %s\n", $error['property'], $error['message']);
    }
}
```

### Type coercion

If you're validating data passed to your application via HTTP, you can cast strings and booleans to
the expected types defined by your schema:

```php
<?php

use JsonSchema\SchemaStorage;
use JsonSchema\Validator;
use JsonSchema\Constraints\Factory;
use JsonSchema\Constraints\Constraint;

$request = (object)[
    'processRefund'=>"true",
    'refundAmount'=>"17"
];

$validator->validate(
    $request, (object) [
        "type"=>"object",
        "properties"=>(object)[
            "processRefund"=>(object)[
                "type"=>"boolean"
            ],
            "refundAmount"=>(object)[
                "type"=>"number"
            ]
        ]
    ],
    Constraint::CHECK_MODE_COERCE_TYPES
); // validates!

is_bool($request->processRefund); // true
is_int($request->refundAmount); // true
```

A shorthand method is also available:
```PHP
$validator->coerce($request, $schema);
// equivalent to $validator->validate($data, $schema, Constraint::CHECK_MODE_COERCE_TYPES);
```

### Default values

If your schema contains default values, you can have these automatically applied during validation:

```php
<?php

use JsonSchema\Validator;
use JsonSchema\Constraints\Constraint;

$request = (object)[
    'refundAmount'=>17
];

$validator = new Validator();

$validator->validate(
    $request,
    (object)[
        "type"=>"object",
        "properties"=>(object)[
            "processRefund"=>(object)[
                "type"=>"boolean",
                "default"=>true
            ]
        ]
    ],
    Constraint::CHECK_MODE_APPLY_DEFAULTS
); //validates, and sets defaults for missing properties

is_bool($request->processRefund); // true
$request->processRefund; // true
```

### With inline references

```php
<?php

use JsonSchema\SchemaStorage;
use JsonSchema\Validator;
use JsonSchema\Constraints\Factory;

$jsonSchema = <<<'JSON'
{
    "type": "object",
    "properties": {
        "data": {
            "oneOf": [
                { "$ref": "#/definitions/integerData" },
                { "$ref": "#/definitions/stringData" }
            ]
        }
    },
    "required": ["data"],
    "definitions": {
        "integerData" : {
            "type": "integer",
            "minimum" : 0
        },
        "stringData" : {
            "type": "string"
        }
    }
}
JSON;

// Schema must be decoded before it can be used for validation
$jsonSchemaObject = json_decode($jsonSchema);

// The SchemaStorage can resolve references, loading additional schemas from file as needed, etc.
$schemaStorage = new SchemaStorage();

// This does two things:
// 1) Mutates $jsonSchemaObject to normalize the references (to file://mySchema#/definitions/integerData, etc)
// 2) Tells $schemaStorage that references to file://mySchema... should be resolved by looking in $jsonSchemaObject
$schemaStorage->addSchema('file://mySchema', $jsonSchemaObject);

// Provide $schemaStorage to the Validator so that references can be resolved during validation
$jsonValidator = new Validator(new Factory($schemaStorage));

// JSON must be decoded before it can be validated
$jsonToValidateObject = json_decode('{"data":123}');

// Do validation (use isValid() and getErrors() to check the result)
$jsonValidator->validate($jsonToValidateObject, $jsonSchemaObject);
```

### Configuration Options
A number of flags are available to alter the behavior of the validator. These can be passed as the
third argument to `Validator::validate()`, or can be provided as the third argument to
`Factory::__construct()` if you wish to persist them across multiple `validate()` calls.

| Flag                                            | Description                                                     |
|-------------------------------------------------|-----------------------------------------------------------------|
| `Constraint::CHECK_MODE_NORMAL`                 | Validate in 'normal' mode - this is the default                 |
| `Constraint::CHECK_MODE_TYPE_CAST`              | Enable fuzzy type checking for associative arrays and objects   |
| `Constraint::CHECK_MODE_COERCE_TYPES` [^1][^2]  | Convert data types to match the schema where possible           |
| `Constraint::CHECK_MODE_EARLY_COERCE` [^2]      | Apply type coercion as soon as possible                         |
| `Constraint::CHECK_MODE_APPLY_DEFAULTS` [^1]    | Apply default values from the schema if not set                 |
| `Constraint::CHECK_MODE_ONLY_REQUIRED_DEFAULTS` | When applying defaults, only set values that are required       |
| `Constraint::CHECK_MODE_EXCEPTIONS`             | Throw an exception immediately if validation fails              |
| `Constraint::CHECK_MODE_DISABLE_FORMAT`         | Do not validate "format" constraints                            |
| `Constraint::CHECK_MODE_VALIDATE_SCHEMA`        | Validate the schema as well as the provided document            |
| `Constraint::CHECK_MODE_STRICT` [^3]            | Validate the scheme using strict mode using the specified draft |

[^1]: Please note that using `CHECK_MODE_COERCE_TYPES` or `CHECK_MODE_APPLY_DEFAULTS` will modify your
original data.
[^2]: `CHECK_MODE_EARLY_COERCE` has no effect unless used in combination with `CHECK_MODE_COERCE_TYPES`. If
enabled, the validator will use (and coerce) the first compatible type it encounters, even if the
schema defines another type that matches directly and does not require coercion.
[^3]: `CHECK_MODE_STRICT` only can be used for Draft-6 at this point.

## Running the tests

```bash
composer test                            # run all unit tests
composer testOnly TestClass              # run specific unit test class
composer testOnly TestClass::testMethod  # run specific unit test method
composer style-check                     # check code style for errors
composer style-fix                       # automatically fix code style errors
```

# Contributors  ✨
Thanks go to these wonderful people, without their effort this project wasn't possible.

<a href="https://github.com/jsonrainbow/json-schema/graphs/contributors">
  <img src="https://contrib.rocks/image?repo=jsonrainbow/json-schema" />
</a>
UPGRADE FROM 5.3 to 6.0
=======================

## Introduction

We are excited to release version 6.0 of our open-source package, featuring major improvements and important updates. This release includes several breaking changes from version 5.3 aimed at enhancing performance, security, and flexibility.

Please review the following breaking changes carefully and update your implementations to ensure compatibility with version 6.0. This guide provides key modifications and instructions for a smooth transition.

Thank you for your support and contributions to the project.

## Errors
* `constraint` key is no longer the constraint name but contains more information in order to translate violations.

    *Before*
    ```php
    foreach ($validator->getErrors() as $error) {
        echo $error['constraint']; // required
    }
    ```

    *After*
    ```php
    foreach ($validator->getErrors() as $error) {
        echo $error['constraint']['name']; // required
    }
    ```

## BaseConstraint::addError signature changed

* The signature for the `BaseConstraint::AddError` method has changed.

  The `$message` parameter has been removed and replaced by the `ConstraintError` parameter.
  The `ConstraintError` object encapsulates the error message along with additional information about the constraint violation.

    *Before*
    ```php
    public function addError(?JsonPointer $path, $message, $constraint = '', ?array $more = null)
    ```

    *After*
    ```php
    public function addError(ConstraintError $constraint, ?JsonPointer $path = null, array $more = []): void
    ```

# Contributing to JSON Schema

First off, thanks for taking the time to contribute! ❤️

All types of contributions are encouraged and valued. See the [Table of Contents](#table-of-contents) for different ways to help and details about how this project handles them. Please make sure to read the relevant section before making your contribution. It will make it a lot easier for us maintainers and smooth out the experience for all involved. The community looks forward to your contributions. 🎉

> And if you like the project, but just don't have time to contribute, that's fine. There are other easy ways to support the project and show your appreciation, which we would also be very happy about:
> - Star the project
> - Tweet about it
> - Refer this project in your project's readme
> - Mention the project at local meetups and tell your friends/colleagues

## Table of Contents

- [I Have a Question](#i-have-a-question)
- [I Want To Contribute](#i-want-to-contribute)
- [Reporting Bugs](#reporting-bugs)
- [Suggesting Enhancements](#suggesting-enhancements)
- [Pull Requests](#pull-requests)

## I Have a Question

> If you want to ask a question, we assume that you have read the available [Documentation](https://github.com/jsonrainbow/json-schema/wiki).

Before you ask a question, it is best to search for existing [Issues](https://github.com/jsonrainbow/json-schema/issues) that might help you. In case you have found a suitable issue and still need clarification, you can write your question in this issue. It is also advisable to search the internet for answers first.

If you then still feel the need to ask a question and need clarification, we recommend the following:

- Open an [Issue](https://github.com/jsonrainbow/json-schema/issues/new).
- Provide as much context as you can about what you're running into.
- Provide project and PHP version, depending on what seems relevant.

We will then take care of the issue as soon as possible.

## I Want To Contribute

> ### Legal Notice
> When contributing to this project, you must agree that you have authored 100% of the content, that you have the necessary rights to the content and that the content you contribute may be provided under the project licence.

## Reporting Bugs

### Before Submitting a Bug Report

A good bug report shouldn't leave others needing to chase you up for more information. Therefore, we ask you to investigate carefully, collect information and describe the issue in detail in your report. Please complete the following steps in advance to help us fix any potential bug as fast as possible.

- Make sure that you are using the latest version.
- Determine if your bug is really a bug and not an error on your side e.g. using incompatible environment components/versions (Make sure that you have read the [documentation](https://github.com/jsonrainbow/json-schema/wiki). If you are looking for support, you might want to check [this section](#i-have-a-question)).
- To see if other users have experienced (and potentially already solved) the same issue you are having, check if there is not already a bug report existing for your bug or error in the [bug tracker](https://github.com/jsonrainbow/json-schema/issues?q=label%3Abug).
- Collect information about the bug:
  - Stack trace (Traceback)
  - OS, Platform and Version (Windows, Linux, macOS, x86, ARM)
  - Version of the interpreter, compiler, SDK, runtime environment, package manager, depending on what seems relevant.
  - Possibly your input and the output
- Can you reliably reproduce the issue? And can you also reproduce it with older versions?

### How Do I Submit a Good Bug Report?

> You must never report security related issues, vulnerabilities or bugs including sensitive information to the issue tracker, or elsewhere in public. Instead, sensitive bugs must be reported at https://github.com/jsonrainbow/json-schema/security

GitHub issues is used to track bugs and errors. If you run into an issue with the project:

- Open an [Issue](https://github.com/jsonrainbow/json-schema/issues/new).
- Explain the behavior you would expect and the actual behavior.
- Please provide as much context as possible and describe the *reproduction steps* that someone else can follow to recreate the issue on their own. This usually includes your code. For good bug reports you should isolate the problem and create a reduced test case.
- Provide the information you collected in the previous section.

Once it's filed:

- The project team will label the issue accordingly.
- A team member will try to reproduce the issue with your provided steps. If there are no reproduction steps or no obvious way to reproduce the issue, the team will ask you for those steps and mark the issue as `needs-repro`. Bugs with the `needs-repro` tag will not be addressed until they are reproduced.
- If the team is able to reproduce the issue, it will be marked `needs-fix`, as well as possibly other tags (such as `critical`), and the issue will be left to be [implemented by someone](#your-first-code-contribution).

### Suggesting Enhancements

This section guides you through submitting an enhancement suggestion for JSON Schema, **including completely new features and minor improvements to existing functionality**. Following these guidelines will help maintainers and the community to understand your suggestion and find related suggestions.

#### Before Submitting an Enhancement

- Make sure that you are using the latest version.
- Read the [documentation](https://github.com/jsonrainbow/json-schema/wiki) carefully and find out if the functionality is already covered, maybe by an individual configuration.
- Perform a [search](https://github.com/jsonrainbow/json-schema/issues) to see if the enhancement has already been suggested. If it has, add a comment to the existing issue instead of opening a new one.
- Find out whether your idea fits with the scope and aims of the project. It's up to you to make a strong case to convince the project's developers of the merits of this feature. Keep in mind that we want features that will be useful to the majority of our users and not just a small subset. If you're just targeting a minority of users, consider writing an add-on/plugin library.

#### How Do I Submit a Good Enhancement Suggestion?

Enhancement suggestions are tracked as [GitHub issues](https://github.com/jsonrainbow/json-schema/issues).

- Use a **clear and descriptive title** for the issue to identify the suggestion.
- Provide a **step-by-step description of the suggested enhancement** in as many details as possible.
- **Describe the current behavior** and **explain which behavior you expected to see instead** and why. At this point you can also tell which alternatives do not work for you.
- You may want to **include screenshots or screen recordings** which help you demonstrate the steps or point out the part which the suggestion is related to. 
- **Explain why this enhancement would be useful** to most JSON Schema users. You may also want to point out the other projects that solved it better and which could serve as inspiration.

## Pull Requests

When submitting a pull request, please keep the following in mind:

### Automated Changelog

This project uses an automated changelog system. When your PR is merged to `main`, a GitHub Actions workflow will automatically add an entry to the CHANGELOG.md file under the "Unreleased" section.

**PR Labels and Changelog Categories:**

The workflow determines which category to place your entry under based on the labels on your PR:

- `bug`, `fix` → **Fixed** - for bug fixes
- `enhancement`, `feature`, `added` → **Added** - for new features
- `changed` → **Changed** - for changes in existing functionality
- `deprecated` → **Deprecated** - for soon-to-be removed features
- `removed` → **Removed** - for now removed features
- `security` → **Security** - for security-related changes
- `breaking` → **Changed** - for breaking changes
- No matching label → **Changed** (default)

**What this means for you:**

- ✅ You do NOT need to manually update CHANGELOG.md in your PR
- ✅ Make sure your PR title is clear and descriptive (it will become the changelog entry)
- ✅ Add appropriate labels to your PR to ensure it appears in the correct category
- ✅ Maintainers will add labels during the review process if needed

<!-- You might want to create an issue template for enhancement suggestions that can be used as a guide and that defines the structure of the information to be included. If you do so, reference it here in the description. -->

## Attribution
This guide is based on the [contributing.md](https://contributing.md/generator)!{
    "name": "justinrainbow\/json-schema",
    "type": "library",
    "description": "A library to validate a json schema.",
    "keywords": [
        "json",
        "schema"
    ],
    "homepage": "https:\/\/github.com\/jsonrainbow\/json-schema",
    "license": "MIT",
    "authors": [
        {
            "name": "Bruno Prieto Reis",
            "email": "bruno.p.reis@gmail.com"
        },
        {
            "name": "Justin Rainbow",
            "email": "justin.rainbow@gmail.com"
        },
        {
            "name": "Igor Wiedler",
            "email": "igor@wiedler.ch"
        },
        {
            "name": "Robert Sch\u00f6nthal",
            "email": "seroscho@googlemail.com"
        }
    ],
    "require": {
        "php": "^7.2 || ^8.0",
        "ext-json": "*",
        "marc-mabe\/php-enum": "^4.4"
    },
    "require-dev": {
        "friendsofphp\/php-cs-fixer": "3.3.0",
        "json-schema\/json-schema-test-suite": "^23.2",
        "phpunit\/phpunit": "^8.5",
        "phpspec\/prophecy": "^1.19",
        "phpstan\/phpstan": "^1.12",
        "marc-mabe\/php-enum-phpstan": "^2.0"
    },
    "extra": {
        "branch-alias": {
            "dev-master": "6.x-dev"
        }
    },
    "autoload": {
        "psr-4": {
            "_ContaoManager\\JsonSchema\\": "src\/JsonSchema\/"
        }
    },
    "autoload-dev": {
        "psr-4": {
            "_ContaoManager\\JsonSchema\\Tests\\": "tests\/"
        }
    },
    "repositories": [
        {
            "type": "package",
            "package": {
                "name": "json-schema\/json-schema-test-suite",
                "version": "23.2.0",
                "source": {
                    "type": "git",
                    "url": "https:\/\/github.com\/json-schema\/JSON-Schema-Test-Suite",
                    "reference": "23.2.0"
                }
            }
        }
    ],
    "bin": [
        "bin\/validate-json"
    ],
    "scripts": {
        "coverage": "phpunit --coverage-text",
        "style-check": "php-cs-fixer fix --dry-run --verbose --diff",
        "style-fix": "php-cs-fixer fix --verbose",
        "test": "phpunit",
        "testOnly": "phpunit --colors --filter",
        "phpstan": "@php phpstan",
        "phpstan-generate-baseline": "@php phpstan --generate-baseline"
    }
}# Security Policy

## Supported Versions

| Version | Supported          |
| ------- | ------------------ |
| 6.x.x   | :white_check_mark: |
| 5.x.x   | :white_check_mark: |
| < 5.0   | :x:                |

## Reporting a Vulnerability

JSON Schema uses the GitHub feature to safely report vulnerabilities, please report them using https://github.com/jsonrainbow/json-schema/security<?php

declare (strict_types=1);
namespace _ContaoManager\JsonSchema;

class Rfc3339
{
    private const REGEX = '/^(\d{4}-\d{2}-\d{2}[T ](0[0-9]|1[0-9]|2[0-3]):([0-5][0-9]):((?:[0-5][0-9]|60)))(\.\d+)?(Z|([+-](0[0-9]|1[0-9]|2[0-3]))(:)?([0-5][0-9]))$/';
    /**
     * Try creating a DateTime instance
     *
     * @param string $input
     *
     * @return \DateTime|null
     */
    public static function createFromString($input): ?\DateTime
    {
        if (!preg_match(self::REGEX, strtoupper($input), $matches)) {
            return null;
        }
        $input = strtoupper($input);
        // Cleanup for lowercase t and z
        $inputHasTSeparator = strpos($input, 'T');
        $dateAndTime = $matches[1];
        $microseconds = $matches[5] ?: '.000000';
        $timeZone = 'Z' !== $matches[6] ? $matches[6] : '+00:00';
        $dateFormat = $inputHasTSeparator === \false ? 'Y-m-d H:i:s.uP' : 'Y-m-d\TH:i:s.uP';
        $dateTime = \DateTimeImmutable::createFromFormat($dateFormat, $dateAndTime . $microseconds . $timeZone, new \DateTimeZone('UTC'));
        if ($dateTime === \false) {
            return null;
        }
        $utcDateTime = $dateTime->setTimezone(new \DateTimeZone('+00:00'));
        $oneSecond = new \DateInterval('PT1S');
        // handle leap seconds
        if ($matches[4] === '60' && $utcDateTime->sub($oneSecond)->format('H:i:s') === '23:59:59') {
            $dateTime = $dateTime->sub($oneSecond);
            $matches[1] = str_replace(':60', ':59', $matches[1]);
        }
        // Ensure we still have the same year, month, day, hour, minutes and seconds to ensure no rollover took place.
        if ($dateTime->format($inputHasTSeparator ? 'Y-m-d\TH:i:s' : 'Y-m-d H:i:s') !== $matches[1]) {
            return null;
        }
        $mutable = \DateTime::createFromFormat('U.u', $dateTime->format('U.u'));
        if ($mutable === \false) {
            throw new \RuntimeException('Unable to create DateTime from DateTimeImmutable');
        }
        $mutable->setTimezone($dateTime->getTimezone());
        return $mutable;
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of the JsonSchema package.
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\JsonSchema;

use _ContaoManager\JsonSchema\Constraints\BaseConstraint;
use _ContaoManager\JsonSchema\Constraints\Constraint;
use _ContaoManager\JsonSchema\Constraints\TypeCheck\LooseTypeCheck;
/**
 * A JsonSchema Constraint
 *
 * @author Robert Schönthal <seroscho@googlemail.com>
 * @author Bruno Prieto Reis <bruno.p.reis@gmail.com>
 *
 * @see    README.md
 */
class Validator extends BaseConstraint
{
    public const SCHEMA_MEDIA_TYPE = 'application/schema+json';
    public const ERROR_NONE = 0;
    public const ERROR_ALL = -1;
    public const ERROR_DOCUMENT_VALIDATION = 1;
    public const ERROR_SCHEMA_VALIDATION = 2;
    /**
     * Validates the given data against the schema and returns an object containing the results
     * Both the php object and the schema are supposed to be a result of a json_decode call.
     * The validation works as defined by the schema proposal in http://json-schema.org.
     *
     * Note that the first argument is passed by reference, so you must pass in a variable.
     *
     * @param mixed $value
     * @param mixed $schema
     *
     * @phpstan-param int-mask-of<Constraint::CHECK_MODE_*> $checkMode
     * @phpstan-return int-mask-of<Validator::ERROR_*>
     */
    public function validate(&$value, $schema = null, ?int $checkMode = null): int
    {
        // reset errors prior to validation
        $this->reset();
        // set checkMode
        $initialCheckMode = $this->factory->getConfig();
        if ($checkMode !== null) {
            $this->factory->setConfig($checkMode);
        }
        // add provided schema to SchemaStorage with internal URI to allow internal $ref resolution
        $schemaURI = SchemaStorage::INTERNAL_PROVIDED_SCHEMA_URI;
        if (LooseTypeCheck::propertyExists($schema, 'id')) {
            $schemaURI = LooseTypeCheck::propertyGet($schema, 'id');
        }
        if (LooseTypeCheck::propertyExists($schema, '$id')) {
            $schemaURI = LooseTypeCheck::propertyGet($schema, '$id');
        }
        $this->factory->getSchemaStorage()->addSchema($schemaURI, $schema);
        $validator = $this->factory->createInstanceFor('schema');
        $schema = $this->factory->getSchemaStorage()->getSchema($schemaURI);
        // Boolean schema requires no further validation
        if (is_bool($schema)) {
            if ($schema === \false) {
                $this->addError(ConstraintError::FALSE());
            }
            return $this->getErrorMask();
        }
        if ($this->factory->getConfig(Constraint::CHECK_MODE_STRICT)) {
            $dialect = $this->factory->getDefaultDialect();
            if (property_exists($schema, '$schema')) {
                $dialect = $schema->{'$schema'};
            }
            $validator = $this->factory->createInstanceFor(DraftIdentifiers::byValue($dialect)->toConstraintName());
        }
        $validator->check($value, $schema);
        $this->factory->setConfig($initialCheckMode);
        $this->addErrors(array_unique($validator->getErrors(), \SORT_REGULAR));
        return $validator->getErrorMask();
    }
    /**
     * Alias to validate(), to maintain backwards-compatibility with the previous API
     *
     * @deprecated since 6.0.0, use Validator::validate() instead, to be removed in 7.0
     *
     * @param mixed $value
     * @param mixed $schema
     *
     * @phpstan-return int-mask-of<Validator::ERROR_*>
     */
    public function check($value, $schema): int
    {
        return $this->validate($value, $schema);
    }
    /**
     * Alias to validate(), to maintain backwards-compatibility with the previous API
     *
     * @deprecated since 6.0.0, use Validator::validate() instead, to be removed in 7.0
     *
     * @param mixed $value
     * @param mixed $schema
     *
     * @phpstan-return int-mask-of<Validator::ERROR_*>
     */
    public function coerce(&$value, $schema): int
    {
        return $this->validate($value, $schema, Constraint::CHECK_MODE_COERCE_TYPES);
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of the JsonSchema package.
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\JsonSchema;

/**
 * @package JsonSchema
 */
interface UriRetrieverInterface
{
    /**
     * Retrieve a URI
     *
     * @param string      $uri     JSON Schema URI
     * @param null|string $baseUri
     *
     * @return object JSON Schema contents
     */
    public function retrieve($uri, $baseUri = null);
}
<?php

declare (strict_types=1);
namespace _ContaoManager\JsonSchema\Constraints;

use _ContaoManager\JsonSchema\ConstraintError;
use _ContaoManager\JsonSchema\Entity\JsonPointer;
class ObjectConstraint extends Constraint
{
    /**
     * @var list<string> List of properties to which a default value has been applied
     */
    protected $appliedDefaults = [];
    /**
     * {@inheritdoc}
     *
     * @param list<string> $appliedDefaults
     */
    public function check(&$element, $schema = null, ?JsonPointer $path = null, $properties = null, $additionalProp = null, $patternProperties = null, $appliedDefaults = []): void
    {
        if ($element instanceof UndefinedConstraint) {
            return;
        }
        $this->appliedDefaults = $appliedDefaults;
        $matches = [];
        if ($patternProperties) {
            // validate the element pattern properties
            $matches = $this->validatePatternProperties($element, $path, $patternProperties);
        }
        if ($properties) {
            // validate the element properties
            $this->validateProperties($element, $properties, $path);
        }
        // validate additional element properties & constraints
        $this->validateElement($element, $matches, $schema, $path, $properties, $additionalProp);
    }
    public function validatePatternProperties($element, ?JsonPointer $path, $patternProperties)
    {
        $matches = [];
        foreach ($patternProperties as $pregex => $schema) {
            $fullRegex = self::jsonPatternToPhpRegex($pregex);
            // Validate the pattern before using it to test for matches
            if (@preg_match($fullRegex, '') === \false) {
                $this->addError(ConstraintError::PREGEX_INVALID(), $path, ['pregex' => $pregex]);
                continue;
            }
            foreach ($element as $i => $value) {
                if (preg_match($fullRegex, (string) $i)) {
                    $matches[] = $i;
                    $this->checkUndefined($value, $schema ?: new \stdClass(), $path, $i, in_array($i, $this->appliedDefaults));
                }
            }
        }
        return $matches;
    }
    /**
     * Validates the element properties
     *
     * @param \StdClass        $element        Element to validate
     * @param array            $matches        Matches from patternProperties (if any)
     * @param \StdClass        $schema         ObjectConstraint definition
     * @param JsonPointer|null $path           Current test path
     * @param \StdClass        $properties     Properties
     * @param mixed            $additionalProp Additional properties
     */
    public function validateElement($element, $matches, $schema = null, ?JsonPointer $path = null, $properties = null, $additionalProp = null)
    {
        $this->validateMinMaxConstraint($element, $schema, $path);
        foreach ($element as $i => $value) {
            $definition = $this->getProperty($properties, $i);
            // no additional properties allowed
            if (!in_array($i, $matches) && $additionalProp === \false && $this->inlineSchemaProperty !== $i && !$definition) {
                $this->addError(ConstraintError::ADDITIONAL_PROPERTIES(), $path, ['property' => $i]);
            }
            // additional properties defined
            if (!in_array($i, $matches) && $additionalProp && !$definition) {
                if ($additionalProp === \true) {
                    $this->checkUndefined($value, null, $path, $i, in_array($i, $this->appliedDefaults));
                } else {
                    $this->checkUndefined($value, $additionalProp, $path, $i, in_array($i, $this->appliedDefaults));
                }
            }
            // property requires presence of another
            $require = $this->getProperty($definition, 'requires');
            if ($require && !$this->getProperty($element, $require)) {
                $this->addError(ConstraintError::REQUIRES(), $path, ['property' => $i, 'requiredProperty' => $require]);
            }
            $property = $this->getProperty($element, $i, $this->factory->createInstanceFor('undefined'));
            if (is_object($property)) {
                $this->validateMinMaxConstraint(!$property instanceof UndefinedConstraint ? $property : $element, $definition, $path);
            }
        }
    }
    /**
     * Validates the definition properties
     *
     * @param \stdClass        $element    Element to validate
     * @param \stdClass        $properties Property definitions
     * @param JsonPointer|null $path       Path?
     */
    public function validateProperties(&$element, $properties = null, ?JsonPointer $path = null)
    {
        $undefinedConstraint = $this->factory->createInstanceFor('undefined');
        foreach ($properties as $i => $value) {
            $property =& $this->getProperty($element, $i, $undefinedConstraint);
            $definition = $this->getProperty($properties, $i);
            if (is_object($definition)) {
                // Undefined constraint will check for is_object() and quit if is not - so why pass it?
                $this->checkUndefined($property, $definition, $path, $i, in_array($i, $this->appliedDefaults));
            }
        }
    }
    /**
     * retrieves a property from an object or array
     *
     * @param mixed  $element  Element to validate
     * @param string $property Property to retrieve
     * @param mixed  $fallback Default value if property is not found
     *
     * @return mixed
     */
    protected function &getProperty(&$element, $property, $fallback = null)
    {
        if (is_array($element) && (isset($element[$property]) || array_key_exists($property, $element))) {
            return $element[$property];
        } elseif (is_object($element) && property_exists($element, (string) $property)) {
            return $element->{$property};
        }
        return $fallback;
    }
    /**
     * validating minimum and maximum property constraints (if present) against an element
     *
     * @param \stdClass        $element          Element to validate
     * @param \stdClass        $objectDefinition ObjectConstraint definition
     * @param JsonPointer|null $path             Path to test?
     */
    protected function validateMinMaxConstraint($element, $objectDefinition, ?JsonPointer $path = null)
    {
        if (!$this->getTypeCheck()::isObject($element)) {
            return;
        }
        // Verify minimum number of properties
        if (isset($objectDefinition->minProperties) && is_int($objectDefinition->minProperties)) {
            if ($this->getTypeCheck()->propertyCount($element) < max(0, $objectDefinition->minProperties)) {
                $this->addError(ConstraintError::PROPERTIES_MIN(), $path, ['minProperties' => $objectDefinition->minProperties]);
            }
        }
        // Verify maximum number of properties
        if (isset($objectDefinition->maxProperties) && is_int($objectDefinition->maxProperties)) {
            if ($this->getTypeCheck()->propertyCount($element) > max(0, $objectDefinition->maxProperties)) {
                $this->addError(ConstraintError::PROPERTIES_MAX(), $path, ['maxProperties' => $objectDefinition->maxProperties]);
            }
        }
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of the JsonSchema package.
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\JsonSchema\Constraints;

use _ContaoManager\JsonSchema\DraftIdentifiers;
use _ContaoManager\JsonSchema\Exception\InvalidArgumentException;
use _ContaoManager\JsonSchema\SchemaStorage;
use _ContaoManager\JsonSchema\SchemaStorageInterface;
use _ContaoManager\JsonSchema\Uri\UriRetriever;
use _ContaoManager\JsonSchema\UriRetrieverInterface;
use _ContaoManager\JsonSchema\Validator;
/**
 * Factory for centralize constraint initialization.
 */
class Factory
{
    /**
     * @var SchemaStorageInterface
     */
    protected $schemaStorage;
    /**
     * @var UriRetriever
     */
    protected $uriRetriever;
    /**
     * @var int
     * @phpstan-var int-mask-of<Constraint::CHECK_MODE_*>
     */
    private $checkMode = Constraint::CHECK_MODE_NORMAL;
    /**
     * @var array<int, TypeCheck\TypeCheckInterface>
     * @phpstan-var array<int-mask-of<Constraint::CHECK_MODE_*>, TypeCheck\TypeCheckInterface>
     */
    private $typeCheck = [];
    /**
     * @var int-mask-of<Validator::ERROR_*> Validation context
     */
    protected $errorContext = Validator::ERROR_DOCUMENT_VALIDATION;
    /**
     * The default dialect used for strict mode (Constraint::CHECK_MODE_STRICT) when the schema is without a schema property
     *
     * @var string
     */
    private $defaultDialect = DraftIdentifiers::DRAFT_6;
    /**
     * @var array
     */
    protected $constraintMap = ['array' => '_ContaoManager\JsonSchema\Constraints\CollectionConstraint', 'collection' => '_ContaoManager\JsonSchema\Constraints\CollectionConstraint', 'object' => '_ContaoManager\JsonSchema\Constraints\ObjectConstraint', 'type' => '_ContaoManager\JsonSchema\Constraints\TypeConstraint', 'undefined' => '_ContaoManager\JsonSchema\Constraints\UndefinedConstraint', 'string' => '_ContaoManager\JsonSchema\Constraints\StringConstraint', 'number' => '_ContaoManager\JsonSchema\Constraints\NumberConstraint', 'enum' => '_ContaoManager\JsonSchema\Constraints\EnumConstraint', 'const' => '_ContaoManager\JsonSchema\Constraints\ConstConstraint', 'format' => '_ContaoManager\JsonSchema\Constraints\FormatConstraint', 'schema' => '_ContaoManager\JsonSchema\Constraints\SchemaConstraint', 'validator' => '_ContaoManager\JsonSchema\Validator', 'draft06' => Drafts\Draft06\Draft06Constraint::class, 'draft07' => Drafts\Draft07\Draft07Constraint::class];
    /**
     * @var array<ConstraintInterface>
     */
    private $instanceCache = [];
    /**
     * @phpstan-param int-mask-of<Constraint::CHECK_MODE_*> $checkMode
     */
    public function __construct(?SchemaStorageInterface $schemaStorage = null, ?UriRetrieverInterface $uriRetriever = null, int $checkMode = Constraint::CHECK_MODE_NORMAL)
    {
        // set provided config options
        $this->setConfig($checkMode);
        $this->uriRetriever = $uriRetriever ?: new UriRetriever();
        $this->schemaStorage = $schemaStorage ?: new SchemaStorage($this->uriRetriever);
    }
    /**
     * Set config values
     *
     * @param int $checkMode Set checkMode options - does not preserve existing flags
     * @phpstan-param int-mask-of<Constraint::CHECK_MODE_*> $checkMode
     */
    public function setConfig(int $checkMode = Constraint::CHECK_MODE_NORMAL): void
    {
        $this->checkMode = $checkMode;
    }
    /**
     * Enable checkMode flags
     *
     * @phpstan-param int-mask-of<Constraint::CHECK_MODE_*> $options
     */
    public function addConfig(int $options): void
    {
        $this->checkMode |= $options;
    }
    /**
     * Disable checkMode flags
     *
     * @phpstan-param int-mask-of<Constraint::CHECK_MODE_*> $options
     */
    public function removeConfig(int $options): void
    {
        $this->checkMode &= ~$options;
    }
    /**
     * Get checkMode option
     *
     * @param int|null $options Options to get, if null then return entire bitmask
     * @phpstan-param int-mask-of<Constraint::CHECK_MODE_*>|null $options Options to get, if null then return entire bitmask
     *
     * @phpstan-return int-mask-of<Constraint::CHECK_MODE_*>
     */
    public function getConfig(?int $options = null): int
    {
        if ($options === null) {
            return $this->checkMode;
        }
        return $this->checkMode & $options;
    }
    public function getUriRetriever(): UriRetrieverInterface
    {
        return $this->uriRetriever;
    }
    public function getSchemaStorage(): SchemaStorageInterface
    {
        return $this->schemaStorage;
    }
    public function getTypeCheck(): TypeCheck\TypeCheckInterface
    {
        if (!isset($this->typeCheck[$this->checkMode])) {
            $this->typeCheck[$this->checkMode] = $this->checkMode & Constraint::CHECK_MODE_TYPE_CAST ? new TypeCheck\LooseTypeCheck() : new TypeCheck\StrictTypeCheck();
        }
        return $this->typeCheck[$this->checkMode];
    }
    public function setConstraintClass(string $name, string $class): Factory
    {
        // Ensure class exists
        if (!class_exists($class)) {
            throw new InvalidArgumentException('Unknown constraint ' . $name);
        }
        // Ensure class is appropriate
        if (!in_array('_ContaoManager\JsonSchema\Constraints\ConstraintInterface', class_implements($class))) {
            throw new InvalidArgumentException('Invalid class ' . $name);
        }
        $this->constraintMap[$name] = $class;
        return $this;
    }
    /**
     * Create a constraint instance for the given constraint name.
     *
     * @param string $constraintName
     *
     * @throws InvalidArgumentException if is not possible create the constraint instance
     *
     * @return ConstraintInterface&BaseConstraint
     * @phpstan-return ConstraintInterface&BaseConstraint
     */
    public function createInstanceFor($constraintName)
    {
        if (!isset($this->constraintMap[$constraintName])) {
            throw new InvalidArgumentException('Unknown constraint ' . $constraintName);
        }
        if (!isset($this->instanceCache[$constraintName])) {
            $this->instanceCache[$constraintName] = new $this->constraintMap[$constraintName]($this);
        }
        return clone $this->instanceCache[$constraintName];
    }
    /**
     * Get the error context
     *
     * @return int-mask-of<Validator::ERROR_*>
     */
    public function getErrorContext(): int
    {
        return $this->errorContext;
    }
    /**
     * Set the error context
     *
     * @param int-mask-of<Validator::ERROR_*> $errorContext
     */
    public function setErrorContext(int $errorContext): void
    {
        $this->errorContext = $errorContext;
    }
    public function getDefaultDialect(): string
    {
        return $this->defaultDialect;
    }
    public function setDefaultDialect(string $defaultDialect): void
    {
        $this->defaultDialect = $defaultDialect;
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of the JsonSchema package.
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\JsonSchema\Constraints;

use _ContaoManager\JsonSchema\ConstraintError;
use _ContaoManager\JsonSchema\Entity\JsonPointer;
use _ContaoManager\JsonSchema\Tool\DeepComparer;
/**
 * The ConstConstraint Constraints, validates an element against a constant value
 *
 * @author Martin Helmich <martin@helmich.me>
 */
class ConstConstraint extends Constraint
{
    /**
     * {@inheritdoc}
     */
    public function check(&$element, $schema = null, ?JsonPointer $path = null, $i = null): void
    {
        // Only validate const if the attribute exists
        if ($element instanceof UndefinedConstraint && (!isset($schema->required) || !$schema->required)) {
            return;
        }
        $const = $schema->const;
        $type = gettype($element);
        $constType = gettype($const);
        if ($this->factory->getConfig(self::CHECK_MODE_TYPE_CAST) && $type === 'array' && $constType === 'object') {
            if (DeepComparer::isEqual((object) $element, $const)) {
                return;
            }
        }
        if (DeepComparer::isEqual($element, $const)) {
            return;
        }
        $this->addError(ConstraintError::CONSTANT(), $path, ['const' => $schema->const]);
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of the JsonSchema package.
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\JsonSchema\Constraints;

use _ContaoManager\JsonSchema\ConstraintError;
use _ContaoManager\JsonSchema\Entity\JsonPointer;
/**
 * The NumberConstraint Constraints, validates an number against a given schema
 *
 * @author Robert Schönthal <seroscho@googlemail.com>
 * @author Bruno Prieto Reis <bruno.p.reis@gmail.com>
 */
class NumberConstraint extends Constraint
{
    /**
     * {@inheritdoc}
     */
    public function check(&$element, $schema = null, ?JsonPointer $path = null, $i = null): void
    {
        // Verify minimum
        if (isset($schema->exclusiveMinimum)) {
            if (isset($schema->minimum)) {
                if ($schema->exclusiveMinimum && $element <= $schema->minimum) {
                    $this->addError(ConstraintError::EXCLUSIVE_MINIMUM(), $path, ['minimum' => $schema->minimum]);
                } elseif ($element < $schema->minimum) {
                    $this->addError(ConstraintError::MINIMUM(), $path, ['minimum' => $schema->minimum]);
                }
            } else {
                $this->addError(ConstraintError::MISSING_MINIMUM(), $path);
            }
        } elseif (isset($schema->minimum) && $element < $schema->minimum) {
            $this->addError(ConstraintError::MINIMUM(), $path, ['minimum' => $schema->minimum]);
        }
        // Verify maximum
        if (isset($schema->exclusiveMaximum)) {
            if (isset($schema->maximum)) {
                if ($schema->exclusiveMaximum && $element >= $schema->maximum) {
                    $this->addError(ConstraintError::EXCLUSIVE_MAXIMUM(), $path, ['maximum' => $schema->maximum]);
                } elseif ($element > $schema->maximum) {
                    $this->addError(ConstraintError::MAXIMUM(), $path, ['maximum' => $schema->maximum]);
                }
            } else {
                $this->addError(ConstraintError::MISSING_MAXIMUM(), $path);
            }
        } elseif (isset($schema->maximum) && $element > $schema->maximum) {
            $this->addError(ConstraintError::MAXIMUM(), $path, ['maximum' => $schema->maximum]);
        }
        // Verify divisibleBy - Draft v3
        if (isset($schema->divisibleBy) && $this->fmod($element, $schema->divisibleBy) != 0) {
            $this->addError(ConstraintError::DIVISIBLE_BY(), $path, ['divisibleBy' => $schema->divisibleBy]);
        }
        // Verify multipleOf - Draft v4
        if (isset($schema->multipleOf) && $this->fmod($element, $schema->multipleOf) != 0) {
            $this->addError(ConstraintError::MULTIPLE_OF(), $path, ['multipleOf' => $schema->multipleOf]);
        }
        $this->checkFormat($element, $schema, $path, $i);
    }
    private function fmod($number1, $number2)
    {
        $modulus = $number1 - round($number1 / $number2) * $number2;
        $precision = 1.0E-10;
        if (-$precision < $modulus && $modulus < $precision) {
            return 0.0;
        }
        return $modulus;
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of the JsonSchema package.
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\JsonSchema\Constraints;

use _ContaoManager\JsonSchema\ConstraintError;
use _ContaoManager\JsonSchema\Entity\JsonPointer;
use _ContaoManager\JsonSchema\Exception\InvalidArgumentException;
use UnexpectedValueException as StandardUnexpectedValueException;
/**
 * The TypeConstraint Constraints, validates an element against a given type
 *
 * @author Robert Schönthal <seroscho@googlemail.com>
 * @author Bruno Prieto Reis <bruno.p.reis@gmail.com>
 */
class TypeConstraint extends Constraint
{
    /**
     * @var array|string[] type wordings for validation error messages
     */
    public static $wording = [
        'integer' => 'an integer',
        'number' => 'a number',
        'boolean' => 'a boolean',
        'object' => 'an object',
        'array' => 'an array',
        'string' => 'a string',
        'null' => 'a null',
        'any' => null,
        // validation of 'any' is always true so is not needed in message wording
        0 => null,
    ];
    /**
     * {@inheritdoc}
     */
    public function check(&$value = null, $schema = null, ?JsonPointer $path = null, $i = null): void
    {
        $type = isset($schema->type) ? $schema->type : null;
        $isValid = \false;
        $coerce = $this->factory->getConfig(self::CHECK_MODE_COERCE_TYPES);
        $earlyCoerce = $this->factory->getConfig(self::CHECK_MODE_EARLY_COERCE);
        $wording = [];
        if (is_array($type)) {
            $this->validateTypesArray($value, $type, $wording, $isValid, $path, $coerce && $earlyCoerce);
            if (!$isValid && $coerce && !$earlyCoerce) {
                $this->validateTypesArray($value, $type, $wording, $isValid, $path, \true);
            }
        } elseif (is_object($type)) {
            $this->checkUndefined($value, $type, $path);
            return;
        } else {
            $isValid = $this->validateType($value, $type, $coerce && $earlyCoerce);
            if (!$isValid && $coerce && !$earlyCoerce) {
                $isValid = $this->validateType($value, $type, \true);
            }
        }
        if ($isValid === \false) {
            if (!is_array($type)) {
                $this->validateTypeNameWording($type);
                $wording[] = self::$wording[$type];
            }
            $this->addError(ConstraintError::TYPE(), $path, ['found' => gettype($value), 'expected' => $this->implodeWith($wording, ', ', 'or')]);
        }
    }
    /**
     * Validates the given $value against the array of types in $type. Sets the value
     * of $isValid to true, if at least one $type mateches the type of $value or the value
     * passed as $isValid is already true.
     *
     * @param mixed        $value             Value to validate
     * @param array        $type              TypeConstraints to check against
     * @param array        $validTypesWording An array of wordings of the valid types of the array $type
     * @param bool         $isValid           The current validation value
     * @param ?JsonPointer $path
     * @param bool         $coerce
     */
    protected function validateTypesArray(&$value, array $type, &$validTypesWording, &$isValid, $path, $coerce = \false)
    {
        foreach ($type as $tp) {
            // already valid, so no need to waste cycles looping over everything
            if ($isValid) {
                return;
            }
            // $tp can be an object, if it's a schema instead of a simple type, validate it
            // with a new type constraint
            if (is_object($tp)) {
                if (!$isValid) {
                    $validator = $this->factory->createInstanceFor('type');
                    $subSchema = new \stdClass();
                    $subSchema->type = $tp;
                    $validator->check($value, $subSchema, $path, null);
                    $error = $validator->getErrors();
                    $isValid = !(bool) $error;
                    $validTypesWording[] = self::$wording['object'];
                }
            } else {
                $this->validateTypeNameWording($tp);
                $validTypesWording[] = self::$wording[$tp];
                if (!$isValid) {
                    $isValid = $this->validateType($value, $tp, $coerce);
                }
            }
        }
    }
    /**
     * Implodes the given array like implode() with turned around parameters and with the
     * difference, that, if $listEnd isn't false, the last element delimiter is $listEnd instead of
     * $delimiter.
     *
     * @param array  $elements  The elements to implode
     * @param string $delimiter The delimiter to use
     * @param bool   $listEnd   The last delimiter to use (defaults to $delimiter)
     *
     * @return string
     */
    protected function implodeWith(array $elements, $delimiter = ', ', $listEnd = \false)
    {
        if ($listEnd === \false || !isset($elements[1])) {
            return implode($delimiter, $elements);
        }
        $lastElement = array_slice($elements, -1);
        $firsElements = join($delimiter, array_slice($elements, 0, -1));
        $implodedElements = array_merge([$firsElements], $lastElement);
        return join(" {$listEnd} ", $implodedElements);
    }
    /**
     * Validates the given $type, if there's an associated self::$wording. If not, throws an
     * exception.
     *
     * @param string $type The type to validate
     *
     * @throws StandardUnexpectedValueException
     */
    protected function validateTypeNameWording($type)
    {
        if (!array_key_exists($type, self::$wording)) {
            throw new StandardUnexpectedValueException(sprintf('No wording for %s available, expected wordings are: [%s]', var_export($type, \true), implode(', ', array_filter(self::$wording))));
        }
    }
    /**
     * Verifies that a given value is of a certain type
     *
     * @param mixed  $value Value to validate
     * @param string $type  TypeConstraint to check against
     *
     * @throws InvalidArgumentException
     *
     * @return bool
     */
    protected function validateType(&$value, $type, $coerce = \false)
    {
        //mostly the case for inline schema
        if (!$type) {
            return \true;
        }
        if ('any' === $type) {
            return \true;
        }
        if ('object' === $type) {
            return $this->getTypeCheck()->isObject($value);
        }
        if ('array' === $type) {
            if ($coerce) {
                $value = $this->toArray($value);
            }
            return $this->getTypeCheck()->isArray($value);
        }
        if ('integer' === $type) {
            if ($coerce) {
                $value = $this->toInteger($value);
            }
            return is_int($value);
        }
        if ('number' === $type) {
            if ($coerce) {
                $value = $this->toNumber($value);
            }
            return is_numeric($value) && !is_string($value);
        }
        if ('boolean' === $type) {
            if ($coerce) {
                $value = $this->toBoolean($value);
            }
            return is_bool($value);
        }
        if ('string' === $type) {
            if ($coerce) {
                $value = $this->toString($value);
            }
            return is_string($value);
        }
        if ('null' === $type) {
            if ($coerce) {
                $value = $this->toNull($value);
            }
            return is_null($value);
        }
        throw new InvalidArgumentException((is_object($value) ? 'object' : $value) . ' is an invalid type for ' . $type);
    }
    /**
     * Converts a value to boolean. For example, "true" becomes true.
     *
     * @param mixed $value The value to convert to boolean
     *
     * @return bool|mixed
     */
    protected function toBoolean($value)
    {
        if ($value === 1 || $value === 'true') {
            return \true;
        }
        if (is_null($value) || $value === 0 || $value === 'false') {
            return \false;
        }
        if ($this->getTypeCheck()->isArray($value) && count($value) === 1) {
            return $this->toBoolean(reset($value));
        }
        return $value;
    }
    /**
     * Converts a value to a number. For example, "4.5" becomes 4.5.
     *
     * @param mixed $value the value to convert to a number
     *
     * @return int|float|mixed
     */
    protected function toNumber($value)
    {
        if (is_numeric($value)) {
            return $value + 0;
            // cast to number
        }
        if (is_bool($value) || is_null($value)) {
            return (int) $value;
        }
        if ($this->getTypeCheck()->isArray($value) && count($value) === 1) {
            return $this->toNumber(reset($value));
        }
        return $value;
    }
    /**
     * Converts a value to an integer. For example, "4" becomes 4.
     *
     * @param mixed $value
     *
     * @return int|mixed
     */
    protected function toInteger($value)
    {
        $numberValue = $this->toNumber($value);
        if (is_numeric($numberValue) && (int) $numberValue == $numberValue) {
            return (int) $numberValue;
            // cast to number
        }
        return $value;
    }
    /**
     * Converts a value to an array containing that value. For example, [4] becomes 4.
     *
     * @param mixed $value
     *
     * @return array|mixed
     */
    protected function toArray($value)
    {
        if (is_scalar($value) || is_null($value)) {
            return [$value];
        }
        return $value;
    }
    /**
     * Convert a value to a string representation of that value. For example, null becomes "".
     *
     * @param mixed $value
     *
     * @return string|mixed
     */
    protected function toString($value)
    {
        if (is_numeric($value)) {
            return "{$value}";
        }
        if ($value === \true) {
            return 'true';
        }
        if ($value === \false) {
            return 'false';
        }
        if (is_null($value)) {
            return '';
        }
        if ($this->getTypeCheck()->isArray($value) && count($value) === 1) {
            return $this->toString(reset($value));
        }
        return $value;
    }
    /**
     * Convert a value to a null. For example, 0 becomes null.
     *
     * @param mixed $value
     *
     * @return null|mixed
     */
    protected function toNull($value)
    {
        if ($value === 0 || $value === \false || $value === '') {
            return null;
        }
        if ($this->getTypeCheck()->isArray($value) && count($value) === 1) {
            return $this->toNull(reset($value));
        }
        return $value;
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\JsonSchema\Constraints;

use const JSON_ERROR_NONE;
use _ContaoManager\JsonSchema\ConstraintError;
use _ContaoManager\JsonSchema\Entity\JsonPointer;
use _ContaoManager\JsonSchema\Exception\InvalidArgumentException;
use _ContaoManager\JsonSchema\Exception\ValidationException;
use _ContaoManager\JsonSchema\Validator;
/**
 * A more basic constraint definition - used for the public
 * interface to avoid exposing library internals.
 */
class BaseConstraint
{
    /**
     * @var array Errors
     */
    protected $errors = [];
    /**
     * @var int All error types which have occurred
     * @phpstan-var int-mask-of<Validator::ERROR_*>
     */
    protected $errorMask = Validator::ERROR_NONE;
    /**
     * @var Factory
     */
    protected $factory;
    public function __construct(?Factory $factory = null)
    {
        $this->factory = $factory ?: new Factory();
    }
    public function addError(ConstraintError $constraint, ?JsonPointer $path = null, array $more = []): void
    {
        $message = $constraint->getMessage();
        $name = $constraint->getValue();
        $error = ['property' => $this->convertJsonPointerIntoPropertyPath($path ?: new JsonPointer('')), 'pointer' => ltrim((string) ($path ?: new JsonPointer('')), '#'), 'message' => ucfirst(vsprintf($message, array_map(static function ($val) {
            if (is_scalar($val)) {
                return is_bool($val) ? var_export($val, \true) : $val;
            }
            return json_encode($val);
        }, array_values($more)))), 'constraint' => ['name' => $name, 'params' => $more], 'context' => $this->factory->getErrorContext()];
        if ($this->factory->getConfig(Constraint::CHECK_MODE_EXCEPTIONS)) {
            throw new ValidationException(sprintf('Error validating %s: %s', $error['pointer'], $error['message']));
        }
        $this->errors[] = $error;
        $this->errorMask |= $error['context'];
    }
    public function addErrors(array $errors): void
    {
        if ($errors) {
            $this->errors = array_merge($this->errors, $errors);
            $errorMask =& $this->errorMask;
            array_walk($errors, static function ($error) use (&$errorMask) {
                if (isset($error['context'])) {
                    $errorMask |= $error['context'];
                }
            });
        }
    }
    /**
     * @phpstan-param int-mask-of<Validator::ERROR_*> $errorContext
     */
    public function getErrors(int $errorContext = Validator::ERROR_ALL): array
    {
        if ($errorContext === Validator::ERROR_ALL) {
            return $this->errors;
        }
        return array_filter($this->errors, static function ($error) use ($errorContext) {
            return (bool) ($errorContext & $error['context']);
        });
    }
    /**
     * @phpstan-param int-mask-of<Validator::ERROR_*> $errorContext
     */
    public function numErrors(int $errorContext = Validator::ERROR_ALL): int
    {
        if ($errorContext === Validator::ERROR_ALL) {
            return count($this->errors);
        }
        return count($this->getErrors($errorContext));
    }
    public function isValid(): bool
    {
        return !$this->getErrors();
    }
    /**
     * Clears any reported errors. Should be used between
     * multiple validation checks.
     */
    public function reset(): void
    {
        $this->errors = [];
        $this->errorMask = Validator::ERROR_NONE;
    }
    /**
     * Get the error mask
     *
     * @phpstan-return int-mask-of<Validator::ERROR_*>
     */
    public function getErrorMask(): int
    {
        return $this->errorMask;
    }
    /**
     * Recursively cast an associative array to an object
     */
    public static function arrayToObjectRecursive(array $array): object
    {
        $json = json_encode($array);
        if (json_last_error() !== JSON_ERROR_NONE) {
            $message = 'Unable to encode schema array as JSON';
            if (function_exists('json_last_error_msg')) {
                $message .= ': ' . json_last_error_msg();
            }
            throw new InvalidArgumentException($message);
        }
        return (object) json_decode($json, \false);
    }
    /**
     * Transform a JSON pattern into a PCRE regex
     */
    public static function jsonPatternToPhpRegex(string $pattern): string
    {
        return '~' . str_replace('~', '\~', $pattern) . '~u';
    }
    protected function convertJsonPointerIntoPropertyPath(JsonPointer $pointer): string
    {
        $result = array_map(static function ($path) {
            return sprintf(is_numeric($path) ? '[%d]' : '.%s', $path);
        }, $pointer->getPropertyPaths());
        return trim(implode('', $result), '.');
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of the JsonSchema package.
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\JsonSchema\Constraints;

use _ContaoManager\JsonSchema\ConstraintError;
use _ContaoManager\JsonSchema\Entity\JsonPointer;
use _ContaoManager\JsonSchema\Tool\DeepComparer;
/**
 * The EnumConstraint Constraints, validates an element against a given set of possibilities
 *
 * @author Robert Schönthal <seroscho@googlemail.com>
 * @author Bruno Prieto Reis <bruno.p.reis@gmail.com>
 */
class EnumConstraint extends Constraint
{
    /**
     * {@inheritdoc}
     */
    public function check(&$element, $schema = null, ?JsonPointer $path = null, $i = null): void
    {
        // Only validate enum if the attribute exists
        if ($element instanceof UndefinedConstraint && (!isset($schema->required) || !$schema->required)) {
            return;
        }
        $type = gettype($element);
        foreach ($schema->enum as $enum) {
            $enumType = gettype($enum);
            if ($enumType === 'object' && $type === 'array' && $this->factory->getConfig(self::CHECK_MODE_TYPE_CAST) && DeepComparer::isEqual((object) $element, $enum)) {
                return;
            }
            if ($type === $enumType && DeepComparer::isEqual($element, $enum)) {
                return;
            }
            if (is_numeric($element) && is_numeric($enum) && DeepComparer::isEqual((float) $element, (float) $enum)) {
                return;
            }
        }
        $this->addError(ConstraintError::ENUM(), $path, ['enum' => $schema->enum]);
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of the JsonSchema package.
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\JsonSchema\Constraints;

use _ContaoManager\JsonSchema\ConstraintError;
use _ContaoManager\JsonSchema\Entity\JsonPointer;
/**
 * The StringConstraint Constraints, validates an string against a given schema
 *
 * @author Robert Schönthal <seroscho@googlemail.com>
 * @author Bruno Prieto Reis <bruno.p.reis@gmail.com>
 */
class StringConstraint extends Constraint
{
    /**
     * {@inheritdoc}
     */
    public function check(&$element, $schema = null, ?JsonPointer $path = null, $i = null): void
    {
        // Verify maxLength
        if (isset($schema->maxLength) && $this->strlen($element) > $schema->maxLength) {
            $this->addError(ConstraintError::LENGTH_MAX(), $path, ['maxLength' => $schema->maxLength]);
        }
        //verify minLength
        if (isset($schema->minLength) && $this->strlen($element) < $schema->minLength) {
            $this->addError(ConstraintError::LENGTH_MIN(), $path, ['minLength' => $schema->minLength]);
        }
        // Verify a regex pattern
        if (isset($schema->pattern) && !preg_match(self::jsonPatternToPhpRegex($schema->pattern), $element)) {
            $this->addError(ConstraintError::PATTERN(), $path, ['pattern' => $schema->pattern]);
        }
        $this->checkFormat($element, $schema, $path, $i);
    }
    private function strlen($string)
    {
        if (extension_loaded('mbstring')) {
            return mb_strlen($string, mb_detect_encoding($string));
        }
        // mbstring is present on all test platforms, so strlen() can be ignored for coverage
        return strlen($string);
        // @codeCoverageIgnore
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\JsonSchema\Constraints\Drafts\Draft07;

class Factory extends \_ContaoManager\JsonSchema\Constraints\Factory
{
    /**
     * @var array<string, class-string>
     */
    protected $constraintMap = ['schema' => Draft07Constraint::class, 'additionalProperties' => AdditionalPropertiesConstraint::class, 'additionalItems' => AdditionalItemsConstraint::class, 'dependencies' => DependenciesConstraint::class, 'type' => TypeConstraint::class, 'const' => ConstConstraint::class, 'enum' => EnumConstraint::class, 'uniqueItems' => UniqueItemsConstraint::class, 'minItems' => MinItemsConstraint::class, 'minProperties' => MinPropertiesConstraint::class, 'maxProperties' => MaxPropertiesConstraint::class, 'minimum' => MinimumConstraint::class, 'maximum' => MaximumConstraint::class, 'exclusiveMinimum' => ExclusiveMinimumConstraint::class, 'minLength' => MinLengthConstraint::class, 'maxLength' => MaxLengthConstraint::class, 'maxItems' => MaxItemsConstraint::class, 'exclusiveMaximum' => ExclusiveMaximumConstraint::class, 'multipleOf' => MultipleOfConstraint::class, 'required' => RequiredConstraint::class, 'format' => FormatConstraint::class, 'anyOf' => AnyOfConstraint::class, 'allOf' => AllOfConstraint::class, 'oneOf' => OneOfConstraint::class, 'not' => NotConstraint::class, 'ifThenElse' => IfThenElseConstraint::class, 'contains' => ContainsConstraint::class, 'propertyNames' => PropertiesNamesConstraint::class, 'patternProperties' => PatternPropertiesConstraint::class, 'pattern' => PatternConstraint::class, 'properties' => PropertiesConstraint::class, 'items' => ItemsConstraint::class, 'ref' => RefConstraint::class, 'content' => ContentConstraint::class];
}
<?php

declare (strict_types=1);
namespace _ContaoManager\JsonSchema\Constraints\Drafts\Draft07;

use _ContaoManager\JsonSchema\ConstraintError;
use _ContaoManager\JsonSchema\Constraints\ConstraintInterface;
use _ContaoManager\JsonSchema\Constraints\Factory;
use _ContaoManager\JsonSchema\Entity\ErrorBagProxy;
use _ContaoManager\JsonSchema\Entity\JsonPointer;
class ExclusiveMinimumConstraint implements ConstraintInterface
{
    use ErrorBagProxy;
    public function __construct(?Factory $factory = null)
    {
        $this->initialiseErrorBag($factory ?: new Factory());
    }
    public function check(&$value, $schema = null, ?JsonPointer $path = null, $i = null): void
    {
        if (!property_exists($schema, 'exclusiveMinimum')) {
            return;
        }
        if (!is_numeric($value)) {
            return;
        }
        if ($value > $schema->exclusiveMinimum) {
            return;
        }
        $this->addError(ConstraintError::EXCLUSIVE_MINIMUM(), $path, ['exclusiveMinimum' => $schema->exclusiveMinimum, 'found' => $value]);
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\JsonSchema\Constraints\Drafts\Draft07;

use _ContaoManager\JsonSchema\ConstraintError;
use _ContaoManager\JsonSchema\Constraints\ConstraintInterface;
use _ContaoManager\JsonSchema\Entity\ErrorBagProxy;
use _ContaoManager\JsonSchema\Entity\JsonPointer;
class AdditionalItemsConstraint implements ConstraintInterface
{
    use ErrorBagProxy;
    /** @var Factory */
    private $factory;
    public function __construct(?Factory $factory = null)
    {
        $this->factory = $factory ?: new Factory();
        $this->initialiseErrorBag($this->factory);
    }
    public function check(&$value, $schema = null, ?JsonPointer $path = null, $i = null): void
    {
        if (!property_exists($schema, 'additionalItems')) {
            return;
        }
        if ($schema->additionalItems === \true) {
            return;
        }
        if ($schema->additionalItems === \false && !property_exists($schema, 'items')) {
            return;
        }
        if (!is_array($value)) {
            return;
        }
        if (!property_exists($schema, 'items')) {
            return;
        }
        if (property_exists($schema, 'items') && is_object($schema->items)) {
            return;
        }
        $additionalItems = array_diff_key($value, property_exists($schema, 'items') ? $schema->items : []);
        foreach ($additionalItems as $propertyName => $propertyValue) {
            $schemaConstraint = $this->factory->createInstanceFor('schema');
            $schemaConstraint->check($propertyValue, $schema->additionalItems, $path, $i);
            if ($schemaConstraint->isValid()) {
                continue;
            }
            $this->addError(ConstraintError::ADDITIONAL_ITEMS(), $path, ['item' => $i, 'property' => $propertyName, 'additionalItems' => $schema->additionalItems]);
        }
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\JsonSchema\Constraints\Drafts\Draft07;

use _ContaoManager\JsonSchema\ConstraintError;
use _ContaoManager\JsonSchema\Constraints\ConstraintInterface;
use _ContaoManager\JsonSchema\Constraints\Factory;
use _ContaoManager\JsonSchema\Entity\ErrorBagProxy;
use _ContaoManager\JsonSchema\Entity\JsonPointer;
use _ContaoManager\JsonSchema\Tool\DeepComparer;
class ConstConstraint implements ConstraintInterface
{
    use ErrorBagProxy;
    public function __construct(?Factory $factory = null)
    {
        $this->initialiseErrorBag($factory ?: new Factory());
    }
    public function check(&$value, $schema = null, ?JsonPointer $path = null, $i = null): void
    {
        if (!property_exists($schema, 'const')) {
            return;
        }
        if (DeepComparer::isEqual($value, $schema->const)) {
            return;
        }
        $this->addError(ConstraintError::CONSTANT(), $path, ['const' => $schema->const]);
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\JsonSchema\Constraints\Drafts\Draft07;

use _ContaoManager\JsonSchema\ConstraintError;
use _ContaoManager\JsonSchema\Constraints\ConstraintInterface;
use _ContaoManager\JsonSchema\Entity\ErrorBagProxy;
use _ContaoManager\JsonSchema\Entity\JsonPointer;
class AdditionalPropertiesConstraint implements ConstraintInterface
{
    use ErrorBagProxy;
    /** @var Factory */
    private $factory;
    public function __construct(?Factory $factory = null)
    {
        $this->factory = $factory ?: new Factory();
        $this->initialiseErrorBag($this->factory);
    }
    public function check(&$value, $schema = null, ?JsonPointer $path = null, $i = null): void
    {
        if (!property_exists($schema, 'additionalProperties')) {
            return;
        }
        if ($schema->additionalProperties === \true) {
            return;
        }
        if (!is_object($value)) {
            return;
        }
        $additionalProperties = get_object_vars($value);
        if (isset($schema->properties)) {
            $additionalProperties = array_diff_key($additionalProperties, (array) $schema->properties);
        }
        if (isset($schema->patternProperties)) {
            $patterns = array_keys(get_object_vars($schema->patternProperties));
            foreach ($additionalProperties as $key => $_) {
                foreach ($patterns as $pattern) {
                    if (preg_match($this->createPregMatchPattern($pattern), (string) $key)) {
                        unset($additionalProperties[$key]);
                        break;
                    }
                }
            }
        }
        if (is_object($schema->additionalProperties)) {
            foreach ($additionalProperties as $key => $additionalPropertiesValue) {
                $schemaConstraint = $this->factory->createInstanceFor('schema');
                $schemaConstraint->check($additionalPropertiesValue, $schema->additionalProperties, $path, $i);
                // @todo increment path
                if ($schemaConstraint->isValid()) {
                    unset($additionalProperties[$key]);
                }
            }
        }
        foreach ($additionalProperties as $key => $additionalPropertiesValue) {
            $this->addError(ConstraintError::ADDITIONAL_PROPERTIES(), $path, ['found' => $additionalPropertiesValue]);
        }
    }
    private function createPregMatchPattern(string $pattern): string
    {
        $replacements = [
            //            '\D' => '[^0-9]',
            //            '\d' => '[0-9]',
            '\p{digit}' => '\p{Nd}',
            //            '\w' => '[A-Za-z0-9_]',
            //            '\W' => '[^A-Za-z0-9_]',
            //            '\s' => '[\s\x{200B}]' // Explicitly include zero width white space,
            '\p{Letter}' => '\p{L}',
        ];
        $pattern = str_replace(array_keys($replacements), array_values($replacements), $pattern);
        return '/' . str_replace('/', '\/', $pattern) . '/u';
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\JsonSchema\Constraints\Drafts\Draft07;

use _ContaoManager\JsonSchema\ConstraintError;
use _ContaoManager\JsonSchema\Constraints\ConstraintInterface;
use _ContaoManager\JsonSchema\Constraints\Factory;
use _ContaoManager\JsonSchema\Entity\ErrorBagProxy;
use _ContaoManager\JsonSchema\Entity\JsonPointer;
class TypeConstraint implements ConstraintInterface
{
    use ErrorBagProxy;
    public function __construct(?Factory $factory = null)
    {
        $this->initialiseErrorBag($factory ?: new Factory());
    }
    public function check(&$value, $schema = null, ?JsonPointer $path = null, $i = null): void
    {
        if (!property_exists($schema, 'type')) {
            return;
        }
        $schemaTypes = (array) $schema->type;
        $valueType = strtolower(gettype($value));
        // All specific number types are a number
        $valueIsNumber = $valueType === 'double' || $valueType === 'integer';
        // A float with zero fractional part is an integer
        $isInteger = $valueIsNumber && fmod($value, 1.0) === 0.0;
        foreach ($schemaTypes as $type) {
            if ($valueType === $type) {
                return;
            }
            if ($type === 'number' && $valueIsNumber) {
                return;
            }
            if ($type === 'integer' && $isInteger) {
                return;
            }
        }
        $this->addError(ConstraintError::TYPE(), $path, ['found' => $valueType, 'expected' => implode(', ', $schemaTypes)]);
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\JsonSchema\Constraints\Drafts\Draft07;

use _ContaoManager\JsonSchema\ConstraintError;
use _ContaoManager\JsonSchema\Constraints\ConstraintInterface;
use _ContaoManager\JsonSchema\Entity\ErrorBagProxy;
use _ContaoManager\JsonSchema\Entity\JsonPointer;
use _ContaoManager\JsonSchema\Exception\ValidationException;
class AnyOfConstraint implements ConstraintInterface
{
    use ErrorBagProxy;
    /** @var Factory */
    private $factory;
    public function __construct(?Factory $factory = null)
    {
        $this->factory = $factory ?: new Factory();
        $this->initialiseErrorBag($this->factory);
    }
    public function check(&$value, $schema = null, ?JsonPointer $path = null, $i = null): void
    {
        if (!property_exists($schema, 'anyOf')) {
            return;
        }
        foreach ($schema->anyOf as $anyOfSchema) {
            $schemaConstraint = $this->factory->createInstanceFor('schema');
            try {
                $schemaConstraint->check($value, $anyOfSchema, $path, $i);
                if ($schemaConstraint->isValid()) {
                    $this->errorBag()->reset();
                    return;
                }
                $this->addErrors($schemaConstraint->getErrors());
            } catch (ValidationException $e) {
            }
        }
        $this->addError(ConstraintError::ANY_OF(), $path);
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\JsonSchema\Constraints\Drafts\Draft07;

use _ContaoManager\JsonSchema\ConstraintError;
use _ContaoManager\JsonSchema\Constraints\ConstraintInterface;
use _ContaoManager\JsonSchema\Constraints\Factory;
use _ContaoManager\JsonSchema\Entity\ErrorBagProxy;
use _ContaoManager\JsonSchema\Entity\JsonPointer;
class ContentConstraint implements ConstraintInterface
{
    use ErrorBagProxy;
    public function __construct(?Factory $factory = null)
    {
        $this->initialiseErrorBag($factory ?: new Factory());
    }
    public function check(&$value, $schema = null, ?JsonPointer $path = null, $i = null): void
    {
        if (!property_exists($schema, 'contentMediaType') && !property_exists($schema, 'contentEncoding')) {
            return;
        }
        if (!is_string($value)) {
            return;
        }
        $decodedValue = $value;
        if (property_exists($schema, 'contentEncoding')) {
            if ($schema->contentEncoding === 'base64') {
                if (!preg_match('/^[A-Za-z0-9+\/=]+$/', $decodedValue)) {
                    $this->addError(ConstraintError::CONTENT_ENCODING(), $path, ['contentEncoding' => $schema->contentEncoding]);
                    return;
                }
                $decodedValue = base64_decode($decodedValue);
            }
        }
        if (property_exists($schema, 'contentMediaType')) {
            if ($schema->contentMediaType === 'application/json') {
                json_decode($decodedValue, \false);
                if (json_last_error() === \JSON_ERROR_NONE) {
                    return;
                }
            }
            $this->addError(ConstraintError::CONTENT_MEDIA_TYPE(), $path, ['contentMediaType' => $schema->contentMediaType]);
        }
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\JsonSchema\Constraints\Drafts\Draft07;

use _ContaoManager\JsonSchema\ConstraintError;
use _ContaoManager\JsonSchema\Constraints\ConstraintInterface;
use _ContaoManager\JsonSchema\Constraints\Factory;
use _ContaoManager\JsonSchema\Entity\ErrorBagProxy;
use _ContaoManager\JsonSchema\Entity\JsonPointer;
use _ContaoManager\JsonSchema\Tool\DeepComparer;
class EnumConstraint implements ConstraintInterface
{
    use ErrorBagProxy;
    public function __construct(?Factory $factory = null)
    {
        $this->initialiseErrorBag($factory ?: new Factory());
    }
    public function check(&$value, $schema = null, ?JsonPointer $path = null, $i = null): void
    {
        if (!property_exists($schema, 'enum')) {
            return;
        }
        foreach ($schema->enum as $enumCase) {
            if (DeepComparer::isEqual($value, $enumCase)) {
                return;
            }
            if (is_numeric($value) && is_numeric($enumCase) && DeepComparer::isEqual((float) $value, (float) $enumCase)) {
                return;
            }
        }
        $this->addError(ConstraintError::ENUM(), $path, ['enum' => $schema->enum]);
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\JsonSchema\Constraints\Drafts\Draft07;

use _ContaoManager\JsonSchema\ConstraintError;
use _ContaoManager\JsonSchema\Constraints\ConstraintInterface;
use _ContaoManager\JsonSchema\Entity\ErrorBagProxy;
use _ContaoManager\JsonSchema\Entity\JsonPointer;
class PropertiesNamesConstraint implements ConstraintInterface
{
    use ErrorBagProxy;
    /** @var Factory */
    private $factory;
    public function __construct(?Factory $factory = null)
    {
        $this->factory = $factory ?: new Factory();
        $this->initialiseErrorBag($this->factory);
    }
    public function check(&$value, $schema = null, ?JsonPointer $path = null, $i = null): void
    {
        if (!property_exists($schema, 'propertyNames')) {
            return;
        }
        if (!is_object($value)) {
            return;
        }
        if ($schema->propertyNames === \true) {
            return;
        }
        $propertyNames = get_object_vars($value);
        if ($schema->propertyNames === \false) {
            foreach ($propertyNames as $propertyName => $_) {
                $this->addError(ConstraintError::PROPERTY_NAMES(), $path, ['propertyNames' => $schema->propertyNames, 'violating' => 'false', 'name' => $propertyName]);
            }
            return;
        }
        if (property_exists($schema->propertyNames, 'maxLength')) {
            foreach ($propertyNames as $propertyName => $_) {
                $length = mb_strlen($propertyName);
                if ($length > $schema->propertyNames->maxLength) {
                    $this->addError(ConstraintError::PROPERTY_NAMES(), $path, ['propertyNames' => $schema->propertyNames, 'violating' => 'maxLength', 'length' => $length, 'name' => $propertyName]);
                }
            }
        }
        if (property_exists($schema->propertyNames, 'pattern')) {
            foreach ($propertyNames as $propertyName => $_) {
                if (!preg_match('/' . str_replace('/', '\/', $schema->propertyNames->pattern) . '/', $propertyName)) {
                    $this->addError(ConstraintError::PROPERTY_NAMES(), $path, ['propertyNames' => $schema->propertyNames, 'violating' => 'pattern', 'name' => $propertyName]);
                }
            }
        }
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\JsonSchema\Constraints\Drafts\Draft07;

use _ContaoManager\JsonSchema\ConstraintError;
use _ContaoManager\JsonSchema\Constraints\ConstraintInterface;
use _ContaoManager\JsonSchema\Constraints\Factory;
use _ContaoManager\JsonSchema\Entity\ErrorBagProxy;
use _ContaoManager\JsonSchema\Entity\JsonPointer;
class MaximumConstraint implements ConstraintInterface
{
    use ErrorBagProxy;
    public function __construct(?Factory $factory = null)
    {
        $this->initialiseErrorBag($factory ?: new Factory());
    }
    public function check(&$value, $schema = null, ?JsonPointer $path = null, $i = null): void
    {
        if (!property_exists($schema, 'maximum')) {
            return;
        }
        if (!is_numeric($value)) {
            return;
        }
        if ($value <= $schema->maximum) {
            return;
        }
        $this->addError(ConstraintError::MAXIMUM(), $path, ['maximum' => $schema->maximum, 'found' => $value]);
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\JsonSchema\Constraints\Drafts\Draft07;

use _ContaoManager\JsonSchema\ConstraintError;
use _ContaoManager\JsonSchema\Constraints\ConstraintInterface;
use _ContaoManager\JsonSchema\Entity\ErrorBagProxy;
use _ContaoManager\JsonSchema\Entity\JsonPointer;
class PatternConstraint implements ConstraintInterface
{
    use ErrorBagProxy;
    /** @var Factory */
    private $factory;
    public function __construct(?Factory $factory = null)
    {
        $this->factory = $factory ?: new Factory();
        $this->initialiseErrorBag($this->factory);
    }
    public function check(&$value, $schema = null, ?JsonPointer $path = null, $i = null): void
    {
        if (!property_exists($schema, 'pattern')) {
            return;
        }
        if (!is_string($value)) {
            return;
        }
        $matchPattern = $this->createPregMatchPattern($schema->pattern);
        if (preg_match($matchPattern, $value) === 1) {
            return;
        }
        $this->addError(ConstraintError::PATTERN(), $path, ['found' => $value, 'pattern' => $schema->pattern]);
    }
    private function createPregMatchPattern(string $pattern): string
    {
        $replacements = [
            '\D' => '[^0-9]',
            '\d' => '[0-9]',
            '\p{digit}' => '[0-9]',
            '\w' => '[A-Za-z0-9_]',
            '\W' => '[^A-Za-z0-9_]',
            '\s' => '[\s\x{200B}]',
            // Explicitly include zero width white space
            '\p{Letter}' => '\p{L}',
        ];
        $pattern = str_replace(array_keys($replacements), array_values($replacements), $pattern);
        return '/' . str_replace('/', '\/', $pattern) . '/u';
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\JsonSchema\Constraints\Drafts\Draft07;

use _ContaoManager\JsonSchema\ConstraintError;
use _ContaoManager\JsonSchema\Constraints\ConstraintInterface;
use _ContaoManager\JsonSchema\Constraints\Factory;
use _ContaoManager\JsonSchema\Entity\ErrorBagProxy;
use _ContaoManager\JsonSchema\Entity\JsonPointer;
class MaxLengthConstraint implements ConstraintInterface
{
    use ErrorBagProxy;
    public function __construct(?Factory $factory = null)
    {
        $this->initialiseErrorBag($factory ?: new Factory());
    }
    public function check(&$value, $schema = null, ?JsonPointer $path = null, $i = null): void
    {
        if (!property_exists($schema, 'maxLength')) {
            return;
        }
        if (!is_string($value)) {
            return;
        }
        $length = mb_strlen($value);
        if ($length <= $schema->maxLength) {
            return;
        }
        $this->addError(ConstraintError::LENGTH_MAX(), $path, ['maxLength' => $schema->maxLength, 'found' => $length]);
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\JsonSchema\Constraints\Drafts\Draft07;

use _ContaoManager\JsonSchema\ConstraintError;
use _ContaoManager\JsonSchema\Constraints\ConstraintInterface;
use _ContaoManager\JsonSchema\Constraints\Factory;
use _ContaoManager\JsonSchema\Entity\ErrorBagProxy;
use _ContaoManager\JsonSchema\Entity\JsonPointer;
class MinItemsConstraint implements ConstraintInterface
{
    use ErrorBagProxy;
    public function __construct(?Factory $factory = null)
    {
        $this->initialiseErrorBag($factory ?: new Factory());
    }
    public function check(&$value, $schema = null, ?JsonPointer $path = null, $i = null): void
    {
        if (!property_exists($schema, 'minItems')) {
            return;
        }
        if (!is_array($value)) {
            return;
        }
        $count = count($value);
        if ($count >= $schema->minItems) {
            return;
        }
        $this->addError(ConstraintError::MIN_ITEMS(), $path, ['minItems' => $schema->minItems, 'found' => $count]);
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\JsonSchema\Constraints\Drafts\Draft07;

use _ContaoManager\JsonSchema\ConstraintError;
use _ContaoManager\JsonSchema\Constraints\ConstraintInterface;
use _ContaoManager\JsonSchema\Constraints\Factory;
use _ContaoManager\JsonSchema\Entity\ErrorBagProxy;
use _ContaoManager\JsonSchema\Entity\JsonPointer;
use _ContaoManager\JsonSchema\Tool\DeepComparer;
class UniqueItemsConstraint implements ConstraintInterface
{
    use ErrorBagProxy;
    public function __construct(?Factory $factory = null)
    {
        $this->initialiseErrorBag($factory ?: new Factory());
    }
    public function check(&$value, $schema = null, ?JsonPointer $path = null, $i = null): void
    {
        if (!property_exists($schema, 'uniqueItems')) {
            return;
        }
        if (!is_array($value)) {
            return;
        }
        if ($schema->uniqueItems !== \true) {
            // If unique items not is true duplicates are allowed.
            return;
        }
        $count = count($value);
        for ($x = 0; $x < $count - 1; $x++) {
            for ($y = $x + 1; $y < $count; $y++) {
                if (DeepComparer::isEqual($value[$x], $value[$y])) {
                    $this->addError(ConstraintError::UNIQUE_ITEMS(), $path);
                    return;
                }
            }
        }
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\JsonSchema\Constraints\Drafts\Draft07;

use _ContaoManager\JsonSchema\ConstraintError;
use _ContaoManager\JsonSchema\Constraints\ConstraintInterface;
use _ContaoManager\JsonSchema\Constraints\Factory;
use _ContaoManager\JsonSchema\Entity\ErrorBagProxy;
use _ContaoManager\JsonSchema\Entity\JsonPointer;
class ExclusiveMaximumConstraint implements ConstraintInterface
{
    use ErrorBagProxy;
    public function __construct(?Factory $factory = null)
    {
        $this->initialiseErrorBag($factory ?: new Factory());
    }
    public function check(&$value, $schema = null, ?JsonPointer $path = null, $i = null): void
    {
        if (!property_exists($schema, 'exclusiveMaximum')) {
            return;
        }
        if (!is_numeric($value)) {
            return;
        }
        if ($value < $schema->exclusiveMaximum) {
            return;
        }
        $this->addError(ConstraintError::EXCLUSIVE_MAXIMUM(), $path, ['exclusiveMaximum' => $schema->exclusiveMaximum, 'found' => $value]);
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\JsonSchema\Constraints\Drafts\Draft07;

use _ContaoManager\JsonSchema\ConstraintError;
use _ContaoManager\JsonSchema\Constraints\ConstraintInterface;
use _ContaoManager\JsonSchema\Entity\ErrorBagProxy;
use _ContaoManager\JsonSchema\Entity\JsonPointer;
class DependenciesConstraint implements ConstraintInterface
{
    use ErrorBagProxy;
    /** @var Factory */
    private $factory;
    public function __construct(?Factory $factory = null)
    {
        $this->factory = $factory ?: new Factory();
        $this->initialiseErrorBag($this->factory);
    }
    public function check(&$value, $schema = null, ?JsonPointer $path = null, $i = null): void
    {
        if (!property_exists($schema, 'dependencies')) {
            return;
        }
        if (!is_object($value)) {
            return;
        }
        foreach ($schema->dependencies as $dependant => $dependencies) {
            if (!property_exists($value, $dependant)) {
                continue;
            }
            if ($dependencies === \true) {
                continue;
            }
            if ($dependencies === \false) {
                $this->addError(ConstraintError::FALSE(), $path, ['dependant' => $dependant]);
                continue;
            }
            if (is_array($dependencies)) {
                foreach ($dependencies as $dependency) {
                    if (property_exists($value, $dependant) && !property_exists($value, $dependency)) {
                        $this->addError(ConstraintError::DEPENDENCIES(), $path, ['dependant' => $dependant, 'dependency' => $dependency]);
                    }
                }
            }
            if (is_object($dependencies)) {
                $schemaConstraint = $this->factory->createInstanceFor('schema');
                $schemaConstraint->check($value, $dependencies, $path, $i);
                if (!$schemaConstraint->isValid()) {
                    $this->addErrors($schemaConstraint->getErrors());
                }
            }
        }
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\JsonSchema\Constraints\Drafts\Draft07;

use _ContaoManager\JsonSchema\ConstraintError;
use _ContaoManager\JsonSchema\Constraints\ConstraintInterface;
use _ContaoManager\JsonSchema\Constraints\Factory;
use _ContaoManager\JsonSchema\Entity\ErrorBagProxy;
use _ContaoManager\JsonSchema\Entity\JsonPointer;
class MultipleOfConstraint implements ConstraintInterface
{
    use ErrorBagProxy;
    public function __construct(?Factory $factory = null)
    {
        $this->initialiseErrorBag($factory ?: new Factory());
    }
    public function check(&$value, $schema = null, ?JsonPointer $path = null, $i = null): void
    {
        if (!property_exists($schema, 'multipleOf')) {
            return;
        }
        if (!is_int($schema->multipleOf) && !is_float($schema->multipleOf) && $schema->multipleOf <= 0.0) {
            return;
        }
        if (!is_int($value) && !is_float($value)) {
            return;
        }
        if ($this->isMultipleOf($value, $schema->multipleOf)) {
            return;
        }
        $this->addError(ConstraintError::MULTIPLE_OF(), $path, ['multipleOf' => $schema->multipleOf, 'found' => $value]);
    }
    /**
     * @param int|float $number1
     * @param int|float $number2
     */
    private function isMultipleOf($number1, $number2): bool
    {
        $modulus = $number1 - round($number1 / $number2) * $number2;
        $precision = 1.0E-10;
        return -$precision < $modulus && $modulus < $precision;
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\JsonSchema\Constraints\Drafts\Draft07;

use _ContaoManager\JsonSchema\ConstraintError;
use _ContaoManager\JsonSchema\Constraints\ConstraintInterface;
use _ContaoManager\JsonSchema\Entity\ErrorBagProxy;
use _ContaoManager\JsonSchema\Entity\JsonPointer;
class AllOfConstraint implements ConstraintInterface
{
    use ErrorBagProxy;
    /** @var Factory */
    private $factory;
    public function __construct(?Factory $factory = null)
    {
        $this->factory = $factory ?: new Factory();
        $this->initialiseErrorBag($this->factory);
    }
    public function check(&$value, $schema = null, ?JsonPointer $path = null, $i = null): void
    {
        if (!property_exists($schema, 'allOf')) {
            return;
        }
        foreach ($schema->allOf as $allOfSchema) {
            $schemaConstraint = $this->factory->createInstanceFor('schema');
            $schemaConstraint->check($value, $allOfSchema, $path, $i);
            if ($schemaConstraint->isValid()) {
                continue;
            }
            $this->addError(ConstraintError::ALL_OF(), $path);
            $this->addErrors($schemaConstraint->getErrors());
        }
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\JsonSchema\Constraints\Drafts\Draft07;

use _ContaoManager\JsonSchema\Constraints\ConstraintInterface;
use _ContaoManager\JsonSchema\Entity\ErrorBagProxy;
use _ContaoManager\JsonSchema\Entity\JsonPointer;
class RefConstraint implements ConstraintInterface
{
    use ErrorBagProxy;
    /** @var Factory */
    private $factory;
    public function __construct(?Factory $factory = null)
    {
        $this->factory = $factory ?: new Factory();
        $this->initialiseErrorBag($this->factory);
    }
    public function check(&$value, $schema = null, ?JsonPointer $path = null, $i = null): void
    {
        if (!property_exists($schema, '$ref')) {
            return;
        }
        try {
            $refSchema = $this->factory->getSchemaStorage()->resolveRefSchema($schema);
        } catch (\Exception $e) {
            return;
        }
        $schemaConstraint = $this->factory->createInstanceFor('schema');
        $schemaConstraint->check($value, $refSchema, $path, $i);
        if ($schemaConstraint->isValid()) {
            return;
        }
        $this->addErrors($schemaConstraint->getErrors());
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\JsonSchema\Constraints\Drafts\Draft07;

use _ContaoManager\JsonSchema\Constraints\ConstraintInterface;
use _ContaoManager\JsonSchema\Entity\ErrorBagProxy;
use _ContaoManager\JsonSchema\Entity\JsonPointer;
class ItemsConstraint implements ConstraintInterface
{
    use ErrorBagProxy;
    /** @var Factory */
    private $factory;
    public function __construct(?Factory $factory = null)
    {
        $this->factory = $factory ?: new Factory();
        $this->initialiseErrorBag($this->factory);
    }
    public function check(&$value, $schema = null, ?JsonPointer $path = null, $i = null): void
    {
        if (!property_exists($schema, 'items')) {
            return;
        }
        if (!is_array($value)) {
            return;
        }
        foreach ($value as $propertyName => $propertyValue) {
            $itemSchema = $schema->items;
            if (is_array($itemSchema)) {
                if (!array_key_exists($propertyName, $itemSchema)) {
                    continue;
                }
                $itemSchema = $itemSchema[$propertyName];
            }
            $schemaConstraint = $this->factory->createInstanceFor('schema');
            $schemaConstraint->check($propertyValue, $itemSchema, $path, $i);
            if ($schemaConstraint->isValid()) {
                continue;
            }
            $this->addErrors($schemaConstraint->getErrors());
        }
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\JsonSchema\Constraints\Drafts\Draft07;

use _ContaoManager\JsonSchema\Constraints\ConstraintInterface;
use _ContaoManager\JsonSchema\Entity\ErrorBagProxy;
use _ContaoManager\JsonSchema\Entity\JsonPointer;
class PropertiesConstraint implements ConstraintInterface
{
    use ErrorBagProxy;
    /** @var Factory */
    private $factory;
    public function __construct(?Factory $factory = null)
    {
        $this->factory = $factory ?: new Factory();
        $this->initialiseErrorBag($this->factory);
    }
    public function check(&$value, $schema = null, ?JsonPointer $path = null, $i = null): void
    {
        if (!property_exists($schema, 'properties')) {
            return;
        }
        if (!is_object($value)) {
            return;
        }
        foreach ($schema->properties as $propertyName => $propertySchema) {
            $schemaConstraint = $this->factory->createInstanceFor('schema');
            if (!property_exists($value, $propertyName)) {
                continue;
            }
            $schemaConstraint->check($value->{$propertyName}, $propertySchema, $path, $i);
            if ($schemaConstraint->isValid()) {
                continue;
            }
            $this->addErrors($schemaConstraint->getErrors());
        }
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\JsonSchema\Constraints\Drafts\Draft07;

use _ContaoManager\JsonSchema\ConstraintError;
use _ContaoManager\JsonSchema\Constraints\ConstraintInterface;
use _ContaoManager\JsonSchema\Constraints\Factory;
use _ContaoManager\JsonSchema\Entity\ErrorBagProxy;
use _ContaoManager\JsonSchema\Entity\JsonPointer;
class MaxPropertiesConstraint implements ConstraintInterface
{
    use ErrorBagProxy;
    public function __construct(?Factory $factory = null)
    {
        $this->initialiseErrorBag($factory ?: new Factory());
    }
    public function check(&$value, $schema = null, ?JsonPointer $path = null, $i = null): void
    {
        if (!property_exists($schema, 'maxProperties')) {
            return;
        }
        if (!is_object($value)) {
            return;
        }
        $count = count(get_object_vars($value));
        if ($count <= $schema->maxProperties) {
            return;
        }
        $this->addError(ConstraintError::PROPERTIES_MAX(), $path, ['maxProperties' => $schema->maxProperties, 'found' => $count]);
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\JsonSchema\Constraints\Drafts\Draft07;

use _ContaoManager\JsonSchema\ConstraintError;
use _ContaoManager\JsonSchema\Constraints\ConstraintInterface;
use _ContaoManager\JsonSchema\Entity\ErrorBagProxy;
use _ContaoManager\JsonSchema\Entity\JsonPointer;
class NotConstraint implements ConstraintInterface
{
    use ErrorBagProxy;
    /** @var Factory */
    private $factory;
    public function __construct(?Factory $factory = null)
    {
        $this->factory = $factory ?: new Factory();
        $this->initialiseErrorBag($this->factory);
    }
    public function check(&$value, $schema = null, ?JsonPointer $path = null, $i = null): void
    {
        if (!property_exists($schema, 'not')) {
            return;
        }
        $schemaConstraint = $this->factory->createInstanceFor('schema');
        $schemaConstraint->check($value, $schema->not, $path, $i);
        if (!$schemaConstraint->isValid()) {
            return;
        }
        $this->addError(ConstraintError::NOT(), $path);
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\JsonSchema\Constraints\Drafts\Draft07;

use DateTimeZone;
use _ContaoManager\JsonSchema\ConstraintError;
use _ContaoManager\JsonSchema\Constraints\ConstraintInterface;
use _ContaoManager\JsonSchema\Constraints\Factory;
use _ContaoManager\JsonSchema\Entity\ErrorBagProxy;
use _ContaoManager\JsonSchema\Entity\JsonPointer;
use _ContaoManager\JsonSchema\Rfc3339;
use _ContaoManager\JsonSchema\Tool\Validator\RelativeReferenceValidator;
use _ContaoManager\JsonSchema\Tool\Validator\UriValidator;
class FormatConstraint implements ConstraintInterface
{
    use ErrorBagProxy;
    public function __construct(?Factory $factory = null)
    {
        $this->initialiseErrorBag($factory ?: new Factory());
    }
    public function check(&$value, $schema = null, ?JsonPointer $path = null, $i = null): void
    {
        if (!property_exists($schema, 'format')) {
            return;
        }
        if (!is_string($value)) {
            return;
        }
        switch ($schema->format) {
            case 'date':
                if (!$this->validateDateTime($value, 'Y-m-d')) {
                    $this->addError(ConstraintError::FORMAT_DATE(), $path, ['date' => $value, 'format' => $schema->format]);
                }
                break;
            case 'time':
                if (!$this->validateDateTime($value, 'H:i:sp') && !$this->validateDateTime($value, 'H:i:s.up')) {
                    $this->addError(ConstraintError::FORMAT_TIME(), $path, ['time' => $value, 'format' => $schema->format]);
                }
                break;
            case 'date-time':
                if (!$this->validateRfc3339DateTime($value)) {
                    $this->addError(ConstraintError::FORMAT_DATE_TIME(), $path, ['dateTime' => $value, 'format' => $schema->format]);
                }
                break;
            case 'utc-millisec':
                if (!$this->validateDateTime($value, 'U')) {
                    $this->addError(ConstraintError::FORMAT_DATE_UTC(), $path, ['value' => $value, 'format' => $schema->format]);
                }
                break;
            case 'regex':
                if (!$this->validateRegex($value)) {
                    $this->addError(ConstraintError::FORMAT_REGEX(), $path, ['value' => $value, 'format' => $schema->format]);
                }
                break;
            case 'ip-address':
            case 'ipv4':
                if (filter_var($value, \FILTER_VALIDATE_IP, \FILTER_NULL_ON_FAILURE | \FILTER_FLAG_IPV4) === null) {
                    $this->addError(ConstraintError::FORMAT_IP(), $path, ['format' => $schema->format]);
                }
                break;
            case 'ipv6':
                if (filter_var($value, \FILTER_VALIDATE_IP, \FILTER_NULL_ON_FAILURE | \FILTER_FLAG_IPV6) === null) {
                    $this->addError(ConstraintError::FORMAT_IP(), $path, ['format' => $schema->format]);
                }
                break;
            case 'color':
                if (!$this->validateColor($value)) {
                    $this->addError(ConstraintError::FORMAT_COLOR(), $path, ['format' => $schema->format]);
                }
                break;
            case 'style':
                if (!$this->validateStyle($value)) {
                    $this->addError(ConstraintError::FORMAT_STYLE(), $path, ['format' => $schema->format]);
                }
                break;
            case 'phone':
                if (!$this->validatePhone($value)) {
                    $this->addError(ConstraintError::FORMAT_PHONE(), $path, ['format' => $schema->format]);
                }
                break;
            case 'uri':
                if (!UriValidator::isValid($value)) {
                    $this->addError(ConstraintError::FORMAT_URL(), $path, ['format' => $schema->format]);
                }
                break;
            case 'uriref':
            case 'uri-reference':
                if (!(UriValidator::isValid($value) || RelativeReferenceValidator::isValid($value))) {
                    $this->addError(ConstraintError::FORMAT_URL(), $path, ['format' => $schema->format]);
                }
                break;
            case 'uri-template':
                if (!$this->validateUriTemplate($value)) {
                    $this->addError(ConstraintError::FORMAT_URI_TEMPLATE(), $path, ['format' => $schema->format]);
                }
                break;
            case 'email':
                if (filter_var($value, \FILTER_VALIDATE_EMAIL, \FILTER_NULL_ON_FAILURE | \FILTER_FLAG_EMAIL_UNICODE) === null) {
                    $this->addError(ConstraintError::FORMAT_EMAIL(), $path, ['format' => $schema->format]);
                }
                break;
            case 'host-name':
            case 'hostname':
                if (!$this->validateHostname($value)) {
                    $this->addError(ConstraintError::FORMAT_HOSTNAME(), $path, ['format' => $schema->format]);
                }
                break;
            case 'idn-hostname':
                if (!$this->validateInternationalizedHostname($value)) {
                    $this->addError(ConstraintError::FORMAT_HOSTNAME(), $path, ['format' => $schema->format]);
                }
                break;
            case 'json-pointer':
                if (!$this->validateJsonPointer($value)) {
                    $this->addError(ConstraintError::FORMAT_JSON_POINTER(), $path, ['format' => $schema->format]);
                }
                break;
            default:
                break;
        }
    }
    private function validateDateTime(string $datetime, string $format): bool
    {
        $datetime = strtoupper($datetime);
        // Cleanup for lowercase z
        $isLeap = substr($datetime, 6, 2) === '60';
        $input = $datetime;
        // Correct for leap second
        if ($isLeap) {
            $input = sprintf('%s59%s', substr($datetime, 0, 6), substr($datetime, 8));
        }
        $dt = \DateTimeImmutable::createFromFormat($format, $input);
        if (!$dt) {
            return \false;
        }
        // Handle invalid timezone offsets
        $timezoneOffset = $dt->getTimezone()->getOffset($dt);
        if ($timezoneOffset >= 86400 || $timezoneOffset <= -86400) {
            return \false;
        }
        $expected = $dt->format($format);
        // Correct for trailing zeros on microseconds
        if ($format === 'H:i:s.up') {
            $expected = sprintf('%s%s', rtrim($dt->format('H:i:s.u'), '0'), $dt->format('p'));
        }
        // Correct back for leap seconds
        if ($isLeap) {
            // Only when 23:59:59 in UTC
            $utcDT = $dt->setTimezone(new DateTimeZone('UTC'));
            if ($utcDT->format('H:i:s') !== '23:59:59') {
                return \false;
            }
            $expected = sprintf('%s60%s', substr($expected, 0, 6), substr($expected, 8));
        }
        return $datetime === $expected;
    }
    private function validateRegex(string $regex): bool
    {
        return preg_match(self::jsonPatternToPhpRegex($regex), '') !== \false;
    }
    /**
     * Transform a JSON pattern into a PCRE regex
     */
    private static function jsonPatternToPhpRegex(string $pattern): string
    {
        return '~' . str_replace('~', '\~', $pattern) . '~u';
    }
    private function validateColor(string $color): bool
    {
        if (in_array(strtolower($color), ['aqua', 'black', 'blue', 'fuchsia', 'gray', 'green', 'lime', 'maroon', 'navy', 'olive', 'orange', 'purple', 'red', 'silver', 'teal', 'white', 'yellow'])) {
            return \true;
        }
        return preg_match('/^#([a-f0-9]{3}|[a-f0-9]{6})$/i', $color) !== \false;
    }
    private function validateStyle(string $style): bool
    {
        $properties = explode(';', rtrim($style, ';'));
        $invalidEntries = preg_grep('/^\s*[-a-z]+\s*:\s*.+$/i', $properties, \PREG_GREP_INVERT);
        return empty($invalidEntries);
    }
    private function validatePhone(string $phone): bool
    {
        return preg_match('/^\+?(\(\d{3}\)|\d{3}) \d{3} \d{4}$/', $phone) !== \false;
    }
    private function validateHostname(string $host): bool
    {
        $hostnameRegex = '/^(?!-)(?!.*?[^A-Za-z0-9\-\.])(?:(?!-)[A-Za-z0-9](?:[A-Za-z0-9\-]{0,61}[A-Za-z0-9])?\.)*(?!-)[A-Za-z0-9](?:[A-Za-z0-9\-]{0,61}[A-Za-z0-9])?$/';
        return preg_match($hostnameRegex, $host) === 1;
    }
    private function validateInternationalizedHostname(string $host): bool
    {
        if ($host === '') {
            return \false;
        }
        $host = rtrim($host, '.');
        $labels = explode('.', $host);
        $asciiLabels = [];
        if ($labels === \false) {
            return \false;
        }
        foreach ($labels as $label) {
            if ($label === '') {
                return \false;
            }
            // CONTEXTJ / CONTEXTO checks
            if (preg_match('/\x{0375}/u', $label) && !preg_match('/\x{0375}[\x{0370}-\x{03FF}]/u', $label)) {
                return \false;
            }
            // Hebrew GERESH / GERSHAYIM U+05F3 / U+05F4
            if (preg_match('/[\x{05F3}\x{05F4}]/u', $label) && !preg_match('/[\x{0590}-\x{05FF}][\x{05F3}\x{05F4}]/u', $label)) {
                return \false;
            }
            // Katakana middle dot U+30FB
            if (str_contains($label, "・") && !preg_match('/[\x{30A0}-\x{30FF}]/u', $label)) {
                return \false;
            }
            // Arabic digit mixing
            $hasArabicIndic = preg_match('/[\x{0660}-\x{0669}]/u', $label);
            $hasExtArabicIndic = preg_match('/[\x{06F0}-\x{06F9}]/u', $label);
            if ($hasArabicIndic && $hasExtArabicIndic) {
                return \false;
            }
            // Devanagari danda U+0964 / U+0965
            if (preg_match('/[\x{0964}\x{0965}]/u', $label) && !preg_match('/[\x{0900}-\x{097F}]/u', $label)) {
                return \false;
            }
            // ZWNJ / ZWJ U+200C / U+200D
            if (preg_match('/[\x{200C}\x{200D}]/u', $label)) {
                return \false;
            }
            $ascii = idn_to_ascii($label, \IDNA_DEFAULT, \INTL_IDNA_VARIANT_UTS46);
            if ($ascii === \false) {
                return \false;
            }
            // DNS label length
            if (strlen($ascii) > 63) {
                return \false;
            }
            // LDH rule (after IDNA)
            if (!preg_match('/^[a-z0-9](?:[a-z0-9-]*[a-z0-9])?$/i', $ascii)) {
                return \false;
            }
            $asciiLabels[] = $ascii;
        }
        // Total hostname length (ASCII)
        $asciiHost = implode('.', $asciiLabels);
        return strlen($asciiHost) <= 253;
    }
    private function validateJsonPointer(string $value): bool
    {
        // Must be empty or start with a forward slash
        if ($value !== '' && $value[0] !== '/') {
            return \false;
        }
        // Split into reference tokens and check for invalid escape sequences
        $tokens = explode('/', $value);
        array_shift($tokens);
        // remove leading empty part due to leading slash
        foreach ($tokens as $token) {
            // "~" must only be followed by "0" or "1"
            if (preg_match('/~(?![01])/', $token)) {
                return \false;
            }
        }
        return \true;
    }
    private function validateRfc3339DateTime(string $value): bool
    {
        $dateTime = Rfc3339::createFromString($value);
        if (is_null($dateTime)) {
            return \false;
        }
        // Compare value and date result to be equal
        return \true;
    }
    private function validateUriTemplate(string $value): bool
    {
        return preg_match('/^(?:[^\{\}]*|\{[a-zA-Z0-9_:%\/\.~\-\+\*]+\})*$/', $value) === 1;
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\JsonSchema\Constraints\Drafts\Draft07;

use _ContaoManager\JsonSchema\ConstraintError;
use _ContaoManager\JsonSchema\Constraints\ConstraintInterface;
use _ContaoManager\JsonSchema\Entity\ErrorBagProxy;
use _ContaoManager\JsonSchema\Entity\JsonPointer;
class ContainsConstraint implements ConstraintInterface
{
    use ErrorBagProxy;
    /** @var Factory */
    private $factory;
    public function __construct(?Factory $factory = null)
    {
        $this->factory = $factory ?: new Factory();
        $this->initialiseErrorBag($this->factory);
    }
    public function check(&$value, $schema = null, ?JsonPointer $path = null, $i = null): void
    {
        if (!property_exists($schema, 'contains')) {
            return;
        }
        $properties = [];
        if (!is_array($value)) {
            return;
        }
        foreach ($value as $propertyName => $propertyValue) {
            $schemaConstraint = $this->factory->createInstanceFor('schema');
            $schemaConstraint->check($propertyValue, $schema->contains, $path, $i);
            if ($schemaConstraint->isValid()) {
                return;
            }
        }
        $this->addError(ConstraintError::CONTAINS(), $path, ['contains' => $schema->contains]);
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\JsonSchema\Constraints\Drafts\Draft07;

use _ContaoManager\JsonSchema\Constraints\ConstraintInterface;
use _ContaoManager\JsonSchema\Entity\ErrorBagProxy;
use _ContaoManager\JsonSchema\Entity\JsonPointer;
class IfThenElseConstraint implements ConstraintInterface
{
    use ErrorBagProxy;
    /** @var Factory */
    private $factory;
    public function __construct(?Factory $factory = null)
    {
        $this->factory = $factory ?: new Factory();
        $this->initialiseErrorBag($this->factory);
    }
    public function check(&$value, $schema = null, ?JsonPointer $path = null, $i = null): void
    {
        if (!property_exists($schema, 'if')) {
            return;
        }
        $schemaConstraint = $this->factory->createInstanceFor('schema');
        $ifSchema = $schema->if;
        if (!is_bool($ifSchema)) {
            $schemaConstraint->check($value, $ifSchema, $path, $i);
            $meetsIfConditions = $schemaConstraint->isValid();
            $schemaConstraint->reset();
        } else {
            $meetsIfConditions = $ifSchema;
        }
        if ($meetsIfConditions) {
            if (!property_exists($schema, 'then')) {
                return;
            }
            $schemaConstraint->check($value, $schema->then, $path, $i);
            if ($schemaConstraint->isValid()) {
                return;
            }
            $this->addErrors($schemaConstraint->getErrors());
            return;
        }
        if (!property_exists($schema, 'else')) {
            return;
        }
        $schemaConstraint->check($value, $schema->else, $path, $i);
        if ($schemaConstraint->isValid()) {
            return;
        }
        $this->addErrors($schemaConstraint->getErrors());
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\JsonSchema\Constraints\Drafts\Draft07;

use _ContaoManager\JsonSchema\ConstraintError;
use _ContaoManager\JsonSchema\Constraints\ConstraintInterface;
use _ContaoManager\JsonSchema\Entity\ErrorBagProxy;
use _ContaoManager\JsonSchema\Entity\JsonPointer;
class OneOfConstraint implements ConstraintInterface
{
    use ErrorBagProxy;
    /** @var Factory */
    private $factory;
    public function __construct(?Factory $factory = null)
    {
        $this->factory = $factory ?: new Factory();
        $this->initialiseErrorBag($this->factory);
    }
    public function check(&$value, $schema = null, ?JsonPointer $path = null, $i = null): void
    {
        if (!property_exists($schema, 'oneOf')) {
            return;
        }
        $matchedSchema = 0;
        foreach ($schema->oneOf as $oneOfSchema) {
            $schemaConstraint = $this->factory->createInstanceFor('schema');
            $schemaConstraint->check($value, $oneOfSchema, $path, $i);
            if ($schemaConstraint->isValid()) {
                $matchedSchema++;
                continue;
            }
            $this->addErrors($schemaConstraint->getErrors());
        }
        if ($matchedSchema !== 1) {
            $this->addError(ConstraintError::ONE_OF(), $path);
        } else {
            $this->errorBag()->reset();
        }
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\JsonSchema\Constraints\Drafts\Draft07;

use _ContaoManager\JsonSchema\ConstraintError;
use _ContaoManager\JsonSchema\Constraints\ConstraintInterface;
use _ContaoManager\JsonSchema\Constraints\Factory;
use _ContaoManager\JsonSchema\Entity\ErrorBagProxy;
use _ContaoManager\JsonSchema\Entity\JsonPointer;
class MaxItemsConstraint implements ConstraintInterface
{
    use ErrorBagProxy;
    public function __construct(?Factory $factory = null)
    {
        $this->initialiseErrorBag($factory ?: new Factory());
    }
    public function check(&$value, $schema = null, ?JsonPointer $path = null, $i = null): void
    {
        if (!property_exists($schema, 'maxItems')) {
            return;
        }
        if (!is_array($value)) {
            return;
        }
        $count = count($value);
        if ($count <= $schema->maxItems) {
            return;
        }
        $this->addError(ConstraintError::MAX_ITEMS(), $path, ['maxItems' => $schema->maxItems, 'found' => $count]);
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\JsonSchema\Constraints\Drafts\Draft07;

use _ContaoManager\JsonSchema\ConstraintError;
use _ContaoManager\JsonSchema\Constraints\ConstraintInterface;
use _ContaoManager\JsonSchema\Constraints\Factory;
use _ContaoManager\JsonSchema\Entity\ErrorBagProxy;
use _ContaoManager\JsonSchema\Entity\JsonPointer;
class MinimumConstraint implements ConstraintInterface
{
    use ErrorBagProxy;
    public function __construct(?Factory $factory = null)
    {
        $this->initialiseErrorBag($factory ?: new Factory());
    }
    public function check(&$value, $schema = null, ?JsonPointer $path = null, $i = null): void
    {
        if (!property_exists($schema, 'minimum')) {
            return;
        }
        if (!is_numeric($value)) {
            return;
        }
        if ($value >= $schema->minimum) {
            return;
        }
        $this->addError(ConstraintError::MINIMUM(), $path, ['minimum' => $schema->minimum, 'found' => $value]);
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\JsonSchema\Constraints\Drafts\Draft07;

use _ContaoManager\JsonSchema\Constraints\ConstraintInterface;
use _ContaoManager\JsonSchema\Entity\ErrorBagProxy;
use _ContaoManager\JsonSchema\Entity\JsonPointer;
class PatternPropertiesConstraint implements ConstraintInterface
{
    use ErrorBagProxy;
    /** @var Factory */
    private $factory;
    public function __construct(?Factory $factory = null)
    {
        $this->factory = $factory ?: new Factory();
        $this->initialiseErrorBag($this->factory);
    }
    public function check(&$value, $schema = null, ?JsonPointer $path = null, $i = null): void
    {
        if (!property_exists($schema, 'patternProperties')) {
            return;
        }
        if (!is_object($value)) {
            return;
        }
        $properties = get_object_vars($value);
        foreach ($properties as $propertyName => $propertyValue) {
            foreach ($schema->patternProperties as $patternPropertyRegex => $patternPropertySchema) {
                $matchPattern = $this->createPregMatchPattern($patternPropertyRegex);
                if (preg_match($matchPattern, (string) $propertyName)) {
                    $schemaConstraint = $this->factory->createInstanceFor('schema');
                    $schemaConstraint->check($propertyValue, $patternPropertySchema, $path, $i);
                    if ($schemaConstraint->isValid()) {
                        continue;
                    }
                    $this->addErrors($schemaConstraint->getErrors());
                }
            }
        }
    }
    private function createPregMatchPattern(string $pattern): string
    {
        $replacements = [
            //            '\D' => '[^0-9]',
            '\d' => '[0-9]',
            '\p{digit}' => '[0-9]',
            //            '\w' => '[A-Za-z0-9_]',
            //            '\W' => '[^A-Za-z0-9_]',
            //            '\s' => '[\s\x{200B}]' // Explicitly include zero width white space
            '\p{Letter}' => '\p{L}',
        ];
        $pattern = str_replace(array_keys($replacements), array_values($replacements), $pattern);
        return '/' . str_replace('/', '\/', $pattern) . '/u';
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\JsonSchema\Constraints\Drafts\Draft07;

use _ContaoManager\JsonSchema\ConstraintError;
use _ContaoManager\JsonSchema\Constraints\Constraint;
use _ContaoManager\JsonSchema\Entity\JsonPointer;
use _ContaoManager\JsonSchema\SchemaStorage;
use _ContaoManager\JsonSchema\Uri\UriRetriever;
class Draft07Constraint extends Constraint
{
    public function __construct(?\_ContaoManager\JsonSchema\Constraints\Factory $factory = null)
    {
        parent::__construct(new Factory($factory ? $factory->getSchemaStorage() : new SchemaStorage(), $factory ? $factory->getUriRetriever() : new UriRetriever(), $factory ? $factory->getConfig() : Constraint::CHECK_MODE_NORMAL));
    }
    public function check(&$value, $schema = null, ?JsonPointer $path = null, $i = null): void
    {
        if (is_bool($schema)) {
            if ($schema === \false) {
                $this->addError(ConstraintError::FALSE(), $path, []);
            }
            return;
        }
        // Apply defaults
        $this->checkForKeyword('ref', $value, $schema, $path, $i);
        $this->checkForKeyword('required', $value, $schema, $path, $i);
        $this->checkForKeyword('contains', $value, $schema, $path, $i);
        $this->checkForKeyword('properties', $value, $schema, $path, $i);
        $this->checkForKeyword('propertyNames', $value, $schema, $path, $i);
        $this->checkForKeyword('patternProperties', $value, $schema, $path, $i);
        $this->checkForKeyword('type', $value, $schema, $path, $i);
        $this->checkForKeyword('not', $value, $schema, $path, $i);
        $this->checkForKeyword('dependencies', $value, $schema, $path, $i);
        $this->checkForKeyword('allOf', $value, $schema, $path, $i);
        $this->checkForKeyword('anyOf', $value, $schema, $path, $i);
        $this->checkForKeyword('oneOf', $value, $schema, $path, $i);
        $this->checkForKeyword('ifThenElse', $value, $schema, $path, $i);
        $this->checkForKeyword('additionalProperties', $value, $schema, $path, $i);
        $this->checkForKeyword('items', $value, $schema, $path, $i);
        $this->checkForKeyword('additionalItems', $value, $schema, $path, $i);
        $this->checkForKeyword('uniqueItems', $value, $schema, $path, $i);
        $this->checkForKeyword('minItems', $value, $schema, $path, $i);
        $this->checkForKeyword('minProperties', $value, $schema, $path, $i);
        $this->checkForKeyword('maxProperties', $value, $schema, $path, $i);
        $this->checkForKeyword('minimum', $value, $schema, $path, $i);
        $this->checkForKeyword('maximum', $value, $schema, $path, $i);
        $this->checkForKeyword('minLength', $value, $schema, $path, $i);
        $this->checkForKeyword('exclusiveMinimum', $value, $schema, $path, $i);
        $this->checkForKeyword('maxItems', $value, $schema, $path, $i);
        $this->checkForKeyword('maxLength', $value, $schema, $path, $i);
        $this->checkForKeyword('exclusiveMaximum', $value, $schema, $path, $i);
        $this->checkForKeyword('enum', $value, $schema, $path, $i);
        $this->checkForKeyword('const', $value, $schema, $path, $i);
        $this->checkForKeyword('multipleOf', $value, $schema, $path, $i);
        $this->checkForKeyword('format', $value, $schema, $path, $i);
        $this->checkForKeyword('pattern', $value, $schema, $path, $i);
        $this->checkForKeyword('content', $value, $schema, $path, $i);
    }
    /**
     * @param mixed $value
     * @param mixed $schema
     * @param mixed $i
     */
    protected function checkForKeyword(string $keyword, $value, $schema = null, ?JsonPointer $path = null, $i = null): void
    {
        $validator = $this->factory->createInstanceFor($keyword);
        $validator->check($value, $schema, $path, $i);
        $this->addErrors($validator->getErrors());
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\JsonSchema\Constraints\Drafts\Draft07;

use _ContaoManager\JsonSchema\ConstraintError;
use _ContaoManager\JsonSchema\Constraints\ConstraintInterface;
use _ContaoManager\JsonSchema\Constraints\Factory;
use _ContaoManager\JsonSchema\Entity\ErrorBagProxy;
use _ContaoManager\JsonSchema\Entity\JsonPointer;
class MinLengthConstraint implements ConstraintInterface
{
    use ErrorBagProxy;
    public function __construct(?Factory $factory = null)
    {
        $this->initialiseErrorBag($factory ?: new Factory());
    }
    public function check(&$value, $schema = null, ?JsonPointer $path = null, $i = null): void
    {
        if (!property_exists($schema, 'minLength')) {
            return;
        }
        if (!is_string($value)) {
            return;
        }
        $length = mb_strlen($value);
        if ($length >= $schema->minLength) {
            return;
        }
        $this->addError(ConstraintError::LENGTH_MIN(), $path, ['minLength' => $schema->minLength, 'found' => $length]);
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\JsonSchema\Constraints\Drafts\Draft07;

use _ContaoManager\JsonSchema\ConstraintError;
use _ContaoManager\JsonSchema\Constraints\ConstraintInterface;
use _ContaoManager\JsonSchema\Constraints\Factory;
use _ContaoManager\JsonSchema\Entity\ErrorBagProxy;
use _ContaoManager\JsonSchema\Entity\JsonPointer;
class RequiredConstraint implements ConstraintInterface
{
    use ErrorBagProxy;
    public function __construct(?Factory $factory = null)
    {
        $this->initialiseErrorBag($factory ?: new Factory());
    }
    public function check(&$value, $schema = null, ?JsonPointer $path = null, $i = null): void
    {
        if (!property_exists($schema, 'required')) {
            return;
        }
        if (!is_object($value)) {
            return;
        }
        foreach ($schema->required as $required) {
            if (property_exists($value, $required)) {
                continue;
            }
            $this->addError(ConstraintError::REQUIRED(), $this->incrementPath($path, $required), ['property' => $required]);
        }
    }
    /**
     * @todo refactor as this was only copied from UndefinedConstraint
     * Bubble down the path
     *
     * @param JsonPointer|null $path Current path
     * @param mixed            $i    What to append to the path
     */
    protected function incrementPath(?JsonPointer $path, $i): JsonPointer
    {
        $path = $path ?? new JsonPointer('');
        if ($i === null || $i === '') {
            return $path;
        }
        return $path->withPropertyPaths(array_merge($path->getPropertyPaths(), [$i]));
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\JsonSchema\Constraints\Drafts\Draft07;

use _ContaoManager\JsonSchema\ConstraintError;
use _ContaoManager\JsonSchema\Constraints\ConstraintInterface;
use _ContaoManager\JsonSchema\Constraints\Factory;
use _ContaoManager\JsonSchema\Entity\ErrorBagProxy;
use _ContaoManager\JsonSchema\Entity\JsonPointer;
class MinPropertiesConstraint implements ConstraintInterface
{
    use ErrorBagProxy;
    public function __construct(?Factory $factory = null)
    {
        $this->initialiseErrorBag($factory ?: new Factory());
    }
    public function check(&$value, $schema = null, ?JsonPointer $path = null, $i = null): void
    {
        if (!property_exists($schema, 'minProperties')) {
            return;
        }
        if (!is_object($value)) {
            return;
        }
        $count = count(get_object_vars($value));
        if ($count >= $schema->minProperties) {
            return;
        }
        $this->addError(ConstraintError::PROPERTIES_MIN(), $path, ['minProperties' => $schema->minProperties, 'found' => $count]);
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\JsonSchema\Constraints\Drafts\Draft06;

class Factory extends \_ContaoManager\JsonSchema\Constraints\Factory
{
    /**
     * @var array<string, class-string>
     */
    protected $constraintMap = ['schema' => Draft06Constraint::class, 'additionalProperties' => AdditionalPropertiesConstraint::class, 'additionalItems' => AdditionalItemsConstraint::class, 'dependencies' => DependenciesConstraint::class, 'type' => TypeConstraint::class, 'const' => ConstConstraint::class, 'enum' => EnumConstraint::class, 'uniqueItems' => UniqueItemsConstraint::class, 'minItems' => MinItemsConstraint::class, 'minProperties' => MinPropertiesConstraint::class, 'maxProperties' => MaxPropertiesConstraint::class, 'minimum' => MinimumConstraint::class, 'maximum' => MaximumConstraint::class, 'exclusiveMinimum' => ExclusiveMinimumConstraint::class, 'minLength' => MinLengthConstraint::class, 'maxLength' => MaxLengthConstraint::class, 'maxItems' => MaxItemsConstraint::class, 'exclusiveMaximum' => ExclusiveMaximumConstraint::class, 'multipleOf' => MultipleOfConstraint::class, 'required' => RequiredConstraint::class, 'format' => FormatConstraint::class, 'anyOf' => AnyOfConstraint::class, 'allOf' => AllOfConstraint::class, 'oneOf' => OneOfConstraint::class, 'not' => NotConstraint::class, 'contains' => ContainsConstraint::class, 'propertyNames' => PropertiesNamesConstraint::class, 'patternProperties' => PatternPropertiesConstraint::class, 'pattern' => PatternConstraint::class, 'properties' => PropertiesConstraint::class, 'items' => ItemsConstraint::class, 'ref' => RefConstraint::class];
}
<?php

declare (strict_types=1);
namespace _ContaoManager\JsonSchema\Constraints\Drafts\Draft06;

use _ContaoManager\JsonSchema\ConstraintError;
use _ContaoManager\JsonSchema\Constraints\ConstraintInterface;
use _ContaoManager\JsonSchema\Constraints\Factory;
use _ContaoManager\JsonSchema\Entity\ErrorBagProxy;
use _ContaoManager\JsonSchema\Entity\JsonPointer;
class ExclusiveMinimumConstraint implements ConstraintInterface
{
    use ErrorBagProxy;
    public function __construct(?Factory $factory = null)
    {
        $this->initialiseErrorBag($factory ?: new Factory());
    }
    public function check(&$value, $schema = null, ?JsonPointer $path = null, $i = null): void
    {
        if (!property_exists($schema, 'exclusiveMinimum')) {
            return;
        }
        if (!is_numeric($value)) {
            return;
        }
        if ($value > $schema->exclusiveMinimum) {
            return;
        }
        $this->addError(ConstraintError::EXCLUSIVE_MINIMUM(), $path, ['exclusiveMinimum' => $schema->exclusiveMinimum, 'found' => $value]);
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\JsonSchema\Constraints\Drafts\Draft06;

use _ContaoManager\JsonSchema\ConstraintError;
use _ContaoManager\JsonSchema\Constraints\ConstraintInterface;
use _ContaoManager\JsonSchema\Entity\ErrorBagProxy;
use _ContaoManager\JsonSchema\Entity\JsonPointer;
class AdditionalItemsConstraint implements ConstraintInterface
{
    use ErrorBagProxy;
    /** @var Factory */
    private $factory;
    public function __construct(?Factory $factory = null)
    {
        $this->factory = $factory ?: new Factory();
        $this->initialiseErrorBag($this->factory);
    }
    public function check(&$value, $schema = null, ?JsonPointer $path = null, $i = null): void
    {
        if (!property_exists($schema, 'additionalItems')) {
            return;
        }
        if ($schema->additionalItems === \true) {
            return;
        }
        if ($schema->additionalItems === \false && !property_exists($schema, 'items')) {
            return;
        }
        if (!is_array($value)) {
            return;
        }
        if (!property_exists($schema, 'items')) {
            return;
        }
        if (property_exists($schema, 'items') && is_object($schema->items)) {
            return;
        }
        $additionalItems = array_diff_key($value, property_exists($schema, 'items') ? $schema->items : []);
        foreach ($additionalItems as $propertyName => $propertyValue) {
            $schemaConstraint = $this->factory->createInstanceFor('schema');
            $schemaConstraint->check($propertyValue, $schema->additionalItems, $path, $i);
            if ($schemaConstraint->isValid()) {
                continue;
            }
            $this->addError(ConstraintError::ADDITIONAL_ITEMS(), $path, ['item' => $i, 'property' => $propertyName, 'additionalItems' => $schema->additionalItems]);
        }
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\JsonSchema\Constraints\Drafts\Draft06;

use _ContaoManager\JsonSchema\ConstraintError;
use _ContaoManager\JsonSchema\Constraints\ConstraintInterface;
use _ContaoManager\JsonSchema\Constraints\Factory;
use _ContaoManager\JsonSchema\Entity\ErrorBagProxy;
use _ContaoManager\JsonSchema\Entity\JsonPointer;
use _ContaoManager\JsonSchema\Tool\DeepComparer;
class ConstConstraint implements ConstraintInterface
{
    use ErrorBagProxy;
    public function __construct(?Factory $factory = null)
    {
        $this->initialiseErrorBag($factory ?: new Factory());
    }
    public function check(&$value, $schema = null, ?JsonPointer $path = null, $i = null): void
    {
        if (!property_exists($schema, 'const')) {
            return;
        }
        if (DeepComparer::isEqual($value, $schema->const)) {
            return;
        }
        $this->addError(ConstraintError::CONSTANT(), $path, ['const' => $schema->const]);
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\JsonSchema\Constraints\Drafts\Draft06;

use _ContaoManager\JsonSchema\ConstraintError;
use _ContaoManager\JsonSchema\Constraints\ConstraintInterface;
use _ContaoManager\JsonSchema\Entity\ErrorBagProxy;
use _ContaoManager\JsonSchema\Entity\JsonPointer;
class AdditionalPropertiesConstraint implements ConstraintInterface
{
    use ErrorBagProxy;
    /** @var Factory */
    private $factory;
    public function __construct(?Factory $factory = null)
    {
        $this->factory = $factory ?: new Factory();
        $this->initialiseErrorBag($this->factory);
    }
    public function check(&$value, $schema = null, ?JsonPointer $path = null, $i = null): void
    {
        if (!property_exists($schema, 'additionalProperties')) {
            return;
        }
        if ($schema->additionalProperties === \true) {
            return;
        }
        if (!is_object($value)) {
            return;
        }
        $additionalProperties = get_object_vars($value);
        if (isset($schema->properties)) {
            $additionalProperties = array_diff_key($additionalProperties, (array) $schema->properties);
        }
        if (isset($schema->patternProperties)) {
            $patterns = array_keys(get_object_vars($schema->patternProperties));
            foreach ($additionalProperties as $key => $_) {
                foreach ($patterns as $pattern) {
                    if (preg_match($this->createPregMatchPattern($pattern), (string) $key)) {
                        unset($additionalProperties[$key]);
                        break;
                    }
                }
            }
        }
        if (is_object($schema->additionalProperties)) {
            foreach ($additionalProperties as $key => $additionalPropertiesValue) {
                $schemaConstraint = $this->factory->createInstanceFor('schema');
                $schemaConstraint->check($additionalPropertiesValue, $schema->additionalProperties, $path, $i);
                // @todo increment path
                if ($schemaConstraint->isValid()) {
                    unset($additionalProperties[$key]);
                }
            }
        }
        foreach ($additionalProperties as $key => $additionalPropertiesValue) {
            $this->addError(ConstraintError::ADDITIONAL_PROPERTIES(), $path, ['found' => $additionalPropertiesValue]);
        }
    }
    private function createPregMatchPattern(string $pattern): string
    {
        $replacements = [
            //            '\D' => '[^0-9]',
            //            '\d' => '[0-9]',
            '\p{digit}' => '\p{Nd}',
            //            '\w' => '[A-Za-z0-9_]',
            //            '\W' => '[^A-Za-z0-9_]',
            //            '\s' => '[\s\x{200B}]' // Explicitly include zero width white space,
            '\p{Letter}' => '\p{L}',
        ];
        $pattern = str_replace(array_keys($replacements), array_values($replacements), $pattern);
        return '/' . str_replace('/', '\/', $pattern) . '/u';
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\JsonSchema\Constraints\Drafts\Draft06;

use _ContaoManager\JsonSchema\ConstraintError;
use _ContaoManager\JsonSchema\Constraints\Constraint;
use _ContaoManager\JsonSchema\Entity\JsonPointer;
use _ContaoManager\JsonSchema\SchemaStorage;
use _ContaoManager\JsonSchema\Uri\UriRetriever;
class Draft06Constraint extends Constraint
{
    public function __construct(?\_ContaoManager\JsonSchema\Constraints\Factory $factory = null)
    {
        parent::__construct(new Factory($factory ? $factory->getSchemaStorage() : new SchemaStorage(), $factory ? $factory->getUriRetriever() : new UriRetriever(), $factory ? $factory->getConfig() : Constraint::CHECK_MODE_NORMAL));
    }
    public function check(&$value, $schema = null, ?JsonPointer $path = null, $i = null): void
    {
        if (is_bool($schema)) {
            if ($schema === \false) {
                $this->addError(ConstraintError::FALSE(), $path, []);
            }
            return;
        }
        // Apply defaults
        $this->checkForKeyword('ref', $value, $schema, $path, $i);
        $this->checkForKeyword('required', $value, $schema, $path, $i);
        $this->checkForKeyword('contains', $value, $schema, $path, $i);
        $this->checkForKeyword('properties', $value, $schema, $path, $i);
        $this->checkForKeyword('propertyNames', $value, $schema, $path, $i);
        $this->checkForKeyword('patternProperties', $value, $schema, $path, $i);
        $this->checkForKeyword('type', $value, $schema, $path, $i);
        $this->checkForKeyword('not', $value, $schema, $path, $i);
        $this->checkForKeyword('dependencies', $value, $schema, $path, $i);
        $this->checkForKeyword('allOf', $value, $schema, $path, $i);
        $this->checkForKeyword('anyOf', $value, $schema, $path, $i);
        $this->checkForKeyword('oneOf', $value, $schema, $path, $i);
        $this->checkForKeyword('additionalProperties', $value, $schema, $path, $i);
        $this->checkForKeyword('items', $value, $schema, $path, $i);
        $this->checkForKeyword('additionalItems', $value, $schema, $path, $i);
        $this->checkForKeyword('uniqueItems', $value, $schema, $path, $i);
        $this->checkForKeyword('minItems', $value, $schema, $path, $i);
        $this->checkForKeyword('minProperties', $value, $schema, $path, $i);
        $this->checkForKeyword('maxProperties', $value, $schema, $path, $i);
        $this->checkForKeyword('minimum', $value, $schema, $path, $i);
        $this->checkForKeyword('maximum', $value, $schema, $path, $i);
        $this->checkForKeyword('minLength', $value, $schema, $path, $i);
        $this->checkForKeyword('exclusiveMinimum', $value, $schema, $path, $i);
        $this->checkForKeyword('maxItems', $value, $schema, $path, $i);
        $this->checkForKeyword('maxLength', $value, $schema, $path, $i);
        $this->checkForKeyword('exclusiveMaximum', $value, $schema, $path, $i);
        $this->checkForKeyword('enum', $value, $schema, $path, $i);
        $this->checkForKeyword('const', $value, $schema, $path, $i);
        $this->checkForKeyword('multipleOf', $value, $schema, $path, $i);
        $this->checkForKeyword('format', $value, $schema, $path, $i);
        $this->checkForKeyword('pattern', $value, $schema, $path, $i);
    }
    /**
     * @param mixed $value
     * @param mixed $schema
     * @param mixed $i
     */
    protected function checkForKeyword(string $keyword, $value, $schema = null, ?JsonPointer $path = null, $i = null): void
    {
        $validator = $this->factory->createInstanceFor($keyword);
        $validator->check($value, $schema, $path, $i);
        $this->addErrors($validator->getErrors());
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\JsonSchema\Constraints\Drafts\Draft06;

use _ContaoManager\JsonSchema\ConstraintError;
use _ContaoManager\JsonSchema\Constraints\ConstraintInterface;
use _ContaoManager\JsonSchema\Constraints\Factory;
use _ContaoManager\JsonSchema\Entity\ErrorBagProxy;
use _ContaoManager\JsonSchema\Entity\JsonPointer;
class TypeConstraint implements ConstraintInterface
{
    use ErrorBagProxy;
    public function __construct(?Factory $factory = null)
    {
        $this->initialiseErrorBag($factory ?: new Factory());
    }
    public function check(&$value, $schema = null, ?JsonPointer $path = null, $i = null): void
    {
        if (!property_exists($schema, 'type')) {
            return;
        }
        $schemaTypes = (array) $schema->type;
        $valueType = strtolower(gettype($value));
        // All specific number types are a number
        $valueIsNumber = $valueType === 'double' || $valueType === 'integer';
        // A float with zero fractional part is an integer
        $isInteger = $valueIsNumber && fmod($value, 1.0) === 0.0;
        foreach ($schemaTypes as $type) {
            if ($valueType === $type) {
                return;
            }
            if ($type === 'number' && $valueIsNumber) {
                return;
            }
            if ($type === 'integer' && $isInteger) {
                return;
            }
        }
        $this->addError(ConstraintError::TYPE(), $path, ['found' => $valueType, 'expected' => implode(', ', $schemaTypes)]);
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\JsonSchema\Constraints\Drafts\Draft06;

use _ContaoManager\JsonSchema\ConstraintError;
use _ContaoManager\JsonSchema\Constraints\ConstraintInterface;
use _ContaoManager\JsonSchema\Entity\ErrorBagProxy;
use _ContaoManager\JsonSchema\Entity\JsonPointer;
use _ContaoManager\JsonSchema\Exception\ValidationException;
class AnyOfConstraint implements ConstraintInterface
{
    use ErrorBagProxy;
    /** @var Factory */
    private $factory;
    public function __construct(?Factory $factory = null)
    {
        $this->factory = $factory ?: new Factory();
        $this->initialiseErrorBag($this->factory);
    }
    public function check(&$value, $schema = null, ?JsonPointer $path = null, $i = null): void
    {
        if (!property_exists($schema, 'anyOf')) {
            return;
        }
        foreach ($schema->anyOf as $anyOfSchema) {
            $schemaConstraint = $this->factory->createInstanceFor('schema');
            try {
                $schemaConstraint->check($value, $anyOfSchema, $path, $i);
                if ($schemaConstraint->isValid()) {
                    $this->errorBag()->reset();
                    return;
                }
                $this->addErrors($schemaConstraint->getErrors());
            } catch (ValidationException $e) {
            }
        }
        $this->addError(ConstraintError::ANY_OF(), $path);
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\JsonSchema\Constraints\Drafts\Draft06;

use _ContaoManager\JsonSchema\ConstraintError;
use _ContaoManager\JsonSchema\Constraints\ConstraintInterface;
use _ContaoManager\JsonSchema\Constraints\Factory;
use _ContaoManager\JsonSchema\Entity\ErrorBagProxy;
use _ContaoManager\JsonSchema\Entity\JsonPointer;
use _ContaoManager\JsonSchema\Tool\DeepComparer;
class EnumConstraint implements ConstraintInterface
{
    use ErrorBagProxy;
    public function __construct(?Factory $factory = null)
    {
        $this->initialiseErrorBag($factory ?: new Factory());
    }
    public function check(&$value, $schema = null, ?JsonPointer $path = null, $i = null): void
    {
        if (!property_exists($schema, 'enum')) {
            return;
        }
        foreach ($schema->enum as $enumCase) {
            if (DeepComparer::isEqual($value, $enumCase)) {
                return;
            }
            if (is_numeric($value) && is_numeric($enumCase) && DeepComparer::isEqual((float) $value, (float) $enumCase)) {
                return;
            }
        }
        $this->addError(ConstraintError::ENUM(), $path, ['enum' => $schema->enum]);
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\JsonSchema\Constraints\Drafts\Draft06;

use _ContaoManager\JsonSchema\ConstraintError;
use _ContaoManager\JsonSchema\Constraints\ConstraintInterface;
use _ContaoManager\JsonSchema\Entity\ErrorBagProxy;
use _ContaoManager\JsonSchema\Entity\JsonPointer;
class PropertiesNamesConstraint implements ConstraintInterface
{
    use ErrorBagProxy;
    /** @var Factory */
    private $factory;
    public function __construct(?Factory $factory = null)
    {
        $this->factory = $factory ?: new Factory();
        $this->initialiseErrorBag($this->factory);
    }
    public function check(&$value, $schema = null, ?JsonPointer $path = null, $i = null): void
    {
        if (!property_exists($schema, 'propertyNames')) {
            return;
        }
        if (!is_object($value)) {
            return;
        }
        if ($schema->propertyNames === \true) {
            return;
        }
        $propertyNames = get_object_vars($value);
        if ($schema->propertyNames === \false) {
            foreach ($propertyNames as $propertyName => $_) {
                $this->addError(ConstraintError::PROPERTY_NAMES(), $path, ['propertyNames' => $schema->propertyNames, 'violating' => 'false', 'name' => $propertyName]);
            }
            return;
        }
        if (property_exists($schema->propertyNames, 'maxLength')) {
            foreach ($propertyNames as $propertyName => $_) {
                $length = mb_strlen($propertyName);
                if ($length > $schema->propertyNames->maxLength) {
                    $this->addError(ConstraintError::PROPERTY_NAMES(), $path, ['propertyNames' => $schema->propertyNames, 'violating' => 'maxLength', 'length' => $length, 'name' => $propertyName]);
                }
            }
        }
        if (property_exists($schema->propertyNames, 'pattern')) {
            foreach ($propertyNames as $propertyName => $_) {
                if (!preg_match('/' . str_replace('/', '\/', $schema->propertyNames->pattern) . '/', $propertyName)) {
                    $this->addError(ConstraintError::PROPERTY_NAMES(), $path, ['propertyNames' => $schema->propertyNames, 'violating' => 'pattern', 'name' => $propertyName]);
                }
            }
        }
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\JsonSchema\Constraints\Drafts\Draft06;

use _ContaoManager\JsonSchema\ConstraintError;
use _ContaoManager\JsonSchema\Constraints\ConstraintInterface;
use _ContaoManager\JsonSchema\Constraints\Factory;
use _ContaoManager\JsonSchema\Entity\ErrorBagProxy;
use _ContaoManager\JsonSchema\Entity\JsonPointer;
class MaximumConstraint implements ConstraintInterface
{
    use ErrorBagProxy;
    public function __construct(?Factory $factory = null)
    {
        $this->initialiseErrorBag($factory ?: new Factory());
    }
    public function check(&$value, $schema = null, ?JsonPointer $path = null, $i = null): void
    {
        if (!property_exists($schema, 'maximum')) {
            return;
        }
        if (!is_numeric($value)) {
            return;
        }
        if ($value <= $schema->maximum) {
            return;
        }
        $this->addError(ConstraintError::MAXIMUM(), $path, ['maximum' => $schema->maximum, 'found' => $value]);
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\JsonSchema\Constraints\Drafts\Draft06;

use _ContaoManager\JsonSchema\ConstraintError;
use _ContaoManager\JsonSchema\Constraints\ConstraintInterface;
use _ContaoManager\JsonSchema\Entity\ErrorBagProxy;
use _ContaoManager\JsonSchema\Entity\JsonPointer;
class PatternConstraint implements ConstraintInterface
{
    use ErrorBagProxy;
    /** @var Factory */
    private $factory;
    public function __construct(?Factory $factory = null)
    {
        $this->factory = $factory ?: new Factory();
        $this->initialiseErrorBag($this->factory);
    }
    public function check(&$value, $schema = null, ?JsonPointer $path = null, $i = null): void
    {
        if (!property_exists($schema, 'pattern')) {
            return;
        }
        if (!is_string($value)) {
            return;
        }
        $matchPattern = $this->createPregMatchPattern($schema->pattern);
        if (preg_match($matchPattern, $value) === 1) {
            return;
        }
        $this->addError(ConstraintError::PATTERN(), $path, ['found' => $value, 'pattern' => $schema->pattern]);
    }
    private function createPregMatchPattern(string $pattern): string
    {
        $replacements = [
            '\D' => '[^0-9]',
            '\d' => '[0-9]',
            '\p{digit}' => '[0-9]',
            '\w' => '[A-Za-z0-9_]',
            '\W' => '[^A-Za-z0-9_]',
            '\s' => '[\s\x{200B}]',
            // Explicitly include zero width white space
            '\p{Letter}' => '\p{L}',
        ];
        $pattern = str_replace(array_keys($replacements), array_values($replacements), $pattern);
        return '/' . str_replace('/', '\/', $pattern) . '/u';
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\JsonSchema\Constraints\Drafts\Draft06;

use _ContaoManager\JsonSchema\ConstraintError;
use _ContaoManager\JsonSchema\Constraints\ConstraintInterface;
use _ContaoManager\JsonSchema\Constraints\Factory;
use _ContaoManager\JsonSchema\Entity\ErrorBagProxy;
use _ContaoManager\JsonSchema\Entity\JsonPointer;
class MaxLengthConstraint implements ConstraintInterface
{
    use ErrorBagProxy;
    public function __construct(?Factory $factory = null)
    {
        $this->initialiseErrorBag($factory ?: new Factory());
    }
    public function check(&$value, $schema = null, ?JsonPointer $path = null, $i = null): void
    {
        if (!property_exists($schema, 'maxLength')) {
            return;
        }
        if (!is_string($value)) {
            return;
        }
        $length = mb_strlen($value);
        if ($length <= $schema->maxLength) {
            return;
        }
        $this->addError(ConstraintError::LENGTH_MAX(), $path, ['maxLength' => $schema->maxLength, 'found' => $length]);
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\JsonSchema\Constraints\Drafts\Draft06;

use _ContaoManager\JsonSchema\ConstraintError;
use _ContaoManager\JsonSchema\Constraints\ConstraintInterface;
use _ContaoManager\JsonSchema\Constraints\Factory;
use _ContaoManager\JsonSchema\Entity\ErrorBagProxy;
use _ContaoManager\JsonSchema\Entity\JsonPointer;
class MinItemsConstraint implements ConstraintInterface
{
    use ErrorBagProxy;
    public function __construct(?Factory $factory = null)
    {
        $this->initialiseErrorBag($factory ?: new Factory());
    }
    public function check(&$value, $schema = null, ?JsonPointer $path = null, $i = null): void
    {
        if (!property_exists($schema, 'minItems')) {
            return;
        }
        if (!is_array($value)) {
            return;
        }
        $count = count($value);
        if ($count >= $schema->minItems) {
            return;
        }
        $this->addError(ConstraintError::MIN_ITEMS(), $path, ['minItems' => $schema->minItems, 'found' => $count]);
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\JsonSchema\Constraints\Drafts\Draft06;

use _ContaoManager\JsonSchema\ConstraintError;
use _ContaoManager\JsonSchema\Constraints\ConstraintInterface;
use _ContaoManager\JsonSchema\Constraints\Factory;
use _ContaoManager\JsonSchema\Entity\ErrorBagProxy;
use _ContaoManager\JsonSchema\Entity\JsonPointer;
use _ContaoManager\JsonSchema\Tool\DeepComparer;
class UniqueItemsConstraint implements ConstraintInterface
{
    use ErrorBagProxy;
    public function __construct(?Factory $factory = null)
    {
        $this->initialiseErrorBag($factory ?: new Factory());
    }
    public function check(&$value, $schema = null, ?JsonPointer $path = null, $i = null): void
    {
        if (!property_exists($schema, 'uniqueItems')) {
            return;
        }
        if (!is_array($value)) {
            return;
        }
        if ($schema->uniqueItems !== \true) {
            // If unique items not is true duplicates are allowed.
            return;
        }
        $count = count($value);
        for ($x = 0; $x < $count - 1; $x++) {
            for ($y = $x + 1; $y < $count; $y++) {
                if (DeepComparer::isEqual($value[$x], $value[$y])) {
                    $this->addError(ConstraintError::UNIQUE_ITEMS(), $path);
                    return;
                }
            }
        }
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\JsonSchema\Constraints\Drafts\Draft06;

use _ContaoManager\JsonSchema\ConstraintError;
use _ContaoManager\JsonSchema\Constraints\ConstraintInterface;
use _ContaoManager\JsonSchema\Constraints\Factory;
use _ContaoManager\JsonSchema\Entity\ErrorBagProxy;
use _ContaoManager\JsonSchema\Entity\JsonPointer;
class ExclusiveMaximumConstraint implements ConstraintInterface
{
    use ErrorBagProxy;
    public function __construct(?Factory $factory = null)
    {
        $this->initialiseErrorBag($factory ?: new Factory());
    }
    public function check(&$value, $schema = null, ?JsonPointer $path = null, $i = null): void
    {
        if (!property_exists($schema, 'exclusiveMaximum')) {
            return;
        }
        if (!is_numeric($value)) {
            return;
        }
        if ($value < $schema->exclusiveMaximum) {
            return;
        }
        $this->addError(ConstraintError::EXCLUSIVE_MAXIMUM(), $path, ['exclusiveMaximum' => $schema->exclusiveMaximum, 'found' => $value]);
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\JsonSchema\Constraints\Drafts\Draft06;

use _ContaoManager\JsonSchema\ConstraintError;
use _ContaoManager\JsonSchema\Constraints\ConstraintInterface;
use _ContaoManager\JsonSchema\Entity\ErrorBagProxy;
use _ContaoManager\JsonSchema\Entity\JsonPointer;
class DependenciesConstraint implements ConstraintInterface
{
    use ErrorBagProxy;
    /** @var Factory */
    private $factory;
    public function __construct(?Factory $factory = null)
    {
        $this->factory = $factory ?: new Factory();
        $this->initialiseErrorBag($this->factory);
    }
    public function check(&$value, $schema = null, ?JsonPointer $path = null, $i = null): void
    {
        if (!property_exists($schema, 'dependencies')) {
            return;
        }
        if (!is_object($value)) {
            return;
        }
        foreach ($schema->dependencies as $dependant => $dependencies) {
            if (!property_exists($value, $dependant)) {
                continue;
            }
            if ($dependencies === \true) {
                continue;
            }
            if ($dependencies === \false) {
                $this->addError(ConstraintError::FALSE(), $path, ['dependant' => $dependant]);
                continue;
            }
            if (is_array($dependencies)) {
                foreach ($dependencies as $dependency) {
                    if (property_exists($value, $dependant) && !property_exists($value, $dependency)) {
                        $this->addError(ConstraintError::DEPENDENCIES(), $path, ['dependant' => $dependant, 'dependency' => $dependency]);
                    }
                }
            }
            if (is_object($dependencies)) {
                $schemaConstraint = $this->factory->createInstanceFor('schema');
                $schemaConstraint->check($value, $dependencies, $path, $i);
                if (!$schemaConstraint->isValid()) {
                    $this->addErrors($schemaConstraint->getErrors());
                }
            }
        }
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\JsonSchema\Constraints\Drafts\Draft06;

use _ContaoManager\JsonSchema\ConstraintError;
use _ContaoManager\JsonSchema\Constraints\ConstraintInterface;
use _ContaoManager\JsonSchema\Constraints\Factory;
use _ContaoManager\JsonSchema\Entity\ErrorBagProxy;
use _ContaoManager\JsonSchema\Entity\JsonPointer;
class MultipleOfConstraint implements ConstraintInterface
{
    use ErrorBagProxy;
    public function __construct(?Factory $factory = null)
    {
        $this->initialiseErrorBag($factory ?: new Factory());
    }
    public function check(&$value, $schema = null, ?JsonPointer $path = null, $i = null): void
    {
        if (!property_exists($schema, 'multipleOf')) {
            return;
        }
        if (!is_int($schema->multipleOf) && !is_float($schema->multipleOf) && $schema->multipleOf <= 0.0) {
            return;
        }
        if (!is_int($value) && !is_float($value)) {
            return;
        }
        if ($this->isMultipleOf($value, $schema->multipleOf)) {
            return;
        }
        $this->addError(ConstraintError::MULTIPLE_OF(), $path, ['multipleOf' => $schema->multipleOf, 'found' => $value]);
    }
    /**
     * @param int|float $number1
     * @param int|float $number2
     */
    private function isMultipleOf($number1, $number2): bool
    {
        $modulus = $number1 - round($number1 / $number2) * $number2;
        $precision = 1.0E-10;
        return -$precision < $modulus && $modulus < $precision;
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\JsonSchema\Constraints\Drafts\Draft06;

use _ContaoManager\JsonSchema\ConstraintError;
use _ContaoManager\JsonSchema\Constraints\ConstraintInterface;
use _ContaoManager\JsonSchema\Entity\ErrorBagProxy;
use _ContaoManager\JsonSchema\Entity\JsonPointer;
class AllOfConstraint implements ConstraintInterface
{
    use ErrorBagProxy;
    /** @var Factory */
    private $factory;
    public function __construct(?Factory $factory = null)
    {
        $this->factory = $factory ?: new Factory();
        $this->initialiseErrorBag($this->factory);
    }
    public function check(&$value, $schema = null, ?JsonPointer $path = null, $i = null): void
    {
        if (!property_exists($schema, 'allOf')) {
            return;
        }
        foreach ($schema->allOf as $allOfSchema) {
            $schemaConstraint = $this->factory->createInstanceFor('schema');
            $schemaConstraint->check($value, $allOfSchema, $path, $i);
            if ($schemaConstraint->isValid()) {
                continue;
            }
            $this->addError(ConstraintError::ALL_OF(), $path);
            $this->addErrors($schemaConstraint->getErrors());
        }
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\JsonSchema\Constraints\Drafts\Draft06;

use _ContaoManager\JsonSchema\Constraints\ConstraintInterface;
use _ContaoManager\JsonSchema\Entity\ErrorBagProxy;
use _ContaoManager\JsonSchema\Entity\JsonPointer;
class RefConstraint implements ConstraintInterface
{
    use ErrorBagProxy;
    /** @var Factory */
    private $factory;
    public function __construct(?Factory $factory = null)
    {
        $this->factory = $factory ?: new Factory();
        $this->initialiseErrorBag($this->factory);
    }
    public function check(&$value, $schema = null, ?JsonPointer $path = null, $i = null): void
    {
        if (!property_exists($schema, '$ref')) {
            return;
        }
        try {
            $refSchema = $this->factory->getSchemaStorage()->resolveRefSchema($schema);
        } catch (\Exception $e) {
            return;
        }
        $schemaConstraint = $this->factory->createInstanceFor('schema');
        $schemaConstraint->check($value, $refSchema, $path, $i);
        if ($schemaConstraint->isValid()) {
            return;
        }
        $this->addErrors($schemaConstraint->getErrors());
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\JsonSchema\Constraints\Drafts\Draft06;

use _ContaoManager\JsonSchema\Constraints\ConstraintInterface;
use _ContaoManager\JsonSchema\Entity\ErrorBagProxy;
use _ContaoManager\JsonSchema\Entity\JsonPointer;
class ItemsConstraint implements ConstraintInterface
{
    use ErrorBagProxy;
    /** @var Factory */
    private $factory;
    public function __construct(?Factory $factory = null)
    {
        $this->factory = $factory ?: new Factory();
        $this->initialiseErrorBag($this->factory);
    }
    public function check(&$value, $schema = null, ?JsonPointer $path = null, $i = null): void
    {
        if (!property_exists($schema, 'items')) {
            return;
        }
        if (!is_array($value)) {
            return;
        }
        foreach ($value as $propertyName => $propertyValue) {
            $itemSchema = $schema->items;
            if (is_array($itemSchema)) {
                if (!array_key_exists($propertyName, $itemSchema)) {
                    continue;
                }
                $itemSchema = $itemSchema[$propertyName];
            }
            $schemaConstraint = $this->factory->createInstanceFor('schema');
            $schemaConstraint->check($propertyValue, $itemSchema, $path, $i);
            if ($schemaConstraint->isValid()) {
                continue;
            }
            $this->addErrors($schemaConstraint->getErrors());
        }
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\JsonSchema\Constraints\Drafts\Draft06;

use _ContaoManager\JsonSchema\Constraints\ConstraintInterface;
use _ContaoManager\JsonSchema\Entity\ErrorBagProxy;
use _ContaoManager\JsonSchema\Entity\JsonPointer;
class PropertiesConstraint implements ConstraintInterface
{
    use ErrorBagProxy;
    /** @var Factory */
    private $factory;
    public function __construct(?Factory $factory = null)
    {
        $this->factory = $factory ?: new Factory();
        $this->initialiseErrorBag($this->factory);
    }
    public function check(&$value, $schema = null, ?JsonPointer $path = null, $i = null): void
    {
        if (!property_exists($schema, 'properties')) {
            return;
        }
        if (!is_object($value)) {
            return;
        }
        foreach ($schema->properties as $propertyName => $propertySchema) {
            $schemaConstraint = $this->factory->createInstanceFor('schema');
            if (!property_exists($value, $propertyName)) {
                continue;
            }
            $schemaConstraint->check($value->{$propertyName}, $propertySchema, $path, $i);
            if ($schemaConstraint->isValid()) {
                continue;
            }
            $this->addErrors($schemaConstraint->getErrors());
        }
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\JsonSchema\Constraints\Drafts\Draft06;

use _ContaoManager\JsonSchema\ConstraintError;
use _ContaoManager\JsonSchema\Constraints\ConstraintInterface;
use _ContaoManager\JsonSchema\Constraints\Factory;
use _ContaoManager\JsonSchema\Entity\ErrorBagProxy;
use _ContaoManager\JsonSchema\Entity\JsonPointer;
class MaxPropertiesConstraint implements ConstraintInterface
{
    use ErrorBagProxy;
    public function __construct(?Factory $factory = null)
    {
        $this->initialiseErrorBag($factory ?: new Factory());
    }
    public function check(&$value, $schema = null, ?JsonPointer $path = null, $i = null): void
    {
        if (!property_exists($schema, 'maxProperties')) {
            return;
        }
        if (!is_object($value)) {
            return;
        }
        $count = count(get_object_vars($value));
        if ($count <= $schema->maxProperties) {
            return;
        }
        $this->addError(ConstraintError::PROPERTIES_MAX(), $path, ['maxProperties' => $schema->maxProperties, 'found' => $count]);
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\JsonSchema\Constraints\Drafts\Draft06;

use _ContaoManager\JsonSchema\ConstraintError;
use _ContaoManager\JsonSchema\Constraints\ConstraintInterface;
use _ContaoManager\JsonSchema\Entity\ErrorBagProxy;
use _ContaoManager\JsonSchema\Entity\JsonPointer;
class NotConstraint implements ConstraintInterface
{
    use ErrorBagProxy;
    /** @var Factory */
    private $factory;
    public function __construct(?Factory $factory = null)
    {
        $this->factory = $factory ?: new Factory();
        $this->initialiseErrorBag($this->factory);
    }
    public function check(&$value, $schema = null, ?JsonPointer $path = null, $i = null): void
    {
        if (!property_exists($schema, 'not')) {
            return;
        }
        $schemaConstraint = $this->factory->createInstanceFor('schema');
        $schemaConstraint->check($value, $schema->not, $path, $i);
        if (!$schemaConstraint->isValid()) {
            return;
        }
        $this->addError(ConstraintError::NOT(), $path);
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\JsonSchema\Constraints\Drafts\Draft06;

use _ContaoManager\JsonSchema\ConstraintError;
use _ContaoManager\JsonSchema\Constraints\ConstraintInterface;
use _ContaoManager\JsonSchema\Constraints\Factory;
use _ContaoManager\JsonSchema\Entity\ErrorBagProxy;
use _ContaoManager\JsonSchema\Entity\JsonPointer;
use _ContaoManager\JsonSchema\Rfc3339;
use _ContaoManager\JsonSchema\Tool\Validator\RelativeReferenceValidator;
use _ContaoManager\JsonSchema\Tool\Validator\UriValidator;
class FormatConstraint implements ConstraintInterface
{
    use ErrorBagProxy;
    public function __construct(?Factory $factory = null)
    {
        $this->initialiseErrorBag($factory ?: new Factory());
    }
    public function check(&$value, $schema = null, ?JsonPointer $path = null, $i = null): void
    {
        if (!property_exists($schema, 'format')) {
            return;
        }
        if (!is_string($value)) {
            return;
        }
        switch ($schema->format) {
            case 'date':
                if (!$this->validateDateTime($value, 'Y-m-d')) {
                    $this->addError(ConstraintError::FORMAT_DATE(), $path, ['date' => $value, 'format' => $schema->format]);
                }
                break;
            case 'time':
                if (!$this->validateDateTime($value, 'H:i:s')) {
                    $this->addError(ConstraintError::FORMAT_TIME(), $path, ['time' => $value, 'format' => $schema->format]);
                }
                break;
            case 'date-time':
                if (!$this->validateRfc3339DateTime($value)) {
                    $this->addError(ConstraintError::FORMAT_DATE_TIME(), $path, ['dateTime' => $value, 'format' => $schema->format]);
                }
                break;
            case 'utc-millisec':
                if (!$this->validateDateTime($value, 'U')) {
                    $this->addError(ConstraintError::FORMAT_DATE_UTC(), $path, ['value' => $value, 'format' => $schema->format]);
                }
                break;
            case 'regex':
                if (!$this->validateRegex($value)) {
                    $this->addError(ConstraintError::FORMAT_REGEX(), $path, ['value' => $value, 'format' => $schema->format]);
                }
                break;
            case 'ip-address':
            case 'ipv4':
                if (filter_var($value, \FILTER_VALIDATE_IP, \FILTER_NULL_ON_FAILURE | \FILTER_FLAG_IPV4) === null) {
                    $this->addError(ConstraintError::FORMAT_IP(), $path, ['format' => $schema->format]);
                }
                break;
            case 'ipv6':
                if (filter_var($value, \FILTER_VALIDATE_IP, \FILTER_NULL_ON_FAILURE | \FILTER_FLAG_IPV6) === null) {
                    $this->addError(ConstraintError::FORMAT_IP(), $path, ['format' => $schema->format]);
                }
                break;
            case 'color':
                if (!$this->validateColor($value)) {
                    $this->addError(ConstraintError::FORMAT_COLOR(), $path, ['format' => $schema->format]);
                }
                break;
            case 'style':
                if (!$this->validateStyle($value)) {
                    $this->addError(ConstraintError::FORMAT_STYLE(), $path, ['format' => $schema->format]);
                }
                break;
            case 'phone':
                if (!$this->validatePhone($value)) {
                    $this->addError(ConstraintError::FORMAT_PHONE(), $path, ['format' => $schema->format]);
                }
                break;
            case 'uri':
                if (!UriValidator::isValid($value)) {
                    $this->addError(ConstraintError::FORMAT_URL(), $path, ['format' => $schema->format]);
                }
                break;
            case 'uriref':
            case 'uri-reference':
                if (!(UriValidator::isValid($value) || RelativeReferenceValidator::isValid($value))) {
                    $this->addError(ConstraintError::FORMAT_URL(), $path, ['format' => $schema->format]);
                }
                break;
            case 'uri-template':
                if (!$this->validateUriTemplate($value)) {
                    $this->addError(ConstraintError::FORMAT_URI_TEMPLATE(), $path, ['format' => $schema->format]);
                }
                break;
            case 'email':
                if (filter_var($value, \FILTER_VALIDATE_EMAIL, \FILTER_NULL_ON_FAILURE | \FILTER_FLAG_EMAIL_UNICODE) === null) {
                    $this->addError(ConstraintError::FORMAT_EMAIL(), $path, ['format' => $schema->format]);
                }
                break;
            case 'host-name':
            case 'hostname':
                if (!$this->validateHostname($value)) {
                    $this->addError(ConstraintError::FORMAT_HOSTNAME(), $path, ['format' => $schema->format]);
                }
                break;
            case 'json-pointer':
                if (!$this->validateJsonPointer($value)) {
                    $this->addError(ConstraintError::FORMAT_JSON_POINTER(), $path, ['format' => $schema->format]);
                }
                break;
            default:
                break;
        }
    }
    private function validateDateTime(string $datetime, string $format): bool
    {
        $dt = \DateTime::createFromFormat($format, $datetime);
        if (!$dt) {
            return \false;
        }
        return $datetime === $dt->format($format);
    }
    private function validateRegex(string $regex): bool
    {
        return preg_match(self::jsonPatternToPhpRegex($regex), '') !== \false;
    }
    /**
     * Transform a JSON pattern into a PCRE regex
     */
    private static function jsonPatternToPhpRegex(string $pattern): string
    {
        return '~' . str_replace('~', '\~', $pattern) . '~u';
    }
    private function validateColor(string $color): bool
    {
        if (in_array(strtolower($color), ['aqua', 'black', 'blue', 'fuchsia', 'gray', 'green', 'lime', 'maroon', 'navy', 'olive', 'orange', 'purple', 'red', 'silver', 'teal', 'white', 'yellow'])) {
            return \true;
        }
        return preg_match('/^#([a-f0-9]{3}|[a-f0-9]{6})$/i', $color) !== \false;
    }
    private function validateStyle(string $style): bool
    {
        $properties = explode(';', rtrim($style, ';'));
        $invalidEntries = preg_grep('/^\s*[-a-z]+\s*:\s*.+$/i', $properties, \PREG_GREP_INVERT);
        return empty($invalidEntries);
    }
    private function validatePhone(string $phone): bool
    {
        return preg_match('/^\+?(\(\d{3}\)|\d{3}) \d{3} \d{4}$/', $phone) !== \false;
    }
    private function validateHostname(string $host): bool
    {
        $hostnameRegex = '/^(?!-)(?!.*?[^A-Za-z0-9\-\.])(?:(?!-)[A-Za-z0-9](?:[A-Za-z0-9\-]{0,61}[A-Za-z0-9])?\.)*(?!-)[A-Za-z0-9](?:[A-Za-z0-9\-]{0,61}[A-Za-z0-9])?$/';
        return preg_match($hostnameRegex, $host) === 1;
    }
    private function validateJsonPointer(string $value): bool
    {
        // Must be empty or start with a forward slash
        if ($value !== '' && $value[0] !== '/') {
            return \false;
        }
        // Split into reference tokens and check for invalid escape sequences
        $tokens = explode('/', $value);
        array_shift($tokens);
        // remove leading empty part due to leading slash
        foreach ($tokens as $token) {
            // "~" must only be followed by "0" or "1"
            if (preg_match('/~(?![01])/', $token)) {
                return \false;
            }
        }
        return \true;
    }
    private function validateRfc3339DateTime(string $value): bool
    {
        $dateTime = Rfc3339::createFromString($value);
        if (is_null($dateTime)) {
            return \false;
        }
        // Compare value and date result to be equal
        return \true;
    }
    private function validateUriTemplate(string $value): bool
    {
        return preg_match('/^(?:[^\{\}]*|\{[a-zA-Z0-9_:%\/\.~\-\+\*]+\})*$/', $value) === 1;
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\JsonSchema\Constraints\Drafts\Draft06;

use _ContaoManager\JsonSchema\ConstraintError;
use _ContaoManager\JsonSchema\Constraints\ConstraintInterface;
use _ContaoManager\JsonSchema\Entity\ErrorBagProxy;
use _ContaoManager\JsonSchema\Entity\JsonPointer;
class ContainsConstraint implements ConstraintInterface
{
    use ErrorBagProxy;
    /** @var Factory */
    private $factory;
    public function __construct(?Factory $factory = null)
    {
        $this->factory = $factory ?: new Factory();
        $this->initialiseErrorBag($this->factory);
    }
    public function check(&$value, $schema = null, ?JsonPointer $path = null, $i = null): void
    {
        if (!property_exists($schema, 'contains')) {
            return;
        }
        $properties = [];
        if (!is_array($value)) {
            return;
        }
        foreach ($value as $propertyName => $propertyValue) {
            $schemaConstraint = $this->factory->createInstanceFor('schema');
            $schemaConstraint->check($propertyValue, $schema->contains, $path, $i);
            if ($schemaConstraint->isValid()) {
                return;
            }
        }
        $this->addError(ConstraintError::CONTAINS(), $path, ['contains' => $schema->contains]);
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\JsonSchema\Constraints\Drafts\Draft06;

use _ContaoManager\JsonSchema\ConstraintError;
use _ContaoManager\JsonSchema\Constraints\ConstraintInterface;
use _ContaoManager\JsonSchema\Entity\ErrorBagProxy;
use _ContaoManager\JsonSchema\Entity\JsonPointer;
class OneOfConstraint implements ConstraintInterface
{
    use ErrorBagProxy;
    /** @var Factory */
    private $factory;
    public function __construct(?Factory $factory = null)
    {
        $this->factory = $factory ?: new Factory();
        $this->initialiseErrorBag($this->factory);
    }
    public function check(&$value, $schema = null, ?JsonPointer $path = null, $i = null): void
    {
        if (!property_exists($schema, 'oneOf')) {
            return;
        }
        $matchedSchema = 0;
        foreach ($schema->oneOf as $oneOfSchema) {
            $schemaConstraint = $this->factory->createInstanceFor('schema');
            $schemaConstraint->check($value, $oneOfSchema, $path, $i);
            if ($schemaConstraint->isValid()) {
                $matchedSchema++;
                continue;
            }
            $this->addErrors($schemaConstraint->getErrors());
        }
        if ($matchedSchema !== 1) {
            $this->addError(ConstraintError::ONE_OF(), $path);
        } else {
            $this->errorBag()->reset();
        }
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\JsonSchema\Constraints\Drafts\Draft06;

use _ContaoManager\JsonSchema\ConstraintError;
use _ContaoManager\JsonSchema\Constraints\ConstraintInterface;
use _ContaoManager\JsonSchema\Constraints\Factory;
use _ContaoManager\JsonSchema\Entity\ErrorBagProxy;
use _ContaoManager\JsonSchema\Entity\JsonPointer;
class MaxItemsConstraint implements ConstraintInterface
{
    use ErrorBagProxy;
    public function __construct(?Factory $factory = null)
    {
        $this->initialiseErrorBag($factory ?: new Factory());
    }
    public function check(&$value, $schema = null, ?JsonPointer $path = null, $i = null): void
    {
        if (!property_exists($schema, 'maxItems')) {
            return;
        }
        if (!is_array($value)) {
            return;
        }
        $count = count($value);
        if ($count <= $schema->maxItems) {
            return;
        }
        $this->addError(ConstraintError::MAX_ITEMS(), $path, ['maxItems' => $schema->maxItems, 'found' => $count]);
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\JsonSchema\Constraints\Drafts\Draft06;

use _ContaoManager\JsonSchema\ConstraintError;
use _ContaoManager\JsonSchema\Constraints\ConstraintInterface;
use _ContaoManager\JsonSchema\Constraints\Factory;
use _ContaoManager\JsonSchema\Entity\ErrorBagProxy;
use _ContaoManager\JsonSchema\Entity\JsonPointer;
class MinimumConstraint implements ConstraintInterface
{
    use ErrorBagProxy;
    public function __construct(?Factory $factory = null)
    {
        $this->initialiseErrorBag($factory ?: new Factory());
    }
    public function check(&$value, $schema = null, ?JsonPointer $path = null, $i = null): void
    {
        if (!property_exists($schema, 'minimum')) {
            return;
        }
        if (!is_numeric($value)) {
            return;
        }
        if ($value >= $schema->minimum) {
            return;
        }
        $this->addError(ConstraintError::MINIMUM(), $path, ['minimum' => $schema->minimum, 'found' => $value]);
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\JsonSchema\Constraints\Drafts\Draft06;

use _ContaoManager\JsonSchema\Constraints\ConstraintInterface;
use _ContaoManager\JsonSchema\Entity\ErrorBagProxy;
use _ContaoManager\JsonSchema\Entity\JsonPointer;
class PatternPropertiesConstraint implements ConstraintInterface
{
    use ErrorBagProxy;
    /** @var Factory */
    private $factory;
    public function __construct(?Factory $factory = null)
    {
        $this->factory = $factory ?: new Factory();
        $this->initialiseErrorBag($this->factory);
    }
    public function check(&$value, $schema = null, ?JsonPointer $path = null, $i = null): void
    {
        if (!property_exists($schema, 'patternProperties')) {
            return;
        }
        if (!is_object($value)) {
            return;
        }
        $properties = get_object_vars($value);
        foreach ($properties as $propertyName => $propertyValue) {
            foreach ($schema->patternProperties as $patternPropertyRegex => $patternPropertySchema) {
                $matchPattern = $this->createPregMatchPattern($patternPropertyRegex);
                if (preg_match($matchPattern, (string) $propertyName)) {
                    $schemaConstraint = $this->factory->createInstanceFor('schema');
                    $schemaConstraint->check($propertyValue, $patternPropertySchema, $path, $i);
                    if ($schemaConstraint->isValid()) {
                        continue;
                    }
                    $this->addErrors($schemaConstraint->getErrors());
                }
            }
        }
    }
    private function createPregMatchPattern(string $pattern): string
    {
        $replacements = [
            //            '\D' => '[^0-9]',
            '\d' => '[0-9]',
            '\p{digit}' => '[0-9]',
            //            '\w' => '[A-Za-z0-9_]',
            //            '\W' => '[^A-Za-z0-9_]',
            //            '\s' => '[\s\x{200B}]' // Explicitly include zero width white space
            '\p{Letter}' => '\p{L}',
        ];
        $pattern = str_replace(array_keys($replacements), array_values($replacements), $pattern);
        return '/' . str_replace('/', '\/', $pattern) . '/u';
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\JsonSchema\Constraints\Drafts\Draft06;

use _ContaoManager\JsonSchema\ConstraintError;
use _ContaoManager\JsonSchema\Constraints\ConstraintInterface;
use _ContaoManager\JsonSchema\Constraints\Factory;
use _ContaoManager\JsonSchema\Entity\ErrorBagProxy;
use _ContaoManager\JsonSchema\Entity\JsonPointer;
class MinLengthConstraint implements ConstraintInterface
{
    use ErrorBagProxy;
    public function __construct(?Factory $factory = null)
    {
        $this->initialiseErrorBag($factory ?: new Factory());
    }
    public function check(&$value, $schema = null, ?JsonPointer $path = null, $i = null): void
    {
        if (!property_exists($schema, 'minLength')) {
            return;
        }
        if (!is_string($value)) {
            return;
        }
        $length = mb_strlen($value);
        if ($length >= $schema->minLength) {
            return;
        }
        $this->addError(ConstraintError::LENGTH_MIN(), $path, ['minLength' => $schema->minLength, 'found' => $length]);
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\JsonSchema\Constraints\Drafts\Draft06;

use _ContaoManager\JsonSchema\ConstraintError;
use _ContaoManager\JsonSchema\Constraints\ConstraintInterface;
use _ContaoManager\JsonSchema\Constraints\Factory;
use _ContaoManager\JsonSchema\Entity\ErrorBagProxy;
use _ContaoManager\JsonSchema\Entity\JsonPointer;
class RequiredConstraint implements ConstraintInterface
{
    use ErrorBagProxy;
    public function __construct(?Factory $factory = null)
    {
        $this->initialiseErrorBag($factory ?: new Factory());
    }
    public function check(&$value, $schema = null, ?JsonPointer $path = null, $i = null): void
    {
        if (!property_exists($schema, 'required')) {
            return;
        }
        if (!is_object($value)) {
            return;
        }
        foreach ($schema->required as $required) {
            if (property_exists($value, $required)) {
                continue;
            }
            $this->addError(ConstraintError::REQUIRED(), $this->incrementPath($path, $required), ['property' => $required]);
        }
    }
    /**
     * @todo refactor as this was only copied from UndefinedConstraint
     * Bubble down the path
     *
     * @param JsonPointer|null $path Current path
     * @param mixed            $i    What to append to the path
     */
    protected function incrementPath(?JsonPointer $path, $i): JsonPointer
    {
        $path = $path ?? new JsonPointer('');
        if ($i === null || $i === '') {
            return $path;
        }
        return $path->withPropertyPaths(array_merge($path->getPropertyPaths(), [$i]));
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\JsonSchema\Constraints\Drafts\Draft06;

use _ContaoManager\JsonSchema\ConstraintError;
use _ContaoManager\JsonSchema\Constraints\ConstraintInterface;
use _ContaoManager\JsonSchema\Constraints\Factory;
use _ContaoManager\JsonSchema\Entity\ErrorBagProxy;
use _ContaoManager\JsonSchema\Entity\JsonPointer;
class MinPropertiesConstraint implements ConstraintInterface
{
    use ErrorBagProxy;
    public function __construct(?Factory $factory = null)
    {
        $this->initialiseErrorBag($factory ?: new Factory());
    }
    public function check(&$value, $schema = null, ?JsonPointer $path = null, $i = null): void
    {
        if (!property_exists($schema, 'minProperties')) {
            return;
        }
        if (!is_object($value)) {
            return;
        }
        $count = count(get_object_vars($value));
        if ($count >= $schema->minProperties) {
            return;
        }
        $this->addError(ConstraintError::PROPERTIES_MIN(), $path, ['minProperties' => $schema->minProperties, 'found' => $count]);
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of the JsonSchema package.
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\JsonSchema\Constraints;

use _ContaoManager\JsonSchema\ConstraintError;
use _ContaoManager\JsonSchema\Entity\JsonPointer;
/**
 * The Constraints Interface
 *
 * @author Robert Schönthal <seroscho@googlemail.com>
 */
interface ConstraintInterface
{
    /**
     * returns all collected errors
     */
    public function getErrors(): array;
    /**
     * adds errors to this validator
     */
    public function addErrors(array $errors): void;
    /**
     * adds an error
     *
     * @param ConstraintError $constraint the constraint/rule that is broken, e.g.: ConstraintErrors::LENGTH_MIN()
     * @param array           $more       more array elements to add to the error
     */
    public function addError(ConstraintError $constraint, ?JsonPointer $path = null, array $more = []): void;
    /**
     * checks if the validator has not raised errors
     */
    public function isValid(): bool;
    /**
     * invokes the validation of an element
     *
     * @abstract
     *
     * @param mixed $value
     * @param mixed $schema
     * @param mixed $i
     *
     * @throws \JsonSchema\Exception\ExceptionInterface
     */
    public function check(&$value, $schema = null, ?JsonPointer $path = null, $i = null): void;
}
<?php

declare (strict_types=1);
/*
 * This file is part of the JsonSchema package.
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\JsonSchema\Constraints;

use _ContaoManager\JsonSchema\ConstraintError;
use _ContaoManager\JsonSchema\Entity\JsonPointer;
use _ContaoManager\JsonSchema\Tool\DeepComparer;
/**
 * The CollectionConstraint Constraints, validates an array against a given schema
 *
 * @author Robert Schönthal <seroscho@googlemail.com>
 * @author Bruno Prieto Reis <bruno.p.reis@gmail.com>
 */
class CollectionConstraint extends Constraint
{
    /**
     * {@inheritdoc}
     */
    public function check(&$value, $schema = null, ?JsonPointer $path = null, $i = null): void
    {
        // Verify minItems
        if (isset($schema->minItems) && count($value) < $schema->minItems) {
            $this->addError(ConstraintError::MIN_ITEMS(), $path, ['minItems' => $schema->minItems, 'found' => count($value)]);
        }
        // Verify maxItems
        if (isset($schema->maxItems) && count($value) > $schema->maxItems) {
            $this->addError(ConstraintError::MAX_ITEMS(), $path, ['maxItems' => $schema->maxItems, 'found' => count($value)]);
        }
        // Verify uniqueItems
        if (isset($schema->uniqueItems) && $schema->uniqueItems) {
            $count = count($value);
            for ($x = 0; $x < $count - 1; $x++) {
                for ($y = $x + 1; $y < $count; $y++) {
                    if (DeepComparer::isEqual($value[$x], $value[$y])) {
                        $this->addError(ConstraintError::UNIQUE_ITEMS(), $path);
                        break 2;
                    }
                }
            }
        }
        $this->validateItems($value, $schema, $path, $i);
    }
    /**
     * Validates the items
     *
     * @param array     $value
     * @param \stdClass $schema
     * @param string    $i
     */
    protected function validateItems(&$value, $schema = null, ?JsonPointer $path = null, $i = null): void
    {
        if (\is_null($schema) || !isset($schema->items)) {
            return;
        }
        if ($schema->items === \true) {
            return;
        }
        if (is_object($schema->items)) {
            // just one type definition for the whole array
            foreach ($value as $k => &$v) {
                $initErrors = $this->getErrors();
                // First check if its defined in "items"
                $this->checkUndefined($v, $schema->items, $path, $k);
                // Recheck with "additionalItems" if the first test fails
                if (count($initErrors) < count($this->getErrors()) && (isset($schema->additionalItems) && $schema->additionalItems !== \false)) {
                    $secondErrors = $this->getErrors();
                    $this->checkUndefined($v, $schema->additionalItems, $path, $k);
                }
                // Reset errors if needed
                if (isset($secondErrors) && count($secondErrors) < count($this->getErrors())) {
                    $this->errors = $secondErrors;
                } elseif (isset($secondErrors) && count($secondErrors) === count($this->getErrors())) {
                    $this->errors = $initErrors;
                }
            }
            unset($v);
            /* remove dangling reference to prevent any future bugs
             * caused by accidentally using $v elsewhere */
        } else {
            // Defined item type definitions
            foreach ($value as $k => &$v) {
                if (array_key_exists($k, $schema->items)) {
                    $this->checkUndefined($v, $schema->items[$k], $path, $k);
                } else if (property_exists($schema, 'additionalItems')) {
                    if ($schema->additionalItems !== \false) {
                        $this->checkUndefined($v, $schema->additionalItems, $path, $k);
                    } else {
                        $this->addError(ConstraintError::ADDITIONAL_ITEMS(), $path, ['item' => $i, 'property' => $k, 'additionalItems' => $schema->additionalItems]);
                    }
                } else {
                    // Should be valid against an empty schema
                    $this->checkUndefined($v, new \stdClass(), $path, $k);
                }
            }
            unset($v);
            /* remove dangling reference to prevent any future bugs
             * caused by accidentally using $v elsewhere */
            // Treat when we have more schema definitions than values, not for empty arrays
            if (count($value) > 0) {
                for ($k = count($value); $k < count($schema->items); $k++) {
                    $undefinedInstance = $this->factory->createInstanceFor('undefined');
                    $this->checkUndefined($undefinedInstance, $schema->items[$k], $path, $k);
                }
            }
        }
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\JsonSchema\Constraints;

use _ContaoManager\JsonSchema\Entity\JsonPointer;
abstract class Constraint extends BaseConstraint implements ConstraintInterface
{
    /** @var string */
    protected $inlineSchemaProperty = '$schema';
    /** @deprecated CHECK_MODE_NONE is unused and will be removed in the next major release (7.0.0) */
    public const CHECK_MODE_NONE = 0x0;
    public const CHECK_MODE_NORMAL = 0x1;
    public const CHECK_MODE_TYPE_CAST = 0x2;
    public const CHECK_MODE_COERCE_TYPES = 0x4;
    public const CHECK_MODE_APPLY_DEFAULTS = 0x8;
    public const CHECK_MODE_EXCEPTIONS = 0x10;
    public const CHECK_MODE_DISABLE_FORMAT = 0x20;
    public const CHECK_MODE_EARLY_COERCE = 0x40;
    public const CHECK_MODE_ONLY_REQUIRED_DEFAULTS = 0x80;
    public const CHECK_MODE_VALIDATE_SCHEMA = 0x100;
    public const CHECK_MODE_STRICT = 0x200;
    /**
     * Bubble down the path
     *
     * @param JsonPointer|null $path Current path
     * @param mixed            $i    What to append to the path
     */
    protected function incrementPath(?JsonPointer $path, $i): JsonPointer
    {
        $path = $path ?? new JsonPointer('');
        if ($i === null || $i === '') {
            return $path;
        }
        return $path->withPropertyPaths(array_merge($path->getPropertyPaths(), [$i]));
    }
    /**
     * Validates an array
     *
     * @param mixed $value
     * @param mixed $schema
     * @param mixed $i
     */
    protected function checkArray(&$value, $schema = null, ?JsonPointer $path = null, $i = null): void
    {
        $validator = $this->factory->createInstanceFor('collection');
        $validator->check($value, $schema, $path, $i);
        $this->addErrors($validator->getErrors());
    }
    /**
     * Validates an object
     *
     * @param mixed         $value
     * @param mixed         $schema
     * @param mixed         $properties
     * @param mixed         $additionalProperties
     * @param mixed         $patternProperties
     * @param array<string> $appliedDefaults
     */
    protected function checkObject(&$value, $schema = null, ?JsonPointer $path = null, $properties = null, $additionalProperties = null, $patternProperties = null, array $appliedDefaults = []): void
    {
        /** @var ObjectConstraint $validator */
        $validator = $this->factory->createInstanceFor('object');
        $validator->check($value, $schema, $path, $properties, $additionalProperties, $patternProperties, $appliedDefaults);
        $this->addErrors($validator->getErrors());
    }
    /**
     * Validates the type of the value
     *
     * @param mixed $value
     * @param mixed $schema
     * @param mixed $i
     */
    protected function checkType(&$value, $schema = null, ?JsonPointer $path = null, $i = null): void
    {
        $validator = $this->factory->createInstanceFor('type');
        $validator->check($value, $schema, $path, $i);
        $this->addErrors($validator->getErrors());
    }
    /**
     * Checks a undefined element
     *
     * @param mixed $value
     * @param mixed $schema
     * @param mixed $i
     */
    protected function checkUndefined(&$value, $schema = null, ?JsonPointer $path = null, $i = null, bool $fromDefault = \false): void
    {
        /** @var UndefinedConstraint $validator */
        $validator = $this->factory->createInstanceFor('undefined');
        $validator->check($value, $this->factory->getSchemaStorage()->resolveRefSchema($schema), $path, $i, $fromDefault);
        $this->addErrors($validator->getErrors());
    }
    /**
     * Checks a string element
     *
     * @param mixed $value
     * @param mixed $schema
     * @param mixed $i
     */
    protected function checkString($value, $schema = null, ?JsonPointer $path = null, $i = null): void
    {
        $validator = $this->factory->createInstanceFor('string');
        $validator->check($value, $schema, $path, $i);
        $this->addErrors($validator->getErrors());
    }
    /**
     * Checks a number element
     *
     * @param mixed $value
     * @param mixed $schema
     * @param mixed $i
     */
    protected function checkNumber($value, $schema = null, ?JsonPointer $path = null, $i = null): void
    {
        $validator = $this->factory->createInstanceFor('number');
        $validator->check($value, $schema, $path, $i);
        $this->addErrors($validator->getErrors());
    }
    /**
     * Checks a enum element
     *
     * @param mixed $value
     * @param mixed $schema
     * @param mixed $i
     */
    protected function checkEnum($value, $schema = null, ?JsonPointer $path = null, $i = null): void
    {
        $validator = $this->factory->createInstanceFor('enum');
        $validator->check($value, $schema, $path, $i);
        $this->addErrors($validator->getErrors());
    }
    /**
     * Checks a const element
     *
     * @param mixed $value
     * @param mixed $schema
     * @param mixed $i
     */
    protected function checkConst($value, $schema = null, ?JsonPointer $path = null, $i = null): void
    {
        $validator = $this->factory->createInstanceFor('const');
        $validator->check($value, $schema, $path, $i);
        $this->addErrors($validator->getErrors());
    }
    /**
     * Checks format of an element
     *
     * @param mixed $value
     * @param mixed $schema
     * @param mixed $i
     */
    protected function checkFormat($value, $schema = null, ?JsonPointer $path = null, $i = null): void
    {
        $validator = $this->factory->createInstanceFor('format');
        $validator->check($value, $schema, $path, $i);
        $this->addErrors($validator->getErrors());
    }
    /**
     * Get the type check based on the set check mode.
     */
    protected function getTypeCheck(): TypeCheck\TypeCheckInterface
    {
        return $this->factory->getTypeCheck();
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of the JsonSchema package.
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\JsonSchema\Constraints;

use _ContaoManager\JsonSchema\ConstraintError;
use _ContaoManager\JsonSchema\Entity\JsonPointer;
use _ContaoManager\JsonSchema\Rfc3339;
use _ContaoManager\JsonSchema\Tool\Validator\RelativeReferenceValidator;
use _ContaoManager\JsonSchema\Tool\Validator\UriValidator;
/**
 * Validates against the "format" property
 *
 * @author Justin Rainbow <justin.rainbow@gmail.com>
 *
 * @see   http://tools.ietf.org/html/draft-zyp-json-schema-03#section-5.23
 */
class FormatConstraint extends Constraint
{
    /**
     * {@inheritdoc}
     */
    public function check(&$element, $schema = null, ?JsonPointer $path = null, $i = null): void
    {
        if (!isset($schema->format) || $this->factory->getConfig(self::CHECK_MODE_DISABLE_FORMAT)) {
            return;
        }
        switch ($schema->format) {
            case 'date':
                if (is_string($element) && !$date = $this->validateDateTime($element, 'Y-m-d')) {
                    $this->addError(ConstraintError::FORMAT_DATE(), $path, ['date' => $element, 'format' => $schema->format]);
                }
                break;
            case 'time':
                if (is_string($element) && !$this->validateDateTime($element, 'H:i:s')) {
                    $this->addError(ConstraintError::FORMAT_TIME(), $path, ['time' => json_encode($element), 'format' => $schema->format]);
                }
                break;
            case 'date-time':
                if (is_string($element) && null === Rfc3339::createFromString($element)) {
                    $this->addError(ConstraintError::FORMAT_DATE_TIME(), $path, ['dateTime' => json_encode($element), 'format' => $schema->format]);
                }
                break;
            case 'utc-millisec':
                if (!$this->validateDateTime($element, 'U')) {
                    $this->addError(ConstraintError::FORMAT_DATE_UTC(), $path, ['value' => $element, 'format' => $schema->format]);
                }
                break;
            case 'regex':
                if (!$this->validateRegex($element)) {
                    $this->addError(ConstraintError::FORMAT_REGEX(), $path, ['value' => $element, 'format' => $schema->format]);
                }
                break;
            case 'color':
                if (!$this->validateColor($element)) {
                    $this->addError(ConstraintError::FORMAT_COLOR(), $path, ['format' => $schema->format]);
                }
                break;
            case 'style':
                if (!$this->validateStyle($element)) {
                    $this->addError(ConstraintError::FORMAT_STYLE(), $path, ['format' => $schema->format]);
                }
                break;
            case 'phone':
                if (!$this->validatePhone($element)) {
                    $this->addError(ConstraintError::FORMAT_PHONE(), $path, ['format' => $schema->format]);
                }
                break;
            case 'uri':
                if (is_string($element) && !UriValidator::isValid($element)) {
                    $this->addError(ConstraintError::FORMAT_URL(), $path, ['format' => $schema->format]);
                }
                break;
            case 'uriref':
            case 'uri-reference':
                if (is_string($element) && !(UriValidator::isValid($element) || RelativeReferenceValidator::isValid($element))) {
                    $this->addError(ConstraintError::FORMAT_URL(), $path, ['format' => $schema->format]);
                }
                break;
            case 'email':
                if (is_string($element) && null === filter_var($element, \FILTER_VALIDATE_EMAIL, \FILTER_NULL_ON_FAILURE | \FILTER_FLAG_EMAIL_UNICODE)) {
                    $this->addError(ConstraintError::FORMAT_EMAIL(), $path, ['format' => $schema->format]);
                }
                break;
            case 'ip-address':
            case 'ipv4':
                if (is_string($element) && null === filter_var($element, \FILTER_VALIDATE_IP, \FILTER_NULL_ON_FAILURE | \FILTER_FLAG_IPV4)) {
                    $this->addError(ConstraintError::FORMAT_IP(), $path, ['format' => $schema->format]);
                }
                break;
            case 'ipv6':
                if (is_string($element) && null === filter_var($element, \FILTER_VALIDATE_IP, \FILTER_NULL_ON_FAILURE | \FILTER_FLAG_IPV6)) {
                    $this->addError(ConstraintError::FORMAT_IP(), $path, ['format' => $schema->format]);
                }
                break;
            case 'host-name':
            case 'hostname':
                if (!$this->validateHostname($element)) {
                    $this->addError(ConstraintError::FORMAT_HOSTNAME(), $path, ['format' => $schema->format]);
                }
                break;
            default:
                // Empty as it should be:
                // The value of this keyword is called a format attribute. It MUST be a string.
                // A format attribute can generally only validate a given set of instance types.
                // If the type of the instance to validate is not in this set, validation for
                // this format attribute and instance SHOULD succeed.
                // http://json-schema.org/latest/json-schema-validation.html#anchor105
                break;
        }
    }
    protected function validateDateTime($datetime, $format)
    {
        $dt = \DateTime::createFromFormat($format, (string) $datetime);
        if (!$dt) {
            return \false;
        }
        if ($datetime === $dt->format($format)) {
            return \true;
        }
        return \false;
    }
    protected function validateRegex($regex)
    {
        if (!is_string($regex)) {
            return \true;
        }
        return \false !== @preg_match(self::jsonPatternToPhpRegex($regex), '');
    }
    protected function validateColor($color)
    {
        if (!is_string($color)) {
            return \true;
        }
        if (in_array(strtolower($color), ['aqua', 'black', 'blue', 'fuchsia', 'gray', 'green', 'lime', 'maroon', 'navy', 'olive', 'orange', 'purple', 'red', 'silver', 'teal', 'white', 'yellow'])) {
            return \true;
        }
        return preg_match('/^#([a-f0-9]{3}|[a-f0-9]{6})$/i', $color);
    }
    protected function validateStyle($style)
    {
        $properties = explode(';', rtrim($style, ';'));
        $invalidEntries = preg_grep('/^\s*[-a-z]+\s*:\s*.+$/i', $properties, \PREG_GREP_INVERT);
        return empty($invalidEntries);
    }
    protected function validatePhone($phone)
    {
        return preg_match('/^\+?(\(\d{3}\)|\d{3}) \d{3} \d{4}$/', $phone);
    }
    protected function validateHostname($host)
    {
        if (!is_string($host)) {
            return \true;
        }
        // RFC 1035: labels are max 63 chars (1 start + 0-61 middle + 1 end)
        $hostnameRegex = '/^(?!-)(?!.*?[^A-Za-z0-9\-\.])(?:(?!-)[A-Za-z0-9](?:[A-Za-z0-9\-]{0,61}[A-Za-z0-9])?\.)*(?!-)[A-Za-z0-9](?:[A-Za-z0-9\-]{0,61}[A-Za-z0-9])?$/';
        return preg_match($hostnameRegex, $host);
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\JsonSchema\Constraints\TypeCheck;

interface TypeCheckInterface
{
    public static function isObject($value);
    public static function isArray($value);
    public static function propertyGet($value, $property);
    public static function propertySet(&$value, $property, $data);
    public static function propertyExists($value, $property);
    public static function propertyCount($value);
}
<?php

declare (strict_types=1);
namespace _ContaoManager\JsonSchema\Constraints\TypeCheck;

class StrictTypeCheck implements TypeCheckInterface
{
    public static function isObject($value)
    {
        return is_object($value);
    }
    public static function isArray($value)
    {
        return is_array($value);
    }
    public static function propertyGet($value, $property)
    {
        return $value->{$property};
    }
    public static function propertySet(&$value, $property, $data)
    {
        $value->{$property} = $data;
    }
    public static function propertyExists($value, $property)
    {
        return property_exists($value, $property);
    }
    public static function propertyCount($value)
    {
        if (!is_object($value)) {
            return 0;
        }
        return count(get_object_vars($value));
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\JsonSchema\Constraints\TypeCheck;

class LooseTypeCheck implements TypeCheckInterface
{
    public static function isObject($value)
    {
        return is_object($value) || is_array($value) && (count($value) == 0 || self::isAssociativeArray($value));
    }
    public static function isArray($value)
    {
        return is_array($value) && (count($value) == 0 || !self::isAssociativeArray($value));
    }
    public static function propertyGet($value, $property)
    {
        if (is_object($value)) {
            return $value->{$property};
        }
        return $value[$property];
    }
    public static function propertySet(&$value, $property, $data)
    {
        if (is_object($value)) {
            $value->{$property} = $data;
        } else {
            $value[$property] = $data;
        }
    }
    public static function propertyExists($value, $property)
    {
        if (is_object($value)) {
            return property_exists($value, $property);
        }
        return is_array($value) && array_key_exists($property, $value);
    }
    public static function propertyCount($value)
    {
        if (is_object($value)) {
            return count(get_object_vars($value));
        }
        return count($value);
    }
    /**
     * Check if the provided array is associative or not
     *
     * @param array $arr
     *
     * @return bool
     */
    private static function isAssociativeArray($arr)
    {
        return array_keys($arr) !== range(0, count($arr) - 1);
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\JsonSchema\Constraints;

use _ContaoManager\JsonSchema\ConstraintError;
use _ContaoManager\JsonSchema\Constraints\TypeCheck\LooseTypeCheck;
use _ContaoManager\JsonSchema\Entity\JsonPointer;
use _ContaoManager\JsonSchema\Exception\ValidationException;
use _ContaoManager\JsonSchema\Tool\DeepCopy;
use _ContaoManager\JsonSchema\Uri\UriResolver;
#[\AllowDynamicProperties]
class UndefinedConstraint extends Constraint
{
    /**
     * @var list<string> List of properties to which a default value has been applied
     */
    protected $appliedDefaults = [];
    /**
     * {@inheritdoc}
     * */
    public function check(&$value, $schema = null, ?JsonPointer $path = null, $i = null, bool $fromDefault = \false): void
    {
        if (is_null($schema) || !is_object($schema)) {
            return;
        }
        $path = $this->incrementPath($path, $i);
        if ($fromDefault) {
            $path->setFromDefault();
        }
        // check special properties
        $this->validateCommonProperties($value, $schema, $path, $i);
        // check allOf, anyOf, and oneOf properties
        $this->validateOfProperties($value, $schema, $path, '');
        // check known types
        $this->validateTypes($value, $schema, $path, $i);
    }
    /**
     * Validates the value against the types
     *
     * @param mixed       $value
     * @param mixed       $schema
     * @param JsonPointer $path
     * @param string      $i
     */
    public function validateTypes(&$value, $schema, JsonPointer $path, $i = null)
    {
        // check array
        if ($this->getTypeCheck()->isArray($value)) {
            $this->checkArray($value, $schema, $path, $i);
        }
        // check object
        if (LooseTypeCheck::isObject($value)) {
            // object processing should always be run on assoc arrays,
            // so use LooseTypeCheck here even if CHECK_MODE_TYPE_CAST
            // is not set (i.e. don't use $this->getTypeCheck() here).
            $this->checkObject($value, $schema, $path, isset($schema->properties) ? $schema->properties : null, isset($schema->additionalProperties) ? $schema->additionalProperties : null, isset($schema->patternProperties) ? $schema->patternProperties : null, $this->appliedDefaults);
        }
        // check string
        if (is_string($value)) {
            $this->checkString($value, $schema, $path, $i);
        }
        // check numeric
        if (is_numeric($value)) {
            $this->checkNumber($value, $schema, $path, $i);
        }
        // check enum
        if (isset($schema->enum)) {
            $this->checkEnum($value, $schema, $path, $i);
        }
        // check const
        if (isset($schema->const)) {
            $this->checkConst($value, $schema, $path, $i);
        }
    }
    /**
     * Validates common properties
     *
     * @param mixed       $value
     * @param mixed       $schema
     * @param JsonPointer $path
     * @param string      $i
     */
    protected function validateCommonProperties(&$value, $schema, JsonPointer $path, $i = '')
    {
        // if it extends another schema, it must pass that schema as well
        if (isset($schema->extends)) {
            if (is_string($schema->extends)) {
                $schema->extends = $this->validateUri($schema, $schema->extends);
            }
            if (is_array($schema->extends)) {
                foreach ($schema->extends as $extends) {
                    $this->checkUndefined($value, $extends, $path, $i);
                }
            } else {
                $this->checkUndefined($value, $schema->extends, $path, $i);
            }
        }
        // Apply default values from schema
        if (!$path->fromDefault()) {
            $this->applyDefaultValues($value, $schema, $path);
        }
        // Verify required values
        if ($this->getTypeCheck()->isObject($value)) {
            if (!$value instanceof self && isset($schema->required) && is_array($schema->required)) {
                // Draft 4 - Required is an array of strings - e.g. "required": ["foo", ...]
                foreach ($schema->required as $required) {
                    if (!$this->getTypeCheck()->propertyExists($value, $required)) {
                        $this->addError(ConstraintError::REQUIRED(), $this->incrementPath($path, $required), ['property' => $required]);
                    }
                }
            } elseif (isset($schema->required) && !is_array($schema->required)) {
                // Draft 3 - Required attribute - e.g. "foo": {"type": "string", "required": true}
                if ($schema->required && $value instanceof self) {
                    $propertyPaths = $path->getPropertyPaths();
                    $propertyName = end($propertyPaths);
                    $this->addError(ConstraintError::REQUIRED(), $path, ['property' => $propertyName]);
                }
            } else if ($value instanceof self) {
                return;
            }
        }
        // Verify type
        if (!$value instanceof self) {
            $this->checkType($value, $schema, $path, $i);
        }
        // Verify disallowed items
        if (isset($schema->disallow)) {
            $initErrors = $this->getErrors();
            $typeSchema = new \stdClass();
            $typeSchema->type = $schema->disallow;
            $this->checkType($value, $typeSchema, $path);
            // if no new errors were raised it must be a disallowed value
            if (count($this->getErrors()) == count($initErrors)) {
                $this->addError(ConstraintError::DISALLOW(), $path);
            } else {
                $this->errors = $initErrors;
            }
        }
        if (isset($schema->not)) {
            $initErrors = $this->getErrors();
            $this->checkUndefined($value, $schema->not, $path, $i);
            // if no new errors were raised then the instance validated against the "not" schema
            if (count($this->getErrors()) == count($initErrors)) {
                $this->addError(ConstraintError::NOT(), $path);
            } else {
                $this->errors = $initErrors;
            }
        }
        // Verify that dependencies are met
        if (isset($schema->dependencies) && $this->getTypeCheck()->isObject($value)) {
            $this->validateDependencies($value, $schema->dependencies, $path);
        }
    }
    /**
     * Check whether a default should be applied for this value
     *
     * @param mixed $schema
     * @param mixed $parentSchema
     * @param bool  $requiredOnly
     *
     * @return bool
     */
    private function shouldApplyDefaultValue($requiredOnly, $schema, $name = null, $parentSchema = null)
    {
        // required-only mode is off
        if (!$requiredOnly) {
            return \true;
        }
        // draft-04 required is set
        if ($name !== null && isset($parentSchema->required) && is_array($parentSchema->required) && in_array($name, $parentSchema->required)) {
            return \true;
        }
        // draft-03 required is set
        if (isset($schema->required) && !is_array($schema->required) && $schema->required) {
            return \true;
        }
        // default case
        return \false;
    }
    /**
     * Apply default values
     *
     * @param mixed       $value
     * @param mixed       $schema
     * @param JsonPointer $path
     */
    protected function applyDefaultValues(&$value, $schema, $path): void
    {
        // only apply defaults if feature is enabled
        if (!$this->factory->getConfig(self::CHECK_MODE_APPLY_DEFAULTS)) {
            return;
        }
        if (is_bool($schema)) {
            return;
        }
        // apply defaults if appropriate
        $requiredOnly = (bool) $this->factory->getConfig(self::CHECK_MODE_ONLY_REQUIRED_DEFAULTS);
        if (isset($schema->properties) && LooseTypeCheck::isObject($value)) {
            // $value is an object or assoc array, and properties are defined - treat as an object
            foreach ($schema->properties as $currentProperty => $propertyDefinition) {
                $propertyDefinition = $this->factory->getSchemaStorage()->resolveRefSchema($propertyDefinition);
                if (is_bool($propertyDefinition)) {
                    continue;
                }
                if (!LooseTypeCheck::propertyExists($value, $currentProperty) && property_exists($propertyDefinition, 'default') && $this->shouldApplyDefaultValue($requiredOnly, $propertyDefinition, $currentProperty, $schema)) {
                    // assign default value
                    if (is_object($propertyDefinition->default)) {
                        LooseTypeCheck::propertySet($value, $currentProperty, clone $propertyDefinition->default);
                    } else {
                        LooseTypeCheck::propertySet($value, $currentProperty, $propertyDefinition->default);
                    }
                    $this->appliedDefaults[] = $currentProperty;
                }
            }
        } elseif (isset($schema->items) && LooseTypeCheck::isArray($value)) {
            $items = [];
            if (LooseTypeCheck::isArray($schema->items)) {
                $items = $schema->items;
            } elseif (isset($schema->minItems) && count($value) < $schema->minItems) {
                $items = array_fill(count($value), $schema->minItems - count($value), $schema->items);
            }
            // $value is an array, and items are defined - treat as plain array
            foreach ($items as $currentItem => $itemDefinition) {
                $itemDefinition = $this->factory->getSchemaStorage()->resolveRefSchema($itemDefinition);
                if (is_bool($itemDefinition)) {
                    continue;
                }
                if (!array_key_exists($currentItem, $value) && property_exists($itemDefinition, 'default') && $this->shouldApplyDefaultValue($requiredOnly, $itemDefinition)) {
                    if (is_object($itemDefinition->default)) {
                        $value[$currentItem] = clone $itemDefinition->default;
                    } else {
                        $value[$currentItem] = $itemDefinition->default;
                    }
                }
                $path->setFromDefault();
            }
        } elseif ($value instanceof self && property_exists($schema, 'default') && $this->shouldApplyDefaultValue($requiredOnly, $schema)) {
            // $value is a leaf, not a container - apply the default directly
            $value = is_object($schema->default) ? clone $schema->default : $schema->default;
            $path->setFromDefault();
        }
    }
    /**
     * Validate allOf, anyOf, and oneOf properties
     *
     * @param mixed       $value
     * @param mixed       $schema
     * @param JsonPointer $path
     * @param string      $i
     */
    protected function validateOfProperties(&$value, $schema, JsonPointer $path, $i = '')
    {
        // Verify type
        if ($value instanceof self) {
            return;
        }
        if (isset($schema->allOf)) {
            $isValid = \true;
            foreach ($schema->allOf as $allOf) {
                $initErrors = $this->getErrors();
                $this->checkUndefined($value, $allOf, $path, $i);
                $isValid = $isValid && count($this->getErrors()) == count($initErrors);
            }
            if (!$isValid) {
                $this->addError(ConstraintError::ALL_OF(), $path);
            }
        }
        if (isset($schema->anyOf)) {
            $isValid = \false;
            $startErrors = $this->getErrors();
            $coerceOrDefaults = $this->factory->getConfig(self::CHECK_MODE_COERCE_TYPES | self::CHECK_MODE_APPLY_DEFAULTS);
            foreach ($schema->anyOf as $anyOf) {
                $initErrors = $this->getErrors();
                try {
                    $anyOfValue = $coerceOrDefaults ? DeepCopy::copyOf($value) : $value;
                    $this->checkUndefined($anyOfValue, $anyOf, $path, $i);
                    if ($isValid = count($this->getErrors()) === count($initErrors)) {
                        $value = $anyOfValue;
                        break;
                    }
                } catch (ValidationException $e) {
                    $isValid = \false;
                }
            }
            if (!$isValid) {
                $this->addError(ConstraintError::ANY_OF(), $path);
            } else {
                $this->errors = $startErrors;
            }
        }
        if (isset($schema->oneOf)) {
            $allErrors = [];
            $matchedSchemas = [];
            $startErrors = $this->getErrors();
            $coerceOrDefaults = $this->factory->getConfig(self::CHECK_MODE_COERCE_TYPES | self::CHECK_MODE_APPLY_DEFAULTS);
            foreach ($schema->oneOf as $oneOf) {
                try {
                    $this->errors = [];
                    $oneOfValue = $coerceOrDefaults ? DeepCopy::copyOf($value) : $value;
                    $this->checkUndefined($oneOfValue, $oneOf, $path, $i);
                    if (count($this->getErrors()) === 0) {
                        $matchedSchemas[] = ['schema' => $oneOf, 'value' => $oneOfValue];
                    }
                    $allErrors = array_merge($allErrors, array_values($this->getErrors()));
                } catch (ValidationException $e) {
                    // deliberately do nothing here - validation failed, but we want to check
                    // other schema options in the OneOf field.
                }
            }
            if (count($matchedSchemas) !== 1) {
                $this->addErrors(array_merge($allErrors, $startErrors));
                $this->addError(ConstraintError::ONE_OF(), $path);
            } else {
                $this->errors = $startErrors;
                $value = $matchedSchemas[0]['value'];
            }
        }
    }
    /**
     * Validate dependencies
     *
     * @param mixed       $value
     * @param mixed       $dependencies
     * @param JsonPointer $path
     * @param string      $i
     */
    protected function validateDependencies($value, $dependencies, JsonPointer $path, $i = '')
    {
        foreach ($dependencies as $key => $dependency) {
            if ($this->getTypeCheck()->propertyExists($value, $key)) {
                if (is_string($dependency)) {
                    // Draft 3 string is allowed - e.g. "dependencies": {"bar": "foo"}
                    if (!$this->getTypeCheck()->propertyExists($value, $dependency)) {
                        $this->addError(ConstraintError::DEPENDENCIES(), $path, ['key' => $key, 'dependency' => $dependency]);
                    }
                } elseif (is_array($dependency)) {
                    // Draft 4 must be an array - e.g. "dependencies": {"bar": ["foo"]}
                    foreach ($dependency as $d) {
                        if (!$this->getTypeCheck()->propertyExists($value, $d)) {
                            $this->addError(ConstraintError::DEPENDENCIES(), $path, ['key' => $key, 'dependency' => $dependency]);
                        }
                    }
                } elseif (is_object($dependency)) {
                    // Schema - e.g. "dependencies": {"bar": {"properties": {"foo": {...}}}}
                    $this->checkUndefined($value, $dependency, $path, $i);
                }
            }
        }
    }
    protected function validateUri($schema, $schemaUri = null)
    {
        $resolver = new UriResolver();
        $retriever = $this->factory->getUriRetriever();
        $jsonSchema = null;
        if ($resolver->isValid($schemaUri)) {
            $schemaId = property_exists($schema, 'id') ? $schema->id : null;
            $jsonSchema = $retriever->retrieve($schemaId, $schemaUri);
        }
        return $jsonSchema;
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of the JsonSchema package.
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\JsonSchema\Constraints;

use _ContaoManager\JsonSchema\ConstraintError;
use _ContaoManager\JsonSchema\DraftIdentifiers;
use _ContaoManager\JsonSchema\Entity\JsonPointer;
use _ContaoManager\JsonSchema\Exception\InvalidArgumentException;
use _ContaoManager\JsonSchema\Exception\InvalidSchemaException;
use _ContaoManager\JsonSchema\Exception\RuntimeException;
use _ContaoManager\JsonSchema\Validator;
/**
 * The SchemaConstraint Constraints, validates an element against a given schema
 *
 * @author Robert Schönthal <seroscho@googlemail.com>
 * @author Bruno Prieto Reis <bruno.p.reis@gmail.com>
 */
class SchemaConstraint extends Constraint
{
    private const DEFAULT_SCHEMA_SPEC = DraftIdentifiers::DRAFT_4;
    /**
     * {@inheritdoc}
     */
    public function check(&$element, $schema = null, ?JsonPointer $path = null, $i = null): void
    {
        if ($schema !== null) {
            // passed schema
            $validationSchema = $schema;
        } elseif ($this->getTypeCheck()->propertyExists($element, $this->inlineSchemaProperty)) {
            // inline schema
            $validationSchema = $this->getTypeCheck()->propertyGet($element, $this->inlineSchemaProperty);
        } else {
            throw new InvalidArgumentException('no schema found to verify against');
        }
        // cast array schemas to object
        if (is_array($validationSchema)) {
            $validationSchema = BaseConstraint::arrayToObjectRecursive($validationSchema);
        }
        // validate schema against whatever is defined in $validationSchema->$schema. If no
        // schema is defined, assume self::DEFAULT_SCHEMA_SPEC (currently draft-04).
        if ($this->factory->getConfig(self::CHECK_MODE_VALIDATE_SCHEMA)) {
            if (!$this->getTypeCheck()->isObject($validationSchema)) {
                throw new RuntimeException('Cannot validate the schema of a non-object');
            }
            if ($this->getTypeCheck()->propertyExists($validationSchema, '$schema')) {
                $schemaSpec = $this->getTypeCheck()->propertyGet($validationSchema, '$schema');
            } else {
                $schemaSpec = self::DEFAULT_SCHEMA_SPEC;
            }
            // get the spec schema
            $schemaStorage = $this->factory->getSchemaStorage();
            if (!$this->getTypeCheck()->isObject($schemaSpec)) {
                $schemaSpec = $schemaStorage->getSchema($schemaSpec);
            }
            // save error count, config & subtract CHECK_MODE_VALIDATE_SCHEMA
            $initialErrorCount = $this->numErrors();
            $initialConfig = $this->factory->getConfig();
            $initialContext = $this->factory->getErrorContext();
            $this->factory->removeConfig(self::CHECK_MODE_VALIDATE_SCHEMA | self::CHECK_MODE_APPLY_DEFAULTS);
            $this->factory->addConfig(self::CHECK_MODE_TYPE_CAST);
            $this->factory->setErrorContext(Validator::ERROR_SCHEMA_VALIDATION);
            // validate schema
            try {
                $this->check($validationSchema, $schemaSpec);
            } catch (\Exception $e) {
                if ($this->factory->getConfig(self::CHECK_MODE_EXCEPTIONS)) {
                    throw new InvalidSchemaException('Schema did not pass validation', 0, $e);
                }
            }
            if ($this->numErrors() > $initialErrorCount) {
                $this->addError(ConstraintError::INVALID_SCHEMA(), $path);
            }
            // restore the initial config
            $this->factory->setConfig($initialConfig);
            $this->factory->setErrorContext($initialContext);
        }
        // validate element against $validationSchema
        $this->checkUndefined($element, $validationSchema, $path, $i);
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\JsonSchema;

abstract class Enum extends \_ContaoManager\MabeEnum\Enum
{
}
<?php

declare (strict_types=1);
namespace _ContaoManager\JsonSchema\Entity;

use _ContaoManager\JsonSchema\ConstraintError;
use _ContaoManager\JsonSchema\Constraints\Constraint;
use _ContaoManager\JsonSchema\Constraints\Factory;
use _ContaoManager\JsonSchema\Exception\ValidationException;
use _ContaoManager\JsonSchema\Validator;
/**
 * @phpstan-type Error array{
 *     "property": string,
 *     "pointer": string,
 *     "message": string,
 *     "constraint": array{"name": string, "params": array<string, mixed>},
 *     "context": int-mask-of<Validator::ERROR_*>
 * }
 * @phpstan-type ErrorList list<Error>
 */
class ErrorBag
{
    /** @var Factory */
    private $factory;
    /** @var ErrorList */
    private $errors = [];
    /**
     * @var int-mask-of<Validator::ERROR_*> All error types that have occurred
     */
    protected $errorMask = Validator::ERROR_NONE;
    public function __construct(Factory $factory)
    {
        $this->factory = $factory;
    }
    public function reset(): void
    {
        $this->errors = [];
        $this->errorMask = Validator::ERROR_NONE;
    }
    /** @return ErrorList */
    public function getErrors(): array
    {
        return $this->errors;
    }
    /** @param array<string, mixed> $more */
    public function addError(ConstraintError $constraint, ?JsonPointer $path = null, array $more = []): void
    {
        $message = $constraint->getMessage();
        $name = $constraint->getValue();
        /** @var Error $error */
        $error = ['property' => $this->convertJsonPointerIntoPropertyPath($path ?: new JsonPointer('')), 'pointer' => ltrim((string) ($path ?: new JsonPointer('')), '#'), 'message' => ucfirst(vsprintf($message, array_map(static function ($val) {
            if (is_scalar($val)) {
                return is_bool($val) ? var_export($val, \true) : $val;
            }
            return json_encode($val);
        }, array_values($more)))), 'constraint' => ['name' => $name, 'params' => $more], 'context' => $this->factory->getErrorContext()];
        if ($this->factory->getConfig(Constraint::CHECK_MODE_EXCEPTIONS)) {
            throw new ValidationException(sprintf('Error validating %s: %s', $error['pointer'], $error['message']));
        }
        $this->errors[] = $error;
        /* @see https://github.com/phpstan/phpstan/issues/9384 */
        $this->errorMask |= $error['context'];
        // @phpstan-ignore assign.propertyType
    }
    /** @param ErrorList $errors */
    public function addErrors(array $errors): void
    {
        if (!$errors) {
            return;
        }
        $this->errors = array_merge($this->errors, $errors);
        $errorMask =& $this->errorMask;
        array_walk($errors, static function ($error) use (&$errorMask) {
            $errorMask |= $error['context'];
        });
    }
    private function convertJsonPointerIntoPropertyPath(JsonPointer $pointer): string
    {
        $result = array_map(static function ($path) {
            return sprintf(is_numeric($path) ? '[%d]' : '.%s', $path);
        }, $pointer->getPropertyPaths());
        return trim(implode('', $result), '.');
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of the JsonSchema package.
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\JsonSchema\Entity;

use _ContaoManager\JsonSchema\Exception\InvalidArgumentException;
/**
 * @package JsonSchema\Entity
 *
 * @author Joost Nijhuis <jnijhuis81@gmail.com>
 */
class JsonPointer
{
    /** @var string */
    private $filename;
    /** @var string[] */
    private $propertyPaths = [];
    /**
     * @var bool Whether the value at this path was set from a schema default
     */
    private $fromDefault = \false;
    /**
     * @param string $value
     *
     * @throws InvalidArgumentException when $value is not a string
     */
    public function __construct($value)
    {
        if (!is_string($value)) {
            throw new InvalidArgumentException('Ref value must be a string');
        }
        $splitRef = explode('#', $value, 2);
        $this->filename = $splitRef[0];
        if (array_key_exists(1, $splitRef)) {
            $this->propertyPaths = $this->decodePropertyPaths($splitRef[1]);
        }
    }
    /**
     * @param string $propertyPathString
     *
     * @return string[]
     */
    private function decodePropertyPaths($propertyPathString)
    {
        $paths = [];
        foreach (explode('/', trim($propertyPathString, '/')) as $path) {
            $path = $this->decodePath($path);
            if (is_string($path) && '' !== $path) {
                $paths[] = $path;
            }
        }
        return $paths;
    }
    /**
     * @return array
     */
    private function encodePropertyPaths()
    {
        return array_map([$this, 'encodePath'], $this->getPropertyPaths());
    }
    /**
     * @param string $path
     *
     * @return string
     */
    private function decodePath($path)
    {
        return strtr($path, ['~1' => '/', '~0' => '~', '%25' => '%']);
    }
    /**
     * @param string $path
     *
     * @return string
     */
    private function encodePath($path)
    {
        return strtr($path, ['/' => '~1', '~' => '~0', '%' => '%25']);
    }
    /**
     * @return string
     */
    public function getFilename()
    {
        return $this->filename;
    }
    /**
     * @return string[]
     */
    public function getPropertyPaths()
    {
        return $this->propertyPaths;
    }
    /**
     * @param array $propertyPaths
     *
     * @return JsonPointer
     */
    public function withPropertyPaths(array $propertyPaths)
    {
        $new = clone $this;
        $new->propertyPaths = array_map(function ($p): string {
            return (string) $p;
        }, $propertyPaths);
        return $new;
    }
    /**
     * @return string
     */
    public function getPropertyPathAsString()
    {
        return rtrim('#/' . implode('/', $this->encodePropertyPaths()), '/');
    }
    /**
     * @return string
     */
    public function __toString()
    {
        return $this->getFilename() . $this->getPropertyPathAsString();
    }
    /**
     * Mark the value at this path as being set from a schema default
     */
    public function setFromDefault(): void
    {
        $this->fromDefault = \true;
    }
    /**
     * Check whether the value at this path was set from a schema default
     *
     * @return bool
     */
    public function fromDefault()
    {
        return $this->fromDefault;
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\JsonSchema\Entity;

use _ContaoManager\JsonSchema\ConstraintError;
use _ContaoManager\JsonSchema\Constraints\Factory;
/**
 * @phpstan-import-type Error from ErrorBag
 * @phpstan-import-type ErrorList from ErrorBag
 */
trait ErrorBagProxy
{
    /** @var ?ErrorBag */
    protected $errorBag = null;
    /** @return ErrorList */
    public function getErrors(): array
    {
        return $this->errorBag()->getErrors();
    }
    /** @param ErrorList $errors */
    public function addErrors(array $errors): void
    {
        $this->errorBag()->addErrors($errors);
    }
    /**
     * @param array<string, mixed> $more more array elements to add to the error
     */
    public function addError(ConstraintError $constraint, ?JsonPointer $path = null, array $more = []): void
    {
        $this->errorBag()->addError($constraint, $path, $more);
    }
    public function isValid(): bool
    {
        return $this->errorBag()->getErrors() === [];
    }
    protected function initialiseErrorBag(Factory $factory): ErrorBag
    {
        if (is_null($this->errorBag)) {
            $this->errorBag = new ErrorBag($factory);
        }
        return $this->errorBag;
    }
    protected function errorBag(): ErrorBag
    {
        if (is_null($this->errorBag)) {
            throw new \RuntimeException('ErrorBag not initialized');
        }
        return $this->errorBag;
    }
    public function __clone()
    {
        $this->errorBag()->reset();
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of the JsonSchema package.
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\JsonSchema;

/**
 * @package JsonSchema
 */
interface UriResolverInterface
{
    /**
     * Resolves a URI
     *
     * @param string      $uri     Absolute or relative
     * @param null|string $baseUri Optional base URI
     *
     * @return string Absolute URI
     */
    public function resolve($uri, $baseUri = null);
}
<?php

declare (strict_types=1);
namespace _ContaoManager\JsonSchema;

use _ContaoManager\JsonSchema\Exception\InvalidArgumentException;
class ConstraintError extends Enum
{
    public const ADDITIONAL_ITEMS = 'additionalItems';
    public const ADDITIONAL_PROPERTIES = 'additionalProp';
    public const ALL_OF = 'allOf';
    public const ANY_OF = 'anyOf';
    public const DEPENDENCIES = 'dependencies';
    public const DISALLOW = 'disallow';
    public const DIVISIBLE_BY = 'divisibleBy';
    public const ENUM = 'enum';
    public const CONSTANT = 'const';
    public const CONTAINS = 'contains';
    public const EXCLUSIVE_MINIMUM = 'exclusiveMinimum';
    public const EXCLUSIVE_MAXIMUM = 'exclusiveMaximum';
    public const FALSE = 'false';
    public const FORMAT_COLOR = 'colorFormat';
    public const FORMAT_DATE = 'dateFormat';
    public const FORMAT_DATE_TIME = 'dateTimeFormat';
    public const FORMAT_DATE_UTC = 'dateUtcFormat';
    public const FORMAT_EMAIL = 'emailFormat';
    public const FORMAT_HOSTNAME = 'styleHostName';
    public const FORMAT_IP = 'ipFormat';
    public const FORMAT_JSON_POINTER = 'jsonPointerFormat';
    public const FORMAT_PHONE = 'phoneFormat';
    public const FORMAT_REGEX = 'regexFormat';
    public const FORMAT_STYLE = 'styleFormat';
    public const FORMAT_TIME = 'timeFormat';
    public const FORMAT_URI_TEMPLATE = 'uriTemplateFormat';
    public const FORMAT_URL = 'urlFormat';
    public const FORMAT_URL_REF = 'urlRefFormat';
    public const INVALID_SCHEMA = 'invalidSchema';
    public const LENGTH_MAX = 'maxLength';
    public const LENGTH_MIN = 'minLength';
    public const MAXIMUM = 'maximum';
    public const MIN_ITEMS = 'minItems';
    public const MINIMUM = 'minimum';
    public const MISSING_ERROR = 'missingError';
    public const MISSING_MAXIMUM = 'missingMaximum';
    public const MISSING_MINIMUM = 'missingMinimum';
    public const MAX_ITEMS = 'maxItems';
    public const MULTIPLE_OF = 'multipleOf';
    public const NOT = 'not';
    public const ONE_OF = 'oneOf';
    public const REQUIRED = 'required';
    public const REQUIRES = 'requires';
    public const PATTERN = 'pattern';
    public const PREGEX_INVALID = 'pregrex';
    public const PROPERTIES_MIN = 'minProperties';
    public const PROPERTIES_MAX = 'maxProperties';
    public const PROPERTY_NAMES = 'propertyNames';
    public const TYPE = 'type';
    public const UNIQUE_ITEMS = 'uniqueItems';
    public const CONTENT_MEDIA_TYPE = 'contentMediaType';
    public const CONTENT_ENCODING = 'contentEncoding';
    /**
     * @return string
     */
    public function getMessage()
    {
        $name = $this->getValue();
        static $messages = [
            self::ADDITIONAL_ITEMS => 'The item %s[%s] is not defined and the definition does not allow additional items',
            self::ADDITIONAL_PROPERTIES => 'The property %s is not defined and the definition does not allow additional properties',
            self::ALL_OF => 'Failed to match all schemas',
            self::ANY_OF => 'Failed to match at least one schema',
            self::DEPENDENCIES => '%s depends on %s, which is missing',
            self::DISALLOW => 'Disallowed value was matched',
            self::DIVISIBLE_BY => 'Is not divisible by %d',
            self::ENUM => 'Does not have a value in the enumeration %s',
            self::CONSTANT => 'Does not have a value equal to %s',
            self::CONTAINS => 'Does not have a value valid to contains schema',
            self::EXCLUSIVE_MINIMUM => 'Must have a minimum value greater than %d',
            self::EXCLUSIVE_MAXIMUM => 'Must have a maximum value less than %d',
            self::FALSE => 'Boolean schema false',
            self::FORMAT_COLOR => 'Invalid color',
            self::FORMAT_DATE => 'Invalid date %s, expected format YYYY-MM-DD',
            self::FORMAT_DATE_TIME => 'Invalid date-time %s, expected format YYYY-MM-DDThh:mm:ssZ or YYYY-MM-DDThh:mm:ss+hh:mm',
            self::FORMAT_DATE_UTC => 'Invalid time %s, expected integer of milliseconds since Epoch',
            self::FORMAT_EMAIL => 'Invalid email',
            self::FORMAT_HOSTNAME => 'Invalid hostname',
            self::FORMAT_IP => 'Invalid IP address',
            self::FORMAT_JSON_POINTER => 'Invalid JSON pointer',
            self::FORMAT_PHONE => 'Invalid phone number',
            self::FORMAT_REGEX => 'Invalid regex format %s',
            self::FORMAT_STYLE => 'Invalid style',
            self::FORMAT_TIME => 'Invalid time %s, expected format hh:mm:ss',
            self::FORMAT_URI_TEMPLATE => 'Invalid URI template format',
            self::FORMAT_URL => 'Invalid URL format',
            self::FORMAT_URL_REF => 'Invalid URL reference format',
            self::LENGTH_MAX => 'Must be at most %d characters long',
            self::INVALID_SCHEMA => 'Schema is not valid',
            self::LENGTH_MIN => 'Must be at least %d characters long',
            self::MAX_ITEMS => 'There must be a maximum of %d items in the array, %d found',
            self::MAXIMUM => 'Must have a maximum value less than or equal to %d',
            self::MIN_ITEMS => 'There must be a minimum of %d items in the array, %d found',
            self::MINIMUM => 'Must have a minimum value greater than or equal to %d',
            self::MISSING_MAXIMUM => 'Use of exclusiveMaximum requires presence of maximum',
            self::MISSING_MINIMUM => 'Use of exclusiveMinimum requires presence of minimum',
            /*self::MISSING_ERROR => 'Used for tests; this error is deliberately commented out',*/
            self::MULTIPLE_OF => 'Must be a multiple of %s',
            self::NOT => 'Matched a schema which it should not',
            self::ONE_OF => 'Failed to match exactly one schema',
            self::REQUIRED => 'The property %s is required',
            self::REQUIRES => 'The presence of the property %s requires that %s also be present',
            self::PATTERN => 'Does not match the regex pattern %s',
            self::PREGEX_INVALID => 'The pattern %s is invalid',
            self::PROPERTIES_MIN => 'Must contain a minimum of %d properties',
            self::PROPERTIES_MAX => 'Must contain no more than %d properties',
            self::PROPERTY_NAMES => 'Property name %s is invalid',
            self::TYPE => '%s value found, but %s is required',
            self::UNIQUE_ITEMS => 'There are no duplicates allowed in the array',
            self::CONTENT_MEDIA_TYPE => 'Value is not valid with content media type',
            self::CONTENT_ENCODING => 'Value is not valid with content encoding',
        ];
        if (!isset($messages[$name])) {
            throw new InvalidArgumentException('Missing error message for ' . $name);
        }
        return $messages[$name];
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of the JsonSchema package.
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\JsonSchema\Iterator;

/**
 * @package JsonSchema\Iterator
 *
 * @author Joost Nijhuis <jnijhuis81@gmail.com>
 */
class ObjectIterator implements \Iterator, \Countable
{
    /** @var object */
    private $object;
    /** @var int */
    private $position = 0;
    /** @var array */
    private $data = [];
    /** @var bool */
    private $initialized = \false;
    /**
     * @param object $object
     */
    public function __construct($object)
    {
        $this->object = $object;
    }
    /**
     * {@inheritdoc}
     */
    #[\ReturnTypeWillChange]
    public function current()
    {
        $this->initialize();
        return $this->data[$this->position];
    }
    /**
     * {@inheritdoc}
     */
    public function next(): void
    {
        $this->initialize();
        $this->position++;
    }
    /**
     * {@inheritdoc}
     */
    public function key(): int
    {
        $this->initialize();
        return $this->position;
    }
    /**
     * {@inheritdoc}
     */
    public function valid(): bool
    {
        $this->initialize();
        return isset($this->data[$this->position]);
    }
    /**
     * {@inheritdoc}
     */
    public function rewind(): void
    {
        $this->initialize();
        $this->position = 0;
    }
    /**
     * {@inheritdoc}
     */
    public function count(): int
    {
        $this->initialize();
        return count($this->data);
    }
    /**
     * Initializer
     */
    private function initialize()
    {
        if (!$this->initialized) {
            $this->data = $this->buildDataFromObject($this->object);
            $this->initialized = \true;
        }
    }
    /**
     * @param object $object
     *
     * @return array
     */
    private function buildDataFromObject($object)
    {
        $result = [];
        $stack = new \SplStack();
        $stack->push($object);
        while (!$stack->isEmpty()) {
            $current = $stack->pop();
            if (is_object($current)) {
                array_push($result, $current);
            }
            foreach ($this->getDataFromItem($current) as $propertyName => $propertyValue) {
                if (is_object($propertyValue) || is_array($propertyValue)) {
                    $stack->push($propertyValue);
                }
            }
        }
        return $result;
    }
    /**
     * @param object|array $item
     *
     * @return array
     */
    private function getDataFromItem($item)
    {
        if (!is_object($item) && !is_array($item)) {
            return [];
        }
        return is_object($item) ? get_object_vars($item) : $item;
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\JsonSchema;

use _ContaoManager\JsonSchema\Constraints\BaseConstraint;
use _ContaoManager\JsonSchema\Entity\JsonPointer;
use _ContaoManager\JsonSchema\Exception\UnresolvableJsonPointerException;
use _ContaoManager\JsonSchema\Uri\UriResolver;
use _ContaoManager\JsonSchema\Uri\UriRetriever;
class SchemaStorage implements SchemaStorageInterface
{
    public const INTERNAL_PROVIDED_SCHEMA_URI = 'internal://provided-schema/';
    protected $uriRetriever;
    protected $uriResolver;
    protected $schemas = [];
    public function __construct(?UriRetrieverInterface $uriRetriever = null, ?UriResolverInterface $uriResolver = null)
    {
        $this->uriRetriever = $uriRetriever ?: new UriRetriever();
        $this->uriResolver = $uriResolver ?: new UriResolver();
    }
    /**
     * @return UriRetrieverInterface
     */
    public function getUriRetriever()
    {
        return $this->uriRetriever;
    }
    /**
     * @return UriResolverInterface
     */
    public function getUriResolver()
    {
        return $this->uriResolver;
    }
    /**
     * {@inheritdoc}
     */
    public function addSchema(string $id, $schema = null): void
    {
        if (is_null($schema) && $id !== self::INTERNAL_PROVIDED_SCHEMA_URI) {
            // if the schema was user-provided to Validator and is still null, then assume this is
            // what the user intended, as there's no way for us to retrieve anything else. User-supplied
            // schemas do not have an associated URI when passed via Validator::validate().
            $schema = $this->uriRetriever->retrieve($id);
        }
        // cast array schemas to object
        if (is_array($schema)) {
            $schema = BaseConstraint::arrayToObjectRecursive($schema);
        }
        // workaround for bug in draft-03 & draft-04 meta-schemas (id & $ref defined with incorrect format)
        // see https://github.com/json-schema-org/JSON-Schema-Test-Suite/issues/177#issuecomment-293051367
        if (is_object($schema) && property_exists($schema, 'id')) {
            if ($schema->id === DraftIdentifiers::DRAFT_4) {
                $schema->properties->id->format = 'uri-reference';
            } elseif ($schema->id === DraftIdentifiers::DRAFT_3) {
                $schema->properties->id->format = 'uri-reference';
                $schema->properties->{'$ref'}->format = 'uri-reference';
            }
        }
        $this->scanForSubschemas($schema, $id);
        // resolve references
        $this->expandRefs($schema, $id);
        $this->schemas[$id] = $schema;
    }
    /**
     * Recursively resolve all references against the provided base
     *
     * @param mixed        $schema
     * @param list<string> $propertyStack
     */
    private function expandRefs(&$schema, ?string $parentId = null, array $propertyStack = []): void
    {
        if (!is_object($schema)) {
            if (is_array($schema)) {
                foreach ($schema as &$member) {
                    $this->expandRefs($member, $parentId);
                }
            }
            return;
        }
        if (property_exists($schema, '$ref') && is_string($schema->{'$ref'})) {
            $refPointer = new JsonPointer($this->uriResolver->resolve($schema->{'$ref'}, $parentId));
            $schema->{'$ref'} = (string) $refPointer;
        }
        $parentProperty = array_slice($propertyStack, -1)[0] ?? '';
        foreach ($schema as $propertyName => &$member) {
            if ($parentProperty !== 'properties' && in_array($propertyName, ['enum', 'const'])) {
                // Enum and const don't allow $ref as a keyword, see https://github.com/json-schema-org/JSON-Schema-Test-Suite/pull/445
                continue;
            }
            $schemaId = $this->findSchemaIdInObject($schema);
            $childId = $parentId;
            if (is_string($schemaId) && $childId !== $schemaId) {
                $childId = $this->uriResolver->resolve($schemaId, $childId);
            }
            $clonedPropertyStack = $propertyStack;
            $clonedPropertyStack[] = $propertyName;
            $this->expandRefs($member, $childId, $clonedPropertyStack);
        }
    }
    /**
     * {@inheritdoc}
     */
    public function getSchema(string $id)
    {
        if (!array_key_exists($id, $this->schemas)) {
            $this->addSchema($id);
        }
        return $this->schemas[$id];
    }
    /**
     * {@inheritdoc}
     */
    public function resolveRef(string $ref, $resolveStack = [])
    {
        $jsonPointer = new JsonPointer($ref);
        // resolve filename for pointer
        $fileName = $jsonPointer->getFilename();
        if (!strlen($fileName)) {
            throw new UnresolvableJsonPointerException(sprintf("Could not resolve fragment '%s': no file is defined", $jsonPointer->getPropertyPathAsString()));
        }
        // get & process the schema
        $refSchema = $this->getSchema($fileName);
        foreach ($jsonPointer->getPropertyPaths() as $path) {
            $path = urldecode($path);
            if (is_object($refSchema) && property_exists($refSchema, $path)) {
                $refSchema = $this->resolveRefSchema($refSchema->{$path}, $resolveStack);
            } elseif (is_array($refSchema) && array_key_exists($path, $refSchema)) {
                $refSchema = $this->resolveRefSchema($refSchema[$path], $resolveStack);
            } else {
                throw new UnresolvableJsonPointerException(sprintf('File: %s is found, but could not resolve fragment: %s', $jsonPointer->getFilename(), $jsonPointer->getPropertyPathAsString()));
            }
        }
        return $refSchema;
    }
    /**
     * {@inheritdoc}
     */
    public function resolveRefSchema($refSchema, $resolveStack = [])
    {
        if (is_object($refSchema) && property_exists($refSchema, '$ref') && is_string($refSchema->{'$ref'})) {
            if (in_array($refSchema, $resolveStack, \true)) {
                throw new UnresolvableJsonPointerException(sprintf('Dereferencing a pointer to %s results in an infinite loop', $refSchema->{'$ref'}));
            }
            $resolveStack[] = $refSchema;
            return $this->resolveRef($refSchema->{'$ref'}, $resolveStack);
        }
        if (is_object($refSchema) && array_keys(get_object_vars($refSchema)) === ['']) {
            $refSchema = get_object_vars($refSchema)[''];
        }
        return $refSchema;
    }
    /**
     * @param mixed $schema
     */
    private function scanForSubschemas($schema, string $parentId): void
    {
        if (!$schema instanceof \stdClass && !is_array($schema)) {
            return;
        }
        foreach ($schema as $propertyName => $potentialSubSchema) {
            if (!is_object($potentialSubSchema)) {
                if (is_array($potentialSubSchema)) {
                    foreach ($potentialSubSchema as $potentialSubSchemaItem) {
                        $this->scanForSubschemas($potentialSubSchemaItem, $parentId);
                    }
                }
                continue;
            }
            $potentialSubSchemaId = $this->findSchemaIdInObject($potentialSubSchema);
            if (is_string($potentialSubSchemaId) && property_exists($potentialSubSchema, 'type')) {
                // Enum and const don't allow id as a keyword, see https://github.com/json-schema-org/JSON-Schema-Test-Suite/pull/471
                if (in_array($propertyName, ['enum', 'const'])) {
                    continue;
                }
                // $id in unknow keywords is not valid
                if (in_array($propertyName, [])) {
                    continue;
                }
                // Found sub schema
                $this->addSchema($this->uriResolver->resolve($potentialSubSchemaId, $parentId), $potentialSubSchema);
            }
            $this->scanForSubschemas($potentialSubSchema, $parentId);
        }
    }
    private function findSchemaIdInObject(object $schema): ?string
    {
        if (property_exists($schema, 'id') && is_string($schema->id)) {
            return $schema->id;
        }
        if (property_exists($schema, '$id') && is_string($schema->{'$id'})) {
            return $schema->{'$id'};
        }
        return null;
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\JsonSchema;

/**
 * @method static DraftIdentifiers DRAFT_3()
 * @method static DraftIdentifiers DRAFT_4()
 * @method static DraftIdentifiers DRAFT_6()
 * @method static DraftIdentifiers DRAFT_7()
 * @method static DraftIdentifiers DRAFT_2019_09()
 * @method static DraftIdentifiers DRAFT_2020_12()
 */
class DraftIdentifiers extends Enum
{
    public const DRAFT_3 = 'http://json-schema.org/draft-03/schema#';
    public const DRAFT_4 = 'http://json-schema.org/draft-04/schema#';
    public const DRAFT_6 = 'http://json-schema.org/draft-06/schema#';
    public const DRAFT_7 = 'http://json-schema.org/draft-07/schema#';
    public const DRAFT_2019_09 = 'https://json-schema.org/draft/2019-09/schema';
    public const DRAFT_2020_12 = 'https://json-schema.org/draft/2020-12/schema';
    /** @var array<DraftIdentifiers::DRAFT_*, string> */
    private const MAPPING = [self::DRAFT_3 => 'draft03', self::DRAFT_4 => 'draft04', self::DRAFT_6 => 'draft06', self::DRAFT_7 => 'draft07', self::DRAFT_2019_09 => 'draft2019-09', self::DRAFT_2020_12 => 'draft2020-12'];
    private const FALLBACK_MAPPING = ['draft3' => self::DRAFT_3, 'draft4' => self::DRAFT_4, 'draft6' => self::DRAFT_6, 'draft7' => self::DRAFT_7];
    public function toConstraintName(): string
    {
        return self::MAPPING[$this->getValue()];
    }
    public static function fromConstraintName(string $name): DraftIdentifiers
    {
        $reverseMap = array_flip(self::MAPPING);
        if (!array_key_exists($name, $reverseMap)) {
            if (array_key_exists($name, self::FALLBACK_MAPPING)) {
                return DraftIdentifiers::byValue(self::FALLBACK_MAPPING[$name]);
            }
            throw new \InvalidArgumentException("{$name} is not a valid constraint name.");
        }
        return DraftIdentifiers::byValue($reverseMap[$name]);
    }
    public function withoutFragment(): string
    {
        return rtrim($this->getValue(), '#');
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of the JsonSchema package.
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\JsonSchema\Uri\Retrievers;

/**
 * Interface for URI retrievers
 *
 * @author Sander Coolen <sander@jibber.nl>
 */
interface UriRetrieverInterface
{
    /**
     * Retrieve a schema from the specified URI
     *
     * @param string $uri URI that resolves to a JSON schema
     *
     * @throws \JsonSchema\Exception\ResourceNotFoundException
     *
     * @return mixed string|null
     */
    public function retrieve($uri);
    /**
     * Get media content type
     *
     * @return string
     */
    public function getContentType();
}
<?php

declare (strict_types=1);
/**
 * JsonSchema
 *
 * @filesource
 */
namespace _ContaoManager\JsonSchema\Uri\Retrievers;

/**
 * AbstractRetriever implements the default shared behavior
 * that all descendant Retrievers should inherit
 *
 * @author Steven Garcia <webwhammy@gmail.com>
 */
abstract class AbstractRetriever implements UriRetrieverInterface
{
    /**
     * Media content type
     *
     * @var string
     */
    protected $contentType;
    /**
     * {@inheritdoc}
     *
     * @see \JsonSchema\Uri\Retrievers\UriRetrieverInterface::getContentType()
     */
    public function getContentType()
    {
        return $this->contentType;
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of the JsonSchema package.
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\JsonSchema\Uri\Retrievers;

use _ContaoManager\JsonSchema\Exception\RuntimeException;
use _ContaoManager\JsonSchema\Validator;
/**
 * Tries to retrieve JSON schemas from a URI using cURL library
 *
 * @author Sander Coolen <sander@jibber.nl>
 */
class Curl extends AbstractRetriever
{
    protected $messageBody;
    public function __construct()
    {
        if (!function_exists('curl_init')) {
            // Cannot test this, because curl_init is present on all test platforms plus mock
            throw new RuntimeException('cURL not installed');
            // @codeCoverageIgnore
        }
    }
    /**
     * {@inheritdoc}
     *
     * @see \JsonSchema\Uri\Retrievers\UriRetrieverInterface::retrieve()
     */
    public function retrieve($uri)
    {
        $ch = curl_init();
        curl_setopt($ch, \CURLOPT_URL, $uri);
        curl_setopt($ch, \CURLOPT_HEADER, \true);
        curl_setopt($ch, \CURLOPT_RETURNTRANSFER, \true);
        curl_setopt($ch, \CURLOPT_HTTPHEADER, ['Accept: ' . Validator::SCHEMA_MEDIA_TYPE]);
        $response = curl_exec($ch);
        if (\false === $response) {
            throw new \_ContaoManager\JsonSchema\Exception\ResourceNotFoundException('JSON schema not found');
        }
        $this->fetchMessageBody($response);
        $this->fetchContentType($response);
        if (\PHP_VERSION_ID < 80000) {
            curl_close($ch);
        }
        return $this->messageBody;
    }
    /**
     * @param string $response cURL HTTP response
     */
    private function fetchMessageBody($response)
    {
        preg_match("/(?:\r\n){2}(.*)\$/ms", $response, $match);
        $this->messageBody = $match[1];
    }
    /**
     * @param string $response cURL HTTP response
     *
     * @return bool Whether the Content-Type header was found or not
     */
    protected function fetchContentType($response)
    {
        if (0 < preg_match("/Content-Type:(\\V*)/ims", $response, $match)) {
            $this->contentType = trim($match[1]);
            return \true;
        }
        return \false;
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of the JsonSchema package.
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\JsonSchema\Uri\Retrievers;

use _ContaoManager\JsonSchema\Exception\ResourceNotFoundException;
/**
 * Tries to retrieve JSON schemas from a URI using file_get_contents()
 *
 * @author Sander Coolen <sander@jibber.nl>
 */
class FileGetContents extends AbstractRetriever
{
    protected $messageBody;
    /**
     * {@inheritdoc}
     *
     * @see \JsonSchema\Uri\Retrievers\UriRetrieverInterface::retrieve()
     */
    public function retrieve($uri)
    {
        if (function_exists('http_clear_last_response_headers')) {
            http_clear_last_response_headers();
        }
        $errorMessage = null;
        set_error_handler(function ($errno, $errstr) use (&$errorMessage) {
            $errorMessage = $errstr;
        });
        $response = file_get_contents($uri);
        restore_error_handler();
        if ($errorMessage) {
            throw new ResourceNotFoundException($errorMessage);
        }
        if (\false === $response) {
            throw new ResourceNotFoundException('JSON schema not found at ' . $uri);
        }
        if ($response == '' && substr($uri, 0, 7) == 'file://' && substr($uri, -1) == '/') {
            throw new ResourceNotFoundException('JSON schema not found at ' . $uri);
        }
        $this->messageBody = $response;
        if (function_exists('http_get_last_response_headers')) {
            // Use http_get_last_response_headers() for compatibility with PHP 8.5+
            // where $http_response_header is deprecated.
            $httpResponseHeaders = http_get_last_response_headers();
        } else {
            /** @phpstan-ignore nullCoalesce.variable ($http_response_header can non-existing when no http request was done) */
            $httpResponseHeaders = $http_response_header ?? [];
        }
        if (!empty($httpResponseHeaders)) {
            $this->fetchContentType($httpResponseHeaders);
        } else {
            $this->contentType = null;
        }
        return $this->messageBody;
    }
    /**
     * @param array $headers HTTP Response Headers
     *
     * @return bool Whether the Content-Type header was found or not
     */
    private function fetchContentType(array $headers): bool
    {
        foreach (array_reverse($headers) as $header) {
            if ($this->contentType = self::getContentTypeMatchInHeader($header)) {
                return \true;
            }
        }
        return \false;
    }
    /**
     * @param string $header
     *
     * @return string|null
     */
    protected static function getContentTypeMatchInHeader($header)
    {
        if (0 < preg_match("/Content-Type:(\\V*)/ims", $header, $match)) {
            return trim($match[1]);
        }
        return null;
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\JsonSchema\Uri\Retrievers;

use _ContaoManager\JsonSchema\Validator;
/**
 * URI retrieved based on a predefined array of schemas
 *
 * @example
 *
 *      $retriever = new PredefinedArray(array(
 *          'http://acme.com/schemas/person#'  => '{ ... }',
 *          'http://acme.com/schemas/address#' => '{ ... }',
 *      ))
 *
 *      $schema = $retriever->retrieve('http://acme.com/schemas/person#');
 */
class PredefinedArray extends AbstractRetriever
{
    /**
     * Contains schemas as URI => JSON
     *
     * @var array
     */
    private $schemas;
    /**
     * Constructor
     *
     * @param array  $schemas
     * @param string $contentType
     */
    public function __construct(array $schemas, $contentType = Validator::SCHEMA_MEDIA_TYPE)
    {
        $this->schemas = $schemas;
        $this->contentType = $contentType;
    }
    /**
     * {@inheritdoc}
     *
     * @see \JsonSchema\Uri\Retrievers\UriRetrieverInterface::retrieve()
     */
    public function retrieve($uri)
    {
        if (!array_key_exists($uri, $this->schemas)) {
            throw new \_ContaoManager\JsonSchema\Exception\ResourceNotFoundException(sprintf('The JSON schema "%s" was not found.', $uri));
        }
        return $this->schemas[$uri];
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of the JsonSchema package.
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\JsonSchema\Uri;

use _ContaoManager\JsonSchema\Exception\InvalidSchemaMediaTypeException;
use _ContaoManager\JsonSchema\Exception\JsonDecodingException;
use _ContaoManager\JsonSchema\Exception\ResourceNotFoundException;
use _ContaoManager\JsonSchema\Uri\Retrievers\FileGetContents;
use _ContaoManager\JsonSchema\Uri\Retrievers\UriRetrieverInterface;
use _ContaoManager\JsonSchema\UriRetrieverInterface as BaseUriRetrieverInterface;
use _ContaoManager\JsonSchema\Validator;
/**
 * Retrieves JSON Schema URIs
 *
 * @author Tyler Akins <fidian@rumkin.com>
 */
class UriRetriever implements BaseUriRetrieverInterface
{
    /**
     * @var array Map of URL translations
     */
    protected $translationMap = [
        // use local copies of the spec schemas
        '|^https?://json-schema.org/draft-(0[3467])/schema#?|' => 'package://dist/schema/json-schema-draft-$1.json',
    ];
    /**
     * @var array A list of endpoints for media type check exclusion
     */
    protected $allowedInvalidContentTypeEndpoints = ['http://json-schema.org/', 'https://json-schema.org/'];
    /**
     * @var null|UriRetrieverInterface
     */
    protected $uriRetriever = null;
    /**
     * @var array|object[]
     *
     * @see loadSchema
     */
    private $schemaCache = [];
    /**
     * Adds an endpoint to the media type validation exclusion list
     *
     * @param string $endpoint
     */
    public function addInvalidContentTypeEndpoint($endpoint)
    {
        $this->allowedInvalidContentTypeEndpoints[] = $endpoint;
    }
    /**
     * Guarantee the correct media type was encountered
     *
     * @param UriRetrieverInterface $uriRetriever
     * @param string                $uri
     *
     * @return bool|void
     */
    public function confirmMediaType($uriRetriever, $uri)
    {
        $contentType = $uriRetriever->getContentType();
        if (is_null($contentType)) {
            // Well, we didn't get an invalid one
            return;
        }
        if (in_array($contentType, [Validator::SCHEMA_MEDIA_TYPE, 'application/json'])) {
            return;
        }
        foreach ($this->allowedInvalidContentTypeEndpoints as $endpoint) {
            if (!\is_null($uri) && strpos($uri, $endpoint) === 0) {
                return \true;
            }
        }
        throw new InvalidSchemaMediaTypeException(sprintf('Media type %s expected, but %s given', Validator::SCHEMA_MEDIA_TYPE, $contentType));
    }
    /**
     * Get a URI Retriever
     *
     * If none is specified, sets a default FileGetContents retriever and
     * returns that object.
     *
     * @return UriRetrieverInterface
     */
    public function getUriRetriever()
    {
        if (is_null($this->uriRetriever)) {
            $this->setUriRetriever(new FileGetContents());
        }
        return $this->uriRetriever;
    }
    /**
     * Resolve a schema based on pointer
     *
     * URIs can have a fragment at the end in the format of
     * #/path/to/object and we are to look up the 'path' property of
     * the first object then the 'to' and 'object' properties.
     *
     * @param object $jsonSchema JSON Schema contents
     * @param string $uri        JSON Schema URI
     *
     * @throws ResourceNotFoundException
     *
     * @return object JSON Schema after walking down the fragment pieces
     */
    public function resolvePointer($jsonSchema, $uri)
    {
        $resolver = new UriResolver();
        $parsed = $resolver->parse($uri);
        if (empty($parsed['fragment'])) {
            return $jsonSchema;
        }
        $path = explode('/', $parsed['fragment']);
        while ($path) {
            $pathElement = array_shift($path);
            if (!empty($pathElement)) {
                $pathElement = str_replace('~1', '/', $pathElement);
                $pathElement = str_replace('~0', '~', $pathElement);
                if (!empty($jsonSchema->{$pathElement})) {
                    $jsonSchema = $jsonSchema->{$pathElement};
                } else {
                    throw new ResourceNotFoundException('Fragment "' . $parsed['fragment'] . '" not found' . ' in ' . $uri);
                }
                if (!is_object($jsonSchema)) {
                    throw new ResourceNotFoundException('Fragment part "' . $pathElement . '" is no object ' . ' in ' . $uri);
                }
            }
        }
        return $jsonSchema;
    }
    /**
     * {@inheritdoc}
     */
    public function retrieve($uri, $baseUri = null, $translate = \true)
    {
        $resolver = new UriResolver();
        $resolvedUri = $fetchUri = $resolver->resolve($uri, $baseUri);
        //fetch URL without #fragment
        $arParts = $resolver->parse($resolvedUri);
        if (isset($arParts['fragment'])) {
            unset($arParts['fragment']);
            $fetchUri = $resolver->generate($arParts);
        }
        // apply URI translations
        if ($translate) {
            $fetchUri = $this->translate($fetchUri);
        }
        $jsonSchema = $this->loadSchema($fetchUri);
        // Use the JSON pointer if specified
        $jsonSchema = $this->resolvePointer($jsonSchema, $resolvedUri);
        if ($jsonSchema instanceof \stdClass) {
            $jsonSchema->id = $resolvedUri;
        }
        return $jsonSchema;
    }
    /**
     * Fetch a schema from the given URI, json-decode it and return it.
     * Caches schema objects.
     *
     * @param string $fetchUri Absolute URI
     *
     * @return object JSON schema object
     */
    protected function loadSchema($fetchUri)
    {
        if (isset($this->schemaCache[$fetchUri])) {
            return $this->schemaCache[$fetchUri];
        }
        $uriRetriever = $this->getUriRetriever();
        $contents = $this->uriRetriever->retrieve($fetchUri);
        $this->confirmMediaType($uriRetriever, $fetchUri);
        $jsonSchema = json_decode($contents);
        if (\JSON_ERROR_NONE < $error = json_last_error()) {
            throw new JsonDecodingException($error);
        }
        $this->schemaCache[$fetchUri] = $jsonSchema;
        return $jsonSchema;
    }
    /**
     * Set the URI Retriever
     *
     * @param UriRetrieverInterface $uriRetriever
     *
     * @return $this for chaining
     */
    public function setUriRetriever(UriRetrieverInterface $uriRetriever)
    {
        $this->uriRetriever = $uriRetriever;
        return $this;
    }
    /**
     * Parses a URI into five main components
     *
     * @param string $uri
     *
     * @return array
     */
    public function parse($uri)
    {
        preg_match('|^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?|', $uri, $match);
        $components = [];
        if (5 < count($match)) {
            $components = ['scheme' => $match[2], 'authority' => $match[4], 'path' => $match[5]];
        }
        if (7 < count($match)) {
            $components['query'] = $match[7];
        }
        if (9 < count($match)) {
            $components['fragment'] = $match[9];
        }
        return $components;
    }
    /**
     * Builds a URI based on n array with the main components
     *
     * @param array $components
     *
     * @return string
     */
    public function generate(array $components)
    {
        $uri = $components['scheme'] . '://' . $components['authority'] . $components['path'];
        if (array_key_exists('query', $components)) {
            $uri .= $components['query'];
        }
        if (array_key_exists('fragment', $components)) {
            $uri .= $components['fragment'];
        }
        return $uri;
    }
    /**
     * Resolves a URI
     *
     * @param string $uri     Absolute or relative
     * @param string $baseUri Optional base URI
     *
     * @return string
     */
    public function resolve($uri, $baseUri = null)
    {
        $components = $this->parse($uri);
        $path = $components['path'];
        if (array_key_exists('scheme', $components) && 'http' === $components['scheme']) {
            return $uri;
        }
        $baseComponents = $this->parse($baseUri);
        $basePath = $baseComponents['path'];
        $baseComponents['path'] = UriResolver::combineRelativePathWithBasePath($path, $basePath);
        return $this->generate($baseComponents);
    }
    /**
     * @param string $uri
     *
     * @return bool
     */
    public function isValid($uri)
    {
        $components = $this->parse($uri);
        return !empty($components);
    }
    /**
     * Set a URL translation rule
     */
    public function setTranslation($from, $to)
    {
        $this->translationMap[$from] = $to;
    }
    /**
     * Apply URI translation rules
     */
    public function translate($uri)
    {
        foreach ($this->translationMap as $from => $to) {
            $uri = preg_replace($from, $to, $uri);
        }
        // translate references to local files within the json-schema package
        $uri = preg_replace('|^package://|', sprintf('file://%s/', realpath(__DIR__ . '/../../..')), $uri);
        return $uri;
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of the JsonSchema package.
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\JsonSchema\Uri;

use _ContaoManager\JsonSchema\Exception\UriResolverException;
use _ContaoManager\JsonSchema\UriResolverInterface;
/**
 * Resolves JSON Schema URIs
 *
 * @author Sander Coolen <sander@jibber.nl>
 */
class UriResolver implements UriResolverInterface
{
    /**
     * Parses a URI into five main components
     *
     * @param string $uri
     *
     * @return array
     */
    public function parse($uri)
    {
        preg_match('|^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?|', (string) $uri, $match);
        $components = [];
        if (5 < count($match)) {
            $components = ['scheme' => $match[2], 'authority' => $match[4], 'path' => $match[5]];
        }
        if (7 < count($match)) {
            $components['query'] = $match[7];
        }
        if (9 < count($match)) {
            $components['fragment'] = $match[9];
        }
        return $components;
    }
    /**
     * Builds a URI based on n array with the main components
     *
     * @param array $components
     *
     * @return string
     */
    public function generate(array $components)
    {
        $uri = $components['scheme'] . '://' . $components['authority'] . $components['path'];
        if (array_key_exists('query', $components) && strlen($components['query'])) {
            $uri .= '?' . $components['query'];
        }
        if (array_key_exists('fragment', $components)) {
            $uri .= '#' . $components['fragment'];
        }
        return $uri;
    }
    /**
     * {@inheritdoc}
     */
    public function resolve($uri, $baseUri = null)
    {
        // treat non-uri base as local file path
        if (!is_null($baseUri) && !filter_var($baseUri, \FILTER_VALIDATE_URL) && !preg_match('|^[^/]+://|u', $baseUri)) {
            if (is_file($baseUri)) {
                $baseUri = 'file://' . realpath($baseUri);
            } elseif (is_dir($baseUri)) {
                $baseUri = 'file://' . realpath($baseUri) . '/';
            } else {
                $baseUri = 'file://' . getcwd() . '/' . $baseUri;
            }
        }
        if ($uri == '') {
            return $baseUri;
        }
        $components = $this->parse($uri);
        $path = $components['path'];
        if (!empty($components['scheme'])) {
            return $uri;
        }
        $baseComponents = $this->parse($baseUri);
        $basePath = $baseComponents['path'];
        $baseComponents['path'] = self::combineRelativePathWithBasePath($path, $basePath);
        if (isset($components['fragment'])) {
            $baseComponents['fragment'] = $components['fragment'];
        }
        return $this->generate($baseComponents);
    }
    /**
     * Tries to glue a relative path onto an absolute one
     *
     * @param string $relativePath
     * @param string $basePath
     *
     * @throws UriResolverException
     *
     * @return string Merged path
     */
    public static function combineRelativePathWithBasePath($relativePath, $basePath)
    {
        $relativePath = self::normalizePath($relativePath);
        if (!$relativePath) {
            return $basePath;
        }
        if ($relativePath[0] === '/') {
            return $relativePath;
        }
        if (!$basePath) {
            throw new UriResolverException(sprintf("Unable to resolve URI '%s' from base '%s'", $relativePath, $basePath));
        }
        $dirname = $basePath[strlen($basePath) - 1] === '/' ? $basePath : dirname($basePath);
        $combined = rtrim($dirname, '/') . '/' . ltrim($relativePath, '/');
        $combinedSegments = explode('/', $combined);
        $collapsedSegments = [];
        while ($combinedSegments) {
            $segment = array_shift($combinedSegments);
            if ($segment === '..') {
                if (count($collapsedSegments) <= 1) {
                    // Do not remove the top level (domain)
                    // This is not ideal - the domain should not be part of the path here. parse() and generate()
                    // should handle the "domain" separately, like the schema.
                    // Then the if-condition here would be `if (!$collapsedSegments) {`.
                    throw new UriResolverException(sprintf("Unable to resolve URI '%s' from base '%s'", $relativePath, $basePath));
                }
                array_pop($collapsedSegments);
            } else {
                $collapsedSegments[] = $segment;
            }
        }
        return implode('/', $collapsedSegments);
    }
    /**
     * Normalizes a URI path component by removing dot-slash and double slashes
     *
     * @param string $path
     *
     * @return string
     */
    private static function normalizePath($path)
    {
        $path = preg_replace('|((?<!\.)\./)*|', '', $path);
        $path = preg_replace('|//|', '/', $path);
        return $path;
    }
    /**
     * @param string $uri
     *
     * @return bool
     */
    public function isValid($uri)
    {
        $components = $this->parse($uri);
        return !empty($components);
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of the JsonSchema package.
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\JsonSchema\Exception;

/**
 * Wrapper for the ResourceNotFoundException
 */
class ResourceNotFoundException extends RuntimeException
{
}
<?php

declare (strict_types=1);
namespace _ContaoManager\JsonSchema\Exception;

interface ExceptionInterface
{
}
<?php

declare (strict_types=1);
/*
 * This file is part of the JsonSchema package.
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\JsonSchema\Exception;

/**
 * Wrapper for the RuntimeException
 */
class RuntimeException extends \RuntimeException implements ExceptionInterface
{
}
<?php

declare (strict_types=1);
/*
 * This file is part of the JsonSchema package.
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\JsonSchema\Exception;

/**
 * Wrapper for the InvalidSourceUriException
 */
class InvalidSourceUriException extends InvalidArgumentException
{
}
<?php

declare (strict_types=1);
/*
 * This file is part of the JsonSchema package.
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\JsonSchema\Exception;

/**
 * Wrapper for the InvalidArgumentException
 */
class InvalidArgumentException extends \InvalidArgumentException implements ExceptionInterface
{
}
<?php

declare (strict_types=1);
/*
 * This file is part of the JsonSchema package.
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\JsonSchema\Exception;

/**
 * @package JsonSchema\Exception
 *
 * @author Joost Nijhuis <jnijhuis81@gmail.com>
 */
class UnresolvableJsonPointerException extends InvalidArgumentException
{
}
<?php

declare (strict_types=1);
/*
 * This file is part of the JsonSchema package.
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\JsonSchema\Exception;

class ValidationException extends RuntimeException
{
}
<?php

declare (strict_types=1);
/*
 * This file is part of the JsonSchema package.
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\JsonSchema\Exception;

/**
 * Wrapper for the ResourceNotFoundException
 */
class InvalidConfigException extends RuntimeException
{
}
<?php

declare (strict_types=1);
/*
 * This file is part of the JsonSchema package.
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\JsonSchema\Exception;

/**
 * Wrapper for the JsonDecodingException
 */
class JsonDecodingException extends RuntimeException
{
    public function __construct($code = \JSON_ERROR_NONE, ?\Exception $previous = null)
    {
        switch ($code) {
            case \JSON_ERROR_DEPTH:
                $message = 'The maximum stack depth has been exceeded';
                break;
            case \JSON_ERROR_STATE_MISMATCH:
                $message = 'Invalid or malformed JSON';
                break;
            case \JSON_ERROR_CTRL_CHAR:
                $message = 'Control character error, possibly incorrectly encoded';
                break;
            case \JSON_ERROR_UTF8:
                $message = 'Malformed UTF-8 characters, possibly incorrectly encoded';
                break;
            case \JSON_ERROR_SYNTAX:
                $message = 'JSON syntax is malformed';
                break;
            default:
                $message = 'Syntax error';
        }
        parent::__construct($message, $code, $previous);
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of the JsonSchema package.
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\JsonSchema\Exception;

/**
 * Wrapper for the InvalidSchemaMediaType
 */
class InvalidSchemaException extends RuntimeException
{
}
<?php

declare (strict_types=1);
/*
 * This file is part of the JsonSchema package.
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\JsonSchema\Exception;

/**
 * Wrapper for the UriResolverException
 */
class UriResolverException extends RuntimeException
{
}
<?php

declare (strict_types=1);
/*
 * This file is part of the JsonSchema package.
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\JsonSchema\Exception;

/**
 * Wrapper for the InvalidSchemaMediaType
 */
class InvalidSchemaMediaTypeException extends RuntimeException
{
}
<?php

declare (strict_types=1);
namespace _ContaoManager\JsonSchema;

interface SchemaStorageInterface
{
    /**
     * Adds schema with given identifier
     *
     * @param object|bool $schema
     */
    public function addSchema(string $id, $schema = null): void;
    /**
     * Returns schema for given identifier, or null if it does not exist
     *
     * @return object|bool
     */
    public function getSchema(string $id);
    /**
     * Returns schema for given reference with all sub-references resolved
     *
     * @return object|bool
     */
    public function resolveRef(string $ref);
    /**
     * Returns schema referenced by '$ref' property
     *
     * @param mixed $refSchema
     *
     * @return object|bool
     */
    public function resolveRefSchema($refSchema);
}
<?php

declare (strict_types=1);
namespace _ContaoManager\JsonSchema\Tool;

class DeepComparer
{
    /**
     * @param mixed $left
     * @param mixed $right
     */
    public static function isEqual($left, $right): bool
    {
        if ($left === null && $right === null) {
            return \true;
        }
        $isLeftScalar = is_scalar($left);
        $isLeftNumber = is_int($left) || is_float($left);
        $isRightScalar = is_scalar($right);
        $isRightNumber = is_int($right) || is_float($right);
        if ($isLeftScalar && $isRightScalar) {
            /*
             * In Json-Schema mathematically equal numbers are compared equal
             */
            if ($isLeftNumber && $isRightNumber && (float) $left === (float) $right) {
                return \true;
            }
            return $left === $right;
        }
        if ($isLeftScalar !== $isRightScalar) {
            return \false;
        }
        if (is_array($left) && is_array($right)) {
            return self::isArrayEqual($left, $right);
        }
        if ($left instanceof \stdClass && $right instanceof \stdClass) {
            return self::isArrayEqual((array) $left, (array) $right);
        }
        return \false;
    }
    /**
     * @param array<string|int, mixed> $left
     * @param array<string|int, mixed> $right
     */
    private static function isArrayEqual(array $left, array $right): bool
    {
        if (count($left) !== count($right)) {
            return \false;
        }
        foreach ($left as $key => $value) {
            if (!array_key_exists($key, $right)) {
                return \false;
            }
            if (!self::isEqual($value, $right[$key])) {
                return \false;
            }
        }
        return \true;
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\JsonSchema\Tool\Validator;

class UriValidator
{
    public static function isValid(string $uri): bool
    {
        // RFC 3986: Hierarchical URIs (http, https, ftp, etc.)
        $hierarchicalPattern = '/^
            ([a-z][a-z0-9+\-.]*):\/\/                # Scheme (http, https, ftp, etc.)
            (?:([^:@\/?#]+)(?::([^@\/?#]*))?@)?      # Optional userinfo (user:pass@)
            ([a-z0-9._~-]+|\[[a-f0-9:.]+\])          # Hostname or IPv6 in brackets
            (?::(\d{1,5}))?                          # Optional port
            (\/[a-zA-Z0-9._~!$&\'()*+,;=:@\/%-]*)*   # Path (valid characters only)
            (\?([^#]*))?                             # Optional query
            (\#(.*))?                                # Optional fragment
        $/ix';
        // RFC 3986: Non-Hierarchical URIs (mailto, data, urn, news)
        $nonHierarchicalPattern = '/^
                (mailto|data|urn|news|tel|file):     # Only allow known non-hierarchical schemes
                (.+)                                 # Must contain at least one character after scheme
        $/ix';
        // Validation for newsgroup name (alphanumeric + dots, no empty segments)
        $newsGroupPattern = '/^[a-z0-9]+(\.[a-z0-9]+)*$/i';
        $telPattern = '/^\+?[0-9.\-() ]+$/';
        // Allows +, digits, separators
        // RFC 5322-compliant email validation for `mailto:` URIs
        $emailPattern = '/^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/';
        // First, check if it's a valid hierarchical URI
        if (preg_match($hierarchicalPattern, $uri, $matches) === 1) {
            // Validate domain name (no double dots like example..com)
            if (!empty($matches[4]) && preg_match('/\.\./', $matches[4])) {
                return \false;
            }
            // Validate port (should be between 1 and 65535 if specified)
            if (!empty($matches[5]) && ($matches[5] < 1 || $matches[5] > 65535)) {
                return \false;
            }
            // Validate the path (reject illegal characters: < > { } | \ ^ `)
            if (!empty($matches[6]) && preg_match('/[<>{}|\\\\^`]/', $matches[6])) {
                return \false;
            }
            return \true;
        }
        // If not hierarchical, check non-hierarchical URIs
        if (preg_match($nonHierarchicalPattern, $uri, $matches) === 1) {
            $scheme = strtolower($matches[1]);
            // Extract the scheme
            // Special case: `mailto:` must contain a **valid email address**
            if ($scheme === 'mailto') {
                return preg_match($emailPattern, $matches[2]) === 1;
            }
            if ($scheme === 'news') {
                return preg_match($newsGroupPattern, $matches[2]) === 1;
            }
            if ($scheme === 'tel') {
                return preg_match($telPattern, $matches[2]) === 1;
            }
            return \true;
            // Valid non-hierarchical URI
        }
        return \false;
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\JsonSchema\Tool\Validator;

class RelativeReferenceValidator
{
    public static function isValid(string $ref): bool
    {
        // Relative reference pattern as per RFC 3986, Section 4.1
        $pattern = '/^(([^\/?#]+):)?(\/\/([^\/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?$/';
        if (preg_match($pattern, $ref) !== 1) {
            return \false;
        }
        // Additional checks for invalid cases
        if (strpos($ref, '\\') !== \false) {
            return \false;
            // Backslashes are not allowed in URI references
        }
        if (preg_match('/^(http|https):\/\//', $ref)) {
            return \false;
            // Absolute URI
        }
        if (preg_match('/^:\/\//', $ref)) {
            return \false;
            // Missing scheme in authority
        }
        if (preg_match('/^:\//', $ref)) {
            return \false;
            // Invalid scheme separator
        }
        if (preg_match('/^\/\/$/', $ref)) {
            return \false;
            // Empty authority
        }
        if (preg_match('/^\/\/\/[^\/]/', $ref)) {
            return \false;
            // Invalid authority with three slashes
        }
        if (preg_match('/\s/', $ref)) {
            return \false;
            // Spaces are not allowed in URIs
        }
        if (preg_match('/^\?#|^#$/', $ref)) {
            return \false;
            // Missing path but having query and fragment
        }
        if ($ref === '#' || $ref === '?') {
            return \false;
            // Missing path and having only fragment or query
        }
        return \true;
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\JsonSchema\Tool;

use _ContaoManager\JsonSchema\Exception\JsonDecodingException;
use _ContaoManager\JsonSchema\Exception\RuntimeException;
class DeepCopy
{
    /**
     * @param mixed $input
     *
     * @return mixed
     */
    public static function copyOf($input)
    {
        $json = json_encode($input);
        if (\JSON_ERROR_NONE < $error = json_last_error()) {
            throw new JsonDecodingException($error);
        }
        if ($json === \false) {
            throw new RuntimeException('Failed to encode input to JSON: ' . json_last_error_msg());
        }
        return json_decode($json, self::isAssociativeArray($input));
    }
    /**
     * @param mixed $input
     */
    private static function isAssociativeArray($input): bool
    {
        return is_array($input) && array_keys($input) !== range(0, count($input) - 1);
    }
}
The Code Manifesto
==================

We want to work in an ecosystem that empowers developers to reach their potential--one that encourages growth and effective collaboration. A space that is safe for all.

A space such as this benefits everyone that participates in it. It encourages new developers to enter our field. It is through discussion and collaboration that we grow, and through growth that we improve.

In the effort to create such a place, we hold to these values:

1. **Discrimination limits us.** This includes discrimination on the basis of race, gender, sexual orientation, gender identity, age, nationality, technology and any other arbitrary exclusion of a group of people.
2. **Boundaries honor us.** Your comfort levels are not everyone’s comfort levels. Remember that, and if brought to your attention, heed it.
3. **We are our biggest assets.** None of us were born masters of our trade. Each of us has been helped along the way. Return that favor, when and where you can.
4. **We are resources for the future.** As an extension of #3, share what you know. Make yourself a resource to help those that come after you.
5. **Respect defines us.** Treat others as you wish to be treated. Make your discussions, criticisms and debates from a position of respectfulness. Ask yourself, is it true? Is it necessary? Is it constructive? Anything less is unacceptable.
6. **Reactions require grace.** Angry responses are valid, but abusive language and vindictive actions are toxic. When something happens that offends you, handle it assertively, but be respectful. Escalate reasonably, and try to allow the offender an opportunity to explain themselves, and possibly correct the issue.
7. **Opinions are just that: opinions.** Each and every one of us, due to our background and upbringing, have varying opinions. That is perfectly acceptable. Remember this: if you respect your own opinions, you should respect the opinions of others.
8. **To err is human.** You might not intend it, but mistakes do happen and contribute to build experience. Tolerate honest mistakes, and don't hesitate to apologize if you make one yourself.
Copyright (C) 2013-2026 Larry Garfield

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
# Changelog

All notable changes to `ApiProblem` will be documented in this file.

Updates should follow the [Keep a CHANGELOG](http://keepachangelog.com/) principles.

## 3.7.1 - 2026-01-12

### Added
- Changed PHPDocs to use `$this` for fluent methods, which helps IDE autocompletes.

### Deprecated
- Nothing

### Fixed
- Assorted legalese and paperwork updates.
- Improved .gitattributes to ship fewer files.

### Removed
- Nothing

### Security
- Nothing
# ApiProblem

[![Build Status](https://travis-ci.org/Crell/ApiProblem.svg?branch=master)](https://travis-ci.org/Crell/ApiProblem)

This library provides a simple and straightforward implementation of the IETF Problem Details for HTTP APIs, [RFC 9457][1].

[RFC 9457][1] is a simple specification for formatting error responses from RESTful APIs on the web.  This library provides a simple and convenient way to interact with that specification.  It supports generating and parsing [RFC 9457][1] messages, in both JSON and XML variants.

## Generating responses

What's that you say?  Someone sent your API a bad request?  Tell them it's a problem!

```php
use Crell\ApiProblem\ApiProblem;

$problem = new ApiProblem("You do not have enough credit.", "http://example.com/probs/out-of-credit");
// Defined properties in the API have their own setter methods.
$problem
  ->setDetail("Your current balance is 30, but that costs 50.")
  ->setInstance("http://example.net/account/12345/msgs/abc");
// But you can also support any arbitrary extended properties!
$problem['balance'] = 30;
$problem['accounts'] = [
  "http://example.net/account/12345",
  "http://example.net/account/67890"
];

$json_string = $problem->asJson();

// Now send that JSON string as a response along with the appropriate HTTP error
// code and content type which is available via ApiProblem::CONTENT_TYPE_JSON.
// Also check out asXml() and ApiProblem::CONTENT_TYPE_XML for the angle-bracket fans in the room.
```

Or, even better, you can subclass ApiProblem for a specific problem type (since the type and title are supposed to go together and be relatively fixed), then just populate your own error-specific data.  Just like extending an exception!

If you're using a library or framework that wants to do its own JSON serialization, that's also fully supported.  ApiProblem implements`\JsonSerializable`, so you can pass it directly to `json_encode()` as if it were a naked array.

```php
$response = new MyFrameworksJsonResponse($problem);

// Or do it yourself
$body = json_encode($problem);
```

## Sending Responses

You're probably using [PSR-7][3] for your responses. That's why this library includes a utility to convert your `ApiProblem` object to a PSR-7 `ResponseInterface` object, using a [PSR-17][4] factory of your choice.  Like so:

```php
use Crell\ApiProblem\HttpConverter;

$factory = getResponseFactoryFromSomewhere();

// The second parameter says whether to pretty-print the output.
$converter = new HttpConverter($factory, true);

$response = $converter->toJsonResponse($problem);
// or
$response = $converter->toXmlResponse($problem);
```

That gives back a fully-functional and marked Response object, ready to send back to the client.

## Receiving responses

Are you sending messages to an API that is responding with API-Problem errors? No problem!  You can easily handle that response like so:

```php
use Crell\ApiProblem\ApiProblem;

$problem = ApiProblem::fromJson($some_json_string);
$title = $problem->getTitle();
$type = $problem->getType();
// Great, now we know what went wrong, so we can figure out what to do about it.
```

(It works for fromXml(), too!)

## Installation

Install ApiProblem like any other Composer package:

    composer require crell/api-problem

See the [Composer documentation][2] for more details.

## Security

If you discover any security related issues, please use the [GitHub security reporting form](https://github.com/Crell/ApiProblem/security) rather than the issue queue.

## Credits

- [Larry Garfield][link-author]
- [All Contributors][link-contributors]

## License

This library is released under the MIT license.  In short, "leave the copyright statement intact, otherwise have fun."  See LICENSE for more information.

## Contributing

Pull requests accepted!  The goal is complete conformance with the IETF spec.

[1]: https://tools.ietf.org/html/rfc9457
[2]: http://getcomposer.org/
[3]: https://www.php-fig.org/psr/psr-7/
[4]: https://www.php-fig.org/psr/psr-17/
# Contributing

Contributions are **welcome** and will be fully **credited**.

We accept contributions via Pull Requests on [Github](https://github.com/Crell/ApiProblem).


## Pull Requests

- **[PER-Coding Standards](https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-2-coding-style-guide.md)** - Check the code style with ``$ composer check-style`` and fix it with ``$ composer fix-style``.

- **Add tests!** - Your patch won't be accepted if it doesn't have tests.

- **Document any change in behaviour** - Make sure the `README.md` and any other relevant documentation are kept up-to-date.

- **Consider our release cycle** - We try to follow [SemVer v2.0.0](http://semver.org/). Randomly breaking public APIs is not an option.

- **Create feature branches** - Don't ask us to pull from your master branch.

- **One pull request per feature** - If you want to do more than one thing, send multiple pull requests.

- **Send coherent history** - Make sure each individual commit in your pull request is meaningful. If you had to make multiple intermediate commits while developing, please [squash them](http://www.git-scm.com/book/en/v2/Git-Tools-Rewriting-History#Changing-Multiple-Commit-Messages) before submitting.


## Running Tests

``` bash
$ composer test
```

## AI Policy

This project respects the copyright of all Open Source contributors.  The legality of using Open Source data to train Code-generation AIs (including but not limited to GitHub Copilot) or of using Code-generation AIs to produce Open Source code is still very murky and unclear.  For that reason, *AI-generated code is not welcome in this project and will be rejected on sight*.  By submitting a PR, you affirm that the code was written 100% by you, and that you have the legal permission to offer it under the licensing terms of this project.  Violation of this policy may result in your banning from the project.

**Happy coding**!
# Maintenance Terms

Current as of 2025

The code, text and data in this repository are provided as-is under
the terms of the repository's LICENSE.md file, as a gift to the commons
and the common good. In providing this software as-is, its author(s)
admit no further obligations from anyone using the software for any reason,
particularly with respect to:

- Response time,
- Change review and integration,
- Disclosure schedules,
- Discretionary, proprietary or otherwise secretive communications, and
- Any other non-contractual obligations or conventions, regardless of
  their presumed urgency or severity.

The author(s) hope you find it valuable on those terms.

Terms created by Mike Hoye - mhoye, 2025

Original: https://github.com/mhoye/maintenance-terms
{
    "name": "crell\/api-problem",
    "type": "library",
    "description": "PHP wrapper for the api-problem IETF specification",
    "license": "MIT",
    "keywords": [
        "api-problem",
        "rest",
        "http",
        "json",
        "xml"
    ],
    "homepage": "https:\/\/github.com\/Crell\/ApiProblem",
    "authors": [
        {
            "name": "Larry Garfield",
            "email": "larry@garfieldtech.com",
            "homepage": "http:\/\/www.garfieldtech.com\/"
        }
    ],
    "autoload": {
        "psr-4": {
            "_ContaoManager\\Crell\\ApiProblem\\": "src\/"
        }
    },
    "autoload-dev": {
        "psr-4": {
            "_ContaoManager\\Crell\\ApiProblem\\": "tests"
        }
    },
    "require": {
        "php": "^7.4 || ^8.0"
    },
    "suggest": {
        "psr\/http-message": "Common interface for HTTP messages",
        "psr\/http-factory": "Common interfaces for PSR-7 HTTP message factories"
    },
    "require-dev": {
        "nyholm\/psr7": "^1.8.2",
        "phpunit\/phpunit": "^7.0 || ^8.0 || ^9.6.31",
        "psr\/http-factory": "^1.1",
        "psr\/http-message": "^1.1",
        "phpstan\/phpstan": "^2.1.33"
    },
    "extra": {
        "branch-alias": {
            "dev-master": "2.0.x-dev"
        }
    },
    "scripts": {
        "test": "XDEBUG_MODE=develop,debug phpunit",
        "phpstan": "php -d memory_limit=256M vendor\/bin\/phpstan",
        "coverage": "XDEBUG_MODE=coverage vendor\/bin\/phpunit --coverage-text",
        "all-checks": [
            "@test",
            "@phpstan"
        ]
    }
}# Brand Promise

Perfect security is not an achievable goal, but it is a goal to strive for nonetheless.  To that end, we welcome responsible security reports from both users and external security researchers.

# Scope

If you believe you've found a security issue in software that is maintained in this repository, we encourage you to notify us.

| Version | In scope | Source code                         |
| ------- | -------- |-------------------------------------|
| latest  | ✅ | https://github.com/Crell/ApiProblem |

Only the latest stable release of this library is supported.  In general, bug and security fixes will not be backported unless there is a substantial imminent threat to users in not doing so.  

# How to Submit a Report

To submit a vulnerability report, please contact us through [GitHub](https://github.com/Crell/ApiProblem/security). Your submission will be reviewed as soon as feasible, but as this is a volunteer project we cannot guarantee a response time.

# Safe Harbor

We support safe harbor for security researchers who:

* Make a good faith effort to avoid privacy violations, destruction of data, and interruption or degradation of our services.
* Only interact with accounts you own or with explicit permission of the account holder. If you do encounter Personally Identifiable Information (PII) contact us immediately, do not proceed with access, and immediately purge any local information.
* Provide us with a reasonable amount of time to resolve vulnerabilities prior to any disclosure to the public or a third-party.

We will consider activities conducted consistent with this policy to constitute "authorized" conduct and will not pursue civil action or initiate a complaint to law enforcement. We will help to the extent we can if legal action is initiated by a third party against you.

Please submit a report to us before engaging in conduct that may be inconsistent with or unaddressed by this policy.

# Preferences

* Please provide detailed reports with reproducible steps and a clearly defined impact.
* Include the version number of the vulnerable package in your report.
* Providing a suggested fix is welcome, but not required, and we may choose to implement our own, based on your submitted fix or not.
* This is a volunteer project. We will make every effort to respond to security reports in a timely manner, but that may be a week or two on the first contact.

<?php

declare (strict_types=1);
namespace _ContaoManager\Crell\ApiProblem;

class JsonEncodeException extends JsonException
{
}
<?php

declare (strict_types=1);
namespace _ContaoManager\Crell\ApiProblem;

use _ContaoManager\Psr\Http\Message\ResponseFactoryInterface;
use _ContaoManager\Psr\Http\Message\ResponseInterface;
/**
 * Utility class to convert a problem object to an HTTP Response, using PSR-7/17.
 */
class HttpConverter
{
    protected ResponseFactoryInterface $responseFactory;
    /**
     * Whether or not the response body should be "pretty-printed".
     */
    protected bool $pretty;
    /**
     * HttpConverter constructor.
     *
     * @param ResponseFactoryInterface $responseFactory
     *   An HTTP Response factory that can give us a Response object.
     * @param bool $pretty
     *   Whether or not the response body should be pretty-printed.
     */
    public function __construct(ResponseFactoryInterface $responseFactory, bool $pretty = \false)
    {
        $this->responseFactory = $responseFactory;
        $this->pretty = $pretty;
    }
    /**
     * Converts a problem to a JSON HTTP Response object, provided.
     *
     * @param ApiProblem $problem
     *   The problem to convert.
     *
     * @return ResponseInterface
     *   The appropriate response object.
     */
    public function toJsonResponse(ApiProblem $problem): ResponseInterface
    {
        $response = $this->toResponse($problem);
        $body = $response->getBody();
        $body->write($problem->asJson($this->pretty));
        $body->rewind();
        return $response->withHeader('Content-Type', ApiProblem::CONTENT_TYPE_JSON)->withBody($body);
    }
    /**
     * Converts a problem to an XML HTTP Response object, provided.
     *
     * @param ApiProblem $problem
     *   The problem to convert.
     *
     * @return ResponseInterface
     *   The appropriate response object.
     */
    public function toXmlResponse(ApiProblem $problem): ResponseInterface
    {
        $response = $this->toResponse($problem);
        $body = $response->getBody();
        $body->write($problem->asXml($this->pretty));
        $body->rewind();
        return $this->toResponse($problem)->withHeader('Content-Type', ApiProblem::CONTENT_TYPE_XML)->withBody($body);
    }
    /**
     * Converts a problem to a provided Response, without the format-sensitive bits.
     *
     * @param ApiProblem $problem
     *   The problem to convert.
     *
     * @return ResponseInterface
     *   The appropriate response object.
     */
    protected function toResponse(ApiProblem $problem): ResponseInterface
    {
        $status = $problem->getStatus() ?: 500;
        return $this->responseFactory->createResponse($status);
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\Crell\ApiProblem;

class JsonParseException extends JsonException
{
    /**
     * JsonParseException constructor.
     *
     * This version forces a string for $failedValue, as that's the only thing that
     * could fail to parse, since that's all you can even try to parse.
     */
    public function __construct(string $message = '', int $code = 0, ?\Throwable $previous = null, string $failedValue = '')
    {
        parent::__construct($message, $code, $previous);
        $this->setFailedValue($failedValue);
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\Crell\ApiProblem;

class JsonException extends \InvalidArgumentException
{
    /**
     * This mapping is based on the PHP manual.
     *
     * Why this isn't built into the language somewhere I have no idea.
     */
    protected const EXCEPTION_MESSAGES = [\JSON_ERROR_DEPTH => 'Maximum stack depth exceeded', \JSON_ERROR_STATE_MISMATCH => 'Underflow or the modes mismatch', \JSON_ERROR_CTRL_CHAR => 'Unexpected control character found', \JSON_ERROR_SYNTAX => 'Syntax error, malformed JSON', \JSON_ERROR_UTF8 => 'Malformed UTF-8 characters, possibly incorrectly encoded', \JSON_ERROR_RECURSION => 'One or more recursive references in the value to be encoded', \JSON_ERROR_INF_OR_NAN => 'One or more NAN or INF values in the value to be encoded', \JSON_ERROR_UNSUPPORTED_TYPE => 'A value of a type that cannot be encoded was given', \JSON_ERROR_INVALID_PROPERTY_NAME => 'A property name that cannot be encoded was given', \JSON_ERROR_UTF16 => 'Malformed UTF-16 characters, possibly incorrectly encoded'];
    /**
     * @var mixed
     */
    protected $failedValue;
    /**
     * Maps a JSON error code to a human-friendly error message.
     *
     * @param int $jsonError
     *   the JSON error code, as returned by json_last_error().
     * @return string
     */
    protected static function getExceptionMessage(int $jsonError): string
    {
        return self::EXCEPTION_MESSAGES[$jsonError] ?? 'Unknown error';
    }
    /**
     * Creates a new exception object based on the JSON error code.
     *
     * @param int $jsonError
     *   the JSON error code.
     * @param mixed $failedValue
     *   The value that failed to parse or encode.
     * @return JsonException
     *   A new exception object.
     */
    public static function fromJsonError(int $jsonError, $failedValue): self
    {
        // This is a valid use of `new static`, even if PHPStan is wrong about it.
        // @phpstan-ignore-next-line
        return new static(static::getExceptionMessage($jsonError), $jsonError, null, $failedValue);
    }
    /**
     * @param mixed $failedValue
     */
    public function __construct(string $message = '', int $code = 0, ?\Throwable $previous = null, $failedValue = null)
    {
        parent::__construct($message, $code, $previous);
        $this->setFailedValue($failedValue);
    }
    /**
     * Sets the value that failed to parse or encode so it can be analyzed later.
     *
     * @param mixed $failedValue
     *   The value that failed to parse or encode correctly.
     * @return JsonException
     *   The invoked object.
     */
    public function setFailedValue($failedValue): self
    {
        $this->failedValue = $failedValue;
        return $this;
    }
    /**
     * Returns the value that failed to parse or encode properly.
     *
     * @return mixed
     *   The value that failed to process.
     */
    public function getFailedValue()
    {
        return $this->failedValue;
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\Crell\ApiProblem;

/**
 * An API error of some form.
 *
 * This object generates errors in compliance with RFC 9457 "API Problem".
 *
 * This object should be configured via the appropriate methods, and then
 * rendered using the asJson() or asXml() methods. The resulting string is
 * safe to then send in response to an HTTP request. When sent, the response
 * should have a mime type of application/problem+json or
 * application/problem+xml, as appropriate.
 *
 * Subclassing this class to provide defaults for different problem types for
 * your application is encouraged.
 *
 * For problem properties defined by the specification, use the methods provided
 * to get/set those values. For extended values, use the ArrayAccess interface
 * to specify arbitrary additional properties.
 *
 * @link http://tools.ietf.org/html/rfc9457
 *
 * @author Larry Garfield
 *
 * @implements \ArrayAccess<string, mixed> \JsonSerializable
 */
class ApiProblem implements \ArrayAccess, \JsonSerializable
{
    /**
     * The content type for a JSON based HTTP response carrying
     * problem details.
     *
     * @var string
     */
    public const CONTENT_TYPE_JSON = 'application/problem+json';
    /**
     * The content type for a XML based HTTP response carrying
     * problem details.
     *
     * @var string
     */
    public const CONTENT_TYPE_XML = 'application/problem+xml';
    /**
     *  A short, human-readable summary of the problem type.
     *
     *  It SHOULD NOT change from occurrence to occurrence of the problem,
     *  except for purposes of localization.
     */
    protected string $title;
    /**
     * A URI reference (RFC3986) that identifies the problem type.
     *
     * This specification encourages that, when dereferenced, it provide
     * human-readable documentation for the problem type (e.g., using HTML
     * [W3C.REC-html5-20141028]).  When this member is not present, its value
     * is assumed to be "about:blank".
     *
     * Consumers MUST use the type string as the primary identifier for the
     * problem type.
     *
     * This value may be an absolute or or relative URI. If relative, it MUST be
     * resolved relative to the document's base URI, as per RFC3986, Section 5.
     *
     * @link http://tools.ietf.org/html/rfc3986
     */
    protected string $type;
    /**
     * The HTTP status code set by the origin server for this occurrence of the problem.
     *
     * The status member, if present, is only advisory; it conveys the HTTP
     * status code used for the convenience of the consumer. Generators MUST
     * use the same status code in the actual HTTP response, to assure that
     * generic HTTP software that does not understand this format still behaves
     * correctly.
     */
    protected int $status = 0;
    /**
     * An human readable explanation specific to this occurrence of the problem.
     *
     * The "detail" member, if present, ought to focus on helping the client
     * correct the problem, rather than giving debugging information.
     *
     * Consumers SHOULD NOT parse the "detail" member for information; extensions
     * are more suitable and less error-prone ways to obtain such information.
     */
    protected string $detail = '';
    /**
     * A URI reference that identifies the specific occurrence of the problem.
     *
     * It may or may not yield further information if dereferenced.
     *
     * This value may be an absolute or or relative URI. If relative, it MUST be
     * resolved relative to the document's base URI, as per RFC3986, Section 5.
     *
     * @link http://tools.ietf.org/html/rfc3986
     */
    protected string $instance = '';
    /**
     * Any arbitrary extension properties that have been assigned on this object.
     *
     * @var array<string, string>
     */
    protected array $extensions = [];
    /**
     * Parses a JSON string into a Problem object.
     *
     * @param string $json
     *   The JSON string to parse.
     * @return ApiProblem
     *   A newly constructed problem object.
     *
     * @throws JsonParseException
     *   Invalid JSON strings will result in a thrown exception.
     */
    public static function fromJson(string $json): self
    {
        if (trim($json) === '') {
            throw new JsonParseException('An empty string is not a valid JSON value', \JSON_ERROR_SYNTAX, null, $json);
        }
        $parsed = json_decode($json, \true);
        $lastError = json_last_error();
        if (\JSON_ERROR_NONE !== $lastError) {
            throw JsonParseException::fromJsonError($lastError, $json);
        }
        return static::decompile($parsed);
    }
    /**
     * Converts a SimpleXMLElement to a nested array.
     *
     * @param \SimpleXMLElement $element
     *   The XML
     * @return array<mixed>
     *   A nested array corresponding to the XML element provided.
     */
    protected static function xmlToArray(\SimpleXMLElement $element): array
    {
        $data = (array) $element;
        foreach ($data as $key => $value) {
            if ($value instanceof \SimpleXMLElement) {
                $data[$key] = static::xmlToArray($value);
            }
        }
        return $data;
    }
    /**
     * Parses an XML string into a Problem object.
     *
     * @param string $string
     *   The XML string to parse.
     * @return ApiProblem
     *   A newly constructed problem object.
     */
    public static function fromXml(string $string): self
    {
        $xml = new \SimpleXMLElement($string);
        $data = static::xmlToArray($xml);
        return static::decompile($data);
    }
    /**
     * Parses an array into a Problem object.
     *
     * @param array<mixed> $input
     *   The array to parse.
     * @return ApiProblem
     *   A newly constructed problem object.
     */
    public static function fromArray(array $input): self
    {
        $defaultInput = ['title' => null, 'type' => null, 'status' => null, 'detail' => null, 'instance' => null];
        $data = $input + $defaultInput;
        return self::decompile($data);
    }
    /**
     * Decompiles an array into an ApiProblem object.
     *
     * @param array<mixed> $parsed
     *   An array parsed from JSON or XML to turn into an ApiProblem object.
     * @return ApiProblem
     *   A new ApiProblem object.
     */
    protected static function decompile(array $parsed): self
    {
        // This line is fine as long as the constructor has only optional arguments. That is a requirement
        // that cannot be enforced in code, but is effectively a requirement of the class.
        // @phpstan-ignore-next-line
        $problem = new static();
        if (null !== $title = self::filterStringValue('title', $parsed)) {
            $problem->setTitle($title);
        }
        if (null !== $type = self::filterStringValue('type', $parsed)) {
            $problem->setType($type);
        }
        if (null !== $status = self::filterIntValue('status', $parsed)) {
            $problem->setStatus($status);
        }
        if (null !== $detail = self::filterStringValue('detail', $parsed)) {
            $problem->setDetail($detail);
        }
        if (null !== $instance = self::filterStringValue('instance', $parsed)) {
            $problem->setInstance($instance);
        }
        // Remove the defined keys. That means whatever is left must be a custom
        // extension property.
        unset($parsed['title'], $parsed['type'], $parsed['status'], $parsed['detail'], $parsed['instance']);
        foreach ($parsed as $key => $value) {
            $problem[$key] = $value;
        }
        return $problem;
    }
    /**
     * Parse the incoming value as non empty string.
     * The returned value can be used to populate Problem string based properties.
     *
     * Skip empty string or missing values. The string 0, however is allowed.
     * PHP makes this ugly.
     * The check on string handles XML decompile which may return an empty array.
     *
     * @param string|int $key
     * @param array<int|string, mixed> $arr
     *
     * @return string|null
     */
    protected static function filterStringValue($key, array $arr): ?string
    {
        if (!array_key_exists($key, $arr) || !is_string($value = $arr[$key])) {
            return null;
        }
        if ($value === '') {
            return null;
        }
        return $value;
    }
    /**
     * Parse the incoming value as integer
     * The returned value can be used to populate Problem integer based properties.
     *
     * If the value can be parse as an integer it is return as one
     * otherwise null is returned.
     *
     * non integer value will all be discarded float included
     * @see https://3v4l.org/vZjLD
     * The check on scalar handles XML decompile which may return an empty array.
     *
     * @param int|string $key
     * @param array<int|string, mixed> $arr
     *
     * @return int|null
     */
    protected static function filterIntValue($key, array $arr): ?int
    {
        if (!array_key_exists($key, $arr) || !is_scalar($value = $arr[$key])) {
            return null;
        }
        $intValue = intval($value);
        if (strval($value) !== strval($intValue)) {
            return null;
        }
        return $intValue;
    }
    /**
     * Constructs a new ApiProblem.
     *
     * @param string $title
     *   A short, human-readable summary of the problem type.  It SHOULD NOT
     *   change from occurrence to occurrence of the problem, except for
     *   purposes of localization.
     * @param string $type
     *   An absolute URI (RFC3986) that identifies the problem type.  When
     *   dereferenced, it SHOULD provide human-readable documentation for the
     *   problem type (e.g., using HTML).
     */
    public function __construct(string $title = '', string $type = 'about:blank')
    {
        $this->title = $title;
        $this->type = $type;
    }
    /**
     * Retrieves the title of the problem.
     *
     * @return string
     *   The current title.
     */
    public function getTitle(): string
    {
        return $this->title;
    }
    /**
     * Sets the title for this problem.
     *
     * @param string $title
     *   The title to set.
     *  @return $this
     *   The invoked object.
     */
    public function setTitle(string $title): self
    {
        $this->title = $title;
        return $this;
    }
    /**
     * Retrieves the problem type of this problem.
     *
     * @return string
     *   The problem type URI of this problem.
     */
    public function getType(): string
    {
        return $this->type;
    }
    /**
     * Sets the problem type of this problem.
     *
     * @param string $type
     *   The resolvable problem type URI of this problem.
     * @return $this
     *   The invoked object.
     */
    public function setType(string $type): self
    {
        $this->type = $type;
        return $this;
    }
    /**
     * Retrieves the detail information of the problem.
     *
     * @return string
     *   The detail of this problem.
     */
    public function getDetail(): string
    {
        return $this->detail;
    }
    /**
     * Sets the detail for this problem.
     *
     * @param string $detail
     *   The human-readable detail string about this problem.
     * @return $this
     *   The invoked object.
     */
    public function setDetail(string $detail): self
    {
        $this->detail = $detail;
        return $this;
    }
    /**
     * Returns the problem instance URI of this problem.
     *
     * @return string
     *   The problem instance URI of this problem.
     */
    public function getInstance(): string
    {
        return $this->instance;
    }
    /**
     * Sets the problem instance URI of this problem.
     *
     * @param string $instance
     *   An absolute URI that uniquely identifies this problem. It MAY link to
     *   further information about the error, but that is not required.
     *
     * @return $this
     *   The invoked object.
     */
    public function setInstance(string $instance): self
    {
        $this->instance = $instance;
        return $this;
    }
    /**
     * Returns the current HTTP status code.
     *
     * @return int
     *   The current HTTP status code. If not set, it will return 0.
     */
    public function getStatus(): int
    {
        return $this->status;
    }
    /**
     * Sets the HTTP status code for this problem.
     *
     * It is an error for this value to be set to a different value than the
     * actual HTTP response code.
     *
     * @param int $status
     *   A valid HTTP status code.
     * @return $this
     *   The invoked object.
     */
    public function setStatus(int $status): self
    {
        $this->status = $status;
        return $this;
    }
    /**
     * Renders this problem as JSON.
     *
     * @param bool $pretty
     *   Whether or not to pretty-print the JSON string for easier debugging.
     * @return string
     *   A JSON string representing this problem.
     */
    public function asJson(bool $pretty = \false): string
    {
        $response = $this->compile();
        $options = 0;
        if ($pretty) {
            $options = \JSON_UNESCAPED_SLASHES | \JSON_PRETTY_PRINT;
        }
        $json = json_encode($response, $options);
        if (\false === $json) {
            throw JsonEncodeException::fromJsonError(\json_last_error(), $response);
        }
        return $json;
    }
    /**
     * Renders this problem as XML.
     *
     * @param bool $pretty
     *   Whether or not to pretty-print the XML string for easier debugging.
     * @return string
     *   An XML string representing this problem.
     */
    public function asXml(bool $pretty = \false): string
    {
        $doc = new \SimpleXMLElement('<problem></problem>');
        $this->arrayToXml($this->compile(), $doc);
        /** @var \DOMElement */
        $dom = dom_import_simplexml($doc);
        if ($pretty) {
            $dom->ownerDocument->preserveWhiteSpace = \false;
            $dom->ownerDocument->formatOutput = \true;
        }
        return $dom->ownerDocument->saveXML();
    }
    /**
     * Renders this problem as a native PHP array.
     *
     * This is mostly useful for debugging, or for placing
     * this problem response into, say, a Symfony JsonResponse object.
     *
     * @return array<mixed>
     *   The API problem represented as an array.
     */
    public function asArray(): array
    {
        return $this->compile();
    }
    /**
     * Supports rendering this problem as a JSON using the json_encode() function.
     *
     * @return array<mixed>
     *   The API problem represented as an array for rendering.
     */
    public function jsonSerialize(): array
    {
        return $this->compile();
    }
    /**
     * Compiles the object down to an array format, suitable for serializing.
     *
     * @return array<mixed>
     *   This object, rendered to an array.
     */
    protected function compile(): array
    {
        // Start with any extensions, since that's already an array.
        $response = $this->extensions;
        // These properties are optional.
        foreach (['title', 'type', 'status', 'detail', 'instance'] as $key) {
            // Skip empty string or missing values, as they are optional.
            // The string or integer 0, however, are allowed.  PHP makes
            // this ugly.
            if (isset($this->{$key}) && $this->{$key} !== 0 && $this->{$key} !== '') {
                $response[$key] = $this->{$key};
            }
        }
        return $response;
    }
    /**
     * Adds a nested array to a SimpleXML element.
     *
     * This method was shamelessly coped from the Nocarrier\Hal library:
     *
     * @link https://github.com/blongden/hal
     *
     * @param array<mixed> $data
     *   The data to add to the element.
     * @param \SimpleXMLElement $element
     *   The XML object to which to add data.
     * @param mixed $parent
     *   Used for internal recursion only.
     */
    protected function arrayToXml(array $data, \SimpleXMLElement $element, $parent = null): void
    {
        foreach ($data as $key => $value) {
            if (is_array($value)) {
                if (!is_numeric($key)) {
                    if (count($value) > 0 && isset($value[0])) {
                        $this->arrayToXml($value, $element, $key);
                    } else {
                        $subnode = $element->addChild($key);
                        $this->arrayToXml($value, $subnode, $key);
                    }
                } else {
                    $subnode = $element->addChild($parent);
                    $this->arrayToXml($value, $subnode, $parent);
                }
            } else if (!is_numeric($key)) {
                if ($key[0] === '@') {
                    $element->addAttribute(substr($key, 1), $value);
                } elseif ($key === 'value') {
                    $element->{0} = $value;
                } elseif (is_bool($value)) {
                    $element->addChild($key, strval($value));
                } else {
                    $element->addChild($key, htmlspecialchars((string) $value, \ENT_QUOTES));
                }
            } else {
                $element->addChild($parent, htmlspecialchars($value, \ENT_QUOTES));
            }
        }
    }
    /**
     * {@inheritdoc}
     * @param string $offset
     */
    public function offsetExists($offset): bool
    {
        return array_key_exists($offset, $this->extensions);
    }
    /**
     * {@inheritdoc}
     *
     * @param string $offset
     * @return mixed
     *
     * The proper return type here is `mixed`, which is only available as of 8.0.
     */
    #[\ReturnTypeWillChange]
    public function &offsetGet($offset)
    {
        return $this->extensions[$offset];
    }
    /**
     * {@inheritdoc}
     *
     * @param string $offset
     * @param mixed $value
     */
    public function offsetSet($offset, $value): void
    {
        $this->extensions[$offset] = $value;
    }
    /**
     * {@inheritdoc}
     *
     * @param string $offset
     */
    public function offsetUnset($offset): void
    {
        unset($this->extensions[$offset]);
    }
}
# Changelog

All notable changes to this project will be documented in this file, in reverse chronological order by release.

## 1.0.1 - 2016-08-06

### Fixed

- Make spacing consistent in phpdoc annotations php-fig/cache#9 - chalasr
- Fix grammar in phpdoc annotations php-fig/cache#10 - chalasr
- Be more specific in docblocks that `getItems()` and `deleteItems()` take an array of strings (`string[]`) compared to just `array` php-fig/cache#8 - GrahamCampbell
- For `expiresAt()` and `expiresAfter()` in CacheItemInterface fix docblock to specify null as a valid parameters as well as an implementation of DateTimeInterface php-fig/cache#7 - GrahamCampbell

## 1.0.0 - 2015-12-11

Initial stable release; reflects accepted PSR-6 specification
Caching Interface
==============

This repository holds all interfaces related to [PSR-6 (Caching Interface)][psr-url].

Note that this is not a Caching implementation of its own. It is merely interfaces that describe the components of a Caching mechanism.

The installable [package][package-url] and [implementations][implementation-url] are listed on Packagist.

[psr-url]: https://www.php-fig.org/psr/psr-6/
[package-url]: https://packagist.org/packages/psr/cache
[implementation-url]: https://packagist.org/providers/psr/cache-implementation
Copyright (c) 2015 PHP Framework Interoperability Group

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
{
    "name": "psr\/cache",
    "description": "Common interface for caching libraries",
    "keywords": [
        "psr",
        "psr-6",
        "cache"
    ],
    "license": "MIT",
    "authors": [
        {
            "name": "PHP-FIG",
            "homepage": "https:\/\/www.php-fig.org\/"
        }
    ],
    "require": {
        "php": ">=8.0.0"
    },
    "autoload": {
        "psr-4": {
            "_ContaoManager\\Psr\\Cache\\": "src\/"
        }
    },
    "extra": {
        "branch-alias": {
            "dev-master": "1.0.x-dev"
        }
    }
}<?php

namespace _ContaoManager\Psr\Cache;

/**
 * CacheItemPoolInterface generates CacheItemInterface objects.
 *
 * The primary purpose of Cache\CacheItemPoolInterface is to accept a key from
 * the Calling Library and return the associated Cache\CacheItemInterface object.
 * It is also the primary point of interaction with the entire cache collection.
 * All configuration and initialization of the Pool is left up to an
 * Implementing Library.
 */
interface CacheItemPoolInterface
{
    /**
     * Returns a Cache Item representing the specified key.
     *
     * This method must always return a CacheItemInterface object, even in case of
     * a cache miss. It MUST NOT return null.
     *
     * @param string $key
     *   The key for which to return the corresponding Cache Item.
     *
     * @throws InvalidArgumentException
     *   If the $key string is not a legal value a \Psr\Cache\InvalidArgumentException
     *   MUST be thrown.
     *
     * @return CacheItemInterface
     *   The corresponding Cache Item.
     */
    public function getItem(string $key): CacheItemInterface;
    /**
     * Returns a traversable set of cache items.
     *
     * @param string[] $keys
     *   An indexed array of keys of items to retrieve.
     *
     * @throws InvalidArgumentException
     *   If any of the keys in $keys are not a legal value a \Psr\Cache\InvalidArgumentException
     *   MUST be thrown.
     *
     * @return iterable
     *   An iterable collection of Cache Items keyed by the cache keys of
     *   each item. A Cache item will be returned for each key, even if that
     *   key is not found. However, if no keys are specified then an empty
     *   traversable MUST be returned instead.
     */
    public function getItems(array $keys = []): iterable;
    /**
     * Confirms if the cache contains specified cache item.
     *
     * Note: This method MAY avoid retrieving the cached value for performance reasons.
     * This could result in a race condition with CacheItemInterface::get(). To avoid
     * such situation use CacheItemInterface::isHit() instead.
     *
     * @param string $key
     *   The key for which to check existence.
     *
     * @throws InvalidArgumentException
     *   If the $key string is not a legal value a \Psr\Cache\InvalidArgumentException
     *   MUST be thrown.
     *
     * @return bool
     *   True if item exists in the cache, false otherwise.
     */
    public function hasItem(string $key): bool;
    /**
     * Deletes all items in the pool.
     *
     * @return bool
     *   True if the pool was successfully cleared. False if there was an error.
     */
    public function clear(): bool;
    /**
     * Removes the item from the pool.
     *
     * @param string $key
     *   The key to delete.
     *
     * @throws InvalidArgumentException
     *   If the $key string is not a legal value a \Psr\Cache\InvalidArgumentException
     *   MUST be thrown.
     *
     * @return bool
     *   True if the item was successfully removed. False if there was an error.
     */
    public function deleteItem(string $key): bool;
    /**
     * Removes multiple items from the pool.
     *
     * @param string[] $keys
     *   An array of keys that should be removed from the pool.
     *
     * @throws InvalidArgumentException
     *   If any of the keys in $keys are not a legal value a \Psr\Cache\InvalidArgumentException
     *   MUST be thrown.
     *
     * @return bool
     *   True if the items were successfully removed. False if there was an error.
     */
    public function deleteItems(array $keys): bool;
    /**
     * Persists a cache item immediately.
     *
     * @param CacheItemInterface $item
     *   The cache item to save.
     *
     * @return bool
     *   True if the item was successfully persisted. False if there was an error.
     */
    public function save(CacheItemInterface $item): bool;
    /**
     * Sets a cache item to be persisted later.
     *
     * @param CacheItemInterface $item
     *   The cache item to save.
     *
     * @return bool
     *   False if the item could not be queued or if a commit was attempted and failed. True otherwise.
     */
    public function saveDeferred(CacheItemInterface $item): bool;
    /**
     * Persists any deferred cache items.
     *
     * @return bool
     *   True if all not-yet-saved items were successfully saved or there were none. False otherwise.
     */
    public function commit(): bool;
}
<?php

namespace _ContaoManager\Psr\Cache;

/**
 * CacheItemInterface defines an interface for interacting with objects inside a cache.
 *
 * Each Item object MUST be associated with a specific key, which can be set
 * according to the implementing system and is typically passed by the
 * Cache\CacheItemPoolInterface object.
 *
 * The Cache\CacheItemInterface object encapsulates the storage and retrieval of
 * cache items. Each Cache\CacheItemInterface is generated by a
 * Cache\CacheItemPoolInterface object, which is responsible for any required
 * setup as well as associating the object with a unique Key.
 * Cache\CacheItemInterface objects MUST be able to store and retrieve any type
 * of PHP value defined in the Data section of the specification.
 *
 * Calling Libraries MUST NOT instantiate Item objects themselves. They may only
 * be requested from a Pool object via the getItem() method.  Calling Libraries
 * SHOULD NOT assume that an Item created by one Implementing Library is
 * compatible with a Pool from another Implementing Library.
 */
interface CacheItemInterface
{
    /**
     * Returns the key for the current cache item.
     *
     * The key is loaded by the Implementing Library, but should be available to
     * the higher level callers when needed.
     *
     * @return string
     *   The key string for this cache item.
     */
    public function getKey(): string;
    /**
     * Retrieves the value of the item from the cache associated with this object's key.
     *
     * The value returned must be identical to the value originally stored by set().
     *
     * If isHit() returns false, this method MUST return null. Note that null
     * is a legitimate cached value, so the isHit() method SHOULD be used to
     * differentiate between "null value was found" and "no value was found."
     *
     * @return mixed
     *   The value corresponding to this cache item's key, or null if not found.
     */
    public function get(): mixed;
    /**
     * Confirms if the cache item lookup resulted in a cache hit.
     *
     * Note: This method MUST NOT have a race condition between calling isHit()
     * and calling get().
     *
     * @return bool
     *   True if the request resulted in a cache hit. False otherwise.
     */
    public function isHit(): bool;
    /**
     * Sets the value represented by this cache item.
     *
     * The $value argument may be any item that can be serialized by PHP,
     * although the method of serialization is left up to the Implementing
     * Library.
     *
     * @param mixed $value
     *   The serializable value to be stored.
     *
     * @return static
     *   The invoked object.
     */
    public function set(mixed $value): static;
    /**
     * Sets the expiration time for this cache item.
     *
     * @param ?\DateTimeInterface $expiration
     *   The point in time after which the item MUST be considered expired.
     *   If null is passed explicitly, a default value MAY be used. If none is set,
     *   the value should be stored permanently or for as long as the
     *   implementation allows.
     *
     * @return static
     *   The called object.
     */
    public function expiresAt(?\DateTimeInterface $expiration): static;
    /**
     * Sets the expiration time for this cache item.
     *
     * @param int|\DateInterval|null $time
     *   The period of time from the present after which the item MUST be considered
     *   expired. An integer parameter is understood to be the time in seconds until
     *   expiration. If null is passed explicitly, a default value MAY be used.
     *   If none is set, the value should be stored permanently or for as long as the
     *   implementation allows.
     *
     * @return static
     *   The called object.
     */
    public function expiresAfter(int|\DateInterval|null $time): static;
}
<?php

namespace _ContaoManager\Psr\Cache;

/**
 * Exception interface for invalid cache arguments.
 *
 * Any time an invalid argument is passed into a method it must throw an
 * exception class which implements Psr\Cache\InvalidArgumentException.
 */
interface InvalidArgumentException extends CacheException
{
}
<?php

namespace _ContaoManager\Psr\Cache;

/**
 * Exception interface for all exceptions thrown by an Implementing Library.
 */
interface CacheException extends \Throwable
{
}
MIT License

Copyright (c) 2018 PHP-FIG

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
PSR Event Dispatcher
====================

This repository holds the interfaces related to [PSR-14](http://www.php-fig.org/psr/psr-14/).

Note that this is not an Event Dispatcher implementation of its own. It is merely interfaces that describe the components of an Event Dispatcher.  See the specification for more details.
{
    "name": "psr\/event-dispatcher",
    "description": "Standard interfaces for event handling.",
    "type": "library",
    "keywords": [
        "psr",
        "psr-14",
        "events"
    ],
    "license": "MIT",
    "authors": [
        {
            "name": "PHP-FIG",
            "homepage": "http:\/\/www.php-fig.org\/"
        }
    ],
    "require": {
        "php": ">=7.2.0"
    },
    "autoload": {
        "psr-4": {
            "_ContaoManager\\Psr\\EventDispatcher\\": "src\/"
        }
    },
    "extra": {
        "branch-alias": {
            "dev-master": "1.0.x-dev"
        }
    }
}<?php

declare (strict_types=1);
namespace _ContaoManager\Psr\EventDispatcher;

/**
 * Mapper from an event to the listeners that are applicable to that event.
 */
interface ListenerProviderInterface
{
    /**
     * @param object $event
     *   An event for which to return the relevant listeners.
     * @return iterable[callable]
     *   An iterable (array, iterator, or generator) of callables.  Each
     *   callable MUST be type-compatible with $event.
     */
    public function getListenersForEvent(object $event): iterable;
}
<?php

declare (strict_types=1);
namespace _ContaoManager\Psr\EventDispatcher;

/**
 * Defines a dispatcher for events.
 */
interface EventDispatcherInterface
{
    /**
     * Provide all relevant listeners with an event to process.
     *
     * @param object $event
     *   The object to process.
     *
     * @return object
     *   The Event that was passed, now modified by listeners.
     */
    public function dispatch(object $event);
}
<?php

declare (strict_types=1);
namespace _ContaoManager\Psr\EventDispatcher;

/**
 * An Event whose processing may be interrupted when the event has been handled.
 *
 * A Dispatcher implementation MUST check to determine if an Event
 * is marked as stopped after each listener is called.  If it is then it should
 * return immediately without calling any further Listeners.
 */
interface StoppableEventInterface
{
    /**
     * Is propagation stopped?
     *
     * This will typically only be used by the Dispatcher to determine if the
     * previous listener halted propagation.
     *
     * @return bool
     *   True if the Event is complete and no further listeners should be called.
     *   False to continue calling listeners.
     */
    public function isPropagationStopped(): bool;
}
Copyright (c) 2014 PHP Framework Interoperability Group

Permission is hereby granted, free of charge, to any person obtaining a copy 
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights 
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 
copies of the Software, and to permit persons to whom the Software is 
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in 
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
# Changelog

All notable changes to this project will be documented in this file, in reverse chronological order by release.

## 1.0.1 - 2016-08-06

### Added

- Nothing.

### Deprecated

- Nothing.

### Removed

- Nothing.

### Fixed

- Updated all `@return self` annotation references in interfaces to use
  `@return static`, which more closelly follows the semantics of the
  specification.
- Updated the `MessageInterface::getHeaders()` return annotation to use the
  value `string[][]`, indicating the format is a nested array of strings.
- Updated the `@link` annotation for `RequestInterface::withRequestTarget()`
  to point to the correct section of RFC 7230.
- Updated the `ServerRequestInterface::withUploadedFiles()` parameter annotation
  to add the parameter name (`$uploadedFiles`).
- Updated a `@throws` annotation for the `UploadedFileInterface::moveTo()`
  method to correctly reference the method parameter (it was referencing an
  incorrect parameter name previously).

## 1.0.0 - 2016-05-18

Initial stable release; reflects accepted PSR-7 specification.
PSR Http Message
================

This repository holds all interfaces/classes/traits related to
[PSR-7](http://www.php-fig.org/psr/psr-7/).

Note that this is not a HTTP message implementation of its own. It is merely an
interface that describes a HTTP message. See the specification for more details.

Usage
-----

Before reading the usage guide we recommend reading the PSR-7 interfaces method list:

* [`PSR-7 Interfaces Method List`](docs/PSR7-Interfaces.md)
* [`PSR-7 Usage Guide`](docs/PSR7-Usage.md){
    "name": "psr\/http-message",
    "description": "Common interface for HTTP messages",
    "keywords": [
        "psr",
        "psr-7",
        "http",
        "http-message",
        "request",
        "response"
    ],
    "homepage": "https:\/\/github.com\/php-fig\/http-message",
    "license": "MIT",
    "authors": [
        {
            "name": "PHP-FIG",
            "homepage": "https:\/\/www.php-fig.org\/"
        }
    ],
    "require": {
        "php": "^7.2 || ^8.0"
    },
    "autoload": {
        "psr-4": {
            "_ContaoManager\\Psr\\Http\\Message\\": "src\/"
        }
    },
    "extra": {
        "branch-alias": {
            "dev-master": "2.0.x-dev"
        }
    }
}<?php

namespace _ContaoManager\Psr\Http\Message;

/**
 * Representation of an incoming, server-side HTTP request.
 *
 * Per the HTTP specification, this interface includes properties for
 * each of the following:
 *
 * - Protocol version
 * - HTTP method
 * - URI
 * - Headers
 * - Message body
 *
 * Additionally, it encapsulates all data as it has arrived to the
 * application from the CGI and/or PHP environment, including:
 *
 * - The values represented in $_SERVER.
 * - Any cookies provided (generally via $_COOKIE)
 * - Query string arguments (generally via $_GET, or as parsed via parse_str())
 * - Upload files, if any (as represented by $_FILES)
 * - Deserialized body parameters (generally from $_POST)
 *
 * $_SERVER values MUST be treated as immutable, as they represent application
 * state at the time of request; as such, no methods are provided to allow
 * modification of those values. The other values provide such methods, as they
 * can be restored from $_SERVER or the request body, and may need treatment
 * during the application (e.g., body parameters may be deserialized based on
 * content type).
 *
 * Additionally, this interface recognizes the utility of introspecting a
 * request to derive and match additional parameters (e.g., via URI path
 * matching, decrypting cookie values, deserializing non-form-encoded body
 * content, matching authorization headers to users, etc). These parameters
 * are stored in an "attributes" property.
 *
 * Requests are considered immutable; all methods that might change state MUST
 * be implemented such that they retain the internal state of the current
 * message and return an instance that contains the changed state.
 */
interface ServerRequestInterface extends RequestInterface
{
    /**
     * Retrieve server parameters.
     *
     * Retrieves data related to the incoming request environment,
     * typically derived from PHP's $_SERVER superglobal. The data IS NOT
     * REQUIRED to originate from $_SERVER.
     *
     * @return array
     */
    public function getServerParams(): array;
    /**
     * Retrieve cookies.
     *
     * Retrieves cookies sent by the client to the server.
     *
     * The data MUST be compatible with the structure of the $_COOKIE
     * superglobal.
     *
     * @return array
     */
    public function getCookieParams(): array;
    /**
     * Return an instance with the specified cookies.
     *
     * The data IS NOT REQUIRED to come from the $_COOKIE superglobal, but MUST
     * be compatible with the structure of $_COOKIE. Typically, this data will
     * be injected at instantiation.
     *
     * This method MUST NOT update the related Cookie header of the request
     * instance, nor related values in the server params.
     *
     * This method MUST be implemented in such a way as to retain the
     * immutability of the message, and MUST return an instance that has the
     * updated cookie values.
     *
     * @param array $cookies Array of key/value pairs representing cookies.
     * @return static
     */
    public function withCookieParams(array $cookies): ServerRequestInterface;
    /**
     * Retrieve query string arguments.
     *
     * Retrieves the deserialized query string arguments, if any.
     *
     * Note: the query params might not be in sync with the URI or server
     * params. If you need to ensure you are only getting the original
     * values, you may need to parse the query string from `getUri()->getQuery()`
     * or from the `QUERY_STRING` server param.
     *
     * @return array
     */
    public function getQueryParams(): array;
    /**
     * Return an instance with the specified query string arguments.
     *
     * These values SHOULD remain immutable over the course of the incoming
     * request. They MAY be injected during instantiation, such as from PHP's
     * $_GET superglobal, or MAY be derived from some other value such as the
     * URI. In cases where the arguments are parsed from the URI, the data
     * MUST be compatible with what PHP's parse_str() would return for
     * purposes of how duplicate query parameters are handled, and how nested
     * sets are handled.
     *
     * Setting query string arguments MUST NOT change the URI stored by the
     * request, nor the values in the server params.
     *
     * This method MUST be implemented in such a way as to retain the
     * immutability of the message, and MUST return an instance that has the
     * updated query string arguments.
     *
     * @param array $query Array of query string arguments, typically from
     *     $_GET.
     * @return static
     */
    public function withQueryParams(array $query): ServerRequestInterface;
    /**
     * Retrieve normalized file upload data.
     *
     * This method returns upload metadata in a normalized tree, with each leaf
     * an instance of Psr\Http\Message\UploadedFileInterface.
     *
     * These values MAY be prepared from $_FILES or the message body during
     * instantiation, or MAY be injected via withUploadedFiles().
     *
     * @return array An array tree of UploadedFileInterface instances; an empty
     *     array MUST be returned if no data is present.
     */
    public function getUploadedFiles(): array;
    /**
     * Create a new instance with the specified uploaded files.
     *
     * This method MUST be implemented in such a way as to retain the
     * immutability of the message, and MUST return an instance that has the
     * updated body parameters.
     *
     * @param array $uploadedFiles An array tree of UploadedFileInterface instances.
     * @return static
     * @throws \InvalidArgumentException if an invalid structure is provided.
     */
    public function withUploadedFiles(array $uploadedFiles): ServerRequestInterface;
    /**
     * Retrieve any parameters provided in the request body.
     *
     * If the request Content-Type is either application/x-www-form-urlencoded
     * or multipart/form-data, and the request method is POST, this method MUST
     * return the contents of $_POST.
     *
     * Otherwise, this method may return any results of deserializing
     * the request body content; as parsing returns structured content, the
     * potential types MUST be arrays or objects only. A null value indicates
     * the absence of body content.
     *
     * @return null|array|object The deserialized body parameters, if any.
     *     These will typically be an array or object.
     */
    public function getParsedBody();
    /**
     * Return an instance with the specified body parameters.
     *
     * These MAY be injected during instantiation.
     *
     * If the request Content-Type is either application/x-www-form-urlencoded
     * or multipart/form-data, and the request method is POST, use this method
     * ONLY to inject the contents of $_POST.
     *
     * The data IS NOT REQUIRED to come from $_POST, but MUST be the results of
     * deserializing the request body content. Deserialization/parsing returns
     * structured data, and, as such, this method ONLY accepts arrays or objects,
     * or a null value if nothing was available to parse.
     *
     * As an example, if content negotiation determines that the request data
     * is a JSON payload, this method could be used to create a request
     * instance with the deserialized parameters.
     *
     * This method MUST be implemented in such a way as to retain the
     * immutability of the message, and MUST return an instance that has the
     * updated body parameters.
     *
     * @param null|array|object $data The deserialized body data. This will
     *     typically be in an array or object.
     * @return static
     * @throws \InvalidArgumentException if an unsupported argument type is
     *     provided.
     */
    public function withParsedBody($data): ServerRequestInterface;
    /**
     * Retrieve attributes derived from the request.
     *
     * The request "attributes" may be used to allow injection of any
     * parameters derived from the request: e.g., the results of path
     * match operations; the results of decrypting cookies; the results of
     * deserializing non-form-encoded message bodies; etc. Attributes
     * will be application and request specific, and CAN be mutable.
     *
     * @return array Attributes derived from the request.
     */
    public function getAttributes(): array;
    /**
     * Retrieve a single derived request attribute.
     *
     * Retrieves a single derived request attribute as described in
     * getAttributes(). If the attribute has not been previously set, returns
     * the default value as provided.
     *
     * This method obviates the need for a hasAttribute() method, as it allows
     * specifying a default value to return if the attribute is not found.
     *
     * @see getAttributes()
     * @param string $name The attribute name.
     * @param mixed $default Default value to return if the attribute does not exist.
     * @return mixed
     */
    public function getAttribute(string $name, $default = null);
    /**
     * Return an instance with the specified derived request attribute.
     *
     * This method allows setting a single derived request attribute as
     * described in getAttributes().
     *
     * This method MUST be implemented in such a way as to retain the
     * immutability of the message, and MUST return an instance that has the
     * updated attribute.
     *
     * @see getAttributes()
     * @param string $name The attribute name.
     * @param mixed $value The value of the attribute.
     * @return static
     */
    public function withAttribute(string $name, $value): ServerRequestInterface;
    /**
     * Return an instance that removes the specified derived request attribute.
     *
     * This method allows removing a single derived request attribute as
     * described in getAttributes().
     *
     * This method MUST be implemented in such a way as to retain the
     * immutability of the message, and MUST return an instance that removes
     * the attribute.
     *
     * @see getAttributes()
     * @param string $name The attribute name.
     * @return static
     */
    public function withoutAttribute(string $name): ServerRequestInterface;
}
<?php

namespace _ContaoManager\Psr\Http\Message;

/**
 * Value object representing a URI.
 *
 * This interface is meant to represent URIs according to RFC 3986 and to
 * provide methods for most common operations. Additional functionality for
 * working with URIs can be provided on top of the interface or externally.
 * Its primary use is for HTTP requests, but may also be used in other
 * contexts.
 *
 * Instances of this interface are considered immutable; all methods that
 * might change state MUST be implemented such that they retain the internal
 * state of the current instance and return an instance that contains the
 * changed state.
 *
 * Typically the Host header will be also be present in the request message.
 * For server-side requests, the scheme will typically be discoverable in the
 * server parameters.
 *
 * @link http://tools.ietf.org/html/rfc3986 (the URI specification)
 */
interface UriInterface
{
    /**
     * Retrieve the scheme component of the URI.
     *
     * If no scheme is present, this method MUST return an empty string.
     *
     * The value returned MUST be normalized to lowercase, per RFC 3986
     * Section 3.1.
     *
     * The trailing ":" character is not part of the scheme and MUST NOT be
     * added.
     *
     * @see https://tools.ietf.org/html/rfc3986#section-3.1
     * @return string The URI scheme.
     */
    public function getScheme(): string;
    /**
     * Retrieve the authority component of the URI.
     *
     * If no authority information is present, this method MUST return an empty
     * string.
     *
     * The authority syntax of the URI is:
     *
     * <pre>
     * [user-info@]host[:port]
     * </pre>
     *
     * If the port component is not set or is the standard port for the current
     * scheme, it SHOULD NOT be included.
     *
     * @see https://tools.ietf.org/html/rfc3986#section-3.2
     * @return string The URI authority, in "[user-info@]host[:port]" format.
     */
    public function getAuthority(): string;
    /**
     * Retrieve the user information component of the URI.
     *
     * If no user information is present, this method MUST return an empty
     * string.
     *
     * If a user is present in the URI, this will return that value;
     * additionally, if the password is also present, it will be appended to the
     * user value, with a colon (":") separating the values.
     *
     * The trailing "@" character is not part of the user information and MUST
     * NOT be added.
     *
     * @return string The URI user information, in "username[:password]" format.
     */
    public function getUserInfo(): string;
    /**
     * Retrieve the host component of the URI.
     *
     * If no host is present, this method MUST return an empty string.
     *
     * The value returned MUST be normalized to lowercase, per RFC 3986
     * Section 3.2.2.
     *
     * @see http://tools.ietf.org/html/rfc3986#section-3.2.2
     * @return string The URI host.
     */
    public function getHost(): string;
    /**
     * Retrieve the port component of the URI.
     *
     * If a port is present, and it is non-standard for the current scheme,
     * this method MUST return it as an integer. If the port is the standard port
     * used with the current scheme, this method SHOULD return null.
     *
     * If no port is present, and no scheme is present, this method MUST return
     * a null value.
     *
     * If no port is present, but a scheme is present, this method MAY return
     * the standard port for that scheme, but SHOULD return null.
     *
     * @return null|int The URI port.
     */
    public function getPort(): ?int;
    /**
     * Retrieve the path component of the URI.
     *
     * The path can either be empty or absolute (starting with a slash) or
     * rootless (not starting with a slash). Implementations MUST support all
     * three syntaxes.
     *
     * Normally, the empty path "" and absolute path "/" are considered equal as
     * defined in RFC 7230 Section 2.7.3. But this method MUST NOT automatically
     * do this normalization because in contexts with a trimmed base path, e.g.
     * the front controller, this difference becomes significant. It's the task
     * of the user to handle both "" and "/".
     *
     * The value returned MUST be percent-encoded, but MUST NOT double-encode
     * any characters. To determine what characters to encode, please refer to
     * RFC 3986, Sections 2 and 3.3.
     *
     * As an example, if the value should include a slash ("/") not intended as
     * delimiter between path segments, that value MUST be passed in encoded
     * form (e.g., "%2F") to the instance.
     *
     * @see https://tools.ietf.org/html/rfc3986#section-2
     * @see https://tools.ietf.org/html/rfc3986#section-3.3
     * @return string The URI path.
     */
    public function getPath(): string;
    /**
     * Retrieve the query string of the URI.
     *
     * If no query string is present, this method MUST return an empty string.
     *
     * The leading "?" character is not part of the query and MUST NOT be
     * added.
     *
     * The value returned MUST be percent-encoded, but MUST NOT double-encode
     * any characters. To determine what characters to encode, please refer to
     * RFC 3986, Sections 2 and 3.4.
     *
     * As an example, if a value in a key/value pair of the query string should
     * include an ampersand ("&") not intended as a delimiter between values,
     * that value MUST be passed in encoded form (e.g., "%26") to the instance.
     *
     * @see https://tools.ietf.org/html/rfc3986#section-2
     * @see https://tools.ietf.org/html/rfc3986#section-3.4
     * @return string The URI query string.
     */
    public function getQuery(): string;
    /**
     * Retrieve the fragment component of the URI.
     *
     * If no fragment is present, this method MUST return an empty string.
     *
     * The leading "#" character is not part of the fragment and MUST NOT be
     * added.
     *
     * The value returned MUST be percent-encoded, but MUST NOT double-encode
     * any characters. To determine what characters to encode, please refer to
     * RFC 3986, Sections 2 and 3.5.
     *
     * @see https://tools.ietf.org/html/rfc3986#section-2
     * @see https://tools.ietf.org/html/rfc3986#section-3.5
     * @return string The URI fragment.
     */
    public function getFragment(): string;
    /**
     * Return an instance with the specified scheme.
     *
     * This method MUST retain the state of the current instance, and return
     * an instance that contains the specified scheme.
     *
     * Implementations MUST support the schemes "http" and "https" case
     * insensitively, and MAY accommodate other schemes if required.
     *
     * An empty scheme is equivalent to removing the scheme.
     *
     * @param string $scheme The scheme to use with the new instance.
     * @return static A new instance with the specified scheme.
     * @throws \InvalidArgumentException for invalid or unsupported schemes.
     */
    public function withScheme(string $scheme): UriInterface;
    /**
     * Return an instance with the specified user information.
     *
     * This method MUST retain the state of the current instance, and return
     * an instance that contains the specified user information.
     *
     * Password is optional, but the user information MUST include the
     * user; an empty string for the user is equivalent to removing user
     * information.
     *
     * @param string $user The user name to use for authority.
     * @param null|string $password The password associated with $user.
     * @return static A new instance with the specified user information.
     */
    public function withUserInfo(string $user, ?string $password = null): UriInterface;
    /**
     * Return an instance with the specified host.
     *
     * This method MUST retain the state of the current instance, and return
     * an instance that contains the specified host.
     *
     * An empty host value is equivalent to removing the host.
     *
     * @param string $host The hostname to use with the new instance.
     * @return static A new instance with the specified host.
     * @throws \InvalidArgumentException for invalid hostnames.
     */
    public function withHost(string $host): UriInterface;
    /**
     * Return an instance with the specified port.
     *
     * This method MUST retain the state of the current instance, and return
     * an instance that contains the specified port.
     *
     * Implementations MUST raise an exception for ports outside the
     * established TCP and UDP port ranges.
     *
     * A null value provided for the port is equivalent to removing the port
     * information.
     *
     * @param null|int $port The port to use with the new instance; a null value
     *     removes the port information.
     * @return static A new instance with the specified port.
     * @throws \InvalidArgumentException for invalid ports.
     */
    public function withPort(?int $port): UriInterface;
    /**
     * Return an instance with the specified path.
     *
     * This method MUST retain the state of the current instance, and return
     * an instance that contains the specified path.
     *
     * The path can either be empty or absolute (starting with a slash) or
     * rootless (not starting with a slash). Implementations MUST support all
     * three syntaxes.
     *
     * If the path is intended to be domain-relative rather than path relative then
     * it must begin with a slash ("/"). Paths not starting with a slash ("/")
     * are assumed to be relative to some base path known to the application or
     * consumer.
     *
     * Users can provide both encoded and decoded path characters.
     * Implementations ensure the correct encoding as outlined in getPath().
     *
     * @param string $path The path to use with the new instance.
     * @return static A new instance with the specified path.
     * @throws \InvalidArgumentException for invalid paths.
     */
    public function withPath(string $path): UriInterface;
    /**
     * Return an instance with the specified query string.
     *
     * This method MUST retain the state of the current instance, and return
     * an instance that contains the specified query string.
     *
     * Users can provide both encoded and decoded query characters.
     * Implementations ensure the correct encoding as outlined in getQuery().
     *
     * An empty query string value is equivalent to removing the query string.
     *
     * @param string $query The query string to use with the new instance.
     * @return static A new instance with the specified query string.
     * @throws \InvalidArgumentException for invalid query strings.
     */
    public function withQuery(string $query): UriInterface;
    /**
     * Return an instance with the specified URI fragment.
     *
     * This method MUST retain the state of the current instance, and return
     * an instance that contains the specified URI fragment.
     *
     * Users can provide both encoded and decoded fragment characters.
     * Implementations ensure the correct encoding as outlined in getFragment().
     *
     * An empty fragment value is equivalent to removing the fragment.
     *
     * @param string $fragment The fragment to use with the new instance.
     * @return static A new instance with the specified fragment.
     */
    public function withFragment(string $fragment): UriInterface;
    /**
     * Return the string representation as a URI reference.
     *
     * Depending on which components of the URI are present, the resulting
     * string is either a full URI or relative reference according to RFC 3986,
     * Section 4.1. The method concatenates the various components of the URI,
     * using the appropriate delimiters:
     *
     * - If a scheme is present, it MUST be suffixed by ":".
     * - If an authority is present, it MUST be prefixed by "//".
     * - The path can be concatenated without delimiters. But there are two
     *   cases where the path has to be adjusted to make the URI reference
     *   valid as PHP does not allow to throw an exception in __toString():
     *     - If the path is rootless and an authority is present, the path MUST
     *       be prefixed by "/".
     *     - If the path is starting with more than one "/" and no authority is
     *       present, the starting slashes MUST be reduced to one.
     * - If a query is present, it MUST be prefixed by "?".
     * - If a fragment is present, it MUST be prefixed by "#".
     *
     * @see http://tools.ietf.org/html/rfc3986#section-4.1
     * @return string
     */
    public function __toString(): string;
}
<?php

namespace _ContaoManager\Psr\Http\Message;

/**
 * Describes a data stream.
 *
 * Typically, an instance will wrap a PHP stream; this interface provides
 * a wrapper around the most common operations, including serialization of
 * the entire stream to a string.
 */
interface StreamInterface
{
    /**
     * Reads all data from the stream into a string, from the beginning to end.
     *
     * This method MUST attempt to seek to the beginning of the stream before
     * reading data and read the stream until the end is reached.
     *
     * Warning: This could attempt to load a large amount of data into memory.
     *
     * This method MUST NOT raise an exception in order to conform with PHP's
     * string casting operations.
     *
     * @see http://php.net/manual/en/language.oop5.magic.php#object.tostring
     * @return string
     */
    public function __toString(): string;
    /**
     * Closes the stream and any underlying resources.
     *
     * @return void
     */
    public function close(): void;
    /**
     * Separates any underlying resources from the stream.
     *
     * After the stream has been detached, the stream is in an unusable state.
     *
     * @return resource|null Underlying PHP stream, if any
     */
    public function detach();
    /**
     * Get the size of the stream if known.
     *
     * @return int|null Returns the size in bytes if known, or null if unknown.
     */
    public function getSize(): ?int;
    /**
     * Returns the current position of the file read/write pointer
     *
     * @return int Position of the file pointer
     * @throws \RuntimeException on error.
     */
    public function tell(): int;
    /**
     * Returns true if the stream is at the end of the stream.
     *
     * @return bool
     */
    public function eof(): bool;
    /**
     * Returns whether or not the stream is seekable.
     *
     * @return bool
     */
    public function isSeekable(): bool;
    /**
     * Seek to a position in the stream.
     *
     * @link http://www.php.net/manual/en/function.fseek.php
     * @param int $offset Stream offset
     * @param int $whence Specifies how the cursor position will be calculated
     *     based on the seek offset. Valid values are identical to the built-in
     *     PHP $whence values for `fseek()`.  SEEK_SET: Set position equal to
     *     offset bytes SEEK_CUR: Set position to current location plus offset
     *     SEEK_END: Set position to end-of-stream plus offset.
     * @throws \RuntimeException on failure.
     */
    public function seek(int $offset, int $whence = \SEEK_SET): void;
    /**
     * Seek to the beginning of the stream.
     *
     * If the stream is not seekable, this method will raise an exception;
     * otherwise, it will perform a seek(0).
     *
     * @see seek()
     * @link http://www.php.net/manual/en/function.fseek.php
     * @throws \RuntimeException on failure.
     */
    public function rewind(): void;
    /**
     * Returns whether or not the stream is writable.
     *
     * @return bool
     */
    public function isWritable(): bool;
    /**
     * Write data to the stream.
     *
     * @param string $string The string that is to be written.
     * @return int Returns the number of bytes written to the stream.
     * @throws \RuntimeException on failure.
     */
    public function write(string $string): int;
    /**
     * Returns whether or not the stream is readable.
     *
     * @return bool
     */
    public function isReadable(): bool;
    /**
     * Read data from the stream.
     *
     * @param int $length Read up to $length bytes from the object and return
     *     them. Fewer than $length bytes may be returned if underlying stream
     *     call returns fewer bytes.
     * @return string Returns the data read from the stream, or an empty string
     *     if no bytes are available.
     * @throws \RuntimeException if an error occurs.
     */
    public function read(int $length): string;
    /**
     * Returns the remaining contents in a string
     *
     * @return string
     * @throws \RuntimeException if unable to read or an error occurs while
     *     reading.
     */
    public function getContents(): string;
    /**
     * Get stream metadata as an associative array or retrieve a specific key.
     *
     * The keys returned are identical to the keys returned from PHP's
     * stream_get_meta_data() function.
     *
     * @link http://php.net/manual/en/function.stream-get-meta-data.php
     * @param string|null $key Specific metadata to retrieve.
     * @return array|mixed|null Returns an associative array if no key is
     *     provided. Returns a specific key value if a key is provided and the
     *     value is found, or null if the key is not found.
     */
    public function getMetadata(?string $key = null);
}
<?php

namespace _ContaoManager\Psr\Http\Message;

/**
 * Value object representing a file uploaded through an HTTP request.
 *
 * Instances of this interface are considered immutable; all methods that
 * might change state MUST be implemented such that they retain the internal
 * state of the current instance and return an instance that contains the
 * changed state.
 */
interface UploadedFileInterface
{
    /**
     * Retrieve a stream representing the uploaded file.
     *
     * This method MUST return a StreamInterface instance, representing the
     * uploaded file. The purpose of this method is to allow utilizing native PHP
     * stream functionality to manipulate the file upload, such as
     * stream_copy_to_stream() (though the result will need to be decorated in a
     * native PHP stream wrapper to work with such functions).
     *
     * If the moveTo() method has been called previously, this method MUST raise
     * an exception.
     *
     * @return StreamInterface Stream representation of the uploaded file.
     * @throws \RuntimeException in cases when no stream is available or can be
     *     created.
     */
    public function getStream(): StreamInterface;
    /**
     * Move the uploaded file to a new location.
     *
     * Use this method as an alternative to move_uploaded_file(). This method is
     * guaranteed to work in both SAPI and non-SAPI environments.
     * Implementations must determine which environment they are in, and use the
     * appropriate method (move_uploaded_file(), rename(), or a stream
     * operation) to perform the operation.
     *
     * $targetPath may be an absolute path, or a relative path. If it is a
     * relative path, resolution should be the same as used by PHP's rename()
     * function.
     *
     * The original file or stream MUST be removed on completion.
     *
     * If this method is called more than once, any subsequent calls MUST raise
     * an exception.
     *
     * When used in an SAPI environment where $_FILES is populated, when writing
     * files via moveTo(), is_uploaded_file() and move_uploaded_file() SHOULD be
     * used to ensure permissions and upload status are verified correctly.
     *
     * If you wish to move to a stream, use getStream(), as SAPI operations
     * cannot guarantee writing to stream destinations.
     *
     * @see http://php.net/is_uploaded_file
     * @see http://php.net/move_uploaded_file
     * @param string $targetPath Path to which to move the uploaded file.
     * @throws \InvalidArgumentException if the $targetPath specified is invalid.
     * @throws \RuntimeException on any error during the move operation, or on
     *     the second or subsequent call to the method.
     */
    public function moveTo(string $targetPath): void;
    /**
     * Retrieve the file size.
     *
     * Implementations SHOULD return the value stored in the "size" key of
     * the file in the $_FILES array if available, as PHP calculates this based
     * on the actual size transmitted.
     *
     * @return int|null The file size in bytes or null if unknown.
     */
    public function getSize(): ?int;
    /**
     * Retrieve the error associated with the uploaded file.
     *
     * The return value MUST be one of PHP's UPLOAD_ERR_XXX constants.
     *
     * If the file was uploaded successfully, this method MUST return
     * UPLOAD_ERR_OK.
     *
     * Implementations SHOULD return the value stored in the "error" key of
     * the file in the $_FILES array.
     *
     * @see http://php.net/manual/en/features.file-upload.errors.php
     * @return int One of PHP's UPLOAD_ERR_XXX constants.
     */
    public function getError(): int;
    /**
     * Retrieve the filename sent by the client.
     *
     * Do not trust the value returned by this method. A client could send
     * a malicious filename with the intention to corrupt or hack your
     * application.
     *
     * Implementations SHOULD return the value stored in the "name" key of
     * the file in the $_FILES array.
     *
     * @return string|null The filename sent by the client or null if none
     *     was provided.
     */
    public function getClientFilename(): ?string;
    /**
     * Retrieve the media type sent by the client.
     *
     * Do not trust the value returned by this method. A client could send
     * a malicious media type with the intention to corrupt or hack your
     * application.
     *
     * Implementations SHOULD return the value stored in the "type" key of
     * the file in the $_FILES array.
     *
     * @return string|null The media type sent by the client or null if none
     *     was provided.
     */
    public function getClientMediaType(): ?string;
}
<?php

namespace _ContaoManager\Psr\Http\Message;

/**
 * Representation of an outgoing, client-side request.
 *
 * Per the HTTP specification, this interface includes properties for
 * each of the following:
 *
 * - Protocol version
 * - HTTP method
 * - URI
 * - Headers
 * - Message body
 *
 * During construction, implementations MUST attempt to set the Host header from
 * a provided URI if no Host header is provided.
 *
 * Requests are considered immutable; all methods that might change state MUST
 * be implemented such that they retain the internal state of the current
 * message and return an instance that contains the changed state.
 */
interface RequestInterface extends MessageInterface
{
    /**
     * Retrieves the message's request target.
     *
     * Retrieves the message's request-target either as it will appear (for
     * clients), as it appeared at request (for servers), or as it was
     * specified for the instance (see withRequestTarget()).
     *
     * In most cases, this will be the origin-form of the composed URI,
     * unless a value was provided to the concrete implementation (see
     * withRequestTarget() below).
     *
     * If no URI is available, and no request-target has been specifically
     * provided, this method MUST return the string "/".
     *
     * @return string
     */
    public function getRequestTarget(): string;
    /**
     * Return an instance with the specific request-target.
     *
     * If the request needs a non-origin-form request-target — e.g., for
     * specifying an absolute-form, authority-form, or asterisk-form —
     * this method may be used to create an instance with the specified
     * request-target, verbatim.
     *
     * This method MUST be implemented in such a way as to retain the
     * immutability of the message, and MUST return an instance that has the
     * changed request target.
     *
     * @link http://tools.ietf.org/html/rfc7230#section-5.3 (for the various
     *     request-target forms allowed in request messages)
     * @param string $requestTarget
     * @return static
     */
    public function withRequestTarget(string $requestTarget): RequestInterface;
    /**
     * Retrieves the HTTP method of the request.
     *
     * @return string Returns the request method.
     */
    public function getMethod(): string;
    /**
     * Return an instance with the provided HTTP method.
     *
     * While HTTP method names are typically all uppercase characters, HTTP
     * method names are case-sensitive and thus implementations SHOULD NOT
     * modify the given string.
     *
     * This method MUST be implemented in such a way as to retain the
     * immutability of the message, and MUST return an instance that has the
     * changed request method.
     *
     * @param string $method Case-sensitive method.
     * @return static
     * @throws \InvalidArgumentException for invalid HTTP methods.
     */
    public function withMethod(string $method): RequestInterface;
    /**
     * Retrieves the URI instance.
     *
     * This method MUST return a UriInterface instance.
     *
     * @link http://tools.ietf.org/html/rfc3986#section-4.3
     * @return UriInterface Returns a UriInterface instance
     *     representing the URI of the request.
     */
    public function getUri(): UriInterface;
    /**
     * Returns an instance with the provided URI.
     *
     * This method MUST update the Host header of the returned request by
     * default if the URI contains a host component. If the URI does not
     * contain a host component, any pre-existing Host header MUST be carried
     * over to the returned request.
     *
     * You can opt-in to preserving the original state of the Host header by
     * setting `$preserveHost` to `true`. When `$preserveHost` is set to
     * `true`, this method interacts with the Host header in the following ways:
     *
     * - If the Host header is missing or empty, and the new URI contains
     *   a host component, this method MUST update the Host header in the returned
     *   request.
     * - If the Host header is missing or empty, and the new URI does not contain a
     *   host component, this method MUST NOT update the Host header in the returned
     *   request.
     * - If a Host header is present and non-empty, this method MUST NOT update
     *   the Host header in the returned request.
     *
     * This method MUST be implemented in such a way as to retain the
     * immutability of the message, and MUST return an instance that has the
     * new UriInterface instance.
     *
     * @link http://tools.ietf.org/html/rfc3986#section-4.3
     * @param UriInterface $uri New request URI to use.
     * @param bool $preserveHost Preserve the original state of the Host header.
     * @return static
     */
    public function withUri(UriInterface $uri, bool $preserveHost = \false): RequestInterface;
}
<?php

namespace _ContaoManager\Psr\Http\Message;

/**
 * Representation of an outgoing, server-side response.
 *
 * Per the HTTP specification, this interface includes properties for
 * each of the following:
 *
 * - Protocol version
 * - Status code and reason phrase
 * - Headers
 * - Message body
 *
 * Responses are considered immutable; all methods that might change state MUST
 * be implemented such that they retain the internal state of the current
 * message and return an instance that contains the changed state.
 */
interface ResponseInterface extends MessageInterface
{
    /**
     * Gets the response status code.
     *
     * The status code is a 3-digit integer result code of the server's attempt
     * to understand and satisfy the request.
     *
     * @return int Status code.
     */
    public function getStatusCode(): int;
    /**
     * Return an instance with the specified status code and, optionally, reason phrase.
     *
     * If no reason phrase is specified, implementations MAY choose to default
     * to the RFC 7231 or IANA recommended reason phrase for the response's
     * status code.
     *
     * This method MUST be implemented in such a way as to retain the
     * immutability of the message, and MUST return an instance that has the
     * updated status and reason phrase.
     *
     * @link http://tools.ietf.org/html/rfc7231#section-6
     * @link http://www.iana.org/assignments/http-status-codes/http-status-codes.xhtml
     * @param int $code The 3-digit integer result code to set.
     * @param string $reasonPhrase The reason phrase to use with the
     *     provided status code; if none is provided, implementations MAY
     *     use the defaults as suggested in the HTTP specification.
     * @return static
     * @throws \InvalidArgumentException For invalid status code arguments.
     */
    public function withStatus(int $code, string $reasonPhrase = ''): ResponseInterface;
    /**
     * Gets the response reason phrase associated with the status code.
     *
     * Because a reason phrase is not a required element in a response
     * status line, the reason phrase value MAY be null. Implementations MAY
     * choose to return the default RFC 7231 recommended reason phrase (or those
     * listed in the IANA HTTP Status Code Registry) for the response's
     * status code.
     *
     * @link http://tools.ietf.org/html/rfc7231#section-6
     * @link http://www.iana.org/assignments/http-status-codes/http-status-codes.xhtml
     * @return string Reason phrase; must return an empty string if none present.
     */
    public function getReasonPhrase(): string;
}
<?php

namespace _ContaoManager\Psr\Http\Message;

/**
 * HTTP messages consist of requests from a client to a server and responses
 * from a server to a client. This interface defines the methods common to
 * each.
 *
 * Messages are considered immutable; all methods that might change state MUST
 * be implemented such that they retain the internal state of the current
 * message and return an instance that contains the changed state.
 *
 * @link http://www.ietf.org/rfc/rfc7230.txt
 * @link http://www.ietf.org/rfc/rfc7231.txt
 */
interface MessageInterface
{
    /**
     * Retrieves the HTTP protocol version as a string.
     *
     * The string MUST contain only the HTTP version number (e.g., "1.1", "1.0").
     *
     * @return string HTTP protocol version.
     */
    public function getProtocolVersion(): string;
    /**
     * Return an instance with the specified HTTP protocol version.
     *
     * The version string MUST contain only the HTTP version number (e.g.,
     * "1.1", "1.0").
     *
     * This method MUST be implemented in such a way as to retain the
     * immutability of the message, and MUST return an instance that has the
     * new protocol version.
     *
     * @param string $version HTTP protocol version
     * @return static
     */
    public function withProtocolVersion(string $version): MessageInterface;
    /**
     * Retrieves all message header values.
     *
     * The keys represent the header name as it will be sent over the wire, and
     * each value is an array of strings associated with the header.
     *
     *     // Represent the headers as a string
     *     foreach ($message->getHeaders() as $name => $values) {
     *         echo $name . ": " . implode(", ", $values);
     *     }
     *
     *     // Emit headers iteratively:
     *     foreach ($message->getHeaders() as $name => $values) {
     *         foreach ($values as $value) {
     *             header(sprintf('%s: %s', $name, $value), false);
     *         }
     *     }
     *
     * While header names are not case-sensitive, getHeaders() will preserve the
     * exact case in which headers were originally specified.
     *
     * @return string[][] Returns an associative array of the message's headers. Each
     *     key MUST be a header name, and each value MUST be an array of strings
     *     for that header.
     */
    public function getHeaders(): array;
    /**
     * Checks if a header exists by the given case-insensitive name.
     *
     * @param string $name Case-insensitive header field name.
     * @return bool Returns true if any header names match the given header
     *     name using a case-insensitive string comparison. Returns false if
     *     no matching header name is found in the message.
     */
    public function hasHeader(string $name): bool;
    /**
     * Retrieves a message header value by the given case-insensitive name.
     *
     * This method returns an array of all the header values of the given
     * case-insensitive header name.
     *
     * If the header does not appear in the message, this method MUST return an
     * empty array.
     *
     * @param string $name Case-insensitive header field name.
     * @return string[] An array of string values as provided for the given
     *    header. If the header does not appear in the message, this method MUST
     *    return an empty array.
     */
    public function getHeader(string $name): array;
    /**
     * Retrieves a comma-separated string of the values for a single header.
     *
     * This method returns all of the header values of the given
     * case-insensitive header name as a string concatenated together using
     * a comma.
     *
     * NOTE: Not all header values may be appropriately represented using
     * comma concatenation. For such headers, use getHeader() instead
     * and supply your own delimiter when concatenating.
     *
     * If the header does not appear in the message, this method MUST return
     * an empty string.
     *
     * @param string $name Case-insensitive header field name.
     * @return string A string of values as provided for the given header
     *    concatenated together using a comma. If the header does not appear in
     *    the message, this method MUST return an empty string.
     */
    public function getHeaderLine(string $name): string;
    /**
     * Return an instance with the provided value replacing the specified header.
     *
     * While header names are case-insensitive, the casing of the header will
     * be preserved by this function, and returned from getHeaders().
     *
     * This method MUST be implemented in such a way as to retain the
     * immutability of the message, and MUST return an instance that has the
     * new and/or updated header and value.
     *
     * @param string $name Case-insensitive header field name.
     * @param string|string[] $value Header value(s).
     * @return static
     * @throws \InvalidArgumentException for invalid header names or values.
     */
    public function withHeader(string $name, $value): MessageInterface;
    /**
     * Return an instance with the specified header appended with the given value.
     *
     * Existing values for the specified header will be maintained. The new
     * value(s) will be appended to the existing list. If the header did not
     * exist previously, it will be added.
     *
     * This method MUST be implemented in such a way as to retain the
     * immutability of the message, and MUST return an instance that has the
     * new header and/or value.
     *
     * @param string $name Case-insensitive header field name to add.
     * @param string|string[] $value Header value(s).
     * @return static
     * @throws \InvalidArgumentException for invalid header names or values.
     */
    public function withAddedHeader(string $name, $value): MessageInterface;
    /**
     * Return an instance without the specified header.
     *
     * Header resolution MUST be done without case-sensitivity.
     *
     * This method MUST be implemented in such a way as to retain the
     * immutability of the message, and MUST return an instance that removes
     * the named header.
     *
     * @param string $name Case-insensitive header field name to remove.
     * @return static
     */
    public function withoutHeader(string $name): MessageInterface;
    /**
     * Gets the body of the message.
     *
     * @return StreamInterface Returns the body as a stream.
     */
    public function getBody(): StreamInterface;
    /**
     * Return an instance with the specified message body.
     *
     * The body MUST be a StreamInterface object.
     *
     * This method MUST be implemented in such a way as to retain the
     * immutability of the message, and MUST return a new instance that has the
     * new body stream.
     *
     * @param StreamInterface $body Body.
     * @return static
     * @throws \InvalidArgumentException When the body is not valid.
     */
    public function withBody(StreamInterface $body): MessageInterface;
}
The MIT License (MIT)

Copyright (c) 2013-2016 container-interop
Copyright (c) 2016 PHP Framework Interoperability Group

Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Container interface
==============

This repository holds all interfaces related to [PSR-11 (Container Interface)][psr-url].

Note that this is not a Container implementation of its own. It is merely abstractions that describe the components of a Dependency Injection Container.

The installable [package][package-url] and [implementations][implementation-url] are listed on Packagist.

[psr-url]: https://www.php-fig.org/psr/psr-11/
[package-url]: https://packagist.org/packages/psr/container
[implementation-url]: https://packagist.org/providers/psr/container-implementation

{
    "name": "psr\/container",
    "type": "library",
    "description": "Common Container Interface (PHP FIG PSR-11)",
    "keywords": [
        "psr",
        "psr-11",
        "container",
        "container-interop",
        "container-interface"
    ],
    "homepage": "https:\/\/github.com\/php-fig\/container",
    "license": "MIT",
    "authors": [
        {
            "name": "PHP-FIG",
            "homepage": "https:\/\/www.php-fig.org\/"
        }
    ],
    "require": {
        "php": ">=7.4.0"
    },
    "autoload": {
        "psr-4": {
            "_ContaoManager\\Psr\\Container\\": "src\/"
        }
    },
    "extra": {
        "branch-alias": {
            "dev-master": "2.0.x-dev"
        }
    }
}<?php

namespace _ContaoManager\Psr\Container;

/**
 * No entry was found in the container.
 */
interface NotFoundExceptionInterface extends ContainerExceptionInterface
{
}
<?php

declare (strict_types=1);
namespace _ContaoManager\Psr\Container;

/**
 * Describes the interface of a container that exposes methods to read its entries.
 */
interface ContainerInterface
{
    /**
     * Finds an entry of the container by its identifier and returns it.
     *
     * @param string $id Identifier of the entry to look for.
     *
     * @throws NotFoundExceptionInterface  No entry was found for **this** identifier.
     * @throws ContainerExceptionInterface Error while retrieving the entry.
     *
     * @return mixed Entry.
     */
    public function get(string $id);
    /**
     * Returns true if the container can return an entry for the given identifier.
     * Returns false otherwise.
     *
     * `has($id)` returning true does not mean that `get($id)` will not throw an exception.
     * It does however mean that `get($id)` will not throw a `NotFoundExceptionInterface`.
     *
     * @param string $id Identifier of the entry to look for.
     *
     * @return bool
     */
    public function has(string $id): bool;
}
<?php

namespace _ContaoManager\Psr\Container;

use Throwable;
/**
 * Base interface representing a generic exception in a container.
 */
interface ContainerExceptionInterface extends Throwable
{
}
Copyright (c) 2017 PHP Framework Interoperability Group

Permission is hereby granted, free of charge, to any person obtaining a copy 
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights 
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 
copies of the Software, and to permit persons to whom the Software is 
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in 
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
# Changelog

All notable changes to this project will be documented in this file, in reverse chronological order by release.

## 1.0.3

Add `source` link in composer.json. No code changes.

## 1.0.2

Allow PSR-7 (psr/http-message) 2.0. No code changes.

## 1.0.1

Allow installation with PHP 8. No code changes.

## 1.0.0

First stable release. No changes since 0.3.0.

## 0.3.0

Added Interface suffix on exceptions
 
## 0.2.0 

All exceptions are in `Psr\Http\Client` namespace

## 0.1.0

First release
HTTP Client
===========

This repository holds all the common code related to [PSR-18 (HTTP Client)][psr-url].

Note that this is not a HTTP Client implementation of its own. It is merely abstractions that describe the components of a HTTP Client.

The installable [package][package-url] and [implementations][implementation-url] are listed on Packagist.

[psr-url]: https://www.php-fig.org/psr/psr-18
[package-url]: https://packagist.org/packages/psr/http-client
[implementation-url]: https://packagist.org/providers/psr/http-client-implementation
{
    "name": "psr\/http-client",
    "description": "Common interface for HTTP clients",
    "keywords": [
        "psr",
        "psr-18",
        "http",
        "http-client"
    ],
    "homepage": "https:\/\/github.com\/php-fig\/http-client",
    "license": "MIT",
    "authors": [
        {
            "name": "PHP-FIG",
            "homepage": "https:\/\/www.php-fig.org\/"
        }
    ],
    "support": {
        "source": "https:\/\/github.com\/php-fig\/http-client"
    },
    "require": {
        "php": "^7.0 || ^8.0",
        "psr\/http-message": "^1.0 || ^2.0"
    },
    "autoload": {
        "psr-4": {
            "_ContaoManager\\Psr\\Http\\Client\\": "src\/"
        }
    },
    "extra": {
        "branch-alias": {
            "dev-master": "1.0.x-dev"
        }
    }
}<?php

namespace _ContaoManager\Psr\Http\Client;

use _ContaoManager\Psr\Http\Message\RequestInterface;
/**
 * Thrown when the request cannot be completed because of network issues.
 *
 * There is no response object as this exception is thrown when no response has been received.
 *
 * Example: the target host name can not be resolved or the connection failed.
 */
interface NetworkExceptionInterface extends ClientExceptionInterface
{
    /**
     * Returns the request.
     *
     * The request object MAY be a different object from the one passed to ClientInterface::sendRequest()
     *
     * @return RequestInterface
     */
    public function getRequest(): RequestInterface;
}
<?php

namespace _ContaoManager\Psr\Http\Client;

use _ContaoManager\Psr\Http\Message\RequestInterface;
/**
 * Exception for when a request failed.
 *
 * Examples:
 *      - Request is invalid (e.g. method is missing)
 *      - Runtime request errors (e.g. the body stream is not seekable)
 */
interface RequestExceptionInterface extends ClientExceptionInterface
{
    /**
     * Returns the request.
     *
     * The request object MAY be a different object from the one passed to ClientInterface::sendRequest()
     *
     * @return RequestInterface
     */
    public function getRequest(): RequestInterface;
}
<?php

namespace _ContaoManager\Psr\Http\Client;

use _ContaoManager\Psr\Http\Message\RequestInterface;
use _ContaoManager\Psr\Http\Message\ResponseInterface;
interface ClientInterface
{
    /**
     * Sends a PSR-7 request and returns a PSR-7 response.
     *
     * @param RequestInterface $request
     *
     * @return ResponseInterface
     *
     * @throws \Psr\Http\Client\ClientExceptionInterface If an error happens while processing the request.
     */
    public function sendRequest(RequestInterface $request): ResponseInterface;
}
<?php

namespace _ContaoManager\Psr\Http\Client;

/**
 * Every HTTP client related exception MUST implement this interface.
 */
interface ClientExceptionInterface extends \Throwable
{
}
Copyright (c) 2012 PHP Framework Interoperability Group

Permission is hereby granted, free of charge, to any person obtaining a copy 
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights 
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 
copies of the Software, and to permit persons to whom the Software is 
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in 
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
PSR Log
=======

This repository holds all interfaces/classes/traits related to
[PSR-3](https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-3-logger-interface.md).

Note that this is not a logger of its own. It is merely an interface that
describes a logger. See the specification for more details.

Installation
------------

```bash
composer require psr/log
```

Usage
-----

If you need a logger, you can use the interface like this:

```php
<?php

use Psr\Log\LoggerInterface;

class Foo
{
    private $logger;

    public function __construct(LoggerInterface $logger = null)
    {
        $this->logger = $logger;
    }

    public function doSomething()
    {
        if ($this->logger) {
            $this->logger->info('Doing work');
        }
           
        try {
            $this->doSomethingElse();
        } catch (Exception $exception) {
            $this->logger->error('Oh no!', array('exception' => $exception));
        }

        // do something useful
    }
}
```

You can then pick one of the implementations of the interface to get a logger.

If you want to implement the interface, you can require this package and
implement `Psr\Log\LoggerInterface` in your code. Please read the
[specification text](https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-3-logger-interface.md)
for details.
{
    "name": "psr\/log",
    "description": "Common interface for logging libraries",
    "keywords": [
        "psr",
        "psr-3",
        "log"
    ],
    "homepage": "https:\/\/github.com\/php-fig\/log",
    "license": "MIT",
    "authors": [
        {
            "name": "PHP-FIG",
            "homepage": "https:\/\/www.php-fig.org\/"
        }
    ],
    "require": {
        "php": ">=8.0.0"
    },
    "autoload": {
        "psr-4": {
            "_ContaoManager\\Psr\\Log\\": "src"
        }
    },
    "extra": {
        "branch-alias": {
            "dev-master": "3.x-dev"
        }
    }
}<?php

namespace _ContaoManager\Psr\Log;

/**
 * Describes a logger-aware instance.
 */
interface LoggerAwareInterface
{
    /**
     * Sets a logger instance on the object.
     */
    public function setLogger(LoggerInterface $logger): void;
}
<?php

namespace _ContaoManager\Psr\Log;

/**
 * Describes log levels.
 */
class LogLevel
{
    const EMERGENCY = 'emergency';
    const ALERT = 'alert';
    const CRITICAL = 'critical';
    const ERROR = 'error';
    const WARNING = 'warning';
    const NOTICE = 'notice';
    const INFO = 'info';
    const DEBUG = 'debug';
}
<?php

namespace _ContaoManager\Psr\Log;

/**
 * Basic Implementation of LoggerAwareInterface.
 */
trait LoggerAwareTrait
{
    /**
     * The logger instance.
     */
    protected ?LoggerInterface $logger = null;
    /**
     * Sets a logger.
     */
    public function setLogger(LoggerInterface $logger): void
    {
        $this->logger = $logger;
    }
}
<?php

namespace _ContaoManager\Psr\Log;

class InvalidArgumentException extends \InvalidArgumentException
{
}
<?php

namespace _ContaoManager\Psr\Log;

/**
 * This Logger can be used to avoid conditional log calls.
 *
 * Logging should always be optional, and if no logger is provided to your
 * library creating a NullLogger instance to have something to throw logs at
 * is a good way to avoid littering your code with `if ($this->logger) { }`
 * blocks.
 */
class NullLogger extends AbstractLogger
{
    /**
     * Logs with an arbitrary level.
     *
     * @param mixed[] $context
     *
     * @throws \Psr\Log\InvalidArgumentException
     */
    public function log($level, string|\Stringable $message, array $context = []): void
    {
        // noop
    }
}
<?php

namespace _ContaoManager\Psr\Log;

/**
 * Describes a logger instance.
 *
 * The message MUST be a string or object implementing __toString().
 *
 * The message MAY contain placeholders in the form: {foo} where foo
 * will be replaced by the context data in key "foo".
 *
 * The context array can contain arbitrary data. The only assumption that
 * can be made by implementors is that if an Exception instance is given
 * to produce a stack trace, it MUST be in a key named "exception".
 *
 * See https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-3-logger-interface.md
 * for the full interface specification.
 */
interface LoggerInterface
{
    /**
     * System is unusable.
     *
     * @param mixed[] $context
     */
    public function emergency(string|\Stringable $message, array $context = []): void;
    /**
     * Action must be taken immediately.
     *
     * Example: Entire website down, database unavailable, etc. This should
     * trigger the SMS alerts and wake you up.
     *
     * @param mixed[] $context
     */
    public function alert(string|\Stringable $message, array $context = []): void;
    /**
     * Critical conditions.
     *
     * Example: Application component unavailable, unexpected exception.
     *
     * @param mixed[] $context
     */
    public function critical(string|\Stringable $message, array $context = []): void;
    /**
     * Runtime errors that do not require immediate action but should typically
     * be logged and monitored.
     *
     * @param mixed[] $context
     */
    public function error(string|\Stringable $message, array $context = []): void;
    /**
     * Exceptional occurrences that are not errors.
     *
     * Example: Use of deprecated APIs, poor use of an API, undesirable things
     * that are not necessarily wrong.
     *
     * @param mixed[] $context
     */
    public function warning(string|\Stringable $message, array $context = []): void;
    /**
     * Normal but significant events.
     *
     * @param mixed[] $context
     */
    public function notice(string|\Stringable $message, array $context = []): void;
    /**
     * Interesting events.
     *
     * Example: User logs in, SQL logs.
     *
     * @param mixed[] $context
     */
    public function info(string|\Stringable $message, array $context = []): void;
    /**
     * Detailed debug information.
     *
     * @param mixed[] $context
     */
    public function debug(string|\Stringable $message, array $context = []): void;
    /**
     * Logs with an arbitrary level.
     *
     * @param mixed $level
     * @param mixed[] $context
     *
     * @throws \Psr\Log\InvalidArgumentException
     */
    public function log($level, string|\Stringable $message, array $context = []): void;
}
<?php

namespace _ContaoManager\Psr\Log;

/**
 * This is a simple Logger trait that classes unable to extend AbstractLogger
 * (because they extend another class, etc) can include.
 *
 * It simply delegates all log-level-specific methods to the `log` method to
 * reduce boilerplate code that a simple Logger that does the same thing with
 * messages regardless of the error level has to implement.
 */
trait LoggerTrait
{
    /**
     * System is unusable.
     */
    public function emergency(string|\Stringable $message, array $context = []): void
    {
        $this->log(LogLevel::EMERGENCY, $message, $context);
    }
    /**
     * Action must be taken immediately.
     *
     * Example: Entire website down, database unavailable, etc. This should
     * trigger the SMS alerts and wake you up.
     */
    public function alert(string|\Stringable $message, array $context = []): void
    {
        $this->log(LogLevel::ALERT, $message, $context);
    }
    /**
     * Critical conditions.
     *
     * Example: Application component unavailable, unexpected exception.
     */
    public function critical(string|\Stringable $message, array $context = []): void
    {
        $this->log(LogLevel::CRITICAL, $message, $context);
    }
    /**
     * Runtime errors that do not require immediate action but should typically
     * be logged and monitored.
     */
    public function error(string|\Stringable $message, array $context = []): void
    {
        $this->log(LogLevel::ERROR, $message, $context);
    }
    /**
     * Exceptional occurrences that are not errors.
     *
     * Example: Use of deprecated APIs, poor use of an API, undesirable things
     * that are not necessarily wrong.
     */
    public function warning(string|\Stringable $message, array $context = []): void
    {
        $this->log(LogLevel::WARNING, $message, $context);
    }
    /**
     * Normal but significant events.
     */
    public function notice(string|\Stringable $message, array $context = []): void
    {
        $this->log(LogLevel::NOTICE, $message, $context);
    }
    /**
     * Interesting events.
     *
     * Example: User logs in, SQL logs.
     */
    public function info(string|\Stringable $message, array $context = []): void
    {
        $this->log(LogLevel::INFO, $message, $context);
    }
    /**
     * Detailed debug information.
     */
    public function debug(string|\Stringable $message, array $context = []): void
    {
        $this->log(LogLevel::DEBUG, $message, $context);
    }
    /**
     * Logs with an arbitrary level.
     *
     * @param mixed $level
     *
     * @throws \Psr\Log\InvalidArgumentException
     */
    abstract public function log($level, string|\Stringable $message, array $context = []): void;
}
<?php

namespace _ContaoManager\Psr\Log;

/**
 * This is a simple Logger implementation that other Loggers can inherit from.
 *
 * It simply delegates all log-level-specific methods to the `log` method to
 * reduce boilerplate code that a simple Logger that does the same thing with
 * messages regardless of the error level has to implement.
 */
abstract class AbstractLogger implements LoggerInterface
{
    use LoggerTrait;
}
Copyright (c) 2017 PHP Framework Interoperability Group

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
# Changelog

All notable changes to this project will be documented in this file, in reverse chronological order by release.

## 1.0.0

First stable release after PSR-20 acceptance

## 0.1.0

First release
# PSR Clock

This repository holds the interface for [PSR-20][psr-url].

Note that this is not a clock of its own. It is merely an interface that
describes a clock. See the specification for more details.

## Installation

```bash
composer require psr/clock
```

## Usage

If you need a clock, you can use the interface like this:

```php
<?php

use Psr\Clock\ClockInterface;

class Foo
{
    private ClockInterface $clock;

    public function __construct(ClockInterface $clock)
    {
        $this->clock = $clock;
    }

    public function doSomething()
    {
        /** @var DateTimeImmutable $currentDateAndTime */
        $currentDateAndTime = $this->clock->now();
        // do something useful with that information
    }
}
```

You can then pick one of the [implementations][implementation-url] of the interface to get a clock.

If you want to implement the interface, you can require this package and
implement `Psr\Clock\ClockInterface` in your code. 

Don't forget to add `psr/clock-implementation` to your `composer.json`s `provides`-section like this:

```json
{
  "provides": {
    "psr/clock-implementation": "1.0"
  }
}
```

And please read the [specification text][specification-url] for details on the interface.

[psr-url]: https://www.php-fig.org/psr/psr-20
[package-url]: https://packagist.org/packages/psr/clock
[implementation-url]: https://packagist.org/providers/psr/clock-implementation
[specification-url]: https://github.com/php-fig/fig-standards/blob/master/proposed/clock.md
{
    "name": "psr\/clock",
    "description": "Common interface for reading the clock.",
    "keywords": [
        "psr",
        "psr-20",
        "time",
        "clock",
        "now"
    ],
    "homepage": "https:\/\/github.com\/php-fig\/clock",
    "license": "MIT",
    "authors": [
        {
            "name": "PHP-FIG",
            "homepage": "https:\/\/www.php-fig.org\/"
        }
    ],
    "require": {
        "php": "^7.0 || ^8.0"
    },
    "autoload": {
        "psr-4": {
            "_ContaoManager\\Psr\\Clock\\": "src\/"
        }
    }
}<?php

namespace _ContaoManager\Psr\Clock;

use DateTimeImmutable;
interface ClockInterface
{
    /**
     * Returns the current time as a DateTimeImmutable Object
     */
    public function now(): DateTimeImmutable;
}
MIT License

Copyright (c) 2018 PHP-FIG

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
HTTP Factories
==============

This repository holds all interfaces related to [PSR-17 (HTTP Factories)][psr-url].

Note that this is not a HTTP Factory implementation of its own. It is merely interfaces that describe the components of a HTTP Factory.

The installable [package][package-url] and [implementations][implementation-url] are listed on Packagist.

[psr-url]: https://www.php-fig.org/psr/psr-17/
[package-url]: https://packagist.org/packages/psr/http-factory
[implementation-url]: https://packagist.org/providers/psr/http-factory-implementation
{
    "name": "psr\/http-factory",
    "description": "PSR-17: Common interfaces for PSR-7 HTTP message factories",
    "keywords": [
        "psr",
        "psr-7",
        "psr-17",
        "http",
        "factory",
        "message",
        "request",
        "response"
    ],
    "license": "MIT",
    "authors": [
        {
            "name": "PHP-FIG",
            "homepage": "https:\/\/www.php-fig.org\/"
        }
    ],
    "support": {
        "source": "https:\/\/github.com\/php-fig\/http-factory"
    },
    "require": {
        "php": ">=7.1",
        "psr\/http-message": "^1.0 || ^2.0"
    },
    "autoload": {
        "psr-4": {
            "_ContaoManager\\Psr\\Http\\Message\\": "src\/"
        }
    },
    "extra": {
        "branch-alias": {
            "dev-master": "1.0.x-dev"
        }
    }
}<?php

namespace _ContaoManager\Psr\Http\Message;

interface ResponseFactoryInterface
{
    /**
     * Create a new response.
     *
     * @param int $code HTTP status code; defaults to 200
     * @param string $reasonPhrase Reason phrase to associate with status code
     *     in generated response; if none is provided implementations MAY use
     *     the defaults as suggested in the HTTP specification.
     *
     * @return ResponseInterface
     */
    public function createResponse(int $code = 200, string $reasonPhrase = ''): ResponseInterface;
}
<?php

namespace _ContaoManager\Psr\Http\Message;

interface StreamFactoryInterface
{
    /**
     * Create a new stream from a string.
     *
     * The stream SHOULD be created with a temporary resource.
     *
     * @param string $content String content with which to populate the stream.
     *
     * @return StreamInterface
     */
    public function createStream(string $content = ''): StreamInterface;
    /**
     * Create a stream from an existing file.
     *
     * The file MUST be opened using the given mode, which may be any mode
     * supported by the `fopen` function.
     *
     * The `$filename` MAY be any string supported by `fopen()`.
     *
     * @param string $filename Filename or stream URI to use as basis of stream.
     * @param string $mode Mode with which to open the underlying filename/stream.
     *
     * @return StreamInterface
     * @throws \RuntimeException If the file cannot be opened.
     * @throws \InvalidArgumentException If the mode is invalid.
     */
    public function createStreamFromFile(string $filename, string $mode = 'r'): StreamInterface;
    /**
     * Create a new stream from an existing resource.
     *
     * The stream MUST be readable and may be writable.
     *
     * @param resource $resource PHP resource to use as basis of stream.
     *
     * @return StreamInterface
     */
    public function createStreamFromResource($resource): StreamInterface;
}
<?php

namespace _ContaoManager\Psr\Http\Message;

interface UploadedFileFactoryInterface
{
    /**
     * Create a new uploaded file.
     *
     * If a size is not provided it will be determined by checking the size of
     * the file.
     *
     * @see http://php.net/manual/features.file-upload.post-method.php
     * @see http://php.net/manual/features.file-upload.errors.php
     *
     * @param StreamInterface $stream Underlying stream representing the
     *     uploaded file content.
     * @param int|null $size in bytes
     * @param int $error PHP file upload error
     * @param string|null $clientFilename Filename as provided by the client, if any.
     * @param string|null $clientMediaType Media type as provided by the client, if any.
     *
     * @return UploadedFileInterface
     *
     * @throws \InvalidArgumentException If the file resource is not readable.
     */
    public function createUploadedFile(StreamInterface $stream, ?int $size = null, int $error = \UPLOAD_ERR_OK, ?string $clientFilename = null, ?string $clientMediaType = null): UploadedFileInterface;
}
<?php

namespace _ContaoManager\Psr\Http\Message;

interface UriFactoryInterface
{
    /**
     * Create a new URI.
     *
     * @param string $uri
     *
     * @return UriInterface
     *
     * @throws \InvalidArgumentException If the given URI cannot be parsed.
     */
    public function createUri(string $uri = ''): UriInterface;
}
<?php

namespace _ContaoManager\Psr\Http\Message;

interface ServerRequestFactoryInterface
{
    /**
     * Create a new server request.
     *
     * Note that server-params are taken precisely as given - no parsing/processing
     * of the given values is performed, and, in particular, no attempt is made to
     * determine the HTTP method or URI, which must be provided explicitly.
     *
     * @param string $method The HTTP method associated with the request.
     * @param UriInterface|string $uri The URI associated with the request. If
     *     the value is a string, the factory MUST create a UriInterface
     *     instance based on it.
     * @param array $serverParams Array of SAPI parameters with which to seed
     *     the generated request instance.
     *
     * @return ServerRequestInterface
     */
    public function createServerRequest(string $method, $uri, array $serverParams = []): ServerRequestInterface;
}
<?php

namespace _ContaoManager\Psr\Http\Message;

interface RequestFactoryInterface
{
    /**
     * Create a new request.
     *
     * @param string $method The HTTP method associated with the request.
     * @param UriInterface|string $uri The URI associated with the request. If
     *     the value is a string, the factory MUST create a UriInterface
     *     instance based on it.
     *
     * @return RequestInterface
     */
    public function createRequest(string $method, $uri): RequestInterface;
}
Copyright (c) 2011-2020 Jordi Boggiano

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is furnished
to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
### 3.10.0 (2026-01-02)

  * Added automatic directory cleanup in RotatingFileHandler (#2000)
  * Added timezone-aware file rotation to RotatingFileHandler (#1982)
  * Added support for mongodb/mongodb 2.0+ (#1998)
  * Added NoDiscard attribute to TestHandler methods to ensure the result is used (#2013)
  * Fixed JsonFormatter crashing if __toString throws while normalizing data (#1968)
  * Fixed PHP 8.5 deprecation warnings (#1997, #2009)
  * Fixed DeduplicatingHandler collecting duplicate logs if the file cannot be locked (2e97231)
  * Fixed GelfMessageFormatter to use integers instead of bool for gelf 1.1 support (#1973)
  * Fixed empty stack traces being output anyway (#1979)
  * Fixed StreamHandler not reopening the file if the inode changed (#1963)
  * Fixed TelegramBotHandler sending empty messages (#1992)
  * Fixed file paths in stack traces containing backslashes on windows, always using / now to unify logs (#1980)
  * Fixed RotatingFileHandler unlink errors not being suppressed correctly (#1999)

### 3.9.0 (2025-03-24)

  * BC Warning: Fixed SendGridHandler to use the V3 API as V2 is now shut down, but this requires a new API key (#1952)
  * Deprecated Monolog\Test\TestCase in favor of Monolog\Test\MonologTestCase (#1953)
  * Added extension point for NativeMailerHandler::mail (#1948)
  * Added setHandler method to BufferHandler to modify the nested handler at runtime (#1946)
  * Fixed date format in ElasticsearchFormatter to use +00:00 vs +0000 tz identifiers (#1942)
  * Fixed GelfMessageFormatter handling numeric context/extra keys (#1932)

### 3.8.1 (2024-12-05)

  * Deprecated Monolog\DateTimeImmutable in favor of Monolog\JsonSerializableDateTimeImmutable (#1928)
  * Fixed gelf keys not being valid when context/extra data keys have spaces in them (#1927)
  * Fixed empty lines appearing in the stack traces when a custom formatter returned null (#1925)

### 3.8.0 (2024-11-12)

  * Added `$fileOpenMode` param to `StreamHandler` to define a custom fopen mode to open the log file (#1913)
  * Fixed PHP 8.4 deprecation notices (#1903)
  * Added ability to extend/override `IntrospectionProcessor` (#1899)
  * Added `$timeout` param to `ProcessHandler` to configure the stream_select() timeout to avoid blocking too long (default is 1.0 sec) (#1916)
  * Fixed JsonFormatter batch handling to normalize records individually to make sure they look the same as if they were handled one by one (#1906)
  * Fixed `StreamHandler` handling of write failures so that it now closes/reopens the stream and retries the write once before failing (#1882)
  * Fixed `StreamHandler` error handler causing issues if a stream handler triggers an error (#1866)
  * Fixed `StreamHandler::reset` not closing the stream, so that it would fail to write in some cases with long running processes (#1862)
  * Fixed `RotatingFileHandler` issue where rotation does not happen in some long running processes (#1905)
  * Fixed `JsonFormatter` handling of incomplete classes (#1834)
  * Fixed `RotatingFileHandler` bug where rotation could sometimes not happen correctly (#1905)

### 3.7.0 (2024-06-28)

  * Added `NormalizerFormatter->setBasePath(...)` (and `JsonFormatter` by extension) that allows removing the project's path from the stack trace output (47e301d3e)
  * Fixed JsonFormatter handling of incomplete classes (#1834)
  * Fixed private error handlers causing problems with custom StreamHandler implementations (#1866)

### 3.6.0 (2024-04-12)

  * Added `LineFormatter->setBasePath(...)` that allows removing the project's path from the stack trace output (#1873)
  * Added `$includeExtra` option in `PsrHandler` to also use extra data to replace placeholder values in the message (#1852)
  * Added ability to customize what is a duplicated message by extending the `DeduplicationHandler` (#1879)
  * Added handling for using `GelfMessageFormatter` together with the `AmqpHandler` (#1869)
  * Added ability to extend `GoogleCloudLoggingFormatter` (#1859)
  * Fixed `__toString` failures in context data crashing the normalization process (#1868)
  * Fixed PHP 8.4 deprecation warnings (#1874)

### 3.5.0 (2023-10-27)

  * Added ability to indent stack traces in LineFormatter via e.g. `indentStacktraces('  ')` (#1835)
  * Added ability to configure a max level name length in LineFormatter via e.g. `setMaxLevelNameLength(3)` (#1850)
  * Added support for indexed arrays (i.e. `[]` and not `{}` arrays once json serialized) containing inline linebreaks in LineFormatter (#1818)
  * Added `WithMonologChannel` attribute for integrators to use to configure autowiring (#1847)
  * Fixed log record `extra` data leaking between handlers that have handler-specific processors set (#1819)
  * Fixed LogglyHandler issue with record level filtering (#1841)
  * Fixed display_errors parsing in ErrorHandler which did not support string values (#1804)
  * Fixed bug where the previous error handler would not be restored in some cases where StreamHandler fails (#1815)
  * Fixed normalization error when normalizing incomplete classes (#1833)

### 3.4.0 (2023-06-21)

  * Added `LoadAverageProcessor` to track one of the 1, 5 or 15min load averages (#1803)
  * Added support for priority to the `AsMonologProcessor` attribute (#1797)
  * Added `TelegramBotHandler` `topic`/`message_thread_id` support (#1802)
  * Fixed `FingersCrossedHandler` passthruLevel checking (#1801)
  * Fixed support of yearly and monthly rotation log file to rotate only once a month/year (#1805)
  * Fixed `TestHandler` method docs (#1794)
  * Fixed handling of falsey `display_errors` string values (#1804)

### 3.3.1 (2023-02-06)

  * Fixed Logger not being serializable anymore (#1792)

### 3.3.0 (2023-02-06)

  * Deprecated FlowdockHandler & Formatter as the flowdock service was shutdown (#1748)
  * Added `ClosureContextProcessor` to allow delaying the creation of context data by setting a Closure in context which is called when the log record is used (#1745)
  * Added an ElasticsearchHandler option to set the `op_type` to `create` instead of the default `index` (#1766)
  * Added support for enum context values in PsrLogMessageProcessor (#1773)
  * Added graylog2/gelf-php 2.x support (#1747)
  * Improved `BrowserConsoleHandler` logging to use more appropriate methods than just console.log in the browser (#1739)
  * Fixed GitProcessor not filtering correctly based on Level (#1749)
  * Fixed `WhatFailureGroupHandler` not catching errors happening inside `close()` (#1791)
  * Fixed datetime field in `GoogleCloudLoggingFormatter` (#1758)
  * Fixed infinite loop detection within Fibers (#1753)
  * Fixed `AmqpHandler->setExtraAttributes` not working with buffering handler wrappers (#1781)

### 3.2.0 (2022-07-24)

  * Deprecated `CubeHandler` and `PHPConsoleHandler` as both projects are abandoned and those should not be used anymore (#1734)
  * Marked `Logger` `@final` as it should not be extended, prefer composition or talk to us if you are missing something
  * Added RFC 5424 level (`7` to `0`) support to `Logger::log` and `Logger::addRecord` to increase interoperability (#1723)
  * Added `SyslogFormatter` to output syslog-like files which can be consumed by tools like [lnav](https://lnav.org/) (#1689)
  * Added support for `__toString` for objects which are not json serializable in `JsonFormatter` (#1733)
  * Added `GoogleCloudLoggingFormatter` (#1719)
  * Added support for Predis 2.x (#1732)
  * Added `AmqpHandler->setExtraAttributes` to allow configuring attributes when using an AMQPExchange (#1724)
  * Fixed serialization/unserialization of handlers to make sure private properties are included (#1727)
  * Fixed allowInlineLineBreaks in LineFormatter causing issues with windows paths containing `\n` or `\r` sequences (#1720)
  * Fixed max normalization depth not being taken into account when formatting exceptions with a deep chain of previous exceptions (#1726)
  * Fixed PHP 8.2 deprecation warnings (#1722)
  * Fixed rare race condition or filesystem issue where StreamHandler is unable to create the directory the log should go into yet it exists already (#1678)

### 3.1.0 (2022-06-09)

  * Added `$datetime` parameter to `Logger::addRecord` as low level API to allow logging into the past or future (#1682)
  * Added `Logger::useLoggingLoopDetection` to allow disabling cyclic logging detection in concurrent frameworks (#1681)
  * Fixed handling of fatal errors if callPrevious is disabled in ErrorHandler (#1670)
  * Fixed interop issue by removing the need for a return type in ProcessorInterface (#1680)
  * Marked the reusable `Monolog\Test\TestCase` class as `@internal` to make sure PHPStorm does not show it above PHPUnit, you may still use it to test your own handlers/etc though (#1677)
  * Fixed RotatingFileHandler issue when the date format contained slashes (#1671)

### 3.0.0 (2022-05-10)

Changes from RC1

- The `Monolog\LevelName` enum does not exist anymore, use `Monolog\Level->getName()` instead.

### 3.0.0-RC1 (2022-05-08)

This is mostly a cleanup release offering stronger type guarantees for integrators with the
array->object/enum changes, but there is no big new feature for end users.

See [UPGRADE notes](UPGRADE.md#300) for details on all breaking changes especially if you are extending/implementing Monolog classes/interfaces.

Noteworthy BC Breaks:

- The minimum supported PHP version is now `8.1.0`.
- Log records have been converted from an array to a [`Monolog\LogRecord` object](src/Monolog/LogRecord.php)
  with public (and mostly readonly) properties. e.g. instead of doing
  `$record['context']` use `$record->context`.
  In formatters or handlers if you rather need an array to work with you can use `$record->toArray()`
  to get back a Monolog 1/2 style record array. This will contain the enum values instead of enum cases
  in the `level` and `level_name` keys to be more backwards compatible and use simpler data types.
- `FormatterInterface`, `HandlerInterface`, `ProcessorInterface`, etc. changed to contain `LogRecord $record`
  instead of `array $record` parameter types. If you want to support multiple Monolog versions this should
  be possible by type-hinting nothing, or `array|LogRecord` if you support PHP 8.0+. You can then code
  against the $record using Monolog 2 style as LogRecord implements ArrayAccess for BC.
  The interfaces do not require a `LogRecord` return type even where it would be applicable, but if you only
  support Monolog 3 in integration code I would recommend you use `LogRecord` return types wherever fitting
  to ensure forward compatibility as it may be added in Monolog 4.
- Log levels are now enums [`Monolog\Level`](src/Monolog/Level.php) and [`Monolog\LevelName`](src/Monolog/LevelName.php)
- Removed deprecated SwiftMailerHandler, migrate to SymfonyMailerHandler instead.
- `ResettableInterface::reset()` now requires a void return type.
- All properties have had types added, which may require you to do so as well if you extended
  a Monolog class and declared the same property.

New deprecations:

- `Logger::DEBUG`, `Logger::ERROR`, etc. are now deprecated in favor of the `Monolog\Level` enum.
  e.g. instead of `Logger::WARNING` use `Level::Warning` if you need to pass the enum case
  to Monolog or one of its handlers, or `Level::Warning->value` if you need the integer
  value equal to what `Logger::WARNING` was giving you.
- `Logger::getLevelName()` is now deprecated.

### 2.10.0 (2024-11-12)

  * Added `$fileOpenMode` to `StreamHandler` to define a custom fopen mode to open the log file (#1913)
  * Fixed `StreamHandler` handling of write failures so that it now closes/reopens the stream and retries the write once before failing (#1882)
  * Fixed `StreamHandler` error handler causing issues if a stream handler triggers an error (#1866)
  * Fixed `JsonFormatter` handling of incomplete classes (#1834)
  * Fixed `RotatingFileHandler` bug where rotation could sometimes not happen correctly (#1905)

### 2.9.3 (2024-04-12)

  * Fixed PHP 8.4 deprecation warnings (#1874)

### 2.9.2 (2023-10-27)

  * Fixed display_errors parsing in ErrorHandler which did not support string values (#1804)
  * Fixed bug where the previous error handler would not be restored in some cases where StreamHandler fails (#1815)
  * Fixed normalization error when normalizing incomplete classes (#1833)

### 2.9.1 (2023-02-06)

  * Fixed Logger not being serializable anymore (#1792)

### 2.9.0 (2023-02-05)

  * Deprecated FlowdockHandler & Formatter as the flowdock service was shutdown (#1748)
  * Added support for enum context values in PsrLogMessageProcessor (#1773)
  * Added graylog2/gelf-php 2.x support (#1747)
  * Improved `BrowserConsoleHandler` logging to use more appropriate methods than just console.log in the browser (#1739)
  * Fixed `WhatFailureGroupHandler` not catching errors happening inside `close()` (#1791)
  * Fixed datetime field in `GoogleCloudLoggingFormatter` (#1758)
  * Fixed infinite loop detection within Fibers (#1753)
  * Fixed `AmqpHandler->setExtraAttributes` not working with buffering handler wrappers (#1781)

### 2.8.0 (2022-07-24)

  * Deprecated `CubeHandler` and `PHPConsoleHandler` as both projects are abandoned and those should not be used anymore (#1734)
  * Added RFC 5424 level (`7` to `0`) support to `Logger::log` and `Logger::addRecord` to increase interoperability (#1723)
  * Added support for `__toString` for objects which are not json serializable in `JsonFormatter` (#1733)
  * Added `GoogleCloudLoggingFormatter` (#1719)
  * Added support for Predis 2.x (#1732)
  * Added `AmqpHandler->setExtraAttributes` to allow configuring attributes when using an AMQPExchange (#1724)
  * Fixed serialization/unserialization of handlers to make sure private properties are included (#1727)
  * Fixed allowInlineLineBreaks in LineFormatter causing issues with windows paths containing `\n` or `\r` sequences (#1720)
  * Fixed max normalization depth not being taken into account when formatting exceptions with a deep chain of previous exceptions (#1726)
  * Fixed PHP 8.2 deprecation warnings (#1722)
  * Fixed rare race condition or filesystem issue where StreamHandler is unable to create the directory the log should go into yet it exists already (#1678)

### 2.7.0 (2022-06-09)

  * Added `$datetime` parameter to `Logger::addRecord` as low level API to allow logging into the past or future (#1682)
  * Added `Logger::useLoggingLoopDetection` to allow disabling cyclic logging detection in concurrent frameworks (#1681)
  * Fixed handling of fatal errors if callPrevious is disabled in ErrorHandler (#1670)
  * Marked the reusable `Monolog\Test\TestCase` class as `@internal` to make sure PHPStorm does not show it above PHPUnit, you may still use it to test your own handlers/etc though (#1677)
  * Fixed RotatingFileHandler issue when the date format contained slashes (#1671)

### 2.6.0 (2022-05-10)

  * Deprecated `SwiftMailerHandler`, use `SymfonyMailerHandler` instead
  * Added `SymfonyMailerHandler` (#1663)
  * Added ElasticSearch 8.x support to the ElasticsearchHandler (#1662)
  * Added a way to filter/modify stack traces in LineFormatter (#1665)
  * Fixed UdpSocket not being able to reopen/reconnect after close()
  * Fixed infinite loops if a Handler is triggering logging while handling log records

### 2.5.0 (2022-04-08)

  * Added `callType` to IntrospectionProcessor (#1612)
  * Fixed AsMonologProcessor syntax to be compatible with PHP 7.2 (#1651)

### 2.4.0 (2022-03-14)

  * Added [`Monolog\LogRecord`](src/Monolog/LogRecord.php) interface that can be used to type-hint records like `array|\Monolog\LogRecord $record` to be forward compatible with the upcoming Monolog 3 changes
  * Added `includeStacktraces` constructor params to LineFormatter & JsonFormatter (#1603)
  * Added `persistent`, `timeout`, `writingTimeout`, `connectionTimeout`, `chunkSize` constructor params to SocketHandler and derivatives (#1600)
  * Added `AsMonologProcessor` PHP attribute which can help autowiring / autoconfiguration of processors if frameworks / integrations decide to make use of it. This is useless when used purely with Monolog (#1637)
  * Added support for keeping native BSON types as is in MongoDBFormatter (#1620)
  * Added support for a `user_agent` key in WebProcessor, disabled by default but you can use it by configuring the $extraFields you want (#1613)
  * Added support for username/userIcon in SlackWebhookHandler (#1617)
  * Added extension points to BrowserConsoleHandler (#1593)
  * Added record message/context/extra info to exceptions thrown when a StreamHandler cannot open its stream to avoid completely losing the data logged (#1630)
  * Fixed error handler signature to accept a null $context which happens with internal PHP errors (#1614)
  * Fixed a few setter methods not returning `self` (#1609)
  * Fixed handling of records going over the max Telegram message length (#1616)

### 2.3.5 (2021-10-01)

  * Fixed regression in StreamHandler since 2.3.3 on systems with the memory_limit set to >=20GB (#1592)

### 2.3.4 (2021-09-15)

  * Fixed support for psr/log 3.x (#1589)

### 2.3.3 (2021-09-14)

  * Fixed memory usage when using StreamHandler and calling stream_get_contents on the resource you passed to it (#1578, #1577)
  * Fixed support for psr/log 2.x (#1587)
  * Fixed some type annotations

### 2.3.2 (2021-07-23)

  * Fixed compatibility with PHP 7.2 - 7.4 when experiencing PCRE errors (#1568)

### 2.3.1 (2021-07-14)

  * Fixed Utils::getClass handling of anonymous classes not being fully compatible with PHP 8 (#1563)
  * Fixed some `@inheritDoc` annotations having the wrong case

### 2.3.0 (2021-07-05)

  * Added a ton of PHPStan type annotations as well as type aliases on Monolog\Logger for Record, Level and LevelName that you can import (#1557)
  * Added ability to customize date format when using JsonFormatter (#1561)
  * Fixed FilterHandler not calling reset on its internal handler when reset() is called on it (#1531)
  * Fixed SyslogUdpHandler not setting the timezone correctly on DateTimeImmutable instances (#1540)
  * Fixed StreamHandler thread safety - chunk size set to 2GB now to avoid interlacing when doing concurrent writes (#1553)

### 2.2.0 (2020-12-14)

  * Added JSON_PARTIAL_OUTPUT_ON_ERROR to default json encoding flags, to avoid dropping entire context data or even records due to an invalid subset of it somewhere
  * Added setDateFormat to NormalizerFormatter (and Line/Json formatters by extension) to allow changing this after object creation
  * Added RedisPubSubHandler to log records to a Redis channel using PUBLISH
  * Added support for Elastica 7, and deprecated the $type argument of ElasticaFormatter which is not in use anymore as of Elastica 7
  * Added support for millisecond write timeouts in SocketHandler, you can now pass floats to setWritingTimeout, e.g. 0.2 is 200ms
  * Added support for unix sockets in SyslogUdpHandler (set $port to 0 to make the $host a unix socket)
  * Added handleBatch support for TelegramBotHandler
  * Added RFC5424e extended date format including milliseconds to SyslogUdpHandler
  * Added support for configuring handlers with numeric level values in strings (coming from e.g. env vars)
  * Fixed Wildfire/FirePHP/ChromePHP handling of unicode characters
  * Fixed PHP 8 issues in SyslogUdpHandler
  * Fixed internal type error when mbstring is missing

### 2.1.1 (2020-07-23)

  * Fixed removing of json encoding options
  * Fixed type hint of $level not accepting strings in SendGridHandler and OverflowHandler
  * Fixed SwiftMailerHandler not accepting email templates with an empty subject
  * Fixed array access on null in RavenHandler
  * Fixed unique_id in WebProcessor not being disableable

### 2.1.0 (2020-05-22)

  * Added `JSON_INVALID_UTF8_SUBSTITUTE` to default json flags, so that invalid UTF8 characters now get converted to [�](https://en.wikipedia.org/wiki/Specials_(Unicode_block)#Replacement_character) instead of being converted from ISO-8859-15 to UTF8 as it was before, which was hardly a comprehensive solution
  * Added `$ignoreEmptyContextAndExtra` option to JsonFormatter to skip empty context/extra entirely from the output
  * Added `$parseMode`, `$disableWebPagePreview` and `$disableNotification` options to TelegramBotHandler
  * Added tentative support for PHP 8
  * NormalizerFormatter::addJsonEncodeOption and removeJsonEncodeOption are now public to allow modifying default json flags
  * Fixed GitProcessor type error when there is no git repo present
  * Fixed normalization of SoapFault objects containing deeply nested objects as "detail"
  * Fixed support for relative paths in RotatingFileHandler

### 2.0.2 (2019-12-20)

  * Fixed ElasticsearchHandler swallowing exceptions details when failing to index log records
  * Fixed normalization of SoapFault objects containing non-strings as "detail" in LineFormatter
  * Fixed formatting of resources in JsonFormatter
  * Fixed RedisHandler failing to use MULTI properly when passed a proxied Redis instance (e.g. in Symfony with lazy services)
  * Fixed FilterHandler triggering a notice when handleBatch was filtering all records passed to it
  * Fixed Turkish locale messing up the conversion of level names to their constant values

### 2.0.1 (2019-11-13)

  * Fixed normalization of Traversables to avoid traversing them as not all of them are rewindable
  * Fixed setFormatter/getFormatter to forward to the nested handler in FilterHandler, FingersCrossedHandler, BufferHandler, OverflowHandler and SamplingHandler
  * Fixed BrowserConsoleHandler formatting when using multiple styles
  * Fixed normalization of exception codes to be always integers even for PDOException which have them as numeric strings
  * Fixed normalization of SoapFault objects containing non-strings as "detail"
  * Fixed json encoding across all handlers to always attempt recovery of non-UTF-8 strings instead of failing the whole encoding
  * Fixed ChromePHPHandler to avoid sending more data than latest Chrome versions allow in headers (4KB down from 256KB).
  * Fixed type error in BrowserConsoleHandler when the context array of log records was not associative.

### 2.0.0 (2019-08-30)

  * BC Break: This is a major release, see [UPGRADE.md](UPGRADE.md) for details if you are coming from a 1.x release
  * BC Break: Logger methods log/debug/info/notice/warning/error/critical/alert/emergency now have explicit void return types
  * Added FallbackGroupHandler which works like the WhatFailureGroupHandler but stops dispatching log records as soon as one handler accepted it
  * Fixed support for UTF-8 when cutting strings to avoid cutting a multibyte-character in half
  * Fixed normalizers handling of exception backtraces to avoid serializing arguments in some cases
  * Fixed date timezone handling in SyslogUdpHandler

### 2.0.0-beta2 (2019-07-06)

  * BC Break: This is a major release, see [UPGRADE.md](UPGRADE.md) for details if you are coming from a 1.x release
  * BC Break: PHP 7.2 is now the minimum required PHP version.
  * BC Break: Removed SlackbotHandler, RavenHandler and HipChatHandler, see [UPGRADE.md](UPGRADE.md) for details
  * Added OverflowHandler which will only flush log records to its nested handler when reaching a certain amount of logs (i.e. only pass through when things go really bad)
  * Added TelegramBotHandler to log records to a [Telegram](https://core.telegram.org/bots/api) bot account
  * Added support for JsonSerializable when normalizing exceptions
  * Added support for RFC3164 (outdated BSD syslog protocol) to SyslogUdpHandler
  * Added SoapFault details to formatted exceptions
  * Fixed DeduplicationHandler silently failing to start when file could not be opened
  * Fixed issue in GroupHandler and WhatFailureGroupHandler where setting multiple processors would duplicate records
  * Fixed GelfFormatter losing some data when one attachment was too long
  * Fixed issue in SignalHandler restarting syscalls functionality
  * Improved performance of LogglyHandler when sending multiple logs in a single request

### 2.0.0-beta1 (2018-12-08)

  * BC Break: This is a major release, see [UPGRADE.md](UPGRADE.md) for details if you are coming from a 1.x release
  * BC Break: PHP 7.1 is now the minimum required PHP version.
  * BC Break: Quite a few interface changes, only relevant if you implemented your own handlers/processors/formatters
  * BC Break: Removed non-PSR-3 methods to add records, all the `add*` (e.g. `addWarning`) methods as well as `emerg`, `crit`, `err` and `warn`
  * BC Break: The record timezone is now set per Logger instance and not statically anymore
  * BC Break: There is no more default handler configured on empty Logger instances
  * BC Break: ElasticSearchHandler renamed to ElasticaHandler
  * BC Break: Various handler-specific breaks, see [UPGRADE.md](UPGRADE.md) for details
  * Added scalar type hints and return hints in all the places it was possible. Switched strict_types on for more reliability.
  * Added DateTimeImmutable support, all record datetime are now immutable, and will toString/json serialize with the correct date format, including microseconds (unless disabled)
  * Added timezone and microseconds to the default date format
  * Added SendGridHandler to use the SendGrid API to send emails
  * Added LogmaticHandler to use the Logmatic.io API to store log records
  * Added SqsHandler to send log records to an AWS SQS queue
  * Added ElasticsearchHandler to send records via the official ES library. Elastica users should now use ElasticaHandler instead of ElasticSearchHandler
  * Added NoopHandler which is similar to the NullHandle but does not prevent the bubbling of log records to handlers further down the configuration, useful for temporarily disabling a handler in configuration files
  * Added ProcessHandler to write log output to the STDIN of a given process
  * Added HostnameProcessor that adds the machine's hostname to log records
  * Added a `$dateFormat` option to the PsrLogMessageProcessor which lets you format DateTime instances nicely
  * Added support for the PHP 7.x `mongodb` extension in the MongoDBHandler
  * Fixed many minor issues in various handlers, and probably added a few regressions too

### 1.26.1 (2021-05-28)

  * Fixed PHP 8.1 deprecation warning

### 1.26.0 (2020-12-14)

  * Added $dateFormat and $removeUsedContextFields arguments to PsrLogMessageProcessor (backport from 2.x)

### 1.25.5 (2020-07-23)

  * Fixed array access on null in RavenHandler
  * Fixed unique_id in WebProcessor not being disableable

### 1.25.4 (2020-05-22)

  * Fixed GitProcessor type error when there is no git repo present
  * Fixed normalization of SoapFault objects containing deeply nested objects as "detail"
  * Fixed support for relative paths in RotatingFileHandler

### 1.25.3 (2019-12-20)

  * Fixed formatting of resources in JsonFormatter
  * Fixed RedisHandler failing to use MULTI properly when passed a proxied Redis instance (e.g. in Symfony with lazy services)
  * Fixed FilterHandler triggering a notice when handleBatch was filtering all records passed to it
  * Fixed Turkish locale messing up the conversion of level names to their constant values

### 1.25.2 (2019-11-13)

  * Fixed normalization of Traversables to avoid traversing them as not all of them are rewindable
  * Fixed setFormatter/getFormatter to forward to the nested handler in FilterHandler, FingersCrossedHandler, BufferHandler and SamplingHandler
  * Fixed BrowserConsoleHandler formatting when using multiple styles
  * Fixed normalization of exception codes to be always integers even for PDOException which have them as numeric strings
  * Fixed normalization of SoapFault objects containing non-strings as "detail"
  * Fixed json encoding across all handlers to always attempt recovery of non-UTF-8 strings instead of failing the whole encoding

### 1.25.1 (2019-09-06)

  * Fixed forward-compatible interfaces to be compatible with Monolog 1.x too.

### 1.25.0 (2019-09-06)

  * Deprecated SlackbotHandler, use SlackWebhookHandler or SlackHandler instead
  * Deprecated RavenHandler, use sentry/sentry 2.x and their Sentry\Monolog\Handler instead
  * Deprecated HipChatHandler, migrate to Slack and use SlackWebhookHandler or SlackHandler instead
  * Added forward-compatible interfaces and traits FormattableHandlerInterface, FormattableHandlerTrait, ProcessableHandlerInterface, ProcessableHandlerTrait. If you use modern PHP and want to make code compatible with Monolog 1 and 2 this can help. You will have to require at least Monolog 1.25 though.
  * Added support for RFC3164 (outdated BSD syslog protocol) to SyslogUdpHandler
  * Fixed issue in GroupHandler and WhatFailureGroupHandler where setting multiple processors would duplicate records
  * Fixed issue in SignalHandler restarting syscalls functionality
  * Fixed normalizers handling of exception backtraces to avoid serializing arguments in some cases
  * Fixed ZendMonitorHandler to work with the latest Zend Server versions
  * Fixed ChromePHPHandler to avoid sending more data than latest Chrome versions allow in headers (4KB down from 256KB).

### 1.24.0 (2018-11-05)

  * BC Notice: If you are extending any of the Monolog's Formatters' `normalize` method, make sure you add the new `$depth = 0` argument to your function signature to avoid strict PHP warnings.
  * Added a `ResettableInterface` in order to reset/reset/clear/flush handlers and processors
  * Added a `ProcessorInterface` as an optional way to label a class as being a processor (mostly useful for autowiring dependency containers)
  * Added a way to log signals being received using Monolog\SignalHandler
  * Added ability to customize error handling at the Logger level using Logger::setExceptionHandler
  * Added InsightOpsHandler to migrate users of the LogEntriesHandler
  * Added protection to NormalizerFormatter against circular and very deep structures, it now stops normalizing at a depth of 9
  * Added capture of stack traces to ErrorHandler when logging PHP errors
  * Added RavenHandler support for a `contexts` context or extra key to forward that to Sentry's contexts
  * Added forwarding of context info to FluentdFormatter
  * Added SocketHandler::setChunkSize to override the default chunk size in case you must send large log lines to rsyslog for example
  * Added ability to extend/override BrowserConsoleHandler
  * Added SlackWebhookHandler::getWebhookUrl and SlackHandler::getToken to enable class extensibility
  * Added SwiftMailerHandler::getSubjectFormatter to enable class extensibility
  * Dropped official support for HHVM in test builds
  * Fixed normalization of exception traces when call_user_func is used to avoid serializing objects and the data they contain
  * Fixed naming of fields in Slack handler, all field names are now capitalized in all cases
  * Fixed HipChatHandler bug where slack dropped messages randomly
  * Fixed normalization of objects in Slack handlers
  * Fixed support for PHP7's Throwable in NewRelicHandler
  * Fixed race bug when StreamHandler sometimes incorrectly reported it failed to create a directory
  * Fixed table row styling issues in HtmlFormatter
  * Fixed RavenHandler dropping the message when logging exception
  * Fixed WhatFailureGroupHandler skipping processors when using handleBatch
    and implement it where possible
  * Fixed display of anonymous class names

### 1.23.0 (2017-06-19)

  * Improved SyslogUdpHandler's support for RFC5424 and added optional `$ident` argument
  * Fixed GelfHandler truncation to be per field and not per message
  * Fixed compatibility issue with PHP <5.3.6
  * Fixed support for headless Chrome in ChromePHPHandler
  * Fixed support for latest Aws SDK in DynamoDbHandler
  * Fixed support for SwiftMailer 6.0+ in SwiftMailerHandler

### 1.22.1 (2017-03-13)

  * Fixed lots of minor issues in the new Slack integrations
  * Fixed support for allowInlineLineBreaks in LineFormatter when formatting exception backtraces

### 1.22.0 (2016-11-26)

  * Added SlackbotHandler and SlackWebhookHandler to set up Slack integration more easily
  * Added MercurialProcessor to add mercurial revision and branch names to log records
  * Added support for AWS SDK v3 in DynamoDbHandler
  * Fixed fatal errors occurring when normalizing generators that have been fully consumed
  * Fixed RollbarHandler to include a level (rollbar level), monolog_level (original name), channel and datetime (unix)
  * Fixed RollbarHandler not flushing records automatically, calling close() explicitly is not necessary anymore
  * Fixed SyslogUdpHandler to avoid sending empty frames
  * Fixed a few PHP 7.0 and 7.1 compatibility issues

### 1.21.0 (2016-07-29)

  * Break: Reverted the addition of $context when the ErrorHandler handles regular php errors from 1.20.0 as it was causing issues
  * Added support for more formats in RotatingFileHandler::setFilenameFormat as long as they have Y, m and d in order
  * Added ability to format the main line of text the SlackHandler sends by explicitly setting a formatter on the handler
  * Added information about SoapFault instances in NormalizerFormatter
  * Added $handleOnlyReportedErrors option on ErrorHandler::registerErrorHandler (default true) to allow logging of all errors no matter the error_reporting level

### 1.20.0 (2016-07-02)

  * Added FingersCrossedHandler::activate() to manually trigger the handler regardless of the activation policy
  * Added StreamHandler::getUrl to retrieve the stream's URL
  * Added ability to override addRow/addTitle in HtmlFormatter
  * Added the $context to context information when the ErrorHandler handles a regular php error
  * Deprecated RotatingFileHandler::setFilenameFormat to only support 3 formats: Y, Y-m and Y-m-d
  * Fixed WhatFailureGroupHandler to work with PHP7 throwables
  * Fixed a few minor bugs

### 1.19.0 (2016-04-12)

  * Break: StreamHandler will not close streams automatically that it does not own. If you pass in a stream (not a path/url), then it will not close it for you. You can retrieve those using getStream() if needed
  * Added DeduplicationHandler to remove duplicate records from notifications across multiple requests, useful for email or other notifications on errors
  * Added ability to use `%message%` and other LineFormatter replacements in the subject line of emails sent with NativeMailHandler and SwiftMailerHandler
  * Fixed HipChatHandler handling of long messages

### 1.18.2 (2016-04-02)

  * Fixed ElasticaFormatter to use more precise dates
  * Fixed GelfMessageFormatter sending too long messages

### 1.18.1 (2016-03-13)

  * Fixed SlackHandler bug where slack dropped messages randomly
  * Fixed RedisHandler issue when using with the PHPRedis extension
  * Fixed AmqpHandler content-type being incorrectly set when using with the AMQP extension
  * Fixed BrowserConsoleHandler regression

### 1.18.0 (2016-03-01)

  * Added optional reduction of timestamp precision via `Logger->useMicrosecondTimestamps(false)`, disabling it gets you a bit of performance boost but reduces the precision to the second instead of microsecond
  * Added possibility to skip some extra stack frames in IntrospectionProcessor if you have some library wrapping Monolog that is always adding frames
  * Added `Logger->withName` to clone a logger (keeping all handlers) with a new name
  * Added FluentdFormatter for the Fluentd unix socket protocol
  * Added HandlerWrapper base class to ease the creation of handler wrappers, just extend it and override as needed
  * Added support for replacing context sub-keys using `%context.*%` in LineFormatter
  * Added support for `payload` context value in RollbarHandler
  * Added setRelease to RavenHandler to describe the application version, sent with every log
  * Added support for `fingerprint` context value in RavenHandler
  * Fixed JSON encoding errors that would gobble up the whole log record, we now handle those more gracefully by dropping chars as needed
  * Fixed write timeouts in SocketHandler and derivatives, set to 10sec by default, lower it with `setWritingTimeout()`
  * Fixed PHP7 compatibility with regard to Exception/Throwable handling in a few places

### 1.17.2 (2015-10-14)

  * Fixed ErrorHandler compatibility with non-Monolog PSR-3 loggers
  * Fixed SlackHandler handling to use slack functionalities better
  * Fixed SwiftMailerHandler bug when sending multiple emails they all had the same id
  * Fixed 5.3 compatibility regression

### 1.17.1 (2015-08-31)

  * Fixed RollbarHandler triggering PHP notices

### 1.17.0 (2015-08-30)

  * Added support for `checksum` and `release` context/extra values in RavenHandler
  * Added better support for exceptions in RollbarHandler
  * Added UidProcessor::getUid
  * Added support for showing the resource type in NormalizedFormatter
  * Fixed IntrospectionProcessor triggering PHP notices

### 1.16.0 (2015-08-09)

  * Added IFTTTHandler to notify ifttt.com triggers
  * Added Logger::setHandlers() to allow setting/replacing all handlers
  * Added $capSize in RedisHandler to cap the log size
  * Fixed StreamHandler creation of directory to only trigger when the first log write happens
  * Fixed bug in the handling of curl failures
  * Fixed duplicate logging of fatal errors when both error and fatal error handlers are registered in monolog's ErrorHandler
  * Fixed missing fatal errors records with handlers that need to be closed to flush log records
  * Fixed TagProcessor::addTags support for associative arrays

### 1.15.0 (2015-07-12)

  * Added addTags and setTags methods to change a TagProcessor
  * Added automatic creation of directories if they are missing for a StreamHandler to open a log file
  * Added retry functionality to Loggly, Cube and Mandrill handlers so they retry up to 5 times in case of network failure
  * Fixed process exit code being incorrectly reset to 0 if ErrorHandler::registerExceptionHandler was used
  * Fixed HTML/JS escaping in BrowserConsoleHandler
  * Fixed JSON encoding errors being silently suppressed (PHP 5.5+ only)

### 1.14.0 (2015-06-19)

  * Added PHPConsoleHandler to send record to Chrome's PHP Console extension and library
  * Added support for objects implementing __toString in the NormalizerFormatter
  * Added support for HipChat's v2 API in HipChatHandler
  * Added Logger::setTimezone() to initialize the timezone monolog should use in case date.timezone isn't correct for your app
  * Added an option to send formatted message instead of the raw record on PushoverHandler via ->useFormattedMessage(true)
  * Fixed curl errors being silently suppressed

### 1.13.1 (2015-03-09)

  * Fixed regression in HipChat requiring a new token to be created

### 1.13.0 (2015-03-05)

  * Added Registry::hasLogger to check for the presence of a logger instance
  * Added context.user support to RavenHandler
  * Added HipChat API v2 support in the HipChatHandler
  * Added NativeMailerHandler::addParameter to pass params to the mail() process
  * Added context data to SlackHandler when $includeContextAndExtra is true
  * Added ability to customize the Swift_Message per-email in SwiftMailerHandler
  * Fixed SwiftMailerHandler to lazily create message instances if a callback is provided
  * Fixed serialization of INF and NaN values in Normalizer and LineFormatter

### 1.12.0 (2014-12-29)

  * Break: HandlerInterface::isHandling now receives a partial record containing only a level key. This was always the intent and does not break any Monolog handler but is strictly speaking a BC break and you should check if you relied on any other field in your own handlers.
  * Added PsrHandler to forward records to another PSR-3 logger
  * Added SamplingHandler to wrap around a handler and include only every Nth record
  * Added MongoDBFormatter to support better storage with MongoDBHandler (it must be enabled manually for now)
  * Added exception codes in the output of most formatters
  * Added LineFormatter::includeStacktraces to enable exception stack traces in logs (uses more than one line)
  * Added $useShortAttachment to SlackHandler to minify attachment size and $includeExtra to append extra data
  * Added $host to HipChatHandler for users of private instances
  * Added $transactionName to NewRelicHandler and support for a transaction_name context value
  * Fixed MandrillHandler to avoid outputting API call responses
  * Fixed some non-standard behaviors in SyslogUdpHandler

### 1.11.0 (2014-09-30)

  * Break: The NewRelicHandler extra and context data are now prefixed with extra_ and context_ to avoid clashes. Watch out if you have scripts reading those from the API and rely on names
  * Added WhatFailureGroupHandler to suppress any exception coming from the wrapped handlers and avoid chain failures if a logging service fails
  * Added MandrillHandler to send emails via the Mandrillapp.com API
  * Added SlackHandler to log records to a Slack.com account
  * Added FleepHookHandler to log records to a Fleep.io account
  * Added LogglyHandler::addTag to allow adding tags to an existing handler
  * Added $ignoreEmptyContextAndExtra to LineFormatter to avoid empty [] at the end
  * Added $useLocking to StreamHandler and RotatingFileHandler to enable flock() while writing
  * Added support for PhpAmqpLib in the AmqpHandler
  * Added FingersCrossedHandler::clear and BufferHandler::clear to reset them between batches in long running jobs
  * Added support for adding extra fields from $_SERVER in the WebProcessor
  * Fixed support for non-string values in PrsLogMessageProcessor
  * Fixed SwiftMailer messages being sent with the wrong date in long running scripts
  * Fixed minor PHP 5.6 compatibility issues
  * Fixed BufferHandler::close being called twice

### 1.10.0 (2014-06-04)

  * Added Logger::getHandlers() and Logger::getProcessors() methods
  * Added $passthruLevel argument to FingersCrossedHandler to let it always pass some records through even if the trigger level is not reached
  * Added support for extra data in NewRelicHandler
  * Added $expandNewlines flag to the ErrorLogHandler to create multiple log entries when a message has multiple lines

### 1.9.1 (2014-04-24)

  * Fixed regression in RotatingFileHandler file permissions
  * Fixed initialization of the BufferHandler to make sure it gets flushed after receiving records
  * Fixed ChromePHPHandler and FirePHPHandler's activation strategies to be more conservative

### 1.9.0 (2014-04-20)

  * Added LogEntriesHandler to send logs to a LogEntries account
  * Added $filePermissions to tweak file mode on StreamHandler and RotatingFileHandler
  * Added $useFormatting flag to MemoryProcessor to make it send raw data in bytes
  * Added support for table formatting in FirePHPHandler via the table context key
  * Added a TagProcessor to add tags to records, and support for tags in RavenHandler
  * Added $appendNewline flag to the JsonFormatter to enable using it when logging to files
  * Added sound support to the PushoverHandler
  * Fixed multi-threading support in StreamHandler
  * Fixed empty headers issue when ChromePHPHandler received no records
  * Fixed default format of the ErrorLogHandler

### 1.8.0 (2014-03-23)

  * Break: the LineFormatter now strips newlines by default because this was a bug, set $allowInlineLineBreaks to true if you need them
  * Added BrowserConsoleHandler to send logs to any browser's console via console.log() injection in the output
  * Added FilterHandler to filter records and only allow those of a given list of levels through to the wrapped handler
  * Added FlowdockHandler to send logs to a Flowdock account
  * Added RollbarHandler to send logs to a Rollbar account
  * Added HtmlFormatter to send prettier log emails with colors for each log level
  * Added GitProcessor to add the current branch/commit to extra record data
  * Added a Monolog\Registry class to allow easier global access to pre-configured loggers
  * Added support for the new official graylog2/gelf-php lib for GelfHandler, upgrade if you can by replacing the mlehner/gelf-php requirement
  * Added support for HHVM
  * Added support for Loggly batch uploads
  * Added support for tweaking the content type and encoding in NativeMailerHandler
  * Added $skipClassesPartials to tweak the ignored classes in the IntrospectionProcessor
  * Fixed batch request support in GelfHandler

### 1.7.0 (2013-11-14)

  * Added ElasticSearchHandler to send logs to an Elastic Search server
  * Added DynamoDbHandler and ScalarFormatter to send logs to Amazon's Dynamo DB
  * Added SyslogUdpHandler to send logs to a remote syslogd server
  * Added LogglyHandler to send logs to a Loggly account
  * Added $level to IntrospectionProcessor so it only adds backtraces when needed
  * Added $version to LogstashFormatter to allow using the new v1 Logstash format
  * Added $appName to NewRelicHandler
  * Added configuration of Pushover notification retries/expiry
  * Added $maxColumnWidth to NativeMailerHandler to change the 70 chars default
  * Added chainability to most setters for all handlers
  * Fixed RavenHandler batch processing so it takes the message from the record with highest priority
  * Fixed HipChatHandler batch processing so it sends all messages at once
  * Fixed issues with eAccelerator
  * Fixed and improved many small things

### 1.6.0 (2013-07-29)

  * Added HipChatHandler to send logs to a HipChat chat room
  * Added ErrorLogHandler to send logs to PHP's error_log function
  * Added NewRelicHandler to send logs to NewRelic's service
  * Added Monolog\ErrorHandler helper class to register a Logger as exception/error/fatal handler
  * Added ChannelLevelActivationStrategy for the FingersCrossedHandler to customize levels by channel
  * Added stack traces output when normalizing exceptions (json output & co)
  * Added Monolog\Logger::API constant (currently 1)
  * Added support for ChromePHP's v4.0 extension
  * Added support for message priorities in PushoverHandler, see $highPriorityLevel and $emergencyLevel
  * Added support for sending messages to multiple users at once with the PushoverHandler
  * Fixed RavenHandler's support for batch sending of messages (when behind a Buffer or FingersCrossedHandler)
  * Fixed normalization of Traversables with very large data sets, only the first 1000 items are shown now
  * Fixed issue in RotatingFileHandler when an open_basedir restriction is active
  * Fixed minor issues in RavenHandler and bumped the API to Raven 0.5.0
  * Fixed SyslogHandler issue when many were used concurrently with different facilities

### 1.5.0 (2013-04-23)

  * Added ProcessIdProcessor to inject the PID in log records
  * Added UidProcessor to inject a unique identifier to all log records of one request/run
  * Added support for previous exceptions in the LineFormatter exception serialization
  * Added Monolog\Logger::getLevels() to get all available levels
  * Fixed ChromePHPHandler so it avoids sending headers larger than Chrome can handle

### 1.4.1 (2013-04-01)

  * Fixed exception formatting in the LineFormatter to be more minimalistic
  * Fixed RavenHandler's handling of context/extra data, requires Raven client >0.1.0
  * Fixed log rotation in RotatingFileHandler to work with long running scripts spanning multiple days
  * Fixed WebProcessor array access so it checks for data presence
  * Fixed Buffer, Group and FingersCrossed handlers to make use of their processors

### 1.4.0 (2013-02-13)

  * Added RedisHandler to log to Redis via the Predis library or the phpredis extension
  * Added ZendMonitorHandler to log to the Zend Server monitor
  * Added the possibility to pass arrays of handlers and processors directly in the Logger constructor
  * Added `$useSSL` option to the PushoverHandler which is enabled by default
  * Fixed ChromePHPHandler and FirePHPHandler issue when multiple instances are used simultaneously
  * Fixed header injection capability in the NativeMailHandler

### 1.3.1 (2013-01-11)

  * Fixed LogstashFormatter to be usable with stream handlers
  * Fixed GelfMessageFormatter levels on Windows

### 1.3.0 (2013-01-08)

  * Added PSR-3 compliance, the `Monolog\Logger` class is now an instance of `Psr\Log\LoggerInterface`
  * Added PsrLogMessageProcessor that you can selectively enable for full PSR-3 compliance
  * Added LogstashFormatter (combine with SocketHandler or StreamHandler to send logs to Logstash)
  * Added PushoverHandler to send mobile notifications
  * Added CouchDBHandler and DoctrineCouchDBHandler
  * Added RavenHandler to send data to Sentry servers
  * Added support for the new MongoClient class in MongoDBHandler
  * Added microsecond precision to log records' timestamps
  * Added `$flushOnOverflow` param to BufferHandler to flush by batches instead of losing
    the oldest entries
  * Fixed normalization of objects with cyclic references

### 1.2.1 (2012-08-29)

  * Added new $logopts arg to SyslogHandler to provide custom openlog options
  * Fixed fatal error in SyslogHandler

### 1.2.0 (2012-08-18)

  * Added AmqpHandler (for use with AMQP servers)
  * Added CubeHandler
  * Added NativeMailerHandler::addHeader() to send custom headers in mails
  * Added the possibility to specify more than one recipient in NativeMailerHandler
  * Added the possibility to specify float timeouts in SocketHandler
  * Added NOTICE and EMERGENCY levels to conform with RFC 5424
  * Fixed the log records to use the php default timezone instead of UTC
  * Fixed BufferHandler not being flushed properly on PHP fatal errors
  * Fixed normalization of exotic resource types
  * Fixed the default format of the SyslogHandler to avoid duplicating datetimes in syslog

### 1.1.0 (2012-04-23)

  * Added Monolog\Logger::isHandling() to check if a handler will
    handle the given log level
  * Added ChromePHPHandler
  * Added MongoDBHandler
  * Added GelfHandler (for use with Graylog2 servers)
  * Added SocketHandler (for use with syslog-ng for example)
  * Added NormalizerFormatter
  * Added the possibility to change the activation strategy of the FingersCrossedHandler
  * Added possibility to show microseconds in logs
  * Added `server` and `referer` to WebProcessor output

### 1.0.2 (2011-10-24)

  * Fixed bug in IE with large response headers and FirePHPHandler

### 1.0.1 (2011-08-25)

  * Added MemoryPeakUsageProcessor and MemoryUsageProcessor
  * Added Monolog\Logger::getName() to get a logger's channel name

### 1.0.0 (2011-07-06)

  * Added IntrospectionProcessor to get info from where the logger was called
  * Fixed WebProcessor in CLI

### 1.0.0-RC1 (2011-07-01)

  * Initial release
<p align="center"><img src="logo.jpg" alt="Monolog" width="400"></p>

# Monolog - Logging for PHP [![Continuous Integration](https://github.com/Seldaek/monolog/workflows/Continuous%20Integration/badge.svg?branch=main)](https://github.com/Seldaek/monolog/actions)

[![Total Downloads](https://img.shields.io/packagist/dt/monolog/monolog.svg)](https://packagist.org/packages/monolog/monolog)
[![Latest Stable Version](https://img.shields.io/packagist/v/monolog/monolog.svg)](https://packagist.org/packages/monolog/monolog)

>**Note** This is the **documentation for Monolog 3.x**, if you are using older releases
>see the documentation for [Monolog 2.x](https://github.com/Seldaek/monolog/blob/2.x/README.md) or [Monolog 1.x](https://github.com/Seldaek/monolog/blob/1.x/README.md)

Monolog sends your logs to files, sockets, inboxes, databases and various
web services. See the complete list of handlers below. Special handlers
allow you to build advanced logging strategies.

This library implements the [PSR-3](https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-3-logger-interface.md)
interface that you can type-hint against in your own libraries to keep
a maximum of interoperability. You can also use it in your applications to
make sure you can always use another compatible logger at a later time.
As of 1.11.0 Monolog public APIs will also accept PSR-3 log levels.
Internally Monolog still uses its own level scheme since it predates PSR-3.

<div align="center">
  <hr>
  <sup><b>Sponsored by:</b></sup>
  <br>
  <a href="https://betterstack.com">
    <div>
      <img src="https://github.com/Seldaek/monolog/assets/183678/7de58ce0-2fa2-45c0-b3e8-e60cebb3c4cf" width="200" alt="Better Stack">
    </div>
    <div>
      Better Stack lets you centralize, search, and visualize your logs.
    </div>
  </a>
  <br>
  <hr>
</div>

## Installation

Install the latest version with

```bash
composer require monolog/monolog
```

## Basic Usage

```php
<?php

use Monolog\Level;
use Monolog\Logger;
use Monolog\Handler\StreamHandler;

// create a log channel
$log = new Logger('name');
$log->pushHandler(new StreamHandler('path/to/your.log', Level::Warning));

// add records to the log
$log->warning('Foo');
$log->error('Bar');
```

## Documentation

- [Usage Instructions](doc/01-usage.md)
- [Handlers, Formatters and Processors](doc/02-handlers-formatters-processors.md)
- [Utility Classes](doc/03-utilities.md)
- [Extending Monolog](doc/04-extending.md)
- [Log Record Structure](doc/message-structure.md)

## Support Monolog Financially

Get supported Monolog and help fund the project with the [Tidelift Subscription](https://tidelift.com/subscription/pkg/packagist-monolog-monolog?utm_source=packagist-monolog-monolog&utm_medium=referral&utm_campaign=enterprise) or via [GitHub sponsorship](https://github.com/sponsors/Seldaek).

Tidelift delivers commercial support and maintenance for the open source dependencies you use to build your applications. Save time, reduce risk, and improve code health, while paying the maintainers of the exact dependencies you use.

## Third Party Packages

Third party handlers, formatters and processors are
[listed in the wiki](https://github.com/Seldaek/monolog/wiki/Third-Party-Packages). You
can also add your own there if you publish one.

## About

### Requirements

- Monolog `^3.0` works with PHP 8.1 or above.
- Monolog `^2.5` works with PHP 7.2 or above.
- Monolog `^1.25` works with PHP 5.3 up to 8.1, but is not very maintained anymore and will not receive PHP support fixes anymore.

### Support

Monolog 1.x support is somewhat limited at this point and only important fixes will be done. You should migrate to Monolog 2 or 3 where possible to benefit from all the latest features and fixes.

### Submitting bugs and feature requests

Bugs and feature request are tracked on [GitHub](https://github.com/Seldaek/monolog/issues)

### Framework Integrations

- Frameworks and libraries using [PSR-3](https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-3-logger-interface.md)
  can be used very easily with Monolog since it implements the interface.
- [Symfony](http://symfony.com) comes out of the box with Monolog.
- [Laravel](http://laravel.com/) comes out of the box with Monolog.
- [Lumen](http://lumen.laravel.com/) comes out of the box with Monolog.
- [PPI](https://github.com/ppi/framework) comes out of the box with Monolog.
- [CakePHP](http://cakephp.org/) is usable with Monolog via the [cakephp-monolog](https://github.com/jadb/cakephp-monolog) plugin.
- [XOOPS 2.6](http://xoops.org/) comes out of the box with Monolog.
- [Aura.Web_Project](https://github.com/auraphp/Aura.Web_Project) comes out of the box with Monolog.
- [Nette Framework](http://nette.org/en/) is usable with Monolog via the [contributte/monolog](https://github.com/contributte/monolog) or [orisai/nette-monolog](https://github.com/orisai/nette-monolog) extensions.
- [Proton Micro Framework](https://github.com/alexbilbie/Proton) comes out of the box with Monolog.
- [FuelPHP](http://fuelphp.com/) comes out of the box with Monolog.
- [Equip Framework](https://github.com/equip/framework) comes out of the box with Monolog.
- [Yii 2](http://www.yiiframework.com/) is usable with Monolog via the [yii2-monolog](https://github.com/merorafael/yii2-monolog) or [yii2-psr-log-target](https://github.com/samdark/yii2-psr-log-target) plugins.
- [Hawkbit Micro Framework](https://github.com/HawkBitPhp/hawkbit) comes out of the box with Monolog.
- [SilverStripe 4](https://www.silverstripe.org/) comes out of the box with Monolog.
- [Drupal](https://www.drupal.org/) is usable with Monolog via the [monolog](https://www.drupal.org/project/monolog) module.
- [Aimeos ecommerce framework](https://aimeos.org/) is usable with Monolog via the [ai-monolog](https://github.com/aimeos/ai-monolog) extension.
- [Magento](https://magento.com/) comes out of the box with Monolog.
- [Spiral Framework](https://spiral.dev) comes out of the box with Monolog bridge.
- [WebFramework](https://web-framework.com/) comes out of the box with Monolog.

### Author

Jordi Boggiano - <j.boggiano@seld.be> - <http://twitter.com/seldaek><br />
See also the list of [contributors](https://github.com/Seldaek/monolog/contributors) who participated in this project.

### License

Monolog is licensed under the MIT License - see the [LICENSE](LICENSE) file for details

### Acknowledgements

This library is heavily inspired by Python's [Logbook](https://logbook.readthedocs.io/en/stable/)
library, although most concepts have been adjusted to fit to the PHP world.
{
    "name": "monolog\/monolog",
    "description": "Sends your logs to files, sockets, inboxes, databases and various web services",
    "keywords": [
        "log",
        "logging",
        "psr-3"
    ],
    "homepage": "https:\/\/github.com\/Seldaek\/monolog",
    "type": "library",
    "license": "MIT",
    "authors": [
        {
            "name": "Jordi Boggiano",
            "email": "j.boggiano@seld.be",
            "homepage": "https:\/\/seld.be"
        }
    ],
    "require": {
        "php": ">=8.1",
        "psr\/log": "^2.0 || ^3.0"
    },
    "require-dev": {
        "ext-json": "*",
        "aws\/aws-sdk-php": "^3.0",
        "doctrine\/couchdb": "~1.0@dev",
        "elasticsearch\/elasticsearch": "^7 || ^8",
        "graylog2\/gelf-php": "^1.4.2 || ^2.0",
        "guzzlehttp\/guzzle": "^7.4.5",
        "guzzlehttp\/psr7": "^2.2",
        "mongodb\/mongodb": "^1.8 || ^2.0",
        "php-amqplib\/php-amqplib": "~2.4 || ^3",
        "php-console\/php-console": "^3.1.8",
        "phpstan\/phpstan": "^2",
        "phpstan\/phpstan-deprecation-rules": "^2",
        "phpstan\/phpstan-strict-rules": "^2",
        "phpunit\/phpunit": "^10.5.17 || ^11.0.7",
        "predis\/predis": "^1.1 || ^2",
        "rollbar\/rollbar": "^4.0",
        "ruflin\/elastica": "^7 || ^8",
        "symfony\/mailer": "^5.4 || ^6",
        "symfony\/mime": "^5.4 || ^6"
    },
    "suggest": {
        "graylog2\/gelf-php": "Allow sending log messages to a GrayLog2 server",
        "doctrine\/couchdb": "Allow sending log messages to a CouchDB server",
        "ruflin\/elastica": "Allow sending log messages to an Elastic Search server",
        "elasticsearch\/elasticsearch": "Allow sending log messages to an Elasticsearch server via official client",
        "php-amqplib\/php-amqplib": "Allow sending log messages to an AMQP server using php-amqplib",
        "ext-amqp": "Allow sending log messages to an AMQP server (1.0+ required)",
        "ext-mongodb": "Allow sending log messages to a MongoDB server (via driver)",
        "mongodb\/mongodb": "Allow sending log messages to a MongoDB server (via library)",
        "aws\/aws-sdk-php": "Allow sending log messages to AWS services like DynamoDB",
        "rollbar\/rollbar": "Allow sending log messages to Rollbar",
        "ext-mbstring": "Allow to work properly with unicode symbols",
        "ext-sockets": "Allow sending log messages to a Syslog server (via UDP driver)",
        "ext-curl": "Required to send log messages using the IFTTTHandler, the LogglyHandler, the SendGridHandler, the SlackWebhookHandler or the TelegramBotHandler",
        "ext-openssl": "Required to send log messages using SSL"
    },
    "autoload": {
        "psr-4": {
            "_ContaoManager\\Monolog\\": "src\/Monolog"
        }
    },
    "autoload-dev": {
        "psr-4": {
            "_ContaoManager\\Monolog\\": "tests\/Monolog"
        }
    },
    "provide": {
        "psr\/log-implementation": "3.0.0"
    },
    "extra": {
        "branch-alias": {
            "dev-main": "3.x-dev"
        }
    },
    "scripts": {
        "test": "@php vendor\/bin\/phpunit",
        "phpstan": "@php vendor\/bin\/phpstan analyse"
    },
    "config": {
        "lock": false,
        "sort-packages": true,
        "platform-check": false,
        "allow-plugins": {
            "php-http\/discovery": false
        }
    }
}<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Monolog\Handler;

use _ContaoManager\Monolog\Level;
use _ContaoManager\Monolog\Utils;
/**
 * SendGridHandler uses the SendGrid API v3 function to send Log emails, more information in https://www.twilio.com/docs/sendgrid/for-developers/sending-email/api-getting-started
 *
 * @author Ricardo Fontanelli <ricardo.fontanelli@hotmail.com>
 */
class SendGridHandler extends MailHandler
{
    /**
     * The SendGrid API User
     * @deprecated this is not used anymore as of SendGrid API v3
     */
    protected string $apiUser;
    /**
     * The email addresses to which the message will be sent
     * @var string[]
     */
    protected array $to;
    /**
     * @param string|null $apiUser Unused user as of SendGrid API v3, you can pass null or any string
     * @param list<string>|string $to
     * @param non-empty-string $apiHost Allows you to use another endpoint (e.g. api.eu.sendgrid.com)
     * @throws MissingExtensionException If the curl extension is missing
     */
    public function __construct(
        string|null $apiUser,
        protected string $apiKey,
        protected string $from,
        array|string $to,
        protected string $subject,
        int|string|Level $level = Level::Error,
        bool $bubble = \true,
        /** @var non-empty-string */
        private readonly string $apiHost = 'api.sendgrid.com'
    )
    {
        if (!\extension_loaded('curl')) {
            throw new MissingExtensionException('The curl extension is needed to use the SendGridHandler');
        }
        $this->to = (array) $to;
        // @phpstan-ignore property.deprecated
        $this->apiUser = $apiUser ?? '';
        parent::__construct($level, $bubble);
    }
    protected function send(string $content, array $records): void
    {
        $body = [];
        $body['personalizations'] = [];
        $body['from']['email'] = $this->from;
        foreach ($this->to as $recipient) {
            $body['personalizations'][]['to'][]['email'] = $recipient;
        }
        $body['subject'] = $this->subject;
        if ($this->isHtmlBody($content)) {
            $body['content'][] = ['type' => 'text/html', 'value' => $content];
        } else {
            $body['content'][] = ['type' => 'text/plain', 'value' => $content];
        }
        $ch = curl_init();
        curl_setopt($ch, \CURLOPT_HTTPHEADER, ['Content-Type: application/json', 'Authorization: Bearer ' . $this->apiKey]);
        curl_setopt($ch, \CURLOPT_URL, 'https://' . $this->apiHost . '/v3/mail/send');
        curl_setopt($ch, \CURLOPT_POST, \true);
        curl_setopt($ch, \CURLOPT_RETURNTRANSFER, \true);
        curl_setopt($ch, \CURLOPT_POSTFIELDS, Utils::jsonEncode($body));
        Curl\Util::execute($ch, 2);
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Monolog\Handler;

use _ContaoManager\Monolog\Level;
use _ContaoManager\Monolog\LogRecord;
/**
 * Inspired on LogEntriesHandler.
 *
 * @author Robert Kaufmann III <rok3@rok3.me>
 * @author Gabriel Machado <gabriel.ms1@hotmail.com>
 */
class InsightOpsHandler extends SocketHandler
{
    protected string $logToken;
    /**
     * @param string $token  Log token supplied by InsightOps
     * @param string $region Region where InsightOps account is hosted. Could be 'us' or 'eu'.
     * @param bool   $useSSL Whether or not SSL encryption should be used
     *
     * @throws MissingExtensionException If SSL encryption is set to true and OpenSSL is missing
     */
    public function __construct(string $token, string $region = 'us', bool $useSSL = \true, $level = Level::Debug, bool $bubble = \true, bool $persistent = \false, float $timeout = 0.0, float $writingTimeout = 10.0, ?float $connectionTimeout = null, ?int $chunkSize = null)
    {
        if ($useSSL && !\extension_loaded('openssl')) {
            throw new MissingExtensionException('The OpenSSL PHP plugin is required to use SSL encrypted connection for InsightOpsHandler');
        }
        $endpoint = $useSSL ? 'ssl://' . $region . '.data.logs.insight.rapid7.com:443' : $region . '.data.logs.insight.rapid7.com:80';
        parent::__construct($endpoint, $level, $bubble, $persistent, $timeout, $writingTimeout, $connectionTimeout, $chunkSize);
        $this->logToken = $token;
    }
    /**
     * @inheritDoc
     */
    protected function generateDataStream(LogRecord $record): string
    {
        return $this->logToken . ' ' . $record->formatted;
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Monolog\Handler;

use _ContaoManager\Monolog\Level;
use _ContaoManager\Monolog\Logger;
use _ContaoManager\Psr\Log\LogLevel;
use _ContaoManager\Monolog\LogRecord;
use _ContaoManager\NoDiscard;
/**
 * Used for testing purposes.
 *
 * It records all records and gives you access to them for verification.
 *
 * @author Jordi Boggiano <j.boggiano@seld.be>
 *
 * @method bool hasEmergency(array{message: string, context?: mixed[]}|string $recordAssertions)
 * @method bool hasAlert(array{message: string, context?: mixed[]}|string $recordAssertions)
 * @method bool hasCritical(array{message: string, context?: mixed[]}|string $recordAssertions)
 * @method bool hasError(array{message: string, context?: mixed[]}|string $recordAssertions)
 * @method bool hasWarning(array{message: string, context?: mixed[]}|string $recordAssertions)
 * @method bool hasNotice(array{message: string, context?: mixed[]}|string $recordAssertions)
 * @method bool hasInfo(array{message: string, context?: mixed[]}|string $recordAssertions)
 * @method bool hasDebug(array{message: string, context?: mixed[]}|string $recordAssertions)
 *
 * @method bool hasEmergencyRecords()
 * @method bool hasAlertRecords()
 * @method bool hasCriticalRecords()
 * @method bool hasErrorRecords()
 * @method bool hasWarningRecords()
 * @method bool hasNoticeRecords()
 * @method bool hasInfoRecords()
 * @method bool hasDebugRecords()
 *
 * @method bool hasEmergencyThatContains(string $message)
 * @method bool hasAlertThatContains(string $message)
 * @method bool hasCriticalThatContains(string $message)
 * @method bool hasErrorThatContains(string $message)
 * @method bool hasWarningThatContains(string $message)
 * @method bool hasNoticeThatContains(string $message)
 * @method bool hasInfoThatContains(string $message)
 * @method bool hasDebugThatContains(string $message)
 *
 * @method bool hasEmergencyThatMatches(string $regex)
 * @method bool hasAlertThatMatches(string $regex)
 * @method bool hasCriticalThatMatches(string $regex)
 * @method bool hasErrorThatMatches(string $regex)
 * @method bool hasWarningThatMatches(string $regex)
 * @method bool hasNoticeThatMatches(string $regex)
 * @method bool hasInfoThatMatches(string $regex)
 * @method bool hasDebugThatMatches(string $regex)
 *
 * @method bool hasEmergencyThatPasses(callable $predicate)
 * @method bool hasAlertThatPasses(callable $predicate)
 * @method bool hasCriticalThatPasses(callable $predicate)
 * @method bool hasErrorThatPasses(callable $predicate)
 * @method bool hasWarningThatPasses(callable $predicate)
 * @method bool hasNoticeThatPasses(callable $predicate)
 * @method bool hasInfoThatPasses(callable $predicate)
 * @method bool hasDebugThatPasses(callable $predicate)
 */
class TestHandler extends AbstractProcessingHandler
{
    /** @var LogRecord[] */
    protected array $records = [];
    /** @phpstan-var array<value-of<Level::VALUES>, LogRecord[]> */
    protected array $recordsByLevel = [];
    private bool $skipReset = \false;
    /**
     * @return array<LogRecord>
     */
    #[NoDiscard]
    public function getRecords(): array
    {
        return $this->records;
    }
    public function clear(): void
    {
        $this->records = [];
        $this->recordsByLevel = [];
    }
    public function reset(): void
    {
        if (!$this->skipReset) {
            $this->clear();
        }
    }
    public function setSkipReset(bool $skipReset): void
    {
        $this->skipReset = $skipReset;
    }
    /**
     * @param int|string|Level|LogLevel::* $level Logging level value or name
     *
     * @phpstan-param value-of<Level::VALUES>|value-of<Level::NAMES>|Level|LogLevel::* $level
     */
    #[NoDiscard]
    public function hasRecords(int|string|Level $level): bool
    {
        return isset($this->recordsByLevel[Logger::toMonologLevel($level)->value]);
    }
    /**
     * @param string|array $recordAssertions Either a message string or an array containing message and optionally context keys that will be checked against all records
     *
     * @phpstan-param array{message: string, context?: mixed[]}|string $recordAssertions
     */
    #[NoDiscard]
    public function hasRecord(string|array $recordAssertions, Level $level): bool
    {
        if (\is_string($recordAssertions)) {
            $recordAssertions = ['message' => $recordAssertions];
        }
        return $this->hasRecordThatPasses(function (LogRecord $rec) use ($recordAssertions) {
            if ($rec->message !== $recordAssertions['message']) {
                return \false;
            }
            if (isset($recordAssertions['context']) && $rec->context !== $recordAssertions['context']) {
                return \false;
            }
            return \true;
        }, $level);
    }
    #[NoDiscard]
    public function hasRecordThatContains(string $message, Level $level): bool
    {
        return $this->hasRecordThatPasses(fn(LogRecord $rec) => str_contains($rec->message, $message), $level);
    }
    #[NoDiscard]
    public function hasRecordThatMatches(string $regex, Level $level): bool
    {
        return $this->hasRecordThatPasses(fn(LogRecord $rec) => preg_match($regex, $rec->message) > 0, $level);
    }
    /**
     * @phpstan-param callable(LogRecord, int): mixed $predicate
     */
    #[NoDiscard]
    public function hasRecordThatPasses(callable $predicate, Level $level): bool
    {
        $level = Logger::toMonologLevel($level);
        if (!isset($this->recordsByLevel[$level->value])) {
            return \false;
        }
        foreach ($this->recordsByLevel[$level->value] as $i => $rec) {
            if ((bool) $predicate($rec, $i)) {
                return \true;
            }
        }
        return \false;
    }
    /**
     * @inheritDoc
     */
    protected function write(LogRecord $record): void
    {
        $this->recordsByLevel[$record->level->value][] = $record;
        $this->records[] = $record;
    }
    /**
     * @param mixed[] $args
     */
    #[NoDiscard]
    public function __call(string $method, array $args): bool
    {
        if ((bool) preg_match('/(.*)(Debug|Info|Notice|Warning|Error|Critical|Alert|Emergency)(.*)/', $method, $matches)) {
            $genericMethod = $matches[1] . ('Records' !== $matches[3] ? 'Record' : '') . $matches[3];
            $level = \constant(Level::class . '::' . $matches[2]);
            $callback = [$this, $genericMethod];
            if (\is_callable($callback)) {
                $args[] = $level;
                return \call_user_func_array($callback, $args);
            }
        }
        throw new \BadMethodCallException('Call to undefined method ' . \get_class($this) . '::' . $method . '()');
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Monolog\Handler;

use _ContaoManager\Monolog\Level;
use _ContaoManager\Monolog\Utils;
use _ContaoManager\Monolog\LogRecord;
/**
 * IFTTTHandler uses cURL to trigger IFTTT Maker actions
 *
 * Register a secret key and trigger/event name at https://ifttt.com/maker
 *
 * value1 will be the channel from monolog's Logger constructor,
 * value2 will be the level name (ERROR, WARNING, ..)
 * value3 will be the log record's message
 *
 * @author Nehal Patel <nehal@nehalpatel.me>
 */
class IFTTTHandler extends AbstractProcessingHandler
{
    private string $eventName;
    private string $secretKey;
    /**
     * @param string $eventName The name of the IFTTT Maker event that should be triggered
     * @param string $secretKey A valid IFTTT secret key
     *
     * @throws MissingExtensionException If the curl extension is missing
     */
    public function __construct(string $eventName, string $secretKey, int|string|Level $level = Level::Error, bool $bubble = \true)
    {
        if (!\extension_loaded('curl')) {
            throw new MissingExtensionException('The curl extension is needed to use the IFTTTHandler');
        }
        $this->eventName = $eventName;
        $this->secretKey = $secretKey;
        parent::__construct($level, $bubble);
    }
    /**
     * @inheritDoc
     */
    public function write(LogRecord $record): void
    {
        $postData = ["value1" => $record->channel, "value2" => $record["level_name"], "value3" => $record->message];
        $postString = Utils::jsonEncode($postData);
        $ch = curl_init();
        curl_setopt($ch, \CURLOPT_URL, "https://maker.ifttt.com/trigger/" . $this->eventName . "/with/key/" . $this->secretKey);
        curl_setopt($ch, \CURLOPT_POST, \true);
        curl_setopt($ch, \CURLOPT_RETURNTRANSFER, \true);
        curl_setopt($ch, \CURLOPT_POSTFIELDS, $postString);
        curl_setopt($ch, \CURLOPT_HTTPHEADER, ["Content-Type: application/json"]);
        Curl\Util::execute($ch);
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Monolog\Handler;

trait WebRequestRecognizerTrait
{
    /**
     * Checks if PHP's serving a web request
     */
    protected function isWebRequest(): bool
    {
        return 'cli' !== \PHP_SAPI && 'phpdbg' !== \PHP_SAPI;
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Monolog\Handler;

use _ContaoManager\Monolog\Level;
use _ContaoManager\Monolog\LogRecord;
/**
 * Stores to any socket - uses fsockopen() or pfsockopen().
 *
 * @author Pablo de Leon Belloc <pablolb@gmail.com>
 * @see    http://php.net/manual/en/function.fsockopen.php
 */
class SocketHandler extends AbstractProcessingHandler
{
    private string $connectionString;
    private float $connectionTimeout;
    /** @var resource|null */
    private $resource;
    private float $timeout;
    private float $writingTimeout;
    private int|null $lastSentBytes = null;
    private int|null $chunkSize;
    private bool $persistent;
    private int|null $errno = null;
    private string|null $errstr = null;
    private float|null $lastWritingAt = null;
    /**
     * @param string     $connectionString  Socket connection string
     * @param bool       $persistent        Flag to enable/disable persistent connections
     * @param float      $timeout           Socket timeout to wait until the request is being aborted
     * @param float      $writingTimeout    Socket timeout to wait until the request should've been sent/written
     * @param float|null $connectionTimeout Socket connect timeout to wait until the connection should've been
     *                                      established
     * @param int|null   $chunkSize         Sets the chunk size. Only has effect during connection in the writing cycle
     *
     * @throws \InvalidArgumentException If an invalid timeout value (less than 0) is passed.
     */
    public function __construct(string $connectionString, $level = Level::Debug, bool $bubble = \true, bool $persistent = \false, float $timeout = 0.0, float $writingTimeout = 10.0, ?float $connectionTimeout = null, ?int $chunkSize = null)
    {
        parent::__construct($level, $bubble);
        $this->connectionString = $connectionString;
        if ($connectionTimeout !== null) {
            $this->validateTimeout($connectionTimeout);
        }
        $this->connectionTimeout = $connectionTimeout ?? (float) \ini_get('default_socket_timeout');
        $this->persistent = $persistent;
        $this->validateTimeout($timeout);
        $this->timeout = $timeout;
        $this->validateTimeout($writingTimeout);
        $this->writingTimeout = $writingTimeout;
        $this->chunkSize = $chunkSize;
    }
    /**
     * Connect (if necessary) and write to the socket
     *
     * @inheritDoc
     *
     * @throws \UnexpectedValueException
     * @throws \RuntimeException
     */
    protected function write(LogRecord $record): void
    {
        $this->connectIfNotConnected();
        $data = $this->generateDataStream($record);
        $this->writeToSocket($data);
    }
    /**
     * We will not close a PersistentSocket instance so it can be reused in other requests.
     */
    public function close(): void
    {
        if (!$this->isPersistent()) {
            $this->closeSocket();
        }
    }
    /**
     * Close socket, if open
     */
    public function closeSocket(): void
    {
        if (\is_resource($this->resource)) {
            fclose($this->resource);
            $this->resource = null;
        }
    }
    /**
     * Set socket connection to be persistent. It only has effect before the connection is initiated.
     *
     * @return $this
     */
    public function setPersistent(bool $persistent): self
    {
        $this->persistent = $persistent;
        return $this;
    }
    /**
     * Set connection timeout.  Only has effect before we connect.
     *
     * @see http://php.net/manual/en/function.fsockopen.php
     * @return $this
     */
    public function setConnectionTimeout(float $seconds): self
    {
        $this->validateTimeout($seconds);
        $this->connectionTimeout = $seconds;
        return $this;
    }
    /**
     * Set write timeout. Only has effect before we connect.
     *
     * @see http://php.net/manual/en/function.stream-set-timeout.php
     * @return $this
     */
    public function setTimeout(float $seconds): self
    {
        $this->validateTimeout($seconds);
        $this->timeout = $seconds;
        return $this;
    }
    /**
     * Set writing timeout. Only has effect during connection in the writing cycle.
     *
     * @param  float $seconds 0 for no timeout
     * @return $this
     */
    public function setWritingTimeout(float $seconds): self
    {
        $this->validateTimeout($seconds);
        $this->writingTimeout = $seconds;
        return $this;
    }
    /**
     * Set chunk size. Only has effect during connection in the writing cycle.
     *
     * @return $this
     */
    public function setChunkSize(int $bytes): self
    {
        $this->chunkSize = $bytes;
        return $this;
    }
    /**
     * Get current connection string
     */
    public function getConnectionString(): string
    {
        return $this->connectionString;
    }
    /**
     * Get persistent setting
     */
    public function isPersistent(): bool
    {
        return $this->persistent;
    }
    /**
     * Get current connection timeout setting
     */
    public function getConnectionTimeout(): float
    {
        return $this->connectionTimeout;
    }
    /**
     * Get current in-transfer timeout
     */
    public function getTimeout(): float
    {
        return $this->timeout;
    }
    /**
     * Get current local writing timeout
     */
    public function getWritingTimeout(): float
    {
        return $this->writingTimeout;
    }
    /**
     * Get current chunk size
     */
    public function getChunkSize(): ?int
    {
        return $this->chunkSize;
    }
    /**
     * Check to see if the socket is currently available.
     *
     * UDP might appear to be connected but might fail when writing.  See http://php.net/fsockopen for details.
     */
    public function isConnected(): bool
    {
        return \is_resource($this->resource) && !feof($this->resource);
        // on TCP - other party can close connection.
    }
    /**
     * Wrapper to allow mocking
     *
     * @return resource|false
     */
    protected function pfsockopen()
    {
        return @pfsockopen($this->connectionString, -1, $this->errno, $this->errstr, $this->connectionTimeout);
    }
    /**
     * Wrapper to allow mocking
     *
     * @return resource|false
     */
    protected function fsockopen()
    {
        return @fsockopen($this->connectionString, -1, $this->errno, $this->errstr, $this->connectionTimeout);
    }
    /**
     * Wrapper to allow mocking
     *
     * @see http://php.net/manual/en/function.stream-set-timeout.php
     */
    protected function streamSetTimeout(): bool
    {
        $seconds = floor($this->timeout);
        $microseconds = round(($this->timeout - $seconds) * 1000000.0);
        if (!\is_resource($this->resource)) {
            throw new \LogicException('streamSetTimeout called but $this->resource is not a resource');
        }
        return stream_set_timeout($this->resource, (int) $seconds, (int) $microseconds);
    }
    /**
     * Wrapper to allow mocking
     *
     * @see http://php.net/manual/en/function.stream-set-chunk-size.php
     *
     * @return int|false
     */
    protected function streamSetChunkSize(): int|bool
    {
        if (!\is_resource($this->resource)) {
            throw new \LogicException('streamSetChunkSize called but $this->resource is not a resource');
        }
        if (null === $this->chunkSize) {
            throw new \LogicException('streamSetChunkSize called but $this->chunkSize is not set');
        }
        return stream_set_chunk_size($this->resource, $this->chunkSize);
    }
    /**
     * Wrapper to allow mocking
     *
     * @return int|false
     */
    protected function fwrite(string $data): int|bool
    {
        if (!\is_resource($this->resource)) {
            throw new \LogicException('fwrite called but $this->resource is not a resource');
        }
        return @fwrite($this->resource, $data);
    }
    /**
     * Wrapper to allow mocking
     *
     * @return mixed[]|bool
     */
    protected function streamGetMetadata(): array|bool
    {
        if (!\is_resource($this->resource)) {
            throw new \LogicException('streamGetMetadata called but $this->resource is not a resource');
        }
        return stream_get_meta_data($this->resource);
    }
    private function validateTimeout(float $value): void
    {
        if ($value < 0) {
            throw new \InvalidArgumentException("Timeout must be 0 or a positive float (got {$value})");
        }
    }
    private function connectIfNotConnected(): void
    {
        if ($this->isConnected()) {
            return;
        }
        $this->connect();
    }
    protected function generateDataStream(LogRecord $record): string
    {
        return (string) $record->formatted;
    }
    /**
     * @return resource|null
     */
    protected function getResource()
    {
        return $this->resource;
    }
    private function connect(): void
    {
        $this->createSocketResource();
        $this->setSocketTimeout();
        $this->setStreamChunkSize();
    }
    private function createSocketResource(): void
    {
        if ($this->isPersistent()) {
            $resource = $this->pfsockopen();
        } else {
            $resource = $this->fsockopen();
        }
        if (\is_bool($resource)) {
            throw new \UnexpectedValueException("Failed connecting to {$this->connectionString} ({$this->errno}: {$this->errstr})");
        }
        $this->resource = $resource;
    }
    private function setSocketTimeout(): void
    {
        if (!$this->streamSetTimeout()) {
            throw new \UnexpectedValueException("Failed setting timeout with stream_set_timeout()");
        }
    }
    private function setStreamChunkSize(): void
    {
        if (null !== $this->chunkSize && \false === $this->streamSetChunkSize()) {
            throw new \UnexpectedValueException("Failed setting chunk size with stream_set_chunk_size()");
        }
    }
    private function writeToSocket(string $data): void
    {
        $length = \strlen($data);
        $sent = 0;
        $this->lastSentBytes = $sent;
        while ($this->isConnected() && $sent < $length) {
            if (0 === $sent) {
                $chunk = $this->fwrite($data);
            } else {
                $chunk = $this->fwrite(substr($data, $sent));
            }
            if ($chunk === \false) {
                throw new \RuntimeException("Could not write to socket");
            }
            $sent += $chunk;
            $socketInfo = $this->streamGetMetadata();
            if (\is_array($socketInfo) && (bool) $socketInfo['timed_out']) {
                throw new \RuntimeException("Write timed-out");
            }
            if ($this->writingIsTimedOut($sent)) {
                throw new \RuntimeException("Write timed-out, no data sent for `{$this->writingTimeout}` seconds, probably we got disconnected (sent {$sent} of {$length})");
            }
        }
        if (!$this->isConnected() && $sent < $length) {
            throw new \RuntimeException("End-of-file reached, probably we got disconnected (sent {$sent} of {$length})");
        }
    }
    private function writingIsTimedOut(int $sent): bool
    {
        // convert to ms
        if (0.0 === $this->writingTimeout) {
            return \false;
        }
        if ($sent !== $this->lastSentBytes) {
            $this->lastWritingAt = microtime(\true);
            $this->lastSentBytes = $sent;
            return \false;
        } else {
            usleep(100);
        }
        if (microtime(\true) - (float) $this->lastWritingAt >= $this->writingTimeout) {
            $this->closeSocket();
            return \true;
        }
        return \false;
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Monolog\Handler;

use Closure;
use _ContaoManager\Monolog\Level;
use _ContaoManager\Monolog\LogRecord;
use _ContaoManager\Monolog\Utils;
use _ContaoManager\Monolog\Formatter\FormatterInterface;
use _ContaoManager\Monolog\Formatter\LineFormatter;
use _ContaoManager\Symfony\Component\Mailer\MailerInterface;
use _ContaoManager\Symfony\Component\Mailer\Transport\TransportInterface;
use _ContaoManager\Symfony\Component\Mime\Email;
/**
 * SymfonyMailerHandler uses Symfony's Mailer component to send the emails
 *
 * @author Jordi Boggiano <j.boggiano@seld.be>
 */
class SymfonyMailerHandler extends MailHandler
{
    protected MailerInterface|TransportInterface $mailer;
    /** @var Email|Closure(string, LogRecord[]): Email */
    private Email|Closure $emailTemplate;
    /**
     * @phpstan-param Email|Closure(string, LogRecord[]): Email $email
     *
     * @param MailerInterface|TransportInterface $mailer The mailer to use
     * @param Closure|Email                      $email  An email template, the subject/body will be replaced
     */
    public function __construct($mailer, Email|Closure $email, int|string|Level $level = Level::Error, bool $bubble = \true)
    {
        parent::__construct($level, $bubble);
        $this->mailer = $mailer;
        $this->emailTemplate = $email;
    }
    /**
     * {@inheritDoc}
     */
    protected function send(string $content, array $records): void
    {
        $this->mailer->send($this->buildMessage($content, $records));
    }
    /**
     * Gets the formatter for the Swift_Message subject.
     *
     * @param string|null $format The format of the subject
     */
    protected function getSubjectFormatter(?string $format): FormatterInterface
    {
        return new LineFormatter($format);
    }
    /**
     * Creates instance of Email to be sent
     *
     * @param string      $content formatted email body to be sent
     * @param LogRecord[] $records Log records that formed the content
     */
    protected function buildMessage(string $content, array $records): Email
    {
        $message = null;
        if ($this->emailTemplate instanceof Email) {
            $message = clone $this->emailTemplate;
        } elseif (\is_callable($this->emailTemplate)) {
            $message = ($this->emailTemplate)($content, $records);
        }
        if (!$message instanceof Email) {
            $record = reset($records);
            throw new \InvalidArgumentException('Could not resolve message as instance of Email or a callable returning it' . ($record instanceof LogRecord ? Utils::getRecordMessageForException($record) : ''));
        }
        if (\count($records) > 0) {
            $subjectFormatter = $this->getSubjectFormatter($message->getSubject());
            $message->subject($subjectFormatter->format($this->getHighestRecord($records)));
        }
        if ($this->isHtmlBody($content)) {
            if (null !== $charset = $message->getHtmlCharset()) {
                $message->html($content, $charset);
            } else {
                $message->html($content);
            }
        } else if (null !== $charset = $message->getTextCharset()) {
            $message->text($content, $charset);
        } else {
            $message->text($content);
        }
        return $message->date(new \DateTimeImmutable());
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Monolog\Handler;

use _ContaoManager\Monolog\LogRecord;
/**
 * No-op
 *
 * This handler handles anything, but does nothing, and does not stop bubbling to the rest of the stack.
 * This can be used for testing, or to disable a handler when overriding a configuration without
 * influencing the rest of the stack.
 *
 * @author Roel Harbers <roelharbers@gmail.com>
 */
class NoopHandler extends Handler
{
    /**
     * @inheritDoc
     */
    public function isHandling(LogRecord $record): bool
    {
        return \true;
    }
    /**
     * @inheritDoc
     */
    public function handle(LogRecord $record): bool
    {
        return \false;
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Monolog\Handler;

use _ContaoManager\Monolog\Level;
use _ContaoManager\Monolog\ResettableInterface;
use _ContaoManager\Monolog\Formatter\FormatterInterface;
use _ContaoManager\Monolog\LogRecord;
/**
 * Buffers all records until closing the handler and then pass them as batch.
 *
 * This is useful for a MailHandler to send only one mail per request instead of
 * sending one per log message.
 *
 * @author Christophe Coevoet <stof@notk.org>
 */
class BufferHandler extends AbstractHandler implements ProcessableHandlerInterface, FormattableHandlerInterface
{
    use ProcessableHandlerTrait;
    protected HandlerInterface $handler;
    protected int $bufferSize = 0;
    protected int $bufferLimit;
    protected bool $flushOnOverflow;
    /** @var LogRecord[] */
    protected array $buffer = [];
    protected bool $initialized = \false;
    /**
     * @param HandlerInterface $handler         Handler.
     * @param int              $bufferLimit     How many entries should be buffered at most, beyond that the oldest items are removed from the buffer.
     * @param bool             $flushOnOverflow If true, the buffer is flushed when the max size has been reached, by default oldest entries are discarded
     */
    public function __construct(HandlerInterface $handler, int $bufferLimit = 0, int|string|Level $level = Level::Debug, bool $bubble = \true, bool $flushOnOverflow = \false)
    {
        parent::__construct($level, $bubble);
        $this->handler = $handler;
        $this->bufferLimit = $bufferLimit;
        $this->flushOnOverflow = $flushOnOverflow;
    }
    /**
     * @inheritDoc
     */
    public function handle(LogRecord $record): bool
    {
        if ($record->level->isLowerThan($this->level)) {
            return \false;
        }
        if (!$this->initialized) {
            // __destructor() doesn't get called on Fatal errors
            register_shutdown_function([$this, 'close']);
            $this->initialized = \true;
        }
        if ($this->bufferLimit > 0 && $this->bufferSize === $this->bufferLimit) {
            if ($this->flushOnOverflow) {
                $this->flush();
            } else {
                array_shift($this->buffer);
                $this->bufferSize--;
            }
        }
        if (\count($this->processors) > 0) {
            $record = $this->processRecord($record);
        }
        $this->buffer[] = $record;
        $this->bufferSize++;
        return \false === $this->bubble;
    }
    public function flush(): void
    {
        if ($this->bufferSize === 0) {
            return;
        }
        $this->handler->handleBatch($this->buffer);
        $this->clear();
    }
    public function __destruct()
    {
        // suppress the parent behavior since we already have register_shutdown_function()
        // to call close(), and the reference contained there will prevent this from being
        // GC'd until the end of the request
    }
    /**
     * @inheritDoc
     */
    public function close(): void
    {
        $this->flush();
        $this->handler->close();
    }
    /**
     * Clears the buffer without flushing any messages down to the wrapped handler.
     */
    public function clear(): void
    {
        $this->bufferSize = 0;
        $this->buffer = [];
    }
    public function reset(): void
    {
        $this->flush();
        parent::reset();
        $this->resetProcessors();
        if ($this->handler instanceof ResettableInterface) {
            $this->handler->reset();
        }
    }
    /**
     * @inheritDoc
     */
    public function setFormatter(FormatterInterface $formatter): HandlerInterface
    {
        if ($this->handler instanceof FormattableHandlerInterface) {
            $this->handler->setFormatter($formatter);
            return $this;
        }
        throw new \UnexpectedValueException('The nested handler of type ' . \get_class($this->handler) . ' does not support formatters.');
    }
    /**
     * @inheritDoc
     */
    public function getFormatter(): FormatterInterface
    {
        if ($this->handler instanceof FormattableHandlerInterface) {
            return $this->handler->getFormatter();
        }
        throw new \UnexpectedValueException('The nested handler of type ' . \get_class($this->handler) . ' does not support formatters.');
    }
    public function setHandler(HandlerInterface $handler): void
    {
        $this->handler = $handler;
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Monolog\Handler;

use _ContaoManager\Monolog\Level;
use _ContaoManager\Monolog\LogRecord;
/**
 * Logs to syslog service.
 *
 * usage example:
 *
 *   $log = new Logger('application');
 *   $syslog = new SyslogHandler('myfacility', 'local6');
 *   $formatter = new LineFormatter("%channel%.%level_name%: %message% %extra%");
 *   $syslog->setFormatter($formatter);
 *   $log->pushHandler($syslog);
 *
 * @author Sven Paulus <sven@karlsruhe.org>
 */
class SyslogHandler extends AbstractSyslogHandler
{
    protected string $ident;
    protected int $logopts;
    /**
     * @param string|int $facility Either one of the names of the keys in $this->facilities, or a LOG_* facility constant
     * @param int        $logopts  Option flags for the openlog() call, defaults to LOG_PID
     */
    public function __construct(string $ident, string|int $facility = \LOG_USER, int|string|Level $level = Level::Debug, bool $bubble = \true, int $logopts = \LOG_PID)
    {
        parent::__construct($facility, $level, $bubble);
        $this->ident = $ident;
        $this->logopts = $logopts;
    }
    /**
     * @inheritDoc
     */
    public function close(): void
    {
        closelog();
    }
    /**
     * @inheritDoc
     */
    protected function write(LogRecord $record): void
    {
        openlog($this->ident, $this->logopts, $this->facility);
        syslog($this->toSyslogPriority($record->level), (string) $record->formatted);
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Monolog\Handler;

use _ContaoManager\Monolog\Level;
use _ContaoManager\Rollbar\RollbarLogger;
use Throwable;
use _ContaoManager\Monolog\LogRecord;
/**
 * Sends errors to Rollbar
 *
 * If the context data contains a `payload` key, that is used as an array
 * of payload options to RollbarLogger's log method.
 *
 * Rollbar's context info will contain the context + extra keys from the log record
 * merged, and then on top of that a few keys:
 *
 *  - level (rollbar level name)
 *  - monolog_level (monolog level name, raw level, as rollbar only has 5 but monolog 8)
 *  - channel
 *  - datetime (unix timestamp)
 *
 * @author Paul Statezny <paulstatezny@gmail.com>
 */
class RollbarHandler extends AbstractProcessingHandler
{
    protected RollbarLogger $rollbarLogger;
    /**
     * Records whether any log records have been added since the last flush of the rollbar notifier
     */
    private bool $hasRecords = \false;
    protected bool $initialized = \false;
    /**
     * @param RollbarLogger $rollbarLogger RollbarLogger object constructed with valid token
     */
    public function __construct(RollbarLogger $rollbarLogger, int|string|Level $level = Level::Error, bool $bubble = \true)
    {
        $this->rollbarLogger = $rollbarLogger;
        parent::__construct($level, $bubble);
    }
    /**
     * Translates Monolog log levels to Rollbar levels.
     *
     * @return 'debug'|'info'|'warning'|'error'|'critical'
     */
    protected function toRollbarLevel(Level $level): string
    {
        return match ($level) {
            Level::Debug => 'debug',
            Level::Info => 'info',
            Level::Notice => 'info',
            Level::Warning => 'warning',
            Level::Error => 'error',
            Level::Critical => 'critical',
            Level::Alert => 'critical',
            Level::Emergency => 'critical',
        };
    }
    /**
     * @inheritDoc
     */
    protected function write(LogRecord $record): void
    {
        if (!$this->initialized) {
            // __destructor() doesn't get called on Fatal errors
            register_shutdown_function([$this, 'close']);
            $this->initialized = \true;
        }
        $context = $record->context;
        $context = array_merge($context, $record->extra, ['level' => $this->toRollbarLevel($record->level), 'monolog_level' => $record->level->getName(), 'channel' => $record->channel, 'datetime' => $record->datetime->format('U')]);
        if (isset($context['exception']) && $context['exception'] instanceof Throwable) {
            $exception = $context['exception'];
            unset($context['exception']);
            $toLog = $exception;
        } else {
            $toLog = $record->message;
        }
        $this->rollbarLogger->log($context['level'], $toLog, $context);
        $this->hasRecords = \true;
    }
    public function flush(): void
    {
        if ($this->hasRecords) {
            $this->rollbarLogger->flush();
            $this->hasRecords = \false;
        }
    }
    /**
     * @inheritDoc
     */
    public function close(): void
    {
        $this->flush();
    }
    /**
     * @inheritDoc
     */
    public function reset(): void
    {
        $this->flush();
        parent::reset();
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Monolog\Handler;

use Closure;
use _ContaoManager\Monolog\Handler\FingersCrossed\ErrorLevelActivationStrategy;
use _ContaoManager\Monolog\Handler\FingersCrossed\ActivationStrategyInterface;
use _ContaoManager\Monolog\Level;
use _ContaoManager\Monolog\Logger;
use _ContaoManager\Monolog\ResettableInterface;
use _ContaoManager\Monolog\Formatter\FormatterInterface;
use _ContaoManager\Psr\Log\LogLevel;
use _ContaoManager\Monolog\LogRecord;
/**
 * Buffers all records until a certain level is reached
 *
 * The advantage of this approach is that you don't get any clutter in your log files.
 * Only requests which actually trigger an error (or whatever your actionLevel is) will be
 * in the logs, but they will contain all records, not only those above the level threshold.
 *
 * You can then have a passthruLevel as well which means that at the end of the request,
 * even if it did not get activated, it will still send through log records of e.g. at least a
 * warning level.
 *
 * You can find the various activation strategies in the
 * Monolog\Handler\FingersCrossed\ namespace.
 *
 * @author Jordi Boggiano <j.boggiano@seld.be>
 */
class FingersCrossedHandler extends Handler implements ProcessableHandlerInterface, ResettableInterface, FormattableHandlerInterface
{
    use ProcessableHandlerTrait;
    /**
     * Handler or factory Closure($record, $this)
     *
     * @phpstan-var (Closure(LogRecord|null, HandlerInterface): HandlerInterface)|HandlerInterface
     */
    protected Closure|HandlerInterface $handler;
    protected ActivationStrategyInterface $activationStrategy;
    protected bool $buffering = \true;
    protected int $bufferSize;
    /** @var LogRecord[] */
    protected array $buffer = [];
    protected bool $stopBuffering;
    protected Level|null $passthruLevel = null;
    protected bool $bubble;
    /**
     * @phpstan-param (Closure(LogRecord|null, HandlerInterface): HandlerInterface)|HandlerInterface $handler
     *
     * @param Closure|HandlerInterface          $handler            Handler or factory Closure($record|null, $fingersCrossedHandler).
     * @param int|string|Level|LogLevel::*|null $activationStrategy Strategy which determines when this handler takes action, or a level name/value at which the handler is activated
     * @param int                               $bufferSize         How many entries should be buffered at most, beyond that the oldest items are removed from the buffer.
     * @param bool                              $bubble             Whether the messages that are handled can bubble up the stack or not
     * @param bool                              $stopBuffering      Whether the handler should stop buffering after being triggered (default true)
     * @param int|string|Level|LogLevel::*|null $passthruLevel      Minimum level to always flush to handler on close, even if strategy not triggered
     *
     * @phpstan-param value-of<Level::VALUES>|value-of<Level::NAMES>|Level|LogLevel::*|ActivationStrategyInterface|null $activationStrategy
     * @phpstan-param value-of<Level::VALUES>|value-of<Level::NAMES>|Level|LogLevel::*|null $passthruLevel
     */
    public function __construct(Closure|HandlerInterface $handler, int|string|Level|ActivationStrategyInterface|null $activationStrategy = null, int $bufferSize = 0, bool $bubble = \true, bool $stopBuffering = \true, int|string|Level|null $passthruLevel = null)
    {
        if (null === $activationStrategy) {
            $activationStrategy = new ErrorLevelActivationStrategy(Level::Warning);
        }
        // convert simple int activationStrategy to an object
        if (!$activationStrategy instanceof ActivationStrategyInterface) {
            $activationStrategy = new ErrorLevelActivationStrategy($activationStrategy);
        }
        $this->handler = $handler;
        $this->activationStrategy = $activationStrategy;
        $this->bufferSize = $bufferSize;
        $this->bubble = $bubble;
        $this->stopBuffering = $stopBuffering;
        if ($passthruLevel !== null) {
            $this->passthruLevel = Logger::toMonologLevel($passthruLevel);
        }
    }
    /**
     * @inheritDoc
     */
    public function isHandling(LogRecord $record): bool
    {
        return \true;
    }
    /**
     * Manually activate this logger regardless of the activation strategy
     */
    public function activate(): void
    {
        if ($this->stopBuffering) {
            $this->buffering = \false;
        }
        $this->getHandler(end($this->buffer) ?: null)->handleBatch($this->buffer);
        $this->buffer = [];
    }
    /**
     * @inheritDoc
     */
    public function handle(LogRecord $record): bool
    {
        if (\count($this->processors) > 0) {
            $record = $this->processRecord($record);
        }
        if ($this->buffering) {
            $this->buffer[] = $record;
            if ($this->bufferSize > 0 && \count($this->buffer) > $this->bufferSize) {
                array_shift($this->buffer);
            }
            if ($this->activationStrategy->isHandlerActivated($record)) {
                $this->activate();
            }
        } else {
            $this->getHandler($record)->handle($record);
        }
        return \false === $this->bubble;
    }
    /**
     * @inheritDoc
     */
    public function close(): void
    {
        $this->flushBuffer();
        $this->getHandler()->close();
    }
    public function reset(): void
    {
        $this->flushBuffer();
        $this->resetProcessors();
        if ($this->getHandler() instanceof ResettableInterface) {
            $this->getHandler()->reset();
        }
    }
    /**
     * Clears the buffer without flushing any messages down to the wrapped handler.
     *
     * It also resets the handler to its initial buffering state.
     */
    public function clear(): void
    {
        $this->buffer = [];
        $this->reset();
    }
    /**
     * Resets the state of the handler. Stops forwarding records to the wrapped handler.
     */
    private function flushBuffer(): void
    {
        if (null !== $this->passthruLevel) {
            $passthruLevel = $this->passthruLevel;
            $this->buffer = array_filter($this->buffer, static function ($record) use ($passthruLevel) {
                return $passthruLevel->includes($record->level);
            });
            if (\count($this->buffer) > 0) {
                $this->getHandler(end($this->buffer))->handleBatch($this->buffer);
            }
        }
        $this->buffer = [];
        $this->buffering = \true;
    }
    /**
     * Return the nested handler
     *
     * If the handler was provided as a factory, this will trigger the handler's instantiation.
     */
    public function getHandler(LogRecord|null $record = null): HandlerInterface
    {
        if (!$this->handler instanceof HandlerInterface) {
            $handler = ($this->handler)($record, $this);
            if (!$handler instanceof HandlerInterface) {
                throw new \RuntimeException("The factory Closure should return a HandlerInterface");
            }
            $this->handler = $handler;
        }
        return $this->handler;
    }
    /**
     * @inheritDoc
     */
    public function setFormatter(FormatterInterface $formatter): HandlerInterface
    {
        $handler = $this->getHandler();
        if ($handler instanceof FormattableHandlerInterface) {
            $handler->setFormatter($formatter);
            return $this;
        }
        throw new \UnexpectedValueException('The nested handler of type ' . \get_class($handler) . ' does not support formatters.');
    }
    /**
     * @inheritDoc
     */
    public function getFormatter(): FormatterInterface
    {
        $handler = $this->getHandler();
        if ($handler instanceof FormattableHandlerInterface) {
            return $handler->getFormatter();
        }
        throw new \UnexpectedValueException('The nested handler of type ' . \get_class($handler) . ' does not support formatters.');
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Monolog\Handler;

use _ContaoManager\Monolog\Level;
use _ContaoManager\Monolog\Formatter\FormatterInterface;
use _ContaoManager\Monolog\LogRecord;
/**
 * Handler to only pass log messages when a certain threshold of number of messages is reached.
 *
 * This can be useful in cases of processing a batch of data, but you're for example only interested
 * in case it fails catastrophically instead of a warning for 1 or 2 events. Worse things can happen, right?
 *
 * Usage example:
 *
 * ```
 *   $log = new Logger('application');
 *   $handler = new SomeHandler(...)
 *
 *   // Pass all warnings to the handler when more than 10 & all error messages when more then 5
 *   $overflow = new OverflowHandler($handler, [Level::Warning->value => 10, Level::Error->value => 5]);
 *
 *   $log->pushHandler($overflow);
 *```
 *
 * @author Kris Buist <krisbuist@gmail.com>
 */
class OverflowHandler extends AbstractHandler implements FormattableHandlerInterface
{
    private HandlerInterface $handler;
    /** @var array<int, int> */
    private array $thresholdMap = [];
    /**
     * Buffer of all messages passed to the handler before the threshold was reached
     *
     * @var mixed[][]
     */
    private array $buffer = [];
    /**
     * @param array<int, int> $thresholdMap Dictionary of log level value => threshold
     */
    public function __construct(HandlerInterface $handler, array $thresholdMap = [], $level = Level::Debug, bool $bubble = \true)
    {
        $this->handler = $handler;
        foreach ($thresholdMap as $thresholdLevel => $threshold) {
            $this->thresholdMap[$thresholdLevel] = $threshold;
        }
        parent::__construct($level, $bubble);
    }
    /**
     * Handles a record.
     *
     * All records may be passed to this method, and the handler should discard
     * those that it does not want to handle.
     *
     * The return value of this function controls the bubbling process of the handler stack.
     * Unless the bubbling is interrupted (by returning true), the Logger class will keep on
     * calling further handlers in the stack with a given log record.
     *
     * @inheritDoc
     */
    public function handle(LogRecord $record): bool
    {
        if ($record->level->isLowerThan($this->level)) {
            return \false;
        }
        $level = $record->level->value;
        if (!isset($this->thresholdMap[$level])) {
            $this->thresholdMap[$level] = 0;
        }
        if ($this->thresholdMap[$level] > 0) {
            // The overflow threshold is not yet reached, so we're buffering the record and lowering the threshold by 1
            $this->thresholdMap[$level]--;
            $this->buffer[$level][] = $record;
            return \false === $this->bubble;
        }
        if ($this->thresholdMap[$level] === 0) {
            // This current message is breaking the threshold. Flush the buffer and continue handling the current record
            foreach ($this->buffer[$level] ?? [] as $buffered) {
                $this->handler->handle($buffered);
            }
            $this->thresholdMap[$level]--;
            unset($this->buffer[$level]);
        }
        $this->handler->handle($record);
        return \false === $this->bubble;
    }
    /**
     * @inheritDoc
     */
    public function setFormatter(FormatterInterface $formatter): HandlerInterface
    {
        if ($this->handler instanceof FormattableHandlerInterface) {
            $this->handler->setFormatter($formatter);
            return $this;
        }
        throw new \UnexpectedValueException('The nested handler of type ' . \get_class($this->handler) . ' does not support formatters.');
    }
    /**
     * @inheritDoc
     */
    public function getFormatter(): FormatterInterface
    {
        if ($this->handler instanceof FormattableHandlerInterface) {
            return $this->handler->getFormatter();
        }
        throw new \UnexpectedValueException('The nested handler of type ' . \get_class($this->handler) . ' does not support formatters.');
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Monolog\Handler;

use _ContaoManager\Monolog\ResettableInterface;
use _ContaoManager\Monolog\Formatter\FormatterInterface;
use _ContaoManager\Monolog\LogRecord;
/**
 * This simple wrapper class can be used to extend handlers functionality.
 *
 * Example: A custom filtering that can be applied to any handler.
 *
 * Inherit from this class and override handle() like this:
 *
 *   public function handle(LogRecord $record)
 *   {
 *        if ($record meets certain conditions) {
 *            return false;
 *        }
 *        return $this->handler->handle($record);
 *   }
 *
 * @author Alexey Karapetov <alexey@karapetov.com>
 */
class HandlerWrapper implements HandlerInterface, ProcessableHandlerInterface, FormattableHandlerInterface, ResettableInterface
{
    protected HandlerInterface $handler;
    public function __construct(HandlerInterface $handler)
    {
        $this->handler = $handler;
    }
    /**
     * @inheritDoc
     */
    public function isHandling(LogRecord $record): bool
    {
        return $this->handler->isHandling($record);
    }
    /**
     * @inheritDoc
     */
    public function handle(LogRecord $record): bool
    {
        return $this->handler->handle($record);
    }
    /**
     * @inheritDoc
     */
    public function handleBatch(array $records): void
    {
        $this->handler->handleBatch($records);
    }
    /**
     * @inheritDoc
     */
    public function close(): void
    {
        $this->handler->close();
    }
    /**
     * @inheritDoc
     */
    public function pushProcessor(callable $callback): HandlerInterface
    {
        if ($this->handler instanceof ProcessableHandlerInterface) {
            $this->handler->pushProcessor($callback);
            return $this;
        }
        throw new \LogicException('The wrapped handler does not implement ' . ProcessableHandlerInterface::class);
    }
    /**
     * @inheritDoc
     */
    public function popProcessor(): callable
    {
        if ($this->handler instanceof ProcessableHandlerInterface) {
            return $this->handler->popProcessor();
        }
        throw new \LogicException('The wrapped handler does not implement ' . ProcessableHandlerInterface::class);
    }
    /**
     * @inheritDoc
     */
    public function setFormatter(FormatterInterface $formatter): HandlerInterface
    {
        if ($this->handler instanceof FormattableHandlerInterface) {
            $this->handler->setFormatter($formatter);
            return $this;
        }
        throw new \LogicException('The wrapped handler does not implement ' . FormattableHandlerInterface::class);
    }
    /**
     * @inheritDoc
     */
    public function getFormatter(): FormatterInterface
    {
        if ($this->handler instanceof FormattableHandlerInterface) {
            return $this->handler->getFormatter();
        }
        throw new \LogicException('The wrapped handler does not implement ' . FormattableHandlerInterface::class);
    }
    public function reset(): void
    {
        if ($this->handler instanceof ResettableInterface) {
            $this->handler->reset();
        }
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Monolog\Handler\FingersCrossed;

use _ContaoManager\Monolog\LogRecord;
/**
 * Interface for activation strategies for the FingersCrossedHandler.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
interface ActivationStrategyInterface
{
    /**
     * Returns whether the given record activates the handler.
     */
    public function isHandlerActivated(LogRecord $record): bool;
}
<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Monolog\Handler\FingersCrossed;

use _ContaoManager\Monolog\Level;
use _ContaoManager\Monolog\LogRecord;
use _ContaoManager\Monolog\Logger;
use _ContaoManager\Psr\Log\LogLevel;
/**
 * Error level based activation strategy.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
class ErrorLevelActivationStrategy implements ActivationStrategyInterface
{
    private Level $actionLevel;
    /**
     * @param int|string|Level $actionLevel Level or name or value
     *
     * @phpstan-param value-of<Level::VALUES>|value-of<Level::NAMES>|Level|LogLevel::* $actionLevel
     */
    public function __construct(int|string|Level $actionLevel)
    {
        $this->actionLevel = Logger::toMonologLevel($actionLevel);
    }
    public function isHandlerActivated(LogRecord $record): bool
    {
        return $record->level->value >= $this->actionLevel->value;
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Monolog\Handler\FingersCrossed;

use _ContaoManager\Monolog\Level;
use _ContaoManager\Monolog\Logger;
use _ContaoManager\Psr\Log\LogLevel;
use _ContaoManager\Monolog\LogRecord;
/**
 * Channel and Error level based monolog activation strategy. Allows to trigger activation
 * based on level per channel. e.g. trigger activation on level 'ERROR' by default, except
 * for records of the 'sql' channel; those should trigger activation on level 'WARN'.
 *
 * Example:
 *
 * <code>
 *   $activationStrategy = new ChannelLevelActivationStrategy(
 *       Level::Critical,
 *       array(
 *           'request' => Level::Alert,
 *           'sensitive' => Level::Error,
 *       )
 *   );
 *   $handler = new FingersCrossedHandler(new StreamHandler('php://stderr'), $activationStrategy);
 * </code>
 *
 * @author Mike Meessen <netmikey@gmail.com>
 */
class ChannelLevelActivationStrategy implements ActivationStrategyInterface
{
    private Level $defaultActionLevel;
    /**
     * @var array<string, Level>
     */
    private array $channelToActionLevel;
    /**
     * @param int|string|Level|LogLevel::*                $defaultActionLevel   The default action level to be used if the record's category doesn't match any
     * @param array<string, int|string|Level|LogLevel::*> $channelToActionLevel An array that maps channel names to action levels.
     *
     * @phpstan-param value-of<Level::VALUES>|value-of<Level::NAMES>|Level|LogLevel::* $defaultActionLevel
     * @phpstan-param array<string, value-of<Level::VALUES>|value-of<Level::NAMES>|Level|LogLevel::*> $channelToActionLevel
     */
    public function __construct(int|string|Level $defaultActionLevel, array $channelToActionLevel = [])
    {
        $this->defaultActionLevel = Logger::toMonologLevel($defaultActionLevel);
        $this->channelToActionLevel = array_map(Logger::toMonologLevel(...), $channelToActionLevel);
    }
    public function isHandlerActivated(LogRecord $record): bool
    {
        if (isset($this->channelToActionLevel[$record->channel])) {
            return $record->level->value >= $this->channelToActionLevel[$record->channel]->value;
        }
        return $record->level->value >= $this->defaultActionLevel->value;
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Monolog\Handler;

use _ContaoManager\Monolog\Formatter\FormatterInterface;
use _ContaoManager\Monolog\ResettableInterface;
use _ContaoManager\Monolog\LogRecord;
/**
 * Forwards records to multiple handlers
 *
 * @author Lenar Lõhmus <lenar@city.ee>
 */
class GroupHandler extends Handler implements ProcessableHandlerInterface, ResettableInterface
{
    use ProcessableHandlerTrait;
    /** @var HandlerInterface[] */
    protected array $handlers;
    protected bool $bubble;
    /**
     * @param HandlerInterface[] $handlers Array of Handlers.
     * @param bool               $bubble   Whether the messages that are handled can bubble up the stack or not
     *
     * @throws \InvalidArgumentException if an unsupported handler is set
     */
    public function __construct(array $handlers, bool $bubble = \true)
    {
        foreach ($handlers as $handler) {
            if (!$handler instanceof HandlerInterface) {
                throw new \InvalidArgumentException('The first argument of the GroupHandler must be an array of HandlerInterface instances.');
            }
        }
        $this->handlers = $handlers;
        $this->bubble = $bubble;
    }
    /**
     * @inheritDoc
     */
    public function isHandling(LogRecord $record): bool
    {
        foreach ($this->handlers as $handler) {
            if ($handler->isHandling($record)) {
                return \true;
            }
        }
        return \false;
    }
    /**
     * @inheritDoc
     */
    public function handle(LogRecord $record): bool
    {
        if (\count($this->processors) > 0) {
            $record = $this->processRecord($record);
        }
        foreach ($this->handlers as $handler) {
            $handler->handle(clone $record);
        }
        return \false === $this->bubble;
    }
    /**
     * @inheritDoc
     */
    public function handleBatch(array $records): void
    {
        if (\count($this->processors) > 0) {
            $processed = [];
            foreach ($records as $record) {
                $processed[] = $this->processRecord($record);
            }
            $records = $processed;
        }
        foreach ($this->handlers as $handler) {
            $handler->handleBatch(array_map(fn($record) => clone $record, $records));
        }
    }
    public function reset(): void
    {
        $this->resetProcessors();
        foreach ($this->handlers as $handler) {
            if ($handler instanceof ResettableInterface) {
                $handler->reset();
            }
        }
    }
    public function close(): void
    {
        parent::close();
        foreach ($this->handlers as $handler) {
            $handler->close();
        }
    }
    /**
     * @inheritDoc
     */
    public function setFormatter(FormatterInterface $formatter): HandlerInterface
    {
        foreach ($this->handlers as $handler) {
            if ($handler instanceof FormattableHandlerInterface) {
                $handler->setFormatter($formatter);
            }
        }
        return $this;
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Monolog\Handler;

use _ContaoManager\Elastic\Elasticsearch\Response\Elasticsearch;
use Throwable;
use RuntimeException;
use _ContaoManager\Monolog\Level;
use _ContaoManager\Monolog\Formatter\FormatterInterface;
use _ContaoManager\Monolog\Formatter\ElasticsearchFormatter;
use InvalidArgumentException;
use _ContaoManager\Elasticsearch\Common\Exceptions\RuntimeException as ElasticsearchRuntimeException;
use _ContaoManager\Elasticsearch\Client;
use _ContaoManager\Monolog\LogRecord;
use _ContaoManager\Elastic\Elasticsearch\Exception\InvalidArgumentException as ElasticInvalidArgumentException;
use _ContaoManager\Elastic\Elasticsearch\Client as Client8;
/**
 * Elasticsearch handler
 *
 * @link https://www.elastic.co/guide/en/elasticsearch/client/php-api/current/index.html
 *
 * Simple usage example:
 *
 *    $client = \Elasticsearch\ClientBuilder::create()
 *        ->setHosts($hosts)
 *        ->build();
 *
 *    $options = array(
 *        'index' => 'elastic_index_name',
 *        'type'  => 'elastic_doc_type',
 *    );
 *    $handler = new ElasticsearchHandler($client, $options);
 *    $log = new Logger('application');
 *    $log->pushHandler($handler);
 *
 * @author Avtandil Kikabidze <akalongman@gmail.com>
 * @phpstan-type Options array{
 *     index: string,
 *     type: string,
 *     ignore_error: bool,
 *     op_type: 'index'|'create'
 * }
 * @phpstan-type InputOptions array{
 *     index?: string,
 *     type?: string,
 *     ignore_error?: bool,
 *     op_type?: 'index'|'create'
 * }
 */
class ElasticsearchHandler extends AbstractProcessingHandler
{
    protected Client|Client8 $client;
    /**
     * @var mixed[] Handler config options
     * @phpstan-var Options
     */
    protected array $options;
    /**
     * @var bool
     */
    private $needsType;
    /**
     * @param Client|Client8 $client  Elasticsearch Client object
     * @param mixed[]        $options Handler configuration
     *
     * @phpstan-param InputOptions $options
     */
    public function __construct(Client|Client8 $client, array $options = [], int|string|Level $level = Level::Debug, bool $bubble = \true)
    {
        parent::__construct($level, $bubble);
        $this->client = $client;
        $this->options = array_merge([
            'index' => 'monolog',
            // Elastic index name
            'type' => '_doc',
            // Elastic document type
            'ignore_error' => \false,
            // Suppress Elasticsearch exceptions
            'op_type' => 'index',
        ], $options);
        if ($client instanceof Client8 || $client::VERSION[0] === '7') {
            $this->needsType = \false;
            // force the type to _doc for ES8/ES7
            $this->options['type'] = '_doc';
        } else {
            $this->needsType = \true;
        }
    }
    /**
     * @inheritDoc
     */
    protected function write(LogRecord $record): void
    {
        $this->bulkSend([$record->formatted]);
    }
    /**
     * @inheritDoc
     */
    public function setFormatter(FormatterInterface $formatter): HandlerInterface
    {
        if ($formatter instanceof ElasticsearchFormatter) {
            return parent::setFormatter($formatter);
        }
        throw new InvalidArgumentException('ElasticsearchHandler is only compatible with ElasticsearchFormatter');
    }
    /**
     * Getter options
     *
     * @return mixed[]
     *
     * @phpstan-return Options
     */
    public function getOptions(): array
    {
        return $this->options;
    }
    /**
     * @inheritDoc
     */
    protected function getDefaultFormatter(): FormatterInterface
    {
        return new ElasticsearchFormatter($this->options['index'], $this->options['type']);
    }
    /**
     * @inheritDoc
     */
    public function handleBatch(array $records): void
    {
        $documents = $this->getFormatter()->formatBatch($records);
        $this->bulkSend($documents);
    }
    /**
     * Use Elasticsearch bulk API to send list of documents
     *
     * @param  array<array<mixed>> $records Records + _index/_type keys
     * @throws \RuntimeException
     */
    protected function bulkSend(array $records): void
    {
        try {
            $params = ['body' => []];
            foreach ($records as $record) {
                $params['body'][] = [$this->options['op_type'] => $this->needsType ? ['_index' => $record['_index'], '_type' => $record['_type']] : ['_index' => $record['_index']]];
                unset($record['_index'], $record['_type']);
                $params['body'][] = $record;
            }
            /** @var Elasticsearch */
            $responses = $this->client->bulk($params);
            if ($responses['errors'] === \true) {
                throw $this->createExceptionFromResponses($responses);
            }
        } catch (Throwable $e) {
            if (!$this->options['ignore_error']) {
                throw new RuntimeException('Error sending messages to Elasticsearch', 0, $e);
            }
        }
    }
    /**
     * Creates elasticsearch exception from responses array
     *
     * Only the first error is converted into an exception.
     *
     * @param mixed[]|Elasticsearch $responses returned by $this->client->bulk()
     */
    protected function createExceptionFromResponses($responses): Throwable
    {
        foreach ($responses['items'] ?? [] as $item) {
            if (isset($item['index']['error'])) {
                return $this->createExceptionFromError($item['index']['error']);
            }
        }
        if (class_exists(ElasticInvalidArgumentException::class)) {
            return new ElasticInvalidArgumentException('Elasticsearch failed to index one or more records.');
        }
        if (class_exists(ElasticsearchRuntimeException::class)) {
            return new ElasticsearchRuntimeException('Elasticsearch failed to index one or more records.');
        }
        throw new \LogicException('Unsupported elastic search client version');
    }
    /**
     * Creates elasticsearch exception from error array
     *
     * @param mixed[] $error
     */
    protected function createExceptionFromError(array $error): Throwable
    {
        $previous = isset($error['caused_by']) ? $this->createExceptionFromError($error['caused_by']) : null;
        if (class_exists(ElasticInvalidArgumentException::class)) {
            return new ElasticInvalidArgumentException($error['type'] . ': ' . $error['reason'], 0, $previous);
        }
        if (class_exists(ElasticsearchRuntimeException::class)) {
            return new ElasticsearchRuntimeException($error['type'] . ': ' . $error['reason'], 0, $previous);
        }
        throw new \LogicException('Unsupported elastic search client version');
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Monolog\Handler;

use Closure;
use _ContaoManager\Monolog\Formatter\FormatterInterface;
use _ContaoManager\Monolog\LogRecord;
/**
 * Sampling handler
 *
 * A sampled event stream can be useful for logging high frequency events in
 * a production environment where you only need an idea of what is happening
 * and are not concerned with capturing every occurrence. Since the decision to
 * handle or not handle a particular event is determined randomly, the
 * resulting sampled log is not guaranteed to contain 1/N of the events that
 * occurred in the application, but based on the Law of large numbers, it will
 * tend to be close to this ratio with a large number of attempts.
 *
 * @author Bryan Davis <bd808@wikimedia.org>
 * @author Kunal Mehta <legoktm@gmail.com>
 */
class SamplingHandler extends AbstractHandler implements ProcessableHandlerInterface, FormattableHandlerInterface
{
    use ProcessableHandlerTrait;
    /**
     * Handler or factory Closure($record, $this)
     *
     * @phpstan-var (Closure(LogRecord|null, HandlerInterface): HandlerInterface)|HandlerInterface
     */
    protected Closure|HandlerInterface $handler;
    protected int $factor;
    /**
     * @phpstan-param (Closure(LogRecord|null, HandlerInterface): HandlerInterface)|HandlerInterface $handler
     *
     * @param Closure|HandlerInterface $handler Handler or factory Closure($record|null, $samplingHandler).
     * @param int                      $factor  Sample factor (e.g. 10 means every ~10th record is sampled)
     */
    public function __construct(Closure|HandlerInterface $handler, int $factor)
    {
        parent::__construct();
        $this->handler = $handler;
        $this->factor = $factor;
    }
    public function isHandling(LogRecord $record): bool
    {
        return $this->getHandler($record)->isHandling($record);
    }
    public function handle(LogRecord $record): bool
    {
        if ($this->isHandling($record) && mt_rand(1, $this->factor) === 1) {
            if (\count($this->processors) > 0) {
                $record = $this->processRecord($record);
            }
            $this->getHandler($record)->handle($record);
        }
        return \false === $this->bubble;
    }
    /**
     * Return the nested handler
     *
     * If the handler was provided as a factory, this will trigger the handler's instantiation.
     */
    public function getHandler(LogRecord|null $record = null): HandlerInterface
    {
        if (!$this->handler instanceof HandlerInterface) {
            $handler = ($this->handler)($record, $this);
            if (!$handler instanceof HandlerInterface) {
                throw new \RuntimeException("The factory Closure should return a HandlerInterface");
            }
            $this->handler = $handler;
        }
        return $this->handler;
    }
    /**
     * @inheritDoc
     */
    public function setFormatter(FormatterInterface $formatter): HandlerInterface
    {
        $handler = $this->getHandler();
        if ($handler instanceof FormattableHandlerInterface) {
            $handler->setFormatter($formatter);
            return $this;
        }
        throw new \UnexpectedValueException('The nested handler of type ' . \get_class($handler) . ' does not support formatters.');
    }
    /**
     * @inheritDoc
     */
    public function getFormatter(): FormatterInterface
    {
        $handler = $this->getHandler();
        if ($handler instanceof FormattableHandlerInterface) {
            return $handler->getFormatter();
        }
        throw new \UnexpectedValueException('The nested handler of type ' . \get_class($handler) . ' does not support formatters.');
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Monolog\Handler;

/**
 * Base Handler class providing basic close() support as well as handleBatch
 *
 * @author Jordi Boggiano <j.boggiano@seld.be>
 */
abstract class Handler implements HandlerInterface
{
    /**
     * @inheritDoc
     */
    public function handleBatch(array $records): void
    {
        foreach ($records as $record) {
            $this->handle($record);
        }
    }
    /**
     * @inheritDoc
     */
    public function close(): void
    {
    }
    public function __destruct()
    {
        try {
            $this->close();
        } catch (\Throwable $e) {
            // do nothing
        }
    }
    public function __serialize(): array
    {
        $this->close();
        return (array) $this;
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Monolog\Handler;

use _ContaoManager\Monolog\Level;
use _ContaoManager\Monolog\Logger;
use _ContaoManager\Monolog\ResettableInterface;
use _ContaoManager\Psr\Log\LogLevel;
use _ContaoManager\Monolog\LogRecord;
/**
 * Base Handler class providing basic level/bubble support
 *
 * @author Jordi Boggiano <j.boggiano@seld.be>
 */
abstract class AbstractHandler extends Handler implements ResettableInterface
{
    protected Level $level = Level::Debug;
    protected bool $bubble = \true;
    /**
     * @param int|string|Level|LogLevel::* $level  The minimum logging level at which this handler will be triggered
     * @param bool                         $bubble Whether the messages that are handled can bubble up the stack or not
     *
     * @phpstan-param value-of<Level::VALUES>|value-of<Level::NAMES>|Level|LogLevel::* $level
     */
    public function __construct(int|string|Level $level = Level::Debug, bool $bubble = \true)
    {
        $this->setLevel($level);
        $this->bubble = $bubble;
    }
    /**
     * @inheritDoc
     */
    public function isHandling(LogRecord $record): bool
    {
        return $record->level->value >= $this->level->value;
    }
    /**
     * Sets minimum logging level at which this handler will be triggered.
     *
     * @param  Level|LogLevel::* $level Level or level name
     * @return $this
     *
     * @phpstan-param value-of<Level::VALUES>|value-of<Level::NAMES>|Level|LogLevel::* $level
     */
    public function setLevel(int|string|Level $level): self
    {
        $this->level = Logger::toMonologLevel($level);
        return $this;
    }
    /**
     * Gets minimum logging level at which this handler will be triggered.
     */
    public function getLevel(): Level
    {
        return $this->level;
    }
    /**
     * Sets the bubbling behavior.
     *
     * @param  bool  $bubble true means that this handler allows bubbling.
     *                       false means that bubbling is not permitted.
     * @return $this
     */
    public function setBubble(bool $bubble): self
    {
        $this->bubble = $bubble;
        return $this;
    }
    /**
     * Gets the bubbling behavior.
     *
     * @return bool true means that this handler allows bubbling.
     *              false means that bubbling is not permitted.
     */
    public function getBubble(): bool
    {
        return $this->bubble;
    }
    /**
     * @inheritDoc
     */
    public function reset(): void
    {
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Monolog\Handler;

use _ContaoManager\Monolog\Level;
use _ContaoManager\Monolog\Utils;
use _ContaoManager\Monolog\Formatter\FlowdockFormatter;
use _ContaoManager\Monolog\Formatter\FormatterInterface;
use _ContaoManager\Monolog\LogRecord;
/**
 * Sends notifications through the Flowdock push API
 *
 * This must be configured with a FlowdockFormatter instance via setFormatter()
 *
 * Notes:
 * API token - Flowdock API token
 *
 * @author Dominik Liebler <liebler.dominik@gmail.com>
 * @see https://www.flowdock.com/api/push
 * @deprecated Since 2.9.0 and 3.3.0, Flowdock was shutdown we will thus drop this handler in Monolog 4
 */
class FlowdockHandler extends SocketHandler
{
    protected string $apiToken;
    /**
     * @throws MissingExtensionException if OpenSSL is missing
     */
    public function __construct(string $apiToken, $level = Level::Debug, bool $bubble = \true, bool $persistent = \false, float $timeout = 0.0, float $writingTimeout = 10.0, ?float $connectionTimeout = null, ?int $chunkSize = null)
    {
        if (!\extension_loaded('openssl')) {
            throw new MissingExtensionException('The OpenSSL PHP extension is required to use the FlowdockHandler');
        }
        parent::__construct('ssl://api.flowdock.com:443', $level, $bubble, $persistent, $timeout, $writingTimeout, $connectionTimeout, $chunkSize);
        $this->apiToken = $apiToken;
    }
    /**
     * @inheritDoc
     */
    public function setFormatter(FormatterInterface $formatter): HandlerInterface
    {
        if (!$formatter instanceof FlowdockFormatter) {
            throw new \InvalidArgumentException('The FlowdockHandler requires an instance of Monolog\Formatter\FlowdockFormatter to function correctly');
        }
        return parent::setFormatter($formatter);
    }
    /**
     * Gets the default formatter.
     */
    protected function getDefaultFormatter(): FormatterInterface
    {
        throw new \InvalidArgumentException('The FlowdockHandler must be configured (via setFormatter) with an instance of Monolog\Formatter\FlowdockFormatter to function correctly');
    }
    /**
     * @inheritDoc
     */
    protected function write(LogRecord $record): void
    {
        parent::write($record);
        $this->closeSocket();
    }
    /**
     * @inheritDoc
     */
    protected function generateDataStream(LogRecord $record): string
    {
        $content = $this->buildContent($record);
        return $this->buildHeader($content) . $content;
    }
    /**
     * Builds the body of API call
     */
    private function buildContent(LogRecord $record): string
    {
        return Utils::jsonEncode($record->formatted);
    }
    /**
     * Builds the header of the API Call
     */
    private function buildHeader(string $content): string
    {
        $header = "POST /v1/messages/team_inbox/" . $this->apiToken . " HTTP/1.1\r\n";
        $header .= "Host: api.flowdock.com\r\n";
        $header .= "Content-Type: application/json\r\n";
        $header .= "Content-Length: " . \strlen($content) . "\r\n";
        $header .= "\r\n";
        return $header;
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Monolog\Handler;

use _ContaoManager\Monolog\Level;
use _ContaoManager\Monolog\Logger;
use _ContaoManager\Monolog\Utils;
use _ContaoManager\Psr\Log\LogLevel;
use _ContaoManager\Monolog\LogRecord;
/**
 * Sends notifications through the pushover api to mobile phones
 *
 * @author Sebastian Göttschkes <sebastian.goettschkes@googlemail.com>
 * @see    https://www.pushover.net/api
 */
class PushoverHandler extends SocketHandler
{
    private string $token;
    /** @var array<int|string> */
    private array $users;
    private string $title;
    private string|int|null $user = null;
    private int $retry;
    private int $expire;
    private Level $highPriorityLevel;
    private Level $emergencyLevel;
    private bool $useFormattedMessage = \false;
    /**
     * All parameters that can be sent to Pushover
     * @see https://pushover.net/api
     * @var array<string, bool>
     */
    private array $parameterNames = ['token' => \true, 'user' => \true, 'message' => \true, 'device' => \true, 'title' => \true, 'url' => \true, 'url_title' => \true, 'priority' => \true, 'timestamp' => \true, 'sound' => \true, 'retry' => \true, 'expire' => \true, 'callback' => \true];
    /**
     * Sounds the api supports by default
     * @see https://pushover.net/api#sounds
     * @var string[]
     */
    private array $sounds = ['pushover', 'bike', 'bugle', 'cashregister', 'classical', 'cosmic', 'falling', 'gamelan', 'incoming', 'intermission', 'magic', 'mechanical', 'pianobar', 'siren', 'spacealarm', 'tugboat', 'alien', 'climb', 'persistent', 'echo', 'updown', 'none'];
    /**
     * @param string       $token  Pushover api token
     * @param string|array $users  Pushover user id or array of ids the message will be sent to
     * @param string|null  $title  Title sent to the Pushover API
     * @param bool         $useSSL Whether to connect via SSL. Required when pushing messages to users that are not
     *                             the pushover.net app owner. OpenSSL is required for this option.
     * @param int          $retry  The retry parameter specifies how often (in seconds) the Pushover servers will
     *                             send the same notification to the user.
     * @param int          $expire The expire parameter specifies how many seconds your notification will continue
     *                             to be retried for (every retry seconds).
     *
     * @param int|string|Level|LogLevel::* $highPriorityLevel The minimum logging level at which this handler will start
     *                                                        sending "high priority" requests to the Pushover API
     * @param int|string|Level|LogLevel::* $emergencyLevel    The minimum logging level at which this handler will start
     *                                                        sending "emergency" requests to the Pushover API
     *
     *
     * @phpstan-param string|array<int|string>    $users
     * @phpstan-param value-of<Level::VALUES>|value-of<Level::NAMES>|Level|LogLevel::* $highPriorityLevel
     * @phpstan-param value-of<Level::VALUES>|value-of<Level::NAMES>|Level|LogLevel::* $emergencyLevel
     */
    public function __construct(string $token, $users, ?string $title = null, int|string|Level $level = Level::Critical, bool $bubble = \true, bool $useSSL = \true, int|string|Level $highPriorityLevel = Level::Critical, int|string|Level $emergencyLevel = Level::Emergency, int $retry = 30, int $expire = 25200, bool $persistent = \false, float $timeout = 0.0, float $writingTimeout = 10.0, ?float $connectionTimeout = null, ?int $chunkSize = null)
    {
        $connectionString = $useSSL ? 'ssl://api.pushover.net:443' : 'api.pushover.net:80';
        parent::__construct($connectionString, $level, $bubble, $persistent, $timeout, $writingTimeout, $connectionTimeout, $chunkSize);
        $this->token = $token;
        $this->users = (array) $users;
        $this->title = $title ?? (string) gethostname();
        $this->highPriorityLevel = Logger::toMonologLevel($highPriorityLevel);
        $this->emergencyLevel = Logger::toMonologLevel($emergencyLevel);
        $this->retry = $retry;
        $this->expire = $expire;
    }
    protected function generateDataStream(LogRecord $record): string
    {
        $content = $this->buildContent($record);
        return $this->buildHeader($content) . $content;
    }
    private function buildContent(LogRecord $record): string
    {
        // Pushover has a limit of 512 characters on title and message combined.
        $maxMessageLength = 512 - \strlen($this->title);
        $message = $this->useFormattedMessage ? $record->formatted : $record->message;
        $message = Utils::substr($message, 0, $maxMessageLength);
        $timestamp = $record->datetime->getTimestamp();
        $dataArray = ['token' => $this->token, 'user' => $this->user, 'message' => $message, 'title' => $this->title, 'timestamp' => $timestamp];
        if ($record->level->value >= $this->emergencyLevel->value) {
            $dataArray['priority'] = 2;
            $dataArray['retry'] = $this->retry;
            $dataArray['expire'] = $this->expire;
        } elseif ($record->level->value >= $this->highPriorityLevel->value) {
            $dataArray['priority'] = 1;
        }
        // First determine the available parameters
        $context = array_intersect_key($record->context, $this->parameterNames);
        $extra = array_intersect_key($record->extra, $this->parameterNames);
        // Least important info should be merged with subsequent info
        $dataArray = array_merge($extra, $context, $dataArray);
        // Only pass sounds that are supported by the API
        if (isset($dataArray['sound']) && !\in_array($dataArray['sound'], $this->sounds, \true)) {
            unset($dataArray['sound']);
        }
        return http_build_query($dataArray);
    }
    private function buildHeader(string $content): string
    {
        $header = "POST /1/messages.json HTTP/1.1\r\n";
        $header .= "Host: api.pushover.net\r\n";
        $header .= "Content-Type: application/x-www-form-urlencoded\r\n";
        $header .= "Content-Length: " . \strlen($content) . "\r\n";
        $header .= "\r\n";
        return $header;
    }
    protected function write(LogRecord $record): void
    {
        foreach ($this->users as $user) {
            $this->user = $user;
            parent::write($record);
            $this->closeSocket();
        }
        $this->user = null;
    }
    /**
     * @param  int|string|Level|LogLevel::* $level
     * @return $this
     *
     * @phpstan-param value-of<Level::VALUES>|value-of<Level::NAMES>|Level|LogLevel::* $level
     */
    public function setHighPriorityLevel(int|string|Level $level): self
    {
        $this->highPriorityLevel = Logger::toMonologLevel($level);
        return $this;
    }
    /**
     * @param  int|string|Level|LogLevel::* $level
     * @return $this
     *
     * @phpstan-param value-of<Level::VALUES>|value-of<Level::NAMES>|Level|LogLevel::* $level
     */
    public function setEmergencyLevel(int|string|Level $level): self
    {
        $this->emergencyLevel = Logger::toMonologLevel($level);
        return $this;
    }
    /**
     * Use the formatted message?
     *
     * @return $this
     */
    public function useFormattedMessage(bool $useFormattedMessage): self
    {
        $this->useFormattedMessage = $useFormattedMessage;
        return $this;
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Monolog\Handler;

use _ContaoManager\Monolog\Processor\ProcessorInterface;
use _ContaoManager\Monolog\LogRecord;
/**
 * Interface to describe loggers that have processors
 *
 * @author Jordi Boggiano <j.boggiano@seld.be>
 */
interface ProcessableHandlerInterface
{
    /**
     * Adds a processor in the stack.
     *
     * @phpstan-param ProcessorInterface|(callable(LogRecord): LogRecord) $callback
     *
     * @param  ProcessorInterface|callable $callback
     * @return HandlerInterface            self
     */
    public function pushProcessor(callable $callback): HandlerInterface;
    /**
     * Removes the processor on top of the stack and returns it.
     *
     * @phpstan-return ProcessorInterface|(callable(LogRecord): LogRecord) $callback
     *
     * @throws \LogicException             In case the processor stack is empty
     * @return callable|ProcessorInterface
     */
    public function popProcessor(): callable;
}
<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Monolog\Handler;

/**
 * Exception can be thrown if an extension for a handler is missing
 *
 * @author Christian Bergau <cbergau86@gmail.com>
 */
class MissingExtensionException extends \Exception
{
}
<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Monolog\Handler;

use _ContaoManager\Monolog\Level;
use _ContaoManager\Monolog\Formatter\FormatterInterface;
use _ContaoManager\Monolog\Formatter\LineFormatter;
/**
 * Common syslog functionality
 */
abstract class AbstractSyslogHandler extends AbstractProcessingHandler
{
    protected int $facility;
    /**
     * List of valid log facility names.
     * @var array<string, int>
     */
    protected array $facilities = ['auth' => \LOG_AUTH, 'authpriv' => \LOG_AUTHPRIV, 'cron' => \LOG_CRON, 'daemon' => \LOG_DAEMON, 'kern' => \LOG_KERN, 'lpr' => \LOG_LPR, 'mail' => \LOG_MAIL, 'news' => \LOG_NEWS, 'syslog' => \LOG_SYSLOG, 'user' => \LOG_USER, 'uucp' => \LOG_UUCP];
    /**
     * Translates Monolog log levels to syslog log priorities.
     */
    protected function toSyslogPriority(Level $level): int
    {
        return $level->toRFC5424Level();
    }
    /**
     * @param string|int $facility Either one of the names of the keys in $this->facilities, or a LOG_* facility constant
     */
    public function __construct(string|int $facility = \LOG_USER, int|string|Level $level = Level::Debug, bool $bubble = \true)
    {
        parent::__construct($level, $bubble);
        if (!\defined('PHP_WINDOWS_VERSION_BUILD')) {
            $this->facilities['local0'] = \LOG_LOCAL0;
            $this->facilities['local1'] = \LOG_LOCAL1;
            $this->facilities['local2'] = \LOG_LOCAL2;
            $this->facilities['local3'] = \LOG_LOCAL3;
            $this->facilities['local4'] = \LOG_LOCAL4;
            $this->facilities['local5'] = \LOG_LOCAL5;
            $this->facilities['local6'] = \LOG_LOCAL6;
            $this->facilities['local7'] = \LOG_LOCAL7;
        } else {
            $this->facilities['local0'] = 128;
            // LOG_LOCAL0
            $this->facilities['local1'] = 136;
            // LOG_LOCAL1
            $this->facilities['local2'] = 144;
            // LOG_LOCAL2
            $this->facilities['local3'] = 152;
            // LOG_LOCAL3
            $this->facilities['local4'] = 160;
            // LOG_LOCAL4
            $this->facilities['local5'] = 168;
            // LOG_LOCAL5
            $this->facilities['local6'] = 176;
            // LOG_LOCAL6
            $this->facilities['local7'] = 184;
            // LOG_LOCAL7
        }
        // convert textual description of facility to syslog constant
        if (\is_string($facility) && \array_key_exists(strtolower($facility), $this->facilities)) {
            $facility = $this->facilities[strtolower($facility)];
        } elseif (!\in_array($facility, array_values($this->facilities), \true)) {
            throw new \UnexpectedValueException('Unknown facility value "' . $facility . '" given');
        }
        $this->facility = $facility;
    }
    /**
     * @inheritDoc
     */
    protected function getDefaultFormatter(): FormatterInterface
    {
        return new LineFormatter('%channel%.%level_name%: %message% %context% %extra%');
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Monolog\Handler;

use DateTimeInterface;
use _ContaoManager\Monolog\Handler\SyslogUdp\UdpSocket;
use _ContaoManager\Monolog\Level;
use _ContaoManager\Monolog\LogRecord;
use _ContaoManager\Monolog\Utils;
/**
 * A Handler for logging to a remote syslogd server.
 *
 * @author Jesper Skovgaard Nielsen <nulpunkt@gmail.com>
 * @author Dominik Kukacka <dominik.kukacka@gmail.com>
 */
class SyslogUdpHandler extends AbstractSyslogHandler
{
    const RFC3164 = 0;
    const RFC5424 = 1;
    const RFC5424e = 2;
    /** @var array<self::RFC*, string> */
    private array $dateFormats = [self::RFC3164 => 'M d H:i:s', self::RFC5424 => \DateTime::RFC3339, self::RFC5424e => \DateTime::RFC3339_EXTENDED];
    protected UdpSocket $socket;
    protected string $ident;
    /** @var self::RFC* */
    protected int $rfc;
    /**
     * @param  string                    $host     Either IP/hostname or a path to a unix socket (port must be 0 then)
     * @param  int                       $port     Port number, or 0 if $host is a unix socket
     * @param  string|int                $facility Either one of the names of the keys in $this->facilities, or a LOG_* facility constant
     * @param  bool                      $bubble   Whether the messages that are handled can bubble up the stack or not
     * @param  string                    $ident    Program name or tag for each log message.
     * @param  int                       $rfc      RFC to format the message for.
     * @throws MissingExtensionException when there is no socket extension
     *
     * @phpstan-param self::RFC* $rfc
     */
    public function __construct(string $host, int $port = 514, string|int $facility = \LOG_USER, int|string|Level $level = Level::Debug, bool $bubble = \true, string $ident = 'php', int $rfc = self::RFC5424)
    {
        if (!\extension_loaded('sockets')) {
            throw new MissingExtensionException('The sockets extension is required to use the SyslogUdpHandler');
        }
        parent::__construct($facility, $level, $bubble);
        $this->ident = $ident;
        $this->rfc = $rfc;
        $this->socket = new UdpSocket($host, $port);
    }
    protected function write(LogRecord $record): void
    {
        $lines = $this->splitMessageIntoLines($record->formatted);
        $header = $this->makeCommonSyslogHeader($this->toSyslogPriority($record->level), $record->datetime);
        foreach ($lines as $line) {
            $this->socket->write($line, $header);
        }
    }
    public function close(): void
    {
        $this->socket->close();
    }
    /**
     * @param  string|string[] $message
     * @return string[]
     */
    private function splitMessageIntoLines($message): array
    {
        if (\is_array($message)) {
            $message = implode("\n", $message);
        }
        $lines = preg_split('/$\R?^/m', (string) $message, -1, \PREG_SPLIT_NO_EMPTY);
        if (\false === $lines) {
            $pcreErrorCode = preg_last_error();
            throw new \RuntimeException('Could not preg_split: ' . $pcreErrorCode . ' / ' . preg_last_error_msg());
        }
        return $lines;
    }
    /**
     * Make common syslog header (see rfc5424 or rfc3164)
     */
    protected function makeCommonSyslogHeader(int $severity, DateTimeInterface $datetime): string
    {
        $priority = $severity + $this->facility;
        $pid = getmypid();
        if (\false === $pid) {
            $pid = '-';
        }
        $hostname = gethostname();
        if (\false === $hostname) {
            $hostname = '-';
        }
        if ($this->rfc === self::RFC3164) {
            // see https://github.com/phpstan/phpstan/issues/5348
            // @phpstan-ignore-next-line
            $dateNew = $datetime->setTimezone(new \DateTimeZone('UTC'));
            $date = $dateNew->format($this->dateFormats[$this->rfc]);
            return "<{$priority}>" . $date . " " . $hostname . " " . $this->ident . "[" . $pid . "]: ";
        }
        $date = $datetime->format($this->dateFormats[$this->rfc]);
        return "<{$priority}>1 " . $date . " " . $hostname . " " . $this->ident . " " . $pid . " - - ";
    }
    /**
     * Inject your own socket, mainly used for testing
     *
     * @return $this
     */
    public function setSocket(UdpSocket $socket): self
    {
        $this->socket = $socket;
        return $this;
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Monolog\Handler;

use _ContaoManager\Monolog\Formatter\FormatterInterface;
use _ContaoManager\Monolog\Formatter\LineFormatter;
use _ContaoManager\Monolog\Utils;
use _ContaoManager\Monolog\LogRecord;
use _ContaoManager\Monolog\Level;
use function headers_list;
use function stripos;
/**
 * Handler sending logs to browser's javascript console with no browser extension required
 *
 * @author Olivier Poitrey <rs@dailymotion.com>
 */
class BrowserConsoleHandler extends AbstractProcessingHandler
{
    protected static bool $initialized = \false;
    /** @var LogRecord[] */
    protected static array $records = [];
    protected const FORMAT_HTML = 'html';
    protected const FORMAT_JS = 'js';
    protected const FORMAT_UNKNOWN = 'unknown';
    /**
     * @inheritDoc
     *
     * Formatted output may contain some formatting markers to be transferred to `console.log` using the %c format.
     *
     * Example of formatted string:
     *
     *     You can do [[blue text]]{color: blue} or [[green background]]{background-color: green; color: white}
     */
    protected function getDefaultFormatter(): FormatterInterface
    {
        return new LineFormatter('[[%channel%]]{macro: autolabel} [[%level_name%]]{font-weight: bold} %message%');
    }
    /**
     * @inheritDoc
     */
    protected function write(LogRecord $record): void
    {
        // Accumulate records
        static::$records[] = $record;
        // Register shutdown handler if not already done
        if (!static::$initialized) {
            static::$initialized = \true;
            $this->registerShutdownFunction();
        }
    }
    /**
     * Convert records to javascript console commands and send it to the browser.
     * This method is automatically called on PHP shutdown if output is HTML or Javascript.
     */
    public static function send(): void
    {
        $format = static::getResponseFormat();
        if ($format === self::FORMAT_UNKNOWN) {
            return;
        }
        if (\count(static::$records) > 0) {
            if ($format === self::FORMAT_HTML) {
                static::writeOutput('<script>' . self::generateScript() . '</script>');
            } else {
                // js format
                static::writeOutput(self::generateScript());
            }
            static::resetStatic();
        }
    }
    public function close(): void
    {
        self::resetStatic();
    }
    public function reset(): void
    {
        parent::reset();
        self::resetStatic();
    }
    /**
     * Forget all logged records
     */
    public static function resetStatic(): void
    {
        static::$records = [];
    }
    /**
     * Wrapper for register_shutdown_function to allow overriding
     */
    protected function registerShutdownFunction(): void
    {
        if (\PHP_SAPI !== 'cli') {
            register_shutdown_function(['Monolog\Handler\BrowserConsoleHandler', 'send']);
        }
    }
    /**
     * Wrapper for echo to allow overriding
     */
    protected static function writeOutput(string $str): void
    {
        echo $str;
    }
    /**
     * Checks the format of the response
     *
     * If Content-Type is set to application/javascript or text/javascript -> js
     * If Content-Type is set to text/html, or is unset -> html
     * If Content-Type is anything else -> unknown
     *
     * @return string One of 'js', 'html' or 'unknown'
     * @phpstan-return self::FORMAT_*
     */
    protected static function getResponseFormat(): string
    {
        // Check content type
        foreach (headers_list() as $header) {
            if (stripos($header, 'content-type:') === 0) {
                return static::getResponseFormatFromContentType($header);
            }
        }
        return self::FORMAT_HTML;
    }
    /**
     * @return string One of 'js', 'html' or 'unknown'
     * @phpstan-return self::FORMAT_*
     */
    protected static function getResponseFormatFromContentType(string $contentType): string
    {
        // This handler only works with HTML and javascript outputs
        // text/javascript is obsolete in favour of application/javascript, but still used
        if (stripos($contentType, 'application/javascript') !== \false || stripos($contentType, 'text/javascript') !== \false) {
            return self::FORMAT_JS;
        }
        if (stripos($contentType, 'text/html') !== \false) {
            return self::FORMAT_HTML;
        }
        return self::FORMAT_UNKNOWN;
    }
    private static function generateScript(): string
    {
        $script = [];
        foreach (static::$records as $record) {
            $context = self::dump('Context', $record->context);
            $extra = self::dump('Extra', $record->extra);
            if (\count($context) === 0 && \count($extra) === 0) {
                $script[] = self::call_array(self::getConsoleMethodForLevel($record->level), self::handleStyles($record->formatted));
            } else {
                $script = array_merge($script, [self::call_array('groupCollapsed', self::handleStyles($record->formatted))], $context, $extra, [self::call('groupEnd')]);
            }
        }
        return "(function (c) {if (c && c.groupCollapsed) {\n" . implode("\n", $script) . "\n}})(console);";
    }
    private static function getConsoleMethodForLevel(Level $level): string
    {
        return match ($level) {
            Level::Debug => 'debug',
            Level::Info, Level::Notice => 'info',
            Level::Warning => 'warn',
            Level::Error, Level::Critical, Level::Alert, Level::Emergency => 'error',
        };
    }
    /**
     * @return string[]
     */
    private static function handleStyles(string $formatted): array
    {
        $args = [];
        $format = '%c' . $formatted;
        preg_match_all('/\[\[(.*?)\]\]\{([^}]*)\}/s', $format, $matches, \PREG_OFFSET_CAPTURE | \PREG_SET_ORDER);
        foreach (array_reverse($matches) as $match) {
            $args[] = '"font-weight: normal"';
            $args[] = self::quote(self::handleCustomStyles($match[2][0], $match[1][0]));
            $pos = $match[0][1];
            $format = Utils::substr($format, 0, $pos) . '%c' . $match[1][0] . '%c' . Utils::substr($format, $pos + \strlen($match[0][0]));
        }
        $args[] = self::quote('font-weight: normal');
        $args[] = self::quote($format);
        return array_reverse($args);
    }
    private static function handleCustomStyles(string $style, string $string): string
    {
        static $colors = ['blue', 'green', 'red', 'magenta', 'orange', 'black', 'grey'];
        static $labels = [];
        $style = preg_replace_callback('/macro\s*:(.*?)(?:;|$)/', function (array $m) use ($string, &$colors, &$labels) {
            if (trim($m[1]) === 'autolabel') {
                // Format the string as a label with consistent auto assigned background color
                if (!isset($labels[$string])) {
                    $labels[$string] = $colors[\count($labels) % \count($colors)];
                }
                $color = $labels[$string];
                return "background-color: {$color}; color: white; border-radius: 3px; padding: 0 2px 0 2px";
            }
            return $m[1];
        }, $style);
        if (null === $style) {
            $pcreErrorCode = preg_last_error();
            throw new \RuntimeException('Failed to run preg_replace_callback: ' . $pcreErrorCode . ' / ' . preg_last_error_msg());
        }
        return $style;
    }
    /**
     * @param  mixed[] $dict
     * @return mixed[]
     */
    private static function dump(string $title, array $dict): array
    {
        $script = [];
        $dict = array_filter($dict, fn($value) => $value !== null);
        if (\count($dict) === 0) {
            return $script;
        }
        $script[] = self::call('log', self::quote('%c%s'), self::quote('font-weight: bold'), self::quote($title));
        foreach ($dict as $key => $value) {
            $value = json_encode($value);
            if (\false === $value) {
                $value = self::quote('');
            }
            $script[] = self::call('log', self::quote('%s: %o'), self::quote((string) $key), $value);
        }
        return $script;
    }
    private static function quote(string $arg): string
    {
        return '"' . addcslashes($arg, "\"\n\\") . '"';
    }
    /**
     * @param mixed $args
     */
    private static function call(...$args): string
    {
        $method = array_shift($args);
        if (!\is_string($method)) {
            throw new \UnexpectedValueException('Expected the first arg to be a string, got: ' . var_export($method, \true));
        }
        return self::call_array($method, $args);
    }
    /**
     * @param mixed[] $args
     */
    private static function call_array(string $method, array $args): string
    {
        return 'c.' . $method . '(' . implode(', ', $args) . ');';
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Monolog\Handler;

use Closure;
use _ContaoManager\Monolog\Level;
use _ContaoManager\Monolog\Logger;
use _ContaoManager\Monolog\ResettableInterface;
use _ContaoManager\Monolog\Formatter\FormatterInterface;
use _ContaoManager\Psr\Log\LogLevel;
use _ContaoManager\Monolog\LogRecord;
/**
 * Simple handler wrapper that filters records based on a list of levels
 *
 * It can be configured with an exact list of levels to allow, or a min/max level.
 *
 * @author Hennadiy Verkh
 * @author Jordi Boggiano <j.boggiano@seld.be>
 */
class FilterHandler extends Handler implements ProcessableHandlerInterface, ResettableInterface, FormattableHandlerInterface
{
    use ProcessableHandlerTrait;
    /**
     * Handler or factory Closure($record, $this)
     *
     * @phpstan-var (Closure(LogRecord|null, HandlerInterface): HandlerInterface)|HandlerInterface
     */
    protected Closure|HandlerInterface $handler;
    /**
     * Minimum level for logs that are passed to handler
     *
     * @var bool[] Map of Level value => true
     * @phpstan-var array<value-of<Level::VALUES>, true>
     */
    protected array $acceptedLevels;
    /**
     * Whether the messages that are handled can bubble up the stack or not
     */
    protected bool $bubble;
    /**
     * @phpstan-param (Closure(LogRecord|null, HandlerInterface): HandlerInterface)|HandlerInterface $handler
     *
     * @param Closure|HandlerInterface                             $handler        Handler or factory Closure($record|null, $filterHandler).
     * @param int|string|Level|array<int|string|Level|LogLevel::*> $minLevelOrList A list of levels to accept or a minimum level if maxLevel is provided
     * @param int|string|Level|LogLevel::*                         $maxLevel       Maximum level to accept, only used if $minLevelOrList is not an array
     * @param bool                                                 $bubble         Whether the messages that are handled can bubble up the stack or not
     *
     * @phpstan-param value-of<Level::VALUES>|value-of<Level::NAMES>|Level|LogLevel::*|array<value-of<Level::VALUES>|value-of<Level::NAMES>|Level|LogLevel::*> $minLevelOrList
     * @phpstan-param value-of<Level::VALUES>|value-of<Level::NAMES>|Level|LogLevel::* $maxLevel
     */
    public function __construct(Closure|HandlerInterface $handler, int|string|Level|array $minLevelOrList = Level::Debug, int|string|Level $maxLevel = Level::Emergency, bool $bubble = \true)
    {
        $this->handler = $handler;
        $this->bubble = $bubble;
        $this->setAcceptedLevels($minLevelOrList, $maxLevel);
    }
    /**
     * @phpstan-return list<Level> List of levels
     */
    public function getAcceptedLevels(): array
    {
        return array_map(fn(int $level) => Level::from($level), array_keys($this->acceptedLevels));
    }
    /**
     * @param  int|string|Level|LogLevel::*|array<int|string|Level|LogLevel::*> $minLevelOrList A list of levels to accept or a minimum level or level name if maxLevel is provided
     * @param  int|string|Level|LogLevel::*                                     $maxLevel       Maximum level or level name to accept, only used if $minLevelOrList is not an array
     * @return $this
     *
     * @phpstan-param value-of<Level::VALUES>|value-of<Level::NAMES>|Level|LogLevel::*|array<value-of<Level::VALUES>|value-of<Level::NAMES>|Level|LogLevel::*> $minLevelOrList
     * @phpstan-param value-of<Level::VALUES>|value-of<Level::NAMES>|Level|LogLevel::* $maxLevel
     */
    public function setAcceptedLevels(int|string|Level|array $minLevelOrList = Level::Debug, int|string|Level $maxLevel = Level::Emergency): self
    {
        if (\is_array($minLevelOrList)) {
            $acceptedLevels = array_map(Logger::toMonologLevel(...), $minLevelOrList);
        } else {
            $minLevelOrList = Logger::toMonologLevel($minLevelOrList);
            $maxLevel = Logger::toMonologLevel($maxLevel);
            $acceptedLevels = array_values(array_filter(Level::cases(), fn(Level $level) => $level->value >= $minLevelOrList->value && $level->value <= $maxLevel->value));
        }
        $this->acceptedLevels = [];
        foreach ($acceptedLevels as $level) {
            $this->acceptedLevels[$level->value] = \true;
        }
        return $this;
    }
    /**
     * @inheritDoc
     */
    public function isHandling(LogRecord $record): bool
    {
        return isset($this->acceptedLevels[$record->level->value]);
    }
    /**
     * @inheritDoc
     */
    public function handle(LogRecord $record): bool
    {
        if (!$this->isHandling($record)) {
            return \false;
        }
        if (\count($this->processors) > 0) {
            $record = $this->processRecord($record);
        }
        $this->getHandler($record)->handle($record);
        return \false === $this->bubble;
    }
    /**
     * @inheritDoc
     */
    public function handleBatch(array $records): void
    {
        $filtered = [];
        foreach ($records as $record) {
            if ($this->isHandling($record)) {
                $filtered[] = $record;
            }
        }
        if (\count($filtered) > 0) {
            $this->getHandler($filtered[\count($filtered) - 1])->handleBatch($filtered);
        }
    }
    /**
     * Return the nested handler
     *
     * If the handler was provided as a factory, this will trigger the handler's instantiation.
     */
    public function getHandler(LogRecord|null $record = null): HandlerInterface
    {
        if (!$this->handler instanceof HandlerInterface) {
            $handler = ($this->handler)($record, $this);
            if (!$handler instanceof HandlerInterface) {
                throw new \RuntimeException("The factory Closure should return a HandlerInterface");
            }
            $this->handler = $handler;
        }
        return $this->handler;
    }
    /**
     * @inheritDoc
     */
    public function setFormatter(FormatterInterface $formatter): HandlerInterface
    {
        $handler = $this->getHandler();
        if ($handler instanceof FormattableHandlerInterface) {
            $handler->setFormatter($formatter);
            return $this;
        }
        throw new \UnexpectedValueException('The nested handler of type ' . \get_class($handler) . ' does not support formatters.');
    }
    /**
     * @inheritDoc
     */
    public function getFormatter(): FormatterInterface
    {
        $handler = $this->getHandler();
        if ($handler instanceof FormattableHandlerInterface) {
            return $handler->getFormatter();
        }
        throw new \UnexpectedValueException('The nested handler of type ' . \get_class($handler) . ' does not support formatters.');
    }
    public function reset(): void
    {
        $this->resetProcessors();
        if ($this->getHandler() instanceof ResettableInterface) {
            $this->getHandler()->reset();
        }
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Monolog\Handler;

use _ContaoManager\Aws\Sqs\SqsClient;
use _ContaoManager\Monolog\Level;
use _ContaoManager\Monolog\Utils;
use _ContaoManager\Monolog\LogRecord;
/**
 * Writes to any sqs queue.
 *
 * @author Martijn van Calker <git@amvc.nl>
 */
class SqsHandler extends AbstractProcessingHandler
{
    /** 256 KB in bytes - maximum message size in SQS */
    protected const MAX_MESSAGE_SIZE = 262144;
    /** 100 KB in bytes - head message size for new error log */
    protected const HEAD_MESSAGE_SIZE = 102400;
    private SqsClient $client;
    private string $queueUrl;
    public function __construct(SqsClient $sqsClient, string $queueUrl, int|string|Level $level = Level::Debug, bool $bubble = \true)
    {
        parent::__construct($level, $bubble);
        $this->client = $sqsClient;
        $this->queueUrl = $queueUrl;
    }
    /**
     * @inheritDoc
     */
    protected function write(LogRecord $record): void
    {
        if (!isset($record->formatted) || 'string' !== \gettype($record->formatted)) {
            throw new \InvalidArgumentException('SqsHandler accepts only formatted records as a string' . Utils::getRecordMessageForException($record));
        }
        $messageBody = $record->formatted;
        if (\strlen($messageBody) >= static::MAX_MESSAGE_SIZE) {
            $messageBody = Utils::substr($messageBody, 0, static::HEAD_MESSAGE_SIZE);
        }
        $this->client->sendMessage(['QueueUrl' => $this->queueUrl, 'MessageBody' => $messageBody]);
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Monolog\Handler;

use DateTimeZone;
use InvalidArgumentException;
use _ContaoManager\Monolog\Level;
use _ContaoManager\Monolog\Utils;
use _ContaoManager\Monolog\LogRecord;
/**
 * Stores logs to files that are rotated every day and a limited number of files are kept.
 *
 * This rotation is only intended to be used as a workaround. Using logrotate to
 * handle the rotation is strongly encouraged when you can use it.
 *
 * @author Christophe Coevoet <stof@notk.org>
 * @author Jordi Boggiano <j.boggiano@seld.be>
 */
class RotatingFileHandler extends StreamHandler
{
    public const FILE_PER_DAY = 'Y-m-d';
    public const FILE_PER_MONTH = 'Y-m';
    public const FILE_PER_YEAR = 'Y';
    protected string $filename;
    protected int $maxFiles;
    protected bool|null $mustRotate = null;
    protected \DateTimeImmutable $nextRotation;
    protected string $filenameFormat;
    protected string $dateFormat;
    protected DateTimeZone|null $timezone = null;
    /**
     * @param int      $maxFiles       The maximal amount of files to keep (0 means unlimited)
     * @param int|null $filePermission Optional file permissions (default (0644) are only for owner read/write)
     * @param bool     $useLocking     Try to lock log file before doing any writes
     */
    public function __construct(string $filename, int $maxFiles = 0, int|string|Level $level = Level::Debug, bool $bubble = \true, ?int $filePermission = null, bool $useLocking = \false, string $dateFormat = self::FILE_PER_DAY, string $filenameFormat = '{filename}-{date}', DateTimeZone|null $timezone = null)
    {
        $this->filename = Utils::canonicalizePath($filename);
        $this->maxFiles = $maxFiles;
        $this->setFilenameFormat($filenameFormat, $dateFormat);
        $this->nextRotation = $this->getNextRotation();
        $this->timezone = $timezone;
        parent::__construct($this->getTimedFilename(), $level, $bubble, $filePermission, $useLocking);
    }
    /**
     * @inheritDoc
     */
    public function close(): void
    {
        parent::close();
        if (\true === $this->mustRotate) {
            $this->rotate();
        }
    }
    /**
     * @inheritDoc
     */
    public function reset(): void
    {
        parent::reset();
    }
    /**
     * @return $this
     */
    public function setFilenameFormat(string $filenameFormat, string $dateFormat): self
    {
        $this->setDateFormat($dateFormat);
        if (substr_count($filenameFormat, '{date}') === 0) {
            throw new InvalidArgumentException('Invalid filename format - format must contain at least `{date}`, because otherwise rotating is impossible.');
        }
        $this->filenameFormat = $filenameFormat;
        $this->url = $this->getTimedFilename();
        $this->close();
        return $this;
    }
    /**
     * @inheritDoc
     */
    protected function write(LogRecord $record): void
    {
        // on the first record written, if the log is new, we rotate (once per day) after the log has been written so that the new file exists
        if (null === $this->mustRotate) {
            $this->mustRotate = null === $this->url || !file_exists($this->url);
        }
        // if the next rotation is expired, then we rotate immediately
        if ($this->nextRotation <= $record->datetime) {
            $this->mustRotate = \true;
            $this->close();
            // triggers rotation
        }
        parent::write($record);
        if (\true === $this->mustRotate) {
            $this->close();
            // triggers rotation
        }
    }
    /**
     * Rotates the files.
     */
    protected function rotate(): void
    {
        // update filename
        $this->url = $this->getTimedFilename();
        $this->nextRotation = $this->getNextRotation();
        $this->mustRotate = \false;
        // skip GC of old logs if files are unlimited
        if (0 === $this->maxFiles) {
            return;
        }
        $logFiles = glob($this->getGlobPattern());
        if (\false === $logFiles) {
            // failed to glob
            return;
        }
        if ($this->maxFiles >= \count($logFiles)) {
            // no files to remove
            return;
        }
        // Sorting the files by name to remove the older ones
        usort($logFiles, function ($a, $b) {
            return strcmp($b, $a);
        });
        $basePath = dirname($this->filename);
        foreach (\array_slice($logFiles, $this->maxFiles) as $file) {
            if (is_writable($file)) {
                // suppress errors here as unlink() might fail if two processes
                // are cleaning up/rotating at the same time
                set_error_handler(function (int $errno, string $errstr, string $errfile, int $errline): bool {
                    return \true;
                });
                unlink($file);
                $dir = dirname($file);
                while ($dir !== $basePath) {
                    $entries = scandir($dir);
                    if ($entries === \false || \count(array_diff($entries, ['.', '..'])) > 0) {
                        break;
                    }
                    rmdir($dir);
                    $dir = dirname($dir);
                }
                restore_error_handler();
            }
        }
    }
    protected function getTimedFilename(): string
    {
        $fileInfo = pathinfo($this->filename);
        $timedFilename = str_replace(['{filename}', '{date}'], [$fileInfo['filename'], (new \DateTimeImmutable(timezone: $this->timezone))->format($this->dateFormat)], ($fileInfo['dirname'] ?? '') . '/' . $this->filenameFormat);
        if (isset($fileInfo['extension'])) {
            $timedFilename .= '.' . $fileInfo['extension'];
        }
        return $timedFilename;
    }
    protected function getGlobPattern(): string
    {
        $fileInfo = pathinfo($this->filename);
        $glob = str_replace(['{filename}', '{date}'], [$fileInfo['filename'], str_replace(['Y', 'y', 'm', 'd'], ['[0-9][0-9][0-9][0-9]', '[0-9][0-9]', '[0-9][0-9]', '[0-9][0-9]'], $this->dateFormat)], ($fileInfo['dirname'] ?? '') . '/' . $this->filenameFormat);
        if (isset($fileInfo['extension'])) {
            $glob .= '.' . $fileInfo['extension'];
        }
        return $glob;
    }
    protected function setDateFormat(string $dateFormat): void
    {
        if (0 === preg_match('{^[Yy](([/_.-]?m)([/_.-]?d)?)?$}', $dateFormat)) {
            throw new InvalidArgumentException('Invalid date format - format must be one of ' . 'RotatingFileHandler::FILE_PER_DAY ("Y-m-d"), RotatingFileHandler::FILE_PER_MONTH ("Y-m") ' . 'or RotatingFileHandler::FILE_PER_YEAR ("Y"), or you can set one of the ' . 'date formats using slashes, underscores and/or dots instead of dashes.');
        }
        $this->dateFormat = $dateFormat;
    }
    protected function getNextRotation(): \DateTimeImmutable
    {
        return match (str_replace(['/', '_', '.'], '-', $this->dateFormat)) {
            self::FILE_PER_MONTH => (new \DateTimeImmutable('first day of next month'))->setTime(0, 0, 0),
            self::FILE_PER_YEAR => (new \DateTimeImmutable('first day of January next year'))->setTime(0, 0, 0),
            default => (new \DateTimeImmutable('tomorrow'))->setTime(0, 0, 0),
        };
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Monolog\Handler;

use Throwable;
use _ContaoManager\Monolog\LogRecord;
/**
 * Forwards records to at most one handler
 *
 * If a handler fails, the exception is suppressed and the record is forwarded to the next handler.
 *
 * As soon as one handler handles a record successfully, the handling stops there.
 */
class FallbackGroupHandler extends GroupHandler
{
    /**
     * @inheritDoc
     */
    public function handle(LogRecord $record): bool
    {
        if (\count($this->processors) > 0) {
            $record = $this->processRecord($record);
        }
        foreach ($this->handlers as $handler) {
            try {
                $handler->handle(clone $record);
                break;
            } catch (Throwable $e) {
                // What throwable?
            }
        }
        return \false === $this->bubble;
    }
    /**
     * @inheritDoc
     */
    public function handleBatch(array $records): void
    {
        if (\count($this->processors) > 0) {
            $processed = [];
            foreach ($records as $record) {
                $processed[] = $this->processRecord($record);
            }
            $records = $processed;
        }
        foreach ($this->handlers as $handler) {
            try {
                $handler->handleBatch(array_map(fn($record) => clone $record, $records));
                break;
            } catch (Throwable $e) {
                // What throwable?
            }
        }
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Monolog\Handler;

use _ContaoManager\Monolog\Level;
use _ContaoManager\Monolog\Formatter\LineFormatter;
/**
 * NativeMailerHandler uses the mail() function to send the emails
 *
 * @author Christophe Coevoet <stof@notk.org>
 * @author Mark Garrett <mark@moderndeveloperllc.com>
 */
class NativeMailerHandler extends MailHandler
{
    /**
     * The email addresses to which the message will be sent
     * @var string[]
     */
    protected array $to;
    /**
     * The subject of the email
     */
    protected string $subject;
    /**
     * Optional headers for the message
     * @var string[]
     */
    protected array $headers = [];
    /**
     * Optional parameters for the message
     * @var string[]
     */
    protected array $parameters = [];
    /**
     * The wordwrap length for the message
     */
    protected int $maxColumnWidth;
    /**
     * The Content-type for the message
     */
    protected string|null $contentType = null;
    /**
     * The encoding for the message
     */
    protected string $encoding = 'utf-8';
    /**
     * @param string|string[] $to             The receiver of the mail
     * @param string          $subject        The subject of the mail
     * @param string          $from           The sender of the mail
     * @param int             $maxColumnWidth The maximum column width that the message lines will have
     */
    public function __construct(string|array $to, string $subject, string $from, int|string|Level $level = Level::Error, bool $bubble = \true, int $maxColumnWidth = 70)
    {
        parent::__construct($level, $bubble);
        $this->to = (array) $to;
        $this->subject = $subject;
        $this->addHeader(sprintf('From: %s', $from));
        $this->maxColumnWidth = $maxColumnWidth;
    }
    /**
     * Add headers to the message
     *
     * @param  string|string[] $headers Custom added headers
     * @return $this
     */
    public function addHeader($headers): self
    {
        foreach ((array) $headers as $header) {
            if (strpos($header, "\n") !== \false || strpos($header, "\r") !== \false) {
                throw new \InvalidArgumentException('Headers can not contain newline characters for security reasons');
            }
            $this->headers[] = $header;
        }
        return $this;
    }
    /**
     * Add parameters to the message
     *
     * @param  string|string[] $parameters Custom added parameters
     * @return $this
     */
    public function addParameter($parameters): self
    {
        $this->parameters = array_merge($this->parameters, (array) $parameters);
        return $this;
    }
    /**
     * @inheritDoc
     */
    protected function send(string $content, array $records): void
    {
        $contentType = $this->getContentType() ?? ($this->isHtmlBody($content) ? 'text/html' : 'text/plain');
        if ($contentType !== 'text/html') {
            $content = wordwrap($content, $this->maxColumnWidth);
        }
        $headers = ltrim(implode("\r\n", $this->headers) . "\r\n", "\r\n");
        $headers .= 'Content-type: ' . $contentType . '; charset=' . $this->getEncoding() . "\r\n";
        if ($contentType === 'text/html' && \false === strpos($headers, 'MIME-Version:')) {
            $headers .= 'MIME-Version: 1.0' . "\r\n";
        }
        $subjectFormatter = new LineFormatter($this->subject);
        $subject = $subjectFormatter->format($this->getHighestRecord($records));
        $parameters = implode(' ', $this->parameters);
        foreach ($this->to as $to) {
            $this->mail($to, $subject, $content, $headers, $parameters);
        }
    }
    public function getContentType(): ?string
    {
        return $this->contentType;
    }
    public function getEncoding(): string
    {
        return $this->encoding;
    }
    /**
     * @param  string $contentType The content type of the email - Defaults to text/plain. Use text/html for HTML messages.
     * @return $this
     */
    public function setContentType(string $contentType): self
    {
        if (strpos($contentType, "\n") !== \false || strpos($contentType, "\r") !== \false) {
            throw new \InvalidArgumentException('The content type can not contain newline characters to prevent email header injection');
        }
        $this->contentType = $contentType;
        return $this;
    }
    /**
     * @return $this
     */
    public function setEncoding(string $encoding): self
    {
        if (strpos($encoding, "\n") !== \false || strpos($encoding, "\r") !== \false) {
            throw new \InvalidArgumentException('The encoding can not contain newline characters to prevent email header injection');
        }
        $this->encoding = $encoding;
        return $this;
    }
    protected function mail(string $to, string $subject, string $content, string $headers, string $parameters): void
    {
        mail($to, $subject, $content, $headers, $parameters);
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Monolog\Handler;

use _ContaoManager\MongoDB\Client;
use _ContaoManager\MongoDB\Collection;
use MongoDB\Driver\BulkWrite;
use MongoDB\Driver\Manager;
use _ContaoManager\Monolog\Level;
use _ContaoManager\Monolog\Formatter\FormatterInterface;
use _ContaoManager\Monolog\Formatter\MongoDBFormatter;
use _ContaoManager\Monolog\LogRecord;
/**
 * Logs to a MongoDB database.
 *
 * Usage example:
 *
 *   $log = new \Monolog\Logger('application');
 *   $client = new \MongoDB\Client('mongodb://localhost:27017');
 *   $mongodb = new \Monolog\Handler\MongoDBHandler($client, 'logs', 'prod');
 *   $log->pushHandler($mongodb);
 *
 * The above examples uses the MongoDB PHP library's client class; however, the
 * MongoDB\Driver\Manager class from ext-mongodb is also supported.
 */
class MongoDBHandler extends AbstractProcessingHandler
{
    private Collection $collection;
    private Client|Manager $manager;
    private string|null $namespace = null;
    /**
     * Constructor.
     *
     * @param Client|Manager $mongodb    MongoDB library or driver client
     * @param string         $database   Database name
     * @param string         $collection Collection name
     */
    public function __construct(Client|Manager $mongodb, string $database, string $collection, int|string|Level $level = Level::Debug, bool $bubble = \true)
    {
        if ($mongodb instanceof Client) {
            $this->collection = method_exists($mongodb, 'getCollection') ? $mongodb->getCollection($database, $collection) : $mongodb->selectCollection($database, $collection);
        } else {
            $this->manager = $mongodb;
            $this->namespace = $database . '.' . $collection;
        }
        parent::__construct($level, $bubble);
    }
    protected function write(LogRecord $record): void
    {
        if (isset($this->collection)) {
            $this->collection->insertOne($record->formatted);
        }
        if (isset($this->manager, $this->namespace)) {
            $bulk = new BulkWrite();
            $bulk->insert($record->formatted);
            $this->manager->executeBulkWrite($this->namespace, $bulk);
        }
    }
    /**
     * @inheritDoc
     */
    protected function getDefaultFormatter(): FormatterInterface
    {
        return new MongoDBFormatter();
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Monolog\Handler;

use _ContaoManager\Monolog\Level;
use _ContaoManager\Monolog\LogRecord;
/**
 * Stores to STDIN of any process, specified by a command.
 *
 * Usage example:
 * <pre>
 * $log = new Logger('myLogger');
 * $log->pushHandler(new ProcessHandler('/usr/bin/php /var/www/monolog/someScript.php'));
 * </pre>
 *
 * @author Kolja Zuelsdorf <koljaz@web.de>
 */
class ProcessHandler extends AbstractProcessingHandler
{
    /**
     * Holds the process to receive data on its STDIN.
     *
     * @var resource|bool|null
     */
    private $process;
    private string $command;
    private ?string $cwd;
    /**
     * @var resource[]
     */
    private array $pipes = [];
    private float $timeout;
    /**
     * @var array<int, list<string>>
     */
    protected const DESCRIPTOR_SPEC = [
        0 => ['pipe', 'r'],
        // STDIN is a pipe that the child will read from
        1 => ['pipe', 'w'],
        // STDOUT is a pipe that the child will write to
        2 => ['pipe', 'w'],
    ];
    /**
     * @param  string                    $command Command for the process to start. Absolute paths are recommended,
     *                                            especially if you do not use the $cwd parameter.
     * @param  string|null               $cwd     "Current working directory" (CWD) for the process to be executed in.
     * @param  float                     $timeout The maximum timeout (in seconds) for the stream_select() function.
     * @throws \InvalidArgumentException
     */
    public function __construct(string $command, int|string|Level $level = Level::Debug, bool $bubble = \true, ?string $cwd = null, float $timeout = 1.0)
    {
        if ($command === '') {
            throw new \InvalidArgumentException('The command argument must be a non-empty string.');
        }
        if ($cwd === '') {
            throw new \InvalidArgumentException('The optional CWD argument must be a non-empty string or null.');
        }
        parent::__construct($level, $bubble);
        $this->command = $command;
        $this->cwd = $cwd;
        $this->timeout = $timeout;
    }
    /**
     * Writes the record down to the log of the implementing handler
     *
     * @throws \UnexpectedValueException
     */
    protected function write(LogRecord $record): void
    {
        $this->ensureProcessIsStarted();
        $this->writeProcessInput($record->formatted);
        $errors = $this->readProcessErrors();
        if ($errors !== '') {
            throw new \UnexpectedValueException(sprintf('Errors while writing to process: %s', $errors));
        }
    }
    /**
     * Makes sure that the process is actually started, and if not, starts it,
     * assigns the stream pipes, and handles startup errors, if any.
     */
    private function ensureProcessIsStarted(): void
    {
        if (\is_resource($this->process) === \false) {
            $this->startProcess();
            $this->handleStartupErrors();
        }
    }
    /**
     * Starts the actual process and sets all streams to non-blocking.
     */
    private function startProcess(): void
    {
        $this->process = proc_open($this->command, static::DESCRIPTOR_SPEC, $this->pipes, $this->cwd);
        foreach ($this->pipes as $pipe) {
            stream_set_blocking($pipe, \false);
        }
    }
    /**
     * Selects the STDERR stream, handles upcoming startup errors, and throws an exception, if any.
     *
     * @throws \UnexpectedValueException
     */
    private function handleStartupErrors(): void
    {
        $selected = $this->selectErrorStream();
        if (\false === $selected) {
            throw new \UnexpectedValueException('Something went wrong while selecting a stream.');
        }
        $errors = $this->readProcessErrors();
        if (\is_resource($this->process) === \false || $errors !== '') {
            throw new \UnexpectedValueException(sprintf('The process "%s" could not be opened: ' . $errors, $this->command));
        }
    }
    /**
     * Selects the STDERR stream.
     *
     * @return int|bool
     */
    protected function selectErrorStream()
    {
        $empty = [];
        $errorPipes = [$this->pipes[2]];
        $seconds = (int) $this->timeout;
        return stream_select($errorPipes, $empty, $empty, $seconds, (int) (($this->timeout - $seconds) * 1000000));
    }
    /**
     * Reads the errors of the process, if there are any.
     *
     * @codeCoverageIgnore
     * @return string Empty string if there are no errors.
     */
    protected function readProcessErrors(): string
    {
        return (string) stream_get_contents($this->pipes[2]);
    }
    /**
     * Writes to the input stream of the opened process.
     *
     * @codeCoverageIgnore
     */
    protected function writeProcessInput(string $string): void
    {
        fwrite($this->pipes[0], $string);
    }
    /**
     * @inheritDoc
     */
    public function close(): void
    {
        if (\is_resource($this->process)) {
            foreach ($this->pipes as $pipe) {
                fclose($pipe);
            }
            proc_close($this->process);
            $this->process = null;
        }
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Monolog\Handler;

use _ContaoManager\Monolog\Formatter\FormatterInterface;
use _ContaoManager\Monolog\Formatter\LineFormatter;
/**
 * Helper trait for implementing FormattableInterface
 *
 * @author Jordi Boggiano <j.boggiano@seld.be>
 */
trait FormattableHandlerTrait
{
    protected FormatterInterface|null $formatter = null;
    /**
     * @inheritDoc
     */
    public function setFormatter(FormatterInterface $formatter): HandlerInterface
    {
        $this->formatter = $formatter;
        return $this;
    }
    /**
     * @inheritDoc
     */
    public function getFormatter(): FormatterInterface
    {
        if (null === $this->formatter) {
            $this->formatter = $this->getDefaultFormatter();
        }
        return $this->formatter;
    }
    /**
     * Gets the default formatter.
     *
     * Overwrite this if the LineFormatter is not a good default for your handler.
     */
    protected function getDefaultFormatter(): FormatterInterface
    {
        return new LineFormatter();
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Monolog\Handler;

use _ContaoManager\Gelf\PublisherInterface;
use _ContaoManager\Monolog\Level;
use _ContaoManager\Monolog\Formatter\GelfMessageFormatter;
use _ContaoManager\Monolog\Formatter\FormatterInterface;
use _ContaoManager\Monolog\LogRecord;
/**
 * Handler to send messages to a Graylog2 (http://www.graylog2.org) server
 *
 * @author Matt Lehner <mlehner@gmail.com>
 * @author Benjamin Zikarsky <benjamin@zikarsky.de>
 */
class GelfHandler extends AbstractProcessingHandler
{
    /**
     * @var PublisherInterface the publisher object that sends the message to the server
     */
    protected PublisherInterface $publisher;
    /**
     * @param PublisherInterface $publisher a gelf publisher object
     */
    public function __construct(PublisherInterface $publisher, int|string|Level $level = Level::Debug, bool $bubble = \true)
    {
        parent::__construct($level, $bubble);
        $this->publisher = $publisher;
    }
    /**
     * @inheritDoc
     */
    protected function write(LogRecord $record): void
    {
        $this->publisher->publish($record->formatted);
    }
    /**
     * @inheritDoc
     */
    protected function getDefaultFormatter(): FormatterInterface
    {
        return new GelfMessageFormatter();
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Monolog\Handler;

use _ContaoManager\Monolog\Formatter\FormatterInterface;
use _ContaoManager\Monolog\Formatter\NormalizerFormatter;
use _ContaoManager\Monolog\Level;
use _ContaoManager\Monolog\LogRecord;
/**
 * Handler sending logs to Zend Monitor
 *
 * @author  Christian Bergau <cbergau86@gmail.com>
 * @author  Jason Davis <happydude@jasondavis.net>
 */
class ZendMonitorHandler extends AbstractProcessingHandler
{
    /**
     * @throws MissingExtensionException
     */
    public function __construct(int|string|Level $level = Level::Debug, bool $bubble = \true)
    {
        if (!\function_exists('_ContaoManager\zend_monitor_custom_event')) {
            throw new MissingExtensionException('You must have Zend Server installed with Zend Monitor enabled in order to use this handler');
        }
        parent::__construct($level, $bubble);
    }
    /**
     * Translates Monolog log levels to ZendMonitor levels.
     */
    protected function toZendMonitorLevel(Level $level): int
    {
        return match ($level) {
            Level::Debug => \ZEND_MONITOR_EVENT_SEVERITY_INFO,
            Level::Info => \ZEND_MONITOR_EVENT_SEVERITY_INFO,
            Level::Notice => \ZEND_MONITOR_EVENT_SEVERITY_INFO,
            Level::Warning => \ZEND_MONITOR_EVENT_SEVERITY_WARNING,
            Level::Error => \ZEND_MONITOR_EVENT_SEVERITY_ERROR,
            Level::Critical => \ZEND_MONITOR_EVENT_SEVERITY_ERROR,
            Level::Alert => \ZEND_MONITOR_EVENT_SEVERITY_ERROR,
            Level::Emergency => \ZEND_MONITOR_EVENT_SEVERITY_ERROR,
        };
    }
    /**
     * @inheritDoc
     */
    protected function write(LogRecord $record): void
    {
        $this->writeZendMonitorCustomEvent($record->level->getName(), $record->message, $record->formatted, $this->toZendMonitorLevel($record->level));
    }
    /**
     * Write to Zend Monitor Events
     * @param string       $type      Text displayed in "Class Name (custom)" field
     * @param string       $message   Text displayed in "Error String"
     * @param array<mixed> $formatted Displayed in Custom Variables tab
     * @param int          $severity  Set the event severity level (-1,0,1)
     */
    protected function writeZendMonitorCustomEvent(string $type, string $message, array $formatted, int $severity): void
    {
        zend_monitor_custom_event($type, $message, $formatted, $severity);
    }
    /**
     * @inheritDoc
     */
    public function getDefaultFormatter(): FormatterInterface
    {
        return new NormalizerFormatter();
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Monolog\Handler;

use _ContaoManager\Monolog\Formatter\LineFormatter;
use _ContaoManager\Monolog\Formatter\FormatterInterface;
use _ContaoManager\Monolog\Level;
use _ContaoManager\Monolog\Utils;
use _ContaoManager\PhpConsole\Connector;
use _ContaoManager\PhpConsole\Handler as VendorPhpConsoleHandler;
use _ContaoManager\PhpConsole\Helper;
use _ContaoManager\Monolog\LogRecord;
use _ContaoManager\PhpConsole\Storage;
/**
 * Monolog handler for Google Chrome extension "PHP Console"
 *
 * Display PHP error/debug log messages in Google Chrome console and notification popups, executes PHP code remotely
 *
 * Usage:
 * 1. Install Google Chrome extension [now dead and removed from the chrome store]
 * 2. See overview https://github.com/barbushin/php-console#overview
 * 3. Install PHP Console library https://github.com/barbushin/php-console#installation
 * 4. Example (result will looks like http://i.hizliresim.com/vg3Pz4.png)
 *
 *      $logger = new \Monolog\Logger('all', array(new \Monolog\Handler\PHPConsoleHandler()));
 *      \Monolog\ErrorHandler::register($logger);
 *      echo $undefinedVar;
 *      $logger->debug('SELECT * FROM users', array('db', 'time' => 0.012));
 *      PC::debug($_SERVER); // PHP Console debugger for any type of vars
 *
 * @author Sergey Barbushin https://www.linkedin.com/in/barbushin
 * @phpstan-type Options array{
 *     enabled: bool,
 *     classesPartialsTraceIgnore: string[],
 *     debugTagsKeysInContext: array<int|string>,
 *     useOwnErrorsHandler: bool,
 *     useOwnExceptionsHandler: bool,
 *     sourcesBasePath: string|null,
 *     registerHelper: bool,
 *     serverEncoding: string|null,
 *     headersLimit: int|null,
 *     password: string|null,
 *     enableSslOnlyMode: bool,
 *     ipMasks: string[],
 *     enableEvalListener: bool,
 *     dumperDetectCallbacks: bool,
 *     dumperLevelLimit: int,
 *     dumperItemsCountLimit: int,
 *     dumperItemSizeLimit: int,
 *     dumperDumpSizeLimit: int,
 *     detectDumpTraceAndSource: bool,
 *     dataStorage: Storage|null
 * }
 * @phpstan-type InputOptions array{
 *     enabled?: bool,
 *     classesPartialsTraceIgnore?: string[],
 *     debugTagsKeysInContext?: array<int|string>,
 *     useOwnErrorsHandler?: bool,
 *     useOwnExceptionsHandler?: bool,
 *     sourcesBasePath?: string|null,
 *     registerHelper?: bool,
 *     serverEncoding?: string|null,
 *     headersLimit?: int|null,
 *     password?: string|null,
 *     enableSslOnlyMode?: bool,
 *     ipMasks?: string[],
 *     enableEvalListener?: bool,
 *     dumperDetectCallbacks?: bool,
 *     dumperLevelLimit?: int,
 *     dumperItemsCountLimit?: int,
 *     dumperItemSizeLimit?: int,
 *     dumperDumpSizeLimit?: int,
 *     detectDumpTraceAndSource?: bool,
 *     dataStorage?: Storage|null
 * }
 *
 * @deprecated Since 2.8.0 and 3.2.0, PHPConsole is abandoned and thus we will drop this handler in Monolog 4
 */
class PHPConsoleHandler extends AbstractProcessingHandler
{
    /**
     * @phpstan-var Options
     */
    private array $options = [
        'enabled' => \true,
        // bool Is PHP Console server enabled
        'classesPartialsTraceIgnore' => ['Monolog\\'],
        // array Hide calls of classes started with...
        'debugTagsKeysInContext' => [0, 'tag'],
        // bool Is PHP Console server enabled
        'useOwnErrorsHandler' => \false,
        // bool Enable errors handling
        'useOwnExceptionsHandler' => \false,
        // bool Enable exceptions handling
        'sourcesBasePath' => null,
        // string Base path of all project sources to strip in errors source paths
        'registerHelper' => \true,
        // bool Register PhpConsole\Helper that allows short debug calls like PC::debug($var, 'ta.g.s')
        'serverEncoding' => null,
        // string|null Server internal encoding
        'headersLimit' => null,
        // int|null Set headers size limit for your web-server
        'password' => null,
        // string|null Protect PHP Console connection by password
        'enableSslOnlyMode' => \false,
        // bool Force connection by SSL for clients with PHP Console installed
        'ipMasks' => [],
        // array Set IP masks of clients that will be allowed to connect to PHP Console: array('192.168.*.*', '127.0.0.1')
        'enableEvalListener' => \false,
        // bool Enable eval request to be handled by eval dispatcher(if enabled, 'password' option is also required)
        'dumperDetectCallbacks' => \false,
        // bool Convert callback items in dumper vars to (callback SomeClass::someMethod) strings
        'dumperLevelLimit' => 5,
        // int Maximum dumped vars array or object nested dump level
        'dumperItemsCountLimit' => 100,
        // int Maximum dumped var same level array items or object properties number
        'dumperItemSizeLimit' => 5000,
        // int Maximum length of any string or dumped array item
        'dumperDumpSizeLimit' => 500000,
        // int Maximum approximate size of dumped vars result formatted in JSON
        'detectDumpTraceAndSource' => \false,
        // bool Autodetect and append trace data to debug
        'dataStorage' => null,
    ];
    private Connector $connector;
    /**
     * @param  array<string, mixed> $options   See \Monolog\Handler\PHPConsoleHandler::$options for more details
     * @param  Connector|null       $connector Instance of \PhpConsole\Connector class (optional)
     * @throws \RuntimeException
     * @phpstan-param InputOptions $options
     */
    public function __construct(array $options = [], ?Connector $connector = null, int|string|Level $level = Level::Debug, bool $bubble = \true)
    {
        if (!class_exists('_ContaoManager\PhpConsole\Connector')) {
            throw new \RuntimeException('PHP Console library not found. See https://github.com/barbushin/php-console#installation');
        }
        parent::__construct($level, $bubble);
        $this->options = $this->initOptions($options);
        $this->connector = $this->initConnector($connector);
    }
    /**
     * @param  array<string, mixed> $options
     * @return array<string, mixed>
     *
     * @phpstan-param InputOptions $options
     * @phpstan-return Options
     */
    private function initOptions(array $options): array
    {
        $wrongOptions = array_diff(array_keys($options), array_keys($this->options));
        if (\count($wrongOptions) > 0) {
            throw new \RuntimeException('Unknown options: ' . implode(', ', $wrongOptions));
        }
        return array_replace($this->options, $options);
    }
    private function initConnector(?Connector $connector = null): Connector
    {
        if (null === $connector) {
            if ($this->options['dataStorage'] instanceof Storage) {
                Connector::setPostponeStorage($this->options['dataStorage']);
            }
            $connector = Connector::getInstance();
        }
        if ($this->options['registerHelper'] && !Helper::isRegistered()) {
            Helper::register();
        }
        if ($this->options['enabled'] && $connector->isActiveClient()) {
            if ($this->options['useOwnErrorsHandler'] || $this->options['useOwnExceptionsHandler']) {
                $handler = VendorPhpConsoleHandler::getInstance();
                $handler->setHandleErrors($this->options['useOwnErrorsHandler']);
                $handler->setHandleExceptions($this->options['useOwnExceptionsHandler']);
                $handler->start();
            }
            if (null !== $this->options['sourcesBasePath']) {
                $connector->setSourcesBasePath($this->options['sourcesBasePath']);
            }
            if (null !== $this->options['serverEncoding']) {
                $connector->setServerEncoding($this->options['serverEncoding']);
            }
            if (null !== $this->options['password']) {
                $connector->setPassword($this->options['password']);
            }
            if ($this->options['enableSslOnlyMode']) {
                $connector->enableSslOnlyMode();
            }
            if (\count($this->options['ipMasks']) > 0) {
                $connector->setAllowedIpMasks($this->options['ipMasks']);
            }
            if (null !== $this->options['headersLimit'] && $this->options['headersLimit'] > 0) {
                $connector->setHeadersLimit($this->options['headersLimit']);
            }
            if ($this->options['detectDumpTraceAndSource']) {
                $connector->getDebugDispatcher()->detectTraceAndSource = \true;
            }
            $dumper = $connector->getDumper();
            $dumper->levelLimit = $this->options['dumperLevelLimit'];
            $dumper->itemsCountLimit = $this->options['dumperItemsCountLimit'];
            $dumper->itemSizeLimit = $this->options['dumperItemSizeLimit'];
            $dumper->dumpSizeLimit = $this->options['dumperDumpSizeLimit'];
            $dumper->detectCallbacks = $this->options['dumperDetectCallbacks'];
            if ($this->options['enableEvalListener']) {
                $connector->startEvalRequestsListener();
            }
        }
        return $connector;
    }
    public function getConnector(): Connector
    {
        return $this->connector;
    }
    /**
     * @return array<string, mixed>
     */
    public function getOptions(): array
    {
        return $this->options;
    }
    public function handle(LogRecord $record): bool
    {
        if ($this->options['enabled'] && $this->connector->isActiveClient()) {
            return parent::handle($record);
        }
        return !$this->bubble;
    }
    /**
     * Writes the record down to the log of the implementing handler
     */
    protected function write(LogRecord $record): void
    {
        if ($record->level->isLowerThan(Level::Notice)) {
            $this->handleDebugRecord($record);
        } elseif (isset($record->context['exception']) && $record->context['exception'] instanceof \Throwable) {
            $this->handleExceptionRecord($record);
        } else {
            $this->handleErrorRecord($record);
        }
    }
    private function handleDebugRecord(LogRecord $record): void
    {
        [$tags, $filteredContext] = $this->getRecordTags($record);
        $message = $record->message;
        if (\count($filteredContext) > 0) {
            $message .= ' ' . Utils::jsonEncode($this->connector->getDumper()->dump(array_filter($filteredContext)), null, \true);
        }
        $this->connector->getDebugDispatcher()->dispatchDebug($message, $tags, $this->options['classesPartialsTraceIgnore']);
    }
    private function handleExceptionRecord(LogRecord $record): void
    {
        $this->connector->getErrorsDispatcher()->dispatchException($record->context['exception']);
    }
    private function handleErrorRecord(LogRecord $record): void
    {
        $context = $record->context;
        $this->connector->getErrorsDispatcher()->dispatchError($context['code'] ?? null, $context['message'] ?? $record->message, $context['file'] ?? null, $context['line'] ?? null, $this->options['classesPartialsTraceIgnore']);
    }
    /**
     * @return array{string, mixed[]}
     */
    private function getRecordTags(LogRecord $record): array
    {
        $tags = null;
        $filteredContext = [];
        if ($record->context !== []) {
            $filteredContext = $record->context;
            foreach ($this->options['debugTagsKeysInContext'] as $key) {
                if (isset($filteredContext[$key])) {
                    $tags = $filteredContext[$key];
                    if ($key === 0) {
                        array_shift($filteredContext);
                    } else {
                        unset($filteredContext[$key]);
                    }
                    break;
                }
            }
        }
        return [$tags ?? $record->level->toPsrLogLevel(), $filteredContext];
    }
    /**
     * @inheritDoc
     */
    protected function getDefaultFormatter(): FormatterInterface
    {
        return new LineFormatter('%message%');
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Monolog\Handler;

use _ContaoManager\Monolog\Formatter\LineFormatter;
use _ContaoManager\Monolog\Formatter\FormatterInterface;
use _ContaoManager\Monolog\Level;
use _ContaoManager\Monolog\Utils;
use _ContaoManager\Monolog\LogRecord;
/**
 * Stores to PHP error_log() handler.
 *
 * @author Elan Ruusamäe <glen@delfi.ee>
 */
class ErrorLogHandler extends AbstractProcessingHandler
{
    public const OPERATING_SYSTEM = 0;
    public const SAPI = 4;
    /** @var 0|4 */
    protected int $messageType;
    protected bool $expandNewlines;
    /**
     * @param 0|4 $messageType    Says where the error should go.
     * @param bool $expandNewlines If set to true, newlines in the message will be expanded to be take multiple log entries
     *
     * @throws \InvalidArgumentException If an unsupported message type is set
     */
    public function __construct(int $messageType = self::OPERATING_SYSTEM, int|string|Level $level = Level::Debug, bool $bubble = \true, bool $expandNewlines = \false)
    {
        parent::__construct($level, $bubble);
        if (\false === \in_array($messageType, self::getAvailableTypes(), \true)) {
            $message = sprintf('The given message type "%s" is not supported', print_r($messageType, \true));
            throw new \InvalidArgumentException($message);
        }
        $this->messageType = $messageType;
        $this->expandNewlines = $expandNewlines;
    }
    /**
     * @return int[] With all available types
     */
    public static function getAvailableTypes(): array
    {
        return [self::OPERATING_SYSTEM, self::SAPI];
    }
    /**
     * @inheritDoc
     */
    protected function getDefaultFormatter(): FormatterInterface
    {
        return new LineFormatter('[%datetime%] %channel%.%level_name%: %message% %context% %extra%');
    }
    /**
     * @inheritDoc
     */
    protected function write(LogRecord $record): void
    {
        if (!$this->expandNewlines) {
            error_log((string) $record->formatted, $this->messageType);
            return;
        }
        $lines = preg_split('{[\r\n]+}', (string) $record->formatted);
        if ($lines === \false) {
            $pcreErrorCode = preg_last_error();
            throw new \RuntimeException('Failed to preg_split formatted string: ' . $pcreErrorCode . ' / ' . preg_last_error_msg());
        }
        foreach ($lines as $line) {
            error_log($line, $this->messageType);
        }
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Monolog\Handler;

use _ContaoManager\Monolog\Level;
use _ContaoManager\Monolog\LogRecord;
/**
 * @author Robert Kaufmann III <rok3@rok3.me>
 */
class LogEntriesHandler extends SocketHandler
{
    protected string $logToken;
    /**
     * @param string $token  Log token supplied by LogEntries
     * @param bool   $useSSL Whether or not SSL encryption should be used.
     * @param string $host   Custom hostname to send the data to if needed
     *
     * @throws MissingExtensionException If SSL encryption is set to true and OpenSSL is missing
     */
    public function __construct(string $token, bool $useSSL = \true, $level = Level::Debug, bool $bubble = \true, string $host = 'data.logentries.com', bool $persistent = \false, float $timeout = 0.0, float $writingTimeout = 10.0, ?float $connectionTimeout = null, ?int $chunkSize = null)
    {
        if ($useSSL && !\extension_loaded('openssl')) {
            throw new MissingExtensionException('The OpenSSL PHP plugin is required to use SSL encrypted connection for LogEntriesHandler');
        }
        $endpoint = $useSSL ? 'ssl://' . $host . ':443' : $host . ':80';
        parent::__construct($endpoint, $level, $bubble, $persistent, $timeout, $writingTimeout, $connectionTimeout, $chunkSize);
        $this->logToken = $token;
    }
    /**
     * @inheritDoc
     */
    protected function generateDataStream(LogRecord $record): string
    {
        return $this->logToken . ' ' . $record->formatted;
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Monolog\Handler;

use _ContaoManager\Monolog\Level;
use _ContaoManager\Monolog\Formatter\FormatterInterface;
use _ContaoManager\Monolog\Formatter\LogmaticFormatter;
use _ContaoManager\Monolog\LogRecord;
/**
 * @author Julien Breux <julien.breux@gmail.com>
 */
class LogmaticHandler extends SocketHandler
{
    private string $logToken;
    private string $hostname;
    private string $appName;
    /**
     * @param string $token    Log token supplied by Logmatic.
     * @param string $hostname Host name supplied by Logmatic.
     * @param string $appName  Application name supplied by Logmatic.
     * @param bool   $useSSL   Whether or not SSL encryption should be used.
     *
     * @throws MissingExtensionException If SSL encryption is set to true and OpenSSL is missing
     */
    public function __construct(string $token, string $hostname = '', string $appName = '', bool $useSSL = \true, $level = Level::Debug, bool $bubble = \true, bool $persistent = \false, float $timeout = 0.0, float $writingTimeout = 10.0, ?float $connectionTimeout = null, ?int $chunkSize = null)
    {
        if ($useSSL && !\extension_loaded('openssl')) {
            throw new MissingExtensionException('The OpenSSL PHP extension is required to use SSL encrypted connection for LogmaticHandler');
        }
        $endpoint = $useSSL ? 'ssl://api.logmatic.io:10515' : 'api.logmatic.io:10514';
        $endpoint .= '/v1/';
        parent::__construct($endpoint, $level, $bubble, $persistent, $timeout, $writingTimeout, $connectionTimeout, $chunkSize);
        $this->logToken = $token;
        $this->hostname = $hostname;
        $this->appName = $appName;
    }
    /**
     * @inheritDoc
     */
    protected function generateDataStream(LogRecord $record): string
    {
        return $this->logToken . ' ' . $record->formatted;
    }
    /**
     * @inheritDoc
     */
    protected function getDefaultFormatter(): FormatterInterface
    {
        $formatter = new LogmaticFormatter();
        if ($this->hostname !== '') {
            $formatter->setHostname($this->hostname);
        }
        if ($this->appName !== '') {
            $formatter->setAppName($this->appName);
        }
        return $formatter;
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Monolog\Handler;

use _ContaoManager\Monolog\Level;
use _ContaoManager\Monolog\Logger;
use _ContaoManager\Psr\Log\LogLevel;
use _ContaoManager\Monolog\LogRecord;
/**
 * Simple handler wrapper that deduplicates log records across multiple requests
 *
 * It also includes the BufferHandler functionality and will buffer
 * all messages until the end of the request or flush() is called.
 *
 * This works by storing all log records' messages above $deduplicationLevel
 * to the file specified by $deduplicationStore. When further logs come in at the end of the
 * request (or when flush() is called), all those above $deduplicationLevel are checked
 * against the existing stored logs. If they match and the timestamps in the stored log is
 * not older than $time seconds, the new log record is discarded. If no log record is new, the
 * whole data set is discarded.
 *
 * This is mainly useful in combination with Mail handlers or things like Slack or HipChat handlers
 * that send messages to people, to avoid spamming with the same message over and over in case of
 * a major component failure like a database server being down which makes all requests fail in the
 * same way.
 *
 * @author Jordi Boggiano <j.boggiano@seld.be>
 */
class DeduplicationHandler extends BufferHandler
{
    protected string $deduplicationStore;
    protected Level $deduplicationLevel;
    protected int $time;
    protected bool $gc = \false;
    /**
     * @param HandlerInterface             $handler            Handler.
     * @param string|null                  $deduplicationStore The file/path where the deduplication log should be kept
     * @param int|string|Level|LogLevel::* $deduplicationLevel The minimum logging level for log records to be looked at for deduplication purposes
     * @param int                          $time               The period (in seconds) during which duplicate entries should be suppressed after a given log is sent through
     * @param bool                         $bubble             Whether the messages that are handled can bubble up the stack or not
     *
     * @phpstan-param value-of<Level::VALUES>|value-of<Level::NAMES>|Level|LogLevel::* $deduplicationLevel
     */
    public function __construct(HandlerInterface $handler, ?string $deduplicationStore = null, int|string|Level $deduplicationLevel = Level::Error, int $time = 60, bool $bubble = \true)
    {
        parent::__construct($handler, 0, Level::Debug, $bubble, \false);
        $this->deduplicationStore = $deduplicationStore === null ? sys_get_temp_dir() . '/monolog-dedup-' . substr(md5(__FILE__), 0, 20) . '.log' : $deduplicationStore;
        $this->deduplicationLevel = Logger::toMonologLevel($deduplicationLevel);
        $this->time = $time;
    }
    public function flush(): void
    {
        if ($this->bufferSize === 0) {
            return;
        }
        $store = null;
        if (file_exists($this->deduplicationStore)) {
            $store = file($this->deduplicationStore, \FILE_IGNORE_NEW_LINES | \FILE_SKIP_EMPTY_LINES);
        }
        $passthru = null;
        foreach ($this->buffer as $record) {
            if ($record->level->value >= $this->deduplicationLevel->value) {
                $passthru = $passthru === \true || !\is_array($store) || !$this->isDuplicate($store, $record);
                if ($passthru) {
                    $line = $this->buildDeduplicationStoreEntry($record);
                    file_put_contents($this->deduplicationStore, $line . "\n", \FILE_APPEND);
                    if (!\is_array($store)) {
                        $store = [];
                    }
                    $store[] = $line;
                }
            }
        }
        // default of null is valid as well as if no record matches duplicationLevel we just pass through
        if ($passthru === \true || $passthru === null) {
            $this->handler->handleBatch($this->buffer);
        }
        $this->clear();
        if ($this->gc) {
            $this->collectLogs();
        }
    }
    /**
     * If there is a store entry older than e.g. a day, this method should set `$this->gc` to `true` to trigger garbage collection.
     * @param string[] $store The deduplication store
     */
    protected function isDuplicate(array $store, LogRecord $record): bool
    {
        $timestampValidity = $record->datetime->getTimestamp() - $this->time;
        $expectedMessage = preg_replace('{[\r\n].*}', '', $record->message);
        $yesterday = time() - 86400;
        for ($i = \count($store) - 1; $i >= 0; $i--) {
            list($timestamp, $level, $message) = explode(':', $store[$i], 3);
            if ($level === $record->level->getName() && $message === $expectedMessage && $timestamp > $timestampValidity) {
                return \true;
            }
            if ($timestamp < $yesterday) {
                $this->gc = \true;
            }
        }
        return \false;
    }
    /**
     * @return string The given record serialized as a single line of text
     */
    protected function buildDeduplicationStoreEntry(LogRecord $record): string
    {
        return $record->datetime->getTimestamp() . ':' . $record->level->getName() . ':' . preg_replace('{[\r\n].*}', '', $record->message);
    }
    private function collectLogs(): void
    {
        if (!file_exists($this->deduplicationStore)) {
            return;
        }
        $handle = fopen($this->deduplicationStore, 'rw+');
        if (\false === $handle) {
            throw new \RuntimeException('Failed to open file for reading and writing: ' . $this->deduplicationStore);
        }
        if (\false === flock($handle, \LOCK_EX)) {
            return;
        }
        $validLogs = [];
        $timestampValidity = time() - $this->time;
        while (!feof($handle)) {
            $log = fgets($handle);
            if (\is_string($log) && '' !== $log && substr($log, 0, 10) >= $timestampValidity) {
                $validLogs[] = $log;
            }
        }
        ftruncate($handle, 0);
        rewind($handle);
        foreach ($validLogs as $log) {
            fwrite($handle, $log);
        }
        flock($handle, \LOCK_UN);
        fclose($handle);
        $this->gc = \false;
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Monolog\Handler;

use _ContaoManager\Monolog\Formatter\WildfireFormatter;
use _ContaoManager\Monolog\Formatter\FormatterInterface;
use _ContaoManager\Monolog\LogRecord;
/**
 * Simple FirePHP Handler (http://www.firephp.org/), which uses the Wildfire protocol.
 *
 * @author Eric Clemmons (@ericclemmons) <eric@uxdriven.com>
 */
class FirePHPHandler extends AbstractProcessingHandler
{
    use WebRequestRecognizerTrait;
    /**
     * WildFire JSON header message format
     */
    protected const PROTOCOL_URI = 'http://meta.wildfirehq.org/Protocol/JsonStream/0.2';
    /**
     * FirePHP structure for parsing messages & their presentation
     */
    protected const STRUCTURE_URI = 'http://meta.firephp.org/Wildfire/Structure/FirePHP/FirebugConsole/0.1';
    /**
     * Must reference a "known" plugin, otherwise headers won't display in FirePHP
     */
    protected const PLUGIN_URI = 'http://meta.firephp.org/Wildfire/Plugin/FirePHP/Library-FirePHPCore/0.3';
    /**
     * Header prefix for Wildfire to recognize & parse headers
     */
    protected const HEADER_PREFIX = 'X-Wf';
    /**
     * Whether or not Wildfire vendor-specific headers have been generated & sent yet
     */
    protected static bool $initialized = \false;
    /**
     * Shared static message index between potentially multiple handlers
     */
    protected static int $messageIndex = 1;
    protected static bool $sendHeaders = \true;
    /**
     * Base header creation function used by init headers & record headers
     *
     * @param array<int|string> $meta    Wildfire Plugin, Protocol & Structure Indexes
     * @param string            $message Log message
     *
     * @return array<string, string> Complete header string ready for the client as key and message as value
     *
     * @phpstan-return non-empty-array<string, string>
     */
    protected function createHeader(array $meta, string $message): array
    {
        $header = sprintf('%s-%s', static::HEADER_PREFIX, join('-', $meta));
        return [$header => $message];
    }
    /**
     * Creates message header from record
     *
     * @return array<string, string>
     *
     * @phpstan-return non-empty-array<string, string>
     *
     * @see createHeader()
     */
    protected function createRecordHeader(LogRecord $record): array
    {
        // Wildfire is extensible to support multiple protocols & plugins in a single request,
        // but we're not taking advantage of that (yet), so we're using "1" for simplicity's sake.
        return $this->createHeader([1, 1, 1, self::$messageIndex++], $record->formatted);
    }
    /**
     * @inheritDoc
     */
    protected function getDefaultFormatter(): FormatterInterface
    {
        return new WildfireFormatter();
    }
    /**
     * Wildfire initialization headers to enable message parsing
     *
     * @see createHeader()
     * @see sendHeader()
     *
     * @return array<string, string>
     */
    protected function getInitHeaders(): array
    {
        // Initial payload consists of required headers for Wildfire
        return array_merge($this->createHeader(['Protocol', 1], static::PROTOCOL_URI), $this->createHeader([1, 'Structure', 1], static::STRUCTURE_URI), $this->createHeader([1, 'Plugin', 1], static::PLUGIN_URI));
    }
    /**
     * Send header string to the client
     */
    protected function sendHeader(string $header, string $content): void
    {
        if (!headers_sent() && self::$sendHeaders) {
            header(sprintf('%s: %s', $header, $content));
        }
    }
    /**
     * Creates & sends header for a record, ensuring init headers have been sent prior
     *
     * @see sendHeader()
     * @see sendInitHeaders()
     */
    protected function write(LogRecord $record): void
    {
        if (!self::$sendHeaders || !$this->isWebRequest()) {
            return;
        }
        // WildFire-specific headers must be sent prior to any messages
        if (!self::$initialized) {
            self::$initialized = \true;
            self::$sendHeaders = $this->headersAccepted();
            if (!self::$sendHeaders) {
                return;
            }
            foreach ($this->getInitHeaders() as $header => $content) {
                $this->sendHeader($header, $content);
            }
        }
        $header = $this->createRecordHeader($record);
        if (trim(current($header)) !== '') {
            $this->sendHeader(key($header), current($header));
        }
    }
    /**
     * Verifies if the headers are accepted by the current user agent
     */
    protected function headersAccepted(): bool
    {
        if (isset($_SERVER['HTTP_USER_AGENT']) && 1 === preg_match('{\bFirePHP/\d+\.\d+\b}', $_SERVER['HTTP_USER_AGENT'])) {
            return \true;
        }
        return isset($_SERVER['HTTP_X_FIREPHP_VERSION']);
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Monolog\Handler\Curl;

use CurlHandle;
/**
 * This class is marked as internal and it is not under the BC promise of the package.
 *
 * @internal
 */
final class Util
{
    /** @var array<int> */
    private static array $retriableErrorCodes = [\CURLE_COULDNT_RESOLVE_HOST, \CURLE_COULDNT_CONNECT, \CURLE_HTTP_NOT_FOUND, \CURLE_READ_ERROR, \CURLE_OPERATION_TIMEOUTED, \CURLE_HTTP_POST_ERROR, \CURLE_SSL_CONNECT_ERROR];
    /**
     * Executes a CURL request with optional retries and exception on failure
     *
     * @param  CurlHandle  $ch curl handler
     * @return bool|string @see curl_exec
     */
    public static function execute(CurlHandle $ch, int $retries = 5): bool|string
    {
        while ($retries > 0) {
            $retries--;
            $curlResponse = curl_exec($ch);
            if ($curlResponse === \false) {
                $curlErrno = curl_errno($ch);
                if (\false === \in_array($curlErrno, self::$retriableErrorCodes, \true) || $retries === 0) {
                    $curlError = curl_error($ch);
                    throw new \RuntimeException(sprintf('Curl error (code %d): %s', $curlErrno, $curlError));
                }
                continue;
            }
            return $curlResponse;
        }
        return \false;
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Monolog\Handler;

use _ContaoManager\Monolog\Level;
use _ContaoManager\Monolog\Formatter\NormalizerFormatter;
use _ContaoManager\Monolog\Formatter\FormatterInterface;
use _ContaoManager\Doctrine\CouchDB\CouchDBClient;
use _ContaoManager\Monolog\LogRecord;
/**
 * CouchDB handler for Doctrine CouchDB ODM
 *
 * @author Markus Bachmann <markus.bachmann@bachi.biz>
 */
class DoctrineCouchDBHandler extends AbstractProcessingHandler
{
    private CouchDBClient $client;
    public function __construct(CouchDBClient $client, int|string|Level $level = Level::Debug, bool $bubble = \true)
    {
        $this->client = $client;
        parent::__construct($level, $bubble);
    }
    /**
     * @inheritDoc
     */
    protected function write(LogRecord $record): void
    {
        $this->client->postDocument($record->formatted);
    }
    protected function getDefaultFormatter(): FormatterInterface
    {
        return new NormalizerFormatter();
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Monolog\Handler;

use _ContaoManager\Aws\Sdk;
use _ContaoManager\Aws\DynamoDb\DynamoDbClient;
use _ContaoManager\Monolog\Formatter\FormatterInterface;
use _ContaoManager\Aws\DynamoDb\Marshaler;
use _ContaoManager\Monolog\Formatter\ScalarFormatter;
use _ContaoManager\Monolog\Level;
use _ContaoManager\Monolog\LogRecord;
/**
 * Amazon DynamoDB handler (http://aws.amazon.com/dynamodb/)
 *
 * @link https://github.com/aws/aws-sdk-php/
 * @author Andrew Lawson <adlawson@gmail.com>
 */
class DynamoDbHandler extends AbstractProcessingHandler
{
    public const DATE_FORMAT = 'Y-m-d\TH:i:s.uO';
    protected DynamoDbClient $client;
    protected string $table;
    protected Marshaler $marshaler;
    public function __construct(DynamoDbClient $client, string $table, int|string|Level $level = Level::Debug, bool $bubble = \true)
    {
        $this->marshaler = new Marshaler();
        $this->client = $client;
        $this->table = $table;
        parent::__construct($level, $bubble);
    }
    /**
     * @inheritDoc
     */
    protected function write(LogRecord $record): void
    {
        $filtered = $this->filterEmptyFields($record->formatted);
        $formatted = $this->marshaler->marshalItem($filtered);
        $this->client->putItem(['TableName' => $this->table, 'Item' => $formatted]);
    }
    /**
     * @param  mixed[] $record
     * @return mixed[]
     */
    protected function filterEmptyFields(array $record): array
    {
        return array_filter($record, function ($value) {
            return [] !== $value;
        });
    }
    /**
     * @inheritDoc
     */
    protected function getDefaultFormatter(): FormatterInterface
    {
        return new ScalarFormatter(self::DATE_FORMAT);
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Monolog\Handler;

use _ContaoManager\Monolog\Formatter\FormatterInterface;
/**
 * Interface to describe loggers that have a formatter
 *
 * @author Jordi Boggiano <j.boggiano@seld.be>
 */
interface FormattableHandlerInterface
{
    /**
     * Sets the formatter.
     *
     * @return HandlerInterface self
     */
    public function setFormatter(FormatterInterface $formatter): HandlerInterface;
    /**
     * Gets the formatter.
     */
    public function getFormatter(): FormatterInterface;
}
<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Monolog\Handler;

use _ContaoManager\Monolog\Formatter\LineFormatter;
use _ContaoManager\Monolog\Formatter\FormatterInterface;
use _ContaoManager\Monolog\Level;
use _ContaoManager\Monolog\LogRecord;
use _ContaoManager\Predis\Client as Predis;
use Redis;
/**
 * Sends the message to a Redis Pub/Sub channel using PUBLISH
 *
 * usage example:
 *
 *   $log = new Logger('application');
 *   $redis = new RedisPubSubHandler(new Predis\Client("tcp://localhost:6379"), "logs", Level::Warning);
 *   $log->pushHandler($redis);
 *
 * @author Gaëtan Faugère <gaetan@fauge.re>
 */
class RedisPubSubHandler extends AbstractProcessingHandler
{
    /** @var Predis<Predis>|Redis */
    private Predis|Redis $redisClient;
    private string $channelKey;
    /**
     * @param Predis<Predis>|Redis $redis The redis instance
     * @param string               $key   The channel key to publish records to
     */
    public function __construct(Predis|Redis $redis, string $key, int|string|Level $level = Level::Debug, bool $bubble = \true)
    {
        $this->redisClient = $redis;
        $this->channelKey = $key;
        parent::__construct($level, $bubble);
    }
    /**
     * @inheritDoc
     */
    protected function write(LogRecord $record): void
    {
        $this->redisClient->publish($this->channelKey, $record->formatted);
    }
    /**
     * @inheritDoc
     */
    protected function getDefaultFormatter(): FormatterInterface
    {
        return new LineFormatter();
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Monolog\Handler;

use _ContaoManager\Monolog\Formatter\FormatterInterface;
use _ContaoManager\Monolog\Formatter\HtmlFormatter;
use _ContaoManager\Monolog\LogRecord;
/**
 * Base class for all mail handlers
 *
 * @author Gyula Sallai
 */
abstract class MailHandler extends AbstractProcessingHandler
{
    /**
     * @inheritDoc
     */
    public function handleBatch(array $records): void
    {
        $messages = [];
        foreach ($records as $record) {
            if ($record->level->isLowerThan($this->level)) {
                continue;
            }
            $message = $this->processRecord($record);
            $messages[] = $message;
        }
        if (\count($messages) > 0) {
            $this->send((string) $this->getFormatter()->formatBatch($messages), $messages);
        }
    }
    /**
     * Send a mail with the given content
     *
     * @param string $content formatted email body to be sent
     * @param array  $records the array of log records that formed this content
     *
     * @phpstan-param non-empty-array<LogRecord> $records
     */
    abstract protected function send(string $content, array $records): void;
    /**
     * @inheritDoc
     */
    protected function write(LogRecord $record): void
    {
        $this->send((string) $record->formatted, [$record]);
    }
    /**
     * @phpstan-param non-empty-array<LogRecord> $records
     */
    protected function getHighestRecord(array $records): LogRecord
    {
        $highestRecord = null;
        foreach ($records as $record) {
            if ($highestRecord === null || $record->level->isHigherThan($highestRecord->level)) {
                $highestRecord = $record;
            }
        }
        return $highestRecord;
    }
    protected function isHtmlBody(string $body): bool
    {
        return ($body[0] ?? null) === '<';
    }
    /**
     * Gets the default formatter.
     */
    protected function getDefaultFormatter(): FormatterInterface
    {
        return new HtmlFormatter();
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Monolog\Handler;

use _ContaoManager\Monolog\Level;
use _ContaoManager\Monolog\Utils;
use _ContaoManager\Monolog\LogRecord;
/**
 * Stores to any stream resource
 *
 * Can be used to store into php://stderr, remote and local files, etc.
 *
 * @author Jordi Boggiano <j.boggiano@seld.be>
 */
class StreamHandler extends AbstractProcessingHandler
{
    protected const MAX_CHUNK_SIZE = 2147483647;
    /** 10MB */
    protected const DEFAULT_CHUNK_SIZE = 10 * 1024 * 1024;
    protected int $streamChunkSize;
    /** @var resource|null */
    protected $stream;
    protected string|null $url = null;
    private string|null $errorMessage = null;
    protected int|null $filePermission;
    protected bool $useLocking;
    protected string $fileOpenMode;
    /** @var true|null */
    private bool|null $dirCreated = null;
    private bool $retrying = \false;
    private int|null $inodeUrl = null;
    /**
     * @param resource|string $stream         If a missing path can't be created, an UnexpectedValueException will be thrown on first write
     * @param int|null        $filePermission Optional file permissions (default (0644) are only for owner read/write)
     * @param bool            $useLocking     Try to lock log file before doing any writes
     * @param string          $fileOpenMode   The fopen() mode used when opening a file, if $stream is a file path
     *
     * @throws \InvalidArgumentException If stream is not a resource or string
     */
    public function __construct($stream, int|string|Level $level = Level::Debug, bool $bubble = \true, ?int $filePermission = null, bool $useLocking = \false, string $fileOpenMode = 'a')
    {
        parent::__construct($level, $bubble);
        if (($phpMemoryLimit = Utils::expandIniShorthandBytes(\ini_get('memory_limit'))) !== \false) {
            if ($phpMemoryLimit > 0) {
                // use max 10% of allowed memory for the chunk size, and at least 100KB
                $this->streamChunkSize = min(static::MAX_CHUNK_SIZE, max((int) ($phpMemoryLimit / 10), 100 * 1024));
            } else {
                // memory is unlimited, set to the default 10MB
                $this->streamChunkSize = static::DEFAULT_CHUNK_SIZE;
            }
        } else {
            // no memory limit information, set to the default 10MB
            $this->streamChunkSize = static::DEFAULT_CHUNK_SIZE;
        }
        if (\is_resource($stream)) {
            $this->stream = $stream;
            stream_set_chunk_size($this->stream, $this->streamChunkSize);
        } elseif (\is_string($stream)) {
            $this->url = Utils::canonicalizePath($stream);
        } else {
            throw new \InvalidArgumentException('A stream must either be a resource or a string.');
        }
        $this->fileOpenMode = $fileOpenMode;
        $this->filePermission = $filePermission;
        $this->useLocking = $useLocking;
    }
    /**
     * @inheritDoc
     */
    public function reset(): void
    {
        parent::reset();
        // auto-close on reset to make sure we periodically close the file in long running processes
        // as long as they correctly call reset() between jobs
        if ($this->url !== null && $this->url !== 'php://memory') {
            $this->close();
        }
    }
    /**
     * @inheritDoc
     */
    public function close(): void
    {
        if (null !== $this->url && \is_resource($this->stream)) {
            fclose($this->stream);
        }
        $this->stream = null;
        $this->dirCreated = null;
    }
    /**
     * Return the currently active stream if it is open
     *
     * @return resource|null
     */
    public function getStream()
    {
        return $this->stream;
    }
    /**
     * Return the stream URL if it was configured with a URL and not an active resource
     */
    public function getUrl(): ?string
    {
        return $this->url;
    }
    public function getStreamChunkSize(): int
    {
        return $this->streamChunkSize;
    }
    /**
     * @inheritDoc
     */
    protected function write(LogRecord $record): void
    {
        if ($this->hasUrlInodeWasChanged()) {
            $this->close();
            $this->write($record);
            return;
        }
        if (!\is_resource($this->stream)) {
            $url = $this->url;
            if (null === $url || '' === $url) {
                throw new \LogicException('Missing stream url, the stream can not be opened. This may be caused by a premature call to close().' . Utils::getRecordMessageForException($record));
            }
            $this->createDir($url);
            $this->errorMessage = null;
            set_error_handler($this->customErrorHandler(...));
            try {
                $stream = fopen($url, $this->fileOpenMode);
                if ($this->filePermission !== null) {
                    @chmod($url, $this->filePermission);
                }
            } finally {
                restore_error_handler();
            }
            if (!\is_resource($stream)) {
                $this->stream = null;
                throw new \UnexpectedValueException(sprintf('The stream or file "%s" could not be opened in append mode: ' . $this->errorMessage, $url) . Utils::getRecordMessageForException($record));
            }
            stream_set_chunk_size($stream, $this->streamChunkSize);
            $this->stream = $stream;
            $this->inodeUrl = $this->getInodeFromUrl();
        }
        $stream = $this->stream;
        if ($this->useLocking) {
            // ignoring errors here, there's not much we can do about them
            flock($stream, \LOCK_EX);
        }
        $this->errorMessage = null;
        set_error_handler($this->customErrorHandler(...));
        try {
            $this->streamWrite($stream, $record);
        } finally {
            restore_error_handler();
        }
        if ($this->errorMessage !== null) {
            $error = $this->errorMessage;
            // close the resource if possible to reopen it, and retry the failed write
            if (!$this->retrying && $this->url !== null && $this->url !== 'php://memory') {
                $this->retrying = \true;
                $this->close();
                $this->write($record);
                return;
            }
            throw new \UnexpectedValueException('Writing to the log file failed: ' . $error . Utils::getRecordMessageForException($record));
        }
        $this->retrying = \false;
        if ($this->useLocking) {
            flock($stream, \LOCK_UN);
        }
    }
    /**
     * Write to stream
     * @param resource $stream
     */
    protected function streamWrite($stream, LogRecord $record): void
    {
        fwrite($stream, (string) $record->formatted);
    }
    /**
     * @return true
     */
    private function customErrorHandler(int $code, string $msg): bool
    {
        $this->errorMessage = preg_replace('{^(fopen|mkdir|fwrite)\(.*?\): }', '', $msg);
        return \true;
    }
    private function getDirFromStream(string $stream): ?string
    {
        $pos = strpos($stream, '://');
        if ($pos === \false) {
            return \dirname($stream);
        }
        if ('file://' === substr($stream, 0, 7)) {
            return \dirname(substr($stream, 7));
        }
        return null;
    }
    private function createDir(string $url): void
    {
        // Do not try to create dir if it has already been tried.
        if (\true === $this->dirCreated) {
            return;
        }
        $dir = $this->getDirFromStream($url);
        if (null !== $dir && !is_dir($dir)) {
            $this->errorMessage = null;
            set_error_handler(function (...$args) {
                return $this->customErrorHandler(...$args);
            });
            $status = mkdir($dir, 0777, \true);
            restore_error_handler();
            if (\false === $status && !is_dir($dir) && strpos((string) $this->errorMessage, 'File exists') === \false) {
                throw new \UnexpectedValueException(sprintf('There is no existing directory at "%s" and it could not be created: ' . $this->errorMessage, $dir));
            }
        }
        $this->dirCreated = \true;
    }
    private function getInodeFromUrl(): ?int
    {
        if ($this->url === null || str_starts_with($this->url, 'php://')) {
            return null;
        }
        $inode = @fileinode($this->url);
        return $inode === \false ? null : $inode;
    }
    private function hasUrlInodeWasChanged(): bool
    {
        if ($this->inodeUrl === null || $this->retrying || $this->inodeUrl === $this->getInodeFromUrl()) {
            return \false;
        }
        $this->retrying = \true;
        return \true;
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Monolog\Handler;

use _ContaoManager\Monolog\Level;
use _ContaoManager\Monolog\Formatter\FormatterInterface;
use _ContaoManager\Monolog\Formatter\LogglyFormatter;
use CurlHandle;
use _ContaoManager\Monolog\LogRecord;
/**
 * Sends errors to Loggly.
 *
 * @author Przemek Sobstel <przemek@sobstel.org>
 * @author Adam Pancutt <adam@pancutt.com>
 * @author Gregory Barchard <gregory@barchard.net>
 */
class LogglyHandler extends AbstractProcessingHandler
{
    protected const HOST = 'logs-01.loggly.com';
    protected const ENDPOINT_SINGLE = 'inputs';
    protected const ENDPOINT_BATCH = 'bulk';
    /**
     * Caches the curl handlers for every given endpoint.
     *
     * @var CurlHandle[]
     */
    protected array $curlHandlers = [];
    protected string $token;
    /** @var string[] */
    protected array $tag = [];
    /**
     * @param string $token API token supplied by Loggly
     *
     * @throws MissingExtensionException If the curl extension is missing
     */
    public function __construct(string $token, int|string|Level $level = Level::Debug, bool $bubble = \true)
    {
        if (!\extension_loaded('curl')) {
            throw new MissingExtensionException('The curl extension is needed to use the LogglyHandler');
        }
        $this->token = $token;
        parent::__construct($level, $bubble);
    }
    /**
     * Loads and returns the shared curl handler for the given endpoint.
     */
    protected function getCurlHandler(string $endpoint): CurlHandle
    {
        if (!\array_key_exists($endpoint, $this->curlHandlers)) {
            $this->curlHandlers[$endpoint] = $this->loadCurlHandle($endpoint);
        }
        return $this->curlHandlers[$endpoint];
    }
    /**
     * Starts a fresh curl session for the given endpoint and returns its handler.
     */
    private function loadCurlHandle(string $endpoint): CurlHandle
    {
        $url = sprintf("https://%s/%s/%s/", static::HOST, $endpoint, $this->token);
        $ch = curl_init();
        curl_setopt($ch, \CURLOPT_URL, $url);
        curl_setopt($ch, \CURLOPT_POST, \true);
        curl_setopt($ch, \CURLOPT_RETURNTRANSFER, \true);
        return $ch;
    }
    /**
     * @param  string[]|string $tag
     * @return $this
     */
    public function setTag(string|array $tag): self
    {
        if ('' === $tag || [] === $tag) {
            $this->tag = [];
        } else {
            $this->tag = \is_array($tag) ? $tag : [$tag];
        }
        return $this;
    }
    /**
     * @param  string[]|string $tag
     * @return $this
     */
    public function addTag(string|array $tag): self
    {
        if ('' !== $tag) {
            $tag = \is_array($tag) ? $tag : [$tag];
            $this->tag = array_unique(array_merge($this->tag, $tag));
        }
        return $this;
    }
    protected function write(LogRecord $record): void
    {
        $this->send($record->formatted, static::ENDPOINT_SINGLE);
    }
    public function handleBatch(array $records): void
    {
        $level = $this->level;
        $records = array_filter($records, function ($record) use ($level) {
            return $record->level->value >= $level->value;
        });
        if (\count($records) > 0) {
            $this->send($this->getFormatter()->formatBatch($records), static::ENDPOINT_BATCH);
        }
    }
    protected function send(string $data, string $endpoint): void
    {
        $ch = $this->getCurlHandler($endpoint);
        $headers = ['Content-Type: application/json'];
        if (\count($this->tag) > 0) {
            $headers[] = 'X-LOGGLY-TAG: ' . implode(',', $this->tag);
        }
        curl_setopt($ch, \CURLOPT_POSTFIELDS, $data);
        curl_setopt($ch, \CURLOPT_HTTPHEADER, $headers);
        Curl\Util::execute($ch, 5);
    }
    protected function getDefaultFormatter(): FormatterInterface
    {
        return new LogglyFormatter();
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Monolog\Handler;

use _ContaoManager\Monolog\Formatter\FormatterInterface;
use _ContaoManager\Monolog\Level;
use _ContaoManager\Monolog\Utils;
use _ContaoManager\Monolog\Handler\Slack\SlackRecord;
use _ContaoManager\Monolog\LogRecord;
/**
 * Sends notifications through Slack Webhooks
 *
 * @author Haralan Dobrev <hkdobrev@gmail.com>
 * @see    https://api.slack.com/incoming-webhooks
 */
class SlackWebhookHandler extends AbstractProcessingHandler
{
    /**
     * Slack Webhook token
     *
     * @var non-empty-string
     */
    private string $webhookUrl;
    /**
     * Instance of the SlackRecord util class preparing data for Slack API.
     */
    private SlackRecord $slackRecord;
    /**
     * @param non-empty-string $webhookUrl             Slack Webhook URL
     * @param string|null $channel                Slack channel (encoded ID or name)
     * @param string|null $username               Name of a bot
     * @param bool        $useAttachment          Whether the message should be added to Slack as attachment (plain text otherwise)
     * @param string|null $iconEmoji              The emoji name to use (or null)
     * @param bool        $useShortAttachment     Whether the the context/extra messages added to Slack as attachments are in a short style
     * @param bool        $includeContextAndExtra Whether the attachment should include context and extra data
     * @param string[]    $excludeFields          Dot separated list of fields to exclude from slack message. E.g. ['context.field1', 'extra.field2']
     *
     * @throws MissingExtensionException If the curl extension is missing
     */
    public function __construct(string $webhookUrl, ?string $channel = null, ?string $username = null, bool $useAttachment = \true, ?string $iconEmoji = null, bool $useShortAttachment = \false, bool $includeContextAndExtra = \false, $level = Level::Critical, bool $bubble = \true, array $excludeFields = [])
    {
        if (!\extension_loaded('curl')) {
            throw new MissingExtensionException('The curl extension is needed to use the SlackWebhookHandler');
        }
        parent::__construct($level, $bubble);
        $this->webhookUrl = $webhookUrl;
        $this->slackRecord = new SlackRecord($channel, $username, $useAttachment, $iconEmoji, $useShortAttachment, $includeContextAndExtra, $excludeFields);
    }
    public function getSlackRecord(): SlackRecord
    {
        return $this->slackRecord;
    }
    public function getWebhookUrl(): string
    {
        return $this->webhookUrl;
    }
    /**
     * @inheritDoc
     */
    protected function write(LogRecord $record): void
    {
        $postData = $this->slackRecord->getSlackData($record);
        $postString = Utils::jsonEncode($postData);
        $ch = curl_init();
        $options = [\CURLOPT_URL => $this->webhookUrl, \CURLOPT_POST => \true, \CURLOPT_RETURNTRANSFER => \true, \CURLOPT_HTTPHEADER => ['Content-type: application/json'], \CURLOPT_POSTFIELDS => $postString];
        curl_setopt_array($ch, $options);
        Curl\Util::execute($ch);
    }
    public function setFormatter(FormatterInterface $formatter): HandlerInterface
    {
        parent::setFormatter($formatter);
        $this->slackRecord->setFormatter($formatter);
        return $this;
    }
    public function getFormatter(): FormatterInterface
    {
        $formatter = parent::getFormatter();
        $this->slackRecord->setFormatter($formatter);
        return $formatter;
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Monolog\Handler;

use _ContaoManager\Elastic\Transport\Exception\TransportException;
use _ContaoManager\Elastica\Document;
use _ContaoManager\Monolog\Formatter\FormatterInterface;
use _ContaoManager\Monolog\Formatter\ElasticaFormatter;
use _ContaoManager\Monolog\Level;
use _ContaoManager\Elastica\Client;
use _ContaoManager\Elastica\Exception\ExceptionInterface;
use _ContaoManager\Monolog\LogRecord;
/**
 * Elastic Search handler
 *
 * Usage example:
 *
 *    $client = new \Elastica\Client();
 *    $options = array(
 *        'index' => 'elastic_index_name',
 *        'type' => 'elastic_doc_type', Types have been removed in Elastica 7
 *    );
 *    $handler = new ElasticaHandler($client, $options);
 *    $log = new Logger('application');
 *    $log->pushHandler($handler);
 *
 * @author Jelle Vink <jelle.vink@gmail.com>
 * @phpstan-type Options array{
 *     index: string,
 *     type: string,
 *     ignore_error: bool
 * }
 * @phpstan-type InputOptions array{
 *     index?: string,
 *     type?: string,
 *     ignore_error?: bool
 * }
 */
class ElasticaHandler extends AbstractProcessingHandler
{
    protected Client $client;
    /**
     * @var mixed[] Handler config options
     * @phpstan-var Options
     */
    protected array $options;
    /**
     * @param Client  $client  Elastica Client object
     * @param mixed[] $options Handler configuration
     *
     * @phpstan-param InputOptions $options
     */
    public function __construct(Client $client, array $options = [], int|string|Level $level = Level::Debug, bool $bubble = \true)
    {
        parent::__construct($level, $bubble);
        $this->client = $client;
        $this->options = array_merge([
            'index' => 'monolog',
            // Elastic index name
            'type' => 'record',
            // Elastic document type
            'ignore_error' => \false,
        ], $options);
    }
    /**
     * @inheritDoc
     */
    protected function write(LogRecord $record): void
    {
        $this->bulkSend([$record->formatted]);
    }
    /**
     * @inheritDoc
     */
    public function setFormatter(FormatterInterface $formatter): HandlerInterface
    {
        if ($formatter instanceof ElasticaFormatter) {
            return parent::setFormatter($formatter);
        }
        throw new \InvalidArgumentException('ElasticaHandler is only compatible with ElasticaFormatter');
    }
    /**
     * @return mixed[]
     *
     * @phpstan-return Options
     */
    public function getOptions(): array
    {
        return $this->options;
    }
    /**
     * @inheritDoc
     */
    protected function getDefaultFormatter(): FormatterInterface
    {
        return new ElasticaFormatter($this->options['index'], $this->options['type']);
    }
    /**
     * @inheritDoc
     */
    public function handleBatch(array $records): void
    {
        $documents = $this->getFormatter()->formatBatch($records);
        $this->bulkSend($documents);
    }
    /**
     * Use Elasticsearch bulk API to send list of documents
     *
     * @param Document[] $documents
     *
     * @throws \RuntimeException
     */
    protected function bulkSend(array $documents): void
    {
        try {
            $this->client->addDocuments($documents);
        } catch (ExceptionInterface|TransportException $e) {
            if (!$this->options['ignore_error']) {
                throw new \RuntimeException("Error sending messages to Elasticsearch", 0, $e);
            }
        }
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Monolog\Handler;

use _ContaoManager\Monolog\LogRecord;
use Throwable;
/**
 * Forwards records to multiple handlers suppressing failures of each handler
 * and continuing through to give every handler a chance to succeed.
 *
 * @author Craig D'Amelio <craig@damelio.ca>
 */
class WhatFailureGroupHandler extends GroupHandler
{
    /**
     * @inheritDoc
     */
    public function handle(LogRecord $record): bool
    {
        if (\count($this->processors) > 0) {
            $record = $this->processRecord($record);
        }
        foreach ($this->handlers as $handler) {
            try {
                $handler->handle(clone $record);
            } catch (Throwable) {
                // What failure?
            }
        }
        return \false === $this->bubble;
    }
    /**
     * @inheritDoc
     */
    public function handleBatch(array $records): void
    {
        if (\count($this->processors) > 0) {
            $processed = [];
            foreach ($records as $record) {
                $processed[] = $this->processRecord($record);
            }
            $records = $processed;
        }
        foreach ($this->handlers as $handler) {
            try {
                $handler->handleBatch(array_map(fn($record) => clone $record, $records));
            } catch (Throwable) {
                // What failure?
            }
        }
    }
    /**
     * {@inheritDoc}
     */
    public function close(): void
    {
        foreach ($this->handlers as $handler) {
            try {
                $handler->close();
            } catch (\Throwable $e) {
                // What failure?
            }
        }
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Monolog\Handler;

use _ContaoManager\Monolog\Formatter\ChromePHPFormatter;
use _ContaoManager\Monolog\Formatter\FormatterInterface;
use _ContaoManager\Monolog\Level;
use _ContaoManager\Monolog\Utils;
use _ContaoManager\Monolog\LogRecord;
use _ContaoManager\Monolog\JsonSerializableDateTimeImmutable;
/**
 * Handler sending logs to the ChromePHP extension (http://www.chromephp.com/)
 *
 * This also works out of the box with Firefox 43+
 *
 * @author Christophe Coevoet <stof@notk.org>
 */
class ChromePHPHandler extends AbstractProcessingHandler
{
    use WebRequestRecognizerTrait;
    /**
     * Version of the extension
     */
    protected const VERSION = '4.0';
    /**
     * Header name
     */
    protected const HEADER_NAME = 'X-ChromeLogger-Data';
    /**
     * Regular expression to detect supported browsers (matches any Chrome, or Firefox 43+)
     */
    protected const USER_AGENT_REGEX = '{\b(?:Chrome/\d+(?:\.\d+)*|HeadlessChrome|Firefox/(?:4[3-9]|[5-9]\d|\d{3,})(?:\.\d)*)\b}';
    protected static bool $initialized = \false;
    /**
     * Tracks whether we sent too much data
     *
     * Chrome limits the headers to 4KB, so when we sent 3KB we stop sending
     */
    protected static bool $overflowed = \false;
    /** @var mixed[] */
    protected static array $json = ['version' => self::VERSION, 'columns' => ['label', 'log', 'backtrace', 'type'], 'rows' => []];
    protected static bool $sendHeaders = \true;
    public function __construct(int|string|Level $level = Level::Debug, bool $bubble = \true)
    {
        parent::__construct($level, $bubble);
    }
    /**
     * @inheritDoc
     */
    public function handleBatch(array $records): void
    {
        if (!$this->isWebRequest()) {
            return;
        }
        $messages = [];
        foreach ($records as $record) {
            if ($record->level < $this->level) {
                continue;
            }
            $message = $this->processRecord($record);
            $messages[] = $message;
        }
        if (\count($messages) > 0) {
            $messages = $this->getFormatter()->formatBatch($messages);
            self::$json['rows'] = array_merge(self::$json['rows'], $messages);
            $this->send();
        }
    }
    /**
     * @inheritDoc
     */
    protected function getDefaultFormatter(): FormatterInterface
    {
        return new ChromePHPFormatter();
    }
    /**
     * Creates & sends header for a record
     *
     * @see sendHeader()
     * @see send()
     */
    protected function write(LogRecord $record): void
    {
        if (!$this->isWebRequest()) {
            return;
        }
        self::$json['rows'][] = $record->formatted;
        $this->send();
    }
    /**
     * Sends the log header
     *
     * @see sendHeader()
     */
    protected function send(): void
    {
        if (self::$overflowed || !self::$sendHeaders) {
            return;
        }
        if (!self::$initialized) {
            self::$initialized = \true;
            self::$sendHeaders = $this->headersAccepted();
            if (!self::$sendHeaders) {
                return;
            }
            self::$json['request_uri'] = $_SERVER['REQUEST_URI'] ?? '';
        }
        $json = Utils::jsonEncode(self::$json, Utils::DEFAULT_JSON_FLAGS & ~\JSON_UNESCAPED_UNICODE, \true);
        $data = base64_encode($json);
        if (\strlen($data) > 3 * 1024) {
            self::$overflowed = \true;
            $record = new LogRecord(message: 'Incomplete logs, chrome header size limit reached', level: Level::Warning, channel: 'monolog', datetime: new JsonSerializableDateTimeImmutable(\true));
            self::$json['rows'][\count(self::$json['rows']) - 1] = $this->getFormatter()->format($record);
            $json = Utils::jsonEncode(self::$json, Utils::DEFAULT_JSON_FLAGS & ~\JSON_UNESCAPED_UNICODE, \true);
            $data = base64_encode($json);
        }
        if (trim($data) !== '') {
            $this->sendHeader(static::HEADER_NAME, $data);
        }
    }
    /**
     * Send header string to the client
     */
    protected function sendHeader(string $header, string $content): void
    {
        if (!headers_sent() && self::$sendHeaders) {
            header(sprintf('%s: %s', $header, $content));
        }
    }
    /**
     * Verifies if the headers are accepted by the current user agent
     */
    protected function headersAccepted(): bool
    {
        if (!isset($_SERVER['HTTP_USER_AGENT'])) {
            return \false;
        }
        return preg_match(static::USER_AGENT_REGEX, $_SERVER['HTTP_USER_AGENT']) === 1;
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Monolog\Handler\Slack;

use _ContaoManager\Monolog\Level;
use _ContaoManager\Monolog\Utils;
use _ContaoManager\Monolog\Formatter\NormalizerFormatter;
use _ContaoManager\Monolog\Formatter\FormatterInterface;
use _ContaoManager\Monolog\LogRecord;
/**
 * Slack record utility helping to log to Slack webhooks or API.
 *
 * @author Greg Kedzierski <greg@gregkedzierski.com>
 * @author Haralan Dobrev <hkdobrev@gmail.com>
 * @see    https://api.slack.com/incoming-webhooks
 * @see    https://api.slack.com/docs/message-attachments
 */
class SlackRecord
{
    public const COLOR_DANGER = 'danger';
    public const COLOR_WARNING = 'warning';
    public const COLOR_GOOD = 'good';
    public const COLOR_DEFAULT = '#e3e4e6';
    /**
     * Slack channel (encoded ID or name)
     */
    private string|null $channel;
    /**
     * Name of a bot
     */
    private string|null $username;
    /**
     * User icon e.g. 'ghost', 'http://example.com/user.png'
     */
    private string|null $userIcon;
    /**
     * Whether the message should be added to Slack as attachment (plain text otherwise)
     */
    private bool $useAttachment;
    /**
     * Whether the the context/extra messages added to Slack as attachments are in a short style
     */
    private bool $useShortAttachment;
    /**
     * Whether the attachment should include context and extra data
     */
    private bool $includeContextAndExtra;
    /**
     * Dot separated list of fields to exclude from slack message. E.g. ['context.field1', 'extra.field2']
     * @var string[]
     */
    private array $excludeFields;
    private FormatterInterface|null $formatter;
    private NormalizerFormatter $normalizerFormatter;
    /**
     * @param string[] $excludeFields
     */
    public function __construct(?string $channel = null, ?string $username = null, bool $useAttachment = \true, ?string $userIcon = null, bool $useShortAttachment = \false, bool $includeContextAndExtra = \false, array $excludeFields = [], FormatterInterface|null $formatter = null)
    {
        $this->setChannel($channel)->setUsername($username)->useAttachment($useAttachment)->setUserIcon($userIcon)->useShortAttachment($useShortAttachment)->includeContextAndExtra($includeContextAndExtra)->excludeFields($excludeFields)->setFormatter($formatter);
        if ($this->includeContextAndExtra) {
            $this->normalizerFormatter = new NormalizerFormatter();
        }
    }
    /**
     * Returns required data in format that Slack
     * is expecting.
     *
     * @phpstan-return mixed[]
     */
    public function getSlackData(LogRecord $record): array
    {
        $dataArray = [];
        if ($this->username !== null) {
            $dataArray['username'] = $this->username;
        }
        if ($this->channel !== null) {
            $dataArray['channel'] = $this->channel;
        }
        if ($this->formatter !== null && !$this->useAttachment) {
            $message = $this->formatter->format($record);
        } else {
            $message = $record->message;
        }
        $recordData = $this->removeExcludedFields($record);
        if ($this->useAttachment) {
            $attachment = ['fallback' => $message, 'text' => $message, 'color' => $this->getAttachmentColor($record->level), 'fields' => [], 'mrkdwn_in' => ['fields'], 'ts' => $recordData['datetime']->getTimestamp(), 'footer' => $this->username, 'footer_icon' => $this->userIcon];
            if ($this->useShortAttachment) {
                $attachment['title'] = $recordData['level_name'];
            } else {
                $attachment['title'] = 'Message';
                $attachment['fields'][] = $this->generateAttachmentField('Level', $recordData['level_name']);
            }
            if ($this->includeContextAndExtra) {
                foreach (['extra', 'context'] as $key) {
                    if (!isset($recordData[$key]) || \count($recordData[$key]) === 0) {
                        continue;
                    }
                    if ($this->useShortAttachment) {
                        $attachment['fields'][] = $this->generateAttachmentField($key, $recordData[$key]);
                    } else {
                        // Add all extra fields as individual fields in attachment
                        $attachment['fields'] = array_merge($attachment['fields'], $this->generateAttachmentFields($recordData[$key]));
                    }
                }
            }
            $dataArray['attachments'] = [$attachment];
        } else {
            $dataArray['text'] = $message;
        }
        if ($this->userIcon !== null) {
            if (\false !== $iconUrl = filter_var($this->userIcon, \FILTER_VALIDATE_URL)) {
                $dataArray['icon_url'] = $iconUrl;
            } else {
                $dataArray['icon_emoji'] = ":{$this->userIcon}:";
            }
        }
        return $dataArray;
    }
    /**
     * Returns a Slack message attachment color associated with
     * provided level.
     */
    public function getAttachmentColor(Level $level): string
    {
        return match ($level) {
            Level::Error, Level::Critical, Level::Alert, Level::Emergency => static::COLOR_DANGER,
            Level::Warning => static::COLOR_WARNING,
            Level::Info, Level::Notice => static::COLOR_GOOD,
            Level::Debug => static::COLOR_DEFAULT,
        };
    }
    /**
     * Stringifies an array of key/value pairs to be used in attachment fields
     *
     * @param mixed[] $fields
     */
    public function stringify(array $fields): string
    {
        /** @var array<array<mixed>|bool|float|int|string|null> $normalized */
        $normalized = $this->normalizerFormatter->normalizeValue($fields);
        $hasSecondDimension = \count(array_filter($normalized, 'is_array')) > 0;
        $hasOnlyNonNumericKeys = \count(array_filter(array_keys($normalized), 'is_numeric')) === 0;
        return $hasSecondDimension || $hasOnlyNonNumericKeys ? Utils::jsonEncode($normalized, \JSON_PRETTY_PRINT | Utils::DEFAULT_JSON_FLAGS) : Utils::jsonEncode($normalized, Utils::DEFAULT_JSON_FLAGS);
    }
    /**
     * Channel used by the bot when posting
     *
     * @param  ?string $channel
     * @return $this
     */
    public function setChannel(?string $channel = null): self
    {
        $this->channel = $channel;
        return $this;
    }
    /**
     * Username used by the bot when posting
     *
     * @param  ?string $username
     * @return $this
     */
    public function setUsername(?string $username = null): self
    {
        $this->username = $username;
        return $this;
    }
    /**
     * @return $this
     */
    public function useAttachment(bool $useAttachment = \true): self
    {
        $this->useAttachment = $useAttachment;
        return $this;
    }
    /**
     * @return $this
     */
    public function setUserIcon(?string $userIcon = null): self
    {
        $this->userIcon = $userIcon;
        if (\is_string($userIcon)) {
            $this->userIcon = trim($userIcon, ':');
        }
        return $this;
    }
    /**
     * @return $this
     */
    public function useShortAttachment(bool $useShortAttachment = \false): self
    {
        $this->useShortAttachment = $useShortAttachment;
        return $this;
    }
    /**
     * @return $this
     */
    public function includeContextAndExtra(bool $includeContextAndExtra = \false): self
    {
        $this->includeContextAndExtra = $includeContextAndExtra;
        if ($this->includeContextAndExtra) {
            $this->normalizerFormatter = new NormalizerFormatter();
        }
        return $this;
    }
    /**
     * @param  string[] $excludeFields
     * @return $this
     */
    public function excludeFields(array $excludeFields = []): self
    {
        $this->excludeFields = $excludeFields;
        return $this;
    }
    /**
     * @return $this
     */
    public function setFormatter(?FormatterInterface $formatter = null): self
    {
        $this->formatter = $formatter;
        return $this;
    }
    /**
     * Generates attachment field
     *
     * @param string|mixed[] $value
     *
     * @return array{title: string, value: string, short: false}
     */
    private function generateAttachmentField(string $title, $value): array
    {
        $value = \is_array($value) ? sprintf('```%s```', substr($this->stringify($value), 0, 1990)) : $value;
        return ['title' => ucfirst($title), 'value' => $value, 'short' => \false];
    }
    /**
     * Generates a collection of attachment fields from array
     *
     * @param mixed[] $data
     *
     * @return array<array{title: string, value: string, short: false}>
     */
    private function generateAttachmentFields(array $data): array
    {
        /** @var array<array<mixed>|string> $normalized */
        $normalized = $this->normalizerFormatter->normalizeValue($data);
        $fields = [];
        foreach ($normalized as $key => $value) {
            $fields[] = $this->generateAttachmentField((string) $key, $value);
        }
        return $fields;
    }
    /**
     * Get a copy of record with fields excluded according to $this->excludeFields
     *
     * @return mixed[]
     */
    private function removeExcludedFields(LogRecord $record): array
    {
        $recordData = $record->toArray();
        foreach ($this->excludeFields as $field) {
            $keys = explode('.', $field);
            $node =& $recordData;
            $lastKey = end($keys);
            foreach ($keys as $key) {
                if (!isset($node[$key])) {
                    break;
                }
                if ($lastKey === $key) {
                    unset($node[$key]);
                    break;
                }
                $node =& $node[$key];
            }
        }
        return $recordData;
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Monolog\Handler;

use _ContaoManager\Monolog\Level;
use _ContaoManager\Psr\Log\LoggerInterface;
use _ContaoManager\Monolog\Formatter\FormatterInterface;
use _ContaoManager\Monolog\LogRecord;
/**
 * Proxies log messages to an existing PSR-3 compliant logger.
 *
 * If a formatter is configured, the formatter's output MUST be a string and the
 * formatted message will be fed to the wrapped PSR logger instead of the original
 * log record's message.
 *
 * @author Michael Moussa <michael.moussa@gmail.com>
 */
class PsrHandler extends AbstractHandler implements FormattableHandlerInterface
{
    /**
     * PSR-3 compliant logger
     */
    protected LoggerInterface $logger;
    protected FormatterInterface|null $formatter = null;
    private bool $includeExtra;
    /**
     * @param LoggerInterface $logger The underlying PSR-3 compliant logger to which messages will be proxied
     */
    public function __construct(LoggerInterface $logger, int|string|Level $level = Level::Debug, bool $bubble = \true, bool $includeExtra = \false)
    {
        parent::__construct($level, $bubble);
        $this->logger = $logger;
        $this->includeExtra = $includeExtra;
    }
    /**
     * @inheritDoc
     */
    public function handle(LogRecord $record): bool
    {
        if (!$this->isHandling($record)) {
            return \false;
        }
        $message = $this->formatter !== null ? (string) $this->formatter->format($record) : $record->message;
        $context = $this->includeExtra ? [...$record->extra, ...$record->context] : $record->context;
        $this->logger->log($record->level->toPsrLogLevel(), $message, $context);
        return \false === $this->bubble;
    }
    /**
     * Sets the formatter.
     */
    public function setFormatter(FormatterInterface $formatter): HandlerInterface
    {
        $this->formatter = $formatter;
        return $this;
    }
    /**
     * Gets the formatter.
     */
    public function getFormatter(): FormatterInterface
    {
        if ($this->formatter === null) {
            throw new \LogicException('No formatter has been set and this handler does not have a default formatter');
        }
        return $this->formatter;
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Monolog\Handler;

use _ContaoManager\Monolog\Level;
use _ContaoManager\Monolog\Utils;
use _ContaoManager\Monolog\Formatter\NormalizerFormatter;
use _ContaoManager\Monolog\Formatter\FormatterInterface;
use _ContaoManager\Monolog\LogRecord;
/**
 * Class to record a log on a NewRelic application.
 * Enabling New Relic High Security mode may prevent capture of useful information.
 *
 * This handler requires a NormalizerFormatter to function and expects an array in $record->formatted
 *
 * @see https://docs.newrelic.com/docs/agents/php-agent
 * @see https://docs.newrelic.com/docs/accounts-partnerships/accounts/security/high-security
 */
class NewRelicHandler extends AbstractProcessingHandler
{
    /**
     * @inheritDoc
     */
    public function __construct(
        int|string|Level $level = Level::Error,
        bool $bubble = \true,
        /**
         * Name of the New Relic application that will receive logs from this handler.
         */
        protected string|null $appName = null,
        /**
         * Some context and extra data is passed into the handler as arrays of values. Do we send them as is
         * (useful if we are using the API), or explode them for display on the NewRelic RPM website?
         */
        protected bool $explodeArrays = \false,
        /**
         * Name of the current transaction
         */
        protected string|null $transactionName = null
    )
    {
        parent::__construct($level, $bubble);
    }
    /**
     * @inheritDoc
     */
    protected function write(LogRecord $record): void
    {
        if (!$this->isNewRelicEnabled()) {
            throw new MissingExtensionException('The newrelic PHP extension is required to use the NewRelicHandler');
        }
        if (null !== $appName = $this->getAppName($record->context)) {
            $this->setNewRelicAppName($appName);
        }
        if (null !== $transactionName = $this->getTransactionName($record->context)) {
            $this->setNewRelicTransactionName($transactionName);
            unset($record->formatted['context']['transaction_name']);
        }
        if (isset($record->context['exception']) && $record->context['exception'] instanceof \Throwable) {
            newrelic_notice_error($record->message, $record->context['exception']);
            unset($record->formatted['context']['exception']);
        } else {
            newrelic_notice_error($record->message);
        }
        if (isset($record->formatted['context']) && \is_array($record->formatted['context'])) {
            foreach ($record->formatted['context'] as $key => $parameter) {
                if (\is_array($parameter) && $this->explodeArrays) {
                    foreach ($parameter as $paramKey => $paramValue) {
                        $this->setNewRelicParameter('context_' . $key . '_' . $paramKey, $paramValue);
                    }
                } else {
                    $this->setNewRelicParameter('context_' . $key, $parameter);
                }
            }
        }
        if (isset($record->formatted['extra']) && \is_array($record->formatted['extra'])) {
            foreach ($record->formatted['extra'] as $key => $parameter) {
                if (\is_array($parameter) && $this->explodeArrays) {
                    foreach ($parameter as $paramKey => $paramValue) {
                        $this->setNewRelicParameter('extra_' . $key . '_' . $paramKey, $paramValue);
                    }
                } else {
                    $this->setNewRelicParameter('extra_' . $key, $parameter);
                }
            }
        }
    }
    /**
     * Checks whether the NewRelic extension is enabled in the system.
     */
    protected function isNewRelicEnabled(): bool
    {
        return \extension_loaded('newrelic');
    }
    /**
     * Returns the appname where this log should be sent. Each log can override the default appname, set in this
     * handler's constructor, by providing the appname in it's context.
     *
     * @param mixed[] $context
     */
    protected function getAppName(array $context): ?string
    {
        if (isset($context['appname'])) {
            return $context['appname'];
        }
        return $this->appName;
    }
    /**
     * Returns the name of the current transaction. Each log can override the default transaction name, set in this
     * handler's constructor, by providing the transaction_name in it's context
     *
     * @param mixed[] $context
     */
    protected function getTransactionName(array $context): ?string
    {
        if (isset($context['transaction_name'])) {
            return $context['transaction_name'];
        }
        return $this->transactionName;
    }
    /**
     * Sets the NewRelic application that should receive this log.
     */
    protected function setNewRelicAppName(string $appName): void
    {
        newrelic_set_appname($appName);
    }
    /**
     * Overwrites the name of the current transaction
     */
    protected function setNewRelicTransactionName(string $transactionName): void
    {
        newrelic_name_transaction($transactionName);
    }
    /**
     * @param mixed $value
     */
    protected function setNewRelicParameter(string $key, $value): void
    {
        if (null === $value || \is_scalar($value)) {
            newrelic_add_custom_parameter($key, $value);
        } else {
            newrelic_add_custom_parameter($key, Utils::jsonEncode($value, null, \true));
        }
    }
    /**
     * @inheritDoc
     */
    protected function getDefaultFormatter(): FormatterInterface
    {
        return new NormalizerFormatter();
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Monolog\Handler;

use _ContaoManager\Monolog\ResettableInterface;
use _ContaoManager\Monolog\Processor\ProcessorInterface;
use _ContaoManager\Monolog\LogRecord;
/**
 * Helper trait for implementing ProcessableInterface
 *
 * @author Jordi Boggiano <j.boggiano@seld.be>
 */
trait ProcessableHandlerTrait
{
    /**
     * @var callable[]
     * @phpstan-var array<(callable(LogRecord): LogRecord)|ProcessorInterface>
     */
    protected array $processors = [];
    /**
     * @inheritDoc
     */
    public function pushProcessor(callable $callback): HandlerInterface
    {
        array_unshift($this->processors, $callback);
        return $this;
    }
    /**
     * @inheritDoc
     */
    public function popProcessor(): callable
    {
        if (\count($this->processors) === 0) {
            throw new \LogicException('You tried to pop from an empty processor stack.');
        }
        return array_shift($this->processors);
    }
    protected function processRecord(LogRecord $record): LogRecord
    {
        foreach ($this->processors as $processor) {
            $record = $processor($record);
        }
        return $record;
    }
    protected function resetProcessors(): void
    {
        foreach ($this->processors as $processor) {
            if ($processor instanceof ResettableInterface) {
                $processor->reset();
            }
        }
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Monolog\Handler;

use _ContaoManager\Monolog\LogRecord;
/**
 * Interface that all Monolog Handlers must implement
 *
 * @author Jordi Boggiano <j.boggiano@seld.be>
 */
interface HandlerInterface
{
    /**
     * Checks whether the given record will be handled by this handler.
     *
     * This is mostly done for performance reasons, to avoid calling processors for nothing.
     *
     * Handlers should still check the record levels within handle(), returning false in isHandling()
     * is no guarantee that handle() will not be called, and isHandling() might not be called
     * for a given record.
     *
     * @param LogRecord $record Partial log record having only a level initialized
     */
    public function isHandling(LogRecord $record): bool;
    /**
     * Handles a record.
     *
     * All records may be passed to this method, and the handler should discard
     * those that it does not want to handle.
     *
     * The return value of this function controls the bubbling process of the handler stack.
     * Unless the bubbling is interrupted (by returning true), the Logger class will keep on
     * calling further handlers in the stack with a given log record.
     *
     * @param  LogRecord $record The record to handle
     * @return bool      true means that this handler handled the record, and that bubbling is not permitted.
     *                   false means the record was either not processed or that this handler allows bubbling.
     */
    public function handle(LogRecord $record): bool;
    /**
     * Handles a set of records at once.
     *
     * @param array<LogRecord> $records The records to handle
     */
    public function handleBatch(array $records): void;
    /**
     * Closes the handler.
     *
     * Ends a log cycle and frees all resources used by the handler.
     *
     * Closing a Handler means flushing all buffers and freeing any open resources/handles.
     *
     * Implementations have to be idempotent (i.e. it should be possible to call close several times without breakage)
     * and ideally handlers should be able to reopen themselves on handle() after they have been closed.
     *
     * This is useful at the end of a request and will be called automatically when the object
     * is destroyed if you extend Monolog\Handler\Handler.
     *
     * If you are thinking of calling this method yourself, most likely you should be
     * calling ResettableInterface::reset instead. Have a look.
     */
    public function close(): void;
}
<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Monolog\Handler;

use _ContaoManager\Monolog\Formatter\FormatterInterface;
use _ContaoManager\Monolog\Level;
use _ContaoManager\Monolog\Utils;
use _ContaoManager\Monolog\Handler\Slack\SlackRecord;
use _ContaoManager\Monolog\LogRecord;
/**
 * Sends notifications through Slack API
 *
 * @author Greg Kedzierski <greg@gregkedzierski.com>
 * @see    https://api.slack.com/
 */
class SlackHandler extends SocketHandler
{
    /**
     * Slack API token
     */
    private string $token;
    /**
     * Instance of the SlackRecord util class preparing data for Slack API.
     */
    private SlackRecord $slackRecord;
    /**
     * @param  string                    $token                  Slack API token
     * @param  string                    $channel                Slack channel (encoded ID or name)
     * @param  string|null               $username               Name of a bot
     * @param  bool                      $useAttachment          Whether the message should be added to Slack as attachment (plain text otherwise)
     * @param  string|null               $iconEmoji              The emoji name to use (or null)
     * @param  bool                      $useShortAttachment     Whether the context/extra messages added to Slack as attachments are in a short style
     * @param  bool                      $includeContextAndExtra Whether the attachment should include context and extra data
     * @param  string[]                  $excludeFields          Dot separated list of fields to exclude from slack message. E.g. ['context.field1', 'extra.field2']
     * @throws MissingExtensionException If no OpenSSL PHP extension configured
     */
    public function __construct(string $token, string $channel, ?string $username = null, bool $useAttachment = \true, ?string $iconEmoji = null, $level = Level::Critical, bool $bubble = \true, bool $useShortAttachment = \false, bool $includeContextAndExtra = \false, array $excludeFields = [], bool $persistent = \false, float $timeout = 0.0, float $writingTimeout = 10.0, ?float $connectionTimeout = null, ?int $chunkSize = null)
    {
        if (!\extension_loaded('openssl')) {
            throw new MissingExtensionException('The OpenSSL PHP extension is required to use the SlackHandler');
        }
        parent::__construct('ssl://slack.com:443', $level, $bubble, $persistent, $timeout, $writingTimeout, $connectionTimeout, $chunkSize);
        $this->slackRecord = new SlackRecord($channel, $username, $useAttachment, $iconEmoji, $useShortAttachment, $includeContextAndExtra, $excludeFields);
        $this->token = $token;
    }
    public function getSlackRecord(): SlackRecord
    {
        return $this->slackRecord;
    }
    public function getToken(): string
    {
        return $this->token;
    }
    /**
     * @inheritDoc
     */
    protected function generateDataStream(LogRecord $record): string
    {
        $content = $this->buildContent($record);
        return $this->buildHeader($content) . $content;
    }
    /**
     * Builds the body of API call
     */
    private function buildContent(LogRecord $record): string
    {
        $dataArray = $this->prepareContentData($record);
        return http_build_query($dataArray);
    }
    /**
     * @return string[]
     */
    protected function prepareContentData(LogRecord $record): array
    {
        $dataArray = $this->slackRecord->getSlackData($record);
        $dataArray['token'] = $this->token;
        if (isset($dataArray['attachments']) && \is_array($dataArray['attachments']) && \count($dataArray['attachments']) > 0) {
            $dataArray['attachments'] = Utils::jsonEncode($dataArray['attachments']);
        }
        return $dataArray;
    }
    /**
     * Builds the header of the API Call
     */
    private function buildHeader(string $content): string
    {
        $header = "POST /api/chat.postMessage HTTP/1.1\r\n";
        $header .= "Host: slack.com\r\n";
        $header .= "Content-Type: application/x-www-form-urlencoded\r\n";
        $header .= "Content-Length: " . \strlen($content) . "\r\n";
        $header .= "\r\n";
        return $header;
    }
    /**
     * @inheritDoc
     */
    protected function write(LogRecord $record): void
    {
        parent::write($record);
        $this->finalizeWrite();
    }
    /**
     * Finalizes the request by reading some bytes and then closing the socket
     *
     * If we do not read some but close the socket too early, slack sometimes
     * drops the request entirely.
     */
    protected function finalizeWrite(): void
    {
        $res = $this->getResource();
        if (\is_resource($res)) {
            @fread($res, 2048);
        }
        $this->closeSocket();
    }
    public function setFormatter(FormatterInterface $formatter): HandlerInterface
    {
        parent::setFormatter($formatter);
        $this->slackRecord->setFormatter($formatter);
        return $this;
    }
    public function getFormatter(): FormatterInterface
    {
        $formatter = parent::getFormatter();
        $this->slackRecord->setFormatter($formatter);
        return $formatter;
    }
    /**
     * Channel used by the bot when posting
     *
     * @return $this
     */
    public function setChannel(string $channel): self
    {
        $this->slackRecord->setChannel($channel);
        return $this;
    }
    /**
     * Username used by the bot when posting
     *
     * @return $this
     */
    public function setUsername(string $username): self
    {
        $this->slackRecord->setUsername($username);
        return $this;
    }
    /**
     * @return $this
     */
    public function useAttachment(bool $useAttachment): self
    {
        $this->slackRecord->useAttachment($useAttachment);
        return $this;
    }
    /**
     * @return $this
     */
    public function setIconEmoji(string $iconEmoji): self
    {
        $this->slackRecord->setUserIcon($iconEmoji);
        return $this;
    }
    /**
     * @return $this
     */
    public function useShortAttachment(bool $useShortAttachment): self
    {
        $this->slackRecord->useShortAttachment($useShortAttachment);
        return $this;
    }
    /**
     * @return $this
     */
    public function includeContextAndExtra(bool $includeContextAndExtra): self
    {
        $this->slackRecord->includeContextAndExtra($includeContextAndExtra);
        return $this;
    }
    /**
     * @param  string[] $excludeFields
     * @return $this
     */
    public function excludeFields(array $excludeFields): self
    {
        $this->slackRecord->excludeFields($excludeFields);
        return $this;
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Monolog\Handler;

use _ContaoManager\Monolog\Formatter\FormatterInterface;
use _ContaoManager\Monolog\Formatter\LineFormatter;
use _ContaoManager\Monolog\Level;
use _ContaoManager\Monolog\LogRecord;
/**
 * Sends logs to Fleep.io using Webhook integrations
 *
 * You'll need a Fleep.io account to use this handler.
 *
 * @see https://fleep.io/integrations/webhooks/ Fleep Webhooks Documentation
 * @author Ando Roots <ando@sqroot.eu>
 */
class FleepHookHandler extends SocketHandler
{
    protected const FLEEP_HOST = 'fleep.io';
    protected const FLEEP_HOOK_URI = '/hook/';
    /**
     * @var string Webhook token (specifies the conversation where logs are sent)
     */
    protected string $token;
    /**
     * Construct a new Fleep.io Handler.
     *
     * For instructions on how to create a new web hook in your conversations
     * see https://fleep.io/integrations/webhooks/
     *
     * @param  string                    $token Webhook token
     * @throws MissingExtensionException if OpenSSL is missing
     */
    public function __construct(string $token, $level = Level::Debug, bool $bubble = \true, bool $persistent = \false, float $timeout = 0.0, float $writingTimeout = 10.0, ?float $connectionTimeout = null, ?int $chunkSize = null)
    {
        if (!\extension_loaded('openssl')) {
            throw new MissingExtensionException('The OpenSSL PHP extension is required to use the FleepHookHandler');
        }
        $this->token = $token;
        $connectionString = 'ssl://' . static::FLEEP_HOST . ':443';
        parent::__construct($connectionString, $level, $bubble, $persistent, $timeout, $writingTimeout, $connectionTimeout, $chunkSize);
    }
    /**
     * Returns the default formatter to use with this handler
     *
     * Overloaded to remove empty context and extra arrays from the end of the log message.
     *
     * @return LineFormatter
     */
    protected function getDefaultFormatter(): FormatterInterface
    {
        return new LineFormatter(null, null, \true, \true);
    }
    /**
     * Handles a log record
     */
    public function write(LogRecord $record): void
    {
        parent::write($record);
        $this->closeSocket();
    }
    /**
     * @inheritDoc
     */
    protected function generateDataStream(LogRecord $record): string
    {
        $content = $this->buildContent($record);
        return $this->buildHeader($content) . $content;
    }
    /**
     * Builds the header of the API Call
     */
    private function buildHeader(string $content): string
    {
        $header = "POST " . static::FLEEP_HOOK_URI . $this->token . " HTTP/1.1\r\n";
        $header .= "Host: " . static::FLEEP_HOST . "\r\n";
        $header .= "Content-Type: application/x-www-form-urlencoded\r\n";
        $header .= "Content-Length: " . \strlen($content) . "\r\n";
        $header .= "\r\n";
        return $header;
    }
    /**
     * Builds the body of API call
     */
    private function buildContent(LogRecord $record): string
    {
        $dataArray = ['message' => $record->formatted];
        return http_build_query($dataArray);
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Monolog\Handler;

use _ContaoManager\Monolog\Level;
use _ContaoManager\Psr\Log\LogLevel;
use _ContaoManager\Monolog\Logger;
use _ContaoManager\Monolog\LogRecord;
/**
 * Blackhole
 *
 * Any record it can handle will be thrown away. This can be used
 * to put on top of an existing stack to override it temporarily.
 *
 * @author Jordi Boggiano <j.boggiano@seld.be>
 */
class NullHandler extends Handler
{
    private Level $level;
    /**
     * @param string|int|Level $level The minimum logging level at which this handler will be triggered
     *
     * @phpstan-param value-of<Level::VALUES>|value-of<Level::NAMES>|Level|LogLevel::* $level
     */
    public function __construct(string|int|Level $level = Level::Debug)
    {
        $this->level = Logger::toMonologLevel($level);
    }
    /**
     * @inheritDoc
     */
    public function isHandling(LogRecord $record): bool
    {
        return $record->level->value >= $this->level->value;
    }
    /**
     * @inheritDoc
     */
    public function handle(LogRecord $record): bool
    {
        return $record->level->value >= $this->level->value;
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Monolog\Handler;

use _ContaoManager\Gelf\Message as GelfMessage;
use _ContaoManager\Monolog\Level;
use _ContaoManager\Monolog\Formatter\FormatterInterface;
use _ContaoManager\Monolog\Formatter\JsonFormatter;
use _ContaoManager\PhpAmqpLib\Message\AMQPMessage;
use _ContaoManager\PhpAmqpLib\Channel\AMQPChannel;
use AMQPExchange;
use _ContaoManager\Monolog\LogRecord;
class AmqpHandler extends AbstractProcessingHandler
{
    protected AMQPExchange|AMQPChannel $exchange;
    /** @var array<string, mixed> */
    private array $extraAttributes = [];
    protected string $exchangeName;
    /**
     * @param AMQPExchange|AMQPChannel $exchange     AMQPExchange (php AMQP ext) or PHP AMQP lib channel, ready for use
     * @param string|null              $exchangeName Optional exchange name, for AMQPChannel (PhpAmqpLib) only
     */
    public function __construct(AMQPExchange|AMQPChannel $exchange, ?string $exchangeName = null, int|string|Level $level = Level::Debug, bool $bubble = \true)
    {
        if ($exchange instanceof AMQPChannel) {
            $this->exchangeName = (string) $exchangeName;
        } elseif ($exchangeName !== null) {
            @trigger_error('The $exchangeName parameter can only be passed when using PhpAmqpLib, if using an AMQPExchange instance configure it beforehand', \E_USER_DEPRECATED);
        }
        $this->exchange = $exchange;
        parent::__construct($level, $bubble);
    }
    /**
     * @return array<string, mixed>
     */
    public function getExtraAttributes(): array
    {
        return $this->extraAttributes;
    }
    /**
     * Configure extra attributes to pass to the AMQPExchange (if you are using the amqp extension)
     *
     * @param  array<string, mixed> $extraAttributes One of content_type, content_encoding,
     *                                               message_id, user_id, app_id, delivery_mode,
     *                                               priority, timestamp, expiration, type
     *                                               or reply_to, headers.
     * @return $this
     */
    public function setExtraAttributes(array $extraAttributes): self
    {
        $this->extraAttributes = $extraAttributes;
        return $this;
    }
    /**
     * @inheritDoc
     */
    protected function write(LogRecord $record): void
    {
        $data = $record->formatted;
        $routingKey = $this->getRoutingKey($record);
        if ($data instanceof GelfMessage) {
            $data = json_encode($data->toArray());
        }
        if ($this->exchange instanceof AMQPExchange) {
            $attributes = ['delivery_mode' => 2, 'content_type' => 'application/json'];
            if (\count($this->extraAttributes) > 0) {
                $attributes = array_merge($attributes, $this->extraAttributes);
            }
            $this->exchange->publish($data, $routingKey, 0, $attributes);
        } else {
            $this->exchange->basic_publish($this->createAmqpMessage($data), $this->exchangeName, $routingKey);
        }
    }
    /**
     * @inheritDoc
     */
    public function handleBatch(array $records): void
    {
        if ($this->exchange instanceof AMQPExchange) {
            parent::handleBatch($records);
            return;
        }
        foreach ($records as $record) {
            if (!$this->isHandling($record)) {
                continue;
            }
            $record = $this->processRecord($record);
            $data = $this->getFormatter()->format($record);
            if ($data instanceof GelfMessage) {
                $data = json_encode($data->toArray());
            }
            $this->exchange->batch_basic_publish($this->createAmqpMessage($data), $this->exchangeName, $this->getRoutingKey($record));
        }
        $this->exchange->publish_batch();
    }
    /**
     * Gets the routing key for the AMQP exchange
     */
    protected function getRoutingKey(LogRecord $record): string
    {
        $routingKey = sprintf('%s.%s', $record->level->name, $record->channel);
        return strtolower($routingKey);
    }
    private function createAmqpMessage(string $data): AMQPMessage
    {
        $attributes = ['delivery_mode' => 2, 'content_type' => 'application/json'];
        if (\count($this->extraAttributes) > 0) {
            $attributes = array_merge($attributes, $this->extraAttributes);
        }
        return new AMQPMessage($data, $attributes);
    }
    /**
     * @inheritDoc
     */
    protected function getDefaultFormatter(): FormatterInterface
    {
        return new JsonFormatter(JsonFormatter::BATCH_MODE_JSON, \false);
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Monolog\Handler;

use RuntimeException;
use _ContaoManager\Monolog\Level;
use _ContaoManager\Monolog\Utils;
use _ContaoManager\Monolog\LogRecord;
/**
 * Handler sends logs to Telegram using Telegram Bot API.
 *
 * How to use:
 *  1) Create a Telegram bot with https://telegram.me/BotFather;
 *  2) Create a Telegram channel or a group where logs will be recorded;
 *  3) Add the created bot from step 1 to the created channel/group from step 2.
 *
 * In order to create an instance of TelegramBotHandler use
 *  1. The Telegram bot API key from step 1
 *  2. The channel name with the `@` prefix if you created a public channel (e.g. `@my_public_channel`),
 *     or the channel ID with the `-100` prefix if you created a private channel (e.g. `-1001234567890`),
 *     or the group ID from step 2 (e.g. `-1234567890`).
 *
 * @link https://core.telegram.org/bots/api
 *
 * @author Mazur Alexandr <alexandrmazur96@gmail.com>
 */
class TelegramBotHandler extends AbstractProcessingHandler
{
    private const BOT_API = 'https://api.telegram.org/bot';
    /**
     * The available values of parseMode according to the Telegram api documentation
     */
    private const AVAILABLE_PARSE_MODES = ['HTML', 'MarkdownV2', 'Markdown'];
    /**
     * The maximum number of characters allowed in a message according to the Telegram api documentation
     */
    private const MAX_MESSAGE_LENGTH = 4096;
    /**
     * Telegram bot access token provided by BotFather.
     * Create telegram bot with https://telegram.me/BotFather and use access token from it.
     */
    private string $apiKey;
    /**
     * Telegram channel name.
     * Since to start with '@' symbol as prefix.
     */
    private string $channel;
    /**
     * The kind of formatting that is used for the message.
     * See available options at https://core.telegram.org/bots/api#formatting-options
     * or in AVAILABLE_PARSE_MODES
     */
    private string|null $parseMode;
    /**
     * Disables link previews for links in the message.
     */
    private bool|null $disableWebPagePreview;
    /**
     * Sends the message silently. Users will receive a notification with no sound.
     */
    private bool|null $disableNotification;
    /**
     * True - split a message longer than MAX_MESSAGE_LENGTH into parts and send in multiple messages.
     * False - truncates a message that is too long.
     */
    private bool $splitLongMessages;
    /**
     * Adds 1-second delay between sending a split message (according to Telegram API to avoid 429 Too Many Requests).
     */
    private bool $delayBetweenMessages;
    /**
     * Telegram message thread id, unique identifier for the target message thread (topic) of the forum; for forum supergroups only
     * See how to get the `message_thread_id` https://stackoverflow.com/a/75178418
     */
    private int|null $topic;
    /**
     * @param  string                    $apiKey               Telegram bot access token provided by BotFather
     * @param  string                    $channel              Telegram channel name
     * @param  bool                      $splitLongMessages    Split a message longer than MAX_MESSAGE_LENGTH into parts and send in multiple messages
     * @param  bool                      $delayBetweenMessages Adds delay between sending a split message according to Telegram API
     * @param  int                       $topic                Telegram message thread id, unique identifier for the target message thread (topic) of the forum
     * @throws MissingExtensionException If the curl extension is missing
     */
    public function __construct(string $apiKey, string $channel, $level = Level::Debug, bool $bubble = \true, ?string $parseMode = null, ?bool $disableWebPagePreview = null, ?bool $disableNotification = null, bool $splitLongMessages = \false, bool $delayBetweenMessages = \false, ?int $topic = null)
    {
        if (!\extension_loaded('curl')) {
            throw new MissingExtensionException('The curl extension is needed to use the TelegramBotHandler');
        }
        parent::__construct($level, $bubble);
        $this->apiKey = $apiKey;
        $this->channel = $channel;
        $this->setParseMode($parseMode);
        $this->disableWebPagePreview($disableWebPagePreview);
        $this->disableNotification($disableNotification);
        $this->splitLongMessages($splitLongMessages);
        $this->delayBetweenMessages($delayBetweenMessages);
        $this->setTopic($topic);
    }
    /**
     * @return $this
     */
    public function setParseMode(string|null $parseMode = null): self
    {
        if ($parseMode !== null && !\in_array($parseMode, self::AVAILABLE_PARSE_MODES, \true)) {
            throw new \InvalidArgumentException('Unknown parseMode, use one of these: ' . implode(', ', self::AVAILABLE_PARSE_MODES) . '.');
        }
        $this->parseMode = $parseMode;
        return $this;
    }
    /**
     * @return $this
     */
    public function disableWebPagePreview(bool|null $disableWebPagePreview = null): self
    {
        $this->disableWebPagePreview = $disableWebPagePreview;
        return $this;
    }
    /**
     * @return $this
     */
    public function disableNotification(bool|null $disableNotification = null): self
    {
        $this->disableNotification = $disableNotification;
        return $this;
    }
    /**
     * True - split a message longer than MAX_MESSAGE_LENGTH into parts and send in multiple messages.
     * False - truncates a message that is too long.
     *
     * @return $this
     */
    public function splitLongMessages(bool $splitLongMessages = \false): self
    {
        $this->splitLongMessages = $splitLongMessages;
        return $this;
    }
    /**
     * Adds 1-second delay between sending a split message (according to Telegram API to avoid 429 Too Many Requests).
     *
     * @return $this
     */
    public function delayBetweenMessages(bool $delayBetweenMessages = \false): self
    {
        $this->delayBetweenMessages = $delayBetweenMessages;
        return $this;
    }
    /**
     * @return $this
     */
    public function setTopic(?int $topic = null): self
    {
        $this->topic = $topic;
        return $this;
    }
    /**
     * @inheritDoc
     */
    public function handleBatch(array $records): void
    {
        $messages = [];
        foreach ($records as $record) {
            if (!$this->isHandling($record)) {
                continue;
            }
            if (\count($this->processors) > 0) {
                $record = $this->processRecord($record);
            }
            $messages[] = $record;
        }
        if (\count($messages) > 0) {
            $this->send((string) $this->getFormatter()->formatBatch($messages));
        }
    }
    /**
     * @inheritDoc
     */
    protected function write(LogRecord $record): void
    {
        $this->send($record->formatted);
    }
    /**
     * Send request to @link https://api.telegram.org/bot on SendMessage action.
     */
    protected function send(string $message): void
    {
        $messages = $this->handleMessageLength($message);
        foreach ($messages as $key => $msg) {
            if ($this->delayBetweenMessages && $key > 0) {
                sleep(1);
            }
            $this->sendCurl($msg);
        }
    }
    protected function sendCurl(string $message): void
    {
        if ('' === trim($message)) {
            return;
        }
        $ch = curl_init();
        $url = self::BOT_API . $this->apiKey . '/SendMessage';
        curl_setopt($ch, \CURLOPT_URL, $url);
        curl_setopt($ch, \CURLOPT_RETURNTRANSFER, \true);
        curl_setopt($ch, \CURLOPT_SSL_VERIFYPEER, \true);
        $params = ['text' => $message, 'chat_id' => $this->channel, 'parse_mode' => $this->parseMode, 'disable_web_page_preview' => $this->disableWebPagePreview, 'disable_notification' => $this->disableNotification];
        if ($this->topic !== null) {
            $params['message_thread_id'] = $this->topic;
        }
        curl_setopt($ch, \CURLOPT_POSTFIELDS, http_build_query($params));
        $result = Curl\Util::execute($ch);
        if (!\is_string($result)) {
            throw new RuntimeException('Telegram API error. Description: No response');
        }
        $result = json_decode($result, \true);
        if ($result['ok'] === \false) {
            throw new RuntimeException('Telegram API error. Description: ' . $result['description']);
        }
    }
    /**
     * Handle a message that is too long: truncates or splits into several
     * @return string[]
     */
    private function handleMessageLength(string $message): array
    {
        $truncatedMarker = ' (…truncated)';
        if (!$this->splitLongMessages && \strlen($message) > self::MAX_MESSAGE_LENGTH) {
            return [Utils::substr($message, 0, self::MAX_MESSAGE_LENGTH - \strlen($truncatedMarker)) . $truncatedMarker];
        }
        return str_split($message, self::MAX_MESSAGE_LENGTH);
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Monolog\Handler;

use _ContaoManager\Monolog\Level;
use _ContaoManager\Swift;
use _ContaoManager\Swift_Message;
/**
 * MandrillHandler uses cURL to send the emails to the Mandrill API
 *
 * @author Adam Nicholson <adamnicholson10@gmail.com>
 */
class MandrillHandler extends MailHandler
{
    protected Swift_Message $message;
    protected string $apiKey;
    /**
     * @phpstan-param (Swift_Message|callable(): Swift_Message) $message
     *
     * @param string                 $apiKey  A valid Mandrill API key
     * @param callable|Swift_Message $message An example message for real messages, only the body will be replaced
     *
     * @throws \InvalidArgumentException if not a Swift Message is set
     */
    public function __construct(string $apiKey, callable|Swift_Message $message, int|string|Level $level = Level::Error, bool $bubble = \true)
    {
        parent::__construct($level, $bubble);
        if (!$message instanceof Swift_Message) {
            $message = $message();
        }
        if (!$message instanceof Swift_Message) {
            throw new \InvalidArgumentException('You must provide either a Swift_Message instance or a callable returning it');
        }
        $this->message = $message;
        $this->apiKey = $apiKey;
    }
    /**
     * @inheritDoc
     */
    protected function send(string $content, array $records): void
    {
        $mime = 'text/plain';
        if ($this->isHtmlBody($content)) {
            $mime = 'text/html';
        }
        $message = clone $this->message;
        $message->setBody($content, $mime);
        /** @phpstan-ignore-next-line */
        if (version_compare(Swift::VERSION, '6.0.0', '>=')) {
            $message->setDate(new \DateTimeImmutable());
        } else {
            /** @phpstan-ignore-next-line */
            $message->setDate(time());
        }
        $ch = curl_init();
        curl_setopt($ch, \CURLOPT_URL, 'https://mandrillapp.com/api/1.0/messages/send-raw.json');
        curl_setopt($ch, \CURLOPT_POST, \true);
        curl_setopt($ch, \CURLOPT_RETURNTRANSFER, \true);
        curl_setopt($ch, \CURLOPT_POSTFIELDS, http_build_query(['key' => $this->apiKey, 'raw_message' => (string) $message, 'async' => \false]));
        Curl\Util::execute($ch);
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Monolog\Handler;

use _ContaoManager\Monolog\LogRecord;
/**
 * Base Handler class providing the Handler structure, including processors and formatters
 *
 * Classes extending it should (in most cases) only implement write($record)
 *
 * @author Jordi Boggiano <j.boggiano@seld.be>
 * @author Christophe Coevoet <stof@notk.org>
 */
abstract class AbstractProcessingHandler extends AbstractHandler implements ProcessableHandlerInterface, FormattableHandlerInterface
{
    use ProcessableHandlerTrait;
    use FormattableHandlerTrait;
    /**
     * @inheritDoc
     */
    public function handle(LogRecord $record): bool
    {
        if (!$this->isHandling($record)) {
            return \false;
        }
        if (\count($this->processors) > 0) {
            $record = $this->processRecord($record);
        }
        $record->formatted = $this->getFormatter()->format($record);
        $this->write($record);
        return \false === $this->bubble;
    }
    /**
     * Writes the (already formatted) record down to the log of the implementing handler
     */
    abstract protected function write(LogRecord $record): void;
    public function reset(): void
    {
        parent::reset();
        $this->resetProcessors();
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Monolog\Handler;

use _ContaoManager\Monolog\Formatter\FormatterInterface;
use _ContaoManager\Monolog\Formatter\JsonFormatter;
use _ContaoManager\Monolog\Level;
use _ContaoManager\Monolog\LogRecord;
/**
 * CouchDB handler
 *
 * @author Markus Bachmann <markus.bachmann@bachi.biz>
 * @phpstan-type Options array{
 *     host: string,
 *     port: int,
 *     dbname: string,
 *     username: string|null,
 *     password: string|null
 * }
 * @phpstan-type InputOptions array{
 *     host?: string,
 *     port?: int,
 *     dbname?: string,
 *     username?: string|null,
 *     password?: string|null
 * }
 */
class CouchDBHandler extends AbstractProcessingHandler
{
    /**
     * @var mixed[]
     * @phpstan-var Options
     */
    private array $options;
    /**
     * @param mixed[] $options
     *
     * @phpstan-param InputOptions $options
     */
    public function __construct(array $options = [], int|string|Level $level = Level::Debug, bool $bubble = \true)
    {
        $this->options = array_merge(['host' => 'localhost', 'port' => 5984, 'dbname' => 'logger', 'username' => null, 'password' => null], $options);
        parent::__construct($level, $bubble);
    }
    /**
     * @inheritDoc
     */
    protected function write(LogRecord $record): void
    {
        $basicAuth = null;
        if (null !== $this->options['username'] && null !== $this->options['password']) {
            $basicAuth = sprintf('%s:%s@', $this->options['username'], $this->options['password']);
        }
        $url = 'http://' . $basicAuth . $this->options['host'] . ':' . $this->options['port'] . '/' . $this->options['dbname'];
        $context = stream_context_create(['http' => ['method' => 'POST', 'content' => $record->formatted, 'ignore_errors' => \true, 'max_redirects' => 0, 'header' => 'Content-type: application/json']]);
        if (\false === @file_get_contents($url, \false, $context)) {
            throw new \RuntimeException(sprintf('Could not connect to %s', $url));
        }
    }
    /**
     * @inheritDoc
     */
    protected function getDefaultFormatter(): FormatterInterface
    {
        return new JsonFormatter(JsonFormatter::BATCH_MODE_JSON, \false);
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Monolog\Handler;

use _ContaoManager\Monolog\Formatter\LineFormatter;
use _ContaoManager\Monolog\Formatter\FormatterInterface;
use _ContaoManager\Monolog\Level;
use _ContaoManager\Monolog\LogRecord;
use _ContaoManager\Predis\Client as Predis;
use Redis;
/**
 * Logs to a Redis key using rpush
 *
 * usage example:
 *
 *   $log = new Logger('application');
 *   $redis = new RedisHandler(new Predis\Client("tcp://localhost:6379"), "logs");
 *   $log->pushHandler($redis);
 *
 * @author Thomas Tourlourat <thomas@tourlourat.com>
 */
class RedisHandler extends AbstractProcessingHandler
{
    /** @var Predis<Predis>|Redis */
    private Predis|Redis $redisClient;
    private string $redisKey;
    protected int $capSize;
    /**
     * @param Predis<Predis>|Redis $redis   The redis instance
     * @param string               $key     The key name to push records to
     * @param int                  $capSize Number of entries to limit list size to, 0 = unlimited
     */
    public function __construct(Predis|Redis $redis, string $key, int|string|Level $level = Level::Debug, bool $bubble = \true, int $capSize = 0)
    {
        $this->redisClient = $redis;
        $this->redisKey = $key;
        $this->capSize = $capSize;
        parent::__construct($level, $bubble);
    }
    /**
     * @inheritDoc
     */
    protected function write(LogRecord $record): void
    {
        if ($this->capSize > 0) {
            $this->writeCapped($record);
        } else {
            $this->redisClient->rpush($this->redisKey, $record->formatted);
        }
    }
    /**
     * Write and cap the collection
     * Writes the record to the redis list and caps its
     */
    protected function writeCapped(LogRecord $record): void
    {
        if ($this->redisClient instanceof Redis) {
            $mode = \defined('Redis::MULTI') ? Redis::MULTI : 1;
            $this->redisClient->multi($mode)->rPush($this->redisKey, $record->formatted)->ltrim($this->redisKey, -$this->capSize, -1)->exec();
        } else {
            $redisKey = $this->redisKey;
            $capSize = $this->capSize;
            $this->redisClient->transaction(function ($tx) use ($record, $redisKey, $capSize) {
                $tx->rpush($redisKey, $record->formatted);
                $tx->ltrim($redisKey, -$capSize, -1);
            });
        }
    }
    /**
     * @inheritDoc
     */
    protected function getDefaultFormatter(): FormatterInterface
    {
        return new LineFormatter();
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Monolog\Handler;

use _ContaoManager\Monolog\Level;
use _ContaoManager\Monolog\Utils;
use _ContaoManager\Monolog\LogRecord;
/**
 * Logs to Cube.
 *
 * @link https://github.com/square/cube/wiki
 * @author Wan Chen <kami@kamisama.me>
 * @deprecated Since 2.8.0 and 3.2.0, Cube appears abandoned and thus we will drop this handler in Monolog 4
 */
class CubeHandler extends AbstractProcessingHandler
{
    private ?\Socket $udpConnection = null;
    private ?\CurlHandle $httpConnection = null;
    private string $scheme;
    private string $host;
    private int $port;
    /** @var string[] */
    private array $acceptedSchemes = ['http', 'udp'];
    /**
     * Create a Cube handler
     *
     * @throws \UnexpectedValueException when given url is not a valid url.
     *                                   A valid url must consist of three parts : protocol://host:port
     *                                   Only valid protocols used by Cube are http and udp
     */
    public function __construct(string $url, int|string|Level $level = Level::Debug, bool $bubble = \true)
    {
        $urlInfo = parse_url($url);
        if ($urlInfo === \false || !isset($urlInfo['scheme'], $urlInfo['host'], $urlInfo['port'])) {
            throw new \UnexpectedValueException('URL "' . $url . '" is not valid');
        }
        if (!\in_array($urlInfo['scheme'], $this->acceptedSchemes, \true)) {
            throw new \UnexpectedValueException('Invalid protocol (' . $urlInfo['scheme'] . ').' . ' Valid options are ' . implode(', ', $this->acceptedSchemes));
        }
        $this->scheme = $urlInfo['scheme'];
        $this->host = $urlInfo['host'];
        $this->port = $urlInfo['port'];
        parent::__construct($level, $bubble);
    }
    /**
     * Establish a connection to an UDP socket
     *
     * @throws \LogicException           when unable to connect to the socket
     * @throws MissingExtensionException when there is no socket extension
     */
    protected function connectUdp(): void
    {
        if (!\extension_loaded('sockets')) {
            throw new MissingExtensionException('The sockets extension is required to use udp URLs with the CubeHandler');
        }
        $udpConnection = socket_create(\AF_INET, \SOCK_DGRAM, 0);
        if (\false === $udpConnection) {
            throw new \LogicException('Unable to create a socket');
        }
        $this->udpConnection = $udpConnection;
        if (!socket_connect($this->udpConnection, $this->host, $this->port)) {
            throw new \LogicException('Unable to connect to the socket at ' . $this->host . ':' . $this->port);
        }
    }
    /**
     * Establish a connection to an http server
     *
     * @throws \LogicException           when unable to connect to the socket
     * @throws MissingExtensionException when no curl extension
     */
    protected function connectHttp(): void
    {
        if (!\extension_loaded('curl')) {
            throw new MissingExtensionException('The curl extension is required to use http URLs with the CubeHandler');
        }
        $httpConnection = curl_init('http://' . $this->host . ':' . $this->port . '/1.0/event/put');
        if (\false === $httpConnection) {
            throw new \LogicException('Unable to connect to ' . $this->host . ':' . $this->port);
        }
        $this->httpConnection = $httpConnection;
        curl_setopt($this->httpConnection, \CURLOPT_CUSTOMREQUEST, "POST");
        curl_setopt($this->httpConnection, \CURLOPT_RETURNTRANSFER, \true);
    }
    /**
     * @inheritDoc
     */
    protected function write(LogRecord $record): void
    {
        $date = $record->datetime;
        $data = ['time' => $date->format('Y-m-d\TH:i:s.uO')];
        $context = $record->context;
        if (isset($context['type'])) {
            $data['type'] = $context['type'];
            unset($context['type']);
        } else {
            $data['type'] = $record->channel;
        }
        $data['data'] = $context;
        $data['data']['level'] = $record->level;
        if ($this->scheme === 'http') {
            $this->writeHttp(Utils::jsonEncode($data));
        } else {
            $this->writeUdp(Utils::jsonEncode($data));
        }
    }
    private function writeUdp(string $data): void
    {
        if (null === $this->udpConnection) {
            $this->connectUdp();
        }
        if (null === $this->udpConnection) {
            throw new \LogicException('No UDP socket could be opened');
        }
        socket_send($this->udpConnection, $data, \strlen($data), 0);
    }
    private function writeHttp(string $data): void
    {
        if (null === $this->httpConnection) {
            $this->connectHttp();
        }
        if (null === $this->httpConnection) {
            throw new \LogicException('No connection could be established');
        }
        curl_setopt($this->httpConnection, \CURLOPT_POSTFIELDS, '[' . $data . ']');
        curl_setopt($this->httpConnection, \CURLOPT_HTTPHEADER, ['Content-Type: application/json', 'Content-Length: ' . \strlen('[' . $data . ']')]);
        Curl\Util::execute($this->httpConnection, 5);
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Monolog\Handler\SyslogUdp;

use _ContaoManager\Monolog\Utils;
use Socket;
class UdpSocket
{
    protected const DATAGRAM_MAX_LENGTH = 65023;
    protected string $ip;
    protected int $port;
    protected ?Socket $socket = null;
    public function __construct(string $ip, int $port = 514)
    {
        $this->ip = $ip;
        $this->port = $port;
    }
    public function write(string $line, string $header = ""): void
    {
        $this->send($this->assembleMessage($line, $header));
    }
    public function close(): void
    {
        if ($this->socket instanceof Socket) {
            socket_close($this->socket);
            $this->socket = null;
        }
    }
    protected function getSocket(): Socket
    {
        if (null !== $this->socket) {
            return $this->socket;
        }
        $domain = \AF_INET;
        $protocol = \SOL_UDP;
        // Check if we are using unix sockets.
        if ($this->port === 0) {
            $domain = \AF_UNIX;
            $protocol = \IPPROTO_IP;
        }
        $socket = socket_create($domain, \SOCK_DGRAM, $protocol);
        if ($socket instanceof Socket) {
            return $this->socket = $socket;
        }
        throw new \RuntimeException('The UdpSocket to ' . $this->ip . ':' . $this->port . ' could not be opened via socket_create');
    }
    protected function send(string $chunk): void
    {
        socket_sendto($this->getSocket(), $chunk, \strlen($chunk), $flags = 0, $this->ip, $this->port);
    }
    protected function assembleMessage(string $line, string $header): string
    {
        $chunkSize = static::DATAGRAM_MAX_LENGTH - \strlen($header);
        return $header . Utils::substr($line, 0, $chunkSize);
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Monolog;

use DateTimeZone;
/**
 * Overrides default json encoding of date time objects
 *
 * @author Menno Holtkamp
 * @author Jordi Boggiano <j.boggiano@seld.be>
 */
class JsonSerializableDateTimeImmutable extends \DateTimeImmutable implements \JsonSerializable
{
    private bool $useMicroseconds;
    public function __construct(bool $useMicroseconds, ?DateTimeZone $timezone = null)
    {
        $this->useMicroseconds = $useMicroseconds;
        // if you like to use a custom time to pass to Logger::addRecord directly,
        // call modify() or setTimestamp() on this instance to change the date after creating it
        parent::__construct('now', $timezone);
    }
    public function jsonSerialize(): string
    {
        if ($this->useMicroseconds) {
            return $this->format('Y-m-d\TH:i:s.uP');
        }
        return $this->format('Y-m-d\TH:i:sP');
    }
    public function __toString(): string
    {
        return $this->jsonSerialize();
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Monolog;

use Closure;
use DateTimeZone;
use Fiber;
use _ContaoManager\Monolog\Handler\HandlerInterface;
use _ContaoManager\Monolog\Processor\ProcessorInterface;
use _ContaoManager\Psr\Log\LoggerInterface;
use _ContaoManager\Psr\Log\InvalidArgumentException;
use _ContaoManager\Psr\Log\LogLevel;
use Throwable;
use Stringable;
use WeakMap;
/**
 * Monolog log channel
 *
 * It contains a stack of Handlers and a stack of Processors,
 * and uses them to store records that are added to it.
 *
 * @author Jordi Boggiano <j.boggiano@seld.be>
 * @final
 */
class Logger implements LoggerInterface, ResettableInterface
{
    /**
     * Detailed debug information
     *
     * @deprecated Use \Monolog\Level::Debug
     */
    public const DEBUG = 100;
    /**
     * Interesting events
     *
     * Examples: User logs in, SQL logs.
     *
     * @deprecated Use \Monolog\Level::Info
     */
    public const INFO = 200;
    /**
     * Uncommon events
     *
     * @deprecated Use \Monolog\Level::Notice
     */
    public const NOTICE = 250;
    /**
     * Exceptional occurrences that are not errors
     *
     * Examples: Use of deprecated APIs, poor use of an API,
     * undesirable things that are not necessarily wrong.
     *
     * @deprecated Use \Monolog\Level::Warning
     */
    public const WARNING = 300;
    /**
     * Runtime errors
     *
     * @deprecated Use \Monolog\Level::Error
     */
    public const ERROR = 400;
    /**
     * Critical conditions
     *
     * Example: Application component unavailable, unexpected exception.
     *
     * @deprecated Use \Monolog\Level::Critical
     */
    public const CRITICAL = 500;
    /**
     * Action must be taken immediately
     *
     * Example: Entire website down, database unavailable, etc.
     * This should trigger the SMS alerts and wake you up.
     *
     * @deprecated Use \Monolog\Level::Alert
     */
    public const ALERT = 550;
    /**
     * Urgent alert.
     *
     * @deprecated Use \Monolog\Level::Emergency
     */
    public const EMERGENCY = 600;
    /**
     * Monolog API version
     *
     * This is only bumped when API breaks are done and should
     * follow the major version of the library
     */
    public const API = 3;
    /**
     * Mapping between levels numbers defined in RFC 5424 and Monolog ones
     *
     * @phpstan-var array<int, Level> $rfc_5424_levels
     */
    private const RFC_5424_LEVELS = [7 => Level::Debug, 6 => Level::Info, 5 => Level::Notice, 4 => Level::Warning, 3 => Level::Error, 2 => Level::Critical, 1 => Level::Alert, 0 => Level::Emergency];
    protected string $name;
    /**
     * The handler stack
     *
     * @var list<HandlerInterface>
     */
    protected array $handlers;
    /**
     * Processors that will process all log records
     *
     * To process records of a single handler instead, add the processor on that specific handler
     *
     * @var array<(callable(LogRecord): LogRecord)|ProcessorInterface>
     */
    protected array $processors;
    protected bool $microsecondTimestamps = \true;
    protected DateTimeZone $timezone;
    protected Closure|null $exceptionHandler = null;
    /**
     * Keeps track of depth to prevent infinite logging loops
     */
    private int $logDepth = 0;
    /**
     * @var WeakMap<Fiber<mixed, mixed, mixed, mixed>, int> Keeps track of depth inside fibers to prevent infinite logging loops
     */
    private WeakMap $fiberLogDepth;
    /**
     * Whether to detect infinite logging loops
     * This can be disabled via {@see useLoggingLoopDetection} if you have async handlers that do not play well with this
     */
    private bool $detectCycles = \true;
    /**
     * @param string             $name       The logging channel, a simple descriptive name that is attached to all log records
     * @param list<HandlerInterface> $handlers   Optional stack of handlers, the first one in the array is called first, etc.
     * @param callable[]         $processors Optional array of processors
     * @param DateTimeZone|null  $timezone   Optional timezone, if not provided date_default_timezone_get() will be used
     *
     * @phpstan-param array<(callable(LogRecord): LogRecord)|ProcessorInterface> $processors
     */
    public function __construct(string $name, array $handlers = [], array $processors = [], DateTimeZone|null $timezone = null)
    {
        $this->name = $name;
        $this->setHandlers($handlers);
        $this->processors = $processors;
        $this->timezone = $timezone ?? new DateTimeZone(date_default_timezone_get());
        $this->fiberLogDepth = new \WeakMap();
    }
    public function getName(): string
    {
        return $this->name;
    }
    /**
     * Return a new cloned instance with the name changed
     *
     * @return static
     */
    public function withName(string $name): self
    {
        $new = clone $this;
        $new->name = $name;
        return $new;
    }
    /**
     * Pushes a handler on to the stack.
     *
     * @return $this
     */
    public function pushHandler(HandlerInterface $handler): self
    {
        array_unshift($this->handlers, $handler);
        return $this;
    }
    /**
     * Pops a handler from the stack
     *
     * @throws \LogicException If empty handler stack
     */
    public function popHandler(): HandlerInterface
    {
        if (0 === \count($this->handlers)) {
            throw new \LogicException('You tried to pop from an empty handler stack.');
        }
        return array_shift($this->handlers);
    }
    /**
     * Set handlers, replacing all existing ones.
     *
     * If a map is passed, keys will be ignored.
     *
     * @param  list<HandlerInterface> $handlers
     * @return $this
     */
    public function setHandlers(array $handlers): self
    {
        $this->handlers = [];
        foreach (array_reverse($handlers) as $handler) {
            $this->pushHandler($handler);
        }
        return $this;
    }
    /**
     * @return list<HandlerInterface>
     */
    public function getHandlers(): array
    {
        return $this->handlers;
    }
    /**
     * Adds a processor on to the stack.
     *
     * @phpstan-param ProcessorInterface|(callable(LogRecord): LogRecord) $callback
     * @return $this
     */
    public function pushProcessor(ProcessorInterface|callable $callback): self
    {
        array_unshift($this->processors, $callback);
        return $this;
    }
    /**
     * Removes the processor on top of the stack and returns it.
     *
     * @phpstan-return ProcessorInterface|(callable(LogRecord): LogRecord)
     * @throws \LogicException If empty processor stack
     */
    public function popProcessor(): callable
    {
        if (0 === \count($this->processors)) {
            throw new \LogicException('You tried to pop from an empty processor stack.');
        }
        return array_shift($this->processors);
    }
    /**
     * @return callable[]
     * @phpstan-return array<ProcessorInterface|(callable(LogRecord): LogRecord)>
     */
    public function getProcessors(): array
    {
        return $this->processors;
    }
    /**
     * Control the use of microsecond resolution timestamps in the 'datetime'
     * member of new records.
     *
     * As of PHP7.1 microseconds are always included by the engine, so
     * there is no performance penalty and Monolog 2 enabled microseconds
     * by default. This function lets you disable them though in case you want
     * to suppress microseconds from the output.
     *
     * @param  bool  $micro True to use microtime() to create timestamps
     * @return $this
     */
    public function useMicrosecondTimestamps(bool $micro): self
    {
        $this->microsecondTimestamps = $micro;
        return $this;
    }
    /**
     * @return $this
     */
    public function useLoggingLoopDetection(bool $detectCycles): self
    {
        $this->detectCycles = $detectCycles;
        return $this;
    }
    /**
     * Adds a log record.
     *
     * @param  int                    $level    The logging level (a Monolog or RFC 5424 level)
     * @param  string                 $message  The log message
     * @param  mixed[]                $context  The log context
     * @param  JsonSerializableDateTimeImmutable|null $datetime Optional log date to log into the past or future
     *
     * @return bool                   Whether the record has been processed
     *
     * @phpstan-param value-of<Level::VALUES>|Level $level
     */
    public function addRecord(int|Level $level, string $message, array $context = [], JsonSerializableDateTimeImmutable|null $datetime = null): bool
    {
        if (\is_int($level) && isset(self::RFC_5424_LEVELS[$level])) {
            $level = self::RFC_5424_LEVELS[$level];
        }
        if ($this->detectCycles) {
            if (null !== $fiber = Fiber::getCurrent()) {
                $logDepth = $this->fiberLogDepth[$fiber] = ($this->fiberLogDepth[$fiber] ?? 0) + 1;
            } else {
                $logDepth = ++$this->logDepth;
            }
        } else {
            $logDepth = 0;
        }
        if ($logDepth === 3) {
            $this->warning('A possible infinite logging loop was detected and aborted. It appears some of your handler code is triggering logging, see the previous log record for a hint as to what may be the cause.');
            return \false;
        } elseif ($logDepth >= 5) {
            // log depth 4 is let through, so we can log the warning above
            return \false;
        }
        try {
            $recordInitialized = \count($this->processors) === 0;
            $record = new LogRecord(datetime: $datetime ?? new JsonSerializableDateTimeImmutable($this->microsecondTimestamps, $this->timezone), channel: $this->name, level: self::toMonologLevel($level), message: $message, context: $context, extra: []);
            $handled = \false;
            foreach ($this->handlers as $handler) {
                if (\false === $recordInitialized) {
                    // skip initializing the record as long as no handler is going to handle it
                    if (!$handler->isHandling($record)) {
                        continue;
                    }
                    try {
                        foreach ($this->processors as $processor) {
                            $record = $processor($record);
                        }
                        $recordInitialized = \true;
                    } catch (Throwable $e) {
                        $this->handleException($e, $record);
                        return \true;
                    }
                }
                // once the record is initialized, send it to all handlers as long as the bubbling chain is not interrupted
                try {
                    $handled = \true;
                    if (\true === $handler->handle(clone $record)) {
                        break;
                    }
                } catch (Throwable $e) {
                    $this->handleException($e, $record);
                    return \true;
                }
            }
            return $handled;
        } finally {
            if ($this->detectCycles) {
                if (isset($fiber)) {
                    $this->fiberLogDepth[$fiber]--;
                } else {
                    $this->logDepth--;
                }
            }
        }
    }
    /**
     * Ends a log cycle and frees all resources used by handlers.
     *
     * Closing a Handler means flushing all buffers and freeing any open resources/handles.
     * Handlers that have been closed should be able to accept log records again and re-open
     * themselves on demand, but this may not always be possible depending on implementation.
     *
     * This is useful at the end of a request and will be called automatically on every handler
     * when they get destructed.
     */
    public function close(): void
    {
        foreach ($this->handlers as $handler) {
            $handler->close();
        }
    }
    /**
     * Ends a log cycle and resets all handlers and processors to their initial state.
     *
     * Resetting a Handler or a Processor means flushing/cleaning all buffers, resetting internal
     * state, and getting it back to a state in which it can receive log records again.
     *
     * This is useful in case you want to avoid logs leaking between two requests or jobs when you
     * have a long running process like a worker or an application server serving multiple requests
     * in one process.
     */
    public function reset(): void
    {
        foreach ($this->handlers as $handler) {
            if ($handler instanceof ResettableInterface) {
                $handler->reset();
            }
        }
        foreach ($this->processors as $processor) {
            if ($processor instanceof ResettableInterface) {
                $processor->reset();
            }
        }
    }
    /**
     * Gets the name of the logging level as a string.
     *
     * This still returns a string instead of a Level for BC, but new code should not rely on this method.
     *
     * @throws \Psr\Log\InvalidArgumentException If level is not defined
     *
     * @phpstan-param  value-of<Level::VALUES>|Level $level
     * @phpstan-return value-of<Level::NAMES>
     *
     * @deprecated Since 3.0, use {@see toMonologLevel} or {@see \Monolog\Level->getName()} instead
     */
    public static function getLevelName(int|Level $level): string
    {
        return self::toMonologLevel($level)->getName();
    }
    /**
     * Converts PSR-3 levels to Monolog ones if necessary
     *
     * @param  int|string|Level|LogLevel::*      $level Level number (monolog) or name (PSR-3)
     * @throws \Psr\Log\InvalidArgumentException If level is not defined
     *
     * @phpstan-param value-of<Level::VALUES>|value-of<Level::NAMES>|Level|LogLevel::* $level
     */
    public static function toMonologLevel(string|int|Level $level): Level
    {
        if ($level instanceof Level) {
            return $level;
        }
        if (\is_string($level)) {
            if (is_numeric($level)) {
                $levelEnum = Level::tryFrom((int) $level);
                if ($levelEnum === null) {
                    throw new InvalidArgumentException('Level "' . $level . '" is not defined, use one of: ' . implode(', ', Level::NAMES + Level::VALUES));
                }
                return $levelEnum;
            }
            // Contains first char of all log levels and avoids using strtoupper() which may have
            // strange results depending on locale (for example, "i" will become "İ" in Turkish locale)
            $upper = strtr(substr($level, 0, 1), 'dinweca', 'DINWECA') . strtolower(substr($level, 1));
            if (\defined(Level::class . '::' . $upper)) {
                return \constant(Level::class . '::' . $upper);
            }
            throw new InvalidArgumentException('Level "' . $level . '" is not defined, use one of: ' . implode(', ', Level::NAMES + Level::VALUES));
        }
        $levelEnum = Level::tryFrom($level);
        if ($levelEnum === null) {
            throw new InvalidArgumentException('Level "' . var_export($level, \true) . '" is not defined, use one of: ' . implode(', ', Level::NAMES + Level::VALUES));
        }
        return $levelEnum;
    }
    /**
     * Checks whether the Logger has a handler that listens on the given level
     *
     * @phpstan-param value-of<Level::VALUES>|value-of<Level::NAMES>|Level|LogLevel::* $level
     */
    public function isHandling(int|string|Level $level): bool
    {
        $record = new LogRecord(datetime: new JsonSerializableDateTimeImmutable($this->microsecondTimestamps, $this->timezone), channel: $this->name, message: '', level: self::toMonologLevel($level));
        foreach ($this->handlers as $handler) {
            if ($handler->isHandling($record)) {
                return \true;
            }
        }
        return \false;
    }
    /**
     * Set a custom exception handler that will be called if adding a new record fails
     *
     * The Closure will receive an exception object and the record that failed to be logged
     *
     * @return $this
     */
    public function setExceptionHandler(Closure|null $callback): self
    {
        $this->exceptionHandler = $callback;
        return $this;
    }
    public function getExceptionHandler(): Closure|null
    {
        return $this->exceptionHandler;
    }
    /**
     * Adds a log record at an arbitrary level.
     *
     * This method allows for compatibility with common interfaces.
     *
     * @param mixed             $level   The log level (a Monolog, PSR-3 or RFC 5424 level)
     * @param string|Stringable $message The log message
     * @param mixed[]           $context The log context
     *
     * @phpstan-param Level|LogLevel::* $level
     */
    public function log($level, string|\Stringable $message, array $context = []): void
    {
        if (!$level instanceof Level) {
            if (!\is_string($level) && !\is_int($level)) {
                throw new \InvalidArgumentException('$level is expected to be a string, int or ' . Level::class . ' instance');
            }
            if (isset(self::RFC_5424_LEVELS[$level])) {
                $level = self::RFC_5424_LEVELS[$level];
            }
            $level = static::toMonologLevel($level);
        }
        $this->addRecord($level, (string) $message, $context);
    }
    /**
     * Adds a log record at the DEBUG level.
     *
     * This method allows for compatibility with common interfaces.
     *
     * @param string|Stringable $message The log message
     * @param mixed[]           $context The log context
     */
    public function debug(string|\Stringable $message, array $context = []): void
    {
        $this->addRecord(Level::Debug, (string) $message, $context);
    }
    /**
     * Adds a log record at the INFO level.
     *
     * This method allows for compatibility with common interfaces.
     *
     * @param string|Stringable $message The log message
     * @param mixed[]           $context The log context
     */
    public function info(string|\Stringable $message, array $context = []): void
    {
        $this->addRecord(Level::Info, (string) $message, $context);
    }
    /**
     * Adds a log record at the NOTICE level.
     *
     * This method allows for compatibility with common interfaces.
     *
     * @param string|Stringable $message The log message
     * @param mixed[]           $context The log context
     */
    public function notice(string|\Stringable $message, array $context = []): void
    {
        $this->addRecord(Level::Notice, (string) $message, $context);
    }
    /**
     * Adds a log record at the WARNING level.
     *
     * This method allows for compatibility with common interfaces.
     *
     * @param string|Stringable $message The log message
     * @param mixed[]           $context The log context
     */
    public function warning(string|\Stringable $message, array $context = []): void
    {
        $this->addRecord(Level::Warning, (string) $message, $context);
    }
    /**
     * Adds a log record at the ERROR level.
     *
     * This method allows for compatibility with common interfaces.
     *
     * @param string|Stringable $message The log message
     * @param mixed[]           $context The log context
     */
    public function error(string|\Stringable $message, array $context = []): void
    {
        $this->addRecord(Level::Error, (string) $message, $context);
    }
    /**
     * Adds a log record at the CRITICAL level.
     *
     * This method allows for compatibility with common interfaces.
     *
     * @param string|Stringable $message The log message
     * @param mixed[]           $context The log context
     */
    public function critical(string|\Stringable $message, array $context = []): void
    {
        $this->addRecord(Level::Critical, (string) $message, $context);
    }
    /**
     * Adds a log record at the ALERT level.
     *
     * This method allows for compatibility with common interfaces.
     *
     * @param string|Stringable $message The log message
     * @param mixed[]           $context The log context
     */
    public function alert(string|\Stringable $message, array $context = []): void
    {
        $this->addRecord(Level::Alert, (string) $message, $context);
    }
    /**
     * Adds a log record at the EMERGENCY level.
     *
     * This method allows for compatibility with common interfaces.
     *
     * @param string|Stringable $message The log message
     * @param mixed[]           $context The log context
     */
    public function emergency(string|\Stringable $message, array $context = []): void
    {
        $this->addRecord(Level::Emergency, (string) $message, $context);
    }
    /**
     * Sets the timezone to be used for the timestamp of log records.
     *
     * @return $this
     */
    public function setTimezone(DateTimeZone $tz): self
    {
        $this->timezone = $tz;
        return $this;
    }
    /**
     * Returns the timezone to be used for the timestamp of log records.
     */
    public function getTimezone(): DateTimeZone
    {
        return $this->timezone;
    }
    /**
     * Delegates exception management to the custom exception handler,
     * or throws the exception if no custom handler is set.
     */
    protected function handleException(Throwable $e, LogRecord $record): void
    {
        if (null === $this->exceptionHandler) {
            throw $e;
        }
        ($this->exceptionHandler)($e, $record);
    }
    /**
     * @return array<string, mixed>
     */
    public function __serialize(): array
    {
        return ['name' => $this->name, 'handlers' => $this->handlers, 'processors' => $this->processors, 'microsecondTimestamps' => $this->microsecondTimestamps, 'timezone' => $this->timezone, 'exceptionHandler' => $this->exceptionHandler, 'logDepth' => $this->logDepth, 'detectCycles' => $this->detectCycles];
    }
    /**
     * @param array<string, mixed> $data
     */
    public function __unserialize(array $data): void
    {
        foreach (['name', 'handlers', 'processors', 'microsecondTimestamps', 'timezone', 'exceptionHandler', 'logDepth', 'detectCycles'] as $property) {
            if (isset($data[$property])) {
                $this->{$property} = $data[$property];
            }
        }
        $this->fiberLogDepth = new \WeakMap();
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Monolog\Attribute;

/**
 * A reusable attribute to help configure a class or a method as a processor.
 *
 * Using it offers no guarantee: it needs to be leveraged by a Monolog third-party consumer.
 *
 * Using it with the Monolog library only has no effect at all: processors should still be turned into a callable if
 * needed and manually pushed to the loggers and to the processable handlers.
 */
#[\Attribute(\Attribute::TARGET_CLASS | \Attribute::TARGET_METHOD | \Attribute::IS_REPEATABLE)]
class AsMonologProcessor
{
    /**
     * @param string|null $channel  The logging channel the processor should be pushed to.
     * @param string|null $handler  The handler the processor should be pushed to.
     * @param string|null $method   The method that processes the records (if the attribute is used at the class level).
     * @param int|null    $priority The priority of the processor so the order can be determined.
     */
    public function __construct(public readonly ?string $channel = null, public readonly ?string $handler = null, public readonly ?string $method = null, public readonly ?int $priority = null)
    {
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Monolog\Attribute;

/**
 * A reusable attribute to help configure a class as expecting a given logger channel.
 *
 * Using it offers no guarantee: it needs to be leveraged by a Monolog third-party consumer.
 *
 * Using it with the Monolog library only has no effect at all: wiring the logger instance into
 * other classes is not managed by Monolog.
 */
#[\Attribute(\Attribute::TARGET_CLASS)]
final class WithMonologChannel
{
    public function __construct(public readonly string $channel)
    {
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Monolog;

class_alias(JsonSerializableDateTimeImmutable::class, '_ContaoManager\Monolog\DateTimeImmutable');
// @phpstan-ignore-next-line
if (\false) {
    /**
     * @deprecated Use \Monolog\JsonSerializableDateTimeImmutable instead.
     */
    class DateTimeImmutable extends JsonSerializableDateTimeImmutable
    {
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Monolog\Test;

use _ContaoManager\Monolog\Level;
use _ContaoManager\Monolog\Logger;
use _ContaoManager\Monolog\LogRecord;
use _ContaoManager\Monolog\JsonSerializableDateTimeImmutable;
use _ContaoManager\Monolog\Formatter\FormatterInterface;
use _ContaoManager\Psr\Log\LogLevel;
/**
 * Lets you easily generate log records and a dummy formatter for testing purposes
 *
 * @author Jordi Boggiano <j.boggiano@seld.be>
 */
class MonologTestCase extends \_ContaoManager\PHPUnit\Framework\TestCase
{
    /**
     * @param array<mixed> $context
     * @param array<mixed> $extra
     *
     * @phpstan-param value-of<Level::VALUES>|value-of<Level::NAMES>|Level|LogLevel::* $level
     */
    protected function getRecord(int|string|Level $level = Level::Warning, string|\Stringable $message = 'test', array $context = [], string $channel = 'test', \DateTimeImmutable $datetime = new JsonSerializableDateTimeImmutable(\true), array $extra = []): LogRecord
    {
        return new LogRecord(message: (string) $message, context: $context, level: Logger::toMonologLevel($level), channel: $channel, datetime: $datetime, extra: $extra);
    }
    /**
     * @phpstan-return list<LogRecord>
     */
    protected function getMultipleRecords(): array
    {
        return [$this->getRecord(Level::Debug, 'debug message 1'), $this->getRecord(Level::Debug, 'debug message 2'), $this->getRecord(Level::Info, 'information'), $this->getRecord(Level::Warning, 'warning'), $this->getRecord(Level::Error, 'error')];
    }
    protected function getIdentityFormatter(): FormatterInterface
    {
        $formatter = $this->createMock(FormatterInterface::class);
        $formatter->expects(self::any())->method('format')->willReturnCallback(function ($record) {
            return $record->message;
        });
        return $formatter;
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Monolog\Test;

/**
 * Lets you easily generate log records and a dummy formatter for testing purposes
 *
 * @author Jordi Boggiano <j.boggiano@seld.be>
 *
 * @deprecated use MonologTestCase instead.
 */
class TestCase extends MonologTestCase
{
}
<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Monolog;

use InvalidArgumentException;
/**
 * Monolog log registry
 *
 * Allows to get `Logger` instances in the global scope
 * via static method calls on this class.
 *
 * <code>
 * $application = new Monolog\Logger('application');
 * $api = new Monolog\Logger('api');
 *
 * Monolog\Registry::addLogger($application);
 * Monolog\Registry::addLogger($api);
 *
 * function testLogger()
 * {
 *     Monolog\Registry::api()->error('Sent to $api Logger instance');
 *     Monolog\Registry::application()->error('Sent to $application Logger instance');
 * }
 * </code>
 *
 * @author Tomas Tatarko <tomas@tatarko.sk>
 */
class Registry
{
    /**
     * List of all loggers in the registry (by named indexes)
     *
     * @var Logger[]
     */
    private static array $loggers = [];
    /**
     * Adds new logging channel to the registry
     *
     * @param  Logger                    $logger    Instance of the logging channel
     * @param  string|null               $name      Name of the logging channel ($logger->getName() by default)
     * @param  bool                      $overwrite Overwrite instance in the registry if the given name already exists?
     * @throws \InvalidArgumentException If $overwrite set to false and named Logger instance already exists
     */
    public static function addLogger(Logger $logger, ?string $name = null, bool $overwrite = \false): void
    {
        $name = $name ?? $logger->getName();
        if (isset(self::$loggers[$name]) && !$overwrite) {
            throw new InvalidArgumentException('Logger with the given name already exists');
        }
        self::$loggers[$name] = $logger;
    }
    /**
     * Checks if such logging channel exists by name or instance
     *
     * @param string|Logger $logger Name or logger instance
     */
    public static function hasLogger($logger): bool
    {
        if ($logger instanceof Logger) {
            $index = array_search($logger, self::$loggers, \true);
            return \false !== $index;
        }
        return isset(self::$loggers[$logger]);
    }
    /**
     * Removes instance from registry by name or instance
     *
     * @param string|Logger $logger Name or logger instance
     */
    public static function removeLogger($logger): void
    {
        if ($logger instanceof Logger) {
            if (\false !== $idx = array_search($logger, self::$loggers, \true)) {
                unset(self::$loggers[$idx]);
            }
        } else {
            unset(self::$loggers[$logger]);
        }
    }
    /**
     * Clears the registry
     */
    public static function clear(): void
    {
        self::$loggers = [];
    }
    /**
     * Gets Logger instance from the registry
     *
     * @param  string                    $name Name of the requested Logger instance
     * @throws \InvalidArgumentException If named Logger instance is not in the registry
     */
    public static function getInstance(string $name): Logger
    {
        if (!isset(self::$loggers[$name])) {
            throw new InvalidArgumentException(sprintf('Requested "%s" logger instance is not in the registry', $name));
        }
        return self::$loggers[$name];
    }
    /**
     * Gets Logger instance from the registry via static method call
     *
     * @param  string                    $name      Name of the requested Logger instance
     * @param  mixed[]                   $arguments Arguments passed to static method call
     * @throws \InvalidArgumentException If named Logger instance is not in the registry
     * @return Logger                    Requested instance of Logger
     */
    public static function __callStatic(string $name, array $arguments): Logger
    {
        return self::getInstance($name);
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Monolog\Processor;

use _ContaoManager\Monolog\LogRecord;
/**
 * Injects value of gethostname in all records
 */
class HostnameProcessor implements ProcessorInterface
{
    private static string $host;
    public function __construct()
    {
        self::$host = (string) gethostname();
    }
    /**
     * @inheritDoc
     */
    public function __invoke(LogRecord $record): LogRecord
    {
        $record->extra['hostname'] = self::$host;
        return $record;
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Monolog\Processor;

use _ContaoManager\Monolog\Utils;
use _ContaoManager\Monolog\LogRecord;
/**
 * Processes a record's message according to PSR-3 rules
 *
 * It replaces {foo} with the value from $context['foo']
 *
 * @author Jordi Boggiano <j.boggiano@seld.be>
 */
class PsrLogMessageProcessor implements ProcessorInterface
{
    public const SIMPLE_DATE = "Y-m-d\\TH:i:s.uP";
    private ?string $dateFormat;
    private bool $removeUsedContextFields;
    /**
     * @param string|null $dateFormat              The format of the timestamp: one supported by DateTime::format
     * @param bool        $removeUsedContextFields If set to true the fields interpolated into message gets unset
     */
    public function __construct(?string $dateFormat = null, bool $removeUsedContextFields = \false)
    {
        $this->dateFormat = $dateFormat;
        $this->removeUsedContextFields = $removeUsedContextFields;
    }
    /**
     * @inheritDoc
     */
    public function __invoke(LogRecord $record): LogRecord
    {
        if (\false === strpos($record->message, '{')) {
            return $record;
        }
        $replacements = [];
        $context = $record->context;
        foreach ($context as $key => $val) {
            $placeholder = '{' . $key . '}';
            if (strpos($record->message, $placeholder) === \false) {
                continue;
            }
            if (null === $val || \is_scalar($val) || \is_object($val) && method_exists($val, "__toString")) {
                $replacements[$placeholder] = $val;
            } elseif ($val instanceof \DateTimeInterface) {
                if (null === $this->dateFormat && $val instanceof \_ContaoManager\Monolog\JsonSerializableDateTimeImmutable) {
                    // handle monolog dates using __toString if no specific dateFormat was asked for
                    // so that it follows the useMicroseconds flag
                    $replacements[$placeholder] = (string) $val;
                } else {
                    $replacements[$placeholder] = $val->format($this->dateFormat ?? static::SIMPLE_DATE);
                }
            } elseif ($val instanceof \UnitEnum) {
                $replacements[$placeholder] = $val instanceof \BackedEnum ? $val->value : $val->name;
            } elseif (\is_object($val)) {
                $replacements[$placeholder] = '[object ' . Utils::getClass($val) . ']';
            } elseif (\is_array($val)) {
                $replacements[$placeholder] = 'array' . Utils::jsonEncode($val, null, \true);
            } else {
                $replacements[$placeholder] = '[' . \gettype($val) . ']';
            }
            if ($this->removeUsedContextFields) {
                unset($context[$key]);
            }
        }
        return $record->with(message: strtr($record->message, $replacements), context: $context);
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Monolog\Processor;

use ArrayAccess;
use _ContaoManager\Monolog\LogRecord;
/**
 * Injects url/method and remote IP of the current web request in all records
 *
 * @author Jordi Boggiano <j.boggiano@seld.be>
 */
class WebProcessor implements ProcessorInterface
{
    /**
     * @var array<string, mixed>|ArrayAccess<string, mixed>
     */
    protected array|ArrayAccess $serverData;
    /**
     * Default fields
     *
     * Array is structured as [key in record.extra => key in $serverData]
     *
     * @var array<string, string>
     */
    protected array $extraFields = ['url' => 'REQUEST_URI', 'ip' => 'REMOTE_ADDR', 'http_method' => 'REQUEST_METHOD', 'server' => 'SERVER_NAME', 'referrer' => 'HTTP_REFERER', 'user_agent' => 'HTTP_USER_AGENT'];
    /**
     * @param array<string, mixed>|ArrayAccess<string, mixed>|null $serverData  Array or object w/ ArrayAccess that provides access to the $_SERVER data
     * @param array<string, string>|array<string>|null             $extraFields Field names and the related key inside $serverData to be added (or just a list of field names to use the default configured $serverData mapping). If not provided it defaults to: [url, ip, http_method, server, referrer] + unique_id if present in server data
     */
    public function __construct(array|ArrayAccess|null $serverData = null, array|null $extraFields = null)
    {
        if (null === $serverData) {
            $this->serverData =& $_SERVER;
        } else {
            $this->serverData = $serverData;
        }
        $defaultEnabled = ['url', 'ip', 'http_method', 'server', 'referrer'];
        if (isset($this->serverData['UNIQUE_ID'])) {
            $this->extraFields['unique_id'] = 'UNIQUE_ID';
            $defaultEnabled[] = 'unique_id';
        }
        if (null === $extraFields) {
            $extraFields = $defaultEnabled;
        }
        if (isset($extraFields[0])) {
            foreach (array_keys($this->extraFields) as $fieldName) {
                if (!\in_array($fieldName, $extraFields, \true)) {
                    unset($this->extraFields[$fieldName]);
                }
            }
        } else {
            $this->extraFields = $extraFields;
        }
    }
    /**
     * @inheritDoc
     */
    public function __invoke(LogRecord $record): LogRecord
    {
        // skip processing if for some reason request data
        // is not present (CLI or wonky SAPIs)
        if (!isset($this->serverData['REQUEST_URI'])) {
            return $record;
        }
        $record->extra = $this->appendExtraFields($record->extra);
        return $record;
    }
    /**
     * @return $this
     */
    public function addExtraField(string $extraName, string $serverName): self
    {
        $this->extraFields[$extraName] = $serverName;
        return $this;
    }
    /**
     * @param  mixed[] $extra
     * @return mixed[]
     */
    private function appendExtraFields(array $extra): array
    {
        foreach ($this->extraFields as $extraName => $serverName) {
            $extra[$extraName] = $this->serverData[$serverName] ?? null;
        }
        return $extra;
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Monolog\Processor;

use _ContaoManager\Monolog\LogRecord;
/**
 * Injects memory_get_peak_usage in all records
 *
 * @see Monolog\Processor\MemoryProcessor::__construct() for options
 * @author Rob Jensen
 */
class MemoryPeakUsageProcessor extends MemoryProcessor
{
    /**
     * @inheritDoc
     */
    public function __invoke(LogRecord $record): LogRecord
    {
        $usage = memory_get_peak_usage($this->realUsage);
        if ($this->useFormatting) {
            $usage = $this->formatBytes($usage);
        }
        $record->extra['memory_peak_usage'] = $usage;
        return $record;
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Monolog\Processor;

use _ContaoManager\Monolog\LogRecord;
/**
 * Adds value of getmypid into records
 *
 * @author Andreas Hörnicke
 */
class ProcessIdProcessor implements ProcessorInterface
{
    /**
     * @inheritDoc
     */
    public function __invoke(LogRecord $record): LogRecord
    {
        $record->extra['process_id'] = getmypid();
        return $record;
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Monolog\Processor;

use _ContaoManager\Monolog\LogRecord;
/**
 * Injects sys_getloadavg in all records @see https://www.php.net/manual/en/function.sys-getloadavg.php
 *
 * @author Johan Vlaar <johan.vlaar.1994@gmail.com>
 */
class LoadAverageProcessor implements ProcessorInterface
{
    public const LOAD_1_MINUTE = 0;
    public const LOAD_5_MINUTE = 1;
    public const LOAD_15_MINUTE = 2;
    private const AVAILABLE_LOAD = [self::LOAD_1_MINUTE, self::LOAD_5_MINUTE, self::LOAD_15_MINUTE];
    /**
     * @var int
     */
    protected $avgSystemLoad;
    /**
     * @param self::LOAD_* $avgSystemLoad
     */
    public function __construct(int $avgSystemLoad = self::LOAD_1_MINUTE)
    {
        if (!\in_array($avgSystemLoad, self::AVAILABLE_LOAD, \true)) {
            throw new \InvalidArgumentException(sprintf('Invalid average system load: `%s`', $avgSystemLoad));
        }
        $this->avgSystemLoad = $avgSystemLoad;
    }
    /**
     * {@inheritDoc}
     */
    public function __invoke(LogRecord $record): LogRecord
    {
        if (!\function_exists('sys_getloadavg') && !\function_exists('_ContaoManager\sys_getloadavg')) {
            return $record;
        }
        $usage = sys_getloadavg();
        if (\false === $usage) {
            return $record;
        }
        $record->extra['load_average'] = $usage[$this->avgSystemLoad];
        return $record;
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Monolog\Processor;

use _ContaoManager\Monolog\LogRecord;
/**
 * Generates a context from a Closure if the Closure is the only value
 * in the context
 *
 * It helps reduce the performance impact of debug logs if they do
 * need to create lots of context information. If this processor is added
 * on the correct handler the context data will only be generated
 * when the logs are actually logged to that handler, which is useful when
 * using FingersCrossedHandler or other filtering handlers to conditionally
 * log records.
 */
class ClosureContextProcessor implements ProcessorInterface
{
    public function __invoke(LogRecord $record): LogRecord
    {
        $context = $record->context;
        if (isset($context[0]) && 1 === \count($context) && $context[0] instanceof \Closure) {
            try {
                $context = $context[0]();
            } catch (\Throwable $e) {
                $context = ['error_on_context_generation' => $e->getMessage(), 'exception' => $e];
            }
            if (!\is_array($context)) {
                $context = [$context];
            }
            $record = $record->with(context: $context);
        }
        return $record;
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Monolog\Processor;

use _ContaoManager\Monolog\Level;
use _ContaoManager\Monolog\Logger;
use _ContaoManager\Psr\Log\LogLevel;
use _ContaoManager\Monolog\LogRecord;
/**
 * Injects Hg branch and Hg revision number in all records
 *
 * @author Jonathan A. Schweder <jonathanschweder@gmail.com>
 */
class MercurialProcessor implements ProcessorInterface
{
    private Level $level;
    /** @var array{branch: string, revision: string}|array<never>|null */
    private static $cache = null;
    /**
     * @param int|string|Level $level The minimum logging level at which this Processor will be triggered
     *
     * @phpstan-param value-of<Level::VALUES>|value-of<Level::NAMES>|Level|LogLevel::* $level
     */
    public function __construct(int|string|Level $level = Level::Debug)
    {
        $this->level = Logger::toMonologLevel($level);
    }
    /**
     * @inheritDoc
     */
    public function __invoke(LogRecord $record): LogRecord
    {
        // return if the level is not high enough
        if ($record->level->isLowerThan($this->level)) {
            return $record;
        }
        $record->extra['hg'] = self::getMercurialInfo();
        return $record;
    }
    /**
     * @return array{branch: string, revision: string}|array<never>
     */
    private static function getMercurialInfo(): array
    {
        if (self::$cache !== null) {
            return self::$cache;
        }
        $result = explode(' ', trim((string) shell_exec('hg id -nb')));
        if (\count($result) >= 3) {
            return self::$cache = ['branch' => $result[1], 'revision' => $result[2]];
        }
        if (\count($result) === 2) {
            return self::$cache = ['branch' => $result[1], 'revision' => $result[0]];
        }
        return self::$cache = [];
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Monolog\Processor;

use _ContaoManager\Monolog\LogRecord;
/**
 * Adds a tags array into record
 *
 * @author Martijn Riemers
 */
class TagProcessor implements ProcessorInterface
{
    /** @var string[] */
    private array $tags;
    /**
     * @param string[] $tags
     */
    public function __construct(array $tags = [])
    {
        $this->setTags($tags);
    }
    /**
     * @param  string[] $tags
     * @return $this
     */
    public function addTags(array $tags = []): self
    {
        $this->tags = array_merge($this->tags, $tags);
        return $this;
    }
    /**
     * @param  string[] $tags
     * @return $this
     */
    public function setTags(array $tags = []): self
    {
        $this->tags = $tags;
        return $this;
    }
    /**
     * @inheritDoc
     */
    public function __invoke(LogRecord $record): LogRecord
    {
        $record->extra['tags'] = $this->tags;
        return $record;
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Monolog\Processor;

use _ContaoManager\Monolog\Level;
use _ContaoManager\Monolog\Logger;
use _ContaoManager\Psr\Log\LogLevel;
use _ContaoManager\Monolog\LogRecord;
/**
 * Injects Git branch and Git commit SHA in all records
 *
 * @author Nick Otter
 * @author Jordi Boggiano <j.boggiano@seld.be>
 */
class GitProcessor implements ProcessorInterface
{
    private Level $level;
    /** @var array{branch: string, commit: string}|array<never>|null */
    private static $cache = null;
    /**
     * @param int|string|Level|LogLevel::* $level The minimum logging level at which this Processor will be triggered
     *
     * @phpstan-param value-of<Level::VALUES>|value-of<Level::NAMES>|Level|LogLevel::* $level
     */
    public function __construct(int|string|Level $level = Level::Debug)
    {
        $this->level = Logger::toMonologLevel($level);
    }
    /**
     * @inheritDoc
     */
    public function __invoke(LogRecord $record): LogRecord
    {
        // return if the level is not high enough
        if ($record->level->isLowerThan($this->level)) {
            return $record;
        }
        $record->extra['git'] = self::getGitInfo();
        return $record;
    }
    /**
     * @return array{branch: string, commit: string}|array<never>
     */
    private static function getGitInfo(): array
    {
        if (self::$cache !== null) {
            return self::$cache;
        }
        $branches = shell_exec('git branch -v --no-abbrev');
        if (\is_string($branches) && 1 === preg_match('{^\* (.+?)\s+([a-f0-9]{40})(?:\s|$)}m', $branches, $matches)) {
            return self::$cache = ['branch' => $matches[1], 'commit' => $matches[2]];
        }
        return self::$cache = [];
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Monolog\Processor;

/**
 * Some methods that are common for all memory processors
 *
 * @author Rob Jensen
 */
abstract class MemoryProcessor implements ProcessorInterface
{
    /**
     * @var bool If true, get the real size of memory allocated from system. Else, only the memory used by emalloc() is reported.
     */
    protected bool $realUsage;
    /**
     * @var bool If true, then format memory size to human readable string (MB, KB, B depending on size)
     */
    protected bool $useFormatting;
    /**
     * @param bool $realUsage     Set this to true to get the real size of memory allocated from system.
     * @param bool $useFormatting If true, then format memory size to human readable string (MB, KB, B depending on size)
     */
    public function __construct(bool $realUsage = \true, bool $useFormatting = \true)
    {
        $this->realUsage = $realUsage;
        $this->useFormatting = $useFormatting;
    }
    /**
     * Formats bytes into a human readable string if $this->useFormatting is true, otherwise return $bytes as is
     *
     * @return string|int Formatted string if $this->useFormatting is true, otherwise return $bytes as int
     */
    protected function formatBytes(int $bytes)
    {
        if (!$this->useFormatting) {
            return $bytes;
        }
        if ($bytes > 1024 * 1024) {
            return round($bytes / 1024 / 1024, 2) . ' MB';
        } elseif ($bytes > 1024) {
            return round($bytes / 1024, 2) . ' KB';
        }
        return $bytes . ' B';
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Monolog\Processor;

use _ContaoManager\Monolog\Level;
use _ContaoManager\Monolog\Logger;
use _ContaoManager\Psr\Log\LogLevel;
use _ContaoManager\Monolog\LogRecord;
/**
 * Injects line/file:class/function where the log message came from
 *
 * Warning: This only works if the handler processes the logs directly.
 * If you put the processor on a handler that is behind a FingersCrossedHandler
 * for example, the processor will only be called once the trigger level is reached,
 * and all the log records will have the same file/line/.. data from the call that
 * triggered the FingersCrossedHandler.
 *
 * @author Jordi Boggiano <j.boggiano@seld.be>
 */
class IntrospectionProcessor implements ProcessorInterface
{
    protected Level $level;
    /** @var string[] */
    protected array $skipClassesPartials;
    protected int $skipStackFramesCount;
    protected const SKIP_FUNCTIONS = ['call_user_func', 'call_user_func_array'];
    protected const SKIP_CLASSES = ['Monolog\\'];
    /**
     * @param string|int|Level $level               The minimum logging level at which this Processor will be triggered
     * @param string[]         $skipClassesPartials
     *
     * @phpstan-param value-of<Level::VALUES>|value-of<Level::NAMES>|Level|LogLevel::* $level
     */
    public function __construct(int|string|Level $level = Level::Debug, array $skipClassesPartials = [], int $skipStackFramesCount = 0)
    {
        $this->level = Logger::toMonologLevel($level);
        $this->skipClassesPartials = array_merge(static::SKIP_CLASSES, $skipClassesPartials);
        $this->skipStackFramesCount = $skipStackFramesCount;
    }
    /**
     * @inheritDoc
     */
    public function __invoke(LogRecord $record): LogRecord
    {
        // return if the level is not high enough
        if ($record->level->isLowerThan($this->level)) {
            return $record;
        }
        $trace = debug_backtrace(\DEBUG_BACKTRACE_IGNORE_ARGS);
        // skip first since it's always the current method
        array_shift($trace);
        // the call_user_func call is also skipped
        array_shift($trace);
        $i = 0;
        while ($this->isTraceClassOrSkippedFunction($trace, $i)) {
            if (isset($trace[$i]['class'])) {
                foreach ($this->skipClassesPartials as $part) {
                    if (strpos($trace[$i]['class'], $part) !== \false) {
                        $i++;
                        continue 2;
                    }
                }
            } elseif (\in_array($trace[$i]['function'], self::SKIP_FUNCTIONS, \true)) {
                $i++;
                continue;
            }
            break;
        }
        $i += $this->skipStackFramesCount;
        // we should have the call source now
        $record->extra = array_merge($record->extra, ['file' => $trace[$i - 1]['file'] ?? null, 'line' => $trace[$i - 1]['line'] ?? null, 'class' => $trace[$i]['class'] ?? null, 'callType' => $trace[$i]['type'] ?? null, 'function' => $trace[$i]['function'] ?? null]);
        return $record;
    }
    /**
     * @param array<mixed> $trace
     */
    private function isTraceClassOrSkippedFunction(array $trace, int $index): bool
    {
        if (!isset($trace[$index])) {
            return \false;
        }
        return isset($trace[$index]['class']) || \in_array($trace[$index]['function'], self::SKIP_FUNCTIONS, \true);
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Monolog\Processor;

use _ContaoManager\Monolog\ResettableInterface;
use _ContaoManager\Monolog\LogRecord;
/**
 * Adds a unique identifier into records
 *
 * @author Simon Mönch <sm@webfactory.de>
 */
class UidProcessor implements ProcessorInterface, ResettableInterface
{
    /** @var non-empty-string */
    private string $uid;
    /**
     * @param int<1, 32> $length
     */
    public function __construct(int $length = 7)
    {
        if ($length > 32 || $length < 1) {
            throw new \InvalidArgumentException('The uid length must be an integer between 1 and 32');
        }
        $this->uid = $this->generateUid($length);
    }
    /**
     * @inheritDoc
     */
    public function __invoke(LogRecord $record): LogRecord
    {
        $record->extra['uid'] = $this->uid;
        return $record;
    }
    public function getUid(): string
    {
        return $this->uid;
    }
    public function reset(): void
    {
        $this->uid = $this->generateUid(\strlen($this->uid));
    }
    /**
     * @param  positive-int     $length
     * @return non-empty-string
     */
    private function generateUid(int $length): string
    {
        return substr(bin2hex(random_bytes((int) ceil($length / 2))), 0, $length);
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Monolog\Processor;

use _ContaoManager\Monolog\LogRecord;
/**
 * An optional interface to allow labelling Monolog processors.
 *
 * @author Nicolas Grekas <p@tchwork.com>
 */
interface ProcessorInterface
{
    /**
     * @return LogRecord The processed record
     */
    public function __invoke(LogRecord $record);
}
<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Monolog\Processor;

use _ContaoManager\Monolog\LogRecord;
/**
 * Injects memory_get_usage in all records
 *
 * @see Monolog\Processor\MemoryProcessor::__construct() for options
 * @author Rob Jensen
 */
class MemoryUsageProcessor extends MemoryProcessor
{
    /**
     * @inheritDoc
     */
    public function __invoke(LogRecord $record): LogRecord
    {
        $usage = memory_get_usage($this->realUsage);
        if ($this->useFormatting) {
            $usage = $this->formatBytes($usage);
        }
        $record->extra['memory_usage'] = $usage;
        return $record;
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Monolog;

/**
 * Handler or Processor implementing this interface will be reset when Logger::reset() is called.
 *
 * Resetting ends a log cycle gets them back to their initial state.
 *
 * Resetting a Handler or a Processor means flushing/cleaning all buffers, resetting internal
 * state, and getting it back to a state in which it can receive log records again.
 *
 * This is useful in case you want to avoid logs leaking between two requests or jobs when you
 * have a long running process like a worker or an application server serving multiple requests
 * in one process.
 *
 * @author Grégoire Pineau <lyrixx@lyrixx.info>
 */
interface ResettableInterface
{
    public function reset(): void;
}
<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Monolog;

use _ContaoManager\Psr\Log\LoggerInterface;
use _ContaoManager\Psr\Log\LogLevel;
use ReflectionExtension;
/**
 * Monolog POSIX signal handler
 *
 * @author Robert Gust-Bardon <robert@gust-bardon.org>
 */
class SignalHandler
{
    private LoggerInterface $logger;
    /** @var array<int, callable|string|int> SIG_DFL, SIG_IGN or previous callable */
    private array $previousSignalHandler = [];
    /** @var array<int, \Psr\Log\LogLevel::*> */
    private array $signalLevelMap = [];
    /** @var array<int, bool> */
    private array $signalRestartSyscalls = [];
    public function __construct(LoggerInterface $logger)
    {
        $this->logger = $logger;
    }
    /**
     * @param  int|string|Level $level Level or level name
     * @return $this
     *
     * @phpstan-param value-of<Level::VALUES>|value-of<Level::NAMES>|Level|LogLevel::* $level
     */
    public function registerSignalHandler(int $signo, int|string|Level $level = LogLevel::CRITICAL, bool $callPrevious = \true, bool $restartSyscalls = \true, ?bool $async = \true): self
    {
        if (!\extension_loaded('pcntl') || !\function_exists('pcntl_signal') && !\function_exists('_ContaoManager\pcntl_signal')) {
            return $this;
        }
        $level = Logger::toMonologLevel($level)->toPsrLogLevel();
        if ($callPrevious) {
            $handler = pcntl_signal_get_handler($signo);
            $this->previousSignalHandler[$signo] = $handler;
        } else {
            unset($this->previousSignalHandler[$signo]);
        }
        $this->signalLevelMap[$signo] = $level;
        $this->signalRestartSyscalls[$signo] = $restartSyscalls;
        if ($async !== null) {
            pcntl_async_signals($async);
        }
        pcntl_signal($signo, [$this, 'handleSignal'], $restartSyscalls);
        return $this;
    }
    /**
     * @param mixed $siginfo
     */
    public function handleSignal(int $signo, $siginfo = null): void
    {
        /** @var array<int, string> $signals */
        static $signals = [];
        if (\count($signals) === 0 && \extension_loaded('pcntl')) {
            $pcntl = new ReflectionExtension('pcntl');
            foreach ($pcntl->getConstants() as $name => $value) {
                if (substr($name, 0, 3) === 'SIG' && $name[3] !== '_' && \is_int($value)) {
                    $signals[$value] = $name;
                }
            }
        }
        $level = $this->signalLevelMap[$signo] ?? LogLevel::CRITICAL;
        $signal = $signals[$signo] ?? $signo;
        $context = $siginfo ?? [];
        $this->logger->log($level, sprintf('Program received signal %s', $signal), $context);
        if (!isset($this->previousSignalHandler[$signo])) {
            return;
        }
        if ($this->previousSignalHandler[$signo] === \SIG_DFL) {
            if (\extension_loaded('pcntl') && \function_exists('pcntl_signal') && \function_exists('pcntl_sigprocmask') && \function_exists('pcntl_signal_dispatch') && \extension_loaded('posix') && \function_exists('posix_getpid') && \function_exists('posix_kill')) {
                $restartSyscalls = $this->signalRestartSyscalls[$signo] ?? \true;
                pcntl_signal($signo, \SIG_DFL, $restartSyscalls);
                pcntl_sigprocmask(\SIG_UNBLOCK, [$signo], $oldset);
                posix_kill(posix_getpid(), $signo);
                pcntl_signal_dispatch();
                pcntl_sigprocmask(\SIG_SETMASK, $oldset);
                pcntl_signal($signo, [$this, 'handleSignal'], $restartSyscalls);
            }
        } elseif (\is_callable($this->previousSignalHandler[$signo])) {
            $this->previousSignalHandler[$signo]($signo, $siginfo);
        }
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Monolog;

use _ContaoManager\Psr\Log\LogLevel;
/**
 * Represents the log levels
 *
 * Monolog supports the logging levels described by RFC 5424 {@see https://datatracker.ietf.org/doc/html/rfc5424}
 * but due to BC the severity values used internally are not 0-7.
 *
 * To get the level name/value out of a Level there are several options:
 *
 * - Use ->getName() to get the standard Monolog name which is full uppercased (e.g. "DEBUG")
 * - Use ->toPsrLogLevel() to get the standard PSR-3 name which is full lowercased (e.g. "debug")
 * - Use ->toRFC5424Level() to get the standard RFC 5424 value (e.g. 7 for debug, 0 for emergency)
 * - Use ->name to get the enum case's name which is capitalized (e.g. "Debug")
 *
 * To get the internal value for filtering, if the includes/isLowerThan/isHigherThan methods are
 * not enough, you can use ->value to get the enum case's integer value.
 */
enum Level : int
{
    /**
     * Detailed debug information
     */
    case Debug = 100;
    /**
     * Interesting events
     *
     * Examples: User logs in, SQL logs.
     */
    case Info = 200;
    /**
     * Uncommon events
     */
    case Notice = 250;
    /**
     * Exceptional occurrences that are not errors
     *
     * Examples: Use of deprecated APIs, poor use of an API,
     * undesirable things that are not necessarily wrong.
     */
    case Warning = 300;
    /**
     * Runtime errors
     */
    case Error = 400;
    /**
     * Critical conditions
     *
     * Example: Application component unavailable, unexpected exception.
     */
    case Critical = 500;
    /**
     * Action must be taken immediately
     *
     * Example: Entire website down, database unavailable, etc.
     * This should trigger the SMS alerts and wake you up.
     */
    case Alert = 550;
    /**
     * Urgent alert.
     */
    case Emergency = 600;
    /**
     * @param  value-of<self::NAMES>|LogLevel::*|'Debug'|'Info'|'Notice'|'Warning'|'Error'|'Critical'|'Alert'|'Emergency' $name
     * @return static
     */
    public static function fromName(string $name): self
    {
        return match (strtolower($name)) {
            'debug' => self::Debug,
            'info' => self::Info,
            'notice' => self::Notice,
            'warning' => self::Warning,
            'error' => self::Error,
            'critical' => self::Critical,
            'alert' => self::Alert,
            'emergency' => self::Emergency,
        };
    }
    /**
     * @param  value-of<self::VALUES> $value
     * @return static
     */
    public static function fromValue(int $value): self
    {
        return self::from($value);
    }
    /**
     * Returns true if the passed $level is higher or equal to $this
     */
    public function includes(Level $level): bool
    {
        return $this->value <= $level->value;
    }
    public function isHigherThan(Level $level): bool
    {
        return $this->value > $level->value;
    }
    public function isLowerThan(Level $level): bool
    {
        return $this->value < $level->value;
    }
    /**
     * Returns the monolog standardized all-capitals name of the level
     *
     * Use this instead of $level->name which returns the enum case name (e.g. Debug vs DEBUG if you use getName())
     *
     * @return value-of<self::NAMES>
     */
    public function getName(): string
    {
        return match ($this) {
            self::Debug => 'DEBUG',
            self::Info => 'INFO',
            self::Notice => 'NOTICE',
            self::Warning => 'WARNING',
            self::Error => 'ERROR',
            self::Critical => 'CRITICAL',
            self::Alert => 'ALERT',
            self::Emergency => 'EMERGENCY',
        };
    }
    /**
     * Returns the PSR-3 level matching this instance
     *
     * @phpstan-return \Psr\Log\LogLevel::*
     */
    public function toPsrLogLevel(): string
    {
        return match ($this) {
            self::Debug => LogLevel::DEBUG,
            self::Info => LogLevel::INFO,
            self::Notice => LogLevel::NOTICE,
            self::Warning => LogLevel::WARNING,
            self::Error => LogLevel::ERROR,
            self::Critical => LogLevel::CRITICAL,
            self::Alert => LogLevel::ALERT,
            self::Emergency => LogLevel::EMERGENCY,
        };
    }
    /**
     * Returns the RFC 5424 level matching this instance
     *
     * @phpstan-return int<0, 7>
     */
    public function toRFC5424Level(): int
    {
        return match ($this) {
            self::Debug => 7,
            self::Info => 6,
            self::Notice => 5,
            self::Warning => 4,
            self::Error => 3,
            self::Critical => 2,
            self::Alert => 1,
            self::Emergency => 0,
        };
    }
    public const VALUES = [100, 200, 250, 300, 400, 500, 550, 600];
    public const NAMES = ['DEBUG', 'INFO', 'NOTICE', 'WARNING', 'ERROR', 'CRITICAL', 'ALERT', 'EMERGENCY'];
}
<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Monolog\Formatter;

use _ContaoManager\Monolog\LogRecord;
/**
 * Encodes message information into JSON in a format compatible with Logmatic.
 *
 * @author Julien Breux <julien.breux@gmail.com>
 */
class LogmaticFormatter extends JsonFormatter
{
    protected const MARKERS = ["sourcecode", "php"];
    protected string $hostname = '';
    protected string $appName = '';
    /**
     * @return $this
     */
    public function setHostname(string $hostname): self
    {
        $this->hostname = $hostname;
        return $this;
    }
    /**
     * @return $this
     */
    public function setAppName(string $appName): self
    {
        $this->appName = $appName;
        return $this;
    }
    /**
     * Appends the 'hostname' and 'appname' parameter for indexing by Logmatic.
     *
     * @see http://doc.logmatic.io/docs/basics-to-send-data
     * @see \Monolog\Formatter\JsonFormatter::format()
     */
    public function normalizeRecord(LogRecord $record): array
    {
        $record = parent::normalizeRecord($record);
        if ($this->hostname !== '') {
            $record["hostname"] = $this->hostname;
        }
        if ($this->appName !== '') {
            $record["appname"] = $this->appName;
        }
        $record["@marker"] = static::MARKERS;
        return $record;
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Monolog\Formatter;

use _ContaoManager\Elastica\Document;
use _ContaoManager\Monolog\LogRecord;
/**
 * Format a log message into an Elastica Document
 *
 * @author Jelle Vink <jelle.vink@gmail.com>
 */
class ElasticaFormatter extends NormalizerFormatter
{
    /**
     * @var string Elastic search index name
     */
    protected string $index;
    /**
     * @var string|null Elastic search document type
     */
    protected string|null $type;
    /**
     * @param string  $index Elastic Search index name
     * @param ?string $type  Elastic Search document type, deprecated as of Elastica 7
     */
    public function __construct(string $index, ?string $type)
    {
        // elasticsearch requires a ISO 8601 format date with optional millisecond precision.
        parent::__construct('Y-m-d\TH:i:s.uP');
        $this->index = $index;
        $this->type = $type;
    }
    /**
     * @inheritDoc
     */
    public function format(LogRecord $record)
    {
        $record = parent::format($record);
        return $this->getDocument($record);
    }
    public function getIndex(): string
    {
        return $this->index;
    }
    /**
     * @deprecated since Elastica 7 type has no effect
     */
    public function getType(): string
    {
        /** @phpstan-ignore-next-line */
        return $this->type;
    }
    /**
     * Convert a log message into an Elastica Document
     *
     * @param mixed[] $record
     */
    protected function getDocument(array $record): Document
    {
        $document = new Document();
        $document->setData($record);
        $document->setIndex($this->index);
        return $document;
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Monolog\Formatter;

use Closure;
use _ContaoManager\Monolog\Utils;
use _ContaoManager\Monolog\LogRecord;
/**
 * Formats incoming records into a one-line string
 *
 * This is especially useful for logging to files
 *
 * @author Jordi Boggiano <j.boggiano@seld.be>
 * @author Christophe Coevoet <stof@notk.org>
 */
class LineFormatter extends NormalizerFormatter
{
    public const SIMPLE_FORMAT = "[%datetime%] %channel%.%level_name%: %message% %context% %extra%\n";
    protected string $format;
    protected bool $allowInlineLineBreaks;
    protected bool $ignoreEmptyContextAndExtra;
    protected bool $includeStacktraces;
    protected ?int $maxLevelNameLength = null;
    protected string $indentStacktraces = '';
    protected Closure|null $stacktracesParser = null;
    protected string $basePath = '';
    /**
     * @param string|null $format                The format of the message
     * @param string|null $dateFormat            The format of the timestamp: one supported by DateTime::format
     * @param bool        $allowInlineLineBreaks Whether to allow inline line breaks in log entries
     */
    public function __construct(?string $format = null, ?string $dateFormat = null, bool $allowInlineLineBreaks = \false, bool $ignoreEmptyContextAndExtra = \false, bool $includeStacktraces = \false)
    {
        $this->format = $format === null ? static::SIMPLE_FORMAT : $format;
        $this->allowInlineLineBreaks = $allowInlineLineBreaks;
        $this->ignoreEmptyContextAndExtra = $ignoreEmptyContextAndExtra;
        $this->includeStacktraces($includeStacktraces);
        parent::__construct($dateFormat);
    }
    /**
     * Setting a base path will hide the base path from exception and stack trace file names to shorten them
     * @return $this
     */
    public function setBasePath(string $path = ''): self
    {
        if ($path !== '') {
            $path = rtrim($path, \DIRECTORY_SEPARATOR) . \DIRECTORY_SEPARATOR;
        }
        $this->basePath = $path;
        return $this;
    }
    /**
     * @return $this
     */
    public function includeStacktraces(bool $include = \true, ?Closure $parser = null): self
    {
        $this->includeStacktraces = $include;
        if ($this->includeStacktraces) {
            $this->allowInlineLineBreaks = \true;
            $this->stacktracesParser = $parser;
        }
        return $this;
    }
    /**
     * Indent stack traces to separate them a bit from the main log record messages
     *
     * @param  string $indent The string used to indent, for example "    "
     * @return $this
     */
    public function indentStacktraces(string $indent): self
    {
        $this->indentStacktraces = $indent;
        return $this;
    }
    /**
     * @return $this
     */
    public function allowInlineLineBreaks(bool $allow = \true): self
    {
        $this->allowInlineLineBreaks = $allow;
        return $this;
    }
    /**
     * @return $this
     */
    public function ignoreEmptyContextAndExtra(bool $ignore = \true): self
    {
        $this->ignoreEmptyContextAndExtra = $ignore;
        return $this;
    }
    /**
     * Allows cutting the level name to get fixed-length levels like INF for INFO, ERR for ERROR if you set this to 3 for example
     *
     * @param  int|null $maxLevelNameLength Maximum characters for the level name. Set null for infinite length (default)
     * @return $this
     */
    public function setMaxLevelNameLength(?int $maxLevelNameLength = null): self
    {
        $this->maxLevelNameLength = $maxLevelNameLength;
        return $this;
    }
    /**
     * @inheritDoc
     */
    public function format(LogRecord $record): string
    {
        $vars = parent::format($record);
        if ($this->maxLevelNameLength !== null) {
            $vars['level_name'] = substr($vars['level_name'], 0, $this->maxLevelNameLength);
        }
        $output = $this->format;
        foreach ($vars['extra'] as $var => $val) {
            if (\false !== strpos($output, '%extra.' . $var . '%')) {
                $output = str_replace('%extra.' . $var . '%', $this->stringify($val), $output);
                unset($vars['extra'][$var]);
            }
        }
        foreach ($vars['context'] as $var => $val) {
            if (\false !== strpos($output, '%context.' . $var . '%')) {
                $output = str_replace('%context.' . $var . '%', $this->stringify($val), $output);
                unset($vars['context'][$var]);
            }
        }
        if ($this->ignoreEmptyContextAndExtra) {
            if (\count($vars['context']) === 0) {
                unset($vars['context']);
                $output = str_replace('%context%', '', $output);
            }
            if (\count($vars['extra']) === 0) {
                unset($vars['extra']);
                $output = str_replace('%extra%', '', $output);
            }
        }
        foreach ($vars as $var => $val) {
            if (\false !== strpos($output, '%' . $var . '%')) {
                $output = str_replace('%' . $var . '%', $this->stringify($val), $output);
            }
        }
        // remove leftover %extra.xxx% and %context.xxx% if any
        if (\false !== strpos($output, '%')) {
            $output = preg_replace('/%(?:extra|context)\..+?%/', '', $output);
            if (null === $output) {
                $pcreErrorCode = preg_last_error();
                throw new \RuntimeException('Failed to run preg_replace: ' . $pcreErrorCode . ' / ' . preg_last_error_msg());
            }
        }
        return $output;
    }
    public function formatBatch(array $records): string
    {
        $message = '';
        foreach ($records as $record) {
            $message .= $this->format($record);
        }
        return $message;
    }
    /**
     * @param mixed $value
     */
    public function stringify($value): string
    {
        return $this->replaceNewlines($this->convertToString($value));
    }
    protected function normalizeException(\Throwable $e, int $depth = 0): string
    {
        $str = $this->formatException($e);
        $previous = $e->getPrevious();
        while ($previous instanceof \Throwable) {
            $depth++;
            if ($depth > $this->maxNormalizeDepth) {
                $str .= "\n[previous exception] Over " . $this->maxNormalizeDepth . ' levels deep, aborting normalization';
                break;
            }
            $str .= "\n[previous exception] " . $this->formatException($previous);
            $previous = $previous->getPrevious();
        }
        return $str;
    }
    /**
     * @param mixed $data
     */
    protected function convertToString($data): string
    {
        if (null === $data || \is_bool($data)) {
            return var_export($data, \true);
        }
        if (\is_scalar($data)) {
            return (string) $data;
        }
        return $this->toJson($data, \true);
    }
    protected function replaceNewlines(string $str): string
    {
        if ($this->allowInlineLineBreaks) {
            if (0 === strpos($str, '{') || 0 === strpos($str, '[')) {
                $str = preg_replace('/(?<!\\\\)\\\\[rn]/', "\n", $str);
                if (null === $str) {
                    $pcreErrorCode = preg_last_error();
                    throw new \RuntimeException('Failed to run preg_replace: ' . $pcreErrorCode . ' / ' . preg_last_error_msg());
                }
            }
            return $str;
        }
        return str_replace(["\r\n", "\r", "\n"], ' ', $str);
    }
    private function formatException(\Throwable $e): string
    {
        $str = '[object] (' . Utils::getClass($e) . '(code: ' . $e->getCode();
        if ($e instanceof \SoapFault) {
            if (isset($e->faultcode)) {
                $str .= ' faultcode: ' . $e->faultcode;
            }
            if (isset($e->faultactor)) {
                $str .= ' faultactor: ' . $e->faultactor;
            }
            if (isset($e->detail)) {
                if (\is_string($e->detail)) {
                    $str .= ' detail: ' . $e->detail;
                } elseif (\is_object($e->detail) || \is_array($e->detail)) {
                    $str .= ' detail: ' . $this->toJson($e->detail, \true);
                }
            }
        }
        $file = $e->getFile();
        if ($this->basePath !== '') {
            $file = preg_replace('{^' . preg_quote($this->basePath) . '}', '', $file);
        }
        $str .= '): ' . $e->getMessage() . ' at ' . strtr((string) $file, \DIRECTORY_SEPARATOR, '/') . ':' . $e->getLine() . ')';
        if ($this->includeStacktraces) {
            $str .= $this->stacktracesParser($e);
        }
        return $str;
    }
    private function stacktracesParser(\Throwable $e): string
    {
        $trace = $e->getTraceAsString();
        if ($this->basePath !== '') {
            $trace = preg_replace('{^(#\d+ )' . preg_quote($this->basePath) . '}m', '$1', $trace) ?? $trace;
        }
        if ($this->stacktracesParser !== null) {
            $trace = $this->stacktracesParserCustom($trace);
        }
        if ($this->indentStacktraces !== '') {
            $trace = str_replace("\n", "\n{$this->indentStacktraces}", $trace);
        }
        if (trim($trace) === '') {
            return '';
        }
        return "\n{$this->indentStacktraces}[stacktrace]\n{$this->indentStacktraces}" . strtr($trace, \DIRECTORY_SEPARATOR, '/') . "\n";
    }
    private function stacktracesParserCustom(string $trace): string
    {
        return implode("\n", array_filter(array_map($this->stacktracesParser, explode("\n", $trace)), fn($line) => is_string($line) && trim($line) !== ''));
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Monolog\Formatter;

use Stringable;
use Throwable;
use _ContaoManager\Monolog\LogRecord;
/**
 * Encodes whatever record data is passed to it as json
 *
 * This can be useful to log to databases or remote APIs
 *
 * @author Jordi Boggiano <j.boggiano@seld.be>
 */
class JsonFormatter extends NormalizerFormatter
{
    public const BATCH_MODE_JSON = 1;
    public const BATCH_MODE_NEWLINES = 2;
    /** @var self::BATCH_MODE_* */
    protected int $batchMode;
    protected bool $appendNewline;
    protected bool $ignoreEmptyContextAndExtra;
    protected bool $includeStacktraces = \false;
    /**
     * @param self::BATCH_MODE_* $batchMode
     */
    public function __construct(int $batchMode = self::BATCH_MODE_JSON, bool $appendNewline = \true, bool $ignoreEmptyContextAndExtra = \false, bool $includeStacktraces = \false)
    {
        $this->batchMode = $batchMode;
        $this->appendNewline = $appendNewline;
        $this->ignoreEmptyContextAndExtra = $ignoreEmptyContextAndExtra;
        $this->includeStacktraces = $includeStacktraces;
        parent::__construct();
    }
    /**
     * The batch mode option configures the formatting style for
     * multiple records. By default, multiple records will be
     * formatted as a JSON-encoded array. However, for
     * compatibility with some API endpoints, alternative styles
     * are available.
     */
    public function getBatchMode(): int
    {
        return $this->batchMode;
    }
    /**
     * True if newlines are appended to every formatted record
     */
    public function isAppendingNewlines(): bool
    {
        return $this->appendNewline;
    }
    /**
     * @inheritDoc
     */
    public function format(LogRecord $record): string
    {
        $normalized = $this->normalizeRecord($record);
        return $this->toJson($normalized, \true) . ($this->appendNewline ? "\n" : '');
    }
    /**
     * @inheritDoc
     */
    public function formatBatch(array $records): string
    {
        return match ($this->batchMode) {
            static::BATCH_MODE_NEWLINES => $this->formatBatchNewlines($records),
            default => $this->formatBatchJson($records),
        };
    }
    /**
     * @return $this
     */
    public function includeStacktraces(bool $include = \true): self
    {
        $this->includeStacktraces = $include;
        return $this;
    }
    /**
     * @return array<array<mixed>|bool|float|int|\stdClass|string|null>
     */
    protected function normalizeRecord(LogRecord $record): array
    {
        $normalized = parent::normalizeRecord($record);
        if (isset($normalized['context']) && $normalized['context'] === []) {
            if ($this->ignoreEmptyContextAndExtra) {
                unset($normalized['context']);
            } else {
                $normalized['context'] = new \stdClass();
            }
        }
        if (isset($normalized['extra']) && $normalized['extra'] === []) {
            if ($this->ignoreEmptyContextAndExtra) {
                unset($normalized['extra']);
            } else {
                $normalized['extra'] = new \stdClass();
            }
        }
        return $normalized;
    }
    /**
     * Return a JSON-encoded array of records.
     *
     * @phpstan-param LogRecord[] $records
     */
    protected function formatBatchJson(array $records): string
    {
        $formatted = array_map(fn(LogRecord $record) => $this->normalizeRecord($record), $records);
        return $this->toJson($formatted, \true);
    }
    /**
     * Use new lines to separate records instead of a
     * JSON-encoded array.
     *
     * @phpstan-param LogRecord[] $records
     */
    protected function formatBatchNewlines(array $records): string
    {
        $oldNewline = $this->appendNewline;
        $this->appendNewline = \false;
        $formatted = array_map(fn(LogRecord $record) => $this->format($record), $records);
        $this->appendNewline = $oldNewline;
        return implode("\n", $formatted);
    }
    /**
     * Normalizes given $data.
     *
     * @return null|scalar|array<mixed[]|scalar|null|object>|object
     */
    protected function normalize(mixed $data, int $depth = 0): mixed
    {
        if ($depth > $this->maxNormalizeDepth) {
            return 'Over ' . $this->maxNormalizeDepth . ' levels deep, aborting normalization';
        }
        if (\is_array($data)) {
            $normalized = [];
            $count = 1;
            foreach ($data as $key => $value) {
                if ($count++ > $this->maxNormalizeItemCount) {
                    $normalized['...'] = 'Over ' . $this->maxNormalizeItemCount . ' items (' . \count($data) . ' total), aborting normalization';
                    break;
                }
                $normalized[$key] = $this->normalize($value, $depth + 1);
            }
            return $normalized;
        }
        if (\is_object($data)) {
            if ($data instanceof \DateTimeInterface) {
                return $this->formatDate($data);
            }
            if ($data instanceof Throwable) {
                return $this->normalizeException($data, $depth);
            }
            // if the object has specific json serializability we want to make sure we skip the __toString treatment below
            if ($data instanceof \JsonSerializable) {
                return $data;
            }
            if ($data instanceof Stringable) {
                try {
                    return $data->__toString();
                } catch (Throwable) {
                    return $data::class;
                }
            }
            if (\get_class($data) === '__PHP_Incomplete_Class') {
                return new \ArrayObject($data);
            }
            return $data;
        }
        if (\is_resource($data)) {
            return parent::normalize($data);
        }
        return $data;
    }
    /**
     * Normalizes given exception with or without its own stack trace based on
     * `includeStacktraces` property.
     *
     * @return array<array-key, string|int|array<string|int|array<string>>>
     */
    protected function normalizeException(Throwable $e, int $depth = 0): array
    {
        $data = parent::normalizeException($e, $depth);
        if (!$this->includeStacktraces) {
            unset($data['trace']);
        }
        return $data;
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Monolog\Formatter;

use _ContaoManager\Monolog\LogRecord;
/**
 * formats the record to be used in the FlowdockHandler
 *
 * @author Dominik Liebler <liebler.dominik@gmail.com>
 * @deprecated Since 2.9.0 and 3.3.0, Flowdock was shutdown we will thus drop this handler in Monolog 4
 */
class FlowdockFormatter implements FormatterInterface
{
    private string $source;
    private string $sourceEmail;
    public function __construct(string $source, string $sourceEmail)
    {
        $this->source = $source;
        $this->sourceEmail = $sourceEmail;
    }
    /**
     * @inheritDoc
     *
     * @return mixed[]
     */
    public function format(LogRecord $record): array
    {
        $tags = ['#logs', '#' . $record->level->toPsrLogLevel(), '#' . $record->channel];
        foreach ($record->extra as $value) {
            $tags[] = '#' . $value;
        }
        $subject = sprintf('in %s: %s - %s', $this->source, $record->level->getName(), $this->getShortMessage($record->message));
        return ['source' => $this->source, 'from_address' => $this->sourceEmail, 'subject' => $subject, 'content' => $record->message, 'tags' => $tags, 'project' => $this->source];
    }
    /**
     * @inheritDoc
     *
     * @return mixed[][]
     */
    public function formatBatch(array $records): array
    {
        $formatted = [];
        foreach ($records as $record) {
            $formatted[] = $this->format($record);
        }
        return $formatted;
    }
    public function getShortMessage(string $message): string
    {
        static $hasMbString;
        if (null === $hasMbString) {
            $hasMbString = \function_exists('mb_strlen');
        }
        $maxLength = 45;
        if ($hasMbString) {
            if (mb_strlen($message, 'UTF-8') > $maxLength) {
                $message = mb_substr($message, 0, $maxLength - 4, 'UTF-8') . ' ...';
            }
        } else if (\strlen($message) > $maxLength) {
            $message = substr($message, 0, $maxLength - 4) . ' ...';
        }
        return $message;
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Monolog\Formatter;

use _ContaoManager\Monolog\LogRecord;
/**
 * Interface for formatters
 *
 * @author Jordi Boggiano <j.boggiano@seld.be>
 */
interface FormatterInterface
{
    /**
     * Formats a log record.
     *
     * @param  LogRecord $record A record to format
     * @return mixed     The formatted record
     */
    public function format(LogRecord $record);
    /**
     * Formats a set of log records.
     *
     * @param  array<LogRecord> $records A set of records to format
     * @return mixed            The formatted set of records
     */
    public function formatBatch(array $records);
}
<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Monolog\Formatter;

use _ContaoManager\Monolog\LogRecord;
/**
 * Serializes a log message to Logstash Event Format
 *
 * @see https://www.elastic.co/products/logstash
 * @see https://github.com/elastic/logstash/blob/master/logstash-core/src/main/java/org/logstash/Event.java
 *
 * @author Tim Mower <timothy.mower@gmail.com>
 */
class LogstashFormatter extends NormalizerFormatter
{
    /**
     * @var string the name of the system for the Logstash log message, used to fill the @source field
     */
    protected string $systemName;
    /**
     * @var string an application name for the Logstash log message, used to fill the @type field
     */
    protected string $applicationName;
    /**
     * @var string the key for 'extra' fields from the Monolog record
     */
    protected string $extraKey;
    /**
     * @var string the key for 'context' fields from the Monolog record
     */
    protected string $contextKey;
    /**
     * @param string      $applicationName The application that sends the data, used as the "type" field of logstash
     * @param string|null $systemName      The system/machine name, used as the "source" field of logstash, defaults to the hostname of the machine
     * @param string      $extraKey        The key for extra keys inside logstash "fields", defaults to extra
     * @param string      $contextKey      The key for context keys inside logstash "fields", defaults to context
     */
    public function __construct(string $applicationName, ?string $systemName = null, string $extraKey = 'extra', string $contextKey = 'context')
    {
        // logstash requires a ISO 8601 format date with optional millisecond precision.
        parent::__construct('Y-m-d\TH:i:s.uP');
        $this->systemName = $systemName === null ? (string) gethostname() : $systemName;
        $this->applicationName = $applicationName;
        $this->extraKey = $extraKey;
        $this->contextKey = $contextKey;
    }
    /**
     * @inheritDoc
     */
    public function format(LogRecord $record): string
    {
        $recordData = parent::format($record);
        $message = ['@timestamp' => $recordData['datetime'], '@version' => 1, 'host' => $this->systemName];
        if (isset($recordData['message'])) {
            $message['message'] = $recordData['message'];
        }
        if (isset($recordData['channel'])) {
            $message['type'] = $recordData['channel'];
            $message['channel'] = $recordData['channel'];
        }
        if (isset($recordData['level_name'])) {
            $message['level'] = $recordData['level_name'];
        }
        if (isset($recordData['level'])) {
            $message['monolog_level'] = $recordData['level'];
        }
        if ('' !== $this->applicationName) {
            $message['type'] = $this->applicationName;
        }
        if (\count($recordData['extra']) > 0) {
            $message[$this->extraKey] = $recordData['extra'];
        }
        if (\count($recordData['context']) > 0) {
            $message[$this->contextKey] = $recordData['context'];
        }
        return $this->toJson($message) . "\n";
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Monolog\Formatter;

use _ContaoManager\Monolog\LogRecord;
/**
 * Encodes message information into JSON in a format compatible with Loggly.
 *
 * @author Adam Pancutt <adam@pancutt.com>
 */
class LogglyFormatter extends JsonFormatter
{
    /**
     * Overrides the default batch mode to new lines for compatibility with the
     * Loggly bulk API.
     */
    public function __construct(int $batchMode = self::BATCH_MODE_NEWLINES, bool $appendNewline = \false)
    {
        parent::__construct($batchMode, $appendNewline);
    }
    /**
     * Appends the 'timestamp' parameter for indexing by Loggly.
     *
     * @see https://www.loggly.com/docs/automated-parsing/#json
     * @see \Monolog\Formatter\JsonFormatter::format()
     */
    protected function normalizeRecord(LogRecord $record): array
    {
        $recordData = parent::normalizeRecord($record);
        $recordData["timestamp"] = $record->datetime->format("Y-m-d\\TH:i:s.uO");
        unset($recordData["datetime"]);
        return $recordData;
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Monolog\Formatter;

use DateTimeInterface;
use _ContaoManager\Monolog\LogRecord;
/**
 * Format a log message into an Elasticsearch record
 *
 * @author Avtandil Kikabidze <akalongman@gmail.com>
 */
class ElasticsearchFormatter extends NormalizerFormatter
{
    /**
     * @var string Elasticsearch index name
     */
    protected string $index;
    /**
     * @var string Elasticsearch record type
     */
    protected string $type;
    /**
     * @param string $index Elasticsearch index name
     * @param string $type  Elasticsearch record type
     */
    public function __construct(string $index, string $type)
    {
        // Elasticsearch requires an ISO 8601 format date with optional millisecond precision.
        parent::__construct(DateTimeInterface::ATOM);
        $this->index = $index;
        $this->type = $type;
    }
    /**
     * @inheritDoc
     */
    public function format(LogRecord $record)
    {
        $record = parent::format($record);
        return $this->getDocument($record);
    }
    /**
     * Getter index
     */
    public function getIndex(): string
    {
        return $this->index;
    }
    /**
     * Getter type
     */
    public function getType(): string
    {
        return $this->type;
    }
    /**
     * Convert a log message into an Elasticsearch record
     *
     * @param  mixed[] $record Log message
     * @return mixed[]
     */
    protected function getDocument(array $record): array
    {
        $record['_index'] = $this->index;
        $record['_type'] = $this->type;
        return $record;
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Monolog\Formatter;

use _ContaoManager\Monolog\LogRecord;
/**
 * Formats data into an associative array of scalar (+ null) values.
 * Objects and arrays will be JSON encoded.
 *
 * @author Andrew Lawson <adlawson@gmail.com>
 */
class ScalarFormatter extends NormalizerFormatter
{
    /**
     * @inheritDoc
     *
     * @phpstan-return array<string, scalar|null> $record
     */
    public function format(LogRecord $record): array
    {
        $result = [];
        foreach ($record->toArray() as $key => $value) {
            $result[$key] = $this->toScalar($value);
        }
        return $result;
    }
    protected function toScalar(mixed $value): string|int|float|bool|null
    {
        $normalized = $this->normalize($value);
        if (\is_array($normalized)) {
            return $this->toJson($normalized, \true);
        }
        return $normalized;
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Monolog\Formatter;

use MongoDB\BSON\Type;
use MongoDB\BSON\UTCDateTime;
use _ContaoManager\Monolog\Utils;
use _ContaoManager\Monolog\LogRecord;
/**
 * Formats a record for use with the MongoDBHandler.
 *
 * @author Florian Plattner <me@florianplattner.de>
 */
class MongoDBFormatter implements FormatterInterface
{
    private bool $exceptionTraceAsString;
    private int $maxNestingLevel;
    /**
     * @param int  $maxNestingLevel        0 means infinite nesting, the $record itself is level 1, $record->context is 2
     * @param bool $exceptionTraceAsString set to false to log exception traces as a sub documents instead of strings
     */
    public function __construct(int $maxNestingLevel = 3, bool $exceptionTraceAsString = \true)
    {
        $this->maxNestingLevel = max($maxNestingLevel, 0);
        $this->exceptionTraceAsString = $exceptionTraceAsString;
    }
    /**
     * @inheritDoc
     *
     * @return mixed[]
     */
    public function format(LogRecord $record): array
    {
        /** @var mixed[] $res */
        $res = $this->formatArray($record->toArray());
        return $res;
    }
    /**
     * @inheritDoc
     *
     * @return array<mixed[]>
     */
    public function formatBatch(array $records): array
    {
        $formatted = [];
        foreach ($records as $key => $record) {
            $formatted[$key] = $this->format($record);
        }
        return $formatted;
    }
    /**
     * @param  mixed[]        $array
     * @return mixed[]|string Array except when max nesting level is reached then a string "[...]"
     */
    protected function formatArray(array $array, int $nestingLevel = 0)
    {
        if ($this->maxNestingLevel > 0 && $nestingLevel > $this->maxNestingLevel) {
            return '[...]';
        }
        foreach ($array as $name => $value) {
            if ($value instanceof \DateTimeInterface) {
                $array[$name] = $this->formatDate($value, $nestingLevel + 1);
            } elseif ($value instanceof \Throwable) {
                $array[$name] = $this->formatException($value, $nestingLevel + 1);
            } elseif (\is_array($value)) {
                $array[$name] = $this->formatArray($value, $nestingLevel + 1);
            } elseif (\is_object($value) && !$value instanceof Type) {
                $array[$name] = $this->formatObject($value, $nestingLevel + 1);
            }
        }
        return $array;
    }
    /**
     * @param  mixed          $value
     * @return mixed[]|string
     */
    protected function formatObject($value, int $nestingLevel)
    {
        $objectVars = get_object_vars($value);
        $objectVars['class'] = Utils::getClass($value);
        return $this->formatArray($objectVars, $nestingLevel);
    }
    /**
     * @return mixed[]|string
     */
    protected function formatException(\Throwable $exception, int $nestingLevel)
    {
        $formattedException = ['class' => Utils::getClass($exception), 'message' => $exception->getMessage(), 'code' => (int) $exception->getCode(), 'file' => $exception->getFile() . ':' . $exception->getLine()];
        if ($this->exceptionTraceAsString === \true) {
            $formattedException['trace'] = $exception->getTraceAsString();
        } else {
            $formattedException['trace'] = $exception->getTrace();
        }
        return $this->formatArray($formattedException, $nestingLevel);
    }
    protected function formatDate(\DateTimeInterface $value, int $nestingLevel): UTCDateTime
    {
        return new UTCDateTime((int) floor((float) $value->format('U.u') * 1000));
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Monolog\Formatter;

use _ContaoManager\Monolog\Level;
use _ContaoManager\Monolog\LogRecord;
/**
 * Formats a log message according to the ChromePHP array format
 *
 * @author Christophe Coevoet <stof@notk.org>
 */
class ChromePHPFormatter implements FormatterInterface
{
    /**
     * Translates Monolog log levels to Wildfire levels.
     *
     * @return 'log'|'info'|'warn'|'error'
     */
    private function toWildfireLevel(Level $level): string
    {
        return match ($level) {
            Level::Debug => 'log',
            Level::Info => 'info',
            Level::Notice => 'info',
            Level::Warning => 'warn',
            Level::Error => 'error',
            Level::Critical => 'error',
            Level::Alert => 'error',
            Level::Emergency => 'error',
        };
    }
    /**
     * @inheritDoc
     */
    public function format(LogRecord $record)
    {
        // Retrieve the line and file if set and remove them from the formatted extra
        $backtrace = 'unknown';
        if (isset($record->extra['file'], $record->extra['line'])) {
            $backtrace = $record->extra['file'] . ' : ' . $record->extra['line'];
            unset($record->extra['file'], $record->extra['line']);
        }
        $message = ['message' => $record->message];
        if (\count($record->context) > 0) {
            $message['context'] = $record->context;
        }
        if (\count($record->extra) > 0) {
            $message['extra'] = $record->extra;
        }
        if (\count($message) === 1) {
            $message = reset($message);
        }
        return [$record->channel, $message, $backtrace, $this->toWildfireLevel($record->level)];
    }
    /**
     * @inheritDoc
     */
    public function formatBatch(array $records)
    {
        $formatted = [];
        foreach ($records as $record) {
            $formatted[] = $this->format($record);
        }
        return $formatted;
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Monolog\Formatter;

use _ContaoManager\Monolog\Utils;
use _ContaoManager\Monolog\LogRecord;
/**
 * Class FluentdFormatter
 *
 * Serializes a log message to Fluentd unix socket protocol
 *
 * Fluentd config:
 *
 * <source>
 *  type unix
 *  path /var/run/td-agent/td-agent.sock
 * </source>
 *
 * Monolog setup:
 *
 * $logger = new Monolog\Logger('fluent.tag');
 * $fluentHandler = new Monolog\Handler\SocketHandler('unix:///var/run/td-agent/td-agent.sock');
 * $fluentHandler->setFormatter(new Monolog\Formatter\FluentdFormatter());
 * $logger->pushHandler($fluentHandler);
 *
 * @author Andrius Putna <fordnox@gmail.com>
 */
class FluentdFormatter implements FormatterInterface
{
    /**
     * @var bool $levelTag should message level be a part of the fluentd tag
     */
    protected bool $levelTag = \false;
    public function __construct(bool $levelTag = \false)
    {
        $this->levelTag = $levelTag;
    }
    public function isUsingLevelsInTag(): bool
    {
        return $this->levelTag;
    }
    public function format(LogRecord $record): string
    {
        $tag = $record->channel;
        if ($this->levelTag) {
            $tag .= '.' . $record->level->toPsrLogLevel();
        }
        $message = ['message' => $record->message, 'context' => $record->context, 'extra' => $record->extra];
        if (!$this->levelTag) {
            $message['level'] = $record->level->value;
            $message['level_name'] = $record->level->getName();
        }
        return Utils::jsonEncode([$tag, $record->datetime->getTimestamp(), $message]);
    }
    public function formatBatch(array $records): string
    {
        $message = '';
        foreach ($records as $record) {
            $message .= $this->format($record);
        }
        return $message;
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Monolog\Formatter;

use _ContaoManager\Monolog\Level;
use _ContaoManager\Gelf\Message;
use _ContaoManager\Monolog\Utils;
use _ContaoManager\Monolog\LogRecord;
/**
 * Serializes a log message to GELF
 * @see http://docs.graylog.org/en/latest/pages/gelf.html
 *
 * @author Matt Lehner <mlehner@gmail.com>
 */
class GelfMessageFormatter extends NormalizerFormatter
{
    protected const DEFAULT_MAX_LENGTH = 32766;
    /**
     * @var string the name of the system for the Gelf log message
     */
    protected string $systemName;
    /**
     * @var string a prefix for 'extra' fields from the Monolog record (optional)
     */
    protected string $extraPrefix;
    /**
     * @var string a prefix for 'context' fields from the Monolog record (optional)
     */
    protected string $contextPrefix;
    /**
     * @var int max length per field
     */
    protected int $maxLength;
    /**
     * Translates Monolog log levels to Graylog2 log priorities.
     */
    private function getGraylog2Priority(Level $level): int
    {
        return match ($level) {
            Level::Debug => 7,
            Level::Info => 6,
            Level::Notice => 5,
            Level::Warning => 4,
            Level::Error => 3,
            Level::Critical => 2,
            Level::Alert => 1,
            Level::Emergency => 0,
        };
    }
    /**
     * @throws \RuntimeException
     */
    public function __construct(?string $systemName = null, ?string $extraPrefix = null, string $contextPrefix = 'ctxt_', ?int $maxLength = null)
    {
        if (!class_exists(Message::class)) {
            throw new \RuntimeException('Composer package graylog2/gelf-php is required to use Monolog\'s GelfMessageFormatter');
        }
        parent::__construct('U.u');
        $this->systemName = null === $systemName || $systemName === '' ? (string) gethostname() : $systemName;
        $this->extraPrefix = null === $extraPrefix ? '' : $extraPrefix;
        $this->contextPrefix = $contextPrefix;
        $this->maxLength = null === $maxLength ? self::DEFAULT_MAX_LENGTH : $maxLength;
    }
    /**
     * @inheritDoc
     */
    public function format(LogRecord $record): Message
    {
        $context = $extra = [];
        if (isset($record->context)) {
            /** @var array<array<mixed>|bool|float|int|string|null> $context */
            $context = parent::normalize($record->context);
        }
        if (isset($record->extra)) {
            /** @var array<array<mixed>|bool|float|int|string|null> $extra */
            $extra = parent::normalize($record->extra);
        }
        $message = new Message();
        $message->setTimestamp($record->datetime)->setShortMessage($record->message)->setHost($this->systemName)->setLevel($this->getGraylog2Priority($record->level));
        // message length + system name length + 200 for padding / metadata
        $len = 200 + \strlen($record->message) + \strlen($this->systemName);
        if ($len > $this->maxLength) {
            $message->setShortMessage(Utils::substr($record->message, 0, $this->maxLength));
        }
        if (isset($record->channel)) {
            $message->setAdditional('facility', $record->channel);
        }
        foreach ($extra as $key => $val) {
            $key = (string) preg_replace('#[^\w.-]#', '-', (string) $key);
            $val = \is_bool($val) ? $val ? 1 : 0 : $val;
            $val = \is_scalar($val) || null === $val ? $val : $this->toJson($val);
            $len = \strlen($this->extraPrefix . $key . $val);
            if ($len > $this->maxLength) {
                $message->setAdditional($this->extraPrefix . $key, Utils::substr((string) $val, 0, $this->maxLength));
                continue;
            }
            $message->setAdditional($this->extraPrefix . $key, $val);
        }
        foreach ($context as $key => $val) {
            $key = (string) preg_replace('#[^\w.-]#', '-', (string) $key);
            $val = \is_bool($val) ? $val ? 1 : 0 : $val;
            $val = \is_scalar($val) || null === $val ? $val : $this->toJson($val);
            $len = \strlen($this->contextPrefix . $key . $val);
            if ($len > $this->maxLength) {
                $message->setAdditional($this->contextPrefix . $key, Utils::substr((string) $val, 0, $this->maxLength));
                continue;
            }
            $message->setAdditional($this->contextPrefix . $key, $val);
        }
        if (!$message->hasAdditional('file') && isset($context['exception']['file'])) {
            if (1 === preg_match("/^(.+):([0-9]+)\$/", $context['exception']['file'], $matches)) {
                $message->setAdditional('file', $matches[1]);
                $message->setAdditional('line', $matches[2]);
            }
        }
        return $message;
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Monolog\Formatter;

use _ContaoManager\Monolog\Level;
use _ContaoManager\Monolog\LogRecord;
/**
 * Serializes a log message according to Wildfire's header requirements
 *
 * @author Eric Clemmons (@ericclemmons) <eric@uxdriven.com>
 * @author Christophe Coevoet <stof@notk.org>
 * @author Kirill chEbba Chebunin <iam@chebba.org>
 */
class WildfireFormatter extends NormalizerFormatter
{
    /**
     * @param string|null $dateFormat The format of the timestamp: one supported by DateTime::format
     */
    public function __construct(?string $dateFormat = null)
    {
        parent::__construct($dateFormat);
        // http headers do not like non-ISO-8559-1 characters
        $this->removeJsonEncodeOption(\JSON_UNESCAPED_UNICODE);
    }
    /**
     * Translates Monolog log levels to Wildfire levels.
     *
     * @return 'LOG'|'INFO'|'WARN'|'ERROR'
     */
    private function toWildfireLevel(Level $level): string
    {
        return match ($level) {
            Level::Debug => 'LOG',
            Level::Info => 'INFO',
            Level::Notice => 'INFO',
            Level::Warning => 'WARN',
            Level::Error => 'ERROR',
            Level::Critical => 'ERROR',
            Level::Alert => 'ERROR',
            Level::Emergency => 'ERROR',
        };
    }
    /**
     * @inheritDoc
     */
    public function format(LogRecord $record): string
    {
        // Retrieve the line and file if set and remove them from the formatted extra
        $file = $line = '';
        if (isset($record->extra['file'])) {
            $file = $record->extra['file'];
            unset($record->extra['file']);
        }
        if (isset($record->extra['line'])) {
            $line = $record->extra['line'];
            unset($record->extra['line']);
        }
        $message = ['message' => $record->message];
        $handleError = \false;
        if (\count($record->context) > 0) {
            $message['context'] = $this->normalize($record->context);
            $handleError = \true;
        }
        if (\count($record->extra) > 0) {
            $message['extra'] = $this->normalize($record->extra);
            $handleError = \true;
        }
        if (\count($message) === 1) {
            $message = reset($message);
        }
        if (is_array($message) && isset($message['context']) && \is_array($message['context']) && isset($message['context']['table'])) {
            $type = 'TABLE';
            $label = $record->channel . ': ' . $record->message;
            $message = $message['context']['table'];
        } else {
            $type = $this->toWildfireLevel($record->level);
            $label = $record->channel;
        }
        // Create JSON object describing the appearance of the message in the console
        $json = $this->toJson([['Type' => $type, 'File' => $file, 'Line' => $line, 'Label' => $label], $message], $handleError);
        // The message itself is a serialization of the above JSON object + it's length
        return sprintf('%d|%s|', \strlen($json), $json);
    }
    /**
     * @inheritDoc
     *
     * @phpstan-return never
     */
    public function formatBatch(array $records)
    {
        throw new \BadMethodCallException('Batch formatting does not make sense for the WildfireFormatter');
    }
    /**
     * @inheritDoc
     *
     * @return null|scalar|array<mixed[]|scalar|null>|object
     */
    protected function normalize(mixed $data, int $depth = 0): mixed
    {
        if (\is_object($data) && !$data instanceof \DateTimeInterface) {
            return $data;
        }
        return parent::normalize($data, $depth);
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Monolog\Formatter;

use DateTimeInterface;
use _ContaoManager\Monolog\LogRecord;
/**
 * Encodes message information into JSON in a format compatible with Cloud logging.
 *
 * @see https://cloud.google.com/logging/docs/structured-logging
 * @see https://cloud.google.com/logging/docs/reference/v2/rest/v2/LogEntry
 *
 * @author Luís Cobucci <lcobucci@gmail.com>
 */
class GoogleCloudLoggingFormatter extends JsonFormatter
{
    protected function normalizeRecord(LogRecord $record): array
    {
        $normalized = parent::normalizeRecord($record);
        // Re-key level for GCP logging
        $normalized['severity'] = $normalized['level_name'];
        $normalized['time'] = $record->datetime->format(DateTimeInterface::RFC3339_EXTENDED);
        // Remove keys that are not used by GCP
        unset($normalized['level'], $normalized['level_name'], $normalized['datetime']);
        return $normalized;
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Monolog\Formatter;

use _ContaoManager\Monolog\Level;
use _ContaoManager\Monolog\LogRecord;
/**
 * Serializes a log message according to RFC 5424
 *
 * @author Dalibor Karlović <dalibor.karlovic@sigwin.hr>
 * @author Renat Gabdullin <renatobyj@gmail.com>
 */
class SyslogFormatter extends LineFormatter
{
    private const SYSLOG_FACILITY_USER = 1;
    private const FORMAT = "<%extra.priority%>1 %datetime% %extra.hostname% %extra.app-name% %extra.procid% %channel% %extra.structured-data% %level_name%: %message% %context% %extra%\n";
    private const NILVALUE = '-';
    private string $hostname;
    private int $procid;
    public function __construct(private string $applicationName = self::NILVALUE)
    {
        parent::__construct(self::FORMAT, 'Y-m-d\TH:i:s.uP', \true, \true);
        $this->hostname = (string) gethostname();
        $this->procid = (int) getmypid();
    }
    public function format(LogRecord $record): string
    {
        $record->extra = $this->formatExtra($record);
        return parent::format($record);
    }
    /**
     * @return array<string, mixed>
     */
    private function formatExtra(LogRecord $record): array
    {
        $extra = $record->extra;
        $extra['app-name'] = $this->applicationName;
        $extra['hostname'] = $this->hostname;
        $extra['procid'] = $this->procid;
        $extra['priority'] = self::calculatePriority($record->level);
        $extra['structured-data'] = self::NILVALUE;
        return $extra;
    }
    private static function calculatePriority(Level $level): int
    {
        return self::SYSLOG_FACILITY_USER * 8 + $level->toRFC5424Level();
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Monolog\Formatter;

use _ContaoManager\Monolog\JsonSerializableDateTimeImmutable;
use _ContaoManager\Monolog\Utils;
use Throwable;
use _ContaoManager\Monolog\LogRecord;
/**
 * Normalizes incoming records to remove objects/resources so it's easier to dump to various targets
 *
 * @author Jordi Boggiano <j.boggiano@seld.be>
 */
class NormalizerFormatter implements FormatterInterface
{
    public const SIMPLE_DATE = "Y-m-d\\TH:i:sP";
    protected string $dateFormat;
    protected int $maxNormalizeDepth = 9;
    protected int $maxNormalizeItemCount = 1000;
    private int $jsonEncodeOptions = Utils::DEFAULT_JSON_FLAGS;
    protected string $basePath = '';
    /**
     * @param string|null $dateFormat The format of the timestamp: one supported by DateTime::format
     */
    public function __construct(?string $dateFormat = null)
    {
        $this->dateFormat = null === $dateFormat ? static::SIMPLE_DATE : $dateFormat;
    }
    /**
     * @inheritDoc
     */
    public function format(LogRecord $record)
    {
        return $this->normalizeRecord($record);
    }
    /**
     * Normalize an arbitrary value to a scalar|array|null
     *
     * @return null|scalar|array<mixed[]|scalar|null>
     */
    public function normalizeValue(mixed $data): mixed
    {
        return $this->normalize($data);
    }
    /**
     * @inheritDoc
     */
    public function formatBatch(array $records)
    {
        foreach ($records as $key => $record) {
            $records[$key] = $this->format($record);
        }
        return $records;
    }
    public function getDateFormat(): string
    {
        return $this->dateFormat;
    }
    /**
     * @return $this
     */
    public function setDateFormat(string $dateFormat): self
    {
        $this->dateFormat = $dateFormat;
        return $this;
    }
    /**
     * The maximum number of normalization levels to go through
     */
    public function getMaxNormalizeDepth(): int
    {
        return $this->maxNormalizeDepth;
    }
    /**
     * @return $this
     */
    public function setMaxNormalizeDepth(int $maxNormalizeDepth): self
    {
        $this->maxNormalizeDepth = $maxNormalizeDepth;
        return $this;
    }
    /**
     * The maximum number of items to normalize per level
     */
    public function getMaxNormalizeItemCount(): int
    {
        return $this->maxNormalizeItemCount;
    }
    /**
     * @return $this
     */
    public function setMaxNormalizeItemCount(int $maxNormalizeItemCount): self
    {
        $this->maxNormalizeItemCount = $maxNormalizeItemCount;
        return $this;
    }
    /**
     * Enables `json_encode` pretty print.
     *
     * @return $this
     */
    public function setJsonPrettyPrint(bool $enable): self
    {
        if ($enable) {
            $this->jsonEncodeOptions |= \JSON_PRETTY_PRINT;
        } else {
            $this->jsonEncodeOptions &= ~\JSON_PRETTY_PRINT;
        }
        return $this;
    }
    /**
     * Setting a base path will hide the base path from exception and stack trace file names to shorten them
     * @return $this
     */
    public function setBasePath(string $path = ''): self
    {
        if ($path !== '') {
            $path = rtrim($path, \DIRECTORY_SEPARATOR) . \DIRECTORY_SEPARATOR;
        }
        $this->basePath = $path;
        return $this;
    }
    /**
     * Provided as extension point
     *
     * Because normalize is called with sub-values of context data etc, normalizeRecord can be
     * extended when data needs to be appended on the record array but not to other normalized data.
     *
     * @return array<mixed[]|scalar|null>
     */
    protected function normalizeRecord(LogRecord $record): array
    {
        /** @var array<mixed[]|scalar|null> $normalized */
        $normalized = $this->normalize($record->toArray());
        return $normalized;
    }
    /**
     * @return null|scalar|array<mixed[]|scalar|null>
     */
    protected function normalize(mixed $data, int $depth = 0): mixed
    {
        if ($depth > $this->maxNormalizeDepth) {
            return 'Over ' . $this->maxNormalizeDepth . ' levels deep, aborting normalization';
        }
        if (null === $data || \is_scalar($data)) {
            if (\is_float($data)) {
                if (is_infinite($data)) {
                    return ($data > 0 ? '' : '-') . 'INF';
                }
                if (is_nan($data)) {
                    return 'NaN';
                }
            }
            return $data;
        }
        if (\is_array($data)) {
            $normalized = [];
            $count = 1;
            foreach ($data as $key => $value) {
                if ($count++ > $this->maxNormalizeItemCount) {
                    $normalized['...'] = 'Over ' . $this->maxNormalizeItemCount . ' items (' . \count($data) . ' total), aborting normalization';
                    break;
                }
                $normalized[$key] = $this->normalize($value, $depth + 1);
            }
            return $normalized;
        }
        if ($data instanceof \DateTimeInterface) {
            return $this->formatDate($data);
        }
        if (\is_object($data)) {
            if ($data instanceof Throwable) {
                return $this->normalizeException($data, $depth);
            }
            if ($data instanceof \JsonSerializable) {
                /** @var null|scalar|array<mixed[]|scalar|null> $value */
                $value = $data->jsonSerialize();
            } elseif (\get_class($data) === '__PHP_Incomplete_Class') {
                $accessor = new \ArrayObject($data);
                $value = (string) $accessor['__PHP_Incomplete_Class_Name'];
            } elseif (method_exists($data, '__toString')) {
                try {
                    /** @var string $value */
                    $value = $data->__toString();
                } catch (\Throwable) {
                    // if the toString method is failing, use the default behavior
                    /** @var null|scalar|array<mixed[]|scalar|null> $value */
                    $value = json_decode($this->toJson($data, \true), \true);
                }
            } else {
                // the rest is normalized by json encoding and decoding it
                /** @var null|scalar|array<mixed[]|scalar|null> $value */
                $value = json_decode($this->toJson($data, \true), \true);
            }
            return [Utils::getClass($data) => $value];
        }
        if (\is_resource($data)) {
            return sprintf('[resource(%s)]', get_resource_type($data));
        }
        return '[unknown(' . \gettype($data) . ')]';
    }
    /**
     * @return array<array-key, string|int|array<string|int|array<string>>>
     */
    protected function normalizeException(Throwable $e, int $depth = 0)
    {
        if ($depth > $this->maxNormalizeDepth) {
            return ['Over ' . $this->maxNormalizeDepth . ' levels deep, aborting normalization'];
        }
        if ($e instanceof \JsonSerializable) {
            return (array) $e->jsonSerialize();
        }
        $file = $e->getFile();
        if ($this->basePath !== '') {
            $file = preg_replace('{^' . preg_quote($this->basePath) . '}', '', $file);
        }
        $data = ['class' => Utils::getClass($e), 'message' => $e->getMessage(), 'code' => (int) $e->getCode(), 'file' => $file . ':' . $e->getLine()];
        if ($e instanceof \SoapFault) {
            if (isset($e->faultcode)) {
                $data['faultcode'] = $e->faultcode;
            }
            if (isset($e->faultactor)) {
                $data['faultactor'] = $e->faultactor;
            }
            if (isset($e->detail)) {
                if (\is_string($e->detail)) {
                    $data['detail'] = $e->detail;
                } elseif (\is_object($e->detail) || \is_array($e->detail)) {
                    $data['detail'] = $this->toJson($e->detail, \true);
                }
            }
        }
        $trace = $e->getTrace();
        foreach ($trace as $frame) {
            if (isset($frame['file'], $frame['line'])) {
                $file = $frame['file'];
                if ($this->basePath !== '') {
                    $file = preg_replace('{^' . preg_quote($this->basePath) . '}', '', $file);
                }
                $data['trace'][] = $file . ':' . $frame['line'];
            }
        }
        if (($previous = $e->getPrevious()) instanceof \Throwable) {
            $data['previous'] = $this->normalizeException($previous, $depth + 1);
        }
        return $data;
    }
    /**
     * Return the JSON representation of a value
     *
     * @param  mixed             $data
     * @throws \RuntimeException if encoding fails and errors are not ignored
     * @return string            if encoding fails and ignoreErrors is true 'null' is returned
     */
    protected function toJson($data, bool $ignoreErrors = \false): string
    {
        return Utils::jsonEncode($data, $this->jsonEncodeOptions, $ignoreErrors);
    }
    protected function formatDate(\DateTimeInterface $date): string
    {
        // in case the date format isn't custom then we defer to the custom JsonSerializableDateTimeImmutable
        // formatting logic, which will pick the right format based on whether useMicroseconds is on
        if ($this->dateFormat === self::SIMPLE_DATE && $date instanceof JsonSerializableDateTimeImmutable) {
            return (string) $date;
        }
        return $date->format($this->dateFormat);
    }
    /**
     * @return $this
     */
    public function addJsonEncodeOption(int $option): self
    {
        $this->jsonEncodeOptions |= $option;
        return $this;
    }
    /**
     * @return $this
     */
    public function removeJsonEncodeOption(int $option): self
    {
        $this->jsonEncodeOptions &= ~$option;
        return $this;
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Monolog\Formatter;

use _ContaoManager\Monolog\Level;
use _ContaoManager\Monolog\Utils;
use _ContaoManager\Monolog\LogRecord;
/**
 * Formats incoming records into an HTML table
 *
 * This is especially useful for html email logging
 *
 * @author Tiago Brito <tlfbrito@gmail.com>
 */
class HtmlFormatter extends NormalizerFormatter
{
    /**
     * Translates Monolog log levels to html color priorities.
     */
    protected function getLevelColor(Level $level): string
    {
        return match ($level) {
            Level::Debug => '#CCCCCC',
            Level::Info => '#28A745',
            Level::Notice => '#17A2B8',
            Level::Warning => '#FFC107',
            Level::Error => '#FD7E14',
            Level::Critical => '#DC3545',
            Level::Alert => '#821722',
            Level::Emergency => '#000000',
        };
    }
    /**
     * @param string|null $dateFormat The format of the timestamp: one supported by DateTime::format
     */
    public function __construct(?string $dateFormat = null)
    {
        parent::__construct($dateFormat);
    }
    /**
     * Creates an HTML table row
     *
     * @param string $th       Row header content
     * @param string $td       Row standard cell content
     * @param bool   $escapeTd false if td content must not be html escaped
     */
    protected function addRow(string $th, string $td = ' ', bool $escapeTd = \true): string
    {
        $th = htmlspecialchars($th, \ENT_NOQUOTES, 'UTF-8');
        if ($escapeTd) {
            $td = '<pre>' . htmlspecialchars($td, \ENT_NOQUOTES, 'UTF-8') . '</pre>';
        }
        return "<tr style=\"padding: 4px;text-align: left;\">\n<th style=\"vertical-align: top;background: #ccc;color: #000\" width=\"100\">{$th}:</th>\n<td style=\"padding: 4px;text-align: left;vertical-align: top;background: #eee;color: #000\">" . $td . "</td>\n</tr>";
    }
    /**
     * Create a HTML h1 tag
     *
     * @param string $title Text to be in the h1
     */
    protected function addTitle(string $title, Level $level): string
    {
        $title = htmlspecialchars($title, \ENT_NOQUOTES, 'UTF-8');
        return '<h1 style="background: ' . $this->getLevelColor($level) . ';color: #ffffff;padding: 5px;" class="monolog-output">' . $title . '</h1>';
    }
    /**
     * Formats a log record.
     *
     * @return string The formatted record
     */
    public function format(LogRecord $record): string
    {
        $output = $this->addTitle($record->level->getName(), $record->level);
        $output .= '<table cellspacing="1" width="100%" class="monolog-output">';
        $output .= $this->addRow('Message', $record->message);
        $output .= $this->addRow('Time', $this->formatDate($record->datetime));
        $output .= $this->addRow('Channel', $record->channel);
        if (\count($record->context) > 0) {
            $embeddedTable = '<table cellspacing="1" width="100%">';
            foreach ($record->context as $key => $value) {
                $embeddedTable .= $this->addRow((string) $key, $this->convertToString($value));
            }
            $embeddedTable .= '</table>';
            $output .= $this->addRow('Context', $embeddedTable, \false);
        }
        if (\count($record->extra) > 0) {
            $embeddedTable = '<table cellspacing="1" width="100%">';
            foreach ($record->extra as $key => $value) {
                $embeddedTable .= $this->addRow((string) $key, $this->convertToString($value));
            }
            $embeddedTable .= '</table>';
            $output .= $this->addRow('Extra', $embeddedTable, \false);
        }
        return $output . '</table>';
    }
    /**
     * Formats a set of log records.
     *
     * @return string The formatted set of records
     */
    public function formatBatch(array $records): string
    {
        $message = '';
        foreach ($records as $record) {
            $message .= $this->format($record);
        }
        return $message;
    }
    /**
     * @param mixed $data
     */
    protected function convertToString($data): string
    {
        if (null === $data || \is_scalar($data)) {
            return (string) $data;
        }
        $data = $this->normalize($data);
        return Utils::jsonEncode($data, \JSON_PRETTY_PRINT | Utils::DEFAULT_JSON_FLAGS, \true);
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Monolog;

use ArrayAccess;
/**
 * Monolog log record
 *
 * @author Jordi Boggiano <j.boggiano@seld.be>
 * @template-implements ArrayAccess<'message'|'level'|'context'|'level_name'|'channel'|'datetime'|'extra'|'formatted', int|string|\DateTimeImmutable|array<mixed>>
 */
class LogRecord implements ArrayAccess
{
    private const MODIFIABLE_FIELDS = ['extra' => \true, 'formatted' => \true];
    public function __construct(
        public readonly \DateTimeImmutable $datetime,
        public readonly string $channel,
        public readonly Level $level,
        public readonly string $message,
        /** @var array<mixed> */
        public readonly array $context = [],
        /** @var array<mixed> */
        public array $extra = [],
        public mixed $formatted = null
    )
    {
    }
    public function offsetSet(mixed $offset, mixed $value): void
    {
        if ($offset === 'extra') {
            if (!\is_array($value)) {
                throw new \InvalidArgumentException('extra must be an array');
            }
            $this->extra = $value;
            return;
        }
        if ($offset === 'formatted') {
            $this->formatted = $value;
            return;
        }
        throw new \LogicException('Unsupported operation: setting ' . $offset);
    }
    public function offsetExists(mixed $offset): bool
    {
        if ($offset === 'level_name') {
            return \true;
        }
        return isset($this->{$offset});
    }
    public function offsetUnset(mixed $offset): void
    {
        throw new \LogicException('Unsupported operation');
    }
    public function &offsetGet(mixed $offset): mixed
    {
        // handle special cases for the level enum
        if ($offset === 'level_name') {
            // avoid returning readonly props by ref as this is illegal
            $copy = $this->level->getName();
            return $copy;
        }
        if ($offset === 'level') {
            // avoid returning readonly props by ref as this is illegal
            $copy = $this->level->value;
            return $copy;
        }
        if (isset(self::MODIFIABLE_FIELDS[$offset])) {
            return $this->{$offset};
        }
        // avoid returning readonly props by ref as this is illegal
        $copy = $this->{$offset};
        return $copy;
    }
    /**
     * @phpstan-return array{message: string, context: mixed[], level: value-of<Level::VALUES>, level_name: value-of<Level::NAMES>, channel: string, datetime: \DateTimeImmutable, extra: mixed[]}
     */
    public function toArray(): array
    {
        return ['message' => $this->message, 'context' => $this->context, 'level' => $this->level->value, 'level_name' => $this->level->getName(), 'channel' => $this->channel, 'datetime' => $this->datetime, 'extra' => $this->extra];
    }
    public function with(mixed ...$args): self
    {
        foreach (['message', 'context', 'level', 'channel', 'datetime', 'extra'] as $prop) {
            $args[$prop] ??= $this->{$prop};
        }
        return new self(...$args);
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Monolog;

use Closure;
use _ContaoManager\Psr\Log\LoggerInterface;
use _ContaoManager\Psr\Log\LogLevel;
/**
 * Monolog error handler
 *
 * A facility to enable logging of runtime errors, exceptions and fatal errors.
 *
 * Quick setup: <code>ErrorHandler::register($logger);</code>
 *
 * @author Jordi Boggiano <j.boggiano@seld.be>
 */
class ErrorHandler
{
    private Closure|null $previousExceptionHandler = null;
    /** @var array<class-string, LogLevel::*> an array of class name to LogLevel::* constant mapping */
    private array $uncaughtExceptionLevelMap = [];
    /** @var Closure|true|null */
    private Closure|bool|null $previousErrorHandler = null;
    /** @var array<int, LogLevel::*> an array of E_* constant to LogLevel::* constant mapping */
    private array $errorLevelMap = [];
    private bool $handleOnlyReportedErrors = \true;
    private bool $hasFatalErrorHandler = \false;
    private string $fatalLevel = LogLevel::ALERT;
    private string|null $reservedMemory = null;
    /** @var ?array{type: int, message: string, file: string, line: int, trace: mixed} */
    private array|null $lastFatalData = null;
    private const FATAL_ERRORS = [\E_ERROR, \E_PARSE, \E_CORE_ERROR, \E_COMPILE_ERROR, \E_USER_ERROR];
    public function __construct(private LoggerInterface $logger)
    {
    }
    /**
     * Registers a new ErrorHandler for a given Logger
     *
     * By default it will handle errors, exceptions and fatal errors
     *
     * @param  array<int, LogLevel::*>|false          $errorLevelMap     an array of E_* constant to LogLevel::* constant mapping, or false to disable error handling
     * @param  array<class-string, LogLevel::*>|false $exceptionLevelMap an array of class name to LogLevel::* constant mapping, or false to disable exception handling
     * @param  LogLevel::*|null|false                 $fatalLevel        a LogLevel::* constant, null to use the default LogLevel::ALERT or false to disable fatal error handling
     * @return static
     */
    public static function register(LoggerInterface $logger, $errorLevelMap = [], $exceptionLevelMap = [], $fatalLevel = null): self
    {
        /** @phpstan-ignore-next-line */
        $handler = new static($logger);
        if ($errorLevelMap !== \false) {
            $handler->registerErrorHandler($errorLevelMap);
        }
        if ($exceptionLevelMap !== \false) {
            $handler->registerExceptionHandler($exceptionLevelMap);
        }
        if ($fatalLevel !== \false) {
            $handler->registerFatalHandler($fatalLevel);
        }
        return $handler;
    }
    /**
     * @param  array<class-string, LogLevel::*> $levelMap an array of class name to LogLevel::* constant mapping
     * @return $this
     */
    public function registerExceptionHandler(array $levelMap = [], bool $callPrevious = \true): self
    {
        $prev = set_exception_handler(function (\Throwable $e): void {
            $this->handleException($e);
        });
        $this->uncaughtExceptionLevelMap = $levelMap;
        foreach ($this->defaultExceptionLevelMap() as $class => $level) {
            if (!isset($this->uncaughtExceptionLevelMap[$class])) {
                $this->uncaughtExceptionLevelMap[$class] = $level;
            }
        }
        if ($callPrevious && null !== $prev) {
            $this->previousExceptionHandler = $prev(...);
        }
        return $this;
    }
    /**
     * @param  array<int, LogLevel::*> $levelMap an array of E_* constant to LogLevel::* constant mapping
     * @return $this
     */
    public function registerErrorHandler(array $levelMap = [], bool $callPrevious = \true, int $errorTypes = -1, bool $handleOnlyReportedErrors = \true): self
    {
        $prev = set_error_handler($this->handleError(...), $errorTypes);
        $this->errorLevelMap = array_replace($this->defaultErrorLevelMap(), $levelMap);
        if ($callPrevious) {
            $this->previousErrorHandler = $prev !== null ? $prev(...) : \true;
        } else {
            $this->previousErrorHandler = null;
        }
        $this->handleOnlyReportedErrors = $handleOnlyReportedErrors;
        return $this;
    }
    /**
     * @param  LogLevel::*|null $level              a LogLevel::* constant, null to use the default LogLevel::ALERT
     * @param  int              $reservedMemorySize Amount of KBs to reserve in memory so that it can be freed when handling fatal errors giving Monolog some room in memory to get its job done
     * @return $this
     */
    public function registerFatalHandler($level = null, int $reservedMemorySize = 20): self
    {
        register_shutdown_function($this->handleFatalError(...));
        $this->reservedMemory = str_repeat(' ', 1024 * $reservedMemorySize);
        $this->fatalLevel = null === $level ? LogLevel::ALERT : $level;
        $this->hasFatalErrorHandler = \true;
        return $this;
    }
    /**
     * @return array<class-string, LogLevel::*>
     */
    protected function defaultExceptionLevelMap(): array
    {
        return ['ParseError' => LogLevel::CRITICAL, 'Throwable' => LogLevel::ERROR];
    }
    /**
     * @return array<int, LogLevel::*>
     */
    protected function defaultErrorLevelMap(): array
    {
        return [
            \E_ERROR => LogLevel::CRITICAL,
            \E_WARNING => LogLevel::WARNING,
            \E_PARSE => LogLevel::ALERT,
            \E_NOTICE => LogLevel::NOTICE,
            \E_CORE_ERROR => LogLevel::CRITICAL,
            \E_CORE_WARNING => LogLevel::WARNING,
            \E_COMPILE_ERROR => LogLevel::ALERT,
            \E_COMPILE_WARNING => LogLevel::WARNING,
            \E_USER_ERROR => LogLevel::ERROR,
            \E_USER_WARNING => LogLevel::WARNING,
            \E_USER_NOTICE => LogLevel::NOTICE,
            2048 => LogLevel::NOTICE,
            // E_STRICT
            \E_RECOVERABLE_ERROR => LogLevel::ERROR,
            \E_DEPRECATED => LogLevel::NOTICE,
            \E_USER_DEPRECATED => LogLevel::NOTICE,
        ];
    }
    private function handleException(\Throwable $e): never
    {
        $level = LogLevel::ERROR;
        foreach ($this->uncaughtExceptionLevelMap as $class => $candidate) {
            if ($e instanceof $class) {
                $level = $candidate;
                break;
            }
        }
        $this->logger->log($level, sprintf('Uncaught Exception %s: "%s" at %s line %s', Utils::getClass($e), $e->getMessage(), $e->getFile(), $e->getLine()), ['exception' => $e]);
        if (null !== $this->previousExceptionHandler) {
            ($this->previousExceptionHandler)($e);
        }
        if (!headers_sent() && \in_array(strtolower((string) \ini_get('display_errors')), ['0', '', 'false', 'off', 'none', 'no'], \true)) {
            http_response_code(500);
        }
        exit(255);
    }
    private function handleError(int $code, string $message, string $file = '', int $line = 0): bool
    {
        if ($this->handleOnlyReportedErrors && 0 === (error_reporting() & $code)) {
            return \false;
        }
        // fatal error codes are ignored if a fatal error handler is present as well to avoid duplicate log entries
        if (!$this->hasFatalErrorHandler || !\in_array($code, self::FATAL_ERRORS, \true)) {
            $level = $this->errorLevelMap[$code] ?? LogLevel::CRITICAL;
            $this->logger->log($level, self::codeToString($code) . ': ' . $message, ['code' => $code, 'message' => $message, 'file' => $file, 'line' => $line]);
        } else {
            $trace = debug_backtrace(\DEBUG_BACKTRACE_IGNORE_ARGS);
            array_shift($trace);
            // Exclude handleError from trace
            $this->lastFatalData = ['type' => $code, 'message' => $message, 'file' => $file, 'line' => $line, 'trace' => $trace];
        }
        if ($this->previousErrorHandler === \true) {
            return \false;
        }
        if ($this->previousErrorHandler instanceof Closure) {
            return (bool) ($this->previousErrorHandler)($code, $message, $file, $line);
        }
        return \true;
    }
    /**
     * @private
     */
    public function handleFatalError(): void
    {
        $this->reservedMemory = '';
        if (\is_array($this->lastFatalData)) {
            $lastError = $this->lastFatalData;
        } else {
            $lastError = error_get_last();
        }
        if (\is_array($lastError) && \in_array($lastError['type'], self::FATAL_ERRORS, \true)) {
            $trace = $lastError['trace'] ?? null;
            $this->logger->log($this->fatalLevel, 'Fatal Error (' . self::codeToString($lastError['type']) . '): ' . $lastError['message'], ['code' => $lastError['type'], 'message' => $lastError['message'], 'file' => $lastError['file'], 'line' => $lastError['line'], 'trace' => $trace]);
            if ($this->logger instanceof Logger) {
                foreach ($this->logger->getHandlers() as $handler) {
                    $handler->close();
                }
            }
        }
    }
    private static function codeToString(int $code): string
    {
        return match ($code) {
            \E_ERROR => 'E_ERROR',
            \E_WARNING => 'E_WARNING',
            \E_PARSE => 'E_PARSE',
            \E_NOTICE => 'E_NOTICE',
            \E_CORE_ERROR => 'E_CORE_ERROR',
            \E_CORE_WARNING => 'E_CORE_WARNING',
            \E_COMPILE_ERROR => 'E_COMPILE_ERROR',
            \E_COMPILE_WARNING => 'E_COMPILE_WARNING',
            \E_USER_ERROR => 'E_USER_ERROR',
            \E_USER_WARNING => 'E_USER_WARNING',
            \E_USER_NOTICE => 'E_USER_NOTICE',
            2048 => 'E_STRICT',
            \E_RECOVERABLE_ERROR => 'E_RECOVERABLE_ERROR',
            \E_DEPRECATED => 'E_DEPRECATED',
            \E_USER_DEPRECATED => 'E_USER_DEPRECATED',
            default => 'Unknown PHP error',
        };
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Monolog;

final class Utils
{
    const DEFAULT_JSON_FLAGS = \JSON_UNESCAPED_SLASHES | \JSON_UNESCAPED_UNICODE | \JSON_PRESERVE_ZERO_FRACTION | \JSON_INVALID_UTF8_SUBSTITUTE | \JSON_PARTIAL_OUTPUT_ON_ERROR;
    public static function getClass(object $object): string
    {
        $class = \get_class($object);
        if (\false === $pos = strpos($class, "@anonymous\x00")) {
            return $class;
        }
        if (\false === $parent = get_parent_class($class)) {
            return substr($class, 0, $pos + 10);
        }
        return $parent . '@anonymous';
    }
    public static function substr(string $string, int $start, ?int $length = null): string
    {
        if (\extension_loaded('mbstring')) {
            return mb_strcut($string, $start, $length);
        }
        return substr($string, $start, null === $length ? \strlen($string) : $length);
    }
    /**
     * Makes sure if a relative path is passed in it is turned into an absolute path
     *
     * @param string $streamUrl stream URL or path without protocol
     */
    public static function canonicalizePath(string $streamUrl): string
    {
        $prefix = '';
        if ('file://' === substr($streamUrl, 0, 7)) {
            $streamUrl = substr($streamUrl, 7);
            $prefix = 'file://';
        }
        // other type of stream, not supported
        if (\false !== strpos($streamUrl, '://')) {
            return $streamUrl;
        }
        // already absolute
        if (substr($streamUrl, 0, 1) === '/' || substr($streamUrl, 1, 1) === ':' || substr($streamUrl, 0, 2) === '\\\\') {
            return $prefix . $streamUrl;
        }
        $streamUrl = getcwd() . '/' . $streamUrl;
        return $prefix . $streamUrl;
    }
    /**
     * Return the JSON representation of a value
     *
     * @param  mixed             $data
     * @param  int               $encodeFlags  flags to pass to json encode, defaults to DEFAULT_JSON_FLAGS
     * @param  bool              $ignoreErrors whether to ignore encoding errors or to throw on error, when ignored and the encoding fails, "null" is returned which is valid json for null
     * @throws \RuntimeException if encoding fails and errors are not ignored
     * @return string            when errors are ignored and the encoding fails, "null" is returned which is valid json for null
     */
    public static function jsonEncode($data, ?int $encodeFlags = null, bool $ignoreErrors = \false): string
    {
        if (null === $encodeFlags) {
            $encodeFlags = self::DEFAULT_JSON_FLAGS;
        }
        if ($ignoreErrors) {
            $json = @json_encode($data, $encodeFlags);
            if (\false === $json) {
                return 'null';
            }
            return $json;
        }
        $json = json_encode($data, $encodeFlags);
        if (\false === $json) {
            $json = self::handleJsonError(json_last_error(), $data);
        }
        return $json;
    }
    /**
     * Handle a json_encode failure.
     *
     * If the failure is due to invalid string encoding, try to clean the
     * input and encode again. If the second encoding attempt fails, the
     * initial error is not encoding related or the input can't be cleaned then
     * raise a descriptive exception.
     *
     * @param  int               $code        return code of json_last_error function
     * @param  mixed             $data        data that was meant to be encoded
     * @param  int               $encodeFlags flags to pass to json encode, defaults to JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE | JSON_PRESERVE_ZERO_FRACTION
     * @throws \RuntimeException if failure can't be corrected
     * @return string            JSON encoded data after error correction
     */
    public static function handleJsonError(int $code, $data, ?int $encodeFlags = null): string
    {
        if ($code !== \JSON_ERROR_UTF8) {
            self::throwEncodeError($code, $data);
        }
        if (\is_string($data)) {
            self::detectAndCleanUtf8($data);
        } elseif (\is_array($data)) {
            array_walk_recursive($data, ['Monolog\Utils', 'detectAndCleanUtf8']);
        } else {
            self::throwEncodeError($code, $data);
        }
        if (null === $encodeFlags) {
            $encodeFlags = self::DEFAULT_JSON_FLAGS;
        }
        $json = json_encode($data, $encodeFlags);
        if ($json === \false) {
            self::throwEncodeError(json_last_error(), $data);
        }
        return $json;
    }
    /**
     * Throws an exception according to a given code with a customized message
     *
     * @param  int               $code return code of json_last_error function
     * @param  mixed             $data data that was meant to be encoded
     * @throws \RuntimeException
     */
    private static function throwEncodeError(int $code, $data): never
    {
        $msg = match ($code) {
            \JSON_ERROR_DEPTH => 'Maximum stack depth exceeded',
            \JSON_ERROR_STATE_MISMATCH => 'Underflow or the modes mismatch',
            \JSON_ERROR_CTRL_CHAR => 'Unexpected control character found',
            \JSON_ERROR_UTF8 => 'Malformed UTF-8 characters, possibly incorrectly encoded',
            default => 'Unknown error',
        };
        throw new \RuntimeException('JSON encoding failed: ' . $msg . '. Encoding: ' . var_export($data, \true));
    }
    /**
     * Detect invalid UTF-8 string characters and convert to valid UTF-8.
     *
     * Valid UTF-8 input will be left unmodified, but strings containing
     * invalid UTF-8 codepoints will be reencoded as UTF-8 with an assumed
     * original encoding of ISO-8859-15. This conversion may result in
     * incorrect output if the actual encoding was not ISO-8859-15, but it
     * will be clean UTF-8 output and will not rely on expensive and fragile
     * detection algorithms.
     *
     * Function converts the input in place in the passed variable so that it
     * can be used as a callback for array_walk_recursive.
     *
     * @param mixed $data Input to check and convert if needed, passed by ref
     */
    private static function detectAndCleanUtf8(&$data): void
    {
        if (\is_string($data) && preg_match('//u', $data) !== 1) {
            $data = preg_replace_callback('/[\x80-\xFF]+/', function (array $m): string {
                return \function_exists('mb_convert_encoding') ? mb_convert_encoding($m[0], 'UTF-8', 'ISO-8859-1') : (\function_exists('utf8_encode') ? utf8_encode($m[0]) : '');
            }, $data);
            if (!\is_string($data)) {
                $pcreErrorCode = preg_last_error();
                throw new \RuntimeException('Failed to preg_replace_callback: ' . $pcreErrorCode . ' / ' . preg_last_error_msg());
            }
            $data = str_replace(['¤', '¦', '¨', '´', '¸', '¼', '½', '¾'], ['€', 'Š', 'š', 'Ž', 'ž', 'Œ', 'œ', 'Ÿ'], $data);
        }
    }
    /**
     * Converts a string with a valid 'memory_limit' format, to bytes.
     *
     * @param  string|false $val
     * @return int|false    Returns an integer representing bytes. Returns FALSE in case of error.
     */
    public static function expandIniShorthandBytes($val)
    {
        if (!\is_string($val)) {
            return \false;
        }
        // support -1
        if ((int) $val < 0) {
            return (int) $val;
        }
        if (!(bool) preg_match('/^\s*(?<val>\d+)(?:\.\d+)?\s*(?<unit>[gmk]?)\s*$/i', $val, $match)) {
            return \false;
        }
        $val = (int) $match['val'];
        switch (strtolower($match['unit'])) {
            case 'g':
                $val *= 1024;
            // no break
            case 'm':
                $val *= 1024;
            // no break
            case 'k':
                $val *= 1024;
        }
        return $val;
    }
    public static function getRecordMessageForException(LogRecord $record): string
    {
        $context = '';
        $extra = '';
        try {
            if (\count($record->context) > 0) {
                $context = "\nContext: " . json_encode($record->context, \JSON_THROW_ON_ERROR);
            }
            if (\count($record->extra) > 0) {
                $extra = "\nExtra: " . json_encode($record->extra, \JSON_THROW_ON_ERROR);
            }
        } catch (\Throwable $e) {
            // noop
        }
        return "\nThe exception occurred while attempting to log: " . $record->message . $context . $extra;
    }
}
The MIT License (MIT)

Copyright (c) 2016 Studio 24 Ltd

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation 
files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, 
modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the 
Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE 
WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
<phpunit bootstrap="tests/src/bootstrap.php"
         colors="true"
         syntaxCheck="true"
>
    <testsuites>
        <testsuite name="Source">
            <directory>tests/src/</directory>
        </testsuite>
    </testsuites>

</phpunit>
# Rotate

Simple file rotation utility which rotates and removes old files or folders, useful where you cannot use logrotate (e.g. a Windows system) 
or you want to rotate or delete files based on a timestamp or date contained in the filename. 

## Installation

```sh
composer require studio24/rotate
```

## Usage

You can use Rotate in two modes: rotate (renames files and removes oldest files) or delete (deletes files according to a pattern).

Import at the top of your PHP script via:

```sh
use studio24\Rotate\Rotate;
```

### Setting the filename format to match

Both Rotate and Delete pass in the filename pattern you want to match for in the constructor or via the `setFilenameFormat()` method.
This can be used to match a single file, files matching a pattern, or files with a datetime within the filename pattern. 

Rotate only works on files. Delete can also delete folders and recursively deletes any child files in that folder. 

#### Matches on leaf elements

Please note files are matched on the last leaf element. All files in the parent folder are scanned, files (and folders 
for Delete) are checked to see whether they match the specified pattern.

For example passing `path/to/*.log` will search for all files ending .log in the folder `path/to`.

#### Filename patterns

The following patterns are supported when matching files or folders:

* `debug.log` - exact match for a file called debug.log
* `*` - matches any string, for example `*.log` matches all files ending .log
* `{Ymd}` - matches time segment in a file, for example `order.{Ymd}.log` matches a file in the format order.20160401.log

#### Datetime formats

For datetime formats, any date format supported by [DateTime::createFromFormat](http://php.net/datetime.createfromformat) is allowed 
excluding the Timezone identifier `e` and whitespace and separator characters. 

### Deleting folders recursively

You can also delete folders and all child files that match. This is, however, dangerous so by default no folders can be deleted. You 
 need to explicitly add folder paths that are safe to delete via `Delete::addSafeRecursiveDeletePath($path)`. When using 
 this function you need to use the full absolute path. Use `realpath()` to expand full paths if you need to.

For example, if you want to delete all folders in `/var/www/test/staging/data/logs/` that are 1+ months old:

```
$rotate = new Delete('/var/www/test/staging/data/logs/old-logs/*');
$rotate->addSafeRecursiveDeletePath('/var/www/test/staging/data/logs/');
$files = $rotate->deleteByFilenameTime('1 month');
```

The above code would allow you to delete folders within `/var/www/test/staging/data/logs/` only. 

### Rotate

Rotate log files in a similar manner to logrotate.

The following example rotates the file debug.log, this renames debug.log to debug.log.1, debug.log.1 to debug.log.2, debug.log.2 to 
debug.log.3 and so on. It keeps 10 copies, so it deletes debug.log.10 and renames debug.log.9 to debug.log.10.

```sh
use studio24\Rotate\Rotate;

$rotate = new Rotate('path/to/debug.log');
$rotate->run();
```

#### How many copies to keep

Rotate keeps 10 copies of files by default, you can change this via:

```
$rotate->keep(20);
```

#### Rotated based on filesize
You can only rotate files when they reach a certain filesize, rather than automatically rotate each time the `$rotate->run()` method is run.
 
```
$rotate->size("12MB");
```

### Delete

Deletes files based on modification time, datetime in the filename, or based on a custom callback function.

#### Time-based

Deletes files based on the modification time. For example, to delete all JPG files in a folder over 3 months old: 

```sh
use studio24\Rotate\Delete;

$rotate = new Delete('path/to/images/*.jpg');
$deletedFiles = $rotate->deleteByFileModifiedDate('3 months');
```

The `deleteByFileModifiedDate()` method accepts either a valid DateInterval object or a relative date format as specified on 
[Relative Formats](http://php.net/manual/en/datetime.formats.relative.php).

#### Time format in filename
Deletes files based on the datetime in the filename. For example, to delete all  order logfiles with a date in their 
filename over 3 months old:

```sh
use studio24\Rotate\Delete;

$rotate = new Delete('path/to/logs/orders.YYYYMMDD.log');
$deletedFiles = $rotate->deleteByFilenameTime('3 months');
```

#### Based on a custom callback 
Deletes files based on a custom callback function, this is useful if you need to perform more complex code to assess whether a file
should be deleted. For example, to delete all image files called 1000.jpg and below:

```sh
use studio24\Rotate\Delete;
use studio24\Rotate\DirectoryIterator;

$rotate = new Delete('path/to/logs/*.jpg');
$deletedFiles = $rotate->deleteByCallback(function(DirectoryIterator $file){
    if ($file->getBasename() <= 1000) {
        return true;
    } 
    return false;
});
```

##### DirectoryIterator
The callback function must accept one parameter `$file`, which is of type `\studio24\Rotate\DirectoryIterator`.

This iterator has the following methods in addition to the normal [SPL DirectoryIterator](http://php.net/DirectoryIterator).

* `isMatch()` - whether the current file matches the filename patter we are looking for
* `hasDate()` - whether the current file has a datetime within the filename
* `getFilenameDate()` - return the datetime from the current file (as a DateTime object)

## License

The MIT License (MIT). Please see [License File](LICENSE.md) for more information.

## Credits

- [Simon R Jones](https://github.com/simonrjones){
    "name": "studio24\/rotate",
    "type": "library",
    "description": "File rotation utility which rotates and removes old files",
    "keywords": [
        "rotate",
        "logrotate",
        "delete files"
    ],
    "homepage": "https:\/\/github.com\/studio24\/rotate",
    "license": "MIT",
    "authors": [
        {
            "name": "Simon R Jones",
            "email": "hello@studio24.net",
            "homepage": "http:\/\/simonrjones.net",
            "role": "Developer"
        }
    ],
    "require": {
        "php": ">=5.6.0"
    },
    "autoload": {
        "psr-4": {
            "_ContaoManager\\studio24\\Rotate\\": "src\/"
        }
    },
    "require-dev": {
        "phpunit\/phpunit": "^5.2"
    }
}<?php

namespace _ContaoManager\studio24\Rotate;

class RotateException extends \Exception
{
}
<?php

namespace _ContaoManager\studio24\Rotate;

/**
 * Class to manage file rotation
 *
 * @package studio24\Rotate
 */
class Rotate extends RotateAbstract
{
    /**
     * Number of copies to keep, defaults to 10
     *
     * @var int
     */
    protected $keepNumber = 10;
    /**
     * Filesize to rotate files on (in bytes)
     *
     * @var int
     */
    protected $sizeToRotate;
    /**
     * Set the number of old copies to keep
     *
     * @param $number
     */
    public function keep($number)
    {
        $this->keepNumber = $number;
    }
    /**
     * Return number of old copies to keep
     *
     * @return int
     */
    public function getKeepNumber()
    {
        return $this->keepNumber;
    }
    /**
     * Set the filesize to rotate files on
     *
     * @param string $size Define as an number with a string suffix indicating the unit measurement, e.g. 5MB
     * @throws RotateException
     */
    public function size($size)
    {
        if (!preg_match('/^(\d+)\s?(B|KB|MB|GB)$/i', $size, $m)) {
            throw new RotateException("You must define size in the format 10B|KB|MB|GB");
        }
        if ($m[1] === 0) {
            throw new RotateException("You must define a non-zero size to rotate files on");
        }
        switch (strtoupper($m[2])) {
            case 'B':
                $this->sizeToRotate = $m[1];
                break;
            case 'KB':
                $this->sizeToRotate = $m[1] * 1024;
                break;
            case 'MB':
                $this->sizeToRotate = $m[1] * 1024 * 1024;
                break;
            case 'GB':
                $this->sizeToRotate = $m[1] * 1024 * 1024 * 1024;
                break;
        }
    }
    /**
     * Return filesize to rotate files on (in bytes)
     *
     * @return int
     */
    public function getSizeToRotate()
    {
        return $this->sizeToRotate;
    }
    /**
     * Have we defined a filesize to rotate on?
     *
     * @return bool
     */
    public function hasSizeToRotate()
    {
        return is_int($this->getSizeToRotate()) && $this->getSizeToRotate() !== 0;
    }
    /**
     * Run the file rotation
     *
     * @return array Array of files which have been rotated
     * @throws FilenameFormatException
     * @throws RotateException
     */
    public function run()
    {
        if (!$this->hasFilenameFormat()) {
            throw new FilenameFormatException('You must set a filename format to match files against');
        }
        $rotated = [];
        $dir = new DirectoryIterator($this->getFilenameFormat()->getPath());
        $dir->setFilenameFormat($this->getFilenameFormat());
        foreach ($dir as $file) {
            if ($file->isFile() && $file->isMatch()) {
                // Skip if rotate size specified and initial matched file doesn't exceed this
                if ($this->hasSizeToRotate()) {
                    if ($file->getSize() < $this->getSizeToRotate()) {
                        continue;
                    }
                }
                // Rotate files
                for ($x = $this->keepNumber; $x--; $x > 0) {
                    $fileToRotate = $file->getPath() . '/' . $file->getRotatedFilename($x);
                    if (!file_exists($fileToRotate)) {
                        continue;
                    }
                    if ($x === $this->keepNumber) {
                        if (!$this->isDryRun()) {
                            if (!unlink($fileToRotate)) {
                                throw new RotateException('Cannot delete file: ' . $file->getRotatedFilename($x));
                            }
                        }
                        $rotated[] = $fileToRotate;
                    } else {
                        if (!$this->isDryRun()) {
                            if (!rename($fileToRotate, $file->getPath() . '/' . $file->getRotatedFilename($x + 1))) {
                                throw new RotateException('Cannot rotate file: ' . $file->getRotatedFilename($x));
                            }
                        }
                        $rotated[] = $fileToRotate;
                    }
                }
                if (!$this->isDryRun()) {
                    if (!rename($file->getPath() . '/' . $file->getBasename(), $file->getPath() . '/' . $file->getRotatedFilename(1))) {
                        throw new RotateException('Cannot rotate file: ' . $file->getBasename());
                    }
                }
                $rotated[] = $file->getPath() . '/' . $file->getBasename();
            }
        }
        return $rotated;
    }
}
<?php

namespace _ContaoManager\studio24\Rotate;

// @todo support '/cygdrive/z/bakerdays-shared/' . $environment . '/processed-preview/*/preview_*.jpg'
class FilenameFormat
{
    /**
     * Path to files to rotate / delete
     *
     * @var string
     */
    protected $path;
    /**
     * Filename pattern of files to rotate / delete
     *
     * @var string
     */
    protected $filenamePattern;
    /**
     * Filename regex pattern to match files
     *
     * @var string
     */
    protected $filenameRegex;
    /**
     * Date format within filename
     *
     * @var string
     */
    protected $dateFormat;
    /**
     * Constructor
     *
     * @param string $filenameFormat Filename format to match files against
     * @throws FilenameFormatException
     */
    public function __construct($filenameFormat)
    {
        $this->path = dirname($filenameFormat);
        if (!is_dir($this->path) || !is_readable($this->path)) {
            throw new FilenameFormatException("Directory path does not exist or is not readable at: " . strip_tags($filenameFormat));
        }
        $this->filenamePattern = basename($filenameFormat);
        $this->filenameRegex = $this->extractRegex($this->filenamePattern);
    }
    /**
     * Extract regex pattern from filename pattern
     *
     * * matches any string, for example *.log matches all files ending .log
     * {Ymd} = matches time segment in a file, for example order.{Ymd}.log matches a file in the format order.20160401.log
     * Any date format supported by DateTime::createFromFormat is allowed (excluding the Timezone identifier 'e' and whitespace and separator characters)
     *
     * @param string $filename
     * @return string Regex pattern for matching files (with the ungreedy modifier set)
     * @throws FilenameFormatException
     */
    public function extractRegex($filename)
    {
        if (strpos('/', $filename) !== \false) {
            throw new FilenameFormatException("Filename part cannot contain '/' character");
        }
        $escape = ['/\./' => '\.', '/\+/' => '\+', '/\:/' => '\:', '/\-/' => '\-'];
        $pattern = preg_replace(array_keys($escape), array_values($escape), $filename);
        $replacements = ['/\*/' => '.+'];
        $pattern = preg_replace(array_keys($replacements), array_values($replacements), $pattern);
        if (preg_match('/{([^}]+)}/', $filename, $m)) {
            $dateFormat = $m[1];
            $validDateFormat = 'djDlSzFMmnYyaAghGHisuOPTU';
            if (!empty(array_diff(str_split($dateFormat), str_split($validDateFormat)))) {
                throw new FilenameFormatException("Date format is not valid: {$dateFormat}");
            }
            $this->dateFormat = $dateFormat;
            $pattern = preg_replace('/{[^}]+}/', '([^.]+)', $pattern);
        }
        return '/^' . $pattern . '$/';
    }
    /**
     * Return path to folder we're looking for files in
     *
     * @return string
     */
    public function getPath()
    {
        return $this->path;
    }
    /**
     * Return filename pattern to match files
     *
     * @return string
     */
    public function getFilenamePattern()
    {
        return $this->filenamePattern;
    }
    /**
     * Return regex to match files
     *
     * @return string
     */
    public function getFilenameRegex()
    {
        return $this->filenameRegex;
    }
    /**
     * Does the filename pattern contain a date format?
     *
     * @return bool
     */
    public function hasDateFormat()
    {
        return $this->dateFormat !== null;
    }
    /**
     * Return the date format
     *
     * @return string
     */
    public function getDateFormat()
    {
        return $this->dateFormat;
    }
}
<?php

namespace _ContaoManager\studio24\Rotate;

abstract class RotateAbstract
{
    /**
     * The filename format we're matching against
     *
     * @var FilenameFormat
     */
    protected $filenameFormat;
    /**
     * Do we run this as a dry-run, i.e. not actually delete any files?
     *
     * @var boolean
     */
    protected $dryRun = \false;
    /**
     * Constructor
     *
     * @param string|null $filenameFormat
     */
    public function __construct($filenameFormat = null)
    {
        if ($filenameFormat !== null) {
            $this->setFilenameFormat($filenameFormat);
        }
    }
    /**
     * Set the filename format we're matching
     *
     * @param string $filenameFormat Filename format to match files against
     */
    public function setFilenameFormat($filenameFormat)
    {
        $this->filenameFormat = new FilenameFormat($filenameFormat);
    }
    /**
     * Return the filename format we're matching
     *
     * @return FilenameFormat
     */
    public function getFilenameFormat()
    {
        return $this->filenameFormat;
    }
    /**
     * Does this object have a valid filename format set?
     *
     * @return bool
     */
    public function hasFilenameFormat()
    {
        return $this->filenameFormat instanceof FilenameFormat;
    }
    /**
     * Set the dry run flag, which means we don't actually delete any files
     *
     * @param $dryRun
     */
    public function setDryRun($dryRun)
    {
        $this->dryRun = (bool) $dryRun;
    }
    /**
     * Are we in dry-run mode?
     *
     * @return bool
     */
    public function isDryRun()
    {
        return $this->dryRun;
    }
}
<?php

namespace _ContaoManager\studio24\Rotate;

class FilenameFormatException extends \Exception
{
}
<?php

namespace _ContaoManager\studio24\Rotate;

use DateTime, DateInterval;
/**
 * Class to manage file deletion
 *
 * @package studio24\Rotate
 */
class Delete extends RotateAbstract
{
    /**
     * Current date & time for file comparison purposes
     *
     * @var DateTime
     */
    protected $now;
    /**
     * Paths it is safe to perform recursive delete on
     *
     * @var array
     */
    protected $safeRecursiveDeletePaths = [];
    /**
     * Set the current date & time
     *
     * @param DateTime $dateTime
     */
    public function setNow(DateTime $dateTime)
    {
        $this->now = $dateTime;
    }
    /**
     * Return current time
     *
     * Defaults to current date, midnight
     *
     * @return DateTime
     */
    public function getNow()
    {
        if (!$this->now instanceof DateTime) {
            $now = new DateTime();
            $this->now = new DateTime($now->format('Y-m-d') . ' 00:00:00');
        }
        return $this->now;
    }
    /**
     * Add a folder path it is safe to perform recursive delete on
     *
     * If you don't do this you cannot recursively delete a folder, this is for safety!
     *
     * @param string $path Folder path
     * @throws RotateException
     */
    public function addSafeRecursiveDeletePath($path)
    {
        if (!file_exists($path) || !is_dir($path)) {
            throw new RotateException("Cannot set path as a safe recursive delete path since does not exist or is not a folder");
        }
        $this->safeRecursiveDeletePaths[] = $path;
    }
    /**
     * Delete a file or a folder containing files
     *
     * If you try to delete a folder containing files, you must add the path via addSafeRecursiveDeletePath()
     *
     * @param $path
     * @return array Array of deleted files
     * @throws RotateException
     */
    protected function delete($path)
    {
        if (is_dir($path)) {
            return $this->recursiveDeleteFolder($path);
        } else {
            if (!unlink($path)) {
                throw new RotateException('Cannot delete file: ' . $path);
            }
            return [$path];
        }
    }
    /**
     * Recursively delete a folder and its contents
     *
     * Warning: this can be dangerous, you must add paths that are safe to perform recursive deletion on via addSafeRecursiveDeletePath()
     * otherwise this function will fail
     *
     * @param $folderPath
     * @return array Array of deleted files
     * @throws RotateException
     */
    protected function recursiveDeleteFolder($folderPath)
    {
        $deleted = [];
        $folderPath = realpath($folderPath);
        if (!is_dir($folderPath)) {
            throw new RotateException("Path {$path} is not a folder");
        }
        $safeToDelete = \false;
        foreach ($this->safeRecursiveDeletePaths as $safePath) {
            if (preg_match('!^' . preg_quote($safePath, '!') . '.+$!', $folderPath)) {
                $safeToDelete = \true;
            }
        }
        if (!$safeToDelete) {
            throw new RotateException("It is not safe to perform a recursive delete on path: {$folderPath}");
        }
        $dir = new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($folderPath, \RecursiveDirectoryIterator::SKIP_DOTS), \RecursiveIteratorIterator::CHILD_FIRST);
        foreach ($dir as $file) {
            if (!$this->isDryRun()) {
                if ($file->isDir()) {
                    if (!rmdir($file->getPathname())) {
                        throw new RotateException('Cannot delete folder: ' . $file->getPathname());
                    }
                } else if (!unlink($file->getPathname())) {
                    throw new RotateException('Cannot delete file: ' . $file->getPathname());
                }
            }
            $deleted[] = $file->getPathname();
        }
        if (!$this->isDryRun()) {
            rmdir($folderPath);
            $deleted[] = $folderPath;
        }
        unset($dir, $file);
        return $deleted;
    }
    /**
     * Delete files by the filename time stored within the filename itself
     *
     * For example delete all files with a filename date pattern of payment.2016-01-01.log over 3 months old
     *
     * @param mixed $timePeriod DateInterval object, or time interval supported by DateInterval::createFromDateString, e.g. 3 months
     * @return array Array of deleted files
     * @throws FilenameFormatException
     * @throws RotateException
     */
    public function deleteByFilenameTime($timePeriod)
    {
        if (!$this->hasFilenameFormat()) {
            throw new FilenameFormatException('You must set a filename format to match files against');
        }
        $deleted = [];
        if ($timePeriod instanceof DateInterval) {
            $interval = $timePeriod;
        } else {
            $interval = DateInterval::createFromDateString($timePeriod);
        }
        $oldestDate = clone $this->getNow();
        $oldestDate = $oldestDate->sub($interval);
        $dir = new DirectoryIterator($this->getFilenameFormat()->getPath());
        $dir->setFilenameFormat($this->getFilenameFormat());
        foreach ($dir as $file) {
            if (!$file->isDot() && $file->isMatch()) {
                if ($file->getFilenameDate() < $oldestDate) {
                    if (!$this->isDryRun()) {
                        $results = $this->delete($file->getPathname());
                        $deleted = array_merge($deleted, $results);
                    } else {
                        $deleted[] = $file->getPathname();
                    }
                }
            }
        }
        return $deleted;
    }
    /**
     * Delete files by the last modified time of the filename
     *
     * For example delete all files over 3 months old.
     *
     * @param mixed $timePeriod DateInterval object, or time interval supported by DateInterval::createFromDateString, e.g. 3 months
     * @return array Array of deleted files
     * @throws FilenameFormatException
     * @throws RotateException
     */
    public function deleteByFileModifiedDate($timePeriod)
    {
        if (!$this->hasFilenameFormat()) {
            throw new FilenameFormatException('You must set a filename format to match files against');
        }
        $deleted = [];
        if ($timePeriod instanceof DateInterval) {
            $interval = $timePeriod;
        } else {
            $interval = DateInterval::createFromDateString($timePeriod);
        }
        $oldestDate = clone $this->getNow();
        $oldestDate = $oldestDate->sub($interval);
        $dir = new DirectoryIterator($this->getFilenameFormat()->getPath());
        $dir->setFilenameFormat($this->getFilenameFormat());
        foreach ($dir as $file) {
            if (!$file->isDot() && $file->isMatch()) {
                $fileDate = new DateTime();
                $fileDate->setTimestamp($file->getMTime());
                if ($fileDate < $oldestDate) {
                    if (!$this->isDryRun()) {
                        $results = $this->delete($file->getPathname());
                        $deleted = array_merge($deleted, $results);
                    } else {
                        $deleted[] = $file->getPathname();
                    }
                }
            }
        }
        return $deleted;
    }
    /**
     * Delete files by a custom callback function
     *
     * For example, do a database lookup on the order ID stored within the filename to ensure the order has been completed, if so delete the file.
     *
     * Callback function must accept one parameter (DirectoryIterator $file) and must return true (delete file) or false (do not delete file)
     *
     * Example to delete all files over 5Mb in size:
     * $callback = function(DirectoryIterator $file) {
     *     if ($file->getSize() > 5 * 1024 * 1024) {
     *         return true;
     *     } else {
     *         return false;
     *     }
     * }
     *
     * @param callable $callback
     * @return array Array of deleted files
     * @throws FilenameFormatException
     * @throws RotateException
     */
    public function deleteByCallback(callable $callback)
    {
        if (!$this->hasFilenameFormat()) {
            throw new FilenameFormatException('You must set a filename format to match files against');
        }
        $deleted = [];
        $dir = new DirectoryIterator($this->getFilenameFormat()->getPath());
        $dir->setFilenameFormat($this->getFilenameFormat());
        foreach ($dir as $file) {
            if (!$file->isDot() && $file->isMatch()) {
                if ($callback($file)) {
                    if (!$this->isDryRun()) {
                        $results = $this->delete($file->getPathname());
                        $deleted = array_merge($deleted, $results);
                    } else {
                        $deleted[] = $file->getPathname();
                    }
                }
            }
        }
        return $deleted;
    }
}
<?php

namespace _ContaoManager\studio24\Rotate;

class DirectoryIterator extends \DirectoryIterator
{
    /**
     * Filename format to match files against
     *
     * @var FilenameFormat
     */
    protected $filenameFormat;
    /**
     * Set the filename format for this iterator
     *
     * @param FilenameFormat $filenameFormat
     */
    public function setFilenameFormat(FilenameFormat $filenameFormat)
    {
        $this->filenameFormat = $filenameFormat;
    }
    /**
     * Is the current filename a match for the filename format we're looking for?
     *
     * @return bool
     */
    public function isMatch()
    {
        return (bool) preg_match($this->filenameFormat->getFilenameRegex(), $this->getFilename());
    }
    /**
     * Does the filename format we're looking for contain a date?
     *
     * @return bool
     */
    public function hasDate()
    {
        return $this->filenameFormat->hasDateFormat();
    }
    /**
     * Return date contained within the current filename
     *
     * @return DateTime or false on failure
     */
    public function getFilenameDate()
    {
        if (!$this->hasDate()) {
            return \false;
        }
        if (preg_match($this->filenameFormat->getFilenameRegex(), $this->getFilename(), $m)) {
            return \DateTime::createFromFormat($this->filenameFormat->getDateFormat(), $m[1]);
        }
        return \false;
    }
    /**
     * Return rotated filename
     *
     * @param int $num Rotation number
     * @return string
     */
    public function getRotatedFilename($num)
    {
        return $this->getBasename() . '.' . $num;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Bundle\FrameworkBundle\DataCollector;

use _ContaoManager\Symfony\Component\HttpKernel\DataCollector\DataCollector;
/**
 * @author Laurent VOULLEMIER <laurent.voullemier@gmail.com>
 */
abstract class AbstractDataCollector extends DataCollector implements TemplateAwareDataCollectorInterface
{
    public function getName(): string
    {
        return static::class;
    }
    public static function getTemplate(): ?string
    {
        return null;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Bundle\FrameworkBundle\DataCollector;

use _ContaoManager\Symfony\Bundle\FrameworkBundle\Controller\RedirectController;
use _ContaoManager\Symfony\Component\HttpFoundation\Request;
use _ContaoManager\Symfony\Component\HttpKernel\DataCollector\RouterDataCollector as BaseRouterDataCollector;
/**
 * @author Fabien Potencier <fabien@symfony.com>
 *
 * @final
 */
class RouterDataCollector extends BaseRouterDataCollector
{
    public function guessRoute(Request $request, mixed $controller): string
    {
        if (\is_array($controller)) {
            $controller = $controller[0];
        }
        if ($controller instanceof RedirectController && $request->attributes->has('_route')) {
            return $request->attributes->get('_route');
        }
        return parent::guessRoute($request, $controller);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Bundle\FrameworkBundle\DataCollector;

use _ContaoManager\Symfony\Component\HttpKernel\DataCollector\DataCollectorInterface;
/**
 * @author Laurent VOULLEMIER <laurent.voullemier@gmail.com>
 */
interface TemplateAwareDataCollectorInterface extends DataCollectorInterface
{
    public static function getTemplate(): ?string;
}
Copyright (c) 2004-present Fabien Potencier

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is furnished
to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Bundle\FrameworkBundle\Test;

use _ContaoManager\PHPUnit\Framework\TestCase;
use _ContaoManager\Symfony\Component\Config\Resource\SelfCheckingResourceChecker;
use _ContaoManager\Symfony\Component\DependencyInjection\Container;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException;
use _ContaoManager\Symfony\Component\Filesystem\Filesystem;
use _ContaoManager\Symfony\Component\HttpKernel\Kernel;
use _ContaoManager\Symfony\Component\HttpKernel\KernelInterface;
use _ContaoManager\Symfony\Contracts\Service\ResetInterface;
/**
 * KernelTestCase is the base class for tests needing a Kernel.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
abstract class KernelTestCase extends TestCase
{
    use MailerAssertionsTrait;
    use NotificationAssertionsTrait;
    protected static $class;
    /**
     * @var KernelInterface
     */
    protected static $kernel;
    protected static $booted = \false;
    private static bool $kernelHasBeenRebooted = \false;
    protected function tearDown(): void
    {
        static::ensureKernelShutdown();
        static::$class = null;
        static::$kernel = null;
        static::$booted = \false;
    }
    public static function tearDownAfterClass(): void
    {
        static::ensureKernelShutdown();
        static::$class = null;
        static::$kernel = null;
        static::$booted = \false;
    }
    /**
     * @throws \RuntimeException
     * @throws \LogicException
     */
    protected static function getKernelClass(): string
    {
        if (!isset($_SERVER['KERNEL_CLASS']) && !isset($_ENV['KERNEL_CLASS'])) {
            throw new \LogicException(\sprintf('You must set the KERNEL_CLASS environment variable to the fully-qualified class name of your Kernel in phpunit.xml / phpunit.xml.dist or override the "%1$s::createKernel()" or "%1$s::getKernelClass()" method.', static::class));
        }
        if (!class_exists($class = $_ENV['KERNEL_CLASS'] ?? $_SERVER['KERNEL_CLASS'])) {
            throw new \RuntimeException(\sprintf('Class "%s" doesn\'t exist or cannot be autoloaded. Check that the KERNEL_CLASS value in phpunit.xml matches the fully-qualified class name of your Kernel or override the "%s::createKernel()" method.', $class, static::class));
        }
        return $class;
    }
    /**
     * Boots the Kernel for this test.
     */
    protected static function bootKernel(array $options = []): KernelInterface
    {
        static::ensureKernelShutdown();
        $kernel = static::createKernel($options);
        $kernel->boot();
        static::$kernel = $kernel;
        static::$booted = \true;
        // If the cache warmer is registered, it means that the cache has been
        // warmed up, so the current container is not fresh anymore. Let's
        // reboot a fresh one.
        if ($kernel->getContainer()->initialized('cache_warmer')) {
            static::ensureKernelShutdown();
            self::$kernelHasBeenRebooted = \true;
            $kernel = static::createKernel($options);
            $kernel->boot();
            static::$kernel = $kernel;
            static::$booted = \true;
        }
        return static::$kernel;
    }
    /**
     * Provides a dedicated test container with access to both public and private
     * services. The container will not include private services that have been
     * inlined or removed. Private services will be removed when they are not
     * used by other services.
     *
     * Using this method is the best way to get a container from your test code.
     *
     * @return Container
     */
    protected static function getContainer(): ContainerInterface
    {
        if (!static::$booted) {
            static::bootKernel();
        }
        try {
            return self::$kernel->getContainer()->get('test.service_container');
        } catch (ServiceNotFoundException $e) {
            throw new \LogicException('Could not find service "test.service_container". Try updating the "framework.test" config to "true".', 0, $e);
        }
    }
    /**
     * Creates a Kernel.
     *
     * Available options:
     *
     *  * environment
     *  * debug
     */
    protected static function createKernel(array $options = []): KernelInterface
    {
        static::$class ??= static::getKernelClass();
        $env = $options['environment'] ?? $_ENV['APP_ENV'] ?? $_SERVER['APP_ENV'] ?? 'test';
        $debug = $options['debug'] ?? $_ENV['APP_DEBUG'] ?? $_SERVER['APP_DEBUG'] ?? \true;
        return new static::$class($env, $debug);
    }
    /**
     * Shuts the kernel down if it was used in the test - called by the tearDown method by default.
     */
    protected static function ensureKernelShutdown()
    {
        if (null !== static::$kernel) {
            static::$kernel->boot();
            $container = static::$kernel->getContainer();
            $httpCacheDir = null;
            if ($container->has('http_cache')) {
                $httpCacheDir = static::$kernel->getCacheDir() . '/http_cache';
            }
            if ($container->has('services_resetter')) {
                // Instantiate the service because Container::reset() only resets services that have been used
                $container->get('services_resetter');
            }
            static::$kernel->shutdown();
            static::$booted = \false;
            if (self::$kernelHasBeenRebooted) {
                self::$kernelHasBeenRebooted = \false;
                try {
                    (new \ReflectionProperty(Kernel::class, 'freshCache'))->setValue(null, []);
                } catch (\ReflectionException) {
                    // ignore if the property doesn't exist
                }
                try {
                    (new \ReflectionProperty(SelfCheckingResourceChecker::class, 'cache'))->setValue(null, []);
                } catch (\ReflectionException) {
                    // ignore if the property doesn't exist
                }
            }
            if ($container instanceof ResetInterface) {
                $container->reset();
            }
            if (null !== $httpCacheDir && is_dir($httpCacheDir)) {
                (new Filesystem())->remove($httpCacheDir);
            }
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Bundle\FrameworkBundle\Test;

use _ContaoManager\PHPUnit\Framework\Constraint\LogicalAnd;
use _ContaoManager\PHPUnit\Framework\Constraint\LogicalNot;
use _ContaoManager\Symfony\Component\DomCrawler\Crawler;
use _ContaoManager\Symfony\Component\DomCrawler\Test\Constraint as DomCrawlerConstraint;
use _ContaoManager\Symfony\Component\DomCrawler\Test\Constraint\CrawlerSelectorExists;
/**
 * Ideas borrowed from Laravel Dusk's assertions.
 *
 * @see https://laravel.com/docs/5.7/dusk#available-assertions
 */
trait DomCrawlerAssertionsTrait
{
    public static function assertSelectorExists(string $selector, string $message = ''): void
    {
        self::assertThat(self::getCrawler(), new CrawlerSelectorExists($selector), $message);
    }
    public static function assertSelectorNotExists(string $selector, string $message = ''): void
    {
        self::assertThat(self::getCrawler(), new LogicalNot(new CrawlerSelectorExists($selector)), $message);
    }
    public static function assertSelectorCount(int $expectedCount, string $selector, string $message = ''): void
    {
        self::assertThat(self::getCrawler(), new DomCrawlerConstraint\CrawlerSelectorCount($expectedCount, $selector), $message);
    }
    public static function assertSelectorTextContains(string $selector, string $text, string $message = ''): void
    {
        self::assertThat(self::getCrawler(), LogicalAnd::fromConstraints(new CrawlerSelectorExists($selector), new DomCrawlerConstraint\CrawlerSelectorTextContains($selector, $text)), $message);
    }
    public static function assertAnySelectorTextContains(string $selector, string $text, string $message = ''): void
    {
        self::assertThat(self::getCrawler(), LogicalAnd::fromConstraints(new CrawlerSelectorExists($selector), new DomCrawlerConstraint\CrawlerAnySelectorTextContains($selector, $text)), $message);
    }
    public static function assertSelectorTextSame(string $selector, string $text, string $message = ''): void
    {
        self::assertThat(self::getCrawler(), LogicalAnd::fromConstraints(new CrawlerSelectorExists($selector), new DomCrawlerConstraint\CrawlerSelectorTextSame($selector, $text)), $message);
    }
    public static function assertAnySelectorTextSame(string $selector, string $text, string $message = ''): void
    {
        self::assertThat(self::getCrawler(), LogicalAnd::fromConstraints(new CrawlerSelectorExists($selector), new DomCrawlerConstraint\CrawlerAnySelectorTextSame($selector, $text)), $message);
    }
    public static function assertSelectorTextNotContains(string $selector, string $text, string $message = ''): void
    {
        self::assertThat(self::getCrawler(), LogicalAnd::fromConstraints(new CrawlerSelectorExists($selector), new LogicalNot(new DomCrawlerConstraint\CrawlerSelectorTextContains($selector, $text))), $message);
    }
    public static function assertAnySelectorTextNotContains(string $selector, string $text, string $message = ''): void
    {
        self::assertThat(self::getCrawler(), LogicalAnd::fromConstraints(new CrawlerSelectorExists($selector), new LogicalNot(new DomCrawlerConstraint\CrawlerAnySelectorTextContains($selector, $text))), $message);
    }
    public static function assertPageTitleSame(string $expectedTitle, string $message = ''): void
    {
        self::assertSelectorTextSame('title', $expectedTitle, $message);
    }
    public static function assertPageTitleContains(string $expectedTitle, string $message = ''): void
    {
        self::assertSelectorTextContains('title', $expectedTitle, $message);
    }
    public static function assertInputValueSame(string $fieldName, string $expectedValue, string $message = ''): void
    {
        self::assertThat(self::getCrawler(), LogicalAnd::fromConstraints(new CrawlerSelectorExists("input[name=\"{$fieldName}\"]"), new DomCrawlerConstraint\CrawlerSelectorAttributeValueSame("input[name=\"{$fieldName}\"]", 'value', $expectedValue)), $message);
    }
    public static function assertInputValueNotSame(string $fieldName, string $expectedValue, string $message = ''): void
    {
        self::assertThat(self::getCrawler(), LogicalAnd::fromConstraints(new CrawlerSelectorExists("input[name=\"{$fieldName}\"]"), new LogicalNot(new DomCrawlerConstraint\CrawlerSelectorAttributeValueSame("input[name=\"{$fieldName}\"]", 'value', $expectedValue))), $message);
    }
    public static function assertCheckboxChecked(string $fieldName, string $message = ''): void
    {
        self::assertThat(self::getCrawler(), new CrawlerSelectorExists("input[name=\"{$fieldName}\"]:checked"), $message);
    }
    public static function assertCheckboxNotChecked(string $fieldName, string $message = ''): void
    {
        self::assertThat(self::getCrawler(), new LogicalNot(new CrawlerSelectorExists("input[name=\"{$fieldName}\"]:checked")), $message);
    }
    public static function assertFormValue(string $formSelector, string $fieldName, string $value, string $message = ''): void
    {
        $node = self::getCrawler()->filter($formSelector);
        self::assertNotEmpty($node, \sprintf('Form "%s" not found.', $formSelector));
        $values = $node->form()->getValues();
        self::assertArrayHasKey($fieldName, $values, $message ?: \sprintf('Field "%s" not found in form "%s".', $fieldName, $formSelector));
        self::assertSame($value, $values[$fieldName]);
    }
    public static function assertNoFormValue(string $formSelector, string $fieldName, string $message = ''): void
    {
        $node = self::getCrawler()->filter($formSelector);
        self::assertNotEmpty($node, \sprintf('Form "%s" not found.', $formSelector));
        $values = $node->form()->getValues();
        self::assertArrayNotHasKey($fieldName, $values, $message ?: \sprintf('Field "%s" has a value in form "%s".', $fieldName, $formSelector));
    }
    private static function getCrawler(): Crawler
    {
        if (!$crawler = self::getClient()->getCrawler()) {
            static::fail('A client must have a crawler to make assertions. Did you forget to make an HTTP request?');
        }
        return $crawler;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Bundle\FrameworkBundle\Test;

use _ContaoManager\PHPUnit\Framework\Constraint\LogicalNot;
use _ContaoManager\Symfony\Component\Mailer\Event\MessageEvent;
use _ContaoManager\Symfony\Component\Mailer\Event\MessageEvents;
use _ContaoManager\Symfony\Component\Mailer\Test\Constraint as MailerConstraint;
use _ContaoManager\Symfony\Component\Mime\RawMessage;
use _ContaoManager\Symfony\Component\Mime\Test\Constraint as MimeConstraint;
trait MailerAssertionsTrait
{
    public static function assertEmailCount(int $count, ?string $transport = null, string $message = ''): void
    {
        self::assertThat(self::getMessageMailerEvents(), new MailerConstraint\EmailCount($count, $transport), $message);
    }
    public static function assertQueuedEmailCount(int $count, ?string $transport = null, string $message = ''): void
    {
        self::assertThat(self::getMessageMailerEvents(), new MailerConstraint\EmailCount($count, $transport, \true), $message);
    }
    public static function assertEmailIsQueued(MessageEvent $event, string $message = ''): void
    {
        self::assertThat($event, new MailerConstraint\EmailIsQueued(), $message);
    }
    public static function assertEmailIsNotQueued(MessageEvent $event, string $message = ''): void
    {
        self::assertThat($event, new LogicalNot(new MailerConstraint\EmailIsQueued()), $message);
    }
    public static function assertEmailAttachmentCount(RawMessage $email, int $count, string $message = ''): void
    {
        self::assertThat($email, new MimeConstraint\EmailAttachmentCount($count), $message);
    }
    public static function assertEmailTextBodyContains(RawMessage $email, string $text, string $message = ''): void
    {
        self::assertThat($email, new MimeConstraint\EmailTextBodyContains($text), $message);
    }
    public static function assertEmailTextBodyNotContains(RawMessage $email, string $text, string $message = ''): void
    {
        self::assertThat($email, new LogicalNot(new MimeConstraint\EmailTextBodyContains($text)), $message);
    }
    public static function assertEmailHtmlBodyContains(RawMessage $email, string $text, string $message = ''): void
    {
        self::assertThat($email, new MimeConstraint\EmailHtmlBodyContains($text), $message);
    }
    public static function assertEmailHtmlBodyNotContains(RawMessage $email, string $text, string $message = ''): void
    {
        self::assertThat($email, new LogicalNot(new MimeConstraint\EmailHtmlBodyContains($text)), $message);
    }
    public static function assertEmailHasHeader(RawMessage $email, string $headerName, string $message = ''): void
    {
        self::assertThat($email, new MimeConstraint\EmailHasHeader($headerName), $message);
    }
    public static function assertEmailNotHasHeader(RawMessage $email, string $headerName, string $message = ''): void
    {
        self::assertThat($email, new LogicalNot(new MimeConstraint\EmailHasHeader($headerName)), $message);
    }
    public static function assertEmailHeaderSame(RawMessage $email, string $headerName, string $expectedValue, string $message = ''): void
    {
        self::assertThat($email, new MimeConstraint\EmailHeaderSame($headerName, $expectedValue), $message);
    }
    public static function assertEmailHeaderNotSame(RawMessage $email, string $headerName, string $expectedValue, string $message = ''): void
    {
        self::assertThat($email, new LogicalNot(new MimeConstraint\EmailHeaderSame($headerName, $expectedValue)), $message);
    }
    public static function assertEmailAddressContains(RawMessage $email, string $headerName, string $expectedValue, string $message = ''): void
    {
        self::assertThat($email, new MimeConstraint\EmailAddressContains($headerName, $expectedValue), $message);
    }
    public static function assertEmailSubjectContains(RawMessage $email, string $expectedValue, string $message = ''): void
    {
        self::assertThat($email, new MimeConstraint\EmailSubjectContains($expectedValue), $message);
    }
    public static function assertEmailSubjectNotContains(RawMessage $email, string $expectedValue, string $message = ''): void
    {
        self::assertThat($email, new LogicalNot(new MimeConstraint\EmailSubjectContains($expectedValue)), $message);
    }
    /**
     * @return MessageEvent[]
     */
    public static function getMailerEvents(?string $transport = null): array
    {
        return self::getMessageMailerEvents()->getEvents($transport);
    }
    public static function getMailerEvent(int $index = 0, ?string $transport = null): ?MessageEvent
    {
        return self::getMailerEvents($transport)[$index] ?? null;
    }
    /**
     * @return RawMessage[]
     */
    public static function getMailerMessages(?string $transport = null): array
    {
        return self::getMessageMailerEvents()->getMessages($transport);
    }
    public static function getMailerMessage(int $index = 0, ?string $transport = null): ?RawMessage
    {
        return self::getMailerMessages($transport)[$index] ?? null;
    }
    private static function getMessageMailerEvents(): MessageEvents
    {
        $container = static::getContainer();
        if ($container->has('mailer.message_logger_listener')) {
            return $container->get('mailer.message_logger_listener')->getEvents();
        }
        static::fail('A client must have Mailer enabled to make email assertions. Did you forget to require symfony/mailer?');
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Bundle\FrameworkBundle\Test;

use _ContaoManager\PHPUnit\Framework\Constraint\LogicalNot;
use _ContaoManager\Symfony\Component\Notifier\Event\MessageEvent;
use _ContaoManager\Symfony\Component\Notifier\Event\NotificationEvents;
use _ContaoManager\Symfony\Component\Notifier\Message\MessageInterface;
use _ContaoManager\Symfony\Component\Notifier\Test\Constraint as NotifierConstraint;
/**
 * @author Smaïne Milianni <smaine.milianni@gmail.com>
 */
trait NotificationAssertionsTrait
{
    public static function assertNotificationCount(int $count, ?string $transportName = null, string $message = ''): void
    {
        self::assertThat(self::getNotificationEvents(), new NotifierConstraint\NotificationCount($count, $transportName), $message);
    }
    public static function assertQueuedNotificationCount(int $count, ?string $transportName = null, string $message = ''): void
    {
        self::assertThat(self::getNotificationEvents(), new NotifierConstraint\NotificationCount($count, $transportName, \true), $message);
    }
    public static function assertNotificationIsQueued(MessageEvent $event, string $message = ''): void
    {
        self::assertThat($event, new NotifierConstraint\NotificationIsQueued(), $message);
    }
    public static function assertNotificationIsNotQueued(MessageEvent $event, string $message = ''): void
    {
        self::assertThat($event, new LogicalNot(new NotifierConstraint\NotificationIsQueued()), $message);
    }
    public static function assertNotificationSubjectContains(MessageInterface $notification, string $text, string $message = ''): void
    {
        self::assertThat($notification, new NotifierConstraint\NotificationSubjectContains($text), $message);
    }
    public static function assertNotificationSubjectNotContains(MessageInterface $notification, string $text, string $message = ''): void
    {
        self::assertThat($notification, new LogicalNot(new NotifierConstraint\NotificationSubjectContains($text)), $message);
    }
    public static function assertNotificationTransportIsEqual(MessageInterface $notification, ?string $transportName = null, string $message = ''): void
    {
        self::assertThat($notification, new NotifierConstraint\NotificationTransportIsEqual($transportName), $message);
    }
    public static function assertNotificationTransportIsNotEqual(MessageInterface $notification, ?string $transportName = null, string $message = ''): void
    {
        self::assertThat($notification, new LogicalNot(new NotifierConstraint\NotificationTransportIsEqual($transportName)), $message);
    }
    /**
     * @return MessageEvent[]
     */
    public static function getNotifierEvents(?string $transportName = null): array
    {
        return self::getNotificationEvents()->getEvents($transportName);
    }
    public static function getNotifierEvent(int $index = 0, ?string $transportName = null): ?MessageEvent
    {
        return self::getNotifierEvents($transportName)[$index] ?? null;
    }
    /**
     * @return MessageInterface[]
     */
    public static function getNotifierMessages(?string $transportName = null): array
    {
        return self::getNotificationEvents()->getMessages($transportName);
    }
    public static function getNotifierMessage(int $index = 0, ?string $transportName = null): ?MessageInterface
    {
        return self::getNotifierMessages($transportName)[$index] ?? null;
    }
    public static function getNotificationEvents(): NotificationEvents
    {
        $container = static::getContainer();
        if ($container->has('notifier.notification_logger_listener')) {
            return $container->get('notifier.notification_logger_listener')->getEvents();
        }
        static::fail('A client must have Notifier enabled to make notifications assertions. Did you forget to require symfony/notifier?');
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Bundle\FrameworkBundle\Test;

use _ContaoManager\Symfony\Bundle\FrameworkBundle\KernelBrowser;
use _ContaoManager\Symfony\Component\HttpClient\DataCollector\HttpClientDataCollector;
/**
 * @author Mathieu Santostefano <msantostefano@protonmail.com>
 */
trait HttpClientAssertionsTrait
{
    public static function assertHttpClientRequest(string $expectedUrl, string $expectedMethod = 'GET', string|array|null $expectedBody = null, array $expectedHeaders = [], string $httpClientId = 'http_client'): void
    {
        /** @var KernelBrowser $client */
        $client = static::getClient();
        if (!$profile = $client->getProfile()) {
            static::fail('The Profiler must be enabled for the current request. Please ensure to call "$client->enableProfiler()" before making the request.');
        }
        /** @var HttpClientDataCollector $httpClientDataCollector */
        $httpClientDataCollector = $profile->getCollector('http_client');
        $expectedRequestHasBeenFound = \false;
        if (!\array_key_exists($httpClientId, $httpClientDataCollector->getClients())) {
            static::fail(\sprintf('HttpClient "%s" is not registered.', $httpClientId));
        }
        foreach ($httpClientDataCollector->getClients()[$httpClientId]['traces'] as $trace) {
            if ($expectedUrl !== $trace['info']['url'] && $expectedUrl !== $trace['url'] || $expectedMethod !== $trace['method']) {
                continue;
            }
            if (null !== $expectedBody) {
                $actualBody = null;
                if (null !== $trace['options']['body'] && null === $trace['options']['json']) {
                    $actualBody = \is_string($trace['options']['body']) ? $trace['options']['body'] : $trace['options']['body']->getValue(\true);
                }
                if (null === $trace['options']['body'] && null !== $trace['options']['json']) {
                    $actualBody = $trace['options']['json']->getValue(\true);
                }
                if (!$actualBody) {
                    continue;
                }
                if ($expectedBody === $actualBody) {
                    $expectedRequestHasBeenFound = \true;
                    if (!$expectedHeaders) {
                        break;
                    }
                }
            }
            if ($expectedHeaders) {
                $actualHeaders = $trace['options']['headers'] ?? [];
                foreach ($actualHeaders as $headerKey => $actualHeader) {
                    if (\array_key_exists($headerKey, $expectedHeaders) && $expectedHeaders[$headerKey] === $actualHeader->getValue(\true)) {
                        $expectedRequestHasBeenFound = \true;
                        break 2;
                    }
                }
            }
            $expectedRequestHasBeenFound = \true;
            break;
        }
        self::assertTrue($expectedRequestHasBeenFound, 'The expected request has not been called: "' . $expectedMethod . '" - "' . $expectedUrl . '"');
    }
    public function assertNotHttpClientRequest(string $unexpectedUrl, string $expectedMethod = 'GET', string $httpClientId = 'http_client'): void
    {
        /** @var KernelBrowser $client */
        $client = static::getClient();
        if (!$profile = $client->getProfile()) {
            static::fail('The Profiler must be enabled for the current request. Please ensure to call "$client->enableProfiler()" before making the request.');
        }
        /** @var HttpClientDataCollector $httpClientDataCollector */
        $httpClientDataCollector = $profile->getCollector('http_client');
        $unexpectedUrlHasBeenFound = \false;
        if (!\array_key_exists($httpClientId, $httpClientDataCollector->getClients())) {
            static::fail(\sprintf('HttpClient "%s" is not registered.', $httpClientId));
        }
        foreach ($httpClientDataCollector->getClients()[$httpClientId]['traces'] as $trace) {
            if (($unexpectedUrl === $trace['info']['url'] || $unexpectedUrl === $trace['url']) && $expectedMethod === $trace['method']) {
                $unexpectedUrlHasBeenFound = \true;
                break;
            }
        }
        self::assertFalse($unexpectedUrlHasBeenFound, \sprintf('Unexpected URL called: "%s" - "%s"', $expectedMethod, $unexpectedUrl));
    }
    public static function assertHttpClientRequestCount(int $count, string $httpClientId = 'http_client'): void
    {
        /** @var KernelBrowser $client */
        $client = static::getClient();
        if (!$profile = $client->getProfile()) {
            static::fail('The Profiler must be enabled for the current request. Please ensure to call "$client->enableProfiler()" before making the request.');
        }
        /** @var HttpClientDataCollector $httpClientDataCollector */
        $httpClientDataCollector = $profile->getCollector('http_client');
        self::assertCount($count, $httpClientDataCollector->getClients()[$httpClientId]['traces']);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Bundle\FrameworkBundle\Test;

use _ContaoManager\PHPUnit\Framework\Constraint\Constraint;
use _ContaoManager\PHPUnit\Framework\Constraint\LogicalAnd;
use _ContaoManager\PHPUnit\Framework\Constraint\LogicalNot;
use _ContaoManager\PHPUnit\Framework\ExpectationFailedException;
use _ContaoManager\Symfony\Component\BrowserKit\AbstractBrowser;
use _ContaoManager\Symfony\Component\BrowserKit\Request as BrowserKitRequest;
use _ContaoManager\Symfony\Component\BrowserKit\Response as BrowserKitResponse;
use _ContaoManager\Symfony\Component\BrowserKit\Test\Constraint as BrowserKitConstraint;
use _ContaoManager\Symfony\Component\HttpFoundation\Request;
use _ContaoManager\Symfony\Component\HttpFoundation\Response;
use _ContaoManager\Symfony\Component\HttpFoundation\Test\Constraint as ResponseConstraint;
/**
 * Ideas borrowed from Laravel Dusk's assertions.
 *
 * @see https://laravel.com/docs/5.7/dusk#available-assertions
 */
trait BrowserKitAssertionsTrait
{
    public static function assertResponseIsSuccessful(string $message = ''): void
    {
        self::assertThatForResponse(new ResponseConstraint\ResponseIsSuccessful(), $message);
    }
    public static function assertResponseStatusCodeSame(int $expectedCode, string $message = ''): void
    {
        self::assertThatForResponse(new ResponseConstraint\ResponseStatusCodeSame($expectedCode), $message);
    }
    public static function assertResponseFormatSame(?string $expectedFormat, string $message = ''): void
    {
        self::assertThatForResponse(new ResponseConstraint\ResponseFormatSame(self::getRequest(), $expectedFormat), $message);
    }
    public static function assertResponseRedirects(?string $expectedLocation = null, ?int $expectedCode = null, string $message = ''): void
    {
        $constraint = new ResponseConstraint\ResponseIsRedirected();
        if ($expectedLocation) {
            if (class_exists(ResponseConstraint\ResponseHeaderLocationSame::class)) {
                $locationConstraint = new ResponseConstraint\ResponseHeaderLocationSame(self::getRequest(), $expectedLocation);
            } else {
                $locationConstraint = new ResponseConstraint\ResponseHeaderSame('Location', $expectedLocation);
            }
            $constraint = LogicalAnd::fromConstraints($constraint, $locationConstraint);
        }
        if ($expectedCode) {
            $constraint = LogicalAnd::fromConstraints($constraint, new ResponseConstraint\ResponseStatusCodeSame($expectedCode));
        }
        self::assertThatForResponse($constraint, $message);
    }
    public static function assertResponseHasHeader(string $headerName, string $message = ''): void
    {
        self::assertThatForResponse(new ResponseConstraint\ResponseHasHeader($headerName), $message);
    }
    public static function assertResponseNotHasHeader(string $headerName, string $message = ''): void
    {
        self::assertThatForResponse(new LogicalNot(new ResponseConstraint\ResponseHasHeader($headerName)), $message);
    }
    public static function assertResponseHeaderSame(string $headerName, string $expectedValue, string $message = ''): void
    {
        self::assertThatForResponse(new ResponseConstraint\ResponseHeaderSame($headerName, $expectedValue), $message);
    }
    public static function assertResponseHeaderNotSame(string $headerName, string $expectedValue, string $message = ''): void
    {
        self::assertThatForResponse(new LogicalNot(new ResponseConstraint\ResponseHeaderSame($headerName, $expectedValue)), $message);
    }
    public static function assertResponseHasCookie(string $name, string $path = '/', ?string $domain = null, string $message = ''): void
    {
        self::assertThatForResponse(new ResponseConstraint\ResponseHasCookie($name, $path, $domain), $message);
    }
    public static function assertResponseNotHasCookie(string $name, string $path = '/', ?string $domain = null, string $message = ''): void
    {
        self::assertThatForResponse(new LogicalNot(new ResponseConstraint\ResponseHasCookie($name, $path, $domain)), $message);
    }
    public static function assertResponseCookieValueSame(string $name, string $expectedValue, string $path = '/', ?string $domain = null, string $message = ''): void
    {
        self::assertThatForResponse(LogicalAnd::fromConstraints(new ResponseConstraint\ResponseHasCookie($name, $path, $domain), new ResponseConstraint\ResponseCookieValueSame($name, $expectedValue, $path, $domain)), $message);
    }
    public static function assertResponseIsUnprocessable(string $message = ''): void
    {
        self::assertThatForResponse(new ResponseConstraint\ResponseIsUnprocessable(), $message);
    }
    public static function assertBrowserHasCookie(string $name, string $path = '/', ?string $domain = null, string $message = ''): void
    {
        self::assertThatForClient(new BrowserKitConstraint\BrowserHasCookie($name, $path, $domain), $message);
    }
    public static function assertBrowserNotHasCookie(string $name, string $path = '/', ?string $domain = null, string $message = ''): void
    {
        self::assertThatForClient(new LogicalNot(new BrowserKitConstraint\BrowserHasCookie($name, $path, $domain)), $message);
    }
    public static function assertBrowserCookieValueSame(string $name, string $expectedValue, bool $raw = \false, string $path = '/', ?string $domain = null, string $message = ''): void
    {
        self::assertThatForClient(LogicalAnd::fromConstraints(new BrowserKitConstraint\BrowserHasCookie($name, $path, $domain), new BrowserKitConstraint\BrowserCookieValueSame($name, $expectedValue, $raw, $path, $domain)), $message);
    }
    public static function assertRequestAttributeValueSame(string $name, string $expectedValue, string $message = ''): void
    {
        self::assertThat(self::getRequest(), new ResponseConstraint\RequestAttributeValueSame($name, $expectedValue), $message);
    }
    public static function assertRouteSame(string $expectedRoute, array $parameters = [], string $message = ''): void
    {
        $constraint = new ResponseConstraint\RequestAttributeValueSame('_route', $expectedRoute);
        $constraints = [];
        foreach ($parameters as $key => $value) {
            $constraints[] = new ResponseConstraint\RequestAttributeValueSame($key, $value);
        }
        if ($constraints) {
            $constraint = LogicalAnd::fromConstraints($constraint, ...$constraints);
        }
        self::assertThat(self::getRequest(), $constraint, $message);
    }
    public static function assertThatForResponse(Constraint $constraint, string $message = ''): void
    {
        try {
            self::assertThat(self::getResponse(), $constraint, $message);
        } catch (ExpectationFailedException $exception) {
            if (($serverExceptionMessage = self::getResponse()->headers->get('X-Debug-Exception')) && $serverExceptionFile = self::getResponse()->headers->get('X-Debug-Exception-File')) {
                $serverExceptionFile = explode(':', $serverExceptionFile);
                $exception->__construct($exception->getMessage(), $exception->getComparisonFailure(), new \ErrorException(rawurldecode($serverExceptionMessage), 0, 1, rawurldecode($serverExceptionFile[0]), $serverExceptionFile[1]), $exception->getPrevious());
            }
            throw $exception;
        }
    }
    public static function assertThatForClient(Constraint $constraint, string $message = ''): void
    {
        self::assertThat(self::getClient(), $constraint, $message);
    }
    protected static function getClient(?AbstractBrowser $newClient = null): ?AbstractBrowser
    {
        static $client;
        if (0 < \func_num_args()) {
            return $client = $newClient;
        }
        if (!$client instanceof AbstractBrowser) {
            static::fail(\sprintf('A client must be set to make assertions on it. Did you forget to call "%s::createClient()"?', __CLASS__));
        }
        return $client;
    }
    private static function getResponse(): Response
    {
        if (!$response = self::getClient()->getResponse()) {
            static::fail('A client must have an HTTP Response to make assertions. Did you forget to make an HTTP request?');
        }
        if ($response instanceof BrowserKitResponse) {
            return new Response($response->getContent(), $response->getStatusCode(), $response->getHeaders());
        }
        return $response;
    }
    private static function getRequest(): Request
    {
        if (!$request = self::getClient()->getRequest()) {
            static::fail('A client must have an HTTP Request to make assertions. Did you forget to make an HTTP request?');
        }
        if ($request instanceof BrowserKitRequest) {
            return Request::create($request->getUri(), $request->getMethod(), $request->getParameters(), $request->getCookies(), $request->getFiles(), $request->getServer(), $request->getContent());
        }
        return $request;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Bundle\FrameworkBundle\Test;

use _ContaoManager\Symfony\Component\Security\Core\Authentication\Token\AbstractToken;
use _ContaoManager\Symfony\Component\Security\Core\User\UserInterface;
/**
 * A very limited token that is used to login in tests using the KernelBrowser.
 *
 * @author Wouter de Jong <wouter@wouterj.nl>
 */
class TestBrowserToken extends AbstractToken
{
    private string $firewallName;
    public function __construct(array $roles = [], ?UserInterface $user = null, string $firewallName = 'main')
    {
        parent::__construct($roles);
        if (null !== $user) {
            $this->setUser($user);
        }
        $this->firewallName = $firewallName;
    }
    public function getFirewallName(): string
    {
        return $this->firewallName;
    }
    public function getCredentials(): mixed
    {
        return null;
    }
    public function __serialize(): array
    {
        return [$this->firewallName, parent::__serialize()];
    }
    public function __unserialize(array $data): void
    {
        [$this->firewallName, $parentData] = $data;
        parent::__unserialize($parentData);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Bundle\FrameworkBundle\Test;

use _ContaoManager\Symfony\Bundle\FrameworkBundle\KernelBrowser;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException;
/**
 * WebTestCase is the base class for functional tests.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
abstract class WebTestCase extends KernelTestCase
{
    use WebTestAssertionsTrait;
    protected function tearDown(): void
    {
        parent::tearDown();
        self::getClient(null);
    }
    /**
     * Creates a KernelBrowser.
     *
     * @param array $options An array of options to pass to the createKernel method
     * @param array $server  An array of server parameters
     */
    protected static function createClient(array $options = [], array $server = []): KernelBrowser
    {
        if (static::$booted) {
            throw new \LogicException(\sprintf('Booting the kernel before calling "%s()" is not supported, the kernel should only be booted once.', __METHOD__));
        }
        $kernel = static::bootKernel($options);
        try {
            $client = $kernel->getContainer()->get('test.client');
        } catch (ServiceNotFoundException) {
            if (class_exists(KernelBrowser::class)) {
                throw new \LogicException('You cannot create the client used in functional tests if the "framework.test" config is not set to true.');
            }
            throw new \LogicException('You cannot create the client used in functional tests if the BrowserKit component is not available. Try running "composer require symfony/browser-kit".');
        }
        $client->setServerParameters($server);
        return self::getClient($client);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Bundle\FrameworkBundle\Test;

trait WebTestAssertionsTrait
{
    use BrowserKitAssertionsTrait;
    use DomCrawlerAssertionsTrait;
    use HttpClientAssertionsTrait;
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Bundle\FrameworkBundle\Test;

use _ContaoManager\Psr\Container\ContainerInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Container;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
use _ContaoManager\Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface;
use _ContaoManager\Symfony\Component\HttpKernel\KernelInterface;
/**
 * A special container used in tests. This gives access to both public and
 * private services. The container will not include private services that have
 * been inlined or removed. Private services will be removed when they are not
 * used by other services.
 *
 * @author Nicolas Grekas <p@tchwork.com>
 *
 * @internal
 */
class TestContainer extends Container
{
    public function __construct(private KernelInterface $kernel, private string $privateServicesLocatorId, private array $renamedIds = [])
    {
    }
    public function compile(): void
    {
        $this->getPublicContainer()->compile();
    }
    public function isCompiled(): bool
    {
        return $this->getPublicContainer()->isCompiled();
    }
    public function getParameterBag(): ParameterBagInterface
    {
        return $this->getPublicContainer()->getParameterBag();
    }
    public function getParameter(string $name): array|bool|string|int|float|\UnitEnum|null
    {
        return $this->getPublicContainer()->getParameter($name);
    }
    public function hasParameter(string $name): bool
    {
        return $this->getPublicContainer()->hasParameter($name);
    }
    public function setParameter(string $name, mixed $value): void
    {
        $this->getPublicContainer()->setParameter($name, $value);
    }
    public function set(string $id, mixed $service): void
    {
        $container = $this->getPublicContainer();
        $renamedId = $this->renamedIds[$id] ?? $id;
        if (!$this->getPrivateContainer()->has($renamedId)) {
            $container->set($renamedId, $service);
        } elseif (isset($container->privates[$renamedId])) {
            throw new InvalidArgumentException(\sprintf('The "%s" service is already initialized, you cannot replace it.', $id));
        } else {
            $container->privates[$renamedId] = $service;
        }
    }
    public function has(string $id): bool
    {
        return $this->getPublicContainer()->has($id) || $this->getPrivateContainer()->has($id);
    }
    public function get(string $id, int $invalidBehavior = self::EXCEPTION_ON_INVALID_REFERENCE): ?object
    {
        return $this->getPrivateContainer()->has($id) ? $this->getPrivateContainer()->get($id) : $this->getPublicContainer()->get($id, $invalidBehavior);
    }
    public function initialized(string $id): bool
    {
        return $this->getPublicContainer()->initialized($id);
    }
    public function reset(): void
    {
        // ignore the call
    }
    public function getServiceIds(): array
    {
        return $this->getPublicContainer()->getServiceIds();
    }
    public function getRemovedIds(): array
    {
        return $this->getPublicContainer()->getRemovedIds();
    }
    private function getPublicContainer(): Container
    {
        return $this->kernel->getContainer() ?? throw new \LogicException('Cannot access the container on a non-booted kernel. Did you forget to boot it?');
    }
    private function getPrivateContainer(): ContainerInterface
    {
        return $this->getPublicContainer()->get($this->privateServicesLocatorId);
    }
}
CHANGELOG
=========

6.4
---

 * Add `HttpClientAssertionsTrait`
 * Add `AbstractController::renderBlock()` and `renderBlockView()`
 * Remove call to `renderView()` in `AbstractController::render()`
 * Add native return type to `Translator` and to `Application::reset()`
 * Deprecate the integration of Doctrine annotations, either uninstall the `doctrine/annotations` package or disable the integration by setting `framework.annotations` to `false`
 * Enable `json_decode_detailed_errors` context for Serializer by default if `kernel.debug` is true and the `seld/jsonlint` package is installed
 * Add `DomCrawlerAssertionsTrait::assertAnySelectorTextContains(string $selector, string $text)`
 * Add `DomCrawlerAssertionsTrait::assertAnySelectorTextSame(string $selector, string $text)`
 * Add `DomCrawlerAssertionsTrait::assertAnySelectorTextNotContains(string $selector, string $text)`
 * Deprecate `EnableLoggerDebugModePass`, use argument `$debug` of HttpKernel's `Logger` instead
 * Deprecate `AddDebugLogProcessorPass::configureLogger()`, use HttpKernel's `DebugLoggerConfigurator` instead
 * Deprecate not setting the `framework.handle_all_throwables` config option; it will default to `true` in 7.0
 * Deprecate not setting the `framework.php_errors.log` config option; it will default to `true` in 7.0
 * Deprecate not setting the `framework.session.cookie_secure` config option; it will default to `auto` in 7.0
 * Deprecate not setting the `framework.session.cookie_samesite` config option; it will default to `lax` in 7.0
 * Deprecate not setting either `framework.session.handler_id` or `save_path` config options; `handler_id` will
   default to null in 7.0 if `save_path` is not set and to `session.handler.native_file` otherwise
 * Deprecate not setting the `framework.uid.default_uuid_version` config option; it will default to `7` in 7.0
 * Deprecate not setting the `framework.uid.time_based_uuid_version` config option; it will default to `7` in 7.0
 * Deprecate not setting the `framework.validation.email_validation_mode` config option; it will default to `html5` in 7.0
 * Deprecate `framework.validation.enable_annotations`, use `framework.validation.enable_attributes` instead
 * Deprecate `framework.serializer.enable_annotations`, use `framework.serializer.enable_attributes` instead
 * Add `array $tokenAttributes = []` optional parameter to `KernelBrowser::loginUser()`
 * Add support for relative URLs in BrowserKit's redirect assertion
 * Change BrowserKitAssertionsTrait::getClient() to be protected
 * Deprecate the `framework.asset_mapper.provider` config option
 * Add `--exclude` option to the `cache:pool:clear` command
 * Add parameters deprecations to the output of `debug:container` command
 * Change `framework.asset_mapper.importmap_polyfill` from a URL to the name of an item in the importmap
 * Provide `$buildDir` when running `CacheWarmer` to build read-only resources
 * Add the global `--profile` option to the console to enable profiling commands
 * Deprecate the `routing.loader.annotation` service, use the `routing.loader.attribute` service instead
 * Deprecate the `routing.loader.annotation.directory` service, use the `routing.loader.attribute.directory` service instead
 * Deprecate the `routing.loader.annotation.file` service, use the `routing.loader.attribute.file` service instead
 * Deprecate `AnnotatedRouteControllerLoader`, use `AttributeRouteControllerLoader` instead
 * Deprecate `AddExpressionLanguageProvidersPass`, use `Symfony\Component\Routing\DependencyInjection\AddExpressionLanguageProvidersPass` instead
 * Deprecate `DataCollectorTranslatorPass`, use `Symfony\Component\Translation\DependencyInjection\DataCollectorTranslatorPass` instead
 * Deprecate `LoggingTranslatorPass`, use `Symfony\Component\Translation\DependencyInjection\LoggingTranslatorPass` instead
 * Deprecate `WorkflowGuardListenerPass`, use `Symfony\Component\Workflow\DependencyInjection\WorkflowGuardListenerPass` instead

6.3
---

 * Add `extra` option for `http_client.default_options` and `http_client.scoped_client`
 * Add `DomCrawlerAssertionsTrait::assertSelectorCount(int $count, string $selector)`
 * Allow to avoid `limit` definition in a RateLimiter configuration when using the `no_limit` policy
 * Add `--format` option to the `debug:config` command
 * Add support to pass namespace wildcard in `framework.messenger.routing`
 * Deprecate `framework:exceptions` tag, unwrap it and replace `framework:exception` tags' `name` attribute by `class`
 * Deprecate the `notifier.logger_notification_listener` service, use the `notifier.notification_logger_listener` service instead
 * Allow setting private services with the test container
 * Register alias for argument for workflow services with workflow name only
 * Configure the `ErrorHandler` on `FrameworkBundle::boot()`
 * Allow setting `debug.container.dump` to `false` to disable dumping the container to XML
 * Add `framework.http_cache.skip_response_headers` option
 * Display warmers duration on debug verbosity for `cache:clear` command
 * Add `AbstractController::sendEarlyHints()` to send HTTP Early Hints
 * Add autowiring aliases for `Http\Client\HttpAsyncClient`
 * Deprecate the `Http\Client\HttpClient` service, use `Psr\Http\Client\ClientInterface` instead
 * Add `stop_worker_on_signals` configuration option to `messenger` to define signals which would stop a worker
 * Add support for `--all` option to clear all cache pools with `cache:pool:clear` command
 * Add `--show-aliases` option to `debug:router` command

6.2
---

 * Add `resolve-env` option to `debug:config` command to display actual values of environment variables in dumped configuration
 * Add `NotificationAssertionsTrait`
 * Add option `framework.handle_all_throwables` to allow `Symfony\Component\HttpKernel\HttpKernel` to handle all kinds of `Throwable`
 * Make `AbstractController::render()` able to deal with forms and deprecate `renderForm()`
 * Deprecate the `Symfony\Component\Serializer\Normalizer\ObjectNormalizer` and
   `Symfony\Component\Serializer\Normalizer\PropertyNormalizer` autowiring aliases, type-hint against
   `Symfony\Component\Serializer\Normalizer\NormalizerInterface` or implement `NormalizerAwareInterface` instead
 * Add service usages list to the `debug:container` command output
 * Add service and alias deprecation message to `debug:container [<name>]` output
 * Tag all workflows services with `workflow`, those with type=workflow are
   tagged with `workflow.workflow`, and those with type=state_machine with
   `workflow.state_machine`
 * Add `rate_limiter` configuration option to `messenger.transport` to allow rate limited transports using the RateLimiter component
 * Remove `@internal` tag from secret vaults to allow them to be used directly outside the framework bundle and custom vaults to be added
 * Deprecate `framework.form.legacy_error_messages` config node
 * Add a `framework.router.cache_dir` configuration option to configure the default `Router` `cache_dir` option
 * Add option `framework.messenger.buses.*.default_middleware.allow_no_senders` to enable throwing when a message doesn't have a sender
 * Deprecate `AbstractController::renderForm()`, use `render()` instead
 * Deprecate `FrameworkExtension::registerRateLimiter()`

6.1
---

 * Add support for configuring semaphores
 * Environment variable `SYMFONY_IDE` is read by default when `framework.ide` config is not set
 * Load PHP configuration files by default in the `MicroKernelTrait`
 * Add `cache:pool:invalidate-tags` command
 * Add `xliff` support in addition to `xlf` for `XliffFileDumper`
 * Deprecate the `reset_on_message` config option. It can be set to `true` only and does nothing now
 * Add `trust_x_sendfile_type_header` option
 * Add support for first-class callable route controller in `MicroKernelTrait`
 * Add tag `routing.condition_service` to autoconfigure routing condition services
 * Automatically register kernel methods marked with the `Symfony\Component\Routing\Annotation\Route` attribute or annotation as controllers in `MicroKernelTrait`
 * Deprecate not setting the `http_method_override` config option. The default value will change to `false` in 7.0.
 * Add `framework.profiler.collect_serializer_data` config option, set it to `true` to enable the serializer data collector and profiler panel

6.0
---

 * Remove the `session.storage` alias and `session.storage.*` services, use the `session.storage.factory` alias and `session.storage.factory.*` services instead
 * Remove `framework.session.storage_id` configuration option, use the `framework.session.storage_factory_id` configuration option instead
 * Remove the `session` service and the `SessionInterface` alias, use the `\Symfony\Component\HttpFoundation\Request::getSession()` or the new `\Symfony\Component\HttpFoundation\RequestStack::getSession()` methods instead
 * Remove the `session.attribute_bag` service and `session.flash_bag` service
 * Remove the `lock.RESOURCE_NAME` and `lock.RESOURCE_NAME.store` services and the `lock`, `LockInterface`, `lock.store` and `PersistingStoreInterface` aliases, use `lock.RESOURCE_NAME.factory`, `lock.factory` or `LockFactory` instead
 * The `form.factory`, `form.type.file`, `translator`, `security.csrf.token_manager`, `serializer`,
   `cache_clearer`, `filesystem` and `validator` services are now private
 * Remove the `output-format` and `xliff-version` options from `TranslationUpdateCommand`
 * Remove `has()`, `get()`, `getDoctrine()`n and `dispatchMessage()` from `AbstractController`, use method/constructor injection instead
 * Make the "framework.router.utf8" configuration option default to `true`
 * Remove the `AdapterInterface` autowiring alias, use `CacheItemPoolInterface` instead
 * Make the `profiler` service private
 * Remove all other values than "none", "php_array" and "file" for `framework.annotation.cache`
 * Register workflow services as private
 * Remove support for passing a `RouteCollectionBuilder` to `MicroKernelTrait::configureRoutes()`, type-hint `RoutingConfigurator` instead
 * Remove the `cache.adapter.doctrine` service
 * Remove the `framework.translator.enabled_locales` config option, use `framework.enabled_locales` instead
 * Make the `framework.messenger.reset_on_message` configuration option default to `true`

5.4
---

 * Add `set_locale_from_accept_language` config option to automatically set the request locale based on the `Accept-Language`
   HTTP request header and the `framework.enabled_locales` config option
 * Add `set_content_language_from_locale` config option to automatically set the `Content-Language` HTTP response header based on the Request locale
 * Deprecate the `framework.translator.enabled_locales`, use `framework.enabled_locales` instead
 * Add autowiring alias for `HttpCache\StoreInterface`
 * Add the ability to enable the profiler using a request query parameter, body parameter or attribute
 * Deprecate the `AdapterInterface` autowiring alias, use `CacheItemPoolInterface` instead
 * Deprecate the public `profiler` service to private
 * Deprecate `get()`, `has()`, `getDoctrine()`, and `dispatchMessage()` in `AbstractController`, use method/constructor injection instead
 * Deprecate the `cache.adapter.doctrine` service
 * Add support for resetting container services after each messenger message
 * Add `configureContainer()`, `configureRoutes()`, `getConfigDir()` and `getBundlesPath()` to `MicroKernelTrait`
 * Add support for configuring log level, and status code by exception class
 * Bind the `default_context` parameter onto serializer's encoders and normalizers
 * Add support for `statusCode` default parameter when loading a template directly from route using the `Symfony\Bundle\FrameworkBundle\Controller\TemplateController` controller
 * Deprecate `translation:update` command, use `translation:extract` instead
 * Add `PhpStanExtractor` support for the PropertyInfo component
 * Add `cache.adapter.doctrine_dbal` service to replace `cache.adapter.pdo` when a Doctrine DBAL connection is used.

5.3
---

 * Deprecate the `session.storage` alias and `session.storage.*` services, use the `session.storage.factory` alias and `session.storage.factory.*` services instead
 * Deprecate the `framework.session.storage_id` configuration option, use the `framework.session.storage_factory_id` configuration option instead
 * Deprecate the `session` service and the `SessionInterface` alias, use the `Request::getSession()` or the new `RequestStack::getSession()` methods instead
 * Add `AbstractController::renderForm()` to render a form and set the appropriate HTTP status code
 * Add support for configuring PHP error level to log levels
 * Add the `dispatcher` option to `debug:event-dispatcher`
 * Add the `event_dispatcher.dispatcher` tag
 * Add `assertResponseFormatSame()` in `BrowserKitAssertionsTrait`
 * Add support for configuring UUID factory services
 * Add tag `assets.package` to register asset packages
 * Add support to use a PSR-6 compatible cache for Doctrine annotations
 * Deprecate all other values than "none", "php_array" and "file" for `framework.annotation.cache`
 * Add `KernelTestCase::getContainer()` as the best way to get a container in tests
 * Rename the container parameter `profiler_listener.only_master_requests` to `profiler_listener.only_main_requests`
 * Add service `fragment.uri_generator` to generate the URI of a fragment
 * Deprecate registering workflow services as public
 * Deprecate option `--xliff-version` of the `translation:update` command, use e.g. `--format=xlf20` instead
 * Deprecate option `--output-format` of the `translation:update` command, use e.g. `--format=xlf20` instead

5.2.0
-----

 * Added `framework.http_cache` configuration tree
 * Added `framework.trusted_proxies` and `framework.trusted_headers` configuration options
 * Deprecated the public `form.factory`, `form.type.file`, `translator`, `security.csrf.token_manager`, `serializer`,
   `cache_clearer`, `filesystem` and `validator` services to private.
 * Added `TemplateAwareDataCollectorInterface` and `AbstractDataCollector` to simplify custom data collector creation and leverage autoconfiguration
 * Add `cache.adapter.redis_tag_aware` tag to use `RedisCacheAwareAdapter`
 * added `framework.http_client.retry_failing` configuration tree
 * added `assertCheckboxChecked()` and `assertCheckboxNotChecked()` in `WebTestCase`
 * added `assertFormValue()` and `assertNoFormValue()` in `WebTestCase`
 * Added "--as-tree=3" option to `translation:update` command to dump messages as a tree-like structure. The given value defines the level where to switch to inline YAML
 * Deprecated the `lock.RESOURCE_NAME` and `lock.RESOURCE_NAME.store` services and the `lock`, `LockInterface`, `lock.store` and `PersistingStoreInterface` aliases, use `lock.RESOURCE_NAME.factory`, `lock.factory` or `LockFactory` instead.

5.1.0
-----
 * Removed `--no-backup` option from `translation:update` command (broken since `5.0.0`)
 * Added link to source for controllers registered as named services
 * Added link to source on controller on `router:match`/`debug:router` (when `framework.ide` is configured)
 * Added the `framework.router.default_uri` configuration option to configure the default `RequestContext`
 * Made `MicroKernelTrait::configureContainer()` compatible with `ContainerConfigurator`
 * Added a new `mailer.message_bus` option to configure or disable the message bus to use to send mails.
 * Added flex-compatible default implementation for `MicroKernelTrait::registerBundles()`
 * Deprecated passing a `RouteCollectionBuilder` to `MicroKernelTrait::configureRoutes()`, type-hint `RoutingConfigurator` instead
 * The `TemplateController` now accepts context argument
 * Deprecated *not* setting the "framework.router.utf8" configuration option as it will default to `true` in Symfony 6.0
 * Added tag `routing.expression_language_function` to define functions available in route conditions
 * Added `debug:container --deprecations` option to see compile-time deprecations.
 * Made `BrowserKitAssertionsTrait` report the original error message in case of a failure
 * Added ability for `config:dump-reference` and `debug:config` to dump and debug kernel container extension configuration.
 * Deprecated `session.attribute_bag` service and `session.flash_bag` service.

5.0.0
-----

 * Removed support to load translation resources from the legacy directories `src/Resources/translations/` and `src/Resources/<BundleName>/translations/`
 * Removed `ControllerNameParser`.
 * Removed `ResolveControllerNameSubscriber`
 * Removed support for `bundle:controller:action` to reference controllers. Use `serviceOrFqcn::method` instead
 * Removed support for PHP templating, use Twig instead
 * Removed `Controller`, use `AbstractController` instead
 * Removed `Client`, use `KernelBrowser` instead
 * Removed `ContainerAwareCommand`, use dependency injection instead
 * Removed the `validation.strict_email` option, use `validation.email_validation_mode` instead
 * Removed the `cache.app.simple` service and its corresponding PSR-16 autowiring alias
 * Removed cache-related compiler passes and `RequestDataCollector`
 * Removed the `translator.selector` and `session.save_listener` services
 * Removed `SecurityUserValueResolver`, use `UserValueResolver` instead
 * Removed `routing.loader.service`.
 * Service route loaders must be tagged with `routing.route_loader`.
 * Added `slugger` service and `SluggerInterface` alias
 * Removed the `lock.store.flock`, `lock.store.semaphore`, `lock.store.memcached.abstract` and `lock.store.redis.abstract` services.
 * Removed the `router.cache_class_prefix` parameter.

4.4.0
-----

 * Added `lint:container` command to check that services wiring matches type declarations
 * Added `MailerAssertionsTrait`
 * Deprecated support for `templating` engine in `TemplateController`, use Twig instead
 * Deprecated the `$parser` argument of `ControllerResolver::__construct()` and `DelegatingLoader::__construct()`
 * Deprecated the `controller_name_converter` and `resolve_controller_name_subscriber` services
 * The `ControllerResolver` and `DelegatingLoader` classes have been marked as `final`
 * Added support for configuring chained cache pools
 * Deprecated calling `WebTestCase::createClient()` while a kernel has been booted, ensure the kernel is shut down before calling the method
 * Deprecated `routing.loader.service`, use `routing.loader.container` instead.
 * Not tagging service route loaders with `routing.route_loader` has been deprecated.
 * Overriding the methods `KernelTestCase::tearDown()` and `WebTestCase::tearDown()` without the `void` return-type is deprecated.
 * Added new `error_controller` configuration to handle system exceptions
 * Added sort option for `translation:update` command.
 * [BC Break] The `framework.messenger.routing.senders` config key is not deeply merged anymore.
 * Added `secrets:*` commands to deal with secrets seamlessly.
 * Made `framework.session.handler_id` accept a DSN
 * Marked the `RouterDataCollector` class as `@final`.
 * [BC Break] The `framework.messenger.buses.<name>.middleware` config key is not deeply merged anymore.
 * Moved `MailerAssertionsTrait` in `KernelTestCase`

4.3.0
-----

 * Deprecated the `framework.templating` option, configure the Twig bundle instead.
 * Added `WebTestAssertionsTrait` (included by default in `WebTestCase`)
 * Renamed `Client` to `KernelBrowser`
 * Not passing the project directory to the constructor of the `AssetsInstallCommand` is deprecated. This argument will
   be mandatory in 5.0.
 * Deprecated the "Psr\SimpleCache\CacheInterface" / "cache.app.simple" service, use "Symfony\Contracts\Cache\CacheInterface" / "cache.app" instead
 * Added the ability to specify a custom `serializer` option for each
   transport under`framework.messenger.transports`.
 * Added the `RegisterLocaleAwareServicesPass` and configured the `LocaleAwareListener`
 * [BC Break] When using Messenger, the default transport changed from
   using Symfony's serializer service to use `PhpSerializer`, which uses
   PHP's native `serialize()` and `unserialize()` functions. To use the
   original serialization method, set the `framework.messenger.default_serializer`
   config option to `messenger.transport.symfony_serializer`. Or set the
   `serializer` option under one specific `transport`.
 * [BC Break] The `framework.messenger.serializer` config key changed to
   `framework.messenger.default_serializer`, which holds the string service
   id and `framework.messenger.symfony_serializer`, which configures the
   options if you're using Symfony's serializer.
 * [BC Break] Removed the `framework.messenger.routing.send_and_handle` configuration.
   Instead of setting it to true, configure a `SyncTransport` and route messages to it.
 * Added information about deprecated aliases in `debug:autowiring`
 * Added php ini session options `sid_length` and `sid_bits_per_character`
   to the `session` section of the configuration
 * Added support for Translator paths, Twig paths in translation commands.
 * Added support for PHP files with translations in translation commands.
 * Added support for boolean container parameters within routes.
 * Added the `messenger:setup-transports` command to setup messenger transports
 * Added a `InMemoryTransport` to Messenger. Use it with a DSN starting with `in-memory://`.
 * Added `framework.property_access.throw_exception_on_invalid_property_path` config option.
 * Added `cache:pool:list` command to list all available cache pools.

4.2.0
-----

 * Added a `AbstractController::addLink()` method to add Link headers to the current response
 * Allowed configuring taggable cache pools via a new `framework.cache.pools.tags` option (bool|service-id)
 * Allowed configuring PDO-based cache pools via a new `cache.adapter.pdo` abstract service
 * Deprecated auto-injection of the container in AbstractController instances, register them as service subscribers instead
 * Deprecated processing of services tagged `security.expression_language_provider` in favor of a new `AddExpressionLanguageProvidersPass` in SecurityBundle.
 * Deprecated the `Symfony\Bundle\FrameworkBundle\Controller\Controller` class in favor of `Symfony\Bundle\FrameworkBundle\Controller\AbstractController`.
 * Enabled autoconfiguration for `Psr\Log\LoggerAwareInterface`
 * Added new "auto" mode for `framework.session.cookie_secure` to turn it on when HTTPS is used
 * Removed the `framework.messenger.encoder` and `framework.messenger.decoder` options. Use the `framework.messenger.serializer.id` option to replace the Messenger serializer.
 * Deprecated the `ContainerAwareCommand` class in favor of `Symfony\Component\Console\Command\Command`
 * Made `debug:container` and `debug:autowiring` ignore backslashes in service ids
 * Deprecated the `Templating\Helper\TranslatorHelper::transChoice()` method, use the `trans()` one instead with a `%count%` parameter
 * Deprecated `CacheCollectorPass`. Use `Symfony\Component\Cache\DependencyInjection\CacheCollectorPass` instead.
 * Deprecated `CachePoolClearerPass`. Use `Symfony\Component\Cache\DependencyInjection\CachePoolClearerPass` instead.
 * Deprecated `CachePoolPass`. Use `Symfony\Component\Cache\DependencyInjection\CachePoolPass` instead.
 * Deprecated `CachePoolPrunerPass`. Use `Symfony\Component\Cache\DependencyInjection\CachePoolPrunerPass` instead.
 * Deprecated support for legacy translations directories `src/Resources/translations/` and `src/Resources/<BundleName>/translations/`, use `translations/` instead.
 * Deprecated support for the legacy directory structure in `translation:update` and `debug:translation` commands.

4.1.0
-----

 * Allowed to pass an optional `LoggerInterface $logger` instance to the `Router`
 * Added a new `parameter_bag` service with related autowiring aliases to access parameters as-a-service
 * Allowed the `Router` to work with any PSR-11 container
 * Added option in workflow dump command to label graph with a custom label
 * Using a `RouterInterface` that does not implement the `WarmableInterface` is deprecated.
 * Warming up a router in `RouterCacheWarmer` that does not implement the `WarmableInterface` is deprecated and will not
   be supported anymore in 5.0.
 * The `RequestDataCollector` class has been deprecated. Use the `Symfony\Component\HttpKernel\DataCollector\RequestDataCollector` class instead.
 * The `RedirectController` class allows for 307/308 HTTP status codes
 * Deprecated `bundle:controller:action` syntax to reference controllers. Use `serviceOrFqcn::method` instead where `serviceOrFqcn`
   is either the service ID or the FQCN of the controller.
 * Deprecated `Symfony\Bundle\FrameworkBundle\Controller\ControllerNameParser`
 * The `container.service_locator` tag of `ServiceLocator`s is now autoconfigured.
 * Add the ability to search a route in `debug:router`.
 * Add the ability to use SameSite cookies for sessions.

4.0.0
-----

 * The default `type` option of the `framework.workflows.*` configuration entries is `state_machine`
 * removed `AddConsoleCommandPass`, `AddConstraintValidatorsPass`,
   `AddValidatorInitializersPass`, `CompilerDebugDumpPass`,  `ConfigCachePass`,
   `ControllerArgumentValueResolverPass`, `FormPass`, `PropertyInfoPass`,
   `RoutingResolverPass`, `SerializerPass`, `ValidateWorkflowsPass`
 * made  `Translator::__construct()` `$defaultLocale` argument required
 * removed `SessionListener`, `TestSessionListener`
 * Removed `cache:clear` warmup part along with the `--no-optional-warmers` option
 * Removed core form types services registration when unnecessary
 * Removed `framework.serializer.cache` option and `serializer.mapping.cache.apc`, `serializer.mapping.cache.doctrine.apc` services
 * Removed `ConstraintValidatorFactory`
 * Removed class parameters related to routing
 * Removed absolute template paths support in the template name parser
 * Removed support of the `KERNEL_DIR` environment variable with `KernelTestCase::getKernelClass()`.
 * Removed the `KernelTestCase::getPhpUnitXmlDir()` and `KernelTestCase::getPhpUnitCliConfigArgument()` methods.
 * Removed the "framework.validation.cache" configuration option. Configure the "cache.validator" service under "framework.cache.pools" instead.
 * Removed `PhpStringTokenParser`, use `Symfony\Component\Translation\Extractor\PhpStringTokenParser` instead.
 * Removed `PhpExtractor`, use `Symfony\Component\Translation\Extractor\PhpExtractor` instead.
 * Removed the `use_strict_mode` session option, it's is now enabled by default

3.4.0
-----

 * Added `translator.default_path` option and parameter
 * Session `use_strict_mode` is now enabled by default and the corresponding option has been deprecated
 * Made the `cache:clear` command to *not* clear "app" PSR-6 cache pools anymore,
   but to still clear "system" ones; use the `cache:pool:clear` command to clear "app" pools instead
 * Always register a minimalist logger that writes in `stderr`
 * Deprecated `profiler.matcher` option
 * Added support for `EventSubscriberInterface` on `MicroKernelTrait`
 * Removed `doctrine/cache` from the list of required dependencies in `composer.json`
 * Deprecated `validator.mapping.cache.doctrine.apc` service
 * The `symfony/stopwatch` dependency has been removed, require it via `composer
   require symfony/stopwatch` in your `dev` environment.
 * Deprecated using the `KERNEL_DIR` environment variable with `KernelTestCase::getKernelClass()`.
 * Deprecated the `KernelTestCase::getPhpUnitXmlDir()` and `KernelTestCase::getPhpUnitCliConfigArgument()` methods.
 * Deprecated `AddCacheClearerPass`, use tagged iterator arguments instead.
 * Deprecated `AddCacheWarmerPass`, use tagged iterator arguments instead.
 * Deprecated `TranslationDumperPass`, use
   `Symfony\Component\Translation\DependencyInjection\TranslationDumperPass` instead
 * Deprecated `TranslationExtractorPass`, use
   `Symfony\Component\Translation\DependencyInjection\TranslationExtractorPass` instead
 * Deprecated `TranslatorPass`, use
   `Symfony\Component\Translation\DependencyInjection\TranslatorPass` instead
 * Added `command` attribute to the `console.command` tag which takes the command
   name as value, using it makes the command lazy
 * Added `cache:pool:prune` command to allow manual stale cache item pruning of supported PSR-6 and PSR-16 cache pool
   implementations
 * Deprecated `Symfony\Bundle\FrameworkBundle\Translation\TranslationLoader`, use
   `Symfony\Component\Translation\Reader\TranslationReader` instead
 * Deprecated `translation.loader` service, use `translation.reader` instead
 * `AssetsInstallCommand::__construct()` now takes an instance of
   `Symfony\Component\Filesystem\Filesystem` as first argument
 * `CacheClearCommand::__construct()` now takes an instance of
   `Symfony\Component\HttpKernel\CacheClearer\CacheClearerInterface` as
    first argument
 * `CachePoolClearCommand::__construct()` now takes an instance of
   `Symfony\Component\HttpKernel\CacheClearer\Psr6CacheClearer` as
    first argument
 * `EventDispatcherDebugCommand::__construct()` now takes an instance of
   `Symfony\Component\EventDispatcher\EventDispatcherInterface` as
    first argument
 * `RouterDebugCommand::__construct()` now takes an instance of
   `Symfony\Component\Routing\RouterInterface` as
    first argument
 * `RouterMatchCommand::__construct()` now takes an instance of
   `Symfony\Component\Routing\RouterInterface` as
    first argument
 * `TranslationDebugCommand::__construct()` now takes an instance of
   `Symfony\Component\Translation\TranslatorInterface` as
    first argument
 * `TranslationUpdateCommand::__construct()` now takes an instance of
   `Symfony\Component\Translation\TranslatorInterface` as
    first argument
 * `AssetsInstallCommand`, `CacheClearCommand`, `CachePoolClearCommand`,
   `EventDispatcherDebugCommand`, `RouterDebugCommand`, `RouterMatchCommand`,
   `TranslationDebugCommand`, `TranslationUpdateCommand`, `XliffLintCommand`
    and `YamlLintCommand` classes have been marked as final
 * Added `asset.request_context.base_path` and `asset.request_context.secure` parameters
   to provide a default request context in case the stack is empty (similar to `router.request_context.*` parameters)
 * Display environment variables managed by `Dotenv` in `AboutCommand`

3.3.0
-----

 * Not defining the `type` option of the `framework.workflows.*` configuration entries is deprecated.
   The default value will be `state_machine` in Symfony 4.0.
 * Deprecated the `CompilerDebugDumpPass` class
 * Deprecated the "framework.trusted_proxies" configuration option and the corresponding "kernel.trusted_proxies" parameter
 * Added a new version strategy option called "json_manifest_path"
   that allows you to use the `JsonManifestVersionStrategy`.
 * Added `Symfony\Bundle\FrameworkBundle\Controller\AbstractController`. It provides
   the same helpers as the `Controller` class, but does not allow accessing the dependency
   injection container, in order to encourage explicit dependency declarations.
 * Added support for the `controller.service_arguments` tag, for injecting services into controllers' actions
 * Changed default configuration for
   assets/forms/validation/translation/serialization/csrf from `canBeEnabled()` to
   `canBeDisabled()` when Flex is used
 * The server:* commands and their associated router files were moved to WebServerBundle
 * Translation related services are not loaded anymore when the `framework.translator` option
   is disabled.
 * Added `GlobalVariables::getToken()`
 * Deprecated `Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\AddConsoleCommandPass`. Use `Symfony\Component\Console\DependencyInjection\AddConsoleCommandPass` instead.
 * Added configurable paths for validation files
 * Deprecated `SerializerPass`, use `Symfony\Component\Serializer\DependencyInjection\SerializerPass` instead
 * Deprecated `FormPass`, use `Symfony\Component\Form\DependencyInjection\FormPass` instead
 * Deprecated `SessionListener`
 * Deprecated `TestSessionListener`
 * Deprecated `Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\ConfigCachePass`.
   Use tagged iterator arguments instead.
 * Deprecated `PropertyInfoPass`, use `Symfony\Component\PropertyInfo\DependencyInjection\PropertyInfoPass` instead
 * Deprecated `ControllerArgumentValueResolverPass`. Use
   `Symfony\Component\HttpKernel\DependencyInjection\ControllerArgumentValueResolverPass` instead
 * Deprecated `RoutingResolverPass`, use `Symfony\Component\Routing\DependencyInjection\RoutingResolverPass` instead
 * [BC BREAK] The `server:run`, `server:start`, `server:stop` and
   `server:status` console commands have been moved to a dedicated bundle.
   Require `symfony/web-server-bundle` in your composer.json and register
   `Symfony\Bundle\WebServerBundle\WebServerBundle` in your AppKernel to use them.
 * Added `$defaultLocale` as 3rd argument of `Translator::__construct()`
   making `Translator` works with any PSR-11 container
 * Added `framework.serializer.mapping` config option allowing to define custom
   serialization mapping files and directories
 * Deprecated `AddValidatorInitializersPass`, use
   `Symfony\Component\Validator\DependencyInjection\AddValidatorInitializersPass` instead
 * Deprecated `AddConstraintValidatorsPass`, use
   `Symfony\Component\Validator\DependencyInjection\AddConstraintValidatorsPass` instead
 * Deprecated `ValidateWorkflowsPass`, use
   `Symfony\Component\Workflow\DependencyInjection\ValidateWorkflowsPass` instead
 * Deprecated `ConstraintValidatorFactory`, use
   `Symfony\Component\Validator\ContainerConstraintValidatorFactory` instead.
 * Deprecated `PhpStringTokenParser`, use
   `Symfony\Component\Translation\Extractor\PhpStringTokenParser` instead.
 * Deprecated `PhpExtractor`, use
   `Symfony\Component\Translation\Extractor\PhpExtractor` instead.

3.2.0
-----

 * Removed `doctrine/annotations` from the list of required dependencies in `composer.json`
 * Removed `symfony/security-core` and `symfony/security-csrf` from the list of required dependencies in `composer.json`
 * Removed `symfony/templating` from the list of required dependencies in `composer.json`
 * Removed `symfony/translation` from the list of required dependencies in `composer.json`
 * Removed `symfony/asset` from the list of required dependencies in `composer.json`
 * The `Resources/public/images/*` files have been removed.
 * The `Resources/public/css/*.css` files have been removed (they are now inlined in TwigBundle).
 * Added possibility to prioritize form type extensions with `'priority'` attribute on tags `form.type_extension`

3.1.0
-----

 * Added `Controller::json` to simplify creating JSON responses when using the Serializer component
 * Deprecated absolute template paths support in the template name parser
 * Deprecated using core form types without dependencies as services
 * Added `Symfony\Component\HttpHernel\DataCollector\RequestDataCollector::onKernelResponse()`
 * Added `Symfony\Bundle\FrameworkBundle\DataCollector\RequestDataCollector`
 * The `framework.serializer.cache` option and the service `serializer.mapping.cache.apc` have been
   deprecated. APCu should now be automatically used when available.

3.0.0
-----

 * removed `validator.api` parameter
 * removed `alias` option of the `form.type` tag

2.8.0
-----

 * Deprecated the `alias` option of the `form.type_extension` tag in favor of the
   `extended_type`/`extended-type` option
 * Deprecated the `alias` option of the `form.type` tag
 * Deprecated the Shell

2.7.0
-----

 * Added possibility to extract translation messages from a file or files besides extracting from a directory
 * Added `TranslationsCacheWarmer` to create catalogues at warmup

2.6.0
-----

 * Added helper commands (`server:start`, `server:stop` and `server:status`) to control the built-in web
   server in the background
 * Added `Controller::isCsrfTokenValid` helper
 * Added configuration for the PropertyAccess component
 * Added `Controller::redirectToRoute` helper
 * Added `Controller::addFlash` helper
 * Added `Controller::isGranted` helper
 * Added `Controller::denyAccessUnlessGranted` helper
 * Deprecated `app.security` in twig as `app.user` and `is_granted()` are already available

2.5.0
-----

 * Added `translation:debug` command
 * Added `--no-backup` option to `translation:update` command
 * Added `config:debug` command
 * Added `yaml:lint` command
 * Deprecated the `RouterApacheDumperCommand` which will be removed in Symfony 3.0.

2.4.0
-----

 * allowed multiple IP addresses in profiler matcher settings
 * added stopwatch helper to time templates with the WebProfilerBundle
 * added service definition for "security.secure_random" service
 * added service definitions for the new Security CSRF sub-component

2.3.0
-----

 * [BC BREAK] added a way to disable the profiler (when disabling the profiler, it is now completely removed)
   To get the same "disabled" behavior as before, set `enabled` to `true` and `collect` to `false`
 * [BC BREAK] the `Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\RegisterKernelListenersPass` was moved
   to `Component\HttpKernel\DependencyInjection\RegisterListenersPass`
 * added ControllerNameParser::build() which converts a controller short notation (a:b:c) to a class::method notation
 * added possibility to run PHP built-in server in production environment
 * added possibility to load the serializer component in the service container
 * added route debug information when using the `router:match` command
 * added `TimedPhpEngine`
 * added `--clean` option to the `translation:update` command
 * added `http_method_override` option
 * added support for default templates per render tag
 * added FormHelper::form(), FormHelper::start() and FormHelper::end()
 * deprecated FormHelper::enctype() in favor of FormHelper::start()
 * RedirectController actions now receive the Request instance via the method signature.

2.2.0
-----

 * added a new `uri_signer` service to help sign URIs
 * deprecated `Symfony\Bundle\FrameworkBundle\HttpKernel::render()` and `Symfony\Bundle\FrameworkBundle\HttpKernel::forward()`
 * deprecated the `Symfony\Bundle\FrameworkBundle\HttpKernel` class in favor of `Symfony\Component\HttpKernel\DependencyInjection\ContainerAwareHttpKernel`
 * added support for adding new HTTP content rendering strategies (like ESI and Hinclude)
   in the DIC via the `kernel.fragment_renderer` tag
 * [BC BREAK] restricted the `Symfony\Bundle\FrameworkBundle\HttpKernel::render()` method to only accept URIs or ControllerReference instances
   * `Symfony\Bundle\FrameworkBundle\HttpKernel::render()` method signature changed and the first argument
     must now be a URI or a ControllerReference instance (the `generateInternalUri()` method was removed)
   * The internal routes (`Resources/config/routing/internal.xml`) have been removed and replaced with a listener (`Symfony\Component\HttpKernel\EventListener\FragmentListener`)
   * The `render` method of the `actions` templating helper signature and arguments changed
 * replaced Symfony\Bundle\FrameworkBundle\Controller\TraceableControllerResolver by Symfony\Component\HttpKernel\Controller\TraceableControllerResolver
 * replaced Symfony\Component\HttpKernel\Debug\ContainerAwareTraceableEventDispatcher by Symfony\Component\HttpKernel\Debug\TraceableEventDispatcher
 * added Client::enableProfiler()
 * a new parameter has been added to the DIC: `router.request_context.base_url`
   You can customize it for your functional tests or for generating URLs with
   the right base URL when your are in the CLI context.
 * added support for default templates per render tag

2.1.0
-----

 * moved the translation files to the Form and Validator components
 * changed the default extension for XLIFF files from .xliff to .xlf
 * moved Symfony\Bundle\FrameworkBundle\ContainerAwareEventDispatcher to Symfony\Component\EventDispatcher\ContainerAwareEventDispatcher
 * moved Symfony\Bundle\FrameworkBundle\Debug\TraceableEventDispatcher to Symfony\Component\EventDispatcher\ContainerAwareTraceableEventDispatcher
 * added a router:match command
 * added a config:dump-reference command
 * added a server:run command
 * added kernel.event_subscriber tag
 * added a way to create relative symlinks when running assets:install command (--relative option)
 * added Controller::getUser()
 * [BC BREAK] assets_base_urls and base_urls merging strategy has changed
 * changed the default profiler storage to use the filesystem instead of SQLite
 * added support for placeholders in route defaults and requirements (replaced
   by the value set in the service container)
 * added Filesystem component as a dependency
 * added support for hinclude (use ``standalone: 'js'`` in render tag)
 * session options: lifetime, path, domain, secure, httponly were deprecated.
   Prefixed versions should now be used instead: cookie_lifetime, cookie_path,
   cookie_domain, cookie_secure, cookie_httponly
 * [BC BREAK] following session options: 'lifetime', 'path', 'domain', 'secure',
   'httponly' are now prefixed with cookie_ when dumped to the container
 * Added `handler_id` configuration under `session` key to represent `session.handler`
   service, defaults to `session.handler.native_file`.
 * Added `gc_maxlifetime`, `gc_probability`, and `gc_divisor` to session
   configuration. This means session garbage collection has a
  `gc_probability`/`gc_divisor` chance of being run. The `gc_maxlifetime` defines
   how long a session can idle for. It is different from cookie lifetime which
   declares how long a cookie can be stored on the remote client.
 * Removed 'auto_start' configuration parameter from session config. The session will
   start on demand.
 * [BC BREAK] TemplateNameParser::parseFromFilename() has been moved to a dedicated
   parser: TemplateFilenameParser::parse().
 * [BC BREAK] Kernel parameters are replaced by their value wherever they appear
   in Route patterns, requirements and defaults. Use '%%' as the escaped value for '%'.
 * [BC BREAK] Switched behavior of flash messages to expire flash messages on retrieval
   using Symfony\Component\HttpFoundation\Session\Flash\FlashBag as opposed to on
   next pageload regardless of whether they are displayed or not.
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Bundle\FrameworkBundle\Translation;

use _ContaoManager\Psr\Container\ContainerInterface;
use _ContaoManager\Symfony\Component\Config\Resource\DirectoryResource;
use _ContaoManager\Symfony\Component\Config\Resource\FileExistenceResource;
use _ContaoManager\Symfony\Component\HttpKernel\CacheWarmer\WarmableInterface;
use _ContaoManager\Symfony\Component\Translation\Exception\InvalidArgumentException;
use _ContaoManager\Symfony\Component\Translation\Formatter\MessageFormatterInterface;
use _ContaoManager\Symfony\Component\Translation\Translator as BaseTranslator;
/**
 * @author Fabien Potencier <fabien@symfony.com>
 */
class Translator extends BaseTranslator implements WarmableInterface
{
    protected $container;
    protected $loaderIds;
    protected $options = ['cache_dir' => null, 'debug' => \false, 'resource_files' => [], 'scanned_directories' => [], 'cache_vary' => []];
    /**
     * @var list<string>
     */
    private array $resourceLocales;
    /**
     * Holds parameters from addResource() calls so we can defer the actual
     * parent::addResource() calls until initialize() is executed.
     *
     * @var array[]
     */
    private array $resources = [];
    /**
     * @var string[][]
     */
    private array $resourceFiles;
    /**
     * @var string[]
     */
    private array $scannedDirectories;
    /**
     * @var string[]
     */
    private array $enabledLocales;
    /**
     * Constructor.
     *
     * Available options:
     *
     *   * cache_dir:      The cache directory (or null to disable caching)
     *   * debug:          Whether to enable debugging or not (false by default)
     *   * resource_files: List of translation resources available grouped by locale.
     *   * cache_vary:     An array of data that is serialized to generate the cached catalogue name.
     *
     * @throws InvalidArgumentException
     */
    public function __construct(ContainerInterface $container, MessageFormatterInterface $formatter, string $defaultLocale, array $loaderIds = [], array $options = [], array $enabledLocales = [])
    {
        $this->container = $container;
        $this->loaderIds = $loaderIds;
        $this->enabledLocales = $enabledLocales;
        // check option names
        if ($diff = array_diff(array_keys($options), array_keys($this->options))) {
            throw new InvalidArgumentException(\sprintf('The Translator does not support the following options: \'%s\'.', implode('\', \'', $diff)));
        }
        $this->options = array_merge($this->options, $options);
        $this->resourceLocales = array_keys($this->options['resource_files']);
        $this->resourceFiles = $this->options['resource_files'];
        $this->scannedDirectories = $this->options['scanned_directories'];
        parent::__construct($defaultLocale, $formatter, $this->options['cache_dir'], $this->options['debug'], $this->options['cache_vary']);
    }
    /**
     * @param string|null $buildDir
     */
    public function warmUp(string $cacheDir): array
    {
        // skip warmUp when translator doesn't use cache
        if (null === $this->options['cache_dir']) {
            return [];
        }
        $localesToWarmUp = $this->enabledLocales ?: array_merge($this->getFallbackLocales(), [$this->getLocale()], $this->resourceLocales);
        foreach (array_unique($localesToWarmUp) as $locale) {
            // reset catalogue in case it's already loaded during the dump of the other locales.
            if (isset($this->catalogues[$locale])) {
                unset($this->catalogues[$locale]);
            }
            $this->loadCatalogue($locale);
        }
        return [];
    }
    public function addResource(string $format, mixed $resource, string $locale, ?string $domain = null): void
    {
        if ($this->resourceFiles) {
            $this->addResourceFiles();
        }
        $this->resources[] = [$format, $resource, $locale, $domain];
    }
    protected function initializeCatalogue(string $locale): void
    {
        $this->initialize();
        parent::initializeCatalogue($locale);
    }
    /**
     * @internal
     */
    protected function doLoadCatalogue(string $locale): void
    {
        parent::doLoadCatalogue($locale);
        foreach ($this->scannedDirectories as $directory) {
            $resourceClass = file_exists($directory) ? DirectoryResource::class : FileExistenceResource::class;
            $this->catalogues[$locale]->addResource(new $resourceClass($directory));
        }
    }
    /**
     * @return void
     */
    protected function initialize()
    {
        if ($this->resourceFiles) {
            $this->addResourceFiles();
        }
        foreach ($this->resources as $params) {
            [$format, $resource, $locale, $domain] = $params;
            parent::addResource($format, $resource, $locale, $domain);
        }
        $this->resources = [];
        foreach ($this->loaderIds as $id => $aliases) {
            foreach ($aliases as $alias) {
                $this->addLoader($alias, $this->container->get($id));
            }
        }
    }
    private function addResourceFiles(): void
    {
        $filesByLocale = $this->resourceFiles;
        $this->resourceFiles = [];
        foreach ($filesByLocale as $files) {
            foreach ($files as $file) {
                // filename is domain.locale.format
                $fileNameParts = explode('.', basename($file));
                $format = array_pop($fileNameParts);
                $locale = array_pop($fileNameParts);
                $domain = implode('.', $fileNameParts);
                $this->addResource($format, $file, $locale, $domain);
            }
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Bundle\FrameworkBundle\Secrets;

use _ContaoManager\Symfony\Component\DependencyInjection\EnvVarLoaderInterface;
use _ContaoManager\Symfony\Component\String\LazyString;
use _ContaoManager\Symfony\Component\VarExporter\VarExporter;
/**
 * @author Tobias Schultze <http://tobion.de>
 * @author Jérémy Derussé <jeremy@derusse.com>
 * @author Nicolas Grekas <p@tchwork.com>
 */
class SodiumVault extends AbstractVault implements EnvVarLoaderInterface
{
    private ?string $encryptionKey = null;
    private string|\Stringable|null $decryptionKey = null;
    private string $pathPrefix;
    private ?string $secretsDir;
    /**
     * @param $decryptionKey A string or a stringable object that defines the private key to use to decrypt the vault
     *                       or null to store generated keys in the provided $secretsDir
     */
    public function __construct(
        string $secretsDir,
        #[\SensitiveParameter]
        string|\Stringable|null $decryptionKey = null
    )
    {
        $this->pathPrefix = rtrim(strtr($secretsDir, '/', \DIRECTORY_SEPARATOR), \DIRECTORY_SEPARATOR) . \DIRECTORY_SEPARATOR . basename($secretsDir) . '.';
        $this->decryptionKey = $decryptionKey;
        $this->secretsDir = $secretsDir;
    }
    public function generateKeys(bool $override = \false): bool
    {
        $this->lastMessage = null;
        if (null === $this->encryptionKey && '' !== $this->decryptionKey = (string) $this->decryptionKey) {
            $this->lastMessage = 'Cannot generate keys when a decryption key has been provided while instantiating the vault.';
            return \false;
        }
        try {
            $this->loadKeys();
        } catch (\RuntimeException) {
            // ignore failures to load keys
        }
        if ('' !== $this->decryptionKey && !is_file($this->pathPrefix . 'encrypt.public.php')) {
            $this->export('encrypt.public', $this->encryptionKey);
        }
        if (!$override && null !== $this->encryptionKey) {
            $this->lastMessage = \sprintf('Sodium keys already exist at "%s*.{public,private}" and won\'t be overridden.', $this->getPrettyPath($this->pathPrefix));
            return \false;
        }
        $this->decryptionKey = sodium_crypto_box_keypair();
        $this->encryptionKey = sodium_crypto_box_publickey($this->decryptionKey);
        $this->export('encrypt.public', $this->encryptionKey);
        $this->export('decrypt.private', $this->decryptionKey);
        $this->lastMessage = \sprintf('Sodium keys have been generated at "%s*.public/private.php".', $this->getPrettyPath($this->pathPrefix));
        return \true;
    }
    public function seal(string $name, string $value): void
    {
        $this->lastMessage = null;
        $this->validateName($name);
        $this->loadKeys();
        $filename = $this->getFilename($name);
        $this->export($filename, sodium_crypto_box_seal($value, $this->encryptionKey ?? sodium_crypto_box_publickey($this->decryptionKey)));
        $list = $this->list();
        $list[$name] = null;
        uksort($list, 'strnatcmp');
        file_put_contents($this->pathPrefix . 'list.php', \sprintf("<?php\n\nreturn %s;\n", VarExporter::export($list)), \LOCK_EX);
        $this->lastMessage = \sprintf('Secret "%s" encrypted in "%s"; you can commit it.', $name, $this->getPrettyPath(\dirname($this->pathPrefix) . \DIRECTORY_SEPARATOR));
    }
    public function reveal(string $name): ?string
    {
        $this->lastMessage = null;
        $this->validateName($name);
        $filename = $this->getFilename($name);
        if (!is_file($file = $this->pathPrefix . $filename . '.php')) {
            $this->lastMessage = \sprintf('Secret "%s" not found in "%s".', $name, $this->getPrettyPath(\dirname($this->pathPrefix) . \DIRECTORY_SEPARATOR));
            return null;
        }
        if (!\function_exists('sodium_crypto_box_seal') && !\function_exists('_ContaoManager\sodium_crypto_box_seal')) {
            $this->lastMessage = \sprintf('Secret "%s" cannot be revealed as the "sodium" PHP extension missing. Try running "composer require paragonie/sodium_compat" if you cannot enable the extension."', $name);
            return null;
        }
        $this->loadKeys();
        if ('' === $this->decryptionKey) {
            $this->lastMessage = \sprintf('Secret "%s" cannot be revealed as no decryption key was found in "%s".', $name, $this->getPrettyPath(\dirname($this->pathPrefix) . \DIRECTORY_SEPARATOR));
            return null;
        }
        if (\false === $value = sodium_crypto_box_seal_open(include $file, $this->decryptionKey)) {
            $this->lastMessage = \sprintf('Secret "%s" cannot be revealed as the wrong decryption key was provided for "%s".', $name, $this->getPrettyPath(\dirname($this->pathPrefix) . \DIRECTORY_SEPARATOR));
            return null;
        }
        return $value;
    }
    public function remove(string $name): bool
    {
        $this->lastMessage = null;
        $this->validateName($name);
        $filename = $this->getFilename($name);
        if (!is_file($file = $this->pathPrefix . $filename . '.php')) {
            $this->lastMessage = \sprintf('Secret "%s" not found in "%s".', $name, $this->getPrettyPath(\dirname($this->pathPrefix) . \DIRECTORY_SEPARATOR));
            return \false;
        }
        $list = $this->list();
        unset($list[$name]);
        file_put_contents($this->pathPrefix . 'list.php', \sprintf("<?php\n\nreturn %s;\n", VarExporter::export($list)), \LOCK_EX);
        $this->lastMessage = \sprintf('Secret "%s" removed from "%s".', $name, $this->getPrettyPath(\dirname($this->pathPrefix) . \DIRECTORY_SEPARATOR));
        return @unlink($file) || !file_exists($file);
    }
    public function list(bool $reveal = \false): array
    {
        $this->lastMessage = null;
        if (!is_file($file = $this->pathPrefix . 'list.php')) {
            return [];
        }
        $secrets = include $file;
        if (!$reveal) {
            return $secrets;
        }
        foreach ($secrets as $name => $value) {
            $secrets[$name] = $this->reveal($name);
        }
        return $secrets;
    }
    public function loadEnvVars(): array
    {
        $envs = [];
        $reveal = $this->reveal(...);
        foreach ($this->list() as $name => $value) {
            $envs[$name] = LazyString::fromCallable($reveal, $name);
        }
        return $envs;
    }
    private function loadKeys(): void
    {
        if (!\function_exists('sodium_crypto_box_seal') && !\function_exists('_ContaoManager\sodium_crypto_box_seal')) {
            throw new \LogicException('The "sodium" PHP extension is required to deal with secrets. Alternatively, try running "composer require paragonie/sodium_compat" if you cannot enable the extension.".');
        }
        if (null !== $this->encryptionKey || '' !== $this->decryptionKey = (string) $this->decryptionKey) {
            return;
        }
        if (is_file($this->pathPrefix . 'decrypt.private.php')) {
            $this->decryptionKey = (string) include $this->pathPrefix . 'decrypt.private.php';
        }
        if (is_file($this->pathPrefix . 'encrypt.public.php')) {
            $this->encryptionKey = (string) include $this->pathPrefix . 'encrypt.public.php';
        } elseif ('' !== $this->decryptionKey) {
            $this->encryptionKey = sodium_crypto_box_publickey($this->decryptionKey);
        } else {
            throw new \RuntimeException(\sprintf('Encryption key not found in "%s".', \dirname($this->pathPrefix)));
        }
    }
    private function export(string $filename, string $data): void
    {
        $b64 = 'decrypt.private' === $filename ? '// SYMFONY_DECRYPTION_SECRET=' . base64_encode($data) . "\n" : '';
        $name = basename($this->pathPrefix . $filename);
        $data = str_replace('%', '\x', rawurlencode($data));
        $data = \sprintf("<?php // %s on %s\n\n%sreturn \"%s\";\n", $name, date('r'), $b64, $data);
        $this->createSecretsDir();
        if (\false === file_put_contents($this->pathPrefix . $filename . '.php', $data, \LOCK_EX)) {
            $e = error_get_last();
            throw new \ErrorException($e['message'] ?? 'Failed to write secrets data.', 0, $e['type'] ?? \E_USER_WARNING);
        }
    }
    private function createSecretsDir(): void
    {
        if ($this->secretsDir && !is_dir($this->secretsDir) && !@mkdir($this->secretsDir, 0777, \true) && !is_dir($this->secretsDir)) {
            throw new \RuntimeException(\sprintf('Unable to create the secrets directory (%s).', $this->secretsDir));
        }
        $this->secretsDir = null;
    }
    private function getFilename(string $name): string
    {
        // The MD5 hash allows making secrets case-sensitive. The filename is not enough on Windows.
        return $name . '.' . substr(md5($name), 0, 6);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Bundle\FrameworkBundle\Secrets;

/**
 * @author Nicolas Grekas <p@tchwork.com>
 */
class DotenvVault extends AbstractVault
{
    private string $dotenvFile;
    public function __construct(string $dotenvFile)
    {
        $this->dotenvFile = strtr($dotenvFile, '/', \DIRECTORY_SEPARATOR);
    }
    public function generateKeys(bool $override = \false): bool
    {
        $this->lastMessage = 'The dotenv vault doesn\'t encrypt secrets thus doesn\'t need keys.';
        return \false;
    }
    public function seal(string $name, string $value): void
    {
        $this->lastMessage = null;
        $this->validateName($name);
        $v = str_replace("'", "'\\''", $value);
        $content = is_file($this->dotenvFile) ? file_get_contents($this->dotenvFile) : '';
        $content = preg_replace("/^{$name}=((\\\\'|'[^']++')++|.*)/m", "{$name}='{$v}'", $content, -1, $count);
        if (!$count) {
            $content .= "{$name}='{$v}'\n";
        }
        file_put_contents($this->dotenvFile, $content);
        $this->lastMessage = \sprintf('Secret "%s" %s in "%s".', $name, $count ? 'added' : 'updated', $this->getPrettyPath($this->dotenvFile));
    }
    public function reveal(string $name): ?string
    {
        $this->lastMessage = null;
        $this->validateName($name);
        $v = $_ENV[$name] ?? (str_starts_with($name, 'HTTP_') ? null : $_SERVER[$name] ?? null);
        if ('' === ($v ?? '')) {
            $this->lastMessage = \sprintf('Secret "%s" not found in "%s".', $name, $this->getPrettyPath($this->dotenvFile));
            return null;
        }
        return $v;
    }
    public function remove(string $name): bool
    {
        $this->lastMessage = null;
        $this->validateName($name);
        $content = is_file($this->dotenvFile) ? file_get_contents($this->dotenvFile) : '';
        $content = preg_replace("/^{$name}=((\\\\'|'[^']++')++|.*)\n?/m", '', $content, -1, $count);
        if ($count) {
            file_put_contents($this->dotenvFile, $content);
            $this->lastMessage = \sprintf('Secret "%s" removed from file "%s".', $name, $this->getPrettyPath($this->dotenvFile));
            return \true;
        }
        $this->lastMessage = \sprintf('Secret "%s" not found in "%s".', $name, $this->getPrettyPath($this->dotenvFile));
        return \false;
    }
    public function list(bool $reveal = \false): array
    {
        $this->lastMessage = null;
        $secrets = [];
        foreach ($_ENV as $k => $v) {
            if ('' !== ($v ?? '') && preg_match('/^\w+$/D', $k)) {
                $secrets[$k] = $reveal ? $v : null;
            }
        }
        foreach ($_SERVER as $k => $v) {
            if ('' !== ($v ?? '') && preg_match('/^\w+$/D', $k)) {
                $secrets[$k] = $reveal ? $v : null;
            }
        }
        return $secrets;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Bundle\FrameworkBundle\Secrets;

/**
 * @author Nicolas Grekas <p@tchwork.com>
 */
abstract class AbstractVault
{
    protected $lastMessage;
    public function getLastMessage(): ?string
    {
        return $this->lastMessage;
    }
    abstract public function generateKeys(bool $override = \false): bool;
    abstract public function seal(string $name, string $value): void;
    abstract public function reveal(string $name): ?string;
    abstract public function remove(string $name): bool;
    abstract public function list(bool $reveal = \false): array;
    protected function validateName(string $name): void
    {
        if (!preg_match('/^\w++$/D', $name)) {
            throw new \LogicException(\sprintf('Invalid secret name "%s": only "word" characters are allowed.', $name));
        }
    }
    /**
     * @return string
     */
    protected function getPrettyPath(string $path)
    {
        return str_replace(getcwd() . \DIRECTORY_SEPARATOR, '', $path);
    }
}
<?php

namespace _ContaoManager;

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
if ('cli' !== \PHP_SAPI) {
    throw new \Exception('This script must be run from the command line.');
}
require \dirname(__DIR__, 6) . '/vendor/autoload.php';
use _ContaoManager\Symfony\Bundle\FrameworkBundle\Tests\DependencyInjection\Compiler\UnusedTagsPassUtils;
$target = \dirname(__DIR__, 2) . '/DependencyInjection/Compiler/UnusedTagsPass.php';
$contents = \file_get_contents($target);
$contents = \preg_replace('{private const KNOWN_TAGS = \[(.+?)\];}sm', "private const KNOWN_TAGS = [\n        '" . \implode("',\n        '", UnusedTagsPassUtils::getDefinedTags()) . "',\n    ];", $contents);
\file_put_contents($target, $contents);
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\DependencyInjection\Loader\Configurator;

use _ContaoManager\Symfony\Component\AssetMapper\AssetMapper;
use _ContaoManager\Symfony\Component\AssetMapper\AssetMapperCompiler;
use _ContaoManager\Symfony\Component\AssetMapper\AssetMapperDevServerSubscriber;
use _ContaoManager\Symfony\Component\AssetMapper\AssetMapperInterface;
use _ContaoManager\Symfony\Component\AssetMapper\AssetMapperRepository;
use _ContaoManager\Symfony\Component\AssetMapper\Command\AssetMapperCompileCommand;
use _ContaoManager\Symfony\Component\AssetMapper\Command\DebugAssetMapperCommand;
use _ContaoManager\Symfony\Component\AssetMapper\Command\ImportMapAuditCommand;
use _ContaoManager\Symfony\Component\AssetMapper\Command\ImportMapInstallCommand;
use _ContaoManager\Symfony\Component\AssetMapper\Command\ImportMapOutdatedCommand;
use _ContaoManager\Symfony\Component\AssetMapper\Command\ImportMapRemoveCommand;
use _ContaoManager\Symfony\Component\AssetMapper\Command\ImportMapRequireCommand;
use _ContaoManager\Symfony\Component\AssetMapper\Command\ImportMapUpdateCommand;
use _ContaoManager\Symfony\Component\AssetMapper\CompiledAssetMapperConfigReader;
use _ContaoManager\Symfony\Component\AssetMapper\Compiler\CssAssetUrlCompiler;
use _ContaoManager\Symfony\Component\AssetMapper\Compiler\JavaScriptImportPathCompiler;
use _ContaoManager\Symfony\Component\AssetMapper\Compiler\SourceMappingUrlsCompiler;
use _ContaoManager\Symfony\Component\AssetMapper\Factory\CachedMappedAssetFactory;
use _ContaoManager\Symfony\Component\AssetMapper\Factory\MappedAssetFactory;
use _ContaoManager\Symfony\Component\AssetMapper\ImportMap\ImportMapAuditor;
use _ContaoManager\Symfony\Component\AssetMapper\ImportMap\ImportMapConfigReader;
use _ContaoManager\Symfony\Component\AssetMapper\ImportMap\ImportMapGenerator;
use _ContaoManager\Symfony\Component\AssetMapper\ImportMap\ImportMapManager;
use _ContaoManager\Symfony\Component\AssetMapper\ImportMap\ImportMapRenderer;
use _ContaoManager\Symfony\Component\AssetMapper\ImportMap\ImportMapUpdateChecker;
use _ContaoManager\Symfony\Component\AssetMapper\ImportMap\ImportMapVersionChecker;
use _ContaoManager\Symfony\Component\AssetMapper\ImportMap\RemotePackageDownloader;
use _ContaoManager\Symfony\Component\AssetMapper\ImportMap\RemotePackageStorage;
use _ContaoManager\Symfony\Component\AssetMapper\ImportMap\Resolver\JsDelivrEsmResolver;
use _ContaoManager\Symfony\Component\AssetMapper\MapperAwareAssetPackage;
use _ContaoManager\Symfony\Component\AssetMapper\Path\LocalPublicAssetsFilesystem;
use _ContaoManager\Symfony\Component\AssetMapper\Path\PublicAssetsPathResolver;
return static function (ContainerConfigurator $container) {
    $container->services()->set('asset_mapper', AssetMapper::class)->args([service('asset_mapper.repository'), service('asset_mapper.mapped_asset_factory'), service('asset_mapper.compiled_asset_mapper_config_reader')])->alias(AssetMapperInterface::class, 'asset_mapper')->alias('asset_mapper.http_client', 'http_client')->set('asset_mapper.mapped_asset_factory', MappedAssetFactory::class)->args([service('asset_mapper.public_assets_path_resolver'), service('asset_mapper_compiler'), abstract_arg('vendor directory')])->set('asset_mapper.cached_mapped_asset_factory', CachedMappedAssetFactory::class)->args([service('.inner'), param('kernel.cache_dir') . '/asset_mapper', param('kernel.debug')])->decorate('asset_mapper.mapped_asset_factory')->set('asset_mapper.repository', AssetMapperRepository::class)->args([abstract_arg('array of asset mapper paths'), param('kernel.project_dir'), abstract_arg('array of excluded path patterns'), abstract_arg('exclude dot files'), param('kernel.debug')])->set('asset_mapper.public_assets_path_resolver', PublicAssetsPathResolver::class)->args([abstract_arg('asset public prefix')])->set('asset_mapper.local_public_assets_filesystem', LocalPublicAssetsFilesystem::class)->args([abstract_arg('public directory')])->set('asset_mapper.compiled_asset_mapper_config_reader', CompiledAssetMapperConfigReader::class)->args([abstract_arg('public assets directory')])->set('asset_mapper.asset_package', MapperAwareAssetPackage::class)->decorate('assets._default_package')->args([service('.inner'), service('asset_mapper')])->set('asset_mapper.dev_server_subscriber', AssetMapperDevServerSubscriber::class)->args([service('asset_mapper'), abstract_arg('asset public prefix'), abstract_arg('extensions map'), service('cache.asset_mapper'), service('profiler')->nullOnInvalid()])->tag('kernel.event_subscriber')->set('asset_mapper.command.compile', AssetMapperCompileCommand::class)->args([service('asset_mapper.compiled_asset_mapper_config_reader'), service('asset_mapper'), service('asset_mapper.importmap.generator'), service('asset_mapper.local_public_assets_filesystem'), param('kernel.project_dir'), param('kernel.debug'), service('event_dispatcher')->nullOnInvalid()])->tag('console.command')->set('asset_mapper.command.debug', DebugAssetMapperCommand::class)->args([service('asset_mapper'), service('asset_mapper.repository'), param('kernel.project_dir')])->tag('console.command')->set('asset_mapper_compiler', AssetMapperCompiler::class)->args([tagged_iterator('asset_mapper.compiler'), service_closure('asset_mapper')])->set('asset_mapper.compiler.css_asset_url_compiler', CssAssetUrlCompiler::class)->args([abstract_arg('missing import mode'), service('logger')])->tag('asset_mapper.compiler')->tag('monolog.logger', ['channel' => 'asset_mapper'])->set('asset_mapper.compiler.source_mapping_urls_compiler', SourceMappingUrlsCompiler::class)->tag('asset_mapper.compiler')->set('asset_mapper.compiler.javascript_import_path_compiler', JavaScriptImportPathCompiler::class)->args([service('asset_mapper.importmap.config_reader'), abstract_arg('missing import mode'), service('logger')])->tag('asset_mapper.compiler')->tag('monolog.logger', ['channel' => 'asset_mapper'])->set('asset_mapper.importmap.config_reader', ImportMapConfigReader::class)->args([abstract_arg('importmap.php path'), service('asset_mapper.importmap.remote_package_storage')])->set('asset_mapper.importmap.manager', ImportMapManager::class)->args([service('asset_mapper'), service('asset_mapper.importmap.config_reader'), service('asset_mapper.importmap.remote_package_downloader'), service('asset_mapper.importmap.resolver')])->alias(ImportMapManager::class, 'asset_mapper.importmap.manager')->set('asset_mapper.importmap.generator', ImportMapGenerator::class)->args([service('asset_mapper'), service('asset_mapper.compiled_asset_mapper_config_reader'), service('asset_mapper.importmap.config_reader')])->set('asset_mapper.importmap.remote_package_storage', RemotePackageStorage::class)->args([abstract_arg('vendor directory')])->set('asset_mapper.importmap.remote_package_downloader', RemotePackageDownloader::class)->args([service('asset_mapper.importmap.remote_package_storage'), service('asset_mapper.importmap.config_reader'), service('asset_mapper.importmap.resolver')])->set('asset_mapper.importmap.version_checker', ImportMapVersionChecker::class)->args([service('asset_mapper.importmap.config_reader'), service('asset_mapper.importmap.remote_package_downloader')])->set('asset_mapper.importmap.resolver', JsDelivrEsmResolver::class)->args([service('asset_mapper.http_client')])->set('asset_mapper.importmap.renderer', ImportMapRenderer::class)->args([service('asset_mapper.importmap.generator'), service('assets.packages')->nullOnInvalid(), param('kernel.charset'), abstract_arg('polyfill URL'), abstract_arg('script HTML attributes'), service('request_stack')])->set('asset_mapper.importmap.auditor', ImportMapAuditor::class)->args([service('asset_mapper.importmap.config_reader'), service('asset_mapper.http_client')])->set('asset_mapper.importmap.update_checker', ImportMapUpdateChecker::class)->args([service('asset_mapper.importmap.config_reader'), service('asset_mapper.http_client')])->set('asset_mapper.importmap.command.require', ImportMapRequireCommand::class)->args([service('asset_mapper.importmap.manager'), service('asset_mapper.importmap.version_checker')])->tag('console.command')->set('asset_mapper.importmap.command.remove', ImportMapRemoveCommand::class)->args([service('asset_mapper.importmap.manager')])->tag('console.command')->set('asset_mapper.importmap.command.update', ImportMapUpdateCommand::class)->args([service('asset_mapper.importmap.manager'), service('asset_mapper.importmap.version_checker')])->tag('console.command')->set('asset_mapper.importmap.command.install', ImportMapInstallCommand::class)->args([service('asset_mapper.importmap.remote_package_downloader'), param('kernel.project_dir')])->tag('console.command')->set('asset_mapper.importmap.command.audit', ImportMapAuditCommand::class)->args([service('asset_mapper.importmap.auditor')])->tag('console.command')->set('asset_mapper.importmap.command.outdated', ImportMapOutdatedCommand::class)->args([service('asset_mapper.importmap.update_checker')])->tag('console.command');
};
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\DependencyInjection\Loader\Configurator;

use _ContaoManager\Symfony\Component\HttpKernel\EventListener\SurrogateListener;
use _ContaoManager\Symfony\Component\HttpKernel\HttpCache\Esi;
return static function (ContainerConfigurator $container) {
    $container->services()->set('esi', Esi::class)->set('esi_listener', SurrogateListener::class)->args([service('esi')->ignoreOnInvalid()])->tag('kernel.event_subscriber');
};
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\DependencyInjection\Loader\Configurator;

use _ContaoManager\Psr\Container\ContainerInterface;
use _ContaoManager\Symfony\Bundle\FrameworkBundle\CacheWarmer\TranslationsCacheWarmer;
use _ContaoManager\Symfony\Bundle\FrameworkBundle\Translation\Translator;
use _ContaoManager\Symfony\Component\Translation\Dumper\CsvFileDumper;
use _ContaoManager\Symfony\Component\Translation\Dumper\IcuResFileDumper;
use _ContaoManager\Symfony\Component\Translation\Dumper\IniFileDumper;
use _ContaoManager\Symfony\Component\Translation\Dumper\JsonFileDumper;
use _ContaoManager\Symfony\Component\Translation\Dumper\MoFileDumper;
use _ContaoManager\Symfony\Component\Translation\Dumper\PhpFileDumper;
use _ContaoManager\Symfony\Component\Translation\Dumper\PoFileDumper;
use _ContaoManager\Symfony\Component\Translation\Dumper\QtFileDumper;
use _ContaoManager\Symfony\Component\Translation\Dumper\XliffFileDumper;
use _ContaoManager\Symfony\Component\Translation\Dumper\YamlFileDumper;
use _ContaoManager\Symfony\Component\Translation\Extractor\ChainExtractor;
use _ContaoManager\Symfony\Component\Translation\Extractor\ExtractorInterface;
use _ContaoManager\Symfony\Component\Translation\Extractor\PhpAstExtractor;
use _ContaoManager\Symfony\Component\Translation\Extractor\PhpExtractor;
use _ContaoManager\Symfony\Component\Translation\Extractor\Visitor\ConstraintVisitor;
use _ContaoManager\Symfony\Component\Translation\Extractor\Visitor\TranslatableMessageVisitor;
use _ContaoManager\Symfony\Component\Translation\Extractor\Visitor\TransMethodVisitor;
use _ContaoManager\Symfony\Component\Translation\Formatter\MessageFormatter;
use _ContaoManager\Symfony\Component\Translation\Loader\CsvFileLoader;
use _ContaoManager\Symfony\Component\Translation\Loader\IcuDatFileLoader;
use _ContaoManager\Symfony\Component\Translation\Loader\IcuResFileLoader;
use _ContaoManager\Symfony\Component\Translation\Loader\IniFileLoader;
use _ContaoManager\Symfony\Component\Translation\Loader\JsonFileLoader;
use _ContaoManager\Symfony\Component\Translation\Loader\MoFileLoader;
use _ContaoManager\Symfony\Component\Translation\Loader\PhpFileLoader;
use _ContaoManager\Symfony\Component\Translation\Loader\PoFileLoader;
use _ContaoManager\Symfony\Component\Translation\Loader\QtFileLoader;
use _ContaoManager\Symfony\Component\Translation\Loader\XliffFileLoader;
use _ContaoManager\Symfony\Component\Translation\Loader\YamlFileLoader;
use _ContaoManager\Symfony\Component\Translation\LocaleSwitcher;
use _ContaoManager\Symfony\Component\Translation\LoggingTranslator;
use _ContaoManager\Symfony\Component\Translation\Reader\TranslationReader;
use _ContaoManager\Symfony\Component\Translation\Reader\TranslationReaderInterface;
use _ContaoManager\Symfony\Component\Translation\Writer\TranslationWriter;
use _ContaoManager\Symfony\Component\Translation\Writer\TranslationWriterInterface;
use _ContaoManager\Symfony\Contracts\Translation\LocaleAwareInterface;
use _ContaoManager\Symfony\Contracts\Translation\TranslatorInterface;
return static function (ContainerConfigurator $container) {
    $container->services()->set('translator.default', Translator::class)->args([abstract_arg('translation loaders locator'), service('translator.formatter'), param('kernel.default_locale'), abstract_arg('translation loaders ids'), ['cache_dir' => param('kernel.cache_dir') . '/translations', 'debug' => param('kernel.debug')], abstract_arg('enabled locales')])->call('setConfigCacheFactory', [service('config_cache_factory')])->tag('kernel.locale_aware')->alias(TranslatorInterface::class, 'translator')->set('translator.logging', LoggingTranslator::class)->args([service('translator.logging.inner'), service('logger')])->tag('monolog.logger', ['channel' => 'translation'])->set('translator.formatter.default', MessageFormatter::class)->args([service('identity_translator')])->set('translation.loader.php', PhpFileLoader::class)->tag('translation.loader', ['alias' => 'php'])->set('translation.loader.yml', YamlFileLoader::class)->tag('translation.loader', ['alias' => 'yaml', 'legacy-alias' => 'yml'])->set('translation.loader.xliff', XliffFileLoader::class)->tag('translation.loader', ['alias' => 'xlf', 'legacy-alias' => 'xliff'])->set('translation.loader.po', PoFileLoader::class)->tag('translation.loader', ['alias' => 'po'])->set('translation.loader.mo', MoFileLoader::class)->tag('translation.loader', ['alias' => 'mo'])->set('translation.loader.qt', QtFileLoader::class)->tag('translation.loader', ['alias' => 'ts'])->set('translation.loader.csv', CsvFileLoader::class)->tag('translation.loader', ['alias' => 'csv'])->set('translation.loader.res', IcuResFileLoader::class)->tag('translation.loader', ['alias' => 'res'])->set('translation.loader.dat', IcuDatFileLoader::class)->tag('translation.loader', ['alias' => 'dat'])->set('translation.loader.ini', IniFileLoader::class)->tag('translation.loader', ['alias' => 'ini'])->set('translation.loader.json', JsonFileLoader::class)->tag('translation.loader', ['alias' => 'json'])->set('translation.dumper.php', PhpFileDumper::class)->tag('translation.dumper', ['alias' => 'php'])->set('translation.dumper.xliff', XliffFileDumper::class)->tag('translation.dumper', ['alias' => 'xlf'])->set('translation.dumper.xliff.xliff', XliffFileDumper::class)->args(['xliff'])->tag('translation.dumper', ['alias' => 'xliff'])->set('translation.dumper.po', PoFileDumper::class)->tag('translation.dumper', ['alias' => 'po'])->set('translation.dumper.mo', MoFileDumper::class)->tag('translation.dumper', ['alias' => 'mo'])->set('translation.dumper.yml', YamlFileDumper::class)->tag('translation.dumper', ['alias' => 'yml'])->set('translation.dumper.yaml', YamlFileDumper::class)->args(['yaml'])->tag('translation.dumper', ['alias' => 'yaml'])->set('translation.dumper.qt', QtFileDumper::class)->tag('translation.dumper', ['alias' => 'ts'])->set('translation.dumper.csv', CsvFileDumper::class)->tag('translation.dumper', ['alias' => 'csv'])->set('translation.dumper.ini', IniFileDumper::class)->tag('translation.dumper', ['alias' => 'ini'])->set('translation.dumper.json', JsonFileDumper::class)->tag('translation.dumper', ['alias' => 'json'])->set('translation.dumper.res', IcuResFileDumper::class)->tag('translation.dumper', ['alias' => 'res'])->set('translation.extractor.php', PhpExtractor::class)->deprecate('symfony/framework-bundle', '6.2', 'The "%service_id%" service is deprecated, use "translation.extractor.php_ast" instead.')->tag('translation.extractor', ['alias' => 'php'])->set('translation.extractor.php_ast', PhpAstExtractor::class)->args([tagged_iterator('translation.extractor.visitor')])->tag('translation.extractor', ['alias' => 'php'])->set('translation.extractor.visitor.trans_method', TransMethodVisitor::class)->tag('translation.extractor.visitor')->set('translation.extractor.visitor.translatable_message', TranslatableMessageVisitor::class)->tag('translation.extractor.visitor')->set('translation.extractor.visitor.constraint', ConstraintVisitor::class)->tag('translation.extractor.visitor')->set('translation.reader', TranslationReader::class)->alias(TranslationReaderInterface::class, 'translation.reader')->set('translation.extractor', ChainExtractor::class)->alias(ExtractorInterface::class, 'translation.extractor')->set('translation.writer', TranslationWriter::class)->alias(TranslationWriterInterface::class, 'translation.writer')->set('translation.warmer', TranslationsCacheWarmer::class)->args([service(ContainerInterface::class)])->tag('container.service_subscriber', ['id' => 'translator'])->tag('kernel.cache_warmer')->set('translation.locale_switcher', LocaleSwitcher::class)->args([param('kernel.default_locale'), tagged_iterator('kernel.locale_aware', exclude: 'translation.locale_switcher'), service('router.request_context')->ignoreOnInvalid()])->tag('kernel.reset', ['method' => 'reset'])->tag('kernel.locale_aware')->alias(LocaleAwareInterface::class, 'translation.locale_switcher')->alias(LocaleSwitcher::class, 'translation.locale_switcher');
};
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\DependencyInjection\Loader\Configurator;

use _ContaoManager\Psr\Cache\CacheItemPoolInterface;
use _ContaoManager\Symfony\Bundle\FrameworkBundle\CacheWarmer\SerializerCacheWarmer;
use _ContaoManager\Symfony\Component\Cache\Adapter\PhpArrayAdapter;
use _ContaoManager\Symfony\Component\ErrorHandler\ErrorRenderer\HtmlErrorRenderer;
use _ContaoManager\Symfony\Component\ErrorHandler\ErrorRenderer\SerializerErrorRenderer;
use _ContaoManager\Symfony\Component\PropertyInfo\Extractor\SerializerExtractor;
use _ContaoManager\Symfony\Component\Serializer\Encoder\CsvEncoder;
use _ContaoManager\Symfony\Component\Serializer\Encoder\DecoderInterface;
use _ContaoManager\Symfony\Component\Serializer\Encoder\EncoderInterface;
use _ContaoManager\Symfony\Component\Serializer\Encoder\JsonEncoder;
use _ContaoManager\Symfony\Component\Serializer\Encoder\XmlEncoder;
use _ContaoManager\Symfony\Component\Serializer\Encoder\YamlEncoder;
use _ContaoManager\Symfony\Component\Serializer\Mapping\ClassDiscriminatorFromClassMetadata;
use _ContaoManager\Symfony\Component\Serializer\Mapping\ClassDiscriminatorResolverInterface;
use _ContaoManager\Symfony\Component\Serializer\Mapping\Factory\CacheClassMetadataFactory;
use _ContaoManager\Symfony\Component\Serializer\Mapping\Factory\ClassMetadataFactory;
use _ContaoManager\Symfony\Component\Serializer\Mapping\Factory\ClassMetadataFactoryInterface;
use _ContaoManager\Symfony\Component\Serializer\Mapping\Loader\LoaderChain;
use _ContaoManager\Symfony\Component\Serializer\NameConverter\CamelCaseToSnakeCaseNameConverter;
use _ContaoManager\Symfony\Component\Serializer\NameConverter\MetadataAwareNameConverter;
use _ContaoManager\Symfony\Component\Serializer\Normalizer\ArrayDenormalizer;
use _ContaoManager\Symfony\Component\Serializer\Normalizer\BackedEnumNormalizer;
use _ContaoManager\Symfony\Component\Serializer\Normalizer\ConstraintViolationListNormalizer;
use _ContaoManager\Symfony\Component\Serializer\Normalizer\DataUriNormalizer;
use _ContaoManager\Symfony\Component\Serializer\Normalizer\DateIntervalNormalizer;
use _ContaoManager\Symfony\Component\Serializer\Normalizer\DateTimeNormalizer;
use _ContaoManager\Symfony\Component\Serializer\Normalizer\DateTimeZoneNormalizer;
use _ContaoManager\Symfony\Component\Serializer\Normalizer\DenormalizerInterface;
use _ContaoManager\Symfony\Component\Serializer\Normalizer\FormErrorNormalizer;
use _ContaoManager\Symfony\Component\Serializer\Normalizer\JsonSerializableNormalizer;
use _ContaoManager\Symfony\Component\Serializer\Normalizer\MimeMessageNormalizer;
use _ContaoManager\Symfony\Component\Serializer\Normalizer\NormalizerAwareInterface;
use _ContaoManager\Symfony\Component\Serializer\Normalizer\NormalizerInterface;
use _ContaoManager\Symfony\Component\Serializer\Normalizer\ObjectNormalizer;
use _ContaoManager\Symfony\Component\Serializer\Normalizer\ProblemNormalizer;
use _ContaoManager\Symfony\Component\Serializer\Normalizer\PropertyNormalizer;
use _ContaoManager\Symfony\Component\Serializer\Normalizer\TranslatableNormalizer;
use _ContaoManager\Symfony\Component\Serializer\Normalizer\UidNormalizer;
use _ContaoManager\Symfony\Component\Serializer\Normalizer\UnwrappingDenormalizer;
use _ContaoManager\Symfony\Component\Serializer\Serializer;
use _ContaoManager\Symfony\Component\Serializer\SerializerInterface;
return static function (ContainerConfigurator $container) {
    $container->parameters()->set('serializer.mapping.cache.file', '%kernel.cache_dir%/serialization.php');
    $container->services()->set('serializer', Serializer::class)->args([[], [], []])->alias(SerializerInterface::class, 'serializer')->alias(NormalizerInterface::class, 'serializer')->alias(DenormalizerInterface::class, 'serializer')->alias(EncoderInterface::class, 'serializer')->alias(DecoderInterface::class, 'serializer')->alias('serializer.property_accessor', 'property_accessor')->set('serializer.mapping.class_discriminator_resolver', ClassDiscriminatorFromClassMetadata::class)->args([service('serializer.mapping.class_metadata_factory')])->alias(ClassDiscriminatorResolverInterface::class, 'serializer.mapping.class_discriminator_resolver')->set('serializer.normalizer.constraint_violation_list', ConstraintViolationListNormalizer::class)->args([1 => service('serializer.name_converter.metadata_aware')])->autowire(\true)->tag('serializer.normalizer', ['priority' => -915])->set('serializer.normalizer.mime_message', MimeMessageNormalizer::class)->args([service('serializer.normalizer.property')])->tag('serializer.normalizer', ['priority' => -915])->set('serializer.normalizer.datetimezone', DateTimeZoneNormalizer::class)->tag('serializer.normalizer', ['priority' => -915])->set('serializer.normalizer.dateinterval', DateIntervalNormalizer::class)->tag('serializer.normalizer', ['priority' => -915])->set('serializer.normalizer.data_uri', DataUriNormalizer::class)->args([service('mime_types')->nullOnInvalid()])->tag('serializer.normalizer', ['priority' => -920])->set('serializer.normalizer.datetime', DateTimeNormalizer::class)->tag('serializer.normalizer', ['priority' => -910])->set('serializer.normalizer.json_serializable', JsonSerializableNormalizer::class)->args([null, null])->tag('serializer.normalizer', ['priority' => -950])->set('serializer.normalizer.problem', ProblemNormalizer::class)->args([param('kernel.debug'), '$translator' => service('translator')->nullOnInvalid()])->tag('serializer.normalizer', ['priority' => -890])->set('serializer.denormalizer.unwrapping', UnwrappingDenormalizer::class)->args([service('serializer.property_accessor')])->tag('serializer.normalizer', ['priority' => 1000])->set('serializer.normalizer.uid', UidNormalizer::class)->tag('serializer.normalizer', ['priority' => -890])->set('serializer.normalizer.translatable', TranslatableNormalizer::class)->args(['$translator' => service('translator')])->tag('serializer.normalizer', ['priority' => -920])->set('serializer.normalizer.form_error', FormErrorNormalizer::class)->tag('serializer.normalizer', ['priority' => -915])->set('serializer.normalizer.object', ObjectNormalizer::class)->args([service('serializer.mapping.class_metadata_factory'), service('serializer.name_converter.metadata_aware'), service('serializer.property_accessor'), service('property_info')->ignoreOnInvalid(), service('serializer.mapping.class_discriminator_resolver')->ignoreOnInvalid(), null, null, service('property_info')->ignoreOnInvalid()])->tag('serializer.normalizer', ['priority' => -1000])->alias(ObjectNormalizer::class, 'serializer.normalizer.object')->deprecate('symfony/serializer', '6.2', 'The "%alias_id%" service alias is deprecated, type-hint against "' . NormalizerInterface::class . '" or implement "' . NormalizerAwareInterface::class . '" instead.')->set('serializer.normalizer.property', PropertyNormalizer::class)->args([service('serializer.mapping.class_metadata_factory'), service('serializer.name_converter.metadata_aware'), service('property_info')->ignoreOnInvalid(), service('serializer.mapping.class_discriminator_resolver')->ignoreOnInvalid(), null])->alias(PropertyNormalizer::class, 'serializer.normalizer.property')->deprecate('symfony/serializer', '6.2', 'The "%alias_id%" service alias is deprecated, type-hint against "' . NormalizerInterface::class . '" or implement "' . NormalizerAwareInterface::class . '" instead.')->set('serializer.denormalizer.array', ArrayDenormalizer::class)->tag('serializer.normalizer', ['priority' => -990])->set('serializer.mapping.chain_loader', LoaderChain::class)->args([[]])->set('serializer.mapping.class_metadata_factory', ClassMetadataFactory::class)->args([service('serializer.mapping.chain_loader')])->alias(ClassMetadataFactoryInterface::class, 'serializer.mapping.class_metadata_factory')->set('serializer.mapping.cache_warmer', SerializerCacheWarmer::class)->args([abstract_arg('The serializer metadata loaders'), param('serializer.mapping.cache.file')])->tag('kernel.cache_warmer')->set('serializer.mapping.cache.symfony', CacheItemPoolInterface::class)->factory([PhpArrayAdapter::class, 'create'])->args([param('serializer.mapping.cache.file'), service('cache.serializer')])->set('serializer.mapping.cache_class_metadata_factory', CacheClassMetadataFactory::class)->decorate('serializer.mapping.class_metadata_factory')->args([service('serializer.mapping.cache_class_metadata_factory.inner'), service('serializer.mapping.cache.symfony')])->set('serializer.encoder.xml', XmlEncoder::class)->tag('serializer.encoder')->set('serializer.encoder.json', JsonEncoder::class)->args([null, null])->tag('serializer.encoder')->set('serializer.encoder.yaml', YamlEncoder::class)->args([null, null])->tag('serializer.encoder')->set('serializer.encoder.csv', CsvEncoder::class)->tag('serializer.encoder')->set('serializer.name_converter.camel_case_to_snake_case', CamelCaseToSnakeCaseNameConverter::class)->set('serializer.name_converter.metadata_aware', MetadataAwareNameConverter::class)->args([service('serializer.mapping.class_metadata_factory')])->set('property_info.serializer_extractor', SerializerExtractor::class)->args([service('serializer.mapping.class_metadata_factory')])->tag('property_info.list_extractor', ['priority' => -999])->alias('error_renderer', 'error_renderer.serializer')->alias('error_renderer.serializer', 'error_handler.error_renderer.serializer')->set('error_handler.error_renderer.serializer', SerializerErrorRenderer::class)->args([service('serializer'), inline_service()->factory([SerializerErrorRenderer::class, 'getPreferredFormat'])->args([service('request_stack')]), service('error_renderer.html'), inline_service()->factory([HtmlErrorRenderer::class, 'isDebug'])->args([service('request_stack'), param('kernel.debug')])])->set('serializer.normalizer.backed_enum', BackedEnumNormalizer::class)->tag('serializer.normalizer', ['priority' => -915]);
};
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\DependencyInjection\Loader\Configurator;

use _ContaoManager\Symfony\Component\Form\Extension\DataCollector\FormDataCollector;
use _ContaoManager\Symfony\Component\Form\Extension\DataCollector\FormDataExtractor;
use _ContaoManager\Symfony\Component\Form\Extension\DataCollector\Proxy\ResolvedTypeFactoryDataCollectorProxy;
use _ContaoManager\Symfony\Component\Form\Extension\DataCollector\Type\DataCollectorTypeExtension;
use _ContaoManager\Symfony\Component\Form\ResolvedFormTypeFactory;
return static function (ContainerConfigurator $container) {
    $container->services()->set('form.resolved_type_factory', ResolvedTypeFactoryDataCollectorProxy::class)->args([inline_service(ResolvedFormTypeFactory::class), service('data_collector.form')])->set('form.type_extension.form.data_collector', DataCollectorTypeExtension::class)->args([service('data_collector.form')])->tag('form.type_extension')->set('data_collector.form.extractor', FormDataExtractor::class)->set('data_collector.form', FormDataCollector::class)->args([service('data_collector.form.extractor')])->tag('data_collector', ['template' => '@WebProfiler/Collector/form.html.twig', 'id' => 'form', 'priority' => 310]);
};
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\DependencyInjection\Loader\Configurator;

use _ContaoManager\Symfony\Bundle\FrameworkBundle\CacheWarmer\ValidatorCacheWarmer;
use _ContaoManager\Symfony\Component\Cache\Adapter\PhpArrayAdapter;
use _ContaoManager\Symfony\Component\ExpressionLanguage\ExpressionLanguage;
use _ContaoManager\Symfony\Component\Validator\Constraints\EmailValidator;
use _ContaoManager\Symfony\Component\Validator\Constraints\ExpressionLanguageProvider;
use _ContaoManager\Symfony\Component\Validator\Constraints\ExpressionValidator;
use _ContaoManager\Symfony\Component\Validator\Constraints\NoSuspiciousCharactersValidator;
use _ContaoManager\Symfony\Component\Validator\Constraints\NotCompromisedPasswordValidator;
use _ContaoManager\Symfony\Component\Validator\Constraints\WhenValidator;
use _ContaoManager\Symfony\Component\Validator\ContainerConstraintValidatorFactory;
use _ContaoManager\Symfony\Component\Validator\Mapping\Loader\PropertyInfoLoader;
use _ContaoManager\Symfony\Component\Validator\Validation;
use _ContaoManager\Symfony\Component\Validator\Validator\ValidatorInterface;
use _ContaoManager\Symfony\Component\Validator\ValidatorBuilder;
return static function (ContainerConfigurator $container) {
    $container->parameters()->set('validator.mapping.cache.file', param('kernel.cache_dir') . '/validation.php');
    $validatorsDir = \dirname((new \ReflectionClass(EmailValidator::class))->getFileName());
    $container->services()->set('validator', ValidatorInterface::class)->factory([service('validator.builder'), 'getValidator'])->alias(ValidatorInterface::class, 'validator')->set('validator.builder', ValidatorBuilder::class)->factory([Validation::class, 'createValidatorBuilder'])->call('setConstraintValidatorFactory', [service('validator.validator_factory')])->call('setGroupProviderLocator', [tagged_locator('validator.group_provider')])->call('setTranslator', [service('translator')->ignoreOnInvalid()])->call('setTranslationDomain', [param('validator.translation_domain')])->alias('validator.mapping.class_metadata_factory', 'validator')->set('validator.mapping.cache_warmer', ValidatorCacheWarmer::class)->args([service('validator.builder'), param('validator.mapping.cache.file')])->tag('kernel.cache_warmer')->set('validator.mapping.cache.adapter', PhpArrayAdapter::class)->factory([PhpArrayAdapter::class, 'create'])->args([param('validator.mapping.cache.file'), service('cache.validator')])->set('validator.validator_factory', ContainerConstraintValidatorFactory::class)->args([abstract_arg('Constraint validators locator')])->load('Symfony\Component\Validator\Constraints\\', $validatorsDir . '/*Validator.php')->exclude($validatorsDir . '/ExpressionLanguageSyntaxValidator.php')->abstract()->tag('container.excluded')->tag('validator.constraint_validator')->set('validator.expression', ExpressionValidator::class)->args([service('validator.expression_language')->nullOnInvalid()])->tag('validator.constraint_validator', ['alias' => 'validator.expression'])->set('validator.expression_language', ExpressionLanguage::class)->args([service('cache.validator_expression_language')->nullOnInvalid()])->call('registerProvider', [service('validator.expression_language_provider')->ignoreOnInvalid()])->set('cache.validator_expression_language')->parent('cache.system')->tag('cache.pool')->set('validator.expression_language_provider', ExpressionLanguageProvider::class)->set('validator.email', EmailValidator::class)->args([abstract_arg('Default mode')])->tag('validator.constraint_validator')->set('validator.not_compromised_password', NotCompromisedPasswordValidator::class)->args([service('http_client')->nullOnInvalid(), param('kernel.charset'), \false])->tag('validator.constraint_validator')->set('validator.when', WhenValidator::class)->args([service('validator.expression_language')->nullOnInvalid()])->tag('validator.constraint_validator')->set('validator.no_suspicious_characters', NoSuspiciousCharactersValidator::class)->args([param('kernel.enabled_locales')])->tag('validator.constraint_validator', ['alias' => NoSuspiciousCharactersValidator::class])->set('validator.property_info_loader', PropertyInfoLoader::class)->args([service('property_info'), service('property_info'), service('property_info')])->tag('validator.auto_mapper');
};
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\DependencyInjection\Loader\Configurator;

use _ContaoManager\Symfony\Component\Semaphore\SemaphoreFactory;
return static function (ContainerConfigurator $container) {
    $container->services()->set('semaphore.factory.abstract', SemaphoreFactory::class)->abstract()->args([abstract_arg('Store')])->call('setLogger', [service('logger')->ignoreOnInvalid()])->tag('monolog.logger', ['channel' => 'semaphore']);
};
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\DependencyInjection\Loader\Configurator;

use _ContaoManager\Doctrine\Common\Annotations\AnnotationReader;
use _ContaoManager\Doctrine\Common\Annotations\PsrCachedReader;
use _ContaoManager\Doctrine\Common\Annotations\Reader;
use _ContaoManager\Symfony\Bundle\FrameworkBundle\CacheWarmer\AnnotationsCacheWarmer;
use _ContaoManager\Symfony\Component\Cache\Adapter\ArrayAdapter;
use _ContaoManager\Symfony\Component\Cache\Adapter\FilesystemAdapter;
use _ContaoManager\Symfony\Component\Cache\Adapter\PhpArrayAdapter;
return static function (ContainerConfigurator $container) {
    $container->services()->set('annotations.reader', AnnotationReader::class)->call('addGlobalIgnoredName', ['required'])->deprecate('symfony/framework-bundle', '6.4', 'The "%service_id%" service is deprecated without replacement.')->set('annotations.cached_reader', PsrCachedReader::class)->args([service('annotations.reader'), inline_service(ArrayAdapter::class), abstract_arg('Debug-Flag')])->tag('annotations.cached_reader')->tag('container.do_not_inline')->deprecate('symfony/framework-bundle', '6.4', 'The "%service_id%" service is deprecated without replacement.')->set('annotations.filesystem_cache_adapter', FilesystemAdapter::class)->args(['', 0, abstract_arg('Cache-Directory')])->deprecate('symfony/framework-bundle', '6.4', 'The "%service_id%" service is deprecated without replacement.')->set('annotations.cache_warmer', AnnotationsCacheWarmer::class)->args([service('annotations.reader'), param('kernel.cache_dir') . '/annotations.php', '#^Symfony\\\\(?:Component\\\\HttpKernel\\\\|Bundle\\\\FrameworkBundle\\\\Controller\\\\(?!.*Controller$))#', param('kernel.debug'), \false])->deprecate('symfony/framework-bundle', '6.4', 'The "%service_id%" service is deprecated without replacement.')->set('annotations.cache_adapter', PhpArrayAdapter::class)->factory([PhpArrayAdapter::class, 'create'])->args([param('kernel.cache_dir') . '/annotations.php', service('cache.annotations')])->tag('container.hot_path')->deprecate('symfony/framework-bundle', '6.4', 'The "%service_id%" service is deprecated without replacement.')->alias('annotation_reader', 'annotations.reader')->deprecate('symfony/framework-bundle', '6.4', 'The "%alias_id%" service alias is deprecated without replacement.')->alias(Reader::class, 'annotation_reader')->deprecate('symfony/framework-bundle', '6.4', 'The "%alias_id%" service alias is deprecated without replacement.');
};
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\DependencyInjection\Loader\Configurator;

use _ContaoManager\Symfony\Bundle\FrameworkBundle\EventListener\ConsoleProfilerListener;
use _ContaoManager\Symfony\Component\HttpKernel\Debug\VirtualRequestStack;
use _ContaoManager\Symfony\Component\HttpKernel\EventListener\ProfilerListener;
use _ContaoManager\Symfony\Component\HttpKernel\Profiler\FileProfilerStorage;
use _ContaoManager\Symfony\Component\HttpKernel\Profiler\Profiler;
return static function (ContainerConfigurator $container) {
    $container->services()->set('profiler', Profiler::class)->public()->args([service('profiler.storage'), service('logger')->nullOnInvalid()])->tag('monolog.logger', ['channel' => 'profiler'])->tag('container.private', ['package' => 'symfony/framework-bundle', 'version' => '5.4'])->set('profiler.storage', FileProfilerStorage::class)->args([param('profiler.storage.dsn')])->set('profiler_listener', ProfilerListener::class)->args([service('profiler'), service('request_stack'), null, param('profiler_listener.only_exceptions'), param('profiler_listener.only_main_requests')])->tag('kernel.event_subscriber')->set('console_profiler_listener', ConsoleProfilerListener::class)->args([service('.lazy_profiler'), service('.virtual_request_stack'), service('debug.stopwatch'), param('kernel.runtime_mode.cli'), service('router')->nullOnInvalid()])->tag('kernel.event_subscriber')->set('.lazy_profiler', Profiler::class)->factory('current')->args([[service('profiler')]])->lazy()->set('.virtual_request_stack', VirtualRequestStack::class)->args([service('request_stack')])->public();
};
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\DependencyInjection\Loader\Configurator;

use _ContaoManager\Symfony\Component\Mailer\Command\MailerTestCommand;
use _ContaoManager\Symfony\Component\Mailer\EventListener\EnvelopeListener;
use _ContaoManager\Symfony\Component\Mailer\EventListener\MessageListener;
use _ContaoManager\Symfony\Component\Mailer\EventListener\MessageLoggerListener;
use _ContaoManager\Symfony\Component\Mailer\EventListener\MessengerTransportListener;
use _ContaoManager\Symfony\Component\Mailer\Mailer;
use _ContaoManager\Symfony\Component\Mailer\MailerInterface;
use _ContaoManager\Symfony\Component\Mailer\Messenger\MessageHandler;
use _ContaoManager\Symfony\Component\Mailer\Transport;
use _ContaoManager\Symfony\Component\Mailer\Transport\TransportInterface;
use _ContaoManager\Symfony\Component\Mailer\Transport\Transports;
return static function (ContainerConfigurator $container) {
    $container->services()->set('mailer.mailer', Mailer::class)->args([service('mailer.transports'), abstract_arg('message bus'), service('event_dispatcher')->ignoreOnInvalid()])->alias('mailer', 'mailer.mailer')->alias(MailerInterface::class, 'mailer.mailer')->set('mailer.transports', Transports::class)->factory([service('mailer.transport_factory'), 'fromStrings'])->args([abstract_arg('transports')])->set('mailer.transport_factory', Transport::class)->args([tagged_iterator('mailer.transport_factory')])->alias('mailer.default_transport', 'mailer.transports')->alias(TransportInterface::class, 'mailer.default_transport')->set('mailer.messenger.message_handler', MessageHandler::class)->args([service('mailer.transports')])->tag('messenger.message_handler')->set('mailer.envelope_listener', EnvelopeListener::class)->args([abstract_arg('sender'), abstract_arg('recipients')])->tag('kernel.event_subscriber')->set('mailer.message_listener', MessageListener::class)->args([abstract_arg('headers')])->tag('kernel.event_subscriber')->set('mailer.message_logger_listener', MessageLoggerListener::class)->tag('kernel.event_subscriber')->tag('kernel.reset', ['method' => 'reset'])->set('mailer.messenger_transport_listener', MessengerTransportListener::class)->tag('kernel.event_subscriber')->set('console.command.mailer_test', MailerTestCommand::class)->args([service('mailer.transports')])->tag('console.command');
};
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\DependencyInjection\Loader\Configurator;

use _ContaoManager\Symfony\Component\HttpKernel\EventListener\FragmentListener;
return static function (ContainerConfigurator $container) {
    $container->services()->set('fragment.listener', FragmentListener::class)->args([service('uri_signer'), param('fragment.path')])->tag('kernel.event_subscriber');
};
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\DependencyInjection\Loader\Configurator;

use _ContaoManager\Symfony\Component\Translation\DataCollector\TranslationDataCollector;
use _ContaoManager\Symfony\Component\Translation\DataCollectorTranslator;
return static function (ContainerConfigurator $container) {
    $container->services()->set('translator.data_collector', DataCollectorTranslator::class)->args([service('translator.data_collector.inner')])->set('data_collector.translation', TranslationDataCollector::class)->args([service('translator.data_collector')])->tag('data_collector', ['template' => '@WebProfiler/Collector/translation.html.twig', 'id' => 'translation', 'priority' => 275]);
};
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\DependencyInjection\Loader\Configurator;

use _ContaoManager\Symfony\Component\Notifier\DataCollector\NotificationDataCollector;
return static function (ContainerConfigurator $container) {
    $container->services()->set('notifier.data_collector', NotificationDataCollector::class)->args([service('notifier.notification_logger_listener')])->tag('data_collector', ['template' => '@WebProfiler/Collector/notifier.html.twig', 'id' => 'notifier']);
};
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\DependencyInjection\Loader\Configurator;

use _ContaoManager\Symfony\Component\RateLimiter\RateLimiterFactory;
return static function (ContainerConfigurator $container) {
    $container->services()->set('cache.rate_limiter')->parent('cache.app')->tag('cache.pool')->set('limiter', RateLimiterFactory::class)->abstract()->args([abstract_arg('config'), abstract_arg('storage'), null]);
};
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\DependencyInjection\Loader\Configurator;

use _ContaoManager\Symfony\Component\Lock\LockFactory;
use _ContaoManager\Symfony\Component\Lock\Store\CombinedStore;
use _ContaoManager\Symfony\Component\Lock\Strategy\ConsensusStrategy;
return static function (ContainerConfigurator $container) {
    $container->services()->set('lock.store.combined.abstract', CombinedStore::class)->abstract()->args([abstract_arg('List of stores'), service('lock.strategy.majority')])->set('lock.strategy.majority', ConsensusStrategy::class)->set('lock.factory.abstract', LockFactory::class)->abstract()->args([abstract_arg('Store')])->call('setLogger', [service('logger')->ignoreOnInvalid()])->tag('monolog.logger', ['channel' => 'lock']);
};
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\DependencyInjection\Loader\Configurator;

use _ContaoManager\Symfony\Component\Translation\IdentityTranslator;
use _ContaoManager\Symfony\Contracts\Translation\TranslatorInterface;
return static function (ContainerConfigurator $container) {
    $container->services()->set('translator', IdentityTranslator::class)->alias(TranslatorInterface::class, 'translator')->set('identity_translator', IdentityTranslator::class);
};
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\DependencyInjection\Loader\Configurator;

use _ContaoManager\Http\Client\HttpAsyncClient;
use _ContaoManager\Psr\Http\Client\ClientInterface;
use _ContaoManager\Psr\Http\Message\ResponseFactoryInterface;
use _ContaoManager\Psr\Http\Message\StreamFactoryInterface;
use _ContaoManager\Symfony\Component\HttpClient\HttpClient;
use _ContaoManager\Symfony\Component\HttpClient\HttplugClient;
use _ContaoManager\Symfony\Component\HttpClient\Messenger\PingWebhookMessageHandler;
use _ContaoManager\Symfony\Component\HttpClient\Psr18Client;
use _ContaoManager\Symfony\Component\HttpClient\Retry\GenericRetryStrategy;
use _ContaoManager\Symfony\Component\HttpClient\UriTemplateHttpClient;
use _ContaoManager\Symfony\Contracts\HttpClient\HttpClientInterface;
return static function (ContainerConfigurator $container) {
    $container->services()->set('http_client.transport', HttpClientInterface::class)->factory([HttpClient::class, 'create'])->args([
        [],
        // default options
        abstract_arg('max host connections'),
    ])->call('setLogger', [service('logger')->ignoreOnInvalid()])->tag('monolog.logger', ['channel' => 'http_client'])->tag('kernel.reset', ['method' => 'reset', 'on_invalid' => 'ignore'])->set('http_client', HttpClientInterface::class)->factory('current')->args([[service('http_client.transport')]])->tag('http_client.client')->tag('kernel.reset', ['method' => 'reset', 'on_invalid' => 'ignore'])->alias(HttpClientInterface::class, 'http_client')->set('psr18.http_client', Psr18Client::class)->args([service('http_client'), service(ResponseFactoryInterface::class)->ignoreOnInvalid(), service(StreamFactoryInterface::class)->ignoreOnInvalid()])->alias(ClientInterface::class, 'psr18.http_client')->set('httplug.http_client', HttplugClient::class)->args([service('http_client'), service(ResponseFactoryInterface::class)->ignoreOnInvalid(), service(StreamFactoryInterface::class)->ignoreOnInvalid()])->alias(HttpAsyncClient::class, 'httplug.http_client')->alias(\_ContaoManager\Http\Client\HttpClient::class, 'httplug.http_client')->deprecate('symfony/framework-bundle', '6.3', 'The "%alias_id%" service is deprecated, use "' . ClientInterface::class . '" instead.')->set('http_client.abstract_retry_strategy', GenericRetryStrategy::class)->abstract()->args([abstract_arg('http codes'), abstract_arg('delay ms'), abstract_arg('multiplier'), abstract_arg('max delay ms'), abstract_arg('jitter')])->set('http_client.uri_template', UriTemplateHttpClient::class)->decorate('http_client', null, 7)->args([service('.inner'), service('http_client.uri_template_expander')->nullOnInvalid(), abstract_arg('default vars')])->set('http_client.uri_template_expander.guzzle', \Closure::class)->factory([\Closure::class, 'fromCallable'])->args([[\_ContaoManager\GuzzleHttp\UriTemplate\UriTemplate::class, 'expand']])->set('http_client.uri_template_expander.rize', \Closure::class)->factory([\Closure::class, 'fromCallable'])->args([[inline_service(\_ContaoManager\Rize\UriTemplate::class), 'expand']])->set('http_client.messenger.ping_webhook_handler', PingWebhookMessageHandler::class)->args([service('http_client')])->tag('messenger.message_handler');
};
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\DependencyInjection\Loader\Configurator;

use _ContaoManager\Symfony\Component\Mailer\DataCollector\MessageDataCollector;
return static function (ContainerConfigurator $container) {
    $container->services()->set('mailer.data_collector', MessageDataCollector::class)->args([service('mailer.message_logger_listener')])->tag('data_collector', ['template' => '@WebProfiler/Collector/mailer.html.twig', 'id' => 'mailer']);
};
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\DependencyInjection\Loader\Configurator;

use _ContaoManager\Psr\Clock\ClockInterface as PsrClockInterface;
use _ContaoManager\Psr\EventDispatcher\EventDispatcherInterface as PsrEventDispatcherInterface;
use _ContaoManager\Symfony\Bundle\FrameworkBundle\CacheWarmer\ConfigBuilderCacheWarmer;
use _ContaoManager\Symfony\Bundle\FrameworkBundle\HttpCache\HttpCache;
use _ContaoManager\Symfony\Component\Clock\Clock;
use _ContaoManager\Symfony\Component\Clock\ClockInterface;
use _ContaoManager\Symfony\Component\Config\Loader\LoaderInterface;
use _ContaoManager\Symfony\Component\Config\Resource\SelfCheckingResourceChecker;
use _ContaoManager\Symfony\Component\Config\ResourceCheckerConfigCacheFactory;
use _ContaoManager\Symfony\Component\Console\ConsoleEvents;
use _ContaoManager\Symfony\Component\DependencyInjection\Config\ContainerParametersResourceChecker;
use _ContaoManager\Symfony\Component\DependencyInjection\EnvVarProcessor;
use _ContaoManager\Symfony\Component\DependencyInjection\ParameterBag\ContainerBag;
use _ContaoManager\Symfony\Component\DependencyInjection\ParameterBag\ContainerBagInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\ReverseContainer;
use _ContaoManager\Symfony\Component\EventDispatcher\EventDispatcher;
use _ContaoManager\Symfony\Component\EventDispatcher\EventDispatcherInterface as EventDispatcherInterfaceComponentAlias;
use _ContaoManager\Symfony\Component\Filesystem\Filesystem;
use _ContaoManager\Symfony\Component\Form\FormEvents;
use _ContaoManager\Symfony\Component\HttpFoundation\Request;
use _ContaoManager\Symfony\Component\HttpFoundation\RequestStack;
use _ContaoManager\Symfony\Component\HttpFoundation\Response;
use _ContaoManager\Symfony\Component\HttpFoundation\Session\SessionInterface;
use _ContaoManager\Symfony\Component\HttpFoundation\UriSigner;
use _ContaoManager\Symfony\Component\HttpFoundation\UrlHelper;
use _ContaoManager\Symfony\Component\HttpKernel\CacheClearer\ChainCacheClearer;
use _ContaoManager\Symfony\Component\HttpKernel\CacheWarmer\CacheWarmerAggregate;
use _ContaoManager\Symfony\Component\HttpKernel\Config\FileLocator;
use _ContaoManager\Symfony\Component\HttpKernel\DependencyInjection\ServicesResetter;
use _ContaoManager\Symfony\Component\HttpKernel\EventListener\LocaleAwareListener;
use _ContaoManager\Symfony\Component\HttpKernel\HttpCache\Store;
use _ContaoManager\Symfony\Component\HttpKernel\HttpCache\StoreInterface;
use _ContaoManager\Symfony\Component\HttpKernel\HttpKernel;
use _ContaoManager\Symfony\Component\HttpKernel\HttpKernelInterface;
use _ContaoManager\Symfony\Component\HttpKernel\KernelEvents;
use _ContaoManager\Symfony\Component\HttpKernel\KernelInterface;
use _ContaoManager\Symfony\Component\HttpKernel\UriSigner as HttpKernelUriSigner;
use _ContaoManager\Symfony\Component\Runtime\Runner\Symfony\HttpKernelRunner;
use _ContaoManager\Symfony\Component\Runtime\Runner\Symfony\ResponseRunner;
use _ContaoManager\Symfony\Component\Runtime\SymfonyRuntime;
use _ContaoManager\Symfony\Component\String\LazyString;
use _ContaoManager\Symfony\Component\String\Slugger\AsciiSlugger;
use _ContaoManager\Symfony\Component\String\Slugger\SluggerInterface;
use _ContaoManager\Symfony\Component\Workflow\WorkflowEvents;
use _ContaoManager\Symfony\Contracts\EventDispatcher\EventDispatcherInterface;
return static function (ContainerConfigurator $container) {
    // this parameter is used at compile time in RegisterListenersPass
    $container->parameters()->set('event_dispatcher.event_aliases', array_merge(class_exists(ConsoleEvents::class) ? ConsoleEvents::ALIASES : [], class_exists(FormEvents::class) ? FormEvents::ALIASES : [], KernelEvents::ALIASES, class_exists(WorkflowEvents::class) ? WorkflowEvents::ALIASES : []));
    $container->services()->set('parameter_bag', ContainerBag::class)->args([service('service_container')])->alias(ContainerBagInterface::class, 'parameter_bag')->alias(ParameterBagInterface::class, 'parameter_bag')->set('event_dispatcher', EventDispatcher::class)->public()->tag('container.hot_path')->tag('event_dispatcher.dispatcher', ['name' => 'event_dispatcher'])->alias(EventDispatcherInterfaceComponentAlias::class, 'event_dispatcher')->alias(EventDispatcherInterface::class, 'event_dispatcher')->alias(PsrEventDispatcherInterface::class, 'event_dispatcher')->set('http_kernel', HttpKernel::class)->public()->args([service('event_dispatcher'), service('controller_resolver'), service('request_stack'), service('argument_resolver'), \false])->tag('container.hot_path')->tag('container.preload', ['class' => HttpKernelRunner::class])->tag('container.preload', ['class' => ResponseRunner::class])->tag('container.preload', ['class' => SymfonyRuntime::class])->alias(HttpKernelInterface::class, 'http_kernel')->set('request_stack', RequestStack::class)->tag('kernel.reset', ['method' => 'resetRequestFormats', 'on_invalid' => 'ignore'])->public()->alias(RequestStack::class, 'request_stack')->set('http_cache', HttpCache::class)->args([service('kernel'), service('http_cache.store'), service('esi')->nullOnInvalid(), abstract_arg('options')])->tag('container.hot_path')->set('http_cache.store', Store::class)->args([param('kernel.cache_dir') . '/http_cache'])->alias(StoreInterface::class, 'http_cache.store')->set('url_helper', UrlHelper::class)->args([service('request_stack'), service('router')->ignoreOnInvalid()])->alias(UrlHelper::class, 'url_helper')->set('cache_warmer', CacheWarmerAggregate::class)->public()->args([tagged_iterator('kernel.cache_warmer'), param('kernel.debug'), \sprintf('%s/%sDeprecations.log', param('kernel.build_dir'), param('kernel.container_class'))])->tag('container.no_preload')->set('cache_clearer', ChainCacheClearer::class)->args([tagged_iterator('kernel.cache_clearer')])->set('kernel')->synthetic()->public()->alias(KernelInterface::class, 'kernel')->set('filesystem', Filesystem::class)->alias(Filesystem::class, 'filesystem')->set('file_locator', FileLocator::class)->args([service('kernel')])->alias(FileLocator::class, 'file_locator')->set('uri_signer', UriSigner::class)->args([param('kernel.secret')])->alias(UriSigner::class, 'uri_signer')->alias(HttpKernelUriSigner::class, 'uri_signer')->deprecate('symfony/framework-bundle', '6.4', 'The "%alias_id%" alias is deprecated, use "' . UriSigner::class . '" instead.')->set('config_cache_factory', ResourceCheckerConfigCacheFactory::class)->args([tagged_iterator('config_cache.resource_checker')])->set('dependency_injection.config.container_parameters_resource_checker', ContainerParametersResourceChecker::class)->args([service('service_container')])->tag('config_cache.resource_checker', ['priority' => -980])->set('config.resource.self_checking_resource_checker', SelfCheckingResourceChecker::class)->tag('config_cache.resource_checker', ['priority' => -990])->set('services_resetter', ServicesResetter::class)->public()->set('reverse_container', ReverseContainer::class)->args([service('service_container'), service_locator([])])->alias(ReverseContainer::class, 'reverse_container')->set('locale_aware_listener', LocaleAwareListener::class)->args([
        [],
        // locale aware services
        service('request_stack'),
    ])->tag('kernel.event_subscriber')->set('container.env_var_processor', EnvVarProcessor::class)->args([service('service_container'), tagged_iterator('container.env_var_loader')])->tag('container.env_var_processor')->set('slugger', AsciiSlugger::class)->args([param('kernel.default_locale')])->tag('kernel.locale_aware')->alias(SluggerInterface::class, 'slugger')->set('container.getenv', \Closure::class)->factory([\Closure::class, 'fromCallable'])->args([[service('service_container'), 'getEnv']])->tag('routing.expression_language_function', ['function' => 'env'])->set('container.get_routing_condition_service', \Closure::class)->public()->factory([\Closure::class, 'fromCallable'])->args([[tagged_locator('routing.condition_service', 'alias'), 'get']])->tag('routing.expression_language_function', ['function' => 'service'])->set('container.env', LazyString::class)->abstract()->factory([LazyString::class, 'fromCallable'])->args([service('container.getenv')])->set('config_builder.warmer', ConfigBuilderCacheWarmer::class)->args([service(KernelInterface::class), service('logger')->nullOnInvalid()])->tag('kernel.cache_warmer')->set('clock', Clock::class)->alias(ClockInterface::class, 'clock')->alias(PsrClockInterface::class, 'clock')->set(LoaderInterface::class)->abstract()->tag('container.excluded')->set(Request::class)->abstract()->tag('container.excluded')->set(Response::class)->abstract()->tag('container.excluded')->set(SessionInterface::class)->abstract()->tag('container.excluded');
};
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\DependencyInjection\Loader\Configurator;

use _ContaoManager\Psr\Cache\CacheItemPoolInterface;
use _ContaoManager\Symfony\Component\Cache\Adapter\AbstractAdapter;
use _ContaoManager\Symfony\Component\Cache\Adapter\AdapterInterface;
use _ContaoManager\Symfony\Component\Cache\Adapter\ApcuAdapter;
use _ContaoManager\Symfony\Component\Cache\Adapter\ArrayAdapter;
use _ContaoManager\Symfony\Component\Cache\Adapter\DoctrineDbalAdapter;
use _ContaoManager\Symfony\Component\Cache\Adapter\FilesystemAdapter;
use _ContaoManager\Symfony\Component\Cache\Adapter\MemcachedAdapter;
use _ContaoManager\Symfony\Component\Cache\Adapter\PdoAdapter;
use _ContaoManager\Symfony\Component\Cache\Adapter\ProxyAdapter;
use _ContaoManager\Symfony\Component\Cache\Adapter\RedisAdapter;
use _ContaoManager\Symfony\Component\Cache\Adapter\RedisTagAwareAdapter;
use _ContaoManager\Symfony\Component\Cache\Adapter\TagAwareAdapter;
use _ContaoManager\Symfony\Component\Cache\Marshaller\DefaultMarshaller;
use _ContaoManager\Symfony\Component\Cache\Messenger\EarlyExpirationHandler;
use _ContaoManager\Symfony\Component\HttpKernel\CacheClearer\Psr6CacheClearer;
use _ContaoManager\Symfony\Contracts\Cache\CacheInterface;
use _ContaoManager\Symfony\Contracts\Cache\TagAwareCacheInterface;
return static function (ContainerConfigurator $container) {
    $container->services()->set('cache.app')->parent('cache.adapter.filesystem')->public()->tag('cache.pool', ['clearer' => 'cache.app_clearer'])->set('cache.app.taggable', TagAwareAdapter::class)->args([service('cache.app')])->tag('cache.taggable', ['pool' => 'cache.app'])->set('cache.system')->parent('cache.adapter.system')->public()->tag('cache.pool')->set('cache.validator')->parent('cache.system')->private()->tag('cache.pool')->set('cache.serializer')->parent('cache.system')->private()->tag('cache.pool')->set('cache.annotations')->parent('cache.system')->private()->tag('cache.pool')->set('cache.property_info')->parent('cache.system')->private()->tag('cache.pool')->set('cache.asset_mapper')->parent('cache.system')->private()->tag('cache.pool')->set('cache.messenger.restart_workers_signal')->parent('cache.app')->private()->tag('cache.pool')->set('cache.scheduler')->parent('cache.app')->private()->tag('cache.pool')->set('cache.adapter.system', AdapterInterface::class)->abstract()->factory([AbstractAdapter::class, 'createSystemCache'])->args([
        '',
        // namespace
        0,
        // default lifetime
        abstract_arg('version'),
        \sprintf('%s/pools/system', param('kernel.cache_dir')),
        service('logger')->ignoreOnInvalid(),
    ])->tag('cache.pool', ['clearer' => 'cache.system_clearer', 'reset' => 'reset'])->tag('monolog.logger', ['channel' => 'cache'])->set('cache.adapter.apcu', ApcuAdapter::class)->abstract()->args([
        '',
        // namespace
        0,
        // default lifetime
        abstract_arg('version'),
    ])->call('setLogger', [service('logger')->ignoreOnInvalid()])->tag('cache.pool', ['clearer' => 'cache.default_clearer', 'reset' => 'reset'])->tag('monolog.logger', ['channel' => 'cache'])->set('cache.adapter.filesystem', FilesystemAdapter::class)->abstract()->args([
        '',
        // namespace
        0,
        // default lifetime
        \sprintf('%s/pools/app', param('kernel.cache_dir')),
        service('cache.default_marshaller')->ignoreOnInvalid(),
    ])->call('setLogger', [service('logger')->ignoreOnInvalid()])->tag('cache.pool', ['clearer' => 'cache.default_clearer', 'reset' => 'reset'])->tag('monolog.logger', ['channel' => 'cache'])->set('cache.adapter.psr6', ProxyAdapter::class)->abstract()->args([
        abstract_arg('PSR-6 provider service'),
        '',
        // namespace
        0,
    ])->tag('cache.pool', ['provider' => 'cache.default_psr6_provider', 'clearer' => 'cache.default_clearer', 'reset' => 'reset'])->set('cache.adapter.redis', RedisAdapter::class)->abstract()->args([
        abstract_arg('Redis connection service'),
        '',
        // namespace
        0,
        // default lifetime
        service('cache.default_marshaller')->ignoreOnInvalid(),
    ])->call('setLogger', [service('logger')->ignoreOnInvalid()])->tag('cache.pool', ['provider' => 'cache.default_redis_provider', 'clearer' => 'cache.default_clearer', 'reset' => 'reset'])->tag('monolog.logger', ['channel' => 'cache'])->set('cache.adapter.redis_tag_aware', RedisTagAwareAdapter::class)->abstract()->args([
        abstract_arg('Redis connection service'),
        '',
        // namespace
        0,
        // default lifetime
        service('cache.default_marshaller')->ignoreOnInvalid(),
    ])->call('setLogger', [service('logger')->ignoreOnInvalid()])->tag('cache.pool', ['provider' => 'cache.default_redis_provider', 'clearer' => 'cache.default_clearer', 'reset' => 'reset'])->tag('monolog.logger', ['channel' => 'cache'])->set('cache.adapter.memcached', MemcachedAdapter::class)->abstract()->args([
        abstract_arg('Memcached connection service'),
        '',
        // namespace
        0,
        // default lifetime
        service('cache.default_marshaller')->ignoreOnInvalid(),
    ])->call('setLogger', [service('logger')->ignoreOnInvalid()])->tag('cache.pool', ['provider' => 'cache.default_memcached_provider', 'clearer' => 'cache.default_clearer', 'reset' => 'reset'])->tag('monolog.logger', ['channel' => 'cache'])->set('cache.adapter.doctrine_dbal', DoctrineDbalAdapter::class)->abstract()->args([
        abstract_arg('DBAL connection service'),
        '',
        // namespace
        0,
        // default lifetime
        [],
        // table options
        service('cache.default_marshaller')->ignoreOnInvalid(),
    ])->call('setLogger', [service('logger')->ignoreOnInvalid()])->tag('cache.pool', ['provider' => 'cache.default_doctrine_dbal_provider', 'clearer' => 'cache.default_clearer', 'reset' => 'reset'])->tag('monolog.logger', ['channel' => 'cache'])->set('cache.adapter.pdo', PdoAdapter::class)->abstract()->args([
        abstract_arg('PDO connection service'),
        '',
        // namespace
        0,
        // default lifetime
        [],
        // table options
        service('cache.default_marshaller')->ignoreOnInvalid(),
    ])->call('setLogger', [service('logger')->ignoreOnInvalid()])->tag('cache.pool', ['provider' => 'cache.default_pdo_provider', 'clearer' => 'cache.default_clearer', 'reset' => 'reset'])->tag('monolog.logger', ['channel' => 'cache'])->set('cache.adapter.array', ArrayAdapter::class)->abstract()->args([0])->call('setLogger', [service('logger')->ignoreOnInvalid()])->tag('cache.pool', ['clearer' => 'cache.default_clearer', 'reset' => 'reset'])->tag('monolog.logger', ['channel' => 'cache'])->set('cache.default_marshaller', DefaultMarshaller::class)->args([
        null,
        // use igbinary_serialize() when available
        '%kernel.debug%',
    ])->set('cache.early_expiration_handler', EarlyExpirationHandler::class)->args([service('reverse_container')])->tag('messenger.message_handler')->set('cache.default_clearer', Psr6CacheClearer::class)->args([[]])->set('cache.system_clearer')->parent('cache.default_clearer')->public()->set('cache.global_clearer')->parent('cache.default_clearer')->public()->alias('cache.app_clearer', 'cache.default_clearer')->public()->alias(CacheItemPoolInterface::class, 'cache.app')->alias(CacheInterface::class, 'cache.app')->alias(TagAwareCacheInterface::class, 'cache.app.taggable');
};
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\DependencyInjection\Loader\Configurator;

use _ContaoManager\Symfony\Component\HttpFoundation\Session\SessionFactory;
use _ContaoManager\Symfony\Component\HttpFoundation\Session\Storage\Handler\AbstractSessionHandler;
use _ContaoManager\Symfony\Component\HttpFoundation\Session\Storage\Handler\IdentityMarshaller;
use _ContaoManager\Symfony\Component\HttpFoundation\Session\Storage\Handler\MarshallingSessionHandler;
use _ContaoManager\Symfony\Component\HttpFoundation\Session\Storage\Handler\NativeFileSessionHandler;
use _ContaoManager\Symfony\Component\HttpFoundation\Session\Storage\Handler\SessionHandlerFactory;
use _ContaoManager\Symfony\Component\HttpFoundation\Session\Storage\Handler\StrictSessionHandler;
use _ContaoManager\Symfony\Component\HttpFoundation\Session\Storage\MetadataBag;
use _ContaoManager\Symfony\Component\HttpFoundation\Session\Storage\MockFileSessionStorageFactory;
use _ContaoManager\Symfony\Component\HttpFoundation\Session\Storage\NativeSessionStorageFactory;
use _ContaoManager\Symfony\Component\HttpFoundation\Session\Storage\PhpBridgeSessionStorageFactory;
use _ContaoManager\Symfony\Component\HttpKernel\EventListener\SessionListener;
return static function (ContainerConfigurator $container) {
    $container->parameters()->set('session.metadata.storage_key', '_sf2_meta');
    $container->services()->set('session.factory', SessionFactory::class)->args([service('request_stack'), service('session.storage.factory'), [service('session_listener'), 'onSessionUsage']])->set('session.storage.factory.native', NativeSessionStorageFactory::class)->args([param('session.storage.options'), service('session.handler'), inline_service(MetadataBag::class)->args([param('session.metadata.storage_key'), param('session.metadata.update_threshold'), param('session.metadata.cookie_lifetime')]), \false])->set('session.storage.factory.php_bridge', PhpBridgeSessionStorageFactory::class)->args([service('session.handler'), inline_service(MetadataBag::class)->args([param('session.metadata.storage_key'), param('session.metadata.update_threshold'), param('session.metadata.cookie_lifetime')]), \false])->set('session.storage.factory.mock_file', MockFileSessionStorageFactory::class)->args([param('kernel.cache_dir') . '/sessions', 'MOCKSESSID', inline_service(MetadataBag::class)->args([param('session.metadata.storage_key'), param('session.metadata.update_threshold'), param('session.metadata.cookie_lifetime')])])->alias(\SessionHandlerInterface::class, 'session.handler')->set('session.handler.native', StrictSessionHandler::class)->args([inline_service(\SessionHandler::class)])->set('session.handler.native_file', StrictSessionHandler::class)->args([inline_service(NativeFileSessionHandler::class)->args([param('session.save_path')])])->set('session.abstract_handler', AbstractSessionHandler::class)->factory([SessionHandlerFactory::class, 'createHandler'])->args([abstract_arg('A string or a connection object'), []])->set('session_listener', SessionListener::class)->args([service_locator(['session_factory' => service('session.factory')->ignoreOnInvalid(), 'logger' => service('logger')->ignoreOnInvalid(), 'session_collector' => service('data_collector.request.session_collector')->ignoreOnInvalid(), 'request_stack' => service('request_stack')->ignoreOnInvalid()]), param('kernel.debug'), param('session.storage.options')])->tag('kernel.event_subscriber')->tag('kernel.reset', ['method' => 'reset'])->set('session.marshaller', IdentityMarshaller::class)->set('session.marshalling_handler', MarshallingSessionHandler::class)->decorate('session.handler')->args([service('session.marshalling_handler.inner'), service('session.marshaller')]);
};
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\DependencyInjection\Loader\Configurator;

use _ContaoManager\Symfony\Component\Mailer\Bridge\Amazon\Transport\SesTransportFactory;
use _ContaoManager\Symfony\Component\Mailer\Bridge\Brevo\Transport\BrevoTransportFactory;
use _ContaoManager\Symfony\Component\Mailer\Bridge\Google\Transport\GmailTransportFactory;
use _ContaoManager\Symfony\Component\Mailer\Bridge\Infobip\Transport\InfobipTransportFactory;
use _ContaoManager\Symfony\Component\Mailer\Bridge\Mailchimp\Transport\MandrillTransportFactory;
use _ContaoManager\Symfony\Component\Mailer\Bridge\MailerSend\Transport\MailerSendTransportFactory;
use _ContaoManager\Symfony\Component\Mailer\Bridge\Mailgun\Transport\MailgunTransportFactory;
use _ContaoManager\Symfony\Component\Mailer\Bridge\Mailjet\Transport\MailjetTransportFactory;
use _ContaoManager\Symfony\Component\Mailer\Bridge\MailPace\Transport\MailPaceTransportFactory;
use _ContaoManager\Symfony\Component\Mailer\Bridge\OhMySmtp\Transport\OhMySmtpTransportFactory;
use _ContaoManager\Symfony\Component\Mailer\Bridge\Postmark\Transport\PostmarkTransportFactory;
use _ContaoManager\Symfony\Component\Mailer\Bridge\Scaleway\Transport\ScalewayTransportFactory;
use _ContaoManager\Symfony\Component\Mailer\Bridge\Sendgrid\Transport\SendgridTransportFactory;
use _ContaoManager\Symfony\Component\Mailer\Bridge\Sendinblue\Transport\SendinblueTransportFactory;
use _ContaoManager\Symfony\Component\Mailer\Transport\AbstractTransportFactory;
use _ContaoManager\Symfony\Component\Mailer\Transport\NativeTransportFactory;
use _ContaoManager\Symfony\Component\Mailer\Transport\NullTransportFactory;
use _ContaoManager\Symfony\Component\Mailer\Transport\SendmailTransportFactory;
use _ContaoManager\Symfony\Component\Mailer\Transport\Smtp\EsmtpTransportFactory;
return static function (ContainerConfigurator $container) {
    $container->services()->set('mailer.transport_factory.abstract', AbstractTransportFactory::class)->abstract()->args([service('event_dispatcher'), service('http_client')->ignoreOnInvalid(), service('logger')->ignoreOnInvalid()])->tag('monolog.logger', ['channel' => 'mailer'])->set('mailer.transport_factory.amazon', SesTransportFactory::class)->parent('mailer.transport_factory.abstract')->tag('mailer.transport_factory')->set('mailer.transport_factory.brevo', BrevoTransportFactory::class)->parent('mailer.transport_factory.abstract')->tag('mailer.transport_factory')->set('mailer.transport_factory.gmail', GmailTransportFactory::class)->parent('mailer.transport_factory.abstract')->tag('mailer.transport_factory')->set('mailer.transport_factory.infobip', InfobipTransportFactory::class)->parent('mailer.transport_factory.abstract')->tag('mailer.transport_factory')->set('mailer.transport_factory.mailersend', MailerSendTransportFactory::class)->parent('mailer.transport_factory.abstract')->tag('mailer.transport_factory')->set('mailer.transport_factory.mailchimp', MandrillTransportFactory::class)->parent('mailer.transport_factory.abstract')->tag('mailer.transport_factory')->set('mailer.transport_factory.mailjet', MailjetTransportFactory::class)->parent('mailer.transport_factory.abstract')->tag('mailer.transport_factory')->set('mailer.transport_factory.mailgun', MailgunTransportFactory::class)->parent('mailer.transport_factory.abstract')->tag('mailer.transport_factory')->set('mailer.transport_factory.mailpace', MailPaceTransportFactory::class)->parent('mailer.transport_factory.abstract')->tag('mailer.transport_factory')->set('mailer.transport_factory.postmark', PostmarkTransportFactory::class)->parent('mailer.transport_factory.abstract')->tag('mailer.transport_factory')->set('mailer.transport_factory.sendgrid', SendgridTransportFactory::class)->parent('mailer.transport_factory.abstract')->tag('mailer.transport_factory')->set('mailer.transport_factory.null', NullTransportFactory::class)->parent('mailer.transport_factory.abstract')->tag('mailer.transport_factory')->set('mailer.transport_factory.scaleway', ScalewayTransportFactory::class)->parent('mailer.transport_factory.abstract')->tag('mailer.transport_factory')->set('mailer.transport_factory.sendmail', SendmailTransportFactory::class)->parent('mailer.transport_factory.abstract')->tag('mailer.transport_factory')->set('mailer.transport_factory.sendinblue', SendinblueTransportFactory::class)->parent('mailer.transport_factory.abstract')->tag('mailer.transport_factory')->set('mailer.transport_factory.ohmysmtp', OhMySmtpTransportFactory::class)->parent('mailer.transport_factory.abstract')->tag('mailer.transport_factory')->set('mailer.transport_factory.smtp', EsmtpTransportFactory::class)->parent('mailer.transport_factory.abstract')->tag('mailer.transport_factory', ['priority' => -100])->set('mailer.transport_factory.native', NativeTransportFactory::class)->parent('mailer.transport_factory.abstract')->tag('mailer.transport_factory');
};
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\DependencyInjection\Loader\Configurator;

use _ContaoManager\Symfony\Component\Translation\Bridge\Crowdin\CrowdinProviderFactory;
use _ContaoManager\Symfony\Component\Translation\Bridge\Loco\LocoProviderFactory;
use _ContaoManager\Symfony\Component\Translation\Bridge\Lokalise\LokaliseProviderFactory;
use _ContaoManager\Symfony\Component\Translation\Bridge\Phrase\PhraseProviderFactory;
use _ContaoManager\Symfony\Component\Translation\Provider\NullProviderFactory;
use _ContaoManager\Symfony\Component\Translation\Provider\TranslationProviderCollection;
use _ContaoManager\Symfony\Component\Translation\Provider\TranslationProviderCollectionFactory;
return static function (ContainerConfigurator $container) {
    $container->services()->set('translation.provider_collection', TranslationProviderCollection::class)->factory([service('translation.provider_collection_factory'), 'fromConfig'])->args([[]])->set('translation.provider_collection_factory', TranslationProviderCollectionFactory::class)->args([tagged_iterator('translation.provider_factory'), []])->set('translation.provider_factory.null', NullProviderFactory::class)->tag('translation.provider_factory')->set('translation.provider_factory.crowdin', CrowdinProviderFactory::class)->args([service('http_client'), service('logger'), param('kernel.default_locale'), service('translation.loader.xliff'), service('translation.dumper.xliff')])->tag('translation.provider_factory')->set('translation.provider_factory.loco', LocoProviderFactory::class)->args([service('http_client'), service('logger'), param('kernel.default_locale'), service('translation.loader.xliff'), service('translator')])->tag('translation.provider_factory')->set('translation.provider_factory.lokalise', LokaliseProviderFactory::class)->args([service('http_client'), service('logger'), param('kernel.default_locale'), service('translation.loader.xliff')])->tag('translation.provider_factory')->set('translation.provider_factory.phrase', PhraseProviderFactory::class)->args([service('http_client'), service('logger'), service('translation.loader.xliff'), service('translation.dumper.xliff'), service('cache.app'), param('kernel.default_locale')])->tag('translation.provider_factory');
};
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\DependencyInjection\Loader\Configurator;

use _ContaoManager\Symfony\Component\HttpKernel\Controller\ArgumentResolver\NotTaggedControllerValueResolver;
use _ContaoManager\Symfony\Component\HttpKernel\Controller\TraceableArgumentResolver;
use _ContaoManager\Symfony\Component\HttpKernel\Controller\TraceableControllerResolver;
use _ContaoManager\Symfony\Component\HttpKernel\Debug\TraceableEventDispatcher;
return static function (ContainerConfigurator $container) {
    $container->services()->set('debug.event_dispatcher', TraceableEventDispatcher::class)->decorate('event_dispatcher')->args([service('debug.event_dispatcher.inner'), service('debug.stopwatch'), service('logger')->nullOnInvalid(), service('.virtual_request_stack')->nullOnInvalid()])->tag('monolog.logger', ['channel' => 'event'])->tag('kernel.reset', ['method' => 'reset'])->set('debug.controller_resolver', TraceableControllerResolver::class)->decorate('controller_resolver')->args([service('debug.controller_resolver.inner'), service('debug.stopwatch')])->set('debug.argument_resolver', TraceableArgumentResolver::class)->decorate('argument_resolver')->args([service('debug.argument_resolver.inner'), service('debug.stopwatch')])->set('argument_resolver.not_tagged_controller', NotTaggedControllerValueResolver::class)->args([abstract_arg('Controller argument, set in FrameworkExtension')])->tag('controller.argument_value_resolver', ['priority' => -200]);
};
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\DependencyInjection\Loader\Configurator;

use _ContaoManager\Symfony\Component\Notifier\Bridge\Twilio\Webhook\TwilioRequestParser;
use _ContaoManager\Symfony\Component\Notifier\Bridge\Vonage\Webhook\VonageRequestParser;
return static function (ContainerConfigurator $container) {
    $container->services()->set('notifier.webhook.request_parser.twilio', TwilioRequestParser::class)->alias(TwilioRequestParser::class, 'notifier.webhook.request_parser.twilio')->set('notifier.webhook.request_parser.vonage', VonageRequestParser::class)->alias(VonageRequestParser::class, 'notifier.webhook.request_parser.vonage');
};
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\DependencyInjection\Loader\Configurator;

use _ContaoManager\Symfony\Component\HttpKernel\DependencyInjection\LazyLoadingFragmentHandler;
use _ContaoManager\Symfony\Component\HttpKernel\Fragment\EsiFragmentRenderer;
use _ContaoManager\Symfony\Component\HttpKernel\Fragment\FragmentUriGenerator;
use _ContaoManager\Symfony\Component\HttpKernel\Fragment\FragmentUriGeneratorInterface;
use _ContaoManager\Symfony\Component\HttpKernel\Fragment\HIncludeFragmentRenderer;
use _ContaoManager\Symfony\Component\HttpKernel\Fragment\InlineFragmentRenderer;
use _ContaoManager\Symfony\Component\HttpKernel\Fragment\SsiFragmentRenderer;
return static function (ContainerConfigurator $container) {
    $container->parameters()->set('fragment.renderer.hinclude.global_template', null)->set('fragment.path', '/_fragment');
    $container->services()->set('fragment.handler', LazyLoadingFragmentHandler::class)->args([abstract_arg('fragment renderer locator'), service('request_stack'), param('kernel.debug')])->set('fragment.uri_generator', FragmentUriGenerator::class)->args([param('fragment.path'), service('uri_signer'), service('request_stack')])->alias(FragmentUriGeneratorInterface::class, 'fragment.uri_generator')->set('fragment.renderer.inline', InlineFragmentRenderer::class)->args([service('http_kernel'), service('event_dispatcher')])->call('setFragmentPath', [param('fragment.path')])->tag('kernel.fragment_renderer', ['alias' => 'inline'])->set('fragment.renderer.hinclude', HIncludeFragmentRenderer::class)->args([service('twig')->nullOnInvalid(), service('uri_signer'), param('fragment.renderer.hinclude.global_template')])->call('setFragmentPath', [param('fragment.path')])->set('fragment.renderer.esi', EsiFragmentRenderer::class)->args([service('esi')->nullOnInvalid(), service('fragment.renderer.inline'), service('uri_signer')])->call('setFragmentPath', [param('fragment.path')])->tag('kernel.fragment_renderer', ['alias' => 'esi'])->set('fragment.renderer.ssi', SsiFragmentRenderer::class)->args([service('ssi')->nullOnInvalid(), service('fragment.renderer.inline'), service('uri_signer')])->call('setFragmentPath', [param('fragment.path')])->tag('kernel.fragment_renderer', ['alias' => 'ssi']);
};
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\DependencyInjection\Loader\Configurator;

use _ContaoManager\Symfony\Component\WebLink\EventListener\AddLinkHeaderListener;
use _ContaoManager\Symfony\Component\WebLink\HttpHeaderSerializer;
return static function (ContainerConfigurator $container) {
    $container->services()->set('web_link.http_header_serializer', HttpHeaderSerializer::class)->alias(HttpHeaderSerializer::class, 'web_link.http_header_serializer')->set('web_link.add_link_header_listener', AddLinkHeaderListener::class)->args([service('web_link.http_header_serializer')])->tag('kernel.event_subscriber');
};
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\DependencyInjection\Loader\Configurator;

use _ContaoManager\Psr\Container\ContainerInterface;
use _ContaoManager\Symfony\Bundle\FrameworkBundle\CacheWarmer\RouterCacheWarmer;
use _ContaoManager\Symfony\Bundle\FrameworkBundle\Controller\RedirectController;
use _ContaoManager\Symfony\Bundle\FrameworkBundle\Controller\TemplateController;
use _ContaoManager\Symfony\Bundle\FrameworkBundle\Routing\AttributeRouteControllerLoader;
use _ContaoManager\Symfony\Bundle\FrameworkBundle\Routing\DelegatingLoader;
use _ContaoManager\Symfony\Bundle\FrameworkBundle\Routing\RedirectableCompiledUrlMatcher;
use _ContaoManager\Symfony\Bundle\FrameworkBundle\Routing\Router;
use _ContaoManager\Symfony\Component\Config\Loader\LoaderResolver;
use _ContaoManager\Symfony\Component\HttpKernel\EventListener\RouterListener;
use _ContaoManager\Symfony\Component\Routing\Generator\CompiledUrlGenerator;
use _ContaoManager\Symfony\Component\Routing\Generator\Dumper\CompiledUrlGeneratorDumper;
use _ContaoManager\Symfony\Component\Routing\Generator\UrlGeneratorInterface;
use _ContaoManager\Symfony\Component\Routing\Loader\AttributeDirectoryLoader;
use _ContaoManager\Symfony\Component\Routing\Loader\AttributeFileLoader;
use _ContaoManager\Symfony\Component\Routing\Loader\ContainerLoader;
use _ContaoManager\Symfony\Component\Routing\Loader\DirectoryLoader;
use _ContaoManager\Symfony\Component\Routing\Loader\GlobFileLoader;
use _ContaoManager\Symfony\Component\Routing\Loader\PhpFileLoader;
use _ContaoManager\Symfony\Component\Routing\Loader\Psr4DirectoryLoader;
use _ContaoManager\Symfony\Component\Routing\Loader\XmlFileLoader;
use _ContaoManager\Symfony\Component\Routing\Loader\YamlFileLoader;
use _ContaoManager\Symfony\Component\Routing\Matcher\Dumper\CompiledUrlMatcherDumper;
use _ContaoManager\Symfony\Component\Routing\Matcher\ExpressionLanguageProvider;
use _ContaoManager\Symfony\Component\Routing\Matcher\UrlMatcherInterface;
use _ContaoManager\Symfony\Component\Routing\RequestContext;
use _ContaoManager\Symfony\Component\Routing\RequestContextAwareInterface;
use _ContaoManager\Symfony\Component\Routing\RouterInterface;
return static function (ContainerConfigurator $container) {
    $container->parameters()->set('router.request_context.host', 'localhost')->set('router.request_context.scheme', 'http')->set('router.request_context.base_url', '');
    $container->services()->set('routing.resolver', LoaderResolver::class)->set('routing.loader.xml', XmlFileLoader::class)->args([service('file_locator'), '%kernel.environment%'])->tag('routing.loader')->set('routing.loader.yml', YamlFileLoader::class)->args([service('file_locator'), '%kernel.environment%'])->tag('routing.loader')->set('routing.loader.php', PhpFileLoader::class)->args([service('file_locator'), '%kernel.environment%'])->tag('routing.loader')->set('routing.loader.glob', GlobFileLoader::class)->args([service('file_locator'), '%kernel.environment%'])->tag('routing.loader')->set('routing.loader.directory', DirectoryLoader::class)->args([service('file_locator'), '%kernel.environment%'])->tag('routing.loader')->set('routing.loader.container', ContainerLoader::class)->args([tagged_locator('routing.route_loader'), '%kernel.environment%'])->tag('routing.loader')->set('routing.loader.attribute', AttributeRouteControllerLoader::class)->args(['%kernel.environment%'])->tag('routing.loader', ['priority' => -10])->alias('routing.loader.annotation', 'routing.loader.attribute')->deprecate('symfony/routing', '6.4', 'The "%alias_id%" service is deprecated, use the "routing.loader.attribute" service instead.')->set('routing.loader.attribute.directory', AttributeDirectoryLoader::class)->args([service('file_locator'), service('routing.loader.attribute')])->tag('routing.loader', ['priority' => -10])->alias('routing.loader.annotation.directory', 'routing.loader.attribute.directory')->deprecate('symfony/routing', '6.4', 'The "%alias_id%" service is deprecated, use the "routing.loader.attribute.directory" service instead.')->set('routing.loader.attribute.file', AttributeFileLoader::class)->args([service('file_locator'), service('routing.loader.attribute')])->tag('routing.loader', ['priority' => -10])->alias('routing.loader.annotation.file', 'routing.loader.attribute.file')->deprecate('symfony/routing', '6.4', 'The "%alias_id%" service is deprecated, use the "routing.loader.attribute.file" service instead.')->set('routing.loader.psr4', Psr4DirectoryLoader::class)->args([service('file_locator')])->tag('routing.loader', ['priority' => -10])->set('routing.loader', DelegatingLoader::class)->public()->args([
        service('routing.resolver'),
        [],
        // Default options
        [],
    ])->set('router.default', Router::class)->args([service(ContainerInterface::class), param('router.resource'), ['cache_dir' => param('router.cache_dir'), 'debug' => param('kernel.debug'), 'generator_class' => CompiledUrlGenerator::class, 'generator_dumper_class' => CompiledUrlGeneratorDumper::class, 'matcher_class' => RedirectableCompiledUrlMatcher::class, 'matcher_dumper_class' => CompiledUrlMatcherDumper::class], service('router.request_context')->ignoreOnInvalid(), service('parameter_bag')->ignoreOnInvalid(), service('logger')->ignoreOnInvalid(), param('kernel.default_locale')])->call('setConfigCacheFactory', [service('config_cache_factory')])->tag('monolog.logger', ['channel' => 'router'])->tag('container.service_subscriber', ['id' => 'routing.loader'])->alias('router', 'router.default')->public()->alias(RouterInterface::class, 'router')->alias(UrlGeneratorInterface::class, 'router')->alias(UrlMatcherInterface::class, 'router')->alias(RequestContextAwareInterface::class, 'router')->set('router.request_context', RequestContext::class)->factory([RequestContext::class, 'fromUri'])->args([param('router.request_context.base_url'), param('router.request_context.host'), param('router.request_context.scheme'), param('request_listener.http_port'), param('request_listener.https_port')])->call('setParameter', ['_functions', service('router.expression_language_provider')->ignoreOnInvalid()])->alias(RequestContext::class, 'router.request_context')->set('router.expression_language_provider', ExpressionLanguageProvider::class)->args([tagged_locator('routing.expression_language_function', 'function')])->tag('routing.expression_language_provider')->set('router.cache_warmer', RouterCacheWarmer::class)->args([service(ContainerInterface::class)])->tag('container.service_subscriber', ['id' => 'router'])->tag('kernel.cache_warmer')->set('router_listener', RouterListener::class)->args([service('router'), service('request_stack'), service('router.request_context')->ignoreOnInvalid(), service('logger')->ignoreOnInvalid(), param('kernel.project_dir'), param('kernel.debug')])->tag('kernel.event_subscriber')->tag('monolog.logger', ['channel' => 'request'])->set(RedirectController::class)->public()->args([service('router'), inline_service('int')->factory([service('router.request_context'), 'getHttpPort']), inline_service('int')->factory([service('router.request_context'), 'getHttpsPort'])])->set(TemplateController::class)->args([service('twig')->ignoreOnInvalid()])->public();
};
<?xml version="1.0" encoding="UTF-8" ?>

<xsd:schema xmlns="http://symfony.com/schema/dic/symfony"
    xmlns:xsd="http://www.w3.org/2001/XMLSchema"
    targetNamespace="http://symfony.com/schema/dic/symfony"
    elementFormDefault="qualified">

    <xsd:element name="config" type="config" />

    <xsd:complexType name="config">
        <xsd:choice maxOccurs="unbounded">
            <xsd:element name="assets" type="assets" minOccurs="0" maxOccurs="1" />
            <xsd:element name="asset-mapper" type="asset_mapper" minOccurs="0" maxOccurs="1" />
            <xsd:element name="form" type="form" minOccurs="0" maxOccurs="1" />
            <xsd:element name="csrf-protection" type="csrf_protection" minOccurs="0" maxOccurs="1" />
            <xsd:element name="esi" type="esi" minOccurs="0" maxOccurs="1" />
            <xsd:element name="ssi" type="ssi" minOccurs="0" maxOccurs="1" />
            <xsd:element name="fragments" type="fragments" minOccurs="0" maxOccurs="1" />
            <xsd:element name="web-link" type="web_link" minOccurs="0" maxOccurs="1" />
            <xsd:element name="profiler" type="profiler" minOccurs="0" maxOccurs="1" />
            <xsd:element name="router" type="router" minOccurs="0" maxOccurs="1" />
            <xsd:element name="session" type="session" minOccurs="0" maxOccurs="1" />
            <xsd:element name="request" type="request" minOccurs="0" maxOccurs="1" />
            <xsd:element name="translator" type="translator" minOccurs="0" maxOccurs="1" />
            <xsd:element name="validation" type="validation" minOccurs="0" maxOccurs="1" />
            <xsd:element name="annotations" type="annotations" minOccurs="0" maxOccurs="1" />
            <xsd:element name="property-access" type="property_access" minOccurs="0" maxOccurs="1" />
            <xsd:element name="scheduler" type="scheduler" minOccurs="0" maxOccurs="1" />
            <xsd:element name="serializer" type="serializer" minOccurs="0" maxOccurs="1" />
            <xsd:element name="property-info" type="property_info" minOccurs="0" maxOccurs="1" />
            <xsd:element name="cache" type="cache" minOccurs="0" maxOccurs="1" />
            <xsd:element name="workflow" type="workflow" minOccurs="0" maxOccurs="unbounded" />
            <xsd:element name="php-errors" type="php-errors" minOccurs="0" maxOccurs="1" />
            <xsd:element name="exceptions" type="exceptions" minOccurs="0" maxOccurs="1" />
            <xsd:element name="exception" type="new-exception" minOccurs="0" maxOccurs="unbounded" />
            <xsd:element name="lock" type="lock" minOccurs="0" maxOccurs="1" />
            <xsd:element name="semaphore" type="semaphore" minOccurs="0" maxOccurs="1" />
            <xsd:element name="messenger" type="messenger" minOccurs="0" maxOccurs="1" />
            <xsd:element name="http-client" type="http_client" minOccurs="0" maxOccurs="1" />
            <xsd:element name="mailer" type="mailer" minOccurs="0" maxOccurs="1" />
            <xsd:element name="http-cache" type="http_cache" minOccurs="0" maxOccurs="1" />
            <xsd:element name="rate-limiter" type="rate_limiter" minOccurs="0" maxOccurs="1" />
            <xsd:element name="uid" type="uid" minOccurs="0" maxOccurs="1" />
            <xsd:element name="notifier" type="notifier" minOccurs="0" maxOccurs="1" />
            <xsd:element name="html-sanitizer" type="html-sanitizer" minOccurs="0" maxOccurs="1" />
            <xsd:element name="enabled-locale" type="xsd:string" minOccurs="0" maxOccurs="unbounded" />
            <xsd:element name="webhook" type="webhook" minOccurs="0" maxOccurs="1" />
            <xsd:element name="remote-event" type="remote-event" minOccurs="0" maxOccurs="1" />
        </xsd:choice>

        <xsd:attribute name="http-method-override" type="xsd:boolean" />
        <xsd:attribute name="handle-all-throwables" type="xsd:boolean" />
        <xsd:attribute name="trust-x-sendfile-type-header" type="xsd:boolean" />
        <xsd:attribute name="ide" type="xsd:string" />
        <xsd:attribute name="secret" type="xsd:string" />
        <xsd:attribute name="default-locale" type="xsd:string" />
        <xsd:attribute name="set_locale_from_accept_language" type="xsd:boolean" />
        <xsd:attribute name="set_content_language_from_locale" type="xsd:boolean" />
        <xsd:attribute name="test" type="xsd:boolean" />
        <xsd:attribute name="error-controller" type="xsd:string" />
        <xsd:attribute name="trusted-hosts" type="xsd:string" />
        <xsd:attribute name="trusted-proxies" type="xsd:string" />
        <xsd:attribute name="trusted-headers" type="xsd:string" />
    </xsd:complexType>

    <xsd:complexType name="form">
        <xsd:all>
            <xsd:element name="csrf-protection" type="form_csrf_protection" minOccurs="0" maxOccurs="1" />
        </xsd:all>
        <xsd:attribute name="enabled" type="xsd:boolean" />
        <xsd:attribute name="legacy-error-messages" type="xsd:boolean" />
    </xsd:complexType>

    <xsd:complexType name="form_csrf_protection">
        <xsd:attribute name="enabled" type="xsd:boolean" />
        <xsd:attribute name="field-name" type="xsd:string" />
    </xsd:complexType>

    <xsd:complexType name="csrf_protection">
        <xsd:attribute name="enabled" type="xsd:boolean" />
    </xsd:complexType>

    <xsd:complexType name="esi">
        <xsd:attribute name="enabled" type="xsd:boolean" />
    </xsd:complexType>

    <xsd:complexType name="ssi">
        <xsd:attribute name="enabled" type="xsd:boolean" />
    </xsd:complexType>

    <xsd:complexType name="fragments">
        <xsd:attribute name="enabled" type="xsd:boolean" />
        <xsd:attribute name="path" type="xsd:string" />
        <xsd:attribute name="hinclude-default-template" type="xsd:string" />
    </xsd:complexType>

    <xsd:complexType name="web_link">
        <xsd:attribute name="enabled" type="xsd:boolean" />
    </xsd:complexType>

    <xsd:complexType name="profiler">
        <xsd:attribute name="collect" type="xsd:string" />
        <xsd:attribute name="collect-parameter" type="xsd:string" />
        <xsd:attribute name="only-exceptions" type="xsd:string" />
        <xsd:attribute name="only-main-requests" type="xsd:string" />
        <xsd:attribute name="only-master-requests" type="xsd:string" />
        <xsd:attribute name="enabled" type="xsd:string" />
        <xsd:attribute name="dsn" type="xsd:string" />
        <xsd:attribute name="username" type="xsd:string" />
        <xsd:attribute name="password" type="xsd:string" />
        <xsd:attribute name="lifetime" type="xsd:string" />
        <xsd:attribute name="collect-serializer-data" type="xsd:boolean" />
    </xsd:complexType>

    <xsd:complexType name="router">
        <xsd:attribute name="resource" type="xsd:string" />
        <xsd:attribute name="type" type="xsd:string" />
        <xsd:attribute name="http-port" type="xsd:string" />
        <xsd:attribute name="https-port" type="xsd:string" />
        <xsd:attribute name="strict-requirements" type="xsd:string" />
        <xsd:attribute name="utf8" type="xsd:boolean" />
        <xsd:attribute name="default-uri" type="xsd:string" />
        <xsd:attribute name="cache-dir" type="xsd:string" />
    </xsd:complexType>

    <xsd:complexType name="session">
        <xsd:attribute name="enabled" type="xsd:boolean" />
        <xsd:attribute name="storage-factory-id" type="xsd:string" />
        <xsd:attribute name="storage-id" type="xsd:string" />
        <xsd:attribute name="handler-id" type="xsd:string" />
        <xsd:attribute name="name" type="xsd:string" />
        <xsd:attribute name="cookie-lifetime" type="xsd:string" />
        <xsd:attribute name="cookie-path" type="xsd:string" />
        <xsd:attribute name="cookie-domain" type="xsd:string" />
        <xsd:attribute name="cookie-secure" type="cookie_secure" />
        <xsd:attribute name="cookie-httponly" type="xsd:boolean" />
        <xsd:attribute name="cookie-samesite" type="cookie_samesite" />
        <xsd:attribute name="use-cookies" type="xsd:boolean" />
        <xsd:attribute name="cache-limiter" type="xsd:string" />
        <xsd:attribute name="gc-maxlifetime" type="xsd:string" />
        <xsd:attribute name="gc-divisor" type="xsd:string" />
        <xsd:attribute name="gc-probability" type="xsd:string" />
        <xsd:attribute name="save-path" type="xsd:string" />
        <xsd:attribute name="metadata-update-threshold" type="xsd:nonNegativeInteger" />
        <xsd:attribute name="sid-length" type="sid_length" />
        <xsd:attribute name="sid-bits-per-character" type="sid_bits_per_character" />
    </xsd:complexType>

    <xsd:complexType name="request">
        <xsd:sequence>
            <xsd:element name="format" type="format" minOccurs="0" maxOccurs="unbounded" />
        </xsd:sequence>
    </xsd:complexType>

    <xsd:complexType name="format">
        <xsd:choice minOccurs="1" maxOccurs="unbounded">
            <xsd:element name="mime-type" type="xsd:string" />
        </xsd:choice>
        <xsd:attribute name="name" type="xsd:string" use="required"/>
    </xsd:complexType>

    <xsd:complexType name="assets">
        <xsd:sequence>
            <xsd:element name="base-url" type="xsd:string" minOccurs="0" maxOccurs="unbounded" />
            <xsd:element name="package" type="package" minOccurs="0" maxOccurs="unbounded" />
        </xsd:sequence>

        <xsd:attribute name="enabled" type="xsd:boolean" />
        <xsd:attribute name="base-path" type="xsd:string" />
        <xsd:attribute name="version-strategy" type="xsd:string" />
        <xsd:attribute name="version" type="xsd:string" />
        <xsd:attribute name="version-format" type="xsd:string" />
        <xsd:attribute name="json-manifest-path" type="xsd:string" />
        <xsd:attribute name="strict-mode" type="xsd:boolean" />
    </xsd:complexType>

    <xsd:complexType name="package">
        <xsd:sequence>
            <xsd:element name="base-url" type="xsd:string" minOccurs="0" maxOccurs="unbounded" />
        </xsd:sequence>

        <xsd:attribute name="name" type="xsd:string" use="required" />
        <xsd:attribute name="base-path" type="xsd:string" />
        <xsd:attribute name="version-strategy" type="xsd:string" />
        <xsd:attribute name="version" type="xsd:string" />
        <xsd:attribute name="version-format" type="xsd:string" />
        <xsd:attribute name="json-manifest-path" type="xsd:string" />
        <xsd:attribute name="strict-mode" type="xsd:boolean" />
    </xsd:complexType>

    <xsd:complexType name="asset_mapper">
        <xsd:sequence>
            <xsd:element name="path" type="asset_mapper_path" minOccurs="0" maxOccurs="unbounded" />
            <xsd:element name="excluded-pattern" type="xsd:string" minOccurs="0" maxOccurs="unbounded" />
            <xsd:element name="extension" type="asset_mapper_extension" minOccurs="0" maxOccurs="unbounded" />
            <xsd:element name="importmap-script-attribute" type="asset_mapper_attribute" minOccurs="0" maxOccurs="unbounded" />
        </xsd:sequence>
        <xsd:attribute name="enabled" type="xsd:boolean" />
        <xsd:attribute name="exclude-dotfiles" type="xsd:boolean" />
        <xsd:attribute name="server" type="xsd:boolean" />
        <xsd:attribute name="public-prefix" type="xsd:string" />
        <xsd:attribute name="missing-import-mode" type="missing-import-mode" />
        <xsd:attribute name="importmap-path" type="xsd:string" />
        <xsd:attribute name="importmap-polyfill" type="xsd:string" />
        <xsd:attribute name="vendor-dir" type="xsd:string" />
        <xsd:attribute name="provider" type="xsd:string" />
    </xsd:complexType>

    <xsd:complexType name="asset_mapper_path" mixed="true">
        <xsd:attribute name="namespace" type="xsd:string" />
    </xsd:complexType>

    <xsd:complexType name="asset_mapper_extension" mixed="true">
        <xsd:attribute name="extension" type="xsd:string" use="required" />
    </xsd:complexType>

    <xsd:complexType name="asset_mapper_attribute" mixed="true">
        <xsd:attribute name="key" type="xsd:string" use="required" />
    </xsd:complexType>

    <xsd:simpleType name="missing-import-mode">
        <xsd:restriction base="xsd:string">
            <xsd:enumeration value="strict" />
            <xsd:enumeration value="warn" />
            <xsd:enumeration value="ignore" />
        </xsd:restriction>
    </xsd:simpleType>

    <xsd:complexType name="translator">
        <xsd:sequence>
            <xsd:element name="fallback" type="xsd:string" minOccurs="0" maxOccurs="unbounded" />
            <xsd:element name="path" type="xsd:string" minOccurs="0" maxOccurs="unbounded" />
            <xsd:element name="pseudo-localization" type="pseudo_localization" minOccurs="0" maxOccurs="1" />
            <xsd:element name="provider" type="translation_provider" minOccurs="0" maxOccurs="unbounded" />
        </xsd:sequence>
        <xsd:attribute name="enabled" type="xsd:boolean" />
        <xsd:attribute name="fallback" type="xsd:string" />
        <xsd:attribute name="logging" type="xsd:boolean" />
        <xsd:attribute name="formatter" type="xsd:string" />
        <xsd:attribute name="cache-dir" type="xsd:string" />
        <xsd:attribute name="default-path" type="xsd:string" />
    </xsd:complexType>

    <xsd:complexType name="pseudo_localization">
        <xsd:sequence>
            <xsd:element name="localizable-html-attribute" type="xsd:string" minOccurs="0" maxOccurs="unbounded" />
        </xsd:sequence>
        <xsd:attribute name="enabled" type="xsd:boolean" />
        <xsd:attribute name="accents" type="xsd:boolean" />
        <xsd:attribute name="expansion_factor" type="xsd:float" />
        <xsd:attribute name="brackets" type="xsd:boolean" />
        <xsd:attribute name="parse_html" type="xsd:boolean" />
    </xsd:complexType>

    <xsd:complexType name="translation_provider">
        <xsd:sequence>
            <xsd:element name="domain" type="xsd:string" minOccurs="0" maxOccurs="unbounded" />
            <xsd:element name="locale" type="xsd:string" minOccurs="0" maxOccurs="unbounded" />
        </xsd:sequence>
        <xsd:attribute name="name" type="xsd:string" />
        <xsd:attribute name="dsn" type="xsd:string" />
    </xsd:complexType>

    <xsd:complexType name="validation">
        <xsd:choice minOccurs="0" maxOccurs="unbounded">
            <xsd:element name="static-method" type="xsd:string" />
            <xsd:element name="mapping" type="file_mapping" />
            <xsd:element name="auto-mapping" type="auto_mapping" />
            <xsd:element name="not-compromised-password" type="not-compromised-password" />
        </xsd:choice>

        <xsd:attribute name="enabled" type="xsd:boolean" />
        <xsd:attribute name="cache" type="xsd:string" />
        <xsd:attribute name="enable-annotations" type="xsd:boolean" />
        <xsd:attribute name="enable-attributes" type="xsd:boolean" />
        <xsd:attribute name="static-method" type="xsd:boolean" />
        <xsd:attribute name="translation-domain" type="xsd:string" />
        <xsd:attribute name="strict-email" type="xsd:boolean" />
        <xsd:attribute name="email-validation-mode" type="email-validation-mode" />
    </xsd:complexType>

    <xsd:complexType name="file_mapping">
        <xsd:sequence>
            <xsd:element name="path" type="xsd:string" minOccurs="1" maxOccurs="unbounded" />
        </xsd:sequence>
    </xsd:complexType>

    <xsd:complexType name="auto_mapping">
        <xsd:sequence>
            <xsd:element name="service" type="xsd:string" minOccurs="0" maxOccurs="unbounded" />
        </xsd:sequence>
        <xsd:attribute name="namespace" type="xsd:string" use="required" />
    </xsd:complexType>

    <xsd:simpleType name="email-validation-mode">
        <xsd:restriction base="xsd:string">
            <xsd:enumeration value="html5" />
            <xsd:enumeration value="html5-allow-no-tld" />
            <xsd:enumeration value="loose" />
            <xsd:enumeration value="strict" />
        </xsd:restriction>
    </xsd:simpleType>

    <xsd:complexType name="not-compromised-password">
        <xsd:attribute name="enabled" type="xsd:boolean" />
        <xsd:attribute name="endpoint" type="xsd:string" />
    </xsd:complexType>

    <xsd:complexType name="annotations">
        <xsd:attribute name="cache" type="xsd:string" />
        <xsd:attribute name="debug" type="xsd:string" />
        <xsd:attribute name="file-cache-dir" type="xsd:string" />
        <xsd:attribute name="enabled" type="xsd:boolean" />
    </xsd:complexType>

    <xsd:complexType name="property_access">
        <xsd:attribute name="magic-call" type="xsd:boolean" />
        <xsd:attribute name="magic-get" type="xsd:boolean" />
        <xsd:attribute name="magic-set" type="xsd:boolean" />
        <xsd:attribute name="throw-exception-on-invalid-index" type="xsd:boolean" />
        <xsd:attribute name="throw-exception-on-invalid-property-path" type="xsd:boolean" />
    </xsd:complexType>

    <xsd:complexType name="scheduler">
        <xsd:attribute name="enabled" type="xsd:boolean" />
    </xsd:complexType>

    <xsd:complexType name="serializer">
        <xsd:choice minOccurs="0" maxOccurs="unbounded">
            <xsd:element name="mapping" type="file_mapping" />
            <xsd:element name="default-context" type="metadata" minOccurs="0" maxOccurs="1" />
        </xsd:choice>
        <xsd:attribute name="enabled" type="xsd:boolean" />
        <xsd:attribute name="enable-annotations" type="xsd:boolean" />
        <xsd:attribute name="enable-attributes" type="xsd:boolean" />
        <xsd:attribute name="name-converter" type="xsd:string" />
        <xsd:attribute name="circular-reference-handler" type="xsd:string" />
        <xsd:attribute name="max-depth-handler" type="xsd:string" />
    </xsd:complexType>

    <xsd:complexType name="property_info">
        <xsd:attribute name="enabled" type="xsd:boolean" />
    </xsd:complexType>

    <xsd:complexType name="cache">
        <xsd:sequence>
            <xsd:element name="app" type="xsd:string" minOccurs="0" maxOccurs="1" />
            <xsd:element name="system" type="xsd:string" minOccurs="0" maxOccurs="1" />
            <xsd:element name="directory" type="xsd:string" minOccurs="0" maxOccurs="1" />
            <xsd:element name="default-doctrine-provider" type="xsd:string" minOccurs="0" maxOccurs="1" />
            <xsd:element name="default-psr6-provider" type="xsd:string" minOccurs="0" maxOccurs="1" />
            <xsd:element name="default-redis-provider" type="xsd:string" minOccurs="0" maxOccurs="1" />
            <xsd:element name="default-memcached-provider" type="xsd:string" minOccurs="0" maxOccurs="1" />
            <xsd:element name="default-pdo-provider" type="xsd:string" minOccurs="0" maxOccurs="1" />
            <xsd:element name="pool" type="cache_pool" minOccurs="0" maxOccurs="unbounded" />
        </xsd:sequence>
        <xsd:attribute name="app" type="xsd:string" />
        <xsd:attribute name="system" type="xsd:string" />
        <xsd:attribute name="directory" type="xsd:string" />
        <xsd:attribute name="default-doctrine-provider" type="xsd:string" />
        <xsd:attribute name="default-psr6-provider" type="xsd:string" />
        <xsd:attribute name="default-redis-provider" type="xsd:string" />
        <xsd:attribute name="default-memcached-provider" type="xsd:string" />
        <xsd:attribute name="default-pdo-provider" type="xsd:string" />
        <xsd:attribute name="default-doctrine-dbal-provider" type="xsd:string" />
        <xsd:attribute name="prefix-seed" type="xsd:string" />
    </xsd:complexType>

    <xsd:complexType name="cache_pool">
        <xsd:sequence>
            <xsd:element name="adapter" type="cache_pool_adapter" minOccurs="0" maxOccurs="unbounded" />
        </xsd:sequence>

        <xsd:attribute name="name" type="xsd:string" use="required" />
        <xsd:attribute name="adapter" type="xsd:string" />
        <xsd:attribute name="tags" type="xsd:string" />
        <xsd:attribute name="public" type="xsd:boolean" />
        <xsd:attribute name="default-lifetime" type="xsd:string" />
        <xsd:attribute name="provider" type="xsd:string" />
        <xsd:attribute name="early-expiration-message-bus" type="xsd:string" />
        <xsd:attribute name="clearer" type="xsd:string" />
    </xsd:complexType>

    <xsd:complexType name="cache_pool_adapter">
        <xsd:attribute name="name" type="xsd:string" use="required" />
        <xsd:attribute name="provider" type="xsd:string" />
    </xsd:complexType>

    <xsd:complexType name="workflow">
        <xsd:sequence>
            <xsd:element name="audit-trail" type="audit_trail" minOccurs="0" maxOccurs="1" />
            <xsd:element name="initial-marking" type="xsd:string" minOccurs="0" maxOccurs="unbounded" />
            <xsd:element name="marking-store" type="marking_store" minOccurs="0" maxOccurs="1" />
            <xsd:element name="support" type="xsd:string" minOccurs="0" maxOccurs="unbounded" />
            <xsd:element name="event-to-dispatch" type="event_to_dispatch" minOccurs="0" maxOccurs="unbounded" />
            <xsd:element name="place" type="place" minOccurs="0" maxOccurs="unbounded" />
            <xsd:element name="transition" type="transition" minOccurs="0" maxOccurs="unbounded" />
            <xsd:element name="metadata" type="metadata" minOccurs="0" maxOccurs="unbounded" />
        </xsd:sequence>
        <xsd:attribute name="name" type="xsd:string" />
        <xsd:attribute name="type" type="workflow_type" />
        <xsd:attribute name="initial-place" type="xsd:string" />
        <xsd:attribute name="initial-marking" type="xsd:string" />
        <xsd:attribute name="support-strategy" type="xsd:string" />
        <xsd:attribute name="enabled" type="xsd:boolean" />
    </xsd:complexType>

    <xsd:complexType name="php-errors">
        <xsd:sequence>
            <xsd:element name="log" type="logLevel" minOccurs="0" maxOccurs="unbounded" />
        </xsd:sequence>
        <xsd:attribute name="log" type="xsd:string" />
        <xsd:attribute name="throw" type="xsd:boolean" />
    </xsd:complexType>

    <xsd:complexType name="logLevel" mixed="true">
        <xsd:attribute name="type" type="xsd:string" use="required" />
        <xsd:attribute name="logLevel" type="xsd:string" />
    </xsd:complexType>

    <xsd:complexType name="audit_trail">
        <xsd:attribute name="enabled" type="xsd:boolean" />
    </xsd:complexType>

    <xsd:complexType name="exceptions">
        <xsd:sequence>
            <xsd:element name="exception" type="old-exception" minOccurs="0" maxOccurs="unbounded" />
        </xsd:sequence>
    </xsd:complexType>

    <xsd:complexType name="exception" abstract="true">
        <xsd:attribute name="log-level" type="xsd:string" />
        <xsd:attribute name="status-code" type="xsd:integer" />
    </xsd:complexType>

    <xsd:complexType name="old-exception">
        <xsd:complexContent>
            <xsd:extension base="exception">
                <xsd:attribute name="name" type="xsd:string" use="required" />
            </xsd:extension>
        </xsd:complexContent>
    </xsd:complexType>

    <xsd:complexType name="new-exception">
        <xsd:complexContent>
            <xsd:extension base="exception">
                <xsd:attribute name="class" type="xsd:string" use="required" />
            </xsd:extension>
        </xsd:complexContent>
    </xsd:complexType>

    <xsd:complexType name="marking_store">
        <xsd:sequence>
            <xsd:element name="argument" type="xsd:string" minOccurs="0" maxOccurs="unbounded" />
        </xsd:sequence>
        <xsd:attribute name="type" type="marking_store_type" />
        <xsd:attribute name="service" type="xsd:string" />
        <xsd:attribute name="property" type="xsd:string" />
    </xsd:complexType>

    <xsd:simpleType name="marking_store_type">
        <xsd:restriction base="xsd:string">
            <xsd:enumeration value="method" />
        </xsd:restriction>
    </xsd:simpleType>

    <xsd:complexType name="transition">
        <xsd:sequence>
            <xsd:element name="from" type="xsd:string" minOccurs="1" maxOccurs="unbounded" />
            <xsd:element name="to" type="xsd:string" minOccurs="1" maxOccurs="unbounded" />
            <xsd:element name="metadata" type="metadata" minOccurs="0" maxOccurs="unbounded" />
            <xsd:element name="guard" type="xsd:string" minOccurs="0" maxOccurs="unbounded" />
        </xsd:sequence>
        <xsd:attribute name="name" type="xsd:string" />
        <xsd:attribute name="key" type="xsd:string" />
    </xsd:complexType>

    <xsd:complexType name="place" mixed="true">
        <xsd:sequence>
            <xsd:element name="metadata" type="metadata" minOccurs="0" maxOccurs="unbounded" />
        </xsd:sequence>
        <xsd:attribute name="name" type="xsd:string" />
    </xsd:complexType>

    <xsd:complexType name="metadata">
        <xsd:sequence>
            <xsd:any minOccurs="0" maxOccurs="unbounded" processContents="lax"/>
        </xsd:sequence>
        <xsd:attribute name="key" type="xsd:string" />
    </xsd:complexType>

    <xsd:simpleType name="event_to_dispatch">
        <xsd:restriction base="xsd:string">
            <xsd:enumeration value="" />
            <xsd:enumeration value="workflow.leave" />
            <xsd:enumeration value="workflow.transition" />
            <xsd:enumeration value="workflow.enter" />
            <xsd:enumeration value="workflow.entered" />
            <xsd:enumeration value="workflow.completed" />
            <xsd:enumeration value="workflow.announce" />
        </xsd:restriction>
    </xsd:simpleType>

    <xsd:simpleType name="default_middleware_attr">
        <xsd:restriction base="xsd:string">
            <xsd:enumeration value="true" />
            <xsd:enumeration value="false" />
            <xsd:enumeration value="1" />
            <xsd:enumeration value="0" />
            <xsd:enumeration value="allow_no_handlers" />
        </xsd:restriction>
    </xsd:simpleType>

    <xsd:complexType name="default_middleware_elem">
        <xsd:attribute name="enabled" type="xsd:boolean" />
        <xsd:attribute name="allow_no_handlers" type="xsd:boolean" />
        <xsd:attribute name="allow_no_senders" type="xsd:boolean" />
    </xsd:complexType>

    <xsd:simpleType name="cookie_secure">
        <xsd:restriction base="xsd:string">
            <xsd:enumeration value="true" />
            <xsd:enumeration value="false" />
            <xsd:enumeration value="1" />
            <xsd:enumeration value="0" />
            <xsd:enumeration value="auto" />
        </xsd:restriction>
    </xsd:simpleType>

    <xsd:simpleType name="cookie_samesite">
        <xsd:restriction base="xsd:string">
            <xsd:enumeration value="" />
            <xsd:enumeration value="none" />
            <xsd:enumeration value="lax" />
            <xsd:enumeration value="strict" />
        </xsd:restriction>
    </xsd:simpleType>

    <xsd:simpleType name="sid_bits_per_character">
        <xsd:restriction base="xsd:positiveInteger">
            <xsd:enumeration value="4" />
            <xsd:enumeration value="5" />
            <xsd:enumeration value="6" />
        </xsd:restriction>
    </xsd:simpleType>

    <xsd:simpleType name="sid_length">
        <xsd:restriction base="xsd:positiveInteger">
            <xsd:minInclusive value="22" />
            <xsd:maxInclusive value="256" />
        </xsd:restriction>
    </xsd:simpleType>

    <xsd:simpleType name="workflow_type">
        <xsd:restriction base="xsd:string">
            <xsd:enumeration value="state_machine" />
            <xsd:enumeration value="workflow" />
        </xsd:restriction>
    </xsd:simpleType>

    <xsd:complexType name="lock">
        <xsd:sequence>
            <xsd:element name="resource" type="lock_resource" minOccurs="0" maxOccurs="unbounded" />
        </xsd:sequence>
        <xsd:attribute name="enabled" type="xsd:boolean" />
    </xsd:complexType>

    <xsd:complexType name="lock_resource">
        <xsd:simpleContent>
            <xsd:extension base="xsd:string">
                <xsd:attribute name="name" type="xsd:string" />
            </xsd:extension>
        </xsd:simpleContent>
    </xsd:complexType>

    <xsd:complexType name="semaphore">
        <xsd:sequence>
            <xsd:element name="resource" type="semaphore_resource" minOccurs="1" maxOccurs="unbounded" />
        </xsd:sequence>
        <xsd:attribute name="enabled" type="xsd:boolean" />
    </xsd:complexType>

    <xsd:complexType name="semaphore_resource">
        <xsd:simpleContent>
            <xsd:extension base="xsd:string">
                <xsd:attribute name="name" type="xsd:string" />
            </xsd:extension>
        </xsd:simpleContent>
    </xsd:complexType>

    <xsd:complexType name="messenger">
        <xsd:sequence>
            <xsd:element name="serializer" type="messenger_serializer" minOccurs="0" />
            <xsd:element name="routing" type="messenger_routing" minOccurs="0" maxOccurs="unbounded" />
            <xsd:element name="transport" type="messenger_transport" minOccurs="0" maxOccurs="unbounded" />
            <xsd:element name="bus" type="messenger_bus" minOccurs="0" maxOccurs="unbounded" />
        </xsd:sequence>
        <xsd:attribute name="default-bus" type="xsd:string" />
        <xsd:attribute name="enabled" type="xsd:boolean" />
        <xsd:attribute name="failure-transport" type="xsd:string" />
        <xsd:attribute name="reset-on-message" type="xsd:boolean" />
    </xsd:complexType>

    <xsd:complexType name="messenger_serializer">
        <xsd:sequence>
            <xsd:element name="symfony-serializer" type="messenger_symfony_serializer" minOccurs="0" />
        </xsd:sequence>
        <xsd:attribute name="default-serializer" type="xsd:string" />
    </xsd:complexType>

    <xsd:complexType name="messenger_symfony_serializer">
        <xsd:sequence>
            <xsd:element name="context" type="metadata" minOccurs="0" maxOccurs="unbounded" />
        </xsd:sequence>
        <xsd:attribute name="format" type="xsd:string" />
    </xsd:complexType>

    <xsd:complexType name="messenger_routing">
        <xsd:choice minOccurs="0" maxOccurs="unbounded">
            <xsd:element name="sender" type="messenger_routing_sender" />
        </xsd:choice>
        <xsd:attribute name="message-class" type="xsd:string" use="required"/>
    </xsd:complexType>

    <xsd:complexType name="messenger_routing_sender">
        <xsd:attribute name="service" type="xsd:string" use="required"/>
    </xsd:complexType>

    <xsd:complexType name="messenger_transport">
        <xsd:sequence>
            <xsd:element name="options" type="metadata" minOccurs="0" maxOccurs="unbounded" />
            <xsd:element name="retry-strategy" type="messenger_retry_strategy" minOccurs="0" maxOccurs="1" />
        </xsd:sequence>
        <xsd:attribute name="name" type="xsd:string" />
        <xsd:attribute name="serializer" type="xsd:string" />
        <xsd:attribute name="dsn" type="xsd:string" />
        <xsd:attribute name="failure-transport" type="xsd:string" />
        <xsd:attribute name="rate-limiter" type="xsd:string" />
    </xsd:complexType>

    <xsd:complexType name="messenger_retry_strategy">
        <xsd:attribute name="service" type="xsd:string" />
        <xsd:attribute name="max-retries" type="xsd:integer" />
        <xsd:attribute name="delay" type="xsd:integer" />
        <xsd:attribute name="multiplier" type="xsd:float" />
        <xsd:attribute name="max-delay" type="xsd:float" />
    </xsd:complexType>

    <xsd:complexType name="messenger_bus">
        <xsd:sequence>
            <xsd:element name="default-middleware" type="default_middleware_elem" minOccurs="0" maxOccurs="unbounded"/>
            <xsd:element name="middleware" type="messenger_middleware" minOccurs="0" maxOccurs="unbounded" />
        </xsd:sequence>
        <xsd:attribute name="name" type="xsd:string" use="required"/>
        <xsd:attribute name="default-middleware" type="default_middleware_attr"/>
    </xsd:complexType>

    <xsd:complexType name="messenger_middleware">
        <xsd:sequence>
            <xsd:element name="argument" type="xsd:anyType" minOccurs="0" maxOccurs="unbounded" />
        </xsd:sequence>
        <xsd:attribute name="id" type="xsd:string" use="required"/>
    </xsd:complexType>

    <xsd:complexType name="http_client">
        <xsd:sequence>
            <xsd:element name="default-options" type="http_client_default_options" minOccurs="0" />
            <xsd:element name="scoped-client" type="http_client_scope_options" minOccurs="0" maxOccurs="unbounded" />
        </xsd:sequence>
        <xsd:attribute name="enabled" type="xsd:boolean" />
        <xsd:attribute name="max-host-connections" type="xsd:integer" />
        <xsd:attribute name="mock-response-factory" type="xsd:string" />
    </xsd:complexType>

    <xsd:complexType name="http_client_default_options" mixed="true">
        <xsd:choice maxOccurs="unbounded">
            <xsd:element name="resolve" type="http_resolve" minOccurs="0" maxOccurs="unbounded" />
            <xsd:element name="header" type="http_header" minOccurs="0" maxOccurs="unbounded" />
            <xsd:element name="peer-fingerprint" type="fingerprint" minOccurs="0" maxOccurs="unbounded" />
            <xsd:element name="retry-failed" type="http_client_retry_failed" minOccurs="0" maxOccurs="1" />
            <xsd:element name="extra" type="xsd:anyType" minOccurs="0" maxOccurs="unbounded" />
        </xsd:choice>
        <xsd:attribute name="max-redirects" type="xsd:integer" />
        <xsd:attribute name="http-version" type="xsd:string" />
        <xsd:attribute name="proxy" type="xsd:string" />
        <xsd:attribute name="no-proxy" type="xsd:string" />
        <xsd:attribute name="timeout" type="xsd:float" />
        <xsd:attribute name="max-duration" type="xsd:float" />
        <xsd:attribute name="bindto" type="xsd:string" />
        <xsd:attribute name="verify-peer" type="xsd:boolean" />
        <xsd:attribute name="verify-host" type="xsd:boolean" />
        <xsd:attribute name="cafile" type="xsd:string" />
        <xsd:attribute name="capath" type="xsd:string" />
        <xsd:attribute name="local-cert" type="xsd:string" />
        <xsd:attribute name="local-pk" type="xsd:string" />
        <xsd:attribute name="passphrase" type="xsd:string" />
        <xsd:attribute name="ciphers" type="xsd:string" />
    </xsd:complexType>

    <xsd:complexType name="http_client_scope_options" mixed="true">
        <xsd:choice maxOccurs="unbounded">
            <xsd:element name="query" type="http_query" minOccurs="0" maxOccurs="unbounded" />
            <xsd:element name="resolve" type="http_resolve" minOccurs="0" maxOccurs="unbounded" />
            <xsd:element name="header" type="http_header" minOccurs="0" maxOccurs="unbounded" />
            <xsd:element name="peer-fingerprint" type="fingerprint" minOccurs="0" maxOccurs="unbounded" />
            <xsd:element name="retry-failed" type="http_client_retry_failed" minOccurs="0" maxOccurs="1" />
            <xsd:element name="extra" type="xsd:anyType" minOccurs="0" maxOccurs="unbounded" />
        </xsd:choice>
        <xsd:attribute name="name" type="xsd:string" />
        <xsd:attribute name="scope" type="xsd:string" />
        <xsd:attribute name="base-uri" type="xsd:string" />
        <xsd:attribute name="auth-basic" type="xsd:string" />
        <xsd:attribute name="auth-bearer" type="xsd:string" />
        <xsd:attribute name="max-redirects" type="xsd:integer" />
        <xsd:attribute name="http-version" type="xsd:string" />
        <xsd:attribute name="proxy" type="xsd:string" />
        <xsd:attribute name="no-proxy" type="xsd:string" />
        <xsd:attribute name="timeout" type="xsd:float" />
        <xsd:attribute name="bindto" type="xsd:string" />
        <xsd:attribute name="verify-peer" type="xsd:boolean" />
        <xsd:attribute name="verify-host" type="xsd:boolean" />
        <xsd:attribute name="cafile" type="xsd:string" />
        <xsd:attribute name="capath" type="xsd:string" />
        <xsd:attribute name="local-cert" type="xsd:string" />
        <xsd:attribute name="local-pk" type="xsd:string" />
        <xsd:attribute name="passphrase" type="xsd:string" />
        <xsd:attribute name="ciphers" type="xsd:string" />
    </xsd:complexType>

    <xsd:complexType name="fingerprint">
        <xsd:choice maxOccurs="unbounded">
            <xsd:element name="pin-sha256" type="xsd:string" minOccurs="0" />
            <xsd:element name="sha1" type="xsd:string" minOccurs="0" />
            <xsd:element name="md5" type="xsd:string" minOccurs="0" />
        </xsd:choice>
    </xsd:complexType>

    <xsd:complexType name="http_client_retry_failed">
        <xsd:sequence>
            <xsd:element name="http-code" type="http_client_retry_code" minOccurs="0" maxOccurs="unbounded" />
        </xsd:sequence>
        <xsd:attribute name="enabled" type="xsd:boolean" />
        <xsd:attribute name="retry-strategy" type="xsd:string" />
        <xsd:attribute name="max-retries" type="xsd:integer" />
        <xsd:attribute name="delay" type="xsd:integer" />
        <xsd:attribute name="multiplier" type="xsd:float" />
        <xsd:attribute name="max-delay" type="xsd:float" />
        <xsd:attribute name="jitter" type="xsd:float" />
        <xsd:attribute name="response_header" type="xsd:boolean" />
    </xsd:complexType>

    <xsd:complexType name="http_client_retry_code">
        <xsd:sequence>
            <xsd:element name="method" type="xsd:string" minOccurs="0" maxOccurs="unbounded" />
        </xsd:sequence>
        <xsd:attribute name="code" type="xsd:integer" />
    </xsd:complexType>

    <xsd:complexType name="http_query" mixed="true">
        <xsd:attribute name="key" type="xsd:string" />
    </xsd:complexType>

    <xsd:complexType name="http_resolve" mixed="true">
        <xsd:attribute name="host" type="xsd:string" />
    </xsd:complexType>

    <xsd:complexType name="http_header" mixed="true">
        <xsd:attribute name="name" type="xsd:string" />
    </xsd:complexType>

    <xsd:complexType name="mailer">
        <xsd:sequence>
            <xsd:element name="transport" type="mailer_transport" minOccurs="0" maxOccurs="unbounded" />
            <xsd:element name="envelope" type="mailer_envelope" minOccurs="0" maxOccurs="1" />
            <xsd:element name="header" type="header" minOccurs="0" maxOccurs="unbounded" />
        </xsd:sequence>
        <xsd:attribute name="enabled" type="xsd:boolean" />
        <xsd:attribute name="dsn" type="xsd:string" />
        <xsd:attribute name="message-bus" type="xsd:string" />
    </xsd:complexType>

    <xsd:complexType name="header" mixed="true">
        <xsd:attribute name="name" type="xsd:string" use="required" />
    </xsd:complexType>

    <xsd:complexType name="mailer_transport" mixed="true">
        <xsd:attribute name="name" type="xsd:string" use="required" />
    </xsd:complexType>

    <xsd:complexType name="mailer_envelope">
        <xsd:sequence>
            <xsd:element name="sender" type="xsd:string" minOccurs="0" maxOccurs="1" />
            <xsd:element name="recipient" type="xsd:string" minOccurs="0" maxOccurs="unbounded" />
        </xsd:sequence>
    </xsd:complexType>

    <xsd:complexType name="http_cache">
        <xsd:sequence>
            <xsd:element name="private-header" type="xsd:string" minOccurs="0" maxOccurs="unbounded" />
        </xsd:sequence>

        <xsd:attribute name="enabled" type="xsd:boolean" />
        <xsd:attribute name="debug" type="xsd:boolean" />
        <xsd:attribute name="trace-level" type="http_cache_trace_levels" />
        <xsd:attribute name="trace-header" type="xsd:string" />
        <xsd:attribute name="default-ttl" type="xsd:integer" />
        <xsd:attribute name="allow-reload" type="xsd:boolean" />
        <xsd:attribute name="allow-revalidate" type="xsd:boolean" />
        <xsd:attribute name="stale-while-revalidate" type="xsd:integer" />
        <xsd:attribute name="stale-if-error" type="xsd:integer" />
        <xsd:attribute name="terminate-on-cache-hit" type="xsd:boolean" />
    </xsd:complexType>

    <xsd:simpleType name="http_cache_trace_levels">
        <xsd:restriction base="xsd:string">
            <xsd:enumeration value="none" />
            <xsd:enumeration value="short" />
            <xsd:enumeration value="full" />
        </xsd:restriction>
    </xsd:simpleType>

    <xsd:complexType name="rate_limiter">
        <xsd:sequence>
            <xsd:element name="limiter" type="rate_limiter_limiter" minOccurs="0"  maxOccurs="unbounded" />
        </xsd:sequence>
        <xsd:attribute name="enabled" type="xsd:boolean" />
        <xsd:attribute name="max-host-connections" type="xsd:integer" />
        <xsd:attribute name="mock-response-factory" type="xsd:string" />
    </xsd:complexType>

    <xsd:complexType name="rate_limiter_limiter">
        <xsd:sequence>
            <xsd:element name="rate" type="rate_limiter_rate" minOccurs="0" />
        </xsd:sequence>
        <xsd:attribute name="name" type="xsd:string" />
        <xsd:attribute name="lock-factory" type="xsd:string" />
        <xsd:attribute name="storage-service" type="xsd:string" />
        <xsd:attribute name="cache-pool" type="xsd:string" />
        <xsd:attribute name="policy" type="xsd:string" />
        <xsd:attribute name="limit" type="xsd:int" />
        <xsd:attribute name="interval" type="xsd:string" />
    </xsd:complexType>

    <xsd:complexType name="rate_limiter_rate">
        <xsd:attribute name="interval" type="xsd:string" />
        <xsd:attribute name="amount" type="xsd:int" />
    </xsd:complexType>

    <xsd:complexType name="uid">
        <xsd:attribute name="enabled" type="xsd:boolean" />
        <xsd:attribute name="default_uuid_version" type="default_uuid_version" />
        <xsd:attribute name="name_based_uuid_version" type="name_based_uuid_version" />
        <xsd:attribute name="time_based_uuid_version" type="time_based_uuid_version" />
        <xsd:attribute name="name_based_uuid_namespace" type="xsd:string" />
        <xsd:attribute name="time_based_uuid_node" type="xsd:string" />
    </xsd:complexType>

    <xsd:simpleType name="default_uuid_version">
        <xsd:restriction base="xsd:int">
            <xsd:enumeration value="6" />
            <xsd:enumeration value="4" />
            <xsd:enumeration value="1" />
        </xsd:restriction>
    </xsd:simpleType>

    <xsd:simpleType name="name_based_uuid_version">
        <xsd:restriction base="xsd:int">
            <xsd:enumeration value="5" />
            <xsd:enumeration value="3" />
        </xsd:restriction>
    </xsd:simpleType>

    <xsd:simpleType name="time_based_uuid_version">
        <xsd:restriction base="xsd:int">
            <xsd:enumeration value="6" />
            <xsd:enumeration value="1" />
        </xsd:restriction>
    </xsd:simpleType>

    <xsd:complexType name="notifier">
        <xsd:sequence>
            <xsd:element name="chatter-transport" type="chatter-transport" minOccurs="0" maxOccurs="unbounded" />
            <xsd:element name="texter-transport" type="texter-transport" minOccurs="0" maxOccurs="unbounded" />
            <xsd:element name="channel-policy" type="channel-policy" minOccurs="0" maxOccurs="unbounded" />
            <xsd:element name="admin-recipients" type="admin-recipients" minOccurs="0" maxOccurs="1" />
        </xsd:sequence>
        <xsd:attribute name="enabled" type="xsd:boolean" />
        <xsd:attribute name="notification-on-failed-messages" type="xsd:boolean" />
        <xsd:attribute name="message-bus" type="xsd:string" />
    </xsd:complexType>

    <xsd:complexType name="chatter-transport" mixed="true">
        <xsd:attribute name="name" type="xsd:string" use="required"/>
    </xsd:complexType>

    <xsd:complexType name="texter-transport" mixed="true">
        <xsd:attribute name="name" type="xsd:string" use="required"/>
    </xsd:complexType>

    <xsd:complexType name="channel-policy" mixed="true">
        <xsd:sequence>
            <xsd:element name="channel" type="xsd:string" minOccurs="0" maxOccurs="unbounded" />
        </xsd:sequence>
        <xsd:attribute name="name" type="xsd:string" use="required" />
    </xsd:complexType>

    <xsd:complexType name="admin-recipients" mixed="true">
        <xsd:sequence>
            <xsd:element name="admin-recipient" type="admin-recipient" minOccurs="1" maxOccurs="unbounded" />
        </xsd:sequence>
    </xsd:complexType>

    <xsd:complexType name="admin-recipient" mixed="true">
        <xsd:attribute name="email" type="xsd:string" use="required" />
        <xsd:attribute name="phone" type="xsd:string" />
    </xsd:complexType>

    <xsd:complexType name="html-sanitizer">
        <xsd:sequence>
            <xsd:element name="sanitizer" type="sanitizer" minOccurs="0" maxOccurs="unbounded" />
        </xsd:sequence>
        <xsd:attribute name="enabled" type="xsd:boolean" />
    </xsd:complexType>

    <xsd:complexType name="sanitizer">
        <xsd:sequence>
            <xsd:element name="allow-element" type="element-option" minOccurs="0" maxOccurs="unbounded" />
            <xsd:element name="block-element" type="xsd:string" minOccurs="0" maxOccurs="unbounded" />
            <xsd:element name="drop-element" type="xsd:string" minOccurs="0" maxOccurs="unbounded" />
            <xsd:element name="allow-attribute" type="attribute-option" minOccurs="0" maxOccurs="unbounded" />
            <xsd:element name="drop-attribute" type="attribute-option" minOccurs="0" maxOccurs="unbounded" />
            <xsd:element name="force-attribute" type="force-attribute" minOccurs="0" maxOccurs="unbounded" />
            <xsd:element name="allowed-link-scheme" type="xsd:string" minOccurs="0" maxOccurs="unbounded" />
            <xsd:element name="allowed-link-host" type="xsd:string" minOccurs="0" maxOccurs="unbounded" />
            <xsd:element name="allowed-media-scheme" type="xsd:string" minOccurs="0" maxOccurs="unbounded" />
            <xsd:element name="allowed-media-host" type="xsd:string" minOccurs="0" maxOccurs="unbounded" />
            <xsd:element name="with-attribute-sanitizer" type="xsd:string" minOccurs="0" maxOccurs="unbounded" />
            <xsd:element name="without-attribute-sanitizer" type="xsd:string" minOccurs="0" maxOccurs="unbounded" />
        </xsd:sequence>
        <xsd:attribute name="name" type="xsd:string" use="required" />
        <xsd:attribute name="allow-safe-elements" type="xsd:boolean" />
        <xsd:attribute name="allow-static-elements" type="xsd:boolean" />
        <xsd:attribute name="force-https-urls" type="xsd:boolean" />
        <xsd:attribute name="allow-relative-links" type="xsd:boolean" />
        <xsd:attribute name="allow-relative-medias" type="xsd:boolean" />
        <xsd:attribute name="max-input-length" type="xsd:positiveInteger" />
    </xsd:complexType>

    <xsd:complexType name="element-option">
        <xsd:sequence>
            <xsd:element name="attribute" type="xsd:string" minOccurs="0" maxOccurs="unbounded" />
        </xsd:sequence>
        <xsd:attribute name="name" type="xsd:string" use="required" />
    </xsd:complexType>

    <xsd:complexType name="attribute-option">
        <xsd:sequence>
            <xsd:element name="element" type="xsd:string" minOccurs="0" maxOccurs="unbounded" />
        </xsd:sequence>
        <xsd:attribute name="name" type="xsd:string" use="required" />
    </xsd:complexType>

    <xsd:complexType name="force-attribute">
        <xsd:sequence>
            <xsd:element name="attribute" minOccurs="0" maxOccurs="unbounded">
                <xsd:complexType>
                    <xsd:simpleContent>
                        <xsd:extension base="xsd:string">
                            <xsd:attribute name="name" type="xsd:string" use="required"/>
                        </xsd:extension>
                    </xsd:simpleContent>
                </xsd:complexType>
            </xsd:element>
        </xsd:sequence>
        <xsd:attribute name="name" type="xsd:string" use="required" />
    </xsd:complexType>

    <xsd:complexType name="webhook">
        <xsd:sequence>
            <xsd:element name="routing" type="webhook_routing" minOccurs="0" maxOccurs="unbounded" />
        </xsd:sequence>
        <xsd:attribute name="enabled" type="xsd:boolean" />
        <xsd:attribute name="message-bus" type="xsd:string" />
    </xsd:complexType>

    <xsd:complexType name="webhook_routing" mixed="true">
        <xsd:sequence>
            <xsd:element name="service" type="xsd:string" minOccurs="0" maxOccurs="1" />
            <xsd:element name="secret" type="xsd:string" minOccurs="0" maxOccurs="1" />
        </xsd:sequence>
        <xsd:attribute name="type" type="xsd:string" use="required" />
    </xsd:complexType>

    <xsd:complexType name="remote-event">
        <xsd:attribute name="enabled" type="xsd:boolean" />
    </xsd:complexType>
</xsd:schema>
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\DependencyInjection\Loader\Configurator;

use _ContaoManager\Symfony\Bridge\Monolog\Handler\NotifierHandler;
use _ContaoManager\Symfony\Component\Notifier\Channel\BrowserChannel;
use _ContaoManager\Symfony\Component\Notifier\Channel\ChannelPolicy;
use _ContaoManager\Symfony\Component\Notifier\Channel\ChatChannel;
use _ContaoManager\Symfony\Component\Notifier\Channel\EmailChannel;
use _ContaoManager\Symfony\Component\Notifier\Channel\PushChannel;
use _ContaoManager\Symfony\Component\Notifier\Channel\SmsChannel;
use _ContaoManager\Symfony\Component\Notifier\Chatter;
use _ContaoManager\Symfony\Component\Notifier\ChatterInterface;
use _ContaoManager\Symfony\Component\Notifier\EventListener\NotificationLoggerListener;
use _ContaoManager\Symfony\Component\Notifier\EventListener\SendFailedMessageToNotifierListener;
use _ContaoManager\Symfony\Component\Notifier\FlashMessage\DefaultFlashMessageImportanceMapper;
use _ContaoManager\Symfony\Component\Notifier\Message\ChatMessage;
use _ContaoManager\Symfony\Component\Notifier\Message\PushMessage;
use _ContaoManager\Symfony\Component\Notifier\Message\SmsMessage;
use _ContaoManager\Symfony\Component\Notifier\Messenger\MessageHandler;
use _ContaoManager\Symfony\Component\Notifier\Notifier;
use _ContaoManager\Symfony\Component\Notifier\NotifierInterface;
use _ContaoManager\Symfony\Component\Notifier\Texter;
use _ContaoManager\Symfony\Component\Notifier\TexterInterface;
use _ContaoManager\Symfony\Component\Notifier\Transport;
use _ContaoManager\Symfony\Component\Notifier\Transport\Transports;
return static function (ContainerConfigurator $container) {
    $container->services()->set('notifier', Notifier::class)->args([tagged_locator('notifier.channel', 'channel'), service('notifier.channel_policy')->ignoreOnInvalid()])->alias(NotifierInterface::class, 'notifier')->set('notifier.channel_policy', ChannelPolicy::class)->args([[]])->set('notifier.flash_message_importance_mapper', DefaultFlashMessageImportanceMapper::class)->args([[]])->set('notifier.channel.browser', BrowserChannel::class)->args([service('request_stack'), service('notifier.flash_message_importance_mapper')])->tag('notifier.channel', ['channel' => 'browser'])->set('notifier.channel.chat', ChatChannel::class)->args([service('chatter.transports'), abstract_arg('message bus')])->tag('notifier.channel', ['channel' => 'chat'])->set('notifier.channel.sms', SmsChannel::class)->args([service('texter.transports'), abstract_arg('message bus')])->tag('notifier.channel', ['channel' => 'sms'])->set('notifier.channel.email', EmailChannel::class)->args([service('mailer.transports'), abstract_arg('message bus')])->tag('notifier.channel', ['channel' => 'email'])->set('notifier.channel.push', PushChannel::class)->args([service('texter.transports'), abstract_arg('message bus')])->tag('notifier.channel', ['channel' => 'push'])->set('notifier.monolog_handler', NotifierHandler::class)->args([service('notifier')])->set('notifier.failed_message_listener', SendFailedMessageToNotifierListener::class)->args([service('notifier')])->set('chatter', Chatter::class)->args([service('chatter.transports'), abstract_arg('message bus'), service('event_dispatcher')->ignoreOnInvalid()])->alias(ChatterInterface::class, 'chatter')->set('chatter.transports', Transports::class)->factory([service('chatter.transport_factory'), 'fromStrings'])->args([[]])->set('chatter.transport_factory', Transport::class)->args([tagged_iterator('chatter.transport_factory')])->set('chatter.messenger.chat_handler', MessageHandler::class)->args([service('chatter.transports')])->tag('messenger.message_handler', ['handles' => ChatMessage::class])->set('texter', Texter::class)->args([service('texter.transports'), abstract_arg('message bus'), service('event_dispatcher')->ignoreOnInvalid()])->alias(TexterInterface::class, 'texter')->set('texter.transports', Transports::class)->factory([service('texter.transport_factory'), 'fromStrings'])->args([[]])->set('texter.transport_factory', Transport::class)->args([tagged_iterator('texter.transport_factory')])->set('texter.messenger.sms_handler', MessageHandler::class)->args([service('texter.transports')])->tag('messenger.message_handler', ['handles' => SmsMessage::class])->set('texter.messenger.push_handler', MessageHandler::class)->args([service('texter.transports')])->tag('messenger.message_handler', ['handles' => PushMessage::class])->set('notifier.notification_logger_listener', NotificationLoggerListener::class)->tag('kernel.event_subscriber')->alias('notifier.logger_notification_listener', 'notifier.notification_logger_listener')->deprecate('symfony/framework-bundle', '6.3', 'The "%alias_id%" service is deprecated, use "notifier.notification_logger_listener" instead.');
};
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\DependencyInjection\Loader\Configurator;

use _ContaoManager\Symfony\Component\HttpClient\DataCollector\HttpClientDataCollector;
return static function (ContainerConfigurator $container) {
    $container->services()->set('data_collector.http_client', HttpClientDataCollector::class)->tag('data_collector', ['template' => '@WebProfiler/Collector/http_client.html.twig', 'id' => 'http_client', 'priority' => 250]);
};
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\DependencyInjection\Loader\Configurator;

use _ContaoManager\Symfony\Component\HttpKernel\EventListener\AddRequestFormatsListener;
return static function (ContainerConfigurator $container) {
    $container->services()->set('request.add_request_formats_listener', AddRequestFormatsListener::class)->args([abstract_arg('formats')])->tag('kernel.event_subscriber');
};
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\DependencyInjection\Loader\Configurator;

use _ContaoManager\Symfony\Bundle\FrameworkBundle\KernelBrowser;
use _ContaoManager\Symfony\Bundle\FrameworkBundle\Test\TestContainer;
use _ContaoManager\Symfony\Component\BrowserKit\CookieJar;
use _ContaoManager\Symfony\Component\BrowserKit\History;
use _ContaoManager\Symfony\Component\DependencyInjection\ServiceLocator;
use _ContaoManager\Symfony\Component\HttpKernel\EventListener\SessionListener;
return static function (ContainerConfigurator $container) {
    $container->parameters()->set('test.client.parameters', []);
    $container->services()->set('test.client', KernelBrowser::class)->args([service('kernel'), param('test.client.parameters'), service('test.client.history'), service('test.client.cookiejar')])->share(\false)->public()->set('test.client.history', History::class)->share(\false)->set('test.client.cookiejar', CookieJar::class)->share(\false)->set('test.session.listener', SessionListener::class)->args([service_locator(['session_factory' => service('session.factory')->ignoreOnInvalid()]), param('kernel.debug'), param('session.storage.options')])->tag('kernel.event_subscriber')->set('test.service_container', TestContainer::class)->args([service('kernel'), 'test.private_services_locator'])->public()->set('test.private_services_locator', ServiceLocator::class)->args([abstract_arg('callable collection')])->public();
};
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\DependencyInjection\Loader\Configurator;

use _ContaoManager\Symfony\Component\Webhook\Client\RequestParser;
use _ContaoManager\Symfony\Component\Webhook\Controller\WebhookController;
use _ContaoManager\Symfony\Component\Webhook\Messenger\SendWebhookHandler;
use _ContaoManager\Symfony\Component\Webhook\Server\HeadersConfigurator;
use _ContaoManager\Symfony\Component\Webhook\Server\HeaderSignatureConfigurator;
use _ContaoManager\Symfony\Component\Webhook\Server\JsonBodyConfigurator;
use _ContaoManager\Symfony\Component\Webhook\Server\Transport;
return static function (ContainerConfigurator $container) {
    $container->services()->set('webhook.transport', Transport::class)->args([service('http_client'), service('webhook.headers_configurator'), service('webhook.body_configurator.json'), service('webhook.signer')])->set('webhook.headers_configurator', HeadersConfigurator::class)->set('webhook.body_configurator.json', JsonBodyConfigurator::class)->args([service('serializer')])->set('webhook.signer', HeaderSignatureConfigurator::class)->set('webhook.messenger.send_handler', SendWebhookHandler::class)->args([service('webhook.transport')])->tag('messenger.message_handler')->set('webhook.request_parser', RequestParser::class)->alias(RequestParser::class, 'webhook.request_parser')->set('webhook.controller', WebhookController::class)->public()->args([abstract_arg('user defined parsers'), abstract_arg('message bus')]);
};
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\DependencyInjection\Loader\Configurator;

use _ContaoManager\Symfony\Component\Validator\DataCollector\ValidatorDataCollector;
use _ContaoManager\Symfony\Component\Validator\Validator\TraceableValidator;
return static function (ContainerConfigurator $container) {
    $container->services()->set('debug.validator', TraceableValidator::class)->decorate('validator', null, 255)->args([service('debug.validator.inner')])->tag('kernel.reset', ['method' => 'reset'])->set('data_collector.validator', ValidatorDataCollector::class)->args([service('debug.validator')])->tag('data_collector', ['template' => '@WebProfiler/Collector/validator.html.twig', 'id' => 'validator', 'priority' => 320]);
};
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\DependencyInjection\Loader\Configurator;

use _ContaoManager\Symfony\Component\ErrorHandler\ErrorRenderer\HtmlErrorRenderer;
return static function (ContainerConfigurator $container) {
    $container->services()->set('error_handler.error_renderer.html', HtmlErrorRenderer::class)->args([inline_service()->factory([HtmlErrorRenderer::class, 'isDebug'])->args([service('request_stack'), param('kernel.debug')]), param('kernel.charset'), service('debug.file_link_formatter')->nullOnInvalid(), param('kernel.project_dir'), inline_service()->factory([HtmlErrorRenderer::class, 'getAndCleanOutputBuffer'])->args([service('request_stack')]), service('logger')->nullOnInvalid()])->alias('error_renderer.html', 'error_handler.error_renderer.html')->alias('error_renderer', 'error_renderer.html');
};
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\DependencyInjection\Loader\Configurator;

use _ContaoManager\Symfony\Component\Mime\MimeTypeGuesserInterface;
use _ContaoManager\Symfony\Component\Mime\MimeTypes;
use _ContaoManager\Symfony\Component\Mime\MimeTypesInterface;
return static function (ContainerConfigurator $container) {
    $container->services()->set('mime_types', MimeTypes::class)->call('setDefault', [service('mime_types')])->alias(MimeTypesInterface::class, 'mime_types')->alias(MimeTypeGuesserInterface::class, 'mime_types');
};
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\DependencyInjection\Loader\Configurator;

use _ContaoManager\Symfony\Component\DependencyInjection\ServiceLocator;
use _ContaoManager\Symfony\Component\Messenger\Bridge\AmazonSqs\Transport\AmazonSqsTransportFactory;
use _ContaoManager\Symfony\Component\Messenger\Bridge\Amqp\Transport\AmqpTransportFactory;
use _ContaoManager\Symfony\Component\Messenger\Bridge\Beanstalkd\Transport\BeanstalkdTransportFactory;
use _ContaoManager\Symfony\Component\Messenger\Bridge\Redis\Transport\RedisTransportFactory;
use _ContaoManager\Symfony\Component\Messenger\EventListener\AddErrorDetailsStampListener;
use _ContaoManager\Symfony\Component\Messenger\EventListener\DispatchPcntlSignalListener;
use _ContaoManager\Symfony\Component\Messenger\EventListener\ResetServicesListener;
use _ContaoManager\Symfony\Component\Messenger\EventListener\SendFailedMessageForRetryListener;
use _ContaoManager\Symfony\Component\Messenger\EventListener\SendFailedMessageToFailureTransportListener;
use _ContaoManager\Symfony\Component\Messenger\EventListener\StopWorkerOnCustomStopExceptionListener;
use _ContaoManager\Symfony\Component\Messenger\EventListener\StopWorkerOnRestartSignalListener;
use _ContaoManager\Symfony\Component\Messenger\EventListener\StopWorkerOnSignalsListener;
use _ContaoManager\Symfony\Component\Messenger\Handler\RedispatchMessageHandler;
use _ContaoManager\Symfony\Component\Messenger\Middleware\AddBusNameStampMiddleware;
use _ContaoManager\Symfony\Component\Messenger\Middleware\DispatchAfterCurrentBusMiddleware;
use _ContaoManager\Symfony\Component\Messenger\Middleware\FailedMessageProcessingMiddleware;
use _ContaoManager\Symfony\Component\Messenger\Middleware\HandleMessageMiddleware;
use _ContaoManager\Symfony\Component\Messenger\Middleware\RejectRedeliveredMessageMiddleware;
use _ContaoManager\Symfony\Component\Messenger\Middleware\RouterContextMiddleware;
use _ContaoManager\Symfony\Component\Messenger\Middleware\SendMessageMiddleware;
use _ContaoManager\Symfony\Component\Messenger\Middleware\TraceableMiddleware;
use _ContaoManager\Symfony\Component\Messenger\Middleware\ValidationMiddleware;
use _ContaoManager\Symfony\Component\Messenger\Retry\MultiplierRetryStrategy;
use _ContaoManager\Symfony\Component\Messenger\RoutableMessageBus;
use _ContaoManager\Symfony\Component\Messenger\Transport\InMemory\InMemoryTransportFactory;
use _ContaoManager\Symfony\Component\Messenger\Transport\Sender\SendersLocator;
use _ContaoManager\Symfony\Component\Messenger\Transport\Serialization\Normalizer\FlattenExceptionNormalizer;
use _ContaoManager\Symfony\Component\Messenger\Transport\Serialization\PhpSerializer;
use _ContaoManager\Symfony\Component\Messenger\Transport\Serialization\Serializer;
use _ContaoManager\Symfony\Component\Messenger\Transport\Serialization\SerializerInterface;
use _ContaoManager\Symfony\Component\Messenger\Transport\Sync\SyncTransportFactory;
use _ContaoManager\Symfony\Component\Messenger\Transport\TransportFactory;
return static function (ContainerConfigurator $container) {
    $container->services()->alias(SerializerInterface::class, 'messenger.default_serializer')->set('messenger.senders_locator', SendersLocator::class)->args([abstract_arg('per message senders map'), abstract_arg('senders service locator')])->set('messenger.middleware.send_message', SendMessageMiddleware::class)->abstract()->args([service('messenger.senders_locator'), service('event_dispatcher')])->call('setLogger', [service('logger')->ignoreOnInvalid()])->tag('monolog.logger', ['channel' => 'messenger'])->set('messenger.transport.symfony_serializer', Serializer::class)->args([service('serializer'), abstract_arg('format'), abstract_arg('context')])->set('serializer.normalizer.flatten_exception', FlattenExceptionNormalizer::class)->tag('serializer.normalizer', ['priority' => -880])->set('messenger.transport.native_php_serializer', PhpSerializer::class)->alias('messenger.default_serializer', 'messenger.transport.native_php_serializer')->set('messenger.middleware.handle_message', HandleMessageMiddleware::class)->abstract()->args([abstract_arg('bus handler resolver')])->tag('monolog.logger', ['channel' => 'messenger'])->call('setLogger', [service('logger')->ignoreOnInvalid()])->set('messenger.middleware.add_bus_name_stamp_middleware', AddBusNameStampMiddleware::class)->abstract()->set('messenger.middleware.dispatch_after_current_bus', DispatchAfterCurrentBusMiddleware::class)->set('messenger.middleware.validation', ValidationMiddleware::class)->args([service('validator')])->set('messenger.middleware.reject_redelivered_message_middleware', RejectRedeliveredMessageMiddleware::class)->set('messenger.middleware.failed_message_processing_middleware', FailedMessageProcessingMiddleware::class)->set('messenger.middleware.traceable', TraceableMiddleware::class)->abstract()->args([service('debug.stopwatch')])->set('messenger.middleware.router_context', RouterContextMiddleware::class)->args([service('router')])->set('messenger.receiver_locator', ServiceLocator::class)->args([[]])->tag('container.service_locator')->set('messenger.transport_factory', TransportFactory::class)->args([tagged_iterator('messenger.transport_factory')])->set('messenger.transport.amqp.factory', AmqpTransportFactory::class)->set('messenger.transport.redis.factory', RedisTransportFactory::class)->set('messenger.transport.sync.factory', SyncTransportFactory::class)->args([service('messenger.routable_message_bus')])->tag('messenger.transport_factory')->set('messenger.transport.in_memory.factory', InMemoryTransportFactory::class)->tag('messenger.transport_factory')->tag('kernel.reset', ['method' => 'reset'])->set('messenger.transport.sqs.factory', AmazonSqsTransportFactory::class)->args([service('logger')->ignoreOnInvalid()])->tag('monolog.logger', ['channel' => 'messenger'])->set('messenger.transport.beanstalkd.factory', BeanstalkdTransportFactory::class)->set('messenger.retry_strategy_locator', ServiceLocator::class)->args([[]])->tag('container.service_locator')->set('messenger.retry.abstract_multiplier_retry_strategy', MultiplierRetryStrategy::class)->abstract()->args([abstract_arg('max retries'), abstract_arg('delay ms'), abstract_arg('multiplier'), abstract_arg('max delay ms')])->set('messenger.rate_limiter_locator', ServiceLocator::class)->args([[]])->tag('container.service_locator')->set('messenger.retry.send_failed_message_for_retry_listener', SendFailedMessageForRetryListener::class)->args([abstract_arg('senders service locator'), service('messenger.retry_strategy_locator'), service('logger')->ignoreOnInvalid(), service('event_dispatcher')])->tag('kernel.event_subscriber')->tag('monolog.logger', ['channel' => 'messenger'])->set('messenger.failure.add_error_details_stamp_listener', AddErrorDetailsStampListener::class)->tag('kernel.event_subscriber')->set('messenger.failure.send_failed_message_to_failure_transport_listener', SendFailedMessageToFailureTransportListener::class)->args([abstract_arg('failure transports'), service('logger')->ignoreOnInvalid(), abstract_arg('failure transports by name')])->tag('kernel.event_subscriber')->tag('monolog.logger', ['channel' => 'messenger'])->set('messenger.listener.dispatch_pcntl_signal_listener', DispatchPcntlSignalListener::class)->tag('kernel.event_subscriber')->set('messenger.listener.stop_worker_on_restart_signal_listener', StopWorkerOnRestartSignalListener::class)->args([service('cache.messenger.restart_workers_signal'), service('logger')->ignoreOnInvalid()])->tag('kernel.event_subscriber')->tag('monolog.logger', ['channel' => 'messenger'])->set('messenger.listener.stop_worker_signals_listener', StopWorkerOnSignalsListener::class)->deprecate('6.4', 'symfony/messenger', 'The "%service_id%" service is deprecated, use the "Symfony\Component\Console\Command\SignalableCommandInterface" instead.')->args([null, service('logger')->ignoreOnInvalid()])->tag('kernel.event_subscriber')->tag('monolog.logger', ['channel' => 'messenger'])->alias('messenger.listener.stop_worker_on_sigterm_signal_listener', 'messenger.listener.stop_worker_signals_listener')->deprecate('6.3', 'symfony/messenger', 'The "%alias_id%" service is deprecated, use the "Symfony\Component\Console\Command\SignalableCommandInterface" instead.')->set('messenger.listener.stop_worker_on_stop_exception_listener', StopWorkerOnCustomStopExceptionListener::class)->tag('kernel.event_subscriber')->set('messenger.listener.reset_services', ResetServicesListener::class)->args([service('services_resetter')])->set('messenger.routable_message_bus', RoutableMessageBus::class)->args([abstract_arg('message bus locator'), service('messenger.default_bus')])->set('messenger.redispatch_message_handler', RedispatchMessageHandler::class)->args([service('messenger.default_bus')])->tag('messenger.message_handler');
};
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\DependencyInjection\Loader\Configurator;

use _ContaoManager\Symfony\Bundle\FrameworkBundle\Command\AboutCommand;
use _ContaoManager\Symfony\Bundle\FrameworkBundle\Command\AssetsInstallCommand;
use _ContaoManager\Symfony\Bundle\FrameworkBundle\Command\CacheClearCommand;
use _ContaoManager\Symfony\Bundle\FrameworkBundle\Command\CachePoolClearCommand;
use _ContaoManager\Symfony\Bundle\FrameworkBundle\Command\CachePoolDeleteCommand;
use _ContaoManager\Symfony\Bundle\FrameworkBundle\Command\CachePoolInvalidateTagsCommand;
use _ContaoManager\Symfony\Bundle\FrameworkBundle\Command\CachePoolListCommand;
use _ContaoManager\Symfony\Bundle\FrameworkBundle\Command\CachePoolPruneCommand;
use _ContaoManager\Symfony\Bundle\FrameworkBundle\Command\CacheWarmupCommand;
use _ContaoManager\Symfony\Bundle\FrameworkBundle\Command\ConfigDebugCommand;
use _ContaoManager\Symfony\Bundle\FrameworkBundle\Command\ConfigDumpReferenceCommand;
use _ContaoManager\Symfony\Bundle\FrameworkBundle\Command\ContainerDebugCommand;
use _ContaoManager\Symfony\Bundle\FrameworkBundle\Command\ContainerLintCommand;
use _ContaoManager\Symfony\Bundle\FrameworkBundle\Command\DebugAutowiringCommand;
use _ContaoManager\Symfony\Bundle\FrameworkBundle\Command\EventDispatcherDebugCommand;
use _ContaoManager\Symfony\Bundle\FrameworkBundle\Command\RouterDebugCommand;
use _ContaoManager\Symfony\Bundle\FrameworkBundle\Command\RouterMatchCommand;
use _ContaoManager\Symfony\Bundle\FrameworkBundle\Command\SecretsDecryptToLocalCommand;
use _ContaoManager\Symfony\Bundle\FrameworkBundle\Command\SecretsEncryptFromLocalCommand;
use _ContaoManager\Symfony\Bundle\FrameworkBundle\Command\SecretsGenerateKeysCommand;
use _ContaoManager\Symfony\Bundle\FrameworkBundle\Command\SecretsListCommand;
use _ContaoManager\Symfony\Bundle\FrameworkBundle\Command\SecretsRemoveCommand;
use _ContaoManager\Symfony\Bundle\FrameworkBundle\Command\SecretsSetCommand;
use _ContaoManager\Symfony\Bundle\FrameworkBundle\Command\TranslationDebugCommand;
use _ContaoManager\Symfony\Bundle\FrameworkBundle\Command\TranslationUpdateCommand;
use _ContaoManager\Symfony\Bundle\FrameworkBundle\Command\WorkflowDumpCommand;
use _ContaoManager\Symfony\Bundle\FrameworkBundle\Command\YamlLintCommand;
use _ContaoManager\Symfony\Bundle\FrameworkBundle\Console\Application;
use _ContaoManager\Symfony\Bundle\FrameworkBundle\EventListener\SuggestMissingPackageSubscriber;
use _ContaoManager\Symfony\Component\Console\EventListener\ErrorListener;
use _ContaoManager\Symfony\Component\Console\Messenger\RunCommandMessageHandler;
use _ContaoManager\Symfony\Component\Dotenv\Command\DebugCommand as DotenvDebugCommand;
use _ContaoManager\Symfony\Component\Messenger\Command\ConsumeMessagesCommand;
use _ContaoManager\Symfony\Component\Messenger\Command\DebugCommand as MessengerDebugCommand;
use _ContaoManager\Symfony\Component\Messenger\Command\FailedMessagesRemoveCommand;
use _ContaoManager\Symfony\Component\Messenger\Command\FailedMessagesRetryCommand;
use _ContaoManager\Symfony\Component\Messenger\Command\FailedMessagesShowCommand;
use _ContaoManager\Symfony\Component\Messenger\Command\SetupTransportsCommand;
use _ContaoManager\Symfony\Component\Messenger\Command\StatsCommand;
use _ContaoManager\Symfony\Component\Messenger\Command\StopWorkersCommand;
use _ContaoManager\Symfony\Component\Scheduler\Command\DebugCommand as SchedulerDebugCommand;
use _ContaoManager\Symfony\Component\Serializer\Command\DebugCommand as SerializerDebugCommand;
use _ContaoManager\Symfony\Component\Translation\Command\TranslationPullCommand;
use _ContaoManager\Symfony\Component\Translation\Command\TranslationPushCommand;
use _ContaoManager\Symfony\Component\Translation\Command\XliffLintCommand;
use _ContaoManager\Symfony\Component\Validator\Command\DebugCommand as ValidatorDebugCommand;
return static function (ContainerConfigurator $container) {
    $container->services()->set('console.error_listener', ErrorListener::class)->args([service('logger')->nullOnInvalid()])->tag('kernel.event_subscriber')->tag('monolog.logger', ['channel' => 'console'])->set('console.suggest_missing_package_subscriber', SuggestMissingPackageSubscriber::class)->tag('kernel.event_subscriber')->set('console.command.about', AboutCommand::class)->tag('console.command')->set('console.command.assets_install', AssetsInstallCommand::class)->args([service('filesystem'), param('kernel.project_dir')])->tag('console.command')->set('console.command.cache_clear', CacheClearCommand::class)->args([service('cache_clearer'), service('filesystem')])->tag('console.command')->set('console.command.cache_pool_clear', CachePoolClearCommand::class)->args([service('cache.global_clearer')])->tag('console.command')->set('console.command.cache_pool_prune', CachePoolPruneCommand::class)->args([[]])->tag('console.command')->set('console.command.cache_pool_invalidate_tags', CachePoolInvalidateTagsCommand::class)->args([tagged_locator('cache.taggable', 'pool')])->tag('console.command')->set('console.command.cache_pool_delete', CachePoolDeleteCommand::class)->args([service('cache.global_clearer')])->tag('console.command')->set('console.command.cache_pool_list', CachePoolListCommand::class)->args([null])->tag('console.command')->set('console.command.cache_warmup', CacheWarmupCommand::class)->args([service('cache_warmer')])->tag('console.command')->set('console.command.config_debug', ConfigDebugCommand::class)->args([service('container.env_var_processors_locator')])->tag('console.command')->set('console.command.config_dump_reference', ConfigDumpReferenceCommand::class)->tag('console.command')->set('console.command.container_debug', ContainerDebugCommand::class)->tag('console.command')->set('console.command.container_lint', ContainerLintCommand::class)->tag('console.command')->set('console.command.debug_autowiring', DebugAutowiringCommand::class)->args([null, service('debug.file_link_formatter')->nullOnInvalid()])->tag('console.command')->set('console.command.dotenv_debug', DotenvDebugCommand::class)->args([param('kernel.environment'), param('kernel.project_dir')])->tag('console.command')->set('console.command.event_dispatcher_debug', EventDispatcherDebugCommand::class)->args([tagged_locator('event_dispatcher.dispatcher', 'name')])->tag('console.command')->set('console.command.messenger_consume_messages', ConsumeMessagesCommand::class)->args([
        abstract_arg('Routable message bus'),
        service('messenger.receiver_locator'),
        service('event_dispatcher'),
        service('logger')->nullOnInvalid(),
        [],
        // Receiver names
        service('messenger.listener.reset_services')->nullOnInvalid(),
        [],
        // Bus names
        service('messenger.rate_limiter_locator')->nullOnInvalid(),
        null,
    ])->tag('console.command')->tag('monolog.logger', ['channel' => 'messenger'])->set('console.command.messenger_setup_transports', SetupTransportsCommand::class)->args([service('messenger.receiver_locator'), []])->tag('console.command')->set('console.command.messenger_debug', MessengerDebugCommand::class)->args([[]])->tag('console.command')->set('console.command.messenger_stop_workers', StopWorkersCommand::class)->args([service('cache.messenger.restart_workers_signal')])->tag('console.command')->set('console.command.messenger_failed_messages_retry', FailedMessagesRetryCommand::class)->args([abstract_arg('Default failure receiver name'), abstract_arg('Receivers'), service('messenger.routable_message_bus'), service('event_dispatcher'), service('logger')->nullOnInvalid(), service('messenger.transport.native_php_serializer')->nullOnInvalid(), null])->tag('console.command')->tag('monolog.logger', ['channel' => 'messenger'])->set('console.command.messenger_failed_messages_show', FailedMessagesShowCommand::class)->args([abstract_arg('Default failure receiver name'), abstract_arg('Receivers'), service('messenger.transport.native_php_serializer')->nullOnInvalid()])->tag('console.command')->set('console.command.messenger_failed_messages_remove', FailedMessagesRemoveCommand::class)->args([abstract_arg('Default failure receiver name'), abstract_arg('Receivers'), service('messenger.transport.native_php_serializer')->nullOnInvalid()])->tag('console.command')->set('console.command.messenger_stats', StatsCommand::class)->args([service('messenger.receiver_locator'), abstract_arg('Receivers names')])->tag('console.command')->set('console.command.scheduler_debug', SchedulerDebugCommand::class)->args([tagged_locator('scheduler.schedule_provider', 'name')])->tag('console.command')->set('console.command.router_debug', RouterDebugCommand::class)->args([service('router'), service('debug.file_link_formatter')->nullOnInvalid()])->tag('console.command')->set('console.command.router_match', RouterMatchCommand::class)->args([service('router'), tagged_iterator('routing.expression_language_provider')])->tag('console.command')->set('console.command.serializer_debug', SerializerDebugCommand::class)->args([service('serializer.mapping.class_metadata_factory')])->tag('console.command')->set('console.command.translation_debug', TranslationDebugCommand::class)->args([
        service('translator'),
        service('translation.reader'),
        service('translation.extractor'),
        param('translator.default_path'),
        null,
        // twig.default_path
        [],
        // Translator paths
        [],
        // Twig paths
        param('kernel.enabled_locales'),
    ])->tag('console.command')->set('console.command.translation_extract', TranslationUpdateCommand::class)->args([
        service('translation.writer'),
        service('translation.reader'),
        service('translation.extractor'),
        param('kernel.default_locale'),
        param('translator.default_path'),
        null,
        // twig.default_path
        [],
        // Translator paths
        [],
        // Twig paths
        param('kernel.enabled_locales'),
    ])->tag('console.command')->set('console.command.validator_debug', ValidatorDebugCommand::class)->args([service('validator')])->tag('console.command')->set('console.command.translation_pull', TranslationPullCommand::class)->args([
        service('translation.provider_collection'),
        service('translation.writer'),
        service('translation.reader'),
        param('kernel.default_locale'),
        [],
        // Translator paths
        [],
    ])->tag('console.command', ['command' => 'translation:pull'])->set('console.command.translation_push', TranslationPushCommand::class)->args([
        service('translation.provider_collection'),
        service('translation.reader'),
        [],
        // Translator paths
        [],
    ])->tag('console.command', ['command' => 'translation:push'])->set('console.command.workflow_dump', WorkflowDumpCommand::class)->args([tagged_locator('workflow', 'name')])->tag('console.command')->set('console.command.xliff_lint', XliffLintCommand::class)->tag('console.command')->set('console.command.yaml_lint', YamlLintCommand::class)->tag('console.command')->set('console.command.form_debug', \_ContaoManager\Symfony\Component\Form\Command\DebugCommand::class)->args([
        service('form.registry'),
        [],
        // All form types namespaces are stored here by FormPass
        [],
        // All services form types are stored here by FormPass
        [],
        // All type extensions are stored here by FormPass
        [],
        // All type guessers are stored here by FormPass
        service('debug.file_link_formatter')->nullOnInvalid(),
    ])->tag('console.command')->set('console.command.secrets_set', SecretsSetCommand::class)->args([service('secrets.vault'), service('secrets.local_vault')->nullOnInvalid()])->tag('console.command')->set('console.command.secrets_remove', SecretsRemoveCommand::class)->args([service('secrets.vault'), service('secrets.local_vault')->nullOnInvalid()])->tag('console.command')->set('console.command.secrets_generate_key', SecretsGenerateKeysCommand::class)->args([service('secrets.vault'), service('secrets.local_vault')->ignoreOnInvalid()])->tag('console.command')->set('console.command.secrets_list', SecretsListCommand::class)->args([service('secrets.vault'), service('secrets.local_vault')->ignoreOnInvalid()])->tag('console.command')->set('console.command.secrets_decrypt_to_local', SecretsDecryptToLocalCommand::class)->args([service('secrets.vault'), service('secrets.local_vault')->ignoreOnInvalid()])->tag('console.command')->set('console.command.secrets_encrypt_from_local', SecretsEncryptFromLocalCommand::class)->args([service('secrets.vault'), service('secrets.local_vault')->ignoreOnInvalid()])->tag('console.command')->set('console.messenger.application', Application::class)->share(\false)->call('setAutoExit', [\false])->args([service('kernel')])->set('console.messenger.execute_command_handler', RunCommandMessageHandler::class)->args([service('console.messenger.application')])->tag('messenger.message_handler');
};
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\DependencyInjection\Loader\Configurator;

use _ContaoManager\Symfony\Component\Uid\Factory\NameBasedUuidFactory;
use _ContaoManager\Symfony\Component\Uid\Factory\RandomBasedUuidFactory;
use _ContaoManager\Symfony\Component\Uid\Factory\TimeBasedUuidFactory;
use _ContaoManager\Symfony\Component\Uid\Factory\UlidFactory;
use _ContaoManager\Symfony\Component\Uid\Factory\UuidFactory;
return static function (ContainerConfigurator $container) {
    $container->services()->set('ulid.factory', UlidFactory::class)->alias(UlidFactory::class, 'ulid.factory')->set('uuid.factory', UuidFactory::class)->alias(UuidFactory::class, 'uuid.factory')->set('name_based_uuid.factory', NameBasedUuidFactory::class)->factory([service('uuid.factory'), 'nameBased'])->args([abstract_arg('Please set the "framework.uid.name_based_uuid_namespace" configuration option to use the "name_based_uuid.factory" service')])->alias(NameBasedUuidFactory::class, 'name_based_uuid.factory')->set('random_based_uuid.factory', RandomBasedUuidFactory::class)->factory([service('uuid.factory'), 'randomBased'])->alias(RandomBasedUuidFactory::class, 'random_based_uuid.factory')->set('time_based_uuid.factory', TimeBasedUuidFactory::class)->factory([service('uuid.factory'), 'timeBased'])->alias(TimeBasedUuidFactory::class, 'time_based_uuid.factory');
};
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\DependencyInjection\Loader\Configurator;

use _ContaoManager\Symfony\Component\PropertyInfo\Extractor\ReflectionExtractor;
use _ContaoManager\Symfony\Component\PropertyInfo\PropertyAccessExtractorInterface;
use _ContaoManager\Symfony\Component\PropertyInfo\PropertyDescriptionExtractorInterface;
use _ContaoManager\Symfony\Component\PropertyInfo\PropertyInfoCacheExtractor;
use _ContaoManager\Symfony\Component\PropertyInfo\PropertyInfoExtractor;
use _ContaoManager\Symfony\Component\PropertyInfo\PropertyInfoExtractorInterface;
use _ContaoManager\Symfony\Component\PropertyInfo\PropertyInitializableExtractorInterface;
use _ContaoManager\Symfony\Component\PropertyInfo\PropertyListExtractorInterface;
use _ContaoManager\Symfony\Component\PropertyInfo\PropertyReadInfoExtractorInterface;
use _ContaoManager\Symfony\Component\PropertyInfo\PropertyTypeExtractorInterface;
use _ContaoManager\Symfony\Component\PropertyInfo\PropertyWriteInfoExtractorInterface;
return static function (ContainerConfigurator $container) {
    $container->services()->set('property_info', PropertyInfoExtractor::class)->args([[], [], [], [], []])->alias(PropertyAccessExtractorInterface::class, 'property_info')->alias(PropertyDescriptionExtractorInterface::class, 'property_info')->alias(PropertyInfoExtractorInterface::class, 'property_info')->alias(PropertyTypeExtractorInterface::class, 'property_info')->alias(PropertyListExtractorInterface::class, 'property_info')->alias(PropertyInitializableExtractorInterface::class, 'property_info')->set('property_info.cache', PropertyInfoCacheExtractor::class)->decorate('property_info')->args([service('property_info.cache.inner'), service('cache.property_info')])->set('property_info.reflection_extractor', ReflectionExtractor::class)->tag('property_info.list_extractor', ['priority' => -1000])->tag('property_info.type_extractor', ['priority' => -1002])->tag('property_info.access_extractor', ['priority' => -1000])->tag('property_info.initializable_extractor', ['priority' => -1000])->alias(PropertyReadInfoExtractorInterface::class, 'property_info.reflection_extractor')->alias(PropertyWriteInfoExtractorInterface::class, 'property_info.reflection_extractor');
};
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\DependencyInjection\Loader\Configurator;

use _ContaoManager\Symfony\Component\Scheduler\EventListener\DispatchSchedulerEventListener;
use _ContaoManager\Symfony\Component\Scheduler\Messenger\SchedulerTransportFactory;
use _ContaoManager\Symfony\Component\Scheduler\Messenger\ServiceCallMessageHandler;
return static function (ContainerConfigurator $container) {
    $container->services()->set('scheduler.messenger.service_call_message_handler', ServiceCallMessageHandler::class)->args([tagged_locator('scheduler.task')])->tag('messenger.message_handler')->set('scheduler.messenger_transport_factory', SchedulerTransportFactory::class)->args([tagged_locator('scheduler.schedule_provider', 'name'), service('clock')])->tag('messenger.transport_factory')->set('scheduler.event_listener', DispatchSchedulerEventListener::class)->args([tagged_locator('scheduler.schedule_provider', 'name'), service('event_dispatcher')])->tag('kernel.event_subscriber');
};
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\DependencyInjection\Loader\Configurator;

use _ContaoManager\Symfony\Component\HttpKernel\EventListener\SurrogateListener;
use _ContaoManager\Symfony\Component\HttpKernel\HttpCache\Ssi;
return static function (ContainerConfigurator $container) {
    $container->services()->set('ssi', Ssi::class)->set('ssi_listener', SurrogateListener::class)->args([service('ssi')->ignoreOnInvalid()])->tag('kernel.event_subscriber');
};
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\DependencyInjection\Loader\Configurator;

use _ContaoManager\Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use _ContaoManager\Symfony\Bundle\FrameworkBundle\Controller\ControllerResolver;
use _ContaoManager\Symfony\Bundle\FrameworkBundle\Controller\TemplateController;
use _ContaoManager\Symfony\Component\HttpKernel\Controller\ArgumentResolver;
use _ContaoManager\Symfony\Component\HttpKernel\Controller\ArgumentResolver\BackedEnumValueResolver;
use _ContaoManager\Symfony\Component\HttpKernel\Controller\ArgumentResolver\DateTimeValueResolver;
use _ContaoManager\Symfony\Component\HttpKernel\Controller\ArgumentResolver\DefaultValueResolver;
use _ContaoManager\Symfony\Component\HttpKernel\Controller\ArgumentResolver\QueryParameterValueResolver;
use _ContaoManager\Symfony\Component\HttpKernel\Controller\ArgumentResolver\RequestAttributeValueResolver;
use _ContaoManager\Symfony\Component\HttpKernel\Controller\ArgumentResolver\RequestPayloadValueResolver;
use _ContaoManager\Symfony\Component\HttpKernel\Controller\ArgumentResolver\RequestValueResolver;
use _ContaoManager\Symfony\Component\HttpKernel\Controller\ArgumentResolver\ServiceValueResolver;
use _ContaoManager\Symfony\Component\HttpKernel\Controller\ArgumentResolver\SessionValueResolver;
use _ContaoManager\Symfony\Component\HttpKernel\Controller\ArgumentResolver\UidValueResolver;
use _ContaoManager\Symfony\Component\HttpKernel\Controller\ArgumentResolver\VariadicValueResolver;
use _ContaoManager\Symfony\Component\HttpKernel\Controller\ErrorController;
use _ContaoManager\Symfony\Component\HttpKernel\ControllerMetadata\ArgumentMetadataFactory;
use _ContaoManager\Symfony\Component\HttpKernel\EventListener\CacheAttributeListener;
use _ContaoManager\Symfony\Component\HttpKernel\EventListener\DisallowRobotsIndexingListener;
use _ContaoManager\Symfony\Component\HttpKernel\EventListener\ErrorListener;
use _ContaoManager\Symfony\Component\HttpKernel\EventListener\LocaleListener;
use _ContaoManager\Symfony\Component\HttpKernel\EventListener\ResponseListener;
use _ContaoManager\Symfony\Component\HttpKernel\EventListener\ValidateRequestListener;
return static function (ContainerConfigurator $container) {
    $container->services()->set('controller_resolver', ControllerResolver::class)->args([service('service_container'), service('logger')->ignoreOnInvalid()])->call('allowControllers', [[AbstractController::class, TemplateController::class]])->tag('monolog.logger', ['channel' => 'request'])->set('argument_metadata_factory', ArgumentMetadataFactory::class)->set('argument_resolver', ArgumentResolver::class)->args([service('argument_metadata_factory'), abstract_arg('argument value resolvers'), abstract_arg('targeted value resolvers')])->set('argument_resolver.backed_enum_resolver', BackedEnumValueResolver::class)->tag('controller.argument_value_resolver', ['priority' => 100, 'name' => BackedEnumValueResolver::class])->set('argument_resolver.uid', UidValueResolver::class)->tag('controller.argument_value_resolver', ['priority' => 100, 'name' => UidValueResolver::class])->set('argument_resolver.datetime', DateTimeValueResolver::class)->args([service('clock')->nullOnInvalid()])->tag('controller.argument_value_resolver', ['priority' => 100, 'name' => DateTimeValueResolver::class])->set('argument_resolver.request_payload', RequestPayloadValueResolver::class)->args([service('serializer'), service('validator')->nullOnInvalid(), service('translator')->nullOnInvalid()])->tag('controller.targeted_value_resolver', ['name' => RequestPayloadValueResolver::class])->tag('kernel.event_subscriber')->lazy()->set('argument_resolver.request_attribute', RequestAttributeValueResolver::class)->tag('controller.argument_value_resolver', ['priority' => 100, 'name' => RequestAttributeValueResolver::class])->set('argument_resolver.request', RequestValueResolver::class)->tag('controller.argument_value_resolver', ['priority' => 50, 'name' => RequestValueResolver::class])->set('argument_resolver.session', SessionValueResolver::class)->tag('controller.argument_value_resolver', ['priority' => 50, 'name' => SessionValueResolver::class])->set('argument_resolver.service', ServiceValueResolver::class)->args([abstract_arg('service locator, set in RegisterControllerArgumentLocatorsPass')])->tag('controller.argument_value_resolver', ['priority' => -50, 'name' => ServiceValueResolver::class])->set('argument_resolver.default', DefaultValueResolver::class)->tag('controller.argument_value_resolver', ['priority' => -100, 'name' => DefaultValueResolver::class])->set('argument_resolver.variadic', VariadicValueResolver::class)->tag('controller.argument_value_resolver', ['priority' => -150, 'name' => VariadicValueResolver::class])->set('argument_resolver.query_parameter_value_resolver', QueryParameterValueResolver::class)->tag('controller.targeted_value_resolver', ['name' => QueryParameterValueResolver::class])->set('response_listener', ResponseListener::class)->args([param('kernel.charset'), abstract_arg('The "set_content_language_from_locale" config value')])->tag('kernel.event_subscriber')->set('locale_listener', LocaleListener::class)->args([service('request_stack'), param('kernel.default_locale'), service('router')->ignoreOnInvalid(), abstract_arg('The "set_locale_from_accept_language" config value'), param('kernel.enabled_locales')])->tag('kernel.event_subscriber')->set('validate_request_listener', ValidateRequestListener::class)->tag('kernel.event_subscriber')->set('disallow_search_engine_index_response_listener', DisallowRobotsIndexingListener::class)->tag('kernel.event_subscriber')->set('error_controller', ErrorController::class)->public()->args([service('http_kernel'), param('kernel.error_controller'), service('error_renderer')])->set('exception_listener', ErrorListener::class)->args([param('kernel.error_controller'), service('logger')->nullOnInvalid(), param('kernel.debug'), abstract_arg('an exceptions to log & status code mapping')])->tag('kernel.event_subscriber')->tag('monolog.logger', ['channel' => 'request'])->set('controller.cache_attribute_listener', CacheAttributeListener::class)->tag('kernel.event_subscriber');
};
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\DependencyInjection\Loader\Configurator;

use _ContaoManager\Symfony\Component\Messenger\DataCollector\MessengerDataCollector;
return static function (ContainerConfigurator $container) {
    $container->services()->set('data_collector.messenger', MessengerDataCollector::class)->tag('data_collector', ['template' => '@WebProfiler/Collector/messenger.html.twig', 'id' => 'messenger', 'priority' => 100]);
};
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\DependencyInjection\Loader\Configurator;

use _ContaoManager\Symfony\Bundle\FrameworkBundle\DataCollector\RouterDataCollector;
use _ContaoManager\Symfony\Component\Console\DataCollector\CommandDataCollector;
use _ContaoManager\Symfony\Component\HttpKernel\DataCollector\AjaxDataCollector;
use _ContaoManager\Symfony\Component\HttpKernel\DataCollector\ConfigDataCollector;
use _ContaoManager\Symfony\Component\HttpKernel\DataCollector\EventDataCollector;
use _ContaoManager\Symfony\Component\HttpKernel\DataCollector\ExceptionDataCollector;
use _ContaoManager\Symfony\Component\HttpKernel\DataCollector\LoggerDataCollector;
use _ContaoManager\Symfony\Component\HttpKernel\DataCollector\MemoryDataCollector;
use _ContaoManager\Symfony\Component\HttpKernel\DataCollector\RequestDataCollector;
use _ContaoManager\Symfony\Component\HttpKernel\DataCollector\TimeDataCollector;
use _ContaoManager\Symfony\Component\HttpKernel\KernelEvents;
return static function (ContainerConfigurator $container) {
    $container->services()->set('data_collector.config', ConfigDataCollector::class)->call('setKernel', [service('kernel')->ignoreOnInvalid()])->tag('data_collector', ['template' => '@WebProfiler/Collector/config.html.twig', 'id' => 'config', 'priority' => -255])->set('data_collector.request', RequestDataCollector::class)->args([service('.virtual_request_stack')->ignoreOnInvalid()])->tag('kernel.event_subscriber')->tag('data_collector', ['template' => '@WebProfiler/Collector/request.html.twig', 'id' => 'request', 'priority' => 335])->set('data_collector.request.session_collector', \Closure::class)->factory([\Closure::class, 'fromCallable'])->args([[service('data_collector.request'), 'collectSessionUsage']])->set('data_collector.ajax', AjaxDataCollector::class)->tag('data_collector', ['template' => '@WebProfiler/Collector/ajax.html.twig', 'id' => 'ajax', 'priority' => 315])->set('data_collector.exception', ExceptionDataCollector::class)->tag('data_collector', ['template' => '@WebProfiler/Collector/exception.html.twig', 'id' => 'exception', 'priority' => 305])->set('data_collector.events', EventDataCollector::class)->args([tagged_iterator('event_dispatcher.dispatcher', 'name'), service('.virtual_request_stack')->ignoreOnInvalid()])->tag('data_collector', ['template' => '@WebProfiler/Collector/events.html.twig', 'id' => 'events', 'priority' => 290])->set('data_collector.logger', LoggerDataCollector::class)->args([service('logger')->ignoreOnInvalid(), \sprintf('%s/%s', param('kernel.build_dir'), param('kernel.container_class')), service('.virtual_request_stack')->ignoreOnInvalid()])->tag('monolog.logger', ['channel' => 'profiler'])->tag('data_collector', ['template' => '@WebProfiler/Collector/logger.html.twig', 'id' => 'logger', 'priority' => 300])->set('data_collector.time', TimeDataCollector::class)->args([service('kernel')->ignoreOnInvalid(), service('debug.stopwatch')->ignoreOnInvalid()])->tag('data_collector', ['template' => '@WebProfiler/Collector/time.html.twig', 'id' => 'time', 'priority' => 330])->set('data_collector.memory', MemoryDataCollector::class)->tag('data_collector', ['template' => '@WebProfiler/Collector/memory.html.twig', 'id' => 'memory', 'priority' => 325])->set('data_collector.router', RouterDataCollector::class)->tag('kernel.event_listener', ['event' => KernelEvents::CONTROLLER, 'method' => 'onKernelController'])->tag('data_collector', ['template' => '@WebProfiler/Collector/router.html.twig', 'id' => 'router', 'priority' => 285])->set('.data_collector.command', CommandDataCollector::class)->tag('data_collector', ['template' => '@WebProfiler/Collector/command.html.twig', 'id' => 'command', 'priority' => 335]);
};
<?xml version="1.0" encoding="UTF-8" ?>

<routes xmlns="http://symfony.com/schema/routing"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://symfony.com/schema/routing https://symfony.com/schema/routing/routing-1.0.xsd">

    <route id="_preview_error" path="/{code}.{_format}">
        <default key="_controller">error_controller::preview</default>
        <default key="_format">html</default>
        <requirement key="code">\d+</requirement>
    </route>
</routes>
<?xml version="1.0" encoding="UTF-8" ?>

<routes xmlns="http://symfony.com/schema/routing"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://symfony.com/schema/routing https://symfony.com/schema/routing/routing-1.0.xsd">

    <route id="_webhook_controller" path="/{type}">
        <default key="_controller">webhook.controller::handle</default>
        <requirement key="type">.+</requirement>
    </route>
</routes>
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\DependencyInjection\Loader\Configurator;

use _ContaoManager\Symfony\Component\HtmlSanitizer\HtmlSanitizer;
use _ContaoManager\Symfony\Component\HtmlSanitizer\HtmlSanitizerConfig;
use _ContaoManager\Symfony\Component\HtmlSanitizer\HtmlSanitizerInterface;
return static function (ContainerConfigurator $container) {
    $container->services()->set('html_sanitizer.config.default', HtmlSanitizerConfig::class)->call('allowSafeElements', [], \true)->set('html_sanitizer.sanitizer.default', HtmlSanitizer::class)->args([service('html_sanitizer.config.default')])->tag('html_sanitizer', ['sanitizer' => 'default'])->alias('html_sanitizer', 'html_sanitizer.sanitizer.default')->alias(HtmlSanitizerInterface::class, 'html_sanitizer');
};
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\DependencyInjection\Loader\Configurator;

use _ContaoManager\Symfony\Bundle\FrameworkBundle\Secrets\DotenvVault;
use _ContaoManager\Symfony\Bundle\FrameworkBundle\Secrets\SodiumVault;
return static function (ContainerConfigurator $container) {
    $container->services()->set('secrets.vault', SodiumVault::class)->args([abstract_arg('Secret dir, set in FrameworkExtension'), service('secrets.decryption_key')->ignoreOnInvalid()])->tag('container.env_var_loader')->set('secrets.decryption_key')->parent('container.env')->args([abstract_arg('Decryption env var, set in FrameworkExtension')])->set('secrets.local_vault', DotenvVault::class)->args([abstract_arg('.env file path, set in FrameworkExtension')]);
};
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\DependencyInjection\Loader\Configurator;

use _ContaoManager\Symfony\Component\Form\ChoiceList\Factory\CachingFactoryDecorator;
use _ContaoManager\Symfony\Component\Form\ChoiceList\Factory\DefaultChoiceListFactory;
use _ContaoManager\Symfony\Component\Form\ChoiceList\Factory\PropertyAccessDecorator;
use _ContaoManager\Symfony\Component\Form\Extension\Core\Type\ChoiceType;
use _ContaoManager\Symfony\Component\Form\Extension\Core\Type\ColorType;
use _ContaoManager\Symfony\Component\Form\Extension\Core\Type\FileType;
use _ContaoManager\Symfony\Component\Form\Extension\Core\Type\FormType;
use _ContaoManager\Symfony\Component\Form\Extension\Core\Type\SubmitType;
use _ContaoManager\Symfony\Component\Form\Extension\Core\Type\TextType;
use _ContaoManager\Symfony\Component\Form\Extension\Core\Type\TransformationFailureExtension;
use _ContaoManager\Symfony\Component\Form\Extension\DependencyInjection\DependencyInjectionExtension;
use _ContaoManager\Symfony\Component\Form\Extension\HtmlSanitizer\Type\TextTypeHtmlSanitizerExtension;
use _ContaoManager\Symfony\Component\Form\Extension\HttpFoundation\HttpFoundationRequestHandler;
use _ContaoManager\Symfony\Component\Form\Extension\HttpFoundation\Type\FormTypeHttpFoundationExtension;
use _ContaoManager\Symfony\Component\Form\Extension\Validator\Type\FormTypeValidatorExtension;
use _ContaoManager\Symfony\Component\Form\Extension\Validator\Type\RepeatedTypeValidatorExtension;
use _ContaoManager\Symfony\Component\Form\Extension\Validator\Type\SubmitTypeValidatorExtension;
use _ContaoManager\Symfony\Component\Form\Extension\Validator\Type\UploadValidatorExtension;
use _ContaoManager\Symfony\Component\Form\Extension\Validator\ValidatorTypeGuesser;
use _ContaoManager\Symfony\Component\Form\FormFactory;
use _ContaoManager\Symfony\Component\Form\FormFactoryInterface;
use _ContaoManager\Symfony\Component\Form\FormRegistry;
use _ContaoManager\Symfony\Component\Form\FormRegistryInterface;
use _ContaoManager\Symfony\Component\Form\ResolvedFormTypeFactory;
use _ContaoManager\Symfony\Component\Form\ResolvedFormTypeFactoryInterface;
use _ContaoManager\Symfony\Component\Form\Util\ServerParams;
return static function (ContainerConfigurator $container) {
    $container->services()->set('form.resolved_type_factory', ResolvedFormTypeFactory::class)->alias(ResolvedFormTypeFactoryInterface::class, 'form.resolved_type_factory')->set('form.registry', FormRegistry::class)->args([[
        /*
         * We don't need to be able to add more extensions.
         * more types can be registered with the form.type tag
         * more type extensions can be registered with the form.type_extension tag
         * more type_guessers can be registered with the form.type_guesser tag
         */
        service('form.extension'),
    ], service('form.resolved_type_factory')])->alias(FormRegistryInterface::class, 'form.registry')->set('form.factory', FormFactory::class)->args([service('form.registry')])->alias(FormFactoryInterface::class, 'form.factory')->set('form.extension', DependencyInjectionExtension::class)->args([abstract_arg('All services with tag "form.type" are stored in a service locator by FormPass'), abstract_arg('All services with tag "form.type_extension" are stored here by FormPass'), abstract_arg('All services with tag "form.type_guesser" are stored here by FormPass')])->set('form.type_guesser.validator', ValidatorTypeGuesser::class)->args([service('validator.mapping.class_metadata_factory')])->tag('form.type_guesser')->alias('form.property_accessor', 'property_accessor')->set('form.choice_list_factory.default', DefaultChoiceListFactory::class)->set('form.choice_list_factory.property_access', PropertyAccessDecorator::class)->args([service('form.choice_list_factory.default'), service('form.property_accessor')])->set('form.choice_list_factory.cached', CachingFactoryDecorator::class)->args([service('form.choice_list_factory.property_access')])->tag('kernel.reset', ['method' => 'reset'])->alias('form.choice_list_factory', 'form.choice_list_factory.cached')->set('form.type.form', FormType::class)->args([service('form.property_accessor')])->tag('form.type')->set('form.type.choice', ChoiceType::class)->args([service('form.choice_list_factory'), service('translator')->ignoreOnInvalid()])->tag('form.type')->set('form.type.file', FileType::class)->args([service('translator')->ignoreOnInvalid()])->tag('form.type')->set('form.type.color', ColorType::class)->args([service('translator')->ignoreOnInvalid()])->tag('form.type')->set('form.type_extension.form.transformation_failure_handling', TransformationFailureExtension::class)->args([service('translator')->ignoreOnInvalid()])->tag('form.type_extension', ['extended-type' => FormType::class])->set('form.type_extension.form.html_sanitizer', TextTypeHtmlSanitizerExtension::class)->args([tagged_locator('html_sanitizer', 'sanitizer')])->tag('form.type_extension', ['extended-type' => TextType::class])->set('form.type_extension.form.http_foundation', FormTypeHttpFoundationExtension::class)->args([service('form.type_extension.form.request_handler')])->tag('form.type_extension')->set('form.type_extension.form.request_handler', HttpFoundationRequestHandler::class)->args([service('form.server_params')])->set('form.server_params', ServerParams::class)->args([service('request_stack')])->set('form.type_extension.form.validator', FormTypeValidatorExtension::class)->args([service('validator'), \false, service('twig.form.renderer')->ignoreOnInvalid(), service('translator')->ignoreOnInvalid()])->tag('form.type_extension', ['extended-type' => FormType::class])->set('form.type_extension.repeated.validator', RepeatedTypeValidatorExtension::class)->tag('form.type_extension')->set('form.type_extension.submit.validator', SubmitTypeValidatorExtension::class)->tag('form.type_extension', ['extended-type' => SubmitType::class])->set('form.type_extension.upload.validator', UploadValidatorExtension::class)->args([service('translator'), param('validator.translation_domain')])->tag('form.type_extension');
};
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\DependencyInjection\Loader\Configurator;

use _ContaoManager\Symfony\Component\Serializer\DataCollector\SerializerDataCollector;
use _ContaoManager\Symfony\Component\Serializer\Debug\TraceableSerializer;
return static function (ContainerConfigurator $container) {
    $container->services()->set('debug.serializer', TraceableSerializer::class)->decorate('serializer')->args([service('debug.serializer.inner'), service('serializer.data_collector')])->set('serializer.data_collector', SerializerDataCollector::class)->tag('data_collector', ['template' => '@WebProfiler/Collector/serializer.html.twig', 'id' => 'serializer']);
};
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\DependencyInjection\Loader\Configurator;

use _ContaoManager\Symfony\Component\Workflow\DataCollector\WorkflowDataCollector;
return static function (ContainerConfigurator $container) {
    $container->services()->set('data_collector.workflow', WorkflowDataCollector::class)->tag('data_collector', ['template' => '@WebProfiler/Collector/workflow.html.twig', 'id' => 'workflow'])->args([tagged_iterator('workflow', 'name'), service('event_dispatcher'), service('debug.file_link_formatter')]);
};
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\DependencyInjection\Loader\Configurator;

use _ContaoManager\Symfony\Component\Mailer\Bridge\Brevo\RemoteEvent\BrevoPayloadConverter;
use _ContaoManager\Symfony\Component\Mailer\Bridge\Brevo\Webhook\BrevoRequestParser;
use _ContaoManager\Symfony\Component\Mailer\Bridge\Mailgun\RemoteEvent\MailgunPayloadConverter;
use _ContaoManager\Symfony\Component\Mailer\Bridge\Mailgun\Webhook\MailgunRequestParser;
use _ContaoManager\Symfony\Component\Mailer\Bridge\Mailjet\RemoteEvent\MailjetPayloadConverter;
use _ContaoManager\Symfony\Component\Mailer\Bridge\Mailjet\Webhook\MailjetRequestParser;
use _ContaoManager\Symfony\Component\Mailer\Bridge\Postmark\RemoteEvent\PostmarkPayloadConverter;
use _ContaoManager\Symfony\Component\Mailer\Bridge\Postmark\Webhook\PostmarkRequestParser;
use _ContaoManager\Symfony\Component\Mailer\Bridge\Sendgrid\RemoteEvent\SendgridPayloadConverter;
use _ContaoManager\Symfony\Component\Mailer\Bridge\Sendgrid\Webhook\SendgridRequestParser;
return static function (ContainerConfigurator $container) {
    $container->services()->set('mailer.payload_converter.brevo', BrevoPayloadConverter::class)->set('mailer.webhook.request_parser.brevo', BrevoRequestParser::class)->args([service('mailer.payload_converter.brevo')])->alias(BrevoRequestParser::class, 'mailer.webhook.request_parser.brevo')->set('mailer.payload_converter.mailgun', MailgunPayloadConverter::class)->set('mailer.webhook.request_parser.mailgun', MailgunRequestParser::class)->args([service('mailer.payload_converter.mailgun')])->alias(MailgunRequestParser::class, 'mailer.webhook.request_parser.mailgun')->set('mailer.payload_converter.mailjet', MailjetPayloadConverter::class)->set('mailer.webhook.request_parser.mailjet', MailjetRequestParser::class)->args([service('mailer.payload_converter.mailjet')])->alias(MailjetRequestParser::class, 'mailer.webhook.request_parser.mailjet')->set('mailer.payload_converter.postmark', PostmarkPayloadConverter::class)->set('mailer.webhook.request_parser.postmark', PostmarkRequestParser::class)->args([service('mailer.payload_converter.postmark')])->alias(PostmarkRequestParser::class, 'mailer.webhook.request_parser.postmark')->set('mailer.payload_converter.sendgrid', SendgridPayloadConverter::class)->set('mailer.webhook.request_parser.sendgrid', SendgridRequestParser::class)->args([service('mailer.payload_converter.sendgrid')])->alias(SendgridRequestParser::class, 'mailer.webhook.request_parser.sendgrid');
};
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\DependencyInjection\Loader\Configurator;

use _ContaoManager\Symfony\Component\Form\Extension\Csrf\Type\FormTypeCsrfExtension;
return static function (ContainerConfigurator $container) {
    $container->services()->set('form.type_extension.csrf', FormTypeCsrfExtension::class)->args([service('security.csrf.token_manager'), param('form.type_extension.csrf.enabled'), param('form.type_extension.csrf.field_name'), service('translator')->nullOnInvalid(), param('validator.translation_domain'), service('form.server_params')])->tag('form.type_extension');
};
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\DependencyInjection\Loader\Configurator;

use _ContaoManager\Symfony\Component\Workflow\EventListener\ExpressionLanguage;
use _ContaoManager\Symfony\Component\Workflow\MarkingStore\MethodMarkingStore;
use _ContaoManager\Symfony\Component\Workflow\Registry;
use _ContaoManager\Symfony\Component\Workflow\StateMachine;
use _ContaoManager\Symfony\Component\Workflow\Workflow;
return static function (ContainerConfigurator $container) {
    $container->services()->set('workflow.abstract', Workflow::class)->args([abstract_arg('workflow definition'), abstract_arg('marking store'), service('event_dispatcher')->ignoreOnInvalid(), abstract_arg('workflow name'), abstract_arg('events to dispatch')])->abstract()->set('state_machine.abstract', StateMachine::class)->args([abstract_arg('workflow definition'), abstract_arg('marking store'), service('event_dispatcher')->ignoreOnInvalid(), abstract_arg('workflow name'), abstract_arg('events to dispatch')])->abstract()->set('workflow.marking_store.method', MethodMarkingStore::class)->abstract()->set('workflow.registry', Registry::class)->alias(Registry::class, 'workflow.registry')->set('workflow.security.expression_language', ExpressionLanguage::class);
};
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\DependencyInjection\Loader\Configurator;

use _ContaoManager\Symfony\Bridge\Twig\Extension\CsrfExtension;
use _ContaoManager\Symfony\Bridge\Twig\Extension\CsrfRuntime;
use _ContaoManager\Symfony\Component\Security\Csrf\CsrfTokenManager;
use _ContaoManager\Symfony\Component\Security\Csrf\CsrfTokenManagerInterface;
use _ContaoManager\Symfony\Component\Security\Csrf\TokenGenerator\TokenGeneratorInterface;
use _ContaoManager\Symfony\Component\Security\Csrf\TokenGenerator\UriSafeTokenGenerator;
use _ContaoManager\Symfony\Component\Security\Csrf\TokenStorage\SessionTokenStorage;
use _ContaoManager\Symfony\Component\Security\Csrf\TokenStorage\TokenStorageInterface;
return static function (ContainerConfigurator $container) {
    $container->services()->set('security.csrf.token_generator', UriSafeTokenGenerator::class)->alias(TokenGeneratorInterface::class, 'security.csrf.token_generator')->set('security.csrf.token_storage', SessionTokenStorage::class)->args([service('request_stack')])->alias(TokenStorageInterface::class, 'security.csrf.token_storage')->set('security.csrf.token_manager', CsrfTokenManager::class)->args([service('security.csrf.token_generator'), service('security.csrf.token_storage'), service('request_stack')->ignoreOnInvalid()])->alias(CsrfTokenManagerInterface::class, 'security.csrf.token_manager')->set('twig.runtime.security_csrf', CsrfRuntime::class)->args([service('security.csrf.token_manager')])->tag('twig.runtime')->set('twig.extension.security_csrf', CsrfExtension::class)->tag('twig.extension');
};
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\DependencyInjection\Loader\Configurator;

use _ContaoManager\Symfony\Component\Notifier\Bridge;
use _ContaoManager\Symfony\Component\Notifier\Transport\AbstractTransportFactory;
use _ContaoManager\Symfony\Component\Notifier\Transport\NullTransportFactory;
return static function (ContainerConfigurator $container) {
    $container->services()->set('notifier.transport_factory.abstract', AbstractTransportFactory::class)->abstract()->args([service('event_dispatcher'), service('http_client')->ignoreOnInvalid()])->set('notifier.transport_factory.brevo', Bridge\Brevo\BrevoTransportFactory::class)->parent('notifier.transport_factory.abstract')->tag('texter.transport_factory')->set('notifier.transport_factory.slack', Bridge\Slack\SlackTransportFactory::class)->parent('notifier.transport_factory.abstract')->tag('chatter.transport_factory')->set('notifier.transport_factory.linked-in', Bridge\LinkedIn\LinkedInTransportFactory::class)->parent('notifier.transport_factory.abstract')->tag('chatter.transport_factory')->set('notifier.transport_factory.telegram', Bridge\Telegram\TelegramTransportFactory::class)->parent('notifier.transport_factory.abstract')->tag('chatter.transport_factory')->set('notifier.transport_factory.mattermost', Bridge\Mattermost\MattermostTransportFactory::class)->parent('notifier.transport_factory.abstract')->tag('chatter.transport_factory')->set('notifier.transport_factory.vonage', Bridge\Vonage\VonageTransportFactory::class)->parent('notifier.transport_factory.abstract')->tag('texter.transport_factory')->set('notifier.transport_factory.rocket-chat', Bridge\RocketChat\RocketChatTransportFactory::class)->parent('notifier.transport_factory.abstract')->tag('chatter.transport_factory')->set('notifier.transport_factory.google-chat', Bridge\GoogleChat\GoogleChatTransportFactory::class)->parent('notifier.transport_factory.abstract')->tag('chatter.transport_factory')->set('notifier.transport_factory.twilio', Bridge\Twilio\TwilioTransportFactory::class)->parent('notifier.transport_factory.abstract')->tag('texter.transport_factory')->set('notifier.transport_factory.twitter', Bridge\Twitter\TwitterTransportFactory::class)->parent('notifier.transport_factory.abstract')->tag('chatter.transport_factory')->set('notifier.transport_factory.all-my-sms', Bridge\AllMySms\AllMySmsTransportFactory::class)->parent('notifier.transport_factory.abstract')->tag('texter.transport_factory')->set('notifier.transport_factory.firebase', Bridge\Firebase\FirebaseTransportFactory::class)->parent('notifier.transport_factory.abstract')->tag('chatter.transport_factory')->set('notifier.transport_factory.forty-six-elks', Bridge\FortySixElks\FortySixElksTransportFactory::class)->parent('notifier.transport_factory.abstract')->tag('texter.transport_factory')->set('notifier.transport_factory.free-mobile', Bridge\FreeMobile\FreeMobileTransportFactory::class)->parent('notifier.transport_factory.abstract')->tag('texter.transport_factory')->set('notifier.transport_factory.spot-hit', Bridge\SpotHit\SpotHitTransportFactory::class)->parent('notifier.transport_factory.abstract')->tag('texter.transport_factory')->set('notifier.transport_factory.fake-chat', Bridge\FakeChat\FakeChatTransportFactory::class)->parent('notifier.transport_factory.abstract')->tag('chatter.transport_factory')->set('notifier.transport_factory.fake-sms', Bridge\FakeSms\FakeSmsTransportFactory::class)->parent('notifier.transport_factory.abstract')->tag('texter.transport_factory')->set('notifier.transport_factory.ovh-cloud', Bridge\OvhCloud\OvhCloudTransportFactory::class)->parent('notifier.transport_factory.abstract')->tag('texter.transport_factory')->set('notifier.transport_factory.sinch', Bridge\Sinch\SinchTransportFactory::class)->parent('notifier.transport_factory.abstract')->tag('texter.transport_factory')->set('notifier.transport_factory.zulip', Bridge\Zulip\ZulipTransportFactory::class)->parent('notifier.transport_factory.abstract')->tag('chatter.transport_factory')->set('notifier.transport_factory.infobip', Bridge\Infobip\InfobipTransportFactory::class)->parent('notifier.transport_factory.abstract')->tag('texter.transport_factory')->set('notifier.transport_factory.isendpro', Bridge\Isendpro\IsendproTransportFactory::class)->parent('notifier.transport_factory.abstract')->tag('texter.transport_factory')->set('notifier.transport_factory.mobyt', Bridge\Mobyt\MobytTransportFactory::class)->parent('notifier.transport_factory.abstract')->tag('texter.transport_factory')->set('notifier.transport_factory.smsapi', Bridge\Smsapi\SmsapiTransportFactory::class)->parent('notifier.transport_factory.abstract')->tag('texter.transport_factory')->set('notifier.transport_factory.esendex', Bridge\Esendex\EsendexTransportFactory::class)->parent('notifier.transport_factory.abstract')->tag('texter.transport_factory')->set('notifier.transport_factory.sendberry', Bridge\Sendberry\SendberryTransportFactory::class)->parent('notifier.transport_factory.abstract')->tag('texter.transport_factory')->set('notifier.transport_factory.sendinblue', Bridge\Sendinblue\SendinblueTransportFactory::class)->parent('notifier.transport_factory.abstract')->tag('texter.transport_factory')->set('notifier.transport_factory.iqsms', Bridge\Iqsms\IqsmsTransportFactory::class)->parent('notifier.transport_factory.abstract')->tag('texter.transport_factory')->set('notifier.transport_factory.octopush', Bridge\Octopush\OctopushTransportFactory::class)->parent('notifier.transport_factory.abstract')->tag('texter.transport_factory')->set('notifier.transport_factory.discord', Bridge\Discord\DiscordTransportFactory::class)->parent('notifier.transport_factory.abstract')->tag('chatter.transport_factory')->set('notifier.transport_factory.microsoft-teams', Bridge\MicrosoftTeams\MicrosoftTeamsTransportFactory::class)->parent('notifier.transport_factory.abstract')->tag('chatter.transport_factory')->set('notifier.transport_factory.gateway-api', Bridge\GatewayApi\GatewayApiTransportFactory::class)->parent('notifier.transport_factory.abstract')->tag('texter.transport_factory')->set('notifier.transport_factory.mercure', Bridge\Mercure\MercureTransportFactory::class)->parent('notifier.transport_factory.abstract')->tag('chatter.transport_factory')->set('notifier.transport_factory.gitter', Bridge\Gitter\GitterTransportFactory::class)->parent('notifier.transport_factory.abstract')->tag('chatter.transport_factory')->set('notifier.transport_factory.clickatell', Bridge\Clickatell\ClickatellTransportFactory::class)->parent('notifier.transport_factory.abstract')->tag('texter.transport_factory')->set('notifier.transport_factory.contact-everyone', Bridge\ContactEveryone\ContactEveryoneTransportFactory::class)->parent('notifier.transport_factory.abstract')->tag('texter.transport_factory')->set('notifier.transport_factory.amazon-sns', Bridge\AmazonSns\AmazonSnsTransportFactory::class)->parent('notifier.transport_factory.abstract')->tag('texter.transport_factory')->tag('chatter.transport_factory')->set('notifier.transport_factory.null', NullTransportFactory::class)->parent('notifier.transport_factory.abstract')->tag('chatter.transport_factory')->tag('texter.transport_factory')->set('notifier.transport_factory.light-sms', Bridge\LightSms\LightSmsTransportFactory::class)->parent('notifier.transport_factory.abstract')->tag('texter.transport_factory')->set('notifier.transport_factory.sms-biuras', Bridge\SmsBiuras\SmsBiurasTransportFactory::class)->parent('notifier.transport_factory.abstract')->tag('texter.transport_factory')->set('notifier.transport_factory.smsc', Bridge\Smsc\SmscTransportFactory::class)->parent('notifier.transport_factory.abstract')->tag('texter.transport_factory')->set('notifier.transport_factory.sms-factor', Bridge\SmsFactor\SmsFactorTransportFactory::class)->parent('notifier.transport_factory.abstract')->tag('texter.transport_factory')->set('notifier.transport_factory.message-bird', Bridge\MessageBird\MessageBirdTransportFactory::class)->parent('notifier.transport_factory.abstract')->tag('texter.transport_factory')->set('notifier.transport_factory.message-media', Bridge\MessageMedia\MessageMediaTransportFactory::class)->parent('notifier.transport_factory.abstract')->tag('texter.transport_factory')->set('notifier.transport_factory.telnyx', Bridge\Telnyx\TelnyxTransportFactory::class)->parent('notifier.transport_factory.abstract')->tag('texter.transport_factory')->set('notifier.transport_factory.mailjet', Bridge\Mailjet\MailjetTransportFactory::class)->parent('notifier.transport_factory.abstract')->tag('texter.transport_factory')->set('notifier.transport_factory.yunpian', Bridge\Yunpian\YunpianTransportFactory::class)->parent('notifier.transport_factory.abstract')->tag('texter.transport_factory')->set('notifier.transport_factory.turbo-sms', Bridge\TurboSms\TurboSmsTransportFactory::class)->parent('notifier.transport_factory.abstract')->tag('texter.transport_factory')->set('notifier.transport_factory.sms77', Bridge\Sms77\Sms77TransportFactory::class)->parent('notifier.transport_factory.abstract')->tag('texter.transport_factory')->set('notifier.transport_factory.one-signal', Bridge\OneSignal\OneSignalTransportFactory::class)->parent('notifier.transport_factory.abstract')->tag('texter.transport_factory')->set('notifier.transport_factory.orange-sms', Bridge\OrangeSms\OrangeSmsTransportFactory::class)->parent('notifier.transport_factory.abstract')->tag('texter.transport_factory')->set('notifier.transport_factory.expo', Bridge\Expo\ExpoTransportFactory::class)->parent('notifier.transport_factory.abstract')->tag('texter.transport_factory')->set('notifier.transport_factory.kaz-info-teh', Bridge\KazInfoTeh\KazInfoTehTransportFactory::class)->parent('notifier.transport_factory.abstract')->tag('texter.transport_factory')->set('notifier.transport_factory.engagespot', Bridge\Engagespot\EngagespotTransportFactory::class)->parent('notifier.transport_factory.abstract')->tag('texter.transport_factory')->set('notifier.transport_factory.zendesk', Bridge\Zendesk\ZendeskTransportFactory::class)->parent('notifier.transport_factory.abstract')->tag('chatter.transport_factory')->set('notifier.transport_factory.chatwork', Bridge\Chatwork\ChatworkTransportFactory::class)->parent('notifier.transport_factory.abstract')->tag('chatter.transport_factory')->set('notifier.transport_factory.termii', Bridge\Termii\TermiiTransportFactory::class)->parent('notifier.transport_factory.abstract')->tag('texter.transport_factory')->set('notifier.transport_factory.ring-central', Bridge\RingCentral\RingCentralTransportFactory::class)->parent('notifier.transport_factory.abstract')->tag('texter.transport_factory')->set('notifier.transport_factory.plivo', Bridge\Plivo\PlivoTransportFactory::class)->parent('notifier.transport_factory.abstract')->tag('texter.transport_factory')->set('notifier.transport_factory.bandwidth', Bridge\Bandwidth\BandwidthTransportFactory::class)->parent('notifier.transport_factory.abstract')->tag('texter.transport_factory')->set('notifier.transport_factory.line-notify', Bridge\LineNotify\LineNotifyTransportFactory::class)->parent('notifier.transport_factory.abstract')->tag('chatter.transport_factory')->set('notifier.transport_factory.mastodon', Bridge\Mastodon\MastodonTransportFactory::class)->parent('notifier.transport_factory.abstract')->tag('chatter.transport_factory')->set('notifier.transport_factory.pager-duty', Bridge\PagerDuty\PagerDutyTransportFactory::class)->parent('notifier.transport_factory.abstract')->tag('chatter.transport_factory')->set('notifier.transport_factory.pushover', Bridge\Pushover\PushoverTransportFactory::class)->parent('notifier.transport_factory.abstract')->tag('texter.transport_factory')->set('notifier.transport_factory.simple-textin', Bridge\SimpleTextin\SimpleTextinTransportFactory::class)->parent('notifier.transport_factory.abstract')->tag('texter.transport_factory')->set('notifier.transport_factory.click-send', Bridge\ClickSend\ClickSendTransportFactory::class)->parent('notifier.transport_factory.abstract')->tag('texter.transport_factory')->set('notifier.transport_factory.smsmode', Bridge\Smsmode\SmsmodeTransportFactory::class)->parent('notifier.transport_factory.abstract')->tag('texter.transport_factory')->set('notifier.transport_factory.novu', Bridge\Novu\NovuTransportFactory::class)->parent('notifier.transport_factory.abstract')->tag('texter.transport_factory')->set('notifier.transport_factory.ntfy', Bridge\Ntfy\NtfyTransportFactory::class)->parent('notifier.transport_factory.abstract')->tag('texter.transport_factory')->set('notifier.transport_factory.redlink', Bridge\Redlink\RedlinkTransportFactory::class)->parent('notifier.transport_factory.abstract')->tag('texter.transport_factory')->set('notifier.transport_factory.go-ip', Bridge\GoIp\GoIpTransportFactory::class)->parent('notifier.transport_factory.abstract')->tag('texter.transport_factory');
};
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\DependencyInjection\Loader\Configurator;

use _ContaoManager\Symfony\Component\ErrorHandler\ErrorRenderer\FileLinkFormatter;
use _ContaoManager\Symfony\Component\HttpKernel\Debug\ErrorHandlerConfigurator;
use _ContaoManager\Symfony\Component\HttpKernel\EventListener\DebugHandlersListener;
return static function (ContainerConfigurator $container) {
    $container->parameters()->set('debug.error_handler.throw_at', -1);
    $container->services()->set('debug.error_handler_configurator', ErrorHandlerConfigurator::class)->public()->args([
        service('logger')->nullOnInvalid(),
        null,
        // Log levels map for enabled error levels
        param('debug.error_handler.throw_at'),
        param('kernel.debug'),
        param('kernel.debug'),
        null,
    ])->tag('monolog.logger', ['channel' => 'php'])->set('debug.debug_handlers_listener', DebugHandlersListener::class)->args([null, param('kernel.runtime_mode.web')])->tag('kernel.event_subscriber')->set('debug.file_link_formatter', FileLinkFormatter::class)->args([param('debug.file_link_format')])->alias(FileLinkFormatter::class, 'debug.file_link_formatter');
};
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\DependencyInjection\Loader\Configurator;

use _ContaoManager\Symfony\Component\PropertyAccess\PropertyAccessor;
use _ContaoManager\Symfony\Component\PropertyAccess\PropertyAccessorInterface;
return static function (ContainerConfigurator $container) {
    $container->services()->set('property_accessor', PropertyAccessor::class)->args([abstract_arg('magic methods allowed, set by the extension'), abstract_arg('throw exceptions, set by the extension'), service('cache.property_access')->ignoreOnInvalid(), abstract_arg('propertyReadInfoExtractor, set by the extension'), abstract_arg('propertyWriteInfoExtractor, set by the extension')])->alias(PropertyAccessorInterface::class, 'property_accessor');
};
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\DependencyInjection\Loader\Configurator;

use _ContaoManager\Symfony\Component\Asset\Context\RequestStackContext;
use _ContaoManager\Symfony\Component\Asset\Package;
use _ContaoManager\Symfony\Component\Asset\Packages;
use _ContaoManager\Symfony\Component\Asset\PathPackage;
use _ContaoManager\Symfony\Component\Asset\UrlPackage;
use _ContaoManager\Symfony\Component\Asset\VersionStrategy\EmptyVersionStrategy;
use _ContaoManager\Symfony\Component\Asset\VersionStrategy\JsonManifestVersionStrategy;
use _ContaoManager\Symfony\Component\Asset\VersionStrategy\StaticVersionStrategy;
return static function (ContainerConfigurator $container) {
    $container->parameters()->set('asset.request_context.base_path', null)->set('asset.request_context.secure', null);
    $container->services()->set('assets.packages', Packages::class)->args([service('assets._default_package'), tagged_iterator('assets.package', 'package')])->alias(Packages::class, 'assets.packages')->set('assets.empty_package', Package::class)->args([service('assets.empty_version_strategy')])->alias('assets._default_package', 'assets.empty_package')->set('assets.context', RequestStackContext::class)->args([service('request_stack'), param('asset.request_context.base_path'), param('asset.request_context.secure')])->set('assets.path_package', PathPackage::class)->abstract()->args([abstract_arg('base path'), abstract_arg('version strategy'), service('assets.context')])->set('assets.url_package', UrlPackage::class)->abstract()->args([abstract_arg('base URLs'), abstract_arg('version strategy'), service('assets.context')])->set('assets.static_version_strategy', StaticVersionStrategy::class)->abstract()->args([abstract_arg('version'), abstract_arg('format')])->set('assets.empty_version_strategy', EmptyVersionStrategy::class)->set('assets.json_manifest_version_strategy', JsonManifestVersionStrategy::class)->abstract()->args([abstract_arg('manifest path'), service('http_client')->nullOnInvalid(), \false]);
};
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\DependencyInjection\Loader\Configurator;

use _ContaoManager\Symfony\Bundle\FrameworkBundle\CacheWarmer\CachePoolClearerCacheWarmer;
use _ContaoManager\Symfony\Component\Cache\DataCollector\CacheDataCollector;
return static function (ContainerConfigurator $container) {
    $container->services()->set('data_collector.cache', CacheDataCollector::class)->public()->tag('data_collector', ['template' => '@WebProfiler/Collector/cache.html.twig', 'id' => 'cache', 'priority' => 275])->set('cache_pool_clearer.cache_warmer', CachePoolClearerCacheWarmer::class)->args([service('cache.system_clearer'), ['cache.validator', 'cache.serializer']])->tag('kernel.cache_warmer', ['priority' => 64]);
};
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\DependencyInjection\Loader\Configurator;

use _ContaoManager\Symfony\Component\RemoteEvent\Messenger\ConsumeRemoteEventHandler;
return static function (ContainerConfigurator $container) {
    $container->services()->set('remote_event.messenger.handler', ConsumeRemoteEventHandler::class)->args([tagged_locator('remote_event.consumer', 'consumer')])->tag('messenger.message_handler');
};
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\DependencyInjection\Loader\Configurator;

use _ContaoManager\Symfony\Component\Process\Messenger\RunProcessMessageHandler;
return static function (ContainerConfigurator $container) {
    $container->services()->set('process.messenger.process_message_handler', RunProcessMessageHandler::class)->tag('messenger.message_handler');
};
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Bundle\FrameworkBundle;

use _ContaoManager\Symfony\Bundle\FrameworkBundle\Test\TestBrowserToken;
use _ContaoManager\Symfony\Component\BrowserKit\Cookie;
use _ContaoManager\Symfony\Component\BrowserKit\CookieJar;
use _ContaoManager\Symfony\Component\BrowserKit\History;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerInterface;
use _ContaoManager\Symfony\Component\HttpFoundation\Request;
use _ContaoManager\Symfony\Component\HttpFoundation\Response;
use _ContaoManager\Symfony\Component\HttpKernel\HttpKernelBrowser;
use _ContaoManager\Symfony\Component\HttpKernel\KernelInterface;
use _ContaoManager\Symfony\Component\HttpKernel\Profiler\Profile as HttpProfile;
use _ContaoManager\Symfony\Component\Security\Core\User\UserInterface;
/**
 * Simulates a browser and makes requests to a Kernel object.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class KernelBrowser extends HttpKernelBrowser
{
    private bool $hasPerformedRequest = \false;
    private bool $profiler = \false;
    private bool $reboot = \true;
    public function __construct(KernelInterface $kernel, array $server = [], ?History $history = null, ?CookieJar $cookieJar = null)
    {
        parent::__construct($kernel, $server, $history, $cookieJar);
    }
    /**
     * Returns the container.
     */
    public function getContainer(): ContainerInterface
    {
        $container = $this->kernel->getContainer();
        return $container->has('test.service_container') ? $container->get('test.service_container') : $container;
    }
    /**
     * Returns the kernel.
     */
    public function getKernel(): KernelInterface
    {
        return $this->kernel;
    }
    /**
     * Gets the profile associated with the current Response.
     */
    public function getProfile(): HttpProfile|false|null
    {
        if (null === $this->response || !$this->getContainer()->has('profiler')) {
            return \false;
        }
        return $this->getContainer()->get('profiler')->loadProfileFromResponse($this->response);
    }
    /**
     * Enables the profiler for the very next request.
     *
     * If the profiler is not enabled, the call to this method does nothing.
     *
     * @return void
     */
    public function enableProfiler()
    {
        if ($this->getContainer()->has('profiler')) {
            $this->profiler = \true;
        }
    }
    /**
     * Disables kernel reboot between requests.
     *
     * By default, the Client reboots the Kernel for each request. This method
     * allows to keep the same kernel across requests.
     *
     * @return void
     */
    public function disableReboot()
    {
        $this->reboot = \false;
    }
    /**
     * Enables kernel reboot between requests.
     *
     * @return void
     */
    public function enableReboot()
    {
        $this->reboot = \true;
    }
    /**
     * @param UserInterface        $user
     * @param array<string, mixed> $tokenAttributes
     *
     * @return $this
     */
    public function loginUser(object $user, string $firewallContext = 'main'): static
    {
        $tokenAttributes = 2 < \func_num_args() ? func_get_arg(2) : [];
        if (!interface_exists(UserInterface::class)) {
            throw new \LogicException(\sprintf('"%s" requires symfony/security-core to be installed. Try running "composer require symfony/security-core".', __METHOD__));
        }
        if (!$user instanceof UserInterface) {
            throw new \LogicException(\sprintf('The first argument of "%s" must be instance of "%s", "%s" provided.', __METHOD__, UserInterface::class, get_debug_type($user)));
        }
        $token = new TestBrowserToken($user->getRoles(), $user, $firewallContext);
        $token->setAttributes($tokenAttributes);
        // required for compatibility with Symfony 5.4
        if (method_exists($token, 'isAuthenticated')) {
            $token->setAuthenticated(\true, \false);
        }
        $container = $this->getContainer();
        $container->get('security.untracked_token_storage')->setToken($token);
        if (!$container->has('session.factory')) {
            return $this;
        }
        $session = $container->get('session.factory')->createSession();
        $session->set('_security_' . $firewallContext, serialize($token));
        $session->save();
        $domains = array_unique(array_map(fn(Cookie $cookie) => $cookie->getName() === $session->getName() ? $cookie->getDomain() : '', $this->getCookieJar()->all())) ?: [''];
        foreach ($domains as $domain) {
            $cookie = new Cookie($session->getName(), $session->getId(), null, null, $domain);
            $this->getCookieJar()->set($cookie);
        }
        return $this;
    }
    /**
     * @param Request $request
     */
    protected function doRequest(object $request): Response
    {
        // avoid shutting down the Kernel if no request has been performed yet
        // WebTestCase::createClient() boots the Kernel but do not handle a request
        if ($this->hasPerformedRequest && $this->reboot) {
            $this->kernel->boot();
            $this->kernel->shutdown();
        } else {
            $this->hasPerformedRequest = \true;
        }
        if ($this->profiler) {
            $this->profiler = \false;
            $this->kernel->boot();
            $this->getContainer()->get('profiler')->enable();
        }
        return parent::doRequest($request);
    }
    /**
     * @param Request $request
     */
    protected function doRequestInProcess(object $request): Response
    {
        $response = parent::doRequestInProcess($request);
        $this->profiler = \false;
        return $response;
    }
    /**
     * Returns the script to execute when the request must be insulated.
     *
     * It assumes that the autoloader is named 'autoload.php' and that it is
     * stored in the same directory as the kernel (this is the case for the
     * Symfony Standard Edition). If this is not your case, create your own
     * client and override this method.
     *
     * @param Request $request
     */
    protected function getScript(object $request): string
    {
        $kernel = var_export(serialize($this->kernel), \true);
        $request = var_export(serialize($request), \true);
        $errorReporting = error_reporting();
        $requires = '';
        foreach (get_declared_classes() as $class) {
            if (str_starts_with($class, 'ComposerAutoloaderInit')) {
                $r = new \ReflectionClass($class);
                $file = \dirname($r->getFileName(), 2) . '/autoload.php';
                if (is_file($file)) {
                    $requires .= 'require_once ' . var_export($file, \true) . ";\n";
                }
            }
        }
        if (!$requires) {
            throw new \RuntimeException('Composer autoloader not found.');
        }
        $requires .= 'require_once ' . var_export((new \ReflectionObject($this->kernel))->getFileName(), \true) . ";\n";
        $profilerCode = '';
        if ($this->profiler) {
            $profilerCode = <<<'EOF'
$container = $kernel->getContainer();
$container = $container->has('test.service_container') ? $container->get('test.service_container') : $container;
$container->get('profiler')->enable();
EOF;
        }
        $code = <<<EOF
<?php

error_reporting({$errorReporting});

{$requires}

\$kernel = unserialize({$kernel});
\$kernel->boot();
{$profilerCode}

\$request = unserialize({$request});
EOF;
        return $code . $this->getHandleScript();
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Bundle\FrameworkBundle\CacheWarmer;

use _ContaoManager\Doctrine\Common\Annotations\AnnotationException;
use _ContaoManager\Symfony\Component\Cache\Adapter\ArrayAdapter;
use _ContaoManager\Symfony\Component\Cache\Adapter\PhpArrayAdapter;
use _ContaoManager\Symfony\Component\Validator\Mapping\Factory\LazyLoadingMetadataFactory;
use _ContaoManager\Symfony\Component\Validator\Mapping\Loader\LoaderChain;
use _ContaoManager\Symfony\Component\Validator\Mapping\Loader\LoaderInterface;
use _ContaoManager\Symfony\Component\Validator\Mapping\Loader\XmlFileLoader;
use _ContaoManager\Symfony\Component\Validator\Mapping\Loader\YamlFileLoader;
use _ContaoManager\Symfony\Component\Validator\ValidatorBuilder;
/**
 * Warms up XML and YAML validator metadata.
 *
 * @author Titouan Galopin <galopintitouan@gmail.com>
 */
class ValidatorCacheWarmer extends AbstractPhpFileCacheWarmer
{
    private ValidatorBuilder $validatorBuilder;
    /**
     * @param string $phpArrayFile The PHP file where metadata are cached
     */
    public function __construct(ValidatorBuilder $validatorBuilder, string $phpArrayFile)
    {
        parent::__construct($phpArrayFile);
        $this->validatorBuilder = $validatorBuilder;
    }
    /**
     * @param string|null $buildDir
     */
    protected function doWarmUp(string $cacheDir, ArrayAdapter $arrayAdapter): bool
    {
        $loaders = $this->validatorBuilder->getLoaders();
        $metadataFactory = new LazyLoadingMetadataFactory(new LoaderChain($loaders), $arrayAdapter);
        foreach ($this->extractSupportedLoaders($loaders) as $loader) {
            foreach ($loader->getMappedClasses() as $mappedClass) {
                try {
                    if ($metadataFactory->hasMetadataFor($mappedClass)) {
                        $metadataFactory->getMetadataFor($mappedClass);
                    }
                } catch (AnnotationException) {
                    // ignore failing annotations
                } catch (\Exception $e) {
                    $this->ignoreAutoloadException($mappedClass, $e);
                }
            }
        }
        return \true;
    }
    /**
     * @return string[] A list of classes to preload on PHP 7.4+
     */
    protected function warmUpPhpArrayAdapter(PhpArrayAdapter $phpArrayAdapter, array $values): array
    {
        // make sure we don't cache null values
        $values = array_filter($values, fn($val) => null !== $val);
        return parent::warmUpPhpArrayAdapter($phpArrayAdapter, $values);
    }
    /**
     * @param LoaderInterface[] $loaders
     *
     * @return XmlFileLoader[]|YamlFileLoader[]
     */
    private function extractSupportedLoaders(array $loaders): array
    {
        $supportedLoaders = [];
        foreach ($loaders as $loader) {
            if ($loader instanceof XmlFileLoader || $loader instanceof YamlFileLoader) {
                $supportedLoaders[] = $loader;
            } elseif ($loader instanceof LoaderChain) {
                $supportedLoaders = array_merge($supportedLoaders, $this->extractSupportedLoaders($loader->getLoaders()));
            }
        }
        return $supportedLoaders;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Bundle\FrameworkBundle\CacheWarmer;

use _ContaoManager\Psr\Log\LoggerInterface;
use _ContaoManager\Symfony\Component\Config\Builder\ConfigBuilderGenerator;
use _ContaoManager\Symfony\Component\Config\Builder\ConfigBuilderGeneratorInterface;
use _ContaoManager\Symfony\Component\Config\Definition\ConfigurationInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Container;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerBuilder;
use _ContaoManager\Symfony\Component\DependencyInjection\Extension\ConfigurationExtensionInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Extension\ExtensionInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\ParameterBag\ContainerBag;
use _ContaoManager\Symfony\Component\DependencyInjection\ParameterBag\ParameterBag;
use _ContaoManager\Symfony\Component\HttpKernel\CacheWarmer\CacheWarmerInterface;
use _ContaoManager\Symfony\Component\HttpKernel\Kernel;
use _ContaoManager\Symfony\Component\HttpKernel\KernelInterface;
/**
 * Generate all config builders.
 *
 * @author Tobias Nyholm <tobias.nyholm@gmail.com>
 */
class ConfigBuilderCacheWarmer implements CacheWarmerInterface
{
    private KernelInterface $kernel;
    private ?LoggerInterface $logger;
    public function __construct(KernelInterface $kernel, ?LoggerInterface $logger = null)
    {
        $this->kernel = $kernel;
        $this->logger = $logger;
    }
    /**
     * @param string|null $buildDir
     */
    public function warmUp(string $cacheDir): array
    {
        $buildDir = 1 < \func_num_args() ? func_get_arg(1) : null;
        if (!$buildDir) {
            return [];
        }
        $generator = new ConfigBuilderGenerator($buildDir);
        if ($this->kernel instanceof Kernel) {
            /** @var ContainerBuilder $container */
            $container = \Closure::bind(function (Kernel $kernel) {
                $containerBuilder = $kernel->getContainerBuilder();
                $kernel->prepareContainer($containerBuilder);
                return $containerBuilder;
            }, null, $this->kernel)($this->kernel);
            $extensions = $container->getExtensions();
        } else {
            $extensions = [];
            foreach ($this->kernel->getBundles() as $bundle) {
                $extension = $bundle->getContainerExtension();
                if (null !== $extension) {
                    $extensions[] = $extension;
                }
            }
        }
        foreach ($extensions as $extension) {
            try {
                $this->dumpExtension($extension, $generator);
            } catch (\Exception $e) {
                $this->logger?->warning('Failed to generate ConfigBuilder for extension {extensionClass}: ' . $e->getMessage(), ['exception' => $e, 'extensionClass' => $extension::class]);
            }
        }
        // No need to preload anything
        return [];
    }
    private function dumpExtension(ExtensionInterface $extension, ConfigBuilderGeneratorInterface $generator): void
    {
        $configuration = null;
        if ($extension instanceof ConfigurationInterface) {
            $configuration = $extension;
        } elseif ($extension instanceof ConfigurationExtensionInterface) {
            $container = $this->kernel->getContainer();
            $configuration = $extension->getConfiguration([], new ContainerBuilder($container instanceof Container ? new ContainerBag($container) : new ParameterBag()));
        }
        if (!$configuration) {
            return;
        }
        $generator->build($configuration);
    }
    public function isOptional(): bool
    {
        return \false;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Bundle\FrameworkBundle\CacheWarmer;

use _ContaoManager\Symfony\Component\Cache\Adapter\ArrayAdapter;
use _ContaoManager\Symfony\Component\Cache\Adapter\NullAdapter;
use _ContaoManager\Symfony\Component\Cache\Adapter\PhpArrayAdapter;
use _ContaoManager\Symfony\Component\Config\Resource\ClassExistenceResource;
use _ContaoManager\Symfony\Component\HttpKernel\CacheWarmer\CacheWarmerInterface;
abstract class AbstractPhpFileCacheWarmer implements CacheWarmerInterface
{
    private string $phpArrayFile;
    /**
     * @param string $phpArrayFile The PHP file where metadata are cached
     */
    public function __construct(string $phpArrayFile)
    {
        $this->phpArrayFile = $phpArrayFile;
    }
    public function isOptional(): bool
    {
        return \true;
    }
    /**
     * @param string|null $buildDir
     */
    public function warmUp(string $cacheDir): array
    {
        $buildDir = 1 < \func_num_args() ? func_get_arg(1) : null;
        $arrayAdapter = new ArrayAdapter();
        spl_autoload_register([ClassExistenceResource::class, 'throwOnRequiredClass']);
        try {
            if (!$this->doWarmUp($cacheDir, $arrayAdapter, $buildDir)) {
                return [];
            }
        } finally {
            spl_autoload_unregister([ClassExistenceResource::class, 'throwOnRequiredClass']);
        }
        // the ArrayAdapter stores the values serialized
        // to avoid mutation of the data after it was written to the cache
        // so here we un-serialize the values first
        $values = array_map(fn($val) => null !== $val ? unserialize($val) : null, $arrayAdapter->getValues());
        return $this->warmUpPhpArrayAdapter(new PhpArrayAdapter($this->phpArrayFile, new NullAdapter()), $values);
    }
    /**
     * @return string[] A list of classes to preload on PHP 7.4+
     */
    protected function warmUpPhpArrayAdapter(PhpArrayAdapter $phpArrayAdapter, array $values): array
    {
        return (array) $phpArrayAdapter->warmUp($values);
    }
    /**
     * @internal
     */
    final protected function ignoreAutoloadException(string $class, \Exception $exception): void
    {
        try {
            ClassExistenceResource::throwOnRequiredClass($class, $exception);
        } catch (\ReflectionException) {
        }
    }
    /**
     * @param string|null $buildDir
     *
     * @return bool false if there is nothing to warm-up
     */
    abstract protected function doWarmUp(string $cacheDir, ArrayAdapter $arrayAdapter): bool;
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Bundle\FrameworkBundle\CacheWarmer;

use _ContaoManager\Psr\Container\ContainerInterface;
use _ContaoManager\Symfony\Component\HttpKernel\CacheWarmer\CacheWarmerInterface;
use _ContaoManager\Symfony\Component\HttpKernel\CacheWarmer\WarmableInterface;
use _ContaoManager\Symfony\Component\Routing\RouterInterface;
use _ContaoManager\Symfony\Contracts\Service\ServiceSubscriberInterface;
/**
 * Generates the router matcher and generator classes.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 *
 * @final
 */
class RouterCacheWarmer implements CacheWarmerInterface, ServiceSubscriberInterface
{
    private ContainerInterface $container;
    public function __construct(ContainerInterface $container)
    {
        // As this cache warmer is optional, dependencies should be lazy-loaded, that's why a container should be injected.
        $this->container = $container;
    }
    public function warmUp(string $cacheDir, ?string $buildDir = null): array
    {
        $router = $this->container->get('router');
        if ($router instanceof WarmableInterface) {
            return (array) $router->warmUp($cacheDir, $buildDir);
        }
        throw new \LogicException(\sprintf('The router "%s" cannot be warmed up because it does not implement "%s".', get_debug_type($router), WarmableInterface::class));
    }
    public function isOptional(): bool
    {
        return \true;
    }
    public static function getSubscribedServices(): array
    {
        return ['router' => RouterInterface::class];
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Bundle\FrameworkBundle\CacheWarmer;

use _ContaoManager\Psr\Container\ContainerInterface;
use _ContaoManager\Symfony\Component\HttpKernel\CacheWarmer\CacheWarmerInterface;
use _ContaoManager\Symfony\Component\HttpKernel\CacheWarmer\WarmableInterface;
use _ContaoManager\Symfony\Contracts\Service\ServiceSubscriberInterface;
use _ContaoManager\Symfony\Contracts\Translation\TranslatorInterface;
/**
 * Generates the catalogues for translations.
 *
 * @author Xavier Leune <xavier.leune@gmail.com>
 */
class TranslationsCacheWarmer implements CacheWarmerInterface, ServiceSubscriberInterface
{
    private ContainerInterface $container;
    private TranslatorInterface $translator;
    public function __construct(ContainerInterface $container)
    {
        // As this cache warmer is optional, dependencies should be lazy-loaded, that's why a container should be injected.
        $this->container = $container;
    }
    /**
     * @param string|null $buildDir
     */
    public function warmUp(string $cacheDir): array
    {
        $this->translator ??= $this->container->get('translator');
        if ($this->translator instanceof WarmableInterface) {
            $buildDir = 1 < \func_num_args() ? func_get_arg(1) : null;
            return (array) $this->translator->warmUp($cacheDir, $buildDir);
        }
        return [];
    }
    public function isOptional(): bool
    {
        return \true;
    }
    public static function getSubscribedServices(): array
    {
        return ['translator' => TranslatorInterface::class];
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Bundle\FrameworkBundle\CacheWarmer;

use _ContaoManager\Doctrine\Common\Annotations\AnnotationException;
use _ContaoManager\Symfony\Component\Cache\Adapter\ArrayAdapter;
use _ContaoManager\Symfony\Component\Serializer\Mapping\Factory\CacheClassMetadataFactory;
use _ContaoManager\Symfony\Component\Serializer\Mapping\Factory\ClassMetadataFactory;
use _ContaoManager\Symfony\Component\Serializer\Mapping\Loader\LoaderChain;
use _ContaoManager\Symfony\Component\Serializer\Mapping\Loader\LoaderInterface;
use _ContaoManager\Symfony\Component\Serializer\Mapping\Loader\XmlFileLoader;
use _ContaoManager\Symfony\Component\Serializer\Mapping\Loader\YamlFileLoader;
/**
 * Warms up XML and YAML serializer metadata.
 *
 * @author Titouan Galopin <galopintitouan@gmail.com>
 */
class SerializerCacheWarmer extends AbstractPhpFileCacheWarmer
{
    private array $loaders;
    /**
     * @param LoaderInterface[] $loaders      The serializer metadata loaders
     * @param string            $phpArrayFile The PHP file where metadata are cached
     */
    public function __construct(array $loaders, string $phpArrayFile)
    {
        parent::__construct($phpArrayFile);
        $this->loaders = $loaders;
    }
    /**
     * @param string|null $buildDir
     */
    protected function doWarmUp(string $cacheDir, ArrayAdapter $arrayAdapter): bool
    {
        if (!$this->loaders) {
            return \true;
        }
        $metadataFactory = new CacheClassMetadataFactory(new ClassMetadataFactory(new LoaderChain($this->loaders)), $arrayAdapter);
        foreach ($this->extractSupportedLoaders($this->loaders) as $loader) {
            foreach ($loader->getMappedClasses() as $mappedClass) {
                try {
                    $metadataFactory->getMetadataFor($mappedClass);
                } catch (AnnotationException) {
                    // ignore failing annotations
                } catch (\Exception $e) {
                    $this->ignoreAutoloadException($mappedClass, $e);
                }
            }
        }
        return \true;
    }
    /**
     * @param LoaderInterface[] $loaders
     *
     * @return XmlFileLoader[]|YamlFileLoader[]
     */
    private function extractSupportedLoaders(array $loaders): array
    {
        $supportedLoaders = [];
        foreach ($loaders as $loader) {
            if ($loader instanceof XmlFileLoader || $loader instanceof YamlFileLoader) {
                $supportedLoaders[] = $loader;
            } elseif ($loader instanceof LoaderChain) {
                $supportedLoaders = array_merge($supportedLoaders, $this->extractSupportedLoaders($loader->getLoaders()));
            }
        }
        return $supportedLoaders;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Bundle\FrameworkBundle\CacheWarmer;

use _ContaoManager\Symfony\Component\HttpKernel\CacheClearer\Psr6CacheClearer;
use _ContaoManager\Symfony\Component\HttpKernel\CacheWarmer\CacheWarmerInterface;
/**
 * Clears the cache pools when warming up the cache.
 *
 * Do not use in production!
 *
 * @author Teoh Han Hui <teohhanhui@gmail.com>
 *
 * @internal
 */
final class CachePoolClearerCacheWarmer implements CacheWarmerInterface
{
    private Psr6CacheClearer $poolClearer;
    private array $pools;
    /**
     * @param string[] $pools
     */
    public function __construct(Psr6CacheClearer $poolClearer, array $pools = [])
    {
        $this->poolClearer = $poolClearer;
        $this->pools = $pools;
    }
    public function warmUp(string $cacheDir, ?string $buildDir = null): array
    {
        foreach ($this->pools as $pool) {
            if ($this->poolClearer->hasPool($pool)) {
                $this->poolClearer->clearPool($pool);
            }
        }
        return [];
    }
    public function isOptional(): bool
    {
        // optional cache warmers are not run when handling the request
        return \false;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Bundle\FrameworkBundle\CacheWarmer;

use _ContaoManager\Doctrine\Common\Annotations\AnnotationException;
use _ContaoManager\Doctrine\Common\Annotations\PsrCachedReader;
use _ContaoManager\Doctrine\Common\Annotations\Reader;
use _ContaoManager\Symfony\Component\Cache\Adapter\ArrayAdapter;
use _ContaoManager\Symfony\Component\Cache\Adapter\PhpArrayAdapter;
/**
 * Warms up annotation caches for classes found in composer's autoload class map
 * and declared in DI bundle extensions using the addAnnotatedClassesToCache method.
 *
 * @author Titouan Galopin <galopintitouan@gmail.com>
 *
 * @deprecated since Symfony 6.4 without replacement
 */
class AnnotationsCacheWarmer extends AbstractPhpFileCacheWarmer
{
    /**
     * @param string $phpArrayFile The PHP file where annotations are cached
     */
    public function __construct(private readonly Reader $annotationReader, string $phpArrayFile, private readonly ?string $excludeRegexp = null, private readonly bool $debug = \false)
    {
        if (\func_num_args() < 5 || func_get_arg(4)) {
            trigger_deprecation('symfony/framework-bundle', '6.4', 'The "%s" class is deprecated without replacement.', __CLASS__);
        }
        parent::__construct($phpArrayFile);
    }
    /**
     * @param string|null $buildDir
     */
    protected function doWarmUp(string $cacheDir, ArrayAdapter $arrayAdapter): bool
    {
        $annotatedClassPatterns = $cacheDir . '/annotations.map';
        if (!is_file($annotatedClassPatterns)) {
            return \true;
        }
        $annotatedClasses = include $annotatedClassPatterns;
        $reader = new PsrCachedReader($this->annotationReader, $arrayAdapter, $this->debug);
        foreach ($annotatedClasses as $class) {
            if (null !== $this->excludeRegexp && preg_match($this->excludeRegexp, $class)) {
                continue;
            }
            try {
                $this->readAllComponents($reader, $class);
            } catch (\Exception $e) {
                $this->ignoreAutoloadException($class, $e);
            }
        }
        return \true;
    }
    /**
     * @return string[] A list of classes to preload on PHP 7.4+
     */
    protected function warmUpPhpArrayAdapter(PhpArrayAdapter $phpArrayAdapter, array $values): array
    {
        // make sure we don't cache null values
        $values = array_filter($values, fn($val) => null !== $val);
        return parent::warmUpPhpArrayAdapter($phpArrayAdapter, $values);
    }
    private function readAllComponents(Reader $reader, string $class): void
    {
        $reflectionClass = new \ReflectionClass($class);
        try {
            $reader->getClassAnnotations($reflectionClass);
        } catch (AnnotationException) {
            /*
             * Ignore any AnnotationException to not break the cache warming process if an Annotation is badly
             * configured or could not be found / read / etc.
             *
             * In particular cases, an Annotation in your code can be used and defined only for a specific
             * environment but is always added to the annotations.map file by some Symfony default behaviors,
             * and you always end up with a not found Annotation.
             */
        }
        foreach ($reflectionClass->getMethods() as $reflectionMethod) {
            try {
                $reader->getMethodAnnotations($reflectionMethod);
            } catch (AnnotationException) {
            }
        }
        foreach ($reflectionClass->getProperties() as $reflectionProperty) {
            try {
                $reader->getPropertyAnnotations($reflectionProperty);
            } catch (AnnotationException) {
            }
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Bundle\FrameworkBundle\Controller;

use _ContaoManager\Psr\Container\ContainerInterface;
use _ContaoManager\Psr\Link\EvolvableLinkInterface;
use _ContaoManager\Psr\Link\LinkInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException;
use _ContaoManager\Symfony\Component\DependencyInjection\ParameterBag\ContainerBagInterface;
use _ContaoManager\Symfony\Component\Form\Extension\Core\Type\FormType;
use _ContaoManager\Symfony\Component\Form\FormBuilderInterface;
use _ContaoManager\Symfony\Component\Form\FormFactoryInterface;
use _ContaoManager\Symfony\Component\Form\FormInterface;
use _ContaoManager\Symfony\Component\HttpFoundation\BinaryFileResponse;
use _ContaoManager\Symfony\Component\HttpFoundation\Exception\SessionNotFoundException;
use _ContaoManager\Symfony\Component\HttpFoundation\JsonResponse;
use _ContaoManager\Symfony\Component\HttpFoundation\RedirectResponse;
use _ContaoManager\Symfony\Component\HttpFoundation\Request;
use _ContaoManager\Symfony\Component\HttpFoundation\RequestStack;
use _ContaoManager\Symfony\Component\HttpFoundation\Response;
use _ContaoManager\Symfony\Component\HttpFoundation\ResponseHeaderBag;
use _ContaoManager\Symfony\Component\HttpFoundation\Session\FlashBagAwareSessionInterface;
use _ContaoManager\Symfony\Component\HttpFoundation\StreamedResponse;
use _ContaoManager\Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
use _ContaoManager\Symfony\Component\HttpKernel\HttpKernelInterface;
use _ContaoManager\Symfony\Component\Routing\Generator\UrlGeneratorInterface;
use _ContaoManager\Symfony\Component\Routing\RouterInterface;
use _ContaoManager\Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
use _ContaoManager\Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface;
use _ContaoManager\Symfony\Component\Security\Core\Exception\AccessDeniedException;
use _ContaoManager\Symfony\Component\Security\Core\User\UserInterface;
use _ContaoManager\Symfony\Component\Security\Csrf\CsrfToken;
use _ContaoManager\Symfony\Component\Security\Csrf\CsrfTokenManagerInterface;
use _ContaoManager\Symfony\Component\Serializer\SerializerInterface;
use _ContaoManager\Symfony\Component\WebLink\EventListener\AddLinkHeaderListener;
use _ContaoManager\Symfony\Component\WebLink\GenericLinkProvider;
use _ContaoManager\Symfony\Component\WebLink\HttpHeaderSerializer;
use _ContaoManager\Symfony\Contracts\Service\Attribute\Required;
use _ContaoManager\Symfony\Contracts\Service\ServiceSubscriberInterface;
use _ContaoManager\Twig\Environment;
/**
 * Provides shortcuts for HTTP-related features in controllers.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
abstract class AbstractController implements ServiceSubscriberInterface
{
    /**
     * @var ContainerInterface
     */
    protected $container;
    #[Required]
    public function setContainer(ContainerInterface $container): ?ContainerInterface
    {
        $previous = $this->container ?? null;
        $this->container = $container;
        return $previous;
    }
    /**
     * Gets a container parameter by its name.
     */
    protected function getParameter(string $name): array|bool|string|int|float|\UnitEnum|null
    {
        if (!$this->container->has('parameter_bag')) {
            throw new ServiceNotFoundException('parameter_bag.', null, null, [], \sprintf('The "%s::getParameter()" method is missing a parameter bag to work properly. Did you forget to register your controller as a service subscriber? This can be fixed either by using autoconfiguration or by manually wiring a "parameter_bag" in the service locator passed to the controller.', static::class));
        }
        return $this->container->get('parameter_bag')->get($name);
    }
    public static function getSubscribedServices(): array
    {
        return ['router' => '?' . RouterInterface::class, 'request_stack' => '?' . RequestStack::class, 'http_kernel' => '?' . HttpKernelInterface::class, 'serializer' => '?' . SerializerInterface::class, 'security.authorization_checker' => '?' . AuthorizationCheckerInterface::class, 'twig' => '?' . Environment::class, 'form.factory' => '?' . FormFactoryInterface::class, 'security.token_storage' => '?' . TokenStorageInterface::class, 'security.csrf.token_manager' => '?' . CsrfTokenManagerInterface::class, 'parameter_bag' => '?' . ContainerBagInterface::class, 'web_link.http_header_serializer' => '?' . HttpHeaderSerializer::class];
    }
    /**
     * Generates a URL from the given parameters.
     *
     * @see UrlGeneratorInterface
     */
    protected function generateUrl(string $route, array $parameters = [], int $referenceType = UrlGeneratorInterface::ABSOLUTE_PATH): string
    {
        return $this->container->get('router')->generate($route, $parameters, $referenceType);
    }
    /**
     * Forwards the request to another controller.
     *
     * @param string $controller The controller name (a string like "App\Controller\PostController::index" or "App\Controller\PostController" if it is invokable)
     */
    protected function forward(string $controller, array $path = [], array $query = []): Response
    {
        $request = $this->container->get('request_stack')->getCurrentRequest();
        $path['_controller'] = $controller;
        $subRequest = $request->duplicate($query, null, $path);
        return $this->container->get('http_kernel')->handle($subRequest, HttpKernelInterface::SUB_REQUEST);
    }
    /**
     * Returns a RedirectResponse to the given URL.
     *
     * @param int $status The HTTP status code (302 "Found" by default)
     */
    protected function redirect(string $url, int $status = 302): RedirectResponse
    {
        return new RedirectResponse($url, $status);
    }
    /**
     * Returns a RedirectResponse to the given route with the given parameters.
     *
     * @param int $status The HTTP status code (302 "Found" by default)
     */
    protected function redirectToRoute(string $route, array $parameters = [], int $status = 302): RedirectResponse
    {
        return $this->redirect($this->generateUrl($route, $parameters), $status);
    }
    /**
     * Returns a JsonResponse that uses the serializer component if enabled, or json_encode.
     *
     * @param int $status The HTTP status code (200 "OK" by default)
     */
    protected function json(mixed $data, int $status = 200, array $headers = [], array $context = []): JsonResponse
    {
        if ($this->container->has('serializer')) {
            $json = $this->container->get('serializer')->serialize($data, 'json', array_merge(['json_encode_options' => JsonResponse::DEFAULT_ENCODING_OPTIONS], $context));
            return new JsonResponse($json, $status, $headers, \true);
        }
        if (null === $data) {
            return new JsonResponse('null', $status, $headers, \true);
        }
        return new JsonResponse($data, $status, $headers);
    }
    /**
     * Returns a BinaryFileResponse object with original or customized file name and disposition header.
     */
    protected function file(\SplFileInfo|string $file, ?string $fileName = null, string $disposition = ResponseHeaderBag::DISPOSITION_ATTACHMENT): BinaryFileResponse
    {
        $response = new BinaryFileResponse($file);
        $response->setContentDisposition($disposition, $fileName ?? $response->getFile()->getFilename());
        return $response;
    }
    /**
     * Adds a flash message to the current session for type.
     *
     * @throws \LogicException
     */
    protected function addFlash(string $type, mixed $message): void
    {
        try {
            $session = $this->container->get('request_stack')->getSession();
        } catch (SessionNotFoundException $e) {
            throw new \LogicException('You cannot use the addFlash method if sessions are disabled. Enable them in "config/packages/framework.yaml".', 0, $e);
        }
        if (!$session instanceof FlashBagAwareSessionInterface) {
            trigger_deprecation('symfony/framework-bundle', '6.2', 'Calling "addFlash()" method when the session does not implement %s is deprecated.', FlashBagAwareSessionInterface::class);
        }
        $session->getFlashBag()->add($type, $message);
    }
    /**
     * Checks if the attribute is granted against the current authentication token and optionally supplied subject.
     *
     * @throws \LogicException
     */
    protected function isGranted(mixed $attribute, mixed $subject = null): bool
    {
        if (!$this->container->has('security.authorization_checker')) {
            throw new \LogicException('The SecurityBundle is not registered in your application. Try running "composer require symfony/security-bundle".');
        }
        return $this->container->get('security.authorization_checker')->isGranted($attribute, $subject);
    }
    /**
     * Throws an exception unless the attribute is granted against the current authentication token and optionally
     * supplied subject.
     *
     * @throws AccessDeniedException
     */
    protected function denyAccessUnlessGranted(mixed $attribute, mixed $subject = null, string $message = 'Access Denied.'): void
    {
        if (!$this->isGranted($attribute, $subject)) {
            $exception = $this->createAccessDeniedException($message);
            $exception->setAttributes([$attribute]);
            $exception->setSubject($subject);
            throw $exception;
        }
    }
    /**
     * Returns a rendered view.
     *
     * Forms found in parameters are auto-cast to form views.
     */
    protected function renderView(string $view, array $parameters = []): string
    {
        return $this->doRenderView($view, null, $parameters, __FUNCTION__);
    }
    /**
     * Returns a rendered block from a view.
     *
     * Forms found in parameters are auto-cast to form views.
     */
    protected function renderBlockView(string $view, string $block, array $parameters = []): string
    {
        return $this->doRenderView($view, $block, $parameters, __FUNCTION__);
    }
    /**
     * Renders a view.
     *
     * If an invalid form is found in the list of parameters, a 422 status code is returned.
     * Forms found in parameters are auto-cast to form views.
     */
    protected function render(string $view, array $parameters = [], ?Response $response = null): Response
    {
        return $this->doRender($view, null, $parameters, $response, __FUNCTION__);
    }
    /**
     * Renders a block in a view.
     *
     * If an invalid form is found in the list of parameters, a 422 status code is returned.
     * Forms found in parameters are auto-cast to form views.
     */
    protected function renderBlock(string $view, string $block, array $parameters = [], ?Response $response = null): Response
    {
        return $this->doRender($view, $block, $parameters, $response, __FUNCTION__);
    }
    /**
     * Renders a view and sets the appropriate status code when a form is listed in parameters.
     *
     * If an invalid form is found in the list of parameters, a 422 status code is returned.
     *
     * @deprecated since Symfony 6.2, use render() instead
     */
    protected function renderForm(string $view, array $parameters = [], ?Response $response = null): Response
    {
        trigger_deprecation('symfony/framework-bundle', '6.2', 'The "%s::renderForm()" method is deprecated, use "render()" instead.', get_debug_type($this));
        return $this->render($view, $parameters, $response);
    }
    /**
     * Streams a view.
     */
    protected function stream(string $view, array $parameters = [], ?StreamedResponse $response = null): StreamedResponse
    {
        if (!$this->container->has('twig')) {
            throw new \LogicException('You cannot use the "stream" method if the Twig Bundle is not available. Try running "composer require symfony/twig-bundle".');
        }
        $twig = $this->container->get('twig');
        $callback = function () use ($twig, $view, $parameters) {
            $twig->display($view, $parameters);
        };
        if (null === $response) {
            return new StreamedResponse($callback);
        }
        $response->setCallback($callback);
        return $response;
    }
    /**
     * Returns a NotFoundHttpException.
     *
     * This will result in a 404 response code. Usage example:
     *
     *     throw $this->createNotFoundException('Page not found!');
     */
    protected function createNotFoundException(string $message = 'Not Found', ?\Throwable $previous = null): NotFoundHttpException
    {
        return new NotFoundHttpException($message, $previous);
    }
    /**
     * Returns an AccessDeniedException.
     *
     * This will result in a 403 response code. Usage example:
     *
     *     throw $this->createAccessDeniedException('Unable to access this page!');
     *
     * @throws \LogicException If the Security component is not available
     */
    protected function createAccessDeniedException(string $message = 'Access Denied.', ?\Throwable $previous = null): AccessDeniedException
    {
        if (!class_exists(AccessDeniedException::class)) {
            throw new \LogicException('You cannot use the "createAccessDeniedException" method if the Security component is not available. Try running "composer require symfony/security-bundle".');
        }
        return new AccessDeniedException($message, $previous);
    }
    /**
     * Creates and returns a Form instance from the type of the form.
     */
    protected function createForm(string $type, mixed $data = null, array $options = []): FormInterface
    {
        return $this->container->get('form.factory')->create($type, $data, $options);
    }
    /**
     * Creates and returns a form builder instance.
     */
    protected function createFormBuilder(mixed $data = null, array $options = []): FormBuilderInterface
    {
        return $this->container->get('form.factory')->createBuilder(FormType::class, $data, $options);
    }
    /**
     * Get a user from the Security Token Storage.
     *
     * @throws \LogicException If SecurityBundle is not available
     *
     * @see TokenInterface::getUser()
     */
    protected function getUser(): ?UserInterface
    {
        if (!$this->container->has('security.token_storage')) {
            throw new \LogicException('The SecurityBundle is not registered in your application. Try running "composer require symfony/security-bundle".');
        }
        if (null === $token = $this->container->get('security.token_storage')->getToken()) {
            return null;
        }
        return $token->getUser();
    }
    /**
     * Checks the validity of a CSRF token.
     *
     * @param string      $id    The id used when generating the token
     * @param string|null $token The actual token sent with the request that should be validated
     */
    protected function isCsrfTokenValid(
        string $id,
        #[\SensitiveParameter]
        ?string $token
    ): bool
    {
        if (!$this->container->has('security.csrf.token_manager')) {
            throw new \LogicException('CSRF protection is not enabled in your application. Enable it with the "csrf_protection" key in "config/packages/framework.yaml".');
        }
        return $this->container->get('security.csrf.token_manager')->isTokenValid(new CsrfToken($id, $token));
    }
    /**
     * Adds a Link HTTP header to the current response.
     *
     * @see https://tools.ietf.org/html/rfc5988
     */
    protected function addLink(Request $request, LinkInterface $link): void
    {
        if (!class_exists(AddLinkHeaderListener::class)) {
            throw new \LogicException('You cannot use the "addLink" method if the WebLink component is not available. Try running "composer require symfony/web-link".');
        }
        if (null === $linkProvider = $request->attributes->get('_links')) {
            $request->attributes->set('_links', new GenericLinkProvider([$link]));
            return;
        }
        $request->attributes->set('_links', $linkProvider->withLink($link));
    }
    /**
     * @param LinkInterface[] $links
     */
    protected function sendEarlyHints(iterable $links = [], ?Response $response = null): Response
    {
        if (!$this->container->has('web_link.http_header_serializer')) {
            throw new \LogicException('You cannot use the "sendEarlyHints" method if the WebLink component is not available. Try running "composer require symfony/web-link".');
        }
        $response ??= new Response();
        $populatedLinks = [];
        foreach ($links as $link) {
            if ($link instanceof EvolvableLinkInterface && !$link->getRels()) {
                $link = $link->withRel('preload');
            }
            $populatedLinks[] = $link;
        }
        $response->headers->set('Link', $this->container->get('web_link.http_header_serializer')->serialize($populatedLinks), \false);
        $response->sendHeaders(103);
        return $response;
    }
    private function doRenderView(string $view, ?string $block, array $parameters, string $method): string
    {
        if (!$this->container->has('twig')) {
            throw new \LogicException(\sprintf('You cannot use the "%s" method if the Twig Bundle is not available. Try running "composer require symfony/twig-bundle".', $method));
        }
        foreach ($parameters as $k => $v) {
            if ($v instanceof FormInterface) {
                $parameters[$k] = $v->createView();
            }
        }
        if (null !== $block) {
            return $this->container->get('twig')->load($view)->renderBlock($block, $parameters);
        }
        return $this->container->get('twig')->render($view, $parameters);
    }
    private function doRender(string $view, ?string $block, array $parameters, ?Response $response, string $method): Response
    {
        $content = $this->doRenderView($view, $block, $parameters, $method);
        $response ??= new Response();
        if (200 === $response->getStatusCode()) {
            foreach ($parameters as $v) {
                if ($v instanceof FormInterface && $v->isSubmitted() && !$v->isValid()) {
                    $response->setStatusCode(422);
                    break;
                }
            }
        }
        $response->setContent($content);
        return $response;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Bundle\FrameworkBundle\Controller;

use _ContaoManager\Symfony\Component\HttpFoundation\Response;
use _ContaoManager\Twig\Environment;
/**
 * TemplateController.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 *
 * @final
 */
class TemplateController
{
    private ?Environment $twig;
    public function __construct(?Environment $twig = null)
    {
        $this->twig = $twig;
    }
    /**
     * Renders a template.
     *
     * @param string    $template   The template name
     * @param int|null  $maxAge     Max age for client caching
     * @param int|null  $sharedAge  Max age for shared (proxy) caching
     * @param bool|null $private    Whether or not caching should apply for client caches only
     * @param array     $context    The context (arguments) of the template
     * @param int       $statusCode The HTTP status code to return with the response (200 "OK" by default)
     */
    public function templateAction(string $template, ?int $maxAge = null, ?int $sharedAge = null, ?bool $private = null, array $context = [], int $statusCode = 200): Response
    {
        if (null === $this->twig) {
            throw new \LogicException('You cannot use the TemplateController if the Twig Bundle is not available. Try running "composer require symfony/twig-bundle".');
        }
        $response = new Response($this->twig->render($template, $context), $statusCode);
        if ($maxAge) {
            $response->setMaxAge($maxAge);
        }
        if (null !== $sharedAge) {
            $response->setSharedMaxAge($sharedAge);
        }
        if ($private) {
            $response->setPrivate();
        } elseif (\false === $private || null === $private && (null !== $maxAge || null !== $sharedAge)) {
            $response->setPublic();
        }
        return $response;
    }
    /**
     * @param int $statusCode The HTTP status code (200 "OK" by default)
     */
    public function __invoke(string $template, ?int $maxAge = null, ?int $sharedAge = null, ?bool $private = null, array $context = [], int $statusCode = 200): Response
    {
        return $this->templateAction($template, $maxAge, $sharedAge, $private, $context, $statusCode);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Bundle\FrameworkBundle\Controller;

use _ContaoManager\Symfony\Component\DependencyInjection\ContainerAwareInterface;
use _ContaoManager\Symfony\Component\HttpKernel\Controller\ContainerControllerResolver;
/**
 * @author Fabien Potencier <fabien@symfony.com>
 *
 * @final
 */
class ControllerResolver extends ContainerControllerResolver
{
    protected function instantiateController(string $class): object
    {
        $controller = parent::instantiateController($class);
        if ($controller instanceof ContainerAwareInterface) {
            trigger_deprecation('symfony/dependency-injection', '6.4', 'Relying on "%s" to get the container in "%s" is deprecated, register the controller as a service and use dependency injection instead.', ContainerAwareInterface::class, get_debug_type($controller));
            $controller->setContainer($this->container);
        }
        if ($controller instanceof AbstractController) {
            if (null === $previousContainer = $controller->setContainer($this->container)) {
                throw new \LogicException(\sprintf('"%s" has no container set, did you forget to define it as a service subscriber?', $class));
            } else {
                $controller->setContainer($previousContainer);
            }
        }
        return $controller;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Bundle\FrameworkBundle\Controller;

use _ContaoManager\Symfony\Component\HttpFoundation\HeaderUtils;
use _ContaoManager\Symfony\Component\HttpFoundation\RedirectResponse;
use _ContaoManager\Symfony\Component\HttpFoundation\Request;
use _ContaoManager\Symfony\Component\HttpFoundation\Response;
use _ContaoManager\Symfony\Component\HttpKernel\Exception\HttpException;
use _ContaoManager\Symfony\Component\Routing\Generator\UrlGeneratorInterface;
/**
 * Redirects a request to another URL.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 *
 * @final
 */
class RedirectController
{
    private ?UrlGeneratorInterface $router;
    private ?int $httpPort;
    private ?int $httpsPort;
    public function __construct(?UrlGeneratorInterface $router = null, ?int $httpPort = null, ?int $httpsPort = null)
    {
        $this->router = $router;
        $this->httpPort = $httpPort;
        $this->httpsPort = $httpsPort;
    }
    /**
     * Redirects to another route with the given name.
     *
     * The response status code is 302 if the permanent parameter is false (default),
     * and 301 if the redirection is permanent.
     *
     * In case the route name is empty, the status code will be 404 when permanent is false
     * and 410 otherwise.
     *
     * @param string     $route             The route name to redirect to
     * @param bool       $permanent         Whether the redirection is permanent
     * @param bool|array $ignoreAttributes  Whether to ignore attributes or an array of attributes to ignore
     * @param bool       $keepRequestMethod Whether redirect action should keep HTTP request method
     *
     * @throws HttpException In case the route name is empty
     */
    public function redirectAction(Request $request, string $route, bool $permanent = \false, bool|array $ignoreAttributes = \false, bool $keepRequestMethod = \false, bool $keepQueryParams = \false): Response
    {
        if ('' == $route) {
            throw new HttpException($permanent ? 410 : 404);
        }
        $attributes = [];
        if (\false === $ignoreAttributes || \is_array($ignoreAttributes)) {
            $attributes = $request->attributes->get('_route_params');
            if ($keepQueryParams) {
                if ($query = $request->server->get('QUERY_STRING')) {
                    $query = HeaderUtils::parseQuery($query);
                } else {
                    $query = $request->query->all();
                }
                $attributes = array_merge($query, $attributes);
            }
            unset($attributes['route'], $attributes['permanent'], $attributes['ignoreAttributes'], $attributes['keepRequestMethod'], $attributes['keepQueryParams']);
            if ($ignoreAttributes) {
                $attributes = array_diff_key($attributes, array_flip($ignoreAttributes));
            }
        }
        if ($keepRequestMethod) {
            $statusCode = $permanent ? 308 : 307;
        } else {
            $statusCode = $permanent ? 301 : 302;
        }
        return new RedirectResponse($this->router->generate($route, $attributes, UrlGeneratorInterface::ABSOLUTE_URL), $statusCode);
    }
    /**
     * Redirects to a URL.
     *
     * The response status code is 302 if the permanent parameter is false (default),
     * and 301 if the redirection is permanent.
     *
     * In case the path is empty, the status code will be 404 when permanent is false
     * and 410 otherwise.
     *
     * @param string      $path              The absolute path or URL to redirect to
     * @param bool        $permanent         Whether the redirect is permanent or not
     * @param string|null $scheme            The URL scheme (null to keep the current one)
     * @param int|null    $httpPort          The HTTP port (null to keep the current one for the same scheme or the default configured port)
     * @param int|null    $httpsPort         The HTTPS port (null to keep the current one for the same scheme or the default configured port)
     * @param bool        $keepRequestMethod Whether redirect action should keep HTTP request method
     *
     * @throws HttpException In case the path is empty
     */
    public function urlRedirectAction(Request $request, string $path, bool $permanent = \false, ?string $scheme = null, ?int $httpPort = null, ?int $httpsPort = null, bool $keepRequestMethod = \false): Response
    {
        if ('' === $path) {
            throw new HttpException($permanent ? 410 : 404);
        }
        if ($keepRequestMethod) {
            $statusCode = $permanent ? 308 : 307;
        } else {
            $statusCode = $permanent ? 301 : 302;
        }
        $scheme ??= $request->getScheme();
        if (str_starts_with($path, '//')) {
            $path = $scheme . ':' . $path;
        }
        // redirect if the path is a full URL
        if (parse_url($path, \PHP_URL_SCHEME)) {
            return new RedirectResponse($path, $statusCode);
        }
        if ($qs = $request->server->get('QUERY_STRING') ?: $request->getQueryString()) {
            if (!str_contains($path, '?')) {
                $qs = '?' . $qs;
            } else {
                $qs = '&' . $qs;
            }
        }
        $port = '';
        if ('http' === $scheme) {
            if (null === $httpPort) {
                if ('http' === $request->getScheme()) {
                    $httpPort = $request->getPort();
                } else {
                    $httpPort = $this->httpPort;
                }
            }
            if (null !== $httpPort && 80 != $httpPort) {
                $port = ":{$httpPort}";
            }
        } elseif ('https' === $scheme) {
            if (null === $httpsPort) {
                if ('https' === $request->getScheme()) {
                    $httpsPort = $request->getPort();
                } else {
                    $httpsPort = $this->httpsPort;
                }
            }
            if (null !== $httpsPort && 443 != $httpsPort) {
                $port = ":{$httpsPort}";
            }
        }
        $url = $scheme . '://' . $request->getHost() . $port . $request->getBaseUrl() . $path . $qs;
        return new RedirectResponse($url, $statusCode);
    }
    public function __invoke(Request $request): Response
    {
        $p = $request->attributes->get('_route_params', []);
        if (\array_key_exists('route', $p)) {
            if (\array_key_exists('path', $p)) {
                throw new \RuntimeException(\sprintf('Ambiguous redirection settings, use the "path" or "route" parameter, not both: "%s" and "%s" found respectively in "%s" routing configuration.', $p['path'], $p['route'], $request->attributes->get('_route')));
            }
            return $this->redirectAction($request, $p['route'], $p['permanent'] ?? \false, $p['ignoreAttributes'] ?? \false, $p['keepRequestMethod'] ?? \false, $p['keepQueryParams'] ?? \false);
        }
        if (\array_key_exists('path', $p)) {
            return $this->urlRedirectAction($request, $p['path'], $p['permanent'] ?? \false, $p['scheme'] ?? null, $p['httpPort'] ?? null, $p['httpsPort'] ?? null, $p['keepRequestMethod'] ?? \false);
        }
        throw new \RuntimeException(\sprintf('The parameter "path" or "route" is required to configure the redirect action in "%s" routing configuration.', $request->attributes->get('_route')));
    }
}
FrameworkBundle
===============

FrameworkBundle provides a tight integration between Symfony components and the
Symfony full-stack framework.

Sponsor
-------

Help Symfony by [sponsoring][1] its development!

Resources
---------

 * [Contributing](https://symfony.com/doc/current/contributing/index.html)
 * [Report issues](https://github.com/symfony/symfony/issues) and
   [send Pull Requests](https://github.com/symfony/symfony/pulls)
   in the [main Symfony repository](https://github.com/symfony/symfony)

[1]: https://symfony.com/sponsor
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Bundle\FrameworkBundle\HttpCache;

use _ContaoManager\Symfony\Component\HttpFoundation\Request;
use _ContaoManager\Symfony\Component\HttpFoundation\Response;
use _ContaoManager\Symfony\Component\HttpKernel\HttpCache\Esi;
use _ContaoManager\Symfony\Component\HttpKernel\HttpCache\HttpCache as BaseHttpCache;
use _ContaoManager\Symfony\Component\HttpKernel\HttpCache\Store;
use _ContaoManager\Symfony\Component\HttpKernel\HttpCache\StoreInterface;
use _ContaoManager\Symfony\Component\HttpKernel\HttpCache\SurrogateInterface;
use _ContaoManager\Symfony\Component\HttpKernel\KernelInterface;
/**
 * Manages HTTP cache objects in a Container.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class HttpCache extends BaseHttpCache
{
    protected $cacheDir;
    protected $kernel;
    private ?StoreInterface $store = null;
    private ?SurrogateInterface $surrogate;
    private array $options;
    /**
     * @param $cache The cache directory (default used if null) or the storage instance
     */
    public function __construct(KernelInterface $kernel, string|StoreInterface|null $cache = null, ?SurrogateInterface $surrogate = null, ?array $options = null)
    {
        $this->kernel = $kernel;
        $this->surrogate = $surrogate;
        $this->options = $options ?? [];
        if ($cache instanceof StoreInterface) {
            $this->store = $cache;
        } else {
            $this->cacheDir = $cache;
        }
        if (null === $options && $kernel->isDebug()) {
            $this->options = ['debug' => \true];
        }
        if ($this->options['debug'] ?? \false) {
            $this->options += ['stale_if_error' => 0];
        }
        parent::__construct($kernel, $this->createStore(), $this->createSurrogate(), array_merge($this->options, $this->getOptions()));
    }
    protected function forward(Request $request, bool $catch = \false, ?Response $entry = null): Response
    {
        $this->getKernel()->boot();
        $this->getKernel()->getContainer()->set('cache', $this);
        return parent::forward($request, $catch, $entry);
    }
    /**
     * Returns an array of options to customize the Cache configuration.
     */
    protected function getOptions(): array
    {
        return [];
    }
    protected function createSurrogate(): SurrogateInterface
    {
        return $this->surrogate ?? new Esi();
    }
    protected function createStore(): StoreInterface
    {
        return $this->store ?? new Store($this->cacheDir ?: $this->kernel->getCacheDir() . '/http_cache');
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Bundle\FrameworkBundle;

use _ContaoManager\Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\AddAnnotationsCachedReaderPass;
use _ContaoManager\Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\AddDebugLogProcessorPass;
use _ContaoManager\Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\AssetsContextPass;
use _ContaoManager\Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\ContainerBuilderDebugDumpPass;
use _ContaoManager\Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\ErrorLoggerCompilerPass;
use _ContaoManager\Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\ProfilerPass;
use _ContaoManager\Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\RemoveUnusedSessionMarshallingHandlerPass;
use _ContaoManager\Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\TestServiceContainerRealRefPass;
use _ContaoManager\Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\TestServiceContainerWeakRefPass;
use _ContaoManager\Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\TranslationUpdateCommandPass;
use _ContaoManager\Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\UnusedTagsPass;
use _ContaoManager\Symfony\Bundle\FrameworkBundle\DependencyInjection\VirtualRequestStackPass;
use _ContaoManager\Symfony\Component\Cache\Adapter\ApcuAdapter;
use _ContaoManager\Symfony\Component\Cache\Adapter\ArrayAdapter;
use _ContaoManager\Symfony\Component\Cache\Adapter\ChainAdapter;
use _ContaoManager\Symfony\Component\Cache\Adapter\PhpArrayAdapter;
use _ContaoManager\Symfony\Component\Cache\Adapter\PhpFilesAdapter;
use _ContaoManager\Symfony\Component\Cache\DependencyInjection\CacheCollectorPass;
use _ContaoManager\Symfony\Component\Cache\DependencyInjection\CachePoolClearerPass;
use _ContaoManager\Symfony\Component\Cache\DependencyInjection\CachePoolPass;
use _ContaoManager\Symfony\Component\Cache\DependencyInjection\CachePoolPrunerPass;
use _ContaoManager\Symfony\Component\Config\Resource\ClassExistenceResource;
use _ContaoManager\Symfony\Component\Console\ConsoleEvents;
use _ContaoManager\Symfony\Component\Console\DependencyInjection\AddConsoleCommandPass;
use _ContaoManager\Symfony\Component\DependencyInjection\Compiler\PassConfig;
use _ContaoManager\Symfony\Component\DependencyInjection\Compiler\RegisterReverseContainerPass;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerBuilder;
use _ContaoManager\Symfony\Component\Dotenv\Dotenv;
use _ContaoManager\Symfony\Component\ErrorHandler\ErrorHandler;
use _ContaoManager\Symfony\Component\EventDispatcher\DependencyInjection\RegisterListenersPass;
use _ContaoManager\Symfony\Component\Form\DependencyInjection\FormPass;
use _ContaoManager\Symfony\Component\HttpClient\DependencyInjection\HttpClientPass;
use _ContaoManager\Symfony\Component\HttpFoundation\BinaryFileResponse;
use _ContaoManager\Symfony\Component\HttpFoundation\Request;
use _ContaoManager\Symfony\Component\HttpKernel\Bundle\Bundle;
use _ContaoManager\Symfony\Component\HttpKernel\DependencyInjection\ControllerArgumentValueResolverPass;
use _ContaoManager\Symfony\Component\HttpKernel\DependencyInjection\FragmentRendererPass;
use _ContaoManager\Symfony\Component\HttpKernel\DependencyInjection\LoggerPass;
use _ContaoManager\Symfony\Component\HttpKernel\DependencyInjection\RegisterControllerArgumentLocatorsPass;
use _ContaoManager\Symfony\Component\HttpKernel\DependencyInjection\RegisterLocaleAwareServicesPass;
use _ContaoManager\Symfony\Component\HttpKernel\DependencyInjection\RemoveEmptyControllerArgumentLocatorsPass;
use _ContaoManager\Symfony\Component\HttpKernel\DependencyInjection\ResettableServicePass;
use _ContaoManager\Symfony\Component\HttpKernel\KernelEvents;
use _ContaoManager\Symfony\Component\Messenger\DependencyInjection\MessengerPass;
use _ContaoManager\Symfony\Component\Mime\DependencyInjection\AddMimeTypeGuesserPass;
use _ContaoManager\Symfony\Component\PropertyInfo\DependencyInjection\PropertyInfoPass;
use _ContaoManager\Symfony\Component\Routing\DependencyInjection\AddExpressionLanguageProvidersPass;
use _ContaoManager\Symfony\Component\Routing\DependencyInjection\RoutingResolverPass;
use _ContaoManager\Symfony\Component\Runtime\SymfonyRuntime;
use _ContaoManager\Symfony\Component\Scheduler\DependencyInjection\AddScheduleMessengerPass;
use _ContaoManager\Symfony\Component\Serializer\DependencyInjection\SerializerPass;
use _ContaoManager\Symfony\Component\Translation\DependencyInjection\DataCollectorTranslatorPass;
use _ContaoManager\Symfony\Component\Translation\DependencyInjection\LoggingTranslatorPass;
use _ContaoManager\Symfony\Component\Translation\DependencyInjection\TranslationDumperPass;
use _ContaoManager\Symfony\Component\Translation\DependencyInjection\TranslationExtractorPass;
use _ContaoManager\Symfony\Component\Translation\DependencyInjection\TranslatorPass;
use _ContaoManager\Symfony\Component\Translation\DependencyInjection\TranslatorPathsPass;
use _ContaoManager\Symfony\Component\Validator\DependencyInjection\AddAutoMappingConfigurationPass;
use _ContaoManager\Symfony\Component\Validator\DependencyInjection\AddConstraintValidatorsPass;
use _ContaoManager\Symfony\Component\Validator\DependencyInjection\AddValidatorInitializersPass;
use _ContaoManager\Symfony\Component\VarExporter\Internal\Hydrator;
use _ContaoManager\Symfony\Component\VarExporter\Internal\Registry;
use _ContaoManager\Symfony\Component\Workflow\DependencyInjection\WorkflowDebugPass;
use _ContaoManager\Symfony\Component\Workflow\DependencyInjection\WorkflowGuardListenerPass;
// Help opcache.preload discover always-needed symbols
class_exists(ApcuAdapter::class);
class_exists(ArrayAdapter::class);
class_exists(ChainAdapter::class);
class_exists(PhpArrayAdapter::class);
class_exists(PhpFilesAdapter::class);
class_exists(Dotenv::class);
class_exists(ErrorHandler::class);
class_exists(Hydrator::class);
class_exists(Registry::class);
/**
 * Bundle.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class FrameworkBundle extends Bundle
{
    /**
     * @return void
     */
    public function boot()
    {
        $_ENV['DOCTRINE_DEPRECATIONS'] = $_SERVER['DOCTRINE_DEPRECATIONS'] ??= 'trigger';
        if (class_exists(SymfonyRuntime::class)) {
            $handler = set_error_handler('var_dump');
            restore_error_handler();
        } else {
            $handler = [ErrorHandler::register(null, \false)];
        }
        if (!$this->container->has('debug.error_handler_configurator')) {
            // When upgrading an existing Symfony application from 6.2 to 6.3, and
            // the cache is warmed up, the service is not available yet, so we need
            // to check if it exists.
        } elseif (\is_array($handler) && $handler[0] instanceof ErrorHandler) {
            $this->container->get('debug.error_handler_configurator')->configure($handler[0]);
        }
        if ($this->container->getParameter('kernel.http_method_override')) {
            Request::enableHttpMethodParameterOverride();
        }
        if ($this->container->hasParameter('kernel.trust_x_sendfile_type_header') && $this->container->getParameter('kernel.trust_x_sendfile_type_header')) {
            BinaryFileResponse::trustXSendfileTypeHeader();
        }
    }
    /**
     * @return void
     */
    public function build(ContainerBuilder $container)
    {
        parent::build($container);
        $registerListenersPass = new RegisterListenersPass();
        $registerListenersPass->setHotPathEvents([KernelEvents::REQUEST, KernelEvents::CONTROLLER, KernelEvents::CONTROLLER_ARGUMENTS, KernelEvents::RESPONSE, KernelEvents::FINISH_REQUEST]);
        if (class_exists(ConsoleEvents::class)) {
            $registerListenersPass->setNoPreloadEvents([ConsoleEvents::COMMAND, ConsoleEvents::TERMINATE, ConsoleEvents::ERROR]);
        }
        $container->addCompilerPass(new AssetsContextPass(), PassConfig::TYPE_BEFORE_OPTIMIZATION);
        $container->addCompilerPass(new LoggerPass(), PassConfig::TYPE_BEFORE_OPTIMIZATION, -32);
        $container->addCompilerPass(new RegisterControllerArgumentLocatorsPass());
        $container->addCompilerPass(new RemoveEmptyControllerArgumentLocatorsPass(), PassConfig::TYPE_BEFORE_REMOVING);
        $container->addCompilerPass(new RoutingResolverPass());
        $this->addCompilerPassIfExists($container, DataCollectorTranslatorPass::class);
        $container->addCompilerPass(new ProfilerPass());
        // must be registered before removing private services as some might be listeners/subscribers
        // but as late as possible to get resolved parameters
        $container->addCompilerPass($registerListenersPass, PassConfig::TYPE_BEFORE_REMOVING);
        $this->addCompilerPassIfExists($container, AddConstraintValidatorsPass::class);
        $container->addCompilerPass(new AddAnnotationsCachedReaderPass(), PassConfig::TYPE_AFTER_REMOVING, -255);
        $this->addCompilerPassIfExists($container, AddValidatorInitializersPass::class);
        $this->addCompilerPassIfExists($container, AddConsoleCommandPass::class, PassConfig::TYPE_BEFORE_REMOVING);
        // must be registered as late as possible to get access to all Twig paths registered in
        // twig.template_iterator definition
        $this->addCompilerPassIfExists($container, TranslatorPass::class, PassConfig::TYPE_BEFORE_OPTIMIZATION, -32);
        $this->addCompilerPassIfExists($container, TranslatorPathsPass::class, PassConfig::TYPE_AFTER_REMOVING);
        $this->addCompilerPassIfExists($container, LoggingTranslatorPass::class);
        $container->addCompilerPass(new AddExpressionLanguageProvidersPass());
        $this->addCompilerPassIfExists($container, TranslationExtractorPass::class);
        $this->addCompilerPassIfExists($container, TranslationDumperPass::class);
        $container->addCompilerPass(new FragmentRendererPass());
        $this->addCompilerPassIfExists($container, SerializerPass::class);
        $this->addCompilerPassIfExists($container, PropertyInfoPass::class);
        $container->addCompilerPass(new ControllerArgumentValueResolverPass());
        $container->addCompilerPass(new CachePoolPass(), PassConfig::TYPE_BEFORE_OPTIMIZATION, 32);
        $container->addCompilerPass(new CachePoolClearerPass(), PassConfig::TYPE_AFTER_REMOVING);
        $container->addCompilerPass(new CachePoolPrunerPass(), PassConfig::TYPE_AFTER_REMOVING);
        $this->addCompilerPassIfExists($container, FormPass::class);
        $this->addCompilerPassIfExists($container, WorkflowGuardListenerPass::class);
        $container->addCompilerPass(new ResettableServicePass(), PassConfig::TYPE_BEFORE_OPTIMIZATION, -32);
        $container->addCompilerPass(new RegisterLocaleAwareServicesPass());
        $container->addCompilerPass(new TestServiceContainerWeakRefPass(), PassConfig::TYPE_BEFORE_REMOVING, -32);
        $container->addCompilerPass(new TestServiceContainerRealRefPass(), PassConfig::TYPE_AFTER_REMOVING);
        $this->addCompilerPassIfExists($container, AddMimeTypeGuesserPass::class);
        $this->addCompilerPassIfExists($container, AddScheduleMessengerPass::class);
        $this->addCompilerPassIfExists($container, MessengerPass::class);
        $this->addCompilerPassIfExists($container, HttpClientPass::class);
        $this->addCompilerPassIfExists($container, AddAutoMappingConfigurationPass::class);
        $container->addCompilerPass(new RegisterReverseContainerPass(\true));
        $container->addCompilerPass(new RegisterReverseContainerPass(\false), PassConfig::TYPE_AFTER_REMOVING);
        $container->addCompilerPass(new RemoveUnusedSessionMarshallingHandlerPass());
        // must be registered after MonologBundle's LoggerChannelPass
        $container->addCompilerPass(new ErrorLoggerCompilerPass(), PassConfig::TYPE_BEFORE_OPTIMIZATION, -32);
        $container->addCompilerPass(new VirtualRequestStackPass());
        $container->addCompilerPass(new TranslationUpdateCommandPass(), PassConfig::TYPE_BEFORE_REMOVING);
        if ($container->getParameter('kernel.debug')) {
            $container->addCompilerPass(new AddDebugLogProcessorPass(), PassConfig::TYPE_BEFORE_OPTIMIZATION, 2);
            $container->addCompilerPass(new UnusedTagsPass(), PassConfig::TYPE_AFTER_REMOVING);
            $container->addCompilerPass(new ContainerBuilderDebugDumpPass(), PassConfig::TYPE_BEFORE_REMOVING, -255);
            $container->addCompilerPass(new CacheCollectorPass(), PassConfig::TYPE_BEFORE_REMOVING);
            $this->addCompilerPassIfExists($container, WorkflowDebugPass::class);
        }
    }
    private function addCompilerPassIfExists(ContainerBuilder $container, string $class, string $type = PassConfig::TYPE_BEFORE_OPTIMIZATION, int $priority = 0): void
    {
        $container->addResource(new ClassExistenceResource($class));
        if (class_exists($class)) {
            $container->addCompilerPass(new $class(), $type, $priority);
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Bundle\FrameworkBundle\Command;

use _ContaoManager\Symfony\Bundle\FrameworkBundle\Secrets\AbstractVault;
use _ContaoManager\Symfony\Component\Console\Attribute\AsCommand;
use _ContaoManager\Symfony\Component\Console\Command\Command;
use _ContaoManager\Symfony\Component\Console\Helper\Dumper;
use _ContaoManager\Symfony\Component\Console\Input\InputInterface;
use _ContaoManager\Symfony\Component\Console\Input\InputOption;
use _ContaoManager\Symfony\Component\Console\Output\ConsoleOutputInterface;
use _ContaoManager\Symfony\Component\Console\Output\OutputInterface;
use _ContaoManager\Symfony\Component\Console\Style\SymfonyStyle;
/**
 * @author Tobias Schultze <http://tobion.de>
 * @author Jérémy Derussé <jeremy@derusse.com>
 * @author Nicolas Grekas <p@tchwork.com>
 *
 * @internal
 */
#[AsCommand(name: 'secrets:list', description: 'List all secrets')]
final class SecretsListCommand extends Command
{
    private AbstractVault $vault;
    private ?AbstractVault $localVault;
    public function __construct(AbstractVault $vault, ?AbstractVault $localVault = null)
    {
        $this->vault = $vault;
        $this->localVault = $localVault;
        parent::__construct();
    }
    protected function configure(): void
    {
        $this->addOption('reveal', 'r', InputOption::VALUE_NONE, 'Display decrypted values alongside names')->setHelp(<<<'EOF'
The <info>%command.name%</info> command list all stored secrets.

    <info>%command.full_name%</info>

When the option <info>--reveal</info> is provided, the decrypted secrets are also displayed.

    <info>%command.full_name% --reveal</info>
EOF
);
    }
    protected function execute(InputInterface $input, OutputInterface $output): int
    {
        $io = new SymfonyStyle($input, $output instanceof ConsoleOutputInterface ? $output->getErrorOutput() : $output);
        $io->comment('Use <info>"%env(<name>)%"</info> to reference a secret in a config file.');
        if (!$reveal = $input->getOption('reveal')) {
            $io->comment(\sprintf('To reveal the secrets run <info>php %s %s --reveal</info>', $_SERVER['PHP_SELF'], $this->getName()));
        }
        $secrets = $this->vault->list($reveal);
        $localSecrets = $this->localVault?->list($reveal);
        $rows = [];
        $dump = new Dumper($output);
        $dump = fn($v) => null === $v ? '******' : $dump($v);
        foreach ($secrets as $name => $value) {
            $rows[$name] = [$name, $dump($value)];
        }
        if (null !== $message = $this->vault->getLastMessage()) {
            $io->comment($message);
        }
        foreach ($localSecrets ?? [] as $name => $value) {
            if (isset($rows[$name])) {
                $rows[$name][] = $dump($value);
            }
        }
        if (null !== $this->localVault && null !== $message = $this->localVault->getLastMessage()) {
            $io->comment($message);
        }
        (new SymfonyStyle($input, $output))->table(['Secret', 'Value'] + (null !== $localSecrets ? [2 => 'Local Value'] : []), $rows);
        $io->comment("Local values override secret values.\nUse <info>secrets:set --local</info> to define them.");
        return 0;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Bundle\FrameworkBundle\Command;

use _ContaoManager\Symfony\Component\Console\Attribute\AsCommand;
use _ContaoManager\Symfony\Component\Console\Command\Command;
use _ContaoManager\Symfony\Component\Console\Completion\CompletionInput;
use _ContaoManager\Symfony\Component\Console\Completion\CompletionSuggestions;
use _ContaoManager\Symfony\Component\Console\Input\InputArgument;
use _ContaoManager\Symfony\Component\Console\Input\InputInterface;
use _ContaoManager\Symfony\Component\Console\Input\InputOption;
use _ContaoManager\Symfony\Component\Console\Output\OutputInterface;
use _ContaoManager\Symfony\Component\Console\Style\SymfonyStyle;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException;
use _ContaoManager\Symfony\Contracts\Cache\TagAwareCacheInterface;
use _ContaoManager\Symfony\Contracts\Service\ServiceProviderInterface;
/**
 * @author Kevin Bond <kevinbond@gmail.com>
 */
#[AsCommand(name: 'cache:pool:invalidate-tags', description: 'Invalidate cache tags for all or a specific pool')]
final class CachePoolInvalidateTagsCommand extends Command
{
    private ServiceProviderInterface $pools;
    private array $poolNames;
    public function __construct(ServiceProviderInterface $pools)
    {
        parent::__construct();
        $this->pools = $pools;
        $this->poolNames = array_keys($pools->getProvidedServices());
    }
    protected function configure(): void
    {
        $this->addArgument('tags', InputArgument::IS_ARRAY | InputArgument::REQUIRED, 'The tags to invalidate')->addOption('pool', 'p', InputOption::VALUE_REQUIRED | InputOption::VALUE_IS_ARRAY, 'The pools to invalidate on')->setHelp(<<<'EOF'
The <info>%command.name%</info> command invalidates tags from taggable pools. By default, all pools
have the passed tags invalidated. Pass <info>--pool=my_pool</info> to invalidate tags on a specific pool.

  php %command.full_name% tag1 tag2
  php %command.full_name% tag1 tag2 --pool=cache2 --pool=cache1
EOF
);
    }
    protected function execute(InputInterface $input, OutputInterface $output): int
    {
        $io = new SymfonyStyle($input, $output);
        $pools = $input->getOption('pool') ?: $this->poolNames;
        $tags = $input->getArgument('tags');
        $tagList = implode(', ', $tags);
        $errors = \false;
        foreach ($pools as $name) {
            $io->comment(\sprintf('Invalidating tag(s): <info>%s</info> from pool <comment>%s</comment>.', $tagList, $name));
            try {
                $pool = $this->pools->get($name);
            } catch (ServiceNotFoundException) {
                $io->error(\sprintf('Pool "%s" not found.', $name));
                $errors = \true;
                continue;
            }
            if (!$pool instanceof TagAwareCacheInterface) {
                $io->error(\sprintf('Pool "%s" is not taggable.', $name));
                $errors = \true;
                continue;
            }
            if (!$pool->invalidateTags($tags)) {
                $io->error(\sprintf('Cache tag(s) "%s" could not be invalidated for pool "%s".', $tagList, $name));
                $errors = \true;
            }
        }
        if ($errors) {
            $io->error('Done but with errors.');
            return 1;
        }
        $io->success('Successfully invalidated cache tags.');
        return 0;
    }
    public function complete(CompletionInput $input, CompletionSuggestions $suggestions): void
    {
        if ($input->mustSuggestOptionValuesFor('pool')) {
            $suggestions->suggestValues($this->poolNames);
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Bundle\FrameworkBundle\Command;

use _ContaoManager\Symfony\Bundle\FrameworkBundle\Secrets\AbstractVault;
use _ContaoManager\Symfony\Component\Console\Attribute\AsCommand;
use _ContaoManager\Symfony\Component\Console\Command\Command;
use _ContaoManager\Symfony\Component\Console\Completion\CompletionInput;
use _ContaoManager\Symfony\Component\Console\Completion\CompletionSuggestions;
use _ContaoManager\Symfony\Component\Console\Input\InputArgument;
use _ContaoManager\Symfony\Component\Console\Input\InputInterface;
use _ContaoManager\Symfony\Component\Console\Input\InputOption;
use _ContaoManager\Symfony\Component\Console\Output\ConsoleOutputInterface;
use _ContaoManager\Symfony\Component\Console\Output\OutputInterface;
use _ContaoManager\Symfony\Component\Console\Style\SymfonyStyle;
/**
 * @author Jérémy Derussé <jeremy@derusse.com>
 * @author Nicolas Grekas <p@tchwork.com>
 *
 * @internal
 */
#[AsCommand(name: 'secrets:remove', description: 'Remove a secret from the vault')]
final class SecretsRemoveCommand extends Command
{
    private AbstractVault $vault;
    private ?AbstractVault $localVault;
    public function __construct(AbstractVault $vault, ?AbstractVault $localVault = null)
    {
        $this->vault = $vault;
        $this->localVault = $localVault;
        parent::__construct();
    }
    protected function configure(): void
    {
        $this->addArgument('name', InputArgument::REQUIRED, 'The name of the secret')->addOption('local', 'l', InputOption::VALUE_NONE, 'Update the local vault.')->setHelp(<<<'EOF'
The <info>%command.name%</info> command removes a secret from the vault.

    <info>%command.full_name% <name></info>
EOF
);
    }
    protected function execute(InputInterface $input, OutputInterface $output): int
    {
        $io = new SymfonyStyle($input, $output instanceof ConsoleOutputInterface ? $output->getErrorOutput() : $output);
        $vault = $input->getOption('local') ? $this->localVault : $this->vault;
        if (null === $vault) {
            $io->error('The local vault is disabled.');
            return 1;
        }
        if ($vault->remove($name = $input->getArgument('name'))) {
            $io->success($vault->getLastMessage() ?? 'Secret was removed from the vault.');
        } else {
            $io->comment($vault->getLastMessage() ?? 'Secret was not found in the vault.');
        }
        if ($this->vault === $vault && null !== $this->localVault->reveal($name)) {
            $io->comment('Note that this secret is overridden in the local vault.');
        }
        return 0;
    }
    public function complete(CompletionInput $input, CompletionSuggestions $suggestions): void
    {
        if (!$input->mustSuggestArgumentValuesFor('name')) {
            return;
        }
        $vaultKeys = array_keys($this->vault->list(\false));
        if ($input->getOption('local')) {
            if (null === $this->localVault) {
                return;
            }
            $vaultKeys = array_intersect($vaultKeys, array_keys($this->localVault->list(\false)));
        }
        $suggestions->suggestValues($vaultKeys);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Bundle\FrameworkBundle\Command;

use _ContaoManager\Symfony\Component\Console\Attribute\AsCommand;
use _ContaoManager\Symfony\Component\Console\Command\Command;
use _ContaoManager\Symfony\Component\Console\Exception\RuntimeException;
use _ContaoManager\Symfony\Component\Console\Input\InputInterface;
use _ContaoManager\Symfony\Component\Console\Input\InputOption;
use _ContaoManager\Symfony\Component\Console\Output\OutputInterface;
use _ContaoManager\Symfony\Component\Console\Style\SymfonyStyle;
use _ContaoManager\Symfony\Component\DependencyInjection\Dumper\Preloader;
use _ContaoManager\Symfony\Component\EventDispatcher\EventDispatcher;
use _ContaoManager\Symfony\Component\Filesystem\Exception\IOException;
use _ContaoManager\Symfony\Component\Filesystem\Filesystem;
use _ContaoManager\Symfony\Component\Finder\Finder;
use _ContaoManager\Symfony\Component\HttpKernel\CacheClearer\CacheClearerInterface;
use _ContaoManager\Symfony\Component\HttpKernel\RebootableInterface;
/**
 * Clear and Warmup the cache.
 *
 * @author Francis Besset <francis.besset@gmail.com>
 * @author Fabien Potencier <fabien@symfony.com>
 *
 * @final
 */
#[AsCommand(name: 'cache:clear', description: 'Clear the cache')]
class CacheClearCommand extends Command
{
    private CacheClearerInterface $cacheClearer;
    private Filesystem $filesystem;
    public function __construct(CacheClearerInterface $cacheClearer, ?Filesystem $filesystem = null)
    {
        parent::__construct();
        $this->cacheClearer = $cacheClearer;
        $this->filesystem = $filesystem ?? new Filesystem();
    }
    protected function configure(): void
    {
        $this->setDefinition([new InputOption('no-warmup', '', InputOption::VALUE_NONE, 'Do not warm up the cache'), new InputOption('no-optional-warmers', '', InputOption::VALUE_NONE, 'Skip optional cache warmers (faster)')])->setHelp(<<<'EOF'
The <info>%command.name%</info> command clears and warms up the application cache for a given environment
and debug mode:

  <info>php %command.full_name% --env=dev</info>
  <info>php %command.full_name% --env=prod --no-debug</info>
EOF
);
    }
    protected function execute(InputInterface $input, OutputInterface $output): int
    {
        $fs = $this->filesystem;
        $io = new SymfonyStyle($input, $output);
        $kernel = $this->getApplication()->getKernel();
        $realCacheDir = $kernel->getContainer()->getParameter('kernel.cache_dir');
        $realBuildDir = $kernel->getContainer()->hasParameter('kernel.build_dir') ? $kernel->getContainer()->getParameter('kernel.build_dir') : $realCacheDir;
        // the old cache dir name must not be longer than the real one to avoid exceeding
        // the maximum length of a directory or file path within it (esp. Windows MAX_PATH)
        $oldCacheDir = substr($realCacheDir, 0, -1) . (str_ends_with($realCacheDir, '~') ? '+' : '~');
        $fs->remove($oldCacheDir);
        if (!is_writable($realCacheDir)) {
            throw new RuntimeException(\sprintf('Unable to write in the "%s" directory.', $realCacheDir));
        }
        $useBuildDir = $realBuildDir !== $realCacheDir;
        $oldBuildDir = substr($realBuildDir, 0, -1) . (str_ends_with($realBuildDir, '~') ? '+' : '~');
        if ($useBuildDir) {
            $fs->remove($oldBuildDir);
            if (!is_writable($realBuildDir)) {
                throw new RuntimeException(\sprintf('Unable to write in the "%s" directory.', $realBuildDir));
            }
            if ($this->isNfs($realCacheDir)) {
                $fs->remove($realCacheDir);
            } else {
                $fs->rename($realCacheDir, $oldCacheDir);
            }
            $fs->mkdir($realCacheDir);
        }
        $io->comment(\sprintf('Clearing the cache for the <info>%s</info> environment with debug <info>%s</info>', $kernel->getEnvironment(), var_export($kernel->isDebug(), \true)));
        if ($useBuildDir) {
            $this->cacheClearer->clear($realBuildDir);
        }
        $this->cacheClearer->clear($realCacheDir);
        // The current event dispatcher is stale, let's not use it anymore
        $this->getApplication()->setDispatcher(new EventDispatcher());
        $containerFile = (new \ReflectionObject($kernel->getContainer()))->getFileName();
        $containerDir = basename(\dirname($containerFile));
        // the warmup cache dir name must have the same length as the real one
        // to avoid the many problems in serialized resources files
        $warmupDir = substr($realBuildDir, 0, -1) . (str_ends_with($realBuildDir, '_') ? '-' : '_');
        if ($output->isVerbose() && $fs->exists($warmupDir)) {
            $io->comment('Clearing outdated warmup directory...');
        }
        $fs->remove($warmupDir);
        if ($_SERVER['REQUEST_TIME'] <= filemtime($containerFile) && filemtime($containerFile) <= time()) {
            if ($output->isVerbose()) {
                $io->comment('Cache is fresh.');
            }
            if (!$input->getOption('no-warmup') && !$input->getOption('no-optional-warmers')) {
                if ($output->isVerbose()) {
                    $io->comment('Warming up optional cache...');
                }
                $this->warmupOptionals($realCacheDir, $realBuildDir, $io);
            }
        } else {
            $fs->mkdir($warmupDir);
            if (!$input->getOption('no-warmup')) {
                if ($output->isVerbose()) {
                    $io->comment('Warming up cache...');
                }
                $this->warmup($warmupDir, $realBuildDir);
                if (!$input->getOption('no-optional-warmers')) {
                    if ($output->isVerbose()) {
                        $io->comment('Warming up optional cache...');
                    }
                    $this->warmupOptionals($useBuildDir ? $realCacheDir : $warmupDir, $warmupDir, $io);
                }
                // fix references to cached files with the real cache directory name
                $search = [$warmupDir, str_replace('/', '\/', $warmupDir), str_replace('\\', '\\\\', $warmupDir)];
                $replace = str_replace('\\', '/', $realBuildDir);
                foreach (Finder::create()->files()->in($warmupDir) as $file) {
                    $content = str_replace($search, $replace, file_get_contents($file), $count);
                    if ($count) {
                        file_put_contents($file, $content);
                    }
                }
            }
            if (!$fs->exists($warmupDir . '/' . $containerDir)) {
                $fs->rename($realBuildDir . '/' . $containerDir, $warmupDir . '/' . $containerDir);
                touch($warmupDir . '/' . $containerDir . '.legacy');
            }
            if ($this->isNfs($realBuildDir)) {
                $io->note('For better performance, you should move the cache and log directories to a non-shared folder of the VM.');
                $fs->remove($realBuildDir);
            } else {
                $fs->rename($realBuildDir, $oldBuildDir);
            }
            $fs->rename($warmupDir, $realBuildDir);
            if ($output->isVerbose()) {
                $io->comment('Removing old build and cache directory...');
            }
            if ($useBuildDir) {
                try {
                    $fs->remove($oldBuildDir);
                } catch (IOException $e) {
                    if ($output->isVerbose()) {
                        $io->warning($e->getMessage());
                    }
                }
            }
            try {
                $fs->remove($oldCacheDir);
            } catch (IOException $e) {
                if ($output->isVerbose()) {
                    $io->warning($e->getMessage());
                }
            }
        }
        if ($output->isVerbose()) {
            $io->comment('Finished');
        }
        $io->success(\sprintf('Cache for the "%s" environment (debug=%s) was successfully cleared.', $kernel->getEnvironment(), var_export($kernel->isDebug(), \true)));
        return 0;
    }
    private function isNfs(string $dir): bool
    {
        static $mounts = null;
        if (null === $mounts) {
            $mounts = [];
            if ('/' === \DIRECTORY_SEPARATOR && @is_readable('/proc/mounts') && $files = @file('/proc/mounts')) {
                foreach ($files as $mount) {
                    $mount = \array_slice(explode(' ', $mount), 1, -3);
                    if (!\in_array(array_pop($mount), ['vboxsf', 'nfs'])) {
                        continue;
                    }
                    $mounts[] = implode(' ', $mount) . '/';
                }
            }
        }
        foreach ($mounts as $mount) {
            if (str_starts_with($dir, $mount)) {
                return \true;
            }
        }
        return \false;
    }
    private function warmup(string $warmupDir, string $realBuildDir): void
    {
        // create a temporary kernel
        $kernel = $this->getApplication()->getKernel();
        if (!$kernel instanceof RebootableInterface) {
            throw new \LogicException('Calling "cache:clear" with a kernel that does not implement "Symfony\Component\HttpKernel\RebootableInterface" is not supported.');
        }
        $kernel->reboot($warmupDir);
    }
    private function warmupOptionals(string $cacheDir, string $warmupDir, SymfonyStyle $io): void
    {
        $kernel = $this->getApplication()->getKernel();
        $warmer = $kernel->getContainer()->get('cache_warmer');
        // non optional warmers already ran during container compilation
        $warmer->enableOnlyOptionalWarmers();
        $preload = (array) $warmer->warmUp($cacheDir, $warmupDir, $io);
        if ($preload && file_exists($preloadFile = $warmupDir . '/' . $kernel->getContainer()->getParameter('kernel.container_class') . '.preload.php')) {
            Preloader::append($preloadFile, $preload);
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Bundle\FrameworkBundle\Command;

use _ContaoManager\Symfony\Component\Console\Attribute\AsCommand;
use _ContaoManager\Symfony\Component\Translation\Command\XliffLintCommand as BaseLintCommand;
/**
 * Validates XLIFF files syntax and outputs encountered errors.
 *
 * @author Grégoire Pineau <lyrixx@lyrixx.info>
 * @author Robin Chalas <robin.chalas@gmail.com>
 * @author Javier Eguiluz <javier.eguiluz@gmail.com>
 *
 * @final
 */
#[AsCommand(name: 'lint:xliff', description: 'Lint an XLIFF file and outputs encountered errors')]
class XliffLintCommand extends BaseLintCommand
{
    public function __construct()
    {
        $directoryIteratorProvider = function ($directory, $default) {
            if (!is_dir($directory)) {
                $directory = $this->getApplication()->getKernel()->locateResource($directory);
            }
            return $default($directory);
        };
        $isReadableProvider = fn($fileOrDirectory, $default) => str_starts_with($fileOrDirectory, '@') || $default($fileOrDirectory);
        parent::__construct(null, $directoryIteratorProvider, $isReadableProvider);
    }
    protected function configure(): void
    {
        parent::configure();
        $this->setHelp($this->getHelp() . <<<'EOF'

Or find all files in a bundle:

  <info>php %command.full_name% @AcmeDemoBundle</info>

EOF
);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Bundle\FrameworkBundle\Command;

use _ContaoManager\Symfony\Bundle\FrameworkBundle\Secrets\AbstractVault;
use _ContaoManager\Symfony\Component\Console\Attribute\AsCommand;
use _ContaoManager\Symfony\Component\Console\Command\Command;
use _ContaoManager\Symfony\Component\Console\Input\InputInterface;
use _ContaoManager\Symfony\Component\Console\Input\InputOption;
use _ContaoManager\Symfony\Component\Console\Output\ConsoleOutputInterface;
use _ContaoManager\Symfony\Component\Console\Output\OutputInterface;
use _ContaoManager\Symfony\Component\Console\Style\SymfonyStyle;
/**
 * @author Nicolas Grekas <p@tchwork.com>
 *
 * @internal
 */
#[AsCommand(name: 'secrets:decrypt-to-local', description: 'Decrypt all secrets and stores them in the local vault')]
final class SecretsDecryptToLocalCommand extends Command
{
    private AbstractVault $vault;
    private ?AbstractVault $localVault;
    public function __construct(AbstractVault $vault, ?AbstractVault $localVault = null)
    {
        $this->vault = $vault;
        $this->localVault = $localVault;
        parent::__construct();
    }
    protected function configure(): void
    {
        $this->addOption('force', 'f', InputOption::VALUE_NONE, 'Force overriding of secrets that already exist in the local vault')->setHelp(<<<'EOF'
The <info>%command.name%</info> command decrypts all secrets and copies them in the local vault.

    <info>%command.full_name%</info>

When the <info>--force</info> option is provided, secrets that already exist in the local vault are overridden.

    <info>%command.full_name% --force</info>
EOF
);
    }
    protected function execute(InputInterface $input, OutputInterface $output): int
    {
        $io = new SymfonyStyle($input, $output instanceof ConsoleOutputInterface ? $output->getErrorOutput() : $output);
        if (null === $this->localVault) {
            $io->error('The local vault is disabled.');
            return 1;
        }
        $secrets = $this->vault->list(\true);
        $io->comment(\sprintf('%d secret%s found in the vault.', \count($secrets), 1 !== \count($secrets) ? 's' : ''));
        $skipped = 0;
        if (!$input->getOption('force')) {
            foreach ($this->localVault->list() as $k => $v) {
                if (isset($secrets[$k])) {
                    ++$skipped;
                    unset($secrets[$k]);
                }
            }
        }
        if ($skipped > 0) {
            $io->warning([\sprintf('%d secret%s already overridden in the local vault and will be skipped.', $skipped, 1 !== $skipped ? 's are' : ' is'), 'Use the --force flag to override these.']);
        }
        foreach ($secrets as $k => $v) {
            if (null === $v) {
                $io->error($this->vault->getLastMessage() ?? \sprintf('Secret "%s" has been skipped as there was an error reading it.', $k));
                continue;
            }
            $this->localVault->seal($k, $v);
            $io->note($this->localVault->getLastMessage());
        }
        return 0;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Bundle\FrameworkBundle\Command;

use _ContaoManager\Symfony\Component\Config\Definition\ConfigurationInterface;
use _ContaoManager\Symfony\Component\Console\Exception\LogicException;
use _ContaoManager\Symfony\Component\Console\Helper\Table;
use _ContaoManager\Symfony\Component\Console\Output\OutputInterface;
use _ContaoManager\Symfony\Component\Console\Style\StyleInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Extension\ConfigurationExtensionInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Extension\ExtensionInterface;
/**
 * A console command for dumping available configuration reference.
 *
 * @author Kevin Bond <kevinbond@gmail.com>
 * @author Wouter J <waldio.webdesign@gmail.com>
 * @author Grégoire Pineau <lyrixx@lyrixx.info>
 */
abstract class AbstractConfigCommand extends ContainerDebugCommand
{
    /**
     * @return void
     */
    protected function listBundles(OutputInterface|StyleInterface $output)
    {
        $title = 'Available registered bundles with their extension alias if available';
        $headers = ['Bundle name', 'Extension alias'];
        $rows = [];
        $bundles = $this->getApplication()->getKernel()->getBundles();
        usort($bundles, fn($bundleA, $bundleB) => strcmp($bundleA->getName(), $bundleB->getName()));
        foreach ($bundles as $bundle) {
            $extension = $bundle->getContainerExtension();
            $rows[] = [$bundle->getName(), $extension ? $extension->getAlias() : ''];
        }
        if ($output instanceof StyleInterface) {
            $output->title($title);
            $output->table($headers, $rows);
        } else {
            $output->writeln($title);
            $table = new Table($output);
            $table->setHeaders($headers)->setRows($rows)->render();
        }
    }
    protected function listNonBundleExtensions(OutputInterface|StyleInterface $output): void
    {
        $title = 'Available registered non-bundle extension aliases';
        $headers = ['Extension alias'];
        $rows = [];
        $kernel = $this->getApplication()->getKernel();
        $bundleExtensions = [];
        foreach ($kernel->getBundles() as $bundle) {
            if ($extension = $bundle->getContainerExtension()) {
                $bundleExtensions[$extension::class] = \true;
            }
        }
        $extensions = $this->getContainerBuilder($kernel)->getExtensions();
        foreach ($extensions as $alias => $extension) {
            if (isset($bundleExtensions[$extension::class])) {
                continue;
            }
            $rows[] = [$alias];
        }
        if (!$rows) {
            return;
        }
        if ($output instanceof StyleInterface) {
            $output->title($title);
            $output->table($headers, $rows);
        } else {
            $output->writeln($title);
            $table = new Table($output);
            $table->setHeaders($headers)->setRows($rows)->render();
        }
    }
    protected function findExtension(string $name): ExtensionInterface
    {
        $bundles = $this->initializeBundles();
        $minScore = \INF;
        $kernel = $this->getApplication()->getKernel();
        if ($kernel instanceof ExtensionInterface && ($kernel instanceof ConfigurationInterface || $kernel instanceof ConfigurationExtensionInterface)) {
            if ($name === $kernel->getAlias()) {
                return $kernel;
            }
            if ($kernel->getAlias()) {
                $distance = levenshtein($name, $kernel->getAlias());
                if ($distance < $minScore) {
                    $guess = $kernel->getAlias();
                    $minScore = $distance;
                }
            }
        }
        foreach ($bundles as $bundle) {
            if ($name === $bundle->getName()) {
                if (!$bundle->getContainerExtension()) {
                    throw new \LogicException(\sprintf('Bundle "%s" does not have a container extension.', $name));
                }
                return $bundle->getContainerExtension();
            }
            $distance = levenshtein($name, $bundle->getName());
            if ($distance < $minScore) {
                $guess = $bundle->getName();
                $minScore = $distance;
            }
        }
        $container = $this->getContainerBuilder($kernel);
        if ($container->hasExtension($name)) {
            return $container->getExtension($name);
        }
        foreach ($container->getExtensions() as $extension) {
            $distance = levenshtein($name, $extension->getAlias());
            if ($distance < $minScore) {
                $guess = $extension->getAlias();
                $minScore = $distance;
            }
        }
        if (!str_ends_with($name, 'Bundle')) {
            $message = \sprintf('No extensions with configuration available for "%s".', $name);
        } else {
            $message = \sprintf('No extension with alias "%s" is enabled.', $name);
        }
        if (isset($guess) && $minScore < 3) {
            $message .= \sprintf("\n\nDid you mean \"%s\"?", $guess);
        }
        throw new LogicException($message);
    }
    /**
     * @return void
     */
    public function validateConfiguration(ExtensionInterface $extension, mixed $configuration)
    {
        if (!$configuration) {
            throw new \LogicException(\sprintf('The extension with alias "%s" does not have its getConfiguration() method setup.', $extension->getAlias()));
        }
        if (!$configuration instanceof ConfigurationInterface) {
            throw new \LogicException(\sprintf('Configuration class "%s" should implement ConfigurationInterface in order to be dumpable.', get_debug_type($configuration)));
        }
    }
    private function initializeBundles(): array
    {
        // Re-build bundle manually to initialize DI extensions that can be extended by other bundles in their build() method
        // as this method is not called when the container is loaded from the cache.
        $kernel = $this->getApplication()->getKernel();
        $container = $this->getContainerBuilder($kernel);
        $bundles = $kernel->getBundles();
        foreach ($bundles as $bundle) {
            if ($extension = $bundle->getContainerExtension()) {
                $container->registerExtension($extension);
            }
        }
        foreach ($bundles as $bundle) {
            $bundle->build($container);
        }
        return $bundles;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Bundle\FrameworkBundle\Command;

use _ContaoManager\Symfony\Bundle\FrameworkBundle\Console\Helper\DescriptorHelper;
use _ContaoManager\Symfony\Component\Console\Attribute\AsCommand;
use _ContaoManager\Symfony\Component\Console\Command\Command;
use _ContaoManager\Symfony\Component\Console\Completion\CompletionInput;
use _ContaoManager\Symfony\Component\Console\Completion\CompletionSuggestions;
use _ContaoManager\Symfony\Component\Console\Exception\InvalidArgumentException;
use _ContaoManager\Symfony\Component\Console\Input\InputArgument;
use _ContaoManager\Symfony\Component\Console\Input\InputInterface;
use _ContaoManager\Symfony\Component\Console\Input\InputOption;
use _ContaoManager\Symfony\Component\Console\Output\OutputInterface;
use _ContaoManager\Symfony\Component\Console\Style\SymfonyStyle;
use _ContaoManager\Symfony\Component\ErrorHandler\ErrorRenderer\FileLinkFormatter;
use _ContaoManager\Symfony\Component\Routing\RouteCollection;
use _ContaoManager\Symfony\Component\Routing\RouterInterface;
/**
 * A console command for retrieving information about routes.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 * @author Tobias Schultze <http://tobion.de>
 *
 * @final
 */
#[AsCommand(name: 'debug:router', description: 'Display current routes for an application')]
class RouterDebugCommand extends Command
{
    use BuildDebugContainerTrait;
    private RouterInterface $router;
    private ?FileLinkFormatter $fileLinkFormatter;
    public function __construct(RouterInterface $router, ?FileLinkFormatter $fileLinkFormatter = null)
    {
        parent::__construct();
        $this->router = $router;
        $this->fileLinkFormatter = $fileLinkFormatter;
    }
    protected function configure(): void
    {
        $this->setDefinition([new InputArgument('name', InputArgument::OPTIONAL, 'A route name'), new InputOption('show-controllers', null, InputOption::VALUE_NONE, 'Show assigned controllers in overview'), new InputOption('show-aliases', null, InputOption::VALUE_NONE, 'Show aliases in overview'), new InputOption('format', null, InputOption::VALUE_REQUIRED, \sprintf('The output format ("%s")', implode('", "', $this->getAvailableFormatOptions())), 'txt'), new InputOption('raw', null, InputOption::VALUE_NONE, 'To output raw route(s)')])->setHelp(<<<'EOF'
The <info>%command.name%</info> displays the configured routes:

  <info>php %command.full_name%</info>

EOF
);
    }
    /**
     * @throws InvalidArgumentException When route does not exist
     */
    protected function execute(InputInterface $input, OutputInterface $output): int
    {
        $io = new SymfonyStyle($input, $output);
        $name = $input->getArgument('name');
        $helper = new DescriptorHelper($this->fileLinkFormatter);
        $routes = $this->router->getRouteCollection();
        $container = null;
        if ($this->fileLinkFormatter) {
            $container = fn() => $this->getContainerBuilder($this->getApplication()->getKernel());
        }
        if ($name) {
            $route = $routes->get($name);
            $matchingRoutes = $this->findRouteNameContaining($name, $routes);
            if (!$input->isInteractive() && !$route && \count($matchingRoutes) > 1) {
                $helper->describe($io, $this->findRouteContaining($name, $routes), ['format' => $input->getOption('format'), 'raw_text' => $input->getOption('raw'), 'show_controllers' => $input->getOption('show-controllers'), 'show_aliases' => $input->getOption('show-aliases'), 'output' => $io]);
                return 0;
            }
            if (!$route && $matchingRoutes) {
                $default = 1 === \count($matchingRoutes) ? $matchingRoutes[0] : null;
                $name = $io->choice('Select one of the matching routes', $matchingRoutes, $default);
                $route = $routes->get($name);
            }
            if (!$route) {
                throw new InvalidArgumentException(\sprintf('The route "%s" does not exist.', $name));
            }
            $helper->describe($io, $route, ['format' => $input->getOption('format'), 'raw_text' => $input->getOption('raw'), 'name' => $name, 'output' => $io, 'container' => $container]);
        } else {
            $helper->describe($io, $routes, ['format' => $input->getOption('format'), 'raw_text' => $input->getOption('raw'), 'show_controllers' => $input->getOption('show-controllers'), 'show_aliases' => $input->getOption('show-aliases'), 'output' => $io, 'container' => $container]);
        }
        return 0;
    }
    private function findRouteNameContaining(string $name, RouteCollection $routes): array
    {
        $foundRoutesNames = [];
        foreach ($routes as $routeName => $route) {
            if (\false !== stripos($routeName, $name)) {
                $foundRoutesNames[] = $routeName;
            }
        }
        return $foundRoutesNames;
    }
    public function complete(CompletionInput $input, CompletionSuggestions $suggestions): void
    {
        if ($input->mustSuggestArgumentValuesFor('name')) {
            $suggestions->suggestValues(array_keys($this->router->getRouteCollection()->all()));
            return;
        }
        if ($input->mustSuggestOptionValuesFor('format')) {
            $suggestions->suggestValues($this->getAvailableFormatOptions());
        }
    }
    private function findRouteContaining(string $name, RouteCollection $routes): RouteCollection
    {
        $foundRoutes = new RouteCollection();
        foreach ($routes as $routeName => $route) {
            if (\false !== stripos($routeName, $name)) {
                $foundRoutes->add($routeName, $route);
            }
        }
        return $foundRoutes;
    }
    private function getAvailableFormatOptions(): array
    {
        return (new DescriptorHelper())->getFormats();
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Bundle\FrameworkBundle\Command;

use _ContaoManager\Symfony\Component\Console\Attribute\AsCommand;
use _ContaoManager\Symfony\Component\Console\Command\Command;
use _ContaoManager\Symfony\Component\Console\Completion\CompletionInput;
use _ContaoManager\Symfony\Component\Console\Completion\CompletionSuggestions;
use _ContaoManager\Symfony\Component\Console\Exception\InvalidArgumentException;
use _ContaoManager\Symfony\Component\Console\Input\InputArgument;
use _ContaoManager\Symfony\Component\Console\Input\InputInterface;
use _ContaoManager\Symfony\Component\Console\Input\InputOption;
use _ContaoManager\Symfony\Component\Console\Output\OutputInterface;
use _ContaoManager\Symfony\Component\Console\Style\SymfonyStyle;
use _ContaoManager\Symfony\Component\HttpKernel\KernelInterface;
use _ContaoManager\Symfony\Component\Translation\Catalogue\MergeOperation;
use _ContaoManager\Symfony\Component\Translation\Catalogue\TargetOperation;
use _ContaoManager\Symfony\Component\Translation\Extractor\ExtractorInterface;
use _ContaoManager\Symfony\Component\Translation\MessageCatalogue;
use _ContaoManager\Symfony\Component\Translation\MessageCatalogueInterface;
use _ContaoManager\Symfony\Component\Translation\Reader\TranslationReaderInterface;
use _ContaoManager\Symfony\Component\Translation\Writer\TranslationWriterInterface;
/**
 * A command that parses templates to extract translation messages and adds them
 * into the translation files.
 *
 * @author Michel Salib <michelsalib@hotmail.com>
 *
 * @final
 */
#[AsCommand(name: 'translation:extract', description: 'Extract missing translations keys from code to translation files')]
class TranslationUpdateCommand extends Command
{
    private const ASC = 'asc';
    private const DESC = 'desc';
    private const SORT_ORDERS = [self::ASC, self::DESC];
    private const FORMATS = ['xlf12' => ['xlf', '1.2'], 'xlf20' => ['xlf', '2.0']];
    private TranslationWriterInterface $writer;
    private TranslationReaderInterface $reader;
    private ExtractorInterface $extractor;
    private string $defaultLocale;
    private ?string $defaultTransPath;
    private ?string $defaultViewsPath;
    private array $transPaths;
    private array $codePaths;
    private array $enabledLocales;
    public function __construct(TranslationWriterInterface $writer, TranslationReaderInterface $reader, ExtractorInterface $extractor, string $defaultLocale, ?string $defaultTransPath = null, ?string $defaultViewsPath = null, array $transPaths = [], array $codePaths = [], array $enabledLocales = [])
    {
        parent::__construct();
        if (!method_exists($writer, 'getFormats')) {
            throw new \InvalidArgumentException(\sprintf('The writer class "%s" does not implement the "getFormats()" method.', $writer::class));
        }
        $this->writer = $writer;
        $this->reader = $reader;
        $this->extractor = $extractor;
        $this->defaultLocale = $defaultLocale;
        $this->defaultTransPath = $defaultTransPath;
        $this->defaultViewsPath = $defaultViewsPath;
        $this->transPaths = $transPaths;
        $this->codePaths = $codePaths;
        $this->enabledLocales = $enabledLocales;
    }
    protected function configure(): void
    {
        $this->setDefinition([new InputArgument('locale', InputArgument::REQUIRED, 'The locale'), new InputArgument('bundle', InputArgument::OPTIONAL, 'The bundle name or directory where to load the messages'), new InputOption('prefix', null, InputOption::VALUE_REQUIRED, 'Override the default prefix', '__'), new InputOption('format', null, InputOption::VALUE_REQUIRED, 'Override the default output format', 'xlf12'), new InputOption('dump-messages', null, InputOption::VALUE_NONE, 'Should the messages be dumped in the console'), new InputOption('force', null, InputOption::VALUE_NONE, 'Should the extract be done'), new InputOption('clean', null, InputOption::VALUE_NONE, 'Should clean not found messages'), new InputOption('domain', null, InputOption::VALUE_REQUIRED, 'Specify the domain to extract'), new InputOption('sort', null, InputOption::VALUE_OPTIONAL, 'Return list of messages sorted alphabetically (only works with --dump-messages)', 'asc'), new InputOption('as-tree', null, InputOption::VALUE_REQUIRED, 'Dump the messages as a tree-like structure: The given value defines the level where to switch to inline YAML')])->setHelp(<<<'EOF'
The <info>%command.name%</info> command extracts translation strings from templates
of a given bundle or the default translations directory. It can display them or merge
the new ones into the translation files.

When new translation strings are found it can automatically add a prefix to the translation
message.

Example running against a Bundle (AcmeBundle)

  <info>php %command.full_name% --dump-messages en AcmeBundle</info>
  <info>php %command.full_name% --force --prefix="new_" fr AcmeBundle</info>

Example running against default messages directory

  <info>php %command.full_name% --dump-messages en</info>
  <info>php %command.full_name% --force --prefix="new_" fr</info>

You can sort the output with the <comment>--sort</> flag:

    <info>php %command.full_name% --dump-messages --sort=asc en AcmeBundle</info>
    <info>php %command.full_name% --dump-messages --sort=desc fr</info>

You can dump a tree-like structure using the yaml format with <comment>--as-tree</> flag:

    <info>php %command.full_name% --force --format=yaml --as-tree=3 en AcmeBundle</info>

EOF
);
    }
    protected function execute(InputInterface $input, OutputInterface $output): int
    {
        $io = new SymfonyStyle($input, $output);
        $errorIo = $io->getErrorStyle();
        // check presence of force or dump-message
        if (\true !== $input->getOption('force') && \true !== $input->getOption('dump-messages')) {
            $errorIo->error('You must choose one of --force or --dump-messages');
            return 1;
        }
        $format = $input->getOption('format');
        $xliffVersion = '1.2';
        if (\array_key_exists($format, self::FORMATS)) {
            [$format, $xliffVersion] = self::FORMATS[$format];
        }
        // check format
        $supportedFormats = $this->writer->getFormats();
        if (!\in_array($format, $supportedFormats, \true)) {
            $errorIo->error(['Wrong output format', 'Supported formats are: ' . implode(', ', $supportedFormats) . ', xlf12 and xlf20.']);
            return 1;
        }
        /** @var KernelInterface $kernel */
        $kernel = $this->getApplication()->getKernel();
        // Define Root Paths
        $transPaths = $this->getRootTransPaths();
        $codePaths = $this->getRootCodePaths($kernel);
        $currentName = 'default directory';
        // Override with provided Bundle info
        if (null !== $input->getArgument('bundle')) {
            try {
                $foundBundle = $kernel->getBundle($input->getArgument('bundle'));
                $bundleDir = $foundBundle->getPath();
                $transPaths = [is_dir($bundleDir . '/Resources/translations') ? $bundleDir . '/Resources/translations' : $bundleDir . '/translations'];
                $codePaths = [is_dir($bundleDir . '/Resources/views') ? $bundleDir . '/Resources/views' : $bundleDir . '/templates'];
                if ($this->defaultTransPath) {
                    $transPaths[] = $this->defaultTransPath;
                }
                if ($this->defaultViewsPath) {
                    $codePaths[] = $this->defaultViewsPath;
                }
                $currentName = $foundBundle->getName();
            } catch (\InvalidArgumentException) {
                // such a bundle does not exist, so treat the argument as path
                $path = $input->getArgument('bundle');
                $transPaths = [$path . '/translations'];
                $codePaths = [$path . '/templates'];
                if (!is_dir($transPaths[0])) {
                    throw new InvalidArgumentException(\sprintf('"%s" is neither an enabled bundle nor a directory.', $transPaths[0]));
                }
            }
        }
        $io->title('Translation Messages Extractor and Dumper');
        $io->comment(\sprintf('Generating "<info>%s</info>" translation files for "<info>%s</info>"', $input->getArgument('locale'), $currentName));
        $io->comment('Parsing templates...');
        $extractedCatalogue = $this->extractMessages($input->getArgument('locale'), $codePaths, $input->getOption('prefix'));
        $io->comment('Loading translation files...');
        $currentCatalogue = $this->loadCurrentMessages($input->getArgument('locale'), $transPaths);
        if (null !== $domain = $input->getOption('domain')) {
            $currentCatalogue = $this->filterCatalogue($currentCatalogue, $domain);
            $extractedCatalogue = $this->filterCatalogue($extractedCatalogue, $domain);
        }
        // process catalogues
        $operation = $input->getOption('clean') ? new TargetOperation($currentCatalogue, $extractedCatalogue) : new MergeOperation($currentCatalogue, $extractedCatalogue);
        // Exit if no messages found.
        if (!\count($operation->getDomains())) {
            $errorIo->warning('No translation messages were found.');
            return 0;
        }
        $resultMessage = 'Translation files were successfully updated';
        $operation->moveMessagesToIntlDomainsIfPossible('new');
        // show compiled list of messages
        if (\true === $input->getOption('dump-messages')) {
            $extractedMessagesCount = 0;
            $io->newLine();
            foreach ($operation->getDomains() as $domain) {
                $newKeys = array_keys($operation->getNewMessages($domain));
                $allKeys = array_keys($operation->getMessages($domain));
                $list = array_merge(array_diff($allKeys, $newKeys), array_map(fn($id) => \sprintf('<fg=green>%s</>', $id), $newKeys), array_map(fn($id) => \sprintf('<fg=red>%s</>', $id), array_keys($operation->getObsoleteMessages($domain))));
                $domainMessagesCount = \count($list);
                if ($sort = $input->getOption('sort')) {
                    $sort = strtolower($sort);
                    if (!\in_array($sort, self::SORT_ORDERS, \true)) {
                        $errorIo->error(['Wrong sort order', 'Supported formats are: ' . implode(', ', self::SORT_ORDERS) . '.']);
                        return 1;
                    }
                    if (self::DESC === $sort) {
                        rsort($list);
                    } else {
                        sort($list);
                    }
                }
                $io->section(\sprintf('Messages extracted for domain "<info>%s</info>" (%d message%s)', $domain, $domainMessagesCount, $domainMessagesCount > 1 ? 's' : ''));
                $io->listing($list);
                $extractedMessagesCount += $domainMessagesCount;
            }
            if ('xlf' === $format) {
                $io->comment(\sprintf('Xliff output version is <info>%s</info>', $xliffVersion));
            }
            $resultMessage = \sprintf('%d message%s successfully extracted', $extractedMessagesCount, $extractedMessagesCount > 1 ? 's were' : ' was');
        }
        // save the files
        if (\true === $input->getOption('force')) {
            $io->comment('Writing files...');
            $bundleTransPath = \false;
            foreach ($transPaths as $path) {
                if (is_dir($path)) {
                    $bundleTransPath = $path;
                }
            }
            if (!$bundleTransPath) {
                $bundleTransPath = end($transPaths);
            }
            $this->writer->write($operation->getResult(), $format, ['path' => $bundleTransPath, 'default_locale' => $this->defaultLocale, 'xliff_version' => $xliffVersion, 'as_tree' => $input->getOption('as-tree'), 'inline' => $input->getOption('as-tree') ?? 0]);
            if (\true === $input->getOption('dump-messages')) {
                $resultMessage .= ' and translation files were updated';
            }
        }
        $io->success($resultMessage . '.');
        return 0;
    }
    public function complete(CompletionInput $input, CompletionSuggestions $suggestions): void
    {
        if ($input->mustSuggestArgumentValuesFor('locale')) {
            $suggestions->suggestValues($this->enabledLocales);
            return;
        }
        /** @var KernelInterface $kernel */
        $kernel = $this->getApplication()->getKernel();
        if ($input->mustSuggestArgumentValuesFor('bundle')) {
            $bundles = [];
            foreach ($kernel->getBundles() as $bundle) {
                $bundles[] = $bundle->getName();
                if ($bundle->getContainerExtension()) {
                    $bundles[] = $bundle->getContainerExtension()->getAlias();
                }
            }
            $suggestions->suggestValues($bundles);
            return;
        }
        if ($input->mustSuggestOptionValuesFor('format')) {
            $suggestions->suggestValues(array_merge($this->writer->getFormats(), array_keys(self::FORMATS)));
            return;
        }
        if ($input->mustSuggestOptionValuesFor('domain') && $locale = $input->getArgument('locale')) {
            $extractedCatalogue = $this->extractMessages($locale, $this->getRootCodePaths($kernel), $input->getOption('prefix'));
            $currentCatalogue = $this->loadCurrentMessages($locale, $this->getRootTransPaths());
            // process catalogues
            $operation = $input->getOption('clean') ? new TargetOperation($currentCatalogue, $extractedCatalogue) : new MergeOperation($currentCatalogue, $extractedCatalogue);
            $suggestions->suggestValues($operation->getDomains());
            return;
        }
        if ($input->mustSuggestOptionValuesFor('sort')) {
            $suggestions->suggestValues(self::SORT_ORDERS);
        }
    }
    private function filterCatalogue(MessageCatalogue $catalogue, string $domain): MessageCatalogue
    {
        $filteredCatalogue = new MessageCatalogue($catalogue->getLocale());
        // extract intl-icu messages only
        $intlDomain = $domain . MessageCatalogueInterface::INTL_DOMAIN_SUFFIX;
        if ($intlMessages = $catalogue->all($intlDomain)) {
            $filteredCatalogue->add($intlMessages, $intlDomain);
        }
        // extract all messages and subtract intl-icu messages
        if ($messages = array_diff($catalogue->all($domain), $intlMessages)) {
            $filteredCatalogue->add($messages, $domain);
        }
        foreach ($catalogue->getResources() as $resource) {
            $filteredCatalogue->addResource($resource);
        }
        if ($metadata = $catalogue->getMetadata('', $intlDomain)) {
            foreach ($metadata as $k => $v) {
                $filteredCatalogue->setMetadata($k, $v, $intlDomain);
            }
        }
        if ($metadata = $catalogue->getMetadata('', $domain)) {
            foreach ($metadata as $k => $v) {
                $filteredCatalogue->setMetadata($k, $v, $domain);
            }
        }
        return $filteredCatalogue;
    }
    private function extractMessages(string $locale, array $transPaths, string $prefix): MessageCatalogue
    {
        $extractedCatalogue = new MessageCatalogue($locale);
        $this->extractor->setPrefix($prefix);
        $transPaths = $this->filterDuplicateTransPaths($transPaths);
        foreach ($transPaths as $path) {
            if (is_dir($path) || is_file($path)) {
                $this->extractor->extract($path, $extractedCatalogue);
            }
        }
        return $extractedCatalogue;
    }
    private function filterDuplicateTransPaths(array $transPaths): array
    {
        $transPaths = array_filter(array_map('realpath', $transPaths));
        sort($transPaths);
        $filteredPaths = [];
        foreach ($transPaths as $path) {
            foreach ($filteredPaths as $filteredPath) {
                if (str_starts_with($path, $filteredPath . \DIRECTORY_SEPARATOR)) {
                    continue 2;
                }
            }
            $filteredPaths[] = $path;
        }
        return $filteredPaths;
    }
    private function loadCurrentMessages(string $locale, array $transPaths): MessageCatalogue
    {
        $currentCatalogue = new MessageCatalogue($locale);
        foreach ($transPaths as $path) {
            if (is_dir($path)) {
                $this->reader->read($path, $currentCatalogue);
            }
        }
        return $currentCatalogue;
    }
    private function getRootTransPaths(): array
    {
        $transPaths = $this->transPaths;
        if ($this->defaultTransPath) {
            $transPaths[] = $this->defaultTransPath;
        }
        return $transPaths;
    }
    private function getRootCodePaths(KernelInterface $kernel): array
    {
        $codePaths = $this->codePaths;
        $codePaths[] = $kernel->getProjectDir() . '/src';
        if ($this->defaultViewsPath) {
            $codePaths[] = $this->defaultViewsPath;
        }
        return $codePaths;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Bundle\FrameworkBundle\Command;

use _ContaoManager\Symfony\Component\Config\Definition\ConfigurationInterface;
use _ContaoManager\Symfony\Component\Config\Definition\Dumper\XmlReferenceDumper;
use _ContaoManager\Symfony\Component\Config\Definition\Dumper\YamlReferenceDumper;
use _ContaoManager\Symfony\Component\Console\Attribute\AsCommand;
use _ContaoManager\Symfony\Component\Console\Completion\CompletionInput;
use _ContaoManager\Symfony\Component\Console\Completion\CompletionSuggestions;
use _ContaoManager\Symfony\Component\Console\Exception\InvalidArgumentException;
use _ContaoManager\Symfony\Component\Console\Input\InputArgument;
use _ContaoManager\Symfony\Component\Console\Input\InputInterface;
use _ContaoManager\Symfony\Component\Console\Input\InputOption;
use _ContaoManager\Symfony\Component\Console\Output\OutputInterface;
use _ContaoManager\Symfony\Component\Console\Style\SymfonyStyle;
use _ContaoManager\Symfony\Component\Yaml\Yaml;
/**
 * A console command for dumping available configuration reference.
 *
 * @author Kevin Bond <kevinbond@gmail.com>
 * @author Wouter J <waldio.webdesign@gmail.com>
 * @author Grégoire Pineau <lyrixx@lyrixx.info>
 *
 * @final
 */
#[AsCommand(name: 'config:dump-reference', description: 'Dump the default configuration for an extension')]
class ConfigDumpReferenceCommand extends AbstractConfigCommand
{
    protected function configure(): void
    {
        $commentedHelpFormats = array_map(fn($format) => \sprintf('<comment>%s</comment>', $format), $this->getAvailableFormatOptions());
        $helpFormats = implode('", "', $commentedHelpFormats);
        $this->setDefinition([new InputArgument('name', InputArgument::OPTIONAL, 'The Bundle name or the extension alias'), new InputArgument('path', InputArgument::OPTIONAL, 'The configuration option path'), new InputOption('format', null, InputOption::VALUE_REQUIRED, \sprintf('The output format ("%s")', implode('", "', $this->getAvailableFormatOptions())), 'yaml')])->setHelp(<<<EOF
The <info>%command.name%</info> command dumps the default configuration for an
extension/bundle.

Either the extension alias or bundle name can be used:

  <info>php %command.full_name% framework</info>
  <info>php %command.full_name% FrameworkBundle</info>

The <info>--format</info> option specifies the format of the configuration,
these are "{$helpFormats}".

  <info>php %command.full_name% FrameworkBundle --format=xml</info>

For dumping a specific option, add its path as second argument (only available for the yaml format):

  <info>php %command.full_name% framework http_client.default_options</info>

EOF
);
    }
    /**
     * @throws \LogicException
     */
    protected function execute(InputInterface $input, OutputInterface $output): int
    {
        $io = new SymfonyStyle($input, $output);
        $errorIo = $io->getErrorStyle();
        if (null === $name = $input->getArgument('name')) {
            $this->listBundles($errorIo);
            $this->listNonBundleExtensions($errorIo);
            $errorIo->comment(['Provide the name of a bundle as the first argument of this command to dump its default configuration. (e.g. <comment>config:dump-reference FrameworkBundle</comment>)', 'For dumping a specific option, add its path as the second argument of this command. (e.g. <comment>config:dump-reference FrameworkBundle http_client.default_options</comment> to dump the <comment>framework.http_client.default_options</comment> configuration)']);
            return 0;
        }
        $extension = $this->findExtension($name);
        if ($extension instanceof ConfigurationInterface) {
            $configuration = $extension;
        } else {
            $configuration = $extension->getConfiguration([], $this->getContainerBuilder($this->getApplication()->getKernel()));
        }
        $this->validateConfiguration($extension, $configuration);
        $format = $input->getOption('format');
        if ('yaml' === $format && !class_exists(Yaml::class)) {
            $errorIo->error('Setting the "format" option to "yaml" requires the Symfony Yaml component. Try running "composer install symfony/yaml" or use "--format=xml" instead.');
            return 1;
        }
        $path = $input->getArgument('path');
        if (null !== $path && 'yaml' !== $format) {
            $errorIo->error('The "path" option is only available for the "yaml" format.');
            return 1;
        }
        if ($name === $extension->getAlias()) {
            $message = \sprintf('Default configuration for extension with alias: "%s"', $name);
        } else {
            $message = \sprintf('Default configuration for "%s"', $name);
        }
        if (null !== $path) {
            $message .= \sprintf(' at path "%s"', $path);
        }
        switch ($format) {
            case 'yaml':
                $io->writeln(\sprintf('# %s', $message));
                $dumper = new YamlReferenceDumper();
                break;
            case 'xml':
                $io->writeln(\sprintf('<!-- %s -->', $message));
                $dumper = new XmlReferenceDumper();
                break;
            default:
                $io->writeln($message);
                throw new InvalidArgumentException(\sprintf('Supported formats are "%s".', implode('", "', $this->getAvailableFormatOptions())));
        }
        $io->writeln(null === $path ? $dumper->dump($configuration, $extension->getNamespace()) : $dumper->dumpAtPath($configuration, $path));
        return 0;
    }
    public function complete(CompletionInput $input, CompletionSuggestions $suggestions): void
    {
        if ($input->mustSuggestArgumentValuesFor('name')) {
            $suggestions->suggestValues($this->getAvailableExtensions());
            $suggestions->suggestValues($this->getAvailableBundles());
        }
        if ($input->mustSuggestOptionValuesFor('format')) {
            $suggestions->suggestValues($this->getAvailableFormatOptions());
        }
    }
    private function getAvailableExtensions(): array
    {
        $kernel = $this->getApplication()->getKernel();
        $extensions = [];
        foreach ($this->getContainerBuilder($kernel)->getExtensions() as $alias => $extension) {
            $extensions[] = $alias;
        }
        return $extensions;
    }
    private function getAvailableBundles(): array
    {
        $bundles = [];
        foreach ($this->getApplication()->getKernel()->getBundles() as $bundle) {
            $bundles[] = $bundle->getName();
        }
        return $bundles;
    }
    private function getAvailableFormatOptions(): array
    {
        return ['yaml', 'xml'];
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Bundle\FrameworkBundle\Command;

use _ContaoManager\Symfony\Component\Console\Attribute\AsCommand;
use _ContaoManager\Symfony\Component\Console\Command\Command;
use _ContaoManager\Symfony\Component\Console\Exception\InvalidArgumentException;
use _ContaoManager\Symfony\Component\Console\Input\InputArgument;
use _ContaoManager\Symfony\Component\Console\Input\InputInterface;
use _ContaoManager\Symfony\Component\Console\Input\InputOption;
use _ContaoManager\Symfony\Component\Console\Output\OutputInterface;
use _ContaoManager\Symfony\Component\Console\Style\SymfonyStyle;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerInterface;
use _ContaoManager\Symfony\Component\Filesystem\Exception\IOException;
use _ContaoManager\Symfony\Component\Filesystem\Filesystem;
use _ContaoManager\Symfony\Component\Finder\Finder;
use _ContaoManager\Symfony\Component\HttpKernel\Bundle\BundleInterface;
use _ContaoManager\Symfony\Component\HttpKernel\KernelInterface;
/**
 * Command that places bundle web assets into a given directory.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 * @author Gábor Egyed <gabor.egyed@gmail.com>
 *
 * @final
 */
#[AsCommand(name: 'assets:install', description: 'Install bundle\'s web assets under a public directory')]
class AssetsInstallCommand extends Command
{
    public const METHOD_COPY = 'copy';
    public const METHOD_ABSOLUTE_SYMLINK = 'absolute symlink';
    public const METHOD_RELATIVE_SYMLINK = 'relative symlink';
    private Filesystem $filesystem;
    private string $projectDir;
    public function __construct(Filesystem $filesystem, string $projectDir)
    {
        parent::__construct();
        $this->filesystem = $filesystem;
        $this->projectDir = $projectDir;
    }
    protected function configure(): void
    {
        $this->setDefinition([new InputArgument('target', InputArgument::OPTIONAL, 'The target directory', null)])->addOption('symlink', null, InputOption::VALUE_NONE, 'Symlink the assets instead of copying them')->addOption('relative', null, InputOption::VALUE_NONE, 'Make relative symlinks')->addOption('no-cleanup', null, InputOption::VALUE_NONE, 'Do not remove the assets of the bundles that no longer exist')->setHelp(<<<'EOT'
The <info>%command.name%</info> command installs bundle assets into a given
directory (e.g. the <comment>public</comment> directory).

  <info>php %command.full_name% public</info>

A "bundles" directory will be created inside the target directory and the
"Resources/public" directory of each bundle will be copied into it.

To create a symlink to each bundle instead of copying its assets, use the
<info>--symlink</info> option (will fall back to hard copies when symbolic links aren't possible:

  <info>php %command.full_name% public --symlink</info>

To make symlink relative, add the <info>--relative</info> option:

  <info>php %command.full_name% public --symlink --relative</info>

EOT
);
    }
    protected function execute(InputInterface $input, OutputInterface $output): int
    {
        /** @var KernelInterface $kernel */
        $kernel = $this->getApplication()->getKernel();
        $targetArg = rtrim($input->getArgument('target') ?? '', '/');
        if (!$targetArg) {
            $targetArg = $this->getPublicDirectory($kernel->getContainer());
        }
        if (!is_dir($targetArg)) {
            $targetArg = $kernel->getProjectDir() . '/' . $targetArg;
            if (!is_dir($targetArg)) {
                throw new InvalidArgumentException(\sprintf('The target directory "%s" does not exist.', $targetArg));
            }
        }
        $bundlesDir = $targetArg . '/bundles/';
        $io = new SymfonyStyle($input, $output);
        $io->newLine();
        if ($input->getOption('relative')) {
            $expectedMethod = self::METHOD_RELATIVE_SYMLINK;
            $io->text('Trying to install assets as <info>relative symbolic links</info>.');
        } elseif ($input->getOption('symlink')) {
            $expectedMethod = self::METHOD_ABSOLUTE_SYMLINK;
            $io->text('Trying to install assets as <info>absolute symbolic links</info>.');
        } else {
            $expectedMethod = self::METHOD_COPY;
            $io->text('Installing assets as <info>hard copies</info>.');
        }
        $io->newLine();
        $rows = [];
        $copyUsed = \false;
        $exitCode = 0;
        $validAssetDirs = [];
        /** @var BundleInterface $bundle */
        foreach ($kernel->getBundles() as $bundle) {
            if (!is_dir($originDir = $bundle->getPath() . '/Resources/public') && !is_dir($originDir = $bundle->getPath() . '/public')) {
                continue;
            }
            $assetDir = preg_replace('/bundle$/', '', strtolower($bundle->getName()));
            $targetDir = $bundlesDir . $assetDir;
            $validAssetDirs[] = $assetDir;
            if (OutputInterface::VERBOSITY_VERBOSE <= $output->getVerbosity()) {
                $message = \sprintf("%s\n-> %s", $bundle->getName(), $targetDir);
            } else {
                $message = $bundle->getName();
            }
            try {
                $this->filesystem->remove($targetDir);
                if (self::METHOD_RELATIVE_SYMLINK === $expectedMethod) {
                    $method = $this->relativeSymlinkWithFallback($originDir, $targetDir);
                } elseif (self::METHOD_ABSOLUTE_SYMLINK === $expectedMethod) {
                    $method = $this->absoluteSymlinkWithFallback($originDir, $targetDir);
                } else {
                    $method = $this->hardCopy($originDir, $targetDir);
                }
                if (self::METHOD_COPY === $method) {
                    $copyUsed = \true;
                }
                if ($method === $expectedMethod) {
                    $rows[] = [\sprintf('<fg=green;options=bold>%s</>', '\\' === \DIRECTORY_SEPARATOR ? 'OK' : "✔"), $message, $method];
                } else {
                    $rows[] = [\sprintf('<fg=yellow;options=bold>%s</>', '\\' === \DIRECTORY_SEPARATOR ? 'WARNING' : '!'), $message, $method];
                }
            } catch (\Exception $e) {
                $exitCode = 1;
                $rows[] = [\sprintf('<fg=red;options=bold>%s</>', '\\' === \DIRECTORY_SEPARATOR ? 'ERROR' : "✘"), $message, $e->getMessage()];
            }
        }
        // remove the assets of the bundles that no longer exist
        if (!$input->getOption('no-cleanup') && is_dir($bundlesDir)) {
            $dirsToRemove = Finder::create()->depth(0)->directories()->exclude($validAssetDirs)->in($bundlesDir);
            $this->filesystem->remove($dirsToRemove);
        }
        if ($rows) {
            $io->table(['', 'Bundle', 'Method / Error'], $rows);
        }
        if (0 !== $exitCode) {
            $io->error('Some errors occurred while installing assets.');
        } else {
            if ($copyUsed) {
                $io->note('Some assets were installed via copy. If you make changes to these assets you have to run this command again.');
            }
            $io->success($rows ? 'All assets were successfully installed.' : 'No assets were provided by any bundle.');
        }
        return $exitCode;
    }
    /**
     * Try to create relative symlink.
     *
     * Falling back to absolute symlink and finally hard copy.
     */
    private function relativeSymlinkWithFallback(string $originDir, string $targetDir): string
    {
        try {
            $this->symlink($originDir, $targetDir, \true);
            $method = self::METHOD_RELATIVE_SYMLINK;
        } catch (IOException) {
            $method = $this->absoluteSymlinkWithFallback($originDir, $targetDir);
        }
        return $method;
    }
    /**
     * Try to create absolute symlink.
     *
     * Falling back to hard copy.
     */
    private function absoluteSymlinkWithFallback(string $originDir, string $targetDir): string
    {
        try {
            $this->symlink($originDir, $targetDir);
            $method = self::METHOD_ABSOLUTE_SYMLINK;
        } catch (IOException) {
            // fall back to copy
            $method = $this->hardCopy($originDir, $targetDir);
        }
        return $method;
    }
    /**
     * Creates symbolic link.
     *
     * @throws IOException if link cannot be created
     */
    private function symlink(string $originDir, string $targetDir, bool $relative = \false): void
    {
        if ($relative) {
            $this->filesystem->mkdir(\dirname($targetDir));
            $originDir = $this->filesystem->makePathRelative($originDir, realpath(\dirname($targetDir)));
        }
        $this->filesystem->symlink($originDir, $targetDir);
        if (!file_exists($targetDir)) {
            throw new IOException(\sprintf('Symbolic link "%s" was created but appears to be broken.', $targetDir), 0, null, $targetDir);
        }
    }
    /**
     * Copies origin to target.
     */
    private function hardCopy(string $originDir, string $targetDir): string
    {
        $this->filesystem->mkdir($targetDir, 0777);
        // We use a custom iterator to ignore VCS files
        $this->filesystem->mirror($originDir, $targetDir, Finder::create()->ignoreDotFiles(\false)->in($originDir));
        return self::METHOD_COPY;
    }
    private function getPublicDirectory(ContainerInterface $container): string
    {
        $defaultPublicDir = 'public';
        if (null === $this->projectDir && !$container->hasParameter('kernel.project_dir')) {
            return $defaultPublicDir;
        }
        $composerFilePath = ($this->projectDir ?? $container->getParameter('kernel.project_dir')) . '/composer.json';
        if (!file_exists($composerFilePath)) {
            return $defaultPublicDir;
        }
        $composerConfig = json_decode(file_get_contents($composerFilePath), \true);
        return $composerConfig['extra']['public-dir'] ?? $defaultPublicDir;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Bundle\FrameworkBundle\Command;

use _ContaoManager\Symfony\Component\Cache\PruneableInterface;
use _ContaoManager\Symfony\Component\Console\Attribute\AsCommand;
use _ContaoManager\Symfony\Component\Console\Command\Command;
use _ContaoManager\Symfony\Component\Console\Input\InputInterface;
use _ContaoManager\Symfony\Component\Console\Output\OutputInterface;
use _ContaoManager\Symfony\Component\Console\Style\SymfonyStyle;
/**
 * Cache pool pruner command.
 *
 * @author Rob Frawley 2nd <rmf@src.run>
 */
#[AsCommand(name: 'cache:pool:prune', description: 'Prune cache pools')]
final class CachePoolPruneCommand extends Command
{
    private iterable $pools;
    /**
     * @param iterable<mixed, PruneableInterface> $pools
     */
    public function __construct(iterable $pools)
    {
        parent::__construct();
        $this->pools = $pools;
    }
    protected function configure(): void
    {
        $this->setHelp(<<<'EOF'
The <info>%command.name%</info> command deletes all expired items from all pruneable pools.

    %command.full_name%
EOF
);
    }
    protected function execute(InputInterface $input, OutputInterface $output): int
    {
        $io = new SymfonyStyle($input, $output);
        $exitCode = Command::SUCCESS;
        foreach ($this->pools as $name => $pool) {
            $io->comment(\sprintf('Pruning cache pool: <info>%s</info>', $name));
            if (!$pool->prune()) {
                $io->error(\sprintf('Cache pool "%s" could not be pruned.', $name));
                $exitCode = Command::FAILURE;
            }
        }
        if (Command::SUCCESS === $exitCode) {
            $io->success('Successfully pruned cache pool(s).');
        }
        return $exitCode;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Bundle\FrameworkBundle\Command;

use _ContaoManager\Psr\Cache\CacheItemPoolInterface;
use _ContaoManager\Symfony\Component\Console\Attribute\AsCommand;
use _ContaoManager\Symfony\Component\Console\Command\Command;
use _ContaoManager\Symfony\Component\Console\Completion\CompletionInput;
use _ContaoManager\Symfony\Component\Console\Completion\CompletionSuggestions;
use _ContaoManager\Symfony\Component\Console\Exception\InvalidArgumentException;
use _ContaoManager\Symfony\Component\Console\Input\InputArgument;
use _ContaoManager\Symfony\Component\Console\Input\InputInterface;
use _ContaoManager\Symfony\Component\Console\Input\InputOption;
use _ContaoManager\Symfony\Component\Console\Output\OutputInterface;
use _ContaoManager\Symfony\Component\Console\Style\SymfonyStyle;
use _ContaoManager\Symfony\Component\HttpKernel\CacheClearer\Psr6CacheClearer;
/**
 * Clear cache pools.
 *
 * @author Nicolas Grekas <p@tchwork.com>
 */
#[AsCommand(name: 'cache:pool:clear', description: 'Clear cache pools')]
final class CachePoolClearCommand extends Command
{
    private Psr6CacheClearer $poolClearer;
    private ?array $poolNames;
    /**
     * @param string[]|null $poolNames
     */
    public function __construct(Psr6CacheClearer $poolClearer, ?array $poolNames = null)
    {
        parent::__construct();
        $this->poolClearer = $poolClearer;
        $this->poolNames = $poolNames;
    }
    protected function configure(): void
    {
        $this->setDefinition([new InputArgument('pools', InputArgument::IS_ARRAY | InputArgument::OPTIONAL, 'A list of cache pools or cache pool clearers')])->addOption('all', null, InputOption::VALUE_NONE, 'Clear all cache pools')->addOption('exclude', null, InputOption::VALUE_IS_ARRAY | InputOption::VALUE_REQUIRED, 'A list of cache pools or cache pool clearers to exclude')->setHelp(<<<'EOF'
The <info>%command.name%</info> command clears the given cache pools or cache pool clearers.

    %command.full_name% <cache pool or clearer 1> [...<cache pool or clearer N>]
EOF
);
    }
    protected function execute(InputInterface $input, OutputInterface $output): int
    {
        $io = new SymfonyStyle($input, $output);
        $kernel = $this->getApplication()->getKernel();
        $pools = [];
        $clearers = [];
        $poolNames = $input->getArgument('pools');
        $excludedPoolNames = $input->getOption('exclude');
        if ($clearAll = $input->getOption('all')) {
            if (!$this->poolNames) {
                throw new InvalidArgumentException('Could not clear all cache pools, try specifying a specific pool or cache clearer.');
            }
            if (!$excludedPoolNames) {
                $io->comment('Clearing all cache pools...');
            }
            $poolNames = $this->poolNames;
        } elseif (!$poolNames) {
            throw new InvalidArgumentException('Either specify at least one pool name, or provide the --all option to clear all pools.');
        }
        $poolNames = array_diff($poolNames, $excludedPoolNames);
        foreach ($poolNames as $id) {
            if ($this->poolClearer->hasPool($id)) {
                $pools[$id] = $id;
            } elseif (!$clearAll || $kernel->getContainer()->has($id)) {
                $pool = $kernel->getContainer()->get($id);
                if ($pool instanceof CacheItemPoolInterface) {
                    $pools[$id] = $pool;
                } elseif ($pool instanceof Psr6CacheClearer) {
                    $clearers[$id] = $pool;
                } else {
                    throw new InvalidArgumentException(\sprintf('"%s" is not a cache pool nor a cache clearer.', $id));
                }
            }
        }
        foreach ($clearers as $id => $clearer) {
            $io->comment(\sprintf('Calling cache clearer: <info>%s</info>', $id));
            $clearer->clear($kernel->getContainer()->getParameter('kernel.cache_dir'));
        }
        $failure = \false;
        foreach ($pools as $id => $pool) {
            $io->comment(\sprintf('Clearing cache pool: <info>%s</info>', $id));
            if ($pool instanceof CacheItemPoolInterface) {
                if (!$pool->clear()) {
                    $io->warning(\sprintf('Cache pool "%s" could not be cleared.', $pool));
                    $failure = \true;
                }
            } else if (\false === $this->poolClearer->clearPool($id)) {
                $io->warning(\sprintf('Cache pool "%s" could not be cleared.', $pool));
                $failure = \true;
            }
        }
        if ($failure) {
            return 1;
        }
        $io->success('Cache was successfully cleared.');
        return 0;
    }
    public function complete(CompletionInput $input, CompletionSuggestions $suggestions): void
    {
        if (\is_array($this->poolNames) && $input->mustSuggestArgumentValuesFor('pools')) {
            $suggestions->suggestValues($this->poolNames);
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Bundle\FrameworkBundle\Command;

use _ContaoManager\Symfony\Component\Config\ConfigCache;
use _ContaoManager\Symfony\Component\Config\FileLocator;
use _ContaoManager\Symfony\Component\Console\Attribute\AsCommand;
use _ContaoManager\Symfony\Component\Console\Command\Command;
use _ContaoManager\Symfony\Component\Console\Exception\RuntimeException;
use _ContaoManager\Symfony\Component\Console\Input\InputInterface;
use _ContaoManager\Symfony\Component\Console\Output\OutputInterface;
use _ContaoManager\Symfony\Component\Console\Style\SymfonyStyle;
use _ContaoManager\Symfony\Component\DependencyInjection\Compiler\CheckTypeDeclarationsPass;
use _ContaoManager\Symfony\Component\DependencyInjection\Compiler\PassConfig;
use _ContaoManager\Symfony\Component\DependencyInjection\Compiler\ResolveFactoryClassPass;
use _ContaoManager\Symfony\Component\DependencyInjection\Container;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerBuilder;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
use _ContaoManager\Symfony\Component\DependencyInjection\Loader\XmlFileLoader;
use _ContaoManager\Symfony\Component\DependencyInjection\ParameterBag\EnvPlaceholderParameterBag;
use _ContaoManager\Symfony\Component\HttpKernel\Kernel;
#[AsCommand(name: 'lint:container', description: 'Ensure that arguments injected into services match type declarations')]
final class ContainerLintCommand extends Command
{
    private ContainerBuilder $container;
    protected function configure(): void
    {
        $this->setHelp('This command parses service definitions and ensures that injected values match the type declarations of each services\' class.');
    }
    protected function execute(InputInterface $input, OutputInterface $output): int
    {
        $io = new SymfonyStyle($input, $output);
        $errorIo = $io->getErrorStyle();
        try {
            $container = $this->getContainerBuilder();
        } catch (RuntimeException $e) {
            $errorIo->error($e->getMessage());
            return 2;
        }
        $container->setParameter('container.build_time', time());
        try {
            $container->compile();
        } catch (InvalidArgumentException $e) {
            $errorIo->error($e->getMessage());
            return 1;
        }
        $io->success('The container was linted successfully: all services are injected with values that are compatible with their type declarations.');
        return 0;
    }
    private function getContainerBuilder(): ContainerBuilder
    {
        if (isset($this->container)) {
            return $this->container;
        }
        $kernel = $this->getApplication()->getKernel();
        $kernelContainer = $kernel->getContainer();
        if (!$kernel->isDebug() || !$kernelContainer->getParameter('debug.container.dump') || !(new ConfigCache($kernelContainer->getParameter('debug.container.dump'), \true))->isFresh()) {
            if (!$kernel instanceof Kernel) {
                throw new RuntimeException(\sprintf('This command does not support the application kernel: "%s" does not extend "%s".', get_debug_type($kernel), Kernel::class));
            }
            $buildContainer = \Closure::bind(function (): ContainerBuilder {
                $this->initializeBundles();
                return $this->buildContainer();
            }, $kernel, $kernel::class);
            $container = $buildContainer();
        } else {
            if (!$kernelContainer instanceof Container) {
                throw new RuntimeException(\sprintf('This command does not support the application container: "%s" does not extend "%s".', get_debug_type($kernelContainer), Container::class));
            }
            (new XmlFileLoader($container = new ContainerBuilder($parameterBag = new EnvPlaceholderParameterBag()), new FileLocator()))->load($kernelContainer->getParameter('debug.container.dump'));
            $refl = new \ReflectionProperty($parameterBag, 'resolved');
            $refl->setValue($parameterBag, \true);
            $container->getCompilerPassConfig()->setBeforeOptimizationPasses([]);
            $container->getCompilerPassConfig()->setOptimizationPasses([new ResolveFactoryClassPass()]);
            $container->getCompilerPassConfig()->setBeforeRemovingPasses([]);
        }
        $container->setParameter('container.build_hash', 'lint_container');
        $container->setParameter('container.build_id', 'lint_container');
        $container->addCompilerPass(new CheckTypeDeclarationsPass(\true), PassConfig::TYPE_AFTER_REMOVING, -100);
        return $this->container = $container;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Bundle\FrameworkBundle\Command;

use _ContaoManager\Symfony\Bundle\FrameworkBundle\Secrets\AbstractVault;
use _ContaoManager\Symfony\Component\Console\Attribute\AsCommand;
use _ContaoManager\Symfony\Component\Console\Command\Command;
use _ContaoManager\Symfony\Component\Console\Input\InputInterface;
use _ContaoManager\Symfony\Component\Console\Output\ConsoleOutputInterface;
use _ContaoManager\Symfony\Component\Console\Output\OutputInterface;
use _ContaoManager\Symfony\Component\Console\Style\SymfonyStyle;
/**
 * @author Nicolas Grekas <p@tchwork.com>
 *
 * @internal
 */
#[AsCommand(name: 'secrets:encrypt-from-local', description: 'Encrypt all local secrets to the vault')]
final class SecretsEncryptFromLocalCommand extends Command
{
    private AbstractVault $vault;
    private ?AbstractVault $localVault;
    public function __construct(AbstractVault $vault, ?AbstractVault $localVault = null)
    {
        $this->vault = $vault;
        $this->localVault = $localVault;
        parent::__construct();
    }
    protected function configure(): void
    {
        $this->setHelp(<<<'EOF'
The <info>%command.name%</info> command encrypts all locally overridden secrets to the vault.

    <info>%command.full_name%</info>
EOF
);
    }
    protected function execute(InputInterface $input, OutputInterface $output): int
    {
        $io = new SymfonyStyle($input, $output instanceof ConsoleOutputInterface ? $output->getErrorOutput() : $output);
        if (null === $this->localVault) {
            $io->error('The local vault is disabled.');
            return 1;
        }
        foreach ($this->vault->list(\true) as $name => $value) {
            if (null === $localValue = $this->localVault->reveal($name)) {
                continue;
            }
            if ($value !== $localValue) {
                $this->vault->seal($name, $localValue);
                $io->note($this->vault->getLastMessage());
            }
        }
        return 0;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Bundle\FrameworkBundle\Command;

use _ContaoManager\Symfony\Bundle\FrameworkBundle\Console\Descriptor\Descriptor;
use _ContaoManager\Symfony\Component\Console\Attribute\AsCommand;
use _ContaoManager\Symfony\Component\Console\Completion\CompletionInput;
use _ContaoManager\Symfony\Component\Console\Completion\CompletionSuggestions;
use _ContaoManager\Symfony\Component\Console\Input\InputArgument;
use _ContaoManager\Symfony\Component\Console\Input\InputInterface;
use _ContaoManager\Symfony\Component\Console\Input\InputOption;
use _ContaoManager\Symfony\Component\Console\Output\OutputInterface;
use _ContaoManager\Symfony\Component\Console\Style\SymfonyStyle;
use _ContaoManager\Symfony\Component\DependencyInjection\Attribute\Target;
use _ContaoManager\Symfony\Component\ErrorHandler\ErrorRenderer\FileLinkFormatter;
/**
 * A console command for autowiring information.
 *
 * @author Ryan Weaver <ryan@knpuniversity.com>
 *
 * @internal
 */
#[AsCommand(name: 'debug:autowiring', description: 'List classes/interfaces you can use for autowiring')]
class DebugAutowiringCommand extends ContainerDebugCommand
{
    private ?FileLinkFormatter $fileLinkFormatter;
    public function __construct(?string $name = null, ?FileLinkFormatter $fileLinkFormatter = null)
    {
        $this->fileLinkFormatter = $fileLinkFormatter;
        parent::__construct($name);
    }
    protected function configure(): void
    {
        $this->setDefinition([new InputArgument('search', InputArgument::OPTIONAL, 'A search filter'), new InputOption('all', null, InputOption::VALUE_NONE, 'Show also services that are not aliased')])->setHelp(<<<'EOF'
The <info>%command.name%</info> command displays the classes and interfaces that
you can use as type-hints for autowiring:

  <info>php %command.full_name%</info>

You can also pass a search term to filter the list:

  <info>php %command.full_name% log</info>

EOF
);
    }
    protected function execute(InputInterface $input, OutputInterface $output): int
    {
        $io = new SymfonyStyle($input, $output);
        $errorIo = $io->getErrorStyle();
        $container = $this->getContainerBuilder($this->getApplication()->getKernel());
        $serviceIds = $container->getServiceIds();
        $serviceIds = array_filter($serviceIds, $this->filterToServiceTypes(...));
        if ($search = $input->getArgument('search')) {
            $searchNormalized = preg_replace('/[^a-zA-Z0-9\x7f-\xff $]++/', '', $search);
            $serviceIds = array_filter($serviceIds, fn($serviceId) => \false !== stripos(str_replace('\\', '', $serviceId), $searchNormalized) && !str_starts_with($serviceId, '.'));
            if (!$serviceIds) {
                $errorIo->error(\sprintf('No autowirable classes or interfaces found matching "%s"', $search));
                return 1;
            }
        }
        $reverseAliases = [];
        foreach ($container->getAliases() as $id => $alias) {
            if ('.' === ($id[0] ?? null)) {
                $reverseAliases[(string) $alias][] = $id;
            }
        }
        uasort($serviceIds, 'strnatcmp');
        $io->title('Autowirable Types');
        $io->text('The following classes & interfaces can be used as type-hints when autowiring:');
        if ($search) {
            $io->text(\sprintf('(only showing classes/interfaces matching <comment>%s</comment>)', $search));
        }
        $hasAlias = [];
        $all = $input->getOption('all');
        $previousId = '-';
        $serviceIdsNb = 0;
        foreach ($serviceIds as $serviceId) {
            if ($container->hasDefinition($serviceId) && $container->getDefinition($serviceId)->hasTag('container.excluded')) {
                continue;
            }
            $text = [];
            $resolvedServiceId = $serviceId;
            if (!str_starts_with($serviceId, $previousId . ' $')) {
                $text[] = '';
                $previousId = preg_replace('/ \$.*/', '', $serviceId);
                if ('' !== $description = Descriptor::getClassDescription($previousId, $resolvedServiceId)) {
                    if (isset($hasAlias[$previousId])) {
                        continue;
                    }
                    $text[] = $description;
                }
            }
            $serviceLine = \sprintf('<fg=yellow>%s</>', $serviceId);
            if ('' !== $fileLink = $this->getFileLink($previousId)) {
                $serviceLine = substr($serviceId, \strlen($previousId));
                $serviceLine = \sprintf('<fg=yellow;href=%s>%s</>', $fileLink, $previousId) . ('' !== $serviceLine ? \sprintf('<fg=yellow>%s</>', $serviceLine) : '');
            }
            if ($container->hasAlias($serviceId)) {
                $hasAlias[$serviceId] = \true;
                $serviceAlias = $container->getAlias($serviceId);
                $alias = (string) $serviceAlias;
                $target = null;
                foreach ($reverseAliases[(string) $serviceAlias] ?? [] as $id) {
                    if (!str_starts_with($id, '.' . $previousId . ' $')) {
                        continue;
                    }
                    $target = substr($id, \strlen($previousId) + 3);
                    if ($previousId . ' $' . (new Target($target))->getParsedName() === $serviceId) {
                        $serviceLine .= ' - <fg=magenta>target:</><fg=cyan>' . $target . '</>';
                        break;
                    }
                }
                if ($container->hasDefinition($serviceAlias) && $decorated = $container->getDefinition($serviceAlias)->getTag('container.decorator')) {
                    $alias = $decorated[0]['id'];
                }
                if ($alias !== $target) {
                    $serviceLine .= ' - <fg=magenta>alias:</><fg=cyan>' . $alias . '</>';
                }
                if ($serviceAlias->isDeprecated()) {
                    $serviceLine .= ' - <fg=magenta>deprecated</>';
                }
            } elseif (!$all) {
                ++$serviceIdsNb;
                continue;
            } elseif ($container->getDefinition($serviceId)->isDeprecated()) {
                $serviceLine .= ' - <fg=magenta>deprecated</>';
            }
            $text[] = $serviceLine;
            $io->text($text);
        }
        $io->newLine();
        if (0 < $serviceIdsNb) {
            $io->text(\sprintf('%s more concrete service%s would be displayed when adding the "--all" option.', $serviceIdsNb, $serviceIdsNb > 1 ? 's' : ''));
        }
        if ($all) {
            $io->text('Pro-tip: use interfaces in your type-hints instead of classes to benefit from the dependency inversion principle.');
        }
        $io->newLine();
        return 0;
    }
    private function getFileLink(string $class): string
    {
        if (null === $this->fileLinkFormatter || null === $r = $this->getContainerBuilder($this->getApplication()->getKernel())->getReflectionClass($class, \false)) {
            return '';
        }
        return (string) $this->fileLinkFormatter->format($r->getFileName(), $r->getStartLine());
    }
    public function complete(CompletionInput $input, CompletionSuggestions $suggestions): void
    {
        if ($input->mustSuggestArgumentValuesFor('search')) {
            $container = $this->getContainerBuilder($this->getApplication()->getKernel());
            $suggestions->suggestValues(array_filter($container->getServiceIds(), $this->filterToServiceTypes(...)));
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Bundle\FrameworkBundle\Command;

use _ContaoManager\Symfony\Component\Console\Attribute\AsCommand;
use _ContaoManager\Symfony\Component\Console\Command\Command;
use _ContaoManager\Symfony\Component\Console\Input\InputInterface;
use _ContaoManager\Symfony\Component\Console\Input\InputOption;
use _ContaoManager\Symfony\Component\Console\Output\OutputInterface;
use _ContaoManager\Symfony\Component\Console\Style\SymfonyStyle;
use _ContaoManager\Symfony\Component\DependencyInjection\Dumper\Preloader;
use _ContaoManager\Symfony\Component\HttpKernel\CacheWarmer\CacheWarmerAggregate;
use _ContaoManager\Symfony\Component\HttpKernel\CacheWarmer\WarmableInterface;
/**
 * Warmup the cache.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 *
 * @final
 */
#[AsCommand(name: 'cache:warmup', description: 'Warm up an empty cache')]
class CacheWarmupCommand extends Command
{
    private CacheWarmerAggregate $cacheWarmer;
    public function __construct(CacheWarmerAggregate $cacheWarmer)
    {
        parent::__construct();
        $this->cacheWarmer = $cacheWarmer;
    }
    protected function configure(): void
    {
        $this->setDefinition([new InputOption('no-optional-warmers', '', InputOption::VALUE_NONE, 'Skip optional cache warmers (faster)')])->setHelp(<<<'EOF'
The <info>%command.name%</info> command warms up the cache.

Before running this command, the cache must be empty.

EOF
);
    }
    protected function execute(InputInterface $input, OutputInterface $output): int
    {
        $io = new SymfonyStyle($input, $output);
        $kernel = $this->getApplication()->getKernel();
        $io->comment(\sprintf('Warming up the cache for the <info>%s</info> environment with debug <info>%s</info>', $kernel->getEnvironment(), var_export($kernel->isDebug(), \true)));
        if (!$input->getOption('no-optional-warmers')) {
            $this->cacheWarmer->enableOptionalWarmers();
        }
        $cacheDir = $kernel->getContainer()->getParameter('kernel.cache_dir');
        if ($kernel instanceof WarmableInterface) {
            $kernel->warmUp($cacheDir);
        }
        $buildDir = $kernel->getContainer()->getParameter('kernel.build_dir');
        $preload = $this->cacheWarmer->warmUp($cacheDir, $buildDir);
        if ($preload && $cacheDir === $buildDir && file_exists($preloadFile = $buildDir . '/' . $kernel->getContainer()->getParameter('kernel.container_class') . '.preload.php')) {
            Preloader::append($preloadFile, $preload);
        }
        $io->success(\sprintf('Cache for the "%s" environment (debug=%s) was successfully warmed.', $kernel->getEnvironment(), var_export($kernel->isDebug(), \true)));
        return 0;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Bundle\FrameworkBundle\Command;

use _ContaoManager\Symfony\Component\Console\Attribute\AsCommand;
use _ContaoManager\Symfony\Component\Console\Command\Command;
use _ContaoManager\Symfony\Component\Console\Completion\CompletionInput;
use _ContaoManager\Symfony\Component\Console\Completion\CompletionSuggestions;
use _ContaoManager\Symfony\Component\Console\Exception\InvalidArgumentException;
use _ContaoManager\Symfony\Component\Console\Input\InputArgument;
use _ContaoManager\Symfony\Component\Console\Input\InputInterface;
use _ContaoManager\Symfony\Component\Console\Input\InputOption;
use _ContaoManager\Symfony\Component\Console\Output\OutputInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\ServiceLocator;
use _ContaoManager\Symfony\Component\Workflow\Definition;
use _ContaoManager\Symfony\Component\Workflow\Dumper\GraphvizDumper;
use _ContaoManager\Symfony\Component\Workflow\Dumper\MermaidDumper;
use _ContaoManager\Symfony\Component\Workflow\Dumper\PlantUmlDumper;
use _ContaoManager\Symfony\Component\Workflow\Dumper\StateMachineGraphvizDumper;
use _ContaoManager\Symfony\Component\Workflow\Marking;
use _ContaoManager\Symfony\Component\Workflow\StateMachine;
/**
 * @author Grégoire Pineau <lyrixx@lyrixx.info>
 *
 * @final
 */
#[AsCommand(name: 'workflow:dump', description: 'Dump a workflow')]
class WorkflowDumpCommand extends Command
{
    /**
     * string is the service id.
     *
     * @var array<string, Definition>
     */
    private array $definitions = [];
    private ServiceLocator $workflows;
    private const DUMP_FORMAT_OPTIONS = ['puml', 'mermaid', 'dot'];
    public function __construct($workflows)
    {
        parent::__construct();
        if ($workflows instanceof ServiceLocator) {
            $this->workflows = $workflows;
        } elseif (\is_array($workflows)) {
            $this->definitions = $workflows;
            trigger_deprecation('symfony/framework-bundle', '6.2', 'Passing an array of definitions in "%s()" is deprecated. Inject a ServiceLocator filled with all workflows instead.', __METHOD__);
        } else {
            throw new \TypeError(\sprintf('Argument 1 passed to "%s()" must be an array or a ServiceLocator, "%s" given.', __METHOD__, \gettype($workflows)));
        }
    }
    protected function configure(): void
    {
        $this->setDefinition([new InputArgument('name', InputArgument::REQUIRED, 'A workflow name'), new InputArgument('marking', InputArgument::IS_ARRAY, 'A marking (a list of places)'), new InputOption('label', 'l', InputOption::VALUE_REQUIRED, 'Label a graph'), new InputOption('with-metadata', null, InputOption::VALUE_NONE, 'Include the workflow\'s metadata in the dumped graph', null), new InputOption('dump-format', null, InputOption::VALUE_REQUIRED, 'The dump format [' . implode('|', self::DUMP_FORMAT_OPTIONS) . ']', 'dot')])->setHelp(<<<'EOF'
The <info>%command.name%</info> command dumps the graphical representation of a
workflow in different formats

<info>DOT</info>:  %command.full_name% <workflow name> | dot -Tpng > workflow.png
<info>PUML</info>: %command.full_name% <workflow name> --dump-format=puml | java -jar plantuml.jar -p > workflow.png
<info>MERMAID</info>: %command.full_name% <workflow name> --dump-format=mermaid | mmdc -o workflow.svg
EOF
);
    }
    protected function execute(InputInterface $input, OutputInterface $output): int
    {
        $workflowName = $input->getArgument('name');
        if (isset($this->workflows)) {
            if (!$this->workflows->has($workflowName)) {
                throw new InvalidArgumentException(\sprintf('The workflow named "%s" cannot be found.', $workflowName));
            }
            $workflow = $this->workflows->get($workflowName);
            $type = $workflow instanceof StateMachine ? 'state_machine' : 'workflow';
            $definition = $workflow->getDefinition();
        } elseif (isset($this->definitions['workflow.' . $workflowName])) {
            $definition = $this->definitions['workflow.' . $workflowName];
            $type = 'workflow';
        } elseif (isset($this->definitions['state_machine.' . $workflowName])) {
            $definition = $this->definitions['state_machine.' . $workflowName];
            $type = 'state_machine';
        }
        if (null === $definition) {
            throw new InvalidArgumentException(\sprintf('No service found for "workflow.%1$s" nor "state_machine.%1$s".', $workflowName));
        }
        switch ($input->getOption('dump-format')) {
            case 'puml':
                $transitionType = 'workflow' === $type ? PlantUmlDumper::WORKFLOW_TRANSITION : PlantUmlDumper::STATEMACHINE_TRANSITION;
                $dumper = new PlantUmlDumper($transitionType);
                break;
            case 'mermaid':
                $transitionType = 'workflow' === $type ? MermaidDumper::TRANSITION_TYPE_WORKFLOW : MermaidDumper::TRANSITION_TYPE_STATEMACHINE;
                $dumper = new MermaidDumper($transitionType);
                break;
            case 'dot':
            default:
                $dumper = 'workflow' === $type ? new GraphvizDumper() : new StateMachineGraphvizDumper();
        }
        $marking = new Marking();
        foreach ($input->getArgument('marking') as $place) {
            $marking->mark($place);
        }
        $options = ['name' => $workflowName, 'with-metadata' => $input->getOption('with-metadata'), 'nofooter' => \true, 'label' => $input->getOption('label')];
        $output->writeln($dumper->dump($definition, $marking, $options));
        return 0;
    }
    public function complete(CompletionInput $input, CompletionSuggestions $suggestions): void
    {
        if ($input->mustSuggestArgumentValuesFor('name')) {
            if (isset($this->workflows)) {
                $suggestions->suggestValues(array_keys($this->workflows->getProvidedServices()));
            } else {
                $suggestions->suggestValues(array_keys($this->definitions));
            }
        }
        if ($input->mustSuggestOptionValuesFor('dump-format')) {
            $suggestions->suggestValues(self::DUMP_FORMAT_OPTIONS);
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Bundle\FrameworkBundle\Command;

use _ContaoManager\Psr\Container\ContainerInterface;
use _ContaoManager\Symfony\Bundle\FrameworkBundle\Console\Helper\DescriptorHelper;
use _ContaoManager\Symfony\Component\Console\Attribute\AsCommand;
use _ContaoManager\Symfony\Component\Console\Command\Command;
use _ContaoManager\Symfony\Component\Console\Completion\CompletionInput;
use _ContaoManager\Symfony\Component\Console\Completion\CompletionSuggestions;
use _ContaoManager\Symfony\Component\Console\Input\InputArgument;
use _ContaoManager\Symfony\Component\Console\Input\InputInterface;
use _ContaoManager\Symfony\Component\Console\Input\InputOption;
use _ContaoManager\Symfony\Component\Console\Output\OutputInterface;
use _ContaoManager\Symfony\Component\Console\Style\SymfonyStyle;
use _ContaoManager\Symfony\Component\EventDispatcher\EventDispatcherInterface;
use _ContaoManager\Symfony\Contracts\Service\ServiceProviderInterface;
/**
 * A console command for retrieving information about event dispatcher.
 *
 * @author Matthieu Auger <mail@matthieuauger.com>
 *
 * @final
 */
#[AsCommand(name: 'debug:event-dispatcher', description: 'Display configured listeners for an application')]
class EventDispatcherDebugCommand extends Command
{
    private const DEFAULT_DISPATCHER = 'event_dispatcher';
    private ContainerInterface $dispatchers;
    public function __construct(ContainerInterface $dispatchers)
    {
        parent::__construct();
        $this->dispatchers = $dispatchers;
    }
    protected function configure(): void
    {
        $this->setDefinition([new InputArgument('event', InputArgument::OPTIONAL, 'An event name or a part of the event name'), new InputOption('dispatcher', null, InputOption::VALUE_REQUIRED, 'To view events of a specific event dispatcher', self::DEFAULT_DISPATCHER), new InputOption('format', null, InputOption::VALUE_REQUIRED, \sprintf('The output format ("%s")', implode('", "', $this->getAvailableFormatOptions())), 'txt'), new InputOption('raw', null, InputOption::VALUE_NONE, 'To output raw description')])->setHelp(<<<'EOF'
The <info>%command.name%</info> command displays all configured listeners:

  <info>php %command.full_name%</info>

To get specific listeners for an event, specify its name:

  <info>php %command.full_name% kernel.request</info>
EOF
);
    }
    /**
     * @throws \LogicException
     */
    protected function execute(InputInterface $input, OutputInterface $output): int
    {
        $io = new SymfonyStyle($input, $output);
        $options = [];
        $dispatcherServiceName = $input->getOption('dispatcher');
        if (!$this->dispatchers->has($dispatcherServiceName)) {
            $io->getErrorStyle()->error(\sprintf('Event dispatcher "%s" is not available.', $dispatcherServiceName));
            return 1;
        }
        $dispatcher = $this->dispatchers->get($dispatcherServiceName);
        if ($event = $input->getArgument('event')) {
            if ($dispatcher->hasListeners($event)) {
                $options = ['event' => $event];
            } else {
                // if there is no direct match, try find partial matches
                $events = $this->searchForEvent($dispatcher, $event);
                if (0 === \count($events)) {
                    $io->getErrorStyle()->warning(\sprintf('The event "%s" does not have any registered listeners.', $event));
                    return 0;
                } elseif (1 === \count($events)) {
                    $options = ['event' => $events[array_key_first($events)]];
                } else {
                    $options = ['events' => $events];
                }
            }
        }
        $helper = new DescriptorHelper();
        if (self::DEFAULT_DISPATCHER !== $dispatcherServiceName) {
            $options['dispatcher_service_name'] = $dispatcherServiceName;
        }
        $options['format'] = $input->getOption('format');
        $options['raw_text'] = $input->getOption('raw');
        $options['output'] = $io;
        $helper->describe($io, $dispatcher, $options);
        return 0;
    }
    public function complete(CompletionInput $input, CompletionSuggestions $suggestions): void
    {
        if ($input->mustSuggestArgumentValuesFor('event')) {
            $dispatcherServiceName = $input->getOption('dispatcher');
            if ($this->dispatchers->has($dispatcherServiceName)) {
                $dispatcher = $this->dispatchers->get($dispatcherServiceName);
                $suggestions->suggestValues(array_keys($dispatcher->getListeners()));
            }
            return;
        }
        if ($input->mustSuggestOptionValuesFor('dispatcher')) {
            if ($this->dispatchers instanceof ServiceProviderInterface) {
                $suggestions->suggestValues(array_keys($this->dispatchers->getProvidedServices()));
            }
            return;
        }
        if ($input->mustSuggestOptionValuesFor('format')) {
            $suggestions->suggestValues($this->getAvailableFormatOptions());
        }
    }
    private function searchForEvent(EventDispatcherInterface $dispatcher, string $needle): array
    {
        $output = [];
        $lcNeedle = strtolower($needle);
        $allEvents = array_keys($dispatcher->getListeners());
        foreach ($allEvents as $event) {
            if (str_contains(strtolower($event), $lcNeedle)) {
                $output[] = $event;
            }
        }
        return $output;
    }
    private function getAvailableFormatOptions(): array
    {
        return (new DescriptorHelper())->getFormats();
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Bundle\FrameworkBundle\Command;

use _ContaoManager\Symfony\Bundle\FrameworkBundle\Console\Helper\DescriptorHelper;
use _ContaoManager\Symfony\Component\Console\Attribute\AsCommand;
use _ContaoManager\Symfony\Component\Console\Command\Command;
use _ContaoManager\Symfony\Component\Console\Completion\CompletionInput;
use _ContaoManager\Symfony\Component\Console\Completion\CompletionSuggestions;
use _ContaoManager\Symfony\Component\Console\Exception\InvalidArgumentException;
use _ContaoManager\Symfony\Component\Console\Input\InputArgument;
use _ContaoManager\Symfony\Component\Console\Input\InputInterface;
use _ContaoManager\Symfony\Component\Console\Input\InputOption;
use _ContaoManager\Symfony\Component\Console\Output\OutputInterface;
use _ContaoManager\Symfony\Component\Console\Style\SymfonyStyle;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerBuilder;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException;
use _ContaoManager\Symfony\Component\DependencyInjection\ParameterBag\ParameterBag;
/**
 * A console command for retrieving information about services.
 *
 * @author Ryan Weaver <ryan@thatsquality.com>
 *
 * @internal
 */
#[AsCommand(name: 'debug:container', description: 'Display current services for an application')]
class ContainerDebugCommand extends Command
{
    use BuildDebugContainerTrait;
    protected function configure(): void
    {
        $this->setDefinition([new InputArgument('name', InputArgument::OPTIONAL, 'A service name (foo)'), new InputOption('show-arguments', null, InputOption::VALUE_NONE, 'Show arguments in services'), new InputOption('show-hidden', null, InputOption::VALUE_NONE, 'Show hidden (internal) services'), new InputOption('tag', null, InputOption::VALUE_REQUIRED, 'Show all services with a specific tag'), new InputOption('tags', null, InputOption::VALUE_NONE, 'Display tagged services for an application'), new InputOption('parameter', null, InputOption::VALUE_REQUIRED, 'Display a specific parameter for an application'), new InputOption('parameters', null, InputOption::VALUE_NONE, 'Display parameters for an application'), new InputOption('types', null, InputOption::VALUE_NONE, 'Display types (classes/interfaces) available in the container'), new InputOption('env-var', null, InputOption::VALUE_REQUIRED, 'Display a specific environment variable used in the container'), new InputOption('env-vars', null, InputOption::VALUE_NONE, 'Display environment variables used in the container'), new InputOption('format', null, InputOption::VALUE_REQUIRED, \sprintf('The output format ("%s")', implode('", "', $this->getAvailableFormatOptions())), 'txt'), new InputOption('raw', null, InputOption::VALUE_NONE, 'To output raw description'), new InputOption('deprecations', null, InputOption::VALUE_NONE, 'Display deprecations generated when compiling and warming up the container')])->setHelp(<<<'EOF'
The <info>%command.name%</info> command displays all configured <comment>public</comment> services:

  <info>php %command.full_name%</info>

To see deprecations generated during container compilation and cache warmup, use the <info>--deprecations</info> option:

  <info>php %command.full_name% --deprecations</info>

To get specific information about a service, specify its name:

  <info>php %command.full_name% validator</info>

To get specific information about a service including all its arguments, use the <info>--show-arguments</info> flag:

  <info>php %command.full_name% validator --show-arguments</info>

To see available types that can be used for autowiring, use the <info>--types</info> flag:

  <info>php %command.full_name% --types</info>

To see environment variables used by the container, use the <info>--env-vars</info> flag:

  <info>php %command.full_name% --env-vars</info>

Display a specific environment variable by specifying its name with the <info>--env-var</info> option:

  <info>php %command.full_name% --env-var=APP_ENV</info>

Use the --tags option to display tagged <comment>public</comment> services grouped by tag:

  <info>php %command.full_name% --tags</info>

Find all services with a specific tag by specifying the tag name with the <info>--tag</info> option:

  <info>php %command.full_name% --tag=form.type</info>

Use the <info>--parameters</info> option to display all parameters:

  <info>php %command.full_name% --parameters</info>

Display a specific parameter by specifying its name with the <info>--parameter</info> option:

  <info>php %command.full_name% --parameter=kernel.debug</info>

By default, internal services are hidden. You can display them
using the <info>--show-hidden</info> flag:

  <info>php %command.full_name% --show-hidden</info>

EOF
);
    }
    protected function execute(InputInterface $input, OutputInterface $output): int
    {
        $io = new SymfonyStyle($input, $output);
        $errorIo = $io->getErrorStyle();
        $this->validateInput($input);
        $kernel = $this->getApplication()->getKernel();
        $object = $this->getContainerBuilder($kernel);
        if ($input->getOption('env-vars')) {
            $options = ['env-vars' => \true];
        } elseif ($envVar = $input->getOption('env-var')) {
            $options = ['env-vars' => \true, 'name' => $envVar];
        } elseif ($input->getOption('types')) {
            $options = [];
            $options['filter'] = $this->filterToServiceTypes(...);
        } elseif ($input->getOption('parameters')) {
            $parameters = [];
            $parameterBag = $object->getParameterBag();
            foreach ($parameterBag->all() as $k => $v) {
                $parameters[$k] = $object->resolveEnvPlaceholders($v);
            }
            $object = new ParameterBag($parameters);
            if ($parameterBag instanceof ParameterBag) {
                foreach ($parameterBag->allDeprecated() as $k => $deprecation) {
                    $object->deprecate($k, ...$deprecation);
                }
            }
            $options = [];
        } elseif ($parameter = $input->getOption('parameter')) {
            $options = ['parameter' => $parameter];
        } elseif ($input->getOption('tags')) {
            $options = ['group_by' => 'tags'];
        } elseif ($tag = $input->getOption('tag')) {
            $tag = $this->findProperTagName($input, $errorIo, $object, $tag);
            $options = ['tag' => $tag];
        } elseif ($name = $input->getArgument('name')) {
            $name = $this->findProperServiceName($input, $errorIo, $object, $name, $input->getOption('show-hidden'));
            $options = ['id' => $name];
        } elseif ($input->getOption('deprecations')) {
            $options = ['deprecations' => \true];
        } else {
            $options = [];
        }
        $helper = new DescriptorHelper();
        $options['format'] = $input->getOption('format');
        $options['show_arguments'] = $input->getOption('show-arguments');
        $options['show_hidden'] = $input->getOption('show-hidden');
        $options['raw_text'] = $input->getOption('raw');
        $options['output'] = $io;
        $options['is_debug'] = $kernel->isDebug();
        try {
            $helper->describe($io, $object, $options);
            if ('txt' === $options['format'] && isset($options['id'])) {
                if ($object->hasDefinition($options['id'])) {
                    $definition = $object->getDefinition($options['id']);
                    if ($definition->isDeprecated()) {
                        $errorIo->warning($definition->getDeprecation($options['id'])['message'] ?? \sprintf('The "%s" service is deprecated.', $options['id']));
                    }
                }
                if ($object->hasAlias($options['id'])) {
                    $alias = $object->getAlias($options['id']);
                    if ($alias->isDeprecated()) {
                        $errorIo->warning($alias->getDeprecation($options['id'])['message'] ?? \sprintf('The "%s" alias is deprecated.', $options['id']));
                    }
                }
            }
            if (isset($options['id']) && isset($kernel->getContainer()->getRemovedIds()[$options['id']])) {
                $errorIo->note(\sprintf('The "%s" service or alias has been removed or inlined when the container was compiled.', $options['id']));
            }
        } catch (ServiceNotFoundException $e) {
            if ('' !== $e->getId() && '@' === $e->getId()[0]) {
                throw new ServiceNotFoundException($e->getId(), $e->getSourceId(), null, [substr($e->getId(), 1)]);
            }
            throw $e;
        }
        if (!$input->getArgument('name') && !$input->getOption('tag') && !$input->getOption('parameter') && !$input->getOption('env-vars') && !$input->getOption('env-var') && $input->isInteractive()) {
            if ($input->getOption('tags')) {
                $errorIo->comment('To search for a specific tag, re-run this command with a search term. (e.g. <comment>debug:container --tag=form.type</comment>)');
            } elseif ($input->getOption('parameters')) {
                $errorIo->comment('To search for a specific parameter, re-run this command with a search term. (e.g. <comment>debug:container --parameter=kernel.debug</comment>)');
            } elseif (!$input->getOption('deprecations')) {
                $errorIo->comment('To search for a specific service, re-run this command with a search term. (e.g. <comment>debug:container log</comment>)');
            }
        }
        return 0;
    }
    public function complete(CompletionInput $input, CompletionSuggestions $suggestions): void
    {
        if ($input->mustSuggestOptionValuesFor('format')) {
            $suggestions->suggestValues($this->getAvailableFormatOptions());
            return;
        }
        $kernel = $this->getApplication()->getKernel();
        $object = $this->getContainerBuilder($kernel);
        if ($input->mustSuggestArgumentValuesFor('name') && !$input->getOption('tag') && !$input->getOption('tags') && !$input->getOption('parameter') && !$input->getOption('parameters') && !$input->getOption('env-var') && !$input->getOption('env-vars') && !$input->getOption('types') && !$input->getOption('deprecations')) {
            $suggestions->suggestValues($this->findServiceIdsContaining($object, $input->getCompletionValue(), (bool) $input->getOption('show-hidden')));
            return;
        }
        if ($input->mustSuggestOptionValuesFor('tag')) {
            $suggestions->suggestValues($object->findTags());
            return;
        }
        if ($input->mustSuggestOptionValuesFor('parameter')) {
            $suggestions->suggestValues(array_keys($object->getParameterBag()->all()));
        }
    }
    /**
     * Validates input arguments and options.
     *
     * @throws \InvalidArgumentException
     */
    protected function validateInput(InputInterface $input): void
    {
        $options = ['tags', 'tag', 'parameters', 'parameter'];
        $optionsCount = 0;
        foreach ($options as $option) {
            if ($input->getOption($option)) {
                ++$optionsCount;
            }
        }
        $name = $input->getArgument('name');
        if (null !== $name && $optionsCount > 0) {
            throw new InvalidArgumentException('The options tags, tag, parameters & parameter cannot be combined with the service name argument.');
        } elseif (null === $name && $optionsCount > 1) {
            throw new InvalidArgumentException('The options tags, tag, parameters & parameter cannot be combined together.');
        }
    }
    private function findProperServiceName(InputInterface $input, SymfonyStyle $io, ContainerBuilder $container, string $name, bool $showHidden): string
    {
        $name = ltrim($name, '\\');
        if ($container->has($name) || !$input->isInteractive()) {
            return $name;
        }
        $matchingServices = $this->findServiceIdsContaining($container, $name, $showHidden);
        if (!$matchingServices) {
            throw new InvalidArgumentException(\sprintf('No services found that match "%s".', $name));
        }
        if (1 === \count($matchingServices)) {
            return $matchingServices[0];
        }
        natsort($matchingServices);
        return $io->choice('Select one of the following services to display its information', array_values($matchingServices));
    }
    private function findProperTagName(InputInterface $input, SymfonyStyle $io, ContainerBuilder $container, string $tagName): string
    {
        if (\in_array($tagName, $container->findTags(), \true) || !$input->isInteractive()) {
            return $tagName;
        }
        $matchingTags = $this->findTagsContaining($container, $tagName);
        if (!$matchingTags) {
            throw new InvalidArgumentException(\sprintf('No tags found that match "%s".', $tagName));
        }
        if (1 === \count($matchingTags)) {
            return $matchingTags[0];
        }
        natsort($matchingTags);
        return $io->choice('Select one of the following tags to display its information', array_values($matchingTags));
    }
    private function findServiceIdsContaining(ContainerBuilder $container, string $name, bool $showHidden): array
    {
        $serviceIds = $container->getServiceIds();
        $foundServiceIds = $foundServiceIdsIgnoringBackslashes = [];
        foreach ($serviceIds as $serviceId) {
            if (!$showHidden && str_starts_with($serviceId, '.')) {
                continue;
            }
            if (!$showHidden && $container->hasDefinition($serviceId) && $container->getDefinition($serviceId)->hasTag('container.excluded')) {
                continue;
            }
            if (\false !== stripos(str_replace('\\', '', $serviceId), $name)) {
                $foundServiceIdsIgnoringBackslashes[] = $serviceId;
            }
            if ('' === $name || \false !== stripos($serviceId, $name)) {
                $foundServiceIds[] = $serviceId;
            }
        }
        return $foundServiceIds ?: $foundServiceIdsIgnoringBackslashes;
    }
    private function findTagsContaining(ContainerBuilder $container, string $tagName): array
    {
        $tags = $container->findTags();
        $foundTags = [];
        foreach ($tags as $tag) {
            if (str_contains($tag, $tagName)) {
                $foundTags[] = $tag;
            }
        }
        return $foundTags;
    }
    /**
     * @internal
     */
    public function filterToServiceTypes(string $serviceId): bool
    {
        // filter out things that could not be valid class names
        if (!preg_match('/(?(DEFINE)(?<V>[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*+))^(?&V)(?:\\\\(?&V))*+(?: \$(?&V))?$/', $serviceId)) {
            return \false;
        }
        // if the id has a \, assume it is a class
        if (str_contains($serviceId, '\\')) {
            return \true;
        }
        return class_exists($serviceId) || interface_exists($serviceId, \false);
    }
    private function getAvailableFormatOptions(): array
    {
        return (new DescriptorHelper())->getFormats();
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Bundle\FrameworkBundle\Command;

use _ContaoManager\Symfony\Component\Console\Attribute\AsCommand;
use _ContaoManager\Symfony\Component\Console\Command\Command;
use _ContaoManager\Symfony\Component\Console\Completion\CompletionInput;
use _ContaoManager\Symfony\Component\Console\Completion\CompletionSuggestions;
use _ContaoManager\Symfony\Component\Console\Exception\InvalidArgumentException;
use _ContaoManager\Symfony\Component\Console\Input\InputArgument;
use _ContaoManager\Symfony\Component\Console\Input\InputInterface;
use _ContaoManager\Symfony\Component\Console\Input\InputOption;
use _ContaoManager\Symfony\Component\Console\Output\OutputInterface;
use _ContaoManager\Symfony\Component\Console\Style\SymfonyStyle;
use _ContaoManager\Symfony\Component\HttpKernel\KernelInterface;
use _ContaoManager\Symfony\Component\Translation\Catalogue\MergeOperation;
use _ContaoManager\Symfony\Component\Translation\DataCollectorTranslator;
use _ContaoManager\Symfony\Component\Translation\Extractor\ExtractorInterface;
use _ContaoManager\Symfony\Component\Translation\LoggingTranslator;
use _ContaoManager\Symfony\Component\Translation\MessageCatalogue;
use _ContaoManager\Symfony\Component\Translation\Reader\TranslationReaderInterface;
use _ContaoManager\Symfony\Component\Translation\Translator;
use _ContaoManager\Symfony\Contracts\Translation\TranslatorInterface;
/**
 * Helps finding unused or missing translation messages in a given locale
 * and comparing them with the fallback ones.
 *
 * @author Florian Voutzinos <florian@voutzinos.com>
 *
 * @final
 */
#[AsCommand(name: 'debug:translation', description: 'Display translation messages information')]
class TranslationDebugCommand extends Command
{
    public const EXIT_CODE_GENERAL_ERROR = 64;
    public const EXIT_CODE_MISSING = 65;
    public const EXIT_CODE_UNUSED = 66;
    public const EXIT_CODE_FALLBACK = 68;
    public const MESSAGE_MISSING = 0;
    public const MESSAGE_UNUSED = 1;
    public const MESSAGE_EQUALS_FALLBACK = 2;
    private TranslatorInterface $translator;
    private TranslationReaderInterface $reader;
    private ExtractorInterface $extractor;
    private ?string $defaultTransPath;
    private ?string $defaultViewsPath;
    private array $transPaths;
    private array $codePaths;
    private array $enabledLocales;
    public function __construct(TranslatorInterface $translator, TranslationReaderInterface $reader, ExtractorInterface $extractor, ?string $defaultTransPath = null, ?string $defaultViewsPath = null, array $transPaths = [], array $codePaths = [], array $enabledLocales = [])
    {
        parent::__construct();
        $this->translator = $translator;
        $this->reader = $reader;
        $this->extractor = $extractor;
        $this->defaultTransPath = $defaultTransPath;
        $this->defaultViewsPath = $defaultViewsPath;
        $this->transPaths = $transPaths;
        $this->codePaths = $codePaths;
        $this->enabledLocales = $enabledLocales;
    }
    protected function configure(): void
    {
        $this->setDefinition([new InputArgument('locale', InputArgument::REQUIRED, 'The locale'), new InputArgument('bundle', InputArgument::OPTIONAL, 'The bundle name or directory where to load the messages'), new InputOption('domain', null, InputOption::VALUE_REQUIRED, 'The messages domain'), new InputOption('only-missing', null, InputOption::VALUE_NONE, 'Display only missing messages'), new InputOption('only-unused', null, InputOption::VALUE_NONE, 'Display only unused messages'), new InputOption('all', null, InputOption::VALUE_NONE, 'Load messages from all registered bundles')])->setHelp(<<<'EOF'
The <info>%command.name%</info> command helps finding unused or missing translation
messages and comparing them with the fallback ones by inspecting the
templates and translation files of a given bundle or the default translations directory.

You can display information about bundle translations in a specific locale:

  <info>php %command.full_name% en AcmeDemoBundle</info>

You can also specify a translation domain for the search:

  <info>php %command.full_name% --domain=messages en AcmeDemoBundle</info>

You can only display missing messages:

  <info>php %command.full_name% --only-missing en AcmeDemoBundle</info>

You can only display unused messages:

  <info>php %command.full_name% --only-unused en AcmeDemoBundle</info>

You can display information about application translations in a specific locale:

  <info>php %command.full_name% en</info>

You can display information about translations in all registered bundles in a specific locale:

  <info>php %command.full_name% --all en</info>

EOF
);
    }
    protected function execute(InputInterface $input, OutputInterface $output): int
    {
        $io = new SymfonyStyle($input, $output);
        $locale = $input->getArgument('locale');
        $domain = $input->getOption('domain');
        $exitCode = self::SUCCESS;
        /** @var KernelInterface $kernel */
        $kernel = $this->getApplication()->getKernel();
        // Define Root Paths
        $transPaths = $this->getRootTransPaths();
        $codePaths = $this->getRootCodePaths($kernel);
        // Override with provided Bundle info
        if (null !== $input->getArgument('bundle')) {
            try {
                $bundle = $kernel->getBundle($input->getArgument('bundle'));
                $bundleDir = $bundle->getPath();
                $transPaths = [is_dir($bundleDir . '/Resources/translations') ? $bundleDir . '/Resources/translations' : $bundleDir . '/translations'];
                $codePaths = [is_dir($bundleDir . '/Resources/views') ? $bundleDir . '/Resources/views' : $bundleDir . '/templates'];
                if ($this->defaultTransPath) {
                    $transPaths[] = $this->defaultTransPath;
                }
                if ($this->defaultViewsPath) {
                    $codePaths[] = $this->defaultViewsPath;
                }
            } catch (\InvalidArgumentException) {
                // such a bundle does not exist, so treat the argument as path
                $path = $input->getArgument('bundle');
                $transPaths = [$path . '/translations'];
                $codePaths = [$path . '/templates'];
                if (!is_dir($transPaths[0])) {
                    throw new InvalidArgumentException(\sprintf('"%s" is neither an enabled bundle nor a directory.', $transPaths[0]));
                }
            }
        } elseif ($input->getOption('all')) {
            foreach ($kernel->getBundles() as $bundle) {
                $bundleDir = $bundle->getPath();
                $transPaths[] = is_dir($bundleDir . '/Resources/translations') ? $bundleDir . '/Resources/translations' : $bundle->getPath() . '/translations';
                $codePaths[] = is_dir($bundleDir . '/Resources/views') ? $bundleDir . '/Resources/views' : $bundle->getPath() . '/templates';
            }
        }
        // Extract used messages
        $extractedCatalogue = $this->extractMessages($locale, $codePaths);
        // Load defined messages
        $currentCatalogue = $this->loadCurrentMessages($locale, $transPaths);
        // Merge defined and extracted messages to get all message ids
        $mergeOperation = new MergeOperation($extractedCatalogue, $currentCatalogue);
        $allMessages = $mergeOperation->getResult()->all($domain);
        if (null !== $domain) {
            $allMessages = [$domain => $allMessages];
        }
        // No defined or extracted messages
        if (!$allMessages || null !== $domain && empty($allMessages[$domain])) {
            $outputMessage = \sprintf('No defined or extracted messages for locale "%s"', $locale);
            if (null !== $domain) {
                $outputMessage .= \sprintf(' and domain "%s"', $domain);
            }
            $io->getErrorStyle()->warning($outputMessage);
            return self::EXIT_CODE_GENERAL_ERROR;
        }
        // Load the fallback catalogues
        $fallbackCatalogues = $this->loadFallbackCatalogues($locale, $transPaths);
        // Display header line
        $headers = ['State', 'Domain', 'Id', \sprintf('Message Preview (%s)', $locale)];
        foreach ($fallbackCatalogues as $fallbackCatalogue) {
            $headers[] = \sprintf('Fallback Message Preview (%s)', $fallbackCatalogue->getLocale());
        }
        $rows = [];
        // Iterate all message ids and determine their state
        foreach ($allMessages as $domain => $messages) {
            foreach (array_keys($messages) as $messageId) {
                $value = $currentCatalogue->get($messageId, $domain);
                $states = [];
                if ($extractedCatalogue->defines($messageId, $domain)) {
                    if (!$currentCatalogue->defines($messageId, $domain)) {
                        $states[] = self::MESSAGE_MISSING;
                        if (!$input->getOption('only-unused')) {
                            $exitCode |= self::EXIT_CODE_MISSING;
                        }
                    }
                } elseif ($currentCatalogue->defines($messageId, $domain)) {
                    $states[] = self::MESSAGE_UNUSED;
                    if (!$input->getOption('only-missing')) {
                        $exitCode |= self::EXIT_CODE_UNUSED;
                    }
                }
                if (!\in_array(self::MESSAGE_UNUSED, $states) && $input->getOption('only-unused') || !\in_array(self::MESSAGE_MISSING, $states) && $input->getOption('only-missing')) {
                    continue;
                }
                foreach ($fallbackCatalogues as $fallbackCatalogue) {
                    if ($fallbackCatalogue->defines($messageId, $domain) && $value === $fallbackCatalogue->get($messageId, $domain)) {
                        $states[] = self::MESSAGE_EQUALS_FALLBACK;
                        $exitCode |= self::EXIT_CODE_FALLBACK;
                        break;
                    }
                }
                $row = [$this->formatStates($states), $domain, $this->formatId($messageId), $this->sanitizeString($value)];
                foreach ($fallbackCatalogues as $fallbackCatalogue) {
                    $row[] = $this->sanitizeString($fallbackCatalogue->get($messageId, $domain));
                }
                $rows[] = $row;
            }
        }
        $io->table($headers, $rows);
        return $exitCode;
    }
    public function complete(CompletionInput $input, CompletionSuggestions $suggestions): void
    {
        if ($input->mustSuggestArgumentValuesFor('locale')) {
            $suggestions->suggestValues($this->enabledLocales);
            return;
        }
        /** @var KernelInterface $kernel */
        $kernel = $this->getApplication()->getKernel();
        if ($input->mustSuggestArgumentValuesFor('bundle')) {
            $availableBundles = [];
            foreach ($kernel->getBundles() as $bundle) {
                $availableBundles[] = $bundle->getName();
                if ($extension = $bundle->getContainerExtension()) {
                    $availableBundles[] = $extension->getAlias();
                }
            }
            $suggestions->suggestValues($availableBundles);
            return;
        }
        if ($input->mustSuggestOptionValuesFor('domain')) {
            $locale = $input->getArgument('locale');
            $mergeOperation = new MergeOperation($this->extractMessages($locale, $this->getRootCodePaths($kernel)), $this->loadCurrentMessages($locale, $this->getRootTransPaths()));
            $suggestions->suggestValues($mergeOperation->getDomains());
        }
    }
    private function formatState(int $state): string
    {
        if (self::MESSAGE_MISSING === $state) {
            return '<error> missing </error>';
        }
        if (self::MESSAGE_UNUSED === $state) {
            return '<comment> unused </comment>';
        }
        if (self::MESSAGE_EQUALS_FALLBACK === $state) {
            return '<info> fallback </info>';
        }
        return $state;
    }
    private function formatStates(array $states): string
    {
        $result = [];
        foreach ($states as $state) {
            $result[] = $this->formatState($state);
        }
        return implode(' ', $result);
    }
    private function formatId(string $id): string
    {
        return \sprintf('<fg=cyan;options=bold>%s</>', $id);
    }
    private function sanitizeString(string $string, int $length = 40): string
    {
        $string = trim(preg_replace('/\s+/', ' ', $string));
        if (\false !== $encoding = mb_detect_encoding($string, null, \true)) {
            if (mb_strlen($string, $encoding) > $length) {
                return mb_substr($string, 0, $length - 3, $encoding) . '...';
            }
        } elseif (\strlen($string) > $length) {
            return substr($string, 0, $length - 3) . '...';
        }
        return $string;
    }
    private function extractMessages(string $locale, array $transPaths): MessageCatalogue
    {
        $extractedCatalogue = new MessageCatalogue($locale);
        foreach ($transPaths as $path) {
            if (is_dir($path) || is_file($path)) {
                $this->extractor->extract($path, $extractedCatalogue);
            }
        }
        return $extractedCatalogue;
    }
    private function loadCurrentMessages(string $locale, array $transPaths): MessageCatalogue
    {
        $currentCatalogue = new MessageCatalogue($locale);
        foreach ($transPaths as $path) {
            if (is_dir($path)) {
                $this->reader->read($path, $currentCatalogue);
            }
        }
        return $currentCatalogue;
    }
    /**
     * @return MessageCatalogue[]
     */
    private function loadFallbackCatalogues(string $locale, array $transPaths): array
    {
        $fallbackCatalogues = [];
        if ($this->translator instanceof Translator || $this->translator instanceof DataCollectorTranslator || $this->translator instanceof LoggingTranslator) {
            foreach ($this->translator->getFallbackLocales() as $fallbackLocale) {
                if ($fallbackLocale === $locale) {
                    continue;
                }
                $fallbackCatalogue = new MessageCatalogue($fallbackLocale);
                foreach ($transPaths as $path) {
                    if (is_dir($path)) {
                        $this->reader->read($path, $fallbackCatalogue);
                    }
                }
                $fallbackCatalogues[] = $fallbackCatalogue;
            }
        }
        return $fallbackCatalogues;
    }
    private function getRootTransPaths(): array
    {
        $transPaths = $this->transPaths;
        if ($this->defaultTransPath) {
            $transPaths[] = $this->defaultTransPath;
        }
        return $transPaths;
    }
    private function getRootCodePaths(KernelInterface $kernel): array
    {
        $codePaths = $this->codePaths;
        $codePaths[] = $kernel->getProjectDir() . '/src';
        if ($this->defaultViewsPath) {
            $codePaths[] = $this->defaultViewsPath;
        }
        return $codePaths;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Bundle\FrameworkBundle\Command;

use _ContaoManager\Symfony\Component\Console\Attribute\AsCommand;
use _ContaoManager\Symfony\Component\Yaml\Command\LintCommand as BaseLintCommand;
/**
 * Validates YAML files syntax and outputs encountered errors.
 *
 * @author Grégoire Pineau <lyrixx@lyrixx.info>
 * @author Robin Chalas <robin.chalas@gmail.com>
 *
 * @final
 */
#[AsCommand(name: 'lint:yaml', description: 'Lint a YAML file and outputs encountered errors')]
class YamlLintCommand extends BaseLintCommand
{
    public function __construct()
    {
        $directoryIteratorProvider = function ($directory, $default) {
            if (!is_dir($directory)) {
                $directory = $this->getApplication()->getKernel()->locateResource($directory);
            }
            return $default($directory);
        };
        $isReadableProvider = fn($fileOrDirectory, $default) => str_starts_with($fileOrDirectory, '@') || $default($fileOrDirectory);
        parent::__construct(null, $directoryIteratorProvider, $isReadableProvider);
    }
    protected function configure(): void
    {
        parent::configure();
        $this->setHelp($this->getHelp() . <<<'EOF'

Or find all files in a bundle:

  <info>php %command.full_name% @AcmeDemoBundle</info>

EOF
);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Bundle\FrameworkBundle\Command;

use _ContaoManager\Symfony\Component\Console\Attribute\AsCommand;
use _ContaoManager\Symfony\Component\Console\Command\Command;
use _ContaoManager\Symfony\Component\Console\Input\InputInterface;
use _ContaoManager\Symfony\Component\Console\Output\OutputInterface;
use _ContaoManager\Symfony\Component\Console\Style\SymfonyStyle;
/**
 * List available cache pools.
 *
 * @author Tobias Nyholm <tobias.nyholm@gmail.com>
 */
#[AsCommand(name: 'cache:pool:list', description: 'List available cache pools')]
final class CachePoolListCommand extends Command
{
    private array $poolNames;
    /**
     * @param string[] $poolNames
     */
    public function __construct(array $poolNames)
    {
        parent::__construct();
        $this->poolNames = $poolNames;
    }
    protected function configure(): void
    {
        $this->setHelp(<<<'EOF'
The <info>%command.name%</info> command lists all available cache pools.
EOF
);
    }
    protected function execute(InputInterface $input, OutputInterface $output): int
    {
        $io = new SymfonyStyle($input, $output);
        $io->table(['Pool name'], array_map(fn($pool) => [$pool], $this->poolNames));
        return 0;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Bundle\FrameworkBundle\Command;

use _ContaoManager\Symfony\Bundle\FrameworkBundle\Secrets\AbstractVault;
use _ContaoManager\Symfony\Component\Console\Attribute\AsCommand;
use _ContaoManager\Symfony\Component\Console\Command\Command;
use _ContaoManager\Symfony\Component\Console\Input\InputInterface;
use _ContaoManager\Symfony\Component\Console\Input\InputOption;
use _ContaoManager\Symfony\Component\Console\Output\ConsoleOutputInterface;
use _ContaoManager\Symfony\Component\Console\Output\OutputInterface;
use _ContaoManager\Symfony\Component\Console\Style\SymfonyStyle;
/**
 * @author Tobias Schultze <http://tobion.de>
 * @author Jérémy Derussé <jeremy@derusse.com>
 * @author Nicolas Grekas <p@tchwork.com>
 *
 * @internal
 */
#[AsCommand(name: 'secrets:generate-keys', description: 'Generate new encryption keys')]
final class SecretsGenerateKeysCommand extends Command
{
    private AbstractVault $vault;
    private ?AbstractVault $localVault;
    public function __construct(AbstractVault $vault, ?AbstractVault $localVault = null)
    {
        $this->vault = $vault;
        $this->localVault = $localVault;
        parent::__construct();
    }
    protected function configure(): void
    {
        $this->addOption('local', 'l', InputOption::VALUE_NONE, 'Update the local vault.')->addOption('rotate', 'r', InputOption::VALUE_NONE, 'Re-encrypt existing secrets with the newly generated keys.')->setHelp(<<<'EOF'
The <info>%command.name%</info> command generates a new encryption key.

    <info>%command.full_name%</info>

If encryption keys already exist, the command must be called with
the <info>--rotate</info> option in order to override those keys and re-encrypt
existing secrets.

    <info>%command.full_name% --rotate</info>
EOF
);
    }
    protected function execute(InputInterface $input, OutputInterface $output): int
    {
        $io = new SymfonyStyle($input, $output instanceof ConsoleOutputInterface ? $output->getErrorOutput() : $output);
        $vault = $input->getOption('local') ? $this->localVault : $this->vault;
        if (null === $vault) {
            $io->error('The local vault is disabled.');
            return 1;
        }
        if (!$input->getOption('rotate')) {
            if ($vault->generateKeys()) {
                $io->success($vault->getLastMessage());
                if ($this->vault === $vault) {
                    $io->caution('DO NOT COMMIT THE DECRYPTION KEY FOR THE PROD ENVIRONMENT⚠️');
                }
                return 0;
            }
            $io->warning($vault->getLastMessage());
            return 1;
        }
        $secrets = [];
        foreach ($vault->list(\true) as $name => $value) {
            if (null === $value) {
                $io->error($vault->getLastMessage());
                return 1;
            }
            $secrets[$name] = $value;
        }
        if (!$vault->generateKeys(\true)) {
            $io->warning($vault->getLastMessage());
            return 1;
        }
        $io->success($vault->getLastMessage());
        if ($secrets) {
            foreach ($secrets as $name => $value) {
                $vault->seal($name, $value);
            }
            $io->comment('Existing secrets have been rotated to the new keys.');
        }
        if ($this->vault === $vault) {
            $io->caution('DO NOT COMMIT THE DECRYPTION KEY FOR THE PROD ENVIRONMENT⚠️');
        }
        return 0;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Bundle\FrameworkBundle\Command;

use _ContaoManager\Symfony\Component\Console\Attribute\AsCommand;
use _ContaoManager\Symfony\Component\Console\Command\Command;
use _ContaoManager\Symfony\Component\Console\Completion\CompletionInput;
use _ContaoManager\Symfony\Component\Console\Completion\CompletionSuggestions;
use _ContaoManager\Symfony\Component\Console\Input\InputArgument;
use _ContaoManager\Symfony\Component\Console\Input\InputInterface;
use _ContaoManager\Symfony\Component\Console\Output\OutputInterface;
use _ContaoManager\Symfony\Component\Console\Style\SymfonyStyle;
use _ContaoManager\Symfony\Component\HttpKernel\CacheClearer\Psr6CacheClearer;
/**
 * Delete an item from a cache pool.
 *
 * @author Pierre du Plessis <pdples@gmail.com>
 */
#[AsCommand(name: 'cache:pool:delete', description: 'Delete an item from a cache pool')]
final class CachePoolDeleteCommand extends Command
{
    private Psr6CacheClearer $poolClearer;
    private ?array $poolNames;
    /**
     * @param string[]|null $poolNames
     */
    public function __construct(Psr6CacheClearer $poolClearer, ?array $poolNames = null)
    {
        parent::__construct();
        $this->poolClearer = $poolClearer;
        $this->poolNames = $poolNames;
    }
    protected function configure(): void
    {
        $this->setDefinition([new InputArgument('pool', InputArgument::REQUIRED, 'The cache pool from which to delete an item'), new InputArgument('key', InputArgument::REQUIRED, 'The cache key to delete from the pool')])->setHelp(<<<'EOF'
The <info>%command.name%</info> deletes an item from a given cache pool.

    %command.full_name% <pool> <key>
EOF
);
    }
    protected function execute(InputInterface $input, OutputInterface $output): int
    {
        $io = new SymfonyStyle($input, $output);
        $pool = $input->getArgument('pool');
        $key = $input->getArgument('key');
        $cachePool = $this->poolClearer->getPool($pool);
        if (!$cachePool->hasItem($key)) {
            $io->note(\sprintf('Cache item "%s" does not exist in cache pool "%s".', $key, $pool));
            return 0;
        }
        if (!$cachePool->deleteItem($key)) {
            throw new \Exception(\sprintf('Cache item "%s" could not be deleted.', $key));
        }
        $io->success(\sprintf('Cache item "%s" was successfully deleted.', $key));
        return 0;
    }
    public function complete(CompletionInput $input, CompletionSuggestions $suggestions): void
    {
        if (\is_array($this->poolNames) && $input->mustSuggestArgumentValuesFor('pool')) {
            $suggestions->suggestValues($this->poolNames);
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Bundle\FrameworkBundle\Command;

use _ContaoManager\Symfony\Component\Config\ConfigCache;
use _ContaoManager\Symfony\Component\Config\FileLocator;
use _ContaoManager\Symfony\Component\DependencyInjection\Compiler\ServiceLocatorTagPass;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerBuilder;
use _ContaoManager\Symfony\Component\DependencyInjection\Loader\XmlFileLoader;
use _ContaoManager\Symfony\Component\HttpKernel\KernelInterface;
/**
 * @internal
 *
 * @author Robin Chalas <robin.chalas@gmail.com>
 * @author Nicolas Grekas <p@tchwork.com>
 */
trait BuildDebugContainerTrait
{
    protected ContainerBuilder $container;
    /**
     * Loads the ContainerBuilder from the cache.
     *
     * @throws \LogicException
     */
    protected function getContainerBuilder(KernelInterface $kernel): ContainerBuilder
    {
        if (isset($this->container)) {
            return $this->container;
        }
        if (!$kernel->isDebug() || !$kernel->getContainer()->getParameter('debug.container.dump') || !(new ConfigCache($kernel->getContainer()->getParameter('debug.container.dump'), \true))->isFresh()) {
            $buildContainer = \Closure::bind(function () {
                $this->initializeBundles();
                return $this->buildContainer();
            }, $kernel, $kernel::class);
            $container = $buildContainer();
            $container->getCompilerPassConfig()->setRemovingPasses([]);
            $container->getCompilerPassConfig()->setAfterRemovingPasses([]);
            $container->compile();
        } else {
            $buildContainer = \Closure::bind(function () {
                $containerBuilder = $this->getContainerBuilder();
                $this->prepareContainer($containerBuilder);
                return $containerBuilder;
            }, $kernel, $kernel::class);
            $container = $buildContainer();
            (new XmlFileLoader($container, new FileLocator()))->load($kernel->getContainer()->getParameter('debug.container.dump'));
            $locatorPass = new ServiceLocatorTagPass();
            $locatorPass->process($container);
            $container->getCompilerPassConfig()->setBeforeOptimizationPasses([]);
            $container->getCompilerPassConfig()->setOptimizationPasses([]);
            $container->getCompilerPassConfig()->setBeforeRemovingPasses([]);
        }
        return $this->container = $container;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Bundle\FrameworkBundle\Command;

use _ContaoManager\Symfony\Component\Console\Attribute\AsCommand;
use _ContaoManager\Symfony\Component\Console\Command\Command;
use _ContaoManager\Symfony\Component\Console\Helper\Helper;
use _ContaoManager\Symfony\Component\Console\Helper\TableSeparator;
use _ContaoManager\Symfony\Component\Console\Input\InputInterface;
use _ContaoManager\Symfony\Component\Console\Output\OutputInterface;
use _ContaoManager\Symfony\Component\Console\Style\SymfonyStyle;
use _ContaoManager\Symfony\Component\HttpKernel\Kernel;
use _ContaoManager\Symfony\Component\HttpKernel\KernelInterface;
/**
 * A console command to display information about the current installation.
 *
 * @author Roland Franssen <franssen.roland@gmail.com>
 *
 * @final
 */
#[AsCommand(name: 'about', description: 'Display information about the current project')]
class AboutCommand extends Command
{
    protected function configure(): void
    {
        $this->setHelp(<<<'EOT'
The <info>%command.name%</info> command displays information about the current Symfony project.

The <info>PHP</info> section displays important configuration that could affect your application. The values might
be different between web and CLI.
EOT
);
    }
    protected function execute(InputInterface $input, OutputInterface $output): int
    {
        $io = new SymfonyStyle($input, $output);
        /** @var KernelInterface $kernel */
        $kernel = $this->getApplication()->getKernel();
        if (method_exists($kernel, 'getBuildDir')) {
            $buildDir = $kernel->getBuildDir();
        } else {
            $buildDir = $kernel->getCacheDir();
        }
        $rows = [['<info>Symfony</>'], new TableSeparator(), ['Version', Kernel::VERSION], ['Long-Term Support', 4 === Kernel::MINOR_VERSION ? 'Yes' : 'No'], ['End of maintenance', Kernel::END_OF_MAINTENANCE . (self::isExpired(Kernel::END_OF_MAINTENANCE) ? ' <error>Expired</>' : ' (<comment>' . self::daysBeforeExpiration(Kernel::END_OF_MAINTENANCE) . '</>)')], ['End of life', Kernel::END_OF_LIFE . (self::isExpired(Kernel::END_OF_LIFE) ? ' <error>Expired</>' : ' (<comment>' . self::daysBeforeExpiration(Kernel::END_OF_LIFE) . '</>)')], new TableSeparator(), ['<info>Kernel</>'], new TableSeparator(), ['Type', $kernel::class], ['Environment', $kernel->getEnvironment()], ['Debug', $kernel->isDebug() ? 'true' : 'false'], ['Charset', $kernel->getCharset()], ['Cache directory', self::formatPath($kernel->getCacheDir(), $kernel->getProjectDir()) . ' (<comment>' . self::formatFileSize($kernel->getCacheDir()) . '</>)'], ['Build directory', self::formatPath($buildDir, $kernel->getProjectDir()) . ' (<comment>' . self::formatFileSize($buildDir) . '</>)'], ['Log directory', self::formatPath($kernel->getLogDir(), $kernel->getProjectDir()) . ' (<comment>' . self::formatFileSize($kernel->getLogDir()) . '</>)'], new TableSeparator(), ['<info>PHP</>'], new TableSeparator(), ['Version', \PHP_VERSION], ['Architecture', \PHP_INT_SIZE * 8 . ' bits'], ['Intl locale', class_exists(\Locale::class, \false) && \Locale::getDefault() ? \Locale::getDefault() : 'n/a'], ['Timezone', date_default_timezone_get() . ' (<comment>' . (new \DateTimeImmutable())->format(\DateTimeInterface::W3C) . '</>)'], ['OPcache', \extension_loaded('Zend OPcache') && filter_var(\ini_get('opcache.enable'), \FILTER_VALIDATE_BOOL) ? 'true' : 'false'], ['APCu', \extension_loaded('apcu') && filter_var(\ini_get('apc.enabled'), \FILTER_VALIDATE_BOOL) ? 'true' : 'false'], ['Xdebug', \extension_loaded('xdebug') ? 'true' : 'false']];
        $io->table([], $rows);
        return 0;
    }
    private static function formatPath(string $path, string $baseDir): string
    {
        return preg_replace('~^' . preg_quote($baseDir, '~') . '~', '.', $path);
    }
    private static function formatFileSize(string $path): string
    {
        if (is_file($path)) {
            $size = filesize($path) ?: 0;
        } else {
            if (!is_dir($path)) {
                return 'n/a';
            }
            $size = 0;
            foreach (new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($path, \RecursiveDirectoryIterator::SKIP_DOTS | \RecursiveDirectoryIterator::FOLLOW_SYMLINKS)) as $file) {
                if ($file->isReadable()) {
                    $size += $file->getSize();
                }
            }
        }
        return Helper::formatMemory($size);
    }
    private static function isExpired(string $date): bool
    {
        $date = \DateTimeImmutable::createFromFormat('d/m/Y', '01/' . $date);
        return \false !== $date && new \DateTimeImmutable() > $date->modify('last day of this month 23:59:59');
    }
    private static function daysBeforeExpiration(string $date): string
    {
        $date = \DateTimeImmutable::createFromFormat('d/m/Y', '01/' . $date);
        return (new \DateTimeImmutable())->diff($date->modify('last day of this month 23:59:59'))->format('in %R%a days');
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Bundle\FrameworkBundle\Command;

use _ContaoManager\Symfony\Component\Console\Attribute\AsCommand;
use _ContaoManager\Symfony\Component\Console\Command\Command;
use _ContaoManager\Symfony\Component\Console\Input\ArrayInput;
use _ContaoManager\Symfony\Component\Console\Input\InputArgument;
use _ContaoManager\Symfony\Component\Console\Input\InputInterface;
use _ContaoManager\Symfony\Component\Console\Input\InputOption;
use _ContaoManager\Symfony\Component\Console\Output\OutputInterface;
use _ContaoManager\Symfony\Component\Console\Style\SymfonyStyle;
use _ContaoManager\Symfony\Component\ExpressionLanguage\ExpressionFunctionProviderInterface;
use _ContaoManager\Symfony\Component\Routing\Matcher\TraceableUrlMatcher;
use _ContaoManager\Symfony\Component\Routing\RouterInterface;
/**
 * A console command to test route matching.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 *
 * @final
 */
#[AsCommand(name: 'router:match', description: 'Help debug routes by simulating a path info match')]
class RouterMatchCommand extends Command
{
    private RouterInterface $router;
    private iterable $expressionLanguageProviders;
    /**
     * @param iterable<mixed, ExpressionFunctionProviderInterface> $expressionLanguageProviders
     */
    public function __construct(RouterInterface $router, iterable $expressionLanguageProviders = [])
    {
        parent::__construct();
        $this->router = $router;
        $this->expressionLanguageProviders = $expressionLanguageProviders;
    }
    protected function configure(): void
    {
        $this->setDefinition([new InputArgument('path_info', InputArgument::REQUIRED, 'A path info'), new InputOption('method', null, InputOption::VALUE_REQUIRED, 'Set the HTTP method'), new InputOption('scheme', null, InputOption::VALUE_REQUIRED, 'Set the URI scheme (usually http or https)'), new InputOption('host', null, InputOption::VALUE_REQUIRED, 'Set the URI host')])->setHelp(<<<'EOF'
The <info>%command.name%</info> shows which routes match a given request and which don't and for what reason:

  <info>php %command.full_name% /foo</info>

or

  <info>php %command.full_name% /foo --method POST --scheme https --host symfony.com --verbose</info>

EOF
);
    }
    protected function execute(InputInterface $input, OutputInterface $output): int
    {
        $io = new SymfonyStyle($input, $output);
        $context = $this->router->getContext();
        if (null !== $method = $input->getOption('method')) {
            $context->setMethod($method);
        }
        if (null !== $scheme = $input->getOption('scheme')) {
            $context->setScheme($scheme);
        }
        if (null !== $host = $input->getOption('host')) {
            $context->setHost($host);
        }
        $matcher = new TraceableUrlMatcher($this->router->getRouteCollection(), $context);
        foreach ($this->expressionLanguageProviders as $provider) {
            $matcher->addExpressionLanguageProvider($provider);
        }
        $traces = $matcher->getTraces($input->getArgument('path_info'));
        $io->newLine();
        $matches = \false;
        foreach ($traces as $trace) {
            if (TraceableUrlMatcher::ROUTE_ALMOST_MATCHES == $trace['level']) {
                $io->text(\sprintf('Route <info>"%s"</> almost matches but %s', $trace['name'], lcfirst($trace['log'])));
            } elseif (TraceableUrlMatcher::ROUTE_MATCHES == $trace['level']) {
                $io->success(\sprintf('Route "%s" matches', $trace['name']));
                $routerDebugCommand = $this->getApplication()->find('debug:router');
                $routerDebugCommand->run(new ArrayInput(['name' => $trace['name']]), $output);
                $matches = \true;
            } elseif ($input->getOption('verbose')) {
                $io->text(\sprintf('Route "%s" does not match: %s', $trace['name'], $trace['log']));
            }
        }
        if (!$matches) {
            $io->error(\sprintf('None of the routes match the path "%s"', $input->getArgument('path_info')));
            return 1;
        }
        return 0;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Bundle\FrameworkBundle\Command;

use _ContaoManager\Symfony\Bundle\FrameworkBundle\Secrets\AbstractVault;
use _ContaoManager\Symfony\Component\Console\Attribute\AsCommand;
use _ContaoManager\Symfony\Component\Console\Command\Command;
use _ContaoManager\Symfony\Component\Console\Completion\CompletionInput;
use _ContaoManager\Symfony\Component\Console\Completion\CompletionSuggestions;
use _ContaoManager\Symfony\Component\Console\Input\InputArgument;
use _ContaoManager\Symfony\Component\Console\Input\InputInterface;
use _ContaoManager\Symfony\Component\Console\Input\InputOption;
use _ContaoManager\Symfony\Component\Console\Output\ConsoleOutputInterface;
use _ContaoManager\Symfony\Component\Console\Output\OutputInterface;
use _ContaoManager\Symfony\Component\Console\Style\SymfonyStyle;
/**
 * @author Tobias Schultze <http://tobion.de>
 * @author Jérémy Derussé <jeremy@derusse.com>
 * @author Nicolas Grekas <p@tchwork.com>
 *
 * @internal
 */
#[AsCommand(name: 'secrets:set', description: 'Set a secret in the vault')]
final class SecretsSetCommand extends Command
{
    private AbstractVault $vault;
    private ?AbstractVault $localVault;
    public function __construct(AbstractVault $vault, ?AbstractVault $localVault = null)
    {
        $this->vault = $vault;
        $this->localVault = $localVault;
        parent::__construct();
    }
    protected function configure(): void
    {
        $this->addArgument('name', InputArgument::REQUIRED, 'The name of the secret')->addArgument('file', InputArgument::OPTIONAL, 'A file where to read the secret from or "-" for reading from STDIN')->addOption('local', 'l', InputOption::VALUE_NONE, 'Update the local vault.')->addOption('random', 'r', InputOption::VALUE_OPTIONAL, 'Generate a random value.', \false)->setHelp(<<<'EOF'
The <info>%command.name%</info> command stores a secret in the vault.

    <info>%command.full_name% <name></info>

To reference secrets in services.yaml or any other config
files, use <info>"%env(<name>)%"</info>.

By default, the secret value should be entered interactively.
Alternatively, provide a file where to read the secret from:

    <info>php %command.full_name% <name> filename</info>

Use "-" as a file name to read from STDIN:

    <info>cat filename | php %command.full_name% <name> -</info>

Use <info>--local</info> to override secrets for local needs.
EOF
);
    }
    protected function execute(InputInterface $input, OutputInterface $output): int
    {
        $errOutput = $output instanceof ConsoleOutputInterface ? $output->getErrorOutput() : $output;
        $io = new SymfonyStyle($input, $errOutput);
        $name = $input->getArgument('name');
        $vault = $input->getOption('local') ? $this->localVault : $this->vault;
        if (null === $vault) {
            $io->error('The local vault is disabled.');
            return 1;
        }
        if ($this->localVault === $vault && !\array_key_exists($name, $this->vault->list())) {
            $io->error(\sprintf('Secret "%s" does not exist in the vault, you cannot override it locally.', $name));
            return 1;
        }
        if (0 < $random = $input->getOption('random') ?? 16) {
            $value = strtr(substr(base64_encode(random_bytes($random)), 0, $random), '+/', '-_');
        } elseif (!$file = $input->getArgument('file')) {
            $value = $io->askHidden('Please type the secret value');
            if (null === $value) {
                $io->warning('No value provided: using empty string');
                $value = '';
            }
        } elseif ('-' === $file) {
            $value = file_get_contents('php://stdin');
        } elseif (is_file($file) && is_readable($file)) {
            $value = file_get_contents($file);
        } elseif (!is_file($file)) {
            throw new \InvalidArgumentException(\sprintf('File not found: "%s".', $file));
        } elseif (!is_readable($file)) {
            throw new \InvalidArgumentException(\sprintf('File is not readable: "%s".', $file));
        }
        if ($vault->generateKeys()) {
            $io->success($vault->getLastMessage());
            if ($this->vault === $vault) {
                $io->caution('DO NOT COMMIT THE DECRYPTION KEY FOR THE PROD ENVIRONMENT⚠️');
            }
        }
        $vault->seal($name, $value);
        $io->success($vault->getLastMessage() ?? 'Secret was successfully stored in the vault.');
        if (0 < $random) {
            $errOutput->write(' // The generated random value is: <comment>');
            $output->write($value);
            $errOutput->writeln('</comment>');
            $io->newLine();
        }
        if ($this->vault === $vault && null !== $this->localVault->reveal($name)) {
            $io->comment('Note that this secret is overridden in the local vault.');
        }
        return 0;
    }
    public function complete(CompletionInput $input, CompletionSuggestions $suggestions): void
    {
        if ($input->mustSuggestArgumentValuesFor('name')) {
            $suggestions->suggestValues(array_keys($this->vault->list(\false)));
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Bundle\FrameworkBundle\Command;

use _ContaoManager\Psr\Container\ContainerInterface;
use _ContaoManager\Symfony\Component\Config\Definition\ConfigurationInterface;
use _ContaoManager\Symfony\Component\Config\Definition\Processor;
use _ContaoManager\Symfony\Component\Console\Attribute\AsCommand;
use _ContaoManager\Symfony\Component\Console\Completion\CompletionInput;
use _ContaoManager\Symfony\Component\Console\Completion\CompletionSuggestions;
use _ContaoManager\Symfony\Component\Console\Exception\InvalidArgumentException;
use _ContaoManager\Symfony\Component\Console\Exception\LogicException;
use _ContaoManager\Symfony\Component\Console\Input\InputArgument;
use _ContaoManager\Symfony\Component\Console\Input\InputInterface;
use _ContaoManager\Symfony\Component\Console\Input\InputOption;
use _ContaoManager\Symfony\Component\Console\Output\OutputInterface;
use _ContaoManager\Symfony\Component\Console\Style\SymfonyStyle;
use _ContaoManager\Symfony\Component\DependencyInjection\Compiler\ValidateEnvPlaceholdersPass;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerBuilder;
use _ContaoManager\Symfony\Component\DependencyInjection\Extension\ConfigurationExtensionInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Extension\ExtensionInterface;
use _ContaoManager\Symfony\Component\Yaml\Yaml;
/**
 * A console command for dumping available configuration reference.
 *
 * @author Grégoire Pineau <lyrixx@lyrixx.info>
 *
 * @final
 */
#[AsCommand(name: 'debug:config', description: 'Dump the current configuration for an extension')]
class ConfigDebugCommand extends AbstractConfigCommand
{
    public function __construct(private ?ContainerInterface $envVarProcessors = null)
    {
        parent::__construct();
    }
    protected function configure(): void
    {
        $commentedHelpFormats = array_map(static fn($format) => \sprintf('<comment>%s</comment>', $format), $this->getAvailableFormatOptions());
        $helpFormats = implode('", "', $commentedHelpFormats);
        $this->setDefinition([new InputArgument('name', InputArgument::OPTIONAL, 'The bundle name or the extension alias'), new InputArgument('path', InputArgument::OPTIONAL, 'The configuration option path'), new InputOption('resolve-env', null, InputOption::VALUE_NONE, 'Display resolved environment variable values instead of placeholders'), new InputOption('format', null, InputOption::VALUE_REQUIRED, \sprintf('The output format ("%s")', implode('", "', $this->getAvailableFormatOptions())), class_exists(Yaml::class) ? 'txt' : 'json')])->setHelp(<<<EOF
The <info>%command.name%</info> command dumps the current configuration for an
extension/bundle.

Either the extension alias or bundle name can be used:

  <info>php %command.full_name% framework</info>
  <info>php %command.full_name% FrameworkBundle</info>

The <info>--format</info> option specifies the format of the configuration,
these are "{$helpFormats}".

  <info>php %command.full_name% framework --format=json</info>

For dumping a specific option, add its path as second argument:

  <info>php %command.full_name% framework serializer.enabled</info>

EOF
);
    }
    protected function execute(InputInterface $input, OutputInterface $output): int
    {
        $io = new SymfonyStyle($input, $output);
        $errorIo = $io->getErrorStyle();
        if (null === $name = $input->getArgument('name')) {
            $this->listBundles($errorIo);
            $this->listNonBundleExtensions($errorIo);
            $errorIo->comment('Provide the name of a bundle as the first argument of this command to dump its configuration. (e.g. <comment>debug:config FrameworkBundle</comment>)');
            $errorIo->comment('For dumping a specific option, add its path as the second argument of this command. (e.g. <comment>debug:config FrameworkBundle serializer</comment> to dump the <comment>framework.serializer</comment> configuration)');
            return 0;
        }
        $extension = $this->findExtension($name);
        $extensionAlias = $extension->getAlias();
        $container = $this->compileContainer();
        $config = $this->getConfig($extension, $container, $input->getOption('resolve-env'));
        $format = $input->getOption('format');
        if (\in_array($format, ['txt', 'yml'], \true) && !class_exists(Yaml::class)) {
            $errorIo->error('Setting the "format" option to "txt" or "yaml" requires the Symfony Yaml component. Try running "composer install symfony/yaml" or use "--format=json" instead.');
            return 1;
        }
        if (null === $path = $input->getArgument('path')) {
            if ('txt' === $input->getOption('format')) {
                $io->title(\sprintf('Current configuration for %s', $name === $extensionAlias ? \sprintf('extension with alias "%s"', $extensionAlias) : \sprintf('"%s"', $name)));
            }
            $io->writeln($this->convertToFormat([$extensionAlias => $config], $format));
            return 0;
        }
        try {
            $config = $this->getConfigForPath($config, $path, $extensionAlias);
        } catch (LogicException $e) {
            $errorIo->error($e->getMessage());
            return 1;
        }
        $io->title(\sprintf('Current configuration for "%s.%s"', $extensionAlias, $path));
        $io->writeln($this->convertToFormat($config, $format));
        return 0;
    }
    private function convertToFormat(mixed $config, string $format): string
    {
        return match ($format) {
            'txt', 'yaml' => Yaml::dump($config, 10),
            'json' => json_encode($config, \JSON_PRETTY_PRINT | \JSON_UNESCAPED_SLASHES | \JSON_UNESCAPED_UNICODE),
            default => throw new InvalidArgumentException(\sprintf('Supported formats are "%s".', implode('", "', $this->getAvailableFormatOptions()))),
        };
    }
    private function compileContainer(): ContainerBuilder
    {
        $kernel = clone $this->getApplication()->getKernel();
        $kernel->boot();
        $method = new \ReflectionMethod($kernel, 'buildContainer');
        $container = $method->invoke($kernel);
        if ($this->envVarProcessors) {
            $container->set('container.env_var_processors_locator', $this->envVarProcessors);
        }
        $container->getCompiler()->compile($container);
        return $container;
    }
    /**
     * Iterate over configuration until the last step of the given path.
     *
     * @throws LogicException If the configuration does not exist
     */
    private function getConfigForPath(array $config, string $path, string $alias): mixed
    {
        $steps = explode('.', $path);
        foreach ($steps as $step) {
            if (!\is_array($config) || !\array_key_exists($step, $config)) {
                throw new LogicException(\sprintf('Unable to find configuration for "%s.%s".', $alias, $path));
            }
            $config = $config[$step];
        }
        return $config;
    }
    private function getConfigForExtension(ExtensionInterface $extension, ContainerBuilder $container): array
    {
        $extensionAlias = $extension->getAlias();
        $extensionConfig = [];
        foreach ($container->getCompilerPassConfig()->getPasses() as $pass) {
            if ($pass instanceof ValidateEnvPlaceholdersPass) {
                $extensionConfig = $pass->getExtensionConfig();
                break;
            }
        }
        if (isset($extensionConfig[$extensionAlias])) {
            return $extensionConfig[$extensionAlias];
        }
        // Fall back to default config if the extension has one
        if (!$extension instanceof ConfigurationExtensionInterface && !$extension instanceof ConfigurationInterface) {
            throw new \LogicException(\sprintf('The extension with alias "%s" does not have configuration.', $extensionAlias));
        }
        $configs = $container->getExtensionConfig($extensionAlias);
        $configuration = $extension instanceof ConfigurationInterface ? $extension : $extension->getConfiguration($configs, $container);
        $this->validateConfiguration($extension, $configuration);
        return (new Processor())->processConfiguration($configuration, $configs);
    }
    public function complete(CompletionInput $input, CompletionSuggestions $suggestions): void
    {
        if ($input->mustSuggestArgumentValuesFor('name')) {
            $suggestions->suggestValues($this->getAvailableExtensions());
            $suggestions->suggestValues($this->getAvailableBundles());
            return;
        }
        if ($input->mustSuggestArgumentValuesFor('path') && null !== $name = $input->getArgument('name')) {
            try {
                $config = $this->getConfig($this->findExtension($name), $this->compileContainer());
                $paths = array_keys(self::buildPathsCompletion($config));
                $suggestions->suggestValues($paths);
            } catch (LogicException) {
            }
        }
        if ($input->mustSuggestOptionValuesFor('format')) {
            $suggestions->suggestValues($this->getAvailableFormatOptions());
        }
    }
    private function getAvailableExtensions(): array
    {
        $kernel = $this->getApplication()->getKernel();
        $extensions = [];
        foreach ($this->getContainerBuilder($kernel)->getExtensions() as $alias => $extension) {
            $extensions[] = $alias;
        }
        return $extensions;
    }
    private function getAvailableBundles(): array
    {
        $availableBundles = [];
        foreach ($this->getApplication()->getKernel()->getBundles() as $bundle) {
            $availableBundles[] = $bundle->getName();
        }
        return $availableBundles;
    }
    private function getConfig(ExtensionInterface $extension, ContainerBuilder $container, bool $resolveEnvs = \false): mixed
    {
        return $container->resolveEnvPlaceholders($container->getParameterBag()->resolveValue($this->getConfigForExtension($extension, $container)), $resolveEnvs ?: null);
    }
    private static function buildPathsCompletion(array $paths, string $prefix = ''): array
    {
        $completionPaths = [];
        foreach ($paths as $key => $values) {
            if (\is_array($values)) {
                $completionPaths += self::buildPathsCompletion($values, $prefix . $key . '.');
            } else {
                $completionPaths[$prefix . $key] = null;
            }
        }
        return $completionPaths;
    }
    private function getAvailableFormatOptions(): array
    {
        return ['txt', 'yaml', 'json'];
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Bundle\FrameworkBundle\Routing;

use _ContaoManager\Symfony\Component\Routing\Matcher\CompiledUrlMatcher;
use _ContaoManager\Symfony\Component\Routing\Matcher\RedirectableUrlMatcherInterface;
/**
 * @author Fabien Potencier <fabien@symfony.com>
 *
 * @internal
 */
class RedirectableCompiledUrlMatcher extends CompiledUrlMatcher implements RedirectableUrlMatcherInterface
{
    public function redirect(string $path, string $route, ?string $scheme = null): array
    {
        return ['_controller' => '_ContaoManager\Symfony\Bundle\FrameworkBundle\Controller\RedirectController::urlRedirectAction', 'path' => $path, 'permanent' => \true, 'scheme' => $scheme, 'httpPort' => $this->context->getHttpPort(), 'httpsPort' => $this->context->getHttpsPort(), '_route' => $route];
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Bundle\FrameworkBundle\Routing;

use _ContaoManager\Symfony\Component\Routing\Loader\AttributeClassLoader;
use _ContaoManager\Symfony\Component\Routing\Route;
/**
 * AttributeRouteControllerLoader is an implementation of AttributeClassLoader
 * that sets the '_controller' default based on the class and method names.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 * @author Alexandre Daubois <alex.daubois@gmail.com>
 */
class AttributeRouteControllerLoader extends AttributeClassLoader
{
    /**
     * Configures the _controller default parameter of a given Route instance.
     *
     * @return void
     */
    protected function configureRoute(Route $route, \ReflectionClass $class, \ReflectionMethod $method, object $annot)
    {
        if ('__invoke' === $method->getName()) {
            $route->setDefault('_controller', $class->getName());
        } else {
            $route->setDefault('_controller', $class->getName() . '::' . $method->getName());
        }
    }
    /**
     * Makes the default route name more sane by removing common keywords.
     */
    protected function getDefaultRouteName(\ReflectionClass $class, \ReflectionMethod $method): string
    {
        $name = preg_replace('/(bundle|controller)_/', '_', parent::getDefaultRouteName($class, $method));
        if (str_ends_with($method->name, 'Action') || str_ends_with($method->name, '_action')) {
            $name = preg_replace('/action(_\d+)?$/', '\1', $name);
        }
        return str_replace('__', '_', $name);
    }
}
if (!class_exists(AnnotatedRouteControllerLoader::class, \false)) {
    class_alias(AttributeRouteControllerLoader::class, AnnotatedRouteControllerLoader::class);
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Bundle\FrameworkBundle\Routing\Attribute;

use _ContaoManager\Symfony\Component\DependencyInjection\Attribute\AutoconfigureTag;
/**
 * Service tag to autoconfigure routing condition services.
 *
 * You can tag a service:
 *
 *     #[AsRoutingConditionService('foo')]
 *     class SomeFooService
 *     {
 *         public function bar(): bool
 *         {
 *             // ...
 *         }
 *     }
 *
 * Then you can use the tagged service in the routing condition:
 *
 *     class PageController
 *     {
 *         #[Route('/page', condition: "service('foo').bar()")]
 *         public function page(): Response
 *         {
 *             // ...
 *         }
 *     }
 */
#[\Attribute(\Attribute::TARGET_CLASS)]
class AsRoutingConditionService extends AutoconfigureTag
{
    public function __construct(?string $alias = null, int $priority = 0)
    {
        parent::__construct('routing.condition_service', ['alias' => $alias, 'priority' => $priority]);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Bundle\FrameworkBundle\Routing;

/**
 * Marker interface for service route loaders.
 */
interface RouteLoaderInterface
{
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Bundle\FrameworkBundle\Routing;

use _ContaoManager\Psr\Container\ContainerInterface;
use _ContaoManager\Psr\Log\LoggerInterface;
use _ContaoManager\Symfony\Component\Config\Loader\LoaderInterface;
use _ContaoManager\Symfony\Component\Config\Resource\FileExistenceResource;
use _ContaoManager\Symfony\Component\Config\Resource\FileResource;
use _ContaoManager\Symfony\Component\DependencyInjection\Config\ContainerParametersResource;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerInterface as SymfonyContainerInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\ParameterNotFoundException;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\RuntimeException;
use _ContaoManager\Symfony\Component\HttpKernel\CacheWarmer\WarmableInterface;
use _ContaoManager\Symfony\Component\Routing\RequestContext;
use _ContaoManager\Symfony\Component\Routing\RouteCollection;
use _ContaoManager\Symfony\Component\Routing\Router as BaseRouter;
use _ContaoManager\Symfony\Contracts\Service\ServiceSubscriberInterface;
/**
 * This Router creates the Loader only when the cache is empty.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class Router extends BaseRouter implements WarmableInterface, ServiceSubscriberInterface
{
    private ContainerInterface $container;
    private array $collectedParameters = [];
    private \Closure $paramFetcher;
    /**
     * @param mixed $resource The main resource to load
     */
    public function __construct(ContainerInterface $container, mixed $resource, array $options = [], ?RequestContext $context = null, ?ContainerInterface $parameters = null, ?LoggerInterface $logger = null, ?string $defaultLocale = null)
    {
        $this->container = $container;
        $this->resource = $resource;
        $this->context = $context ?? new RequestContext();
        $this->logger = $logger;
        $this->setOptions($options);
        if ($parameters) {
            $this->paramFetcher = $parameters->get(...);
        } elseif ($container instanceof SymfonyContainerInterface) {
            $this->paramFetcher = $container->getParameter(...);
        } else {
            throw new \LogicException(\sprintf('You should either pass a "%s" instance or provide the $parameters argument of the "%s" method.', SymfonyContainerInterface::class, __METHOD__));
        }
        $this->defaultLocale = $defaultLocale;
    }
    public function getRouteCollection(): RouteCollection
    {
        if (!isset($this->collection)) {
            $this->collection = $this->container->get('routing.loader')->load($this->resource, $this->options['resource_type']);
            $this->resolveParameters($this->collection);
            $this->collection->addResource(new ContainerParametersResource($this->collectedParameters));
            try {
                $containerFile = ($this->paramFetcher)('kernel.cache_dir') . '/' . ($this->paramFetcher)('kernel.container_class') . '.php';
                if (file_exists($containerFile)) {
                    $this->collection->addResource(new FileResource($containerFile));
                } else {
                    $this->collection->addResource(new FileExistenceResource($containerFile));
                }
            } catch (ParameterNotFoundException) {
            }
        }
        return $this->collection;
    }
    /**
     * @param string|null $buildDir
     */
    public function warmUp(string $cacheDir): array
    {
        $currentDir = $this->getOption('cache_dir');
        // force cache generation
        $this->setOption('cache_dir', $cacheDir);
        $this->getMatcher();
        $this->getGenerator();
        $this->setOption('cache_dir', $currentDir);
        return [$this->getOption('generator_class'), $this->getOption('matcher_class')];
    }
    /**
     * Replaces placeholders with service container parameter values in:
     * - the route defaults,
     * - the route requirements,
     * - the route path,
     * - the route host,
     * - the route schemes,
     * - the route methods.
     */
    private function resolveParameters(RouteCollection $collection): void
    {
        foreach ($collection as $route) {
            foreach ($route->getDefaults() as $name => $value) {
                $route->setDefault($name, $this->resolve($value));
            }
            foreach ($route->getRequirements() as $name => $value) {
                $route->setRequirement($name, $this->resolve($value));
            }
            $route->setPath($this->resolve($route->getPath()));
            $route->setHost($this->resolve($route->getHost()));
            $schemes = [];
            foreach ($route->getSchemes() as $scheme) {
                $schemes[] = explode('|', $this->resolve($scheme));
            }
            $route->setSchemes(array_merge([], ...$schemes));
            $methods = [];
            foreach ($route->getMethods() as $method) {
                $methods[] = explode('|', $this->resolve($method));
            }
            $route->setMethods(array_merge([], ...$methods));
            $route->setCondition($this->resolve($route->getCondition()));
        }
    }
    /**
     * Recursively replaces %placeholders% with the service container parameters.
     *
     * @throws ParameterNotFoundException When a placeholder does not exist as a container parameter
     * @throws RuntimeException           When a container value is not a string or a numeric value
     */
    private function resolve(mixed $value): mixed
    {
        if (\is_array($value)) {
            foreach ($value as $key => $val) {
                $value[$key] = $this->resolve($val);
            }
            return $value;
        }
        if (!\is_string($value)) {
            return $value;
        }
        $escapedValue = preg_replace_callback('/%%|%([^%\s]++)%/', function ($match) use ($value) {
            // skip %%
            if (!isset($match[1])) {
                return '%%';
            }
            if (preg_match('/^env\((?:\w++:)*+\w++\)$/', $match[1])) {
                throw new RuntimeException(\sprintf('Using "%%%s%%" is not allowed in routing configuration.', $match[1]));
            }
            $resolved = ($this->paramFetcher)($match[1]);
            if (\is_scalar($resolved)) {
                $this->collectedParameters[$match[1]] = $resolved;
                if (\is_string($resolved)) {
                    $resolved = $this->resolve($resolved);
                }
                if (\is_scalar($resolved)) {
                    return \false === $resolved ? '0' : (string) $resolved;
                }
            }
            throw new RuntimeException(\sprintf('The container parameter "%s", used in the route configuration value "%s", must be a string or numeric, but it is of type "%s".', $match[1], $value, get_debug_type($resolved)));
        }, $value);
        return str_replace('%%', '%', $escapedValue);
    }
    public static function getSubscribedServices(): array
    {
        return ['routing.loader' => LoaderInterface::class];
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Bundle\FrameworkBundle\Routing;

use _ContaoManager\Symfony\Component\Config\Exception\LoaderLoadException;
use _ContaoManager\Symfony\Component\Config\Loader\DelegatingLoader as BaseDelegatingLoader;
use _ContaoManager\Symfony\Component\Config\Loader\LoaderResolverInterface;
use _ContaoManager\Symfony\Component\Routing\RouteCollection;
/**
 * DelegatingLoader delegates route loading to other loaders using a loader resolver.
 *
 * This implementation resolves the _controller attribute from the short notation
 * to the fully-qualified form (from a:b:c to class::method).
 *
 * @author Fabien Potencier <fabien@symfony.com>
 *
 * @final
 */
class DelegatingLoader extends BaseDelegatingLoader
{
    private bool $loading = \false;
    private array $defaultOptions;
    private array $defaultRequirements;
    public function __construct(LoaderResolverInterface $resolver, array $defaultOptions = [], array $defaultRequirements = [])
    {
        $this->defaultOptions = $defaultOptions;
        $this->defaultRequirements = $defaultRequirements;
        parent::__construct($resolver);
    }
    public function load(mixed $resource, ?string $type = null): RouteCollection
    {
        if ($this->loading) {
            // This can happen if a fatal error occurs in parent::load().
            // Here is the scenario:
            // - while routes are being loaded by parent::load() below, a fatal error
            //   occurs (e.g. parse error in a controller while loading annotations);
            // - PHP abruptly empties the stack trace, bypassing all catch/finally blocks;
            //   it then calls the registered shutdown functions;
            // - the ErrorHandler catches the fatal error and re-injects it for rendering
            //   thanks to HttpKernel->terminateWithException() (that calls handleException());
            // - at this stage, if we try to load the routes again, we must prevent
            //   the fatal error from occurring a second time,
            //   otherwise the PHP process would be killed immediately;
            // - while rendering the exception page, the router can be required
            //   (by e.g. the web profiler that needs to generate a URL);
            // - this handles the case and prevents the second fatal error
            //   by triggering an exception beforehand.
            throw new LoaderLoadException($resource, null, 0, null, $type);
        }
        $this->loading = \true;
        try {
            $collection = parent::load($resource, $type);
        } finally {
            $this->loading = \false;
        }
        foreach ($collection->all() as $route) {
            if ($this->defaultOptions) {
                $route->setOptions($route->getOptions() + $this->defaultOptions);
            }
            if ($this->defaultRequirements) {
                $route->setRequirements($route->getRequirements() + $this->defaultRequirements);
            }
            if (!\is_string($controller = $route->getDefault('_controller'))) {
                continue;
            }
            if (str_contains($controller, '::')) {
                continue;
            }
            $route->setDefault('_controller', $controller);
        }
        return $collection;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Bundle\FrameworkBundle\Routing;

trigger_deprecation('symfony/framework-bundle', '6.4', 'The "%s" class is deprecated, use "%s" instead.', AnnotatedRouteControllerLoader::class, AttributeRouteControllerLoader::class);
class_exists(AttributeRouteControllerLoader::class);
if (\false) {
    /**
     * @deprecated since Symfony 6.4, to be removed in 7.0, use {@link AttributeRouteControllerLoader} instead
     */
    class AnnotatedRouteControllerLoader extends AttributeRouteControllerLoader
    {
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Bundle\FrameworkBundle\DependencyInjection;

use _ContaoManager\Doctrine\Common\Annotations\Annotation;
use _ContaoManager\Doctrine\DBAL\Connection;
use _ContaoManager\Psr\Log\LogLevel;
use _ContaoManager\Seld\JsonLint\JsonParser;
use _ContaoManager\Symfony\Bundle\FullStack;
use _ContaoManager\Symfony\Component\Asset\Package;
use _ContaoManager\Symfony\Component\AssetMapper\AssetMapper;
use _ContaoManager\Symfony\Component\Cache\Adapter\DoctrineAdapter;
use _ContaoManager\Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition;
use _ContaoManager\Symfony\Component\Config\Definition\Builder\NodeBuilder;
use _ContaoManager\Symfony\Component\Config\Definition\Builder\TreeBuilder;
use _ContaoManager\Symfony\Component\Config\Definition\ConfigurationInterface;
use _ContaoManager\Symfony\Component\Config\Definition\Exception\InvalidConfigurationException;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerBuilder;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\LogicException;
use _ContaoManager\Symfony\Component\Form\Form;
use _ContaoManager\Symfony\Component\HtmlSanitizer\HtmlSanitizerInterface;
use _ContaoManager\Symfony\Component\HttpClient\HttpClient;
use _ContaoManager\Symfony\Component\HttpFoundation\Cookie;
use _ContaoManager\Symfony\Component\Lock\Lock;
use _ContaoManager\Symfony\Component\Lock\Store\SemaphoreStore;
use _ContaoManager\Symfony\Component\Mailer\Mailer;
use _ContaoManager\Symfony\Component\Messenger\MessageBusInterface;
use _ContaoManager\Symfony\Component\Notifier\Notifier;
use _ContaoManager\Symfony\Component\PropertyAccess\PropertyAccessor;
use _ContaoManager\Symfony\Component\PropertyInfo\PropertyInfoExtractorInterface;
use _ContaoManager\Symfony\Component\RateLimiter\Policy\TokenBucketLimiter;
use _ContaoManager\Symfony\Component\RemoteEvent\RemoteEvent;
use _ContaoManager\Symfony\Component\Scheduler\Schedule;
use _ContaoManager\Symfony\Component\Semaphore\Semaphore;
use _ContaoManager\Symfony\Component\Serializer\Encoder\JsonDecode;
use _ContaoManager\Symfony\Component\Serializer\Serializer;
use _ContaoManager\Symfony\Component\Translation\Translator;
use _ContaoManager\Symfony\Component\Uid\Factory\UuidFactory;
use _ContaoManager\Symfony\Component\Validator\Validation;
use _ContaoManager\Symfony\Component\Webhook\Controller\WebhookController;
use _ContaoManager\Symfony\Component\WebLink\HttpHeaderSerializer;
use _ContaoManager\Symfony\Component\Workflow\WorkflowEvents;
/**
 * FrameworkExtension configuration structure.
 */
class Configuration implements ConfigurationInterface
{
    private bool $debug;
    /**
     * @param bool $debug Whether debugging is enabled or not
     */
    public function __construct(bool $debug)
    {
        $this->debug = $debug;
    }
    /**
     * Generates the configuration tree builder.
     */
    public function getConfigTreeBuilder(): TreeBuilder
    {
        $treeBuilder = new TreeBuilder('framework');
        $rootNode = $treeBuilder->getRootNode();
        $rootNode->beforeNormalization()->ifTrue(fn($v) => !isset($v['assets']) && isset($v['templating']) && class_exists(Package::class))->then(function ($v) {
            $v['assets'] = [];
            return $v;
        })->end()->validate()->always(function ($v) {
            if (!isset($v['http_method_override'])) {
                trigger_deprecation('symfony/framework-bundle', '6.1', 'Not setting the "framework.http_method_override" config option is deprecated. It will default to "false" in 7.0.');
                $v['http_method_override'] = \true;
            }
            if (!isset($v['handle_all_throwables'])) {
                trigger_deprecation('symfony/framework-bundle', '6.4', 'Not setting the "framework.handle_all_throwables" config option is deprecated. It will default to "true" in 7.0.');
            }
            return $v;
        })->end()->fixXmlConfig('enabled_locale')->children()->scalarNode('secret')->end()->booleanNode('http_method_override')->info("Set true to enable support for the '_method' request parameter to determine the intended HTTP method on POST requests. Note: When using the HttpCache, you need to call the method in your front controller instead")->treatNullLike(\false)->end()->scalarNode('trust_x_sendfile_type_header')->info('Set true to enable support for xsendfile in binary file responses.')->defaultFalse()->end()->scalarNode('ide')->defaultValue($this->debug ? '%env(default::SYMFONY_IDE)%' : null)->end()->booleanNode('test')->end()->scalarNode('default_locale')->defaultValue('en')->end()->booleanNode('set_locale_from_accept_language')->info('Whether to use the Accept-Language HTTP header to set the Request locale (only when the "_locale" request attribute is not passed).')->defaultFalse()->end()->booleanNode('set_content_language_from_locale')->info('Whether to set the Content-Language HTTP header on the Response using the Request locale.')->defaultFalse()->end()->arrayNode('enabled_locales')->info('Defines the possible locales for the application. This list is used for generating translations files, but also to restrict which locales are allowed when it is set from Accept-Language header (using "set_locale_from_accept_language").')->prototype('scalar')->end()->end()->arrayNode('trusted_hosts')->beforeNormalization()->ifString()->then(fn($v) => [$v])->end()->prototype('scalar')->end()->end()->scalarNode('trusted_proxies')->end()->arrayNode('trusted_headers')->fixXmlConfig('trusted_header')->performNoDeepMerging()->defaultValue(['x-forwarded-for', 'x-forwarded-port', 'x-forwarded-proto'])->beforeNormalization()->ifString()->then(fn($v) => $v ? array_map('trim', explode(',', $v)) : [])->end()->enumPrototype()->values(['forwarded', 'x-forwarded-for', 'x-forwarded-host', 'x-forwarded-proto', 'x-forwarded-port', 'x-forwarded-prefix'])->end()->end()->scalarNode('error_controller')->defaultValue('error_controller')->end()->booleanNode('handle_all_throwables')->info('HttpKernel will handle all kinds of \Throwable')->end()->end();
        $willBeAvailable = static function (string $package, string $class, ?string $parentPackage = null) {
            $parentPackages = (array) $parentPackage;
            $parentPackages[] = 'symfony/framework-bundle';
            return ContainerBuilder::willBeAvailable($package, $class, $parentPackages);
        };
        $enableIfStandalone = fn(string $package, string $class) => !class_exists(FullStack::class) && $willBeAvailable($package, $class) ? 'canBeDisabled' : 'canBeEnabled';
        $this->addCsrfSection($rootNode);
        $this->addFormSection($rootNode, $enableIfStandalone);
        $this->addHttpCacheSection($rootNode);
        $this->addEsiSection($rootNode);
        $this->addSsiSection($rootNode);
        $this->addFragmentsSection($rootNode);
        $this->addProfilerSection($rootNode);
        $this->addWorkflowSection($rootNode);
        $this->addRouterSection($rootNode);
        $this->addSessionSection($rootNode);
        $this->addRequestSection($rootNode);
        $this->addAssetsSection($rootNode, $enableIfStandalone);
        $this->addAssetMapperSection($rootNode, $enableIfStandalone);
        $this->addTranslatorSection($rootNode, $enableIfStandalone);
        $this->addValidationSection($rootNode, $enableIfStandalone);
        $this->addAnnotationsSection($rootNode, $willBeAvailable);
        $this->addSerializerSection($rootNode, $enableIfStandalone);
        $this->addPropertyAccessSection($rootNode, $willBeAvailable);
        $this->addPropertyInfoSection($rootNode, $enableIfStandalone);
        $this->addCacheSection($rootNode, $willBeAvailable);
        $this->addPhpErrorsSection($rootNode);
        $this->addExceptionsSection($rootNode);
        $this->addWebLinkSection($rootNode, $enableIfStandalone);
        $this->addLockSection($rootNode, $enableIfStandalone);
        $this->addSemaphoreSection($rootNode, $enableIfStandalone);
        $this->addMessengerSection($rootNode, $enableIfStandalone);
        $this->addSchedulerSection($rootNode, $enableIfStandalone);
        $this->addRobotsIndexSection($rootNode);
        $this->addHttpClientSection($rootNode, $enableIfStandalone);
        $this->addMailerSection($rootNode, $enableIfStandalone);
        $this->addSecretsSection($rootNode);
        $this->addNotifierSection($rootNode, $enableIfStandalone);
        $this->addRateLimiterSection($rootNode, $enableIfStandalone);
        $this->addUidSection($rootNode, $enableIfStandalone);
        $this->addHtmlSanitizerSection($rootNode, $enableIfStandalone);
        $this->addWebhookSection($rootNode, $enableIfStandalone);
        $this->addRemoteEventSection($rootNode, $enableIfStandalone);
        return $treeBuilder;
    }
    private function addSecretsSection(ArrayNodeDefinition $rootNode): void
    {
        $rootNode->children()->arrayNode('secrets')->canBeDisabled()->children()->scalarNode('vault_directory')->defaultValue('%kernel.project_dir%/config/secrets/%kernel.runtime_environment%')->cannotBeEmpty()->end()->scalarNode('local_dotenv_file')->defaultValue('%kernel.project_dir%/.env.%kernel.environment%.local')->end()->scalarNode('decryption_env_var')->defaultValue('base64:default::SYMFONY_DECRYPTION_SECRET')->end()->end()->end()->end();
    }
    private function addCsrfSection(ArrayNodeDefinition $rootNode): void
    {
        $rootNode->children()->arrayNode('csrf_protection')->treatFalseLike(['enabled' => \false])->treatTrueLike(['enabled' => \true])->treatNullLike(['enabled' => \true])->addDefaultsIfNotSet()->children()->booleanNode('enabled')->defaultNull()->end()->end()->end()->end();
    }
    private function addFormSection(ArrayNodeDefinition $rootNode, callable $enableIfStandalone): void
    {
        $rootNode->children()->arrayNode('form')->info('form configuration')->{$enableIfStandalone('symfony/form', Form::class)}()->children()->arrayNode('csrf_protection')->treatFalseLike(['enabled' => \false])->treatTrueLike(['enabled' => \true])->treatNullLike(['enabled' => \true])->addDefaultsIfNotSet()->children()->booleanNode('enabled')->defaultNull()->end()->scalarNode('field_name')->defaultValue('_token')->end()->end()->end()->booleanNode('legacy_error_messages')->setDeprecated('symfony/framework-bundle', '6.2')->end()->end()->end()->end();
    }
    private function addHttpCacheSection(ArrayNodeDefinition $rootNode): void
    {
        $rootNode->children()->arrayNode('http_cache')->info('HTTP cache configuration')->canBeEnabled()->fixXmlConfig('private_header')->children()->booleanNode('debug')->defaultValue('%kernel.debug%')->end()->enumNode('trace_level')->values(['none', 'short', 'full'])->end()->scalarNode('trace_header')->end()->integerNode('default_ttl')->end()->arrayNode('private_headers')->performNoDeepMerging()->scalarPrototype()->end()->end()->arrayNode('skip_response_headers')->performNoDeepMerging()->scalarPrototype()->end()->end()->booleanNode('allow_reload')->end()->booleanNode('allow_revalidate')->end()->integerNode('stale_while_revalidate')->end()->integerNode('stale_if_error')->end()->booleanNode('terminate_on_cache_hit')->end()->end()->end()->end();
    }
    private function addEsiSection(ArrayNodeDefinition $rootNode): void
    {
        $rootNode->children()->arrayNode('esi')->info('esi configuration')->canBeEnabled()->end()->end();
    }
    private function addSsiSection(ArrayNodeDefinition $rootNode): void
    {
        $rootNode->children()->arrayNode('ssi')->info('ssi configuration')->canBeEnabled()->end()->end();
    }
    private function addFragmentsSection(ArrayNodeDefinition $rootNode): void
    {
        $rootNode->children()->arrayNode('fragments')->info('fragments configuration')->canBeEnabled()->children()->scalarNode('hinclude_default_template')->defaultNull()->end()->scalarNode('path')->defaultValue('/_fragment')->end()->end()->end()->end();
    }
    private function addProfilerSection(ArrayNodeDefinition $rootNode): void
    {
        $rootNode->children()->arrayNode('profiler')->info('profiler configuration')->canBeEnabled()->children()->booleanNode('collect')->defaultTrue()->end()->scalarNode('collect_parameter')->defaultNull()->info('The name of the parameter to use to enable or disable collection on a per request basis')->end()->booleanNode('only_exceptions')->defaultFalse()->end()->booleanNode('only_main_requests')->defaultFalse()->end()->scalarNode('dsn')->defaultValue('file:%kernel.cache_dir%/profiler')->end()->booleanNode('collect_serializer_data')->info('Enables the serializer data collector and profiler panel')->defaultFalse()->end()->end()->end()->end();
    }
    private function addWorkflowSection(ArrayNodeDefinition $rootNode): void
    {
        $rootNode->fixXmlConfig('workflow')->children()->arrayNode('workflows')->canBeEnabled()->beforeNormalization()->always(static function ($v) {
            if (\is_array($v) && \true === $v['enabled']) {
                $workflows = $v;
                unset($workflows['enabled']);
                if (1 === \count($workflows) && isset($workflows[0]['enabled']) && 1 === \count($workflows[0])) {
                    $workflows = [];
                }
                if (1 === \count($workflows) && isset($workflows['workflows']) && !array_is_list($workflows['workflows']) && array_diff_key($workflows['workflows'], ['audit_trail' => 1, 'type' => 1, 'marking_store' => 1, 'supports' => 1, 'support_strategy' => 1, 'initial_marking' => 1, 'places' => 1, 'transitions' => 1])) {
                    $workflows = $workflows['workflows'];
                }
                foreach ($workflows as $key => $workflow) {
                    if (isset($workflow['enabled']) && \false === $workflow['enabled']) {
                        throw new LogicException(\sprintf('Cannot disable a single workflow. Remove the configuration for the workflow "%s" instead.', $key));
                    }
                    unset($workflows[$key]['enabled']);
                }
                $v = ['enabled' => \true, 'workflows' => $workflows];
            }
            return $v;
        })->end()->children()->arrayNode('workflows')->useAttributeAsKey('name')->prototype('array')->fixXmlConfig('support')->fixXmlConfig('place')->fixXmlConfig('transition')->fixXmlConfig('event_to_dispatch', 'events_to_dispatch')->children()->arrayNode('audit_trail')->canBeEnabled()->end()->enumNode('type')->values(['workflow', 'state_machine'])->defaultValue('state_machine')->end()->arrayNode('marking_store')->children()->enumNode('type')->values(['method'])->end()->scalarNode('property')->cannotBeEmpty()->end()->scalarNode('service')->cannotBeEmpty()->end()->end()->end()->arrayNode('supports')->beforeNormalization()->ifString()->then(fn($v) => [$v])->end()->prototype('scalar')->cannotBeEmpty()->validate()->ifTrue(fn($v) => !class_exists($v) && !interface_exists($v, \false))->thenInvalid('The supported class or interface "%s" does not exist.')->end()->end()->end()->scalarNode('support_strategy')->cannotBeEmpty()->end()->arrayNode('initial_marking')->beforeNormalization()->castToArray()->end()->defaultValue([])->prototype('scalar')->end()->end()->variableNode('events_to_dispatch')->defaultValue(null)->validate()->ifTrue(function ($v) {
            if (null === $v) {
                return \false;
            }
            if (!\is_array($v)) {
                return \true;
            }
            foreach ($v as $value) {
                if (!\is_string($value)) {
                    return \true;
                }
                if (class_exists(WorkflowEvents::class) && !\in_array($value, WorkflowEvents::ALIASES)) {
                    return \true;
                }
            }
            return \false;
        })->thenInvalid('The value must be "null" or an array of workflow events (like ["workflow.enter"]).')->end()->info('Select which Transition events should be dispatched for this Workflow')->example(['workflow.enter', 'workflow.transition'])->end()->arrayNode('places')->beforeNormalization()->always()->then(function ($places) {
            if (!\is_array($places)) {
                throw new InvalidConfigurationException('The "places" option must be an array in workflow configuration.');
            }
            $normalizedPlaces = [];
            foreach ($places as $key => $value) {
                if (!\is_array($value)) {
                    $value = ['name' => $value];
                }
                $value['name'] ??= $key;
                $normalizedPlaces[] = $value;
            }
            return $normalizedPlaces;
        })->end()->isRequired()->requiresAtLeastOneElement()->prototype('array')->children()->scalarNode('name')->isRequired()->cannotBeEmpty()->end()->arrayNode('metadata')->useAttributeAsKey('key')->normalizeKeys(\false)->defaultValue([])->example(['color' => 'blue', 'description' => 'Workflow to manage article.'])->prototype('variable')->end()->end()->end()->end()->end()->arrayNode('transitions')->beforeNormalization()->always(static function ($transitions) {
            if (!\is_array($transitions)) {
                throw new InvalidConfigurationException('The "transitions" option must be an array in workflow configuration.');
            }
            $normalizedTransitions = [];
            foreach ($transitions as $key => $transition) {
                if (\is_array($transition)) {
                    if (\is_string($key = $transition['key'] ?? $key)) {
                        $transition['name'] ??= $key;
                    }
                    if (!($transition['name'] ?? \false)) {
                        throw new InvalidConfigurationException('The "name" option is required for each transition in workflow configuration.');
                    }
                    unset($transition['key']);
                }
                $normalizedTransitions[$key] = $transition;
            }
            return $normalizedTransitions;
        })->end()->isRequired()->requiresAtLeastOneElement()->prototype('array')->children()->scalarNode('name')->isRequired()->cannotBeEmpty()->end()->scalarNode('guard')->cannotBeEmpty()->info('An expression to block the transition')->example('is_fully_authenticated() and is_granted(\'ROLE_JOURNALIST\') and subject.getTitle() == \'My first article\'')->end()->arrayNode('from')->performNoDeepMerging()->beforeNormalization()->ifString()->then(fn($v) => [$v])->end()->requiresAtLeastOneElement()->prototype('scalar')->cannotBeEmpty()->end()->end()->arrayNode('to')->performNoDeepMerging()->beforeNormalization()->ifString()->then(fn($v) => [$v])->end()->requiresAtLeastOneElement()->prototype('scalar')->cannotBeEmpty()->end()->end()->arrayNode('metadata')->useAttributeAsKey('key')->normalizeKeys(\false)->defaultValue([])->example(['color' => 'blue', 'description' => 'Workflow to manage article.'])->prototype('variable')->end()->end()->end()->end()->end()->arrayNode('metadata')->useAttributeAsKey('key')->normalizeKeys(\false)->defaultValue([])->example(['color' => 'blue', 'description' => 'Workflow to manage article.'])->prototype('variable')->end()->end()->end()->validate()->ifTrue(function ($v) {
            return $v['supports'] && isset($v['support_strategy']);
        })->thenInvalid('"supports" and "support_strategy" cannot be used together.')->end()->validate()->ifTrue(function ($v) {
            return !$v['supports'] && !isset($v['support_strategy']);
        })->thenInvalid('"supports" or "support_strategy" should be configured.')->end()->beforeNormalization()->always()->then(function ($values) {
            // Special case to deal with XML when the user wants an empty array
            if (\array_key_exists('event_to_dispatch', $values) && null === $values['event_to_dispatch']) {
                $values['events_to_dispatch'] = [];
                unset($values['event_to_dispatch']);
            }
            return $values;
        })->end()->end()->end()->end()->end()->end();
    }
    private function addRouterSection(ArrayNodeDefinition $rootNode): void
    {
        $rootNode->children()->arrayNode('router')->info('router configuration')->canBeEnabled()->children()->scalarNode('resource')->isRequired()->end()->scalarNode('type')->end()->scalarNode('cache_dir')->defaultValue('%kernel.cache_dir%')->end()->scalarNode('default_uri')->info('The default URI used to generate URLs in a non-HTTP context')->defaultNull()->end()->scalarNode('http_port')->defaultValue(80)->end()->scalarNode('https_port')->defaultValue(443)->end()->scalarNode('strict_requirements')->info("set to true to throw an exception when a parameter does not match the requirements\n" . "set to false to disable exceptions when a parameter does not match the requirements (and return null instead)\n" . "set to null to disable parameter checks against requirements\n" . "'true' is the preferred configuration in development mode, while 'false' or 'null' might be preferred in production")->defaultTrue()->end()->booleanNode('utf8')->defaultTrue()->end()->end()->end()->end();
    }
    private function addSessionSection(ArrayNodeDefinition $rootNode): void
    {
        $rootNode->validate()->always(function (array $v): array {
            if ($v['session']['enabled']) {
                if (!\array_key_exists('cookie_secure', $v['session'])) {
                    trigger_deprecation('symfony/framework-bundle', '6.4', 'Not setting the "framework.session.cookie_secure" config option is deprecated. It will default to "auto" in 7.0.');
                }
                if (!\array_key_exists('cookie_samesite', $v['session'])) {
                    trigger_deprecation('symfony/framework-bundle', '6.4', 'Not setting the "framework.session.cookie_samesite" config option is deprecated. It will default to "lax" in 7.0.');
                }
                if (!\array_key_exists('handler_id', $v['session']) && !\array_key_exists('save_path', $v['session'])) {
                    trigger_deprecation('symfony/framework-bundle', '6.4', 'Not setting either "framework.session.handler_id" or "save_path" config options is deprecated; "handler_id" will default to null in 7.0 if "save_path" is not set and to "session.handler.native_file" otherwise.');
                }
            }
            $v['session'] += ['cookie_samesite' => null, 'handler_id' => 'session.handler.native_file', 'save_path' => '%kernel.cache_dir%/sessions'];
            return $v;
        })->end()->children()->arrayNode('session')->info('session configuration')->canBeEnabled()->children()->scalarNode('storage_factory_id')->defaultValue('session.storage.factory.native')->end()->scalarNode('handler_id')->end()->scalarNode('name')->validate()->ifTrue(function ($v) {
            parse_str($v, $parsed);
            return implode('&', array_keys($parsed)) !== (string) $v;
        })->thenInvalid('Session name %s contains illegal character(s)')->end()->end()->scalarNode('cookie_lifetime')->end()->scalarNode('cookie_path')->end()->scalarNode('cookie_domain')->end()->enumNode('cookie_secure')->values([\true, \false, 'auto'])->end()->booleanNode('cookie_httponly')->defaultTrue()->end()->enumNode('cookie_samesite')->values([null, Cookie::SAMESITE_LAX, Cookie::SAMESITE_STRICT, Cookie::SAMESITE_NONE])->end()->booleanNode('use_cookies')->end()->scalarNode('gc_divisor')->end()->scalarNode('gc_probability')->defaultValue(1)->end()->scalarNode('gc_maxlifetime')->end()->scalarNode('save_path')->end()->integerNode('metadata_update_threshold')->defaultValue(0)->info('seconds to wait between 2 session metadata updates')->end()->integerNode('sid_length')->min(22)->max(256)->end()->integerNode('sid_bits_per_character')->min(4)->max(6)->end()->end()->end()->end();
    }
    private function addRequestSection(ArrayNodeDefinition $rootNode): void
    {
        $rootNode->children()->arrayNode('request')->info('request configuration')->canBeEnabled()->fixXmlConfig('format')->children()->arrayNode('formats')->useAttributeAsKey('name')->prototype('array')->beforeNormalization()->ifTrue(fn($v) => \is_array($v) && isset($v['mime_type']))->then(fn($v) => $v['mime_type'])->end()->beforeNormalization()->castToArray()->end()->prototype('scalar')->end()->end()->end()->end()->end()->end();
    }
    private function addAssetsSection(ArrayNodeDefinition $rootNode, callable $enableIfStandalone): void
    {
        $rootNode->children()->arrayNode('assets')->info('assets configuration')->{$enableIfStandalone('symfony/asset', Package::class)}()->fixXmlConfig('base_url')->children()->booleanNode('strict_mode')->info('Throw an exception if an entry is missing from the manifest.json')->defaultFalse()->end()->scalarNode('version_strategy')->defaultNull()->end()->scalarNode('version')->defaultNull()->end()->scalarNode('version_format')->defaultValue('%%s?%%s')->end()->scalarNode('json_manifest_path')->defaultNull()->end()->scalarNode('base_path')->defaultValue('')->end()->arrayNode('base_urls')->requiresAtLeastOneElement()->beforeNormalization()->castToArray()->end()->prototype('scalar')->end()->end()->end()->validate()->ifTrue(function ($v) {
            return isset($v['version_strategy']) && isset($v['version']);
        })->thenInvalid('You cannot use both "version_strategy" and "version" at the same time under "assets".')->end()->validate()->ifTrue(function ($v) {
            return isset($v['version_strategy']) && isset($v['json_manifest_path']);
        })->thenInvalid('You cannot use both "version_strategy" and "json_manifest_path" at the same time under "assets".')->end()->validate()->ifTrue(function ($v) {
            return isset($v['version']) && isset($v['json_manifest_path']);
        })->thenInvalid('You cannot use both "version" and "json_manifest_path" at the same time under "assets".')->end()->fixXmlConfig('package')->children()->arrayNode('packages')->normalizeKeys(\false)->useAttributeAsKey('name')->prototype('array')->fixXmlConfig('base_url')->children()->booleanNode('strict_mode')->info('Throw an exception if an entry is missing from the manifest.json')->defaultFalse()->end()->scalarNode('version_strategy')->defaultNull()->end()->scalarNode('version')->beforeNormalization()->ifTrue(fn($v) => '' === $v)->then(fn() => null)->end()->end()->scalarNode('version_format')->defaultNull()->end()->scalarNode('json_manifest_path')->defaultNull()->end()->scalarNode('base_path')->defaultValue('')->end()->arrayNode('base_urls')->requiresAtLeastOneElement()->beforeNormalization()->castToArray()->end()->prototype('scalar')->end()->end()->end()->validate()->ifTrue(function ($v) {
            return isset($v['version_strategy']) && isset($v['version']);
        })->thenInvalid('You cannot use both "version_strategy" and "version" at the same time under "assets" packages.')->end()->validate()->ifTrue(function ($v) {
            return isset($v['version_strategy']) && isset($v['json_manifest_path']);
        })->thenInvalid('You cannot use both "version_strategy" and "json_manifest_path" at the same time under "assets" packages.')->end()->validate()->ifTrue(function ($v) {
            return isset($v['version']) && isset($v['json_manifest_path']);
        })->thenInvalid('You cannot use both "version" and "json_manifest_path" at the same time under "assets" packages.')->end()->end()->end()->end()->end()->end();
    }
    private function addAssetMapperSection(ArrayNodeDefinition $rootNode, callable $enableIfStandalone): void
    {
        $rootNode->children()->arrayNode('asset_mapper')->info('Asset Mapper configuration')->{$enableIfStandalone('symfony/asset-mapper', AssetMapper::class)}()->fixXmlConfig('path')->fixXmlConfig('excluded_pattern')->fixXmlConfig('extension')->fixXmlConfig('importmap_script_attribute')->children()->arrayNode('paths')->info('Directories that hold assets that should be in the mapper. Can be a simple array of an array of ["path/to/assets": "namespace"]')->example(['assets/'])->normalizeKeys(\false)->useAttributeAsKey('namespace')->beforeNormalization()->always()->then(function ($v) {
            $result = [];
            foreach ($v as $key => $item) {
                // "dir" => "namespace"
                if (\is_string($key)) {
                    $result[$key] = $item;
                    continue;
                }
                if (\is_array($item)) {
                    // $item = ["namespace" => "the/namespace", "value" => "the/dir"]
                    $result[$item['value']] = $item['namespace'] ?? '';
                } else {
                    // $item = "the/dir"
                    $result[$item] = '';
                }
            }
            return $result;
        })->end()->prototype('scalar')->end()->end()->arrayNode('excluded_patterns')->info('Array of glob patterns of asset file paths that should not be in the asset mapper')->prototype('scalar')->end()->example(['*/assets/build/*', '*/*_.scss'])->end()->booleanNode('exclude_dotfiles')->info('If true, any files starting with "." will be excluded from the asset mapper')->defaultTrue()->end()->booleanNode('server')->info('If true, a "dev server" will return the assets from the public directory (true in "debug" mode only by default)')->defaultValue($this->debug)->end()->scalarNode('public_prefix')->info('The public path where the assets will be written to (and served from when "server" is true)')->defaultValue('/assets/')->end()->enumNode('missing_import_mode')->values(['strict', 'warn', 'ignore'])->info('Behavior if an asset cannot be found when imported from JavaScript or CSS files - e.g. "import \'./non-existent.js\'". "strict" means an exception is thrown, "warn" means a warning is logged, "ignore" means the import is left as-is.')->defaultValue('warn')->end()->arrayNode('extensions')->info('Key-value pair of file extensions set to their mime type.')->normalizeKeys(\false)->useAttributeAsKey('extension')->example(['.zip' => 'application/zip'])->prototype('scalar')->end()->end()->scalarNode('importmap_path')->info('The path of the importmap.php file.')->defaultValue('%kernel.project_dir%/importmap.php')->end()->scalarNode('importmap_polyfill')->info('The importmap name that will be used to load the polyfill. Set to false to disable.')->validate()->ifTrue()->thenInvalid('Invalid "importmap_polyfill" value. Must be either an importmap name or false.')->end()->defaultValue('es-module-shims')->end()->arrayNode('importmap_script_attributes')->info('Key-value pair of attributes to add to script tags output for the importmap.')->normalizeKeys(\false)->useAttributeAsKey('key')->example(['data-turbo-track' => 'reload'])->prototype('scalar')->end()->end()->scalarNode('vendor_dir')->info('The directory to store JavaScript vendors.')->defaultValue('%kernel.project_dir%/assets/vendor')->end()->scalarNode('provider')->setDeprecated('symfony/framework-bundle', '6.4', 'Option "%node%" at "%path%" is deprecated and does nothing. Remove it.')->end()->end()->end()->end();
    }
    private function addTranslatorSection(ArrayNodeDefinition $rootNode, callable $enableIfStandalone): void
    {
        $rootNode->children()->arrayNode('translator')->info('translator configuration')->{$enableIfStandalone('symfony/translation', Translator::class)}()->fixXmlConfig('fallback')->fixXmlConfig('path')->fixXmlConfig('provider')->children()->arrayNode('fallbacks')->info('Defaults to the value of "default_locale".')->beforeNormalization()->ifString()->then(fn($v) => [$v])->end()->prototype('scalar')->end()->defaultValue([])->end()->booleanNode('logging')->defaultValue(\false)->end()->scalarNode('formatter')->defaultValue('translator.formatter.default')->end()->scalarNode('cache_dir')->defaultValue('%kernel.cache_dir%/translations')->end()->scalarNode('default_path')->info('The default path used to load translations')->defaultValue('%kernel.project_dir%/translations')->end()->arrayNode('paths')->prototype('scalar')->end()->end()->arrayNode('pseudo_localization')->canBeEnabled()->fixXmlConfig('localizable_html_attribute')->children()->booleanNode('accents')->defaultTrue()->end()->floatNode('expansion_factor')->min(1.0)->defaultValue(1.0)->end()->booleanNode('brackets')->defaultTrue()->end()->booleanNode('parse_html')->defaultFalse()->end()->arrayNode('localizable_html_attributes')->prototype('scalar')->end()->end()->end()->end()->arrayNode('providers')->info('Translation providers you can read/write your translations from')->useAttributeAsKey('name')->prototype('array')->fixXmlConfig('domain')->fixXmlConfig('locale')->children()->scalarNode('dsn')->end()->arrayNode('domains')->prototype('scalar')->end()->defaultValue([])->end()->arrayNode('locales')->prototype('scalar')->end()->defaultValue([])->info('If not set, all locales listed under framework.enabled_locales are used.')->end()->end()->end()->defaultValue([])->end()->end()->end()->end();
    }
    private function addValidationSection(ArrayNodeDefinition $rootNode, callable $enableIfStandalone): void
    {
        $rootNode->validate()->always(function ($v) {
            if ($v['validation']['enabled'] && !\array_key_exists('email_validation_mode', $v['validation'])) {
                trigger_deprecation('symfony/framework-bundle', '6.4', 'Not setting the "framework.validation.email_validation_mode" config option is deprecated. It will default to "html5" in 7.0.');
            }
            return $v;
        })->end()->children()->arrayNode('validation')->beforeNormalization()->ifTrue(fn($v) => isset($v['enable_annotations']))->then(function ($v) {
            trigger_deprecation('symfony/framework-bundle', '6.4', 'Option "enable_annotations" at "framework.validation" is deprecated. Use the "enable_attributes" option instead.');
            if (isset($v['enable_attributes'])) {
                throw new LogicException('The "enable_annotations" and "enable_attributes" options at path "framework.validation" must not be both set. Only the "enable_attributes" option must be used.');
            }
            $v['enable_attributes'] = $v['enable_annotations'];
            return $v;
        })->end()->info('validation configuration')->{$enableIfStandalone('symfony/validator', Validation::class)}()->children()->scalarNode('cache')->end()->booleanNode('enable_annotations')->end()->booleanNode('enable_attributes')->{class_exists(FullStack::class) ? 'defaultFalse' : 'defaultTrue'}()->end()->arrayNode('static_method')->defaultValue(['loadValidatorMetadata'])->prototype('scalar')->end()->treatFalseLike([])->validate()->castToArray()->end()->end()->scalarNode('translation_domain')->defaultValue('validators')->end()->enumNode('email_validation_mode')->values(['html5', 'html5-allow-no-tld', 'strict', 'loose'])->end()->arrayNode('mapping')->addDefaultsIfNotSet()->fixXmlConfig('path')->children()->arrayNode('paths')->prototype('scalar')->end()->end()->end()->end()->arrayNode('not_compromised_password')->canBeDisabled()->children()->booleanNode('enabled')->defaultTrue()->info('When disabled, compromised passwords will be accepted as valid.')->end()->scalarNode('endpoint')->defaultNull()->info('API endpoint for the NotCompromisedPassword Validator.')->end()->end()->end()->arrayNode('auto_mapping')->info('A collection of namespaces for which auto-mapping will be enabled by default, or null to opt-in with the EnableAutoMapping constraint.')->example(['App\Entity\\' => [], 'App\WithSpecificLoaders\\' => ['validator.property_info_loader']])->useAttributeAsKey('namespace')->normalizeKeys(\false)->beforeNormalization()->ifArray()->then(function (array $values): array {
            foreach ($values as $k => $v) {
                if (isset($v['service'])) {
                    continue;
                }
                if (isset($v['namespace'])) {
                    $values[$k]['services'] = [];
                    continue;
                }
                if (!\is_array($v)) {
                    $values[$v]['services'] = [];
                    unset($values[$k]);
                    continue;
                }
                $tmp = $v;
                unset($values[$k]);
                $values[$k]['services'] = $tmp;
            }
            return $values;
        })->end()->arrayPrototype()->fixXmlConfig('service')->children()->arrayNode('services')->prototype('scalar')->end()->end()->end()->end()->end()->end()->end()->end();
    }
    private function addAnnotationsSection(ArrayNodeDefinition $rootNode, callable $willBeAvailable): void
    {
        $rootNode->children()->arrayNode('annotations')->info('annotation configuration')->{$willBeAvailable('doctrine/annotations', Annotation::class) ? 'canBeDisabled' : 'canBeEnabled'}()->children()->enumNode('cache')->values(['none', 'php_array', 'file'])->defaultValue('php_array')->end()->scalarNode('file_cache_dir')->defaultValue('%kernel.cache_dir%/annotations')->end()->booleanNode('debug')->defaultValue($this->debug)->end()->end()->end()->end();
    }
    private function addSerializerSection(ArrayNodeDefinition $rootNode, callable $enableIfStandalone): void
    {
        $rootNode->children()->arrayNode('serializer')->beforeNormalization()->ifTrue(fn($v) => isset($v['enable_annotations']))->then(function ($v) {
            trigger_deprecation('symfony/framework-bundle', '6.4', 'Option "enable_annotations" at "framework.serializer" is deprecated. Use the "enable_attributes" option instead.');
            if (isset($v['enable_attributes'])) {
                throw new LogicException('The "enable_annotations" and "enable_attributes" options at path "framework.serializer" must not be both set. Only the "enable_attributes" option must be used.');
            }
            $v['enable_attributes'] = $v['enable_annotations'];
            return $v;
        })->end()->info('serializer configuration')->{$enableIfStandalone('symfony/serializer', Serializer::class)}()->children()->booleanNode('enable_annotations')->end()->booleanNode('enable_attributes')->{class_exists(FullStack::class) ? 'defaultFalse' : 'defaultTrue'}()->end()->scalarNode('name_converter')->end()->scalarNode('circular_reference_handler')->end()->scalarNode('max_depth_handler')->end()->arrayNode('mapping')->addDefaultsIfNotSet()->fixXmlConfig('path')->children()->arrayNode('paths')->prototype('scalar')->end()->end()->end()->end()->arrayNode('default_context')->useAttributeAsKey('key')->normalizeKeys(\false)->validate()->ifTrue(fn() => $this->debug && class_exists(JsonParser::class))->then(fn(array $v) => $v + [JsonDecode::DETAILED_ERROR_MESSAGES => \true])->end()->defaultValue([])->prototype('variable')->end()->end()->end()->end()->end();
    }
    private function addPropertyAccessSection(ArrayNodeDefinition $rootNode, callable $willBeAvailable): void
    {
        $rootNode->children()->arrayNode('property_access')->addDefaultsIfNotSet()->info('Property access configuration')->{$willBeAvailable('symfony/property-access', PropertyAccessor::class) ? 'canBeDisabled' : 'canBeEnabled'}()->children()->booleanNode('magic_call')->defaultFalse()->end()->booleanNode('magic_get')->defaultTrue()->end()->booleanNode('magic_set')->defaultTrue()->end()->booleanNode('throw_exception_on_invalid_index')->defaultFalse()->end()->booleanNode('throw_exception_on_invalid_property_path')->defaultTrue()->end()->end()->end()->end();
    }
    private function addPropertyInfoSection(ArrayNodeDefinition $rootNode, callable $enableIfStandalone): void
    {
        $rootNode->children()->arrayNode('property_info')->info('Property info configuration')->{$enableIfStandalone('symfony/property-info', PropertyInfoExtractorInterface::class)}()->end()->end();
    }
    private function addCacheSection(ArrayNodeDefinition $rootNode, callable $willBeAvailable): void
    {
        $rootNode->children()->arrayNode('cache')->info('Cache configuration')->addDefaultsIfNotSet()->fixXmlConfig('pool')->children()->scalarNode('prefix_seed')->info('Used to namespace cache keys when using several apps with the same shared backend')->defaultValue('_%kernel.project_dir%.%kernel.container_class%')->example('my-application-name/%kernel.environment%')->end()->scalarNode('app')->info('App related cache pools configuration')->defaultValue('cache.adapter.filesystem')->end()->scalarNode('system')->info('System related cache pools configuration')->defaultValue('cache.adapter.system')->end()->scalarNode('directory')->defaultValue('%kernel.cache_dir%/pools/app')->end()->scalarNode('default_psr6_provider')->end()->scalarNode('default_redis_provider')->defaultValue('redis://localhost')->end()->scalarNode('default_memcached_provider')->defaultValue('memcached://localhost')->end()->scalarNode('default_doctrine_dbal_provider')->defaultValue('database_connection')->end()->scalarNode('default_pdo_provider')->defaultValue($willBeAvailable('doctrine/dbal', Connection::class) && class_exists(DoctrineAdapter::class) ? 'database_connection' : null)->end()->arrayNode('pools')->useAttributeAsKey('name')->prototype('array')->fixXmlConfig('adapter')->beforeNormalization()->ifTrue(fn($v) => isset($v['provider']) && \is_array($v['adapters'] ?? $v['adapter'] ?? null) && 1 < \count($v['adapters'] ?? $v['adapter']))->thenInvalid('Pool cannot have a "provider" while more than one adapter is defined')->end()->children()->arrayNode('adapters')->performNoDeepMerging()->info('One or more adapters to chain for creating the pool, defaults to "cache.app".')->beforeNormalization()->castToArray()->end()->beforeNormalization()->always()->then(function ($values) {
            if ([0] === array_keys($values) && \is_array($values[0])) {
                return $values[0];
            }
            $adapters = [];
            foreach ($values as $k => $v) {
                if (\is_int($k) && \is_string($v)) {
                    $adapters[] = $v;
                } elseif (!\is_array($v)) {
                    $adapters[$k] = $v;
                } elseif (isset($v['provider'])) {
                    $adapters[$v['provider']] = $v['name'] ?? $v;
                } else {
                    $adapters[] = $v['name'] ?? $v;
                }
            }
            return $adapters;
        })->end()->prototype('scalar')->end()->end()->scalarNode('tags')->defaultNull()->end()->booleanNode('public')->defaultFalse()->end()->scalarNode('default_lifetime')->info('Default lifetime of the pool')->example('"300" for 5 minutes expressed in seconds, "PT5M" for five minutes expressed as ISO 8601 time interval, or "5 minutes" as a date expression')->end()->scalarNode('provider')->info('Overwrite the setting from the default provider for this adapter.')->end()->scalarNode('early_expiration_message_bus')->example('"messenger.default_bus" to send early expiration events to the default Messenger bus.')->end()->scalarNode('clearer')->end()->end()->end()->validate()->ifTrue(fn($v) => isset($v['cache.app']) || isset($v['cache.system']))->thenInvalid('"cache.app" and "cache.system" are reserved names')->end()->end()->end()->end()->end();
    }
    private function addPhpErrorsSection(ArrayNodeDefinition $rootNode): void
    {
        $rootNode->validate()->always(function (array $v): array {
            if (!\array_key_exists('log', $v['php_errors'])) {
                trigger_deprecation('symfony/framework-bundle', '6.4', 'Not setting the "framework.php_errors.log" config option is deprecated. It will default to "true" in 7.0.');
                $v['php_errors']['log'] = $this->debug;
            }
            return $v;
        })->end()->children()->arrayNode('php_errors')->info('PHP errors handling configuration')->addDefaultsIfNotSet()->children()->variableNode('log')->info('Use the application logger instead of the PHP logger for logging PHP errors.')->example('"true" to use the default configuration: log all errors. "false" to disable. An integer bit field of E_* constants, or an array mapping E_* constants to log levels.')->treatNullLike($this->debug)->beforeNormalization()->ifArray()->then(function (array $v): array {
            if (!($v[0]['type'] ?? \false)) {
                return $v;
            }
            // Fix XML normalization
            $ret = [];
            foreach ($v as ['type' => $type, 'logLevel' => $logLevel]) {
                $ret[$type] = $logLevel;
            }
            return $ret;
        })->end()->validate()->ifTrue(fn($v) => !(\is_int($v) || \is_bool($v) || \is_array($v)))->thenInvalid('The "php_errors.log" parameter should be either an integer, a boolean, or an array')->end()->end()->booleanNode('throw')->info('Throw PHP errors as \ErrorException instances.')->defaultValue($this->debug)->treatNullLike($this->debug)->end()->end()->end()->end();
    }
    private function addExceptionsSection(ArrayNodeDefinition $rootNode): void
    {
        $logLevels = (new \ReflectionClass(LogLevel::class))->getConstants();
        $rootNode->fixXmlConfig('exception')->children()->arrayNode('exceptions')->info('Exception handling configuration')->useAttributeAsKey('class')->beforeNormalization()->ifArray()->then(function (array $v): array {
            if (!\array_key_exists('exception', $v)) {
                return $v;
            }
            trigger_deprecation('symfony/framework-bundle', '6.3', '"framework:exceptions" tag is deprecated. Unwrap it and replace your "framework:exception" tags\' "name" attribute by "class".');
            $v = $v['exception'];
            unset($v['exception']);
            foreach ($v as &$exception) {
                $exception['class'] = $exception['name'];
                unset($exception['name']);
            }
            return $v;
        })->end()->prototype('array')->children()->scalarNode('log_level')->info('The level of log message. Null to let Symfony decide.')->validate()->ifTrue(fn($v) => null !== $v && !\in_array($v, $logLevels, \true))->thenInvalid(\sprintf('The log level is not valid. Pick one among "%s".', implode('", "', $logLevels)))->end()->defaultNull()->end()->scalarNode('status_code')->info('The status code of the response. Null or 0 to let Symfony decide.')->beforeNormalization()->ifTrue(fn($v) => 0 === $v)->then(fn($v) => null)->end()->validate()->ifTrue(fn($v) => null !== $v && ($v < 100 || $v > 599))->thenInvalid('The status code is not valid. Pick a value between 100 and 599.')->end()->defaultNull()->end()->end()->end()->end()->end();
    }
    private function addLockSection(ArrayNodeDefinition $rootNode, callable $enableIfStandalone): void
    {
        $rootNode->children()->arrayNode('lock')->info('Lock configuration')->{$enableIfStandalone('symfony/lock', Lock::class)}()->beforeNormalization()->ifString()->then(fn($v) => ['enabled' => \true, 'resources' => $v])->end()->beforeNormalization()->ifTrue(fn($v) => \is_array($v) && !isset($v['enabled']))->then(fn($v) => $v + ['enabled' => \true])->end()->beforeNormalization()->ifTrue(fn($v) => \is_array($v) && !isset($v['resources']) && !isset($v['resource']))->then(function ($v) {
            $e = $v['enabled'];
            unset($v['enabled']);
            return ['enabled' => $e, 'resources' => $v];
        })->end()->addDefaultsIfNotSet()->validate()->ifTrue(fn($config) => $config['enabled'] && !$config['resources'])->thenInvalid('At least one resource must be defined.')->end()->fixXmlConfig('resource')->children()->arrayNode('resources')->normalizeKeys(\false)->useAttributeAsKey('name')->defaultValue(['default' => [class_exists(SemaphoreStore::class) && SemaphoreStore::isSupported() ? 'semaphore' : 'flock']])->beforeNormalization()->ifString()->then(fn($v) => ['default' => $v])->end()->beforeNormalization()->ifTrue(fn($v) => \is_array($v) && array_is_list($v))->then(function ($v) {
            $resources = [];
            foreach ($v as $resource) {
                $resources[] = \is_array($resource) && isset($resource['name']) ? [$resource['name'] => $resource['value']] : ['default' => $resource];
            }
            return array_merge_recursive([], ...$resources);
        })->end()->prototype('array')->performNoDeepMerging()->beforeNormalization()->ifString()->then(fn($v) => [$v])->end()->prototype('scalar')->end()->end()->end()->end()->end()->end();
    }
    private function addSemaphoreSection(ArrayNodeDefinition $rootNode, callable $enableIfStandalone): void
    {
        $rootNode->children()->arrayNode('semaphore')->info('Semaphore configuration')->{$enableIfStandalone('symfony/semaphore', Semaphore::class)}()->beforeNormalization()->ifString()->then(fn($v) => ['enabled' => \true, 'resources' => $v])->end()->beforeNormalization()->ifTrue(fn($v) => \is_array($v) && !isset($v['enabled']))->then(fn($v) => $v + ['enabled' => \true])->end()->beforeNormalization()->ifTrue(fn($v) => \is_array($v) && !isset($v['resources']) && !isset($v['resource']))->then(function ($v) {
            $e = $v['enabled'];
            unset($v['enabled']);
            return ['enabled' => $e, 'resources' => $v];
        })->end()->addDefaultsIfNotSet()->fixXmlConfig('resource')->children()->arrayNode('resources')->normalizeKeys(\false)->useAttributeAsKey('name')->requiresAtLeastOneElement()->beforeNormalization()->ifString()->then(fn($v) => ['default' => $v])->end()->beforeNormalization()->ifTrue(fn($v) => \is_array($v) && array_is_list($v))->then(function ($v) {
            $resources = [];
            foreach ($v as $resource) {
                $resources[] = \is_array($resource) && isset($resource['name']) ? [$resource['name'] => $resource['value']] : ['default' => $resource];
            }
            return array_merge_recursive([], ...$resources);
        })->end()->prototype('scalar')->end()->end()->end()->end()->end();
    }
    private function addWebLinkSection(ArrayNodeDefinition $rootNode, callable $enableIfStandalone): void
    {
        $rootNode->children()->arrayNode('web_link')->info('web links configuration')->{$enableIfStandalone('symfony/weblink', HttpHeaderSerializer::class)}()->end()->end();
    }
    private function addMessengerSection(ArrayNodeDefinition $rootNode, callable $enableIfStandalone): void
    {
        $rootNode->children()->arrayNode('messenger')->info('Messenger configuration')->{$enableIfStandalone('symfony/messenger', MessageBusInterface::class)}()->fixXmlConfig('transport')->fixXmlConfig('bus', 'buses')->validate()->ifTrue(fn($v) => isset($v['buses']) && \count($v['buses']) > 1 && null === $v['default_bus'])->thenInvalid('You must specify the "default_bus" if you define more than one bus.')->end()->validate()->ifTrue(fn($v) => isset($v['buses']) && null !== $v['default_bus'] && !isset($v['buses'][$v['default_bus']]))->then(fn($v) => throw new InvalidConfigurationException(\sprintf('The specified default bus "%s" is not configured. Available buses are "%s".', $v['default_bus'], implode('", "', array_keys($v['buses'])))))->end()->children()->arrayNode('routing')->normalizeKeys(\false)->useAttributeAsKey('message_class')->beforeNormalization()->always()->then(function ($config) {
            if (!\is_array($config)) {
                return [];
            }
            // If XML config with only one routing attribute
            if (2 === \count($config) && isset($config['message-class']) && isset($config['sender'])) {
                $config = [0 => $config];
            }
            $newConfig = [];
            foreach ($config as $k => $v) {
                if (!\is_int($k)) {
                    $newConfig[$k] = ['senders' => $v['senders'] ?? (\is_array($v) ? array_values($v) : [$v])];
                } else {
                    $newConfig[$v['message-class']]['senders'] = array_map(function ($a) {
                        return \is_string($a) ? $a : $a['service'];
                    }, array_values($v['sender']));
                }
            }
            return $newConfig;
        })->end()->prototype('array')->performNoDeepMerging()->children()->arrayNode('senders')->requiresAtLeastOneElement()->prototype('scalar')->end()->end()->end()->end()->end()->arrayNode('serializer')->addDefaultsIfNotSet()->children()->scalarNode('default_serializer')->defaultValue('messenger.transport.native_php_serializer')->info('Service id to use as the default serializer for the transports.')->end()->arrayNode('symfony_serializer')->addDefaultsIfNotSet()->children()->scalarNode('format')->defaultValue('json')->info('Serialization format for the messenger.transport.symfony_serializer service (which is not the serializer used by default).')->end()->arrayNode('context')->normalizeKeys(\false)->useAttributeAsKey('name')->defaultValue([])->info('Context array for the messenger.transport.symfony_serializer service (which is not the serializer used by default).')->prototype('variable')->end()->end()->end()->end()->end()->end()->arrayNode('transports')->normalizeKeys(\false)->useAttributeAsKey('name')->arrayPrototype()->beforeNormalization()->ifString()->then(function (string $dsn) {
            return ['dsn' => $dsn];
        })->end()->fixXmlConfig('option')->children()->scalarNode('dsn')->end()->scalarNode('serializer')->defaultNull()->info('Service id of a custom serializer to use.')->end()->arrayNode('options')->useAttributeAsKey('key')->normalizeKeys(\false)->defaultValue([])->prototype('variable')->end()->end()->scalarNode('failure_transport')->defaultNull()->info('Transport name to send failed messages to (after all retries have failed).')->end()->arrayNode('retry_strategy')->addDefaultsIfNotSet()->beforeNormalization()->always(function ($v) {
            if (isset($v['service']) && (isset($v['max_retries']) || isset($v['delay']) || isset($v['multiplier']) || isset($v['max_delay']))) {
                throw new \InvalidArgumentException('The "service" cannot be used along with the other "retry_strategy" options.');
            }
            return $v;
        })->end()->children()->scalarNode('service')->defaultNull()->info('Service id to override the retry strategy entirely')->end()->integerNode('max_retries')->defaultValue(3)->min(0)->end()->integerNode('delay')->defaultValue(1000)->min(0)->info('Time in ms to delay (or the initial value when multiplier is used)')->end()->floatNode('multiplier')->defaultValue(2)->min(1)->info('If greater than 1, delay will grow exponentially for each retry: this delay = (delay * (multiple ^ retries))')->end()->integerNode('max_delay')->defaultValue(0)->min(0)->info('Max time in ms that a retry should ever be delayed (0 = infinite)')->end()->end()->end()->scalarNode('rate_limiter')->defaultNull()->info('Rate limiter name to use when processing messages')->end()->end()->end()->end()->scalarNode('failure_transport')->defaultNull()->info('Transport name to send failed messages to (after all retries have failed).')->end()->booleanNode('reset_on_message')->defaultTrue()->info('Reset container services after each message.')->setDeprecated('symfony/framework-bundle', '6.1', 'Option "%node%" at "%path%" is deprecated. It does nothing and will be removed in version 7.0.')->validate()->ifTrue(fn($v) => \true !== $v)->thenInvalid('The "framework.messenger.reset_on_message" configuration option can be set to "true" only. To prevent services resetting after each message you can set the "--no-reset" option in "messenger:consume" command.')->end()->end()->arrayNode('stop_worker_on_signals')->defaultValue([])->info('A list of signals that should stop the worker; defaults to SIGTERM and SIGINT.')->integerPrototype()->end()->end()->scalarNode('default_bus')->defaultNull()->end()->arrayNode('buses')->defaultValue(['messenger.bus.default' => ['default_middleware' => ['enabled' => \true, 'allow_no_handlers' => \false, 'allow_no_senders' => \true], 'middleware' => []]])->normalizeKeys(\false)->useAttributeAsKey('name')->arrayPrototype()->addDefaultsIfNotSet()->children()->arrayNode('default_middleware')->beforeNormalization()->ifTrue(fn($v) => \is_string($v) || \is_bool($v))->then(fn($v) => ['enabled' => 'allow_no_handlers' === $v ? \true : $v, 'allow_no_handlers' => 'allow_no_handlers' === $v, 'allow_no_senders' => \true])->end()->canBeDisabled()->children()->booleanNode('allow_no_handlers')->defaultFalse()->end()->booleanNode('allow_no_senders')->defaultTrue()->end()->end()->end()->arrayNode('middleware')->performNoDeepMerging()->beforeNormalization()->ifTrue(fn($v) => \is_string($v) || \is_array($v) && !\is_int(key($v)))->then(fn($v) => [$v])->end()->defaultValue([])->arrayPrototype()->beforeNormalization()->always()->then(function ($middleware): array {
            if (!\is_array($middleware)) {
                return ['id' => $middleware];
            }
            if (isset($middleware['id'])) {
                return $middleware;
            }
            if (1 < \count($middleware)) {
                throw new \InvalidArgumentException('Invalid middleware at path "framework.messenger": a map with a single factory id as key and its arguments as value was expected, ' . json_encode($middleware) . ' given.');
            }
            return ['id' => key($middleware), 'arguments' => current($middleware)];
        })->end()->fixXmlConfig('argument')->children()->scalarNode('id')->isRequired()->cannotBeEmpty()->end()->arrayNode('arguments')->normalizeKeys(\false)->defaultValue([])->prototype('variable')->end()->end()->end()->end()->end()->end()->end()->end()->end()->end();
    }
    private function addSchedulerSection(ArrayNodeDefinition $rootNode, callable $enableIfStandalone): void
    {
        $rootNode->children()->arrayNode('scheduler')->info('Scheduler configuration')->{$enableIfStandalone('symfony/scheduler', Schedule::class)}()->end()->end();
    }
    private function addRobotsIndexSection(ArrayNodeDefinition $rootNode): void
    {
        $rootNode->children()->booleanNode('disallow_search_engine_index')->info('Enabled by default when debug is enabled.')->defaultValue($this->debug)->treatNullLike($this->debug)->end()->end();
    }
    private function addHttpClientSection(ArrayNodeDefinition $rootNode, callable $enableIfStandalone): void
    {
        $rootNode->children()->arrayNode('http_client')->info('HTTP Client configuration')->{$enableIfStandalone('symfony/http-client', HttpClient::class)}()->fixXmlConfig('scoped_client')->beforeNormalization()->always(function ($config) {
            if (empty($config['scoped_clients']) || !\is_array($config['default_options']['retry_failed'] ?? null)) {
                return $config;
            }
            foreach ($config['scoped_clients'] as &$scopedConfig) {
                if (!isset($scopedConfig['retry_failed']) || \true === $scopedConfig['retry_failed']) {
                    $scopedConfig['retry_failed'] = $config['default_options']['retry_failed'];
                    continue;
                }
                if (\is_array($scopedConfig['retry_failed'])) {
                    $scopedConfig['retry_failed'] += $config['default_options']['retry_failed'];
                }
            }
            return $config;
        })->end()->children()->integerNode('max_host_connections')->info('The maximum number of connections to a single host.')->end()->arrayNode('default_options')->fixXmlConfig('header')->children()->arrayNode('headers')->info('Associative array: header => value(s).')->useAttributeAsKey('name')->normalizeKeys(\false)->variablePrototype()->end()->end()->arrayNode('vars')->info('Associative array: the default vars used to expand the templated URI.')->useAttributeAsKey('name')->normalizeKeys(\false)->variablePrototype()->end()->end()->integerNode('max_redirects')->info('The maximum number of redirects to follow.')->end()->scalarNode('http_version')->info('The default HTTP version, typically 1.1 or 2.0, leave to null for the best version.')->end()->arrayNode('resolve')->info('Associative array: domain => IP.')->useAttributeAsKey('host')->beforeNormalization()->always(function ($config) {
            if (!\is_array($config)) {
                return [];
            }
            if (!isset($config['host'], $config['value']) || \count($config) > 2) {
                return $config;
            }
            return [$config['host'] => $config['value']];
        })->end()->normalizeKeys(\false)->scalarPrototype()->end()->end()->scalarNode('proxy')->info('The URL of the proxy to pass requests through or null for automatic detection.')->end()->scalarNode('no_proxy')->info('A comma separated list of hosts that do not require a proxy to be reached.')->end()->floatNode('timeout')->info('The idle timeout, defaults to the "default_socket_timeout" ini parameter.')->end()->floatNode('max_duration')->info('The maximum execution time for the request+response as a whole.')->end()->scalarNode('bindto')->info('A network interface name, IP address, a host name or a UNIX socket to bind to.')->end()->booleanNode('verify_peer')->info('Indicates if the peer should be verified in a TLS context.')->end()->booleanNode('verify_host')->info('Indicates if the host should exist as a certificate common name.')->end()->scalarNode('cafile')->info('A certificate authority file.')->end()->scalarNode('capath')->info('A directory that contains multiple certificate authority files.')->end()->scalarNode('local_cert')->info('A PEM formatted certificate file.')->end()->scalarNode('local_pk')->info('A private key file.')->end()->scalarNode('passphrase')->info('The passphrase used to encrypt the "local_pk" file.')->end()->scalarNode('ciphers')->info('A list of TLS ciphers separated by colons, commas or spaces (e.g. "RC3-SHA:TLS13-AES-128-GCM-SHA256"...)')->end()->arrayNode('peer_fingerprint')->info('Associative array: hashing algorithm => hash(es).')->normalizeKeys(\false)->children()->variableNode('sha1')->end()->variableNode('pin-sha256')->end()->variableNode('md5')->end()->end()->end()->scalarNode('crypto_method')->info('The minimum version of TLS to accept; must be one of STREAM_CRYPTO_METHOD_TLSv*_CLIENT constants.')->end()->arrayNode('extra')->info('Extra options for specific HTTP client')->useAttributeAsKey('name')->normalizeKeys(\false)->variablePrototype()->end()->end()->append($this->createHttpClientRetrySection())->end()->end()->scalarNode('mock_response_factory')->info('The id of the service that should generate mock responses. It should be either an invokable or an iterable.')->end()->arrayNode('scoped_clients')->useAttributeAsKey('name')->normalizeKeys(\false)->arrayPrototype()->fixXmlConfig('header')->beforeNormalization()->always()->then(function ($config) {
            if (!class_exists(HttpClient::class)) {
                throw new LogicException('HttpClient support cannot be enabled as the component is not installed. Try running "composer require symfony/http-client".');
            }
            return \is_array($config) ? $config : ['base_uri' => $config];
        })->end()->validate()->ifTrue(fn($v) => !isset($v['scope']) && !isset($v['base_uri']))->thenInvalid('Either "scope" or "base_uri" should be defined.')->end()->validate()->ifTrue(fn($v) => !empty($v['query']) && !isset($v['base_uri']))->thenInvalid('"query" applies to "base_uri" but no base URI is defined.')->end()->children()->scalarNode('scope')->info('The regular expression that the request URL must match before adding the other options. When none is provided, the base URI is used instead.')->cannotBeEmpty()->end()->scalarNode('base_uri')->info('The URI to resolve relative URLs, following rules in RFC 3985, section 2.')->cannotBeEmpty()->end()->scalarNode('auth_basic')->info('An HTTP Basic authentication "username:password".')->end()->scalarNode('auth_bearer')->info('A token enabling HTTP Bearer authorization.')->end()->scalarNode('auth_ntlm')->info('A "username:password" pair to use Microsoft NTLM authentication (requires the cURL extension).')->end()->arrayNode('query')->info('Associative array of query string values merged with the base URI.')->useAttributeAsKey('key')->beforeNormalization()->always(function ($config) {
            if (!\is_array($config)) {
                return [];
            }
            if (!isset($config['key'], $config['value']) || \count($config) > 2) {
                return $config;
            }
            return [$config['key'] => $config['value']];
        })->end()->normalizeKeys(\false)->scalarPrototype()->end()->end()->arrayNode('headers')->info('Associative array: header => value(s).')->useAttributeAsKey('name')->normalizeKeys(\false)->variablePrototype()->end()->end()->integerNode('max_redirects')->info('The maximum number of redirects to follow.')->end()->scalarNode('http_version')->info('The default HTTP version, typically 1.1 or 2.0, leave to null for the best version.')->end()->arrayNode('resolve')->info('Associative array: domain => IP.')->useAttributeAsKey('host')->beforeNormalization()->always(function ($config) {
            if (!\is_array($config)) {
                return [];
            }
            if (!isset($config['host'], $config['value']) || \count($config) > 2) {
                return $config;
            }
            return [$config['host'] => $config['value']];
        })->end()->normalizeKeys(\false)->scalarPrototype()->end()->end()->scalarNode('proxy')->info('The URL of the proxy to pass requests through or null for automatic detection.')->end()->scalarNode('no_proxy')->info('A comma separated list of hosts that do not require a proxy to be reached.')->end()->floatNode('timeout')->info('The idle timeout, defaults to the "default_socket_timeout" ini parameter.')->end()->floatNode('max_duration')->info('The maximum execution time for the request+response as a whole.')->end()->scalarNode('bindto')->info('A network interface name, IP address, a host name or a UNIX socket to bind to.')->end()->booleanNode('verify_peer')->info('Indicates if the peer should be verified in a TLS context.')->end()->booleanNode('verify_host')->info('Indicates if the host should exist as a certificate common name.')->end()->scalarNode('cafile')->info('A certificate authority file.')->end()->scalarNode('capath')->info('A directory that contains multiple certificate authority files.')->end()->scalarNode('local_cert')->info('A PEM formatted certificate file.')->end()->scalarNode('local_pk')->info('A private key file.')->end()->scalarNode('passphrase')->info('The passphrase used to encrypt the "local_pk" file.')->end()->scalarNode('ciphers')->info('A list of TLS ciphers separated by colons, commas or spaces (e.g. "RC3-SHA:TLS13-AES-128-GCM-SHA256"...)')->end()->arrayNode('peer_fingerprint')->info('Associative array: hashing algorithm => hash(es).')->normalizeKeys(\false)->children()->variableNode('sha1')->end()->variableNode('pin-sha256')->end()->variableNode('md5')->end()->end()->end()->scalarNode('crypto_method')->info('The minimum version of TLS to accept; must be one of STREAM_CRYPTO_METHOD_TLSv*_CLIENT constants.')->end()->arrayNode('extra')->info('Extra options for specific HTTP client')->useAttributeAsKey('name')->normalizeKeys(\false)->variablePrototype()->end()->end()->append($this->createHttpClientRetrySection())->end()->end()->end()->end()->end()->end();
    }
    private function createHttpClientRetrySection(): ArrayNodeDefinition
    {
        $root = new NodeBuilder();
        return $root->arrayNode('retry_failed')->fixXmlConfig('http_code')->canBeEnabled()->addDefaultsIfNotSet()->beforeNormalization()->always(function ($v) {
            if (isset($v['retry_strategy']) && (isset($v['http_codes']) || isset($v['delay']) || isset($v['multiplier']) || isset($v['max_delay']) || isset($v['jitter']))) {
                throw new \InvalidArgumentException('The "retry_strategy" option cannot be used along with the "http_codes", "delay", "multiplier", "max_delay" or "jitter" options.');
            }
            return $v;
        })->end()->children()->scalarNode('retry_strategy')->defaultNull()->info('service id to override the retry strategy')->end()->arrayNode('http_codes')->performNoDeepMerging()->beforeNormalization()->ifArray()->then(static function ($v) {
            $list = [];
            foreach ($v as $key => $val) {
                if (is_numeric($val)) {
                    $list[] = ['code' => $val];
                } elseif (\is_array($val)) {
                    if (isset($val['code']) || isset($val['methods'])) {
                        $list[] = $val;
                    } else {
                        $list[] = ['code' => $key, 'methods' => $val];
                    }
                } elseif (\true === $val || null === $val) {
                    $list[] = ['code' => $key];
                }
            }
            return $list;
        })->end()->useAttributeAsKey('code')->arrayPrototype()->fixXmlConfig('method')->children()->integerNode('code')->end()->arrayNode('methods')->beforeNormalization()->ifArray()->then(fn($v) => array_map('strtoupper', $v))->end()->prototype('scalar')->end()->info('A list of HTTP methods that triggers a retry for this status code. When empty, all methods are retried')->end()->end()->end()->info('A list of HTTP status code that triggers a retry')->end()->integerNode('max_retries')->defaultValue(3)->min(0)->end()->integerNode('delay')->defaultValue(1000)->min(0)->info('Time in ms to delay (or the initial value when multiplier is used)')->end()->floatNode('multiplier')->defaultValue(2)->min(1)->info('If greater than 1, delay will grow exponentially for each retry: delay * (multiple ^ retries)')->end()->integerNode('max_delay')->defaultValue(0)->min(0)->info('Max time in ms that a retry should ever be delayed (0 = infinite)')->end()->floatNode('jitter')->defaultValue(0.1)->min(0)->max(1)->info('Randomness in percent (between 0 and 1) to apply to the delay')->end()->end();
    }
    private function addMailerSection(ArrayNodeDefinition $rootNode, callable $enableIfStandalone): void
    {
        $rootNode->children()->arrayNode('mailer')->info('Mailer configuration')->{$enableIfStandalone('symfony/mailer', Mailer::class)}()->validate()->ifTrue(fn($v) => isset($v['dsn']) && \count($v['transports']))->thenInvalid('"dsn" and "transports" cannot be used together.')->end()->fixXmlConfig('transport')->fixXmlConfig('header')->children()->scalarNode('message_bus')->defaultNull()->info('The message bus to use. Defaults to the default bus if the Messenger component is installed.')->end()->scalarNode('dsn')->defaultNull()->end()->arrayNode('transports')->useAttributeAsKey('name')->prototype('scalar')->end()->end()->arrayNode('envelope')->info('Mailer Envelope configuration')->fixXmlConfig('recipient')->children()->scalarNode('sender')->end()->arrayNode('recipients')->performNoDeepMerging()->beforeNormalization()->ifArray()->then(fn($v) => array_filter(array_values($v)))->end()->prototype('scalar')->end()->end()->end()->end()->arrayNode('headers')->normalizeKeys(\false)->useAttributeAsKey('name')->prototype('array')->normalizeKeys(\false)->beforeNormalization()->ifTrue(fn($v) => !\is_array($v) || array_keys($v) !== ['value'])->then(fn($v) => ['value' => $v])->end()->children()->variableNode('value')->end()->end()->end()->end()->end()->end()->end();
    }
    private function addNotifierSection(ArrayNodeDefinition $rootNode, callable $enableIfStandalone): void
    {
        $rootNode->children()->arrayNode('notifier')->info('Notifier configuration')->{$enableIfStandalone('symfony/notifier', Notifier::class)}()->children()->scalarNode('message_bus')->defaultNull()->info('The message bus to use. Defaults to the default bus if the Messenger component is installed.')->end()->end()->fixXmlConfig('chatter_transport')->children()->arrayNode('chatter_transports')->useAttributeAsKey('name')->prototype('scalar')->end()->end()->end()->fixXmlConfig('texter_transport')->children()->arrayNode('texter_transports')->useAttributeAsKey('name')->prototype('scalar')->end()->end()->end()->children()->booleanNode('notification_on_failed_messages')->defaultFalse()->end()->end()->children()->arrayNode('channel_policy')->useAttributeAsKey('name')->prototype('array')->beforeNormalization()->ifString()->then(fn($v) => [$v])->end()->prototype('scalar')->end()->end()->end()->end()->fixXmlConfig('admin_recipient')->children()->arrayNode('admin_recipients')->prototype('array')->children()->scalarNode('email')->cannotBeEmpty()->end()->scalarNode('phone')->defaultValue('')->end()->end()->end()->end()->end()->end()->end();
    }
    private function addWebhookSection(ArrayNodeDefinition $rootNode, callable $enableIfStandalone): void
    {
        $rootNode->children()->arrayNode('webhook')->info('Webhook configuration')->{$enableIfStandalone('symfony/webhook', WebhookController::class)}()->children()->scalarNode('message_bus')->defaultValue('messenger.default_bus')->info('The message bus to use.')->end()->arrayNode('routing')->normalizeKeys(\false)->useAttributeAsKey('type')->prototype('array')->children()->scalarNode('service')->isRequired()->cannotBeEmpty()->end()->scalarNode('secret')->defaultValue('')->end()->end()->end()->end()->end()->end();
    }
    private function addRemoteEventSection(ArrayNodeDefinition $rootNode, callable $enableIfStandalone): void
    {
        $rootNode->children()->arrayNode('remote-event')->info('RemoteEvent configuration')->{$enableIfStandalone('symfony/remote-event', RemoteEvent::class)}()->end()->end();
    }
    private function addRateLimiterSection(ArrayNodeDefinition $rootNode, callable $enableIfStandalone): void
    {
        $rootNode->children()->arrayNode('rate_limiter')->info('Rate limiter configuration')->{$enableIfStandalone('symfony/rate-limiter', TokenBucketLimiter::class)}()->fixXmlConfig('limiter')->beforeNormalization()->ifTrue(fn($v) => \is_array($v) && !isset($v['limiters']) && !isset($v['limiter']))->then(function (array $v) {
            $newV = ['enabled' => $v['enabled'] ?? \true];
            unset($v['enabled']);
            $newV['limiters'] = $v;
            return $newV;
        })->end()->children()->arrayNode('limiters')->useAttributeAsKey('name')->arrayPrototype()->children()->scalarNode('lock_factory')->info('The service ID of the lock factory used by this limiter (or null to disable locking)')->defaultValue('lock.factory')->end()->scalarNode('cache_pool')->info('The cache pool to use for storing the current limiter state')->defaultValue('cache.rate_limiter')->end()->scalarNode('storage_service')->info('The service ID of a custom storage implementation, this precedes any configured "cache_pool"')->defaultNull()->end()->enumNode('policy')->info('The algorithm to be used by this limiter')->isRequired()->values(['fixed_window', 'token_bucket', 'sliding_window', 'no_limit'])->end()->integerNode('limit')->info('The maximum allowed hits in a fixed interval or burst')->end()->scalarNode('interval')->info('Configures the fixed interval if "policy" is set to "fixed_window" or "sliding_window". The value must be a number followed by "second", "minute", "hour", "day", "week" or "month" (or their plural equivalent).')->end()->arrayNode('rate')->info('Configures the fill rate if "policy" is set to "token_bucket"')->children()->scalarNode('interval')->info('Configures the rate interval. The value must be a number followed by "second", "minute", "hour", "day", "week" or "month" (or their plural equivalent).')->end()->integerNode('amount')->info('Amount of tokens to add each interval')->defaultValue(1)->end()->end()->end()->end()->validate()->ifTrue(fn($v) => 'no_limit' !== $v['policy'] && !isset($v['limit']))->thenInvalid('A limit must be provided when using a policy different than "no_limit".')->end()->end()->end()->end()->end()->end();
    }
    private function addUidSection(ArrayNodeDefinition $rootNode, callable $enableIfStandalone): void
    {
        $rootNode->validate()->always(function ($v) {
            if ($v['uid']['enabled']) {
                if (!\array_key_exists('default_uuid_version', $v['uid'])) {
                    trigger_deprecation('symfony/framework-bundle', '6.4', 'Not setting the "framework.uid.default_uuid_version" config option is deprecated. It will default to "7" in 7.0.');
                }
                if (!\array_key_exists('time_based_uuid_version', $v['uid'])) {
                    trigger_deprecation('symfony/framework-bundle', '6.4', 'Not setting the "framework.uid.time_based_uuid_version" config option is deprecated. It will default to "7" in 7.0.');
                }
            }
            $v['uid'] += ['default_uuid_version' => 6, 'time_based_uuid_version' => 6];
            return $v;
        })->end()->children()->arrayNode('uid')->info('Uid configuration')->{$enableIfStandalone('symfony/uid', UuidFactory::class)}()->addDefaultsIfNotSet()->children()->enumNode('default_uuid_version')->values([7, 6, 4, 1])->end()->enumNode('name_based_uuid_version')->defaultValue(5)->values([5, 3])->end()->scalarNode('name_based_uuid_namespace')->cannotBeEmpty()->end()->enumNode('time_based_uuid_version')->values([7, 6, 1])->end()->scalarNode('time_based_uuid_node')->cannotBeEmpty()->end()->end()->end()->end();
    }
    private function addHtmlSanitizerSection(ArrayNodeDefinition $rootNode, callable $enableIfStandalone): void
    {
        $rootNode->children()->arrayNode('html_sanitizer')->info('HtmlSanitizer configuration')->{$enableIfStandalone('symfony/html-sanitizer', HtmlSanitizerInterface::class)}()->fixXmlConfig('sanitizer')->children()->arrayNode('sanitizers')->useAttributeAsKey('name')->arrayPrototype()->fixXmlConfig('allow_element')->fixXmlConfig('block_element')->fixXmlConfig('drop_element')->fixXmlConfig('allow_attribute')->fixXmlConfig('drop_attribute')->fixXmlConfig('force_attribute')->fixXmlConfig('allowed_link_scheme')->fixXmlConfig('allowed_link_host')->fixXmlConfig('allowed_media_scheme')->fixXmlConfig('allowed_media_host')->fixXmlConfig('with_attribute_sanitizer')->fixXmlConfig('without_attribute_sanitizer')->children()->booleanNode('allow_safe_elements')->info('Allows "safe" elements and attributes.')->defaultFalse()->end()->booleanNode('allow_static_elements')->info('Allows all static elements and attributes from the W3C Sanitizer API standard.')->defaultFalse()->end()->arrayNode('allow_elements')->info('Configures the elements that the sanitizer should retain from the input. The element name is the key, the value is either a list of allowed attributes for this element or "*" to allow the default set of attributes (https://wicg.github.io/sanitizer-api/#default-configuration).')->example(['i' => '*', 'a' => ['title'], 'span' => 'class'])->normalizeKeys(\false)->useAttributeAsKey('name')->variablePrototype()->beforeNormalization()->ifArray()->then(fn($n) => $n['attribute'] ?? $n)->end()->validate()->ifTrue(fn($n): bool => !\is_string($n) && !\is_array($n))->thenInvalid('The value must be either a string or an array of strings.')->end()->end()->end()->arrayNode('block_elements')->info('Configures elements as blocked. Blocked elements are elements the sanitizer should remove from the input, but retain their children.')->beforeNormalization()->ifString()->then(fn(string $n): array => (array) $n)->end()->scalarPrototype()->end()->end()->arrayNode('drop_elements')->info('Configures elements as dropped. Dropped elements are elements the sanitizer should remove from the input, including their children.')->beforeNormalization()->ifString()->then(fn(string $n): array => (array) $n)->end()->scalarPrototype()->end()->end()->arrayNode('allow_attributes')->info('Configures attributes as allowed. Allowed attributes are attributes the sanitizer should retain from the input.')->normalizeKeys(\false)->useAttributeAsKey('name')->variablePrototype()->beforeNormalization()->ifArray()->then(fn($n) => $n['element'] ?? $n)->end()->end()->end()->arrayNode('drop_attributes')->info('Configures attributes as dropped. Dropped attributes are attributes the sanitizer should remove from the input.')->normalizeKeys(\false)->useAttributeAsKey('name')->variablePrototype()->beforeNormalization()->ifArray()->then(fn($n) => $n['element'] ?? $n)->end()->end()->end()->arrayNode('force_attributes')->info('Forcefully set the values of certain attributes on certain elements.')->normalizeKeys(\false)->useAttributeAsKey('name')->arrayPrototype()->normalizeKeys(\false)->useAttributeAsKey('name')->scalarPrototype()->end()->end()->end()->booleanNode('force_https_urls')->info('Transforms URLs using the HTTP scheme to use the HTTPS scheme instead.')->defaultFalse()->end()->arrayNode('allowed_link_schemes')->info('Allows only a given list of schemes to be used in links href attributes.')->scalarPrototype()->end()->end()->variableNode('allowed_link_hosts')->info('Allows only a given list of hosts to be used in links href attributes.')->defaultValue(null)->validate()->ifTrue(fn($v) => !\is_array($v) && null !== $v)->thenInvalid('The "allowed_link_hosts" parameter must be an array or null')->end()->end()->booleanNode('allow_relative_links')->info('Allows relative URLs to be used in links href attributes.')->defaultFalse()->end()->arrayNode('allowed_media_schemes')->info('Allows only a given list of schemes to be used in media source attributes (img, audio, video, ...).')->scalarPrototype()->end()->end()->variableNode('allowed_media_hosts')->info('Allows only a given list of hosts to be used in media source attributes (img, audio, video, ...).')->defaultValue(null)->validate()->ifTrue(fn($v) => !\is_array($v) && null !== $v)->thenInvalid('The "allowed_media_hosts" parameter must be an array or null')->end()->end()->booleanNode('allow_relative_medias')->info('Allows relative URLs to be used in media source attributes (img, audio, video, ...).')->defaultFalse()->end()->arrayNode('with_attribute_sanitizers')->info('Registers custom attribute sanitizers.')->scalarPrototype()->end()->end()->arrayNode('without_attribute_sanitizers')->info('Unregisters custom attribute sanitizers.')->scalarPrototype()->end()->end()->integerNode('max_input_length')->info('The maximum length allowed for the sanitized input.')->defaultValue(0)->end()->end()->end()->end()->end()->end()->end();
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Bundle\FrameworkBundle\DependencyInjection;

use Composer\InstalledVersions;
use _ContaoManager\Doctrine\Common\Annotations\Reader;
use _ContaoManager\Http\Client\HttpAsyncClient;
use _ContaoManager\Http\Client\HttpClient;
use _ContaoManager\phpDocumentor\Reflection\DocBlockFactoryInterface;
use _ContaoManager\phpDocumentor\Reflection\Types\ContextFactory;
use _ContaoManager\PhpParser\Parser;
use _ContaoManager\PHPStan\PhpDocParser\Parser\PhpDocParser;
use _ContaoManager\Psr\Cache\CacheItemPoolInterface;
use _ContaoManager\Psr\Clock\ClockInterface as PsrClockInterface;
use _ContaoManager\Psr\Container\ContainerInterface as PsrContainerInterface;
use _ContaoManager\Psr\Http\Client\ClientInterface;
use _ContaoManager\Psr\Log\LoggerAwareInterface;
use _ContaoManager\Symfony\Bridge\Monolog\Processor\DebugProcessor;
use _ContaoManager\Symfony\Bridge\Twig\Extension\CsrfExtension;
use _ContaoManager\Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use _ContaoManager\Symfony\Bundle\FrameworkBundle\Routing\RouteLoaderInterface;
use _ContaoManager\Symfony\Bundle\FullStack;
use _ContaoManager\Symfony\Bundle\MercureBundle\MercureBundle;
use _ContaoManager\Symfony\Component\Asset\PackageInterface;
use _ContaoManager\Symfony\Component\AssetMapper\AssetMapper;
use _ContaoManager\Symfony\Component\AssetMapper\Compiler\AssetCompilerInterface;
use _ContaoManager\Symfony\Component\BrowserKit\AbstractBrowser;
use _ContaoManager\Symfony\Component\Cache\Adapter\AdapterInterface;
use _ContaoManager\Symfony\Component\Cache\Adapter\ArrayAdapter;
use _ContaoManager\Symfony\Component\Cache\Adapter\ChainAdapter;
use _ContaoManager\Symfony\Component\Cache\Adapter\TagAwareAdapter;
use _ContaoManager\Symfony\Component\Cache\DependencyInjection\CachePoolPass;
use _ContaoManager\Symfony\Component\Cache\Marshaller\MarshallerInterface;
use _ContaoManager\Symfony\Component\Cache\ResettableInterface;
use _ContaoManager\Symfony\Component\Clock\ClockInterface;
use _ContaoManager\Symfony\Component\Config\Definition\ConfigurationInterface;
use _ContaoManager\Symfony\Component\Config\FileLocator;
use _ContaoManager\Symfony\Component\Config\Loader\LoaderInterface;
use _ContaoManager\Symfony\Component\Config\Resource\DirectoryResource;
use _ContaoManager\Symfony\Component\Config\Resource\FileResource;
use _ContaoManager\Symfony\Component\Config\ResourceCheckerInterface;
use _ContaoManager\Symfony\Component\Console\Application;
use _ContaoManager\Symfony\Component\Console\Command\Command;
use _ContaoManager\Symfony\Component\Console\DataCollector\CommandDataCollector;
use _ContaoManager\Symfony\Component\Console\Debug\CliRequest;
use _ContaoManager\Symfony\Component\Console\Messenger\RunCommandMessageHandler;
use _ContaoManager\Symfony\Component\DependencyInjection\Alias;
use _ContaoManager\Symfony\Component\DependencyInjection\Argument\ServiceClosureArgument;
use _ContaoManager\Symfony\Component\DependencyInjection\ChildDefinition;
use _ContaoManager\Symfony\Component\DependencyInjection\Compiler\ServiceLocatorTagPass;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerBuilder;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Definition;
use _ContaoManager\Symfony\Component\DependencyInjection\EnvVarLoaderInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\EnvVarProcessorInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\LogicException;
use _ContaoManager\Symfony\Component\DependencyInjection\Loader\PhpFileLoader;
use _ContaoManager\Symfony\Component\DependencyInjection\Parameter;
use _ContaoManager\Symfony\Component\DependencyInjection\Reference;
use _ContaoManager\Symfony\Component\DependencyInjection\ServiceLocator;
use _ContaoManager\Symfony\Component\Dotenv\Command\DebugCommand;
use _ContaoManager\Symfony\Component\EventDispatcher\Attribute\AsEventListener;
use _ContaoManager\Symfony\Component\EventDispatcher\EventSubscriberInterface;
use _ContaoManager\Symfony\Component\ExpressionLanguage\ExpressionLanguage;
use _ContaoManager\Symfony\Component\Finder\Finder;
use _ContaoManager\Symfony\Component\Finder\Glob;
use _ContaoManager\Symfony\Component\Form\Extension\HtmlSanitizer\Type\TextTypeHtmlSanitizerExtension;
use _ContaoManager\Symfony\Component\Form\Form;
use _ContaoManager\Symfony\Component\Form\FormTypeExtensionInterface;
use _ContaoManager\Symfony\Component\Form\FormTypeGuesserInterface;
use _ContaoManager\Symfony\Component\Form\FormTypeInterface;
use _ContaoManager\Symfony\Component\HtmlSanitizer\HtmlSanitizer;
use _ContaoManager\Symfony\Component\HtmlSanitizer\HtmlSanitizerConfig;
use _ContaoManager\Symfony\Component\HtmlSanitizer\HtmlSanitizerInterface;
use _ContaoManager\Symfony\Component\HttpClient\Messenger\PingWebhookMessageHandler;
use _ContaoManager\Symfony\Component\HttpClient\MockHttpClient;
use _ContaoManager\Symfony\Component\HttpClient\Retry\GenericRetryStrategy;
use _ContaoManager\Symfony\Component\HttpClient\RetryableHttpClient;
use _ContaoManager\Symfony\Component\HttpClient\ScopingHttpClient;
use _ContaoManager\Symfony\Component\HttpClient\UriTemplateHttpClient;
use _ContaoManager\Symfony\Component\HttpFoundation\Request;
use _ContaoManager\Symfony\Component\HttpKernel\Attribute\AsController;
use _ContaoManager\Symfony\Component\HttpKernel\Attribute\AsTargetedValueResolver;
use _ContaoManager\Symfony\Component\HttpKernel\CacheClearer\CacheClearerInterface;
use _ContaoManager\Symfony\Component\HttpKernel\CacheWarmer\CacheWarmerInterface;
use _ContaoManager\Symfony\Component\HttpKernel\Controller\ArgumentValueResolverInterface;
use _ContaoManager\Symfony\Component\HttpKernel\Controller\ValueResolverInterface;
use _ContaoManager\Symfony\Component\HttpKernel\DataCollector\DataCollectorInterface;
use _ContaoManager\Symfony\Component\HttpKernel\DependencyInjection\Extension;
use _ContaoManager\Symfony\Component\HttpKernel\Log\DebugLoggerConfigurator;
use _ContaoManager\Symfony\Component\Lock\LockFactory;
use _ContaoManager\Symfony\Component\Lock\LockInterface;
use _ContaoManager\Symfony\Component\Lock\PersistingStoreInterface;
use _ContaoManager\Symfony\Component\Lock\Store\StoreFactory;
use _ContaoManager\Symfony\Component\Mailer\Bridge as MailerBridge;
use _ContaoManager\Symfony\Component\Mailer\Command\MailerTestCommand;
use _ContaoManager\Symfony\Component\Mailer\EventListener\MessengerTransportListener;
use _ContaoManager\Symfony\Component\Mailer\Mailer;
use _ContaoManager\Symfony\Component\Mercure\HubRegistry;
use _ContaoManager\Symfony\Component\Messenger\Attribute\AsMessageHandler;
use _ContaoManager\Symfony\Component\Messenger\Bridge as MessengerBridge;
use _ContaoManager\Symfony\Component\Messenger\EventListener\StopWorkerOnSignalsListener;
use _ContaoManager\Symfony\Component\Messenger\Handler\BatchHandlerInterface;
use _ContaoManager\Symfony\Component\Messenger\Handler\MessageHandlerInterface;
use _ContaoManager\Symfony\Component\Messenger\MessageBus;
use _ContaoManager\Symfony\Component\Messenger\MessageBusInterface;
use _ContaoManager\Symfony\Component\Messenger\Middleware\RouterContextMiddleware;
use _ContaoManager\Symfony\Component\Messenger\Transport\Serialization\SerializerInterface;
use _ContaoManager\Symfony\Component\Messenger\Transport\TransportFactoryInterface as MessengerTransportFactoryInterface;
use _ContaoManager\Symfony\Component\Messenger\Transport\TransportInterface;
use _ContaoManager\Symfony\Component\Mime\Header\Headers;
use _ContaoManager\Symfony\Component\Mime\MimeTypeGuesserInterface;
use _ContaoManager\Symfony\Component\Mime\MimeTypes;
use _ContaoManager\Symfony\Component\Notifier\Bridge as NotifierBridge;
use _ContaoManager\Symfony\Component\Notifier\Bridge\FakeChat\FakeChatTransportFactory;
use _ContaoManager\Symfony\Component\Notifier\Bridge\FakeSms\FakeSmsTransportFactory;
use _ContaoManager\Symfony\Component\Notifier\ChatterInterface;
use _ContaoManager\Symfony\Component\Notifier\Notifier;
use _ContaoManager\Symfony\Component\Notifier\Recipient\Recipient;
use _ContaoManager\Symfony\Component\Notifier\TexterInterface;
use _ContaoManager\Symfony\Component\Notifier\Transport\TransportFactoryInterface as NotifierTransportFactoryInterface;
use _ContaoManager\Symfony\Component\Process\Messenger\RunProcessMessageHandler;
use _ContaoManager\Symfony\Component\PropertyAccess\PropertyAccessor;
use _ContaoManager\Symfony\Component\PropertyInfo\Extractor\PhpDocExtractor;
use _ContaoManager\Symfony\Component\PropertyInfo\Extractor\PhpStanExtractor;
use _ContaoManager\Symfony\Component\PropertyInfo\PropertyAccessExtractorInterface;
use _ContaoManager\Symfony\Component\PropertyInfo\PropertyDescriptionExtractorInterface;
use _ContaoManager\Symfony\Component\PropertyInfo\PropertyInfoExtractorInterface;
use _ContaoManager\Symfony\Component\PropertyInfo\PropertyInitializableExtractorInterface;
use _ContaoManager\Symfony\Component\PropertyInfo\PropertyListExtractorInterface;
use _ContaoManager\Symfony\Component\PropertyInfo\PropertyReadInfoExtractorInterface;
use _ContaoManager\Symfony\Component\PropertyInfo\PropertyTypeExtractorInterface;
use _ContaoManager\Symfony\Component\PropertyInfo\PropertyWriteInfoExtractorInterface;
use _ContaoManager\Symfony\Component\RateLimiter\LimiterInterface;
use _ContaoManager\Symfony\Component\RateLimiter\RateLimiterFactory;
use _ContaoManager\Symfony\Component\RateLimiter\Storage\CacheStorage;
use _ContaoManager\Symfony\Component\RemoteEvent\Attribute\AsRemoteEventConsumer;
use _ContaoManager\Symfony\Component\RemoteEvent\RemoteEvent;
use _ContaoManager\Symfony\Component\Routing\Loader\AttributeClassLoader;
use _ContaoManager\Symfony\Component\Scheduler\Attribute\AsCronTask;
use _ContaoManager\Symfony\Component\Scheduler\Attribute\AsPeriodicTask;
use _ContaoManager\Symfony\Component\Scheduler\Attribute\AsSchedule;
use _ContaoManager\Symfony\Component\Scheduler\Messenger\SchedulerTransportFactory;
use _ContaoManager\Symfony\Component\Security\Core\AuthenticationEvents;
use _ContaoManager\Symfony\Component\Security\Core\Exception\AuthenticationException;
use _ContaoManager\Symfony\Component\Security\Csrf\CsrfTokenManagerInterface;
use _ContaoManager\Symfony\Component\Semaphore\PersistingStoreInterface as SemaphoreStoreInterface;
use _ContaoManager\Symfony\Component\Semaphore\Semaphore;
use _ContaoManager\Symfony\Component\Semaphore\SemaphoreFactory;
use _ContaoManager\Symfony\Component\Semaphore\Store\StoreFactory as SemaphoreStoreFactory;
use _ContaoManager\Symfony\Component\Serializer\Encoder\DecoderInterface;
use _ContaoManager\Symfony\Component\Serializer\Encoder\EncoderInterface;
use _ContaoManager\Symfony\Component\Serializer\Mapping\Loader\AttributeLoader;
use _ContaoManager\Symfony\Component\Serializer\Mapping\Loader\XmlFileLoader;
use _ContaoManager\Symfony\Component\Serializer\Mapping\Loader\YamlFileLoader;
use _ContaoManager\Symfony\Component\Serializer\Normalizer\CacheableSupportsMethodInterface;
use _ContaoManager\Symfony\Component\Serializer\Normalizer\DenormalizerInterface;
use _ContaoManager\Symfony\Component\Serializer\Normalizer\NormalizerInterface;
use _ContaoManager\Symfony\Component\Serializer\Serializer;
use _ContaoManager\Symfony\Component\Stopwatch\Stopwatch;
use _ContaoManager\Symfony\Component\String\LazyString;
use _ContaoManager\Symfony\Component\String\Slugger\SluggerInterface;
use _ContaoManager\Symfony\Component\Translation\Bridge as TranslationBridge;
use _ContaoManager\Symfony\Component\Translation\Command\XliffLintCommand as BaseXliffLintCommand;
use _ContaoManager\Symfony\Component\Translation\Extractor\PhpAstExtractor;
use _ContaoManager\Symfony\Component\Translation\LocaleSwitcher;
use _ContaoManager\Symfony\Component\Translation\PseudoLocalizationTranslator;
use _ContaoManager\Symfony\Component\Translation\Translator;
use _ContaoManager\Symfony\Component\Uid\Factory\UuidFactory;
use _ContaoManager\Symfony\Component\Uid\UuidV4;
use _ContaoManager\Symfony\Component\Validator\Constraints\ExpressionLanguageProvider;
use _ContaoManager\Symfony\Component\Validator\ConstraintValidatorInterface;
use _ContaoManager\Symfony\Component\Validator\GroupProviderInterface;
use _ContaoManager\Symfony\Component\Validator\Mapping\Loader\PropertyInfoLoader;
use _ContaoManager\Symfony\Component\Validator\ObjectInitializerInterface;
use _ContaoManager\Symfony\Component\Validator\Validation;
use _ContaoManager\Symfony\Component\Validator\ValidatorBuilder;
use _ContaoManager\Symfony\Component\Webhook\Controller\WebhookController;
use _ContaoManager\Symfony\Component\WebLink\HttpHeaderSerializer;
use _ContaoManager\Symfony\Component\Workflow;
use _ContaoManager\Symfony\Component\Workflow\WorkflowInterface;
use _ContaoManager\Symfony\Component\Yaml\Command\LintCommand as BaseYamlLintCommand;
use _ContaoManager\Symfony\Component\Yaml\Yaml;
use _ContaoManager\Symfony\Contracts\Cache\CacheInterface;
use _ContaoManager\Symfony\Contracts\Cache\CallbackInterface;
use _ContaoManager\Symfony\Contracts\Cache\TagAwareCacheInterface;
use _ContaoManager\Symfony\Contracts\EventDispatcher\EventDispatcherInterface;
use _ContaoManager\Symfony\Contracts\HttpClient\HttpClientInterface;
use _ContaoManager\Symfony\Contracts\Service\ResetInterface;
use _ContaoManager\Symfony\Contracts\Service\ServiceSubscriberInterface;
use _ContaoManager\Symfony\Contracts\Translation\LocaleAwareInterface;
/**
 * Process the configuration and prepare the dependency injection container with
 * parameters and services.
 */
class FrameworkExtension extends Extension
{
    private array $configsEnabled = [];
    /**
     * Responds to the app.config configuration parameter.
     *
     * @return void
     *
     * @throws LogicException
     */
    public function load(array $configs, ContainerBuilder $container)
    {
        $loader = new PhpFileLoader($container, new FileLocator(\dirname(__DIR__) . '/Resources/config'));
        if (class_exists(InstalledVersions::class) && InstalledVersions::isInstalled('symfony/symfony') && 'symfony/symfony' !== (InstalledVersions::getRootPackage()['name'] ?? '')) {
            trigger_deprecation('symfony/symfony', '6.1', 'Requiring the "symfony/symfony" package is deprecated; replace it with standalone components instead.');
        }
        $loader->load('web.php');
        $loader->load('services.php');
        $loader->load('fragment_renderer.php');
        $loader->load('error_renderer.php');
        if (!ContainerBuilder::willBeAvailable('symfony/clock', ClockInterface::class, ['symfony/framework-bundle'])) {
            $container->removeDefinition('clock');
            $container->removeAlias(ClockInterface::class);
            $container->removeAlias(PsrClockInterface::class);
        }
        $container->registerAliasForArgument('parameter_bag', PsrContainerInterface::class);
        $loader->load('process.php');
        if (!class_exists(RunProcessMessageHandler::class)) {
            $container->removeDefinition('process.messenger.process_message_handler');
        }
        if ($this->hasConsole()) {
            $loader->load('console.php');
            if (!class_exists(BaseXliffLintCommand::class)) {
                $container->removeDefinition('console.command.xliff_lint');
            }
            if (!class_exists(BaseYamlLintCommand::class)) {
                $container->removeDefinition('console.command.yaml_lint');
            }
            if (!class_exists(DebugCommand::class)) {
                $container->removeDefinition('console.command.dotenv_debug');
            }
            if (!class_exists(RunCommandMessageHandler::class)) {
                $container->removeDefinition('console.messenger.application');
                $container->removeDefinition('console.messenger.execute_command_handler');
            }
        }
        // Load Cache configuration first as it is used by other components
        $loader->load('cache.php');
        $configuration = $this->getConfiguration($configs, $container);
        $config = $this->processConfiguration($configuration, $configs);
        // warmup config enabled
        $this->readConfigEnabled('annotations', $container, $config['annotations']);
        $this->readConfigEnabled('translator', $container, $config['translator']);
        $this->readConfigEnabled('property_access', $container, $config['property_access']);
        $this->readConfigEnabled('profiler', $container, $config['profiler']);
        $this->readConfigEnabled('workflows', $container, $config['workflows']);
        // A translator must always be registered (as support is included by
        // default in the Form and Validator component). If disabled, an identity
        // translator will be used and everything will still work as expected.
        if ($this->readConfigEnabled('translator', $container, $config['translator']) || $this->readConfigEnabled('form', $container, $config['form']) || $this->readConfigEnabled('validation', $container, $config['validation'])) {
            if (!class_exists(Translator::class) && $this->readConfigEnabled('translator', $container, $config['translator'])) {
                throw new LogicException('Translation support cannot be enabled as the Translation component is not installed. Try running "composer require symfony/translation".');
            }
            if (class_exists(Translator::class)) {
                $loader->load('identity_translator.php');
            }
        }
        $container->getDefinition('locale_listener')->replaceArgument(3, $config['set_locale_from_accept_language']);
        $container->getDefinition('response_listener')->replaceArgument(1, $config['set_content_language_from_locale']);
        $container->getDefinition('http_kernel')->replaceArgument(4, $config['handle_all_throwables'] ?? \false);
        // If the slugger is used but the String component is not available, we should throw an error
        if (!ContainerBuilder::willBeAvailable('symfony/string', SluggerInterface::class, ['symfony/framework-bundle'])) {
            $container->register('slugger', SluggerInterface::class)->addError('You cannot use the "slugger" service since the String component is not installed. Try running "composer require symfony/string".');
        } else {
            if (!ContainerBuilder::willBeAvailable('symfony/translation', LocaleAwareInterface::class, ['symfony/framework-bundle'])) {
                $container->register('slugger', SluggerInterface::class)->addError('You cannot use the "slugger" service since the Translation contracts are not installed. Try running "composer require symfony/translation".');
            }
            if (!\extension_loaded('intl') && !\defined('PHPUNIT_COMPOSER_INSTALL')) {
                trigger_deprecation('', '', 'Please install the "intl" PHP extension for best performance.');
            }
        }
        if (isset($config['secret'])) {
            $container->setParameter('kernel.secret', $config['secret']);
        }
        $container->setParameter('kernel.http_method_override', $config['http_method_override']);
        $container->setParameter('kernel.trust_x_sendfile_type_header', $config['trust_x_sendfile_type_header']);
        $container->setParameter('kernel.trusted_hosts', $config['trusted_hosts']);
        $container->setParameter('kernel.default_locale', $config['default_locale']);
        $container->setParameter('kernel.enabled_locales', $config['enabled_locales']);
        $container->setParameter('kernel.error_controller', $config['error_controller']);
        if (($config['trusted_proxies'] ?? \false) && ($config['trusted_headers'] ?? \false)) {
            $container->setParameter('kernel.trusted_proxies', $config['trusted_proxies']);
            $container->setParameter('kernel.trusted_headers', $this->resolveTrustedHeaders($config['trusted_headers']));
        }
        if (!$container->hasParameter('debug.file_link_format')) {
            $container->setParameter('debug.file_link_format', $config['ide']);
        }
        if (!empty($config['test'])) {
            $loader->load('test.php');
            if (!class_exists(AbstractBrowser::class)) {
                $container->removeDefinition('test.client');
            }
        }
        if ($this->readConfigEnabled('request', $container, $config['request'])) {
            $this->registerRequestConfiguration($config['request'], $container, $loader);
        }
        if ($this->readConfigEnabled('assets', $container, $config['assets'])) {
            if (!class_exists(\_ContaoManager\Symfony\Component\Asset\Package::class)) {
                throw new LogicException('Asset support cannot be enabled as the Asset component is not installed. Try running "composer require symfony/asset".');
            }
            $this->registerAssetsConfiguration($config['assets'], $container, $loader);
        }
        if ($this->readConfigEnabled('asset_mapper', $container, $config['asset_mapper'])) {
            if (!class_exists(AssetMapper::class)) {
                throw new LogicException('AssetMapper support cannot be enabled as the AssetMapper component is not installed. Try running "composer require symfony/asset-mapper".');
            }
            $this->registerAssetMapperConfiguration($config['asset_mapper'], $container, $loader, $this->readConfigEnabled('assets', $container, $config['assets']), $this->readConfigEnabled('http_client', $container, $config['http_client']));
        } else {
            $container->removeDefinition('cache.asset_mapper');
        }
        if ($this->readConfigEnabled('http_client', $container, $config['http_client'])) {
            $this->registerHttpClientConfiguration($config['http_client'], $container, $loader);
        }
        if ($this->readConfigEnabled('mailer', $container, $config['mailer'])) {
            $this->registerMailerConfiguration($config['mailer'], $container, $loader, $this->readConfigEnabled('webhook', $container, $config['webhook']));
            if (!$this->hasConsole() || !class_exists(MailerTestCommand::class)) {
                $container->removeDefinition('console.command.mailer_test');
            }
        }
        $propertyInfoEnabled = $this->readConfigEnabled('property_info', $container, $config['property_info']);
        $this->registerHttpCacheConfiguration($config['http_cache'], $container, $config['http_method_override']);
        $this->registerEsiConfiguration($config['esi'], $container, $loader);
        $this->registerSsiConfiguration($config['ssi'], $container, $loader);
        $this->registerFragmentsConfiguration($config['fragments'], $container, $loader);
        $this->registerTranslatorConfiguration($config['translator'], $container, $loader, $config['default_locale'], $config['enabled_locales']);
        $this->registerWorkflowConfiguration($config['workflows'], $container, $loader);
        $this->registerDebugConfiguration($config['php_errors'], $container, $loader);
        $this->registerRouterConfiguration($config['router'], $container, $loader, $config['enabled_locales']);
        $this->registerAnnotationsConfiguration($config['annotations'], $container, $loader);
        $this->registerPropertyAccessConfiguration($config['property_access'], $container, $loader);
        $this->registerSecretsConfiguration($config['secrets'], $container, $loader);
        $container->getDefinition('exception_listener')->replaceArgument(3, $config['exceptions']);
        if ($this->readConfigEnabled('serializer', $container, $config['serializer'])) {
            if (!class_exists(Serializer::class)) {
                throw new LogicException('Serializer support cannot be enabled as the Serializer component is not installed. Try running "composer require symfony/serializer-pack".');
            }
            $this->registerSerializerConfiguration($config['serializer'], $container, $loader);
        } else {
            $container->getDefinition('argument_resolver.request_payload')->setArguments([])->addError('You can neither use "#[MapRequestPayload]" nor "#[MapQueryString]" since the Serializer component is not ' . (class_exists(Serializer::class) ? 'enabled. Try setting "framework.serializer.enabled" to true.' : 'installed. Try running "composer require symfony/serializer-pack".'))->addTag('container.error')->clearTag('kernel.event_subscriber');
            $container->removeDefinition('console.command.serializer_debug');
        }
        if ($propertyInfoEnabled) {
            $this->registerPropertyInfoConfiguration($container, $loader);
        }
        if ($this->readConfigEnabled('lock', $container, $config['lock'])) {
            $this->registerLockConfiguration($config['lock'], $container, $loader);
        }
        if ($this->readConfigEnabled('semaphore', $container, $config['semaphore'])) {
            $this->registerSemaphoreConfiguration($config['semaphore'], $container, $loader);
        }
        if ($this->readConfigEnabled('rate_limiter', $container, $config['rate_limiter'])) {
            if (!interface_exists(LimiterInterface::class)) {
                throw new LogicException('Rate limiter support cannot be enabled as the RateLimiter component is not installed. Try running "composer require symfony/rate-limiter".');
            }
            $this->registerRateLimiterConfiguration($config['rate_limiter'], $container, $loader);
        }
        if ($this->readConfigEnabled('web_link', $container, $config['web_link'])) {
            if (!class_exists(HttpHeaderSerializer::class)) {
                throw new LogicException('WebLink support cannot be enabled as the WebLink component is not installed. Try running "composer require symfony/weblink".');
            }
            $loader->load('web_link.php');
        }
        if ($this->readConfigEnabled('uid', $container, $config['uid'])) {
            if (!class_exists(UuidFactory::class)) {
                throw new LogicException('Uid support cannot be enabled as the Uid component is not installed. Try running "composer require symfony/uid".');
            }
            $this->registerUidConfiguration($config['uid'], $container, $loader);
        } else {
            $container->removeDefinition('argument_resolver.uid');
        }
        // register cache before session so both can share the connection services
        $this->registerCacheConfiguration($config['cache'], $container);
        if ($this->readConfigEnabled('session', $container, $config['session'])) {
            if (!\extension_loaded('session')) {
                throw new LogicException('Session support cannot be enabled as the session extension is not installed. See https://php.net/session.installation for instructions.');
            }
            $this->registerSessionConfiguration($config['session'], $container, $loader);
            if (!empty($config['test'])) {
                // test listener will replace the existing session listener
                // as we are aliasing to avoid duplicated registered events
                $container->setAlias('session_listener', 'test.session.listener');
            }
        } elseif (!empty($config['test'])) {
            $container->removeDefinition('test.session.listener');
        }
        // csrf depends on session being registered
        if (null === $config['csrf_protection']['enabled']) {
            $this->writeConfigEnabled('csrf_protection', $this->readConfigEnabled('session', $container, $config['session']) && !class_exists(FullStack::class) && ContainerBuilder::willBeAvailable('symfony/security-csrf', CsrfTokenManagerInterface::class, ['symfony/framework-bundle']), $config['csrf_protection']);
        }
        $this->registerSecurityCsrfConfiguration($config['csrf_protection'], $container, $loader);
        // form depends on csrf being registered
        if ($this->readConfigEnabled('form', $container, $config['form'])) {
            if (!class_exists(Form::class)) {
                throw new LogicException('Form support cannot be enabled as the Form component is not installed. Try running "composer require symfony/form".');
            }
            $this->registerFormConfiguration($config, $container, $loader);
            if (ContainerBuilder::willBeAvailable('symfony/validator', Validation::class, ['symfony/framework-bundle', 'symfony/form'])) {
                $this->writeConfigEnabled('validation', \true, $config['validation']);
            } else {
                $container->setParameter('validator.translation_domain', 'validators');
                $container->removeDefinition('form.type_extension.form.validator');
                $container->removeDefinition('form.type_guesser.validator');
            }
            if (!$this->readConfigEnabled('html_sanitizer', $container, $config['html_sanitizer']) || !class_exists(TextTypeHtmlSanitizerExtension::class)) {
                $container->removeDefinition('form.type_extension.form.html_sanitizer');
            }
        } else {
            $container->removeDefinition('console.command.form_debug');
        }
        // validation depends on form, annotations being registered
        $this->registerValidationConfiguration($config['validation'], $container, $loader, $propertyInfoEnabled);
        $messengerEnabled = $this->readConfigEnabled('messenger', $container, $config['messenger']);
        if ($this->readConfigEnabled('scheduler', $container, $config['scheduler'])) {
            if (!$messengerEnabled) {
                throw new LogicException('Scheduler support cannot be enabled as the Messenger component is not ' . (interface_exists(MessageBusInterface::class) ? 'enabled.' : 'installed. Try running "composer require symfony/messenger".'));
            }
            $this->registerSchedulerConfiguration($config['scheduler'], $container, $loader);
        } else {
            $container->removeDefinition('cache.scheduler');
            $container->removeDefinition('console.command.scheduler_debug');
        }
        // messenger depends on validation being registered
        if ($messengerEnabled) {
            $this->registerMessengerConfiguration($config['messenger'], $container, $loader, $this->readConfigEnabled('validation', $container, $config['validation']));
        } else {
            $container->removeDefinition('console.command.messenger_consume_messages');
            $container->removeDefinition('console.command.messenger_stats');
            $container->removeDefinition('console.command.messenger_debug');
            $container->removeDefinition('console.command.messenger_stop_workers');
            $container->removeDefinition('console.command.messenger_setup_transports');
            $container->removeDefinition('console.command.messenger_failed_messages_retry');
            $container->removeDefinition('console.command.messenger_failed_messages_show');
            $container->removeDefinition('console.command.messenger_failed_messages_remove');
            $container->removeDefinition('cache.messenger.restart_workers_signal');
            if ($container->hasDefinition('messenger.transport.amqp.factory') && !class_exists(MessengerBridge\Amqp\Transport\AmqpTransportFactory::class)) {
                if (class_exists(\_ContaoManager\Symfony\Component\Messenger\Transport\AmqpExt\AmqpTransportFactory::class)) {
                    $container->getDefinition('messenger.transport.amqp.factory')->setClass(\_ContaoManager\Symfony\Component\Messenger\Transport\AmqpExt\AmqpTransportFactory::class)->addTag('messenger.transport_factory');
                } else {
                    $container->removeDefinition('messenger.transport.amqp.factory');
                }
            }
            if ($container->hasDefinition('messenger.transport.redis.factory') && !class_exists(MessengerBridge\Redis\Transport\RedisTransportFactory::class)) {
                if (class_exists(\_ContaoManager\Symfony\Component\Messenger\Transport\RedisExt\RedisTransportFactory::class)) {
                    $container->getDefinition('messenger.transport.redis.factory')->setClass(\_ContaoManager\Symfony\Component\Messenger\Transport\RedisExt\RedisTransportFactory::class)->addTag('messenger.transport_factory');
                } else {
                    $container->removeDefinition('messenger.transport.redis.factory');
                }
            }
        }
        // notifier depends on messenger, mailer being registered
        if ($this->readConfigEnabled('notifier', $container, $config['notifier'])) {
            $this->registerNotifierConfiguration($config['notifier'], $container, $loader, $this->readConfigEnabled('webhook', $container, $config['webhook']));
        }
        // profiler depends on form, validation, translation, messenger, mailer, http-client, notifier, serializer being registered
        $this->registerProfilerConfiguration($config['profiler'], $container, $loader);
        if ($this->readConfigEnabled('webhook', $container, $config['webhook'])) {
            $this->registerWebhookConfiguration($config['webhook'], $container, $loader);
            // If Webhook is installed but the HttpClient or Serializer components are not available, we should throw an error
            if (!$this->readConfigEnabled('http_client', $container, $config['http_client'])) {
                $container->getDefinition('webhook.transport')->setArguments([])->addError('You cannot use the "webhook transport" service since the HttpClient component is not ' . (class_exists(ScopingHttpClient::class) ? 'enabled. Try setting "framework.http_client.enabled" to true.' : 'installed. Try running "composer require symfony/http-client".'))->addTag('container.error');
            }
            if (!$this->readConfigEnabled('serializer', $container, $config['serializer'])) {
                $container->getDefinition('webhook.body_configurator.json')->setArguments([])->addError('You cannot use the "webhook transport" service since the Serializer component is not ' . (class_exists(Serializer::class) ? 'enabled. Try setting "framework.serializer.enabled" to true.' : 'installed. Try running "composer require symfony/serializer-pack".'))->addTag('container.error');
            }
        }
        if ($this->readConfigEnabled('remote-event', $container, $config['remote-event'])) {
            $this->registerRemoteEventConfiguration($config['remote-event'], $container, $loader);
        }
        if ($this->readConfigEnabled('html_sanitizer', $container, $config['html_sanitizer'])) {
            if (!class_exists(HtmlSanitizerConfig::class)) {
                throw new LogicException('HtmlSanitizer support cannot be enabled as the HtmlSanitizer component is not installed. Try running "composer require symfony/html-sanitizer".');
            }
            $this->registerHtmlSanitizerConfiguration($config['html_sanitizer'], $container, $loader);
        }
        $this->addAnnotatedClassesToCompile([
            '**\Controller\\',
            '**\Entity\\',
            // Added explicitly so that we don't rely on the class map being dumped to make it work
            AbstractController::class,
        ]);
        if (ContainerBuilder::willBeAvailable('symfony/mime', MimeTypes::class, ['symfony/framework-bundle'])) {
            $loader->load('mime_type.php');
        }
        $container->registerForAutoconfiguration(PackageInterface::class)->addTag('assets.package');
        $container->registerForAutoconfiguration(AssetCompilerInterface::class)->addTag('asset_mapper.compiler');
        $container->registerForAutoconfiguration(Command::class)->addTag('console.command');
        $container->registerForAutoconfiguration(ResourceCheckerInterface::class)->addTag('config_cache.resource_checker');
        $container->registerForAutoconfiguration(EnvVarLoaderInterface::class)->addTag('container.env_var_loader');
        $container->registerForAutoconfiguration(EnvVarProcessorInterface::class)->addTag('container.env_var_processor');
        $container->registerForAutoconfiguration(CallbackInterface::class)->addTag('container.reversible');
        $container->registerForAutoconfiguration(ServiceLocator::class)->addTag('container.service_locator');
        $container->registerForAutoconfiguration(ServiceSubscriberInterface::class)->addTag('container.service_subscriber');
        $container->registerForAutoconfiguration(ArgumentValueResolverInterface::class)->addTag('controller.argument_value_resolver');
        $container->registerForAutoconfiguration(ValueResolverInterface::class)->addTag('controller.argument_value_resolver');
        $container->registerForAutoconfiguration(AbstractController::class)->addTag('controller.service_arguments');
        $container->registerForAutoconfiguration(DataCollectorInterface::class)->addTag('data_collector');
        $container->registerForAutoconfiguration(FormTypeInterface::class)->addTag('form.type');
        $container->registerForAutoconfiguration(FormTypeGuesserInterface::class)->addTag('form.type_guesser');
        $container->registerForAutoconfiguration(FormTypeExtensionInterface::class)->addTag('form.type_extension');
        $container->registerForAutoconfiguration(CacheClearerInterface::class)->addTag('kernel.cache_clearer');
        $container->registerForAutoconfiguration(CacheWarmerInterface::class)->addTag('kernel.cache_warmer');
        $container->registerForAutoconfiguration(EventDispatcherInterface::class)->addTag('event_dispatcher.dispatcher');
        $container->registerForAutoconfiguration(EventSubscriberInterface::class)->addTag('kernel.event_subscriber');
        $container->registerForAutoconfiguration(LocaleAwareInterface::class)->addTag('kernel.locale_aware');
        $container->registerForAutoconfiguration(ResetInterface::class)->addTag('kernel.reset', ['method' => 'reset']);
        if (!interface_exists(MarshallerInterface::class)) {
            $container->registerForAutoconfiguration(ResettableInterface::class)->addTag('kernel.reset', ['method' => 'reset']);
        }
        $container->registerForAutoconfiguration(PropertyListExtractorInterface::class)->addTag('property_info.list_extractor');
        $container->registerForAutoconfiguration(PropertyTypeExtractorInterface::class)->addTag('property_info.type_extractor');
        $container->registerForAutoconfiguration(PropertyDescriptionExtractorInterface::class)->addTag('property_info.description_extractor');
        $container->registerForAutoconfiguration(PropertyAccessExtractorInterface::class)->addTag('property_info.access_extractor');
        $container->registerForAutoconfiguration(PropertyInitializableExtractorInterface::class)->addTag('property_info.initializable_extractor');
        $container->registerForAutoconfiguration(EncoderInterface::class)->addTag('serializer.encoder');
        $container->registerForAutoconfiguration(DecoderInterface::class)->addTag('serializer.encoder');
        $container->registerForAutoconfiguration(NormalizerInterface::class)->addTag('serializer.normalizer');
        $container->registerForAutoconfiguration(DenormalizerInterface::class)->addTag('serializer.normalizer');
        $container->registerForAutoconfiguration(ConstraintValidatorInterface::class)->addTag('validator.constraint_validator');
        $container->registerForAutoconfiguration(GroupProviderInterface::class)->addTag('validator.group_provider');
        $container->registerForAutoconfiguration(ObjectInitializerInterface::class)->addTag('validator.initializer');
        $container->registerForAutoconfiguration(MessageHandlerInterface::class)->addTag('messenger.message_handler');
        $container->registerForAutoconfiguration(BatchHandlerInterface::class)->addTag('messenger.message_handler');
        $container->registerForAutoconfiguration(MessengerTransportFactoryInterface::class)->addTag('messenger.transport_factory');
        $container->registerForAutoconfiguration(MimeTypeGuesserInterface::class)->addTag('mime.mime_type_guesser');
        $container->registerForAutoconfiguration(LoggerAwareInterface::class)->addMethodCall('setLogger', [new Reference('logger')]);
        $container->registerAttributeForAutoconfiguration(AsEventListener::class, static function (ChildDefinition $definition, AsEventListener $attribute, \ReflectionClass|\ReflectionMethod $reflector) {
            $tagAttributes = get_object_vars($attribute);
            if ($reflector instanceof \ReflectionMethod) {
                if (isset($tagAttributes['method'])) {
                    throw new LogicException(\sprintf('AsEventListener attribute cannot declare a method on "%s::%s()".', $reflector->class, $reflector->name));
                }
                $tagAttributes['method'] = $reflector->getName();
            }
            $definition->addTag('kernel.event_listener', $tagAttributes);
        });
        $container->registerAttributeForAutoconfiguration(AsController::class, static function (ChildDefinition $definition, AsController $attribute): void {
            $definition->addTag('controller.service_arguments');
        });
        $container->registerAttributeForAutoconfiguration(AsRemoteEventConsumer::class, static function (ChildDefinition $definition, AsRemoteEventConsumer $attribute): void {
            $definition->addTag('remote_event.consumer', ['consumer' => $attribute->name]);
        });
        $container->registerAttributeForAutoconfiguration(AsMessageHandler::class, static function (ChildDefinition $definition, AsMessageHandler $attribute, \ReflectionClass|\ReflectionMethod $reflector): void {
            $tagAttributes = get_object_vars($attribute);
            $tagAttributes['from_transport'] = $tagAttributes['fromTransport'];
            unset($tagAttributes['fromTransport']);
            if ($reflector instanceof \ReflectionMethod) {
                if (isset($tagAttributes['method'])) {
                    throw new LogicException(\sprintf('AsMessageHandler attribute cannot declare a method on "%s::%s()".', $reflector->class, $reflector->name));
                }
                $tagAttributes['method'] = $reflector->getName();
            }
            $definition->addTag('messenger.message_handler', $tagAttributes);
        });
        $container->registerAttributeForAutoconfiguration(AsTargetedValueResolver::class, static function (ChildDefinition $definition, AsTargetedValueResolver $attribute): void {
            $definition->addTag('controller.targeted_value_resolver', $attribute->name ? ['name' => $attribute->name] : []);
        });
        $container->registerAttributeForAutoconfiguration(AsSchedule::class, static function (ChildDefinition $definition, AsSchedule $attribute): void {
            $definition->addTag('scheduler.schedule_provider', ['name' => $attribute->name]);
        });
        foreach ([AsPeriodicTask::class, AsCronTask::class] as $taskAttributeClass) {
            $container->registerAttributeForAutoconfiguration($taskAttributeClass, static function (ChildDefinition $definition, AsPeriodicTask|AsCronTask $attribute, \ReflectionClass|\ReflectionMethod $reflector): void {
                $tagAttributes = get_object_vars($attribute) + ['trigger' => match ($attribute::class) {
                    AsPeriodicTask::class => 'every',
                    AsCronTask::class => 'cron',
                }];
                if ($reflector instanceof \ReflectionMethod) {
                    if (isset($tagAttributes['method'])) {
                        throw new LogicException(\sprintf('"%s" attribute cannot declare a method on "%s::%s()".', $attribute::class, $reflector->class, $reflector->name));
                    }
                    $tagAttributes['method'] = $reflector->getName();
                }
                $definition->addTag('scheduler.task', $tagAttributes);
            });
        }
        if (!$container->getParameter('kernel.debug')) {
            // remove tagged iterator argument for resource checkers
            $container->getDefinition('config_cache_factory')->setArguments([]);
        }
        if (!$config['disallow_search_engine_index']) {
            $container->removeDefinition('disallow_search_engine_index_response_listener');
        }
        $container->registerForAutoconfiguration(RouteLoaderInterface::class)->addTag('routing.route_loader');
        $container->setParameter('container.behavior_describing_tags', ['annotations.cached_reader', 'container.do_not_inline', 'container.service_locator', 'container.service_subscriber', 'kernel.event_subscriber', 'kernel.event_listener', 'kernel.locale_aware', 'kernel.reset']);
    }
    public function getConfiguration(array $config, ContainerBuilder $container): ?ConfigurationInterface
    {
        return new Configuration($container->getParameter('kernel.debug'));
    }
    protected function hasConsole(): bool
    {
        return class_exists(Application::class);
    }
    private function registerFormConfiguration(array $config, ContainerBuilder $container, PhpFileLoader $loader): void
    {
        $loader->load('form.php');
        if (null === $config['form']['csrf_protection']['enabled']) {
            $this->writeConfigEnabled('form.csrf_protection', $config['csrf_protection']['enabled'], $config['form']['csrf_protection']);
        }
        if ($this->readConfigEnabled('form.csrf_protection', $container, $config['form']['csrf_protection'])) {
            if (!$container->hasDefinition('security.csrf.token_generator')) {
                throw new \LogicException('To use form CSRF protection, "framework.csrf_protection" must be enabled.');
            }
            $loader->load('form_csrf.php');
            $container->setParameter('form.type_extension.csrf.enabled', \true);
            $container->setParameter('form.type_extension.csrf.field_name', $config['form']['csrf_protection']['field_name']);
        } else {
            $container->setParameter('form.type_extension.csrf.enabled', \false);
        }
        if (!ContainerBuilder::willBeAvailable('symfony/translation', Translator::class, ['symfony/framework-bundle', 'symfony/form'])) {
            $container->removeDefinition('form.type_extension.upload.validator');
        }
    }
    private function registerHttpCacheConfiguration(array $config, ContainerBuilder $container, bool $httpMethodOverride): void
    {
        $options = $config;
        unset($options['enabled']);
        if (!$options['private_headers']) {
            unset($options['private_headers']);
        }
        if (!$options['skip_response_headers']) {
            unset($options['skip_response_headers']);
        }
        $container->getDefinition('http_cache')->setPublic($config['enabled'])->replaceArgument(3, $options);
        if ($httpMethodOverride) {
            $container->getDefinition('http_cache')->addArgument((new Definition('void'))->setFactory([Request::class, 'enableHttpMethodParameterOverride']));
        }
    }
    private function registerEsiConfiguration(array $config, ContainerBuilder $container, PhpFileLoader $loader): void
    {
        if (!$this->readConfigEnabled('esi', $container, $config)) {
            $container->removeDefinition('fragment.renderer.esi');
            return;
        }
        $loader->load('esi.php');
    }
    private function registerSsiConfiguration(array $config, ContainerBuilder $container, PhpFileLoader $loader): void
    {
        if (!$this->readConfigEnabled('ssi', $container, $config)) {
            $container->removeDefinition('fragment.renderer.ssi');
            return;
        }
        $loader->load('ssi.php');
    }
    private function registerFragmentsConfiguration(array $config, ContainerBuilder $container, PhpFileLoader $loader): void
    {
        if (!$this->readConfigEnabled('fragments', $container, $config)) {
            $container->removeDefinition('fragment.renderer.hinclude');
            return;
        }
        $container->setParameter('fragment.renderer.hinclude.global_template', $config['hinclude_default_template']);
        $loader->load('fragment_listener.php');
        $container->setParameter('fragment.path', $config['path']);
    }
    private function registerProfilerConfiguration(array $config, ContainerBuilder $container, PhpFileLoader $loader): void
    {
        if (!$this->readConfigEnabled('profiler', $container, $config)) {
            // this is needed for the WebProfiler to work even if the profiler is disabled
            $container->setParameter('data_collector.templates', []);
            return;
        }
        $loader->load('profiling.php');
        $loader->load('collectors.php');
        $loader->load('cache_debug.php');
        if ($this->isInitializedConfigEnabled('form')) {
            $loader->load('form_debug.php');
        }
        if ($this->isInitializedConfigEnabled('validation')) {
            $loader->load('validator_debug.php');
        }
        if ($this->isInitializedConfigEnabled('translator')) {
            $loader->load('translation_debug.php');
            $container->getDefinition('translator.data_collector')->setDecoratedService('translator');
        }
        if ($this->isInitializedConfigEnabled('messenger')) {
            $loader->load('messenger_debug.php');
        }
        if ($this->isInitializedConfigEnabled('mailer')) {
            $loader->load('mailer_debug.php');
        }
        if ($this->isInitializedConfigEnabled('workflows')) {
            $loader->load('workflow_debug.php');
        }
        if ($this->isInitializedConfigEnabled('http_client')) {
            $loader->load('http_client_debug.php');
        }
        if ($this->isInitializedConfigEnabled('notifier')) {
            $loader->load('notifier_debug.php');
        }
        if ($this->isInitializedConfigEnabled('serializer') && $config['collect_serializer_data']) {
            $loader->load('serializer_debug.php');
        }
        $container->setParameter('profiler_listener.only_exceptions', $config['only_exceptions']);
        $container->setParameter('profiler_listener.only_main_requests', $config['only_main_requests']);
        // Choose storage class based on the DSN
        [$class] = explode(':', $config['dsn'], 2);
        if ('file' !== $class) {
            throw new \LogicException(\sprintf('Driver "%s" is not supported for the profiler.', $class));
        }
        $container->setParameter('profiler.storage.dsn', $config['dsn']);
        $container->getDefinition('profiler')->addArgument($config['collect'])->addTag('kernel.reset', ['method' => 'reset']);
        $container->getDefinition('profiler_listener')->addArgument($config['collect_parameter']);
        if (!$container->getParameter('kernel.debug') || !$this->hasConsole() || !$container->has('debug.stopwatch') || !class_exists(CliRequest::class)) {
            $container->removeDefinition('console_profiler_listener');
        }
        if (!$this->hasConsole() || !class_exists(CommandDataCollector::class)) {
            $container->removeDefinition('.data_collector.command');
        }
    }
    private function registerWorkflowConfiguration(array $config, ContainerBuilder $container, PhpFileLoader $loader): void
    {
        if (!$config['enabled']) {
            $container->removeDefinition('console.command.workflow_dump');
            return;
        }
        if (!class_exists(Workflow\Workflow::class)) {
            throw new LogicException('Workflow support cannot be enabled as the Workflow component is not installed. Try running "composer require symfony/workflow".');
        }
        $loader->load('workflow.php');
        $registryDefinition = $container->getDefinition('workflow.registry');
        foreach ($config['workflows'] as $name => $workflow) {
            $type = $workflow['type'];
            $workflowId = \sprintf('%s.%s', $type, $name);
            // Process Metadata (workflow + places (transition is done in the "create transition" block))
            $metadataStoreDefinition = new Definition(Workflow\Metadata\InMemoryMetadataStore::class, [[], [], null]);
            if ($workflow['metadata']) {
                $metadataStoreDefinition->replaceArgument(0, $workflow['metadata']);
            }
            $placesMetadata = [];
            foreach ($workflow['places'] as $place) {
                if ($place['metadata']) {
                    $placesMetadata[$place['name']] = $place['metadata'];
                }
            }
            if ($placesMetadata) {
                $metadataStoreDefinition->replaceArgument(1, $placesMetadata);
            }
            // Create transitions
            $transitions = [];
            $guardsConfiguration = [];
            $transitionsMetadataDefinition = new Definition(\SplObjectStorage::class);
            // Global transition counter per workflow
            $transitionCounter = 0;
            foreach ($workflow['transitions'] as $transition) {
                if ('workflow' === $type) {
                    $transitionId = \sprintf('.%s.transition.%s', $workflowId, $transitionCounter++);
                    $container->register($transitionId, Workflow\Transition::class)->setArguments([$transition['name'], $transition['from'], $transition['to']]);
                    $transitions[] = new Reference($transitionId);
                    if (isset($transition['guard'])) {
                        $eventName = \sprintf('workflow.%s.guard.%s', $name, $transition['name']);
                        $guardsConfiguration[$eventName][] = new Definition(Workflow\EventListener\GuardExpression::class, [new Reference($transitionId), $transition['guard']]);
                    }
                    if ($transition['metadata']) {
                        $transitionsMetadataDefinition->addMethodCall('offsetSet', [new Reference($transitionId), $transition['metadata']]);
                    }
                } elseif ('state_machine' === $type) {
                    foreach ($transition['from'] as $from) {
                        foreach ($transition['to'] as $to) {
                            $transitionId = \sprintf('.%s.transition.%s', $workflowId, $transitionCounter++);
                            $container->register($transitionId, Workflow\Transition::class)->setArguments([$transition['name'], $from, $to]);
                            $transitions[] = new Reference($transitionId);
                            if (isset($transition['guard'])) {
                                $eventName = \sprintf('workflow.%s.guard.%s', $name, $transition['name']);
                                $guardsConfiguration[$eventName][] = new Definition(Workflow\EventListener\GuardExpression::class, [new Reference($transitionId), $transition['guard']]);
                            }
                            if ($transition['metadata']) {
                                $transitionsMetadataDefinition->addMethodCall('offsetSet', [new Reference($transitionId), $transition['metadata']]);
                            }
                        }
                    }
                }
            }
            $metadataStoreDefinition->replaceArgument(2, $transitionsMetadataDefinition);
            $container->setDefinition(\sprintf('%s.metadata_store', $workflowId), $metadataStoreDefinition);
            // Create places
            $places = array_column($workflow['places'], 'name');
            $initialMarking = $workflow['initial_marking'] ?? [];
            // Create a Definition
            $definitionDefinition = new Definition(Workflow\Definition::class);
            $definitionDefinition->addArgument($places);
            $definitionDefinition->addArgument($transitions);
            $definitionDefinition->addArgument($initialMarking);
            $definitionDefinition->addArgument(new Reference(\sprintf('%s.metadata_store', $workflowId)));
            // Create MarkingStore
            $markingStoreDefinition = null;
            if (isset($workflow['marking_store']['type']) || isset($workflow['marking_store']['property'])) {
                $markingStoreDefinition = new ChildDefinition('workflow.marking_store.method');
                $markingStoreDefinition->setArguments([
                    'state_machine' === $type,
                    // single state
                    $workflow['marking_store']['property'] ?? 'marking',
                ]);
            } elseif (isset($workflow['marking_store']['service'])) {
                $markingStoreDefinition = new Reference($workflow['marking_store']['service']);
            }
            // Create Workflow
            $workflowDefinition = new ChildDefinition(\sprintf('%s.abstract', $type));
            $workflowDefinition->replaceArgument(0, new Reference(\sprintf('%s.definition', $workflowId)));
            $workflowDefinition->replaceArgument(1, $markingStoreDefinition);
            $workflowDefinition->replaceArgument(3, $name);
            $workflowDefinition->replaceArgument(4, $workflow['events_to_dispatch']);
            $workflowDefinition->addTag('workflow', ['name' => $name]);
            if ('workflow' === $type) {
                $workflowDefinition->addTag('workflow.workflow', ['name' => $name]);
            } elseif ('state_machine' === $type) {
                $workflowDefinition->addTag('workflow.state_machine', ['name' => $name]);
            }
            // Store to container
            $container->setDefinition($workflowId, $workflowDefinition);
            $container->setDefinition(\sprintf('%s.definition', $workflowId), $definitionDefinition);
            $container->registerAliasForArgument($workflowId, WorkflowInterface::class, $name . '.' . $type);
            $container->registerAliasForArgument($workflowId, WorkflowInterface::class, $name);
            // Validate Workflow
            if ('state_machine' === $workflow['type']) {
                $validator = new Workflow\Validator\StateMachineValidator();
            } else {
                $validator = new Workflow\Validator\WorkflowValidator();
            }
            $trs = array_map(fn(Reference $ref): Workflow\Transition => $container->get((string) $ref), $transitions);
            $realDefinition = new Workflow\Definition($places, $trs, $initialMarking);
            $validator->validate($realDefinition, $name);
            // Add workflow to Registry
            if ($workflow['supports']) {
                foreach ($workflow['supports'] as $supportedClassName) {
                    $strategyDefinition = new Definition(Workflow\SupportStrategy\InstanceOfSupportStrategy::class, [$supportedClassName]);
                    $registryDefinition->addMethodCall('addWorkflow', [new Reference($workflowId), $strategyDefinition]);
                }
            } elseif (isset($workflow['support_strategy'])) {
                $registryDefinition->addMethodCall('addWorkflow', [new Reference($workflowId), new Reference($workflow['support_strategy'])]);
            }
            // Enable the AuditTrail
            if ($workflow['audit_trail']['enabled']) {
                $listener = new Definition(Workflow\EventListener\AuditTrailListener::class);
                $listener->addTag('monolog.logger', ['channel' => 'workflow']);
                $listener->addTag('kernel.event_listener', ['event' => \sprintf('workflow.%s.leave', $name), 'method' => 'onLeave']);
                $listener->addTag('kernel.event_listener', ['event' => \sprintf('workflow.%s.transition', $name), 'method' => 'onTransition']);
                $listener->addTag('kernel.event_listener', ['event' => \sprintf('workflow.%s.enter', $name), 'method' => 'onEnter']);
                $listener->addArgument(new Reference('logger'));
                $container->setDefinition(\sprintf('.%s.listener.audit_trail', $workflowId), $listener);
            }
            // Add Guard Listener
            if ($guardsConfiguration) {
                if (!class_exists(ExpressionLanguage::class)) {
                    throw new LogicException('Cannot guard workflows as the ExpressionLanguage component is not installed. Try running "composer require symfony/expression-language".');
                }
                if (!class_exists(AuthenticationEvents::class)) {
                    throw new LogicException('Cannot guard workflows as the Security component is not installed. Try running "composer require symfony/security-core".');
                }
                $guard = new Definition(Workflow\EventListener\GuardListener::class);
                $guard->setArguments([$guardsConfiguration, new Reference('workflow.security.expression_language'), new Reference('security.token_storage'), new Reference('security.authorization_checker'), new Reference('security.authentication.trust_resolver'), new Reference('security.role_hierarchy'), new Reference('validator', ContainerInterface::NULL_ON_INVALID_REFERENCE)]);
                foreach ($guardsConfiguration as $eventName => $config) {
                    $guard->addTag('kernel.event_listener', ['event' => $eventName, 'method' => 'onTransition']);
                }
                $container->setDefinition(\sprintf('.%s.listener.guard', $workflowId), $guard);
                $container->setParameter('workflow.has_guard_listeners', \true);
            }
        }
        $listenerAttributes = [Workflow\Attribute\AsAnnounceListener::class, Workflow\Attribute\AsCompletedListener::class, Workflow\Attribute\AsEnterListener::class, Workflow\Attribute\AsEnteredListener::class, Workflow\Attribute\AsGuardListener::class, Workflow\Attribute\AsLeaveListener::class, Workflow\Attribute\AsTransitionListener::class];
        foreach ($listenerAttributes as $attribute) {
            $container->registerAttributeForAutoconfiguration($attribute, static function (ChildDefinition $definition, AsEventListener $attribute, \ReflectionClass|\ReflectionMethod $reflector) {
                $tagAttributes = get_object_vars($attribute);
                if ($reflector instanceof \ReflectionMethod) {
                    if (isset($tagAttributes['method'])) {
                        throw new LogicException(\sprintf('"%s" attribute cannot declare a method on "%s::%s()".', $attribute::class, $reflector->class, $reflector->name));
                    }
                    $tagAttributes['method'] = $reflector->getName();
                }
                $definition->addTag('kernel.event_listener', $tagAttributes);
            });
        }
    }
    private function registerDebugConfiguration(array $config, ContainerBuilder $container, PhpFileLoader $loader): void
    {
        $loader->load('debug_prod.php');
        $debug = $container->getParameter('kernel.debug');
        if (class_exists(Stopwatch::class)) {
            $container->register('debug.stopwatch', Stopwatch::class)->addArgument(\true)->setPublic($debug)->addTag('kernel.reset', ['method' => 'reset']);
            $container->setAlias(Stopwatch::class, new Alias('debug.stopwatch', \false));
        }
        if ($debug && !$container->hasParameter('debug.container.dump')) {
            $container->setParameter('debug.container.dump', '%kernel.build_dir%/%kernel.container_class%.xml');
        }
        if ($debug && class_exists(Stopwatch::class)) {
            $loader->load('debug.php');
        }
        $definition = $container->findDefinition('debug.error_handler_configurator');
        if (\false === $config['log']) {
            $definition->replaceArgument(0, null);
        } elseif (\true !== $config['log']) {
            $definition->replaceArgument(1, $config['log']);
        }
        if (!$config['throw']) {
            $container->setParameter('debug.error_handler.throw_at', 0);
        }
        if ($debug && class_exists(DebugProcessor::class)) {
            $definition = new Definition(DebugProcessor::class);
            $definition->addArgument(new Reference('.virtual_request_stack'));
            $definition->addTag('kernel.reset', ['method' => 'reset']);
            $container->setDefinition('debug.log_processor', $definition);
            $container->register('debug.debug_logger_configurator', DebugLoggerConfigurator::class)->setArguments([new Reference('debug.log_processor'), '%kernel.runtime_mode.web%']);
        }
    }
    private function registerRouterConfiguration(array $config, ContainerBuilder $container, PhpFileLoader $loader, array $enabledLocales = []): void
    {
        if (!$this->readConfigEnabled('router', $container, $config)) {
            $container->removeDefinition('console.command.router_debug');
            $container->removeDefinition('console.command.router_match');
            $container->removeDefinition('messenger.middleware.router_context');
            return;
        }
        if (!class_exists(RouterContextMiddleware::class)) {
            $container->removeDefinition('messenger.middleware.router_context');
        }
        $loader->load('routing.php');
        if ($config['utf8']) {
            $container->getDefinition('routing.loader')->replaceArgument(1, ['utf8' => \true]);
        }
        if ($enabledLocales) {
            $enabledLocales = implode('|', array_map('preg_quote', $enabledLocales));
            $container->getDefinition('routing.loader')->replaceArgument(2, ['_locale' => $enabledLocales]);
        }
        if (!ContainerBuilder::willBeAvailable('symfony/expression-language', ExpressionLanguage::class, ['symfony/framework-bundle', 'symfony/routing'])) {
            $container->removeDefinition('router.expression_language_provider');
        }
        $container->setParameter('router.resource', $config['resource']);
        $container->setParameter('router.cache_dir', $config['cache_dir']);
        $router = $container->findDefinition('router.default');
        $argument = $router->getArgument(2);
        $argument['strict_requirements'] = $config['strict_requirements'];
        if (isset($config['type'])) {
            $argument['resource_type'] = $config['type'];
        }
        $router->replaceArgument(2, $argument);
        $container->setParameter('request_listener.http_port', $config['http_port']);
        $container->setParameter('request_listener.https_port', $config['https_port']);
        if (null !== $config['default_uri']) {
            $container->setParameter('router.request_context.base_url', $config['default_uri']);
        }
        if ($this->isInitializedConfigEnabled('annotations') && (new \ReflectionClass(AttributeClassLoader::class))->hasProperty('reader')) {
            $container->getDefinition('routing.loader.attribute')->setArguments([new Reference('annotation_reader'), '%kernel.environment%']);
        }
    }
    private function registerSessionConfiguration(array $config, ContainerBuilder $container, PhpFileLoader $loader): void
    {
        $loader->load('session.php');
        // session storage
        $container->setAlias('session.storage.factory', $config['storage_factory_id']);
        $options = ['cache_limiter' => '0'];
        foreach (['name', 'cookie_lifetime', 'cookie_path', 'cookie_domain', 'cookie_secure', 'cookie_httponly', 'cookie_samesite', 'use_cookies', 'gc_maxlifetime', 'gc_probability', 'gc_divisor', 'sid_length', 'sid_bits_per_character'] as $key) {
            if (isset($config[$key])) {
                $options[$key] = $config[$key];
            }
        }
        if ('auto' === ($options['cookie_secure'] ?? null)) {
            $container->getDefinition('session.storage.factory.native')->replaceArgument(3, \true);
            $container->getDefinition('session.storage.factory.php_bridge')->replaceArgument(2, \true);
        }
        $container->setParameter('session.storage.options', $options);
        $container->setParameter('session.metadata.cookie_lifetime', $options['cookie_lifetime'] ?? null);
        // session handler (the internal callback registered with PHP session management)
        if (null === $config['handler_id']) {
            $config['save_path'] = null;
            $container->setAlias('session.handler', 'session.handler.native');
        } else {
            $container->resolveEnvPlaceholders($config['handler_id'], null, $usedEnvs);
            if ($usedEnvs || preg_match('#^[a-z]++://#', $config['handler_id'])) {
                $id = '.cache_connection.' . ContainerBuilder::hash($config['handler_id']);
                $container->getDefinition('session.abstract_handler')->replaceArgument(0, $container->hasDefinition($id) ? new Reference($id) : $config['handler_id']);
                $container->setAlias('session.handler', 'session.abstract_handler');
            } else {
                $container->setAlias('session.handler', $config['handler_id']);
            }
        }
        $container->setParameter('session.save_path', $config['save_path']);
        $container->setParameter('session.metadata.update_threshold', $config['metadata_update_threshold']);
    }
    private function registerRequestConfiguration(array $config, ContainerBuilder $container, PhpFileLoader $loader): void
    {
        if ($config['formats']) {
            $loader->load('request.php');
            $listener = $container->getDefinition('request.add_request_formats_listener');
            $listener->replaceArgument(0, $config['formats']);
        }
    }
    private function registerAssetsConfiguration(array $config, ContainerBuilder $container, PhpFileLoader $loader): void
    {
        $loader->load('assets.php');
        if ($config['version_strategy']) {
            $defaultVersion = new Reference($config['version_strategy']);
        } else {
            $defaultVersion = $this->createVersion($container, $config['version'], $config['version_format'], $config['json_manifest_path'], '_default', $config['strict_mode']);
        }
        $defaultPackage = $this->createPackageDefinition($config['base_path'], $config['base_urls'], $defaultVersion);
        $container->setDefinition('assets._default_package', $defaultPackage);
        foreach ($config['packages'] as $name => $package) {
            if (null !== $package['version_strategy']) {
                $version = new Reference($package['version_strategy']);
            } elseif (!\array_key_exists('version', $package) && null === $package['json_manifest_path']) {
                // if neither version nor json_manifest_path are specified, use the default
                $version = $defaultVersion;
            } else {
                // let format fallback to main version_format
                $format = $package['version_format'] ?: $config['version_format'];
                $version = $package['version'] ?? null;
                $version = $this->createVersion($container, $version, $format, $package['json_manifest_path'], $name, $package['strict_mode']);
            }
            $packageDefinition = $this->createPackageDefinition($package['base_path'], $package['base_urls'], $version)->addTag('assets.package', ['package' => $name]);
            $container->setDefinition('assets._package_' . $name, $packageDefinition);
            $container->registerAliasForArgument('assets._package_' . $name, PackageInterface::class, $name . '.package');
        }
    }
    private function registerAssetMapperConfiguration(array $config, ContainerBuilder $container, PhpFileLoader $loader, bool $assetEnabled, bool $httpClientEnabled): void
    {
        $loader->load('asset_mapper.php');
        if (!$assetEnabled) {
            $container->removeDefinition('asset_mapper.asset_package');
        }
        if (!$httpClientEnabled) {
            $container->register('asset_mapper.http_client', HttpClientInterface::class)->addTag('container.error')->addError('You cannot use the AssetMapper integration since the HttpClient component is not enabled. Try enabling the "framework.http_client" config option.');
        }
        $paths = $config['paths'];
        foreach ($container->getParameter('kernel.bundles_metadata') as $name => $bundle) {
            if ($container->fileExists($dir = $bundle['path'] . '/Resources/public') || $container->fileExists($dir = $bundle['path'] . '/public')) {
                $paths[$dir] = \sprintf('bundles/%s', preg_replace('/bundle$/', '', strtolower($name)));
            }
        }
        $excludedPathPatterns = [];
        foreach ($config['excluded_patterns'] as $path) {
            $excludedPathPatterns[] = Glob::toRegex($path, \true, \false);
        }
        $container->getDefinition('asset_mapper.repository')->setArgument(0, $paths)->setArgument(2, $excludedPathPatterns)->setArgument(3, $config['exclude_dotfiles']);
        $container->getDefinition('asset_mapper.public_assets_path_resolver')->setArgument(0, $config['public_prefix']);
        $publicDirectory = $this->getPublicDirectory($container);
        $publicAssetsDirectory = rtrim($publicDirectory . '/' . ltrim($config['public_prefix'], '/'), '/');
        $container->getDefinition('asset_mapper.local_public_assets_filesystem')->setArgument(0, $publicDirectory);
        $container->getDefinition('asset_mapper.compiled_asset_mapper_config_reader')->setArgument(0, $publicAssetsDirectory);
        if (!$config['server']) {
            $container->removeDefinition('asset_mapper.dev_server_subscriber');
        } else {
            $container->getDefinition('asset_mapper.dev_server_subscriber')->setArgument(1, $config['public_prefix'])->setArgument(2, $config['extensions']);
        }
        $container->getDefinition('asset_mapper.compiler.css_asset_url_compiler')->setArgument(0, $config['missing_import_mode']);
        $container->getDefinition('asset_mapper.compiler.javascript_import_path_compiler')->setArgument(1, $config['missing_import_mode']);
        $container->getDefinition('asset_mapper.importmap.remote_package_storage')->replaceArgument(0, $config['vendor_dir']);
        $container->getDefinition('asset_mapper.mapped_asset_factory')->replaceArgument(2, $config['vendor_dir']);
        $container->getDefinition('asset_mapper.importmap.config_reader')->replaceArgument(0, $config['importmap_path']);
        $container->getDefinition('asset_mapper.importmap.renderer')->replaceArgument(3, $config['importmap_polyfill'])->replaceArgument(4, $config['importmap_script_attributes']);
    }
    /**
     * Returns a definition for an asset package.
     */
    private function createPackageDefinition(?string $basePath, array $baseUrls, Reference $version): Definition
    {
        if ($basePath && $baseUrls) {
            throw new \LogicException('An asset package cannot have base URLs and base paths.');
        }
        $package = new ChildDefinition($baseUrls ? 'assets.url_package' : 'assets.path_package');
        $package->replaceArgument(0, $baseUrls ?: $basePath)->replaceArgument(1, $version);
        return $package;
    }
    private function createVersion(ContainerBuilder $container, ?string $version, ?string $format, ?string $jsonManifestPath, string $name, bool $strictMode): Reference
    {
        // Configuration prevents $version and $jsonManifestPath from being set
        if (null !== $version) {
            $def = new ChildDefinition('assets.static_version_strategy');
            $def->replaceArgument(0, $version)->replaceArgument(1, $format);
            $container->setDefinition('assets._version_' . $name, $def);
            return new Reference('assets._version_' . $name);
        }
        if (null !== $jsonManifestPath) {
            $def = new ChildDefinition('assets.json_manifest_version_strategy');
            $def->replaceArgument(0, $jsonManifestPath);
            $def->replaceArgument(2, $strictMode);
            $container->setDefinition('assets._version_' . $name, $def);
            return new Reference('assets._version_' . $name);
        }
        return new Reference('assets.empty_version_strategy');
    }
    private function registerTranslatorConfiguration(array $config, ContainerBuilder $container, LoaderInterface $loader, string $defaultLocale, array $enabledLocales): void
    {
        if (!$this->readConfigEnabled('translator', $container, $config)) {
            $container->removeDefinition('console.command.translation_debug');
            $container->removeDefinition('console.command.translation_extract');
            $container->removeDefinition('console.command.translation_pull');
            $container->removeDefinition('console.command.translation_push');
            return;
        }
        $loader->load('translation.php');
        if (!ContainerBuilder::willBeAvailable('symfony/translation', LocaleSwitcher::class, ['symfony/framework-bundle'])) {
            $container->removeDefinition('translation.locale_switcher');
        }
        // don't use ContainerBuilder::willBeAvailable() as these are not needed in production
        if (interface_exists(Parser::class) && class_exists(PhpAstExtractor::class)) {
            $container->removeDefinition('translation.extractor.php');
        } else {
            $container->removeDefinition('translation.extractor.php_ast');
        }
        $loader->load('translation_providers.php');
        // Use the "real" translator instead of the identity default
        $container->setAlias('translator', 'translator.default')->setPublic(\true);
        $container->setAlias('translator.formatter', new Alias($config['formatter'], \false));
        $translator = $container->findDefinition('translator.default');
        $translator->addMethodCall('setFallbackLocales', [$config['fallbacks'] ?: [$defaultLocale]]);
        $defaultOptions = $translator->getArgument(4);
        $defaultOptions['cache_dir'] = $config['cache_dir'];
        $translator->setArgument(4, $defaultOptions);
        $translator->setArgument(5, $enabledLocales);
        $container->setParameter('translator.logging', $config['logging']);
        $container->setParameter('translator.default_path', $config['default_path']);
        // Discover translation directories
        $dirs = [];
        $transPaths = [];
        $nonExistingDirs = [];
        if (ContainerBuilder::willBeAvailable('symfony/validator', Validation::class, ['symfony/framework-bundle', 'symfony/translation'])) {
            $r = new \ReflectionClass(Validation::class);
            $dirs[] = $transPaths[] = \dirname($r->getFileName()) . '/Resources/translations';
        }
        if (ContainerBuilder::willBeAvailable('symfony/form', Form::class, ['symfony/framework-bundle', 'symfony/translation'])) {
            $r = new \ReflectionClass(Form::class);
            $dirs[] = $transPaths[] = \dirname($r->getFileName()) . '/Resources/translations';
        }
        if (ContainerBuilder::willBeAvailable('symfony/security-core', AuthenticationException::class, ['symfony/framework-bundle', 'symfony/translation'])) {
            $r = new \ReflectionClass(AuthenticationException::class);
            $dirs[] = $transPaths[] = \dirname($r->getFileName(), 2) . '/Resources/translations';
        }
        $defaultDir = $container->getParameterBag()->resolveValue($config['default_path']);
        foreach ($container->getParameter('kernel.bundles_metadata') as $name => $bundle) {
            if ($container->fileExists($dir = $bundle['path'] . '/Resources/translations') || $container->fileExists($dir = $bundle['path'] . '/translations')) {
                $dirs[] = $transPaths[] = $dir;
            } else {
                $nonExistingDirs[] = $dir;
            }
        }
        foreach ($config['paths'] as $dir) {
            if ($container->fileExists($dir)) {
                $dirs[] = $transPaths[] = $dir;
            } else {
                throw new \UnexpectedValueException(\sprintf('"%s" defined in translator.paths does not exist or is not a directory.', $dir));
            }
        }
        if ($container->hasDefinition('console.command.translation_debug')) {
            $container->getDefinition('console.command.translation_debug')->replaceArgument(5, $transPaths);
        }
        if ($container->hasDefinition('console.command.translation_extract')) {
            $container->getDefinition('console.command.translation_extract')->replaceArgument(6, $transPaths);
        }
        if (null === $defaultDir) {
            // allow null
        } elseif ($container->fileExists($defaultDir)) {
            $dirs[] = $defaultDir;
        } else {
            $nonExistingDirs[] = $defaultDir;
        }
        // Register translation resources
        if ($dirs) {
            $files = [];
            foreach ($dirs as $dir) {
                $finder = Finder::create()->followLinks()->files()->filter(fn(\SplFileInfo $file) => 2 <= substr_count($file->getBasename(), '.') && preg_match('/\.\w+$/', $file->getBasename()))->in($dir)->sortByName();
                foreach ($finder as $file) {
                    $fileNameParts = explode('.', basename($file));
                    $locale = $fileNameParts[\count($fileNameParts) - 2];
                    if (!isset($files[$locale])) {
                        $files[$locale] = [];
                    }
                    $files[$locale][] = (string) $file;
                }
            }
            $projectDir = $container->getParameter('kernel.project_dir');
            $options = array_merge($translator->getArgument(4), ['resource_files' => $files, 'scanned_directories' => $scannedDirectories = array_merge($dirs, $nonExistingDirs), 'cache_vary' => ['scanned_directories' => array_map(fn($dir) => str_starts_with($dir, $projectDir . '/') ? substr($dir, 1 + \strlen($projectDir)) : $dir, $scannedDirectories)]]);
            $translator->replaceArgument(4, $options);
        }
        if ($config['pseudo_localization']['enabled']) {
            $options = $config['pseudo_localization'];
            unset($options['enabled']);
            $container->register('translator.pseudo', PseudoLocalizationTranslator::class)->setDecoratedService('translator', null, -1)->setArguments([new Reference('translator.pseudo.inner'), $options]);
        }
        $classToServices = [TranslationBridge\Crowdin\CrowdinProviderFactory::class => 'translation.provider_factory.crowdin', TranslationBridge\Loco\LocoProviderFactory::class => 'translation.provider_factory.loco', TranslationBridge\Lokalise\LokaliseProviderFactory::class => 'translation.provider_factory.lokalise', TranslationBridge\Phrase\PhraseProviderFactory::class => 'translation.provider_factory.phrase'];
        $parentPackages = ['symfony/framework-bundle', 'symfony/translation', 'symfony/http-client'];
        foreach ($classToServices as $class => $service) {
            $package = substr($service, \strlen('translation.provider_factory.'));
            if (!$container->hasDefinition('http_client') || !ContainerBuilder::willBeAvailable(\sprintf('symfony/%s-translation-provider', $package), $class, $parentPackages)) {
                $container->removeDefinition($service);
            }
        }
        if (!$config['providers']) {
            return;
        }
        $locales = $enabledLocales;
        foreach ($config['providers'] as $provider) {
            if ($provider['locales']) {
                $locales = array_merge($locales, $provider['locales']);
            }
        }
        $locales = array_values(array_unique($locales));
        $container->getDefinition('console.command.translation_pull')->replaceArgument(4, array_merge($transPaths, [$config['default_path']]))->replaceArgument(5, $locales);
        $container->getDefinition('console.command.translation_push')->replaceArgument(2, array_merge($transPaths, [$config['default_path']]))->replaceArgument(3, $locales);
        $container->getDefinition('translation.provider_collection_factory')->replaceArgument(1, $locales);
        $container->getDefinition('translation.provider_collection')->setArgument(0, $config['providers']);
    }
    private function registerValidationConfiguration(array $config, ContainerBuilder $container, PhpFileLoader $loader, bool $propertyInfoEnabled): void
    {
        if (!$this->readConfigEnabled('validation', $container, $config)) {
            $container->removeDefinition('console.command.validator_debug');
            return;
        }
        if (!class_exists(Validation::class)) {
            throw new LogicException('Validation support cannot be enabled as the Validator component is not installed. Try running "composer require symfony/validator".');
        }
        if (!isset($config['email_validation_mode'])) {
            $config['email_validation_mode'] = 'loose';
        }
        $loader->load('validator.php');
        $validatorBuilder = $container->getDefinition('validator.builder');
        $container->setParameter('validator.translation_domain', $config['translation_domain']);
        $files = ['xml' => [], 'yml' => []];
        $this->registerValidatorMapping($container, $config, $files);
        if (!empty($files['xml'])) {
            $validatorBuilder->addMethodCall('addXmlMappings', [$files['xml']]);
        }
        if (!empty($files['yml'])) {
            $validatorBuilder->addMethodCall('addYamlMappings', [$files['yml']]);
        }
        $definition = $container->findDefinition('validator.email');
        $definition->replaceArgument(0, $config['email_validation_mode']);
        if (\array_key_exists('enable_attributes', $config) && $config['enable_attributes']) {
            $validatorBuilder->addMethodCall('enableAttributeMapping', [\true]);
            if ($this->isInitializedConfigEnabled('annotations') && method_exists(ValidatorBuilder::class, 'setDoctrineAnnotationReader')) {
                $validatorBuilder->addMethodCall('setDoctrineAnnotationReader', [new Reference('annotation_reader')]);
            }
        }
        if (\array_key_exists('static_method', $config) && $config['static_method']) {
            foreach ($config['static_method'] as $methodName) {
                $validatorBuilder->addMethodCall('addMethodMapping', [$methodName]);
            }
        }
        if (!$container->getParameter('kernel.debug')) {
            $validatorBuilder->addMethodCall('setMappingCache', [new Reference('validator.mapping.cache.adapter')]);
        }
        $container->setParameter('validator.auto_mapping', $config['auto_mapping']);
        if (!$propertyInfoEnabled || !class_exists(PropertyInfoLoader::class)) {
            $container->removeDefinition('validator.property_info_loader');
        }
        $container->getDefinition('validator.not_compromised_password')->setArgument(2, $config['not_compromised_password']['enabled'])->setArgument(3, $config['not_compromised_password']['endpoint']);
        if (!class_exists(ExpressionLanguage::class)) {
            $container->removeDefinition('validator.expression_language');
            $container->removeDefinition('validator.expression_language_provider');
        } elseif (!class_exists(ExpressionLanguageProvider::class)) {
            $container->removeDefinition('validator.expression_language_provider');
        }
    }
    private function registerValidatorMapping(ContainerBuilder $container, array $config, array &$files): void
    {
        $fileRecorder = function ($extension, $path) use (&$files) {
            $files['yaml' === $extension ? 'yml' : $extension][] = $path;
        };
        if (ContainerBuilder::willBeAvailable('symfony/form', Form::class, ['symfony/framework-bundle', 'symfony/validator'])) {
            $reflClass = new \ReflectionClass(Form::class);
            $fileRecorder('xml', \dirname($reflClass->getFileName()) . '/Resources/config/validation.xml');
        }
        foreach ($container->getParameter('kernel.bundles_metadata') as $bundle) {
            $configDir = is_dir($bundle['path'] . '/Resources/config') ? $bundle['path'] . '/Resources/config' : $bundle['path'] . '/config';
            if ($container->fileExists($file = $configDir . '/validation.yaml', \false) || $container->fileExists($file = $configDir . '/validation.yml', \false)) {
                $fileRecorder('yml', $file);
            }
            if ($container->fileExists($file = $configDir . '/validation.xml', \false)) {
                $fileRecorder('xml', $file);
            }
            if ($container->fileExists($dir = $configDir . '/validation', '/^$/')) {
                $this->registerMappingFilesFromDir($dir, $fileRecorder);
            }
        }
        $projectDir = $container->getParameter('kernel.project_dir');
        if ($container->fileExists($dir = $projectDir . '/config/validator', '/^$/')) {
            $this->registerMappingFilesFromDir($dir, $fileRecorder);
        }
        $this->registerMappingFilesFromConfig($container, $config, $fileRecorder);
    }
    private function registerMappingFilesFromDir(string $dir, callable $fileRecorder): void
    {
        foreach (Finder::create()->followLinks()->files()->in($dir)->name('/\.(xml|ya?ml)$/')->sortByName() as $file) {
            $fileRecorder($file->getExtension(), $file->getRealPath());
        }
    }
    private function registerMappingFilesFromConfig(ContainerBuilder $container, array $config, callable $fileRecorder): void
    {
        foreach ($config['mapping']['paths'] as $path) {
            if (is_dir($path)) {
                $this->registerMappingFilesFromDir($path, $fileRecorder);
                $container->addResource(new DirectoryResource($path, '/^$/'));
            } elseif ($container->fileExists($path, \false)) {
                if (!preg_match('/\.(xml|ya?ml)$/', $path, $matches)) {
                    throw new \RuntimeException(\sprintf('Unsupported mapping type in "%s", supported types are XML & Yaml.', $path));
                }
                $fileRecorder($matches[1], $path);
            } else {
                throw new \RuntimeException(\sprintf('Could not open file or directory "%s".', $path));
            }
        }
    }
    private function registerAnnotationsConfiguration(array $config, ContainerBuilder $container, LoaderInterface $loader): void
    {
        if (!$this->isInitializedConfigEnabled('annotations')) {
            return;
        }
        if (!class_exists(\_ContaoManager\Doctrine\Common\Annotations\Annotation::class)) {
            throw new LogicException('Annotations cannot be enabled as the Doctrine Annotation library is not installed. Try running "composer require doctrine/annotations".');
        }
        trigger_deprecation('symfony/framework-bundle', '6.4', 'Enabling the integration of Doctrine annotations is deprecated. Set the "framework.annotations.enabled" config option to false.');
        $loader->load('annotations.php');
        if ('none' === $config['cache']) {
            $container->removeDefinition('annotations.cached_reader');
            return;
        }
        if ('php_array' === $config['cache']) {
            $cacheService = 'annotations.cache_adapter';
            // Enable warmer only if PHP array is used for cache
            $definition = $container->findDefinition('annotations.cache_warmer');
            $definition->addTag('kernel.cache_warmer');
        } else {
            $cacheService = 'annotations.filesystem_cache_adapter';
            $cacheDir = $container->getParameterBag()->resolveValue($config['file_cache_dir']);
            if (!is_dir($cacheDir) && \false === @mkdir($cacheDir, 0777, \true) && !is_dir($cacheDir)) {
                throw new \RuntimeException(\sprintf('Could not create cache directory "%s".', $cacheDir));
            }
            $container->getDefinition('annotations.filesystem_cache_adapter')->replaceArgument(2, $cacheDir);
        }
        $container->getDefinition('annotations.cached_reader')->replaceArgument(2, $config['debug'])->addArgument(new ServiceClosureArgument(new Reference($cacheService)));
        $container->setAlias('annotation_reader', 'annotations.cached_reader');
        $container->setAlias(Reader::class, new Alias('annotations.cached_reader', \false));
        $container->removeDefinition('annotations.psr_cached_reader');
    }
    private function registerPropertyAccessConfiguration(array $config, ContainerBuilder $container, PhpFileLoader $loader): void
    {
        if (!$this->readConfigEnabled('property_access', $container, $config)) {
            return;
        }
        $loader->load('property_access.php');
        $magicMethods = PropertyAccessor::DISALLOW_MAGIC_METHODS;
        $magicMethods |= $config['magic_call'] ? PropertyAccessor::MAGIC_CALL : 0;
        $magicMethods |= $config['magic_get'] ? PropertyAccessor::MAGIC_GET : 0;
        $magicMethods |= $config['magic_set'] ? PropertyAccessor::MAGIC_SET : 0;
        $throw = PropertyAccessor::DO_NOT_THROW;
        $throw |= $config['throw_exception_on_invalid_index'] ? PropertyAccessor::THROW_ON_INVALID_INDEX : 0;
        $throw |= $config['throw_exception_on_invalid_property_path'] ? PropertyAccessor::THROW_ON_INVALID_PROPERTY_PATH : 0;
        $container->getDefinition('property_accessor')->replaceArgument(0, $magicMethods)->replaceArgument(1, $throw)->replaceArgument(3, new Reference(PropertyReadInfoExtractorInterface::class, ContainerInterface::NULL_ON_INVALID_REFERENCE))->replaceArgument(4, new Reference(PropertyWriteInfoExtractorInterface::class, ContainerInterface::NULL_ON_INVALID_REFERENCE));
    }
    private function registerSecretsConfiguration(array $config, ContainerBuilder $container, PhpFileLoader $loader): void
    {
        if (!$this->readConfigEnabled('secrets', $container, $config)) {
            $container->removeDefinition('console.command.secrets_set');
            $container->removeDefinition('console.command.secrets_list');
            $container->removeDefinition('console.command.secrets_remove');
            $container->removeDefinition('console.command.secrets_generate_key');
            $container->removeDefinition('console.command.secrets_decrypt_to_local');
            $container->removeDefinition('console.command.secrets_encrypt_from_local');
            return;
        }
        $loader->load('secrets.php');
        $container->getDefinition('secrets.vault')->replaceArgument(0, $config['vault_directory']);
        if ($config['local_dotenv_file']) {
            $container->getDefinition('secrets.local_vault')->replaceArgument(0, $config['local_dotenv_file']);
        } else {
            $container->removeDefinition('secrets.local_vault');
        }
        if ($config['decryption_env_var']) {
            if (!preg_match('/^(?:[-.\w\\\\]*+:)*+\w++$/', $config['decryption_env_var'])) {
                throw new InvalidArgumentException(\sprintf('Invalid value "%s" set as "decryption_env_var": only "word" characters are allowed.', $config['decryption_env_var']));
            }
            if (ContainerBuilder::willBeAvailable('symfony/string', LazyString::class, ['symfony/framework-bundle'])) {
                $container->getDefinition('secrets.decryption_key')->replaceArgument(1, $config['decryption_env_var']);
            } else {
                $container->getDefinition('secrets.vault')->replaceArgument(1, "%env({$config['decryption_env_var']})%");
                $container->removeDefinition('secrets.decryption_key');
            }
        } else {
            $container->getDefinition('secrets.vault')->replaceArgument(1, null);
            $container->removeDefinition('secrets.decryption_key');
        }
    }
    private function registerSecurityCsrfConfiguration(array $config, ContainerBuilder $container, PhpFileLoader $loader): void
    {
        if (!$this->readConfigEnabled('csrf_protection', $container, $config)) {
            return;
        }
        if (!class_exists(\_ContaoManager\Symfony\Component\Security\Csrf\CsrfToken::class)) {
            throw new LogicException('CSRF support cannot be enabled as the Security CSRF component is not installed. Try running "composer require symfony/security-csrf".');
        }
        if (!$this->isInitializedConfigEnabled('session')) {
            throw new \LogicException('CSRF protection needs sessions to be enabled.');
        }
        // Enable services for CSRF protection (even without forms)
        $loader->load('security_csrf.php');
        if (!class_exists(CsrfExtension::class)) {
            $container->removeDefinition('twig.extension.security_csrf');
        }
    }
    private function registerSerializerConfiguration(array $config, ContainerBuilder $container, PhpFileLoader $loader): void
    {
        $loader->load('serializer.php');
        $chainLoader = $container->getDefinition('serializer.mapping.chain_loader');
        if (!$this->isInitializedConfigEnabled('property_access')) {
            $container->removeAlias('serializer.property_accessor');
            $container->removeDefinition('serializer.normalizer.object');
        }
        if (!class_exists(Yaml::class)) {
            $container->removeDefinition('serializer.encoder.yaml');
        }
        if (!$this->isInitializedConfigEnabled('property_access')) {
            $container->removeDefinition('serializer.denormalizer.unwrapping');
        }
        if (!class_exists(Headers::class)) {
            $container->removeDefinition('serializer.normalizer.mime_message');
        }
        if ($container->getParameter('kernel.debug')) {
            $container->removeDefinition('serializer.mapping.cache_class_metadata_factory');
        }
        if (!$this->readConfigEnabled('translator', $container, $config)) {
            $container->removeDefinition('serializer.normalizer.translatable');
        }
        $serializerLoaders = [];
        if (isset($config['enable_attributes']) && $config['enable_attributes']) {
            $annotationLoader = new Definition(AttributeLoader::class, interface_exists(CacheableSupportsMethodInterface::class) ? [new Reference('annotation_reader', ContainerInterface::NULL_ON_INVALID_REFERENCE)] : []);
            $serializerLoaders[] = $annotationLoader;
        }
        $fileRecorder = function ($extension, $path) use (&$serializerLoaders) {
            $definition = new Definition(\in_array($extension, ['yaml', 'yml']) ? YamlFileLoader::class : XmlFileLoader::class, [$path]);
            $serializerLoaders[] = $definition;
        };
        foreach ($container->getParameter('kernel.bundles_metadata') as $bundle) {
            $configDir = is_dir($bundle['path'] . '/Resources/config') ? $bundle['path'] . '/Resources/config' : $bundle['path'] . '/config';
            if ($container->fileExists($file = $configDir . '/serialization.xml', \false)) {
                $fileRecorder('xml', $file);
            }
            if ($container->fileExists($file = $configDir . '/serialization.yaml', \false) || $container->fileExists($file = $configDir . '/serialization.yml', \false)) {
                $fileRecorder('yml', $file);
            }
            if ($container->fileExists($dir = $configDir . '/serialization', '/^$/')) {
                $this->registerMappingFilesFromDir($dir, $fileRecorder);
            }
        }
        $projectDir = $container->getParameter('kernel.project_dir');
        if ($container->fileExists($dir = $projectDir . '/config/serializer', '/^$/')) {
            $this->registerMappingFilesFromDir($dir, $fileRecorder);
        }
        $this->registerMappingFilesFromConfig($container, $config, $fileRecorder);
        $chainLoader->replaceArgument(0, $serializerLoaders);
        $container->getDefinition('serializer.mapping.cache_warmer')->replaceArgument(0, $serializerLoaders);
        if (isset($config['name_converter']) && $config['name_converter']) {
            $container->getDefinition('serializer.name_converter.metadata_aware')->setArgument(1, new Reference($config['name_converter']));
        }
        $defaultContext = $config['default_context'] ?? [];
        if ($defaultContext) {
            $container->setParameter('serializer.default_context', $defaultContext);
        }
        if ($container->hasDefinition('serializer.normalizer.object')) {
            $arguments = $container->getDefinition('serializer.normalizer.object')->getArguments();
            $context = $arguments[6] ?? $defaultContext;
            if (isset($config['circular_reference_handler']) && $config['circular_reference_handler']) {
                $context += ['circular_reference_handler' => new Reference($config['circular_reference_handler'])];
                $container->getDefinition('serializer.normalizer.object')->setArgument(5, null);
            }
            if ($config['max_depth_handler'] ?? \false) {
                $context += ['max_depth_handler' => new Reference($config['max_depth_handler'])];
            }
            $container->getDefinition('serializer.normalizer.object')->setArgument(6, $context);
        }
        $container->getDefinition('serializer.normalizer.property')->setArgument(5, $defaultContext);
    }
    private function registerPropertyInfoConfiguration(ContainerBuilder $container, PhpFileLoader $loader): void
    {
        if (!interface_exists(PropertyInfoExtractorInterface::class)) {
            throw new LogicException('PropertyInfo support cannot be enabled as the PropertyInfo component is not installed. Try running "composer require symfony/property-info".');
        }
        $loader->load('property_info.php');
        if (ContainerBuilder::willBeAvailable('phpstan/phpdoc-parser', PhpDocParser::class, ['symfony/framework-bundle', 'symfony/property-info']) && ContainerBuilder::willBeAvailable('phpdocumentor/type-resolver', ContextFactory::class, ['symfony/framework-bundle', 'symfony/property-info'])) {
            $definition = $container->register('property_info.phpstan_extractor', PhpStanExtractor::class);
            $definition->addTag('property_info.type_extractor', ['priority' => -1000]);
        }
        if (ContainerBuilder::willBeAvailable('phpdocumentor/reflection-docblock', DocBlockFactoryInterface::class, ['symfony/framework-bundle', 'symfony/property-info'], \true)) {
            $definition = $container->register('property_info.php_doc_extractor', PhpDocExtractor::class);
            $definition->addTag('property_info.description_extractor', ['priority' => -1000]);
            $definition->addTag('property_info.type_extractor', ['priority' => -1001]);
        }
        if ($container->getParameter('kernel.debug')) {
            $container->removeDefinition('property_info.cache');
        }
    }
    private function registerLockConfiguration(array $config, ContainerBuilder $container, PhpFileLoader $loader): void
    {
        $loader->load('lock.php');
        foreach ($config['resources'] as $resourceName => $resourceStores) {
            if (0 === \count($resourceStores)) {
                continue;
            }
            // Generate stores
            $storeDefinitions = [];
            foreach ($resourceStores as $resourceStore) {
                $storeDsn = $container->resolveEnvPlaceholders($resourceStore, null, $usedEnvs);
                $storeDefinition = new Definition(PersistingStoreInterface::class);
                $storeDefinition->setFactory([StoreFactory::class, 'createStore'])->setArguments([$resourceStore])->addTag('lock.store');
                $container->setDefinition($storeDefinitionId = '.lock.' . $resourceName . '.store.' . $container->hash($storeDsn), $storeDefinition);
                $storeDefinition = new Reference($storeDefinitionId);
                $storeDefinitions[] = $storeDefinition;
            }
            // Wrap array of stores with CombinedStore
            if (\count($storeDefinitions) > 1) {
                $combinedDefinition = new ChildDefinition('lock.store.combined.abstract');
                $combinedDefinition->replaceArgument(0, $storeDefinitions);
                $container->setDefinition($storeDefinitionId = '.lock.' . $resourceName . '.store.' . $container->hash($resourceStores), $combinedDefinition);
            }
            // Generate factories for each resource
            $factoryDefinition = new ChildDefinition('lock.factory.abstract');
            $factoryDefinition->replaceArgument(0, new Reference($storeDefinitionId));
            $container->setDefinition('lock.' . $resourceName . '.factory', $factoryDefinition);
            // provide alias for default resource
            if ('default' === $resourceName) {
                $container->setAlias('lock.factory', new Alias('lock.' . $resourceName . '.factory', \false));
                $container->setAlias(LockFactory::class, new Alias('lock.factory', \false));
            } else {
                $container->registerAliasForArgument('lock.' . $resourceName . '.factory', LockFactory::class, $resourceName . '.lock.factory');
            }
        }
    }
    private function registerSemaphoreConfiguration(array $config, ContainerBuilder $container, PhpFileLoader $loader): void
    {
        if (!class_exists(Semaphore::class)) {
            throw new LogicException('Semaphore support cannot be enabled as the Semaphore component is not installed. Try running "composer require symfony/semaphore".');
        }
        $loader->load('semaphore.php');
        foreach ($config['resources'] as $resourceName => $resourceStore) {
            $storeDsn = $container->resolveEnvPlaceholders($resourceStore, null, $usedEnvs);
            $storeDefinition = new Definition(SemaphoreStoreInterface::class);
            $storeDefinition->setFactory([SemaphoreStoreFactory::class, 'createStore']);
            $storeDefinition->setArguments([$resourceStore]);
            $container->setDefinition($storeDefinitionId = '.semaphore.' . $resourceName . '.store.' . $container->hash($storeDsn), $storeDefinition);
            // Generate factories for each resource
            $factoryDefinition = new ChildDefinition('semaphore.factory.abstract');
            $factoryDefinition->replaceArgument(0, new Reference($storeDefinitionId));
            $container->setDefinition('semaphore.' . $resourceName . '.factory', $factoryDefinition);
            // Generate services for semaphore instances
            $semaphoreDefinition = new Definition(Semaphore::class);
            $semaphoreDefinition->setFactory([new Reference('semaphore.' . $resourceName . '.factory'), 'createSemaphore']);
            $semaphoreDefinition->setArguments([$resourceName]);
            // provide alias for default resource
            if ('default' === $resourceName) {
                $container->setAlias('semaphore.factory', new Alias('semaphore.' . $resourceName . '.factory', \false));
                $container->setAlias(SemaphoreFactory::class, new Alias('semaphore.factory', \false));
            } else {
                $container->registerAliasForArgument('semaphore.' . $resourceName . '.factory', SemaphoreFactory::class, $resourceName . '.semaphore.factory');
            }
        }
    }
    private function registerSchedulerConfiguration(array $config, ContainerBuilder $container, PhpFileLoader $loader): void
    {
        if (!class_exists(SchedulerTransportFactory::class)) {
            throw new LogicException('Scheduler support cannot be enabled as the Scheduler component is not installed. Try running "composer require symfony/scheduler".');
        }
        $loader->load('scheduler.php');
        if (!$this->hasConsole()) {
            $container->removeDefinition('console.command.scheduler_debug');
        }
    }
    private function registerMessengerConfiguration(array $config, ContainerBuilder $container, PhpFileLoader $loader, bool $validationEnabled): void
    {
        if (!interface_exists(MessageBusInterface::class)) {
            throw new LogicException('Messenger support cannot be enabled as the Messenger component is not installed. Try running "composer require symfony/messenger".');
        }
        if (!$this->hasConsole()) {
            $container->removeDefinition('console.command.messenger_stats');
        }
        $loader->load('messenger.php');
        if (!interface_exists(DenormalizerInterface::class)) {
            $container->removeDefinition('serializer.normalizer.flatten_exception');
        }
        if (ContainerBuilder::willBeAvailable('symfony/amqp-messenger', MessengerBridge\Amqp\Transport\AmqpTransportFactory::class, ['symfony/framework-bundle', 'symfony/messenger'])) {
            $container->getDefinition('messenger.transport.amqp.factory')->addTag('messenger.transport_factory');
        }
        if (ContainerBuilder::willBeAvailable('symfony/redis-messenger', MessengerBridge\Redis\Transport\RedisTransportFactory::class, ['symfony/framework-bundle', 'symfony/messenger'])) {
            $container->getDefinition('messenger.transport.redis.factory')->addTag('messenger.transport_factory');
        }
        if (ContainerBuilder::willBeAvailable('symfony/amazon-sqs-messenger', MessengerBridge\AmazonSqs\Transport\AmazonSqsTransportFactory::class, ['symfony/framework-bundle', 'symfony/messenger'])) {
            $container->getDefinition('messenger.transport.sqs.factory')->addTag('messenger.transport_factory');
        }
        if (ContainerBuilder::willBeAvailable('symfony/beanstalkd-messenger', MessengerBridge\Beanstalkd\Transport\BeanstalkdTransportFactory::class, ['symfony/framework-bundle', 'symfony/messenger'])) {
            $container->getDefinition('messenger.transport.beanstalkd.factory')->addTag('messenger.transport_factory');
        }
        if ($config['stop_worker_on_signals'] && $this->hasConsole()) {
            $container->getDefinition('console.command.messenger_consume_messages')->replaceArgument(8, $config['stop_worker_on_signals']);
            $container->getDefinition('console.command.messenger_failed_messages_retry')->replaceArgument(6, $config['stop_worker_on_signals']);
        }
        if ($this->hasConsole() && $container->hasDefinition('messenger.listener.stop_worker_signals_listener')) {
            $container->getDefinition('messenger.listener.stop_worker_signals_listener')->clearTag('kernel.event_subscriber');
        }
        if (!class_exists(StopWorkerOnSignalsListener::class)) {
            $container->removeDefinition('messenger.listener.stop_worker_signals_listener');
        } elseif ($config['stop_worker_on_signals']) {
            $container->getDefinition('messenger.listener.stop_worker_signals_listener')->replaceArgument(0, $config['stop_worker_on_signals']);
        }
        if (null === $config['default_bus'] && 1 === \count($config['buses'])) {
            $config['default_bus'] = key($config['buses']);
        }
        $defaultMiddleware = ['before' => [['id' => 'add_bus_name_stamp_middleware'], ['id' => 'reject_redelivered_message_middleware'], ['id' => 'dispatch_after_current_bus'], ['id' => 'failed_message_processing_middleware']], 'after' => [['id' => 'send_message'], ['id' => 'handle_message']]];
        foreach ($config['buses'] as $busId => $bus) {
            $middleware = $bus['middleware'];
            if ($bus['default_middleware']['enabled']) {
                $defaultMiddleware['after'][0]['arguments'] = [$bus['default_middleware']['allow_no_senders']];
                $defaultMiddleware['after'][1]['arguments'] = [$bus['default_middleware']['allow_no_handlers']];
                $middleware = array_merge($defaultMiddleware['before'], $middleware, $defaultMiddleware['after']);
            }
            foreach ($middleware as $key => $middlewareItem) {
                if (!$validationEnabled && \in_array($middlewareItem['id'], ['validation', 'messenger.middleware.validation'], \true)) {
                    throw new LogicException('The Validation middleware is only available when the Validator component is installed and enabled. Try running "composer require symfony/validator".');
                }
                // argument to add_bus_name_stamp_middleware
                if ('add_bus_name_stamp_middleware' === $middlewareItem['id']) {
                    $middleware[$key]['arguments'] = [$busId];
                }
            }
            if ($container->getParameter('kernel.debug') && class_exists(Stopwatch::class)) {
                array_unshift($middleware, ['id' => 'traceable', 'arguments' => [$busId]]);
            }
            $container->setParameter($busId . '.middleware', $middleware);
            $container->register($busId, MessageBus::class)->addArgument([])->addTag('messenger.bus');
            if ($busId === $config['default_bus']) {
                $container->setAlias('messenger.default_bus', $busId)->setPublic(\true);
                $container->setAlias(MessageBusInterface::class, $busId);
            } else {
                $container->registerAliasForArgument($busId, MessageBusInterface::class);
            }
        }
        if (empty($config['transports'])) {
            $container->removeDefinition('messenger.transport.symfony_serializer');
            $container->removeDefinition('messenger.transport.amqp.factory');
            $container->removeDefinition('messenger.transport.redis.factory');
            $container->removeDefinition('messenger.transport.sqs.factory');
            $container->removeDefinition('messenger.transport.beanstalkd.factory');
            $container->removeAlias(SerializerInterface::class);
        } else {
            $container->getDefinition('messenger.transport.symfony_serializer')->replaceArgument(1, $config['serializer']['symfony_serializer']['format'])->replaceArgument(2, $config['serializer']['symfony_serializer']['context']);
            $container->setAlias('messenger.default_serializer', $config['serializer']['default_serializer']);
        }
        $failureTransports = [];
        if ($config['failure_transport']) {
            if (!isset($config['transports'][$config['failure_transport']])) {
                throw new LogicException(\sprintf('Invalid Messenger configuration: the failure transport "%s" is not a valid transport or service id.', $config['failure_transport']));
            }
            $container->setAlias('messenger.failure_transports.default', 'messenger.transport.' . $config['failure_transport']);
            $failureTransports[] = $config['failure_transport'];
        }
        $failureTransportsByName = [];
        foreach ($config['transports'] as $name => $transport) {
            if ($transport['failure_transport']) {
                $failureTransports[] = $transport['failure_transport'];
                $failureTransportsByName[$name] = $transport['failure_transport'];
            } elseif ($config['failure_transport']) {
                $failureTransportsByName[$name] = $config['failure_transport'];
            }
        }
        $senderAliases = [];
        $transportRetryReferences = [];
        $transportRateLimiterReferences = [];
        foreach ($config['transports'] as $name => $transport) {
            $serializerId = $transport['serializer'] ?? 'messenger.default_serializer';
            $tags = ['alias' => $name, 'is_failure_transport' => \in_array($name, $failureTransports)];
            if (str_starts_with($transport['dsn'], 'sync://')) {
                $tags['is_consumable'] = \false;
            }
            $transportDefinition = (new Definition(TransportInterface::class))->setFactory([new Reference('messenger.transport_factory'), 'createTransport'])->setArguments([$transport['dsn'], $transport['options'] + ['transport_name' => $name], new Reference($serializerId)])->addTag('messenger.receiver', $tags);
            $container->setDefinition($transportId = 'messenger.transport.' . $name, $transportDefinition);
            $senderAliases[$name] = $transportId;
            if (null !== $transport['retry_strategy']['service']) {
                $transportRetryReferences[$name] = new Reference($transport['retry_strategy']['service']);
            } else {
                $retryServiceId = \sprintf('messenger.retry.multiplier_retry_strategy.%s', $name);
                $retryDefinition = new ChildDefinition('messenger.retry.abstract_multiplier_retry_strategy');
                $retryDefinition->replaceArgument(0, $transport['retry_strategy']['max_retries'])->replaceArgument(1, $transport['retry_strategy']['delay'])->replaceArgument(2, $transport['retry_strategy']['multiplier'])->replaceArgument(3, $transport['retry_strategy']['max_delay']);
                $container->setDefinition($retryServiceId, $retryDefinition);
                $transportRetryReferences[$name] = new Reference($retryServiceId);
            }
            if ($transport['rate_limiter']) {
                if (!interface_exists(LimiterInterface::class)) {
                    throw new LogicException('Rate limiter cannot be used within Messenger as the RateLimiter component is not installed. Try running "composer require symfony/rate-limiter".');
                }
                $transportRateLimiterReferences[$name] = new Reference('limiter.' . $transport['rate_limiter']);
            }
        }
        $senderReferences = [];
        // alias => service_id
        foreach ($senderAliases as $alias => $serviceId) {
            $senderReferences[$alias] = new Reference($serviceId);
        }
        // service_id => service_id
        foreach ($senderAliases as $serviceId) {
            $senderReferences[$serviceId] = new Reference($serviceId);
        }
        foreach ($config['transports'] as $name => $transport) {
            if ($transport['failure_transport']) {
                if (!isset($senderReferences[$transport['failure_transport']])) {
                    throw new LogicException(\sprintf('Invalid Messenger configuration: the failure transport "%s" is not a valid transport or service id.', $transport['failure_transport']));
                }
            }
        }
        $failureTransportReferencesByTransportName = array_map(fn($failureTransportName) => $senderReferences[$failureTransportName], $failureTransportsByName);
        $messageToSendersMapping = [];
        foreach ($config['routing'] as $message => $messageConfiguration) {
            if ('*' !== $message && !class_exists($message) && !interface_exists($message, \false) && !preg_match('/^(?:[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*+\\\\)++\*$/', $message)) {
                if (str_contains($message, '*')) {
                    throw new LogicException(\sprintf('Invalid Messenger routing configuration: invalid namespace "%s" wildcard.', $message));
                }
                throw new LogicException(\sprintf('Invalid Messenger routing configuration: class or interface "%s" not found.', $message));
            }
            // make sure senderAliases contains all senders
            foreach ($messageConfiguration['senders'] as $sender) {
                if (!isset($senderReferences[$sender])) {
                    throw new LogicException(\sprintf('Invalid Messenger routing configuration: the "%s" class is being routed to a sender called "%s". This is not a valid transport or service id.', $message, $sender));
                }
            }
            $messageToSendersMapping[$message] = $messageConfiguration['senders'];
        }
        $sendersServiceLocator = ServiceLocatorTagPass::register($container, $senderReferences);
        $container->getDefinition('messenger.senders_locator')->replaceArgument(0, $messageToSendersMapping)->replaceArgument(1, $sendersServiceLocator);
        $container->getDefinition('messenger.retry.send_failed_message_for_retry_listener')->replaceArgument(0, $sendersServiceLocator);
        $container->getDefinition('messenger.retry_strategy_locator')->replaceArgument(0, $transportRetryReferences);
        if (!$transportRateLimiterReferences) {
            $container->removeDefinition('messenger.rate_limiter_locator');
        } else {
            $container->getDefinition('messenger.rate_limiter_locator')->replaceArgument(0, $transportRateLimiterReferences);
        }
        if (\count($failureTransports) > 0) {
            if ($this->hasConsole()) {
                $container->getDefinition('console.command.messenger_failed_messages_retry')->replaceArgument(0, $config['failure_transport']);
                $container->getDefinition('console.command.messenger_failed_messages_show')->replaceArgument(0, $config['failure_transport']);
                $container->getDefinition('console.command.messenger_failed_messages_remove')->replaceArgument(0, $config['failure_transport']);
            }
            $failureTransportsByTransportNameServiceLocator = ServiceLocatorTagPass::register($container, $failureTransportReferencesByTransportName);
            $container->getDefinition('messenger.failure.send_failed_message_to_failure_transport_listener')->replaceArgument(0, $failureTransportsByTransportNameServiceLocator)->replaceArgument(2, $failureTransportsByName);
        } else {
            $container->removeDefinition('messenger.failure.send_failed_message_to_failure_transport_listener');
            $container->removeDefinition('console.command.messenger_failed_messages_retry');
            $container->removeDefinition('console.command.messenger_failed_messages_show');
            $container->removeDefinition('console.command.messenger_failed_messages_remove');
        }
        if (!$container->hasDefinition('console.command.messenger_consume_messages')) {
            $container->removeDefinition('messenger.listener.reset_services');
        }
    }
    private function registerCacheConfiguration(array $config, ContainerBuilder $container): void
    {
        $version = new Parameter('container.build_id');
        $container->getDefinition('cache.adapter.apcu')->replaceArgument(2, $version);
        $container->getDefinition('cache.adapter.system')->replaceArgument(2, $version);
        $container->getDefinition('cache.adapter.filesystem')->replaceArgument(2, $config['directory']);
        if (isset($config['prefix_seed'])) {
            $container->setParameter('cache.prefix.seed', $config['prefix_seed']);
        }
        if ($container->hasParameter('cache.prefix.seed')) {
            // Inline any env vars referenced in the parameter
            $container->setParameter('cache.prefix.seed', $container->resolveEnvPlaceholders($container->getParameter('cache.prefix.seed'), \true));
        }
        foreach (['psr6', 'redis', 'memcached', 'doctrine_dbal', 'pdo'] as $name) {
            if (isset($config[$name = 'default_' . $name . '_provider'])) {
                $container->setAlias('cache.' . $name, new Alias(CachePoolPass::getServiceProvider($container, $config[$name]), \false));
            }
        }
        foreach (['app', 'system'] as $name) {
            $config['pools']['cache.' . $name] = ['adapters' => [$config[$name]], 'public' => \true, 'tags' => \false];
        }
        foreach ($config['pools'] as $name => $pool) {
            $pool['adapters'] = $pool['adapters'] ?: ['cache.app'];
            $isRedisTagAware = ['cache.adapter.redis_tag_aware'] === $pool['adapters'];
            foreach ($pool['adapters'] as $provider => $adapter) {
                if (($config['pools'][$adapter]['adapters'] ?? null) === ['cache.adapter.redis_tag_aware']) {
                    $isRedisTagAware = \true;
                } elseif ($config['pools'][$adapter]['tags'] ?? \false) {
                    $pool['adapters'][$provider] = $adapter = '.' . $adapter . '.inner';
                }
            }
            if (1 === \count($pool['adapters'])) {
                if (!isset($pool['provider']) && !\is_int($provider)) {
                    $pool['provider'] = $provider;
                }
                $definition = new ChildDefinition($adapter);
            } else {
                $definition = new Definition(ChainAdapter::class, [$pool['adapters'], 0]);
                $pool['reset'] = 'reset';
            }
            if ($isRedisTagAware && 'cache.app' === $name) {
                $container->setAlias('cache.app.taggable', $name);
                $definition->addTag('cache.taggable', ['pool' => $name]);
            } elseif ($isRedisTagAware) {
                $tagAwareId = $name;
                $container->setAlias('.' . $name . '.inner', $name);
                $definition->addTag('cache.taggable', ['pool' => $name]);
            } elseif ($pool['tags']) {
                if (\true !== $pool['tags'] && ($config['pools'][$pool['tags']]['tags'] ?? \false)) {
                    $pool['tags'] = '.' . $pool['tags'] . '.inner';
                }
                $container->register($name, TagAwareAdapter::class)->addArgument(new Reference('.' . $name . '.inner'))->addArgument(\true !== $pool['tags'] ? new Reference($pool['tags']) : null)->addMethodCall('setLogger', [new Reference('logger', ContainerInterface::IGNORE_ON_INVALID_REFERENCE)])->setPublic($pool['public'])->addTag('cache.taggable', ['pool' => $name])->addTag('monolog.logger', ['channel' => 'cache']);
                $pool['name'] = $tagAwareId = $name;
                $pool['public'] = \false;
                $name = '.' . $name . '.inner';
            } elseif (!\in_array($name, ['cache.app', 'cache.system'], \true)) {
                $tagAwareId = '.' . $name . '.taggable';
                $container->register($tagAwareId, TagAwareAdapter::class)->addArgument(new Reference($name))->addTag('cache.taggable', ['pool' => $name]);
            }
            if (!\in_array($name, ['cache.app', 'cache.system'], \true)) {
                $container->registerAliasForArgument($tagAwareId, TagAwareCacheInterface::class, $pool['name'] ?? $name);
                $container->registerAliasForArgument($name, CacheInterface::class, $pool['name'] ?? $name);
                $container->registerAliasForArgument($name, CacheItemPoolInterface::class, $pool['name'] ?? $name);
            }
            $definition->setPublic($pool['public']);
            unset($pool['adapters'], $pool['public'], $pool['tags']);
            $definition->addTag('cache.pool', $pool);
            $container->setDefinition($name, $definition);
        }
        if (class_exists(PropertyAccessor::class)) {
            $propertyAccessDefinition = $container->register('cache.property_access', AdapterInterface::class);
            if (!$container->getParameter('kernel.debug')) {
                $propertyAccessDefinition->setFactory([PropertyAccessor::class, 'createCache']);
                $propertyAccessDefinition->setArguments(['', 0, $version, new Reference('logger', ContainerInterface::IGNORE_ON_INVALID_REFERENCE)]);
                $propertyAccessDefinition->addTag('cache.pool', ['clearer' => 'cache.system_clearer']);
                $propertyAccessDefinition->addTag('monolog.logger', ['channel' => 'cache']);
            } else {
                $propertyAccessDefinition->setClass(ArrayAdapter::class);
                $propertyAccessDefinition->setArguments([0, \false]);
            }
        }
    }
    private function registerHttpClientConfiguration(array $config, ContainerBuilder $container, PhpFileLoader $loader): void
    {
        $loader->load('http_client.php');
        $options = $config['default_options'] ?? [];
        $retryOptions = $options['retry_failed'] ?? ['enabled' => \false];
        unset($options['retry_failed']);
        $defaultUriTemplateVars = $options['vars'] ?? [];
        unset($options['vars']);
        $container->getDefinition('http_client.transport')->setArguments([$options, $config['max_host_connections'] ?? 6]);
        if (!class_exists(PingWebhookMessageHandler::class)) {
            $container->removeDefinition('http_client.messenger.ping_webhook_handler');
        }
        if (!$hasPsr18 = ContainerBuilder::willBeAvailable('psr/http-client', ClientInterface::class, ['symfony/framework-bundle', 'symfony/http-client'])) {
            $container->removeDefinition('psr18.http_client');
            $container->removeAlias(ClientInterface::class);
        }
        if (!$hasHttplug = ContainerBuilder::willBeAvailable('php-http/httplug', HttpAsyncClient::class, ['symfony/framework-bundle', 'symfony/http-client'])) {
            $container->removeDefinition('httplug.http_client');
            $container->removeAlias(HttpAsyncClient::class);
            $container->removeAlias(HttpClient::class);
        }
        if ($this->readConfigEnabled('http_client.retry_failed', $container, $retryOptions)) {
            $this->registerRetryableHttpClient($retryOptions, 'http_client', $container);
        }
        if (ContainerBuilder::willBeAvailable('guzzlehttp/uri-template', \_ContaoManager\GuzzleHttp\UriTemplate\UriTemplate::class, [])) {
            $container->setAlias('http_client.uri_template_expander', 'http_client.uri_template_expander.guzzle');
        } elseif (ContainerBuilder::willBeAvailable('rize/uri-template', \_ContaoManager\Rize\UriTemplate::class, [])) {
            $container->setAlias('http_client.uri_template_expander', 'http_client.uri_template_expander.rize');
        }
        $container->getDefinition('http_client.uri_template')->setArgument(2, $defaultUriTemplateVars);
        foreach ($config['scoped_clients'] as $name => $scopeConfig) {
            if ($container->has($name)) {
                throw new InvalidArgumentException(\sprintf('Invalid scope name: "%s" is reserved.', $name));
            }
            $scope = $scopeConfig['scope'] ?? null;
            unset($scopeConfig['scope']);
            $retryOptions = $scopeConfig['retry_failed'] ?? ['enabled' => \false];
            unset($scopeConfig['retry_failed']);
            if (null === $scope) {
                $baseUri = $scopeConfig['base_uri'];
                unset($scopeConfig['base_uri']);
                $container->register($name, ScopingHttpClient::class)->setFactory([ScopingHttpClient::class, 'forBaseUri'])->setArguments([new Reference('http_client.transport'), $baseUri, $scopeConfig])->addTag('http_client.client')->addTag('kernel.reset', ['method' => 'reset', 'on_invalid' => 'ignore']);
            } else {
                $container->register($name, ScopingHttpClient::class)->setArguments([new Reference('http_client.transport'), [$scope => $scopeConfig], $scope])->addTag('http_client.client')->addTag('kernel.reset', ['method' => 'reset', 'on_invalid' => 'ignore']);
            }
            if ($this->readConfigEnabled('http_client.scoped_clients.' . $name . '.retry_failed', $container, $retryOptions)) {
                $this->registerRetryableHttpClient($retryOptions, $name, $container);
            }
            $container->register($name . '.uri_template', UriTemplateHttpClient::class)->setDecoratedService($name, null, 7)->setArguments([new Reference($name . '.uri_template.inner'), new Reference('http_client.uri_template_expander', ContainerInterface::NULL_ON_INVALID_REFERENCE), $defaultUriTemplateVars]);
            $container->registerAliasForArgument($name, HttpClientInterface::class);
            if ($hasPsr18) {
                $container->setDefinition('psr18.' . $name, new ChildDefinition('psr18.http_client'))->replaceArgument(0, new Reference($name));
                $container->registerAliasForArgument('psr18.' . $name, ClientInterface::class, $name);
            }
            if ($hasHttplug) {
                $container->setDefinition('httplug.' . $name, new ChildDefinition('httplug.http_client'))->replaceArgument(0, new Reference($name));
                $container->registerAliasForArgument('httplug.' . $name, HttpAsyncClient::class, $name);
            }
        }
        if ($responseFactoryId = $config['mock_response_factory'] ?? null) {
            $container->register('http_client.mock_client', MockHttpClient::class)->setDecoratedService('http_client.transport', null, -10)->setArguments([new Reference($responseFactoryId)]);
        }
    }
    private function registerRetryableHttpClient(array $options, string $name, ContainerBuilder $container): void
    {
        if (null !== $options['retry_strategy']) {
            $retryStrategy = new Reference($options['retry_strategy']);
        } else {
            $retryStrategy = new ChildDefinition('http_client.abstract_retry_strategy');
            $codes = [];
            foreach ($options['http_codes'] as $code => $codeOptions) {
                if ($codeOptions['methods']) {
                    $codes[$code] = $codeOptions['methods'];
                } else {
                    $codes[] = $code;
                }
            }
            $retryStrategy->replaceArgument(0, $codes ?: GenericRetryStrategy::DEFAULT_RETRY_STATUS_CODES)->replaceArgument(1, $options['delay'])->replaceArgument(2, $options['multiplier'])->replaceArgument(3, $options['max_delay'])->replaceArgument(4, $options['jitter']);
            $container->setDefinition($name . '.retry_strategy', $retryStrategy);
            $retryStrategy = new Reference($name . '.retry_strategy');
        }
        $container->register($name . '.retryable', RetryableHttpClient::class)->setDecoratedService($name, null, 10)->setArguments([new Reference($name . '.retryable.inner'), $retryStrategy, $options['max_retries'], new Reference('logger')])->addTag('monolog.logger', ['channel' => 'http_client']);
    }
    private function registerMailerConfiguration(array $config, ContainerBuilder $container, PhpFileLoader $loader, bool $webhookEnabled): void
    {
        if (!class_exists(Mailer::class)) {
            throw new LogicException('Mailer support cannot be enabled as the component is not installed. Try running "composer require symfony/mailer".');
        }
        $loader->load('mailer.php');
        $loader->load('mailer_transports.php');
        if (!\count($config['transports']) && null === $config['dsn']) {
            $config['dsn'] = 'smtp://null';
        }
        $transports = $config['dsn'] ? ['main' => $config['dsn']] : $config['transports'];
        $container->getDefinition('mailer.transports')->setArgument(0, $transports);
        $mailer = $container->getDefinition('mailer.mailer');
        if (\false === $messageBus = $config['message_bus']) {
            $mailer->replaceArgument(1, null);
        } else {
            $mailer->replaceArgument(1, $messageBus ? new Reference($messageBus) : new Reference('messenger.default_bus', ContainerInterface::NULL_ON_INVALID_REFERENCE));
        }
        $classToServices = [MailerBridge\Brevo\Transport\BrevoTransportFactory::class => 'mailer.transport_factory.brevo', MailerBridge\Google\Transport\GmailTransportFactory::class => 'mailer.transport_factory.gmail', MailerBridge\Infobip\Transport\InfobipTransportFactory::class => 'mailer.transport_factory.infobip', MailerBridge\MailerSend\Transport\MailerSendTransportFactory::class => 'mailer.transport_factory.mailersend', MailerBridge\Mailgun\Transport\MailgunTransportFactory::class => 'mailer.transport_factory.mailgun', MailerBridge\Mailjet\Transport\MailjetTransportFactory::class => 'mailer.transport_factory.mailjet', MailerBridge\MailPace\Transport\MailPaceTransportFactory::class => 'mailer.transport_factory.mailpace', MailerBridge\Mailchimp\Transport\MandrillTransportFactory::class => 'mailer.transport_factory.mailchimp', MailerBridge\OhMySmtp\Transport\OhMySmtpTransportFactory::class => 'mailer.transport_factory.ohmysmtp', MailerBridge\Postmark\Transport\PostmarkTransportFactory::class => 'mailer.transport_factory.postmark', MailerBridge\Scaleway\Transport\ScalewayTransportFactory::class => 'mailer.transport_factory.scaleway', MailerBridge\Sendgrid\Transport\SendgridTransportFactory::class => 'mailer.transport_factory.sendgrid', MailerBridge\Sendinblue\Transport\SendinblueTransportFactory::class => 'mailer.transport_factory.sendinblue', MailerBridge\Amazon\Transport\SesTransportFactory::class => 'mailer.transport_factory.amazon'];
        foreach ($classToServices as $class => $service) {
            $package = substr($service, \strlen('mailer.transport_factory.'));
            if (!ContainerBuilder::willBeAvailable(\sprintf('symfony/%s-mailer', 'gmail' === $package ? 'google' : $package), $class, ['symfony/framework-bundle', 'symfony/mailer'])) {
                $container->removeDefinition($service);
            }
        }
        if ($webhookEnabled) {
            $webhookRequestParsers = [MailerBridge\Brevo\Webhook\BrevoRequestParser::class => 'mailer.webhook.request_parser.brevo', MailerBridge\Mailgun\Webhook\MailgunRequestParser::class => 'mailer.webhook.request_parser.mailgun', MailerBridge\Mailjet\Webhook\MailjetRequestParser::class => 'mailer.webhook.request_parser.mailjet', MailerBridge\Postmark\Webhook\PostmarkRequestParser::class => 'mailer.webhook.request_parser.postmark', MailerBridge\Sendgrid\Webhook\SendgridRequestParser::class => 'mailer.webhook.request_parser.sendgrid'];
            foreach ($webhookRequestParsers as $class => $service) {
                $package = substr($service, \strlen('mailer.webhook.request_parser.'));
                if (!ContainerBuilder::willBeAvailable(\sprintf('symfony/%s-mailer', 'gmail' === $package ? 'google' : $package), $class, ['symfony/framework-bundle', 'symfony/mailer'])) {
                    $container->removeDefinition($service);
                }
            }
        }
        $envelopeListener = $container->getDefinition('mailer.envelope_listener');
        $envelopeListener->setArgument(0, $config['envelope']['sender'] ?? null);
        $envelopeListener->setArgument(1, $config['envelope']['recipients'] ?? null);
        if ($config['headers']) {
            $headers = new Definition(Headers::class);
            foreach ($config['headers'] as $name => $data) {
                $value = $data['value'];
                if (\in_array(strtolower($name), ['from', 'to', 'cc', 'bcc', 'reply-to'])) {
                    $value = (array) $value;
                }
                $headers->addMethodCall('addHeader', [$name, $value]);
            }
            $messageListener = $container->getDefinition('mailer.message_listener');
            $messageListener->setArgument(0, $headers);
        } else {
            $container->removeDefinition('mailer.message_listener');
        }
        if (!class_exists(MessengerTransportListener::class)) {
            $container->removeDefinition('mailer.messenger_transport_listener');
        }
        if ($webhookEnabled) {
            $loader->load('mailer_webhook.php');
        }
    }
    private function registerNotifierConfiguration(array $config, ContainerBuilder $container, PhpFileLoader $loader, bool $webhookEnabled): void
    {
        if (!class_exists(Notifier::class)) {
            throw new LogicException('Notifier support cannot be enabled as the component is not installed. Try running "composer require symfony/notifier".');
        }
        $loader->load('notifier.php');
        $loader->load('notifier_transports.php');
        if ($config['chatter_transports']) {
            $container->getDefinition('chatter.transports')->setArgument(0, $config['chatter_transports']);
        } else {
            $container->removeDefinition('chatter');
            $container->removeAlias(ChatterInterface::class);
        }
        if ($config['texter_transports']) {
            $container->getDefinition('texter.transports')->setArgument(0, $config['texter_transports']);
        } else {
            $container->removeDefinition('texter');
            $container->removeAlias(TexterInterface::class);
        }
        if ($this->isInitializedConfigEnabled('mailer')) {
            $sender = $container->getDefinition('mailer.envelope_listener')->getArgument(0);
            $container->getDefinition('notifier.channel.email')->setArgument(2, $sender);
        } else {
            $container->removeDefinition('notifier.channel.email');
        }
        foreach (['texter', 'chatter', 'notifier.channel.chat', 'notifier.channel.email', 'notifier.channel.sms', 'notifier.channel.push'] as $serviceId) {
            if (!$container->hasDefinition($serviceId)) {
                continue;
            }
            if (\false === $messageBus = $config['message_bus']) {
                $container->getDefinition($serviceId)->replaceArgument(1, null);
            } else {
                $container->getDefinition($serviceId)->replaceArgument(1, $messageBus ? new Reference($messageBus) : new Reference('messenger.default_bus', ContainerInterface::NULL_ON_INVALID_REFERENCE));
            }
        }
        if ($this->isInitializedConfigEnabled('messenger')) {
            if ($config['notification_on_failed_messages']) {
                $container->getDefinition('notifier.failed_message_listener')->addTag('kernel.event_subscriber');
            }
            // as we have a bus, the channels don't need the transports
            $container->getDefinition('notifier.channel.chat')->setArgument(0, null);
            if ($container->hasDefinition('notifier.channel.email')) {
                $container->getDefinition('notifier.channel.email')->setArgument(0, null);
            }
            $container->getDefinition('notifier.channel.sms')->setArgument(0, null);
            $container->getDefinition('notifier.channel.push')->setArgument(0, null);
        }
        $container->getDefinition('notifier.channel_policy')->setArgument(0, $config['channel_policy']);
        $container->registerForAutoconfiguration(NotifierTransportFactoryInterface::class)->addTag('chatter.transport_factory');
        $container->registerForAutoconfiguration(NotifierTransportFactoryInterface::class)->addTag('texter.transport_factory');
        $classToServices = [NotifierBridge\AllMySms\AllMySmsTransportFactory::class => 'notifier.transport_factory.all-my-sms', NotifierBridge\AmazonSns\AmazonSnsTransportFactory::class => 'notifier.transport_factory.amazon-sns', NotifierBridge\Bandwidth\BandwidthTransportFactory::class => 'notifier.transport_factory.bandwidth', NotifierBridge\Brevo\BrevoTransportFactory::class => 'notifier.transport_factory.brevo', NotifierBridge\Chatwork\ChatworkTransportFactory::class => 'notifier.transport_factory.chatwork', NotifierBridge\Clickatell\ClickatellTransportFactory::class => 'notifier.transport_factory.clickatell', NotifierBridge\ClickSend\ClickSendTransportFactory::class => 'notifier.transport_factory.click-send', NotifierBridge\ContactEveryone\ContactEveryoneTransportFactory::class => 'notifier.transport_factory.contact-everyone', NotifierBridge\Discord\DiscordTransportFactory::class => 'notifier.transport_factory.discord', NotifierBridge\Engagespot\EngagespotTransportFactory::class => 'notifier.transport_factory.engagespot', NotifierBridge\Esendex\EsendexTransportFactory::class => 'notifier.transport_factory.esendex', NotifierBridge\Expo\ExpoTransportFactory::class => 'notifier.transport_factory.expo', NotifierBridge\Firebase\FirebaseTransportFactory::class => 'notifier.transport_factory.firebase', NotifierBridge\FortySixElks\FortySixElksTransportFactory::class => 'notifier.transport_factory.forty-six-elks', NotifierBridge\FreeMobile\FreeMobileTransportFactory::class => 'notifier.transport_factory.free-mobile', NotifierBridge\GatewayApi\GatewayApiTransportFactory::class => 'notifier.transport_factory.gateway-api', NotifierBridge\Gitter\GitterTransportFactory::class => 'notifier.transport_factory.gitter', NotifierBridge\GoIp\GoIpTransportFactory::class => 'notifier.transport_factory.go-ip', NotifierBridge\GoogleChat\GoogleChatTransportFactory::class => 'notifier.transport_factory.google-chat', NotifierBridge\Infobip\InfobipTransportFactory::class => 'notifier.transport_factory.infobip', NotifierBridge\Iqsms\IqsmsTransportFactory::class => 'notifier.transport_factory.iqsms', NotifierBridge\Isendpro\IsendproTransportFactory::class => 'notifier.transport_factory.isendpro', NotifierBridge\KazInfoTeh\KazInfoTehTransportFactory::class => 'notifier.transport_factory.kaz-info-teh', NotifierBridge\LightSms\LightSmsTransportFactory::class => 'notifier.transport_factory.light-sms', NotifierBridge\LineNotify\LineNotifyTransportFactory::class => 'notifier.transport_factory.line-notify', NotifierBridge\LinkedIn\LinkedInTransportFactory::class => 'notifier.transport_factory.linked-in', NotifierBridge\Mailjet\MailjetTransportFactory::class => 'notifier.transport_factory.mailjet', NotifierBridge\Mastodon\MastodonTransportFactory::class => 'notifier.transport_factory.mastodon', NotifierBridge\Mattermost\MattermostTransportFactory::class => 'notifier.transport_factory.mattermost', NotifierBridge\Mercure\MercureTransportFactory::class => 'notifier.transport_factory.mercure', NotifierBridge\MessageBird\MessageBirdTransportFactory::class => 'notifier.transport_factory.message-bird', NotifierBridge\MessageMedia\MessageMediaTransportFactory::class => 'notifier.transport_factory.message-media', NotifierBridge\MicrosoftTeams\MicrosoftTeamsTransportFactory::class => 'notifier.transport_factory.microsoft-teams', NotifierBridge\Mobyt\MobytTransportFactory::class => 'notifier.transport_factory.mobyt', NotifierBridge\Novu\NovuTransportFactory::class => 'notifier.transport_factory.novu', NotifierBridge\Ntfy\NtfyTransportFactory::class => 'notifier.transport_factory.ntfy', NotifierBridge\Octopush\OctopushTransportFactory::class => 'notifier.transport_factory.octopush', NotifierBridge\OneSignal\OneSignalTransportFactory::class => 'notifier.transport_factory.one-signal', NotifierBridge\OrangeSms\OrangeSmsTransportFactory::class => 'notifier.transport_factory.orange-sms', NotifierBridge\OvhCloud\OvhCloudTransportFactory::class => 'notifier.transport_factory.ovh-cloud', NotifierBridge\PagerDuty\PagerDutyTransportFactory::class => 'notifier.transport_factory.pager-duty', NotifierBridge\Plivo\PlivoTransportFactory::class => 'notifier.transport_factory.plivo', NotifierBridge\Pushover\PushoverTransportFactory::class => 'notifier.transport_factory.pushover', NotifierBridge\Redlink\RedlinkTransportFactory::class => 'notifier.transport_factory.redlink', NotifierBridge\RingCentral\RingCentralTransportFactory::class => 'notifier.transport_factory.ring-central', NotifierBridge\RocketChat\RocketChatTransportFactory::class => 'notifier.transport_factory.rocket-chat', NotifierBridge\Sendberry\SendberryTransportFactory::class => 'notifier.transport_factory.sendberry', NotifierBridge\SimpleTextin\SimpleTextinTransportFactory::class => 'notifier.transport_factory.simple-textin', NotifierBridge\Sendinblue\SendinblueTransportFactory::class => 'notifier.transport_factory.sendinblue', NotifierBridge\Sinch\SinchTransportFactory::class => 'notifier.transport_factory.sinch', NotifierBridge\Slack\SlackTransportFactory::class => 'notifier.transport_factory.slack', NotifierBridge\Sms77\Sms77TransportFactory::class => 'notifier.transport_factory.sms77', NotifierBridge\Smsapi\SmsapiTransportFactory::class => 'notifier.transport_factory.smsapi', NotifierBridge\SmsBiuras\SmsBiurasTransportFactory::class => 'notifier.transport_factory.sms-biuras', NotifierBridge\Smsc\SmscTransportFactory::class => 'notifier.transport_factory.smsc', NotifierBridge\SmsFactor\SmsFactorTransportFactory::class => 'notifier.transport_factory.sms-factor', NotifierBridge\Smsmode\SmsmodeTransportFactory::class => 'notifier.transport_factory.smsmode', NotifierBridge\SpotHit\SpotHitTransportFactory::class => 'notifier.transport_factory.spot-hit', NotifierBridge\Telegram\TelegramTransportFactory::class => 'notifier.transport_factory.telegram', NotifierBridge\Telnyx\TelnyxTransportFactory::class => 'notifier.transport_factory.telnyx', NotifierBridge\Termii\TermiiTransportFactory::class => 'notifier.transport_factory.termii', NotifierBridge\TurboSms\TurboSmsTransportFactory::class => 'notifier.transport_factory.turbo-sms', NotifierBridge\Twilio\TwilioTransportFactory::class => 'notifier.transport_factory.twilio', NotifierBridge\Twitter\TwitterTransportFactory::class => 'notifier.transport_factory.twitter', NotifierBridge\Vonage\VonageTransportFactory::class => 'notifier.transport_factory.vonage', NotifierBridge\Yunpian\YunpianTransportFactory::class => 'notifier.transport_factory.yunpian', NotifierBridge\Zendesk\ZendeskTransportFactory::class => 'notifier.transport_factory.zendesk', NotifierBridge\Zulip\ZulipTransportFactory::class => 'notifier.transport_factory.zulip'];
        $parentPackages = ['symfony/framework-bundle', 'symfony/notifier'];
        foreach ($classToServices as $class => $service) {
            $package = substr($service, \strlen('notifier.transport_factory.'));
            if (!ContainerBuilder::willBeAvailable(\sprintf('symfony/%s-notifier', $package), $class, $parentPackages)) {
                $container->removeDefinition($service);
            }
        }
        if (ContainerBuilder::willBeAvailable('symfony/mercure-notifier', NotifierBridge\Mercure\MercureTransportFactory::class, $parentPackages) && ContainerBuilder::willBeAvailable('symfony/mercure-bundle', MercureBundle::class, $parentPackages) && \in_array(MercureBundle::class, $container->getParameter('kernel.bundles'), \true)) {
            $container->getDefinition($classToServices[NotifierBridge\Mercure\MercureTransportFactory::class])->replaceArgument(0, new Reference(HubRegistry::class))->replaceArgument(1, new Reference('event_dispatcher', ContainerBuilder::NULL_ON_INVALID_REFERENCE))->addArgument(new Reference('http_client', ContainerBuilder::NULL_ON_INVALID_REFERENCE));
        } elseif (ContainerBuilder::willBeAvailable('symfony/mercure-notifier', NotifierBridge\Mercure\MercureTransportFactory::class, $parentPackages)) {
            $container->removeDefinition($classToServices[NotifierBridge\Mercure\MercureTransportFactory::class]);
        }
        // don't use ContainerBuilder::willBeAvailable() as these are not needed in production
        if (class_exists(FakeChatTransportFactory::class)) {
            $container->getDefinition('notifier.transport_factory.fake-chat')->replaceArgument(0, new Reference('mailer', ContainerBuilder::NULL_ON_INVALID_REFERENCE))->replaceArgument(1, new Reference('logger', ContainerBuilder::NULL_ON_INVALID_REFERENCE))->addArgument(new Reference('event_dispatcher', ContainerBuilder::NULL_ON_INVALID_REFERENCE))->addArgument(new Reference('http_client', ContainerBuilder::NULL_ON_INVALID_REFERENCE));
        } else {
            $container->removeDefinition('notifier.transport_factory.fake-chat');
        }
        // don't use ContainerBuilder::willBeAvailable() as these are not needed in production
        if (class_exists(FakeSmsTransportFactory::class)) {
            $container->getDefinition('notifier.transport_factory.fake-sms')->replaceArgument(0, new Reference('mailer', ContainerBuilder::NULL_ON_INVALID_REFERENCE))->replaceArgument(1, new Reference('logger', ContainerBuilder::NULL_ON_INVALID_REFERENCE))->addArgument(new Reference('event_dispatcher', ContainerBuilder::NULL_ON_INVALID_REFERENCE))->addArgument(new Reference('http_client', ContainerBuilder::NULL_ON_INVALID_REFERENCE));
        } else {
            $container->removeDefinition('notifier.transport_factory.fake-sms');
        }
        if (isset($config['admin_recipients'])) {
            $notifier = $container->getDefinition('notifier');
            foreach ($config['admin_recipients'] as $i => $recipient) {
                $id = 'notifier.admin_recipient.' . $i;
                $container->setDefinition($id, new Definition(Recipient::class, [$recipient['email'], $recipient['phone']]));
                $notifier->addMethodCall('addAdminRecipient', [new Reference($id)]);
            }
        }
        if ($webhookEnabled) {
            $loader->load('notifier_webhook.php');
            $webhookRequestParsers = [NotifierBridge\Twilio\Webhook\TwilioRequestParser::class => 'notifier.webhook.request_parser.twilio', NotifierBridge\Vonage\Webhook\VonageRequestParser::class => 'notifier.webhook.request_parser.vonage'];
            foreach ($webhookRequestParsers as $class => $service) {
                $package = substr($service, \strlen('notifier.webhook.request_parser.'));
                if (!ContainerBuilder::willBeAvailable(\sprintf('symfony/%s-notifier', $package), $class, ['symfony/framework-bundle', 'symfony/notifier'])) {
                    $container->removeDefinition($service);
                }
            }
        }
    }
    private function registerWebhookConfiguration(array $config, ContainerBuilder $container, PhpFileLoader $loader): void
    {
        if (!class_exists(WebhookController::class)) {
            throw new LogicException('Webhook support cannot be enabled as the component is not installed. Try running "composer require symfony/webhook".');
        }
        $loader->load('webhook.php');
        $parsers = [];
        foreach ($config['routing'] as $type => $cfg) {
            $parsers[$type] = ['parser' => new Reference($cfg['service']), 'secret' => $cfg['secret']];
        }
        $controller = $container->getDefinition('webhook.controller');
        $controller->replaceArgument(0, $parsers);
        $controller->replaceArgument(1, new Reference($config['message_bus']));
    }
    private function registerRemoteEventConfiguration(array $config, ContainerBuilder $container, PhpFileLoader $loader): void
    {
        if (!class_exists(RemoteEvent::class)) {
            throw new LogicException('RemoteEvent support cannot be enabled as the component is not installed. Try running "composer require symfony/remote-event".');
        }
        $loader->load('remote_event.php');
    }
    private function registerRateLimiterConfiguration(array $config, ContainerBuilder $container, PhpFileLoader $loader): void
    {
        $loader->load('rate_limiter.php');
        foreach ($config['limiters'] as $name => $limiterConfig) {
            // default configuration (when used by other DI extensions)
            $limiterConfig += ['lock_factory' => 'lock.factory', 'cache_pool' => 'cache.rate_limiter'];
            $limiter = $container->setDefinition($limiterId = 'limiter.' . $name, new ChildDefinition('limiter'));
            if (null !== $limiterConfig['lock_factory']) {
                if (!interface_exists(LockInterface::class)) {
                    throw new LogicException(\sprintf('Rate limiter "%s" requires the Lock component to be installed. Try running "composer require symfony/lock".', $name));
                }
                if (!$this->isInitializedConfigEnabled('lock')) {
                    throw new LogicException(\sprintf('Rate limiter "%s" requires the Lock component to be configured.', $name));
                }
                $limiter->replaceArgument(2, new Reference($limiterConfig['lock_factory']));
            }
            unset($limiterConfig['lock_factory']);
            if (null === $storageId = $limiterConfig['storage_service'] ?? null) {
                $container->register($storageId = 'limiter.storage.' . $name, CacheStorage::class)->addArgument(new Reference($limiterConfig['cache_pool']));
            }
            $limiter->replaceArgument(1, new Reference($storageId));
            unset($limiterConfig['storage_service'], $limiterConfig['cache_pool']);
            $limiterConfig['id'] = $name;
            $limiter->replaceArgument(0, $limiterConfig);
            $container->registerAliasForArgument($limiterId, RateLimiterFactory::class, $name . '.limiter');
        }
    }
    /**
     * @deprecated since Symfony 6.2
     *
     * @return void
     */
    public static function registerRateLimiter(ContainerBuilder $container, string $name, array $limiterConfig)
    {
        trigger_deprecation('symfony/framework-bundle', '6.2', 'The "%s()" method is deprecated.', __METHOD__);
        // default configuration (when used by other DI extensions)
        $limiterConfig += ['lock_factory' => 'lock.factory', 'cache_pool' => 'cache.rate_limiter'];
        $limiter = $container->setDefinition($limiterId = 'limiter.' . $name, new ChildDefinition('limiter'));
        if (null !== $limiterConfig['lock_factory']) {
            if (!interface_exists(LockInterface::class)) {
                throw new LogicException(\sprintf('Rate limiter "%s" requires the Lock component to be installed. Try running "composer require symfony/lock".', $name));
            }
            if (!$container->hasDefinition('lock.factory.abstract')) {
                throw new LogicException(\sprintf('Rate limiter "%s" requires the Lock component to be configured.', $name));
            }
            $limiter->replaceArgument(2, new Reference($limiterConfig['lock_factory']));
        }
        unset($limiterConfig['lock_factory']);
        if (null === $storageId = $limiterConfig['storage_service'] ?? null) {
            $container->register($storageId = 'limiter.storage.' . $name, CacheStorage::class)->addArgument(new Reference($limiterConfig['cache_pool']));
        }
        $limiter->replaceArgument(1, new Reference($storageId));
        unset($limiterConfig['storage_service'], $limiterConfig['cache_pool']);
        $limiterConfig['id'] = $name;
        $limiter->replaceArgument(0, $limiterConfig);
        $container->registerAliasForArgument($limiterId, RateLimiterFactory::class, $name . '.limiter');
    }
    private function registerUidConfiguration(array $config, ContainerBuilder $container, PhpFileLoader $loader): void
    {
        $loader->load('uid.php');
        $container->getDefinition('uuid.factory')->setArguments([$config['default_uuid_version'], $config['time_based_uuid_version'], $config['name_based_uuid_version'], UuidV4::class, $config['time_based_uuid_node'] ?? null, $config['name_based_uuid_namespace'] ?? null]);
        if (isset($config['name_based_uuid_namespace'])) {
            $container->getDefinition('name_based_uuid.factory')->setArguments([$config['name_based_uuid_namespace']]);
        }
    }
    private function registerHtmlSanitizerConfiguration(array $config, ContainerBuilder $container, PhpFileLoader $loader): void
    {
        $loader->load('html_sanitizer.php');
        foreach ($config['sanitizers'] as $sanitizerName => $sanitizerConfig) {
            $configId = 'html_sanitizer.config.' . $sanitizerName;
            $def = $container->register($configId, HtmlSanitizerConfig::class);
            // Base
            if ($sanitizerConfig['allow_safe_elements']) {
                $def->addMethodCall('allowSafeElements', [], \true);
            }
            if ($sanitizerConfig['allow_static_elements']) {
                $def->addMethodCall('allowStaticElements', [], \true);
            }
            // Configures elements
            foreach ($sanitizerConfig['allow_elements'] as $element => $attributes) {
                $def->addMethodCall('allowElement', [$element, $attributes], \true);
            }
            foreach ($sanitizerConfig['block_elements'] as $element) {
                $def->addMethodCall('blockElement', [$element], \true);
            }
            foreach ($sanitizerConfig['drop_elements'] as $element) {
                $def->addMethodCall('dropElement', [$element], \true);
            }
            // Configures attributes
            foreach ($sanitizerConfig['allow_attributes'] as $attribute => $elements) {
                $def->addMethodCall('allowAttribute', [$attribute, $elements], \true);
            }
            foreach ($sanitizerConfig['drop_attributes'] as $attribute => $elements) {
                $def->addMethodCall('dropAttribute', [$attribute, $elements], \true);
            }
            // Force attributes
            foreach ($sanitizerConfig['force_attributes'] as $element => $attributes) {
                foreach ($attributes as $attrName => $attrValue) {
                    $def->addMethodCall('forceAttribute', [$element, $attrName, $attrValue], \true);
                }
            }
            // Settings
            $def->addMethodCall('forceHttpsUrls', [$sanitizerConfig['force_https_urls']], \true);
            if ($sanitizerConfig['allowed_link_schemes']) {
                $def->addMethodCall('allowLinkSchemes', [$sanitizerConfig['allowed_link_schemes']], \true);
            }
            $def->addMethodCall('allowLinkHosts', [$sanitizerConfig['allowed_link_hosts']], \true);
            $def->addMethodCall('allowRelativeLinks', [$sanitizerConfig['allow_relative_links']], \true);
            if ($sanitizerConfig['allowed_media_schemes']) {
                $def->addMethodCall('allowMediaSchemes', [$sanitizerConfig['allowed_media_schemes']], \true);
            }
            $def->addMethodCall('allowMediaHosts', [$sanitizerConfig['allowed_media_hosts']], \true);
            $def->addMethodCall('allowRelativeMedias', [$sanitizerConfig['allow_relative_medias']], \true);
            // Custom attribute sanitizers
            foreach ($sanitizerConfig['with_attribute_sanitizers'] as $serviceName) {
                $def->addMethodCall('withAttributeSanitizer', [new Reference($serviceName)], \true);
            }
            foreach ($sanitizerConfig['without_attribute_sanitizers'] as $serviceName) {
                $def->addMethodCall('withoutAttributeSanitizer', [new Reference($serviceName)], \true);
            }
            if ($sanitizerConfig['max_input_length']) {
                $def->addMethodCall('withMaxInputLength', [$sanitizerConfig['max_input_length']], \true);
            }
            // Create the sanitizer and link its config
            $sanitizerId = 'html_sanitizer.sanitizer.' . $sanitizerName;
            $container->register($sanitizerId, HtmlSanitizer::class)->addTag('html_sanitizer', ['sanitizer' => $sanitizerName])->addArgument(new Reference($configId));
            if ('default' !== $sanitizerName) {
                $container->registerAliasForArgument($sanitizerId, HtmlSanitizerInterface::class, $sanitizerName);
            }
        }
    }
    private function resolveTrustedHeaders(array $headers): int
    {
        $trustedHeaders = 0;
        foreach ($headers as $h) {
            $trustedHeaders |= match ($h) {
                'forwarded' => Request::HEADER_FORWARDED,
                'x-forwarded-for' => Request::HEADER_X_FORWARDED_FOR,
                'x-forwarded-host' => Request::HEADER_X_FORWARDED_HOST,
                'x-forwarded-proto' => Request::HEADER_X_FORWARDED_PROTO,
                'x-forwarded-port' => Request::HEADER_X_FORWARDED_PORT,
                'x-forwarded-prefix' => Request::HEADER_X_FORWARDED_PREFIX,
                default => 0,
            };
        }
        return $trustedHeaders;
    }
    public function getXsdValidationBasePath(): string|false
    {
        return \dirname(__DIR__) . '/Resources/config/schema';
    }
    public function getNamespace(): string
    {
        return 'http://symfony.com/schema/dic/symfony';
    }
    protected function isConfigEnabled(ContainerBuilder $container, array $config): bool
    {
        throw new \LogicException('To prevent using outdated configuration, you must use the "readConfigEnabled" method instead.');
    }
    private function isInitializedConfigEnabled(string $path): bool
    {
        if (isset($this->configsEnabled[$path])) {
            return $this->configsEnabled[$path];
        }
        throw new LogicException(\sprintf('Can not read config enabled at "%s" because it has not been initialized.', $path));
    }
    private function readConfigEnabled(string $path, ContainerBuilder $container, array $config): bool
    {
        return $this->configsEnabled[$path] ??= parent::isConfigEnabled($container, $config);
    }
    private function writeConfigEnabled(string $path, bool $value, array &$config): void
    {
        if (isset($this->configsEnabled[$path])) {
            throw new LogicException('Can not change config enabled because it has already been read.');
        }
        $this->configsEnabled[$path] = $value;
        $config['enabled'] = $value;
    }
    private function getPublicDirectory(ContainerBuilder $container): string
    {
        $projectDir = $container->getParameter('kernel.project_dir');
        $defaultPublicDir = $projectDir . '/public';
        $composerFilePath = $projectDir . '/composer.json';
        if (!file_exists($composerFilePath)) {
            return $defaultPublicDir;
        }
        $container->addResource(new FileResource($composerFilePath));
        $composerConfig = json_decode(file_get_contents($composerFilePath), \true);
        return isset($composerConfig['extra']['public-dir']) ? $projectDir . '/' . $composerConfig['extra']['public-dir'] : $defaultPublicDir;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Bundle\FrameworkBundle\DependencyInjection;

use _ContaoManager\Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerBuilder;
use _ContaoManager\Symfony\Component\DependencyInjection\Reference;
class VirtualRequestStackPass implements CompilerPassInterface
{
    public function process(ContainerBuilder $container): void
    {
        if ($container->has('.virtual_request_stack')) {
            return;
        }
        if ($container->hasDefinition('debug.event_dispatcher')) {
            $container->getDefinition('debug.event_dispatcher')->replaceArgument(3, new Reference('request_stack', ContainerBuilder::NULL_ON_INVALID_REFERENCE));
        }
        if ($container->hasDefinition('debug.log_processor')) {
            $container->getDefinition('debug.log_processor')->replaceArgument(0, new Reference('request_stack'));
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler;

use _ContaoManager\Symfony\Component\Config\ConfigCache;
use _ContaoManager\Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerBuilder;
use _ContaoManager\Symfony\Component\DependencyInjection\Dumper\XmlDumper;
/**
 * Dumps the ContainerBuilder to a cache file so that it can be used by
 * debugging tools such as the debug:container console command.
 *
 * @author Ryan Weaver <ryan@thatsquality.com>
 * @author Fabien Potencier <fabien@symfony.com>
 */
class ContainerBuilderDebugDumpPass implements CompilerPassInterface
{
    /**
     * @return void
     */
    public function process(ContainerBuilder $container)
    {
        if (!$container->getParameter('debug.container.dump')) {
            return;
        }
        $cache = new ConfigCache($container->getParameter('debug.container.dump'), \true);
        if (!$cache->isFresh()) {
            $cache->write((new XmlDumper($container))->dump(), $container->getResources());
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler;

use _ContaoManager\Symfony\Component\DependencyInjection\Argument\ServiceClosureArgument;
use _ContaoManager\Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerBuilder;
use _ContaoManager\Symfony\Component\DependencyInjection\Reference;
/**
 * @author Nicolas Grekas <p@tchwork.com>
 */
class TestServiceContainerRealRefPass implements CompilerPassInterface
{
    /**
     * @return void
     */
    public function process(ContainerBuilder $container)
    {
        if (!$container->hasDefinition('test.private_services_locator')) {
            return;
        }
        $privateContainer = $container->getDefinition('test.private_services_locator');
        $definitions = $container->getDefinitions();
        $privateServices = $privateContainer->getArgument(0);
        $renamedIds = [];
        foreach ($privateServices as $id => $argument) {
            if (isset($definitions[$target = (string) $argument->getValues()[0]])) {
                $argument->setValues([new Reference($target)]);
                if ($id !== $target) {
                    $renamedIds[$id] = $target;
                }
                if ($inner = $definitions[$target]->getTag('container.decorator')[0]['inner'] ?? null) {
                    $renamedIds[$id] = $inner;
                }
            } else {
                unset($privateServices[$id]);
            }
        }
        foreach ($container->getAliases() as $id => $target) {
            while ($container->hasAlias($target = (string) $target)) {
                $target = $container->getAlias($target);
            }
            if ($definitions[$target]->hasTag('container.private')) {
                $privateServices[$id] = new ServiceClosureArgument(new Reference($target));
            }
            $renamedIds[$id] = $target;
        }
        $privateContainer->replaceArgument(0, $privateServices);
        if ($container->hasDefinition('test.service_container') && $renamedIds) {
            $container->getDefinition('test.service_container')->setArgument(2, $renamedIds);
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler;

use _ContaoManager\Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerBuilder;
use _ContaoManager\Symfony\Component\DependencyInjection\Reference;
trigger_deprecation('symfony/framework-bundle', '6.4', 'The "%s" class is deprecated, use "%s" instead.', AddExpressionLanguageProvidersPass::class, \_ContaoManager\Symfony\Component\Routing\DependencyInjection\AddExpressionLanguageProvidersPass::class);
/**
 * Registers the expression language providers.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 *
 * @deprecated since Symfony 6.4, use Symfony\Component\Routing\DependencyInjection\AddExpressionLanguageProvidersPass instead.
 */
class AddExpressionLanguageProvidersPass implements CompilerPassInterface
{
    /**
     * @return void
     */
    public function process(ContainerBuilder $container)
    {
        // routing
        if ($container->has('router.default')) {
            $definition = $container->findDefinition('router.default');
            foreach ($container->findTaggedServiceIds('routing.expression_language_provider', \true) as $id => $attributes) {
                $definition->addMethodCall('addExpressionLanguageProvider', [new Reference($id)]);
            }
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler;

use _ContaoManager\Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerBuilder;
/**
 * Find all service tags which are defined, but not used and yield a warning log message.
 *
 * @author Florian Pfitzer <pfitzer@wurzel3.de>
 */
class UnusedTagsPass implements CompilerPassInterface
{
    private const KNOWN_TAGS = ['annotations.cached_reader', 'assets.package', 'asset_mapper.compiler', 'auto_alias', 'cache.pool', 'cache.pool.clearer', 'cache.taggable', 'chatter.transport_factory', 'config_cache.resource_checker', 'console.command', 'container.do_not_inline', 'container.env_var_loader', 'container.env_var_processor', 'container.excluded', 'container.hot_path', 'container.no_preload', 'container.preload', 'container.private', 'container.reversible', 'container.service_locator', 'container.service_locator_context', 'container.service_subscriber', 'container.stack', 'controller.argument_value_resolver', 'controller.service_arguments', 'controller.targeted_value_resolver', 'data_collector', 'event_dispatcher.dispatcher', 'form.type', 'form.type_extension', 'form.type_guesser', 'html_sanitizer', 'http_client.client', 'kernel.cache_clearer', 'kernel.cache_warmer', 'kernel.event_listener', 'kernel.event_subscriber', 'kernel.fragment_renderer', 'kernel.locale_aware', 'kernel.reset', 'ldap', 'mailer.transport_factory', 'messenger.bus', 'messenger.message_handler', 'messenger.receiver', 'messenger.transport_factory', 'mime.mime_type_guesser', 'monolog.logger', 'notifier.channel', 'property_info.access_extractor', 'property_info.initializable_extractor', 'property_info.list_extractor', 'property_info.type_extractor', 'proxy', 'remote_event.consumer', 'routing.condition_service', 'routing.expression_language_function', 'routing.expression_language_provider', 'routing.loader', 'routing.route_loader', 'scheduler.schedule_provider', 'scheduler.task', 'security.authenticator.login_linker', 'security.expression_language_provider', 'security.remember_me_handler', 'security.voter', 'serializer.encoder', 'serializer.normalizer', 'texter.transport_factory', 'translation.dumper', 'translation.extractor', 'translation.extractor.visitor', 'translation.loader', 'translation.provider_factory', 'twig.extension', 'twig.loader', 'twig.runtime', 'validator.auto_mapper', 'validator.constraint_validator', 'validator.group_provider', 'validator.initializer', 'workflow'];
    /**
     * @return void
     */
    public function process(ContainerBuilder $container)
    {
        $tags = array_unique(array_merge($container->findTags(), self::KNOWN_TAGS));
        foreach ($container->findUnusedTags() as $tag) {
            // skip known tags
            if (\in_array($tag, self::KNOWN_TAGS)) {
                continue;
            }
            // check for typos
            $candidates = [];
            foreach ($tags as $definedTag) {
                if ($definedTag === $tag) {
                    continue;
                }
                if (str_contains($definedTag, $tag) || levenshtein($tag, $definedTag) <= \strlen($tag) / 3) {
                    $candidates[] = $definedTag;
                }
            }
            $services = array_keys($container->findTaggedServiceIds($tag));
            $message = \sprintf('Tag "%s" was defined on service(s) "%s", but was never used.', $tag, implode('", "', $services));
            if ($candidates) {
                $message .= \sprintf(' Did you mean "%s"?', implode('", "', $candidates));
            }
            $container->log($this, $message);
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler;

use _ContaoManager\Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerBuilder;
use _ContaoManager\Symfony\Component\DependencyInjection\Definition;
use _ContaoManager\Symfony\Component\DependencyInjection\Reference;
class AssetsContextPass implements CompilerPassInterface
{
    /**
     * @return void
     */
    public function process(ContainerBuilder $container)
    {
        if (!$container->hasDefinition('assets.context')) {
            return;
        }
        if (!$container->hasDefinition('router.request_context')) {
            $container->setParameter('asset.request_context.base_path', $container->getParameter('asset.request_context.base_path') ?? '');
            $container->setParameter('asset.request_context.secure', $container->getParameter('asset.request_context.secure') ?? \false);
            return;
        }
        $context = $container->getDefinition('assets.context');
        if (null === $container->getParameter('asset.request_context.base_path')) {
            $context->replaceArgument(1, (new Definition('string'))->setFactory([new Reference('router.request_context'), 'getBaseUrl']));
        }
        if (null === $container->getParameter('asset.request_context.secure')) {
            $context->replaceArgument(2, (new Definition('bool'))->setFactory([new Reference('router.request_context'), 'isSecure']));
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler;

use _ContaoManager\Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerBuilder;
use _ContaoManager\Symfony\Component\DependencyInjection\Reference;
/**
 * @internal
 */
class ErrorLoggerCompilerPass implements CompilerPassInterface
{
    public function process(ContainerBuilder $container): void
    {
        if (!$container->hasDefinition('debug.error_handler_configurator')) {
            return;
        }
        $definition = $container->getDefinition('debug.error_handler_configurator');
        if ($container->hasDefinition('monolog.logger.php')) {
            $definition->replaceArgument(0, new Reference('monolog.logger.php'));
        }
        if ($container->hasDefinition('monolog.logger.deprecation')) {
            $definition->replaceArgument(5, new Reference('monolog.logger.deprecation'));
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler;

use _ContaoManager\Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerBuilder;
class TranslationUpdateCommandPass implements CompilerPassInterface
{
    public function process(ContainerBuilder $container): void
    {
        if (!$container->hasDefinition('console.command.translation_extract')) {
            return;
        }
        $translationWriterClass = $container->getParameterBag()->resolveValue($container->findDefinition('translation.writer')->getClass());
        if (!method_exists($translationWriterClass, 'getFormats')) {
            $container->removeDefinition('console.command.translation_extract');
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler;

use _ContaoManager\Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerBuilder;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\LogicException;
trigger_deprecation('symfony/framework-bundle', '6.4', 'The "%s" class is deprecated, use "%s" instead.', WorkflowGuardListenerPass::class, \_ContaoManager\Symfony\Component\Workflow\DependencyInjection\WorkflowGuardListenerPass::class);
/**
 * @author Christian Flothmann <christian.flothmann@sensiolabs.de>
 * @author Grégoire Pineau <lyrixx@lyrixx.info>
 *
 * @deprecated since Symfony 6.4, use Symfony\Component\Workflow\DependencyInjection\WorkflowGuardListenerPass instead.
 */
class WorkflowGuardListenerPass implements CompilerPassInterface
{
    /**
     * @return void
     */
    public function process(ContainerBuilder $container)
    {
        if (!$container->hasParameter('workflow.has_guard_listeners')) {
            return;
        }
        $container->getParameterBag()->remove('workflow.has_guard_listeners');
        $servicesNeeded = ['security.token_storage', 'security.authorization_checker', 'security.authentication.trust_resolver', 'security.role_hierarchy'];
        foreach ($servicesNeeded as $service) {
            if (!$container->has($service)) {
                throw new LogicException(\sprintf('The "%s" service is needed to be able to use the workflow guard listener.', $service));
            }
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler;

trigger_deprecation('symfony/framework-bundle', '6.4', 'The "%s" class is deprecated, use argument $debug of HttpKernel\'s Logger instead.', EnableLoggerDebugModePass::class);
use _ContaoManager\Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerBuilder;
use _ContaoManager\Symfony\Component\HttpKernel\Log\Logger;
/**
 * @deprecated since Symfony 6.4, use argument $debug of HttpKernel's Logger instead
 */
final class EnableLoggerDebugModePass implements CompilerPassInterface
{
    public function process(ContainerBuilder $container): void
    {
        if (!$container->hasDefinition('profiler') || !$container->hasDefinition('logger')) {
            return;
        }
        $loggerDefinition = $container->getDefinition('logger');
        if (Logger::class === $loggerDefinition->getClass()) {
            $loggerDefinition->setConfigurator([__CLASS__, 'configureLogger']);
        }
    }
    public static function configureLogger(Logger $logger): void
    {
        if (!\in_array(\PHP_SAPI, ['cli', 'phpdbg'], \true)) {
            $logger->enableDebug();
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler;

use _ContaoManager\Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Compiler\ServiceLocatorTagPass;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerBuilder;
use _ContaoManager\Symfony\Component\DependencyInjection\Reference;
/**
 * @author Nicolas Grekas <p@tchwork.com>
 */
class TestServiceContainerWeakRefPass implements CompilerPassInterface
{
    /**
     * @return void
     */
    public function process(ContainerBuilder $container)
    {
        if (!$container->hasDefinition('test.private_services_locator')) {
            return;
        }
        $privateServices = [];
        $definitions = $container->getDefinitions();
        foreach ($definitions as $id => $definition) {
            if ($inner = $definition->getTag('container.decorator')[0]['inner'] ?? null) {
                $privateServices[$inner] = new Reference($inner, ContainerBuilder::IGNORE_ON_UNINITIALIZED_REFERENCE);
            }
            if ($id && '.' !== $id[0] && ($definition->isPrivate() || $definition->hasTag('container.private')) && !$definition->hasErrors() && !$definition->isAbstract()) {
                $privateServices[$id] = new Reference($id, ContainerBuilder::IGNORE_ON_UNINITIALIZED_REFERENCE);
            }
        }
        $aliases = $container->getAliases();
        foreach ($aliases as $id => $alias) {
            if ($id && '.' !== $id[0] && (!$alias->isPublic() || $alias->isPrivate())) {
                while (isset($aliases[$target = (string) $alias])) {
                    $alias = $aliases[$target];
                }
                if (isset($definitions[$target]) && !$definitions[$target]->hasErrors() && !$definitions[$target]->isAbstract()) {
                    $privateServices[$id] = new Reference($target, ContainerBuilder::IGNORE_ON_UNINITIALIZED_REFERENCE);
                }
            }
        }
        if ($privateServices) {
            $id = (string) ServiceLocatorTagPass::register($container, $privateServices);
            $container->setDefinition('test.private_services_locator', $container->getDefinition($id))->setPublic(\true);
            $container->removeDefinition($id);
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler;

use _ContaoManager\Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerBuilder;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
use _ContaoManager\Symfony\Component\Translation\TranslatorBagInterface;
use _ContaoManager\Symfony\Contracts\Translation\TranslatorInterface;
trigger_deprecation('symfony/framework-bundle', '6.4', 'The "%s" class is deprecated, use "%s" instead.', LoggingTranslatorPass::class, \_ContaoManager\Symfony\Component\Translation\DependencyInjection\LoggingTranslatorPass::class);
/**
 * @author Abdellatif Ait boudad <a.aitboudad@gmail.com>
 *
 * @deprecated since Symfony 6.4, use Symfony\Component\Translation\DependencyInjection\LoggingTranslatorPass instead.
 */
class LoggingTranslatorPass implements CompilerPassInterface
{
    /**
     * @return void
     */
    public function process(ContainerBuilder $container)
    {
        if (!$container->hasAlias('logger') || !$container->hasAlias('translator')) {
            return;
        }
        if ($container->hasParameter('translator.logging') && $container->getParameter('translator.logging')) {
            $translatorAlias = $container->getAlias('translator');
            $definition = $container->getDefinition((string) $translatorAlias);
            $class = $container->getParameterBag()->resolveValue($definition->getClass());
            if (!$r = $container->getReflectionClass($class)) {
                throw new InvalidArgumentException(\sprintf('Class "%s" used for service "%s" cannot be found.', $class, $translatorAlias));
            }
            if ($r->isSubclassOf(TranslatorInterface::class) && $r->isSubclassOf(TranslatorBagInterface::class)) {
                $container->getDefinition('translator.logging')->setDecoratedService('translator');
                $warmer = $container->getDefinition('translation.warmer');
                $subscriberAttributes = $warmer->getTag('container.service_subscriber');
                $warmer->clearTag('container.service_subscriber');
                foreach ($subscriberAttributes as $k => $v) {
                    if ((!isset($v['id']) || 'translator' !== $v['id']) && (!isset($v['key']) || 'translator' !== $v['key'])) {
                        $warmer->addTag('container.service_subscriber', $v);
                    }
                }
                $warmer->addTag('container.service_subscriber', ['key' => 'translator', 'id' => 'translator.logging.inner']);
            }
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler;

use _ContaoManager\Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerBuilder;
use _ContaoManager\Symfony\Component\Translation\TranslatorBagInterface;
trigger_deprecation('symfony/framework-bundle', '6.4', 'The "%s" class is deprecated, use "%s" instead.', DataCollectorTranslatorPass::class, \_ContaoManager\Symfony\Component\Translation\DependencyInjection\DataCollectorTranslatorPass::class);
/**
 * @author Christian Flothmann <christian.flothmann@sensiolabs.de>
 *
 * @deprecated since Symfony 6.4, use Symfony\Component\Translation\DependencyInjection\DataCollectorTranslatorPass instead.
 */
class DataCollectorTranslatorPass implements CompilerPassInterface
{
    /**
     * @return void
     */
    public function process(ContainerBuilder $container)
    {
        if (!$container->has('translator')) {
            return;
        }
        $translatorClass = $container->getParameterBag()->resolveValue($container->findDefinition('translator')->getClass());
        if (!is_subclass_of($translatorClass, TranslatorBagInterface::class)) {
            $container->removeDefinition('translator.data_collector');
            $container->removeDefinition('data_collector.translation');
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler;

use _ContaoManager\Symfony\Component\DependencyInjection\Argument\ServiceClosureArgument;
use _ContaoManager\Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerBuilder;
/**
 * @internal
 */
class AddAnnotationsCachedReaderPass implements CompilerPassInterface
{
    public function process(ContainerBuilder $container): void
    {
        // "annotations.cached_reader" is wired late so that any passes using
        // "annotation_reader" at build time don't get any cache
        foreach ($container->findTaggedServiceIds('annotations.cached_reader') as $id => $tags) {
            $reader = $container->getDefinition($id);
            $properties = $reader->getProperties();
            if (isset($properties['cacheProviderBackup'])) {
                $provider = $properties['cacheProviderBackup']->getValues()[0];
                unset($properties['cacheProviderBackup']);
                $reader->setProperties($properties);
                $reader->replaceArgument(1, $provider);
            } elseif (4 <= \count($arguments = $reader->getArguments()) && $arguments[3] instanceof ServiceClosureArgument) {
                $arguments[1] = $arguments[3]->getValues()[0];
                unset($arguments[3]);
                $reader->setArguments($arguments);
            }
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler;

use _ContaoManager\Symfony\Bundle\FrameworkBundle\DataCollector\TemplateAwareDataCollectorInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerBuilder;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
use _ContaoManager\Symfony\Component\DependencyInjection\Reference;
/**
 * Adds tagged data_collector services to profiler service.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class ProfilerPass implements CompilerPassInterface
{
    /**
     * @return void
     */
    public function process(ContainerBuilder $container)
    {
        if (\false === $container->hasDefinition('profiler')) {
            return;
        }
        $definition = $container->getDefinition('profiler');
        $collectors = new \SplPriorityQueue();
        $order = \PHP_INT_MAX;
        foreach ($container->findTaggedServiceIds('data_collector', \true) as $id => $attributes) {
            $priority = $attributes[0]['priority'] ?? 0;
            $template = null;
            $collectorClass = $container->findDefinition($id)->getClass();
            if (isset($attributes[0]['template']) || is_subclass_of($collectorClass, TemplateAwareDataCollectorInterface::class)) {
                $idForTemplate = $attributes[0]['id'] ?? $collectorClass;
                if (!$idForTemplate) {
                    throw new InvalidArgumentException(\sprintf('Data collector service "%s" must have an id attribute in order to specify a template.', $id));
                }
                $template = [$idForTemplate, $attributes[0]['template'] ?? $collectorClass::getTemplate()];
            }
            $collectors->insert([$id, $template], [$priority, --$order]);
        }
        $templates = [];
        foreach ($collectors as $collector) {
            $definition->addMethodCall('add', [new Reference($collector[0])]);
            $templates[$collector[0]] = $collector[1];
        }
        $container->setParameter('data_collector.templates', $templates);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler;

use _ContaoManager\Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerBuilder;
/**
 * @author Ahmed TAILOULOUTE <ahmed.tailouloute@gmail.com>
 */
class RemoveUnusedSessionMarshallingHandlerPass implements CompilerPassInterface
{
    /**
     * @return void
     */
    public function process(ContainerBuilder $container)
    {
        if (!$container->hasDefinition('session.marshalling_handler')) {
            return;
        }
        $isMarshallerDecorated = \false;
        foreach ($container->getDefinitions() as $definition) {
            $decorated = $definition->getDecoratedService();
            if (null !== $decorated && 'session.marshaller' === $decorated[0]) {
                $isMarshallerDecorated = \true;
                break;
            }
        }
        if (!$isMarshallerDecorated) {
            $container->removeDefinition('session.marshalling_handler');
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler;

use _ContaoManager\Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerBuilder;
use _ContaoManager\Symfony\Component\DependencyInjection\Reference;
class AddDebugLogProcessorPass implements CompilerPassInterface
{
    /**
     * @return void
     */
    public function process(ContainerBuilder $container)
    {
        if (!$container->hasDefinition('profiler')) {
            return;
        }
        if (!$container->hasDefinition('monolog.logger_prototype')) {
            return;
        }
        if (!$container->hasDefinition('debug.log_processor')) {
            return;
        }
        $container->getDefinition('monolog.logger_prototype')->setConfigurator([new Reference('debug.debug_logger_configurator'), 'pushDebugLogger']);
    }
    /**
     * @deprecated since Symfony 6.4, use HttpKernel's DebugLoggerConfigurator instead
     *
     * @return void
     */
    public static function configureLogger(mixed $logger)
    {
        trigger_deprecation('symfony/framework-bundle', '6.4', 'The "%s()" method is deprecated, use HttpKernel\'s DebugLoggerConfigurator instead.', __METHOD__);
        if (\is_object($logger) && method_exists($logger, 'removeDebugLogger') && \in_array(\PHP_SAPI, ['cli', 'phpdbg'], \true)) {
            $logger->removeDebugLogger();
        }
    }
}
{
    "name": "symfony\/framework-bundle",
    "type": "symfony-bundle",
    "description": "Provides a tight integration between Symfony components and the Symfony full-stack framework",
    "keywords": [],
    "homepage": "https:\/\/symfony.com",
    "license": "MIT",
    "authors": [
        {
            "name": "Fabien Potencier",
            "email": "fabien@symfony.com"
        },
        {
            "name": "Symfony Community",
            "homepage": "https:\/\/symfony.com\/contributors"
        }
    ],
    "require": {
        "php": ">=8.1",
        "composer-runtime-api": ">=2.1",
        "ext-xml": "*",
        "symfony\/cache": "^5.4|^6.0|^7.0",
        "symfony\/config": "^6.1|^7.0",
        "symfony\/dependency-injection": "^6.4.12|^7.0",
        "symfony\/deprecation-contracts": "^2.5|^3",
        "symfony\/error-handler": "^6.1|^7.0",
        "symfony\/event-dispatcher": "^5.4|^6.0|^7.0",
        "symfony\/http-foundation": "^6.4|^7.0",
        "symfony\/http-kernel": "^6.4",
        "symfony\/polyfill-mbstring": "~1.0",
        "symfony\/filesystem": "^5.4|^6.0|^7.0",
        "symfony\/finder": "^5.4|^6.0|^7.0",
        "symfony\/routing": "^6.4|^7.0"
    },
    "require-dev": {
        "doctrine\/annotations": "^1.13.1|^2",
        "doctrine\/persistence": "^1.3|^2|^3",
        "dragonmantank\/cron-expression": "^3.1",
        "seld\/jsonlint": "^1.10",
        "symfony\/asset": "^5.4|^6.0|^7.0",
        "symfony\/asset-mapper": "^6.4|^7.0",
        "symfony\/browser-kit": "^5.4|^6.0|^7.0",
        "symfony\/console": "^5.4.9|^6.0.9|^7.0",
        "symfony\/clock": "^6.2|^7.0",
        "symfony\/css-selector": "^5.4|^6.0|^7.0",
        "symfony\/dom-crawler": "^6.4|^7.0",
        "symfony\/dotenv": "^5.4|^6.0|^7.0",
        "symfony\/polyfill-intl-icu": "~1.0",
        "symfony\/form": "^5.4|^6.0|^7.0",
        "symfony\/expression-language": "^5.4|^6.0|^7.0",
        "symfony\/html-sanitizer": "^6.1|^7.0",
        "symfony\/http-client": "^6.3|^7.0",
        "symfony\/lock": "^5.4|^6.0|^7.0",
        "symfony\/mailer": "^5.4|^6.0|^7.0",
        "symfony\/messenger": "^6.3|^7.0",
        "symfony\/mime": "^6.4|^7.0",
        "symfony\/notifier": "^5.4|^6.0|^7.0",
        "symfony\/process": "^5.4|^6.0|^7.0",
        "symfony\/rate-limiter": "^5.4|^6.0|^7.0",
        "symfony\/scheduler": "^6.4.4|^7.0.4",
        "symfony\/security-bundle": "^5.4|^6.0|^7.0",
        "symfony\/semaphore": "^5.4|^6.0|^7.0",
        "symfony\/serializer": "^6.4|^7.0",
        "symfony\/stopwatch": "^5.4|^6.0|^7.0",
        "symfony\/string": "^5.4|^6.0|^7.0",
        "symfony\/translation": "^6.4|^7.0",
        "symfony\/twig-bundle": "^5.4|^6.0|^7.0",
        "symfony\/validator": "^6.4|^7.0",
        "symfony\/workflow": "^6.4|^7.0",
        "symfony\/yaml": "^5.4|^6.0|^7.0",
        "symfony\/property-info": "^5.4|^6.0|^7.0",
        "symfony\/uid": "^5.4|^6.0|^7.0",
        "symfony\/web-link": "^5.4|^6.0|^7.0",
        "phpdocumentor\/reflection-docblock": "^3.0|^4.0|^5.0",
        "twig\/twig": "^2.10|^3.0.4"
    },
    "conflict": {
        "doctrine\/annotations": "<1.13.1",
        "doctrine\/persistence": "<1.3",
        "phpdocumentor\/reflection-docblock": "<3.2.2",
        "phpdocumentor\/type-resolver": "<1.4.0",
        "symfony\/asset": "<5.4",
        "symfony\/asset-mapper": "<6.4",
        "symfony\/clock": "<6.3",
        "symfony\/console": "<5.4|>=7.0",
        "symfony\/dotenv": "<5.4",
        "symfony\/dom-crawler": "<6.4",
        "symfony\/http-client": "<6.3",
        "symfony\/form": "<5.4",
        "symfony\/lock": "<5.4",
        "symfony\/mailer": "<5.4",
        "symfony\/messenger": "<6.3",
        "symfony\/mime": "<6.4",
        "symfony\/property-info": "<5.4",
        "symfony\/property-access": "<5.4",
        "symfony\/runtime": "<5.4.45|>=6.0,<6.4.13|>=7.0,<7.1.6",
        "symfony\/scheduler": "<6.4.4|>=7.0.0,<7.0.4",
        "symfony\/serializer": "<6.4",
        "symfony\/security-csrf": "<5.4",
        "symfony\/security-core": "<5.4",
        "symfony\/stopwatch": "<5.4",
        "symfony\/translation": "<6.4",
        "symfony\/twig-bridge": "<5.4",
        "symfony\/twig-bundle": "<5.4",
        "symfony\/validator": "<6.4",
        "symfony\/web-profiler-bundle": "<6.4",
        "symfony\/workflow": "<6.4"
    },
    "autoload": {
        "psr-4": {
            "_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\": ""
        },
        "exclude-from-classmap": [
            "\/Tests\/"
        ]
    },
    "minimum-stability": "dev"
}<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Bundle\FrameworkBundle\Kernel;

use _ContaoManager\Symfony\Component\Config\Loader\LoaderInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerBuilder;
use _ContaoManager\Symfony\Component\DependencyInjection\Loader\Configurator\AbstractConfigurator;
use _ContaoManager\Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;
use _ContaoManager\Symfony\Component\DependencyInjection\Loader\PhpFileLoader as ContainerPhpFileLoader;
use _ContaoManager\Symfony\Component\DependencyInjection\Reference;
use _ContaoManager\Symfony\Component\Routing\Loader\Configurator\RoutingConfigurator;
use _ContaoManager\Symfony\Component\Routing\Loader\PhpFileLoader as RoutingPhpFileLoader;
use _ContaoManager\Symfony\Component\Routing\RouteCollection;
/**
 * A Kernel that provides configuration hooks.
 *
 * @author Ryan Weaver <ryan@knpuniversity.com>
 * @author Fabien Potencier <fabien@symfony.com>
 */
trait MicroKernelTrait
{
    /**
     * Configures the container.
     *
     * You can register extensions:
     *
     *     $container->extension('framework', [
     *         'secret' => '%secret%'
     *     ]);
     *
     * Or services:
     *
     *     $container->services()->set('halloween', 'FooBundle\HalloweenProvider');
     *
     * Or parameters:
     *
     *     $container->parameters()->set('halloween', 'lot of fun');
     */
    private function configureContainer(ContainerConfigurator $container, LoaderInterface $loader, ContainerBuilder $builder): void
    {
        $configDir = $this->getConfigDir();
        $container->import($configDir . '/{packages}/*.{php,yaml}');
        $container->import($configDir . '/{packages}/' . $this->environment . '/*.{php,yaml}');
        if (is_file($configDir . '/services.yaml')) {
            $container->import($configDir . '/services.yaml');
            $container->import($configDir . '/{services}_' . $this->environment . '.yaml');
        } else {
            $container->import($configDir . '/{services}.php');
            $container->import($configDir . '/{services}_' . $this->environment . '.php');
        }
    }
    /**
     * Adds or imports routes into your application.
     *
     *     $routes->import($this->getConfigDir().'/*.{yaml,php}');
     *     $routes
     *         ->add('admin_dashboard', '/admin')
     *         ->controller('App\Controller\AdminController::dashboard')
     *     ;
     */
    private function configureRoutes(RoutingConfigurator $routes): void
    {
        $configDir = $this->getConfigDir();
        $routes->import($configDir . '/{routes}/' . $this->environment . '/*.{php,yaml}');
        $routes->import($configDir . '/{routes}/*.{php,yaml}');
        if (is_file($configDir . '/routes.yaml')) {
            $routes->import($configDir . '/routes.yaml');
        } else {
            $routes->import($configDir . '/{routes}.php');
        }
        if (\false !== $fileName = (new \ReflectionObject($this))->getFileName()) {
            $routes->import($fileName, 'attribute');
        }
    }
    /**
     * Gets the path to the configuration directory.
     */
    private function getConfigDir(): string
    {
        return $this->getProjectDir() . '/config';
    }
    /**
     * Gets the path to the bundles configuration file.
     */
    private function getBundlesPath(): string
    {
        return $this->getConfigDir() . '/bundles.php';
    }
    public function getCacheDir(): string
    {
        if (isset($_SERVER['APP_CACHE_DIR'])) {
            return $_SERVER['APP_CACHE_DIR'] . '/' . $this->environment;
        }
        return parent::getCacheDir();
    }
    public function getBuildDir(): string
    {
        if (isset($_SERVER['APP_BUILD_DIR'])) {
            return $_SERVER['APP_BUILD_DIR'] . '/' . $this->environment;
        }
        return parent::getBuildDir();
    }
    public function getLogDir(): string
    {
        return $_SERVER['APP_LOG_DIR'] ?? parent::getLogDir();
    }
    public function registerBundles(): iterable
    {
        $contents = require $this->getBundlesPath();
        foreach ($contents as $class => $envs) {
            if ($envs[$this->environment] ?? $envs['all'] ?? \false) {
                yield new $class();
            }
        }
    }
    /**
     * @return void
     */
    public function registerContainerConfiguration(LoaderInterface $loader)
    {
        $loader->load(function (ContainerBuilder $container) use ($loader) {
            $container->loadFromExtension('framework', ['router' => ['resource' => 'kernel::loadRoutes', 'type' => 'service']]);
            $kernelClass = str_contains(static::class, "@anonymous\x00") ? parent::class : static::class;
            if (!$container->hasDefinition('kernel')) {
                $container->register('kernel', $kernelClass)->addTag('controller.service_arguments')->setAutoconfigured(\true)->setSynthetic(\true)->setPublic(\true);
            }
            $kernelDefinition = $container->getDefinition('kernel');
            $kernelDefinition->addTag('routing.route_loader');
            $container->addObjectResource($this);
            $container->fileExists($this->getBundlesPath());
            $configureContainer = new \ReflectionMethod($this, 'configureContainer');
            $configuratorClass = $configureContainer->getNumberOfParameters() > 0 && ($type = $configureContainer->getParameters()[0]->getType()) instanceof \ReflectionNamedType && !$type->isBuiltin() ? $type->getName() : null;
            if ($configuratorClass && !is_a(ContainerConfigurator::class, $configuratorClass, \true)) {
                $configureContainer->getClosure($this)($container, $loader);
                return;
            }
            $file = (new \ReflectionObject($this))->getFileName();
            /** @var ContainerPhpFileLoader $kernelLoader */
            $kernelLoader = $loader->getResolver()->resolve($file);
            $kernelLoader->setCurrentDir(\dirname($file));
            $instanceof =& \Closure::bind(fn&() => $this->instanceof, $kernelLoader, $kernelLoader)();
            $valuePreProcessor = AbstractConfigurator::$valuePreProcessor;
            AbstractConfigurator::$valuePreProcessor = fn($value) => $this === $value ? new Reference('kernel') : $value;
            try {
                $configureContainer->getClosure($this)(new ContainerConfigurator($container, $kernelLoader, $instanceof, $file, $file, $this->getEnvironment()), $loader, $container);
            } finally {
                $instanceof = [];
                $kernelLoader->registerAliasesForSinglyImplementedInterfaces();
                AbstractConfigurator::$valuePreProcessor = $valuePreProcessor;
            }
            $container->setAlias($kernelClass, 'kernel')->setPublic(\true);
        });
    }
    /**
     * @internal
     */
    public function loadRoutes(LoaderInterface $loader): RouteCollection
    {
        $file = (new \ReflectionObject($this))->getFileName();
        /** @var RoutingPhpFileLoader $kernelLoader */
        $kernelLoader = $loader->getResolver()->resolve($file, 'php');
        $kernelLoader->setCurrentDir(\dirname($file));
        $collection = new RouteCollection();
        $configureRoutes = new \ReflectionMethod($this, 'configureRoutes');
        $configureRoutes->getClosure($this)(new RoutingConfigurator($collection, $kernelLoader, $file, $file, $this->getEnvironment()));
        foreach ($collection as $route) {
            $controller = $route->getDefault('_controller');
            if (\is_array($controller) && [0, 1] === array_keys($controller) && $this === $controller[0]) {
                $route->setDefault('_controller', ['kernel', $controller[1]]);
            } elseif ($controller instanceof \Closure && $this === ($r = new \ReflectionFunction($controller))->getClosureThis() && !str_contains($r->name, '{closure')) {
                $route->setDefault('_controller', ['kernel', $r->name]);
            }
        }
        return $collection;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Bundle\FrameworkBundle\Console;

use _ContaoManager\Symfony\Component\Console\Application as BaseApplication;
use _ContaoManager\Symfony\Component\Console\Command\Command;
use _ContaoManager\Symfony\Component\Console\Command\ListCommand;
use _ContaoManager\Symfony\Component\Console\Command\TraceableCommand;
use _ContaoManager\Symfony\Component\Console\Debug\CliRequest;
use _ContaoManager\Symfony\Component\Console\Input\InputInterface;
use _ContaoManager\Symfony\Component\Console\Input\InputOption;
use _ContaoManager\Symfony\Component\Console\Output\ConsoleOutputInterface;
use _ContaoManager\Symfony\Component\Console\Output\OutputInterface;
use _ContaoManager\Symfony\Component\Console\Style\SymfonyStyle;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerAwareInterface;
use _ContaoManager\Symfony\Component\HttpKernel\Bundle\Bundle;
use _ContaoManager\Symfony\Component\HttpKernel\Kernel;
use _ContaoManager\Symfony\Component\HttpKernel\KernelInterface;
/**
 * @author Fabien Potencier <fabien@symfony.com>
 */
class Application extends BaseApplication
{
    private KernelInterface $kernel;
    private bool $commandsRegistered = \false;
    private array $registrationErrors = [];
    public function __construct(KernelInterface $kernel)
    {
        $this->kernel = $kernel;
        parent::__construct('Symfony', Kernel::VERSION);
        $inputDefinition = $this->getDefinition();
        $inputDefinition->addOption(new InputOption('--env', '-e', InputOption::VALUE_REQUIRED, 'The Environment name.', $kernel->getEnvironment()));
        $inputDefinition->addOption(new InputOption('--no-debug', null, InputOption::VALUE_NONE, 'Switch off debug mode.'));
        $inputDefinition->addOption(new InputOption('--profile', null, InputOption::VALUE_NONE, 'Enables profiling (requires debug).'));
    }
    /**
     * Gets the Kernel associated with this Console.
     */
    public function getKernel(): KernelInterface
    {
        return $this->kernel;
    }
    public function reset(): void
    {
        if ($this->kernel->getContainer()->has('services_resetter')) {
            $this->kernel->getContainer()->get('services_resetter')->reset();
        }
    }
    /**
     * Runs the current application.
     *
     * @return int 0 if everything went fine, or an error code
     */
    public function doRun(InputInterface $input, OutputInterface $output): int
    {
        $this->registerCommands();
        if ($this->registrationErrors) {
            $this->renderRegistrationErrors($input, $output);
        }
        $this->setDispatcher($this->kernel->getContainer()->get('event_dispatcher'));
        return parent::doRun($input, $output);
    }
    protected function doRunCommand(Command $command, InputInterface $input, OutputInterface $output): int
    {
        $requestStack = null;
        $renderRegistrationErrors = \true;
        if (!$command instanceof ListCommand) {
            if ($this->registrationErrors) {
                $this->renderRegistrationErrors($input, $output);
                $this->registrationErrors = [];
                $renderRegistrationErrors = \false;
            }
        }
        if ($input->hasParameterOption('--profile')) {
            $container = $this->kernel->getContainer();
            if (!$this->kernel->isDebug()) {
                if ($output instanceof ConsoleOutputInterface) {
                    $output = $output->getErrorOutput();
                }
                (new SymfonyStyle($input, $output))->warning('Debug mode should be enabled when the "--profile" option is used.');
            } elseif (!$container->has('debug.stopwatch')) {
                if ($output instanceof ConsoleOutputInterface) {
                    $output = $output->getErrorOutput();
                }
                (new SymfonyStyle($input, $output))->warning('The "--profile" option needs the Stopwatch component. Try running "composer require symfony/stopwatch".');
            } elseif (!$container->has('.virtual_request_stack')) {
                if ($output instanceof ConsoleOutputInterface) {
                    $output = $output->getErrorOutput();
                }
                (new SymfonyStyle($input, $output))->warning('The "--profile" option needs the profiler integration. Try enabling the "framework.profiler" option.');
            } else {
                $command = new TraceableCommand($command, $container->get('debug.stopwatch'));
                $requestStack = $container->get('.virtual_request_stack');
                $requestStack->push(new CliRequest($command));
            }
        }
        try {
            $returnCode = parent::doRunCommand($command, $input, $output);
        } finally {
            $requestStack?->pop();
        }
        if ($renderRegistrationErrors && $this->registrationErrors) {
            $this->renderRegistrationErrors($input, $output);
            $this->registrationErrors = [];
        }
        return $returnCode;
    }
    public function find(string $name): Command
    {
        $this->registerCommands();
        return parent::find($name);
    }
    public function get(string $name): Command
    {
        $this->registerCommands();
        $command = parent::get($name);
        if ($command instanceof ContainerAwareInterface) {
            trigger_deprecation('symfony/dependency-injection', '6.4', 'Relying on "%s" to get the container in "%s" is deprecated, register the command as a service and use dependency injection instead.', ContainerAwareInterface::class, get_debug_type($command));
            $command->setContainer($this->kernel->getContainer());
        }
        return $command;
    }
    public function all(?string $namespace = null): array
    {
        $this->registerCommands();
        return parent::all($namespace);
    }
    public function getLongVersion(): string
    {
        return parent::getLongVersion() . \sprintf(' (env: <comment>%s</>, debug: <comment>%s</>)', $this->kernel->getEnvironment(), $this->kernel->isDebug() ? 'true' : 'false');
    }
    public function add(Command $command): ?Command
    {
        $this->registerCommands();
        return parent::add($command);
    }
    /**
     * @return void
     */
    protected function registerCommands()
    {
        if ($this->commandsRegistered) {
            return;
        }
        $this->commandsRegistered = \true;
        $this->kernel->boot();
        $container = $this->kernel->getContainer();
        foreach ($this->kernel->getBundles() as $bundle) {
            if ($bundle instanceof Bundle) {
                try {
                    $bundle->registerCommands($this);
                } catch (\Throwable $e) {
                    $this->registrationErrors[] = $e;
                }
            }
        }
        if ($container->has('console.command_loader')) {
            $this->setCommandLoader($container->get('console.command_loader'));
        }
        if ($container->hasParameter('console.command.ids')) {
            $lazyCommandIds = $container->hasParameter('console.lazy_command.ids') ? $container->getParameter('console.lazy_command.ids') : [];
            foreach ($container->getParameter('console.command.ids') as $id) {
                if (!isset($lazyCommandIds[$id])) {
                    try {
                        $this->add($container->get($id));
                    } catch (\Throwable $e) {
                        $this->registrationErrors[] = $e;
                    }
                }
            }
        }
    }
    private function renderRegistrationErrors(InputInterface $input, OutputInterface $output): void
    {
        if ($output instanceof ConsoleOutputInterface) {
            $output = $output->getErrorOutput();
        }
        (new SymfonyStyle($input, $output))->warning('Some commands could not be registered:');
        foreach ($this->registrationErrors as $error) {
            $this->doRenderThrowable($error, $output);
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Bundle\FrameworkBundle\Console\Descriptor;

use _ContaoManager\Symfony\Component\Console\Formatter\OutputFormatter;
use _ContaoManager\Symfony\Component\Console\Helper\Dumper;
use _ContaoManager\Symfony\Component\Console\Helper\Table;
use _ContaoManager\Symfony\Component\Console\Helper\TableCell;
use _ContaoManager\Symfony\Component\Console\Style\SymfonyStyle;
use _ContaoManager\Symfony\Component\DependencyInjection\Alias;
use _ContaoManager\Symfony\Component\DependencyInjection\Argument\AbstractArgument;
use _ContaoManager\Symfony\Component\DependencyInjection\Argument\IteratorArgument;
use _ContaoManager\Symfony\Component\DependencyInjection\Argument\ServiceClosureArgument;
use _ContaoManager\Symfony\Component\DependencyInjection\Argument\ServiceLocatorArgument;
use _ContaoManager\Symfony\Component\DependencyInjection\Argument\TaggedIteratorArgument;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerBuilder;
use _ContaoManager\Symfony\Component\DependencyInjection\Definition;
use _ContaoManager\Symfony\Component\DependencyInjection\ParameterBag\ParameterBag;
use _ContaoManager\Symfony\Component\DependencyInjection\Reference;
use _ContaoManager\Symfony\Component\ErrorHandler\ErrorRenderer\FileLinkFormatter;
use _ContaoManager\Symfony\Component\EventDispatcher\EventDispatcherInterface;
use _ContaoManager\Symfony\Component\Routing\Route;
use _ContaoManager\Symfony\Component\Routing\RouteCollection;
/**
 * @author Jean-François Simon <jeanfrancois.simon@sensiolabs.com>
 *
 * @internal
 */
class TextDescriptor extends Descriptor
{
    private ?FileLinkFormatter $fileLinkFormatter;
    public function __construct(?FileLinkFormatter $fileLinkFormatter = null)
    {
        $this->fileLinkFormatter = $fileLinkFormatter;
    }
    protected function describeRouteCollection(RouteCollection $routes, array $options = []): void
    {
        $showControllers = isset($options['show_controllers']) && $options['show_controllers'];
        $tableHeaders = ['Name', 'Method', 'Scheme', 'Host', 'Path'];
        if ($showControllers) {
            $tableHeaders[] = 'Controller';
        }
        if ($showAliases = $options['show_aliases'] ?? \false) {
            $tableHeaders[] = 'Aliases';
        }
        $tableRows = [];
        foreach ($routes->all() as $name => $route) {
            $controller = $route->getDefault('_controller');
            $row = [$name, $route->getMethods() ? implode('|', $route->getMethods()) : 'ANY', $route->getSchemes() ? implode('|', $route->getSchemes()) : 'ANY', '' !== $route->getHost() ? $route->getHost() : 'ANY', $this->formatControllerLink($controller, $route->getPath(), $options['container'] ?? null)];
            if ($showControllers) {
                $row[] = $controller ? $this->formatControllerLink($controller, $this->formatCallable($controller), $options['container'] ?? null) : '';
            }
            if ($showAliases) {
                $row[] = implode('|', ($reverseAliases ??= $this->getReverseAliases($routes))[$name] ?? []);
            }
            $tableRows[] = $row;
        }
        if (isset($options['output'])) {
            $options['output']->table($tableHeaders, $tableRows);
        } else {
            $table = new Table($this->getOutput());
            $table->setHeaders($tableHeaders)->setRows($tableRows);
            $table->render();
        }
    }
    protected function describeRoute(Route $route, array $options = []): void
    {
        $defaults = $route->getDefaults();
        if (isset($defaults['_controller'])) {
            $defaults['_controller'] = $this->formatControllerLink($defaults['_controller'], $this->formatCallable($defaults['_controller']), $options['container'] ?? null);
        }
        $tableHeaders = ['Property', 'Value'];
        $tableRows = [['Route Name', $options['name'] ?? ''], ['Path', $route->getPath()], ['Path Regex', $route->compile()->getRegex()], ['Host', '' !== $route->getHost() ? $route->getHost() : 'ANY'], ['Host Regex', '' !== $route->getHost() ? $route->compile()->getHostRegex() : ''], ['Scheme', $route->getSchemes() ? implode('|', $route->getSchemes()) : 'ANY'], ['Method', $route->getMethods() ? implode('|', $route->getMethods()) : 'ANY'], ['Requirements', $route->getRequirements() ? $this->formatRouterConfig($route->getRequirements()) : 'NO CUSTOM'], ['Class', $route::class], ['Defaults', $this->formatRouterConfig($defaults)], ['Options', $this->formatRouterConfig($route->getOptions())]];
        if ('' !== $route->getCondition()) {
            $tableRows[] = ['Condition', $route->getCondition()];
        }
        $table = new Table($this->getOutput());
        $table->setHeaders($tableHeaders)->setRows($tableRows);
        $table->render();
    }
    protected function describeContainerParameters(ParameterBag $parameters, array $options = []): void
    {
        $tableHeaders = ['Parameter', 'Value'];
        $deprecatedParameters = $parameters->allDeprecated();
        $tableRows = [];
        foreach ($this->sortParameters($parameters) as $parameter => $value) {
            $tableRows[] = [$parameter, $this->formatParameter($value)];
            if (isset($deprecatedParameters[$parameter])) {
                $tableRows[] = [new TableCell(\sprintf('<comment>(Since %s %s: %s)</comment>', $deprecatedParameters[$parameter][0], $deprecatedParameters[$parameter][1], \sprintf(...\array_slice($deprecatedParameters[$parameter], 2))), ['colspan' => 2])];
            }
        }
        $options['output']->title('Symfony Container Parameters');
        $options['output']->table($tableHeaders, $tableRows);
    }
    protected function describeContainerTags(ContainerBuilder $container, array $options = []): void
    {
        $showHidden = isset($options['show_hidden']) && $options['show_hidden'];
        if ($showHidden) {
            $options['output']->title('Symfony Container Hidden Tags');
        } else {
            $options['output']->title('Symfony Container Tags');
        }
        foreach ($this->findDefinitionsByTag($container, $showHidden) as $tag => $definitions) {
            $options['output']->section(\sprintf('"%s" tag', $tag));
            $options['output']->listing(array_keys($definitions));
        }
    }
    protected function describeContainerService(object $service, array $options = [], ?ContainerBuilder $container = null): void
    {
        if (!isset($options['id'])) {
            throw new \InvalidArgumentException('An "id" option must be provided.');
        }
        if ($service instanceof Alias) {
            $this->describeContainerAlias($service, $options, $container);
        } elseif ($service instanceof Definition) {
            $this->describeContainerDefinition($service, $options, $container);
        } else {
            $options['output']->title(\sprintf('Information for Service "<info>%s</info>"', $options['id']));
            $options['output']->table(['Service ID', 'Class'], [[$options['id'] ?? '-', $service::class]]);
        }
    }
    protected function describeContainerServices(ContainerBuilder $container, array $options = []): void
    {
        $showHidden = isset($options['show_hidden']) && $options['show_hidden'];
        $showTag = $options['tag'] ?? null;
        if ($showHidden) {
            $title = 'Symfony Container Hidden Services';
        } else {
            $title = 'Symfony Container Services';
        }
        if ($showTag) {
            $title .= \sprintf(' Tagged with "%s" Tag', $options['tag']);
        }
        $options['output']->title($title);
        $serviceIds = isset($options['tag']) && $options['tag'] ? $this->sortTaggedServicesByPriority($container->findTaggedServiceIds($options['tag'])) : $this->sortServiceIds($container->getServiceIds());
        $maxTags = [];
        if (isset($options['filter'])) {
            $serviceIds = array_filter($serviceIds, $options['filter']);
        }
        foreach ($serviceIds as $key => $serviceId) {
            $definition = $this->resolveServiceDefinition($container, $serviceId);
            // filter out hidden services unless shown explicitly
            if ($showHidden xor '.' === ($serviceId[0] ?? null)) {
                unset($serviceIds[$key]);
                continue;
            }
            if ($definition instanceof Definition) {
                if ($definition->hasTag('container.excluded')) {
                    unset($serviceIds[$key]);
                    continue;
                }
                if ($showTag) {
                    $tags = $definition->getTag($showTag);
                    foreach ($tags as $tag) {
                        foreach ($tag as $key => $value) {
                            if (!isset($maxTags[$key])) {
                                $maxTags[$key] = \strlen($key);
                            }
                            if (\is_array($value)) {
                                $value = $this->formatParameter($value);
                            }
                            if (\strlen($value) > $maxTags[$key]) {
                                $maxTags[$key] = \strlen($value);
                            }
                        }
                    }
                }
            }
        }
        $tagsCount = \count($maxTags);
        $tagsNames = array_keys($maxTags);
        $tableHeaders = array_merge(['Service ID'], $tagsNames, ['Class name']);
        $tableRows = [];
        $rawOutput = isset($options['raw_text']) && $options['raw_text'];
        foreach ($serviceIds as $serviceId) {
            $definition = $this->resolveServiceDefinition($container, $serviceId);
            $styledServiceId = $rawOutput ? $serviceId : \sprintf('<fg=cyan>%s</fg=cyan>', OutputFormatter::escape($serviceId));
            if ($definition instanceof Definition) {
                if ($showTag) {
                    foreach ($this->sortByPriority($definition->getTag($showTag)) as $key => $tag) {
                        $tagValues = [];
                        foreach ($tagsNames as $tagName) {
                            if (\is_array($tagValue = $tag[$tagName] ?? '')) {
                                $tagValue = $this->formatParameter($tagValue);
                            }
                            $tagValues[] = $tagValue;
                        }
                        if (0 === $key) {
                            $tableRows[] = array_merge([$serviceId], $tagValues, [$definition->getClass()]);
                        } else {
                            $tableRows[] = array_merge([' (same service as previous, another tag)'], $tagValues, ['']);
                        }
                    }
                } else {
                    $tableRows[] = [$styledServiceId, $definition->getClass()];
                }
            } elseif ($definition instanceof Alias) {
                $alias = $definition;
                $tableRows[] = array_merge([$styledServiceId, \sprintf('alias for "%s"', $alias)], $tagsCount ? array_fill(0, $tagsCount, '') : []);
            } else {
                $tableRows[] = array_merge([$styledServiceId, $definition::class], $tagsCount ? array_fill(0, $tagsCount, '') : []);
            }
        }
        $options['output']->table($tableHeaders, $tableRows);
    }
    protected function describeContainerDefinition(Definition $definition, array $options = [], ?ContainerBuilder $container = null): void
    {
        if (isset($options['id'])) {
            $options['output']->title(\sprintf('Information for Service "<info>%s</info>"', $options['id']));
        }
        if ('' !== $classDescription = $this->getClassDescription((string) $definition->getClass())) {
            $options['output']->text($classDescription . "\n");
        }
        $tableHeaders = ['Option', 'Value'];
        $tableRows[] = ['Service ID', $options['id'] ?? '-'];
        $tableRows[] = ['Class', $definition->getClass() ?: '-'];
        $omitTags = isset($options['omit_tags']) && $options['omit_tags'];
        if (!$omitTags && $tags = $definition->getTags()) {
            $tagInformation = [];
            foreach ($tags as $tagName => $tagData) {
                foreach ($tagData as $tagParameters) {
                    $parameters = array_map(fn($key, $value) => \sprintf('<info>%s</info>: %s', $key, \is_array($value) ? $this->formatParameter($value) : $value), array_keys($tagParameters), array_values($tagParameters));
                    $parameters = implode(', ', $parameters);
                    if ('' === $parameters) {
                        $tagInformation[] = \sprintf('%s', $tagName);
                    } else {
                        $tagInformation[] = \sprintf('%s (%s)', $tagName, $parameters);
                    }
                }
            }
            $tagInformation = implode("\n", $tagInformation);
        } else {
            $tagInformation = '-';
        }
        $tableRows[] = ['Tags', $tagInformation];
        $calls = $definition->getMethodCalls();
        if (\count($calls) > 0) {
            $callInformation = [];
            foreach ($calls as $call) {
                $callInformation[] = $call[0];
            }
            $tableRows[] = ['Calls', implode(', ', $callInformation)];
        }
        $tableRows[] = ['Public', $definition->isPublic() && !$definition->isPrivate() ? 'yes' : 'no'];
        $tableRows[] = ['Synthetic', $definition->isSynthetic() ? 'yes' : 'no'];
        $tableRows[] = ['Lazy', $definition->isLazy() ? 'yes' : 'no'];
        $tableRows[] = ['Shared', $definition->isShared() ? 'yes' : 'no'];
        $tableRows[] = ['Abstract', $definition->isAbstract() ? 'yes' : 'no'];
        $tableRows[] = ['Autowired', $definition->isAutowired() ? 'yes' : 'no'];
        $tableRows[] = ['Autoconfigured', $definition->isAutoconfigured() ? 'yes' : 'no'];
        if ($definition->getFile()) {
            $tableRows[] = ['Required File', $definition->getFile() ?: '-'];
        }
        if ($factory = $definition->getFactory()) {
            if (\is_array($factory)) {
                if ($factory[0] instanceof Reference) {
                    $tableRows[] = ['Factory Service', $factory[0]];
                } elseif ($factory[0] instanceof Definition) {
                    $tableRows[] = ['Factory Service', \sprintf('inline factory service (%s)', $factory[0]->getClass() ?? 'class not configured')];
                } else {
                    $tableRows[] = ['Factory Class', $factory[0]];
                }
                $tableRows[] = ['Factory Method', $factory[1]];
            } else {
                $tableRows[] = ['Factory Function', $factory];
            }
        }
        $showArguments = isset($options['show_arguments']) && $options['show_arguments'];
        $argumentsInformation = [];
        if ($showArguments && $arguments = $definition->getArguments()) {
            foreach ($arguments as $argument) {
                if ($argument instanceof ServiceClosureArgument) {
                    $argument = $argument->getValues()[0];
                }
                if ($argument instanceof Reference) {
                    $argumentsInformation[] = \sprintf('Service(%s)', (string) $argument);
                } elseif ($argument instanceof IteratorArgument) {
                    if ($argument instanceof TaggedIteratorArgument) {
                        $argumentsInformation[] = \sprintf('Tagged Iterator for "%s"%s', $argument->getTag(), $options['is_debug'] ? '' : \sprintf(' (%d element(s))', \count($argument->getValues())));
                    } else {
                        $argumentsInformation[] = \sprintf('Iterator (%d element(s))', \count($argument->getValues()));
                    }
                    foreach ($argument->getValues() as $ref) {
                        $argumentsInformation[] = \sprintf('- Service(%s)', $ref);
                    }
                } elseif ($argument instanceof ServiceLocatorArgument) {
                    $argumentsInformation[] = \sprintf('Service locator (%d element(s))', \count($argument->getValues()));
                } elseif ($argument instanceof Definition) {
                    $argumentsInformation[] = 'Inlined Service';
                } elseif ($argument instanceof \UnitEnum) {
                    $argumentsInformation[] = ltrim(var_export($argument, \true), '\\');
                } elseif ($argument instanceof AbstractArgument) {
                    $argumentsInformation[] = \sprintf('Abstract argument (%s)', $argument->getText());
                } else {
                    $argumentsInformation[] = \is_array($argument) ? \sprintf('Array (%d element(s))', \count($argument)) : $argument;
                }
            }
            $tableRows[] = ['Arguments', implode("\n", $argumentsInformation)];
        }
        $inEdges = null !== $container && isset($options['id']) ? $this->getServiceEdges($container, $options['id']) : [];
        $tableRows[] = ['Usages', $inEdges ? implode(\PHP_EOL, $inEdges) : 'none'];
        $options['output']->table($tableHeaders, $tableRows);
    }
    protected function describeContainerDeprecations(ContainerBuilder $container, array $options = []): void
    {
        $containerDeprecationFilePath = \sprintf('%s/%sDeprecations.log', $container->getParameter('kernel.build_dir'), $container->getParameter('kernel.container_class'));
        if (!file_exists($containerDeprecationFilePath)) {
            $options['output']->warning('The deprecation file does not exist, please try warming the cache first.');
            return;
        }
        $logs = unserialize(file_get_contents($containerDeprecationFilePath));
        if (0 === \count($logs)) {
            $options['output']->success('There are no deprecations in the logs!');
            return;
        }
        $formattedLogs = [];
        $remainingCount = 0;
        foreach ($logs as $log) {
            $formattedLogs[] = \sprintf("%sx: %s\n      in %s:%s", $log['count'], $log['message'], $log['file'], $log['line']);
            $remainingCount += $log['count'];
        }
        $options['output']->title(\sprintf('Remaining deprecations (%s)', $remainingCount));
        $options['output']->listing($formattedLogs);
    }
    protected function describeContainerAlias(Alias $alias, array $options = [], ?ContainerBuilder $container = null): void
    {
        if ($alias->isPublic() && !$alias->isPrivate()) {
            $options['output']->comment(\sprintf('This service is a <info>public</info> alias for the service <info>%s</info>', (string) $alias));
        } else {
            $options['output']->comment(\sprintf('This service is a <comment>private</comment> alias for the service <info>%s</info>', (string) $alias));
        }
        if (!$container) {
            return;
        }
        $this->describeContainerDefinition($container->getDefinition((string) $alias), array_merge($options, ['id' => (string) $alias]), $container);
    }
    protected function describeContainerParameter(mixed $parameter, ?array $deprecation, array $options = []): void
    {
        $parameterName = $options['parameter'];
        $rows = [[$parameterName, $this->formatParameter($parameter)]];
        if ($deprecation) {
            $rows[] = [new TableCell(\sprintf('<comment>(Since %s %s: %s)</comment>', $deprecation[0], $deprecation[1], \sprintf(...\array_slice($deprecation, 2))), ['colspan' => 2])];
        }
        $options['output']->table(['Parameter', 'Value'], $rows);
    }
    protected function describeContainerEnvVars(array $envs, array $options = []): void
    {
        $dump = new Dumper($this->output);
        $options['output']->title('Symfony Container Environment Variables');
        if (null !== $name = $options['name'] ?? null) {
            $options['output']->comment('Displaying detailed environment variable usage matching ' . $name);
            $matches = \false;
            foreach ($envs as $env) {
                if ($name === $env['name'] || \false !== stripos($env['name'], $name)) {
                    $matches = \true;
                    $options['output']->section('%env(' . $env['processor'] . ':' . $env['name'] . ')%');
                    $options['output']->table([], [['<info>Default value</>', $env['default_available'] ? $dump($env['default_value']) : 'n/a'], ['<info>Real value</>', $env['runtime_available'] ? $dump($env['runtime_value']) : 'n/a'], ['<info>Processed value</>', $env['default_available'] || $env['runtime_available'] ? $dump($env['processed_value']) : 'n/a']]);
                }
            }
            if (!$matches) {
                $options['output']->block('None of the environment variables match this name.');
            } else {
                $options['output']->comment('Note real values might be different between web and CLI.');
            }
            return;
        }
        if (!$envs) {
            $options['output']->block('No environment variables are being used.');
            return;
        }
        $rows = [];
        $missing = [];
        foreach ($envs as $env) {
            if (isset($rows[$env['name']])) {
                continue;
            }
            $rows[$env['name']] = [$env['name'], $env['default_available'] ? $dump($env['default_value']) : 'n/a', $env['runtime_available'] ? $dump($env['runtime_value']) : 'n/a'];
            if (!$env['default_available'] && !$env['runtime_available']) {
                $missing[$env['name']] = \true;
            }
        }
        $options['output']->table(['Name', 'Default value', 'Real value'], $rows);
        $options['output']->comment('Note real values might be different between web and CLI.');
        if ($missing) {
            $options['output']->warning('The following variables are missing:');
            $options['output']->listing(array_keys($missing));
        }
    }
    protected function describeEventDispatcherListeners(EventDispatcherInterface $eventDispatcher, array $options = []): void
    {
        $event = $options['event'] ?? null;
        $dispatcherServiceName = $options['dispatcher_service_name'] ?? null;
        $title = 'Registered Listeners';
        if (null !== $dispatcherServiceName) {
            $title .= \sprintf(' of Event Dispatcher "%s"', $dispatcherServiceName);
        }
        if (null !== $event) {
            $title .= \sprintf(' for "%s" Event', $event);
            $registeredListeners = $eventDispatcher->getListeners($event);
        } else {
            $title .= ' Grouped by Event';
            // Try to see if "events" exists
            $registeredListeners = \array_key_exists('events', $options) ? array_combine($options['events'], array_map(fn($event) => $eventDispatcher->getListeners($event), $options['events'])) : $eventDispatcher->getListeners();
        }
        $options['output']->title($title);
        if (null !== $event) {
            $this->renderEventListenerTable($eventDispatcher, $event, $registeredListeners, $options['output']);
        } else {
            ksort($registeredListeners);
            foreach ($registeredListeners as $eventListened => $eventListeners) {
                $options['output']->section(\sprintf('"%s" event', $eventListened));
                $this->renderEventListenerTable($eventDispatcher, $eventListened, $eventListeners, $options['output']);
            }
        }
    }
    protected function describeCallable(mixed $callable, array $options = []): void
    {
        $this->writeText($this->formatCallable($callable), $options);
    }
    private function renderEventListenerTable(EventDispatcherInterface $eventDispatcher, string $event, array $eventListeners, SymfonyStyle $io): void
    {
        $tableHeaders = ['Order', 'Callable', 'Priority'];
        $tableRows = [];
        foreach ($eventListeners as $order => $listener) {
            $tableRows[] = [\sprintf('#%d', $order + 1), $this->formatCallable($listener), $eventDispatcher->getListenerPriority($event, $listener)];
        }
        $io->table($tableHeaders, $tableRows);
    }
    private function formatRouterConfig(array $config): string
    {
        if (!$config) {
            return 'NONE';
        }
        ksort($config);
        $configAsString = '';
        foreach ($config as $key => $value) {
            $configAsString .= \sprintf("\n%s: %s", $key, $this->formatValue($value));
        }
        return trim($configAsString);
    }
    private function formatControllerLink(mixed $controller, string $anchorText, ?callable $getContainer = null): string
    {
        if (null === $this->fileLinkFormatter) {
            return $anchorText;
        }
        try {
            if (null === $controller) {
                return $anchorText;
            } elseif (\is_array($controller)) {
                $r = new \ReflectionMethod($controller[0], $controller[1]);
            } elseif ($controller instanceof \Closure) {
                $r = new \ReflectionFunction($controller);
            } elseif (method_exists($controller, '__invoke')) {
                $r = new \ReflectionMethod($controller, '__invoke');
            } elseif (!\is_string($controller)) {
                return $anchorText;
            } elseif (str_contains($controller, '::')) {
                $r = new \ReflectionMethod(...explode('::', $controller, 2));
            } else {
                $r = new \ReflectionFunction($controller);
            }
        } catch (\ReflectionException) {
            if (\is_array($controller)) {
                $controller = implode('::', $controller);
            }
            $id = $controller;
            $method = '__invoke';
            if ($pos = strpos($controller, '::')) {
                $id = substr($controller, 0, $pos);
                $method = substr($controller, $pos + 2);
            }
            if (!$getContainer || !($container = $getContainer()) || !$container->has($id)) {
                return $anchorText;
            }
            try {
                $r = new \ReflectionMethod($container->findDefinition($id)->getClass(), $method);
            } catch (\ReflectionException) {
                return $anchorText;
            }
        }
        $fileLink = $this->fileLinkFormatter->format($r->getFileName(), $r->getStartLine());
        if ($fileLink) {
            return \sprintf('<href=%s>%s</>', $fileLink, $anchorText);
        }
        return $anchorText;
    }
    private function formatCallable(mixed $callable): string
    {
        if (\is_array($callable)) {
            if (\is_object($callable[0])) {
                return \sprintf('%s::%s()', $callable[0]::class, $callable[1]);
            }
            return \sprintf('%s::%s()', $callable[0], $callable[1]);
        }
        if (\is_string($callable)) {
            return \sprintf('%s()', $callable);
        }
        if ($callable instanceof \Closure) {
            $r = new \ReflectionFunction($callable);
            if (str_contains($r->name, '{closure')) {
                return 'Closure()';
            }
            if ($class = \PHP_VERSION_ID >= 80111 ? $r->getClosureCalledClass() : $r->getClosureScopeClass()) {
                return \sprintf('%s::%s()', $class->name, $r->name);
            }
            return $r->name . '()';
        }
        if (method_exists($callable, '__invoke')) {
            return \sprintf('%s::__invoke()', $callable::class);
        }
        throw new \InvalidArgumentException('Callable is not describable.');
    }
    private function writeText(string $content, array $options = []): void
    {
        $this->write(isset($options['raw_text']) && $options['raw_text'] ? strip_tags($content) : $content, isset($options['raw_output']) ? !$options['raw_output'] : \true);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Bundle\FrameworkBundle\Console\Descriptor;

use _ContaoManager\Symfony\Component\Console\Exception\LogicException;
use _ContaoManager\Symfony\Component\Console\Exception\RuntimeException;
use _ContaoManager\Symfony\Component\DependencyInjection\Alias;
use _ContaoManager\Symfony\Component\DependencyInjection\Argument\AbstractArgument;
use _ContaoManager\Symfony\Component\DependencyInjection\Argument\IteratorArgument;
use _ContaoManager\Symfony\Component\DependencyInjection\Argument\ServiceClosureArgument;
use _ContaoManager\Symfony\Component\DependencyInjection\Argument\ServiceLocatorArgument;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerBuilder;
use _ContaoManager\Symfony\Component\DependencyInjection\Definition;
use _ContaoManager\Symfony\Component\DependencyInjection\ParameterBag\ParameterBag;
use _ContaoManager\Symfony\Component\DependencyInjection\Reference;
use _ContaoManager\Symfony\Component\EventDispatcher\EventDispatcherInterface;
use _ContaoManager\Symfony\Component\Routing\Route;
use _ContaoManager\Symfony\Component\Routing\RouteCollection;
/**
 * @author Jean-François Simon <jeanfrancois.simon@sensiolabs.com>
 *
 * @internal
 */
class XmlDescriptor extends Descriptor
{
    protected function describeRouteCollection(RouteCollection $routes, array $options = []): void
    {
        $this->writeDocument($this->getRouteCollectionDocument($routes, $options));
    }
    protected function describeRoute(Route $route, array $options = []): void
    {
        $this->writeDocument($this->getRouteDocument($route, $options['name'] ?? null));
    }
    protected function describeContainerParameters(ParameterBag $parameters, array $options = []): void
    {
        $this->writeDocument($this->getContainerParametersDocument($parameters));
    }
    protected function describeContainerTags(ContainerBuilder $container, array $options = []): void
    {
        $this->writeDocument($this->getContainerTagsDocument($container, isset($options['show_hidden']) && $options['show_hidden']));
    }
    protected function describeContainerService(object $service, array $options = [], ?ContainerBuilder $container = null): void
    {
        if (!isset($options['id'])) {
            throw new \InvalidArgumentException('An "id" option must be provided.');
        }
        $this->writeDocument($this->getContainerServiceDocument($service, $options['id'], $container, isset($options['show_arguments']) && $options['show_arguments']));
    }
    protected function describeContainerServices(ContainerBuilder $container, array $options = []): void
    {
        $this->writeDocument($this->getContainerServicesDocument($container, $options['tag'] ?? null, isset($options['show_hidden']) && $options['show_hidden'], isset($options['show_arguments']) && $options['show_arguments'], $options['filter'] ?? null, $options['id'] ?? null));
    }
    protected function describeContainerDefinition(Definition $definition, array $options = [], ?ContainerBuilder $container = null): void
    {
        $this->writeDocument($this->getContainerDefinitionDocument($definition, $options['id'] ?? null, isset($options['omit_tags']) && $options['omit_tags'], isset($options['show_arguments']) && $options['show_arguments'], $container));
    }
    protected function describeContainerAlias(Alias $alias, array $options = [], ?ContainerBuilder $container = null): void
    {
        $dom = new \DOMDocument('1.0', 'UTF-8');
        $dom->appendChild($dom->importNode($this->getContainerAliasDocument($alias, $options['id'] ?? null)->childNodes->item(0), \true));
        if (!$container) {
            $this->writeDocument($dom);
            return;
        }
        $dom->appendChild($dom->importNode($this->getContainerDefinitionDocument($container->getDefinition((string) $alias), (string) $alias, \false, \false, $container)->childNodes->item(0), \true));
        $this->writeDocument($dom);
    }
    protected function describeEventDispatcherListeners(EventDispatcherInterface $eventDispatcher, array $options = []): void
    {
        $this->writeDocument($this->getEventDispatcherListenersDocument($eventDispatcher, $options));
    }
    protected function describeCallable(mixed $callable, array $options = []): void
    {
        $this->writeDocument($this->getCallableDocument($callable));
    }
    protected function describeContainerParameter(mixed $parameter, ?array $deprecation, array $options = []): void
    {
        $this->writeDocument($this->getContainerParameterDocument($parameter, $deprecation, $options));
    }
    protected function describeContainerEnvVars(array $envs, array $options = []): void
    {
        throw new LogicException('Using the XML format to debug environment variables is not supported.');
    }
    protected function describeContainerDeprecations(ContainerBuilder $container, array $options = []): void
    {
        $containerDeprecationFilePath = \sprintf('%s/%sDeprecations.log', $container->getParameter('kernel.build_dir'), $container->getParameter('kernel.container_class'));
        if (!file_exists($containerDeprecationFilePath)) {
            throw new RuntimeException('The deprecation file does not exist, please try warming the cache first.');
        }
        $logs = unserialize(file_get_contents($containerDeprecationFilePath));
        $dom = new \DOMDocument('1.0', 'UTF-8');
        $dom->appendChild($deprecationsXML = $dom->createElement('deprecations'));
        $remainingCount = 0;
        foreach ($logs as $log) {
            $deprecationsXML->appendChild($deprecationXML = $dom->createElement('deprecation'));
            $deprecationXML->setAttribute('count', $log['count']);
            $deprecationXML->appendChild($dom->createElement('message', $log['message']));
            $deprecationXML->appendChild($dom->createElement('file', $log['file']));
            $deprecationXML->appendChild($dom->createElement('line', $log['line']));
            $remainingCount += $log['count'];
        }
        $deprecationsXML->setAttribute('remainingCount', $remainingCount);
        $this->writeDocument($dom);
    }
    private function writeDocument(\DOMDocument $dom): void
    {
        $dom->formatOutput = \true;
        $this->write($dom->saveXML());
    }
    private function getRouteCollectionDocument(RouteCollection $routes, array $options): \DOMDocument
    {
        $dom = new \DOMDocument('1.0', 'UTF-8');
        $dom->appendChild($routesXML = $dom->createElement('routes'));
        foreach ($routes->all() as $name => $route) {
            $routeXML = $this->getRouteDocument($route, $name);
            if (($showAliases ??= $options['show_aliases'] ?? \false) && $aliases = ($reverseAliases ??= $this->getReverseAliases($routes))[$name] ?? []) {
                $routeXML->firstChild->appendChild($aliasesXML = $routeXML->createElement('aliases'));
                foreach ($aliases as $alias) {
                    $aliasesXML->appendChild($aliasXML = $routeXML->createElement('alias'));
                    $aliasXML->appendChild(new \DOMText($alias));
                }
            }
            $routesXML->appendChild($routesXML->ownerDocument->importNode($routeXML->childNodes->item(0), \true));
        }
        return $dom;
    }
    private function getRouteDocument(Route $route, ?string $name = null): \DOMDocument
    {
        $dom = new \DOMDocument('1.0', 'UTF-8');
        $dom->appendChild($routeXML = $dom->createElement('route'));
        if ($name) {
            $routeXML->setAttribute('name', $name);
        }
        $routeXML->setAttribute('class', $route::class);
        $routeXML->appendChild($pathXML = $dom->createElement('path'));
        $pathXML->setAttribute('regex', $route->compile()->getRegex());
        $pathXML->appendChild(new \DOMText($route->getPath()));
        if ('' !== $route->getHost()) {
            $routeXML->appendChild($hostXML = $dom->createElement('host'));
            $hostXML->setAttribute('regex', $route->compile()->getHostRegex());
            $hostXML->appendChild(new \DOMText($route->getHost()));
        }
        foreach ($route->getSchemes() as $scheme) {
            $routeXML->appendChild($schemeXML = $dom->createElement('scheme'));
            $schemeXML->appendChild(new \DOMText($scheme));
        }
        foreach ($route->getMethods() as $method) {
            $routeXML->appendChild($methodXML = $dom->createElement('method'));
            $methodXML->appendChild(new \DOMText($method));
        }
        if ($route->getDefaults()) {
            $routeXML->appendChild($defaultsXML = $dom->createElement('defaults'));
            foreach ($route->getDefaults() as $attribute => $value) {
                $defaultsXML->appendChild($defaultXML = $dom->createElement('default'));
                $defaultXML->setAttribute('key', $attribute);
                $defaultXML->appendChild(new \DOMText($this->formatValue($value)));
            }
        }
        $originRequirements = $requirements = $route->getRequirements();
        unset($requirements['_scheme'], $requirements['_method']);
        if ($requirements) {
            $routeXML->appendChild($requirementsXML = $dom->createElement('requirements'));
            foreach ($originRequirements as $attribute => $pattern) {
                $requirementsXML->appendChild($requirementXML = $dom->createElement('requirement'));
                $requirementXML->setAttribute('key', $attribute);
                $requirementXML->appendChild(new \DOMText($pattern));
            }
        }
        if ($route->getOptions()) {
            $routeXML->appendChild($optionsXML = $dom->createElement('options'));
            foreach ($route->getOptions() as $name => $value) {
                $optionsXML->appendChild($optionXML = $dom->createElement('option'));
                $optionXML->setAttribute('key', $name);
                $optionXML->appendChild(new \DOMText($this->formatValue($value)));
            }
        }
        if ('' !== $route->getCondition()) {
            $routeXML->appendChild($conditionXML = $dom->createElement('condition'));
            $conditionXML->appendChild(new \DOMText($route->getCondition()));
        }
        return $dom;
    }
    private function getContainerParametersDocument(ParameterBag $parameters): \DOMDocument
    {
        $dom = new \DOMDocument('1.0', 'UTF-8');
        $dom->appendChild($parametersXML = $dom->createElement('parameters'));
        $deprecatedParameters = $parameters->allDeprecated();
        foreach ($this->sortParameters($parameters) as $key => $value) {
            $parametersXML->appendChild($parameterXML = $dom->createElement('parameter'));
            $parameterXML->setAttribute('key', $key);
            $parameterXML->appendChild(new \DOMText($this->formatParameter($value)));
            if (isset($deprecatedParameters[$key])) {
                $parameterXML->setAttribute('deprecated', \sprintf('Since %s %s: %s', $deprecatedParameters[$key][0], $deprecatedParameters[$key][1], \sprintf(...\array_slice($deprecatedParameters[$key], 2))));
            }
        }
        return $dom;
    }
    private function getContainerTagsDocument(ContainerBuilder $container, bool $showHidden = \false): \DOMDocument
    {
        $dom = new \DOMDocument('1.0', 'UTF-8');
        $dom->appendChild($containerXML = $dom->createElement('container'));
        foreach ($this->findDefinitionsByTag($container, $showHidden) as $tag => $definitions) {
            $containerXML->appendChild($tagXML = $dom->createElement('tag'));
            $tagXML->setAttribute('name', $tag);
            foreach ($definitions as $serviceId => $definition) {
                $definitionXML = $this->getContainerDefinitionDocument($definition, $serviceId, \true, \false, $container);
                $tagXML->appendChild($dom->importNode($definitionXML->childNodes->item(0), \true));
            }
        }
        return $dom;
    }
    private function getContainerServiceDocument(object $service, string $id, ?ContainerBuilder $container = null, bool $showArguments = \false): \DOMDocument
    {
        $dom = new \DOMDocument('1.0', 'UTF-8');
        if ($service instanceof Alias) {
            $dom->appendChild($dom->importNode($this->getContainerAliasDocument($service, $id)->childNodes->item(0), \true));
            if ($container) {
                $dom->appendChild($dom->importNode($this->getContainerDefinitionDocument($container->getDefinition((string) $service), (string) $service, \false, $showArguments, $container)->childNodes->item(0), \true));
            }
        } elseif ($service instanceof Definition) {
            $dom->appendChild($dom->importNode($this->getContainerDefinitionDocument($service, $id, \false, $showArguments, $container)->childNodes->item(0), \true));
        } else {
            $dom->appendChild($serviceXML = $dom->createElement('service'));
            $serviceXML->setAttribute('id', $id);
            $serviceXML->setAttribute('class', $service::class);
        }
        return $dom;
    }
    private function getContainerServicesDocument(ContainerBuilder $container, ?string $tag = null, bool $showHidden = \false, bool $showArguments = \false, ?callable $filter = null, ?string $id = null): \DOMDocument
    {
        $dom = new \DOMDocument('1.0', 'UTF-8');
        $dom->appendChild($containerXML = $dom->createElement('container'));
        $serviceIds = $tag ? $this->sortTaggedServicesByPriority($container->findTaggedServiceIds($tag)) : $this->sortServiceIds($container->getServiceIds());
        if ($filter) {
            $serviceIds = array_filter($serviceIds, $filter);
        }
        foreach ($serviceIds as $serviceId) {
            $service = $this->resolveServiceDefinition($container, $serviceId);
            if ($showHidden xor '.' === ($serviceId[0] ?? null)) {
                continue;
            }
            if ($service instanceof Definition && $service->hasTag('container.excluded')) {
                continue;
            }
            $serviceXML = $this->getContainerServiceDocument($service, $serviceId, null, $showArguments);
            $containerXML->appendChild($containerXML->ownerDocument->importNode($serviceXML->childNodes->item(0), \true));
        }
        return $dom;
    }
    private function getContainerDefinitionDocument(Definition $definition, ?string $id = null, bool $omitTags = \false, bool $showArguments = \false, ?ContainerBuilder $container = null): \DOMDocument
    {
        $dom = new \DOMDocument('1.0', 'UTF-8');
        $dom->appendChild($serviceXML = $dom->createElement('definition'));
        if ($id) {
            $serviceXML->setAttribute('id', $id);
        }
        if ('' !== $classDescription = $this->getClassDescription((string) $definition->getClass())) {
            $serviceXML->appendChild($descriptionXML = $dom->createElement('description'));
            $descriptionXML->appendChild($dom->createCDATASection($classDescription));
        }
        $serviceXML->setAttribute('class', $definition->getClass() ?? '');
        if ($factory = $definition->getFactory()) {
            $serviceXML->appendChild($factoryXML = $dom->createElement('factory'));
            if (\is_array($factory)) {
                if ($factory[0] instanceof Reference) {
                    $factoryXML->setAttribute('service', (string) $factory[0]);
                } elseif ($factory[0] instanceof Definition) {
                    $factoryXML->setAttribute('service', \sprintf('inline factory service (%s)', $factory[0]->getClass() ?? 'not configured'));
                } else {
                    $factoryXML->setAttribute('class', $factory[0]);
                }
                $factoryXML->setAttribute('method', $factory[1]);
            } else {
                $factoryXML->setAttribute('function', $factory);
            }
        }
        $serviceXML->setAttribute('public', $definition->isPublic() && !$definition->isPrivate() ? 'true' : 'false');
        $serviceXML->setAttribute('synthetic', $definition->isSynthetic() ? 'true' : 'false');
        $serviceXML->setAttribute('lazy', $definition->isLazy() ? 'true' : 'false');
        $serviceXML->setAttribute('shared', $definition->isShared() ? 'true' : 'false');
        $serviceXML->setAttribute('abstract', $definition->isAbstract() ? 'true' : 'false');
        $serviceXML->setAttribute('autowired', $definition->isAutowired() ? 'true' : 'false');
        $serviceXML->setAttribute('autoconfigured', $definition->isAutoconfigured() ? 'true' : 'false');
        if ($definition->isDeprecated()) {
            $serviceXML->setAttribute('deprecated', 'true');
            $serviceXML->setAttribute('deprecation_message', $definition->getDeprecation($id)['message']);
        } else {
            $serviceXML->setAttribute('deprecated', 'false');
        }
        $serviceXML->setAttribute('file', $definition->getFile() ?? '');
        $calls = $definition->getMethodCalls();
        if (\count($calls) > 0) {
            $serviceXML->appendChild($callsXML = $dom->createElement('calls'));
            foreach ($calls as $callData) {
                $callsXML->appendChild($callXML = $dom->createElement('call'));
                $callXML->setAttribute('method', $callData[0]);
                if ($callData[2] ?? \false) {
                    $callXML->setAttribute('returns-clone', 'true');
                }
            }
        }
        if ($showArguments) {
            foreach ($this->getArgumentNodes($definition->getArguments(), $dom, $container) as $node) {
                $serviceXML->appendChild($node);
            }
        }
        if (!$omitTags) {
            if ($tags = $this->sortTagsByPriority($definition->getTags())) {
                $serviceXML->appendChild($tagsXML = $dom->createElement('tags'));
                foreach ($tags as $tagName => $tagData) {
                    foreach ($tagData as $parameters) {
                        $tagsXML->appendChild($tagXML = $dom->createElement('tag'));
                        $tagXML->setAttribute('name', $tagName);
                        foreach ($parameters as $name => $value) {
                            $tagXML->appendChild($parameterXML = $dom->createElement('parameter'));
                            $parameterXML->setAttribute('name', $name);
                            $parameterXML->appendChild(new \DOMText($this->formatParameter($value)));
                        }
                    }
                }
            }
        }
        if (null !== $container && null !== $id) {
            $edges = $this->getServiceEdges($container, $id);
            if ($edges) {
                $serviceXML->appendChild($usagesXML = $dom->createElement('usages'));
                foreach ($edges as $edge) {
                    $usagesXML->appendChild($usageXML = $dom->createElement('usage'));
                    $usageXML->appendChild(new \DOMText($edge));
                }
            }
        }
        return $dom;
    }
    /**
     * @return \DOMNode[]
     */
    private function getArgumentNodes(array $arguments, \DOMDocument $dom, ?ContainerBuilder $container = null): array
    {
        $nodes = [];
        foreach ($arguments as $argumentKey => $argument) {
            $argumentXML = $dom->createElement('argument');
            if (\is_string($argumentKey)) {
                $argumentXML->setAttribute('key', $argumentKey);
            }
            if ($argument instanceof ServiceClosureArgument) {
                $argument = $argument->getValues()[0];
            }
            if ($argument instanceof Reference) {
                $argumentXML->setAttribute('type', 'service');
                $argumentXML->setAttribute('id', (string) $argument);
            } elseif ($argument instanceof IteratorArgument || $argument instanceof ServiceLocatorArgument) {
                $argumentXML->setAttribute('type', $argument instanceof IteratorArgument ? 'iterator' : 'service_locator');
                foreach ($this->getArgumentNodes($argument->getValues(), $dom, $container) as $childArgumentXML) {
                    $argumentXML->appendChild($childArgumentXML);
                }
            } elseif ($argument instanceof Definition) {
                $argumentXML->appendChild($dom->importNode($this->getContainerDefinitionDocument($argument, null, \false, \true, $container)->childNodes->item(0), \true));
            } elseif ($argument instanceof AbstractArgument) {
                $argumentXML->setAttribute('type', 'abstract');
                $argumentXML->appendChild(new \DOMText($argument->getText()));
            } elseif (\is_array($argument)) {
                $argumentXML->setAttribute('type', 'collection');
                foreach ($this->getArgumentNodes($argument, $dom, $container) as $childArgumentXML) {
                    $argumentXML->appendChild($childArgumentXML);
                }
            } elseif ($argument instanceof \UnitEnum) {
                $argumentXML->setAttribute('type', 'constant');
                $argumentXML->appendChild(new \DOMText(ltrim(var_export($argument, \true), '\\')));
            } else {
                $argumentXML->appendChild(new \DOMText($argument));
            }
            $nodes[] = $argumentXML;
        }
        return $nodes;
    }
    private function getContainerAliasDocument(Alias $alias, ?string $id = null): \DOMDocument
    {
        $dom = new \DOMDocument('1.0', 'UTF-8');
        $dom->appendChild($aliasXML = $dom->createElement('alias'));
        if ($id) {
            $aliasXML->setAttribute('id', $id);
        }
        $aliasXML->setAttribute('service', (string) $alias);
        $aliasXML->setAttribute('public', $alias->isPublic() && !$alias->isPrivate() ? 'true' : 'false');
        return $dom;
    }
    private function getContainerParameterDocument(mixed $parameter, ?array $deprecation, array $options = []): \DOMDocument
    {
        $dom = new \DOMDocument('1.0', 'UTF-8');
        $dom->appendChild($parameterXML = $dom->createElement('parameter'));
        if (isset($options['parameter'])) {
            $parameterXML->setAttribute('key', $options['parameter']);
            if ($deprecation) {
                $parameterXML->setAttribute('deprecated', \sprintf('Since %s %s: %s', $deprecation[0], $deprecation[1], \sprintf(...\array_slice($deprecation, 2))));
            }
        }
        $parameterXML->appendChild(new \DOMText($this->formatParameter($parameter)));
        return $dom;
    }
    private function getEventDispatcherListenersDocument(EventDispatcherInterface $eventDispatcher, array $options): \DOMDocument
    {
        $event = \array_key_exists('event', $options) ? $options['event'] : null;
        $dom = new \DOMDocument('1.0', 'UTF-8');
        $dom->appendChild($eventDispatcherXML = $dom->createElement('event-dispatcher'));
        if (null !== $event) {
            $registeredListeners = $eventDispatcher->getListeners($event);
            $this->appendEventListenerDocument($eventDispatcher, $event, $eventDispatcherXML, $registeredListeners);
        } else {
            // Try to see if "events" exists
            $registeredListeners = \array_key_exists('events', $options) ? array_combine($options['events'], array_map(fn($event) => $eventDispatcher->getListeners($event), $options['events'])) : $eventDispatcher->getListeners();
            ksort($registeredListeners);
            foreach ($registeredListeners as $eventListened => $eventListeners) {
                $eventDispatcherXML->appendChild($eventXML = $dom->createElement('event'));
                $eventXML->setAttribute('name', $eventListened);
                $this->appendEventListenerDocument($eventDispatcher, $eventListened, $eventXML, $eventListeners);
            }
        }
        return $dom;
    }
    private function appendEventListenerDocument(EventDispatcherInterface $eventDispatcher, string $event, \DOMElement $element, array $eventListeners): void
    {
        foreach ($eventListeners as $listener) {
            $callableXML = $this->getCallableDocument($listener);
            $callableXML->childNodes->item(0)->setAttribute('priority', $eventDispatcher->getListenerPriority($event, $listener));
            $element->appendChild($element->ownerDocument->importNode($callableXML->childNodes->item(0), \true));
        }
    }
    private function getCallableDocument(mixed $callable): \DOMDocument
    {
        $dom = new \DOMDocument('1.0', 'UTF-8');
        $dom->appendChild($callableXML = $dom->createElement('callable'));
        if (\is_array($callable)) {
            $callableXML->setAttribute('type', 'function');
            if (\is_object($callable[0])) {
                $callableXML->setAttribute('name', $callable[1]);
                $callableXML->setAttribute('class', $callable[0]::class);
            } else if (!str_starts_with($callable[1], 'parent::')) {
                $callableXML->setAttribute('name', $callable[1]);
                $callableXML->setAttribute('class', $callable[0]);
                $callableXML->setAttribute('static', 'true');
            } else {
                $callableXML->setAttribute('name', substr($callable[1], 8));
                $callableXML->setAttribute('class', $callable[0]);
                $callableXML->setAttribute('static', 'true');
                $callableXML->setAttribute('parent', 'true');
            }
            return $dom;
        }
        if (\is_string($callable)) {
            $callableXML->setAttribute('type', 'function');
            if (!str_contains($callable, '::')) {
                $callableXML->setAttribute('name', $callable);
            } else {
                $callableParts = explode('::', $callable);
                $callableXML->setAttribute('name', $callableParts[1]);
                $callableXML->setAttribute('class', $callableParts[0]);
                $callableXML->setAttribute('static', 'true');
            }
            return $dom;
        }
        if ($callable instanceof \Closure) {
            $callableXML->setAttribute('type', 'closure');
            $r = new \ReflectionFunction($callable);
            if (str_contains($r->name, '{closure')) {
                return $dom;
            }
            $callableXML->setAttribute('name', $r->name);
            if ($class = \PHP_VERSION_ID >= 80111 ? $r->getClosureCalledClass() : $r->getClosureScopeClass()) {
                $callableXML->setAttribute('class', $class->name);
                if (!$r->getClosureThis()) {
                    $callableXML->setAttribute('static', 'true');
                }
            }
            return $dom;
        }
        if (method_exists($callable, '__invoke')) {
            $callableXML->setAttribute('type', 'object');
            $callableXML->setAttribute('name', $callable::class);
            return $dom;
        }
        throw new \InvalidArgumentException('Callable is not describable.');
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Bundle\FrameworkBundle\Console\Descriptor;

use _ContaoManager\Symfony\Component\Config\Resource\ClassExistenceResource;
use _ContaoManager\Symfony\Component\Console\Descriptor\DescriptorInterface;
use _ContaoManager\Symfony\Component\Console\Output\OutputInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Alias;
use _ContaoManager\Symfony\Component\DependencyInjection\Compiler\AnalyzeServiceReferencesPass;
use _ContaoManager\Symfony\Component\DependencyInjection\Compiler\ServiceReferenceGraphEdge;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerBuilder;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Definition;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
use _ContaoManager\Symfony\Component\DependencyInjection\ParameterBag\ParameterBag;
use _ContaoManager\Symfony\Component\EventDispatcher\EventDispatcherInterface;
use _ContaoManager\Symfony\Component\Routing\Route;
use _ContaoManager\Symfony\Component\Routing\RouteCollection;
/**
 * @author Jean-François Simon <jeanfrancois.simon@sensiolabs.com>
 *
 * @internal
 */
abstract class Descriptor implements DescriptorInterface
{
    protected OutputInterface $output;
    public function describe(OutputInterface $output, mixed $object, array $options = []): void
    {
        $this->output = $output;
        if ($object instanceof ContainerBuilder) {
            (new AnalyzeServiceReferencesPass(\false, \false))->process($object);
        }
        $deprecatedParameters = [];
        if ($object instanceof ContainerBuilder && isset($options['parameter']) && ($parameterBag = $object->getParameterBag()) instanceof ParameterBag) {
            $deprecatedParameters = $parameterBag->allDeprecated();
        }
        match (\true) {
            $object instanceof RouteCollection => $this->describeRouteCollection($object, $options),
            $object instanceof Route => $this->describeRoute($object, $options),
            $object instanceof ParameterBag => $this->describeContainerParameters($object, $options),
            $object instanceof ContainerBuilder && !empty($options['env-vars']) => $this->describeContainerEnvVars($this->getContainerEnvVars($object), $options),
            $object instanceof ContainerBuilder && isset($options['group_by']) && 'tags' === $options['group_by'] => $this->describeContainerTags($object, $options),
            $object instanceof ContainerBuilder && isset($options['id']) => $this->describeContainerService($this->resolveServiceDefinition($object, $options['id']), $options, $object),
            $object instanceof ContainerBuilder && isset($options['parameter']) => $this->describeContainerParameter($object->resolveEnvPlaceholders($object->getParameter($options['parameter'])), $deprecatedParameters[$options['parameter']] ?? null, $options),
            $object instanceof ContainerBuilder && isset($options['deprecations']) => $this->describeContainerDeprecations($object, $options),
            $object instanceof ContainerBuilder => $this->describeContainerServices($object, $options),
            $object instanceof Definition => $this->describeContainerDefinition($object, $options),
            $object instanceof Alias => $this->describeContainerAlias($object, $options),
            $object instanceof EventDispatcherInterface => $this->describeEventDispatcherListeners($object, $options),
            \is_callable($object) => $this->describeCallable($object, $options),
            default => throw new \InvalidArgumentException(\sprintf('Object of type "%s" is not describable.', get_debug_type($object))),
        };
        if ($object instanceof ContainerBuilder) {
            $object->getCompiler()->getServiceReferenceGraph()->clear();
        }
    }
    protected function getOutput(): OutputInterface
    {
        return $this->output;
    }
    protected function write(string $content, bool $decorated = \false): void
    {
        $this->output->write($content, \false, $decorated ? OutputInterface::OUTPUT_NORMAL : OutputInterface::OUTPUT_RAW);
    }
    abstract protected function describeRouteCollection(RouteCollection $routes, array $options = []): void;
    abstract protected function describeRoute(Route $route, array $options = []): void;
    abstract protected function describeContainerParameters(ParameterBag $parameters, array $options = []): void;
    abstract protected function describeContainerTags(ContainerBuilder $container, array $options = []): void;
    /**
     * Describes a container service by its name.
     *
     * Common options are:
     * * name: name of described service
     *
     * @param Definition|Alias|object $service
     */
    abstract protected function describeContainerService(object $service, array $options = [], ?ContainerBuilder $container = null): void;
    /**
     * Describes container services.
     *
     * Common options are:
     * * tag: filters described services by given tag
     */
    abstract protected function describeContainerServices(ContainerBuilder $container, array $options = []): void;
    abstract protected function describeContainerDeprecations(ContainerBuilder $container, array $options = []): void;
    abstract protected function describeContainerDefinition(Definition $definition, array $options = [], ?ContainerBuilder $container = null): void;
    abstract protected function describeContainerAlias(Alias $alias, array $options = [], ?ContainerBuilder $container = null): void;
    abstract protected function describeContainerParameter(mixed $parameter, ?array $deprecation, array $options = []): void;
    abstract protected function describeContainerEnvVars(array $envs, array $options = []): void;
    /**
     * Describes event dispatcher listeners.
     *
     * Common options are:
     * * name: name of listened event
     */
    abstract protected function describeEventDispatcherListeners(EventDispatcherInterface $eventDispatcher, array $options = []): void;
    abstract protected function describeCallable(mixed $callable, array $options = []): void;
    protected function formatValue(mixed $value): string
    {
        if ($value instanceof \UnitEnum) {
            return ltrim(var_export($value, \true), '\\');
        }
        if (\is_object($value)) {
            return \sprintf('object(%s)', $value::class);
        }
        if (\is_string($value)) {
            return $value;
        }
        return preg_replace("/\n\\s*/s", '', var_export($value, \true));
    }
    protected function formatParameter(mixed $value): string
    {
        if ($value instanceof \UnitEnum) {
            return ltrim(var_export($value, \true), '\\');
        }
        // Recursively search for enum values, so we can replace it
        // before json_encode (which will not display anything for \UnitEnum otherwise)
        if (\is_array($value)) {
            array_walk_recursive($value, static function (&$value) {
                if ($value instanceof \UnitEnum) {
                    $value = ltrim(var_export($value, \true), '\\');
                }
            });
        }
        if (\is_bool($value) || \is_array($value) || null === $value) {
            $jsonString = json_encode($value);
            if (preg_match('/^(.{60})./us', $jsonString, $matches)) {
                return $matches[1] . '...';
            }
            return $jsonString;
        }
        return (string) $value;
    }
    protected function resolveServiceDefinition(ContainerBuilder $container, string $serviceId): mixed
    {
        if ($container->hasDefinition($serviceId)) {
            return $container->getDefinition($serviceId);
        }
        // Some service IDs don't have a Definition, they're aliases
        if ($container->hasAlias($serviceId)) {
            return $container->getAlias($serviceId);
        }
        if ('service_container' === $serviceId) {
            return (new Definition(ContainerInterface::class))->setPublic(\true)->setSynthetic(\true);
        }
        // the service has been injected in some special way, just return the service
        return $container->get($serviceId);
    }
    protected function findDefinitionsByTag(ContainerBuilder $container, bool $showHidden): array
    {
        $definitions = [];
        $tags = $container->findTags();
        asort($tags);
        foreach ($tags as $tag) {
            foreach ($container->findTaggedServiceIds($tag) as $serviceId => $attributes) {
                $definition = $this->resolveServiceDefinition($container, $serviceId);
                if ($showHidden xor '.' === ($serviceId[0] ?? null)) {
                    continue;
                }
                if (!isset($definitions[$tag])) {
                    $definitions[$tag] = [];
                }
                $definitions[$tag][$serviceId] = $definition;
            }
        }
        return $definitions;
    }
    protected function sortParameters(ParameterBag $parameters): array
    {
        $parameters = $parameters->all();
        ksort($parameters);
        return $parameters;
    }
    protected function sortServiceIds(array $serviceIds): array
    {
        asort($serviceIds);
        return $serviceIds;
    }
    protected function sortTaggedServicesByPriority(array $services): array
    {
        $maxPriority = [];
        foreach ($services as $service => $tags) {
            $maxPriority[$service] = \PHP_INT_MIN;
            foreach ($tags as $tag) {
                $currentPriority = $tag['priority'] ?? 0;
                if ($maxPriority[$service] < $currentPriority) {
                    $maxPriority[$service] = $currentPriority;
                }
            }
        }
        uasort($maxPriority, fn($a, $b) => $b <=> $a);
        return array_keys($maxPriority);
    }
    protected function sortTagsByPriority(array $tags): array
    {
        $sortedTags = [];
        foreach ($tags as $tagName => $tag) {
            $sortedTags[$tagName] = $this->sortByPriority($tag);
        }
        return $sortedTags;
    }
    protected function sortByPriority(array $tag): array
    {
        usort($tag, fn($a, $b) => ($b['priority'] ?? 0) <=> ($a['priority'] ?? 0));
        return $tag;
    }
    /**
     * @return array<string, string[]>
     */
    protected function getReverseAliases(RouteCollection $routes): array
    {
        $reverseAliases = [];
        foreach ($routes->getAliases() as $name => $alias) {
            $reverseAliases[$alias->getId()][] = $name;
        }
        return $reverseAliases;
    }
    public static function getClassDescription(string $class, ?string &$resolvedClass = null): string
    {
        $resolvedClass = $class;
        try {
            $resource = new ClassExistenceResource($class, \false);
            // isFresh() will explode ONLY if a parent class/trait does not exist
            $resource->isFresh(0);
            $r = new \ReflectionClass($class);
            $resolvedClass = $r->name;
            if ($docComment = $r->getDocComment()) {
                $docComment = preg_split('#\n\s*\*\s*[\n@]#', substr($docComment, 3, -2), 2)[0];
                return trim(preg_replace('#\s*\n\s*\*\s*#', ' ', $docComment));
            }
        } catch (\ReflectionException) {
        }
        return '';
    }
    private function getContainerEnvVars(ContainerBuilder $container): array
    {
        if (!$container->hasParameter('debug.container.dump')) {
            return [];
        }
        if (!$container->getParameter('debug.container.dump') || !is_file($container->getParameter('debug.container.dump'))) {
            return [];
        }
        $file = file_get_contents($container->getParameter('debug.container.dump'));
        preg_match_all('{%env\(((?:\w++:)*+\w++)\)%}', $file, $envVars);
        $envVars = array_unique($envVars[1]);
        $bag = $container->getParameterBag();
        $getDefaultParameter = fn(string $name) => parent::get($name);
        $getDefaultParameter = $getDefaultParameter->bindTo($bag, $bag::class);
        $getEnvReflection = new \ReflectionMethod($container, 'getEnv');
        $envs = [];
        foreach ($envVars as $env) {
            $processor = 'string';
            if (\false !== $i = strrpos($name = $env, ':')) {
                $name = substr($env, $i + 1);
                $processor = substr($env, 0, $i);
            }
            $defaultValue = ($hasDefault = $container->hasParameter("env({$name})")) ? $getDefaultParameter("env({$name})") : null;
            if (\false === $runtimeValue = $_ENV[$name] ?? $_SERVER[$name] ?? getenv($name)) {
                $runtimeValue = null;
            }
            $processedValue = ($hasRuntime = null !== $runtimeValue) || $hasDefault ? $getEnvReflection->invoke($container, $env) : null;
            $envs["{$name}{$processor}"] = ['name' => $name, 'processor' => $processor, 'default_available' => $hasDefault, 'default_value' => $defaultValue, 'runtime_available' => $hasRuntime, 'runtime_value' => $runtimeValue, 'processed_value' => $processedValue];
        }
        ksort($envs);
        return array_values($envs);
    }
    protected function getServiceEdges(ContainerBuilder $container, string $serviceId): array
    {
        try {
            return array_values(array_unique(array_map(fn(ServiceReferenceGraphEdge $edge) => $edge->getSourceNode()->getId(), $container->getCompiler()->getServiceReferenceGraph()->getNode($serviceId)->getInEdges())));
        } catch (InvalidArgumentException $exception) {
            return [];
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Bundle\FrameworkBundle\Console\Descriptor;

use _ContaoManager\Symfony\Component\Console\Exception\LogicException;
use _ContaoManager\Symfony\Component\Console\Exception\RuntimeException;
use _ContaoManager\Symfony\Component\DependencyInjection\Alias;
use _ContaoManager\Symfony\Component\DependencyInjection\Argument\AbstractArgument;
use _ContaoManager\Symfony\Component\DependencyInjection\Argument\ArgumentInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Argument\ServiceClosureArgument;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerBuilder;
use _ContaoManager\Symfony\Component\DependencyInjection\Definition;
use _ContaoManager\Symfony\Component\DependencyInjection\ParameterBag\ParameterBag;
use _ContaoManager\Symfony\Component\DependencyInjection\Reference;
use _ContaoManager\Symfony\Component\EventDispatcher\EventDispatcherInterface;
use _ContaoManager\Symfony\Component\Routing\Route;
use _ContaoManager\Symfony\Component\Routing\RouteCollection;
/**
 * @author Jean-François Simon <jeanfrancois.simon@sensiolabs.com>
 *
 * @internal
 */
class JsonDescriptor extends Descriptor
{
    protected function describeRouteCollection(RouteCollection $routes, array $options = []): void
    {
        $data = [];
        foreach ($routes->all() as $name => $route) {
            $data[$name] = $this->getRouteData($route);
            if (($showAliases ??= $options['show_aliases'] ?? \false) && $aliases = ($reverseAliases ??= $this->getReverseAliases($routes))[$name] ?? []) {
                $data[$name]['aliases'] = $aliases;
            }
        }
        $this->writeData($data, $options);
    }
    protected function describeRoute(Route $route, array $options = []): void
    {
        $this->writeData($this->getRouteData($route), $options);
    }
    protected function describeContainerParameters(ParameterBag $parameters, array $options = []): void
    {
        $this->writeData($this->sortParameters($parameters), $options);
    }
    protected function describeContainerTags(ContainerBuilder $container, array $options = []): void
    {
        $showHidden = isset($options['show_hidden']) && $options['show_hidden'];
        $data = [];
        foreach ($this->findDefinitionsByTag($container, $showHidden) as $tag => $definitions) {
            $data[$tag] = [];
            foreach ($definitions as $definition) {
                $data[$tag][] = $this->getContainerDefinitionData($definition, \true, \false, $container, $options['id'] ?? null);
            }
        }
        $this->writeData($data, $options);
    }
    protected function describeContainerService(object $service, array $options = [], ?ContainerBuilder $container = null): void
    {
        if (!isset($options['id'])) {
            throw new \InvalidArgumentException('An "id" option must be provided.');
        }
        if ($service instanceof Alias) {
            $this->describeContainerAlias($service, $options, $container);
        } elseif ($service instanceof Definition) {
            $this->writeData($this->getContainerDefinitionData($service, isset($options['omit_tags']) && $options['omit_tags'], isset($options['show_arguments']) && $options['show_arguments'], $container, $options['id']), $options);
        } else {
            $this->writeData($service::class, $options);
        }
    }
    protected function describeContainerServices(ContainerBuilder $container, array $options = []): void
    {
        $serviceIds = isset($options['tag']) && $options['tag'] ? $this->sortTaggedServicesByPriority($container->findTaggedServiceIds($options['tag'])) : $this->sortServiceIds($container->getServiceIds());
        $showHidden = isset($options['show_hidden']) && $options['show_hidden'];
        $omitTags = isset($options['omit_tags']) && $options['omit_tags'];
        $showArguments = isset($options['show_arguments']) && $options['show_arguments'];
        $data = ['definitions' => [], 'aliases' => [], 'services' => []];
        if (isset($options['filter'])) {
            $serviceIds = array_filter($serviceIds, $options['filter']);
        }
        foreach ($serviceIds as $serviceId) {
            $service = $this->resolveServiceDefinition($container, $serviceId);
            if ($showHidden xor '.' === ($serviceId[0] ?? null)) {
                continue;
            }
            if ($service instanceof Alias) {
                $data['aliases'][$serviceId] = $this->getContainerAliasData($service);
            } elseif ($service instanceof Definition) {
                if ($service->hasTag('container.excluded')) {
                    continue;
                }
                $data['definitions'][$serviceId] = $this->getContainerDefinitionData($service, $omitTags, $showArguments, $container, $serviceId);
            } else {
                $data['services'][$serviceId] = $service::class;
            }
        }
        $this->writeData($data, $options);
    }
    protected function describeContainerDefinition(Definition $definition, array $options = [], ?ContainerBuilder $container = null): void
    {
        $this->writeData($this->getContainerDefinitionData($definition, isset($options['omit_tags']) && $options['omit_tags'], isset($options['show_arguments']) && $options['show_arguments'], $container, $options['id'] ?? null), $options);
    }
    protected function describeContainerAlias(Alias $alias, array $options = [], ?ContainerBuilder $container = null): void
    {
        if (!$container) {
            $this->writeData($this->getContainerAliasData($alias), $options);
            return;
        }
        $this->writeData([$this->getContainerAliasData($alias), $this->getContainerDefinitionData($container->getDefinition((string) $alias), isset($options['omit_tags']) && $options['omit_tags'], isset($options['show_arguments']) && $options['show_arguments'], $container, (string) $alias)], array_merge($options, ['id' => (string) $alias]));
    }
    protected function describeEventDispatcherListeners(EventDispatcherInterface $eventDispatcher, array $options = []): void
    {
        $this->writeData($this->getEventDispatcherListenersData($eventDispatcher, $options), $options);
    }
    protected function describeCallable(mixed $callable, array $options = []): void
    {
        $this->writeData($this->getCallableData($callable), $options);
    }
    protected function describeContainerParameter(mixed $parameter, ?array $deprecation, array $options = []): void
    {
        $key = $options['parameter'] ?? '';
        $data = [$key => $parameter];
        if ($deprecation) {
            $data['_deprecation'] = \sprintf('Since %s %s: %s', $deprecation[0], $deprecation[1], \sprintf(...\array_slice($deprecation, 2)));
        }
        $this->writeData($data, $options);
    }
    protected function describeContainerEnvVars(array $envs, array $options = []): void
    {
        throw new LogicException('Using the JSON format to debug environment variables is not supported.');
    }
    protected function describeContainerDeprecations(ContainerBuilder $container, array $options = []): void
    {
        $containerDeprecationFilePath = \sprintf('%s/%sDeprecations.log', $container->getParameter('kernel.build_dir'), $container->getParameter('kernel.container_class'));
        if (!file_exists($containerDeprecationFilePath)) {
            throw new RuntimeException('The deprecation file does not exist, please try warming the cache first.');
        }
        $logs = unserialize(file_get_contents($containerDeprecationFilePath));
        $formattedLogs = [];
        $remainingCount = 0;
        foreach ($logs as $log) {
            $formattedLogs[] = ['message' => $log['message'], 'file' => $log['file'], 'line' => $log['line'], 'count' => $log['count']];
            $remainingCount += $log['count'];
        }
        $this->writeData(['remainingCount' => $remainingCount, 'deprecations' => $formattedLogs], $options);
    }
    private function writeData(array $data, array $options): void
    {
        $flags = $options['json_encoding'] ?? 0;
        // Recursively search for enum values, so we can replace it
        // before json_encode (which will not display anything for \UnitEnum otherwise)
        array_walk_recursive($data, static function (&$value) {
            if ($value instanceof \UnitEnum) {
                $value = ltrim(var_export($value, \true), '\\');
            }
        });
        $this->write(json_encode($data, $flags | \JSON_PRETTY_PRINT) . "\n");
    }
    protected function getRouteData(Route $route): array
    {
        $data = ['path' => $route->getPath(), 'pathRegex' => $route->compile()->getRegex(), 'host' => '' !== $route->getHost() ? $route->getHost() : 'ANY', 'hostRegex' => '' !== $route->getHost() ? $route->compile()->getHostRegex() : '', 'scheme' => $route->getSchemes() ? implode('|', $route->getSchemes()) : 'ANY', 'method' => $route->getMethods() ? implode('|', $route->getMethods()) : 'ANY', 'class' => $route::class, 'defaults' => $route->getDefaults(), 'requirements' => $route->getRequirements() ?: 'NO CUSTOM', 'options' => $route->getOptions()];
        if ('' !== $route->getCondition()) {
            $data['condition'] = $route->getCondition();
        }
        return $data;
    }
    protected function sortParameters(ParameterBag $parameters): array
    {
        $sortedParameters = parent::sortParameters($parameters);
        if ($deprecated = $parameters->allDeprecated()) {
            $deprecations = [];
            foreach ($deprecated as $parameter => $deprecation) {
                $deprecations[$parameter] = \sprintf('Since %s %s: %s', $deprecation[0], $deprecation[1], \sprintf(...\array_slice($deprecation, 2)));
            }
            $sortedParameters['_deprecations'] = $deprecations;
        }
        return $sortedParameters;
    }
    private function getContainerDefinitionData(Definition $definition, bool $omitTags = \false, bool $showArguments = \false, ?ContainerBuilder $container = null, ?string $id = null): array
    {
        $data = ['class' => (string) $definition->getClass(), 'public' => $definition->isPublic() && !$definition->isPrivate(), 'synthetic' => $definition->isSynthetic(), 'lazy' => $definition->isLazy(), 'shared' => $definition->isShared(), 'abstract' => $definition->isAbstract(), 'autowire' => $definition->isAutowired(), 'autoconfigure' => $definition->isAutoconfigured()];
        if ($definition->isDeprecated()) {
            $data['deprecated'] = \true;
            $data['deprecation_message'] = $definition->getDeprecation($id)['message'];
        } else {
            $data['deprecated'] = \false;
        }
        if ('' !== $classDescription = $this->getClassDescription((string) $definition->getClass())) {
            $data['description'] = $classDescription;
        }
        if ($showArguments) {
            $data['arguments'] = $this->describeValue($definition->getArguments(), $omitTags, $showArguments, $container, $id);
        }
        $data['file'] = $definition->getFile();
        if ($factory = $definition->getFactory()) {
            if (\is_array($factory)) {
                if ($factory[0] instanceof Reference) {
                    $data['factory_service'] = (string) $factory[0];
                } elseif ($factory[0] instanceof Definition) {
                    $data['factory_service'] = \sprintf('inline factory service (%s)', $factory[0]->getClass() ?? 'class not configured');
                } else {
                    $data['factory_class'] = $factory[0];
                }
                $data['factory_method'] = $factory[1];
            } else {
                $data['factory_function'] = $factory;
            }
        }
        $calls = $definition->getMethodCalls();
        if (\count($calls) > 0) {
            $data['calls'] = [];
            foreach ($calls as $callData) {
                $data['calls'][] = $callData[0];
            }
        }
        if (!$omitTags) {
            $data['tags'] = [];
            foreach ($this->sortTagsByPriority($definition->getTags()) as $tagName => $tagData) {
                foreach ($tagData as $parameters) {
                    $data['tags'][] = ['name' => $tagName, 'parameters' => $parameters];
                }
            }
        }
        $data['usages'] = null !== $container && null !== $id ? $this->getServiceEdges($container, $id) : [];
        return $data;
    }
    private function getContainerAliasData(Alias $alias): array
    {
        return ['service' => (string) $alias, 'public' => $alias->isPublic() && !$alias->isPrivate()];
    }
    private function getEventDispatcherListenersData(EventDispatcherInterface $eventDispatcher, array $options): array
    {
        $data = [];
        $event = \array_key_exists('event', $options) ? $options['event'] : null;
        if (null !== $event) {
            foreach ($eventDispatcher->getListeners($event) as $listener) {
                $l = $this->getCallableData($listener);
                $l['priority'] = $eventDispatcher->getListenerPriority($event, $listener);
                $data[] = $l;
            }
        } else {
            $registeredListeners = \array_key_exists('events', $options) ? array_combine($options['events'], array_map(fn($event) => $eventDispatcher->getListeners($event), $options['events'])) : $eventDispatcher->getListeners();
            ksort($registeredListeners);
            foreach ($registeredListeners as $eventListened => $eventListeners) {
                foreach ($eventListeners as $eventListener) {
                    $l = $this->getCallableData($eventListener);
                    $l['priority'] = $eventDispatcher->getListenerPriority($eventListened, $eventListener);
                    $data[$eventListened][] = $l;
                }
            }
        }
        return $data;
    }
    private function getCallableData(mixed $callable): array
    {
        $data = [];
        if (\is_array($callable)) {
            $data['type'] = 'function';
            if (\is_object($callable[0])) {
                $data['name'] = $callable[1];
                $data['class'] = $callable[0]::class;
            } else if (!str_starts_with($callable[1], 'parent::')) {
                $data['name'] = $callable[1];
                $data['class'] = $callable[0];
                $data['static'] = \true;
            } else {
                $data['name'] = substr($callable[1], 8);
                $data['class'] = $callable[0];
                $data['static'] = \true;
                $data['parent'] = \true;
            }
            return $data;
        }
        if (\is_string($callable)) {
            $data['type'] = 'function';
            if (!str_contains($callable, '::')) {
                $data['name'] = $callable;
            } else {
                $callableParts = explode('::', $callable);
                $data['name'] = $callableParts[1];
                $data['class'] = $callableParts[0];
                $data['static'] = \true;
            }
            return $data;
        }
        if ($callable instanceof \Closure) {
            $data['type'] = 'closure';
            $r = new \ReflectionFunction($callable);
            if (str_contains($r->name, '{closure')) {
                return $data;
            }
            $data['name'] = $r->name;
            if ($class = \PHP_VERSION_ID >= 80111 ? $r->getClosureCalledClass() : $r->getClosureScopeClass()) {
                $data['class'] = $class->name;
                if (!$r->getClosureThis()) {
                    $data['static'] = \true;
                }
            }
            return $data;
        }
        if (method_exists($callable, '__invoke')) {
            $data['type'] = 'object';
            $data['name'] = $callable::class;
            return $data;
        }
        throw new \InvalidArgumentException('Callable is not describable.');
    }
    private function describeValue($value, bool $omitTags, bool $showArguments, ?ContainerBuilder $container = null, ?string $id = null): mixed
    {
        if (\is_array($value)) {
            $data = [];
            foreach ($value as $k => $v) {
                $data[$k] = $this->describeValue($v, $omitTags, $showArguments, $container, $id);
            }
            return $data;
        }
        if ($value instanceof ServiceClosureArgument) {
            $value = $value->getValues()[0];
        }
        if ($value instanceof Reference) {
            return ['type' => 'service', 'id' => (string) $value];
        }
        if ($value instanceof AbstractArgument) {
            return ['type' => 'abstract', 'text' => $value->getText()];
        }
        if ($value instanceof ArgumentInterface) {
            return $this->describeValue($value->getValues(), $omitTags, $showArguments, $container, $id);
        }
        if ($value instanceof Definition) {
            return $this->getContainerDefinitionData($value, $omitTags, $showArguments, $container, $id);
        }
        return $value;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Bundle\FrameworkBundle\Console\Descriptor;

use _ContaoManager\Symfony\Component\Console\Exception\LogicException;
use _ContaoManager\Symfony\Component\Console\Exception\RuntimeException;
use _ContaoManager\Symfony\Component\DependencyInjection\Alias;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerBuilder;
use _ContaoManager\Symfony\Component\DependencyInjection\Definition;
use _ContaoManager\Symfony\Component\DependencyInjection\ParameterBag\ParameterBag;
use _ContaoManager\Symfony\Component\DependencyInjection\Reference;
use _ContaoManager\Symfony\Component\EventDispatcher\EventDispatcherInterface;
use _ContaoManager\Symfony\Component\Routing\Route;
use _ContaoManager\Symfony\Component\Routing\RouteCollection;
/**
 * @author Jean-François Simon <jeanfrancois.simon@sensiolabs.com>
 *
 * @internal
 */
class MarkdownDescriptor extends Descriptor
{
    protected function describeRouteCollection(RouteCollection $routes, array $options = []): void
    {
        $first = \true;
        foreach ($routes->all() as $name => $route) {
            if ($first) {
                $first = \false;
            } else {
                $this->write("\n\n");
            }
            $this->describeRoute($route, ['name' => $name]);
            if (($showAliases ??= $options['show_aliases'] ?? \false) && $aliases = ($reverseAliases ??= $this->getReverseAliases($routes))[$name] ?? []) {
                $this->write(\sprintf("- Aliases: \n%s", implode("\n", array_map(static fn(string $alias): string => \sprintf('    - %s', $alias), $aliases))));
            }
        }
        $this->write("\n");
    }
    protected function describeRoute(Route $route, array $options = []): void
    {
        $output = '- Path: ' . $route->getPath() . "\n" . '- Path Regex: ' . $route->compile()->getRegex() . "\n" . '- Host: ' . ('' !== $route->getHost() ? $route->getHost() : 'ANY') . "\n" . '- Host Regex: ' . ('' !== $route->getHost() ? $route->compile()->getHostRegex() : '') . "\n" . '- Scheme: ' . ($route->getSchemes() ? implode('|', $route->getSchemes()) : 'ANY') . "\n" . '- Method: ' . ($route->getMethods() ? implode('|', $route->getMethods()) : 'ANY') . "\n" . '- Class: ' . $route::class . "\n" . '- Defaults: ' . $this->formatRouterConfig($route->getDefaults()) . "\n" . '- Requirements: ' . ($route->getRequirements() ? $this->formatRouterConfig($route->getRequirements()) : 'NO CUSTOM') . "\n" . '- Options: ' . $this->formatRouterConfig($route->getOptions());
        if ('' !== $route->getCondition()) {
            $output .= "\n" . '- Condition: ' . $route->getCondition();
        }
        $this->write(isset($options['name']) ? $options['name'] . "\n" . str_repeat('-', \strlen($options['name'])) . "\n\n" . $output : $output);
        $this->write("\n");
    }
    protected function describeContainerParameters(ParameterBag $parameters, array $options = []): void
    {
        $deprecatedParameters = $parameters->allDeprecated();
        $this->write("Container parameters\n====================\n");
        foreach ($this->sortParameters($parameters) as $key => $value) {
            $this->write(\sprintf("\n- `%s`: `%s`%s", $key, $this->formatParameter($value), isset($deprecatedParameters[$key]) ? \sprintf(' *Since %s %s: %s*', $deprecatedParameters[$key][0], $deprecatedParameters[$key][1], \sprintf(...\array_slice($deprecatedParameters[$key], 2))) : ''));
        }
    }
    protected function describeContainerTags(ContainerBuilder $container, array $options = []): void
    {
        $showHidden = isset($options['show_hidden']) && $options['show_hidden'];
        $this->write("Container tags\n==============");
        foreach ($this->findDefinitionsByTag($container, $showHidden) as $tag => $definitions) {
            $this->write("\n\n" . $tag . "\n" . str_repeat('-', \strlen($tag)));
            foreach ($definitions as $serviceId => $definition) {
                $this->write("\n\n");
                $this->describeContainerDefinition($definition, ['omit_tags' => \true, 'id' => $serviceId], $container);
            }
        }
    }
    protected function describeContainerService(object $service, array $options = [], ?ContainerBuilder $container = null): void
    {
        if (!isset($options['id'])) {
            throw new \InvalidArgumentException('An "id" option must be provided.');
        }
        $childOptions = array_merge($options, ['id' => $options['id'], 'as_array' => \true]);
        if ($service instanceof Alias) {
            $this->describeContainerAlias($service, $childOptions, $container);
        } elseif ($service instanceof Definition) {
            $this->describeContainerDefinition($service, $childOptions, $container);
        } else {
            $this->write(\sprintf('**`%s`:** `%s`', $options['id'], $service::class));
        }
    }
    protected function describeContainerDeprecations(ContainerBuilder $container, array $options = []): void
    {
        $containerDeprecationFilePath = \sprintf('%s/%sDeprecations.log', $container->getParameter('kernel.build_dir'), $container->getParameter('kernel.container_class'));
        if (!file_exists($containerDeprecationFilePath)) {
            throw new RuntimeException('The deprecation file does not exist, please try warming the cache first.');
        }
        $logs = unserialize(file_get_contents($containerDeprecationFilePath));
        if (0 === \count($logs)) {
            $this->write("## There are no deprecations in the logs!\n");
            return;
        }
        $formattedLogs = [];
        $remainingCount = 0;
        foreach ($logs as $log) {
            $formattedLogs[] = \sprintf("- %sx: \"%s\" in %s:%s\n", $log['count'], $log['message'], $log['file'], $log['line']);
            $remainingCount += $log['count'];
        }
        $this->write(\sprintf("## Remaining deprecations (%s)\n\n", $remainingCount));
        foreach ($formattedLogs as $formattedLog) {
            $this->write($formattedLog);
        }
    }
    protected function describeContainerServices(ContainerBuilder $container, array $options = []): void
    {
        $showHidden = isset($options['show_hidden']) && $options['show_hidden'];
        $title = $showHidden ? 'Hidden services' : 'Services';
        if (isset($options['tag'])) {
            $title .= ' with tag `' . $options['tag'] . '`';
        }
        $this->write($title . "\n" . str_repeat('=', \strlen($title)));
        $serviceIds = isset($options['tag']) && $options['tag'] ? $this->sortTaggedServicesByPriority($container->findTaggedServiceIds($options['tag'])) : $this->sortServiceIds($container->getServiceIds());
        $showArguments = isset($options['show_arguments']) && $options['show_arguments'];
        $services = ['definitions' => [], 'aliases' => [], 'services' => []];
        if (isset($options['filter'])) {
            $serviceIds = array_filter($serviceIds, $options['filter']);
        }
        foreach ($serviceIds as $serviceId) {
            $service = $this->resolveServiceDefinition($container, $serviceId);
            if ($showHidden xor '.' === ($serviceId[0] ?? null)) {
                continue;
            }
            if ($service instanceof Alias) {
                $services['aliases'][$serviceId] = $service;
            } elseif ($service instanceof Definition) {
                if ($service->hasTag('container.excluded')) {
                    continue;
                }
                $services['definitions'][$serviceId] = $service;
            } else {
                $services['services'][$serviceId] = $service;
            }
        }
        if (!empty($services['definitions'])) {
            $this->write("\n\nDefinitions\n-----------\n");
            foreach ($services['definitions'] as $id => $service) {
                $this->write("\n");
                $this->describeContainerDefinition($service, ['id' => $id, 'show_arguments' => $showArguments], $container);
            }
        }
        if (!empty($services['aliases'])) {
            $this->write("\n\nAliases\n-------\n");
            foreach ($services['aliases'] as $id => $service) {
                $this->write("\n");
                $this->describeContainerAlias($service, ['id' => $id]);
            }
        }
        if (!empty($services['services'])) {
            $this->write("\n\nServices\n--------\n");
            foreach ($services['services'] as $id => $service) {
                $this->write("\n");
                $this->write(\sprintf('- `%s`: `%s`', $id, $service::class));
            }
        }
    }
    protected function describeContainerDefinition(Definition $definition, array $options = [], ?ContainerBuilder $container = null): void
    {
        $output = '';
        if ('' !== $classDescription = $this->getClassDescription((string) $definition->getClass())) {
            $output .= '- Description: `' . $classDescription . '`' . "\n";
        }
        $output .= '- Class: `' . $definition->getClass() . '`' . "\n" . '- Public: ' . ($definition->isPublic() && !$definition->isPrivate() ? 'yes' : 'no') . "\n" . '- Synthetic: ' . ($definition->isSynthetic() ? 'yes' : 'no') . "\n" . '- Lazy: ' . ($definition->isLazy() ? 'yes' : 'no') . "\n" . '- Shared: ' . ($definition->isShared() ? 'yes' : 'no') . "\n" . '- Abstract: ' . ($definition->isAbstract() ? 'yes' : 'no') . "\n" . '- Autowired: ' . ($definition->isAutowired() ? 'yes' : 'no') . "\n" . '- Autoconfigured: ' . ($definition->isAutoconfigured() ? 'yes' : 'no');
        if ($definition->isDeprecated()) {
            $output .= "\n" . '- Deprecated: yes';
            $output .= "\n" . '- Deprecation message: ' . $definition->getDeprecation($options['id'])['message'];
        } else {
            $output .= "\n" . '- Deprecated: no';
        }
        if (isset($options['show_arguments']) && $options['show_arguments']) {
            $output .= "\n" . '- Arguments: ' . ($definition->getArguments() ? 'yes' : 'no');
        }
        if ($definition->getFile()) {
            $output .= "\n" . '- File: `' . $definition->getFile() . '`';
        }
        if ($factory = $definition->getFactory()) {
            if (\is_array($factory)) {
                if ($factory[0] instanceof Reference) {
                    $output .= "\n" . '- Factory Service: `' . $factory[0] . '`';
                } elseif ($factory[0] instanceof Definition) {
                    $output .= "\n" . \sprintf('- Factory Service: inline factory service (%s)', $factory[0]->getClass() ? \sprintf('`%s`', $factory[0]->getClass()) : 'not configured');
                } else {
                    $output .= "\n" . '- Factory Class: `' . $factory[0] . '`';
                }
                $output .= "\n" . '- Factory Method: `' . $factory[1] . '`';
            } else {
                $output .= "\n" . '- Factory Function: `' . $factory . '`';
            }
        }
        $calls = $definition->getMethodCalls();
        foreach ($calls as $callData) {
            $output .= "\n" . '- Call: `' . $callData[0] . '`';
        }
        if (!(isset($options['omit_tags']) && $options['omit_tags'])) {
            foreach ($this->sortTagsByPriority($definition->getTags()) as $tagName => $tagData) {
                foreach ($tagData as $parameters) {
                    $output .= "\n" . '- Tag: `' . $tagName . '`';
                    foreach ($parameters as $name => $value) {
                        $output .= "\n" . '    - ' . ucfirst($name) . ': ' . (\is_array($value) ? $this->formatParameter($value) : $value);
                    }
                }
            }
        }
        $inEdges = null !== $container && isset($options['id']) ? $this->getServiceEdges($container, $options['id']) : [];
        $output .= "\n" . '- Usages: ' . ($inEdges ? implode(', ', $inEdges) : 'none');
        $this->write(isset($options['id']) ? \sprintf("### %s\n\n%s\n", $options['id'], $output) : $output);
    }
    protected function describeContainerAlias(Alias $alias, array $options = [], ?ContainerBuilder $container = null): void
    {
        $output = '- Service: `' . $alias . '`' . "\n" . '- Public: ' . ($alias->isPublic() && !$alias->isPrivate() ? 'yes' : 'no');
        if (!isset($options['id'])) {
            $this->write($output);
            return;
        }
        $this->write(\sprintf("### %s\n\n%s\n", $options['id'], $output));
        if (!$container) {
            return;
        }
        $this->write("\n");
        $this->describeContainerDefinition($container->getDefinition((string) $alias), array_merge($options, ['id' => (string) $alias]), $container);
    }
    protected function describeContainerParameter(mixed $parameter, ?array $deprecation, array $options = []): void
    {
        if (isset($options['parameter'])) {
            $this->write(\sprintf("%s\n%s\n\n%s%s", $options['parameter'], str_repeat('=', \strlen($options['parameter'])), $this->formatParameter($parameter), $deprecation ? \sprintf("\n\n*Since %s %s: %s*", $deprecation[0], $deprecation[1], \sprintf(...\array_slice($deprecation, 2))) : ''));
        } else {
            $this->write($parameter);
        }
    }
    protected function describeContainerEnvVars(array $envs, array $options = []): void
    {
        throw new LogicException('Using the markdown format to debug environment variables is not supported.');
    }
    protected function describeEventDispatcherListeners(EventDispatcherInterface $eventDispatcher, array $options = []): void
    {
        $event = $options['event'] ?? null;
        $dispatcherServiceName = $options['dispatcher_service_name'] ?? null;
        $title = 'Registered listeners';
        if (null !== $dispatcherServiceName) {
            $title .= \sprintf(' of event dispatcher "%s"', $dispatcherServiceName);
        }
        if (null !== $event) {
            $title .= \sprintf(' for event `%s` ordered by descending priority', $event);
            $registeredListeners = $eventDispatcher->getListeners($event);
        } else {
            // Try to see if "events" exists
            $registeredListeners = \array_key_exists('events', $options) ? array_combine($options['events'], array_map(fn($event) => $eventDispatcher->getListeners($event), $options['events'])) : $eventDispatcher->getListeners();
        }
        $this->write(\sprintf('# %s', $title) . "\n");
        if (null !== $event) {
            foreach ($registeredListeners as $order => $listener) {
                $this->write("\n" . \sprintf('## Listener %d', $order + 1) . "\n");
                $this->describeCallable($listener);
                $this->write(\sprintf('- Priority: `%d`', $eventDispatcher->getListenerPriority($event, $listener)) . "\n");
            }
        } else {
            ksort($registeredListeners);
            foreach ($registeredListeners as $eventListened => $eventListeners) {
                $this->write("\n" . \sprintf('## %s', $eventListened) . "\n");
                foreach ($eventListeners as $order => $eventListener) {
                    $this->write("\n" . \sprintf('### Listener %d', $order + 1) . "\n");
                    $this->describeCallable($eventListener);
                    $this->write(\sprintf('- Priority: `%d`', $eventDispatcher->getListenerPriority($eventListened, $eventListener)) . "\n");
                }
            }
        }
    }
    protected function describeCallable(mixed $callable, array $options = []): void
    {
        $string = '';
        if (\is_array($callable)) {
            $string .= "\n- Type: `function`";
            if (\is_object($callable[0])) {
                $string .= "\n" . \sprintf('- Name: `%s`', $callable[1]);
                $string .= "\n" . \sprintf('- Class: `%s`', $callable[0]::class);
            } else if (!str_starts_with($callable[1], 'parent::')) {
                $string .= "\n" . \sprintf('- Name: `%s`', $callable[1]);
                $string .= "\n" . \sprintf('- Class: `%s`', $callable[0]);
                $string .= "\n- Static: yes";
            } else {
                $string .= "\n" . \sprintf('- Name: `%s`', substr($callable[1], 8));
                $string .= "\n" . \sprintf('- Class: `%s`', $callable[0]);
                $string .= "\n- Static: yes";
                $string .= "\n- Parent: yes";
            }
            $this->write($string . "\n");
            return;
        }
        if (\is_string($callable)) {
            $string .= "\n- Type: `function`";
            if (!str_contains($callable, '::')) {
                $string .= "\n" . \sprintf('- Name: `%s`', $callable);
            } else {
                $callableParts = explode('::', $callable);
                $string .= "\n" . \sprintf('- Name: `%s`', $callableParts[1]);
                $string .= "\n" . \sprintf('- Class: `%s`', $callableParts[0]);
                $string .= "\n- Static: yes";
            }
            $this->write($string . "\n");
            return;
        }
        if ($callable instanceof \Closure) {
            $string .= "\n- Type: `closure`";
            $r = new \ReflectionFunction($callable);
            if (str_contains($r->name, '{closure')) {
                $this->write($string . "\n");
                return;
            }
            $string .= "\n" . \sprintf('- Name: `%s`', $r->name);
            if ($class = \PHP_VERSION_ID >= 80111 ? $r->getClosureCalledClass() : $r->getClosureScopeClass()) {
                $string .= "\n" . \sprintf('- Class: `%s`', $class->name);
                if (!$r->getClosureThis()) {
                    $string .= "\n- Static: yes";
                }
            }
            $this->write($string . "\n");
            return;
        }
        if (method_exists($callable, '__invoke')) {
            $string .= "\n- Type: `object`";
            $string .= "\n" . \sprintf('- Name: `%s`', $callable::class);
            $this->write($string . "\n");
            return;
        }
        throw new \InvalidArgumentException('Callable is not describable.');
    }
    private function formatRouterConfig(array $array): string
    {
        if (!$array) {
            return 'NONE';
        }
        $string = '';
        ksort($array);
        foreach ($array as $name => $value) {
            $string .= "\n" . '    - `' . $name . '`: ' . $this->formatValue($value);
        }
        return $string;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Bundle\FrameworkBundle\Console\Helper;

use _ContaoManager\Symfony\Bundle\FrameworkBundle\Console\Descriptor\JsonDescriptor;
use _ContaoManager\Symfony\Bundle\FrameworkBundle\Console\Descriptor\MarkdownDescriptor;
use _ContaoManager\Symfony\Bundle\FrameworkBundle\Console\Descriptor\TextDescriptor;
use _ContaoManager\Symfony\Bundle\FrameworkBundle\Console\Descriptor\XmlDescriptor;
use _ContaoManager\Symfony\Component\Console\Helper\DescriptorHelper as BaseDescriptorHelper;
use _ContaoManager\Symfony\Component\ErrorHandler\ErrorRenderer\FileLinkFormatter;
/**
 * @author Jean-François Simon <jeanfrancois.simon@sensiolabs.com>
 *
 * @internal
 */
class DescriptorHelper extends BaseDescriptorHelper
{
    public function __construct(?FileLinkFormatter $fileLinkFormatter = null)
    {
        $this->register('txt', new TextDescriptor($fileLinkFormatter))->register('xml', new XmlDescriptor())->register('json', new JsonDescriptor())->register('md', new MarkdownDescriptor());
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Bundle\FrameworkBundle\EventListener;

use _ContaoManager\Symfony\Component\Console\ConsoleEvents;
use _ContaoManager\Symfony\Component\Console\Debug\CliRequest;
use _ContaoManager\Symfony\Component\Console\Event\ConsoleCommandEvent;
use _ContaoManager\Symfony\Component\Console\Event\ConsoleErrorEvent;
use _ContaoManager\Symfony\Component\Console\Event\ConsoleTerminateEvent;
use _ContaoManager\Symfony\Component\Console\Output\ConsoleOutputInterface;
use _ContaoManager\Symfony\Component\EventDispatcher\EventSubscriberInterface;
use _ContaoManager\Symfony\Component\HttpFoundation\Request;
use _ContaoManager\Symfony\Component\HttpFoundation\RequestStack;
use _ContaoManager\Symfony\Component\HttpKernel\Profiler\Profile;
use _ContaoManager\Symfony\Component\HttpKernel\Profiler\Profiler;
use _ContaoManager\Symfony\Component\Routing\Generator\UrlGeneratorInterface;
use _ContaoManager\Symfony\Component\Stopwatch\Stopwatch;
/**
 * @internal
 *
 * @author Jules Pietri <jules@heahprod.com>
 */
final class ConsoleProfilerListener implements EventSubscriberInterface
{
    private ?\Throwable $error = null;
    /** @var \SplObjectStorage<Request, Profile> */
    private \SplObjectStorage $profiles;
    /** @var \SplObjectStorage<Request, ?Request> */
    private \SplObjectStorage $parents;
    private bool $disabled = \false;
    public function __construct(private readonly Profiler $profiler, private readonly RequestStack $requestStack, private readonly Stopwatch $stopwatch, private readonly bool $cliMode, private readonly ?UrlGeneratorInterface $urlGenerator = null)
    {
        $this->profiles = new \SplObjectStorage();
        $this->parents = new \SplObjectStorage();
    }
    public static function getSubscribedEvents(): array
    {
        return [ConsoleEvents::COMMAND => ['initialize', 4096], ConsoleEvents::ERROR => ['catch', -2048], ConsoleEvents::TERMINATE => ['profile', -4096]];
    }
    public function initialize(ConsoleCommandEvent $event): void
    {
        if (!$this->cliMode) {
            return;
        }
        $input = $event->getInput();
        if (!$input->hasOption('profile') || !$input->getOption('profile')) {
            $this->disabled = \true;
            return;
        }
        $request = $this->requestStack->getCurrentRequest();
        if (!$request instanceof CliRequest || $request->command !== $event->getCommand()) {
            return;
        }
        $request->attributes->set('_stopwatch_token', substr(hash('sha256', uniqid(mt_rand(), \true)), 0, 6));
        $this->stopwatch->openSection();
    }
    public function catch(ConsoleErrorEvent $event): void
    {
        if (!$this->cliMode) {
            return;
        }
        $this->error = $event->getError();
    }
    public function profile(ConsoleTerminateEvent $event): void
    {
        $error = $this->error;
        $this->error = null;
        if (!$this->cliMode || $this->disabled) {
            $this->disabled = \false;
            return;
        }
        $request = $this->requestStack->getCurrentRequest();
        if (!$request instanceof CliRequest || $request->command !== $event->getCommand()) {
            return;
        }
        if (!$this->profiler->isEnabled()) {
            return;
        }
        if (null !== $sectionId = $request->attributes->get('_stopwatch_token')) {
            // we must close the section before saving the profile to allow late collect
            try {
                $this->stopwatch->stopSection($sectionId);
            } catch (\LogicException) {
                // noop
            }
        }
        $request->command->exitCode = $event->getExitCode();
        $request->command->interruptedBySignal = $event->getInterruptingSignal();
        $profile = $this->profiler->collect($request, $request->getResponse(), $error);
        $this->profiles[$request] = $profile;
        if ($this->parents[$request] = $this->requestStack->getParentRequest()) {
            // do not save on sub commands
            return;
        }
        // attach children to parents
        foreach ($this->profiles as $request) {
            if (null !== $parentRequest = $this->parents[$request]) {
                if (isset($this->profiles[$parentRequest])) {
                    $this->profiles[$parentRequest]->addChild($this->profiles[$request]);
                }
            }
        }
        $output = $event->getOutput();
        $output = $output instanceof ConsoleOutputInterface && $output->isVerbose() ? $output->getErrorOutput() : null;
        // save profiles
        foreach ($this->profiles as $r) {
            $p = $this->profiles[$r];
            $this->profiler->saveProfile($p);
            if ($this->urlGenerator && $output) {
                $token = $p->getToken();
                $output->writeln(\sprintf('See profile <href=%s>%s</>', $this->urlGenerator->generate('_profiler', ['token' => $token], UrlGeneratorInterface::ABSOLUTE_URL), $token));
            }
        }
        $this->profiles = new \SplObjectStorage();
        $this->parents = new \SplObjectStorage();
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Bundle\FrameworkBundle\EventListener;

use _ContaoManager\Symfony\Component\Console\ConsoleEvents;
use _ContaoManager\Symfony\Component\Console\Event\ConsoleErrorEvent;
use _ContaoManager\Symfony\Component\Console\Exception\CommandNotFoundException;
use _ContaoManager\Symfony\Component\EventDispatcher\EventSubscriberInterface;
/**
 * Suggests a package, that should be installed (via composer),
 * if the package is missing, and the input command namespace can be mapped to a Symfony bundle.
 *
 * @author Przemysław Bogusz <przemyslaw.bogusz@tubotax.pl>
 *
 * @internal
 */
final class SuggestMissingPackageSubscriber implements EventSubscriberInterface
{
    private const PACKAGES = ['doctrine' => ['fixtures' => ['DoctrineFixturesBundle', 'doctrine/doctrine-fixtures-bundle --dev'], 'mongodb' => ['DoctrineMongoDBBundle', 'doctrine/mongodb-odm-bundle'], '_default' => ['Doctrine ORM', 'symfony/orm-pack']], 'make' => ['_default' => ['MakerBundle', 'symfony/maker-bundle --dev']], 'server' => ['_default' => ['Debug Bundle', 'symfony/debug-bundle --dev']]];
    public function onConsoleError(ConsoleErrorEvent $event): void
    {
        if (!$event->getError() instanceof CommandNotFoundException) {
            return;
        }
        [$namespace, $command] = explode(':', $event->getInput()->getFirstArgument()) + [1 => ''];
        if (!isset(self::PACKAGES[$namespace])) {
            return;
        }
        if (isset(self::PACKAGES[$namespace][$command])) {
            $suggestion = self::PACKAGES[$namespace][$command];
            $exact = \true;
        } else {
            $suggestion = self::PACKAGES[$namespace]['_default'];
            $exact = \false;
        }
        $error = $event->getError();
        if ($error->getAlternatives() && !$exact) {
            return;
        }
        $message = \sprintf("%s\n\nYou may be looking for a command provided by the \"%s\" which is currently not installed. Try running \"composer require %s\".", $error->getMessage(), $suggestion[0], $suggestion[1]);
        $event->setError(new CommandNotFoundException($message));
    }
    public static function getSubscribedEvents(): array
    {
        return [ConsoleEvents::ERROR => ['onConsoleError', 0]];
    }
}
Copyright (c) 2004-2019 Fabien Potencier

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is furnished
to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
## Unreleased

## 3.11.2 (2026-04-02)

* Add missing target to named autowiring alias

## 3.11.1 (2025-12-09)

* Fix `rollbar` handler to use `RollbarLogger` with Monolog 2+
* Fix `monolog.processor` attributes to use consecutive keys

## 3.11.0 (2025-11-27)

* Reorganize files to match the "Reusable Bundles" structure
* Migrate services configuration to PHP
* Add `console.interactive_only` flag
* Add `slack.exclude_fields` and `slackwebhook.exclude_fields` configuration
* Add a processor to all loggers only when tags do not specify a channel or handler
* Deprecate abstract `monolog.activation_strategy.not_found` and `monolog.handler.fingers_crossed.error_level_activation_strategy` service definitions
* Drop support for PHP < 8.1
* Drop support for Symfony < 6.4
* Add TelegramBotHandler `topic` support
* Deprecate `sentry` and `raven` handler, use a `service` handler with [`sentry/sentry-symfony`](https://docs.sentry.io/platforms/php/guides/symfony/logs/) instead
* Add configuration for Gelf encoders
* Fix `host` configuration for `elastic_search` handler
* Add `hosts` configuration for `elastica` handler
* Add `enabled` option to `handlers` configuration
* Add `priority` field to `processor` tag
* Add `mongodb` handler and deprecate `mongo`
* Add `monolog.formatter.syslog` service definition to format RFC5424-compliant messages

## 3.10.0 (2023-11-06)

* Add configuration support for SamplingHandler

## 3.9.0 (2023-11-06)

* Add support for the `WithMonologChannel` attribute of Monolog 3.5.0 to autoconfigure the `monolog.logger` tag
* Add support for Symfony 7
* Remove support for Symfony 4
* Mark classes as internal when relevant
* Add support for env placeholders in the `level` option of handlers

## 3.8.0 (2022-05-10)

* Deprecated ambiguous `elasticsearch` type, use `elastica` instead
* Added support for Monolog 3.0 (requires symfony/monolog-bridge 6.1)
* Added support for `AsMonologProcessor` to autoconfigure processors
* Added support for `FallbackGroupHandler`
* Added support for `ElasticsearchHandler` as `elastic_search` type
* Added support for `ElasticaHandler` as `elastica` type
* Added support for `TelegramBotHandler` as `telegram`
* Added `fill_extra_context` flag for `sentry` handlers
* Added support for configuring PsrLogMessageProcessor (`date_format` and `remove_used_context_fields`)
* Fixed issue on Windows + PHP 8, workaround for https://github.com/php/php-src/issues/8315
* Fixed MongoDBHandler support when no client id is provided

## 3.7.1 (2021-11-05)

* Indicate compatibility with Symfony 6

## 3.7.0 (2021-03-31)

* Use `ActivationStrategy` instead of `actionLevel` when available
* Register resettable processors (`ResettableInterface`) for autoconfiguration (tag: `kernel.reset`)
* Drop support for Symfony 3.4
* Drop support for PHP < 7.1
* Fix call to undefined method pushProcessor on handler that does not implement ProcessableHandlerInterface
* Use "use_locking" option with rotating file handler
* Add ability to specify custom Sentry hub service

## 3.6.0 (2020-10-06)

* Added support for Symfony Mailer
* Added support for setting log levels from parameters or environment variables

## 3.5.0 (2019-11-13)

* Added support for Monolog 2.0
* Added `sentry` type to use sentry 2.0 client
* Added `insightops` handler
* Added possibility for auto-wire monolog channel according to the type-hinted aliases, introduced in the Symfony 4.2

## 3.4.0 (2019-06-20)

* Deprecate "excluded_404s" option
* Flush loggers on `kernel.reset`
* Register processors (`ProcessorInterface`) for autoconfiguration (tag: `monolog.processor`)
* Expose configuration for the `ConsoleHandler`
* Fixed psr-3 processing being applied to all handlers, only leaf ones are now processing
* Fixed regression when `app` channel is defined explicitly
* Fixed handlers marked as nested not being ignored properly from the stack
* Added support for Redis configuration
* Drop support for Symfony <3

## 3.3.1 (2018-11-04)

* Fixed compatibility with Symfony 4.2

## 3.3.0 (2018-06-04)

* Fixed the autowiring of the channel logger in autoconfigured services
* Added timeouts to the pushover, hipchat, slack handlers
* Dropped support for PHP 5.3, 5.4, and HHVM
* Added configuration for HttpCodeActivationStrategy
* Deprecated "excluded_404s" option for Symfony >= 3.4

## 3.2.0 (2018-03-05)

* Removed randomness from the container build
* Fixed support for the `monolog.logger` tag specifying a channel in combination with Symfony 3.4+ autowiring
* Fixed visibility of channels configured explicitly in the bundle config (they are now public in Symfony 4 too)
* Fixed invalid service definitions

## 3.1.2 (2017-11-06)

* fix invalid usage of count()

## 3.1.1 (2017-09-26)

* added support for Symfony 4

## 3.1.0 (2017-03-26)

* Added support for server_log handler
* Allow configuring VERBOSITY_QUIET in console handlers
* Fixed autowiring
* Fixed slackbot handler not escaping channel names properly
* Fixed slackbot handler requiring `slack_team` instead of `team` to be configured

## 3.0.3 (2017-01-10)

* Fixed deprecation notices when using Symfony 3.3+ and PHP7+

## 3.0.2 (2017-01-03)

* Revert disabling DebugHandler in CLI environments
* Update configuration for slack handlers for Monolog 1.22 new options
* Revert the removal of the DebugHandlerPass (needed for Symfony <3.2)

## 3.0.1 (2016-11-15)

* Removed obsolete code (DebugHandlerPass)

## 3.0.0 (2016-11-06)

* Removed class parameters for the container configuration
* Bumped minimum version of supported Symfony version to 2.7
* Removed `NotFoundActivationStrategy` (the bundle now uses the class from MonologBridge)
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\DependencyInjection\Loader\Configurator;

use _ContaoManager\Monolog\Formatter\ChromePHPFormatter;
use _ContaoManager\Monolog\Formatter\GelfMessageFormatter;
use _ContaoManager\Monolog\Formatter\HtmlFormatter;
use _ContaoManager\Monolog\Formatter\JsonFormatter;
use _ContaoManager\Monolog\Formatter\LineFormatter;
use _ContaoManager\Monolog\Formatter\LogglyFormatter;
use _ContaoManager\Monolog\Formatter\LogstashFormatter;
use _ContaoManager\Monolog\Formatter\NormalizerFormatter;
use _ContaoManager\Monolog\Formatter\ScalarFormatter;
use _ContaoManager\Monolog\Formatter\SyslogFormatter;
use _ContaoManager\Monolog\Formatter\WildfireFormatter;
use _ContaoManager\Monolog\Handler\FingersCrossed\ErrorLevelActivationStrategy;
use _ContaoManager\Monolog\Logger;
use _ContaoManager\Psr\Log\LoggerInterface;
use _ContaoManager\Symfony\Bridge\Monolog\Handler\FingersCrossed\NotFoundActivationStrategy;
use _ContaoManager\Symfony\Component\HttpClient\HttpClient;
use _ContaoManager\Symfony\Contracts\HttpClient\HttpClientInterface;
return static function (ContainerConfigurator $container) {
    $container->services()->alias('logger', 'monolog.logger')->alias(LoggerInterface::class, 'logger')->set('monolog.logger')->parent('monolog.logger_prototype')->args(['index_0' => 'app'])->call('useMicrosecondTimestamps', [param('monolog.use_microseconds')])->tag('monolog.channel_logger')->set('monolog.logger_prototype', Logger::class)->args([abstract_arg('channel')])->abstract()->set('monolog.activation_strategy.not_found', NotFoundActivationStrategy::class)->abstract()->deprecate('symfony/monolog-bundle', '3.11', 'The "%service_id%" service is deprecated.')->set('monolog.handler.fingers_crossed.error_level_activation_strategy', ErrorLevelActivationStrategy::class)->abstract()->deprecate('symfony/monolog-bundle', '3.11', 'The "%service_id%" service is deprecated.')->set('monolog.formatter.chrome_php', ChromePHPFormatter::class)->set('monolog.formatter.gelf_message', GelfMessageFormatter::class)->set('monolog.formatter.html', HtmlFormatter::class)->set('monolog.formatter.json', JsonFormatter::class)->set('monolog.formatter.line', LineFormatter::class)->set('monolog.formatter.syslog', SyslogFormatter::class)->set('monolog.formatter.loggly', LogglyFormatter::class)->set('monolog.formatter.normalizer', NormalizerFormatter::class)->set('monolog.formatter.scalar', ScalarFormatter::class)->set('monolog.formatter.wildfire', WildfireFormatter::class)->set('monolog.formatter.logstash', LogstashFormatter::class)->args(['app'])->set('monolog.http_client', HttpClientInterface::class)->factory([HttpClient::class, 'create']);
};
<?xml version="1.0" encoding="UTF-8" ?>

<xsd:schema xmlns="http://symfony.com/schema/dic/monolog"
    xmlns:xsd="http://www.w3.org/2001/XMLSchema"
    targetNamespace="http://symfony.com/schema/dic/monolog"
    elementFormDefault="qualified">

    <xsd:element name="config" type="config" />

    <xsd:complexType name="config">
        <xsd:choice minOccurs="0" maxOccurs="unbounded">
            <xsd:element name="handler" type="handler" />
            <xsd:element name="channel" type="xsd:string" />
        </xsd:choice>
    </xsd:complexType>

    <xsd:complexType name="handler">
        <xsd:sequence>
            <xsd:element name="email-prototype" type="email-prototype" minOccurs="0" maxOccurs="1" />
            <xsd:element name="member" type="xsd:string" minOccurs="0" maxOccurs="unbounded" />
            <xsd:element name="channels" type="channels" minOccurs="0" maxOccurs="1" />
            <xsd:element name="publisher" type="publisher" minOccurs="0" maxOccurs="1" />
            <xsd:element name="mongo" type="mongo" minOccurs="0" maxOccurs="1" />
            <xsd:element name="mongodb" type="mongodb" minOccurs="0" maxOccurs="1" />
            <xsd:element name="elasticsearch" type="elasticsearch" minOccurs="0" maxOccurs="1" />
            <xsd:element name="config" type="xsd:anyType" minOccurs="0" maxOccurs="1" />
            <xsd:element name="excluded-404" type="xsd:string" minOccurs="0" maxOccurs="unbounded" />
            <xsd:element name="excluded-http-code" type="excluded-http-code" minOccurs="0" maxOccurs="unbounded" />
            <xsd:element name="tag" type="xsd:string" minOccurs="0" maxOccurs="unbounded" />
            <xsd:element name="accepted-level" type="level" minOccurs="0" maxOccurs="unbounded" />
            <xsd:element name="to-email" type="xsd:string" minOccurs="0" maxOccurs="unbounded" />
            <xsd:element name="header" type="xsd:string" minOccurs="0" maxOccurs="unbounded" />
            <xsd:element name="process-psr-3-messages" type="process-psr-3-messages" minOccurs="0" maxOccurs="1" />
        </xsd:sequence>
        <xsd:attribute name="type" type="xsd:string" />
        <xsd:attribute name="priority" type="xsd:integer" />
        <xsd:attribute name="level" type="level" />
        <xsd:attribute name="bubble" type="xsd:boolean" />
        <xsd:attribute name="interactive-only" type="xsd:boolean" />
        <xsd:attribute name="process-psr-3-messages" type="xsd:boolean" />
        <xsd:attribute name="use_locking" type="xsd:boolean" />
        <xsd:attribute name="app-name" type="xsd:string" />
        <xsd:attribute name="path" type="xsd:string" />
        <xsd:attribute name="id" type="xsd:string" />
        <xsd:attribute name="name" type="xsd:string" use="required" />
        <xsd:attribute name="ident" type="xsd:string" />
        <xsd:attribute name="facility" type="xsd:string" />
        <xsd:attribute name="host" type="xsd:string" />
        <xsd:attribute name="source" type="xsd:string" />
        <xsd:attribute name="port" type="xsd:integer" />
        <xsd:attribute name="action-level" type="level" />
        <xsd:attribute name="passthru-level" type="level" />
        <xsd:attribute name="min-level" type="level" />
        <xsd:attribute name="max-level" type="level" />
        <xsd:attribute name="buffer-size" type="xsd:integer" />
        <xsd:attribute name="flush-on-overflow" type="xsd:boolean" />
        <xsd:attribute name="max-files" type="xsd:integer" />
        <xsd:attribute name="handler" type="xsd:string" />
        <xsd:attribute name="from-email" type="xsd:string" />
        <xsd:attribute name="to-email" type="xsd:string" />
        <xsd:attribute name="subject" type="xsd:string" />
        <xsd:attribute name="notify" type="xsd:boolean" />
        <xsd:attribute name="room" type="xsd:string" />
        <xsd:attribute name="nickname" type="xsd:string" />
        <xsd:attribute name="release" type="xsd:string" />
        <xsd:attribute name="timeout" type="xsd:string" />
        <xsd:attribute name="time" type="xsd:integer" />
        <xsd:attribute name="store" type="xsd:string" />
        <xsd:attribute name="deduplication-level" type="level" />
        <xsd:attribute name="connection-timeout" type="xsd:string" />
        <xsd:attribute name="persistent" type="xsd:boolean" />
        <xsd:attribute name="dsn" type="xsd:string" />
        <xsd:attribute name="hub-id" type="xsd:string" />
        <xsd:attribute name="client-id" type="xsd:string" />
        <xsd:attribute name="use-ssl" type="xsd:boolean" />
        <xsd:attribute name="formatter" type="xsd:string" />
        <xsd:attribute name="token" type="xsd:string" />
        <xsd:attribute name="channel" type="xsd:string" />
        <xsd:attribute name="bot-name" type="xsd:string" />
        <xsd:attribute name="use-attachment" type="xsd:boolean" />
        <xsd:attribute name="use-short-attachment" type="xsd:boolean" />
        <xsd:attribute name="include-extra" type="xsd:boolean" />
        <xsd:attribute name="icon-emoji" type="xsd:string" />
        <xsd:attribute name="file-permission" type="xsd:string" />
        <xsd:attribute name="filename-format" type="xsd:string" />
        <xsd:attribute name="date-format" type="xsd:string" />
        <xsd:attribute name="index" type="xsd:string" />
        <xsd:attribute name="document_type" type="xsd:string" />
        <xsd:attribute name="document-type" type="xsd:string" />
        <xsd:attribute name="ignore-error" type="xsd:string" />
        <xsd:attribute name="api_version" type="xsd:string" />
        <xsd:attribute name="include-stacktraces" type="xsd:string" />
        <xsd:attribute name="content-type" type="xsd:string" />
        <xsd:attribute name="webhook-url" type="xsd:string" />
        <xsd:attribute name="slack-team" type="xsd:string" />
        <xsd:attribute name="region" type="xsd:string" />
        <xsd:attribute name="enabled" type="xsd:boolean" />
    </xsd:complexType>

    <xsd:simpleType name="level">
        <xsd:restriction base="xsd:string">
            <xsd:enumeration value="debug" />
            <xsd:enumeration value="info" />
            <xsd:enumeration value="notice" />
            <xsd:enumeration value="warning" />
            <xsd:enumeration value="error" />
            <xsd:enumeration value="critical" />
            <xsd:enumeration value="alert" />
            <xsd:enumeration value="emergency" />

            <xsd:enumeration value="DEBUG" />
            <xsd:enumeration value="INFO" />
            <xsd:enumeration value="NOTICE" />
            <xsd:enumeration value="WARNING" />
            <xsd:enumeration value="ERROR" />
            <xsd:enumeration value="CRITICAL" />
            <xsd:enumeration value="ALERT" />
            <xsd:enumeration value="EMERGENCY" />

            <xsd:enumeration value="100" />
            <xsd:enumeration value="200" />
            <xsd:enumeration value="250" />
            <xsd:enumeration value="300" />
            <xsd:enumeration value="400" />
            <xsd:enumeration value="500" />
            <xsd:enumeration value="550" />
            <xsd:enumeration value="600" />
        </xsd:restriction>
    </xsd:simpleType>

    <xsd:complexType name="publisher">
        <xsd:attribute name="id" type="xsd:string" />
        <xsd:attribute name="hostname" type="xsd:string" />
        <xsd:attribute name="port" type="xsd:integer" />
        <xsd:attribute name="chunk_size" type="xsd:integer" />
    </xsd:complexType>

    <xsd:complexType name="email-prototype">
        <xsd:attribute name="id" type="xsd:string" />
        <xsd:attribute name="method" type="xsd:string" />
    </xsd:complexType>

    <xsd:complexType name="channels">
        <xsd:sequence>
            <xsd:element name="channel" type="xsd:string" minOccurs="0" maxOccurs="unbounded" />
        </xsd:sequence>
        <xsd:attribute name="type" type="channel_type" />
    </xsd:complexType>

    <xsd:simpleType name="channel_type">
        <xsd:restriction base="xsd:string">
            <xsd:enumeration value="inclusive" />
            <xsd:enumeration value="exclusive" />
        </xsd:restriction>
    </xsd:simpleType>

    <xsd:complexType name="mongo">
        <xsd:attribute name="id" type="xsd:string" />
        <xsd:attribute name="host" type="xsd:string" />
        <xsd:attribute name="port" type="xsd:integer" />
        <xsd:attribute name="user" type="xsd:string" />
        <xsd:attribute name="pass" type="xsd:string" />
        <xsd:attribute name="database" type="xsd:string" />
        <xsd:attribute name="collection" type="xsd:string" />
    </xsd:complexType>

    <xsd:complexType name="mongodb">
        <xsd:attribute name="id" type="xsd:string" />
        <xsd:attribute name="uri" type="xsd:string" />
        <xsd:attribute name="username" type="xsd:string" />
        <xsd:attribute name="password" type="xsd:string" />
        <xsd:attribute name="database" type="xsd:string" />
        <xsd:attribute name="collection" type="xsd:string" />
    </xsd:complexType>

    <xsd:complexType name="redis">
        <xsd:attribute name="id" type="xsd:string" />
        <xsd:attribute name="host" type="xsd:string" />
        <xsd:attribute name="password" type="xsd:string" />
        <xsd:attribute name="port" type="xsd:integer" />
        <xsd:attribute name="database" type="xsd:integer" />
        <xsd:attribute name="key_name" type="xsd:string" />
    </xsd:complexType>

    <xsd:complexType name="predis">
        <xsd:attribute name="id" type="xsd:string" />
        <xsd:attribute name="host" type="xsd:string" />
    </xsd:complexType>

    <xsd:complexType name="elasticsearch">
        <xsd:attribute name="id" type="xsd:string" />
        <xsd:attribute name="host" type="xsd:string" />
        <xsd:attribute name="port" type="xsd:integer" />
        <xsd:attribute name="transport" type="xsd:string" />
        <xsd:attribute name="user" type="xsd:string" />
        <xsd:attribute name="password" type="xsd:string" />
    </xsd:complexType>

    <xsd:complexType name="excluded-http-code">
        <xsd:choice minOccurs="0" maxOccurs="unbounded">
            <xsd:element name="url" type="xsd:string" />
        </xsd:choice>
        <xsd:attribute name="code" type="xsd:integer" />
    </xsd:complexType>

    <xsd:complexType name="headers">
        <xsd:sequence>
            <xsd:any minOccurs="0" processContents="lax" />
        </xsd:sequence>
    </xsd:complexType>

    <xsd:complexType name="process-psr-3-messages">
        <xsd:attribute name="enabled" type="xsd:boolean" />
        <xsd:attribute name="date-format" type="xsd:string" />
        <xsd:attribute name="remove-used-context-fields" type="xsd:boolean" />
    </xsd:complexType>
</xsd:schema>
MonologBundle
=============

The `MonologBundle` provides integration of the [Monolog](https://github.com/Seldaek/monolog)
library into the Symfony framework.

More information in the official [documentation](https://symfony.com/doc/current/logging.html).

License
=======

This bundle is released under the [MIT license](LICENSE)
{
    "name": "symfony\/monolog-bundle",
    "type": "symfony-bundle",
    "description": "Symfony MonologBundle",
    "keywords": [
        "log",
        "logging"
    ],
    "homepage": "https:\/\/symfony.com",
    "license": "MIT",
    "authors": [
        {
            "name": "Fabien Potencier",
            "email": "fabien@symfony.com"
        },
        {
            "name": "Symfony Community",
            "homepage": "https:\/\/symfony.com\/contributors"
        }
    ],
    "require": {
        "php": ">=8.1",
        "composer-runtime-api": "^2.0",
        "monolog\/monolog": "^1.25.1 || ^2.0 || ^3.0",
        "symfony\/config": "^6.4 || ^7.0",
        "symfony\/dependency-injection": "^6.4 || ^7.0",
        "symfony\/deprecation-contracts": "^2.5 || ^3.0",
        "symfony\/http-kernel": "^6.4 || ^7.0",
        "symfony\/monolog-bridge": "^6.4 || ^7.0",
        "symfony\/polyfill-php84": "^1.30"
    },
    "require-dev": {
        "symfony\/console": "^6.4 || ^7.0",
        "symfony\/phpunit-bridge": "^7.3.3",
        "symfony\/yaml": "^6.4 || ^7.0"
    },
    "autoload": {
        "psr-4": {
            "_ContaoManager\\Symfony\\Bundle\\MonologBundle\\": "src"
        }
    },
    "autoload-dev": {
        "psr-4": {
            "_ContaoManager\\Symfony\\Bundle\\MonologBundle\\Tests\\": "tests"
        }
    }
}<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Bundle\MonologBundle\SwiftMailer;

/**
 * Helps create Swift_Message objects, lazily.
 *
 * @author Ryan Weaver <ryan@knpuniversity.com>
 */
class MessageFactory
{
    private $mailer;
    private $fromEmail;
    private $toEmail;
    private $subject;
    private $contentType;
    public function __construct(\_ContaoManager\Swift_Mailer $mailer, $fromEmail, $toEmail, $subject, $contentType = null)
    {
        $this->mailer = $mailer;
        $this->fromEmail = $fromEmail;
        $this->toEmail = $toEmail;
        $this->subject = $subject;
        $this->contentType = $contentType;
    }
    /**
     * Creates a Swift_Message template that will be used to send the log message.
     *
     * @param string $content formatted email body to be sent
     * @param array  $records Log records that formed the content
     *
     * @return \Swift_Message
     */
    public function createMessage($content, array $records)
    {
        /** @var \Swift_Message $message */
        $message = $this->mailer->createMessage();
        $message->setTo($this->toEmail);
        $message->setFrom($this->fromEmail);
        $message->setSubject($this->subject);
        if ($this->contentType) {
            $message->setContentType($this->contentType);
        }
        return $message;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Bundle\MonologBundle;

use _ContaoManager\Monolog\Formatter\JsonFormatter;
use _ContaoManager\Monolog\Formatter\LineFormatter;
use _ContaoManager\Monolog\Handler\HandlerInterface;
use _ContaoManager\Symfony\Bundle\MonologBundle\DependencyInjection\Compiler\AddProcessorsPass;
use _ContaoManager\Symfony\Bundle\MonologBundle\DependencyInjection\Compiler\AddSwiftMailerTransportPass;
use _ContaoManager\Symfony\Bundle\MonologBundle\DependencyInjection\Compiler\FixEmptyLoggerPass;
use _ContaoManager\Symfony\Bundle\MonologBundle\DependencyInjection\Compiler\LoggerChannelPass;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerBuilder;
use _ContaoManager\Symfony\Component\HttpKernel\Bundle\Bundle;
/**
 * @author Jordi Boggiano <j.boggiano@seld.be>
 *
 * @final since 3.9.0
 */
class MonologBundle extends Bundle
{
    /**
     * @return void
     */
    public function build(ContainerBuilder $container)
    {
        parent::build($container);
        $container->addCompilerPass($channelPass = new LoggerChannelPass());
        $container->addCompilerPass(new FixEmptyLoggerPass($channelPass));
        $container->addCompilerPass(new AddProcessorsPass());
        $container->addCompilerPass(new AddSwiftMailerTransportPass());
    }
    /**
     * @internal
     *
     * @return void
     */
    public static function includeStacktraces(HandlerInterface $handler)
    {
        $formatter = $handler->getFormatter();
        if ($formatter instanceof LineFormatter || $formatter instanceof JsonFormatter) {
            $formatter->includeStacktraces();
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Bundle\MonologBundle\DependencyInjection;

use _ContaoManager\Monolog\Attribute\AsMonologProcessor;
use _ContaoManager\Monolog\Attribute\WithMonologChannel;
use _ContaoManager\Monolog\Handler\FingersCrossed\ErrorLevelActivationStrategy;
use _ContaoManager\Monolog\Handler\HandlerInterface;
use _ContaoManager\Monolog\Logger;
use _ContaoManager\Monolog\Processor\ProcessorInterface;
use _ContaoManager\Monolog\Processor\PsrLogMessageProcessor;
use _ContaoManager\Monolog\ResettableInterface;
use _ContaoManager\Symfony\Bridge\Monolog\Handler\FingersCrossed\HttpCodeActivationStrategy;
use _ContaoManager\Symfony\Bridge\Monolog\Processor\SwitchUserTokenProcessor;
use _ContaoManager\Symfony\Bridge\Monolog\Processor\TokenProcessor;
use _ContaoManager\Symfony\Bridge\Monolog\Processor\WebProcessor;
use _ContaoManager\Symfony\Component\Config\FileLocator;
use _ContaoManager\Symfony\Component\DependencyInjection\Argument\BoundArgument;
use _ContaoManager\Symfony\Component\DependencyInjection\ChildDefinition;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerBuilder;
use _ContaoManager\Symfony\Component\DependencyInjection\Definition;
use _ContaoManager\Symfony\Component\DependencyInjection\Loader\PhpFileLoader;
use _ContaoManager\Symfony\Component\DependencyInjection\Reference;
use _ContaoManager\Symfony\Component\HttpKernel\DependencyInjection\Extension;
use _ContaoManager\Symfony\Contracts\HttpClient\HttpClientInterface;
/**
 * MonologExtension is an extension for the Monolog library.
 *
 * @author Jordi Boggiano <j.boggiano@seld.be>
 * @author Christophe Coevoet <stof@notk.org>
 *
 * @final since 3.9.0
 */
class MonologExtension extends Extension
{
    private $nestedHandlers = [];
    private $swiftMailerHandlers = [];
    /**
     * Loads the Monolog configuration.
     *
     * @param array            $configs   An array of configuration settings
     * @param ContainerBuilder $container A ContainerBuilder instance
     */
    public function load(array $configs, ContainerBuilder $container)
    {
        $configuration = $this->getConfiguration($configs, $container);
        $config = $this->processConfiguration($configuration, $configs);
        if (isset($config['handlers'])) {
            $loader = new PhpFileLoader($container, new FileLocator(__DIR__ . '/../../config'));
            $loader->load('monolog.php');
            $container->setParameter('monolog.use_microseconds', $config['use_microseconds']);
            $handlers = [];
            foreach ($config['handlers'] as $name => $handler) {
                if (!$handler['enabled']) {
                    continue;
                }
                $handlers[$handler['priority']][] = ['id' => $this->buildHandler($container, $name, $handler), 'channels' => empty($handler['channels']) ? null : $handler['channels']];
            }
            $container->setParameter('monolog.swift_mailer.handlers', $this->swiftMailerHandlers);
            ksort($handlers);
            $sortedHandlers = [];
            foreach ($handlers as $priorityHandlers) {
                foreach (array_reverse($priorityHandlers) as $handler) {
                    $sortedHandlers[] = $handler;
                }
            }
            $handlersToChannels = [];
            foreach ($sortedHandlers as $handler) {
                if (!\in_array($handler['id'], $this->nestedHandlers)) {
                    $handlersToChannels[$handler['id']] = $handler['channels'];
                }
            }
            $container->setParameter('monolog.handlers_to_channels', $handlersToChannels);
        }
        $container->setParameter('monolog.additional_channels', $config['channels'] ?? []);
        if (interface_exists(ProcessorInterface::class)) {
            $container->registerForAutoconfiguration(ProcessorInterface::class)->addTag('monolog.processor');
        } else {
            $container->registerForAutoconfiguration(WebProcessor::class)->addTag('monolog.processor');
        }
        if (interface_exists(ResettableInterface::class)) {
            $container->registerForAutoconfiguration(ResettableInterface::class)->addTag('kernel.reset', ['method' => 'reset']);
        }
        $container->registerForAutoconfiguration(TokenProcessor::class)->addTag('monolog.processor');
        if (interface_exists(HttpClientInterface::class)) {
            $handlerAutoconfiguration = $container->registerForAutoconfiguration(HandlerInterface::class);
            $handlerAutoconfiguration->setBindings($handlerAutoconfiguration->getBindings() + [HttpClientInterface::class => new BoundArgument(new Reference('monolog.http_client'), \false)]);
        }
        $container->registerAttributeForAutoconfiguration(AsMonologProcessor::class, static function (ChildDefinition $definition, AsMonologProcessor $attribute, \Reflector $reflector): void {
            $tagAttributes = get_object_vars($attribute);
            if ($reflector instanceof \ReflectionMethod) {
                if (isset($tagAttributes['method'])) {
                    throw new \LogicException(\sprintf('AsMonologProcessor attribute cannot declare a method on "%s::%s()".', $reflector->class, $reflector->name));
                }
                $tagAttributes['method'] = $reflector->getName();
            }
            $definition->addTag('monolog.processor', $tagAttributes);
        });
        $container->registerAttributeForAutoconfiguration(WithMonologChannel::class, static function (ChildDefinition $definition, WithMonologChannel $attribute): void {
            $definition->addTag('monolog.logger', ['channel' => $attribute->channel]);
        });
    }
    /**
     * Returns the base path for the XSD files.
     *
     * @return string The XSD base path
     */
    public function getXsdValidationBasePath()
    {
        return __DIR__ . '/../../config/schema';
    }
    public function getNamespace()
    {
        return 'http://symfony.com/schema/dic/monolog';
    }
    private function buildHandler(ContainerBuilder $container, $name, array $handler)
    {
        $handlerId = $this->getHandlerId($name);
        if ('service' === $handler['type']) {
            $container->setAlias($handlerId, $handler['id']);
            if (!empty($handler['nested']) && \true === $handler['nested']) {
                $this->markNestedHandler($handlerId);
            }
            return $handlerId;
        }
        $handlerClass = $this->getHandlerClassByType($handler['type']);
        $definition = new Definition($handlerClass);
        if ($handler['include_stacktraces']) {
            $definition->setConfigurator(['_ContaoManager\Symfony\Bundle\MonologBundle\MonologBundle', 'includeStacktraces']);
        }
        if (null === $handler['process_psr_3_messages']['enabled']) {
            $handler['process_psr_3_messages']['enabled'] = !isset($handler['handler']) && !$handler['members'];
        }
        if ($handler['process_psr_3_messages']['enabled'] && method_exists($handlerClass, 'pushProcessor')) {
            $processorId = $this->buildPsrLogMessageProcessor($container, $handler['process_psr_3_messages']);
            $definition->addMethodCall('pushProcessor', [new Reference($processorId)]);
        }
        switch ($handler['type']) {
            case 'stream':
                $definition->setArguments([$handler['path'], $handler['level'], $handler['bubble'], $handler['file_permission'], $handler['use_locking']]);
                break;
            case 'console':
                $definition->setArguments([null, $handler['bubble'], $handler['verbosity_levels'] ?? [], $handler['console_formatter_options'], $handler['interactive_only']]);
                $definition->addTag('kernel.event_subscriber');
                break;
            case 'chromephp':
            case 'firephp':
                $definition->setArguments([$handler['level'], $handler['bubble']]);
                $definition->addTag('kernel.event_listener', ['event' => 'kernel.response', 'method' => 'onKernelResponse']);
                break;
            case 'gelf':
                if (isset($handler['publisher']['id'])) {
                    $publisher = new Reference($handler['publisher']['id']);
                } elseif (class_exists('_ContaoManager\Gelf\Transport\UdpTransport')) {
                    $transport = new Definition("_ContaoManager\\Gelf\\Transport\\UdpTransport", [$handler['publisher']['hostname'], $handler['publisher']['port'], $handler['publisher']['chunk_size']]);
                    $transport->setPublic(\false);
                    if (isset($handler['publisher']['encoder'])) {
                        if ('compressed_json' === $handler['publisher']['encoder']) {
                            $encoderClass = '_ContaoManager\Gelf\Encoder\CompressedJsonEncoder';
                        } elseif ('json' === $handler['publisher']['encoder']) {
                            $encoderClass = '_ContaoManager\Gelf\Encoder\JsonEncoder';
                        } else {
                            throw new \RuntimeException('The gelf message encoder must be either "compressed_json" or "json".');
                        }
                        $encoder = new Definition($encoderClass);
                        $encoder->setPublic(\false);
                        $transport->addMethodCall('setMessageEncoder', [$encoder]);
                    }
                    $publisher = new Definition('_ContaoManager\Gelf\Publisher', []);
                    $publisher->addMethodCall('addTransport', [$transport]);
                    $publisher->setPublic(\false);
                } elseif (class_exists('_ContaoManager\Gelf\MessagePublisher')) {
                    if (isset($handler['publisher']['encoder']) && 'compressed_json' !== $handler['publisher']['encoder']) {
                        throw new \RuntimeException('The Gelf\MessagePublisher publisher supports only the compressed json encoding. Omit the option to use the default encoding or use "compressed_json" as the encoder option.');
                    }
                    $publisher = new Definition('_ContaoManager\Gelf\MessagePublisher', [$handler['publisher']['hostname'], $handler['publisher']['port'], $handler['publisher']['chunk_size']]);
                    $publisher->setPublic(\false);
                } else {
                    throw new \RuntimeException('The gelf handler requires the graylog2/gelf-php package to be installed.');
                }
                $definition->setArguments([$publisher, $handler['level'], $handler['bubble']]);
                break;
            case 'mongo':
                trigger_deprecation('symfony/monolog-bundle', '3.11', 'The "mongo" handler type is deprecated in MonologBundle since version 3.11.0, use the "mongodb" type instead.');
                if (!class_exists('_ContaoManager\MongoDB\Client')) {
                    throw new \RuntimeException('The "mongo" handler requires the mongodb/mongodb package to be installed.');
                }
                if (isset($handler['mongo']['id'])) {
                    $client = new Reference($handler['mongo']['id']);
                } else {
                    $server = 'mongodb://';
                    if (isset($handler['mongo']['user'])) {
                        $server .= $handler['mongo']['user'] . ':' . $handler['mongo']['pass'] . '@';
                    }
                    $server .= $handler['mongo']['host'] . ':' . $handler['mongo']['port'];
                    $client = new Definition('_ContaoManager\MongoDB\Client', [$server, ['appname' => 'monolog-bundle']]);
                }
                $definition->setArguments([$client, $handler['mongo']['database'], $handler['mongo']['collection'], $handler['level'], $handler['bubble']]);
                break;
            case 'mongodb':
                if (!class_exists('_ContaoManager\MongoDB\Client')) {
                    throw new \RuntimeException('The "mongodb" handler requires the mongodb/mongodb package to be installed.');
                }
                if (isset($handler['mongodb']['id'])) {
                    $client = new Reference($handler['mongodb']['id']);
                } else {
                    $uriOptions = ['appname' => 'monolog-bundle'];
                    if (isset($handler['mongodb']['username'])) {
                        $uriOptions['username'] = $handler['mongodb']['username'];
                    }
                    if (isset($handler['mongodb']['password'])) {
                        $uriOptions['password'] = $handler['mongodb']['password'];
                    }
                    $client = new Definition('_ContaoManager\MongoDB\Client', [$handler['mongodb']['uri'], $uriOptions]);
                }
                $definition->setArguments([$client, $handler['mongodb']['database'], $handler['mongodb']['collection'], $handler['level'], $handler['bubble']]);
                if (empty($handler['formatter'])) {
                    $formatter = new Definition('_ContaoManager\Monolog\Formatter\MongoDBFormatter');
                    $definition->addMethodCall('setFormatter', [$formatter]);
                }
                break;
            case 'elasticsearch':
                trigger_deprecation('symfony/monolog-bundle', '3.8', 'The "elasticsearch" handler type is deprecated in MonologBundle since version 3.8.0, use the "elastica" type instead, or switch to the official Elastic client using the "elastic_search" type.');
            // no break
            case 'elastica':
            case 'elastic_search':
                if (isset($handler['elasticsearch']['id'])) {
                    $client = new Reference($handler['elasticsearch']['id']);
                } else {
                    if ('elastic_search' === $handler['type']) {
                        // v8 has a new Elastic\ prefix
                        $client = new Definition(class_exists('_ContaoManager\Elastic\Elasticsearch\Client') ? 'Elastic\Elasticsearch\Client' : 'Elasticsearch\Client');
                        $factory = class_exists('_ContaoManager\Elastic\Elasticsearch\ClientBuilder') ? 'Elastic\Elasticsearch\ClientBuilder' : 'Elasticsearch\ClientBuilder';
                        $client->setFactory([$factory, 'fromConfig']);
                        $clientArguments = ['hosts' => $handler['elasticsearch']['hosts'] ?? [$handler['elasticsearch']['host']]];
                        if (isset($handler['elasticsearch']['user'], $handler['elasticsearch']['password'])) {
                            $clientArguments['basicAuthentication'] = [$handler['elasticsearch']['user'], $handler['elasticsearch']['password']];
                        }
                    } else {
                        $client = new Definition('_ContaoManager\Elastica\Client');
                        if (isset($handler['elasticsearch']['hosts'])) {
                            $clientArguments = ['hosts' => $handler['elasticsearch']['hosts'], 'transport' => $handler['elasticsearch']['transport']];
                        } else {
                            $clientArguments = ['host' => $handler['elasticsearch']['host'], 'port' => $handler['elasticsearch']['port'], 'transport' => $handler['elasticsearch']['transport']];
                        }
                        if (isset($handler['elasticsearch']['user'], $handler['elasticsearch']['password'])) {
                            $clientArguments['headers'] = ['Authorization' => 'Basic ' . base64_encode($handler['elasticsearch']['user'] . ':' . $handler['elasticsearch']['password'])];
                        }
                    }
                    $client->setArguments([$clientArguments]);
                    $client->setPublic(\false);
                }
                // elastica handler definition
                $definition->setArguments([$client, ['index' => $handler['index'], 'type' => $handler['document_type'], 'ignore_error' => $handler['ignore_error']], $handler['level'], $handler['bubble']]);
                break;
            case 'telegram':
                if (!class_exists('_ContaoManager\Monolog\Handler\TelegramBotHandler')) {
                    throw new \RuntimeException('The TelegramBotHandler is not available. Please update "monolog/monolog" to 2.2.0.');
                }
                $definition->setArguments([$handler['token'], $handler['channel'], $handler['level'], $handler['bubble'], $handler['parse_mode'], $handler['disable_webpage_preview'], $handler['disable_notification'], $handler['split_long_messages'], $handler['delay_between_messages'], $handler['topic']]);
                break;
            case 'redis':
            case 'predis':
                if (isset($handler['redis']['id'])) {
                    $clientId = $handler['redis']['id'];
                } elseif ('redis' === $handler['type']) {
                    if (!class_exists(\Redis::class)) {
                        throw new \RuntimeException('The \Redis class is not available.');
                    }
                    $client = new Definition(\Redis::class);
                    $client->addMethodCall('connect', [$handler['redis']['host'], $handler['redis']['port']]);
                    $client->addMethodCall('auth', [$handler['redis']['password']]);
                    $client->addMethodCall('select', [$handler['redis']['database']]);
                    $client->setPublic(\false);
                    $clientId = uniqid('monolog.redis.client.', \true);
                    $container->setDefinition($clientId, $client);
                } else {
                    if (!class_exists(\_ContaoManager\Predis\Client::class)) {
                        throw new \RuntimeException('The \Predis\Client class is not available.');
                    }
                    $client = new Definition(\_ContaoManager\Predis\Client::class);
                    $client->setArguments([$handler['redis']['host']]);
                    $client->setPublic(\false);
                    $clientId = uniqid('monolog.predis.client.', \true);
                    $container->setDefinition($clientId, $client);
                }
                $definition->setArguments([new Reference($clientId), $handler['redis']['key_name'], $handler['level'], $handler['bubble']]);
                break;
            case 'rotating_file':
                $definition->setArguments([$handler['path'], $handler['max_files'], $handler['level'], $handler['bubble'], $handler['file_permission'], $handler['use_locking']]);
                $definition->addMethodCall('setFilenameFormat', [$handler['filename_format'], $handler['date_format']]);
                break;
            case 'fingers_crossed':
                $nestedHandlerId = $this->getHandlerId($handler['handler']);
                $this->markNestedHandler($nestedHandlerId);
                $activation = $handler['action_level'];
                if (class_exists(SwitchUserTokenProcessor::class)) {
                    $activation = new Definition(ErrorLevelActivationStrategy::class, [$activation]);
                }
                if (isset($handler['activation_strategy'])) {
                    $activation = new Reference($handler['activation_strategy']);
                } elseif (!empty($handler['excluded_404s'])) {
                    if (class_exists(HttpCodeActivationStrategy::class)) {
                        trigger_deprecation('symfony/monolog-bundle', '3.4', 'The "excluded_404s" option is deprecated, you should rely on the "excluded_http_codes" option instead.');
                    }
                    $activationDef = new Definition('_ContaoManager\Symfony\Bridge\Monolog\Handler\FingersCrossed\NotFoundActivationStrategy', [new Reference('request_stack'), $handler['excluded_404s'], $activation]);
                    $container->setDefinition($handlerId . '.not_found_strategy', $activationDef);
                    $activation = new Reference($handlerId . '.not_found_strategy');
                } elseif (!empty($handler['excluded_http_codes'])) {
                    $activationDef = new Definition('_ContaoManager\Symfony\Bridge\Monolog\Handler\FingersCrossed\HttpCodeActivationStrategy', [new Reference('request_stack'), $handler['excluded_http_codes'], $activation]);
                    $container->setDefinition($handlerId . '.http_code_strategy', $activationDef);
                    $activation = new Reference($handlerId . '.http_code_strategy');
                }
                $definition->setArguments([new Reference($nestedHandlerId), $activation, $handler['buffer_size'], $handler['bubble'], $handler['stop_buffering'], $handler['passthru_level']]);
                break;
            case 'filter':
                $nestedHandlerId = $this->getHandlerId($handler['handler']);
                $this->markNestedHandler($nestedHandlerId);
                $minLevelOrList = !empty($handler['accepted_levels']) ? $handler['accepted_levels'] : $handler['min_level'];
                $definition->setArguments([new Reference($nestedHandlerId), $minLevelOrList, $handler['max_level'], $handler['bubble']]);
                break;
            case 'buffer':
                $nestedHandlerId = $this->getHandlerId($handler['handler']);
                $this->markNestedHandler($nestedHandlerId);
                $definition->setArguments([new Reference($nestedHandlerId), $handler['buffer_size'], $handler['level'], $handler['bubble'], $handler['flush_on_overflow']]);
                break;
            case 'deduplication':
                $nestedHandlerId = $this->getHandlerId($handler['handler']);
                $this->markNestedHandler($nestedHandlerId);
                $defaultStore = '%kernel.cache_dir%/monolog_dedup_' . sha1($handlerId);
                $definition->setArguments([new Reference($nestedHandlerId), $handler['store'] ?? $defaultStore, $handler['deduplication_level'], $handler['time'], $handler['bubble']]);
                break;
            case 'group':
            case 'whatfailuregroup':
            case 'fallbackgroup':
                $references = [];
                foreach ($handler['members'] as $nestedHandler) {
                    $nestedHandlerId = $this->getHandlerId($nestedHandler);
                    $this->markNestedHandler($nestedHandlerId);
                    $references[] = new Reference($nestedHandlerId);
                }
                $definition->setArguments([$references, $handler['bubble']]);
                break;
            case 'syslog':
                $definition->setArguments([$handler['ident'], $handler['facility'], $handler['level'], $handler['bubble'], $handler['logopts']]);
                break;
            case 'syslogudp':
                $definition->setArguments([$handler['host'], $handler['port'], $handler['facility'], $handler['level'], $handler['bubble']]);
                if ($handler['ident']) {
                    $definition->addArgument($handler['ident']);
                }
                break;
            case 'swift_mailer':
                $mailer = $handler['mailer'] ?: 'mailer';
                if (isset($handler['email_prototype'])) {
                    if (!empty($handler['email_prototype']['method'])) {
                        $prototype = [new Reference($handler['email_prototype']['id']), $handler['email_prototype']['method']];
                    } else {
                        $prototype = new Reference($handler['email_prototype']['id']);
                    }
                } else {
                    $messageFactory = new Definition('_ContaoManager\Symfony\Bundle\MonologBundle\SwiftMailer\MessageFactory');
                    $messageFactory->setLazy(\true);
                    $messageFactory->setPublic(\false);
                    $messageFactory->setArguments([new Reference($mailer), $handler['from_email'], $handler['to_email'], $handler['subject'], $handler['content_type']]);
                    $messageFactoryId = \sprintf('%s.mail_message_factory', $handlerId);
                    $container->setDefinition($messageFactoryId, $messageFactory);
                    // set the prototype as a callable
                    $prototype = [new Reference($messageFactoryId), 'createMessage'];
                }
                $definition->setArguments([new Reference($mailer), $prototype, $handler['level'], $handler['bubble']]);
                $this->swiftMailerHandlers[] = $handlerId;
                $definition->addTag('kernel.event_listener', ['event' => 'kernel.terminate', 'method' => 'onKernelTerminate']);
                $definition->addTag('kernel.event_listener', ['event' => 'console.terminate', 'method' => 'onCliTerminate']);
                break;
            case 'native_mailer':
                $definition->setArguments([$handler['to_email'], $handler['subject'], $handler['from_email'], $handler['level'], $handler['bubble']]);
                if (!empty($handler['headers'])) {
                    $definition->addMethodCall('addHeader', [$handler['headers']]);
                }
                break;
            case 'symfony_mailer':
                $mailer = $handler['mailer'] ?: 'mailer.mailer';
                if (isset($handler['email_prototype'])) {
                    if (!empty($handler['email_prototype']['method'])) {
                        $prototype = [new Reference($handler['email_prototype']['id']), $handler['email_prototype']['method']];
                    } else {
                        $prototype = new Reference($handler['email_prototype']['id']);
                    }
                } else {
                    $prototype = (new Definition('_ContaoManager\Symfony\Component\Mime\Email'))->setPublic(\false)->addMethodCall('from', [$handler['from_email']])->addMethodCall('to', $handler['to_email'])->addMethodCall('subject', [$handler['subject']]);
                }
                $definition->setArguments([new Reference($mailer), $prototype, $handler['level'], $handler['bubble']]);
                break;
            case 'socket':
                $definition->setArguments([$handler['connection_string'], $handler['level'], $handler['bubble']]);
                if (isset($handler['timeout'])) {
                    $definition->addMethodCall('setTimeout', [$handler['timeout']]);
                }
                if (isset($handler['connection_timeout'])) {
                    $definition->addMethodCall('setConnectionTimeout', [$handler['connection_timeout']]);
                }
                if (isset($handler['persistent'])) {
                    $definition->addMethodCall('setPersistent', [$handler['persistent']]);
                }
                break;
            case 'pushover':
                $definition->setArguments([$handler['token'], $handler['user'], $handler['title'], $handler['level'], $handler['bubble']]);
                if (isset($handler['timeout'])) {
                    $definition->addMethodCall('setTimeout', [$handler['timeout']]);
                }
                if (isset($handler['connection_timeout'])) {
                    $definition->addMethodCall('setConnectionTimeout', [$handler['connection_timeout']]);
                }
                break;
            case 'hipchat':
                $definition->setArguments([$handler['token'], $handler['room'], $handler['nickname'], $handler['notify'], $handler['level'], $handler['bubble'], $handler['use_ssl'], $handler['message_format'], !empty($handler['host']) ? $handler['host'] : 'api.hipchat.com', !empty($handler['api_version']) ? $handler['api_version'] : 'v1']);
                if (isset($handler['timeout'])) {
                    $definition->addMethodCall('setTimeout', [$handler['timeout']]);
                }
                if (isset($handler['connection_timeout'])) {
                    $definition->addMethodCall('setConnectionTimeout', [$handler['connection_timeout']]);
                }
                break;
            case 'slack':
                $definition->setArguments([$handler['token'], $handler['channel'], $handler['bot_name'], $handler['use_attachment'], $handler['icon_emoji'], $handler['level'], $handler['bubble'], $handler['use_short_attachment'], $handler['include_extra'], $handler['exclude_fields']]);
                if (isset($handler['timeout'])) {
                    $definition->addMethodCall('setTimeout', [$handler['timeout']]);
                }
                if (isset($handler['connection_timeout'])) {
                    $definition->addMethodCall('setConnectionTimeout', [$handler['connection_timeout']]);
                }
                break;
            case 'slackwebhook':
                $definition->setArguments([$handler['webhook_url'], $handler['channel'], $handler['bot_name'], $handler['use_attachment'], $handler['icon_emoji'], $handler['use_short_attachment'], $handler['include_extra'], $handler['level'], $handler['bubble'], $handler['exclude_fields']]);
                break;
            case 'slackbot':
                $definition->setArguments([$handler['team'], $handler['token'], urlencode($handler['channel']), $handler['level'], $handler['bubble']]);
                break;
            case 'cube':
                $definition->setArguments([$handler['url'], $handler['level'], $handler['bubble']]);
                break;
            case 'amqp':
                $definition->setArguments([new Reference($handler['exchange']), $handler['exchange_name'], $handler['level'], $handler['bubble']]);
                break;
            case 'error_log':
                $definition->setArguments([$handler['message_type'], $handler['level'], $handler['bubble']]);
                break;
            case 'sentry':
                trigger_deprecation('symfony/monolog-bundle', '3.11', 'The "sentry" handler type is deprecated, use the "sentry/sentry-symfony" and a "service" handler instead.');
                if (null !== $handler['hub_id']) {
                    $hubId = $handler['hub_id'];
                } else {
                    if (null !== $handler['client_id']) {
                        $clientId = $handler['client_id'];
                    } else {
                        $options = new Definition('_ContaoManager\Sentry\Options', [['dsn' => $handler['dsn']]]);
                        if (!empty($handler['environment'])) {
                            $options->addMethodCall('setEnvironment', [$handler['environment']]);
                        }
                        if (!empty($handler['release'])) {
                            $options->addMethodCall('setRelease', [$handler['release']]);
                        }
                        $builder = new Definition('_ContaoManager\Sentry\ClientBuilder', [$options]);
                        $client = new Definition('_ContaoManager\Sentry\Client');
                        $client->setFactory([$builder, 'getClient']);
                        $clientId = 'monolog.sentry.client.' . sha1($handler['dsn']);
                        $container->setDefinition($clientId, $client);
                        if (!$container->hasAlias('_ContaoManager\Sentry\ClientInterface')) {
                            $container->setAlias('_ContaoManager\Sentry\ClientInterface', $clientId);
                        }
                    }
                    $hubId = \sprintf('monolog.handler.%s.hub', $name);
                    $hub = $container->setDefinition($hubId, new Definition('_ContaoManager\Sentry\State\Hub', [new Reference($clientId)]));
                    // can't set the hub to the current hub, getting into a recursion otherwise...
                    // $hub->addMethodCall('setCurrent', array($hub));
                }
                $definition->setArguments([new Reference($hubId), $handler['level'], $handler['bubble'], $handler['fill_extra_context']]);
                break;
            case 'raven':
                trigger_deprecation('symfony/monolog-bundle', '3.11', 'The "raven" handler type is deprecated, use the "sentry/sentry-symfony" and a "service" handler instead.');
                if (null !== $handler['client_id']) {
                    $clientId = $handler['client_id'];
                } else {
                    $client = new Definition('Raven_Client', [$handler['dsn'], ['auto_log_stacks' => $handler['auto_log_stacks'], 'environment' => $handler['environment']]]);
                    $client->setPublic(\false);
                    $clientId = 'monolog.raven.client.' . sha1($handler['dsn']);
                    $container->setDefinition($clientId, $client);
                }
                $definition->setArguments([new Reference($clientId), $handler['level'], $handler['bubble']]);
                if (!empty($handler['release'])) {
                    $definition->addMethodCall('setRelease', [$handler['release']]);
                }
                break;
            case 'loggly':
                $definition->setArguments([$handler['token'], $handler['level'], $handler['bubble']]);
                if (!empty($handler['tags'])) {
                    $definition->addMethodCall('setTag', [implode(',', $handler['tags'])]);
                }
                break;
            case 'logentries':
                $definition->setArguments([$handler['token'], $handler['use_ssl'], $handler['level'], $handler['bubble']]);
                if (isset($handler['timeout'])) {
                    $definition->addMethodCall('setTimeout', [$handler['timeout']]);
                }
                if (isset($handler['connection_timeout'])) {
                    $definition->addMethodCall('setConnectionTimeout', [$handler['connection_timeout']]);
                }
                break;
            case 'insightops':
                $definition->setArguments([$handler['token'], $handler['region'] ?: 'us', $handler['use_ssl'], $handler['level'], $handler['bubble']]);
                break;
            case 'flowdock':
                $definition->setArguments([$handler['token'], $handler['level'], $handler['bubble']]);
                if (empty($handler['formatter'])) {
                    $formatter = new Definition("_ContaoManager\\Monolog\\Formatter\\FlowdockFormatter", [$handler['source'], $handler['from_email']]);
                    $formatterId = 'monolog.flowdock.formatter.' . sha1($handler['source'] . '|' . $handler['from_email']);
                    $formatter->setPublic(\false);
                    $container->setDefinition($formatterId, $formatter);
                    $definition->addMethodCall('setFormatter', [new Reference($formatterId)]);
                }
                break;
            case 'rollbar':
                if (!empty($handler['id'])) {
                    $rollbarId = $handler['id'];
                } else {
                    $config = $handler['config'] ?: [];
                    $config['access_token'] = $handler['token'];
                    $rollbar = new Definition(Logger::API === 1 ? 'RollbarNotifier' : 'Rollbar\RollbarLogger', [$config]);
                    $rollbarId = 'monolog.rollbar.notifier.' . sha1(json_encode($config));
                    $rollbar->setPublic(\false);
                    $container->setDefinition($rollbarId, $rollbar);
                }
                $definition->setArguments([new Reference($rollbarId), $handler['level'], $handler['bubble']]);
                break;
            case 'newrelic':
                $definition->setArguments([$handler['level'], $handler['bubble'], $handler['app_name']]);
                break;
            case 'server_log':
                $definition->setArguments([$handler['host'], $handler['level'], $handler['bubble']]);
                break;
            case 'sampling':
                $nestedHandlerId = $this->getHandlerId($handler['handler']);
                $this->markNestedHandler($nestedHandlerId);
                $definition->setArguments([new Reference($nestedHandlerId), $handler['factor']]);
                break;
            // Handlers using the constructor of AbstractHandler without adding their own arguments
            case 'browser_console':
            case 'test':
            case 'null':
            case 'noop':
            case 'debug':
                $definition->setArguments([$handler['level'], $handler['bubble']]);
                break;
            default:
                $nullWarning = '';
                if ('' == $handler['type']) {
                    $nullWarning = ', if you meant to define a null handler in a yaml config, make sure you quote "null" so it does not get converted to a php null';
                }
                throw new \InvalidArgumentException(\sprintf('Invalid handler type "%s" given for handler "%s".' . $nullWarning, $handler['type'], $name));
        }
        if (!empty($handler['nested']) && \true === $handler['nested']) {
            $this->markNestedHandler($handlerId);
        }
        if (!empty($handler['formatter'])) {
            $definition->addMethodCall('setFormatter', [new Reference($handler['formatter'])]);
        }
        if (!\in_array($handlerId, $this->nestedHandlers) && is_subclass_of($handlerClass, ResettableInterface::class)) {
            $definition->addTag('kernel.reset', ['method' => 'reset']);
        }
        $container->setDefinition($handlerId, $definition);
        return $handlerId;
    }
    private function markNestedHandler($nestedHandlerId)
    {
        if (\in_array($nestedHandlerId, $this->nestedHandlers)) {
            return;
        }
        $this->nestedHandlers[] = $nestedHandlerId;
    }
    private function getHandlerId($name)
    {
        return \sprintf('monolog.handler.%s', $name);
    }
    private function getHandlerClassByType($handlerType)
    {
        $typeToClassMapping = ['stream' => '_ContaoManager\Monolog\Handler\StreamHandler', 'console' => '_ContaoManager\Symfony\Bridge\Monolog\Handler\ConsoleHandler', 'group' => '_ContaoManager\Monolog\Handler\GroupHandler', 'buffer' => '_ContaoManager\Monolog\Handler\BufferHandler', 'deduplication' => '_ContaoManager\Monolog\Handler\DeduplicationHandler', 'rotating_file' => '_ContaoManager\Monolog\Handler\RotatingFileHandler', 'syslog' => '_ContaoManager\Monolog\Handler\SyslogHandler', 'syslogudp' => '_ContaoManager\Monolog\Handler\SyslogUdpHandler', 'null' => '_ContaoManager\Monolog\Handler\NullHandler', 'test' => '_ContaoManager\Monolog\Handler\TestHandler', 'gelf' => '_ContaoManager\Monolog\Handler\GelfHandler', 'rollbar' => '_ContaoManager\Monolog\Handler\RollbarHandler', 'flowdock' => '_ContaoManager\Monolog\Handler\FlowdockHandler', 'browser_console' => '_ContaoManager\Monolog\Handler\BrowserConsoleHandler', 'firephp' => '_ContaoManager\Symfony\Bridge\Monolog\Handler\FirePHPHandler', 'chromephp' => '_ContaoManager\Symfony\Bridge\Monolog\Handler\ChromePhpHandler', 'debug' => '_ContaoManager\Symfony\Bridge\Monolog\Handler\DebugHandler', 'swift_mailer' => '_ContaoManager\Symfony\Bridge\Monolog\Handler\SwiftMailerHandler', 'native_mailer' => '_ContaoManager\Monolog\Handler\NativeMailerHandler', 'symfony_mailer' => '_ContaoManager\Symfony\Bridge\Monolog\Handler\MailerHandler', 'socket' => '_ContaoManager\Monolog\Handler\SocketHandler', 'pushover' => '_ContaoManager\Monolog\Handler\PushoverHandler', 'raven' => '_ContaoManager\Monolog\Handler\RavenHandler', 'sentry' => '_ContaoManager\Sentry\Monolog\Handler', 'newrelic' => '_ContaoManager\Monolog\Handler\NewRelicHandler', 'hipchat' => '_ContaoManager\Monolog\Handler\HipChatHandler', 'slack' => '_ContaoManager\Monolog\Handler\SlackHandler', 'slackwebhook' => '_ContaoManager\Monolog\Handler\SlackWebhookHandler', 'slackbot' => '_ContaoManager\Monolog\Handler\SlackbotHandler', 'cube' => '_ContaoManager\Monolog\Handler\CubeHandler', 'amqp' => '_ContaoManager\Monolog\Handler\AmqpHandler', 'error_log' => '_ContaoManager\Monolog\Handler\ErrorLogHandler', 'loggly' => '_ContaoManager\Monolog\Handler\LogglyHandler', 'logentries' => '_ContaoManager\Monolog\Handler\LogEntriesHandler', 'whatfailuregroup' => '_ContaoManager\Monolog\Handler\WhatFailureGroupHandler', 'fingers_crossed' => '_ContaoManager\Monolog\Handler\FingersCrossedHandler', 'filter' => '_ContaoManager\Monolog\Handler\FilterHandler', 'mongo' => '_ContaoManager\Monolog\Handler\MongoDBHandler', 'mongodb' => '_ContaoManager\Monolog\Handler\MongoDBHandler', 'elasticsearch' => '_ContaoManager\Monolog\Handler\ElasticSearchHandler', 'telegram' => '_ContaoManager\Monolog\Handler\TelegramBotHandler', 'server_log' => '_ContaoManager\Symfony\Bridge\Monolog\Handler\ServerLogHandler', 'redis' => '_ContaoManager\Monolog\Handler\RedisHandler', 'predis' => '_ContaoManager\Monolog\Handler\RedisHandler', 'insightops' => '_ContaoManager\Monolog\Handler\InsightOpsHandler', 'sampling' => '_ContaoManager\Monolog\Handler\SamplingHandler'];
        $v2HandlerTypesAdded = ['elastica' => '_ContaoManager\Monolog\Handler\ElasticaHandler', 'elasticsearch' => '_ContaoManager\Monolog\Handler\ElasticaHandler', 'elastic_search' => '_ContaoManager\Monolog\Handler\ElasticsearchHandler', 'fallbackgroup' => '_ContaoManager\Monolog\Handler\FallbackGroupHandler', 'noop' => '_ContaoManager\Monolog\Handler\NoopHandler'];
        $v2HandlerTypesRemoved = ['hipchat', 'raven', 'slackbot'];
        $v3HandlerTypesRemoved = ['swift_mailer'];
        if (Logger::API >= 2) {
            $typeToClassMapping = array_merge($typeToClassMapping, $v2HandlerTypesAdded);
            foreach ($v2HandlerTypesRemoved as $v2HandlerTypeRemoved) {
                unset($typeToClassMapping[$v2HandlerTypeRemoved]);
            }
        }
        if (Logger::API >= 3) {
            foreach ($v3HandlerTypesRemoved as $v3HandlerTypeRemoved) {
                unset($typeToClassMapping[$v3HandlerTypeRemoved]);
            }
        }
        if (!isset($typeToClassMapping[$handlerType])) {
            if (Logger::API === 1 && \array_key_exists($handlerType, $v2HandlerTypesAdded)) {
                throw new \InvalidArgumentException(\sprintf('"%s" was added in Monolog v2, please upgrade if you wish to use it.', $handlerType));
            }
            if (Logger::API >= 2 && \array_key_exists($handlerType, $v2HandlerTypesRemoved)) {
                throw new \InvalidArgumentException(\sprintf('"%s" was removed in Monolog v2.', $handlerType));
            }
            if (Logger::API >= 3 && \array_key_exists($handlerType, $v3HandlerTypesRemoved)) {
                throw new \InvalidArgumentException(\sprintf('"%s" was removed in Monolog v3.', $handlerType));
            }
            throw new \InvalidArgumentException(\sprintf('There is no handler class defined for handler "%s".', $handlerType));
        }
        return $typeToClassMapping[$handlerType];
    }
    private function buildPsrLogMessageProcessor(ContainerBuilder $container, array $processorOptions): string
    {
        static $hasConstructorArguments;
        if (!isset($hasConstructorArguments)) {
            $reflectionConstructor = (new \ReflectionClass(PsrLogMessageProcessor::class))->getConstructor();
            $hasConstructorArguments = null !== $reflectionConstructor && $reflectionConstructor->getNumberOfParameters() > 0;
            unset($reflectionConstructor);
        }
        $processorId = 'monolog.processor.psr_log_message';
        $processorArguments = [];
        unset($processorOptions['enabled']);
        if (!empty($processorOptions)) {
            if (!$hasConstructorArguments) {
                throw new \RuntimeException('Monolog 1.26 or higher is required for the "date_format" and "remove_used_context_fields" options to be used.');
            }
            $processorArguments = [$processorOptions['date_format'] ?? null, $processorOptions['remove_used_context_fields'] ?? \false];
            $processorId .= '.' . ContainerBuilder::hash($processorArguments);
        }
        if (!$container->hasDefinition($processorId)) {
            $processor = new Definition(PsrLogMessageProcessor::class);
            $processor->setPublic(\false);
            $processor->setArguments($processorArguments);
            $container->setDefinition($processorId, $processor);
        }
        return $processorId;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Bundle\MonologBundle\DependencyInjection;

use Composer\InstalledVersions;
use _ContaoManager\Monolog\Logger;
use _ContaoManager\Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition;
use _ContaoManager\Symfony\Component\Config\Definition\Builder\TreeBuilder;
use _ContaoManager\Symfony\Component\Config\Definition\ConfigurationInterface;
use _ContaoManager\Symfony\Component\Config\Definition\Exception\InvalidConfigurationException;
/**
 * This class contains the configuration information for the bundle.
 *
 * This information is solely responsible for how the different configuration
 * sections are normalized, and merged.
 *
 * Possible handler types and related configurations (brackets indicate optional params):
 *
 * - service:
 *   - id
 *
 * - stream:
 *   - path: string
 *   - [level]: level name or int value, defaults to DEBUG
 *   - [bubble]: bool, defaults to true
 *   - [file_permission]: int|null, defaults to null (0644)
 *   - [use_locking]: bool, defaults to false
 *
 * - console:
 *   - [verbosity_levels]: level => verbosity configuration
 *   - [level]: level name or int value, defaults to DEBUG
 *   - [bubble]: bool, defaults to true
 *   - [console_formatter_options]: array
 *   - [interactive_only]: bool, defaults to false
 *
 * - firephp:
 *   - [level]: level name or int value, defaults to DEBUG
 *   - [bubble]: bool, defaults to true
 *
 * - browser_console:
 *   - [level]: level name or int value, defaults to DEBUG
 *   - [bubble]: bool, defaults to true
 *
 * - gelf:
 *   - publisher: (one of the following configurations)
 *     # Option 1: Service-based configuration
 *     - id: string, service id of a publisher implementation
 *
 *     # Option 2: Direct connection configuration
 *     - hostname: string, server hostname
 *     - [port]: int, server port (default: 12201)
 *     - [chunk_size]: int, UDP packet size (default: 1420)
 *     - [encoder]: string, encoding format ('json' or 'compressed_json')
 *   - [level]: level name or int value, defaults to DEBUG
 *   - [bubble]: bool, defaults to true
 *
 * - chromephp:
 *   - [level]: level name or int value, defaults to DEBUG
 *   - [bubble]: bool, defaults to true
 *
 * - rotating_file:
 *   - path: string
 *   - [max_files]: files to keep, defaults to zero (infinite)
 *   - [level]: level name or int value, defaults to DEBUG
 *   - [bubble]: bool, defaults to true
 *   - [file_permission]: int|null, defaults to null (0o644)
 *   - [use_locking]: bool, defaults to false
 *   - [filename_format]: string, defaults to '{filename}-{date}'
 *   - [date_format]: string, defaults to 'Y-m-d'
 *
 * - mongo:
 *   - mongo:
 *      - id: optional if host is given
 *      - host: database host name, optional if id is given
 *      - [port]: defaults to 27017
 *      - [user]: database user name
 *      - pass: mandatory only if user is present
 *      - [database]: defaults to monolog
 *      - [collection]: defaults to logs
 *   - [level]: level name or int value, defaults to DEBUG
 *   - [bubble]: bool, defaults to true
 *
 * - mongodb:
 *    - mongodb:
 *       - id: optional if uri is given
 *       - uri: MongoDB connection string, optional if id is given
 *       - [username]: Username for database authentication
 *       - [password]: Password for database authentication
 *       - [database]: Database to which logs are written (not used for auth), defaults to "monolog"
 *       - [collection]: Collection to which logs are written, defaults to "logs"
 *    - [level]: level name or int value, defaults to DEBUG
 *    - [bubble]: bool, defaults to true
 *
 * - elastic_search:
 *   - elasticsearch:
 *      - id: optional if host is given
 *      - host: elastic search host name, with scheme (e.g. "https://127.0.0.1:9200")
 *      - [user]: elastic search user name
 *      - [password]: elastic search user password
 *   - [index]: index name, defaults to monolog
 *   - [document_type]: document_type, defaults to logs
 *   - [level]: level name or int value, defaults to DEBUG
 *   - [bubble]: bool, defaults to true
 *
 * - elastica:
 *   - elasticsearch:
 *      - id: optional if host is given
 *      - host: elastic search host name. Do not prepend with http(s)://
 *      - [port]: defaults to 9200
 *      - [transport]: transport protocol (http by default)
 *      - [user]: elastic search user name
 *      - [password]: elastic search user password
 *   - [index]: index name, defaults to monolog
 *   - [document_type]: document_type, defaults to logs
 *   - [level]: level name or int value, defaults to DEBUG
 *   - [bubble]: bool, defaults to true
 *
 * - redis:
 *   - redis:
 *      - id: optional if host is given
 *      - host: 127.0.0.1
 *      - password: null
 *      - port: 6379
 *      - database: 0
 *      - key_name: monolog_redis
 *
 * - predis:
 *   - redis:
 *      - id: optional if host is given
 *      - host: tcp://10.0.0.1:6379
 *      - key_name: monolog_redis
 *
 * - fingers_crossed:
 *   - handler: the wrapped handler's name
 *   - [action_level|activation_strategy]: minimum level or service id to activate the handler, defaults to WARNING
 *   - [excluded_404s]: if set, the strategy will be changed to one that excludes 404s coming from URLs matching any of those patterns
 *   - [excluded_http_codes]: if set, the strategy will be changed to one that excludes specific HTTP codes (requires Symfony Monolog bridge 4.1+)
 *   - [buffer_size]: defaults to 0 (unlimited)
 *   - [stop_buffering]: bool to disable buffering once the handler has been activated, defaults to true
 *   - [passthru_level]: level name or int value for messages to always flush, disabled by default
 *   - [bubble]: bool, defaults to true
 *
 * - filter:
 *   - handler: the wrapped handler's name
 *   - [accepted_levels]: list of levels to accept
 *   - [min_level]: minimum level to accept (only used if accepted_levels not specified)
 *   - [max_level]: maximum level to accept (only used if accepted_levels not specified)
 *   - [bubble]: bool, defaults to true
 *
 * - buffer:
 *   - handler: the wrapped handler's name
 *   - [buffer_size]: defaults to 0 (unlimited)
 *   - [level]: level name or int value, defaults to DEBUG
 *   - [bubble]: bool, defaults to true
 *   - [flush_on_overflow]: bool, defaults to false
 *
 * - deduplication:
 *   - handler: the wrapped handler's name
 *   - [store]: The file/path where the deduplication log should be kept, defaults to %kernel.cache_dir%/monolog_dedup_*
 *   - [deduplication_level]: The minimum logging level for log records to be looked at for deduplication purposes, defaults to ERROR
 *   - [time]: The period (in seconds) during which duplicate entries should be suppressed after a given log is sent through, defaults to 60
 *   - [bubble]: bool, defaults to true
 *
 * - group:
 *   - members: the wrapped handlers by name
 *   - [bubble]: bool, defaults to true
 *
 * - whatfailuregroup:
 *   - members: the wrapped handlers by name
 *   - [bubble]: bool, defaults to true
 *
 * - fallbackgroup
 *   - members: the wrapped handlers by name
 *   - [bubble]: bool, defaults to true
 *
 * - syslog:
 *   - ident: string
 *   - [facility]: defaults to 'user', use any of the LOG_* facility constant but without LOG_ prefix, e.g. user for LOG_USER
 *   - [logopts]: defaults to LOG_PID
 *   - [level]: level name or int value, defaults to DEBUG
 *   - [bubble]: bool, defaults to true
 *
 * - syslogudp:
 *   - host: syslogd host name
 *   - [port]: defaults to 514
 *   - [facility]: defaults to 'user', use any of the LOG_* facility constant but without LOG_ prefix, e.g. user for LOG_USER
 *   - [logopts]: defaults to LOG_PID
 *   - [level]: level name or int value, defaults to DEBUG
 *   - [bubble]: bool, defaults to true
 *   - [ident]: string, defaults to
 *
 * - swift_mailer:
 *   - from_email: optional if email_prototype is given
 *   - to_email: optional if email_prototype is given
 *   - subject: optional if email_prototype is given
 *   - [email_prototype]: service id of a message, defaults to a default message with the three fields above
 *   - [content_type]: optional if email_prototype is given, defaults to text/plain
 *   - [mailer]: mailer service, defaults to mailer
 *   - [level]: level name or int value, defaults to DEBUG
 *   - [bubble]: bool, defaults to true
 *   - [lazy]: use service lazy loading, bool, defaults to true
 *
 * - native_mailer:
 *   - from_email: string
 *   - to_email: string
 *   - subject: string
 *   - [level]: level name or int value, defaults to DEBUG
 *   - [bubble]: bool, defaults to true
 *   - [headers]: optional array containing additional headers: ['Foo: Bar', '...']
 *
 * - symfony_mailer:
 *   - from_email: optional if email_prototype is given
 *   - to_email: optional if email_prototype is given
 *   - subject: optional if email_prototype is given
 *   - [email_prototype]: service id of a message, defaults to a default message with the three fields above
 *   - [mailer]: mailer service id, defaults to mailer.mailer
 *   - [level]: level name or int value, defaults to DEBUG
 *   - [bubble]: bool, defaults to true
 *
 * - socket:
 *   - connection_string: string
 *   - [timeout]: float
 *   - [connection_timeout]: float
 *   - [persistent]: bool
 *   - [level]: level name or int value, defaults to DEBUG
 *   - [bubble]: bool, defaults to true
 *
 * - pushover:
 *   - token: pushover api token
 *   - user: user id or array of ids
 *   - [title]: optional title for messages, defaults to the server hostname
 *   - [level]: level name or int value, defaults to DEBUG
 *   - [bubble]: bool, defaults to true
 *   - [timeout]: float
 *   - [connection_timeout]: float
 *
 * - raven / sentry:
 *   - dsn: connection string
 *   - client_id: Raven client custom service id (optional)
 *   - [release]: release number of the application that will be attached to logs, defaults to null
 *   - [level]: level name or int value, defaults to DEBUG
 *   - [bubble]: bool, defaults to true
 *   - [auto_log_stacks]: bool, defaults to false
 *   - [environment]: string, default to null (no env specified)
 *
 * - sentry:
 *   - hub_id: Sentry hub custom service id (optional)
 *   - [fill_extra_context]: bool, defaults to false
 *
 * - newrelic:
 *   - [level]: level name or int value, defaults to DEBUG
 *   - [bubble]: bool, defaults to true
 *   - [app_name]: new relic app name, default null
 *
 * - hipchat:
 *   - token: hipchat api token
 *   - room: room id or name
 *   - [notify]: defaults to false
 *   - [nickname]: defaults to Monolog
 *   - [level]: level name or int value, defaults to DEBUG
 *   - [bubble]: bool, defaults to true
 *   - [use_ssl]: bool, defaults to true
 *   - [message_format]: text or html, defaults to text
 *   - [host]: defaults to "api.hipchat.com"
 *   - [api_version]: defaults to "v1"
 *   - [timeout]: float
 *   - [connection_timeout]: float
 *
 * - slack:
 *   - token: slack api token
 *   - channel: channel name (with starting #)
 *   - [bot_name]: defaults to Monolog
 *   - [icon_emoji]: defaults to null
 *   - [use_attachment]: bool, defaults to true
 *   - [use_short_attachment]: bool, defaults to false
 *   - [include_extra]: bool, defaults to false
 *   - [level]: level name or int value, defaults to DEBUG
 *   - [bubble]: bool, defaults to true
 *   - [timeout]: float
 *   - [connection_timeout]: float
 *   - [exclude_fields]: list of excluded fields, defaults to empty array
 *
 * - slackwebhook:
 *   - webhook_url: slack webhook URL
 *   - channel: channel name (with starting #)
 *   - [bot_name]: defaults to Monolog
 *   - [icon_emoji]: defaults to null
 *   - [use_attachment]: bool, defaults to true
 *   - [use_short_attachment]: bool, defaults to false
 *   - [include_extra]: bool, defaults to false
 *   - [level]: level name or int value, defaults to DEBUG
 *   - [bubble]: bool, defaults to true
 *   - [exclude_fields]: list of excluded fields, defaults to empty array
 *
 * - slackbot:
 *   - team: slack team slug
 *   - token: slackbot token
 *   - channel: channel name (with starting #)
 *   - [level]: level name or int value, defaults to DEBUG
 *   - [bubble]: bool, defaults to true
 *
 * - cube:
 *   - url: http/udp url to the cube server
 *   - [level]: level name or int value, defaults to DEBUG
 *   - [bubble]: bool, defaults to true
 *
 * - amqp:
 *   - exchange: service id of an AMQPExchange
 *   - [exchange_name]: string, defaults to log
 *   - [level]: level name or int value, defaults to DEBUG
 *   - [bubble]: bool, defaults to true
 *
 * - error_log:
 *   - [message_type]: int 0 or 4, defaults to 0
 *   - [level]: level name or int value, defaults to DEBUG
 *   - [bubble]: bool, defaults to true
 *
 * - null:
 *   - [level]: level name or int value, defaults to DEBUG
 *   - [bubble]: bool, defaults to true
 *
 * - test:
 *   - [level]: level name or int value, defaults to DEBUG
 *   - [bubble]: bool, defaults to true
 *
 * - debug:
 *   - [level]: level name or int value, defaults to DEBUG
 *   - [bubble]: bool, defaults to true
 *
 * - loggly:
 *   - token: loggly api token
 *   - [level]: level name or int value, defaults to DEBUG
 *   - [bubble]: bool, defaults to true
 *   - [tags]: tag names
 *
 * - logentries:
 *   - token: logentries api token
 *   - [use_ssl]: whether or not SSL encryption should be used, defaults to true
 *   - [level]: level name or int value, defaults to DEBUG
 *   - [bubble]: bool, defaults to true
 *   - [timeout]: float
 *   - [connection_timeout]: float
 *
 * - insightops:
 *   - token: Log token supplied by InsightOps
 *   - region: Region where InsightOps account is hosted. Could be 'us' or 'eu'. Defaults to 'us'
 *   - [use_ssl]: whether or not SSL encryption should be used, defaults to true
 *   - [level]: level name or int value, defaults to DEBUG
 *   - [bubble]: bool, defaults to true
 *
 * - flowdock:
 *   - token: flowdock api token
 *   - source: human readable identifier of the application
 *   - from_email: email address of the message sender
 *   - [level]: level name or int value, defaults to DEBUG
 *   - [bubble]: bool, defaults to true
 *
 * - rollbar:
 *   - id: RollbarNotifier service (mandatory if token is not provided)
 *   - token: rollbar api token (skip if you provide a RollbarNotifier service id)
 *   - [config]: config values from https://github.com/rollbar/rollbar-php#configuration-reference
 *   - [level]: level name or int value, defaults to DEBUG
 *   - [bubble]: bool, defaults to true
 *
 * - server_log:
 *   - host: server log host. ex: 127.0.0.1:9911
 *   - [level]: level name or int value, defaults to DEBUG
 *   - [bubble]: bool, defaults to true
 *
 * - telegram:
 *   - token: Telegram bot access token provided by BotFather
 *   - channel: Telegram channel name
 *   - [level]: level name or int value, defaults to DEBUG
 *   - [bubble]: bool, defaults to true
 *   - [parse_mode]: optional the kind of formatting that is used for the message
 *   - [disable_webpage_preview]: bool, defaults to false, disables link previews for links in the message
 *   - [disable_notification]: bool, defaults to false, sends the message silently. Users will receive a notification with no sound
 *   - [split_long_messages]: bool, defaults to false, split messages longer than 4096 bytes into multiple messages
 *   - [delay_between_messages]: bool, defaults to false, adds a 1sec delay/sleep between sending split messages
 *   - [topic]: optional the unique identifier for the target message thread (topic) of the forum; for forum supergroups only
 *
 * - sampling:
 *   - handler: the wrapped handler's name
 *   - factor: the sampling factor (e.g. 10 means every ~10th record is sampled)
 *
 * All handlers can also be marked with `nested: true` to make sure they are never added explicitly to the stack
 *
 * @author Jordi Boggiano <j.boggiano@seld.be>
 * @author Christophe Coevoet <stof@notk.org>
 *
 * @final since 3.9.0
 */
class Configuration implements ConfigurationInterface
{
    /**
     * Generates the configuration tree builder.
     */
    public function getConfigTreeBuilder(): TreeBuilder
    {
        $treeBuilder = new TreeBuilder('monolog');
        $rootNode = $treeBuilder->getRootNode();
        $handlers = $rootNode->fixXmlConfig('channel')->fixXmlConfig('handler')->children()->scalarNode('use_microseconds')->defaultTrue()->end()->arrayNode('channels')->info('List of additional channels to create. The "app" channel is already created by default. Channels are also automatically created for services using the "monolog.logger" DI tag with a custom channel attribute.')->canBeUnset()->prototype('scalar')->end()->end()->arrayNode('handlers');
        $handlers->canBeUnset()->useAttributeAsKey('name')->validate()->ifTrue(function ($v) {
            return isset($v['debug']);
        })->thenInvalid('The "debug" name cannot be used as it is reserved for the handler of the profiler')->end()->example(['syslog' => ['type' => 'stream', 'path' => '/var/log/symfony.log', 'level' => 'ERROR', 'bubble' => 'false', 'formatter' => 'my_formatter'], 'main' => ['type' => 'fingers_crossed', 'action_level' => 'WARNING', 'buffer_size' => 30, 'handler' => 'custom'], 'custom' => ['type' => 'service', 'id' => 'my_handler']]);
        $handlerNode = $handlers->prototype('array')->fixXmlConfig('member')->fixXmlConfig('excluded_404')->fixXmlConfig('excluded_http_code')->fixXmlConfig('tag')->fixXmlConfig('accepted_level')->fixXmlConfig('header')->canBeUnset();
        $handlerNode->children()->scalarNode('type')->isRequired()->beforeNormalization()->ifString()->then(function ($v) {
            return strtolower($v);
        })->ifNull()->then(function ($v) {
            return 'null';
        })->end()->end()->scalarNode('id')->end()->booleanNode('enabled')->defaultTrue()->end()->scalarNode('priority')->defaultValue(0)->end()->scalarNode('level')->defaultValue('DEBUG')->end()->booleanNode('bubble')->defaultTrue()->end()->booleanNode('interactive_only')->defaultFalse()->end()->scalarNode('app_name')->defaultNull()->end()->booleanNode('fill_extra_context')->defaultFalse()->end()->booleanNode('include_stacktraces')->defaultFalse()->end()->arrayNode('process_psr_3_messages')->addDefaultsIfNotSet()->beforeNormalization()->ifTrue(static function ($v) {
            return !\is_array($v);
        })->then(static function ($v) {
            return ['enabled' => $v];
        })->end()->children()->booleanNode('enabled')->defaultNull()->end()->scalarNode('date_format')->end()->booleanNode('remove_used_context_fields')->end()->end()->end()->scalarNode('path')->defaultValue('%kernel.logs_dir%/%kernel.environment%.log')->end()->scalarNode('file_permission')->defaultNull()->beforeNormalization()->ifString()->then(function ($v) {
            if ('0' === substr($v, 0, 1)) {
                return octdec($v);
            }
            return (int) $v;
        })->end()->end()->booleanNode('use_locking')->defaultFalse()->end()->scalarNode('filename_format')->defaultValue('{filename}-{date}')->end()->scalarNode('date_format')->defaultValue('Y-m-d')->end()->scalarNode('ident')->defaultFalse()->end()->scalarNode('logopts')->defaultValue(\LOG_PID)->end()->scalarNode('facility')->defaultValue('user')->end()->scalarNode('max_files')->defaultValue(0)->end()->scalarNode('action_level')->defaultValue('WARNING')->end()->scalarNode('activation_strategy')->defaultNull()->end()->booleanNode('stop_buffering')->defaultTrue()->end()->scalarNode('passthru_level')->defaultNull()->end()->arrayNode('excluded_404s')->canBeUnset()->prototype('scalar')->end()->end()->arrayNode('excluded_http_codes')->info('Only for "fingers_crossed" handler type')->example([403, 404, [400 => ['^/foo', '^/bar']]])->canBeUnset()->beforeNormalization()->always(function ($values) {
            if (\false === $values) {
                return \false;
            }
            return array_map(function ($value) {
                /*
                 * Allows YAML:
                 *   excluded_http_codes: [403, 404, { 400: ['^/foo', '^/bar'] }]
                 *
                 * and XML:
                 *   <monolog:excluded-http-code code="403">
                 *     <monolog:url>^/foo</monolog:url>
                 *     <monolog:url>^/bar</monolog:url>
                 *   </monolog:excluded-http-code>
                 *   <monolog:excluded-http-code code="404" />
                 */
                if (\is_array($value)) {
                    return isset($value['code']) ? $value : ['code' => key($value), 'urls' => current($value)];
                }
                return ['code' => $value, 'urls' => []];
            }, $values);
        })->end()->prototype('array')->children()->scalarNode('code')->end()->arrayNode('urls')->prototype('scalar')->end()->end()->end()->end()->end()->arrayNode('accepted_levels')->canBeUnset()->prototype('scalar')->end()->end()->scalarNode('min_level')->defaultValue('DEBUG')->end()->scalarNode('max_level')->defaultValue('EMERGENCY')->end()->scalarNode('buffer_size')->defaultValue(0)->end()->booleanNode('flush_on_overflow')->defaultFalse()->end()->scalarNode('handler')->end()->scalarNode('url')->end()->scalarNode('exchange')->end()->scalarNode('exchange_name')->defaultValue('log')->end()->scalarNode('room')->end()->scalarNode('message_format')->defaultValue('text')->end()->scalarNode('api_version')->defaultNull()->end()->scalarNode('channel')->defaultNull()->end()->scalarNode('bot_name')->defaultValue('Monolog')->end()->scalarNode('use_attachment')->defaultTrue()->end()->scalarNode('use_short_attachment')->defaultFalse()->end()->scalarNode('include_extra')->defaultFalse()->end()->scalarNode('icon_emoji')->defaultNull()->end()->scalarNode('webhook_url')->end()->arrayNode('exclude_fields')->canBeUnset()->prototype('scalar')->end()->end()->scalarNode('team')->end()->scalarNode('notify')->defaultFalse()->end()->scalarNode('nickname')->defaultValue('Monolog')->end()->scalarNode('token')->end()->scalarNode('region')->end()->scalarNode('source')->end()->booleanNode('use_ssl')->defaultTrue()->end()->variableNode('user')->validate()->ifTrue(function ($v) {
            return !\is_string($v) && !\is_array($v);
        })->thenInvalid('User must be a string or an array.')->end()->end()->scalarNode('title')->defaultNull()->end()->scalarNode('host')->defaultNull()->end()->scalarNode('port')->defaultValue(514)->end()->arrayNode('config')->canBeUnset()->prototype('scalar')->end()->end()->arrayNode('members')->canBeUnset()->performNoDeepMerging()->prototype('scalar')->end()->end()->scalarNode('connection_string')->end()->scalarNode('timeout')->end()->scalarNode('time')->defaultValue(60)->end()->scalarNode('deduplication_level')->defaultValue(Logger::ERROR)->end()->scalarNode('store')->defaultNull()->end()->scalarNode('connection_timeout')->end()->booleanNode('persistent')->end()->scalarNode('dsn')->end()->scalarNode('hub_id')->defaultNull()->end()->scalarNode('client_id')->defaultNull()->end()->scalarNode('auto_log_stacks')->defaultFalse()->end()->scalarNode('release')->defaultNull()->end()->scalarNode('environment')->defaultNull()->end()->scalarNode('message_type')->defaultValue(0)->end()->scalarNode('parse_mode')->defaultNull()->end()->booleanNode('disable_webpage_preview')->defaultNull()->end()->booleanNode('disable_notification')->defaultNull()->end()->booleanNode('split_long_messages')->defaultFalse()->end()->booleanNode('delay_between_messages')->defaultFalse()->end()->integerNode('topic')->defaultNull()->end()->integerNode('factor')->defaultValue(1)->min(1)->end()->arrayNode('tags')->beforeNormalization()->ifString()->then(function ($v) {
            return explode(',', $v);
        })->end()->beforeNormalization()->ifArray()->then(function ($v) {
            return array_filter(array_map('trim', $v));
        })->end()->prototype('scalar')->end()->end()->variableNode('console_formater_options')->setDeprecated('symfony/monolog-bundle', 3.7, '"%path%.%node%" is deprecated, use "%path%.console_formatter_options" instead.')->validate()->ifTrue(function ($v) {
            return !\is_array($v);
        })->thenInvalid('The console_formater_options must be an array.')->end()->end()->variableNode('console_formatter_options')->defaultValue([])->validate()->ifTrue(static function ($v) {
            return !\is_array($v);
        })->thenInvalid('The console_formatter_options must be an array.')->end()->end()->scalarNode('formatter')->end()->booleanNode('nested')->defaultFalse()->end()->end();
        $this->addGelfSection($handlerNode);
        $this->addMongoSection($handlerNode);
        $this->addMongoDBSection($handlerNode);
        $this->addElasticsearchSection($handlerNode);
        $this->addRedisSection($handlerNode);
        $this->addPredisSection($handlerNode);
        $this->addMailerSection($handlerNode);
        $this->addVerbosityLevelSection($handlerNode);
        $this->addChannelsSection($handlerNode);
        $handlerNode->beforeNormalization()->always(static function ($v) {
            if (empty($v['console_formatter_options']) && !empty($v['console_formater_options'])) {
                $v['console_formatter_options'] = $v['console_formater_options'];
            }
            return $v;
        })->end()->validate()->always(static function ($v) {
            unset($v['console_formater_options']);
            return $v;
        })->end()->validate()->ifTrue(function ($v) {
            return 'service' === $v['type'] && !empty($v['formatter']);
        })->thenInvalid('Service handlers can not have a formatter configured in the bundle, you must reconfigure the service itself instead')->end()->validate()->ifTrue(function ($v) {
            return \in_array($v['type'], ['fingers_crossed', 'buffer', 'filter', 'deduplication', 'sampling'], \true) && empty($v['handler']);
        })->thenInvalid('The handler has to be specified to use a FingersCrossedHandler, BufferHandler, FilterHandler, DeduplicationHandler or SamplingHandler')->end()->validate()->ifTrue(function ($v) {
            return 'fingers_crossed' === $v['type'] && !empty($v['excluded_404s']) && !empty($v['activation_strategy']);
        })->thenInvalid('You can not use excluded_404s together with a custom activation_strategy in a FingersCrossedHandler')->end()->validate()->ifTrue(function ($v) {
            return 'fingers_crossed' === $v['type'] && !empty($v['excluded_http_codes']) && !empty($v['activation_strategy']);
        })->thenInvalid('You can not use excluded_http_codes together with a custom activation_strategy in a FingersCrossedHandler')->end()->validate()->ifTrue(function ($v) {
            return 'fingers_crossed' === $v['type'] && !empty($v['excluded_http_codes']) && !empty($v['excluded_404s']);
        })->thenInvalid('You can not use excluded_http_codes together with excluded_404s in a FingersCrossedHandler')->end()->validate()->ifTrue(function ($v) {
            return 'fingers_crossed' !== $v['type'] && (!empty($v['excluded_http_codes']) || !empty($v['excluded_404s']));
        })->thenInvalid('You can only use excluded_http_codes/excluded_404s with a FingersCrossedHandler definition')->end()->validate()->ifTrue(function ($v) {
            return 'filter' === $v['type'] && 'DEBUG' !== $v['min_level'] && !empty($v['accepted_levels']);
        })->thenInvalid('You can not use min_level together with accepted_levels in a FilterHandler')->end()->validate()->ifTrue(function ($v) {
            return 'filter' === $v['type'] && 'EMERGENCY' !== $v['max_level'] && !empty($v['accepted_levels']);
        })->thenInvalid('You can not use max_level together with accepted_levels in a FilterHandler')->end()->validate()->ifTrue(function ($v) {
            return 'rollbar' === $v['type'] && !empty($v['id']) && !empty($v['token']);
        })->thenInvalid('You can not use both an id and a token in a RollbarHandler')->end()->validate()->ifTrue(function ($v) {
            return 'rollbar' === $v['type'] && empty($v['id']) && empty($v['token']);
        })->thenInvalid('The id or the token has to be specified to use a RollbarHandler')->end()->validate()->ifTrue(function ($v) {
            return 'telegram' === $v['type'] && (empty($v['token']) || empty($v['channel']));
        })->thenInvalid('The token and channel have to be specified to use a TelegramBotHandler')->end()->validate()->ifTrue(function ($v) {
            return 'service' === $v['type'] && !isset($v['id']);
        })->thenInvalid('The id has to be specified to use a service as handler')->end()->validate()->ifTrue(function ($v) {
            return 'syslogudp' === $v['type'] && !isset($v['host']);
        })->thenInvalid('The host has to be specified to use a syslogudp as handler')->end()->validate()->ifTrue(function ($v) {
            return 'socket' === $v['type'] && !isset($v['connection_string']);
        })->thenInvalid('The connection_string has to be specified to use a SocketHandler')->end()->validate()->ifTrue(function ($v) {
            return 'pushover' === $v['type'] && (empty($v['token']) || empty($v['user']));
        })->thenInvalid('The token and user have to be specified to use a PushoverHandler')->end()->validate()->ifTrue(function ($v) {
            return 'raven' === $v['type'] && !\array_key_exists('dsn', $v) && null === $v['client_id'];
        })->thenInvalid('The DSN has to be specified to use a RavenHandler')->end()->validate()->ifTrue(function ($v) {
            return 'sentry' === $v['type'] && !\array_key_exists('dsn', $v) && null === $v['hub_id'] && null === $v['client_id'];
        })->thenInvalid('The DSN has to be specified to use Sentry\'s handler')->end()->validate()->ifTrue(function ($v) {
            return 'sentry' === $v['type'] && null !== $v['hub_id'] && null !== $v['client_id'];
        })->thenInvalid('You can not use both a hub_id and a client_id in a Sentry handler')->end()->validate()->ifTrue(function ($v) {
            return 'hipchat' === $v['type'] && (empty($v['token']) || empty($v['room']));
        })->thenInvalid('The token and room have to be specified to use a HipChatHandler')->end()->validate()->ifTrue(function ($v) {
            return 'hipchat' === $v['type'] && !\in_array($v['message_format'], ['text', 'html']);
        })->thenInvalid('The message_format has to be "text" or "html" in a HipChatHandler')->end()->validate()->ifTrue(function ($v) {
            return 'hipchat' === $v['type'] && null !== $v['api_version'] && !\in_array($v['api_version'], ['v1', 'v2'], \true);
        })->thenInvalid('The api_version has to be "v1" or "v2" in a HipChatHandler')->end()->validate()->ifTrue(function ($v) {
            return 'slack' === $v['type'] && (empty($v['token']) || empty($v['channel']));
        })->thenInvalid('The token and channel have to be specified to use a SlackHandler')->end()->validate()->ifTrue(function ($v) {
            return 'slackwebhook' === $v['type'] && empty($v['webhook_url']);
        })->thenInvalid('The webhook_url have to be specified to use a SlackWebhookHandler')->end()->validate()->ifTrue(function ($v) {
            return 'slackbot' === $v['type'] && (empty($v['team']) || empty($v['token']) || empty($v['channel']));
        })->thenInvalid('The team, token and channel have to be specified to use a SlackbotHandler')->end()->validate()->ifTrue(function ($v) {
            return 'cube' === $v['type'] && empty($v['url']);
        })->thenInvalid('The url has to be specified to use a CubeHandler')->end()->validate()->ifTrue(function ($v) {
            return 'amqp' === $v['type'] && empty($v['exchange']);
        })->thenInvalid('The exchange has to be specified to use a AmqpHandler')->end()->validate()->ifTrue(function ($v) {
            return 'loggly' === $v['type'] && empty($v['token']);
        })->thenInvalid('The token has to be specified to use a LogglyHandler')->end()->validate()->ifTrue(function ($v) {
            return 'loggly' === $v['type'] && !empty($v['tags']);
        })->then(function ($v) {
            $invalidTags = preg_grep('/^[a-z0-9][a-z0-9\.\-_]*$/i', $v['tags'], \PREG_GREP_INVERT);
            if (!empty($invalidTags)) {
                throw new InvalidConfigurationException(\sprintf('The following Loggly tags are invalid: "%s".', implode('", "', $invalidTags)));
            }
            return $v;
        })->end()->validate()->ifTrue(function ($v) {
            return 'logentries' === $v['type'] && empty($v['token']);
        })->thenInvalid('The token has to be specified to use a LogEntriesHandler')->end()->validate()->ifTrue(function ($v) {
            return 'insightops' === $v['type'] && empty($v['token']);
        })->thenInvalid('The token has to be specified to use a InsightOpsHandler')->end()->validate()->ifTrue(function ($v) {
            return 'flowdock' === $v['type'] && empty($v['token']);
        })->thenInvalid('The token has to be specified to use a FlowdockHandler')->end()->validate()->ifTrue(function ($v) {
            return 'flowdock' === $v['type'] && empty($v['from_email']);
        })->thenInvalid('The from_email has to be specified to use a FlowdockHandler')->end()->validate()->ifTrue(function ($v) {
            return 'flowdock' === $v['type'] && empty($v['source']);
        })->thenInvalid('The source has to be specified to use a FlowdockHandler')->end()->validate()->ifTrue(function ($v) {
            return 'server_log' === $v['type'] && empty($v['host']);
        })->thenInvalid('The host has to be specified to use a ServerLogHandler')->end()->validate()->ifTrue(function ($v) {
            return $v['interactive_only'] && version_compare(InstalledVersions::getVersion('symfony/monolog-bridge'), '7.4.0', '<');
        })->thenInvalid('The interactive_only flag requires symfony/monolog-bridge 7.4 or higher')->end();
        return $treeBuilder;
    }
    private function addGelfSection(ArrayNodeDefinition $handlerNode)
    {
        $handlerNode->children()->arrayNode('publisher')->canBeUnset()->beforeNormalization()->ifString()->then(function ($v) {
            return ['id' => $v];
        })->end()->children()->scalarNode('id')->end()->scalarNode('hostname')->end()->scalarNode('port')->defaultValue(12201)->end()->scalarNode('chunk_size')->defaultValue(1420)->end()->enumNode('encoder')->values(['json', 'compressed_json'])->end()->end()->validate()->ifTrue(function ($v) {
            return !isset($v['id']) && !isset($v['hostname']);
        })->thenInvalid('What must be set is either the hostname or the id.')->end()->end()->end()->validate()->ifTrue(function ($v) {
            return 'gelf' === $v['type'] && !isset($v['publisher']);
        })->thenInvalid('The publisher has to be specified to use a GelfHandler')->end();
    }
    private function addMongoSection(ArrayNodeDefinition $handlerNode)
    {
        $handlerNode->children()->arrayNode('mongo')->canBeUnset()->beforeNormalization()->ifString()->then(function ($v) {
            return ['id' => $v];
        })->end()->children()->scalarNode('id')->end()->scalarNode('host')->end()->scalarNode('port')->defaultValue(27017)->end()->scalarNode('user')->end()->scalarNode('pass')->end()->scalarNode('database')->defaultValue('monolog')->end()->scalarNode('collection')->defaultValue('logs')->end()->end()->validate()->ifTrue(function ($v) {
            return !isset($v['id']) && !isset($v['host']);
        })->thenInvalid('The "mongo" handler configuration requires either a service "id" or a connection "host".')->end()->validate()->ifTrue(function ($v) {
            return isset($v['user']) && !isset($v['pass']);
        })->thenInvalid('If you set user, you must provide a password.')->end()->end()->end()->validate()->ifTrue(function ($v) {
            return 'mongo' === $v['type'] && !isset($v['mongo']);
        })->thenInvalid('The "mongo" configuration has to be specified to use a "mongo" handler type.')->end();
    }
    private function addMongoDBSection(ArrayNodeDefinition $handlerNode)
    {
        $handlerNode->children()->arrayNode('mongodb')->canBeUnset()->beforeNormalization()->ifString()->then(function ($v) {
            return ['id' => $v];
        })->end()->children()->scalarNode('id')->info('ID of a MongoDB\Client service')->example('doctrine_mongodb.odm.logs_connection')->end()->scalarNode('uri')->end()->scalarNode('username')->end()->scalarNode('password')->end()->scalarNode('database')->defaultValue('monolog')->end()->scalarNode('collection')->defaultValue('logs')->end()->end()->validate()->ifTrue(function ($v) {
            return !isset($v['id']) && !isset($v['uri']);
        })->thenInvalid('The "mongodb" handler configuration requires either a service "id" or a connection "uri".')->end()->end()->end()->validate()->ifTrue(function ($v) {
            return 'mongodb' === $v['type'] && !isset($v['mongodb']);
        })->thenInvalid('The "mongodb" configuration has to be specified to use a "mongodb" handler type.')->end();
    }
    private function addElasticsearchSection(ArrayNodeDefinition $handlerNode)
    {
        $handlerNode->children()->arrayNode('elasticsearch')->canBeUnset()->beforeNormalization()->ifString()->then(function ($v) {
            return ['id' => $v];
        })->end()->children()->scalarNode('id')->end()->arrayNode('hosts')->prototype('scalar')->end()->end()->scalarNode('host')->end()->scalarNode('port')->defaultValue(9200)->end()->scalarNode('transport')->defaultValue('Http')->end()->scalarNode('user')->defaultNull()->end()->scalarNode('password')->defaultNull()->end()->end()->validate()->ifTrue(function ($v) {
            return !isset($v['id']) && !isset($v['host']) && !isset($v['hosts']);
        })->thenInvalid('What must be set is either the host or the id.')->end()->end()->scalarNode('index')->defaultValue('monolog')->end()->scalarNode('document_type')->defaultValue('logs')->end()->scalarNode('ignore_error')->defaultValue(\false)->end()->end();
    }
    private function addRedisSection(ArrayNodeDefinition $handlerNode)
    {
        $handlerNode->children()->arrayNode('redis')->canBeUnset()->beforeNormalization()->ifString()->then(function ($v) {
            return ['id' => $v];
        })->end()->children()->scalarNode('id')->end()->scalarNode('host')->end()->scalarNode('password')->defaultNull()->end()->scalarNode('port')->defaultValue(6379)->end()->scalarNode('database')->defaultValue(0)->end()->scalarNode('key_name')->defaultValue('monolog_redis')->end()->end()->validate()->ifTrue(function ($v) {
            return !isset($v['id']) && !isset($v['host']);
        })->thenInvalid('What must be set is either the host or the service id of the Redis client.')->end()->end()->end()->validate()->ifTrue(function ($v) {
            return 'redis' === $v['type'] && empty($v['redis']);
        })->thenInvalid('The host has to be specified to use a RedisLogHandler')->end();
    }
    private function addPredisSection(ArrayNodeDefinition $handlerNode)
    {
        $handlerNode->children()->arrayNode('predis')->canBeUnset()->beforeNormalization()->ifString()->then(function ($v) {
            return ['id' => $v];
        })->end()->children()->scalarNode('id')->end()->scalarNode('host')->end()->end()->validate()->ifTrue(function ($v) {
            return !isset($v['id']) && !isset($v['host']);
        })->thenInvalid('What must be set is either the host or the service id of the Predis client.')->end()->end()->end()->validate()->ifTrue(function ($v) {
            return 'predis' === $v['type'] && empty($v['redis']);
        })->thenInvalid('The host has to be specified to use a RedisLogHandler')->end();
    }
    private function addMailerSection(ArrayNodeDefinition $handlerNode)
    {
        $handlerNode->children()->scalarNode('from_email')->end()->arrayNode('to_email')->prototype('scalar')->end()->beforeNormalization()->ifString()->then(function ($v) {
            return [$v];
        })->end()->end()->scalarNode('subject')->end()->scalarNode('content_type')->defaultNull()->end()->arrayNode('headers')->canBeUnset()->scalarPrototype()->end()->end()->scalarNode('mailer')->defaultNull()->end()->arrayNode('email_prototype')->canBeUnset()->beforeNormalization()->ifString()->then(function ($v) {
            return ['id' => $v];
        })->end()->children()->scalarNode('id')->isRequired()->end()->scalarNode('method')->defaultNull()->end()->end()->end()->booleanNode('lazy')->defaultValue(\true)->end()->end()->validate()->ifTrue(function ($v) {
            return 'swift_mailer' === $v['type'] && empty($v['email_prototype']) && (empty($v['from_email']) || empty($v['to_email']) || empty($v['subject']));
        })->thenInvalid('The sender, recipient and subject or an email prototype have to be specified to use a SwiftMailerHandler')->end()->validate()->ifTrue(function ($v) {
            return 'native_mailer' === $v['type'] && (empty($v['from_email']) || empty($v['to_email']) || empty($v['subject']));
        })->thenInvalid('The sender, recipient and subject have to be specified to use a NativeMailerHandler')->end()->validate()->ifTrue(function ($v) {
            return 'symfony_mailer' === $v['type'] && empty($v['email_prototype']) && (empty($v['from_email']) || empty($v['to_email']) || empty($v['subject']));
        })->thenInvalid('The sender, recipient and subject or an email prototype have to be specified to use the Symfony MailerHandler')->end();
    }
    private function addVerbosityLevelSection(ArrayNodeDefinition $handlerNode)
    {
        $handlerNode->children()->arrayNode('verbosity_levels')->beforeNormalization()->ifArray()->then(function ($v) {
            $map = [];
            $verbosities = ['VERBOSITY_QUIET', 'VERBOSITY_NORMAL', 'VERBOSITY_VERBOSE', 'VERBOSITY_VERY_VERBOSE', 'VERBOSITY_DEBUG'];
            // allow numeric indexed array with ascendning verbosity and lowercase names of the constants
            foreach ($v as $verbosity => $level) {
                if (\is_int($verbosity) && isset($verbosities[$verbosity])) {
                    $map[$verbosities[$verbosity]] = strtoupper($level);
                } else {
                    $map[strtoupper($verbosity)] = strtoupper($level);
                }
            }
            return $map;
        })->end()->children()->scalarNode('VERBOSITY_QUIET')->defaultValue('ERROR')->end()->scalarNode('VERBOSITY_NORMAL')->defaultValue('WARNING')->end()->scalarNode('VERBOSITY_VERBOSE')->defaultValue('NOTICE')->end()->scalarNode('VERBOSITY_VERY_VERBOSE')->defaultValue('INFO')->end()->scalarNode('VERBOSITY_DEBUG')->defaultValue('DEBUG')->end()->end()->validate()->always(function ($v) {
            $map = [];
            foreach ($v as $verbosity => $level) {
                $verbosityConstant = 'Symfony\Component\Console\Output\OutputInterface::' . $verbosity;
                if (!\defined($verbosityConstant)) {
                    throw new InvalidConfigurationException(\sprintf('The configured verbosity "%s" is invalid as it is not defined in Symfony\Component\Console\Output\OutputInterface.', $verbosity));
                }
                try {
                    if (Logger::API === 3) {
                        $level = Logger::toMonologLevel($level)->value;
                    } else {
                        $level = Logger::toMonologLevel(is_numeric($level) ? (int) $level : $level);
                    }
                } catch (\_ContaoManager\Psr\Log\InvalidArgumentException $e) {
                    throw new InvalidConfigurationException(\sprintf('The configured minimum log level "%s" for verbosity "%s" is invalid as it is not defined in Monolog\Logger.', $level, $verbosity));
                }
                $map[\constant($verbosityConstant)] = $level;
            }
            return $map;
        })->end()->end()->end();
    }
    private function addChannelsSection(ArrayNodeDefinition $handlerNode)
    {
        $handlerNode->children()->arrayNode('channels')->fixXmlConfig('channel', 'elements')->canBeUnset()->beforeNormalization()->ifString()->then(function ($v) {
            return ['elements' => [$v]];
        })->end()->beforeNormalization()->ifTrue(function ($v) {
            return \is_array($v) && is_numeric(key($v));
        })->then(function ($v) {
            return ['elements' => $v];
        })->end()->validate()->ifTrue(function ($v) {
            return empty($v);
        })->thenUnset()->end()->validate()->always(function ($v) {
            $isExclusive = null;
            if (isset($v['type'])) {
                $isExclusive = 'exclusive' === $v['type'];
            }
            $elements = [];
            foreach ($v['elements'] as $element) {
                if (0 === strpos($element, '!')) {
                    if (\false === $isExclusive) {
                        throw new InvalidConfigurationException('Cannot combine exclusive/inclusive definitions in channels list.');
                    }
                    $elements[] = substr($element, 1);
                    $isExclusive = \true;
                } else {
                    if (\true === $isExclusive) {
                        throw new InvalidConfigurationException('Cannot combine exclusive/inclusive definitions in channels list.');
                    }
                    $elements[] = $element;
                    $isExclusive = \false;
                }
            }
            if (!\count($elements)) {
                return null;
            }
            // de-duplicating $elements here in case the handlers are redefined, see https://github.com/symfony/monolog-bundle/issues/433
            return ['type' => $isExclusive ? 'exclusive' : 'inclusive', 'elements' => array_unique($elements)];
        })->end()->children()->scalarNode('type')->validate()->ifNotInArray(['inclusive', 'exclusive'])->thenInvalid('The type of channels has to be inclusive or exclusive')->end()->end()->arrayNode('elements')->prototype('scalar')->end()->end()->end()->end()->end();
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Bundle\MonologBundle\DependencyInjection\Compiler;

use _ContaoManager\Symfony\Component\DependencyInjection\Argument\TaggedIteratorArgument;
use _ContaoManager\Symfony\Component\DependencyInjection\ChildDefinition;
use _ContaoManager\Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Compiler\PriorityTaggedServiceTrait;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerBuilder;
/**
 * Registers processors in Monolog loggers or handlers.
 *
 * @author Christophe Coevoet <stof@notk.org>
 *
 * @internal since 3.9.0
 */
class AddProcessorsPass implements CompilerPassInterface
{
    use PriorityTaggedServiceTrait;
    public function process(ContainerBuilder $container)
    {
        if (!$container->hasDefinition('monolog.logger')) {
            return;
        }
        $indexedTags = [];
        $i = 1;
        foreach ($container->findTaggedServiceIds('monolog.processor') as $id => $tags) {
            if (array_any($tags, $closure = function (array $tag) {
                return (bool) $tag;
            })) {
                $tags = array_values(array_filter($tags, $closure));
            }
            foreach ($tags as &$tag) {
                $indexedTags[$tag['index'] = $i++] = $tag;
            }
            unset($tag);
            $definition = $container->getDefinition($id);
            $definition->setTags(array_merge($definition->getTags(), ['monolog.processor' => $tags]));
        }
        $taggedIteratorArgument = new TaggedIteratorArgument('monolog.processor', 'index', null, \true);
        // array_reverse is used because ProcessableHandlerTrait::pushProcessor prepends processors to the beginning of the stack
        foreach (array_reverse($this->findAndSortTaggedServices($taggedIteratorArgument, $container), \true) as $index => $reference) {
            $tag = $indexedTags[$index];
            if (!empty($tag['channel']) && !empty($tag['handler'])) {
                throw new \InvalidArgumentException(\sprintf('You cannot specify both the "handler" and "channel" attributes for the "monolog.processor" tag on service "%s".', $reference));
            }
            if (!empty($tag['handler'])) {
                $parentDef = $container->findDefinition(\sprintf('monolog.handler.%s', $tag['handler']));
                $definitions = [$parentDef];
                while (!$parentDef->getClass() && $parentDef instanceof ChildDefinition) {
                    $parentDef = $container->findDefinition($parentDef->getParent());
                }
                $class = $container->getParameterBag()->resolveValue($parentDef->getClass());
                if (!method_exists($class, 'pushProcessor')) {
                    throw new \InvalidArgumentException(\sprintf('The "%s" handler does not accept processors.', $tag['handler']));
                }
            } elseif (!empty($tag['channel'])) {
                $loggerId = 'app' === $tag['channel'] ? 'monolog.logger' : \sprintf('monolog.logger.%s', $tag['channel']);
                $definitions = [$container->getDefinition($loggerId)];
            } elseif ($loggerIds = $container->findTaggedServiceIds('monolog.channel_logger')) {
                $definitions = [];
                foreach ($loggerIds as $loggerId => $tags) {
                    $definitions[] = $container->getDefinition($loggerId);
                }
            } else {
                $definitions = [$container->getDefinition('monolog.logger_prototype')];
            }
            if (!empty($tag['method'])) {
                $processor = [$reference, $tag['method']];
            } else {
                // If no method is defined, fallback to use __invoke
                $processor = $reference;
            }
            foreach ($definitions as $definition) {
                $definition->addMethodCall('pushProcessor', [$processor]);
            }
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Bundle\MonologBundle\DependencyInjection\Compiler;

use _ContaoManager\Psr\Log\LoggerInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Argument\BoundArgument;
use _ContaoManager\Symfony\Component\DependencyInjection\ChildDefinition;
use _ContaoManager\Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerBuilder;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
use _ContaoManager\Symfony\Component\DependencyInjection\Reference;
/**
 * Replaces the default logger by another one with its own channel for tagged services.
 *
 * @author Christophe Coevoet <stof@notk.org>
 *
 * @internal since 3.9.0
 */
class LoggerChannelPass implements CompilerPassInterface
{
    protected $channels = ['app'];
    public function process(ContainerBuilder $container)
    {
        if (!$container->hasDefinition('monolog.logger')) {
            return;
        }
        // create channels necessary for the handlers
        foreach ($container->findTaggedServiceIds('monolog.logger') as $id => $tags) {
            foreach ($tags as $tag) {
                if (empty($tag['channel']) || 'app' === $tag['channel']) {
                    continue;
                }
                $resolvedChannel = $container->getParameterBag()->resolveValue($tag['channel']);
                $definition = $container->getDefinition($id);
                $loggerId = \sprintf('monolog.logger.%s', $resolvedChannel);
                $this->createLogger($resolvedChannel, $loggerId, $container);
                foreach ($definition->getArguments() as $index => $argument) {
                    if ($argument instanceof Reference && 'logger' === (string) $argument) {
                        $definition->replaceArgument($index, $this->changeReference($argument, $loggerId));
                    }
                }
                $calls = $definition->getMethodCalls();
                foreach ($calls as $i => $call) {
                    foreach ($call[1] as $index => $argument) {
                        if ($argument instanceof Reference && 'logger' === (string) $argument) {
                            $calls[$i][1][$index] = $this->changeReference($argument, $loggerId);
                        }
                    }
                }
                $definition->setMethodCalls($calls);
                $binding = new BoundArgument(new Reference($loggerId));
                // Mark the binding as used already, to avoid reporting it as unused if the service does not use a
                // logger injected through the LoggerInterface alias.
                $values = $binding->getValues();
                $values[2] = \true;
                $binding->setValues($values);
                $bindings = $definition->getBindings();
                $bindings['Psr\Log\LoggerInterface'] = $binding;
                $definition->setBindings($bindings);
            }
        }
        // create additional channels
        foreach ($container->getParameter('monolog.additional_channels') as $chan) {
            if ('app' === $chan) {
                continue;
            }
            $loggerId = \sprintf('monolog.logger.%s', $chan);
            $this->createLogger($chan, $loggerId, $container);
            $container->getDefinition($loggerId)->setPublic(\true);
        }
        $container->getParameterBag()->remove('monolog.additional_channels');
        // wire handlers to channels
        $handlersToChannels = $container->getParameter('monolog.handlers_to_channels');
        foreach ($handlersToChannels as $handler => $channels) {
            foreach ($this->processChannels($channels) as $channel) {
                try {
                    $logger = $container->getDefinition('app' === $channel ? 'monolog.logger' : 'monolog.logger.' . $channel);
                } catch (InvalidArgumentException $e) {
                    throw new \InvalidArgumentException(\sprintf('Monolog configuration error: The logging channel "%s" assigned to the "%s" handler does not exist.', $channel, substr($handler, 16)), 0, $e);
                }
                $logger->addMethodCall('pushHandler', [new Reference($handler)]);
            }
        }
    }
    /**
     * @return array
     */
    public function getChannels()
    {
        return $this->channels;
    }
    /**
     * @return array
     */
    protected function processChannels(?array $configuration)
    {
        if (null === $configuration) {
            return $this->channels;
        }
        if ('inclusive' === $configuration['type']) {
            return $configuration['elements'] ?: $this->channels;
        }
        return array_diff($this->channels, $configuration['elements']);
    }
    /**
     * Create new logger from the monolog.logger_prototype.
     *
     * @return void
     */
    protected function createLogger(string $channel, string $loggerId, ContainerBuilder $container)
    {
        if (!\in_array($channel, $this->channels)) {
            $logger = new ChildDefinition('monolog.logger_prototype');
            $logger->replaceArgument(0, $channel);
            $logger->addTag('monolog.channel_logger');
            $container->setDefinition($loggerId, $logger);
            $this->channels[] = $channel;
        }
        $container->registerAliasForArgument($loggerId, LoggerInterface::class, $channel . '.logger', $channel);
    }
    /**
     * Creates a copy of a reference and alters the service ID.
     */
    private function changeReference(Reference $reference, string $serviceId): Reference
    {
        return new Reference($serviceId, $reference->getInvalidBehavior());
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Bundle\MonologBundle\DependencyInjection\Compiler;

use _ContaoManager\Monolog\Logger;
use _ContaoManager\Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerBuilder;
use _ContaoManager\Symfony\Component\DependencyInjection\Definition;
use _ContaoManager\Symfony\Component\DependencyInjection\Reference;
/**
 * Adds the DebugHandler when the profiler is enabled and kernel.debug is true.
 *
 * @author Christophe Coevoet <stof@notk.org>
 * @author Jordi Boggiano <j.boggiano@seld.be>
 *
 * @deprecated since version 2.12, to be removed in 4.0. Use AddDebugLogProcessorPass in FrameworkBundle instead.
 */
class DebugHandlerPass implements CompilerPassInterface
{
    private $channelPass;
    public function __construct(LoggerChannelPass $channelPass)
    {
        trigger_deprecation('symfony/monolog-bundle', '2.12', 'The %s class is deprecated and will be removed in 4.0. Use AddDebugLogProcessorPass in FrameworkBundle instead.', __CLASS__);
        $this->channelPass = $channelPass;
    }
    public function process(ContainerBuilder $container)
    {
        if (!$container->hasDefinition('profiler')) {
            return;
        }
        if (!$container->getParameter('kernel.debug')) {
            return;
        }
        $debugHandler = new Definition('_ContaoManager\Symfony\Bridge\Monolog\Handler\DebugHandler', [Logger::DEBUG, \true]);
        $container->setDefinition('monolog.handler.debug', $debugHandler);
        foreach ($this->channelPass->getChannels() as $channel) {
            $container->getDefinition('app' === $channel ? 'monolog.logger' : 'monolog.logger.' . $channel)->addMethodCall('pushHandler', [new Reference('monolog.handler.debug')]);
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Bundle\MonologBundle\DependencyInjection\Compiler;

use _ContaoManager\Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerBuilder;
use _ContaoManager\Symfony\Component\DependencyInjection\Reference;
/**
 * Fixes loggers with no handlers (by registering a "null" one).
 *
 * Monolog 1.x adds a default handler logging on STDERR when a logger has
 * no registered handlers. This is NOT what what we want in Symfony, so in such
 * cases, we add a "null" handler to avoid the issue.
 *
 * Note that Monolog 2.x does not register a default handler anymore, so this pass can
 * be removed when MonologBundle minimum version of Monolog is bumped to 2.0.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 *
 * @see https://github.com/Seldaek/monolog/commit/ad37b7b2d11f300cbace9f5e84f855d329519e28
 *
 * @internal since 3.9.0
 */
class FixEmptyLoggerPass implements CompilerPassInterface
{
    private $channelPass;
    public function __construct(LoggerChannelPass $channelPass)
    {
        $this->channelPass = $channelPass;
    }
    public function process(ContainerBuilder $container)
    {
        $container->register('monolog.handler.null_internal', '_ContaoManager\Monolog\Handler\NullHandler');
        foreach ($this->channelPass->getChannels() as $channel) {
            $def = $container->getDefinition('app' === $channel ? 'monolog.logger' : 'monolog.logger.' . $channel);
            foreach ($def->getMethodCalls() as $method) {
                if ('pushHandler' === $method[0]) {
                    continue 2;
                }
            }
            $def->addMethodCall('pushHandler', [new Reference('monolog.handler.null_internal')]);
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Bundle\MonologBundle\DependencyInjection\Compiler;

use _ContaoManager\Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerBuilder;
use _ContaoManager\Symfony\Component\DependencyInjection\Reference;
/**
 * Sets the transport for Swiftmailer handlers depending on the existing
 * container definitions.
 *
 * @author Christian Flothmann <christian.flothmann@xabbuh.de>
 *
 * @internal since 3.9.0
 */
class AddSwiftMailerTransportPass implements CompilerPassInterface
{
    public function process(ContainerBuilder $container)
    {
        $handlers = $container->getParameter('monolog.swift_mailer.handlers');
        foreach ($handlers as $id) {
            $definition = $container->getDefinition($id);
            $mailerId = (string) $definition->getArgument(0);
            // Try to fetch the transport for a non-default mailer first, then go with the default swiftmailer
            $possibleServices = [$mailerId . '.transport.real', $mailerId . '.transport', 'swiftmailer.transport.real', 'swiftmailer.transport'];
            foreach ($possibleServices as $serviceId) {
                if ($container->hasAlias($serviceId) || $container->hasDefinition($serviceId)) {
                    $definition->addMethodCall('setTransport', [new Reference($serviceId)]);
                    break;
                }
            }
        }
    }
}
Copyright (c) 2018-present Fabien Potencier

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is furnished
to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Symfony\Polyfill\Php73;

/**
 * @author Gabriel Caruso <carusogabriel34@gmail.com>
 * @author Ion Bazan <ion.bazan@gmail.com>
 *
 * @internal
 */
final class Php73
{
    public static $startAt = 1533462603;
    /**
     * @param bool $asNum
     *
     * @return array|float|int
     */
    public static function hrtime($asNum = \false)
    {
        $ns = microtime(\false);
        $s = substr($ns, 11) - self::$startAt;
        $ns = 1000000000.0 * (float) $ns;
        if ($asNum) {
            $ns += $s * 1000000000.0;
            return \PHP_INT_SIZE === 4 ? $ns : (int) $ns;
        }
        return [$s, (int) $ns];
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

if (\PHP_VERSION_ID < 70300) {
    class JsonException extends Exception
    {
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

use Symfony\Polyfill\Php73 as p;

if (\PHP_VERSION_ID >= 70300) {
    return;
}

if (!function_exists('is_countable')) {
    function is_countable($value) { return is_array($value) || $value instanceof Countable || $value instanceof ResourceBundle || $value instanceof SimpleXmlElement; }
}
if (!function_exists('hrtime')) {
    require_once __DIR__.'/Php73.php';
    p\Php73::$startAt = (int) microtime(true);
    function hrtime($as_number = false) { return p\Php73::hrtime($as_number); }
}
if (!function_exists('array_key_first')) {
    function array_key_first(array $array) { foreach ($array as $key => $value) { return $key; } }
}
if (!function_exists('array_key_last')) {
    function array_key_last(array $array) { return key(array_slice($array, -1, 1, true)); }
}
Symfony Polyfill / Php73
========================

This component provides functions added to PHP 7.3 core:

- [`array_key_first`](https://php.net/array_key_first)
- [`array_key_last`](https://php.net/array_key_last)
- [`hrtime`](https://php.net/function.hrtime)
- [`is_countable`](https://php.net/is_countable)
- [`JsonException`](https://php.net/JsonException)

More information can be found in the
[main Polyfill README](https://github.com/symfony/polyfill/blob/main/README.md).

License
=======

This library is released under the [MIT license](LICENSE).
{
    "name": "symfony\/polyfill-php73",
    "type": "library",
    "description": "Symfony polyfill backporting some PHP 7.3+ features to lower PHP versions",
    "keywords": [
        "polyfill",
        "shim",
        "compatibility",
        "portable"
    ],
    "homepage": "https:\/\/symfony.com",
    "license": "MIT",
    "authors": [
        {
            "name": "Nicolas Grekas",
            "email": "p@tchwork.com"
        },
        {
            "name": "Symfony Community",
            "homepage": "https:\/\/symfony.com\/contributors"
        }
    ],
    "require": {
        "php": ">=7.2"
    },
    "autoload": {
        "psr-4": {
            "Symfony\\Polyfill\\Php73\\": ""
        },
        "files": [
            "bootstrap.php"
        ],
        "classmap": [
            "Resources\/stubs"
        ]
    },
    "minimum-stability": "dev",
    "extra": {
        "thanks": {
            "name": "symfony\/polyfill",
            "url": "https:\/\/github.com\/symfony\/polyfill"
        }
    }
}<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Serializer\DataCollector;

use _ContaoManager\Symfony\Component\HttpFoundation\Request;
use _ContaoManager\Symfony\Component\HttpFoundation\Response;
use _ContaoManager\Symfony\Component\HttpKernel\DataCollector\DataCollector;
use _ContaoManager\Symfony\Component\HttpKernel\DataCollector\LateDataCollectorInterface;
use _ContaoManager\Symfony\Component\Serializer\Debug\TraceableSerializer;
use _ContaoManager\Symfony\Component\VarDumper\Cloner\Data;
/**
 * @author Mathias Arlaud <mathias.arlaud@gmail.com>
 *
 * @final
 */
class SerializerDataCollector extends DataCollector implements LateDataCollectorInterface
{
    private array $collected = [];
    public function reset(): void
    {
        $this->data = [];
        $this->collected = [];
    }
    public function collect(Request $request, Response $response, ?\Throwable $exception = null): void
    {
        // Everything is collected during the request, and formatted on kernel terminate.
    }
    public function getName(): string
    {
        return 'serializer';
    }
    public function getData(): Data|array
    {
        return $this->data;
    }
    public function getHandledCount(): int
    {
        return array_sum(array_map('count', $this->data));
    }
    public function getTotalTime(): float
    {
        $totalTime = 0;
        foreach ($this->data as $handled) {
            $totalTime += array_sum(array_map(fn(array $el): float => $el['time'], $handled));
        }
        return $totalTime;
    }
    public function collectSerialize(string $traceId, mixed $data, string $format, array $context, float $time, array $caller): void
    {
        unset($context[TraceableSerializer::DEBUG_TRACE_ID]);
        $this->collected[$traceId] = array_merge($this->collected[$traceId] ?? [], compact('data', 'format', 'context', 'time', 'caller'), ['method' => 'serialize']);
    }
    public function collectDeserialize(string $traceId, mixed $data, string $type, string $format, array $context, float $time, array $caller): void
    {
        unset($context[TraceableSerializer::DEBUG_TRACE_ID]);
        $this->collected[$traceId] = array_merge($this->collected[$traceId] ?? [], compact('data', 'format', 'type', 'context', 'time', 'caller'), ['method' => 'deserialize']);
    }
    public function collectNormalize(string $traceId, mixed $data, ?string $format, array $context, float $time, array $caller): void
    {
        unset($context[TraceableSerializer::DEBUG_TRACE_ID]);
        $this->collected[$traceId] = array_merge($this->collected[$traceId] ?? [], compact('data', 'format', 'context', 'time', 'caller'), ['method' => 'normalize']);
    }
    public function collectDenormalize(string $traceId, mixed $data, string $type, ?string $format, array $context, float $time, array $caller): void
    {
        unset($context[TraceableSerializer::DEBUG_TRACE_ID]);
        $this->collected[$traceId] = array_merge($this->collected[$traceId] ?? [], compact('data', 'format', 'type', 'context', 'time', 'caller'), ['method' => 'denormalize']);
    }
    public function collectEncode(string $traceId, mixed $data, ?string $format, array $context, float $time, array $caller): void
    {
        unset($context[TraceableSerializer::DEBUG_TRACE_ID]);
        $this->collected[$traceId] = array_merge($this->collected[$traceId] ?? [], compact('data', 'format', 'context', 'time', 'caller'), ['method' => 'encode']);
    }
    public function collectDecode(string $traceId, mixed $data, ?string $format, array $context, float $time, array $caller): void
    {
        unset($context[TraceableSerializer::DEBUG_TRACE_ID]);
        $this->collected[$traceId] = array_merge($this->collected[$traceId] ?? [], compact('data', 'format', 'context', 'time', 'caller'), ['method' => 'decode']);
    }
    public function collectNormalization(string $traceId, string $normalizer, float $time): void
    {
        $method = 'normalize';
        $this->collected[$traceId]['normalization'][] = compact('normalizer', 'method', 'time');
    }
    public function collectDenormalization(string $traceId, string $normalizer, float $time): void
    {
        $method = 'denormalize';
        $this->collected[$traceId]['normalization'][] = compact('normalizer', 'method', 'time');
    }
    public function collectEncoding(string $traceId, string $encoder, float $time): void
    {
        $method = 'encode';
        $this->collected[$traceId]['encoding'][] = compact('encoder', 'method', 'time');
    }
    public function collectDecoding(string $traceId, string $encoder, float $time): void
    {
        $method = 'decode';
        $this->collected[$traceId]['encoding'][] = compact('encoder', 'method', 'time');
    }
    public function lateCollect(): void
    {
        $this->data = ['serialize' => [], 'deserialize' => [], 'normalize' => [], 'denormalize' => [], 'encode' => [], 'decode' => []];
        foreach ($this->collected as $collected) {
            if (!isset($collected['data'])) {
                continue;
            }
            $data = ['data' => $this->cloneVar($collected['data']), 'dataType' => get_debug_type($collected['data']), 'type' => $collected['type'] ?? null, 'format' => $collected['format'], 'time' => $collected['time'], 'context' => $this->cloneVar($collected['context']), 'normalization' => [], 'encoding' => [], 'caller' => $collected['caller'] ?? null];
            if (isset($collected['normalization'])) {
                $mainNormalization = array_pop($collected['normalization']);
                $data['normalizer'] = ['time' => $mainNormalization['time']] + $this->getMethodLocation($mainNormalization['normalizer'], $mainNormalization['method']);
                foreach ($collected['normalization'] as $normalization) {
                    if (!isset($data['normalization'][$normalization['normalizer']])) {
                        $data['normalization'][$normalization['normalizer']] = ['time' => 0, 'calls' => 0] + $this->getMethodLocation($normalization['normalizer'], $normalization['method']);
                    }
                    ++$data['normalization'][$normalization['normalizer']]['calls'];
                    $data['normalization'][$normalization['normalizer']]['time'] += $normalization['time'];
                }
            }
            if (isset($collected['encoding'])) {
                $mainEncoding = array_pop($collected['encoding']);
                $data['encoder'] = ['time' => $mainEncoding['time']] + $this->getMethodLocation($mainEncoding['encoder'], $mainEncoding['method']);
                foreach ($collected['encoding'] as $encoding) {
                    if (!isset($data['encoding'][$encoding['encoder']])) {
                        $data['encoding'][$encoding['encoder']] = ['time' => 0, 'calls' => 0] + $this->getMethodLocation($encoding['encoder'], $encoding['method']);
                    }
                    ++$data['encoding'][$encoding['encoder']]['calls'];
                    $data['encoding'][$encoding['encoder']]['time'] += $encoding['time'];
                }
            }
            $this->data[$collected['method']][] = $data;
        }
    }
    private function getMethodLocation(string $class, string $method): array
    {
        $reflection = new \ReflectionClass($class);
        return ['class' => $reflection->getShortName(), 'file' => $reflection->getFileName(), 'line' => $reflection->getMethod($method)->getStartLine()];
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Serializer;

use _ContaoManager\Symfony\Component\Serializer\Encoder\ChainDecoder;
use _ContaoManager\Symfony\Component\Serializer\Encoder\ChainEncoder;
use _ContaoManager\Symfony\Component\Serializer\Encoder\ContextAwareDecoderInterface;
use _ContaoManager\Symfony\Component\Serializer\Encoder\ContextAwareEncoderInterface;
use _ContaoManager\Symfony\Component\Serializer\Encoder\DecoderInterface;
use _ContaoManager\Symfony\Component\Serializer\Encoder\EncoderInterface;
use _ContaoManager\Symfony\Component\Serializer\Exception\InvalidArgumentException;
use _ContaoManager\Symfony\Component\Serializer\Exception\LogicException;
use _ContaoManager\Symfony\Component\Serializer\Exception\NotNormalizableValueException;
use _ContaoManager\Symfony\Component\Serializer\Exception\PartialDenormalizationException;
use _ContaoManager\Symfony\Component\Serializer\Exception\UnsupportedFormatException;
use _ContaoManager\Symfony\Component\Serializer\Normalizer\AbstractObjectNormalizer;
use _ContaoManager\Symfony\Component\Serializer\Normalizer\CacheableSupportsMethodInterface;
use _ContaoManager\Symfony\Component\Serializer\Normalizer\ContextAwareDenormalizerInterface;
use _ContaoManager\Symfony\Component\Serializer\Normalizer\ContextAwareNormalizerInterface;
use _ContaoManager\Symfony\Component\Serializer\Normalizer\DenormalizerAwareInterface;
use _ContaoManager\Symfony\Component\Serializer\Normalizer\DenormalizerInterface;
use _ContaoManager\Symfony\Component\Serializer\Normalizer\NormalizerAwareInterface;
use _ContaoManager\Symfony\Component\Serializer\Normalizer\NormalizerInterface;
/**
 * Serializer serializes and deserializes data.
 *
 * objects are turned into arrays by normalizers.
 * arrays are turned into various output formats by encoders.
 *
 *     $serializer->serialize($obj, 'xml')
 *     $serializer->decode($data, 'xml')
 *     $serializer->denormalize($data, 'Class', 'xml')
 *
 * @author Jordi Boggiano <j.boggiano@seld.be>
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 * @author Lukas Kahwe Smith <smith@pooteeweet.org>
 * @author Kévin Dunglas <dunglas@gmail.com>
 */
class Serializer implements SerializerInterface, ContextAwareNormalizerInterface, ContextAwareDenormalizerInterface, ContextAwareEncoderInterface, ContextAwareDecoderInterface
{
    /**
     * Flag to control whether an empty array should be transformed to an
     * object (in JSON: {}) or to a list (in JSON: []).
     */
    public const EMPTY_ARRAY_AS_OBJECT = 'empty_array_as_object';
    private const SCALAR_TYPES = ['int' => \true, 'bool' => \true, 'float' => \true, 'string' => \true];
    /**
     * @var ChainEncoder
     */
    protected $encoder;
    /**
     * @var ChainDecoder
     */
    protected $decoder;
    /**
     * @var array<string, array<string, array<bool>>>
     */
    private array $denormalizerCache = [];
    /**
     * @var array<string, array<string, array<bool>>>
     */
    private array $normalizerCache = [];
    /**
     * @param array<NormalizerInterface|DenormalizerInterface> $normalizers
     * @param array<EncoderInterface|DecoderInterface>         $encoders
     * @param array<string, mixed>                             $defaultContext
     */
    public function __construct(private array $normalizers = [], array $encoders = [], private array $defaultContext = [])
    {
        foreach ($normalizers as $normalizer) {
            if ($normalizer instanceof SerializerAwareInterface) {
                $normalizer->setSerializer($this);
            }
            if ($normalizer instanceof DenormalizerAwareInterface) {
                $normalizer->setDenormalizer($this);
            }
            if ($normalizer instanceof NormalizerAwareInterface) {
                $normalizer->setNormalizer($this);
            }
            if (!($normalizer instanceof NormalizerInterface || $normalizer instanceof DenormalizerInterface)) {
                throw new InvalidArgumentException(\sprintf('The class "%s" neither implements "%s" nor "%s".', get_debug_type($normalizer), NormalizerInterface::class, DenormalizerInterface::class));
            }
        }
        $decoders = [];
        $realEncoders = [];
        foreach ($encoders as $encoder) {
            if ($encoder instanceof SerializerAwareInterface) {
                $encoder->setSerializer($this);
            }
            if ($encoder instanceof DecoderInterface) {
                $decoders[] = $encoder;
            }
            if ($encoder instanceof EncoderInterface) {
                $realEncoders[] = $encoder;
            }
            if (!($encoder instanceof EncoderInterface || $encoder instanceof DecoderInterface)) {
                throw new InvalidArgumentException(\sprintf('The class "%s" neither implements "%s" nor "%s".', get_debug_type($encoder), EncoderInterface::class, DecoderInterface::class));
            }
        }
        $this->encoder = new ChainEncoder($realEncoders);
        $this->decoder = new ChainDecoder($decoders);
    }
    final public function serialize(mixed $data, string $format, array $context = []): string
    {
        if (!$this->supportsEncoding($format, $context)) {
            throw new UnsupportedFormatException(\sprintf('Serialization for the format "%s" is not supported.', $format));
        }
        if ($this->encoder->needsNormalization($format, $context)) {
            $data = $this->normalize($data, $format, $context);
        }
        return $this->encode($data, $format, $context);
    }
    final public function deserialize(mixed $data, string $type, string $format, array $context = []): mixed
    {
        if (!$this->supportsDecoding($format, $context)) {
            throw new UnsupportedFormatException(\sprintf('Deserialization for the format "%s" is not supported.', $format));
        }
        $data = $this->decode($data, $format, $context);
        return $this->denormalize($data, $type, $format, $context);
    }
    public function normalize(mixed $data, ?string $format = null, array $context = []): array|string|int|float|bool|\ArrayObject|null
    {
        // If a normalizer supports the given data, use it
        if ($normalizer = $this->getNormalizer($data, $format, $context)) {
            return $normalizer->normalize($data, $format, $context);
        }
        if (null === $data || \is_scalar($data)) {
            return $data;
        }
        if (\is_array($data) && !$data && ($context[self::EMPTY_ARRAY_AS_OBJECT] ?? $this->defaultContext[self::EMPTY_ARRAY_AS_OBJECT] ?? \false)) {
            return new \ArrayObject();
        }
        if (is_iterable($data)) {
            if ($data instanceof \Countable && ($context[AbstractObjectNormalizer::PRESERVE_EMPTY_OBJECTS] ?? $this->defaultContext[AbstractObjectNormalizer::PRESERVE_EMPTY_OBJECTS] ?? \false) && !\count($data)) {
                return new \ArrayObject();
            }
            $normalized = [];
            foreach ($data as $key => $val) {
                $normalized[$key] = $this->normalize($val, $format, $context);
            }
            return $normalized;
        }
        if (\is_object($data)) {
            if (!$this->normalizers) {
                throw new LogicException('You must register at least one normalizer to be able to normalize objects.');
            }
            throw new NotNormalizableValueException(\sprintf('Could not normalize object of type "%s", no supporting normalizer found.', get_debug_type($data)));
        }
        throw new NotNormalizableValueException('An unexpected value could not be normalized: ' . (!\is_resource($data) ? var_export($data, \true) : \sprintf('"%s" resource', get_resource_type($data))));
    }
    /**
     * @throws NotNormalizableValueException
     * @throws PartialDenormalizationException Occurs when one or more properties of $type fails to denormalize
     */
    public function denormalize(mixed $data, string $type, ?string $format = null, array $context = []): mixed
    {
        if (isset($context[DenormalizerInterface::COLLECT_DENORMALIZATION_ERRORS], $context['not_normalizable_value_exceptions'])) {
            throw new LogicException('Passing a value for "not_normalizable_value_exceptions" context key is not allowed.');
        }
        $normalizer = $this->getDenormalizer($data, $type, $format, $context);
        // Check for a denormalizer first, e.g. the data is wrapped
        if (!$normalizer && isset(self::SCALAR_TYPES[$type])) {
            if (!('is_' . $type)($data)) {
                throw NotNormalizableValueException::createForUnexpectedDataType(\sprintf('Data expected to be of type "%s" ("%s" given).', $type, get_debug_type($data)), $data, [$type], $context['deserialization_path'] ?? null, \true);
            }
            return $data;
        }
        if (!$this->normalizers) {
            throw new LogicException('You must register at least one normalizer to be able to denormalize objects.');
        }
        if (!$normalizer) {
            throw new NotNormalizableValueException(\sprintf('Could not denormalize object of type "%s", no supporting normalizer found.', $type));
        }
        if ((isset($context[DenormalizerInterface::COLLECT_DENORMALIZATION_ERRORS]) || isset($this->defaultContext[DenormalizerInterface::COLLECT_DENORMALIZATION_ERRORS])) && !isset($context['not_normalizable_value_exceptions'])) {
            unset($context[DenormalizerInterface::COLLECT_DENORMALIZATION_ERRORS]);
            $context['not_normalizable_value_exceptions'] = [];
            $errors =& $context['not_normalizable_value_exceptions'];
            $denormalized = $normalizer->denormalize($data, $type, $format, $context);
            if ($errors) {
                // merge errors so that one path has only one error
                $uniqueErrors = [];
                foreach ($errors as $error) {
                    if (null === $error->getPath()) {
                        $uniqueErrors[] = $error;
                        continue;
                    }
                    $uniqueErrors[$error->getPath()] = $uniqueErrors[$error->getPath()] ?? $error;
                }
                throw new PartialDenormalizationException($denormalized, array_values($uniqueErrors));
            }
            return $denormalized;
        }
        return $normalizer->denormalize($data, $type, $format, $context);
    }
    public function getSupportedTypes(?string $format): array
    {
        return ['*' => \false];
    }
    public function supportsNormalization(mixed $data, ?string $format = null, array $context = []): bool
    {
        return null !== $this->getNormalizer($data, $format, $context);
    }
    public function supportsDenormalization(mixed $data, string $type, ?string $format = null, array $context = []): bool
    {
        return isset(self::SCALAR_TYPES[$type]) || null !== $this->getDenormalizer($data, $type, $format, $context);
    }
    /**
     * Returns a matching normalizer.
     *
     * @param mixed       $data    Data to get the serializer for
     * @param string|null $format  Format name, present to give the option to normalizers to act differently based on formats
     * @param array       $context Options available to the normalizer
     */
    private function getNormalizer(mixed $data, ?string $format, array $context): ?NormalizerInterface
    {
        if (\is_object($data)) {
            $type = $data::class;
            $genericType = 'object';
        } else {
            $type = 'native-' . \gettype($data);
            $genericType = '*';
        }
        if (!isset($this->normalizerCache[$format ?? ''][$type])) {
            $this->normalizerCache[$format ?? ''][$type] = [];
            foreach ($this->normalizers as $k => $normalizer) {
                if (!$normalizer instanceof NormalizerInterface) {
                    continue;
                }
                if (!method_exists($normalizer, 'getSupportedTypes')) {
                    trigger_deprecation('symfony/serializer', '6.3', '"%s" should implement "NormalizerInterface::getSupportedTypes(?string $format): array".', $normalizer::class);
                    if (!$normalizer instanceof CacheableSupportsMethodInterface || !$normalizer->hasCacheableSupportsMethod()) {
                        $this->normalizerCache[$format ?? ''][$type][$k] = \false;
                    } elseif ($normalizer->supportsNormalization($data, $format, $context)) {
                        $this->normalizerCache[$format ?? ''][$type][$k] = \true;
                        break;
                    }
                    continue;
                }
                $supportedTypes = $normalizer->getSupportedTypes($format);
                foreach ($supportedTypes as $supportedType => $isCacheable) {
                    if (\in_array($supportedType, ['*', 'object'], \true) || $type !== $supportedType && ('object' !== $genericType || !is_subclass_of($type, $supportedType))) {
                        continue;
                    }
                    if (null === $isCacheable) {
                        unset($supportedTypes['*'], $supportedTypes['object']);
                    } elseif ($this->normalizerCache[$format ?? ''][$type][$k] = $isCacheable && $normalizer->supportsNormalization($data, $format, $context)) {
                        break 2;
                    }
                    break;
                }
                if (null === $isCacheable = $supportedTypes[\array_key_exists($genericType, $supportedTypes) ? $genericType : '*'] ?? null) {
                    continue;
                }
                if ($this->normalizerCache[$format ?? ''][$type][$k] ??= $isCacheable && $normalizer->supportsNormalization($data, $format, $context)) {
                    break;
                }
            }
        }
        foreach ($this->normalizerCache[$format ?? ''][$type] as $k => $cached) {
            $normalizer = $this->normalizers[$k];
            if ($cached || $normalizer->supportsNormalization($data, $format, $context)) {
                return $normalizer;
            }
        }
        return null;
    }
    /**
     * Returns a matching denormalizer.
     *
     * @param mixed       $data    Data to restore
     * @param string      $class   The expected class to instantiate
     * @param string|null $format  Format name, present to give the option to normalizers to act differently based on formats
     * @param array       $context Options available to the denormalizer
     */
    private function getDenormalizer(mixed $data, string $class, ?string $format, array $context): ?DenormalizerInterface
    {
        if (!isset($this->denormalizerCache[$format ?? ''][$class])) {
            $this->denormalizerCache[$format ?? ''][$class] = [];
            $genericType = class_exists($class) || interface_exists($class, \false) ? 'object' : '*';
            foreach ($this->normalizers as $k => $normalizer) {
                if (!$normalizer instanceof DenormalizerInterface) {
                    continue;
                }
                if (!method_exists($normalizer, 'getSupportedTypes')) {
                    trigger_deprecation('symfony/serializer', '6.3', '"%s" should implement "DenormalizerInterface::getSupportedTypes(?string $format): array".', $normalizer::class);
                    if (!$normalizer instanceof CacheableSupportsMethodInterface || !$normalizer->hasCacheableSupportsMethod()) {
                        $this->denormalizerCache[$format ?? ''][$class][$k] = \false;
                    } elseif ($normalizer->supportsDenormalization(null, $class, $format, $context)) {
                        $this->denormalizerCache[$format ?? ''][$class][$k] = \true;
                        break;
                    }
                    continue;
                }
                $supportedTypes = $normalizer->getSupportedTypes($format);
                $doesClassRepresentCollection = str_ends_with($class, '[]');
                foreach ($supportedTypes as $supportedType => $isCacheable) {
                    if (\in_array($supportedType, ['*', 'object'], \true) || $class !== $supportedType && ('object' !== $genericType || !is_subclass_of($class, $supportedType)) && !($doesClassRepresentCollection && str_ends_with($supportedType, '[]') && is_subclass_of(strstr($class, '[]', \true), strstr($supportedType, '[]', \true)))) {
                        continue;
                    }
                    if (null === $isCacheable) {
                        unset($supportedTypes['*'], $supportedTypes['object']);
                    } elseif ($this->denormalizerCache[$format ?? ''][$class][$k] = $isCacheable && $normalizer->supportsDenormalization(null, $class, $format, $context)) {
                        break 2;
                    }
                    break;
                }
                if (null === $isCacheable = $supportedTypes[\array_key_exists($genericType, $supportedTypes) ? $genericType : '*'] ?? null) {
                    continue;
                }
                if ($this->denormalizerCache[$format ?? ''][$class][$k] ??= $isCacheable && $normalizer->supportsDenormalization(null, $class, $format, $context)) {
                    break;
                }
            }
        }
        foreach ($this->denormalizerCache[$format ?? ''][$class] as $k => $cached) {
            $normalizer = $this->normalizers[$k];
            if ($cached || $normalizer->supportsDenormalization($data, $class, $format, $context)) {
                return $normalizer;
            }
        }
        return null;
    }
    final public function encode(mixed $data, string $format, array $context = []): string
    {
        return $this->encoder->encode($data, $format, $context);
    }
    final public function decode(string $data, string $format, array $context = []): mixed
    {
        return $this->decoder->decode($data, $format, $context);
    }
    public function supportsEncoding(string $format, array $context = []): bool
    {
        return $this->encoder->supportsEncoding($format, $context);
    }
    public function supportsDecoding(string $format, array $context = []): bool
    {
        return $this->decoder->supportsDecoding($format, $context);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Serializer\Mapping;

use _ContaoManager\Symfony\Component\Serializer\Mapping\Factory\ClassMetadataFactoryInterface;
/**
 * @author Samuel Roze <samuel.roze@gmail.com>
 */
class ClassDiscriminatorFromClassMetadata implements ClassDiscriminatorResolverInterface
{
    private array $mappingForMappedObjectCache = [];
    public function __construct(private readonly ClassMetadataFactoryInterface $classMetadataFactory)
    {
    }
    public function getMappingForClass(string $class): ?ClassDiscriminatorMapping
    {
        if ($this->classMetadataFactory->hasMetadataFor($class)) {
            return $this->classMetadataFactory->getMetadataFor($class)->getClassDiscriminatorMapping();
        }
        return null;
    }
    public function getMappingForMappedObject(object|string $object): ?ClassDiscriminatorMapping
    {
        if ($this->classMetadataFactory->hasMetadataFor($object)) {
            $metadata = $this->classMetadataFactory->getMetadataFor($object);
            if (null !== $metadata->getClassDiscriminatorMapping()) {
                return $metadata->getClassDiscriminatorMapping();
            }
        }
        $cacheKey = \is_object($object) ? $object::class : $object;
        if (!\array_key_exists($cacheKey, $this->mappingForMappedObjectCache)) {
            $this->mappingForMappedObjectCache[$cacheKey] = $this->resolveMappingForMappedObject($object);
        }
        return $this->mappingForMappedObjectCache[$cacheKey];
    }
    public function getTypeForMappedObject(object|string $object): ?string
    {
        if (null === $mapping = $this->getMappingForMappedObject($object)) {
            return null;
        }
        return $mapping->getMappedObjectType($object);
    }
    private function resolveMappingForMappedObject(object|string $object): ?ClassDiscriminatorMapping
    {
        $reflectionClass = new \ReflectionClass($object);
        if ($parentClass = $reflectionClass->getParentClass()) {
            if (null !== $parentMapping = $this->getMappingForMappedObject($parentClass->getName())) {
                return $parentMapping;
            }
        }
        foreach ($reflectionClass->getInterfaceNames() as $interfaceName) {
            if (null !== $interfaceMapping = $this->getMappingForMappedObject($interfaceName)) {
                return $interfaceMapping;
            }
        }
        return null;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Serializer\Mapping;

/**
 * Stores metadata needed for serializing and deserializing objects of specific class.
 *
 * Primarily, the metadata stores the set of attributes to serialize or deserialize.
 *
 * There may only exist one metadata for each attribute according to its name.
 *
 * @internal
 *
 * @author Kévin Dunglas <dunglas@gmail.com>
 */
interface ClassMetadataInterface
{
    /**
     * Returns the name of the backing PHP class.
     */
    public function getName(): string;
    /**
     * Adds an {@link AttributeMetadataInterface}.
     */
    public function addAttributeMetadata(AttributeMetadataInterface $attributeMetadata): void;
    /**
     * Gets the list of {@link AttributeMetadataInterface}.
     *
     * @return array<string, AttributeMetadataInterface>
     */
    public function getAttributesMetadata(): array;
    /**
     * Merges a {@link ClassMetadataInterface} in the current one.
     */
    public function merge(self $classMetadata): void;
    /**
     * Returns a {@link \ReflectionClass} instance for this class.
     */
    public function getReflectionClass(): \ReflectionClass;
    public function getClassDiscriminatorMapping(): ?ClassDiscriminatorMapping;
    public function setClassDiscriminatorMapping(?ClassDiscriminatorMapping $mapping): void;
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Serializer\Mapping;

/**
 * @author Kévin Dunglas <dunglas@gmail.com>
 */
class ClassMetadata implements ClassMetadataInterface
{
    /**
     * @internal This property is public in order to reduce the size of the
     *           class' serialized representation. Do not access it. Use
     *           {@link getName()} instead.
     */
    public string $name;
    /**
     * @var AttributeMetadataInterface[]
     *
     * @internal This property is public in order to reduce the size of the
     *           class' serialized representation. Do not access it. Use
     *           {@link getAttributesMetadata()} instead.
     */
    public array $attributesMetadata = [];
    private ?\ReflectionClass $reflClass = null;
    /**
     * @internal This property is public in order to reduce the size of the
     *           class' serialized representation. Do not access it. Use
     *           {@link getClassDiscriminatorMapping()} instead.
     */
    public ?ClassDiscriminatorMapping $classDiscriminatorMapping = null;
    /**
     * Constructs a metadata for the given class.
     */
    public function __construct(string $class, ?ClassDiscriminatorMapping $classDiscriminatorMapping = null)
    {
        $this->name = $class;
        $this->classDiscriminatorMapping = $classDiscriminatorMapping;
    }
    public function getName(): string
    {
        return $this->name;
    }
    public function addAttributeMetadata(AttributeMetadataInterface $attributeMetadata): void
    {
        $this->attributesMetadata[$attributeMetadata->getName()] = $attributeMetadata;
    }
    public function getAttributesMetadata(): array
    {
        return $this->attributesMetadata;
    }
    public function merge(ClassMetadataInterface $classMetadata): void
    {
        foreach ($classMetadata->getAttributesMetadata() as $attributeMetadata) {
            if (isset($this->attributesMetadata[$attributeMetadata->getName()])) {
                $this->attributesMetadata[$attributeMetadata->getName()]->merge($attributeMetadata);
            } else {
                $this->addAttributeMetadata($attributeMetadata);
            }
        }
    }
    public function getReflectionClass(): \ReflectionClass
    {
        if (!$this->reflClass) {
            $this->reflClass = new \ReflectionClass($this->getName());
        }
        return $this->reflClass;
    }
    public function getClassDiscriminatorMapping(): ?ClassDiscriminatorMapping
    {
        return $this->classDiscriminatorMapping;
    }
    public function setClassDiscriminatorMapping(?ClassDiscriminatorMapping $mapping = null): void
    {
        if (1 > \func_num_args()) {
            trigger_deprecation('symfony/serializer', '6.2', 'Calling "%s()" without any arguments is deprecated, pass null explicitly instead.', __METHOD__);
        }
        $this->classDiscriminatorMapping = $mapping;
    }
    /**
     * Returns the names of the properties that should be serialized.
     *
     * @return string[]
     */
    public function __sleep(): array
    {
        return ['name', 'attributesMetadata', 'classDiscriminatorMapping'];
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Serializer\Mapping\Loader;

use _ContaoManager\Doctrine\Common\Annotations\Reader;
use _ContaoManager\Symfony\Component\Serializer\Attribute\Context;
use _ContaoManager\Symfony\Component\Serializer\Attribute\DiscriminatorMap;
use _ContaoManager\Symfony\Component\Serializer\Attribute\Groups;
use _ContaoManager\Symfony\Component\Serializer\Attribute\Ignore;
use _ContaoManager\Symfony\Component\Serializer\Attribute\MaxDepth;
use _ContaoManager\Symfony\Component\Serializer\Attribute\SerializedName;
use _ContaoManager\Symfony\Component\Serializer\Attribute\SerializedPath;
use _ContaoManager\Symfony\Component\Serializer\Exception\MappingException;
use _ContaoManager\Symfony\Component\Serializer\Mapping\AttributeMetadata;
use _ContaoManager\Symfony\Component\Serializer\Mapping\AttributeMetadataInterface;
use _ContaoManager\Symfony\Component\Serializer\Mapping\ClassDiscriminatorMapping;
use _ContaoManager\Symfony\Component\Serializer\Mapping\ClassMetadataInterface;
/**
 * Loader for PHP attributes.
 *
 * @author Kévin Dunglas <dunglas@gmail.com>
 * @author Alexander M. Turek <me@derrabus.de>
 * @author Alexandre Daubois <alex.daubois@gmail.com>
 */
class AttributeLoader implements LoaderInterface
{
    use AccessorCollisionResolverTrait;
    private const KNOWN_ATTRIBUTES = [DiscriminatorMap::class, Groups::class, Ignore::class, MaxDepth::class, SerializedName::class, SerializedPath::class, Context::class];
    public function __construct(private readonly ?Reader $reader = null)
    {
        if ($reader) {
            trigger_deprecation('symfony/serializer', '6.4', 'Passing a "%s" instance as argument 1 to "%s()" is deprecated, pass null or omit the parameter instead.', get_debug_type($reader), __METHOD__);
        }
    }
    public function loadClassMetadata(ClassMetadataInterface $classMetadata): bool
    {
        $reflectionClass = $classMetadata->getReflectionClass();
        $className = $reflectionClass->name;
        $loaded = \false;
        $classGroups = [];
        $classContextAnnotation = null;
        $attributesMetadata = $classMetadata->getAttributesMetadata();
        foreach ($this->loadAttributes($reflectionClass) as $annotation) {
            if ($annotation instanceof DiscriminatorMap) {
                $classMetadata->setClassDiscriminatorMapping(new ClassDiscriminatorMapping($annotation->getTypeProperty(), $annotation->getMapping()));
                continue;
            }
            if ($annotation instanceof Groups) {
                $classGroups = $annotation->getGroups();
                continue;
            }
            if ($annotation instanceof Context) {
                $classContextAnnotation = $annotation;
            }
        }
        foreach ($reflectionClass->getProperties() as $property) {
            if (!isset($attributesMetadata[$property->name])) {
                $attributesMetadata[$property->name] = new AttributeMetadata($property->name);
                $classMetadata->addAttributeMetadata($attributesMetadata[$property->name]);
            }
            if ($property->getDeclaringClass()->name === $className) {
                if ($classContextAnnotation) {
                    $this->setAttributeContextsForGroups($classContextAnnotation, $attributesMetadata[$property->name]);
                }
                foreach ($classGroups as $group) {
                    $attributesMetadata[$property->name]->addGroup($group);
                }
                foreach ($this->loadAttributes($property) as $annotation) {
                    if ($annotation instanceof Groups) {
                        foreach ($annotation->getGroups() as $group) {
                            $attributesMetadata[$property->name]->addGroup($group);
                        }
                    } elseif ($annotation instanceof MaxDepth) {
                        $attributesMetadata[$property->name]->setMaxDepth($annotation->getMaxDepth());
                    } elseif ($annotation instanceof SerializedName) {
                        $attributesMetadata[$property->name]->setSerializedName($annotation->getSerializedName());
                    } elseif ($annotation instanceof SerializedPath) {
                        $attributesMetadata[$property->name]->setSerializedPath($annotation->getSerializedPath());
                    } elseif ($annotation instanceof Ignore) {
                        $attributesMetadata[$property->name]->setIgnore(\true);
                    } elseif ($annotation instanceof Context) {
                        $this->setAttributeContextsForGroups($annotation, $attributesMetadata[$property->name]);
                    }
                    $loaded = \true;
                }
            }
        }
        foreach ($reflectionClass->getMethods() as $method) {
            if ($method->getDeclaringClass()->name !== $className) {
                continue;
            }
            $name = $method->name;
            if (0 === stripos($name, 'get') && $method->getNumberOfRequiredParameters()) {
                continue;
                /*  matches the BC behavior in `Symfony\Component\Serializer\Normalizer\ObjectNormalizer::extractAttributes` */
            }
            $attributeName = $this->getAttributeNameFromAccessor($reflectionClass, $method, \true);
            $accessorOrMutator = null !== $attributeName;
            $hasProperty = $this->hasPropertyForAccessor($method->getDeclaringClass(), $name);
            $attributeMetadata = null;
            if ($hasProperty || $accessorOrMutator) {
                if (null === $attributeName || 's' !== $name[0] && $hasProperty && $this->hasAttributeNameCollision($reflectionClass, $attributeName, $name)) {
                    $attributeName = $name;
                }
                if (isset($attributesMetadata[$attributeName])) {
                    $attributeMetadata = $attributesMetadata[$attributeName];
                } else {
                    $attributesMetadata[$attributeName] = $attributeMetadata = new AttributeMetadata($attributeName);
                    $classMetadata->addAttributeMetadata($attributeMetadata);
                }
            }
            foreach ($this->loadAttributes($method) as $annotation) {
                if ($annotation instanceof Groups) {
                    if (!$attributeMetadata) {
                        throw new MappingException(\sprintf('Groups on "%s::%s()" cannot be added. Groups can only be added on methods beginning with "get", "is", "has", "can" or "set".', $className, $method->name));
                    }
                    foreach ($annotation->getGroups() as $group) {
                        $attributeMetadata->addGroup($group);
                    }
                } elseif ($annotation instanceof MaxDepth) {
                    if (!$attributeMetadata) {
                        throw new MappingException(\sprintf('MaxDepth on "%s::%s()" cannot be added. MaxDepth can only be added on methods beginning with "get", "is", "has", "can" or "set".', $className, $method->name));
                    }
                    $attributeMetadata->setMaxDepth($annotation->getMaxDepth());
                } elseif ($annotation instanceof SerializedName) {
                    if (!$attributeMetadata) {
                        throw new MappingException(\sprintf('SerializedName on "%s::%s()" cannot be added. SerializedName can only be added on methods beginning with "get", "is", "has", "can" or "set".', $className, $method->name));
                    }
                    $attributeMetadata->setSerializedName($annotation->getSerializedName());
                } elseif ($annotation instanceof SerializedPath) {
                    if (!$attributeMetadata) {
                        throw new MappingException(\sprintf('SerializedPath on "%s::%s()" cannot be added. SerializedPath can only be added on methods beginning with "get", "is", "has", "can" or "set".', $className, $method->name));
                    }
                    $attributeMetadata->setSerializedPath($annotation->getSerializedPath());
                } elseif ($annotation instanceof Ignore) {
                    if ($attributeMetadata) {
                        $attributeMetadata->setIgnore(\true);
                    }
                } elseif ($annotation instanceof Context) {
                    if (!$attributeMetadata) {
                        throw new MappingException(\sprintf('Context on "%s::%s()" cannot be added. Context can only be added on methods beginning with "get", "is", "has", "can" or "set".', $className, $method->name));
                    }
                    $this->setAttributeContextsForGroups($annotation, $attributeMetadata);
                }
                $loaded = \true;
            }
        }
        return $loaded;
    }
    private function loadAttributes(\ReflectionMethod|\ReflectionClass|\ReflectionProperty $reflector): iterable
    {
        foreach ($reflector->getAttributes() as $attribute) {
            if ($this->isKnownAttribute($attribute->getName())) {
                try {
                    yield $attribute->newInstance();
                } catch (\Error $e) {
                    if (\Error::class !== $e::class) {
                        throw $e;
                    }
                    $on = match (\true) {
                        $reflector instanceof \ReflectionClass => ' on class ' . $reflector->name,
                        $reflector instanceof \ReflectionMethod => \sprintf(' on "%s::%s()"', $reflector->getDeclaringClass()->name, $reflector->name),
                        $reflector instanceof \ReflectionProperty => \sprintf(' on "%s::$%s"', $reflector->getDeclaringClass()->name, $reflector->name),
                        default => '',
                    };
                    throw new MappingException(\sprintf('Could not instantiate attribute "%s"%s.', $attribute->getName(), $on), 0, $e);
                }
            }
        }
        if (null === $this->reader) {
            return;
        }
        if ($reflector instanceof \ReflectionClass) {
            yield from $this->getClassAnnotations($reflector);
        }
        if ($reflector instanceof \ReflectionMethod) {
            yield from $this->getMethodAnnotations($reflector);
        }
        if ($reflector instanceof \ReflectionProperty) {
            yield from $this->getPropertyAnnotations($reflector);
        }
    }
    /**
     * @deprecated since Symfony 6.4 without replacement
     */
    public function loadAnnotations(\ReflectionMethod|\ReflectionClass|\ReflectionProperty $reflector): iterable
    {
        trigger_deprecation('symfony/serializer', '6.4', 'Method "%s()" is deprecated without replacement.', __METHOD__);
        return $this->loadAttributes($reflector);
    }
    private function setAttributeContextsForGroups(Context $annotation, AttributeMetadataInterface $attributeMetadata): void
    {
        if ($annotation->getContext()) {
            $attributeMetadata->setNormalizationContextForGroups($annotation->getContext(), $annotation->getGroups());
            $attributeMetadata->setDenormalizationContextForGroups($annotation->getContext(), $annotation->getGroups());
        }
        if ($annotation->getNormalizationContext()) {
            $attributeMetadata->setNormalizationContextForGroups($annotation->getNormalizationContext(), $annotation->getGroups());
        }
        if ($annotation->getDenormalizationContext()) {
            $attributeMetadata->setDenormalizationContextForGroups($annotation->getDenormalizationContext(), $annotation->getGroups());
        }
    }
    private function isKnownAttribute(string $attributeName): bool
    {
        foreach (self::KNOWN_ATTRIBUTES as $knownAttribute) {
            if (is_a($attributeName, $knownAttribute, \true)) {
                return \true;
            }
        }
        return \false;
    }
    /**
     * @return object[]
     */
    private function getClassAnnotations(\ReflectionClass $reflector): array
    {
        if ($annotations = array_filter($this->reader->getClassAnnotations($reflector), fn(object $annotation): bool => $this->isKnownAttribute($annotation::class))) {
            trigger_deprecation('symfony/serializer', '6.4', 'Class "%s" uses Doctrine Annotations to configure serialization, which is deprecated. Use PHP attributes instead.', $reflector->getName());
        }
        return $annotations;
    }
    /**
     * @return object[]
     */
    private function getMethodAnnotations(\ReflectionMethod $reflector): array
    {
        if ($annotations = array_filter($this->reader->getMethodAnnotations($reflector), fn(object $annotation): bool => $this->isKnownAttribute($annotation::class))) {
            trigger_deprecation('symfony/serializer', '6.4', 'Method "%s::%s()" uses Doctrine Annotations to configure serialization, which is deprecated. Use PHP attributes instead.', $reflector->getDeclaringClass()->getName(), $reflector->getName());
        }
        return $annotations;
    }
    /**
     * @return object[]
     */
    private function getPropertyAnnotations(\ReflectionProperty $reflector): array
    {
        if ($annotations = array_filter($this->reader->getPropertyAnnotations($reflector), fn(object $annotation): bool => $this->isKnownAttribute($annotation::class))) {
            trigger_deprecation('symfony/serializer', '6.4', 'Property "%s::$%s" uses Doctrine Annotations to configure serialization, which is deprecated. Use PHP attributes instead.', $reflector->getDeclaringClass()->getName(), $reflector->getName());
        }
        return $annotations;
    }
}
if (!class_exists(AnnotationLoader::class, \false)) {
    class_alias(AttributeLoader::class, AnnotationLoader::class);
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Serializer\Mapping\Loader;

use _ContaoManager\Symfony\Component\Serializer\Exception\MappingException;
/**
 * Base class for all file based loaders.
 *
 * @author Kévin Dunglas <dunglas@gmail.com>
 */
abstract class FileLoader implements LoaderInterface
{
    protected $file;
    /**
     * @param string $file The mapping file to load
     *
     * @throws MappingException if the mapping file does not exist or is not readable
     */
    public function __construct(string $file)
    {
        if (!is_file($file)) {
            throw new MappingException(\sprintf('The mapping file "%s" does not exist.', $file));
        }
        if (!is_readable($file)) {
            throw new MappingException(\sprintf('The mapping file "%s" is not readable.', $file));
        }
        $this->file = $file;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Serializer\Mapping\Loader;

use _ContaoManager\Symfony\Component\Serializer\Attribute\Ignore;
/**
 * Provides methods to detect accessor name collisions during serialization.
 *
 * @internal
 */
trait AccessorCollisionResolverTrait
{
    private function getAttributeNameFromAccessor(\ReflectionClass $class, \ReflectionMethod $method, bool $andMutator): ?string
    {
        $methodName = $method->name;
        $i = match ($methodName[0]) {
            's' => $andMutator && str_starts_with($methodName, 'set') ? 3 : null,
            'g' => str_starts_with($methodName, 'get') ? 3 : null,
            'h' => str_starts_with($methodName, 'has') ? 3 : null,
            'c' => str_starts_with($methodName, 'can') ? 3 : null,
            'i' => str_starts_with($methodName, 'is') ? 2 : null,
            default => null,
        };
        // ctype_lower check to find out if method looks like accessor but actually is not, e.g. hash, cancel
        if (null === $i || ctype_lower($methodName[$i] ?? 'a') || !$andMutator && $method->isStatic()) {
            return null;
        }
        if ('s' === $methodName[0] ? !$method->getNumberOfParameters() : $method->getNumberOfRequiredParameters() || \in_array((string) $method->getReturnType(), ['void', 'never'], \true)) {
            return null;
        }
        $attributeName = substr($methodName, $i);
        if (!$class->hasProperty($attributeName)) {
            $attributeName = lcfirst($attributeName);
        }
        return $attributeName;
    }
    private function hasPropertyForAccessor(\ReflectionClass $class, string $propName): bool
    {
        do {
            if ($class->hasProperty($propName)) {
                return \true;
            }
        } while ($class = $class->getParentClass());
        return \false;
    }
    private function hasAttributeNameCollision(\ReflectionClass $class, string $attributeName, string $methodName): bool
    {
        if ($this->hasPropertyForAccessor($class, $attributeName)) {
            return \true;
        }
        if ($class->hasMethod($attributeName)) {
            $candidate = $class->getMethod($attributeName);
            if ($candidate->getName() !== $methodName && $this->isReadableAccessorMethod($candidate)) {
                return \true;
            }
        }
        $ucAttributeName = ucfirst($attributeName);
        foreach (['get', 'is', 'has', 'can'] as $prefix) {
            $candidateName = $prefix . $ucAttributeName;
            if ($candidateName === $methodName || !$class->hasMethod($candidateName)) {
                continue;
            }
            if ($this->isReadableAccessorMethod($class->getMethod($candidateName))) {
                return \true;
            }
        }
        return \false;
    }
    private function isReadableAccessorMethod(\ReflectionMethod $method): bool
    {
        return $method->isPublic() && !$method->isStatic() && !$method->getAttributes(Ignore::class) && !$method->getNumberOfRequiredParameters() && !\in_array((string) $method->getReturnType(), ['void', 'never'], \true);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Serializer\Mapping\Loader;

use _ContaoManager\Symfony\Component\Serializer\Mapping\ClassMetadataInterface;
/**
 * Loads {@link ClassMetadataInterface}.
 *
 * @author Kévin Dunglas <dunglas@gmail.com>
 */
interface LoaderInterface
{
    public function loadClassMetadata(ClassMetadataInterface $classMetadata): bool;
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Serializer\Mapping\Loader;

use _ContaoManager\Symfony\Component\PropertyAccess\Exception\InvalidPropertyPathException;
use _ContaoManager\Symfony\Component\PropertyAccess\PropertyPath;
use _ContaoManager\Symfony\Component\Serializer\Exception\MappingException;
use _ContaoManager\Symfony\Component\Serializer\Mapping\AttributeMetadata;
use _ContaoManager\Symfony\Component\Serializer\Mapping\ClassDiscriminatorMapping;
use _ContaoManager\Symfony\Component\Serializer\Mapping\ClassMetadataInterface;
use _ContaoManager\Symfony\Component\Yaml\Parser;
use _ContaoManager\Symfony\Component\Yaml\Yaml;
/**
 * YAML File Loader.
 *
 * @author Kévin Dunglas <dunglas@gmail.com>
 */
class YamlFileLoader extends FileLoader
{
    private ?Parser $yamlParser = null;
    /**
     * An array of YAML class descriptions.
     */
    private ?array $classes = null;
    public function loadClassMetadata(ClassMetadataInterface $classMetadata): bool
    {
        if (!$this->classes ??= $this->getClassesFromYaml()) {
            return \false;
        }
        if (!isset($this->classes[$classMetadata->getName()])) {
            return \false;
        }
        $yaml = $this->classes[$classMetadata->getName()];
        if (isset($yaml['attributes']) && \is_array($yaml['attributes'])) {
            $attributesMetadata = $classMetadata->getAttributesMetadata();
            foreach ($yaml['attributes'] as $attribute => $data) {
                if (isset($attributesMetadata[$attribute])) {
                    $attributeMetadata = $attributesMetadata[$attribute];
                } else {
                    $attributeMetadata = new AttributeMetadata($attribute);
                    $classMetadata->addAttributeMetadata($attributeMetadata);
                }
                if (isset($data['groups'])) {
                    if (!\is_array($data['groups'])) {
                        throw new MappingException(\sprintf('The "groups" key must be an array of strings in "%s" for the attribute "%s" of the class "%s".', $this->file, $attribute, $classMetadata->getName()));
                    }
                    foreach ($data['groups'] as $group) {
                        if (!\is_string($group)) {
                            throw new MappingException(\sprintf('Group names must be strings in "%s" for the attribute "%s" of the class "%s".', $this->file, $attribute, $classMetadata->getName()));
                        }
                        $attributeMetadata->addGroup($group);
                    }
                }
                if (isset($data['max_depth'])) {
                    if (!\is_int($data['max_depth'])) {
                        throw new MappingException(\sprintf('The "max_depth" value must be an integer in "%s" for the attribute "%s" of the class "%s".', $this->file, $attribute, $classMetadata->getName()));
                    }
                    $attributeMetadata->setMaxDepth($data['max_depth']);
                }
                if (isset($data['serialized_name'])) {
                    if (!\is_string($data['serialized_name']) || '' === $data['serialized_name']) {
                        throw new MappingException(\sprintf('The "serialized_name" value must be a non-empty string in "%s" for the attribute "%s" of the class "%s".', $this->file, $attribute, $classMetadata->getName()));
                    }
                    $attributeMetadata->setSerializedName($data['serialized_name']);
                }
                if (isset($data['serialized_path'])) {
                    try {
                        $attributeMetadata->setSerializedPath(new PropertyPath((string) $data['serialized_path']));
                    } catch (InvalidPropertyPathException) {
                        throw new MappingException(\sprintf('The "serialized_path" value must be a valid property path in "%s" for the attribute "%s" of the class "%s".', $this->file, $attribute, $classMetadata->getName()));
                    }
                }
                if (isset($data['ignore'])) {
                    if (!\is_bool($data['ignore'])) {
                        throw new MappingException(\sprintf('The "ignore" value must be a boolean in "%s" for the attribute "%s" of the class "%s".', $this->file, $attribute, $classMetadata->getName()));
                    }
                    $attributeMetadata->setIgnore($data['ignore']);
                }
                foreach ($data['contexts'] ?? [] as $line) {
                    $groups = $line['groups'] ?? [];
                    if ($context = $line['context'] ?? \false) {
                        $attributeMetadata->setNormalizationContextForGroups($context, $groups);
                        $attributeMetadata->setDenormalizationContextForGroups($context, $groups);
                    }
                    if ($context = $line['normalization_context'] ?? \false) {
                        $attributeMetadata->setNormalizationContextForGroups($context, $groups);
                    }
                    if ($context = $line['denormalization_context'] ?? \false) {
                        $attributeMetadata->setDenormalizationContextForGroups($context, $groups);
                    }
                }
            }
        }
        if (isset($yaml['discriminator_map'])) {
            if (!isset($yaml['discriminator_map']['type_property'])) {
                throw new MappingException(\sprintf('The "type_property" key must be set for the discriminator map of the class "%s" in "%s".', $classMetadata->getName(), $this->file));
            }
            if (!isset($yaml['discriminator_map']['mapping'])) {
                throw new MappingException(\sprintf('The "mapping" key must be set for the discriminator map of the class "%s" in "%s".', $classMetadata->getName(), $this->file));
            }
            $classMetadata->setClassDiscriminatorMapping(new ClassDiscriminatorMapping($yaml['discriminator_map']['type_property'], $yaml['discriminator_map']['mapping']));
        }
        return \true;
    }
    /**
     * Return the names of the classes mapped in this file.
     *
     * @return string[]
     */
    public function getMappedClasses(): array
    {
        return array_keys($this->classes ??= $this->getClassesFromYaml());
    }
    private function getClassesFromYaml(): array
    {
        if (!stream_is_local($this->file)) {
            throw new MappingException(\sprintf('This is not a local file "%s".', $this->file));
        }
        $this->yamlParser ??= new Parser();
        $classes = $this->yamlParser->parseFile($this->file, Yaml::PARSE_CONSTANT);
        if (empty($classes)) {
            return [];
        }
        if (!\is_array($classes)) {
            throw new MappingException(\sprintf('The file "%s" must contain a YAML array.', $this->file));
        }
        return $classes;
    }
}
<?xml version="1.0" ?>

<xsd:schema xmlns="http://symfony.com/schema/dic/serializer-mapping"
            xmlns:xsd="http://www.w3.org/2001/XMLSchema"
            targetNamespace="http://symfony.com/schema/dic/serializer-mapping"
            elementFormDefault="qualified">

    <xsd:annotation>
        <xsd:documentation><![CDATA[
      Symfony Serializer Mapping Schema, version 1.0
      Authors: Kévin Dunglas, Samuel Roze

      A serializer mapping connects attributes with serialization groups.
    ]]></xsd:documentation>
    </xsd:annotation>

    <xsd:element name="serializer" type="serializer" />

    <xsd:complexType name="serializer">
        <xsd:annotation>
            <xsd:documentation><![CDATA[
        The root element of the serializer mapping definition.
      ]]></xsd:documentation>
        </xsd:annotation>
        <xsd:choice minOccurs="0" maxOccurs="unbounded">
            <xsd:element name="class" type="class" />
        </xsd:choice>
    </xsd:complexType>

    <xsd:complexType name="class">
        <xsd:annotation>
            <xsd:documentation><![CDATA[
        Contains serialization groups for a single class.

        Nested elements may be class property and/or getter definitions.
      ]]></xsd:documentation>
        </xsd:annotation>
        <xsd:choice minOccurs="0" maxOccurs="unbounded">
            <xsd:element name="attribute" type="attribute" minOccurs="0" maxOccurs="unbounded" />
            <xsd:element name="discriminator-map" type="discriminator-map" />
        </xsd:choice>
        <xsd:attribute name="name" type="xsd:string" use="required" />
    </xsd:complexType>

    <xsd:complexType name="discriminator-map">
        <xsd:choice minOccurs="0" maxOccurs="unbounded">
            <xsd:element name="mapping" type="discriminator-map-mapping" maxOccurs="unbounded" />
        </xsd:choice>
        <xsd:attribute name="type-property" type="xsd:string" use="required" />
    </xsd:complexType>

    <xsd:complexType name="discriminator-map-mapping">
        <xsd:attribute name="type" type="xsd:string" use="required" />
        <xsd:attribute name="class" type="xsd:string" use="required" />
    </xsd:complexType>

    <xsd:complexType name="attribute">
        <xsd:annotation>
            <xsd:documentation><![CDATA[
        Contains serialization groups and max depth for attributes. The name of the attribute should be given in the "name" option.
      ]]></xsd:documentation>
        </xsd:annotation>
        <xsd:choice minOccurs="0" maxOccurs="unbounded">
            <xsd:element name="group" type="xsd:string" maxOccurs="unbounded" />
            <xsd:element name="context" type="context" maxOccurs="unbounded" />
            <xsd:element name="normalization_context" type="context" maxOccurs="unbounded" />
            <xsd:element name="denormalization_context" type="context" maxOccurs="unbounded" />
        </xsd:choice>
        <xsd:attribute name="name" type="xsd:string" use="required" />
        <xsd:attribute name="max-depth">
            <xsd:simpleType>
                <xsd:restriction base="xsd:integer">
                    <xsd:minInclusive value="0" />
                </xsd:restriction>
            </xsd:simpleType>
        </xsd:attribute>
        <xsd:attribute name="serialized-name">
            <xsd:simpleType>
                <xsd:restriction base="xsd:string">
                    <xsd:minLength value="1" />
                </xsd:restriction>
            </xsd:simpleType>
        </xsd:attribute>
        <xsd:attribute name="serialized-path">
            <xsd:simpleType>
                <xsd:restriction base="xsd:string">
                    <xsd:minLength value="1" />
                </xsd:restriction>
            </xsd:simpleType>
        </xsd:attribute>
        <xsd:attribute name="ignore" type="xsd:boolean" />
    </xsd:complexType>

    <xsd:complexType name="context">
        <xsd:choice maxOccurs="unbounded">
            <xsd:element name="group" type="xsd:string" minOccurs="0" maxOccurs="unbounded" />
            <xsd:element name="entry" type="context-root-entry" maxOccurs="unbounded" />
        </xsd:choice>
    </xsd:complexType>

    <xsd:complexType name="context-root-entry" mixed="true">
        <xsd:sequence minOccurs="0">
            <xsd:element name="entry" type="context-entry" maxOccurs="unbounded" />
        </xsd:sequence>
        <xsd:attribute type="xsd:string" name="name" use="required" />
    </xsd:complexType>

    <xsd:complexType name="context-entry" mixed="true">
        <xsd:sequence minOccurs="0">
            <xsd:element name="entry" type="context-entry" maxOccurs="unbounded" />
        </xsd:sequence>
        <xsd:attribute type="xsd:string" name="name" />
    </xsd:complexType>

</xsd:schema>
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Serializer\Mapping\Loader;

use _ContaoManager\Symfony\Component\Config\Util\XmlUtils;
use _ContaoManager\Symfony\Component\PropertyAccess\Exception\InvalidPropertyPathException;
use _ContaoManager\Symfony\Component\PropertyAccess\PropertyPath;
use _ContaoManager\Symfony\Component\Serializer\Exception\MappingException;
use _ContaoManager\Symfony\Component\Serializer\Mapping\AttributeMetadata;
use _ContaoManager\Symfony\Component\Serializer\Mapping\ClassDiscriminatorMapping;
use _ContaoManager\Symfony\Component\Serializer\Mapping\ClassMetadataInterface;
/**
 * Loads XML mapping files.
 *
 * @author Kévin Dunglas <dunglas@gmail.com>
 */
class XmlFileLoader extends FileLoader
{
    /**
     * An array of {@class \SimpleXMLElement} instances.
     *
     * @var \SimpleXMLElement[]|null
     */
    private ?array $classes = null;
    public function loadClassMetadata(ClassMetadataInterface $classMetadata): bool
    {
        if (!$this->classes ??= $this->getClassesFromXml()) {
            return \false;
        }
        $attributesMetadata = $classMetadata->getAttributesMetadata();
        if (isset($this->classes[$classMetadata->getName()])) {
            $xml = $this->classes[$classMetadata->getName()];
            foreach ($xml->attribute as $attribute) {
                $attributeName = (string) $attribute['name'];
                if (isset($attributesMetadata[$attributeName])) {
                    $attributeMetadata = $attributesMetadata[$attributeName];
                } else {
                    $attributeMetadata = new AttributeMetadata($attributeName);
                    $classMetadata->addAttributeMetadata($attributeMetadata);
                }
                foreach ($attribute->group as $group) {
                    $attributeMetadata->addGroup((string) $group);
                }
                if (isset($attribute['max-depth'])) {
                    $attributeMetadata->setMaxDepth((int) $attribute['max-depth']);
                }
                if (isset($attribute['serialized-name'])) {
                    $attributeMetadata->setSerializedName((string) $attribute['serialized-name']);
                }
                if (isset($attribute['serialized-path'])) {
                    try {
                        $attributeMetadata->setSerializedPath(new PropertyPath((string) $attribute['serialized-path']));
                    } catch (InvalidPropertyPathException) {
                        throw new MappingException(\sprintf('The "serialized-path" value must be a valid property path for the attribute "%s" of the class "%s".', $attributeName, $classMetadata->getName()));
                    }
                }
                if (isset($attribute['ignore'])) {
                    $attributeMetadata->setIgnore(XmlUtils::phpize($attribute['ignore']));
                }
                foreach ($attribute->context as $node) {
                    $groups = (array) $node->group;
                    $context = $this->parseContext($node->entry);
                    $attributeMetadata->setNormalizationContextForGroups($context, $groups);
                    $attributeMetadata->setDenormalizationContextForGroups($context, $groups);
                }
                foreach ($attribute->normalization_context as $node) {
                    $groups = (array) $node->group;
                    $context = $this->parseContext($node->entry);
                    $attributeMetadata->setNormalizationContextForGroups($context, $groups);
                }
                foreach ($attribute->denormalization_context as $node) {
                    $groups = (array) $node->group;
                    $context = $this->parseContext($node->entry);
                    $attributeMetadata->setDenormalizationContextForGroups($context, $groups);
                }
            }
            if (isset($xml->{'discriminator-map'})) {
                $mapping = [];
                foreach ($xml->{'discriminator-map'}->mapping as $element) {
                    $elementAttributes = $element->attributes();
                    $mapping[(string) $elementAttributes->type] = (string) $elementAttributes->class;
                }
                $classMetadata->setClassDiscriminatorMapping(new ClassDiscriminatorMapping((string) $xml->{'discriminator-map'}->attributes()->{'type-property'}, $mapping));
            }
            return \true;
        }
        return \false;
    }
    /**
     * Return the names of the classes mapped in this file.
     *
     * @return string[]
     */
    public function getMappedClasses(): array
    {
        return array_keys($this->classes ??= $this->getClassesFromXml());
    }
    /**
     * Parses an XML File.
     *
     * @throws MappingException
     */
    private function parseFile(string $file): \SimpleXMLElement
    {
        try {
            $dom = XmlUtils::loadFile($file, __DIR__ . '/schema/dic/serializer-mapping/serializer-mapping-1.0.xsd');
        } catch (\Exception $e) {
            throw new MappingException($e->getMessage(), $e->getCode(), $e);
        }
        return simplexml_import_dom($dom);
    }
    private function getClassesFromXml(): array
    {
        $xml = $this->parseFile($this->file);
        $classes = [];
        foreach ($xml->class as $class) {
            $classes[(string) $class['name']] = $class;
        }
        return $classes;
    }
    private function parseContext(\SimpleXMLElement $nodes): array
    {
        $context = [];
        foreach ($nodes as $node) {
            if (\count($node) > 0) {
                if (\count($node->entry) > 0) {
                    $value = $this->parseContext($node->entry);
                } else {
                    $value = [];
                }
            } else {
                $value = XmlUtils::phpize($node);
            }
            if (isset($node['name'])) {
                $context[(string) $node['name']] = $value;
            } else {
                $context[] = $value;
            }
        }
        return $context;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Serializer\Mapping\Loader;

use _ContaoManager\Symfony\Component\Serializer\Exception\MappingException;
use _ContaoManager\Symfony\Component\Serializer\Mapping\ClassMetadataInterface;
/**
 * Calls multiple {@link LoaderInterface} instances in a chain.
 *
 * This class accepts multiple instances of LoaderInterface to be passed to the
 * constructor. When {@link loadClassMetadata()} is called, the same method is called
 * in <em>all</em> of these loaders, regardless of whether any of them was
 * successful or not.
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 * @author Kévin Dunglas <dunglas@gmail.com>
 */
class LoaderChain implements LoaderInterface
{
    /**
     * Accepts a list of LoaderInterface instances.
     *
     * @param LoaderInterface[] $loaders An array of LoaderInterface instances
     *
     * @throws MappingException If any of the loaders does not implement LoaderInterface
     */
    public function __construct(private readonly array $loaders)
    {
        foreach ($loaders as $loader) {
            if (!$loader instanceof LoaderInterface) {
                throw new MappingException(\sprintf('Class "%s" is expected to implement LoaderInterface.', get_debug_type($loader)));
            }
        }
    }
    public function loadClassMetadata(ClassMetadataInterface $metadata): bool
    {
        $success = \false;
        foreach ($this->loaders as $loader) {
            $success = $loader->loadClassMetadata($metadata) || $success;
        }
        return $success;
    }
    /**
     * @return LoaderInterface[]
     */
    public function getLoaders(): array
    {
        return $this->loaders;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Serializer\Mapping\Loader;

trigger_deprecation('symfony/serializer', '6.4', 'The "%s" class is deprecated, use "%s" instead.', AnnotationLoader::class, AttributeLoader::class);
class_exists(AttributeLoader::class);
if (\false) {
    /**
     * @deprecated since Symfony 6.4, to be removed in 7.0, use {@link AttributeLoader} instead
     */
    class AnnotationLoader extends AttributeLoader
    {
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Serializer\Mapping;

/**
 * Knows how to get the class discriminator mapping for classes and objects.
 *
 * @author Samuel Roze <samuel.roze@gmail.com>
 */
interface ClassDiscriminatorResolverInterface
{
    public function getMappingForClass(string $class): ?ClassDiscriminatorMapping;
    public function getMappingForMappedObject(object|string $object): ?ClassDiscriminatorMapping;
    public function getTypeForMappedObject(object|string $object): ?string;
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Serializer\Mapping;

use _ContaoManager\Symfony\Component\PropertyAccess\PropertyPath;
/**
 * Stores metadata needed for serializing and deserializing attributes.
 *
 * Primarily, the metadata stores serialization groups.
 *
 * @internal
 *
 * @author Kévin Dunglas <dunglas@gmail.com>
 */
interface AttributeMetadataInterface
{
    /**
     * Gets the attribute name.
     */
    public function getName(): string;
    /**
     * Adds this attribute to the given group.
     */
    public function addGroup(string $group): void;
    /**
     * Gets groups of this attribute.
     *
     * @return string[]
     */
    public function getGroups(): array;
    /**
     * Sets the serialization max depth for this attribute.
     */
    public function setMaxDepth(?int $maxDepth): void;
    /**
     * Gets the serialization max depth for this attribute.
     */
    public function getMaxDepth(): ?int;
    /**
     * Sets the serialization name for this attribute.
     */
    public function setSerializedName(?string $serializedName): void;
    /**
     * Gets the serialization name for this attribute.
     */
    public function getSerializedName(): ?string;
    public function setSerializedPath(?PropertyPath $serializedPath): void;
    public function getSerializedPath(): ?PropertyPath;
    /**
     * Sets if this attribute must be ignored or not.
     */
    public function setIgnore(bool $ignore): void;
    /**
     * Gets if this attribute is ignored or not.
     */
    public function isIgnored(): bool;
    /**
     * Merges an {@see AttributeMetadataInterface} with in the current one.
     */
    public function merge(self $attributeMetadata): void;
    /**
     * Gets all the normalization contexts per group ("*" being the base context applied to all groups).
     */
    public function getNormalizationContexts(): array;
    /**
     * Gets the computed normalization contexts for given groups.
     */
    public function getNormalizationContextForGroups(array $groups): array;
    /**
     * Sets the normalization context for given groups.
     */
    public function setNormalizationContextForGroups(array $context, array $groups = []): void;
    /**
     * Gets all the denormalization contexts per group ("*" being the base context applied to all groups).
     */
    public function getDenormalizationContexts(): array;
    /**
     * Gets the computed denormalization contexts for given groups.
     */
    public function getDenormalizationContextForGroups(array $groups): array;
    /**
     * Sets the denormalization context for given groups.
     */
    public function setDenormalizationContextForGroups(array $context, array $groups = []): void;
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Serializer\Mapping;

/**
 * @author Samuel Roze <samuel.roze@gmail.com>
 */
class ClassDiscriminatorMapping
{
    /**
     * @param array<string, string> $typesMapping
     */
    public function __construct(private readonly string $typeProperty, private array $typesMapping = [])
    {
        uasort($this->typesMapping, static function (string $a, string $b): int {
            if (is_a($a, $b, \true)) {
                return -1;
            }
            if (is_a($b, $a, \true)) {
                return 1;
            }
            return 0;
        });
    }
    public function getTypeProperty(): string
    {
        return $this->typeProperty;
    }
    public function getClassForType(string $type): ?string
    {
        return $this->typesMapping[$type] ?? null;
    }
    public function getMappedObjectType(object|string $object): ?string
    {
        foreach ($this->typesMapping as $type => $typeClass) {
            if (is_a($object, $typeClass, \true)) {
                return $type;
            }
        }
        return null;
    }
    public function getTypesMapping(): array
    {
        return $this->typesMapping;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Serializer\Mapping\Factory;

use _ContaoManager\Symfony\Component\Serializer\Mapping\ClassMetadataInterface;
use _ContaoManager\Symfony\Component\VarExporter\VarExporter;
/**
 * @author Fabien Bourigault <bourigaultfabien@gmail.com>
 */
final class ClassMetadataFactoryCompiler
{
    /**
     * @param ClassMetadataInterface[] $classMetadatas
     */
    public function compile(array $classMetadatas): string
    {
        return <<<EOF
<?php

// This file has been auto-generated by the Symfony Serializer Component.

return [{$this->generateDeclaredClassMetadata($classMetadatas)}
];
EOF;
    }
    /**
     * @param ClassMetadataInterface[] $classMetadatas
     */
    private function generateDeclaredClassMetadata(array $classMetadatas): string
    {
        $compiled = '';
        foreach ($classMetadatas as $classMetadata) {
            $attributesMetadata = [];
            foreach ($classMetadata->getAttributesMetadata() as $attributeMetadata) {
                $attributesMetadata[$attributeMetadata->getName()] = [$attributeMetadata->getGroups(), $attributeMetadata->getMaxDepth(), $attributeMetadata->getSerializedName(), $attributeMetadata->getSerializedPath()];
            }
            $classDiscriminatorMapping = $classMetadata->getClassDiscriminatorMapping() ? [$classMetadata->getClassDiscriminatorMapping()->getTypeProperty(), $classMetadata->getClassDiscriminatorMapping()->getTypesMapping()] : null;
            $compiled .= \sprintf("\n'%s' => %s,", $classMetadata->getName(), VarExporter::export([$attributesMetadata, $classDiscriminatorMapping]));
        }
        return $compiled;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Serializer\Mapping\Factory;

use _ContaoManager\Symfony\Component\Serializer\Exception\InvalidArgumentException;
/**
 * Resolves a class name.
 *
 * @internal
 *
 * @author Kévin Dunglas <dunglas@gmail.com>
 */
trait ClassResolverTrait
{
    /**
     * Gets a class name for a given class or instance.
     *
     * @throws InvalidArgumentException If the class does not exist
     */
    private function getClass(object|string $value): string
    {
        if (\is_string($value)) {
            if (!class_exists($value) && !interface_exists($value, \false)) {
                throw new InvalidArgumentException(\sprintf('The class or interface "%s" does not exist.', $value));
            }
            return ltrim($value, '\\');
        }
        return $value::class;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Serializer\Mapping\Factory;

use _ContaoManager\Symfony\Component\Serializer\Mapping\ClassMetadata;
use _ContaoManager\Symfony\Component\Serializer\Mapping\ClassMetadataInterface;
use _ContaoManager\Symfony\Component\Serializer\Mapping\Loader\LoaderInterface;
/**
 * Returns a {@link ClassMetadata}.
 *
 * @author Kévin Dunglas <dunglas@gmail.com>
 */
class ClassMetadataFactory implements ClassMetadataFactoryInterface
{
    use ClassResolverTrait;
    /**
     * @var array<string, ClassMetadataInterface>
     */
    private array $loadedClasses;
    public function __construct(private readonly LoaderInterface $loader)
    {
    }
    public function getMetadataFor(string|object $value): ClassMetadataInterface
    {
        $class = $this->getClass($value);
        if (isset($this->loadedClasses[$class])) {
            return $this->loadedClasses[$class];
        }
        $classMetadata = new ClassMetadata($class);
        $this->loader->loadClassMetadata($classMetadata);
        $reflectionClass = $classMetadata->getReflectionClass();
        // Include metadata from the parent class
        if ($parent = $reflectionClass->getParentClass()) {
            $classMetadata->merge($this->getMetadataFor($parent->name));
        }
        // Include metadata from all implemented interfaces
        foreach ($reflectionClass->getInterfaces() as $interface) {
            $classMetadata->merge($this->getMetadataFor($interface->name));
        }
        return $this->loadedClasses[$class] = $classMetadata;
    }
    public function hasMetadataFor(mixed $value): bool
    {
        return \is_object($value) || \is_string($value) && (class_exists($value) || interface_exists($value, \false));
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Serializer\Mapping\Factory;

use _ContaoManager\Psr\Cache\CacheItemPoolInterface;
use _ContaoManager\Symfony\Component\Serializer\Mapping\ClassMetadataInterface;
/**
 * Caches metadata using a PSR-6 implementation.
 *
 * @author Kévin Dunglas <dunglas@gmail.com>
 */
class CacheClassMetadataFactory implements ClassMetadataFactoryInterface
{
    use ClassResolverTrait;
    /**
     * @var array<string, ClassMetadataInterface>
     */
    private array $loadedClasses = [];
    public function __construct(private readonly ClassMetadataFactoryInterface $decorated, private readonly CacheItemPoolInterface $cacheItemPool)
    {
    }
    public function getMetadataFor(string|object $value): ClassMetadataInterface
    {
        $class = $this->getClass($value);
        if (isset($this->loadedClasses[$class])) {
            return $this->loadedClasses[$class];
        }
        $key = rawurlencode(strtr($class, '\\', '_'));
        $item = $this->cacheItemPool->getItem($key);
        if ($item->isHit()) {
            return $this->loadedClasses[$class] = $item->get();
        }
        $metadata = $this->decorated->getMetadataFor($value);
        $this->cacheItemPool->save($item->set($metadata));
        return $this->loadedClasses[$class] = $metadata;
    }
    public function hasMetadataFor(mixed $value): bool
    {
        return $this->decorated->hasMetadataFor($value);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Serializer\Mapping\Factory;

use _ContaoManager\Symfony\Component\Serializer\Mapping\AttributeMetadata;
use _ContaoManager\Symfony\Component\Serializer\Mapping\ClassDiscriminatorMapping;
use _ContaoManager\Symfony\Component\Serializer\Mapping\ClassMetadata;
use _ContaoManager\Symfony\Component\Serializer\Mapping\ClassMetadataInterface;
/**
 * @author Fabien Bourigault <bourigaultfabien@gmail.com>
 */
final class CompiledClassMetadataFactory implements ClassMetadataFactoryInterface
{
    private array $compiledClassMetadata = [];
    private array $loadedClasses = [];
    public function __construct(string $compiledClassMetadataFile, private readonly ClassMetadataFactoryInterface $classMetadataFactory)
    {
        if (!file_exists($compiledClassMetadataFile)) {
            throw new \RuntimeException("File \"{$compiledClassMetadataFile}\" could not be found.");
        }
        $compiledClassMetadata = require $compiledClassMetadataFile;
        if (!\is_array($compiledClassMetadata)) {
            throw new \RuntimeException(\sprintf('Compiled metadata must be of the type array, %s given.', \gettype($compiledClassMetadata)));
        }
        $this->compiledClassMetadata = $compiledClassMetadata;
    }
    public function getMetadataFor(string|object $value): ClassMetadataInterface
    {
        $className = \is_object($value) ? $value::class : $value;
        if (!isset($this->compiledClassMetadata[$className])) {
            return $this->classMetadataFactory->getMetadataFor($value);
        }
        if (!isset($this->loadedClasses[$className])) {
            $classMetadata = new ClassMetadata($className);
            foreach ($this->compiledClassMetadata[$className][0] as $name => $compiledAttributesMetadata) {
                $classMetadata->attributesMetadata[$name] = $attributeMetadata = new AttributeMetadata($name);
                [$attributeMetadata->groups, $attributeMetadata->maxDepth, $attributeMetadata->serializedName] = $compiledAttributesMetadata;
            }
            $classMetadata->classDiscriminatorMapping = $this->compiledClassMetadata[$className][1] ? new ClassDiscriminatorMapping(...$this->compiledClassMetadata[$className][1]) : null;
            $this->loadedClasses[$className] = $classMetadata;
        }
        return $this->loadedClasses[$className];
    }
    public function hasMetadataFor(mixed $value): bool
    {
        $className = \is_object($value) ? $value::class : $value;
        return isset($this->compiledClassMetadata[$className]) || $this->classMetadataFactory->hasMetadataFor($value);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Serializer\Mapping\Factory;

use _ContaoManager\Symfony\Component\Serializer\Exception\InvalidArgumentException;
use _ContaoManager\Symfony\Component\Serializer\Mapping\ClassMetadataInterface;
/**
 * Returns a {@see ClassMetadataInterface}.
 *
 * @author Kévin Dunglas <dunglas@gmail.com>
 */
interface ClassMetadataFactoryInterface
{
    /**
     * If the method was called with the same class name (or an object of that
     * class) before, the same metadata instance is returned.
     *
     * If the factory was configured with a cache, this method will first look
     * for an existing metadata instance in the cache. If an existing instance
     * is found, it will be returned without further ado.
     *
     * Otherwise, a new metadata instance is created. If the factory was
     * configured with a loader, the metadata is passed to the
     * {@link \Symfony\Component\Serializer\Mapping\Loader\LoaderInterface::loadClassMetadata()} method for further
     * configuration. At last, the new object is returned.
     *
     * @throws InvalidArgumentException
     */
    public function getMetadataFor(string|object $value): ClassMetadataInterface;
    /**
     * Checks if class has metadata.
     */
    public function hasMetadataFor(mixed $value): bool;
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Serializer\Mapping;

use _ContaoManager\Symfony\Component\PropertyAccess\PropertyPath;
/**
 * @author Kévin Dunglas <dunglas@gmail.com>
 */
class AttributeMetadata implements AttributeMetadataInterface
{
    /**
     * @internal This property is public in order to reduce the size of the
     *           class' serialized representation. Do not access it. Use
     *           {@link getName()} instead.
     */
    public string $name;
    /**
     * @internal This property is public in order to reduce the size of the
     *           class' serialized representation. Do not access it. Use
     *           {@link getGroups()} instead.
     */
    public array $groups = [];
    /**
     * @internal This property is public in order to reduce the size of the
     *           class' serialized representation. Do not access it. Use
     *           {@link getMaxDepth()} instead.
     */
    public ?int $maxDepth = null;
    /**
     * @internal This property is public in order to reduce the size of the
     *           class' serialized representation. Do not access it. Use
     *           {@link getSerializedName()} instead.
     */
    public ?string $serializedName = null;
    /**
     * @internal This property is public in order to reduce the size of the
     *           class' serialized representation. Do not access it. Use
     *           {@link getSerializedPath()} instead.
     */
    public ?PropertyPath $serializedPath = null;
    /**
     * @internal This property is public in order to reduce the size of the
     *           class' serialized representation. Do not access it. Use
     *           {@link isIgnored()} instead.
     */
    public bool $ignore = \false;
    /**
     * @var array[] Normalization contexts per group name ("*" applies to all groups)
     *
     * @internal This property is public in order to reduce the size of the
     *           class' serialized representation. Do not access it. Use
     *           {@link getNormalizationContexts()} instead.
     */
    public array $normalizationContexts = [];
    /**
     * @var array[] Denormalization contexts per group name ("*" applies to all groups)
     *
     * @internal This property is public in order to reduce the size of the
     *           class' serialized representation. Do not access it. Use
     *           {@link getDenormalizationContexts()} instead.
     */
    public array $denormalizationContexts = [];
    public function __construct(string $name)
    {
        $this->name = $name;
    }
    public function getName(): string
    {
        return $this->name;
    }
    public function addGroup(string $group): void
    {
        if (!\in_array($group, $this->groups)) {
            $this->groups[] = $group;
        }
    }
    public function getGroups(): array
    {
        return $this->groups;
    }
    public function setMaxDepth(?int $maxDepth): void
    {
        $this->maxDepth = $maxDepth;
    }
    public function getMaxDepth(): ?int
    {
        return $this->maxDepth;
    }
    public function setSerializedName(?string $serializedName = null): void
    {
        if (1 > \func_num_args()) {
            trigger_deprecation('symfony/serializer', '6.2', 'Calling "%s()" without any arguments is deprecated, pass null explicitly instead.', __METHOD__);
        }
        $this->serializedName = $serializedName;
    }
    public function getSerializedName(): ?string
    {
        return $this->serializedName;
    }
    public function setSerializedPath(?PropertyPath $serializedPath = null): void
    {
        $this->serializedPath = $serializedPath;
    }
    public function getSerializedPath(): ?PropertyPath
    {
        return $this->serializedPath;
    }
    public function setIgnore(bool $ignore): void
    {
        $this->ignore = $ignore;
    }
    public function isIgnored(): bool
    {
        return $this->ignore;
    }
    public function getNormalizationContexts(): array
    {
        return $this->normalizationContexts;
    }
    public function getNormalizationContextForGroups(array $groups): array
    {
        $contexts = [];
        foreach ($groups as $group) {
            $contexts[] = $this->normalizationContexts[$group] ?? [];
        }
        return array_merge($this->normalizationContexts['*'] ?? [], ...$contexts);
    }
    public function setNormalizationContextForGroups(array $context, array $groups = []): void
    {
        if (!$groups) {
            $this->normalizationContexts['*'] = $context;
        }
        foreach ($groups as $group) {
            $this->normalizationContexts[$group] = $context;
        }
    }
    public function getDenormalizationContexts(): array
    {
        return $this->denormalizationContexts;
    }
    public function getDenormalizationContextForGroups(array $groups): array
    {
        $contexts = [];
        foreach ($groups as $group) {
            $contexts[] = $this->denormalizationContexts[$group] ?? [];
        }
        return array_merge($this->denormalizationContexts['*'] ?? [], ...$contexts);
    }
    public function setDenormalizationContextForGroups(array $context, array $groups = []): void
    {
        if (!$groups) {
            $this->denormalizationContexts['*'] = $context;
        }
        foreach ($groups as $group) {
            $this->denormalizationContexts[$group] = $context;
        }
    }
    public function merge(AttributeMetadataInterface $attributeMetadata): void
    {
        foreach ($attributeMetadata->getGroups() as $group) {
            $this->addGroup($group);
        }
        // Overwrite only if not defined
        $this->maxDepth ??= $attributeMetadata->getMaxDepth();
        $this->serializedName ??= $attributeMetadata->getSerializedName();
        $this->serializedPath ??= $attributeMetadata->getSerializedPath();
        // Overwrite only if both contexts are empty
        if (!$this->normalizationContexts && !$this->denormalizationContexts) {
            $this->normalizationContexts = $attributeMetadata->getNormalizationContexts();
            $this->denormalizationContexts = $attributeMetadata->getDenormalizationContexts();
        }
        if ($ignore = $attributeMetadata->isIgnored()) {
            $this->ignore = $ignore;
        }
    }
    /**
     * Returns the names of the properties that should be serialized.
     *
     * @return string[]
     */
    public function __sleep(): array
    {
        return ['name', 'groups', 'maxDepth', 'serializedName', 'serializedPath', 'ignore', 'normalizationContexts', 'denormalizationContexts'];
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Serializer;

/**
 * @author Jordi Boggiano <j.boggiano@seld.be>
 */
interface SerializerInterface
{
    /**
     * Serializes data in the appropriate format.
     *
     * @param array<string, mixed> $context Options normalizers/encoders have access to
     */
    public function serialize(mixed $data, string $format, array $context = []): string;
    /**
     * Deserializes data into the given type.
     *
     * @template TObject of object
     * @template TType of string|class-string<TObject>
     *
     * @param TType                $type
     * @param array<string, mixed> $context
     *
     * @phpstan-return ($type is class-string<TObject> ? TObject : mixed)
     *
     * @psalm-return (TType is class-string<TObject> ? TObject : mixed)
     */
    public function deserialize(mixed $data, string $type, string $format, array $context = []): mixed;
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Serializer\Context\Encoder;

use _ContaoManager\Symfony\Component\Serializer\Context\ContextBuilderInterface;
use _ContaoManager\Symfony\Component\Serializer\Context\ContextBuilderTrait;
use _ContaoManager\Symfony\Component\Serializer\Encoder\CsvEncoder;
use _ContaoManager\Symfony\Component\Serializer\Exception\InvalidArgumentException;
/**
 * A helper providing autocompletion for available CsvEncoder options.
 *
 * @author Mathias Arlaud <mathias.arlaud@gmail.com>
 */
final class CsvEncoderContextBuilder implements ContextBuilderInterface
{
    use ContextBuilderTrait;
    /**
     * Configures the column delimiter character.
     *
     * Must be a single character.
     *
     * @throws InvalidArgumentException
     */
    public function withDelimiter(?string $delimiter): static
    {
        if (null !== $delimiter && 1 !== \strlen($delimiter)) {
            throw new InvalidArgumentException(\sprintf('The "%s" delimiter must be a single character.', $delimiter));
        }
        return $this->with(CsvEncoder::DELIMITER_KEY, $delimiter);
    }
    /**
     * Configures the field enclosure character.
     *
     * Must be a single character.
     *
     * @throws InvalidArgumentException
     */
    public function withEnclosure(?string $enclosure): static
    {
        if (null !== $enclosure && 1 !== \strlen($enclosure)) {
            throw new InvalidArgumentException(\sprintf('The "%s" enclosure must be a single character.', $enclosure));
        }
        return $this->with(CsvEncoder::ENCLOSURE_KEY, $enclosure);
    }
    /**
     * Configures the escape character.
     *
     * Must be empty or a single character.
     *
     * @throws InvalidArgumentException
     */
    public function withEscapeChar(?string $escapeChar): static
    {
        if (null !== $escapeChar && \strlen($escapeChar) > 1) {
            throw new InvalidArgumentException(\sprintf('The "%s" escape character must be empty or a single character.', $escapeChar));
        }
        return $this->with(CsvEncoder::ESCAPE_CHAR_KEY, $escapeChar);
    }
    /**
     * Configures the key separator when (un)flattening arrays.
     */
    public function withKeySeparator(?string $keySeparator): static
    {
        return $this->with(CsvEncoder::KEY_SEPARATOR_KEY, $keySeparator);
    }
    /**
     * Configures the headers.
     *
     * @param list<mixed>|null $headers
     */
    public function withHeaders(?array $headers): static
    {
        return $this->with(CsvEncoder::HEADERS_KEY, $headers);
    }
    /**
     * Configures whether formulas should be escaped.
     */
    public function withEscapedFormulas(?bool $escapedFormulas): static
    {
        return $this->with(CsvEncoder::ESCAPE_FORMULAS_KEY, $escapedFormulas);
    }
    /**
     * Configures whether the decoded result should be considered as a collection
     * or as a single element.
     */
    public function withAsCollection(?bool $asCollection): static
    {
        return $this->with(CsvEncoder::AS_COLLECTION_KEY, $asCollection);
    }
    /**
     * Configures whether the input (or output) is containing (or will contain) headers.
     */
    public function withNoHeaders(?bool $noHeaders): static
    {
        return $this->with(CsvEncoder::NO_HEADERS_KEY, $noHeaders);
    }
    /**
     * Configures the end of line characters.
     */
    public function withEndOfLine(?string $endOfLine): static
    {
        return $this->with(CsvEncoder::END_OF_LINE, $endOfLine);
    }
    /**
     * Configures whether to add the UTF-8 Byte Order Mark (BOM)
     * at the beginning of the encoded result or not.
     */
    public function withOutputUtf8Bom(?bool $outputUtf8Bom): static
    {
        return $this->with(CsvEncoder::OUTPUT_UTF8_BOM_KEY, $outputUtf8Bom);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Serializer\Context\Encoder;

use _ContaoManager\Symfony\Component\Serializer\Context\ContextBuilderInterface;
use _ContaoManager\Symfony\Component\Serializer\Context\ContextBuilderTrait;
use _ContaoManager\Symfony\Component\Serializer\Encoder\XmlEncoder;
/**
 * A helper providing autocompletion for available XmlEncoder options.
 *
 * @author Mathias Arlaud <mathias.arlaud@gmail.com>
 */
final class XmlEncoderContextBuilder implements ContextBuilderInterface
{
    use ContextBuilderTrait;
    /**
     * Configures whether the decoded result should be considered as a collection
     * or as a single element.
     */
    public function withAsCollection(?bool $asCollection): static
    {
        return $this->with(XmlEncoder::AS_COLLECTION, $asCollection);
    }
    /**
     * Configures node types to ignore while decoding.
     *
     * @see https://php.net/dom.constants
     *
     * @param list<int>|null $decoderIgnoredNodeTypes
     */
    public function withDecoderIgnoredNodeTypes(?array $decoderIgnoredNodeTypes): static
    {
        return $this->with(XmlEncoder::DECODER_IGNORED_NODE_TYPES, $decoderIgnoredNodeTypes);
    }
    /**
     * Configures node types to ignore while encoding.
     *
     * @see https://php.net/dom.constants
     *
     * @param list<int>|null $encoderIgnoredNodeTypes
     */
    public function withEncoderIgnoredNodeTypes(?array $encoderIgnoredNodeTypes): static
    {
        return $this->with(XmlEncoder::ENCODER_IGNORED_NODE_TYPES, $encoderIgnoredNodeTypes);
    }
    /**
     * Configures the DOMDocument encoding.
     *
     * @see https://php.net/class.domdocument#domdocument.props.encoding
     */
    public function withEncoding(?string $encoding): static
    {
        return $this->with(XmlEncoder::ENCODING, $encoding);
    }
    /**
     * Configures whether to encode with indentation and extra space.
     *
     * @see https://php.net/class.domdocument#domdocument.props.formatoutput
     */
    public function withFormatOutput(?bool $formatOutput): static
    {
        return $this->with(XmlEncoder::FORMAT_OUTPUT, $formatOutput);
    }
    /**
     * Configures the DOMDocument::loadXml options bitmask.
     *
     * @see https://php.net/libxml.constants
     *
     * @param positive-int|null $loadOptions
     */
    public function withLoadOptions(?int $loadOptions): static
    {
        return $this->with(XmlEncoder::LOAD_OPTIONS, $loadOptions);
    }
    /**
     * Configures the DOMDocument::saveXml options bitmask.
     *
     * @see https://php.net/libxml.constants
     *
     * @param positive-int|null $saveOptions
     */
    public function withSaveOptions(?int $saveOptions): static
    {
        return $this->with(XmlEncoder::SAVE_OPTIONS, $saveOptions);
    }
    /**
     * Configures whether to keep empty nodes.
     */
    public function withRemoveEmptyTags(?bool $removeEmptyTags): static
    {
        return $this->with(XmlEncoder::REMOVE_EMPTY_TAGS, $removeEmptyTags);
    }
    /**
     * Configures name of the root node.
     */
    public function withRootNodeName(?string $rootNodeName): static
    {
        return $this->with(XmlEncoder::ROOT_NODE_NAME, $rootNodeName);
    }
    /**
     * Configures whether the document will be standalone.
     *
     * @see https://php.net/class.domdocument#domdocument.props.xmlstandalone
     */
    public function withStandalone(?bool $standalone): static
    {
        return $this->with(XmlEncoder::STANDALONE, $standalone);
    }
    /**
     * Configures whether casting numeric string attributes to integers or floats.
     */
    public function withTypeCastAttributes(?bool $typeCastAttributes): static
    {
        return $this->with(XmlEncoder::TYPE_CAST_ATTRIBUTES, $typeCastAttributes);
    }
    /**
     * Configures the version number of the document.
     *
     * @see https://php.net/class.domdocument#domdocument.props.xmlversion
     */
    public function withVersion(?string $version): static
    {
        return $this->with(XmlEncoder::VERSION, $version);
    }
    /**
     * Configures whether to wrap strings within CDATA sections.
     */
    public function withCdataWrapping(?bool $cdataWrapping): static
    {
        return $this->with(XmlEncoder::CDATA_WRAPPING, $cdataWrapping);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Serializer\Context\Encoder;

use _ContaoManager\Symfony\Component\Serializer\Context\ContextBuilderInterface;
use _ContaoManager\Symfony\Component\Serializer\Context\ContextBuilderTrait;
use _ContaoManager\Symfony\Component\Serializer\Encoder\YamlEncoder;
/**
 * A helper providing autocompletion for available YamlEncoder options.
 *
 * Note that the "indentation" setting is not offered in this builder because
 * it can only be set during the construction of the YamlEncoder, but not per
 * call.
 *
 * @author Mathias Arlaud <mathias.arlaud@gmail.com>
 */
final class YamlEncoderContextBuilder implements ContextBuilderInterface
{
    use ContextBuilderTrait;
    /**
     * Configures the threshold to switch to inline YAML.
     */
    public function withInlineThreshold(?int $inlineThreshold): static
    {
        return $this->with(YamlEncoder::YAML_INLINE, $inlineThreshold);
    }
    /**
     * Configures the indentation level.
     *
     * Must be positive.
     *
     * @param int<0, max>|null $indentLevel
     */
    public function withIndentLevel(?int $indentLevel): static
    {
        return $this->with(YamlEncoder::YAML_INDENT, $indentLevel);
    }
    /**
     * Configures \Symfony\Component\Yaml\Dumper::dump flags bitmask.
     *
     * @see \Symfony\Component\Yaml\Yaml
     */
    public function withFlags(?int $flags): static
    {
        return $this->with(YamlEncoder::YAML_FLAGS, $flags);
    }
    /**
     * Configures whether to preserve empty objects "{}" or to convert them to null.
     */
    public function withPreservedEmptyObjects(?bool $preserveEmptyObjects): static
    {
        return $this->with(YamlEncoder::PRESERVE_EMPTY_OBJECTS, $preserveEmptyObjects);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Serializer\Context\Encoder;

use _ContaoManager\Symfony\Component\Serializer\Context\ContextBuilderInterface;
use _ContaoManager\Symfony\Component\Serializer\Context\ContextBuilderTrait;
use _ContaoManager\Symfony\Component\Serializer\Encoder\JsonDecode;
use _ContaoManager\Symfony\Component\Serializer\Encoder\JsonEncode;
/**
 * A helper providing autocompletion for available JsonEncoder options.
 *
 * @author Mathias Arlaud <mathias.arlaud@gmail.com>
 */
final class JsonEncoderContextBuilder implements ContextBuilderInterface
{
    use ContextBuilderTrait;
    /**
     * Configures the json_encode flags bitmask.
     *
     * @see https://php.net/json.constants
     *
     * @param positive-int|null $options
     */
    public function withEncodeOptions(?int $options): static
    {
        return $this->with(JsonEncode::OPTIONS, $options);
    }
    /**
     * Configures the json_decode flags bitmask.
     *
     * @see https://php.net/json.constants
     *
     * @param positive-int|null $options
     */
    public function withDecodeOptions(?int $options): static
    {
        return $this->with(JsonDecode::OPTIONS, $options);
    }
    /**
     * Configures whether decoded objects will be given as
     * associative arrays or as nested stdClass.
     */
    public function withAssociative(?bool $associative): static
    {
        return $this->with(JsonDecode::ASSOCIATIVE, $associative);
    }
    /**
     * Configures the maximum recursion depth.
     *
     * Must be strictly positive.
     *
     * @param positive-int|null $recursionDepth
     */
    public function withRecursionDepth(?int $recursionDepth): static
    {
        return $this->with(JsonDecode::RECURSION_DEPTH, $recursionDepth);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Serializer\Context;

/**
 * @author Mathias Arlaud <mathias.arlaud@gmail.com>
 */
trait ContextBuilderTrait
{
    /**
     * @var array<string, mixed>
     */
    private array $context = [];
    protected function with(string $key, mixed $value): static
    {
        $instance = new static();
        $instance->context = array_merge($this->context, [$key => $value]);
        return $instance;
    }
    /**
     * @param ContextBuilderInterface|array<string, mixed> $context
     */
    public function withContext(ContextBuilderInterface|array $context): static
    {
        if ($context instanceof ContextBuilderInterface) {
            $context = $context->toArray();
        }
        $instance = new static();
        $instance->context = array_merge($this->context, $context);
        return $instance;
    }
    /**
     * @return array<string, mixed>
     */
    public function toArray(): array
    {
        return $this->context;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Serializer\Context;

use _ContaoManager\Symfony\Component\Serializer\Normalizer\DenormalizerInterface;
use _ContaoManager\Symfony\Component\Serializer\Serializer;
/**
 * A helper providing autocompletion for available Serializer options.
 *
 * @author Mathias Arlaud <mathias.arlaud@gmail.com>
 */
final class SerializerContextBuilder implements ContextBuilderInterface
{
    use ContextBuilderTrait;
    /**
     * Configures whether an empty array should be transformed to an
     * object (in JSON: {}) or to a list (in JSON: []).
     */
    public function withEmptyArrayAsObject(?bool $emptyArrayAsObject): static
    {
        return $this->with(Serializer::EMPTY_ARRAY_AS_OBJECT, $emptyArrayAsObject);
    }
    public function withCollectDenormalizationErrors(?bool $collectDenormalizationErrors): static
    {
        return $this->with(DenormalizerInterface::COLLECT_DENORMALIZATION_ERRORS, $collectDenormalizationErrors);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Serializer\Context;

/**
 * Common interface for context builders.
 *
 * @author Mathias Arlaud <mathias.arlaud@gmail.com>
 * @author Robin Chalas <robin.chalas@gmail.com>
 */
interface ContextBuilderInterface
{
    /**
     * @param self|array<string, mixed> $context
     */
    public function withContext(self|array $context): static;
    /**
     * @return array<string, mixed>
     */
    public function toArray(): array;
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Serializer\Context\Normalizer;

/**
 * A helper providing autocompletion for available ObjectNormalizer options.
 *
 * @author Mathias Arlaud <mathias.arlaud@gmail.com>
 */
final class ObjectNormalizerContextBuilder extends AbstractObjectNormalizerContextBuilder
{
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Serializer\Context\Normalizer;

use _ContaoManager\Symfony\Component\Serializer\Context\ContextBuilderInterface;
use _ContaoManager\Symfony\Component\Serializer\Context\ContextBuilderTrait;
use _ContaoManager\Symfony\Component\Serializer\Exception\InvalidArgumentException;
use _ContaoManager\Symfony\Component\Serializer\Normalizer\DateTimeNormalizer;
/**
 * A helper providing autocompletion for available DateTimeNormalizer options.
 *
 * @author Mathias Arlaud <mathias.arlaud@gmail.com>
 */
final class DateTimeNormalizerContextBuilder implements ContextBuilderInterface
{
    use ContextBuilderTrait;
    /**
     * Configures the format of the date.
     *
     * @see https://secure.php.net/manual/en/datetime.format.php
     */
    public function withFormat(?string $format): static
    {
        return $this->with(DateTimeNormalizer::FORMAT_KEY, $format);
    }
    /**
     * Configures the timezone of the date.
     *
     * It could be either a \DateTimeZone or a string
     * that will be used to construct the \DateTimeZone
     *
     * @see https://secure.php.net/manual/en/class.datetimezone.php
     *
     * @throws InvalidArgumentException
     */
    public function withTimezone(\DateTimeZone|string|null $timezone): static
    {
        if (null === $timezone) {
            return $this->with(DateTimeNormalizer::TIMEZONE_KEY, null);
        }
        if (\is_string($timezone)) {
            try {
                $timezone = new \DateTimeZone($timezone);
            } catch (\Exception $e) {
                throw new InvalidArgumentException(\sprintf('The "%s" timezone is invalid.', $timezone), previous: $e);
            }
        }
        return $this->with(DateTimeNormalizer::TIMEZONE_KEY, $timezone);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Serializer\Context\Normalizer;

use _ContaoManager\Symfony\Component\Serializer\Context\ContextBuilderInterface;
use _ContaoManager\Symfony\Component\Serializer\Context\ContextBuilderTrait;
use _ContaoManager\Symfony\Component\Serializer\Normalizer\FormErrorNormalizer;
/**
 * A helper providing autocompletion for available FormErrorNormalizer options.
 *
 * @author Mathias Arlaud <mathias.arlaud@gmail.com>
 */
final class FormErrorNormalizerContextBuilder implements ContextBuilderInterface
{
    use ContextBuilderTrait;
    /**
     * Configures the title of the normalized data.
     */
    public function withTitle(?string $title): static
    {
        return $this->with(FormErrorNormalizer::TITLE, $title);
    }
    /**
     * Configures the type of the normalized data.
     */
    public function withType(?string $type): static
    {
        return $this->with(FormErrorNormalizer::TYPE, $type);
    }
    /**
     * Configures the code of the normalized data.
     */
    public function withStatusCode(?int $statusCode): static
    {
        return $this->with(FormErrorNormalizer::CODE, $statusCode);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Serializer\Context\Normalizer;

/**
 * A helper providing autocompletion for available GetSetMethodNormalizer options.
 *
 * @author Mathias Arlaud <mathias.arlaud@gmail.com>
 */
final class GetSetMethodNormalizerContextBuilder extends AbstractObjectNormalizerContextBuilder
{
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Serializer\Context\Normalizer;

/**
 * A helper providing autocompletion for available JsonSerializableNormalizer options.
 *
 * @author Mathias Arlaud <mathias.arlaud@gmail.com>
 */
final class JsonSerializableNormalizerContextBuilder extends AbstractNormalizerContextBuilder
{
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Serializer\Context\Normalizer;

use _ContaoManager\Symfony\Component\Serializer\Context\ContextBuilderInterface;
use _ContaoManager\Symfony\Component\Serializer\Context\ContextBuilderTrait;
use _ContaoManager\Symfony\Component\Serializer\Normalizer\ProblemNormalizer;
/**
 * A helper providing autocompletion for available ProblemNormalizer options.
 *
 * @author Mathias Arlaud <mathias.arlaud@gmail.com>
 */
final class ProblemNormalizerContextBuilder implements ContextBuilderInterface
{
    use ContextBuilderTrait;
    /**
     * Configure the title field of normalized data.
     */
    public function withTitle(?string $title): static
    {
        return $this->with(ProblemNormalizer::TITLE, $title);
    }
    /**
     * Configure the type field of normalized data.
     */
    public function withType(?string $type): static
    {
        return $this->with(ProblemNormalizer::TYPE, $type);
    }
    /**
     * Configure the status field of normalized data.
     */
    public function withStatusCode(int|string|null $statusCode): static
    {
        return $this->with(ProblemNormalizer::STATUS, $statusCode);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Serializer\Context\Normalizer;

use _ContaoManager\Symfony\Component\Serializer\Exception\InvalidArgumentException;
use _ContaoManager\Symfony\Component\Serializer\Normalizer\AbstractObjectNormalizer;
/**
 * A helper providing autocompletion for available AbstractObjectNormalizer options.
 *
 * @author Mathias Arlaud <mathias.arlaud@gmail.com>
 */
abstract class AbstractObjectNormalizerContextBuilder extends AbstractNormalizerContextBuilder
{
    /**
     * Configures whether to respect the max depth metadata on fields.
     */
    public function withEnableMaxDepth(?bool $enableMaxDepth): static
    {
        return $this->with(AbstractObjectNormalizer::ENABLE_MAX_DEPTH, $enableMaxDepth);
    }
    /**
     * Configures a pattern to keep track of the current depth.
     *
     * Must contain exactly two string placeholders.
     *
     * @throws InvalidArgumentException
     */
    public function withDepthKeyPattern(?string $depthKeyPattern): static
    {
        if (null === $depthKeyPattern) {
            return $this->with(AbstractObjectNormalizer::DEPTH_KEY_PATTERN, null);
        }
        // This will match every occurrences of sprintf specifiers
        $matches = [];
        preg_match_all('/(?<!%)(?:%{2})*%(?<specifier>[a-z])/', $depthKeyPattern, $matches);
        if (2 !== \count($matches['specifier']) || 's' !== $matches['specifier'][0] || 's' !== $matches['specifier'][1]) {
            throw new InvalidArgumentException(\sprintf('The depth key pattern "%s" is not valid. You must set exactly two string placeholders.', $depthKeyPattern));
        }
        return $this->with(AbstractObjectNormalizer::DEPTH_KEY_PATTERN, $depthKeyPattern);
    }
    /**
     * Configures whether verifying types match during denormalization.
     */
    public function withDisableTypeEnforcement(?bool $disableTypeEnforcement): static
    {
        return $this->with(AbstractObjectNormalizer::DISABLE_TYPE_ENFORCEMENT, $disableTypeEnforcement);
    }
    /**
     * Configures whether fields with the value `null` should be output during normalization.
     */
    public function withSkipNullValues(?bool $skipNullValues): static
    {
        return $this->with(AbstractObjectNormalizer::SKIP_NULL_VALUES, $skipNullValues);
    }
    /**
     * Configures whether uninitialized typed class properties should be excluded during normalization.
     */
    public function withSkipUninitializedValues(?bool $skipUninitializedValues): static
    {
        return $this->with(AbstractObjectNormalizer::SKIP_UNINITIALIZED_VALUES, $skipUninitializedValues);
    }
    /**
     * Configures a callback to allow to set a value for an attribute when the max depth has
     * been reached.
     *
     * If no callback is given, the attribute is skipped. If a callable is
     * given, its return value is used (even if null).
     *
     * The arguments are:
     *
     * - mixed                 $attributeValue value of this field
     * - object                $object         the whole object being normalized
     * - string                $attributeName  name of the attribute being normalized
     * - string                $format         the requested format
     * - array<string, mixed>  $context        the serialization context
     */
    public function withMaxDepthHandler(?callable $maxDepthHandler): static
    {
        return $this->with(AbstractObjectNormalizer::MAX_DEPTH_HANDLER, $maxDepthHandler);
    }
    /**
     * Configures which context key are not relevant to determine which attributes
     * of an object to (de)normalize.
     *
     * @param list<string>|null $excludeFromCacheKeys
     */
    public function withExcludeFromCacheKeys(?array $excludeFromCacheKeys): static
    {
        return $this->with(AbstractObjectNormalizer::EXCLUDE_FROM_CACHE_KEY, $excludeFromCacheKeys);
    }
    /**
     * Configures whether to tell the denormalizer to also populate existing objects on
     * attributes of the main object.
     *
     * Setting this to true is only useful if you also specify the root object
     * in AbstractNormalizer::OBJECT_TO_POPULATE.
     */
    public function withDeepObjectToPopulate(?bool $deepObjectToPopulate): static
    {
        return $this->with(AbstractObjectNormalizer::DEEP_OBJECT_TO_POPULATE, $deepObjectToPopulate);
    }
    /**
     * Configures whether an empty object should be kept as an object (in
     * JSON: {}) or converted to a list (in JSON: []).
     */
    public function withPreserveEmptyObjects(?bool $preserveEmptyObjects): static
    {
        return $this->with(AbstractObjectNormalizer::PRESERVE_EMPTY_OBJECTS, $preserveEmptyObjects);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Serializer\Context\Normalizer;

use _ContaoManager\Symfony\Component\Serializer\Context\ContextBuilderInterface;
use _ContaoManager\Symfony\Component\Serializer\Context\ContextBuilderTrait;
use _ContaoManager\Symfony\Component\Serializer\Normalizer\BackedEnumNormalizer;
/**
 * A helper providing autocompletion for available BackedEnumNormalizer options.
 *
 * @author Nicolas PHILIPPE <nikophil@gmail.com>
 */
final class BackedEnumNormalizerContextBuilder implements ContextBuilderInterface
{
    use ContextBuilderTrait;
    /**
     * Configures if invalid values are allowed in denormalization.
     * They will be denormalized into `null` values.
     */
    public function withAllowInvalidValues(bool $allowInvalidValues): static
    {
        return $this->with(BackedEnumNormalizer::ALLOW_INVALID_VALUES, $allowInvalidValues);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Serializer\Context\Normalizer;

use _ContaoManager\Symfony\Component\Serializer\Context\ContextBuilderInterface;
use _ContaoManager\Symfony\Component\Serializer\Context\ContextBuilderTrait;
use _ContaoManager\Symfony\Component\Serializer\Normalizer\ConstraintViolationListNormalizer;
/**
 * A helper providing autocompletion for available ConstraintViolationList options.
 *
 * @author Mathias Arlaud <mathias.arlaud@gmail.com>
 */
final class ConstraintViolationListNormalizerContextBuilder implements ContextBuilderInterface
{
    use ContextBuilderTrait;
    /**
     * Configure the instance field of normalized data.
     */
    public function withInstance(mixed $instance): static
    {
        return $this->with(ConstraintViolationListNormalizer::INSTANCE, $instance);
    }
    /**
     * Configure the status field of normalized data.
     */
    public function withStatus(?int $status): static
    {
        return $this->with(ConstraintViolationListNormalizer::STATUS, $status);
    }
    /**
     * Configure the title field of normalized data.
     */
    public function withTitle(?string $title): static
    {
        return $this->with(ConstraintViolationListNormalizer::TITLE, $title);
    }
    /**
     * Configure the type field of normalized data.
     */
    public function withType(?string $type): static
    {
        return $this->with(ConstraintViolationListNormalizer::TYPE, $type);
    }
    /**
     * Configures the payload fields which will act as an allowlist
     * for the payload field of normalized data.
     *
     * Eg: ['foo', 'bar']
     *
     * @param list<string>|null $payloadFields
     */
    public function withPayloadFields(?array $payloadFields): static
    {
        return $this->with(ConstraintViolationListNormalizer::PAYLOAD_FIELDS, $payloadFields);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Serializer\Context\Normalizer;

use _ContaoManager\Symfony\Component\PropertyAccess\Exception\InvalidPropertyPathException;
use _ContaoManager\Symfony\Component\PropertyAccess\PropertyPath;
use _ContaoManager\Symfony\Component\Serializer\Context\ContextBuilderInterface;
use _ContaoManager\Symfony\Component\Serializer\Context\ContextBuilderTrait;
use _ContaoManager\Symfony\Component\Serializer\Exception\InvalidArgumentException;
use _ContaoManager\Symfony\Component\Serializer\Normalizer\UnwrappingDenormalizer;
/**
 * A helper providing autocompletion for available UnwrappingDenormalizer options.
 *
 * @author Mathias Arlaud <mathias.arlaud@gmail.com>
 */
final class UnwrappingDenormalizerContextBuilder implements ContextBuilderInterface
{
    use ContextBuilderTrait;
    /**
     * Configures the path of wrapped data during denormalization.
     *
     * Eg: [foo].bar[bar]
     *
     * @see https://symfony.com/doc/current/components/property_access.html
     *
     * @throws InvalidArgumentException
     */
    public function withUnwrapPath(?string $unwrapPath): static
    {
        if (null === $unwrapPath) {
            return $this->with(UnwrappingDenormalizer::UNWRAP_PATH, null);
        }
        try {
            new PropertyPath($unwrapPath);
        } catch (InvalidPropertyPathException $e) {
            throw new InvalidArgumentException(\sprintf('The "%s" property path is not valid.', $unwrapPath), previous: $e);
        }
        return $this->with(UnwrappingDenormalizer::UNWRAP_PATH, $unwrapPath);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Serializer\Context\Normalizer;

use _ContaoManager\Symfony\Component\Serializer\Context\ContextBuilderInterface;
use _ContaoManager\Symfony\Component\Serializer\Context\ContextBuilderTrait;
use _ContaoManager\Symfony\Component\Serializer\Exception\InvalidArgumentException;
use _ContaoManager\Symfony\Component\Serializer\Normalizer\AbstractNormalizer;
/**
 * A helper providing autocompletion for available AbstractNormalizer options.
 *
 * @author Mathias Arlaud <mathias.arlaud@gmail.com>
 */
abstract class AbstractNormalizerContextBuilder implements ContextBuilderInterface
{
    use ContextBuilderTrait;
    /**
     * Configures how many loops of circular reference to allow while normalizing.
     *
     * The value 1 means that when we encounter the same object a
     * second time, we consider that a circular reference.
     *
     * You can raise this value for special cases, e.g. in combination with the
     * max depth setting of the object normalizer.
     *
     * Must be strictly positive.
     *
     * @param positive-int|null $circularReferenceLimit
     */
    public function withCircularReferenceLimit(?int $circularReferenceLimit): static
    {
        return $this->with(AbstractNormalizer::CIRCULAR_REFERENCE_LIMIT, $circularReferenceLimit);
    }
    /**
     * Configures an object to be updated instead of creating a new instance.
     *
     * If you have a nested structure, child objects will be overwritten with
     * new instances unless you set AbstractObjectNormalizer::DEEP_OBJECT_TO_POPULATE to true.
     */
    public function withObjectToPopulate(?object $objectToPopulate): static
    {
        return $this->with(AbstractNormalizer::OBJECT_TO_POPULATE, $objectToPopulate);
    }
    /**
     * Configures groups containing attributes to (de)normalize.
     *
     * Eg: ['group1', 'group2']
     *
     * @param list<string>|string|null $groups
     */
    public function withGroups(array|string|null $groups): static
    {
        if (null === $groups) {
            return $this->with(AbstractNormalizer::GROUPS, null);
        }
        return $this->with(AbstractNormalizer::GROUPS, (array) $groups);
    }
    /**
     * Configures attributes to (de)normalize.
     *
     * For nested structures, this list needs to reflect the object tree.
     *
     * Eg: ['foo', 'bar', 'object' => ['baz']]
     *
     * @param array<string|array>|null $attributes
     *
     * @throws InvalidArgumentException
     */
    public function withAttributes(?array $attributes): static
    {
        $it = new \RecursiveIteratorIterator(new \RecursiveArrayIterator($attributes ?? []), \RecursiveIteratorIterator::LEAVES_ONLY);
        foreach ($it as $attribute) {
            if (!\is_string($attribute)) {
                throw new InvalidArgumentException(\sprintf('Each attribute must be a string, "%s" given.', get_debug_type($attribute)));
            }
        }
        return $this->with(AbstractNormalizer::ATTRIBUTES, $attributes);
    }
    /**
     * If AbstractNormalizer::ATTRIBUTES are specified, and the source has fields that are not part of that list,
     * configures whether to ignore those attributes or throw an ExtraAttributesException.
     */
    public function withAllowExtraAttributes(?bool $allowExtraAttributes): static
    {
        return $this->with(AbstractNormalizer::ALLOW_EXTRA_ATTRIBUTES, $allowExtraAttributes);
    }
    /**
     * Configures a hashmap of classes containing hashmaps of constructor argument => default value.
     *
     * The names need to match the parameter names in the constructor arguments.
     *
     * Eg: [Foo::class => ['foo' => true, 'bar' => 0]]
     *
     * @param array<class-string, array<string, mixed>>|null $defaultConstructorArguments
     */
    public function withDefaultConstructorArguments(?array $defaultConstructorArguments): static
    {
        return $this->with(AbstractNormalizer::DEFAULT_CONSTRUCTOR_ARGUMENTS, $defaultConstructorArguments);
    }
    /**
     * Deprecated in Symfony 7.1, use withDefaultConstructorArguments() instead.
     */
    public function withDefaultContructorArguments(?array $defaultContructorArguments): static
    {
        return self::withDefaultConstructorArguments($defaultContructorArguments);
    }
    /**
     * Configures an hashmap of field name => callable to normalize this field.
     *
     * The callable is called if the field is encountered with the arguments:
     *
     * - mixed                 $attributeValue value of this field
     * - object                $object         the whole object being normalized
     * - string                $attributeName  name of the attribute being normalized
     * - string                $format         the requested format
     * - array<string, mixed>  $context        the serialization context
     *
     * @param array<string, callable>|null $callbacks
     */
    public function withCallbacks(?array $callbacks): static
    {
        return $this->with(AbstractNormalizer::CALLBACKS, $callbacks);
    }
    /**
     * Configures an handler to call when a circular reference has been detected.
     *
     * If no handler is specified, a CircularReferenceException is thrown.
     *
     * The method will be called with ($object, $format, $context) and its
     * return value is returned as the result of the normalize call.
     */
    public function withCircularReferenceHandler(?callable $circularReferenceHandler): static
    {
        return $this->with(AbstractNormalizer::CIRCULAR_REFERENCE_HANDLER, $circularReferenceHandler);
    }
    /**
     * Configures attributes to be skipped when normalizing an object tree.
     *
     * This list is applied to each element of nested structures.
     *
     * Eg: ['foo', 'bar']
     *
     * Note: The behaviour for nested structures is different from ATTRIBUTES
     * for historical reason. Aligning the behaviour would be a BC break.
     *
     * @param list<string>|null $ignoredAttributes
     */
    public function withIgnoredAttributes(?array $ignoredAttributes): static
    {
        return $this->with(AbstractNormalizer::IGNORED_ATTRIBUTES, $ignoredAttributes);
    }
    /**
     * Configures requiring all properties to be listed in the input instead
     * of falling back to null for nullable ones.
     */
    public function withRequireAllProperties(?bool $requireAllProperties = \true): static
    {
        return $this->with(AbstractNormalizer::REQUIRE_ALL_PROPERTIES, $requireAllProperties);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Serializer\Context\Normalizer;

use _ContaoManager\Symfony\Component\Serializer\Context\ContextBuilderInterface;
use _ContaoManager\Symfony\Component\Serializer\Context\ContextBuilderTrait;
use _ContaoManager\Symfony\Component\Serializer\Exception\InvalidArgumentException;
use _ContaoManager\Symfony\Component\Serializer\Normalizer\UidNormalizer;
/**
 * A helper providing autocompletion for available UidNormalizer options.
 *
 * @author Mathias Arlaud <mathias.arlaud@gmail.com>
 */
final class UidNormalizerContextBuilder implements ContextBuilderInterface
{
    use ContextBuilderTrait;
    /**
     * Configures the uuid format for normalization.
     *
     * @throws InvalidArgumentException
     */
    public function withNormalizationFormat(?string $normalizationFormat): static
    {
        if (null !== $normalizationFormat && !\in_array($normalizationFormat, UidNormalizer::NORMALIZATION_FORMATS, \true)) {
            throw new InvalidArgumentException(\sprintf('The "%s" normalization format is not valid.', $normalizationFormat));
        }
        return $this->with(UidNormalizer::NORMALIZATION_FORMAT_KEY, $normalizationFormat);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Serializer\Context\Normalizer;

use _ContaoManager\Symfony\Component\Serializer\Normalizer\PropertyNormalizer;
/**
 * A helper providing autocompletion for available PropertyNormalizer options.
 *
 * @author Mathias Arlaud <mathias.arlaud@gmail.com>
 */
final class PropertyNormalizerContextBuilder extends AbstractObjectNormalizerContextBuilder
{
    /**
     * Configures whether fields should be output based on visibility.
     */
    public function withNormalizeVisibility(int $normalizeVisibility): static
    {
        return $this->with(PropertyNormalizer::NORMALIZE_VISIBILITY, $normalizeVisibility);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Serializer\Context\Normalizer;

use _ContaoManager\Symfony\Component\Serializer\Context\ContextBuilderInterface;
use _ContaoManager\Symfony\Component\Serializer\Context\ContextBuilderTrait;
use _ContaoManager\Symfony\Component\Serializer\Normalizer\DateIntervalNormalizer;
/**
 * A helper providing autocompletion for available DateIntervalNormalizer options.
 *
 * @author Mathias Arlaud <mathias.arlaud@gmail.com>
 */
final class DateIntervalNormalizerContextBuilder implements ContextBuilderInterface
{
    use ContextBuilderTrait;
    /**
     * Configures the format of the interval.
     *
     * @see https://php.net/manual/en/dateinterval.format.php
     */
    public function withFormat(?string $format): static
    {
        return $this->with(DateIntervalNormalizer::FORMAT_KEY, $format);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Serializer\Attribute;

use _ContaoManager\Symfony\Component\Serializer\Exception\InvalidArgumentException;
/**
 * Annotation class for @SerializedName().
 *
 * @Annotation
 * @NamedArgumentConstructor
 * @Target({"PROPERTY", "METHOD"})
 *
 * @author Fabien Bourigault <bourigaultfabien@gmail.com>
 */
#[\Attribute(\Attribute::TARGET_METHOD | \Attribute::TARGET_PROPERTY)]
class SerializedName
{
    public function __construct(private readonly string $serializedName)
    {
        if ('' === $serializedName) {
            throw new InvalidArgumentException(\sprintf('Parameter given to "%s" must be a non-empty string.', self::class));
        }
    }
    public function getSerializedName(): string
    {
        return $this->serializedName;
    }
}
if (!class_exists(\_ContaoManager\Symfony\Component\Serializer\Annotation\SerializedName::class, \false)) {
    class_alias(SerializedName::class, \_ContaoManager\Symfony\Component\Serializer\Annotation\SerializedName::class);
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Serializer\Attribute;

/**
 * Annotation class for @Ignore().
 *
 * @Annotation
 * @Target({"PROPERTY", "METHOD"})
 *
 * @author Kévin Dunglas <dunglas@gmail.com>
 */
#[\Attribute(\Attribute::TARGET_METHOD | \Attribute::TARGET_PROPERTY)]
class Ignore
{
}
if (!class_exists(\_ContaoManager\Symfony\Component\Serializer\Annotation\Ignore::class, \false)) {
    class_alias(Ignore::class, \_ContaoManager\Symfony\Component\Serializer\Annotation\Ignore::class);
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Serializer\Attribute;

use _ContaoManager\Symfony\Component\Serializer\Exception\InvalidArgumentException;
/**
 * Annotation class for @Context().
 *
 * @Annotation
 * @NamedArgumentConstructor
 * @Target({"PROPERTY", "METHOD"})
 *
 * @author Maxime Steinhausser <maxime.steinhausser@gmail.com>
 */
#[\Attribute(\Attribute::TARGET_CLASS | \Attribute::TARGET_PROPERTY | \Attribute::TARGET_METHOD | \Attribute::IS_REPEATABLE)]
class Context
{
    private array $groups;
    /**
     * @param string|string[] $groups
     *
     * @throws InvalidArgumentException
     */
    public function __construct(private readonly array $context = [], private readonly array $normalizationContext = [], private readonly array $denormalizationContext = [], string|array $groups = [])
    {
        if (!$context && !$normalizationContext && !$denormalizationContext) {
            throw new InvalidArgumentException(\sprintf('At least one of the "context", "normalizationContext", or "denormalizationContext" options must be provided as a non-empty array to "%s".', static::class));
        }
        $this->groups = (array) $groups;
        foreach ($this->groups as $group) {
            if (!\is_string($group)) {
                throw new InvalidArgumentException(\sprintf('Parameter "groups" given to "%s" must be a string or an array of strings, "%s" given.', static::class, get_debug_type($group)));
            }
        }
    }
    public function getContext(): array
    {
        return $this->context;
    }
    public function getNormalizationContext(): array
    {
        return $this->normalizationContext;
    }
    public function getDenormalizationContext(): array
    {
        return $this->denormalizationContext;
    }
    public function getGroups(): array
    {
        return $this->groups;
    }
}
if (!class_exists(\_ContaoManager\Symfony\Component\Serializer\Annotation\Context::class, \false)) {
    class_alias(Context::class, \_ContaoManager\Symfony\Component\Serializer\Annotation\Context::class);
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Serializer\Attribute;

use _ContaoManager\Symfony\Component\Serializer\Exception\InvalidArgumentException;
/**
 * Annotation class for @DiscriminatorMap().
 *
 * @Annotation
 * @NamedArgumentConstructor
 * @Target({"CLASS"})
 *
 * @author Samuel Roze <samuel.roze@gmail.com>
 */
#[\Attribute(\Attribute::TARGET_CLASS)]
class DiscriminatorMap
{
    public function __construct(private readonly string $typeProperty, private readonly array $mapping)
    {
        if (empty($typeProperty)) {
            throw new InvalidArgumentException(\sprintf('Parameter "typeProperty" given to "%s" cannot be empty.', static::class));
        }
        if (empty($mapping)) {
            throw new InvalidArgumentException(\sprintf('Parameter "mapping" given to "%s" cannot be empty.', static::class));
        }
    }
    public function getTypeProperty(): string
    {
        return $this->typeProperty;
    }
    public function getMapping(): array
    {
        return $this->mapping;
    }
}
if (!class_exists(\_ContaoManager\Symfony\Component\Serializer\Annotation\DiscriminatorMap::class, \false)) {
    class_alias(DiscriminatorMap::class, \_ContaoManager\Symfony\Component\Serializer\Annotation\DiscriminatorMap::class);
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Serializer\Attribute;

use _ContaoManager\Symfony\Component\PropertyAccess\Exception\InvalidPropertyPathException;
use _ContaoManager\Symfony\Component\PropertyAccess\PropertyPath;
use _ContaoManager\Symfony\Component\Serializer\Exception\InvalidArgumentException;
/**
 * Annotation class for @SerializedPath().
 *
 * @Annotation
 * @NamedArgumentConstructor
 * @Target({"PROPERTY", "METHOD"})
 *
 * @author Tobias Bönner <tobi@boenner.family>
 */
#[\Attribute(\Attribute::TARGET_METHOD | \Attribute::TARGET_PROPERTY)]
class SerializedPath
{
    private PropertyPath $serializedPath;
    public function __construct(string $serializedPath)
    {
        try {
            $this->serializedPath = new PropertyPath($serializedPath);
        } catch (InvalidPropertyPathException $pathException) {
            throw new InvalidArgumentException(\sprintf('Parameter given to "%s" must be a valid property path.', self::class));
        }
    }
    public function getSerializedPath(): PropertyPath
    {
        return $this->serializedPath;
    }
}
if (!class_exists(\_ContaoManager\Symfony\Component\Serializer\Annotation\SerializedPath::class, \false)) {
    class_alias(SerializedPath::class, \_ContaoManager\Symfony\Component\Serializer\Annotation\SerializedPath::class);
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Serializer\Attribute;

use _ContaoManager\Symfony\Component\Serializer\Exception\InvalidArgumentException;
/**
 * Annotation class for @MaxDepth().
 *
 * @Annotation
 * @NamedArgumentConstructor
 * @Target({"PROPERTY", "METHOD"})
 *
 * @author Kévin Dunglas <dunglas@gmail.com>
 */
#[\Attribute(\Attribute::TARGET_METHOD | \Attribute::TARGET_PROPERTY)]
class MaxDepth
{
    public function __construct(private readonly int $maxDepth)
    {
        if ($maxDepth <= 0) {
            throw new InvalidArgumentException(\sprintf('Parameter given to "%s" must be a positive integer.', static::class));
        }
    }
    /**
     * @return int
     */
    public function getMaxDepth()
    {
        return $this->maxDepth;
    }
}
if (!class_exists(\_ContaoManager\Symfony\Component\Serializer\Annotation\MaxDepth::class, \false)) {
    class_alias(MaxDepth::class, \_ContaoManager\Symfony\Component\Serializer\Annotation\MaxDepth::class);
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Serializer\Attribute;

use _ContaoManager\Symfony\Component\Serializer\Exception\InvalidArgumentException;
/**
 * Annotation class for @Groups().
 *
 * @Annotation
 * @NamedArgumentConstructor
 * @Target({"PROPERTY", "METHOD", "CLASS"})
 *
 * @author Kévin Dunglas <dunglas@gmail.com>
 */
#[\Attribute(\Attribute::TARGET_METHOD | \Attribute::TARGET_PROPERTY | \Attribute::TARGET_CLASS)]
class Groups
{
    /**
     * @var string[]
     */
    private readonly array $groups;
    /**
     * @param string|string[] $groups
     */
    public function __construct(string|array $groups)
    {
        $this->groups = (array) $groups;
        if (!$this->groups) {
            throw new InvalidArgumentException(\sprintf('Parameter given to "%s" cannot be empty.', static::class));
        }
        foreach ($this->groups as $group) {
            if (!\is_string($group) || '' === $group) {
                throw new InvalidArgumentException(\sprintf('Parameter given to "%s" must be a string or an array of non-empty strings.', static::class));
            }
        }
    }
    /**
     * @return string[]
     */
    public function getGroups(): array
    {
        return $this->groups;
    }
}
if (!class_exists(\_ContaoManager\Symfony\Component\Serializer\Annotation\Groups::class, \false)) {
    class_alias(Groups::class, \_ContaoManager\Symfony\Component\Serializer\Annotation\Groups::class);
}
Copyright (c) 2004-present Fabien Potencier

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is furnished
to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
CHANGELOG
=========

6.4
---

 * Add `TranslatableNormalizer`
 * Allow `Context` attribute to target classes
 * Deprecate Doctrine annotations support in favor of native attributes
 * Allow the `Groups` attribute/annotation on classes
 * JsonDecode: Add `json_decode_detailed_errors` option
 * Make `ProblemNormalizer` give details about Messenger's `ValidationFailedException`
 * Add `XmlEncoder::CDATA_WRAPPING` context option
 * Deprecate `AnnotationLoader`, use `AttributeLoader` instead
 * Add aliases for all classes in the `Annotation` namespace to `Attribute`

6.3
---

 * Add `AbstractNormalizer::REQUIRE_ALL_PROPERTIES` context flag to require all properties to be listed in the input instead of falling back to null for nullable ones
 * Add `XmlEncoder::SAVE_OPTIONS` context option
 * Add `BackedEnumNormalizer::ALLOW_INVALID_VALUES` context option
 * Add `UnsupportedFormatException` which is thrown when there is no decoder for a given format
 * Add method `getSupportedTypes(?string $format)` to `NormalizerInterface` and `DenormalizerInterface`
 * Make `ProblemNormalizer` give details about `ValidationFailedException` and `PartialDenormalizationException`
 * Deprecate `CacheableSupportsMethodInterface` in favor of the new `getSupportedTypes(?string $format)` methods
 * The following Normalizer classes will become final in 7.0:
   * `ConstraintViolationListNormalizer`
   * `CustomNormalizer`
   * `DataUriNormalizer`
   * `DateIntervalNormalizer`
   * `DateTimeNormalizer`
   * `DateTimeZoneNormalizer`
   * `GetSetMethodNormalizer`
   * `JsonSerializableNormalizer`
   * `ObjectNormalizer`
   * `PropertyNormalizer`

6.2
---

 * Add support for constructor promoted properties to `Context` attribute
 * Add context option `PropertyNormalizer::NORMALIZE_VISIBILITY` with bitmask flags `PropertyNormalizer::NORMALIZE_PUBLIC`, `PropertyNormalizer::NORMALIZE_PROTECTED`, `PropertyNormalizer::NORMALIZE_PRIVATE`
 * Add method `withNormalizeVisibility` to `PropertyNormalizerContextBuilder`
 * Deprecate calling `AttributeMetadata::setSerializedName()`, `ClassMetadata::setClassDiscriminatorMapping()` without arguments
 * Change the signature of `AttributeMetadataInterface::setSerializedName()` to `setSerializedName(?string)`
 * Change the signature of `ClassMetadataInterface::setClassDiscriminatorMapping()` to `setClassDiscriminatorMapping(?ClassDiscriminatorMapping)`
 * Add option YamlEncoder::YAML_INDENTATION to YamlEncoder constructor options to configure additional indentation for each level of nesting. This allows configuring indentation in the service configuration.
 * Add `SerializedPath` annotation to flatten nested attributes

6.1
---

 * Add `TraceableSerializer`, `TraceableNormalizer`, `TraceableEncoder` and `SerializerDataCollector` to integrate with the web profiler
 * Add the ability to create contexts using context builders
 * Set `Context` annotation as not final
 * Deprecate `ContextAwareNormalizerInterface`, use `NormalizerInterface` instead
 * Deprecate `ContextAwareDenormalizerInterface`, use `DenormalizerInterface` instead
 * Deprecate supporting denormalization for `AbstractUid` in `UidNormalizer`, use one of `AbstractUid` child class instead
 * Deprecate denormalizing to an abstract class in `UidNormalizer`
 * Add support for `can*()` methods to `ObjectNormalizer`

6.0
---

 * Remove `ArrayDenormalizer::setSerializer()`, call `setDenormalizer()` instead
 * Remove the ability to create instances of the annotation classes by passing an array of parameters, use named arguments instead

5.4
---

 * Add support of PHP backed enumerations
 * Add support for serializing empty array as object
 * Return empty collections as `ArrayObject` from `Serializer::normalize()` when `PRESERVE_EMPTY_OBJECTS` is set
 * Add support for collecting type errors during denormalization
 * Add missing arguments in `MissingConstructorArgumentsException`

5.3
---

 * Add the ability to provide (de)normalization context using metadata (e.g. `@Symfony\Component\Serializer\Annotation\Context`)
 * Deprecate `ArrayDenormalizer::setSerializer()`, call `setDenormalizer()` instead
 * Add normalization formats to `UidNormalizer`
 * Add `CsvEncoder::END_OF_LINE` context option
 * Deprecate creating instances of the annotation classes by passing an array of parameters, use named arguments instead

5.2.0
-----

 * added `CompiledClassMetadataFactory` and `ClassMetadataFactoryCompiler` for faster metadata loading.
 * added `UidNormalizer`
 * added `FormErrorNormalizer`
 * added `MimeMessageNormalizer`
 * serializer mapping can be configured using php attributes

5.1.0
-----

 * added support for scalar values denormalization
 * added support for `\stdClass` to `ObjectNormalizer`
 * added the ability to ignore properties using metadata (e.g. `@Symfony\Component\Serializer\Annotation\Ignore`)
 * added an option to serialize constraint violations payloads (e.g. severity)

5.0.0
-----

 * throw an exception when creating a `Serializer` with normalizers which neither implement `NormalizerInterface` nor `DenormalizerInterface`
 * throw an exception when creating a `Serializer` with encoders which neither implement `EncoderInterface` nor `DecoderInterface`
 * changed the default value of the `CsvEncoder` "as_collection" option to `true`
 * removed `AbstractNormalizer::$circularReferenceLimit`, `AbstractNormalizer::$circularReferenceHandler`,
   `AbstractNormalizer::$callbacks`, `AbstractNormalizer::$ignoredAttributes`,
   `AbstractNormalizer::$camelizedAttributes`, `AbstractNormalizer::setCircularReferenceLimit()`,
   `AbstractNormalizer::setCircularReferenceHandler()`, `AbstractNormalizer::setCallbacks()` and
   `AbstractNormalizer::setIgnoredAttributes()`, use the default context instead.
 * removed `AbstractObjectNormalizer::$maxDepthHandler` and `AbstractObjectNormalizer::setMaxDepthHandler()`,
   use the default context instead.
 * removed `XmlEncoder::setRootNodeName()` & `XmlEncoder::getRootNodeName()`, use the default context instead.
 * removed individual encoders/normalizers options as constructor arguments.
 * removed support for instantiating a `DataUriNormalizer` with a default MIME type guesser when the `symfony/mime` component isn't installed.
 * removed the `XmlEncoder::TYPE_CASE_ATTRIBUTES` constant. Use `XmlEncoder::TYPE_CAST_ATTRIBUTES` instead.

4.4.0
-----

 * deprecated the `XmlEncoder::TYPE_CASE_ATTRIBUTES` constant, use `XmlEncoder::TYPE_CAST_ATTRIBUTES` instead
 * added option to output a UTF-8 BOM in CSV encoder via `CsvEncoder::OUTPUT_UTF8_BOM_KEY` context option
 * added `ProblemNormalizer` to normalize errors according to the API Problem spec (RFC 7807)

4.3.0
-----

 * added the list of constraint violations' parameters in `ConstraintViolationListNormalizer`
 * added support for serializing `DateTimeZone` objects
 * added a `deep_object_to_populate` context option to recursive denormalize on `object_to_populate` object.

4.2.0
-----

 * using the default context is the new recommended way to configure normalizers and encoders
 * added a `skip_null_values` context option to not serialize properties with a `null` values
 * `AbstractNormalizer::handleCircularReference` is now final and receives
   two optional extra arguments: the format and the context
 * added support for XML comment encoding (encoding `['#comment' => ' foo ']` results `<!-- foo -->`)
 * added optional `int[] $encoderIgnoredNodeTypes` argument to `XmlEncoder::__construct`
   to configure node types to be ignored during encoding
 * added `AdvancedNameConverterInterface` to access the class,
   the format and the context in a name converter
 * the `AbstractNormalizer::handleCircularReference()` method will have two new `$format`
   and `$context` arguments in version 5.0, not defining them is deprecated
 * deprecated creating a `Serializer` with normalizers which do not implement
   either `NormalizerInterface` or `DenormalizerInterface`
 * deprecated creating a `Serializer` with normalizers which do not implement
   either `NormalizerInterface` or `DenormalizerInterface`
 * deprecated creating a `Serializer` with encoders which do not implement
   either `EncoderInterface` or `DecoderInterface`
 * added the optional `$objectClassResolver` argument in `AbstractObjectNormalizer`
   and `ObjectNormalizer` constructor
 * added `MetadataAwareNameConverter` to configure the serialized name of properties through metadata
 * `YamlEncoder` now handles the `.yml` extension too
 * `AbstractNormalizer::$circularReferenceLimit`, `AbstractNormalizer::$circularReferenceHandler`,
   `AbstractNormalizer::$callbacks`, `AbstractNormalizer::$ignoredAttributes`,
   `AbstractNormalizer::$camelizedAttributes`, `AbstractNormalizer::setCircularReferenceLimit()`,
   `AbstractNormalizer::setCircularReferenceHandler()`, `AbstractNormalizer::setCallbacks()` and
   `AbstractNormalizer::setIgnoredAttributes()` are deprecated, use the default context instead.
 * `AbstractObjectNormalizer::$maxDepthHandler` and `AbstractObjectNormalizer::setMaxDepthHandler()`
   are deprecated, use the default context instead.
 * passing configuration options directly to the constructor of `CsvEncoder`, `JsonDecode` and
   `XmlEncoder` is deprecated since Symfony 4.2, use the default context instead.

4.1.0
-----

 * added `CacheableSupportsMethodInterface` for normalizers and denormalizers that use
   only the type and the format in their `supports*()` methods
 * added `MissingConstructorArgumentsException` new exception for deserialization failure
   of objects that needs data insertion in constructor
 * added an optional `default_constructor_arguments` option of context to specify a default data in
   case the object is not initializable by its constructor because of data missing
 * added optional `bool $escapeFormulas = false` argument to `CsvEncoder::__construct`
 * added `AbstractObjectNormalizer::setMaxDepthHandler` to set a handler to call when the configured
   maximum depth is reached
 * added optional `int[] $ignoredNodeTypes` argument to `XmlEncoder::__construct`. XML decoding now
   ignores comment node types by default.
 * added `ConstraintViolationListNormalizer`

4.0.0
-----

 * removed the `SerializerAwareEncoder` and `SerializerAwareNormalizer` classes,
   use the `SerializerAwareTrait` instead
 * removed the `Serializer::$normalizerCache` and `Serializer::$denormalizerCache`
   properties
 * added an optional `string $format = null` argument to `AbstractNormalizer::instantiateObject`
 * added an optional `array $context = []` to `Serializer::supportsNormalization`, `Serializer::supportsDenormalization`,
   `Serializer::supportsEncoding` and `Serializer::supportsDecoding`

3.4.0
-----

 * added `AbstractObjectNormalizer::DISABLE_TYPE_ENFORCEMENT` context option
   to disable throwing an `UnexpectedValueException` on a type mismatch
 * added support for serializing `DateInterval` objects
 * added getter for extra attributes in `ExtraAttributesException`
 * improved `CsvEncoder` to handle variable nested structures
 * CSV headers can be passed to the `CsvEncoder` via the `csv_headers` serialization context variable
 * added `$context` when checking for encoding, decoding and normalizing in `Serializer`

3.3.0
-----

 * added `SerializerPass`

3.1.0
-----

 * added support for serializing objects that implement `JsonSerializable`
 * added the `DenormalizerAwareTrait` and `NormalizerAwareTrait` traits to
   support normalizer/denormalizer awareness
 * added the `DenormalizerAwareInterface` and `NormalizerAwareInterface`
   interfaces to support normalizer/denormalizer awareness
 * added a PSR-6 compatible adapter for caching metadata
 * added a `MaxDepth` option to limit the depth of the object graph when
   serializing objects
 * added support for serializing `SplFileInfo` objects
 * added support for serializing objects that implement `DateTimeInterface`
 * added `AbstractObjectNormalizer` as a base class for normalizers that deal
   with objects
 * added support to relation deserialization

2.7.0
-----

 * added support for serialization and deserialization groups including
   annotations, XML and YAML mapping.
 * added `AbstractNormalizer` to factorise code and ease normalizers development
 * added circular references handling for `PropertyNormalizer`
 * added support for a context key called `object_to_populate` in `AbstractNormalizer`
   to reuse existing objects in the deserialization process
 * added `NameConverterInterface` and `CamelCaseToSnakeCaseNameConverter`
 * [DEPRECATION] `GetSetMethodNormalizer::setCamelizedAttributes()` and
   `PropertyNormalizer::setCamelizedAttributes()` are replaced by
   `CamelCaseToSnakeCaseNameConverter`
 * [DEPRECATION] the `Exception` interface has been renamed to `ExceptionInterface`
 * added `ObjectNormalizer` leveraging the `PropertyAccess` component to normalize
   objects containing both properties and getters / setters / issers / hassers methods.
 * added `xml_type_cast_attributes` context option for allowing users to opt-out of typecasting
   xml attributes.

2.6.0
-----

 * added a new serializer: `PropertyNormalizer`. Like `GetSetMethodNormalizer`,
   this normalizer will map an object's properties to an array.
 * added circular references handling for `GetSetMethodNormalizer`

2.5.0
-----

 * added support for `is.*` getters in `GetSetMethodNormalizer`

2.4.0
-----

 * added `$context` support for XMLEncoder.
 * [DEPRECATION] JsonEncode and JsonDecode where modified to throw
   an exception if error found. No need for `get*Error()` functions

2.3.0
-----

 * added `GetSetMethodNormalizer::setCamelizedAttributes` to allow calling
   camel cased methods for underscored properties

2.2.0
-----

 * [BC BREAK] All Serializer, Normalizer and Encoder interfaces have been
   modified to include an optional `$context` array parameter.
 * The XML Root name can now be configured with the `xml_root_name`
   parameter in the context option to the `XmlEncoder`.
 * Options to `json_encode` and `json_decode` can be passed through
   the context options of `JsonEncode` and `JsonDecode` encoder/decoders.

2.1.0
-----

 * added DecoderInterface::supportsDecoding(),
   EncoderInterface::supportsEncoding()
 * removed NormalizableInterface::denormalize(),
   NormalizerInterface::denormalize(),
   NormalizerInterface::supportsDenormalization()
 * removed normalize() denormalize() encode() decode() supportsSerialization()
   supportsDeserialization() supportsEncoding() supportsDecoding()
   getEncoder() from SerializerInterface
 * Serializer now implements NormalizerInterface, DenormalizerInterface,
   EncoderInterface, DecoderInterface in addition to SerializerInterface
 * added DenormalizableInterface and DenormalizerInterface
 * [BC BREAK] changed `GetSetMethodNormalizer`'s key names from all lowercased
   to camelCased (e.g. `mypropertyvalue` to `myPropertyValue`)
 * [BC BREAK] convert the `item` XML tag to an array

    ``` xml
    <?xml version="1.0"?>
    <response>
        <item><title><![CDATA[title1]]></title></item><item><title><![CDATA[title2]]></title></item>
    </response>
    ```

    Before:

        Array()

    After:

        Array(
            [item] => Array(
                [0] => Array(
                    [title] => title1
                )
                [1] => Array(
                    [title] => title2
                )
            )
        )
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Serializer\Encoder;

use _ContaoManager\Symfony\Component\Serializer\Exception\InvalidArgumentException;
use _ContaoManager\Symfony\Component\Serializer\Exception\UnexpectedValueException;
/**
 * Encodes CSV data.
 *
 * @author Kévin Dunglas <dunglas@gmail.com>
 * @author Oliver Hoff <oliver@hofff.com>
 */
class CsvEncoder implements EncoderInterface, DecoderInterface
{
    public const FORMAT = 'csv';
    public const DELIMITER_KEY = 'csv_delimiter';
    public const ENCLOSURE_KEY = 'csv_enclosure';
    public const ESCAPE_CHAR_KEY = 'csv_escape_char';
    public const KEY_SEPARATOR_KEY = 'csv_key_separator';
    public const HEADERS_KEY = 'csv_headers';
    public const ESCAPE_FORMULAS_KEY = 'csv_escape_formulas';
    public const AS_COLLECTION_KEY = 'as_collection';
    public const NO_HEADERS_KEY = 'no_headers';
    public const END_OF_LINE = 'csv_end_of_line';
    public const OUTPUT_UTF8_BOM_KEY = 'output_utf8_bom';
    private const UTF8_BOM = "﻿";
    private const FORMULAS_START_CHARACTERS = ['=', '-', '+', '@', "\t", "\r"];
    private array $defaultContext = [self::DELIMITER_KEY => ',', self::ENCLOSURE_KEY => '"', self::ESCAPE_CHAR_KEY => '', self::END_OF_LINE => "\n", self::ESCAPE_FORMULAS_KEY => \false, self::HEADERS_KEY => [], self::KEY_SEPARATOR_KEY => '.', self::NO_HEADERS_KEY => \false, self::AS_COLLECTION_KEY => \true, self::OUTPUT_UTF8_BOM_KEY => \false];
    public function __construct(array $defaultContext = [])
    {
        $this->defaultContext = array_merge($this->defaultContext, $defaultContext);
    }
    public function encode(mixed $data, string $format, array $context = []): string
    {
        $handle = fopen('php://temp,', 'w+');
        if (!is_iterable($data)) {
            $data = [[$data]];
        } elseif (empty($data)) {
            $data = [[]];
        } else {
            if ($data instanceof \Traversable) {
                // Generators can only be iterated once — convert to array to allow multiple traversals
                $data = iterator_to_array($data);
            }
            // Sequential arrays of arrays are considered as collections
            $i = 0;
            foreach ($data as $key => $value) {
                if ($i !== $key || !\is_array($value)) {
                    $data = [$data];
                    break;
                }
                ++$i;
            }
        }
        [$delimiter, $enclosure, $escapeChar, $keySeparator, $headers, $escapeFormulas, $outputBom] = $this->getCsvOptions($context);
        foreach ($data as &$value) {
            $flattened = [];
            $this->flatten($value, $flattened, $keySeparator, '', $escapeFormulas);
            $value = $flattened;
        }
        unset($value);
        $headers = array_merge(array_values($headers), array_diff($this->extractHeaders($data), $headers));
        $endOfLine = $context[self::END_OF_LINE] ?? $this->defaultContext[self::END_OF_LINE];
        if (!($context[self::NO_HEADERS_KEY] ?? $this->defaultContext[self::NO_HEADERS_KEY])) {
            fputcsv($handle, $headers, $delimiter, $enclosure, $escapeChar);
            if ("\n" !== $endOfLine && 0 === fseek($handle, -1, \SEEK_CUR)) {
                fwrite($handle, $endOfLine);
            }
        }
        $headers = array_fill_keys($headers, '');
        foreach ($data as $row) {
            fputcsv($handle, array_replace($headers, $row), $delimiter, $enclosure, $escapeChar);
            if ("\n" !== $endOfLine && 0 === fseek($handle, -1, \SEEK_CUR)) {
                fwrite($handle, $endOfLine);
            }
        }
        rewind($handle);
        $value = stream_get_contents($handle);
        fclose($handle);
        if ($outputBom) {
            if (!preg_match('//u', $value)) {
                throw new UnexpectedValueException('You are trying to add a UTF-8 BOM to a non UTF-8 text.');
            }
            $value = self::UTF8_BOM . $value;
        }
        return $value;
    }
    public function supportsEncoding(string $format): bool
    {
        return self::FORMAT === $format;
    }
    public function decode(string $data, string $format, array $context = []): mixed
    {
        $handle = fopen('php://temp', 'r+');
        fwrite($handle, $data);
        rewind($handle);
        if (str_starts_with($data, self::UTF8_BOM)) {
            fseek($handle, \strlen(self::UTF8_BOM));
        }
        $headers = null;
        $nbHeaders = 0;
        $headerCount = [];
        $result = [];
        [$delimiter, $enclosure, $escapeChar, $keySeparator, , , , $asCollection] = $this->getCsvOptions($context);
        while (\false !== $cols = fgetcsv($handle, 0, $delimiter, $enclosure, $escapeChar)) {
            $nbCols = \count($cols);
            if (null === $headers) {
                $nbHeaders = $nbCols;
                if ($context[self::NO_HEADERS_KEY] ?? $this->defaultContext[self::NO_HEADERS_KEY]) {
                    for ($i = 0; $i < $nbCols; ++$i) {
                        $headers[] = [$i];
                    }
                    $headerCount = array_fill(0, $nbCols, 1);
                } else {
                    foreach ($cols as $col) {
                        $header = explode($keySeparator, $col ?? '');
                        $headers[] = $header;
                        $headerCount[] = \count($header);
                    }
                    continue;
                }
            }
            $item = [];
            for ($i = 0; $i < $nbCols && $i < $nbHeaders; ++$i) {
                $depth = $headerCount[$i];
                $arr =& $item;
                for ($j = 0; $j < $depth; ++$j) {
                    $headerName = $headers[$i][$j];
                    if ('' === $headerName) {
                        $headerName = $i;
                    }
                    // Handle nested arrays
                    if ($j === $depth - 1) {
                        $arr[$headerName] = $cols[$i];
                        continue;
                    }
                    if (!isset($arr[$headerName])) {
                        $arr[$headerName] = [];
                    }
                    $arr =& $arr[$headerName];
                }
            }
            $result[] = $item;
        }
        fclose($handle);
        if ($asCollection) {
            return $result;
        }
        if (empty($result) || isset($result[1])) {
            return $result;
        }
        // If there is only one data line in the document, return it (the line), the result is not considered as a collection
        return $result[0];
    }
    public function supportsDecoding(string $format): bool
    {
        return self::FORMAT === $format;
    }
    /**
     * Flattens an array and generates keys including the path.
     */
    private function flatten(iterable $array, array &$result, string $keySeparator, string $parentKey = '', bool $escapeFormulas = \false): void
    {
        foreach ($array as $key => $value) {
            if (is_iterable($value)) {
                $this->flatten($value, $result, $keySeparator, $parentKey . $key . $keySeparator, $escapeFormulas);
            } else if ($escapeFormulas && \in_array(substr((string) $value, 0, 1), self::FORMULAS_START_CHARACTERS, \true)) {
                $result[$parentKey . $key] = "'" . $value;
            } else {
                // Ensures an actual value is used when dealing with true and false
                $result[$parentKey . $key] = \false === $value ? 0 : (\true === $value ? 1 : $value);
            }
        }
    }
    private function getCsvOptions(array $context): array
    {
        $delimiter = $context[self::DELIMITER_KEY] ?? $this->defaultContext[self::DELIMITER_KEY];
        $enclosure = $context[self::ENCLOSURE_KEY] ?? $this->defaultContext[self::ENCLOSURE_KEY];
        $escapeChar = $context[self::ESCAPE_CHAR_KEY] ?? $this->defaultContext[self::ESCAPE_CHAR_KEY];
        $keySeparator = $context[self::KEY_SEPARATOR_KEY] ?? $this->defaultContext[self::KEY_SEPARATOR_KEY];
        $headers = $context[self::HEADERS_KEY] ?? $this->defaultContext[self::HEADERS_KEY];
        $escapeFormulas = $context[self::ESCAPE_FORMULAS_KEY] ?? $this->defaultContext[self::ESCAPE_FORMULAS_KEY];
        $outputBom = $context[self::OUTPUT_UTF8_BOM_KEY] ?? $this->defaultContext[self::OUTPUT_UTF8_BOM_KEY];
        $asCollection = $context[self::AS_COLLECTION_KEY] ?? $this->defaultContext[self::AS_COLLECTION_KEY];
        if (!\is_array($headers)) {
            throw new InvalidArgumentException(\sprintf('The "%s" context variable must be an array or null, given "%s".', self::HEADERS_KEY, get_debug_type($headers)));
        }
        return [$delimiter, $enclosure, $escapeChar, $keySeparator, $headers, $escapeFormulas, $outputBom, $asCollection];
    }
    /**
     * @return string[]
     */
    private function extractHeaders(iterable $data): array
    {
        $headers = [];
        $flippedHeaders = [];
        foreach ($data as $row) {
            $previousHeader = null;
            foreach ($row as $header => $_) {
                if (isset($flippedHeaders[$header])) {
                    $previousHeader = $header;
                    continue;
                }
                if (null === $previousHeader) {
                    $n = \count($headers);
                } else {
                    $n = $flippedHeaders[$previousHeader] + 1;
                    for ($j = \count($headers); $j > $n; --$j) {
                        ++$flippedHeaders[$headers[$j] = $headers[$j - 1]];
                    }
                }
                $headers[$n] = $header;
                $flippedHeaders[$header] = $n;
                $previousHeader = $header;
            }
        }
        return $headers;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Serializer\Encoder;

/**
 * Adds the support of an extra $context parameter for the supportsDecoding method.
 *
 * @author Kévin Dunglas <dunglas@gmail.com>
 */
interface ContextAwareDecoderInterface extends DecoderInterface
{
    /**
     * @param array $context options that decoders have access to
     */
    public function supportsDecoding(string $format, array $context = []): bool;
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Serializer\Encoder;

use _ContaoManager\Symfony\Component\Serializer\Debug\TraceableEncoder;
use _ContaoManager\Symfony\Component\Serializer\Exception\RuntimeException;
/**
 * Encoder delegating the decoding to a chain of encoders.
 *
 * @author Jordi Boggiano <j.boggiano@seld.be>
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 * @author Lukas Kahwe Smith <smith@pooteeweet.org>
 *
 * @final
 */
class ChainEncoder implements ContextAwareEncoderInterface
{
    /**
     * @var array<string, array-key>
     */
    private array $encoderByFormat = [];
    /**
     * @param array<EncoderInterface> $encoders
     */
    public function __construct(private readonly array $encoders = [])
    {
    }
    final public function encode(mixed $data, string $format, array $context = []): string
    {
        return $this->getEncoder($format, $context)->encode($data, $format, $context);
    }
    public function supportsEncoding(string $format, array $context = []): bool
    {
        try {
            $this->getEncoder($format, $context);
        } catch (RuntimeException) {
            return \false;
        }
        return \true;
    }
    /**
     * Checks whether the normalization is needed for the given format.
     */
    public function needsNormalization(string $format, array $context = []): bool
    {
        $encoder = $this->getEncoder($format, $context);
        if ($encoder instanceof TraceableEncoder) {
            return $encoder->needsNormalization();
        }
        if (!$encoder instanceof NormalizationAwareInterface) {
            return \true;
        }
        if ($encoder instanceof self) {
            return $encoder->needsNormalization($format, $context);
        }
        return \false;
    }
    /**
     * Gets the encoder supporting the format.
     *
     * @throws RuntimeException if no encoder is found
     */
    private function getEncoder(string $format, array $context): EncoderInterface
    {
        if (isset($this->encoderByFormat[$format]) && isset($this->encoders[$this->encoderByFormat[$format]])) {
            return $this->encoders[$this->encoderByFormat[$format]];
        }
        $cache = \true;
        foreach ($this->encoders as $i => $encoder) {
            $cache = $cache && !$encoder instanceof ContextAwareEncoderInterface;
            if ($encoder->supportsEncoding($format, $context)) {
                if ($cache) {
                    $this->encoderByFormat[$format] = $i;
                }
                return $encoder;
            }
        }
        throw new RuntimeException(\sprintf('No encoder found for format "%s".', $format));
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Serializer\Encoder;

use _ContaoManager\Symfony\Component\Serializer\Exception\UnexpectedValueException;
/**
 * @author Jordi Boggiano <j.boggiano@seld.be>
 */
interface DecoderInterface
{
    /**
     * Decodes a string into PHP data.
     *
     * @param string $data    Data to decode
     * @param string $format  Format name
     * @param array  $context Options that decoders have access to
     *
     * The format parameter specifies which format the data is in; valid values
     * depend on the specific implementation. Authors implementing this interface
     * are encouraged to document which formats they support in a non-inherited
     * phpdoc comment.
     *
     * @return mixed
     *
     * @throws UnexpectedValueException
     */
    public function decode(string $data, string $format, array $context = []);
    /**
     * Checks whether the deserializer can decode from given format.
     *
     * @param string $format Format name
     *
     * @return bool
     */
    public function supportsDecoding(string $format);
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Serializer\Encoder;

/**
 * Adds the support of an extra $context parameter for the supportsEncoding method.
 *
 * @author Kévin Dunglas <dunglas@gmail.com>
 */
interface ContextAwareEncoderInterface extends EncoderInterface
{
    /**
     * @param array $context options that encoders have access to
     */
    public function supportsEncoding(string $format, array $context = []): bool;
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Serializer\Encoder;

/**
 * Defines the interface of encoders that will normalize data themselves.
 *
 * Implementing this interface essentially just tells the Serializer that the
 * data should not be pre-normalized before being passed to this Encoder.
 *
 * @author Jordi Boggiano <j.boggiano@seld.be>
 */
interface NormalizationAwareInterface
{
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Serializer\Encoder;

use _ContaoManager\Symfony\Component\Serializer\Exception\UnexpectedValueException;
/**
 * @author Jordi Boggiano <j.boggiano@seld.be>
 */
interface EncoderInterface
{
    /**
     * Encodes data into the given format.
     *
     * @param mixed  $data    Data to encode
     * @param string $format  Format name
     * @param array  $context Options that normalizers/encoders have access to
     *
     * @throws UnexpectedValueException
     */
    public function encode(mixed $data, string $format, array $context = []): string;
    /**
     * Checks whether the serializer can encode to given format.
     *
     * @param string $format Format name
     */
    public function supportsEncoding(string $format): bool;
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Serializer\Encoder;

use _ContaoManager\Symfony\Component\Serializer\Exception\RuntimeException;
/**
 * Decoder delegating the decoding to a chain of decoders.
 *
 * @author Jordi Boggiano <j.boggiano@seld.be>
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 * @author Lukas Kahwe Smith <smith@pooteeweet.org>
 *
 * @final
 */
class ChainDecoder implements ContextAwareDecoderInterface
{
    /**
     * @var array<string, array-key>
     */
    private array $decoderByFormat = [];
    /**
     * @param array<DecoderInterface> $decoders
     */
    public function __construct(private readonly array $decoders = [])
    {
    }
    final public function decode(string $data, string $format, array $context = []): mixed
    {
        return $this->getDecoder($format, $context)->decode($data, $format, $context);
    }
    public function supportsDecoding(string $format, array $context = []): bool
    {
        try {
            $this->getDecoder($format, $context);
        } catch (RuntimeException) {
            return \false;
        }
        return \true;
    }
    /**
     * Gets the decoder supporting the format.
     *
     * @throws RuntimeException if no decoder is found
     */
    private function getDecoder(string $format, array $context): DecoderInterface
    {
        if (isset($this->decoderByFormat[$format]) && isset($this->decoders[$this->decoderByFormat[$format]])) {
            return $this->decoders[$this->decoderByFormat[$format]];
        }
        $cache = \true;
        foreach ($this->decoders as $i => $decoder) {
            $cache = $cache && !$decoder instanceof ContextAwareDecoderInterface;
            if ($decoder->supportsDecoding($format, $context)) {
                if ($cache) {
                    $this->decoderByFormat[$format] = $i;
                }
                return $decoder;
            }
        }
        throw new RuntimeException(\sprintf('No decoder found for format "%s".', $format));
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Serializer\Encoder;

use _ContaoManager\Symfony\Component\Serializer\Exception\NotEncodableValueException;
/**
 * Encodes JSON data.
 *
 * @author Sander Coolen <sander@jibber.nl>
 */
class JsonEncode implements EncoderInterface
{
    /**
     * Configure the JSON flags bitmask.
     */
    public const OPTIONS = 'json_encode_options';
    private array $defaultContext = [self::OPTIONS => \JSON_PRESERVE_ZERO_FRACTION];
    public function __construct(array $defaultContext = [])
    {
        $this->defaultContext = array_merge($this->defaultContext, $defaultContext);
    }
    public function encode(mixed $data, string $format, array $context = []): string
    {
        $options = $context[self::OPTIONS] ?? $this->defaultContext[self::OPTIONS];
        try {
            $encodedJson = json_encode($data, $options);
        } catch (\JsonException $e) {
            throw new NotEncodableValueException($e->getMessage(), 0, $e);
        }
        if (\JSON_THROW_ON_ERROR & $options) {
            return $encodedJson;
        }
        if (\JSON_ERROR_NONE !== json_last_error() && (\false === $encodedJson || !($options & \JSON_PARTIAL_OUTPUT_ON_ERROR))) {
            throw new NotEncodableValueException(json_last_error_msg());
        }
        return $encodedJson;
    }
    public function supportsEncoding(string $format): bool
    {
        return JsonEncoder::FORMAT === $format;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Serializer\Encoder;

/**
 * Encodes JSON data.
 *
 * @author Jordi Boggiano <j.boggiano@seld.be>
 */
class JsonEncoder implements EncoderInterface, DecoderInterface
{
    public const FORMAT = 'json';
    protected $encodingImpl;
    protected $decodingImpl;
    private array $defaultContext = [JsonDecode::ASSOCIATIVE => \true];
    public function __construct(?JsonEncode $encodingImpl = null, ?JsonDecode $decodingImpl = null, array $defaultContext = [])
    {
        $this->defaultContext = array_merge($this->defaultContext, $defaultContext);
        $this->encodingImpl = $encodingImpl ?? new JsonEncode($this->defaultContext);
        $this->decodingImpl = $decodingImpl ?? new JsonDecode($this->defaultContext);
    }
    public function encode(mixed $data, string $format, array $context = []): string
    {
        $context = array_merge($this->defaultContext, $context);
        return $this->encodingImpl->encode($data, self::FORMAT, $context);
    }
    public function decode(string $data, string $format, array $context = []): mixed
    {
        $context = array_merge($this->defaultContext, $context);
        return $this->decodingImpl->decode($data, self::FORMAT, $context);
    }
    public function supportsEncoding(string $format): bool
    {
        return self::FORMAT === $format;
    }
    public function supportsDecoding(string $format): bool
    {
        return self::FORMAT === $format;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Serializer\Encoder;

use _ContaoManager\Seld\JsonLint\JsonParser;
use _ContaoManager\Symfony\Component\Serializer\Exception\NotEncodableValueException;
use _ContaoManager\Symfony\Component\Serializer\Exception\UnsupportedException;
/**
 * Decodes JSON data.
 *
 * @author Sander Coolen <sander@jibber.nl>
 */
class JsonDecode implements DecoderInterface
{
    /**
     * @deprecated since Symfony 6.4, to be removed in 7.0
     */
    protected $serializer;
    /**
     * True to return the result as an associative array, false for a nested stdClass hierarchy.
     */
    public const ASSOCIATIVE = 'json_decode_associative';
    /**
     * True to enable seld/jsonlint as a source for more specific error messages when json_decode fails.
     */
    public const DETAILED_ERROR_MESSAGES = 'json_decode_detailed_errors';
    public const OPTIONS = 'json_decode_options';
    /**
     * Specifies the recursion depth.
     */
    public const RECURSION_DEPTH = 'json_decode_recursion_depth';
    private array $defaultContext = [self::ASSOCIATIVE => \false, self::DETAILED_ERROR_MESSAGES => \false, self::OPTIONS => 0, self::RECURSION_DEPTH => 512];
    public function __construct(array $defaultContext = [])
    {
        $this->defaultContext = array_merge($this->defaultContext, $defaultContext);
    }
    /**
     * Decodes data.
     *
     * @param string $data    The encoded JSON string to decode
     * @param string $format  Must be set to JsonEncoder::FORMAT
     * @param array  $context An optional set of options for the JSON decoder; see below
     *
     * The $context array is a simple key=>value array, with the following supported keys:
     *
     * json_decode_associative: boolean
     *      If true, returns the object as an associative array.
     *      If false, returns the object as nested stdClass
     *      If not specified, this method will use the default set in JsonDecode::__construct
     *
     * json_decode_recursion_depth: integer
     *      Specifies the maximum recursion depth
     *      If not specified, this method will use the default set in JsonDecode::__construct
     *
     * json_decode_options: integer
     *      Specifies additional options as per documentation for json_decode
     *
     * json_decode_detailed_errors: bool
     *      If true, enables seld/jsonlint as a source for more specific error messages when json_decode fails.
     *      If false or not specified, this method will use default error messages from PHP's json_decode
     *
     * @throws NotEncodableValueException
     *
     * @see https://php.net/json_decode
     */
    public function decode(string $data, string $format, array $context = []): mixed
    {
        $associative = $context[self::ASSOCIATIVE] ?? $this->defaultContext[self::ASSOCIATIVE];
        $recursionDepth = $context[self::RECURSION_DEPTH] ?? $this->defaultContext[self::RECURSION_DEPTH];
        $options = $context[self::OPTIONS] ?? $this->defaultContext[self::OPTIONS];
        try {
            $decodedData = json_decode($data, $associative, $recursionDepth, $options);
        } catch (\JsonException $e) {
            throw new NotEncodableValueException($e->getMessage(), 0, $e);
        }
        if (\JSON_THROW_ON_ERROR & $options) {
            return $decodedData;
        }
        if (\JSON_ERROR_NONE === json_last_error()) {
            return $decodedData;
        }
        $errorMessage = json_last_error_msg();
        if (!($context[self::DETAILED_ERROR_MESSAGES] ?? $this->defaultContext[self::DETAILED_ERROR_MESSAGES])) {
            throw new NotEncodableValueException($errorMessage);
        }
        if (!class_exists(JsonParser::class)) {
            throw new UnsupportedException(\sprintf('Enabling "%s" serializer option requires seld/jsonlint. Try running "composer require seld/jsonlint".', self::DETAILED_ERROR_MESSAGES));
        }
        throw new NotEncodableValueException((new JsonParser())->lint($data)?->getMessage() ?: $errorMessage);
    }
    public function supportsDecoding(string $format): bool
    {
        return JsonEncoder::FORMAT === $format;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Serializer\Encoder;

use _ContaoManager\Symfony\Component\Serializer\Exception\NotEncodableValueException;
use _ContaoManager\Symfony\Component\Serializer\Exception\RuntimeException;
use _ContaoManager\Symfony\Component\Yaml\Dumper;
use _ContaoManager\Symfony\Component\Yaml\Exception\ParseException;
use _ContaoManager\Symfony\Component\Yaml\Parser;
use _ContaoManager\Symfony\Component\Yaml\Yaml;
/**
 * Encodes YAML data.
 *
 * @author Kévin Dunglas <dunglas@gmail.com>
 */
class YamlEncoder implements EncoderInterface, DecoderInterface
{
    public const FORMAT = 'yaml';
    private const ALTERNATIVE_FORMAT = 'yml';
    public const PRESERVE_EMPTY_OBJECTS = 'preserve_empty_objects';
    /**
     * Override the amount of spaces to use for indentation of nested nodes.
     *
     * This option only works in the constructor, not in calls to `encode`.
     */
    public const YAML_INDENTATION = 'yaml_indentation';
    public const YAML_INLINE = 'yaml_inline';
    /**
     * Initial indentation for root element.
     */
    public const YAML_INDENT = 'yaml_indent';
    public const YAML_FLAGS = 'yaml_flags';
    private readonly Dumper $dumper;
    private readonly Parser $parser;
    private array $defaultContext = [self::YAML_INLINE => 0, self::YAML_INDENT => 0, self::YAML_FLAGS => 0];
    public function __construct(?Dumper $dumper = null, ?Parser $parser = null, array $defaultContext = [])
    {
        if (!class_exists(Dumper::class)) {
            throw new RuntimeException('The YamlEncoder class requires the "Yaml" component. Try running "composer require symfony/yaml".');
        }
        if (!$dumper) {
            $dumper = \array_key_exists(self::YAML_INDENTATION, $defaultContext) ? new Dumper($defaultContext[self::YAML_INDENTATION]) : new Dumper();
        }
        $this->dumper = $dumper;
        $this->parser = $parser ?? new Parser();
        unset($defaultContext[self::YAML_INDENTATION]);
        $this->defaultContext = array_merge($this->defaultContext, $defaultContext);
    }
    public function encode(mixed $data, string $format, array $context = []): string
    {
        $context = array_merge($this->defaultContext, $context);
        if ($context[self::PRESERVE_EMPTY_OBJECTS] ?? \false) {
            $context[self::YAML_FLAGS] |= Yaml::DUMP_OBJECT_AS_MAP;
        }
        return $this->dumper->dump($data, $context[self::YAML_INLINE], $context[self::YAML_INDENT], $context[self::YAML_FLAGS]);
    }
    public function supportsEncoding(string $format): bool
    {
        return self::FORMAT === $format || self::ALTERNATIVE_FORMAT === $format;
    }
    public function decode(string $data, string $format, array $context = []): mixed
    {
        $context = array_merge($this->defaultContext, $context);
        try {
            return $this->parser->parse($data, $context[self::YAML_FLAGS]);
        } catch (ParseException $e) {
            throw new NotEncodableValueException($e->getMessage(), $e->getCode(), $e);
        }
    }
    public function supportsDecoding(string $format): bool
    {
        return self::FORMAT === $format || self::ALTERNATIVE_FORMAT === $format;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Serializer\Encoder;

use _ContaoManager\Symfony\Component\Serializer\Exception\BadMethodCallException;
use _ContaoManager\Symfony\Component\Serializer\Exception\NotEncodableValueException;
use _ContaoManager\Symfony\Component\Serializer\SerializerAwareInterface;
use _ContaoManager\Symfony\Component\Serializer\SerializerAwareTrait;
/**
 * @author Jordi Boggiano <j.boggiano@seld.be>
 * @author John Wards <jwards@whiteoctober.co.uk>
 * @author Fabian Vogler <fabian@equivalence.ch>
 * @author Kévin Dunglas <dunglas@gmail.com>
 * @author Dany Maillard <danymaillard93b@gmail.com>
 */
class XmlEncoder implements EncoderInterface, DecoderInterface, NormalizationAwareInterface, SerializerAwareInterface
{
    use SerializerAwareTrait;
    public const FORMAT = 'xml';
    public const AS_COLLECTION = 'as_collection';
    /**
     * An array of ignored XML node types while decoding, each one of the DOM Predefined XML_* constants.
     */
    public const DECODER_IGNORED_NODE_TYPES = 'decoder_ignored_node_types';
    /**
     * An array of ignored XML node types while encoding, each one of the DOM Predefined XML_* constants.
     */
    public const ENCODER_IGNORED_NODE_TYPES = 'encoder_ignored_node_types';
    public const ENCODING = 'xml_encoding';
    public const FORMAT_OUTPUT = 'xml_format_output';
    /**
     * A bit field of LIBXML_* constants for loading XML documents.
     */
    public const LOAD_OPTIONS = 'load_options';
    /**
     * A bit field of LIBXML_* constants for saving XML documents.
     */
    public const SAVE_OPTIONS = 'save_options';
    public const REMOVE_EMPTY_TAGS = 'remove_empty_tags';
    public const ROOT_NODE_NAME = 'xml_root_node_name';
    public const STANDALONE = 'xml_standalone';
    public const TYPE_CAST_ATTRIBUTES = 'xml_type_cast_attributes';
    public const VERSION = 'xml_version';
    public const CDATA_WRAPPING = 'cdata_wrapping';
    private array $defaultContext = [self::AS_COLLECTION => \false, self::DECODER_IGNORED_NODE_TYPES => [\XML_PI_NODE, \XML_COMMENT_NODE], self::ENCODER_IGNORED_NODE_TYPES => [], self::LOAD_OPTIONS => \LIBXML_NONET | \LIBXML_NOBLANKS, self::SAVE_OPTIONS => 0, self::REMOVE_EMPTY_TAGS => \false, self::ROOT_NODE_NAME => 'response', self::TYPE_CAST_ATTRIBUTES => \true, self::CDATA_WRAPPING => \true];
    public function __construct(array $defaultContext = [])
    {
        $this->defaultContext = array_merge($this->defaultContext, $defaultContext);
    }
    public function encode(mixed $data, string $format, array $context = []): string
    {
        $encoderIgnoredNodeTypes = $context[self::ENCODER_IGNORED_NODE_TYPES] ?? $this->defaultContext[self::ENCODER_IGNORED_NODE_TYPES];
        $ignorePiNode = \in_array(\XML_PI_NODE, $encoderIgnoredNodeTypes, \true);
        if ($data instanceof \DOMDocument) {
            return $data->saveXML($ignorePiNode ? $data->documentElement : null);
        }
        $xmlRootNodeName = $context[self::ROOT_NODE_NAME] ?? $this->defaultContext[self::ROOT_NODE_NAME];
        $dom = $this->createDomDocument($context);
        if (null !== $data && !\is_scalar($data)) {
            $root = $dom->createElement($xmlRootNodeName);
            $dom->appendChild($root);
            $this->buildXml($root, $data, $format, $context, $xmlRootNodeName);
        } else {
            $this->appendNode($dom, $data, $format, $context, $xmlRootNodeName);
        }
        return $dom->saveXML($ignorePiNode ? $dom->documentElement : null, $context[self::SAVE_OPTIONS] ?? $this->defaultContext[self::SAVE_OPTIONS]);
    }
    public function decode(string $data, string $format, array $context = []): mixed
    {
        if ('' === trim($data)) {
            throw new NotEncodableValueException('Invalid XML data, it cannot be empty.');
        }
        $internalErrors = libxml_use_internal_errors(\true);
        libxml_clear_errors();
        $dom = new \DOMDocument();
        $dom->loadXML($data, $context[self::LOAD_OPTIONS] ?? $this->defaultContext[self::LOAD_OPTIONS]);
        libxml_use_internal_errors($internalErrors);
        if ($error = libxml_get_last_error()) {
            libxml_clear_errors();
            throw new NotEncodableValueException($error->message);
        }
        $rootNode = null;
        $decoderIgnoredNodeTypes = $context[self::DECODER_IGNORED_NODE_TYPES] ?? $this->defaultContext[self::DECODER_IGNORED_NODE_TYPES];
        foreach ($dom->childNodes as $child) {
            if (\in_array($child->nodeType, $decoderIgnoredNodeTypes, \true)) {
                continue;
            }
            if (\XML_DOCUMENT_TYPE_NODE === $child->nodeType) {
                throw new NotEncodableValueException('Document types are not allowed.');
            }
            if (!$rootNode) {
                $rootNode = $child;
            }
        }
        // todo: throw an exception if the root node name is not correctly configured (bc)
        if ($rootNode->hasChildNodes()) {
            $data = $this->parseXml($rootNode, $context);
            if (\is_array($data)) {
                $data = $this->addXmlNamespaces($data, $rootNode, $dom);
            }
            return $data;
        }
        if (!$rootNode->hasAttributes()) {
            return $rootNode->nodeValue;
        }
        $data = array_merge($this->parseXmlAttributes($rootNode, $context), ['#' => $rootNode->nodeValue]);
        $data = $this->addXmlNamespaces($data, $rootNode, $dom);
        return $data;
    }
    public function supportsEncoding(string $format): bool
    {
        return self::FORMAT === $format;
    }
    public function supportsDecoding(string $format): bool
    {
        return self::FORMAT === $format;
    }
    final protected function appendXMLString(\DOMNode $node, string $val): bool
    {
        if ('' !== $val) {
            $frag = $node->ownerDocument->createDocumentFragment();
            $frag->appendXML($val);
            $node->appendChild($frag);
            return \true;
        }
        return \false;
    }
    final protected function appendText(\DOMNode $node, string $val): bool
    {
        $nodeText = $node->ownerDocument->createTextNode($val);
        $node->appendChild($nodeText);
        return \true;
    }
    final protected function appendCData(\DOMNode $node, string $val): bool
    {
        $nodeText = $node->ownerDocument->createCDATASection($val);
        $node->appendChild($nodeText);
        return \true;
    }
    final protected function appendDocumentFragment(\DOMNode $node, \DOMDocumentFragment $fragment): bool
    {
        if ($fragment instanceof \DOMDocumentFragment) {
            $node->appendChild($fragment);
            return \true;
        }
        return \false;
    }
    final protected function appendComment(\DOMNode $node, string $data): bool
    {
        $node->appendChild($node->ownerDocument->createComment($data));
        return \true;
    }
    /**
     * Checks the name is a valid xml element name.
     */
    final protected function isElementNameValid(string $name): bool
    {
        return $name && !str_contains($name, ' ') && preg_match('#^[\pL_][\pL0-9._:-]*$#ui', $name);
    }
    /**
     * Parse the input DOMNode into an array or a string.
     */
    private function parseXml(\DOMNode $node, array $context = []): array|string
    {
        $data = $this->parseXmlAttributes($node, $context);
        $value = $this->parseXmlValue($node, $context);
        if (!\count($data)) {
            return $value;
        }
        if (!\is_array($value)) {
            $data['#'] = $value;
            return $data;
        }
        if (1 === \count($value) && key($value)) {
            $data[key($value)] = current($value);
            return $data;
        }
        foreach ($value as $key => $val) {
            $data[$key] = $val;
        }
        return $data;
    }
    /**
     * Parse the input DOMNode attributes into an array.
     */
    private function parseXmlAttributes(\DOMNode $node, array $context = []): array
    {
        if (!$node->hasAttributes()) {
            return [];
        }
        $data = [];
        $typeCastAttributes = (bool) ($context[self::TYPE_CAST_ATTRIBUTES] ?? $this->defaultContext[self::TYPE_CAST_ATTRIBUTES]);
        foreach ($node->attributes as $attr) {
            if (!is_numeric($attr->nodeValue) || !$typeCastAttributes || isset($attr->nodeValue[1]) && '0' === $attr->nodeValue[0] && '.' !== $attr->nodeValue[1]) {
                $data['@' . $attr->nodeName] = $attr->nodeValue;
                continue;
            }
            if (\false !== $val = filter_var($attr->nodeValue, \FILTER_VALIDATE_INT)) {
                $data['@' . $attr->nodeName] = $val;
                continue;
            }
            $data['@' . $attr->nodeName] = (float) $attr->nodeValue;
        }
        return $data;
    }
    /**
     * Parse the input DOMNode value (content and children) into an array or a string.
     */
    private function parseXmlValue(\DOMNode $node, array $context = []): array|string
    {
        if (!$node->hasChildNodes()) {
            return $node->nodeValue;
        }
        if (1 === $node->childNodes->length && \in_array($node->firstChild->nodeType, [\XML_TEXT_NODE, \XML_CDATA_SECTION_NODE])) {
            return $node->firstChild->nodeValue;
        }
        $value = [];
        $decoderIgnoredNodeTypes = $context[self::DECODER_IGNORED_NODE_TYPES] ?? $this->defaultContext[self::DECODER_IGNORED_NODE_TYPES];
        foreach ($node->childNodes as $subnode) {
            if (\in_array($subnode->nodeType, $decoderIgnoredNodeTypes, \true)) {
                continue;
            }
            $val = $this->parseXml($subnode, $context);
            if ('item' === $subnode->nodeName && isset($val['@key'])) {
                $value[$val['@key']] = $val['#'] ?? $val;
            } else {
                $value[$subnode->nodeName][] = $val;
            }
        }
        $asCollection = $context[self::AS_COLLECTION] ?? $this->defaultContext[self::AS_COLLECTION];
        foreach ($value as $key => $val) {
            if (!$asCollection && \is_array($val) && 1 === \count($val)) {
                $value[$key] = current($val);
            }
        }
        return $value;
    }
    private function addXmlNamespaces(array $data, \DOMNode $node, \DOMDocument $document): array
    {
        $xpath = new \DOMXPath($document);
        foreach ($xpath->query('namespace::*', $node) as $nsNode) {
            $data['@' . $nsNode->nodeName] = $nsNode->nodeValue;
        }
        unset($data['@xmlns:xml']);
        return $data;
    }
    /**
     * Parse the data and convert it to DOMElements.
     *
     * @throws NotEncodableValueException
     */
    private function buildXml(\DOMNode $parentNode, mixed $data, string $format, array $context, ?string $xmlRootNodeName = null): bool
    {
        $append = \true;
        $removeEmptyTags = $context[self::REMOVE_EMPTY_TAGS] ?? $this->defaultContext[self::REMOVE_EMPTY_TAGS] ?? \false;
        $encoderIgnoredNodeTypes = $context[self::ENCODER_IGNORED_NODE_TYPES] ?? $this->defaultContext[self::ENCODER_IGNORED_NODE_TYPES];
        if (\is_array($data) || $data instanceof \Traversable && (null === $this->serializer || !$this->serializer->supportsNormalization($data, $format))) {
            foreach ($data as $key => $data) {
                // Ah this is the magic @ attribute types.
                if (str_starts_with($key, '@') && $this->isElementNameValid($attributeName = substr($key, 1))) {
                    if (!\is_scalar($data)) {
                        $data = $this->serializer->normalize($data, $format, $context);
                    }
                    if (\is_bool($data)) {
                        $data = (int) $data;
                    }
                    $parentNode->setAttribute($attributeName, $data);
                } elseif ('#' === $key) {
                    $append = $this->selectNodeType($parentNode, $data, $format, $context);
                } elseif ('#comment' === $key) {
                    if (!\in_array(\XML_COMMENT_NODE, $encoderIgnoredNodeTypes, \true)) {
                        $append = $this->appendComment($parentNode, $data);
                    }
                } elseif (\is_array($data) && \false === is_numeric($key)) {
                    // Is this array fully numeric keys?
                    if (ctype_digit(implode('', array_keys($data)))) {
                        /*
                         * Create nodes to append to $parentNode based on the $key of this array
                         * Produces <xml><item>0</item><item>1</item></xml>
                         * From ["item" => [0,1]];.
                         */
                        foreach ($data as $subData) {
                            $append = $this->appendNode($parentNode, $subData, $format, $context, $key);
                        }
                    } else {
                        $append = $this->appendNode($parentNode, $data, $format, $context, $key);
                    }
                } elseif (is_numeric($key) || !$this->isElementNameValid($key)) {
                    $append = $this->appendNode($parentNode, $data, $format, $context, 'item', $key);
                } elseif (null !== $data || !$removeEmptyTags) {
                    $append = $this->appendNode($parentNode, $data, $format, $context, $key);
                }
            }
            return $append;
        }
        if (\is_object($data)) {
            if (null === $this->serializer) {
                throw new BadMethodCallException(\sprintf('The serializer needs to be set to allow "%s()" to be used with object data.', __METHOD__));
            }
            $data = $this->serializer->normalize($data, $format, $context);
            if (null !== $data && !\is_scalar($data)) {
                return $this->buildXml($parentNode, $data, $format, $context, $xmlRootNodeName);
            }
            // top level data object was normalized into a scalar
            if (!$parentNode->parentNode->parentNode) {
                $root = $parentNode->parentNode;
                $root->removeChild($parentNode);
                return $this->appendNode($root, $data, $format, $context, $xmlRootNodeName);
            }
            return $this->appendNode($parentNode, $data, $format, $context, 'data');
        }
        throw new NotEncodableValueException('An unexpected value could not be serialized: ' . (!\is_resource($data) ? var_export($data, \true) : \sprintf('%s resource', get_resource_type($data))));
    }
    /**
     * Selects the type of node to create and appends it to the parent.
     */
    private function appendNode(\DOMNode $parentNode, mixed $data, string $format, array $context, string $nodeName, ?string $key = null): bool
    {
        $dom = $parentNode instanceof \DOMDocument ? $parentNode : $parentNode->ownerDocument;
        $node = $dom->createElement($nodeName);
        if (null !== $key) {
            $node->setAttribute('key', $key);
        }
        $appendNode = $this->selectNodeType($node, $data, $format, $context);
        // we may have decided not to append this node, either in error or if its $nodeName is not valid
        if ($appendNode) {
            $parentNode->appendChild($node);
        }
        return $appendNode;
    }
    /**
     * Checks if a value contains any characters which would require CDATA wrapping.
     */
    private function needsCdataWrapping(string $val, array $context): bool
    {
        return ($context[self::CDATA_WRAPPING] ?? $this->defaultContext[self::CDATA_WRAPPING]) && preg_match('/[<>&]/', $val);
    }
    /**
     * Tests the value being passed and decide what sort of element to create.
     *
     * @throws NotEncodableValueException
     */
    private function selectNodeType(\DOMNode $node, mixed $val, string $format, array $context): bool
    {
        if (\is_array($val)) {
            return $this->buildXml($node, $val, $format, $context);
        } elseif ($val instanceof \SimpleXMLElement) {
            $child = $node->ownerDocument->importNode(dom_import_simplexml($val), \true);
            $node->appendChild($child);
        } elseif ($val instanceof \Traversable) {
            $this->buildXml($node, $val, $format, $context);
        } elseif ($val instanceof \DOMNode) {
            $child = $node->ownerDocument->importNode($val, \true);
            $node->appendChild($child);
        } elseif (\is_object($val)) {
            if (null === $this->serializer) {
                throw new BadMethodCallException(\sprintf('The serializer needs to be set to allow "%s()" to be used with object data.', __METHOD__));
            }
            return $this->selectNodeType($node, $this->serializer->normalize($val, $format, $context), $format, $context);
        } elseif (is_numeric($val)) {
            return $this->appendText($node, is_nan($val) ? 'NAN' : (string) $val);
        } elseif (\is_string($val) && $this->needsCdataWrapping($val, $context)) {
            return $this->appendCData($node, $val);
        } elseif (\is_string($val)) {
            return $this->appendText($node, $val);
        } elseif (\is_bool($val)) {
            return $this->appendText($node, (int) $val);
        }
        return \true;
    }
    /**
     * Create a DOM document, taking serializer options into account.
     */
    private function createDomDocument(array $context): \DOMDocument
    {
        $document = new \DOMDocument();
        // Set an attribute on the DOM document specifying, as part of the XML declaration,
        $xmlOptions = [
            // nicely formats output with indentation and extra space
            self::FORMAT_OUTPUT => 'formatOutput',
            // the version number of the document
            self::VERSION => 'xmlVersion',
            // the encoding of the document
            self::ENCODING => 'encoding',
            // whether the document is standalone
            self::STANDALONE => 'xmlStandalone',
        ];
        foreach ($xmlOptions as $xmlOption => $documentProperty) {
            if ($contextOption = $context[$xmlOption] ?? $this->defaultContext[$xmlOption] ?? \false) {
                $document->{$documentProperty} = $contextOption;
            }
        }
        return $document;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Serializer\CacheWarmer;

use _ContaoManager\Symfony\Component\Filesystem\Filesystem;
use _ContaoManager\Symfony\Component\HttpKernel\CacheWarmer\CacheWarmerInterface;
use _ContaoManager\Symfony\Component\Serializer\Mapping\Factory\ClassMetadataFactoryCompiler;
use _ContaoManager\Symfony\Component\Serializer\Mapping\Factory\ClassMetadataFactoryInterface;
/**
 * @author Fabien Bourigault <bourigaultfabien@gmail.com>
 */
final class CompiledClassMetadataCacheWarmer implements CacheWarmerInterface
{
    public function __construct(private readonly array $classesToCompile, private readonly ClassMetadataFactoryInterface $classMetadataFactory, private readonly ClassMetadataFactoryCompiler $classMetadataFactoryCompiler, private readonly Filesystem $filesystem)
    {
    }
    public function warmUp(string $cacheDir, ?string $buildDir = null): array
    {
        $metadatas = [];
        foreach ($this->classesToCompile as $classToCompile) {
            $metadatas[] = $this->classMetadataFactory->getMetadataFor($classToCompile);
        }
        $code = $this->classMetadataFactoryCompiler->compile($metadatas);
        $this->filesystem->dumpFile("{$cacheDir}/serializer.class.metadata.php", $code);
        return [];
    }
    public function isOptional(): bool
    {
        return \true;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Serializer\Annotation;

class_exists(\_ContaoManager\Symfony\Component\Serializer\Attribute\SerializedName::class);
if (\false) {
    #[\Attribute(\Attribute::TARGET_METHOD | \Attribute::TARGET_PROPERTY)]
    class SerializedName extends \_ContaoManager\Symfony\Component\Serializer\Attribute\SerializedName
    {
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Serializer\Annotation;

class_exists(\_ContaoManager\Symfony\Component\Serializer\Attribute\Ignore::class);
if (\false) {
    #[\Attribute(\Attribute::TARGET_METHOD | \Attribute::TARGET_PROPERTY)]
    class Ignore extends \_ContaoManager\Symfony\Component\Serializer\Attribute\Ignore
    {
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Serializer\Annotation;

// do not deprecate in 6.4/7.0, to make it easier for the ecosystem to support 6.4, 7.4 and 8.0 simultaneously
class_exists(\_ContaoManager\Symfony\Component\Serializer\Attribute\Context::class);
if (\false) {
    #[\Attribute(\Attribute::TARGET_CLASS | \Attribute::TARGET_PROPERTY | \Attribute::TARGET_METHOD | \Attribute::IS_REPEATABLE)]
    class Context extends \_ContaoManager\Symfony\Component\Serializer\Attribute\Context
    {
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Serializer\Annotation;

class_exists(\_ContaoManager\Symfony\Component\Serializer\Attribute\DiscriminatorMap::class);
if (\false) {
    #[\Attribute(\Attribute::TARGET_CLASS)]
    class DiscriminatorMap extends \_ContaoManager\Symfony\Component\Serializer\Attribute\DiscriminatorMap
    {
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Serializer\Annotation;

class_exists(\_ContaoManager\Symfony\Component\Serializer\Attribute\SerializedPath::class);
if (\false) {
    #[\Attribute(\Attribute::TARGET_METHOD | \Attribute::TARGET_PROPERTY)]
    class SerializedPath extends \_ContaoManager\Symfony\Component\Serializer\Attribute\SerializedPath
    {
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Serializer\Annotation;

class_exists(\_ContaoManager\Symfony\Component\Serializer\Attribute\MaxDepth::class);
if (\false) {
    #[\Attribute(\Attribute::TARGET_METHOD | \Attribute::TARGET_PROPERTY)]
    class MaxDepth extends \_ContaoManager\Symfony\Component\Serializer\Attribute\MaxDepth
    {
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Serializer\Annotation;

class_exists(\_ContaoManager\Symfony\Component\Serializer\Attribute\Groups::class);
if (\false) {
    #[\Attribute(\Attribute::TARGET_METHOD | \Attribute::TARGET_PROPERTY | \Attribute::TARGET_CLASS)]
    class Groups extends \_ContaoManager\Symfony\Component\Serializer\Attribute\Groups
    {
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Serializer\Extractor;

/**
 * @author David Maicher <mail@dmaicher.de>
 */
interface ObjectPropertyListExtractorInterface
{
    /**
     * Gets the list of properties available for the given object.
     *
     * @return string[]|null
     */
    public function getProperties(object $object, array $context = []): ?array;
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Serializer\Extractor;

use _ContaoManager\Symfony\Component\PropertyInfo\PropertyListExtractorInterface;
/**
 * @author David Maicher <mail@dmaicher.de>
 */
final class ObjectPropertyListExtractor implements ObjectPropertyListExtractorInterface
{
    private PropertyListExtractorInterface $propertyListExtractor;
    private \Closure $objectClassResolver;
    public function __construct(PropertyListExtractorInterface $propertyListExtractor, ?callable $objectClassResolver = null)
    {
        $this->propertyListExtractor = $propertyListExtractor;
        $this->objectClassResolver = ($objectClassResolver ?? 'get_class')(...);
    }
    public function getProperties(object $object, array $context = []): ?array
    {
        $class = ($this->objectClassResolver)($object);
        return $this->propertyListExtractor->getProperties($class, $context);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Serializer;

/**
 * @author Jordi Boggiano <j.boggiano@seld.be>
 */
interface SerializerAwareInterface
{
    /**
     * Sets the owning Serializer object.
     *
     * @return void
     */
    public function setSerializer(SerializerInterface $serializer);
}
Serializer Component
====================

The Serializer component handles serializing and deserializing data structures,
including object graphs, into array structures or other formats like XML and
JSON.

Resources
---------

 * [Documentation](https://symfony.com/doc/current/components/serializer.html)
 * [Contributing](https://symfony.com/doc/current/contributing/index.html)
 * [Report issues](https://github.com/symfony/symfony/issues) and
   [send Pull Requests](https://github.com/symfony/symfony/pulls)
   in the [main Symfony repository](https://github.com/symfony/symfony)
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Serializer\NameConverter;

/**
 * Defines the interface for property name converters.
 *
 * @author Kévin Dunglas <dunglas@gmail.com>
 */
interface NameConverterInterface
{
    /**
     * Converts a property name to its normalized value.
     */
    public function normalize(string $propertyName): string;
    /**
     * Converts a property name to its denormalized value.
     */
    public function denormalize(string $propertyName): string;
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Serializer\NameConverter;

/**
 * Gives access to the class, the format and the context in the property name converters.
 *
 * @author Kévin Dunglas <dunglas@gmail.com>
 */
interface AdvancedNameConverterInterface extends NameConverterInterface
{
    public function normalize(string $propertyName, ?string $class = null, ?string $format = null, array $context = []): string;
    public function denormalize(string $propertyName, ?string $class = null, ?string $format = null, array $context = []): string;
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Serializer\NameConverter;

use _ContaoManager\Symfony\Component\Serializer\Exception\LogicException;
use _ContaoManager\Symfony\Component\Serializer\Mapping\Factory\ClassMetadataFactoryInterface;
use _ContaoManager\Symfony\Component\Serializer\Normalizer\AbstractNormalizer;
/**
 * @author Fabien Bourigault <bourigaultfabien@gmail.com>
 */
final class MetadataAwareNameConverter implements AdvancedNameConverterInterface
{
    /**
     * @var array<string, array<string, string|null>>
     */
    private static array $normalizeCache = [];
    /**
     * @var array<string, array<string, string|null>>
     */
    private static array $denormalizeCache = [];
    /**
     * @var array<string, array<string, string>>
     */
    private static array $attributesMetadataCache = [];
    public function __construct(private readonly ClassMetadataFactoryInterface $metadataFactory, private readonly ?NameConverterInterface $fallbackNameConverter = null)
    {
    }
    public function normalize(string $propertyName, ?string $class = null, ?string $format = null, array $context = []): string
    {
        if (null === $class) {
            return $this->normalizeFallback($propertyName, $class, $format, $context);
        }
        if (!\array_key_exists($class, self::$normalizeCache) || !\array_key_exists($propertyName, self::$normalizeCache[$class])) {
            self::$normalizeCache[$class][$propertyName] = $this->getCacheValueForNormalization($propertyName, $class);
        }
        return self::$normalizeCache[$class][$propertyName] ?? $this->normalizeFallback($propertyName, $class, $format, $context);
    }
    public function denormalize(string $propertyName, ?string $class = null, ?string $format = null, array $context = []): string
    {
        if (null === $class) {
            return $this->denormalizeFallback($propertyName, $class, $format, $context);
        }
        $cacheKey = $this->getCacheKey($class, $context);
        if (!\array_key_exists($cacheKey, self::$denormalizeCache) || !\array_key_exists($propertyName, self::$denormalizeCache[$cacheKey])) {
            self::$denormalizeCache[$cacheKey][$propertyName] = $this->getCacheValueForDenormalization($propertyName, $class, $context);
        }
        return self::$denormalizeCache[$cacheKey][$propertyName] ?? $this->denormalizeFallback($propertyName, $class, $format, $context);
    }
    private function getCacheValueForNormalization(string $propertyName, string $class): ?string
    {
        if (!$this->metadataFactory->hasMetadataFor($class)) {
            return null;
        }
        $attributesMetadata = $this->metadataFactory->getMetadataFor($class)->getAttributesMetadata();
        if (!\array_key_exists($propertyName, $attributesMetadata)) {
            return null;
        }
        if (null !== $attributesMetadata[$propertyName]->getSerializedName() && null !== $attributesMetadata[$propertyName]->getSerializedPath()) {
            throw new LogicException(\sprintf('Found SerializedName and SerializedPath attributes on property "%s" of class "%s".', $propertyName, $class));
        }
        return $attributesMetadata[$propertyName]->getSerializedName() ?? null;
    }
    private function normalizeFallback(string $propertyName, ?string $class = null, ?string $format = null, array $context = []): string
    {
        return $this->fallbackNameConverter ? $this->fallbackNameConverter->normalize($propertyName, $class, $format, $context) : $propertyName;
    }
    private function getCacheValueForDenormalization(string $propertyName, string $class, array $context): ?string
    {
        $cacheKey = $this->getCacheKey($class, $context);
        if (!\array_key_exists($cacheKey, self::$attributesMetadataCache)) {
            self::$attributesMetadataCache[$cacheKey] = $this->getCacheValueForAttributesMetadata($class, $context);
        }
        return self::$attributesMetadataCache[$cacheKey][$propertyName] ?? null;
    }
    private function denormalizeFallback(string $propertyName, ?string $class = null, ?string $format = null, array $context = []): string
    {
        return $this->fallbackNameConverter ? $this->fallbackNameConverter->denormalize($propertyName, $class, $format, $context) : $propertyName;
    }
    /**
     * @return array<string, string>
     */
    private function getCacheValueForAttributesMetadata(string $class, array $context): array
    {
        if (!$this->metadataFactory->hasMetadataFor($class)) {
            return [];
        }
        $classMetadata = $this->metadataFactory->getMetadataFor($class);
        $cache = [];
        foreach ($classMetadata->getAttributesMetadata() as $name => $metadata) {
            if (null === $metadata->getSerializedName()) {
                continue;
            }
            if (null !== $metadata->getSerializedName() && null !== $metadata->getSerializedPath()) {
                throw new LogicException(\sprintf('Found SerializedName and SerializedPath attributes on property "%s" of class "%s".', $name, $class));
            }
            $metadataGroups = $metadata->getGroups();
            $contextGroups = (array) ($context[AbstractNormalizer::GROUPS] ?? []);
            if ($contextGroups && !$metadataGroups) {
                continue;
            }
            if ($metadataGroups && !array_intersect($metadataGroups, $contextGroups) && !\in_array('*', $contextGroups, \true)) {
                continue;
            }
            $cache[$metadata->getSerializedName()] = $name;
        }
        return $cache;
    }
    private function getCacheKey(string $class, array $context): string
    {
        if (isset($context['cache_key'])) {
            return $class . '-' . $context['cache_key'];
        }
        return $class . hash('xxh128', serialize($context[AbstractNormalizer::GROUPS] ?? []));
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Serializer\NameConverter;

/**
 * CamelCase to Underscore name converter.
 *
 * @author Kévin Dunglas <dunglas@gmail.com>
 */
class CamelCaseToSnakeCaseNameConverter implements NameConverterInterface
{
    /**
     * @param array|null $attributes     The list of attributes to rename or null for all attributes
     * @param bool       $lowerCamelCase Use lowerCamelCase style
     */
    public function __construct(private ?array $attributes = null, private bool $lowerCamelCase = \true)
    {
    }
    public function normalize(string $propertyName): string
    {
        if (null === $this->attributes || \in_array($propertyName, $this->attributes)) {
            return strtolower(preg_replace('/[A-Z]/', '_ContaoManager\_', lcfirst($propertyName)));
        }
        return $propertyName;
    }
    public function denormalize(string $propertyName): string
    {
        $camelCasedName = preg_replace_callback('/(^|_|\.)+(.)/', fn($match) => ('.' === $match[1] ? '_' : '') . strtoupper($match[2]), $propertyName);
        if ($this->lowerCamelCase) {
            $camelCasedName = lcfirst($camelCasedName);
        }
        if (null === $this->attributes || \in_array($camelCasedName, $this->attributes)) {
            return $camelCasedName;
        }
        return $propertyName;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Serializer\Command;

use _ContaoManager\Symfony\Component\Console\Attribute\AsCommand;
use _ContaoManager\Symfony\Component\Console\Command\Command;
use _ContaoManager\Symfony\Component\Console\Helper\Dumper;
use _ContaoManager\Symfony\Component\Console\Helper\Table;
use _ContaoManager\Symfony\Component\Console\Input\InputArgument;
use _ContaoManager\Symfony\Component\Console\Input\InputInterface;
use _ContaoManager\Symfony\Component\Console\Output\OutputInterface;
use _ContaoManager\Symfony\Component\Console\Style\SymfonyStyle;
use _ContaoManager\Symfony\Component\Serializer\Mapping\ClassMetadataInterface;
use _ContaoManager\Symfony\Component\Serializer\Mapping\Factory\ClassMetadataFactoryInterface;
/**
 * A console command to debug Serializer information.
 *
 * @author Loïc Frémont <lc.fremont@gmail.com>
 */
#[AsCommand(name: 'debug:serializer', description: 'Display serialization information for classes')]
class DebugCommand extends Command
{
    public function __construct(private readonly ClassMetadataFactoryInterface $serializer)
    {
        parent::__construct();
    }
    protected function configure(): void
    {
        $this->addArgument('class', InputArgument::REQUIRED, 'A fully qualified class name')->setHelp("The <info>%command.name% 'App\\Entity\\Dummy'</info> command dumps the serializer groups for the dummy class.");
    }
    protected function execute(InputInterface $input, OutputInterface $output): int
    {
        $class = $input->getArgument('class');
        if (!class_exists($class)) {
            $io = new SymfonyStyle($input, $output);
            $io->error(\sprintf('Class "%s" was not found.', $class));
            return Command::FAILURE;
        }
        $this->dumpSerializerDataForClass($input, $output, $class);
        return Command::SUCCESS;
    }
    private function dumpSerializerDataForClass(InputInterface $input, OutputInterface $output, string $class): void
    {
        $io = new SymfonyStyle($input, $output);
        $title = \sprintf('<info>%s</info>', $class);
        $rows = [];
        $dump = new Dumper($output);
        $classMetadata = $this->serializer->getMetadataFor($class);
        foreach ($this->getAttributesData($classMetadata) as $propertyName => $data) {
            $rows[] = [$propertyName, $dump($data)];
        }
        if (!$rows) {
            $io->section($title);
            $io->text('No Serializer data were found for this class.');
            return;
        }
        $io->section($title);
        $table = new Table($output);
        $table->setHeaders(['Property', 'Options']);
        $table->setRows($rows);
        $table->render();
    }
    /**
     * @return array<string, array<string, mixed>>
     */
    private function getAttributesData(ClassMetadataInterface $classMetadata): array
    {
        $data = [];
        foreach ($classMetadata->getAttributesMetadata() as $attributeMetadata) {
            $data[$attributeMetadata->getName()] = ['groups' => $attributeMetadata->getGroups(), 'maxDepth' => $attributeMetadata->getMaxDepth(), 'serializedName' => $attributeMetadata->getSerializedName(), 'ignore' => $attributeMetadata->isIgnored(), 'normalizationContexts' => $attributeMetadata->getNormalizationContexts(), 'denormalizationContexts' => $attributeMetadata->getDenormalizationContexts()];
        }
        return $data;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Serializer\Normalizer;

use _ContaoManager\Symfony\Component\PropertyInfo\Type;
use _ContaoManager\Symfony\Component\Serializer\Exception\InvalidArgumentException;
use _ContaoManager\Symfony\Component\Serializer\Exception\NotNormalizableValueException;
/**
 * Normalizes an object implementing the {@see \DateTimeInterface} to a date string.
 * Denormalizes a date string to an instance of {@see \DateTime} or {@see \DateTimeImmutable}.
 *
 * @author Kévin Dunglas <dunglas@gmail.com>
 *
 * @final since Symfony 6.3
 */
class DateTimeNormalizer implements NormalizerInterface, DenormalizerInterface, CacheableSupportsMethodInterface
{
    public const FORMAT_KEY = 'datetime_format';
    public const TIMEZONE_KEY = 'datetime_timezone';
    private array $defaultContext = [self::FORMAT_KEY => \DateTimeInterface::RFC3339, self::TIMEZONE_KEY => null];
    private const SUPPORTED_TYPES = [\DateTimeInterface::class => \true, \DateTimeImmutable::class => \true, \DateTime::class => \true];
    public function __construct(array $defaultContext = [])
    {
        $this->setDefaultContext($defaultContext);
    }
    public function setDefaultContext(array $defaultContext): void
    {
        $this->defaultContext = array_merge($this->defaultContext, $defaultContext);
    }
    public function getSupportedTypes(?string $format): array
    {
        $isCacheable = __CLASS__ === static::class || $this->hasCacheableSupportsMethod();
        return [\DateTimeInterface::class => $isCacheable, \DateTimeImmutable::class => $isCacheable, \DateTime::class => $isCacheable];
    }
    /**
     * @throws InvalidArgumentException
     */
    public function normalize(mixed $object, ?string $format = null, array $context = []): string
    {
        if (!$object instanceof \DateTimeInterface) {
            throw new InvalidArgumentException('The object must implement the "\DateTimeInterface".');
        }
        $dateTimeFormat = $context[self::FORMAT_KEY] ?? $this->defaultContext[self::FORMAT_KEY];
        $timezone = $this->getTimezone($context);
        if (null !== $timezone) {
            $object = clone $object;
            $object = $object->setTimezone($timezone);
        }
        return $object->format($dateTimeFormat);
    }
    /**
     * @param array $context
     */
    public function supportsNormalization(mixed $data, ?string $format = null): bool
    {
        return $data instanceof \DateTimeInterface;
    }
    /**
     * @throws NotNormalizableValueException
     */
    public function denormalize(mixed $data, string $type, ?string $format = null, array $context = []): \DateTimeInterface
    {
        if (\is_int($data) || \is_float($data)) {
            switch ($context[self::FORMAT_KEY] ?? $this->defaultContext[self::FORMAT_KEY] ?? null) {
                case 'U':
                    $data = \sprintf('%d', $data);
                    break;
                case 'U.u':
                    $data = \sprintf('%.6F', $data);
                    break;
            }
        }
        if (!\is_string($data) || '' === trim($data)) {
            throw NotNormalizableValueException::createForUnexpectedDataType('The data is either not an string, an empty string, or null; you should pass a string that can be parsed with the passed format or a valid DateTime string.', $data, [Type::BUILTIN_TYPE_STRING], $context['deserialization_path'] ?? null, \true);
        }
        try {
            if (\DateTimeInterface::class === $type) {
                $type = \DateTimeImmutable::class;
            }
            $timezone = $this->getTimezone($context);
            $dateTimeFormat = $context[self::FORMAT_KEY] ?? null;
            if (null !== $dateTimeFormat) {
                if (\false !== $object = $type::createFromFormat($dateTimeFormat, $data, $timezone)) {
                    return $object;
                }
                $dateTimeErrors = $type::getLastErrors();
                throw NotNormalizableValueException::createForUnexpectedDataType(\sprintf('Parsing datetime string "%s" using format "%s" resulted in %d errors: ', $data, $dateTimeFormat, $dateTimeErrors['error_count']) . "\n" . implode("\n", $this->formatDateTimeErrors($dateTimeErrors['errors'])), $data, [Type::BUILTIN_TYPE_STRING], $context['deserialization_path'] ?? null, \true);
            }
            $defaultDateTimeFormat = $this->defaultContext[self::FORMAT_KEY] ?? null;
            if (null !== $defaultDateTimeFormat) {
                if (\false !== $object = $type::createFromFormat($defaultDateTimeFormat, $data, $timezone)) {
                    return $object;
                }
            }
            return new $type($data, $timezone);
        } catch (NotNormalizableValueException $e) {
            throw $e;
        } catch (\Exception $e) {
            throw NotNormalizableValueException::createForUnexpectedDataType($e->getMessage(), $data, [Type::BUILTIN_TYPE_STRING], $context['deserialization_path'] ?? null, \false, $e->getCode(), $e);
        }
    }
    /**
     * @param array $context
     */
    public function supportsDenormalization(mixed $data, string $type, ?string $format = null): bool
    {
        return isset(self::SUPPORTED_TYPES[$type]);
    }
    /**
     * @deprecated since Symfony 6.3, use "getSupportedTypes()" instead
     */
    public function hasCacheableSupportsMethod(): bool
    {
        trigger_deprecation('symfony/serializer', '6.3', 'The "%s()" method is deprecated, implement "%s::getSupportedTypes()" instead.', __METHOD__, get_debug_type($this));
        return __CLASS__ === static::class;
    }
    /**
     * Formats datetime errors.
     *
     * @return string[]
     */
    private function formatDateTimeErrors(array $errors): array
    {
        $formattedErrors = [];
        foreach ($errors as $pos => $message) {
            $formattedErrors[] = \sprintf('at position %d: %s', $pos, $message);
        }
        return $formattedErrors;
    }
    private function getTimezone(array $context): ?\DateTimeZone
    {
        $dateTimeZone = $context[self::TIMEZONE_KEY] ?? $this->defaultContext[self::TIMEZONE_KEY];
        if (null === $dateTimeZone) {
            return null;
        }
        return $dateTimeZone instanceof \DateTimeZone ? $dateTimeZone : new \DateTimeZone($dateTimeZone);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Serializer\Normalizer;

use _ContaoManager\Symfony\Component\Mime\Address;
use _ContaoManager\Symfony\Component\Mime\Header\HeaderInterface;
use _ContaoManager\Symfony\Component\Mime\Header\Headers;
use _ContaoManager\Symfony\Component\Mime\Header\UnstructuredHeader;
use _ContaoManager\Symfony\Component\Mime\Message;
use _ContaoManager\Symfony\Component\Mime\Part\AbstractPart;
use _ContaoManager\Symfony\Component\Mime\RawMessage;
use _ContaoManager\Symfony\Component\Serializer\Exception\LogicException;
use _ContaoManager\Symfony\Component\Serializer\SerializerAwareInterface;
use _ContaoManager\Symfony\Component\Serializer\SerializerInterface;
/**
 * Normalize Mime message classes.
 *
 * It forces the use of a PropertyNormalizer instance for normalization
 * of all data objects composing a Message.
 *
 * Emails using resources for any parts are not serializable.
 */
final class MimeMessageNormalizer implements NormalizerInterface, DenormalizerInterface, SerializerAwareInterface, CacheableSupportsMethodInterface
{
    private NormalizerInterface&DenormalizerInterface $serializer;
    private array $headerClassMap;
    private \ReflectionProperty $headersProperty;
    public function __construct(private readonly PropertyNormalizer $normalizer)
    {
        $this->headerClassMap = (new \ReflectionClassConstant(Headers::class, 'HEADER_CLASS_MAP'))->getValue();
        $this->headersProperty = new \ReflectionProperty(Headers::class, 'headers');
    }
    public function getSupportedTypes(?string $format): array
    {
        $isCacheable = __CLASS__ === static::class || $this->hasCacheableSupportsMethod();
        return [Message::class => $isCacheable, Headers::class => $isCacheable, HeaderInterface::class => $isCacheable, Address::class => $isCacheable, AbstractPart::class => $isCacheable];
    }
    public function setSerializer(SerializerInterface $serializer): void
    {
        if (!$serializer instanceof NormalizerInterface || !$serializer instanceof DenormalizerInterface) {
            throw new LogicException(\sprintf('The passed serializer should implement both NormalizerInterface and DenormalizerInterface, "%s" given.', get_debug_type($serializer)));
        }
        $this->serializer = $serializer;
        $this->normalizer->setSerializer($serializer);
    }
    public function normalize(mixed $object, ?string $format = null, array $context = []): array|string|int|float|bool|\ArrayObject|null
    {
        if ($object instanceof Headers) {
            $ret = [];
            foreach ($this->headersProperty->getValue($object) as $name => $header) {
                $ret[$name] = $this->serializer->normalize($header, $format, $context);
            }
            return $ret;
        }
        $ret = $this->normalizer->normalize($object, $format, $context);
        if ($object instanceof AbstractPart) {
            $ret['class'] = $object::class;
            unset($ret['seekable'], $ret['cid'], $ret['handle']);
        }
        if ($object instanceof RawMessage && \array_key_exists('message', $ret) && null === $ret['message']) {
            unset($ret['message']);
        }
        return $ret;
    }
    public function denormalize(mixed $data, string $type, ?string $format = null, array $context = []): mixed
    {
        if (Headers::class === $type) {
            $ret = [];
            foreach ($data as $headers) {
                foreach ($headers as $header) {
                    $ret[] = $this->serializer->denormalize($header, $this->headerClassMap[strtolower($header['name'])] ?? UnstructuredHeader::class, $format, $context);
                }
            }
            return new Headers(...$ret);
        }
        if (AbstractPart::class === $type) {
            $type = $data['class'];
            unset($data['class']);
            $data['headers'] = $this->serializer->denormalize($data['headers'], Headers::class, $format, $context);
        }
        return $this->normalizer->denormalize($data, $type, $format, $context);
    }
    public function supportsNormalization(mixed $data, ?string $format = null, array $context = []): bool
    {
        return $data instanceof Message || $data instanceof Headers || $data instanceof HeaderInterface || $data instanceof Address || $data instanceof AbstractPart;
    }
    public function supportsDenormalization(mixed $data, string $type, ?string $format = null, array $context = []): bool
    {
        return is_a($type, Message::class, \true) || Headers::class === $type || AbstractPart::class === $type;
    }
    /**
     * @deprecated since Symfony 6.3, use "getSupportedTypes()" instead
     */
    public function hasCacheableSupportsMethod(): bool
    {
        trigger_deprecation('symfony/serializer', '6.3', 'The "%s()" method is deprecated, implement "%s::getSupportedTypes()" instead.', __METHOD__, get_debug_type($this));
        return \true;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Serializer\Normalizer;

/**
 * Defines the most basic interface a class must implement to be denormalizable.
 *
 * If a denormalizer is registered for the class and it doesn't implement
 * the Denormalizable interfaces, the normalizer will be used instead
 *
 * @author Jordi Boggiano <j.boggiano@seld.be>
 */
interface DenormalizableInterface
{
    /**
     * Denormalizes the object back from an array of scalars|arrays.
     *
     * It is important to understand that the denormalize() call should denormalize
     * recursively all child objects of the implementor.
     *
     * @param DenormalizerInterface       $denormalizer The denormalizer is given so that you
     *                                                  can use it to denormalize objects contained within this object
     * @param array|string|int|float|bool $data         The data from which to re-create the object
     * @param string|null                 $format       The format is optionally given to be able to denormalize
     *                                                  differently based on different input formats
     * @param array                       $context      Options for denormalizing
     *
     * @return void
     */
    public function denormalize(DenormalizerInterface $denormalizer, array|string|int|float|bool $data, ?string $format = null, array $context = []);
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Serializer\Normalizer;

use _ContaoManager\Symfony\Component\ErrorHandler\Exception\FlattenException;
use _ContaoManager\Symfony\Component\HttpKernel\Exception\HttpExceptionInterface;
use _ContaoManager\Symfony\Component\Messenger\Exception\ValidationFailedException as MessageValidationFailedException;
use _ContaoManager\Symfony\Component\Serializer\Exception\InvalidArgumentException;
use _ContaoManager\Symfony\Component\Serializer\Exception\PartialDenormalizationException;
use _ContaoManager\Symfony\Component\Serializer\SerializerAwareInterface;
use _ContaoManager\Symfony\Component\Serializer\SerializerAwareTrait;
use _ContaoManager\Symfony\Component\Validator\Exception\ValidationFailedException;
use _ContaoManager\Symfony\Contracts\Translation\TranslatorInterface;
/**
 * Normalizes errors according to the API Problem spec (RFC 7807).
 *
 * @see https://tools.ietf.org/html/rfc7807
 *
 * @author Kévin Dunglas <dunglas@gmail.com>
 * @author Yonel Ceruto <yonelceruto@gmail.com>
 */
class ProblemNormalizer implements NormalizerInterface, SerializerAwareInterface, CacheableSupportsMethodInterface
{
    use SerializerAwareTrait;
    public const TITLE = 'title';
    public const TYPE = 'type';
    public const STATUS = 'status';
    public function __construct(private bool $debug = \false, private array $defaultContext = [], private ?TranslatorInterface $translator = null)
    {
    }
    public function getSupportedTypes(?string $format): array
    {
        return [FlattenException::class => __CLASS__ === self::class || $this->hasCacheableSupportsMethod()];
    }
    public function normalize(mixed $object, ?string $format = null, array $context = []): array
    {
        if (!$object instanceof FlattenException) {
            throw new InvalidArgumentException(\sprintf('The object must implement "%s".', FlattenException::class));
        }
        $data = [];
        $context += $this->defaultContext;
        $debug = $this->debug && ($context['debug'] ?? \true);
        $exception = $context['exception'] ?? null;
        if ($exception instanceof HttpExceptionInterface) {
            $exception = $exception->getPrevious();
            if ($exception instanceof PartialDenormalizationException) {
                $trans = $this->translator ? $this->translator->trans(...) : fn($m, $p) => strtr($m, $p);
                $template = 'This value should be of type {{ type }}.';
                $data = [self::TYPE => 'https://symfony.com/errors/validation', self::TITLE => 'Validation Failed', 'violations' => array_map(fn($e) => ['propertyPath' => $e->getPath(), 'title' => $trans($template, ['{{ type }}' => implode('|', $e->getExpectedTypes() ?? ['?'])], 'validators'), 'template' => $template, 'parameters' => ['{{ type }}' => implode('|', $e->getExpectedTypes() ?? ['?'])]] + ($debug || $e->canUseMessageForUser() ? ['hint' => $e->getMessage()] : []), $exception->getErrors())];
                $data['detail'] = implode("\n", array_map(fn($e) => $e['propertyPath'] . ': ' . $e['title'], $data['violations']));
            } elseif (($exception instanceof ValidationFailedException || $exception instanceof MessageValidationFailedException) && $this->serializer instanceof NormalizerInterface && $this->serializer->supportsNormalization($exception->getViolations(), $format, $context)) {
                $data = $this->serializer->normalize($exception->getViolations(), $format, $context);
            }
        }
        $data = [self::TYPE => $data[self::TYPE] ?? $context[self::TYPE] ?? 'https://tools.ietf.org/html/rfc2616#section-10', self::TITLE => $data[self::TITLE] ?? $context[self::TITLE] ?? 'An error occurred', self::STATUS => $context[self::STATUS] ?? $object->getStatusCode(), 'detail' => $data['detail'] ?? ($debug ? $object->getMessage() : $object->getStatusText())] + $data;
        if ($debug) {
            $data['class'] = $object->getClass();
            $data['trace'] = $object->getTrace();
        }
        return $data;
    }
    /**
     * @param array $context
     */
    public function supportsNormalization(mixed $data, ?string $format = null): bool
    {
        return $data instanceof FlattenException;
    }
    /**
     * @deprecated since Symfony 6.3, use "getSupportedTypes()" instead
     */
    public function hasCacheableSupportsMethod(): bool
    {
        trigger_deprecation('symfony/serializer', '6.3', 'The "%s()" method is deprecated, implement "%s::getSupportedTypes()" instead.', __METHOD__, get_debug_type($this));
        return \true;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Serializer\Normalizer;

/**
 * Marker interface for normalizers and denormalizers that use
 * only the type and the format in their supports*() methods.
 *
 * By implementing this interface, the return value of the
 * supports*() methods will be cached by type and format.
 *
 * @author Kévin Dunglas <dunglas@gmail.com>
 *
 * @deprecated since Symfony 6.3, implement "getSupportedTypes(?string $format)" instead
 */
interface CacheableSupportsMethodInterface
{
    public function hasCacheableSupportsMethod(): bool;
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Serializer\Normalizer;

trait ObjectToPopulateTrait
{
    /**
     * Extract the `object_to_populate` field from the context if it exists
     * and is an instance of the provided $class.
     *
     * @param string      $class The class the object should be
     * @param string|null $key   They in which to look for the object to populate.
     *                           Keeps backwards compatibility with `AbstractNormalizer`.
     */
    protected function extractObjectToPopulate(string $class, array $context, ?string $key = null): ?object
    {
        $key ??= AbstractNormalizer::OBJECT_TO_POPULATE;
        if (isset($context[$key]) && \is_object($context[$key]) && $context[$key] instanceof $class) {
            return $context[$key];
        }
        return null;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Serializer\Normalizer;

use _ContaoManager\Symfony\Component\Form\FormInterface;
/**
 * Normalizes invalid Form instances.
 */
final class FormErrorNormalizer implements NormalizerInterface, CacheableSupportsMethodInterface
{
    public const TITLE = 'title';
    public const TYPE = 'type';
    public const CODE = 'status_code';
    public function normalize(mixed $object, ?string $format = null, array $context = []): array
    {
        $data = ['title' => $context[self::TITLE] ?? 'Validation Failed', 'type' => $context[self::TYPE] ?? 'https://symfony.com/errors/form', 'code' => $context[self::CODE] ?? null, 'errors' => $this->convertFormErrorsToArray($object)];
        if (0 !== \count($object->all())) {
            $data['children'] = $this->convertFormChildrenToArray($object);
        }
        return $data;
    }
    public function getSupportedTypes(?string $format): array
    {
        return [FormInterface::class => \false];
    }
    public function supportsNormalization(mixed $data, ?string $format = null, array $context = []): bool
    {
        return $data instanceof FormInterface && $data->isSubmitted() && !$data->isValid();
    }
    private function convertFormErrorsToArray(FormInterface $data): array
    {
        $errors = [];
        foreach ($data->getErrors() as $error) {
            $errors[] = ['message' => $error->getMessage(), 'cause' => $error->getCause()];
        }
        return $errors;
    }
    private function convertFormChildrenToArray(FormInterface $data): array
    {
        $children = [];
        foreach ($data->all() as $child) {
            $childData = ['errors' => $this->convertFormErrorsToArray($child)];
            if ($child->all()) {
                $childData['children'] = $this->convertFormChildrenToArray($child);
            }
            $children[$child->getName()] = $childData;
        }
        return $children;
    }
    /**
     * @deprecated since Symfony 6.3, use "getSupportedTypes()" instead
     */
    public function hasCacheableSupportsMethod(): bool
    {
        trigger_deprecation('symfony/serializer', '6.3', 'The "%s()" method is deprecated, use "getSupportedTypes()" instead.', __METHOD__);
        return \true;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Serializer\Normalizer;

/**
 * Adds the support of an extra $context parameter for the supportsDenormalization method.
 *
 * @author Kévin Dunglas <dunglas@gmail.com>
 *
 * @deprecated since symfony/serializer 6.1, use DenormalizerInterface instead
 */
interface ContextAwareDenormalizerInterface extends DenormalizerInterface
{
    /**
     * @param array $context options that denormalizers have access to
     */
    public function supportsDenormalization(mixed $data, string $type, ?string $format = null, array $context = []): bool;
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Serializer\Normalizer;

use _ContaoManager\Symfony\Component\PropertyInfo\Type;
use _ContaoManager\Symfony\Component\Serializer\Exception\BadMethodCallException;
use _ContaoManager\Symfony\Component\Serializer\Exception\InvalidArgumentException;
use _ContaoManager\Symfony\Component\Serializer\Exception\NotNormalizableValueException;
/**
 * Denormalizes arrays of objects.
 *
 * @author Alexander M. Turek <me@derrabus.de>
 *
 * @final
 */
class ArrayDenormalizer implements ContextAwareDenormalizerInterface, DenormalizerAwareInterface, CacheableSupportsMethodInterface
{
    use DenormalizerAwareTrait;
    public function setDenormalizer(DenormalizerInterface $denormalizer): void
    {
        if (!method_exists($denormalizer, 'getSupportedTypes')) {
            trigger_deprecation('symfony/serializer', '6.3', 'Not implementing the "DenormalizerInterface::getSupportedTypes()" in "%s" is deprecated.', get_debug_type($denormalizer));
        }
        $this->denormalizer = $denormalizer;
    }
    public function getSupportedTypes(?string $format): array
    {
        return ['object' => null, '*' => \false];
    }
    /**
     * @throws NotNormalizableValueException
     */
    public function denormalize(mixed $data, string $type, ?string $format = null, array $context = []): array
    {
        if (null === $this->denormalizer) {
            throw new BadMethodCallException('Please set a denormalizer before calling denormalize()!');
        }
        if (!\is_array($data)) {
            throw NotNormalizableValueException::createForUnexpectedDataType(\sprintf('Data expected to be "%s", "%s" given.', $type, get_debug_type($data)), $data, [Type::BUILTIN_TYPE_ARRAY], $context['deserialization_path'] ?? null);
        }
        if (!str_ends_with($type, '[]')) {
            throw new InvalidArgumentException('Unsupported class: ' . $type);
        }
        $type = substr($type, 0, -2);
        $builtinTypes = array_map(static function (Type $keyType) {
            return $keyType->getBuiltinType();
        }, \is_array($keyType = $context['key_type'] ?? []) ? $keyType : [$keyType]);
        $valueType = $context['value_type'] ?? null;
        if ($valueType instanceof Type && $valueType->isCollection()) {
            if ($collectionKeyTypes = $valueType->getCollectionKeyTypes()) {
                $context['key_type'] = \count($collectionKeyTypes) > 1 ? $collectionKeyTypes : $collectionKeyTypes[0];
            }
            if ($collectionValueTypes = $valueType->getCollectionValueTypes()) {
                $context['value_type'] = $collectionValueTypes[0];
            }
        }
        foreach ($data as $key => $value) {
            $subContext = $context;
            $subContext['deserialization_path'] = $context['deserialization_path'] ?? \false ? \sprintf('%s[%s]', $context['deserialization_path'], $key) : "[{$key}]";
            $this->validateKeyType($builtinTypes, $key, $subContext['deserialization_path']);
            $data[$key] = $this->denormalizer->denormalize($value, $type, $format, $subContext);
        }
        return $data;
    }
    public function supportsDenormalization(mixed $data, string $type, ?string $format = null, array $context = []): bool
    {
        if (null === $this->denormalizer) {
            throw new BadMethodCallException(\sprintf('The nested denormalizer needs to be set to allow "%s()" to be used.', __METHOD__));
        }
        return str_ends_with($type, '[]') && $this->denormalizer->supportsDenormalization($data, substr($type, 0, -2), $format, $context);
    }
    /**
     * @deprecated since Symfony 6.3, use "getSupportedTypes()" instead
     */
    public function hasCacheableSupportsMethod(): bool
    {
        trigger_deprecation('symfony/serializer', '6.3', 'The "%s()" method is deprecated, use "getSupportedTypes()" instead.', __METHOD__);
        return $this->denormalizer instanceof CacheableSupportsMethodInterface && $this->denormalizer->hasCacheableSupportsMethod();
    }
    /**
     * @param mixed $key
     */
    private function validateKeyType(array $builtinTypes, $key, string $path): void
    {
        if (!$builtinTypes) {
            return;
        }
        foreach ($builtinTypes as $builtinType) {
            if (('is_' . $builtinType)($key)) {
                return;
            }
        }
        throw NotNormalizableValueException::createForUnexpectedDataType(\sprintf('The type of the key "%s" must be "%s" ("%s" given).', $key, implode('", "', $builtinTypes), get_debug_type($key)), $key, $builtinTypes, $path, \true);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Serializer\Normalizer;

use _ContaoManager\Symfony\Component\PropertyAccess\Exception\InvalidArgumentException as PropertyAccessInvalidArgumentException;
use _ContaoManager\Symfony\Component\PropertyAccess\Exception\NoSuchIndexException;
use _ContaoManager\Symfony\Component\PropertyAccess\Exception\NoSuchPropertyException;
use _ContaoManager\Symfony\Component\PropertyAccess\Exception\UninitializedPropertyException;
use _ContaoManager\Symfony\Component\PropertyAccess\PropertyAccess;
use _ContaoManager\Symfony\Component\PropertyInfo\PropertyTypeExtractorInterface;
use _ContaoManager\Symfony\Component\PropertyInfo\Type;
use _ContaoManager\Symfony\Component\Serializer\Encoder\CsvEncoder;
use _ContaoManager\Symfony\Component\Serializer\Encoder\JsonEncoder;
use _ContaoManager\Symfony\Component\Serializer\Encoder\XmlEncoder;
use _ContaoManager\Symfony\Component\Serializer\Exception\ExtraAttributesException;
use _ContaoManager\Symfony\Component\Serializer\Exception\InvalidArgumentException;
use _ContaoManager\Symfony\Component\Serializer\Exception\LogicException;
use _ContaoManager\Symfony\Component\Serializer\Exception\MissingConstructorArgumentsException;
use _ContaoManager\Symfony\Component\Serializer\Exception\NotNormalizableValueException;
use _ContaoManager\Symfony\Component\Serializer\Mapping\AttributeMetadata;
use _ContaoManager\Symfony\Component\Serializer\Mapping\AttributeMetadataInterface;
use _ContaoManager\Symfony\Component\Serializer\Mapping\ClassDiscriminatorFromClassMetadata;
use _ContaoManager\Symfony\Component\Serializer\Mapping\ClassDiscriminatorResolverInterface;
use _ContaoManager\Symfony\Component\Serializer\Mapping\ClassMetadataInterface;
use _ContaoManager\Symfony\Component\Serializer\Mapping\Factory\ClassMetadataFactoryInterface;
use _ContaoManager\Symfony\Component\Serializer\NameConverter\NameConverterInterface;
/**
 * Base class for a normalizer dealing with objects.
 *
 * @author Kévin Dunglas <dunglas@gmail.com>
 */
abstract class AbstractObjectNormalizer extends AbstractNormalizer
{
    /**
     * Set to true to respect the max depth metadata on fields.
     */
    public const ENABLE_MAX_DEPTH = 'enable_max_depth';
    /**
     * How to track the current depth in the context.
     */
    public const DEPTH_KEY_PATTERN = 'depth_%s::%s';
    /**
     * While denormalizing, we can verify that types match.
     *
     * You can disable this by setting this flag to true.
     */
    public const DISABLE_TYPE_ENFORCEMENT = 'disable_type_enforcement';
    /**
     * Flag to control whether fields with the value `null` should be output
     * when normalizing or omitted.
     */
    public const SKIP_NULL_VALUES = 'skip_null_values';
    /**
     * Flag to control whether uninitialized PHP>=7.4 typed class properties
     * should be excluded when normalizing.
     */
    public const SKIP_UNINITIALIZED_VALUES = 'skip_uninitialized_values';
    /**
     * Callback to allow to set a value for an attribute when the max depth has
     * been reached.
     *
     * If no callback is given, the attribute is skipped. If a callable is
     * given, its return value is used (even if null).
     *
     * The arguments are:
     *
     * - mixed  $attributeValue value of this field
     * - object $object         the whole object being normalized
     * - string $attributeName  name of the attribute being normalized
     * - string $format         the requested format
     * - array  $context        the serialization context
     */
    public const MAX_DEPTH_HANDLER = 'max_depth_handler';
    /**
     * Specify which context key are not relevant to determine which attributes
     * of an object to (de)normalize.
     */
    public const EXCLUDE_FROM_CACHE_KEY = 'exclude_from_cache_key';
    /**
     * Flag to tell the denormalizer to also populate existing objects on
     * attributes of the main object.
     *
     * Setting this to true is only useful if you also specify the root object
     * in OBJECT_TO_POPULATE.
     */
    public const DEEP_OBJECT_TO_POPULATE = 'deep_object_to_populate';
    /**
     * Flag to control whether an empty object should be kept as an object (in
     * JSON: {}) or converted to a list (in JSON: []).
     */
    public const PRESERVE_EMPTY_OBJECTS = 'preserve_empty_objects';
    private array $typesCache = [];
    private array $attributesCache = [];
    private readonly \Closure $objectClassResolver;
    /**
     * @var ClassDiscriminatorResolverInterface|null
     */
    protected $classDiscriminatorResolver;
    public function __construct(?ClassMetadataFactoryInterface $classMetadataFactory = null, ?NameConverterInterface $nameConverter = null, private ?PropertyTypeExtractorInterface $propertyTypeExtractor = null, ?ClassDiscriminatorResolverInterface $classDiscriminatorResolver = null, ?callable $objectClassResolver = null, array $defaultContext = [])
    {
        parent::__construct($classMetadataFactory, $nameConverter, $defaultContext);
        if (isset($this->defaultContext[self::MAX_DEPTH_HANDLER]) && !\is_callable($this->defaultContext[self::MAX_DEPTH_HANDLER])) {
            throw new InvalidArgumentException(\sprintf('The "%s" given in the default context is not callable.', self::MAX_DEPTH_HANDLER));
        }
        $this->defaultContext[self::EXCLUDE_FROM_CACHE_KEY] = array_merge($this->defaultContext[self::EXCLUDE_FROM_CACHE_KEY] ?? [], [self::CIRCULAR_REFERENCE_LIMIT_COUNTERS]);
        if ($classMetadataFactory) {
            $classDiscriminatorResolver ??= new ClassDiscriminatorFromClassMetadata($classMetadataFactory);
        }
        $this->classDiscriminatorResolver = $classDiscriminatorResolver;
        $this->objectClassResolver = ($objectClassResolver ?? 'get_class')(...);
    }
    /**
     * @param array $context
     *
     * @return bool
     */
    public function supportsNormalization(mixed $data, ?string $format = null)
    {
        return \is_object($data) && !$data instanceof \Traversable;
    }
    /**
     * @return array|string|int|float|bool|\ArrayObject|null
     */
    public function normalize(mixed $object, ?string $format = null, array $context = [])
    {
        $context['_read_attributes'] = \true;
        if (!isset($context['cache_key'])) {
            $context['cache_key'] = $this->getCacheKey($format, $context);
        }
        $this->validateCallbackContext($context);
        if ($this->isCircularReference($object, $context)) {
            return $this->handleCircularReference($object, $format, $context);
        }
        $data = [];
        $stack = [];
        $attributes = $this->getAttributes($object, $format, $context);
        $class = ($this->objectClassResolver)($object);
        $classMetadata = $this->classMetadataFactory?->getMetadataFor($class);
        $attributesMetadata = $this->classMetadataFactory?->getMetadataFor($class)->getAttributesMetadata();
        if (isset($context[self::MAX_DEPTH_HANDLER])) {
            $maxDepthHandler = $context[self::MAX_DEPTH_HANDLER];
            if (!\is_callable($maxDepthHandler)) {
                throw new InvalidArgumentException(\sprintf('The "%s" given in the context is not callable.', self::MAX_DEPTH_HANDLER));
            }
        } else {
            $maxDepthHandler = null;
        }
        foreach ($attributes as $attribute) {
            $maxDepthReached = \false;
            if (null !== $attributesMetadata && ($maxDepthReached = $this->isMaxDepthReached($attributesMetadata, $class, $attribute, $context)) && !$maxDepthHandler) {
                continue;
            }
            $attributeContext = $this->getAttributeNormalizationContext($object, $attribute, $context);
            try {
                $attributeValue = $attribute === $this->classDiscriminatorResolver?->getMappingForMappedObject($object)?->getTypeProperty() ? $this->classDiscriminatorResolver?->getTypeForMappedObject($object) : $this->getAttributeValue($object, $attribute, $format, $attributeContext);
            } catch (UninitializedPropertyException|\Error $e) {
                if (($context[self::SKIP_UNINITIALIZED_VALUES] ?? $this->defaultContext[self::SKIP_UNINITIALIZED_VALUES] ?? \true) && $this->isUninitializedValueError($e)) {
                    continue;
                }
                throw $e;
            }
            if ($maxDepthReached) {
                $attributeValue = $maxDepthHandler($attributeValue, $object, $attribute, $format, $attributeContext);
            }
            $stack[$attribute] = $this->applyCallbacks($attributeValue, $object, $attribute, $format, $attributeContext);
        }
        foreach ($stack as $attribute => $attributeValue) {
            $attributeContext = $this->getAttributeNormalizationContext($object, $attribute, $context);
            if (!$this->serializer instanceof NormalizerInterface) {
                if (null === $attributeValue || \is_scalar($attributeValue)) {
                    $data = $this->updateData($data, $attribute, $attributeValue, $class, $format, $attributeContext, $attributesMetadata, $classMetadata);
                    continue;
                }
                throw new LogicException(\sprintf('Cannot normalize attribute "%s" because the injected serializer is not a normalizer.', $attribute));
            }
            $childContext = $this->createChildContext($attributeContext, $attribute, $format);
            $data = $this->updateData($data, $attribute, $this->serializer->normalize($attributeValue, $format, $childContext), $class, $format, $attributeContext, $attributesMetadata, $classMetadata);
        }
        $preserveEmptyObjects = $context[self::PRESERVE_EMPTY_OBJECTS] ?? $this->defaultContext[self::PRESERVE_EMPTY_OBJECTS] ?? \false;
        if ($preserveEmptyObjects && !$data) {
            return new \ArrayObject();
        }
        return $data;
    }
    /**
     * @return object
     */
    protected function instantiateObject(array &$data, string $class, array &$context, \ReflectionClass $reflectionClass, array|bool $allowedAttributes, ?string $format = null)
    {
        if ($class !== $mappedClass = $this->getMappedClass($data, $class, $context)) {
            return $this->instantiateObject($data, $mappedClass, $context, new \ReflectionClass($mappedClass), $allowedAttributes, $format);
        }
        return parent::instantiateObject($data, $class, $context, $reflectionClass, $allowedAttributes, $format);
    }
    /**
     * Gets and caches attributes for the given object, format and context.
     *
     * @return string[]
     */
    protected function getAttributes(object $object, ?string $format, array $context): array
    {
        $class = ($this->objectClassResolver)($object);
        $key = $class . '-' . $context['cache_key'];
        if (isset($this->attributesCache[$key])) {
            return $this->attributesCache[$key];
        }
        $allowedAttributes = $this->getAllowedAttributes($object, $context, \true);
        if (\false !== $allowedAttributes) {
            if ($context['cache_key']) {
                $this->attributesCache[$key] = $allowedAttributes;
            }
            return $allowedAttributes;
        }
        $attributes = $this->extractAttributes($object, $format, $context);
        if ($mapping = $this->classDiscriminatorResolver?->getMappingForMappedObject($object)) {
            array_unshift($attributes, $mapping->getTypeProperty());
        }
        if ($context['cache_key'] && \stdClass::class !== $class) {
            $this->attributesCache[$key] = $attributes;
        }
        return $attributes;
    }
    /**
     * Extracts attributes to normalize from the class of the given object, format and context.
     *
     * @return string[]
     */
    abstract protected function extractAttributes(object $object, ?string $format = null, array $context = []);
    /**
     * Gets the attribute value.
     *
     * @return mixed
     */
    abstract protected function getAttributeValue(object $object, string $attribute, ?string $format = null, array $context = []);
    /**
     * @param array $context
     *
     * @return bool
     */
    public function supportsDenormalization(mixed $data, string $type, ?string $format = null)
    {
        return class_exists($type) || interface_exists($type, \false) && null !== $this->classDiscriminatorResolver?->getMappingForClass($type);
    }
    /**
     * @return mixed
     */
    public function denormalize(mixed $data, string $type, ?string $format = null, array $context = [])
    {
        $context['_read_attributes'] = \false;
        if (!isset($context['cache_key'])) {
            $context['cache_key'] = $this->getCacheKey($format, $context);
        }
        $this->validateCallbackContext($context);
        if (null === $data && isset($context['value_type']) && $context['value_type'] instanceof Type && $context['value_type']->isNullable()) {
            return null;
        }
        if (XmlEncoder::FORMAT === $format && !\is_array($data)) {
            $data = ['#' => $data];
        }
        $allowedAttributes = $this->getAllowedAttributes($type, $context, \true);
        $normalizedData = $this->prepareForDenormalization($data);
        $extraAttributes = [];
        $mappedClass = $this->getMappedClass($normalizedData, $type, $context);
        $nestedAttributes = $this->getNestedAttributes($mappedClass);
        $nestedData = $originalNestedData = [];
        $propertyAccessor = PropertyAccess::createPropertyAccessorBuilder()->enableExceptionOnInvalidIndex()->getPropertyAccessor();
        foreach ($nestedAttributes as $property => $serializedPath) {
            try {
                $value = $propertyAccessor->getValue($normalizedData, $serializedPath);
                $convertedProperty = $this->nameConverter ? $this->nameConverter->normalize($property, $mappedClass, $format, $context) : $property;
                $nestedData[$convertedProperty] = $value;
                $originalNestedData[$property] = $value;
                $normalizedData = $this->removeNestedValue($serializedPath->getElements(), $normalizedData);
            } catch (NoSuchIndexException) {
            }
        }
        $normalizedData = $nestedData + $normalizedData;
        $object = $this->instantiateObject($normalizedData, $mappedClass, $context, new \ReflectionClass($mappedClass), $allowedAttributes, $format);
        $resolvedClass = ($this->objectClassResolver)($object);
        foreach ($normalizedData as $attribute => $value) {
            if ($this->nameConverter) {
                $notConverted = $attribute;
                $attribute = $this->nameConverter->denormalize($attribute, $resolvedClass, $format, $context);
                if (isset($nestedData[$notConverted]) && !isset($originalNestedData[$attribute])) {
                    throw new LogicException(\sprintf('Duplicate values for key "%s" found. One value is set via the SerializedPath attribute: "%s", the other one is set via the SerializedName attribute: "%s".', $notConverted, implode('->', $nestedAttributes[$notConverted]->getElements()), $attribute));
                }
                if ($attribute === $notConverted && !($context[self::ALLOW_EXTRA_ATTRIBUTES] ?? $this->defaultContext[self::ALLOW_EXTRA_ATTRIBUTES]) && (\false === $allowedAttributes || \in_array($attribute, $allowedAttributes, \true)) && $this->nameConverter->normalize($attribute, $resolvedClass, $format, $context) !== $attribute) {
                    // Input was in wrong format (e.g., camelCase when snake_case expected)
                    $extraAttributes[] = $notConverted;
                    continue;
                }
            }
            $attributeContext = $this->getAttributeDenormalizationContext($resolvedClass, $attribute, $context);
            if (\false !== $allowedAttributes && !\in_array($attribute, $allowedAttributes) || !$this->isAllowedAttribute($resolvedClass, $attribute, $format, $context)) {
                if (!($context[self::ALLOW_EXTRA_ATTRIBUTES] ?? $this->defaultContext[self::ALLOW_EXTRA_ATTRIBUTES])) {
                    $extraAttributes[] = $attribute;
                }
                continue;
            }
            if ($attributeContext[self::DEEP_OBJECT_TO_POPULATE] ?? $this->defaultContext[self::DEEP_OBJECT_TO_POPULATE] ?? \false) {
                $discriminatorMapping = $this->classDiscriminatorResolver?->getMappingForMappedObject($object);
                try {
                    $attributeContext[self::OBJECT_TO_POPULATE] = $attribute === $discriminatorMapping?->getTypeProperty() ? $discriminatorMapping : $this->getAttributeValue($object, $attribute, $format, $attributeContext);
                } catch (NoSuchPropertyException) {
                } catch (UninitializedPropertyException|\Error $e) {
                    if (!(($context[self::SKIP_UNINITIALIZED_VALUES] ?? $this->defaultContext[self::SKIP_UNINITIALIZED_VALUES] ?? \true) && $this->isUninitializedValueError($e))) {
                        throw $e;
                    }
                }
            }
            $types = $this->getTypes($resolvedClass, $attribute);
            if (null !== $types) {
                try {
                    $value = $this->validateAndDenormalize($types, $resolvedClass, $attribute, $value, $format, $attributeContext);
                } catch (NotNormalizableValueException $exception) {
                    if (isset($context['not_normalizable_value_exceptions'])) {
                        $context['not_normalizable_value_exceptions'][] = $exception;
                        continue;
                    }
                    throw $exception;
                }
            }
            $value = $this->applyCallbacks($value, $resolvedClass, $attribute, $format, $attributeContext);
            try {
                $this->setAttributeValue($object, $attribute, $value, $format, $attributeContext);
            } catch (PropertyAccessInvalidArgumentException $e) {
                $exception = NotNormalizableValueException::createForUnexpectedDataType(\sprintf('Failed to denormalize attribute "%s" value for class "%s": ' . $e->getMessage(), $attribute, $type), $data, ['unknown'], $attributeContext['deserialization_path'] ?? null, \false, $e->getCode(), $e);
                if (isset($context['not_normalizable_value_exceptions'])) {
                    $context['not_normalizable_value_exceptions'][] = $exception;
                    continue;
                }
                throw $exception;
            }
        }
        if ($extraAttributes) {
            throw new ExtraAttributesException($extraAttributes);
        }
        return $object;
    }
    /**
     * @return void
     */
    abstract protected function setAttributeValue(object $object, string $attribute, mixed $value, ?string $format = null, array $context = []);
    /**
     * Validates the submitted data and denormalizes it.
     *
     * @param Type[] $types
     *
     * @throws NotNormalizableValueException
     * @throws ExtraAttributesException
     * @throws MissingConstructorArgumentsException
     * @throws LogicException
     */
    private function validateAndDenormalize(array $types, string $currentClass, string $attribute, mixed $data, ?string $format, array $context): mixed
    {
        $expectedTypes = [];
        $isUnionType = \count($types) > 1;
        $e = null;
        $extraAttributesException = null;
        $missingConstructorArgumentsException = null;
        $isNullable = \false;
        foreach ($types as $type) {
            if (null === $data && $type->isNullable()) {
                return null;
            }
            $collectionValueType = $type->isCollection() ? $type->getCollectionValueTypes()[0] ?? null : null;
            // Fix a collection that contains the only one element
            // This is special to xml format only
            if ('xml' === $format && null !== $collectionValueType && (!\is_array($data) || !\is_int(key($data)))) {
                $data = [$data];
            }
            // This try-catch should cover all NotNormalizableValueException (and all return branches after the first
            // exception) so we could try denormalizing all types of an union type. If the target type is not an union
            // type, we will just re-throw the caught exception.
            // In the case of no denormalization succeeds with an union type, it will fall back to the default exception
            // with the acceptable types list.
            try {
                // In XML and CSV all basic datatypes are represented as strings, it is e.g. not possible to determine,
                // if a value is meant to be a string, float, int or a boolean value from the serialized representation.
                // That's why we have to transform the values, if one of these non-string basic datatypes is expected.
                $builtinType = $type->getBuiltinType();
                if (\is_string($data) && (XmlEncoder::FORMAT === $format || CsvEncoder::FORMAT === $format)) {
                    if ('' === $data) {
                        if (Type::BUILTIN_TYPE_ARRAY === $builtinType) {
                            return [];
                        }
                        if (Type::BUILTIN_TYPE_STRING === $builtinType) {
                            return '';
                        }
                        // Don't return null yet because Object-types that come first may accept empty-string too
                        $isNullable = $isNullable ?: $type->isNullable();
                    }
                    switch ($builtinType) {
                        case Type::BUILTIN_TYPE_BOOL:
                            // according to https://www.w3.org/TR/xmlschema-2/#boolean, valid representations are "false", "true", "0" and "1"
                            if ('false' === $data || '0' === $data) {
                                $data = \false;
                            } elseif ('true' === $data || '1' === $data) {
                                $data = \true;
                            } else {
                                throw NotNormalizableValueException::createForUnexpectedDataType(\sprintf('The type of the "%s" attribute for class "%s" must be bool ("%s" given).', $attribute, $currentClass, $data), $data, [Type::BUILTIN_TYPE_BOOL], $context['deserialization_path'] ?? null);
                            }
                            break;
                        case Type::BUILTIN_TYPE_INT:
                            if (ctype_digit(isset($data[0]) && '-' === $data[0] ? substr($data, 1) : $data)) {
                                $data = (int) $data;
                            } else {
                                throw NotNormalizableValueException::createForUnexpectedDataType(\sprintf('The type of the "%s" attribute for class "%s" must be int ("%s" given).', $attribute, $currentClass, $data), $data, [Type::BUILTIN_TYPE_INT], $context['deserialization_path'] ?? null);
                            }
                            break;
                        case Type::BUILTIN_TYPE_FLOAT:
                            if (is_numeric($data)) {
                                return (float) $data;
                            }
                            return match ($data) {
                                'NaN' => \NAN,
                                'INF' => \INF,
                                '-INF' => -\INF,
                                default => throw NotNormalizableValueException::createForUnexpectedDataType(\sprintf('The type of the "%s" attribute for class "%s" must be float ("%s" given).', $attribute, $currentClass, $data), $data, [Type::BUILTIN_TYPE_FLOAT], $context['deserialization_path'] ?? null),
                            };
                    }
                }
                if (null !== $collectionValueType && Type::BUILTIN_TYPE_OBJECT === $collectionValueType->getBuiltinType()) {
                    $builtinType = Type::BUILTIN_TYPE_OBJECT;
                    $class = $collectionValueType->getClassName() . '[]';
                    if ($collectionKeyType = $type->getCollectionKeyTypes()) {
                        $context['key_type'] = \count($collectionKeyType) > 1 ? $collectionKeyType : $collectionKeyType[0];
                    }
                    $context['value_type'] = $collectionValueType;
                } elseif ($type->isCollection() && ($collectionValueType = $type->getCollectionValueTypes()) && Type::BUILTIN_TYPE_ARRAY === $collectionValueType[0]->getBuiltinType()) {
                    // get inner type for any nested array
                    [$innerType] = $collectionValueType;
                    // note that it will break for any other builtinType
                    $dimensions = '[]';
                    while ($innerType->getCollectionValueTypes() && Type::BUILTIN_TYPE_ARRAY === $innerType->getBuiltinType()) {
                        $dimensions .= '[]';
                        [$innerType] = $innerType->getCollectionValueTypes();
                    }
                    if (null !== $innerType->getClassName()) {
                        // the builtinType is the inner one and the class is the class followed by []...[]
                        $builtinType = $innerType->getBuiltinType();
                        $class = $innerType->getClassName() . $dimensions;
                        if ($collectionKeyType = $type->getCollectionKeyTypes()) {
                            $context['key_type'] = \count($collectionKeyType) > 1 ? $collectionKeyType : $collectionKeyType[0];
                        }
                        $context['value_type'] = $collectionValueType[0];
                    } else {
                        // default fallback (keep it as array)
                        $builtinType = $type->getBuiltinType();
                        $class = $type->getClassName();
                    }
                } else {
                    $builtinType = $type->getBuiltinType();
                    $class = $type->getClassName();
                }
                $expectedTypes[Type::BUILTIN_TYPE_OBJECT === $builtinType && $class ? $class : $builtinType] = \true;
                if (Type::BUILTIN_TYPE_OBJECT === $builtinType && null !== $class) {
                    if (!$this->serializer instanceof DenormalizerInterface) {
                        throw new LogicException(\sprintf('Cannot denormalize attribute "%s" for class "%s" because injected serializer is not a denormalizer.', $attribute, $class));
                    }
                    $childContext = $this->createChildContext($context, $attribute, $format);
                    if ($this->serializer->supportsDenormalization($data, $class, $format, $childContext)) {
                        return $this->serializer->denormalize($data, $class, $format, $childContext);
                    }
                }
                // JSON only has a Number type corresponding to both int and float PHP types.
                // PHP's json_encode, JavaScript's JSON.stringify, Go's json.Marshal as well as most other JSON encoders convert
                // floating-point numbers like 12.0 to 12 (the decimal part is dropped when possible).
                // PHP's json_decode automatically converts Numbers without a decimal part to integers.
                // To circumvent this behavior, integers are converted to floats when denormalizing JSON based formats and when
                // a float is expected.
                if (Type::BUILTIN_TYPE_FLOAT === $builtinType && \is_int($data) && null !== $format && str_contains($format, JsonEncoder::FORMAT)) {
                    return (float) $data;
                }
                if (Type::BUILTIN_TYPE_FALSE === $builtinType && \false === $data || Type::BUILTIN_TYPE_TRUE === $builtinType && \true === $data) {
                    return $data;
                }
                switch ($builtinType) {
                    case Type::BUILTIN_TYPE_ARRAY:
                    case Type::BUILTIN_TYPE_BOOL:
                    case Type::BUILTIN_TYPE_CALLABLE:
                    case Type::BUILTIN_TYPE_FLOAT:
                    case Type::BUILTIN_TYPE_INT:
                    case Type::BUILTIN_TYPE_ITERABLE:
                    case Type::BUILTIN_TYPE_NULL:
                    case Type::BUILTIN_TYPE_OBJECT:
                    case Type::BUILTIN_TYPE_RESOURCE:
                    case Type::BUILTIN_TYPE_STRING:
                        if (('is_' . $builtinType)($data)) {
                            return $data;
                        }
                        break;
                }
            } catch (NotNormalizableValueException|InvalidArgumentException $e) {
                if (!$isUnionType && !$isNullable) {
                    throw $e;
                }
                $expectedTypes[Type::BUILTIN_TYPE_OBJECT === $builtinType && $class ? $class : $builtinType] = \true;
            } catch (ExtraAttributesException $e) {
                if (!$isUnionType && !$isNullable) {
                    throw $e;
                }
                $extraAttributesException ??= $e;
            } catch (MissingConstructorArgumentsException $e) {
                if (!$isUnionType && !$isNullable) {
                    throw $e;
                }
                $missingConstructorArgumentsException ??= $e;
            }
        }
        if ($isNullable) {
            return null;
        }
        if ($extraAttributesException) {
            throw $extraAttributesException;
        }
        if ($missingConstructorArgumentsException) {
            throw $missingConstructorArgumentsException;
        }
        if (!$isUnionType && $e) {
            throw $e;
        }
        if ($context[self::DISABLE_TYPE_ENFORCEMENT] ?? $this->defaultContext[self::DISABLE_TYPE_ENFORCEMENT] ?? \false) {
            return $data;
        }
        throw NotNormalizableValueException::createForUnexpectedDataType(\sprintf('The type of the "%s" attribute for class "%s" must be one of "%s" ("%s" given).', $attribute, $currentClass, implode('", "', array_keys($expectedTypes)), get_debug_type($data)), $data, array_keys($expectedTypes), $context['deserialization_path'] ?? $attribute);
    }
    /**
     * @internal
     */
    protected function denormalizeParameter(\ReflectionClass $class, \ReflectionParameter $parameter, string $parameterName, mixed $parameterData, array $context, ?string $format = null): mixed
    {
        if ($parameter->isVariadic() || null === $this->propertyTypeExtractor || null === $types = $this->getTypes($class->getName(), $parameterName)) {
            return parent::denormalizeParameter($class, $parameter, $parameterName, $parameterData, $context, $format);
        }
        $parameterData = $this->validateAndDenormalize($types, $class->getName(), $parameterName, $parameterData, $format, $context);
        return $this->applyCallbacks($parameterData, $class->getName(), $parameterName, $format, $context);
    }
    /**
     * @return Type[]|null
     */
    private function getTypes(string $currentClass, string $attribute): ?array
    {
        if (null === $this->propertyTypeExtractor) {
            return null;
        }
        $key = $currentClass . '::' . $attribute;
        if (isset($this->typesCache[$key])) {
            return \false === $this->typesCache[$key] ? null : $this->typesCache[$key];
        }
        if (null !== $types = $this->propertyTypeExtractor->getTypes($currentClass, $attribute)) {
            return $this->typesCache[$key] = $types;
        }
        if ($discriminatorMapping = $this->classDiscriminatorResolver?->getMappingForClass($currentClass)) {
            if ($discriminatorMapping->getTypeProperty() === $attribute) {
                return $this->typesCache[$key] = [new Type(Type::BUILTIN_TYPE_STRING)];
            }
            foreach ($discriminatorMapping->getTypesMapping() as $mappedClass) {
                if (null !== $types = $this->propertyTypeExtractor->getTypes($mappedClass, $attribute)) {
                    return $this->typesCache[$key] = $types;
                }
            }
        }
        $this->typesCache[$key] = \false;
        return null;
    }
    /**
     * Sets an attribute and apply the name converter if necessary.
     */
    private function updateData(array $data, string $attribute, mixed $attributeValue, string $class, ?string $format, array $context, ?array $attributesMetadata, ?ClassMetadataInterface $classMetadata): array
    {
        if (null === $attributeValue && ($context[self::SKIP_NULL_VALUES] ?? $this->defaultContext[self::SKIP_NULL_VALUES] ?? \false)) {
            return $data;
        }
        if (null !== $classMetadata && null !== $serializedPath = ($attributesMetadata[$attribute] ?? null)?->getSerializedPath()) {
            $propertyAccessor = PropertyAccess::createPropertyAccessor();
            if ($propertyAccessor->isReadable($data, $serializedPath) && null !== $propertyAccessor->getValue($data, $serializedPath)) {
                throw new LogicException(\sprintf('The element you are trying to set is already populated: "%s".', (string) $serializedPath));
            }
            $propertyAccessor->setValue($data, $serializedPath, $attributeValue);
            return $data;
        }
        if ($this->nameConverter) {
            $attribute = $this->nameConverter->normalize($attribute, $class, $format, $context);
        }
        $data[$attribute] = $attributeValue;
        return $data;
    }
    /**
     * Is the max depth reached for the given attribute?
     *
     * @param AttributeMetadataInterface[] $attributesMetadata
     */
    private function isMaxDepthReached(array $attributesMetadata, string $class, string $attribute, array &$context): bool
    {
        if (!($enableMaxDepth = $context[self::ENABLE_MAX_DEPTH] ?? $this->defaultContext[self::ENABLE_MAX_DEPTH] ?? \false) || !isset($attributesMetadata[$attribute]) || null === $maxDepth = $attributesMetadata[$attribute]?->getMaxDepth()) {
            return \false;
        }
        $key = \sprintf(self::DEPTH_KEY_PATTERN, $class, $attribute);
        if (!isset($context[$key])) {
            $context[$key] = 1;
            return \false;
        }
        if ($context[$key] === $maxDepth) {
            return \true;
        }
        ++$context[$key];
        return \false;
    }
    /**
     * Overwritten to update the cache key for the child.
     *
     * We must not mix up the attribute cache between parent and children.
     *
     * @internal
     */
    protected function createChildContext(array $parentContext, string $attribute, ?string $format): array
    {
        $context = parent::createChildContext($parentContext, $attribute, $format);
        if ($context['cache_key'] ?? \false) {
            $context['cache_key'] .= '-' . $attribute;
        } elseif (\false !== ($context['cache_key'] ?? null)) {
            $context['cache_key'] = $this->getCacheKey($format, $context);
        }
        return $context;
    }
    protected function getAllowedAttributes(string|object $classOrObject, array $context, bool $attributesAsString = \false)
    {
        if (\false === $allowedAttributes = parent::getAllowedAttributes($classOrObject, $context, $attributesAsString)) {
            return \false;
        }
        if (null !== $this->classDiscriminatorResolver) {
            $class = \is_object($classOrObject) ? $classOrObject::class : $classOrObject;
            if (null !== $discriminatorMapping = $this->classDiscriminatorResolver->getMappingForMappedObject($classOrObject)) {
                $allowedAttributes[] = $attributesAsString ? $discriminatorMapping->getTypeProperty() : new AttributeMetadata($discriminatorMapping->getTypeProperty());
            }
            if (null !== $discriminatorMapping = $this->classDiscriminatorResolver->getMappingForClass($class)) {
                $attributes = [];
                foreach ($discriminatorMapping->getTypesMapping() as $mappedClass) {
                    $attributes[] = parent::getAllowedAttributes($mappedClass, $context, $attributesAsString);
                }
                $allowedAttributes = array_merge($allowedAttributes, ...$attributes);
            }
        }
        return $allowedAttributes;
    }
    /**
     * Builds the cache key for the attributes cache.
     *
     * The key must be different for every option in the context that could change which attributes should be handled.
     */
    private function getCacheKey(?string $format, array $context): bool|string
    {
        foreach ($context[self::EXCLUDE_FROM_CACHE_KEY] ?? $this->defaultContext[self::EXCLUDE_FROM_CACHE_KEY] as $key) {
            unset($context[$key]);
        }
        unset($context[self::EXCLUDE_FROM_CACHE_KEY]);
        unset($context[self::OBJECT_TO_POPULATE]);
        unset($context['cache_key']);
        // avoid artificially different keys
        try {
            return hash('xxh128', $format . serialize(['context' => $context, 'ignored' => $context[self::IGNORED_ATTRIBUTES] ?? $this->defaultContext[self::IGNORED_ATTRIBUTES]]));
        } catch (\Exception) {
            // The context cannot be serialized, skip the cache
            return \false;
        }
    }
    /**
     * This error may occur when specific object normalizer implementation gets attribute value
     * by accessing a public uninitialized property or by calling a method accessing such property.
     */
    private function isUninitializedValueError(\Error|UninitializedPropertyException $e): bool
    {
        return $e instanceof UninitializedPropertyException || str_starts_with($e->getMessage(), 'Typed property') && str_ends_with($e->getMessage(), 'must not be accessed before initialization');
    }
    /**
     * Returns all attributes with a SerializedPath attribute and the respective path.
     */
    private function getNestedAttributes(string $class): array
    {
        if (!$this->classMetadataFactory?->hasMetadataFor($class)) {
            return [];
        }
        $properties = [];
        $serializedPaths = [];
        $classMetadata = $this->classMetadataFactory->getMetadataFor($class);
        foreach ($classMetadata->getAttributesMetadata() as $name => $metadata) {
            if (!$serializedPath = $metadata->getSerializedPath()) {
                continue;
            }
            $pathIdentifier = implode(',', $serializedPath->getElements());
            if (isset($serializedPaths[$pathIdentifier])) {
                throw new LogicException(\sprintf('Duplicate serialized path: "%s" used for properties "%s" and "%s".', $pathIdentifier, $serializedPaths[$pathIdentifier], $name));
            }
            $serializedPaths[$pathIdentifier] = $name;
            $properties[$name] = $serializedPath;
        }
        return $properties;
    }
    private function removeNestedValue(array $path, array $data): array
    {
        $element = array_shift($path);
        if (!$path || !$data[$element] || !$data[$element] = $this->removeNestedValue($path, $data[$element])) {
            unset($data[$element]);
        }
        return $data;
    }
    /**
     * @return class-string
     */
    private function getMappedClass(array $data, string $class, array $context): string
    {
        if (null !== $object = $this->extractObjectToPopulate($class, $context, self::OBJECT_TO_POPULATE)) {
            return $object::class;
        }
        if (!$mapping = $this->classDiscriminatorResolver?->getMappingForClass($class)) {
            return $class;
        }
        if (null === $type = $data[$mapping->getTypeProperty()] ?? null) {
            throw NotNormalizableValueException::createForUnexpectedDataType(\sprintf('Type property "%s" not found for the abstract object "%s".', $mapping->getTypeProperty(), $class), null, ['string'], isset($context['deserialization_path']) ? $context['deserialization_path'] . '.' . $mapping->getTypeProperty() : $mapping->getTypeProperty(), \false);
        }
        if (null === $mappedClass = $mapping->getClassForType($type)) {
            throw NotNormalizableValueException::createForUnexpectedDataType(\sprintf('The type "%s" is not a valid value.', $type), $type, ['string'], isset($context['deserialization_path']) ? $context['deserialization_path'] . '.' . $mapping->getTypeProperty() : $mapping->getTypeProperty(), \true);
        }
        return $mappedClass;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Serializer\Normalizer;

use _ContaoManager\Symfony\Component\PropertyInfo\Type;
use _ContaoManager\Symfony\Component\Serializer\Exception\InvalidArgumentException;
use _ContaoManager\Symfony\Component\Serializer\Exception\NotNormalizableValueException;
/**
 * Normalizes a {@see \DateTimeZone} object to a timezone string.
 *
 * @author Jérôme Desjardins <jewome62@gmail.com>
 *
 * @final since Symfony 6.3
 */
class DateTimeZoneNormalizer implements NormalizerInterface, DenormalizerInterface, CacheableSupportsMethodInterface
{
    public function getSupportedTypes(?string $format): array
    {
        return [\DateTimeZone::class => __CLASS__ === static::class || $this->hasCacheableSupportsMethod()];
    }
    /**
     * @throws InvalidArgumentException
     */
    public function normalize(mixed $object, ?string $format = null, array $context = []): string
    {
        if (!$object instanceof \DateTimeZone) {
            throw new InvalidArgumentException('The object must be an instance of "\DateTimeZone".');
        }
        return $object->getName();
    }
    /**
     * @param array $context
     */
    public function supportsNormalization(mixed $data, ?string $format = null): bool
    {
        return $data instanceof \DateTimeZone;
    }
    /**
     * @throws NotNormalizableValueException
     */
    public function denormalize(mixed $data, string $type, ?string $format = null, array $context = []): \DateTimeZone
    {
        if ('' === $data || null === $data) {
            throw NotNormalizableValueException::createForUnexpectedDataType('The data is either an empty string or null, you should pass a string that can be parsed as a DateTimeZone.', $data, [Type::BUILTIN_TYPE_STRING], $context['deserialization_path'] ?? null, \true);
        }
        try {
            return new \DateTimeZone($data);
        } catch (\Exception $e) {
            throw NotNormalizableValueException::createForUnexpectedDataType($e->getMessage(), $data, [Type::BUILTIN_TYPE_STRING], $context['deserialization_path'] ?? null, \true, $e->getCode(), $e);
        }
    }
    /**
     * @param array $context
     */
    public function supportsDenormalization(mixed $data, string $type, ?string $format = null): bool
    {
        return \DateTimeZone::class === $type;
    }
    /**
     * @deprecated since Symfony 6.3, use "getSupportedTypes()" instead
     */
    public function hasCacheableSupportsMethod(): bool
    {
        trigger_deprecation('symfony/serializer', '6.3', 'The "%s()" method is deprecated, implement "%s::getSupportedTypes()" instead.', __METHOD__, get_debug_type($this));
        return __CLASS__ === static::class;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Serializer\Normalizer;

use _ContaoManager\Symfony\Component\PropertyAccess\PropertyAccess;
use _ContaoManager\Symfony\Component\PropertyAccess\PropertyAccessorInterface;
use _ContaoManager\Symfony\Component\Serializer\Exception\LogicException;
use _ContaoManager\Symfony\Component\Serializer\SerializerAwareInterface;
use _ContaoManager\Symfony\Component\Serializer\SerializerAwareTrait;
/**
 * @author Eduard Bulava <bulavaeduard@gmail.com>
 */
final class UnwrappingDenormalizer implements DenormalizerInterface, SerializerAwareInterface, CacheableSupportsMethodInterface
{
    use SerializerAwareTrait;
    public const UNWRAP_PATH = 'unwrap_path';
    private readonly PropertyAccessorInterface $propertyAccessor;
    public function __construct(?PropertyAccessorInterface $propertyAccessor = null)
    {
        $this->propertyAccessor = $propertyAccessor ?? PropertyAccess::createPropertyAccessor();
    }
    public function getSupportedTypes(?string $format): array
    {
        return ['*' => \false];
    }
    public function denormalize(mixed $data, string $type, ?string $format = null, array $context = []): mixed
    {
        $propertyPath = $context[self::UNWRAP_PATH];
        $context['unwrapped'] = \true;
        if ($propertyPath) {
            if (!$this->propertyAccessor->isReadable($data, $propertyPath)) {
                return null;
            }
            $data = $this->propertyAccessor->getValue($data, $propertyPath);
        }
        if (!$this->serializer instanceof DenormalizerInterface) {
            throw new LogicException('Cannot unwrap path because the injected serializer is not a denormalizer.');
        }
        return $this->serializer->denormalize($data, $type, $format, $context);
    }
    public function supportsDenormalization(mixed $data, string $type, ?string $format = null, array $context = []): bool
    {
        return \array_key_exists(self::UNWRAP_PATH, $context) && !isset($context['unwrapped']);
    }
    /**
     * @deprecated since Symfony 6.3, use "getSupportedTypes()" instead
     */
    public function hasCacheableSupportsMethod(): bool
    {
        trigger_deprecation('symfony/serializer', '6.3', 'The "%s()" method is deprecated, use "getSupportedTypes()" instead.', __METHOD__);
        return $this->serializer instanceof CacheableSupportsMethodInterface && $this->serializer->hasCacheableSupportsMethod();
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Serializer\Normalizer;

/**
 * @author Joel Wurtz <joel.wurtz@gmail.com>
 */
trait NormalizerAwareTrait
{
    /**
     * @var NormalizerInterface
     */
    protected $normalizer;
    /**
     * @return void
     */
    public function setNormalizer(NormalizerInterface $normalizer)
    {
        $this->normalizer = $normalizer;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Serializer\Normalizer;

/**
 * @author Joel Wurtz <joel.wurtz@gmail.com>
 */
interface NormalizerAwareInterface
{
    /**
     * Sets the owning Normalizer object.
     *
     * @return void
     */
    public function setNormalizer(NormalizerInterface $normalizer);
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Serializer\Normalizer;

use _ContaoManager\Symfony\Component\Serializer\Exception\InvalidArgumentException;
use _ContaoManager\Symfony\Component\Serializer\Exception\LogicException;
/**
 * A normalizer that uses an objects own JsonSerializable implementation.
 *
 * @author Fred Cox <mcfedr@gmail.com>
 *
 * @final since Symfony 6.3
 */
class JsonSerializableNormalizer extends AbstractNormalizer
{
    public function normalize(mixed $object, ?string $format = null, array $context = []): array|string|int|float|bool|\ArrayObject|null
    {
        if ($this->isCircularReference($object, $context)) {
            return $this->handleCircularReference($object, $format, $context);
        }
        if (!$object instanceof \JsonSerializable) {
            throw new InvalidArgumentException(\sprintf('The object must implement "%s".', \JsonSerializable::class));
        }
        if (!$this->serializer instanceof NormalizerInterface) {
            throw new LogicException('Cannot normalize object because injected serializer is not a normalizer.');
        }
        return $this->serializer->normalize($object->jsonSerialize(), $format, $context);
    }
    public function getSupportedTypes(?string $format): array
    {
        return [\JsonSerializable::class => __CLASS__ === static::class || $this->hasCacheableSupportsMethod()];
    }
    /**
     * @param array $context
     */
    public function supportsNormalization(mixed $data, ?string $format = null): bool
    {
        return $data instanceof \JsonSerializable;
    }
    /**
     * @param array $context
     */
    public function supportsDenormalization(mixed $data, string $type, ?string $format = null): bool
    {
        return \false;
    }
    public function denormalize(mixed $data, string $type, ?string $format = null, array $context = []): mixed
    {
        throw new LogicException(\sprintf('Cannot denormalize with "%s".', \JsonSerializable::class));
    }
    /**
     * @deprecated since Symfony 6.3, use "getSupportedTypes()" instead
     */
    public function hasCacheableSupportsMethod(): bool
    {
        trigger_deprecation('symfony/serializer', '6.3', 'The "%s()" method is deprecated, implement "%s::getSupportedTypes()" instead.', __METHOD__, get_debug_type($this));
        return __CLASS__ === static::class;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Serializer\Normalizer;

use _ContaoManager\Symfony\Component\HttpFoundation\File\File;
use _ContaoManager\Symfony\Component\Mime\MimeTypeGuesserInterface;
use _ContaoManager\Symfony\Component\Mime\MimeTypes;
use _ContaoManager\Symfony\Component\Serializer\Exception\InvalidArgumentException;
use _ContaoManager\Symfony\Component\Serializer\Exception\NotNormalizableValueException;
/**
 * Normalizes an {@see \SplFileInfo} object to a data URI.
 * Denormalizes a data URI to a {@see \SplFileObject} object.
 *
 * @author Kévin Dunglas <dunglas@gmail.com>
 *
 * @final since Symfony 6.3
 */
class DataUriNormalizer implements NormalizerInterface, DenormalizerInterface, CacheableSupportsMethodInterface
{
    private const SUPPORTED_TYPES = [\SplFileInfo::class => \true, \SplFileObject::class => \true, File::class => \true];
    private readonly ?MimeTypeGuesserInterface $mimeTypeGuesser;
    public function __construct(?MimeTypeGuesserInterface $mimeTypeGuesser = null)
    {
        if (!$mimeTypeGuesser && class_exists(MimeTypes::class)) {
            $mimeTypeGuesser = MimeTypes::getDefault();
        }
        $this->mimeTypeGuesser = $mimeTypeGuesser;
    }
    public function getSupportedTypes(?string $format): array
    {
        $isCacheable = __CLASS__ === static::class || $this->hasCacheableSupportsMethod();
        return [\SplFileInfo::class => $isCacheable, \SplFileObject::class => $isCacheable, File::class => $isCacheable];
    }
    public function normalize(mixed $object, ?string $format = null, array $context = []): string
    {
        if (!$object instanceof \SplFileInfo) {
            throw new InvalidArgumentException('The object must be an instance of "\SplFileInfo".');
        }
        $mimeType = $this->getMimeType($object);
        $splFileObject = $this->extractSplFileObject($object);
        $data = '';
        $splFileObject->rewind();
        while (!$splFileObject->eof()) {
            $data .= $splFileObject->fgets();
        }
        if ('text' === explode('/', $mimeType, 2)[0]) {
            return \sprintf('data:%s,%s', $mimeType, rawurlencode($data));
        }
        return \sprintf('data:%s;base64,%s', $mimeType, base64_encode($data));
    }
    /**
     * @param array $context
     */
    public function supportsNormalization(mixed $data, ?string $format = null): bool
    {
        return $data instanceof \SplFileInfo;
    }
    /**
     * Regex adapted from Brian Grinstead code.
     *
     * @see https://gist.github.com/bgrins/6194623
     *
     * @throws InvalidArgumentException
     * @throws NotNormalizableValueException
     */
    public function denormalize(mixed $data, string $type, ?string $format = null, array $context = []): \SplFileInfo
    {
        if (null === $data || !preg_match('/^data:([a-z0-9][a-z0-9\!\#\$\&\-\^\_\+\.]{0,126}\/[a-z0-9][a-z0-9\!\#\$\&\-\^\_\+\.]{0,126}(;[a-z0-9\-]+\=[a-z0-9\-]+)?)?(;base64)?,[a-z0-9\!\$\&\\\'\,\(\)\*\+\,\;\=\-\.\_\~\:\@\/\?\%\s]*\s*$/i', $data)) {
            throw NotNormalizableValueException::createForUnexpectedDataType('The provided "data:" URI is not valid.', $data, ['string'], $context['deserialization_path'] ?? null, \true);
        }
        try {
            switch ($type) {
                case File::class:
                    if (!class_exists(File::class)) {
                        throw new InvalidArgumentException(\sprintf('Cannot denormalize to a "%s" without the HttpFoundation component installed. Try running "composer require symfony/http-foundation".', File::class));
                    }
                    return new File($data, \false);
                case 'SplFileObject':
                case 'SplFileInfo':
                    return new \SplFileObject($data);
            }
        } catch (\RuntimeException $exception) {
            throw NotNormalizableValueException::createForUnexpectedDataType($exception->getMessage(), $data, ['string'], $context['deserialization_path'] ?? null, \false, $exception->getCode(), $exception);
        }
        throw new InvalidArgumentException(\sprintf('The class parameter "%s" is not supported. It must be one of "SplFileInfo", "SplFileObject" or "Symfony\Component\HttpFoundation\File\File".', $type));
    }
    /**
     * @param array $context
     */
    public function supportsDenormalization(mixed $data, string $type, ?string $format = null): bool
    {
        return isset(self::SUPPORTED_TYPES[$type]);
    }
    /**
     * @deprecated since Symfony 6.3, use "getSupportedTypes()" instead
     */
    public function hasCacheableSupportsMethod(): bool
    {
        trigger_deprecation('symfony/serializer', '6.3', 'The "%s()" method is deprecated, implement "%s::getSupportedTypes()" instead.', __METHOD__, get_debug_type($this));
        return __CLASS__ === static::class;
    }
    /**
     * Gets the mime type of the object. Defaults to application/octet-stream.
     */
    private function getMimeType(\SplFileInfo $object): string
    {
        if ($object instanceof File) {
            return $object->getMimeType();
        }
        return $this->mimeTypeGuesser?->guessMimeType($object->getPathname()) ?: 'application/octet-stream';
    }
    /**
     * Returns the \SplFileObject instance associated with the given \SplFileInfo instance.
     */
    private function extractSplFileObject(\SplFileInfo $object): \SplFileObject
    {
        if ($object instanceof \SplFileObject) {
            return $object;
        }
        return $object->openFile();
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Serializer\Normalizer;

/**
 * Adds the support of an extra $context parameter for the supportsNormalization method.
 *
 * @author Kévin Dunglas <dunglas@gmail.com>
 *
 * @deprecated since symfony/serializer 6.1, use NormalizerInterface instead
 */
interface ContextAwareNormalizerInterface extends NormalizerInterface
{
    /**
     * @param array $context options that normalizers have access to
     */
    public function supportsNormalization(mixed $data, ?string $format = null, array $context = []): bool;
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Serializer\Normalizer;

use _ContaoManager\Symfony\Component\Serializer\SerializerAwareInterface;
use _ContaoManager\Symfony\Component\Serializer\SerializerAwareTrait;
/**
 * @author Jordi Boggiano <j.boggiano@seld.be>
 *
 * @final since Symfony 6.3
 */
class CustomNormalizer implements NormalizerInterface, DenormalizerInterface, SerializerAwareInterface, CacheableSupportsMethodInterface
{
    use ObjectToPopulateTrait;
    use SerializerAwareTrait;
    public function getSupportedTypes(?string $format): array
    {
        return [NormalizableInterface::class => __CLASS__ === static::class || $this->hasCacheableSupportsMethod(), DenormalizableInterface::class => __CLASS__ === static::class || $this->hasCacheableSupportsMethod()];
    }
    public function normalize(mixed $object, ?string $format = null, array $context = []): array|string|int|float|bool|\ArrayObject|null
    {
        return $object->normalize($this->serializer, $format, $context);
    }
    public function denormalize(mixed $data, string $type, ?string $format = null, array $context = []): mixed
    {
        $object = $this->extractObjectToPopulate($type, $context) ?? new $type();
        $object->denormalize($this->serializer, $data, $format, $context);
        return $object;
    }
    /**
     * Checks if the given class implements the NormalizableInterface.
     *
     * @param mixed       $data    Data to normalize
     * @param string|null $format  The format being (de-)serialized from or into
     * @param array       $context
     */
    public function supportsNormalization(mixed $data, ?string $format = null): bool
    {
        return $data instanceof NormalizableInterface;
    }
    /**
     * Checks if the given class implements the DenormalizableInterface.
     *
     * @param mixed       $data    Data to denormalize from
     * @param string      $type    The class to which the data should be denormalized
     * @param string|null $format  The format being deserialized from
     * @param array       $context
     */
    public function supportsDenormalization(mixed $data, string $type, ?string $format = null): bool
    {
        return is_subclass_of($type, DenormalizableInterface::class);
    }
    /**
     * @deprecated since Symfony 6.3, use "getSupportedTypes()" instead
     */
    public function hasCacheableSupportsMethod(): bool
    {
        trigger_deprecation('symfony/serializer', '6.3', 'The "%s()" method is deprecated, implement "%s::getSupportedTypes()" instead.', __METHOD__, get_debug_type($this));
        return __CLASS__ === static::class;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Serializer\Normalizer;

/**
 * @author Joel Wurtz <joel.wurtz@gmail.com>
 */
interface DenormalizerAwareInterface
{
    /**
     * Sets the owning Denormalizer object.
     *
     * @return void
     */
    public function setDenormalizer(DenormalizerInterface $denormalizer);
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Serializer\Normalizer;

use _ContaoManager\Symfony\Component\Serializer\Exception\InvalidArgumentException;
use _ContaoManager\Symfony\Component\Serializer\Exception\NotNormalizableValueException;
/**
 * Normalizes an instance of {@see \DateInterval} to an interval string.
 * Denormalizes an interval string to an instance of {@see \DateInterval}.
 *
 * @author Jérôme Parmentier <jerome@prmntr.me>
 *
 * @final since Symfony 6.3
 */
class DateIntervalNormalizer implements NormalizerInterface, DenormalizerInterface, CacheableSupportsMethodInterface
{
    public const FORMAT_KEY = 'dateinterval_format';
    private array $defaultContext = [self::FORMAT_KEY => '%rP%yY%mM%dDT%hH%iM%sS'];
    public function __construct(array $defaultContext = [])
    {
        $this->defaultContext = array_merge($this->defaultContext, $defaultContext);
    }
    public function getSupportedTypes(?string $format): array
    {
        return [\DateInterval::class => __CLASS__ === static::class || $this->hasCacheableSupportsMethod()];
    }
    /**
     * @throws InvalidArgumentException
     */
    public function normalize(mixed $object, ?string $format = null, array $context = []): string
    {
        if (!$object instanceof \DateInterval) {
            throw new InvalidArgumentException('The object must be an instance of "\DateInterval".');
        }
        return $object->format($context[self::FORMAT_KEY] ?? $this->defaultContext[self::FORMAT_KEY]);
    }
    /**
     * @param array $context
     */
    public function supportsNormalization(mixed $data, ?string $format = null): bool
    {
        return $data instanceof \DateInterval;
    }
    /**
     * @deprecated since Symfony 6.3, use "getSupportedTypes()" instead
     */
    public function hasCacheableSupportsMethod(): bool
    {
        trigger_deprecation('symfony/serializer', '6.3', 'The "%s()" method is deprecated, implement "%s::getSupportedTypes()" instead.', __METHOD__, get_debug_type($this));
        return __CLASS__ === static::class;
    }
    /**
     * @throws NotNormalizableValueException
     */
    public function denormalize(mixed $data, string $type, ?string $format = null, array $context = []): \DateInterval
    {
        if (!\is_string($data)) {
            throw NotNormalizableValueException::createForUnexpectedDataType('Data expected to be a string.', $data, ['string'], $context['deserialization_path'] ?? null, \true);
        }
        if (!$this->isISO8601($data)) {
            throw NotNormalizableValueException::createForUnexpectedDataType('Expected a valid ISO 8601 interval string.', $data, ['string'], $context['deserialization_path'] ?? null, \true);
        }
        $dateIntervalFormat = $context[self::FORMAT_KEY] ?? $this->defaultContext[self::FORMAT_KEY];
        $signPattern = '';
        switch (substr($dateIntervalFormat, 0, 2)) {
            case '%R':
                $signPattern = '[-+]';
                $dateIntervalFormat = substr($dateIntervalFormat, 2);
                break;
            case '%r':
                $signPattern = '-?';
                $dateIntervalFormat = substr($dateIntervalFormat, 2);
                break;
        }
        $valuePattern = '/^' . $signPattern . preg_replace('/%([yYmMdDhHiIsSwW])(\w)/', '(?:(?P<$1>\d+)$2)?', preg_replace('/(T.*)$/', '($1)?', $dateIntervalFormat)) . '$/';
        if (!preg_match($valuePattern, $data)) {
            throw NotNormalizableValueException::createForUnexpectedDataType(\sprintf('Value "%s" contains intervals not accepted by format "%s".', $data, $dateIntervalFormat), $data, ['string'], $context['deserialization_path'] ?? null, \false);
        }
        try {
            if ('-' === $data[0]) {
                $interval = new \DateInterval(substr($data, 1));
                $interval->invert = 1;
                return $interval;
            }
            if ('+' === $data[0]) {
                return new \DateInterval(substr($data, 1));
            }
            return new \DateInterval($data);
        } catch (\Exception $e) {
            throw NotNormalizableValueException::createForUnexpectedDataType($e->getMessage(), $data, ['string'], $context['deserialization_path'] ?? null, \false, $e->getCode(), $e);
        }
    }
    /**
     * @param array $context
     */
    public function supportsDenormalization(mixed $data, string $type, ?string $format = null): bool
    {
        return \DateInterval::class === $type;
    }
    private function isISO8601(string $string): bool
    {
        return preg_match('/^[\-+]?P(?=\w*(?:\d|%\w))(?:\d+Y|%[yY]Y)?(?:\d+M|%[mM]M)?(?:\d+W|%[wW]W)?(?:\d+D|%[dD]D)?(?:T(?:\d+H|[hH]H)?(?:\d+M|[iI]M)?(?:\d+S|[sS]S)?)?$/', $string);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Serializer\Normalizer;

use _ContaoManager\Symfony\Component\PropertyAccess\Exception\UninitializedPropertyException;
use _ContaoManager\Symfony\Component\PropertyInfo\PropertyTypeExtractorInterface;
use _ContaoManager\Symfony\Component\Serializer\Exception\LogicException;
use _ContaoManager\Symfony\Component\Serializer\Mapping\ClassDiscriminatorResolverInterface;
use _ContaoManager\Symfony\Component\Serializer\Mapping\Factory\ClassMetadataFactoryInterface;
use _ContaoManager\Symfony\Component\Serializer\NameConverter\NameConverterInterface;
/**
 * Converts between objects and arrays by mapping properties.
 *
 * The normalization process looks for all the object's properties (public and private).
 * The result is a map from property names to property values. Property values
 * are normalized through the serializer.
 *
 * The denormalization first looks at the constructor of the given class to see
 * if any of the parameters have the same name as one of the properties. The
 * constructor is then called with all parameters or an exception is thrown if
 * any required parameters were not present as properties. Then the denormalizer
 * walks through the given map of property names to property values to see if a
 * property with the corresponding name exists. If found, the property gets the value.
 *
 * @author Matthieu Napoli <matthieu@mnapoli.fr>
 * @author Kévin Dunglas <dunglas@gmail.com>
 *
 * @final since Symfony 6.3
 */
class PropertyNormalizer extends AbstractObjectNormalizer
{
    public const NORMALIZE_PUBLIC = 1;
    public const NORMALIZE_PROTECTED = 2;
    public const NORMALIZE_PRIVATE = 4;
    /**
     * Flag to control whether fields should be output based on visibility.
     */
    public const NORMALIZE_VISIBILITY = 'normalize_visibility';
    public function __construct(?ClassMetadataFactoryInterface $classMetadataFactory = null, ?NameConverterInterface $nameConverter = null, ?PropertyTypeExtractorInterface $propertyTypeExtractor = null, ?ClassDiscriminatorResolverInterface $classDiscriminatorResolver = null, ?callable $objectClassResolver = null, array $defaultContext = [])
    {
        parent::__construct($classMetadataFactory, $nameConverter, $propertyTypeExtractor, $classDiscriminatorResolver, $objectClassResolver, $defaultContext);
        if (!isset($this->defaultContext[self::NORMALIZE_VISIBILITY])) {
            $this->defaultContext[self::NORMALIZE_VISIBILITY] = self::NORMALIZE_PUBLIC | self::NORMALIZE_PROTECTED | self::NORMALIZE_PRIVATE;
        }
    }
    public function getSupportedTypes(?string $format): array
    {
        return ['object' => __CLASS__ === static::class || $this->hasCacheableSupportsMethod()];
    }
    /**
     * @param array $context
     */
    public function supportsNormalization(mixed $data, ?string $format = null): bool
    {
        return parent::supportsNormalization($data, $format) && $this->supports($data::class);
    }
    /**
     * @param array $context
     */
    public function supportsDenormalization(mixed $data, string $type, ?string $format = null): bool
    {
        return parent::supportsDenormalization($data, $type, $format) && $this->supports($type);
    }
    /**
     * @deprecated since Symfony 6.3, use "getSupportedTypes()" instead
     */
    public function hasCacheableSupportsMethod(): bool
    {
        trigger_deprecation('symfony/serializer', '6.3', 'The "%s()" method is deprecated, implement "%s::getSupportedTypes()" instead.', __METHOD__, get_debug_type($this));
        return __CLASS__ === static::class;
    }
    /**
     * Checks if the given class has any non-static property.
     */
    private function supports(string $class): bool
    {
        if ($this->classDiscriminatorResolver?->getMappingForClass($class)) {
            return \true;
        }
        $class = new \ReflectionClass($class);
        // We look for at least one non-static property
        do {
            foreach ($class->getProperties() as $property) {
                if (!$property->isStatic()) {
                    return \true;
                }
            }
        } while ($class = $class->getParentClass());
        return \false;
    }
    protected function isAllowedAttribute(object|string $classOrObject, string $attribute, ?string $format = null, array $context = []): bool
    {
        if (!parent::isAllowedAttribute($classOrObject, $attribute, $format, $context)) {
            return \false;
        }
        if ($this->classDiscriminatorResolver?->getMappingForMappedObject($classOrObject)?->getTypeProperty() === $attribute) {
            return \true;
        }
        try {
            $reflectionProperty = $this->getReflectionProperty($classOrObject, $attribute);
        } catch (\ReflectionException) {
            return \false;
        }
        if ($reflectionProperty->isStatic()) {
            return \false;
        }
        $normalizeVisibility = $context[self::NORMALIZE_VISIBILITY] ?? $this->defaultContext[self::NORMALIZE_VISIBILITY];
        if (self::NORMALIZE_PUBLIC & $normalizeVisibility && $reflectionProperty->isPublic()) {
            return \true;
        }
        if (self::NORMALIZE_PROTECTED & $normalizeVisibility && $reflectionProperty->isProtected()) {
            return \true;
        }
        if (self::NORMALIZE_PRIVATE & $normalizeVisibility && $reflectionProperty->isPrivate()) {
            return \true;
        }
        return \false;
    }
    protected function extractAttributes(object $object, ?string $format = null, array $context = []): array
    {
        $reflectionObject = new \ReflectionObject($object);
        $attributes = [];
        do {
            foreach ($reflectionObject->getProperties() as $property) {
                if (!$this->isAllowedAttribute($reflectionObject->getName(), $property->name, $format, $context)) {
                    continue;
                }
                $attributes[] = $property->name;
            }
        } while ($reflectionObject = $reflectionObject->getParentClass());
        return array_unique($attributes);
    }
    protected function getAttributeValue(object $object, string $attribute, ?string $format = null, array $context = []): mixed
    {
        try {
            $reflectionProperty = $this->getReflectionProperty($object, $attribute);
        } catch (\ReflectionException) {
            return null;
        }
        if ($reflectionProperty->hasType()) {
            return $reflectionProperty->getValue($object);
        }
        if (!method_exists($object, '__get') && !isset($object->{$attribute})) {
            $propertyValues = (array) $object;
            if ($reflectionProperty->isPublic() && !\array_key_exists($reflectionProperty->name, $propertyValues) || $reflectionProperty->isProtected() && !\array_key_exists("\x00*\x00{$reflectionProperty->name}", $propertyValues) || $reflectionProperty->isPrivate() && !\array_key_exists("\x00{$reflectionProperty->class}\x00{$reflectionProperty->name}", $propertyValues)) {
                throw new UninitializedPropertyException(\sprintf('The property "%s::$%s" is not initialized.', $object::class, $reflectionProperty->name));
            }
        }
        return $reflectionProperty->getValue($object);
    }
    /**
     * @return void
     */
    protected function setAttributeValue(object $object, string $attribute, mixed $value, ?string $format = null, array $context = [])
    {
        try {
            $reflectionProperty = $this->getReflectionProperty($object, $attribute);
        } catch (\ReflectionException) {
            return;
        }
        if ($reflectionProperty->isStatic()) {
            return;
        }
        if (!$reflectionProperty->isReadOnly()) {
            $reflectionProperty->setValue($object, $value);
            return;
        }
        if (!$reflectionProperty->isInitialized($object)) {
            $declaringClass = $reflectionProperty->getDeclaringClass();
            $declaringClass->getProperty($reflectionProperty->getName())->setValue($object, $value);
            return;
        }
        if ($reflectionProperty->getValue($object) !== $value) {
            throw new LogicException(\sprintf('Attempting to change readonly property "%s"::$%s.', $object::class, $reflectionProperty->getName()));
        }
    }
    /**
     * @throws \ReflectionException
     */
    private function getReflectionProperty(string|object $classOrObject, string $attribute): \ReflectionProperty
    {
        $reflectionClass = new \ReflectionClass($classOrObject);
        while (\true) {
            try {
                return $reflectionClass->getProperty($attribute);
            } catch (\ReflectionException $e) {
                if (!$reflectionClass = $reflectionClass->getParentClass()) {
                    throw $e;
                }
            }
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Serializer\Normalizer;

use _ContaoManager\Symfony\Component\PropertyAccess\Exception\NoSuchPropertyException;
use _ContaoManager\Symfony\Component\PropertyAccess\PropertyAccess;
use _ContaoManager\Symfony\Component\PropertyAccess\PropertyAccessorInterface;
use _ContaoManager\Symfony\Component\PropertyInfo\Extractor\ReflectionExtractor;
use _ContaoManager\Symfony\Component\PropertyInfo\PropertyInfoExtractorInterface;
use _ContaoManager\Symfony\Component\PropertyInfo\PropertyTypeExtractorInterface;
use _ContaoManager\Symfony\Component\PropertyInfo\PropertyWriteInfo;
use _ContaoManager\Symfony\Component\Serializer\Attribute\Ignore;
use _ContaoManager\Symfony\Component\Serializer\Exception\LogicException;
use _ContaoManager\Symfony\Component\Serializer\Mapping\ClassDiscriminatorResolverInterface;
use _ContaoManager\Symfony\Component\Serializer\Mapping\Factory\ClassMetadataFactoryInterface;
use _ContaoManager\Symfony\Component\Serializer\Mapping\Loader\AccessorCollisionResolverTrait;
use _ContaoManager\Symfony\Component\Serializer\NameConverter\NameConverterInterface;
/**
 * Converts between objects and arrays using the PropertyAccess component.
 *
 * @author Kévin Dunglas <dunglas@gmail.com>
 *
 * @final since Symfony 6.3
 */
class ObjectNormalizer extends AbstractObjectNormalizer
{
    use AccessorCollisionResolverTrait;
    private static $reflectionCache = [];
    private static $isReadableCache = [];
    private static $isWritableCache = [];
    protected $propertyAccessor;
    protected $propertyInfoExtractor;
    private $writeInfoExtractor;
    private readonly \Closure $objectClassResolver;
    public function __construct(?ClassMetadataFactoryInterface $classMetadataFactory = null, ?NameConverterInterface $nameConverter = null, ?PropertyAccessorInterface $propertyAccessor = null, ?PropertyTypeExtractorInterface $propertyTypeExtractor = null, ?ClassDiscriminatorResolverInterface $classDiscriminatorResolver = null, ?callable $objectClassResolver = null, array $defaultContext = [], ?PropertyInfoExtractorInterface $propertyInfoExtractor = null)
    {
        if (!class_exists(PropertyAccess::class)) {
            throw new LogicException('The ObjectNormalizer class requires the "PropertyAccess" component. Try running "composer require symfony/property-access".');
        }
        parent::__construct($classMetadataFactory, $nameConverter, $propertyTypeExtractor, $classDiscriminatorResolver, $objectClassResolver, $defaultContext);
        $this->propertyAccessor = $propertyAccessor ?: PropertyAccess::createPropertyAccessor();
        $this->objectClassResolver = ($objectClassResolver ?? static fn($class) => \is_object($class) ? $class::class : $class)(...);
        $this->propertyInfoExtractor = $propertyInfoExtractor ?: new ReflectionExtractor();
        $this->writeInfoExtractor = new ReflectionExtractor();
    }
    public function getSupportedTypes(?string $format): array
    {
        return ['object' => __CLASS__ === static::class || $this->hasCacheableSupportsMethod()];
    }
    /**
     * @deprecated since Symfony 6.3, use "getSupportedTypes()" instead
     */
    public function hasCacheableSupportsMethod(): bool
    {
        trigger_deprecation('symfony/serializer', '6.3', 'The "%s()" method is deprecated, implement "%s::getSupportedTypes()" instead.', __METHOD__, get_debug_type($this));
        return __CLASS__ === static::class;
    }
    protected function extractAttributes(object $object, ?string $format = null, array $context = []): array
    {
        if (\stdClass::class === $object::class) {
            return array_keys((array) $object);
        }
        // If not using groups, detect manually
        $attributes = [];
        // methods
        $class = ($this->objectClassResolver)($object);
        $reflClass = new \ReflectionClass($class);
        foreach ($reflClass->getMethods(\ReflectionMethod::IS_PUBLIC) as $reflMethod) {
            $name = $reflMethod->name;
            $attributeName = $this->getAttributeNameFromAccessor($reflClass, $reflMethod, \false);
            if ($this->hasPropertyForAccessor($reflMethod->getDeclaringClass(), $name) && (null === $attributeName || $this->hasAttributeNameCollision($reflClass, $attributeName, $name))) {
                $attributeName = $name;
            }
            if (null !== $attributeName && $this->isAllowedAttribute($object, $attributeName, $format, $context)) {
                $attributes[$attributeName] = \true;
            }
        }
        // properties
        foreach ($reflClass->getProperties() as $reflProperty) {
            if (!$reflProperty->isPublic()) {
                continue;
            }
            if ($reflProperty->isStatic() || !$this->isAllowedAttribute($object, $reflProperty->name, $format, $context)) {
                continue;
            }
            $attributes[$reflProperty->name] = \true;
        }
        return array_keys($attributes);
    }
    protected function getAttributeValue(object $object, string $attribute, ?string $format = null, array $context = []): mixed
    {
        $mapping = $this->classDiscriminatorResolver?->getMappingForMappedObject($object);
        return $attribute === $mapping?->getTypeProperty() ? $mapping : $this->propertyAccessor->getValue($object, $attribute);
    }
    /**
     * @return void
     */
    protected function setAttributeValue(object $object, string $attribute, mixed $value, ?string $format = null, array $context = [])
    {
        try {
            $this->propertyAccessor->setValue($object, $attribute, $value);
        } catch (NoSuchPropertyException) {
            // Properties not found are ignored
        }
    }
    protected function isAllowedAttribute($classOrObject, string $attribute, ?string $format = null, array $context = [])
    {
        if (!parent::isAllowedAttribute($classOrObject, $attribute, $format, $context)) {
            return \false;
        }
        $class = \is_object($classOrObject) ? $classOrObject::class : $classOrObject;
        if ($this->classDiscriminatorResolver?->getMappingForMappedObject($classOrObject)?->getTypeProperty() === $attribute) {
            return \true;
        }
        if ($context['_read_attributes'] ?? \true) {
            $context = array_intersect_key($context, ['enable_getter_setter_extraction' => \true, 'enable_magic_methods_extraction' => \true]);
            $cacheKey = $class . $attribute . hash('xxh128', serialize($context));
            return self::$isReadableCache[$cacheKey] ??= $this->propertyInfoExtractor->isReadable($class, $attribute, $context) || $this->hasAttributeAccessorMethod($class, $attribute) || \is_object($classOrObject) && $this->propertyAccessor->isReadable($classOrObject, $attribute);
        }
        $context = array_intersect_key($context, ['enable_getter_setter_extraction' => \true, 'enable_magic_methods_extraction' => \true, 'enable_constructor_extraction' => \true, 'enable_adder_remover_extraction' => \true]);
        $cacheKey = $class . $attribute . hash('xxh128', serialize($context));
        if (isset(self::$isWritableCache[$cacheKey])) {
            return self::$isWritableCache[$cacheKey];
        }
        if (str_contains($attribute, '.') || $this->propertyInfoExtractor->isWritable($class, $attribute, $context)) {
            return self::$isWritableCache[$cacheKey] = \true;
        }
        $writeType = $this->writeInfoExtractor->getWriteInfo($class, $attribute, $context)?->getType();
        return self::$isWritableCache[$cacheKey] = !\in_array($writeType, [null, PropertyWriteInfo::TYPE_NONE], \true) && (PropertyWriteInfo::TYPE_PROPERTY !== $writeType || !property_exists($class, $attribute));
    }
    private function hasAttributeAccessorMethod(string $class, string $attribute): bool
    {
        $reflection = self::$reflectionCache[$class] ??= new \ReflectionClass($class);
        if (!$reflection->hasMethod($attribute)) {
            return \false;
        }
        $method = $reflection->getMethod($attribute);
        return !$method->isStatic() && !$method->getAttributes(Ignore::class) && !$method->getNumberOfRequiredParameters() && !\in_array((string) $method->getReturnType(), ['void', 'never'], \true);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Serializer\Normalizer;

use _ContaoManager\Symfony\Component\Serializer\Exception\CircularReferenceException;
use _ContaoManager\Symfony\Component\Serializer\Exception\InvalidArgumentException;
use _ContaoManager\Symfony\Component\Serializer\Exception\LogicException;
use _ContaoManager\Symfony\Component\Serializer\Exception\MissingConstructorArgumentsException;
use _ContaoManager\Symfony\Component\Serializer\Exception\NotNormalizableValueException;
use _ContaoManager\Symfony\Component\Serializer\Exception\RuntimeException;
use _ContaoManager\Symfony\Component\Serializer\Mapping\AttributeMetadataInterface;
use _ContaoManager\Symfony\Component\Serializer\Mapping\Factory\ClassMetadataFactoryInterface;
use _ContaoManager\Symfony\Component\Serializer\NameConverter\NameConverterInterface;
use _ContaoManager\Symfony\Component\Serializer\SerializerAwareInterface;
use _ContaoManager\Symfony\Component\Serializer\SerializerAwareTrait;
/**
 * Normalizer implementation.
 *
 * @author Kévin Dunglas <dunglas@gmail.com>
 */
abstract class AbstractNormalizer implements NormalizerInterface, DenormalizerInterface, SerializerAwareInterface, CacheableSupportsMethodInterface
{
    use ObjectToPopulateTrait;
    use SerializerAwareTrait;
    /* constants to configure the context */
    /**
     * How many loops of circular reference to allow while normalizing.
     *
     * The default value of 1 means that when we encounter the same object a
     * second time, we consider that a circular reference.
     *
     * You can raise this value for special cases, e.g. in combination with the
     * max depth setting of the object normalizer.
     */
    public const CIRCULAR_REFERENCE_LIMIT = 'circular_reference_limit';
    /**
     * Instead of creating a new instance of an object, update the specified object.
     *
     * If you have a nested structure, child objects will be overwritten with
     * new instances unless you set DEEP_OBJECT_TO_POPULATE to true.
     */
    public const OBJECT_TO_POPULATE = 'object_to_populate';
    /**
     * Only (de)normalize attributes that are in the specified groups.
     */
    public const GROUPS = 'groups';
    /**
     * Limit (de)normalize to the specified names.
     *
     * For nested structures, this list needs to reflect the object tree.
     */
    public const ATTRIBUTES = 'attributes';
    /**
     * If ATTRIBUTES are specified, and the source has fields that are not part of that list,
     * either ignore those attributes (true) or throw an ExtraAttributesException (false).
     */
    public const ALLOW_EXTRA_ATTRIBUTES = 'allow_extra_attributes';
    /**
     * Hashmap of default values for constructor arguments.
     *
     * The names need to match the parameter names in the constructor arguments.
     */
    public const DEFAULT_CONSTRUCTOR_ARGUMENTS = 'default_constructor_arguments';
    /**
     * Hashmap of field name => callable to (de)normalize this field.
     *
     * The callable is called if the field is encountered with the arguments:
     *
     * - mixed         $attributeValue value of this field
     * - object|string $object         the whole object being normalized or the object's class being denormalized
     * - string        $attributeName  name of the attribute being (de)normalized
     * - string        $format         the requested format
     * - array         $context        the serialization context
     */
    public const CALLBACKS = 'callbacks';
    /**
     * Handler to call when a circular reference has been detected.
     *
     * If you specify no handler, a CircularReferenceException is thrown.
     *
     * The method will be called with ($object, $format, $context) and its
     * return value is returned as the result of the normalize call.
     */
    public const CIRCULAR_REFERENCE_HANDLER = 'circular_reference_handler';
    /**
     * Skip the specified attributes when normalizing an object tree.
     *
     * This list is applied to each element of nested structures.
     *
     * Note: The behaviour for nested structures is different from ATTRIBUTES
     * for historical reason. Aligning the behaviour would be a BC break.
     */
    public const IGNORED_ATTRIBUTES = 'ignored_attributes';
    /**
     * Require all properties to be listed in the input instead of falling
     * back to null for nullable ones.
     */
    public const REQUIRE_ALL_PROPERTIES = 'require_all_properties';
    /**
     * @internal
     */
    protected const CIRCULAR_REFERENCE_LIMIT_COUNTERS = 'circular_reference_limit_counters';
    protected $defaultContext = [self::ALLOW_EXTRA_ATTRIBUTES => \true, self::CIRCULAR_REFERENCE_HANDLER => null, self::CIRCULAR_REFERENCE_LIMIT => 1, self::IGNORED_ATTRIBUTES => []];
    /**
     * @var ClassMetadataFactoryInterface|null
     */
    protected $classMetadataFactory;
    /**
     * @var NameConverterInterface|null
     */
    protected $nameConverter;
    /**
     * Sets the {@link ClassMetadataFactoryInterface} to use.
     */
    public function __construct(?ClassMetadataFactoryInterface $classMetadataFactory = null, ?NameConverterInterface $nameConverter = null, array $defaultContext = [])
    {
        $this->classMetadataFactory = $classMetadataFactory;
        $this->nameConverter = $nameConverter;
        $this->defaultContext = array_merge($this->defaultContext, $defaultContext);
        $this->validateCallbackContext($this->defaultContext, 'default');
        if (isset($this->defaultContext[self::CIRCULAR_REFERENCE_HANDLER]) && !\is_callable($this->defaultContext[self::CIRCULAR_REFERENCE_HANDLER])) {
            throw new InvalidArgumentException(\sprintf('Invalid callback found in the "%s" default context option.', self::CIRCULAR_REFERENCE_HANDLER));
        }
    }
    /**
     * @deprecated since Symfony 6.3, use "getSupportedTypes()" instead
     */
    public function hasCacheableSupportsMethod(): bool
    {
        trigger_deprecation('symfony/serializer', '6.3', 'The "%s()" method is deprecated, implement "%s::getSupportedTypes()" instead.', __METHOD__, get_debug_type($this));
        return \false;
    }
    /**
     * Detects if the configured circular reference limit is reached.
     *
     * @throws CircularReferenceException
     */
    protected function isCircularReference(object $object, array &$context): bool
    {
        $objectHash = spl_object_hash($object);
        $circularReferenceLimit = $context[self::CIRCULAR_REFERENCE_LIMIT] ?? $this->defaultContext[self::CIRCULAR_REFERENCE_LIMIT];
        if (isset($context[self::CIRCULAR_REFERENCE_LIMIT_COUNTERS][$objectHash])) {
            if ($context[self::CIRCULAR_REFERENCE_LIMIT_COUNTERS][$objectHash] >= $circularReferenceLimit) {
                unset($context[self::CIRCULAR_REFERENCE_LIMIT_COUNTERS][$objectHash]);
                return \true;
            }
            ++$context[self::CIRCULAR_REFERENCE_LIMIT_COUNTERS][$objectHash];
        } else {
            $context[self::CIRCULAR_REFERENCE_LIMIT_COUNTERS][$objectHash] = 1;
        }
        return \false;
    }
    /**
     * Handles a circular reference.
     *
     * If a circular reference handler is set, it will be called. Otherwise, a
     * {@class CircularReferenceException} will be thrown.
     *
     * @final
     *
     * @throws CircularReferenceException
     */
    protected function handleCircularReference(object $object, ?string $format = null, array $context = []): mixed
    {
        $circularReferenceHandler = $context[self::CIRCULAR_REFERENCE_HANDLER] ?? $this->defaultContext[self::CIRCULAR_REFERENCE_HANDLER];
        if ($circularReferenceHandler) {
            return $circularReferenceHandler($object, $format, $context);
        }
        throw new CircularReferenceException(\sprintf('A circular reference has been detected when serializing the object of class "%s" (configured limit: %d).', get_debug_type($object), $context[self::CIRCULAR_REFERENCE_LIMIT] ?? $this->defaultContext[self::CIRCULAR_REFERENCE_LIMIT]));
    }
    /**
     * Gets attributes to normalize using groups.
     *
     * @param bool $attributesAsString If false, return an array of {@link AttributeMetadataInterface}
     *
     * @return string[]|AttributeMetadataInterface[]|bool
     *
     * @throws LogicException if the 'allow_extra_attributes' context variable is false and no class metadata factory is provided
     */
    protected function getAllowedAttributes(string|object $classOrObject, array $context, bool $attributesAsString = \false)
    {
        $allowExtraAttributes = $context[self::ALLOW_EXTRA_ATTRIBUTES] ?? $this->defaultContext[self::ALLOW_EXTRA_ATTRIBUTES];
        if (!$this->classMetadataFactory) {
            if (!$allowExtraAttributes) {
                throw new LogicException(\sprintf('A class metadata factory must be provided in the constructor when setting "%s" to false.', self::ALLOW_EXTRA_ATTRIBUTES));
            }
            return \false;
        }
        $groups = $this->getGroups($context);
        $allowedAttributes = [];
        $ignoreUsed = \false;
        foreach ($this->classMetadataFactory->getMetadataFor($classOrObject)->getAttributesMetadata() as $attributeMetadata) {
            if ($ignore = $attributeMetadata->isIgnored()) {
                $ignoreUsed = \true;
            }
            // If you update this check, update accordingly the one in Symfony\Component\PropertyInfo\Extractor\SerializerExtractor::getProperties()
            if (!$ignore && ([] === $groups || array_intersect(array_merge($attributeMetadata->getGroups(), ['*']), $groups)) && $this->isAllowedAttribute($classOrObject, $name = $attributeMetadata->getName(), null, $context)) {
                $allowedAttributes[] = $attributesAsString ? $name : $attributeMetadata;
            }
        }
        if (!$ignoreUsed && [] === $groups && $allowExtraAttributes) {
            // Backward Compatibility with the code using this method written before the introduction of @Ignore
            return \false;
        }
        return $allowedAttributes;
    }
    protected function getGroups(array $context): array
    {
        $groups = $context[self::GROUPS] ?? $this->defaultContext[self::GROUPS] ?? [];
        return \is_scalar($groups) ? (array) $groups : $groups;
    }
    /**
     * Is this attribute allowed?
     *
     * @return bool
     */
    protected function isAllowedAttribute(object|string $classOrObject, string $attribute, ?string $format = null, array $context = [])
    {
        $ignoredAttributes = $context[self::IGNORED_ATTRIBUTES] ?? $this->defaultContext[self::IGNORED_ATTRIBUTES];
        if (\in_array($attribute, $ignoredAttributes)) {
            return \false;
        }
        $attributes = $context[self::ATTRIBUTES] ?? $this->defaultContext[self::ATTRIBUTES] ?? null;
        if (isset($attributes[$attribute])) {
            // Nested attributes
            return \true;
        }
        if (\is_array($attributes)) {
            return \in_array($attribute, $attributes, \true);
        }
        return \true;
    }
    /**
     * Normalizes the given data to an array. It's particularly useful during
     * the denormalization process.
     */
    protected function prepareForDenormalization(mixed $data): array
    {
        return (array) $data;
    }
    /**
     * Returns the method to use to construct an object. This method must be either
     * the object constructor or static.
     */
    protected function getConstructor(array &$data, string $class, array &$context, \ReflectionClass $reflectionClass, array|bool $allowedAttributes): ?\ReflectionMethod
    {
        return $reflectionClass->getConstructor();
    }
    /**
     * Instantiates an object using constructor parameters when needed.
     *
     * This method also allows to denormalize data into an existing object if
     * it is present in the context with the object_to_populate. This object
     * is removed from the context before being returned to avoid side effects
     * when recursively normalizing an object graph.
     *
     * @return object
     *
     * @throws RuntimeException
     * @throws MissingConstructorArgumentsException
     */
    protected function instantiateObject(array &$data, string $class, array &$context, \ReflectionClass $reflectionClass, array|bool $allowedAttributes, ?string $format = null)
    {
        if (null !== $object = $this->extractObjectToPopulate($class, $context, self::OBJECT_TO_POPULATE)) {
            unset($context[self::OBJECT_TO_POPULATE]);
            return $object;
        }
        // clean up even if no match
        unset($context[static::OBJECT_TO_POPULATE]);
        $constructor = $this->getConstructor($data, $class, $context, $reflectionClass, $allowedAttributes);
        if ($constructor) {
            if (\true !== $constructor->isPublic()) {
                return $reflectionClass->newInstanceWithoutConstructor();
            }
            $constructorParameters = $constructor->getParameters();
            $missingConstructorArguments = [];
            $params = [];
            $unsetKeys = [];
            foreach ($constructorParameters as $constructorParameter) {
                $paramName = $constructorParameter->name;
                $attributeContext = $this->getAttributeDenormalizationContext($class, $paramName, $context);
                $key = $this->nameConverter ? $this->nameConverter->normalize($paramName, $class, $format, $context) : $paramName;
                $allowed = \false === $allowedAttributes || \in_array($paramName, $allowedAttributes);
                $ignored = !$this->isAllowedAttribute($class, $paramName, $format, $context);
                if ($constructorParameter->isVariadic()) {
                    if ($allowed && !$ignored && (isset($data[$key]) || \array_key_exists($key, $data))) {
                        if (!\is_array($data[$key])) {
                            throw new RuntimeException(\sprintf('Cannot create an instance of "%s" from serialized data because the variadic parameter "%s" can only accept an array.', $class, $constructorParameter->name));
                        }
                        $variadicParameters = [];
                        foreach ($data[$key] as $parameterKey => $parameterData) {
                            try {
                                $variadicParameters[$parameterKey] = $this->denormalizeParameter($reflectionClass, $constructorParameter, $paramName, $parameterData, $attributeContext, $format);
                            } catch (NotNormalizableValueException $exception) {
                                if (!isset($context['not_normalizable_value_exceptions'])) {
                                    throw $exception;
                                }
                                $context['not_normalizable_value_exceptions'][] = $exception;
                                $params[$paramName] = $parameterData;
                            }
                        }
                        $params = array_merge(array_values($params), $variadicParameters);
                        $unsetKeys[] = $key;
                    }
                } elseif ($allowed && !$ignored && (isset($data[$key]) || \array_key_exists($key, $data))) {
                    $parameterData = $data[$key];
                    if (null === $parameterData && $constructorParameter->allowsNull()) {
                        $params[$paramName] = null;
                        $unsetKeys[] = $key;
                        continue;
                    }
                    try {
                        $params[$paramName] = $this->denormalizeParameter($reflectionClass, $constructorParameter, $paramName, $parameterData, $attributeContext, $format);
                    } catch (NotNormalizableValueException $exception) {
                        if (!isset($context['not_normalizable_value_exceptions'])) {
                            throw $exception;
                        }
                        $context['not_normalizable_value_exceptions'][] = $exception;
                        $params[$paramName] = $parameterData;
                    }
                    $unsetKeys[] = $key;
                } elseif (\array_key_exists($key, $context[static::DEFAULT_CONSTRUCTOR_ARGUMENTS][$class] ?? [])) {
                    $params[$paramName] = $context[static::DEFAULT_CONSTRUCTOR_ARGUMENTS][$class][$key];
                } elseif (\array_key_exists($key, $this->defaultContext[self::DEFAULT_CONSTRUCTOR_ARGUMENTS][$class] ?? [])) {
                    $params[$paramName] = $this->defaultContext[self::DEFAULT_CONSTRUCTOR_ARGUMENTS][$class][$key];
                } elseif ($constructorParameter->isDefaultValueAvailable()) {
                    $params[$paramName] = $constructorParameter->getDefaultValue();
                } elseif (!($context[self::REQUIRE_ALL_PROPERTIES] ?? $this->defaultContext[self::REQUIRE_ALL_PROPERTIES] ?? \false) && $constructorParameter->hasType() && $constructorParameter->getType()->allowsNull()) {
                    $params[$paramName] = null;
                } else {
                    if (!isset($context['not_normalizable_value_exceptions'])) {
                        $missingConstructorArguments[] = $constructorParameter->name;
                        continue;
                    }
                    $constructorParameterTypes = [];
                    $reflectionType = $constructorParameter->getType();
                    if ($reflectionType instanceof \ReflectionUnionType) {
                        foreach ($reflectionType->getTypes() as $reflectionType) {
                            $constructorParameterTypes[] = (string) $reflectionType;
                        }
                    } elseif ($reflectionType instanceof \ReflectionType) {
                        $constructorParameterTypes[] = (string) $reflectionType;
                    } else {
                        $constructorParameterTypes[] = 'unknown';
                    }
                    $exception = NotNormalizableValueException::createForUnexpectedDataType(\sprintf('Failed to create object because the class misses the "%s" property.', $constructorParameter->name), null, $constructorParameterTypes, $attributeContext['deserialization_path'] ?? null, \true);
                    $context['not_normalizable_value_exceptions'][] = $exception;
                }
            }
            if ($missingConstructorArguments) {
                throw new MissingConstructorArgumentsException(\sprintf('Cannot create an instance of "%s" from serialized data because its constructor requires the following parameters to be present : "$%s".', $class, implode('", "$', $missingConstructorArguments)), 0, null, $missingConstructorArguments, $class);
            }
            if (!$constructor->isConstructor()) {
                $instance = $constructor->invokeArgs(null, $params);
                // do not set a parameter that has been set in the constructor
                foreach ($unsetKeys as $key) {
                    unset($data[$key]);
                }
                return $instance;
            }
            try {
                $instance = $reflectionClass->newInstanceArgs($params);
                // do not set a parameter that has been set in the constructor
                foreach ($unsetKeys as $key) {
                    unset($data[$key]);
                }
                return $instance;
            } catch (\TypeError $e) {
                if (!isset($context['not_normalizable_value_exceptions'])) {
                    throw $e;
                }
                return $reflectionClass->newInstanceWithoutConstructor();
            }
        }
        if (!$reflectionClass->isInstantiable()) {
            throw NotNormalizableValueException::createForUnexpectedDataType(\sprintf('Failed to create object because the class "%s" is not instantiable.', $class), $data, ['unknown'], $context['deserialization_path'] ?? null);
        }
        return new $class();
    }
    /**
     * @internal
     */
    protected function denormalizeParameter(\ReflectionClass $class, \ReflectionParameter $parameter, string $parameterName, mixed $parameterData, array $context, ?string $format = null): mixed
    {
        try {
            if (($parameterType = $parameter->getType()) instanceof \ReflectionNamedType && !$parameterType->isBuiltin()) {
                $parameterClass = $parameterType->getName();
                new \ReflectionClass($parameterClass);
                // throws a \ReflectionException if the class doesn't exist
                if (!$this->serializer instanceof DenormalizerInterface) {
                    throw new LogicException(\sprintf('Cannot create an instance of "%s" from serialized data because the serializer inject in "%s" is not a denormalizer.', $parameterClass, static::class));
                }
                $parameterData = $this->serializer->denormalize($parameterData, $parameterClass, $format, $this->createChildContext($context, $parameterName, $format));
            }
        } catch (\ReflectionException $e) {
            throw new RuntimeException(\sprintf('Could not determine the class of the parameter "%s".', $parameterName), 0, $e);
        } catch (MissingConstructorArgumentsException $e) {
            if (!$parameter->getType()->allowsNull()) {
                throw $e;
            }
            return null;
        }
        return $this->applyCallbacks($parameterData, $class->getName(), $parameterName, $format, $context);
    }
    /**
     * @internal
     */
    protected function createChildContext(array $parentContext, string $attribute, ?string $format): array
    {
        if (isset($parentContext[self::ATTRIBUTES][$attribute])) {
            $parentContext[self::ATTRIBUTES] = $parentContext[self::ATTRIBUTES][$attribute];
        } else {
            unset($parentContext[self::ATTRIBUTES]);
        }
        return $parentContext;
    }
    /**
     * Validate callbacks set in context.
     *
     * @param string $contextType Used to specify which context is invalid in exceptions
     *
     * @throws InvalidArgumentException
     */
    final protected function validateCallbackContext(array $context, string $contextType = ''): void
    {
        if (!isset($context[self::CALLBACKS])) {
            return;
        }
        if (!\is_array($context[self::CALLBACKS])) {
            throw new InvalidArgumentException(\sprintf('The "%s"%s context option must be an array of callables.', self::CALLBACKS, '' !== $contextType ? " {$contextType}" : ''));
        }
        foreach ($context[self::CALLBACKS] as $attribute => $callback) {
            if (!\is_callable($callback)) {
                throw new InvalidArgumentException(\sprintf('Invalid callback found for attribute "%s" in the "%s"%s context option.', $attribute, self::CALLBACKS, '' !== $contextType ? " {$contextType}" : ''));
            }
        }
    }
    final protected function applyCallbacks(mixed $value, object|string $object, string $attribute, ?string $format, array $context): mixed
    {
        /**
         * @var callable|null
         */
        $callback = $context[self::CALLBACKS][$attribute] ?? $this->defaultContext[self::CALLBACKS][$attribute] ?? null;
        return $callback ? $callback($value, $object, $attribute, $format, $context) : $value;
    }
    /**
     * Computes the normalization context merged with current one. Metadata always wins over global context, as more specific.
     *
     * @internal
     */
    protected function getAttributeNormalizationContext(object $object, string $attribute, array $context): array
    {
        if (null === $metadata = $this->getAttributeMetadata($object, $attribute)) {
            return $context;
        }
        return array_merge($context, $metadata->getNormalizationContextForGroups($this->getGroups($context)));
    }
    /**
     * Computes the denormalization context merged with current one. Metadata always wins over global context, as more specific.
     *
     * @internal
     */
    protected function getAttributeDenormalizationContext(string $class, string $attribute, array $context): array
    {
        $context['deserialization_path'] = $context['deserialization_path'] ?? \false ? $context['deserialization_path'] . '.' . $attribute : $attribute;
        if (null === $metadata = $this->getAttributeMetadata($class, $attribute)) {
            return $context;
        }
        return array_merge($context, $metadata->getDenormalizationContextForGroups($this->getGroups($context)));
    }
    /**
     * @internal
     */
    protected function getAttributeMetadata(object|string $objectOrClass, string $attribute): ?AttributeMetadataInterface
    {
        if (!$this->classMetadataFactory) {
            return null;
        }
        return $this->classMetadataFactory->getMetadataFor($objectOrClass)->getAttributesMetadata()[$attribute] ?? null;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Serializer\Normalizer;

use _ContaoManager\Symfony\Component\Serializer\Exception\InvalidArgumentException;
use _ContaoManager\Symfony\Component\Serializer\Exception\NotNormalizableValueException;
use _ContaoManager\Symfony\Contracts\Translation\TranslatableInterface;
use _ContaoManager\Symfony\Contracts\Translation\TranslatorInterface;
final class TranslatableNormalizer implements NormalizerInterface
{
    public const NORMALIZATION_LOCALE_KEY = 'translatable_normalization_locale';
    private array $defaultContext = [self::NORMALIZATION_LOCALE_KEY => null];
    public function __construct(private readonly TranslatorInterface $translator, array $defaultContext = [])
    {
        $this->defaultContext = array_merge($this->defaultContext, $defaultContext);
    }
    /**
     * @throws InvalidArgumentException
     */
    public function normalize(mixed $object, ?string $format = null, array $context = []): string
    {
        if (!$object instanceof TranslatableInterface) {
            throw NotNormalizableValueException::createForUnexpectedDataType(\sprintf('The object must implement the "%s".', TranslatableInterface::class), $object, [TranslatableInterface::class]);
        }
        return $object->trans($this->translator, $context[self::NORMALIZATION_LOCALE_KEY] ?? $this->defaultContext[self::NORMALIZATION_LOCALE_KEY]);
    }
    public function supportsNormalization(mixed $data, ?string $format = null, array $context = []): bool
    {
        return $data instanceof TranslatableInterface;
    }
    public function getSupportedTypes(?string $format): array
    {
        return [TranslatableInterface::class => \true];
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Serializer\Normalizer;

use _ContaoManager\Symfony\Component\PropertyInfo\Type;
use _ContaoManager\Symfony\Component\Serializer\Exception\LogicException;
use _ContaoManager\Symfony\Component\Serializer\Exception\NotNormalizableValueException;
use _ContaoManager\Symfony\Component\Uid\AbstractUid;
use _ContaoManager\Symfony\Component\Uid\Uuid;
final class UidNormalizer implements NormalizerInterface, DenormalizerInterface, CacheableSupportsMethodInterface
{
    public const NORMALIZATION_FORMAT_KEY = 'uid_normalization_format';
    public const NORMALIZATION_FORMAT_CANONICAL = 'canonical';
    public const NORMALIZATION_FORMAT_BASE58 = 'base58';
    public const NORMALIZATION_FORMAT_BASE32 = 'base32';
    public const NORMALIZATION_FORMAT_RFC4122 = 'rfc4122';
    // RFC 9562 obsoleted RFC 4122 but the format is the same
    public const NORMALIZATION_FORMATS = [self::NORMALIZATION_FORMAT_CANONICAL, self::NORMALIZATION_FORMAT_BASE58, self::NORMALIZATION_FORMAT_BASE32, self::NORMALIZATION_FORMAT_RFC4122];
    private array $defaultContext = [self::NORMALIZATION_FORMAT_KEY => self::NORMALIZATION_FORMAT_CANONICAL];
    public function __construct(array $defaultContext = [])
    {
        $this->defaultContext = array_merge($this->defaultContext, $defaultContext);
    }
    public function getSupportedTypes(?string $format): array
    {
        return [AbstractUid::class => \true];
    }
    /**
     * @param AbstractUid $object
     */
    public function normalize(mixed $object, ?string $format = null, array $context = []): array|string|int|float|bool|\ArrayObject|null
    {
        return match ($context[self::NORMALIZATION_FORMAT_KEY] ?? $this->defaultContext[self::NORMALIZATION_FORMAT_KEY]) {
            self::NORMALIZATION_FORMAT_CANONICAL => (string) $object,
            self::NORMALIZATION_FORMAT_BASE58 => $object->toBase58(),
            self::NORMALIZATION_FORMAT_BASE32 => $object->toBase32(),
            self::NORMALIZATION_FORMAT_RFC4122 => $object->toRfc4122(),
            default => throw new LogicException(\sprintf('The "%s" format is not valid.', $context[self::NORMALIZATION_FORMAT_KEY] ?? $this->defaultContext[self::NORMALIZATION_FORMAT_KEY])),
        };
    }
    public function supportsNormalization(mixed $data, ?string $format = null, array $context = []): bool
    {
        return $data instanceof AbstractUid;
    }
    public function denormalize(mixed $data, string $type, ?string $format = null, array $context = []): mixed
    {
        try {
            if (AbstractUid::class === $type) {
                trigger_deprecation('symfony/serializer', '6.1', 'Denormalizing to an abstract class in "%s" is deprecated.', __CLASS__);
                return Uuid::fromString($data);
            }
            return $type::fromString($data);
        } catch (\InvalidArgumentException|\TypeError) {
            throw NotNormalizableValueException::createForUnexpectedDataType(\sprintf('The data is not a valid "%s" string representation.', $type), $data, [Type::BUILTIN_TYPE_STRING], $context['deserialization_path'] ?? null, \true);
        } catch (\Error $e) {
            // @deprecated remove this catch block in 7.0
            if (str_starts_with($e->getMessage(), 'Cannot instantiate abstract class')) {
                return $this->denormalize($data, AbstractUid::class, $format, $context);
            }
            throw $e;
        }
    }
    public function supportsDenormalization(mixed $data, string $type, ?string $format = null, array $context = []): bool
    {
        if (AbstractUid::class === $type) {
            trigger_deprecation('symfony/serializer', '6.1', 'Supporting denormalization for the "%s" type in "%s" is deprecated, use one of "%s" child class instead.', AbstractUid::class, __CLASS__, AbstractUid::class);
            return \true;
        }
        return is_subclass_of($type, AbstractUid::class, \true);
    }
    /**
     * @deprecated since Symfony 6.3, use "getSupportedTypes()" instead
     */
    public function hasCacheableSupportsMethod(): bool
    {
        trigger_deprecation('symfony/serializer', '6.3', 'The "%s()" method is deprecated, use "getSupportedTypes()" instead.', __METHOD__);
        return \true;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Serializer\Normalizer;

use _ContaoManager\Symfony\Component\Serializer\Exception\BadMethodCallException;
use _ContaoManager\Symfony\Component\Serializer\Exception\ExceptionInterface;
use _ContaoManager\Symfony\Component\Serializer\Exception\ExtraAttributesException;
use _ContaoManager\Symfony\Component\Serializer\Exception\InvalidArgumentException;
use _ContaoManager\Symfony\Component\Serializer\Exception\LogicException;
use _ContaoManager\Symfony\Component\Serializer\Exception\RuntimeException;
use _ContaoManager\Symfony\Component\Serializer\Exception\UnexpectedValueException;
/**
 * @author Jordi Boggiano <j.boggiano@seld.be>
 *
 * @method array getSupportedTypes(?string $format)
 */
interface DenormalizerInterface
{
    public const COLLECT_DENORMALIZATION_ERRORS = 'collect_denormalization_errors';
    /**
     * Denormalizes data back into an object of the given class.
     *
     * @param mixed       $data    Data to restore
     * @param string      $type    The expected class to instantiate
     * @param string|null $format  Format the given data was extracted from
     * @param array       $context Options available to the denormalizer
     *
     * @return mixed
     *
     * @throws BadMethodCallException   Occurs when the normalizer is not called in an expected context
     * @throws InvalidArgumentException Occurs when the arguments are not coherent or not supported
     * @throws UnexpectedValueException Occurs when the item cannot be hydrated with the given data
     * @throws ExtraAttributesException Occurs when the item doesn't have attribute to receive given data
     * @throws LogicException           Occurs when the normalizer is not supposed to denormalize
     * @throws RuntimeException         Occurs if the class cannot be instantiated
     * @throws ExceptionInterface       Occurs for all the other cases of errors
     */
    public function denormalize(mixed $data, string $type, ?string $format = null, array $context = []);
    /**
     * Checks whether the given class is supported for denormalization by this normalizer.
     *
     * @param mixed       $data    Data to denormalize from
     * @param string      $type    The class to which the data should be denormalized
     * @param string|null $format  The format being deserialized from
     * @param array       $context Options available to the denormalizer
     *
     * @return bool
     */
    public function supportsDenormalization(mixed $data, string $type, ?string $format = null);
    /**
     * Returns the types potentially supported by this denormalizer.
     *
     * For each supported formats (if applicable), the supported types should be
     * returned as keys, and each type should be mapped to a boolean indicating
     * if the result of supportsDenormalization() can be cached or not
     * (a result cannot be cached when it depends on the context or on the data.)
     * A null value means that the denormalizer does not support the corresponding
     * type.
     *
     * Use type "object" to match any classes or interfaces,
     * and type "*" to match any types.
     *
     * @return array<class-string|'*'|'object'|string, bool|null>
     */
    /* public function getSupportedTypes(?string $format): array; */
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Serializer\Normalizer;

/**
 * Defines the most basic interface a class must implement to be normalizable.
 *
 * If a normalizer is registered for the class and it doesn't implement
 * the Normalizable interfaces, the normalizer will be used instead.
 *
 * @author Jordi Boggiano <j.boggiano@seld.be>
 */
interface NormalizableInterface
{
    /**
     * Normalizes the object into an array of scalars|arrays.
     *
     * It is important to understand that the normalize() call should normalize
     * recursively all child objects of the implementor.
     *
     * @param NormalizerInterface $normalizer The normalizer is given so that you
     *                                        can use it to normalize objects contained within this object
     * @param string|null         $format     The format is optionally given to be able to normalize differently
     *                                        based on different output formats
     * @param array               $context    Options for normalizing this object
     */
    public function normalize(NormalizerInterface $normalizer, ?string $format = null, array $context = []): array|string|int|float|bool|\ArrayObject|null;
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Serializer\Normalizer;

use _ContaoManager\Symfony\Component\Serializer\Annotation\Ignore as LegacyIgnore;
use _ContaoManager\Symfony\Component\Serializer\Attribute\Ignore;
/**
 * Converts between objects with getter and setter methods and arrays.
 *
 * The normalization process looks at all public methods and calls the ones
 * which have a name starting with get and take no parameters. The result is a
 * map from property names (method name stripped of the get prefix and converted
 * to lower case) to property values. Property values are normalized through the
 * serializer.
 *
 * The denormalization first looks at the constructor of the given class to see
 * if any of the parameters have the same name as one of the properties. The
 * constructor is then called with all parameters or an exception is thrown if
 * any required parameters were not present as properties. Then the denormalizer
 * walks through the given map of property names to property values to see if a
 * setter method exists for any of the properties. If a setter exists it is
 * called with the property value. No automatic denormalization of the value
 * takes place.
 *
 * @author Nils Adermann <naderman@naderman.de>
 * @author Kévin Dunglas <dunglas@gmail.com>
 *
 * @final since Symfony 6.3
 */
class GetSetMethodNormalizer extends AbstractObjectNormalizer
{
    private static $reflectionCache = [];
    private static array $setterAccessibleCache = [];
    public function getSupportedTypes(?string $format): array
    {
        return ['object' => __CLASS__ === static::class || $this->hasCacheableSupportsMethod()];
    }
    /**
     * @param array $context
     */
    public function supportsNormalization(mixed $data, ?string $format = null): bool
    {
        return parent::supportsNormalization($data, $format) && $this->supports($data::class, \true);
    }
    /**
     * @param array $context
     */
    public function supportsDenormalization(mixed $data, string $type, ?string $format = null): bool
    {
        return parent::supportsDenormalization($data, $type, $format) && $this->supports($type, \false);
    }
    /**
     * @deprecated since Symfony 6.3, use "getSupportedTypes()" instead
     */
    public function hasCacheableSupportsMethod(): bool
    {
        trigger_deprecation('symfony/serializer', '6.3', 'The "%s()" method is deprecated, implement "%s::getSupportedTypes()" instead.', __METHOD__, get_debug_type($this));
        return __CLASS__ === static::class;
    }
    /**
     * Checks if the given class has any getter or setter method.
     */
    private function supports(string $class, bool $readAttributes): bool
    {
        if ($this->classDiscriminatorResolver?->getMappingForClass($class)) {
            return \true;
        }
        if (!isset(self::$reflectionCache[$class])) {
            self::$reflectionCache[$class] = new \ReflectionClass($class);
        }
        $reflection = self::$reflectionCache[$class];
        foreach ($reflection->getMethods(\ReflectionMethod::IS_PUBLIC) as $reflectionMethod) {
            if ($readAttributes ? $this->isGetMethod($reflectionMethod) : $this->isSetMethod($reflectionMethod)) {
                return \true;
            }
        }
        return \false;
    }
    /**
     * Checks if a method's name matches /^(get|is|has|can).+$/ and can be called non-statically without parameters.
     */
    private function isGetMethod(\ReflectionMethod $method): bool
    {
        return !$method->isStatic() && !($method->getAttributes(Ignore::class) || $method->getAttributes(LegacyIgnore::class)) && !$method->getNumberOfRequiredParameters() && !\in_array((string) $method->getReturnType(), ['void', 'never'], \true) && (2 < ($methodLength = \strlen($method->name)) && str_starts_with($method->name, 'is') && !ctype_lower($method->name[2]) || 3 < $methodLength && (str_starts_with($method->name, 'has') || str_starts_with($method->name, 'get') || str_starts_with($method->name, 'can')) && !ctype_lower($method->name[3]));
    }
    /**
     * Checks if a method's name matches /^set.+$/ and can be called non-statically with one parameter.
     */
    private function isSetMethod(\ReflectionMethod $method): bool
    {
        return !$method->isStatic() && !$method->getAttributes(Ignore::class) && 0 < $method->getNumberOfParameters() && 3 < \strlen($method->name) && str_starts_with($method->name, 'set') && !ctype_lower($method->name[3]);
    }
    protected function extractAttributes(object $object, ?string $format = null, array $context = []): array
    {
        $reflectionObject = new \ReflectionObject($object);
        $reflectionMethods = $reflectionObject->getMethods(\ReflectionMethod::IS_PUBLIC);
        $attributes = [];
        foreach ($reflectionMethods as $method) {
            if (!$this->isGetMethod($method)) {
                continue;
            }
            $attributeName = lcfirst(substr($method->name, str_starts_with($method->name, 'is') ? 2 : 3));
            if ($this->isAllowedAttribute($object, $attributeName, $format, $context)) {
                $attributes[] = $attributeName;
            }
        }
        return $attributes;
    }
    protected function getAttributeValue(object $object, string $attribute, ?string $format = null, array $context = []): mixed
    {
        $getter = 'get' . $attribute;
        if (method_exists($object, $getter) && \is_callable([$object, $getter])) {
            return $object->{$getter}();
        }
        $isser = 'is' . $attribute;
        if (method_exists($object, $isser) && \is_callable([$object, $isser])) {
            return $object->{$isser}();
        }
        $haser = 'has' . $attribute;
        if (method_exists($object, $haser) && \is_callable([$object, $haser])) {
            return $object->{$haser}();
        }
        $caner = 'can' . $attribute;
        if (method_exists($object, $caner) && \is_callable([$object, $caner])) {
            return $object->{$caner}();
        }
        return null;
    }
    /**
     * @return void
     */
    protected function setAttributeValue(object $object, string $attribute, mixed $value, ?string $format = null, array $context = [])
    {
        $setter = 'set' . $attribute;
        $key = $object::class . ':' . $setter;
        if (!isset(self::$setterAccessibleCache[$key])) {
            self::$setterAccessibleCache[$key] = method_exists($object, $setter) && \is_callable([$object, $setter]) && !(new \ReflectionMethod($object, $setter))->isStatic();
        }
        if (self::$setterAccessibleCache[$key]) {
            $object->{$setter}($value);
        }
    }
    protected function isAllowedAttribute($classOrObject, string $attribute, ?string $format = null, array $context = [])
    {
        if (!parent::isAllowedAttribute($classOrObject, $attribute, $format, $context)) {
            return \false;
        }
        $class = \is_object($classOrObject) ? $classOrObject::class : $classOrObject;
        if ($this->classDiscriminatorResolver?->getMappingForMappedObject($classOrObject)?->getTypeProperty() === $attribute) {
            return \true;
        }
        if (!isset(self::$reflectionCache[$class])) {
            self::$reflectionCache[$class] = new \ReflectionClass($class);
        }
        $reflection = self::$reflectionCache[$class];
        if ($context['_read_attributes'] ?? \true) {
            foreach (['get', 'is', 'has', 'can'] as $getterPrefix) {
                $getter = $getterPrefix . $attribute;
                $reflectionMethod = $reflection->hasMethod($getter) ? $reflection->getMethod($getter) : null;
                if ($reflectionMethod && $this->isGetMethod($reflectionMethod)) {
                    return \true;
                }
            }
            return \false;
        }
        $setter = 'set' . $attribute;
        if ($reflection->hasMethod($setter) && $this->isSetMethod($reflection->getMethod($setter))) {
            return \true;
        }
        $constructor = $reflection->getConstructor();
        if ($constructor && $constructor->isPublic()) {
            foreach ($constructor->getParameters() as $parameter) {
                if ($parameter->getName() === $attribute) {
                    return \true;
                }
            }
        }
        return \false;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Serializer\Normalizer;

use _ContaoManager\Symfony\Component\PropertyInfo\Type;
use _ContaoManager\Symfony\Component\Serializer\Exception\InvalidArgumentException;
use _ContaoManager\Symfony\Component\Serializer\Exception\NotNormalizableValueException;
/**
 * Normalizes a {@see \BackedEnum} enumeration to a string or an integer.
 *
 * @author Alexandre Daubois <alex.daubois@gmail.com>
 */
final class BackedEnumNormalizer implements NormalizerInterface, DenormalizerInterface, CacheableSupportsMethodInterface
{
    /**
     * If true, will denormalize any invalid value into null.
     */
    public const ALLOW_INVALID_VALUES = 'allow_invalid_values';
    public function getSupportedTypes(?string $format): array
    {
        return [\BackedEnum::class => \true];
    }
    public function normalize(mixed $object, ?string $format = null, array $context = []): int|string
    {
        if (!$object instanceof \BackedEnum) {
            throw new InvalidArgumentException('The data must belong to a backed enumeration.');
        }
        return $object->value;
    }
    public function supportsNormalization(mixed $data, ?string $format = null, array $context = []): bool
    {
        return $data instanceof \BackedEnum;
    }
    /**
     * @throws NotNormalizableValueException
     */
    public function denormalize(mixed $data, string $type, ?string $format = null, array $context = []): mixed
    {
        if (!is_subclass_of($type, \BackedEnum::class)) {
            throw new InvalidArgumentException('The data must belong to a backed enumeration.');
        }
        $allowInvalidValues = $context[self::ALLOW_INVALID_VALUES] ?? \false;
        if (null === $data || !\is_int($data) && !\is_string($data)) {
            if ($allowInvalidValues && !isset($context['not_normalizable_value_exceptions'])) {
                return null;
            }
            throw NotNormalizableValueException::createForUnexpectedDataType('The data is neither an integer nor a string, you should pass an integer or a string that can be parsed as an enumeration case of type ' . $type . '.', $data, [Type::BUILTIN_TYPE_INT, Type::BUILTIN_TYPE_STRING], $context['deserialization_path'] ?? null, \true);
        }
        try {
            return $type::from($data);
        } catch (\ValueError|\TypeError $e) {
            if ($allowInvalidValues && !isset($context['not_normalizable_value_exceptions'])) {
                return null;
            }
            throw NotNormalizableValueException::createForUnexpectedDataType('The data must belong to a backed enumeration of type ' . $type, $data, [Type::BUILTIN_TYPE_INT, Type::BUILTIN_TYPE_STRING], $context['deserialization_path'] ?? null, \true, 0, $e);
        }
    }
    public function supportsDenormalization(mixed $data, string $type, ?string $format = null, array $context = []): bool
    {
        return is_subclass_of($type, \BackedEnum::class);
    }
    /**
     * @deprecated since Symfony 6.3, use "getSupportedTypes()" instead
     */
    public function hasCacheableSupportsMethod(): bool
    {
        trigger_deprecation('symfony/serializer', '6.3', 'The "%s()" method is deprecated, use "getSupportedTypes()" instead.', __METHOD__);
        return \true;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Serializer\Normalizer;

use _ContaoManager\Symfony\Component\Serializer\NameConverter\NameConverterInterface;
use _ContaoManager\Symfony\Component\Validator\ConstraintViolationListInterface;
/**
 * A normalizer that normalizes a ConstraintViolationListInterface instance.
 *
 * This Normalizer implements RFC7807 {@link https://tools.ietf.org/html/rfc7807}.
 *
 * @author Grégoire Pineau <lyrixx@lyrixx.info>
 * @author Kévin Dunglas <dunglas@gmail.com>
 *
 * @final since Symfony 6.3
 */
class ConstraintViolationListNormalizer implements NormalizerInterface, CacheableSupportsMethodInterface
{
    public const INSTANCE = 'instance';
    public const STATUS = 'status';
    public const TITLE = 'title';
    public const TYPE = 'type';
    public const PAYLOAD_FIELDS = 'payload_fields';
    public function __construct(private readonly array $defaultContext = [], private readonly ?NameConverterInterface $nameConverter = null)
    {
    }
    public function getSupportedTypes(?string $format): array
    {
        return [ConstraintViolationListInterface::class => __CLASS__ === static::class || $this->hasCacheableSupportsMethod()];
    }
    public function normalize(mixed $object, ?string $format = null, array $context = []): array
    {
        if (\array_key_exists(self::PAYLOAD_FIELDS, $context)) {
            $payloadFieldsToSerialize = $context[self::PAYLOAD_FIELDS];
        } elseif (\array_key_exists(self::PAYLOAD_FIELDS, $this->defaultContext)) {
            $payloadFieldsToSerialize = $this->defaultContext[self::PAYLOAD_FIELDS];
        } else {
            $payloadFieldsToSerialize = [];
        }
        if (\is_array($payloadFieldsToSerialize) && [] !== $payloadFieldsToSerialize) {
            $payloadFieldsToSerialize = array_flip($payloadFieldsToSerialize);
        }
        $violations = [];
        $messages = [];
        foreach ($object as $violation) {
            $propertyPath = $violation->getPropertyPath();
            if (null !== $this->nameConverter) {
                $propertyPath = $this->normalizePropertyPath($propertyPath, \is_object($violation->getRoot()) ? \get_class($violation->getRoot()) : null, $format, $context);
            }
            $violationEntry = ['propertyPath' => $propertyPath, 'title' => $violation->getMessage(), 'template' => $violation->getMessageTemplate(), 'parameters' => $violation->getParameters()];
            if (null !== $code = $violation->getCode()) {
                $violationEntry['type'] = \sprintf('urn:uuid:%s', $code);
            }
            $constraint = $violation->getConstraint();
            if ([] !== $payloadFieldsToSerialize && $constraint && $constraint->payload && $payloadFields = null === $payloadFieldsToSerialize || \true === $payloadFieldsToSerialize ? $constraint->payload : array_intersect_key($constraint->payload, $payloadFieldsToSerialize)) {
                $violationEntry['payload'] = $payloadFields;
            }
            $violations[] = $violationEntry;
            $prefix = $propertyPath ? \sprintf('%s: ', $propertyPath) : '';
            $messages[] = $prefix . $violation->getMessage();
        }
        $result = ['type' => $context[self::TYPE] ?? $this->defaultContext[self::TYPE] ?? 'https://symfony.com/errors/validation', 'title' => $context[self::TITLE] ?? $this->defaultContext[self::TITLE] ?? 'Validation Failed'];
        if (null !== $status = $context[self::STATUS] ?? $this->defaultContext[self::STATUS] ?? null) {
            $result['status'] = $status;
        }
        if ($messages) {
            $result['detail'] = implode("\n", $messages);
        }
        if (null !== $instance = $context[self::INSTANCE] ?? $this->defaultContext[self::INSTANCE] ?? null) {
            $result['instance'] = $instance;
        }
        return $result + ['violations' => $violations];
    }
    private function normalizePropertyPath(string $propertyPath, ?string $class, ?string $format, array $context): string
    {
        if (!str_contains($propertyPath, '.')) {
            return $this->nameConverter->normalize($propertyPath, $class, $format, $context);
        }
        $result = [];
        $currentClass = $class;
        foreach (explode('.', $propertyPath) as $segment) {
            $subscript = '';
            $propertyName = $segment;
            if (\false !== $bracketPos = strpos($segment, '[')) {
                $propertyName = substr($segment, 0, $bracketPos);
                $subscript = substr($segment, $bracketPos);
            }
            $result[] = $this->nameConverter->normalize($propertyName, $currentClass, $format, $context) . $subscript;
            $currentClass = $this->getPropertyClassFromReflection($currentClass, $propertyName);
        }
        return implode('.', $result);
    }
    private function getPropertyClassFromReflection(?string $class, string $property): ?string
    {
        if (null === $class) {
            return null;
        }
        try {
            $type = (new \ReflectionProperty($class, $property))->getType();
            if ($type instanceof \ReflectionNamedType && !$type->isBuiltin()) {
                return $type->getName();
            }
        } catch (\ReflectionException) {
        }
        return null;
    }
    /**
     * @param array $context
     */
    public function supportsNormalization(mixed $data, ?string $format = null): bool
    {
        return $data instanceof ConstraintViolationListInterface;
    }
    /**
     * @deprecated since Symfony 6.3, use "getSupportedTypes()" instead
     */
    public function hasCacheableSupportsMethod(): bool
    {
        trigger_deprecation('symfony/serializer', '6.3', 'The "%s()" method is deprecated, implement "%s::getSupportedTypes()" instead.', __METHOD__, get_debug_type($this));
        return __CLASS__ === static::class;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Serializer\Normalizer;

use _ContaoManager\Symfony\Component\Serializer\Exception\CircularReferenceException;
use _ContaoManager\Symfony\Component\Serializer\Exception\ExceptionInterface;
use _ContaoManager\Symfony\Component\Serializer\Exception\InvalidArgumentException;
use _ContaoManager\Symfony\Component\Serializer\Exception\LogicException;
/**
 * @author Jordi Boggiano <j.boggiano@seld.be>
 *
 * @method array getSupportedTypes(?string $format)
 */
interface NormalizerInterface
{
    /**
     * Normalizes an object into a set of arrays/scalars.
     *
     * @param mixed       $object  Object to normalize
     * @param string|null $format  Format the normalization result will be encoded as
     * @param array       $context Context options for the normalizer
     *
     * @return array|string|int|float|bool|\ArrayObject|null \ArrayObject is used to make sure an empty object is encoded as an object not an array
     *
     * @throws InvalidArgumentException   Occurs when the object given is not a supported type for the normalizer
     * @throws CircularReferenceException Occurs when the normalizer detects a circular reference when no circular
     *                                    reference handler can fix it
     * @throws LogicException             Occurs when the normalizer is not called in an expected context
     * @throws ExceptionInterface         Occurs for all the other cases of errors
     */
    public function normalize(mixed $object, ?string $format = null, array $context = []);
    /**
     * Checks whether the given class is supported for normalization by this normalizer.
     *
     * @param mixed       $data    Data to normalize
     * @param string|null $format  The format being (de-)serialized from or into
     * @param array       $context Context options for the normalizer
     *
     * @return bool
     */
    public function supportsNormalization(mixed $data, ?string $format = null);
    /**
     * Returns the types potentially supported by this normalizer.
     *
     * For each supported formats (if applicable), the supported types should be
     * returned as keys, and each type should be mapped to a boolean indicating
     * if the result of supportsNormalization() can be cached or not
     * (a result cannot be cached when it depends on the context or on the data.)
     * A null value means that the normalizer does not support the corresponding
     * type.
     *
     * Use type "object" to match any classes or interfaces,
     * and type "*" to match any types.
     *
     * @return array<class-string|'*'|'object'|string, bool|null>
     */
    /* public function getSupportedTypes(?string $format): array; */
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Serializer\Normalizer;

/**
 * @author Joel Wurtz <joel.wurtz@gmail.com>
 */
trait DenormalizerAwareTrait
{
    /**
     * @var DenormalizerInterface
     */
    protected $denormalizer;
    /**
     * @return void
     */
    public function setDenormalizer(DenormalizerInterface $denormalizer)
    {
        $this->denormalizer = $denormalizer;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Serializer;

/**
 * @author Joel Wurtz <joel.wurtz@gmail.com>
 */
trait SerializerAwareTrait
{
    /**
     * @var SerializerInterface
     */
    protected $serializer;
    /**
     * @return void
     */
    public function setSerializer(SerializerInterface $serializer)
    {
        $this->serializer = $serializer;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Serializer\DependencyInjection;

use _ContaoManager\Symfony\Component\DependencyInjection\Argument\BoundArgument;
use _ContaoManager\Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Compiler\PriorityTaggedServiceTrait;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerBuilder;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\RuntimeException;
use _ContaoManager\Symfony\Component\DependencyInjection\Reference;
use _ContaoManager\Symfony\Component\Serializer\Debug\TraceableEncoder;
use _ContaoManager\Symfony\Component\Serializer\Debug\TraceableNormalizer;
/**
 * Adds all services with the tags "serializer.encoder" and "serializer.normalizer" as
 * encoders and normalizers to the "serializer" service.
 *
 * @author Javier Lopez <f12loalf@gmail.com>
 * @author Robin Chalas <robin.chalas@gmail.com>
 */
class SerializerPass implements CompilerPassInterface
{
    use PriorityTaggedServiceTrait;
    /**
     * @return void
     */
    public function process(ContainerBuilder $container)
    {
        if (!$container->hasDefinition('serializer')) {
            return;
        }
        if (!$normalizers = $this->findAndSortTaggedServices('serializer.normalizer', $container)) {
            throw new RuntimeException('You must tag at least one service as "serializer.normalizer" to use the "serializer" service.');
        }
        if (!$encoders = $this->findAndSortTaggedServices('serializer.encoder', $container)) {
            throw new RuntimeException('You must tag at least one service as "serializer.encoder" to use the "serializer" service.');
        }
        if ($container->hasParameter('serializer.default_context')) {
            $defaultContext = $container->getParameter('serializer.default_context');
            foreach (array_merge($normalizers, $encoders) as $service) {
                $definition = $container->getDefinition($service);
                $definition->setBindings(['array $defaultContext' => new BoundArgument($defaultContext, \false)] + $definition->getBindings());
            }
            $container->getParameterBag()->remove('serializer.default_context');
            $container->getDefinition('serializer')->setArgument('$defaultContext', $defaultContext);
        }
        if ($container->getParameter('kernel.debug') && $container->hasDefinition('serializer.data_collector')) {
            foreach ($normalizers as $i => $normalizer) {
                $normalizers[$i] = $container->register('.debug.serializer.normalizer.' . $normalizer, TraceableNormalizer::class)->setArguments([$normalizer, new Reference('serializer.data_collector')]);
            }
            foreach ($encoders as $i => $encoder) {
                $encoders[$i] = $container->register('.debug.serializer.encoder.' . $encoder, TraceableEncoder::class)->setArguments([$encoder, new Reference('serializer.data_collector')]);
            }
        }
        $serializerDefinition = $container->getDefinition('serializer');
        $serializerDefinition->replaceArgument(0, $normalizers);
        $serializerDefinition->replaceArgument(1, $encoders);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Serializer\Exception;

/**
 * LogicException.
 *
 * @author Lukas Kahwe Smith <smith@pooteeweet.org>
 */
class LogicException extends \LogicException implements ExceptionInterface
{
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Serializer\Exception;

/**
 * Base exception interface.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
interface ExceptionInterface extends \Throwable
{
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Serializer\Exception;

/**
 * @author Maxime VEBER <maxime.veber@nekland.fr>
 */
class MissingConstructorArgumentsException extends RuntimeException
{
    /**
     * @param string[]          $missingArguments
     * @param class-string|null $class
     */
    public function __construct(string $message, int $code = 0, ?\Throwable $previous = null, private array $missingArguments = [], private ?string $class = null)
    {
        parent::__construct($message, $code, $previous);
    }
    /**
     * @return string[]
     */
    public function getMissingConstructorArguments(): array
    {
        return $this->missingArguments;
    }
    /**
     * @return class-string|null
     */
    public function getClass(): ?string
    {
        return $this->class;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Serializer\Exception;

/**
 * UnexpectedValueException.
 *
 * @author Lukas Kahwe Smith <smith@pooteeweet.org>
 */
class UnexpectedValueException extends \UnexpectedValueException implements ExceptionInterface
{
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Serializer\Exception;

/**
 * RuntimeException.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
class RuntimeException extends \RuntimeException implements ExceptionInterface
{
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Serializer\Exception;

/**
 * @author Christian Flothmann <christian.flothmann@sensiolabs.de>
 */
class NotNormalizableValueException extends UnexpectedValueException
{
    private ?string $currentType = null;
    private ?array $expectedTypes = null;
    private ?string $path = null;
    private bool $useMessageForUser = \false;
    /**
     * @param string[] $expectedTypes
     * @param bool     $useMessageForUser If the message passed to this exception is something that can be shown
     *                                    safely to your user. In other words, avoid catching other exceptions and
     *                                    passing their message directly to this class.
     */
    public static function createForUnexpectedDataType(string $message, mixed $data, array $expectedTypes, ?string $path = null, bool $useMessageForUser = \false, int $code = 0, ?\Throwable $previous = null): self
    {
        $self = new self($message, $code, $previous);
        $self->currentType = get_debug_type($data);
        $self->expectedTypes = $expectedTypes;
        $self->path = $path;
        $self->useMessageForUser = $useMessageForUser;
        return $self;
    }
    public function getCurrentType(): ?string
    {
        return $this->currentType;
    }
    /**
     * @return string[]|null
     */
    public function getExpectedTypes(): ?array
    {
        return $this->expectedTypes;
    }
    public function getPath(): ?string
    {
        return $this->path;
    }
    public function canUseMessageForUser(): ?bool
    {
        return $this->useMessageForUser;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Serializer\Exception;

/**
 * InvalidArgumentException.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
class InvalidArgumentException extends \InvalidArgumentException implements ExceptionInterface
{
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Serializer\Exception;

/**
 * CircularReferenceException.
 *
 * @author Kévin Dunglas <dunglas@gmail.com>
 */
class CircularReferenceException extends RuntimeException
{
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Serializer\Exception;

class BadMethodCallException extends \BadMethodCallException implements ExceptionInterface
{
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Serializer\Exception;

/**
 * MappingException.
 *
 * @author Kévin Dunglas <dunglas@gmail.com>
 */
class MappingException extends RuntimeException
{
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Serializer\Exception;

/**
 * UnsupportedException.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
class UnsupportedException extends InvalidArgumentException
{
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Serializer\Exception;

/**
 * @author Christian Flothmann <christian.flothmann@sensiolabs.de>
 */
class NotEncodableValueException extends UnexpectedValueException
{
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Serializer\Exception;

/**
 * @author Grégoire Pineau <lyrixx@lyrixx.info>
 */
class PartialDenormalizationException extends UnexpectedValueException
{
    /**
     * @param NotNormalizableValueException[] $errors
     */
    public function __construct(private mixed $data, private array $errors)
    {
    }
    /**
     * @return mixed
     */
    public function getData()
    {
        return $this->data;
    }
    /**
     * @return NotNormalizableValueException[]
     */
    public function getErrors(): array
    {
        return $this->errors;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Serializer\Exception;

/**
 * @author Konstantin Myakshin <molodchick@gmail.com>
 */
class UnsupportedFormatException extends NotEncodableValueException
{
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Serializer\Exception;

/**
 * ExtraAttributesException.
 *
 * @author Julien DIDIER <julien@didier.io>
 */
class ExtraAttributesException extends RuntimeException
{
    public function __construct(private readonly array $extraAttributes, ?\Throwable $previous = null)
    {
        $msg = \sprintf('Extra attributes are not allowed ("%s" %s unknown).', implode('", "', $extraAttributes), \count($extraAttributes) > 1 ? 'are' : 'is');
        parent::__construct($msg, 0, $previous);
    }
    /**
     * Get the extra attributes that are not allowed.
     */
    public function getExtraAttributes(): array
    {
        return $this->extraAttributes;
    }
}
{
    "name": "symfony\/serializer",
    "type": "library",
    "description": "Handles serializing and deserializing data structures, including object graphs, into array structures or other formats like XML and JSON.",
    "keywords": [],
    "homepage": "https:\/\/symfony.com",
    "license": "MIT",
    "authors": [
        {
            "name": "Fabien Potencier",
            "email": "fabien@symfony.com"
        },
        {
            "name": "Symfony Community",
            "homepage": "https:\/\/symfony.com\/contributors"
        }
    ],
    "require": {
        "php": ">=8.1",
        "symfony\/deprecation-contracts": "^2.5|^3",
        "symfony\/polyfill-ctype": "~1.8"
    },
    "require-dev": {
        "doctrine\/annotations": "^1.12|^2",
        "seld\/jsonlint": "^1.10",
        "phpdocumentor\/reflection-docblock": "^3.2|^4.0|^5.0",
        "symfony\/cache": "^5.4|^6.0|^7.0",
        "symfony\/config": "^5.4|^6.0|^7.0",
        "symfony\/console": "^5.4|^6.0|^7.0",
        "symfony\/dependency-injection": "^5.4|^6.0|^7.0",
        "symfony\/error-handler": "^5.4|^6.0|^7.0",
        "symfony\/filesystem": "^5.4|^6.0|^7.0",
        "symfony\/form": "^5.4|^6.0|^7.0",
        "symfony\/http-foundation": "^5.4|^6.0|^7.0",
        "symfony\/http-kernel": "^5.4|^6.0|^7.0",
        "symfony\/messenger": "^5.4|^6.0|^7.0",
        "symfony\/mime": "^5.4|^6.0|^7.0",
        "symfony\/property-access": "^5.4.26|^6.3|^7.0",
        "symfony\/property-info": "^5.4.24|^6.2.11|^7.0",
        "symfony\/translation-contracts": "^2.5|^3",
        "symfony\/uid": "^5.4|^6.0|^7.0",
        "symfony\/validator": "^6.4|^7.0",
        "symfony\/var-dumper": "^5.4|^6.0|^7.0",
        "symfony\/var-exporter": "^5.4|^6.0|^7.0",
        "symfony\/yaml": "^5.4|^6.0|^7.0"
    },
    "conflict": {
        "doctrine\/annotations": "<1.12",
        "phpdocumentor\/reflection-docblock": "<3.2.2",
        "phpdocumentor\/type-resolver": "<1.4.0",
        "symfony\/dependency-injection": "<5.4",
        "symfony\/property-access": "<5.4",
        "symfony\/property-info": "<5.4.24|>=6,<6.2.11",
        "symfony\/validator": "<6.4",
        "symfony\/uid": "<5.4",
        "symfony\/yaml": "<5.4"
    },
    "autoload": {
        "psr-4": {
            "_ContaoManager\\Symfony\\Component\\Serializer\\": ""
        },
        "exclude-from-classmap": [
            "\/Tests\/"
        ]
    },
    "minimum-stability": "dev"
}<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Serializer\Debug;

use _ContaoManager\Symfony\Component\Serializer\DataCollector\SerializerDataCollector;
use _ContaoManager\Symfony\Component\Serializer\Encoder\DecoderInterface;
use _ContaoManager\Symfony\Component\Serializer\Encoder\EncoderInterface;
use _ContaoManager\Symfony\Component\Serializer\Encoder\NormalizationAwareInterface;
use _ContaoManager\Symfony\Component\Serializer\SerializerAwareInterface;
use _ContaoManager\Symfony\Component\Serializer\SerializerInterface;
/**
 * Collects some data about encoding.
 *
 * @author Mathias Arlaud <mathias.arlaud@gmail.com>
 *
 * @final
 */
class TraceableEncoder implements EncoderInterface, DecoderInterface, SerializerAwareInterface
{
    public function __construct(private EncoderInterface|DecoderInterface $encoder, private SerializerDataCollector $dataCollector)
    {
    }
    public function encode(mixed $data, string $format, array $context = []): string
    {
        if (!$this->encoder instanceof EncoderInterface) {
            throw new \BadMethodCallException(\sprintf('The "%s()" method cannot be called as nested encoder doesn\'t implements "%s".', __METHOD__, EncoderInterface::class));
        }
        $startTime = microtime(\true);
        $encoded = $this->encoder->encode($data, $format, $context);
        $time = microtime(\true) - $startTime;
        if ($traceId = $context[TraceableSerializer::DEBUG_TRACE_ID] ?? null) {
            $this->dataCollector->collectEncoding($traceId, $this->encoder::class, $time);
        }
        return $encoded;
    }
    public function supportsEncoding(string $format, array $context = []): bool
    {
        if (!$this->encoder instanceof EncoderInterface) {
            return \false;
        }
        return $this->encoder->supportsEncoding($format, $context);
    }
    public function decode(string $data, string $format, array $context = []): mixed
    {
        if (!$this->encoder instanceof DecoderInterface) {
            throw new \BadMethodCallException(\sprintf('The "%s()" method cannot be called as nested encoder doesn\'t implements "%s".', __METHOD__, DecoderInterface::class));
        }
        $startTime = microtime(\true);
        $encoded = $this->encoder->decode($data, $format, $context);
        $time = microtime(\true) - $startTime;
        if ($traceId = $context[TraceableSerializer::DEBUG_TRACE_ID] ?? null) {
            $this->dataCollector->collectDecoding($traceId, $this->encoder::class, $time);
        }
        return $encoded;
    }
    public function supportsDecoding(string $format, array $context = []): bool
    {
        if (!$this->encoder instanceof DecoderInterface) {
            return \false;
        }
        return $this->encoder->supportsDecoding($format, $context);
    }
    public function setSerializer(SerializerInterface $serializer): void
    {
        if (!$this->encoder instanceof SerializerAwareInterface) {
            return;
        }
        $this->encoder->setSerializer($serializer);
    }
    public function needsNormalization(): bool
    {
        return !$this->encoder instanceof NormalizationAwareInterface;
    }
    /**
     * Proxies all method calls to the original encoder.
     */
    public function __call(string $method, array $arguments): mixed
    {
        return $this->encoder->{$method}(...$arguments);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Serializer\Debug;

use _ContaoManager\Symfony\Component\Serializer\DataCollector\SerializerDataCollector;
use _ContaoManager\Symfony\Component\Serializer\Encoder\DecoderInterface;
use _ContaoManager\Symfony\Component\Serializer\Encoder\EncoderInterface;
use _ContaoManager\Symfony\Component\Serializer\Normalizer\CacheableSupportsMethodInterface;
use _ContaoManager\Symfony\Component\Serializer\Normalizer\DenormalizerInterface;
use _ContaoManager\Symfony\Component\Serializer\Normalizer\NormalizerInterface;
use _ContaoManager\Symfony\Component\Serializer\SerializerInterface;
/**
 * Collects some data about serialization.
 *
 * @author Mathias Arlaud <mathias.arlaud@gmail.com>
 *
 * @final
 */
class TraceableSerializer implements SerializerInterface, NormalizerInterface, DenormalizerInterface, EncoderInterface, DecoderInterface
{
    public const DEBUG_TRACE_ID = 'debug_trace_id';
    public function __construct(private SerializerInterface&NormalizerInterface&DenormalizerInterface&EncoderInterface&DecoderInterface $serializer, private SerializerDataCollector $dataCollector)
    {
        if (!method_exists($serializer, 'getSupportedTypes')) {
            trigger_deprecation('symfony/serializer', '6.3', 'Not implementing the "NormalizerInterface::getSupportedTypes()" in "%s" is deprecated.', get_debug_type($serializer));
        }
    }
    public function serialize(mixed $data, string $format, array $context = []): string
    {
        $context[self::DEBUG_TRACE_ID] = $traceId = uniqid('', \true);
        $startTime = microtime(\true);
        $result = $this->serializer->serialize($data, $format, $context);
        $time = microtime(\true) - $startTime;
        $caller = $this->getCaller(__FUNCTION__, SerializerInterface::class);
        $this->dataCollector->collectSerialize($traceId, $data, $format, $context, $time, $caller);
        return $result;
    }
    public function deserialize(mixed $data, string $type, string $format, array $context = []): mixed
    {
        $context[self::DEBUG_TRACE_ID] = $traceId = uniqid('', \true);
        $startTime = microtime(\true);
        $result = $this->serializer->deserialize($data, $type, $format, $context);
        $time = microtime(\true) - $startTime;
        $caller = $this->getCaller(__FUNCTION__, SerializerInterface::class);
        $this->dataCollector->collectDeserialize($traceId, $data, $type, $format, $context, $time, $caller);
        return $result;
    }
    public function normalize(mixed $object, ?string $format = null, array $context = []): array|string|int|float|bool|\ArrayObject|null
    {
        $context[self::DEBUG_TRACE_ID] = $traceId = uniqid('', \true);
        $startTime = microtime(\true);
        $result = $this->serializer->normalize($object, $format, $context);
        $time = microtime(\true) - $startTime;
        $caller = $this->getCaller(__FUNCTION__, NormalizerInterface::class);
        $this->dataCollector->collectNormalize($traceId, $object, $format, $context, $time, $caller);
        return $result;
    }
    public function denormalize(mixed $data, string $type, ?string $format = null, array $context = []): mixed
    {
        $context[self::DEBUG_TRACE_ID] = $traceId = uniqid('', \true);
        $startTime = microtime(\true);
        $result = $this->serializer->denormalize($data, $type, $format, $context);
        $time = microtime(\true) - $startTime;
        $caller = $this->getCaller(__FUNCTION__, DenormalizerInterface::class);
        $this->dataCollector->collectDenormalize($traceId, $data, $type, $format, $context, $time, $caller);
        return $result;
    }
    public function encode(mixed $data, string $format, array $context = []): string
    {
        $context[self::DEBUG_TRACE_ID] = $traceId = uniqid('', \true);
        $startTime = microtime(\true);
        $result = $this->serializer->encode($data, $format, $context);
        $time = microtime(\true) - $startTime;
        $caller = $this->getCaller(__FUNCTION__, EncoderInterface::class);
        $this->dataCollector->collectEncode($traceId, $data, $format, $context, $time, $caller);
        return $result;
    }
    public function decode(string $data, string $format, array $context = []): mixed
    {
        $context[self::DEBUG_TRACE_ID] = $traceId = uniqid('', \true);
        $startTime = microtime(\true);
        $result = $this->serializer->decode($data, $format, $context);
        $time = microtime(\true) - $startTime;
        $caller = $this->getCaller(__FUNCTION__, DecoderInterface::class);
        $this->dataCollector->collectDecode($traceId, $data, $format, $context, $time, $caller);
        return $result;
    }
    public function getSupportedTypes(?string $format): array
    {
        // @deprecated remove condition in 7.0
        if (!method_exists($this->serializer, 'getSupportedTypes')) {
            return ['*' => $this->serializer instanceof CacheableSupportsMethodInterface && $this->serializer->hasCacheableSupportsMethod()];
        }
        return $this->serializer->getSupportedTypes($format);
    }
    public function supportsNormalization(mixed $data, ?string $format = null, array $context = []): bool
    {
        return $this->serializer->supportsNormalization($data, $format, $context);
    }
    public function supportsDenormalization(mixed $data, string $type, ?string $format = null, array $context = []): bool
    {
        return $this->serializer->supportsDenormalization($data, $type, $format, $context);
    }
    public function supportsEncoding(string $format, array $context = []): bool
    {
        return $this->serializer->supportsEncoding($format, $context);
    }
    public function supportsDecoding(string $format, array $context = []): bool
    {
        return $this->serializer->supportsDecoding($format, $context);
    }
    /**
     * Proxies all method calls to the original serializer.
     */
    public function __call(string $method, array $arguments): mixed
    {
        return $this->serializer->{$method}(...$arguments);
    }
    private function getCaller(string $method, string $interface): array
    {
        $trace = debug_backtrace(\DEBUG_BACKTRACE_IGNORE_ARGS, 8);
        $file = $trace[0]['file'];
        $line = $trace[0]['line'];
        for ($i = 1; $i < 8; ++$i) {
            if (isset($trace[$i]['class'], $trace[$i]['function']) && $method === $trace[$i]['function'] && is_a($trace[$i]['class'], $interface, \true)) {
                $file = $trace[$i]['file'] ?? $trace[$i + 1]['file'];
                $line = $trace[$i]['line'] ?? $trace[$i + 1]['line'];
                break;
            }
        }
        $name = str_replace('\\', '/', $file);
        $name = substr($name, strrpos($name, '/') + 1);
        return compact('name', 'file', 'line');
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Serializer\Debug;

use _ContaoManager\Symfony\Component\Serializer\DataCollector\SerializerDataCollector;
use _ContaoManager\Symfony\Component\Serializer\Normalizer\CacheableSupportsMethodInterface;
use _ContaoManager\Symfony\Component\Serializer\Normalizer\DenormalizerAwareInterface;
use _ContaoManager\Symfony\Component\Serializer\Normalizer\DenormalizerInterface;
use _ContaoManager\Symfony\Component\Serializer\Normalizer\NormalizerAwareInterface;
use _ContaoManager\Symfony\Component\Serializer\Normalizer\NormalizerInterface;
use _ContaoManager\Symfony\Component\Serializer\SerializerAwareInterface;
use _ContaoManager\Symfony\Component\Serializer\SerializerInterface;
/**
 * Collects some data about normalization.
 *
 * @author Mathias Arlaud <mathias.arlaud@gmail.com>
 *
 * @final
 */
class TraceableNormalizer implements NormalizerInterface, DenormalizerInterface, SerializerAwareInterface, NormalizerAwareInterface, DenormalizerAwareInterface, CacheableSupportsMethodInterface
{
    public function __construct(private NormalizerInterface|DenormalizerInterface $normalizer, private SerializerDataCollector $dataCollector)
    {
        if (!method_exists($normalizer, 'getSupportedTypes')) {
            trigger_deprecation('symfony/serializer', '6.3', 'Not implementing the "NormalizerInterface::getSupportedTypes()" in "%s" is deprecated.', get_debug_type($normalizer));
        }
    }
    public function getSupportedTypes(?string $format): array
    {
        // @deprecated remove condition in 7.0
        if (!method_exists($this->normalizer, 'getSupportedTypes')) {
            return ['*' => $this->normalizer instanceof CacheableSupportsMethodInterface && $this->normalizer->hasCacheableSupportsMethod()];
        }
        return $this->normalizer->getSupportedTypes($format);
    }
    public function normalize(mixed $object, ?string $format = null, array $context = []): array|string|int|float|bool|\ArrayObject|null
    {
        if (!$this->normalizer instanceof NormalizerInterface) {
            throw new \BadMethodCallException(\sprintf('The "%s()" method cannot be called as nested normalizer doesn\'t implements "%s".', __METHOD__, NormalizerInterface::class));
        }
        $startTime = microtime(\true);
        $normalized = $this->normalizer->normalize($object, $format, $context);
        $time = microtime(\true) - $startTime;
        if ($traceId = $context[TraceableSerializer::DEBUG_TRACE_ID] ?? null) {
            $this->dataCollector->collectNormalization($traceId, $this->normalizer::class, $time);
        }
        return $normalized;
    }
    public function supportsNormalization(mixed $data, ?string $format = null, array $context = []): bool
    {
        if (!$this->normalizer instanceof NormalizerInterface) {
            return \false;
        }
        return $this->normalizer->supportsNormalization($data, $format, $context);
    }
    public function denormalize(mixed $data, string $type, ?string $format = null, array $context = []): mixed
    {
        if (!$this->normalizer instanceof DenormalizerInterface) {
            throw new \BadMethodCallException(\sprintf('The "%s()" method cannot be called as nested normalizer doesn\'t implements "%s".', __METHOD__, DenormalizerInterface::class));
        }
        $startTime = microtime(\true);
        $denormalized = $this->normalizer->denormalize($data, $type, $format, $context);
        $time = microtime(\true) - $startTime;
        if ($traceId = $context[TraceableSerializer::DEBUG_TRACE_ID] ?? null) {
            $this->dataCollector->collectDenormalization($traceId, $this->normalizer::class, $time);
        }
        return $denormalized;
    }
    public function supportsDenormalization(mixed $data, string $type, ?string $format = null, array $context = []): bool
    {
        if (!$this->normalizer instanceof DenormalizerInterface) {
            return \false;
        }
        return $this->normalizer->supportsDenormalization($data, $type, $format, $context);
    }
    public function setSerializer(SerializerInterface $serializer): void
    {
        if (!$this->normalizer instanceof SerializerAwareInterface) {
            return;
        }
        $this->normalizer->setSerializer($serializer);
    }
    public function setNormalizer(NormalizerInterface $normalizer): void
    {
        if (!$this->normalizer instanceof NormalizerAwareInterface) {
            return;
        }
        $this->normalizer->setNormalizer($normalizer);
    }
    public function setDenormalizer(DenormalizerInterface $denormalizer): void
    {
        if (!$this->normalizer instanceof DenormalizerAwareInterface) {
            return;
        }
        $this->normalizer->setDenormalizer($denormalizer);
    }
    /**
     * @deprecated since Symfony 6.3, use "getSupportedTypes()" instead
     */
    public function hasCacheableSupportsMethod(): bool
    {
        trigger_deprecation('symfony/serializer', '6.3', 'The "%s()" method is deprecated, implement "%s::getSupportedTypes()" instead.', __METHOD__, get_debug_type($this->normalizer));
        return $this->normalizer instanceof CacheableSupportsMethodInterface && $this->normalizer->hasCacheableSupportsMethod();
    }
    /**
     * Proxies all method calls to the original normalizer.
     */
    public function __call(string $method, array $arguments): mixed
    {
        return $this->normalizer->{$method}(...$arguments);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Symfony\Polyfill\Php80;

/**
 * @author Fedonyuk Anton <info@ensostudio.ru>
 *
 * @internal
 */
class PhpToken implements \Stringable
{
    /**
     * @var int
     */
    public $id;
    /**
     * @var string
     */
    public $text;
    /**
     * @var -1|positive-int
     */
    public $line;
    /**
     * @var int
     */
    public $pos;
    /**
     * @param -1|positive-int $line
     */
    public function __construct(int $id, string $text, int $line = -1, int $position = -1)
    {
        $this->id = $id;
        $this->text = $text;
        $this->line = $line;
        $this->pos = $position;
    }
    public function getTokenName(): ?string
    {
        if ('UNKNOWN' === $name = token_name($this->id)) {
            $name = \strlen($this->text) > 1 || \ord($this->text) < 32 ? null : $this->text;
        }
        return $name;
    }
    /**
     * @param int|string|array $kind
     */
    public function is($kind): bool
    {
        foreach ((array) $kind as $value) {
            if (\in_array($value, [$this->id, $this->text], \true)) {
                return \true;
            }
        }
        return \false;
    }
    public function isIgnorable(): bool
    {
        return \in_array($this->id, [\T_WHITESPACE, \T_COMMENT, \T_DOC_COMMENT, \T_OPEN_TAG], \true);
    }
    public function __toString(): string
    {
        return (string) $this->text;
    }
    /**
     * @return list<static>
     */
    public static function tokenize(string $code, int $flags = 0): array
    {
        $line = 1;
        $position = 0;
        $tokens = token_get_all($code, $flags);
        foreach ($tokens as $index => $token) {
            if (\is_string($token)) {
                $id = \ord($token);
                $text = $token;
            } else {
                [$id, $text, $line] = $token;
            }
            $tokens[$index] = new static($id, $text, $line, $position);
            $position += \strlen($text);
        }
        return $tokens;
    }
}
Copyright (c) 2020-present Fabien Potencier

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is furnished
to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

if (\PHP_VERSION_ID < 80000 && extension_loaded('tokenizer')) {
    class PhpToken extends Symfony\Polyfill\Php80\PhpToken
    {
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

if (\PHP_VERSION_ID < 80000) {
    class ValueError extends Error
    {
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

#[Attribute(Attribute::TARGET_CLASS)]
final class Attribute
{
    public const TARGET_CLASS = 1;
    public const TARGET_FUNCTION = 2;
    public const TARGET_METHOD = 4;
    public const TARGET_PROPERTY = 8;
    public const TARGET_CLASS_CONSTANT = 16;
    public const TARGET_PARAMETER = 32;
    public const TARGET_ALL = 63;
    public const IS_REPEATABLE = 64;

    /** @var int */
    public $flags;

    public function __construct(int $flags = self::TARGET_ALL)
    {
        $this->flags = $flags;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

if (\PHP_VERSION_ID < 80000) {
    class UnhandledMatchError extends Error
    {
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

if (\PHP_VERSION_ID < 80000) {
    interface Stringable
    {
        /**
         * @return string
         */
        public function __toString();
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

use Symfony\Polyfill\Php80 as p;

if (\PHP_VERSION_ID >= 80000) {
    return;
}

if (!defined('FILTER_VALIDATE_BOOL') && defined('FILTER_VALIDATE_BOOLEAN')) {
    define('FILTER_VALIDATE_BOOL', \FILTER_VALIDATE_BOOLEAN);
}

if (!function_exists('fdiv')) {
    function fdiv(float $num1, float $num2): float { return p\Php80::fdiv($num1, $num2); }
}
if (!function_exists('preg_last_error_msg')) {
    function preg_last_error_msg(): string { return p\Php80::preg_last_error_msg(); }
}
if (!function_exists('str_contains')) {
    function str_contains(?string $haystack, ?string $needle): bool { return p\Php80::str_contains($haystack ?? '', $needle ?? ''); }
}
if (!function_exists('str_starts_with')) {
    function str_starts_with(?string $haystack, ?string $needle): bool { return p\Php80::str_starts_with($haystack ?? '', $needle ?? ''); }
}
if (!function_exists('str_ends_with')) {
    function str_ends_with(?string $haystack, ?string $needle): bool { return p\Php80::str_ends_with($haystack ?? '', $needle ?? ''); }
}
if (!function_exists('get_debug_type')) {
    function get_debug_type($value): string { return p\Php80::get_debug_type($value); }
}
if (!function_exists('get_resource_id')) {
    function get_resource_id($resource): int { return p\Php80::get_resource_id($resource); }
}
Symfony Polyfill / Php80
========================

This component provides features added to PHP 8.0 core:

- [`Stringable`](https://php.net/stringable) interface
- [`fdiv`](https://php.net/fdiv)
- [`ValueError`](https://php.net/valueerror) class
- [`UnhandledMatchError`](https://php.net/unhandledmatcherror) class
- `FILTER_VALIDATE_BOOL` constant
- [`get_debug_type`](https://php.net/get_debug_type)
- [`PhpToken`](https://php.net/phptoken) class
- [`preg_last_error_msg`](https://php.net/preg_last_error_msg)
- [`str_contains`](https://php.net/str_contains)
- [`str_starts_with`](https://php.net/str_starts_with)
- [`str_ends_with`](https://php.net/str_ends_with)
- [`get_resource_id`](https://php.net/get_resource_id)

More information can be found in the
[main Polyfill README](https://github.com/symfony/polyfill/blob/main/README.md).

License
=======

This library is released under the [MIT license](LICENSE).
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Symfony\Polyfill\Php80;

/**
 * @author Ion Bazan <ion.bazan@gmail.com>
 * @author Nico Oelgart <nicoswd@gmail.com>
 * @author Nicolas Grekas <p@tchwork.com>
 *
 * @internal
 */
final class Php80
{
    public static function fdiv(float $dividend, float $divisor): float
    {
        return @($dividend / $divisor);
    }
    public static function get_debug_type($value): string
    {
        switch (\true) {
            case null === $value:
                return 'null';
            case \is_bool($value):
                return 'bool';
            case \is_string($value):
                return 'string';
            case \is_array($value):
                return 'array';
            case \is_int($value):
                return 'int';
            case \is_float($value):
                return 'float';
            case \is_object($value):
                break;
            case $value instanceof \__PHP_Incomplete_Class:
                return '__PHP_Incomplete_Class';
            default:
                if (null === $type = @get_resource_type($value)) {
                    return 'unknown';
                }
                if ('Unknown' === $type) {
                    $type = 'closed';
                }
                return "resource ({$type})";
        }
        $class = \get_class($value);
        if (\false === strpos($class, '@')) {
            return $class;
        }
        return ((get_parent_class($class) ?: key(class_implements($class))) ?: 'class') . '@anonymous';
    }
    public static function get_resource_id($res): int
    {
        if (!\is_resource($res) && null === @get_resource_type($res)) {
            throw new \TypeError(\sprintf('Argument 1 passed to get_resource_id() must be of the type resource, %s given', get_debug_type($res)));
        }
        return (int) $res;
    }
    public static function preg_last_error_msg(): string
    {
        switch (preg_last_error()) {
            case \PREG_INTERNAL_ERROR:
                return 'Internal error';
            case \PREG_BAD_UTF8_ERROR:
                return 'Malformed UTF-8 characters, possibly incorrectly encoded';
            case \PREG_BAD_UTF8_OFFSET_ERROR:
                return 'The offset did not correspond to the beginning of a valid UTF-8 code point';
            case \PREG_BACKTRACK_LIMIT_ERROR:
                return 'Backtrack limit exhausted';
            case \PREG_RECURSION_LIMIT_ERROR:
                return 'Recursion limit exhausted';
            case \PREG_JIT_STACKLIMIT_ERROR:
                return 'JIT stack limit exhausted';
            case \PREG_NO_ERROR:
                return 'No error';
            default:
                return 'Unknown error';
        }
    }
    public static function str_contains(string $haystack, string $needle): bool
    {
        return '' === $needle || \false !== strpos($haystack, $needle);
    }
    public static function str_starts_with(string $haystack, string $needle): bool
    {
        return 0 === strncmp($haystack, $needle, \strlen($needle));
    }
    public static function str_ends_with(string $haystack, string $needle): bool
    {
        if ('' === $needle || $needle === $haystack) {
            return \true;
        }
        if ('' === $haystack) {
            return \false;
        }
        $needleLength = \strlen($needle);
        return $needleLength <= \strlen($haystack) && 0 === substr_compare($haystack, $needle, -$needleLength);
    }
}
{
    "name": "symfony\/polyfill-php80",
    "type": "library",
    "description": "Symfony polyfill backporting some PHP 8.0+ features to lower PHP versions",
    "keywords": [
        "polyfill",
        "shim",
        "compatibility",
        "portable"
    ],
    "homepage": "https:\/\/symfony.com",
    "license": "MIT",
    "authors": [
        {
            "name": "Ion Bazan",
            "email": "ion.bazan@gmail.com"
        },
        {
            "name": "Nicolas Grekas",
            "email": "p@tchwork.com"
        },
        {
            "name": "Symfony Community",
            "homepage": "https:\/\/symfony.com\/contributors"
        }
    ],
    "require": {
        "php": ">=7.2"
    },
    "autoload": {
        "psr-4": {
            "Symfony\\Polyfill\\Php80\\": ""
        },
        "files": [
            "bootstrap.php"
        ],
        "classmap": [
            "Resources\/stubs"
        ]
    },
    "minimum-stability": "dev",
    "extra": {
        "thanks": {
            "name": "symfony\/polyfill",
            "url": "https:\/\/github.com\/symfony\/polyfill"
        }
    }
}<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Bridge\Monolog\Handler;

use _ContaoManager\Monolog\Formatter\FormatterInterface;
use _ContaoManager\Monolog\Formatter\HtmlFormatter;
use _ContaoManager\Monolog\Formatter\LineFormatter;
use _ContaoManager\Monolog\Handler\AbstractProcessingHandler;
use _ContaoManager\Monolog\Level;
use _ContaoManager\Monolog\Logger;
use _ContaoManager\Monolog\LogRecord;
use _ContaoManager\Symfony\Component\Mailer\MailerInterface;
use _ContaoManager\Symfony\Component\Mime\Email;
/**
 * @author Alexander Borisov <boshurik@gmail.com>
 *
 * @final since Symfony 6.1
 */
class MailerHandler extends AbstractProcessingHandler
{
    use CompatibilityProcessingHandler;
    private MailerInterface $mailer;
    private \Closure|Email $messageTemplate;
    public function __construct(MailerInterface $mailer, callable|Email $messageTemplate, string|int|Level $level = Logger::DEBUG, bool $bubble = \true)
    {
        parent::__construct($level, $bubble);
        $this->mailer = $mailer;
        $this->messageTemplate = $messageTemplate instanceof Email ? $messageTemplate : $messageTemplate(...);
    }
    public function handleBatch(array $records): void
    {
        $messages = [];
        if (Logger::API >= 3) {
            /** @var LogRecord $record */
            foreach ($records as $record) {
                if ($record->level->isLowerThan($this->level)) {
                    continue;
                }
                $messages[] = $this->processRecord($record);
            }
        } else {
            foreach ($records as $record) {
                if ($record['level'] < $this->level) {
                    continue;
                }
                $messages[] = $this->processRecord($record);
            }
        }
        if ($messages) {
            $this->send((string) $this->getFormatter()->formatBatch($messages), $messages);
        }
    }
    private function doWrite(array|LogRecord $record): void
    {
        $this->send((string) $record['formatted'], [$record]);
    }
    /**
     * Send a mail with the given content.
     *
     * @param string $content formatted email body to be sent
     * @param array  $records the array of log records that formed this content
     *
     * @return void
     */
    protected function send(string $content, array $records)
    {
        $this->mailer->send($this->buildMessage($content, $records));
    }
    /**
     * Gets the formatter for the Message subject.
     *
     * @param string $format The format of the subject
     */
    protected function getSubjectFormatter(string $format): FormatterInterface
    {
        return new LineFormatter($format);
    }
    /**
     * Creates instance of Message to be sent.
     *
     * @param string $content formatted email body to be sent
     * @param array  $records Log records that formed the content
     */
    protected function buildMessage(string $content, array $records): Email
    {
        if ($this->messageTemplate instanceof Email) {
            $message = clone $this->messageTemplate;
        } elseif (\is_callable($this->messageTemplate)) {
            $message = ($this->messageTemplate)($content, $records);
            if (!$message instanceof Email) {
                throw new \InvalidArgumentException(\sprintf('Could not resolve message from a callable. Instance of "%s" is expected.', Email::class));
            }
        } else {
            throw new \InvalidArgumentException('Could not resolve message as instance of Email or a callable returning it.');
        }
        if ($records) {
            $subjectFormatter = $this->getSubjectFormatter($message->getSubject());
            $message->subject($subjectFormatter->format($this->getHighestRecord($records)));
        }
        if ($this->getFormatter() instanceof HtmlFormatter) {
            if ($message->getHtmlCharset()) {
                $message->html($content, $message->getHtmlCharset());
            } else {
                $message->html($content);
            }
        } else if ($message->getTextCharset()) {
            $message->text($content, $message->getTextCharset());
        } else {
            $message->text($content);
        }
        return $message;
    }
    protected function getHighestRecord(array $records): array|LogRecord
    {
        $highestRecord = null;
        foreach ($records as $record) {
            if (null === $highestRecord || $highestRecord['level'] < $record['level']) {
                $highestRecord = $record;
            }
        }
        return $highestRecord;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Bridge\Monolog\Handler;

use _ContaoManager\Monolog\Logger;
use _ContaoManager\Monolog\LogRecord;
if (Logger::API >= 3) {
    /**
     * The base class for compatibility between Monolog 3 LogRecord and Monolog 1/2 array records.
     *
     * @author Jordi Boggiano <j.boggiano@seld.be>
     *
     * @internal
     */
    trait CompatibilityProcessingHandler
    {
        abstract private function doWrite(array|LogRecord $record): void;
        protected function write(LogRecord $record): void
        {
            $this->doWrite($record);
        }
    }
} else {
    /**
     * The base class for compatibility between Monolog 3 LogRecord and Monolog 1/2 array records.
     *
     * @author Jordi Boggiano <j.boggiano@seld.be>
     *
     * @internal
     */
    trait CompatibilityProcessingHandler
    {
        abstract private function doWrite(array|LogRecord $record): void;
        protected function write(array $record): void
        {
            $this->doWrite($record);
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Bridge\Monolog\Handler;

use _ContaoManager\Monolog\Formatter\FormatterInterface;
use _ContaoManager\Monolog\Formatter\LineFormatter;
use _ContaoManager\Monolog\Handler\AbstractProcessingHandler;
use _ContaoManager\Monolog\Logger;
use _ContaoManager\Monolog\LogRecord;
use _ContaoManager\Symfony\Bridge\Monolog\Formatter\ConsoleFormatter;
use _ContaoManager\Symfony\Component\Console\ConsoleEvents;
use _ContaoManager\Symfony\Component\Console\Event\ConsoleCommandEvent;
use _ContaoManager\Symfony\Component\Console\Event\ConsoleTerminateEvent;
use _ContaoManager\Symfony\Component\Console\Output\ConsoleOutputInterface;
use _ContaoManager\Symfony\Component\Console\Output\OutputInterface;
use _ContaoManager\Symfony\Component\EventDispatcher\EventSubscriberInterface;
use _ContaoManager\Symfony\Component\VarDumper\Dumper\CliDumper;
if (Logger::API >= 3) {
    /**
     * The base class for compatibility between Monolog 3 LogRecord and Monolog 1/2 array records.
     *
     * @author Jordi Boggiano <j.boggiano@seld.be>
     *
     * @internal
     */
    trait CompatibilityIsHandlingHandler
    {
        abstract private function doIsHandling(array|LogRecord $record): bool;
        public function isHandling(LogRecord $record): bool
        {
            return $this->doIsHandling($record);
        }
    }
} else {
    /**
     * The base class for compatibility between Monolog 3 LogRecord and Monolog 1/2 array records.
     *
     * @author Jordi Boggiano <j.boggiano@seld.be>
     *
     * @internal
     */
    trait CompatibilityIsHandlingHandler
    {
        abstract private function doIsHandling(array|LogRecord $record): bool;
        public function isHandling(array $record): bool
        {
            return $this->doIsHandling($record);
        }
    }
}
/**
 * Writes logs to the console output depending on its verbosity setting.
 *
 * It is disabled by default and gets activated as soon as a command is executed.
 * Instead of listening to the console events, the output can also be set manually.
 *
 * The minimum logging level at which this handler will be triggered depends on the
 * verbosity setting of the console output. The default mapping is:
 * - OutputInterface::VERBOSITY_NORMAL will show all WARNING and higher logs
 * - OutputInterface::VERBOSITY_VERBOSE (-v) will show all NOTICE and higher logs
 * - OutputInterface::VERBOSITY_VERY_VERBOSE (-vv) will show all INFO and higher logs
 * - OutputInterface::VERBOSITY_DEBUG (-vvv) will show all DEBUG and higher logs, i.e. all logs
 *
 * This mapping can be customized with the $verbosityLevelMap constructor parameter.
 *
 * @author Tobias Schultze <http://tobion.de>
 *
 * @final since Symfony 6.1
 */
class ConsoleHandler extends AbstractProcessingHandler implements EventSubscriberInterface
{
    use CompatibilityHandler;
    use CompatibilityIsHandlingHandler;
    use CompatibilityProcessingHandler;
    private ?OutputInterface $output;
    private array $verbosityLevelMap = [OutputInterface::VERBOSITY_QUIET => Logger::ERROR, OutputInterface::VERBOSITY_NORMAL => Logger::WARNING, OutputInterface::VERBOSITY_VERBOSE => Logger::NOTICE, OutputInterface::VERBOSITY_VERY_VERBOSE => Logger::INFO, OutputInterface::VERBOSITY_DEBUG => Logger::DEBUG];
    private array $consoleFormatterOptions;
    private int $nestedCommandDepth = 0;
    /**
     * @param OutputInterface|null $output            The console output to use (the handler remains disabled when passing null
     *                                                until the output is set, e.g. by using console events)
     * @param bool                 $bubble            Whether the messages that are handled can bubble up the stack
     * @param array                $verbosityLevelMap Array that maps the OutputInterface verbosity to a minimum logging
     *                                                level (leave empty to use the default mapping)
     */
    public function __construct(?OutputInterface $output = null, bool $bubble = \true, array $verbosityLevelMap = [], array $consoleFormatterOptions = [])
    {
        parent::__construct(Logger::DEBUG, $bubble);
        $this->output = $output;
        if ($verbosityLevelMap) {
            $this->verbosityLevelMap = $verbosityLevelMap;
        }
        $this->consoleFormatterOptions = $consoleFormatterOptions;
    }
    private function doIsHandling(array|LogRecord $record): bool
    {
        return $this->updateLevel() && parent::isHandling($record);
    }
    private function doHandle(array|LogRecord $record): bool
    {
        // we have to update the logging level each time because the verbosity of the
        // console output might have changed in the meantime (it is not immutable)
        return $this->updateLevel() && parent::handle($record);
    }
    /**
     * Sets the console output to use for printing logs.
     *
     * @return void
     */
    public function setOutput(OutputInterface $output)
    {
        $this->output = $output;
    }
    /**
     * Disables the output.
     */
    public function close(): void
    {
        $this->nestedCommandDepth = 0;
        $this->output = null;
        parent::close();
    }
    /**
     * Before a command is executed, the handler gets activated and the console output
     * is set in order to know where to write the logs.
     *
     * @return void
     */
    public function onCommand(ConsoleCommandEvent $event)
    {
        if (1 !== ++$this->nestedCommandDepth) {
            return;
        }
        $output = $event->getOutput();
        if ($output instanceof ConsoleOutputInterface) {
            $output = $output->getErrorOutput();
        }
        $this->setOutput($output);
    }
    /**
     * After a command has been executed, it disables the output.
     *
     * @return void
     */
    public function onTerminate(ConsoleTerminateEvent $event)
    {
        if ($this->nestedCommandDepth && !--$this->nestedCommandDepth) {
            $this->close();
        }
    }
    public static function getSubscribedEvents(): array
    {
        return [ConsoleEvents::COMMAND => ['onCommand', 255], ConsoleEvents::TERMINATE => ['onTerminate', -255]];
    }
    private function doWrite(array|LogRecord $record): void
    {
        // at this point we've determined for sure that we want to output the record, so use the output's own verbosity
        $this->output->write((string) $record['formatted'], \false, $this->output->getVerbosity());
    }
    protected function getDefaultFormatter(): FormatterInterface
    {
        if (!class_exists(CliDumper::class)) {
            return new LineFormatter();
        }
        if (!$this->output) {
            return new ConsoleFormatter($this->consoleFormatterOptions);
        }
        return new ConsoleFormatter(array_replace(['colors' => $this->output->isDecorated(), 'multiline' => OutputInterface::VERBOSITY_DEBUG <= $this->output->getVerbosity()], $this->consoleFormatterOptions));
    }
    /**
     * Updates the logging level based on the verbosity setting of the console output.
     *
     * @return bool Whether the handler is enabled and verbosity is not set to quiet
     */
    private function updateLevel(): bool
    {
        if (null === $this->output) {
            return \false;
        }
        $verbosity = $this->output->getVerbosity();
        if (isset($this->verbosityLevelMap[$verbosity])) {
            $this->setLevel($this->verbosityLevelMap[$verbosity]);
        } else {
            $this->setLevel(Logger::DEBUG);
        }
        return \true;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Bridge\Monolog\Handler\FingersCrossed;

use _ContaoManager\Monolog\Handler\FingersCrossed\ActivationStrategyInterface;
use _ContaoManager\Monolog\LogRecord;
use _ContaoManager\Symfony\Component\HttpFoundation\RequestStack;
use _ContaoManager\Symfony\Component\HttpKernel\Exception\HttpExceptionInterface;
/**
 * Activation strategy that ignores certain HTTP codes.
 *
 * @author Shaun Simmons <shaun@envysphere.com>
 * @author Pierrick Vignand <pierrick.vignand@gmail.com>
 */
final class HttpCodeActivationStrategy implements ActivationStrategyInterface
{
    /**
     * @param array $exclusions each exclusion must have a "code" and "urls" keys
     */
    public function __construct(private RequestStack $requestStack, private array $exclusions, private ActivationStrategyInterface $inner)
    {
        foreach ($exclusions as $exclusion) {
            if (!\array_key_exists('code', $exclusion)) {
                throw new \LogicException('An exclusion must have a "code" key.');
            }
            if (!\array_key_exists('urls', $exclusion)) {
                throw new \LogicException('An exclusion must have a "urls" key.');
            }
        }
    }
    public function isHandlerActivated(array|LogRecord $record): bool
    {
        $isActivated = $this->inner->isHandlerActivated($record);
        if ($isActivated && isset($record['context']['exception']) && $record['context']['exception'] instanceof HttpExceptionInterface && $request = $this->requestStack->getMainRequest()) {
            foreach ($this->exclusions as $exclusion) {
                if ($record['context']['exception']->getStatusCode() !== $exclusion['code']) {
                    continue;
                }
                if (\count($exclusion['urls'])) {
                    return !preg_match('{(' . implode('|', $exclusion['urls']) . ')}i', $request->getPathInfo());
                }
                return \false;
            }
        }
        return $isActivated;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Bridge\Monolog\Handler\FingersCrossed;

use _ContaoManager\Monolog\Handler\FingersCrossed\ActivationStrategyInterface;
use _ContaoManager\Monolog\LogRecord;
use _ContaoManager\Symfony\Component\HttpFoundation\RequestStack;
use _ContaoManager\Symfony\Component\HttpKernel\Exception\HttpException;
/**
 * Activation strategy that ignores 404s for certain URLs.
 *
 * @author Jordi Boggiano <j.boggiano@seld.be>
 * @author Fabien Potencier <fabien@symfony.com>
 * @author Pierrick Vignand <pierrick.vignand@gmail.com>
 */
final class NotFoundActivationStrategy implements ActivationStrategyInterface
{
    private string $exclude;
    public function __construct(private RequestStack $requestStack, array $excludedUrls, private ActivationStrategyInterface $inner)
    {
        $this->exclude = '{(' . implode('|', $excludedUrls) . ')}i';
    }
    public function isHandlerActivated(array|LogRecord $record): bool
    {
        $isActivated = $this->inner->isHandlerActivated($record);
        if ($isActivated && isset($record['context']['exception']) && $record['context']['exception'] instanceof HttpException && 404 == $record['context']['exception']->getStatusCode() && $request = $this->requestStack->getMainRequest()) {
            return !preg_match($this->exclude, $request->getPathInfo());
        }
        return $isActivated;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Bridge\Monolog\Handler;

use _ContaoManager\Monolog\Formatter\FormatterInterface;
use _ContaoManager\Monolog\Handler\AbstractProcessingHandler;
use _ContaoManager\Monolog\Handler\FormattableHandlerTrait;
use _ContaoManager\Monolog\Level;
use _ContaoManager\Monolog\Logger;
use _ContaoManager\Monolog\LogRecord;
use _ContaoManager\Symfony\Bridge\Monolog\Formatter\VarDumperFormatter;
if (trait_exists(FormattableHandlerTrait::class)) {
    /**
     * @final since Symfony 6.1
     */
    class ServerLogHandler extends AbstractProcessingHandler
    {
        use CompatibilityHandler;
        use CompatibilityProcessingHandler;
        use ServerLogHandlerTrait;
        protected function getDefaultFormatter(): FormatterInterface
        {
            return new VarDumperFormatter();
        }
    }
} else {
    /**
     * @final since Symfony 6.1
     */
    class ServerLogHandler extends AbstractProcessingHandler
    {
        use CompatibilityHandler;
        use CompatibilityProcessingHandler;
        use ServerLogHandlerTrait;
        protected function getDefaultFormatter()
        {
            return new VarDumperFormatter();
        }
    }
}
/**
 * @author Grégoire Pineau <lyrixx@lyrixx.info>
 *
 * @internal since Symfony 6.1
 */
trait ServerLogHandlerTrait
{
    private string $host;
    /**
     * @var resource
     */
    private $context;
    /**
     * @var resource|null
     */
    private $socket;
    public function __construct(string $host, string|int|Level $level = Logger::DEBUG, bool $bubble = \true, array $context = [])
    {
        parent::__construct($level, $bubble);
        if (!str_contains($host, '://')) {
            $host = 'tcp://' . $host;
        }
        $this->host = $host;
        $this->context = stream_context_create($context);
    }
    private function doHandle(array|LogRecord $record): bool
    {
        if (!$this->isHandling($record)) {
            return \false;
        }
        set_error_handler(static fn() => null);
        try {
            if (!$this->socket = $this->socket ?: $this->createSocket()) {
                return \false === $this->bubble;
            }
        } finally {
            restore_error_handler();
        }
        return parent::handle($record);
    }
    private function doWrite(array|LogRecord $record): void
    {
        $recordFormatted = $this->formatRecord($record);
        set_error_handler(static fn() => null);
        try {
            if (-1 === stream_socket_sendto($this->socket, $recordFormatted)) {
                stream_socket_shutdown($this->socket, \STREAM_SHUT_RDWR);
                // Let's retry: the persistent connection might just be stale
                if ($this->socket = $this->createSocket()) {
                    stream_socket_sendto($this->socket, $recordFormatted);
                }
            }
        } finally {
            restore_error_handler();
        }
    }
    protected function getDefaultFormatter(): FormatterInterface
    {
        return new VarDumperFormatter();
    }
    /**
     * @return resource
     */
    private function createSocket()
    {
        $socket = stream_socket_client($this->host, $errno, $errstr, 0, \STREAM_CLIENT_CONNECT | \STREAM_CLIENT_ASYNC_CONNECT | \STREAM_CLIENT_PERSISTENT, $this->context);
        if ($socket) {
            stream_set_blocking($socket, \false);
        }
        return $socket;
    }
    private function formatRecord(array|LogRecord $record): string
    {
        $recordFormatted = $record['formatted'];
        foreach (['log_uuid', 'uuid', 'uid'] as $key) {
            if (isset($record['extra'][$key])) {
                $recordFormatted['log_id'] = $record['extra'][$key];
                break;
            }
        }
        return base64_encode(serialize($recordFormatted)) . "\n";
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Bridge\Monolog\Handler;

use _ContaoManager\Monolog\Logger;
use _ContaoManager\Monolog\LogRecord;
if (Logger::API >= 3) {
    /**
     * The base class for compatibility between Monolog 3 LogRecord and Monolog 1/2 array records.
     *
     * @author Jordi Boggiano <j.boggiano@seld.be>
     *
     * @internal
     */
    trait CompatibilityHandler
    {
        abstract private function doHandle(array|LogRecord $record): bool;
        public function handle(LogRecord $record): bool
        {
            return $this->doHandle($record);
        }
    }
} else {
    /**
     * The base class for compatibility between Monolog 3 LogRecord and Monolog 1/2 array records.
     *
     * @author Jordi Boggiano <j.boggiano@seld.be>
     *
     * @internal
     */
    trait CompatibilityHandler
    {
        abstract private function doHandle(array|LogRecord $record): bool;
        public function handle(array $record): bool
        {
            return $this->doHandle($record);
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Bridge\Monolog\Handler;

use _ContaoManager\Monolog\Handler\AbstractHandler;
use _ContaoManager\Monolog\Level;
use _ContaoManager\Monolog\Logger;
use _ContaoManager\Monolog\LogRecord;
use _ContaoManager\Symfony\Component\Notifier\Notification\Notification;
use _ContaoManager\Symfony\Component\Notifier\Notifier;
use _ContaoManager\Symfony\Component\Notifier\NotifierInterface;
/**
 * Uses Notifier as a log handler.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 *
 * @final since Symfony 6.1
 */
class NotifierHandler extends AbstractHandler
{
    use CompatibilityHandler;
    private NotifierInterface $notifier;
    public function __construct(NotifierInterface $notifier, string|int|Level $level = Logger::ERROR, bool $bubble = \true)
    {
        $this->notifier = $notifier;
        parent::__construct(Logger::toMonologLevel($level) < Logger::ERROR ? Logger::ERROR : $level, $bubble);
    }
    private function doHandle(array|LogRecord $record): bool
    {
        if (!$this->isHandling($record)) {
            return \false;
        }
        $this->notify([$record]);
        return !$this->bubble;
    }
    public function handleBatch(array $records): void
    {
        if ($records = array_filter($records, $this->isHandling(...))) {
            $this->notify($records);
        }
    }
    private function notify(array $records): void
    {
        $record = $this->getHighestRecord($records);
        if (($record['context']['exception'] ?? null) instanceof \Throwable) {
            $notification = Notification::fromThrowable($record['context']['exception']);
        } else {
            $notification = new Notification($record['message']);
        }
        $notification->importanceFromLogLevelName(Logger::getLevelName($record['level']));
        $this->notifier->send($notification, ...$this->notifier->getAdminRecipients());
    }
    private function getHighestRecord(array $records): array|LogRecord
    {
        $highestRecord = null;
        foreach ($records as $record) {
            if (null === $highestRecord || $highestRecord['level'] < $record['level']) {
                $highestRecord = $record;
            }
        }
        return $highestRecord;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Bridge\Monolog\Handler;

use _ContaoManager\Monolog\Handler\FirePHPHandler as BaseFirePHPHandler;
use _ContaoManager\Symfony\Component\HttpFoundation\Response;
use _ContaoManager\Symfony\Component\HttpKernel\Event\ResponseEvent;
/**
 * FirePHPHandler.
 *
 * @author Jordi Boggiano <j.boggiano@seld.be>
 *
 * @final
 */
class FirePHPHandler extends BaseFirePHPHandler
{
    private array $headers = [];
    private ?Response $response = null;
    /**
     * Adds the headers to the response once it's created.
     */
    public function onKernelResponse(ResponseEvent $event): void
    {
        if (!$event->isMainRequest()) {
            return;
        }
        $request = $event->getRequest();
        if (!preg_match('{\bFirePHP/\d+\.\d+\b}', $request->headers->get('User-Agent', '')) && !$request->headers->has('X-FirePHP-Version')) {
            self::$sendHeaders = \false;
            $this->headers = [];
            return;
        }
        $this->response = $event->getResponse();
        foreach ($this->headers as $header => $content) {
            $this->response->headers->set($header, $content);
        }
        $this->headers = [];
    }
    protected function sendHeader($header, $content): void
    {
        if (!self::$sendHeaders) {
            return;
        }
        if (null !== $this->response) {
            $this->response->headers->set($header, $content);
        } else {
            $this->headers[$header] = $content;
        }
    }
    /**
     * Override default behavior since we check the user agent in onKernelResponse.
     */
    protected function headersAccepted(): bool
    {
        return \true;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Bridge\Monolog\Handler;

use _ContaoManager\Monolog\Handler\ChromePHPHandler as BaseChromePhpHandler;
use _ContaoManager\Symfony\Component\HttpFoundation\Response;
use _ContaoManager\Symfony\Component\HttpKernel\Event\ResponseEvent;
/**
 * ChromePhpHandler.
 *
 * @author Christophe Coevoet <stof@notk.org>
 *
 * @final
 */
class ChromePhpHandler extends BaseChromePhpHandler
{
    private array $headers = [];
    private Response $response;
    /**
     * Adds the headers to the response once it's created.
     */
    public function onKernelResponse(ResponseEvent $event): void
    {
        if (!$event->isMainRequest()) {
            return;
        }
        if (!preg_match(static::USER_AGENT_REGEX, $event->getRequest()->headers->get('User-Agent', ''))) {
            self::$sendHeaders = \false;
            $this->headers = [];
            return;
        }
        $this->response = $event->getResponse();
        foreach ($this->headers as $header => $content) {
            $this->response->headers->set($header, $content);
        }
        $this->headers = [];
    }
    protected function sendHeader($header, $content): void
    {
        if (!self::$sendHeaders) {
            return;
        }
        if (isset($this->response)) {
            $this->response->headers->set($header, $content);
        } else {
            $this->headers[$header] = $content;
        }
    }
    /**
     * Override default behavior since we check it in onKernelResponse.
     */
    protected function headersAccepted(): bool
    {
        return \true;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Bridge\Monolog\Handler;

use _ContaoManager\Monolog\Formatter\FormatterInterface;
use _ContaoManager\Monolog\Formatter\LogstashFormatter;
use _ContaoManager\Monolog\Handler\AbstractHandler;
use _ContaoManager\Monolog\Handler\FormattableHandlerTrait;
use _ContaoManager\Monolog\Handler\ProcessableHandlerTrait;
use _ContaoManager\Monolog\Level;
use _ContaoManager\Monolog\Logger;
use _ContaoManager\Monolog\LogRecord;
use _ContaoManager\Symfony\Component\HttpClient\HttpClient;
use _ContaoManager\Symfony\Contracts\HttpClient\Exception\ExceptionInterface;
use _ContaoManager\Symfony\Contracts\HttpClient\HttpClientInterface;
use _ContaoManager\Symfony\Contracts\HttpClient\ResponseInterface;
/**
 * Push logs directly to Elasticsearch and format them according to Logstash specification.
 *
 * This handler dials directly with the HTTP interface of Elasticsearch. This
 * means it will slow down your application if Elasticsearch takes times to
 * answer. Even if all HTTP calls are done asynchronously.
 *
 * In a development environment, it's fine to keep the default configuration:
 * for each log, an HTTP request will be made to push the log to Elasticsearch.
 *
 * In a production environment, it's highly recommended to wrap this handler
 * in a handler with buffering capabilities (like the FingersCrossedHandler, or
 * BufferHandler) in order to call Elasticsearch only once with a bulk push. For
 * even better performance and fault tolerance, a proper ELK (https://www.elastic.co/what-is/elk-stack)
 * stack is recommended.
 *
 * @author Grégoire Pineau <lyrixx@lyrixx.info>
 *
 * @final since Symfony 6.1
 */
class ElasticsearchLogstashHandler extends AbstractHandler
{
    use CompatibilityHandler;
    use FormattableHandlerTrait;
    use ProcessableHandlerTrait;
    private string $endpoint;
    private string $index;
    private HttpClientInterface $client;
    private string $elasticsearchVersion;
    /**
     * @var \SplObjectStorage<ResponseInterface, null>
     */
    private \SplObjectStorage $responses;
    public function __construct(string $endpoint = 'http://127.0.0.1:9200', string $index = 'monolog', ?HttpClientInterface $client = null, string|int|Level $level = Logger::DEBUG, bool $bubble = \true, string $elasticsearchVersion = '1.0.0')
    {
        if (!$client && !class_exists(HttpClient::class)) {
            throw new \LogicException(\sprintf('The "%s" handler needs an HTTP client. Try running "composer require symfony/http-client".', __CLASS__));
        }
        parent::__construct($level, $bubble);
        $this->endpoint = $endpoint;
        $this->index = $index;
        $this->client = $client ?: HttpClient::create(['timeout' => 1]);
        $this->responses = new \SplObjectStorage();
        $this->elasticsearchVersion = $elasticsearchVersion;
    }
    private function doHandle(array|LogRecord $record): bool
    {
        if (!$this->isHandling($record)) {
            return \false;
        }
        $this->sendToElasticsearch([$record]);
        return !$this->bubble;
    }
    public function handleBatch(array $records): void
    {
        $records = array_filter($records, $this->isHandling(...));
        if ($records) {
            $this->sendToElasticsearch($records);
        }
    }
    protected function getDefaultFormatter(): FormatterInterface
    {
        // Monolog 1.X
        if (\defined(LogstashFormatter::class . '::V1')) {
            return new LogstashFormatter('application', null, null, 'ctxt_', LogstashFormatter::V1);
        }
        // Monolog 2.X
        return new LogstashFormatter('application');
    }
    private function sendToElasticsearch(array $records): void
    {
        $formatter = $this->getFormatter();
        if (version_compare($this->elasticsearchVersion, '7', '>=')) {
            $headers = json_encode(['index' => ['_index' => $this->index]]);
        } else {
            $headers = json_encode(['index' => ['_index' => $this->index, '_type' => '_doc']]);
        }
        $body = '';
        foreach ($records as $record) {
            foreach ($this->processors as $processor) {
                $record = $processor($record);
            }
            $body .= $headers;
            $body .= "\n";
            $body .= $formatter->format($record);
            $body .= "\n";
        }
        $response = $this->client->request('POST', $this->endpoint . '/_bulk', ['body' => $body, 'headers' => ['Content-Type' => 'application/json']]);
        $this->responses[$response] = null;
        $this->wait(\false);
    }
    public function __serialize(): array
    {
        throw new \BadMethodCallException('Cannot serialize ' . __CLASS__);
    }
    public function __unserialize(array $data): void
    {
        throw new \BadMethodCallException('Cannot unserialize ' . __CLASS__);
    }
    public function __destruct()
    {
        $this->wait(\true);
    }
    private function wait(bool $blocking): void
    {
        foreach ($this->client->stream($this->responses, $blocking ? null : 0.0) as $response => $chunk) {
            try {
                if ($chunk->isTimeout() && !$blocking) {
                    continue;
                }
                if (!$chunk->isFirst() && !$chunk->isLast()) {
                    continue;
                }
                if ($chunk->isLast()) {
                    unset($this->responses[$response]);
                }
            } catch (ExceptionInterface $e) {
                unset($this->responses[$response]);
                error_log(\sprintf("Could not push logs to Elasticsearch:\n%s", (string) $e));
            }
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Bridge\Monolog;

trigger_deprecation('symfony/monolog-bridge', '6.4', 'The "%s" class is deprecated, use HttpKernel\'s DebugLoggerConfigurator instead.', Logger::class);
use _ContaoManager\Monolog\Logger as BaseLogger;
use _ContaoManager\Monolog\ResettableInterface;
use _ContaoManager\Symfony\Component\HttpFoundation\Request;
use _ContaoManager\Symfony\Component\HttpKernel\Log\DebugLoggerInterface;
use _ContaoManager\Symfony\Contracts\Service\ResetInterface;
/**
 * @deprecated since Symfony 6.4, use HttpKernel's DebugLoggerConfigurator instead
 */
class Logger extends BaseLogger implements DebugLoggerInterface, ResetInterface
{
    public function getLogs(?Request $request = null): array
    {
        if ($logger = $this->getDebugLogger()) {
            return $logger->getLogs($request);
        }
        return [];
    }
    public function countErrors(?Request $request = null): int
    {
        if ($logger = $this->getDebugLogger()) {
            return $logger->countErrors($request);
        }
        return 0;
    }
    public function clear(): void
    {
        if ($logger = $this->getDebugLogger()) {
            $logger->clear();
        }
    }
    public function reset(): void
    {
        $this->clear();
        if ($this instanceof ResettableInterface) {
            parent::reset();
        }
    }
    /**
     * @return void
     */
    public function removeDebugLogger()
    {
        foreach ($this->processors as $k => $processor) {
            if ($processor instanceof DebugLoggerInterface) {
                unset($this->processors[$k]);
            }
        }
        foreach ($this->handlers as $k => $handler) {
            if ($handler instanceof DebugLoggerInterface) {
                unset($this->handlers[$k]);
            }
        }
    }
    /**
     * Returns a DebugLoggerInterface instance if one is registered with this logger.
     */
    private function getDebugLogger(): ?DebugLoggerInterface
    {
        foreach ($this->processors as $processor) {
            if ($processor instanceof DebugLoggerInterface) {
                return $processor;
            }
        }
        foreach ($this->handlers as $handler) {
            if ($handler instanceof DebugLoggerInterface) {
                return $handler;
            }
        }
        return null;
    }
}
Copyright (c) 2004-present Fabien Potencier

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is furnished
to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
CHANGELOG
=========

6.4
---

 * Add native return type to `Logger::clear()` and to `DebugProcessor::clear()`
 * Deprecate class `Logger`, use HttpKernel's `DebugLoggerConfigurator` instead

6.1
---

 * Add support for Monolog 3

6.0
---

 * The `$actionLevel` constructor argument of `NotFoundActivationStrategy` has been replaced by the `$inner` one which expects an `ActivationStrategyInterface` to decorate instead
 * The `$actionLevel` constructor argument of `HttpCodeActivationStrategy` has been replaced by the `$inner` one which expects an `ActivationStrategyInterface` to decorate instead
 * Remove `ResetLoggersWorkerSubscriber` in favor of "reset_on_message" option in messenger configuration
 * Remove `SwiftMailerHandler`, use `MailerHandler` instead

5.4
---

 * Deprecate `ResetLoggersWorkerSubscriber` to reset buffered logs in messenger
   workers, use "reset_on_message" option in messenger configuration instead.

5.3
---

 * Add `ResetLoggersWorkerSubscriber` to reset buffered logs in messenger workers

5.2.0
-----

 * The `$actionLevel` constructor argument of `Symfony\Bridge\Monolog\Handler\FingersCrossed\NotFoundActivationStrategy` has been deprecated and replaced by the `$inner` one which expects an ActivationStrategyInterface to decorate instead. `Symfony\Bridge\Monolog\Handler\FingersCrossed\NotFoundActivationStrategy` will become final in 6.0.
 * The `$actionLevel` constructor argument of `Symfony\Bridge\Monolog\Handler\FingersCrossed\HttpCodeActivationStrategy` has been deprecated and replaced by the `$inner` one which expects an ActivationStrategyInterface to decorate instead. `Symfony\Bridge\Monolog\Handler\FingersCrossed\HttpCodeActivationStrategy` will become final in 6.0

5.1.0
-----

 * Added `MailerHandler`

5.0.0
-----

 * The methods `DebugProcessor::getLogs()`, `DebugProcessor::countErrors()`, `Logger::getLogs()` and `Logger::countErrors()` have a new `$request` argument.
 * Added support for Monolog 2.

4.4.0
-----

 * The `RouteProcessor` class has been made final
 * Added `ElasticsearchLogstashHandler`
 * Added the `ServerLogCommand`. Backport from the deprecated WebServerBundle

4.3.0
-----

 * added `ConsoleCommandProcessor`: monolog processor that adds command name and arguments
 * added `RouteProcessor`: monolog processor that adds route name, controller::action and route params

4.2.0
-----

 * The methods `DebugProcessor::getLogs()`, `DebugProcessor::countErrors()`, `Logger::getLogs()`
   and `Logger::countErrors()` will have a new `$request` argument in version 5.0, not defining
   it is deprecated

4.1.0
-----

 * `WebProcessor` now implements `EventSubscriberInterface` in order to be easily autoconfigured

4.0.0
-----

 * the `$format`, `$dateFormat`, `$allowInlineLineBreaks`, and `$ignoreEmptyContextAndExtra`
   constructor arguments of the `ConsoleFormatter` class have been removed, use
   `$options` instead
 * the `DebugHandler` class has been removed

3.3.0
-----

 * Improved the console handler output formatting by adding var-dumper support

3.0.0
-----

 * deprecated interface `Symfony\Component\HttpKernel\Log\LoggerInterface` has been removed
 * deprecated methods `Logger::crit()`, `Logger::emerg()`, `Logger::err()` and `Logger::warn()` have been removed

2.4.0
-----

 * added ConsoleHandler and ConsoleFormatter which can be used to show log messages
   in the console output depending on the verbosity settings

2.1.0
-----

 * added ChromePhpHandler
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Bridge\Monolog\Processor;

use _ContaoManager\Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
/**
 * Adds the current security token to the log entry.
 *
 * @author Dany Maillard <danymaillard93b@gmail.com>
 * @author Igor Timoshenko <igor.timoshenko@i.ua>
 *
 * @final since Symfony 6.1
 */
class TokenProcessor extends AbstractTokenProcessor
{
    protected function getKey(): string
    {
        return 'token';
    }
    protected function getToken(): ?TokenInterface
    {
        return $this->tokenStorage->getToken();
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Bridge\Monolog\Processor;

use _ContaoManager\Symfony\Component\Security\Core\Authentication\Token\SwitchUserToken;
use _ContaoManager\Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
/**
 * Adds the original security token to the log entry.
 *
 * @author Igor Timoshenko <igor.timoshenko@i.ua>
 *
 * @final since Symfony 6.1
 */
class SwitchUserTokenProcessor extends AbstractTokenProcessor
{
    protected function getKey(): string
    {
        return 'impersonator_token';
    }
    protected function getToken(): ?TokenInterface
    {
        $token = $this->tokenStorage->getToken();
        if ($token instanceof SwitchUserToken) {
            return $token->getOriginalToken();
        }
        return null;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Bridge\Monolog\Processor;

use _ContaoManager\Monolog\Processor\WebProcessor as BaseWebProcessor;
use _ContaoManager\Symfony\Component\EventDispatcher\EventSubscriberInterface;
use _ContaoManager\Symfony\Component\HttpKernel\Event\RequestEvent;
use _ContaoManager\Symfony\Component\HttpKernel\KernelEvents;
/**
 * WebProcessor override to read from the HttpFoundation's Request.
 *
 * @author Jordi Boggiano <j.boggiano@seld.be>
 *
 * @final
 */
class WebProcessor extends BaseWebProcessor implements EventSubscriberInterface
{
    public function __construct(?array $extraFields = null)
    {
        // Pass an empty array as the default null value would access $_SERVER
        parent::__construct([], $extraFields);
    }
    public function onKernelRequest(RequestEvent $event): void
    {
        if ($event->isMainRequest()) {
            $this->serverData = $event->getRequest()->server->all();
            $this->serverData['REMOTE_ADDR'] = $event->getRequest()->getClientIp();
        }
    }
    public static function getSubscribedEvents(): array
    {
        return [KernelEvents::REQUEST => ['onKernelRequest', 4096]];
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Bridge\Monolog\Processor;

use _ContaoManager\Monolog\Logger;
use _ContaoManager\Monolog\LogRecord;
if (Logger::API >= 3) {
    /**
     * The base class for compatibility between Monolog 3 LogRecord and Monolog 1/2 array records.
     *
     * @author Jordi Boggiano <j.boggiano@seld.be>
     *
     * @internal
     */
    trait CompatibilityProcessor
    {
        abstract private function doInvoke(array|LogRecord $record): array|LogRecord;
        public function __invoke(LogRecord $record): LogRecord
        {
            return $this->doInvoke($record);
        }
    }
} else {
    /**
     * The base class for compatibility between Monolog 3 LogRecord and Monolog 1/2 array records.
     *
     * @author Jordi Boggiano <j.boggiano@seld.be>
     *
     * @internal
     */
    trait CompatibilityProcessor
    {
        abstract private function doInvoke(array|LogRecord $record): array|LogRecord;
        public function __invoke(array $record): array
        {
            return $this->doInvoke($record);
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Bridge\Monolog\Processor;

use _ContaoManager\Monolog\LogRecord;
use _ContaoManager\Symfony\Component\EventDispatcher\EventSubscriberInterface;
use _ContaoManager\Symfony\Component\HttpKernel\Event\FinishRequestEvent;
use _ContaoManager\Symfony\Component\HttpKernel\Event\RequestEvent;
use _ContaoManager\Symfony\Component\HttpKernel\KernelEvents;
use _ContaoManager\Symfony\Contracts\Service\ResetInterface;
/**
 * Adds the current route information to the log entry.
 *
 * @author Piotr Stankowski <git@trakos.pl>
 *
 * @final
 */
class RouteProcessor implements EventSubscriberInterface, ResetInterface
{
    private array $routeData = [];
    private bool $includeParams;
    public function __construct(bool $includeParams = \true)
    {
        $this->includeParams = $includeParams;
        $this->reset();
    }
    public function __invoke(array|LogRecord $record): array|LogRecord
    {
        if ($this->routeData && !isset($record['extra']['requests'])) {
            $record['extra']['requests'] = array_values($this->routeData);
        }
        return $record;
    }
    public function reset(): void
    {
        $this->routeData = [];
    }
    public function addRouteData(RequestEvent $event): void
    {
        if ($event->isMainRequest()) {
            $this->reset();
        }
        $request = $event->getRequest();
        if (!$request->attributes->has('_controller')) {
            return;
        }
        $currentRequestData = ['controller' => $request->attributes->get('_controller'), 'route' => $request->attributes->get('_route')];
        if ($this->includeParams) {
            $currentRequestData['route_params'] = $request->attributes->get('_route_params');
        }
        $this->routeData[spl_object_id($request)] = $currentRequestData;
    }
    public function removeRouteData(FinishRequestEvent $event): void
    {
        $requestId = spl_object_id($event->getRequest());
        unset($this->routeData[$requestId]);
    }
    public static function getSubscribedEvents(): array
    {
        return [KernelEvents::REQUEST => ['addRouteData', 1], KernelEvents::FINISH_REQUEST => ['removeRouteData', 1]];
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Bridge\Monolog\Processor;

use _ContaoManager\Monolog\LogRecord;
use _ContaoManager\Symfony\Component\Console\ConsoleEvents;
use _ContaoManager\Symfony\Component\Console\Event\ConsoleEvent;
use _ContaoManager\Symfony\Component\EventDispatcher\EventSubscriberInterface;
use _ContaoManager\Symfony\Contracts\Service\ResetInterface;
/**
 * Adds the current console command information to the log entry.
 *
 * @author Piotr Stankowski <git@trakos.pl>
 *
 * @final since Symfony 6.1
 */
class ConsoleCommandProcessor implements EventSubscriberInterface, ResetInterface
{
    use CompatibilityProcessor;
    private array $commandData;
    private bool $includeArguments;
    private bool $includeOptions;
    public function __construct(bool $includeArguments = \true, bool $includeOptions = \false)
    {
        $this->includeArguments = $includeArguments;
        $this->includeOptions = $includeOptions;
    }
    private function doInvoke(array|LogRecord $record): array|LogRecord
    {
        if (isset($this->commandData) && !isset($record['extra']['command'])) {
            $record['extra']['command'] = $this->commandData;
        }
        return $record;
    }
    /**
     * @return void
     */
    public function reset()
    {
        unset($this->commandData);
    }
    /**
     * @return void
     */
    public function addCommandData(ConsoleEvent $event)
    {
        $this->commandData = ['name' => $event->getCommand()->getName()];
        if ($this->includeArguments) {
            $this->commandData['arguments'] = $event->getInput()->getArguments();
        }
        if ($this->includeOptions) {
            $this->commandData['options'] = $event->getInput()->getOptions();
        }
    }
    public static function getSubscribedEvents(): array
    {
        return [ConsoleEvents::COMMAND => ['addCommandData', 1]];
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Bridge\Monolog\Processor;

use _ContaoManager\Monolog\LogRecord;
use _ContaoManager\Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
use _ContaoManager\Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
/**
 * The base class for security token processors.
 *
 * @author Dany Maillard <danymaillard93b@gmail.com>
 * @author Igor Timoshenko <igor.timoshenko@i.ua>
 *
 * @internal since Symfony 6.1
 */
abstract class AbstractTokenProcessor
{
    use CompatibilityProcessor;
    /**
     * @var TokenStorageInterface
     */
    protected $tokenStorage;
    public function __construct(TokenStorageInterface $tokenStorage)
    {
        $this->tokenStorage = $tokenStorage;
    }
    abstract protected function getKey(): string;
    abstract protected function getToken(): ?TokenInterface;
    private function doInvoke(array|LogRecord $record): array|LogRecord
    {
        $record['extra'][$this->getKey()] = null;
        if (null !== $token = $this->getToken()) {
            $record['extra'][$this->getKey()] = ['authenticated' => (bool) $token->getUser(), 'roles' => $token->getRoleNames()];
            // @deprecated since Symfony 5.3, change to $token->getUserIdentifier() in 7.0
            $record['extra'][$this->getKey()]['user_identifier'] = method_exists($token, 'getUserIdentifier') ? $token->getUserIdentifier() : $token->getUsername();
        }
        return $record;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Bridge\Monolog\Processor;

use _ContaoManager\Monolog\Logger;
use _ContaoManager\Monolog\LogRecord;
use _ContaoManager\Symfony\Component\HttpFoundation\Request;
use _ContaoManager\Symfony\Component\HttpFoundation\RequestStack;
use _ContaoManager\Symfony\Component\HttpKernel\Log\DebugLoggerInterface;
use _ContaoManager\Symfony\Contracts\Service\ResetInterface;
class DebugProcessor implements DebugLoggerInterface, ResetInterface
{
    use CompatibilityProcessor;
    private array $records = [];
    private array $errorCount = [];
    private ?RequestStack $requestStack;
    public function __construct(?RequestStack $requestStack = null)
    {
        $this->requestStack = $requestStack;
    }
    private function doInvoke(array|LogRecord $record): array|LogRecord
    {
        $key = $this->requestStack && ($request = $this->requestStack->getCurrentRequest()) ? spl_object_id($request) : '';
        $timestampRfc3339 = \false;
        if ($record['datetime'] instanceof \DateTimeInterface) {
            $timestamp = $record['datetime']->getTimestamp();
            $timestampRfc3339 = $record['datetime']->format(\DateTimeInterface::RFC3339_EXTENDED);
        } elseif (\false !== $timestamp = strtotime($record['datetime'])) {
            $timestampRfc3339 = (new \DateTimeImmutable($record['datetime']))->format(\DateTimeInterface::RFC3339_EXTENDED);
        }
        $this->records[$key][] = ['timestamp' => $timestamp, 'timestamp_rfc3339' => $timestampRfc3339, 'message' => $record['message'], 'priority' => $record['level'], 'priorityName' => $record['level_name'], 'context' => $record['context'], 'channel' => $record['channel'] ?? ''];
        if (!isset($this->errorCount[$key])) {
            $this->errorCount[$key] = 0;
        }
        switch ($record['level']) {
            case Logger::ERROR:
            case Logger::CRITICAL:
            case Logger::ALERT:
            case Logger::EMERGENCY:
                ++$this->errorCount[$key];
        }
        return $record;
    }
    public function getLogs(?Request $request = null): array
    {
        if (null !== $request) {
            return $this->records[spl_object_id($request)] ?? [];
        }
        if (0 === \count($this->records)) {
            return [];
        }
        return array_merge(...array_values($this->records));
    }
    public function countErrors(?Request $request = null): int
    {
        if (null !== $request) {
            return $this->errorCount[spl_object_id($request)] ?? 0;
        }
        return array_sum($this->errorCount);
    }
    public function clear(): void
    {
        $this->records = [];
        $this->errorCount = [];
    }
    /**
     * @return void
     */
    public function reset()
    {
        $this->clear();
    }
}
Monolog Bridge
==============

The Monolog bridge provides integration for
[Monolog](https://seldaek.github.io/monolog/) with various Symfony components.

Resources
---------

 * [Contributing](https://symfony.com/doc/current/contributing/index.html)
 * [Report issues](https://github.com/symfony/symfony/issues) and
   [send Pull Requests](https://github.com/symfony/symfony/pulls)
   in the [main Symfony repository](https://github.com/symfony/symfony)
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Bridge\Monolog\Formatter;

use _ContaoManager\Monolog\Formatter\FormatterInterface;
use _ContaoManager\Monolog\Logger;
use _ContaoManager\Monolog\LogRecord;
use _ContaoManager\Symfony\Component\Console\Formatter\OutputFormatter;
use _ContaoManager\Symfony\Component\VarDumper\Cloner\Data;
use _ContaoManager\Symfony\Component\VarDumper\Cloner\Stub;
use _ContaoManager\Symfony\Component\VarDumper\Cloner\VarCloner;
use _ContaoManager\Symfony\Component\VarDumper\Dumper\CliDumper;
/**
 * Formats incoming records for console output by coloring them depending on log level.
 *
 * @author Tobias Schultze <http://tobion.de>
 * @author Grégoire Pineau <lyrixx@lyrixx.info>
 *
 * @final since Symfony 6.1
 */
class ConsoleFormatter implements FormatterInterface
{
    use CompatibilityFormatter;
    public const SIMPLE_FORMAT = "%datetime% %start_tag%%level_name%%end_tag% <comment>[%channel%]</> %message%%context%%extra%\n";
    public const SIMPLE_DATE = 'H:i:s';
    private const LEVEL_COLOR_MAP = [Logger::DEBUG => 'fg=white', Logger::INFO => 'fg=green', Logger::NOTICE => 'fg=blue', Logger::WARNING => 'fg=cyan', Logger::ERROR => 'fg=yellow', Logger::CRITICAL => 'fg=red', Logger::ALERT => 'fg=red', Logger::EMERGENCY => 'fg=white;bg=red'];
    private array $options;
    private VarCloner $cloner;
    /**
     * @var resource|null
     */
    private $outputBuffer;
    private CliDumper $dumper;
    /**
     * Available options:
     *   * format: The format of the outputted log string. The following placeholders are supported: %datetime%, %start_tag%, %level_name%, %end_tag%, %channel%, %message%, %context%, %extra%;
     *   * date_format: The format of the outputted date string;
     *   * colors: If true, the log string contains ANSI code to add color;
     *   * multiline: If false, "context" and "extra" are dumped on one line.
     */
    public function __construct(array $options = [])
    {
        $this->options = array_replace(['format' => self::SIMPLE_FORMAT, 'date_format' => self::SIMPLE_DATE, 'colors' => \true, 'multiline' => \false, 'level_name_format' => '%-9s', 'ignore_empty_context_and_extra' => \true], $options);
        if (class_exists(VarCloner::class)) {
            $this->cloner = new VarCloner();
            $this->cloner->addCasters(['*' => $this->castObject(...)]);
            $this->outputBuffer = fopen('php://memory', 'r+');
            if ($this->options['multiline']) {
                $output = $this->outputBuffer;
            } else {
                $output = $this->echoLine(...);
            }
            $this->dumper = new CliDumper($output, null, CliDumper::DUMP_LIGHT_ARRAY | CliDumper::DUMP_COMMA_SEPARATOR);
        }
    }
    public function formatBatch(array $records): mixed
    {
        foreach ($records as $key => $record) {
            $records[$key] = $this->format($record);
        }
        return $records;
    }
    private function doFormat(array|LogRecord $record): mixed
    {
        if ($record instanceof LogRecord) {
            $record = $record->toArray();
        }
        $record = $this->replacePlaceHolder($record);
        if (!$this->options['ignore_empty_context_and_extra'] || !empty($record['context'])) {
            $context = ($this->options['multiline'] ? "\n" : ' ') . $this->dumpData($record['context']);
        } else {
            $context = '';
        }
        if (!$this->options['ignore_empty_context_and_extra'] || !empty($record['extra'])) {
            $extra = ($this->options['multiline'] ? "\n" : ' ') . $this->dumpData($record['extra']);
        } else {
            $extra = '';
        }
        $formatted = strtr($this->options['format'], ['%datetime%' => $record['datetime'] instanceof \DateTimeInterface ? $record['datetime']->format($this->options['date_format']) : $record['datetime'], '%start_tag%' => \sprintf('<%s>', self::LEVEL_COLOR_MAP[$record['level']]), '%level_name%' => \sprintf($this->options['level_name_format'], $record['level_name']), '%end_tag%' => '</>', '%channel%' => $record['channel'], '%message%' => $this->replacePlaceHolder($record)['message'], '%context%' => $context, '%extra%' => $extra]);
        return $formatted;
    }
    /**
     * @internal
     */
    public function echoLine(string $line, int $depth, string $indentPad): void
    {
        if (-1 !== $depth) {
            fwrite($this->outputBuffer, $line);
        }
    }
    /**
     * @internal
     */
    public function castObject(mixed $v, array $a, Stub $s, bool $isNested): array
    {
        if ($this->options['multiline']) {
            return $a;
        }
        if ($isNested && !$v instanceof \DateTimeInterface) {
            $s->cut = -1;
            $a = [];
        }
        return $a;
    }
    private function replacePlaceHolder(array $record): array
    {
        $message = $record['message'];
        if (!str_contains($message, '{')) {
            return $record;
        }
        $context = $record['context'];
        $replacements = [];
        foreach ($context as $k => $v) {
            // Remove quotes added by the dumper around string.
            $v = trim($this->dumpData($v, \false), '"');
            $v = OutputFormatter::escape($v);
            $replacements['{' . $k . '}'] = \sprintf('<comment>%s</>', $v);
        }
        $record['message'] = strtr($message, $replacements);
        return $record;
    }
    private function dumpData(mixed $data, ?bool $colors = null): string
    {
        if (!isset($this->dumper)) {
            return '';
        }
        if (null === $colors) {
            $this->dumper->setColors($this->options['colors']);
        } else {
            $this->dumper->setColors($colors);
        }
        if (!$data instanceof Data) {
            $data = $this->cloner->cloneVar($data);
        }
        $data = $data->withRefHandles(\false);
        $this->dumper->dump($data);
        $dump = stream_get_contents($this->outputBuffer, -1, 0);
        rewind($this->outputBuffer);
        ftruncate($this->outputBuffer, 0);
        return rtrim($dump);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Bridge\Monolog\Formatter;

use _ContaoManager\Monolog\Formatter\FormatterInterface;
use _ContaoManager\Monolog\LogRecord;
use _ContaoManager\Symfony\Component\VarDumper\Cloner\VarCloner;
/**
 * @author Grégoire Pineau <lyrixx@lyrixx.info>
 *
 * @final since Symfony 6.1
 */
class VarDumperFormatter implements FormatterInterface
{
    use CompatibilityFormatter;
    private VarCloner $cloner;
    public function __construct(?VarCloner $cloner = null)
    {
        $this->cloner = $cloner ?? new VarCloner();
    }
    private function doFormat(array|LogRecord $record): mixed
    {
        if ($record instanceof LogRecord) {
            $record = $record->toArray();
        }
        $record['context'] = $this->cloner->cloneVar($record['context']);
        $record['extra'] = $this->cloner->cloneVar($record['extra']);
        return $record;
    }
    public function formatBatch(array $records): mixed
    {
        foreach ($records as $k => $record) {
            $record[$k] = $this->format($record);
        }
        return $records;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Bridge\Monolog\Formatter;

use _ContaoManager\Monolog\Logger;
use _ContaoManager\Monolog\LogRecord;
if (Logger::API >= 3) {
    /**
     * The base class for compatibility between Monolog 3 LogRecord and Monolog 1/2 array records.
     *
     * @author Jordi Boggiano <j.boggiano@seld.be>
     *
     * @internal
     */
    trait CompatibilityFormatter
    {
        abstract private function doFormat(array|LogRecord $record): mixed;
        public function format(LogRecord $record): mixed
        {
            return $this->doFormat($record);
        }
    }
} else {
    /**
     * The base class for compatibility between Monolog 3 LogRecord and Monolog 1/2 array records.
     *
     * @author Jordi Boggiano <j.boggiano@seld.be>
     *
     * @internal
     */
    trait CompatibilityFormatter
    {
        abstract private function doFormat(array|LogRecord $record): mixed;
        public function format(array $record): mixed
        {
            return $this->doFormat($record);
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Bridge\Monolog\Command;

use _ContaoManager\Monolog\Formatter\FormatterInterface;
use _ContaoManager\Monolog\Handler\HandlerInterface;
use _ContaoManager\Monolog\Level;
use _ContaoManager\Monolog\Logger;
use _ContaoManager\Monolog\LogRecord;
use _ContaoManager\Symfony\Bridge\Monolog\Formatter\ConsoleFormatter;
use _ContaoManager\Symfony\Bridge\Monolog\Handler\ConsoleHandler;
use _ContaoManager\Symfony\Component\Console\Attribute\AsCommand;
use _ContaoManager\Symfony\Component\Console\Command\Command;
use _ContaoManager\Symfony\Component\Console\Exception\LogicException;
use _ContaoManager\Symfony\Component\Console\Exception\RuntimeException;
use _ContaoManager\Symfony\Component\Console\Input\InputInterface;
use _ContaoManager\Symfony\Component\Console\Input\InputOption;
use _ContaoManager\Symfony\Component\Console\Output\OutputInterface;
use _ContaoManager\Symfony\Component\ExpressionLanguage\ExpressionLanguage;
/**
 * @author Grégoire Pineau <lyrixx@lyrixx.info>
 */
#[AsCommand(name: 'server:log', description: 'Start a log server that displays logs in real time')]
class ServerLogCommand extends Command
{
    private const BG_COLOR = ['black', 'blue', 'cyan', 'green', 'magenta', 'red', 'white', 'yellow'];
    private ExpressionLanguage $el;
    private HandlerInterface $handler;
    public function isEnabled(): bool
    {
        if (!class_exists(ConsoleFormatter::class)) {
            return \false;
        }
        // based on a symfony/symfony package, it crashes due a missing FormatterInterface from monolog/monolog
        if (!interface_exists(FormatterInterface::class)) {
            return \false;
        }
        return parent::isEnabled();
    }
    /**
     * @return void
     */
    protected function configure()
    {
        if (!class_exists(ConsoleFormatter::class)) {
            return;
        }
        $this->addOption('host', null, InputOption::VALUE_REQUIRED, 'The server host', '0.0.0.0:9911')->addOption('format', null, InputOption::VALUE_REQUIRED, 'The line format', ConsoleFormatter::SIMPLE_FORMAT)->addOption('date-format', null, InputOption::VALUE_REQUIRED, 'The date format', ConsoleFormatter::SIMPLE_DATE)->addOption('filter', null, InputOption::VALUE_REQUIRED, 'An expression to filter log. Example: "level > 200 or channel in [\'app\', \'doctrine\']"')->setHelp(<<<'EOF'
<info>%command.name%</info> starts a log server to display in real time the log
messages generated by your application:

  <info>php %command.full_name%</info>

To filter the log messages using any ExpressionLanguage compatible expression, use the <comment>--filter</> option:

<info>php %command.full_name% --filter="level > 200 or channel in ['app', 'doctrine']"</info>
EOF
);
    }
    protected function execute(InputInterface $input, OutputInterface $output): int
    {
        $filter = $input->getOption('filter');
        if ($filter) {
            if (!class_exists(ExpressionLanguage::class)) {
                throw new LogicException('Package "symfony/expression-language" is required to use the "filter" option. Try running "composer require symfony/expression-language".');
            }
            $this->el = new ExpressionLanguage();
        }
        $this->handler = new ConsoleHandler($output, \true, [OutputInterface::VERBOSITY_NORMAL => Logger::DEBUG]);
        $this->handler->setFormatter(new ConsoleFormatter(['format' => str_replace('\n', "\n", $input->getOption('format')), 'date_format' => $input->getOption('date-format'), 'colors' => $output->isDecorated(), 'multiline' => OutputInterface::VERBOSITY_DEBUG <= $output->getVerbosity()]));
        if (!str_contains($host = $input->getOption('host'), '://')) {
            $host = 'tcp://' . $host;
        }
        if (!$socket = stream_socket_server($host, $errno, $errstr)) {
            throw new RuntimeException(\sprintf('Server start failed on "%s": ', $host) . $errstr . ' ' . $errno);
        }
        foreach ($this->getLogs($socket) as $clientId => $message) {
            $record = unserialize(base64_decode($message));
            // Impossible to decode the message, give up.
            if (\false === $record) {
                continue;
            }
            if ($filter && !$this->el->evaluate($filter, $record)) {
                continue;
            }
            $this->displayLog($output, $clientId, $record);
        }
        return 0;
    }
    private function getLogs($socket): iterable
    {
        $sockets = [(int) $socket => $socket];
        $write = [];
        while (\true) {
            $read = $sockets;
            stream_select($read, $write, $write, null);
            foreach ($read as $stream) {
                if ($socket === $stream) {
                    $stream = stream_socket_accept($socket);
                    $sockets[(int) $stream] = $stream;
                } elseif (feof($stream)) {
                    unset($sockets[(int) $stream]);
                    fclose($stream);
                } else {
                    yield (int) $stream => fgets($stream);
                }
            }
        }
    }
    private function displayLog(OutputInterface $output, int $clientId, array $record): void
    {
        if (isset($record['log_id'])) {
            $clientId = unpack('H*', $record['log_id'])[1];
        }
        $logBlock = \sprintf('<bg=%s> </>', self::BG_COLOR[$clientId % 8]);
        $output->write($logBlock);
        if (Logger::API >= 3) {
            $record = new LogRecord($record['datetime'], $record['channel'], Level::fromValue($record['level']), $record['message'], $record['context']->getValue(\true), $record['extra']->getValue(\true));
        }
        $this->handler->handle($record);
    }
}
{
    "name": "symfony\/monolog-bridge",
    "type": "symfony-bridge",
    "description": "Provides integration for Monolog with various Symfony components",
    "keywords": [],
    "homepage": "https:\/\/symfony.com",
    "license": "MIT",
    "authors": [
        {
            "name": "Fabien Potencier",
            "email": "fabien@symfony.com"
        },
        {
            "name": "Symfony Community",
            "homepage": "https:\/\/symfony.com\/contributors"
        }
    ],
    "require": {
        "php": ">=8.1",
        "monolog\/monolog": "^1.25.1|^2|^3",
        "symfony\/deprecation-contracts": "^2.5|^3",
        "symfony\/service-contracts": "^2.5|^3",
        "symfony\/http-kernel": "^5.4|^6.0|^7.0"
    },
    "require-dev": {
        "symfony\/console": "^5.4|^6.0|^7.0",
        "symfony\/http-client": "^5.4|^6.0|^7.0",
        "symfony\/security-core": "^5.4|^6.0|^7.0",
        "symfony\/var-dumper": "^5.4|^6.0|^7.0",
        "symfony\/mailer": "^5.4|^6.0|^7.0",
        "symfony\/mime": "^5.4|^6.0|^7.0",
        "symfony\/messenger": "^5.4|^6.0|^7.0"
    },
    "conflict": {
        "symfony\/console": "<5.4",
        "symfony\/http-foundation": "<5.4",
        "symfony\/security-core": "<5.4"
    },
    "autoload": {
        "psr-4": {
            "_ContaoManager\\Symfony\\Bridge\\Monolog\\": ""
        },
        "exclude-from-classmap": [
            "\/Tests\/"
        ]
    },
    "minimum-stability": "dev"
}<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Cache\DataCollector;

use _ContaoManager\Symfony\Component\Cache\Adapter\TraceableAdapter;
use _ContaoManager\Symfony\Component\Cache\Adapter\TraceableAdapterEvent;
use _ContaoManager\Symfony\Component\HttpFoundation\Request;
use _ContaoManager\Symfony\Component\HttpFoundation\Response;
use _ContaoManager\Symfony\Component\HttpKernel\DataCollector\DataCollector;
use _ContaoManager\Symfony\Component\HttpKernel\DataCollector\LateDataCollectorInterface;
/**
 * @author Aaron Scherer <aequasi@gmail.com>
 * @author Tobias Nyholm <tobias.nyholm@gmail.com>
 *
 * @final
 */
class CacheDataCollector extends DataCollector implements LateDataCollectorInterface
{
    /**
     * @var TraceableAdapter[]
     */
    private array $instances = [];
    public function addInstance(string $name, TraceableAdapter $instance): void
    {
        $this->instances[$name] = $instance;
    }
    public function collect(Request $request, Response $response, ?\Throwable $exception = null): void
    {
        $this->lateCollect();
    }
    public function reset(): void
    {
        $this->data = [];
        foreach ($this->instances as $instance) {
            $instance->clearCalls();
        }
    }
    public function lateCollect(): void
    {
        $empty = ['calls' => [], 'adapters' => [], 'config' => [], 'options' => [], 'statistics' => []];
        $this->data = ['instances' => $empty, 'total' => $empty];
        foreach ($this->instances as $name => $instance) {
            $this->data['instances']['calls'][$name] = $instance->getCalls();
            $this->data['instances']['adapters'][$name] = get_debug_type($instance->getPool());
        }
        $this->data['instances']['statistics'] = $this->calculateStatistics();
        $this->data['total']['statistics'] = $this->calculateTotalStatistics();
        $this->data['instances']['calls'] = $this->cloneVar($this->data['instances']['calls']);
    }
    public function getName(): string
    {
        return 'cache';
    }
    /**
     * Method returns amount of logged Cache reads: "get" calls.
     */
    public function getStatistics(): array
    {
        return $this->data['instances']['statistics'];
    }
    /**
     * Method returns the statistic totals.
     */
    public function getTotals(): array
    {
        return $this->data['total']['statistics'];
    }
    /**
     * Method returns all logged Cache call objects.
     */
    public function getCalls(): mixed
    {
        return $this->data['instances']['calls'];
    }
    /**
     * Method returns all logged Cache adapter classes.
     */
    public function getAdapters(): array
    {
        return $this->data['instances']['adapters'];
    }
    private function calculateStatistics(): array
    {
        $statistics = [];
        foreach ($this->data['instances']['calls'] as $name => $calls) {
            $statistics[$name] = ['calls' => 0, 'time' => 0, 'reads' => 0, 'writes' => 0, 'deletes' => 0, 'hits' => 0, 'misses' => 0];
            /** @var TraceableAdapterEvent $call */
            foreach ($calls as $call) {
                ++$statistics[$name]['calls'];
                $statistics[$name]['time'] += ($call->end ?? microtime(\true)) - $call->start;
                if ('get' === $call->name) {
                    ++$statistics[$name]['reads'];
                    if ($call->hits) {
                        ++$statistics[$name]['hits'];
                    } else {
                        ++$statistics[$name]['misses'];
                        ++$statistics[$name]['writes'];
                    }
                } elseif ('getItem' === $call->name) {
                    ++$statistics[$name]['reads'];
                    if ($call->hits) {
                        ++$statistics[$name]['hits'];
                    } else {
                        ++$statistics[$name]['misses'];
                    }
                } elseif ('getItems' === $call->name) {
                    $statistics[$name]['reads'] += $call->hits + $call->misses;
                    $statistics[$name]['hits'] += $call->hits;
                    $statistics[$name]['misses'] += $call->misses;
                } elseif ('hasItem' === $call->name) {
                    ++$statistics[$name]['reads'];
                    foreach ($call->result ?? [] as $result) {
                        ++$statistics[$name][$result ? 'hits' : 'misses'];
                    }
                } elseif ('save' === $call->name) {
                    ++$statistics[$name]['writes'];
                } elseif ('saveDeferred' === $call->name) {
                    ++$statistics[$name]['writes'];
                } elseif ('deleteItem' === $call->name) {
                    ++$statistics[$name]['deletes'];
                }
            }
            if ($statistics[$name]['reads']) {
                $statistics[$name]['hit_read_ratio'] = round(100 * $statistics[$name]['hits'] / $statistics[$name]['reads'], 2);
            } else {
                $statistics[$name]['hit_read_ratio'] = null;
            }
        }
        return $statistics;
    }
    private function calculateTotalStatistics(): array
    {
        $statistics = $this->getStatistics();
        $totals = ['calls' => 0, 'time' => 0, 'reads' => 0, 'writes' => 0, 'deletes' => 0, 'hits' => 0, 'misses' => 0];
        foreach ($statistics as $name => $values) {
            foreach ($totals as $key => $value) {
                $totals[$key] += $statistics[$name][$key];
            }
        }
        if ($totals['reads']) {
            $totals['hit_read_ratio'] = round(100 * $totals['hits'] / $totals['reads'], 2);
        } else {
            $totals['hit_read_ratio'] = null;
        }
        return $totals;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Cache;

use _ContaoManager\Psr\Cache\CacheItemInterface;
use _ContaoManager\Psr\Log\LoggerInterface;
use _ContaoManager\Symfony\Component\Cache\Exception\InvalidArgumentException;
use _ContaoManager\Symfony\Component\Cache\Exception\LogicException;
use _ContaoManager\Symfony\Contracts\Cache\ItemInterface;
/**
 * @author Nicolas Grekas <p@tchwork.com>
 */
final class CacheItem implements ItemInterface
{
    private const METADATA_EXPIRY_OFFSET = 1527506807;
    private const VALUE_WRAPPER = "\xa9";
    protected string $key;
    protected mixed $value = null;
    protected bool $isHit = \false;
    protected float|int|null $expiry = null;
    protected array $metadata = [];
    protected array $newMetadata = [];
    protected ?CacheItemInterface $innerItem = null;
    protected ?string $poolHash = null;
    protected bool $isTaggable = \false;
    public function getKey(): string
    {
        return $this->key;
    }
    public function get(): mixed
    {
        return $this->value;
    }
    public function isHit(): bool
    {
        return $this->isHit;
    }
    /**
     * @return $this
     */
    public function set($value): static
    {
        $this->value = $value;
        return $this;
    }
    /**
     * @return $this
     */
    public function expiresAt(?\DateTimeInterface $expiration): static
    {
        $this->expiry = null !== $expiration ? (float) $expiration->format('U.u') : null;
        return $this;
    }
    /**
     * @return $this
     */
    public function expiresAfter(mixed $time): static
    {
        if (null === $time) {
            $this->expiry = null;
        } elseif ($time instanceof \DateInterval) {
            $this->expiry = microtime(\true) + \DateTimeImmutable::createFromFormat('U', 0)->add($time)->format('U.u');
        } elseif (\is_int($time)) {
            $this->expiry = $time + microtime(\true);
        } else {
            throw new InvalidArgumentException(\sprintf('Expiration date must be an integer, a DateInterval or null, "%s" given.', get_debug_type($time)));
        }
        return $this;
    }
    public function tag(mixed $tags): static
    {
        if (!$this->isTaggable) {
            throw new LogicException(\sprintf('Cache item "%s" comes from a non tag-aware pool: you cannot tag it.', $this->key));
        }
        if (!\is_array($tags) && !$tags instanceof \Traversable) {
            // don't use is_iterable(), it's slow
            $tags = [$tags];
        }
        foreach ($tags as $tag) {
            if (!\is_string($tag) && !$tag instanceof \Stringable) {
                throw new InvalidArgumentException(\sprintf('Cache tag must be string or object that implements __toString(), "%s" given.', get_debug_type($tag)));
            }
            $tag = (string) $tag;
            if (isset($this->newMetadata[self::METADATA_TAGS][$tag])) {
                continue;
            }
            if ('' === $tag) {
                throw new InvalidArgumentException('Cache tag length must be greater than zero.');
            }
            if (\false !== strpbrk($tag, self::RESERVED_CHARACTERS)) {
                throw new InvalidArgumentException(\sprintf('Cache tag "%s" contains reserved characters "%s".', $tag, self::RESERVED_CHARACTERS));
            }
            $this->newMetadata[self::METADATA_TAGS][$tag] = $tag;
        }
        return $this;
    }
    public function getMetadata(): array
    {
        return $this->metadata;
    }
    /**
     * Validates a cache key according to PSR-6.
     *
     * @param mixed $key The key to validate
     *
     * @throws InvalidArgumentException When $key is not valid
     */
    public static function validateKey($key): string
    {
        if (!\is_string($key)) {
            throw new InvalidArgumentException(\sprintf('Cache key must be string, "%s" given.', get_debug_type($key)));
        }
        if ('' === $key) {
            throw new InvalidArgumentException('Cache key length must be greater than zero.');
        }
        if (\false !== strpbrk($key, self::RESERVED_CHARACTERS)) {
            throw new InvalidArgumentException(\sprintf('Cache key "%s" contains reserved characters "%s".', $key, self::RESERVED_CHARACTERS));
        }
        return $key;
    }
    /**
     * Internal logging helper.
     *
     * @internal
     */
    public static function log(?LoggerInterface $logger, string $message, array $context = []): void
    {
        if ($logger) {
            $logger->warning($message, $context);
        } else {
            $replace = [];
            foreach ($context as $k => $v) {
                if (\is_scalar($v)) {
                    $replace['{' . $k . '}'] = $v;
                }
            }
            @trigger_error(strtr($message, $replace), \E_USER_WARNING);
        }
    }
    private function pack(): mixed
    {
        if (!$m = $this->newMetadata) {
            return $this->value;
        }
        $valueWrapper = self::VALUE_WRAPPER;
        if ($this->value instanceof $valueWrapper) {
            return new $valueWrapper($this->value->value, $m + ['expiry' => $this->expiry] + $this->value->metadata);
        }
        return new $valueWrapper($this->value, $m + ['expiry' => $this->expiry]);
    }
    private function unpack(): bool
    {
        $v = $this->value;
        $valueWrapper = self::VALUE_WRAPPER;
        if ($v instanceof $valueWrapper) {
            $this->value = $v->value;
            $this->metadata = $v->metadata;
            return \true;
        }
        if (!\is_array($v) || 1 !== \count($v) || 10 !== \strlen($k = (string) array_key_first($v)) || "\x9d" !== $k[0] || "\x00" !== $k[5] || "_" !== $k[9]) {
            return \false;
        }
        // BC with pools populated before v6.1
        $this->value = $v[$k];
        $this->metadata = unpack('Vexpiry/Nctime', substr($k, 1, -1));
        $this->metadata['expiry'] += self::METADATA_EXPIRY_OFFSET;
        return \true;
    }
}
// @php-cs-fixer-ignore protected_to_private Friend-level scope access relies on protected properties
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Cache;

use _ContaoManager\Psr\Cache\CacheException as Psr6CacheException;
use _ContaoManager\Psr\Cache\CacheItemPoolInterface;
use _ContaoManager\Psr\SimpleCache\CacheException as SimpleCacheException;
use _ContaoManager\Psr\SimpleCache\CacheInterface;
use _ContaoManager\Symfony\Component\Cache\Adapter\AdapterInterface;
use _ContaoManager\Symfony\Component\Cache\Exception\InvalidArgumentException;
use _ContaoManager\Symfony\Component\Cache\Traits\ProxyTrait;
use _ContaoManager\Symfony\Contracts\Cache\ItemInterface;
/**
 * Turns a PSR-6 cache into a PSR-16 one.
 *
 * @author Nicolas Grekas <p@tchwork.com>
 */
class Psr16Cache implements CacheInterface, PruneableInterface, ResettableInterface
{
    use ProxyTrait;
    private ?\Closure $createCacheItem = null;
    private ?CacheItem $cacheItemPrototype = null;
    private static \Closure $packCacheItem;
    public function __construct(CacheItemPoolInterface $pool)
    {
        $this->pool = $pool;
        if (!$pool instanceof AdapterInterface) {
            return;
        }
        $cacheItemPrototype =& $this->cacheItemPrototype;
        $createCacheItem = \Closure::bind(static function ($key, $value, $allowInt = \false) use (&$cacheItemPrototype) {
            $item = clone $cacheItemPrototype;
            $item->poolHash = $item->innerItem = null;
            if ($allowInt && \is_int($key)) {
                $item->key = (string) $key;
            } else {
                \assert('' !== CacheItem::validateKey($key));
                $item->key = $key;
            }
            $item->value = $value;
            $item->isHit = \false;
            return $item;
        }, null, CacheItem::class);
        $this->createCacheItem = function ($key, $value, $allowInt = \false) use ($createCacheItem) {
            if (null === $this->cacheItemPrototype) {
                $this->get($allowInt && \is_int($key) ? (string) $key : $key);
            }
            $this->createCacheItem = $createCacheItem;
            return $createCacheItem($key, null, $allowInt)->set($value);
        };
        self::$packCacheItem ??= \Closure::bind(static function (CacheItem $item) {
            // Only re-pack if there's timing metadata (for Psr16Adapter compatibility)
            // Don't re-pack if only tags metadata exists (TagAwareAdapter direct use case)
            if (!isset($item->metadata[ItemInterface::METADATA_CTIME]) && !isset($item->metadata[ItemInterface::METADATA_EXPIRY])) {
                return $item->value;
            }
            $item->newMetadata = $item->metadata;
            return $item->pack();
        }, null, CacheItem::class);
    }
    public function get($key, $default = null): mixed
    {
        try {
            $item = $this->pool->getItem($key);
        } catch (SimpleCacheException $e) {
            throw $e;
        } catch (Psr6CacheException $e) {
            throw new InvalidArgumentException($e->getMessage(), $e->getCode(), $e);
        }
        if (null === $this->cacheItemPrototype) {
            $this->cacheItemPrototype = clone $item;
            $this->cacheItemPrototype->set(null);
        }
        return $item->isHit() ? $item->get() : $default;
    }
    public function set($key, $value, $ttl = null): bool
    {
        try {
            if (null !== $f = $this->createCacheItem) {
                $item = $f($key, $value);
            } else {
                $item = $this->pool->getItem($key)->set($value);
            }
        } catch (SimpleCacheException $e) {
            throw $e;
        } catch (Psr6CacheException $e) {
            throw new InvalidArgumentException($e->getMessage(), $e->getCode(), $e);
        }
        if (null !== $ttl) {
            $item->expiresAfter($ttl);
        }
        return $this->pool->save($item);
    }
    public function delete($key): bool
    {
        try {
            return $this->pool->deleteItem($key);
        } catch (SimpleCacheException $e) {
            throw $e;
        } catch (Psr6CacheException $e) {
            throw new InvalidArgumentException($e->getMessage(), $e->getCode(), $e);
        }
    }
    public function clear(): bool
    {
        return $this->pool->clear();
    }
    public function getMultiple($keys, $default = null): iterable
    {
        if ($keys instanceof \Traversable) {
            $keys = iterator_to_array($keys, \false);
        } elseif (!\is_array($keys)) {
            throw new InvalidArgumentException(\sprintf('Cache keys must be array or Traversable, "%s" given.', get_debug_type($keys)));
        }
        try {
            $items = $this->pool->getItems($keys);
        } catch (SimpleCacheException $e) {
            throw $e;
        } catch (Psr6CacheException $e) {
            throw new InvalidArgumentException($e->getMessage(), $e->getCode(), $e);
        }
        $values = [];
        if (!$this->pool instanceof AdapterInterface) {
            foreach ($items as $key => $item) {
                $values[$key] = $item->isHit() ? $item->get() : $default;
            }
            return $values;
        }
        foreach ($items as $key => $item) {
            $values[$key] = $item->isHit() ? (self::$packCacheItem)($item) : $default;
        }
        return $values;
    }
    public function setMultiple($values, $ttl = null): bool
    {
        $valuesIsArray = \is_array($values);
        if (!$valuesIsArray && !$values instanceof \Traversable) {
            throw new InvalidArgumentException(\sprintf('Cache values must be array or Traversable, "%s" given.', get_debug_type($values)));
        }
        $items = [];
        try {
            if (null !== $f = $this->createCacheItem) {
                $valuesIsArray = \false;
                foreach ($values as $key => $value) {
                    $items[$key] = $f($key, $value, \true);
                }
            } elseif ($valuesIsArray) {
                $items = [];
                foreach ($values as $key => $value) {
                    $items[] = (string) $key;
                }
                $items = $this->pool->getItems($items);
            } else {
                foreach ($values as $key => $value) {
                    if (\is_int($key)) {
                        $key = (string) $key;
                    }
                    $items[$key] = $this->pool->getItem($key)->set($value);
                }
            }
        } catch (SimpleCacheException $e) {
            throw $e;
        } catch (Psr6CacheException $e) {
            throw new InvalidArgumentException($e->getMessage(), $e->getCode(), $e);
        }
        $ok = \true;
        foreach ($items as $key => $item) {
            if ($valuesIsArray) {
                $item->set($values[$key]);
            }
            if (null !== $ttl) {
                $item->expiresAfter($ttl);
            }
            $ok = $this->pool->saveDeferred($item) && $ok;
        }
        return $this->pool->commit() && $ok;
    }
    public function deleteMultiple($keys): bool
    {
        if ($keys instanceof \Traversable) {
            $keys = iterator_to_array($keys, \false);
        } elseif (!\is_array($keys)) {
            throw new InvalidArgumentException(\sprintf('Cache keys must be array or Traversable, "%s" given.', get_debug_type($keys)));
        }
        try {
            return $this->pool->deleteItems($keys);
        } catch (SimpleCacheException $e) {
            throw $e;
        } catch (Psr6CacheException $e) {
            throw new InvalidArgumentException($e->getMessage(), $e->getCode(), $e);
        }
    }
    public function has($key): bool
    {
        try {
            return $this->pool->hasItem($key);
        } catch (SimpleCacheException $e) {
            throw $e;
        } catch (Psr6CacheException $e) {
            throw new InvalidArgumentException($e->getMessage(), $e->getCode(), $e);
        }
    }
}
Copyright (c) 2016-present Fabien Potencier

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is furnished
to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Cache;

/**
 * Interface extends psr-6 and psr-16 caches to allow for pruning (deletion) of all expired cache items.
 */
interface PruneableInterface
{
    public function prune(): bool;
}
CHANGELOG
=========

6.4
---

 * `EarlyExpirationHandler` no longer implements `MessageHandlerInterface`, rely on `AsMessageHandler` instead

6.3
---

 * Add support for Relay PHP extension for Redis
 * Updates to allow Redis cluster connections using predis/predis:^2.0
 * Add optional parameter `$isSameDatabase` to `DoctrineDbalAdapter::configureSchema()`

6.1
---

 * Add support for ACL auth in RedisAdapter
 * Improve reliability and performance of `TagAwareAdapter` by making tag versions an integral part of item value

6.0
---

 * Remove `DoctrineProvider` and `DoctrineAdapter`
 * Remove support of Doctrine DBAL in `PdoAdapter`

5.4
---

 * Deprecate `DoctrineProvider` and `DoctrineAdapter` because these classes have been added to the `doctrine/cache` package
 * Add `DoctrineDbalAdapter` identical to `PdoAdapter` for `Doctrine\DBAL\Connection` or DBAL URL
 * Deprecate usage of `PdoAdapter` with `Doctrine\DBAL\Connection` or DBAL URL

5.3
---

 * added support for connecting to Redis Sentinel clusters when using the Redis PHP extension
 * add support for a custom serializer to the `ApcuAdapter` class

5.2.0
-----

 * added integration with Messenger to allow computing cached values in a worker
 * allow ISO 8601 time intervals to specify default lifetime

5.1.0
-----

 * added max-items + LRU + max-lifetime capabilities to `ArrayCache`
 * added `CouchbaseBucketAdapter`
 * added context `cache-adapter` to log messages

5.0.0
-----

 * removed all PSR-16 implementations in the `Simple` namespace
 * removed `SimpleCacheAdapter`
 * removed `AbstractAdapter::unserialize()`
 * removed `CacheItem::getPreviousTags()`

4.4.0
-----

 * added support for connecting to Redis Sentinel clusters
 * added argument `$prefix` to `AdapterInterface::clear()`
 * improved `RedisTagAwareAdapter` to support Redis server >= 2.8 and up to 4B items per tag
 * added `TagAwareMarshaller` for optimized data storage when using `AbstractTagAwareAdapter`
 * added `DeflateMarshaller` to compress serialized values
 * removed support for phpredis 4 `compression`
 * [BC BREAK] `RedisTagAwareAdapter` is not compatible with `RedisCluster` from `Predis` anymore, use `phpredis` instead
 * Marked the `CacheDataCollector` class as `@final`.
 * added `SodiumMarshaller` to encrypt/decrypt values using libsodium

4.3.0
-----

 * removed `psr/simple-cache` dependency, run `composer require psr/simple-cache` if you need it
 * deprecated all PSR-16 adapters, use `Psr16Cache` or `Symfony\Contracts\Cache\CacheInterface` implementations instead
 * deprecated `SimpleCacheAdapter`, use `Psr16Adapter` instead

4.2.0
-----

 * added support for connecting to Redis clusters via DSN
 * added support for configuring multiple Memcached servers via DSN
 * added `MarshallerInterface` and `DefaultMarshaller` to allow changing the serializer and provide one that automatically uses igbinary when available
 * implemented `CacheInterface`, which provides stampede protection via probabilistic early expiration and should become the preferred way to use a cache
 * added sub-second expiry accuracy for backends that support it
 * added support for phpredis 4 `compression` and `tcp_keepalive` options
 * added automatic table creation when using Doctrine DBAL with PDO-based backends
 * throw `LogicException` when `CacheItem::tag()` is called on an item coming from a non tag-aware pool
 * deprecated `CacheItem::getPreviousTags()`, use `CacheItem::getMetadata()` instead
 * deprecated the `AbstractAdapter::unserialize()` and `AbstractCache::unserialize()` methods
 * added `CacheCollectorPass` (originally in `FrameworkBundle`)
 * added `CachePoolClearerPass` (originally in `FrameworkBundle`)
 * added `CachePoolPass` (originally in `FrameworkBundle`)
 * added `CachePoolPrunerPass` (originally in `FrameworkBundle`)

3.4.0
-----

 * added using options from Memcached DSN
 * added PruneableInterface so PSR-6 or PSR-16 cache implementations can declare support for manual stale cache pruning
 * added prune logic to FilesystemTrait, PhpFilesTrait, PdoTrait, TagAwareAdapter and ChainTrait
 * now FilesystemAdapter, PhpFilesAdapter, FilesystemCache, PhpFilesCache, PdoAdapter, PdoCache, ChainAdapter, and
   ChainCache implement PruneableInterface and support manual stale cache pruning

3.3.0
-----

 * added CacheItem::getPreviousTags() to get bound tags coming from the pool storage if any
 * added PSR-16 "Simple Cache" implementations for all existing PSR-6 adapters
 * added Psr6Cache and SimpleCacheAdapter for bidirectional interoperability between PSR-6 and PSR-16
 * added MemcachedAdapter (PSR-6) and MemcachedCache (PSR-16)
 * added TraceableAdapter (PSR-6) and TraceableCache (PSR-16)

3.2.0
-----

 * added TagAwareAdapter for tags-based invalidation
 * added PdoAdapter with PDO and Doctrine DBAL support
 * added PhpArrayAdapter and PhpFilesAdapter for OPcache-backed shared memory storage (PHP 7+ only)
 * added NullAdapter

3.1.0
-----

 * added the component with strict PSR-6 implementations
 * added ApcuAdapter, ArrayAdapter, FilesystemAdapter and RedisAdapter
 * added AbstractAdapter, ChainAdapter and ProxyAdapter
 * added DoctrineAdapter and DoctrineProvider for bidirectional interoperability with Doctrine Cache
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Cache\Traits;

/**
 * This file acts as a wrapper to the \RedisCluster implementation so it can accept the same type of calls as
 *  individual \Redis objects.
 *
 * Calls are made to individual nodes via: RedisCluster->{method}($host, ...args)'
 *  according to https://github.com/phpredis/phpredis/blob/develop/cluster.markdown#directed-node-commands
 *
 * @author Jack Thomas <jack.thomas@solidalpha.com>
 *
 * @internal
 */
class RedisClusterNodeProxy
{
    public function __construct(private array $host, private \RedisCluster $redis)
    {
    }
    public function __call(string $method, array $args)
    {
        return $this->redis->{$method}($this->host, ...$args);
    }
    public function scan(&$iIterator, $strPattern = null, $iCount = null)
    {
        return $this->redis->scan($iIterator, $this->host, $strPattern, $iCount);
    }
    public function getOption($name)
    {
        return $this->redis->getOption($name);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Cache\Traits;

if (version_compare(phpversion('relay'), '0.8.1', '>=')) {
    /**
     * @internal
     */
    trait RelayProxyTrait
    {
        public function jsonArrAppend($key, $value_or_array, $path = null): \Relay\Relay|array|false
        {
            return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->jsonArrAppend(...\func_get_args());
        }
        public function jsonArrIndex($key, $path, $value, $start = 0, $stop = -1): \Relay\Relay|array|false
        {
            return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->jsonArrIndex(...\func_get_args());
        }
        public function jsonArrInsert($key, $path, $index, $value, ...$other_values): \Relay\Relay|array|false
        {
            return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->jsonArrInsert(...\func_get_args());
        }
        public function jsonArrLen($key, $path = null): \Relay\Relay|array|false
        {
            return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->jsonArrLen(...\func_get_args());
        }
        public function jsonArrPop($key, $path = null, $index = -1): \Relay\Relay|array|false
        {
            return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->jsonArrPop(...\func_get_args());
        }
        public function jsonArrTrim($key, $path, $start, $stop): \Relay\Relay|array|false
        {
            return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->jsonArrTrim(...\func_get_args());
        }
        public function jsonClear($key, $path = null): \Relay\Relay|false|int
        {
            return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->jsonClear(...\func_get_args());
        }
        public function jsonDebug($command, $key, $path = null): \Relay\Relay|false|int
        {
            return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->jsonDebug(...\func_get_args());
        }
        public function jsonDel($key, $path = null): \Relay\Relay|false|int
        {
            return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->jsonDel(...\func_get_args());
        }
        public function jsonForget($key, $path = null): \Relay\Relay|false|int
        {
            return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->jsonForget(...\func_get_args());
        }
        public function jsonGet($key, $options = [], ...$paths): mixed
        {
            return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->jsonGet(...\func_get_args());
        }
        public function jsonMerge($key, $path, $value): \Relay\Relay|bool
        {
            return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->jsonMerge(...\func_get_args());
        }
        public function jsonMget($key_or_array, $path): \Relay\Relay|array|false
        {
            return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->jsonMget(...\func_get_args());
        }
        public function jsonMset($key, $path, $value, ...$other_triples): \Relay\Relay|bool
        {
            return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->jsonMset(...\func_get_args());
        }
        public function jsonNumIncrBy($key, $path, $value): \Relay\Relay|array|false
        {
            return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->jsonNumIncrBy(...\func_get_args());
        }
        public function jsonNumMultBy($key, $path, $value): \Relay\Relay|array|false
        {
            return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->jsonNumMultBy(...\func_get_args());
        }
        public function jsonObjKeys($key, $path = null): \Relay\Relay|array|false
        {
            return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->jsonObjKeys(...\func_get_args());
        }
        public function jsonObjLen($key, $path = null): \Relay\Relay|array|false
        {
            return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->jsonObjLen(...\func_get_args());
        }
        public function jsonResp($key, $path = null): \Relay\Relay|array|false|int|string
        {
            return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->jsonResp(...\func_get_args());
        }
        public function jsonSet($key, $path, $value, $condition = null): \Relay\Relay|bool
        {
            return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->jsonSet(...\func_get_args());
        }
        public function jsonStrAppend($key, $value, $path = null): \Relay\Relay|array|false
        {
            return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->jsonStrAppend(...\func_get_args());
        }
        public function jsonStrLen($key, $path = null): \Relay\Relay|array|false
        {
            return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->jsonStrLen(...\func_get_args());
        }
        public function jsonToggle($key, $path): \Relay\Relay|array|false
        {
            return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->jsonToggle(...\func_get_args());
        }
        public function jsonType($key, $path = null): \Relay\Relay|array|false
        {
            return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->jsonType(...\func_get_args());
        }
    }
} else {
    /**
     * @internal
     */
    trait RelayProxyTrait
    {
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Cache\Traits;

use _ContaoManager\Predis\Command\Redis\UNLINK;
use _ContaoManager\Predis\Connection\Aggregate\ClusterInterface;
use _ContaoManager\Predis\Connection\Aggregate\RedisCluster;
use _ContaoManager\Predis\Connection\Aggregate\ReplicationInterface;
use _ContaoManager\Predis\Connection\Cluster\ClusterInterface as Predis2ClusterInterface;
use _ContaoManager\Predis\Connection\Cluster\RedisCluster as Predis2RedisCluster;
use _ContaoManager\Predis\Connection\Replication\ReplicationInterface as Predis2ReplicationInterface;
use _ContaoManager\Predis\Response\ErrorInterface;
use _ContaoManager\Predis\Response\Status;
use Relay\Relay;
use Relay\Sentinel;
use _ContaoManager\Symfony\Component\Cache\Exception\CacheException;
use _ContaoManager\Symfony\Component\Cache\Exception\InvalidArgumentException;
use _ContaoManager\Symfony\Component\Cache\Marshaller\DefaultMarshaller;
use _ContaoManager\Symfony\Component\Cache\Marshaller\MarshallerInterface;
/**
 * @author Aurimas Niekis <aurimas@niekis.lt>
 * @author Nicolas Grekas <p@tchwork.com>
 *
 * @internal
 */
trait RedisTrait
{
    private static array $defaultConnectionOptions = ['class' => null, 'auth' => null, 'persistent' => 0, 'persistent_id' => null, 'timeout' => 30, 'read_timeout' => 0, 'retry_interval' => 0, 'tcp_keepalive' => 0, 'lazy' => null, 'redis_cluster' => \false, 'redis_sentinel' => null, 'dbindex' => 0, 'failover' => 'none', 'ssl' => null];
    private \Redis|Relay|\RedisArray|\RedisCluster|\_ContaoManager\Predis\ClientInterface $redis;
    private MarshallerInterface $marshaller;
    private function init(\Redis|Relay|\RedisArray|\RedisCluster|\_ContaoManager\Predis\ClientInterface $redis, string $namespace, int $defaultLifetime, ?MarshallerInterface $marshaller): void
    {
        parent::__construct($namespace, $defaultLifetime);
        if (preg_match('#[^-+_.A-Za-z0-9]#', $namespace, $match)) {
            throw new InvalidArgumentException(\sprintf('RedisAdapter namespace contains "%s" but only characters in [-+_.A-Za-z0-9] are allowed.', $match[0]));
        }
        if ($redis instanceof \_ContaoManager\Predis\ClientInterface && $redis->getOptions()->exceptions) {
            $options = clone $redis->getOptions();
            \Closure::bind(function () {
                $this->options['exceptions'] = \false;
            }, $options, $options)();
            $redis = new $redis($redis->getConnection(), $options);
        }
        $this->redis = $redis;
        $this->marshaller = $marshaller ?? new DefaultMarshaller();
    }
    /**
     * Creates a Redis connection using a DSN configuration.
     *
     * Example DSN:
     *   - redis://localhost
     *   - redis://example.com:1234
     *   - redis://secret@example.com/13
     *   - redis:///var/run/redis.sock
     *   - redis://secret@/var/run/redis.sock/13
     *
     * @param array $options See self::$defaultConnectionOptions
     *
     * @throws InvalidArgumentException when the DSN is invalid
     */
    public static function createConnection(
        #[\SensitiveParameter]
        string $dsn,
        array $options = []
    ): \Redis|\RedisArray|\RedisCluster|\_ContaoManager\Predis\ClientInterface|Relay
    {
        if (str_starts_with($dsn, 'redis:')) {
            $scheme = 'redis';
        } elseif (str_starts_with($dsn, 'rediss:')) {
            $scheme = 'rediss';
        } else {
            throw new InvalidArgumentException('Invalid Redis DSN: it does not start with "redis[s]:".');
        }
        if (!\extension_loaded('redis') && !\extension_loaded('relay') && !class_exists(\_ContaoManager\Predis\Client::class)) {
            throw new CacheException('Cannot find the "redis" extension nor the "relay" extension nor the "predis/predis" package.');
        }
        $auth = null;
        $params = preg_replace_callback('#^' . $scheme . ':(//)?(?:(?:(?<user>[^:@]*+):)?(?<password>[^@]*+)@)?#', function ($m) use (&$auth) {
            if (isset($m['password'])) {
                if (\in_array($m['user'], ['', 'default'], \true)) {
                    $auth = rawurldecode($m['password']);
                } else {
                    $auth = [rawurldecode($m['user']), rawurldecode($m['password'])];
                }
                if ('' === $auth) {
                    $auth = null;
                }
            }
            return 'file:' . ($m[1] ?? '');
        }, $dsn);
        if (\false === $params = parse_url($params)) {
            throw new InvalidArgumentException('Invalid Redis DSN.');
        }
        $query = $hosts = [];
        $tls = 'rediss' === $scheme;
        $tcpScheme = $tls ? 'tls' : 'tcp';
        if (isset($params['query'])) {
            parse_str($params['query'], $query);
            if (isset($query['host'])) {
                if (!\is_array($hosts = $query['host'])) {
                    throw new InvalidArgumentException('Invalid Redis DSN: query parameter "host" must be an array.');
                }
                foreach ($hosts as $host => $parameters) {
                    if (\is_string($parameters)) {
                        parse_str($parameters, $parameters);
                    }
                    if (\false === $i = strrpos($host, ':')) {
                        $hosts[$host] = ['scheme' => $tcpScheme, 'host' => $host, 'port' => 6379] + $parameters;
                    } elseif ($port = (int) substr($host, 1 + $i)) {
                        $hosts[$host] = ['scheme' => $tcpScheme, 'host' => substr($host, 0, $i), 'port' => $port] + $parameters;
                    } else {
                        $hosts[$host] = ['scheme' => 'unix', 'path' => substr($host, 0, $i)] + $parameters;
                    }
                }
                $hosts = array_values($hosts);
            }
        }
        if (isset($params['host']) || isset($params['path'])) {
            if (!isset($params['dbindex']) && isset($params['path'])) {
                if (preg_match('#/(\d+)?$#', $params['path'], $m)) {
                    $params['dbindex'] = $m[1] ?? $query['dbindex'] ?? '0';
                    $params['path'] = substr($params['path'], 0, -\strlen($m[0]));
                } elseif (isset($params['host'])) {
                    throw new InvalidArgumentException('Invalid Redis DSN: parameter "dbindex" must be a number.');
                }
            }
            if (isset($params['host'])) {
                array_unshift($hosts, ['scheme' => $tcpScheme, 'host' => $params['host'], 'port' => $params['port'] ?? 6379]);
            } else {
                array_unshift($hosts, ['scheme' => 'unix', 'path' => $params['path']]);
            }
        }
        if (!$hosts) {
            throw new InvalidArgumentException('Invalid Redis DSN: missing host.');
        }
        if (isset($params['dbindex'], $query['dbindex']) && $params['dbindex'] !== $query['dbindex']) {
            throw new InvalidArgumentException('Invalid Redis DSN: path and query "dbindex" parameters mismatch.');
        }
        $params += $query + $options + self::$defaultConnectionOptions;
        $booleanStreamOptions = ['allow_self_signed', 'capture_peer_cert', 'capture_peer_cert_chain', 'disable_compression', 'SNI_enabled', 'verify_peer', 'verify_peer_name'];
        foreach ($params['ssl'] ?? [] as $streamOption => $value) {
            if (\in_array($streamOption, $booleanStreamOptions, \true) && \is_string($value)) {
                $params['ssl'][$streamOption] = filter_var($value, \FILTER_VALIDATE_BOOL);
            }
        }
        if (!isset($params['redis_sentinel'])) {
            $params['auth'] ??= $auth;
        } elseif (!class_exists(\_ContaoManager\Predis\Client::class) && !class_exists(\RedisSentinel::class) && !class_exists(Sentinel::class)) {
            throw new CacheException('Redis Sentinel support requires one of: "predis/predis", "ext-redis >= 5.2", "ext-relay".');
        }
        if (isset($params['lazy'])) {
            $params['lazy'] = filter_var($params['lazy'], \FILTER_VALIDATE_BOOLEAN);
        }
        $params['redis_cluster'] = filter_var($params['redis_cluster'], \FILTER_VALIDATE_BOOLEAN);
        if ($params['redis_cluster'] && isset($params['redis_sentinel'])) {
            throw new InvalidArgumentException('Cannot use both "redis_cluster" and "redis_sentinel" at the same time.');
        }
        $class = $params['class'] ?? match (\true) {
            $params['redis_cluster'] => \extension_loaded('redis') ? \RedisCluster::class : \_ContaoManager\Predis\Client::class,
            isset($params['redis_sentinel']) => match (\true) {
                \extension_loaded('redis') => \Redis::class,
                \extension_loaded('relay') => Relay::class,
                default => \_ContaoManager\Predis\Client::class,
            },
            1 < \count($hosts) && \extension_loaded('redis') => 1 < \count($hosts) ? \RedisArray::class : \Redis::class,
            \extension_loaded('redis') => \Redis::class,
            \extension_loaded('relay') => Relay::class,
            default => \_ContaoManager\Predis\Client::class,
        };
        if (isset($params['redis_sentinel']) && !is_a($class, \_ContaoManager\Predis\Client::class, \true) && !class_exists(\RedisSentinel::class) && !class_exists(Sentinel::class)) {
            throw new CacheException(\sprintf('Cannot use Redis Sentinel: class "%s" does not extend "Predis\Client" and neither ext-redis >= 5.2 nor ext-relay have been found.', $class));
        }
        $isRedisExt = is_a($class, \Redis::class, \true);
        $isRelayExt = !$isRedisExt && is_a($class, Relay::class, \true);
        if ($isRedisExt || $isRelayExt) {
            $connect = $params['persistent'] || $params['persistent_id'] ? 'pconnect' : 'connect';
            $initializer = static function () use ($class, $isRedisExt, $connect, $params, $auth, $hosts, $tls) {
                $sentinelClass = $isRedisExt ? \RedisSentinel::class : Sentinel::class;
                $redis = new $class();
                $hostIndex = 0;
                do {
                    $host = $hosts[$hostIndex]['host'] ?? $hosts[$hostIndex]['path'];
                    $port = $hosts[$hostIndex]['port'] ?? 0;
                    $passAuth = null !== $params['auth'] && (!$isRedisExt || \defined('Redis::OPT_NULL_MULTIBULK_AS_NULL'));
                    $address = \false;
                    if (isset($hosts[$hostIndex]['host']) && $tls) {
                        $host = 'tls://' . $host;
                    }
                    if (!isset($params['redis_sentinel'])) {
                        break;
                    }
                    try {
                        if ($isRedisExt && version_compare(phpversion('redis'), '6.0.0', '>=')) {
                            $options = ['host' => $host, 'port' => $port, 'connectTimeout' => (float) $params['timeout'], 'persistent' => $params['persistent_id'], 'retryInterval' => (int) $params['retry_interval'], 'readTimeout' => (float) $params['read_timeout']];
                            if ($passAuth) {
                                $options['auth'] = $params['auth'];
                            }
                            if (null !== $params['ssl'] && version_compare(phpversion('redis'), '6.2.0', '>=')) {
                                $options['ssl'] = $params['ssl'];
                            }
                            $sentinel = new \RedisSentinel($options);
                        } else {
                            $extra = $passAuth ? [$params['auth']] : [];
                            $sentinel = @new $sentinelClass($host, $port, $params['timeout'], (string) $params['persistent_id'], $params['retry_interval'], $params['read_timeout'], ...$extra);
                        }
                        if ($address = @$sentinel->getMasterAddrByName($params['redis_sentinel'])) {
                            [$host, $port] = $address;
                        }
                    } catch (\RedisException|\Relay\Exception $redisException) {
                    }
                } while (++$hostIndex < \count($hosts) && !$address);
                if (isset($params['redis_sentinel']) && !$address) {
                    throw new InvalidArgumentException(\sprintf('Failed to retrieve master information from sentinel "%s".', $params['redis_sentinel']), previous: $redisException ?? null);
                }
                try {
                    $extra = ['stream' => $params['ssl'] ?? null];
                    if (null !== $params['auth']) {
                        $extra['auth'] = $params['auth'];
                    }
                    @$redis->{$connect}($host, $port, (float) $params['timeout'], (string) $params['persistent_id'], $params['retry_interval'], $params['read_timeout'], ...\defined('Redis::SCAN_PREFIX') || !$isRedisExt ? [$extra] : []);
                    set_error_handler(function ($type, $msg) use (&$error) {
                        $error = $msg;
                    });
                    try {
                        $isConnected = $redis->isConnected();
                    } finally {
                        restore_error_handler();
                    }
                    if (!$isConnected) {
                        $error = preg_match('/^Redis::p?connect\(\): (.*)/', $error ?? $redis->getLastError() ?? '', $error) ? \sprintf(' (%s)', $error[1]) : '';
                        throw new InvalidArgumentException('Redis connection failed: ' . $error . '.');
                    }
                    if (0 < $params['tcp_keepalive'] && (!$isRedisExt || \defined('Redis::OPT_TCP_KEEPALIVE'))) {
                        $redis->setOption($isRedisExt ? \Redis::OPT_TCP_KEEPALIVE : Relay::OPT_TCP_KEEPALIVE, $params['tcp_keepalive']);
                    }
                    if (!\defined('Redis::SCAN_PREFIX') && null !== $auth && $isRedisExt && !$redis->auth($auth) || !$redis->select($params['dbindex'])) {
                        $e = preg_replace('/^ERR /', '', $redis->getLastError());
                        throw new InvalidArgumentException('Redis connection failed: ' . $e . '.');
                    }
                } catch (\RedisException|\Relay\Exception $e) {
                    throw new InvalidArgumentException('Redis connection failed: ' . $e->getMessage());
                }
                return $redis;
            };
            if ($params['lazy']) {
                $redis = $isRedisExt ? RedisProxy::createLazyProxy($initializer) : RelayProxy::createLazyProxy($initializer);
            } else {
                $redis = $initializer();
            }
        } elseif (is_a($class, \RedisArray::class, \true)) {
            foreach ($hosts as $i => $host) {
                $hosts[$i] = match ($host['scheme']) {
                    'tcp' => $host['host'] . ':' . $host['port'],
                    'tls' => 'tls://' . $host['host'] . ':' . $host['port'],
                    default => $host['path'],
                };
            }
            $params['lazy_connect'] = $params['lazy'] ?? \true;
            $params['connect_timeout'] = $params['timeout'];
            try {
                $redis = new $class($hosts, $params);
            } catch (\RedisClusterException $e) {
                throw new InvalidArgumentException('Redis connection failed: ' . $e->getMessage());
            }
            if (0 < $params['tcp_keepalive'] && (!$isRedisExt || \defined('Redis::OPT_TCP_KEEPALIVE'))) {
                $redis->setOption($isRedisExt ? \Redis::OPT_TCP_KEEPALIVE : Relay::OPT_TCP_KEEPALIVE, $params['tcp_keepalive']);
            }
        } elseif (is_a($class, \RedisCluster::class, \true)) {
            $initializer = static function () use ($isRedisExt, $class, $params, $hosts) {
                foreach ($hosts as $i => $host) {
                    $hosts[$i] = match ($host['scheme']) {
                        'tcp' => $host['host'] . ':' . $host['port'],
                        'tls' => 'tls://' . $host['host'] . ':' . $host['port'],
                        default => $host['path'],
                    };
                }
                try {
                    $redis = new $class(null, $hosts, $params['timeout'], $params['read_timeout'], (bool) $params['persistent'], $params['auth'] ?? '', ...\defined('Redis::SCAN_PREFIX') ? [$params['ssl'] ?? null] : []);
                } catch (\RedisClusterException $e) {
                    throw new InvalidArgumentException('Redis connection failed: ' . $e->getMessage());
                }
                if (0 < $params['tcp_keepalive'] && (!$isRedisExt || \defined('Redis::OPT_TCP_KEEPALIVE'))) {
                    $redis->setOption($isRedisExt ? \Redis::OPT_TCP_KEEPALIVE : Relay::OPT_TCP_KEEPALIVE, $params['tcp_keepalive']);
                }
                $redis->setOption(\RedisCluster::OPT_SLAVE_FAILOVER, match ($params['failover']) {
                    'error' => \RedisCluster::FAILOVER_ERROR,
                    'distribute' => \RedisCluster::FAILOVER_DISTRIBUTE,
                    'slaves' => \RedisCluster::FAILOVER_DISTRIBUTE_SLAVES,
                    'none' => \RedisCluster::FAILOVER_NONE,
                });
                return $redis;
            };
            $redis = $params['lazy'] ? RedisClusterProxy::createLazyProxy($initializer) : $initializer();
        } elseif (is_a($class, \_ContaoManager\Predis\ClientInterface::class, \true)) {
            if ($params['redis_cluster']) {
                $params['cluster'] = 'redis';
            } elseif (isset($params['redis_sentinel'])) {
                $params['replication'] = 'sentinel';
                $params['service'] = $params['redis_sentinel'];
            }
            $params += ['parameters' => []];
            $params['parameters'] += ['persistent' => $params['persistent'], 'timeout' => $params['timeout'], 'read_write_timeout' => $params['read_timeout'], 'tcp_nodelay' => \true];
            if ($params['dbindex']) {
                $params['parameters']['database'] = $params['dbindex'];
            }
            if (\is_array($auth)) {
                // ACL
                $params['parameters']['username'] = $auth[0];
                $params['parameters']['password'] = $auth[1];
            } elseif (null !== $auth) {
                $params['parameters']['password'] = $auth;
            }
            if (isset($params['ssl'])) {
                foreach ($hosts as $i => $host) {
                    $hosts[$i]['ssl'] ??= $params['ssl'];
                }
            }
            if (1 === \count($hosts) && !($params['redis_cluster'] || $params['redis_sentinel'])) {
                $hosts = $hosts[0];
            } elseif (\in_array($params['failover'], ['slaves', 'distribute'], \true) && !isset($params['replication'])) {
                $params['replication'] = \true;
                $hosts[0] += ['alias' => 'master'];
            }
            $params['exceptions'] = \false;
            $redis = new $class($hosts, array_diff_key($params, self::$defaultConnectionOptions));
            if (isset($params['redis_sentinel'])) {
                $redis->getConnection()->setSentinelTimeout($params['timeout']);
            }
        } elseif (class_exists($class, \false)) {
            throw new InvalidArgumentException(\sprintf('"%s" is not a subclass of "Redis", "RedisArray", "RedisCluster", "Relay\Relay" nor "Predis\ClientInterface".', $class));
        } else {
            throw new InvalidArgumentException(\sprintf('Class "%s" does not exist.', $class));
        }
        return $redis;
    }
    protected function doFetch(array $ids): iterable
    {
        if (!$ids) {
            return [];
        }
        $result = [];
        if ($this->redis instanceof \_ContaoManager\Predis\ClientInterface && ($this->redis->getConnection() instanceof ClusterInterface || $this->redis->getConnection() instanceof Predis2ClusterInterface) || $this->redis instanceof RelayCluster) {
            $values = $this->pipeline(function () use ($ids) {
                foreach ($ids as $id) {
                    yield 'get' => [$id];
                }
            });
        } else {
            $values = $this->redis->mget($ids);
            if (!\is_array($values) || \count($values) !== \count($ids)) {
                return [];
            }
            $values = array_combine($ids, $values);
        }
        foreach ($values as $id => $v) {
            if ($v) {
                $result[$id] = $this->marshaller->unmarshall($v);
            }
        }
        return $result;
    }
    protected function doHave(string $id): bool
    {
        return (bool) $this->redis->exists($id);
    }
    protected function doClear(string $namespace): bool
    {
        if ($this->redis instanceof \_ContaoManager\Predis\ClientInterface) {
            $prefix = $this->redis->getOptions()->prefix ? $this->redis->getOptions()->prefix->getPrefix() : '';
            $prefixLen = \strlen($prefix ?? '');
        }
        $cleared = \true;
        $hosts = $this->getHosts();
        $host = reset($hosts);
        if ($host instanceof \_ContaoManager\Predis\Client) {
            $connection = $host->getConnection();
            if ($connection instanceof ReplicationInterface) {
                $hosts = [$host->getClientFor('master')];
            } elseif ($connection instanceof Predis2ReplicationInterface) {
                $connection->switchToMaster();
                $hosts = [$host];
            }
        }
        foreach ($hosts as $host) {
            if (!isset($namespace[0])) {
                $cleared = $host->flushDb() && $cleared;
                continue;
            }
            $info = $host->info('Server');
            $info = !$info instanceof ErrorInterface ? $info['Server'] ?? $info : ['redis_version' => '2.0'];
            if ($host instanceof Relay) {
                $prefix = Relay::SCAN_PREFIX & $host->getOption(Relay::OPT_SCAN) ? '' : $host->getOption(Relay::OPT_PREFIX);
                $prefixLen = \strlen($host->getOption(Relay::OPT_PREFIX) ?? '');
            } elseif (!$host instanceof \_ContaoManager\Predis\ClientInterface) {
                $prefix = \defined('Redis::SCAN_PREFIX') && \Redis::SCAN_PREFIX & $host->getOption(\Redis::OPT_SCAN) ? '' : $host->getOption(\Redis::OPT_PREFIX);
                $prefixLen = \strlen($host->getOption(\Redis::OPT_PREFIX) ?? '');
            }
            $pattern = $prefix . $namespace . '*';
            if (!version_compare($info['redis_version'], '2.8', '>=')) {
                // As documented in Redis documentation (http://redis.io/commands/keys) using KEYS
                // can hang your server when it is executed against large databases (millions of items).
                // Whenever you hit this scale, you should really consider upgrading to Redis 2.8 or above.
                $unlink = version_compare($info['redis_version'], '4.0', '>=') ? 'UNLINK' : 'DEL';
                $args = $this->redis instanceof \_ContaoManager\Predis\ClientInterface ? [0, $pattern] : [[$pattern], 0];
                $cleared = $host->eval("local keys=redis.call('KEYS',ARGV[1]) for i=1,#keys,5000 do redis.call('{$unlink}',unpack(keys,i,math.min(i+4999,#keys))) end return 1", $args[0], $args[1]) && $cleared;
                continue;
            }
            $cursor = null;
            do {
                $keys = $host instanceof \_ContaoManager\Predis\ClientInterface ? $host->scan($cursor ?? 0, 'MATCH', $pattern, 'COUNT', 1000) : $host->scan($cursor, $pattern, 1000);
                if (isset($keys[1]) && \is_array($keys[1])) {
                    $cursor = $keys[0];
                    $keys = $keys[1];
                }
                if ($keys) {
                    if ($prefixLen) {
                        foreach ($keys as $i => $key) {
                            $keys[$i] = substr($key, $prefixLen);
                        }
                    }
                    $this->doDelete($keys);
                }
            } while ($cursor);
        }
        return $cleared;
    }
    protected function doDelete(array $ids): bool
    {
        if (!$ids) {
            return \true;
        }
        if ($this->redis instanceof \_ContaoManager\Predis\ClientInterface && ($this->redis->getConnection() instanceof ClusterInterface || $this->redis->getConnection() instanceof Predis2ClusterInterface)) {
            static $del;
            $del ??= class_exists(UNLINK::class) ? 'unlink' : 'del';
            $this->pipeline(function () use ($ids, $del) {
                foreach ($ids as $id) {
                    yield $del => [$id];
                }
            })->rewind();
        } else {
            static $unlink = \true;
            if ($unlink) {
                try {
                    $unlink = \false !== $this->redis->unlink($ids);
                } catch (\Throwable) {
                    $unlink = \false;
                }
            }
            if (!$unlink) {
                $this->redis->del($ids);
            }
        }
        return \true;
    }
    protected function doSave(array $values, int $lifetime): array|bool
    {
        if (!$values = $this->marshaller->marshall($values, $failed)) {
            return $failed;
        }
        $results = $this->pipeline(function () use ($values, $lifetime) {
            foreach ($values as $id => $value) {
                if (0 >= $lifetime) {
                    yield 'set' => [$id, $value];
                } else {
                    yield 'setEx' => [$id, $lifetime, $value];
                }
            }
        });
        foreach ($results as $id => $result) {
            if (\true !== $result && (!$result instanceof Status || Status::get('OK') !== $result)) {
                $failed[] = $id;
            }
        }
        return $failed;
    }
    private function pipeline(\Closure $generator, ?object $redis = null): \Generator
    {
        $ids = [];
        $redis ??= $this->redis;
        if ($redis instanceof \RedisCluster || $redis instanceof \_ContaoManager\Predis\ClientInterface && ($redis->getConnection() instanceof RedisCluster || $redis->getConnection() instanceof Predis2RedisCluster)) {
            // phpredis & predis don't support pipelining with RedisCluster
            // see https://github.com/phpredis/phpredis/blob/develop/cluster.markdown#pipelining
            // see https://github.com/nrk/predis/issues/267#issuecomment-123781423
            $results = [];
            foreach ($generator() as $command => $args) {
                $results[] = $redis->{$command}(...$args);
                $ids[] = 'eval' === $command ? $redis instanceof \_ContaoManager\Predis\ClientInterface ? $args[2] : $args[1][0] : $args[0];
            }
        } elseif ($redis instanceof \_ContaoManager\Predis\ClientInterface) {
            $results = $redis->pipeline(static function ($redis) use ($generator, &$ids) {
                foreach ($generator() as $command => $args) {
                    $redis->{$command}(...$args);
                    $ids[] = 'eval' === $command ? $args[2] : $args[0];
                }
            });
        } elseif ($redis instanceof \RedisArray) {
            $connections = $results = $ids = [];
            foreach ($generator() as $command => $args) {
                $id = 'eval' === $command ? $args[1][0] : $args[0];
                if (!isset($connections[$h = $redis->_target($id)])) {
                    $connections[$h] = [$redis->_instance($h), -1];
                    $connections[$h][0]->multi(\Redis::PIPELINE);
                }
                $connections[$h][0]->{$command}(...$args);
                $results[] = [$h, ++$connections[$h][1]];
                $ids[] = $id;
            }
            foreach ($connections as $h => $c) {
                $connections[$h] = $c[0]->exec();
            }
            foreach ($results as $k => [$h, $c]) {
                $results[$k] = $connections[$h][$c];
            }
        } else {
            $redis->multi($redis instanceof Relay ? Relay::PIPELINE : \Redis::PIPELINE);
            foreach ($generator() as $command => $args) {
                $redis->{$command}(...$args);
                $ids[] = 'eval' === $command ? $args[1][0] : $args[0];
            }
            $results = $redis->exec();
        }
        if (!$redis instanceof \_ContaoManager\Predis\ClientInterface && 'eval' === $command && $redis->getLastError()) {
            $e = $redis instanceof Relay ? new \Relay\Exception($redis->getLastError()) : new \RedisException($redis->getLastError());
            $results = array_map(fn($v) => \false === $v ? $e : $v, (array) $results);
        }
        if (\is_bool($results)) {
            return;
        }
        foreach ($ids as $k => $id) {
            yield $id => $results[$k];
        }
    }
    private function getHosts(): array
    {
        $hosts = [$this->redis];
        if ($this->redis instanceof \_ContaoManager\Predis\ClientInterface) {
            $connection = $this->redis->getConnection();
            if (($connection instanceof ClusterInterface || $connection instanceof Predis2ClusterInterface) && $connection instanceof \Traversable) {
                $hosts = [];
                foreach ($connection as $c) {
                    $hosts[] = new \_ContaoManager\Predis\Client($c);
                }
            }
        } elseif ($this->redis instanceof \RedisArray) {
            $hosts = [];
            foreach ($this->redis->_hosts() as $host) {
                $hosts[] = $this->redis->_instance($host);
            }
        } elseif ($this->redis instanceof \RedisCluster) {
            $hosts = [];
            foreach ($this->redis->_masters() as $host) {
                $hosts[] = new RedisClusterNodeProxy($host, $this->redis);
            }
        }
        return $hosts;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Cache\Traits;

use _ContaoManager\Symfony\Component\VarExporter\LazyObjectInterface;
use _ContaoManager\Symfony\Component\VarExporter\LazyProxyTrait;
use _ContaoManager\Symfony\Contracts\Service\ResetInterface;
// Help opcache.preload discover always-needed symbols
class_exists(\_ContaoManager\Symfony\Component\VarExporter\Internal\Hydrator::class);
class_exists(\_ContaoManager\Symfony\Component\VarExporter\Internal\LazyObjectRegistry::class);
class_exists(\_ContaoManager\Symfony\Component\VarExporter\Internal\LazyObjectState::class);
/**
 * @internal
 */
class Redis5Proxy extends \Redis implements ResetInterface, LazyObjectInterface
{
    use LazyProxyTrait {
        resetLazyObject as reset;
    }
    private const LAZY_OBJECT_PROPERTY_SCOPES = [];
    public function __construct()
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->__construct(...\func_get_args());
    }
    public function _prefix($key)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->_prefix(...\func_get_args());
    }
    public function _serialize($value)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->_serialize(...\func_get_args());
    }
    public function _unserialize($value)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->_unserialize(...\func_get_args());
    }
    public function _pack($value)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->_pack(...\func_get_args());
    }
    public function _unpack($value)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->_unpack(...\func_get_args());
    }
    public function _compress($value)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->_compress(...\func_get_args());
    }
    public function _uncompress($value)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->_uncompress(...\func_get_args());
    }
    public function acl($subcmd, ...$args)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->acl(...\func_get_args());
    }
    public function append($key, $value)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->append(...\func_get_args());
    }
    public function auth(
        #[\SensitiveParameter]
        $auth
    )
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->auth(...\func_get_args());
    }
    public function bgSave()
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->bgSave(...\func_get_args());
    }
    public function bgrewriteaof()
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->bgrewriteaof(...\func_get_args());
    }
    public function bitcount($key)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->bitcount(...\func_get_args());
    }
    public function bitop($operation, $ret_key, $key, ...$other_keys)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->bitop(...\func_get_args());
    }
    public function bitpos($key, $bit, $start = null, $end = null)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->bitpos(...\func_get_args());
    }
    public function blPop($key, $timeout_or_key, ...$extra_args)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->blPop(...\func_get_args());
    }
    public function brPop($key, $timeout_or_key, ...$extra_args)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->brPop(...\func_get_args());
    }
    public function brpoplpush($src, $dst, $timeout)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->brpoplpush(...\func_get_args());
    }
    public function bzPopMax($key, $timeout_or_key, ...$extra_args)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->bzPopMax(...\func_get_args());
    }
    public function bzPopMin($key, $timeout_or_key, ...$extra_args)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->bzPopMin(...\func_get_args());
    }
    public function clearLastError()
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->clearLastError(...\func_get_args());
    }
    public function client($cmd, ...$args)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->client(...\func_get_args());
    }
    public function close()
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->close(...\func_get_args());
    }
    public function command(...$args)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->command(...\func_get_args());
    }
    public function config($cmd, $key, $value = null)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->config(...\func_get_args());
    }
    public function connect($host, $port = null, $timeout = null, $retry_interval = null)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->connect(...\func_get_args());
    }
    public function dbSize()
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->dbSize(...\func_get_args());
    }
    public function debug($key)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->debug(...\func_get_args());
    }
    public function decr($key)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->decr(...\func_get_args());
    }
    public function decrBy($key, $value)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->decrBy(...\func_get_args());
    }
    public function del($key, ...$other_keys)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->del(...\func_get_args());
    }
    public function discard()
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->discard(...\func_get_args());
    }
    public function dump($key)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->dump(...\func_get_args());
    }
    public function echo($msg)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->echo(...\func_get_args());
    }
    public function eval($script, $args = null, $num_keys = null)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->eval(...\func_get_args());
    }
    public function evalsha($script_sha, $args = null, $num_keys = null)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->evalsha(...\func_get_args());
    }
    public function exec()
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->exec(...\func_get_args());
    }
    public function exists($key, ...$other_keys)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->exists(...\func_get_args());
    }
    public function expire($key, $timeout)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->expire(...\func_get_args());
    }
    public function expireAt($key, $timestamp)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->expireAt(...\func_get_args());
    }
    public function flushAll($async = null)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->flushAll(...\func_get_args());
    }
    public function flushDB($async = null)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->flushDB(...\func_get_args());
    }
    public function geoadd($key, $lng, $lat, $member, ...$other_triples)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->geoadd(...\func_get_args());
    }
    public function geodist($key, $src, $dst, $unit = null)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->geodist(...\func_get_args());
    }
    public function geohash($key, $member, ...$other_members)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->geohash(...\func_get_args());
    }
    public function geopos($key, $member, ...$other_members)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->geopos(...\func_get_args());
    }
    public function georadius($key, $lng, $lan, $radius, $unit, $opts = null)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->georadius(...\func_get_args());
    }
    public function georadius_ro($key, $lng, $lan, $radius, $unit, $opts = null)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->georadius_ro(...\func_get_args());
    }
    public function georadiusbymember($key, $member, $radius, $unit, $opts = null)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->georadiusbymember(...\func_get_args());
    }
    public function georadiusbymember_ro($key, $member, $radius, $unit, $opts = null)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->georadiusbymember_ro(...\func_get_args());
    }
    public function get($key)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->get(...\func_get_args());
    }
    public function getAuth()
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->getAuth(...\func_get_args());
    }
    public function getBit($key, $offset)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->getBit(...\func_get_args());
    }
    public function getDBNum()
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->getDBNum(...\func_get_args());
    }
    public function getHost()
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->getHost(...\func_get_args());
    }
    public function getLastError()
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->getLastError(...\func_get_args());
    }
    public function getMode()
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->getMode(...\func_get_args());
    }
    public function getOption($option)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->getOption(...\func_get_args());
    }
    public function getPersistentID()
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->getPersistentID(...\func_get_args());
    }
    public function getPort()
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->getPort(...\func_get_args());
    }
    public function getRange($key, $start, $end)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->getRange(...\func_get_args());
    }
    public function getReadTimeout()
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->getReadTimeout(...\func_get_args());
    }
    public function getSet($key, $value)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->getSet(...\func_get_args());
    }
    public function getTimeout()
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->getTimeout(...\func_get_args());
    }
    public function hDel($key, $member, ...$other_members)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->hDel(...\func_get_args());
    }
    public function hExists($key, $member)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->hExists(...\func_get_args());
    }
    public function hGet($key, $member)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->hGet(...\func_get_args());
    }
    public function hGetAll($key)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->hGetAll(...\func_get_args());
    }
    public function hIncrBy($key, $member, $value)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->hIncrBy(...\func_get_args());
    }
    public function hIncrByFloat($key, $member, $value)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->hIncrByFloat(...\func_get_args());
    }
    public function hKeys($key)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->hKeys(...\func_get_args());
    }
    public function hLen($key)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->hLen(...\func_get_args());
    }
    public function hMget($key, $keys)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->hMget(...\func_get_args());
    }
    public function hMset($key, $pairs)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->hMset(...\func_get_args());
    }
    public function hSet($key, $member, $value)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->hSet(...\func_get_args());
    }
    public function hSetNx($key, $member, $value)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->hSetNx(...\func_get_args());
    }
    public function hStrLen($key, $member)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->hStrLen(...\func_get_args());
    }
    public function hVals($key)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->hVals(...\func_get_args());
    }
    public function hscan($str_key, &$i_iterator, $str_pattern = null, $i_count = null)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->hscan($str_key, $i_iterator, ...\array_slice(\func_get_args(), 2));
    }
    public function incr($key)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->incr(...\func_get_args());
    }
    public function incrBy($key, $value)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->incrBy(...\func_get_args());
    }
    public function incrByFloat($key, $value)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->incrByFloat(...\func_get_args());
    }
    public function info($option = null)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->info(...\func_get_args());
    }
    public function isConnected()
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->isConnected(...\func_get_args());
    }
    public function keys($pattern)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->keys(...\func_get_args());
    }
    public function lInsert($key, $position, $pivot, $value)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->lInsert(...\func_get_args());
    }
    public function lLen($key)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->lLen(...\func_get_args());
    }
    public function lPop($key)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->lPop(...\func_get_args());
    }
    public function lPush($key, $value)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->lPush(...\func_get_args());
    }
    public function lPushx($key, $value)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->lPushx(...\func_get_args());
    }
    public function lSet($key, $index, $value)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->lSet(...\func_get_args());
    }
    public function lastSave()
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->lastSave(...\func_get_args());
    }
    public function lindex($key, $index)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->lindex(...\func_get_args());
    }
    public function lrange($key, $start, $end)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->lrange(...\func_get_args());
    }
    public function lrem($key, $value, $count)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->lrem(...\func_get_args());
    }
    public function ltrim($key, $start, $stop)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->ltrim(...\func_get_args());
    }
    public function mget($keys)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->mget(...\func_get_args());
    }
    public function migrate($host, $port, $key, $db, $timeout, $copy = null, $replace = null)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->migrate(...\func_get_args());
    }
    public function move($key, $dbindex)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->move(...\func_get_args());
    }
    public function mset($pairs)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->mset(...\func_get_args());
    }
    public function msetnx($pairs)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->msetnx(...\func_get_args());
    }
    public function multi($mode = null)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->multi(...\func_get_args());
    }
    public function object($field, $key)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->object(...\func_get_args());
    }
    public function pconnect($host, $port = null, $timeout = null)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->pconnect(...\func_get_args());
    }
    public function persist($key)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->persist(...\func_get_args());
    }
    public function pexpire($key, $timestamp)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->pexpire(...\func_get_args());
    }
    public function pexpireAt($key, $timestamp)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->pexpireAt(...\func_get_args());
    }
    public function pfadd($key, $elements)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->pfadd(...\func_get_args());
    }
    public function pfcount($key)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->pfcount(...\func_get_args());
    }
    public function pfmerge($dstkey, $keys)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->pfmerge(...\func_get_args());
    }
    public function ping()
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->ping(...\func_get_args());
    }
    public function pipeline()
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->pipeline(...\func_get_args());
    }
    public function psetex($key, $expire, $value)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->psetex(...\func_get_args());
    }
    public function psubscribe($patterns, $callback)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->psubscribe(...\func_get_args());
    }
    public function pttl($key)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->pttl(...\func_get_args());
    }
    public function publish($channel, $message)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->publish(...\func_get_args());
    }
    public function pubsub($cmd, ...$args)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->pubsub(...\func_get_args());
    }
    public function punsubscribe($pattern, ...$other_patterns)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->punsubscribe(...\func_get_args());
    }
    public function rPop($key)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->rPop(...\func_get_args());
    }
    public function rPush($key, $value)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->rPush(...\func_get_args());
    }
    public function rPushx($key, $value)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->rPushx(...\func_get_args());
    }
    public function randomKey()
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->randomKey(...\func_get_args());
    }
    public function rawcommand($cmd, ...$args)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->rawcommand(...\func_get_args());
    }
    public function rename($key, $newkey)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->rename(...\func_get_args());
    }
    public function renameNx($key, $newkey)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->renameNx(...\func_get_args());
    }
    public function restore($ttl, $key, $value)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->restore(...\func_get_args());
    }
    public function role()
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->role(...\func_get_args());
    }
    public function rpoplpush($src, $dst)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->rpoplpush(...\func_get_args());
    }
    public function sAdd($key, $value)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->sAdd(...\func_get_args());
    }
    public function sAddArray($key, $options)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->sAddArray(...\func_get_args());
    }
    public function sDiff($key, ...$other_keys)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->sDiff(...\func_get_args());
    }
    public function sDiffStore($dst, $key, ...$other_keys)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->sDiffStore(...\func_get_args());
    }
    public function sInter($key, ...$other_keys)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->sInter(...\func_get_args());
    }
    public function sInterStore($dst, $key, ...$other_keys)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->sInterStore(...\func_get_args());
    }
    public function sMembers($key)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->sMembers(...\func_get_args());
    }
    public function sMisMember($key, $member, ...$other_members)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->sMisMember(...\func_get_args());
    }
    public function sMove($src, $dst, $value)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->sMove(...\func_get_args());
    }
    public function sPop($key)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->sPop(...\func_get_args());
    }
    public function sRandMember($key, $count = null)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->sRandMember(...\func_get_args());
    }
    public function sUnion($key, ...$other_keys)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->sUnion(...\func_get_args());
    }
    public function sUnionStore($dst, $key, ...$other_keys)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->sUnionStore(...\func_get_args());
    }
    public function save()
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->save(...\func_get_args());
    }
    public function scan(&$i_iterator, $str_pattern = null, $i_count = null)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->scan($i_iterator, ...\array_slice(\func_get_args(), 1));
    }
    public function scard($key)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->scard(...\func_get_args());
    }
    public function script($cmd, ...$args)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->script(...\func_get_args());
    }
    public function select($dbindex)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->select(...\func_get_args());
    }
    public function set($key, $value, $opts = null)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->set(...\func_get_args());
    }
    public function setBit($key, $offset, $value)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->setBit(...\func_get_args());
    }
    public function setOption($option, $value)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->setOption(...\func_get_args());
    }
    public function setRange($key, $offset, $value)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->setRange(...\func_get_args());
    }
    public function setex($key, $expire, $value)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->setex(...\func_get_args());
    }
    public function setnx($key, $value)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->setnx(...\func_get_args());
    }
    public function sismember($key, $value)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->sismember(...\func_get_args());
    }
    public function slaveof($host = null, $port = null)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->slaveof(...\func_get_args());
    }
    public function slowlog($arg, $option = null)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->slowlog(...\func_get_args());
    }
    public function sort($key, $options = null)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->sort(...\func_get_args());
    }
    public function sortAsc($key, $pattern = null, $get = null, $start = null, $end = null, $getList = null)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->sortAsc(...\func_get_args());
    }
    public function sortAscAlpha($key, $pattern = null, $get = null, $start = null, $end = null, $getList = null)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->sortAscAlpha(...\func_get_args());
    }
    public function sortDesc($key, $pattern = null, $get = null, $start = null, $end = null, $getList = null)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->sortDesc(...\func_get_args());
    }
    public function sortDescAlpha($key, $pattern = null, $get = null, $start = null, $end = null, $getList = null)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->sortDescAlpha(...\func_get_args());
    }
    public function srem($key, $member, ...$other_members)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->srem(...\func_get_args());
    }
    public function sscan($str_key, &$i_iterator, $str_pattern = null, $i_count = null)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->sscan($str_key, $i_iterator, ...\array_slice(\func_get_args(), 2));
    }
    public function strlen($key)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->strlen(...\func_get_args());
    }
    public function subscribe($channels, $callback)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->subscribe(...\func_get_args());
    }
    public function swapdb($srcdb, $dstdb)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->swapdb(...\func_get_args());
    }
    public function time()
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->time(...\func_get_args());
    }
    public function ttl($key)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->ttl(...\func_get_args());
    }
    public function type($key)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->type(...\func_get_args());
    }
    public function unlink($key, ...$other_keys)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->unlink(...\func_get_args());
    }
    public function unsubscribe($channel, ...$other_channels)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->unsubscribe(...\func_get_args());
    }
    public function unwatch()
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->unwatch(...\func_get_args());
    }
    public function wait($numslaves, $timeout)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->wait(...\func_get_args());
    }
    public function watch($key, ...$other_keys)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->watch(...\func_get_args());
    }
    public function xack($str_key, $str_group, $arr_ids)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->xack(...\func_get_args());
    }
    public function xadd($str_key, $str_id, $arr_fields, $i_maxlen = null, $boo_approximate = null)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->xadd(...\func_get_args());
    }
    public function xclaim($str_key, $str_group, $str_consumer, $i_min_idle, $arr_ids, $arr_opts = null)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->xclaim(...\func_get_args());
    }
    public function xdel($str_key, $arr_ids)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->xdel(...\func_get_args());
    }
    public function xgroup($str_operation, $str_key = null, $str_arg1 = null, $str_arg2 = null, $str_arg3 = null)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->xgroup(...\func_get_args());
    }
    public function xinfo($str_cmd, $str_key = null, $str_group = null)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->xinfo(...\func_get_args());
    }
    public function xlen($key)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->xlen(...\func_get_args());
    }
    public function xpending($str_key, $str_group, $str_start = null, $str_end = null, $i_count = null, $str_consumer = null)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->xpending(...\func_get_args());
    }
    public function xrange($str_key, $str_start, $str_end, $i_count = null)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->xrange(...\func_get_args());
    }
    public function xread($arr_streams, $i_count = null, $i_block = null)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->xread(...\func_get_args());
    }
    public function xreadgroup($str_group, $str_consumer, $arr_streams, $i_count = null, $i_block = null)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->xreadgroup(...\func_get_args());
    }
    public function xrevrange($str_key, $str_start, $str_end, $i_count = null)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->xrevrange(...\func_get_args());
    }
    public function xtrim($str_key, $i_maxlen, $boo_approximate = null)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->xtrim(...\func_get_args());
    }
    public function zAdd($key, $score, $value, ...$extra_args)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->zAdd(...\func_get_args());
    }
    public function zCard($key)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->zCard(...\func_get_args());
    }
    public function zCount($key, $min, $max)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->zCount(...\func_get_args());
    }
    public function zIncrBy($key, $value, $member)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->zIncrBy(...\func_get_args());
    }
    public function zLexCount($key, $min, $max)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->zLexCount(...\func_get_args());
    }
    public function zPopMax($key)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->zPopMax(...\func_get_args());
    }
    public function zPopMin($key)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->zPopMin(...\func_get_args());
    }
    public function zRange($key, $start, $end, $scores = null)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->zRange(...\func_get_args());
    }
    public function zRangeByLex($key, $min, $max, $offset = null, $limit = null)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->zRangeByLex(...\func_get_args());
    }
    public function zRangeByScore($key, $start, $end, $options = null)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->zRangeByScore(...\func_get_args());
    }
    public function zRank($key, $member)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->zRank(...\func_get_args());
    }
    public function zRem($key, $member, ...$other_members)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->zRem(...\func_get_args());
    }
    public function zRemRangeByLex($key, $min, $max)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->zRemRangeByLex(...\func_get_args());
    }
    public function zRemRangeByRank($key, $start, $end)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->zRemRangeByRank(...\func_get_args());
    }
    public function zRemRangeByScore($key, $min, $max)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->zRemRangeByScore(...\func_get_args());
    }
    public function zRevRange($key, $start, $end, $scores = null)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->zRevRange(...\func_get_args());
    }
    public function zRevRangeByLex($key, $min, $max, $offset = null, $limit = null)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->zRevRangeByLex(...\func_get_args());
    }
    public function zRevRangeByScore($key, $start, $end, $options = null)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->zRevRangeByScore(...\func_get_args());
    }
    public function zRevRank($key, $member)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->zRevRank(...\func_get_args());
    }
    public function zScore($key, $member)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->zScore(...\func_get_args());
    }
    public function zinterstore($key, $keys, $weights = null, $aggregate = null)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->zinterstore(...\func_get_args());
    }
    public function zscan($str_key, &$i_iterator, $str_pattern = null, $i_count = null)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->zscan($str_key, $i_iterator, ...\array_slice(\func_get_args(), 2));
    }
    public function zunionstore($key, $keys, $weights = null, $aggregate = null)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->zunionstore(...\func_get_args());
    }
    public function delete($key, ...$other_keys)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->delete(...\func_get_args());
    }
    public function evaluate($script, $args = null, $num_keys = null)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->evaluate(...\func_get_args());
    }
    public function evaluateSha($script_sha, $args = null, $num_keys = null)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->evaluateSha(...\func_get_args());
    }
    public function getKeys($pattern)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->getKeys(...\func_get_args());
    }
    public function getMultiple($keys)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->getMultiple(...\func_get_args());
    }
    public function lGet($key, $index)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->lGet(...\func_get_args());
    }
    public function lGetRange($key, $start, $end)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->lGetRange(...\func_get_args());
    }
    public function lRemove($key, $value, $count)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->lRemove(...\func_get_args());
    }
    public function lSize($key)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->lSize(...\func_get_args());
    }
    public function listTrim($key, $start, $stop)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->listTrim(...\func_get_args());
    }
    public function open($host, $port = null, $timeout = null, $retry_interval = null)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->open(...\func_get_args());
    }
    public function popen($host, $port = null, $timeout = null)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->popen(...\func_get_args());
    }
    public function renameKey($key, $newkey)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->renameKey(...\func_get_args());
    }
    public function sContains($key, $value)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->sContains(...\func_get_args());
    }
    public function sGetMembers($key)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->sGetMembers(...\func_get_args());
    }
    public function sRemove($key, $member, ...$other_members)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->sRemove(...\func_get_args());
    }
    public function sSize($key)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->sSize(...\func_get_args());
    }
    public function sendEcho($msg)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->sendEcho(...\func_get_args());
    }
    public function setTimeout($key, $timeout)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->setTimeout(...\func_get_args());
    }
    public function substr($key, $start, $end)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->substr(...\func_get_args());
    }
    public function zDelete($key, $member, ...$other_members)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->zDelete(...\func_get_args());
    }
    public function zDeleteRangeByRank($key, $min, $max)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->zDeleteRangeByRank(...\func_get_args());
    }
    public function zDeleteRangeByScore($key, $min, $max)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->zDeleteRangeByScore(...\func_get_args());
    }
    public function zInter($key, $keys, $weights = null, $aggregate = null)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->zInter(...\func_get_args());
    }
    public function zRemove($key, $member, ...$other_members)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->zRemove(...\func_get_args());
    }
    public function zRemoveRangeByScore($key, $min, $max)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->zRemoveRangeByScore(...\func_get_args());
    }
    public function zReverseRange($key, $start, $end, $scores = null)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->zReverseRange(...\func_get_args());
    }
    public function zSize($key)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->zSize(...\func_get_args());
    }
    public function zUnion($key, $keys, $weights = null, $aggregate = null)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->zUnion(...\func_get_args());
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Cache\Traits;

use _ContaoManager\Symfony\Component\VarExporter\LazyObjectInterface;
use _ContaoManager\Symfony\Component\VarExporter\LazyProxyTrait;
use _ContaoManager\Symfony\Contracts\Service\ResetInterface;
// Help opcache.preload discover always-needed symbols
class_exists(\_ContaoManager\Symfony\Component\VarExporter\Internal\Hydrator::class);
class_exists(\_ContaoManager\Symfony\Component\VarExporter\Internal\LazyObjectRegistry::class);
class_exists(\_ContaoManager\Symfony\Component\VarExporter\Internal\LazyObjectState::class);
/**
 * @internal
 */
class RedisCluster6Proxy extends \RedisCluster implements ResetInterface, LazyObjectInterface
{
    use RedisCluster61ProxyTrait;
    use RedisCluster62ProxyTrait;
    use RedisCluster63ProxyTrait;
    use LazyProxyTrait {
        resetLazyObject as reset;
    }
    private const LAZY_OBJECT_PROPERTY_SCOPES = [];
    public function __construct(
        $name,
        $seeds = null,
        $timeout = 0,
        $read_timeout = 0,
        $persistent = \false,
        #[\SensitiveParameter]
        $auth = null,
        $context = null
    )
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->__construct(...\func_get_args());
    }
    public function _compress($value): string
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->_compress(...\func_get_args());
    }
    public function _uncompress($value): string
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->_uncompress(...\func_get_args());
    }
    public function _serialize($value): bool|string
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->_serialize(...\func_get_args());
    }
    public function _unserialize($value): mixed
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->_unserialize(...\func_get_args());
    }
    public function _pack($value): string
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->_pack(...\func_get_args());
    }
    public function _unpack($value): mixed
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->_unpack(...\func_get_args());
    }
    public function _prefix($key): bool|string
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->_prefix(...\func_get_args());
    }
    public function _masters(): array
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->_masters(...\func_get_args());
    }
    public function _redir(): ?string
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->_redir(...\func_get_args());
    }
    public function acl($key_or_address, $subcmd, ...$args): mixed
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->acl(...\func_get_args());
    }
    public function append($key, $value): \RedisCluster|bool|int
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->append(...\func_get_args());
    }
    public function bgrewriteaof($key_or_address): \RedisCluster|bool
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->bgrewriteaof(...\func_get_args());
    }
    public function bgsave($key_or_address): \RedisCluster|bool
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->bgsave(...\func_get_args());
    }
    public function bitcount($key, $start = 0, $end = -1, $bybit = \false): \RedisCluster|bool|int
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->bitcount(...\func_get_args());
    }
    public function bitop($operation, $deskey, $srckey, ...$otherkeys): \RedisCluster|bool|int
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->bitop(...\func_get_args());
    }
    public function bitpos($key, $bit, $start = 0, $end = -1, $bybit = \false): \RedisCluster|false|int
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->bitpos(...\func_get_args());
    }
    public function blpop($key, $timeout_or_key, ...$extra_args): \RedisCluster|array|false|null
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->blpop(...\func_get_args());
    }
    public function brpop($key, $timeout_or_key, ...$extra_args): \RedisCluster|array|false|null
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->brpop(...\func_get_args());
    }
    public function brpoplpush($srckey, $deskey, $timeout): mixed
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->brpoplpush(...\func_get_args());
    }
    public function lmove($src, $dst, $wherefrom, $whereto): \Redis|false|string
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->lmove(...\func_get_args());
    }
    public function blmove($src, $dst, $wherefrom, $whereto, $timeout): \Redis|false|string
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->blmove(...\func_get_args());
    }
    public function bzpopmax($key, $timeout_or_key, ...$extra_args): array
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->bzpopmax(...\func_get_args());
    }
    public function bzpopmin($key, $timeout_or_key, ...$extra_args): array
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->bzpopmin(...\func_get_args());
    }
    public function bzmpop($timeout, $keys, $from, $count = 1): \RedisCluster|array|false|null
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->bzmpop(...\func_get_args());
    }
    public function zmpop($keys, $from, $count = 1): \RedisCluster|array|false|null
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->zmpop(...\func_get_args());
    }
    public function blmpop($timeout, $keys, $from, $count = 1): \RedisCluster|array|false|null
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->blmpop(...\func_get_args());
    }
    public function lmpop($keys, $from, $count = 1): \RedisCluster|array|false|null
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->lmpop(...\func_get_args());
    }
    public function clearlasterror(): bool
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->clearlasterror(...\func_get_args());
    }
    public function client($key_or_address, $subcommand, $arg = null): array|bool|string
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->client(...\func_get_args());
    }
    public function close(): bool
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->close(...\func_get_args());
    }
    public function cluster($key_or_address, $command, ...$extra_args): mixed
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->cluster(...\func_get_args());
    }
    public function command(...$extra_args): mixed
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->command(...\func_get_args());
    }
    public function config($key_or_address, $subcommand, ...$extra_args): mixed
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->config(...\func_get_args());
    }
    public function dbsize($key_or_address): \RedisCluster|int
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->dbsize(...\func_get_args());
    }
    public function copy($src, $dst, $options = null): \RedisCluster|bool
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->copy(...\func_get_args());
    }
    public function decr($key, $by = 1): \RedisCluster|false|int
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->decr(...\func_get_args());
    }
    public function decrby($key, $value): \RedisCluster|false|int
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->decrby(...\func_get_args());
    }
    public function decrbyfloat($key, $value): float
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->decrbyfloat(...\func_get_args());
    }
    public function del($key, ...$other_keys): \RedisCluster|false|int
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->del(...\func_get_args());
    }
    public function discard(): bool
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->discard(...\func_get_args());
    }
    public function dump($key): \RedisCluster|false|string
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->dump(...\func_get_args());
    }
    public function echo($key_or_address, $msg): \RedisCluster|false|string
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->echo(...\func_get_args());
    }
    public function eval($script, $args = [], $num_keys = 0): mixed
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->eval(...\func_get_args());
    }
    public function eval_ro($script, $args = [], $num_keys = 0): mixed
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->eval_ro(...\func_get_args());
    }
    public function evalsha($script_sha, $args = [], $num_keys = 0): mixed
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->evalsha(...\func_get_args());
    }
    public function evalsha_ro($script_sha, $args = [], $num_keys = 0): mixed
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->evalsha_ro(...\func_get_args());
    }
    public function exec(): array|false
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->exec(...\func_get_args());
    }
    public function exists($key, ...$other_keys): \RedisCluster|bool|int
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->exists(...\func_get_args());
    }
    public function touch($key, ...$other_keys): \RedisCluster|bool|int
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->touch(...\func_get_args());
    }
    public function expire($key, $timeout, $mode = null): \RedisCluster|bool
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->expire(...\func_get_args());
    }
    public function expireat($key, $timestamp, $mode = null): \RedisCluster|bool
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->expireat(...\func_get_args());
    }
    public function expiretime($key): \RedisCluster|false|int
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->expiretime(...\func_get_args());
    }
    public function pexpiretime($key): \RedisCluster|false|int
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->pexpiretime(...\func_get_args());
    }
    public function flushall($key_or_address, $async = \false): \RedisCluster|bool
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->flushall(...\func_get_args());
    }
    public function flushdb($key_or_address, $async = \false): \RedisCluster|bool
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->flushdb(...\func_get_args());
    }
    public function geoadd($key, $lng, $lat, $member, ...$other_triples_and_options): \RedisCluster|false|int
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->geoadd(...\func_get_args());
    }
    public function geodist($key, $src, $dest, $unit = null): \RedisCluster|false|float
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->geodist(...\func_get_args());
    }
    public function geohash($key, $member, ...$other_members): \RedisCluster|array|false
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->geohash(...\func_get_args());
    }
    public function geopos($key, $member, ...$other_members): \RedisCluster|array|false
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->geopos(...\func_get_args());
    }
    public function georadius($key, $lng, $lat, $radius, $unit, $options = []): mixed
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->georadius(...\func_get_args());
    }
    public function georadius_ro($key, $lng, $lat, $radius, $unit, $options = []): mixed
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->georadius_ro(...\func_get_args());
    }
    public function georadiusbymember($key, $member, $radius, $unit, $options = []): mixed
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->georadiusbymember(...\func_get_args());
    }
    public function georadiusbymember_ro($key, $member, $radius, $unit, $options = []): mixed
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->georadiusbymember_ro(...\func_get_args());
    }
    public function geosearch($key, $position, $shape, $unit, $options = []): \RedisCluster|array
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->geosearch(...\func_get_args());
    }
    public function geosearchstore($dst, $src, $position, $shape, $unit, $options = []): \RedisCluster|array|false|int
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->geosearchstore(...\func_get_args());
    }
    public function get($key): mixed
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->get(...\func_get_args());
    }
    public function getbit($key, $value): \RedisCluster|false|int
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->getbit(...\func_get_args());
    }
    public function getlasterror(): ?string
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->getlasterror(...\func_get_args());
    }
    public function getmode(): int
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->getmode(...\func_get_args());
    }
    public function getoption($option): mixed
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->getoption(...\func_get_args());
    }
    public function getrange($key, $start, $end): \RedisCluster|false|string
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->getrange(...\func_get_args());
    }
    public function lcs($key1, $key2, $options = null): \RedisCluster|array|false|int|string
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->lcs(...\func_get_args());
    }
    public function getset($key, $value): \RedisCluster|bool|string
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->getset(...\func_get_args());
    }
    public function gettransferredbytes(): array|false
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->gettransferredbytes(...\func_get_args());
    }
    public function cleartransferredbytes(): void
    {
        ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->cleartransferredbytes(...\func_get_args());
    }
    public function hdel($key, $member, ...$other_members): \RedisCluster|false|int
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->hdel(...\func_get_args());
    }
    public function hexists($key, $member): \RedisCluster|bool
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->hexists(...\func_get_args());
    }
    public function hget($key, $member): mixed
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->hget(...\func_get_args());
    }
    public function hgetall($key): \RedisCluster|array|false
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->hgetall(...\func_get_args());
    }
    public function hincrby($key, $member, $value): \RedisCluster|false|int
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->hincrby(...\func_get_args());
    }
    public function hincrbyfloat($key, $member, $value): \RedisCluster|false|float
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->hincrbyfloat(...\func_get_args());
    }
    public function hkeys($key): \RedisCluster|array|false
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->hkeys(...\func_get_args());
    }
    public function hlen($key): \RedisCluster|false|int
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->hlen(...\func_get_args());
    }
    public function hmget($key, $keys): \RedisCluster|array|false
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->hmget(...\func_get_args());
    }
    public function hmset($key, $key_values): \RedisCluster|bool
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->hmset(...\func_get_args());
    }
    public function hscan($key, &$iterator, $pattern = null, $count = 0): array|bool
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->hscan($key, $iterator, ...\array_slice(\func_get_args(), 2));
    }
    public function hrandfield($key, $options = null): \RedisCluster|array|string
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->hrandfield(...\func_get_args());
    }
    public function hset($key, $member, $value): \RedisCluster|false|int
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->hset(...\func_get_args());
    }
    public function hsetnx($key, $member, $value): \RedisCluster|bool
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->hsetnx(...\func_get_args());
    }
    public function hstrlen($key, $field): \RedisCluster|false|int
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->hstrlen(...\func_get_args());
    }
    public function hvals($key): \RedisCluster|array|false
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->hvals(...\func_get_args());
    }
    public function incr($key, $by = 1): \RedisCluster|false|int
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->incr(...\func_get_args());
    }
    public function incrby($key, $value): \RedisCluster|false|int
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->incrby(...\func_get_args());
    }
    public function incrbyfloat($key, $value): \RedisCluster|false|float
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->incrbyfloat(...\func_get_args());
    }
    public function info($key_or_address, ...$sections): \RedisCluster|array|false
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->info(...\func_get_args());
    }
    public function keys($pattern): \RedisCluster|array|false
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->keys(...\func_get_args());
    }
    public function lastsave($key_or_address): \RedisCluster|false|int
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->lastsave(...\func_get_args());
    }
    public function lget($key, $index): \RedisCluster|bool|string
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->lget(...\func_get_args());
    }
    public function lindex($key, $index): mixed
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->lindex(...\func_get_args());
    }
    public function linsert($key, $pos, $pivot, $value): \RedisCluster|false|int
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->linsert(...\func_get_args());
    }
    public function llen($key): \RedisCluster|bool|int
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->llen(...\func_get_args());
    }
    public function lpop($key, $count = 0): \RedisCluster|array|bool|string
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->lpop(...\func_get_args());
    }
    public function lpos($key, $value, $options = null): \Redis|array|bool|int|null
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->lpos(...\func_get_args());
    }
    public function lpush($key, $value, ...$other_values): \RedisCluster|bool|int
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->lpush(...\func_get_args());
    }
    public function lpushx($key, $value): \RedisCluster|bool|int
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->lpushx(...\func_get_args());
    }
    public function lrange($key, $start, $end): \RedisCluster|array|false
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->lrange(...\func_get_args());
    }
    public function lrem($key, $value, $count = 0): \RedisCluster|bool|int
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->lrem(...\func_get_args());
    }
    public function lset($key, $index, $value): \RedisCluster|bool
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->lset(...\func_get_args());
    }
    public function ltrim($key, $start, $end): \RedisCluster|bool
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->ltrim(...\func_get_args());
    }
    public function mget($keys): \RedisCluster|array|false
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->mget(...\func_get_args());
    }
    public function mset($key_values): \RedisCluster|bool
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->mset(...\func_get_args());
    }
    public function msetnx($key_values): \RedisCluster|array|false
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->msetnx(...\func_get_args());
    }
    public function multi($value = \Redis::MULTI): \RedisCluster|bool
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->multi(...\func_get_args());
    }
    public function object($subcommand, $key): \RedisCluster|false|int|string
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->object(...\func_get_args());
    }
    public function persist($key): \RedisCluster|bool
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->persist(...\func_get_args());
    }
    public function pexpire($key, $timeout, $mode = null): \RedisCluster|bool
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->pexpire(...\func_get_args());
    }
    public function pexpireat($key, $timestamp, $mode = null): \RedisCluster|bool
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->pexpireat(...\func_get_args());
    }
    public function pfadd($key, $elements): \RedisCluster|bool
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->pfadd(...\func_get_args());
    }
    public function pfcount($key): \RedisCluster|false|int
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->pfcount(...\func_get_args());
    }
    public function pfmerge($key, $keys): \RedisCluster|bool
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->pfmerge(...\func_get_args());
    }
    public function ping($key_or_address, $message = null): mixed
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->ping(...\func_get_args());
    }
    public function psetex($key, $timeout, $value): \RedisCluster|bool
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->psetex(...\func_get_args());
    }
    public function psubscribe($patterns, $callback): void
    {
        ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->psubscribe(...\func_get_args());
    }
    public function pttl($key): \RedisCluster|false|int
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->pttl(...\func_get_args());
    }
    public function pubsub($key_or_address, ...$values): mixed
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->pubsub(...\func_get_args());
    }
    public function punsubscribe($pattern, ...$other_patterns): array|bool
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->punsubscribe(...\func_get_args());
    }
    public function randomkey($key_or_address): \RedisCluster|bool|string
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->randomkey(...\func_get_args());
    }
    public function rawcommand($key_or_address, $command, ...$args): mixed
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->rawcommand(...\func_get_args());
    }
    public function rename($key_src, $key_dst): \RedisCluster|bool
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->rename(...\func_get_args());
    }
    public function renamenx($key, $newkey): \RedisCluster|bool
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->renamenx(...\func_get_args());
    }
    public function restore($key, $timeout, $value, $options = null): \RedisCluster|bool
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->restore(...\func_get_args());
    }
    public function role($key_or_address): mixed
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->role(...\func_get_args());
    }
    public function rpop($key, $count = 0): \RedisCluster|array|bool|string
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->rpop(...\func_get_args());
    }
    public function rpoplpush($src, $dst): \RedisCluster|bool|string
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->rpoplpush(...\func_get_args());
    }
    public function rpush($key, ...$elements): \RedisCluster|false|int
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->rpush(...\func_get_args());
    }
    public function rpushx($key, $value): \RedisCluster|bool|int
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->rpushx(...\func_get_args());
    }
    public function sadd($key, $value, ...$other_values): \RedisCluster|false|int
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->sadd(...\func_get_args());
    }
    public function saddarray($key, $values): \RedisCluster|bool|int
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->saddarray(...\func_get_args());
    }
    public function save($key_or_address): \RedisCluster|bool
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->save(...\func_get_args());
    }
    public function scan(&$iterator, $key_or_address, $pattern = null, $count = 0): array|bool
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->scan($iterator, ...\array_slice(\func_get_args(), 1));
    }
    public function scard($key): \RedisCluster|false|int
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->scard(...\func_get_args());
    }
    public function script($key_or_address, ...$args): mixed
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->script(...\func_get_args());
    }
    public function sdiff($key, ...$other_keys): \RedisCluster|array|false
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->sdiff(...\func_get_args());
    }
    public function sdiffstore($dst, $key, ...$other_keys): \RedisCluster|false|int
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->sdiffstore(...\func_get_args());
    }
    public function set($key, $value, $options = null): \RedisCluster|bool|string
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->set(...\func_get_args());
    }
    public function setbit($key, $offset, $onoff): \RedisCluster|false|int
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->setbit(...\func_get_args());
    }
    public function setex($key, $expire, $value): \RedisCluster|bool
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->setex(...\func_get_args());
    }
    public function setnx($key, $value): \RedisCluster|bool
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->setnx(...\func_get_args());
    }
    public function setoption($option, $value): bool
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->setoption(...\func_get_args());
    }
    public function setrange($key, $offset, $value): \RedisCluster|false|int
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->setrange(...\func_get_args());
    }
    public function sinter($key, ...$other_keys): \RedisCluster|array|false
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->sinter(...\func_get_args());
    }
    public function sintercard($keys, $limit = -1): \RedisCluster|false|int
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->sintercard(...\func_get_args());
    }
    public function sinterstore($key, ...$other_keys): \RedisCluster|false|int
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->sinterstore(...\func_get_args());
    }
    public function sismember($key, $value): \RedisCluster|bool
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->sismember(...\func_get_args());
    }
    public function smismember($key, $member, ...$other_members): \RedisCluster|array|false
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->smismember(...\func_get_args());
    }
    public function slowlog($key_or_address, ...$args): mixed
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->slowlog(...\func_get_args());
    }
    public function smembers($key): \RedisCluster|array|false
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->smembers(...\func_get_args());
    }
    public function smove($src, $dst, $member): \RedisCluster|bool
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->smove(...\func_get_args());
    }
    public function sort($key, $options = null): \RedisCluster|array|bool|int|string
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->sort(...\func_get_args());
    }
    public function sort_ro($key, $options = null): \RedisCluster|array|bool|int|string
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->sort_ro(...\func_get_args());
    }
    public function spop($key, $count = 0): \RedisCluster|array|false|string
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->spop(...\func_get_args());
    }
    public function srandmember($key, $count = 0): \RedisCluster|array|false|string
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->srandmember(...\func_get_args());
    }
    public function srem($key, $value, ...$other_values): \RedisCluster|false|int
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->srem(...\func_get_args());
    }
    public function sscan($key, &$iterator, $pattern = null, $count = 0): array|false
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->sscan($key, $iterator, ...\array_slice(\func_get_args(), 2));
    }
    public function strlen($key): \RedisCluster|false|int
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->strlen(...\func_get_args());
    }
    public function subscribe($channels, $cb): void
    {
        ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->subscribe(...\func_get_args());
    }
    public function sunion($key, ...$other_keys): \RedisCluster|array|bool
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->sunion(...\func_get_args());
    }
    public function sunionstore($dst, $key, ...$other_keys): \RedisCluster|false|int
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->sunionstore(...\func_get_args());
    }
    public function time($key_or_address): \RedisCluster|array|bool
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->time(...\func_get_args());
    }
    public function ttl($key): \RedisCluster|false|int
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->ttl(...\func_get_args());
    }
    public function type($key): \RedisCluster|false|int
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->type(...\func_get_args());
    }
    public function unsubscribe($channels): array|bool
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->unsubscribe(...\func_get_args());
    }
    public function unlink($key, ...$other_keys): \RedisCluster|false|int
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->unlink(...\func_get_args());
    }
    public function unwatch(): bool
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->unwatch(...\func_get_args());
    }
    public function watch($key, ...$other_keys): \RedisCluster|bool
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->watch(...\func_get_args());
    }
    public function xack($key, $group, $ids): \RedisCluster|false|int
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->xack(...\func_get_args());
    }
    public function xadd($key, $id, $values, $maxlen = 0, $approx = \false): \RedisCluster|false|string
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->xadd(...\func_get_args());
    }
    public function xclaim($key, $group, $consumer, $min_iddle, $ids, $options): \RedisCluster|array|false|string
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->xclaim(...\func_get_args());
    }
    public function xdel($key, $ids): \RedisCluster|false|int
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->xdel(...\func_get_args());
    }
    public function xgroup($operation, $key = null, $group = null, $id_or_consumer = null, $mkstream = \false, $entries_read = -2): mixed
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->xgroup(...\func_get_args());
    }
    public function xautoclaim($key, $group, $consumer, $min_idle, $start, $count = -1, $justid = \false): \RedisCluster|array|bool
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->xautoclaim(...\func_get_args());
    }
    public function xinfo($operation, $arg1 = null, $arg2 = null, $count = -1): mixed
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->xinfo(...\func_get_args());
    }
    public function xlen($key): \RedisCluster|false|int
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->xlen(...\func_get_args());
    }
    public function xpending($key, $group, $start = null, $end = null, $count = -1, $consumer = null): \RedisCluster|array|false
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->xpending(...\func_get_args());
    }
    public function xrange($key, $start, $end, $count = -1): \RedisCluster|array|bool
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->xrange(...\func_get_args());
    }
    public function xread($streams, $count = -1, $block = -1): \RedisCluster|array|bool
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->xread(...\func_get_args());
    }
    public function xreadgroup($group, $consumer, $streams, $count = 1, $block = 1): \RedisCluster|array|bool
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->xreadgroup(...\func_get_args());
    }
    public function xrevrange($key, $start, $end, $count = -1): \RedisCluster|array|bool
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->xrevrange(...\func_get_args());
    }
    public function xtrim($key, $maxlen, $approx = \false, $minid = \false, $limit = -1): \RedisCluster|false|int
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->xtrim(...\func_get_args());
    }
    public function zadd($key, $score_or_options, ...$more_scores_and_mems): \RedisCluster|false|float|int
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->zadd(...\func_get_args());
    }
    public function zcard($key): \RedisCluster|false|int
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->zcard(...\func_get_args());
    }
    public function zcount($key, $start, $end): \RedisCluster|false|int
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->zcount(...\func_get_args());
    }
    public function zincrby($key, $value, $member): \RedisCluster|false|float
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->zincrby(...\func_get_args());
    }
    public function zinterstore($dst, $keys, $weights = null, $aggregate = null): \RedisCluster|false|int
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->zinterstore(...\func_get_args());
    }
    public function zintercard($keys, $limit = -1): \RedisCluster|false|int
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->zintercard(...\func_get_args());
    }
    public function zlexcount($key, $min, $max): \RedisCluster|false|int
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->zlexcount(...\func_get_args());
    }
    public function zpopmax($key, $value = null): \RedisCluster|array|bool
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->zpopmax(...\func_get_args());
    }
    public function zpopmin($key, $value = null): \RedisCluster|array|bool
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->zpopmin(...\func_get_args());
    }
    public function zrange($key, $start, $end, $options = null): \RedisCluster|array|bool
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->zrange(...\func_get_args());
    }
    public function zrangestore($dstkey, $srckey, $start, $end, $options = null): \RedisCluster|false|int
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->zrangestore(...\func_get_args());
    }
    public function zrandmember($key, $options = null): \RedisCluster|array|string
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->zrandmember(...\func_get_args());
    }
    public function zrangebylex($key, $min, $max, $offset = -1, $count = -1): \RedisCluster|array|false
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->zrangebylex(...\func_get_args());
    }
    public function zrangebyscore($key, $start, $end, $options = []): \RedisCluster|array|false
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->zrangebyscore(...\func_get_args());
    }
    public function zrank($key, $member): \RedisCluster|false|int
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->zrank(...\func_get_args());
    }
    public function zrem($key, $value, ...$other_values): \RedisCluster|false|int
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->zrem(...\func_get_args());
    }
    public function zremrangebylex($key, $min, $max): \RedisCluster|false|int
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->zremrangebylex(...\func_get_args());
    }
    public function zremrangebyrank($key, $min, $max): \RedisCluster|false|int
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->zremrangebyrank(...\func_get_args());
    }
    public function zremrangebyscore($key, $min, $max): \RedisCluster|false|int
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->zremrangebyscore(...\func_get_args());
    }
    public function zrevrange($key, $min, $max, $options = null): \RedisCluster|array|bool
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->zrevrange(...\func_get_args());
    }
    public function zrevrangebylex($key, $min, $max, $options = null): \RedisCluster|array|bool
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->zrevrangebylex(...\func_get_args());
    }
    public function zrevrangebyscore($key, $min, $max, $options = null): \RedisCluster|array|bool
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->zrevrangebyscore(...\func_get_args());
    }
    public function zrevrank($key, $member): \RedisCluster|false|int
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->zrevrank(...\func_get_args());
    }
    public function zscan($key, &$iterator, $pattern = null, $count = 0): \RedisCluster|array|bool
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->zscan($key, $iterator, ...\array_slice(\func_get_args(), 2));
    }
    public function zscore($key, $member): \RedisCluster|false|float
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->zscore(...\func_get_args());
    }
    public function zmscore($key, $member, ...$other_members): \Redis|array|false
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->zmscore(...\func_get_args());
    }
    public function zunionstore($dst, $keys, $weights = null, $aggregate = null): \RedisCluster|false|int
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->zunionstore(...\func_get_args());
    }
    public function zinter($keys, $weights = null, $options = null): \RedisCluster|array|false
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->zinter(...\func_get_args());
    }
    public function zdiffstore($dst, $keys): \RedisCluster|false|int
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->zdiffstore(...\func_get_args());
    }
    public function zunion($keys, $weights = null, $options = null): \RedisCluster|array|false
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->zunion(...\func_get_args());
    }
    public function zdiff($keys, $options = null): \RedisCluster|array|false
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->zdiff(...\func_get_args());
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Cache\Traits;

use _ContaoManager\Symfony\Component\Cache\PruneableInterface;
use _ContaoManager\Symfony\Contracts\Service\ResetInterface;
/**
 * @author Nicolas Grekas <p@tchwork.com>
 *
 * @internal
 */
trait ProxyTrait
{
    private object $pool;
    public function prune(): bool
    {
        return $this->pool instanceof PruneableInterface && $this->pool->prune();
    }
    public function reset(): void
    {
        if ($this->pool instanceof ResetInterface) {
            $this->pool->reset();
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Cache\Traits;

use _ContaoManager\Symfony\Component\Cache\Exception\InvalidArgumentException;
/**
 * @author Nicolas Grekas <p@tchwork.com>
 *
 * @internal
 */
trait FilesystemCommonTrait
{
    private string $directory;
    private string $tmpSuffix;
    private function init(string $namespace, ?string $directory): void
    {
        if (!isset($directory[0])) {
            $directory = sys_get_temp_dir() . \DIRECTORY_SEPARATOR . 'symfony-cache';
        } else {
            $directory = realpath($directory) ?: $directory;
        }
        if (isset($namespace[0])) {
            if (preg_match('#[^-+_.A-Za-z0-9]#', $namespace, $match)) {
                throw new InvalidArgumentException(\sprintf('Namespace contains "%s" but only characters in [-+_.A-Za-z0-9] are allowed.', $match[0]));
            }
            $directory .= \DIRECTORY_SEPARATOR . $namespace;
        } else {
            $directory .= \DIRECTORY_SEPARATOR . '@';
        }
        if (!is_dir($directory)) {
            @mkdir($directory, 0777, \true);
        }
        $directory .= \DIRECTORY_SEPARATOR;
        // On Windows the whole path is limited to 258 chars
        if ('\\' === \DIRECTORY_SEPARATOR && \strlen($directory) > 234) {
            throw new InvalidArgumentException(\sprintf('Cache directory too long (%s).', $directory));
        }
        $this->directory = $directory;
    }
    protected function doClear(string $namespace): bool
    {
        $ok = \true;
        foreach ($this->scanHashDir($this->directory) as $file) {
            if ('' !== $namespace && !str_starts_with($this->getFileKey($file), $namespace)) {
                continue;
            }
            $ok = ($this->doUnlink($file) || !file_exists($file)) && $ok;
        }
        return $ok;
    }
    protected function doDelete(array $ids): bool
    {
        $ok = \true;
        foreach ($ids as $id) {
            $file = $this->getFile($id);
            $ok = (!is_file($file) || $this->doUnlink($file) || !file_exists($file)) && $ok;
        }
        return $ok;
    }
    /**
     * @return bool
     */
    protected function doUnlink(string $file)
    {
        return @unlink($file);
    }
    private function write(string $file, string $data, ?int $expiresAt = null): bool
    {
        $unlink = \false;
        set_error_handler(static fn($type, $message, $file, $line) => throw new \ErrorException($message, 0, $type, $file, $line));
        try {
            $tmp = $this->directory . $this->tmpSuffix ??= str_replace('/', '-', base64_encode(random_bytes(6)));
            try {
                $h = fopen($tmp, 'x');
            } catch (\ErrorException $e) {
                if (!str_contains($e->getMessage(), 'File exists')) {
                    throw $e;
                }
                $tmp = $this->directory . $this->tmpSuffix = str_replace('/', '-', base64_encode(random_bytes(6)));
                $h = fopen($tmp, 'x');
            }
            fwrite($h, $data);
            fclose($h);
            $unlink = \true;
            if (null !== $expiresAt) {
                touch($tmp, $expiresAt ?: time() + 31556952);
                // 1 year in seconds
            }
            if ('\\' === \DIRECTORY_SEPARATOR) {
                $success = copy($tmp, $file);
                $unlink = \true;
            } else {
                $success = rename($tmp, $file);
                $unlink = !$success;
            }
            return $success;
        } finally {
            restore_error_handler();
            if ($unlink) {
                @unlink($tmp);
            }
        }
    }
    private function getFile(string $id, bool $mkdir = \false, ?string $directory = null): string
    {
        // Use xxh128 to favor speed over security, which is not an issue here
        $hash = str_replace('/', '-', base64_encode(hash('xxh128', static::class . $id, \true)));
        $dir = ($directory ?? $this->directory) . strtoupper($hash[0] . \DIRECTORY_SEPARATOR . $hash[1] . \DIRECTORY_SEPARATOR);
        if ($mkdir && !is_dir($dir)) {
            @mkdir($dir, 0777, \true);
        }
        return $dir . substr($hash, 2, 20);
    }
    private function getFileKey(string $file): string
    {
        return '';
    }
    private function scanHashDir(string $directory): \Generator
    {
        if (!is_dir($directory)) {
            return;
        }
        $chars = '+-ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
        for ($i = 0; $i < 38; ++$i) {
            if (!is_dir($directory . $chars[$i])) {
                continue;
            }
            for ($j = 0; $j < 38; ++$j) {
                if (!is_dir($dir = $directory . $chars[$i] . \DIRECTORY_SEPARATOR . $chars[$j])) {
                    continue;
                }
                foreach (@scandir($dir, \SCANDIR_SORT_NONE) ?: [] as $file) {
                    if ('.' !== $file && '..' !== $file) {
                        yield $dir . \DIRECTORY_SEPARATOR . $file;
                    }
                }
            }
        }
    }
    public function __serialize(): array
    {
        throw new \BadMethodCallException('Cannot serialize ' . __CLASS__);
    }
    public function __unserialize(array $data): void
    {
        throw new \BadMethodCallException('Cannot unserialize ' . __CLASS__);
    }
    public function __destruct()
    {
        if (method_exists(parent::class, '__destruct')) {
            parent::__destruct();
        }
        if (isset($this->tmpSuffix) && is_file($this->directory . $this->tmpSuffix)) {
            unlink($this->directory . $this->tmpSuffix);
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Cache\Traits;

class_alias(6.0 <= (float) phpversion('redis') ? RedisCluster6Proxy::class : RedisCluster5Proxy::class, RedisClusterProxy::class);
if (\false) {
    /**
     * @internal
     */
    class RedisClusterProxy extends \RedisCluster
    {
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Cache\Traits;

class_alias(6.0 <= (float) phpversion('redis') ? Redis6Proxy::class : Redis5Proxy::class, RedisProxy::class);
if (\false) {
    /**
     * @internal
     */
    class RedisProxy extends \Redis
    {
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Cache\Traits;

use _ContaoManager\Psr\Log\LoggerInterface;
use _ContaoManager\Symfony\Component\Cache\Adapter\AdapterInterface;
use _ContaoManager\Symfony\Component\Cache\CacheItem;
use _ContaoManager\Symfony\Component\Cache\Exception\InvalidArgumentException;
use _ContaoManager\Symfony\Component\Cache\LockRegistry;
use _ContaoManager\Symfony\Contracts\Cache\CacheInterface;
use _ContaoManager\Symfony\Contracts\Cache\CacheTrait;
use _ContaoManager\Symfony\Contracts\Cache\ItemInterface;
/**
 * @author Nicolas Grekas <p@tchwork.com>
 *
 * @internal
 */
trait ContractsTrait
{
    use CacheTrait {
        doGet as private contractsGet;
    }
    private \Closure $callbackWrapper;
    private array $computing = [];
    /**
     * Wraps the callback passed to ->get() in a callable.
     *
     * @return callable the previous callback wrapper
     */
    public function setCallbackWrapper(?callable $callbackWrapper): callable
    {
        if (!isset($this->callbackWrapper)) {
            $this->callbackWrapper = LockRegistry::compute(...);
            if (\in_array(\PHP_SAPI, ['cli', 'phpdbg', 'embed'], \true)) {
                $this->setCallbackWrapper(null);
            }
        }
        if (null !== $callbackWrapper && !$callbackWrapper instanceof \Closure) {
            $callbackWrapper = $callbackWrapper(...);
        }
        $previousWrapper = $this->callbackWrapper;
        $this->callbackWrapper = $callbackWrapper ?? static fn(callable $callback, ItemInterface $item, bool &$save, CacheInterface $pool, \Closure $setMetadata, ?LoggerInterface $logger, ?float $beta = null) => $callback($item, $save);
        return $previousWrapper;
    }
    private function doGet(AdapterInterface $pool, string $key, callable $callback, ?float $beta, ?array &$metadata = null): mixed
    {
        if (0 > $beta ??= 1.0) {
            throw new InvalidArgumentException(\sprintf('Argument "$beta" provided to "%s::get()" must be a positive number, %f given.', static::class, $beta));
        }
        static $setMetadata;
        $setMetadata ??= \Closure::bind(static function (CacheItem $item, float $startTime, ?array &$metadata) {
            if ($item->expiry > $endTime = microtime(\true)) {
                $item->newMetadata[CacheItem::METADATA_EXPIRY] = $metadata[CacheItem::METADATA_EXPIRY] = $item->expiry;
                $item->newMetadata[CacheItem::METADATA_CTIME] = $metadata[CacheItem::METADATA_CTIME] = (int) ceil(1000 * ($endTime - $startTime));
            } else {
                unset($metadata[CacheItem::METADATA_EXPIRY], $metadata[CacheItem::METADATA_CTIME], $metadata[CacheItem::METADATA_TAGS]);
            }
        }, null, CacheItem::class);
        $this->callbackWrapper ??= LockRegistry::compute(...);
        return $this->contractsGet($pool, $key, function (CacheItem $item, bool &$save) use ($pool, $callback, $setMetadata, &$metadata, $key, $beta) {
            // don't wrap nor save recursive calls
            if (isset($this->computing[$key])) {
                $value = $callback($item, $save);
                $save = \false;
                return $value;
            }
            $this->computing[$key] = $key;
            $startTime = microtime(\true);
            if (!isset($this->callbackWrapper)) {
                $this->setCallbackWrapper($this->setCallbackWrapper(null));
            }
            try {
                $value = ($this->callbackWrapper)($callback, $item, $save, $pool, function (CacheItem $item) use ($setMetadata, $startTime, &$metadata) {
                    $setMetadata($item, $startTime, $metadata);
                }, $this->logger ?? null, $beta);
                $setMetadata($item, $startTime, $metadata);
                return $value;
            } finally {
                unset($this->computing[$key]);
            }
        }, $beta, $metadata, $this->logger ?? null);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Cache\Traits;

if (version_compare(phpversion('redis'), '6.2.0', '>=')) {
    /**
     * @internal
     */
    trait RedisCluster62ProxyTrait
    {
        public function expiremember($key, $field, $ttl, $unit = null): \Redis|false|int
        {
            return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->expiremember(...\func_get_args());
        }
        public function expirememberat($key, $field, $timestamp): \Redis|false|int
        {
            return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->expirememberat(...\func_get_args());
        }
        public function getdel($key): mixed
        {
            return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->getdel(...\func_get_args());
        }
        public function getWithMeta($key): \RedisCluster|array|false
        {
            return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->getWithMeta(...\func_get_args());
        }
    }
} else {
    /**
     * @internal
     */
    trait RedisCluster62ProxyTrait
    {
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Cache\Traits;

if (version_compare(phpversion('redis'), '6.3.0', '>=')) {
    /**
     * @internal
     */
    trait Redis63ProxyTrait
    {
        public function delifeq($key, $value): \Redis|int|false
        {
            return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->delifeq(...\func_get_args());
        }
        public function hexpire($key, $ttl, $fields, $mode = null): \Redis|array|false
        {
            return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->hexpire(...\func_get_args());
        }
        public function hexpireat($key, $time, $fields, $mode = null): \Redis|array|false
        {
            return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->hexpireat(...\func_get_args());
        }
        public function hexpiretime($key, $fields): \Redis|array|false
        {
            return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->hexpiretime(...\func_get_args());
        }
        public function hgetdel($key, $fields): \Redis|array|false
        {
            return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->hgetdel(...\func_get_args());
        }
        public function hgetex($key, $fields, $expiry = null): \Redis|array|false
        {
            return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->hgetex(...\func_get_args());
        }
        public function hGetWithMeta($key, $member): mixed
        {
            return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->hGetWithMeta(...\func_get_args());
        }
        public function hpersist($key, $fields): \Redis|array|false
        {
            return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->hpersist(...\func_get_args());
        }
        public function hpexpire($key, $ttl, $fields, $mode = null): \Redis|array|false
        {
            return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->hpexpire(...\func_get_args());
        }
        public function hpexpireat($key, $mstime, $fields, $mode = null): \Redis|array|false
        {
            return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->hpexpireat(...\func_get_args());
        }
        public function hpexpiretime($key, $fields): \Redis|array|false
        {
            return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->hpexpiretime(...\func_get_args());
        }
        public function hpttl($key, $fields): \Redis|array|false
        {
            return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->hpttl(...\func_get_args());
        }
        public function hsetex($key, $fields, $expiry = null): \Redis|int|false
        {
            return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->hsetex(...\func_get_args());
        }
        public function httl($key, $fields): \Redis|array|false
        {
            return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->httl(...\func_get_args());
        }
        public function vadd($key, $values, $element, $options = null): \Redis|int|false
        {
            return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->vadd(...\func_get_args());
        }
        public function vcard($key): \Redis|int|false
        {
            return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->vcard(...\func_get_args());
        }
        public function vdim($key): \Redis|int|false
        {
            return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->vdim(...\func_get_args());
        }
        public function vemb($key, $member, $raw = \false): \Redis|array|false
        {
            return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->vemb(...\func_get_args());
        }
        public function vgetattr($key, $member, $decode = \true): \Redis|array|string|false
        {
            return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->vgetattr(...\func_get_args());
        }
        public function vinfo($key): \Redis|array|false
        {
            return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->vinfo(...\func_get_args());
        }
        public function vismember($key, $member): \Redis|bool
        {
            return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->vismember(...\func_get_args());
        }
        public function vlinks($key, $member, $withscores = \false): \Redis|array|false
        {
            return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->vlinks(...\func_get_args());
        }
        public function vrandmember($key, $count = 0): \Redis|array|string|false
        {
            return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->vrandmember(...\func_get_args());
        }
        public function vrange($key, $min, $max, $count = -1): \Redis|array|false
        {
            return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->vrange(...\func_get_args());
        }
        public function vrem($key, $member): \Redis|int|false
        {
            return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->vrem(...\func_get_args());
        }
        public function vsetattr($key, $member, $attributes): \Redis|int|false
        {
            return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->vsetattr(...\func_get_args());
        }
        public function vsim($key, $member, $options = null): \Redis|array|false
        {
            return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->vsim(...\func_get_args());
        }
    }
} else {
    /**
     * @internal
     */
    trait Redis63ProxyTrait
    {
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Cache\Traits;

if (version_compare(phpversion('redis'), '6.1.0-dev', '>')) {
    /**
     * @internal
     */
    trait RedisCluster61ProxyTrait
    {
        public function getex($key, $options = []): \RedisCluster|string|false
        {
            return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->getex(...\func_get_args());
        }
        public function publish($channel, $message): \RedisCluster|bool|int
        {
            return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->publish(...\func_get_args());
        }
        public function waitaof($key_or_address, $numlocal, $numreplicas, $timeout): \RedisCluster|array|false
        {
            return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->waitaof(...\func_get_args());
        }
    }
} else {
    /**
     * @internal
     */
    trait RedisCluster61ProxyTrait
    {
        public function publish($channel, $message): \RedisCluster|bool
        {
            return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->publish(...\func_get_args());
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Cache\Traits;

use _ContaoManager\Symfony\Component\Cache\Traits\Relay\BgsaveTrait;
use _ContaoManager\Symfony\Component\Cache\Traits\Relay\CopyTrait;
use _ContaoManager\Symfony\Component\Cache\Traits\Relay\FtTrait;
use _ContaoManager\Symfony\Component\Cache\Traits\Relay\GeosearchTrait;
use _ContaoManager\Symfony\Component\Cache\Traits\Relay\GetrangeTrait;
use _ContaoManager\Symfony\Component\Cache\Traits\Relay\GetWithMetaTrait;
use _ContaoManager\Symfony\Component\Cache\Traits\Relay\HsetTrait;
use _ContaoManager\Symfony\Component\Cache\Traits\Relay\IsTrackedTrait;
use _ContaoManager\Symfony\Component\Cache\Traits\Relay\MoveTrait;
use _ContaoManager\Symfony\Component\Cache\Traits\Relay\NullableReturnTrait;
use _ContaoManager\Symfony\Component\Cache\Traits\Relay\PfcountTrait;
use _ContaoManager\Symfony\Component\Cache\Traits\Relay\Relay11Trait;
use _ContaoManager\Symfony\Component\Cache\Traits\Relay\Relay121Trait;
use _ContaoManager\Symfony\Component\Cache\Traits\Relay\Relay12Trait;
use _ContaoManager\Symfony\Component\Cache\Traits\Relay\Relay20Trait;
use _ContaoManager\Symfony\Component\Cache\Traits\Relay\Relay21Trait;
use _ContaoManager\Symfony\Component\Cache\Traits\Relay\SwapdbTrait;
use _ContaoManager\Symfony\Component\VarExporter\LazyObjectInterface;
use _ContaoManager\Symfony\Component\VarExporter\LazyProxyTrait;
use _ContaoManager\Symfony\Contracts\Service\ResetInterface;
// Help opcache.preload discover always-needed symbols
class_exists(\_ContaoManager\Symfony\Component\VarExporter\Internal\Hydrator::class);
class_exists(\_ContaoManager\Symfony\Component\VarExporter\Internal\LazyObjectRegistry::class);
class_exists(\_ContaoManager\Symfony\Component\VarExporter\Internal\LazyObjectState::class);
/**
 * @internal
 */
class RelayProxy extends \Relay\Relay implements ResetInterface, LazyObjectInterface
{
    use BgsaveTrait;
    use CopyTrait;
    use FtTrait;
    use GeosearchTrait;
    use GetrangeTrait;
    use GetWithMetaTrait;
    use HsetTrait;
    use IsTrackedTrait;
    use LazyProxyTrait {
        resetLazyObject as reset;
    }
    use MoveTrait;
    use NullableReturnTrait;
    use PfcountTrait;
    use RelayProxyTrait;
    use Relay11Trait;
    use Relay12Trait;
    use Relay121Trait;
    use Relay20Trait;
    use Relay21Trait;
    use SwapdbTrait;
    private const LAZY_OBJECT_PROPERTY_SCOPES = [];
    public function __construct(
        $host = null,
        $port = 6379,
        $connect_timeout = 0.0,
        $command_timeout = 0.0,
        #[\SensitiveParameter]
        $context = [],
        $database = 0
    )
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->__construct(...\func_get_args());
    }
    public function connect(
        $host,
        $port = 6379,
        $timeout = 0.0,
        $persistent_id = null,
        $retry_interval = 0,
        $read_timeout = 0.0,
        #[\SensitiveParameter]
        $context = [],
        $database = 0
    ): bool
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->connect(...\func_get_args());
    }
    public function pconnect(
        $host,
        $port = 6379,
        $timeout = 0.0,
        $persistent_id = null,
        $retry_interval = 0,
        $read_timeout = 0.0,
        #[\SensitiveParameter]
        $context = [],
        $database = 0
    ): bool
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->pconnect(...\func_get_args());
    }
    public function close(): bool
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->close(...\func_get_args());
    }
    public function pclose(): bool
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->pclose(...\func_get_args());
    }
    public function listen($callback): bool
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->listen(...\func_get_args());
    }
    public function onFlushed($callback): bool
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->onFlushed(...\func_get_args());
    }
    public function onInvalidated($callback, $pattern = null): bool
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->onInvalidated(...\func_get_args());
    }
    public function dispatchEvents(): false|int
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->dispatchEvents(...\func_get_args());
    }
    public function getOption($option): mixed
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->getOption(...\func_get_args());
    }
    public function option($option, $value = null): mixed
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->option(...\func_get_args());
    }
    public function setOption($option, $value): bool
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->setOption(...\func_get_args());
    }
    public function addIgnorePatterns(...$pattern): int
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->addIgnorePatterns(...\func_get_args());
    }
    public function addAllowPatterns(...$pattern): int
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->addAllowPatterns(...\func_get_args());
    }
    public function getTimeout(): false|float
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->getTimeout(...\func_get_args());
    }
    public function timeout(): false|float
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->timeout(...\func_get_args());
    }
    public function getReadTimeout(): false|float
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->getReadTimeout(...\func_get_args());
    }
    public function readTimeout(): false|float
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->readTimeout(...\func_get_args());
    }
    public function getBytes(): array
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->getBytes(...\func_get_args());
    }
    public function bytes(): array
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->bytes(...\func_get_args());
    }
    public function getHost(): false|string
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->getHost(...\func_get_args());
    }
    public function isConnected(): bool
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->isConnected(...\func_get_args());
    }
    public function getPort(): false|int
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->getPort(...\func_get_args());
    }
    public function getAuth(): mixed
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->getAuth(...\func_get_args());
    }
    public function getDbNum(): mixed
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->getDbNum(...\func_get_args());
    }
    public function _serialize($value): mixed
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->_serialize(...\func_get_args());
    }
    public function _unserialize($value): mixed
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->_unserialize(...\func_get_args());
    }
    public function _compress($value): string
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->_compress(...\func_get_args());
    }
    public function _uncompress($value): string
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->_uncompress(...\func_get_args());
    }
    public function _pack($value): string
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->_pack(...\func_get_args());
    }
    public function _unpack($value): mixed
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->_unpack(...\func_get_args());
    }
    public function _prefix($value): string
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->_prefix(...\func_get_args());
    }
    public function getLastError(): ?string
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->getLastError(...\func_get_args());
    }
    public function clearLastError(): bool
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->clearLastError(...\func_get_args());
    }
    public function endpointId(): false|string
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->endpointId(...\func_get_args());
    }
    public function getPersistentID(): false|string
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->getPersistentID(...\func_get_args());
    }
    public function socketId(): false|string
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->socketId(...\func_get_args());
    }
    public function rawCommand($cmd, ...$args): mixed
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->rawCommand(...\func_get_args());
    }
    public function auth(
        #[\SensitiveParameter]
        $auth
    ): bool
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->auth(...\func_get_args());
    }
    public function info(...$sections): \Relay\Relay|array|false
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->info(...\func_get_args());
    }
    public function flushdb($sync = null): \Relay\Relay|bool
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->flushdb(...\func_get_args());
    }
    public function flushall($sync = null): \Relay\Relay|bool
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->flushall(...\func_get_args());
    }
    public function fcall($name, $keys = [], $argv = [], $handler = null): mixed
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->fcall(...\func_get_args());
    }
    public function fcall_ro($name, $keys = [], $argv = [], $handler = null): mixed
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->fcall_ro(...\func_get_args());
    }
    public function function($op, ...$args): mixed
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->function(...\func_get_args());
    }
    public function dbsize(): \Relay\Relay|false|int
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->dbsize(...\func_get_args());
    }
    public function replicaof($host = null, $port = 0): \Relay\Relay|bool
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->replicaof(...\func_get_args());
    }
    public function waitaof($numlocal, $numremote, $timeout): \Relay\Relay|array|false
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->waitaof(...\func_get_args());
    }
    public function restore($key, $ttl, $value, $options = null): \Relay\Relay|bool
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->restore(...\func_get_args());
    }
    public function migrate(
        $host,
        $port,
        $key,
        $dstdb,
        $timeout,
        $copy = \false,
        $replace = \false,
        #[\SensitiveParameter]
        $credentials = null
    ): \Relay\Relay|bool
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->migrate(...\func_get_args());
    }
    public function echo($arg): \Relay\Relay|bool|string
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->echo(...\func_get_args());
    }
    public function ping($arg = null): \Relay\Relay|bool|string
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->ping(...\func_get_args());
    }
    public function idleTime(): \Relay\Relay|false|int
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->idleTime(...\func_get_args());
    }
    public function randomkey(): \Relay\Relay|bool|null|string
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->randomkey(...\func_get_args());
    }
    public function time(): \Relay\Relay|array|false
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->time(...\func_get_args());
    }
    public function bgrewriteaof(): \Relay\Relay|bool
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->bgrewriteaof(...\func_get_args());
    }
    public function lastsave(): \Relay\Relay|false|int
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->lastsave(...\func_get_args());
    }
    public function lcs($key1, $key2, $options = null): mixed
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->lcs(...\func_get_args());
    }
    public function save(): \Relay\Relay|bool
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->save(...\func_get_args());
    }
    public function role(): \Relay\Relay|array|false
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->role(...\func_get_args());
    }
    public function ttl($key): \Relay\Relay|false|int
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->ttl(...\func_get_args());
    }
    public function pttl($key): \Relay\Relay|false|int
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->pttl(...\func_get_args());
    }
    public function exists(...$keys): \Relay\Relay|bool|int
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->exists(...\func_get_args());
    }
    public function eval($script, $args = [], $num_keys = 0): mixed
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->eval(...\func_get_args());
    }
    public function eval_ro($script, $args = [], $num_keys = 0): mixed
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->eval_ro(...\func_get_args());
    }
    public function evalsha($sha, $args = [], $num_keys = 0): mixed
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->evalsha(...\func_get_args());
    }
    public function evalsha_ro($sha, $args = [], $num_keys = 0): mixed
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->evalsha_ro(...\func_get_args());
    }
    public function client($operation, ...$args): mixed
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->client(...\func_get_args());
    }
    public function geoadd($key, $lng, $lat, $member, ...$other_triples_and_options): \Relay\Relay|false|int
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->geoadd(...\func_get_args());
    }
    public function geohash($key, $member, ...$other_members): \Relay\Relay|array|false
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->geohash(...\func_get_args());
    }
    public function georadius($key, $lng, $lat, $radius, $unit, $options = []): mixed
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->georadius(...\func_get_args());
    }
    public function georadiusbymember($key, $member, $radius, $unit, $options = []): mixed
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->georadiusbymember(...\func_get_args());
    }
    public function georadiusbymember_ro($key, $member, $radius, $unit, $options = []): mixed
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->georadiusbymember_ro(...\func_get_args());
    }
    public function georadius_ro($key, $lng, $lat, $radius, $unit, $options = []): mixed
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->georadius_ro(...\func_get_args());
    }
    public function geosearchstore($dst, $src, $position, $shape, $unit, $options = []): \Relay\Relay|false|int
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->geosearchstore(...\func_get_args());
    }
    public function get($key): mixed
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->get(...\func_get_args());
    }
    public function getset($key, $value): mixed
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->getset(...\func_get_args());
    }
    public function setrange($key, $start, $value): \Relay\Relay|false|int
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->setrange(...\func_get_args());
    }
    public function getbit($key, $pos): \Relay\Relay|false|int
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->getbit(...\func_get_args());
    }
    public function bitcount($key, $start = 0, $end = -1, $by_bit = \false): \Relay\Relay|false|int
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->bitcount(...\func_get_args());
    }
    public function bitfield($key, ...$args): \Relay\Relay|array|false
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->bitfield(...\func_get_args());
    }
    public function config($operation, $key = null, $value = null): \Relay\Relay|array|bool
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->config(...\func_get_args());
    }
    public function command(...$args): \Relay\Relay|array|false|int
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->command(...\func_get_args());
    }
    public function bitop($operation, $dstkey, $srckey, ...$other_keys): \Relay\Relay|false|int
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->bitop(...\func_get_args());
    }
    public function bitpos($key, $bit, $start = null, $end = null, $bybit = \false): \Relay\Relay|false|int
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->bitpos(...\func_get_args());
    }
    public function setbit($key, $pos, $val): \Relay\Relay|false|int
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->setbit(...\func_get_args());
    }
    public function acl($cmd, ...$args): mixed
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->acl(...\func_get_args());
    }
    public function append($key, $value): \Relay\Relay|false|int
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->append(...\func_get_args());
    }
    public function set($key, $value, $options = null): mixed
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->set(...\func_get_args());
    }
    public function getex($key, $options = null): mixed
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->getex(...\func_get_args());
    }
    public function getdel($key): mixed
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->getdel(...\func_get_args());
    }
    public function setex($key, $seconds, $value): \Relay\Relay|bool
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->setex(...\func_get_args());
    }
    public function pfadd($key, $elements): \Relay\Relay|false|int
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->pfadd(...\func_get_args());
    }
    public function pfmerge($dst, $srckeys): \Relay\Relay|bool
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->pfmerge(...\func_get_args());
    }
    public function psetex($key, $milliseconds, $value): \Relay\Relay|bool
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->psetex(...\func_get_args());
    }
    public function publish($channel, $message): \Relay\Relay|false|int
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->publish(...\func_get_args());
    }
    public function pubsub($operation, ...$args): mixed
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->pubsub(...\func_get_args());
    }
    public function spublish($channel, $message): \Relay\Relay|false|int
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->spublish(...\func_get_args());
    }
    public function setnx($key, $value): \Relay\Relay|bool
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->setnx(...\func_get_args());
    }
    public function mget($keys): \Relay\Relay|array|false
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->mget(...\func_get_args());
    }
    public function move($key, $db): \Relay\Relay|false|int
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->move(...\func_get_args());
    }
    public function mset($kvals): \Relay\Relay|bool
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->mset(...\func_get_args());
    }
    public function msetnx($kvals): \Relay\Relay|bool
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->msetnx(...\func_get_args());
    }
    public function rename($key, $newkey): \Relay\Relay|bool
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->rename(...\func_get_args());
    }
    public function renamenx($key, $newkey): \Relay\Relay|bool
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->renamenx(...\func_get_args());
    }
    public function del(...$keys): \Relay\Relay|bool|int
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->del(...\func_get_args());
    }
    public function unlink(...$keys): \Relay\Relay|false|int
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->unlink(...\func_get_args());
    }
    public function expire($key, $seconds, $mode = null): \Relay\Relay|bool
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->expire(...\func_get_args());
    }
    public function pexpire($key, $milliseconds): \Relay\Relay|bool
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->pexpire(...\func_get_args());
    }
    public function expireat($key, $timestamp): \Relay\Relay|bool
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->expireat(...\func_get_args());
    }
    public function expiretime($key): \Relay\Relay|false|int
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->expiretime(...\func_get_args());
    }
    public function pexpireat($key, $timestamp_ms): \Relay\Relay|bool
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->pexpireat(...\func_get_args());
    }
    public function pexpiretime($key): \Relay\Relay|false|int
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->pexpiretime(...\func_get_args());
    }
    public function persist($key): \Relay\Relay|bool
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->persist(...\func_get_args());
    }
    public function type($key): \Relay\Relay|bool|int|string
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->type(...\func_get_args());
    }
    public function lrange($key, $start, $stop): \Relay\Relay|array|false
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->lrange(...\func_get_args());
    }
    public function lpush($key, $mem, ...$mems): \Relay\Relay|false|int
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->lpush(...\func_get_args());
    }
    public function rpush($key, $mem, ...$mems): \Relay\Relay|false|int
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->rpush(...\func_get_args());
    }
    public function lpushx($key, $mem, ...$mems): \Relay\Relay|false|int
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->lpushx(...\func_get_args());
    }
    public function rpushx($key, $mem, ...$mems): \Relay\Relay|false|int
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->rpushx(...\func_get_args());
    }
    public function lset($key, $index, $mem): \Relay\Relay|bool
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->lset(...\func_get_args());
    }
    public function lpop($key, $count = 1): mixed
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->lpop(...\func_get_args());
    }
    public function lpos($key, $value, $options = null): \Relay\Relay|array|false|int|null
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->lpos(...\func_get_args());
    }
    public function rpop($key, $count = 1): mixed
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->rpop(...\func_get_args());
    }
    public function rpoplpush($source, $dest): mixed
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->rpoplpush(...\func_get_args());
    }
    public function brpoplpush($source, $dest, $timeout): mixed
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->brpoplpush(...\func_get_args());
    }
    public function blpop($key, $timeout_or_key, ...$extra_args): \Relay\Relay|array|false|null
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->blpop(...\func_get_args());
    }
    public function blmpop($timeout, $keys, $from, $count = 1): \Relay\Relay|array|false|null
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->blmpop(...\func_get_args());
    }
    public function bzmpop($timeout, $keys, $from, $count = 1): \Relay\Relay|array|false|null
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->bzmpop(...\func_get_args());
    }
    public function lmpop($keys, $from, $count = 1): \Relay\Relay|array|false|null
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->lmpop(...\func_get_args());
    }
    public function zmpop($keys, $from, $count = 1): \Relay\Relay|array|false|null
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->zmpop(...\func_get_args());
    }
    public function brpop($key, $timeout_or_key, ...$extra_args): \Relay\Relay|array|false|null
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->brpop(...\func_get_args());
    }
    public function bzpopmax($key, $timeout_or_key, ...$extra_args): \Relay\Relay|array|false|null
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->bzpopmax(...\func_get_args());
    }
    public function bzpopmin($key, $timeout_or_key, ...$extra_args): \Relay\Relay|array|false|null
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->bzpopmin(...\func_get_args());
    }
    public function object($op, $key): mixed
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->object(...\func_get_args());
    }
    public function geopos($key, ...$members): \Relay\Relay|array|false
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->geopos(...\func_get_args());
    }
    public function lrem($key, $mem, $count = 0): \Relay\Relay|false|int
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->lrem(...\func_get_args());
    }
    public function lindex($key, $index): mixed
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->lindex(...\func_get_args());
    }
    public function linsert($key, $op, $pivot, $element): \Relay\Relay|false|int
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->linsert(...\func_get_args());
    }
    public function ltrim($key, $start, $end): \Relay\Relay|bool
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->ltrim(...\func_get_args());
    }
    public function hget($hash, $member): mixed
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->hget(...\func_get_args());
    }
    public function hstrlen($hash, $member): \Relay\Relay|false|int
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->hstrlen(...\func_get_args());
    }
    public function hgetall($hash): \Relay\Relay|array|false
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->hgetall(...\func_get_args());
    }
    public function hkeys($hash): \Relay\Relay|array|false
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->hkeys(...\func_get_args());
    }
    public function hvals($hash): \Relay\Relay|array|false
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->hvals(...\func_get_args());
    }
    public function hmget($hash, $members): \Relay\Relay|array|false
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->hmget(...\func_get_args());
    }
    public function hmset($hash, $members): \Relay\Relay|bool
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->hmset(...\func_get_args());
    }
    public function hexists($hash, $member): \Relay\Relay|bool
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->hexists(...\func_get_args());
    }
    public function hsetnx($hash, $member, $value): \Relay\Relay|bool
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->hsetnx(...\func_get_args());
    }
    public function hdel($key, $mem, ...$mems): \Relay\Relay|false|int
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->hdel(...\func_get_args());
    }
    public function hincrby($key, $mem, $value): \Relay\Relay|false|int
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->hincrby(...\func_get_args());
    }
    public function hincrbyfloat($key, $mem, $value): \Relay\Relay|bool|float
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->hincrbyfloat(...\func_get_args());
    }
    public function incr($key, $by = 1): \Relay\Relay|false|int
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->incr(...\func_get_args());
    }
    public function decr($key, $by = 1): \Relay\Relay|false|int
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->decr(...\func_get_args());
    }
    public function incrby($key, $value): \Relay\Relay|false|int
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->incrby(...\func_get_args());
    }
    public function decrby($key, $value): \Relay\Relay|false|int
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->decrby(...\func_get_args());
    }
    public function incrbyfloat($key, $value): \Relay\Relay|false|float
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->incrbyfloat(...\func_get_args());
    }
    public function sdiff($key, ...$other_keys): \Relay\Relay|array|false
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->sdiff(...\func_get_args());
    }
    public function sdiffstore($key, ...$other_keys): \Relay\Relay|false|int
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->sdiffstore(...\func_get_args());
    }
    public function sinter($key, ...$other_keys): \Relay\Relay|array|false
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->sinter(...\func_get_args());
    }
    public function sintercard($keys, $limit = -1): \Relay\Relay|false|int
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->sintercard(...\func_get_args());
    }
    public function sinterstore($key, ...$other_keys): \Relay\Relay|false|int
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->sinterstore(...\func_get_args());
    }
    public function sunion($key, ...$other_keys): \Relay\Relay|array|false
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->sunion(...\func_get_args());
    }
    public function sunionstore($key, ...$other_keys): \Relay\Relay|false|int
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->sunionstore(...\func_get_args());
    }
    public function subscribe($channels, $callback): bool
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->subscribe(...\func_get_args());
    }
    public function unsubscribe($channels = []): bool
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->unsubscribe(...\func_get_args());
    }
    public function psubscribe($patterns, $callback): bool
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->psubscribe(...\func_get_args());
    }
    public function punsubscribe($patterns = []): bool
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->punsubscribe(...\func_get_args());
    }
    public function ssubscribe($channels, $callback): bool
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->ssubscribe(...\func_get_args());
    }
    public function sunsubscribe($channels = []): bool
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->sunsubscribe(...\func_get_args());
    }
    public function touch($key_or_array, ...$more_keys): \Relay\Relay|false|int
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->touch(...\func_get_args());
    }
    public function pipeline(): \Relay\Relay|bool
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->pipeline(...\func_get_args());
    }
    public function multi($mode = 0): \Relay\Relay|bool
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->multi(...\func_get_args());
    }
    public function exec(): \Relay\Relay|array|bool
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->exec(...\func_get_args());
    }
    public function wait($replicas, $timeout): \Relay\Relay|false|int
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->wait(...\func_get_args());
    }
    public function unwatch(): \Relay\Relay|bool
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->unwatch(...\func_get_args());
    }
    public function discard(): bool
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->discard(...\func_get_args());
    }
    public function getMode($masked = \false): int
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->getMode(...\func_get_args());
    }
    public function clearBytes(): void
    {
        ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->clearBytes(...\func_get_args());
    }
    public function scan(&$iterator, $match = null, $count = 0, $type = null): array|false
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->scan($iterator, ...\array_slice(\func_get_args(), 1));
    }
    public function hscan($key, &$iterator, $match = null, $count = 0): array|false
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->hscan($key, $iterator, ...\array_slice(\func_get_args(), 2));
    }
    public function sscan($key, &$iterator, $match = null, $count = 0): array|false
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->sscan($key, $iterator, ...\array_slice(\func_get_args(), 2));
    }
    public function zscan($key, &$iterator, $match = null, $count = 0): array|false
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->zscan($key, $iterator, ...\array_slice(\func_get_args(), 2));
    }
    public function keys($pattern): \Relay\Relay|array|false
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->keys(...\func_get_args());
    }
    public function slowlog($operation, ...$extra_args): \Relay\Relay|array|bool|int
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->slowlog(...\func_get_args());
    }
    public function smembers($set): \Relay\Relay|array|false
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->smembers(...\func_get_args());
    }
    public function sismember($set, $member): \Relay\Relay|bool
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->sismember(...\func_get_args());
    }
    public function smismember($set, ...$members): \Relay\Relay|array|false
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->smismember(...\func_get_args());
    }
    public function srem($set, $member, ...$members): \Relay\Relay|false|int
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->srem(...\func_get_args());
    }
    public function sadd($set, $member, ...$members): \Relay\Relay|false|int
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->sadd(...\func_get_args());
    }
    public function sort($key, $options = []): \Relay\Relay|array|false|int
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->sort(...\func_get_args());
    }
    public function sort_ro($key, $options = []): \Relay\Relay|array|false
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->sort_ro(...\func_get_args());
    }
    public function smove($srcset, $dstset, $member): \Relay\Relay|bool
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->smove(...\func_get_args());
    }
    public function spop($set, $count = 1): mixed
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->spop(...\func_get_args());
    }
    public function srandmember($set, $count = 1): mixed
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->srandmember(...\func_get_args());
    }
    public function scard($key): \Relay\Relay|false|int
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->scard(...\func_get_args());
    }
    public function script($command, ...$args): mixed
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->script(...\func_get_args());
    }
    public function strlen($key): \Relay\Relay|false|int
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->strlen(...\func_get_args());
    }
    public function hlen($key): \Relay\Relay|false|int
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->hlen(...\func_get_args());
    }
    public function llen($key): \Relay\Relay|false|int
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->llen(...\func_get_args());
    }
    public function xack($key, $group, $ids): \Relay\Relay|false|int
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->xack(...\func_get_args());
    }
    public function xclaim($key, $group, $consumer, $min_idle, $ids, $options): \Relay\Relay|array|bool
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->xclaim(...\func_get_args());
    }
    public function xautoclaim($key, $group, $consumer, $min_idle, $start, $count = -1, $justid = \false): \Relay\Relay|array|bool
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->xautoclaim(...\func_get_args());
    }
    public function xlen($key): \Relay\Relay|false|int
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->xlen(...\func_get_args());
    }
    public function xgroup($operation, $key = null, $group = null, $id_or_consumer = null, $mkstream = \false, $entries_read = -2): mixed
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->xgroup(...\func_get_args());
    }
    public function xdel($key, $ids): \Relay\Relay|false|int
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->xdel(...\func_get_args());
    }
    public function xinfo($operation, $arg1 = null, $arg2 = null, $count = -1): mixed
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->xinfo(...\func_get_args());
    }
    public function xpending($key, $group, $start = null, $end = null, $count = -1, $consumer = null, $idle = 0): \Relay\Relay|array|false
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->xpending(...\func_get_args());
    }
    public function xrange($key, $start, $end, $count = -1): \Relay\Relay|array|false
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->xrange(...\func_get_args());
    }
    public function xrevrange($key, $end, $start, $count = -1): \Relay\Relay|array|bool
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->xrevrange(...\func_get_args());
    }
    public function xread($streams, $count = -1, $block = -1): \Relay\Relay|array|bool|null
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->xread(...\func_get_args());
    }
    public function xreadgroup($group, $consumer, $streams, $count = 1, $block = 1): \Relay\Relay|array|bool|null
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->xreadgroup(...\func_get_args());
    }
    public function xtrim($key, $threshold, $approx = \false, $minid = \false, $limit = -1): \Relay\Relay|false|int
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->xtrim(...\func_get_args());
    }
    public function zadd($key, ...$args): mixed
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->zadd(...\func_get_args());
    }
    public function zrandmember($key, $options = null): mixed
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->zrandmember(...\func_get_args());
    }
    public function zrange($key, $start, $end, $options = null): \Relay\Relay|array|false
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->zrange(...\func_get_args());
    }
    public function zrevrange($key, $start, $end, $options = null): \Relay\Relay|array|false
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->zrevrange(...\func_get_args());
    }
    public function zrangebyscore($key, $start, $end, $options = null): \Relay\Relay|array|false
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->zrangebyscore(...\func_get_args());
    }
    public function zrevrangebyscore($key, $start, $end, $options = null): \Relay\Relay|array|false
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->zrevrangebyscore(...\func_get_args());
    }
    public function zrangestore($dst, $src, $start, $end, $options = null): \Relay\Relay|false|int
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->zrangestore(...\func_get_args());
    }
    public function zrangebylex($key, $min, $max, $offset = -1, $count = -1): \Relay\Relay|array|false
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->zrangebylex(...\func_get_args());
    }
    public function zrevrangebylex($key, $max, $min, $offset = -1, $count = -1): \Relay\Relay|array|false
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->zrevrangebylex(...\func_get_args());
    }
    public function zrem($key, ...$args): \Relay\Relay|false|int
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->zrem(...\func_get_args());
    }
    public function zremrangebylex($key, $min, $max): \Relay\Relay|false|int
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->zremrangebylex(...\func_get_args());
    }
    public function zremrangebyrank($key, $start, $end): \Relay\Relay|false|int
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->zremrangebyrank(...\func_get_args());
    }
    public function zremrangebyscore($key, $min, $max): \Relay\Relay|false|int
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->zremrangebyscore(...\func_get_args());
    }
    public function zcard($key): \Relay\Relay|false|int
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->zcard(...\func_get_args());
    }
    public function zcount($key, $min, $max): \Relay\Relay|false|int
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->zcount(...\func_get_args());
    }
    public function zdiff($keys, $options = null): \Relay\Relay|array|false
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->zdiff(...\func_get_args());
    }
    public function zdiffstore($dst, $keys): \Relay\Relay|false|int
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->zdiffstore(...\func_get_args());
    }
    public function zincrby($key, $score, $mem): \Relay\Relay|false|float
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->zincrby(...\func_get_args());
    }
    public function zlexcount($key, $min, $max): \Relay\Relay|false|int
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->zlexcount(...\func_get_args());
    }
    public function zmscore($key, ...$mems): \Relay\Relay|array|false
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->zmscore(...\func_get_args());
    }
    public function zinter($keys, $weights = null, $options = null): \Relay\Relay|array|false
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->zinter(...\func_get_args());
    }
    public function zintercard($keys, $limit = -1): \Relay\Relay|false|int
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->zintercard(...\func_get_args());
    }
    public function zinterstore($dst, $keys, $weights = null, $options = null): \Relay\Relay|false|int
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->zinterstore(...\func_get_args());
    }
    public function zunion($keys, $weights = null, $options = null): \Relay\Relay|array|false
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->zunion(...\func_get_args());
    }
    public function zunionstore($dst, $keys, $weights = null, $options = null): \Relay\Relay|false|int
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->zunionstore(...\func_get_args());
    }
    public function zpopmin($key, $count = 1): \Relay\Relay|array|false
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->zpopmin(...\func_get_args());
    }
    public function zpopmax($key, $count = 1): \Relay\Relay|array|false
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->zpopmax(...\func_get_args());
    }
    public function _getKeys()
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->_getKeys(...\func_get_args());
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Cache\Traits;

if (version_compare(phpversion('redis'), '6.2.0', '>=')) {
    /**
     * @internal
     */
    trait Redis62ProxyTrait
    {
        public function expiremember($key, $field, $ttl, $unit = null): \Redis|false|int
        {
            return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->expiremember(...\func_get_args());
        }
        public function expirememberat($key, $field, $timestamp): \Redis|false|int
        {
            return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->expirememberat(...\func_get_args());
        }
        public function getWithMeta($key): \Redis|array|false
        {
            return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->getWithMeta(...\func_get_args());
        }
        public function serverName(): false|string
        {
            return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->serverName(...\func_get_args());
        }
        public function serverVersion(): false|string
        {
            return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->serverVersion(...\func_get_args());
        }
    }
} else {
    /**
     * @internal
     */
    trait Redis62ProxyTrait
    {
    }
}
<?php

namespace _ContaoManager;

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
/**
 * A short namespace-less class to serialize items with metadata.
 *
 * @author Nicolas Grekas <p@tchwork.com>
 *
 * @internal
 */
class 
{
    private const EXPIRY_OFFSET = 1648206727;
    private const INT32_MAX = 2147483647;
    public readonly mixed $value;
    public readonly array $metadata;
    public function __construct(mixed $value, array $metadata)
    {
        $this->value = $value;
        $this->metadata = $metadata;
    }
    public function __serialize(): array
    {
        // pack 31-bits ctime into 14bits
        $c = $this->metadata['ctime'] ?? 0;
        $c = match (\true) {
            $c > self::INT32_MAX - 2 => self::INT32_MAX,
            $c > 0 => 1 + $c,
            default => 1,
        };
        $e = 0;
        while (!(0x40000000 & $c)) {
            $c <<= 1;
            ++$e;
        }
        $c = 0x7fe0 & $c >> 16 | $e;
        $pack = \pack('Vn', (int) (0.1 + ($this->metadata['expiry'] ?: self::INT32_MAX + self::EXPIRY_OFFSET) - self::EXPIRY_OFFSET), $c);
        if (isset($this->metadata['tags'])) {
            $pack[4] = $pack[4] | "\x80";
        }
        return [$pack => $this->value] + ($this->metadata['tags'] ?? []);
    }
    public function __unserialize(array $data): void
    {
        $pack = \array_key_first($data);
        $this->value = $data[$pack];
        if ($hasTags = "\x80" === ($pack[4] & "\x80")) {
            unset($data[$pack]);
            $pack[4] = $pack[4] & "";
        }
        $metadata = \unpack('Vexpiry/nctime', $pack);
        $metadata['expiry'] += self::EXPIRY_OFFSET;
        if (!$metadata['ctime'] = ((0x4000 | $metadata['ctime']) << 16 >> (0x1f & $metadata['ctime'])) - 1) {
            unset($metadata['ctime']);
        }
        if ($hasTags) {
            $metadata['tags'] = $data;
        }
        $this->metadata = $metadata;
    }
}
/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
/**
 * A short namespace-less class to serialize items with metadata.
 *
 * @author Nicolas Grekas <p@tchwork.com>
 *
 * @internal
 */
\class_alias('_ContaoManager\', '', \false);
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Cache\Traits;

use _ContaoManager\Symfony\Component\VarExporter\LazyObjectInterface;
use _ContaoManager\Symfony\Component\VarExporter\LazyProxyTrait;
use _ContaoManager\Symfony\Contracts\Service\ResetInterface;
// Help opcache.preload discover always-needed symbols
class_exists(\_ContaoManager\Symfony\Component\VarExporter\Internal\Hydrator::class);
class_exists(\_ContaoManager\Symfony\Component\VarExporter\Internal\LazyObjectRegistry::class);
class_exists(\_ContaoManager\Symfony\Component\VarExporter\Internal\LazyObjectState::class);
/**
 * @internal
 */
class RedisCluster5Proxy extends \RedisCluster implements ResetInterface, LazyObjectInterface
{
    use LazyProxyTrait {
        resetLazyObject as reset;
    }
    private const LAZY_OBJECT_PROPERTY_SCOPES = [];
    public function __construct(
        $name,
        $seeds = null,
        $timeout = null,
        $read_timeout = null,
        $persistent = null,
        #[\SensitiveParameter]
        $auth = null
    )
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->__construct(...\func_get_args());
    }
    public function _masters()
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->_masters(...\func_get_args());
    }
    public function _prefix($key)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->_prefix(...\func_get_args());
    }
    public function _redir()
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->_redir(...\func_get_args());
    }
    public function _serialize($value)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->_serialize(...\func_get_args());
    }
    public function _unserialize($value)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->_unserialize(...\func_get_args());
    }
    public function _compress($value)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->_compress(...\func_get_args());
    }
    public function _uncompress($value)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->_uncompress(...\func_get_args());
    }
    public function _pack($value)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->_pack(...\func_get_args());
    }
    public function _unpack($value)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->_unpack(...\func_get_args());
    }
    public function acl($key_or_address, $subcmd, ...$args)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->acl(...\func_get_args());
    }
    public function append($key, $value)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->append(...\func_get_args());
    }
    public function bgrewriteaof($key_or_address)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->bgrewriteaof(...\func_get_args());
    }
    public function bgsave($key_or_address)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->bgsave(...\func_get_args());
    }
    public function bitcount($key)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->bitcount(...\func_get_args());
    }
    public function bitop($operation, $ret_key, $key, ...$other_keys)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->bitop(...\func_get_args());
    }
    public function bitpos($key, $bit, $start = null, $end = null)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->bitpos(...\func_get_args());
    }
    public function blpop($key, $timeout_or_key, ...$extra_args)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->blpop(...\func_get_args());
    }
    public function brpop($key, $timeout_or_key, ...$extra_args)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->brpop(...\func_get_args());
    }
    public function brpoplpush($src, $dst, $timeout)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->brpoplpush(...\func_get_args());
    }
    public function clearlasterror()
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->clearlasterror(...\func_get_args());
    }
    public function bzpopmax($key, $timeout_or_key, ...$extra_args)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->bzpopmax(...\func_get_args());
    }
    public function bzpopmin($key, $timeout_or_key, ...$extra_args)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->bzpopmin(...\func_get_args());
    }
    public function client($key_or_address, $arg = null, ...$other_args)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->client(...\func_get_args());
    }
    public function close()
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->close(...\func_get_args());
    }
    public function cluster($key_or_address, $arg = null, ...$other_args)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->cluster(...\func_get_args());
    }
    public function command(...$args)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->command(...\func_get_args());
    }
    public function config($key_or_address, $arg = null, ...$other_args)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->config(...\func_get_args());
    }
    public function dbsize($key_or_address)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->dbsize(...\func_get_args());
    }
    public function decr($key)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->decr(...\func_get_args());
    }
    public function decrby($key, $value)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->decrby(...\func_get_args());
    }
    public function del($key, ...$other_keys)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->del(...\func_get_args());
    }
    public function discard()
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->discard(...\func_get_args());
    }
    public function dump($key)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->dump(...\func_get_args());
    }
    public function echo($msg)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->echo(...\func_get_args());
    }
    public function eval($script, $args = null, $num_keys = null)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->eval(...\func_get_args());
    }
    public function evalsha($script_sha, $args = null, $num_keys = null)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->evalsha(...\func_get_args());
    }
    public function exec()
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->exec(...\func_get_args());
    }
    public function exists($key)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->exists(...\func_get_args());
    }
    public function expire($key, $timeout)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->expire(...\func_get_args());
    }
    public function expireat($key, $timestamp)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->expireat(...\func_get_args());
    }
    public function flushall($key_or_address, $async = null)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->flushall(...\func_get_args());
    }
    public function flushdb($key_or_address, $async = null)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->flushdb(...\func_get_args());
    }
    public function geoadd($key, $lng, $lat, $member, ...$other_triples)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->geoadd(...\func_get_args());
    }
    public function geodist($key, $src, $dst, $unit = null)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->geodist(...\func_get_args());
    }
    public function geohash($key, $member, ...$other_members)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->geohash(...\func_get_args());
    }
    public function geopos($key, $member, ...$other_members)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->geopos(...\func_get_args());
    }
    public function georadius($key, $lng, $lan, $radius, $unit, $opts = null)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->georadius(...\func_get_args());
    }
    public function georadius_ro($key, $lng, $lan, $radius, $unit, $opts = null)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->georadius_ro(...\func_get_args());
    }
    public function georadiusbymember($key, $member, $radius, $unit, $opts = null)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->georadiusbymember(...\func_get_args());
    }
    public function georadiusbymember_ro($key, $member, $radius, $unit, $opts = null)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->georadiusbymember_ro(...\func_get_args());
    }
    public function get($key)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->get(...\func_get_args());
    }
    public function getbit($key, $offset)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->getbit(...\func_get_args());
    }
    public function getlasterror()
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->getlasterror(...\func_get_args());
    }
    public function getmode()
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->getmode(...\func_get_args());
    }
    public function getoption($option)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->getoption(...\func_get_args());
    }
    public function getrange($key, $start, $end)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->getrange(...\func_get_args());
    }
    public function getset($key, $value)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->getset(...\func_get_args());
    }
    public function hdel($key, $member, ...$other_members)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->hdel(...\func_get_args());
    }
    public function hexists($key, $member)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->hexists(...\func_get_args());
    }
    public function hget($key, $member)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->hget(...\func_get_args());
    }
    public function hgetall($key)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->hgetall(...\func_get_args());
    }
    public function hincrby($key, $member, $value)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->hincrby(...\func_get_args());
    }
    public function hincrbyfloat($key, $member, $value)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->hincrbyfloat(...\func_get_args());
    }
    public function hkeys($key)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->hkeys(...\func_get_args());
    }
    public function hlen($key)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->hlen(...\func_get_args());
    }
    public function hmget($key, $keys)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->hmget(...\func_get_args());
    }
    public function hmset($key, $pairs)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->hmset(...\func_get_args());
    }
    public function hscan($str_key, &$i_iterator, $str_pattern = null, $i_count = null)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->hscan($str_key, $i_iterator, ...\array_slice(\func_get_args(), 2));
    }
    public function hset($key, $member, $value)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->hset(...\func_get_args());
    }
    public function hsetnx($key, $member, $value)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->hsetnx(...\func_get_args());
    }
    public function hstrlen($key, $member)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->hstrlen(...\func_get_args());
    }
    public function hvals($key)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->hvals(...\func_get_args());
    }
    public function incr($key)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->incr(...\func_get_args());
    }
    public function incrby($key, $value)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->incrby(...\func_get_args());
    }
    public function incrbyfloat($key, $value)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->incrbyfloat(...\func_get_args());
    }
    public function info($key_or_address, $option = null)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->info(...\func_get_args());
    }
    public function keys($pattern)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->keys(...\func_get_args());
    }
    public function lastsave($key_or_address)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->lastsave(...\func_get_args());
    }
    public function lget($key, $index)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->lget(...\func_get_args());
    }
    public function lindex($key, $index)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->lindex(...\func_get_args());
    }
    public function linsert($key, $position, $pivot, $value)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->linsert(...\func_get_args());
    }
    public function llen($key)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->llen(...\func_get_args());
    }
    public function lpop($key)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->lpop(...\func_get_args());
    }
    public function lpush($key, $value)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->lpush(...\func_get_args());
    }
    public function lpushx($key, $value)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->lpushx(...\func_get_args());
    }
    public function lrange($key, $start, $end)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->lrange(...\func_get_args());
    }
    public function lrem($key, $value)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->lrem(...\func_get_args());
    }
    public function lset($key, $index, $value)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->lset(...\func_get_args());
    }
    public function ltrim($key, $start, $stop)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->ltrim(...\func_get_args());
    }
    public function mget($keys)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->mget(...\func_get_args());
    }
    public function mset($pairs)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->mset(...\func_get_args());
    }
    public function msetnx($pairs)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->msetnx(...\func_get_args());
    }
    public function multi()
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->multi(...\func_get_args());
    }
    public function object($field, $key)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->object(...\func_get_args());
    }
    public function persist($key)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->persist(...\func_get_args());
    }
    public function pexpire($key, $timestamp)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->pexpire(...\func_get_args());
    }
    public function pexpireat($key, $timestamp)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->pexpireat(...\func_get_args());
    }
    public function pfadd($key, $elements)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->pfadd(...\func_get_args());
    }
    public function pfcount($key)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->pfcount(...\func_get_args());
    }
    public function pfmerge($dstkey, $keys)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->pfmerge(...\func_get_args());
    }
    public function ping($key_or_address)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->ping(...\func_get_args());
    }
    public function psetex($key, $expire, $value)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->psetex(...\func_get_args());
    }
    public function psubscribe($patterns, $callback)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->psubscribe(...\func_get_args());
    }
    public function pttl($key)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->pttl(...\func_get_args());
    }
    public function publish($channel, $message)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->publish(...\func_get_args());
    }
    public function pubsub($key_or_address, $arg = null, ...$other_args)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->pubsub(...\func_get_args());
    }
    public function punsubscribe($pattern, ...$other_patterns)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->punsubscribe(...\func_get_args());
    }
    public function randomkey($key_or_address)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->randomkey(...\func_get_args());
    }
    public function rawcommand($cmd, ...$args)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->rawcommand(...\func_get_args());
    }
    public function rename($key, $newkey)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->rename(...\func_get_args());
    }
    public function renamenx($key, $newkey)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->renamenx(...\func_get_args());
    }
    public function restore($ttl, $key, $value)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->restore(...\func_get_args());
    }
    public function role()
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->role(...\func_get_args());
    }
    public function rpop($key)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->rpop(...\func_get_args());
    }
    public function rpoplpush($src, $dst)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->rpoplpush(...\func_get_args());
    }
    public function rpush($key, $value)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->rpush(...\func_get_args());
    }
    public function rpushx($key, $value)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->rpushx(...\func_get_args());
    }
    public function sadd($key, $value)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->sadd(...\func_get_args());
    }
    public function saddarray($key, $options)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->saddarray(...\func_get_args());
    }
    public function save($key_or_address)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->save(...\func_get_args());
    }
    public function scan(&$i_iterator, $str_node, $str_pattern = null, $i_count = null)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->scan($i_iterator, ...\array_slice(\func_get_args(), 1));
    }
    public function scard($key)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->scard(...\func_get_args());
    }
    public function script($key_or_address, $arg = null, ...$other_args)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->script(...\func_get_args());
    }
    public function sdiff($key, ...$other_keys)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->sdiff(...\func_get_args());
    }
    public function sdiffstore($dst, $key, ...$other_keys)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->sdiffstore(...\func_get_args());
    }
    public function set($key, $value, $opts = null)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->set(...\func_get_args());
    }
    public function setbit($key, $offset, $value)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->setbit(...\func_get_args());
    }
    public function setex($key, $expire, $value)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->setex(...\func_get_args());
    }
    public function setnx($key, $value)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->setnx(...\func_get_args());
    }
    public function setoption($option, $value)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->setoption(...\func_get_args());
    }
    public function setrange($key, $offset, $value)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->setrange(...\func_get_args());
    }
    public function sinter($key, ...$other_keys)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->sinter(...\func_get_args());
    }
    public function sinterstore($dst, $key, ...$other_keys)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->sinterstore(...\func_get_args());
    }
    public function sismember($key, $value)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->sismember(...\func_get_args());
    }
    public function slowlog($key_or_address, $arg = null, ...$other_args)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->slowlog(...\func_get_args());
    }
    public function smembers($key)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->smembers(...\func_get_args());
    }
    public function smove($src, $dst, $value)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->smove(...\func_get_args());
    }
    public function sort($key, $options = null)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->sort(...\func_get_args());
    }
    public function spop($key)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->spop(...\func_get_args());
    }
    public function srandmember($key, $count = null)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->srandmember(...\func_get_args());
    }
    public function srem($key, $value)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->srem(...\func_get_args());
    }
    public function sscan($str_key, &$i_iterator, $str_pattern = null, $i_count = null)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->sscan($str_key, $i_iterator, ...\array_slice(\func_get_args(), 2));
    }
    public function strlen($key)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->strlen(...\func_get_args());
    }
    public function subscribe($channels, $callback)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->subscribe(...\func_get_args());
    }
    public function sunion($key, ...$other_keys)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->sunion(...\func_get_args());
    }
    public function sunionstore($dst, $key, ...$other_keys)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->sunionstore(...\func_get_args());
    }
    public function time()
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->time(...\func_get_args());
    }
    public function ttl($key)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->ttl(...\func_get_args());
    }
    public function type($key)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->type(...\func_get_args());
    }
    public function unsubscribe($channel, ...$other_channels)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->unsubscribe(...\func_get_args());
    }
    public function unlink($key, ...$other_keys)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->unlink(...\func_get_args());
    }
    public function unwatch()
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->unwatch(...\func_get_args());
    }
    public function watch($key, ...$other_keys)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->watch(...\func_get_args());
    }
    public function xack($str_key, $str_group, $arr_ids)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->xack(...\func_get_args());
    }
    public function xadd($str_key, $str_id, $arr_fields, $i_maxlen = null, $boo_approximate = null)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->xadd(...\func_get_args());
    }
    public function xclaim($str_key, $str_group, $str_consumer, $i_min_idle, $arr_ids, $arr_opts = null)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->xclaim(...\func_get_args());
    }
    public function xdel($str_key, $arr_ids)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->xdel(...\func_get_args());
    }
    public function xgroup($str_operation, $str_key = null, $str_arg1 = null, $str_arg2 = null, $str_arg3 = null)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->xgroup(...\func_get_args());
    }
    public function xinfo($str_cmd, $str_key = null, $str_group = null)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->xinfo(...\func_get_args());
    }
    public function xlen($key)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->xlen(...\func_get_args());
    }
    public function xpending($str_key, $str_group, $str_start = null, $str_end = null, $i_count = null, $str_consumer = null)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->xpending(...\func_get_args());
    }
    public function xrange($str_key, $str_start, $str_end, $i_count = null)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->xrange(...\func_get_args());
    }
    public function xread($arr_streams, $i_count = null, $i_block = null)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->xread(...\func_get_args());
    }
    public function xreadgroup($str_group, $str_consumer, $arr_streams, $i_count = null, $i_block = null)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->xreadgroup(...\func_get_args());
    }
    public function xrevrange($str_key, $str_start, $str_end, $i_count = null)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->xrevrange(...\func_get_args());
    }
    public function xtrim($str_key, $i_maxlen, $boo_approximate = null)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->xtrim(...\func_get_args());
    }
    public function zadd($key, $score, $value, ...$extra_args)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->zadd(...\func_get_args());
    }
    public function zcard($key)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->zcard(...\func_get_args());
    }
    public function zcount($key, $min, $max)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->zcount(...\func_get_args());
    }
    public function zincrby($key, $value, $member)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->zincrby(...\func_get_args());
    }
    public function zinterstore($key, $keys, $weights = null, $aggregate = null)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->zinterstore(...\func_get_args());
    }
    public function zlexcount($key, $min, $max)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->zlexcount(...\func_get_args());
    }
    public function zpopmax($key)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->zpopmax(...\func_get_args());
    }
    public function zpopmin($key)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->zpopmin(...\func_get_args());
    }
    public function zrange($key, $start, $end, $scores = null)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->zrange(...\func_get_args());
    }
    public function zrangebylex($key, $min, $max, $offset = null, $limit = null)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->zrangebylex(...\func_get_args());
    }
    public function zrangebyscore($key, $start, $end, $options = null)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->zrangebyscore(...\func_get_args());
    }
    public function zrank($key, $member)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->zrank(...\func_get_args());
    }
    public function zrem($key, $member, ...$other_members)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->zrem(...\func_get_args());
    }
    public function zremrangebylex($key, $min, $max)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->zremrangebylex(...\func_get_args());
    }
    public function zremrangebyrank($key, $min, $max)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->zremrangebyrank(...\func_get_args());
    }
    public function zremrangebyscore($key, $min, $max)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->zremrangebyscore(...\func_get_args());
    }
    public function zrevrange($key, $start, $end, $scores = null)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->zrevrange(...\func_get_args());
    }
    public function zrevrangebylex($key, $min, $max, $offset = null, $limit = null)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->zrevrangebylex(...\func_get_args());
    }
    public function zrevrangebyscore($key, $start, $end, $options = null)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->zrevrangebyscore(...\func_get_args());
    }
    public function zrevrank($key, $member)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->zrevrank(...\func_get_args());
    }
    public function zscan($str_key, &$i_iterator, $str_pattern = null, $i_count = null)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->zscan($str_key, $i_iterator, ...\array_slice(\func_get_args(), 2));
    }
    public function zscore($key, $member)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->zscore(...\func_get_args());
    }
    public function zunionstore($key, $keys, $weights = null, $aggregate = null)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->zunionstore(...\func_get_args());
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Cache\Traits;

use _ContaoManager\Symfony\Component\Cache\Exception\CacheException;
use _ContaoManager\Symfony\Component\Cache\Marshaller\MarshallerInterface;
/**
 * @author Nicolas Grekas <p@tchwork.com>
 * @author Rob Frawley 2nd <rmf@src.run>
 *
 * @internal
 */
trait FilesystemTrait
{
    use FilesystemCommonTrait;
    private MarshallerInterface $marshaller;
    public function prune(): bool
    {
        $time = time();
        $pruned = \true;
        foreach ($this->scanHashDir($this->directory) as $file) {
            if (!$h = @fopen($file, 'r')) {
                continue;
            }
            if (($expiresAt = (int) fgets($h)) && $time >= $expiresAt) {
                fclose($h);
                $pruned = (@unlink($file) || !file_exists($file)) && $pruned;
            } else {
                fclose($h);
            }
        }
        return $pruned;
    }
    protected function doFetch(array $ids): iterable
    {
        $values = [];
        $now = time();
        foreach ($ids as $id) {
            $file = $this->getFile($id);
            if (!is_file($file) || !$h = @fopen($file, 'r')) {
                continue;
            }
            if (($expiresAt = (int) fgets($h)) && $now >= $expiresAt) {
                fclose($h);
                @unlink($file);
            } else {
                $i = rawurldecode(rtrim(fgets($h)));
                $value = stream_get_contents($h);
                fclose($h);
                if ($i === $id) {
                    $values[$id] = $this->marshaller->unmarshall($value);
                }
            }
        }
        return $values;
    }
    protected function doHave(string $id): bool
    {
        $file = $this->getFile($id);
        return is_file($file) && (@filemtime($file) > time() || $this->doFetch([$id]));
    }
    protected function doSave(array $values, int $lifetime): array|bool
    {
        $expiresAt = $lifetime ? time() + $lifetime : 0;
        $values = $this->marshaller->marshall($values, $failed);
        foreach ($values as $id => $value) {
            if (!$this->write($this->getFile($id, \true), $expiresAt . "\n" . rawurlencode($id) . "\n" . $value, $expiresAt)) {
                $failed[] = $id;
            }
        }
        if ($failed && !is_writable($this->directory)) {
            throw new CacheException(\sprintf('Cache directory is not writable (%s).', $this->directory));
        }
        return $failed;
    }
    private function getFileKey(string $file): string
    {
        if (!$h = @fopen($file, 'r')) {
            return '';
        }
        fgets($h);
        // expiry
        $encodedKey = fgets($h);
        fclose($h);
        return rawurldecode(rtrim($encodedKey));
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Cache\Traits;

use _ContaoManager\Symfony\Component\VarExporter\LazyObjectInterface;
use _ContaoManager\Symfony\Component\VarExporter\LazyProxyTrait;
use _ContaoManager\Symfony\Contracts\Service\ResetInterface;
// Help opcache.preload discover always-needed symbols
class_exists(\_ContaoManager\Symfony\Component\VarExporter\Internal\Hydrator::class);
class_exists(\_ContaoManager\Symfony\Component\VarExporter\Internal\LazyObjectRegistry::class);
class_exists(\_ContaoManager\Symfony\Component\VarExporter\Internal\LazyObjectState::class);
/**
 * @internal
 */
class Redis6Proxy extends \Redis implements ResetInterface, LazyObjectInterface
{
    use Redis61ProxyTrait;
    use Redis62ProxyTrait;
    use Redis63ProxyTrait;
    use LazyProxyTrait {
        resetLazyObject as reset;
    }
    private const LAZY_OBJECT_PROPERTY_SCOPES = [];
    public function __construct($options = null)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->__construct(...\func_get_args());
    }
    public function _compress($value): string
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->_compress(...\func_get_args());
    }
    public function _uncompress($value): string
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->_uncompress(...\func_get_args());
    }
    public function _prefix($key): string
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->_prefix(...\func_get_args());
    }
    public function _serialize($value): string
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->_serialize(...\func_get_args());
    }
    public function _unserialize($value): mixed
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->_unserialize(...\func_get_args());
    }
    public function _pack($value): string
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->_pack(...\func_get_args());
    }
    public function _unpack($value): mixed
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->_unpack(...\func_get_args());
    }
    public function acl($subcmd, ...$args): mixed
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->acl(...\func_get_args());
    }
    public function append($key, $value): \Redis|false|int
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->append(...\func_get_args());
    }
    public function auth(
        #[\SensitiveParameter]
        $credentials
    ): \Redis|bool
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->auth(...\func_get_args());
    }
    public function bgSave(): \Redis|bool
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->bgSave(...\func_get_args());
    }
    public function bgrewriteaof(): \Redis|bool
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->bgrewriteaof(...\func_get_args());
    }
    public function bitcount($key, $start = 0, $end = -1, $bybit = \false): \Redis|false|int
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->bitcount(...\func_get_args());
    }
    public function bitop($operation, $deskey, $srckey, ...$other_keys): \Redis|false|int
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->bitop(...\func_get_args());
    }
    public function bitpos($key, $bit, $start = 0, $end = -1, $bybit = \false): \Redis|false|int
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->bitpos(...\func_get_args());
    }
    public function blPop($key_or_keys, $timeout_or_key, ...$extra_args): \Redis|array|false|null
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->blPop(...\func_get_args());
    }
    public function brPop($key_or_keys, $timeout_or_key, ...$extra_args): \Redis|array|false|null
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->brPop(...\func_get_args());
    }
    public function brpoplpush($src, $dst, $timeout): \Redis|false|string
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->brpoplpush(...\func_get_args());
    }
    public function bzPopMax($key, $timeout_or_key, ...$extra_args): \Redis|array|false
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->bzPopMax(...\func_get_args());
    }
    public function bzPopMin($key, $timeout_or_key, ...$extra_args): \Redis|array|false
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->bzPopMin(...\func_get_args());
    }
    public function bzmpop($timeout, $keys, $from, $count = 1): \Redis|array|false|null
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->bzmpop(...\func_get_args());
    }
    public function zmpop($keys, $from, $count = 1): \Redis|array|false|null
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->zmpop(...\func_get_args());
    }
    public function blmpop($timeout, $keys, $from, $count = 1): \Redis|array|false|null
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->blmpop(...\func_get_args());
    }
    public function lmpop($keys, $from, $count = 1): \Redis|array|false|null
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->lmpop(...\func_get_args());
    }
    public function clearLastError(): bool
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->clearLastError(...\func_get_args());
    }
    public function client($opt, ...$args): mixed
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->client(...\func_get_args());
    }
    public function close(): bool
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->close(...\func_get_args());
    }
    public function command($opt = null, ...$args): mixed
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->command(...\func_get_args());
    }
    public function config($operation, $key_or_settings = null, $value = null): mixed
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->config(...\func_get_args());
    }
    public function connect($host, $port = 6379, $timeout = 0, $persistent_id = null, $retry_interval = 0, $read_timeout = 0, $context = null): bool
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->connect(...\func_get_args());
    }
    public function copy($src, $dst, $options = null): \Redis|bool
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->copy(...\func_get_args());
    }
    public function dbSize(): \Redis|false|int
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->dbSize(...\func_get_args());
    }
    public function debug($key): \Redis|string
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->debug(...\func_get_args());
    }
    public function decr($key, $by = 1): \Redis|false|int
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->decr(...\func_get_args());
    }
    public function decrBy($key, $value): \Redis|false|int
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->decrBy(...\func_get_args());
    }
    public function del($key, ...$other_keys): \Redis|false|int
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->del(...\func_get_args());
    }
    public function delete($key, ...$other_keys): \Redis|false|int
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->delete(...\func_get_args());
    }
    public function discard(): \Redis|bool
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->discard(...\func_get_args());
    }
    public function echo($str): \Redis|false|string
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->echo(...\func_get_args());
    }
    public function eval($script, $args = [], $num_keys = 0): mixed
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->eval(...\func_get_args());
    }
    public function eval_ro($script_sha, $args = [], $num_keys = 0): mixed
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->eval_ro(...\func_get_args());
    }
    public function evalsha($sha1, $args = [], $num_keys = 0): mixed
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->evalsha(...\func_get_args());
    }
    public function evalsha_ro($sha1, $args = [], $num_keys = 0): mixed
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->evalsha_ro(...\func_get_args());
    }
    public function exec(): \Redis|array|false
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->exec(...\func_get_args());
    }
    public function exists($key, ...$other_keys): \Redis|bool|int
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->exists(...\func_get_args());
    }
    public function expire($key, $timeout, $mode = null): \Redis|bool
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->expire(...\func_get_args());
    }
    public function expireAt($key, $timestamp, $mode = null): \Redis|bool
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->expireAt(...\func_get_args());
    }
    public function failover($to = null, $abort = \false, $timeout = 0): \Redis|bool
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->failover(...\func_get_args());
    }
    public function expiretime($key): \Redis|false|int
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->expiretime(...\func_get_args());
    }
    public function pexpiretime($key): \Redis|false|int
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->pexpiretime(...\func_get_args());
    }
    public function fcall($fn, $keys = [], $args = []): mixed
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->fcall(...\func_get_args());
    }
    public function fcall_ro($fn, $keys = [], $args = []): mixed
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->fcall_ro(...\func_get_args());
    }
    public function flushAll($sync = null): \Redis|bool
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->flushAll(...\func_get_args());
    }
    public function flushDB($sync = null): \Redis|bool
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->flushDB(...\func_get_args());
    }
    public function function($operation, ...$args): \Redis|array|bool|string
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->function(...\func_get_args());
    }
    public function geoadd($key, $lng, $lat, $member, ...$other_triples_and_options): \Redis|false|int
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->geoadd(...\func_get_args());
    }
    public function geodist($key, $src, $dst, $unit = null): \Redis|false|float
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->geodist(...\func_get_args());
    }
    public function geohash($key, $member, ...$other_members): \Redis|array|false
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->geohash(...\func_get_args());
    }
    public function geopos($key, $member, ...$other_members): \Redis|array|false
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->geopos(...\func_get_args());
    }
    public function georadius($key, $lng, $lat, $radius, $unit, $options = []): mixed
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->georadius(...\func_get_args());
    }
    public function georadius_ro($key, $lng, $lat, $radius, $unit, $options = []): mixed
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->georadius_ro(...\func_get_args());
    }
    public function georadiusbymember($key, $member, $radius, $unit, $options = []): mixed
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->georadiusbymember(...\func_get_args());
    }
    public function georadiusbymember_ro($key, $member, $radius, $unit, $options = []): mixed
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->georadiusbymember_ro(...\func_get_args());
    }
    public function geosearch($key, $position, $shape, $unit, $options = []): array
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->geosearch(...\func_get_args());
    }
    public function geosearchstore($dst, $src, $position, $shape, $unit, $options = []): \Redis|array|false|int
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->geosearchstore(...\func_get_args());
    }
    public function get($key): mixed
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->get(...\func_get_args());
    }
    public function getAuth(): mixed
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->getAuth(...\func_get_args());
    }
    public function getBit($key, $idx): \Redis|false|int
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->getBit(...\func_get_args());
    }
    public function getEx($key, $options = []): \Redis|bool|string
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->getEx(...\func_get_args());
    }
    public function getDBNum(): int
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->getDBNum(...\func_get_args());
    }
    public function getDel($key): \Redis|bool|string
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->getDel(...\func_get_args());
    }
    public function getHost(): string
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->getHost(...\func_get_args());
    }
    public function getLastError(): ?string
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->getLastError(...\func_get_args());
    }
    public function getMode(): int
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->getMode(...\func_get_args());
    }
    public function getOption($option): mixed
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->getOption(...\func_get_args());
    }
    public function getPersistentID(): ?string
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->getPersistentID(...\func_get_args());
    }
    public function getPort(): int
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->getPort(...\func_get_args());
    }
    public function getRange($key, $start, $end): \Redis|false|string
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->getRange(...\func_get_args());
    }
    public function lcs($key1, $key2, $options = null): \Redis|array|false|int|string
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->lcs(...\func_get_args());
    }
    public function getReadTimeout(): float
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->getReadTimeout(...\func_get_args());
    }
    public function getset($key, $value): \Redis|false|string
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->getset(...\func_get_args());
    }
    public function getTimeout(): false|float
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->getTimeout(...\func_get_args());
    }
    public function getTransferredBytes(): array
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->getTransferredBytes(...\func_get_args());
    }
    public function clearTransferredBytes(): void
    {
        ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->clearTransferredBytes(...\func_get_args());
    }
    public function hDel($key, $field, ...$other_fields): \Redis|false|int
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->hDel(...\func_get_args());
    }
    public function hExists($key, $field): \Redis|bool
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->hExists(...\func_get_args());
    }
    public function hGet($key, $member): mixed
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->hGet(...\func_get_args());
    }
    public function hGetAll($key): \Redis|array|false
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->hGetAll(...\func_get_args());
    }
    public function hIncrBy($key, $field, $value): \Redis|false|int
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->hIncrBy(...\func_get_args());
    }
    public function hIncrByFloat($key, $field, $value): \Redis|false|float
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->hIncrByFloat(...\func_get_args());
    }
    public function hKeys($key): \Redis|array|false
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->hKeys(...\func_get_args());
    }
    public function hLen($key): \Redis|false|int
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->hLen(...\func_get_args());
    }
    public function hMget($key, $fields): \Redis|array|false
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->hMget(...\func_get_args());
    }
    public function hMset($key, $fieldvals): \Redis|bool
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->hMset(...\func_get_args());
    }
    public function hSetNx($key, $field, $value): \Redis|bool
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->hSetNx(...\func_get_args());
    }
    public function hStrLen($key, $field): \Redis|false|int
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->hStrLen(...\func_get_args());
    }
    public function hVals($key): \Redis|array|false
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->hVals(...\func_get_args());
    }
    public function hscan($key, &$iterator, $pattern = null, $count = 0): \Redis|array|bool
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->hscan($key, $iterator, ...\array_slice(\func_get_args(), 2));
    }
    public function incr($key, $by = 1): \Redis|false|int
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->incr(...\func_get_args());
    }
    public function incrBy($key, $value): \Redis|false|int
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->incrBy(...\func_get_args());
    }
    public function incrByFloat($key, $value): \Redis|false|float
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->incrByFloat(...\func_get_args());
    }
    public function info(...$sections): \Redis|array|false
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->info(...\func_get_args());
    }
    public function isConnected(): bool
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->isConnected(...\func_get_args());
    }
    public function keys($pattern)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->keys(...\func_get_args());
    }
    public function lInsert($key, $pos, $pivot, $value)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->lInsert(...\func_get_args());
    }
    public function lLen($key): \Redis|false|int
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->lLen(...\func_get_args());
    }
    public function lMove($src, $dst, $wherefrom, $whereto): \Redis|false|string
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->lMove(...\func_get_args());
    }
    public function blmove($src, $dst, $wherefrom, $whereto, $timeout): \Redis|false|string
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->blmove(...\func_get_args());
    }
    public function lPop($key, $count = 0): \Redis|array|bool|string
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->lPop(...\func_get_args());
    }
    public function lPos($key, $value, $options = null): \Redis|array|bool|int|null
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->lPos(...\func_get_args());
    }
    public function lPush($key, ...$elements): \Redis|false|int
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->lPush(...\func_get_args());
    }
    public function rPush($key, ...$elements): \Redis|false|int
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->rPush(...\func_get_args());
    }
    public function lPushx($key, $value): \Redis|false|int
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->lPushx(...\func_get_args());
    }
    public function rPushx($key, $value): \Redis|false|int
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->rPushx(...\func_get_args());
    }
    public function lSet($key, $index, $value): \Redis|bool
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->lSet(...\func_get_args());
    }
    public function lastSave(): int
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->lastSave(...\func_get_args());
    }
    public function lindex($key, $index): mixed
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->lindex(...\func_get_args());
    }
    public function lrange($key, $start, $end): \Redis|array|false
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->lrange(...\func_get_args());
    }
    public function lrem($key, $value, $count = 0): \Redis|false|int
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->lrem(...\func_get_args());
    }
    public function ltrim($key, $start, $end): \Redis|bool
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->ltrim(...\func_get_args());
    }
    public function migrate(
        $host,
        $port,
        $key,
        $dstdb,
        $timeout,
        $copy = \false,
        $replace = \false,
        #[\SensitiveParameter]
        $credentials = null
    ): \Redis|bool
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->migrate(...\func_get_args());
    }
    public function move($key, $index): \Redis|bool
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->move(...\func_get_args());
    }
    public function mset($key_values): \Redis|bool
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->mset(...\func_get_args());
    }
    public function msetnx($key_values): \Redis|bool
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->msetnx(...\func_get_args());
    }
    public function multi($value = \Redis::MULTI): \Redis|bool
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->multi(...\func_get_args());
    }
    public function object($subcommand, $key): \Redis|false|int|string
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->object(...\func_get_args());
    }
    public function open($host, $port = 6379, $timeout = 0, $persistent_id = null, $retry_interval = 0, $read_timeout = 0, $context = null): bool
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->open(...\func_get_args());
    }
    public function pconnect($host, $port = 6379, $timeout = 0, $persistent_id = null, $retry_interval = 0, $read_timeout = 0, $context = null): bool
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->pconnect(...\func_get_args());
    }
    public function persist($key): \Redis|bool
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->persist(...\func_get_args());
    }
    public function pexpire($key, $timeout, $mode = null): bool
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->pexpire(...\func_get_args());
    }
    public function pexpireAt($key, $timestamp, $mode = null): \Redis|bool
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->pexpireAt(...\func_get_args());
    }
    public function pfadd($key, $elements): \Redis|int
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->pfadd(...\func_get_args());
    }
    public function pfcount($key_or_keys): \Redis|false|int
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->pfcount(...\func_get_args());
    }
    public function pfmerge($dst, $srckeys): \Redis|bool
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->pfmerge(...\func_get_args());
    }
    public function ping($message = null): \Redis|bool|string
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->ping(...\func_get_args());
    }
    public function pipeline(): \Redis|bool
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->pipeline(...\func_get_args());
    }
    public function popen($host, $port = 6379, $timeout = 0, $persistent_id = null, $retry_interval = 0, $read_timeout = 0, $context = null): bool
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->popen(...\func_get_args());
    }
    public function psetex($key, $expire, $value): \Redis|bool
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->psetex(...\func_get_args());
    }
    public function psubscribe($patterns, $cb): bool
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->psubscribe(...\func_get_args());
    }
    public function pttl($key): \Redis|false|int
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->pttl(...\func_get_args());
    }
    public function publish($channel, $message): \Redis|false|int
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->publish(...\func_get_args());
    }
    public function pubsub($command, $arg = null): mixed
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->pubsub(...\func_get_args());
    }
    public function punsubscribe($patterns): \Redis|array|bool
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->punsubscribe(...\func_get_args());
    }
    public function rPop($key, $count = 0): \Redis|array|bool|string
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->rPop(...\func_get_args());
    }
    public function randomKey(): \Redis|false|string
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->randomKey(...\func_get_args());
    }
    public function rawcommand($command, ...$args): mixed
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->rawcommand(...\func_get_args());
    }
    public function rename($old_name, $new_name): \Redis|bool
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->rename(...\func_get_args());
    }
    public function renameNx($key_src, $key_dst): \Redis|bool
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->renameNx(...\func_get_args());
    }
    public function restore($key, $ttl, $value, $options = null): \Redis|bool
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->restore(...\func_get_args());
    }
    public function role(): mixed
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->role(...\func_get_args());
    }
    public function rpoplpush($srckey, $dstkey): \Redis|false|string
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->rpoplpush(...\func_get_args());
    }
    public function sAdd($key, $value, ...$other_values): \Redis|false|int
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->sAdd(...\func_get_args());
    }
    public function sAddArray($key, $values): int
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->sAddArray(...\func_get_args());
    }
    public function sDiff($key, ...$other_keys): \Redis|array|false
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->sDiff(...\func_get_args());
    }
    public function sDiffStore($dst, $key, ...$other_keys): \Redis|false|int
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->sDiffStore(...\func_get_args());
    }
    public function sInter($key, ...$other_keys): \Redis|array|false
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->sInter(...\func_get_args());
    }
    public function sintercard($keys, $limit = -1): \Redis|false|int
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->sintercard(...\func_get_args());
    }
    public function sInterStore($key, ...$other_keys): \Redis|false|int
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->sInterStore(...\func_get_args());
    }
    public function sMembers($key): \Redis|array|false
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->sMembers(...\func_get_args());
    }
    public function sMisMember($key, $member, ...$other_members): \Redis|array|false
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->sMisMember(...\func_get_args());
    }
    public function sMove($src, $dst, $value): \Redis|bool
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->sMove(...\func_get_args());
    }
    public function sPop($key, $count = 0): \Redis|array|false|string
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->sPop(...\func_get_args());
    }
    public function sUnion($key, ...$other_keys): \Redis|array|false
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->sUnion(...\func_get_args());
    }
    public function sUnionStore($dst, $key, ...$other_keys): \Redis|false|int
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->sUnionStore(...\func_get_args());
    }
    public function save(): \Redis|bool
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->save(...\func_get_args());
    }
    public function scan(&$iterator, $pattern = null, $count = 0, $type = null): array|false
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->scan($iterator, ...\array_slice(\func_get_args(), 1));
    }
    public function scard($key): \Redis|false|int
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->scard(...\func_get_args());
    }
    public function script($command, ...$args): mixed
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->script(...\func_get_args());
    }
    public function select($db): \Redis|bool
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->select(...\func_get_args());
    }
    public function set($key, $value, $options = null): \Redis|bool|string
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->set(...\func_get_args());
    }
    public function setBit($key, $idx, $value): \Redis|false|int
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->setBit(...\func_get_args());
    }
    public function setRange($key, $index, $value): \Redis|false|int
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->setRange(...\func_get_args());
    }
    public function setOption($option, $value): bool
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->setOption(...\func_get_args());
    }
    public function setex($key, $expire, $value)
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->setex(...\func_get_args());
    }
    public function setnx($key, $value): \Redis|bool
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->setnx(...\func_get_args());
    }
    public function sismember($key, $value): \Redis|bool
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->sismember(...\func_get_args());
    }
    public function slaveof($host = null, $port = 6379): \Redis|bool
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->slaveof(...\func_get_args());
    }
    public function replicaof($host = null, $port = 6379): \Redis|bool
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->replicaof(...\func_get_args());
    }
    public function touch($key_or_array, ...$more_keys): \Redis|false|int
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->touch(...\func_get_args());
    }
    public function slowlog($operation, $length = 0): mixed
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->slowlog(...\func_get_args());
    }
    public function sort($key, $options = null): mixed
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->sort(...\func_get_args());
    }
    public function sort_ro($key, $options = null): mixed
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->sort_ro(...\func_get_args());
    }
    public function sortAsc($key, $pattern = null, $get = null, $offset = -1, $count = -1, $store = null): array
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->sortAsc(...\func_get_args());
    }
    public function sortAscAlpha($key, $pattern = null, $get = null, $offset = -1, $count = -1, $store = null): array
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->sortAscAlpha(...\func_get_args());
    }
    public function sortDesc($key, $pattern = null, $get = null, $offset = -1, $count = -1, $store = null): array
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->sortDesc(...\func_get_args());
    }
    public function sortDescAlpha($key, $pattern = null, $get = null, $offset = -1, $count = -1, $store = null): array
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->sortDescAlpha(...\func_get_args());
    }
    public function srem($key, $value, ...$other_values): \Redis|false|int
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->srem(...\func_get_args());
    }
    public function sscan($key, &$iterator, $pattern = null, $count = 0): array|false
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->sscan($key, $iterator, ...\array_slice(\func_get_args(), 2));
    }
    public function ssubscribe($channels, $cb): bool
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->ssubscribe(...\func_get_args());
    }
    public function strlen($key): \Redis|false|int
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->strlen(...\func_get_args());
    }
    public function subscribe($channels, $cb): bool
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->subscribe(...\func_get_args());
    }
    public function sunsubscribe($channels): \Redis|array|bool
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->sunsubscribe(...\func_get_args());
    }
    public function swapdb($src, $dst): \Redis|bool
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->swapdb(...\func_get_args());
    }
    public function time(): \Redis|array
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->time(...\func_get_args());
    }
    public function ttl($key): \Redis|false|int
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->ttl(...\func_get_args());
    }
    public function type($key): \Redis|false|int
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->type(...\func_get_args());
    }
    public function unlink($key, ...$other_keys): \Redis|false|int
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->unlink(...\func_get_args());
    }
    public function unsubscribe($channels): \Redis|array|bool
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->unsubscribe(...\func_get_args());
    }
    public function unwatch(): \Redis|bool
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->unwatch(...\func_get_args());
    }
    public function watch($key, ...$other_keys): \Redis|bool
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->watch(...\func_get_args());
    }
    public function wait($numreplicas, $timeout): false|int
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->wait(...\func_get_args());
    }
    public function xack($key, $group, $ids): false|int
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->xack(...\func_get_args());
    }
    public function xadd($key, $id, $values, $maxlen = 0, $approx = \false, $nomkstream = \false): \Redis|false|string
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->xadd(...\func_get_args());
    }
    public function xautoclaim($key, $group, $consumer, $min_idle, $start, $count = -1, $justid = \false): \Redis|array|bool
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->xautoclaim(...\func_get_args());
    }
    public function xclaim($key, $group, $consumer, $min_idle, $ids, $options): \Redis|array|bool
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->xclaim(...\func_get_args());
    }
    public function xdel($key, $ids): \Redis|false|int
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->xdel(...\func_get_args());
    }
    public function xgroup($operation, $key = null, $group = null, $id_or_consumer = null, $mkstream = \false, $entries_read = -2): mixed
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->xgroup(...\func_get_args());
    }
    public function xinfo($operation, $arg1 = null, $arg2 = null, $count = -1): mixed
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->xinfo(...\func_get_args());
    }
    public function xlen($key): \Redis|false|int
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->xlen(...\func_get_args());
    }
    public function xpending($key, $group, $start = null, $end = null, $count = -1, $consumer = null): \Redis|array|false
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->xpending(...\func_get_args());
    }
    public function xrange($key, $start, $end, $count = -1): \Redis|array|bool
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->xrange(...\func_get_args());
    }
    public function xread($streams, $count = -1, $block = -1): \Redis|array|bool
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->xread(...\func_get_args());
    }
    public function xreadgroup($group, $consumer, $streams, $count = 1, $block = 1): \Redis|array|bool
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->xreadgroup(...\func_get_args());
    }
    public function xrevrange($key, $end, $start, $count = -1): \Redis|array|bool
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->xrevrange(...\func_get_args());
    }
    public function xtrim($key, $threshold, $approx = \false, $minid = \false, $limit = -1): \Redis|false|int
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->xtrim(...\func_get_args());
    }
    public function zAdd($key, $score_or_options, ...$more_scores_and_mems): \Redis|false|float|int
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->zAdd(...\func_get_args());
    }
    public function zCard($key): \Redis|false|int
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->zCard(...\func_get_args());
    }
    public function zCount($key, $start, $end): \Redis|false|int
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->zCount(...\func_get_args());
    }
    public function zIncrBy($key, $value, $member): \Redis|false|float
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->zIncrBy(...\func_get_args());
    }
    public function zLexCount($key, $min, $max): \Redis|false|int
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->zLexCount(...\func_get_args());
    }
    public function zMscore($key, $member, ...$other_members): \Redis|array|false
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->zMscore(...\func_get_args());
    }
    public function zPopMax($key, $count = null): \Redis|array|false
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->zPopMax(...\func_get_args());
    }
    public function zPopMin($key, $count = null): \Redis|array|false
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->zPopMin(...\func_get_args());
    }
    public function zRange($key, $start, $end, $options = null): \Redis|array|false
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->zRange(...\func_get_args());
    }
    public function zRangeByLex($key, $min, $max, $offset = -1, $count = -1): \Redis|array|false
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->zRangeByLex(...\func_get_args());
    }
    public function zRangeByScore($key, $start, $end, $options = []): \Redis|array|false
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->zRangeByScore(...\func_get_args());
    }
    public function zrangestore($dstkey, $srckey, $start, $end, $options = null): \Redis|false|int
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->zrangestore(...\func_get_args());
    }
    public function zRandMember($key, $options = null): \Redis|array|string
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->zRandMember(...\func_get_args());
    }
    public function zRank($key, $member): \Redis|false|int
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->zRank(...\func_get_args());
    }
    public function zRem($key, $member, ...$other_members): \Redis|false|int
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->zRem(...\func_get_args());
    }
    public function zRemRangeByLex($key, $min, $max): \Redis|false|int
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->zRemRangeByLex(...\func_get_args());
    }
    public function zRemRangeByRank($key, $start, $end): \Redis|false|int
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->zRemRangeByRank(...\func_get_args());
    }
    public function zRemRangeByScore($key, $start, $end): \Redis|false|int
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->zRemRangeByScore(...\func_get_args());
    }
    public function zRevRange($key, $start, $end, $scores = null): \Redis|array|false
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->zRevRange(...\func_get_args());
    }
    public function zRevRangeByLex($key, $max, $min, $offset = -1, $count = -1): \Redis|array|false
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->zRevRangeByLex(...\func_get_args());
    }
    public function zRevRangeByScore($key, $max, $min, $options = []): \Redis|array|false
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->zRevRangeByScore(...\func_get_args());
    }
    public function zRevRank($key, $member): \Redis|false|int
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->zRevRank(...\func_get_args());
    }
    public function zScore($key, $member): \Redis|false|float
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->zScore(...\func_get_args());
    }
    public function zdiff($keys, $options = null): \Redis|array|false
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->zdiff(...\func_get_args());
    }
    public function zdiffstore($dst, $keys): \Redis|false|int
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->zdiffstore(...\func_get_args());
    }
    public function zinter($keys, $weights = null, $options = null): \Redis|array|false
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->zinter(...\func_get_args());
    }
    public function zintercard($keys, $limit = -1): \Redis|false|int
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->zintercard(...\func_get_args());
    }
    public function zinterstore($dst, $keys, $weights = null, $aggregate = null): \Redis|false|int
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->zinterstore(...\func_get_args());
    }
    public function zscan($key, &$iterator, $pattern = null, $count = 0): \Redis|array|false
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->zscan($key, $iterator, ...\array_slice(\func_get_args(), 2));
    }
    public function zunion($keys, $weights = null, $options = null): \Redis|array|false
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->zunion(...\func_get_args());
    }
    public function zunionstore($dst, $keys, $weights = null, $aggregate = null): \Redis|false|int
    {
        return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->zunionstore(...\func_get_args());
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Cache\Traits;

if (version_compare(phpversion('redis'), '6.1.0-dev', '>=')) {
    /**
     * @internal
     */
    trait Redis61ProxyTrait
    {
        public function dump($key): \Redis|string|false
        {
            return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->dump(...\func_get_args());
        }
        public function hRandField($key, $options = null): \Redis|array|string|false
        {
            return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->hRandField(...\func_get_args());
        }
        public function hSet($key, ...$fields_and_vals): \Redis|false|int
        {
            return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->hSet(...\func_get_args());
        }
        public function mget($keys): \Redis|array|false
        {
            return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->mget(...\func_get_args());
        }
        public function sRandMember($key, $count = 0): mixed
        {
            return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->sRandMember(...\func_get_args());
        }
        public function waitaof($numlocal, $numreplicas, $timeout): \Redis|array|false
        {
            return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->waitaof(...\func_get_args());
        }
    }
} else {
    /**
     * @internal
     */
    trait Redis61ProxyTrait
    {
        public function dump($key): \Redis|string
        {
            return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->dump(...\func_get_args());
        }
        public function hRandField($key, $options = null): \Redis|array|string
        {
            return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->hRandField(...\func_get_args());
        }
        public function hSet($key, $member, $value): \Redis|false|int
        {
            return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->hSet(...\func_get_args());
        }
        public function mget($keys): \Redis|array
        {
            return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->mget(...\func_get_args());
        }
        public function sRandMember($key, $count = 0): \Redis|array|false|string
        {
            return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->sRandMember(...\func_get_args());
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Cache\Traits;

if (version_compare(phpversion('redis'), '6.3.0', '>=')) {
    /**
     * @internal
     */
    trait RedisCluster63ProxyTrait
    {
        public function delifeq($key, $value): \RedisCluster|int|false
        {
            return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->delifeq(...\func_get_args());
        }
        public function hexpire($key, $ttl, $fields, $mode = null): \RedisCluster|array|false
        {
            return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->hexpire(...\func_get_args());
        }
        public function hexpireat($key, $time, $fields, $mode = null): \RedisCluster|array|false
        {
            return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->hexpireat(...\func_get_args());
        }
        public function hexpiretime($key, $fields): \RedisCluster|array|false
        {
            return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->hexpiretime(...\func_get_args());
        }
        public function hgetdel($key, $fields): \RedisCluster|array|false
        {
            return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->hgetdel(...\func_get_args());
        }
        public function hgetex($key, $fields, $expiry = null): \RedisCluster|array|false
        {
            return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->hgetex(...\func_get_args());
        }
        public function hgetWithMeta($key, $member): mixed
        {
            return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->hgetWithMeta(...\func_get_args());
        }
        public function hpersist($key, $fields): \RedisCluster|array|false
        {
            return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->hpersist(...\func_get_args());
        }
        public function hpexpire($key, $ttl, $fields, $mode = null): \RedisCluster|array|false
        {
            return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->hpexpire(...\func_get_args());
        }
        public function hpexpireat($key, $mstime, $fields, $mode = null): \RedisCluster|array|false
        {
            return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->hpexpireat(...\func_get_args());
        }
        public function hpexpiretime($key, $fields): \RedisCluster|array|false
        {
            return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->hpexpiretime(...\func_get_args());
        }
        public function hpttl($key, $fields): \RedisCluster|array|false
        {
            return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->hpttl(...\func_get_args());
        }
        public function hsetex($key, $fields, $expiry = null): \RedisCluster|int|false
        {
            return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->hsetex(...\func_get_args());
        }
        public function httl($key, $fields): \RedisCluster|array|false
        {
            return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->httl(...\func_get_args());
        }
        public function vadd($key, $values, $element, $options = null): \RedisCluster|int|false
        {
            return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->vadd(...\func_get_args());
        }
        public function vcard($key): \RedisCluster|int|false
        {
            return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->vcard(...\func_get_args());
        }
        public function vdim($key): \RedisCluster|int|false
        {
            return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->vdim(...\func_get_args());
        }
        public function vemb($key, $member, $raw = \false): \RedisCluster|array|false
        {
            return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->vemb(...\func_get_args());
        }
        public function vgetattr($key, $member, $decode = \true): \RedisCluster|array|string|false
        {
            return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->vgetattr(...\func_get_args());
        }
        public function vinfo($key): \RedisCluster|array|false
        {
            return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->vinfo(...\func_get_args());
        }
        public function vismember($key, $member): \RedisCluster|bool
        {
            return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->vismember(...\func_get_args());
        }
        public function vlinks($key, $member, $withscores = \false): \RedisCluster|array|false
        {
            return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->vlinks(...\func_get_args());
        }
        public function vrandmember($key, $count = 0): \RedisCluster|array|string|false
        {
            return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->vrandmember(...\func_get_args());
        }
        public function vrange($key, $min, $max, $count = -1): \RedisCluster|array|false
        {
            return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->vrange(...\func_get_args());
        }
        public function vrem($key, $member): \RedisCluster|int|false
        {
            return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->vrem(...\func_get_args());
        }
        public function vsetattr($key, $member, $attributes): \RedisCluster|int|false
        {
            return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->vsetattr(...\func_get_args());
        }
        public function vsim($key, $member, $options = null): \RedisCluster|array|false
        {
            return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->vsim(...\func_get_args());
        }
    }
} else {
    /**
     * @internal
     */
    trait RedisCluster63ProxyTrait
    {
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Cache\Traits\Relay;

if (version_compare(phpversion('relay'), '0.9.0', '>=')) {
    /**
     * @internal
     */
    trait GeosearchTrait
    {
        public function geosearch($key, $position, $shape, $unit, $options = []): \Relay\Relay|array|false
        {
            return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->geosearch(...\func_get_args());
        }
    }
} else {
    /**
     * @internal
     */
    trait GeosearchTrait
    {
        public function geosearch($key, $position, $shape, $unit, $options = []): \Relay\Relay|array
        {
            return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->geosearch(...\func_get_args());
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Cache\Traits\Relay;

if (version_compare(phpversion('relay'), '0.9.0', '>=')) {
    /**
     * @internal
     */
    trait MoveTrait
    {
        public function blmove($srckey, $dstkey, $srcpos, $dstpos, $timeout): mixed
        {
            return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->blmove(...\func_get_args());
        }
        public function lmove($srckey, $dstkey, $srcpos, $dstpos): mixed
        {
            return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->lmove(...\func_get_args());
        }
    }
} else {
    /**
     * @internal
     */
    trait MoveTrait
    {
        public function blmove($srckey, $dstkey, $srcpos, $dstpos, $timeout): \Relay\Relay|false|string|null
        {
            return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->blmove(...\func_get_args());
        }
        public function lmove($srckey, $dstkey, $srcpos, $dstpos): \Relay\Relay|false|string|null
        {
            return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->lmove(...\func_get_args());
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Cache\Traits\Relay;

if (version_compare(phpversion('relay'), '0.12.0', '>=')) {
    /**
     * @internal
     */
    trait Relay12Trait
    {
        public function delifeq($key, $value): \Relay\Relay|false|int
        {
            return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->delifeq(...\func_get_args());
        }
        public function vadd($key, $values, $element, $options = null): \Relay\Relay|false|int
        {
            return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->vadd(...\func_get_args());
        }
        public function vcard($key): \Relay\Relay|false|int
        {
            return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->vcard(...\func_get_args());
        }
        public function vdim($key): \Relay\Relay|false|int
        {
            return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->vdim(...\func_get_args());
        }
        public function vemb($key, $element, $raw = \false): \Relay\Relay|array|false
        {
            return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->vemb(...\func_get_args());
        }
        public function vgetattr($key, $element, $raw = \false): \Relay\Relay|array|false|string
        {
            return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->vgetattr(...\func_get_args());
        }
        public function vinfo($key): \Relay\Relay|array|false
        {
            return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->vinfo(...\func_get_args());
        }
        public function vismember($key, $element): \Relay\Relay|bool
        {
            return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->vismember(...\func_get_args());
        }
        public function vlinks($key, $element, $withscores): \Relay\Relay|array|false
        {
            return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->vlinks(...\func_get_args());
        }
        public function vrandmember($key, $count = 0): \Relay\Relay|array|false|string
        {
            return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->vrandmember(...\func_get_args());
        }
        public function vrange($key, $min, $max, $count = -1): \Relay\Relay|array|false
        {
            return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->vrange(...\func_get_args());
        }
        public function vrem($key, $element): \Relay\Relay|false|int
        {
            return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->vrem(...\func_get_args());
        }
        public function vsetattr($key, $element, $attributes): \Relay\Relay|false|int
        {
            return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->vsetattr(...\func_get_args());
        }
        public function vsim($key, $member, $options = null): \Relay\Relay|array|false
        {
            return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->vsim(...\func_get_args());
        }
        public function xdelex($key, $ids, $mode = null): \Relay\Relay|array|false
        {
            return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->xdelex(...\func_get_args());
        }
        public function xackdel($key, $group, $ids, $mode = null): \Relay\Relay|array|false
        {
            return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->xackdel(...\func_get_args());
        }
    }
} else {
    /**
     * @internal
     */
    trait Relay12Trait
    {
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Cache\Traits\Relay;

if (version_compare(phpversion('relay'), '0.9.0', '>=')) {
    /**
     * @internal
     */
    trait PfcountTrait
    {
        public function pfcount($key_or_keys): \Relay\Relay|false|int
        {
            return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->pfcount(...\func_get_args());
        }
    }
} else {
    /**
     * @internal
     */
    trait PfcountTrait
    {
        public function pfcount($key): \Relay\Relay|false|int
        {
            return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->pfcount(...\func_get_args());
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Cache\Traits\Relay;

if (version_compare(phpversion('relay'), '0.12.1', '>=')) {
    /**
     * @internal
     */
    trait Relay121Trait
    {
        public function hgetWithMeta($hash, $member): \Relay\Relay|array|false
        {
            return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->hgetWithMeta(...\func_get_args());
        }
        public function select($db): \Relay\Relay|bool|string
        {
            return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->select(...\func_get_args());
        }
        public function watch($key, ...$other_keys): \Relay\Relay|bool|string
        {
            return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->watch(...\func_get_args());
        }
    }
} else {
    /**
     * @internal
     */
    trait Relay121Trait
    {
        public function select($db): \Relay\Relay|bool
        {
            return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->select(...\func_get_args());
        }
        public function watch($key, ...$other_keys): \Relay\Relay|bool
        {
            return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->watch(...\func_get_args());
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Cache\Traits\Relay;

if (version_compare(phpversion('relay'), '0.21.0', '>=')) {
    /**
     * @internal
     */
    trait Relay21Trait
    {
        public function gcra($key, $maxBurst, $requestsPerPeriod, $period, $numRequests = 0): \Relay\Relay|array|false
        {
            return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->gcra(...\func_get_args());
        }
        public function hotkeys($subcmd, $args = null): \Relay\Relay|array|bool
        {
            return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->hotkeys(...\func_get_args());
        }
    }
} else {
    /**
     * @internal
     */
    trait Relay21Trait
    {
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Cache\Traits\Relay;

if (version_compare(phpversion('relay'), '0.20.0', '>=')) {
    /**
     * @internal
     */
    trait Relay20Trait
    {
        public function _digest($value): string
        {
            return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->_digest(...\func_get_args());
        }
        public function delex($key, $options = null): \Relay\Relay|false|int
        {
            return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->delex(...\func_get_args());
        }
        public function digest($key): \Relay\Relay|false|null|string
        {
            return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->digest(...\func_get_args());
        }
        public function msetex($kvals, $ttl = null): \Relay\Relay|false|int
        {
            return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->msetx(...\func_get_args());
        }
    }
} else {
    /**
     * @internal
     */
    trait Relay20Trait
    {
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Cache\Traits\Relay;

if (version_compare(phpversion('relay'), '0.8.1', '>=')) {
    /**
     * @internal
     */
    trait CopyTrait
    {
        public function copy($src, $dst, $options = null): \Relay\Relay|bool
        {
            return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->copy(...\func_get_args());
        }
    }
} else {
    /**
     * @internal
     */
    trait CopyTrait
    {
        public function copy($src, $dst, $options = null): \Relay\Relay|false|int
        {
            return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->copy(...\func_get_args());
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Cache\Traits\Relay;

if (version_compare(phpversion('relay'), '0.9.0', '>=')) {
    /**
     * @internal
     */
    trait NullableReturnTrait
    {
        public function dump($key): \Relay\Relay|false|string|null
        {
            return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->dump(...\func_get_args());
        }
        public function geodist($key, $src, $dst, $unit = null): \Relay\Relay|false|float|null
        {
            return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->geodist(...\func_get_args());
        }
        public function hrandfield($hash, $options = null): \Relay\Relay|array|false|string|null
        {
            return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->hrandfield(...\func_get_args());
        }
        public function xadd($key, $id, $values, $maxlen = 0, $approx = \false, $nomkstream = \false): \Relay\Relay|false|string|null
        {
            return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->xadd(...\func_get_args());
        }
        public function zrank($key, $rank, $withscore = \false): \Relay\Relay|array|false|int|null
        {
            return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->zrank(...\func_get_args());
        }
        public function zrevrank($key, $rank, $withscore = \false): \Relay\Relay|array|false|int|null
        {
            return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->zrevrank(...\func_get_args());
        }
        public function zscore($key, $member): \Relay\Relay|false|float|null
        {
            return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->zscore(...\func_get_args());
        }
    }
} else {
    /**
     * @internal
     */
    trait NullableReturnTrait
    {
        public function dump($key): \Relay\Relay|false|string
        {
            return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->dump(...\func_get_args());
        }
        public function geodist($key, $src, $dst, $unit = null): \Relay\Relay|false|float
        {
            return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->geodist(...\func_get_args());
        }
        public function hrandfield($hash, $options = null): \Relay\Relay|array|false|string
        {
            return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->hrandfield(...\func_get_args());
        }
        public function xadd($key, $id, $values, $maxlen = 0, $approx = \false, $nomkstream = \false): \Relay\Relay|false|string
        {
            return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->xadd(...\func_get_args());
        }
        public function zrank($key, $rank, $withscore = \false): \Relay\Relay|array|false|int
        {
            return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->zrank(...\func_get_args());
        }
        public function zrevrank($key, $rank, $withscore = \false): \Relay\Relay|array|false|int
        {
            return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->zrevrank(...\func_get_args());
        }
        public function zscore($key, $member): \Relay\Relay|false|float
        {
            return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->zscore(...\func_get_args());
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Cache\Traits\Relay;

if (version_compare(phpversion('relay'), '0.11.0', '>=')) {
    /**
     * @internal
     */
    trait Relay11Trait
    {
        public function cmsIncrBy($key, $field, $value, ...$fields_and_falues): \Relay\Relay|array|false
        {
            return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->cmsIncrBy(...\func_get_args());
        }
        public function cmsInfo($key): \Relay\Relay|array|false
        {
            return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->cmsInfo(...\func_get_args());
        }
        public function cmsInitByDim($key, $width, $depth): \Relay\Relay|bool
        {
            return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->cmsInitByDim(...\func_get_args());
        }
        public function cmsInitByProb($key, $error, $probability): \Relay\Relay|bool
        {
            return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->cmsInitByProb(...\func_get_args());
        }
        public function cmsMerge($dstkey, $keys, $weights = []): \Relay\Relay|bool
        {
            return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->cmsMerge(...\func_get_args());
        }
        public function cmsQuery($key, ...$fields): \Relay\Relay|array|false
        {
            return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->cmsQuery(...\func_get_args());
        }
        public function commandlog($subcmd, ...$args): \Relay\Relay|array|bool|int
        {
            return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->commandlog(...\func_get_args());
        }
        public function hexpire($hash, $ttl, $fields, $mode = null): \Relay\Relay|array|false
        {
            return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->hexpire(...\func_get_args());
        }
        public function hexpireat($hash, $ttl, $fields, $mode = null): \Relay\Relay|array|false
        {
            return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->hexpireat(...\func_get_args());
        }
        public function hexpiretime($hash, $fields): \Relay\Relay|array|false
        {
            return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->hexpiretime(...\func_get_args());
        }
        public function hgetdel($key, $fields): \Relay\Relay|array|false
        {
            return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->hgetdel(...\func_get_args());
        }
        public function hgetex($hash, $fields, $expiry = null): \Relay\Relay|array|false
        {
            return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->hgetex(...\func_get_args());
        }
        public function hpersist($hash, $fields): \Relay\Relay|array|false
        {
            return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->hpersist(...\func_get_args());
        }
        public function hpexpire($hash, $ttl, $fields, $mode = null): \Relay\Relay|array|false
        {
            return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->hpexpire(...\func_get_args());
        }
        public function hpexpireat($hash, $ttl, $fields, $mode = null): \Relay\Relay|array|false
        {
            return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->hpexpireat(...\func_get_args());
        }
        public function hpexpiretime($hash, $fields): \Relay\Relay|array|false
        {
            return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->hpexpiretime(...\func_get_args());
        }
        public function hpttl($hash, $fields): \Relay\Relay|array|false
        {
            return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->hpttl(...\func_get_args());
        }
        public function hsetex($key, $fields, $expiry = null): \Relay\Relay|false|int
        {
            return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->hsetex(...\func_get_args());
        }
        public function httl($hash, $fields): \Relay\Relay|array|false
        {
            return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->httl(...\func_get_args());
        }
        public function serverName(): false|string
        {
            return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->serverName(...\func_get_args());
        }
        public function serverVersion(): false|string
        {
            return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->serverVersion(...\func_get_args());
        }
    }
} else {
    /**
     * @internal
     */
    trait Relay11Trait
    {
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Cache\Traits\Relay;

if (version_compare(phpversion('relay'), '0.9.0', '>=')) {
    /**
     * @internal
     */
    trait HsetTrait
    {
        public function hset($key, ...$keys_and_vals): \Relay\Relay|false|int
        {
            return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->hset(...\func_get_args());
        }
    }
} else {
    /**
     * @internal
     */
    trait HsetTrait
    {
        public function hset($key, $mem, $val, ...$kvals): \Relay\Relay|false|int
        {
            return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->hset(...\func_get_args());
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Cache\Traits\Relay;

if (version_compare(phpversion('relay'), '0.9.0', '>=')) {
    /**
     * @internal
     */
    trait SwapdbTrait
    {
        public function swapdb($index1, $index2): \Relay\Relay|bool
        {
            return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->swapdb(...\func_get_args());
        }
    }
} else {
    /**
     * @internal
     */
    trait SwapdbTrait
    {
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Cache\Traits\Relay;

if (version_compare(phpversion('relay'), '0.9.0', '>=')) {
    /**
     * @internal
     */
    trait GetrangeTrait
    {
        public function getrange($key, $start, $end): mixed
        {
            return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->getrange(...\func_get_args());
        }
    }
} else {
    /**
     * @internal
     */
    trait GetrangeTrait
    {
        public function getrange($key, $start, $end): \Relay\Relay|false|string
        {
            return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->getrange(...\func_get_args());
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Cache\Traits\Relay;

if (version_compare(phpversion('relay'), '0.11.1', '>=')) {
    /**
     * @internal
     */
    trait IsTrackedTrait
    {
        public function isTracked($key): bool
        {
            return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->isTracked(...\func_get_args());
        }
    }
} else {
    /**
     * @internal
     */
    trait IsTrackedTrait
    {
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Cache\Traits\Relay;

if (version_compare(phpversion('relay'), '0.9.0', '>=')) {
    /**
     * @internal
     */
    trait FtTrait
    {
        public function ftAggregate($index, $query, $options = null): \Relay\Relay|array|false
        {
            return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->ftAggregate(...\func_get_args());
        }
        public function ftAliasAdd($index, $alias): \Relay\Relay|bool
        {
            return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->ftAliasAdd(...\func_get_args());
        }
        public function ftAliasDel($alias): \Relay\Relay|bool
        {
            return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->ftAliasDel(...\func_get_args());
        }
        public function ftAliasUpdate($index, $alias): \Relay\Relay|bool
        {
            return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->ftAliasUpdate(...\func_get_args());
        }
        public function ftAlter($index, $schema, $skipinitialscan = \false): \Relay\Relay|bool
        {
            return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->ftAlter(...\func_get_args());
        }
        public function ftConfig($operation, $option, $value = null): \Relay\Relay|array|bool
        {
            return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->ftConfig(...\func_get_args());
        }
        public function ftCreate($index, $schema, $options = null): \Relay\Relay|bool
        {
            return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->ftCreate(...\func_get_args());
        }
        public function ftCursor($operation, $index, $cursor, $options = null): \Relay\Relay|array|bool
        {
            return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->ftCursor(...\func_get_args());
        }
        public function ftDictAdd($dict, $term, ...$other_terms): \Relay\Relay|false|int
        {
            return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->ftDictAdd(...\func_get_args());
        }
        public function ftDictDel($dict, $term, ...$other_terms): \Relay\Relay|false|int
        {
            return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->ftDictDel(...\func_get_args());
        }
        public function ftDictDump($dict): \Relay\Relay|array|false
        {
            return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->ftDictDump(...\func_get_args());
        }
        public function ftDropIndex($index, $dd = \false): \Relay\Relay|bool
        {
            return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->ftDropIndex(...\func_get_args());
        }
        public function ftExplain($index, $query, $dialect = 0): \Relay\Relay|false|string
        {
            return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->ftExplain(...\func_get_args());
        }
        public function ftExplainCli($index, $query, $dialect = 0): \Relay\Relay|array|false
        {
            return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->ftExplainCli(...\func_get_args());
        }
        public function ftInfo($index): \Relay\Relay|array|false
        {
            return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->ftInfo(...\func_get_args());
        }
        public function ftProfile($index, $command, $query, $limited = \false): \Relay\Relay|array|false
        {
            return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->ftProfile(...\func_get_args());
        }
        public function ftSearch($index, $query, $options = null): \Relay\Relay|array|false
        {
            return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->ftSearch(...\func_get_args());
        }
        public function ftSpellCheck($index, $query, $options = null): \Relay\Relay|array|false
        {
            return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->ftSpellCheck(...\func_get_args());
        }
        public function ftSynDump($index): \Relay\Relay|array|false
        {
            return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->ftSynDump(...\func_get_args());
        }
        public function ftSynUpdate($index, $synonym, $term_or_terms, $skipinitialscan = \false): \Relay\Relay|bool
        {
            return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->ftSynUpdate(...\func_get_args());
        }
        public function ftTagVals($index, $tag): \Relay\Relay|array|false
        {
            return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->ftTagVals(...\func_get_args());
        }
    }
} else {
    /**
     * @internal
     */
    trait FtTrait
    {
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Cache\Traits\Relay;

if (version_compare(phpversion('relay'), '0.10.1', '>=')) {
    /**
     * @internal
     */
    trait GetWithMetaTrait
    {
        public function getWithMeta($key): \Relay\Relay|array|false
        {
            return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->getWithMeta(...\func_get_args());
        }
    }
} else {
    /**
     * @internal
     */
    trait GetWithMetaTrait
    {
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Cache\Traits\Relay;

if (version_compare(phpversion('relay'), '0.11', '>=')) {
    /**
     * @internal
     */
    trait BgsaveTrait
    {
        public function bgsave($arg = null): \Relay\Relay|bool
        {
            return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->bgsave(...\func_get_args());
        }
    }
} else {
    /**
     * @internal
     */
    trait BgsaveTrait
    {
        public function bgsave($schedule = \false): \Relay\Relay|bool
        {
            return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->bgsave(...\func_get_args());
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Cache\Traits;

use _ContaoManager\Psr\Cache\CacheItemInterface;
use _ContaoManager\Psr\Log\LoggerAwareTrait;
use _ContaoManager\Symfony\Component\Cache\CacheItem;
use _ContaoManager\Symfony\Component\Cache\Exception\InvalidArgumentException;
/**
 * @author Nicolas Grekas <p@tchwork.com>
 *
 * @internal
 */
trait AbstractAdapterTrait
{
    use LoggerAwareTrait;
    /**
     * needs to be set by class, signature is function(string <key>, mixed <value>, bool <isHit>).
     */
    private static \Closure $createCacheItem;
    /**
     * needs to be set by class, signature is function(array <deferred>, string <namespace>, array <&expiredIds>).
     */
    private static \Closure $mergeByLifetime;
    private string $namespace = '';
    private int $defaultLifetime;
    private string $namespaceVersion = '';
    private bool $versioningIsEnabled = \false;
    private array $deferred = [];
    private array $ids = [];
    /**
     * @var int|null The maximum length to enforce for identifiers or null when no limit applies
     */
    protected $maxIdLength;
    /**
     * Fetches several cache items.
     *
     * @param array $ids The cache identifiers to fetch
     */
    abstract protected function doFetch(array $ids): iterable;
    /**
     * Confirms if the cache contains specified cache item.
     *
     * @param string $id The identifier for which to check existence
     */
    abstract protected function doHave(string $id): bool;
    /**
     * Deletes all items in the pool.
     *
     * @param string $namespace The prefix used for all identifiers managed by this pool
     */
    abstract protected function doClear(string $namespace): bool;
    /**
     * Removes multiple items from the pool.
     *
     * @param array $ids An array of identifiers that should be removed from the pool
     */
    abstract protected function doDelete(array $ids): bool;
    /**
     * Persists several cache items immediately.
     *
     * @param array $values   The values to cache, indexed by their cache identifier
     * @param int   $lifetime The lifetime of the cached values, 0 for persisting until manual cleaning
     *
     * @return array|bool The identifiers that failed to be cached or a boolean stating if caching succeeded or not
     */
    abstract protected function doSave(array $values, int $lifetime): array|bool;
    public function hasItem(mixed $key): bool
    {
        $id = $this->getId($key);
        if (isset($this->deferred[$key])) {
            $this->commit();
        }
        try {
            return $this->doHave($id);
        } catch (\Exception $e) {
            CacheItem::log($this->logger, 'Failed to check if key "{key}" is cached: ' . $e->getMessage(), ['key' => $key, 'exception' => $e, 'cache-adapter' => get_debug_type($this)]);
            return \false;
        }
    }
    public function clear(string $prefix = ''): bool
    {
        $this->deferred = [];
        if ($cleared = $this->versioningIsEnabled) {
            if ('' === $namespaceVersionToClear = $this->namespaceVersion) {
                foreach ($this->doFetch([static::NS_SEPARATOR . $this->namespace]) as $v) {
                    $namespaceVersionToClear = $v;
                }
            }
            $namespaceToClear = $this->namespace . $namespaceVersionToClear;
            $namespaceVersion = self::formatNamespaceVersion(mt_rand());
            try {
                $e = $this->doSave([static::NS_SEPARATOR . $this->namespace => $namespaceVersion], 0);
            } catch (\Exception $e) {
            }
            if (\true !== $e && [] !== $e) {
                $cleared = \false;
                $message = 'Failed to save the new namespace' . ($e instanceof \Exception ? ': ' . $e->getMessage() : '.');
                CacheItem::log($this->logger, $message, ['exception' => $e instanceof \Exception ? $e : null, 'cache-adapter' => get_debug_type($this)]);
            } else {
                $this->namespaceVersion = $namespaceVersion;
                $this->ids = [];
            }
        } else {
            $namespaceToClear = $this->namespace . $prefix;
        }
        try {
            return $this->doClear($namespaceToClear) || $cleared;
        } catch (\Exception $e) {
            CacheItem::log($this->logger, 'Failed to clear the cache: ' . $e->getMessage(), ['exception' => $e, 'cache-adapter' => get_debug_type($this)]);
            return \false;
        }
    }
    public function deleteItem(mixed $key): bool
    {
        return $this->deleteItems([$key]);
    }
    public function deleteItems(array $keys): bool
    {
        $ids = [];
        foreach ($keys as $key) {
            $ids[$key] = $this->getId($key);
            unset($this->deferred[$key]);
        }
        try {
            if ($this->doDelete($ids)) {
                return \true;
            }
        } catch (\Exception) {
        }
        $ok = \true;
        // When bulk-delete failed, retry each item individually
        foreach ($ids as $key => $id) {
            try {
                $e = null;
                if ($this->doDelete([$id])) {
                    continue;
                }
            } catch (\Exception $e) {
            }
            $message = 'Failed to delete key "{key}"' . ($e instanceof \Exception ? ': ' . $e->getMessage() : '.');
            CacheItem::log($this->logger, $message, ['key' => $key, 'exception' => $e, 'cache-adapter' => get_debug_type($this)]);
            $ok = \false;
        }
        return $ok;
    }
    public function getItem(mixed $key): CacheItem
    {
        $id = $this->getId($key);
        if (isset($this->deferred[$key])) {
            $this->commit();
        }
        $isHit = \false;
        $value = null;
        try {
            foreach ($this->doFetch([$id]) as $value) {
                $isHit = \true;
            }
            return (self::$createCacheItem)($key, $value, $isHit);
        } catch (\Exception $e) {
            CacheItem::log($this->logger, 'Failed to fetch key "{key}": ' . $e->getMessage(), ['key' => $key, 'exception' => $e, 'cache-adapter' => get_debug_type($this)]);
        }
        return (self::$createCacheItem)($key, null, \false);
    }
    public function getItems(array $keys = []): iterable
    {
        $ids = [];
        $commit = \false;
        foreach ($keys as $key) {
            $ids[] = $this->getId($key);
            $commit = $commit || isset($this->deferred[$key]);
        }
        if ($commit) {
            $this->commit();
        }
        try {
            $items = $this->doFetch($ids);
        } catch (\Exception $e) {
            CacheItem::log($this->logger, 'Failed to fetch items: ' . $e->getMessage(), ['keys' => $keys, 'exception' => $e, 'cache-adapter' => get_debug_type($this)]);
            $items = [];
        }
        $ids = array_combine($ids, $keys);
        return $this->generateItems($items, $ids);
    }
    public function save(CacheItemInterface $item): bool
    {
        if (!$item instanceof CacheItem) {
            return \false;
        }
        $this->deferred[$item->getKey()] = $item;
        return $this->commit();
    }
    public function saveDeferred(CacheItemInterface $item): bool
    {
        if (!$item instanceof CacheItem) {
            return \false;
        }
        $this->deferred[$item->getKey()] = $item;
        return \true;
    }
    /**
     * Enables/disables versioning of items.
     *
     * When versioning is enabled, clearing the cache is atomic and doesn't require listing existing keys to proceed,
     * but old keys may need garbage collection and extra round-trips to the back-end are required.
     *
     * Calling this method also clears the memoized namespace version and thus forces a resynchronization of it.
     *
     * @return bool the previous state of versioning
     */
    public function enableVersioning(bool $enable = \true): bool
    {
        $wasEnabled = $this->versioningIsEnabled;
        $this->versioningIsEnabled = $enable;
        $this->namespaceVersion = '';
        $this->ids = [];
        return $wasEnabled;
    }
    public function reset(): void
    {
        if ($this->deferred) {
            $this->commit();
        }
        $this->namespaceVersion = '';
        $this->ids = [];
    }
    public function __serialize(): array
    {
        throw new \BadMethodCallException('Cannot serialize ' . __CLASS__);
    }
    public function __unserialize(array $data): void
    {
        throw new \BadMethodCallException('Cannot unserialize ' . __CLASS__);
    }
    public function __destruct()
    {
        if ($this->deferred) {
            $this->commit();
        }
    }
    private function generateItems(iterable $items, array &$keys): \Generator
    {
        $f = self::$createCacheItem;
        try {
            foreach ($items as $id => $value) {
                if (!isset($keys[$id])) {
                    throw new InvalidArgumentException(\sprintf('Could not match value id "%s" to keys "%s".', $id, implode('", "', $keys)));
                }
                $key = $keys[$id];
                unset($keys[$id]);
                yield $key => $f($key, $value, \true);
            }
        } catch (\Exception $e) {
            CacheItem::log($this->logger, 'Failed to fetch items: ' . $e->getMessage(), ['keys' => array_values($keys), 'exception' => $e, 'cache-adapter' => get_debug_type($this)]);
        }
        foreach ($keys as $key) {
            yield $key => $f($key, null, \false);
        }
    }
    /**
     * @internal
     */
    protected function getId(mixed $key): string
    {
        if ($this->versioningIsEnabled && '' === $this->namespaceVersion) {
            $this->ids = [];
            $this->namespaceVersion = '1' . static::NS_SEPARATOR;
            try {
                foreach ($this->doFetch([static::NS_SEPARATOR . $this->namespace]) as $v) {
                    $this->namespaceVersion = $v;
                }
                $e = \true;
                if ('1' . static::NS_SEPARATOR === $this->namespaceVersion) {
                    $this->namespaceVersion = self::formatNamespaceVersion(time());
                    $e = $this->doSave([static::NS_SEPARATOR . $this->namespace => $this->namespaceVersion], 0);
                }
            } catch (\Exception $e) {
            }
            if (\true !== $e && [] !== $e) {
                $message = 'Failed to save the new namespace' . ($e instanceof \Exception ? ': ' . $e->getMessage() : '.');
                CacheItem::log($this->logger, $message, ['exception' => $e instanceof \Exception ? $e : null, 'cache-adapter' => get_debug_type($this)]);
            }
        }
        if (\is_string($key) && isset($this->ids[$key])) {
            return $this->namespace . $this->namespaceVersion . $this->ids[$key];
        }
        \assert('' !== CacheItem::validateKey($key));
        $this->ids[$key] = $key;
        if (\count($this->ids) > 1000) {
            $this->ids = \array_slice($this->ids, 500, null, \true);
            // stop memory leak if there are many keys
        }
        if (null === $this->maxIdLength) {
            return $this->namespace . $this->namespaceVersion . $key;
        }
        if (\strlen($id = $this->namespace . $this->namespaceVersion . $key) > $this->maxIdLength) {
            // Use xxh128 to favor speed over security, which is not an issue here
            $this->ids[$key] = $id = substr_replace(base64_encode(hash('xxh128', $key, \true)), static::NS_SEPARATOR, -(\strlen($this->namespaceVersion) + 2));
            $id = $this->namespace . $this->namespaceVersion . $id;
        }
        return $id;
    }
    /**
     * @internal
     */
    public static function handleUnserializeCallback(string $class): never
    {
        throw new \DomainException('Class not found: ' . $class);
    }
    private static function formatNamespaceVersion(int $value): string
    {
        return strtr(substr_replace(base64_encode(pack('V', $value)), static::NS_SEPARATOR, 5), '/', '_');
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Cache\Traits;

/**
 * @internal
 */
interface CachedValueInterface
{
    public function getValue(): mixed;
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Cache\Adapter;

use _ContaoManager\Psr\Cache\CacheItemInterface;
use _ContaoManager\Psr\Cache\CacheItemPoolInterface;
use _ContaoManager\Symfony\Component\Cache\CacheItem;
use _ContaoManager\Symfony\Component\Cache\PruneableInterface;
use _ContaoManager\Symfony\Component\Cache\ResettableInterface;
use _ContaoManager\Symfony\Component\Cache\Traits\ContractsTrait;
use _ContaoManager\Symfony\Component\Cache\Traits\ProxyTrait;
use _ContaoManager\Symfony\Contracts\Cache\CacheInterface;
/**
 * @author Nicolas Grekas <p@tchwork.com>
 */
class ProxyAdapter implements AdapterInterface, CacheInterface, PruneableInterface, ResettableInterface
{
    use ContractsTrait;
    use ProxyTrait;
    private string $namespace = '';
    private int $namespaceLen;
    private string $poolHash;
    private int $defaultLifetime;
    private static \Closure $createCacheItem;
    private static \Closure $setInnerItem;
    public function __construct(CacheItemPoolInterface $pool, string $namespace = '', int $defaultLifetime = 0)
    {
        $this->pool = $pool;
        $this->poolHash = spl_object_hash($pool);
        if ('' !== $namespace) {
            \assert('' !== CacheItem::validateKey($namespace));
            $this->namespace = $namespace;
        }
        $this->namespaceLen = \strlen($namespace);
        $this->defaultLifetime = $defaultLifetime;
        self::$createCacheItem ??= \Closure::bind(static function ($key, $innerItem, $poolHash) {
            $item = new CacheItem();
            $item->key = $key;
            if (null === $innerItem) {
                return $item;
            }
            $item->value = $innerItem->get();
            $item->isHit = $innerItem->isHit();
            $item->innerItem = $innerItem;
            $item->poolHash = $poolHash;
            if (!$item->unpack() && $innerItem instanceof CacheItem) {
                $item->metadata = $innerItem->metadata;
            }
            $innerItem->set(null);
            return $item;
        }, null, CacheItem::class);
        self::$setInnerItem ??= \Closure::bind(static function (CacheItemInterface $innerItem, CacheItem $item, $expiry = null) {
            $innerItem->set($item->pack());
            $innerItem->expiresAt($expiry ?? $item->expiry ? \DateTimeImmutable::createFromFormat('U.u', \sprintf('%.6F', $expiry ?? $item->expiry)) : null);
        }, null, CacheItem::class);
    }
    public function get(string $key, callable $callback, ?float $beta = null, ?array &$metadata = null): mixed
    {
        if (!$this->pool instanceof CacheInterface) {
            return $this->doGet($this, $key, $callback, $beta, $metadata);
        }
        return $this->pool->get($this->getId($key), function ($innerItem, bool &$save) use ($key, $callback) {
            $item = (self::$createCacheItem)($key, $innerItem, $this->poolHash);
            $item->set($value = $callback($item, $save));
            (self::$setInnerItem)($innerItem, $item);
            return $value;
        }, $beta, $metadata);
    }
    public function getItem(mixed $key): CacheItem
    {
        $item = $this->pool->getItem($this->getId($key));
        return (self::$createCacheItem)($key, $item, $this->poolHash);
    }
    public function getItems(array $keys = []): iterable
    {
        if ($this->namespaceLen) {
            foreach ($keys as $i => $key) {
                $keys[$i] = $this->getId($key);
            }
        }
        return $this->generateItems($this->pool->getItems($keys));
    }
    public function hasItem(mixed $key): bool
    {
        return $this->pool->hasItem($this->getId($key));
    }
    public function clear(string $prefix = ''): bool
    {
        if ($this->pool instanceof AdapterInterface) {
            return $this->pool->clear($this->namespace . $prefix);
        }
        return $this->pool->clear();
    }
    public function deleteItem(mixed $key): bool
    {
        return $this->pool->deleteItem($this->getId($key));
    }
    public function deleteItems(array $keys): bool
    {
        if ($this->namespaceLen) {
            foreach ($keys as $i => $key) {
                $keys[$i] = $this->getId($key);
            }
        }
        return $this->pool->deleteItems($keys);
    }
    public function save(CacheItemInterface $item): bool
    {
        return $this->doSave($item, __FUNCTION__);
    }
    public function saveDeferred(CacheItemInterface $item): bool
    {
        return $this->doSave($item, __FUNCTION__);
    }
    public function commit(): bool
    {
        return $this->pool->commit();
    }
    private function doSave(CacheItemInterface $item, string $method): bool
    {
        if (!$item instanceof CacheItem) {
            return \false;
        }
        $castItem = (array) $item;
        if (null === $castItem["\x00*\x00expiry"] && 0 < $this->defaultLifetime) {
            $castItem["\x00*\x00expiry"] = microtime(\true) + $this->defaultLifetime;
        }
        if ($castItem["\x00*\x00poolHash"] === $this->poolHash && $castItem["\x00*\x00innerItem"]) {
            $innerItem = $castItem["\x00*\x00innerItem"];
        } elseif ($this->pool instanceof AdapterInterface) {
            // this is an optimization specific for AdapterInterface implementations
            // so we can save a round-trip to the backend by just creating a new item
            $innerItem = (self::$createCacheItem)($this->namespace . $castItem["\x00*\x00key"], null, $this->poolHash);
        } else {
            $innerItem = $this->pool->getItem($this->namespace . $castItem["\x00*\x00key"]);
        }
        (self::$setInnerItem)($innerItem, $item, $castItem["\x00*\x00expiry"]);
        return $this->pool->{$method}($innerItem);
    }
    private function generateItems(iterable $items): \Generator
    {
        $f = self::$createCacheItem;
        foreach ($items as $key => $item) {
            if ($this->namespaceLen) {
                $key = substr($key, $this->namespaceLen);
            }
            yield $key => $f($key, $item, $this->poolHash);
        }
    }
    private function getId(mixed $key): string
    {
        \assert('' !== CacheItem::validateKey($key));
        return $this->namespace . $key;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Cache\Adapter;

use _ContaoManager\Symfony\Component\Cache\CacheItem;
use _ContaoManager\Symfony\Component\Cache\Exception\CacheException;
use _ContaoManager\Symfony\Component\Cache\Marshaller\MarshallerInterface;
/**
 * @author Nicolas Grekas <p@tchwork.com>
 */
class ApcuAdapter extends AbstractAdapter
{
    private ?MarshallerInterface $marshaller;
    /**
     * @throws CacheException if APCu is not enabled
     */
    public function __construct(string $namespace = '', int $defaultLifetime = 0, ?string $version = null, ?MarshallerInterface $marshaller = null)
    {
        if (!static::isSupported()) {
            throw new CacheException('APCu is not enabled.');
        }
        if ('cli' === \PHP_SAPI) {
            ini_set('apc.use_request_time', 0);
        }
        parent::__construct($namespace, $defaultLifetime);
        if (null !== $version) {
            CacheItem::validateKey($version);
            if (!apcu_exists($version . '@' . $namespace)) {
                $this->doClear($namespace);
                apcu_add($version . '@' . $namespace, null);
            }
        }
        $this->marshaller = $marshaller;
    }
    /**
     * @return bool
     */
    public static function isSupported()
    {
        return \function_exists('apcu_fetch') && filter_var(\ini_get('apc.enabled'), \FILTER_VALIDATE_BOOL);
    }
    protected function doFetch(array $ids): iterable
    {
        $unserializeCallbackHandler = ini_set('unserialize_callback_func', __CLASS__ . '::handleUnserializeCallback');
        try {
            $values = [];
            foreach (apcu_fetch($ids, $ok) ?: [] as $k => $v) {
                if (null !== $v || $ok) {
                    $values[$k] = null !== $this->marshaller ? $this->marshaller->unmarshall($v) : $v;
                }
            }
            return $values;
        } catch (\Error $e) {
            throw new \ErrorException($e->getMessage(), $e->getCode(), \E_ERROR, $e->getFile(), $e->getLine());
        } finally {
            ini_set('unserialize_callback_func', $unserializeCallbackHandler);
        }
    }
    protected function doHave(string $id): bool
    {
        return apcu_exists($id);
    }
    protected function doClear(string $namespace): bool
    {
        return isset($namespace[0]) && class_exists(\APCUIterator::class, \false) && ('cli' !== \PHP_SAPI || filter_var(\ini_get('apc.enable_cli'), \FILTER_VALIDATE_BOOL)) ? apcu_delete(new \APCUIterator(\sprintf('/^%s/', preg_quote($namespace, '/')), \APC_ITER_KEY)) : apcu_clear_cache();
    }
    protected function doDelete(array $ids): bool
    {
        foreach ($ids as $id) {
            apcu_delete($id);
        }
        return \true;
    }
    protected function doSave(array $values, int $lifetime): array|bool
    {
        if (null !== $this->marshaller && !$values = $this->marshaller->marshall($values, $failed)) {
            return $failed;
        }
        if (\false === $failures = apcu_store($values, null, $lifetime)) {
            $failures = $values;
        }
        return array_keys($failures);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Cache\Adapter;

use Couchbase\Bucket;
use Couchbase\Cluster;
use Couchbase\ClusterOptions;
use Couchbase\Collection;
use Couchbase\DocumentNotFoundException;
use Couchbase\UpsertOptions;
use _ContaoManager\Symfony\Component\Cache\Exception\CacheException;
use _ContaoManager\Symfony\Component\Cache\Exception\InvalidArgumentException;
use _ContaoManager\Symfony\Component\Cache\Marshaller\DefaultMarshaller;
use _ContaoManager\Symfony\Component\Cache\Marshaller\MarshallerInterface;
/**
 * @author Antonio Jose Cerezo Aranda <aj.cerezo@gmail.com>
 */
class CouchbaseCollectionAdapter extends AbstractAdapter
{
    private const MAX_KEY_LENGTH = 250;
    private Collection $connection;
    private MarshallerInterface $marshaller;
    public function __construct(Collection $connection, string $namespace = '', int $defaultLifetime = 0, ?MarshallerInterface $marshaller = null)
    {
        if (!static::isSupported()) {
            throw new CacheException('Couchbase >= 3.0.5 < 4.0.0 is required.');
        }
        $this->maxIdLength = static::MAX_KEY_LENGTH;
        $this->connection = $connection;
        parent::__construct($namespace, $defaultLifetime);
        $this->enableVersioning();
        $this->marshaller = $marshaller ?? new DefaultMarshaller();
    }
    public static function createConnection(
        #[\SensitiveParameter]
        array|string $dsn,
        array $options = []
    ): Bucket|Collection
    {
        if (\is_string($dsn)) {
            $dsn = [$dsn];
        }
        if (!static::isSupported()) {
            throw new CacheException('Couchbase >= 3.0.5 < 4.0.0 is required.');
        }
        set_error_handler(static fn($type, $msg, $file, $line) => throw new \ErrorException($msg, 0, $type, $file, $line));
        $dsnPattern = '/^(?<protocol>couchbase(?:s)?)\:\/\/(?:(?<username>[^\:]+)\:(?<password>[^\@]{6,})@)?' . '(?<host>[^\:]+(?:\:\d+)?)(?:\/(?<bucketName>[^\/\?]+))(?:(?:\/(?<scopeName>[^\/]+))' . '(?:\/(?<collectionName>[^\/\?]+)))?(?:\/)?(?:\?(?<options>.*))?$/i';
        $newServers = [];
        $protocol = 'couchbase';
        try {
            $username = $options['username'] ?? '';
            $password = $options['password'] ?? '';
            foreach ($dsn as $server) {
                if (!str_starts_with($server, 'couchbase:')) {
                    throw new InvalidArgumentException('Invalid Couchbase DSN: it does not start with "couchbase:".');
                }
                preg_match($dsnPattern, $server, $matches);
                $username = $matches['username'] ?: $username;
                $password = $matches['password'] ?: $password;
                $protocol = $matches['protocol'] ?: $protocol;
                if (isset($matches['options'])) {
                    $optionsInDsn = self::getOptions($matches['options']);
                    foreach ($optionsInDsn as $parameter => $value) {
                        $options[$parameter] = $value;
                    }
                }
                $newServers[] = $matches['host'];
            }
            $option = isset($matches['options']) ? '?' . $matches['options'] : '';
            $connectionString = $protocol . '://' . implode(',', $newServers) . $option;
            $clusterOptions = new ClusterOptions();
            $clusterOptions->credentials($username, $password);
            $client = new Cluster($connectionString, $clusterOptions);
            $bucket = $client->bucket($matches['bucketName']);
            $collection = $bucket->defaultCollection();
            if (!empty($matches['scopeName'])) {
                $scope = $bucket->scope($matches['scopeName']);
                $collection = $scope->collection($matches['collectionName']);
            }
            return $collection;
        } finally {
            restore_error_handler();
        }
    }
    public static function isSupported(): bool
    {
        return \extension_loaded('couchbase') && version_compare(phpversion('couchbase'), '3.0.5', '>=') && version_compare(phpversion('couchbase'), '4.0', '<');
    }
    private static function getOptions(string $options): array
    {
        $results = [];
        $optionsInArray = explode('&', $options);
        foreach ($optionsInArray as $option) {
            [$key, $value] = explode('=', $option);
            $results[$key] = $value;
        }
        return $results;
    }
    protected function doFetch(array $ids): array
    {
        $results = [];
        foreach ($ids as $id) {
            try {
                $resultCouchbase = $this->connection->get($id);
            } catch (DocumentNotFoundException) {
                continue;
            }
            $content = $resultCouchbase->value ?? $resultCouchbase->content();
            $results[$id] = $this->marshaller->unmarshall($content);
        }
        return $results;
    }
    protected function doHave($id): bool
    {
        return $this->connection->exists($id)->exists();
    }
    protected function doClear($namespace): bool
    {
        return \false;
    }
    protected function doDelete(array $ids): bool
    {
        $idsErrors = [];
        foreach ($ids as $id) {
            try {
                $result = $this->connection->remove($id);
                if (null === $result->mutationToken()) {
                    $idsErrors[] = $id;
                }
            } catch (DocumentNotFoundException) {
            }
        }
        return 0 === \count($idsErrors);
    }
    protected function doSave(array $values, $lifetime): array|bool
    {
        if (!$values = $this->marshaller->marshall($values, $failed)) {
            return $failed;
        }
        $upsertOptions = new UpsertOptions();
        $upsertOptions->expiry($lifetime);
        $ko = [];
        foreach ($values as $key => $value) {
            try {
                $this->connection->upsert($key, $value, $upsertOptions);
            } catch (\Exception) {
                $ko[$key] = '';
            }
        }
        return [] === $ko ? \true : $ko;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Cache\Adapter;

use _ContaoManager\Psr\Cache\CacheItemInterface;
use _ContaoManager\Symfony\Component\Cache\CacheItem;
use _ContaoManager\Symfony\Component\Cache\PruneableInterface;
use _ContaoManager\Symfony\Component\Cache\ResettableInterface;
use _ContaoManager\Symfony\Contracts\Cache\CacheInterface;
use _ContaoManager\Symfony\Contracts\Service\ResetInterface;
/**
 * An adapter that collects data about all cache calls.
 *
 * @author Aaron Scherer <aequasi@gmail.com>
 * @author Tobias Nyholm <tobias.nyholm@gmail.com>
 * @author Nicolas Grekas <p@tchwork.com>
 */
class TraceableAdapter implements AdapterInterface, CacheInterface, PruneableInterface, ResettableInterface
{
    protected $pool;
    private array $calls = [];
    public function __construct(AdapterInterface $pool)
    {
        $this->pool = $pool;
    }
    public function get(string $key, callable $callback, ?float $beta = null, ?array &$metadata = null): mixed
    {
        if (!$this->pool instanceof CacheInterface) {
            throw new \BadMethodCallException(\sprintf('Cannot call "%s::get()": this class doesn\'t implement "%s".', get_debug_type($this->pool), CacheInterface::class));
        }
        $isHit = \true;
        $callback = function (CacheItem $item, bool &$save) use ($callback, &$isHit) {
            $isHit = $item->isHit();
            return $callback($item, $save);
        };
        $event = $this->start(__FUNCTION__);
        try {
            $value = $this->pool->get($key, $callback, $beta, $metadata);
            $event->result[$key] = get_debug_type($value);
        } finally {
            $event->end = microtime(\true);
        }
        if ($isHit) {
            ++$event->hits;
        } else {
            ++$event->misses;
        }
        return $value;
    }
    public function getItem(mixed $key): CacheItem
    {
        $event = $this->start(__FUNCTION__);
        try {
            $item = $this->pool->getItem($key);
        } finally {
            $event->end = microtime(\true);
        }
        if ($event->result[$key] = $item->isHit()) {
            ++$event->hits;
        } else {
            ++$event->misses;
        }
        return $item;
    }
    public function hasItem(mixed $key): bool
    {
        $event = $this->start(__FUNCTION__);
        try {
            return $event->result[$key] = $this->pool->hasItem($key);
        } finally {
            $event->end = microtime(\true);
        }
    }
    public function deleteItem(mixed $key): bool
    {
        $event = $this->start(__FUNCTION__);
        try {
            return $event->result[$key] = $this->pool->deleteItem($key);
        } finally {
            $event->end = microtime(\true);
        }
    }
    public function save(CacheItemInterface $item): bool
    {
        $event = $this->start(__FUNCTION__);
        try {
            return $event->result[$item->getKey()] = $this->pool->save($item);
        } finally {
            $event->end = microtime(\true);
        }
    }
    public function saveDeferred(CacheItemInterface $item): bool
    {
        $event = $this->start(__FUNCTION__);
        try {
            return $event->result[$item->getKey()] = $this->pool->saveDeferred($item);
        } finally {
            $event->end = microtime(\true);
        }
    }
    public function getItems(array $keys = []): iterable
    {
        $event = $this->start(__FUNCTION__);
        try {
            $result = $this->pool->getItems($keys);
        } finally {
            $event->end = microtime(\true);
        }
        $f = function () use ($result, $event) {
            $event->result = [];
            foreach ($result as $key => $item) {
                if ($event->result[$key] = $item->isHit()) {
                    ++$event->hits;
                } else {
                    ++$event->misses;
                }
                yield $key => $item;
            }
        };
        return $f();
    }
    public function clear(string $prefix = ''): bool
    {
        $event = $this->start(__FUNCTION__);
        try {
            if ($this->pool instanceof AdapterInterface) {
                return $event->result = $this->pool->clear($prefix);
            }
            return $event->result = $this->pool->clear();
        } finally {
            $event->end = microtime(\true);
        }
    }
    public function deleteItems(array $keys): bool
    {
        $event = $this->start(__FUNCTION__);
        $event->result['keys'] = $keys;
        try {
            return $event->result['result'] = $this->pool->deleteItems($keys);
        } finally {
            $event->end = microtime(\true);
        }
    }
    public function commit(): bool
    {
        $event = $this->start(__FUNCTION__);
        try {
            return $event->result = $this->pool->commit();
        } finally {
            $event->end = microtime(\true);
        }
    }
    public function prune(): bool
    {
        if (!$this->pool instanceof PruneableInterface) {
            return \false;
        }
        $event = $this->start(__FUNCTION__);
        try {
            return $event->result = $this->pool->prune();
        } finally {
            $event->end = microtime(\true);
        }
    }
    /**
     * @return void
     */
    public function reset()
    {
        if ($this->pool instanceof ResetInterface) {
            $this->pool->reset();
        }
        $this->clearCalls();
    }
    public function delete(string $key): bool
    {
        $event = $this->start(__FUNCTION__);
        try {
            return $event->result[$key] = $this->pool->deleteItem($key);
        } finally {
            $event->end = microtime(\true);
        }
    }
    /**
     * @return array
     */
    public function getCalls()
    {
        return $this->calls;
    }
    /**
     * @return void
     */
    public function clearCalls()
    {
        $this->calls = [];
    }
    public function getPool(): AdapterInterface
    {
        return $this->pool;
    }
    /**
     * @return TraceableAdapterEvent
     */
    protected function start(string $name)
    {
        $this->calls[] = $event = new TraceableAdapterEvent();
        $event->name = $name;
        $event->start = microtime(\true);
        return $event;
    }
}
/**
 * @internal
 */
class TraceableAdapterEvent
{
    public string $name;
    public float $start;
    public float $end;
    public array|bool $result;
    public int $hits = 0;
    public int $misses = 0;
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Cache\Adapter;

use _ContaoManager\Symfony\Component\Cache\Exception\InvalidArgumentException;
use _ContaoManager\Symfony\Component\Cache\Marshaller\DefaultMarshaller;
use _ContaoManager\Symfony\Component\Cache\Marshaller\MarshallerInterface;
use _ContaoManager\Symfony\Component\Cache\PruneableInterface;
class PdoAdapter extends AbstractAdapter implements PruneableInterface
{
    private const MAX_KEY_LENGTH = 255;
    private MarshallerInterface $marshaller;
    private \PDO $conn;
    private string $dsn;
    private string $driver;
    private string $serverVersion;
    private string $table = 'cache_items';
    private string $idCol = 'item_id';
    private string $dataCol = 'item_data';
    private string $lifetimeCol = 'item_lifetime';
    private string $timeCol = 'item_time';
    private ?string $username = null;
    private ?string $password = null;
    private array $connectionOptions = [];
    private string $namespace;
    /**
     * You can either pass an existing database connection as PDO instance or
     * a DSN string that will be used to lazy-connect to the database when the
     * cache is actually used.
     *
     * List of available options:
     *  * db_table: The name of the table [default: cache_items]
     *  * db_id_col: The column where to store the cache id [default: item_id]
     *  * db_data_col: The column where to store the cache data [default: item_data]
     *  * db_lifetime_col: The column where to store the lifetime [default: item_lifetime]
     *  * db_time_col: The column where to store the timestamp [default: item_time]
     *  * db_username: The username when lazy-connect [default: '']
     *  * db_password: The password when lazy-connect [default: '']
     *  * db_connection_options: An array of driver-specific connection options [default: []]
     *
     * @throws InvalidArgumentException When first argument is not PDO nor Connection nor string
     * @throws InvalidArgumentException When PDO error mode is not PDO::ERRMODE_EXCEPTION
     * @throws InvalidArgumentException When namespace contains invalid characters
     */
    public function __construct(
        #[\SensitiveParameter]
        \PDO|string $connOrDsn,
        string $namespace = '',
        int $defaultLifetime = 0,
        array $options = [],
        ?MarshallerInterface $marshaller = null
    )
    {
        if (\is_string($connOrDsn) && str_contains($connOrDsn, '://')) {
            throw new InvalidArgumentException(\sprintf('Usage of Doctrine DBAL URL with "%s" is not supported. Use a PDO DSN or "%s" instead.', __CLASS__, DoctrineDbalAdapter::class));
        }
        if (isset($namespace[0]) && preg_match('#[^-+.A-Za-z0-9]#', $namespace, $match)) {
            throw new InvalidArgumentException(\sprintf('Namespace contains "%s" but only characters in [-+.A-Za-z0-9] are allowed.', $match[0]));
        }
        if ($connOrDsn instanceof \PDO) {
            if (\PDO::ERRMODE_EXCEPTION !== $connOrDsn->getAttribute(\PDO::ATTR_ERRMODE)) {
                throw new InvalidArgumentException(\sprintf('"%s" requires PDO error mode attribute be set to throw Exceptions (i.e. $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION)).', __CLASS__));
            }
            $this->conn = $connOrDsn;
        } else {
            $this->dsn = $connOrDsn;
        }
        $this->maxIdLength = self::MAX_KEY_LENGTH;
        $this->table = $options['db_table'] ?? $this->table;
        $this->idCol = $options['db_id_col'] ?? $this->idCol;
        $this->dataCol = $options['db_data_col'] ?? $this->dataCol;
        $this->lifetimeCol = $options['db_lifetime_col'] ?? $this->lifetimeCol;
        $this->timeCol = $options['db_time_col'] ?? $this->timeCol;
        $this->username = $options['db_username'] ?? $this->username;
        $this->password = $options['db_password'] ?? $this->password;
        $this->connectionOptions = $options['db_connection_options'] ?? $this->connectionOptions;
        $this->namespace = $namespace;
        $this->marshaller = $marshaller ?? new DefaultMarshaller();
        parent::__construct($namespace, $defaultLifetime);
    }
    /**
     * Creates the table to store cache items which can be called once for setup.
     *
     * Cache ID are saved in a column of maximum length 255. Cache data is
     * saved in a BLOB.
     *
     * @return void
     *
     * @throws \PDOException    When the table already exists
     * @throws \DomainException When an unsupported PDO driver is used
     */
    public function createTable()
    {
        $sql = match ($driver = $this->getDriver()) {
            // We use varbinary for the ID column because it prevents unwanted conversions:
            // - character set conversions between server and client
            // - trailing space removal
            // - case-insensitivity
            // - language processing like é == e
            'mysql' => "CREATE TABLE {$this->table} ({$this->idCol} VARBINARY(255) NOT NULL PRIMARY KEY, {$this->dataCol} MEDIUMBLOB NOT NULL, {$this->lifetimeCol} INTEGER UNSIGNED, {$this->timeCol} INTEGER UNSIGNED NOT NULL) ENGINE = InnoDB",
            'sqlite' => "CREATE TABLE {$this->table} ({$this->idCol} TEXT NOT NULL PRIMARY KEY, {$this->dataCol} BLOB NOT NULL, {$this->lifetimeCol} INTEGER, {$this->timeCol} INTEGER NOT NULL)",
            'pgsql' => "CREATE TABLE {$this->table} ({$this->idCol} VARCHAR(255) NOT NULL PRIMARY KEY, {$this->dataCol} BYTEA NOT NULL, {$this->lifetimeCol} INTEGER, {$this->timeCol} INTEGER NOT NULL)",
            'oci' => "CREATE TABLE {$this->table} ({$this->idCol} VARCHAR2(255) NOT NULL PRIMARY KEY, {$this->dataCol} BLOB NOT NULL, {$this->lifetimeCol} INTEGER, {$this->timeCol} INTEGER NOT NULL)",
            'sqlsrv' => "CREATE TABLE {$this->table} ({$this->idCol} VARCHAR(255) NOT NULL PRIMARY KEY, {$this->dataCol} VARBINARY(MAX) NOT NULL, {$this->lifetimeCol} INTEGER, {$this->timeCol} INTEGER NOT NULL)",
            default => throw new \DomainException(\sprintf('Creating the cache table is currently not implemented for PDO driver "%s".', $driver)),
        };
        $this->getConnection()->exec($sql);
    }
    public function prune(): bool
    {
        $deleteSql = "DELETE FROM {$this->table} WHERE {$this->lifetimeCol} + {$this->timeCol} <= :time";
        if ('' !== $this->namespace) {
            $deleteSql .= " AND {$this->idCol} LIKE :namespace";
        }
        $connection = $this->getConnection();
        try {
            $delete = $connection->prepare($deleteSql);
        } catch (\PDOException) {
            return \true;
        }
        $delete->bindValue(':time', time(), \PDO::PARAM_INT);
        if ('' !== $this->namespace) {
            $delete->bindValue(':namespace', \sprintf('%s%%', $this->namespace), \PDO::PARAM_STR);
        }
        try {
            return $delete->execute();
        } catch (\PDOException) {
            return \true;
        }
    }
    protected function doFetch(array $ids): iterable
    {
        $connection = $this->getConnection();
        $now = time();
        $expired = [];
        $sql = str_pad('', (\count($ids) << 1) - 1, '?,');
        $sql = "SELECT {$this->idCol}, CASE WHEN {$this->lifetimeCol} IS NULL OR {$this->lifetimeCol} + {$this->timeCol} > ? THEN {$this->dataCol} ELSE NULL END FROM {$this->table} WHERE {$this->idCol} IN ({$sql})";
        $stmt = $connection->prepare($sql);
        $stmt->bindValue($i = 1, $now, \PDO::PARAM_INT);
        foreach ($ids as $id) {
            $stmt->bindValue(++$i, $id);
        }
        $result = $stmt->execute();
        if (\is_object($result)) {
            $result = $result->iterateNumeric();
        } else {
            $stmt->setFetchMode(\PDO::FETCH_NUM);
            $result = $stmt;
        }
        foreach ($result as $row) {
            if (null === $row[1]) {
                $expired[] = $row[0];
            } else {
                yield $row[0] => $this->marshaller->unmarshall(\is_resource($row[1]) ? stream_get_contents($row[1]) : $row[1]);
            }
        }
        if ($expired) {
            $sql = str_pad('', (\count($expired) << 1) - 1, '?,');
            $sql = "DELETE FROM {$this->table} WHERE {$this->lifetimeCol} + {$this->timeCol} <= ? AND {$this->idCol} IN ({$sql})";
            $stmt = $connection->prepare($sql);
            $stmt->bindValue($i = 1, $now, \PDO::PARAM_INT);
            foreach ($expired as $id) {
                $stmt->bindValue(++$i, $id);
            }
            $stmt->execute();
        }
    }
    protected function doHave(string $id): bool
    {
        $connection = $this->getConnection();
        $sql = "SELECT 1 FROM {$this->table} WHERE {$this->idCol} = :id AND ({$this->lifetimeCol} IS NULL OR {$this->lifetimeCol} + {$this->timeCol} > :time)";
        $stmt = $connection->prepare($sql);
        $stmt->bindValue(':id', $id);
        $stmt->bindValue(':time', time(), \PDO::PARAM_INT);
        $stmt->execute();
        return (bool) $stmt->fetchColumn();
    }
    protected function doClear(string $namespace): bool
    {
        $conn = $this->getConnection();
        if ('' === $namespace) {
            if ('sqlite' === $this->getDriver()) {
                $sql = "DELETE FROM {$this->table}";
            } else {
                $sql = "TRUNCATE TABLE {$this->table}";
            }
        } else {
            $sql = "DELETE FROM {$this->table} WHERE {$this->idCol} LIKE '{$namespace}%'";
        }
        try {
            $conn->exec($sql);
        } catch (\PDOException) {
        }
        return \true;
    }
    protected function doDelete(array $ids): bool
    {
        $sql = str_pad('', (\count($ids) << 1) - 1, '?,');
        $sql = "DELETE FROM {$this->table} WHERE {$this->idCol} IN ({$sql})";
        try {
            $stmt = $this->getConnection()->prepare($sql);
            $stmt->execute(array_values($ids));
        } catch (\PDOException) {
        }
        return \true;
    }
    protected function doSave(array $values, int $lifetime): array|bool
    {
        if (!$values = $this->marshaller->marshall($values, $failed)) {
            return $failed;
        }
        $conn = $this->getConnection();
        $driver = $this->getDriver();
        $insertSql = "INSERT INTO {$this->table} ({$this->idCol}, {$this->dataCol}, {$this->lifetimeCol}, {$this->timeCol}) VALUES (:id, :data, :lifetime, :time)";
        switch (\true) {
            case 'mysql' === $driver:
                $sql = $insertSql . " ON DUPLICATE KEY UPDATE {$this->dataCol} = VALUES({$this->dataCol}), {$this->lifetimeCol} = VALUES({$this->lifetimeCol}), {$this->timeCol} = VALUES({$this->timeCol})";
                break;
            case 'oci' === $driver:
                // DUAL is Oracle specific dummy table
                $sql = "MERGE INTO {$this->table} USING DUAL ON ({$this->idCol} = ?) " . "WHEN NOT MATCHED THEN INSERT ({$this->idCol}, {$this->dataCol}, {$this->lifetimeCol}, {$this->timeCol}) VALUES (?, ?, ?, ?) " . "WHEN MATCHED THEN UPDATE SET {$this->dataCol} = ?, {$this->lifetimeCol} = ?, {$this->timeCol} = ?";
                break;
            case 'sqlsrv' === $driver && version_compare($this->getServerVersion(), '10', '>='):
                // MERGE is only available since SQL Server 2008 and must be terminated by semicolon
                // It also requires HOLDLOCK according to http://weblogs.sqlteam.com/dang/archive/2009/01/31/UPSERT-Race-Condition-With-MERGE.aspx
                $sql = "MERGE INTO {$this->table} WITH (HOLDLOCK) USING (SELECT 1 AS dummy) AS src ON ({$this->idCol} = ?) " . "WHEN NOT MATCHED THEN INSERT ({$this->idCol}, {$this->dataCol}, {$this->lifetimeCol}, {$this->timeCol}) VALUES (?, ?, ?, ?) " . "WHEN MATCHED THEN UPDATE SET {$this->dataCol} = ?, {$this->lifetimeCol} = ?, {$this->timeCol} = ?;";
                break;
            case 'sqlite' === $driver:
                $sql = 'INSERT OR REPLACE' . substr($insertSql, 6);
                break;
            case 'pgsql' === $driver && version_compare($this->getServerVersion(), '9.5', '>='):
                $sql = $insertSql . " ON CONFLICT ({$this->idCol}) DO UPDATE SET ({$this->dataCol}, {$this->lifetimeCol}, {$this->timeCol}) = (EXCLUDED.{$this->dataCol}, EXCLUDED.{$this->lifetimeCol}, EXCLUDED.{$this->timeCol})";
                break;
            default:
                $driver = null;
                $sql = "UPDATE {$this->table} SET {$this->dataCol} = :data, {$this->lifetimeCol} = :lifetime, {$this->timeCol} = :time WHERE {$this->idCol} = :id";
                break;
        }
        $now = time();
        $lifetime = $lifetime ?: null;
        try {
            $stmt = $conn->prepare($sql);
        } catch (\PDOException $e) {
            if ($this->isTableMissing($e) && (!$conn->inTransaction() || \in_array($driver, ['pgsql', 'sqlite', 'sqlsrv'], \true))) {
                $this->createTable();
            }
            $stmt = $conn->prepare($sql);
        }
        // $id and $data are defined later in the loop. Binding is done by reference, values are read on execution.
        if ('sqlsrv' === $driver || 'oci' === $driver) {
            $stmt->bindParam(1, $id);
            $stmt->bindParam(2, $id);
            $stmt->bindParam(3, $data, \PDO::PARAM_LOB);
            $stmt->bindValue(4, $lifetime, \PDO::PARAM_INT);
            $stmt->bindValue(5, $now, \PDO::PARAM_INT);
            $stmt->bindParam(6, $data, \PDO::PARAM_LOB);
            $stmt->bindValue(7, $lifetime, \PDO::PARAM_INT);
            $stmt->bindValue(8, $now, \PDO::PARAM_INT);
        } else {
            $stmt->bindParam(':id', $id);
            $stmt->bindParam(':data', $data, \PDO::PARAM_LOB);
            $stmt->bindValue(':lifetime', $lifetime, \PDO::PARAM_INT);
            $stmt->bindValue(':time', $now, \PDO::PARAM_INT);
        }
        if (null === $driver) {
            $insertStmt = $conn->prepare($insertSql);
            $insertStmt->bindParam(':id', $id);
            $insertStmt->bindParam(':data', $data, \PDO::PARAM_LOB);
            $insertStmt->bindValue(':lifetime', $lifetime, \PDO::PARAM_INT);
            $insertStmt->bindValue(':time', $now, \PDO::PARAM_INT);
        }
        if ('sqlsrv' === $driver) {
            $dataStream = fopen('php://memory', 'r+');
        }
        foreach ($values as $id => $data) {
            if ('sqlsrv' === $driver) {
                rewind($dataStream);
                fwrite($dataStream, $data);
                ftruncate($dataStream, \strlen($data));
                rewind($dataStream);
                $data = $dataStream;
            }
            try {
                $stmt->execute();
            } catch (\PDOException $e) {
                if ($this->isTableMissing($e) && (!$conn->inTransaction() || \in_array($driver, ['pgsql', 'sqlite', 'sqlsrv'], \true))) {
                    $this->createTable();
                }
                $stmt->execute();
            }
            if (null === $driver && !$stmt->rowCount()) {
                try {
                    $insertStmt->execute();
                } catch (\PDOException) {
                    // A concurrent write won, let it be
                }
            }
        }
        return $failed;
    }
    /**
     * @internal
     */
    protected function getId(mixed $key): string
    {
        if ('pgsql' !== $this->getDriver()) {
            return parent::getId($key);
        }
        if (str_contains($key, "\x00") || str_contains($key, '%') || !preg_match('//u', $key)) {
            $key = rawurlencode($key);
        }
        return parent::getId($key);
    }
    private function getConnection(): \PDO
    {
        if (!isset($this->conn)) {
            $this->conn = new \PDO($this->dsn, $this->username, $this->password, $this->connectionOptions);
            $this->conn->setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION);
        }
        return $this->conn;
    }
    private function getDriver(): string
    {
        return $this->driver ??= $this->getConnection()->getAttribute(\PDO::ATTR_DRIVER_NAME);
    }
    private function getServerVersion(): string
    {
        return $this->serverVersion ??= $this->getConnection()->getAttribute(\PDO::ATTR_SERVER_VERSION);
    }
    private function isTableMissing(\PDOException $exception): bool
    {
        $driver = $this->getDriver();
        [$sqlState, $code] = $exception->errorInfo ?? [null, $exception->getCode()];
        return match ($driver) {
            'pgsql' => '42P01' === $sqlState,
            'sqlite' => str_contains($exception->getMessage(), 'no such table:'),
            'oci' => 942 === $code,
            'sqlsrv' => 208 === $code,
            'mysql' => 1146 === $code,
            default => \false,
        };
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Cache\Adapter;

use _ContaoManager\Psr\Cache\CacheItemInterface;
use _ContaoManager\Psr\Log\LoggerAwareInterface;
use _ContaoManager\Psr\Log\LoggerAwareTrait;
use _ContaoManager\Symfony\Component\Cache\CacheItem;
use _ContaoManager\Symfony\Component\Cache\Exception\InvalidArgumentException;
use _ContaoManager\Symfony\Component\Cache\ResettableInterface;
use _ContaoManager\Symfony\Contracts\Cache\CacheInterface;
/**
 * An in-memory cache storage.
 *
 * Acts as a least-recently-used (LRU) storage when configured with a maximum number of items.
 *
 * @author Nicolas Grekas <p@tchwork.com>
 */
class ArrayAdapter implements AdapterInterface, CacheInterface, LoggerAwareInterface, ResettableInterface
{
    use LoggerAwareTrait;
    private bool $storeSerialized;
    private array $values = [];
    private array $tags = [];
    private array $expiries = [];
    private array $explicitExpiries = [];
    private int $defaultLifetime;
    private float $maxLifetime;
    private int $maxItems;
    private static \Closure $createCacheItem;
    /**
     * @param bool $storeSerialized Disabling serialization can lead to cache corruptions when storing mutable values but increases performance otherwise
     */
    public function __construct(int $defaultLifetime = 0, bool $storeSerialized = \true, float $maxLifetime = 0, int $maxItems = 0)
    {
        if (0 > $maxLifetime) {
            throw new InvalidArgumentException(\sprintf('Argument $maxLifetime must be positive, %F passed.', $maxLifetime));
        }
        if (0 > $maxItems) {
            throw new InvalidArgumentException(\sprintf('Argument $maxItems must be a positive integer, %d passed.', $maxItems));
        }
        $this->defaultLifetime = $defaultLifetime;
        $this->storeSerialized = $storeSerialized;
        $this->maxLifetime = $maxLifetime;
        $this->maxItems = $maxItems;
        self::$createCacheItem ??= \Closure::bind(static function ($key, $value, $isHit, $tags, $expiry = null) {
            $item = new CacheItem();
            $item->key = $key;
            $item->value = $value;
            $item->isHit = $isHit;
            if (null !== $tags) {
                $item->metadata[CacheItem::METADATA_TAGS] = $tags;
            }
            if (null !== $expiry) {
                $item->metadata[CacheItem::METADATA_EXPIRY] = $expiry;
            }
            return $item;
        }, null, CacheItem::class);
    }
    public function get(string $key, callable $callback, ?float $beta = null, ?array &$metadata = null): mixed
    {
        $item = $this->getItem($key);
        $metadata = $item->getMetadata();
        // ArrayAdapter works in memory, we don't care about stampede protection
        if (\INF === $beta || !$item->isHit()) {
            $save = \true;
            $item->set($callback($item, $save));
            if ($save) {
                $this->save($item);
            }
        }
        return $item->get();
    }
    public function delete(string $key): bool
    {
        return $this->deleteItem($key);
    }
    public function hasItem(mixed $key): bool
    {
        if (\is_string($key) && isset($this->expiries[$key]) && $this->expiries[$key] > microtime(\true)) {
            if ($this->maxItems) {
                // Move the item last in the storage
                $value = $this->values[$key];
                unset($this->values[$key]);
                $this->values[$key] = $value;
            }
            return \true;
        }
        \assert('' !== CacheItem::validateKey($key));
        return isset($this->expiries[$key]) && !$this->deleteItem($key);
    }
    public function getItem(mixed $key): CacheItem
    {
        if (!$isHit = $this->hasItem($key)) {
            $value = null;
            if (!$this->maxItems) {
                // Track misses in non-LRU mode only
                $this->values[$key] = null;
            }
        } else {
            $value = $this->storeSerialized ? $this->unfreeze($key, $isHit) : $this->values[$key];
        }
        return (self::$createCacheItem)($key, $value, $isHit, $this->tags[$key] ?? null, $this->explicitExpiries[$key] ?? null);
    }
    public function getItems(array $keys = []): iterable
    {
        \assert(self::validateKeys($keys));
        return $this->generateItems($keys, microtime(\true), self::$createCacheItem);
    }
    public function deleteItem(mixed $key): bool
    {
        \assert('' !== CacheItem::validateKey($key));
        unset($this->values[$key], $this->tags[$key], $this->expiries[$key], $this->explicitExpiries[$key]);
        return \true;
    }
    public function deleteItems(array $keys): bool
    {
        foreach ($keys as $key) {
            $this->deleteItem($key);
        }
        return \true;
    }
    public function save(CacheItemInterface $item): bool
    {
        if (!$item instanceof CacheItem) {
            return \false;
        }
        $item = (array) $item;
        $key = $item["\x00*\x00key"];
        $value = $item["\x00*\x00value"];
        $expiry = $item["\x00*\x00expiry"];
        $now = microtime(\true);
        if (null !== $expiry) {
            if (!$expiry) {
                $expiry = \PHP_INT_MAX;
            } elseif ($expiry <= $now) {
                $this->deleteItem($key);
                return \true;
            }
        }
        if ($this->storeSerialized && null === $value = $this->freeze($value, $key)) {
            return \false;
        }
        if (null === $expiry && 0 < $this->defaultLifetime) {
            $expiry = $this->defaultLifetime;
            $expiry = $now + ($expiry > ($this->maxLifetime ?: $expiry) ? $this->maxLifetime : $expiry);
        } elseif ($this->maxLifetime && (null === $expiry || $expiry > $now + $this->maxLifetime)) {
            $expiry = $now + $this->maxLifetime;
        }
        if ($this->maxItems) {
            unset($this->values[$key], $this->tags[$key]);
            // Iterate items and vacuum expired ones while we are at it
            foreach ($this->values as $k => $v) {
                if ($this->expiries[$k] > $now && \count($this->values) < $this->maxItems) {
                    break;
                }
                unset($this->values[$k], $this->tags[$k], $this->expiries[$k], $this->explicitExpiries[$k]);
            }
        }
        $this->values[$key] = $value;
        $this->expiries[$key] = $expiry ?? \PHP_INT_MAX;
        if (null !== $item["\x00*\x00expiry"] && \PHP_INT_MAX !== $this->expiries[$key]) {
            $this->explicitExpiries[$key] = $this->expiries[$key];
        } else {
            unset($this->explicitExpiries[$key]);
        }
        if (null === $this->tags[$key] = $item["\x00*\x00newMetadata"][CacheItem::METADATA_TAGS] ?? null) {
            unset($this->tags[$key]);
        }
        return \true;
    }
    public function saveDeferred(CacheItemInterface $item): bool
    {
        return $this->save($item);
    }
    public function commit(): bool
    {
        return \true;
    }
    public function clear(string $prefix = ''): bool
    {
        if ('' !== $prefix) {
            $now = microtime(\true);
            foreach ($this->values as $key => $value) {
                if (!isset($this->expiries[$key]) || $this->expiries[$key] <= $now || str_starts_with($key, $prefix)) {
                    unset($this->values[$key], $this->tags[$key], $this->expiries[$key], $this->explicitExpiries[$key]);
                }
            }
            if ($this->values) {
                return \true;
            }
        }
        $this->values = $this->tags = $this->expiries = $this->explicitExpiries = [];
        return \true;
    }
    /**
     * Returns all cached values, with cache miss as null.
     */
    public function getValues(): array
    {
        if (!$this->storeSerialized) {
            return $this->values;
        }
        $values = $this->values;
        foreach ($values as $k => $v) {
            if (null === $v || 'N;' === $v) {
                continue;
            }
            if (!\is_string($v) || !isset($v[2]) || ':' !== $v[1]) {
                $values[$k] = serialize($v);
            }
        }
        return $values;
    }
    /**
     * @return void
     */
    public function reset()
    {
        $this->clear();
    }
    private function generateItems(array $keys, float $now, \Closure $f): \Generator
    {
        foreach ($keys as $i => $key) {
            if (!$isHit = isset($this->expiries[$key]) && ($this->expiries[$key] > $now || !$this->deleteItem($key))) {
                $value = null;
                if (!$this->maxItems) {
                    // Track misses in non-LRU mode only
                    $this->values[$key] = null;
                }
            } else {
                if ($this->maxItems) {
                    // Move the item last in the storage
                    $value = $this->values[$key];
                    unset($this->values[$key]);
                    $this->values[$key] = $value;
                }
                $value = $this->storeSerialized ? $this->unfreeze($key, $isHit) : $this->values[$key];
            }
            unset($keys[$i]);
            yield $key => $f($key, $value, $isHit, $this->tags[$key] ?? null, $this->explicitExpiries[$key] ?? null);
        }
        foreach ($keys as $key) {
            yield $key => $f($key, null, \false);
        }
    }
    private function freeze($value, string $key): string|int|float|bool|array|\UnitEnum|null
    {
        if (null === $value) {
            return 'N;';
        }
        if (\is_string($value)) {
            // Serialize strings if they could be confused with serialized objects or arrays
            if ('N;' === $value || isset($value[2]) && ':' === $value[1]) {
                return serialize($value);
            }
        } elseif (!\is_scalar($value)) {
            try {
                $serialized = serialize($value);
            } catch (\Exception $e) {
                if (!isset($this->expiries[$key])) {
                    unset($this->values[$key]);
                }
                $type = get_debug_type($value);
                $message = \sprintf('Failed to save key "{key}" of type %s: %s', $type, $e->getMessage());
                CacheItem::log($this->logger, $message, ['key' => $key, 'exception' => $e, 'cache-adapter' => get_debug_type($this)]);
                return null;
            }
            // Keep value serialized if it contains any objects or any internal references
            if ('C' === $serialized[0] || 'O' === $serialized[0] || preg_match('/;[OCRr]:[1-9]/', $serialized)) {
                return $serialized;
            }
        }
        return $value;
    }
    private function unfreeze(string $key, bool &$isHit): mixed
    {
        if ('N;' === $value = $this->values[$key]) {
            return null;
        }
        if (\is_string($value) && isset($value[2]) && ':' === $value[1]) {
            try {
                $value = unserialize($value);
            } catch (\Exception $e) {
                CacheItem::log($this->logger, 'Failed to unserialize key "{key}": ' . $e->getMessage(), ['key' => $key, 'exception' => $e, 'cache-adapter' => get_debug_type($this)]);
                $value = \false;
            }
            if (\false === $value) {
                $value = null;
                $isHit = \false;
                if (!$this->maxItems) {
                    $this->values[$key] = null;
                }
            }
        }
        return $value;
    }
    private function validateKeys(array $keys): bool
    {
        foreach ($keys as $key) {
            if (!\is_string($key) || !isset($this->expiries[$key])) {
                CacheItem::validateKey($key);
            }
        }
        return \true;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Cache\Adapter;

use _ContaoManager\Predis\Connection\Aggregate\ClusterInterface;
use _ContaoManager\Predis\Connection\Aggregate\PredisCluster;
use _ContaoManager\Predis\Connection\Aggregate\ReplicationInterface;
use _ContaoManager\Predis\Connection\Replication\ReplicationInterface as Predis2ReplicationInterface;
use _ContaoManager\Predis\Response\ErrorInterface;
use _ContaoManager\Predis\Response\Status;
use Relay\Relay;
use _ContaoManager\Symfony\Component\Cache\CacheItem;
use _ContaoManager\Symfony\Component\Cache\Exception\InvalidArgumentException;
use _ContaoManager\Symfony\Component\Cache\Exception\LogicException;
use _ContaoManager\Symfony\Component\Cache\Marshaller\DeflateMarshaller;
use _ContaoManager\Symfony\Component\Cache\Marshaller\MarshallerInterface;
use _ContaoManager\Symfony\Component\Cache\Marshaller\TagAwareMarshaller;
use _ContaoManager\Symfony\Component\Cache\Traits\RedisTrait;
/**
 * Stores tag id <> cache id relationship as a Redis Set.
 *
 * Set (tag relation info) is stored without expiry (non-volatile), while cache always gets an expiry (volatile) even
 * if not set by caller. Thus if you configure redis with the right eviction policy you can be safe this tag <> cache
 * relationship survives eviction (cache cleanup when Redis runs out of memory).
 *
 * Redis server 2.8+ with any `volatile-*` eviction policy, OR `noeviction` if you're sure memory will NEVER fill up
 *
 * Design limitations:
 *  - Max 4 billion cache keys per cache tag as limited by Redis Set datatype.
 *    E.g. If you use a "all" items tag for expiry instead of clear(), that limits you to 4 billion cache items also.
 *
 * @see https://redis.io/topics/lru-cache#eviction-policies Documentation for Redis eviction policies.
 * @see https://redis.io/topics/data-types#sets Documentation for Redis Set datatype.
 *
 * @author Nicolas Grekas <p@tchwork.com>
 * @author André Rømcke <andre.romcke+symfony@gmail.com>
 */
class RedisTagAwareAdapter extends AbstractTagAwareAdapter
{
    use RedisTrait;
    /**
     * On cache items without a lifetime set, we set it to 100 days. This is to make sure cache items are
     * preferred to be evicted over tag Sets, if eviction policy is configured according to requirements.
     */
    private const DEFAULT_CACHE_TTL = 8640000;
    /**
     * detected eviction policy used on Redis server.
     */
    private string $redisEvictionPolicy;
    private string $namespace;
    public function __construct(\Redis|Relay|\RedisArray|\RedisCluster|\_ContaoManager\Predis\ClientInterface $redis, string $namespace = '', int $defaultLifetime = 0, ?MarshallerInterface $marshaller = null)
    {
        if ($redis instanceof \_ContaoManager\Predis\ClientInterface && $redis->getConnection() instanceof ClusterInterface && !$redis->getConnection() instanceof PredisCluster) {
            throw new InvalidArgumentException(\sprintf('Unsupported Predis cluster connection: only "%s" is, "%s" given.', PredisCluster::class, get_debug_type($redis->getConnection())));
        }
        $isRelay = $redis instanceof Relay;
        if ($isRelay || \defined('Redis::OPT_COMPRESSION') && \in_array($redis::class, [\Redis::class, \RedisArray::class, \RedisCluster::class], \true)) {
            $compression = $redis->getOption($isRelay ? Relay::OPT_COMPRESSION : \Redis::OPT_COMPRESSION);
            foreach (\is_array($compression) ? $compression : [$compression] as $c) {
                if ($isRelay ? Relay::COMPRESSION_NONE : \Redis::COMPRESSION_NONE !== $c) {
                    throw new InvalidArgumentException(\sprintf('redis compression must be disabled when using "%s", use "%s" instead.', static::class, DeflateMarshaller::class));
                }
            }
        }
        $this->init($redis, $namespace, $defaultLifetime, new TagAwareMarshaller($marshaller));
        $this->namespace = $namespace;
    }
    protected function doSave(array $values, int $lifetime, array $addTagData = [], array $delTagData = []): array
    {
        $eviction = $this->getRedisEvictionPolicy();
        if ('noeviction' !== $eviction && !str_starts_with($eviction, 'volatile-')) {
            throw new LogicException(\sprintf('Redis maxmemory-policy setting "%s" is *not* supported by RedisTagAwareAdapter, use "noeviction" or "volatile-*" eviction policies.', $eviction));
        }
        // serialize values
        if (!$serialized = $this->marshaller->marshall($values, $failed)) {
            return $failed;
        }
        // While pipeline isn't supported on RedisCluster, other setups will at least benefit from doing this in one op
        $results = $this->pipeline(static function () use ($serialized, $lifetime, $addTagData, $delTagData, $failed) {
            // Store cache items, force a ttl if none is set, as there is no MSETEX we need to set each one
            foreach ($serialized as $id => $value) {
                yield 'setEx' => [$id, 0 >= $lifetime ? self::DEFAULT_CACHE_TTL : $lifetime, $value];
            }
            // Add and Remove Tags
            foreach ($addTagData as $tagId => $ids) {
                if (!$failed || $ids = array_diff($ids, $failed)) {
                    yield 'sAdd' => array_merge([$tagId], $ids);
                }
            }
            foreach ($delTagData as $tagId => $ids) {
                if (!$failed || $ids = array_diff($ids, $failed)) {
                    yield 'sRem' => array_merge([$tagId], $ids);
                }
            }
        });
        foreach ($results as $id => $result) {
            // Skip results of SADD/SREM operations, they'll be 1 or 0 depending on if set value already existed or not
            if (is_numeric($result)) {
                continue;
            }
            // setEx results
            if (\true !== $result && (!$result instanceof Status || Status::get('OK') !== $result)) {
                $failed[] = $id;
            }
        }
        return $failed;
    }
    protected function doDeleteYieldTags(array $ids): iterable
    {
        $lua = <<<'EOLUA'
            local v = redis.call('GET', KEYS[1])
            local e = redis.pcall('UNLINK', KEYS[1])

            if type(e) ~= 'number' then
                redis.call('DEL', KEYS[1])
            end

            if not v or v:len() <= 13 or v:byte(1) ~= 0x9D or v:byte(6) ~= 0 or v:byte(10) ~= 0x5F then
                return ''
            end

            return v:sub(14, 13 + v:byte(13) + v:byte(12) * 256 + v:byte(11) * 65536)
EOLUA;
        $results = $this->pipeline(function () use ($ids, $lua) {
            foreach ($ids as $id) {
                yield 'eval' => $this->redis instanceof \_ContaoManager\Predis\ClientInterface ? [$lua, 1, $id] : [$lua, [$id], 1];
            }
        });
        foreach ($results as $id => $result) {
            if ($result instanceof \RedisException || $result instanceof \Relay\Exception || $result instanceof ErrorInterface) {
                CacheItem::log($this->logger, 'Failed to delete key "{key}": ' . $result->getMessage(), ['key' => substr($id, \strlen($this->namespace)), 'exception' => $result]);
                continue;
            }
            try {
                yield $id => !\is_string($result) || '' === $result ? [] : $this->marshaller->unmarshall($result);
            } catch (\Exception) {
                yield $id => [];
            }
        }
    }
    protected function doDeleteTagRelations(array $tagData): bool
    {
        $results = $this->pipeline(static function () use ($tagData) {
            foreach ($tagData as $tagId => $idList) {
                array_unshift($idList, $tagId);
                yield 'sRem' => $idList;
            }
        });
        foreach ($results as $result) {
            // no-op
        }
        return \true;
    }
    protected function doInvalidate(array $tagIds): bool
    {
        // This script scans the set of items linked to tag: it empties the set
        // and removes the linked items. When the set is still not empty after
        // the scan, it means we're in cluster mode and that the linked items
        // are on other nodes: we move the links to a temporary set and we
        // garbage collect that set from the client side.
        $lua = <<<'EOLUA'
            redis.replicate_commands()

            local cursor = '0'
            local id = KEYS[1]
            repeat
                local result = redis.call('SSCAN', id, cursor, 'COUNT', 5000);
                cursor = result[1];
                local rems = {}

                for _, v in ipairs(result[2]) do
                    local ok, _ = pcall(redis.call, 'DEL', ARGV[1]..v)
                    if ok then
                        table.insert(rems, v)
                    end
                end
                if 0 < #rems then
                    redis.call('SREM', id, unpack(rems))
                end
            until '0' == cursor;

            redis.call('SUNIONSTORE', '{'..id..'}'..id, id)
            redis.call('DEL', id)

            return redis.call('SSCAN', '{'..id..'}'..id, '0', 'COUNT', 5000)
EOLUA;
        $results = $this->pipeline(function () use ($tagIds, $lua) {
            if ($this->redis instanceof \_ContaoManager\Predis\ClientInterface) {
                $prefix = $this->redis->getOptions()->prefix ? $this->redis->getOptions()->prefix->getPrefix() : '';
            } elseif (\is_array($prefix = $this->redis->getOption($this->redis instanceof Relay ? Relay::OPT_PREFIX : \Redis::OPT_PREFIX) ?? '')) {
                $prefix = current($prefix);
            }
            foreach ($tagIds as $id) {
                yield 'eval' => $this->redis instanceof \_ContaoManager\Predis\ClientInterface ? [$lua, 1, $id, $prefix] : [$lua, [$id, $prefix], 1];
            }
        });
        $lua = <<<'EOLUA'
            redis.replicate_commands()

            local id = KEYS[1]
            local cursor = table.remove(ARGV)
            redis.call('SREM', '{'..id..'}'..id, unpack(ARGV))

            return redis.call('SSCAN', '{'..id..'}'..id, cursor, 'COUNT', 5000)
EOLUA;
        $success = \true;
        foreach ($results as $id => $values) {
            if ($values instanceof \RedisException || $values instanceof \Relay\Exception || $values instanceof ErrorInterface) {
                CacheItem::log($this->logger, 'Failed to invalidate key "{key}": ' . $values->getMessage(), ['key' => substr($id, \strlen($this->namespace)), 'exception' => $values]);
                $success = \false;
                continue;
            }
            [$cursor, $ids] = $values;
            while ($ids || '0' !== $cursor) {
                $this->doDelete($ids);
                $evalArgs = [$id, $cursor];
                array_splice($evalArgs, 1, 0, $ids);
                if ($this->redis instanceof \_ContaoManager\Predis\ClientInterface) {
                    array_unshift($evalArgs, $lua, 1);
                } else {
                    $evalArgs = [$lua, $evalArgs, 1];
                }
                $results = $this->pipeline(function () use ($evalArgs) {
                    yield 'eval' => $evalArgs;
                });
                foreach ($results as [$cursor, $ids]) {
                    // no-op
                }
            }
        }
        return $success;
    }
    private function getRedisEvictionPolicy(): string
    {
        if (isset($this->redisEvictionPolicy)) {
            return $this->redisEvictionPolicy;
        }
        $hosts = $this->getHosts();
        $host = reset($hosts);
        if ($host instanceof \_ContaoManager\Predis\Client) {
            $connection = $host->getConnection();
            // Predis supports info command only on the master in replication environments
            if ($connection instanceof ReplicationInterface) {
                $hosts = [$host->getClientFor('master')];
            } elseif ($connection instanceof Predis2ReplicationInterface) {
                $connection->switchToMaster();
                $hosts = [$host];
            }
        }
        foreach ($hosts as $host) {
            $info = $host->info('Memory');
            if (\false === $info || null === $info || $info instanceof ErrorInterface) {
                continue;
            }
            $info = $info['Memory'] ?? $info;
            return $this->redisEvictionPolicy = $info['maxmemory_policy'] ?? '';
        }
        return $this->redisEvictionPolicy = '';
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Cache\Adapter;

use _ContaoManager\Symfony\Component\Cache\Exception\CacheException;
use _ContaoManager\Symfony\Component\Cache\Exception\InvalidArgumentException;
use _ContaoManager\Symfony\Component\Cache\Marshaller\DefaultMarshaller;
use _ContaoManager\Symfony\Component\Cache\Marshaller\MarshallerInterface;
/**
 * @author Antonio Jose Cerezo Aranda <aj.cerezo@gmail.com>
 */
class CouchbaseBucketAdapter extends AbstractAdapter
{
    private const THIRTY_DAYS_IN_SECONDS = 2592000;
    private const MAX_KEY_LENGTH = 250;
    private const KEY_NOT_FOUND = 13;
    private const VALID_DSN_OPTIONS = ['operationTimeout', 'configTimeout', 'configNodeTimeout', 'n1qlTimeout', 'httpTimeout', 'configDelay', 'htconfigIdleTimeout', 'durabilityInterval', 'durabilityTimeout'];
    private \_ContaoManager\CouchbaseBucket $bucket;
    private MarshallerInterface $marshaller;
    public function __construct(\_ContaoManager\CouchbaseBucket $bucket, string $namespace = '', int $defaultLifetime = 0, ?MarshallerInterface $marshaller = null)
    {
        if (!static::isSupported()) {
            throw new CacheException('Couchbase >= 2.6.0 < 3.0.0 is required.');
        }
        $this->maxIdLength = static::MAX_KEY_LENGTH;
        $this->bucket = $bucket;
        parent::__construct($namespace, $defaultLifetime);
        $this->enableVersioning();
        $this->marshaller = $marshaller ?? new DefaultMarshaller();
    }
    public static function createConnection(
        #[\SensitiveParameter]
        array|string $servers,
        array $options = []
    ): \_ContaoManager\CouchbaseBucket
    {
        if (\is_string($servers)) {
            $servers = [$servers];
        }
        if (!static::isSupported()) {
            throw new CacheException('Couchbase >= 2.6.0 < 3.0.0 is required.');
        }
        set_error_handler(static fn($type, $msg, $file, $line) => throw new \ErrorException($msg, 0, $type, $file, $line));
        $dsnPattern = '/^(?<protocol>couchbase(?:s)?)\:\/\/(?:(?<username>[^\:]+)\:(?<password>[^\@]{6,})@)?' . '(?<host>[^\:]+(?:\:\d+)?)(?:\/(?<bucketName>[^\?]+))(?:\?(?<options>.*))?$/i';
        $newServers = [];
        $protocol = 'couchbase';
        try {
            $options = self::initOptions($options);
            $username = $options['username'];
            $password = $options['password'];
            foreach ($servers as $dsn) {
                if (!str_starts_with($dsn, 'couchbase:')) {
                    throw new InvalidArgumentException('Invalid Couchbase DSN: it does not start with "couchbase:".');
                }
                preg_match($dsnPattern, $dsn, $matches);
                $username = $matches['username'] ?: $username;
                $password = $matches['password'] ?: $password;
                $protocol = $matches['protocol'] ?: $protocol;
                if (isset($matches['options'])) {
                    $optionsInDsn = self::getOptions($matches['options']);
                    foreach ($optionsInDsn as $parameter => $value) {
                        $options[$parameter] = $value;
                    }
                }
                $newServers[] = $matches['host'];
            }
            $connectionString = $protocol . '://' . implode(',', $newServers);
            $client = new \_ContaoManager\CouchbaseCluster($connectionString);
            $client->authenticateAs($username, $password);
            $bucket = $client->openBucket($matches['bucketName']);
            unset($options['username'], $options['password']);
            foreach ($options as $option => $value) {
                if (!empty($value)) {
                    $bucket->{$option} = $value;
                }
            }
            return $bucket;
        } finally {
            restore_error_handler();
        }
    }
    public static function isSupported(): bool
    {
        return \extension_loaded('couchbase') && version_compare(phpversion('couchbase'), '2.6.0', '>=') && version_compare(phpversion('couchbase'), '3.0', '<');
    }
    private static function getOptions(string $options): array
    {
        $results = [];
        $optionsInArray = explode('&', $options);
        foreach ($optionsInArray as $option) {
            [$key, $value] = explode('=', $option);
            if (\in_array($key, static::VALID_DSN_OPTIONS, \true)) {
                $results[$key] = $value;
            }
        }
        return $results;
    }
    private static function initOptions(array $options): array
    {
        $options['username'] ??= '';
        $options['password'] ??= '';
        $options['operationTimeout'] ??= 0;
        $options['configTimeout'] ??= 0;
        $options['configNodeTimeout'] ??= 0;
        $options['n1qlTimeout'] ??= 0;
        $options['httpTimeout'] ??= 0;
        $options['configDelay'] ??= 0;
        $options['htconfigIdleTimeout'] ??= 0;
        $options['durabilityInterval'] ??= 0;
        $options['durabilityTimeout'] ??= 0;
        return $options;
    }
    protected function doFetch(array $ids): iterable
    {
        $resultsCouchbase = $this->bucket->get($ids);
        $results = [];
        foreach ($resultsCouchbase as $key => $value) {
            if (null !== $value->error) {
                continue;
            }
            $results[$key] = $this->marshaller->unmarshall($value->value);
        }
        return $results;
    }
    protected function doHave(string $id): bool
    {
        return \false !== $this->bucket->get($id);
    }
    protected function doClear(string $namespace): bool
    {
        if ('' === $namespace) {
            $this->bucket->manager()->flush();
            return \true;
        }
        return \false;
    }
    protected function doDelete(array $ids): bool
    {
        $results = $this->bucket->remove(array_values($ids));
        foreach ($results as $key => $result) {
            if (null !== $result->error && static::KEY_NOT_FOUND !== $result->error->getCode()) {
                continue;
            }
            unset($results[$key]);
        }
        return 0 === \count($results);
    }
    protected function doSave(array $values, int $lifetime): array|bool
    {
        if (!$values = $this->marshaller->marshall($values, $failed)) {
            return $failed;
        }
        $lifetime = $this->normalizeExpiry($lifetime);
        $ko = [];
        foreach ($values as $key => $value) {
            $result = $this->bucket->upsert($key, $value, ['expiry' => $lifetime]);
            if (null !== $result->error) {
                $ko[$key] = $result;
            }
        }
        return [] === $ko ? \true : $ko;
    }
    private function normalizeExpiry(int $expiry): int
    {
        if ($expiry && $expiry > static::THIRTY_DAYS_IN_SECONDS) {
            $expiry += time();
        }
        return $expiry;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Cache\Adapter;

use _ContaoManager\Psr\Cache\CacheItemInterface;
use _ContaoManager\Symfony\Component\Cache\CacheItem;
use _ContaoManager\Symfony\Contracts\Cache\CacheInterface;
/**
 * @author Titouan Galopin <galopintitouan@gmail.com>
 */
class NullAdapter implements AdapterInterface, CacheInterface
{
    private static \Closure $createCacheItem;
    public function __construct()
    {
        self::$createCacheItem ??= \Closure::bind(static function ($key) {
            $item = new CacheItem();
            $item->key = $key;
            $item->isHit = \false;
            return $item;
        }, null, CacheItem::class);
    }
    public function get(string $key, callable $callback, ?float $beta = null, ?array &$metadata = null): mixed
    {
        $save = \true;
        return $callback((self::$createCacheItem)($key), $save);
    }
    public function getItem(mixed $key): CacheItem
    {
        return (self::$createCacheItem)($key);
    }
    public function getItems(array $keys = []): iterable
    {
        return $this->generateItems($keys);
    }
    public function hasItem(mixed $key): bool
    {
        return \false;
    }
    public function clear(string $prefix = ''): bool
    {
        return \true;
    }
    public function deleteItem(mixed $key): bool
    {
        return \true;
    }
    public function deleteItems(array $keys): bool
    {
        return \true;
    }
    public function save(CacheItemInterface $item): bool
    {
        return \true;
    }
    public function saveDeferred(CacheItemInterface $item): bool
    {
        return \true;
    }
    public function commit(): bool
    {
        return \true;
    }
    public function delete(string $key): bool
    {
        return $this->deleteItem($key);
    }
    private function generateItems(array $keys): \Generator
    {
        $f = self::$createCacheItem;
        foreach ($keys as $key) {
            yield $key => $f($key);
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Cache\Adapter;

/**
 * @author Lars Strojny <lars@strojny.net>
 */
final class ParameterNormalizer
{
    public static function normalizeDuration(string $duration): int
    {
        if (is_numeric($duration)) {
            return $duration;
        }
        if (\false !== $time = strtotime($duration, 0)) {
            return $time;
        }
        try {
            return \DateTimeImmutable::createFromFormat('U', 0)->add(new \DateInterval($duration))->getTimestamp();
        } catch (\Exception $e) {
            throw new \InvalidArgumentException(\sprintf('Cannot parse date interval "%s".', $duration), 0, $e);
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Cache\Adapter;

use _ContaoManager\Psr\Cache\CacheItemInterface;
use _ContaoManager\Psr\Cache\InvalidArgumentException;
use _ContaoManager\Psr\Log\LoggerAwareInterface;
use _ContaoManager\Psr\Log\LoggerAwareTrait;
use _ContaoManager\Symfony\Component\Cache\CacheItem;
use _ContaoManager\Symfony\Component\Cache\PruneableInterface;
use _ContaoManager\Symfony\Component\Cache\ResettableInterface;
use _ContaoManager\Symfony\Component\Cache\Traits\ContractsTrait;
use _ContaoManager\Symfony\Contracts\Cache\TagAwareCacheInterface;
/**
 * Implements simple and robust tag-based invalidation suitable for use with volatile caches.
 *
 * This adapter works by storing a version for each tags. When saving an item, it is stored together with its tags and
 * their corresponding versions. When retrieving an item, those tag versions are compared to the current version of
 * each tags. Invalidation is achieved by deleting tags, thereby ensuring that their versions change even when the
 * storage is out of space. When versions of non-existing tags are requested for item commits, this adapter assigns a
 * new random version to them.
 *
 * @author Nicolas Grekas <p@tchwork.com>
 * @author Sergey Belyshkin <sbelyshkin@gmail.com>
 */
class TagAwareAdapter implements TagAwareAdapterInterface, TagAwareCacheInterface, PruneableInterface, ResettableInterface, LoggerAwareInterface
{
    use ContractsTrait;
    use LoggerAwareTrait;
    public const TAGS_PREFIX = "\x01tags\x01";
    private array $deferred = [];
    private AdapterInterface $pool;
    private AdapterInterface $tags;
    private array $knownTagVersions = [];
    private float $knownTagVersionsTtl;
    private static \Closure $setCacheItemTags;
    private static \Closure $setTagVersions;
    private static \Closure $getTagsByKey;
    private static \Closure $saveTags;
    public function __construct(AdapterInterface $itemsPool, ?AdapterInterface $tagsPool = null, float $knownTagVersionsTtl = 0.15)
    {
        $this->pool = $itemsPool;
        $this->tags = $tagsPool ?? $itemsPool;
        $this->knownTagVersionsTtl = $knownTagVersionsTtl;
        self::$setCacheItemTags ??= \Closure::bind(static function (array $items, array $itemTags) {
            foreach ($items as $key => $item) {
                $item->isTaggable = \true;
                if (isset($itemTags[$key])) {
                    $tags = array_keys($itemTags[$key]);
                    $item->metadata[CacheItem::METADATA_TAGS] = array_combine($tags, $tags);
                } else {
                    $item->value = null;
                    $item->isHit = \false;
                    $item->metadata = [];
                }
            }
            return $items;
        }, null, CacheItem::class);
        self::$setTagVersions ??= \Closure::bind(static function (array $items, array $tagVersions) {
            foreach ($items as $item) {
                $item->newMetadata[CacheItem::METADATA_TAGS] = array_intersect_key($tagVersions, $item->newMetadata[CacheItem::METADATA_TAGS] ?? []);
            }
        }, null, CacheItem::class);
        self::$getTagsByKey ??= \Closure::bind(static function ($deferred) {
            $tagsByKey = [];
            foreach ($deferred as $key => $item) {
                $tagsByKey[$key] = $item->newMetadata[CacheItem::METADATA_TAGS] ?? [];
                $item->metadata = $item->newMetadata;
            }
            return $tagsByKey;
        }, null, CacheItem::class);
        self::$saveTags ??= \Closure::bind(static function (AdapterInterface $tagsAdapter, array $tags) {
            ksort($tags);
            foreach ($tags as $v) {
                $v->expiry = 0;
                $tagsAdapter->saveDeferred($v);
            }
            return $tagsAdapter->commit();
        }, null, CacheItem::class);
    }
    public function invalidateTags(array $tags): bool
    {
        $ids = [];
        foreach ($tags as $tag) {
            \assert('' !== CacheItem::validateKey($tag));
            unset($this->knownTagVersions[$tag]);
            $ids[] = $tag . static::TAGS_PREFIX;
        }
        return !$tags || $this->tags->deleteItems($ids);
    }
    public function hasItem(mixed $key): bool
    {
        return $this->getItem($key)->isHit();
    }
    public function getItem(mixed $key): CacheItem
    {
        foreach ($this->getItems([$key]) as $item) {
            return $item;
        }
    }
    public function getItems(array $keys = []): iterable
    {
        $tagKeys = [];
        $commit = \false;
        foreach ($keys as $key) {
            if ('' !== $key && \is_string($key)) {
                $commit = $commit || isset($this->deferred[$key]);
            }
        }
        if ($commit) {
            $this->commit();
        }
        try {
            $items = $this->pool->getItems($keys);
        } catch (InvalidArgumentException $e) {
            $this->pool->getItems($keys);
            // Should throw an exception
            throw $e;
        }
        $bufferedItems = $itemTags = [];
        foreach ($items as $key => $item) {
            if (null !== $tags = $item->getMetadata()[CacheItem::METADATA_TAGS] ?? null) {
                $itemTags[$key] = $tags;
            }
            $bufferedItems[$key] = $item;
            if (null === $tags) {
                $key = "\x00tags\x00" . $key;
                $tagKeys[$key] = $key;
                // BC with pools populated before v6.1
            }
        }
        if ($tagKeys) {
            foreach ($this->pool->getItems($tagKeys) as $key => $item) {
                if ($item->isHit()) {
                    $itemTags[substr($key, \strlen("\x00tags\x00"))] = $item->get() ?: [];
                }
            }
        }
        $tagVersions = $this->getTagVersions($itemTags, \false);
        foreach ($itemTags as $key => $tags) {
            foreach ($tags as $tag => $version) {
                if ($tagVersions[$tag] !== $version) {
                    unset($itemTags[$key]);
                    continue 2;
                }
            }
        }
        $tagVersions = null;
        return (self::$setCacheItemTags)($bufferedItems, $itemTags);
    }
    public function clear(string $prefix = ''): bool
    {
        if ('' !== $prefix) {
            foreach ($this->deferred as $key => $item) {
                if (str_starts_with($key, $prefix)) {
                    unset($this->deferred[$key]);
                }
            }
        } else {
            $this->deferred = [];
        }
        if ($this->pool instanceof AdapterInterface) {
            return $this->pool->clear($prefix);
        }
        return $this->pool->clear();
    }
    public function deleteItem(mixed $key): bool
    {
        return $this->deleteItems([$key]);
    }
    public function deleteItems(array $keys): bool
    {
        foreach ($keys as $key) {
            if ('' !== $key && \is_string($key)) {
                $keys[] = "\x00tags\x00" . $key;
                // BC with pools populated before v6.1
            }
        }
        return $this->pool->deleteItems($keys);
    }
    public function save(CacheItemInterface $item): bool
    {
        if (!$item instanceof CacheItem) {
            return \false;
        }
        $this->deferred[$item->getKey()] = $item;
        return $this->commit();
    }
    public function saveDeferred(CacheItemInterface $item): bool
    {
        if (!$item instanceof CacheItem) {
            return \false;
        }
        $this->deferred[$item->getKey()] = $item;
        return \true;
    }
    public function commit(): bool
    {
        if (!$items = $this->deferred) {
            return \true;
        }
        $tagVersions = $this->getTagVersions((self::$getTagsByKey)($items), \true);
        (self::$setTagVersions)($items, $tagVersions);
        $ok = \true;
        foreach ($items as $key => $item) {
            if ($this->pool->saveDeferred($item)) {
                unset($this->deferred[$key]);
            } else {
                $ok = \false;
            }
        }
        $ok = $this->pool->commit() && $ok;
        $tagVersions = array_keys($tagVersions);
        (self::$setTagVersions)($items, array_combine($tagVersions, $tagVersions));
        return $ok;
    }
    public function prune(): bool
    {
        return $this->pool instanceof PruneableInterface && $this->pool->prune();
    }
    /**
     * @return void
     */
    public function reset()
    {
        $this->commit();
        $this->knownTagVersions = [];
        $this->pool instanceof ResettableInterface && $this->pool->reset();
        $this->tags instanceof ResettableInterface && $this->tags->reset();
    }
    public function __serialize(): array
    {
        throw new \BadMethodCallException('Cannot serialize ' . __CLASS__);
    }
    public function __unserialize(array $data): void
    {
        throw new \BadMethodCallException('Cannot unserialize ' . __CLASS__);
    }
    public function __destruct()
    {
        $this->commit();
    }
    private function getTagVersions(array $tagsByKey, bool $persistTags): array
    {
        $tagVersions = [];
        $fetchTagVersions = $persistTags;
        foreach ($tagsByKey as $tags) {
            $tagVersions += $tags;
            if ($fetchTagVersions) {
                continue;
            }
            foreach ($tags as $tag => $version) {
                if ($tagVersions[$tag] !== $version) {
                    $fetchTagVersions = \true;
                }
            }
        }
        if (!$tagVersions) {
            return [];
        }
        $now = microtime(\true);
        $tags = [];
        foreach ($tagVersions as $tag => $version) {
            $tags[$tag . static::TAGS_PREFIX] = $tag;
            $knownTagVersion = $this->knownTagVersions[$tag] ?? [0, null];
            if ($fetchTagVersions || $now > $knownTagVersion[0] || $knownTagVersion[1] !== $version) {
                // reuse previously fetched tag versions until the expiration
                $fetchTagVersions = \true;
            }
        }
        if (!$fetchTagVersions) {
            return $tagVersions;
        }
        $newTags = [];
        $newVersion = null;
        $expiration = $now + $this->knownTagVersionsTtl;
        foreach ($this->tags->getItems(array_keys($tags)) as $tag => $version) {
            unset($this->knownTagVersions[$tag = $tags[$tag]]);
            // update FIFO
            if (null !== $tagVersions[$tag] = $version->get()) {
                $this->knownTagVersions[$tag] = [$expiration, $tagVersions[$tag]];
            } elseif ($persistTags) {
                $newTags[$tag] = $version->set($newVersion ??= random_bytes(6));
                $tagVersions[$tag] = $newVersion;
                $this->knownTagVersions[$tag] = [$expiration, $newVersion];
            }
        }
        if ($newTags) {
            (self::$saveTags)($this->tags, $newTags);
        }
        while ($now > ($this->knownTagVersions[$tag = array_key_first($this->knownTagVersions) ?? ''][0] ?? \INF)) {
            unset($this->knownTagVersions[$tag]);
        }
        return $tagVersions;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Cache\Adapter;

use _ContaoManager\Symfony\Component\Cache\Exception\CacheException;
use _ContaoManager\Symfony\Component\Cache\Exception\InvalidArgumentException;
use _ContaoManager\Symfony\Component\Cache\PruneableInterface;
use _ContaoManager\Symfony\Component\Cache\Traits\CachedValueInterface;
use _ContaoManager\Symfony\Component\Cache\Traits\FilesystemCommonTrait;
use _ContaoManager\Symfony\Component\VarExporter\VarExporter;
/**
 * @author Piotr Stankowski <git@trakos.pl>
 * @author Nicolas Grekas <p@tchwork.com>
 * @author Rob Frawley 2nd <rmf@src.run>
 */
class PhpFilesAdapter extends AbstractAdapter implements PruneableInterface
{
    use FilesystemCommonTrait {
        doClear as private doCommonClear;
        doDelete as private doCommonDelete;
    }
    private \Closure $includeHandler;
    private bool $appendOnly;
    private array $values = [];
    private array $files = [];
    private static int $startTime;
    private static array $valuesCache = [];
    /**
     * @param $appendOnly Set to `true` to gain extra performance when the items stored in this pool never expire.
     *                    Doing so is encouraged because it fits perfectly OPcache's memory model.
     *
     * @throws CacheException if OPcache is not enabled
     */
    public function __construct(string $namespace = '', int $defaultLifetime = 0, ?string $directory = null, bool $appendOnly = \false)
    {
        $this->appendOnly = $appendOnly;
        self::$startTime ??= $_SERVER['REQUEST_TIME'] ?? time();
        parent::__construct('', $defaultLifetime);
        $this->init($namespace, $directory);
        $this->includeHandler = static function ($type, $msg, $file, $line) {
            throw new \ErrorException($msg, 0, $type, $file, $line);
        };
    }
    /**
     * @return bool
     */
    public static function isSupported()
    {
        self::$startTime ??= $_SERVER['REQUEST_TIME'] ?? time();
        return \function_exists('opcache_invalidate') && filter_var(\ini_get('opcache.enable'), \FILTER_VALIDATE_BOOL) && (!\in_array(\PHP_SAPI, ['cli', 'phpdbg', 'embed'], \true) || filter_var(\ini_get('opcache.enable_cli'), \FILTER_VALIDATE_BOOL));
    }
    public function prune(): bool
    {
        $time = time();
        $pruned = \true;
        $getExpiry = \true;
        set_error_handler($this->includeHandler);
        try {
            foreach ($this->scanHashDir($this->directory) as $file) {
                try {
                    if (\is_array($expiresAt = include $file)) {
                        $expiresAt = $expiresAt[0];
                    }
                } catch (\ErrorException $e) {
                    $expiresAt = $time;
                }
                if ($time >= $expiresAt) {
                    $pruned = ($this->doUnlink($file) || !file_exists($file)) && $pruned;
                }
            }
        } finally {
            restore_error_handler();
        }
        return $pruned;
    }
    protected function doFetch(array $ids): iterable
    {
        if ($this->appendOnly) {
            $now = 0;
            $missingIds = [];
        } else {
            $now = time();
            $missingIds = $ids;
            $ids = [];
        }
        $values = [];
        begin:
        $getExpiry = \false;
        foreach ($ids as $id) {
            if (null === $value = $this->values[$id] ?? null) {
                $missingIds[] = $id;
            } elseif ('N;' === $value) {
                $values[$id] = null;
            } elseif (!\is_object($value)) {
                $values[$id] = $value;
            } elseif ($value instanceof CachedValueInterface) {
                $values[$id] = $value->getValue();
            } elseif (!$value instanceof LazyValue) {
                $values[$id] = $value;
            } elseif (\false === $values[$id] = include $value->file) {
                unset($values[$id], $this->values[$id]);
                $missingIds[] = $id;
            }
            if (!$this->appendOnly) {
                unset($this->values[$id]);
            }
        }
        if (!$missingIds) {
            return $values;
        }
        set_error_handler($this->includeHandler);
        try {
            $getExpiry = \true;
            foreach ($missingIds as $k => $id) {
                try {
                    $file = $this->files[$id] ??= $this->getFile($id);
                    if (isset(self::$valuesCache[$file])) {
                        [$expiresAt, $this->values[$id]] = self::$valuesCache[$file];
                    } elseif (\is_array($expiresAt = include $file)) {
                        if ($this->appendOnly) {
                            self::$valuesCache[$file] = $expiresAt;
                        }
                        [$expiresAt, $this->values[$id]] = $expiresAt;
                    } elseif ($now < $expiresAt) {
                        $this->values[$id] = new LazyValue($file);
                    }
                    if ($now >= $expiresAt) {
                        unset($this->values[$id], $missingIds[$k], self::$valuesCache[$file]);
                    }
                } catch (\ErrorException) {
                    unset($missingIds[$k]);
                }
            }
        } finally {
            restore_error_handler();
        }
        $ids = $missingIds;
        $missingIds = [];
        goto begin;
    }
    protected function doHave(string $id): bool
    {
        if ($this->appendOnly && isset($this->values[$id])) {
            return \true;
        }
        set_error_handler($this->includeHandler);
        try {
            $file = $this->files[$id] ??= $this->getFile($id);
            $getExpiry = \true;
            if (isset(self::$valuesCache[$file])) {
                [$expiresAt, $value] = self::$valuesCache[$file];
            } elseif (\is_array($expiresAt = include $file)) {
                if ($this->appendOnly) {
                    self::$valuesCache[$file] = $expiresAt;
                }
                [$expiresAt, $value] = $expiresAt;
            } elseif ($this->appendOnly) {
                $value = new LazyValue($file);
            }
        } catch (\ErrorException) {
            return \false;
        } finally {
            restore_error_handler();
        }
        if ($this->appendOnly) {
            $now = 0;
            $this->values[$id] = $value;
        } else {
            $now = time();
        }
        return $now < $expiresAt;
    }
    protected function doSave(array $values, int $lifetime): array|bool
    {
        $ok = \true;
        $expiry = $lifetime ? time() + $lifetime : 'PHP_INT_MAX';
        $allowCompile = self::isSupported();
        foreach ($values as $key => $value) {
            unset($this->values[$key]);
            $isStaticValue = \true;
            if (null === $value) {
                $value = "'N;'";
            } elseif (\is_object($value) || \is_array($value)) {
                try {
                    $value = VarExporter::export($value, $isStaticValue);
                } catch (\Exception $e) {
                    throw new InvalidArgumentException(\sprintf('Cache key "%s" has non-serializable "%s" value.', $key, get_debug_type($value)), 0, $e);
                }
            } elseif (\is_string($value)) {
                // Wrap "N;" in a closure to not confuse it with an encoded `null`
                if ('N;' === $value) {
                    $isStaticValue = \false;
                }
                $value = var_export($value, \true);
            } elseif (!\is_scalar($value)) {
                throw new InvalidArgumentException(\sprintf('Cache key "%s" has non-serializable "%s" value.', $key, get_debug_type($value)));
            } else {
                $value = var_export($value, \true);
            }
            $encodedKey = rawurlencode($key);
            if ($isStaticValue) {
                $value = "return [{$expiry}, {$value}];";
            } elseif ($this->appendOnly) {
                $value = "return [{$expiry}, new class() implements \\" . CachedValueInterface::class . " { public function getValue(): mixed { return {$value}; } }];";
            } else {
                // We cannot use a closure here because of https://bugs.php.net/76982
                $value = str_replace('\Symfony\Component\VarExporter\Internal\\', '', $value);
                $value = "namespace Symfony\\Component\\VarExporter\\Internal;\n\nreturn \$getExpiry ? {$expiry} : {$value};";
            }
            $file = $this->files[$key] = $this->getFile($key, \true);
            // Since OPcache only compiles files older than the script execution start, set the file's mtime in the past
            $ok = $this->write($file, "<?php //{$encodedKey}\n\n{$value}\n", self::$startTime - 10) && $ok;
            if ($allowCompile) {
                @opcache_invalidate($file, \true);
                @opcache_compile_file($file);
            }
            unset(self::$valuesCache[$file]);
        }
        if (!$ok && !is_writable($this->directory)) {
            throw new CacheException(\sprintf('Cache directory is not writable (%s).', $this->directory));
        }
        return $ok;
    }
    protected function doClear(string $namespace): bool
    {
        $this->values = [];
        return $this->doCommonClear($namespace);
    }
    protected function doDelete(array $ids): bool
    {
        foreach ($ids as $id) {
            unset($this->values[$id]);
        }
        return $this->doCommonDelete($ids);
    }
    /**
     * @return bool
     */
    protected function doUnlink(string $file)
    {
        unset(self::$valuesCache[$file]);
        if (self::isSupported()) {
            @opcache_invalidate($file, \true);
        }
        return @unlink($file);
    }
    private function getFileKey(string $file): string
    {
        if (!$h = @fopen($file, 'r')) {
            return '';
        }
        $encodedKey = substr(fgets($h), 8);
        fclose($h);
        return rawurldecode(rtrim($encodedKey));
    }
}
/**
 * @internal
 */
class LazyValue
{
    public string $file;
    public function __construct(string $file)
    {
        $this->file = $file;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Cache\Adapter;

use _ContaoManager\Doctrine\DBAL\ArrayParameterType;
use _ContaoManager\Doctrine\DBAL\Configuration;
use _ContaoManager\Doctrine\DBAL\Connection;
use _ContaoManager\Doctrine\DBAL\Driver\ServerInfoAwareConnection;
use _ContaoManager\Doctrine\DBAL\DriverManager;
use _ContaoManager\Doctrine\DBAL\Exception as DBALException;
use _ContaoManager\Doctrine\DBAL\Exception\TableNotFoundException;
use _ContaoManager\Doctrine\DBAL\ParameterType;
use _ContaoManager\Doctrine\DBAL\Schema\DefaultSchemaManagerFactory;
use _ContaoManager\Doctrine\DBAL\Schema\Schema;
use _ContaoManager\Doctrine\DBAL\ServerVersionProvider;
use _ContaoManager\Doctrine\DBAL\Tools\DsnParser;
use _ContaoManager\Symfony\Component\Cache\Exception\InvalidArgumentException;
use _ContaoManager\Symfony\Component\Cache\Marshaller\DefaultMarshaller;
use _ContaoManager\Symfony\Component\Cache\Marshaller\MarshallerInterface;
use _ContaoManager\Symfony\Component\Cache\PruneableInterface;
class DoctrineDbalAdapter extends AbstractAdapter implements PruneableInterface
{
    private const MAX_KEY_LENGTH = 255;
    private static int $savepointCounter = 0;
    private MarshallerInterface $marshaller;
    private Connection $conn;
    private string $platformName;
    private string $serverVersion;
    private string $table = 'cache_items';
    private string $idCol = 'item_id';
    private string $dataCol = 'item_data';
    private string $lifetimeCol = 'item_lifetime';
    private string $timeCol = 'item_time';
    private string $namespace;
    /**
     * You can either pass an existing database Doctrine DBAL Connection or
     * a DSN string that will be used to connect to the database.
     *
     * The cache table is created automatically when possible.
     * Otherwise, use the createTable() method.
     *
     * List of available options:
     *  * db_table: The name of the table [default: cache_items]
     *  * db_id_col: The column where to store the cache id [default: item_id]
     *  * db_data_col: The column where to store the cache data [default: item_data]
     *  * db_lifetime_col: The column where to store the lifetime [default: item_lifetime]
     *  * db_time_col: The column where to store the timestamp [default: item_time]
     *
     * @throws InvalidArgumentException When namespace contains invalid characters
     */
    public function __construct(Connection|string $connOrDsn, string $namespace = '', int $defaultLifetime = 0, array $options = [], ?MarshallerInterface $marshaller = null)
    {
        if (isset($namespace[0]) && preg_match('#[^-+.A-Za-z0-9]#', $namespace, $match)) {
            throw new InvalidArgumentException(\sprintf('Namespace contains "%s" but only characters in [-+.A-Za-z0-9] are allowed.', $match[0]));
        }
        if ($connOrDsn instanceof Connection) {
            $this->conn = $connOrDsn;
        } else {
            if (!class_exists(DriverManager::class)) {
                throw new InvalidArgumentException('Failed to parse DSN. Try running "composer require doctrine/dbal".');
            }
            if (class_exists(DsnParser::class)) {
                $params = (new DsnParser(['db2' => 'ibm_db2', 'mssql' => 'pdo_sqlsrv', 'mysql' => 'pdo_mysql', 'mysql2' => 'pdo_mysql', 'postgres' => 'pdo_pgsql', 'postgresql' => 'pdo_pgsql', 'pgsql' => 'pdo_pgsql', 'sqlite' => 'pdo_sqlite', 'sqlite3' => 'pdo_sqlite']))->parse($connOrDsn);
            } else {
                $params = ['url' => $connOrDsn];
            }
            $config = new Configuration();
            if (class_exists(DefaultSchemaManagerFactory::class)) {
                $config->setSchemaManagerFactory(new DefaultSchemaManagerFactory());
            }
            $this->conn = DriverManager::getConnection($params, $config);
        }
        $this->maxIdLength = self::MAX_KEY_LENGTH;
        $this->table = $options['db_table'] ?? $this->table;
        $this->idCol = $options['db_id_col'] ?? $this->idCol;
        $this->dataCol = $options['db_data_col'] ?? $this->dataCol;
        $this->lifetimeCol = $options['db_lifetime_col'] ?? $this->lifetimeCol;
        $this->timeCol = $options['db_time_col'] ?? $this->timeCol;
        $this->namespace = $namespace;
        $this->marshaller = $marshaller ?? new DefaultMarshaller();
        parent::__construct($namespace, $defaultLifetime);
    }
    /**
     * Creates the table to store cache items which can be called once for setup.
     *
     * Cache ID are saved in a column of maximum length 255. Cache data is
     * saved in a BLOB.
     *
     * @throws DBALException When the table already exists
     */
    public function createTable(): void
    {
        $schema = new Schema();
        $this->addTableToSchema($schema);
        foreach ($schema->toSql($this->conn->getDatabasePlatform()) as $sql) {
            $this->conn->executeStatement($sql);
        }
    }
    /**
     * @param \Closure $isSameDatabase
     */
    public function configureSchema(Schema $schema, Connection $forConnection): void
    {
        if ($schema->hasTable($this->table)) {
            return;
        }
        $isSameDatabase = 2 < \func_num_args() ? func_get_arg(2) : static fn() => \false;
        if ($forConnection !== $this->conn && !$isSameDatabase($this->conn->executeStatement(...))) {
            return;
        }
        $this->addTableToSchema($schema);
    }
    public function prune(): bool
    {
        $deleteSql = "DELETE FROM {$this->table} WHERE {$this->lifetimeCol} + {$this->timeCol} <= ?";
        $params = [time()];
        $paramTypes = [ParameterType::INTEGER];
        if ('' !== $this->namespace) {
            $deleteSql .= " AND {$this->idCol} LIKE ?";
            $params[] = \sprintf('%s%%', $this->namespace);
            $paramTypes[] = ParameterType::STRING;
        }
        try {
            $this->conn->executeStatement($deleteSql, $params, $paramTypes);
        } catch (TableNotFoundException) {
        }
        return \true;
    }
    protected function doFetch(array $ids): iterable
    {
        $now = time();
        $expired = [];
        $sql = "SELECT {$this->idCol}, CASE WHEN {$this->lifetimeCol} IS NULL OR {$this->lifetimeCol} + {$this->timeCol} > ? THEN {$this->dataCol} ELSE NULL END FROM {$this->table} WHERE {$this->idCol} IN (?)";
        $result = $this->conn->executeQuery($sql, [$now, $ids], [ParameterType::INTEGER, class_exists(ArrayParameterType::class) ? ArrayParameterType::STRING : Connection::PARAM_STR_ARRAY])->iterateNumeric();
        foreach ($result as $row) {
            if (null === $row[1]) {
                $expired[] = $row[0];
            } else {
                yield $row[0] => $this->marshaller->unmarshall(\is_resource($row[1]) ? stream_get_contents($row[1]) : $row[1]);
            }
        }
        if ($expired) {
            $sql = "DELETE FROM {$this->table} WHERE {$this->lifetimeCol} + {$this->timeCol} <= ? AND {$this->idCol} IN (?)";
            $this->conn->executeStatement($sql, [$now, $expired], [ParameterType::INTEGER, class_exists(ArrayParameterType::class) ? ArrayParameterType::STRING : Connection::PARAM_STR_ARRAY]);
        }
    }
    protected function doHave(string $id): bool
    {
        $sql = "SELECT 1 FROM {$this->table} WHERE {$this->idCol} = ? AND ({$this->lifetimeCol} IS NULL OR {$this->lifetimeCol} + {$this->timeCol} > ?)";
        $result = $this->conn->executeQuery($sql, [$id, time()], [ParameterType::STRING, ParameterType::INTEGER]);
        return (bool) $result->fetchOne();
    }
    protected function doClear(string $namespace): bool
    {
        if ('' === $namespace) {
            $sql = $this->conn->getDatabasePlatform()->getTruncateTableSQL($this->table);
        } else {
            $sql = "DELETE FROM {$this->table} WHERE {$this->idCol} LIKE '{$namespace}%'";
        }
        try {
            $this->conn->executeStatement($sql);
        } catch (TableNotFoundException) {
        }
        return \true;
    }
    protected function doDelete(array $ids): bool
    {
        $sql = "DELETE FROM {$this->table} WHERE {$this->idCol} IN (?)";
        try {
            $this->conn->executeStatement($sql, [array_values($ids)], [class_exists(ArrayParameterType::class) ? ArrayParameterType::STRING : Connection::PARAM_STR_ARRAY]);
        } catch (TableNotFoundException) {
        }
        return \true;
    }
    protected function doSave(array $values, int $lifetime): array|bool
    {
        if (!$values = $this->marshaller->marshall($values, $failed)) {
            return $failed;
        }
        if ($this->conn->isTransactionActive() && $this->conn->getDatabasePlatform()->supportsSavepoints()) {
            $savepoint = 'cache_save_' . ++self::$savepointCounter;
            try {
                $this->conn->createSavepoint($savepoint);
                $failed = $this->doSaveInner($values, $lifetime, $failed);
                $this->conn->releaseSavepoint($savepoint);
                return $failed;
            } catch (\Throwable $e) {
                $this->conn->rollbackSavepoint($savepoint);
                throw $e;
            }
        }
        return $this->doSaveInner($values, $lifetime, $failed);
    }
    private function doSaveInner(array $values, int $lifetime, array $failed): array|bool
    {
        $platformName = $this->getPlatformName();
        $insertSql = "INSERT INTO {$this->table} ({$this->idCol}, {$this->dataCol}, {$this->lifetimeCol}, {$this->timeCol}) VALUES (?, ?, ?, ?)";
        switch (\true) {
            case 'mysql' === $platformName:
                $sql = $insertSql . " ON DUPLICATE KEY UPDATE {$this->dataCol} = VALUES({$this->dataCol}), {$this->lifetimeCol} = VALUES({$this->lifetimeCol}), {$this->timeCol} = VALUES({$this->timeCol})";
                break;
            case 'oci' === $platformName:
                // DUAL is Oracle specific dummy table
                $sql = "MERGE INTO {$this->table} USING DUAL ON ({$this->idCol} = ?) " . "WHEN NOT MATCHED THEN INSERT ({$this->idCol}, {$this->dataCol}, {$this->lifetimeCol}, {$this->timeCol}) VALUES (?, ?, ?, ?) " . "WHEN MATCHED THEN UPDATE SET {$this->dataCol} = ?, {$this->lifetimeCol} = ?, {$this->timeCol} = ?";
                break;
            case 'sqlsrv' === $platformName && version_compare($this->getServerVersion(), '10', '>='):
                // MERGE is only available since SQL Server 2008 and must be terminated by semicolon
                // It also requires HOLDLOCK according to http://weblogs.sqlteam.com/dang/archive/2009/01/31/UPSERT-Race-Condition-With-MERGE.aspx
                $sql = "MERGE INTO {$this->table} WITH (HOLDLOCK) USING (SELECT 1 AS dummy) AS src ON ({$this->idCol} = ?) " . "WHEN NOT MATCHED THEN INSERT ({$this->idCol}, {$this->dataCol}, {$this->lifetimeCol}, {$this->timeCol}) VALUES (?, ?, ?, ?) " . "WHEN MATCHED THEN UPDATE SET {$this->dataCol} = ?, {$this->lifetimeCol} = ?, {$this->timeCol} = ?;";
                break;
            case 'sqlite' === $platformName:
                $sql = 'INSERT OR REPLACE' . substr($insertSql, 6);
                break;
            case 'pgsql' === $platformName && version_compare($this->getServerVersion(), '9.5', '>='):
                $sql = $insertSql . " ON CONFLICT ({$this->idCol}) DO UPDATE SET ({$this->dataCol}, {$this->lifetimeCol}, {$this->timeCol}) = (EXCLUDED.{$this->dataCol}, EXCLUDED.{$this->lifetimeCol}, EXCLUDED.{$this->timeCol})";
                break;
            default:
                $platformName = null;
                $sql = "UPDATE {$this->table} SET {$this->dataCol} = ?, {$this->lifetimeCol} = ?, {$this->timeCol} = ? WHERE {$this->idCol} = ?";
                break;
        }
        $now = time();
        $lifetime = $lifetime ?: null;
        try {
            $stmt = $this->conn->prepare($sql);
        } catch (TableNotFoundException) {
            if (!$this->conn->isTransactionActive() || \in_array($platformName, ['pgsql', 'sqlite', 'sqlsrv'], \true)) {
                $this->createTable();
            }
            $stmt = $this->conn->prepare($sql);
        }
        if ('sqlsrv' === $platformName || 'oci' === $platformName) {
            $bind = static function ($id, $data) use ($stmt) {
                $stmt->bindValue(1, $id);
                $stmt->bindValue(2, $id);
                $stmt->bindValue(3, $data, ParameterType::LARGE_OBJECT);
                $stmt->bindValue(6, $data, ParameterType::LARGE_OBJECT);
            };
            $stmt->bindValue(4, $lifetime, ParameterType::INTEGER);
            $stmt->bindValue(5, $now, ParameterType::INTEGER);
            $stmt->bindValue(7, $lifetime, ParameterType::INTEGER);
            $stmt->bindValue(8, $now, ParameterType::INTEGER);
        } elseif (null !== $platformName) {
            $bind = static function ($id, $data) use ($stmt) {
                $stmt->bindValue(1, $id);
                $stmt->bindValue(2, $data, ParameterType::LARGE_OBJECT);
            };
            $stmt->bindValue(3, $lifetime, ParameterType::INTEGER);
            $stmt->bindValue(4, $now, ParameterType::INTEGER);
        } else {
            $stmt->bindValue(2, $lifetime, ParameterType::INTEGER);
            $stmt->bindValue(3, $now, ParameterType::INTEGER);
            $insertStmt = $this->conn->prepare($insertSql);
            $insertStmt->bindValue(3, $lifetime, ParameterType::INTEGER);
            $insertStmt->bindValue(4, $now, ParameterType::INTEGER);
            $bind = static function ($id, $data) use ($stmt, $insertStmt) {
                $stmt->bindValue(1, $data, ParameterType::LARGE_OBJECT);
                $stmt->bindValue(4, $id);
                $insertStmt->bindValue(1, $id);
                $insertStmt->bindValue(2, $data, ParameterType::LARGE_OBJECT);
            };
        }
        foreach ($values as $id => $data) {
            $bind($id, $data);
            try {
                $rowCount = $stmt->executeStatement();
            } catch (TableNotFoundException) {
                if (!$this->conn->isTransactionActive() || \in_array($platformName, ['pgsql', 'sqlite', 'sqlsrv'], \true)) {
                    $this->createTable();
                }
                $rowCount = $stmt->executeStatement();
            }
            if (null === $platformName && 0 === $rowCount) {
                try {
                    $insertStmt->executeStatement();
                } catch (DBALException) {
                    // A concurrent write won, let it be
                }
            }
        }
        return $failed;
    }
    /**
     * @internal
     */
    protected function getId(mixed $key): string
    {
        if ('pgsql' !== $this->platformName ??= $this->getPlatformName()) {
            return parent::getId($key);
        }
        if (str_contains($key, "\x00") || str_contains($key, '%') || !preg_match('//u', $key)) {
            $key = rawurlencode($key);
        }
        return parent::getId($key);
    }
    private function getPlatformName(): string
    {
        if (isset($this->platformName)) {
            return $this->platformName;
        }
        $platform = $this->conn->getDatabasePlatform();
        return $this->platformName = match (\true) {
            $platform instanceof \_ContaoManager\Doctrine\DBAL\Platforms\MySQLPlatform, $platform instanceof \_ContaoManager\Doctrine\DBAL\Platforms\MySQL57Platform => 'mysql',
            $platform instanceof \_ContaoManager\Doctrine\DBAL\Platforms\SqlitePlatform => 'sqlite',
            $platform instanceof \_ContaoManager\Doctrine\DBAL\Platforms\PostgreSQLPlatform, $platform instanceof \_ContaoManager\Doctrine\DBAL\Platforms\PostgreSQL94Platform => 'pgsql',
            $platform instanceof \_ContaoManager\Doctrine\DBAL\Platforms\OraclePlatform => 'oci',
            $platform instanceof \_ContaoManager\Doctrine\DBAL\Platforms\SQLServerPlatform, $platform instanceof \_ContaoManager\Doctrine\DBAL\Platforms\SQLServer2012Platform => 'sqlsrv',
            default => $platform::class,
        };
    }
    private function getServerVersion(): string
    {
        if (isset($this->serverVersion)) {
            return $this->serverVersion;
        }
        if ($this->conn instanceof ServerVersionProvider || $this->conn instanceof ServerInfoAwareConnection) {
            return $this->serverVersion = $this->conn->getServerVersion();
        }
        // The condition should be removed once support for DBAL <3.3 is dropped
        $conn = method_exists($this->conn, 'getNativeConnection') ? $this->conn->getNativeConnection() : $this->conn->getWrappedConnection();
        return $this->serverVersion = $conn->getAttribute(\PDO::ATTR_SERVER_VERSION);
    }
    private function addTableToSchema(Schema $schema): void
    {
        $types = ['mysql' => 'binary', 'sqlite' => 'text'];
        $table = $schema->createTable($this->table);
        $table->addColumn($this->idCol, $types[$this->getPlatformName()] ?? 'string', ['length' => 255]);
        $table->addColumn($this->dataCol, 'blob', ['length' => 16777215]);
        $table->addColumn($this->lifetimeCol, 'integer', ['unsigned' => \true, 'notnull' => \false]);
        $table->addColumn($this->timeCol, 'integer', ['unsigned' => \true]);
        $table->setPrimaryKey([$this->idCol]);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Cache\Adapter;

use _ContaoManager\Psr\Cache\InvalidArgumentException;
/**
 * Interface for invalidating cached items using tags.
 *
 * @author Nicolas Grekas <p@tchwork.com>
 */
interface TagAwareAdapterInterface extends AdapterInterface
{
    /**
     * Invalidates cached items using tags.
     *
     * @param string[] $tags An array of tags to invalidate
     *
     * @throws InvalidArgumentException When $tags is not valid
     */
    public function invalidateTags(array $tags): bool;
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Cache\Adapter;

use _ContaoManager\Symfony\Component\Cache\Exception\CacheException;
use _ContaoManager\Symfony\Component\Cache\Exception\InvalidArgumentException;
use _ContaoManager\Symfony\Component\Cache\Marshaller\DefaultMarshaller;
use _ContaoManager\Symfony\Component\Cache\Marshaller\MarshallerInterface;
/**
 * @author Rob Frawley 2nd <rmf@src.run>
 * @author Nicolas Grekas <p@tchwork.com>
 */
class MemcachedAdapter extends AbstractAdapter
{
    /**
     * We are replacing characters that are illegal in Memcached keys with reserved characters from
     * {@see \Symfony\Contracts\Cache\ItemInterface::RESERVED_CHARACTERS} that are legal in Memcached.
     * Note: don’t use {@see AbstractAdapter::NS_SEPARATOR}.
     */
    private const RESERVED_MEMCACHED = " \n\r\t\v\f\x00";
    private const RESERVED_PSR6 = '@()\{}/';
    private const MAX_KEY_LENGTH = 250;
    private MarshallerInterface $marshaller;
    private \Memcached $client;
    private \Memcached $lazyClient;
    /**
     * Using a MemcachedAdapter with a TagAwareAdapter for storing tags is discouraged.
     * Using a RedisAdapter is recommended instead. If you cannot do otherwise, be aware that:
     * - the Memcached::OPT_BINARY_PROTOCOL must be enabled
     *   (that's the default when using MemcachedAdapter::createConnection());
     * - tags eviction by Memcached's LRU algorithm will break by-tags invalidation;
     *   your Memcached memory should be large enough to never trigger LRU.
     *
     * Using a MemcachedAdapter as a pure items store is fine.
     */
    public function __construct(\Memcached $client, string $namespace = '', int $defaultLifetime = 0, ?MarshallerInterface $marshaller = null)
    {
        if (!static::isSupported()) {
            throw new CacheException('Memcached > 3.1.5 is required.');
        }
        $this->maxIdLength = self::MAX_KEY_LENGTH;
        if ('Memcached' === $client::class) {
            $opt = $client->getOption(\Memcached::OPT_SERIALIZER);
            if (\Memcached::SERIALIZER_PHP !== $opt && \Memcached::SERIALIZER_IGBINARY !== $opt) {
                throw new CacheException('MemcachedAdapter: "serializer" option must be "php" or "igbinary".');
            }
            $this->maxIdLength -= \strlen($client->getOption(\Memcached::OPT_PREFIX_KEY));
            $this->client = $client;
        } else {
            $this->lazyClient = $client;
        }
        parent::__construct($namespace, $defaultLifetime);
        $this->enableVersioning();
        $this->marshaller = $marshaller ?? new DefaultMarshaller();
    }
    /**
     * @return bool
     */
    public static function isSupported()
    {
        return \extension_loaded('memcached') && version_compare(phpversion('memcached'), '3.1.6', '>=');
    }
    /**
     * Creates a Memcached instance.
     *
     * By default, the binary protocol, no block, and libketama compatible options are enabled.
     *
     * Examples for servers:
     * - 'memcached://user:pass@localhost?weight=33'
     * - [['localhost', 11211, 33]]
     *
     * @param array[]|string|string[] $servers An array of servers, a DSN, or an array of DSNs
     *
     * @throws \ErrorException When invalid options or servers are provided
     */
    public static function createConnection(
        #[\SensitiveParameter]
        array|string $servers,
        array $options = []
    ): \Memcached
    {
        if (\is_string($servers)) {
            $servers = [$servers];
        }
        if (!static::isSupported()) {
            throw new CacheException('Memcached > 3.1.5 is required.');
        }
        set_error_handler(static fn($type, $msg, $file, $line) => throw new \ErrorException($msg, 0, $type, $file, $line));
        try {
            $client = new \Memcached($options['persistent_id'] ?? null);
            $username = $options['username'] ?? null;
            $password = $options['password'] ?? null;
            // parse any DSN in $servers
            foreach ($servers as $i => $dsn) {
                if (\is_array($dsn)) {
                    continue;
                }
                if (!str_starts_with($dsn, 'memcached:')) {
                    throw new InvalidArgumentException('Invalid Memcached DSN: it does not start with "memcached:".');
                }
                $params = preg_replace_callback('#^memcached:(//)?(?:([^@]*+)@)?#', function ($m) use (&$username, &$password) {
                    if (!empty($m[2])) {
                        [$username, $password] = explode(':', $m[2], 2) + [1 => null];
                        $username = rawurldecode($username);
                        $password = null !== $password ? rawurldecode($password) : null;
                    }
                    return 'file:' . ($m[1] ?? '');
                }, $dsn);
                if (\false === $params = parse_url($params)) {
                    throw new InvalidArgumentException('Invalid Memcached DSN.');
                }
                $query = $hosts = [];
                if (isset($params['query'])) {
                    parse_str($params['query'], $query);
                    if (isset($query['host'])) {
                        if (!\is_array($hosts = $query['host'])) {
                            throw new InvalidArgumentException('Invalid Memcached DSN: query parameter "host" must be an array.');
                        }
                        foreach ($hosts as $host => $weight) {
                            if (\false === $port = strrpos($host, ':')) {
                                $hosts[$host] = [$host, 11211, (int) $weight];
                            } else {
                                $hosts[$host] = [substr($host, 0, $port), (int) substr($host, 1 + $port), (int) $weight];
                            }
                        }
                        $hosts = array_values($hosts);
                        unset($query['host']);
                    }
                    if ($hosts && !isset($params['host']) && !isset($params['path'])) {
                        unset($servers[$i]);
                        $servers = array_merge($servers, $hosts);
                        continue;
                    }
                }
                if (!isset($params['host']) && !isset($params['path'])) {
                    throw new InvalidArgumentException('Invalid Memcached DSN: missing host or path.');
                }
                if (isset($params['path']) && preg_match('#/(\d+)$#', $params['path'], $m)) {
                    $params['weight'] = $m[1];
                    $params['path'] = substr($params['path'], 0, -\strlen($m[0]));
                }
                $params += ['host' => $params['host'] ?? $params['path'], 'port' => isset($params['host']) ? 11211 : null, 'weight' => 0];
                if ($query) {
                    $params += $query;
                    $options = $query + $options;
                }
                $servers[$i] = [$params['host'], $params['port'], $params['weight']];
                if ($hosts) {
                    $servers = array_merge($servers, $hosts);
                }
            }
            // set client's options
            unset($options['persistent_id'], $options['username'], $options['password'], $options['weight'], $options['lazy']);
            $options = array_change_key_case($options, \CASE_UPPER);
            $client->setOption(\Memcached::OPT_BINARY_PROTOCOL, \true);
            $client->setOption(\Memcached::OPT_NO_BLOCK, \true);
            $client->setOption(\Memcached::OPT_TCP_NODELAY, \true);
            if (!\array_key_exists('LIBKETAMA_COMPATIBLE', $options) && !\array_key_exists(\Memcached::OPT_LIBKETAMA_COMPATIBLE, $options)) {
                $client->setOption(\Memcached::OPT_LIBKETAMA_COMPATIBLE, \true);
            }
            foreach ($options as $name => $value) {
                if (\is_int($name)) {
                    continue;
                }
                if ('HASH' === $name || 'SERIALIZER' === $name || 'DISTRIBUTION' === $name) {
                    $value = \constant('Memcached::' . $name . '_' . strtoupper($value));
                }
                unset($options[$name]);
                if (\defined('Memcached::OPT_' . $name)) {
                    $options[\constant('Memcached::OPT_' . $name)] = $value;
                }
            }
            $client->setOptions($options + [\Memcached::OPT_SERIALIZER => \Memcached::SERIALIZER_PHP]);
            // set client's servers, taking care of persistent connections
            if (!$client->isPristine()) {
                $oldServers = [];
                foreach ($client->getServerList() as $server) {
                    $oldServers[] = [$server['host'], $server['port']];
                }
                $newServers = [];
                foreach ($servers as $server) {
                    if (1 < \count($server)) {
                        $server = array_values($server);
                        unset($server[2]);
                        $server[1] = (int) $server[1];
                    }
                    $newServers[] = $server;
                }
                if ($oldServers !== $newServers) {
                    $client->resetServerList();
                    $client->addServers($servers);
                }
            } else {
                $client->addServers($servers);
            }
            if (null !== $username || null !== $password) {
                if (!method_exists($client, 'setSaslAuthData')) {
                    trigger_error('Missing SASL support: the memcached extension must be compiled with --enable-memcached-sasl.');
                }
                $client->setSaslAuthData($username, $password);
            }
            return $client;
        } finally {
            restore_error_handler();
        }
    }
    protected function doSave(array $values, int $lifetime): array|bool
    {
        if (!$values = $this->marshaller->marshall($values, $failed)) {
            return $failed;
        }
        if ($lifetime && $lifetime > 30 * 86400) {
            $lifetime += time();
        }
        $encodedValues = [];
        foreach ($values as $key => $value) {
            $encodedValues[self::encodeKey($key)] = $value;
        }
        return $this->checkResultCode($this->getClient()->setMulti($encodedValues, $lifetime)) ? $failed : \false;
    }
    protected function doFetch(array $ids): iterable
    {
        try {
            $encodedIds = array_map([__CLASS__, 'encodeKey'], $ids);
            $encodedResult = $this->checkResultCode($this->getClient()->getMulti($encodedIds));
            $result = [];
            foreach ($encodedResult as $key => $value) {
                $result[self::decodeKey($key)] = $this->marshaller->unmarshall($value);
            }
            return $result;
        } catch (\Error $e) {
            throw new \ErrorException($e->getMessage(), $e->getCode(), \E_ERROR, $e->getFile(), $e->getLine());
        }
    }
    protected function doHave(string $id): bool
    {
        return \false !== $this->getClient()->get(self::encodeKey($id)) || $this->checkResultCode(\Memcached::RES_SUCCESS === $this->client->getResultCode());
    }
    protected function doDelete(array $ids): bool
    {
        $ok = \true;
        $encodedIds = array_map([__CLASS__, 'encodeKey'], $ids);
        foreach ($this->checkResultCode($this->getClient()->deleteMulti($encodedIds)) as $result) {
            if (\Memcached::RES_SUCCESS !== $result && \Memcached::RES_NOTFOUND !== $result) {
                $ok = \false;
            }
        }
        return $ok;
    }
    protected function doClear(string $namespace): bool
    {
        return '' === $namespace && $this->getClient()->flush();
    }
    private function checkResultCode(mixed $result): mixed
    {
        $code = $this->client->getResultCode();
        if (\Memcached::RES_SUCCESS === $code || \Memcached::RES_NOTFOUND === $code) {
            return $result;
        }
        throw new CacheException('MemcachedAdapter client error: ' . strtolower($this->client->getResultMessage()));
    }
    private function getClient(): \Memcached
    {
        if (isset($this->client)) {
            return $this->client;
        }
        $opt = $this->lazyClient->getOption(\Memcached::OPT_SERIALIZER);
        if (\Memcached::SERIALIZER_PHP !== $opt && \Memcached::SERIALIZER_IGBINARY !== $opt) {
            throw new CacheException('MemcachedAdapter: "serializer" option must be "php" or "igbinary".');
        }
        if ('' !== $prefix = (string) $this->lazyClient->getOption(\Memcached::OPT_PREFIX_KEY)) {
            throw new CacheException(\sprintf('MemcachedAdapter: "prefix_key" option must be empty when using proxified connections, "%s" given.', $prefix));
        }
        return $this->client = $this->lazyClient;
    }
    private static function encodeKey(string $key): string
    {
        return strtr($key, self::RESERVED_MEMCACHED, self::RESERVED_PSR6);
    }
    private static function decodeKey(string $key): string
    {
        return strtr($key, self::RESERVED_PSR6, self::RESERVED_MEMCACHED);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Cache\Adapter;

use _ContaoManager\Symfony\Component\Cache\Marshaller\MarshallerInterface;
use _ContaoManager\Symfony\Component\Cache\Traits\RedisTrait;
class RedisAdapter extends AbstractAdapter
{
    use RedisTrait;
    public function __construct(\Redis|\RedisArray|\RedisCluster|\_ContaoManager\Predis\ClientInterface|\Relay\Relay $redis, string $namespace = '', int $defaultLifetime = 0, ?MarshallerInterface $marshaller = null)
    {
        $this->init($redis, $namespace, $defaultLifetime, $marshaller);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Cache\Adapter;

use _ContaoManager\Psr\Cache\CacheItemPoolInterface;
use _ContaoManager\Symfony\Component\Cache\CacheItem;
// Help opcache.preload discover always-needed symbols
class_exists(CacheItem::class);
/**
 * Interface for adapters managing instances of Symfony's CacheItem.
 *
 * @author Kévin Dunglas <dunglas@gmail.com>
 */
interface AdapterInterface extends CacheItemPoolInterface
{
    public function getItem(mixed $key): CacheItem;
    /**
     * @return iterable<string, CacheItem>
     */
    public function getItems(array $keys = []): iterable;
    public function clear(string $prefix = ''): bool;
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Cache\Adapter;

use _ContaoManager\Symfony\Component\Cache\Marshaller\MarshallerInterface;
use _ContaoManager\Symfony\Component\Cache\Marshaller\TagAwareMarshaller;
use _ContaoManager\Symfony\Component\Cache\PruneableInterface;
use _ContaoManager\Symfony\Component\Cache\Traits\FilesystemTrait;
/**
 * Stores tag id <> cache id relationship as a symlink, and lookup on invalidation calls.
 *
 * @author Nicolas Grekas <p@tchwork.com>
 * @author André Rømcke <andre.romcke+symfony@gmail.com>
 */
class FilesystemTagAwareAdapter extends AbstractTagAwareAdapter implements PruneableInterface
{
    use FilesystemTrait {
        prune as private doPrune;
        doClear as private doClearCache;
        doSave as private doSaveCache;
    }
    /**
     * Folder used for tag symlinks.
     */
    private const TAG_FOLDER = 'tags';
    public function __construct(string $namespace = '', int $defaultLifetime = 0, ?string $directory = null, ?MarshallerInterface $marshaller = null)
    {
        $this->marshaller = new TagAwareMarshaller($marshaller);
        parent::__construct('', $defaultLifetime);
        $this->init($namespace, $directory);
    }
    public function prune(): bool
    {
        $ok = $this->doPrune();
        set_error_handler(static function () {
        });
        $chars = '+-ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
        try {
            foreach ($this->scanHashDir($this->directory . self::TAG_FOLDER . \DIRECTORY_SEPARATOR) as $dir) {
                $dir .= \DIRECTORY_SEPARATOR;
                $keepDir = \false;
                for ($i = 0; $i < 38; ++$i) {
                    if (!is_dir($dir . $chars[$i])) {
                        continue;
                    }
                    for ($j = 0; $j < 38; ++$j) {
                        if (!is_dir($d = $dir . $chars[$i] . \DIRECTORY_SEPARATOR . $chars[$j])) {
                            continue;
                        }
                        foreach (scandir($d, \SCANDIR_SORT_NONE) ?: [] as $link) {
                            if ('.' === $link || '..' === $link) {
                                continue;
                            }
                            if ('_' !== $dir[-2] && realpath($d . \DIRECTORY_SEPARATOR . $link)) {
                                $keepDir = \true;
                            } else {
                                unlink($d . \DIRECTORY_SEPARATOR . $link);
                            }
                        }
                        $keepDir ?: rmdir($d);
                    }
                    $keepDir ?: rmdir($dir . $chars[$i]);
                }
                $keepDir ?: rmdir($dir);
            }
        } finally {
            restore_error_handler();
        }
        return $ok;
    }
    protected function doClear(string $namespace): bool
    {
        $ok = $this->doClearCache($namespace);
        if ('' !== $namespace) {
            return $ok;
        }
        set_error_handler(static function () {
        });
        $chars = '+-ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
        $this->tmpSuffix ??= str_replace('/', '-', base64_encode(random_bytes(6)));
        try {
            foreach ($this->scanHashDir($this->directory . self::TAG_FOLDER . \DIRECTORY_SEPARATOR) as $dir) {
                if (rename($dir, $renamed = substr_replace($dir, $this->tmpSuffix . '_', -9))) {
                    $dir = $renamed . \DIRECTORY_SEPARATOR;
                } else {
                    $dir .= \DIRECTORY_SEPARATOR;
                    $renamed = null;
                }
                for ($i = 0; $i < 38; ++$i) {
                    if (!is_dir($dir . $chars[$i])) {
                        continue;
                    }
                    for ($j = 0; $j < 38; ++$j) {
                        if (!is_dir($d = $dir . $chars[$i] . \DIRECTORY_SEPARATOR . $chars[$j])) {
                            continue;
                        }
                        foreach (scandir($d, \SCANDIR_SORT_NONE) ?: [] as $link) {
                            if ('.' !== $link && '..' !== $link && (null !== $renamed || !realpath($d . \DIRECTORY_SEPARATOR . $link))) {
                                unlink($d . \DIRECTORY_SEPARATOR . $link);
                            }
                        }
                        null === $renamed ?: rmdir($d);
                    }
                    null === $renamed ?: rmdir($dir . $chars[$i]);
                }
                null === $renamed ?: rmdir($renamed);
            }
        } finally {
            restore_error_handler();
        }
        return $ok;
    }
    protected function doSave(array $values, int $lifetime, array $addTagData = [], array $removeTagData = []): array
    {
        $failed = $this->doSaveCache($values, $lifetime);
        // Add Tags as symlinks
        foreach ($addTagData as $tagId => $ids) {
            $tagFolder = $this->getTagFolder($tagId);
            foreach ($ids as $id) {
                if ($failed && \in_array($id, $failed, \true)) {
                    continue;
                }
                $file = $this->getFile($id);
                if (!@symlink($file, $tagLink = $this->getFile($id, \true, $tagFolder)) && !is_link($tagLink)) {
                    @unlink($file);
                    $failed[] = $id;
                }
            }
        }
        // Unlink removed Tags
        foreach ($removeTagData as $tagId => $ids) {
            $tagFolder = $this->getTagFolder($tagId);
            foreach ($ids as $id) {
                if ($failed && \in_array($id, $failed, \true)) {
                    continue;
                }
                @unlink($this->getFile($id, \false, $tagFolder));
            }
        }
        return $failed;
    }
    protected function doDeleteYieldTags(array $ids): iterable
    {
        foreach ($ids as $id) {
            $file = $this->getFile($id);
            if (!is_file($file) || !$h = @fopen($file, 'r')) {
                continue;
            }
            if (!@unlink($file)) {
                fclose($h);
                continue;
            }
            $meta = explode("\n", fread($h, 4096), 3)[2] ?? '';
            // detect the compact format used in marshall() using magic numbers in the form 9D-..-..-..-..-00-..-..-..-5F
            if (13 < \strlen($meta) && "\x9d" === $meta[0] && "\x00" === $meta[5] && "_" === $meta[9]) {
                $meta[9] = "\x00";
                $tagLen = unpack('Nlen', $meta, 9)['len'];
                $meta = substr($meta, 13, $tagLen);
                if (0 < $tagLen -= \strlen($meta)) {
                    $meta .= fread($h, $tagLen);
                }
                try {
                    yield $id => '' === $meta ? [] : $this->marshaller->unmarshall($meta);
                } catch (\Exception) {
                    yield $id => [];
                }
            }
            fclose($h);
        }
    }
    protected function doDeleteTagRelations(array $tagData): bool
    {
        foreach ($tagData as $tagId => $idList) {
            $tagFolder = $this->getTagFolder($tagId);
            foreach ($idList as $id) {
                @unlink($this->getFile($id, \false, $tagFolder));
            }
        }
        return \true;
    }
    protected function doInvalidate(array $tagIds): bool
    {
        foreach ($tagIds as $tagId) {
            if (!is_dir($tagFolder = $this->getTagFolder($tagId))) {
                continue;
            }
            $this->tmpSuffix ??= str_replace('/', '-', base64_encode(random_bytes(6)));
            set_error_handler(static function () {
            });
            try {
                if (rename($tagFolder, $renamed = substr_replace($tagFolder, $this->tmpSuffix . '_', -10))) {
                    $tagFolder = $renamed . \DIRECTORY_SEPARATOR;
                } else {
                    $renamed = null;
                }
                foreach ($this->scanHashDir($tagFolder) as $itemLink) {
                    unlink(realpath($itemLink) ?: $itemLink);
                    unlink($itemLink);
                }
                if (null === $renamed) {
                    continue;
                }
                $chars = '+-ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
                for ($i = 0; $i < 38; ++$i) {
                    for ($j = 0; $j < 38; ++$j) {
                        rmdir($tagFolder . $chars[$i] . \DIRECTORY_SEPARATOR . $chars[$j]);
                    }
                    rmdir($tagFolder . $chars[$i]);
                }
                rmdir($renamed);
            } finally {
                restore_error_handler();
            }
        }
        return \true;
    }
    private function getTagFolder(string $tagId): string
    {
        return $this->getFile($tagId, \false, $this->directory . self::TAG_FOLDER . \DIRECTORY_SEPARATOR) . \DIRECTORY_SEPARATOR;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Cache\Adapter;

use _ContaoManager\Symfony\Contracts\Cache\TagAwareCacheInterface;
/**
 * @author Robin Chalas <robin.chalas@gmail.com>
 */
class TraceableTagAwareAdapter extends TraceableAdapter implements TagAwareAdapterInterface, TagAwareCacheInterface
{
    public function __construct(TagAwareAdapterInterface $pool)
    {
        parent::__construct($pool);
    }
    public function invalidateTags(array $tags): bool
    {
        $event = $this->start(__FUNCTION__);
        try {
            return $event->result = $this->pool->invalidateTags($tags);
        } finally {
            $event->end = microtime(\true);
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Cache\Adapter;

use _ContaoManager\Psr\SimpleCache\CacheInterface;
use _ContaoManager\Symfony\Component\Cache\PruneableInterface;
use _ContaoManager\Symfony\Component\Cache\ResettableInterface;
use _ContaoManager\Symfony\Component\Cache\Traits\ProxyTrait;
/**
 * Turns a PSR-16 cache into a PSR-6 one.
 *
 * @author Nicolas Grekas <p@tchwork.com>
 */
class Psr16Adapter extends AbstractAdapter implements PruneableInterface, ResettableInterface
{
    use ProxyTrait;
    /**
     * @internal
     */
    protected const NS_SEPARATOR = '_';
    private object $miss;
    public function __construct(CacheInterface $pool, string $namespace = '', int $defaultLifetime = 0)
    {
        parent::__construct($namespace, $defaultLifetime);
        $this->pool = $pool;
        $this->miss = new \stdClass();
    }
    protected function doFetch(array $ids): iterable
    {
        foreach ($this->pool->getMultiple($ids, $this->miss) as $key => $value) {
            if ($this->miss !== $value) {
                yield $key => $value;
            }
        }
    }
    protected function doHave(string $id): bool
    {
        return $this->pool->has($id);
    }
    protected function doClear(string $namespace): bool
    {
        return $this->pool->clear();
    }
    protected function doDelete(array $ids): bool
    {
        return $this->pool->deleteMultiple($ids);
    }
    protected function doSave(array $values, int $lifetime): array|bool
    {
        return $this->pool->setMultiple($values, 0 === $lifetime ? null : $lifetime);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Cache\Adapter;

use _ContaoManager\Psr\Cache\CacheItemInterface;
use _ContaoManager\Psr\Cache\CacheItemPoolInterface;
use _ContaoManager\Symfony\Component\Cache\CacheItem;
use _ContaoManager\Symfony\Component\Cache\Exception\InvalidArgumentException;
use _ContaoManager\Symfony\Component\Cache\PruneableInterface;
use _ContaoManager\Symfony\Component\Cache\ResettableInterface;
use _ContaoManager\Symfony\Component\Cache\Traits\ContractsTrait;
use _ContaoManager\Symfony\Contracts\Cache\CacheInterface;
use _ContaoManager\Symfony\Contracts\Service\ResetInterface;
/**
 * Chains several adapters together.
 *
 * Cached items are fetched from the first adapter having them in its data store.
 * They are saved and deleted in all adapters at once.
 *
 * @author Kévin Dunglas <dunglas@gmail.com>
 */
class ChainAdapter implements AdapterInterface, CacheInterface, PruneableInterface, ResettableInterface
{
    use ContractsTrait;
    private array $adapters = [];
    private int $adapterCount;
    private int $defaultLifetime;
    private static \Closure $syncItem;
    /**
     * @param CacheItemPoolInterface[] $adapters        The ordered list of adapters used to fetch cached items
     * @param int                      $defaultLifetime The default lifetime of items propagated from lower adapters to upper ones
     */
    public function __construct(array $adapters, int $defaultLifetime = 0)
    {
        if (!$adapters) {
            throw new InvalidArgumentException('At least one adapter must be specified.');
        }
        foreach ($adapters as $adapter) {
            if (!$adapter instanceof CacheItemPoolInterface) {
                throw new InvalidArgumentException(\sprintf('The class "%s" does not implement the "%s" interface.', get_debug_type($adapter), CacheItemPoolInterface::class));
            }
            if ('cli' === \PHP_SAPI && $adapter instanceof ApcuAdapter && !filter_var(\ini_get('apc.enable_cli'), \FILTER_VALIDATE_BOOL)) {
                continue;
                // skip putting APCu in the chain when the backend is disabled
            }
            if ($adapter instanceof AdapterInterface) {
                $this->adapters[] = $adapter;
            } else {
                $this->adapters[] = new ProxyAdapter($adapter);
            }
        }
        $this->adapterCount = \count($this->adapters);
        $this->defaultLifetime = $defaultLifetime;
        self::$syncItem ??= \Closure::bind(static function ($sourceItem, $item, $defaultLifetime, $sourceMetadata = null) {
            $sourceItem->isTaggable = \false;
            $sourceMetadata ??= $sourceItem->metadata;
            $item->value = $sourceItem->value;
            $item->isHit = $sourceItem->isHit;
            $item->metadata = $item->newMetadata = $sourceItem->metadata = $sourceMetadata;
            if (isset($item->metadata[CacheItem::METADATA_EXPIRY])) {
                $item->expiresAt(\DateTimeImmutable::createFromFormat('U.u', \sprintf('%.6F', $item->metadata[CacheItem::METADATA_EXPIRY])));
            } elseif (0 < $defaultLifetime) {
                $item->expiresAfter($defaultLifetime);
                $item->newMetadata[CacheItem::METADATA_EXPIRY] = $item->expiry;
            }
            return $item;
        }, null, CacheItem::class);
    }
    public function get(string $key, callable $callback, ?float $beta = null, ?array &$metadata = null): mixed
    {
        $doSave = \true;
        $callback = static function (CacheItem $item, bool &$save) use ($callback, &$doSave) {
            $value = $callback($item, $save);
            $doSave = $save;
            return $value;
        };
        $wrap = function (?CacheItem $item = null, bool &$save = \true) use ($key, $callback, $beta, &$wrap, &$doSave, &$metadata) {
            static $lastItem;
            static $i = 0;
            $adapter = $this->adapters[$i];
            if (isset($this->adapters[++$i])) {
                $callback = $wrap;
                $beta = \INF === $beta ? \INF : 0;
            }
            if ($adapter instanceof CacheInterface && $i !== $this->adapterCount) {
                $value = $adapter->get($key, $callback, $beta, $metadata);
            } else {
                $value = $this->doGet($adapter, $key, $callback, $beta, $metadata);
            }
            if (null !== $item) {
                (self::$syncItem)($lastItem ??= $item, $item, $this->defaultLifetime, $metadata);
            }
            $save = $doSave;
            return $value;
        };
        return $wrap();
    }
    public function getItem(mixed $key): CacheItem
    {
        $syncItem = self::$syncItem;
        $misses = [];
        foreach ($this->adapters as $i => $adapter) {
            $item = $adapter->getItem($key);
            if ($item->isHit()) {
                while (0 <= --$i) {
                    $this->adapters[$i]->save($syncItem($item, $misses[$i], $this->defaultLifetime));
                }
                return $item;
            }
            $misses[$i] = $item;
        }
        return $item;
    }
    public function getItems(array $keys = []): iterable
    {
        return $this->generateItems($this->adapters[0]->getItems($keys), 0);
    }
    private function generateItems(iterable $items, int $adapterIndex): \Generator
    {
        $missing = [];
        $misses = [];
        $nextAdapterIndex = $adapterIndex + 1;
        $nextAdapter = $this->adapters[$nextAdapterIndex] ?? null;
        foreach ($items as $k => $item) {
            if (!$nextAdapter || $item->isHit()) {
                yield $k => $item;
            } else {
                $missing[] = $k;
                $misses[$k] = $item;
            }
        }
        if ($missing) {
            $syncItem = self::$syncItem;
            $adapter = $this->adapters[$adapterIndex];
            $items = $this->generateItems($nextAdapter->getItems($missing), $nextAdapterIndex);
            foreach ($items as $k => $item) {
                if ($item->isHit()) {
                    $adapter->save($syncItem($item, $misses[$k], $this->defaultLifetime));
                }
                yield $k => $item;
            }
        }
    }
    public function hasItem(mixed $key): bool
    {
        foreach ($this->adapters as $adapter) {
            if ($adapter->hasItem($key)) {
                return \true;
            }
        }
        return \false;
    }
    public function clear(string $prefix = ''): bool
    {
        $cleared = \true;
        $i = $this->adapterCount;
        while ($i--) {
            if ($this->adapters[$i] instanceof AdapterInterface) {
                $cleared = $this->adapters[$i]->clear($prefix) && $cleared;
            } else {
                $cleared = $this->adapters[$i]->clear() && $cleared;
            }
        }
        return $cleared;
    }
    public function deleteItem(mixed $key): bool
    {
        $deleted = \true;
        $i = $this->adapterCount;
        while ($i--) {
            $deleted = $this->adapters[$i]->deleteItem($key) && $deleted;
        }
        return $deleted;
    }
    public function deleteItems(array $keys): bool
    {
        $deleted = \true;
        $i = $this->adapterCount;
        while ($i--) {
            $deleted = $this->adapters[$i]->deleteItems($keys) && $deleted;
        }
        return $deleted;
    }
    public function save(CacheItemInterface $item): bool
    {
        $saved = \true;
        $i = $this->adapterCount;
        while ($i--) {
            $saved = $this->adapters[$i]->save($item) && $saved;
        }
        return $saved;
    }
    public function saveDeferred(CacheItemInterface $item): bool
    {
        $saved = \true;
        $i = $this->adapterCount;
        while ($i--) {
            $saved = $this->adapters[$i]->saveDeferred($item) && $saved;
        }
        return $saved;
    }
    public function commit(): bool
    {
        $committed = \true;
        $i = $this->adapterCount;
        while ($i--) {
            $committed = $this->adapters[$i]->commit() && $committed;
        }
        return $committed;
    }
    public function prune(): bool
    {
        $pruned = \true;
        foreach ($this->adapters as $adapter) {
            if ($adapter instanceof PruneableInterface) {
                $pruned = $adapter->prune() && $pruned;
            }
        }
        return $pruned;
    }
    /**
     * @return void
     */
    public function reset()
    {
        foreach ($this->adapters as $adapter) {
            if ($adapter instanceof ResetInterface) {
                $adapter->reset();
            }
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Cache\Adapter;

use _ContaoManager\Symfony\Component\Cache\Marshaller\DefaultMarshaller;
use _ContaoManager\Symfony\Component\Cache\Marshaller\MarshallerInterface;
use _ContaoManager\Symfony\Component\Cache\PruneableInterface;
use _ContaoManager\Symfony\Component\Cache\Traits\FilesystemTrait;
class FilesystemAdapter extends AbstractAdapter implements PruneableInterface
{
    use FilesystemTrait;
    public function __construct(string $namespace = '', int $defaultLifetime = 0, ?string $directory = null, ?MarshallerInterface $marshaller = null)
    {
        $this->marshaller = $marshaller ?? new DefaultMarshaller();
        parent::__construct('', $defaultLifetime);
        $this->init($namespace, $directory);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Cache\Adapter;

use _ContaoManager\Psr\Log\LoggerAwareInterface;
use _ContaoManager\Psr\Log\LoggerInterface;
use _ContaoManager\Symfony\Component\Cache\CacheItem;
use _ContaoManager\Symfony\Component\Cache\Exception\InvalidArgumentException;
use _ContaoManager\Symfony\Component\Cache\ResettableInterface;
use _ContaoManager\Symfony\Component\Cache\Traits\AbstractAdapterTrait;
use _ContaoManager\Symfony\Component\Cache\Traits\ContractsTrait;
use _ContaoManager\Symfony\Contracts\Cache\CacheInterface;
/**
 * @author Nicolas Grekas <p@tchwork.com>
 */
abstract class AbstractAdapter implements AdapterInterface, CacheInterface, LoggerAwareInterface, ResettableInterface
{
    use AbstractAdapterTrait;
    use ContractsTrait;
    /**
     * @internal
     */
    protected const NS_SEPARATOR = ':';
    private static bool $apcuSupported;
    protected function __construct(string $namespace = '', int $defaultLifetime = 0)
    {
        $this->namespace = '' === $namespace ? '' : CacheItem::validateKey($namespace) . static::NS_SEPARATOR;
        $this->defaultLifetime = $defaultLifetime;
        if (null !== $this->maxIdLength && \strlen($namespace) > $this->maxIdLength - 24) {
            throw new InvalidArgumentException(\sprintf('Namespace must be %d chars max, %d given ("%s").', $this->maxIdLength - 24, \strlen($namespace), $namespace));
        }
        self::$createCacheItem ??= \Closure::bind(static function ($key, $value, $isHit) {
            $item = new CacheItem();
            $item->key = $key;
            $item->value = $value;
            $item->isHit = $isHit;
            $item->unpack();
            return $item;
        }, null, CacheItem::class);
        self::$mergeByLifetime ??= \Closure::bind(static function ($deferred, $namespace, &$expiredIds, $getId, $defaultLifetime) {
            $byLifetime = [];
            $now = microtime(\true);
            $expiredIds = [];
            foreach ($deferred as $key => $item) {
                $key = (string) $key;
                if (null === $item->expiry) {
                    $ttl = 0 < $defaultLifetime ? $defaultLifetime : 0;
                } elseif (!$item->expiry) {
                    $ttl = 0;
                } elseif (0 >= $ttl = (int) (0.1 + $item->expiry - $now)) {
                    $expiredIds[] = $getId($key);
                    continue;
                }
                $byLifetime[$ttl][$getId($key)] = $item->pack();
            }
            return $byLifetime;
        }, null, CacheItem::class);
    }
    /**
     * Returns the best possible adapter that your runtime supports.
     *
     * Using ApcuAdapter makes system caches compatible with read-only filesystems.
     */
    public static function createSystemCache(string $namespace, int $defaultLifetime, string $version, string $directory, ?LoggerInterface $logger = null): AdapterInterface
    {
        $opcache = new PhpFilesAdapter($namespace, $defaultLifetime, $directory, \true);
        if (null !== $logger) {
            $opcache->setLogger($logger);
        }
        if (!self::$apcuSupported ??= ApcuAdapter::isSupported()) {
            return $opcache;
        }
        if ('cli' === \PHP_SAPI && !filter_var(\ini_get('apc.enable_cli'), \FILTER_VALIDATE_BOOL)) {
            return $opcache;
        }
        $apcu = new ApcuAdapter($namespace, intdiv($defaultLifetime, 5), $version);
        if (null !== $logger) {
            $apcu->setLogger($logger);
        }
        return new ChainAdapter([$apcu, $opcache]);
    }
    public static function createConnection(
        #[\SensitiveParameter]
        string $dsn,
        array $options = []
    ): mixed
    {
        if (str_starts_with($dsn, 'redis:') || str_starts_with($dsn, 'rediss:')) {
            return RedisAdapter::createConnection($dsn, $options);
        }
        if (str_starts_with($dsn, 'memcached:')) {
            return MemcachedAdapter::createConnection($dsn, $options);
        }
        if (str_starts_with($dsn, 'couchbase:')) {
            if (CouchbaseBucketAdapter::isSupported()) {
                return CouchbaseBucketAdapter::createConnection($dsn, $options);
            }
            return CouchbaseCollectionAdapter::createConnection($dsn, $options);
        }
        throw new InvalidArgumentException('Unsupported DSN: it does not start with "redis[s]:", "memcached:" nor "couchbase:".');
    }
    public function commit(): bool
    {
        $ok = \true;
        $byLifetime = (self::$mergeByLifetime)($this->deferred, $this->namespace, $expiredIds, $this->getId(...), $this->defaultLifetime);
        $retry = $this->deferred = [];
        if ($expiredIds) {
            try {
                $this->doDelete($expiredIds);
            } catch (\Exception $e) {
                $ok = \false;
                CacheItem::log($this->logger, 'Failed to delete expired items: ' . $e->getMessage(), ['exception' => $e, 'cache-adapter' => get_debug_type($this)]);
            }
        }
        foreach ($byLifetime as $lifetime => $values) {
            try {
                $e = $this->doSave($values, $lifetime);
            } catch (\Exception $e) {
            }
            if (\true === $e || [] === $e) {
                continue;
            }
            if (\is_array($e) || 1 === \count($values)) {
                foreach (\is_array($e) ? $e : array_keys($values) as $id) {
                    $ok = \false;
                    $v = $values[$id];
                    $type = get_debug_type($v);
                    $message = \sprintf('Failed to save key "{key}" of type %s%s', $type, $e instanceof \Exception ? ': ' . $e->getMessage() : '.');
                    CacheItem::log($this->logger, $message, ['key' => substr($id, \strlen($this->namespace)), 'exception' => $e instanceof \Exception ? $e : null, 'cache-adapter' => get_debug_type($this)]);
                }
            } else {
                foreach ($values as $id => $v) {
                    $retry[$lifetime][] = $id;
                }
            }
        }
        // When bulk-save failed, retry each item individually
        foreach ($retry as $lifetime => $ids) {
            foreach ($ids as $id) {
                try {
                    $v = $byLifetime[$lifetime][$id];
                    $e = $this->doSave([$id => $v], $lifetime);
                } catch (\Exception $e) {
                }
                if (\true === $e || [] === $e) {
                    continue;
                }
                $ok = \false;
                $type = get_debug_type($v);
                $message = \sprintf('Failed to save key "{key}" of type %s%s', $type, $e instanceof \Exception ? ': ' . $e->getMessage() : '.');
                CacheItem::log($this->logger, $message, ['key' => substr($id, \strlen($this->namespace)), 'exception' => $e instanceof \Exception ? $e : null, 'cache-adapter' => get_debug_type($this)]);
            }
        }
        return $ok;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Cache\Adapter;

use _ContaoManager\Psr\Log\LoggerAwareInterface;
use _ContaoManager\Symfony\Component\Cache\CacheItem;
use _ContaoManager\Symfony\Component\Cache\Exception\InvalidArgumentException;
use _ContaoManager\Symfony\Component\Cache\ResettableInterface;
use _ContaoManager\Symfony\Component\Cache\Traits\AbstractAdapterTrait;
use _ContaoManager\Symfony\Component\Cache\Traits\ContractsTrait;
use _ContaoManager\Symfony\Contracts\Cache\TagAwareCacheInterface;
/**
 * Abstract for native TagAware adapters.
 *
 * To keep info on tags, the tags are both serialized as part of cache value and provided as tag ids
 * to Adapters on operations when needed for storage to doSave(), doDelete() & doInvalidate().
 *
 * @author Nicolas Grekas <p@tchwork.com>
 * @author André Rømcke <andre.romcke+symfony@gmail.com>
 *
 * @internal
 */
abstract class AbstractTagAwareAdapter implements TagAwareAdapterInterface, TagAwareCacheInterface, LoggerAwareInterface, ResettableInterface
{
    use AbstractAdapterTrait;
    use ContractsTrait;
    private const TAGS_PREFIX = "\x01tags\x01";
    protected function __construct(string $namespace = '', int $defaultLifetime = 0)
    {
        $this->namespace = '' === $namespace ? '' : CacheItem::validateKey($namespace) . ':';
        $this->defaultLifetime = $defaultLifetime;
        if (null !== $this->maxIdLength && \strlen($namespace) > $this->maxIdLength - 24) {
            throw new InvalidArgumentException(\sprintf('Namespace must be %d chars max, %d given ("%s").', $this->maxIdLength - 24, \strlen($namespace), $namespace));
        }
        self::$createCacheItem ??= \Closure::bind(static function ($key, $value, $isHit) {
            $item = new CacheItem();
            $item->key = $key;
            $item->isTaggable = \true;
            // If structure does not match what we expect return item as is (no value and not a hit)
            if (!\is_array($value) || !\array_key_exists('value', $value)) {
                return $item;
            }
            $item->isHit = $isHit;
            // Extract value, tags and meta data from the cache value
            $item->value = $value['value'];
            $item->metadata[CacheItem::METADATA_TAGS] = isset($value['tags']) ? array_combine($value['tags'], $value['tags']) : [];
            if (isset($value['meta'])) {
                // For compactness these values are packed, & expiry is offset to reduce size
                $v = unpack('Ve/Nc', $value['meta']);
                $item->metadata[CacheItem::METADATA_EXPIRY] = $v['e'] + CacheItem::METADATA_EXPIRY_OFFSET;
                $item->metadata[CacheItem::METADATA_CTIME] = $v['c'];
            }
            return $item;
        }, null, CacheItem::class);
        self::$mergeByLifetime ??= \Closure::bind(static function ($deferred, &$expiredIds, $getId, $tagPrefix, $defaultLifetime) {
            $byLifetime = [];
            $now = microtime(\true);
            $expiredIds = [];
            foreach ($deferred as $key => $item) {
                $key = (string) $key;
                if (null === $item->expiry) {
                    $ttl = 0 < $defaultLifetime ? $defaultLifetime : 0;
                } elseif (!$item->expiry) {
                    $ttl = 0;
                } elseif (0 >= $ttl = (int) (0.1 + $item->expiry - $now)) {
                    $expiredIds[] = $getId($key);
                    continue;
                }
                // Store Value and Tags on the cache value
                if (isset(($metadata = $item->newMetadata)[CacheItem::METADATA_TAGS])) {
                    $value = ['value' => $item->value, 'tags' => $metadata[CacheItem::METADATA_TAGS]];
                    unset($metadata[CacheItem::METADATA_TAGS]);
                } else {
                    $value = ['value' => $item->value, 'tags' => []];
                }
                if ($metadata) {
                    // For compactness, expiry and creation duration are packed, using magic numbers as separators
                    $value['meta'] = pack('VN', (int) (0.1 + $metadata[CacheItem::METADATA_EXPIRY] - CacheItem::METADATA_EXPIRY_OFFSET), $metadata[CacheItem::METADATA_CTIME]);
                }
                // Extract tag changes, these should be removed from values in doSave()
                $value['tag-operations'] = ['add' => [], 'remove' => []];
                $oldTags = $item->metadata[CacheItem::METADATA_TAGS] ?? [];
                foreach (array_diff_key($value['tags'], $oldTags) as $addedTag) {
                    $value['tag-operations']['add'][] = $getId($tagPrefix . $addedTag);
                }
                foreach (array_diff_key($oldTags, $value['tags']) as $removedTag) {
                    $value['tag-operations']['remove'][] = $getId($tagPrefix . $removedTag);
                }
                $value['tags'] = array_keys($value['tags']);
                $byLifetime[$ttl][$getId($key)] = $value;
                $item->metadata = $item->newMetadata;
            }
            return $byLifetime;
        }, null, CacheItem::class);
    }
    /**
     * Persists several cache items immediately.
     *
     * @param array   $values        The values to cache, indexed by their cache identifier
     * @param int     $lifetime      The lifetime of the cached values, 0 for persisting until manual cleaning
     * @param array[] $addTagData    Hash where key is tag id, and array value is list of cache id's to add to tag
     * @param array[] $removeTagData Hash where key is tag id, and array value is list of cache id's to remove to tag
     *
     * @return array The identifiers that failed to be cached or a boolean stating if caching succeeded or not
     */
    abstract protected function doSave(array $values, int $lifetime, array $addTagData = [], array $removeTagData = []): array;
    /**
     * Removes multiple items from the pool and their corresponding tags.
     *
     * @param array $ids An array of identifiers that should be removed from the pool
     */
    abstract protected function doDelete(array $ids): bool;
    /**
     * Removes relations between tags and deleted items.
     *
     * @param array $tagData Array of tag => key identifiers that should be removed from the pool
     */
    abstract protected function doDeleteTagRelations(array $tagData): bool;
    /**
     * Invalidates cached items using tags.
     *
     * @param string[] $tagIds An array of tags to invalidate, key is tag and value is tag id
     */
    abstract protected function doInvalidate(array $tagIds): bool;
    /**
     * Delete items and yields the tags they were bound to.
     */
    protected function doDeleteYieldTags(array $ids): iterable
    {
        foreach ($this->doFetch($ids) as $id => $value) {
            yield $id => \is_array($value) && \is_array($value['tags'] ?? null) ? $value['tags'] : [];
        }
        $this->doDelete($ids);
    }
    public function commit(): bool
    {
        $ok = \true;
        $byLifetime = (self::$mergeByLifetime)($this->deferred, $expiredIds, $this->getId(...), self::TAGS_PREFIX, $this->defaultLifetime);
        $retry = $this->deferred = [];
        if ($expiredIds) {
            // Tags are not cleaned up in this case, however that is done on invalidateTags().
            try {
                $this->doDelete($expiredIds);
            } catch (\Exception $e) {
                $ok = \false;
                CacheItem::log($this->logger, 'Failed to delete expired items: ' . $e->getMessage(), ['exception' => $e, 'cache-adapter' => get_debug_type($this)]);
            }
        }
        foreach ($byLifetime as $lifetime => $values) {
            try {
                $values = $this->extractTagData($values, $addTagData, $removeTagData);
                $e = $this->doSave($values, $lifetime, $addTagData, $removeTagData);
            } catch (\Exception $e) {
            }
            if (\true === $e || [] === $e) {
                continue;
            }
            if (\is_array($e) || 1 === \count($values)) {
                foreach (\is_array($e) ? $e : array_keys($values) as $id) {
                    $ok = \false;
                    $type = \array_key_exists($id, $values) ? get_debug_type($values[$id]) : 'unknown';
                    $message = \sprintf('Failed to save key "{key}" of type %s%s', $type, $e instanceof \Exception ? ': ' . $e->getMessage() : '.');
                    CacheItem::log($this->logger, $message, ['key' => substr($id, \strlen($this->namespace)), 'exception' => $e instanceof \Exception ? $e : null, 'cache-adapter' => get_debug_type($this)]);
                }
            } else {
                foreach ($values as $id => $v) {
                    $retry[$lifetime][] = $id;
                }
            }
        }
        // When bulk-save failed, retry each item individually
        foreach ($retry as $lifetime => $ids) {
            foreach ($ids as $id) {
                try {
                    $v = $byLifetime[$lifetime][$id];
                    $values = $this->extractTagData([$id => $v], $addTagData, $removeTagData);
                    $e = $this->doSave($values, $lifetime, $addTagData, $removeTagData);
                } catch (\Exception $e) {
                }
                if (\true === $e || [] === $e) {
                    continue;
                }
                $ok = \false;
                $type = get_debug_type($v);
                $message = \sprintf('Failed to save key "{key}" of type %s%s', $type, $e instanceof \Exception ? ': ' . $e->getMessage() : '.');
                CacheItem::log($this->logger, $message, ['key' => substr($id, \strlen($this->namespace)), 'exception' => $e instanceof \Exception ? $e : null, 'cache-adapter' => get_debug_type($this)]);
            }
        }
        return $ok;
    }
    public function deleteItems(array $keys): bool
    {
        if (!$keys) {
            return \true;
        }
        $ok = \true;
        $ids = [];
        $tagData = [];
        foreach ($keys as $key) {
            $ids[$key] = $this->getId($key);
            unset($this->deferred[$key]);
        }
        try {
            foreach ($this->doDeleteYieldTags(array_values($ids)) as $id => $tags) {
                foreach ($tags as $tag) {
                    $tagData[$this->getId(self::TAGS_PREFIX . $tag)][] = $id;
                }
            }
        } catch (\Exception) {
            $ok = \false;
        }
        try {
            if ((!$tagData || $this->doDeleteTagRelations($tagData)) && $ok) {
                return \true;
            }
        } catch (\Exception) {
        }
        // When bulk-delete failed, retry each item individually
        foreach ($ids as $key => $id) {
            try {
                $e = null;
                if ($this->doDelete([$id])) {
                    continue;
                }
            } catch (\Exception $e) {
            }
            $message = 'Failed to delete key "{key}"' . ($e instanceof \Exception ? ': ' . $e->getMessage() : '.');
            CacheItem::log($this->logger, $message, ['key' => $key, 'exception' => $e, 'cache-adapter' => get_debug_type($this)]);
            $ok = \false;
        }
        return $ok;
    }
    public function invalidateTags(array $tags): bool
    {
        if (!$tags) {
            return \false;
        }
        $tagIds = [];
        foreach (array_unique($tags) as $tag) {
            $tagIds[] = $this->getId(self::TAGS_PREFIX . $tag);
        }
        try {
            if ($this->doInvalidate($tagIds)) {
                return \true;
            }
        } catch (\Exception $e) {
            CacheItem::log($this->logger, 'Failed to invalidate tags: ' . $e->getMessage(), ['exception' => $e, 'cache-adapter' => get_debug_type($this)]);
        }
        return \false;
    }
    /**
     * Extracts tags operation data from $values set in mergeByLifetime, and returns values without it.
     */
    private function extractTagData(array $values, ?array &$addTagData, ?array &$removeTagData): array
    {
        $addTagData = $removeTagData = [];
        foreach ($values as $id => $value) {
            foreach ($value['tag-operations']['add'] as $tag => $tagId) {
                $addTagData[$tagId][] = $id;
            }
            foreach ($value['tag-operations']['remove'] as $tag => $tagId) {
                $removeTagData[$tagId][] = $id;
            }
            unset($values[$id]['tag-operations']);
        }
        return $values;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Cache\Adapter;

use _ContaoManager\Psr\Cache\CacheItemInterface;
use _ContaoManager\Psr\Cache\CacheItemPoolInterface;
use _ContaoManager\Symfony\Component\Cache\CacheItem;
use _ContaoManager\Symfony\Component\Cache\Exception\InvalidArgumentException;
use _ContaoManager\Symfony\Component\Cache\PruneableInterface;
use _ContaoManager\Symfony\Component\Cache\ResettableInterface;
use _ContaoManager\Symfony\Component\Cache\Traits\CachedValueInterface;
use _ContaoManager\Symfony\Component\Cache\Traits\ContractsTrait;
use _ContaoManager\Symfony\Component\Cache\Traits\ProxyTrait;
use _ContaoManager\Symfony\Component\VarExporter\VarExporter;
use _ContaoManager\Symfony\Contracts\Cache\CacheInterface;
/**
 * Caches items at warm up time using a PHP array that is stored in shared memory by OPCache since PHP 7.0.
 * Warmed up items are read-only and run-time discovered items are cached using a fallback adapter.
 *
 * @author Titouan Galopin <galopintitouan@gmail.com>
 * @author Nicolas Grekas <p@tchwork.com>
 */
class PhpArrayAdapter implements AdapterInterface, CacheInterface, PruneableInterface, ResettableInterface
{
    use ContractsTrait;
    use ProxyTrait;
    private string $file;
    private array $keys;
    private array $values;
    private static \Closure $createCacheItem;
    private static array $valuesCache = [];
    /**
     * @param string           $file         The PHP file were values are cached
     * @param AdapterInterface $fallbackPool A pool to fallback on when an item is not hit
     */
    public function __construct(string $file, AdapterInterface $fallbackPool)
    {
        $this->file = $file;
        $this->pool = $fallbackPool;
        self::$createCacheItem ??= \Closure::bind(static function ($key, $value, $isHit) {
            $item = new CacheItem();
            $item->key = $key;
            $item->value = $value;
            $item->isHit = $isHit;
            return $item;
        }, null, CacheItem::class);
    }
    /**
     * This adapter takes advantage of how PHP stores arrays in its latest versions.
     *
     * @param string                 $file         The PHP file were values are cached
     * @param CacheItemPoolInterface $fallbackPool A pool to fallback on when an item is not hit
     */
    public static function create(string $file, CacheItemPoolInterface $fallbackPool): CacheItemPoolInterface
    {
        if (!$fallbackPool instanceof AdapterInterface) {
            $fallbackPool = new ProxyAdapter($fallbackPool);
        }
        return new static($file, $fallbackPool);
    }
    public function get(string $key, callable $callback, ?float $beta = null, ?array &$metadata = null): mixed
    {
        if (!isset($this->values)) {
            $this->initialize();
        }
        if (!isset($this->keys[$key])) {
            get_from_pool:
            if ($this->pool instanceof CacheInterface) {
                return $this->pool->get($key, $callback, $beta, $metadata);
            }
            return $this->doGet($this->pool, $key, $callback, $beta, $metadata);
        }
        $value = $this->values[$this->keys[$key]];
        if ('N;' === $value) {
            return null;
        }
        if (!$value instanceof CachedValueInterface) {
            return $value;
        }
        try {
            return $value->getValue();
        } catch (\Throwable) {
            unset($this->keys[$key]);
            goto get_from_pool;
        }
    }
    public function getItem(mixed $key): CacheItem
    {
        if (!\is_string($key)) {
            throw new InvalidArgumentException(\sprintf('Cache key must be string, "%s" given.', get_debug_type($key)));
        }
        if (!isset($this->values)) {
            $this->initialize();
        }
        if (!isset($this->keys[$key])) {
            return $this->pool->getItem($key);
        }
        $value = $this->values[$this->keys[$key]];
        $isHit = \true;
        if ('N;' === $value) {
            $value = null;
        } elseif ($value instanceof CachedValueInterface) {
            try {
                $value = $value->getValue();
            } catch (\Throwable) {
                $value = null;
                $isHit = \false;
            }
        }
        return (self::$createCacheItem)($key, $value, $isHit);
    }
    public function getItems(array $keys = []): iterable
    {
        foreach ($keys as $key) {
            if (!\is_string($key)) {
                throw new InvalidArgumentException(\sprintf('Cache key must be string, "%s" given.', get_debug_type($key)));
            }
        }
        if (!isset($this->values)) {
            $this->initialize();
        }
        return $this->generateItems($keys);
    }
    public function hasItem(mixed $key): bool
    {
        if (!\is_string($key)) {
            throw new InvalidArgumentException(\sprintf('Cache key must be string, "%s" given.', get_debug_type($key)));
        }
        if (!isset($this->values)) {
            $this->initialize();
        }
        return isset($this->keys[$key]) || $this->pool->hasItem($key);
    }
    public function deleteItem(mixed $key): bool
    {
        if (!\is_string($key)) {
            throw new InvalidArgumentException(\sprintf('Cache key must be string, "%s" given.', get_debug_type($key)));
        }
        if (!isset($this->values)) {
            $this->initialize();
        }
        return !isset($this->keys[$key]) && $this->pool->deleteItem($key);
    }
    public function deleteItems(array $keys): bool
    {
        $deleted = \true;
        $fallbackKeys = [];
        foreach ($keys as $key) {
            if (!\is_string($key)) {
                throw new InvalidArgumentException(\sprintf('Cache key must be string, "%s" given.', get_debug_type($key)));
            }
            if (isset($this->keys[$key])) {
                $deleted = \false;
            } else {
                $fallbackKeys[] = $key;
            }
        }
        if (!isset($this->values)) {
            $this->initialize();
        }
        if ($fallbackKeys) {
            $deleted = $this->pool->deleteItems($fallbackKeys) && $deleted;
        }
        return $deleted;
    }
    public function save(CacheItemInterface $item): bool
    {
        if (!isset($this->values)) {
            $this->initialize();
        }
        return !isset($this->keys[$item->getKey()]) && $this->pool->save($item);
    }
    public function saveDeferred(CacheItemInterface $item): bool
    {
        if (!isset($this->values)) {
            $this->initialize();
        }
        return !isset($this->keys[$item->getKey()]) && $this->pool->saveDeferred($item);
    }
    public function commit(): bool
    {
        return $this->pool->commit();
    }
    public function clear(string $prefix = ''): bool
    {
        $this->keys = $this->values = [];
        $cleared = @unlink($this->file) || !file_exists($this->file);
        unset(self::$valuesCache[$this->file]);
        if ($this->pool instanceof AdapterInterface) {
            return $this->pool->clear($prefix) && $cleared;
        }
        return $this->pool->clear() && $cleared;
    }
    /**
     * Store an array of cached values.
     *
     * @param array $values The cached values
     *
     * @return string[] A list of classes to preload on PHP 7.4+
     */
    public function warmUp(array $values): array
    {
        if (file_exists($this->file)) {
            if (!is_file($this->file)) {
                throw new InvalidArgumentException(\sprintf('Cache path exists and is not a file: "%s".', $this->file));
            }
            if (!is_writable($this->file)) {
                throw new InvalidArgumentException(\sprintf('Cache file is not writable: "%s".', $this->file));
            }
        } else {
            $directory = \dirname($this->file);
            if (!is_dir($directory) && !@mkdir($directory, 0777, \true)) {
                throw new InvalidArgumentException(\sprintf('Cache directory does not exist and cannot be created: "%s".', $directory));
            }
            if (!is_writable($directory)) {
                throw new InvalidArgumentException(\sprintf('Cache directory is not writable: "%s".', $directory));
            }
        }
        $preload = [];
        $dumpedValues = '';
        $dumpedMap = [];
        $dump = <<<'EOF'
<?php

// This file has been auto-generated by the Symfony Cache Component.

return [[


EOF;
        foreach ($values as $key => $value) {
            CacheItem::validateKey(\is_int($key) ? (string) $key : $key);
            $isStaticValue = \true;
            if (null === $value) {
                $value = "'N;'";
            } elseif (\is_object($value) || \is_array($value)) {
                try {
                    $value = VarExporter::export($value, $isStaticValue, $preload);
                } catch (\Exception $e) {
                    throw new InvalidArgumentException(\sprintf('Cache key "%s" has non-serializable "%s" value.', $key, get_debug_type($value)), 0, $e);
                }
            } elseif (\is_string($value)) {
                // Wrap "N;" in a closure to not confuse it with an encoded `null`
                if ('N;' === $value) {
                    $isStaticValue = \false;
                }
                $value = var_export($value, \true);
            } elseif (!\is_scalar($value)) {
                throw new InvalidArgumentException(\sprintf('Cache key "%s" has non-serializable "%s" value.', $key, get_debug_type($value)));
            } else {
                $value = var_export($value, \true);
            }
            if (!$isStaticValue) {
                $value = 'new class() implements \\' . CachedValueInterface::class . " { public function getValue(): mixed { return {$value}; } }";
            }
            $hash = hash('xxh128', $value);
            if (null === $id = $dumpedMap[$hash] ?? null) {
                $id = $dumpedMap[$hash] = \count($dumpedMap);
                $dumpedValues .= "{$id} => {$value},\n";
            }
            $dump .= var_export($key, \true) . " => {$id},\n";
        }
        $dump .= "\n], [\n\n{$dumpedValues}\n]];\n";
        $tmpFile = uniqid($this->file, \true);
        file_put_contents($tmpFile, $dump);
        @chmod($tmpFile, 0666 & ~umask());
        unset($serialized, $value, $dump);
        @rename($tmpFile, $this->file);
        unset(self::$valuesCache[$this->file]);
        $this->initialize();
        return $preload;
    }
    /**
     * Load the cache file.
     */
    private function initialize(): void
    {
        if (isset(self::$valuesCache[$this->file])) {
            $values = self::$valuesCache[$this->file];
        } elseif (!is_file($this->file)) {
            $this->keys = $this->values = [];
            return;
        } else {
            $values = self::$valuesCache[$this->file] = (include $this->file) ?: [[], []];
        }
        if (2 !== \count($values) || !isset($values[0], $values[1])) {
            $this->keys = $this->values = [];
        } else {
            [$this->keys, $this->values] = $values;
        }
    }
    private function generateItems(array $keys): \Generator
    {
        $f = self::$createCacheItem;
        $fallbackKeys = [];
        foreach ($keys as $key) {
            if (isset($this->keys[$key])) {
                $value = $this->values[$this->keys[$key]];
                if ('N;' === $value) {
                    yield $key => $f($key, null, \true);
                } elseif ($value instanceof CachedValueInterface) {
                    try {
                        yield $key => $f($key, $value->getValue(), \true);
                    } catch (\Throwable) {
                        yield $key => $f($key, null, \false);
                    }
                } else {
                    yield $key => $f($key, $value, \true);
                }
            } else {
                $fallbackKeys[] = $key;
            }
        }
        if ($fallbackKeys) {
            yield from $this->pool->getItems($fallbackKeys);
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Cache;

use _ContaoManager\Psr\Log\LoggerInterface;
use _ContaoManager\Symfony\Contracts\Cache\CacheInterface;
use _ContaoManager\Symfony\Contracts\Cache\ItemInterface;
/**
 * LockRegistry is used internally by existing adapters to protect against cache stampede.
 *
 * It does so by wrapping the computation of items in a pool of locks.
 * Foreach each apps, there can be at most 20 concurrent processes that
 * compute items at the same time and only one per cache-key.
 *
 * @author Nicolas Grekas <p@tchwork.com>
 */
final class LockRegistry
{
    private static array $openedFiles = [];
    private static ?array $lockedFiles = null;
    private static \Exception $signalingException;
    private static \Closure $signalingCallback;
    /**
     * The number of items in this list controls the max number of concurrent processes.
     */
    private static array $files = [__DIR__ . \DIRECTORY_SEPARATOR . 'Adapter' . \DIRECTORY_SEPARATOR . 'AbstractAdapter.php', __DIR__ . \DIRECTORY_SEPARATOR . 'Adapter' . \DIRECTORY_SEPARATOR . 'AbstractTagAwareAdapter.php', __DIR__ . \DIRECTORY_SEPARATOR . 'Adapter' . \DIRECTORY_SEPARATOR . 'AdapterInterface.php', __DIR__ . \DIRECTORY_SEPARATOR . 'Adapter' . \DIRECTORY_SEPARATOR . 'ApcuAdapter.php', __DIR__ . \DIRECTORY_SEPARATOR . 'Adapter' . \DIRECTORY_SEPARATOR . 'ArrayAdapter.php', __DIR__ . \DIRECTORY_SEPARATOR . 'Adapter' . \DIRECTORY_SEPARATOR . 'ChainAdapter.php', __DIR__ . \DIRECTORY_SEPARATOR . 'Adapter' . \DIRECTORY_SEPARATOR . 'CouchbaseBucketAdapter.php', __DIR__ . \DIRECTORY_SEPARATOR . 'Adapter' . \DIRECTORY_SEPARATOR . 'CouchbaseCollectionAdapter.php', __DIR__ . \DIRECTORY_SEPARATOR . 'Adapter' . \DIRECTORY_SEPARATOR . 'DoctrineDbalAdapter.php', __DIR__ . \DIRECTORY_SEPARATOR . 'Adapter' . \DIRECTORY_SEPARATOR . 'FilesystemAdapter.php', __DIR__ . \DIRECTORY_SEPARATOR . 'Adapter' . \DIRECTORY_SEPARATOR . 'FilesystemTagAwareAdapter.php', __DIR__ . \DIRECTORY_SEPARATOR . 'Adapter' . \DIRECTORY_SEPARATOR . 'MemcachedAdapter.php', __DIR__ . \DIRECTORY_SEPARATOR . 'Adapter' . \DIRECTORY_SEPARATOR . 'NullAdapter.php', __DIR__ . \DIRECTORY_SEPARATOR . 'Adapter' . \DIRECTORY_SEPARATOR . 'ParameterNormalizer.php', __DIR__ . \DIRECTORY_SEPARATOR . 'Adapter' . \DIRECTORY_SEPARATOR . 'PdoAdapter.php', __DIR__ . \DIRECTORY_SEPARATOR . 'Adapter' . \DIRECTORY_SEPARATOR . 'PhpArrayAdapter.php', __DIR__ . \DIRECTORY_SEPARATOR . 'Adapter' . \DIRECTORY_SEPARATOR . 'PhpFilesAdapter.php', __DIR__ . \DIRECTORY_SEPARATOR . 'Adapter' . \DIRECTORY_SEPARATOR . 'ProxyAdapter.php', __DIR__ . \DIRECTORY_SEPARATOR . 'Adapter' . \DIRECTORY_SEPARATOR . 'Psr16Adapter.php', __DIR__ . \DIRECTORY_SEPARATOR . 'Adapter' . \DIRECTORY_SEPARATOR . 'RedisAdapter.php', __DIR__ . \DIRECTORY_SEPARATOR . 'Adapter' . \DIRECTORY_SEPARATOR . 'RedisTagAwareAdapter.php', __DIR__ . \DIRECTORY_SEPARATOR . 'Adapter' . \DIRECTORY_SEPARATOR . 'TagAwareAdapter.php', __DIR__ . \DIRECTORY_SEPARATOR . 'Adapter' . \DIRECTORY_SEPARATOR . 'TagAwareAdapterInterface.php', __DIR__ . \DIRECTORY_SEPARATOR . 'Adapter' . \DIRECTORY_SEPARATOR . 'TraceableAdapter.php', __DIR__ . \DIRECTORY_SEPARATOR . 'Adapter' . \DIRECTORY_SEPARATOR . 'TraceableTagAwareAdapter.php'];
    /**
     * Defines a set of existing files that will be used as keys to acquire locks.
     *
     * @param list<string> $files A list of existing files
     *
     * @return list<string> The previously defined set of files
     */
    public static function setFiles(array $files): array
    {
        $previousFiles = self::$files;
        self::$files = array_values($files);
        foreach (self::$openedFiles as $file) {
            if ($file) {
                flock($file, \LOCK_UN);
                fclose($file);
            }
        }
        self::$openedFiles = self::$lockedFiles = [];
        return $previousFiles;
    }
    public static function compute(callable $callback, ItemInterface $item, bool &$save, CacheInterface $pool, ?\Closure $setMetadata = null, ?LoggerInterface $logger = null, ?float $beta = null): mixed
    {
        if ('\\' === \DIRECTORY_SEPARATOR && null === self::$lockedFiles) {
            // disable locking on Windows by default
            self::$files = self::$lockedFiles = [];
        }
        $key = self::$files ? abs(crc32($item->getKey())) % \count(self::$files) : -1;
        if ($key < 0 || self::$lockedFiles || !$lock = self::open($key)) {
            return $callback($item, $save);
        }
        self::$signalingException ??= unserialize("O:9:\"Exception\":1:{s:16:\"\x00Exception\x00trace\";a:0:{}}");
        self::$signalingCallback ??= static fn() => throw self::$signalingException;
        while (\true) {
            try {
                // race to get the lock in non-blocking mode
                $locked = flock($lock, \LOCK_EX | \LOCK_NB, $wouldBlock);
                if ($locked || !$wouldBlock) {
                    $logger?->info(\sprintf('Lock %s, now computing item "{key}"', $locked ? 'acquired' : 'not supported'), ['key' => $item->getKey()]);
                    self::$lockedFiles[$key] = \true;
                    $value = $callback($item, $save);
                    if ($save) {
                        if ($setMetadata) {
                            $setMetadata($item);
                        }
                        $pool->save($item->set($value));
                        $save = \false;
                    }
                    return $value;
                }
                // if we failed the race, retry locking in blocking mode to wait for the winner
                $logger?->info('Item "{key}" is locked, waiting for it to be released', ['key' => $item->getKey()]);
                $deadline = microtime(\true) + 30.0;
                $acquired = \false;
                do {
                    if ($acquired = flock($lock, \LOCK_SH | \LOCK_NB)) {
                        break;
                    }
                    usleep(100000);
                } while (microtime(\true) < $deadline);
                if (!$acquired) {
                    $logger?->warning('Lock on item "{key}" timed out, evicting slot', ['key' => $item->getKey()]);
                    unset(self::$files[$key]);
                    self::setFiles(self::$files);
                    $lock = null;
                    return self::compute($callback, $item, $save, $pool, $setMetadata, $logger, $beta);
                }
                if (\INF === $beta) {
                    $logger?->info('Force-recomputing item "{key}"', ['key' => $item->getKey()]);
                    continue;
                }
            } finally {
                if ($lock) {
                    flock($lock, \LOCK_UN);
                }
                unset(self::$lockedFiles[$key]);
            }
            try {
                $value = $pool->get($item->getKey(), self::$signalingCallback, 0);
                $logger?->info('Item "{key}" retrieved after lock was released', ['key' => $item->getKey()]);
                $save = \false;
                return $value;
            } catch (\Exception $e) {
                if (self::$signalingException !== $e) {
                    throw $e;
                }
                $logger?->info('Item "{key}" not found while lock was released, now retrying', ['key' => $item->getKey()]);
            }
        }
        return null;
    }
    /**
     * @return resource|false
     */
    private static function open(int $key)
    {
        if (null !== $h = self::$openedFiles[$key] ?? null) {
            return $h;
        }
        set_error_handler(static fn() => null);
        try {
            $h = fopen(self::$files[$key], 'r+');
        } finally {
            restore_error_handler();
        }
        return self::$openedFiles[$key] = $h ?: @fopen(self::$files[$key], 'r');
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Cache;

use _ContaoManager\Symfony\Contracts\Service\ResetInterface;
/**
 * Resets a pool's local state.
 */
interface ResettableInterface extends ResetInterface
{
}
Symfony PSR-6 implementation for caching
========================================

The Cache component provides extended
[PSR-6](https://www.php-fig.org/psr/psr-6/) implementations for adding cache to
your applications. It is designed to have a low overhead so that caching is
fastest. It ships with adapters for the most widespread caching backends.
It also provides a [PSR-16](https://www.php-fig.org/psr/psr-16/) adapter,
and implementations for [symfony/cache-contracts](https://github.com/symfony/cache-contracts)'
`CacheInterface` and `TagAwareCacheInterface`.

Resources
---------

 * [Documentation](https://symfony.com/doc/current/components/cache.html)
 * [Contributing](https://symfony.com/doc/current/contributing/index.html)
 * [Report issues](https://github.com/symfony/symfony/issues) and
   [send Pull Requests](https://github.com/symfony/symfony/pulls)
   in the [main Symfony repository](https://github.com/symfony/symfony)
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Cache\Messenger;

use _ContaoManager\Symfony\Component\Cache\CacheItem;
use _ContaoManager\Symfony\Component\DependencyInjection\ReverseContainer;
use _ContaoManager\Symfony\Component\Messenger\Attribute\AsMessageHandler;
/**
 * Computes cached values sent to a message bus.
 */
#[AsMessageHandler]
class EarlyExpirationHandler
{
    private ReverseContainer $reverseContainer;
    private array $processedNonces = [];
    public function __construct(ReverseContainer $reverseContainer)
    {
        $this->reverseContainer = $reverseContainer;
    }
    /**
     * @return void
     */
    public function __invoke(EarlyExpirationMessage $message)
    {
        $item = $message->getItem();
        $metadata = $item->getMetadata();
        $expiry = $metadata[CacheItem::METADATA_EXPIRY] ?? 0;
        $ctime = $metadata[CacheItem::METADATA_CTIME] ?? 0;
        if ($expiry && $ctime) {
            // skip duplicate or expired messages
            $processingNonce = [$expiry, $ctime];
            $pool = $message->getPool();
            $key = $item->getKey();
            if (($this->processedNonces[$pool][$key] ?? null) === $processingNonce) {
                return;
            }
            if (microtime(\true) >= $expiry) {
                return;
            }
            $this->processedNonces[$pool] = [$key => $processingNonce] + ($this->processedNonces[$pool] ?? []);
            if (\count($this->processedNonces[$pool]) > 100) {
                array_pop($this->processedNonces[$pool]);
            }
        }
        static $setMetadata;
        $setMetadata ??= \Closure::bind(function (CacheItem $item, float $startTime) {
            if ($item->expiry > $endTime = microtime(\true)) {
                $item->newMetadata[CacheItem::METADATA_EXPIRY] = $item->expiry;
                $item->newMetadata[CacheItem::METADATA_CTIME] = (int) ceil(1000 * ($endTime - $startTime));
            }
        }, null, CacheItem::class);
        $startTime = microtime(\true);
        $pool = $message->findPool($this->reverseContainer);
        $callback = $message->findCallback($this->reverseContainer);
        $save = \true;
        $value = $callback($item, $save);
        $setMetadata($item, $startTime);
        $pool->save($item->set($value));
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Cache\Messenger;

use _ContaoManager\Symfony\Component\Cache\Adapter\AdapterInterface;
use _ContaoManager\Symfony\Component\Cache\CacheItem;
use _ContaoManager\Symfony\Component\DependencyInjection\ReverseContainer;
/**
 * Conveys a cached value that needs to be computed.
 */
final class EarlyExpirationMessage
{
    private CacheItem $item;
    private string $pool;
    private string|array $callback;
    public static function create(ReverseContainer $reverseContainer, callable $callback, CacheItem $item, AdapterInterface $pool): ?self
    {
        try {
            $item = clone $item;
            $item->set(null);
        } catch (\Exception) {
            return null;
        }
        $pool = $reverseContainer->getId($pool);
        if ($callback instanceof \Closure && !str_contains(($r = new \ReflectionFunction($callback))->name, '{closure')) {
            $callback = [$r->getClosureThis() ?? (\PHP_VERSION_ID >= 80111 ? $r->getClosureCalledClass() : $r->getClosureScopeClass())?->name, $r->name];
            $callback[0] ?: $callback = $r->name;
        }
        if (\is_object($callback)) {
            if (null === $id = $reverseContainer->getId($callback)) {
                return null;
            }
            $callback = '@' . $id;
        } elseif (!\is_array($callback)) {
            $callback = (string) $callback;
        } elseif (!\is_object($callback[0])) {
            $callback = [(string) $callback[0], (string) $callback[1]];
        } else {
            if (null === $id = $reverseContainer->getId($callback[0])) {
                return null;
            }
            $callback = ['@' . $id, (string) $callback[1]];
        }
        return new self($item, $pool, $callback);
    }
    public function getItem(): CacheItem
    {
        return $this->item;
    }
    public function getPool(): string
    {
        return $this->pool;
    }
    /**
     * @return string|string[]
     */
    public function getCallback(): string|array
    {
        return $this->callback;
    }
    public function findPool(ReverseContainer $reverseContainer): AdapterInterface
    {
        return $reverseContainer->getService($this->pool);
    }
    public function findCallback(ReverseContainer $reverseContainer): callable
    {
        if (\is_string($callback = $this->callback)) {
            return '@' === $callback[0] ? $reverseContainer->getService(substr($callback, 1)) : $callback;
        }
        if ('@' === $callback[0][0]) {
            $callback[0] = $reverseContainer->getService(substr($callback[0], 1));
        }
        return $callback;
    }
    private function __construct(CacheItem $item, string $pool, string|array $callback)
    {
        $this->item = $item;
        $this->pool = $pool;
        $this->callback = $callback;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Cache\Messenger;

use _ContaoManager\Psr\Log\LoggerInterface;
use _ContaoManager\Symfony\Component\Cache\Adapter\AdapterInterface;
use _ContaoManager\Symfony\Component\Cache\CacheItem;
use _ContaoManager\Symfony\Component\DependencyInjection\ReverseContainer;
use _ContaoManager\Symfony\Component\Messenger\MessageBusInterface;
use _ContaoManager\Symfony\Component\Messenger\Stamp\HandledStamp;
/**
 * Sends the computation of cached values to a message bus.
 */
class EarlyExpirationDispatcher
{
    private MessageBusInterface $bus;
    private ReverseContainer $reverseContainer;
    private ?\Closure $callbackWrapper;
    public function __construct(MessageBusInterface $bus, ReverseContainer $reverseContainer, ?callable $callbackWrapper = null)
    {
        $this->bus = $bus;
        $this->reverseContainer = $reverseContainer;
        $this->callbackWrapper = null === $callbackWrapper ? null : $callbackWrapper(...);
    }
    /**
     * @return mixed
     */
    public function __invoke(callable $callback, CacheItem $item, bool &$save, AdapterInterface $pool, \Closure $setMetadata, ?LoggerInterface $logger = null, ?float $beta = null)
    {
        if (!$item->isHit() || null === $message = EarlyExpirationMessage::create($this->reverseContainer, $callback, $item, $pool)) {
            // The item is stale or the callback cannot be reversed: we must compute the value now
            $logger?->info('Computing item "{key}" online: ' . ($item->isHit() ? 'callback cannot be reversed' : 'item is stale'), ['key' => $item->getKey()]);
            return null !== $this->callbackWrapper ? ($this->callbackWrapper)($callback, $item, $save, $pool, $setMetadata, $logger, $beta) : $callback($item, $save);
        }
        $envelope = $this->bus->dispatch($message);
        if ($logger) {
            if ($envelope->last(HandledStamp::class)) {
                $logger->info('Item "{key}" was computed online', ['key' => $item->getKey()]);
            } else {
                $logger->info('Item "{key}" sent for recomputation', ['key' => $item->getKey()]);
            }
        }
        // The item's value is not stale, no need to write it to the backend
        $save = \false;
        return $message->getItem()->get() ?? $item->get();
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Cache\Marshaller;

use _ContaoManager\Symfony\Component\Cache\Exception\CacheException;
/**
 * Serializes/unserializes values using igbinary_serialize() if available, serialize() otherwise.
 *
 * @author Nicolas Grekas <p@tchwork.com>
 */
class DefaultMarshaller implements MarshallerInterface
{
    private bool $useIgbinarySerialize = \true;
    private bool $throwOnSerializationFailure = \false;
    public function __construct(?bool $useIgbinarySerialize = null, bool $throwOnSerializationFailure = \false)
    {
        if (null === $useIgbinarySerialize) {
            $useIgbinarySerialize = \extension_loaded('igbinary') && version_compare('3.1.6', phpversion('igbinary'), '<=');
        } elseif ($useIgbinarySerialize && (!\extension_loaded('igbinary') || version_compare('3.1.6', phpversion('igbinary'), '>'))) {
            throw new CacheException(\extension_loaded('igbinary') ? 'Please upgrade the "igbinary" PHP extension to v3.1.6 or higher.' : 'The "igbinary" PHP extension is not loaded.');
        }
        $this->useIgbinarySerialize = $useIgbinarySerialize;
        $this->throwOnSerializationFailure = $throwOnSerializationFailure;
    }
    public function marshall(array $values, ?array &$failed): array
    {
        $serialized = $failed = [];
        foreach ($values as $id => $value) {
            try {
                if ($this->useIgbinarySerialize) {
                    $serialized[$id] = igbinary_serialize($value);
                } else {
                    $serialized[$id] = serialize($value);
                }
            } catch (\Exception $e) {
                if ($this->throwOnSerializationFailure) {
                    throw new \ValueError($e->getMessage(), 0, $e);
                }
                $failed[] = $id;
            }
        }
        return $serialized;
    }
    public function unmarshall(string $value): mixed
    {
        if ('b:0;' === $value) {
            return \false;
        }
        if ('N;' === $value) {
            return null;
        }
        static $igbinaryNull;
        if ($value === $igbinaryNull ??= \extension_loaded('igbinary') ? igbinary_serialize(null) : \false) {
            return null;
        }
        $unserializeCallbackHandler = ini_set('unserialize_callback_func', __CLASS__ . '::handleUnserializeCallback');
        try {
            if (':' === ($value[1] ?? ':')) {
                if (\false !== $value = unserialize($value)) {
                    return $value;
                }
            } elseif (\false === $igbinaryNull) {
                throw new \RuntimeException('Failed to unserialize values, did you forget to install the "igbinary" extension?');
            } elseif (null !== $value = igbinary_unserialize($value)) {
                return $value;
            }
            throw new \DomainException(error_get_last() ? error_get_last()['message'] : 'Failed to unserialize values.');
        } catch (\Error $e) {
            throw new \ErrorException($e->getMessage(), $e->getCode(), \E_ERROR, $e->getFile(), $e->getLine());
        } finally {
            ini_set('unserialize_callback_func', $unserializeCallbackHandler);
        }
    }
    /**
     * @internal
     */
    public static function handleUnserializeCallback(string $class): never
    {
        throw new \DomainException('Class not found: ' . $class);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Cache\Marshaller;

use _ContaoManager\Symfony\Component\Cache\Exception\CacheException;
/**
 * Compresses values using gzdeflate().
 *
 * @author Nicolas Grekas <p@tchwork.com>
 */
class DeflateMarshaller implements MarshallerInterface
{
    private MarshallerInterface $marshaller;
    public function __construct(MarshallerInterface $marshaller)
    {
        if (!\function_exists('gzdeflate') && !\function_exists('_ContaoManager\gzdeflate')) {
            throw new CacheException('The "zlib" PHP extension is not loaded.');
        }
        $this->marshaller = $marshaller;
    }
    public function marshall(array $values, ?array &$failed): array
    {
        return array_map('gzdeflate', $this->marshaller->marshall($values, $failed));
    }
    public function unmarshall(string $value): mixed
    {
        if (\false !== $inflatedValue = @gzinflate($value)) {
            $value = $inflatedValue;
        }
        return $this->marshaller->unmarshall($value);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Cache\Marshaller;

/**
 * Serializes/unserializes PHP values.
 *
 * Implementations of this interface MUST deal with errors carefully. They MUST
 * also deal with forward and backward compatibility at the storage format level.
 *
 * @author Nicolas Grekas <p@tchwork.com>
 */
interface MarshallerInterface
{
    /**
     * Serializes a list of values.
     *
     * When serialization fails for a specific value, no exception should be
     * thrown. Instead, its key should be listed in $failed.
     */
    public function marshall(array $values, ?array &$failed): array;
    /**
     * Unserializes a single value and throws an exception if anything goes wrong.
     *
     * @throws \Exception Whenever unserialization fails
     */
    public function unmarshall(string $value): mixed;
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Cache\Marshaller;

/**
 * A marshaller optimized for data structures generated by AbstractTagAwareAdapter.
 *
 * @author Nicolas Grekas <p@tchwork.com>
 */
class TagAwareMarshaller implements MarshallerInterface
{
    private MarshallerInterface $marshaller;
    public function __construct(?MarshallerInterface $marshaller = null)
    {
        $this->marshaller = $marshaller ?? new DefaultMarshaller();
    }
    public function marshall(array $values, ?array &$failed): array
    {
        $failed = $notSerialized = $serialized = [];
        foreach ($values as $id => $value) {
            if (\is_array($value) && \is_array($value['tags'] ?? null) && \array_key_exists('value', $value) && \count($value) === 2 + (\is_string($value['meta'] ?? null) && 8 === \strlen($value['meta']))) {
                // if the value is an array with keys "tags", "value" and "meta", use a compact serialization format
                // magic numbers in the form 9D-..-..-..-..-00-..-..-..-5F allow detecting this format quickly in unmarshall()
                $v = $this->marshaller->marshall($value, $f);
                if ($f) {
                    $f = [];
                    $failed[] = $id;
                } else {
                    if ([] === $value['tags']) {
                        $v['tags'] = '';
                    }
                    $serialized[$id] = "\x9d" . ($value['meta'] ?? "\x00\x00\x00\x00\x00\x00\x00\x00") . pack('N', \strlen($v['tags'])) . $v['tags'] . $v['value'];
                    $serialized[$id][9] = "_";
                }
            } else {
                // other arbitrary values are serialized using the decorated marshaller below
                $notSerialized[$id] = $value;
            }
        }
        if ($notSerialized) {
            $serialized += $this->marshaller->marshall($notSerialized, $f);
            $failed = array_merge($failed, $f);
        }
        return $serialized;
    }
    public function unmarshall(string $value): mixed
    {
        // detect the compact format used in marshall() using magic numbers in the form 9D-..-..-..-..-00-..-..-..-5F
        if (13 >= \strlen($value) || "\x9d" !== $value[0] || "\x00" !== $value[5] || "_" !== $value[9]) {
            return $this->marshaller->unmarshall($value);
        }
        // data consists of value, tags and metadata which we need to unpack
        $meta = substr($value, 1, 12);
        $meta[8] = "\x00";
        $tagLen = unpack('Nlen', $meta, 8)['len'];
        $meta = substr($meta, 0, 8);
        return ['value' => $this->marshaller->unmarshall(substr($value, 13 + $tagLen)), 'tags' => $tagLen ? $this->marshaller->unmarshall(substr($value, 13, $tagLen)) : [], 'meta' => "\x00\x00\x00\x00\x00\x00\x00\x00" === $meta ? null : $meta];
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Cache\Marshaller;

use _ContaoManager\Symfony\Component\Cache\Exception\CacheException;
use _ContaoManager\Symfony\Component\Cache\Exception\InvalidArgumentException;
/**
 * Encrypt/decrypt values using Libsodium.
 *
 * @author Ahmed TAILOULOUTE <ahmed.tailouloute@gmail.com>
 */
class SodiumMarshaller implements MarshallerInterface
{
    private MarshallerInterface $marshaller;
    private array $decryptionKeys;
    /**
     * @param string[] $decryptionKeys The key at index "0" is required and is used to decrypt and encrypt values;
     *                                 more rotating keys can be provided to decrypt values;
     *                                 each key must be generated using sodium_crypto_box_keypair()
     */
    public function __construct(array $decryptionKeys, ?MarshallerInterface $marshaller = null)
    {
        if (!self::isSupported()) {
            throw new CacheException('The "sodium" PHP extension is not loaded.');
        }
        if (!isset($decryptionKeys[0])) {
            throw new InvalidArgumentException('At least one decryption key must be provided at index "0".');
        }
        $this->marshaller = $marshaller ?? new DefaultMarshaller();
        $this->decryptionKeys = $decryptionKeys;
    }
    public static function isSupported(): bool
    {
        return \function_exists('sodium_crypto_box_seal');
    }
    public function marshall(array $values, ?array &$failed): array
    {
        $encryptionKey = sodium_crypto_box_publickey($this->decryptionKeys[0]);
        $encryptedValues = [];
        foreach ($this->marshaller->marshall($values, $failed) as $k => $v) {
            $encryptedValues[$k] = sodium_crypto_box_seal($v, $encryptionKey);
        }
        return $encryptedValues;
    }
    public function unmarshall(string $value): mixed
    {
        foreach ($this->decryptionKeys as $k) {
            if (\false !== $decryptedValue = @sodium_crypto_box_seal_open($value, $k)) {
                $value = $decryptedValue;
                break;
            }
        }
        return $this->marshaller->unmarshall($value);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Cache\DependencyInjection;

use _ContaoManager\Symfony\Component\Cache\Adapter\AbstractAdapter;
use _ContaoManager\Symfony\Component\Cache\Adapter\ArrayAdapter;
use _ContaoManager\Symfony\Component\Cache\Adapter\ChainAdapter;
use _ContaoManager\Symfony\Component\Cache\Adapter\NullAdapter;
use _ContaoManager\Symfony\Component\Cache\Adapter\ParameterNormalizer;
use _ContaoManager\Symfony\Component\Cache\Adapter\TagAwareAdapter;
use _ContaoManager\Symfony\Component\Cache\Messenger\EarlyExpirationDispatcher;
use _ContaoManager\Symfony\Component\Cache\PruneableInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\ChildDefinition;
use _ContaoManager\Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerBuilder;
use _ContaoManager\Symfony\Component\DependencyInjection\Definition;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
use _ContaoManager\Symfony\Component\DependencyInjection\Reference;
/**
 * @author Nicolas Grekas <p@tchwork.com>
 */
class CachePoolPass implements CompilerPassInterface
{
    /**
     * @return void
     */
    public function process(ContainerBuilder $container)
    {
        if ($container->hasParameter('cache.prefix.seed')) {
            $seed = $container->getParameterBag()->resolveValue($container->getParameter('cache.prefix.seed'));
        } else {
            $seed = '_' . $container->getParameter('kernel.project_dir');
            $seed .= '.' . $container->getParameter('kernel.container_class');
        }
        $needsMessageHandler = \false;
        $allPools = [];
        $clearers = [];
        $attributes = ['provider', 'name', 'namespace', 'default_lifetime', 'early_expiration_message_bus', 'reset', 'pruneable'];
        foreach ($container->findTaggedServiceIds('cache.pool') as $id => $tags) {
            $adapter = $pool = $container->getDefinition($id);
            if ($pool->isAbstract()) {
                continue;
            }
            $class = $adapter->getClass();
            $providers = $adapter->getArguments();
            while ($adapter instanceof ChildDefinition) {
                $adapter = $container->findDefinition($adapter->getParent());
                $class = $class ?: $adapter->getClass();
                $providers += $adapter->getArguments();
                if ($t = $adapter->getTag('cache.pool')) {
                    $tags[0] += $t[0];
                }
            }
            $name = $tags[0]['name'] ?? $id;
            if (!isset($tags[0]['namespace'])) {
                $namespaceSeed = $seed;
                if (null !== $class) {
                    $namespaceSeed .= '.' . $class;
                }
                $tags[0]['namespace'] = $this->getNamespace($namespaceSeed, $name);
            }
            if (isset($tags[0]['clearer'])) {
                $clearer = $tags[0]['clearer'];
                while ($container->hasAlias($clearer)) {
                    $clearer = (string) $container->getAlias($clearer);
                }
            } else {
                $clearer = null;
            }
            unset($tags[0]['clearer'], $tags[0]['name']);
            if (isset($tags[0]['provider'])) {
                $tags[0]['provider'] = new Reference(static::getServiceProvider($container, $tags[0]['provider']));
            }
            $pruneable = $tags[0]['pruneable'] ?? $container->getReflectionClass($class, \false)?->implementsInterface(PruneableInterface::class) ?? \false;
            if (ChainAdapter::class === $class) {
                $adapters = [];
                foreach ($providers['index_0'] ?? $providers[0] as $provider => $adapter) {
                    if ($adapter instanceof ChildDefinition) {
                        $chainedPool = clone $adapter;
                    } else {
                        $chainedPool = $adapter = new ChildDefinition($adapter);
                    }
                    $chainedTags = [\is_int($provider) ? [] : ['provider' => $provider]];
                    $chainedClass = '';
                    while ($adapter instanceof ChildDefinition) {
                        $adapter = $container->findDefinition($adapter->getParent());
                        $chainedClass = $chainedClass ?: $adapter->getClass();
                        if ($t = $adapter->getTag('cache.pool')) {
                            $chainedTags[0] += $t[0];
                        }
                    }
                    if (ChainAdapter::class === $chainedClass) {
                        throw new InvalidArgumentException(\sprintf('Invalid service "%s": chain of adapters cannot reference another chain, found "%s".', $id, $chainedPool->getParent()));
                    }
                    $i = 0;
                    if (isset($chainedTags[0]['provider'])) {
                        $chainedPool->replaceArgument($i++, new Reference(static::getServiceProvider($container, $chainedTags[0]['provider'])));
                    }
                    if (isset($tags[0]['namespace']) && !\in_array($adapter->getClass(), [ArrayAdapter::class, NullAdapter::class], \true)) {
                        $chainedPool->replaceArgument($i++, $tags[0]['namespace']);
                    }
                    if (isset($tags[0]['default_lifetime'])) {
                        $chainedPool->replaceArgument($i++, $tags[0]['default_lifetime']);
                    }
                    $adapters[] = $chainedPool;
                }
                $pool->replaceArgument(0, $adapters);
                unset($tags[0]['provider'], $tags[0]['namespace']);
                $i = 1;
            } else {
                $i = 0;
            }
            foreach ($attributes as $attr) {
                if (!isset($tags[0][$attr])) {
                    // no-op
                } elseif ('reset' === $attr) {
                    if ($tags[0][$attr]) {
                        $pool->addTag('kernel.reset', ['method' => $tags[0][$attr]]);
                    }
                } elseif ('early_expiration_message_bus' === $attr) {
                    $needsMessageHandler = \true;
                    $pool->addMethodCall('setCallbackWrapper', [(new Definition(EarlyExpirationDispatcher::class))->addArgument(new Reference($tags[0]['early_expiration_message_bus']))->addArgument(new Reference('reverse_container'))->addArgument((new Definition('callable'))->setFactory([new Reference($id), 'setCallbackWrapper'])->addArgument(null))]);
                    $pool->addTag('container.reversible');
                } elseif ('pruneable' === $attr) {
                    // no-op
                } elseif ('namespace' !== $attr || !\in_array($class, [ArrayAdapter::class, NullAdapter::class, TagAwareAdapter::class], \true)) {
                    $argument = $tags[0][$attr];
                    if ('default_lifetime' === $attr && !is_numeric($argument)) {
                        $argument = (new Definition('int', [$argument]))->setFactory([ParameterNormalizer::class, 'normalizeDuration']);
                    }
                    $pool->replaceArgument($i++, $argument);
                }
                unset($tags[0][$attr]);
            }
            if (!empty($tags[0])) {
                throw new InvalidArgumentException(\sprintf('Invalid "cache.pool" tag for service "%s": accepted attributes are "clearer", "provider", "name", "namespace", "default_lifetime", "early_expiration_message_bus", "reset" and "pruneable", found "%s".', $id, implode('", "', array_keys($tags[0]))));
            }
            if (null !== $clearer) {
                $clearers[$clearer][$name] = new Reference($id, $container::IGNORE_ON_UNINITIALIZED_REFERENCE);
            }
            $poolTags = $pool->getTags();
            $poolTags['cache.pool'][0]['pruneable'] ??= $pruneable;
            $pool->setTags($poolTags);
            $allPools[$name] = new Reference($id, $container::IGNORE_ON_UNINITIALIZED_REFERENCE);
        }
        if (!$needsMessageHandler) {
            $container->removeDefinition('cache.early_expiration_handler');
        }
        $notAliasedCacheClearerId = 'cache.global_clearer';
        while ($container->hasAlias($notAliasedCacheClearerId)) {
            $notAliasedCacheClearerId = (string) $container->getAlias($notAliasedCacheClearerId);
        }
        if ($container->hasDefinition($notAliasedCacheClearerId)) {
            $clearers[$notAliasedCacheClearerId] = $allPools;
        }
        foreach ($clearers as $id => $pools) {
            $clearer = $container->getDefinition($id);
            if ($clearer instanceof ChildDefinition) {
                $clearer->replaceArgument(0, $pools);
            } else {
                $clearer->setArgument(0, $pools);
            }
            $clearer->addTag('cache.pool.clearer');
        }
        $allPoolsKeys = array_keys($allPools);
        if ($container->hasDefinition('console.command.cache_pool_list')) {
            $container->getDefinition('console.command.cache_pool_list')->replaceArgument(0, $allPoolsKeys);
        }
        if ($container->hasDefinition('console.command.cache_pool_clear')) {
            $container->getDefinition('console.command.cache_pool_clear')->addArgument($allPoolsKeys);
        }
        if ($container->hasDefinition('console.command.cache_pool_delete')) {
            $container->getDefinition('console.command.cache_pool_delete')->addArgument($allPoolsKeys);
        }
    }
    private function getNamespace(string $seed, string $id): string
    {
        return substr(str_replace('/', '-', base64_encode(hash('sha256', $id . $seed, \true))), 0, 10);
    }
    /**
     * @internal
     */
    public static function getServiceProvider(ContainerBuilder $container, string $name): string
    {
        $container->resolveEnvPlaceholders($name, null, $usedEnvs);
        if ($usedEnvs || preg_match('#^[a-z]++:#', $name)) {
            $dsn = $name;
            if (!$container->hasDefinition($name = '.cache_connection.' . ContainerBuilder::hash($dsn))) {
                $definition = new Definition(AbstractAdapter::class);
                $definition->setFactory([AbstractAdapter::class, 'createConnection']);
                $definition->setArguments([$dsn, ['lazy' => \true]]);
                $container->setDefinition($name, $definition);
            }
        }
        return $name;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Cache\DependencyInjection;

use _ContaoManager\Symfony\Component\Cache\PruneableInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Argument\IteratorArgument;
use _ContaoManager\Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerBuilder;
use _ContaoManager\Symfony\Component\DependencyInjection\Reference;
/**
 * @author Rob Frawley 2nd <rmf@src.run>
 */
class CachePoolPrunerPass implements CompilerPassInterface
{
    /**
     * @return void
     */
    public function process(ContainerBuilder $container)
    {
        if (!$container->hasDefinition('console.command.cache_pool_prune')) {
            return;
        }
        $services = [];
        foreach ($container->findTaggedServiceIds('cache.pool') as $id => $tags) {
            if ($tags[0]['pruneable'] ?? $container->getReflectionClass($container->getDefinition($id)->getClass(), \false)?->implementsInterface(PruneableInterface::class) ?? \false) {
                $services[$tags[0]['name'] ?? $id] = new Reference($id);
            }
        }
        $container->getDefinition('console.command.cache_pool_prune')->replaceArgument(0, new IteratorArgument($services));
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Cache\DependencyInjection;

use _ContaoManager\Symfony\Component\Cache\Adapter\TagAwareAdapterInterface;
use _ContaoManager\Symfony\Component\Cache\Adapter\TraceableAdapter;
use _ContaoManager\Symfony\Component\Cache\Adapter\TraceableTagAwareAdapter;
use _ContaoManager\Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerBuilder;
use _ContaoManager\Symfony\Component\DependencyInjection\Definition;
use _ContaoManager\Symfony\Component\DependencyInjection\Reference;
/**
 * Inject a data collector to all the cache services to be able to get detailed statistics.
 *
 * @author Tobias Nyholm <tobias.nyholm@gmail.com>
 */
class CacheCollectorPass implements CompilerPassInterface
{
    /**
     * @return void
     */
    public function process(ContainerBuilder $container)
    {
        if (!$container->hasDefinition('data_collector.cache')) {
            return;
        }
        foreach ($container->findTaggedServiceIds('cache.pool') as $id => $attributes) {
            $poolName = $attributes[0]['name'] ?? $id;
            $this->addToCollector($id, $poolName, $container);
        }
    }
    private function addToCollector(string $id, string $name, ContainerBuilder $container): void
    {
        $definition = $container->getDefinition($id);
        if ($definition->isAbstract()) {
            return;
        }
        $collectorDefinition = $container->getDefinition('data_collector.cache');
        $recorder = new Definition(is_subclass_of($definition->getClass(), TagAwareAdapterInterface::class) ? TraceableTagAwareAdapter::class : TraceableAdapter::class);
        $recorder->setTags($definition->getTags());
        if (!$definition->isPublic() || !$definition->isPrivate()) {
            $recorder->setPublic($definition->isPublic());
        }
        $recorder->setArguments([new Reference($innerId = $id . '.recorder_inner')]);
        foreach ($definition->getMethodCalls() as [$method, $args]) {
            if ('setCallbackWrapper' !== $method || !$args[0] instanceof Definition || !($args[0]->getArguments()[2] ?? null) instanceof Definition) {
                continue;
            }
            if ([new Reference($id), 'setCallbackWrapper'] == $args[0]->getArguments()[2]->getFactory()) {
                $args[0]->getArguments()[2]->setFactory([new Reference($innerId), 'setCallbackWrapper']);
            }
        }
        $definition->setTags([]);
        $definition->setPublic(\false);
        $container->setDefinition($innerId, $definition);
        $container->setDefinition($id, $recorder);
        // Tell the collector to add the new instance
        $collectorDefinition->addMethodCall('addInstance', [$name, new Reference($id)]);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Cache\DependencyInjection;

use _ContaoManager\Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerBuilder;
use _ContaoManager\Symfony\Component\DependencyInjection\Reference;
/**
 * @author Nicolas Grekas <p@tchwork.com>
 */
class CachePoolClearerPass implements CompilerPassInterface
{
    /**
     * @return void
     */
    public function process(ContainerBuilder $container)
    {
        $container->getParameterBag()->remove('cache.prefix.seed');
        foreach ($container->findTaggedServiceIds('cache.pool.clearer') as $id => $attr) {
            $clearer = $container->getDefinition($id);
            $pools = [];
            foreach ($clearer->getArgument(0) as $name => $ref) {
                if ($container->hasDefinition($ref)) {
                    $pools[$name] = new Reference($ref);
                }
            }
            $clearer->replaceArgument(0, $pools);
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Cache\Exception;

use _ContaoManager\Psr\Cache\CacheException as Psr6CacheInterface;
use _ContaoManager\Psr\SimpleCache\CacheException as SimpleCacheInterface;
if (interface_exists(SimpleCacheInterface::class)) {
    class LogicException extends \LogicException implements Psr6CacheInterface, SimpleCacheInterface
    {
    }
} else {
    class LogicException extends \LogicException implements Psr6CacheInterface
    {
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Cache\Exception;

use _ContaoManager\Psr\Cache\InvalidArgumentException as Psr6CacheInterface;
use _ContaoManager\Psr\SimpleCache\InvalidArgumentException as SimpleCacheInterface;
if (interface_exists(SimpleCacheInterface::class)) {
    class InvalidArgumentException extends \InvalidArgumentException implements Psr6CacheInterface, SimpleCacheInterface
    {
    }
} else {
    class InvalidArgumentException extends \InvalidArgumentException implements Psr6CacheInterface
    {
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Cache\Exception;

use _ContaoManager\Psr\Cache\CacheException as Psr6CacheInterface;
use _ContaoManager\Psr\SimpleCache\CacheException as SimpleCacheInterface;
if (interface_exists(SimpleCacheInterface::class)) {
    class CacheException extends \Exception implements Psr6CacheInterface, SimpleCacheInterface
    {
    }
} else {
    class CacheException extends \Exception implements Psr6CacheInterface
    {
    }
}
{
    "name": "symfony\/cache",
    "type": "library",
    "description": "Provides extended PSR-6, PSR-16 (and tags) implementations",
    "keywords": [
        "caching",
        "psr6"
    ],
    "homepage": "https:\/\/symfony.com",
    "license": "MIT",
    "authors": [
        {
            "name": "Nicolas Grekas",
            "email": "p@tchwork.com"
        },
        {
            "name": "Symfony Community",
            "homepage": "https:\/\/symfony.com\/contributors"
        }
    ],
    "provide": {
        "psr\/cache-implementation": "2.0|3.0",
        "psr\/simple-cache-implementation": "1.0|2.0|3.0",
        "symfony\/cache-implementation": "1.1|2.0|3.0"
    },
    "require": {
        "php": ">=8.1",
        "psr\/cache": "^2.0|^3.0",
        "psr\/log": "^1.1|^2|^3",
        "symfony\/cache-contracts": "^2.5|^3",
        "symfony\/service-contracts": "^2.5|^3",
        "symfony\/var-exporter": "^6.3.6|^7.0"
    },
    "require-dev": {
        "cache\/integration-tests": "dev-master",
        "doctrine\/dbal": "^2.13.1|^3|^4",
        "predis\/predis": "^1.1|^2.0",
        "psr\/simple-cache": "^1.0|^2.0|^3.0",
        "symfony\/config": "^5.4|^6.0|^7.0",
        "symfony\/dependency-injection": "^5.4|^6.0|^7.0",
        "symfony\/filesystem": "^5.4|^6.0|^7.0",
        "symfony\/http-kernel": "^5.4|^6.0|^7.0",
        "symfony\/messenger": "^5.4|^6.0|^7.0",
        "symfony\/var-dumper": "^5.4|^6.0|^7.0"
    },
    "conflict": {
        "doctrine\/dbal": "<2.13.1",
        "symfony\/dependency-injection": "<5.4",
        "symfony\/http-kernel": "<5.4",
        "symfony\/var-dumper": "<5.4"
    },
    "autoload": {
        "psr-4": {
            "_ContaoManager\\Symfony\\Component\\Cache\\": ""
        },
        "classmap": [
            "Traits\/ValueWrapper.php"
        ],
        "exclude-from-classmap": [
            "\/Tests\/"
        ]
    },
    "minimum-stability": "dev"
}<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

use Symfony\Polyfill\Ctype as p;

if (!function_exists('ctype_alnum')) {
    function ctype_alnum(mixed $text): bool { return p\Ctype::ctype_alnum($text); }
}
if (!function_exists('ctype_alpha')) {
    function ctype_alpha(mixed $text): bool { return p\Ctype::ctype_alpha($text); }
}
if (!function_exists('ctype_cntrl')) {
    function ctype_cntrl(mixed $text): bool { return p\Ctype::ctype_cntrl($text); }
}
if (!function_exists('ctype_digit')) {
    function ctype_digit(mixed $text): bool { return p\Ctype::ctype_digit($text); }
}
if (!function_exists('ctype_graph')) {
    function ctype_graph(mixed $text): bool { return p\Ctype::ctype_graph($text); }
}
if (!function_exists('ctype_lower')) {
    function ctype_lower(mixed $text): bool { return p\Ctype::ctype_lower($text); }
}
if (!function_exists('ctype_print')) {
    function ctype_print(mixed $text): bool { return p\Ctype::ctype_print($text); }
}
if (!function_exists('ctype_punct')) {
    function ctype_punct(mixed $text): bool { return p\Ctype::ctype_punct($text); }
}
if (!function_exists('ctype_space')) {
    function ctype_space(mixed $text): bool { return p\Ctype::ctype_space($text); }
}
if (!function_exists('ctype_upper')) {
    function ctype_upper(mixed $text): bool { return p\Ctype::ctype_upper($text); }
}
if (!function_exists('ctype_xdigit')) {
    function ctype_xdigit(mixed $text): bool { return p\Ctype::ctype_xdigit($text); }
}
Copyright (c) 2018-present Fabien Potencier

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is furnished
to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

use Symfony\Polyfill\Ctype as p;

if (\PHP_VERSION_ID >= 80000) {
    return require __DIR__.'/bootstrap80.php';
}

if (!function_exists('ctype_alnum')) {
    function ctype_alnum($text) { return p\Ctype::ctype_alnum($text); }
}
if (!function_exists('ctype_alpha')) {
    function ctype_alpha($text) { return p\Ctype::ctype_alpha($text); }
}
if (!function_exists('ctype_cntrl')) {
    function ctype_cntrl($text) { return p\Ctype::ctype_cntrl($text); }
}
if (!function_exists('ctype_digit')) {
    function ctype_digit($text) { return p\Ctype::ctype_digit($text); }
}
if (!function_exists('ctype_graph')) {
    function ctype_graph($text) { return p\Ctype::ctype_graph($text); }
}
if (!function_exists('ctype_lower')) {
    function ctype_lower($text) { return p\Ctype::ctype_lower($text); }
}
if (!function_exists('ctype_print')) {
    function ctype_print($text) { return p\Ctype::ctype_print($text); }
}
if (!function_exists('ctype_punct')) {
    function ctype_punct($text) { return p\Ctype::ctype_punct($text); }
}
if (!function_exists('ctype_space')) {
    function ctype_space($text) { return p\Ctype::ctype_space($text); }
}
if (!function_exists('ctype_upper')) {
    function ctype_upper($text) { return p\Ctype::ctype_upper($text); }
}
if (!function_exists('ctype_xdigit')) {
    function ctype_xdigit($text) { return p\Ctype::ctype_xdigit($text); }
}
Symfony Polyfill / Ctype
========================

This component provides `ctype_*` functions to users who run php versions without the ctype extension.

More information can be found in the
[main Polyfill README](https://github.com/symfony/polyfill/blob/main/README.md).

License
=======

This library is released under the [MIT license](LICENSE).
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Symfony\Polyfill\Ctype;

/**
 * Ctype implementation through regex.
 *
 * @internal
 *
 * @author Gert de Pagter <BackEndTea@gmail.com>
 */
final class Ctype
{
    /**
     * Returns TRUE if every character in text is either a letter or a digit, FALSE otherwise.
     *
     * @see https://php.net/ctype-alnum
     *
     * @param mixed $text
     *
     * @return bool
     */
    public static function ctype_alnum($text)
    {
        $text = self::convert_int_to_char_for_ctype($text, __FUNCTION__);
        return \is_string($text) && '' !== $text && !preg_match('/[^A-Za-z0-9]/', $text);
    }
    /**
     * Returns TRUE if every character in text is a letter, FALSE otherwise.
     *
     * @see https://php.net/ctype-alpha
     *
     * @param mixed $text
     *
     * @return bool
     */
    public static function ctype_alpha($text)
    {
        $text = self::convert_int_to_char_for_ctype($text, __FUNCTION__);
        return \is_string($text) && '' !== $text && !preg_match('/[^A-Za-z]/', $text);
    }
    /**
     * Returns TRUE if every character in text is a control character from the current locale, FALSE otherwise.
     *
     * @see https://php.net/ctype-cntrl
     *
     * @param mixed $text
     *
     * @return bool
     */
    public static function ctype_cntrl($text)
    {
        $text = self::convert_int_to_char_for_ctype($text, __FUNCTION__);
        return \is_string($text) && '' !== $text && !preg_match('/[^\x00-\x1f\x7f]/', $text);
    }
    /**
     * Returns TRUE if every character in the string text is a decimal digit, FALSE otherwise.
     *
     * @see https://php.net/ctype-digit
     *
     * @param mixed $text
     *
     * @return bool
     */
    public static function ctype_digit($text)
    {
        $text = self::convert_int_to_char_for_ctype($text, __FUNCTION__);
        return \is_string($text) && '' !== $text && !preg_match('/[^0-9]/', $text);
    }
    /**
     * Returns TRUE if every character in text is printable and actually creates visible output (no white space), FALSE otherwise.
     *
     * @see https://php.net/ctype-graph
     *
     * @param mixed $text
     *
     * @return bool
     */
    public static function ctype_graph($text)
    {
        $text = self::convert_int_to_char_for_ctype($text, __FUNCTION__);
        return \is_string($text) && '' !== $text && !preg_match('/[^!-~]/', $text);
    }
    /**
     * Returns TRUE if every character in text is a lowercase letter.
     *
     * @see https://php.net/ctype-lower
     *
     * @param mixed $text
     *
     * @return bool
     */
    public static function ctype_lower($text)
    {
        $text = self::convert_int_to_char_for_ctype($text, __FUNCTION__);
        return \is_string($text) && '' !== $text && !preg_match('/[^a-z]/', $text);
    }
    /**
     * Returns TRUE if every character in text will actually create output (including blanks). Returns FALSE if text contains control characters or characters that do not have any output or control function at all.
     *
     * @see https://php.net/ctype-print
     *
     * @param mixed $text
     *
     * @return bool
     */
    public static function ctype_print($text)
    {
        $text = self::convert_int_to_char_for_ctype($text, __FUNCTION__);
        return \is_string($text) && '' !== $text && !preg_match('/[^ -~]/', $text);
    }
    /**
     * Returns TRUE if every character in text is printable, but neither letter, digit or blank, FALSE otherwise.
     *
     * @see https://php.net/ctype-punct
     *
     * @param mixed $text
     *
     * @return bool
     */
    public static function ctype_punct($text)
    {
        $text = self::convert_int_to_char_for_ctype($text, __FUNCTION__);
        return \is_string($text) && '' !== $text && !preg_match('/[^!-\/\:-@\[-`\{-~]/', $text);
    }
    /**
     * Returns TRUE if every character in text creates some sort of white space, FALSE otherwise. Besides the blank character this also includes tab, vertical tab, line feed, carriage return and form feed characters.
     *
     * @see https://php.net/ctype-space
     *
     * @param mixed $text
     *
     * @return bool
     */
    public static function ctype_space($text)
    {
        $text = self::convert_int_to_char_for_ctype($text, __FUNCTION__);
        return \is_string($text) && '' !== $text && !preg_match('/[^\s]/', $text);
    }
    /**
     * Returns TRUE if every character in text is an uppercase letter.
     *
     * @see https://php.net/ctype-upper
     *
     * @param mixed $text
     *
     * @return bool
     */
    public static function ctype_upper($text)
    {
        $text = self::convert_int_to_char_for_ctype($text, __FUNCTION__);
        return \is_string($text) && '' !== $text && !preg_match('/[^A-Z]/', $text);
    }
    /**
     * Returns TRUE if every character in text is a hexadecimal 'digit', that is a decimal digit or a character from [A-Fa-f] , FALSE otherwise.
     *
     * @see https://php.net/ctype-xdigit
     *
     * @param mixed $text
     *
     * @return bool
     */
    public static function ctype_xdigit($text)
    {
        $text = self::convert_int_to_char_for_ctype($text, __FUNCTION__);
        return \is_string($text) && '' !== $text && !preg_match('/[^A-Fa-f0-9]/', $text);
    }
    /**
     * Converts integers to their char versions according to normal ctype behaviour, if needed.
     *
     * If an integer between -128 and 255 inclusive is provided,
     * it is interpreted as the ASCII value of a single character
     * (negative values have 256 added in order to allow characters in the Extended ASCII range).
     * Any other integer is interpreted as a string containing the decimal digits of the integer.
     *
     * @param mixed  $int
     * @param string $function
     *
     * @return mixed
     */
    private static function convert_int_to_char_for_ctype($int, $function)
    {
        if (\PHP_VERSION_ID >= 80100 && !\is_string($int)) {
            @trigger_error($function . '(): Argument of type ' . get_debug_type($int) . ' will be interpreted as string in the future', \E_USER_DEPRECATED);
        }
        if (!\is_int($int)) {
            return $int;
        }
        if ($int < -128 || $int > 255) {
            return (string) $int;
        }
        if ($int < 0) {
            $int += 256;
        }
        return \chr($int);
    }
}
{
    "name": "symfony\/polyfill-ctype",
    "type": "library",
    "description": "Symfony polyfill for ctype functions",
    "keywords": [
        "polyfill",
        "compatibility",
        "portable",
        "ctype"
    ],
    "homepage": "https:\/\/symfony.com",
    "license": "MIT",
    "authors": [
        {
            "name": "Gert de Pagter",
            "email": "BackEndTea@gmail.com"
        },
        {
            "name": "Symfony Community",
            "homepage": "https:\/\/symfony.com\/contributors"
        }
    ],
    "require": {
        "php": ">=7.2"
    },
    "provide": {
        "ext-ctype": "*"
    },
    "autoload": {
        "psr-4": {
            "Symfony\\Polyfill\\Ctype\\": ""
        },
        "files": [
            "bootstrap.php"
        ]
    },
    "suggest": {
        "ext-ctype": "For best performance"
    },
    "minimum-stability": "dev",
    "extra": {
        "thanks": {
            "name": "symfony\/polyfill",
            "url": "https:\/\/github.com\/symfony\/polyfill"
        }
    }
}Copyright (c) 2021-present Fabien Potencier

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is furnished
to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

if (\PHP_VERSION_ID < 80100) {
    #[Attribute(Attribute::TARGET_METHOD)]
    final class ReturnTypeWillChange
    {
        public function __construct()
        {
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

if (\PHP_VERSION_ID >= 70400 && extension_loaded('curl')) {
    /**
     * @property string $data
     */
    class CURLStringFile extends CURLFile
    {
        private $data;

        public function __construct(string $data, string $postname, string $mime = 'application/octet-stream')
        {
            $this->data = $data;
            parent::__construct('data://application/octet-stream;base64,'.base64_encode($data), $mime, $postname);
        }

        public function __set(string $name, $value): void
        {
            if ('data' !== $name) {
                $this->$name = $value;

                return;
            }

            if (is_object($value) ? !method_exists($value, '__toString') : !is_scalar($value)) {
                throw new TypeError('Cannot assign '.gettype($value).' to property CURLStringFile::$data of type string');
            }

            $this->name = 'data://application/octet-stream;base64,'.base64_encode($value);
        }

        public function __isset(string $name): bool
        {
            return isset($this->$name);
        }

        public function &__get(string $name)
        {
            return $this->$name;
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

use Symfony\Polyfill\Php81 as p;

if (\PHP_VERSION_ID >= 80100) {
    return;
}

if (defined('MYSQLI_REFRESH_SLAVE') && !defined('MYSQLI_REFRESH_REPLICA')) {
    define('MYSQLI_REFRESH_REPLICA', 64);
}

if (!function_exists('array_is_list')) {
    function array_is_list(array $array): bool { return p\Php81::array_is_list($array); }
}

if (!function_exists('enum_exists')) {
    function enum_exists(string $enum, bool $autoload = true): bool { return $autoload && class_exists($enum) && false; }
}
Symfony Polyfill / Php81
========================

This component provides features added to PHP 8.1 core:

- [`array_is_list`](https://php.net/array_is_list)
- [`enum_exists`](https://php.net/enum-exists)
- [`MYSQLI_REFRESH_REPLICA`](https://php.net/mysqli.constants#constantmysqli-refresh-replica) constant
- [`ReturnTypeWillChange`](https://wiki.php.net/rfc/internal_method_return_types)
- [`CURLStringFile`](https://php.net/CURLStringFile) (but only if PHP >= 7.4 is used)

More information can be found in the
[main Polyfill README](https://github.com/symfony/polyfill/blob/main/README.md).

License
=======

This library is released under the [MIT license](LICENSE).
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Symfony\Polyfill\Php81;

/**
 * @author Nicolas Grekas <p@tchwork.com>
 *
 * @internal
 */
final class Php81
{
    public static function array_is_list(array $array): bool
    {
        if ([] === $array || $array === array_values($array)) {
            return \true;
        }
        $nextKey = -1;
        foreach ($array as $k => $v) {
            if ($k !== ++$nextKey) {
                return \false;
            }
        }
        return \true;
    }
}
{
    "name": "symfony\/polyfill-php81",
    "type": "library",
    "description": "Symfony polyfill backporting some PHP 8.1+ features to lower PHP versions",
    "keywords": [
        "polyfill",
        "shim",
        "compatibility",
        "portable"
    ],
    "homepage": "https:\/\/symfony.com",
    "license": "MIT",
    "authors": [
        {
            "name": "Nicolas Grekas",
            "email": "p@tchwork.com"
        },
        {
            "name": "Symfony Community",
            "homepage": "https:\/\/symfony.com\/contributors"
        }
    ],
    "require": {
        "php": ">=7.2"
    },
    "autoload": {
        "psr-4": {
            "Symfony\\Polyfill\\Php81\\": ""
        },
        "files": [
            "bootstrap.php"
        ],
        "classmap": [
            "Resources\/stubs"
        ]
    },
    "minimum-stability": "dev",
    "extra": {
        "thanks": {
            "name": "symfony\/polyfill",
            "url": "https:\/\/github.com\/symfony\/polyfill"
        }
    }
}<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Bundle\SecurityBundle\DataCollector;

use _ContaoManager\Symfony\Bundle\SecurityBundle\Debug\TraceableFirewallListener;
use _ContaoManager\Symfony\Bundle\SecurityBundle\Security\FirewallMap;
use _ContaoManager\Symfony\Component\HttpFoundation\Request;
use _ContaoManager\Symfony\Component\HttpFoundation\Response;
use _ContaoManager\Symfony\Component\HttpKernel\DataCollector\DataCollector;
use _ContaoManager\Symfony\Component\HttpKernel\DataCollector\LateDataCollectorInterface;
use _ContaoManager\Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
use _ContaoManager\Symfony\Component\Security\Core\Authentication\Token\SwitchUserToken;
use _ContaoManager\Symfony\Component\Security\Core\Authorization\AccessDecisionManagerInterface;
use _ContaoManager\Symfony\Component\Security\Core\Authorization\TraceableAccessDecisionManager;
use _ContaoManager\Symfony\Component\Security\Core\Authorization\Voter\TraceableVoter;
use _ContaoManager\Symfony\Component\Security\Core\Role\RoleHierarchyInterface;
use _ContaoManager\Symfony\Component\Security\Http\Firewall\SwitchUserListener;
use _ContaoManager\Symfony\Component\Security\Http\FirewallMapInterface;
use _ContaoManager\Symfony\Component\Security\Http\Logout\LogoutUrlGenerator;
use _ContaoManager\Symfony\Component\VarDumper\Caster\ClassStub;
use _ContaoManager\Symfony\Component\VarDumper\Cloner\Data;
/**
 * @author Fabien Potencier <fabien@symfony.com>
 *
 * @final
 */
class SecurityDataCollector extends DataCollector implements LateDataCollectorInterface
{
    private ?TokenStorageInterface $tokenStorage;
    private ?RoleHierarchyInterface $roleHierarchy;
    private ?LogoutUrlGenerator $logoutUrlGenerator;
    private ?AccessDecisionManagerInterface $accessDecisionManager;
    private ?FirewallMapInterface $firewallMap;
    private ?TraceableFirewallListener $firewall;
    private bool $hasVarDumper;
    public function __construct(?TokenStorageInterface $tokenStorage = null, ?RoleHierarchyInterface $roleHierarchy = null, ?LogoutUrlGenerator $logoutUrlGenerator = null, ?AccessDecisionManagerInterface $accessDecisionManager = null, ?FirewallMapInterface $firewallMap = null, ?TraceableFirewallListener $firewall = null)
    {
        $this->tokenStorage = $tokenStorage;
        $this->roleHierarchy = $roleHierarchy;
        $this->logoutUrlGenerator = $logoutUrlGenerator;
        $this->accessDecisionManager = $accessDecisionManager;
        $this->firewallMap = $firewallMap;
        $this->firewall = $firewall;
        $this->hasVarDumper = class_exists(ClassStub::class);
    }
    public function collect(Request $request, Response $response, ?\Throwable $exception = null): void
    {
        if (null === $this->tokenStorage) {
            $this->data = ['enabled' => \false, 'authenticated' => \false, 'impersonated' => \false, 'impersonator_user' => null, 'impersonation_exit_path' => null, 'token' => null, 'token_class' => null, 'logout_url' => null, 'user' => '', 'roles' => [], 'inherited_roles' => [], 'supports_role_hierarchy' => null !== $this->roleHierarchy];
        } elseif (null === $token = $this->tokenStorage->getToken()) {
            $this->data = ['enabled' => \true, 'authenticated' => \false, 'impersonated' => \false, 'impersonator_user' => null, 'impersonation_exit_path' => null, 'token' => null, 'token_class' => null, 'logout_url' => null, 'user' => '', 'roles' => [], 'inherited_roles' => [], 'supports_role_hierarchy' => null !== $this->roleHierarchy];
        } else {
            $inheritedRoles = [];
            $assignedRoles = $token->getRoleNames();
            $impersonatorUser = null;
            if ($token instanceof SwitchUserToken) {
                $originalToken = $token->getOriginalToken();
                $impersonatorUser = $originalToken->getUserIdentifier();
            }
            if (null !== $this->roleHierarchy) {
                foreach ($this->roleHierarchy->getReachableRoleNames($assignedRoles) as $role) {
                    if (!\in_array($role, $assignedRoles, \true)) {
                        $inheritedRoles[] = $role;
                    }
                }
            }
            $logoutUrl = null;
            if ($this->logoutUrlGenerator && method_exists($token, 'getFirewallName')) {
                try {
                    $logoutUrl = $this->logoutUrlGenerator->getLogoutPath($token->getFirewallName());
                } catch (\Exception) {
                    // fail silently when the logout URL cannot be generated
                }
            }
            $this->data = ['enabled' => \true, 'authenticated' => (bool) $token->getUser(), 'impersonated' => null !== $impersonatorUser, 'impersonator_user' => $impersonatorUser, 'impersonation_exit_path' => null, 'token' => $token, 'token_class' => $this->hasVarDumper ? new ClassStub($token::class) : $token::class, 'logout_url' => $logoutUrl, 'user' => $token->getUserIdentifier(), 'roles' => $assignedRoles, 'inherited_roles' => array_unique($inheritedRoles), 'supports_role_hierarchy' => null !== $this->roleHierarchy];
        }
        // collect voters and access decision manager information
        if ($this->accessDecisionManager instanceof TraceableAccessDecisionManager) {
            $this->data['voter_strategy'] = $this->accessDecisionManager->getStrategy();
            $this->data['voters'] = [];
            foreach ($this->accessDecisionManager->getVoters() as $voter) {
                if ($voter instanceof TraceableVoter) {
                    $voter = $voter->getDecoratedVoter();
                }
                $this->data['voters'][] = $this->hasVarDumper ? new ClassStub($voter::class) : $voter::class;
            }
            // collect voter details
            $decisionLog = $this->accessDecisionManager->getDecisionLog();
            foreach ($decisionLog as $key => $log) {
                $decisionLog[$key]['voter_details'] = [];
                foreach ($log['voterDetails'] as $voterDetail) {
                    $voterClass = $voterDetail['voter']::class;
                    $classData = $this->hasVarDumper ? new ClassStub($voterClass) : $voterClass;
                    $decisionLog[$key]['voter_details'][] = [
                        'class' => $classData,
                        'attributes' => $voterDetail['attributes'],
                        // Only displayed for unanimous strategy
                        'vote' => $voterDetail['vote'],
                    ];
                }
                unset($decisionLog[$key]['voterDetails']);
            }
            $this->data['access_decision_log'] = $decisionLog;
        } else {
            $this->data['access_decision_log'] = [];
            $this->data['voter_strategy'] = 'unknown';
            $this->data['voters'] = [];
        }
        // collect firewall context information
        $this->data['firewall'] = null;
        if ($this->firewallMap instanceof FirewallMap) {
            $firewallConfig = $this->firewallMap->getFirewallConfig($request);
            if (null !== $firewallConfig) {
                $this->data['firewall'] = ['name' => $firewallConfig->getName(), 'request_matcher' => $firewallConfig->getRequestMatcher(), 'security_enabled' => $firewallConfig->isSecurityEnabled(), 'stateless' => $firewallConfig->isStateless(), 'provider' => $firewallConfig->getProvider(), 'context' => $firewallConfig->getContext(), 'entry_point' => $firewallConfig->getEntryPoint(), 'access_denied_handler' => $firewallConfig->getAccessDeniedHandler(), 'access_denied_url' => $firewallConfig->getAccessDeniedUrl(), 'user_checker' => $firewallConfig->getUserChecker(), 'authenticators' => $firewallConfig->getAuthenticators()];
                // generate exit impersonation path from current request
                if ($this->data['impersonated'] && null !== $switchUserConfig = $firewallConfig->getSwitchUser()) {
                    $exitPath = $request->getRequestUri();
                    $exitPath .= null === $request->getQueryString() ? '?' : '&';
                    $exitPath .= \sprintf('%s=%s', urlencode($switchUserConfig['parameter']), SwitchUserListener::EXIT_VALUE);
                    $this->data['impersonation_exit_path'] = $exitPath;
                }
            }
        }
        // collect firewall listeners information
        $this->data['listeners'] = [];
        if ($this->firewall) {
            $this->data['listeners'] = $this->firewall->getWrappedListeners();
        }
        $this->data['authenticators'] = $this->firewall ? $this->firewall->getAuthenticatorsInfo() : [];
    }
    public function reset(): void
    {
        $this->data = [];
    }
    public function lateCollect(): void
    {
        $this->data = $this->cloneVar($this->data);
    }
    /**
     * Checks if security is enabled.
     */
    public function isEnabled(): bool
    {
        return $this->data['enabled'];
    }
    /**
     * Gets the user.
     */
    public function getUser(): string
    {
        return $this->data['user'];
    }
    /**
     * Gets the roles of the user.
     */
    public function getRoles(): array|Data
    {
        return $this->data['roles'];
    }
    /**
     * Gets the inherited roles of the user.
     */
    public function getInheritedRoles(): array|Data
    {
        return $this->data['inherited_roles'];
    }
    /**
     * Checks if the data contains information about inherited roles. Still the inherited
     * roles can be an empty array.
     */
    public function supportsRoleHierarchy(): bool
    {
        return $this->data['supports_role_hierarchy'];
    }
    /**
     * Checks if the user is authenticated or not.
     */
    public function isAuthenticated(): bool
    {
        return $this->data['authenticated'];
    }
    public function isImpersonated(): bool
    {
        return $this->data['impersonated'];
    }
    public function getImpersonatorUser(): ?string
    {
        return $this->data['impersonator_user'];
    }
    public function getImpersonationExitPath(): ?string
    {
        return $this->data['impersonation_exit_path'];
    }
    /**
     * Get the class name of the security token.
     */
    public function getTokenClass(): string|Data|null
    {
        return $this->data['token_class'];
    }
    /**
     * Get the full security token class as Data object.
     */
    public function getToken(): ?Data
    {
        return $this->data['token'];
    }
    /**
     * Get the logout URL.
     */
    public function getLogoutUrl(): ?string
    {
        return $this->data['logout_url'];
    }
    /**
     * Returns the FQCN of the security voters enabled in the application.
     *
     * @return string[]|Data
     */
    public function getVoters(): array|Data
    {
        return $this->data['voters'];
    }
    /**
     * Returns the strategy configured for the security voters.
     */
    public function getVoterStrategy(): string
    {
        return $this->data['voter_strategy'];
    }
    /**
     * Returns the log of the security decisions made by the access decision manager.
     */
    public function getAccessDecisionLog(): array|Data
    {
        return $this->data['access_decision_log'];
    }
    /**
     * Returns the configuration of the current firewall context.
     */
    public function getFirewall(): array|Data|null
    {
        return $this->data['firewall'];
    }
    public function getListeners(): array|Data
    {
        return $this->data['listeners'];
    }
    public function getAuthenticators(): array|Data
    {
        return $this->data['authenticators'];
    }
    public function getName(): string
    {
        return 'security';
    }
}
Copyright (c) 2004-present Fabien Potencier

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is furnished
to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
CHANGELOG
=========

6.4
---

 * Deprecate `Security::ACCESS_DENIED_ERROR`, `AUTHENTICATION_ERROR` and `LAST_USERNAME` constants, use the ones on `SecurityRequestAttributes` instead
 * Allow an array of `pattern` in firewall configuration
 * Add `$badges` argument to `Security::login`
 * Deprecate the `require_previous_session` config option. Setting it has no effect anymore
 * Add `LogoutRouteLoader`

6.3
---

 * Deprecate enabling bundle and not configuring it
 * Add `_stateless` attribute to the request when firewall is stateless and the attribute is not already set
 * Add `StatelessAuthenticatorFactoryInterface` for authenticators targeting `stateless` firewalls only and that don't require a user provider
 * Modify "icon.svg" to improve accessibility for blind/low vision users
 * Make `Security::login()` return the authenticator response
 * Deprecate the `security.firewalls.logout.csrf_token_generator` config option, use `security.firewalls.logout.csrf_token_manager` instead
 * Make firewalls event dispatcher traceable on debug mode
 * Add `TokenHandlerFactoryInterface`, `OidcUserInfoTokenHandlerFactory`, `OidcTokenHandlerFactory` and `ServiceTokenHandlerFactory` for `AccessTokenFactory`

6.2
---

 * Add the `Security` helper class
 * Deprecate the `Symfony\Component\Security\Core\Security` service alias, use `Symfony\Bundle\SecurityBundle\Security` instead
 * Add `Security::getFirewallConfig()` to help to get the firewall configuration associated to the Request
 * Add `Security::login()` to login programmatically
 * Add `Security::logout()` to logout programmatically
 * Add `security.firewalls.logout.enable_csrf` to enable CSRF protection using the default CSRF token generator
 * Add RFC6750 Access Token support to allow token-based authentication
 * Add `security.firewalls.switch_user.target_route` option to configure redirect target route on switch user
 * Deprecate the `security.enable_authenticator_manager` config option

6.1
---

 * The `security.access_control` now accepts a `RequestMatcherInterface` under the `request_matcher` option as scope configuration
 * The `security.access_control` now accepts an `attributes` array to match request attributes in the `RequestMatcher`
 * The `security.access_control` now accepts a `route` option to match request route in the `RequestMatcher`
 * Display the inherited roles of the logged-in user in the Web Debug Toolbar

6.0
---

 * The `security.authorization_checker` and `security.token_storage` services are now private
 * Remove `UserPasswordEncoderCommand` class and the corresponding `user:encode-password` command,
   use `UserPasswordHashCommand` and `user:hash-password` instead
 * Remove the `security.encoder_factory.generic` service, the `security.encoder_factory` and `Symfony\Component\Security\Core\Encoder\EncoderFactoryInterface` aliases,
   use `security.password_hasher_factory` and `Symfony\Component\PasswordHasher\Hasher\PasswordHasherFactoryInterface` instead
 * Remove the `security.user_password_encoder.generic` service, the `security.password_encoder` and the `Symfony\Component\Security\Core\Encoder\UserPasswordEncoderInterface` aliases,
   use `security.user_password_hasher`, `security.password_hasher` and `Symfony\Component\PasswordHasher\Hasher\UserPasswordHasherInterface` instead
 * Remove the `logout.success_handler` and `logout.handlers` config options, register a listener on the `LogoutEvent` event instead
 * Remove `FirewallConfig::getListeners()`, use `FirewallConfig::getAuthenticators()` instead

5.4
---

 * Deprecate `FirewallConfig::getListeners()`, use `FirewallConfig::getAuthenticators()` instead
 * Deprecate `security.authentication.basic_entry_point` and `security.authentication.retry_entry_point` services, the logic is moved into the
   `HttpBasicAuthenticator` and `ChannelListener` respectively
 * Deprecate `FirewallConfig::allowsAnonymous()` and the `allows_anonymous` from the data collector data, there will be no anonymous concept as of version 6.
 * Deprecate not setting `$authenticatorManagerEnabled` to `true` in `SecurityDataCollector` and `DebugFirewallCommand`
 * Deprecate `SecurityFactoryInterface` and `SecurityExtension::addSecurityListenerFactory()` in favor of
   `AuthenticatorFactoryInterface` and `SecurityExtension::addAuthenticatorFactory()`
 * Add `AuthenticatorFactoryInterface::getPriority()` which replaces `SecurityFactoryInterface::getPosition()`
 * Deprecate passing an array of arrays as 1st argument to `MainConfiguration`, pass a sorted flat array of
   factories instead.
 * Deprecate the `always_authenticate_before_granting` option
 * Display the roles of the logged-in user in the Web Debug Toolbar
 * Add the `security.access_decision_manager.strategy_service` option
 * Deprecate not configuring explicitly a provider for custom_authenticators when there is more than one registered provider


5.3
---

 * The authenticator system is no longer experimental
 * Login Link functionality is no longer experimental
 * Add `required_badges` firewall config option
 * [BC break] Add `login_throttling.lock_factory` setting defaulting to `null` (instead of `lock.factory`)
 * Add a `login_throttling.interval` (in `security.firewalls`) option to change the default throttling interval.
 * Add the `debug:firewall` command.
 * Deprecate `UserPasswordEncoderCommand` class and the corresponding `user:encode-password` command,
   use `UserPasswordHashCommand` and `user:hash-password` instead
 * Deprecate the `security.encoder_factory.generic` service, the `security.encoder_factory` and `Symfony\Component\Security\Core\Encoder\EncoderFactoryInterface` aliases,
   use `security.password_hasher_factory` and `Symfony\Component\PasswordHasher\Hasher\PasswordHasherFactoryInterface` instead
 * Deprecate the `security.user_password_encoder.generic` service, the `security.password_encoder` and the `Symfony\Component\Security\Core\Encoder\UserPasswordEncoderInterface` aliases,
   use `security.user_password_hasher`, `security.password_hasher` and `Symfony\Component\PasswordHasher\Hasher\UserPasswordHasherInterface` instead
 * Deprecate the public `security.authorization_checker` and `security.token_storage` services to private
 * Not setting the `enable_authenticator_manager` config option to `true` is deprecated
 * Deprecate the `security.authentication.provider.*` services, use the new authenticator system instead
 * Deprecate the `security.authentication.listener.*` services, use the new authenticator system instead
 * Deprecate the Guard component integration, use the new authenticator system instead
 * Add `form_login.form_only` option

5.2.0
-----

 * Added `FirewallListenerFactoryInterface`, which can be implemented by security factories to add firewall listeners
 * Added `SortFirewallListenersPass` to make the execution order of firewall listeners configurable by
   leveraging `Symfony\Component\Security\Http\Firewall\FirewallListenerInterface`
 * Added ability to use comma separated ip address list for `security.access_control`
 * [BC break] Removed `EntryPointFactoryInterface`, authenticators must now implement `AuthenticationEntryPointInterface` if
   they require autoregistration of a Security entry point.

5.1.0
-----

 * Added XSD for configuration
 * Added security configuration for priority-based access decision strategy
 * Marked the `AnonymousFactory`, `FormLoginFactory`, `FormLoginLdapFactory`, `GuardAuthenticationFactory`, `HttpBasicFactory`, `HttpBasicLdapFactory`, `JsonLoginFactory`, `JsonLoginLdapFactory`, `RememberMeFactory`, `RemoteUserFactory` and `X509Factory` as `@internal`
 * Renamed method `AbstractFactory#createEntryPoint()` to `AbstractFactory#createDefaultEntryPoint()`

5.0.0
-----

 * The `switch_user.stateless` firewall option has been removed.
 * Removed the ability to configure encoders using `argon2i` or `bcrypt` as algorithm, use `auto` instead
 * The `simple_form` and `simple_preauth` authentication listeners have been removed,
   use Guard instead.
 * The `SimpleFormFactory` and `SimplePreAuthenticationFactory` classes have been removed,
   use Guard instead.
 * Removed `LogoutUrlHelper` and `SecurityHelper` templating helpers, use Twig instead
 * Removed the `logout_on_user_change` firewall option
 * Removed the `threads` encoder option
 * Removed the `security.authentication.trust_resolver.anonymous_class` parameter
 * Removed the `security.authentication.trust_resolver.rememberme_class` parameter
 * Removed the `security.user.provider.in_memory.user` service.

4.4.0
-----

 * Added `anonymous: lazy` mode to firewalls to make them (not) start the session as late as possible
 * Added `migrate_from` option to encoders configuration.
 * Added new `argon2id` encoder, undeprecated the `bcrypt` and `argon2i` ones (using `auto` is still recommended by default.)
 * Deprecated the usage of "query_string" without a "search_dn" and a "search_password" config key in Ldap factories.
 * Marked the `SecurityDataCollector` class as `@final`.

4.3.0
-----

 * Added new encoder types: `auto` (recommended), `native` and `sodium`
 * The normalization of the cookie names configured in the `logout.delete_cookies`
   option is deprecated and will be disabled in Symfony 5.0. This affects to cookies
   with dashes in their names. For example, starting from Symfony 5.0, the `my-cookie`
   name will delete `my-cookie` (with a dash) instead of `my_cookie` (with an underscore).

4.2.0
-----

 * Using the `security.authentication.trust_resolver.anonymous_class` and
   `security.authentication.trust_resolver.rememberme_class` parameters to define
   the token classes is deprecated. To use custom tokens extend the existing
   `Symfony\Component\Security\Core\Authentication\Token\AnonymousToken`.
   or `Symfony\Component\Security\Core\Authentication\Token\RememberMeToken`.
 * Added `Symfony\Bundle\SecurityBundle\DependencyInjection\Compiler\AddExpressionLanguageProvidersPass`
 * Added `json_login_ldap` authentication provider to use LDAP authentication with a REST API.
 * Made remember-me cookies inherit their default config from `framework.session.cookie_*`
   and added an "auto" mode to their "secure" config option to make them secure on HTTPS automatically.
 * Deprecated the `simple_form` and `simple_preauth` authentication listeners, use Guard instead.
 * Deprecated the `SimpleFormFactory` and `SimplePreAuthenticationFactory` classes, use Guard instead.
 * Added `port` in access_control
 * Added individual voter decisions to the profiler

4.1.0
-----

 * The `switch_user.stateless` firewall option is deprecated, use the `stateless` option instead.
 * The `logout_on_user_change` firewall option is deprecated.
 * deprecated `SecurityUserValueResolver`, use
   `Symfony\Component\Security\Http\Controller\UserValueResolver` instead.

4.0.0
-----

 * removed `FirewallContext::getContext()`
 * made `FirewallMap::$container` and `::$map` private
 * made the first `UserPasswordEncoderCommand::_construct()` argument mandatory
 * `UserPasswordEncoderCommand` does not extend `ContainerAwareCommand` anymore
 * removed support for voters that don't implement the `VoterInterface`
 * removed HTTP digest authentication
 * removed command `acl:set` along with `SetAclCommand` class
 * removed command `init:acl` along with `InitAclCommand` class
 * removed `acl` configuration key and related services, use symfony/acl-bundle instead
 * removed auto picking the first registered provider when no configured provider on a firewall and ambiguous
 * the firewall option `logout_on_user_change` is now always true, which will trigger a logout if the user changes
   between requests
 * the `switch_user.stateless` firewall option is `true` for stateless firewalls

3.4.0
-----

 * Added new `security.helper` service that is an instance of `Symfony\Component\Security\Core\Security`
   and provides shortcuts for common security tasks.
 * Tagging voters with the `security.voter` tag without implementing the
   `VoterInterface` on the class is now deprecated and will be removed in 4.0.
 * [BC BREAK] `FirewallContext::getListeners()` now returns `\Traversable|array`
 * added info about called security listeners in profiler
 * Added `logout_on_user_change` to the firewall options. This config item will
   trigger a logout when the user has changed. Should be set to true to avoid
   deprecations in the configuration.
 * deprecated HTTP digest authentication
 * deprecated command `acl:set` along with `SetAclCommand` class
 * deprecated command `init:acl` along with `InitAclCommand` class
 * Added support for the new Argon2i password encoder
 * added `stateless` option to the `switch_user` listener
 * deprecated auto picking the first registered provider when no configured provider on a firewall and ambiguous

3.3.0
-----

 * Deprecated instantiating `UserPasswordEncoderCommand` without its constructor
   arguments fully provided.
 * Deprecated `UserPasswordEncoderCommand::getContainer()` and relying on the
  `ContainerAwareCommand` sub class or `ContainerAwareInterface` implementation for this command.
 * Deprecated the `FirewallMap::$map` and `$container` properties.
 * [BC BREAK] Keys of the `users` node for `in_memory` user provider are no longer normalized.
 * deprecated `FirewallContext::getListeners()`

3.2.0
-----

 * Added the `SecurityUserValueResolver` to inject the security users in actions via
   `Symfony\Component\Security\Core\User\UserInterface` in the method signature.

3.0.0
-----

 * Removed the `security.context` service.

2.8.0
-----

 * deprecated the `key` setting of `anonymous`, `remember_me` and `http_digest`
   in favor of the `secret` setting.
 * deprecated the `intention` firewall listener setting in favor of the `csrf_token_id`.

2.6.0
-----

 * Added the possibility to override the default success/failure handler
   to get the provider key and the options injected
 * Deprecated the `security.context` service for the `security.token_storage` and
   `security.authorization_checker` services.

2.4.0
-----

 * Added 'host' option to firewall configuration
 * Added 'csrf_token_generator' and 'csrf_token_id' options to firewall logout
   listener configuration to supersede/alias 'csrf_provider' and 'intention'
   respectively
 * Moved 'security.secure_random' service configuration to FrameworkBundle

2.3.0
-----

 * allowed for multiple IP address in security access_control rules

2.2.0
-----

 * Added PBKDF2 Password encoder
 * Added BCrypt password encoder

2.1.0
-----

 * [BC BREAK] The custom factories for the firewall configuration are now
   registered during the build method of bundles instead of being registered
   by the end-user (you need to remove the 'factories' keys in your security
   configuration).

 * [BC BREAK] The Firewall listener is now registered after the Router one. This
   means that specific Firewall URLs (like /login_check and /logout must now
   have proper route defined in your routing configuration)

 * [BC BREAK] refactored the user provider configuration. The configuration
   changed for the chain provider and the memory provider:

    Before:

    ``` yaml
    security:
        providers:
            my_chain_provider:
                providers: [my_memory_provider, my_doctrine_provider]
            my_memory_provider:
                users:
                    toto: { password: foobar, roles: [ROLE_USER] }
                    foo: { password: bar, roles: [ROLE_USER, ROLE_ADMIN] }
    ```

    After:

    ``` yaml
    security:
        providers:
            my_chain_provider:
                chain:
                    providers: [my_memory_provider, my_doctrine_provider]
            my_memory_provider:
                memory:
                    users:
                        toto: { password: foobar, roles: [ROLE_USER] }
                        foo: { password: bar, roles: [ROLE_USER, ROLE_ADMIN] }
    ```

 * [BC BREAK] Method `equals` was removed from `UserInterface` to its own new
   `EquatableInterface`. The user class can now implement this interface to override
   the default implementation of users equality test.

 * added a validator for the user password
 * added 'erase_credentials' as a configuration key (true by default)
 * added new events: `security.authentication.success` and `security.authentication.failure`
   fired on authentication success/failure, regardless of authentication method,
   events are defined in new event class: `Symfony\Component\Security\Core\AuthenticationEvents`.

 * Added optional CSRF protection to LogoutListener:

    ``` yaml
    security:
        firewalls:
            default:
                logout:
                    path: /logout_path
                    target: /
                    csrf_parameter: _csrf_token                   # Optional (defaults to "_csrf_token")
                    csrf_provider:  security.csrf.token_generator # Required to enable protection
                    intention:      logout                        # Optional (defaults to "logout")
    ```

    If the LogoutListener has CSRF protection enabled but cannot validate a token,
   then a LogoutException will be thrown.

 * Added `logout_url` templating helper and Twig extension, which may be used to
   generate logout URL's within templates. The security firewall's config key
   must be specified. If a firewall's logout listener has CSRF protection
   enabled, a token will be automatically added to the generated URL.
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Bundle\SecurityBundle\Security;

use _ContaoManager\Symfony\Component\HttpKernel\Event\RequestEvent;
use _ContaoManager\Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorage;
use _ContaoManager\Symfony\Component\Security\Http\Event\LazyResponseEvent;
use _ContaoManager\Symfony\Component\Security\Http\Firewall\ExceptionListener;
use _ContaoManager\Symfony\Component\Security\Http\Firewall\FirewallListenerInterface;
use _ContaoManager\Symfony\Component\Security\Http\Firewall\LogoutListener;
/**
 * Lazily calls authentication listeners when actually required by the access listener.
 *
 * @author Nicolas Grekas <p@tchwork.com>
 */
class LazyFirewallContext extends FirewallContext
{
    private TokenStorage $tokenStorage;
    public function __construct(iterable $listeners, ?ExceptionListener $exceptionListener, ?LogoutListener $logoutListener, ?FirewallConfig $config, TokenStorage $tokenStorage)
    {
        parent::__construct($listeners, $exceptionListener, $logoutListener, $config);
        $this->tokenStorage = $tokenStorage;
    }
    public function getListeners(): iterable
    {
        return [$this];
    }
    public function __invoke(RequestEvent $event): void
    {
        $listeners = [];
        $request = $event->getRequest();
        $lazy = \true;
        foreach (parent::getListeners() as $listener) {
            if (!$lazy || !$listener instanceof FirewallListenerInterface) {
                $listeners[] = $listener;
                $lazy = $lazy && $listener instanceof FirewallListenerInterface;
            } elseif (\false !== $supports = $listener->supports($request)) {
                $listeners[] = [$listener, 'authenticate'];
                $lazy = null === $supports;
            }
        }
        if (!$lazy) {
            foreach ($listeners as $listener) {
                $listener($event);
                if ($event->hasResponse()) {
                    return;
                }
            }
            return;
        }
        $this->tokenStorage->setInitializer(static function () use ($event, $listeners) {
            $event = new LazyResponseEvent($event);
            foreach ($listeners as $listener) {
                $listener($event);
            }
        });
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Bundle\SecurityBundle\Security;

use _ContaoManager\Psr\Container\ContainerInterface;
use _ContaoManager\Symfony\Component\HttpFoundation\Request;
use _ContaoManager\Symfony\Component\HttpFoundation\RequestStack;
use _ContaoManager\Symfony\Component\HttpFoundation\Response;
use _ContaoManager\Symfony\Component\Security\Core\User\UserInterface;
use _ContaoManager\Symfony\Component\Security\Http\Authentication\UserAuthenticatorInterface;
use _ContaoManager\Symfony\Component\Security\Http\Authenticator\AuthenticatorInterface;
/**
 * A decorator that delegates all method calls to the authenticator
 * manager of the current firewall.
 *
 * @author Wouter de Jong <wouter@wouterj.nl>
 *
 * @final
 */
class UserAuthenticator implements UserAuthenticatorInterface
{
    use FirewallAwareTrait;
    public function __construct(FirewallMap $firewallMap, ContainerInterface $userAuthenticators, RequestStack $requestStack)
    {
        $this->firewallMap = $firewallMap;
        $this->locator = $userAuthenticators;
        $this->requestStack = $requestStack;
    }
    public function authenticateUser(UserInterface $user, AuthenticatorInterface $authenticator, Request $request, array $badges = []): ?Response
    {
        return $this->getForFirewall()->authenticateUser($user, $authenticator, $request, $badges);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Bundle\SecurityBundle\Security;

use _ContaoManager\Symfony\Component\Security\Http\Firewall\ExceptionListener;
use _ContaoManager\Symfony\Component\Security\Http\Firewall\FirewallListenerInterface;
use _ContaoManager\Symfony\Component\Security\Http\Firewall\LogoutListener;
/**
 * This is a wrapper around the actual firewall configuration which allows us
 * to lazy load the context for one specific firewall only when we need it.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
class FirewallContext
{
    private iterable $listeners;
    private ?ExceptionListener $exceptionListener;
    private ?LogoutListener $logoutListener;
    private ?FirewallConfig $config;
    /**
     * @param iterable<mixed, callable|FirewallListenerInterface> $listeners
     */
    public function __construct(iterable $listeners, ?ExceptionListener $exceptionListener = null, ?LogoutListener $logoutListener = null, ?FirewallConfig $config = null)
    {
        $this->listeners = $listeners;
        $this->exceptionListener = $exceptionListener;
        $this->logoutListener = $logoutListener;
        $this->config = $config;
    }
    /**
     * @return FirewallConfig|null
     */
    public function getConfig()
    {
        return $this->config;
    }
    /**
     * @return iterable<mixed, callable|FirewallListenerInterface>
     */
    public function getListeners(): iterable
    {
        return $this->listeners;
    }
    /**
     * @return ExceptionListener|null
     */
    public function getExceptionListener()
    {
        return $this->exceptionListener;
    }
    /**
     * @return LogoutListener|null
     */
    public function getLogoutListener()
    {
        return $this->logoutListener;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Bundle\SecurityBundle\Security;

use _ContaoManager\Psr\Container\ContainerInterface;
use _ContaoManager\Symfony\Component\HttpFoundation\Request;
use _ContaoManager\Symfony\Component\Security\Http\FirewallMapInterface;
/**
 * This is a lazy-loading firewall map implementation.
 *
 * Listeners will only be initialized if we really need them.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
class FirewallMap implements FirewallMapInterface
{
    private ContainerInterface $container;
    private iterable $map;
    public function __construct(ContainerInterface $container, iterable $map)
    {
        $this->container = $container;
        $this->map = $map;
    }
    public function getListeners(Request $request): array
    {
        $context = $this->getFirewallContext($request);
        if (null === $context) {
            return [[], null, null];
        }
        return [$context->getListeners(), $context->getExceptionListener(), $context->getLogoutListener()];
    }
    public function getFirewallConfig(Request $request): ?FirewallConfig
    {
        $context = $this->getFirewallContext($request);
        if (null === $context) {
            return null;
        }
        return $context->getConfig();
    }
    private function getFirewallContext(Request $request): ?FirewallContext
    {
        if ($request->attributes->has('_firewall_context')) {
            $storedContextId = $request->attributes->get('_firewall_context');
            foreach ($this->map as $contextId => $requestMatcher) {
                if ($contextId === $storedContextId) {
                    return $this->container->get($contextId);
                }
            }
            $request->attributes->remove('_firewall_context');
        }
        foreach ($this->map as $contextId => $requestMatcher) {
            if (null === $requestMatcher || $requestMatcher->matches($request)) {
                $request->attributes->set('_firewall_context', $contextId);
                return $this->container->get($contextId);
            }
        }
        return null;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Bundle\SecurityBundle\Security;

/**
 * @author Robin Chalas <robin.chalas@gmail.com>
 */
final class FirewallConfig
{
    public function __construct(private readonly string $name, private readonly string $userChecker, private readonly ?string $requestMatcher = null, private readonly bool $securityEnabled = \true, private readonly bool $stateless = \false, private readonly ?string $provider = null, private readonly ?string $context = null, private readonly ?string $entryPoint = null, private readonly ?string $accessDeniedHandler = null, private readonly ?string $accessDeniedUrl = null, private readonly array $authenticators = [], private readonly ?array $switchUser = null, private readonly ?array $logout = null)
    {
    }
    public function getName(): string
    {
        return $this->name;
    }
    /**
     * @return string|null The request matcher service id or null if neither the request matcher, pattern or host
     *                     options were provided
     */
    public function getRequestMatcher(): ?string
    {
        return $this->requestMatcher;
    }
    public function isSecurityEnabled(): bool
    {
        return $this->securityEnabled;
    }
    public function isStateless(): bool
    {
        return $this->stateless;
    }
    public function getProvider(): ?string
    {
        return $this->provider;
    }
    /**
     * @return string|null The context key (will be null if the firewall is stateless)
     */
    public function getContext(): ?string
    {
        return $this->context;
    }
    public function getEntryPoint(): ?string
    {
        return $this->entryPoint;
    }
    public function getUserChecker(): string
    {
        return $this->userChecker;
    }
    public function getAccessDeniedHandler(): ?string
    {
        return $this->accessDeniedHandler;
    }
    public function getAccessDeniedUrl(): ?string
    {
        return $this->accessDeniedUrl;
    }
    public function getAuthenticators(): array
    {
        return $this->authenticators;
    }
    public function getSwitchUser(): ?array
    {
        return $this->switchUser;
    }
    public function getLogout(): ?array
    {
        return $this->logout;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Bundle\SecurityBundle\Security;

use _ContaoManager\Psr\Container\ContainerInterface;
use _ContaoManager\Symfony\Component\HttpFoundation\RequestStack;
/**
 * Provides basic functionality for services mapped by the firewall name
 * in a container locator.
 *
 * @author Wouter de Jong <wouter@wouterj.nl>
 *
 * @internal
 */
trait FirewallAwareTrait
{
    private ContainerInterface $locator;
    private RequestStack $requestStack;
    private FirewallMap $firewallMap;
    private function getForFirewall(): object
    {
        $serviceIdentifier = str_replace('FirewallAware', '', static::class);
        if (null === $request = $this->requestStack->getCurrentRequest()) {
            throw new \LogicException('Cannot determine the correct ' . $serviceIdentifier . ' to use: there is no active Request and so, the firewall cannot be determined. Try using a specific ' . $serviceIdentifier . ' service.');
        }
        $firewall = $this->firewallMap->getFirewallConfig($request);
        if (!$firewall) {
            throw new \LogicException('No ' . $serviceIdentifier . ' found as the current route is not covered by a firewall.');
        }
        $firewallName = $firewall->getName();
        if (!$this->locator->has($firewallName)) {
            $message = 'No ' . $serviceIdentifier . ' found for this firewall.';
            if (\defined(static::class . '::FIREWALL_OPTION')) {
                $message .= \sprintf(' Did you forget to add a "' . static::FIREWALL_OPTION . '" key under your "%s" firewall?', $firewallName);
            }
            throw new \LogicException($message);
        }
        return $this->locator->get($firewallName);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\DependencyInjection\Loader\Configurator;

use _ContaoManager\Jose\Component\Core\Algorithm;
use _ContaoManager\Jose\Component\Core\JWK;
use _ContaoManager\Jose\Component\Signature\Algorithm\ES256;
use _ContaoManager\Jose\Component\Signature\Algorithm\ES384;
use _ContaoManager\Jose\Component\Signature\Algorithm\ES512;
use _ContaoManager\Symfony\Bundle\SecurityBundle\DependencyInjection\Security\Factory\SignatureAlgorithmFactory;
use _ContaoManager\Symfony\Component\Security\Http\AccessToken\ChainAccessTokenExtractor;
use _ContaoManager\Symfony\Component\Security\Http\AccessToken\FormEncodedBodyExtractor;
use _ContaoManager\Symfony\Component\Security\Http\AccessToken\HeaderAccessTokenExtractor;
use _ContaoManager\Symfony\Component\Security\Http\AccessToken\Oidc\OidcTokenHandler;
use _ContaoManager\Symfony\Component\Security\Http\AccessToken\Oidc\OidcUserInfoTokenHandler;
use _ContaoManager\Symfony\Component\Security\Http\AccessToken\QueryAccessTokenExtractor;
use _ContaoManager\Symfony\Component\Security\Http\Authenticator\AccessTokenAuthenticator;
use _ContaoManager\Symfony\Contracts\HttpClient\HttpClientInterface;
return static function (ContainerConfigurator $container) {
    $container->services()->set('security.access_token_extractor.header', HeaderAccessTokenExtractor::class)->set('security.access_token_extractor.query_string', QueryAccessTokenExtractor::class)->set('security.access_token_extractor.request_body', FormEncodedBodyExtractor::class)->set('security.authenticator.access_token', AccessTokenAuthenticator::class)->abstract()->args([abstract_arg('access token handler'), abstract_arg('access token extractor'), null, null, null, null])->set('security.authenticator.access_token.chain_extractor', ChainAccessTokenExtractor::class)->abstract()->args([abstract_arg('access token extractors')])->set('security.access_token_handler.oidc_user_info.http_client', HttpClientInterface::class)->abstract()->factory([service('http_client'), 'withOptions'])->args([abstract_arg('http client options')])->set('security.access_token_handler.oidc_user_info', OidcUserInfoTokenHandler::class)->abstract()->args([abstract_arg('http client'), service('logger')->nullOnInvalid(), abstract_arg('claim')])->set('security.access_token_handler.oidc', OidcTokenHandler::class)->abstract()->args([abstract_arg('signature algorithm'), abstract_arg('signature key'), abstract_arg('audience'), abstract_arg('issuers'), 'sub', service('logger')->nullOnInvalid(), service('clock')])->set('security.access_token_handler.oidc.jwk', JWK::class)->abstract()->factory([JWK::class, 'createFromJson'])->args([abstract_arg('signature key')])->set('security.access_token_handler.oidc.signature', Algorithm::class)->abstract()->factory([SignatureAlgorithmFactory::class, 'create'])->args([abstract_arg('signature algorithm')])->set('security.access_token_handler.oidc.signature.ES256', ES256::class)->parent('security.access_token_handler.oidc.signature')->args(['index_0' => 'ES256'])->set('security.access_token_handler.oidc.signature.ES384', ES384::class)->parent('security.access_token_handler.oidc.signature')->args(['index_0' => 'ES384'])->set('security.access_token_handler.oidc.signature.ES512', ES512::class)->parent('security.access_token_handler.oidc.signature')->args(['index_0' => 'ES512']);
};
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\DependencyInjection\Loader\Configurator;

use _ContaoManager\Symfony\Bridge\Twig\Extension\LogoutUrlExtension;
use _ContaoManager\Symfony\Bridge\Twig\Extension\SecurityExtension;
return static function (ContainerConfigurator $container) {
    $container->services()->set('twig.extension.logout_url', LogoutUrlExtension::class)->args([service('security.logout_url_generator')])->tag('twig.extension')->set('twig.extension.security', SecurityExtension::class)->args([service('security.authorization_checker')->ignoreOnInvalid(), service('security.impersonate_url_generator')->ignoreOnInvalid()])->tag('twig.extension');
};
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\DependencyInjection\Loader\Configurator;

use _ContaoManager\Symfony\Component\DependencyInjection\ServiceLocator;
use _ContaoManager\Symfony\Component\Security\Http\AccessMap;
use _ContaoManager\Symfony\Component\Security\Http\Authentication\CustomAuthenticationFailureHandler;
use _ContaoManager\Symfony\Component\Security\Http\Authentication\CustomAuthenticationSuccessHandler;
use _ContaoManager\Symfony\Component\Security\Http\Authentication\DefaultAuthenticationFailureHandler;
use _ContaoManager\Symfony\Component\Security\Http\Authentication\DefaultAuthenticationSuccessHandler;
use _ContaoManager\Symfony\Component\Security\Http\EventListener\ClearSiteDataLogoutListener;
use _ContaoManager\Symfony\Component\Security\Http\EventListener\CookieClearingLogoutListener;
use _ContaoManager\Symfony\Component\Security\Http\EventListener\DefaultLogoutListener;
use _ContaoManager\Symfony\Component\Security\Http\EventListener\SessionLogoutListener;
use _ContaoManager\Symfony\Component\Security\Http\Firewall\AccessListener;
use _ContaoManager\Symfony\Component\Security\Http\Firewall\ChannelListener;
use _ContaoManager\Symfony\Component\Security\Http\Firewall\ContextListener;
use _ContaoManager\Symfony\Component\Security\Http\Firewall\ExceptionListener;
use _ContaoManager\Symfony\Component\Security\Http\Firewall\LogoutListener;
use _ContaoManager\Symfony\Component\Security\Http\Firewall\SwitchUserListener;
return static function (ContainerConfigurator $container) {
    $container->services()->set('security.channel_listener', ChannelListener::class)->args([service('security.access_map'), service('logger')->nullOnInvalid(), inline_service('int')->factory([service('router.request_context'), 'getHttpPort']), inline_service('int')->factory([service('router.request_context'), 'getHttpsPort'])])->tag('monolog.logger', ['channel' => 'security'])->set('security.access_map', AccessMap::class)->set('security.context_listener', ContextListener::class)->args([service('security.untracked_token_storage'), [], abstract_arg('Provider Key'), service('logger')->nullOnInvalid(), service('event_dispatcher')->nullOnInvalid(), service('security.authentication.trust_resolver')])->tag('monolog.logger', ['channel' => 'security'])->set('security.logout_listener', LogoutListener::class)->abstract()->args([service('security.token_storage'), service('security.http_utils'), abstract_arg('event dispatcher'), []])->set('security.logout.listener.session', SessionLogoutListener::class)->abstract()->set('security.logout.listener.clear_site_data', ClearSiteDataLogoutListener::class)->abstract()->set('security.logout.listener.cookie_clearing', CookieClearingLogoutListener::class)->abstract()->set('security.logout.listener.default', DefaultLogoutListener::class)->abstract()->args([service('security.http_utils'), abstract_arg('target url')])->set('security.authentication.listener.abstract')->abstract()->args([service('security.token_storage'), service('security.authentication.manager'), service('security.authentication.session_strategy'), service('security.http_utils'), abstract_arg('Provider-shared Key'), service('security.authentication.success_handler'), service('security.authentication.failure_handler'), [], service('logger')->nullOnInvalid(), service('event_dispatcher')->nullOnInvalid()])->tag('monolog.logger', ['channel' => 'security'])->set('security.authentication.custom_success_handler', CustomAuthenticationSuccessHandler::class)->abstract()->args([
        abstract_arg('The custom success handler service'),
        [],
        // Options
        abstract_arg('Provider-shared Key'),
    ])->set('security.authentication.success_handler', DefaultAuthenticationSuccessHandler::class)->abstract()->args([
        service('security.http_utils'),
        [],
        // Options
        service('logger')->nullOnInvalid(),
    ])->set('security.authentication.custom_failure_handler', CustomAuthenticationFailureHandler::class)->abstract()->args([abstract_arg('The custom failure handler service'), []])->set('security.authentication.failure_handler', DefaultAuthenticationFailureHandler::class)->abstract()->args([
        service('http_kernel'),
        service('security.http_utils'),
        [],
        // Options
        service('logger')->nullOnInvalid(),
    ])->tag('monolog.logger', ['channel' => 'security'])->set('security.exception_listener', ExceptionListener::class)->abstract()->args([service('security.token_storage'), service('security.authentication.trust_resolver'), service('security.http_utils'), abstract_arg('Provider-shared Key'), service('security.authentication.entry_point')->nullOnInvalid(), param('security.access.denied_url'), service('security.access.denied_handler')->nullOnInvalid(), service('logger')->nullOnInvalid(), \false])->tag('monolog.logger', ['channel' => 'security'])->set('security.authentication.switchuser_listener', SwitchUserListener::class)->abstract()->args([
        service('security.token_storage'),
        abstract_arg('User Provider'),
        abstract_arg('User Checker'),
        abstract_arg('Provider Key'),
        service('security.access.decision_manager'),
        service('logger')->nullOnInvalid(),
        '_switch_user',
        'ROLE_ALLOWED_TO_SWITCH',
        service('event_dispatcher')->nullOnInvalid(),
        \false,
        // Stateless
        service('router')->nullOnInvalid(),
        abstract_arg('Target Route'),
    ])->tag('monolog.logger', ['channel' => 'security'])->set('security.access_listener', AccessListener::class)->args([service('security.token_storage'), service('security.access.decision_manager'), service('security.access_map')])->tag('monolog.logger', ['channel' => 'security'])->set('security.firewall.event_dispatcher_locator', ServiceLocator::class)->args([[]]);
};
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\DependencyInjection\Loader\Configurator;

use _ContaoManager\Symfony\Bundle\SecurityBundle\LoginLink\FirewallAwareLoginLinkHandler;
use _ContaoManager\Symfony\Component\Security\Core\Signature\ExpiredSignatureStorage;
use _ContaoManager\Symfony\Component\Security\Core\Signature\SignatureHasher;
use _ContaoManager\Symfony\Component\Security\Http\Authenticator\LoginLinkAuthenticator;
use _ContaoManager\Symfony\Component\Security\Http\LoginLink\LoginLinkHandler;
use _ContaoManager\Symfony\Component\Security\Http\LoginLink\LoginLinkHandlerInterface;
return static function (ContainerConfigurator $container) {
    $container->services()->set('security.authenticator.login_link', LoginLinkAuthenticator::class)->abstract()->args([abstract_arg('the login link handler instance'), service('security.http_utils'), abstract_arg('authentication success handler'), abstract_arg('authentication failure handler'), abstract_arg('options')])->set('security.authenticator.abstract_login_link_handler', LoginLinkHandler::class)->abstract()->args([service('router'), abstract_arg('user provider'), abstract_arg('signature hasher'), abstract_arg('options')])->set('security.authenticator.abstract_login_link_signature_hasher', SignatureHasher::class)->args([service('property_accessor'), abstract_arg('signature properties'), '%kernel.secret%', abstract_arg('expired signature storage'), abstract_arg('max signature uses')])->set('security.authenticator.expired_login_link_storage', ExpiredSignatureStorage::class)->abstract()->args([abstract_arg('cache pool service'), abstract_arg('expired login link storage')])->set('security.authenticator.cache.expired_links')->parent('cache.app')->private()->set('security.authenticator.firewall_aware_login_link_handler', FirewallAwareLoginLinkHandler::class)->args([service('security.firewall.map'), tagged_locator('security.authenticator.login_linker', 'firewall'), service('request_stack')])->alias(LoginLinkHandlerInterface::class, 'security.authenticator.firewall_aware_login_link_handler');
};
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\DependencyInjection\Loader\Configurator;

use _ContaoManager\Symfony\Bundle\SecurityBundle\Debug\TraceableFirewallListener;
use _ContaoManager\Symfony\Bundle\SecurityBundle\EventListener\VoteListener;
use _ContaoManager\Symfony\Component\Security\Core\Authorization\TraceableAccessDecisionManager;
return static function (ContainerConfigurator $container) {
    $container->services()->set('debug.security.access.decision_manager', TraceableAccessDecisionManager::class)->decorate('security.access.decision_manager')->args([service('debug.security.access.decision_manager.inner')])->set('debug.security.voter.vote_listener', VoteListener::class)->args([service('debug.security.access.decision_manager')])->tag('kernel.event_subscriber')->set('debug.security.firewall', TraceableFirewallListener::class)->args([service('security.firewall.map'), service('event_dispatcher'), service('security.logout_url_generator')])->tag('kernel.event_subscriber')->tag('kernel.reset', ['method' => 'reset'])->alias('security.firewall', 'debug.security.firewall');
};
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\DependencyInjection\Loader\Configurator;

use _ContaoManager\Symfony\Bundle\SecurityBundle\Command\DebugFirewallCommand;
return static function (ContainerConfigurator $container) {
    $container->services()->set('security.command.debug_firewall', DebugFirewallCommand::class)->args([param('security.firewalls'), service('security.firewall.context_locator'), tagged_locator('event_dispatcher.dispatcher', 'name'), [], \false])->tag('console.command', ['command' => 'debug:firewall']);
};
<?xml version="1.0" encoding="UTF-8" ?>
<xsd:schema xmlns="http://symfony.com/schema/dic/security"
    xmlns:xsd="http://www.w3.org/2001/XMLSchema"
    targetNamespace="http://symfony.com/schema/dic/security"
    elementFormDefault="qualified">

    <xsd:element name="config" type="config" />

    <xsd:complexType name="config">
        <xsd:choice maxOccurs="unbounded">
            <xsd:element name="access-decision-manager" type="access_decision_manager" minOccurs="0" maxOccurs="1" />
            <xsd:element name="password_hashers" type="password_hashers" minOccurs="0" maxOccurs="1" />
            <xsd:element name="password_hasher" type="password_hasher" minOccurs="0" maxOccurs="unbounded" />
            <xsd:element name="providers" type="providers" minOccurs="0" maxOccurs="1" />
            <xsd:element name="provider" type="provider" minOccurs="0" maxOccurs="unbounded" />
            <xsd:element name="firewalls" type="firewalls" minOccurs="0" maxOccurs="1" />
            <xsd:element name="firewall" type="firewall" minOccurs="0" maxOccurs="unbounded" />
            <xsd:element name="rule" type="rule" minOccurs="0" maxOccurs="unbounded" />
            <xsd:element name="role" type="role" minOccurs="0" maxOccurs="unbounded" />
        </xsd:choice>
        <xsd:attribute name="access-denied-url" type="xsd:string" />
        <xsd:attribute name="session-fixation-strategy" type="session_fixation_strategy" />
        <xsd:attribute name="hide-user-not-found" type="xsd:boolean" />
        <xsd:attribute name="always-authenticate-before-granting" type="xsd:boolean" />
        <xsd:attribute name="erase-credentials" type="xsd:boolean" />
        <xsd:attribute name="enable-authenticator-manager" type="xsd:boolean" />
    </xsd:complexType>

    <xsd:complexType name="password_hashers">
        <xsd:sequence>
            <xsd:element name="password_hasher" type="password_hasher" minOccurs="1" maxOccurs="unbounded" />
        </xsd:sequence>
    </xsd:complexType>

    <xsd:complexType name="providers">
        <xsd:sequence>
            <xsd:element name="provider" type="provider" minOccurs="1" maxOccurs="unbounded" />
        </xsd:sequence>
    </xsd:complexType>

    <xsd:complexType name="firewalls">
        <xsd:sequence>
            <xsd:element name="firewall" type="firewall" minOccurs="1" maxOccurs="unbounded" />
        </xsd:sequence>
    </xsd:complexType>

    <xsd:simpleType name="session_fixation_strategy">
        <xsd:restriction base="xsd:string">
            <xsd:enumeration value="none" />
            <xsd:enumeration value="migrate" />
            <xsd:enumeration value="invalidate" />
        </xsd:restriction>
    </xsd:simpleType>

    <xsd:complexType name="access_decision_manager">
        <xsd:attribute name="strategy" type="access_decision_manager_strategy" />
        <xsd:attribute name="service" type="xsd:string" />
        <xsd:attribute name="strategy-service" type="xsd:string" />
        <xsd:attribute name="allow-if-all-abstain" type="xsd:boolean" />
        <xsd:attribute name="allow-if-equal-granted-denied" type="xsd:boolean" />
    </xsd:complexType>

    <xsd:simpleType name="access_decision_manager_strategy">
        <xsd:restriction base="xsd:string">
            <xsd:enumeration value="affirmative" />
            <xsd:enumeration value="consensus" />
            <xsd:enumeration value="unanimous" />
            <xsd:enumeration value="priority" />
        </xsd:restriction>
    </xsd:simpleType>

    <xsd:complexType name="password_hasher">
        <xsd:sequence>
            <xsd:element name="migrate-from" type="xsd:string" minOccurs="0" maxOccurs="unbounded" />
        </xsd:sequence>
        <xsd:attribute name="class" type="xsd:string" use="required" />
        <xsd:attribute name="algorithm" type="xsd:string" />
        <xsd:attribute name="hash-algorithm" type="xsd:string" />
        <xsd:attribute name="key-length" type="xsd:string" />
        <xsd:attribute name="ignore-case" type="xsd:boolean" />
        <xsd:attribute name="encode-as-base64" type="xsd:boolean" />
        <xsd:attribute name="iterations" type="xsd:string" />
        <xsd:attribute name="cost" type="xsd:integer" />
        <xsd:attribute name="memory-cost" type="xsd:string" />
        <xsd:attribute name="time-cost" type="xsd:string" />
        <xsd:attribute name="id" type="xsd:string" />
    </xsd:complexType>

    <xsd:complexType name="provider">
        <xsd:choice minOccurs="0" maxOccurs="1">
            <xsd:element name="chain" type="chain" />
            <xsd:element name="memory" type="memory" />
            <xsd:element name="ldap" type="ldap" />
            <!-- allow factories to use dynamic elements -->
            <xsd:any processContents="lax" namespace="##other" />
        </xsd:choice>
        <xsd:attribute name="name" type="xsd:string" use="required" />
        <xsd:attribute name="id" type="xsd:string" />
    </xsd:complexType>

    <xsd:complexType name="chain">
        <xsd:sequence minOccurs="0" maxOccurs="unbounded">
            <xsd:element name="provider" type="xsd:string" />
        </xsd:sequence>
        <xsd:attribute name="providers" type="xsd:string" />
    </xsd:complexType>

    <xsd:complexType name="memory">
        <xsd:sequence>
            <xsd:element name="user" type="user" minOccurs="1" maxOccurs="unbounded" />
        </xsd:sequence>
    </xsd:complexType>

    <xsd:complexType name="user">
        <xsd:attribute name="identifier" type="xsd:string" />
        <xsd:attribute name="password" type="xsd:string" />
        <xsd:attribute name="roles" type="xsd:string" />
    </xsd:complexType>

    <xsd:complexType name="ldap">
        <xsd:choice minOccurs="0" maxOccurs="unbounded">
            <xsd:element name="extra-field" type="xsd:string" minOccurs="0" maxOccurs="unbounded" />
            <xsd:element name="default-role" type="xsd:string" minOccurs="0" maxOccurs="unbounded" />
        </xsd:choice>
        <xsd:attribute name="service" type="xsd:string" use="required" />
        <xsd:attribute name="base-dn" type="xsd:string" use="required" />
        <xsd:attribute name="search-dn" type="xsd:string" />
        <xsd:attribute name="search-password" type="xsd:string" />
        <xsd:attribute name="uid-key" type="xsd:string" />
        <xsd:attribute name="filter" type="xsd:string" />
        <xsd:attribute name="password-attribute" type="xsd:string" />
    </xsd:complexType>

    <xsd:complexType name="firewall">
        <xsd:choice maxOccurs="unbounded">
            <xsd:element name="logout" type="logout" minOccurs="0" maxOccurs="1" />
            <xsd:element name="switch-user" type="switch_user" minOccurs="0" maxOccurs="1" />
            <xsd:element name="anonymous" type="anonymous" minOccurs="0" maxOccurs="1" />
            <xsd:element name="form-login" type="form_login" minOccurs="0" maxOccurs="1" />
            <xsd:element name="form-login-ldap" type="form_login_ldap" minOccurs="0" maxOccurs="1" />
            <xsd:element name="guard" type="guard" minOccurs="0" maxOccurs="1" />
            <xsd:element name="access-token" type="access_token" minOccurs="0" maxOccurs="1" />
            <xsd:element name="http-basic" type="http_basic" minOccurs="0" maxOccurs="1" />
            <xsd:element name="http-basic-ldap" type="http_basic_ldap" minOccurs="0" maxOccurs="1" />
            <xsd:element name="json-login" type="json_login" minOccurs="0" maxOccurs="1" />
            <xsd:element name="json-login-ldap" type="json_login_ldap" minOccurs="0" maxOccurs="1" />
            <xsd:element name="login-link" type="login_link" minOccurs="0" maxOccurs="1" />
            <xsd:element name="login-throttling" type="login_throttling" minOccurs="0" maxOccurs="1" />
            <xsd:element name="remember-me" type="remember_me" minOccurs="0" maxOccurs="1" />
            <xsd:element name="remote-user" type="remote_user" minOccurs="0" maxOccurs="1" />
            <xsd:element name="x509" type="x509" minOccurs="0" maxOccurs="1" />
            <xsd:element name="required-badge" type="xsd:string" minOccurs="0" maxOccurs="unbounded" />
            <!-- allow factories to use dynamic elements -->
            <xsd:any processContents="lax" minOccurs="0" maxOccurs="unbounded" namespace="##other" />
        </xsd:choice>
        <xsd:attribute name="name" type="xsd:string" use="required" />
        <xsd:attribute name="pattern" type="xsd:string" />
        <xsd:attribute name="host" type="xsd:string" />
        <xsd:attribute name="methods" type="xsd:string" />
        <xsd:attribute name="security" type="xsd:boolean" />
        <xsd:attribute name="user-checker" type="xsd:string" />
        <xsd:attribute name="request-matcher" type="xsd:string" />
        <xsd:attribute name="access-denied-url" type="xsd:string" />
        <xsd:attribute name="access-denied-handler" type="xsd:string" />
        <xsd:attribute name="entry-point" type="xsd:string" />
        <xsd:attribute name="provider" type="xsd:string" />
        <xsd:attribute name="stateless" type="xsd:boolean" />
        <xsd:attribute name="context" type="xsd:string" />
        <xsd:attribute name="lazy" type="xsd:boolean" />
        <!-- allow factories to use dynamic elements -->
        <xsd:anyAttribute processContents="lax" />
    </xsd:complexType>

    <xsd:complexType name="logout">
        <xsd:choice minOccurs="0" maxOccurs="unbounded">
            <xsd:element name="delete-cookie" type="delete_cookie" minOccurs="0" maxOccurs="unbounded" />
            <xsd:element name="clear-site-data" type="clear_site_data" minOccurs="0" maxOccurs="unbounded" />
        </xsd:choice>
        <xsd:attribute name="csrf-parameter" type="xsd:string" />
        <xsd:attribute name="csrf-token-generator" type="xsd:string" />
        <xsd:attribute name="csrf-token-manager" type="xsd:string" />
        <xsd:attribute name="csrf-token-id" type="xsd:string" />
        <xsd:attribute name="enable-csrf" type="xsd:boolean" />
        <xsd:attribute name="path" type="xsd:string" />
        <xsd:attribute name="target" type="xsd:string" />
        <xsd:attribute name="invalidate-session" type="xsd:boolean" />
    </xsd:complexType>

    <xsd:complexType name="delete_cookie">
        <xsd:attribute name="name" type="xsd:string" use="required" />
        <xsd:attribute name="path" type="xsd:string" />
        <xsd:attribute name="domain" type="xsd:string" />
    </xsd:complexType>

    <xsd:complexType name="switch_user">
        <xsd:attribute name="provider" type="xsd:string" />
        <xsd:attribute name="parameter" type="xsd:string" />
        <xsd:attribute name="role" type="xsd:string" />
    </xsd:complexType>

    <xsd:complexType name="anonymous">
        <xsd:attribute name="lazy" type="xsd:boolean" />
        <xsd:attribute name="secret" type="xsd:string" />
    </xsd:complexType>

    <xsd:complexType name="factory" abstract="true">
        <xsd:attribute name="check-path" type="xsd:string" />
        <xsd:attribute name="use-forward" type="xsd:boolean" />
        <xsd:attribute name="require-previous-session" type="xsd:boolean" />
        <xsd:attribute name="provider" type="xsd:string" />
    </xsd:complexType>

    <xsd:attributeGroup name="success-handler-options">
        <xsd:attribute name="always-use-default-target-path" type="xsd:boolean" />
        <xsd:attribute name="default-target-path" type="xsd:string" />
        <xsd:attribute name="target-path-parameter" type="xsd:string" />
        <xsd:attribute name="use-referer" type="xsd:boolean" />
    </xsd:attributeGroup>

    <xsd:attributeGroup name="failure-handler-options">
        <xsd:attribute name="failure-path" type="xsd:string" />
        <xsd:attribute name="failure-forward" type="xsd:boolean" />
        <xsd:attribute name="failure-path-parameter" type="xsd:string" />
    </xsd:attributeGroup>

    <xsd:attributeGroup name="ldap-factory">
        <xsd:attribute name="service" type="xsd:string" />
        <xsd:attribute name="dn-string" type="xsd:string" />
        <xsd:attribute name="query-string" type="xsd:string" />
        <xsd:attribute name="search-dn" type="xsd:string" />
        <xsd:attribute name="search-password" type="xsd:string" />
    </xsd:attributeGroup>

    <xsd:complexType name="form_login">
        <xsd:complexContent>
            <xsd:extension base="factory">
                <xsd:attribute name="login-path" type="xsd:string" />
                <xsd:attribute name="username-parameter" type="xsd:string" />
                <xsd:attribute name="password-parameter" type="xsd:string" />
                <xsd:attribute name="csrf-parameter" type="xsd:string" />
                <xsd:attribute name="csrf-token-id" type="xsd:string" />
                <xsd:attribute name="post-only" type="xsd:boolean" />
                <xsd:attribute name="csrf-token-generator" type="xsd:string" />
                <xsd:attribute name="enable-csrf" type="xsd:boolean" />
                <xsd:attributeGroup ref="success-handler-options" />
                <xsd:attributeGroup ref="failure-handler-options" />
            </xsd:extension>
        </xsd:complexContent>
    </xsd:complexType>

    <xsd:complexType name="form_login_ldap">
        <xsd:complexContent>
            <xsd:extension base="form_login">
                <xsd:attributeGroup ref="ldap-factory" />
            </xsd:extension>
        </xsd:complexContent>
    </xsd:complexType>

    <xsd:complexType name="guard">
        <xsd:sequence>
            <xsd:element name="authenticator" type="xsd:string" minOccurs="1" maxOccurs="unbounded" />
        </xsd:sequence>
        <xsd:attribute name="provider" type="xsd:string" />
        <xsd:attribute name="entry-point" type="xsd:string" />
    </xsd:complexType>

    <xsd:complexType name="http_basic">
        <xsd:attribute name="provider" type="xsd:string" />
        <xsd:attribute name="realm" type="xsd:string" />
    </xsd:complexType>

    <xsd:complexType name="http_basic_ldap">
        <xsd:complexContent>
            <xsd:extension base="http_basic">
                <xsd:attributeGroup ref="ldap-factory" />
            </xsd:extension>
        </xsd:complexContent>
    </xsd:complexType>

    <xsd:complexType name="json_login">
        <xsd:complexContent>
            <xsd:extension base="factory">
                <xsd:attribute name="username-path" type="xsd:string" />
                <xsd:attribute name="password-path" type="xsd:string" />
            </xsd:extension>
        </xsd:complexContent>
    </xsd:complexType>

    <xsd:complexType name="json_login_ldap">
        <xsd:complexContent>
            <xsd:extension base="json_login">
                <xsd:attributeGroup ref="ldap-factory" />
            </xsd:extension>
        </xsd:complexContent>
    </xsd:complexType>

    <xsd:complexType name="login_link">
        <xsd:choice minOccurs="0" maxOccurs="unbounded">
            <xsd:element name="signature-property" type="xsd:string" />
        </xsd:choice>
        <xsd:attribute name="check-route" type="xsd:string" />
        <xsd:attribute name="check-post-only" type="xsd:boolean" />
        <xsd:attribute name="lifetime" type="xsd:integer" />
        <xsd:attribute name="max-uses" type="xsd:integer" />
        <xsd:attribute name="used-link-cache" type="xsd:string" />
        <xsd:attribute name="success-handler" type="xsd:string" />
        <xsd:attribute name="failure-handler" type="xsd:string" />
        <xsd:attribute name="provider" type="xsd:string" />
    </xsd:complexType>

    <xsd:complexType name="access_token">
        <xsd:choice minOccurs="0" maxOccurs="unbounded">
            <xsd:element name="token-extractor" type="xsd:string" />
            <xsd:element name="token-handler" type="oidc_token_handler" />
        </xsd:choice>
        <xsd:attribute name="token-handler" type="xsd:string" />
        <xsd:attribute name="realm" type="xsd:string" />
        <xsd:attribute name="success-handler" type="xsd:string" />
        <xsd:attribute name="failure-handler" type="xsd:string" />
        <xsd:attribute name="provider" type="xsd:string" />
    </xsd:complexType>

    <xsd:complexType name="oidc_token_handler">
        <xsd:sequence>
            <xsd:choice minOccurs="0" maxOccurs="1">
                <xsd:element name="oidc-user-info" type="oidc_user_info"></xsd:element>
                <xsd:element name="oidc" type="oidc"></xsd:element>
            </xsd:choice>
        </xsd:sequence>
        <xsd:attribute name="oidc-user-info" type="xsd:anyURI"></xsd:attribute>
    </xsd:complexType>

    <xsd:complexType name="oidc_user_info">
        <xsd:attribute name="base-uri" type="xsd:anyURI" use="required" />
        <xsd:attribute name="claim" type="xsd:string" />
        <xsd:attribute name="client" type="xsd:string" />
    </xsd:complexType>

    <xsd:complexType name="oidc">
        <xsd:choice maxOccurs="unbounded">
            <xsd:element name="issuers" type="oidc_issuers" minOccurs="0" maxOccurs="1" />
            <xsd:element name="issuer" type="password_hasher" minOccurs="0" maxOccurs="unbounded" />
        </xsd:choice>
        <xsd:attribute name="claim" type="xsd:string" />
        <xsd:attribute name="audience" type="xsd:string" use="required" />
        <xsd:attribute name="algorithm" type="xsd:string" use="required" />
        <xsd:attribute name="key" type="xsd:string" use="required" />
    </xsd:complexType>

    <xsd:complexType name="oidc_issuers">
        <xsd:sequence>
            <xsd:element name="issuer" type="xsd:string" minOccurs="1" maxOccurs="unbounded" />
        </xsd:sequence>
    </xsd:complexType>

    <xsd:complexType name="login_throttling">
        <xsd:attribute name="limiter" type="xsd:string" />
        <xsd:attribute name="max-attempts" type="xsd:integer" />
    </xsd:complexType>

    <xsd:complexType name="remember_me">
        <xsd:sequence minOccurs="0">
            <xsd:choice minOccurs="0" maxOccurs="unbounded">
                <xsd:element name="user-provider" type="xsd:string" />
            </xsd:choice>
            <xsd:element name="token-provider" type="remember_me_token_provider" />
        </xsd:sequence>
        <xsd:attribute name="name" type="xsd:string" />
        <xsd:attribute name="lifetime" type="xsd:integer" />
        <xsd:attribute name="path" type="xsd:string" />
        <xsd:attribute name="domain" type="xsd:string" />
        <xsd:attribute name="http-only" type="xsd:boolean" />
        <xsd:attribute name="always-remember-me" type="xsd:boolean" />
        <xsd:attribute name="remember-me-parameter" type="xsd:string" />
        <xsd:attribute name="secret" type="xsd:string" use="required" />
        <xsd:attribute name="service" type="xsd:string" />
        <xsd:attribute name="token-provider" type="xsd:string" />
        <xsd:attribute name="token-verifier" type="xsd:string" />
        <xsd:attribute name="catch-exceptions" type="xsd:boolean" />
        <xsd:attribute name="secure" type="remember_me_secure" />
        <xsd:attribute name="samesite" type="remember_me_samesite" />
        <xsd:attribute name="partitioned" type="xsd:boolean" />
    </xsd:complexType>

    <xsd:complexType name="remember_me_token_provider">
        <xsd:sequence>
            <xsd:element name="doctrine" type="remember_me_token_provider_doctrine" />
        </xsd:sequence>
        <xsd:attribute name="service" type="xsd:string" />
    </xsd:complexType>

    <xsd:complexType name="remember_me_token_provider_doctrine">
        <xsd:attribute name="enabled" type="xsd:boolean" />
        <xsd:attribute name="connection" type="xsd:string" />
    </xsd:complexType>

    <xsd:simpleType name="remember_me_secure">
        <xsd:restriction base="xsd:string">
            <xsd:enumeration value="true" />
            <xsd:enumeration value="false" />
            <xsd:enumeration value="auto" />
        </xsd:restriction>
    </xsd:simpleType>

    <xsd:simpleType name="remember_me_samesite">
        <xsd:restriction base="xsd:string">
            <xsd:enumeration value="null" />
            <xsd:enumeration value="lax" />
            <xsd:enumeration value="strict" />
            <xsd:enumeration value="none" />
        </xsd:restriction>
    </xsd:simpleType>

    <xsd:complexType name="remote_user">
        <xsd:attribute name="provider" type="xsd:string" />
        <xsd:attribute name="user" type="xsd:string" />
    </xsd:complexType>

    <xsd:complexType name="x509">
        <xsd:attribute name="provider" type="xsd:string" />
        <xsd:attribute name="user" type="xsd:string" />
        <xsd:attribute name="credentials" type="xsd:string" />
    </xsd:complexType>

    <xsd:complexType name="rule">
        <xsd:choice>
            <xsd:element name="ip" type="xsd:string" minOccurs="0" maxOccurs="unbounded" />
            <xsd:element name="method" type="xsd:string" minOccurs="0" maxOccurs="unbounded" />
            <xsd:element name="role" type="xsd:string" minOccurs="0" maxOccurs="unbounded" />
            <xsd:element name="allow-if" type="xsd:string" minOccurs="0" maxOccurs="1" />
            <xsd:element name="attribute" type="rule_attribute" minOccurs="0" maxOccurs="1" />
        </xsd:choice>
        <xsd:attribute name="requires-channel" type="xsd:string" />
        <xsd:attribute name="path" type="xsd:string" />
        <xsd:attribute name="host" type="xsd:string" />
        <xsd:attribute name="port" type="xsd:integer" />
        <xsd:attribute name="role" type="xsd:string" />
        <xsd:attribute name="methods" type="xsd:string" />
        <xsd:attribute name="allow-if" type="xsd:string" />
        <xsd:attribute name="route" type="xsd:string" />
    </xsd:complexType>

    <xsd:complexType name="role">
        <xsd:simpleContent>
            <xsd:extension base="xsd:string">
                <xsd:attribute name="id" type="xsd:string" use="required" />
                <xsd:attribute name="value" type="xsd:string" />
            </xsd:extension>
        </xsd:simpleContent>
    </xsd:complexType>

    <xsd:complexType name="rule_attribute">
        <xsd:simpleContent>
            <xsd:extension base="xsd:string">
                <xsd:attribute name="key" type="xsd:string" use="required" />
            </xsd:extension>
        </xsd:simpleContent>
    </xsd:complexType>

    <xsd:simpleType name="clear_site_data">
        <xsd:restriction base="xsd:string">
            <xsd:enumeration value="*" />
            <xsd:enumeration value="cache" />
            <xsd:enumeration value="cookies" />
            <xsd:enumeration value="storage" />
            <xsd:enumeration value="executionContexts" />
        </xsd:restriction>
    </xsd:simpleType>

</xsd:schema>
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\DependencyInjection\Loader\Configurator;

use _ContaoManager\Symfony\Component\PasswordHasher\Command\UserPasswordHashCommand;
return static function (ContainerConfigurator $container) {
    $container->services()->set('security.command.user_password_hash', UserPasswordHashCommand::class)->args([service('security.password_hasher_factory'), abstract_arg('list of user classes')])->tag('console.command');
};
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\DependencyInjection\Loader\Configurator;

use _ContaoManager\Symfony\Component\Form\Extension\Core\Type\FormType;
use _ContaoManager\Symfony\Component\Form\Extension\Core\Type\PasswordType;
use _ContaoManager\Symfony\Component\Form\Extension\PasswordHasher\EventListener\PasswordHasherListener;
use _ContaoManager\Symfony\Component\Form\Extension\PasswordHasher\Type\FormTypePasswordHasherExtension;
use _ContaoManager\Symfony\Component\Form\Extension\PasswordHasher\Type\PasswordTypePasswordHasherExtension;
use _ContaoManager\Symfony\Component\PasswordHasher\Hasher\PasswordHasherFactory;
use _ContaoManager\Symfony\Component\PasswordHasher\Hasher\PasswordHasherFactoryInterface;
use _ContaoManager\Symfony\Component\PasswordHasher\Hasher\UserPasswordHasher;
use _ContaoManager\Symfony\Component\PasswordHasher\Hasher\UserPasswordHasherInterface;
return static function (ContainerConfigurator $container) {
    $container->services()->set('security.password_hasher_factory', PasswordHasherFactory::class)->args([[]])->alias(PasswordHasherFactoryInterface::class, 'security.password_hasher_factory')->set('security.user_password_hasher', UserPasswordHasher::class)->args([service('security.password_hasher_factory')])->alias('security.password_hasher', 'security.user_password_hasher')->alias(UserPasswordHasherInterface::class, 'security.password_hasher')->set('form.listener.password_hasher', PasswordHasherListener::class)->args([service('security.password_hasher'), service('property_accessor')->nullOnInvalid()])->set('form.type_extension.form.password_hasher', FormTypePasswordHasherExtension::class)->args([service('form.listener.password_hasher')])->tag('form.type_extension', ['extended-type' => FormType::class])->set('form.type_extension.password.password_hasher', PasswordTypePasswordHasherExtension::class)->args([service('form.listener.password_hasher')])->tag('form.type_extension', ['extended-type' => PasswordType::class]);
};
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\DependencyInjection\Loader\Configurator;

use _ContaoManager\Symfony\Bundle\SecurityBundle\DataCollector\SecurityDataCollector;
return static function (ContainerConfigurator $container) {
    $container->services()->set('data_collector.security', SecurityDataCollector::class)->args([service('security.untracked_token_storage'), service('security.role_hierarchy'), service('security.logout_url_generator'), service('security.access.decision_manager'), service('security.firewall.map'), service('debug.security.firewall')->nullOnInvalid()])->tag('data_collector', ['template' => '@Security/Collector/security.html.twig', 'id' => 'security', 'priority' => 270]);
};
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\DependencyInjection\Loader\Configurator;

use _ContaoManager\Symfony\Bundle\SecurityBundle\Security\UserAuthenticator;
use _ContaoManager\Symfony\Component\DependencyInjection\ServiceLocator;
use _ContaoManager\Symfony\Component\Security\Http\Authentication\AuthenticatorManager;
use _ContaoManager\Symfony\Component\Security\Http\Authentication\UserAuthenticatorInterface;
use _ContaoManager\Symfony\Component\Security\Http\Authenticator\FormLoginAuthenticator;
use _ContaoManager\Symfony\Component\Security\Http\Authenticator\HttpBasicAuthenticator;
use _ContaoManager\Symfony\Component\Security\Http\Authenticator\JsonLoginAuthenticator;
use _ContaoManager\Symfony\Component\Security\Http\Authenticator\RemoteUserAuthenticator;
use _ContaoManager\Symfony\Component\Security\Http\Authenticator\X509Authenticator;
use _ContaoManager\Symfony\Component\Security\Http\Event\CheckPassportEvent;
use _ContaoManager\Symfony\Component\Security\Http\EventListener\CheckCredentialsListener;
use _ContaoManager\Symfony\Component\Security\Http\EventListener\LoginThrottlingListener;
use _ContaoManager\Symfony\Component\Security\Http\EventListener\PasswordMigratingListener;
use _ContaoManager\Symfony\Component\Security\Http\EventListener\SessionStrategyListener;
use _ContaoManager\Symfony\Component\Security\Http\EventListener\UserCheckerListener;
use _ContaoManager\Symfony\Component\Security\Http\EventListener\UserProviderListener;
use _ContaoManager\Symfony\Component\Security\Http\Firewall\AuthenticatorManagerListener;
return static function (ContainerConfigurator $container) {
    $container->services()->set('security.authenticator.manager', AuthenticatorManager::class)->abstract()->args([abstract_arg('authenticators'), service('security.token_storage'), service('event_dispatcher'), abstract_arg('provider key'), service('logger')->nullOnInvalid(), param('security.authentication.manager.erase_credentials'), param('security.authentication.hide_user_not_found'), abstract_arg('required badges')])->tag('monolog.logger', ['channel' => 'security'])->set('security.authenticator.managers_locator', ServiceLocator::class)->args([[]])->set('security.user_authenticator', UserAuthenticator::class)->args([service('security.firewall.map'), service('security.authenticator.managers_locator'), service('request_stack')])->alias(UserAuthenticatorInterface::class, 'security.user_authenticator')->set('security.firewall.authenticator', AuthenticatorManagerListener::class)->abstract()->args([abstract_arg('authenticator manager')])->set('security.listener.check_authenticator_credentials', CheckCredentialsListener::class)->args([service('security.password_hasher_factory')])->tag('kernel.event_subscriber')->set('security.listener.user_provider', UserProviderListener::class)->args([service('security.user_providers')])->tag('kernel.event_listener', ['event' => CheckPassportEvent::class, 'priority' => 1024, 'method' => 'checkPassport'])->set('security.listener.user_provider.abstract', UserProviderListener::class)->abstract()->args([abstract_arg('user provider')])->set('security.listener.password_migrating', PasswordMigratingListener::class)->args([service('security.password_hasher_factory')])->tag('kernel.event_subscriber')->set('security.listener.user_checker', UserCheckerListener::class)->abstract()->args([abstract_arg('user checker')])->set('security.listener.session', SessionStrategyListener::class)->abstract()->args([service('security.authentication.session_strategy')])->set('security.listener.login_throttling', LoginThrottlingListener::class)->abstract()->args([service('request_stack'), abstract_arg('request rate limiter')])->set('security.authenticator.http_basic', HttpBasicAuthenticator::class)->abstract()->args([abstract_arg('realm name'), abstract_arg('user provider'), service('logger')->nullOnInvalid()])->tag('monolog.logger', ['channel' => 'security'])->set('security.authenticator.form_login', FormLoginAuthenticator::class)->abstract()->args([service('security.http_utils'), abstract_arg('user provider'), abstract_arg('authentication success handler'), abstract_arg('authentication failure handler'), abstract_arg('options')])->set('security.authenticator.json_login', JsonLoginAuthenticator::class)->abstract()->args([service('security.http_utils'), abstract_arg('user provider'), abstract_arg('authentication success handler'), abstract_arg('authentication failure handler'), abstract_arg('options'), service('property_accessor')->nullOnInvalid()])->call('setTranslator', [service('translator')->ignoreOnInvalid()])->set('security.authenticator.x509', X509Authenticator::class)->abstract()->args([abstract_arg('user provider'), service('security.token_storage'), abstract_arg('firewall name'), abstract_arg('user key'), abstract_arg('credentials key'), service('logger')->nullOnInvalid(), abstract_arg('credentials user identifier')])->tag('monolog.logger', ['channel' => 'security'])->set('security.authenticator.remote_user', RemoteUserAuthenticator::class)->abstract()->args([abstract_arg('user provider'), service('security.token_storage'), abstract_arg('firewall name'), abstract_arg('user key'), service('logger')->nullOnInvalid()])->tag('monolog.logger', ['channel' => 'security']);
};
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\DependencyInjection\Loader\Configurator;

use _ContaoManager\Symfony\Bundle\SecurityBundle\CacheWarmer\ExpressionCacheWarmer;
use _ContaoManager\Symfony\Bundle\SecurityBundle\EventListener\FirewallListener;
use _ContaoManager\Symfony\Bundle\SecurityBundle\Routing\LogoutRouteLoader;
use _ContaoManager\Symfony\Bundle\SecurityBundle\Security;
use _ContaoManager\Symfony\Bundle\SecurityBundle\Security\FirewallConfig;
use _ContaoManager\Symfony\Bundle\SecurityBundle\Security\FirewallContext;
use _ContaoManager\Symfony\Bundle\SecurityBundle\Security\FirewallMap;
use _ContaoManager\Symfony\Bundle\SecurityBundle\Security\LazyFirewallContext;
use _ContaoManager\Symfony\Component\DependencyInjection\ServiceLocator;
use _ContaoManager\Symfony\Component\ExpressionLanguage\ExpressionLanguage as BaseExpressionLanguage;
use _ContaoManager\Symfony\Component\Ldap\Security\LdapUserProvider;
use _ContaoManager\Symfony\Component\Security\Core\Authentication\AuthenticationTrustResolver;
use _ContaoManager\Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorage;
use _ContaoManager\Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
use _ContaoManager\Symfony\Component\Security\Core\Authentication\Token\Storage\UsageTrackingTokenStorage;
use _ContaoManager\Symfony\Component\Security\Core\Authorization\AccessDecisionManager;
use _ContaoManager\Symfony\Component\Security\Core\Authorization\AccessDecisionManagerInterface;
use _ContaoManager\Symfony\Component\Security\Core\Authorization\AuthorizationChecker;
use _ContaoManager\Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface;
use _ContaoManager\Symfony\Component\Security\Core\Authorization\ExpressionLanguage;
use _ContaoManager\Symfony\Component\Security\Core\Authorization\Voter\AuthenticatedVoter;
use _ContaoManager\Symfony\Component\Security\Core\Authorization\Voter\ExpressionVoter;
use _ContaoManager\Symfony\Component\Security\Core\Authorization\Voter\RoleHierarchyVoter;
use _ContaoManager\Symfony\Component\Security\Core\Authorization\Voter\RoleVoter;
use _ContaoManager\Symfony\Component\Security\Core\Role\RoleHierarchy;
use _ContaoManager\Symfony\Component\Security\Core\Role\RoleHierarchyInterface;
use _ContaoManager\Symfony\Component\Security\Core\Security as LegacySecurity;
use _ContaoManager\Symfony\Component\Security\Core\User\ChainUserProvider;
use _ContaoManager\Symfony\Component\Security\Core\User\InMemoryUserChecker;
use _ContaoManager\Symfony\Component\Security\Core\User\InMemoryUserProvider;
use _ContaoManager\Symfony\Component\Security\Core\User\MissingUserProvider;
use _ContaoManager\Symfony\Component\Security\Core\Validator\Constraints\UserPasswordValidator;
use _ContaoManager\Symfony\Component\Security\Http\Authentication\AuthenticationUtils;
use _ContaoManager\Symfony\Component\Security\Http\Controller\SecurityTokenValueResolver;
use _ContaoManager\Symfony\Component\Security\Http\Controller\UserValueResolver;
use _ContaoManager\Symfony\Component\Security\Http\EventListener\IsGrantedAttributeListener;
use _ContaoManager\Symfony\Component\Security\Http\Firewall;
use _ContaoManager\Symfony\Component\Security\Http\FirewallMapInterface;
use _ContaoManager\Symfony\Component\Security\Http\HttpUtils;
use _ContaoManager\Symfony\Component\Security\Http\Impersonate\ImpersonateUrlGenerator;
use _ContaoManager\Symfony\Component\Security\Http\Logout\LogoutUrlGenerator;
use _ContaoManager\Symfony\Component\Security\Http\Session\SessionAuthenticationStrategy;
use _ContaoManager\Symfony\Component\Security\Http\Session\SessionAuthenticationStrategyInterface;
return static function (ContainerConfigurator $container) {
    $container->parameters()->set('security.role_hierarchy.roles', []);
    $container->services()->set('security.authorization_checker', AuthorizationChecker::class)->args([service('security.token_storage'), service('security.access.decision_manager')])->alias(AuthorizationCheckerInterface::class, 'security.authorization_checker')->set('security.token_storage', UsageTrackingTokenStorage::class)->args([service('security.untracked_token_storage'), service_locator(['request_stack' => service('request_stack')])])->tag('kernel.reset', ['method' => 'disableUsageTracking'])->tag('kernel.reset', ['method' => 'setToken'])->alias(TokenStorageInterface::class, 'security.token_storage')->set('security.untracked_token_storage', TokenStorage::class)->set('security.helper', Security::class)->args([service_locator(['security.token_storage' => service('security.token_storage'), 'security.authorization_checker' => service('security.authorization_checker'), 'security.authenticator.managers_locator' => service('security.authenticator.managers_locator')->ignoreOnInvalid(), 'request_stack' => service('request_stack'), 'security.firewall.map' => service('security.firewall.map'), 'security.user_checker_locator' => service('security.user_checker_locator'), 'security.firewall.event_dispatcher_locator' => service('security.firewall.event_dispatcher_locator'), 'security.csrf.token_manager' => service('security.csrf.token_manager')->ignoreOnInvalid()]), abstract_arg('authenticators')])->alias(Security::class, 'security.helper')->alias(LegacySecurity::class, 'security.helper')->deprecate('symfony/security-bundle', '6.2', 'The "%alias_id%" service alias is deprecated, use "' . Security::class . '" instead.')->set('security.user_value_resolver', UserValueResolver::class)->args([service('security.token_storage')])->tag('controller.argument_value_resolver', ['priority' => 120, 'name' => UserValueResolver::class])->set('security.security_token_value_resolver', SecurityTokenValueResolver::class)->args([service('security.token_storage')])->tag('controller.argument_value_resolver', ['priority' => 120, 'name' => SecurityTokenValueResolver::class])->set('security.authentication.trust_resolver', AuthenticationTrustResolver::class)->set('security.authentication.session_strategy', SessionAuthenticationStrategy::class)->args([param('security.authentication.session_strategy.strategy'), service('security.csrf.token_storage')->ignoreOnInvalid()])->alias(SessionAuthenticationStrategyInterface::class, 'security.authentication.session_strategy')->set('security.authentication.session_strategy_noop', SessionAuthenticationStrategy::class)->args(['none'])->set('security.user_checker', InMemoryUserChecker::class)->set('security.user_checker_locator', ServiceLocator::class)->args([[]])->set('security.expression_language', ExpressionLanguage::class)->args([service('cache.security_expression_language')->nullOnInvalid()])->set('security.authentication_utils', AuthenticationUtils::class)->args([service('request_stack')])->alias(AuthenticationUtils::class, 'security.authentication_utils')->set('security.access.decision_manager', AccessDecisionManager::class)->args([[]])->alias(AccessDecisionManagerInterface::class, 'security.access.decision_manager')->set('security.role_hierarchy', RoleHierarchy::class)->args([param('security.role_hierarchy.roles')])->alias(RoleHierarchyInterface::class, 'security.role_hierarchy')->set('security.access.simple_role_voter', RoleVoter::class)->tag('security.voter', ['priority' => 245])->set('security.access.authenticated_voter', AuthenticatedVoter::class)->args([service('security.authentication.trust_resolver')])->tag('security.voter', ['priority' => 250])->set('security.access.role_hierarchy_voter', RoleHierarchyVoter::class)->args([service('security.role_hierarchy')])->tag('security.voter', ['priority' => 245])->set('security.access.expression_voter', ExpressionVoter::class)->args([service('security.expression_language'), service('security.authentication.trust_resolver'), service('security.authorization_checker'), service('security.role_hierarchy')->nullOnInvalid()])->tag('security.voter', ['priority' => 245])->set('security.impersonate_url_generator', ImpersonateUrlGenerator::class)->args([service('request_stack'), service('security.firewall.map'), service('security.token_storage')])->set('security.firewall', FirewallListener::class)->args([service('security.firewall.map'), service('event_dispatcher'), service('security.logout_url_generator')])->tag('kernel.event_subscriber')->alias(Firewall::class, 'security.firewall')->set('security.firewall.map', FirewallMap::class)->args([abstract_arg('Firewall context locator'), abstract_arg('Request matchers')])->alias(FirewallMapInterface::class, 'security.firewall.map')->set('security.firewall.context', FirewallContext::class)->abstract()->args([[], service('security.exception_listener'), abstract_arg('LogoutListener'), abstract_arg('FirewallConfig')])->set('security.firewall.lazy_context', LazyFirewallContext::class)->abstract()->args([[], service('security.exception_listener'), abstract_arg('LogoutListener'), abstract_arg('FirewallConfig'), service('security.untracked_token_storage')])->set('security.firewall.config', FirewallConfig::class)->abstract()->args([
        abstract_arg('name'),
        abstract_arg('user_checker'),
        abstract_arg('request_matcher'),
        \false,
        // security enabled
        \false,
        // stateless
        null,
        null,
        null,
        null,
        null,
        [],
        // listeners
        null,
        // switch_user
        null,
    ])->set('security.logout_url_generator', LogoutUrlGenerator::class)->args([service('request_stack')->nullOnInvalid(), service('router')->nullOnInvalid(), service('security.token_storage')->nullOnInvalid()])->set('security.route_loader.logout', LogoutRouteLoader::class)->args(['%security.logout_uris%', 'security.logout_uris'])->tag('routing.route_loader')->set('security.user.provider.missing', MissingUserProvider::class)->abstract()->args([abstract_arg('firewall')])->set('security.user.provider.in_memory', InMemoryUserProvider::class)->abstract()->set('security.user.provider.ldap', LdapUserProvider::class)->abstract()->args([abstract_arg('security.ldap.ldap'), abstract_arg('base dn'), abstract_arg('search dn'), abstract_arg('search password'), abstract_arg('default_roles'), abstract_arg('uid key'), abstract_arg('filter'), abstract_arg('password_attribute'), abstract_arg('extra_fields (email etc)')])->set('security.user.provider.chain', ChainUserProvider::class)->abstract()->set('security.http_utils', HttpUtils::class)->args([service('router')->nullOnInvalid(), service('router')->nullOnInvalid()])->alias(HttpUtils::class, 'security.http_utils')->set('security.validator.user_password', UserPasswordValidator::class)->args([service('security.token_storage'), service('security.password_hasher_factory')])->tag('validator.constraint_validator', ['alias' => 'security.validator.user_password'])->set('cache.security_expression_language')->parent('cache.system')->private()->tag('cache.pool')->set('security.cache_warmer.expression', ExpressionCacheWarmer::class)->args([[], service('security.expression_language')])->tag('kernel.cache_warmer')->set('controller.is_granted_attribute_listener', IsGrantedAttributeListener::class)->args([service('security.authorization_checker'), service('security.is_granted_attribute_expression_language')->nullOnInvalid()])->tag('kernel.event_subscriber')->set('security.is_granted_attribute_expression_language', BaseExpressionLanguage::class)->args([service('cache.security_is_granted_attribute_expression_language')->nullOnInvalid()])->set('cache.security_is_granted_attribute_expression_language')->parent('cache.system')->tag('cache.pool');
};
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\DependencyInjection\Loader\Configurator;

use _ContaoManager\Symfony\Bundle\SecurityBundle\RememberMe\FirewallAwareRememberMeHandler;
use _ContaoManager\Symfony\Component\Security\Core\Signature\SignatureHasher;
use _ContaoManager\Symfony\Component\Security\Http\Authenticator\RememberMeAuthenticator;
use _ContaoManager\Symfony\Component\Security\Http\EventListener\CheckRememberMeConditionsListener;
use _ContaoManager\Symfony\Component\Security\Http\EventListener\RememberMeListener;
use _ContaoManager\Symfony\Component\Security\Http\RememberMe\PersistentRememberMeHandler;
use _ContaoManager\Symfony\Component\Security\Http\RememberMe\RememberMeHandlerInterface;
use _ContaoManager\Symfony\Component\Security\Http\RememberMe\ResponseListener;
use _ContaoManager\Symfony\Component\Security\Http\RememberMe\SignatureRememberMeHandler;
return static function (ContainerConfigurator $container) {
    $container->services()->set('security.rememberme.response_listener', ResponseListener::class)->tag('kernel.event_subscriber')->set('security.authenticator.remember_me_signature_hasher', SignatureHasher::class)->args([service('property_accessor'), abstract_arg('signature properties'), '%kernel.secret%', null, null])->set('security.authenticator.signature_remember_me_handler', SignatureRememberMeHandler::class)->abstract()->args([abstract_arg('signature hasher'), abstract_arg('user provider'), service('request_stack'), abstract_arg('options'), service('logger')->nullOnInvalid()])->tag('monolog.logger', ['channel' => 'security'])->set('security.authenticator.persistent_remember_me_handler', PersistentRememberMeHandler::class)->abstract()->args([abstract_arg('token provider'), abstract_arg('user provider'), service('request_stack'), abstract_arg('options'), service('logger')->nullOnInvalid(), abstract_arg('token verifier')])->tag('monolog.logger', ['channel' => 'security'])->set('security.authenticator.firewall_aware_remember_me_handler', FirewallAwareRememberMeHandler::class)->args([service('security.firewall.map'), tagged_locator('security.remember_me_handler', 'firewall'), service('request_stack')])->alias(RememberMeHandlerInterface::class, 'security.authenticator.firewall_aware_remember_me_handler')->set('security.listener.check_remember_me_conditions', CheckRememberMeConditionsListener::class)->abstract()->args([abstract_arg('options'), service('logger')->nullOnInvalid()])->set('security.listener.remember_me', RememberMeListener::class)->abstract()->args([abstract_arg('remember me handler'), service('logger')->nullOnInvalid()])->tag('monolog.logger', ['channel' => 'security'])->set('security.authenticator.remember_me', RememberMeAuthenticator::class)->abstract()->args([abstract_arg('remember me handler'), param('kernel.secret'), service('security.token_storage'), abstract_arg('options'), service('logger')->nullOnInvalid()])->tag('monolog.logger', ['channel' => 'security'])->set('cache.security_token_verifier')->parent('cache.system')->private()->tag('cache.pool');
};
<svg xmlns="http://www.w3.org/2000/svg" data-icon-name="icon-tabler-user" width="24" height="24" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round"  role="img">
    <title>Security</title>
    <path stroke="none" d="M0 0h24v24H0z" fill="none"></path>
    <circle cx="12" cy="7" r="4"></circle>
    <path d="M6 21v-2a4 4 0 0 1 4 -4h4a4 4 0 0 1 4 4v2"></path>
</svg>
{% extends '@WebProfiler/Profiler/layout.html.twig' %}

{% block page_title 'Security' %}

{% block head %}
    {{ parent() }}

    <style>
        #collector-content .decision-log .voter_result td {
            border-top-width: 1px;
            border-bottom-width: 0;
            padding-bottom: 0;
        }

        #collector-content .decision-log .voter_details td {
            border-top-width: 0;
            border-bottom-width: 1px;
            padding-bottom: 0;
        }

        #collector-content .decision-log .voter_details table {
            border: 0;
            margin: 0;
            box-shadow: unset;
        }

        #collector-content .decision-log .voter_details table td {
            border: 0;
            padding: 0 0 8px 0;
        }

        #collector-content .authenticators .badge {
            color: var(--white);
            display: inline-block;
            text-align: center;
        }
        #collector-content .authenticators .badge.badge-resolved {
            background-color: var(--green-500);
        }
        #collector-content .authenticators .badge.badge-not_resolved {
            background-color: var(--yellow-500);
        }

        #collector-content .authenticators svg[data-icon-name="icon-tabler-check"] {
            color: var(--green-500);
        }
        #collector-content .authenticators svg[data-icon-name="icon-tabler-x"] {
            color: var(--red-500);
        }
    </style>
{% endblock %}

{% block toolbar %}
    {% if collector.firewall %}
        {% set icon %}
            {{ source('@Security/Collector/icon.svg') }}
            <span class="sf-toolbar-value">{{ collector.user|default('n/a') }}</span>
        {% endset %}

        {% set text %}
            {% if collector.impersonated %}
                <div class="sf-toolbar-info-group">
                    <div class="sf-toolbar-info-piece">
                        <b>Impersonator</b>
                        <span>{{ collector.impersonatorUser }}</span>
                    </div>
                </div>
            {% endif %}

            <div class="sf-toolbar-info-group">
                {% if collector.enabled %}
                    {% if collector.token %}
                        <div class="sf-toolbar-info-piece">
                            <b>Logged in as</b>
                            <span>{{ collector.user }}</span>
                        </div>

                        <div class="sf-toolbar-info-piece">
                            <b>Authenticated</b>
                            <span class="sf-toolbar-status sf-toolbar-status-{{ collector.authenticated ? 'green' : 'yellow' }}">{{ collector.authenticated ? 'Yes' : 'No' }}</span>
                        </div>

                        <div class="sf-toolbar-info-piece">
                            <b>Roles</b>
                            <span>
                                {% set remainingRoles = collector.roles|slice(1) %}
                                {{ collector.roles|first }}
                                {% if remainingRoles is not empty %}
                                    +
                                    <abbr title="{{ remainingRoles|join(', ') }}">
                                        {{ remainingRoles|length }} more
                                    </abbr>
                                {% endif %}
                            </span>
                        </div>

                        {% if collector.supportsRoleHierarchy %}
                            <div class="sf-toolbar-info-piece">
                                <b>Inherited Roles</b>
                                <span>
                                    {% if collector.inheritedRoles is empty %}
                                        none
                                    {% else %}
                                        {% set remainingRoles = collector.inheritedRoles|slice(1) %}
                                        {{ collector.inheritedRoles|first }}
                                        {% if remainingRoles is not empty %}
                                            +
                                            <abbr title="{{ remainingRoles|join(', ') }}">
                                                {{ remainingRoles|length }} more
                                            </abbr>
                                        {% endif %}
                                    {% endif %}
                                </span>
                            </div>
                        {% endif %}

                        <div class="sf-toolbar-info-piece">
                            <b>Token class</b>
                            <span>{{ collector.tokenClass|abbr_class }}</span>
                        </div>
                    {% else %}
                        <div class="sf-toolbar-info-piece">
                            <b>Authenticated</b>
                            <span class="sf-toolbar-status sf-toolbar-status-yellow">No</span>
                        </div>
                    {% endif %}

                    {% if collector.firewall %}
                        <div class="sf-toolbar-info-piece">
                            <b>Firewall name</b>
                            <span>{{ collector.firewall.name }}</span>
                        </div>
                    {% endif %}

                    {% if collector.token and collector.logoutUrl %}
                        <div class="sf-toolbar-info-piece">
                            <b>Actions</b>
                            <span>
                                <a href="{{ collector.logoutUrl }}">Logout</a>
                                {% if collector.impersonated and collector.impersonationExitPath %}
                                    | <a href="{{ collector.impersonationExitPath }}">Exit impersonation</a>
                                {% endif %}
                            </span>
                        </div>
                    {% endif %}
                {% else %}
                    <div class="sf-toolbar-info-piece">
                        <span>The security is disabled.</span>
                    </div>
                {% endif %}
            </div>
        {% endset %}

        {{ include('@WebProfiler/Profiler/toolbar_item.html.twig', { link: profiler_url }) }}
    {% endif %}
{% endblock %}

{% block menu %}
    <span class="label {{ not collector.firewall or not collector.token ? 'disabled' }}">
        <span class="icon">{{ source('@Security/Collector/icon.svg') }}</span>
        <strong>Security</strong>
    </span>
{% endblock %}

{% block panel %}
    <h2>Security</h2>
    {% if collector.enabled %}
        <div class="sf-tabs">
            <div class="tab {{ collector.token is empty ? 'disabled' }}">
                <h3 class="tab-title">Token</h3>

                <div class="tab-content">
                    {% if collector.token %}
                        <div class="metrics">
                            <div class="metric">
                                <span class="value">{{ collector.user }}</span>
                                <span class="label">Username</span>
                            </div>

                            <div class="metric">
                                <span class="value">{{ source('@WebProfiler/Icon/' ~ (collector.authenticated ? 'yes' : 'no') ~ '.svg') }}</span>
                                <span class="label">Authenticated</span>
                            </div>
                        </div>

                        <table>
                            <thead>
                                <tr>
                                    <th scope="col" class="key">Property</th>
                                    <th scope="col">Value</th>
                                </tr>
                            </thead>
                            <tbody>
                                <tr>
                                    <th>Roles</th>
                                    <td>
                                        {{ collector.roles is empty ? 'none' : profiler_dump(collector.roles, maxDepth=1) }}

                                        {% if not collector.authenticated and collector.roles is empty %}
                                            <p class="help">User is not authenticated probably because they have no roles.</p>
                                        {% endif %}
                                    </td>
                                </tr>

                                {% if collector.supportsRoleHierarchy %}
                                <tr>
                                    <th>Inherited Roles</th>
                                    <td>{{ collector.inheritedRoles is empty ? 'none' : profiler_dump(collector.inheritedRoles, maxDepth=1) }}</td>
                                </tr>
                                {% endif %}

                                {% if collector.token %}
                                <tr>
                                    <th>Token</th>
                                    <td>{{ profiler_dump(collector.token) }}</td>
                                </tr>
                                {% endif %}
                            </tbody>
                        </table>
                    {% elseif collector.enabled %}
                        <div class="empty">
                            <p>There is no security token.</p>
                        </div>
                    {% endif %}
                </div>
            </div>

            <div class="tab {{ (not collector.firewall or collector.firewall.security_enabled is empty) ? 'disabled' }}">
                <h3 class="tab-title">Firewall</h3>
                <div class="tab-content">
                    {% if collector.firewall %}
                        <div class="metrics">
                            <div class="metric">
                                <span class="value">{{ collector.firewall.name }}</span>
                                <span class="label">Name</span>
                            </div>
                            <div class="metric">
                                <span class="value">{{ source('@WebProfiler/Icon/' ~ (collector.firewall.security_enabled ? 'yes' : 'no') ~ '.svg') }}</span>
                                <span class="label">Security enabled</span>
                            </div>
                            <div class="metric">
                                <span class="value">{{ source('@WebProfiler/Icon/' ~ (collector.firewall.stateless ? 'yes' : 'no') ~ '.svg') }}</span>
                                <span class="label">Stateless</span>
                            </div>
                        </div>

                        {% if collector.firewall.security_enabled %}
                            <h4>Configuration</h4>
                            <table>
                                <thead>
                                    <tr>
                                        <th scope="col" class="key">Key</th>
                                        <th scope="col">Value</th>
                                    </tr>
                                </thead>
                                <tbody>
                                    <tr>
                                        <th>provider</th>
                                        <td>{{ collector.firewall.provider ?: '(none)' }}</td>
                                    </tr>
                                    <tr>
                                        <th>context</th>
                                        <td>{{ collector.firewall.context ?: '(none)' }}</td>
                                    </tr>
                                    <tr>
                                        <th>entry_point</th>
                                        <td>{{ collector.firewall.entry_point ?: '(none)' }}</td>
                                    </tr>
                                    <tr>
                                        <th>user_checker</th>
                                        <td>{{ collector.firewall.user_checker ?: '(none)' }}</td>
                                    </tr>
                                    <tr>
                                        <th>access_denied_handler</th>
                                        <td>{{ collector.firewall.access_denied_handler ?: '(none)' }}</td>
                                    </tr>
                                    <tr>
                                        <th>access_denied_url</th>
                                        <td>{{ collector.firewall.access_denied_url ?: '(none)' }}</td>
                                    </tr>
                                    <tr>
                                        <th>authenticators</th>
                                        <td>{{ collector.firewall.authenticators is empty ? '(none)' : profiler_dump(collector.firewall.authenticators, maxDepth=1) }}</td>
                                    </tr>
                                </tbody>
                            </table>
                        {% endif %}
                    {% endif %}
                </div>
            </div>

            <div class="tab {{ collector.listeners|default([]) is empty ? 'disabled' }}">
                <h3 class="tab-title">Listeners</h3>
                <div class="tab-content">
                    {% if collector.listeners|default([]) is empty %}
                        <div class="empty">
                            <p>No security listeners have been recorded. Check that debugging is enabled in the kernel.</p>
                        </div>
                    {% else %}
                        <table>
                            <thead>
                            <tr>
                                <th>Listener</th>
                                <th>Duration</th>
                                <th>Response</th>
                            </tr>
                            </thead>

                            {% set previous_event = (collector.listeners|first) %}
                            {% for listener in collector.listeners %}
                                {% if loop.first or listener != previous_event %}
                                    {% if not loop.first %}
                                        </tbody>
                                    {% endif %}
                                    <tbody>
                                    {% set previous_event = listener %}
                                {% endif %}

                                <tr>
                                    <td class="font-normal">{{ profiler_dump(listener.stub) }}</td>
                                    <td class="no-wrap">{{ '%0.2f'|format(listener.time * 1000) }} ms</td>
                                    <td class="font-normal">{{ listener.response ? profiler_dump(listener.response) : '(none)' }}</td>
                                </tr>

                                {% if loop.last %}
                                    </tbody>
                                {% endif %}
                            {% endfor %}
                        </table>
                    {% endif %}
                </div>
            </div>

            <div class="tab {{ collector.authenticators|default([]) is empty ? 'disabled' }}">
                <h3 class="tab-title">Authenticators</h3>
                <div class="tab-content">
                    {% if collector.authenticators|default([]) is not empty %}
                        <table class="authenticators">
                            <thead>
                            <tr>
                                <th>Authenticator</th>
                                <th>Supports</th>
                                <th>Authenticated</th>
                                <th>Duration</th>
                                <th>Passport</th>
                                <th>Badges</th>
                            </tr>
                            </thead>

                            {% set previous_event = (collector.listeners|first) %}
                            {% for authenticator in collector.authenticators %}
                                {% if loop.first or authenticator != previous_event %}
                                    {% if not loop.first %}
                                        </tbody>
                                    {% endif %}

                                    <tbody>
                                    {% set previous_event = authenticator %}
                                {% endif %}

                                <tr>
                                    <td class="font-normal">{{ profiler_dump(authenticator.stub) }}</td>
                                    <td class="no-wrap">{{ source('@WebProfiler/Icon/' ~ (authenticator.supports ? 'yes' : 'no') ~ '.svg') }}</td>
                                    <td class="no-wrap">{{ authenticator.authenticated is not null ? source('@WebProfiler/Icon/' ~ (authenticator.authenticated ? 'yes' : 'no') ~ '.svg') : '' }}</td>
                                    <td class="no-wrap">{{ '%0.2f'|format(authenticator.duration * 1000) }} ms</td>
                                    <td class="font-normal">{{ authenticator.passport ? profiler_dump(authenticator.passport) : '(none)' }}</td>
                                    <td class="font-normal">
                                        {% for badge in authenticator.badges ?? [] %}
                                            <span class="badge badge-{{ badge.resolved ? 'resolved' : 'not_resolved' }}">
                                            {{ badge.stub|abbr_class }}
                                            </span>
                                        {% else %}
                                            (none)
                                        {% endfor %}
                                    </td>
                                </tr>

                                {% if loop.last %}
                                    </tbody>
                                {% endif %}
                            {% endfor %}
                        </table>
                    {% else %}
                        <div class="empty">
                            <p>No authenticators have been recorded. Check previous profiles on your authentication endpoint.</p>
                        </div>
                    {% endif %}
                </div>
            </div>

            <div class="tab {{ collector.accessDecisionLog|default([]) is empty ? 'disabled' }}">
                <h3 class="tab-title">Access Decision</h3>
                <div class="tab-content">
                    {% if collector.voters|default([]) is not empty %}
                        <div class="metrics">
                            <div class="metric">
                                <span class="value">{{ collector.voterStrategy|default('unknown') }}</span>
                                <span class="label">Strategy</span>
                            </div>
                        </div>

                        <table class="voters">
                            <thead>
                                <tr>
                                    <th>#</th>
                                    <th>Voter class</th>
                                </tr>
                            </thead>

                            <tbody>
                                {% for voter in collector.voters %}
                                    <tr>
                                        <td class="font-normal text-small text-muted nowrap">{{ loop.index }}</td>
                                        <td class="font-normal">{{ profiler_dump(voter) }}</td>
                                    </tr>
                                {% endfor %}
                            </tbody>
                        </table>
                    {% endif %}
                    {% if collector.accessDecisionLog|default([]) is not empty %}
                        <h2>Access decision log</h2>

                        <table class="decision-log">
                            <col style="width: 30px">
                            <col style="width: 120px">
                            <col style="width: 25%">
                            <col style="width: 60%">

                            <thead>
                                <tr>
                                    <th>#</th>
                                    <th>Result</th>
                                    <th>Attributes</th>
                                    <th>Object</th>
                                </tr>
                            </thead>

                            <tbody>
                                {% for decision in collector.accessDecisionLog %}
                                    <tr class="voter_result">
                                        <td class="font-normal text-small text-muted nowrap">{{ loop.index }}</td>
                                        <td class="font-normal">
                                            {{ decision.result
                                                ? '<span class="label status-success same-width">GRANTED</span>'
                                                : '<span class="label status-error same-width">DENIED</span>'
                                            }}
                                        </td>
                                        <td>
                                            {% if decision.attributes|length == 1 %}
                                                {% set attribute = decision.attributes|first %}
                                                {% if attribute.expression is defined %}
                                                    Expression: <pre><code>{{ attribute.expression }}</code></pre>
                                                {% elseif attribute.type == 'string' %}
                                                    {{ attribute }}
                                                {% else %}
                                                     {{ profiler_dump(attribute) }}
                                                {% endif %}
                                            {% else %}
                                                {{ profiler_dump(decision.attributes) }}
                                            {% endif %}
                                        </td>
                                        <td>{{ profiler_dump(decision.seek('object')) }}</td>
                                    </tr>
                                    <tr class="voter_details">
                                        <td></td>
                                        <td colspan="3">
                                        {% if decision.voter_details is not empty %}
                                            {% set voter_details_id = 'voter-details-' ~ loop.index %}
                                            <div id="{{ voter_details_id }}" class="sf-toggle-content sf-toggle-hidden">
                                                <table>
                                                   <tbody>
                                                    {% for voter_detail in decision.voter_details %}
                                                        <tr>
                                                            <td class="font-normal">{{ profiler_dump(voter_detail['class']) }}</td>
                                                            {% if collector.voterStrategy == 'unanimous' %}
                                                            <td class="font-normal text-small">attribute {{ voter_detail['attributes'][0] }}</td>
                                                            {% endif %}
                                                            <td class="font-normal text-small">
                                                                {% if voter_detail['vote'] == constant('Symfony\\Component\\Security\\Core\\Authorization\\Voter\\VoterInterface::ACCESS_GRANTED') %}
                                                                    ACCESS GRANTED
                                                                {% elseif voter_detail['vote'] == constant('Symfony\\Component\\Security\\Core\\Authorization\\Voter\\VoterInterface::ACCESS_ABSTAIN') %}
                                                                    ACCESS ABSTAIN
                                                                {% elseif voter_detail['vote'] == constant('Symfony\\Component\\Security\\Core\\Authorization\\Voter\\VoterInterface::ACCESS_DENIED') %}
                                                                    ACCESS DENIED
                                                                {% else %}
                                                                    unknown ({{ voter_detail['vote'] }})
                                                                {% endif %}
                                                            </td>
                                                        </tr>
                                                    {% endfor %}
                                                    </tbody>
                                                </table>
                                            </div>
                                            <a class="btn btn-link text-small sf-toggle" data-toggle-selector="#{{ voter_details_id }}" data-toggle-alt-content="Hide voter details">Show voter details</a>
                                        {% endif %}
                                        </td>
                                    </tr>
                                {% endfor %}
                            </tbody>
                        </table>
                    </div>
                {% endif %}
            </div>
        </div>
    {% endif %}
{% endblock %}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Bundle\SecurityBundle\CacheWarmer;

use _ContaoManager\Symfony\Component\ExpressionLanguage\Expression;
use _ContaoManager\Symfony\Component\HttpKernel\CacheWarmer\CacheWarmerInterface;
use _ContaoManager\Symfony\Component\Security\Core\Authorization\ExpressionLanguage;
class ExpressionCacheWarmer implements CacheWarmerInterface
{
    private iterable $expressions;
    private ExpressionLanguage $expressionLanguage;
    /**
     * @param iterable<mixed, Expression|string> $expressions
     */
    public function __construct(iterable $expressions, ExpressionLanguage $expressionLanguage)
    {
        $this->expressions = $expressions;
        $this->expressionLanguage = $expressionLanguage;
    }
    public function isOptional(): bool
    {
        return \true;
    }
    /**
     * @param string|null $buildDir
     */
    public function warmUp(string $cacheDir): array
    {
        foreach ($this->expressions as $expression) {
            $this->expressionLanguage->parse($expression, ['token', 'user', 'object', 'subject', 'role_names', 'request', 'trust_resolver']);
        }
        return [];
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Bundle\SecurityBundle;

use _ContaoManager\Symfony\Bundle\SecurityBundle\DependencyInjection\Compiler\AddExpressionLanguageProvidersPass;
use _ContaoManager\Symfony\Bundle\SecurityBundle\DependencyInjection\Compiler\AddSecurityVotersPass;
use _ContaoManager\Symfony\Bundle\SecurityBundle\DependencyInjection\Compiler\AddSessionDomainConstraintPass;
use _ContaoManager\Symfony\Bundle\SecurityBundle\DependencyInjection\Compiler\CleanRememberMeVerifierPass;
use _ContaoManager\Symfony\Bundle\SecurityBundle\DependencyInjection\Compiler\MakeFirewallsEventDispatcherTraceablePass;
use _ContaoManager\Symfony\Bundle\SecurityBundle\DependencyInjection\Compiler\RegisterCsrfFeaturesPass;
use _ContaoManager\Symfony\Bundle\SecurityBundle\DependencyInjection\Compiler\RegisterEntryPointPass;
use _ContaoManager\Symfony\Bundle\SecurityBundle\DependencyInjection\Compiler\RegisterGlobalSecurityEventListenersPass;
use _ContaoManager\Symfony\Bundle\SecurityBundle\DependencyInjection\Compiler\RegisterLdapLocatorPass;
use _ContaoManager\Symfony\Bundle\SecurityBundle\DependencyInjection\Compiler\RegisterTokenUsageTrackingPass;
use _ContaoManager\Symfony\Bundle\SecurityBundle\DependencyInjection\Compiler\ReplaceDecoratedRememberMeHandlerPass;
use _ContaoManager\Symfony\Bundle\SecurityBundle\DependencyInjection\Compiler\SortFirewallListenersPass;
use _ContaoManager\Symfony\Bundle\SecurityBundle\DependencyInjection\Security\AccessToken\OidcTokenHandlerFactory;
use _ContaoManager\Symfony\Bundle\SecurityBundle\DependencyInjection\Security\AccessToken\OidcUserInfoTokenHandlerFactory;
use _ContaoManager\Symfony\Bundle\SecurityBundle\DependencyInjection\Security\AccessToken\ServiceTokenHandlerFactory;
use _ContaoManager\Symfony\Bundle\SecurityBundle\DependencyInjection\Security\Factory\AccessTokenFactory;
use _ContaoManager\Symfony\Bundle\SecurityBundle\DependencyInjection\Security\Factory\CustomAuthenticatorFactory;
use _ContaoManager\Symfony\Bundle\SecurityBundle\DependencyInjection\Security\Factory\FormLoginFactory;
use _ContaoManager\Symfony\Bundle\SecurityBundle\DependencyInjection\Security\Factory\FormLoginLdapFactory;
use _ContaoManager\Symfony\Bundle\SecurityBundle\DependencyInjection\Security\Factory\HttpBasicFactory;
use _ContaoManager\Symfony\Bundle\SecurityBundle\DependencyInjection\Security\Factory\HttpBasicLdapFactory;
use _ContaoManager\Symfony\Bundle\SecurityBundle\DependencyInjection\Security\Factory\JsonLoginFactory;
use _ContaoManager\Symfony\Bundle\SecurityBundle\DependencyInjection\Security\Factory\JsonLoginLdapFactory;
use _ContaoManager\Symfony\Bundle\SecurityBundle\DependencyInjection\Security\Factory\LoginLinkFactory;
use _ContaoManager\Symfony\Bundle\SecurityBundle\DependencyInjection\Security\Factory\LoginThrottlingFactory;
use _ContaoManager\Symfony\Bundle\SecurityBundle\DependencyInjection\Security\Factory\RememberMeFactory;
use _ContaoManager\Symfony\Bundle\SecurityBundle\DependencyInjection\Security\Factory\RemoteUserFactory;
use _ContaoManager\Symfony\Bundle\SecurityBundle\DependencyInjection\Security\Factory\X509Factory;
use _ContaoManager\Symfony\Bundle\SecurityBundle\DependencyInjection\Security\UserProvider\InMemoryFactory;
use _ContaoManager\Symfony\Bundle\SecurityBundle\DependencyInjection\Security\UserProvider\LdapFactory;
use _ContaoManager\Symfony\Bundle\SecurityBundle\DependencyInjection\SecurityExtension;
use _ContaoManager\Symfony\Component\DependencyInjection\Compiler\PassConfig;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerBuilder;
use _ContaoManager\Symfony\Component\EventDispatcher\DependencyInjection\AddEventAliasesPass;
use _ContaoManager\Symfony\Component\HttpKernel\Bundle\Bundle;
use _ContaoManager\Symfony\Component\Security\Core\AuthenticationEvents;
use _ContaoManager\Symfony\Component\Security\Http\SecurityEvents;
/**
 * Bundle.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class SecurityBundle extends Bundle
{
    /**
     * @return void
     */
    public function build(ContainerBuilder $container)
    {
        parent::build($container);
        /** @var SecurityExtension $extension */
        $extension = $container->getExtension('security');
        $extension->addAuthenticatorFactory(new FormLoginFactory());
        $extension->addAuthenticatorFactory(new FormLoginLdapFactory());
        $extension->addAuthenticatorFactory(new JsonLoginFactory());
        $extension->addAuthenticatorFactory(new JsonLoginLdapFactory());
        $extension->addAuthenticatorFactory(new HttpBasicFactory());
        $extension->addAuthenticatorFactory(new HttpBasicLdapFactory());
        $extension->addAuthenticatorFactory(new RememberMeFactory());
        $extension->addAuthenticatorFactory(new X509Factory());
        $extension->addAuthenticatorFactory(new RemoteUserFactory());
        $extension->addAuthenticatorFactory(new CustomAuthenticatorFactory());
        $extension->addAuthenticatorFactory(new LoginThrottlingFactory());
        $extension->addAuthenticatorFactory(new LoginLinkFactory());
        $extension->addAuthenticatorFactory(new AccessTokenFactory([new ServiceTokenHandlerFactory(), new OidcUserInfoTokenHandlerFactory(), new OidcTokenHandlerFactory()]));
        $extension->addUserProviderFactory(new InMemoryFactory());
        $extension->addUserProviderFactory(new LdapFactory());
        $container->addCompilerPass(new AddExpressionLanguageProvidersPass());
        $container->addCompilerPass(new AddSecurityVotersPass());
        $container->addCompilerPass(new AddSessionDomainConstraintPass(), PassConfig::TYPE_BEFORE_REMOVING);
        $container->addCompilerPass(new CleanRememberMeVerifierPass());
        $container->addCompilerPass(new RegisterCsrfFeaturesPass());
        $container->addCompilerPass(new RegisterTokenUsageTrackingPass(), PassConfig::TYPE_BEFORE_OPTIMIZATION, 200);
        $container->addCompilerPass(new RegisterLdapLocatorPass());
        $container->addCompilerPass(new RegisterEntryPointPass());
        // must be registered after RegisterListenersPass (in the FrameworkBundle)
        $container->addCompilerPass(new RegisterGlobalSecurityEventListenersPass(), PassConfig::TYPE_BEFORE_REMOVING, -200);
        // execute after ResolveChildDefinitionsPass optimization pass, to ensure class names are set
        $container->addCompilerPass(new SortFirewallListenersPass(), PassConfig::TYPE_BEFORE_REMOVING);
        $container->addCompilerPass(new ReplaceDecoratedRememberMeHandlerPass(), PassConfig::TYPE_OPTIMIZE);
        $container->addCompilerPass(new AddEventAliasesPass(array_merge(AuthenticationEvents::ALIASES, SecurityEvents::ALIASES)));
        // must be registered before DecoratorServicePass
        $container->addCompilerPass(new MakeFirewallsEventDispatcherTraceablePass(), PassConfig::TYPE_OPTIMIZE, 10);
    }
}
SecurityBundle
==============

SecurityBundle provides a tight integration of the Security component into the
Symfony full-stack framework.

Resources
---------

 * [Contributing](https://symfony.com/doc/current/contributing/index.html)
 * [Report issues](https://github.com/symfony/symfony/issues) and
   [send Pull Requests](https://github.com/symfony/symfony/pulls)
   in the [main Symfony repository](https://github.com/symfony/symfony)
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Bundle\SecurityBundle\RememberMe;

use _ContaoManager\Symfony\Component\Security\Core\User\UserInterface;
use _ContaoManager\Symfony\Component\Security\Http\RememberMe\RememberMeDetails;
use _ContaoManager\Symfony\Component\Security\Http\RememberMe\RememberMeHandlerInterface;
/**
 * Used as a "workaround" for tagging aliases in the RememberMeFactory.
 *
 * @author Wouter de Jong <wouter@wouterj.nl>
 *
 * @internal
 */
final class DecoratedRememberMeHandler implements RememberMeHandlerInterface
{
    private RememberMeHandlerInterface $handler;
    public function __construct(RememberMeHandlerInterface $handler)
    {
        $this->handler = $handler;
    }
    public function createRememberMeCookie(UserInterface $user): void
    {
        $this->handler->createRememberMeCookie($user);
    }
    public function consumeRememberMeCookie(RememberMeDetails $rememberMeDetails): UserInterface
    {
        return $this->handler->consumeRememberMeCookie($rememberMeDetails);
    }
    public function clearRememberMeCookie(): void
    {
        $this->handler->clearRememberMeCookie();
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Bundle\SecurityBundle\RememberMe;

use _ContaoManager\Psr\Container\ContainerInterface;
use _ContaoManager\Symfony\Bundle\SecurityBundle\Security\FirewallAwareTrait;
use _ContaoManager\Symfony\Bundle\SecurityBundle\Security\FirewallMap;
use _ContaoManager\Symfony\Component\HttpFoundation\RequestStack;
use _ContaoManager\Symfony\Component\Security\Core\User\UserInterface;
use _ContaoManager\Symfony\Component\Security\Http\RememberMe\RememberMeDetails;
use _ContaoManager\Symfony\Component\Security\Http\RememberMe\RememberMeHandlerInterface;
/**
 * Decorates {@see RememberMeHandlerInterface} for the current firewall.
 *
 * @author Wouter de Jong <wouter@wouterj.nl>
 */
final class FirewallAwareRememberMeHandler implements RememberMeHandlerInterface
{
    use FirewallAwareTrait;
    private const FIREWALL_OPTION = 'remember_me';
    public function __construct(FirewallMap $firewallMap, ContainerInterface $rememberMeHandlerLocator, RequestStack $requestStack)
    {
        $this->firewallMap = $firewallMap;
        $this->locator = $rememberMeHandlerLocator;
        $this->requestStack = $requestStack;
    }
    public function createRememberMeCookie(UserInterface $user): void
    {
        $this->getForFirewall()->createRememberMeCookie($user);
    }
    public function consumeRememberMeCookie(RememberMeDetails $rememberMeDetails): UserInterface
    {
        return $this->getForFirewall()->consumeRememberMeCookie($rememberMeDetails);
    }
    public function clearRememberMeCookie(): void
    {
        $this->getForFirewall()->clearRememberMeCookie();
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Bundle\SecurityBundle\Command;

use _ContaoManager\Psr\Container\ContainerInterface;
use _ContaoManager\Symfony\Bundle\SecurityBundle\Security\FirewallContext;
use _ContaoManager\Symfony\Bundle\SecurityBundle\Security\LazyFirewallContext;
use _ContaoManager\Symfony\Component\Console\Attribute\AsCommand;
use _ContaoManager\Symfony\Component\Console\Command\Command;
use _ContaoManager\Symfony\Component\Console\Completion\CompletionInput;
use _ContaoManager\Symfony\Component\Console\Completion\CompletionSuggestions;
use _ContaoManager\Symfony\Component\Console\Input\InputArgument;
use _ContaoManager\Symfony\Component\Console\Input\InputInterface;
use _ContaoManager\Symfony\Component\Console\Input\InputOption;
use _ContaoManager\Symfony\Component\Console\Output\OutputInterface;
use _ContaoManager\Symfony\Component\Console\Style\SymfonyStyle;
use _ContaoManager\Symfony\Component\EventDispatcher\EventDispatcherInterface;
use _ContaoManager\Symfony\Component\Security\Http\Authenticator\AuthenticatorInterface;
/**
 * @author Timo Bakx <timobakx@gmail.com>
 */
#[AsCommand(name: 'debug:firewall', description: 'Display information about your security firewall(s)')]
final class DebugFirewallCommand extends Command
{
    private array $firewallNames;
    private ContainerInterface $contexts;
    private ContainerInterface $eventDispatchers;
    private array $authenticators;
    /**
     * @param string[]                   $firewallNames
     * @param AuthenticatorInterface[][] $authenticators
     */
    public function __construct(array $firewallNames, ContainerInterface $contexts, ContainerInterface $eventDispatchers, array $authenticators)
    {
        $this->firewallNames = $firewallNames;
        $this->contexts = $contexts;
        $this->eventDispatchers = $eventDispatchers;
        $this->authenticators = $authenticators;
        parent::__construct();
    }
    protected function configure(): void
    {
        $exampleName = $this->getExampleName();
        $this->setHelp(<<<EOF
The <info>%command.name%</info> command displays the firewalls that are configured
in your application:

  <info>php %command.full_name%</info>

You can pass a firewall name to display more detailed information about
a specific firewall:

  <info>php %command.full_name% {$exampleName}</info>

To include all events and event listeners for a specific firewall, use the
<info>events</info> option:

  <info>php %command.full_name% --events {$exampleName}</info>

EOF
)->setDefinition([new InputArgument('name', InputArgument::OPTIONAL, \sprintf('A firewall name (for example "%s")', $exampleName)), new InputOption('events', null, InputOption::VALUE_NONE, 'Include a list of event listeners (only available in combination with the "name" argument)')]);
    }
    protected function execute(InputInterface $input, OutputInterface $output): int
    {
        $io = new SymfonyStyle($input, $output);
        $name = $input->getArgument('name');
        if (null === $name) {
            $this->displayFirewallList($io);
            return 0;
        }
        $serviceId = \sprintf('security.firewall.map.context.%s', $name);
        if (!$this->contexts->has($serviceId)) {
            $io->error(\sprintf('Firewall %s was not found. Available firewalls are: %s', $name, implode(', ', $this->firewallNames)));
            return 1;
        }
        /** @var FirewallContext $context */
        $context = $this->contexts->get($serviceId);
        $io->title(\sprintf('Firewall "%s"', $name));
        $this->displayFirewallSummary($name, $context, $io);
        $this->displaySwitchUser($context, $io);
        if ($input->getOption('events')) {
            $this->displayEventListeners($name, $context, $io);
        }
        $this->displayAuthenticators($name, $io);
        return 0;
    }
    protected function displayFirewallList(SymfonyStyle $io): void
    {
        $io->title('Firewalls');
        $io->text('The following firewalls are defined:');
        $io->listing($this->firewallNames);
        $io->comment(\sprintf('To view details of a specific firewall, re-run this command with a firewall name. (e.g. <comment>debug:firewall %s</comment>)', $this->getExampleName()));
    }
    protected function displayFirewallSummary(string $name, FirewallContext $context, SymfonyStyle $io): void
    {
        if (null === $context->getConfig()) {
            return;
        }
        $rows = [['Name', $name], ['Context', $context->getConfig()->getContext()], ['Lazy', $context instanceof LazyFirewallContext ? 'Yes' : 'No'], ['Stateless', $context->getConfig()->isStateless() ? 'Yes' : 'No'], ['User Checker', $context->getConfig()->getUserChecker()], ['Provider', $context->getConfig()->getProvider()], ['Entry Point', $context->getConfig()->getEntryPoint()], ['Access Denied URL', $context->getConfig()->getAccessDeniedUrl()], ['Access Denied Handler', $context->getConfig()->getAccessDeniedHandler()]];
        $io->table(['Option', 'Value'], $rows);
    }
    private function displaySwitchUser(FirewallContext $context, SymfonyStyle $io): void
    {
        if (null === ($config = $context->getConfig()) || null === $switchUser = $config->getSwitchUser()) {
            return;
        }
        $io->section('User switching');
        $io->table(['Option', 'Value'], [['Parameter', $switchUser['parameter'] ?? ''], ['Provider', $switchUser['provider'] ?? $config->getProvider()], ['User Role', $switchUser['role'] ?? '']]);
    }
    protected function displayEventListeners(string $name, FirewallContext $context, SymfonyStyle $io): void
    {
        $io->title(\sprintf('Event listeners for firewall "%s"', $name));
        $dispatcherId = \sprintf('security.event_dispatcher.%s', $name);
        if (!$this->eventDispatchers->has($dispatcherId)) {
            $io->text('No event dispatcher has been registered for this firewall.');
            return;
        }
        /** @var EventDispatcherInterface $dispatcher */
        $dispatcher = $this->eventDispatchers->get($dispatcherId);
        foreach ($dispatcher->getListeners() as $event => $listeners) {
            $io->section(\sprintf('"%s" event', $event));
            $rows = [];
            foreach ($listeners as $order => $listener) {
                $rows[] = [\sprintf('#%d', $order + 1), $this->formatCallable($listener), $dispatcher->getListenerPriority($event, $listener)];
            }
            $io->table(['Order', 'Callable', 'Priority'], $rows);
        }
    }
    private function displayAuthenticators(string $name, SymfonyStyle $io): void
    {
        $io->title(\sprintf('Authenticators for firewall "%s"', $name));
        $authenticators = $this->authenticators[$name] ?? [];
        if (0 === \count($authenticators)) {
            $io->text('No authenticators have been registered for this firewall.');
            return;
        }
        $io->table(['Classname'], array_map(fn($authenticator) => [$authenticator::class], $authenticators));
    }
    private function formatCallable(mixed $callable): string
    {
        if (\is_array($callable)) {
            if (\is_object($callable[0])) {
                return \sprintf('%s::%s()', $callable[0]::class, $callable[1]);
            }
            return \sprintf('%s::%s()', $callable[0], $callable[1]);
        }
        if (\is_string($callable)) {
            return \sprintf('%s()', $callable);
        }
        if ($callable instanceof \Closure) {
            $r = new \ReflectionFunction($callable);
            if (str_contains($r->name, '{closure')) {
                return 'Closure()';
            }
            if ($class = \PHP_VERSION_ID >= 80111 ? $r->getClosureCalledClass() : $r->getClosureScopeClass()) {
                return \sprintf('%s::%s()', $class->name, $r->name);
            }
            return $r->name . '()';
        }
        if (method_exists($callable, '__invoke')) {
            return \sprintf('%s::__invoke()', $callable::class);
        }
        throw new \InvalidArgumentException('Callable is not describable.');
    }
    private function getExampleName(): string
    {
        $name = 'main';
        if (!\in_array($name, $this->firewallNames, \true)) {
            $name = reset($this->firewallNames);
        }
        return $name;
    }
    public function complete(CompletionInput $input, CompletionSuggestions $suggestions): void
    {
        if ($input->mustSuggestArgumentValuesFor('name')) {
            $suggestions->suggestValues($this->firewallNames);
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Bundle\SecurityBundle\Routing;

use _ContaoManager\Symfony\Component\DependencyInjection\Config\ContainerParametersResource;
use _ContaoManager\Symfony\Component\Routing\Route;
use _ContaoManager\Symfony\Component\Routing\RouteCollection;
final class LogoutRouteLoader
{
    /**
     * @param array<string, string> $logoutUris    Logout URIs indexed by the corresponding firewall name
     * @param string                $parameterName Name of the container parameter containing {@see $logoutUris} value
     */
    public function __construct(private readonly array $logoutUris, private readonly string $parameterName)
    {
    }
    public function __invoke(): RouteCollection
    {
        $collection = new RouteCollection();
        $collection->addResource(new ContainerParametersResource([$this->parameterName => $this->logoutUris]));
        $routeNames = [];
        foreach ($this->logoutUris as $firewallName => $logoutPath) {
            $routeName = '_logout_' . $firewallName;
            if (isset($routeNames[$logoutPath])) {
                $collection->addAlias($routeName, $routeNames[$logoutPath]);
            } else {
                $routeNames[$logoutPath] = $routeName;
                $collection->add($routeName, new Route($logoutPath));
            }
        }
        return $collection;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Bundle\SecurityBundle;

use _ContaoManager\Psr\Container\ContainerInterface;
use _ContaoManager\Symfony\Bundle\SecurityBundle\Security\FirewallConfig;
use _ContaoManager\Symfony\Component\HttpFoundation\Request;
use _ContaoManager\Symfony\Component\HttpFoundation\Response;
use _ContaoManager\Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
use _ContaoManager\Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use _ContaoManager\Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface;
use _ContaoManager\Symfony\Component\Security\Core\Exception\LogicException;
use _ContaoManager\Symfony\Component\Security\Core\Exception\LogoutException;
use _ContaoManager\Symfony\Component\Security\Core\Security as LegacySecurity;
use _ContaoManager\Symfony\Component\Security\Core\User\UserInterface;
use _ContaoManager\Symfony\Component\Security\Csrf\CsrfToken;
use _ContaoManager\Symfony\Component\Security\Http\Authenticator\AuthenticatorInterface;
use _ContaoManager\Symfony\Component\Security\Http\Authenticator\Passport\Badge\BadgeInterface;
use _ContaoManager\Symfony\Component\Security\Http\Event\LogoutEvent;
use _ContaoManager\Symfony\Component\Security\Http\ParameterBagUtils;
use _ContaoManager\Symfony\Component\Security\Http\SecurityRequestAttributes;
use _ContaoManager\Symfony\Contracts\Service\ServiceProviderInterface;
if (class_exists(InternalSecurity::class, \false)) {
    return;
}
if (class_exists(LegacySecurity::class)) {
    class_alias(LegacySecurity::class, InternalSecurity::class);
} else {
    /**
     * @internal
     */
    class InternalSecurity
    {
    }
}
/**
 * Helper class for commonly-needed security tasks.
 *
 * @author Ryan Weaver <ryan@symfonycasts.com>
 * @author Robin Chalas <robin.chalas@gmail.com>
 * @author Arnaud Frézet <arnaud@larriereguichet.fr>
 *
 * @final
 */
class Security extends InternalSecurity implements AuthorizationCheckerInterface
{
    /**
     * @deprecated since Symfony 6.4, use SecurityRequestAttributes::ACCESS_DENIED_ERROR instead
     */
    public const ACCESS_DENIED_ERROR = SecurityRequestAttributes::ACCESS_DENIED_ERROR;
    /**
     * @deprecated since Symfony 6.4, use SecurityRequestAttributes::AUTHENTICATION_ERROR instead
     */
    public const AUTHENTICATION_ERROR = SecurityRequestAttributes::AUTHENTICATION_ERROR;
    /**
     * @deprecated since Symfony 6.4, use SecurityRequestAttributes::LAST_USERNAME instead
     */
    public const LAST_USERNAME = SecurityRequestAttributes::LAST_USERNAME;
    public function __construct(private readonly ContainerInterface $container, private readonly array $authenticators = [])
    {
    }
    public function getUser(): ?UserInterface
    {
        if (!$token = $this->getToken()) {
            return null;
        }
        return $token->getUser();
    }
    /**
     * Checks if the attributes are granted against the current authentication token and optionally supplied subject.
     */
    public function isGranted(mixed $attributes, mixed $subject = null): bool
    {
        return $this->container->get('security.authorization_checker')->isGranted($attributes, $subject);
    }
    public function getToken(): ?TokenInterface
    {
        return $this->container->get('security.token_storage')->getToken();
    }
    public function getFirewallConfig(Request $request): ?FirewallConfig
    {
        return $this->container->get('security.firewall.map')->getFirewallConfig($request);
    }
    /**
     * @param UserInterface    $user              The user to authenticate
     * @param string|null      $authenticatorName The authenticator name (e.g. "form_login") or service id (e.g. SomeApiKeyAuthenticator::class) - required only if multiple authenticators are configured
     * @param string|null      $firewallName      The firewall name - required only if multiple firewalls are configured
     * @param BadgeInterface[] $badges            Badges to add to the user's passport
     *
     * @return Response|null The authenticator success response if any
     */
    public function login(UserInterface $user, ?string $authenticatorName = null, ?string $firewallName = null, array $badges = []): ?Response
    {
        $request = $this->container->get('request_stack')->getCurrentRequest();
        if (null === $request) {
            throw new LogicException('Unable to login without a request context.');
        }
        $firewallName ??= $this->getFirewallConfig($request)?->getName();
        if (!$firewallName) {
            throw new LogicException('Unable to login as the current route is not covered by any firewall.');
        }
        $authenticator = $this->getAuthenticator($authenticatorName, $firewallName);
        $userCheckerLocator = $this->container->get('security.user_checker_locator');
        $userCheckerLocator->get($firewallName)->checkPreAuth($user);
        return $this->container->get('security.authenticator.managers_locator')->get($firewallName)->authenticateUser($user, $authenticator, $request, $badges);
    }
    /**
     * Logout the current user by dispatching the LogoutEvent.
     *
     * @param bool $validateCsrfToken Whether to look for a valid CSRF token based on the `logout` listener configuration
     *
     * @return Response|null The LogoutEvent's Response if any
     *
     * @throws LogoutException When $validateCsrfToken is true and the CSRF token is not found or invalid
     */
    public function logout(bool $validateCsrfToken = \true): ?Response
    {
        $request = $this->container->get('request_stack')->getMainRequest();
        if (null === $request) {
            throw new LogicException('Unable to logout without a request context.');
        }
        /** @var TokenStorageInterface $tokenStorage */
        $tokenStorage = $this->container->get('security.token_storage');
        if (!($token = $tokenStorage->getToken()) || !$token->getUser()) {
            throw new LogicException('Unable to logout as there is no logged-in user.');
        }
        if (!$firewallConfig = $this->container->get('security.firewall.map')->getFirewallConfig($request)) {
            throw new LogicException('Unable to logout as the request is not behind a firewall.');
        }
        if ($validateCsrfToken) {
            if (!$this->container->has('security.csrf.token_manager') || !$logoutConfig = $firewallConfig->getLogout()) {
                throw new LogicException(\sprintf('Unable to logout with CSRF token validation. Either make sure that CSRF protection is enabled and "logout" is configured on the "%s" firewall, or bypass CSRF token validation explicitly by passing false to the $validateCsrfToken argument of this method.', $firewallConfig->getName()));
            }
            $csrfToken = ParameterBagUtils::getRequestParameterValue($request, $logoutConfig['csrf_parameter']);
            if (!\is_string($csrfToken) || !$this->container->get('security.csrf.token_manager')->isTokenValid(new CsrfToken($logoutConfig['csrf_token_id'], $csrfToken))) {
                throw new LogoutException('Invalid CSRF token.');
            }
        }
        $logoutEvent = new LogoutEvent($request, $token);
        $this->container->get('security.firewall.event_dispatcher_locator')->get($firewallConfig->getName())->dispatch($logoutEvent);
        $tokenStorage->setToken(null);
        return $logoutEvent->getResponse();
    }
    private function getAuthenticator(?string $authenticatorName, string $firewallName): AuthenticatorInterface
    {
        if (!isset($this->authenticators[$firewallName])) {
            throw new LogicException(\sprintf('No authenticators found for firewall "%s".', $firewallName));
        }
        /** @var ServiceProviderInterface $firewallAuthenticatorLocator */
        $firewallAuthenticatorLocator = $this->authenticators[$firewallName];
        if (!$authenticatorName) {
            $authenticatorIds = array_filter(array_keys($firewallAuthenticatorLocator->getProvidedServices()), fn(string $authenticatorId) => $authenticatorId !== \sprintf('security.authenticator.remember_me.%s', $firewallName));
            if (!$authenticatorIds) {
                throw new LogicException(\sprintf('No authenticator was found for the firewall "%s".', $firewallName));
            }
            if (1 < \count($authenticatorIds)) {
                throw new LogicException(\sprintf('Too many authenticators were found for the current firewall "%s". You must provide an instance of "%s" to login programmatically. The available authenticators for the firewall "%s" are "%s".', $firewallName, AuthenticatorInterface::class, $firewallName, implode('" ,"', $authenticatorIds)));
            }
            return $firewallAuthenticatorLocator->get($authenticatorIds[0]);
        }
        if ($firewallAuthenticatorLocator->has($authenticatorName)) {
            return $firewallAuthenticatorLocator->get($authenticatorName);
        }
        $authenticatorId = 'security.authenticator.' . $authenticatorName . '.' . $firewallName;
        if (!$firewallAuthenticatorLocator->has($authenticatorId)) {
            throw new LogicException(\sprintf('Unable to find an authenticator named "%s" for the firewall "%s". Available authenticators: "%s".', $authenticatorName, $firewallName, implode('", "', array_keys($firewallAuthenticatorLocator->getProvidedServices()))));
        }
        return $firewallAuthenticatorLocator->get($authenticatorId);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Bundle\SecurityBundle\LoginLink;

use _ContaoManager\Psr\Container\ContainerInterface;
use _ContaoManager\Symfony\Bundle\SecurityBundle\Security\FirewallAwareTrait;
use _ContaoManager\Symfony\Bundle\SecurityBundle\Security\FirewallMap;
use _ContaoManager\Symfony\Component\HttpFoundation\Request;
use _ContaoManager\Symfony\Component\HttpFoundation\RequestStack;
use _ContaoManager\Symfony\Component\Security\Core\User\UserInterface;
use _ContaoManager\Symfony\Component\Security\Http\LoginLink\LoginLinkDetails;
use _ContaoManager\Symfony\Component\Security\Http\LoginLink\LoginLinkHandlerInterface;
/**
 * Decorates the login link handler for the current firewall.
 *
 * @author Ryan Weaver <ryan@symfonycasts.com>
 */
class FirewallAwareLoginLinkHandler implements LoginLinkHandlerInterface
{
    use FirewallAwareTrait;
    private const FIREWALL_OPTION = 'login_link';
    public function __construct(FirewallMap $firewallMap, ContainerInterface $loginLinkHandlerLocator, RequestStack $requestStack)
    {
        $this->firewallMap = $firewallMap;
        $this->locator = $loginLinkHandlerLocator;
        $this->requestStack = $requestStack;
    }
    public function createLoginLink(UserInterface $user, ?Request $request = null, ?int $lifetime = null): LoginLinkDetails
    {
        return $this->getForFirewall()->createLoginLink($user, $request, $lifetime);
    }
    public function consumeLoginLink(Request $request): UserInterface
    {
        return $this->getForFirewall()->consumeLoginLink($request);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Bundle\SecurityBundle\DependencyInjection;

use _ContaoManager\Symfony\Bundle\SecurityBundle\DependencyInjection\Security\Factory\AbstractFactory;
use _ContaoManager\Symfony\Bundle\SecurityBundle\DependencyInjection\Security\Factory\AuthenticatorFactoryInterface;
use _ContaoManager\Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition;
use _ContaoManager\Symfony\Component\Config\Definition\Builder\TreeBuilder;
use _ContaoManager\Symfony\Component\Config\Definition\ConfigurationInterface;
use _ContaoManager\Symfony\Component\Config\Definition\Exception\InvalidConfigurationException;
use _ContaoManager\Symfony\Component\Security\Http\EntryPoint\AuthenticationEntryPointInterface;
use _ContaoManager\Symfony\Component\Security\Http\Session\SessionAuthenticationStrategy;
/**
 * SecurityExtension configuration structure.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
class MainConfiguration implements ConfigurationInterface
{
    /** @internal */
    public const STRATEGY_AFFIRMATIVE = 'affirmative';
    /** @internal */
    public const STRATEGY_CONSENSUS = 'consensus';
    /** @internal */
    public const STRATEGY_UNANIMOUS = 'unanimous';
    /** @internal */
    public const STRATEGY_PRIORITY = 'priority';
    private array $factories;
    private array $userProviderFactories;
    /**
     * @param array<AuthenticatorFactoryInterface> $factories
     */
    public function __construct(array $factories, array $userProviderFactories)
    {
        $this->factories = $factories;
        $this->userProviderFactories = $userProviderFactories;
    }
    /**
     * Generates the configuration tree builder.
     */
    public function getConfigTreeBuilder(): TreeBuilder
    {
        $tb = new TreeBuilder('security');
        $rootNode = $tb->getRootNode();
        $rootNode->children()->scalarNode('access_denied_url')->defaultNull()->example('/foo/error403')->end()->enumNode('session_fixation_strategy')->values([SessionAuthenticationStrategy::NONE, SessionAuthenticationStrategy::MIGRATE, SessionAuthenticationStrategy::INVALIDATE])->defaultValue(SessionAuthenticationStrategy::MIGRATE)->end()->booleanNode('hide_user_not_found')->defaultTrue()->end()->booleanNode('erase_credentials')->defaultTrue()->end()->booleanNode('enable_authenticator_manager')->setDeprecated('symfony/security-bundle', '6.2', 'The "%node%" option at "%path%" is deprecated.')->defaultTrue()->end()->arrayNode('access_decision_manager')->addDefaultsIfNotSet()->children()->enumNode('strategy')->values($this->getAccessDecisionStrategies())->end()->scalarNode('service')->end()->scalarNode('strategy_service')->end()->booleanNode('allow_if_all_abstain')->defaultFalse()->end()->booleanNode('allow_if_equal_granted_denied')->defaultTrue()->end()->end()->validate()->ifTrue(fn($v) => isset($v['strategy'], $v['service']))->thenInvalid('"strategy" and "service" cannot be used together.')->end()->validate()->ifTrue(fn($v) => isset($v['strategy'], $v['strategy_service']))->thenInvalid('"strategy" and "strategy_service" cannot be used together.')->end()->validate()->ifTrue(fn($v) => isset($v['service'], $v['strategy_service']))->thenInvalid('"service" and "strategy_service" cannot be used together.')->end()->end()->end();
        $this->addPasswordHashersSection($rootNode);
        $this->addProvidersSection($rootNode);
        $this->addFirewallsSection($rootNode, $this->factories);
        $this->addAccessControlSection($rootNode);
        $this->addRoleHierarchySection($rootNode);
        return $tb;
    }
    private function addRoleHierarchySection(ArrayNodeDefinition $rootNode): void
    {
        $rootNode->fixXmlConfig('role', 'role_hierarchy')->children()->arrayNode('role_hierarchy')->useAttributeAsKey('id')->prototype('array')->performNoDeepMerging()->beforeNormalization()->ifString()->then(fn($v) => ['value' => $v])->end()->beforeNormalization()->ifTrue(fn($v) => \is_array($v) && isset($v['value']))->then(fn($v) => preg_split('/\s*,\s*/', $v['value']))->end()->prototype('scalar')->end()->end()->end()->end();
    }
    private function addAccessControlSection(ArrayNodeDefinition $rootNode): void
    {
        $rootNode->fixXmlConfig('rule', 'access_control')->children()->arrayNode('access_control')->cannotBeOverwritten()->prototype('array')->fixXmlConfig('ip')->fixXmlConfig('method')->fixXmlConfig('attribute')->children()->scalarNode('request_matcher')->defaultNull()->end()->scalarNode('requires_channel')->defaultNull()->end()->scalarNode('path')->defaultNull()->info('use the urldecoded format')->example('^/path to resource/')->end()->scalarNode('host')->defaultNull()->end()->integerNode('port')->defaultNull()->end()->arrayNode('ips')->beforeNormalization()->ifString()->then(fn($v) => [$v])->end()->prototype('scalar')->end()->end()->arrayNode('attributes')->useAttributeAsKey('key')->prototype('scalar')->end()->end()->scalarNode('route')->defaultNull()->end()->arrayNode('methods')->beforeNormalization()->ifString()->then(fn($v) => preg_split('/\s*,\s*/', $v))->end()->prototype('scalar')->end()->end()->scalarNode('allow_if')->defaultNull()->end()->end()->fixXmlConfig('role')->children()->arrayNode('roles')->beforeNormalization()->ifString()->then(fn($v) => preg_split('/\s*,\s*/', $v))->end()->prototype('scalar')->end()->end()->end()->end()->end()->end();
    }
    /**
     * @param array<AuthenticatorFactoryInterface> $factories
     */
    private function addFirewallsSection(ArrayNodeDefinition $rootNode, array $factories): void
    {
        $firewallNodeBuilder = $rootNode->fixXmlConfig('firewall')->children()->arrayNode('firewalls')->isRequired()->requiresAtLeastOneElement()->disallowNewKeysInSubsequentConfigs()->useAttributeAsKey('name')->prototype('array')->fixXmlConfig('required_badge')->children();
        $firewallNodeBuilder->scalarNode('pattern')->beforeNormalization()->ifArray()->then(fn($v) => \sprintf('(?:%s)', implode('|', $v)))->end()->end()->scalarNode('host')->end()->arrayNode('methods')->beforeNormalization()->ifString()->then(fn($v) => preg_split('/\s*,\s*/', $v))->end()->prototype('scalar')->end()->end()->booleanNode('security')->defaultTrue()->end()->scalarNode('user_checker')->defaultValue('security.user_checker')->treatNullLike('security.user_checker')->info('The UserChecker to use when authenticating users in this firewall.')->end()->scalarNode('request_matcher')->end()->scalarNode('access_denied_url')->end()->scalarNode('access_denied_handler')->end()->scalarNode('entry_point')->info(\sprintf('An enabled authenticator name or a service id that implements "%s"', AuthenticationEntryPointInterface::class))->end()->scalarNode('provider')->end()->booleanNode('stateless')->defaultFalse()->end()->booleanNode('lazy')->defaultFalse()->end()->scalarNode('context')->cannotBeEmpty()->end()->arrayNode('logout')->treatTrueLike([])->canBeUnset()->beforeNormalization()->ifTrue(fn($v): bool => isset($v['csrf_token_generator']) && !isset($v['csrf_token_manager']))->then(function (array $v): array {
            $v['csrf_token_manager'] = $v['csrf_token_generator'];
            return $v;
        })->end()->beforeNormalization()->ifTrue(fn($v): bool => \is_array($v) && (isset($v['csrf_token_manager']) xor isset($v['enable_csrf'])))->then(function (array $v): array {
            if (isset($v['csrf_token_manager'])) {
                $v['enable_csrf'] = \true;
            } elseif ($v['enable_csrf']) {
                $v['csrf_token_manager'] = 'security.csrf.token_manager';
            }
            return $v;
        })->end()->children()->booleanNode('enable_csrf')->defaultNull()->end()->scalarNode('csrf_token_id')->defaultValue('logout')->end()->scalarNode('csrf_parameter')->defaultValue('_csrf_token')->end()->scalarNode('csrf_token_generator')->setDeprecated('symfony/security-bundle', '6.3', 'The "%node%" option is deprecated. Use "csrf_token_manager" instead.')->end()->scalarNode('csrf_token_manager')->end()->scalarNode('path')->defaultValue('/logout')->end()->scalarNode('target')->defaultValue('/')->end()->booleanNode('invalidate_session')->defaultTrue()->end()->arrayNode('clear_site_data')->performNoDeepMerging()->beforeNormalization()->ifString()->then(fn($v) => $v ? array_map('trim', explode(',', $v)) : [])->end()->enumPrototype()->values(['*', 'cache', 'cookies', 'storage', 'executionContexts'])->end()->end()->end()->fixXmlConfig('delete_cookie')->children()->arrayNode('delete_cookies')->normalizeKeys(\false)->beforeNormalization()->ifTrue(fn($v) => \is_array($v) && \is_int(key($v)))->then(fn($v) => array_map(fn($v) => ['name' => $v], $v))->end()->useAttributeAsKey('name')->prototype('array')->children()->scalarNode('path')->defaultNull()->end()->scalarNode('domain')->defaultNull()->end()->scalarNode('secure')->defaultFalse()->end()->scalarNode('samesite')->defaultNull()->end()->scalarNode('partitioned')->defaultFalse()->end()->end()->end()->end()->end()->end()->arrayNode('switch_user')->canBeUnset()->children()->scalarNode('provider')->end()->scalarNode('parameter')->defaultValue('_switch_user')->end()->scalarNode('role')->defaultValue('ROLE_ALLOWED_TO_SWITCH')->end()->scalarNode('target_route')->defaultValue(null)->end()->end()->end()->arrayNode('required_badges')->info('A list of badges that must be present on the authenticated passport.')->validate()->always()->then(function ($requiredBadges) {
            return array_map(function ($requiredBadge) {
                if (class_exists($requiredBadge)) {
                    return $requiredBadge;
                }
                if (!str_contains($requiredBadge, '\\')) {
                    $fqcn = 'Symfony\Component\Security\Http\Authenticator\Passport\Badge\\' . $requiredBadge;
                    if (class_exists($fqcn)) {
                        return $fqcn;
                    }
                }
                throw new InvalidConfigurationException(\sprintf('Undefined security Badge class "%s" set in "security.firewall.required_badges".', $requiredBadge));
            }, $requiredBadges);
        })->end()->prototype('scalar')->end()->end();
        $abstractFactoryKeys = [];
        foreach ($factories as $factory) {
            $name = str_replace('-', '_', $factory->getKey());
            $factoryNode = $firewallNodeBuilder->arrayNode($name)->canBeUnset();
            if ($factory instanceof AbstractFactory) {
                $abstractFactoryKeys[] = $name;
            }
            $factory->addConfiguration($factoryNode);
        }
        // check for unreachable check paths
        $firewallNodeBuilder->end()->validate()->ifTrue(fn($v) => \true === $v['security'] && isset($v['pattern']) && !isset($v['request_matcher']))->then(function ($firewall) use ($abstractFactoryKeys) {
            foreach ($abstractFactoryKeys as $k) {
                if (!isset($firewall[$k]['check_path'])) {
                    continue;
                }
                if (str_contains($firewall[$k]['check_path'], '/') && !preg_match('#' . $firewall['pattern'] . '#', $firewall[$k]['check_path'])) {
                    throw new \LogicException(\sprintf('The check_path "%s" for login method "%s" is not matched by the firewall pattern "%s".', $firewall[$k]['check_path'], $k, $firewall['pattern']));
                }
            }
            return $firewall;
        })->end();
    }
    private function addProvidersSection(ArrayNodeDefinition $rootNode): void
    {
        $providerNodeBuilder = $rootNode->fixXmlConfig('provider')->children()->arrayNode('providers')->example(['my_memory_provider' => ['memory' => ['users' => ['foo' => ['password' => 'foo', 'roles' => 'ROLE_USER'], 'bar' => ['password' => 'bar', 'roles' => '[ROLE_USER, ROLE_ADMIN]']]]], 'my_entity_provider' => ['entity' => ['class' => 'SecurityBundle:User', 'property' => 'username']]])->requiresAtLeastOneElement()->useAttributeAsKey('name')->prototype('array');
        $providerNodeBuilder->children()->scalarNode('id')->end()->arrayNode('chain')->fixXmlConfig('provider')->children()->arrayNode('providers')->beforeNormalization()->ifString()->then(fn($v) => preg_split('/\s*,\s*/', $v))->end()->prototype('scalar')->end()->end()->end()->end()->end();
        foreach ($this->userProviderFactories as $factory) {
            $name = str_replace('-', '_', $factory->getKey());
            $factoryNode = $providerNodeBuilder->children()->arrayNode($name)->canBeUnset();
            $factory->addConfiguration($factoryNode);
        }
        $providerNodeBuilder->validate()->ifTrue(fn($v) => \count($v) > 1)->thenInvalid('You cannot set multiple provider types for the same provider')->end()->validate()->ifTrue(fn($v) => 0 === \count($v))->thenInvalid('You must set a provider definition for the provider.')->end();
    }
    private function addPasswordHashersSection(ArrayNodeDefinition $rootNode): void
    {
        $rootNode->fixXmlConfig('password_hasher')->children()->arrayNode('password_hashers')->example(['_ContaoManager\App\Entity\User1' => 'auto', '_ContaoManager\App\Entity\User2' => ['algorithm' => 'auto', 'time_cost' => 8, 'cost' => 13]])->requiresAtLeastOneElement()->useAttributeAsKey('class')->prototype('array')->canBeUnset()->performNoDeepMerging()->beforeNormalization()->ifString()->then(fn($v) => ['algorithm' => $v])->end()->children()->scalarNode('algorithm')->cannotBeEmpty()->validate()->ifTrue(fn($v) => !\is_string($v))->thenInvalid('You must provide a string value.')->end()->end()->arrayNode('migrate_from')->prototype('scalar')->end()->beforeNormalization()->castToArray()->end()->end()->scalarNode('hash_algorithm')->info('Name of hashing algorithm for PBKDF2 (i.e. sha256, sha512, etc..) See hash_algos() for a list of supported algorithms.')->defaultValue('sha512')->end()->scalarNode('key_length')->defaultValue(40)->end()->booleanNode('ignore_case')->defaultFalse()->end()->booleanNode('encode_as_base64')->defaultTrue()->end()->scalarNode('iterations')->defaultValue(5000)->end()->integerNode('cost')->min(4)->max(31)->defaultNull()->end()->scalarNode('memory_cost')->defaultNull()->end()->scalarNode('time_cost')->defaultNull()->end()->scalarNode('id')->end()->end()->end()->end()->end();
    }
    private function getAccessDecisionStrategies(): array
    {
        return [self::STRATEGY_AFFIRMATIVE, self::STRATEGY_CONSENSUS, self::STRATEGY_UNANIMOUS, self::STRATEGY_PRIORITY];
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Bundle\SecurityBundle\DependencyInjection\Security\AccessToken;

use _ContaoManager\Jose\Component\Core\Algorithm;
use _ContaoManager\Symfony\Component\Config\Definition\Builder\NodeBuilder;
use _ContaoManager\Symfony\Component\DependencyInjection\ChildDefinition;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerBuilder;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\LogicException;
use _ContaoManager\Symfony\Component\DependencyInjection\Reference;
/**
 * Configures a token handler for decoding and validating an OIDC token.
 */
class OidcTokenHandlerFactory implements TokenHandlerFactoryInterface
{
    public function create(ContainerBuilder $container, string $id, array|string $config): void
    {
        $tokenHandlerDefinition = $container->setDefinition($id, (new ChildDefinition('security.access_token_handler.oidc'))->replaceArgument(2, $config['audience'])->replaceArgument(3, $config['issuers'])->replaceArgument(4, $config['claim']));
        if (!ContainerBuilder::willBeAvailable('web-token/jwt-core', Algorithm::class, ['symfony/security-bundle'])) {
            throw new LogicException('You cannot use the "oidc" token handler since "web-token/jwt-core" is not installed. Try running "composer require web-token/jwt-core".');
        }
        // @see Symfony\Bundle\SecurityBundle\DependencyInjection\Security\Factory\SignatureAlgorithmFactory
        // for supported algorithms
        if (\in_array($config['algorithm'], ['ES256', 'ES384', 'ES512'], \true)) {
            $tokenHandlerDefinition->replaceArgument(0, new Reference('security.access_token_handler.oidc.signature.' . $config['algorithm']));
        } else {
            $tokenHandlerDefinition->replaceArgument(0, (new ChildDefinition('security.access_token_handler.oidc.signature'))->replaceArgument(0, $config['algorithm']));
        }
        $tokenHandlerDefinition->replaceArgument(1, (new ChildDefinition('security.access_token_handler.oidc.jwk'))->replaceArgument(0, $config['key']));
    }
    public function getKey(): string
    {
        return 'oidc';
    }
    public function addConfiguration(NodeBuilder $node): void
    {
        $node->arrayNode($this->getKey())->fixXmlConfig($this->getKey())->children()->scalarNode('claim')->info('Claim which contains the user identifier (e.g.: sub, email..).')->defaultValue('sub')->end()->scalarNode('audience')->info('Audience set in the token, for validation purpose.')->isRequired()->end()->arrayNode('issuers')->info('Issuers allowed to generate the token, for validation purpose.')->isRequired()->prototype('scalar')->end()->end()->scalarNode('algorithm')->info('Algorithm used to sign the token.')->isRequired()->end()->scalarNode('key')->info('JSON-encoded JWK used to sign the token (must contain a "kty" key).')->isRequired()->end()->end()->end();
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Bundle\SecurityBundle\DependencyInjection\Security\AccessToken;

use _ContaoManager\Symfony\Component\Config\Definition\Builder\NodeBuilder;
use _ContaoManager\Symfony\Component\DependencyInjection\ChildDefinition;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerBuilder;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\LogicException;
use _ContaoManager\Symfony\Component\DependencyInjection\Reference;
use _ContaoManager\Symfony\Contracts\HttpClient\HttpClientInterface;
/**
 * Configures a token handler for an OIDC server.
 */
class OidcUserInfoTokenHandlerFactory implements TokenHandlerFactoryInterface
{
    public function create(ContainerBuilder $container, string $id, array|string $config): void
    {
        $clientDefinition = (new ChildDefinition('security.access_token_handler.oidc_user_info.http_client'))->replaceArgument(0, ['base_uri' => $config['base_uri']]);
        if (isset($config['client'])) {
            $clientDefinition->setFactory([new Reference($config['client']), 'withOptions']);
        } elseif (!ContainerBuilder::willBeAvailable('symfony/http-client', HttpClientInterface::class, ['symfony/security-bundle'])) {
            throw new LogicException('You cannot use the "oidc_user_info" token handler since the HttpClient component is not installed. Try running "composer require symfony/http-client".');
        }
        $container->setDefinition($id, new ChildDefinition('security.access_token_handler.oidc_user_info'))->replaceArgument(0, $clientDefinition)->replaceArgument(2, $config['claim']);
    }
    public function getKey(): string
    {
        return 'oidc_user_info';
    }
    public function addConfiguration(NodeBuilder $node): void
    {
        $node->arrayNode($this->getKey())->fixXmlConfig($this->getKey())->beforeNormalization()->ifString()->then(fn($v) => ['claim' => 'sub', 'base_uri' => $v])->end()->children()->scalarNode('base_uri')->info('Base URI of the userinfo endpoint on the OIDC server.')->isRequired()->cannotBeEmpty()->end()->scalarNode('claim')->info('Claim which contains the user identifier (e.g. sub, email, etc.).')->defaultValue('sub')->cannotBeEmpty()->end()->scalarNode('client')->info('HttpClient service id to use to call the OIDC server.')->end()->end()->end();
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Bundle\SecurityBundle\DependencyInjection\Security\AccessToken;

use _ContaoManager\Symfony\Component\Config\Definition\Builder\NodeBuilder;
use _ContaoManager\Symfony\Component\DependencyInjection\ChildDefinition;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerBuilder;
/**
 * Configures a token handler from a service id.
 *
 * @see \Symfony\Bundle\SecurityBundle\Tests\DependencyInjection\Security\Factory\AccessTokenFactoryTest
 */
class ServiceTokenHandlerFactory implements TokenHandlerFactoryInterface
{
    public function create(ContainerBuilder $container, string $id, array|string $config): void
    {
        $container->setDefinition($id, new ChildDefinition($config));
    }
    public function getKey(): string
    {
        return 'id';
    }
    public function addConfiguration(NodeBuilder $node): void
    {
        $node->scalarNode($this->getKey())->end();
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Bundle\SecurityBundle\DependencyInjection\Security\AccessToken;

use _ContaoManager\Symfony\Component\Config\Definition\Builder\NodeBuilder;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerBuilder;
/**
 * Allows creating configurable token handlers.
 */
interface TokenHandlerFactoryInterface
{
    /**
     * Creates a generic token handler service.
     */
    public function create(ContainerBuilder $container, string $id, array|string $config): void;
    /**
     * Gets a generic token handler configuration key.
     */
    public function getKey(): string;
    /**
     * Adds a generic token handler configuration.
     */
    public function addConfiguration(NodeBuilder $node): void;
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Bundle\SecurityBundle\DependencyInjection\Security\UserProvider;

use _ContaoManager\Symfony\Component\Config\Definition\Builder\NodeDefinition;
use _ContaoManager\Symfony\Component\DependencyInjection\ChildDefinition;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerBuilder;
use _ContaoManager\Symfony\Component\DependencyInjection\Reference;
/**
 * LdapFactory creates services for Ldap user provider.
 *
 * @author Grégoire Pineau <lyrixx@lyrixx.info>
 * @author Charles Sarrazin <charles@sarraz.in>
 */
class LdapFactory implements UserProviderFactoryInterface
{
    /**
     * @return void
     */
    public function create(ContainerBuilder $container, string $id, array $config)
    {
        $container->setDefinition($id, new ChildDefinition('security.user.provider.ldap'))->replaceArgument(0, new Reference($config['service']))->replaceArgument(1, $config['base_dn'])->replaceArgument(2, $config['search_dn'])->replaceArgument(3, $config['search_password'])->replaceArgument(4, $config['default_roles'])->replaceArgument(5, $config['uid_key'])->replaceArgument(6, $config['filter'])->replaceArgument(7, $config['password_attribute'])->replaceArgument(8, $config['extra_fields']);
    }
    /**
     * @return string
     */
    public function getKey()
    {
        return 'ldap';
    }
    /**
     * @return void
     */
    public function addConfiguration(NodeDefinition $node)
    {
        $node->fixXmlConfig('extra_field')->fixXmlConfig('default_role')->children()->scalarNode('service')->isRequired()->cannotBeEmpty()->defaultValue('ldap')->end()->scalarNode('base_dn')->isRequired()->cannotBeEmpty()->end()->scalarNode('search_dn')->defaultNull()->end()->scalarNode('search_password')->defaultNull()->end()->arrayNode('extra_fields')->prototype('scalar')->end()->end()->arrayNode('default_roles')->beforeNormalization()->ifString()->then(fn($v) => preg_split('/\s*,\s*/', $v))->end()->requiresAtLeastOneElement()->prototype('scalar')->end()->end()->scalarNode('uid_key')->defaultValue('sAMAccountName')->end()->scalarNode('filter')->defaultValue('({uid_key}={username})')->end()->scalarNode('password_attribute')->defaultNull()->end()->end();
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Bundle\SecurityBundle\DependencyInjection\Security\UserProvider;

use _ContaoManager\Symfony\Component\Config\Definition\Builder\NodeDefinition;
use _ContaoManager\Symfony\Component\DependencyInjection\ChildDefinition;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerBuilder;
use _ContaoManager\Symfony\Component\DependencyInjection\Parameter;
/**
 * InMemoryFactory creates services for the memory provider.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 * @author Christophe Coevoet <stof@notk.org>
 */
class InMemoryFactory implements UserProviderFactoryInterface
{
    /**
     * @return void
     */
    public function create(ContainerBuilder $container, string $id, array $config)
    {
        $definition = $container->setDefinition($id, new ChildDefinition('security.user.provider.in_memory'));
        $defaultPassword = new Parameter('container.build_id');
        $users = [];
        foreach ($config['users'] as $username => $user) {
            $users[$username] = ['password' => null !== $user['password'] ? (string) $user['password'] : $defaultPassword, 'roles' => $user['roles']];
        }
        $definition->addArgument($users);
    }
    /**
     * @return string
     */
    public function getKey()
    {
        return 'memory';
    }
    /**
     * @return void
     */
    public function addConfiguration(NodeDefinition $node)
    {
        $node->fixXmlConfig('user')->children()->arrayNode('users')->useAttributeAsKey('identifier')->normalizeKeys(\false)->prototype('array')->children()->scalarNode('password')->defaultNull()->end()->arrayNode('roles')->beforeNormalization()->ifString()->then(fn($v) => preg_split('/\s*,\s*/', $v))->end()->prototype('scalar')->end()->end()->end()->end()->end()->end();
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Bundle\SecurityBundle\DependencyInjection\Security\UserProvider;

use _ContaoManager\Symfony\Component\Config\Definition\Builder\NodeDefinition;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerBuilder;
/**
 * UserProviderFactoryInterface is the interface for all user provider factories.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 * @author Christophe Coevoet <stof@notk.org>
 */
interface UserProviderFactoryInterface
{
    /**
     * @return void
     */
    public function create(ContainerBuilder $container, string $id, array $config);
    /**
     * @return string
     */
    public function getKey();
    /**
     * @return void
     */
    public function addConfiguration(NodeDefinition $builder);
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Bundle\SecurityBundle\DependencyInjection\Security\Factory;

use _ContaoManager\Symfony\Component\Config\Definition\Builder\NodeBuilder;
use _ContaoManager\Symfony\Component\Config\Definition\Builder\NodeDefinition;
use _ContaoManager\Symfony\Component\Config\FileLocator;
use _ContaoManager\Symfony\Component\DependencyInjection\ChildDefinition;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerBuilder;
use _ContaoManager\Symfony\Component\DependencyInjection\Loader\PhpFileLoader;
use _ContaoManager\Symfony\Component\DependencyInjection\Reference;
use _ContaoManager\Symfony\Component\Security\Http\Authentication\AuthenticationFailureHandlerInterface;
use _ContaoManager\Symfony\Component\Security\Http\Authentication\AuthenticationSuccessHandlerInterface;
/**
 * @internal
 */
class LoginLinkFactory extends AbstractFactory
{
    public const PRIORITY = -20;
    public function addConfiguration(NodeDefinition $node): void
    {
        /** @var NodeBuilder $builder */
        $builder = $node->fixXmlConfig('signature_property', 'signature_properties')->children();
        $builder->scalarNode('check_route')->isRequired()->info('Route that will validate the login link - e.g. "app_login_link_verify".')->end()->scalarNode('check_post_only')->defaultFalse()->info('If true, only HTTP POST requests to "check_route" will be handled by the authenticator.')->end()->arrayNode('signature_properties')->isRequired()->prototype('scalar')->end()->requiresAtLeastOneElement()->info('An array of properties on your User that are used to sign the link. If any of these change, all existing links will become invalid.')->example(['email', 'password'])->end()->integerNode('lifetime')->defaultValue(600)->info('The lifetime of the login link in seconds.')->end()->integerNode('max_uses')->defaultNull()->info('Max number of times a login link can be used - null means unlimited within lifetime.')->end()->scalarNode('used_link_cache')->info('Cache service id used to expired links of max_uses is set.')->end()->scalarNode('success_handler')->info(\sprintf('A service id that implements %s.', AuthenticationSuccessHandlerInterface::class))->end()->scalarNode('failure_handler')->info(\sprintf('A service id that implements %s.', AuthenticationFailureHandlerInterface::class))->end()->scalarNode('provider')->info('The user provider to load users from.')->end();
        foreach (array_merge($this->defaultSuccessHandlerOptions, $this->defaultFailureHandlerOptions) as $name => $default) {
            if (\is_bool($default)) {
                $builder->booleanNode($name)->defaultValue($default);
            } else {
                $builder->scalarNode($name)->defaultValue($default);
            }
        }
    }
    public function getKey(): string
    {
        return 'login-link';
    }
    public function createAuthenticator(ContainerBuilder $container, string $firewallName, array $config, string $userProviderId): string
    {
        if (!$container->hasDefinition('security.authenticator.login_link')) {
            $loader = new PhpFileLoader($container, new FileLocator(\dirname(__DIR__) . '/../../Resources/config'));
            $loader->load('security_authenticator_login_link.php');
        }
        if (null !== $config['max_uses'] && !isset($config['used_link_cache'])) {
            $config['used_link_cache'] = 'security.authenticator.cache.expired_links';
            $defaultCacheDefinition = $container->getDefinition($config['used_link_cache']);
            if (!$defaultCacheDefinition->hasTag('cache.pool')) {
                $defaultCacheDefinition->addTag('cache.pool');
            }
        }
        $expiredStorageId = null;
        if (isset($config['used_link_cache'])) {
            $expiredStorageId = 'security.authenticator.expired_login_link_storage.' . $firewallName;
            $container->setDefinition($expiredStorageId, new ChildDefinition('security.authenticator.expired_login_link_storage'))->replaceArgument(0, new Reference($config['used_link_cache']))->replaceArgument(1, $config['lifetime']);
        }
        $signatureHasherId = 'security.authenticator.login_link_signature_hasher.' . $firewallName;
        $container->setDefinition($signatureHasherId, new ChildDefinition('security.authenticator.abstract_login_link_signature_hasher'))->replaceArgument(1, $config['signature_properties'])->replaceArgument(3, $expiredStorageId ? new Reference($expiredStorageId) : null)->replaceArgument(4, $config['max_uses'] ?? null);
        $linkerId = 'security.authenticator.login_link_handler.' . $firewallName;
        $linkerOptions = ['route_name' => $config['check_route'], 'lifetime' => $config['lifetime']];
        $container->setDefinition($linkerId, new ChildDefinition('security.authenticator.abstract_login_link_handler'))->replaceArgument(1, new Reference($userProviderId))->replaceArgument(2, new Reference($signatureHasherId))->replaceArgument(3, $linkerOptions)->addTag('security.authenticator.login_linker', ['firewall' => $firewallName]);
        $authenticatorId = 'security.authenticator.login_link.' . $firewallName;
        $container->setDefinition($authenticatorId, new ChildDefinition('security.authenticator.login_link'))->replaceArgument(0, new Reference($linkerId))->replaceArgument(2, new Reference($this->createAuthenticationSuccessHandler($container, $firewallName, $config)))->replaceArgument(3, new Reference($this->createAuthenticationFailureHandler($container, $firewallName, $config)))->replaceArgument(4, ['check_route' => $config['check_route'], 'check_post_only' => $config['check_post_only']]);
        return $authenticatorId;
    }
    public function getPriority(): int
    {
        return self::PRIORITY;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Bundle\SecurityBundle\DependencyInjection\Security\Factory;

use _ContaoManager\Symfony\Component\Config\Definition\Builder\NodeDefinition;
use _ContaoManager\Symfony\Component\DependencyInjection\ChildDefinition;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerBuilder;
use _ContaoManager\Symfony\Component\DependencyInjection\Reference;
use _ContaoManager\Symfony\Component\Security\Core\Exception\LogicException;
/**
 * HttpBasicFactory creates services for HTTP basic authentication.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 * @author Grégoire Pineau <lyrixx@lyrixx.info>
 * @author Charles Sarrazin <charles@sarraz.in>
 *
 * @internal
 */
class HttpBasicLdapFactory extends HttpBasicFactory
{
    use LdapFactoryTrait;
    public function create(ContainerBuilder $container, string $id, array $config, string $userProvider, ?string $defaultEntryPoint): array
    {
        $provider = 'security.authentication.provider.ldap_bind.' . $id;
        $definition = $container->setDefinition($provider, new ChildDefinition('security.authentication.provider.ldap_bind'))->replaceArgument(0, new Reference($userProvider))->replaceArgument(1, new Reference('security.user_checker.' . $id))->replaceArgument(2, $id)->replaceArgument(3, new Reference($config['service']))->replaceArgument(4, $config['dn_string'])->replaceArgument(6, $config['search_dn'])->replaceArgument(7, $config['search_password']);
        // entry point
        $entryPointId = $defaultEntryPoint;
        if (null === $entryPointId) {
            $entryPointId = 'security.authentication.basic_entry_point.' . $id;
            $container->setDefinition($entryPointId, new ChildDefinition('security.authentication.basic_entry_point'))->addArgument($config['realm']);
        }
        if (!empty($config['query_string'])) {
            if ('' === $config['search_dn'] || '' === $config['search_password']) {
                throw new LogicException('Using the "query_string" config without using a "search_dn" and a "search_password" is not supported.');
            }
            $definition->addMethodCall('setQueryString', [$config['query_string']]);
        }
        // listener
        $listenerId = 'security.authentication.listener.basic.' . $id;
        $listener = $container->setDefinition($listenerId, new ChildDefinition('security.authentication.listener.basic'));
        $listener->replaceArgument(2, $id);
        $listener->replaceArgument(3, new Reference($entryPointId));
        return [$provider, $listenerId, $entryPointId];
    }
    public function addConfiguration(NodeDefinition $node): void
    {
        parent::addConfiguration($node);
        $node->children()->scalarNode('service')->defaultValue('ldap')->end()->scalarNode('dn_string')->defaultValue('{username}')->end()->scalarNode('query_string')->end()->scalarNode('search_dn')->defaultValue('')->end()->scalarNode('search_password')->defaultValue('')->end()->end();
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Bundle\SecurityBundle\DependencyInjection\Security\Factory;

use _ContaoManager\Symfony\Component\Config\Definition\Builder\NodeDefinition;
/**
 * JsonLoginLdapFactory creates services for json login ldap authentication.
 *
 * @internal
 */
class JsonLoginLdapFactory extends JsonLoginFactory
{
    use LdapFactoryTrait;
    public function addConfiguration(NodeDefinition $node): void
    {
        parent::addConfiguration($node);
        $node->children()->scalarNode('service')->defaultValue('ldap')->end()->scalarNode('dn_string')->defaultValue('{username}')->end()->scalarNode('query_string')->end()->scalarNode('search_dn')->defaultValue('')->end()->scalarNode('search_password')->defaultValue('')->end()->end();
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Bundle\SecurityBundle\DependencyInjection\Security\Factory;

use _ContaoManager\Symfony\Bundle\SecurityBundle\DependencyInjection\Security\AccessToken\TokenHandlerFactoryInterface;
use _ContaoManager\Symfony\Component\Config\Definition\Builder\NodeDefinition;
use _ContaoManager\Symfony\Component\Config\Definition\Exception\InvalidConfigurationException;
use _ContaoManager\Symfony\Component\DependencyInjection\ChildDefinition;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerBuilder;
use _ContaoManager\Symfony\Component\DependencyInjection\Reference;
/**
 * AccessTokenFactory creates services for Access Token authentication.
 *
 * @author Florent Morselli <florent.morselli@spomky-labs.com>
 *
 * @internal
 */
final class AccessTokenFactory extends AbstractFactory implements StatelessAuthenticatorFactoryInterface
{
    private const PRIORITY = -40;
    /**
     * @param array<TokenHandlerFactoryInterface> $tokenHandlerFactories
     */
    public function __construct(private readonly array $tokenHandlerFactories)
    {
        $this->options = [];
        $this->defaultFailureHandlerOptions = [];
        $this->defaultSuccessHandlerOptions = [];
    }
    public function addConfiguration(NodeDefinition $node): void
    {
        parent::addConfiguration($node);
        $builder = $node->children();
        $builder->scalarNode('realm')->defaultNull()->end()->arrayNode('token_extractors')->fixXmlConfig('token_extractors')->beforeNormalization()->ifString()->then(fn($v) => [$v])->end()->cannotBeEmpty()->defaultValue(['security.access_token_extractor.header'])->scalarPrototype()->end()->end();
        $tokenHandlerNodeBuilder = $builder->arrayNode('token_handler')->example(['id' => '_ContaoManager\App\Security\CustomTokenHandler'])->beforeNormalization()->ifString()->then(fn($v) => ['id' => $v])->end()->beforeNormalization()->ifTrue(fn($v) => \is_array($v) && 1 < \count($v))->then(fn() => throw new InvalidConfigurationException('You cannot configure multiple token handlers.'))->end()->isRequired()->beforeNormalization()->ifTrue(fn($v) => \is_array($v) && !$v)->then(fn() => throw new InvalidConfigurationException('You must set a token handler.'))->end()->children();
        foreach ($this->tokenHandlerFactories as $factory) {
            $factory->addConfiguration($tokenHandlerNodeBuilder);
        }
        $tokenHandlerNodeBuilder->end();
    }
    public function getPriority(): int
    {
        return self::PRIORITY;
    }
    public function getKey(): string
    {
        return 'access_token';
    }
    public function createAuthenticator(ContainerBuilder $container, string $firewallName, array $config, ?string $userProviderId): string
    {
        $successHandler = isset($config['success_handler']) ? new Reference($this->createAuthenticationSuccessHandler($container, $firewallName, $config)) : null;
        $failureHandler = isset($config['failure_handler']) ? new Reference($this->createAuthenticationFailureHandler($container, $firewallName, $config)) : null;
        $authenticatorId = \sprintf('security.authenticator.access_token.%s', $firewallName);
        $extractorId = $this->createExtractor($container, $firewallName, $config['token_extractors']);
        $tokenHandlerId = $this->createTokenHandler($container, $firewallName, $config['token_handler'], $userProviderId);
        $container->setDefinition($authenticatorId, new ChildDefinition('security.authenticator.access_token'))->replaceArgument(0, new Reference($tokenHandlerId))->replaceArgument(1, new Reference($extractorId))->replaceArgument(2, $userProviderId ? new Reference($userProviderId) : null)->replaceArgument(3, $successHandler)->replaceArgument(4, $failureHandler)->replaceArgument(5, $config['realm']);
        return $authenticatorId;
    }
    /**
     * @param array<string> $extractors
     */
    private function createExtractor(ContainerBuilder $container, string $firewallName, array $extractors): string
    {
        $aliases = ['query_string' => 'security.access_token_extractor.query_string', 'request_body' => 'security.access_token_extractor.request_body', 'header' => 'security.access_token_extractor.header'];
        $extractors = array_map(fn($extractor) => $aliases[$extractor] ?? $extractor, $extractors);
        if (1 === \count($extractors)) {
            return current($extractors);
        }
        $extractorId = \sprintf('security.authenticator.access_token.chain_extractor.%s', $firewallName);
        $container->setDefinition($extractorId, new ChildDefinition('security.authenticator.access_token.chain_extractor'))->replaceArgument(0, array_map(fn(string $extractorId): Reference => new Reference($extractorId), $extractors));
        return $extractorId;
    }
    private function createTokenHandler(ContainerBuilder $container, string $firewallName, array $config, ?string $userProviderId): string
    {
        $key = array_keys($config)[0];
        $id = \sprintf('security.access_token_handler.%s', $firewallName);
        foreach ($this->tokenHandlerFactories as $factory) {
            if ($key !== $factory->getKey()) {
                continue;
            }
            $factory->create($container, $id, $config[$key], $userProviderId);
        }
        return $id;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Bundle\SecurityBundle\DependencyInjection\Security\Factory;

use _ContaoManager\Symfony\Component\Config\Definition\Builder\NodeDefinition;
use _ContaoManager\Symfony\Component\Config\Definition\Exception\InvalidConfigurationException;
use _ContaoManager\Symfony\Component\DependencyInjection\ChildDefinition;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerBuilder;
use _ContaoManager\Symfony\Component\DependencyInjection\Reference;
/**
 * FormLoginFactory creates services for form login authentication.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 *
 * @internal
 */
class FormLoginFactory extends AbstractFactory
{
    public const PRIORITY = -30;
    public function __construct()
    {
        $this->addOption('username_parameter', '_username');
        $this->addOption('password_parameter', '_password');
        $this->addOption('csrf_parameter', '_csrf_token');
        $this->addOption('csrf_token_id', 'authenticate');
        $this->addOption('enable_csrf', \false);
        $this->addOption('post_only', \true);
        $this->addOption('form_only', \false);
    }
    public function getPriority(): int
    {
        return self::PRIORITY;
    }
    public function getKey(): string
    {
        return 'form-login';
    }
    public function addConfiguration(NodeDefinition $node): void
    {
        parent::addConfiguration($node);
        $node->children()->scalarNode('csrf_token_generator')->cannotBeEmpty()->end()->end();
    }
    public function createAuthenticator(ContainerBuilder $container, string $firewallName, array $config, string $userProviderId): string
    {
        if (isset($config['csrf_token_generator'])) {
            throw new InvalidConfigurationException('The "csrf_token_generator" on "form_login" does not exist, use "enable_csrf" instead.');
        }
        $authenticatorId = 'security.authenticator.form_login.' . $firewallName;
        $options = array_intersect_key($config, $this->options);
        $authenticator = $container->setDefinition($authenticatorId, new ChildDefinition('security.authenticator.form_login'))->replaceArgument(1, new Reference($userProviderId))->replaceArgument(2, new Reference($this->createAuthenticationSuccessHandler($container, $firewallName, $config)))->replaceArgument(3, new Reference($this->createAuthenticationFailureHandler($container, $firewallName, $config)))->replaceArgument(4, $options);
        if ($options['use_forward'] ?? \false) {
            $authenticator->addMethodCall('setHttpKernel', [new Reference('http_kernel')]);
        }
        return $authenticatorId;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Bundle\SecurityBundle\DependencyInjection\Security\Factory;

use _ContaoManager\Symfony\Component\Config\Definition\Builder\NodeDefinition;
/**
 * FormLoginLdapFactory creates services for form login ldap authentication.
 *
 * @author Grégoire Pineau <lyrixx@lyrixx.info>
 * @author Charles Sarrazin <charles@sarraz.in>
 *
 * @internal
 */
class FormLoginLdapFactory extends FormLoginFactory
{
    use LdapFactoryTrait;
    public function addConfiguration(NodeDefinition $node): void
    {
        parent::addConfiguration($node);
        $node->children()->scalarNode('service')->defaultValue('ldap')->end()->scalarNode('dn_string')->defaultValue('{username}')->end()->scalarNode('query_string')->end()->scalarNode('search_dn')->defaultValue('')->end()->scalarNode('search_password')->defaultValue('')->end()->end();
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Bundle\SecurityBundle\DependencyInjection\Security\Factory;

use _ContaoManager\Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition;
use _ContaoManager\Symfony\Component\Config\Definition\Builder\NodeDefinition;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerBuilder;
/**
 * @author Wouter de Jong <wouter@wouterj.nl>
 *
 * @internal
 */
class CustomAuthenticatorFactory implements AuthenticatorFactoryInterface
{
    public function getPriority(): int
    {
        return 0;
    }
    public function getKey(): string
    {
        return 'custom_authenticators';
    }
    /**
     * @param ArrayNodeDefinition $builder
     */
    public function addConfiguration(NodeDefinition $builder): void
    {
        $builder->info('An array of service ids for all of your "authenticators"')->requiresAtLeastOneElement()->prototype('scalar')->end();
        // get the parent array node builder ("firewalls") from inside the children builder
        $factoryRootNode = $builder->end()->end();
        $factoryRootNode->fixXmlConfig('custom_authenticator')->validate()->ifTrue(fn($v) => isset($v['custom_authenticators']) && empty($v['custom_authenticators']))->then(function ($v) {
            unset($v['custom_authenticators']);
            return $v;
        })->end();
    }
    public function createAuthenticator(ContainerBuilder $container, string $firewallName, array $config, string $userProviderId): array
    {
        return $config;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Bundle\SecurityBundle\DependencyInjection\Security\Factory;

use _ContaoManager\Symfony\Component\Config\Definition\Builder\NodeDefinition;
use _ContaoManager\Symfony\Component\DependencyInjection\ChildDefinition;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerBuilder;
use _ContaoManager\Symfony\Component\DependencyInjection\Reference;
/**
 * RemoteUserFactory creates services for REMOTE_USER based authentication.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 * @author Maxime Douailin <maxime.douailin@gmail.com>
 *
 * @internal
 */
class RemoteUserFactory implements AuthenticatorFactoryInterface
{
    public const PRIORITY = -10;
    public function createAuthenticator(ContainerBuilder $container, string $firewallName, array $config, string $userProviderId): string
    {
        $authenticatorId = 'security.authenticator.remote_user.' . $firewallName;
        $container->setDefinition($authenticatorId, new ChildDefinition('security.authenticator.remote_user'))->replaceArgument(0, new Reference($userProviderId))->replaceArgument(2, $firewallName)->replaceArgument(3, $config['user']);
        return $authenticatorId;
    }
    public function getPriority(): int
    {
        return self::PRIORITY;
    }
    public function getKey(): string
    {
        return 'remote-user';
    }
    public function addConfiguration(NodeDefinition $node): void
    {
        $node->children()->scalarNode('provider')->end()->scalarNode('user')->defaultValue('REMOTE_USER')->end()->end();
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Bundle\SecurityBundle\DependencyInjection\Security\Factory;

use _ContaoManager\Symfony\Component\Config\Definition\Builder\NodeDefinition;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerBuilder;
/**
 * @author Wouter de Jong <wouter@wouterj.nl>
 */
interface AuthenticatorFactoryInterface
{
    /**
     * Defines the priority at which the authenticator is called.
     */
    public function getPriority(): int;
    /**
     * Defines the configuration key used to reference the provider
     * in the firewall configuration.
     */
    public function getKey(): string;
    /**
     * @return void
     */
    public function addConfiguration(NodeDefinition $builder);
    /**
     * Creates the authenticator service(s) for the provided configuration.
     *
     * @param array<string, mixed> $config
     *
     * @return string|string[] The authenticator service ID(s) to be used by the firewall
     */
    public function createAuthenticator(ContainerBuilder $container, string $firewallName, array $config, string $userProviderId): string|array;
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Bundle\SecurityBundle\DependencyInjection\Security\Factory;

use _ContaoManager\Symfony\Bridge\Doctrine\Security\RememberMe\DoctrineTokenProvider;
use _ContaoManager\Symfony\Bundle\SecurityBundle\RememberMe\DecoratedRememberMeHandler;
use _ContaoManager\Symfony\Component\Config\Definition\Builder\NodeDefinition;
use _ContaoManager\Symfony\Component\Config\Definition\Exception\InvalidConfigurationException;
use _ContaoManager\Symfony\Component\Config\FileLocator;
use _ContaoManager\Symfony\Component\DependencyInjection\ChildDefinition;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerBuilder;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Extension\PrependExtensionInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Loader\PhpFileLoader;
use _ContaoManager\Symfony\Component\DependencyInjection\Reference;
use _ContaoManager\Symfony\Component\HttpFoundation\Cookie;
use _ContaoManager\Symfony\Component\Security\Core\Authentication\RememberMe\CacheTokenVerifier;
/**
 * @internal
 */
class RememberMeFactory implements AuthenticatorFactoryInterface, PrependExtensionInterface
{
    public const PRIORITY = -50;
    protected $options = ['name' => 'REMEMBERME', 'lifetime' => 31536000, 'path' => '/', 'domain' => null, 'secure' => \false, 'httponly' => \true, 'samesite' => null, 'always_remember_me' => \false, 'remember_me_parameter' => '_remember_me'];
    public function createAuthenticator(ContainerBuilder $container, string $firewallName, array $config, string $userProviderId): string
    {
        if (!$container->hasDefinition('security.authenticator.remember_me')) {
            $loader = new PhpFileLoader($container, new FileLocator(\dirname(__DIR__) . '/../../Resources/config'));
            $loader->load('security_authenticator_remember_me.php');
        }
        if ('auto' === $config['secure']) {
            $config['secure'] = null;
        }
        // create remember me handler (which manage the remember-me cookies)
        $rememberMeHandlerId = 'security.authenticator.remember_me_handler.' . $firewallName;
        if (isset($config['service']) && isset($config['token_provider'])) {
            throw new InvalidConfigurationException(\sprintf('You cannot use both "service" and "token_provider" in "security.firewalls.%s.remember_me".', $firewallName));
        }
        if (isset($config['service'])) {
            $container->register($rememberMeHandlerId, DecoratedRememberMeHandler::class)->addArgument(new Reference($config['service']))->addTag('security.remember_me_handler', ['firewall' => $firewallName]);
        } elseif (isset($config['token_provider'])) {
            $tokenProviderId = $this->createTokenProvider($container, $firewallName, $config['token_provider']);
            $tokenVerifier = $this->createTokenVerifier($container, $firewallName, $config['token_verifier'] ?? null);
            $container->setDefinition($rememberMeHandlerId, new ChildDefinition('security.authenticator.persistent_remember_me_handler'))->replaceArgument(0, new Reference($tokenProviderId))->replaceArgument(1, new Reference($userProviderId))->replaceArgument(3, $config)->replaceArgument(5, $tokenVerifier)->addTag('security.remember_me_handler', ['firewall' => $firewallName]);
        } else {
            $signatureHasherId = 'security.authenticator.remember_me_signature_hasher.' . $firewallName;
            $container->setDefinition($signatureHasherId, new ChildDefinition('security.authenticator.remember_me_signature_hasher'))->replaceArgument(1, $config['signature_properties'])->replaceArgument(2, $config['secret']);
            $container->setDefinition($rememberMeHandlerId, new ChildDefinition('security.authenticator.signature_remember_me_handler'))->replaceArgument(0, new Reference($signatureHasherId))->replaceArgument(1, new Reference($userProviderId))->replaceArgument(3, $config)->addTag('security.remember_me_handler', ['firewall' => $firewallName]);
        }
        // create check remember me conditions listener (which checks if a remember-me cookie is supported and requested)
        $rememberMeConditionsListenerId = 'security.listener.check_remember_me_conditions.' . $firewallName;
        $container->setDefinition($rememberMeConditionsListenerId, new ChildDefinition('security.listener.check_remember_me_conditions'))->replaceArgument(0, array_intersect_key($config, ['always_remember_me' => \true, 'remember_me_parameter' => \true]))->addTag('kernel.event_subscriber', ['dispatcher' => 'security.event_dispatcher.' . $firewallName]);
        // create remember me listener (which executes the remember me services for other authenticators and logout)
        $rememberMeListenerId = 'security.listener.remember_me.' . $firewallName;
        $container->setDefinition($rememberMeListenerId, new ChildDefinition('security.listener.remember_me'))->replaceArgument(0, new Reference($rememberMeHandlerId))->addTag('kernel.event_subscriber', ['dispatcher' => 'security.event_dispatcher.' . $firewallName]);
        // create remember me authenticator (which re-authenticates the user based on the remember-me cookie)
        $authenticatorId = 'security.authenticator.remember_me.' . $firewallName;
        $container->setDefinition($authenticatorId, new ChildDefinition('security.authenticator.remember_me'))->replaceArgument(0, new Reference($rememberMeHandlerId))->replaceArgument(3, $config['name'] ?? $this->options['name']);
        return $authenticatorId;
    }
    public function getPriority(): int
    {
        return self::PRIORITY;
    }
    public function getKey(): string
    {
        return 'remember-me';
    }
    public function addConfiguration(NodeDefinition $node): void
    {
        $builder = $node->fixXmlConfig('user_provider')->children();
        $builder->scalarNode('secret')->cannotBeEmpty()->defaultValue('%kernel.secret%')->end()->scalarNode('service')->end()->arrayNode('user_providers')->beforeNormalization()->ifString()->then(fn($v) => [$v])->end()->prototype('scalar')->end()->end()->booleanNode('catch_exceptions')->defaultTrue()->end()->arrayNode('signature_properties')->prototype('scalar')->end()->requiresAtLeastOneElement()->info('An array of properties on your User that are used to sign the remember-me cookie. If any of these change, all existing cookies will become invalid.')->example(['email', 'password'])->defaultValue(['password'])->end()->arrayNode('token_provider')->beforeNormalization()->ifString()->then(fn($v) => ['service' => $v])->end()->children()->scalarNode('service')->info('The service ID of a custom rememberme token provider.')->end()->arrayNode('doctrine')->canBeEnabled()->children()->scalarNode('connection')->defaultNull()->end()->end()->end()->end()->end()->scalarNode('token_verifier')->info('The service ID of a custom rememberme token verifier.')->end();
        foreach ($this->options as $name => $value) {
            if ('secure' === $name) {
                $builder->enumNode($name)->values([\true, \false, 'auto'])->defaultValue('auto' === $value ? null : $value);
            } elseif ('samesite' === $name) {
                $builder->enumNode($name)->values([null, Cookie::SAMESITE_LAX, Cookie::SAMESITE_STRICT, Cookie::SAMESITE_NONE])->defaultValue($value);
            } elseif (\is_bool($value)) {
                $builder->booleanNode($name)->defaultValue($value);
            } elseif (\is_int($value)) {
                $builder->integerNode($name)->defaultValue($value);
            } else {
                $builder->scalarNode($name)->defaultValue($value);
            }
        }
    }
    private function createTokenProvider(ContainerBuilder $container, string $firewallName, array $config): string
    {
        $tokenProviderId = $config['service'] ?? \false;
        if ($config['doctrine']['enabled'] ?? \false) {
            if (!class_exists(DoctrineTokenProvider::class)) {
                throw new InvalidConfigurationException('Cannot use the "doctrine" token provider for "remember_me" because the Doctrine Bridge is not installed. Try running "composer require symfony/doctrine-bridge".');
            }
            if (null === $config['doctrine']['connection']) {
                $connectionId = 'database_connection';
            } else {
                $connectionId = 'doctrine.dbal.' . $config['doctrine']['connection'] . '_connection';
            }
            $tokenProviderId = 'security.remember_me.doctrine_token_provider.' . $firewallName;
            $container->register($tokenProviderId, DoctrineTokenProvider::class)->addArgument(new Reference($connectionId));
        }
        if (!$tokenProviderId) {
            throw new InvalidConfigurationException(\sprintf('No token provider was set for firewall "%s". Either configure a service ID or set "remember_me.token_provider.doctrine" to true.', $firewallName));
        }
        return $tokenProviderId;
    }
    private function createTokenVerifier(ContainerBuilder $container, string $firewallName, ?string $serviceId): Reference
    {
        if ($serviceId) {
            return new Reference($serviceId);
        }
        $tokenVerifierId = 'security.remember_me.token_verifier.' . $firewallName;
        $container->register($tokenVerifierId, CacheTokenVerifier::class)->addArgument(new Reference('cache.security_token_verifier', ContainerInterface::NULL_ON_INVALID_REFERENCE))->addArgument(60)->addArgument('rememberme-' . $firewallName . '-stale-');
        return new Reference($tokenVerifierId, ContainerInterface::NULL_ON_INVALID_REFERENCE);
    }
    public function prepend(ContainerBuilder $container): void
    {
        $rememberMeSecureDefault = \false;
        $rememberMeSameSiteDefault = null;
        if (!isset($container->getExtensions()['framework'])) {
            return;
        }
        foreach ($container->getExtensionConfig('framework') as $config) {
            if (isset($config['session']) && \is_array($config['session'])) {
                $rememberMeSecureDefault = $config['session']['cookie_secure'] ?? $rememberMeSecureDefault;
                $rememberMeSameSiteDefault = \array_key_exists('cookie_samesite', $config['session']) ? $config['session']['cookie_samesite'] : $rememberMeSameSiteDefault;
            }
        }
        $this->options['secure'] = $rememberMeSecureDefault;
        $this->options['samesite'] = $rememberMeSameSiteDefault;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Bundle\SecurityBundle\DependencyInjection\Security\Factory;

use _ContaoManager\Symfony\Component\Config\Definition\Builder\NodeDefinition;
use _ContaoManager\Symfony\Component\DependencyInjection\ChildDefinition;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerBuilder;
/**
 * @author Fabien Potencier <fabien@symfony.com>
 * @author Lukas Kahwe Smith <smith@pooteeweet.org>
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
abstract class AbstractFactory implements AuthenticatorFactoryInterface
{
    protected $options = ['check_path' => '/login_check', 'use_forward' => \false, 'require_previous_session' => \false, 'login_path' => '/login'];
    protected $defaultSuccessHandlerOptions = ['always_use_default_target_path' => \false, 'default_target_path' => '/', 'login_path' => '/login', 'target_path_parameter' => '_target_path', 'use_referer' => \false];
    protected $defaultFailureHandlerOptions = ['failure_path' => null, 'failure_forward' => \false, 'login_path' => '/login', 'failure_path_parameter' => '_failure_path'];
    final public function addOption(string $name, mixed $default = null): void
    {
        $this->options[$name] = $default;
    }
    /**
     * @return void
     */
    public function addConfiguration(NodeDefinition $node)
    {
        $builder = $node->children();
        $builder->scalarNode('provider')->end()->booleanNode('remember_me')->defaultTrue()->end()->scalarNode('success_handler')->end()->scalarNode('failure_handler')->end();
        foreach (array_merge($this->options, $this->defaultSuccessHandlerOptions, $this->defaultFailureHandlerOptions) as $name => $default) {
            if ('require_previous_session' === $name) {
                $builder->booleanNode($name)->setDeprecated('symfony/security-bundle', '6.4', 'Option "%node%" at "%path%" is deprecated, it will be removed in version 7.0. Setting it has no effect anymore.')->defaultValue($default);
            } elseif (\is_bool($default)) {
                $builder->booleanNode($name)->defaultValue($default);
            } else {
                $builder->scalarNode($name)->defaultValue($default);
            }
        }
    }
    /**
     * @return string
     */
    protected function createAuthenticationSuccessHandler(ContainerBuilder $container, string $id, array $config)
    {
        $successHandlerId = $this->getSuccessHandlerId($id);
        $options = array_intersect_key($config, $this->defaultSuccessHandlerOptions);
        if (isset($config['success_handler'])) {
            $successHandler = $container->setDefinition($successHandlerId, new ChildDefinition('security.authentication.custom_success_handler'));
            $successHandler->replaceArgument(0, new ChildDefinition($config['success_handler']));
            $successHandler->replaceArgument(1, $options);
            $successHandler->replaceArgument(2, $id);
        } else {
            $successHandler = $container->setDefinition($successHandlerId, new ChildDefinition('security.authentication.success_handler'));
            $successHandler->addMethodCall('setOptions', [$options]);
            $successHandler->addMethodCall('setFirewallName', [$id]);
        }
        return $successHandlerId;
    }
    /**
     * @return string
     */
    protected function createAuthenticationFailureHandler(ContainerBuilder $container, string $id, array $config)
    {
        $id = $this->getFailureHandlerId($id);
        $options = array_intersect_key($config, $this->defaultFailureHandlerOptions);
        if (isset($config['failure_handler'])) {
            $failureHandler = $container->setDefinition($id, new ChildDefinition('security.authentication.custom_failure_handler'));
            $failureHandler->replaceArgument(0, new ChildDefinition($config['failure_handler']));
            $failureHandler->replaceArgument(1, $options);
        } else {
            $failureHandler = $container->setDefinition($id, new ChildDefinition('security.authentication.failure_handler'));
            $failureHandler->addMethodCall('setOptions', [$options]);
        }
        return $id;
    }
    /**
     * @return string
     */
    protected function getSuccessHandlerId(string $id)
    {
        return 'security.authentication.success_handler.' . $id . '.' . str_replace('-', '_', $this->getKey());
    }
    /**
     * @return string
     */
    protected function getFailureHandlerId(string $id)
    {
        return 'security.authentication.failure_handler.' . $id . '.' . str_replace('-', '_', $this->getKey());
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Bundle\SecurityBundle\DependencyInjection\Security\Factory;

use _ContaoManager\Symfony\Component\Config\Definition\Builder\NodeDefinition;
use _ContaoManager\Symfony\Component\DependencyInjection\ChildDefinition;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerBuilder;
use _ContaoManager\Symfony\Component\DependencyInjection\Reference;
/**
 * X509Factory creates services for X509 certificate authentication.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 *
 * @internal
 */
class X509Factory implements AuthenticatorFactoryInterface
{
    public const PRIORITY = -10;
    public function createAuthenticator(ContainerBuilder $container, string $firewallName, array $config, string $userProviderId): string
    {
        $authenticatorId = 'security.authenticator.x509.' . $firewallName;
        $container->setDefinition($authenticatorId, new ChildDefinition('security.authenticator.x509'))->replaceArgument(0, new Reference($userProviderId))->replaceArgument(2, $firewallName)->replaceArgument(3, $config['user'])->replaceArgument(4, $config['credentials'])->replaceArgument(6, $config['user_identifier']);
        return $authenticatorId;
    }
    public function getPriority(): int
    {
        return self::PRIORITY;
    }
    public function getKey(): string
    {
        return 'x509';
    }
    public function addConfiguration(NodeDefinition $node): void
    {
        $node->children()->scalarNode('provider')->end()->scalarNode('user')->defaultValue('SSL_CLIENT_S_DN_Email')->end()->scalarNode('credentials')->defaultValue('SSL_CLIENT_S_DN')->end()->scalarNode('user_identifier')->defaultValue('emailAddress')->end()->end();
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Bundle\SecurityBundle\DependencyInjection\Security\Factory;

use _ContaoManager\Jose\Component\Core\Algorithm as AlgorithmInterface;
use _ContaoManager\Jose\Component\Signature\Algorithm;
use _ContaoManager\Symfony\Component\Security\Core\Exception\InvalidArgumentException;
use _ContaoManager\Symfony\Component\Security\Http\AccessToken\Oidc\OidcTokenHandler;
/**
 * Creates a signature algorithm for {@see OidcTokenHandler}.
 *
 * @internal
 */
final class SignatureAlgorithmFactory
{
    public static function create(string $algorithm): AlgorithmInterface
    {
        switch ($algorithm) {
            case 'ES256':
            case 'ES384':
            case 'ES512':
                if (!class_exists(Algorithm::class . '\\' . $algorithm)) {
                    throw new \LogicException(\sprintf('You cannot use the "%s" signature algorithm since "web-token/jwt-signature-algorithm-ecdsa" is not installed. Try running "composer require web-token/jwt-signature-algorithm-ecdsa".', $algorithm));
                }
                $algorithm = Algorithm::class . '\\' . $algorithm;
                return new $algorithm();
        }
        throw new InvalidArgumentException(\sprintf('Unsupported signature algorithm "%s". Only ES* algorithms are supported. If you want to use another algorithm, create your TokenHandler as a service.', $algorithm));
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Bundle\SecurityBundle\DependencyInjection\Security\Factory;

use _ContaoManager\Symfony\Component\DependencyInjection\ContainerBuilder;
/**
 * Can be implemented by a security factory to add a listener to the firewall.
 *
 * @author Christian Scheb <me@christianscheb.de>
 */
interface FirewallListenerFactoryInterface
{
    /**
     * Creates the firewall listener services for the provided configuration.
     *
     * @param array<string, mixed> $config
     *
     * @return string[] The listener service IDs to be used by the firewall
     */
    public function createListeners(ContainerBuilder $container, string $firewallName, array $config): array;
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Bundle\SecurityBundle\DependencyInjection\Security\Factory;

use _ContaoManager\Symfony\Component\DependencyInjection\ChildDefinition;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerBuilder;
use _ContaoManager\Symfony\Component\DependencyInjection\Reference;
/**
 * JsonLoginFactory creates services for JSON login authentication.
 *
 * @author Kévin Dunglas <dunglas@gmail.com>
 *
 * @internal
 */
class JsonLoginFactory extends AbstractFactory
{
    public const PRIORITY = -40;
    public function __construct()
    {
        $this->addOption('username_path', 'username');
        $this->addOption('password_path', 'password');
        $this->defaultFailureHandlerOptions = [];
        $this->defaultSuccessHandlerOptions = [];
    }
    public function getPriority(): int
    {
        return self::PRIORITY;
    }
    public function getKey(): string
    {
        return 'json-login';
    }
    public function createAuthenticator(ContainerBuilder $container, string $firewallName, array $config, string $userProviderId): string
    {
        $authenticatorId = 'security.authenticator.json_login.' . $firewallName;
        $options = array_intersect_key($config, $this->options);
        $container->setDefinition($authenticatorId, new ChildDefinition('security.authenticator.json_login'))->replaceArgument(1, new Reference($userProviderId))->replaceArgument(2, isset($config['success_handler']) ? new Reference($this->createAuthenticationSuccessHandler($container, $firewallName, $config)) : null)->replaceArgument(3, isset($config['failure_handler']) ? new Reference($this->createAuthenticationFailureHandler($container, $firewallName, $config)) : null)->replaceArgument(4, $options);
        return $authenticatorId;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Bundle\SecurityBundle\DependencyInjection\Security\Factory;

use _ContaoManager\Symfony\Component\DependencyInjection\ContainerBuilder;
/**
 * Stateless authenticators are authenticators that can work without a user provider.
 *
 * This situation can only occur in stateless firewalls, as statefull firewalls
 * need the user provider to refresh the user in each subsequent request. A
 * stateless authenticator can be used on both stateless and statefull authenticators.
 *
 * @author Wouter de Jong <wouter@wouterj.nl>
 */
interface StatelessAuthenticatorFactoryInterface extends AuthenticatorFactoryInterface
{
    public function createAuthenticator(ContainerBuilder $container, string $firewallName, array $config, ?string $userProviderId): string|array;
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Bundle\SecurityBundle\DependencyInjection\Security\Factory;

use _ContaoManager\Symfony\Component\Config\Definition\Builder\NodeDefinition;
use _ContaoManager\Symfony\Component\DependencyInjection\ChildDefinition;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerBuilder;
use _ContaoManager\Symfony\Component\DependencyInjection\Reference;
/**
 * HttpBasicFactory creates services for HTTP basic authentication.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 *
 * @internal
 */
class HttpBasicFactory implements AuthenticatorFactoryInterface
{
    public const PRIORITY = -50;
    public function createAuthenticator(ContainerBuilder $container, string $firewallName, array $config, string $userProviderId): string
    {
        $authenticatorId = 'security.authenticator.http_basic.' . $firewallName;
        $container->setDefinition($authenticatorId, new ChildDefinition('security.authenticator.http_basic'))->replaceArgument(0, $config['realm'])->replaceArgument(1, new Reference($userProviderId));
        return $authenticatorId;
    }
    public function getPriority(): int
    {
        return self::PRIORITY;
    }
    public function getKey(): string
    {
        return 'http-basic';
    }
    public function addConfiguration(NodeDefinition $node): void
    {
        $node->children()->scalarNode('provider')->end()->scalarNode('realm')->defaultValue('Secured Area')->end()->end();
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Bundle\SecurityBundle\DependencyInjection\Security\Factory;

use _ContaoManager\Symfony\Component\Config\Definition\Exception\InvalidConfigurationException;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerBuilder;
use _ContaoManager\Symfony\Component\DependencyInjection\Definition;
use _ContaoManager\Symfony\Component\DependencyInjection\Reference;
use _ContaoManager\Symfony\Component\Ldap\Security\CheckLdapCredentialsListener;
use _ContaoManager\Symfony\Component\Ldap\Security\LdapAuthenticator;
/**
 * A trait decorating the authenticator with LDAP functionality.
 *
 * @author Wouter de Jong <wouter@wouterj.nl>
 *
 * @internal
 */
trait LdapFactoryTrait
{
    public function getKey(): string
    {
        return parent::getKey() . '-ldap';
    }
    public function createAuthenticator(ContainerBuilder $container, string $firewallName, array $config, string $userProviderId): string
    {
        $key = str_replace('-', '_', $this->getKey());
        $authenticatorId = parent::createAuthenticator($container, $firewallName, $config, $userProviderId);
        $container->setDefinition('security.listener.' . $key . '.' . $firewallName, new Definition(CheckLdapCredentialsListener::class))->addTag('kernel.event_subscriber', ['dispatcher' => 'security.event_dispatcher.' . $firewallName])->addArgument(new Reference('security.ldap_locator'));
        $ldapAuthenticatorId = 'security.authenticator.' . $key . '.' . $firewallName;
        $definition = $container->setDefinition($ldapAuthenticatorId, new Definition(LdapAuthenticator::class))->setArguments([new Reference($authenticatorId), $config['service'], $config['dn_string'], $config['search_dn'], $config['search_password']]);
        if (!empty($config['query_string'])) {
            if ('' === $config['search_dn'] || '' === $config['search_password']) {
                throw new InvalidConfigurationException('Using the "query_string" config without using a "search_dn" and a "search_password" is not supported.');
            }
            $definition->addArgument($config['query_string']);
        }
        return $ldapAuthenticatorId;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Bundle\SecurityBundle\DependencyInjection\Security\Factory;

use _ContaoManager\Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition;
use _ContaoManager\Symfony\Component\Config\Definition\Builder\NodeDefinition;
use _ContaoManager\Symfony\Component\DependencyInjection\ChildDefinition;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerBuilder;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\LogicException;
use _ContaoManager\Symfony\Component\DependencyInjection\Reference;
use _ContaoManager\Symfony\Component\HttpFoundation\RateLimiter\RequestRateLimiterInterface;
use _ContaoManager\Symfony\Component\Lock\LockInterface;
use _ContaoManager\Symfony\Component\RateLimiter\RateLimiterFactory;
use _ContaoManager\Symfony\Component\RateLimiter\Storage\CacheStorage;
use _ContaoManager\Symfony\Component\Security\Http\RateLimiter\DefaultLoginRateLimiter;
/**
 * @author Wouter de Jong <wouter@wouterj.nl>
 *
 * @internal
 */
class LoginThrottlingFactory implements AuthenticatorFactoryInterface
{
    public function getPriority(): int
    {
        // this factory doesn't register any authenticators, this priority doesn't matter
        return 0;
    }
    public function getKey(): string
    {
        return 'login_throttling';
    }
    /**
     * @param ArrayNodeDefinition $builder
     */
    public function addConfiguration(NodeDefinition $builder): void
    {
        $builder->children()->scalarNode('limiter')->info(\sprintf('A service id implementing "%s".', RequestRateLimiterInterface::class))->end()->integerNode('max_attempts')->defaultValue(5)->end()->scalarNode('interval')->defaultValue('1 minute')->end()->scalarNode('lock_factory')->info('The service ID of the lock factory used by the login rate limiter (or null to disable locking)')->defaultNull()->end()->end();
    }
    public function createAuthenticator(ContainerBuilder $container, string $firewallName, array $config, string $userProviderId): array
    {
        if (!class_exists(RateLimiterFactory::class)) {
            throw new \LogicException('Login throttling requires the Rate Limiter component. Try running "composer require symfony/rate-limiter".');
        }
        if (!isset($config['limiter'])) {
            $limiterOptions = ['policy' => 'fixed_window', 'limit' => $config['max_attempts'], 'interval' => $config['interval'], 'lock_factory' => $config['lock_factory']];
            $this->registerRateLimiter($container, $localId = '_login_local_' . $firewallName, $limiterOptions);
            $limiterOptions['limit'] = 5 * $config['max_attempts'];
            $this->registerRateLimiter($container, $globalId = '_login_global_' . $firewallName, $limiterOptions);
            $container->register($config['limiter'] = 'security.login_throttling.' . $firewallName . '.limiter', DefaultLoginRateLimiter::class)->addArgument(new Reference('limiter.' . $globalId))->addArgument(new Reference('limiter.' . $localId))->addArgument('%kernel.secret%');
        }
        $container->setDefinition('security.listener.login_throttling.' . $firewallName, new ChildDefinition('security.listener.login_throttling'))->replaceArgument(1, new Reference($config['limiter']))->addTag('kernel.event_subscriber', ['dispatcher' => 'security.event_dispatcher.' . $firewallName]);
        return [];
    }
    private function registerRateLimiter(ContainerBuilder $container, string $name, array $limiterConfig): void
    {
        // default configuration (when used by other DI extensions)
        $limiterConfig += ['lock_factory' => 'lock.factory', 'cache_pool' => 'cache.rate_limiter'];
        $limiter = $container->setDefinition($limiterId = 'limiter.' . $name, new ChildDefinition('limiter'));
        if (null !== $limiterConfig['lock_factory']) {
            if (!interface_exists(LockInterface::class)) {
                throw new LogicException(\sprintf('Rate limiter "%s" requires the Lock component to be installed. Try running "composer require symfony/lock".', $name));
            }
            $limiter->replaceArgument(2, new Reference($limiterConfig['lock_factory']));
        }
        unset($limiterConfig['lock_factory']);
        if (null === $storageId = $limiterConfig['storage_service'] ?? null) {
            $container->register($storageId = 'limiter.storage.' . $name, CacheStorage::class)->addArgument(new Reference($limiterConfig['cache_pool']));
        }
        $limiter->replaceArgument(1, new Reference($storageId));
        unset($limiterConfig['storage_service'], $limiterConfig['cache_pool']);
        $limiterConfig['id'] = $name;
        $limiter->replaceArgument(0, $limiterConfig);
        $container->registerAliasForArgument($limiterId, RateLimiterFactory::class, $name . '.limiter');
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Bundle\SecurityBundle\DependencyInjection;

use _ContaoManager\Symfony\Bridge\Twig\Extension\LogoutUrlExtension;
use _ContaoManager\Symfony\Bundle\SecurityBundle\DependencyInjection\Security\Factory\AuthenticatorFactoryInterface;
use _ContaoManager\Symfony\Bundle\SecurityBundle\DependencyInjection\Security\Factory\FirewallListenerFactoryInterface;
use _ContaoManager\Symfony\Bundle\SecurityBundle\DependencyInjection\Security\Factory\StatelessAuthenticatorFactoryInterface;
use _ContaoManager\Symfony\Bundle\SecurityBundle\DependencyInjection\Security\UserProvider\UserProviderFactoryInterface;
use _ContaoManager\Symfony\Bundle\SecurityBundle\SecurityBundle;
use _ContaoManager\Symfony\Component\Config\Definition\ConfigurationInterface;
use _ContaoManager\Symfony\Component\Config\Definition\Exception\InvalidConfigurationException;
use _ContaoManager\Symfony\Component\Config\FileLocator;
use _ContaoManager\Symfony\Component\Console\Application;
use _ContaoManager\Symfony\Component\DependencyInjection\Alias;
use _ContaoManager\Symfony\Component\DependencyInjection\Argument\IteratorArgument;
use _ContaoManager\Symfony\Component\DependencyInjection\Argument\ServiceClosureArgument;
use _ContaoManager\Symfony\Component\DependencyInjection\Argument\TaggedIteratorArgument;
use _ContaoManager\Symfony\Component\DependencyInjection\ChildDefinition;
use _ContaoManager\Symfony\Component\DependencyInjection\Compiler\ServiceLocatorTagPass;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerBuilder;
use _ContaoManager\Symfony\Component\DependencyInjection\Definition;
use _ContaoManager\Symfony\Component\DependencyInjection\Extension\PrependExtensionInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Loader\PhpFileLoader;
use _ContaoManager\Symfony\Component\DependencyInjection\Reference;
use _ContaoManager\Symfony\Component\EventDispatcher\EventDispatcher;
use _ContaoManager\Symfony\Component\ExpressionLanguage\Expression;
use _ContaoManager\Symfony\Component\ExpressionLanguage\ExpressionLanguage;
use _ContaoManager\Symfony\Component\Form\Extension\PasswordHasher\PasswordHasherExtension;
use _ContaoManager\Symfony\Component\HttpFoundation\ChainRequestMatcher;
use _ContaoManager\Symfony\Component\HttpFoundation\RequestMatcher\AttributesRequestMatcher;
use _ContaoManager\Symfony\Component\HttpFoundation\RequestMatcher\HostRequestMatcher;
use _ContaoManager\Symfony\Component\HttpFoundation\RequestMatcher\IpsRequestMatcher;
use _ContaoManager\Symfony\Component\HttpFoundation\RequestMatcher\MethodRequestMatcher;
use _ContaoManager\Symfony\Component\HttpFoundation\RequestMatcher\PathRequestMatcher;
use _ContaoManager\Symfony\Component\HttpFoundation\RequestMatcher\PortRequestMatcher;
use _ContaoManager\Symfony\Component\HttpKernel\DependencyInjection\Extension;
use _ContaoManager\Symfony\Component\HttpKernel\KernelEvents;
use _ContaoManager\Symfony\Component\PasswordHasher\Hasher\NativePasswordHasher;
use _ContaoManager\Symfony\Component\PasswordHasher\Hasher\Pbkdf2PasswordHasher;
use _ContaoManager\Symfony\Component\PasswordHasher\Hasher\PlaintextPasswordHasher;
use _ContaoManager\Symfony\Component\PasswordHasher\Hasher\SodiumPasswordHasher;
use _ContaoManager\Symfony\Component\Routing\Loader\ContainerLoader;
use _ContaoManager\Symfony\Component\Security\Core\Authorization\Strategy\AffirmativeStrategy;
use _ContaoManager\Symfony\Component\Security\Core\Authorization\Strategy\ConsensusStrategy;
use _ContaoManager\Symfony\Component\Security\Core\Authorization\Strategy\PriorityStrategy;
use _ContaoManager\Symfony\Component\Security\Core\Authorization\Strategy\UnanimousStrategy;
use _ContaoManager\Symfony\Component\Security\Core\Authorization\Voter\VoterInterface;
use _ContaoManager\Symfony\Component\Security\Core\User\ChainUserChecker;
use _ContaoManager\Symfony\Component\Security\Core\User\ChainUserProvider;
use _ContaoManager\Symfony\Component\Security\Core\User\UserCheckerInterface;
use _ContaoManager\Symfony\Component\Security\Core\User\UserProviderInterface;
use _ContaoManager\Symfony\Component\Security\Http\Authenticator\Debug\TraceableAuthenticatorManagerListener;
use _ContaoManager\Symfony\Component\Security\Http\Event\CheckPassportEvent;
/**
 * SecurityExtension.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
class SecurityExtension extends Extension implements PrependExtensionInterface
{
    private array $requestMatchers = [];
    private array $expressions = [];
    private array $contextListeners = [];
    /** @var list<array{int, AuthenticatorFactoryInterface}> */
    private array $factories = [];
    /** @var AuthenticatorFactoryInterface[] */
    private array $sortedFactories = [];
    private array $userProviderFactories = [];
    /**
     * @return void
     */
    public function prepend(ContainerBuilder $container)
    {
        foreach ($this->getSortedFactories() as $factory) {
            if ($factory instanceof PrependExtensionInterface) {
                $factory->prepend($container);
            }
        }
    }
    /**
     * @return void
     */
    public function load(array $configs, ContainerBuilder $container)
    {
        if (!array_filter($configs)) {
            trigger_deprecation('symfony/security-bundle', '6.3', 'Enabling bundle "%s" and not configuring it is deprecated.', SecurityBundle::class);
            // uncomment the following line in 7.0
            // throw new InvalidConfigurationException(sprintf('Enabling bundle "%s" and not configuring it is not allowed.', SecurityBundle::class));
            return;
        }
        $mainConfig = $this->getConfiguration($configs, $container);
        $config = $this->processConfiguration($mainConfig, $configs);
        // load services
        $loader = new PhpFileLoader($container, new FileLocator(\dirname(__DIR__) . '/Resources/config'));
        $loader->load('security.php');
        $loader->load('password_hasher.php');
        $loader->load('security_listeners.php');
        if (!$config['enable_authenticator_manager']) {
            throw new InvalidConfigurationException('"security.enable_authenticator_manager" must be set to "true".');
        }
        $loader->load('security_authenticator.php');
        $loader->load('security_authenticator_access_token.php');
        if ($container::willBeAvailable('symfony/twig-bridge', LogoutUrlExtension::class, ['symfony/security-bundle'])) {
            $loader->load('templating_twig.php');
        }
        $loader->load('collectors.php');
        if ($container->hasParameter('kernel.debug') && $container->getParameter('kernel.debug')) {
            $loader->load('security_debug.php');
        }
        if (!$container::willBeAvailable('symfony/expression-language', ExpressionLanguage::class, ['symfony/security-bundle'])) {
            $container->removeDefinition('security.expression_language');
            $container->removeDefinition('security.access.expression_voter');
            $container->removeDefinition('security.is_granted_attribute_expression_language');
        }
        if (!class_exists(PasswordHasherExtension::class)) {
            $container->removeDefinition('form.listener.password_hasher');
            $container->removeDefinition('form.type_extension.form.password_hasher');
            $container->removeDefinition('form.type_extension.password.password_hasher');
        }
        // set some global scalars
        $container->setParameter('security.access.denied_url', $config['access_denied_url']);
        $container->setParameter('security.authentication.manager.erase_credentials', $config['erase_credentials']);
        $container->setParameter('security.authentication.session_strategy.strategy', $config['session_fixation_strategy']);
        if (isset($config['access_decision_manager']['service'])) {
            $container->setAlias('security.access.decision_manager', $config['access_decision_manager']['service']);
        } elseif (isset($config['access_decision_manager']['strategy_service'])) {
            $container->getDefinition('security.access.decision_manager')->addArgument(new Reference($config['access_decision_manager']['strategy_service']));
        } else {
            $container->getDefinition('security.access.decision_manager')->addArgument($this->createStrategyDefinition($config['access_decision_manager']['strategy'] ?? MainConfiguration::STRATEGY_AFFIRMATIVE, $config['access_decision_manager']['allow_if_all_abstain'], $config['access_decision_manager']['allow_if_equal_granted_denied']));
        }
        $container->setParameter('security.authentication.hide_user_not_found', $config['hide_user_not_found']);
        if (class_exists(Application::class)) {
            $loader->load('debug_console.php');
        }
        $this->createFirewalls($config, $container);
        if ($container::willBeAvailable('symfony/routing', ContainerLoader::class, ['symfony/security-bundle'])) {
            $this->createLogoutUrisParameter($config['firewalls'] ?? [], $container);
        } else {
            $container->removeDefinition('security.route_loader.logout');
        }
        $this->createAuthorization($config, $container);
        $this->createRoleHierarchy($config, $container);
        if ($config['password_hashers']) {
            $this->createHashers($config['password_hashers'], $container);
        }
        if (class_exists(Application::class)) {
            $loader->load('console.php');
            $container->getDefinition('security.command.user_password_hash')->replaceArgument(1, array_keys($config['password_hashers']));
        }
        $container->registerForAutoconfiguration(VoterInterface::class)->addTag('security.voter');
        // required for compatibility with Symfony 5.4
        $container->getDefinition('security.access_listener')->setArgument(3, \false);
        $container->getDefinition('security.authorization_checker')->setArgument(2, \false);
        $container->getDefinition('security.authorization_checker')->setArgument(3, \false);
    }
    private function createStrategyDefinition(string $strategy, bool $allowIfAllAbstainDecisions, bool $allowIfEqualGrantedDeniedDecisions): Definition
    {
        return match ($strategy) {
            MainConfiguration::STRATEGY_AFFIRMATIVE => new Definition(AffirmativeStrategy::class, [$allowIfAllAbstainDecisions]),
            MainConfiguration::STRATEGY_CONSENSUS => new Definition(ConsensusStrategy::class, [$allowIfAllAbstainDecisions, $allowIfEqualGrantedDeniedDecisions]),
            MainConfiguration::STRATEGY_UNANIMOUS => new Definition(UnanimousStrategy::class, [$allowIfAllAbstainDecisions]),
            MainConfiguration::STRATEGY_PRIORITY => new Definition(PriorityStrategy::class, [$allowIfAllAbstainDecisions]),
            default => throw new InvalidConfigurationException(\sprintf('The strategy "%s" is not supported.', $strategy)),
        };
    }
    private function createRoleHierarchy(array $config, ContainerBuilder $container): void
    {
        if (!isset($config['role_hierarchy']) || 0 === \count($config['role_hierarchy'])) {
            $container->removeDefinition('security.access.role_hierarchy_voter');
            return;
        }
        $container->setParameter('security.role_hierarchy.roles', $config['role_hierarchy']);
        $container->removeDefinition('security.access.simple_role_voter');
    }
    private function createAuthorization(array $config, ContainerBuilder $container): void
    {
        foreach ($config['access_control'] as $access) {
            if (isset($access['request_matcher'])) {
                if ($access['path'] || $access['host'] || $access['port'] || $access['ips'] || $access['methods'] || $access['attributes'] || $access['route']) {
                    throw new InvalidConfigurationException('The "request_matcher" option should not be specified alongside other options. Consider integrating your constraints inside your RequestMatcher directly.');
                }
                $matcher = new Reference($access['request_matcher']);
            } else {
                $attributes = $access['attributes'];
                if ($access['route']) {
                    if (\array_key_exists('_route', $attributes)) {
                        throw new InvalidConfigurationException('The "route" option should not be specified alongside "attributes._route" option. Use just one of the options.');
                    }
                    $attributes['_route'] = $access['route'];
                }
                $matcher = $this->createRequestMatcher($container, $access['path'], $access['host'], $access['port'], $access['methods'], $access['ips'], $attributes);
            }
            $roles = $access['roles'];
            if ($access['allow_if']) {
                $roles[] = $this->createExpression($container, $access['allow_if']);
            }
            $emptyAccess = 0 === \count(array_filter($access));
            if ($emptyAccess) {
                throw new InvalidConfigurationException('One or more access control items are empty. Did you accidentally add lines only containing a "-" under "security.access_control"?');
            }
            $container->getDefinition('security.access_map')->addMethodCall('add', [$matcher, $roles, $access['requires_channel']]);
        }
        // allow cache warm-up for expressions
        if (\count($this->expressions)) {
            $container->getDefinition('security.cache_warmer.expression')->replaceArgument(0, new IteratorArgument(array_values($this->expressions)));
        } else {
            $container->removeDefinition('security.cache_warmer.expression');
        }
    }
    private function createFirewalls(array $config, ContainerBuilder $container): void
    {
        if (!isset($config['firewalls'])) {
            return;
        }
        $firewalls = $config['firewalls'];
        $providerIds = $this->createUserProviders($config, $container);
        $container->setParameter('security.firewalls', array_keys($firewalls));
        // make the ContextListener aware of the configured user providers
        $contextListenerDefinition = $container->getDefinition('security.context_listener');
        $arguments = $contextListenerDefinition->getArguments();
        $userProviders = [];
        foreach ($providerIds as $userProviderId) {
            $userProviders[] = new Reference($userProviderId);
        }
        $arguments[1] = $userProviderIteratorsArgument = new IteratorArgument($userProviders);
        $contextListenerDefinition->setArguments($arguments);
        $nbUserProviders = \count($userProviders);
        if ($nbUserProviders > 1) {
            $container->setDefinition('security.user_providers', new Definition(ChainUserProvider::class, [$userProviderIteratorsArgument]));
        } elseif (0 === $nbUserProviders) {
            $container->removeDefinition('security.listener.user_provider');
        } else {
            $container->setAlias('security.user_providers', new Alias(current($providerIds)));
        }
        if (1 === \count($providerIds)) {
            $container->setAlias(UserProviderInterface::class, current($providerIds));
        }
        $customUserChecker = \false;
        // load firewall map
        $mapDef = $container->getDefinition('security.firewall.map');
        $map = $authenticationProviders = $contextRefs = $authenticators = [];
        foreach ($firewalls as $name => $firewall) {
            if (isset($firewall['user_checker']) && 'security.user_checker' !== $firewall['user_checker']) {
                $customUserChecker = \true;
            }
            $configId = 'security.firewall.map.config.' . $name;
            [$matcher, $listeners, $exceptionListener, $logoutListener, $firewallAuthenticators] = $this->createFirewall($container, $name, $firewall, $authenticationProviders, $providerIds, $configId);
            if (!$firewallAuthenticators) {
                $authenticators[$name] = null;
            } else {
                $firewallAuthenticatorRefs = [];
                foreach ($firewallAuthenticators as $authenticatorId) {
                    $firewallAuthenticatorRefs[$authenticatorId] = new Reference($authenticatorId);
                }
                $authenticators[$name] = ServiceLocatorTagPass::register($container, $firewallAuthenticatorRefs);
            }
            $contextId = 'security.firewall.map.context.' . $name;
            $isLazy = !$firewall['stateless'] && $firewall['lazy'];
            $context = new ChildDefinition($isLazy ? 'security.firewall.lazy_context' : 'security.firewall.context');
            $context = $container->setDefinition($contextId, $context);
            $context->replaceArgument(0, new IteratorArgument($listeners))->replaceArgument(1, $exceptionListener)->replaceArgument(2, $logoutListener)->replaceArgument(3, new Reference($configId));
            $contextRefs[$contextId] = new Reference($contextId);
            $map[$contextId] = $matcher;
        }
        $container->getDefinition('security.helper')->replaceArgument(1, $authenticators);
        $container->setAlias('security.firewall.context_locator', (string) ServiceLocatorTagPass::register($container, $contextRefs));
        $mapDef->replaceArgument(0, new Reference('security.firewall.context_locator'));
        $mapDef->replaceArgument(1, new IteratorArgument($map));
        // register an autowire alias for the UserCheckerInterface if no custom user checker service is configured
        if (!$customUserChecker) {
            $container->setAlias(UserCheckerInterface::class, new Alias('security.user_checker', \false));
        }
    }
    private function createFirewall(ContainerBuilder $container, string $id, array $firewall, array &$authenticationProviders, array $providerIds, string $configId): array
    {
        $config = $container->setDefinition($configId, new ChildDefinition('security.firewall.config'));
        $config->replaceArgument(0, $id);
        $config->replaceArgument(1, $firewall['user_checker']);
        // Matcher
        $matcher = null;
        if (isset($firewall['request_matcher'])) {
            $matcher = new Reference($firewall['request_matcher']);
        } elseif (isset($firewall['pattern']) || isset($firewall['host'])) {
            $pattern = $firewall['pattern'] ?? null;
            $host = $firewall['host'] ?? null;
            $methods = $firewall['methods'] ?? [];
            $matcher = $this->createRequestMatcher($container, $pattern, $host, null, $methods);
        }
        $config->replaceArgument(2, $matcher ? (string) $matcher : null);
        $config->replaceArgument(3, $firewall['security']);
        // Security disabled?
        if (\false === $firewall['security']) {
            return [$matcher, [], null, null, []];
        }
        $config->replaceArgument(4, $firewall['stateless']);
        $firewallEventDispatcherId = 'security.event_dispatcher.' . $id;
        // Provider id (must be configured explicitly per firewall/authenticator if more than one provider is set)
        $defaultProvider = null;
        if (isset($firewall['provider'])) {
            if (!isset($providerIds[$normalizedName = str_replace('-', '_', $firewall['provider'])])) {
                throw new InvalidConfigurationException(\sprintf('Invalid firewall "%s": user provider "%s" not found.', $id, $firewall['provider']));
            }
            $defaultProvider = $providerIds[$normalizedName];
            $container->setDefinition('security.listener.' . $id . '.user_provider', new ChildDefinition('security.listener.user_provider.abstract'))->addTag('kernel.event_listener', ['dispatcher' => $firewallEventDispatcherId, 'event' => CheckPassportEvent::class, 'priority' => 2048, 'method' => 'checkPassport'])->replaceArgument(0, new Reference($defaultProvider));
        } elseif (1 === \count($providerIds)) {
            $defaultProvider = reset($providerIds);
        }
        $config->replaceArgument(5, $defaultProvider);
        // Register Firewall-specific event dispatcher
        $container->register($firewallEventDispatcherId, EventDispatcher::class)->addTag('event_dispatcher.dispatcher', ['name' => $firewallEventDispatcherId]);
        $eventDispatcherLocator = $container->getDefinition('security.firewall.event_dispatcher_locator');
        $eventDispatcherLocator->replaceArgument(0, array_merge($eventDispatcherLocator->getArgument(0), [$id => new ServiceClosureArgument(new Reference($firewallEventDispatcherId))]));
        // Register Firewall-specific chained user checker
        $container->register('security.user_checker.chain.' . $id, ChainUserChecker::class)->addArgument(new TaggedIteratorArgument('security.user_checker.' . $id));
        // Register listeners
        $listeners = [];
        $listenerKeys = [];
        // Channel listener
        $listeners[] = new Reference('security.channel_listener');
        $contextKey = null;
        // Context serializer listener
        if (\false === $firewall['stateless']) {
            $contextKey = $firewall['context'] ?? $id;
            $listeners[] = new Reference($this->createContextListener($container, $contextKey, $firewallEventDispatcherId));
            $sessionStrategyId = 'security.authentication.session_strategy';
            $container->setDefinition('security.listener.session.' . $id, new ChildDefinition('security.listener.session'))->addTag('kernel.event_subscriber', ['dispatcher' => $firewallEventDispatcherId]);
        } else {
            $sessionStrategyId = 'security.authentication.session_strategy_noop';
        }
        $container->setAlias(new Alias('security.authentication.session_strategy.' . $id, \false), $sessionStrategyId);
        $config->replaceArgument(6, $contextKey);
        // Logout listener
        $logoutListenerId = null;
        if (isset($firewall['logout'])) {
            $logoutListenerId = 'security.logout_listener.' . $id;
            $logoutListener = $container->setDefinition($logoutListenerId, new ChildDefinition('security.logout_listener'));
            $logoutListener->replaceArgument(2, new Reference($firewallEventDispatcherId));
            $logoutListener->replaceArgument(3, ['csrf_parameter' => $firewall['logout']['csrf_parameter'], 'csrf_token_id' => $firewall['logout']['csrf_token_id'], 'logout_path' => $firewall['logout']['path']]);
            $container->setDefinition('security.logout.listener.default.' . $id, new ChildDefinition('security.logout.listener.default'))->replaceArgument(1, $firewall['logout']['target'])->addTag('kernel.event_subscriber', ['dispatcher' => $firewallEventDispatcherId]);
            // add CSRF provider
            if ($firewall['logout']['enable_csrf']) {
                $logoutListener->addArgument(new Reference($firewall['logout']['csrf_token_manager']));
            }
            // add session logout listener
            if (\true === $firewall['logout']['invalidate_session'] && \false === $firewall['stateless']) {
                $container->setDefinition('security.logout.listener.session.' . $id, new ChildDefinition('security.logout.listener.session'))->addTag('kernel.event_subscriber', ['dispatcher' => $firewallEventDispatcherId]);
            }
            // add cookie logout listener
            if (\count($firewall['logout']['delete_cookies']) > 0) {
                $container->setDefinition('security.logout.listener.cookie_clearing.' . $id, new ChildDefinition('security.logout.listener.cookie_clearing'))->addArgument($firewall['logout']['delete_cookies'])->addTag('kernel.event_subscriber', ['dispatcher' => $firewallEventDispatcherId]);
            }
            // add clear site data listener
            if ($firewall['logout']['clear_site_data'] ?? \false) {
                $container->setDefinition('security.logout.listener.clear_site_data.' . $id, new ChildDefinition('security.logout.listener.clear_site_data'))->addArgument($firewall['logout']['clear_site_data'])->addTag('kernel.event_subscriber', ['dispatcher' => $firewallEventDispatcherId]);
            }
            // register with LogoutUrlGenerator
            $container->getDefinition('security.logout_url_generator')->addMethodCall('registerListener', [$id, $firewall['logout']['path'], $firewall['logout']['csrf_token_id'], $firewall['logout']['csrf_parameter'], isset($firewall['logout']['csrf_token_manager']) ? new Reference($firewall['logout']['csrf_token_manager']) : null, \false === $firewall['stateless'] && isset($firewall['context']) ? $firewall['context'] : null]);
            $config->replaceArgument(12, $firewall['logout']);
        }
        // Determine default entry point
        $configuredEntryPoint = $firewall['entry_point'] ?? null;
        // Authentication listeners
        $firewallAuthenticationProviders = [];
        [$authListeners, $defaultEntryPoint] = $this->createAuthenticationListeners($container, $id, $firewall, $firewallAuthenticationProviders, $defaultProvider, $providerIds, $configuredEntryPoint);
        // $configuredEntryPoint is resolved into a service ID and stored in $defaultEntryPoint
        $configuredEntryPoint = $defaultEntryPoint;
        // authenticator manager
        $authenticators = array_map(fn($id) => new Reference($id), $firewallAuthenticationProviders);
        $container->setDefinition($managerId = 'security.authenticator.manager.' . $id, new ChildDefinition('security.authenticator.manager'))->replaceArgument(0, $authenticators)->replaceArgument(2, new Reference($firewallEventDispatcherId))->replaceArgument(3, $id)->replaceArgument(7, $firewall['required_badges'] ?? [])->addTag('monolog.logger', ['channel' => 'security']);
        $managerLocator = $container->getDefinition('security.authenticator.managers_locator');
        $managerLocator->replaceArgument(0, array_merge($managerLocator->getArgument(0), [$id => new ServiceClosureArgument(new Reference($managerId))]));
        // authenticator manager listener
        $container->setDefinition('security.firewall.authenticator.' . $id, new ChildDefinition('security.firewall.authenticator'))->replaceArgument(0, new Reference($managerId));
        if ($container->hasDefinition('debug.security.firewall')) {
            $container->register('debug.security.firewall.authenticator.' . $id, TraceableAuthenticatorManagerListener::class)->setDecoratedService('security.firewall.authenticator.' . $id)->setArguments([new Reference('debug.security.firewall.authenticator.' . $id . '.inner')])->addTag('kernel.reset', ['method' => 'reset']);
        }
        // user checker listener
        $container->setDefinition('security.listener.user_checker.' . $id, new ChildDefinition('security.listener.user_checker'))->replaceArgument(0, new Reference('security.user_checker.' . $id))->addTag('kernel.event_subscriber', ['dispatcher' => $firewallEventDispatcherId]);
        $listeners[] = new Reference('security.firewall.authenticator.' . $id);
        // Add authenticators to the debug:firewall command
        if ($container->hasDefinition('security.command.debug_firewall')) {
            $debugCommand = $container->getDefinition('security.command.debug_firewall');
            $debugCommand->replaceArgument(3, array_merge($debugCommand->getArgument(3), [$id => $authenticators]));
        }
        $config->replaceArgument(7, $configuredEntryPoint ?: $defaultEntryPoint);
        $listeners = array_merge($listeners, $authListeners);
        // Switch user listener
        if (isset($firewall['switch_user'])) {
            $listenerKeys[] = 'switch_user';
            $listeners[] = new Reference($this->createSwitchUserListener($container, $id, $firewall['switch_user'], $defaultProvider, $firewall['stateless']));
        }
        // Access listener
        $listeners[] = new Reference('security.access_listener');
        // Exception listener
        $exceptionListener = new Reference($this->createExceptionListener($container, $firewall, $id, $configuredEntryPoint ?: $defaultEntryPoint, $firewall['stateless']));
        $config->replaceArgument(8, $firewall['access_denied_handler'] ?? null);
        $config->replaceArgument(9, $firewall['access_denied_url'] ?? null);
        $container->setAlias('security.user_checker.' . $id, new Alias($firewall['user_checker'], \false));
        $userCheckerLocator = $container->getDefinition('security.user_checker_locator');
        $userCheckerLocator->replaceArgument(0, array_merge($userCheckerLocator->getArgument(0), [$id => new ServiceClosureArgument(new Reference('security.user_checker.' . $id))]));
        foreach ($this->getSortedFactories() as $factory) {
            $key = str_replace('-', '_', $factory->getKey());
            if ('custom_authenticators' !== $key && \array_key_exists($key, $firewall)) {
                $listenerKeys[] = $key;
            }
        }
        if ($firewall['custom_authenticators'] ?? \false) {
            foreach ($firewall['custom_authenticators'] as $customAuthenticatorId) {
                $listenerKeys[] = $customAuthenticatorId;
            }
        }
        $config->replaceArgument(10, $listenerKeys);
        $config->replaceArgument(11, $firewall['switch_user'] ?? null);
        return [$matcher, $listeners, $exceptionListener, null !== $logoutListenerId ? new Reference($logoutListenerId) : null, $firewallAuthenticationProviders];
    }
    private function createContextListener(ContainerBuilder $container, string $contextKey, ?string $firewallEventDispatcherId): string
    {
        if (isset($this->contextListeners[$contextKey])) {
            return $this->contextListeners[$contextKey];
        }
        $listenerId = 'security.context_listener.' . \count($this->contextListeners);
        $listener = $container->setDefinition($listenerId, new ChildDefinition('security.context_listener'));
        $listener->replaceArgument(2, $contextKey);
        if (null !== $firewallEventDispatcherId) {
            $listener->replaceArgument(4, new Reference($firewallEventDispatcherId));
            $listener->addTag('kernel.event_listener', ['event' => KernelEvents::RESPONSE, 'method' => 'onKernelResponse']);
        }
        return $this->contextListeners[$contextKey] = $listenerId;
    }
    private function createAuthenticationListeners(ContainerBuilder $container, string $id, array $firewall, array &$authenticationProviders, ?string $defaultProvider, array $providerIds, ?string $defaultEntryPoint): array
    {
        $listeners = [];
        $entryPoints = [];
        foreach ($this->getSortedFactories() as $factory) {
            $key = str_replace('-', '_', $factory->getKey());
            if (isset($firewall[$key])) {
                $userProvider = $this->getUserProvider($container, $id, $firewall, $key, $defaultProvider, $providerIds);
                if (!$factory instanceof AuthenticatorFactoryInterface) {
                    throw new InvalidConfigurationException(\sprintf('Authenticator factory "%s" ("%s") must implement "%s".', get_debug_type($factory), $key, AuthenticatorFactoryInterface::class));
                }
                if (null === $userProvider && !$factory instanceof StatelessAuthenticatorFactoryInterface) {
                    $userProvider = $this->createMissingUserProvider($container, $id, $key);
                }
                $authenticators = $factory->createAuthenticator($container, $id, $firewall[$key], $userProvider);
                if (\is_array($authenticators)) {
                    foreach ($authenticators as $authenticator) {
                        $authenticationProviders[] = $authenticator;
                        $entryPoints[] = $authenticator;
                    }
                } else {
                    $authenticationProviders[] = $authenticators;
                    $entryPoints[$key] = $authenticators;
                }
                if ($factory instanceof FirewallListenerFactoryInterface) {
                    $firewallListenerIds = $factory->createListeners($container, $id, $firewall[$key]);
                    foreach ($firewallListenerIds as $firewallListenerId) {
                        $listeners[] = new Reference($firewallListenerId);
                    }
                }
            }
        }
        // the actual entry point is configured by the RegisterEntryPointPass
        $container->setParameter('security.' . $id . '._indexed_authenticators', $entryPoints);
        return [$listeners, $defaultEntryPoint];
    }
    private function getUserProvider(ContainerBuilder $container, string $id, array $firewall, string $factoryKey, ?string $defaultProvider, array $providerIds): ?string
    {
        if (isset($firewall[$factoryKey]['provider'])) {
            if (!isset($providerIds[$normalizedName = str_replace('-', '_', $firewall[$factoryKey]['provider'])])) {
                throw new InvalidConfigurationException(\sprintf('Invalid firewall "%s": user provider "%s" not found.', $id, $firewall[$factoryKey]['provider']));
            }
            return $providerIds[$normalizedName];
        }
        if ($defaultProvider) {
            return $defaultProvider;
        }
        if (!$providerIds) {
            if ($firewall['stateless'] ?? \false) {
                return null;
            }
            return $this->createMissingUserProvider($container, $id, $factoryKey);
        }
        if ('remember_me' === $factoryKey || 'custom_authenticators' === $factoryKey) {
            if ('custom_authenticators' === $factoryKey) {
                trigger_deprecation('symfony/security-bundle', '5.4', 'Not configuring explicitly the provider for the "%s" firewall is deprecated because it\'s ambiguous as there is more than one registered provider. Set the "provider" key to one of the configured providers, even if your custom authenticators don\'t use it.', $id);
            }
            return 'security.user_providers';
        }
        throw new InvalidConfigurationException(\sprintf('Not configuring explicitly the provider for the "%s" authenticator on "%s" firewall is ambiguous as there is more than one registered provider.', $factoryKey, $id));
    }
    private function createMissingUserProvider(ContainerBuilder $container, string $id, string $factoryKey): string
    {
        $userProvider = \sprintf('security.user.provider.missing.%s', $factoryKey);
        $container->setDefinition($userProvider, (new ChildDefinition('security.user.provider.missing'))->replaceArgument(0, $id));
        return $userProvider;
    }
    private function createHashers(array $hashers, ContainerBuilder $container): void
    {
        $hasherMap = [];
        foreach ($hashers as $class => $hasher) {
            $hasherMap[$class] = $this->createHasher($hasher);
        }
        $container->getDefinition('security.password_hasher_factory')->setArguments([$hasherMap]);
    }
    /**
     * @param array<string, mixed> $config
     *
     * @return Reference|array<string, mixed>
     */
    private function createHasher(array $config): Reference|array
    {
        // a custom hasher service
        if (isset($config['id'])) {
            return $config['migrate_from'] ?? \false ? ['instance' => new Reference($config['id']), 'migrate_from' => $config['migrate_from']] : new Reference($config['id']);
        }
        if ($config['migrate_from'] ?? \false) {
            return $config;
        }
        // plaintext hasher
        if ('plaintext' === $config['algorithm']) {
            $arguments = [$config['ignore_case']];
            return ['class' => PlaintextPasswordHasher::class, 'arguments' => $arguments];
        }
        // pbkdf2 hasher
        if ('pbkdf2' === $config['algorithm']) {
            return ['class' => Pbkdf2PasswordHasher::class, 'arguments' => [$config['hash_algorithm'], $config['encode_as_base64'], $config['iterations'], $config['key_length']]];
        }
        // bcrypt hasher
        if ('bcrypt' === $config['algorithm']) {
            $config['algorithm'] = 'native';
            $config['native_algorithm'] = \PASSWORD_BCRYPT;
            return $this->createHasher($config);
        }
        // Argon2i hasher
        if ('argon2i' === $config['algorithm']) {
            if (SodiumPasswordHasher::isSupported() && !\defined('SODIUM_CRYPTO_PWHASH_ALG_ARGON2ID13')) {
                $config['algorithm'] = 'sodium';
            } elseif (\defined('PASSWORD_ARGON2I')) {
                $config['algorithm'] = 'native';
                $config['native_algorithm'] = \PASSWORD_ARGON2I;
            } else {
                throw new InvalidConfigurationException(\sprintf('Algorithm "argon2i" is not available. Either use "%s" or upgrade to PHP 7.2+ instead.', \defined('SODIUM_CRYPTO_PWHASH_ALG_ARGON2ID13') ? 'argon2id", "auto' : 'auto'));
            }
            return $this->createHasher($config);
        }
        if ('argon2id' === $config['algorithm']) {
            if (($hasSodium = SodiumPasswordHasher::isSupported()) && \defined('SODIUM_CRYPTO_PWHASH_ALG_ARGON2ID13')) {
                $config['algorithm'] = 'sodium';
            } elseif (\defined('PASSWORD_ARGON2ID')) {
                $config['algorithm'] = 'native';
                $config['native_algorithm'] = \PASSWORD_ARGON2ID;
            } else {
                throw new InvalidConfigurationException(\sprintf('Algorithm "argon2id" is not available. Either use "%s", upgrade to PHP 7.3+ or use libsodium 1.0.15+ instead.', \defined('PASSWORD_ARGON2I') || $hasSodium ? 'argon2i", "auto' : 'auto'));
            }
            return $this->createHasher($config);
        }
        if ('native' === $config['algorithm']) {
            return ['class' => NativePasswordHasher::class, 'arguments' => [$config['time_cost'], ($config['memory_cost'] ?? 0) << 10 ?: null, $config['cost']] + (isset($config['native_algorithm']) ? [3 => $config['native_algorithm']] : [])];
        }
        if ('sodium' === $config['algorithm']) {
            if (!SodiumPasswordHasher::isSupported()) {
                throw new InvalidConfigurationException('Libsodium is not available. Install the sodium extension or use "auto" instead.');
            }
            return ['class' => SodiumPasswordHasher::class, 'arguments' => [$config['time_cost'], ($config['memory_cost'] ?? 0) << 10 ?: null]];
        }
        // run-time configured hasher
        return $config;
    }
    // Parses user providers and returns an array of their ids
    private function createUserProviders(array $config, ContainerBuilder $container): array
    {
        $providerIds = [];
        foreach ($config['providers'] as $name => $provider) {
            $id = $this->createUserDaoProvider($name, $provider, $container);
            $providerIds[str_replace('-', '_', $name)] = $id;
        }
        return $providerIds;
    }
    // Parses a <provider> tag and returns the id for the related user provider service
    private function createUserDaoProvider(string $name, array $provider, ContainerBuilder $container): string
    {
        $name = $this->getUserProviderId($name);
        // Doctrine Entity and In-memory DAO provider are managed by factories
        foreach ($this->userProviderFactories as $factory) {
            $key = str_replace('-', '_', $factory->getKey());
            if (!empty($provider[$key])) {
                $factory->create($container, $name, $provider[$key]);
                return $name;
            }
        }
        // Existing DAO service provider
        if (isset($provider['id'])) {
            $container->setAlias($name, new Alias($provider['id'], \false));
            return $provider['id'];
        }
        // Chain provider
        if (isset($provider['chain'])) {
            $providers = [];
            foreach ($provider['chain']['providers'] as $providerName) {
                $providers[] = new Reference($this->getUserProviderId($providerName));
            }
            $container->setDefinition($name, new ChildDefinition('security.user.provider.chain'))->addArgument(new IteratorArgument($providers));
            return $name;
        }
        throw new InvalidConfigurationException(\sprintf('Unable to create definition for "%s" user provider.', $name));
    }
    private function getUserProviderId(string $name): string
    {
        return 'security.user.provider.concrete.' . strtolower($name);
    }
    private function createExceptionListener(ContainerBuilder $container, array $config, string $id, ?string $defaultEntryPoint, bool $stateless): string
    {
        $exceptionListenerId = 'security.exception_listener.' . $id;
        $listener = $container->setDefinition($exceptionListenerId, new ChildDefinition('security.exception_listener'));
        $listener->replaceArgument(3, $id);
        $listener->replaceArgument(4, null === $defaultEntryPoint ? null : new Reference($defaultEntryPoint));
        $listener->replaceArgument(8, $stateless);
        // access denied handler setup
        if (isset($config['access_denied_handler'])) {
            $listener->replaceArgument(6, new Reference($config['access_denied_handler']));
        } elseif (isset($config['access_denied_url'])) {
            $listener->replaceArgument(5, $config['access_denied_url']);
        }
        return $exceptionListenerId;
    }
    private function createSwitchUserListener(ContainerBuilder $container, string $id, array $config, ?string $defaultProvider, bool $stateless): string
    {
        $userProvider = isset($config['provider']) ? $this->getUserProviderId($config['provider']) : $defaultProvider;
        if (!$userProvider) {
            throw new InvalidConfigurationException(\sprintf('Not configuring explicitly the provider for the "switch_user" listener on "%s" firewall is ambiguous as there is more than one registered provider.', $id));
        }
        if ($stateless && null !== $config['target_route']) {
            throw new InvalidConfigurationException(\sprintf('Cannot set a "target_route" for the "switch_user" listener on the "%s" firewall as it is stateless.', $id));
        }
        $switchUserListenerId = 'security.authentication.switchuser_listener.' . $id;
        $listener = $container->setDefinition($switchUserListenerId, new ChildDefinition('security.authentication.switchuser_listener'));
        $listener->replaceArgument(1, new Reference($userProvider));
        $listener->replaceArgument(2, new Reference('security.user_checker.' . $id));
        $listener->replaceArgument(3, $id);
        $listener->replaceArgument(6, $config['parameter']);
        $listener->replaceArgument(7, $config['role']);
        $listener->replaceArgument(9, $stateless);
        $listener->replaceArgument(11, $config['target_route']);
        return $switchUserListenerId;
    }
    private function createExpression(ContainerBuilder $container, string $expression): Reference
    {
        if (isset($this->expressions[$id = '.security.expression.' . ContainerBuilder::hash($expression)])) {
            return $this->expressions[$id];
        }
        if (!$container::willBeAvailable('symfony/expression-language', ExpressionLanguage::class, ['symfony/security-bundle'])) {
            throw new \RuntimeException('Unable to use expressions as the Symfony ExpressionLanguage component is not installed. Try running "composer require symfony/expression-language".');
        }
        $container->register($id, Expression::class)->addArgument($expression);
        return $this->expressions[$id] = new Reference($id);
    }
    private function createRequestMatcher(ContainerBuilder $container, ?string $path = null, ?string $host = null, ?int $port = null, array $methods = [], ?array $ips = null, array $attributes = []): Reference
    {
        if ($methods) {
            $methods = array_map('strtoupper', $methods);
        }
        if ($ips) {
            foreach ($ips as $ip) {
                $container->resolveEnvPlaceholders($ip, null, $usedEnvs);
                if (!$usedEnvs && !$this->isValidIps($ip)) {
                    throw new \LogicException(\sprintf('The given value "%s" in the "security.access_control" config option is not a valid IP address.', $ip));
                }
                $usedEnvs = null;
            }
        }
        $id = '.security.request_matcher.' . ContainerBuilder::hash([ChainRequestMatcher::class, $path, $host, $port, $methods, $ips, $attributes]);
        if (isset($this->requestMatchers[$id])) {
            return $this->requestMatchers[$id];
        }
        $arguments = [];
        if ($methods) {
            if (!$container->hasDefinition($lid = '.security.request_matcher.' . ContainerBuilder::hash([MethodRequestMatcher::class, $methods]))) {
                $container->register($lid, MethodRequestMatcher::class)->setArguments([$methods]);
            }
            $arguments[] = new Reference($lid);
        }
        if ($path) {
            if (!$container->hasDefinition($lid = '.security.request_matcher.' . ContainerBuilder::hash([PathRequestMatcher::class, $path]))) {
                $container->register($lid, PathRequestMatcher::class)->setArguments([$path]);
            }
            $arguments[] = new Reference($lid);
        }
        if ($host) {
            if (!$container->hasDefinition($lid = '.security.request_matcher.' . ContainerBuilder::hash([HostRequestMatcher::class, $host]))) {
                $container->register($lid, HostRequestMatcher::class)->setArguments([$host]);
            }
            $arguments[] = new Reference($lid);
        }
        if ($ips) {
            if (!$container->hasDefinition($lid = '.security.request_matcher.' . ContainerBuilder::hash([IpsRequestMatcher::class, $ips]))) {
                $container->register($lid, IpsRequestMatcher::class)->setArguments([$ips]);
            }
            $arguments[] = new Reference($lid);
        }
        if ($attributes) {
            if (!$container->hasDefinition($lid = '.security.request_matcher.' . ContainerBuilder::hash([AttributesRequestMatcher::class, $attributes]))) {
                $container->register($lid, AttributesRequestMatcher::class)->setArguments([$attributes]);
            }
            $arguments[] = new Reference($lid);
        }
        if ($port) {
            if (!$container->hasDefinition($lid = '.security.request_matcher.' . ContainerBuilder::hash([PortRequestMatcher::class, $port]))) {
                $container->register($lid, PortRequestMatcher::class)->setArguments([$port]);
            }
            $arguments[] = new Reference($lid);
        }
        $container->register($id, ChainRequestMatcher::class)->setArguments([$arguments]);
        return $this->requestMatchers[$id] = new Reference($id);
    }
    public function addAuthenticatorFactory(AuthenticatorFactoryInterface $factory): void
    {
        $this->factories[] = [$factory->getPriority(), $factory];
        $this->sortedFactories = [];
    }
    public function addUserProviderFactory(UserProviderFactoryInterface $factory): void
    {
        $this->userProviderFactories[] = $factory;
    }
    public function getXsdValidationBasePath(): string|false
    {
        return __DIR__ . '/../Resources/config/schema';
    }
    public function getNamespace(): string
    {
        return 'http://symfony.com/schema/dic/security';
    }
    public function getConfiguration(array $config, ContainerBuilder $container): ?ConfigurationInterface
    {
        // first assemble the factories
        return new MainConfiguration($this->getSortedFactories(), $this->userProviderFactories);
    }
    private function isValidIps(string|array $ips): bool
    {
        $ipsList = array_reduce((array) $ips, fn($ips, $ip) => array_merge($ips, preg_split('/\s*,\s*/', $ip)), []);
        if (!$ipsList) {
            return \false;
        }
        foreach ($ipsList as $cidr) {
            if (!$this->isValidIp($cidr)) {
                return \false;
            }
        }
        return \true;
    }
    private function isValidIp(string $cidr): bool
    {
        $cidrParts = explode('/', $cidr);
        if (1 === \count($cidrParts)) {
            return \false !== filter_var($cidrParts[0], \FILTER_VALIDATE_IP);
        }
        $ip = $cidrParts[0];
        $netmask = $cidrParts[1];
        if (!ctype_digit($netmask)) {
            return \false;
        }
        if (filter_var($ip, \FILTER_VALIDATE_IP, \FILTER_FLAG_IPV4)) {
            return $netmask <= 32;
        }
        if (filter_var($ip, \FILTER_VALIDATE_IP, \FILTER_FLAG_IPV6)) {
            return $netmask <= 128;
        }
        return \false;
    }
    /**
     * @return array<int, AuthenticatorFactoryInterface>
     */
    private function getSortedFactories(): array
    {
        if (!$this->sortedFactories) {
            $factories = [];
            foreach ($this->factories as $i => $factory) {
                $factories[] = array_merge($factory, [$i]);
            }
            usort($factories, fn($a, $b) => $b[0] <=> $a[0] ?: $a[2] <=> $b[2]);
            $this->sortedFactories = array_column($factories, 1);
        }
        return $this->sortedFactories;
    }
    private function createLogoutUrisParameter(array $firewallsConfig, ContainerBuilder $container): void
    {
        $logoutUris = [];
        foreach ($firewallsConfig as $name => $config) {
            if (!$logoutPath = $config['logout']['path'] ?? null) {
                continue;
            }
            if ('/' === $logoutPath[0]) {
                $logoutUris[$name] = $logoutPath;
            }
        }
        $container->setParameter('security.logout_uris', $logoutUris);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Bundle\SecurityBundle\DependencyInjection\Compiler;

use _ContaoManager\Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerBuilder;
use _ContaoManager\Symfony\Component\DependencyInjection\Reference;
/**
 * Registers the expression language providers.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class AddExpressionLanguageProvidersPass implements CompilerPassInterface
{
    /**
     * @return void
     */
    public function process(ContainerBuilder $container)
    {
        if ($container->has('security.expression_language')) {
            $definition = $container->findDefinition('security.expression_language');
            foreach ($container->findTaggedServiceIds('security.expression_language_provider', \true) as $id => $attributes) {
                $definition->addMethodCall('registerProvider', [new Reference($id)]);
            }
        }
        if (!$container->hasDefinition('cache.system')) {
            $container->removeDefinition('cache.security_expression_language');
            $container->removeDefinition('cache.security_is_granted_attribute_expression_language');
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Bundle\SecurityBundle\DependencyInjection\Compiler;

use _ContaoManager\Monolog\Processor\ProcessorInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Argument\BoundArgument;
use _ContaoManager\Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerBuilder;
use _ContaoManager\Symfony\Component\DependencyInjection\Reference;
use _ContaoManager\Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
/**
 * Injects the session tracker enabler in "security.context_listener" + binds "security.untracked_token_storage" to ProcessorInterface instances.
 *
 * @author Nicolas Grekas <p@tchwork.com>
 *
 * @internal
 */
class RegisterTokenUsageTrackingPass implements CompilerPassInterface
{
    public function process(ContainerBuilder $container): void
    {
        if (!$container->has('security.untracked_token_storage')) {
            return;
        }
        $processorAutoconfiguration = $container->registerForAutoconfiguration(ProcessorInterface::class);
        $processorAutoconfiguration->setBindings($processorAutoconfiguration->getBindings() + [TokenStorageInterface::class => new BoundArgument(new Reference('security.untracked_token_storage'), \false)]);
        if (!$container->has('session.factory')) {
            $container->setAlias('security.token_storage', 'security.untracked_token_storage')->setPublic(\true);
            $container->getDefinition('security.untracked_token_storage')->addTag('kernel.reset', ['method' => 'reset']);
        } elseif ($container->hasDefinition('security.context_listener')) {
            $tokenStorageClass = $container->getParameterBag()->resolveValue($container->findDefinition('security.token_storage')->getClass());
            if (method_exists($tokenStorageClass, 'enableUsageTracking')) {
                $container->getDefinition('security.context_listener')->setArgument(6, [new Reference('security.token_storage'), 'enableUsageTracking']);
            }
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Bundle\SecurityBundle\DependencyInjection\Compiler;

use _ContaoManager\Symfony\Component\DependencyInjection\Argument\ServiceClosureArgument;
use _ContaoManager\Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerBuilder;
use _ContaoManager\Symfony\Component\DependencyInjection\Definition;
use _ContaoManager\Symfony\Component\DependencyInjection\Reference;
use _ContaoManager\Symfony\Component\DependencyInjection\ServiceLocator;
/**
 * @author Wouter de Jong <wouter@wouterj.nl>
 *
 * @internal
 */
class RegisterLdapLocatorPass implements CompilerPassInterface
{
    public function process(ContainerBuilder $container): void
    {
        $definition = $container->setDefinition('security.ldap_locator', new Definition(ServiceLocator::class));
        $locators = [];
        foreach ($container->findTaggedServiceIds('ldap') as $id => $tags) {
            $locators[$id] = new ServiceClosureArgument(new Reference($id));
            $container->getDefinition($id)->addTag('kernel.reset', ['method' => 'reset', 'on_invalid' => 'ignore']);
        }
        $definition->addArgument($locators);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Bundle\SecurityBundle\DependencyInjection\Compiler;

use _ContaoManager\Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerBuilder;
use _ContaoManager\Symfony\Component\Security\Core\AuthenticationEvents;
use _ContaoManager\Symfony\Component\Security\Core\Event\AuthenticationSuccessEvent;
use _ContaoManager\Symfony\Component\Security\Http\Event\AuthenticationTokenCreatedEvent;
use _ContaoManager\Symfony\Component\Security\Http\Event\CheckPassportEvent;
use _ContaoManager\Symfony\Component\Security\Http\Event\InteractiveLoginEvent;
use _ContaoManager\Symfony\Component\Security\Http\Event\LoginFailureEvent;
use _ContaoManager\Symfony\Component\Security\Http\Event\LoginSuccessEvent;
use _ContaoManager\Symfony\Component\Security\Http\Event\LogoutEvent;
use _ContaoManager\Symfony\Component\Security\Http\Event\TokenDeauthenticatedEvent;
use _ContaoManager\Symfony\Component\Security\Http\SecurityEvents;
/**
 * Makes sure all event listeners on the global dispatcher are also listening
 * to events on the firewall-specific dispatchers.
 *
 * This compiler pass must be run after RegisterListenersPass of the
 * EventDispatcher component.
 *
 * @author Wouter de Jong <wouter@wouterj.nl>
 *
 * @internal
 */
class RegisterGlobalSecurityEventListenersPass implements CompilerPassInterface
{
    private const EVENT_BUBBLING_EVENTS = [
        CheckPassportEvent::class,
        LoginFailureEvent::class,
        LoginSuccessEvent::class,
        LogoutEvent::class,
        AuthenticationTokenCreatedEvent::class,
        AuthenticationSuccessEvent::class,
        InteractiveLoginEvent::class,
        TokenDeauthenticatedEvent::class,
        // When events are registered by their name
        AuthenticationEvents::AUTHENTICATION_SUCCESS,
        SecurityEvents::INTERACTIVE_LOGIN,
    ];
    public function process(ContainerBuilder $container): void
    {
        if (!$container->has('event_dispatcher') || !$container->hasParameter('security.firewalls')) {
            return;
        }
        $firewallDispatchers = [];
        foreach ($container->getParameter('security.firewalls') as $firewallName) {
            if (!$container->has('security.event_dispatcher.' . $firewallName)) {
                continue;
            }
            $firewallDispatchers[] = $container->findDefinition('security.event_dispatcher.' . $firewallName);
        }
        $globalDispatcher = $container->findDefinition('event_dispatcher');
        foreach ($globalDispatcher->getMethodCalls() as $methodCall) {
            if ('addListener' !== $methodCall[0]) {
                continue;
            }
            $methodCallArguments = $methodCall[1];
            if (!\in_array($methodCallArguments[0], self::EVENT_BUBBLING_EVENTS, \true)) {
                continue;
            }
            foreach ($firewallDispatchers as $firewallDispatcher) {
                $firewallDispatcher->addMethodCall('addListener', $methodCallArguments);
            }
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Bundle\SecurityBundle\DependencyInjection\Compiler;

use _ContaoManager\Symfony\Component\DependencyInjection\Argument\IteratorArgument;
use _ContaoManager\Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerBuilder;
use _ContaoManager\Symfony\Component\DependencyInjection\Definition;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
use _ContaoManager\Symfony\Component\DependencyInjection\Reference;
use _ContaoManager\Symfony\Component\Security\Http\Firewall\FirewallListenerInterface;
/**
 * Sorts firewall listeners based on the execution order provided by FirewallListenerInterface::getPriority().
 *
 * @author Christian Scheb <me@christianscheb.de>
 */
class SortFirewallListenersPass implements CompilerPassInterface
{
    public function process(ContainerBuilder $container): void
    {
        if (!$container->hasParameter('security.firewalls')) {
            return;
        }
        foreach ($container->getParameter('security.firewalls') as $firewallName) {
            $firewallContextDefinition = $container->getDefinition('security.firewall.map.context.' . $firewallName);
            $this->sortFirewallContextListeners($firewallContextDefinition, $container);
        }
    }
    private function sortFirewallContextListeners(Definition $definition, ContainerBuilder $container): void
    {
        /** @var IteratorArgument $listenerIteratorArgument */
        $listenerIteratorArgument = $definition->getArgument(0);
        $prioritiesByServiceId = $this->getListenerPriorities($listenerIteratorArgument, $container);
        $listeners = $listenerIteratorArgument->getValues();
        usort($listeners, fn(Reference $a, Reference $b) => $prioritiesByServiceId[(string) $b] <=> $prioritiesByServiceId[(string) $a]);
        $listenerIteratorArgument->setValues(array_values($listeners));
    }
    private function getListenerPriorities(IteratorArgument $listeners, ContainerBuilder $container): array
    {
        $priorities = [];
        foreach ($listeners->getValues() as $reference) {
            $id = (string) $reference;
            $def = $container->getDefinition($id);
            // We must assume that the class value has been correctly filled, even if the service is created by a factory
            $class = $def->getClass();
            if (!$r = $container->getReflectionClass($class)) {
                throw new InvalidArgumentException(\sprintf('Class "%s" used for service "%s" cannot be found.', $class, $id));
            }
            $priority = 0;
            if ($r->isSubclassOf(FirewallListenerInterface::class)) {
                $priority = $r->getMethod('getPriority')->invoke(null);
            }
            $priorities[$id] = $priority;
        }
        return $priorities;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Bundle\SecurityBundle\DependencyInjection\Compiler;

use _ContaoManager\Symfony\Bundle\SecurityBundle\RememberMe\DecoratedRememberMeHandler;
use _ContaoManager\Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerBuilder;
/**
 * Replaces the DecoratedRememberMeHandler services with the real definition.
 *
 * @author Wouter de Jong <wouter@wouterj.nl>
 *
 * @internal
 */
final class ReplaceDecoratedRememberMeHandlerPass implements CompilerPassInterface
{
    private const HANDLER_TAG = 'security.remember_me_handler';
    public function process(ContainerBuilder $container): void
    {
        $handledFirewalls = [];
        foreach ($container->findTaggedServiceIds(self::HANDLER_TAG) as $definitionId => $rememberMeHandlerTags) {
            $definition = $container->findDefinition($definitionId);
            if (DecoratedRememberMeHandler::class !== $definition->getClass()) {
                continue;
            }
            // get the actual custom remember me handler definition (passed to the decorator)
            $realRememberMeHandler = $container->findDefinition((string) $definition->getArgument(0));
            if (null === $realRememberMeHandler) {
                throw new \LogicException(\sprintf('Invalid service definition for custom remember me handler; no service found with ID "%s".', (string) $definition->getArgument(0)));
            }
            foreach ($rememberMeHandlerTags as $rememberMeHandlerTag) {
                // some custom handlers may be used on multiple firewalls in the same application
                if (\in_array($rememberMeHandlerTag['firewall'], $handledFirewalls, \true)) {
                    continue;
                }
                $rememberMeHandler = clone $realRememberMeHandler;
                $rememberMeHandler->addTag(self::HANDLER_TAG, $rememberMeHandlerTag);
                $container->setDefinition('security.authenticator.remember_me_handler.' . $rememberMeHandlerTag['firewall'], $rememberMeHandler);
                $handledFirewalls[] = $rememberMeHandlerTag['firewall'];
            }
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Bundle\SecurityBundle\DependencyInjection\Compiler;

use _ContaoManager\Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerBuilder;
/**
 * Uses the session domain to restrict allowed redirection targets.
 *
 * @author Nicolas Grekas <p@tchwork.com>
 */
class AddSessionDomainConstraintPass implements CompilerPassInterface
{
    /**
     * @return void
     */
    public function process(ContainerBuilder $container)
    {
        if (!$container->hasParameter('session.storage.options') || !$container->has('security.http_utils')) {
            return;
        }
        $sessionOptions = $container->getParameter('session.storage.options');
        $domainRegexp = empty($sessionOptions['cookie_domain']) ? '%%s' : \sprintf('(?:%%%%s|(?:.+\.)?%s)', preg_quote(trim($sessionOptions['cookie_domain'], '.')));
        if ('auto' === ($sessionOptions['cookie_secure'] ?? null)) {
            $secureDomainRegexp = \sprintf('{^https://%s$}i', $domainRegexp);
            $domainRegexp = 'https?://' . $domainRegexp;
        } else {
            $secureDomainRegexp = null;
            $domainRegexp = (empty($sessionOptions['cookie_secure']) ? 'https?://' : 'https://') . $domainRegexp;
        }
        $container->findDefinition('security.http_utils')->addArgument(\sprintf('{^%s$}i', $domainRegexp))->addArgument($secureDomainRegexp);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Bundle\SecurityBundle\DependencyInjection\Compiler;

use _ContaoManager\Symfony\Component\DependencyInjection\Argument\IteratorArgument;
use _ContaoManager\Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Compiler\PriorityTaggedServiceTrait;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerBuilder;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\LogicException;
use _ContaoManager\Symfony\Component\DependencyInjection\Reference;
use _ContaoManager\Symfony\Component\Security\Core\Authorization\Voter\TraceableVoter;
use _ContaoManager\Symfony\Component\Security\Core\Authorization\Voter\VoterInterface;
/**
 * Adds all configured security voters to the access decision manager.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
class AddSecurityVotersPass implements CompilerPassInterface
{
    use PriorityTaggedServiceTrait;
    /**
     * @return void
     */
    public function process(ContainerBuilder $container)
    {
        if (!$container->hasDefinition('security.access.decision_manager')) {
            return;
        }
        $voters = $this->findAndSortTaggedServices('security.voter', $container);
        if (!$voters) {
            throw new LogicException('No security voters found. You need to tag at least one with "security.voter".');
        }
        $debug = $container->getParameter('kernel.debug');
        $voterServices = [];
        foreach ($voters as $voter) {
            $voterServiceId = (string) $voter;
            $definition = $container->getDefinition($voterServiceId);
            $class = $container->getParameterBag()->resolveValue($definition->getClass());
            if (!is_a($class, VoterInterface::class, \true)) {
                throw new LogicException(\sprintf('"%s" must implement the "%s" when used as a voter.', $class, VoterInterface::class));
            }
            if ($debug) {
                $voterServices[] = new Reference($debugVoterServiceId = '.debug.security.voter.' . $voterServiceId);
                $container->register($debugVoterServiceId, TraceableVoter::class)->addArgument($voter)->addArgument(new Reference('event_dispatcher'));
            } else {
                $voterServices[] = $voter;
            }
        }
        $container->getDefinition('security.access.decision_manager')->replaceArgument(0, new IteratorArgument($voterServices));
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Bundle\SecurityBundle\DependencyInjection\Compiler;

use _ContaoManager\Symfony\Component\Config\Definition\Exception\InvalidConfigurationException;
use _ContaoManager\Symfony\Component\DependencyInjection\ChildDefinition;
use _ContaoManager\Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerBuilder;
use _ContaoManager\Symfony\Component\DependencyInjection\Reference;
use _ContaoManager\Symfony\Component\Security\Http\EntryPoint\AuthenticationEntryPointInterface;
/**
 * @author Wouter de Jong <wouter@wouterj.nl>
 */
class RegisterEntryPointPass implements CompilerPassInterface
{
    /**
     * @return void
     */
    public function process(ContainerBuilder $container)
    {
        if (!$container->hasParameter('security.firewalls')) {
            return;
        }
        $firewalls = $container->getParameter('security.firewalls');
        foreach ($firewalls as $firewallName) {
            if (!$container->hasDefinition('security.authenticator.manager.' . $firewallName) || !$container->hasParameter('security.' . $firewallName . '._indexed_authenticators')) {
                continue;
            }
            $entryPoints = [];
            $indexedAuthenticators = $container->getParameter('security.' . $firewallName . '._indexed_authenticators');
            // this is a compile-only parameter, removing it cleans up space and avoids unintended usage
            $container->getParameterBag()->remove('security.' . $firewallName . '._indexed_authenticators');
            foreach ($indexedAuthenticators as $key => $authenticatorId) {
                if (!$container->has($authenticatorId)) {
                    continue;
                }
                // because this pass runs before ResolveChildDefinitionPass, child definitions didn't inherit the parent class yet
                $definition = $container->findDefinition($authenticatorId);
                while (!($authenticatorClass = $definition->getClass()) && $definition instanceof ChildDefinition) {
                    $definition = $container->findDefinition($definition->getParent());
                }
                if (is_a($authenticatorClass, AuthenticationEntryPointInterface::class, \true)) {
                    $entryPoints[$key] = $authenticatorId;
                }
            }
            if (!$entryPoints) {
                continue;
            }
            $config = $container->getDefinition('security.firewall.map.config.' . $firewallName);
            $configuredEntryPoint = $config->getArgument(7);
            if (null !== $configuredEntryPoint) {
                // allow entry points to be configured by authenticator key (e.g. "http_basic")
                $entryPoint = $entryPoints[$configuredEntryPoint] ?? $configuredEntryPoint;
            } elseif (1 === \count($entryPoints)) {
                $entryPoint = array_shift($entryPoints);
            } else {
                $entryPointNames = [];
                foreach ($entryPoints as $key => $serviceId) {
                    $entryPointNames[] = is_numeric($key) ? $serviceId : $key;
                }
                throw new InvalidConfigurationException(\sprintf('Because you have multiple authenticators in firewall "%s", you need to set the "entry_point" key to one of your authenticators ("%s") or a service ID implementing "%s". The "entry_point" determines what should happen (e.g. redirect to "/login") when an anonymous user tries to access a protected page.', $firewallName, implode('", "', $entryPointNames), AuthenticationEntryPointInterface::class));
            }
            $config->replaceArgument(7, $entryPoint);
            $container->getDefinition('security.exception_listener.' . $firewallName)->replaceArgument(4, new Reference($entryPoint));
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Bundle\SecurityBundle\DependencyInjection\Compiler;

use _ContaoManager\Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerBuilder;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Reference;
use _ContaoManager\Symfony\Component\EventDispatcher\Debug\TraceableEventDispatcher;
/**
 * @author Mathieu Lechat <mathieu.lechat@les-tilleuls.coop>
 */
class MakeFirewallsEventDispatcherTraceablePass implements CompilerPassInterface
{
    /**
     * @return void
     */
    public function process(ContainerBuilder $container)
    {
        if (!$container->has('event_dispatcher') || !$container->hasParameter('security.firewalls')) {
            return;
        }
        if (!$container->getParameter('kernel.debug') || !$container->has('debug.stopwatch')) {
            return;
        }
        $dispatchersId = [];
        foreach ($container->getParameter('security.firewalls') as $firewallName) {
            $dispatcherId = 'security.event_dispatcher.' . $firewallName;
            if (!$container->has($dispatcherId)) {
                continue;
            }
            $dispatchersId[$dispatcherId] = 'debug.' . $dispatcherId;
            $container->register($dispatchersId[$dispatcherId], TraceableEventDispatcher::class)->setDecoratedService($dispatcherId)->setArguments([new Reference($dispatchersId[$dispatcherId] . '.inner'), new Reference('debug.stopwatch'), new Reference('logger', ContainerInterface::NULL_ON_INVALID_REFERENCE), new Reference('request_stack', ContainerInterface::NULL_ON_INVALID_REFERENCE)]);
        }
        foreach (['kernel.event_subscriber', 'kernel.event_listener'] as $tagName) {
            foreach ($container->findTaggedServiceIds($tagName) as $taggedServiceId => $tags) {
                $taggedServiceDefinition = $container->findDefinition($taggedServiceId);
                $taggedServiceDefinition->clearTag($tagName);
                foreach ($tags as $tag) {
                    if ($dispatcherId = $tag['dispatcher'] ?? null) {
                        $tag['dispatcher'] = $dispatchersId[$dispatcherId] ?? $dispatcherId;
                    }
                    $taggedServiceDefinition->addTag($tagName, $tag);
                }
            }
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Bundle\SecurityBundle\DependencyInjection\Compiler;

use _ContaoManager\Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerBuilder;
/**
 * Cleans up the remember me verifier cache if cache is missing.
 *
 * @author Jordi Boggiano <j.boggiano@seld.be>
 */
class CleanRememberMeVerifierPass implements CompilerPassInterface
{
    /**
     * @return void
     */
    public function process(ContainerBuilder $container)
    {
        if (!$container->hasDefinition('cache.system')) {
            $container->removeDefinition('cache.security_token_verifier');
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Bundle\SecurityBundle\DependencyInjection\Compiler;

use _ContaoManager\Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerBuilder;
use _ContaoManager\Symfony\Component\DependencyInjection\Reference;
use _ContaoManager\Symfony\Component\Security\Csrf\TokenStorage\ClearableTokenStorageInterface;
use _ContaoManager\Symfony\Component\Security\Http\EventListener\CsrfProtectionListener;
use _ContaoManager\Symfony\Component\Security\Http\EventListener\CsrfTokenClearingLogoutListener;
/**
 * @author Christian Flothmann <christian.flothmann@sensiolabs.de>
 * @author Wouter de Jong <wouter@wouterj.nl>
 *
 * @internal
 */
class RegisterCsrfFeaturesPass implements CompilerPassInterface
{
    public function process(ContainerBuilder $container): void
    {
        $this->registerCsrfProtectionListener($container);
        $this->registerLogoutHandler($container);
    }
    private function registerCsrfProtectionListener(ContainerBuilder $container): void
    {
        if (!$container->has('security.authenticator.manager') || !$container->has('security.csrf.token_manager')) {
            return;
        }
        $container->register('security.listener.csrf_protection', CsrfProtectionListener::class)->addArgument(new Reference('security.csrf.token_manager'))->addTag('kernel.event_subscriber');
    }
    protected function registerLogoutHandler(ContainerBuilder $container): void
    {
        if (!$container->has('security.logout_listener') || !$container->has('security.csrf.token_storage')) {
            return;
        }
        $csrfTokenStorage = $container->findDefinition('security.csrf.token_storage');
        $csrfTokenStorageClass = $container->getParameterBag()->resolveValue($csrfTokenStorage->getClass());
        if (!is_subclass_of($csrfTokenStorageClass, ClearableTokenStorageInterface::class)) {
            return;
        }
        $container->register('security.logout.listener.csrf_token_clearing', CsrfTokenClearingLogoutListener::class)->addArgument(new Reference('security.csrf.token_storage'))->addTag('kernel.event_subscriber');
    }
}
{
    "name": "symfony\/security-bundle",
    "type": "symfony-bundle",
    "description": "Provides a tight integration of the Security component into the Symfony full-stack framework",
    "keywords": [],
    "homepage": "https:\/\/symfony.com",
    "license": "MIT",
    "authors": [
        {
            "name": "Fabien Potencier",
            "email": "fabien@symfony.com"
        },
        {
            "name": "Symfony Community",
            "homepage": "https:\/\/symfony.com\/contributors"
        }
    ],
    "require": {
        "php": ">=8.1",
        "composer-runtime-api": ">=2.1",
        "ext-xml": "*",
        "symfony\/clock": "^6.3|^7.0",
        "symfony\/config": "^6.1|^7.0",
        "symfony\/dependency-injection": "^6.4.11|^7.1.4",
        "symfony\/deprecation-contracts": "^2.5|^3",
        "symfony\/event-dispatcher": "^5.4|^6.0|^7.0",
        "symfony\/http-kernel": "^6.2",
        "symfony\/http-foundation": "^6.2|^7.0",
        "symfony\/password-hasher": "^5.4|^6.0|^7.0",
        "symfony\/security-core": "^6.2|^7.0",
        "symfony\/security-csrf": "^5.4|^6.0|^7.0",
        "symfony\/security-http": "^6.3.6|^7.0",
        "symfony\/service-contracts": "^2.5|^3"
    },
    "require-dev": {
        "symfony\/asset": "^5.4|^6.0|^7.0",
        "symfony\/browser-kit": "^5.4|^6.0|^7.0",
        "symfony\/console": "^5.4|^6.0|^7.0",
        "symfony\/css-selector": "^5.4|^6.0|^7.0",
        "symfony\/dom-crawler": "^5.4|^6.0|^7.0",
        "symfony\/expression-language": "^5.4|^6.0|^7.0",
        "symfony\/form": "^5.4|^6.0|^7.0",
        "symfony\/framework-bundle": "^6.4|^7.0",
        "symfony\/http-client": "^5.4|^6.0|^7.0",
        "symfony\/ldap": "^5.4|^6.0|^7.0",
        "symfony\/process": "^5.4|^6.0|^7.0",
        "symfony\/rate-limiter": "^5.4|^6.0|^7.0",
        "symfony\/serializer": "^6.4|^7.0",
        "symfony\/translation": "^5.4|^6.0|^7.0",
        "symfony\/twig-bundle": "^5.4|^6.0|^7.0",
        "symfony\/twig-bridge": "^5.4|^6.0|^7.0",
        "symfony\/validator": "^6.4|^7.0",
        "symfony\/yaml": "^5.4|^6.0|^7.0",
        "twig\/twig": "^2.13|^3.0.4",
        "web-token\/jwt-checker": "^3.1",
        "web-token\/jwt-signature-algorithm-hmac": "^3.1",
        "web-token\/jwt-signature-algorithm-ecdsa": "^3.1",
        "web-token\/jwt-signature-algorithm-rsa": "^3.1",
        "web-token\/jwt-signature-algorithm-eddsa": "^3.1",
        "web-token\/jwt-signature-algorithm-none": "^3.1"
    },
    "conflict": {
        "symfony\/browser-kit": "<5.4",
        "symfony\/console": "<5.4",
        "symfony\/framework-bundle": "<6.4",
        "symfony\/http-client": "<5.4",
        "symfony\/ldap": "<5.4",
        "symfony\/serializer": "<6.4",
        "symfony\/twig-bundle": "<5.4",
        "symfony\/validator": "<6.4"
    },
    "autoload": {
        "psr-4": {
            "_ContaoManager\\Symfony\\Bundle\\SecurityBundle\\": ""
        },
        "exclude-from-classmap": [
            "\/Tests\/"
        ]
    },
    "minimum-stability": "dev"
}<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Bundle\SecurityBundle\Debug;

use _ContaoManager\Symfony\Bundle\SecurityBundle\EventListener\FirewallListener;
use _ContaoManager\Symfony\Bundle\SecurityBundle\Security\FirewallContext;
use _ContaoManager\Symfony\Bundle\SecurityBundle\Security\LazyFirewallContext;
use _ContaoManager\Symfony\Component\HttpKernel\Event\RequestEvent;
use _ContaoManager\Symfony\Component\Security\Http\Authenticator\Debug\TraceableAuthenticatorManagerListener;
use _ContaoManager\Symfony\Component\Security\Http\Firewall\FirewallListenerInterface;
use _ContaoManager\Symfony\Contracts\Service\ResetInterface;
/**
 * Firewall collecting called security listeners and authenticators.
 *
 * @author Robin Chalas <robin.chalas@gmail.com>
 */
final class TraceableFirewallListener extends FirewallListener implements ResetInterface
{
    private array $wrappedListeners = [];
    private array $authenticatorsInfo = [];
    /**
     * @return array
     */
    public function getWrappedListeners()
    {
        return $this->wrappedListeners;
    }
    public function getAuthenticatorsInfo(): array
    {
        return $this->authenticatorsInfo;
    }
    public function reset(): void
    {
        $this->wrappedListeners = [];
        $this->authenticatorsInfo = [];
    }
    protected function callListeners(RequestEvent $event, iterable $listeners): void
    {
        $wrappedListeners = [];
        $wrappedLazyListeners = [];
        $authenticatorManagerListener = null;
        foreach ($listeners as $listener) {
            if ($listener instanceof LazyFirewallContext) {
                \Closure::bind(function () use (&$wrappedLazyListeners, &$wrappedListeners, &$authenticatorManagerListener) {
                    $listeners = [];
                    foreach ($this->listeners as $listener) {
                        if (!$authenticatorManagerListener && $listener instanceof TraceableAuthenticatorManagerListener) {
                            $authenticatorManagerListener = $listener;
                        }
                        if ($listener instanceof FirewallListenerInterface) {
                            $listener = new WrappedLazyListener($listener);
                            $listeners[] = $listener;
                            $wrappedLazyListeners[] = $listener;
                        } else {
                            $listeners[] = function (RequestEvent $event) use ($listener, &$wrappedListeners) {
                                $wrappedListener = new WrappedListener($listener);
                                $wrappedListener($event);
                                $wrappedListeners[] = $wrappedListener->getInfo();
                            };
                        }
                    }
                    $this->listeners = $listeners;
                }, $listener, FirewallContext::class)();
                $listener($event);
            } else {
                $wrappedListener = $listener instanceof FirewallListenerInterface ? new WrappedLazyListener($listener) : new WrappedListener($listener);
                $wrappedListener($event);
                $wrappedListeners[] = $wrappedListener->getInfo();
                if (!$authenticatorManagerListener && $listener instanceof TraceableAuthenticatorManagerListener) {
                    $authenticatorManagerListener = $listener;
                }
            }
            if ($event->hasResponse()) {
                break;
            }
        }
        if ($wrappedLazyListeners) {
            foreach ($wrappedLazyListeners as $lazyListener) {
                $this->wrappedListeners[] = $lazyListener->getInfo();
            }
        }
        $this->wrappedListeners = array_merge($this->wrappedListeners, $wrappedListeners);
        if ($authenticatorManagerListener) {
            $this->authenticatorsInfo = $authenticatorManagerListener->getAuthenticatorsInfo();
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Bundle\SecurityBundle\Debug;

use _ContaoManager\Symfony\Component\HttpKernel\Event\RequestEvent;
/**
 * Wraps a security listener for calls record.
 *
 * @author Robin Chalas <robin.chalas@gmail.com>
 *
 * @internal
 */
final class WrappedListener
{
    use TraceableListenerTrait;
    /**
     * @param callable(RequestEvent):void $listener
     */
    public function __construct(callable $listener)
    {
        $this->listener = $listener;
    }
    public function __invoke(RequestEvent $event): void
    {
        $startTime = microtime(\true);
        ($this->listener)($event);
        $this->time = microtime(\true) - $startTime;
        $this->response = $event->getResponse();
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Bundle\SecurityBundle\Debug;

use _ContaoManager\Symfony\Component\HttpFoundation\Response;
use _ContaoManager\Symfony\Component\Security\Http\Authenticator\Debug\TraceableAuthenticatorManagerListener;
use _ContaoManager\Symfony\Component\VarDumper\Caster\ClassStub;
/**
 * @author Robin Chalas <robin.chalas@gmail.com>
 *
 * @internal
 */
trait TraceableListenerTrait
{
    private ?Response $response = null;
    private mixed $listener;
    private ?float $time = null;
    private object $stub;
    /**
     * Proxies all method calls to the original listener.
     */
    public function __call(string $method, array $arguments): mixed
    {
        return $this->listener->{$method}(...$arguments);
    }
    public function getWrappedListener(): mixed
    {
        return $this->listener;
    }
    public function getInfo(): array
    {
        return ['response' => $this->response, 'time' => $this->time, 'stub' => $this->stub ??= ClassStub::wrapCallable($this->listener instanceof TraceableAuthenticatorManagerListener ? $this->listener->getAuthenticatorManagerListener() : $this->listener)];
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Bundle\SecurityBundle\Debug;

use _ContaoManager\Symfony\Component\HttpFoundation\Request;
use _ContaoManager\Symfony\Component\HttpKernel\Event\RequestEvent;
use _ContaoManager\Symfony\Component\Security\Core\Exception\LazyResponseException;
use _ContaoManager\Symfony\Component\Security\Http\Firewall\AbstractListener;
use _ContaoManager\Symfony\Component\Security\Http\Firewall\FirewallListenerInterface;
/**
 * Wraps a lazy security listener.
 *
 * @author Robin Chalas <robin.chalas@gmail.com>
 *
 * @internal
 */
final class WrappedLazyListener extends AbstractListener
{
    use TraceableListenerTrait;
    public function __construct(FirewallListenerInterface $listener)
    {
        $this->listener = $listener;
    }
    public function supports(Request $request): ?bool
    {
        return $this->listener->supports($request);
    }
    public function authenticate(RequestEvent $event): void
    {
        $startTime = microtime(\true);
        try {
            $this->listener->authenticate($event);
        } catch (LazyResponseException $e) {
            $this->response = $e->getResponse();
            throw $e;
        } finally {
            $this->time = microtime(\true) - $startTime;
        }
        $this->response = $event->getResponse();
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Bundle\SecurityBundle\EventListener;

use _ContaoManager\Symfony\Bundle\SecurityBundle\Security\FirewallMap;
use _ContaoManager\Symfony\Component\HttpKernel\Event\FinishRequestEvent;
use _ContaoManager\Symfony\Component\HttpKernel\Event\RequestEvent;
use _ContaoManager\Symfony\Component\HttpKernel\KernelEvents;
use _ContaoManager\Symfony\Component\Security\Http\Firewall;
use _ContaoManager\Symfony\Component\Security\Http\FirewallMapInterface;
use _ContaoManager\Symfony\Component\Security\Http\Logout\LogoutUrlGenerator;
use _ContaoManager\Symfony\Contracts\EventDispatcher\EventDispatcherInterface;
/**
 * @author Maxime Steinhausser <maxime.steinhausser@gmail.com>
 */
class FirewallListener extends Firewall
{
    private FirewallMapInterface $map;
    private LogoutUrlGenerator $logoutUrlGenerator;
    public function __construct(FirewallMapInterface $map, EventDispatcherInterface $dispatcher, LogoutUrlGenerator $logoutUrlGenerator)
    {
        $this->map = $map;
        $this->logoutUrlGenerator = $logoutUrlGenerator;
        parent::__construct($map, $dispatcher);
    }
    /**
     * @return void
     */
    public function configureLogoutUrlGenerator(RequestEvent $event)
    {
        if (!$event->isMainRequest()) {
            return;
        }
        if ($this->map instanceof FirewallMap && $config = $this->map->getFirewallConfig($event->getRequest())) {
            $this->logoutUrlGenerator->setCurrentFirewall($config->getName(), $config->getContext());
        }
    }
    /**
     * @return void
     */
    public function onKernelFinishRequest(FinishRequestEvent $event)
    {
        if ($event->isMainRequest()) {
            $this->logoutUrlGenerator->setCurrentFirewall(null);
        }
        parent::onKernelFinishRequest($event);
    }
    public static function getSubscribedEvents(): array
    {
        return [KernelEvents::REQUEST => [['configureLogoutUrlGenerator', 8], ['onKernelRequest', 8]], KernelEvents::FINISH_REQUEST => 'onKernelFinishRequest'];
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Bundle\SecurityBundle\EventListener;

use _ContaoManager\Symfony\Component\EventDispatcher\EventSubscriberInterface;
use _ContaoManager\Symfony\Component\Security\Core\Authorization\TraceableAccessDecisionManager;
use _ContaoManager\Symfony\Component\Security\Core\Event\VoteEvent;
/**
 * Listen to vote events from traceable voters.
 *
 * @author Laurent VOULLEMIER <laurent.voullemier@gmail.com>
 *
 * @internal
 */
class VoteListener implements EventSubscriberInterface
{
    private TraceableAccessDecisionManager $traceableAccessDecisionManager;
    public function __construct(TraceableAccessDecisionManager $traceableAccessDecisionManager)
    {
        $this->traceableAccessDecisionManager = $traceableAccessDecisionManager;
    }
    public function onVoterVote(VoteEvent $event): void
    {
        $this->traceableAccessDecisionManager->addVoterVote($event->getVoter(), $event->getAttributes(), $event->getVote());
    }
    public static function getSubscribedEvents(): array
    {
        return ['debug.security.authorization.vote' => 'onVoterVote'];
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Config;

use _ContaoManager\Symfony\Component\Config\Resource\ResourceInterface;
use _ContaoManager\Symfony\Component\Filesystem\Exception\IOException;
use _ContaoManager\Symfony\Component\Filesystem\Filesystem;
/**
 * ResourceCheckerConfigCache uses instances of ResourceCheckerInterface
 * to check whether cached data is still fresh.
 *
 * @author Matthias Pigulla <mp@webfactory.de>
 */
class ResourceCheckerConfigCache implements ConfigCacheInterface
{
    private string $file;
    /**
     * @var iterable<mixed, ResourceCheckerInterface>
     */
    private iterable $resourceCheckers;
    /**
     * @param string                                    $file             The absolute cache path
     * @param iterable<mixed, ResourceCheckerInterface> $resourceCheckers The ResourceCheckers to use for the freshness check
     */
    public function __construct(string $file, iterable $resourceCheckers = [])
    {
        $this->file = $file;
        $this->resourceCheckers = $resourceCheckers;
    }
    public function getPath(): string
    {
        return $this->file;
    }
    /**
     * Checks if the cache is still fresh.
     *
     * This implementation will make a decision solely based on the ResourceCheckers
     * passed in the constructor.
     *
     * The first ResourceChecker that supports a given resource is considered authoritative.
     * Resources with no matching ResourceChecker will silently be ignored and considered fresh.
     */
    public function isFresh(): bool
    {
        if (!is_file($this->file)) {
            return \false;
        }
        if ($this->resourceCheckers instanceof \Traversable && !$this->resourceCheckers instanceof \Countable) {
            $this->resourceCheckers = iterator_to_array($this->resourceCheckers);
        }
        if (!\count($this->resourceCheckers)) {
            return \true;
            // shortcut - if we don't have any checkers we don't need to bother with the meta file at all
        }
        $metadata = $this->getMetaFile();
        if (!is_file($metadata)) {
            return \false;
        }
        $meta = $this->safelyUnserialize($metadata);
        if (\false === $meta) {
            return \false;
        }
        $time = filemtime($this->file);
        foreach ($meta as $resource) {
            foreach ($this->resourceCheckers as $checker) {
                if (!$checker->supports($resource)) {
                    continue;
                    // next checker
                }
                if ($checker->isFresh($resource, $time)) {
                    break;
                    // no need to further check this resource
                }
                return \false;
                // cache is stale
            }
            // no suitable checker found, ignore this resource
        }
        return \true;
    }
    /**
     * Writes cache.
     *
     * @param string              $content  The content to write in the cache
     * @param ResourceInterface[] $metadata An array of metadata
     *
     * @return void
     *
     * @throws \RuntimeException When cache file can't be written
     */
    public function write(string $content, ?array $metadata = null)
    {
        $mode = 0666;
        $umask = umask();
        $filesystem = new Filesystem();
        $filesystem->dumpFile($this->file, $content);
        try {
            $filesystem->chmod($this->file, $mode, $umask);
        } catch (IOException) {
            // discard chmod failure (some filesystem may not support it)
        }
        if (null !== $metadata) {
            $filesystem->dumpFile($this->getMetaFile(), serialize($metadata));
            try {
                $filesystem->chmod($this->getMetaFile(), $mode, $umask);
            } catch (IOException) {
                // discard chmod failure (some filesystem may not support it)
            }
        }
        if (\function_exists('opcache_invalidate') && filter_var(\ini_get('opcache.enable'), \FILTER_VALIDATE_BOOL)) {
            @opcache_invalidate($this->file, \true);
        }
    }
    /**
     * Gets the meta file path.
     */
    private function getMetaFile(): string
    {
        return $this->file . '.meta';
    }
    private function safelyUnserialize(string $file): mixed
    {
        $meta = \false;
        $content = file_get_contents($file);
        $signalingException = new \UnexpectedValueException();
        $prevUnserializeHandler = ini_set('unserialize_callback_func', self::class . '::handleUnserializeCallback');
        $prevErrorHandler = set_error_handler(function ($type, $msg, $file, $line, $context = []) use (&$prevErrorHandler, $signalingException) {
            if (__FILE__ === $file && !\in_array($type, [\E_DEPRECATED, \E_USER_DEPRECATED], \true)) {
                throw $signalingException;
            }
            return $prevErrorHandler ? $prevErrorHandler($type, $msg, $file, $line, $context) : \false;
        });
        try {
            $meta = unserialize($content);
        } catch (\Throwable $e) {
            if ($e !== $signalingException) {
                throw $e;
            }
        } finally {
            restore_error_handler();
            ini_set('unserialize_callback_func', $prevUnserializeHandler);
        }
        return $meta;
    }
    /**
     * @internal
     */
    public static function handleUnserializeCallback(string $class): void
    {
        trigger_error('Class not found: ' . $class);
    }
}
Copyright (c) 2004-present Fabien Potencier

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is furnished
to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Config\Util;

use _ContaoManager\Symfony\Component\Config\Util\Exception\InvalidXmlException;
use _ContaoManager\Symfony\Component\Config\Util\Exception\XmlParsingException;
/**
 * XMLUtils is a bunch of utility methods to XML operations.
 *
 * This class contains static methods only and is not meant to be instantiated.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 * @author Martin Hasoň <martin.hason@gmail.com>
 * @author Ole Rößner <ole@roessner.it>
 */
class XmlUtils
{
    /**
     * This class should not be instantiated.
     */
    private function __construct()
    {
    }
    /**
     * Parses an XML string.
     *
     * @param string               $content          An XML string
     * @param string|callable|null $schemaOrCallable An XSD schema file path, a callable, or null to disable validation
     *
     * @throws XmlParsingException When parsing of XML file returns error
     * @throws InvalidXmlException When parsing of XML with schema or callable produces any errors unrelated to the XML parsing itself
     * @throws \RuntimeException   When DOM extension is missing
     */
    public static function parse(string $content, string|callable|null $schemaOrCallable = null): \DOMDocument
    {
        if (!\extension_loaded('dom')) {
            throw new \LogicException('Extension DOM is required.');
        }
        $internalErrors = libxml_use_internal_errors(\true);
        libxml_clear_errors();
        $dom = new \DOMDocument();
        $dom->validateOnParse = \true;
        if (!$dom->loadXML($content, \LIBXML_NONET | \LIBXML_COMPACT)) {
            throw new XmlParsingException(implode("\n", static::getXmlErrors($internalErrors)));
        }
        $dom->normalizeDocument();
        libxml_use_internal_errors($internalErrors);
        foreach ($dom->childNodes as $child) {
            if (\XML_DOCUMENT_TYPE_NODE === $child->nodeType) {
                throw new XmlParsingException('Document types are not allowed.');
            }
        }
        if (null !== $schemaOrCallable) {
            $internalErrors = libxml_use_internal_errors(\true);
            libxml_clear_errors();
            $e = null;
            if (\is_callable($schemaOrCallable)) {
                try {
                    $valid = $schemaOrCallable($dom, $internalErrors);
                } catch (\Exception $e) {
                    $valid = \false;
                }
            } elseif (is_file($schemaOrCallable)) {
                $schemaSource = file_get_contents((string) $schemaOrCallable);
                $valid = @$dom->schemaValidateSource($schemaSource);
            } else {
                libxml_use_internal_errors($internalErrors);
                throw new XmlParsingException(\sprintf('Invalid XSD file: "%s".', $schemaOrCallable));
            }
            if (!$valid) {
                $messages = static::getXmlErrors($internalErrors);
                if (!$messages) {
                    throw new InvalidXmlException('The XML is not valid.', 0, $e);
                }
                throw new XmlParsingException(implode("\n", $messages), 0, $e);
            }
        }
        libxml_clear_errors();
        libxml_use_internal_errors($internalErrors);
        return $dom;
    }
    /**
     * Loads an XML file.
     *
     * @param string               $file             An XML file path
     * @param string|callable|null $schemaOrCallable An XSD schema file path, a callable, or null to disable validation
     *
     * @throws \InvalidArgumentException When loading of XML file returns error
     * @throws XmlParsingException       When XML parsing returns any errors
     * @throws \RuntimeException         When DOM extension is missing
     */
    public static function loadFile(string $file, string|callable|null $schemaOrCallable = null): \DOMDocument
    {
        if (!is_file($file)) {
            throw new \InvalidArgumentException(\sprintf('Resource "%s" is not a file.', $file));
        }
        if (!is_readable($file)) {
            throw new \InvalidArgumentException(\sprintf('File "%s" is not readable.', $file));
        }
        $content = @file_get_contents($file);
        if ('' === trim($content)) {
            throw new \InvalidArgumentException(\sprintf('File "%s" does not contain valid XML, it is empty.', $file));
        }
        try {
            return static::parse($content, $schemaOrCallable);
        } catch (InvalidXmlException $e) {
            throw new XmlParsingException(\sprintf('The XML file "%s" is not valid.', $file), 0, $e->getPrevious());
        }
    }
    /**
     * Converts a \DOMElement object to a PHP array.
     *
     * The following rules applies during the conversion:
     *
     *  * Each tag is converted to a key value or an array
     *    if there is more than one "value"
     *
     *  * The content of a tag is set under a "value" key (<foo>bar</foo>)
     *    if the tag also has some nested tags
     *
     *  * The attributes are converted to keys (<foo foo="bar"/>)
     *
     *  * The nested-tags are converted to keys (<foo><foo>bar</foo></foo>)
     *
     * @param \DOMElement $element     A \DOMElement instance
     * @param bool        $checkPrefix Check prefix in an element or an attribute name
     */
    public static function convertDomElementToArray(\DOMElement $element, bool $checkPrefix = \true): mixed
    {
        $prefix = (string) $element->prefix;
        $empty = \true;
        $config = [];
        foreach ($element->attributes as $name => $node) {
            if ($checkPrefix && !\in_array((string) $node->prefix, ['', $prefix], \true)) {
                continue;
            }
            $config[$name] = static::phpize($node->value);
            $empty = \false;
        }
        $nodeValue = \false;
        foreach ($element->childNodes as $node) {
            if ($node instanceof \DOMText) {
                if ('' !== trim($node->nodeValue)) {
                    $nodeValue = trim($node->nodeValue);
                    $empty = \false;
                }
            } elseif ($checkPrefix && $prefix != (string) $node->prefix) {
                continue;
            } elseif (!$node instanceof \DOMComment) {
                $value = static::convertDomElementToArray($node, $checkPrefix);
                $key = $node->localName;
                if (isset($config[$key])) {
                    if (!\is_array($config[$key]) || !\is_int(key($config[$key]))) {
                        $config[$key] = [$config[$key]];
                    }
                    $config[$key][] = $value;
                } else {
                    $config[$key] = $value;
                }
                $empty = \false;
            }
        }
        if (\false !== $nodeValue) {
            $value = static::phpize($nodeValue);
            if (\count($config)) {
                $config['value'] = $value;
            } else {
                $config = $value;
            }
        }
        return !$empty ? $config : null;
    }
    /**
     * Converts an xml value to a PHP type.
     */
    public static function phpize(string|\Stringable $value): mixed
    {
        $value = (string) $value;
        $lowercaseValue = strtolower($value);
        switch (\true) {
            case 'null' === $lowercaseValue:
                return null;
            case ctype_digit($value):
            case isset($value[1]) && '-' === $value[0] && ctype_digit(substr($value, 1)):
                $raw = $value;
                $cast = (int) $value;
                return self::isOctal($value) ? \intval($value, 8) : ($raw === (string) $cast ? $cast : $raw);
            case 'true' === $lowercaseValue:
                return \true;
            case 'false' === $lowercaseValue:
                return \false;
            case isset($value[1]) && '0b' == $value[0] . $value[1] && preg_match('/^0b[01]*$/', $value):
                return bindec($value);
            case is_numeric($value):
                return '0x' === $value[0] . $value[1] ? hexdec($value) : (float) $value;
            case preg_match('/^0x[0-9a-f]++$/i', $value):
                return hexdec($value);
            case preg_match('/^[+-]?[0-9]+(\.[0-9]+)?$/', $value):
                return (float) $value;
            default:
                return $value;
        }
    }
    /**
     * @return array
     */
    protected static function getXmlErrors(bool $internalErrors)
    {
        $errors = [];
        foreach (libxml_get_errors() as $error) {
            $errors[] = \sprintf('[%s %s] %s (in %s - line %d, column %d)', \LIBXML_ERR_WARNING == $error->level ? 'WARNING' : 'ERROR', $error->code, trim($error->message), $error->file ?: 'n/a', $error->line, $error->column);
        }
        libxml_clear_errors();
        libxml_use_internal_errors($internalErrors);
        return $errors;
    }
    private static function isOctal(string $str): bool
    {
        if ('-' === $str[0]) {
            $str = substr($str, 1);
        }
        return $str === '0' . decoct(\intval($str, 8));
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Config\Util\Exception;

/**
 * Exception class for when XML cannot be parsed properly.
 *
 * @author Ole Rößner <ole@roessner.it>
 */
class XmlParsingException extends \InvalidArgumentException
{
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Config\Util\Exception;

/**
 * Exception class for when XML parsing with an XSD schema file path or a callable validator produces errors unrelated
 * to the actual XML parsing.
 *
 * @author Ole Rößner <ole@roessner.it>
 */
class InvalidXmlException extends XmlParsingException
{
}
CHANGELOG
=========

6.3
---

 * Allow enum values in `EnumNode`

6.2
---

 * Deprecate calling `NodeBuilder::setParent()` without any arguments
 * Add a more accurate typehint in generated PHP config

6.1
---

 * Allow using environment variables in `EnumNode`
 * Add Node's information in generated Config
 * Add `DefinitionFileLoader` class to load a TreeBuilder definition from an external file
 * Add `DefinitionConfigurator` helper

6.0
---

 * Remove `BaseNode::getDeprecationMessage()`

5.3.0
-----

 * Add support for generating `ConfigBuilder` for extensions

5.1.0
-----

 * updated the signature of method `NodeDefinition::setDeprecated()` to `NodeDefinition::setDeprecation(string $package, string $version, string $message)`
 * updated the signature of method `BaseNode::setDeprecated()` to `BaseNode::setDeprecation(string $package, string $version, string $message)`
 * deprecated passing a null message to `BaseNode::setDeprecated()` to un-deprecate a node
 * deprecated `BaseNode::getDeprecationMessage()`, use `BaseNode::getDeprecation()` instead

5.0.0
-----

 * Dropped support for constructing a `TreeBuilder` without passing root node information.
 * Removed the `root()` method in `TreeBuilder`, pass the root node information to the constructor instead
 * Added method `getChildNodeDefinitions()` to ParentNodeDefinitionInterface
 * Removed `FileLoaderLoadException`, use `LoaderLoadException` instead

4.4.0
-----

 * added a way to exclude patterns of resources from being imported by the `import()` method

4.3.0
-----

 * deprecated using environment variables with `cannotBeEmpty()` if the value is validated with `validate()`
 * made `Resource\*` classes final and not implement `Serializable` anymore
 * deprecated the `root()` method in `TreeBuilder`, pass the root node information to the constructor instead

4.2.0
-----

 * deprecated constructing a `TreeBuilder` without passing root node information
 * renamed `FileLoaderLoadException` to `LoaderLoadException`

4.1.0
-----

 * added `setPathSeparator` method to `NodeBuilder` class
 * added third `$pathSeparator` constructor argument to `BaseNode`
 * the `Processor` class has been made final

4.0.0
-----

 * removed `ConfigCachePass`

3.4.0
-----

 * added `setDeprecated()` method to indicate a deprecated node
 * added `XmlUtils::parse()` method to parse an XML string
 * deprecated `ConfigCachePass`

3.3.0
-----

 * added `ReflectionClassResource` class
 * added second `$exists` constructor argument to `ClassExistenceResource`
 * made `ClassExistenceResource` work with interfaces and traits
 * added `ConfigCachePass` (originally in FrameworkBundle)
 * added `castToArray()` helper to turn any config value into an array

3.0.0
-----

 * removed `ReferenceDumper` class
 * removed the `ResourceInterface::isFresh()` method
 * removed `BCResourceInterfaceChecker` class
 * removed `ResourceInterface::getResource()` method

2.8.0
-----

The edge case of defining just one value for nodes of type Enum is now allowed:

```php
$rootNode
    ->children()
        ->enumNode('variable')
            ->values(['value'])
        ->end()
    ->end()
;
```

Before: `InvalidArgumentException` (variable must contain at least two
distinct elements).
After: the code will work as expected and it will restrict the values of the
`variable` option to just `value`.

 * deprecated the `ResourceInterface::isFresh()` method. If you implement custom resource types and they
   can be validated that way, make them implement the new `SelfCheckingResourceInterface`.
 * deprecated the getResource() method in ResourceInterface. You can still call this method
   on concrete classes implementing the interface, but it does not make sense at the interface
   level as you need to know about the particular type of resource at hand to understand the
   semantics of the returned value.

2.7.0
-----

 * added `ConfigCacheInterface`, `ConfigCacheFactoryInterface` and a basic `ConfigCacheFactory`
   implementation to delegate creation of ConfigCache instances

2.2.0
-----

 * added `ArrayNodeDefinition::canBeEnabled()` and `ArrayNodeDefinition::canBeDisabled()`
   to ease configuration when some sections are respectively disabled / enabled
   by default.
 * added a `normalizeKeys()` method for array nodes (to avoid key normalization)
 * added numerical type handling for config definitions
 * added convenience methods for optional configuration sections to `ArrayNodeDefinition`
 * added a utils class for XML manipulations

2.1.0
-----

 * added a way to add documentation on configuration
 * implemented `Serializable` on resources
 * `LoaderResolverInterface` is now used instead of `LoaderResolver` for type
   hinting
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Config;

use _ContaoManager\Symfony\Component\Config\Resource\ResourceInterface;
/**
 * Interface for ConfigCache.
 *
 * @author Matthias Pigulla <mp@webfactory.de>
 */
interface ConfigCacheInterface
{
    /**
     * Gets the cache file path.
     */
    public function getPath(): string;
    /**
     * Checks if the cache is still fresh.
     *
     * This check should take the metadata passed to the write() method into consideration.
     */
    public function isFresh(): bool;
    /**
     * Writes the given content into the cache file. Metadata will be stored
     * independently and can be used to check cache freshness at a later time.
     *
     * @param string                   $content  The content to write into the cache
     * @param ResourceInterface[]|null $metadata An array of ResourceInterface instances
     *
     * @return void
     *
     * @throws \RuntimeException When the cache file cannot be written
     */
    public function write(string $content, ?array $metadata = null);
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Config;

use _ContaoManager\Symfony\Component\Config\Exception\FileLocatorFileNotFoundException;
/**
 * @author Fabien Potencier <fabien@symfony.com>
 */
interface FileLocatorInterface
{
    /**
     * Returns a full path for a given file name.
     *
     * @param string      $name        The file name to locate
     * @param string|null $currentPath The current path
     * @param bool        $first       Whether to return the first occurrence or an array of filenames
     *
     * @return string|string[] The full path to the file or an array of file paths
     *
     * @psalm-return ($first is true ? string : string[])
     *
     * @throws \InvalidArgumentException        If $name is empty
     * @throws FileLocatorFileNotFoundException If a file is not found
     */
    public function locate(string $name, ?string $currentPath = null, bool $first = \true);
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Config;

use _ContaoManager\Symfony\Component\Config\Resource\SelfCheckingResourceChecker;
/**
 * ConfigCache caches arbitrary content in files on disk.
 *
 * When in debug mode, those metadata resources that implement
 * \Symfony\Component\Config\Resource\SelfCheckingResourceInterface will
 * be used to check cache freshness.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 * @author Matthias Pigulla <mp@webfactory.de>
 */
class ConfigCache extends ResourceCheckerConfigCache
{
    private bool $debug;
    /**
     * @param string $file  The absolute cache path
     * @param bool   $debug Whether debugging is enabled or not
     */
    public function __construct(string $file, bool $debug)
    {
        $this->debug = $debug;
        $checkers = [];
        if (\true === $this->debug) {
            $checkers = [new SelfCheckingResourceChecker()];
        }
        parent::__construct($file, $checkers);
    }
    /**
     * Checks if the cache is still fresh.
     *
     * This implementation always returns true when debug is off and the
     * cache file exists.
     */
    public function isFresh(): bool
    {
        if (!$this->debug && is_file($this->getPath())) {
            return \true;
        }
        return parent::isFresh();
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Config;

/**
 * Interface for a ConfigCache factory. This factory creates
 * an instance of ConfigCacheInterface and initializes the
 * cache if necessary.
 *
 * @author Matthias Pigulla <mp@webfactory.de>
 */
interface ConfigCacheFactoryInterface
{
    /**
     * Creates a cache instance and (re-)initializes it if necessary.
     *
     * @param string   $file     The absolute cache file path
     * @param callable $callable The callable to be executed when the cache needs to be filled (i. e. is not fresh). The cache will be passed as the only parameter to this callback
     */
    public function cache(string $file, callable $callable): ConfigCacheInterface;
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Config;

use _ContaoManager\Symfony\Component\Config\Exception\FileLocatorFileNotFoundException;
/**
 * FileLocator uses an array of pre-defined paths to find files.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class FileLocator implements FileLocatorInterface
{
    protected $paths;
    /**
     * @param string|string[] $paths A path or an array of paths where to look for resources
     */
    public function __construct(string|array $paths = [])
    {
        $this->paths = (array) $paths;
    }
    /**
     * @return string|string[]
     *
     * @psalm-return ($first is true ? string : string[])
     */
    public function locate(string $name, ?string $currentPath = null, bool $first = \true)
    {
        if ('' === $name) {
            throw new \InvalidArgumentException('An empty file name is not valid to be located.');
        }
        if ($this->isAbsolutePath($name)) {
            if (!file_exists($name)) {
                throw new FileLocatorFileNotFoundException(\sprintf('The file "%s" does not exist.', $name), 0, null, [$name]);
            }
            return $name;
        }
        $paths = $this->paths;
        if (null !== $currentPath) {
            array_unshift($paths, $currentPath);
        }
        $paths = array_unique($paths);
        $filepaths = $notfound = [];
        foreach ($paths as $path) {
            if (@file_exists($file = $path . \DIRECTORY_SEPARATOR . $name)) {
                if (\true === $first) {
                    return $file;
                }
                $filepaths[] = $file;
            } else {
                $notfound[] = $file;
            }
        }
        if (!$filepaths) {
            throw new FileLocatorFileNotFoundException(\sprintf('The file "%s" does not exist (in: "%s").', $name, implode('", "', $paths)), 0, null, $notfound);
        }
        return $filepaths;
    }
    /**
     * Returns whether the file path is an absolute path.
     */
    private function isAbsolutePath(string $file): bool
    {
        if ('/' === $file[0] || '\\' === $file[0] || \strlen($file) > 3 && ctype_alpha($file[0]) && ':' === $file[1] && ('\\' === $file[2] || '/' === $file[2]) || parse_url($file, \PHP_URL_SCHEME) || str_starts_with($file, 'phar:///')) {
            return \true;
        }
        return \false;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Config;

use _ContaoManager\Symfony\Component\Config\Resource\ResourceInterface;
/**
 * Interface for ResourceCheckers.
 *
 * When a ResourceCheckerConfigCache instance is checked for freshness, all its associated
 * metadata resources are passed to ResourceCheckers. The ResourceCheckers
 * can then inspect the resources and decide whether the cache can be considered
 * fresh or not.
 *
 * @author Matthias Pigulla <mp@webfactory.de>
 * @author Benjamin Klotz <bk@webfactory.de>
 */
interface ResourceCheckerInterface
{
    /**
     * Queries the ResourceChecker whether it can validate a given
     * resource or not.
     *
     * @return bool
     */
    public function supports(ResourceInterface $metadata);
    /**
     * Validates the resource.
     *
     * @param int $timestamp The timestamp at which the cache associated with this resource was created
     *
     * @return bool
     */
    public function isFresh(ResourceInterface $resource, int $timestamp);
}
Config Component
================

The Config component helps find, load, combine, autofill and validate
configuration values of any kind, whatever their source may be (YAML, XML, INI
files, or for instance a database).

Resources
---------

 * [Documentation](https://symfony.com/doc/current/components/config.html)
 * [Contributing](https://symfony.com/doc/current/contributing/index.html)
 * [Report issues](https://github.com/symfony/symfony/issues) and
   [send Pull Requests](https://github.com/symfony/symfony/pulls)
   in the [main Symfony repository](https://github.com/symfony/symfony)
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Config\Loader;

use _ContaoManager\Symfony\Component\Config\Exception\LoaderLoadException;
/**
 * Loader is the abstract class used by all built-in loaders.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
abstract class Loader implements LoaderInterface
{
    protected $resolver;
    protected $env;
    public function __construct(?string $env = null)
    {
        $this->env = $env;
    }
    public function getResolver(): LoaderResolverInterface
    {
        return $this->resolver;
    }
    /**
     * @return void
     */
    public function setResolver(LoaderResolverInterface $resolver)
    {
        $this->resolver = $resolver;
    }
    /**
     * Imports a resource.
     *
     * @return mixed
     */
    public function import(mixed $resource, ?string $type = null)
    {
        return $this->resolve($resource, $type)->load($resource, $type);
    }
    /**
     * Finds a loader able to load an imported resource.
     *
     * @throws LoaderLoadException If no loader is found
     */
    public function resolve(mixed $resource, ?string $type = null): LoaderInterface
    {
        if ($this->supports($resource, $type)) {
            return $this;
        }
        $loader = null === $this->resolver ? \false : $this->resolver->resolve($resource, $type);
        if (\false === $loader) {
            throw new LoaderLoadException($resource, null, 0, null, $type);
        }
        return $loader;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Config\Loader;

/**
 * A loader that can be scoped to a given filesystem directory.
 *
 * @author Alexander M. Turek <me@derrabus.de>
 */
interface DirectoryAwareLoaderInterface
{
    public function forDirectory(string $currentDirectory): static;
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Config\Loader;

use _ContaoManager\Symfony\Component\Config\Exception\FileLoaderImportCircularReferenceException;
use _ContaoManager\Symfony\Component\Config\Exception\FileLocatorFileNotFoundException;
use _ContaoManager\Symfony\Component\Config\Exception\LoaderLoadException;
use _ContaoManager\Symfony\Component\Config\FileLocatorInterface;
use _ContaoManager\Symfony\Component\Config\Resource\FileExistenceResource;
use _ContaoManager\Symfony\Component\Config\Resource\GlobResource;
/**
 * FileLoader is the abstract class used by all built-in loaders that are file based.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
abstract class FileLoader extends Loader
{
    protected static $loading = [];
    protected $locator;
    private ?string $currentDir = null;
    public function __construct(FileLocatorInterface $locator, ?string $env = null)
    {
        $this->locator = $locator;
        parent::__construct($env);
    }
    /**
     * Sets the current directory.
     *
     * @return void
     */
    public function setCurrentDir(string $dir)
    {
        $this->currentDir = $dir;
    }
    /**
     * Returns the file locator used by this loader.
     */
    public function getLocator(): FileLocatorInterface
    {
        return $this->locator;
    }
    /**
     * Imports a resource.
     *
     * @param mixed                $resource       A Resource
     * @param string|null          $type           The resource type or null if unknown
     * @param bool                 $ignoreErrors   Whether to ignore import errors or not
     * @param string|null          $sourceResource The original resource importing the new resource
     * @param string|string[]|null $exclude        Glob patterns to exclude from the import
     *
     * @return mixed
     *
     * @throws LoaderLoadException
     * @throws FileLoaderImportCircularReferenceException
     * @throws FileLocatorFileNotFoundException
     */
    public function import(mixed $resource, ?string $type = null, bool $ignoreErrors = \false, ?string $sourceResource = null, string|array|null $exclude = null)
    {
        $excluded = [];
        foreach ((array) $exclude as $pattern) {
            foreach ($this->glob($pattern, \true, $_, \false, \true) as $path => $info) {
                // normalize Windows slashes and remove trailing slashes
                $excluded[rtrim(str_replace('\\', '/', $path), '/')] = \true;
            }
        }
        if (\is_string($resource) && !class_exists($resource)) {
            $isGlobPattern = \strlen($resource) !== strcspn($resource, '*?{[');
            if (!$isGlobPattern && $excluded) {
                $resource = rtrim(str_replace('\\', '/', $resource), '/');
                $resource .= '/**/*';
                $isGlobPattern = \true;
            }
            if ($isGlobPattern && !str_contains($resource, "\n")) {
                $ret = [];
                $i = strcspn($resource, '*?{[');
                $isSubpath = 0 !== $i && str_contains(substr($resource, 0, $i), '/');
                foreach ($this->glob($resource, \false, $_, $ignoreErrors || !$isSubpath, \false, $excluded) as $path => $info) {
                    if (null !== $res = $this->doImport($path, 'glob' === $type ? null : $type, $ignoreErrors, $sourceResource)) {
                        $ret[] = $res;
                    }
                    $isSubpath = \true;
                }
                if ($isSubpath) {
                    return isset($ret[1]) ? $ret : $ret[0] ?? null;
                }
            }
        } elseif (\is_array($resource) && $excluded) {
            $resource['_excluded'] = $excluded;
        }
        return $this->doImport($resource, $type, $ignoreErrors, $sourceResource);
    }
    /**
     * @internal
     */
    protected function glob(string $pattern, bool $recursive, array|GlobResource|null &$resource = null, bool $ignoreErrors = \false, bool $forExclusion = \false, array $excluded = []): iterable
    {
        if (\strlen($pattern) === $i = strcspn($pattern, '*?{[')) {
            $prefix = $pattern;
            $pattern = '';
        } elseif (0 === $i || !str_contains(substr($pattern, 0, $i), '/')) {
            $prefix = '.';
            $pattern = '/' . $pattern;
        } else {
            $prefix = \dirname(substr($pattern, 0, 1 + $i));
            $pattern = substr($pattern, \strlen($prefix));
        }
        try {
            $prefix = $this->locator->locate($prefix, $this->currentDir, \true);
        } catch (FileLocatorFileNotFoundException $e) {
            if (!$ignoreErrors) {
                throw $e;
            }
            $resource = [];
            foreach ($e->getPaths() as $path) {
                $resource[] = new FileExistenceResource($path);
            }
            return;
        }
        $resource = new GlobResource($prefix, $pattern, $recursive, $forExclusion, $excluded);
        yield from $resource;
    }
    private function doImport(mixed $resource, ?string $type = null, bool $ignoreErrors = \false, ?string $sourceResource = null): mixed
    {
        try {
            $loader = $this->resolve($resource, $type);
            if ($loader instanceof DirectoryAwareLoaderInterface) {
                $loader = $loader->forDirectory($this->currentDir);
            }
            if (!$loader instanceof self) {
                return $loader->load($resource, $type);
            }
            if (null !== $this->currentDir) {
                $resource = $loader->getLocator()->locate($resource, $this->currentDir, \false);
            }
            $resources = \is_array($resource) ? $resource : [$resource];
            for ($i = 0; $i < $resourcesCount = \count($resources); ++$i) {
                if (isset(self::$loading[$resources[$i]])) {
                    if ($i == $resourcesCount - 1) {
                        throw new FileLoaderImportCircularReferenceException(array_keys(self::$loading));
                    }
                } else {
                    $resource = $resources[$i];
                    break;
                }
            }
            self::$loading[$resource] = \true;
            try {
                $ret = $loader->load($resource, $type);
            } finally {
                unset(self::$loading[$resource]);
            }
            return $ret;
        } catch (FileLoaderImportCircularReferenceException $e) {
            throw $e;
        } catch (\Exception $e) {
            if (!$ignoreErrors) {
                // prevent embedded imports from nesting multiple exceptions
                if ($e instanceof LoaderLoadException) {
                    throw $e;
                }
                throw new LoaderLoadException($resource, $sourceResource, 0, $e, $type);
            }
        }
        return null;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Config\Loader;

/**
 * Placeholder for a parameter.
 *
 * @author Tobias Nyholm <tobias.nyholm@gmail.com>
 */
class ParamConfigurator
{
    private string $name;
    public function __construct(string $name)
    {
        $this->name = $name;
    }
    public function __toString(): string
    {
        return '%' . $this->name . '%';
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Config\Loader;

/**
 * LoaderInterface is the interface implemented by all loader classes.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
interface LoaderInterface
{
    /**
     * Loads a resource.
     *
     * @return mixed
     *
     * @throws \Exception If something went wrong
     */
    public function load(mixed $resource, ?string $type = null);
    /**
     * Returns whether this class supports the given resource.
     *
     * @param mixed $resource A resource
     *
     * @return bool
     */
    public function supports(mixed $resource, ?string $type = null);
    /**
     * Gets the loader resolver.
     *
     * @return LoaderResolverInterface
     */
    public function getResolver();
    /**
     * Sets the loader resolver.
     *
     * @return void
     */
    public function setResolver(LoaderResolverInterface $resolver);
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Config\Loader;

/**
 * LoaderResolverInterface selects a loader for a given resource.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
interface LoaderResolverInterface
{
    /**
     * Returns a loader able to load the resource.
     *
     * @param string|null $type The resource type or null if unknown
     */
    public function resolve(mixed $resource, ?string $type = null): LoaderInterface|false;
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Config\Loader;

/**
 * LoaderResolver selects a loader for a given resource.
 *
 * A resource can be anything (e.g. a full path to a config file or a Closure).
 * Each loader determines whether it can load a resource and how.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class LoaderResolver implements LoaderResolverInterface
{
    /**
     * @var LoaderInterface[] An array of LoaderInterface objects
     */
    private array $loaders = [];
    /**
     * @param LoaderInterface[] $loaders An array of loaders
     */
    public function __construct(array $loaders = [])
    {
        foreach ($loaders as $loader) {
            $this->addLoader($loader);
        }
    }
    public function resolve(mixed $resource, ?string $type = null): LoaderInterface|false
    {
        foreach ($this->loaders as $loader) {
            if ($loader->supports($resource, $type)) {
                return $loader;
            }
        }
        return \false;
    }
    /**
     * @return void
     */
    public function addLoader(LoaderInterface $loader)
    {
        $this->loaders[] = $loader;
        $loader->setResolver($this);
    }
    /**
     * Returns the registered loaders.
     *
     * @return LoaderInterface[]
     */
    public function getLoaders(): array
    {
        return $this->loaders;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Config\Loader;

use _ContaoManager\Symfony\Component\Config\Exception\LoaderLoadException;
/**
 * DelegatingLoader delegates loading to other loaders using a loader resolver.
 *
 * This loader acts as an array of LoaderInterface objects - each having
 * a chance to load a given resource (handled by the resolver)
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class DelegatingLoader extends Loader
{
    public function __construct(LoaderResolverInterface $resolver)
    {
        $this->resolver = $resolver;
    }
    public function load(mixed $resource, ?string $type = null): mixed
    {
        if (\false === $loader = $this->resolver->resolve($resource, $type)) {
            throw new LoaderLoadException($resource, null, 0, null, $type);
        }
        return $loader->load($resource, $type);
    }
    public function supports(mixed $resource, ?string $type = null): bool
    {
        return \false !== $this->resolver->resolve($resource, $type);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Config\Loader;

/**
 * GlobFileLoader loads files from a glob pattern.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class GlobFileLoader extends FileLoader
{
    public function load(mixed $resource, ?string $type = null): mixed
    {
        return $this->import($resource);
    }
    public function supports(mixed $resource, ?string $type = null): bool
    {
        return 'glob' === $type;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Config\Definition;

use _ContaoManager\Symfony\Component\Config\Definition\Exception\InvalidTypeException;
/**
 * This node represents a float value in the config tree.
 *
 * @author Jeanmonod David <david.jeanmonod@gmail.com>
 */
class FloatNode extends NumericNode
{
    /**
     * @return void
     */
    protected function validateType(mixed $value)
    {
        // Integers are also accepted, we just cast them
        if (\is_int($value)) {
            $value = (float) $value;
        }
        if (!\is_float($value)) {
            $ex = new InvalidTypeException(\sprintf('Invalid type for path "%s". Expected "float", but got "%s".', $this->getPath(), get_debug_type($value)));
            if ($hint = $this->getInfo()) {
                $ex->addHint($hint);
            }
            $ex->setPath($this->getPath());
            throw $ex;
        }
    }
    protected function getValidPlaceholderTypes(): array
    {
        return ['float'];
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Config\Definition;

use _ContaoManager\Symfony\Component\Config\Definition\Exception\Exception;
use _ContaoManager\Symfony\Component\Config\Definition\Exception\ForbiddenOverwriteException;
use _ContaoManager\Symfony\Component\Config\Definition\Exception\InvalidConfigurationException;
use _ContaoManager\Symfony\Component\Config\Definition\Exception\InvalidTypeException;
use _ContaoManager\Symfony\Component\Config\Definition\Exception\UnsetKeyException;
/**
 * The base node class.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
abstract class BaseNode implements NodeInterface
{
    public const DEFAULT_PATH_SEPARATOR = '.';
    private static array $placeholderUniquePrefixes = [];
    private static array $placeholders = [];
    protected $name;
    protected $parent;
    protected $normalizationClosures = [];
    protected $normalizedTypes = [];
    protected $finalValidationClosures = [];
    protected $allowOverwrite = \true;
    protected $required = \false;
    protected $deprecation = [];
    protected $equivalentValues = [];
    protected $attributes = [];
    protected $pathSeparator;
    private mixed $handlingPlaceholder = null;
    /**
     * @throws \InvalidArgumentException if the name contains a period
     */
    public function __construct(?string $name, ?NodeInterface $parent = null, string $pathSeparator = self::DEFAULT_PATH_SEPARATOR)
    {
        if (str_contains($name = (string) $name, $pathSeparator)) {
            throw new \InvalidArgumentException('The name must not contain ".' . $pathSeparator . '".');
        }
        $this->name = $name;
        $this->parent = $parent;
        $this->pathSeparator = $pathSeparator;
    }
    /**
     * Register possible (dummy) values for a dynamic placeholder value.
     *
     * Matching configuration values will be processed with a provided value, one by one. After a provided value is
     * successfully processed the configuration value is returned as is, thus preserving the placeholder.
     *
     * @internal
     */
    public static function setPlaceholder(string $placeholder, array $values): void
    {
        if (!$values) {
            throw new \InvalidArgumentException('At least one value must be provided.');
        }
        self::$placeholders[$placeholder] = $values;
    }
    /**
     * Adds a common prefix for dynamic placeholder values.
     *
     * Matching configuration values will be skipped from being processed and are returned as is, thus preserving the
     * placeholder. An exact match provided by {@see setPlaceholder()} might take precedence.
     *
     * @internal
     */
    public static function setPlaceholderUniquePrefix(string $prefix): void
    {
        self::$placeholderUniquePrefixes[] = $prefix;
    }
    /**
     * Resets all current placeholders available.
     *
     * @internal
     */
    public static function resetPlaceholders(): void
    {
        self::$placeholderUniquePrefixes = [];
        self::$placeholders = [];
    }
    /**
     * @return void
     */
    public function setAttribute(string $key, mixed $value)
    {
        $this->attributes[$key] = $value;
    }
    public function getAttribute(string $key, mixed $default = null): mixed
    {
        return $this->attributes[$key] ?? $default;
    }
    public function hasAttribute(string $key): bool
    {
        return isset($this->attributes[$key]);
    }
    public function getAttributes(): array
    {
        return $this->attributes;
    }
    /**
     * @return void
     */
    public function setAttributes(array $attributes)
    {
        $this->attributes = $attributes;
    }
    /**
     * @return void
     */
    public function removeAttribute(string $key)
    {
        unset($this->attributes[$key]);
    }
    /**
     * Sets an info message.
     *
     * @return void
     */
    public function setInfo(string $info)
    {
        $this->setAttribute('info', $info);
    }
    /**
     * Returns info message.
     */
    public function getInfo(): ?string
    {
        return $this->getAttribute('info');
    }
    /**
     * Sets the example configuration for this node.
     *
     * @return void
     */
    public function setExample(string|array $example)
    {
        $this->setAttribute('example', $example);
    }
    /**
     * Retrieves the example configuration for this node.
     */
    public function getExample(): string|array|null
    {
        return $this->getAttribute('example');
    }
    /**
     * Adds an equivalent value.
     *
     * @return void
     */
    public function addEquivalentValue(mixed $originalValue, mixed $equivalentValue)
    {
        $this->equivalentValues[] = [$originalValue, $equivalentValue];
    }
    /**
     * Set this node as required.
     *
     * @return void
     */
    public function setRequired(bool $boolean)
    {
        $this->required = $boolean;
    }
    /**
     * Sets this node as deprecated.
     *
     * You can use %node% and %path% placeholders in your message to display,
     * respectively, the node name and its complete path.
     *
     * @param string $package The name of the composer package that is triggering the deprecation
     * @param string $version The version of the package that introduced the deprecation
     * @param string $message the deprecation message to use
     *
     * @return void
     */
    public function setDeprecated(string $package, string $version, string $message = 'The child node "%node%" at path "%path%" is deprecated.')
    {
        $this->deprecation = ['package' => $package, 'version' => $version, 'message' => $message];
    }
    /**
     * Sets if this node can be overridden.
     *
     * @return void
     */
    public function setAllowOverwrite(bool $allow)
    {
        $this->allowOverwrite = $allow;
    }
    /**
     * Sets the closures used for normalization.
     *
     * @param \Closure[] $closures An array of Closures used for normalization
     *
     * @return void
     */
    public function setNormalizationClosures(array $closures)
    {
        $this->normalizationClosures = $closures;
    }
    /**
     * Sets the list of types supported by normalization.
     *
     * see ExprBuilder::TYPE_* constants.
     *
     * @return void
     */
    public function setNormalizedTypes(array $types)
    {
        $this->normalizedTypes = $types;
    }
    /**
     * Gets the list of types supported by normalization.
     *
     * see ExprBuilder::TYPE_* constants.
     */
    public function getNormalizedTypes(): array
    {
        return $this->normalizedTypes;
    }
    /**
     * Sets the closures used for final validation.
     *
     * @param \Closure[] $closures An array of Closures used for final validation
     *
     * @return void
     */
    public function setFinalValidationClosures(array $closures)
    {
        $this->finalValidationClosures = $closures;
    }
    public function isRequired(): bool
    {
        return $this->required;
    }
    /**
     * Checks if this node is deprecated.
     */
    public function isDeprecated(): bool
    {
        return (bool) $this->deprecation;
    }
    /**
     * @param string $node The configuration node name
     * @param string $path The path of the node
     */
    public function getDeprecation(string $node, string $path): array
    {
        return ['package' => $this->deprecation['package'], 'version' => $this->deprecation['version'], 'message' => strtr($this->deprecation['message'], ['%node%' => $node, '%path%' => $path])];
    }
    public function getName(): string
    {
        return $this->name;
    }
    public function getPath(): string
    {
        if (null !== $this->parent) {
            return $this->parent->getPath() . $this->pathSeparator . $this->name;
        }
        return $this->name;
    }
    final public function merge(mixed $leftSide, mixed $rightSide): mixed
    {
        if (!$this->allowOverwrite) {
            throw new ForbiddenOverwriteException(\sprintf('Configuration path "%s" cannot be overwritten. You have to define all options for this path, and any of its sub-paths in one configuration section.', $this->getPath()));
        }
        if ($leftSide !== $leftPlaceholders = self::resolvePlaceholderValue($leftSide)) {
            foreach ($leftPlaceholders as $leftPlaceholder) {
                $this->handlingPlaceholder = $leftSide;
                try {
                    $this->merge($leftPlaceholder, $rightSide);
                } finally {
                    $this->handlingPlaceholder = null;
                }
            }
            return $rightSide;
        }
        if ($rightSide !== $rightPlaceholders = self::resolvePlaceholderValue($rightSide)) {
            foreach ($rightPlaceholders as $rightPlaceholder) {
                $this->handlingPlaceholder = $rightSide;
                try {
                    $this->merge($leftSide, $rightPlaceholder);
                } finally {
                    $this->handlingPlaceholder = null;
                }
            }
            return $rightSide;
        }
        $this->doValidateType($leftSide);
        $this->doValidateType($rightSide);
        return $this->mergeValues($leftSide, $rightSide);
    }
    final public function normalize(mixed $value): mixed
    {
        $value = $this->preNormalize($value);
        // run custom normalization closures
        foreach ($this->normalizationClosures as $closure) {
            $value = $closure($value);
        }
        // resolve placeholder value
        if ($value !== $placeholders = self::resolvePlaceholderValue($value)) {
            foreach ($placeholders as $placeholder) {
                $this->handlingPlaceholder = $value;
                try {
                    $this->normalize($placeholder);
                } finally {
                    $this->handlingPlaceholder = null;
                }
            }
            return $value;
        }
        // replace value with their equivalent
        foreach ($this->equivalentValues as $data) {
            if ($data[0] === $value) {
                $value = $data[1];
            }
        }
        // validate type
        $this->doValidateType($value);
        // normalize value
        return $this->normalizeValue($value);
    }
    /**
     * Normalizes the value before any other normalization is applied.
     */
    protected function preNormalize(mixed $value): mixed
    {
        return $value;
    }
    /**
     * Returns parent node for this node.
     */
    public function getParent(): ?NodeInterface
    {
        return $this->parent;
    }
    final public function finalize(mixed $value): mixed
    {
        if ($value !== $placeholders = self::resolvePlaceholderValue($value)) {
            foreach ($placeholders as $placeholder) {
                $this->handlingPlaceholder = $value;
                try {
                    $this->finalize($placeholder);
                } finally {
                    $this->handlingPlaceholder = null;
                }
            }
            return $value;
        }
        $this->doValidateType($value);
        $value = $this->finalizeValue($value);
        // Perform validation on the final value if a closure has been set.
        // The closure is also allowed to return another value.
        foreach ($this->finalValidationClosures as $closure) {
            try {
                $value = $closure($value);
            } catch (Exception $e) {
                if ($e instanceof UnsetKeyException && null !== $this->handlingPlaceholder) {
                    continue;
                }
                throw $e;
            } catch (\Exception $e) {
                throw new InvalidConfigurationException(\sprintf('Invalid configuration for path "%s": ', $this->getPath()) . $e->getMessage(), $e->getCode(), $e);
            }
        }
        return $value;
    }
    /**
     * Validates the type of a Node.
     *
     * @return void
     *
     * @throws InvalidTypeException when the value is invalid
     */
    abstract protected function validateType(mixed $value);
    /**
     * Normalizes the value.
     */
    abstract protected function normalizeValue(mixed $value): mixed;
    /**
     * Merges two values together.
     */
    abstract protected function mergeValues(mixed $leftSide, mixed $rightSide): mixed;
    /**
     * Finalizes a value.
     */
    abstract protected function finalizeValue(mixed $value): mixed;
    /**
     * Tests if placeholder values are allowed for this node.
     */
    protected function allowPlaceholders(): bool
    {
        return \true;
    }
    /**
     * Tests if a placeholder is being handled currently.
     */
    protected function isHandlingPlaceholder(): bool
    {
        return null !== $this->handlingPlaceholder;
    }
    /**
     * Gets allowed dynamic types for this node.
     */
    protected function getValidPlaceholderTypes(): array
    {
        return [];
    }
    private static function resolvePlaceholderValue(mixed $value): mixed
    {
        if (\is_string($value)) {
            if (isset(self::$placeholders[$value])) {
                return self::$placeholders[$value];
            }
            foreach (self::$placeholderUniquePrefixes as $placeholderUniquePrefix) {
                if (str_starts_with($value, $placeholderUniquePrefix)) {
                    return [];
                }
            }
        }
        return $value;
    }
    private function doValidateType(mixed $value): void
    {
        if (null !== $this->handlingPlaceholder && !$this->allowPlaceholders()) {
            $e = new InvalidTypeException(\sprintf('A dynamic value is not compatible with a "%s" node type at path "%s".', static::class, $this->getPath()));
            $e->setPath($this->getPath());
            throw $e;
        }
        if (null === $this->handlingPlaceholder || null === $value) {
            $this->validateType($value);
            return;
        }
        $knownTypes = array_keys(self::$placeholders[$this->handlingPlaceholder]);
        $validTypes = $this->getValidPlaceholderTypes();
        if ($validTypes && array_diff($knownTypes, $validTypes)) {
            $e = new InvalidTypeException(\sprintf('Invalid type for path "%s". Expected %s, but got %s.', $this->getPath(), 1 === \count($validTypes) ? '"' . reset($validTypes) . '"' : 'one of "' . implode('", "', $validTypes) . '"', 1 === \count($knownTypes) ? '"' . reset($knownTypes) . '"' : 'one of "' . implode('", "', $knownTypes) . '"'));
            if ($hint = $this->getInfo()) {
                $e->addHint($hint);
            }
            $e->setPath($this->getPath());
            throw $e;
        }
        $this->validateType($value);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Config\Definition;

use _ContaoManager\Symfony\Component\Config\Definition\Exception\InvalidConfigurationException;
/**
 * This node represents a numeric value in the config tree.
 *
 * @author David Jeanmonod <david.jeanmonod@gmail.com>
 */
class NumericNode extends ScalarNode
{
    protected $min;
    protected $max;
    public function __construct(?string $name, ?NodeInterface $parent = null, int|float|null $min = null, int|float|null $max = null, string $pathSeparator = BaseNode::DEFAULT_PATH_SEPARATOR)
    {
        parent::__construct($name, $parent, $pathSeparator);
        $this->min = $min;
        $this->max = $max;
    }
    protected function finalizeValue(mixed $value): mixed
    {
        $value = parent::finalizeValue($value);
        $errorMsg = null;
        if (isset($this->min) && $value < $this->min) {
            $errorMsg = \sprintf('The value %s is too small for path "%s". Should be greater than or equal to %s', $value, $this->getPath(), $this->min);
        }
        if (isset($this->max) && $value > $this->max) {
            $errorMsg = \sprintf('The value %s is too big for path "%s". Should be less than or equal to %s', $value, $this->getPath(), $this->max);
        }
        if (isset($errorMsg)) {
            $ex = new InvalidConfigurationException($errorMsg);
            $ex->setPath($this->getPath());
            throw $ex;
        }
        return $value;
    }
    protected function isValueEmpty(mixed $value): bool
    {
        // a numeric value cannot be empty
        return \false;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Config\Definition;

use _ContaoManager\Symfony\Component\Config\Definition\Configurator\DefinitionConfigurator;
/**
 * @author Yonel Ceruto <yonelceruto@gmail.com>
 */
interface ConfigurableInterface
{
    /**
     * Generates the configuration tree builder.
     */
    public function configure(DefinitionConfigurator $definition): void;
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Config\Definition;

use _ContaoManager\Symfony\Component\Config\Definition\Exception\InvalidTypeException;
/**
 * This node represents an integer value in the config tree.
 *
 * @author Jeanmonod David <david.jeanmonod@gmail.com>
 */
class IntegerNode extends NumericNode
{
    /**
     * @return void
     */
    protected function validateType(mixed $value)
    {
        if (!\is_int($value)) {
            $ex = new InvalidTypeException(\sprintf('Invalid type for path "%s". Expected "int", but got "%s".', $this->getPath(), get_debug_type($value)));
            if ($hint = $this->getInfo()) {
                $ex->addHint($hint);
            }
            $ex->setPath($this->getPath());
            throw $ex;
        }
    }
    protected function getValidPlaceholderTypes(): array
    {
        return ['int'];
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Config\Definition;

/**
 * This interface must be implemented by nodes which can be used as prototypes.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
interface PrototypeNodeInterface extends NodeInterface
{
    /**
     * Sets the name of the node.
     *
     * @return void
     */
    public function setName(string $name);
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Config\Definition;

use _ContaoManager\Symfony\Component\Config\Definition\Builder\TreeBuilder;
use _ContaoManager\Symfony\Component\Config\Definition\Configurator\DefinitionConfigurator;
use _ContaoManager\Symfony\Component\Config\Definition\Loader\DefinitionFileLoader;
use _ContaoManager\Symfony\Component\Config\FileLocator;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerBuilder;
/**
 * @author Yonel Ceruto <yonelceruto@gmail.com>
 *
 * @final
 */
class Configuration implements ConfigurationInterface
{
    public function __construct(private ConfigurableInterface $subject, private ?ContainerBuilder $container, private string $alias)
    {
    }
    public function getConfigTreeBuilder(): TreeBuilder
    {
        $treeBuilder = new TreeBuilder($this->alias);
        $file = (new \ReflectionObject($this->subject))->getFileName();
        $loader = new DefinitionFileLoader($treeBuilder, new FileLocator(\dirname($file)), $this->container);
        $configurator = new DefinitionConfigurator($treeBuilder, $loader, $file, $file);
        $this->subject->configure($configurator);
        return $treeBuilder;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Config\Definition;

use _ContaoManager\Symfony\Component\Config\Definition\Exception\DuplicateKeyException;
use _ContaoManager\Symfony\Component\Config\Definition\Exception\Exception;
use _ContaoManager\Symfony\Component\Config\Definition\Exception\InvalidConfigurationException;
use _ContaoManager\Symfony\Component\Config\Definition\Exception\UnsetKeyException;
/**
 * Represents a prototyped Array node in the config tree.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
class PrototypedArrayNode extends ArrayNode
{
    protected $prototype;
    protected $keyAttribute;
    protected $removeKeyAttribute = \false;
    protected $minNumberOfElements = 0;
    protected $defaultValue = [];
    protected $defaultChildren;
    /**
     * @var NodeInterface[] An array of the prototypes of the simplified value children
     */
    private array $valuePrototypes = [];
    /**
     * Sets the minimum number of elements that a prototype based node must
     * contain. By default this is zero, meaning no elements.
     *
     * @return void
     */
    public function setMinNumberOfElements(int $number)
    {
        $this->minNumberOfElements = $number;
    }
    /**
     * Sets the attribute which value is to be used as key.
     *
     * This is useful when you have an indexed array that should be an
     * associative array. You can select an item from within the array
     * to be the key of the particular item. For example, if "id" is the
     * "key", then:
     *
     *     [
     *         ['id' => 'my_name', 'foo' => 'bar'],
     *     ];
     *
     *  becomes
     *
     *      [
     *          'my_name' => ['foo' => 'bar'],
     *      ];
     *
     * If you'd like "'id' => 'my_name'" to still be present in the resulting
     * array, then you can set the second argument of this method to false.
     *
     * @param string $attribute The name of the attribute which value is to be used as a key
     * @param bool   $remove    Whether or not to remove the key
     *
     * @return void
     */
    public function setKeyAttribute(string $attribute, bool $remove = \true)
    {
        $this->keyAttribute = $attribute;
        $this->removeKeyAttribute = $remove;
    }
    /**
     * Retrieves the name of the attribute which value should be used as key.
     */
    public function getKeyAttribute(): ?string
    {
        return $this->keyAttribute;
    }
    /**
     * Sets the default value of this node.
     *
     * @return void
     */
    public function setDefaultValue(array $value)
    {
        $this->defaultValue = $value;
    }
    public function hasDefaultValue(): bool
    {
        return \true;
    }
    /**
     * Adds default children when none are set.
     *
     * @param int|string|array|null $children The number of children|The child name|The children names to be added
     *
     * @return void
     */
    public function setAddChildrenIfNoneSet(int|string|array|null $children = ['defaults'])
    {
        if (null === $children) {
            $this->defaultChildren = ['defaults'];
        } else {
            $this->defaultChildren = \is_int($children) && $children > 0 ? range(1, $children) : (array) $children;
        }
    }
    /**
     * The default value could be either explicited or derived from the prototype
     * default value.
     */
    public function getDefaultValue(): mixed
    {
        if (null !== $this->defaultChildren) {
            $default = $this->prototype->hasDefaultValue() ? $this->prototype->getDefaultValue() : [];
            $defaults = [];
            foreach (array_values($this->defaultChildren) as $i => $name) {
                $defaults[null === $this->keyAttribute ? $i : $name] = $default;
            }
            return $defaults;
        }
        return $this->defaultValue;
    }
    /**
     * Sets the node prototype.
     *
     * @return void
     */
    public function setPrototype(PrototypeNodeInterface $node)
    {
        $this->prototype = $node;
    }
    /**
     * Retrieves the prototype.
     */
    public function getPrototype(): PrototypeNodeInterface
    {
        return $this->prototype;
    }
    /**
     * Disable adding concrete children for prototyped nodes.
     *
     * @return never
     *
     * @throws Exception
     */
    public function addChild(NodeInterface $node)
    {
        throw new Exception('A prototyped array node cannot have concrete children.');
    }
    protected function finalizeValue(mixed $value): mixed
    {
        if (\false === $value) {
            throw new UnsetKeyException(\sprintf('Unsetting key for path "%s", value: %s.', $this->getPath(), json_encode($value)));
        }
        foreach ($value as $k => $v) {
            $prototype = $this->getPrototypeForChild($k);
            try {
                $value[$k] = $prototype->finalize($v);
            } catch (UnsetKeyException) {
                unset($value[$k]);
            }
        }
        if (\count($value) < $this->minNumberOfElements) {
            $ex = new InvalidConfigurationException(\sprintf('The path "%s" should have at least %d element(s) defined.', $this->getPath(), $this->minNumberOfElements));
            $ex->setPath($this->getPath());
            throw $ex;
        }
        return $value;
    }
    /**
     * @throws DuplicateKeyException
     */
    protected function normalizeValue(mixed $value): mixed
    {
        if (\false === $value) {
            return $value;
        }
        $value = $this->remapXml($value);
        $isList = array_is_list($value);
        $normalized = [];
        foreach ($value as $k => $v) {
            if (null !== $this->keyAttribute && \is_array($v)) {
                if (!isset($v[$this->keyAttribute]) && \is_int($k) && $isList) {
                    $ex = new InvalidConfigurationException(\sprintf('The attribute "%s" must be set for path "%s".', $this->keyAttribute, $this->getPath()));
                    $ex->setPath($this->getPath());
                    throw $ex;
                } elseif (isset($v[$this->keyAttribute])) {
                    $k = $v[$this->keyAttribute];
                    if (\is_float($k)) {
                        $k = var_export($k, \true);
                    }
                    // remove the key attribute when required
                    if ($this->removeKeyAttribute) {
                        unset($v[$this->keyAttribute]);
                    }
                    // if only "value" is left
                    if (array_keys($v) === ['value']) {
                        $v = $v['value'];
                        if ($this->prototype instanceof ArrayNode && ($children = $this->prototype->getChildren()) && \array_key_exists('value', $children)) {
                            $valuePrototype = current($this->valuePrototypes) ?: clone $children['value'];
                            $valuePrototype->parent = $this;
                            $originalClosures = $this->prototype->normalizationClosures;
                            if (\is_array($originalClosures)) {
                                $valuePrototypeClosures = $valuePrototype->normalizationClosures;
                                $valuePrototype->normalizationClosures = \is_array($valuePrototypeClosures) ? array_merge($originalClosures, $valuePrototypeClosures) : $originalClosures;
                            }
                            $this->valuePrototypes[$k] = $valuePrototype;
                        }
                    }
                }
                if (\array_key_exists($k, $normalized)) {
                    $ex = new DuplicateKeyException(\sprintf('Duplicate key "%s" for path "%s".', $k, $this->getPath()));
                    $ex->setPath($this->getPath());
                    throw $ex;
                }
            }
            $prototype = $this->getPrototypeForChild($k);
            if (null !== $this->keyAttribute || !$isList) {
                $normalized[$k] = $prototype->normalize($v);
            } else {
                $normalized[] = $prototype->normalize($v);
            }
        }
        return $normalized;
    }
    protected function mergeValues(mixed $leftSide, mixed $rightSide): mixed
    {
        if (\false === $rightSide) {
            // if this is still false after the last config has been merged the
            // finalization pass will take care of removing this key entirely
            return \false;
        }
        if (\false === $leftSide || !$this->performDeepMerging) {
            return $rightSide;
        }
        $isList = array_is_list($rightSide);
        foreach ($rightSide as $k => $v) {
            // prototype, and key is irrelevant there are no named keys, append the element
            if (null === $this->keyAttribute && $isList) {
                $leftSide[] = $v;
                continue;
            }
            // no conflict
            if (!\array_key_exists($k, $leftSide)) {
                if (!$this->allowNewKeys) {
                    $ex = new InvalidConfigurationException(\sprintf('You are not allowed to define new elements for path "%s". Please define all elements for this path in one config file.', $this->getPath()));
                    $ex->setPath($this->getPath());
                    throw $ex;
                }
                $leftSide[$k] = $v;
                continue;
            }
            $prototype = $this->getPrototypeForChild($k);
            $leftSide[$k] = $prototype->merge($leftSide[$k], $v);
        }
        return $leftSide;
    }
    /**
     * Returns a prototype for the child node that is associated to $key in the value array.
     * For general child nodes, this will be $this->prototype.
     * But if $this->removeKeyAttribute is true and there are only two keys in the child node:
     * one is same as this->keyAttribute and the other is 'value', then the prototype will be different.
     *
     * For example, assume $this->keyAttribute is 'name' and the value array is as follows:
     *
     *     [
     *         [
     *             'name' => 'name001',
     *             'value' => 'value001'
     *         ]
     *     ]
     *
     * Now, the key is 0 and the child node is:
     *
     *     [
     *        'name' => 'name001',
     *        'value' => 'value001'
     *     ]
     *
     * When normalizing the value array, the 'name' element will removed from the child node
     * and its value becomes the new key of the child node:
     *
     *     [
     *         'name001' => ['value' => 'value001']
     *     ]
     *
     * Now only 'value' element is left in the child node which can be further simplified into a string:
     *
     *     ['name001' => 'value001']
     *
     * Now, the key becomes 'name001' and the child node becomes 'value001' and
     * the prototype of child node 'name001' should be a ScalarNode instead of an ArrayNode instance.
     */
    private function getPrototypeForChild(string $key): mixed
    {
        $prototype = $this->valuePrototypes[$key] ?? $this->prototype;
        $prototype->setName($key);
        return $prototype;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Config\Definition;

/**
 * This class is the entry point for config normalization/merging/finalization.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 *
 * @final
 */
class Processor
{
    /**
     * Processes an array of configurations.
     *
     * @param array $configs An array of configuration items to process
     */
    public function process(NodeInterface $configTree, array $configs): array
    {
        $currentConfig = [];
        foreach ($configs as $config) {
            $config = $configTree->normalize($config);
            $currentConfig = $configTree->merge($currentConfig, $config);
        }
        return $configTree->finalize($currentConfig);
    }
    /**
     * Processes an array of configurations.
     *
     * @param array $configs An array of configuration items to process
     */
    public function processConfiguration(ConfigurationInterface $configuration, array $configs): array
    {
        return $this->process($configuration->getConfigTreeBuilder()->buildTree(), $configs);
    }
    /**
     * Normalizes a configuration entry.
     *
     * This method returns a normalize configuration array for a given key
     * to remove the differences due to the original format (YAML and XML mainly).
     *
     * Here is an example.
     *
     * The configuration in XML:
     *
     * <twig:extension>twig.extension.foo</twig:extension>
     * <twig:extension>twig.extension.bar</twig:extension>
     *
     * And the same configuration in YAML:
     *
     * extensions: ['twig.extension.foo', 'twig.extension.bar']
     *
     * @param array       $config A config array
     * @param string      $key    The key to normalize
     * @param string|null $plural The plural form of the key if it is irregular
     */
    public static function normalizeConfig(array $config, string $key, ?string $plural = null): array
    {
        $plural ??= $key . 's';
        if (isset($config[$plural])) {
            return $config[$plural];
        }
        if (isset($config[$key])) {
            if (\is_string($config[$key]) || !\is_int(key($config[$key]))) {
                // only one
                return [$config[$key]];
            }
            return $config[$key];
        }
        return [];
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Config\Definition\Loader;

use _ContaoManager\Symfony\Component\Config\Definition\Builder\TreeBuilder;
use _ContaoManager\Symfony\Component\Config\Definition\Configurator\DefinitionConfigurator;
use _ContaoManager\Symfony\Component\Config\FileLocatorInterface;
use _ContaoManager\Symfony\Component\Config\Loader\FileLoader;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerBuilder;
/**
 * DefinitionFileLoader loads config definitions from a PHP file.
 *
 * The PHP file is required.
 *
 * @author Yonel Ceruto <yonelceruto@gmail.com>
 */
class DefinitionFileLoader extends FileLoader
{
    public function __construct(private TreeBuilder $treeBuilder, FileLocatorInterface $locator, private ?ContainerBuilder $container = null)
    {
        parent::__construct($locator);
    }
    public function load(mixed $resource, ?string $type = null): mixed
    {
        // the loader variable is exposed to the included file below
        $loader = $this;
        $path = $this->locator->locate($resource);
        $this->setCurrentDir(\dirname($path));
        $this->container?->fileExists($path);
        // the closure forbids access to the private scope in the included file
        $load = \Closure::bind(static function ($file) use ($loader) {
            return include $file;
        }, null, ProtectedDefinitionFileLoader::class);
        $callback = $load($path);
        if (\is_object($callback) && \is_callable($callback)) {
            $this->executeCallback($callback, new DefinitionConfigurator($this->treeBuilder, $this, $path, $resource), $path);
        }
        return null;
    }
    public function supports(mixed $resource, ?string $type = null): bool
    {
        if (!\is_string($resource)) {
            return \false;
        }
        if (null === $type && 'php' === pathinfo($resource, \PATHINFO_EXTENSION)) {
            return \true;
        }
        return 'php' === $type;
    }
    private function executeCallback(callable $callback, DefinitionConfigurator $configurator, string $path): void
    {
        $callback = $callback(...);
        $arguments = [];
        $r = new \ReflectionFunction($callback);
        foreach ($r->getParameters() as $parameter) {
            $reflectionType = $parameter->getType();
            if (!$reflectionType instanceof \ReflectionNamedType) {
                throw new \InvalidArgumentException(\sprintf('Could not resolve argument "$%s" for "%s". You must typehint it (for example with "%s").', $parameter->getName(), $path, DefinitionConfigurator::class));
            }
            $arguments[] = match ($reflectionType->getName()) {
                DefinitionConfigurator::class => $configurator,
                TreeBuilder::class => $this->treeBuilder,
                FileLoader::class, self::class => $this,
            };
        }
        $callback(...$arguments);
    }
}
/**
 * @internal
 */
final class ProtectedDefinitionFileLoader extends DefinitionFileLoader
{
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Config\Definition;

use _ContaoManager\Symfony\Component\Config\Definition\Exception\ForbiddenOverwriteException;
use _ContaoManager\Symfony\Component\Config\Definition\Exception\InvalidConfigurationException;
use _ContaoManager\Symfony\Component\Config\Definition\Exception\InvalidTypeException;
/**
 * Common Interface among all nodes.
 *
 * In most cases, it is better to inherit from BaseNode instead of implementing
 * this interface yourself.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
interface NodeInterface
{
    /**
     * Returns the name of the node.
     */
    public function getName(): string;
    /**
     * Returns the path of the node.
     */
    public function getPath(): string;
    /**
     * Returns true when the node is required.
     */
    public function isRequired(): bool;
    /**
     * Returns true when the node has a default value.
     */
    public function hasDefaultValue(): bool;
    /**
     * Returns the default value of the node.
     *
     * @throws \RuntimeException if the node has no default value
     */
    public function getDefaultValue(): mixed;
    /**
     * Normalizes a value.
     *
     * @throws InvalidTypeException if the value type is invalid
     */
    public function normalize(mixed $value): mixed;
    /**
     * Merges two values together.
     *
     * @throws ForbiddenOverwriteException if the configuration path cannot be overwritten
     * @throws InvalidTypeException        if the value type is invalid
     */
    public function merge(mixed $leftSide, mixed $rightSide): mixed;
    /**
     * Finalizes a value.
     *
     * @throws InvalidTypeException          if the value type is invalid
     * @throws InvalidConfigurationException if the value is invalid configuration
     */
    public function finalize(mixed $value): mixed;
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Config\Definition;

use _ContaoManager\Symfony\Component\Config\Definition\Exception\InvalidConfigurationException;
/**
 * Node which only allows a finite set of values.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
class EnumNode extends ScalarNode
{
    private array $values;
    public function __construct(?string $name, ?NodeInterface $parent = null, array $values = [], string $pathSeparator = BaseNode::DEFAULT_PATH_SEPARATOR)
    {
        if (!$values) {
            throw new \InvalidArgumentException('$values must contain at least one element.');
        }
        foreach ($values as $value) {
            if (null === $value || \is_scalar($value)) {
                continue;
            }
            if (!$value instanceof \UnitEnum) {
                throw new \InvalidArgumentException(\sprintf('"%s" only supports scalar, enum, or null values, "%s" given.', __CLASS__, get_debug_type($value)));
            }
            if ($value::class !== $enumClass ??= $value::class) {
                throw new \InvalidArgumentException(\sprintf('"%s" only supports one type of enum, "%s" and "%s" passed.', __CLASS__, $enumClass, $value::class));
            }
        }
        parent::__construct($name, $parent, $pathSeparator);
        $this->values = $values;
    }
    /**
     * @return array
     */
    public function getValues()
    {
        return $this->values;
    }
    /**
     * @internal
     */
    public function getPermissibleValues(string $separator): string
    {
        return implode($separator, array_unique(array_map(static function (mixed $value): string {
            if (!$value instanceof \UnitEnum) {
                return json_encode($value);
            }
            return ltrim(var_export($value, \true), '\\');
        }, $this->values)));
    }
    /**
     * @return void
     */
    protected function validateType(mixed $value)
    {
        if ($value instanceof \UnitEnum) {
            return;
        }
        parent::validateType($value);
    }
    protected function finalizeValue(mixed $value): mixed
    {
        $value = parent::finalizeValue($value);
        if (!\in_array($value, $this->values, \true)) {
            $ex = new InvalidConfigurationException(\sprintf('The value %s is not allowed for path "%s". Permissible values: %s', json_encode($value), $this->getPath(), $this->getPermissibleValues(', ')));
            $ex->setPath($this->getPath());
            throw $ex;
        }
        return $value;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Config\Definition;

use _ContaoManager\Symfony\Component\Config\Definition\Exception\InvalidTypeException;
/**
 * This node represents a Boolean value in the config tree.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
class BooleanNode extends ScalarNode
{
    /**
     * @return void
     */
    protected function validateType(mixed $value)
    {
        if (!\is_bool($value)) {
            $ex = new InvalidTypeException(\sprintf('Invalid type for path "%s". Expected "bool", but got "%s".', $this->getPath(), get_debug_type($value)));
            if ($hint = $this->getInfo()) {
                $ex->addHint($hint);
            }
            $ex->setPath($this->getPath());
            throw $ex;
        }
    }
    protected function isValueEmpty(mixed $value): bool
    {
        // a boolean value cannot be empty
        return \false;
    }
    protected function getValidPlaceholderTypes(): array
    {
        return ['bool'];
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Config\Definition\Configurator;

use _ContaoManager\Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition;
use _ContaoManager\Symfony\Component\Config\Definition\Builder\NodeDefinition;
use _ContaoManager\Symfony\Component\Config\Definition\Builder\TreeBuilder;
use _ContaoManager\Symfony\Component\Config\Definition\Loader\DefinitionFileLoader;
/**
 * @author Yonel Ceruto <yonelceruto@gmail.com>
 */
class DefinitionConfigurator
{
    public function __construct(private TreeBuilder $treeBuilder, private DefinitionFileLoader $loader, private string $path, private string $file)
    {
    }
    public function import(string $resource, ?string $type = null, bool $ignoreErrors = \false): void
    {
        $this->loader->setCurrentDir(\dirname($this->path));
        $this->loader->import($resource, $type, $ignoreErrors, $this->file);
    }
    public function rootNode(): NodeDefinition|ArrayNodeDefinition
    {
        return $this->treeBuilder->getRootNode();
    }
    public function setPathSeparator(string $separator): void
    {
        $this->treeBuilder->setPathSeparator($separator);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Config\Definition;

use _ContaoManager\Symfony\Component\Config\Definition\Exception\InvalidConfigurationException;
use _ContaoManager\Symfony\Component\Config\Definition\Exception\InvalidTypeException;
use _ContaoManager\Symfony\Component\Config\Definition\Exception\UnsetKeyException;
/**
 * Represents an Array node in the config tree.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
class ArrayNode extends BaseNode implements PrototypeNodeInterface
{
    protected $xmlRemappings = [];
    protected $children = [];
    protected $allowFalse = \false;
    protected $allowNewKeys = \true;
    protected $addIfNotSet = \false;
    protected $performDeepMerging = \true;
    protected $ignoreExtraKeys = \false;
    protected $removeExtraKeys = \true;
    protected $normalizeKeys = \true;
    /**
     * @return void
     */
    public function setNormalizeKeys(bool $normalizeKeys)
    {
        $this->normalizeKeys = $normalizeKeys;
    }
    /**
     * Namely, you mostly have foo_bar in YAML while you have foo-bar in XML.
     * After running this method, all keys are normalized to foo_bar.
     *
     * If you have a mixed key like foo-bar_moo, it will not be altered.
     * The key will also not be altered if the target key already exists.
     */
    protected function preNormalize(mixed $value): mixed
    {
        if (!$this->normalizeKeys || !\is_array($value)) {
            return $value;
        }
        $normalized = [];
        foreach ($value as $k => $v) {
            if (str_contains($k, '-') && !str_contains($k, '_') && !\array_key_exists($normalizedKey = str_replace('-', '_', $k), $value)) {
                $normalized[$normalizedKey] = $v;
            } else {
                $normalized[$k] = $v;
            }
        }
        return $normalized;
    }
    /**
     * Retrieves the children of this node.
     *
     * @return array<string, NodeInterface>
     */
    public function getChildren(): array
    {
        return $this->children;
    }
    /**
     * Sets the xml remappings that should be performed.
     *
     * @param array $remappings An array of the form [[string, string]]
     *
     * @return void
     */
    public function setXmlRemappings(array $remappings)
    {
        $this->xmlRemappings = $remappings;
    }
    /**
     * Gets the xml remappings that should be performed.
     *
     * @return array an array of the form [[string, string]]
     */
    public function getXmlRemappings(): array
    {
        return $this->xmlRemappings;
    }
    /**
     * Sets whether to add default values for this array if it has not been
     * defined in any of the configuration files.
     *
     * @return void
     */
    public function setAddIfNotSet(bool $boolean)
    {
        $this->addIfNotSet = $boolean;
    }
    /**
     * Sets whether false is allowed as value indicating that the array should be unset.
     *
     * @return void
     */
    public function setAllowFalse(bool $allow)
    {
        $this->allowFalse = $allow;
    }
    /**
     * Sets whether new keys can be defined in subsequent configurations.
     *
     * @return void
     */
    public function setAllowNewKeys(bool $allow)
    {
        $this->allowNewKeys = $allow;
    }
    /**
     * Sets if deep merging should occur.
     *
     * @return void
     */
    public function setPerformDeepMerging(bool $boolean)
    {
        $this->performDeepMerging = $boolean;
    }
    /**
     * Whether extra keys should just be ignored without an exception.
     *
     * @param bool $boolean To allow extra keys
     * @param bool $remove  To remove extra keys
     *
     * @return void
     */
    public function setIgnoreExtraKeys(bool $boolean, bool $remove = \true)
    {
        $this->ignoreExtraKeys = $boolean;
        $this->removeExtraKeys = $this->ignoreExtraKeys && $remove;
    }
    /**
     * Returns true when extra keys should be ignored without an exception.
     */
    public function shouldIgnoreExtraKeys(): bool
    {
        return $this->ignoreExtraKeys;
    }
    /**
     * @return void
     */
    public function setName(string $name)
    {
        $this->name = $name;
    }
    public function hasDefaultValue(): bool
    {
        return $this->addIfNotSet;
    }
    public function getDefaultValue(): mixed
    {
        if (!$this->hasDefaultValue()) {
            throw new \RuntimeException(\sprintf('The node at path "%s" has no default value.', $this->getPath()));
        }
        $defaults = [];
        foreach ($this->children as $name => $child) {
            if ($child->hasDefaultValue()) {
                $defaults[$name] = $child->getDefaultValue();
            }
        }
        return $defaults;
    }
    /**
     * Adds a child node.
     *
     * @return void
     *
     * @throws \InvalidArgumentException when the child node has no name
     * @throws \InvalidArgumentException when the child node's name is not unique
     */
    public function addChild(NodeInterface $node)
    {
        $name = $node->getName();
        if ('' === $name) {
            throw new \InvalidArgumentException('Child nodes must be named.');
        }
        if (isset($this->children[$name])) {
            throw new \InvalidArgumentException(\sprintf('A child node named "%s" already exists.', $name));
        }
        $this->children[$name] = $node;
    }
    /**
     * @throws UnsetKeyException
     * @throws InvalidConfigurationException if the node doesn't have enough children
     */
    protected function finalizeValue(mixed $value): mixed
    {
        if (\false === $value) {
            throw new UnsetKeyException(\sprintf('Unsetting key for path "%s", value: %s.', $this->getPath(), json_encode($value)));
        }
        foreach ($this->children as $name => $child) {
            if (!\array_key_exists($name, $value)) {
                if ($child->isRequired()) {
                    $message = \sprintf('The child config "%s" under "%s" must be configured', $name, $this->getPath());
                    if ($child->getInfo()) {
                        $message .= \sprintf(': %s', $child->getInfo());
                    } else {
                        $message .= '.';
                    }
                    $ex = new InvalidConfigurationException($message);
                    $ex->setPath($this->getPath());
                    throw $ex;
                }
                if ($child->hasDefaultValue()) {
                    $value[$name] = $child->getDefaultValue();
                }
                continue;
            }
            if ($child->isDeprecated()) {
                $deprecation = $child->getDeprecation($name, $this->getPath());
                trigger_deprecation($deprecation['package'], $deprecation['version'], $deprecation['message']);
            }
            try {
                $value[$name] = $child->finalize($value[$name]);
            } catch (UnsetKeyException) {
                unset($value[$name]);
            }
        }
        return $value;
    }
    /**
     * @return void
     */
    protected function validateType(mixed $value)
    {
        if (!\is_array($value) && (!$this->allowFalse || \false !== $value)) {
            $ex = new InvalidTypeException(\sprintf('Invalid type for path "%s". Expected "array", but got "%s"', $this->getPath(), get_debug_type($value)));
            if ($hint = $this->getInfo()) {
                $ex->addHint($hint);
            }
            $ex->setPath($this->getPath());
            throw $ex;
        }
    }
    /**
     * @throws InvalidConfigurationException
     */
    protected function normalizeValue(mixed $value): mixed
    {
        if (\false === $value) {
            return $value;
        }
        $value = $this->remapXml($value);
        $normalized = [];
        foreach ($value as $name => $val) {
            if (isset($this->children[$name])) {
                try {
                    $normalized[$name] = $this->children[$name]->normalize($val);
                } catch (UnsetKeyException) {
                }
                unset($value[$name]);
            } elseif (!$this->removeExtraKeys) {
                $normalized[$name] = $val;
            }
        }
        // if extra fields are present, throw exception
        if (\count($value) && !$this->ignoreExtraKeys) {
            $proposals = array_keys($this->children);
            sort($proposals);
            $guesses = [];
            foreach (array_keys($value) as $subject) {
                $minScore = \INF;
                foreach ($proposals as $proposal) {
                    $distance = levenshtein($subject, $proposal);
                    if ($distance <= $minScore && $distance < 3) {
                        $guesses[$proposal] = $distance;
                        $minScore = $distance;
                    }
                }
            }
            $msg = \sprintf('Unrecognized option%s "%s" under "%s"', 1 === \count($value) ? '' : 's', implode(', ', array_keys($value)), $this->getPath());
            if (\count($guesses)) {
                asort($guesses);
                $msg .= \sprintf('. Did you mean "%s"?', implode('", "', array_keys($guesses)));
            } else {
                $msg .= \sprintf('. Available option%s %s "%s".', 1 === \count($proposals) ? '' : 's', 1 === \count($proposals) ? 'is' : 'are', implode('", "', $proposals));
            }
            $ex = new InvalidConfigurationException($msg);
            $ex->setPath($this->getPath());
            throw $ex;
        }
        return $normalized;
    }
    /**
     * Remaps multiple singular values to a single plural value.
     */
    protected function remapXml(array $value): array
    {
        foreach ($this->xmlRemappings as [$singular, $plural]) {
            if (!isset($value[$singular])) {
                continue;
            }
            $value[$plural] = Processor::normalizeConfig($value, $singular, $plural);
            unset($value[$singular]);
        }
        return $value;
    }
    /**
     * @throws InvalidConfigurationException
     * @throws \RuntimeException
     */
    protected function mergeValues(mixed $leftSide, mixed $rightSide): mixed
    {
        if (\false === $rightSide) {
            // if this is still false after the last config has been merged the
            // finalization pass will take care of removing this key entirely
            return \false;
        }
        if (\false === $leftSide || !$this->performDeepMerging) {
            return $rightSide;
        }
        foreach ($rightSide as $k => $v) {
            // no conflict
            if (!\array_key_exists($k, $leftSide)) {
                if (!$this->allowNewKeys) {
                    $ex = new InvalidConfigurationException(\sprintf('You are not allowed to define new elements for path "%s". Please define all elements for this path in one config file. If you are trying to overwrite an element, make sure you redefine it with the same name.', $this->getPath()));
                    $ex->setPath($this->getPath());
                    throw $ex;
                }
                $leftSide[$k] = $v;
                continue;
            }
            if (!isset($this->children[$k])) {
                if (!$this->ignoreExtraKeys || $this->removeExtraKeys) {
                    throw new \RuntimeException('merge() expects a normalized config array.');
                }
                $leftSide[$k] = $v;
                continue;
            }
            $leftSide[$k] = $this->children[$k]->merge($leftSide[$k], $v);
        }
        return $leftSide;
    }
    protected function allowPlaceholders(): bool
    {
        return \false;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Config\Definition;

use _ContaoManager\Symfony\Component\Config\Definition\Exception\InvalidTypeException;
/**
 * This node represents a scalar value in the config tree.
 *
 * The following values are considered scalars:
 *   * booleans
 *   * strings
 *   * null
 *   * integers
 *   * floats
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
class ScalarNode extends VariableNode
{
    /**
     * @return void
     */
    protected function validateType(mixed $value)
    {
        if (!\is_scalar($value) && null !== $value) {
            $ex = new InvalidTypeException(\sprintf('Invalid type for path "%s". Expected "scalar", but got "%s".', $this->getPath(), get_debug_type($value)));
            if ($hint = $this->getInfo()) {
                $ex->addHint($hint);
            }
            $ex->setPath($this->getPath());
            throw $ex;
        }
    }
    protected function isValueEmpty(mixed $value): bool
    {
        // assume environment variables are never empty (which in practice is likely to be true during runtime)
        // not doing so breaks many configs that are valid today
        if ($this->isHandlingPlaceholder()) {
            return \false;
        }
        return null === $value || '' === $value;
    }
    protected function getValidPlaceholderTypes(): array
    {
        return ['bool', 'int', 'float', 'string'];
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Config\Definition;

use _ContaoManager\Symfony\Component\Config\Definition\Builder\TreeBuilder;
/**
 * Configuration interface.
 *
 * @author Victor Berchet <victor@suumit.com>
 */
interface ConfigurationInterface
{
    /**
     * Generates the configuration tree builder.
     *
     * @return TreeBuilder
     */
    public function getConfigTreeBuilder();
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Config\Definition\Builder;

use _ContaoManager\Symfony\Component\Config\Definition\Exception\UnsetKeyException;
/**
 * This class builds an if expression.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 * @author Christophe Coevoet <stof@notk.org>
 */
class ExprBuilder
{
    public const TYPE_ANY = 'any';
    public const TYPE_STRING = 'string';
    public const TYPE_NULL = 'null';
    public const TYPE_ARRAY = 'array';
    protected $node;
    public $allowedTypes;
    public $ifPart;
    public $thenPart;
    public function __construct(NodeDefinition $node)
    {
        $this->node = $node;
    }
    /**
     * Marks the expression as being always used.
     *
     * @return $this
     */
    public function always(?\Closure $then = null): static
    {
        $this->ifPart = static fn() => \true;
        $this->allowedTypes = self::TYPE_ANY;
        if (null !== $then) {
            $this->thenPart = $then;
        }
        return $this;
    }
    /**
     * Sets a closure to use as tests.
     *
     * The default one tests if the value is true.
     *
     * @return $this
     */
    public function ifTrue(?\Closure $closure = null): static
    {
        $this->ifPart = $closure ?? static fn($v) => \true === $v;
        $this->allowedTypes = self::TYPE_ANY;
        return $this;
    }
    /**
     * Tests if the value is a string.
     *
     * @return $this
     */
    public function ifString(): static
    {
        $this->ifPart = \is_string(...);
        $this->allowedTypes = self::TYPE_STRING;
        return $this;
    }
    /**
     * Tests if the value is null.
     *
     * @return $this
     */
    public function ifNull(): static
    {
        $this->ifPart = \is_null(...);
        $this->allowedTypes = self::TYPE_NULL;
        return $this;
    }
    /**
     * Tests if the value is empty.
     *
     * @return $this
     */
    public function ifEmpty(): static
    {
        $this->ifPart = static fn($v) => empty($v);
        $this->allowedTypes = self::TYPE_ANY;
        return $this;
    }
    /**
     * Tests if the value is an array.
     *
     * @return $this
     */
    public function ifArray(): static
    {
        $this->ifPart = \is_array(...);
        $this->allowedTypes = self::TYPE_ARRAY;
        return $this;
    }
    /**
     * Tests if the value is in an array.
     *
     * @return $this
     */
    public function ifInArray(array $array): static
    {
        $this->ifPart = static fn($v) => \in_array($v, $array, \true);
        $this->allowedTypes = self::TYPE_ANY;
        return $this;
    }
    /**
     * Tests if the value is not in an array.
     *
     * @return $this
     */
    public function ifNotInArray(array $array): static
    {
        $this->ifPart = static fn($v) => !\in_array($v, $array, \true);
        $this->allowedTypes = self::TYPE_ANY;
        return $this;
    }
    /**
     * Transforms variables of any type into an array.
     *
     * @return $this
     */
    public function castToArray(): static
    {
        $this->ifPart = static fn($v) => !\is_array($v);
        $this->allowedTypes = self::TYPE_ANY;
        $this->thenPart = static fn($v) => [$v];
        return $this;
    }
    /**
     * Sets the closure to run if the test pass.
     *
     * @return $this
     */
    public function then(\Closure $closure): static
    {
        $this->thenPart = $closure;
        return $this;
    }
    /**
     * Sets a closure returning an empty array.
     *
     * @return $this
     */
    public function thenEmptyArray(): static
    {
        $this->thenPart = static fn() => [];
        return $this;
    }
    /**
     * Sets a closure marking the value as invalid at processing time.
     *
     * if you want to add the value of the node in your message just use a %s placeholder.
     *
     * @return $this
     *
     * @throws \InvalidArgumentException
     */
    public function thenInvalid(string $message): static
    {
        $this->thenPart = static fn($v) => throw new \InvalidArgumentException(\sprintf($message, json_encode($v)));
        return $this;
    }
    /**
     * Sets a closure unsetting this key of the array at processing time.
     *
     * @return $this
     *
     * @throws UnsetKeyException
     */
    public function thenUnset(): static
    {
        $this->thenPart = static fn() => throw new UnsetKeyException('Unsetting key.');
        return $this;
    }
    /**
     * Returns the related node.
     *
     * @throws \RuntimeException
     */
    public function end(): NodeDefinition|ArrayNodeDefinition|VariableNodeDefinition
    {
        if (null === $this->ifPart) {
            throw new \RuntimeException('You must specify an if part.');
        }
        if (null === $this->thenPart) {
            throw new \RuntimeException('You must specify a then part.');
        }
        return $this->node;
    }
    /**
     * Builds the expressions.
     *
     * @param ExprBuilder[] $expressions An array of ExprBuilder instances to build
     */
    public static function buildExpressions(array $expressions): array
    {
        foreach ($expressions as $k => $expr) {
            if ($expr instanceof self) {
                $if = $expr->ifPart;
                $then = $expr->thenPart;
                $expressions[$k] = static fn($v) => $if($v) ? $then($v) : $v;
            }
        }
        return $expressions;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Config\Definition\Builder;

use _ContaoManager\Symfony\Component\Config\Definition\EnumNode;
/**
 * Enum Node Definition.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
class EnumNodeDefinition extends ScalarNodeDefinition
{
    private array $values;
    /**
     * @return $this
     */
    public function values(array $values): static
    {
        if (!$values) {
            throw new \InvalidArgumentException('->values() must be called with at least one value.');
        }
        $this->values = $values;
        return $this;
    }
    /**
     * Instantiate a Node.
     *
     * @throws \RuntimeException
     */
    protected function instantiateNode(): EnumNode
    {
        if (!isset($this->values)) {
            throw new \RuntimeException('You must call ->values() on enum nodes.');
        }
        return new EnumNode($this->name, $this->parent, $this->values, $this->pathSeparator);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Config\Definition\Builder;

/**
 * This class builds merge conditions.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
class MergeBuilder
{
    protected $node;
    public $allowFalse = \false;
    public $allowOverwrite = \true;
    public function __construct(NodeDefinition $node)
    {
        $this->node = $node;
    }
    /**
     * Sets whether the node can be unset.
     *
     * @return $this
     */
    public function allowUnset(bool $allow = \true): static
    {
        $this->allowFalse = $allow;
        return $this;
    }
    /**
     * Sets whether the node can be overwritten.
     *
     * @return $this
     */
    public function denyOverwrite(bool $deny = \true): static
    {
        $this->allowOverwrite = !$deny;
        return $this;
    }
    /**
     * Returns the related node.
     */
    public function end(): NodeDefinition|ArrayNodeDefinition|VariableNodeDefinition
    {
        return $this->node;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Config\Definition\Builder;

use _ContaoManager\Symfony\Component\Config\Definition\Exception\InvalidDefinitionException;
/**
 * Abstract class that contains common code of integer and float node definitions.
 *
 * @author David Jeanmonod <david.jeanmonod@gmail.com>
 */
abstract class NumericNodeDefinition extends ScalarNodeDefinition
{
    protected $min;
    protected $max;
    /**
     * Ensures that the value is smaller than the given reference.
     *
     * @return $this
     *
     * @throws \InvalidArgumentException when the constraint is inconsistent
     */
    public function max(int|float $max): static
    {
        if (isset($this->min) && $this->min > $max) {
            throw new \InvalidArgumentException(\sprintf('You cannot define a max(%s) as you already have a min(%s).', $max, $this->min));
        }
        $this->max = $max;
        return $this;
    }
    /**
     * Ensures that the value is bigger than the given reference.
     *
     * @return $this
     *
     * @throws \InvalidArgumentException when the constraint is inconsistent
     */
    public function min(int|float $min): static
    {
        if (isset($this->max) && $this->max < $min) {
            throw new \InvalidArgumentException(\sprintf('You cannot define a min(%s) as you already have a max(%s).', $min, $this->max));
        }
        $this->min = $min;
        return $this;
    }
    /**
     * @throws InvalidDefinitionException
     */
    public function cannotBeEmpty(): static
    {
        throw new InvalidDefinitionException('->cannotBeEmpty() is not applicable to NumericNodeDefinition.');
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Config\Definition\Builder;

/**
 * This class provides a fluent interface for building a node.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
class NodeBuilder implements NodeParentInterface
{
    protected $parent;
    protected $nodeMapping;
    public function __construct()
    {
        $this->nodeMapping = ['variable' => VariableNodeDefinition::class, 'scalar' => ScalarNodeDefinition::class, 'boolean' => BooleanNodeDefinition::class, 'integer' => IntegerNodeDefinition::class, 'float' => FloatNodeDefinition::class, 'array' => ArrayNodeDefinition::class, 'enum' => EnumNodeDefinition::class];
    }
    /**
     * Set the parent node.
     *
     * @return $this
     */
    public function setParent(?ParentNodeDefinitionInterface $parent = null): static
    {
        if (1 > \func_num_args()) {
            trigger_deprecation('symfony/form', '6.2', 'Calling "%s()" without any arguments is deprecated, pass null explicitly instead.', __METHOD__);
        }
        $this->parent = $parent;
        return $this;
    }
    /**
     * Creates a child array node.
     */
    public function arrayNode(string $name): ArrayNodeDefinition
    {
        return $this->node($name, 'array');
    }
    /**
     * Creates a child scalar node.
     */
    public function scalarNode(string $name): ScalarNodeDefinition
    {
        return $this->node($name, 'scalar');
    }
    /**
     * Creates a child Boolean node.
     */
    public function booleanNode(string $name): BooleanNodeDefinition
    {
        return $this->node($name, 'boolean');
    }
    /**
     * Creates a child integer node.
     */
    public function integerNode(string $name): IntegerNodeDefinition
    {
        return $this->node($name, 'integer');
    }
    /**
     * Creates a child float node.
     */
    public function floatNode(string $name): FloatNodeDefinition
    {
        return $this->node($name, 'float');
    }
    /**
     * Creates a child EnumNode.
     */
    public function enumNode(string $name): EnumNodeDefinition
    {
        return $this->node($name, 'enum');
    }
    /**
     * Creates a child variable node.
     */
    public function variableNode(string $name): VariableNodeDefinition
    {
        return $this->node($name, 'variable');
    }
    /**
     * Returns the parent node.
     *
     * @return NodeDefinition&ParentNodeDefinitionInterface
     */
    public function end()
    {
        return $this->parent;
    }
    /**
     * Creates a child node.
     *
     * @throws \RuntimeException When the node type is not registered
     * @throws \RuntimeException When the node class is not found
     */
    public function node(?string $name, string $type): NodeDefinition
    {
        $class = $this->getNodeClass($type);
        $node = new $class($name);
        $this->append($node);
        return $node;
    }
    /**
     * Appends a node definition.
     *
     * Usage:
     *
     *     $node = new ArrayNodeDefinition('name')
     *         ->children()
     *             ->scalarNode('foo')->end()
     *             ->scalarNode('baz')->end()
     *             ->append($this->getBarNodeDefinition())
     *         ->end()
     *     ;
     *
     * @return $this
     */
    public function append(NodeDefinition $node): static
    {
        if ($node instanceof BuilderAwareInterface) {
            $builder = clone $this;
            $builder->setParent(null);
            $node->setBuilder($builder);
        }
        if (null !== $this->parent) {
            $this->parent->append($node);
            // Make this builder the node parent to allow for a fluid interface
            $node->setParent($this);
        }
        return $this;
    }
    /**
     * Adds or overrides a node Type.
     *
     * @param string $type  The name of the type
     * @param string $class The fully qualified name the node definition class
     *
     * @return $this
     */
    public function setNodeClass(string $type, string $class): static
    {
        $this->nodeMapping[strtolower($type)] = $class;
        return $this;
    }
    /**
     * Returns the class name of the node definition.
     *
     * @throws \RuntimeException When the node type is not registered
     * @throws \RuntimeException When the node class is not found
     */
    protected function getNodeClass(string $type): string
    {
        $type = strtolower($type);
        if (!isset($this->nodeMapping[$type])) {
            throw new \RuntimeException(\sprintf('The node type "%s" is not registered.', $type));
        }
        $class = $this->nodeMapping[$type];
        if (!class_exists($class)) {
            throw new \RuntimeException(\sprintf('The node class "%s" does not exist.', $class));
        }
        return $class;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Config\Definition\Builder;

use _ContaoManager\Symfony\Component\Config\Definition\NodeInterface;
use _ContaoManager\Symfony\Component\Config\Definition\VariableNode;
/**
 * This class provides a fluent interface for defining a node.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
class VariableNodeDefinition extends NodeDefinition
{
    /**
     * Instantiate a Node.
     */
    protected function instantiateNode(): VariableNode
    {
        return new VariableNode($this->name, $this->parent, $this->pathSeparator);
    }
    protected function createNode(): NodeInterface
    {
        $node = $this->instantiateNode();
        if (isset($this->normalization)) {
            $node->setNormalizationClosures($this->normalization->before);
        }
        if (isset($this->merge)) {
            $node->setAllowOverwrite($this->merge->allowOverwrite);
        }
        if (\true === $this->default) {
            $node->setDefaultValue($this->defaultValue);
        }
        $node->setAllowEmptyValue($this->allowEmptyValue);
        $node->addEquivalentValue(null, $this->nullEquivalent);
        $node->addEquivalentValue(\true, $this->trueEquivalent);
        $node->addEquivalentValue(\false, $this->falseEquivalent);
        $node->setRequired($this->required);
        if ($this->deprecation) {
            $node->setDeprecated($this->deprecation['package'], $this->deprecation['version'], $this->deprecation['message']);
        }
        if (isset($this->validation)) {
            $node->setFinalValidationClosures($this->validation->rules);
        }
        return $node;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Config\Definition\Builder;

use _ContaoManager\Symfony\Component\Config\Definition\ArrayNode;
use _ContaoManager\Symfony\Component\Config\Definition\Exception\InvalidDefinitionException;
use _ContaoManager\Symfony\Component\Config\Definition\NodeInterface;
use _ContaoManager\Symfony\Component\Config\Definition\PrototypedArrayNode;
/**
 * This class provides a fluent interface for defining an array node.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
class ArrayNodeDefinition extends NodeDefinition implements ParentNodeDefinitionInterface
{
    protected $performDeepMerging = \true;
    protected $ignoreExtraKeys = \false;
    protected $removeExtraKeys = \true;
    protected $children = [];
    protected $prototype;
    protected $atLeastOne = \false;
    protected $allowNewKeys = \true;
    protected $key;
    protected $removeKeyItem;
    protected $addDefaults = \false;
    protected $addDefaultChildren = \false;
    protected $nodeBuilder;
    protected $normalizeKeys = \true;
    public function __construct(?string $name, ?NodeParentInterface $parent = null)
    {
        parent::__construct($name, $parent);
        $this->nullEquivalent = [];
        $this->trueEquivalent = [];
    }
    /**
     * @return void
     */
    public function setBuilder(NodeBuilder $builder)
    {
        $this->nodeBuilder = $builder;
    }
    public function children(): NodeBuilder
    {
        return $this->getNodeBuilder();
    }
    /**
     * Sets a prototype for child nodes.
     */
    public function prototype(string $type): NodeDefinition
    {
        return $this->prototype = $this->getNodeBuilder()->node(null, $type)->setParent($this);
    }
    public function variablePrototype(): VariableNodeDefinition
    {
        return $this->prototype('variable');
    }
    public function scalarPrototype(): ScalarNodeDefinition
    {
        return $this->prototype('scalar');
    }
    public function booleanPrototype(): BooleanNodeDefinition
    {
        return $this->prototype('boolean');
    }
    public function integerPrototype(): IntegerNodeDefinition
    {
        return $this->prototype('integer');
    }
    public function floatPrototype(): FloatNodeDefinition
    {
        return $this->prototype('float');
    }
    public function arrayPrototype(): self
    {
        return $this->prototype('array');
    }
    public function enumPrototype(): EnumNodeDefinition
    {
        return $this->prototype('enum');
    }
    /**
     * Adds the default value if the node is not set in the configuration.
     *
     * This method is applicable to concrete nodes only (not to prototype nodes).
     * If this function has been called and the node is not set during the finalization
     * phase, it's default value will be derived from its children default values.
     *
     * @return $this
     */
    public function addDefaultsIfNotSet(): static
    {
        $this->addDefaults = \true;
        return $this;
    }
    /**
     * Adds children with a default value when none are defined.
     *
     * This method is applicable to prototype nodes only.
     *
     * @param int|string|array|null $children The number of children|The child name|The children names to be added
     *
     * @return $this
     */
    public function addDefaultChildrenIfNoneSet(int|string|array|null $children = null): static
    {
        $this->addDefaultChildren = $children;
        return $this;
    }
    /**
     * Requires the node to have at least one element.
     *
     * This method is applicable to prototype nodes only.
     *
     * @return $this
     */
    public function requiresAtLeastOneElement(): static
    {
        $this->atLeastOne = \true;
        return $this;
    }
    /**
     * Disallows adding news keys in a subsequent configuration.
     *
     * If used all keys have to be defined in the same configuration file.
     *
     * @return $this
     */
    public function disallowNewKeysInSubsequentConfigs(): static
    {
        $this->allowNewKeys = \false;
        return $this;
    }
    /**
     * Sets a normalization rule for XML configurations.
     *
     * @param string      $singular The key to remap
     * @param string|null $plural   The plural of the key for irregular plurals
     *
     * @return $this
     */
    public function fixXmlConfig(string $singular, ?string $plural = null): static
    {
        $this->normalization()->remap($singular, $plural);
        return $this;
    }
    /**
     * Sets the attribute which value is to be used as key.
     *
     * This is useful when you have an indexed array that should be an
     * associative array. You can select an item from within the array
     * to be the key of the particular item. For example, if "id" is the
     * "key", then:
     *
     *     [
     *         ['id' => 'my_name', 'foo' => 'bar'],
     *     ];
     *
     *   becomes
     *
     *     [
     *         'my_name' => ['foo' => 'bar'],
     *     ];
     *
     * If you'd like "'id' => 'my_name'" to still be present in the resulting
     * array, then you can set the second argument of this method to false.
     *
     * This method is applicable to prototype nodes only.
     *
     * @param string $name          The name of the key
     * @param bool   $removeKeyItem Whether or not the key item should be removed
     *
     * @return $this
     */
    public function useAttributeAsKey(string $name, bool $removeKeyItem = \true): static
    {
        $this->key = $name;
        $this->removeKeyItem = $removeKeyItem;
        return $this;
    }
    /**
     * Sets whether the node can be unset.
     *
     * @return $this
     */
    public function canBeUnset(bool $allow = \true): static
    {
        $this->merge()->allowUnset($allow);
        return $this;
    }
    /**
     * Adds an "enabled" boolean to enable the current section.
     *
     * By default, the section is disabled. If any configuration is specified then
     * the node will be automatically enabled:
     *
     * enableableArrayNode: {enabled: true, ...}   # The config is enabled & default values get overridden
     * enableableArrayNode: ~                      # The config is enabled & use the default values
     * enableableArrayNode: true                   # The config is enabled & use the default values
     * enableableArrayNode: {other: value, ...}    # The config is enabled & default values get overridden
     * enableableArrayNode: {enabled: false, ...}  # The config is disabled
     * enableableArrayNode: false                  # The config is disabled
     *
     * @return $this
     */
    public function canBeEnabled(): static
    {
        $this->addDefaultsIfNotSet()->treatFalseLike(['enabled' => \false])->treatTrueLike(['enabled' => \true])->treatNullLike(['enabled' => \true])->beforeNormalization()->ifArray()->then(function (array $v) {
            $v['enabled'] ??= \true;
            return $v;
        })->end()->children()->booleanNode('enabled')->defaultFalse();
        return $this;
    }
    /**
     * Adds an "enabled" boolean to enable the current section.
     *
     * By default, the section is enabled.
     *
     * @return $this
     */
    public function canBeDisabled(): static
    {
        $this->addDefaultsIfNotSet()->treatFalseLike(['enabled' => \false])->treatTrueLike(['enabled' => \true])->treatNullLike(['enabled' => \true])->children()->booleanNode('enabled')->defaultTrue();
        return $this;
    }
    /**
     * Disables the deep merging of the node.
     *
     * @return $this
     */
    public function performNoDeepMerging(): static
    {
        $this->performDeepMerging = \false;
        return $this;
    }
    /**
     * Allows extra config keys to be specified under an array without
     * throwing an exception.
     *
     * Those config values are ignored and removed from the resulting
     * array. This should be used only in special cases where you want
     * to send an entire configuration array through a special tree that
     * processes only part of the array.
     *
     * @param bool $remove Whether to remove the extra keys
     *
     * @return $this
     */
    public function ignoreExtraKeys(bool $remove = \true): static
    {
        $this->ignoreExtraKeys = \true;
        $this->removeExtraKeys = $remove;
        return $this;
    }
    /**
     * Sets whether to enable key normalization.
     *
     * @return $this
     */
    public function normalizeKeys(bool $bool): static
    {
        $this->normalizeKeys = $bool;
        return $this;
    }
    public function append(NodeDefinition $node): static
    {
        $this->children[$node->name ?? ''] = $node->setParent($this);
        return $this;
    }
    /**
     * Returns a node builder to be used to add children and prototype.
     */
    protected function getNodeBuilder(): NodeBuilder
    {
        $this->nodeBuilder ??= new NodeBuilder();
        return $this->nodeBuilder->setParent($this);
    }
    protected function createNode(): NodeInterface
    {
        if (!isset($this->prototype)) {
            $node = new ArrayNode($this->name, $this->parent, $this->pathSeparator);
            $this->validateConcreteNode($node);
            $node->setAddIfNotSet($this->addDefaults);
            foreach ($this->children as $child) {
                $child->parent = $node;
                $node->addChild($child->getNode());
            }
        } else {
            $node = new PrototypedArrayNode($this->name, $this->parent, $this->pathSeparator);
            $this->validatePrototypeNode($node);
            if (null !== $this->key) {
                $node->setKeyAttribute($this->key, $this->removeKeyItem);
            }
            if (\true === $this->atLeastOne || \false === $this->allowEmptyValue) {
                $node->setMinNumberOfElements(1);
            }
            if ($this->default) {
                if (!\is_array($this->defaultValue)) {
                    throw new \InvalidArgumentException(\sprintf('%s: the default value of an array node has to be an array.', $node->getPath()));
                }
                $node->setDefaultValue($this->defaultValue);
            }
            if (\false !== $this->addDefaultChildren) {
                $node->setAddChildrenIfNoneSet($this->addDefaultChildren);
                if ($this->prototype instanceof static && !isset($this->prototype->prototype)) {
                    $this->prototype->addDefaultsIfNotSet();
                }
            }
            $this->prototype->parent = $node;
            $node->setPrototype($this->prototype->getNode());
        }
        $node->setAllowNewKeys($this->allowNewKeys);
        $node->addEquivalentValue(null, $this->nullEquivalent);
        $node->addEquivalentValue(\true, $this->trueEquivalent);
        $node->addEquivalentValue(\false, $this->falseEquivalent);
        $node->setPerformDeepMerging($this->performDeepMerging);
        $node->setRequired($this->required);
        $node->setIgnoreExtraKeys($this->ignoreExtraKeys, $this->removeExtraKeys);
        $node->setNormalizeKeys($this->normalizeKeys);
        if ($this->deprecation) {
            $node->setDeprecated($this->deprecation['package'], $this->deprecation['version'], $this->deprecation['message']);
        }
        if (isset($this->normalization)) {
            $node->setNormalizationClosures($this->normalization->before);
            $node->setNormalizedTypes($this->normalization->declaredTypes);
            $node->setXmlRemappings($this->normalization->remappings);
        }
        if (isset($this->merge)) {
            $node->setAllowOverwrite($this->merge->allowOverwrite);
            $node->setAllowFalse($this->merge->allowFalse);
        }
        if (isset($this->validation)) {
            $node->setFinalValidationClosures($this->validation->rules);
        }
        return $node;
    }
    /**
     * Validate the configuration of a concrete node.
     *
     * @return void
     *
     * @throws InvalidDefinitionException
     */
    protected function validateConcreteNode(ArrayNode $node)
    {
        $path = $node->getPath();
        if (null !== $this->key) {
            throw new InvalidDefinitionException(\sprintf('->useAttributeAsKey() is not applicable to concrete nodes at path "%s".', $path));
        }
        if (\false === $this->allowEmptyValue) {
            throw new InvalidDefinitionException(\sprintf('->cannotBeEmpty() is not applicable to concrete nodes at path "%s".', $path));
        }
        if (\true === $this->atLeastOne) {
            throw new InvalidDefinitionException(\sprintf('->requiresAtLeastOneElement() is not applicable to concrete nodes at path "%s".', $path));
        }
        if ($this->default) {
            throw new InvalidDefinitionException(\sprintf('->defaultValue() is not applicable to concrete nodes at path "%s".', $path));
        }
        if (\false !== $this->addDefaultChildren) {
            throw new InvalidDefinitionException(\sprintf('->addDefaultChildrenIfNoneSet() is not applicable to concrete nodes at path "%s".', $path));
        }
    }
    /**
     * Validate the configuration of a prototype node.
     *
     * @return void
     *
     * @throws InvalidDefinitionException
     */
    protected function validatePrototypeNode(PrototypedArrayNode $node)
    {
        $path = $node->getPath();
        if ($this->addDefaults) {
            throw new InvalidDefinitionException(\sprintf('->addDefaultsIfNotSet() is not applicable to prototype nodes at path "%s".', $path));
        }
        if (\false !== $this->addDefaultChildren) {
            if ($this->default) {
                throw new InvalidDefinitionException(\sprintf('A default value and default children might not be used together at path "%s".', $path));
            }
            if (null !== $this->key && (null === $this->addDefaultChildren || \is_int($this->addDefaultChildren) && $this->addDefaultChildren > 0)) {
                throw new InvalidDefinitionException(\sprintf('->addDefaultChildrenIfNoneSet() should set default children names as ->useAttributeAsKey() is used at path "%s".', $path));
            }
            if (null === $this->key && (\is_string($this->addDefaultChildren) || \is_array($this->addDefaultChildren))) {
                throw new InvalidDefinitionException(\sprintf('->addDefaultChildrenIfNoneSet() might not set default children names as ->useAttributeAsKey() is not used at path "%s".', $path));
            }
        }
    }
    /**
     * @return NodeDefinition[]
     */
    public function getChildNodeDefinitions(): array
    {
        return $this->children;
    }
    /**
     * Finds a node defined by the given $nodePath.
     *
     * @param string $nodePath The path of the node to find. e.g "doctrine.orm.mappings"
     */
    public function find(string $nodePath): NodeDefinition
    {
        $firstPathSegment = \false === ($pathSeparatorPos = strpos($nodePath, $this->pathSeparator)) ? $nodePath : substr($nodePath, 0, $pathSeparatorPos);
        if (null === $node = $this->children[$firstPathSegment] ?? null) {
            throw new \RuntimeException(\sprintf('Node with name "%s" does not exist in the current node "%s".', $firstPathSegment, $this->name));
        }
        if (\false === $pathSeparatorPos) {
            return $node;
        }
        return $node->find(substr($nodePath, $pathSeparatorPos + \strlen($this->pathSeparator)));
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Config\Definition\Builder;

/**
 * An interface that can be implemented by nodes which build other nodes.
 *
 * @author Roland Franssen <franssen.roland@gmail.com>
 */
interface BuilderAwareInterface
{
    /**
     * Sets a custom children builder.
     *
     * @return void
     */
    public function setBuilder(NodeBuilder $builder);
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Config\Definition\Builder;

/**
 * This class builds validation conditions.
 *
 * @author Christophe Coevoet <stof@notk.org>
 */
class ValidationBuilder
{
    protected $node;
    public $rules = [];
    public function __construct(NodeDefinition $node)
    {
        $this->node = $node;
    }
    /**
     * Registers a closure to run as normalization or an expression builder to build it if null is provided.
     *
     * @return ExprBuilder|$this
     */
    public function rule(?\Closure $closure = null): ExprBuilder|static
    {
        if (null !== $closure) {
            $this->rules[] = $closure;
            return $this;
        }
        return $this->rules[] = new ExprBuilder($this->node);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Config\Definition\Builder;

use _ContaoManager\Symfony\Component\Config\Definition\NodeInterface;
/**
 * This is the entry class for building a config tree.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
class TreeBuilder implements NodeParentInterface
{
    /**
     * @var NodeInterface|null
     */
    protected $tree;
    /**
     * @var NodeDefinition
     */
    protected $root;
    public function __construct(string $name, string $type = 'array', ?NodeBuilder $builder = null)
    {
        $builder ??= new NodeBuilder();
        $this->root = $builder->node($name, $type)->setParent($this);
    }
    /**
     * @return NodeDefinition|ArrayNodeDefinition The root node (as an ArrayNodeDefinition when the type is 'array')
     */
    public function getRootNode(): NodeDefinition|ArrayNodeDefinition
    {
        return $this->root;
    }
    /**
     * Builds the tree.
     *
     * @throws \RuntimeException
     */
    public function buildTree(): NodeInterface
    {
        return $this->tree ??= $this->root->getNode(\true);
    }
    /**
     * @return void
     */
    public function setPathSeparator(string $separator)
    {
        // unset last built as changing path separator changes all nodes
        $this->tree = null;
        $this->root->setPathSeparator($separator);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Config\Definition\Builder;

use _ContaoManager\Symfony\Component\Config\Definition\IntegerNode;
/**
 * This class provides a fluent interface for defining an integer node.
 *
 * @author Jeanmonod David <david.jeanmonod@gmail.com>
 */
class IntegerNodeDefinition extends NumericNodeDefinition
{
    /**
     * Instantiates a Node.
     */
    protected function instantiateNode(): IntegerNode
    {
        return new IntegerNode($this->name, $this->parent, $this->min, $this->max, $this->pathSeparator);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Config\Definition\Builder;

/**
 * An interface that must be implemented by all node parents.
 *
 * @author Victor Berchet <victor@suumit.com>
 */
interface NodeParentInterface
{
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Config\Definition\Builder;

/**
 * This class builds normalization conditions.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
class NormalizationBuilder
{
    protected $node;
    public $before = [];
    public $declaredTypes = [];
    public $remappings = [];
    public function __construct(NodeDefinition $node)
    {
        $this->node = $node;
    }
    /**
     * Registers a key to remap to its plural form.
     *
     * @param string      $key    The key to remap
     * @param string|null $plural The plural of the key in case of irregular plural
     *
     * @return $this
     */
    public function remap(string $key, ?string $plural = null): static
    {
        $this->remappings[] = [$key, null === $plural ? $key . 's' : $plural];
        return $this;
    }
    /**
     * Registers a closure to run before the normalization or an expression builder to build it if null is provided.
     *
     * @return ExprBuilder|$this
     */
    public function before(?\Closure $closure = null): ExprBuilder|static
    {
        if (null !== $closure) {
            $this->before[] = $closure;
            return $this;
        }
        return $this->before[] = new ExprBuilder($this->node);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Config\Definition\Builder;

use _ContaoManager\Symfony\Component\Config\Definition\BooleanNode;
use _ContaoManager\Symfony\Component\Config\Definition\Exception\InvalidDefinitionException;
/**
 * This class provides a fluent interface for defining a node.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
class BooleanNodeDefinition extends ScalarNodeDefinition
{
    public function __construct(?string $name, ?NodeParentInterface $parent = null)
    {
        parent::__construct($name, $parent);
        $this->nullEquivalent = \true;
    }
    /**
     * Instantiate a Node.
     */
    protected function instantiateNode(): BooleanNode
    {
        return new BooleanNode($this->name, $this->parent, $this->pathSeparator);
    }
    /**
     * @throws InvalidDefinitionException
     */
    public function cannotBeEmpty(): static
    {
        throw new InvalidDefinitionException('->cannotBeEmpty() is not applicable to BooleanNodeDefinition.');
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Config\Definition\Builder;

/**
 * An interface that must be implemented by nodes which can have children.
 *
 * @author Victor Berchet <victor@suumit.com>
 */
interface ParentNodeDefinitionInterface extends BuilderAwareInterface
{
    /**
     * Returns a builder to add children nodes.
     */
    public function children(): NodeBuilder;
    /**
     * Appends a node definition.
     *
     * Usage:
     *
     *     $node = $parentNode
     *         ->children()
     *             ->scalarNode('foo')->end()
     *             ->scalarNode('baz')->end()
     *             ->append($this->getBarNodeDefinition())
     *         ->end()
     *     ;
     *
     * @return $this
     */
    public function append(NodeDefinition $node): static;
    /**
     * Gets the child node definitions.
     *
     * @return NodeDefinition[]
     */
    public function getChildNodeDefinitions(): array;
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Config\Definition\Builder;

use _ContaoManager\Symfony\Component\Config\Definition\ScalarNode;
/**
 * This class provides a fluent interface for defining a node.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
class ScalarNodeDefinition extends VariableNodeDefinition
{
    /**
     * Instantiate a Node.
     */
    protected function instantiateNode(): ScalarNode
    {
        return new ScalarNode($this->name, $this->parent, $this->pathSeparator);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Config\Definition\Builder;

use _ContaoManager\Symfony\Component\Config\Definition\FloatNode;
/**
 * This class provides a fluent interface for defining a float node.
 *
 * @author Jeanmonod David <david.jeanmonod@gmail.com>
 */
class FloatNodeDefinition extends NumericNodeDefinition
{
    /**
     * Instantiates a Node.
     */
    protected function instantiateNode(): FloatNode
    {
        return new FloatNode($this->name, $this->parent, $this->min, $this->max, $this->pathSeparator);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Config\Definition\Builder;

use _ContaoManager\Symfony\Component\Config\Definition\BaseNode;
use _ContaoManager\Symfony\Component\Config\Definition\Exception\InvalidDefinitionException;
use _ContaoManager\Symfony\Component\Config\Definition\NodeInterface;
/**
 * This class provides a fluent interface for defining a node.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
abstract class NodeDefinition implements NodeParentInterface
{
    protected $name;
    protected $normalization;
    protected $validation;
    protected $defaultValue;
    protected $default = \false;
    protected $required = \false;
    protected $deprecation = [];
    protected $merge;
    protected $allowEmptyValue = \true;
    protected $nullEquivalent;
    protected $trueEquivalent = \true;
    protected $falseEquivalent = \false;
    protected $pathSeparator = BaseNode::DEFAULT_PATH_SEPARATOR;
    protected $parent;
    protected $attributes = [];
    public function __construct(?string $name, ?NodeParentInterface $parent = null)
    {
        $this->parent = $parent;
        $this->name = $name;
    }
    /**
     * Sets the parent node.
     *
     * @return $this
     */
    public function setParent(NodeParentInterface $parent): static
    {
        $this->parent = $parent;
        return $this;
    }
    /**
     * Sets info message.
     *
     * @return $this
     */
    public function info(string $info): static
    {
        return $this->attribute('info', $info);
    }
    /**
     * Sets example configuration.
     *
     * @return $this
     */
    public function example(string|array $example): static
    {
        return $this->attribute('example', $example);
    }
    /**
     * Sets an attribute on the node.
     *
     * @return $this
     */
    public function attribute(string $key, mixed $value): static
    {
        $this->attributes[$key] = $value;
        return $this;
    }
    /**
     * Returns the parent node.
     */
    public function end(): NodeParentInterface|NodeBuilder|self|ArrayNodeDefinition|VariableNodeDefinition|null
    {
        return $this->parent;
    }
    /**
     * Creates the node.
     */
    public function getNode(bool $forceRootNode = \false): NodeInterface
    {
        if ($forceRootNode) {
            $this->parent = null;
        }
        if (isset($this->normalization)) {
            $allowedTypes = [];
            foreach ($this->normalization->before as $expr) {
                $allowedTypes[] = $expr->allowedTypes;
            }
            $allowedTypes = array_unique($allowedTypes);
            $this->normalization->before = ExprBuilder::buildExpressions($this->normalization->before);
            $this->normalization->declaredTypes = $allowedTypes;
        }
        if (isset($this->validation)) {
            $this->validation->rules = ExprBuilder::buildExpressions($this->validation->rules);
        }
        $node = $this->createNode();
        if ($node instanceof BaseNode) {
            $node->setAttributes($this->attributes);
        }
        return $node;
    }
    /**
     * Sets the default value.
     *
     * @return $this
     */
    public function defaultValue(mixed $value): static
    {
        $this->default = \true;
        $this->defaultValue = $value;
        return $this;
    }
    /**
     * Sets the node as required.
     *
     * @return $this
     */
    public function isRequired(): static
    {
        $this->required = \true;
        return $this;
    }
    /**
     * Sets the node as deprecated.
     *
     * @param string $package The name of the composer package that is triggering the deprecation
     * @param string $version The version of the package that introduced the deprecation
     * @param string $message the deprecation message to use
     *
     * You can use %node% and %path% placeholders in your message to display,
     * respectively, the node name and its complete path
     *
     * @return $this
     */
    public function setDeprecated(string $package, string $version, string $message = 'The child node "%node%" at path "%path%" is deprecated.'): static
    {
        $this->deprecation = ['package' => $package, 'version' => $version, 'message' => $message];
        return $this;
    }
    /**
     * Sets the equivalent value used when the node contains null.
     *
     * @return $this
     */
    public function treatNullLike(mixed $value): static
    {
        $this->nullEquivalent = $value;
        return $this;
    }
    /**
     * Sets the equivalent value used when the node contains true.
     *
     * @return $this
     */
    public function treatTrueLike(mixed $value): static
    {
        $this->trueEquivalent = $value;
        return $this;
    }
    /**
     * Sets the equivalent value used when the node contains false.
     *
     * @return $this
     */
    public function treatFalseLike(mixed $value): static
    {
        $this->falseEquivalent = $value;
        return $this;
    }
    /**
     * Sets null as the default value.
     *
     * @return $this
     */
    public function defaultNull(): static
    {
        return $this->defaultValue(null);
    }
    /**
     * Sets true as the default value.
     *
     * @return $this
     */
    public function defaultTrue(): static
    {
        return $this->defaultValue(\true);
    }
    /**
     * Sets false as the default value.
     *
     * @return $this
     */
    public function defaultFalse(): static
    {
        return $this->defaultValue(\false);
    }
    /**
     * Sets an expression to run before the normalization.
     */
    public function beforeNormalization(): ExprBuilder
    {
        return $this->normalization()->before();
    }
    /**
     * Denies the node value being empty.
     *
     * @return $this
     */
    public function cannotBeEmpty(): static
    {
        $this->allowEmptyValue = \false;
        return $this;
    }
    /**
     * Sets an expression to run for the validation.
     *
     * The expression receives the value of the node and must return it. It can
     * modify it.
     * An exception should be thrown when the node is not valid.
     */
    public function validate(): ExprBuilder
    {
        return $this->validation()->rule();
    }
    /**
     * Sets whether the node can be overwritten.
     *
     * @return $this
     */
    public function cannotBeOverwritten(bool $deny = \true): static
    {
        $this->merge()->denyOverwrite($deny);
        return $this;
    }
    /**
     * Gets the builder for validation rules.
     */
    protected function validation(): ValidationBuilder
    {
        return $this->validation ??= new ValidationBuilder($this);
    }
    /**
     * Gets the builder for merging rules.
     */
    protected function merge(): MergeBuilder
    {
        return $this->merge ??= new MergeBuilder($this);
    }
    /**
     * Gets the builder for normalization rules.
     */
    protected function normalization(): NormalizationBuilder
    {
        return $this->normalization ??= new NormalizationBuilder($this);
    }
    /**
     * Instantiate and configure the node according to this definition.
     *
     * @throws InvalidDefinitionException When the definition is invalid
     */
    abstract protected function createNode(): NodeInterface;
    /**
     * Set PathSeparator to use.
     *
     * @return $this
     */
    public function setPathSeparator(string $separator): static
    {
        if ($this instanceof ParentNodeDefinitionInterface) {
            foreach ($this->getChildNodeDefinitions() as $child) {
                $child->setPathSeparator($separator);
            }
        }
        $this->pathSeparator = $separator;
        return $this;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Config\Definition\Exception;

/**
 * This exception is thrown whenever the key of an array is not unique. This can
 * only be the case if the configuration is coming from an XML file.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
class DuplicateKeyException extends InvalidConfigurationException
{
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Config\Definition\Exception;

/**
 * Thrown when an error is detected in a node Definition.
 *
 * @author Victor Berchet <victor.berchet@suumit.com>
 */
class InvalidDefinitionException extends Exception
{
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Config\Definition\Exception;

/**
 * This exception is thrown if an invalid type is encountered.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
class InvalidTypeException extends InvalidConfigurationException
{
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Config\Definition\Exception;

/**
 * This exception is usually not encountered by the end-user, but only used
 * internally to signal the parent scope to unset a key.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
class UnsetKeyException extends Exception
{
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Config\Definition\Exception;

/**
 * A very general exception which can be thrown whenever non of the more specific
 * exceptions is suitable.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
class InvalidConfigurationException extends Exception
{
    private ?string $path = null;
    private bool $containsHints = \false;
    /**
     * @return void
     */
    public function setPath(string $path)
    {
        $this->path = $path;
    }
    public function getPath(): ?string
    {
        return $this->path;
    }
    /**
     * Adds extra information that is suffixed to the original exception message.
     *
     * @return void
     */
    public function addHint(string $hint)
    {
        if (!$this->containsHints) {
            $this->message .= "\nHint: " . $hint;
            $this->containsHints = \true;
        } else {
            $this->message .= ', ' . $hint;
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Config\Definition\Exception;

/**
 * This exception is thrown when a configuration path is overwritten from a
 * subsequent configuration file, but the entry node specifically forbids this.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
class ForbiddenOverwriteException extends InvalidConfigurationException
{
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Config\Definition\Exception;

/**
 * Base exception for all configuration exceptions.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
class Exception extends \RuntimeException
{
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Config\Definition;

use _ContaoManager\Symfony\Component\Config\Definition\Exception\InvalidConfigurationException;
/**
 * This node represents a value of variable type in the config tree.
 *
 * This node is intended for values of arbitrary type.
 * Any PHP type is accepted as a value.
 *
 * @author Jeremy Mikola <jmikola@gmail.com>
 */
class VariableNode extends BaseNode implements PrototypeNodeInterface
{
    protected $defaultValueSet = \false;
    protected $defaultValue;
    protected $allowEmptyValue = \true;
    /**
     * @return void
     */
    public function setDefaultValue(mixed $value)
    {
        $this->defaultValueSet = \true;
        $this->defaultValue = $value;
    }
    public function hasDefaultValue(): bool
    {
        return $this->defaultValueSet;
    }
    public function getDefaultValue(): mixed
    {
        $v = $this->defaultValue;
        return $v instanceof \Closure ? $v() : $v;
    }
    /**
     * Sets if this node is allowed to have an empty value.
     *
     * @param bool $boolean True if this entity will accept empty values
     *
     * @return void
     */
    public function setAllowEmptyValue(bool $boolean)
    {
        $this->allowEmptyValue = $boolean;
    }
    /**
     * @return void
     */
    public function setName(string $name)
    {
        $this->name = $name;
    }
    /**
     * @return void
     */
    protected function validateType(mixed $value)
    {
    }
    protected function finalizeValue(mixed $value): mixed
    {
        // deny environment variables only when using custom validators
        // this avoids ever passing an empty value to final validation closures
        if (!$this->allowEmptyValue && $this->isHandlingPlaceholder() && $this->finalValidationClosures) {
            $e = new InvalidConfigurationException(\sprintf('The path "%s" cannot contain an environment variable when empty values are not allowed by definition and are validated.', $this->getPath()));
            if ($hint = $this->getInfo()) {
                $e->addHint($hint);
            }
            $e->setPath($this->getPath());
            throw $e;
        }
        if (!$this->allowEmptyValue && $this->isValueEmpty($value)) {
            $ex = new InvalidConfigurationException(\sprintf('The path "%s" cannot contain an empty value, but got %s.', $this->getPath(), json_encode($value)));
            if ($hint = $this->getInfo()) {
                $ex->addHint($hint);
            }
            $ex->setPath($this->getPath());
            throw $ex;
        }
        return $value;
    }
    protected function normalizeValue(mixed $value): mixed
    {
        return $value;
    }
    protected function mergeValues(mixed $leftSide, mixed $rightSide): mixed
    {
        return $rightSide;
    }
    /**
     * Evaluates if the given value is to be treated as empty.
     *
     * By default, PHP's empty() function is used to test for emptiness. This
     * method may be overridden by subtypes to better match their understanding
     * of empty data.
     *
     * @see finalizeValue()
     */
    protected function isValueEmpty(mixed $value): bool
    {
        return empty($value);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Config\Definition\Dumper;

use _ContaoManager\Symfony\Component\Config\Definition\ArrayNode;
use _ContaoManager\Symfony\Component\Config\Definition\BaseNode;
use _ContaoManager\Symfony\Component\Config\Definition\ConfigurationInterface;
use _ContaoManager\Symfony\Component\Config\Definition\EnumNode;
use _ContaoManager\Symfony\Component\Config\Definition\NodeInterface;
use _ContaoManager\Symfony\Component\Config\Definition\PrototypedArrayNode;
use _ContaoManager\Symfony\Component\Config\Definition\ScalarNode;
use _ContaoManager\Symfony\Component\Yaml\Inline;
/**
 * Dumps a Yaml reference configuration for the given configuration/node instance.
 *
 * @author Kevin Bond <kevinbond@gmail.com>
 */
class YamlReferenceDumper
{
    private ?string $reference = null;
    /**
     * @return string
     */
    public function dump(ConfigurationInterface $configuration)
    {
        return $this->dumpNode($configuration->getConfigTreeBuilder()->buildTree());
    }
    /**
     * @return string
     */
    public function dumpAtPath(ConfigurationInterface $configuration, string $path)
    {
        $rootNode = $node = $configuration->getConfigTreeBuilder()->buildTree();
        foreach (explode('.', $path) as $step) {
            if (!$node instanceof ArrayNode) {
                throw new \UnexpectedValueException(\sprintf('Unable to find node at path "%s.%s".', $rootNode->getName(), $path));
            }
            /** @var NodeInterface[] $children */
            $children = $node instanceof PrototypedArrayNode ? $this->getPrototypeChildren($node) : $node->getChildren();
            foreach ($children as $child) {
                if ($child->getName() === $step) {
                    $node = $child;
                    continue 2;
                }
            }
            throw new \UnexpectedValueException(\sprintf('Unable to find node at path "%s.%s".', $rootNode->getName(), $path));
        }
        return $this->dumpNode($node);
    }
    /**
     * @return string
     */
    public function dumpNode(NodeInterface $node)
    {
        $this->reference = '';
        $this->writeNode($node);
        $ref = $this->reference;
        $this->reference = null;
        return $ref;
    }
    private function writeNode(NodeInterface $node, ?NodeInterface $parentNode = null, int $depth = 0, bool $prototypedArray = \false): void
    {
        $comments = [];
        $default = '';
        $defaultArray = null;
        $children = null;
        $example = null;
        if ($node instanceof BaseNode) {
            $example = $node->getExample();
        }
        // defaults
        if ($node instanceof ArrayNode) {
            $children = $node->getChildren();
            if ($node instanceof PrototypedArrayNode) {
                $children = $this->getPrototypeChildren($node);
            }
            if (!$children && !($node->hasDefaultValue() && \count($defaultArray = $node->getDefaultValue()))) {
                $default = '[]';
            }
        } elseif ($node instanceof EnumNode) {
            $comments[] = 'One of ' . $node->getPermissibleValues('; ');
            $default = $node->hasDefaultValue() ? Inline::dump($node->getDefaultValue()) : '~';
        } else {
            $default = '~';
            if ($node->hasDefaultValue()) {
                $default = $node->getDefaultValue();
                if (\is_array($default)) {
                    if (\count($defaultArray = $node->getDefaultValue())) {
                        $default = '';
                    } elseif (!\is_array($example)) {
                        $default = '[]';
                    }
                } else {
                    $default = Inline::dump($default);
                }
            }
        }
        // required?
        if ($node->isRequired()) {
            $comments[] = 'Required';
        }
        // deprecated?
        if ($node instanceof BaseNode && $node->isDeprecated()) {
            $deprecation = $node->getDeprecation($node->getName(), $parentNode ? $parentNode->getPath() : $node->getPath());
            $comments[] = \sprintf('Deprecated (%s)', ($deprecation['package'] || $deprecation['version'] ? "Since {$deprecation['package']} {$deprecation['version']}: " : '') . $deprecation['message']);
        }
        // example
        if ($example && !\is_array($example)) {
            $comments[] = 'Example: ' . Inline::dump($example);
        }
        $default = '' != (string) $default ? ' ' . $default : '';
        $comments = \count($comments) ? '# ' . implode(', ', $comments) : '';
        $key = $prototypedArray ? '-' : $node->getName() . ':';
        $text = rtrim(\sprintf('%-21s%s %s', $key, $default, $comments), ' ');
        if ($node instanceof BaseNode && $info = $node->getInfo()) {
            $this->writeLine('');
            // indenting multi-line info
            $info = str_replace("\n", \sprintf("\n%" . $depth * 4 . 's# ', ' '), $info);
            $this->writeLine('# ' . $info, $depth * 4);
        }
        $this->writeLine($text, $depth * 4);
        // output defaults
        if ($defaultArray) {
            $this->writeLine('');
            $message = \count($defaultArray) > 1 ? 'Defaults' : 'Default';
            $this->writeLine('# ' . $message . ':', $depth * 4 + 4);
            $this->writeArray($defaultArray, $depth + 1);
        }
        if (\is_array($example)) {
            $this->writeLine('');
            $message = \count($example) > 1 ? 'Examples' : 'Example';
            $this->writeLine('# ' . $message . ':', $depth * 4 + 4);
            $this->writeArray(array_map(Inline::dump(...), $example), $depth + 1, \true);
        }
        if ($children) {
            foreach ($children as $childNode) {
                $this->writeNode($childNode, $node, $depth + 1, $node instanceof PrototypedArrayNode && !$node->getKeyAttribute());
            }
        }
    }
    /**
     * Outputs a single config reference line.
     */
    private function writeLine(string $text, int $indent = 0): void
    {
        $indent = \strlen($text) + $indent;
        $format = '%' . $indent . 's';
        $this->reference .= \sprintf($format, $text) . "\n";
    }
    private function writeArray(array $array, int $depth, bool $asComment = \false): void
    {
        $isIndexed = array_is_list($array);
        foreach ($array as $key => $value) {
            if (\is_array($value)) {
                $val = '';
            } else {
                $val = $value;
            }
            $prefix = $asComment ? '# ' : '';
            if ($isIndexed) {
                $this->writeLine($prefix . '- ' . $val, $depth * 4);
            } else {
                $this->writeLine(\sprintf('%s%-20s %s', $prefix, $key . ':', $val), $depth * 4);
            }
            if (\is_array($value)) {
                $this->writeArray($value, $depth + 1, $asComment);
            }
        }
    }
    private function getPrototypeChildren(PrototypedArrayNode $node): array
    {
        $prototype = $node->getPrototype();
        $key = $node->getKeyAttribute();
        // Do not expand prototype if it isn't an array node nor uses attribute as key
        if (!$key && !$prototype instanceof ArrayNode) {
            return $node->getChildren();
        }
        if ($prototype instanceof ArrayNode) {
            $keyNode = new ArrayNode($key, $node);
            $children = $prototype->getChildren();
            if ($prototype instanceof PrototypedArrayNode && $prototype->getKeyAttribute()) {
                $children = $this->getPrototypeChildren($prototype);
            }
            // add children
            foreach ($children as $childNode) {
                $keyNode->addChild($childNode);
            }
        } else {
            $keyNode = new ScalarNode($key, $node);
        }
        $info = 'Prototype';
        if (null !== $prototype->getInfo()) {
            $info .= ': ' . $prototype->getInfo();
        }
        $keyNode->setInfo($info);
        return [$key ?? '' => $keyNode];
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Config\Definition\Dumper;

use _ContaoManager\Symfony\Component\Config\Definition\ArrayNode;
use _ContaoManager\Symfony\Component\Config\Definition\BaseNode;
use _ContaoManager\Symfony\Component\Config\Definition\BooleanNode;
use _ContaoManager\Symfony\Component\Config\Definition\ConfigurationInterface;
use _ContaoManager\Symfony\Component\Config\Definition\EnumNode;
use _ContaoManager\Symfony\Component\Config\Definition\FloatNode;
use _ContaoManager\Symfony\Component\Config\Definition\IntegerNode;
use _ContaoManager\Symfony\Component\Config\Definition\NodeInterface;
use _ContaoManager\Symfony\Component\Config\Definition\PrototypedArrayNode;
use _ContaoManager\Symfony\Component\Config\Definition\ScalarNode;
/**
 * Dumps an XML reference configuration for the given configuration/node instance.
 *
 * @author Wouter J <waldio.webdesign@gmail.com>
 */
class XmlReferenceDumper
{
    private ?string $reference = null;
    /**
     * @return string
     */
    public function dump(ConfigurationInterface $configuration, ?string $namespace = null)
    {
        return $this->dumpNode($configuration->getConfigTreeBuilder()->buildTree(), $namespace);
    }
    /**
     * @return string
     */
    public function dumpNode(NodeInterface $node, ?string $namespace = null)
    {
        $this->reference = '';
        $this->writeNode($node, 0, \true, $namespace);
        $ref = $this->reference;
        $this->reference = null;
        return $ref;
    }
    private function writeNode(NodeInterface $node, int $depth = 0, bool $root = \false, ?string $namespace = null): void
    {
        $rootName = $root ? 'config' : $node->getName();
        $rootNamespace = $namespace ?: ($root ? 'http://example.org/schema/dic/' . $node->getName() : null);
        // xml remapping
        if ($node->getParent()) {
            $remapping = array_filter($node->getParent()->getXmlRemappings(), fn(array $mapping) => $rootName === $mapping[1]);
            if (\count($remapping)) {
                [$singular] = current($remapping);
                $rootName = $singular;
            }
        }
        $rootName = str_replace('_', '-', $rootName);
        $rootAttributes = [];
        $rootAttributeComments = [];
        $rootChildren = [];
        $rootComments = [];
        if ($node instanceof ArrayNode) {
            $children = $node->getChildren();
            // comments about the root node
            if ($rootInfo = $node->getInfo()) {
                $rootComments[] = $rootInfo;
            }
            if ($rootNamespace) {
                $rootComments[] = 'Namespace: ' . $rootNamespace;
            }
            // render prototyped nodes
            if ($node instanceof PrototypedArrayNode) {
                $prototype = $node->getPrototype();
                $info = 'prototype';
                if (null !== $prototype->getInfo()) {
                    $info .= ': ' . $prototype->getInfo();
                }
                array_unshift($rootComments, $info);
                if ($key = $node->getKeyAttribute()) {
                    $rootAttributes[$key] = str_replace('-', ' ', $rootName) . ' ' . $key;
                }
                if ($prototype instanceof PrototypedArrayNode) {
                    $prototype->setName($key ?? '');
                    $children = [$key => $prototype];
                } elseif ($prototype instanceof ArrayNode) {
                    $children = $prototype->getChildren();
                } else if ($prototype->hasDefaultValue()) {
                    $prototypeValue = $prototype->getDefaultValue();
                } else {
                    $prototypeValue = match ($prototype::class) {
                        ScalarNode::class => 'scalar value',
                        FloatNode::class, IntegerNode::class => 'numeric value',
                        BooleanNode::class => 'true|false',
                        EnumNode::class => $prototype->getPermissibleValues('|'),
                        default => 'value',
                    };
                }
            }
            // get attributes and elements
            foreach ($children as $child) {
                if ($child instanceof ArrayNode) {
                    // get elements
                    $rootChildren[] = $child;
                    continue;
                }
                // get attributes
                // metadata
                $name = str_replace('_', '-', $child->getName());
                $value = '%%%%not_defined%%%%';
                // use a string which isn't used in the normal world
                // comments
                $comments = [];
                if ($child instanceof BaseNode && $info = $child->getInfo()) {
                    $comments[] = $info;
                }
                if ($child instanceof BaseNode && $example = $child->getExample()) {
                    $comments[] = 'Example: ' . (\is_array($example) ? implode(', ', $example) : $example);
                }
                if ($child->isRequired()) {
                    $comments[] = 'Required';
                }
                if ($child instanceof BaseNode && $child->isDeprecated()) {
                    $deprecation = $child->getDeprecation($child->getName(), $node->getPath());
                    $comments[] = \sprintf('Deprecated (%s)', ($deprecation['package'] || $deprecation['version'] ? "Since {$deprecation['package']} {$deprecation['version']}: " : '') . $deprecation['message']);
                }
                if ($child instanceof EnumNode) {
                    $comments[] = 'One of ' . $child->getPermissibleValues('; ');
                }
                if (\count($comments)) {
                    $rootAttributeComments[$name] = implode(";\n", $comments);
                }
                // default values
                if ($child->hasDefaultValue()) {
                    $value = $child->getDefaultValue();
                }
                // append attribute
                $rootAttributes[$name] = $value;
            }
        }
        // render comments
        // root node comment
        if (\count($rootComments)) {
            foreach ($rootComments as $comment) {
                $this->writeLine('<!-- ' . $comment . ' -->', $depth);
            }
        }
        // attribute comments
        if (\count($rootAttributeComments)) {
            foreach ($rootAttributeComments as $attrName => $comment) {
                $commentDepth = $depth + 4 + \strlen($attrName) + 2;
                $commentLines = explode("\n", $comment);
                $multiline = \count($commentLines) > 1;
                $comment = implode(\PHP_EOL . str_repeat(' ', $commentDepth), $commentLines);
                if ($multiline) {
                    $this->writeLine('<!--', $depth);
                    $this->writeLine($attrName . ': ' . $comment, $depth + 4);
                    $this->writeLine('-->', $depth);
                } else {
                    $this->writeLine('<!-- ' . $attrName . ': ' . $comment . ' -->', $depth);
                }
            }
        }
        // render start tag + attributes
        $rootIsVariablePrototype = isset($prototypeValue);
        $rootIsEmptyTag = 0 === \count($rootChildren) && !$rootIsVariablePrototype;
        $rootOpenTag = '<' . $rootName;
        if (1 >= $attributesCount = \count($rootAttributes)) {
            if (1 === $attributesCount) {
                $rootOpenTag .= \sprintf(' %s="%s"', current(array_keys($rootAttributes)), $this->writeValue(current($rootAttributes)));
            }
            $rootOpenTag .= $rootIsEmptyTag ? ' />' : '>';
            if ($rootIsVariablePrototype) {
                $rootOpenTag .= $prototypeValue . '</' . $rootName . '>';
            }
            $this->writeLine($rootOpenTag, $depth);
        } else {
            $this->writeLine($rootOpenTag, $depth);
            $i = 1;
            foreach ($rootAttributes as $attrName => $attrValue) {
                $attr = \sprintf('%s="%s"', $attrName, $this->writeValue($attrValue));
                $this->writeLine($attr, $depth + 4);
                if ($attributesCount === $i++) {
                    $this->writeLine($rootIsEmptyTag ? '/>' : '>', $depth);
                    if ($rootIsVariablePrototype) {
                        $rootOpenTag .= $prototypeValue . '</' . $rootName . '>';
                    }
                }
            }
        }
        // render children tags
        foreach ($rootChildren as $child) {
            $this->writeLine('');
            $this->writeNode($child, $depth + 4);
        }
        // render end tag
        if (!$rootIsEmptyTag && !$rootIsVariablePrototype) {
            $this->writeLine('');
            $rootEndTag = '</' . $rootName . '>';
            $this->writeLine($rootEndTag, $depth);
        }
    }
    /**
     * Outputs a single config reference line.
     */
    private function writeLine(string $text, int $indent = 0): void
    {
        $indent = \strlen($text) + $indent;
        $format = '%' . $indent . 's';
        $this->reference .= \sprintf($format, $text) . \PHP_EOL;
    }
    /**
     * Renders the string conversion of the value.
     */
    private function writeValue(mixed $value): string
    {
        if ('%%%%not_defined%%%%' === $value) {
            return '';
        }
        if (\is_string($value) || is_numeric($value)) {
            return $value;
        }
        if (\false === $value) {
            return 'false';
        }
        if (\true === $value) {
            return 'true';
        }
        if (null === $value) {
            return 'null';
        }
        if (empty($value)) {
            return '';
        }
        if (\is_array($value)) {
            return implode(',', $value);
        }
        return '';
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Config\Resource;

/**
 * Interface for Resources that can check for freshness autonomously,
 * without special support from external services.
 *
 * @author Matthias Pigulla <mp@webfactory.de>
 */
interface SelfCheckingResourceInterface extends ResourceInterface
{
    /**
     * Returns true if the resource has not been updated since the given timestamp.
     *
     * @param int $timestamp The last time the resource was loaded
     */
    public function isFresh(int $timestamp): bool;
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Config\Resource;

/**
 * FileResource represents a resource stored on the filesystem.
 *
 * The resource can be a file or a directory.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 *
 * @final
 */
class FileResource implements SelfCheckingResourceInterface
{
    private string $resource;
    /**
     * @param string $resource The file path to the resource
     *
     * @throws \InvalidArgumentException
     */
    public function __construct(string $resource)
    {
        $resolvedResource = realpath($resource) ?: (file_exists($resource) ? $resource : \false);
        if (\false === $resolvedResource) {
            throw new \InvalidArgumentException(\sprintf('The file "%s" does not exist.', $resource));
        }
        $this->resource = $resolvedResource;
    }
    public function __toString(): string
    {
        return $this->resource;
    }
    /**
     * Returns the canonicalized, absolute path to the resource.
     */
    public function getResource(): string
    {
        return $this->resource;
    }
    public function isFresh(int $timestamp): bool
    {
        return \false !== ($filemtime = @filemtime($this->resource)) && $filemtime <= $timestamp;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Config\Resource;

use _ContaoManager\Symfony\Component\EventDispatcher\EventSubscriberInterface;
use _ContaoManager\Symfony\Component\Form\FormTypeExtensionInterface;
use _ContaoManager\Symfony\Component\Messenger\Handler\MessageSubscriberInterface;
use _ContaoManager\Symfony\Contracts\Service\ServiceSubscriberInterface;
/**
 * @author Nicolas Grekas <p@tchwork.com>
 *
 * @final
 */
class ReflectionClassResource implements SelfCheckingResourceInterface
{
    private array $files = [];
    private string $className;
    private \ReflectionClass $classReflector;
    private array $excludedVendors = [];
    private string $hash;
    public function __construct(\ReflectionClass $classReflector, array $excludedVendors = [])
    {
        $this->className = $classReflector->name;
        $this->classReflector = $classReflector;
        $this->excludedVendors = $excludedVendors;
    }
    public function isFresh(int $timestamp): bool
    {
        if (!isset($this->hash)) {
            $this->hash = $this->computeHash();
            $this->loadFiles($this->classReflector);
        }
        foreach ($this->files as $file => $v) {
            if (\false === $filemtime = @filemtime($file)) {
                return \false;
            }
            if ($filemtime > $timestamp) {
                return $this->hash === $this->computeHash();
            }
        }
        return \true;
    }
    public function __toString(): string
    {
        return 'reflection.' . $this->className;
    }
    public function __serialize(): array
    {
        if (!isset($this->hash)) {
            $this->hash = $this->computeHash();
            $this->loadFiles($this->classReflector);
        }
        return ['files' => $this->files, 'className' => $this->className, 'excludedVendors' => $this->excludedVendors, 'hash' => $this->hash];
    }
    private function loadFiles(\ReflectionClass $class): void
    {
        foreach ($class->getInterfaces() as $v) {
            $this->loadFiles($v);
        }
        do {
            $file = $class->getFileName();
            if (\false !== $file && is_file($file)) {
                foreach ($this->excludedVendors as $vendor) {
                    if (str_starts_with($file, $vendor) && \false !== strpbrk(substr($file, \strlen($vendor), 1), '/' . \DIRECTORY_SEPARATOR)) {
                        $file = \false;
                        break;
                    }
                }
                if ($file) {
                    $this->files[$file] = null;
                }
            }
            foreach ($class->getTraits() as $v) {
                $this->loadFiles($v);
            }
        } while ($class = $class->getParentClass());
    }
    private function computeHash(): string
    {
        try {
            $this->classReflector ??= new \ReflectionClass($this->className);
        } catch (\ReflectionException) {
            // the class does not exist anymore
            return \false;
        }
        $hash = hash_init('xxh128');
        foreach ($this->generateSignature($this->classReflector) as $info) {
            hash_update($hash, $info);
        }
        return hash_final($hash);
    }
    private function generateSignature(\ReflectionClass $class): iterable
    {
        $attributes = [];
        foreach ($class->getAttributes() as $a) {
            $attributes[] = [$a->getName(), (string) $a];
        }
        yield print_r($attributes, \true);
        $attributes = [];
        yield $class->getDocComment() ?: '';
        yield (int) $class->isFinal();
        yield (int) $class->isAbstract();
        if ($class->isTrait()) {
            yield print_r(class_uses($class->name), \true);
        } else {
            yield print_r(class_parents($class->name), \true);
            yield print_r(class_implements($class->name), \true);
            yield print_r($class->getConstants(), \true);
        }
        foreach ($class->getReflectionConstants() as $constant) {
            foreach ($constant->getAttributes() as $a) {
                $attributes[] = [$a->getName(), (string) $a];
            }
            yield $constant->name . print_r($attributes, \true);
            $attributes = [];
        }
        if (!$class->isInterface()) {
            $defaults = $class->getDefaultProperties();
            foreach ($class->getProperties(\ReflectionProperty::IS_PUBLIC | \ReflectionProperty::IS_PROTECTED) as $p) {
                foreach ($p->getAttributes() as $a) {
                    $attributes[] = [$a->getName(), (string) $a];
                }
                yield print_r($attributes, \true);
                $attributes = [];
                yield $p->getDocComment() ?: '';
                yield $p->isDefault() ? '<default>' : '';
                yield $p->isPublic() ? 'public' : 'protected';
                yield $p->isStatic() ? 'static' : '';
                yield '$' . $p->name;
                yield print_r(isset($defaults[$p->name]) && !\is_object($defaults[$p->name]) ? $defaults[$p->name] : null, \true);
            }
        }
        foreach ($class->getMethods(\ReflectionMethod::IS_PUBLIC | \ReflectionMethod::IS_PROTECTED) as $m) {
            foreach ($m->getAttributes() as $a) {
                $attributes[] = [$a->getName(), (string) $a];
            }
            yield print_r($attributes, \true);
            $attributes = [];
            $defaults = [];
            foreach ($m->getParameters() as $p) {
                foreach ($p->getAttributes() as $a) {
                    $attributes[] = [$a->getName(), (string) $a];
                }
                yield print_r($attributes, \true);
                $attributes = [];
                if (!$p->isDefaultValueAvailable()) {
                    $defaults[$p->name] = null;
                    continue;
                }
                $defaults[$p->name] = (string) $p;
            }
            yield preg_replace('/^  @@.*/m', '', $m);
            yield print_r($defaults, \true);
        }
        if ($class->isAbstract() || $class->isInterface() || $class->isTrait()) {
            return;
        }
        if (interface_exists(EventSubscriberInterface::class, \false) && $class->isSubclassOf(EventSubscriberInterface::class)) {
            yield EventSubscriberInterface::class;
            yield print_r($class->name::getSubscribedEvents(), \true);
        }
        if (interface_exists(MessageSubscriberInterface::class, \false) && $class->isSubclassOf(MessageSubscriberInterface::class)) {
            yield MessageSubscriberInterface::class;
            foreach ($class->name::getHandledMessages() as $key => $value) {
                yield $key . print_r($value, \true);
            }
        }
        if (interface_exists(ServiceSubscriberInterface::class, \false) && $class->isSubclassOf(ServiceSubscriberInterface::class)) {
            yield ServiceSubscriberInterface::class;
            yield print_r($class->name::getSubscribedServices(), \true);
        }
        if (interface_exists(FormTypeExtensionInterface::class, \false) && $class->isSubclassOf(FormTypeExtensionInterface::class)) {
            yield FormTypeExtensionInterface::class;
            foreach ($class->name::getExtendedTypes() as $key => $value) {
                yield $key . print_r($value, \true);
            }
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Config\Resource;

use _ContaoManager\Symfony\Component\Config\ResourceCheckerInterface;
/**
 * Resource checker for instances of SelfCheckingResourceInterface.
 *
 * As these resources perform the actual check themselves, we can provide
 * this class as a standard way of validating them.
 *
 * @author Matthias Pigulla <mp@webfactory.de>
 */
class SelfCheckingResourceChecker implements ResourceCheckerInterface
{
    // Common shared cache, because this checker can be used in different
    // situations. For example, when using the full stack framework, the router
    // and the container have their own cache. But they may check the very same
    // resources
    private static array $cache = [];
    public function supports(ResourceInterface $metadata): bool
    {
        return $metadata instanceof SelfCheckingResourceInterface;
    }
    /**
     * @param SelfCheckingResourceInterface $resource
     */
    public function isFresh(ResourceInterface $resource, int $timestamp): bool
    {
        $key = "{$resource}:{$timestamp}";
        return self::$cache[$key] ??= $resource->isFresh($timestamp);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Config\Resource;

/**
 * ComposerResource tracks the PHP version and Composer dependencies.
 *
 * @author Nicolas Grekas <p@tchwork.com>
 *
 * @final
 */
class ComposerResource implements SelfCheckingResourceInterface
{
    private array $vendors;
    private static array $runtimeVendors;
    public function __construct()
    {
        self::refresh();
        $this->vendors = self::$runtimeVendors;
    }
    public function getVendors(): array
    {
        return array_keys($this->vendors);
    }
    public function __toString(): string
    {
        return __CLASS__;
    }
    public function isFresh(int $timestamp): bool
    {
        self::refresh();
        return array_values(self::$runtimeVendors) === array_values($this->vendors);
    }
    private static function refresh(): void
    {
        self::$runtimeVendors = [];
        foreach (get_declared_classes() as $class) {
            if ('C' === $class[0] && str_starts_with($class, 'ComposerAutoloaderInit')) {
                $r = new \ReflectionClass($class);
                $v = \dirname($r->getFileName(), 2);
                if (is_file($v . '/composer/installed.json')) {
                    self::$runtimeVendors[$v] = @filemtime($v . '/composer/installed.json');
                }
            }
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Config\Resource;

/**
 * FileExistenceResource represents a resource stored on the filesystem.
 * Freshness is only evaluated against resource creation or deletion.
 *
 * The resource can be a file or a directory.
 *
 * @author Charles-Henri Bruyand <charleshenri.bruyand@gmail.com>
 *
 * @final
 */
class FileExistenceResource implements SelfCheckingResourceInterface
{
    private string $resource;
    private bool $exists;
    /**
     * @param string $resource The file path to the resource
     */
    public function __construct(string $resource)
    {
        $this->resource = $resource;
        $this->exists = file_exists($resource);
    }
    public function __toString(): string
    {
        return 'existence.' . $this->resource;
    }
    public function getResource(): string
    {
        return $this->resource;
    }
    public function isFresh(int $timestamp): bool
    {
        return file_exists($this->resource) === $this->exists;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Config\Resource;

/**
 * ResourceInterface is the interface that must be implemented by all Resource classes.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
interface ResourceInterface extends \Stringable
{
    /**
     * Returns a string representation of the Resource.
     *
     * This method is necessary to allow for resource de-duplication, for example by means
     * of array_unique(). The string returned need not have a particular meaning, but has
     * to be identical for different ResourceInterface instances referring to the same
     * resource; and it should be unlikely to collide with that of other, unrelated
     * resource instances.
     */
    public function __toString(): string;
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Config\Resource;

/**
 * ClassExistenceResource represents a class existence.
 * Freshness is only evaluated against resource existence.
 *
 * The resource must be a fully-qualified class name.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 *
 * @final
 */
class ClassExistenceResource implements SelfCheckingResourceInterface
{
    private string $resource;
    private ?array $exists = null;
    private static int $autoloadLevel = 0;
    private static ?string $autoloadedClass = null;
    private static array $existsCache = [];
    /**
     * @param string    $resource The fully-qualified class name
     * @param bool|null $exists   Boolean when the existence check has already been done
     */
    public function __construct(string $resource, ?bool $exists = null)
    {
        $this->resource = $resource;
        if (null !== $exists) {
            $this->exists = [$exists, null];
        }
    }
    public function __toString(): string
    {
        return $this->resource;
    }
    public function getResource(): string
    {
        return $this->resource;
    }
    /**
     * @throws \ReflectionException when a parent class/interface/trait is not found
     */
    public function isFresh(int $timestamp): bool
    {
        $loaded = class_exists($this->resource, \false) || interface_exists($this->resource, \false) || trait_exists($this->resource, \false);
        if (null !== $exists =& self::$existsCache[$this->resource]) {
            if ($loaded) {
                $exists = [\true, null];
            } elseif (0 >= $timestamp && !$exists[0] && null !== $exists[1]) {
                throw new \ReflectionException($exists[1]);
            }
        } elseif ([\false, null] === $exists = [$loaded, null]) {
            if (!self::$autoloadLevel++) {
                spl_autoload_register(__CLASS__ . '::throwOnRequiredClass');
            }
            $autoloadedClass = self::$autoloadedClass;
            self::$autoloadedClass = ltrim($this->resource, '\\');
            try {
                $exists[0] = class_exists($this->resource) || interface_exists($this->resource, \false) || trait_exists($this->resource, \false);
            } catch (\Exception $e) {
                $exists[1] = $e->getMessage();
                try {
                    self::throwOnRequiredClass($this->resource, $e);
                } catch (\ReflectionException $e) {
                    if (0 >= $timestamp) {
                        throw $e;
                    }
                }
            } catch (\Throwable $e) {
                $exists[1] = $e->getMessage();
                throw $e;
            } finally {
                self::$autoloadedClass = $autoloadedClass;
                if (!--self::$autoloadLevel) {
                    spl_autoload_unregister(__CLASS__ . '::throwOnRequiredClass');
                }
            }
        }
        $this->exists ??= $exists;
        return $this->exists[0] xor !$exists[0];
    }
    public function __serialize(): array
    {
        if (null === $this->exists) {
            $this->isFresh(0);
        }
        return ['resource' => $this->resource, 'exists' => $this->exists];
    }
    public function __unserialize(array $data): void
    {
        $this->resource = array_shift($data);
        $this->exists = array_shift($data);
        if (\is_bool($this->exists)) {
            $this->exists = [$this->exists, null];
        }
    }
    /**
     * Throws a reflection exception when the passed class does not exist but is required.
     *
     * A class is considered "not required" when it's loaded as part of a "class_exists" or similar check.
     *
     * This function can be used as an autoload function to throw a reflection
     * exception if the class was not found by previous autoload functions.
     *
     * A previous exception can be passed. In this case, the class is considered as being
     * required totally, so if it doesn't exist, a reflection exception is always thrown.
     * If it exists, the previous exception is rethrown.
     *
     * @throws \ReflectionException
     *
     * @internal
     */
    public static function throwOnRequiredClass(string $class, ?\Exception $previous = null): void
    {
        // If the passed class is the resource being checked, we shouldn't throw.
        if (null === $previous && self::$autoloadedClass === $class) {
            return;
        }
        if (class_exists($class, \false) || interface_exists($class, \false) || trait_exists($class, \false)) {
            if (null !== $previous) {
                throw $previous;
            }
            return;
        }
        if ($previous instanceof \ReflectionException) {
            throw $previous;
        }
        $message = \sprintf('Class "%s" not found.', $class);
        if ($class !== (self::$autoloadedClass ?? $class)) {
            $message = substr_replace($message, \sprintf(' while loading "%s"', self::$autoloadedClass), -1, 0);
        }
        if (null !== $previous) {
            $message = $previous->getMessage();
        }
        $e = new \ReflectionException($message, 0, $previous);
        if (null !== $previous) {
            throw $e;
        }
        $trace = debug_backtrace();
        $autoloadFrame = ['function' => 'spl_autoload_call', 'args' => [$class]];
        if (isset($trace[1])) {
            $callerFrame = $trace[1];
            $i = 2;
        } elseif (\false !== $i = array_search($autoloadFrame, $trace, \true)) {
            $callerFrame = $trace[++$i];
        } else {
            throw $e;
        }
        if (isset($callerFrame['function']) && !isset($callerFrame['class'])) {
            switch ($callerFrame['function']) {
                case 'get_class_methods':
                case 'get_class_vars':
                case 'get_parent_class':
                case 'is_a':
                case 'is_subclass_of':
                case 'class_exists':
                case 'class_implements':
                case 'class_parents':
                case 'trait_exists':
                case 'defined':
                case 'interface_exists':
                case 'method_exists':
                case 'property_exists':
                case 'is_callable':
                    return;
            }
            $props = ['file' => $callerFrame['file'] ?? null, 'line' => $callerFrame['line'] ?? null, 'trace' => \array_slice($trace, 1 + $i)];
            foreach ($props as $p => $v) {
                if (null !== $v) {
                    $r = new \ReflectionProperty(\Exception::class, $p);
                    $r->setValue($e, $v);
                }
            }
        }
        throw $e;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Config\Resource;

/**
 * DirectoryResource represents a resources stored in a subdirectory tree.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 *
 * @final
 */
class DirectoryResource implements SelfCheckingResourceInterface
{
    private string $resource;
    private ?string $pattern;
    /**
     * @param string      $resource The file path to the resource
     * @param string|null $pattern  A pattern to restrict monitored files
     *
     * @throws \InvalidArgumentException
     */
    public function __construct(string $resource, ?string $pattern = null)
    {
        $resolvedResource = realpath($resource) ?: (file_exists($resource) ? $resource : \false);
        $this->pattern = $pattern;
        if (\false === $resolvedResource || !is_dir($resolvedResource)) {
            throw new \InvalidArgumentException(\sprintf('The directory "%s" does not exist.', $resource));
        }
        $this->resource = $resolvedResource;
    }
    public function __toString(): string
    {
        return hash('xxh128', serialize([$this->resource, $this->pattern]));
    }
    public function getResource(): string
    {
        return $this->resource;
    }
    public function getPattern(): ?string
    {
        return $this->pattern;
    }
    public function isFresh(int $timestamp): bool
    {
        if (!is_dir($this->resource)) {
            return \false;
        }
        if ($timestamp < filemtime($this->resource)) {
            return \false;
        }
        foreach (new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($this->resource), \RecursiveIteratorIterator::SELF_FIRST) as $file) {
            // if regex filtering is enabled only check matching files
            if ($this->pattern && $file->isFile() && !preg_match($this->pattern, $file->getBasename())) {
                continue;
            }
            // always monitor directories for changes, except the .. entries
            // (otherwise deleted files wouldn't get detected)
            if ($file->isDir() && str_ends_with($file, '/..')) {
                continue;
            }
            // for broken links
            try {
                $fileMTime = $file->getMTime();
            } catch (\RuntimeException) {
                continue;
            }
            // early return if a file's mtime exceeds the passed timestamp
            if ($timestamp < $fileMTime) {
                return \false;
            }
        }
        return \true;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Config\Resource;

use _ContaoManager\Symfony\Component\Finder\Finder;
use _ContaoManager\Symfony\Component\Finder\Glob;
/**
 * GlobResource represents a set of resources stored on the filesystem.
 *
 * Only existence/removal is tracked (not mtimes.)
 *
 * @author Nicolas Grekas <p@tchwork.com>
 *
 * @final
 *
 * @implements \IteratorAggregate<string, \SplFileInfo>
 */
class GlobResource implements \IteratorAggregate, SelfCheckingResourceInterface
{
    private string $prefix;
    private string $pattern;
    private bool $recursive;
    private string $hash;
    private bool $forExclusion;
    private array $excludedPrefixes;
    private int $globBrace;
    /**
     * @param string $prefix    A directory prefix
     * @param string $pattern   A glob pattern
     * @param bool   $recursive Whether directories should be scanned recursively or not
     *
     * @throws \InvalidArgumentException
     */
    public function __construct(string $prefix, string $pattern, bool $recursive, bool $forExclusion = \false, array $excludedPrefixes = [])
    {
        ksort($excludedPrefixes);
        $resolvedPrefix = realpath($prefix) ?: (file_exists($prefix) ? $prefix : \false);
        $this->pattern = $pattern;
        $this->recursive = $recursive;
        $this->forExclusion = $forExclusion;
        $this->excludedPrefixes = $excludedPrefixes;
        $this->globBrace = \defined('GLOB_BRACE') ? \GLOB_BRACE : 0;
        if (\false === $resolvedPrefix) {
            throw new \InvalidArgumentException(\sprintf('The path "%s" does not exist.', $prefix));
        }
        $this->prefix = $resolvedPrefix;
    }
    public function getPrefix(): string
    {
        return $this->prefix;
    }
    public function __toString(): string
    {
        return 'glob.' . $this->prefix . (int) $this->recursive . $this->pattern . (int) $this->forExclusion . implode("\x00", $this->excludedPrefixes);
    }
    public function isFresh(int $timestamp): bool
    {
        $hash = $this->computeHash();
        $this->hash ??= $hash;
        return $this->hash === $hash;
    }
    public function __serialize(): array
    {
        $this->hash ??= $this->computeHash();
        return ['prefix' => $this->prefix, 'pattern' => $this->pattern, 'recursive' => $this->recursive, 'hash' => $this->hash, 'forExclusion' => $this->forExclusion, 'excludedPrefixes' => $this->excludedPrefixes];
    }
    public function __unserialize(array $data): void
    {
        $this->prefix = array_shift($data);
        $this->pattern = array_shift($data);
        $this->recursive = array_shift($data);
        $this->hash = array_shift($data);
        $this->forExclusion = array_shift($data);
        $this->excludedPrefixes = array_shift($data);
        $this->globBrace = \defined('GLOB_BRACE') ? \GLOB_BRACE : 0;
    }
    public function getIterator(): \Traversable
    {
        if (!$this->recursive && '' === $this->pattern || !file_exists($this->prefix)) {
            return;
        }
        if (is_file($prefix = str_replace('\\', '/', $this->prefix))) {
            $prefix = \dirname($prefix);
            $pattern = basename($prefix) . $this->pattern;
        } else {
            $pattern = $this->pattern;
        }
        if (class_exists(Finder::class)) {
            $regex = Glob::toRegex($pattern);
            if ($this->recursive) {
                $regex = substr_replace($regex, str_ends_with($pattern, '/') ? '' : '(/|$)', -2, 1);
            }
        } else {
            $regex = null;
        }
        $prefixLen = \strlen($prefix);
        $paths = null;
        if ('' === $this->pattern && is_file($this->prefix)) {
            $paths = [$this->prefix => null];
        } elseif (!str_starts_with($this->prefix, 'phar://') && (null !== $regex || !str_contains($this->pattern, '/**/'))) {
            if (!str_contains($this->pattern, '/**/') && ($this->globBrace || !str_contains($this->pattern, '{'))) {
                $paths = array_fill_keys(glob($this->prefix . $this->pattern, \GLOB_NOSORT | $this->globBrace), null);
            } elseif (!str_contains($this->pattern, '\\') || !preg_match('/\\\\[,{}]/', $this->pattern)) {
                $paths = [];
                foreach ($this->expandGlob($this->pattern) as $p) {
                    if (\false !== $i = strpos($p, '/**/')) {
                        $p = substr_replace($p, '/*', $i);
                    }
                    $paths += array_fill_keys(glob($this->prefix . $p, \GLOB_NOSORT), \false !== $i ? $regex : null);
                }
            }
        }
        if (null !== $paths) {
            uksort($paths, 'strnatcmp');
            foreach ($paths as $path => $regex) {
                if ($this->excludedPrefixes) {
                    $normalizedPath = str_replace('\\', '/', $path);
                    do {
                        if (isset($this->excludedPrefixes[$dirPath = $normalizedPath])) {
                            continue 2;
                        }
                    } while ($prefix !== $dirPath && $dirPath !== $normalizedPath = \dirname($dirPath));
                }
                if ((null === $regex || preg_match($regex, substr(str_replace('\\', '/', $path), $prefixLen))) && is_file($path)) {
                    yield $path => new \SplFileInfo($path);
                }
                if (!is_dir($path)) {
                    continue;
                }
                if ($this->forExclusion && (null === $regex || preg_match($regex, substr(str_replace('\\', '/', $path), $prefixLen)))) {
                    yield $path => new \SplFileInfo($path);
                    continue;
                }
                if (!($this->recursive || null !== $regex) || isset($this->excludedPrefixes[str_replace('\\', '/', $path)])) {
                    continue;
                }
                $files = iterator_to_array(new \RecursiveIteratorIterator(new \RecursiveCallbackFilterIterator(new \RecursiveDirectoryIterator($path, \FilesystemIterator::SKIP_DOTS | \FilesystemIterator::FOLLOW_SYMLINKS), fn(\SplFileInfo $file, $path) => !isset($this->excludedPrefixes[$path = str_replace('\\', '/', $path)]) && (null === $regex || preg_match($regex, substr($path, $prefixLen)) || $file->isDir()) && '.' !== $file->getBasename()[0]), \RecursiveIteratorIterator::LEAVES_ONLY));
                uksort($files, 'strnatcmp');
                foreach ($files as $path => $info) {
                    if ($info->isFile()) {
                        yield $path => $info;
                    }
                }
            }
            return;
        }
        if (!class_exists(Finder::class)) {
            throw new \LogicException('Extended glob patterns cannot be used as the Finder component is not installed. Try running "composer require symfony/finder".');
        }
        yield from (new Finder())->followLinks()->filter(function (\SplFileInfo $info) use ($regex, $prefixLen, $prefix) {
            $normalizedPath = str_replace('\\', '/', $info->getPathname());
            if (!preg_match($regex, substr($normalizedPath, $prefixLen)) || !$info->isFile()) {
                return \false;
            }
            if ($this->excludedPrefixes) {
                do {
                    if (isset($this->excludedPrefixes[$dirPath = $normalizedPath])) {
                        return \false;
                    }
                } while ($prefix !== $dirPath && $dirPath !== $normalizedPath = \dirname($dirPath));
            }
        })->sortByName()->in($prefix);
    }
    private function computeHash(): string
    {
        $hash = hash_init('xxh128');
        foreach ($this->getIterator() as $path => $info) {
            hash_update($hash, $path . "\n");
        }
        return hash_final($hash);
    }
    private function expandGlob(string $pattern): array
    {
        $segments = preg_split('/\{([^{}]*+)\}/', $pattern, -1, \PREG_SPLIT_DELIM_CAPTURE);
        $paths = [$segments[0]];
        $patterns = [];
        for ($i = 1; $i < \count($segments); $i += 2) {
            $patterns = [];
            foreach (explode(',', $segments[$i]) as $s) {
                foreach ($paths as $p) {
                    $patterns[] = $p . $s . $segments[1 + $i];
                }
            }
            $paths = $patterns;
        }
        $j = 0;
        foreach ($patterns as $i => $p) {
            if (str_contains($p, '{')) {
                $p = $this->expandGlob($p);
                array_splice($paths, $i + $j, 1, $p);
                $j += \count($p) - 1;
            }
        }
        return $paths;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Config\Builder;

/**
 * A ConfigBuilder provides helper methods to build a large complex array.
 *
 * @author Tobias Nyholm <tobias.nyholm@gmail.com>
 */
interface ConfigBuilderInterface
{
    /**
     * Gets all configuration represented as an array.
     */
    public function toArray(): array;
    /**
     * Gets the alias for the extension which config we are building.
     */
    public function getExtensionAlias(): string;
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Config\Builder;

/**
 * Represents a method when building classes.
 *
 * @internal
 *
 * @author Tobias Nyholm <tobias.nyholm@gmail.com>
 */
class Method
{
    private string $content;
    public function __construct(string $content)
    {
        $this->content = $content;
    }
    public function getContent(): string
    {
        return $this->content;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Config\Builder;

/**
 * Build PHP classes to generate config.
 *
 * @internal
 *
 * @author Tobias Nyholm <tobias.nyholm@gmail.com>
 */
class ClassBuilder
{
    private string $namespace;
    private string $name;
    /** @var Property[] */
    private array $properties = [];
    /** @var Method[] */
    private array $methods = [];
    private array $require = [];
    private array $use = [];
    private array $implements = [];
    private bool $allowExtraKeys = \false;
    public function __construct(string $namespace, string $name)
    {
        $this->namespace = $namespace;
        $this->name = ucfirst($this->camelCase($name)) . 'Config';
    }
    public function getDirectory(): string
    {
        return str_replace('\\', \DIRECTORY_SEPARATOR, $this->namespace);
    }
    public function getFilename(): string
    {
        return $this->name . '.php';
    }
    public function build(): string
    {
        $rootPath = explode(\DIRECTORY_SEPARATOR, $this->getDirectory());
        $require = '';
        foreach ($this->require as $class) {
            // figure out relative path.
            $path = explode(\DIRECTORY_SEPARATOR, $class->getDirectory());
            $path[] = $class->getFilename();
            foreach ($rootPath as $key => $value) {
                if ($path[$key] !== $value) {
                    break;
                }
                unset($path[$key]);
            }
            $require .= \sprintf('require_once __DIR__.\DIRECTORY_SEPARATOR.\'%s\';', implode('\'.\DIRECTORY_SEPARATOR.\'', $path)) . "\n";
        }
        $use = $require ? "\n" : '';
        foreach (array_keys($this->use) as $statement) {
            $use .= \sprintf('use %s;', $statement) . "\n";
        }
        $implements = [] === $this->implements ? '' : 'implements ' . implode(', ', $this->implements);
        $body = '';
        foreach ($this->properties as $property) {
            $body .= '    ' . $property->getContent() . "\n";
        }
        foreach ($this->methods as $method) {
            $lines = explode("\n", $method->getContent());
            foreach ($lines as $line) {
                $body .= ($line ? '    ' . $line : '') . "\n";
            }
        }
        $content = strtr('<?php

namespace NAMESPACE;

REQUIREUSE
/**
 * This class is automatically generated to help in creating a config.
 */
class CLASS IMPLEMENTS
{
BODY
}
', ['NAMESPACE' => $this->namespace, 'REQUIRE' => $require, 'USE' => $use, 'CLASS' => $this->getName(), 'IMPLEMENTS' => $implements, 'BODY' => $body]);
        return $content;
    }
    public function addRequire(self $class): void
    {
        $this->require[] = $class;
    }
    public function addUse(string $class): void
    {
        $this->use[$class] = \true;
    }
    public function addImplements(string $interface): void
    {
        $this->implements[] = '\\' . ltrim($interface, '\\');
    }
    public function addMethod(string $name, string $body, array $params = []): void
    {
        $this->methods[] = new Method(strtr($body, ['NAME' => $this->camelCase($name)] + $params));
    }
    public function addProperty(string $name, ?string $classType = null, ?string $defaultValue = null): Property
    {
        $property = new Property($name, '_' !== $name[0] ? $this->camelCase($name) : $name);
        if (null !== $classType) {
            $property->setType($classType);
        }
        $this->properties[] = $property;
        $defaultValue = null !== $defaultValue ? \sprintf(' = %s', $defaultValue) : '';
        $property->setContent(\sprintf('private $%s%s;', $property->getName(), $defaultValue));
        return $property;
    }
    public function getProperties(): array
    {
        return $this->properties;
    }
    private function camelCase(string $input): string
    {
        $output = lcfirst(str_replace(' ', '', ucwords(str_replace('_', ' ', $input))));
        return preg_replace('#\W#', '', $output);
    }
    public function getName(): string
    {
        return $this->name;
    }
    public function getNamespace(): string
    {
        return $this->namespace;
    }
    public function getFqcn(): string
    {
        return '\\' . $this->namespace . '\\' . $this->name;
    }
    public function setAllowExtraKeys(bool $allowExtraKeys): void
    {
        $this->allowExtraKeys = $allowExtraKeys;
    }
    public function shouldAllowExtraKeys(): bool
    {
        return $this->allowExtraKeys;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Config\Builder;

/**
 * Represents a property when building classes.
 *
 * @internal
 *
 * @author Tobias Nyholm <tobias.nyholm@gmail.com>
 */
class Property
{
    private string $name;
    private string $originalName;
    private bool $array = \false;
    private bool $scalarsAllowed = \false;
    private ?string $type = null;
    private ?string $content = null;
    public function __construct(string $originalName, string $name)
    {
        $this->name = $name;
        $this->originalName = $originalName;
    }
    public function getName(): string
    {
        return $this->name;
    }
    public function getOriginalName(): string
    {
        return $this->originalName;
    }
    public function setType(string $type): void
    {
        $this->array = \false;
        $this->type = $type;
        if (str_ends_with($type, '|scalar')) {
            $this->scalarsAllowed = \true;
            $this->type = $type = substr($type, 0, -7);
        }
        if (str_ends_with($type, '[]')) {
            $this->array = \true;
            $this->type = substr($type, 0, -2);
        }
    }
    public function getType(): ?string
    {
        return $this->type;
    }
    public function getContent(): ?string
    {
        return $this->content;
    }
    public function setContent(string $content): void
    {
        $this->content = $content;
    }
    public function isArray(): bool
    {
        return $this->array;
    }
    public function areScalarsAllowed(): bool
    {
        return $this->scalarsAllowed;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Config\Builder;

use _ContaoManager\Symfony\Component\Config\Definition\ConfigurationInterface;
/**
 * Generates ConfigBuilders to help create valid config.
 *
 * @author Tobias Nyholm <tobias.nyholm@gmail.com>
 */
interface ConfigBuilderGeneratorInterface
{
    /**
     * @return \Closure that will return the root config class
     */
    public function build(ConfigurationInterface $configuration): \Closure;
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Config\Builder;

use _ContaoManager\Symfony\Component\Config\Definition\ArrayNode;
use _ContaoManager\Symfony\Component\Config\Definition\BaseNode;
use _ContaoManager\Symfony\Component\Config\Definition\BooleanNode;
use _ContaoManager\Symfony\Component\Config\Definition\Builder\ExprBuilder;
use _ContaoManager\Symfony\Component\Config\Definition\ConfigurationInterface;
use _ContaoManager\Symfony\Component\Config\Definition\EnumNode;
use _ContaoManager\Symfony\Component\Config\Definition\Exception\InvalidConfigurationException;
use _ContaoManager\Symfony\Component\Config\Definition\FloatNode;
use _ContaoManager\Symfony\Component\Config\Definition\IntegerNode;
use _ContaoManager\Symfony\Component\Config\Definition\NodeInterface;
use _ContaoManager\Symfony\Component\Config\Definition\PrototypedArrayNode;
use _ContaoManager\Symfony\Component\Config\Definition\ScalarNode;
use _ContaoManager\Symfony\Component\Config\Definition\VariableNode;
use _ContaoManager\Symfony\Component\Config\Loader\ParamConfigurator;
/**
 * Generate ConfigBuilders to help create valid config.
 *
 * @author Tobias Nyholm <tobias.nyholm@gmail.com>
 */
class ConfigBuilderGenerator implements ConfigBuilderGeneratorInterface
{
    /**
     * @var ClassBuilder[]
     */
    private array $classes = [];
    private string $outputDir;
    public function __construct(string $outputDir)
    {
        $this->outputDir = $outputDir;
    }
    /**
     * @return \Closure that will return the root config class
     */
    public function build(ConfigurationInterface $configuration): \Closure
    {
        $this->classes = [];
        $rootNode = $configuration->getConfigTreeBuilder()->buildTree();
        $rootClass = new ClassBuilder('_ContaoManager\Symfony\Config', $rootNode->getName());
        $path = $this->getFullPath($rootClass);
        if (!is_file($path)) {
            // Generate the class if the file not exists
            $this->classes[] = $rootClass;
            $this->buildNode($rootNode, $rootClass, $this->getSubNamespace($rootClass));
            $rootClass->addImplements(ConfigBuilderInterface::class);
            $rootClass->addMethod('getExtensionAlias', '
public function NAME(): string
{
    return \'ALIAS\';
}', ['ALIAS' => $rootNode->getPath()]);
            $this->writeClasses();
        }
        return function () use ($path, $rootClass) {
            require_once $path;
            $className = $rootClass->getFqcn();
            return new $className();
        };
    }
    private function getFullPath(ClassBuilder $class): string
    {
        $directory = $this->outputDir . \DIRECTORY_SEPARATOR . $class->getDirectory();
        if (!is_dir($directory)) {
            @mkdir($directory, 0777, \true);
        }
        return $directory . \DIRECTORY_SEPARATOR . $class->getFilename();
    }
    private function writeClasses(): void
    {
        foreach ($this->classes as $class) {
            $this->buildConstructor($class);
            $this->buildToArray($class);
            if ($class->getProperties()) {
                $class->addProperty('_usedProperties', null, '[]');
            }
            $this->buildSetExtraKey($class);
            file_put_contents($this->getFullPath($class), $class->build());
        }
        $this->classes = [];
    }
    private function buildNode(NodeInterface $node, ClassBuilder $class, string $namespace): void
    {
        if (!$node instanceof ArrayNode) {
            throw new \LogicException('The node was expected to be an ArrayNode. This Configuration includes an edge case not supported yet.');
        }
        foreach ($node->getChildren() as $child) {
            match (\true) {
                $child instanceof ScalarNode => $this->handleScalarNode($child, $class),
                $child instanceof PrototypedArrayNode => $this->handlePrototypedArrayNode($child, $class, $namespace),
                $child instanceof VariableNode => $this->handleVariableNode($child, $class),
                $child instanceof ArrayNode => $this->handleArrayNode($child, $class, $namespace),
                default => throw new \RuntimeException(\sprintf('Unknown node "%s".', $child::class)),
            };
        }
    }
    private function handleArrayNode(ArrayNode $node, ClassBuilder $class, string $namespace): void
    {
        $childClass = new ClassBuilder($namespace, $node->getName());
        $childClass->setAllowExtraKeys($node->shouldIgnoreExtraKeys());
        $class->addRequire($childClass);
        $this->classes[] = $childClass;
        $nodeTypes = $this->getParameterTypes($node);
        $paramType = $this->getParamType($nodeTypes);
        $hasNormalizationClosures = $this->hasNormalizationClosures($node);
        $comment = $this->getComment($node);
        if ($hasNormalizationClosures && 'array' !== $paramType) {
            $comment = \sprintf(" * @template TValue of %s\n * @param TValue \$value\n%s", $paramType, $comment);
            $comment .= \sprintf(' * @return %s|$this' . "\n", $childClass->getFqcn());
            $comment .= \sprintf(' * @psalm-return (TValue is array ? %s : static)' . "\n ", $childClass->getFqcn());
        }
        if ('' !== $comment) {
            $comment = "/**\n{$comment}*/\n";
        }
        $property = $class->addProperty($node->getName(), $this->getType($childClass->getFqcn(), $hasNormalizationClosures));
        $body = $hasNormalizationClosures && 'array' !== $paramType ? '
COMMENTpublic function NAME(PARAM_TYPE $value = []): CLASS|static
{
    if (!\is_array($value)) {
        $this->_usedProperties[\'PROPERTY\'] = true;
        $this->PROPERTY = $value;

        return $this;
    }

    if (!$this->PROPERTY instanceof CLASS) {
        $this->_usedProperties[\'PROPERTY\'] = true;
        $this->PROPERTY = new CLASS($value);
    } elseif (0 < \func_num_args()) {
        throw new InvalidConfigurationException(\'The node created by "NAME()" has already been initialized. You cannot pass values the second time you call NAME().\');
    }

    return $this->PROPERTY;
}' : '
COMMENTpublic function NAME(array $value = []): CLASS
{
    if (null === $this->PROPERTY) {
        $this->_usedProperties[\'PROPERTY\'] = true;
        $this->PROPERTY = new CLASS($value);
    } elseif (0 < \func_num_args()) {
        throw new InvalidConfigurationException(\'The node created by "NAME()" has already been initialized. You cannot pass values the second time you call NAME().\');
    }

    return $this->PROPERTY;
}';
        $class->addUse(InvalidConfigurationException::class);
        $class->addMethod($node->getName(), $body, ['COMMENT' => $comment, 'PROPERTY' => $property->getName(), 'CLASS' => $childClass->getFqcn(), 'PARAM_TYPE' => $paramType]);
        $this->buildNode($node, $childClass, $this->getSubNamespace($childClass));
    }
    private function handleVariableNode(VariableNode $node, ClassBuilder $class): void
    {
        $comment = $this->getComment($node);
        $property = $class->addProperty($node->getName());
        $class->addUse(ParamConfigurator::class);
        $body = '
/**
COMMENT *
 * @return $this
 */
public function NAME(mixed $valueDEFAULT): static
{
    $this->_usedProperties[\'PROPERTY\'] = true;
    $this->PROPERTY = $value;

    return $this;
}';
        $class->addMethod($node->getName(), $body, ['PROPERTY' => $property->getName(), 'COMMENT' => $comment, 'DEFAULT' => $node->hasDefaultValue() ? ' = ' . var_export($node->getDefaultValue(), \true) : '']);
    }
    private function handlePrototypedArrayNode(PrototypedArrayNode $node, ClassBuilder $class, string $namespace): void
    {
        $name = $this->getSingularName($node);
        $prototype = $node->getPrototype();
        $methodName = $name;
        $hasNormalizationClosures = $this->hasNormalizationClosures($node) || $this->hasNormalizationClosures($prototype);
        $nodeParameterTypes = $this->getParameterTypes($node);
        $prototypeParameterTypes = $this->getParameterTypes($prototype);
        $noKey = null === $key = $node->getKeyAttribute();
        if (!$prototype instanceof ArrayNode || $prototype instanceof PrototypedArrayNode && $prototype->getPrototype() instanceof ScalarNode) {
            $class->addUse(ParamConfigurator::class);
            $property = $class->addProperty($node->getName());
            if ($noKey) {
                // This is an array of values; don't use singular name
                $nodeTypesWithoutArray = array_filter($nodeParameterTypes, static fn($type) => 'array' !== $type);
                $body = '
/**
 * @param ParamConfigurator|list<ParamConfigurator|PROTOTYPE_TYPE>EXTRA_TYPE $value
 *
 * @return $this
 */
public function NAME(PARAM_TYPE $value): static
{
    $this->_usedProperties[\'PROPERTY\'] = true;
    $this->PROPERTY = $value;

    return $this;
}';
                $class->addMethod($node->getName(), $body, ['PROPERTY' => $property->getName(), 'PROTOTYPE_TYPE' => implode('|', $prototypeParameterTypes), 'EXTRA_TYPE' => $nodeTypesWithoutArray ? '|' . implode('|', $nodeTypesWithoutArray) : '', 'PARAM_TYPE' => $this->getParamType($nodeParameterTypes, \true)]);
            } else {
                $body = '
/**
 * @return $this
 */
public function NAME(string $VAR, TYPE $VALUE): static
{
    $this->_usedProperties[\'PROPERTY\'] = true;
    $this->PROPERTY[$VAR] = $VALUE;

    return $this;
}';
                $class->addMethod($methodName, $body, ['PROPERTY' => $property->getName(), 'TYPE' => $this->getParamType($prototypeParameterTypes, \true), 'VAR' => '' === $key ? 'key' : $key, 'VALUE' => 'value' === $key ? 'data' : 'value']);
            }
            return;
        }
        $childClass = new ClassBuilder($namespace, $name);
        if ($prototype instanceof ArrayNode) {
            $childClass->setAllowExtraKeys($prototype->shouldIgnoreExtraKeys());
        }
        $class->addRequire($childClass);
        $this->classes[] = $childClass;
        $property = $class->addProperty($node->getName(), $this->getType($childClass->getFqcn() . '[]', $hasNormalizationClosures));
        $paramType = $this->getParamType($noKey ? $nodeParameterTypes : $prototypeParameterTypes);
        $comment = $this->getComment($node);
        if ($hasNormalizationClosures && 'array' !== $paramType) {
            $comment = \sprintf(" * @template TValue of %s\n * @param TValue \$value\n%s", $paramType, $comment);
            $comment .= \sprintf(' * @return %s|$this' . "\n", $childClass->getFqcn());
            $comment .= \sprintf(' * @psalm-return (TValue is array ? %s : static)' . "\n ", $childClass->getFqcn());
        }
        if ('' !== $comment) {
            $comment = "/**\n{$comment}*/\n";
        }
        if ($noKey) {
            $body = $hasNormalizationClosures && 'array' !== $paramType ? '
COMMENTpublic function NAME(PARAM_TYPE $value = []): CLASS|static
{
    $this->_usedProperties[\'PROPERTY\'] = true;
    if (!\is_array($value)) {
        $this->PROPERTY[] = $value;

        return $this;
    }

    return $this->PROPERTY[] = new CLASS($value);
}' : '
COMMENTpublic function NAME(array $value = []): CLASS
{
    $this->_usedProperties[\'PROPERTY\'] = true;

    return $this->PROPERTY[] = new CLASS($value);
}';
            $class->addMethod($methodName, $body, ['COMMENT' => $comment, 'PROPERTY' => $property->getName(), 'CLASS' => $childClass->getFqcn(), 'PARAM_TYPE' => $paramType]);
        } else {
            $body = $hasNormalizationClosures && 'array' !== $paramType ? '
COMMENTpublic function NAME(string $VAR, PARAM_TYPE $VALUE = []): CLASS|static
{
    if (!\is_array($VALUE)) {
        $this->_usedProperties[\'PROPERTY\'] = true;
        $this->PROPERTY[$VAR] = $VALUE;

        return $this;
    }

    if (!isset($this->PROPERTY[$VAR]) || !$this->PROPERTY[$VAR] instanceof CLASS) {
        $this->_usedProperties[\'PROPERTY\'] = true;
        $this->PROPERTY[$VAR] = new CLASS($VALUE);
    } elseif (1 < \func_num_args()) {
        throw new InvalidConfigurationException(\'The node created by "NAME()" has already been initialized. You cannot pass values the second time you call NAME().\');
    }

    return $this->PROPERTY[$VAR];
}' : '
COMMENTpublic function NAME(string $VAR, array $VALUE = []): CLASS
{
    if (!isset($this->PROPERTY[$VAR])) {
        $this->_usedProperties[\'PROPERTY\'] = true;
        $this->PROPERTY[$VAR] = new CLASS($VALUE);
    } elseif (1 < \func_num_args()) {
        throw new InvalidConfigurationException(\'The node created by "NAME()" has already been initialized. You cannot pass values the second time you call NAME().\');
    }

    return $this->PROPERTY[$VAR];
}';
            $class->addUse(InvalidConfigurationException::class);
            $class->addMethod($methodName, str_replace('$value', '$VAR', $body), ['COMMENT' => $comment, 'PROPERTY' => $property->getName(), 'CLASS' => $childClass->getFqcn(), 'VAR' => '' === $key ? 'key' : $key, 'VALUE' => 'value' === $key ? 'data' : 'value', 'PARAM_TYPE' => $paramType]);
        }
        $this->buildNode($prototype, $childClass, $namespace . '\\' . $childClass->getName());
    }
    private function handleScalarNode(ScalarNode $node, ClassBuilder $class): void
    {
        $comment = $this->getComment($node);
        $property = $class->addProperty($node->getName());
        $class->addUse(ParamConfigurator::class);
        $body = '
/**
COMMENT * @return $this
 */
public function NAME($value): static
{
    $this->_usedProperties[\'PROPERTY\'] = true;
    $this->PROPERTY = $value;

    return $this;
}';
        $class->addMethod($node->getName(), $body, ['PROPERTY' => $property->getName(), 'COMMENT' => $comment]);
    }
    private function getParameterTypes(NodeInterface $node): array
    {
        $paramTypes = [];
        if ($node instanceof BaseNode) {
            $types = $node->getNormalizedTypes();
            if (\in_array(ExprBuilder::TYPE_ANY, $types, \true)) {
                $paramTypes[] = 'mixed';
            }
            if (\in_array(ExprBuilder::TYPE_STRING, $types, \true)) {
                $paramTypes[] = 'string';
            }
        }
        if ($node instanceof BooleanNode) {
            $paramTypes[] = 'bool';
        } elseif ($node instanceof IntegerNode) {
            $paramTypes[] = 'int';
        } elseif ($node instanceof FloatNode) {
            $paramTypes[] = 'float';
        } elseif ($node instanceof EnumNode) {
            $paramTypes[] = 'mixed';
        } elseif ($node instanceof ArrayNode) {
            $paramTypes[] = 'array';
        } elseif ($node instanceof VariableNode) {
            $paramTypes[] = 'mixed';
        }
        return array_unique($paramTypes);
    }
    private function getComment(BaseNode $node): string
    {
        $comment = '';
        if ('' !== $info = (string) $node->getInfo()) {
            $comment .= $info . "\n";
        }
        if (!$node instanceof ArrayNode) {
            foreach ((array) ($node->getExample() ?? []) as $example) {
                $comment .= '@example ' . $example . "\n";
            }
            if ('' !== $default = $node->getDefaultValue()) {
                $comment .= '@default ' . (null === $default ? 'null' : var_export($default, \true)) . "\n";
            }
            if ($node instanceof EnumNode) {
                $comment .= \sprintf('@param ParamConfigurator|%s $value', implode('|', array_unique(array_map(fn($a) => !$a instanceof \UnitEnum ? var_export($a, \true) : '\\' . ltrim(var_export($a, \true), '\\'), $node->getValues())))) . "\n";
            } else {
                $parameterTypes = $this->getParameterTypes($node);
                $comment .= '@param ParamConfigurator|' . implode('|', $parameterTypes) . ' $value' . "\n";
            }
        } else {
            foreach ((array) ($node->getExample() ?? []) as $example) {
                $comment .= '@example ' . json_encode($example) . "\n";
            }
            if ($node->hasDefaultValue() && [] != $default = $node->getDefaultValue()) {
                $comment .= '@default ' . json_encode($default) . "\n";
            }
        }
        if ($node->isDeprecated()) {
            $comment .= '@deprecated ' . $node->getDeprecation($node->getName(), $node->getParent()->getName())['message'] . "\n";
        }
        return $comment ? ' * ' . str_replace("\n", "\n * ", rtrim($comment, "\n")) . "\n" : '';
    }
    /**
     * Pick a good singular name.
     */
    private function getSingularName(PrototypedArrayNode $node): string
    {
        $name = $node->getName();
        if (!str_ends_with($name, 's')) {
            return $name;
        }
        $parent = $node->getParent();
        $mappings = $parent instanceof ArrayNode ? $parent->getXmlRemappings() : [];
        foreach ($mappings as $map) {
            if ($map[1] === $name) {
                $name = $map[0];
                break;
            }
        }
        return $name;
    }
    private function buildToArray(ClassBuilder $class): void
    {
        $body = '$output = [];';
        foreach ($class->getProperties() as $p) {
            $code = '$this->PROPERTY';
            if (null !== $p->getType()) {
                if ($p->isArray()) {
                    $code = $p->areScalarsAllowed() ? 'array_map(fn ($v) => $v instanceof CLASS ? $v->toArray() : $v, $this->PROPERTY)' : 'array_map(fn ($v) => $v->toArray(), $this->PROPERTY)';
                } else {
                    $code = $p->areScalarsAllowed() ? '$this->PROPERTY instanceof CLASS ? $this->PROPERTY->toArray() : $this->PROPERTY' : '$this->PROPERTY->toArray()';
                }
            }
            $body .= strtr('
    if (isset($this->_usedProperties[\'PROPERTY\'])) {
        $output[\'ORG_NAME\'] = ' . $code . ';
    }', ['PROPERTY' => $p->getName(), 'ORG_NAME' => $p->getOriginalName(), 'CLASS' => $p->getType()]);
        }
        $extraKeys = $class->shouldAllowExtraKeys() ? ' + $this->_extraKeys' : '';
        $class->addMethod('toArray', '
public function NAME(): array
{
    ' . $body . '

    return $output' . $extraKeys . ';
}');
    }
    private function buildConstructor(ClassBuilder $class): void
    {
        $body = '';
        foreach ($class->getProperties() as $p) {
            $code = '$value[\'ORG_NAME\']';
            if (null !== $p->getType()) {
                if ($p->isArray()) {
                    $code = $p->areScalarsAllowed() ? 'array_map(fn ($v) => \is_array($v) ? new ' . $p->getType() . '($v) : $v, $value[\'ORG_NAME\'])' : 'array_map(fn ($v) => new ' . $p->getType() . '($v), $value[\'ORG_NAME\'])';
                } else {
                    $code = $p->areScalarsAllowed() ? '\is_array($value[\'ORG_NAME\']) ? new ' . $p->getType() . '($value[\'ORG_NAME\']) : $value[\'ORG_NAME\']' : 'new ' . $p->getType() . '($value[\'ORG_NAME\'])';
                }
            }
            $body .= strtr('
    if (array_key_exists(\'ORG_NAME\', $value)) {
        $this->_usedProperties[\'PROPERTY\'] = true;
        $this->PROPERTY = ' . $code . ';
        unset($value[\'ORG_NAME\']);
    }
', ['PROPERTY' => $p->getName(), 'ORG_NAME' => $p->getOriginalName()]);
        }
        if ($class->shouldAllowExtraKeys()) {
            $body .= '
    $this->_extraKeys = $value;
';
        } else {
            $body .= '
    if ([] !== $value) {
        throw new InvalidConfigurationException(sprintf(\'The following keys are not supported by "%s": \', __CLASS__).implode(\', \', array_keys($value)));
    }';
            $class->addUse(InvalidConfigurationException::class);
        }
        $class->addMethod('__construct', '
public function __construct(array $value = [])
{' . $body . '
}');
    }
    private function buildSetExtraKey(ClassBuilder $class): void
    {
        if (!$class->shouldAllowExtraKeys()) {
            return;
        }
        $class->addUse(ParamConfigurator::class);
        $class->addProperty('_extraKeys');
        $class->addMethod('set', '
/**
 * @param ParamConfigurator|mixed $value
 *
 * @return $this
 */
public function NAME(string $key, mixed $value): static
{
    $this->_extraKeys[$key] = $value;

    return $this;
}');
    }
    private function getSubNamespace(ClassBuilder $rootClass): string
    {
        return \sprintf('%s\%s', $rootClass->getNamespace(), substr($rootClass->getName(), 0, -6));
    }
    private function hasNormalizationClosures(NodeInterface $node): bool
    {
        try {
            $r = new \ReflectionProperty($node, 'normalizationClosures');
        } catch (\ReflectionException) {
            return \false;
        }
        return [] !== $r->getValue($node);
    }
    private function getType(string $classType, bool $hasNormalizationClosures): string
    {
        return $classType . ($hasNormalizationClosures ? '|scalar' : '');
    }
    private function getParamType(array $types, bool $withParamConfigurator = \false): string
    {
        return \in_array('mixed', $types, \true) ? 'mixed' : ($withParamConfigurator ? 'ParamConfigurator|' : '') . implode('|', $types);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Config\Exception;

/**
 * Exception class for when a resource cannot be loaded or imported.
 *
 * @author Ryan Weaver <ryan@thatsquality.com>
 */
class LoaderLoadException extends \Exception
{
    /**
     * @param mixed           $resource       The resource that could not be imported
     * @param string|null     $sourceResource The original resource importing the new resource
     * @param int             $code           The error code
     * @param \Throwable|null $previous       A previous exception
     * @param string|null     $type           The type of resource
     */
    public function __construct(mixed $resource, ?string $sourceResource = null, int $code = 0, ?\Throwable $previous = null, ?string $type = null)
    {
        if (!\is_string($resource)) {
            try {
                $resource = json_encode($resource, \JSON_THROW_ON_ERROR);
            } catch (\JsonException) {
                $resource = \sprintf('resource of type "%s"', get_debug_type($resource));
            }
        }
        $message = '';
        if ($previous) {
            // Include the previous exception, to help the user see what might be the underlying cause
            // Trim the trailing period of the previous message. We only want 1 period remove so no rtrim...
            if (str_ends_with($previous->getMessage(), '.')) {
                $trimmedMessage = substr($previous->getMessage(), 0, -1);
                $message .= \sprintf('%s', $trimmedMessage) . ' in ';
            } else {
                $message .= \sprintf('%s', $previous->getMessage()) . ' in ';
            }
            $message .= $resource . ' ';
            // show tweaked trace to complete the human readable sentence
            if (null === $sourceResource) {
                $message .= \sprintf('(which is loaded in resource "%s")', $resource);
            } else {
                $message .= \sprintf('(which is being imported from "%s")', $sourceResource);
            }
            $message .= '.';
            // if there's no previous message, present it the default way
        } elseif (null === $sourceResource) {
            $message .= \sprintf('Cannot load resource "%s".', $resource);
        } else {
            $message .= \sprintf('Cannot import resource "%s" from "%s".', $resource, $sourceResource);
        }
        // Is the resource located inside a bundle?
        if ('@' === $resource[0]) {
            $parts = explode(\DIRECTORY_SEPARATOR, $resource);
            $bundle = substr($parts[0], 1);
            $message .= \sprintf(' Make sure the "%s" bundle is correctly registered and loaded in the application kernel class.', $bundle);
            $message .= \sprintf(' If the bundle is registered, make sure the bundle path "%s" is not empty.', $resource);
        } elseif (null !== $type) {
            $message .= \sprintf(' Make sure there is a loader supporting the "%s" type.', $type);
        }
        parent::__construct($message, $code, $previous);
    }
    /**
     * @return string
     */
    protected function varToString(mixed $var)
    {
        if (\is_object($var)) {
            return \sprintf('Object(%s)', $var::class);
        }
        if (\is_array($var)) {
            $a = [];
            foreach ($var as $k => $v) {
                $a[] = \sprintf('%s => %s', $k, $this->varToString($v));
            }
            return \sprintf('Array(%s)', implode(', ', $a));
        }
        if (\is_resource($var)) {
            return \sprintf('Resource(%s)', get_resource_type($var));
        }
        if (null === $var) {
            return 'null';
        }
        if (\false === $var) {
            return 'false';
        }
        if (\true === $var) {
            return 'true';
        }
        return (string) $var;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Config\Exception;

/**
 * Exception class for when a circular reference is detected when importing resources.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class FileLoaderImportCircularReferenceException extends LoaderLoadException
{
    public function __construct(array $resources, int $code = 0, ?\Throwable $previous = null)
    {
        $message = \sprintf('Circular reference detected in "%s" ("%s" > "%s").', $this->varToString($resources[0]), implode('" > "', $resources), $resources[0]);
        \Exception::__construct($message, $code, $previous);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Config\Exception;

/**
 * File locator exception if a file does not exist.
 *
 * @author Leo Feyer <https://github.com/leofeyer>
 */
class FileLocatorFileNotFoundException extends \InvalidArgumentException
{
    private array $paths;
    public function __construct(string $message = '', int $code = 0, ?\Throwable $previous = null, array $paths = [])
    {
        parent::__construct($message, $code, $previous);
        $this->paths = $paths;
    }
    /**
     * @return array
     */
    public function getPaths()
    {
        return $this->paths;
    }
}
{
    "name": "symfony\/config",
    "type": "library",
    "description": "Helps you find, load, combine, autofill and validate configuration values of any kind",
    "keywords": [],
    "homepage": "https:\/\/symfony.com",
    "license": "MIT",
    "authors": [
        {
            "name": "Fabien Potencier",
            "email": "fabien@symfony.com"
        },
        {
            "name": "Symfony Community",
            "homepage": "https:\/\/symfony.com\/contributors"
        }
    ],
    "require": {
        "php": ">=8.1",
        "symfony\/deprecation-contracts": "^2.5|^3",
        "symfony\/filesystem": "^5.4|^6.0|^7.0",
        "symfony\/polyfill-ctype": "~1.8"
    },
    "require-dev": {
        "symfony\/event-dispatcher": "^5.4|^6.0|^7.0",
        "symfony\/finder": "^5.4|^6.0|^7.0",
        "symfony\/messenger": "^5.4|^6.0|^7.0",
        "symfony\/service-contracts": "^2.5|^3",
        "symfony\/yaml": "^5.4|^6.0|^7.0"
    },
    "conflict": {
        "symfony\/finder": "<5.4",
        "symfony\/service-contracts": "<2.5"
    },
    "autoload": {
        "psr-4": {
            "_ContaoManager\\Symfony\\Component\\Config\\": ""
        },
        "exclude-from-classmap": [
            "\/Tests\/"
        ]
    },
    "minimum-stability": "dev"
}<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Config;

/**
 * Basic implementation of ConfigCacheFactoryInterface that
 * creates an instance of the default ConfigCache.
 *
 * This factory and/or cache <em>do not</em> support cache validation
 * by means of ResourceChecker instances (that is, service-based).
 *
 * @author Matthias Pigulla <mp@webfactory.de>
 */
class ConfigCacheFactory implements ConfigCacheFactoryInterface
{
    private bool $debug;
    /**
     * @param bool $debug The debug flag to pass to ConfigCache
     */
    public function __construct(bool $debug)
    {
        $this->debug = $debug;
    }
    public function cache(string $file, callable $callback): ConfigCacheInterface
    {
        $cache = new ConfigCache($file, $this->debug);
        if (!$cache->isFresh()) {
            $callback($cache);
        }
        return $cache;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Config;

/**
 * A ConfigCacheFactory implementation that validates the
 * cache with an arbitrary set of ResourceCheckers.
 *
 * @author Matthias Pigulla <mp@webfactory.de>
 */
class ResourceCheckerConfigCacheFactory implements ConfigCacheFactoryInterface
{
    private iterable $resourceCheckers = [];
    /**
     * @param iterable<int, ResourceCheckerInterface> $resourceCheckers
     */
    public function __construct(iterable $resourceCheckers = [])
    {
        $this->resourceCheckers = $resourceCheckers;
    }
    public function cache(string $file, callable $callable): ConfigCacheInterface
    {
        $cache = new ResourceCheckerConfigCache($file, $this->resourceCheckers);
        if (!$cache->isFresh()) {
            $callable($cache);
        }
        return $cache;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Security\Http\RateLimiter;

use _ContaoManager\Symfony\Component\HttpFoundation\RateLimiter\AbstractRequestRateLimiter;
use _ContaoManager\Symfony\Component\HttpFoundation\Request;
use _ContaoManager\Symfony\Component\RateLimiter\RateLimiterFactory;
use _ContaoManager\Symfony\Component\Security\Core\Exception\InvalidArgumentException;
use _ContaoManager\Symfony\Component\Security\Http\SecurityRequestAttributes;
/**
 * A default login throttling limiter.
 *
 * This limiter prevents breadth-first attacks by enforcing
 * a limit on username+IP and a (higher) limit on IP.
 *
 * @author Wouter de Jong <wouter@wouterj.nl>
 */
final class DefaultLoginRateLimiter extends AbstractRequestRateLimiter
{
    private RateLimiterFactory $globalFactory;
    private RateLimiterFactory $localFactory;
    private string $secret;
    /**
     * @param non-empty-string $secret A secret to use for hashing the IP address and username
     */
    public function __construct(
        RateLimiterFactory $globalFactory,
        RateLimiterFactory $localFactory,
        #[\SensitiveParameter]
        string $secret
    )
    {
        if (!$secret) {
            throw new InvalidArgumentException('A non-empty secret is required.');
        }
        $this->globalFactory = $globalFactory;
        $this->localFactory = $localFactory;
        $this->secret = $secret;
    }
    protected function getLimiters(Request $request): array
    {
        $username = $request->attributes->get(SecurityRequestAttributes::LAST_USERNAME, '');
        $username = preg_match('//u', $username) ? mb_strtolower($username, 'UTF-8') : strtolower($username);
        return [$this->globalFactory->create($this->hash($request->getClientIp())), $this->localFactory->create($this->hash($username . '-' . $request->getClientIp()))];
    }
    private function hash(string $data): string
    {
        return strtr(substr(base64_encode(hash_hmac('sha256', $data, $this->secret, \true)), 0, 8), '/+', '._');
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Security\Http\Attribute;

use _ContaoManager\Symfony\Component\ExpressionLanguage\Expression;
/**
 * @author Ryan Weaver <ryan@knpuniversity.com>
 */
#[\Attribute(\Attribute::IS_REPEATABLE | \Attribute::TARGET_CLASS | \Attribute::TARGET_METHOD | \Attribute::TARGET_FUNCTION)]
final class IsGranted
{
    public function __construct(
        /**
         * Sets the first argument that will be passed to isGranted().
         */
        public string|Expression $attribute,
        /**
         * Sets the second argument passed to isGranted().
         *
         * @var array<string|Expression>|string|Expression|null
         */
        public array|string|Expression|null $subject = null,
        /**
         * The message of the exception - has a nice default if not set.
         */
        public ?string $message = null,
        /**
         * If set, will throw HttpKernel's HttpException with the given $statusCode.
         * If null, Security\Core's AccessDeniedException will be used.
         */
        public ?int $statusCode = null,
        /**
         * If set, will add the exception code to thrown exception.
         */
        public ?int $exceptionCode = null
    )
    {
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Security\Http\Attribute;

use _ContaoManager\Symfony\Component\HttpKernel\Attribute\ValueResolver;
use _ContaoManager\Symfony\Component\Security\Http\Controller\UserValueResolver;
/**
 * Indicates that a controller argument should receive the current logged user.
 */
#[\Attribute(\Attribute::TARGET_PARAMETER)]
class CurrentUser extends ValueResolver
{
    public function __construct(bool $disabled = \false, string $resolver = UserValueResolver::class)
    {
        parent::__construct($resolver, $disabled);
    }
}
Copyright (c) 2004-present Fabien Potencier

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is furnished
to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Security\Http\Util;

use _ContaoManager\Symfony\Component\HttpFoundation\Session\SessionInterface;
/**
 * Trait to get (and set) the URL the user last visited before being forced to authenticate.
 */
trait TargetPathTrait
{
    /**
     * Sets the target path the user should be redirected to after authentication.
     *
     * Usually, you do not need to set this directly.
     */
    private function saveTargetPath(SessionInterface $session, string $firewallName, string $uri): void
    {
        $session->set('_security.' . $firewallName . '.target_path', $uri);
    }
    /**
     * Returns the URL (if any) the user visited that forced them to login.
     */
    private function getTargetPath(SessionInterface $session, string $firewallName): ?string
    {
        return $session->get('_security.' . $firewallName . '.target_path');
    }
    /**
     * Removes the target path from the session.
     */
    private function removeTargetPath(SessionInterface $session, string $firewallName): void
    {
        $session->remove('_security.' . $firewallName . '.target_path');
    }
}
CHANGELOG
=========

6.4
---

 * `UserValueResolver` no longer implements `ArgumentValueResolverInterface`
 * Deprecate calling the constructor of `DefaultLoginRateLimiter` with an empty secret

6.3
---

 * Add `RememberMeBadge` to `JsonLoginAuthenticator` and enable reading parameter in JSON request body
 * Add argument `$exceptionCode` to `#[IsGranted]`
 * Deprecate passing a secret as the 2nd argument to the constructor of `Symfony\Component\Security\Http\RememberMe\PersistentRememberMeHandler`
 * Add `OidcUserInfoTokenHandler` and `OidcTokenHandler` with OIDC support for `AccessTokenAuthenticator`
 * Add `attributes` optional array argument in `UserBadge`
 * Call `UserBadge::userLoader` with attributes if the argument is set
 * Allow to override badge fqcn on `Passport::addBadge`
 * Add `SecurityTokenValueResolver` to inject token as controller argument

6.2
---

 * Add maximum username length enforcement of 4096 characters in `UserBadge`
 * Add `#[IsGranted()]`
 * Deprecate empty username or password when using when using `JsonLoginAuthenticator`
 * Set custom lifetime for login link
 * Add `$lifetime` parameter to `LoginLinkHandlerInterface::createLoginLink()`
 * Add RFC6750 Access Token support to allow token-based authentication
 * Allow using expressions as `#[IsGranted()]` attribute and subject

6.0
---

 * Remove `LogoutSuccessHandlerInterface` and `LogoutHandlerInterface`, register a listener on the `LogoutEvent` event instead
 * Remove `CookieClearingLogoutHandler`, `SessionLogoutHandler` and `CsrfTokenClearingLogoutHandler`.
   Use `CookieClearingLogoutListener`, `SessionLogoutListener` and `CsrfTokenClearingLogoutListener` instead

5.4
---

 * Deprecate the `$authenticationEntryPoint` argument of `ChannelListener`, and add `$httpPort` and `$httpsPort` arguments
 * Deprecate `RetryAuthenticationEntryPoint`, this code is now inlined in the `ChannelListener`
 * Deprecate `FormAuthenticationEntryPoint` and `BasicAuthenticationEntryPoint`, in the new system the `FormLoginAuthenticator`
   and `HttpBasicAuthenticator` should be used instead
 * Deprecate `AbstractRememberMeServices`, `PersistentTokenBasedRememberMeServices`, `RememberMeServicesInterface`,
   `TokenBasedRememberMeServices`, use the remember me handler alternatives instead
 * Deprecate the `$authManager` argument of `AccessListener`
 * Deprecate not setting the `$exceptionOnNoToken` argument of `AccessListener` to `false`
 * Deprecate `DeauthenticatedEvent`, use `TokenDeauthenticatedEvent` instead
 * Deprecate `CookieClearingLogoutHandler`, `SessionLogoutHandler` and `CsrfTokenClearingLogoutHandler`.
   Use `CookieClearingLogoutListener`, `SessionLogoutListener` and `CsrfTokenClearingLogoutListener` instead
 * Deprecate `PassportInterface`, `UserPassportInterface` and `PassportTrait`, use `Passport` instead

5.3
---

The CHANGELOG for version 5.3 and earlier can be found at https://github.com/symfony/symfony/blob/5.3/src/Symfony/Component/Security/CHANGELOG.md
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Security\Http;

use _ContaoManager\Symfony\Component\HttpFoundation\Request;
use _ContaoManager\Symfony\Component\HttpFoundation\RequestMatcherInterface;
use _ContaoManager\Symfony\Component\Security\Http\Firewall\ExceptionListener;
use _ContaoManager\Symfony\Component\Security\Http\Firewall\FirewallListenerInterface;
use _ContaoManager\Symfony\Component\Security\Http\Firewall\LogoutListener;
/**
 * FirewallMap allows configuration of different firewalls for specific parts
 * of the website.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class FirewallMap implements FirewallMapInterface
{
    /**
     * @var list<array{RequestMatcherInterface, list<callable|FirewallListenerInterface>, ExceptionListener|null, LogoutListener|null}>
     */
    private array $map = [];
    /**
     * @param list<callable|FirewallListenerInterface> $listeners
     *
     * @return void
     */
    public function add(?RequestMatcherInterface $requestMatcher = null, array $listeners = [], ?ExceptionListener $exceptionListener = null, ?LogoutListener $logoutListener = null)
    {
        $this->map[] = [$requestMatcher, $listeners, $exceptionListener, $logoutListener];
    }
    public function getListeners(Request $request): array
    {
        foreach ($this->map as $elements) {
            if (null === $elements[0] || $elements[0]->matches($request)) {
                return [$elements[1], $elements[2], $elements[3]];
            }
        }
        return [[], null, null];
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Security\Http;

use _ContaoManager\Symfony\Component\EventDispatcher\EventSubscriberInterface;
use _ContaoManager\Symfony\Component\HttpFoundation\Request;
use _ContaoManager\Symfony\Component\HttpKernel\Event\FinishRequestEvent;
use _ContaoManager\Symfony\Component\HttpKernel\Event\RequestEvent;
use _ContaoManager\Symfony\Component\HttpKernel\KernelEvents;
use _ContaoManager\Symfony\Component\Security\Http\Firewall\ExceptionListener;
use _ContaoManager\Symfony\Component\Security\Http\Firewall\FirewallListenerInterface;
use _ContaoManager\Symfony\Contracts\EventDispatcher\EventDispatcherInterface;
/**
 * Firewall uses a FirewallMap to register security listeners for the given
 * request.
 *
 * It allows for different security strategies within the same application
 * (a Basic authentication for the /api, and a web based authentication for
 * everything else for instance).
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class Firewall implements EventSubscriberInterface
{
    private FirewallMapInterface $map;
    private EventDispatcherInterface $dispatcher;
    /**
     * @var \SplObjectStorage<Request, ExceptionListener>
     */
    private \SplObjectStorage $exceptionListeners;
    public function __construct(FirewallMapInterface $map, EventDispatcherInterface $dispatcher)
    {
        $this->map = $map;
        $this->dispatcher = $dispatcher;
        $this->exceptionListeners = new \SplObjectStorage();
    }
    /**
     * @return void
     */
    public function onKernelRequest(RequestEvent $event)
    {
        if (!$event->isMainRequest()) {
            return;
        }
        // register listeners for this firewall
        $listeners = $this->map->getListeners($event->getRequest());
        $authenticationListeners = $listeners[0];
        $exceptionListener = $listeners[1];
        $logoutListener = $listeners[2];
        if (null !== $exceptionListener) {
            $this->exceptionListeners[$event->getRequest()] = $exceptionListener;
            $exceptionListener->register($this->dispatcher);
        }
        // Authentication listeners are pre-sorted by SortFirewallListenersPass
        $authenticationListeners = function () use ($authenticationListeners, $logoutListener) {
            if (null !== $logoutListener) {
                $logoutListenerPriority = $this->getListenerPriority($logoutListener);
            }
            foreach ($authenticationListeners as $listener) {
                $listenerPriority = $this->getListenerPriority($listener);
                // Yielding the LogoutListener at the correct position
                if (null !== $logoutListener && $listenerPriority < $logoutListenerPriority) {
                    yield $logoutListener;
                    $logoutListener = null;
                }
                yield $listener;
            }
            // When LogoutListener has the lowest priority of all listeners
            if (null !== $logoutListener) {
                yield $logoutListener;
            }
        };
        $this->callListeners($event, $authenticationListeners());
    }
    /**
     * @return void
     */
    public function onKernelFinishRequest(FinishRequestEvent $event)
    {
        $request = $event->getRequest();
        if (isset($this->exceptionListeners[$request])) {
            $this->exceptionListeners[$request]->unregister($this->dispatcher);
            unset($this->exceptionListeners[$request]);
        }
    }
    /**
     * @return array
     */
    public static function getSubscribedEvents()
    {
        return [KernelEvents::REQUEST => ['onKernelRequest', 8], KernelEvents::FINISH_REQUEST => 'onKernelFinishRequest'];
    }
    /**
     * @return void
     */
    protected function callListeners(RequestEvent $event, iterable $listeners)
    {
        foreach ($listeners as $listener) {
            if (!$listener instanceof FirewallListenerInterface) {
                $listener($event);
            } elseif (\false !== $listener->supports($event->getRequest())) {
                $listener->authenticate($event);
            }
            if ($event->hasResponse()) {
                break;
            }
        }
    }
    private function getListenerPriority(object $logoutListener): int
    {
        return $logoutListener instanceof FirewallListenerInterface ? $logoutListener->getPriority() : 0;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Security\Http\AccessToken;

use _ContaoManager\Symfony\Component\HttpFoundation\Request;
/**
 * The token extractor retrieves the token from a request.
 *
 * @author Florent Morselli <florent.morselli@spomky-labs.com>
 */
interface AccessTokenExtractorInterface
{
    public function extractAccessToken(Request $request): ?string;
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Security\Http\AccessToken;

use _ContaoManager\Symfony\Component\Security\Core\Exception\AuthenticationException;
use _ContaoManager\Symfony\Component\Security\Http\Authenticator\Passport\Badge\UserBadge;
/**
 * The token handler retrieves the user identifier from the token.
 * In order to get the user identifier, implementations may need to load and validate the token (e.g. revocation, expiration time, digital signature...).
 *
 * @author Florent Morselli <florent.morselli@spomky-labs.com>
 */
interface AccessTokenHandlerInterface
{
    /**
     * @throws AuthenticationException
     */
    public function getUserBadgeFrom(
        #[\SensitiveParameter]
        string $accessToken
    ): UserBadge;
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Security\Http\AccessToken;

use _ContaoManager\Symfony\Component\HttpFoundation\Request;
/**
 * Extracts a token from the request header.
 *
 * @author Florent Morselli <florent.morselli@spomky-labs.com>
 *
 * @see https://datatracker.ietf.org/doc/html/rfc6750#section-2.1
 */
final class HeaderAccessTokenExtractor implements AccessTokenExtractorInterface
{
    private string $regex;
    public function __construct(private readonly string $headerParameter = 'Authorization', private readonly string $tokenType = 'Bearer')
    {
        $this->regex = \sprintf('/^%s([a-zA-Z0-9\-_\+~\/\.]+=*)$/', '' === $this->tokenType ? '' : preg_quote($this->tokenType) . '\s+');
    }
    public function extractAccessToken(Request $request): ?string
    {
        if (!$request->headers->has($this->headerParameter) || !\is_string($header = $request->headers->get($this->headerParameter))) {
            return null;
        }
        if (preg_match($this->regex, $header, $matches)) {
            return $matches[1];
        }
        return null;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Security\Http\AccessToken;

use _ContaoManager\Symfony\Component\HttpFoundation\Request;
/**
 * The token extractor retrieves the token from a request.
 *
 * @author Florent Morselli <florent.morselli@spomky-labs.com>
 */
final class ChainAccessTokenExtractor implements AccessTokenExtractorInterface
{
    /**
     * @param AccessTokenExtractorInterface[] $accessTokenExtractors
     */
    public function __construct(private readonly iterable $accessTokenExtractors)
    {
    }
    public function extractAccessToken(Request $request): ?string
    {
        foreach ($this->accessTokenExtractors as $extractor) {
            if ($accessToken = $extractor->extractAccessToken($request)) {
                return $accessToken;
            }
        }
        return null;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Security\Http\AccessToken\Oidc;

use _ContaoManager\Psr\Log\LoggerInterface;
use _ContaoManager\Symfony\Component\Security\Core\Exception\BadCredentialsException;
use _ContaoManager\Symfony\Component\Security\Http\AccessToken\AccessTokenHandlerInterface;
use _ContaoManager\Symfony\Component\Security\Http\AccessToken\Oidc\Exception\MissingClaimException;
use _ContaoManager\Symfony\Component\Security\Http\Authenticator\FallbackUserLoader;
use _ContaoManager\Symfony\Component\Security\Http\Authenticator\Passport\Badge\UserBadge;
use _ContaoManager\Symfony\Contracts\HttpClient\HttpClientInterface;
/**
 * The token handler validates the token on the OIDC server and retrieves the user identifier.
 */
final class OidcUserInfoTokenHandler implements AccessTokenHandlerInterface
{
    use OidcTrait;
    public function __construct(private HttpClientInterface $client, private ?LoggerInterface $logger = null, private string $claim = 'sub')
    {
    }
    public function getUserBadgeFrom(string $accessToken): UserBadge
    {
        try {
            // Call the OIDC server to retrieve the user info
            // If the token is invalid or expired, the OIDC server will return an error
            $claims = $this->client->request('GET', '', ['auth_bearer' => $accessToken])->toArray();
            if (empty($claims[$this->claim])) {
                throw new MissingClaimException(\sprintf('"%s" claim not found on OIDC server response.', $this->claim));
            }
            // UserLoader argument can be overridden by a UserProvider on AccessTokenAuthenticator::authenticate
            return new UserBadge($claims[$this->claim], new FallbackUserLoader(function () use ($claims) {
                $claims['user_identifier'] = $claims[$this->claim];
                return $this->createUser($claims);
            }), $claims);
        } catch (\Exception $e) {
            $this->logger?->error('An error occurred on OIDC server.', ['error' => $e->getMessage(), 'trace' => $e->getTraceAsString()]);
            throw new BadCredentialsException('Invalid credentials.', $e->getCode(), $e);
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Security\Http\AccessToken\Oidc;

use _ContaoManager\Symfony\Component\Security\Core\User\OidcUser;
use function _ContaoManager\Symfony\Component\String\u;
/**
 * Creates {@see OidcUser} from claims.
 *
 * @internal
 */
trait OidcTrait
{
    private function createUser(array $claims): OidcUser
    {
        if (!\function_exists(\_ContaoManager\Symfony\Component\String\u::class)) {
            throw new \LogicException('You cannot use the "OidcUserInfoTokenHandler" since the String component is not installed. Try running "composer require symfony/string".');
        }
        foreach ($claims as $claim => $value) {
            unset($claims[$claim]);
            if ('' === $value || null === $value) {
                continue;
            }
            $claims[u($claim)->camel()->toString()] = $value;
        }
        if (isset($claims['updatedAt']) && '' !== $claims['updatedAt']) {
            $claims['updatedAt'] = (new \DateTimeImmutable())->setTimestamp($claims['updatedAt']);
        }
        if (\array_key_exists('emailVerified', $claims) && null !== $claims['emailVerified'] && '' !== $claims['emailVerified']) {
            $claims['emailVerified'] = (bool) $claims['emailVerified'];
        }
        if (\array_key_exists('phoneNumberVerified', $claims) && null !== $claims['phoneNumberVerified'] && '' !== $claims['phoneNumberVerified']) {
            $claims['phoneNumberVerified'] = (bool) $claims['phoneNumberVerified'];
        }
        return new OidcUser(...$claims);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Security\Http\AccessToken\Oidc;

use _ContaoManager\Jose\Component\Checker;
use _ContaoManager\Jose\Component\Checker\ClaimCheckerManager;
use _ContaoManager\Jose\Component\Core\Algorithm;
use _ContaoManager\Jose\Component\Core\AlgorithmManager;
use _ContaoManager\Jose\Component\Core\JWK;
use _ContaoManager\Jose\Component\Signature\JWSTokenSupport;
use _ContaoManager\Jose\Component\Signature\JWSVerifier;
use _ContaoManager\Jose\Component\Signature\Serializer\CompactSerializer;
use _ContaoManager\Jose\Component\Signature\Serializer\JWSSerializerManager;
use _ContaoManager\Psr\Clock\ClockInterface;
use _ContaoManager\Psr\Log\LoggerInterface;
use _ContaoManager\Symfony\Component\Clock\Clock;
use _ContaoManager\Symfony\Component\Security\Core\Exception\BadCredentialsException;
use _ContaoManager\Symfony\Component\Security\Http\AccessToken\AccessTokenHandlerInterface;
use _ContaoManager\Symfony\Component\Security\Http\AccessToken\Oidc\Exception\InvalidSignatureException;
use _ContaoManager\Symfony\Component\Security\Http\AccessToken\Oidc\Exception\MissingClaimException;
use _ContaoManager\Symfony\Component\Security\Http\Authenticator\FallbackUserLoader;
use _ContaoManager\Symfony\Component\Security\Http\Authenticator\Passport\Badge\UserBadge;
/**
 * The token handler decodes and validates the token, and retrieves the user identifier from it.
 */
final class OidcTokenHandler implements AccessTokenHandlerInterface
{
    use OidcTrait;
    public function __construct(private Algorithm $signatureAlgorithm, private JWK $jwk, private string $audience, private array $issuers, private string $claim = 'sub', private ?LoggerInterface $logger = null, private ClockInterface $clock = new Clock())
    {
    }
    public function getUserBadgeFrom(string $accessToken): UserBadge
    {
        if (!class_exists(JWSVerifier::class) || !class_exists(Checker\HeaderCheckerManager::class)) {
            throw new \LogicException('You cannot use the "oidc" token handler since "web-token/jwt-signature" and "web-token/jwt-checker" are not installed. Try running "composer require web-token/jwt-signature web-token/jwt-checker".');
        }
        try {
            // Decode the token
            $jwsVerifier = new JWSVerifier(new AlgorithmManager([$this->signatureAlgorithm]));
            $serializerManager = new JWSSerializerManager([new CompactSerializer()]);
            $jws = $serializerManager->unserialize($accessToken);
            $claims = json_decode($jws->getPayload(), \true);
            // Verify the signature
            if (!$jwsVerifier->verifyWithKey($jws, $this->jwk, 0)) {
                throw new InvalidSignatureException();
            }
            // Verify the headers
            $headerCheckerManager = new Checker\HeaderCheckerManager([new Checker\AlgorithmChecker([$this->signatureAlgorithm->name()])], [new JWSTokenSupport()]);
            // if this check fails, an InvalidHeaderException is thrown
            $headerCheckerManager->check($jws, 0);
            // Verify the claims
            $checkers = [new Checker\IssuedAtChecker(0, \false, $this->clock), new Checker\NotBeforeChecker(0, \false, $this->clock), new Checker\ExpirationTimeChecker(0, \false, $this->clock), new Checker\AudienceChecker($this->audience), new Checker\IssuerChecker($this->issuers)];
            $claimCheckerManager = new ClaimCheckerManager($checkers);
            // if this check fails, an InvalidClaimException is thrown
            $claimCheckerManager->check($claims);
            if (empty($claims[$this->claim])) {
                throw new MissingClaimException(\sprintf('"%s" claim not found.', $this->claim));
            }
            // UserLoader argument can be overridden by a UserProvider on AccessTokenAuthenticator::authenticate
            return new UserBadge($claims[$this->claim], new FallbackUserLoader(function () use ($claims) {
                $claims['user_identifier'] = $claims[$this->claim];
                return $this->createUser($claims);
            }), $claims);
        } catch (\Exception $e) {
            $this->logger?->error('An error occurred while decoding and validating the token.', ['error' => $e->getMessage(), 'trace' => $e->getTraceAsString()]);
            throw new BadCredentialsException('Invalid credentials.', $e->getCode(), $e);
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Security\Http\AccessToken\Oidc\Exception;

use _ContaoManager\Symfony\Component\Security\Core\Exception\AuthenticationException;
/**
 * This exception is thrown when the token signature is invalid.
 */
class InvalidSignatureException extends AuthenticationException
{
    public function getMessageKey(): string
    {
        return 'Invalid token signature.';
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Security\Http\AccessToken\Oidc\Exception;

use _ContaoManager\Symfony\Component\Security\Core\Exception\AuthenticationException;
/**
 * This exception is thrown when the user is invalid on the OIDC server (e.g.: "email" property is not in the scope).
 */
class MissingClaimException extends AuthenticationException
{
    public function getMessageKey(): string
    {
        return 'Missing claim.';
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Security\Http\AccessToken;

use _ContaoManager\Symfony\Component\HttpFoundation\Request;
/**
 * Extracts a token from the body request.
 *
 * WARNING!
 * Because of the security weaknesses associated with this method,
 * the request body method SHOULD NOT be used except in application contexts
 * where participating browsers do not have access to the "Authorization" request header field.
 *
 * @author Florent Morselli <florent.morselli@spomky-labs.com>
 *
 * @see https://datatracker.ietf.org/doc/html/rfc6750#section-2.2
 */
final class FormEncodedBodyExtractor implements AccessTokenExtractorInterface
{
    public function __construct(private readonly string $parameter = 'access_token')
    {
    }
    public function extractAccessToken(Request $request): ?string
    {
        if (Request::METHOD_POST !== $request->getMethod() || !str_starts_with($request->headers->get('CONTENT_TYPE', ''), 'application/x-www-form-urlencoded')) {
            return null;
        }
        $parameter = $request->request->get($this->parameter);
        return \is_string($parameter) ? $parameter : null;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Security\Http\AccessToken;

use _ContaoManager\Symfony\Component\HttpFoundation\Request;
/**
 * Extracts a token from a query string parameter.
 *
 * WARNING!
 * Because of the security weaknesses associated with the URI method,
 * including the high likelihood that the URL containing the access token will be logged,
 * it SHOULD NOT be used unless it is impossible to transport the access token in the
 * request header field.
 *
 * @author Florent Morselli <florent.morselli@spomky-labs.com>
 *
 * @see https://datatracker.ietf.org/doc/html/rfc6750#section-2.3
 */
final class QueryAccessTokenExtractor implements AccessTokenExtractorInterface
{
    public const PARAMETER = 'access_token';
    public function __construct(private readonly string $parameter = self::PARAMETER)
    {
    }
    public function extractAccessToken(Request $request): ?string
    {
        $parameter = $request->query->get($this->parameter);
        return \is_string($parameter) ? $parameter : null;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Security\Http\Logout;

use _ContaoManager\Symfony\Component\HttpFoundation\RequestStack;
use _ContaoManager\Symfony\Component\Routing\Generator\UrlGeneratorInterface;
use _ContaoManager\Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
use _ContaoManager\Symfony\Component\Security\Csrf\CsrfTokenManagerInterface;
/**
 * Provides generator functions for the logout URL.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 * @author Jeremy Mikola <jmikola@gmail.com>
 */
class LogoutUrlGenerator
{
    private ?RequestStack $requestStack;
    private ?UrlGeneratorInterface $router;
    private ?TokenStorageInterface $tokenStorage;
    private array $listeners = [];
    private ?string $currentFirewallName = null;
    private ?string $currentFirewallContext = null;
    public function __construct(?RequestStack $requestStack = null, ?UrlGeneratorInterface $router = null, ?TokenStorageInterface $tokenStorage = null)
    {
        $this->requestStack = $requestStack;
        $this->router = $router;
        $this->tokenStorage = $tokenStorage;
    }
    /**
     * Registers a firewall's LogoutListener, allowing its URL to be generated.
     *
     * @param string      $key           The firewall key
     * @param string      $logoutPath    The path that starts the logout process
     * @param string|null $csrfTokenId   The ID of the CSRF token
     * @param string|null $csrfParameter The CSRF token parameter name
     * @param string|null $context       The listener context
     *
     * @return void
     */
    public function registerListener(string $key, string $logoutPath, ?string $csrfTokenId, ?string $csrfParameter, ?CsrfTokenManagerInterface $csrfTokenManager = null, ?string $context = null)
    {
        $this->listeners[$key] = [$logoutPath, $csrfTokenId, $csrfParameter, $csrfTokenManager, $context];
    }
    /**
     * Generates the absolute logout path for the firewall.
     */
    public function getLogoutPath(?string $key = null): string
    {
        return $this->generateLogoutUrl($key, UrlGeneratorInterface::ABSOLUTE_PATH);
    }
    /**
     * Generates the absolute logout URL for the firewall.
     */
    public function getLogoutUrl(?string $key = null): string
    {
        return $this->generateLogoutUrl($key, UrlGeneratorInterface::ABSOLUTE_URL);
    }
    /**
     * @return void
     */
    public function setCurrentFirewall(?string $key, ?string $context = null)
    {
        $this->currentFirewallName = $key;
        $this->currentFirewallContext = $context;
    }
    /**
     * Generates the logout URL for the firewall.
     */
    private function generateLogoutUrl(?string $key, int $referenceType): string
    {
        [$logoutPath, $csrfTokenId, $csrfParameter, $csrfTokenManager] = $this->getListener($key);
        if (null === $logoutPath) {
            throw new \LogicException('Unable to generate the logout URL without a path.');
        }
        $parameters = null !== $csrfTokenManager ? [$csrfParameter => (string) $csrfTokenManager->getToken($csrfTokenId)] : [];
        if ('/' === $logoutPath[0]) {
            if (!$this->requestStack) {
                throw new \LogicException('Unable to generate the logout URL without a RequestStack.');
            }
            $request = $this->requestStack->getCurrentRequest();
            if (!$request) {
                throw new \LogicException('Unable to generate the logout URL without a Request.');
            }
            $url = UrlGeneratorInterface::ABSOLUTE_URL === $referenceType ? $request->getUriForPath($logoutPath) : $request->getBaseUrl() . $logoutPath;
            if ($parameters) {
                $url .= '?' . http_build_query($parameters, '', '&');
            }
        } else {
            if (!$this->router) {
                throw new \LogicException('Unable to generate the logout URL without a Router.');
            }
            $url = $this->router->generate($logoutPath, $parameters, $referenceType);
        }
        return $url;
    }
    /**
     * @throws \InvalidArgumentException if no LogoutListener is registered for the key or could not be found automatically
     */
    private function getListener(?string $key): array
    {
        if (null !== $key) {
            if (isset($this->listeners[$key])) {
                return $this->listeners[$key];
            }
            throw new \InvalidArgumentException(\sprintf('No LogoutListener found for firewall key "%s".', $key));
        }
        // Fetch the current provider key from token, if possible
        if (null !== $this->tokenStorage) {
            $token = $this->tokenStorage->getToken();
            if (null !== $token && method_exists($token, 'getFirewallName')) {
                $key = $token->getFirewallName();
                if (isset($this->listeners[$key])) {
                    return $this->listeners[$key];
                }
            }
        }
        // Fetch from injected current firewall information, if possible
        if (isset($this->listeners[$this->currentFirewallName ?? ''])) {
            return $this->listeners[$this->currentFirewallName ?? ''];
        }
        foreach ($this->listeners as $listener) {
            if (isset($listener[4]) && $this->currentFirewallContext === $listener[4]) {
                return $listener;
            }
        }
        if (null === $this->currentFirewallName) {
            throw new \InvalidArgumentException('This request is not behind a firewall, pass the firewall name manually to generate a logout URL.');
        }
        throw new \InvalidArgumentException('Unable to find logout in the current firewall, pass the firewall name manually to generate a logout URL.');
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Security\Http;

use _ContaoManager\Symfony\Component\Security\Http\Event\InteractiveLoginEvent;
use _ContaoManager\Symfony\Component\Security\Http\Event\SwitchUserEvent;
final class SecurityEvents
{
    /**
     * The INTERACTIVE_LOGIN event occurs after a user has actively logged
     * into your website. It is important to distinguish this action from
     * non-interactive authentication methods, such as:
     *   - authentication based on your session.
     *   - authentication using an HTTP basic or HTTP digest header.
     *
     * @Event("Symfony\Component\Security\Http\Event\InteractiveLoginEvent")
     */
    public const INTERACTIVE_LOGIN = 'security.interactive_login';
    /**
     * The SWITCH_USER event occurs before switch to another user and
     * before exit from an already switched user.
     *
     * @Event("Symfony\Component\Security\Http\Event\SwitchUserEvent")
     */
    public const SWITCH_USER = 'security.switch_user';
    /**
     * Event aliases.
     *
     * These aliases can be consumed by RegisterListenersPass.
     */
    public const ALIASES = [InteractiveLoginEvent::class => self::INTERACTIVE_LOGIN, SwitchUserEvent::class => self::SWITCH_USER];
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Security\Http\Firewall;

use _ContaoManager\Symfony\Component\HttpFoundation\Request;
use _ContaoManager\Symfony\Component\HttpKernel\Event\RequestEvent;
use _ContaoManager\Symfony\Component\Security\Core\Authentication\Token\NullToken;
use _ContaoManager\Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
use _ContaoManager\Symfony\Component\Security\Core\Authorization\AccessDecisionManagerInterface;
use _ContaoManager\Symfony\Component\Security\Core\Authorization\Voter\AuthenticatedVoter;
use _ContaoManager\Symfony\Component\Security\Core\Exception\AccessDeniedException;
use _ContaoManager\Symfony\Component\Security\Http\AccessMapInterface;
use _ContaoManager\Symfony\Component\Security\Http\Event\LazyResponseEvent;
/**
 * AccessListener enforces access control rules.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 *
 * @final
 */
class AccessListener extends AbstractListener
{
    private TokenStorageInterface $tokenStorage;
    private AccessDecisionManagerInterface $accessDecisionManager;
    private AccessMapInterface $map;
    public function __construct(TokenStorageInterface $tokenStorage, AccessDecisionManagerInterface $accessDecisionManager, AccessMapInterface $map, bool $exceptionOnNoToken = \false)
    {
        if (\false !== $exceptionOnNoToken) {
            throw new \LogicException(\sprintf('Argument $exceptionOnNoToken of "%s()" must be set to "false".', __METHOD__));
        }
        $this->tokenStorage = $tokenStorage;
        $this->accessDecisionManager = $accessDecisionManager;
        $this->map = $map;
    }
    public function supports(Request $request): ?bool
    {
        [$attributes] = $this->map->getPatterns($request);
        $request->attributes->set('_access_control_attributes', $attributes);
        if ($attributes && [AuthenticatedVoter::PUBLIC_ACCESS] !== $attributes) {
            return \true;
        }
        return null;
    }
    /**
     * Handles access authorization.
     *
     * @throws AccessDeniedException
     */
    public function authenticate(RequestEvent $event): void
    {
        $request = $event->getRequest();
        $attributes = $request->attributes->get('_access_control_attributes');
        $request->attributes->remove('_access_control_attributes');
        if (!$attributes || [AuthenticatedVoter::PUBLIC_ACCESS] === $attributes && $event instanceof LazyResponseEvent) {
            return;
        }
        $token = $this->tokenStorage->getToken() ?? new NullToken();
        if (!$this->accessDecisionManager->decide($token, $attributes, $request, \true)) {
            throw $this->createAccessDeniedException($request, $attributes);
        }
    }
    private function createAccessDeniedException(Request $request, array $attributes): AccessDeniedException
    {
        $exception = new AccessDeniedException();
        $exception->setAttributes($attributes);
        $exception->setSubject($request);
        return $exception;
    }
    public static function getPriority(): int
    {
        return -255;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Security\Http\Firewall;

use _ContaoManager\Psr\Log\LoggerInterface;
use _ContaoManager\Symfony\Component\HttpFoundation\Request;
use _ContaoManager\Symfony\Component\HttpFoundation\Session\Session;
use _ContaoManager\Symfony\Component\HttpKernel\Event\RequestEvent;
use _ContaoManager\Symfony\Component\HttpKernel\Event\ResponseEvent;
use _ContaoManager\Symfony\Component\HttpKernel\KernelEvents;
use _ContaoManager\Symfony\Component\Security\Core\Authentication\AuthenticationTrustResolver;
use _ContaoManager\Symfony\Component\Security\Core\Authentication\AuthenticationTrustResolverInterface;
use _ContaoManager\Symfony\Component\Security\Core\Authentication\Token\AbstractToken;
use _ContaoManager\Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
use _ContaoManager\Symfony\Component\Security\Core\Authentication\Token\SwitchUserToken;
use _ContaoManager\Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use _ContaoManager\Symfony\Component\Security\Core\Exception\UnsupportedUserException;
use _ContaoManager\Symfony\Component\Security\Core\Exception\UserNotFoundException;
use _ContaoManager\Symfony\Component\Security\Core\User\EquatableInterface;
use _ContaoManager\Symfony\Component\Security\Core\User\LegacyPasswordAuthenticatedUserInterface;
use _ContaoManager\Symfony\Component\Security\Core\User\PasswordAuthenticatedUserInterface;
use _ContaoManager\Symfony\Component\Security\Core\User\UserInterface;
use _ContaoManager\Symfony\Component\Security\Core\User\UserProviderInterface;
use _ContaoManager\Symfony\Component\Security\Http\Event\TokenDeauthenticatedEvent;
use _ContaoManager\Symfony\Contracts\EventDispatcher\EventDispatcherInterface;
/**
 * ContextListener manages the SecurityContext persistence through a session.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 *
 * @final
 */
class ContextListener extends AbstractListener
{
    private TokenStorageInterface $tokenStorage;
    private string $sessionKey;
    private ?LoggerInterface $logger;
    private iterable $userProviders;
    private ?EventDispatcherInterface $dispatcher;
    private bool $registered = \false;
    private AuthenticationTrustResolverInterface $trustResolver;
    private ?\Closure $sessionTrackerEnabler;
    /**
     * @param iterable<mixed, UserProviderInterface> $userProviders
     */
    public function __construct(TokenStorageInterface $tokenStorage, iterable $userProviders, string $contextKey, ?LoggerInterface $logger = null, ?EventDispatcherInterface $dispatcher = null, ?AuthenticationTrustResolverInterface $trustResolver = null, ?callable $sessionTrackerEnabler = null)
    {
        if (empty($contextKey)) {
            throw new \InvalidArgumentException('$contextKey must not be empty.');
        }
        $this->tokenStorage = $tokenStorage;
        $this->userProviders = $userProviders;
        $this->sessionKey = '_security_' . $contextKey;
        $this->logger = $logger;
        $this->dispatcher = $dispatcher;
        $this->trustResolver = $trustResolver ?? new AuthenticationTrustResolver();
        $this->sessionTrackerEnabler = null === $sessionTrackerEnabler ? null : $sessionTrackerEnabler(...);
    }
    public function supports(Request $request): ?bool
    {
        return null;
        // always run authenticate() lazily with lazy firewalls
    }
    /**
     * Reads the Security Token from the session.
     */
    public function authenticate(RequestEvent $event): void
    {
        if (!$this->registered && null !== $this->dispatcher && $event->isMainRequest()) {
            $this->dispatcher->addListener(KernelEvents::RESPONSE, $this->onKernelResponse(...));
            $this->registered = \true;
        }
        $request = $event->getRequest();
        $session = $request->hasPreviousSession() ? $request->getSession() : null;
        $request->attributes->set('_security_firewall_run', $this->sessionKey);
        if (null !== $session) {
            $usageIndexValue = $session instanceof Session ? $usageIndexReference =& $session->getUsageIndex() : 0;
            $usageIndexReference = \PHP_INT_MIN;
            $sessionId = $request->cookies->all()[$session->getName()] ?? null;
            $token = $session->get($this->sessionKey);
            // sessionId = true is used in the tests
            if ($this->sessionTrackerEnabler && \in_array($sessionId, [\true, $session->getId()], \true)) {
                $usageIndexReference = $usageIndexValue;
            } else {
                $usageIndexReference = $usageIndexReference - \PHP_INT_MIN + $usageIndexValue;
            }
        }
        if (null === $session || null === $token) {
            if ($this->sessionTrackerEnabler) {
                ($this->sessionTrackerEnabler)();
            }
            $this->tokenStorage->setToken(null);
            return;
        }
        $token = $this->safelyUnserialize($token);
        $this->logger?->debug('Read existing security token from the session.', ['key' => $this->sessionKey, 'token_class' => \is_object($token) ? $token::class : null]);
        if ($token instanceof TokenInterface) {
            if (!$token->getUser()) {
                throw new \UnexpectedValueException(\sprintf('Cannot authenticate a "%s" token because it doesn\'t store a user.', $token::class));
            }
            $originalToken = $token;
            $token = $this->refreshUser($token);
            if (!$token) {
                $this->logger?->debug('Token was deauthenticated after trying to refresh it.');
                $this->dispatcher?->dispatch(new TokenDeauthenticatedEvent($originalToken, $request));
            }
        } elseif (null !== $token) {
            $this->logger?->warning('Expected a security token from the session, got something else.', ['key' => $this->sessionKey, 'received' => $token]);
            $token = null;
        }
        if ($this->sessionTrackerEnabler) {
            ($this->sessionTrackerEnabler)();
        }
        $this->tokenStorage->setToken($token);
    }
    /**
     * Writes the security token into the session.
     */
    public function onKernelResponse(ResponseEvent $event): void
    {
        if (!$event->isMainRequest()) {
            return;
        }
        $request = $event->getRequest();
        if (!$request->hasSession() || $request->attributes->get('_security_firewall_run') !== $this->sessionKey) {
            return;
        }
        $this->dispatcher?->removeListener(KernelEvents::RESPONSE, $this->onKernelResponse(...));
        $this->registered = \false;
        $session = $request->getSession();
        $sessionId = $session->getId();
        $usageIndexValue = $session instanceof Session ? $usageIndexReference =& $session->getUsageIndex() : null;
        $usageIndexReference = \PHP_INT_MIN;
        $token = $this->tokenStorage->getToken();
        if (!$this->trustResolver->isAuthenticated($token)) {
            if ($request->hasPreviousSession()) {
                $session->remove($this->sessionKey);
            }
        } else {
            $session->set($this->sessionKey, serialize($token));
            $this->logger?->debug('Stored the security token in the session.', ['key' => $this->sessionKey]);
        }
        if ($this->sessionTrackerEnabler && $session->getId() === $sessionId) {
            $usageIndexReference = $usageIndexValue;
        } else {
            $usageIndexReference = $usageIndexReference - \PHP_INT_MIN + $usageIndexValue;
        }
    }
    /**
     * Refreshes the user by reloading it from the user provider.
     *
     * @throws \RuntimeException
     */
    protected function refreshUser(TokenInterface $token): ?TokenInterface
    {
        $user = $token->getUser();
        $userNotFoundByProvider = \false;
        $userDeauthenticated = \false;
        $userClass = $user::class;
        foreach ($this->userProviders as $provider) {
            if (!$provider instanceof UserProviderInterface) {
                throw new \InvalidArgumentException(\sprintf('User provider "%s" must implement "%s".', get_debug_type($provider), UserProviderInterface::class));
            }
            if (!$provider->supportsClass($userClass)) {
                continue;
            }
            try {
                $refreshedUser = $provider->refreshUser($user);
                $newToken = clone $token;
                $newToken->setUser($refreshedUser, \false);
                // tokens can be deauthenticated if the user has been changed.
                if ($token instanceof AbstractToken && $this->hasUserChanged($user, $newToken)) {
                    $userDeauthenticated = \true;
                    $this->logger?->debug('Cannot refresh token because user has changed.', ['username' => $refreshedUser->getUserIdentifier(), 'provider' => $provider::class]);
                    continue;
                }
                $token->setUser($refreshedUser);
                if (null !== $this->logger) {
                    $context = ['provider' => $provider::class, 'username' => $refreshedUser->getUserIdentifier()];
                    if ($token instanceof SwitchUserToken) {
                        $originalToken = $token->getOriginalToken();
                        $context['impersonator_username'] = $originalToken->getUserIdentifier();
                    }
                    $this->logger->debug('User was reloaded from a user provider.', $context);
                }
                return $token;
            } catch (UnsupportedUserException) {
                // let's try the next user provider
            } catch (UserNotFoundException $e) {
                $this->logger?->warning('Username could not be found in the selected user provider.', ['username' => $e->getUserIdentifier(), 'provider' => $provider::class]);
                $userNotFoundByProvider = \true;
            }
        }
        if ($userDeauthenticated) {
            return null;
        }
        if ($userNotFoundByProvider) {
            return null;
        }
        throw new \RuntimeException(\sprintf('There is no user provider for user "%s". Shouldn\'t the "supportsClass()" method of your user provider return true for this classname?', $userClass));
    }
    private function safelyUnserialize(string $serializedToken): mixed
    {
        $token = null;
        $prevUnserializeHandler = ini_set('unserialize_callback_func', __CLASS__ . '::handleUnserializeCallback');
        $prevErrorHandler = set_error_handler(function ($type, $msg, $file, $line, $context = []) use (&$prevErrorHandler) {
            if (__FILE__ === $file && !\in_array($type, [\E_DEPRECATED, \E_USER_DEPRECATED], \true)) {
                throw new \ErrorException($msg, 0x37313bc, $type, $file, $line);
            }
            return $prevErrorHandler ? $prevErrorHandler($type, $msg, $file, $line, $context) : \false;
        });
        try {
            $token = unserialize($serializedToken);
        } catch (\ErrorException $e) {
            if (0x37313bc !== $e->getCode()) {
                throw $e;
            }
            $this->logger?->warning('Failed to unserialize the security token from the session.', ['key' => $this->sessionKey, 'received' => $serializedToken, 'exception' => $e]);
        } finally {
            restore_error_handler();
            ini_set('unserialize_callback_func', $prevUnserializeHandler);
        }
        return $token;
    }
    private static function hasUserChanged(UserInterface $originalUser, TokenInterface $refreshedToken): bool
    {
        $refreshedUser = $refreshedToken->getUser();
        if ($originalUser instanceof EquatableInterface) {
            return !$originalUser->isEqualTo($refreshedUser);
        }
        if ($originalUser instanceof PasswordAuthenticatedUserInterface || $refreshedUser instanceof PasswordAuthenticatedUserInterface) {
            if (!$originalUser instanceof PasswordAuthenticatedUserInterface || !$refreshedUser instanceof PasswordAuthenticatedUserInterface || $originalUser->getPassword() !== $refreshedUser->getPassword()) {
                return \true;
            }
            if ($originalUser instanceof LegacyPasswordAuthenticatedUserInterface xor $refreshedUser instanceof LegacyPasswordAuthenticatedUserInterface) {
                return \true;
            }
            if ($originalUser instanceof LegacyPasswordAuthenticatedUserInterface && $refreshedUser instanceof LegacyPasswordAuthenticatedUserInterface && $originalUser->getSalt() !== $refreshedUser->getSalt()) {
                return \true;
            }
        }
        $userRoles = array_map('strval', (array) $refreshedUser->getRoles());
        if ($refreshedToken instanceof SwitchUserToken) {
            $userRoles[] = 'ROLE_PREVIOUS_ADMIN';
        }
        if (\count($userRoles) !== \count($refreshedToken->getRoleNames()) || \count($userRoles) !== \count(array_intersect($userRoles, $refreshedToken->getRoleNames()))) {
            return \true;
        }
        if ($originalUser->getUserIdentifier() !== $refreshedUser->getUserIdentifier()) {
            return \true;
        }
        return \false;
    }
    /**
     * @internal
     */
    public static function handleUnserializeCallback(string $class): never
    {
        throw new \ErrorException('Class not found: ' . $class, 0x37313bc);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Security\Http\Firewall;

use _ContaoManager\Symfony\Component\HttpKernel\Event\RequestEvent;
/**
 * A base class for listeners that can tell whether they should authenticate incoming requests.
 *
 * @author Nicolas Grekas <p@tchwork.com>
 */
abstract class AbstractListener implements FirewallListenerInterface
{
    final public function __invoke(RequestEvent $event): void
    {
        if (\false !== $this->supports($event->getRequest())) {
            $this->authenticate($event);
        }
    }
    public static function getPriority(): int
    {
        return 0;
        // Default
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Security\Http\Firewall;

use _ContaoManager\Symfony\Component\HttpFoundation\Request;
use _ContaoManager\Symfony\Component\HttpKernel\Event\RequestEvent;
use _ContaoManager\Symfony\Component\Security\Http\Authentication\AuthenticatorManagerInterface;
/**
 * Firewall authentication listener that delegates to the authenticator system.
 *
 * @author Wouter de Jong <wouter@wouterj.nl>
 */
class AuthenticatorManagerListener extends AbstractListener
{
    private AuthenticatorManagerInterface $authenticatorManager;
    public function __construct(AuthenticatorManagerInterface $authenticationManager)
    {
        $this->authenticatorManager = $authenticationManager;
    }
    public function supports(Request $request): ?bool
    {
        return $this->authenticatorManager->supports($request);
    }
    public function authenticate(RequestEvent $event): void
    {
        $request = $event->getRequest();
        $response = $this->authenticatorManager->authenticateRequest($request);
        if (null === $response) {
            return;
        }
        $event->setResponse($response);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Security\Http\Firewall;

use _ContaoManager\Psr\Log\LoggerInterface;
use _ContaoManager\Symfony\Component\EventDispatcher\EventDispatcherInterface;
use _ContaoManager\Symfony\Component\HttpFoundation\Request;
use _ContaoManager\Symfony\Component\HttpFoundation\Response;
use _ContaoManager\Symfony\Component\HttpKernel\Event\ExceptionEvent;
use _ContaoManager\Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;
use _ContaoManager\Symfony\Component\HttpKernel\Exception\HttpException;
use _ContaoManager\Symfony\Component\HttpKernel\HttpKernelInterface;
use _ContaoManager\Symfony\Component\HttpKernel\KernelEvents;
use _ContaoManager\Symfony\Component\Security\Core\Authentication\AuthenticationTrustResolverInterface;
use _ContaoManager\Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
use _ContaoManager\Symfony\Component\Security\Core\Exception\AccessDeniedException;
use _ContaoManager\Symfony\Component\Security\Core\Exception\AccountStatusException;
use _ContaoManager\Symfony\Component\Security\Core\Exception\AuthenticationException;
use _ContaoManager\Symfony\Component\Security\Core\Exception\InsufficientAuthenticationException;
use _ContaoManager\Symfony\Component\Security\Core\Exception\LazyResponseException;
use _ContaoManager\Symfony\Component\Security\Core\Exception\LogoutException;
use _ContaoManager\Symfony\Component\Security\Http\Authorization\AccessDeniedHandlerInterface;
use _ContaoManager\Symfony\Component\Security\Http\EntryPoint\AuthenticationEntryPointInterface;
use _ContaoManager\Symfony\Component\Security\Http\EntryPoint\Exception\NotAnEntryPointException;
use _ContaoManager\Symfony\Component\Security\Http\HttpUtils;
use _ContaoManager\Symfony\Component\Security\Http\SecurityRequestAttributes;
use _ContaoManager\Symfony\Component\Security\Http\Util\TargetPathTrait;
/**
 * ExceptionListener catches authentication exception and converts them to
 * Response instances.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 *
 * @final
 */
class ExceptionListener
{
    use TargetPathTrait;
    private TokenStorageInterface $tokenStorage;
    private string $firewallName;
    private ?AccessDeniedHandlerInterface $accessDeniedHandler;
    private ?AuthenticationEntryPointInterface $authenticationEntryPoint;
    private AuthenticationTrustResolverInterface $authenticationTrustResolver;
    private ?string $errorPage;
    private ?LoggerInterface $logger;
    private HttpUtils $httpUtils;
    private bool $stateless;
    public function __construct(TokenStorageInterface $tokenStorage, AuthenticationTrustResolverInterface $trustResolver, HttpUtils $httpUtils, string $firewallName, ?AuthenticationEntryPointInterface $authenticationEntryPoint = null, ?string $errorPage = null, ?AccessDeniedHandlerInterface $accessDeniedHandler = null, ?LoggerInterface $logger = null, bool $stateless = \false)
    {
        $this->tokenStorage = $tokenStorage;
        $this->accessDeniedHandler = $accessDeniedHandler;
        $this->httpUtils = $httpUtils;
        $this->firewallName = $firewallName;
        $this->authenticationEntryPoint = $authenticationEntryPoint;
        $this->authenticationTrustResolver = $trustResolver;
        $this->errorPage = $errorPage;
        $this->logger = $logger;
        $this->stateless = $stateless;
    }
    /**
     * Registers a onKernelException listener to take care of security exceptions.
     */
    public function register(EventDispatcherInterface $dispatcher): void
    {
        $dispatcher->addListener(KernelEvents::EXCEPTION, $this->onKernelException(...), 1);
    }
    /**
     * Unregisters the dispatcher.
     */
    public function unregister(EventDispatcherInterface $dispatcher): void
    {
        $dispatcher->removeListener(KernelEvents::EXCEPTION, $this->onKernelException(...));
    }
    /**
     * Handles security related exceptions.
     */
    public function onKernelException(ExceptionEvent $event): void
    {
        $exception = $event->getThrowable();
        do {
            if ($exception instanceof AuthenticationException) {
                $this->handleAuthenticationException($event, $exception);
                return;
            }
            if ($exception instanceof AccessDeniedException) {
                $this->handleAccessDeniedException($event, $exception);
                return;
            }
            if ($exception instanceof LazyResponseException) {
                $event->setResponse($exception->getResponse());
                return;
            }
            if ($exception instanceof LogoutException) {
                $this->handleLogoutException($event, $exception);
                return;
            }
        } while (null !== $exception = $exception->getPrevious());
    }
    private function handleAuthenticationException(ExceptionEvent $event, AuthenticationException $exception): void
    {
        $this->logger?->info('An AuthenticationException was thrown; redirecting to authentication entry point.', ['exception' => $exception]);
        try {
            $event->setResponse($this->startAuthentication($event->getRequest(), $exception));
            $event->allowCustomResponseCode();
        } catch (\Exception $e) {
            $event->setThrowable($e);
        }
    }
    private function handleAccessDeniedException(ExceptionEvent $event, AccessDeniedException $exception): void
    {
        $event->setThrowable(new AccessDeniedHttpException($exception->getMessage(), $exception));
        $token = $this->tokenStorage->getToken();
        if (!$this->authenticationTrustResolver->isFullFledged($token)) {
            $this->logger?->debug('Access denied, the user is not fully authenticated; redirecting to authentication entry point.', ['exception' => $exception]);
            try {
                $insufficientAuthenticationException = new InsufficientAuthenticationException('Full authentication is required to access this resource.', 0, $exception);
                if (null !== $token) {
                    $insufficientAuthenticationException->setToken($token);
                }
                $event->setResponse($this->startAuthentication($event->getRequest(), $insufficientAuthenticationException));
            } catch (\Exception $e) {
                $event->setThrowable($e);
            }
            return;
        }
        $this->logger?->debug('Access denied, the user is neither anonymous, nor remember-me.', ['exception' => $exception]);
        try {
            if (null !== $this->accessDeniedHandler) {
                $response = $this->accessDeniedHandler->handle($event->getRequest(), $exception);
                if ($response instanceof Response) {
                    $event->setResponse($response);
                }
            } elseif (null !== $this->errorPage) {
                $subRequest = $this->httpUtils->createRequest($event->getRequest(), $this->errorPage);
                $subRequest->attributes->set(SecurityRequestAttributes::ACCESS_DENIED_ERROR, $exception);
                $event->setResponse($event->getKernel()->handle($subRequest, HttpKernelInterface::SUB_REQUEST, \true));
                $event->allowCustomResponseCode();
            }
        } catch (\Exception $e) {
            $this->logger?->error('An exception was thrown when handling an AccessDeniedException.', ['exception' => $e]);
            $event->setThrowable(new \RuntimeException('Exception thrown when handling an exception.', 0, $e));
        }
    }
    private function handleLogoutException(ExceptionEvent $event, LogoutException $exception): void
    {
        $event->setThrowable(new AccessDeniedHttpException($exception->getMessage(), $exception));
        $this->logger?->info('A LogoutException was thrown; wrapping with AccessDeniedHttpException', ['exception' => $exception]);
    }
    private function startAuthentication(Request $request, AuthenticationException $authException): Response
    {
        if (null === $this->authenticationEntryPoint) {
            $this->throwUnauthorizedException($authException);
        }
        $this->logger?->debug('Calling Authentication entry point.', ['entry_point' => $this->authenticationEntryPoint]);
        if (!$this->stateless) {
            $this->setTargetPath($request);
        }
        if ($authException instanceof AccountStatusException) {
            // remove the security token to prevent infinite redirect loops
            $this->tokenStorage->setToken(null);
            $this->logger?->info('The security token was removed due to an AccountStatusException.', ['exception' => $authException]);
        }
        try {
            $response = $this->authenticationEntryPoint->start($request, $authException);
        } catch (NotAnEntryPointException) {
            $this->throwUnauthorizedException($authException);
        }
        if (!$response instanceof Response) {
            $given = get_debug_type($response);
            throw new \LogicException(\sprintf('The "%s::start()" method must return a Response object ("%s" returned).', get_debug_type($this->authenticationEntryPoint), $given));
        }
        return $response;
    }
    protected function setTargetPath(Request $request): void
    {
        // session isn't required when using HTTP basic authentication mechanism for example
        if ($request->hasSession() && $request->isMethodSafe() && !$request->isXmlHttpRequest()) {
            $this->saveTargetPath($request->getSession(), $this->firewallName, $request->getUri());
        }
    }
    private function throwUnauthorizedException(AuthenticationException $authException): never
    {
        $this->logger?->notice(\sprintf('No Authentication entry point configured, returning a %s HTTP response. Configure "entry_point" on the firewall "%s" if you want to modify the response.', Response::HTTP_UNAUTHORIZED, $this->firewallName));
        throw new HttpException(Response::HTTP_UNAUTHORIZED, $authException->getMessage(), $authException, [], $authException->getCode());
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Security\Http\Firewall;

use _ContaoManager\Symfony\Component\HttpFoundation\Request;
use _ContaoManager\Symfony\Component\HttpKernel\Event\RequestEvent;
/**
 * Can be implemented by firewall listeners.
 *
 * @author Christian Scheb <me@christianscheb.de>
 * @author Nicolas Grekas <p@tchwork.com>
 * @author Robin Chalas <robin.chalas@gmail.com>
 */
interface FirewallListenerInterface
{
    /**
     * Tells whether the authenticate() method should be called or not depending on the incoming request.
     *
     * Returning null means authenticate() can be called lazily when accessing the token storage.
     */
    public function supports(Request $request): ?bool;
    /**
     * Does whatever is required to authenticate the request, typically calling $event->setResponse() internally.
     *
     * @return void
     */
    public function authenticate(RequestEvent $event);
    /**
     * Defines the priority of the listener.
     * The higher the number, the earlier a listener is executed.
     */
    public static function getPriority(): int;
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Security\Http\Firewall;

use _ContaoManager\Psr\Log\LoggerInterface;
use _ContaoManager\Symfony\Component\HttpFoundation\RedirectResponse;
use _ContaoManager\Symfony\Component\HttpFoundation\Request;
use _ContaoManager\Symfony\Component\HttpKernel\Event\RequestEvent;
use _ContaoManager\Symfony\Component\Security\Http\AccessMapInterface;
/**
 * ChannelListener switches the HTTP protocol based on the access control
 * configuration.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 *
 * @final
 */
class ChannelListener extends AbstractListener
{
    private AccessMapInterface $map;
    private ?LoggerInterface $logger;
    private int $httpPort;
    private int $httpsPort;
    public function __construct(AccessMapInterface $map, ?LoggerInterface $logger = null, int $httpPort = 80, int $httpsPort = 443)
    {
        $this->map = $map;
        $this->logger = $logger;
        $this->httpPort = $httpPort;
        $this->httpsPort = $httpsPort;
    }
    /**
     * Handles channel management.
     */
    public function supports(Request $request): ?bool
    {
        [, $channel] = $this->map->getPatterns($request);
        if ('https' === $channel && !$request->isSecure()) {
            if (null !== $this->logger) {
                if ('https' === $request->headers->get('X-Forwarded-Proto')) {
                    $this->logger->info('Redirecting to HTTPS. ("X-Forwarded-Proto" header is set to "https" - did you set "trusted_proxies" correctly?)');
                } elseif (str_contains($request->headers->get('Forwarded', ''), 'proto=https')) {
                    $this->logger->info('Redirecting to HTTPS. ("Forwarded" header is set to "proto=https" - did you set "trusted_proxies" correctly?)');
                } else {
                    $this->logger->info('Redirecting to HTTPS.');
                }
            }
            return \true;
        }
        if ('http' === $channel && $request->isSecure()) {
            $this->logger?->info('Redirecting to HTTP.');
            return \true;
        }
        return \false;
    }
    public function authenticate(RequestEvent $event): void
    {
        $request = $event->getRequest();
        $event->setResponse($this->createRedirectResponse($request));
    }
    private function createRedirectResponse(Request $request): RedirectResponse
    {
        $scheme = $request->isSecure() ? 'http' : 'https';
        if ('http' === $scheme && 80 != $this->httpPort) {
            $port = ':' . $this->httpPort;
        } elseif ('https' === $scheme && 443 != $this->httpsPort) {
            $port = ':' . $this->httpsPort;
        } else {
            $port = '';
        }
        $qs = $request->getQueryString();
        if (null !== $qs) {
            $qs = '?' . $qs;
        }
        $url = $scheme . '://' . $request->getHost() . $port . $request->getBaseUrl() . $request->getPathInfo() . $qs;
        return new RedirectResponse($url, 301);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Security\Http\Firewall;

use _ContaoManager\Psr\Log\LoggerInterface;
use _ContaoManager\Symfony\Component\HttpFoundation\RedirectResponse;
use _ContaoManager\Symfony\Component\HttpFoundation\Request;
use _ContaoManager\Symfony\Component\HttpKernel\Event\RequestEvent;
use _ContaoManager\Symfony\Component\Routing\Generator\UrlGeneratorInterface;
use _ContaoManager\Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
use _ContaoManager\Symfony\Component\Security\Core\Authentication\Token\SwitchUserToken;
use _ContaoManager\Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use _ContaoManager\Symfony\Component\Security\Core\Authorization\AccessDecisionManagerInterface;
use _ContaoManager\Symfony\Component\Security\Core\Exception\AccessDeniedException;
use _ContaoManager\Symfony\Component\Security\Core\Exception\AuthenticationCredentialsNotFoundException;
use _ContaoManager\Symfony\Component\Security\Core\Exception\AuthenticationException;
use _ContaoManager\Symfony\Component\Security\Core\User\UserCheckerInterface;
use _ContaoManager\Symfony\Component\Security\Core\User\UserInterface;
use _ContaoManager\Symfony\Component\Security\Core\User\UserProviderInterface;
use _ContaoManager\Symfony\Component\Security\Http\Event\SwitchUserEvent;
use _ContaoManager\Symfony\Component\Security\Http\SecurityEvents;
use _ContaoManager\Symfony\Contracts\EventDispatcher\EventDispatcherInterface;
/**
 * SwitchUserListener allows a user to impersonate another one temporarily
 * (like the Unix su command).
 *
 * @author Fabien Potencier <fabien@symfony.com>
 *
 * @final
 */
class SwitchUserListener extends AbstractListener
{
    public const EXIT_VALUE = '_exit';
    private TokenStorageInterface $tokenStorage;
    private UserProviderInterface $provider;
    private UserCheckerInterface $userChecker;
    private string $firewallName;
    private AccessDecisionManagerInterface $accessDecisionManager;
    private string $usernameParameter;
    private string $role;
    private ?LoggerInterface $logger;
    private ?EventDispatcherInterface $dispatcher;
    private bool $stateless;
    private ?UrlGeneratorInterface $urlGenerator;
    private ?string $targetRoute;
    public function __construct(TokenStorageInterface $tokenStorage, UserProviderInterface $provider, UserCheckerInterface $userChecker, string $firewallName, AccessDecisionManagerInterface $accessDecisionManager, ?LoggerInterface $logger = null, string $usernameParameter = '_switch_user', string $role = 'ROLE_ALLOWED_TO_SWITCH', ?EventDispatcherInterface $dispatcher = null, bool $stateless = \false, ?UrlGeneratorInterface $urlGenerator = null, ?string $targetRoute = null)
    {
        if ('' === $firewallName) {
            throw new \InvalidArgumentException('$firewallName must not be empty.');
        }
        $this->tokenStorage = $tokenStorage;
        $this->provider = $provider;
        $this->userChecker = $userChecker;
        $this->firewallName = $firewallName;
        $this->accessDecisionManager = $accessDecisionManager;
        $this->usernameParameter = $usernameParameter;
        $this->role = $role;
        $this->logger = $logger;
        $this->dispatcher = $dispatcher;
        $this->stateless = $stateless;
        $this->urlGenerator = $urlGenerator;
        $this->targetRoute = $targetRoute;
    }
    public function supports(Request $request): ?bool
    {
        // usernames can be falsy
        $username = $request->get($this->usernameParameter);
        if (null === $username || '' === $username) {
            $username = $request->headers->get($this->usernameParameter);
        }
        // if it's still "empty", nothing to do.
        if (null === $username || '' === $username) {
            return \false;
        }
        $request->attributes->set('_switch_user_username', $username);
        return \true;
    }
    /**
     * Handles the switch to another user.
     *
     * @throws \LogicException if switching to a user failed
     */
    public function authenticate(RequestEvent $event): void
    {
        $request = $event->getRequest();
        $username = $request->attributes->get('_switch_user_username');
        $request->attributes->remove('_switch_user_username');
        if (null === $this->tokenStorage->getToken()) {
            throw new AuthenticationCredentialsNotFoundException('Could not find original Token object.');
        }
        if (self::EXIT_VALUE === $username) {
            $this->attemptExitUser($request);
        } else {
            try {
                $this->tokenStorage->setToken($this->attemptSwitchUser($request, $username));
            } catch (AuthenticationException $e) {
                // Generate 403 in any conditions to prevent user enumeration vulnerabilities
                throw new AccessDeniedException('Switch User failed: ' . $e->getMessage(), $e);
            }
        }
        if (!$this->stateless) {
            $request->query->remove($this->usernameParameter);
            $request->server->set('QUERY_STRING', http_build_query($request->query->all(), '', '&'));
            $response = new RedirectResponse($this->urlGenerator && $this->targetRoute && self::EXIT_VALUE !== $username ? $this->urlGenerator->generate($this->targetRoute) : $request->getUri(), 302);
            $event->setResponse($response);
        }
    }
    /**
     * Attempts to switch to another user and returns the new token if successfully switched.
     *
     * @throws \LogicException
     * @throws AccessDeniedException
     */
    private function attemptSwitchUser(Request $request, string $username): ?TokenInterface
    {
        $token = $this->tokenStorage->getToken();
        $originalToken = $this->getOriginalToken($token);
        if (null !== $originalToken) {
            if ($token->getUserIdentifier() === $username) {
                return $token;
            }
            // User already switched, exit before seamlessly switching to another user
            $token = $this->attemptExitUser($request);
        }
        $currentUsername = $token->getUserIdentifier();
        $nonExistentUsername = '_' . hash('xxh128', random_bytes(8) . $username);
        // To protect against user enumeration via timing measurements
        // we always load both successfully and unsuccessfully
        try {
            $user = $this->provider->loadUserByIdentifier($username);
            try {
                $this->provider->loadUserByIdentifier($nonExistentUsername);
            } catch (\Exception) {
            }
        } catch (AuthenticationException $e) {
            $this->provider->loadUserByIdentifier($currentUsername);
            throw $e;
        }
        if (\false === $this->accessDecisionManager->decide($token, [$this->role], $user)) {
            $exception = new AccessDeniedException();
            $exception->setAttributes($this->role);
            throw $exception;
        }
        $this->logger?->info('Attempting to switch to user.', ['username' => $username]);
        $this->userChecker->checkPostAuth($user);
        $roles = $user->getRoles();
        $roles[] = 'ROLE_PREVIOUS_ADMIN';
        $originatedFromUri = str_replace('/&', '/?', preg_replace('#[&?]' . $this->usernameParameter . '=[^&]*#', '', $request->getRequestUri()));
        $token = new SwitchUserToken($user, $this->firewallName, $roles, $token, $originatedFromUri);
        if (null !== $this->dispatcher) {
            $switchEvent = new SwitchUserEvent($request, $token->getUser(), $token);
            $this->dispatcher->dispatch($switchEvent, SecurityEvents::SWITCH_USER);
            // use the token from the event in case any listeners have replaced it.
            $token = $switchEvent->getToken();
        }
        return $token;
    }
    /**
     * Attempts to exit from an already switched user and returns the original token.
     *
     * @throws AuthenticationCredentialsNotFoundException
     */
    private function attemptExitUser(Request $request): TokenInterface
    {
        if (null === ($currentToken = $this->tokenStorage->getToken()) || null === $original = $this->getOriginalToken($currentToken)) {
            throw new AuthenticationCredentialsNotFoundException('Could not find original Token object.');
        }
        if (null !== $this->dispatcher && $original->getUser() instanceof UserInterface) {
            $user = $this->provider->refreshUser($original->getUser());
            $original->setUser($user);
            $switchEvent = new SwitchUserEvent($request, $user, $original);
            $this->dispatcher->dispatch($switchEvent, SecurityEvents::SWITCH_USER);
            $original = $switchEvent->getToken();
        }
        $this->tokenStorage->setToken($original);
        return $original;
    }
    private function getOriginalToken(TokenInterface $token): ?TokenInterface
    {
        if ($token instanceof SwitchUserToken) {
            return $token->getOriginalToken();
        }
        return null;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Security\Http\Firewall;

use _ContaoManager\Symfony\Component\HttpFoundation\Request;
use _ContaoManager\Symfony\Component\HttpFoundation\Response;
use _ContaoManager\Symfony\Component\HttpKernel\Event\RequestEvent;
use _ContaoManager\Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
use _ContaoManager\Symfony\Component\Security\Core\Exception\LogoutException;
use _ContaoManager\Symfony\Component\Security\Csrf\CsrfToken;
use _ContaoManager\Symfony\Component\Security\Csrf\CsrfTokenManagerInterface;
use _ContaoManager\Symfony\Component\Security\Http\Event\LogoutEvent;
use _ContaoManager\Symfony\Component\Security\Http\HttpUtils;
use _ContaoManager\Symfony\Component\Security\Http\ParameterBagUtils;
use _ContaoManager\Symfony\Contracts\EventDispatcher\EventDispatcherInterface;
/**
 * LogoutListener logout users.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 *
 * @final
 */
class LogoutListener extends AbstractListener
{
    private TokenStorageInterface $tokenStorage;
    private array $options;
    private HttpUtils $httpUtils;
    private ?CsrfTokenManagerInterface $csrfTokenManager;
    private EventDispatcherInterface $eventDispatcher;
    /**
     * @param array $options An array of options to process a logout attempt
     */
    public function __construct(TokenStorageInterface $tokenStorage, HttpUtils $httpUtils, EventDispatcherInterface $eventDispatcher, array $options = [], ?CsrfTokenManagerInterface $csrfTokenManager = null)
    {
        $this->tokenStorage = $tokenStorage;
        $this->httpUtils = $httpUtils;
        $this->options = array_merge(['csrf_parameter' => '_csrf_token', 'csrf_token_id' => 'logout', 'logout_path' => '/logout'], $options);
        $this->csrfTokenManager = $csrfTokenManager;
        $this->eventDispatcher = $eventDispatcher;
    }
    public function supports(Request $request): ?bool
    {
        return $this->requiresLogout($request);
    }
    /**
     * Performs the logout if requested.
     *
     * If a CsrfTokenManagerInterface instance is available, it will be used to
     * validate the request.
     *
     * @throws LogoutException   if the CSRF token is invalid
     * @throws \RuntimeException if the LogoutEvent listener does not set a response
     */
    public function authenticate(RequestEvent $event): void
    {
        $request = $event->getRequest();
        if (null !== $this->csrfTokenManager) {
            $csrfToken = ParameterBagUtils::getRequestParameterValue($request, $this->options['csrf_parameter']);
            if (!\is_string($csrfToken) || \false === $this->csrfTokenManager->isTokenValid(new CsrfToken($this->options['csrf_token_id'], $csrfToken))) {
                throw new LogoutException('Invalid CSRF token.');
            }
        }
        $logoutEvent = new LogoutEvent($request, $this->tokenStorage->getToken());
        $this->eventDispatcher->dispatch($logoutEvent);
        if (!$response = $logoutEvent->getResponse()) {
            throw new \RuntimeException('No logout listener set the Response, make sure at least the DefaultLogoutListener is registered.');
        }
        $this->tokenStorage->setToken(null);
        $event->setResponse($response);
    }
    /**
     * Whether this request is asking for logout.
     *
     * The default implementation only processed requests to a specific path,
     * but a subclass could change this to logout requests where
     * certain parameters is present.
     */
    protected function requiresLogout(Request $request): bool
    {
        return isset($this->options['logout_path']) && $this->httpUtils->checkRequestPath($request, $this->options['logout_path']);
    }
    public static function getPriority(): int
    {
        return -127;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Security\Http\Controller;

use _ContaoManager\Symfony\Component\HttpFoundation\Request;
use _ContaoManager\Symfony\Component\HttpFoundation\Response;
use _ContaoManager\Symfony\Component\HttpKernel\Controller\ValueResolverInterface;
use _ContaoManager\Symfony\Component\HttpKernel\ControllerMetadata\ArgumentMetadata;
use _ContaoManager\Symfony\Component\HttpKernel\Exception\HttpException;
use _ContaoManager\Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
use _ContaoManager\Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
/**
 * @author Konstantin Myakshin <molodchick@gmail.com>
 */
final class SecurityTokenValueResolver implements ValueResolverInterface
{
    public function __construct(private readonly TokenStorageInterface $tokenStorage)
    {
    }
    /**
     * @return TokenInterface[]
     */
    public function resolve(Request $request, ArgumentMetadata $argument): array
    {
        if (!($type = $argument->getType()) || TokenInterface::class !== $type && !is_subclass_of($type, TokenInterface::class)) {
            return [];
        }
        if (null !== $token = $this->tokenStorage->getToken()) {
            return [$token];
        }
        if ($argument->isNullable()) {
            return [];
        }
        throw new HttpException(Response::HTTP_UNAUTHORIZED, 'A security token is required but the token storage is empty.');
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Security\Http\Controller;

use _ContaoManager\Symfony\Component\HttpFoundation\Request;
use _ContaoManager\Symfony\Component\HttpKernel\Controller\ValueResolverInterface;
use _ContaoManager\Symfony\Component\HttpKernel\ControllerMetadata\ArgumentMetadata;
use _ContaoManager\Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
use _ContaoManager\Symfony\Component\Security\Core\Exception\AccessDeniedException;
use _ContaoManager\Symfony\Component\Security\Core\User\UserInterface;
use _ContaoManager\Symfony\Component\Security\Http\Attribute\CurrentUser;
/**
 * Supports the argument type of {@see UserInterface}.
 *
 * @author Iltar van der Berg <kjarli@gmail.com>
 */
final class UserValueResolver implements ValueResolverInterface
{
    private TokenStorageInterface $tokenStorage;
    public function __construct(TokenStorageInterface $tokenStorage)
    {
        $this->tokenStorage = $tokenStorage;
    }
    /**
     * @deprecated since Symfony 6.2, use resolve() instead
     */
    public function supports(Request $request, ArgumentMetadata $argument): bool
    {
        @trigger_deprecation('symfony/http-kernel', '6.2', 'The "%s()" method is deprecated, use "resolve()" instead.', __METHOD__);
        // with the attribute, the type can be any UserInterface implementation
        // otherwise, the type must be UserInterface
        if (UserInterface::class !== $argument->getType() && !$argument->getAttributesOfType(CurrentUser::class, ArgumentMetadata::IS_INSTANCEOF)) {
            return \false;
        }
        return \true;
    }
    public function resolve(Request $request, ArgumentMetadata $argument): array
    {
        // with the attribute, the type can be any UserInterface implementation
        // otherwise, the type must be UserInterface
        if (UserInterface::class !== $argument->getType() && !$argument->getAttributesOfType(CurrentUser::class, ArgumentMetadata::IS_INSTANCEOF)) {
            return [];
        }
        if (null === $user = $this->tokenStorage->getToken()?->getUser()) {
            // if no user is present but a default value exists we use it to prevent the EntityValueResolver or others
            // from attempting resolution of the User as the current logged in user was requested here
            if ($argument->hasDefaultValue()) {
                return [$argument->getDefaultValue()];
            }
            if (!$argument->isNullable()) {
                throw new AccessDeniedException(\sprintf('There is no logged-in user to pass to $%s, make the argument nullable if you want to allow anonymous access to the action.', $argument->getName()));
            }
            return [null];
        }
        if (null === $argument->getType() || $user instanceof ($argument->getType())) {
            return [$user];
        }
        throw new AccessDeniedException(\sprintf('The logged-in user is an instance of "%s" but a user of type "%s" is expected.', $user::class, $argument->getType()));
    }
}
Security Component - HTTP Integration
=====================================

The Security HTTP component provides an HTTP integration of the Security Core
component. It allows securing (parts of) your application using firewalls and
provides authenticators to authenticate visitors.

Getting Started
---------------

```
$ composer require symfony/security-http
```

Sponsor
-------

The Security component for Symfony 6.4 is [backed][1] by [SymfonyCasts][2].

Learn Symfony faster by watching real projects being built and actively coding
along with them. SymfonyCasts bridges that learning gap, bringing you video
tutorials and coding challenges. Code on!

Help Symfony by [sponsoring][3] its development!

Resources
---------

 * [Documentation](https://symfony.com/doc/current/components/security.html)
 * [Contributing](https://symfony.com/doc/current/contributing/index.html)
 * [Report issues](https://github.com/symfony/symfony/issues) and
   [send Pull Requests](https://github.com/symfony/symfony/pulls)
   in the [main Symfony repository](https://github.com/symfony/symfony)

[1]: https://symfony.com/backers
[2]: https://symfonycasts.com
[3]: https://symfony.com/sponsor
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Security\Http\RememberMe;

use _ContaoManager\Symfony\Component\EventDispatcher\EventSubscriberInterface;
use _ContaoManager\Symfony\Component\HttpKernel\Event\ResponseEvent;
use _ContaoManager\Symfony\Component\HttpKernel\KernelEvents;
/**
 * Adds remember-me cookies to the Response.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 *
 * @final
 */
class ResponseListener implements EventSubscriberInterface
{
    /**
     * This attribute name can be used by the implementation if it needs to set
     * a cookie on the Request when there is no actual Response, yet.
     */
    public const COOKIE_ATTR_NAME = '_security_remember_me_cookie';
    public function onKernelResponse(ResponseEvent $event): void
    {
        if (!$event->isMainRequest()) {
            return;
        }
        $request = $event->getRequest();
        $response = $event->getResponse();
        if ($request->attributes->has(self::COOKIE_ATTR_NAME)) {
            $response->headers->setCookie($request->attributes->get(self::COOKIE_ATTR_NAME));
        }
    }
    public static function getSubscribedEvents(): array
    {
        return [KernelEvents::RESPONSE => 'onKernelResponse'];
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Security\Http\RememberMe;

use _ContaoManager\Psr\Log\LoggerInterface;
use _ContaoManager\Symfony\Component\HttpFoundation\RequestStack;
use _ContaoManager\Symfony\Component\Security\Core\Authentication\RememberMe\PersistentToken;
use _ContaoManager\Symfony\Component\Security\Core\Authentication\RememberMe\TokenProviderInterface;
use _ContaoManager\Symfony\Component\Security\Core\Authentication\RememberMe\TokenVerifierInterface;
use _ContaoManager\Symfony\Component\Security\Core\Exception\AuthenticationException;
use _ContaoManager\Symfony\Component\Security\Core\Exception\CookieTheftException;
use _ContaoManager\Symfony\Component\Security\Core\User\UserInterface;
use _ContaoManager\Symfony\Component\Security\Core\User\UserProviderInterface;
/**
 * Implements remember-me tokens using a {@see TokenProviderInterface}.
 *
 * This requires storing remember-me tokens in a database. This allows
 * more control over the invalidation of remember-me tokens. See
 * {@see SignatureRememberMeHandler} if you don't want to use a database.
 *
 * @author Wouter de Jong <wouter@wouterj.nl>
 */
final class PersistentRememberMeHandler extends AbstractRememberMeHandler
{
    private TokenProviderInterface $tokenProvider;
    private ?TokenVerifierInterface $tokenVerifier;
    /**
     * @param UserProviderInterface       $userProvider
     * @param RequestStack                $requestStack
     * @param array                       $options
     * @param LoggerInterface|null        $logger
     * @param TokenVerifierInterface|null $tokenVerifier
     */
    public function __construct(
        TokenProviderInterface $tokenProvider,
        #[\SensitiveParameter]
        $userProvider,
        $requestStack,
        $options,
        $logger = null,
        $tokenVerifier = null
    )
    {
        if (\is_string($userProvider)) {
            trigger_deprecation('symfony/security-http', '6.3', 'Calling "%s()" with the secret as the second argument is deprecated. The argument will be dropped in 7.0.', __CLASS__);
            $userProvider = $requestStack;
            $requestStack = $options;
            $options = $logger;
            $logger = $tokenVerifier;
            $tokenVerifier = \func_num_args() > 6 ? func_get_arg(6) : null;
        }
        if (!$userProvider instanceof UserProviderInterface) {
            throw new \TypeError(\sprintf('Argument 2 passed to "%s()" must be an instance of "%s", "%s" given.', __CLASS__, UserProviderInterface::class, get_debug_type($userProvider)));
        }
        if (!$requestStack instanceof RequestStack) {
            throw new \TypeError(\sprintf('Argument 3 passed to "%s()" must be an instance of "%s", "%s" given.', __CLASS__, RequestStack::class, get_debug_type($userProvider)));
        }
        if (!\is_array($options)) {
            throw new \TypeError(\sprintf('Argument 4 passed to "%s()" must be an array, "%s" given.', __CLASS__, get_debug_type($userProvider)));
        }
        if (null !== $logger && !$logger instanceof LoggerInterface) {
            throw new \TypeError(\sprintf('Argument 5 passed to "%s()" must be an instance of "%s", "%s" given.', __CLASS__, LoggerInterface::class, get_debug_type($userProvider)));
        }
        if (null !== $tokenVerifier && !$tokenVerifier instanceof TokenVerifierInterface) {
            throw new \TypeError(\sprintf('Argument 6 passed to "%s()" must be an instance of "%s", "%s" given.', __CLASS__, TokenVerifierInterface::class, get_debug_type($userProvider)));
        }
        parent::__construct($userProvider, $requestStack, $options, $logger);
        if (!$tokenVerifier && $tokenProvider instanceof TokenVerifierInterface) {
            $tokenVerifier = $tokenProvider;
        }
        $this->tokenProvider = $tokenProvider;
        $this->tokenVerifier = $tokenVerifier;
    }
    public function createRememberMeCookie(UserInterface $user): void
    {
        $series = random_bytes(66);
        $tokenValue = strtr(base64_encode(substr($series, 33)), '+/=', '-_~');
        $series = strtr(base64_encode(substr($series, 0, 33)), '+/=', '-_~');
        $token = new PersistentToken($user::class, $user->getUserIdentifier(), $series, $tokenValue, new \DateTimeImmutable());
        $this->tokenProvider->createNewToken($token);
        $this->createCookie(RememberMeDetails::fromPersistentToken($token, time() + $this->options['lifetime']));
    }
    public function consumeRememberMeCookie(RememberMeDetails $rememberMeDetails): UserInterface
    {
        if (!str_contains($rememberMeDetails->getValue(), ':')) {
            throw new AuthenticationException('The cookie is incorrectly formatted.');
        }
        [$series, $tokenValue] = explode(':', $rememberMeDetails->getValue(), 2);
        $persistentToken = $this->tokenProvider->loadTokenBySeries($series);
        if ($persistentToken->getUserIdentifier() !== $rememberMeDetails->getUserIdentifier() || $persistentToken->getClass() !== $rememberMeDetails->getUserFqcn()) {
            throw new AuthenticationException('The cookie\'s hash is invalid.');
        }
        // content of $rememberMeDetails is not trustable. this prevents use of this class
        unset($rememberMeDetails);
        if ($this->tokenVerifier) {
            $isTokenValid = $this->tokenVerifier->verifyToken($persistentToken, $tokenValue);
        } else {
            $isTokenValid = hash_equals($persistentToken->getTokenValue(), $tokenValue);
        }
        if (!$isTokenValid) {
            throw new CookieTheftException('This token was already used. The account is possibly compromised.');
        }
        $expires = $persistentToken->getLastUsed()->getTimestamp() + $this->options['lifetime'];
        if ($expires < time()) {
            throw new AuthenticationException('The cookie has expired.');
        }
        return parent::consumeRememberMeCookie(new RememberMeDetails($persistentToken->getClass(), $persistentToken->getUserIdentifier(), $expires, $persistentToken->getLastUsed()->getTimestamp() . ':' . $series . ':' . $tokenValue . ':' . $persistentToken->getClass()));
    }
    public function processRememberMe(RememberMeDetails $rememberMeDetails, UserInterface $user): void
    {
        [$lastUsed, $series, $tokenValue, $class] = explode(':', $rememberMeDetails->getValue(), 4);
        $persistentToken = new PersistentToken($class, $rememberMeDetails->getUserIdentifier(), $series, $tokenValue, new \DateTimeImmutable('@' . $lastUsed));
        // if a token was regenerated less than a minute ago, there is no need to regenerate it
        // if multiple concurrent requests reauthenticate a user we do not want to update the token several times
        if ($persistentToken->getLastUsed()->getTimestamp() + 60 >= time()) {
            return;
        }
        $tokenValue = strtr(base64_encode(random_bytes(33)), '+/=', '-_~');
        $tokenLastUsed = new \DateTime();
        $this->tokenVerifier?->updateExistingToken($persistentToken, $tokenValue, $tokenLastUsed);
        $this->tokenProvider->updateToken($series, $tokenValue, $tokenLastUsed);
        $this->createCookie($rememberMeDetails->withValue($series . ':' . $tokenValue));
    }
    public function clearRememberMeCookie(): void
    {
        parent::clearRememberMeCookie();
        $cookie = $this->requestStack->getMainRequest()->cookies->get($this->options['name']);
        if (null === $cookie) {
            return;
        }
        try {
            $rememberMeDetails = RememberMeDetails::fromRawCookie($cookie);
        } catch (AuthenticationException) {
            // malformed cookie should not fail the response and can be simply ignored
            return;
        }
        [$series] = explode(':', $rememberMeDetails->getValue());
        $this->tokenProvider->deleteTokenBySeries($series);
    }
    /**
     * @internal
     */
    public function getTokenProvider(): TokenProviderInterface
    {
        return $this->tokenProvider;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Security\Http\RememberMe;

use _ContaoManager\Symfony\Component\Security\Core\Exception\AuthenticationException;
use _ContaoManager\Symfony\Component\Security\Core\User\UserInterface;
/**
 * Handles creating and validating remember-me cookies.
 *
 * If you want to add a custom implementation, you want to extend from
 * {@see AbstractRememberMeHandler} instead.
 *
 * @author Wouter de Jong <wouter@wouterj.nl>
 */
interface RememberMeHandlerInterface
{
    /**
     * Creates a remember-me cookie.
     *
     * The actual cookie should be set as an attribute on the main request,
     * which is transformed into a response cookie by {@see ResponseListener}.
     */
    public function createRememberMeCookie(UserInterface $user): void;
    /**
     * Validates the remember-me cookie and returns the associated User.
     *
     * Every cookie should only be used once. This means that this method should also:
     * - Create a new remember-me cookie to be sent with the response (using the
     *   {@see ResponseListener::COOKIE_ATTR_NAME} request attribute);
     * - If you store the token somewhere else (e.g. in a database), invalidate the
     *   stored token.
     *
     * @throws AuthenticationException
     */
    public function consumeRememberMeCookie(RememberMeDetails $rememberMeDetails): UserInterface;
    /**
     * Clears the remember-me cookie.
     *
     * This should set a cookie with a `null` value on the request attribute.
     */
    public function clearRememberMeCookie(): void;
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Security\Http\RememberMe;

use _ContaoManager\Symfony\Component\Security\Core\Authentication\RememberMe\PersistentToken;
use _ContaoManager\Symfony\Component\Security\Core\Exception\AuthenticationException;
/**
 * @author Wouter de Jong <wouter@wouterj.nl>
 */
class RememberMeDetails
{
    public const COOKIE_DELIMITER = ':';
    private string $userFqcn;
    private string $userIdentifier;
    private int $expires;
    private string $value;
    public function __construct(string $userFqcn, string $userIdentifier, int $expires, string $value)
    {
        $this->userFqcn = $userFqcn;
        $this->userIdentifier = $userIdentifier;
        $this->expires = $expires;
        $this->value = $value;
    }
    public static function fromRawCookie(string $rawCookie): self
    {
        if (!str_contains($rawCookie, self::COOKIE_DELIMITER)) {
            $rawCookie = base64_decode($rawCookie);
        }
        $cookieParts = explode(self::COOKIE_DELIMITER, $rawCookie, 4);
        if (4 !== \count($cookieParts)) {
            throw new AuthenticationException('The cookie contains invalid data.');
        }
        if (\false === $cookieParts[1] = base64_decode(strtr($cookieParts[1], '-_~', '+/='), \true)) {
            throw new AuthenticationException('The user identifier contains a character from outside the base64 alphabet.');
        }
        $cookieParts[0] = strtr($cookieParts[0], '.', '\\');
        return new static(...$cookieParts);
    }
    public static function fromPersistentToken(PersistentToken $persistentToken, int $expires): self
    {
        return new static($persistentToken->getClass(), $persistentToken->getUserIdentifier(), $expires, $persistentToken->getSeries() . ':' . $persistentToken->getTokenValue());
    }
    public function withValue(string $value): self
    {
        $details = clone $this;
        $details->value = $value;
        return $details;
    }
    public function getUserFqcn(): string
    {
        return $this->userFqcn;
    }
    public function getUserIdentifier(): string
    {
        return $this->userIdentifier;
    }
    public function getExpires(): int
    {
        return $this->expires;
    }
    public function getValue(): string
    {
        return $this->value;
    }
    public function toString(): string
    {
        // $userIdentifier is encoded because it might contain COOKIE_DELIMITER, we assume other values don't
        return implode(self::COOKIE_DELIMITER, [strtr($this->userFqcn, '\\', '.'), strtr(base64_encode($this->userIdentifier), '+/=', '-_~'), $this->expires, $this->value]);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Security\Http\RememberMe;

use _ContaoManager\Psr\Log\LoggerInterface;
use _ContaoManager\Symfony\Component\HttpFoundation\Cookie;
use _ContaoManager\Symfony\Component\HttpFoundation\RequestStack;
use _ContaoManager\Symfony\Component\Security\Core\Exception\AuthenticationException;
use _ContaoManager\Symfony\Component\Security\Core\User\UserInterface;
use _ContaoManager\Symfony\Component\Security\Core\User\UserProviderInterface;
/**
 * @author Wouter de Jong <wouter@wouterj.nl>
 */
abstract class AbstractRememberMeHandler implements RememberMeHandlerInterface
{
    private UserProviderInterface $userProvider;
    protected $requestStack;
    protected $options;
    protected $logger;
    public function __construct(UserProviderInterface $userProvider, RequestStack $requestStack, array $options = [], ?LoggerInterface $logger = null)
    {
        $this->userProvider = $userProvider;
        $this->requestStack = $requestStack;
        $this->options = $options + ['name' => 'REMEMBERME', 'lifetime' => 31536000, 'path' => '/', 'domain' => null, 'secure' => \false, 'httponly' => \true, 'samesite' => null, 'always_remember_me' => \false, 'remember_me_parameter' => '_remember_me'];
        $this->logger = $logger;
    }
    /**
     * Checks if the RememberMeDetails is a valid cookie to login the given User.
     *
     * This method should also:
     * - Create a new remember-me cookie to be sent with the response (using {@see createCookie()});
     * - If you store the token somewhere else (e.g. in a database), invalidate the stored token.
     *
     * @throws AuthenticationException If the remember-me details are not accepted
     */
    abstract protected function processRememberMe(RememberMeDetails $rememberMeDetails, UserInterface $user): void;
    public function consumeRememberMeCookie(RememberMeDetails $rememberMeDetails): UserInterface
    {
        try {
            $user = $this->userProvider->loadUserByIdentifier($rememberMeDetails->getUserIdentifier());
        } catch (AuthenticationException $e) {
            throw $e;
        }
        if (!$user instanceof UserInterface) {
            throw new \LogicException(\sprintf('The UserProviderInterface implementation must return an instance of UserInterface, but returned "%s".', get_debug_type($user)));
        }
        $this->processRememberMe($rememberMeDetails, $user);
        $this->logger?->info('Remember-me cookie accepted.');
        return $user;
    }
    public function clearRememberMeCookie(): void
    {
        $this->logger?->debug('Clearing remember-me cookie.', ['name' => $this->options['name']]);
        $this->createCookie(null);
    }
    /**
     * Creates the remember-me cookie using the correct configuration.
     *
     * @param RememberMeDetails|null $rememberMeDetails The details for the cookie, or null to clear the remember-me cookie
     *
     * @return void
     */
    protected function createCookie(?RememberMeDetails $rememberMeDetails)
    {
        $request = $this->requestStack->getMainRequest();
        if (!$request) {
            throw new \LogicException('Cannot create the remember-me cookie; no master request available.');
        }
        // the ResponseListener configures the cookie saved in this attribute on the final response object
        $request->attributes->set(ResponseListener::COOKIE_ATTR_NAME, new Cookie($this->options['name'], $rememberMeDetails?->toString(), $rememberMeDetails?->getExpires() ?? 1, $this->options['path'], $this->options['domain'], $this->options['secure'] ?? $request->isSecure(), $this->options['httponly'], \false, $this->options['samesite']));
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Security\Http\RememberMe;

use _ContaoManager\Psr\Log\LoggerInterface;
use _ContaoManager\Symfony\Component\HttpFoundation\RequestStack;
use _ContaoManager\Symfony\Component\Security\Core\Exception\AuthenticationException;
use _ContaoManager\Symfony\Component\Security\Core\Signature\Exception\ExpiredSignatureException;
use _ContaoManager\Symfony\Component\Security\Core\Signature\Exception\InvalidSignatureException;
use _ContaoManager\Symfony\Component\Security\Core\Signature\SignatureHasher;
use _ContaoManager\Symfony\Component\Security\Core\User\UserInterface;
use _ContaoManager\Symfony\Component\Security\Core\User\UserProviderInterface;
/**
 * Implements safe remember-me cookies using the {@see SignatureHasher}.
 *
 * This handler doesn't require a database for the remember-me tokens.
 * However, it cannot invalidate a specific user session, all sessions for
 * that user will be invalidated instead. Use {@see PersistentRememberMeHandler}
 * if you need this.
 *
 * @author Wouter de Jong <wouter@wouterj.nl>
 */
final class SignatureRememberMeHandler extends AbstractRememberMeHandler
{
    private SignatureHasher $signatureHasher;
    public function __construct(SignatureHasher $signatureHasher, UserProviderInterface $userProvider, RequestStack $requestStack, array $options, ?LoggerInterface $logger = null)
    {
        parent::__construct($userProvider, $requestStack, $options, $logger);
        $this->signatureHasher = $signatureHasher;
    }
    public function createRememberMeCookie(UserInterface $user): void
    {
        $expires = time() + $this->options['lifetime'];
        $value = $this->signatureHasher->computeSignatureHash($user, $expires);
        $details = new RememberMeDetails($user::class, $user->getUserIdentifier(), $expires, $value);
        $this->createCookie($details);
    }
    public function consumeRememberMeCookie(RememberMeDetails $rememberMeDetails): UserInterface
    {
        try {
            $this->signatureHasher->acceptSignatureHash($rememberMeDetails->getUserIdentifier(), $rememberMeDetails->getExpires(), $rememberMeDetails->getValue());
        } catch (InvalidSignatureException $e) {
            throw new AuthenticationException('The cookie\'s hash is invalid.', 0, $e);
        } catch (ExpiredSignatureException $e) {
            throw new AuthenticationException('The cookie has expired.', 0, $e);
        }
        return parent::consumeRememberMeCookie($rememberMeDetails);
    }
    public function processRememberMe(RememberMeDetails $rememberMeDetails, UserInterface $user): void
    {
        try {
            $this->signatureHasher->verifySignatureHash($user, $rememberMeDetails->getExpires(), $rememberMeDetails->getValue());
        } catch (InvalidSignatureException $e) {
            throw new AuthenticationException('The cookie\'s hash is invalid.', 0, $e);
        } catch (ExpiredSignatureException $e) {
            throw new AuthenticationException('The cookie has expired.', 0, $e);
        }
        $this->createRememberMeCookie($user);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Security\Http\EntryPoint;

use _ContaoManager\Symfony\Component\HttpFoundation\Request;
use _ContaoManager\Symfony\Component\HttpFoundation\Response;
use _ContaoManager\Symfony\Component\Security\Core\Exception\AuthenticationException;
/**
 * Implement this interface for any classes that will be called to "start"
 * the authentication process (see method for more details).
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
interface AuthenticationEntryPointInterface
{
    /**
     * Returns a response that directs the user to authenticate.
     *
     * This is called when an anonymous request accesses a resource that
     * requires authentication. The job of this method is to return some
     * response that "helps" the user start into the authentication process.
     *
     * Examples:
     *
     * - For a form login, you might redirect to the login page
     *
     *     return new RedirectResponse('/login');
     *
     * - For an API token authentication system, you return a 401 response
     *
     *     return new Response('Auth header required', 401);
     *
     * @return Response
     */
    public function start(Request $request, ?AuthenticationException $authException = null);
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Security\Http\EntryPoint\Exception;

use _ContaoManager\Symfony\Component\HttpKernel\Attribute\WithHttpStatus;
/**
 * Thrown by generic decorators when a decorated authenticator does not implement
 * {@see AuthenticationEntryPointInterface}.
 *
 * @author Robin Chalas <robin.chalas@gmail.com>
 */
#[WithHttpStatus(401)]
class NotAnEntryPointException extends \RuntimeException
{
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Security\Http;

use _ContaoManager\Symfony\Component\HttpFoundation\RedirectResponse;
use _ContaoManager\Symfony\Component\HttpFoundation\Request;
use _ContaoManager\Symfony\Component\Routing\Exception\MethodNotAllowedException;
use _ContaoManager\Symfony\Component\Routing\Exception\ResourceNotFoundException;
use _ContaoManager\Symfony\Component\Routing\Generator\UrlGeneratorInterface;
use _ContaoManager\Symfony\Component\Routing\Matcher\RequestMatcherInterface;
use _ContaoManager\Symfony\Component\Routing\Matcher\UrlMatcherInterface;
/**
 * Encapsulates the logic needed to create sub-requests, redirect the user, and match URLs.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class HttpUtils
{
    private ?UrlGeneratorInterface $urlGenerator;
    private UrlMatcherInterface|RequestMatcherInterface|null $urlMatcher;
    private ?string $domainRegexp;
    private ?string $secureDomainRegexp;
    /**
     * @param $domainRegexp       A regexp the target of HTTP redirections must match, scheme included
     * @param $secureDomainRegexp A regexp the target of HTTP redirections must match when the scheme is "https"
     *
     * @throws \InvalidArgumentException
     */
    public function __construct(?UrlGeneratorInterface $urlGenerator = null, UrlMatcherInterface|RequestMatcherInterface|null $urlMatcher = null, ?string $domainRegexp = null, ?string $secureDomainRegexp = null)
    {
        $this->urlGenerator = $urlGenerator;
        $this->urlMatcher = $urlMatcher;
        $this->domainRegexp = $domainRegexp;
        $this->secureDomainRegexp = $secureDomainRegexp;
    }
    /**
     * Creates a redirect Response.
     *
     * @param string $path   A path (an absolute path (/foo), an absolute URL (http://...), or a route name (foo))
     * @param int    $status The HTTP status code (302 "Found" by default)
     */
    public function createRedirectResponse(Request $request, string $path, int $status = 302): RedirectResponse
    {
        if (null !== $this->secureDomainRegexp && 'https' === $this->urlMatcher->getContext()->getScheme() && preg_match('#^https?:[/\\\\]{2,}+[^/]++#i', $path, $host) && !preg_match(\sprintf($this->secureDomainRegexp, preg_quote($request->getHttpHost())), $host[0])) {
            $path = '/';
        }
        if (null !== $this->domainRegexp && preg_match('#^https?:[/\\\\]{2,}+[^/]++#i', $path, $host) && !preg_match(\sprintf($this->domainRegexp, preg_quote($request->getHttpHost())), $host[0])) {
            $path = '/';
        }
        return new RedirectResponse($this->generateUri($request, $path), $status);
    }
    /**
     * Creates a Request.
     *
     * @param string $path A path (an absolute path (/foo), an absolute URL (http://...), or a route name (foo))
     */
    public function createRequest(Request $request, string $path): Request
    {
        if ($trustedProxies = Request::getTrustedProxies()) {
            Request::setTrustedProxies([], Request::getTrustedHeaderSet());
        }
        $context = $this->urlGenerator?->getContext();
        if ($baseUrl = $context?->getBaseUrl()) {
            $context->setBaseUrl('');
        }
        try {
            $newRequest = Request::create($this->generateUri($request, $path), 'get', [], $request->cookies->all(), [], $request->server->all());
        } finally {
            if ($trustedProxies) {
                Request::setTrustedProxies($trustedProxies, Request::getTrustedHeaderSet());
            }
            if ($baseUrl) {
                $context->setBaseUrl($baseUrl);
            }
        }
        static $setSession;
        $setSession ??= \Closure::bind(static function ($newRequest, $request) {
            $newRequest->session = $request->session;
        }, null, Request::class);
        $setSession($newRequest, $request);
        if ($request->attributes->has(SecurityRequestAttributes::AUTHENTICATION_ERROR)) {
            $newRequest->attributes->set(SecurityRequestAttributes::AUTHENTICATION_ERROR, $request->attributes->get(SecurityRequestAttributes::AUTHENTICATION_ERROR));
        }
        if ($request->attributes->has(SecurityRequestAttributes::ACCESS_DENIED_ERROR)) {
            $newRequest->attributes->set(SecurityRequestAttributes::ACCESS_DENIED_ERROR, $request->attributes->get(SecurityRequestAttributes::ACCESS_DENIED_ERROR));
        }
        if ($request->attributes->has(SecurityRequestAttributes::LAST_USERNAME)) {
            $newRequest->attributes->set(SecurityRequestAttributes::LAST_USERNAME, $request->attributes->get(SecurityRequestAttributes::LAST_USERNAME));
        }
        if ($request->get('_format')) {
            $newRequest->attributes->set('_format', $request->get('_format'));
        }
        if ($request->getDefaultLocale() !== $request->getLocale()) {
            $newRequest->setLocale($request->getLocale());
        }
        return $newRequest;
    }
    /**
     * Checks that a given path matches the Request.
     *
     * @param string $path A path (an absolute path (/foo), an absolute URL (http://...), or a route name (foo))
     *
     * @return bool true if the path is the same as the one from the Request, false otherwise
     */
    public function checkRequestPath(Request $request, string $path): bool
    {
        if ('/' !== $path[0]) {
            // Shortcut if request has already been matched before
            if ($request->attributes->has('_route')) {
                return $path === $request->attributes->get('_route');
            }
            try {
                // matching a request is more powerful than matching a URL path + context, so try that first
                if ($this->urlMatcher instanceof RequestMatcherInterface) {
                    $parameters = $this->urlMatcher->matchRequest($request);
                } else {
                    $parameters = $this->urlMatcher->match($request->getPathInfo());
                }
                return isset($parameters['_route']) && $path === $parameters['_route'];
            } catch (MethodNotAllowedException) {
                return \false;
            } catch (ResourceNotFoundException) {
                return \false;
            }
        }
        return $path === rawurldecode($request->getPathInfo());
    }
    /**
     * Generates a URI, based on the given path or absolute URL.
     *
     * @param string $path A path (an absolute path (/foo), an absolute URL (http://...), or a route name (foo))
     *
     * @throws \LogicException
     */
    public function generateUri(Request $request, string $path): string
    {
        $url = parse_url($path);
        if ('' === $path || isset($url['scheme'], $url['host'])) {
            return $path;
        }
        if ('/' === $path[0]) {
            return $request->getUriForPath($path);
        }
        if (null === $this->urlGenerator) {
            throw new \LogicException('You must provide a UrlGeneratorInterface instance to be able to use routes.');
        }
        $url = $this->urlGenerator->generate($path, $request->attributes->all(), UrlGeneratorInterface::ABSOLUTE_URL);
        // unnecessary query string parameters must be removed from URL
        // (ie. query parameters that are presents in $attributes)
        // fortunately, they all are, so we have to remove entire query string
        $position = strpos($url, '?');
        if (\false !== $position) {
            $fragment = parse_url($url, \PHP_URL_FRAGMENT);
            $url = substr($url, 0, $position);
            // fragment must be preserved
            if ($fragment) {
                $url .= "#{$fragment}";
            }
        }
        return $url;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Security\Http;

use _ContaoManager\Symfony\Component\HttpFoundation\Request;
use _ContaoManager\Symfony\Component\Security\Http\Firewall\ExceptionListener;
use _ContaoManager\Symfony\Component\Security\Http\Firewall\FirewallListenerInterface;
use _ContaoManager\Symfony\Component\Security\Http\Firewall\LogoutListener;
/**
 * This interface must be implemented by firewall maps.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
interface FirewallMapInterface
{
    /**
     * Returns the authentication listeners, and the exception listener to use
     * for the given request.
     *
     * If there are no authentication listeners, the first inner array must be
     * empty.
     *
     * If there is no exception listener, the second element of the outer array
     * must be null.
     *
     * If there is no logout listener, the third element of the outer array
     * must be null.
     *
     * @return array{iterable<mixed, callable|FirewallListenerInterface>, ExceptionListener, LogoutListener}
     */
    public function getListeners(Request $request);
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Security\Http\Authenticator\Token;

use _ContaoManager\Symfony\Component\Security\Core\Authentication\Token\AbstractToken;
use _ContaoManager\Symfony\Component\Security\Core\User\UserInterface;
class PostAuthenticationToken extends AbstractToken
{
    private string $firewallName;
    /**
     * @param string[] $roles An array of roles
     *
     * @throws \InvalidArgumentException
     */
    public function __construct(UserInterface $user, string $firewallName, array $roles)
    {
        parent::__construct($roles);
        if ('' === $firewallName) {
            throw new \InvalidArgumentException('$firewallName must not be empty.');
        }
        $this->setUser($user);
        $this->firewallName = $firewallName;
        // required for compatibility with Symfony 5.4
        if (method_exists($this, 'setAuthenticated')) {
            // this token is meant to be used after authentication success, so it is always authenticated
            $this->setAuthenticated(\true, \false);
        }
    }
    /**
     * This is meant to be only a token, where credentials
     * have already been used and are thus cleared.
     */
    public function getCredentials(): mixed
    {
        return [];
    }
    public function getFirewallName(): string
    {
        return $this->firewallName;
    }
    public function __serialize(): array
    {
        return [$this->firewallName, parent::__serialize()];
    }
    public function __unserialize(array $data): void
    {
        [$this->firewallName, $parentData] = $data;
        parent::__unserialize($parentData);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Security\Http\Authenticator;

/**
 * This is an extension of the authenticator interface that may
 * be used by interactive authenticators.
 *
 * Interactive login requires explicit user action (e.g. a login
 * form). Implementing this interface will dispatch the InteractiveLoginEvent
 * upon successful login.
 *
 * @author Wouter de Jong <wouter@wouterj.nl>
 */
interface InteractiveAuthenticatorInterface extends AuthenticatorInterface
{
    /**
     * Should return true to make this authenticator perform
     * an interactive login.
     */
    public function isInteractive(): bool;
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Security\Http\Authenticator;

use _ContaoManager\Symfony\Component\HttpFoundation\RedirectResponse;
use _ContaoManager\Symfony\Component\HttpFoundation\Request;
use _ContaoManager\Symfony\Component\HttpFoundation\Response;
use _ContaoManager\Symfony\Component\Security\Core\Exception\AuthenticationException;
use _ContaoManager\Symfony\Component\Security\Http\EntryPoint\AuthenticationEntryPointInterface;
use _ContaoManager\Symfony\Component\Security\Http\SecurityRequestAttributes;
/**
 * A base class to make form login authentication easier!
 *
 * @author Ryan Weaver <ryan@symfonycasts.com>
 */
abstract class AbstractLoginFormAuthenticator extends AbstractAuthenticator implements AuthenticationEntryPointInterface, InteractiveAuthenticatorInterface
{
    /**
     * Return the URL to the login page.
     */
    abstract protected function getLoginUrl(Request $request): string;
    /**
     * Override to change the request conditions that have to be
     * matched in order to handle the login form submit.
     *
     * This default implementation handles all POST requests to the
     * login path (@see getLoginUrl()).
     */
    public function supports(Request $request): bool
    {
        return $request->isMethod('POST') && $this->getLoginUrl($request) === $request->getBaseUrl() . $request->getPathInfo();
    }
    /**
     * Override to change what happens after a bad username/password is submitted.
     */
    public function onAuthenticationFailure(Request $request, AuthenticationException $exception): Response
    {
        if ($request->hasSession()) {
            $request->getSession()->set(SecurityRequestAttributes::AUTHENTICATION_ERROR, $exception);
        }
        $url = $this->getLoginUrl($request);
        return new RedirectResponse($url);
    }
    /**
     * Override to control what happens when the user hits a secure page
     * but isn't logged in yet.
     */
    public function start(Request $request, ?AuthenticationException $authException = null): Response
    {
        $url = $this->getLoginUrl($request);
        return new RedirectResponse($url);
    }
    public function isInteractive(): bool
    {
        return \true;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Security\Http\Authenticator;

use _ContaoManager\Symfony\Component\HttpFoundation\Request;
use _ContaoManager\Symfony\Component\HttpFoundation\Response;
use _ContaoManager\Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use _ContaoManager\Symfony\Component\Security\Core\Exception\AuthenticationException;
use _ContaoManager\Symfony\Component\Security\Http\Authenticator\Passport\Passport;
/**
 * The interface for all authenticators.
 *
 * @author Ryan Weaver <ryan@symfonycasts.com>
 * @author Amaury Leroux de Lens <amaury@lerouxdelens.com>
 * @author Wouter de Jong <wouter@wouterj.nl>
 */
interface AuthenticatorInterface
{
    /**
     * Does the authenticator support the given Request?
     *
     * If this returns true, authenticate() will be called. If false, the authenticator will be skipped.
     *
     * Returning null means authenticate() can be called lazily when accessing the token storage.
     */
    public function supports(Request $request): ?bool;
    /**
     * Create a passport for the current request.
     *
     * The passport contains the user, credentials and any additional information
     * that has to be checked by the Symfony Security system. For example, a login
     * form authenticator will probably return a passport containing the user, the
     * presented password and the CSRF token value.
     *
     * You may throw any AuthenticationException in this method in case of error (e.g.
     * a UserNotFoundException when the user cannot be found).
     *
     * @throws AuthenticationException
     */
    public function authenticate(Request $request): Passport;
    /**
     * Create an authenticated token for the given user.
     *
     * If you don't care about which token class is used or don't really
     * understand what a "token" is, you can skip this method by extending
     * the AbstractAuthenticator class from your authenticator.
     *
     * @see AbstractAuthenticator
     *
     * @param Passport $passport The passport returned from authenticate()
     */
    public function createToken(Passport $passport, string $firewallName): TokenInterface;
    /**
     * Called when authentication executed and was successful!
     *
     * This should return the Response sent back to the user, like a
     * RedirectResponse to the last page they visited.
     *
     * If you return null, the current request will continue, and the user
     * will be authenticated. This makes sense, for example, with an API.
     */
    public function onAuthenticationSuccess(Request $request, TokenInterface $token, string $firewallName): ?Response;
    /**
     * Called when authentication executed, but failed (e.g. wrong username password).
     *
     * This should return the Response sent back to the user, like a
     * RedirectResponse to the login page or a 403 response.
     *
     * If you return null, the request will continue, but the user will
     * not be authenticated. This is probably not what you want to do.
     */
    public function onAuthenticationFailure(Request $request, AuthenticationException $exception): ?Response;
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Security\Http\Authenticator;

use _ContaoManager\Symfony\Component\Security\Core\User\UserInterface;
/**
 * This wrapper serves as a marker interface to indicate badge user loaders that should not be overridden by the
 * default user provider.
 *
 * @internal
 */
final class FallbackUserLoader
{
    public function __construct(private $inner)
    {
    }
    public function __invoke(mixed ...$args): ?UserInterface
    {
        return ($this->inner)(...$args);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Security\Http\Authenticator;

use _ContaoManager\Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use _ContaoManager\Symfony\Component\Security\Http\Authenticator\Passport\Passport;
use _ContaoManager\Symfony\Component\Security\Http\Authenticator\Token\PostAuthenticationToken;
/**
 * An optional base class that creates the necessary tokens for you.
 *
 * @author Ryan Weaver <ryan@symfonycasts.com>
 */
abstract class AbstractAuthenticator implements AuthenticatorInterface
{
    /**
     * Shortcut to create a PostAuthenticationToken for you, if you don't really
     * care about which authenticated token you're using.
     */
    public function createToken(Passport $passport, string $firewallName): TokenInterface
    {
        return new PostAuthenticationToken($passport->getUser(), $firewallName, $passport->getUser()->getRoles());
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Security\Http\Authenticator;

use _ContaoManager\Psr\Log\LoggerInterface;
use _ContaoManager\Symfony\Component\HttpFoundation\Request;
use _ContaoManager\Symfony\Component\HttpFoundation\Response;
use _ContaoManager\Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use _ContaoManager\Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken;
use _ContaoManager\Symfony\Component\Security\Core\Exception\AuthenticationException;
use _ContaoManager\Symfony\Component\Security\Core\User\PasswordUpgraderInterface;
use _ContaoManager\Symfony\Component\Security\Core\User\UserProviderInterface;
use _ContaoManager\Symfony\Component\Security\Http\Authenticator\Passport\Badge\PasswordUpgradeBadge;
use _ContaoManager\Symfony\Component\Security\Http\Authenticator\Passport\Badge\UserBadge;
use _ContaoManager\Symfony\Component\Security\Http\Authenticator\Passport\Credentials\PasswordCredentials;
use _ContaoManager\Symfony\Component\Security\Http\Authenticator\Passport\Passport;
use _ContaoManager\Symfony\Component\Security\Http\EntryPoint\AuthenticationEntryPointInterface;
/**
 * @author Wouter de Jong <wouter@wouterj.nl>
 * @author Fabien Potencier <fabien@symfony.com>
 *
 * @final
 */
class HttpBasicAuthenticator implements AuthenticatorInterface, AuthenticationEntryPointInterface
{
    private string $realmName;
    private UserProviderInterface $userProvider;
    private ?LoggerInterface $logger;
    public function __construct(string $realmName, UserProviderInterface $userProvider, ?LoggerInterface $logger = null)
    {
        $this->realmName = $realmName;
        $this->userProvider = $userProvider;
        $this->logger = $logger;
    }
    public function start(Request $request, ?AuthenticationException $authException = null): Response
    {
        $response = new Response();
        $response->headers->set('WWW-Authenticate', \sprintf('Basic realm="%s"', $this->realmName));
        $response->setStatusCode(401);
        return $response;
    }
    public function supports(Request $request): ?bool
    {
        return $request->headers->has('PHP_AUTH_USER');
    }
    public function authenticate(Request $request): Passport
    {
        $username = $request->headers->get('PHP_AUTH_USER');
        $password = $request->headers->get('PHP_AUTH_PW', '');
        $userBadge = new UserBadge($username, $this->userProvider->loadUserByIdentifier(...));
        $passport = new Passport($userBadge, new PasswordCredentials($password));
        if ($this->userProvider instanceof PasswordUpgraderInterface) {
            $passport->addBadge(new PasswordUpgradeBadge($password, $this->userProvider));
        }
        return $passport;
    }
    public function createToken(Passport $passport, string $firewallName): TokenInterface
    {
        return new UsernamePasswordToken($passport->getUser(), $firewallName, $passport->getUser()->getRoles());
    }
    public function onAuthenticationSuccess(Request $request, TokenInterface $token, string $firewallName): ?Response
    {
        return null;
    }
    public function onAuthenticationFailure(Request $request, AuthenticationException $exception): ?Response
    {
        $this->logger?->info('Basic authentication failed for user.', ['username' => $request->headers->get('PHP_AUTH_USER'), 'exception' => $exception]);
        return $this->start($request, $exception);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Security\Http\Authenticator;

use _ContaoManager\Symfony\Component\HttpFoundation\Request;
use _ContaoManager\Symfony\Component\HttpFoundation\Response;
use _ContaoManager\Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use _ContaoManager\Symfony\Component\Security\Core\Exception\AuthenticationException;
use _ContaoManager\Symfony\Component\Security\Http\Authentication\AuthenticationFailureHandlerInterface;
use _ContaoManager\Symfony\Component\Security\Http\Authentication\AuthenticationSuccessHandlerInterface;
use _ContaoManager\Symfony\Component\Security\Http\Authenticator\Passport\Badge\RememberMeBadge;
use _ContaoManager\Symfony\Component\Security\Http\Authenticator\Passport\Badge\UserBadge;
use _ContaoManager\Symfony\Component\Security\Http\Authenticator\Passport\Passport;
use _ContaoManager\Symfony\Component\Security\Http\Authenticator\Passport\SelfValidatingPassport;
use _ContaoManager\Symfony\Component\Security\Http\HttpUtils;
use _ContaoManager\Symfony\Component\Security\Http\LoginLink\Exception\InvalidLoginLinkAuthenticationException;
use _ContaoManager\Symfony\Component\Security\Http\LoginLink\Exception\InvalidLoginLinkExceptionInterface;
use _ContaoManager\Symfony\Component\Security\Http\LoginLink\LoginLinkHandlerInterface;
/**
 * @author Ryan Weaver <ryan@symfonycasts.com>
 */
final class LoginLinkAuthenticator extends AbstractAuthenticator implements InteractiveAuthenticatorInterface
{
    private LoginLinkHandlerInterface $loginLinkHandler;
    private HttpUtils $httpUtils;
    private AuthenticationSuccessHandlerInterface $successHandler;
    private AuthenticationFailureHandlerInterface $failureHandler;
    private array $options;
    public function __construct(LoginLinkHandlerInterface $loginLinkHandler, HttpUtils $httpUtils, AuthenticationSuccessHandlerInterface $successHandler, AuthenticationFailureHandlerInterface $failureHandler, array $options)
    {
        $this->loginLinkHandler = $loginLinkHandler;
        $this->httpUtils = $httpUtils;
        $this->successHandler = $successHandler;
        $this->failureHandler = $failureHandler;
        $this->options = $options + ['check_post_only' => \false];
    }
    public function supports(Request $request): ?bool
    {
        return ($this->options['check_post_only'] ? $request->isMethod('POST') : \true) && $this->httpUtils->checkRequestPath($request, $this->options['check_route']);
    }
    public function authenticate(Request $request): Passport
    {
        if (!$username = $request->get('user')) {
            throw new InvalidLoginLinkAuthenticationException('Missing user from link.');
        }
        $userBadge = new UserBadge($username, function () use ($request) {
            try {
                $user = $this->loginLinkHandler->consumeLoginLink($request);
            } catch (InvalidLoginLinkExceptionInterface $e) {
                throw new InvalidLoginLinkAuthenticationException('Login link could not be validated.', 0, $e);
            }
            return $user;
        });
        return new SelfValidatingPassport($userBadge, [new RememberMeBadge()]);
    }
    public function onAuthenticationSuccess(Request $request, TokenInterface $token, string $firewallName): ?Response
    {
        return $this->successHandler->onAuthenticationSuccess($request, $token);
    }
    public function onAuthenticationFailure(Request $request, AuthenticationException $exception): Response
    {
        return $this->failureHandler->onAuthenticationFailure($request, $exception);
    }
    public function isInteractive(): bool
    {
        return \true;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Security\Http\Authenticator;

use _ContaoManager\Symfony\Component\HttpFoundation\JsonResponse;
use _ContaoManager\Symfony\Component\HttpFoundation\Request;
use _ContaoManager\Symfony\Component\HttpFoundation\Response;
use _ContaoManager\Symfony\Component\HttpKernel\Exception\BadRequestHttpException;
use _ContaoManager\Symfony\Component\PropertyAccess\Exception\AccessException;
use _ContaoManager\Symfony\Component\PropertyAccess\PropertyAccess;
use _ContaoManager\Symfony\Component\PropertyAccess\PropertyAccessorInterface;
use _ContaoManager\Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use _ContaoManager\Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken;
use _ContaoManager\Symfony\Component\Security\Core\Exception\AuthenticationException;
use _ContaoManager\Symfony\Component\Security\Core\User\PasswordUpgraderInterface;
use _ContaoManager\Symfony\Component\Security\Core\User\UserProviderInterface;
use _ContaoManager\Symfony\Component\Security\Http\Authentication\AuthenticationFailureHandlerInterface;
use _ContaoManager\Symfony\Component\Security\Http\Authentication\AuthenticationSuccessHandlerInterface;
use _ContaoManager\Symfony\Component\Security\Http\Authenticator\Passport\Badge\PasswordUpgradeBadge;
use _ContaoManager\Symfony\Component\Security\Http\Authenticator\Passport\Badge\RememberMeBadge;
use _ContaoManager\Symfony\Component\Security\Http\Authenticator\Passport\Badge\UserBadge;
use _ContaoManager\Symfony\Component\Security\Http\Authenticator\Passport\Credentials\PasswordCredentials;
use _ContaoManager\Symfony\Component\Security\Http\Authenticator\Passport\Passport;
use _ContaoManager\Symfony\Component\Security\Http\HttpUtils;
use _ContaoManager\Symfony\Contracts\Translation\TranslatorInterface;
/**
 * Provides a stateless implementation of an authentication via
 * a JSON document composed of a username and a password.
 *
 * @author Kévin Dunglas <dunglas@gmail.com>
 * @author Wouter de Jong <wouter@wouterj.nl>
 *
 * @final
 */
class JsonLoginAuthenticator implements InteractiveAuthenticatorInterface
{
    private array $options;
    private HttpUtils $httpUtils;
    private UserProviderInterface $userProvider;
    private PropertyAccessorInterface $propertyAccessor;
    private ?AuthenticationSuccessHandlerInterface $successHandler;
    private ?AuthenticationFailureHandlerInterface $failureHandler;
    private ?TranslatorInterface $translator = null;
    public function __construct(HttpUtils $httpUtils, UserProviderInterface $userProvider, ?AuthenticationSuccessHandlerInterface $successHandler = null, ?AuthenticationFailureHandlerInterface $failureHandler = null, array $options = [], ?PropertyAccessorInterface $propertyAccessor = null)
    {
        $this->options = array_merge(['username_path' => 'username', 'password_path' => 'password'], $options);
        $this->httpUtils = $httpUtils;
        $this->successHandler = $successHandler;
        $this->failureHandler = $failureHandler;
        $this->userProvider = $userProvider;
        $this->propertyAccessor = $propertyAccessor ?: PropertyAccess::createPropertyAccessor();
    }
    public function supports(Request $request): ?bool
    {
        if (!str_contains($request->getRequestFormat() ?? '', 'json') && !str_contains($request->getContentTypeFormat() ?? '', 'json')) {
            return \false;
        }
        if (isset($this->options['check_path']) && !$this->httpUtils->checkRequestPath($request, $this->options['check_path'])) {
            return \false;
        }
        return \true;
    }
    public function authenticate(Request $request): Passport
    {
        try {
            $data = json_decode($request->getContent());
            if (!$data instanceof \stdClass) {
                throw new BadRequestHttpException('Invalid JSON.');
            }
            $credentials = $this->getCredentials($data);
        } catch (BadRequestHttpException $e) {
            $request->setRequestFormat('json');
            throw $e;
        }
        $userBadge = new UserBadge($credentials['username'], $this->userProvider->loadUserByIdentifier(...));
        $passport = new Passport($userBadge, new PasswordCredentials($credentials['password']), [new RememberMeBadge((array) $data)]);
        if ($this->userProvider instanceof PasswordUpgraderInterface) {
            $passport->addBadge(new PasswordUpgradeBadge($credentials['password'], $this->userProvider));
        }
        return $passport;
    }
    public function createToken(Passport $passport, string $firewallName): TokenInterface
    {
        return new UsernamePasswordToken($passport->getUser(), $firewallName, $passport->getUser()->getRoles());
    }
    public function onAuthenticationSuccess(Request $request, TokenInterface $token, string $firewallName): ?Response
    {
        if (null === $this->successHandler) {
            return null;
            // let the original request continue
        }
        return $this->successHandler->onAuthenticationSuccess($request, $token);
    }
    public function onAuthenticationFailure(Request $request, AuthenticationException $exception): ?Response
    {
        if (null === $this->failureHandler) {
            if (null !== $this->translator) {
                $errorMessage = $this->translator->trans($exception->getMessageKey(), $exception->getMessageData(), 'security');
            } else {
                $errorMessage = strtr($exception->getMessageKey(), $exception->getMessageData());
            }
            return new JsonResponse(['error' => $errorMessage], JsonResponse::HTTP_UNAUTHORIZED);
        }
        return $this->failureHandler->onAuthenticationFailure($request, $exception);
    }
    public function isInteractive(): bool
    {
        return \true;
    }
    public function setTranslator(TranslatorInterface $translator): void
    {
        $this->translator = $translator;
    }
    private function getCredentials(\stdClass $data): array
    {
        $credentials = [];
        try {
            $credentials['username'] = $this->propertyAccessor->getValue($data, $this->options['username_path']);
            if (!\is_string($credentials['username'])) {
                throw new BadRequestHttpException(\sprintf('The key "%s" must be a string.', $this->options['username_path']));
            }
        } catch (AccessException $e) {
            throw new BadRequestHttpException(\sprintf('The key "%s" must be provided.', $this->options['username_path']), $e);
        }
        try {
            $credentials['password'] = $this->propertyAccessor->getValue($data, $this->options['password_path']);
            $this->propertyAccessor->setValue($data, $this->options['password_path'], null);
            if (!\is_string($credentials['password'])) {
                throw new BadRequestHttpException(\sprintf('The key "%s" must be a string.', $this->options['password_path']));
            }
        } catch (AccessException $e) {
            throw new BadRequestHttpException(\sprintf('The key "%s" must be provided.', $this->options['password_path']), $e);
        }
        if ('' === $credentials['username'] || '' === $credentials['password']) {
            trigger_deprecation('symfony/security', '6.2', 'Passing an empty string as username or password parameter is deprecated.');
        }
        return $credentials;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Security\Http\Authenticator\Passport;

use _ContaoManager\Symfony\Component\Security\Http\Authenticator\Passport\Badge\BadgeInterface;
use _ContaoManager\Symfony\Component\Security\Http\Authenticator\Passport\Badge\UserBadge;
/**
 * An implementation used when there are no credentials to be checked (e.g.
 * API token authentication).
 *
 * @author Wouter de Jong <wouter@wouterj.nl>
 */
class SelfValidatingPassport extends Passport
{
    /**
     * @param BadgeInterface[] $badges
     */
    public function __construct(UserBadge $userBadge, array $badges = [])
    {
        $this->addBadge($userBadge);
        foreach ($badges as $badge) {
            $this->addBadge($badge);
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Security\Http\Authenticator\Passport;

use _ContaoManager\Symfony\Component\Security\Core\User\UserInterface;
use _ContaoManager\Symfony\Component\Security\Http\Authenticator\Passport\Badge\BadgeInterface;
use _ContaoManager\Symfony\Component\Security\Http\Authenticator\Passport\Badge\UserBadge;
use _ContaoManager\Symfony\Component\Security\Http\Authenticator\Passport\Credentials\CredentialsInterface;
/**
 * A Passport contains all security-related information that needs to be
 * validated during authentication.
 *
 * A passport badge can be used to add any additional information to the
 * passport.
 *
 * @author Wouter de Jong <wouter@wouterj.nl>
 */
class Passport
{
    protected $user;
    private array $badges = [];
    private array $attributes = [];
    /**
     * @param CredentialsInterface $credentials The credentials to check for this authentication, use
     *                                          SelfValidatingPassport if no credentials should be checked
     * @param BadgeInterface[]     $badges
     */
    public function __construct(UserBadge $userBadge, CredentialsInterface $credentials, array $badges = [])
    {
        $this->addBadge($userBadge);
        $this->addBadge($credentials);
        foreach ($badges as $badge) {
            $this->addBadge($badge);
        }
    }
    public function getUser(): UserInterface
    {
        if (!isset($this->user)) {
            if (!$this->hasBadge(UserBadge::class)) {
                throw new \LogicException('Cannot get the Security user, no username or UserBadge configured for this passport.');
            }
            $this->user = $this->getBadge(UserBadge::class)->getUser();
        }
        return $this->user;
    }
    /**
     * Adds a new security badge.
     *
     * A passport can hold only one instance of the same security badge.
     * This method replaces the current badge if it is already set on this
     * passport.
     *
     * @param string|null $badgeFqcn A FQCN to which the badge should be mapped to.
     *                               This allows replacing a built-in badge by a custom one using
     *                               e.g. addBadge(new MyCustomUserBadge(), UserBadge::class)
     *
     * @return $this
     */
    public function addBadge(BadgeInterface $badge): static
    {
        $badgeFqcn = $badge::class;
        if (2 === \func_num_args()) {
            $badgeFqcn = func_get_arg(1);
            if (!\is_string($badgeFqcn)) {
                throw new \LogicException(\sprintf('Second argument of "%s" must be a string.', __METHOD__));
            }
        }
        $this->badges[$badgeFqcn] = $badge;
        return $this;
    }
    public function hasBadge(string $badgeFqcn): bool
    {
        return isset($this->badges[$badgeFqcn]);
    }
    /**
     * @template TBadge of BadgeInterface
     *
     * @param class-string<TBadge> $badgeFqcn
     *
     * @return TBadge|null
     */
    public function getBadge(string $badgeFqcn): ?BadgeInterface
    {
        return $this->badges[$badgeFqcn] ?? null;
    }
    /**
     * @return array<class-string<BadgeInterface>, BadgeInterface>
     */
    public function getBadges(): array
    {
        return $this->badges;
    }
    public function setAttribute(string $name, mixed $value): void
    {
        $this->attributes[$name] = $value;
    }
    public function getAttribute(string $name, mixed $default = null): mixed
    {
        return $this->attributes[$name] ?? $default;
    }
    public function getAttributes(): array
    {
        return $this->attributes;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Security\Http\Authenticator\Passport\Credentials;

use _ContaoManager\Symfony\Component\Security\Http\Authenticator\Passport\Badge\BadgeInterface;
/**
 * Credentials are a special badge used to explicitly mark the
 * credential check of an authenticator.
 *
 * @author Wouter de Jong <wouter@wouterj.nl>
 */
interface CredentialsInterface extends BadgeInterface
{
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Security\Http\Authenticator\Passport\Credentials;

use _ContaoManager\Symfony\Component\Security\Core\Exception\BadCredentialsException;
use _ContaoManager\Symfony\Component\Security\Core\User\UserInterface;
/**
 * Implements credentials checking using a custom checker function.
 *
 * @author Wouter de Jong <wouter@wouterj.nl>
 *
 * @final
 */
class CustomCredentials implements CredentialsInterface
{
    private \Closure $customCredentialsChecker;
    private mixed $credentials;
    private bool $resolved = \false;
    /**
     * @param callable $customCredentialsChecker the check function. If this function does not return `true`, a
     *                                           BadCredentialsException is thrown. You may also throw a more
     *                                           specific exception in the function.
     */
    public function __construct(callable $customCredentialsChecker, mixed $credentials)
    {
        $this->customCredentialsChecker = $customCredentialsChecker(...);
        $this->credentials = $credentials;
    }
    public function executeCustomChecker(UserInterface $user): void
    {
        $checker = $this->customCredentialsChecker;
        if (\true !== $checker($this->credentials, $user)) {
            throw new BadCredentialsException('Credentials check failed as the callable passed to CustomCredentials did not return "true".');
        }
        $this->resolved = \true;
    }
    public function isResolved(): bool
    {
        return $this->resolved;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Security\Http\Authenticator\Passport\Credentials;

use _ContaoManager\Symfony\Component\Security\Core\Exception\LogicException;
/**
 * Implements password credentials.
 *
 * These plaintext passwords are checked by the UserPasswordHasher during
 * authentication.
 *
 * @author Wouter de Jong <wouter@wouterj.nl>
 *
 * @final
 */
class PasswordCredentials implements CredentialsInterface
{
    private ?string $password = null;
    private bool $resolved = \false;
    public function __construct(
        #[\SensitiveParameter]
        string $password
    )
    {
        $this->password = $password;
    }
    public function getPassword(): string
    {
        if (null === $this->password) {
            throw new LogicException('The credentials are erased as another listener already verified these credentials.');
        }
        return $this->password;
    }
    /**
     * @internal
     */
    public function markResolved(): void
    {
        $this->resolved = \true;
        $this->password = null;
    }
    public function isResolved(): bool
    {
        return $this->resolved;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Security\Http\Authenticator\Passport\Badge;

use _ContaoManager\Symfony\Component\Security\Http\Authenticator\AbstractPreAuthenticatedAuthenticator;
/**
 * Marks the authentication as being pre-authenticated.
 *
 * This disables pre-authentication user checkers.
 *
 * @see AbstractPreAuthenticatedAuthenticator
 *
 * @author Wouter de Jong <wouter@wouterj.nl>
 *
 * @final
 */
class PreAuthenticatedUserBadge implements BadgeInterface
{
    public function isResolved(): bool
    {
        return \true;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Security\Http\Authenticator\Passport\Badge;

use _ContaoManager\Symfony\Component\Security\Http\EventListener\CsrfProtectionListener;
/**
 * Adds automatic CSRF tokens checking capabilities to this authenticator.
 *
 * @see CsrfProtectionListener
 *
 * @author Wouter de Jong <wouter@wouterj.nl>
 *
 * @final
 */
class CsrfTokenBadge implements BadgeInterface
{
    private bool $resolved = \false;
    private string $csrfTokenId;
    private ?string $csrfToken;
    /**
     * @param string      $csrfTokenId An arbitrary string used to generate the value of the CSRF token.
     *                                 Using a different string for each authenticator improves its security.
     * @param string|null $csrfToken   The CSRF token presented in the request, if any
     */
    public function __construct(
        string $csrfTokenId,
        #[\SensitiveParameter]
        ?string $csrfToken
    )
    {
        $this->csrfTokenId = $csrfTokenId;
        $this->csrfToken = $csrfToken;
    }
    public function getCsrfTokenId(): string
    {
        return $this->csrfTokenId;
    }
    public function getCsrfToken(): ?string
    {
        return $this->csrfToken;
    }
    /**
     * @internal
     */
    public function markResolved(): void
    {
        $this->resolved = \true;
    }
    public function isResolved(): bool
    {
        return $this->resolved;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Security\Http\Authenticator\Passport\Badge;

use _ContaoManager\Symfony\Component\Security\Core\Exception\LogicException;
use _ContaoManager\Symfony\Component\Security\Core\User\PasswordUpgraderInterface;
/**
 * Adds automatic password migration, if enabled and required in the password encoder.
 *
 * @see PasswordUpgraderInterface
 *
 * @author Wouter de Jong <wouter@wouterj.nl>
 *
 * @final
 */
class PasswordUpgradeBadge implements BadgeInterface
{
    private ?string $plaintextPassword = null;
    private ?PasswordUpgraderInterface $passwordUpgrader;
    /**
     * @param string                         $plaintextPassword The presented password, used in the rehash
     * @param PasswordUpgraderInterface|null $passwordUpgrader  The password upgrader, defaults to the UserProvider if null
     */
    public function __construct(
        #[\SensitiveParameter]
        string $plaintextPassword,
        ?PasswordUpgraderInterface $passwordUpgrader = null
    )
    {
        $this->plaintextPassword = $plaintextPassword;
        $this->passwordUpgrader = $passwordUpgrader;
    }
    public function getAndErasePlaintextPassword(): string
    {
        $password = $this->plaintextPassword;
        if (null === $password) {
            throw new LogicException('The password is erased as another listener already used this badge.');
        }
        $this->plaintextPassword = null;
        return $password;
    }
    public function getPasswordUpgrader(): ?PasswordUpgraderInterface
    {
        return $this->passwordUpgrader;
    }
    public function isResolved(): bool
    {
        return \true;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Security\Http\Authenticator\Passport\Badge;

use _ContaoManager\Symfony\Component\Security\Core\Exception\AuthenticationException;
use _ContaoManager\Symfony\Component\Security\Core\Exception\AuthenticationServiceException;
use _ContaoManager\Symfony\Component\Security\Core\Exception\BadCredentialsException;
use _ContaoManager\Symfony\Component\Security\Core\Exception\UserNotFoundException;
use _ContaoManager\Symfony\Component\Security\Core\User\UserInterface;
use _ContaoManager\Symfony\Component\Security\Http\EventListener\UserProviderListener;
/**
 * Represents the user in the authentication process.
 *
 * It uses an identifier (e.g. email, or username) and
 * "user loader" to load the related User object.
 *
 * @author Wouter de Jong <wouter@wouterj.nl>
 */
class UserBadge implements BadgeInterface
{
    public const MAX_USERNAME_LENGTH = 4096;
    private string $userIdentifier;
    /** @var callable|null */
    private $userLoader;
    private UserInterface $user;
    private ?array $attributes;
    /**
     * Initializes the user badge.
     *
     * You must provide a $userIdentifier. This is a unique string representing the
     * user for this authentication (e.g. the email if authentication is done using
     * email + password; or a string combining email+company if authentication is done
     * based on email *and* company name). This string can be used for e.g. login throttling.
     *
     * Optionally, you may pass a user loader. This callable receives the $userIdentifier
     * as argument and must return a UserInterface object (otherwise an AuthenticationServiceException
     * is thrown). If this is not set, the default user provider will be used with
     * $userIdentifier as username.
     */
    public function __construct(string $userIdentifier, ?callable $userLoader = null, ?array $attributes = null)
    {
        if (\strlen($userIdentifier) > self::MAX_USERNAME_LENGTH) {
            throw new BadCredentialsException('Username too long.');
        }
        $this->userIdentifier = $userIdentifier;
        $this->userLoader = $userLoader;
        $this->attributes = $attributes;
    }
    public function getUserIdentifier(): string
    {
        return $this->userIdentifier;
    }
    public function getAttributes(): ?array
    {
        return $this->attributes;
    }
    /**
     * @throws AuthenticationException when the user cannot be found
     */
    public function getUser(): UserInterface
    {
        if (isset($this->user)) {
            return $this->user;
        }
        if (null === $this->userLoader) {
            throw new \LogicException(\sprintf('No user loader is configured, did you forget to register the "%s" listener?', UserProviderListener::class));
        }
        if (null === $this->getAttributes()) {
            $user = ($this->userLoader)($this->userIdentifier);
        } else {
            $user = ($this->userLoader)($this->userIdentifier, $this->getAttributes());
        }
        // No user has been found via the $this->userLoader callback
        if (null === $user) {
            $exception = new UserNotFoundException();
            $exception->setUserIdentifier($this->userIdentifier);
            throw $exception;
        }
        if (!$user instanceof UserInterface) {
            throw new AuthenticationServiceException(\sprintf('The user provider must return a UserInterface object, "%s" given.', get_debug_type($user)));
        }
        return $this->user = $user;
    }
    public function getUserLoader(): ?callable
    {
        return $this->userLoader;
    }
    public function setUserLoader(callable $userLoader): void
    {
        $this->userLoader = $userLoader;
    }
    public function isResolved(): bool
    {
        return \true;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Security\Http\Authenticator\Passport\Badge;

use _ContaoManager\Symfony\Component\Security\Http\EventListener\CheckRememberMeConditionsListener;
/**
 * Adds support for remember me to this authenticator.
 *
 * The presence of this badge doesn't create the remember-me cookie. The actual
 * cookie is only created if this badge is enabled. By default, this is done
 * by the {@see CheckRememberMeConditionsListener} if all conditions are met.
 *
 * @author Wouter de Jong <wouter@wouterj.nl>
 *
 * @final
 */
class RememberMeBadge implements BadgeInterface
{
    private bool $enabled = \false;
    public function __construct(public readonly array $parameters = [])
    {
    }
    /**
     * Enables remember-me cookie creation.
     *
     * In most cases, {@see CheckRememberMeConditionsListener} enables this
     * automatically if always_remember_me is true or the remember_me_parameter
     * exists in the request.
     *
     * @return $this
     */
    public function enable(): static
    {
        $this->enabled = \true;
        return $this;
    }
    /**
     * Disables remember-me cookie creation.
     *
     * The default is disabled, this can be called to suppress creation
     * after it was enabled.
     *
     * @return $this
     */
    public function disable(): static
    {
        $this->enabled = \false;
        return $this;
    }
    public function isEnabled(): bool
    {
        return $this->enabled;
    }
    public function isResolved(): bool
    {
        return \true;
        // remember me does not need to be explicitly resolved
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Security\Http\Authenticator\Passport\Badge;

/**
 * Passport badges allow to add more information to a passport (e.g. a CSRF token).
 *
 * @author Wouter de Jong <wouter@wouterj.nl>
 */
interface BadgeInterface
{
    /**
     * Checks if this badge is resolved by the security system.
     *
     * After authentication, all badges must return `true` in this method in order
     * for the authentication to succeed.
     */
    public function isResolved(): bool;
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Security\Http\Authenticator;

use _ContaoManager\Psr\Log\LoggerInterface;
use _ContaoManager\Symfony\Component\HttpFoundation\Request;
use _ContaoManager\Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
use _ContaoManager\Symfony\Component\Security\Core\Exception\BadCredentialsException;
use _ContaoManager\Symfony\Component\Security\Core\User\UserProviderInterface;
/**
 * This authenticator authenticates pre-authenticated (by the
 * webserver) X.509 certificates.
 *
 * @author Wouter de Jong <wouter@wouterj.nl>
 * @author Fabien Potencier <fabien@symfony.com>
 *
 * @final
 */
class X509Authenticator extends AbstractPreAuthenticatedAuthenticator
{
    private string $userKey;
    private string $credentialsKey;
    private string $credentialUserIdentifier;
    public function __construct(UserProviderInterface $userProvider, TokenStorageInterface $tokenStorage, string $firewallName, string $userKey = 'SSL_CLIENT_S_DN_Email', string $credentialsKey = 'SSL_CLIENT_S_DN', ?LoggerInterface $logger = null, string $credentialUserIdentifier = 'emailAddress')
    {
        parent::__construct($userProvider, $tokenStorage, $firewallName, $logger);
        $this->userKey = $userKey;
        $this->credentialsKey = $credentialsKey;
        $this->credentialUserIdentifier = $credentialUserIdentifier;
    }
    protected function extractUsername(Request $request): string
    {
        $username = null;
        if ($request->server->has($this->userKey)) {
            $username = $request->server->get($this->userKey);
        } elseif ($request->server->has($this->credentialsKey) && preg_match('#' . preg_quote($this->credentialUserIdentifier, '#') . '=([^,/]++)#', $request->server->get($this->credentialsKey), $matches)) {
            $username = trim($matches[1]);
        }
        if (null === $username) {
            throw new BadCredentialsException(\sprintf('SSL credentials not found: "%s", "%s".', $this->userKey, $this->credentialsKey));
        }
        return $username;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Security\Http\Authenticator;

use _ContaoManager\Symfony\Component\HttpFoundation\Request;
use _ContaoManager\Symfony\Component\HttpFoundation\Response;
use _ContaoManager\Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use _ContaoManager\Symfony\Component\Security\Core\Exception\AuthenticationException;
use _ContaoManager\Symfony\Component\Security\Core\Exception\BadCredentialsException;
use _ContaoManager\Symfony\Component\Security\Core\User\UserProviderInterface;
use _ContaoManager\Symfony\Component\Security\Http\AccessToken\AccessTokenExtractorInterface;
use _ContaoManager\Symfony\Component\Security\Http\AccessToken\AccessTokenHandlerInterface;
use _ContaoManager\Symfony\Component\Security\Http\Authentication\AuthenticationFailureHandlerInterface;
use _ContaoManager\Symfony\Component\Security\Http\Authentication\AuthenticationSuccessHandlerInterface;
use _ContaoManager\Symfony\Component\Security\Http\Authenticator\Passport\Passport;
use _ContaoManager\Symfony\Component\Security\Http\Authenticator\Passport\SelfValidatingPassport;
use _ContaoManager\Symfony\Component\Security\Http\Authenticator\Token\PostAuthenticationToken;
use _ContaoManager\Symfony\Contracts\Translation\TranslatorInterface;
/**
 * Provides an implementation of the RFC6750 of an authentication via
 * an access token.
 *
 * @author Florent Morselli <florent.morselli@spomky-labs.com>
 */
class AccessTokenAuthenticator implements AuthenticatorInterface
{
    private ?TranslatorInterface $translator = null;
    public function __construct(private readonly AccessTokenHandlerInterface $accessTokenHandler, private readonly AccessTokenExtractorInterface $accessTokenExtractor, private readonly ?UserProviderInterface $userProvider = null, private readonly ?AuthenticationSuccessHandlerInterface $successHandler = null, private readonly ?AuthenticationFailureHandlerInterface $failureHandler = null, private readonly ?string $realm = null)
    {
    }
    public function supports(Request $request): ?bool
    {
        return null === $this->accessTokenExtractor->extractAccessToken($request) ? \false : null;
    }
    public function authenticate(Request $request): Passport
    {
        $accessToken = $this->accessTokenExtractor->extractAccessToken($request);
        if (!$accessToken) {
            throw new BadCredentialsException('Invalid credentials.');
        }
        $userBadge = $this->accessTokenHandler->getUserBadgeFrom($accessToken);
        if ($this->userProvider && (null === $userBadge->getUserLoader() || $userBadge->getUserLoader() instanceof FallbackUserLoader)) {
            $userBadge->setUserLoader($this->userProvider->loadUserByIdentifier(...));
        }
        return new SelfValidatingPassport($userBadge);
    }
    public function createToken(Passport $passport, string $firewallName): TokenInterface
    {
        return new PostAuthenticationToken($passport->getUser(), $firewallName, $passport->getUser()->getRoles());
    }
    public function onAuthenticationSuccess(Request $request, TokenInterface $token, string $firewallName): ?Response
    {
        return $this->successHandler?->onAuthenticationSuccess($request, $token);
    }
    public function onAuthenticationFailure(Request $request, AuthenticationException $exception): Response
    {
        if (null !== $this->failureHandler) {
            return $this->failureHandler->onAuthenticationFailure($request, $exception);
        }
        if (null !== $this->translator) {
            $errorMessage = $this->translator->trans($exception->getMessageKey(), $exception->getMessageData(), 'security');
        } else {
            $errorMessage = strtr($exception->getMessageKey(), $exception->getMessageData());
        }
        return new Response(null, Response::HTTP_UNAUTHORIZED, ['WWW-Authenticate' => $this->getAuthenticateHeader($errorMessage)]);
    }
    /**
     * @return void
     */
    public function setTranslator(?TranslatorInterface $translator)
    {
        $this->translator = $translator;
    }
    /**
     * @see https://datatracker.ietf.org/doc/html/rfc6750#section-3
     */
    private function getAuthenticateHeader(?string $errorDescription = null): string
    {
        $data = ['realm' => $this->realm, 'error' => 'invalid_token', 'error_description' => $errorDescription];
        $values = [];
        foreach ($data as $k => $v) {
            if (null === $v || '' === $v) {
                continue;
            }
            $values[] = \sprintf('%s="%s"', $k, $v);
        }
        return \sprintf('Bearer %s', implode(',', $values));
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Security\Http\Authenticator;

use _ContaoManager\Psr\Log\LoggerInterface;
use _ContaoManager\Symfony\Component\HttpFoundation\Request;
use _ContaoManager\Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
use _ContaoManager\Symfony\Component\Security\Core\Exception\BadCredentialsException;
use _ContaoManager\Symfony\Component\Security\Core\User\UserProviderInterface;
/**
 * This authenticator authenticates a remote user.
 *
 * @author Wouter de Jong <wouter@wouterj.nl>
 * @author Fabien Potencier <fabien@symfony.com>
 * @author Maxime Douailin <maxime.douailin@gmail.com>
 *
 * @final
 *
 * @internal in Symfony 5.1
 */
class RemoteUserAuthenticator extends AbstractPreAuthenticatedAuthenticator
{
    private string $userKey;
    public function __construct(UserProviderInterface $userProvider, TokenStorageInterface $tokenStorage, string $firewallName, string $userKey = 'REMOTE_USER', ?LoggerInterface $logger = null)
    {
        parent::__construct($userProvider, $tokenStorage, $firewallName, $logger);
        $this->userKey = $userKey;
    }
    protected function extractUsername(Request $request): ?string
    {
        if (!$request->server->has($this->userKey)) {
            throw new BadCredentialsException(\sprintf('User key was not found: "%s".', $this->userKey));
        }
        return $request->server->get($this->userKey) ?: null;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Security\Http\Authenticator;

use _ContaoManager\Symfony\Component\HttpFoundation\Request;
use _ContaoManager\Symfony\Component\HttpFoundation\Response;
use _ContaoManager\Symfony\Component\HttpKernel\Exception\BadRequestHttpException;
use _ContaoManager\Symfony\Component\HttpKernel\HttpKernelInterface;
use _ContaoManager\Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use _ContaoManager\Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken;
use _ContaoManager\Symfony\Component\Security\Core\Exception\AuthenticationException;
use _ContaoManager\Symfony\Component\Security\Core\User\PasswordUpgraderInterface;
use _ContaoManager\Symfony\Component\Security\Core\User\UserProviderInterface;
use _ContaoManager\Symfony\Component\Security\Http\Authentication\AuthenticationFailureHandlerInterface;
use _ContaoManager\Symfony\Component\Security\Http\Authentication\AuthenticationSuccessHandlerInterface;
use _ContaoManager\Symfony\Component\Security\Http\Authenticator\Passport\Badge\CsrfTokenBadge;
use _ContaoManager\Symfony\Component\Security\Http\Authenticator\Passport\Badge\PasswordUpgradeBadge;
use _ContaoManager\Symfony\Component\Security\Http\Authenticator\Passport\Badge\RememberMeBadge;
use _ContaoManager\Symfony\Component\Security\Http\Authenticator\Passport\Badge\UserBadge;
use _ContaoManager\Symfony\Component\Security\Http\Authenticator\Passport\Credentials\PasswordCredentials;
use _ContaoManager\Symfony\Component\Security\Http\Authenticator\Passport\Passport;
use _ContaoManager\Symfony\Component\Security\Http\HttpUtils;
use _ContaoManager\Symfony\Component\Security\Http\ParameterBagUtils;
use _ContaoManager\Symfony\Component\Security\Http\SecurityRequestAttributes;
/**
 * @author Wouter de Jong <wouter@wouterj.nl>
 * @author Fabien Potencier <fabien@symfony.com>
 *
 * @final
 */
class FormLoginAuthenticator extends AbstractLoginFormAuthenticator
{
    private HttpUtils $httpUtils;
    private UserProviderInterface $userProvider;
    private AuthenticationSuccessHandlerInterface $successHandler;
    private AuthenticationFailureHandlerInterface $failureHandler;
    private array $options;
    private HttpKernelInterface $httpKernel;
    public function __construct(HttpUtils $httpUtils, UserProviderInterface $userProvider, AuthenticationSuccessHandlerInterface $successHandler, AuthenticationFailureHandlerInterface $failureHandler, array $options)
    {
        $this->httpUtils = $httpUtils;
        $this->userProvider = $userProvider;
        $this->successHandler = $successHandler;
        $this->failureHandler = $failureHandler;
        $this->options = array_merge(['username_parameter' => '_username', 'password_parameter' => '_password', 'check_path' => '/login_check', 'post_only' => \true, 'form_only' => \false, 'enable_csrf' => \false, 'csrf_parameter' => '_csrf_token', 'csrf_token_id' => 'authenticate'], $options);
    }
    protected function getLoginUrl(Request $request): string
    {
        return $this->httpUtils->generateUri($request, $this->options['login_path']);
    }
    public function supports(Request $request): bool
    {
        return ($this->options['post_only'] ? $request->isMethod('POST') : \true) && $this->httpUtils->checkRequestPath($request, $this->options['check_path']) && ($this->options['form_only'] ? 'form' === $request->getContentTypeFormat() : \true);
    }
    public function authenticate(Request $request): Passport
    {
        $credentials = $this->getCredentials($request);
        $userBadge = new UserBadge($credentials['username'], $this->userProvider->loadUserByIdentifier(...));
        $passport = new Passport($userBadge, new PasswordCredentials($credentials['password']), [new RememberMeBadge()]);
        if ($this->options['enable_csrf']) {
            $passport->addBadge(new CsrfTokenBadge($this->options['csrf_token_id'], $credentials['csrf_token']));
        }
        if ($this->userProvider instanceof PasswordUpgraderInterface) {
            $passport->addBadge(new PasswordUpgradeBadge($credentials['password'], $this->userProvider));
        }
        return $passport;
    }
    public function createToken(Passport $passport, string $firewallName): TokenInterface
    {
        return new UsernamePasswordToken($passport->getUser(), $firewallName, $passport->getUser()->getRoles());
    }
    public function onAuthenticationSuccess(Request $request, TokenInterface $token, string $firewallName): ?Response
    {
        return $this->successHandler->onAuthenticationSuccess($request, $token);
    }
    public function onAuthenticationFailure(Request $request, AuthenticationException $exception): Response
    {
        return $this->failureHandler->onAuthenticationFailure($request, $exception);
    }
    private function getCredentials(Request $request): array
    {
        $credentials = [];
        $credentials['csrf_token'] = ParameterBagUtils::getRequestParameterValue($request, $this->options['csrf_parameter']);
        if ($this->options['post_only']) {
            $credentials['username'] = ParameterBagUtils::getParameterBagValue($request->request, $this->options['username_parameter']);
            $credentials['password'] = ParameterBagUtils::getParameterBagValue($request->request, $this->options['password_parameter']) ?? '';
        } else {
            $credentials['username'] = ParameterBagUtils::getRequestParameterValue($request, $this->options['username_parameter']);
            $credentials['password'] = ParameterBagUtils::getRequestParameterValue($request, $this->options['password_parameter']) ?? '';
        }
        if (!\is_string($credentials['username']) && !$credentials['username'] instanceof \Stringable) {
            throw new BadRequestHttpException(\sprintf('The key "%s" must be a string, "%s" given.', $this->options['username_parameter'], \gettype($credentials['username'])));
        }
        $credentials['username'] = trim($credentials['username']);
        $request->getSession()->set(SecurityRequestAttributes::LAST_USERNAME, $credentials['username']);
        if (!\is_string($credentials['password']) && (!\is_object($credentials['password']) || !method_exists($credentials['password'], '__toString'))) {
            throw new BadRequestHttpException(\sprintf('The key "%s" must be a string, "%s" given.', $this->options['password_parameter'], \gettype($credentials['password'])));
        }
        if (!\is_string($credentials['csrf_token'] ?? '') && (!\is_object($credentials['csrf_token']) || !method_exists($credentials['csrf_token'], '__toString'))) {
            throw new BadRequestHttpException(\sprintf('The key "%s" must be a string, "%s" given.', $this->options['csrf_parameter'], \gettype($credentials['csrf_token'])));
        }
        return $credentials;
    }
    public function setHttpKernel(HttpKernelInterface $httpKernel): void
    {
        $this->httpKernel = $httpKernel;
    }
    public function start(Request $request, ?AuthenticationException $authException = null): Response
    {
        if (!$this->options['use_forward']) {
            return parent::start($request, $authException);
        }
        $subRequest = $this->httpUtils->createRequest($request, $this->options['login_path']);
        $response = $this->httpKernel->handle($subRequest, HttpKernelInterface::SUB_REQUEST);
        if (200 === $response->getStatusCode()) {
            $response->setStatusCode(401);
        }
        return $response;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Security\Http\Authenticator;

use _ContaoManager\Psr\Log\LoggerInterface;
use _ContaoManager\Symfony\Component\HttpFoundation\Request;
use _ContaoManager\Symfony\Component\HttpFoundation\Response;
use _ContaoManager\Symfony\Component\Security\Core\Authentication\Token\PreAuthenticatedToken;
use _ContaoManager\Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
use _ContaoManager\Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use _ContaoManager\Symfony\Component\Security\Core\Exception\AuthenticationException;
use _ContaoManager\Symfony\Component\Security\Core\Exception\BadCredentialsException;
use _ContaoManager\Symfony\Component\Security\Core\User\UserProviderInterface;
use _ContaoManager\Symfony\Component\Security\Http\Authenticator\Passport\Badge\PreAuthenticatedUserBadge;
use _ContaoManager\Symfony\Component\Security\Http\Authenticator\Passport\Badge\UserBadge;
use _ContaoManager\Symfony\Component\Security\Http\Authenticator\Passport\Passport;
use _ContaoManager\Symfony\Component\Security\Http\Authenticator\Passport\SelfValidatingPassport;
/**
 * The base authenticator for authenticators to use pre-authenticated
 * requests (e.g. using certificates).
 *
 * @author Wouter de Jong <wouter@wouterj.nl>
 * @author Fabien Potencier <fabien@symfony.com>
 *
 * @internal
 */
abstract class AbstractPreAuthenticatedAuthenticator implements InteractiveAuthenticatorInterface
{
    private UserProviderInterface $userProvider;
    private TokenStorageInterface $tokenStorage;
    private string $firewallName;
    private ?LoggerInterface $logger;
    public function __construct(UserProviderInterface $userProvider, TokenStorageInterface $tokenStorage, string $firewallName, ?LoggerInterface $logger = null)
    {
        $this->userProvider = $userProvider;
        $this->tokenStorage = $tokenStorage;
        $this->firewallName = $firewallName;
        $this->logger = $logger;
    }
    /**
     * Returns the username of the pre-authenticated user.
     *
     * This authenticator is skipped if null is returned or a custom
     * BadCredentialsException is thrown.
     */
    abstract protected function extractUsername(Request $request): ?string;
    public function supports(Request $request): ?bool
    {
        try {
            $username = $this->extractUsername($request);
        } catch (BadCredentialsException $e) {
            $this->clearToken($e);
            $this->logger?->debug('Skipping pre-authenticated authenticator as a BadCredentialsException is thrown.', ['exception' => $e, 'authenticator' => static::class]);
            return \false;
        }
        if (null === $username) {
            $this->logger?->debug('Skipping pre-authenticated authenticator no username could be extracted.', ['authenticator' => static::class]);
            return \false;
        }
        // do not overwrite already stored tokens from the same user (i.e. from the session)
        $token = $this->tokenStorage->getToken();
        if ($token instanceof PreAuthenticatedToken && $this->firewallName === $token->getFirewallName() && $token->getUserIdentifier() === $username) {
            $this->logger?->debug('Skipping pre-authenticated authenticator as the user already has an existing session.', ['authenticator' => static::class]);
            return \false;
        }
        $request->attributes->set('_pre_authenticated_username', $username);
        return \true;
    }
    public function authenticate(Request $request): Passport
    {
        $userBadge = new UserBadge($request->attributes->get('_pre_authenticated_username'), $this->userProvider->loadUserByIdentifier(...));
        return new SelfValidatingPassport($userBadge, [new PreAuthenticatedUserBadge()]);
    }
    public function createToken(Passport $passport, string $firewallName): TokenInterface
    {
        return new PreAuthenticatedToken($passport->getUser(), $firewallName, $passport->getUser()->getRoles());
    }
    public function onAuthenticationSuccess(Request $request, TokenInterface $token, string $firewallName): ?Response
    {
        return null;
        // let the original request continue
    }
    public function onAuthenticationFailure(Request $request, AuthenticationException $exception): ?Response
    {
        $this->clearToken($exception);
        return null;
    }
    public function isInteractive(): bool
    {
        return \true;
    }
    private function clearToken(AuthenticationException $exception): void
    {
        $token = $this->tokenStorage->getToken();
        if ($token instanceof PreAuthenticatedToken && $this->firewallName === $token->getFirewallName()) {
            $this->tokenStorage->setToken(null);
            $this->logger?->info('Cleared pre-authenticated token due to an exception.', ['exception' => $exception]);
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Security\Http\Authenticator\Debug;

use _ContaoManager\Symfony\Component\HttpFoundation\Request;
use _ContaoManager\Symfony\Component\HttpFoundation\Response;
use _ContaoManager\Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use _ContaoManager\Symfony\Component\Security\Core\Exception\AuthenticationException;
use _ContaoManager\Symfony\Component\Security\Http\Authenticator\AuthenticatorInterface;
use _ContaoManager\Symfony\Component\Security\Http\Authenticator\InteractiveAuthenticatorInterface;
use _ContaoManager\Symfony\Component\Security\Http\Authenticator\Passport\Badge\BadgeInterface;
use _ContaoManager\Symfony\Component\Security\Http\Authenticator\Passport\Passport;
use _ContaoManager\Symfony\Component\Security\Http\EntryPoint\AuthenticationEntryPointInterface;
use _ContaoManager\Symfony\Component\Security\Http\EntryPoint\Exception\NotAnEntryPointException;
use _ContaoManager\Symfony\Component\VarDumper\Caster\ClassStub;
/**
 * Collects info about an authenticator for debugging purposes.
 *
 * @author Robin Chalas <robin.chalas@gmail.com>
 */
final class TraceableAuthenticator implements AuthenticatorInterface, InteractiveAuthenticatorInterface, AuthenticationEntryPointInterface
{
    private ?Passport $passport = null;
    private ?float $duration = null;
    private ClassStub|string $stub;
    private ?bool $authenticated = null;
    public function __construct(private AuthenticatorInterface $authenticator)
    {
    }
    public function getInfo(): array
    {
        return ['supports' => \true, 'passport' => $this->passport, 'duration' => $this->duration, 'stub' => $this->stub ??= class_exists(ClassStub::class) ? new ClassStub($this->authenticator::class) : $this->authenticator::class, 'authenticated' => $this->authenticated, 'badges' => array_map(static function (BadgeInterface $badge): array {
            return ['stub' => class_exists(ClassStub::class) ? new ClassStub($badge::class) : $badge::class, 'resolved' => $badge->isResolved()];
        }, $this->passport?->getBadges() ?? [])];
    }
    public function supports(Request $request): ?bool
    {
        return $this->authenticator->supports($request);
    }
    public function authenticate(Request $request): Passport
    {
        $startTime = microtime(\true);
        $this->passport = $this->authenticator->authenticate($request);
        $this->duration = microtime(\true) - $startTime;
        return $this->passport;
    }
    public function createToken(Passport $passport, string $firewallName): TokenInterface
    {
        return $this->authenticator->createToken($passport, $firewallName);
    }
    public function onAuthenticationSuccess(Request $request, TokenInterface $token, string $firewallName): ?Response
    {
        $this->authenticated = \true;
        return $this->authenticator->onAuthenticationSuccess($request, $token, $firewallName);
    }
    public function onAuthenticationFailure(Request $request, AuthenticationException $exception): ?Response
    {
        $this->authenticated = \false;
        return $this->authenticator->onAuthenticationFailure($request, $exception);
    }
    public function start(Request $request, ?AuthenticationException $authException = null): Response
    {
        if (!$this->authenticator instanceof AuthenticationEntryPointInterface) {
            throw new NotAnEntryPointException();
        }
        return $this->authenticator->start($request, $authException);
    }
    public function isInteractive(): bool
    {
        return $this->authenticator instanceof InteractiveAuthenticatorInterface && $this->authenticator->isInteractive();
    }
    public function getAuthenticator(): AuthenticatorInterface
    {
        return $this->authenticator;
    }
    public function __call($method, $args): mixed
    {
        return $this->authenticator->{$method}(...$args);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Security\Http\Authenticator\Debug;

use _ContaoManager\Symfony\Component\HttpFoundation\Request;
use _ContaoManager\Symfony\Component\HttpKernel\Event\RequestEvent;
use _ContaoManager\Symfony\Component\Security\Http\Firewall\AbstractListener;
use _ContaoManager\Symfony\Component\Security\Http\Firewall\AuthenticatorManagerListener;
use _ContaoManager\Symfony\Component\VarDumper\Caster\ClassStub;
use _ContaoManager\Symfony\Contracts\Service\ResetInterface;
/**
 * Decorates the AuthenticatorManagerListener to collect information about security authenticators.
 *
 * @author Robin Chalas <robin.chalas@gmail.com>
 */
final class TraceableAuthenticatorManagerListener extends AbstractListener implements ResetInterface
{
    private AuthenticatorManagerListener $authenticationManagerListener;
    private array $authenticatorsInfo = [];
    private bool $hasVardumper;
    public function __construct(AuthenticatorManagerListener $authenticationManagerListener)
    {
        $this->authenticationManagerListener = $authenticationManagerListener;
        $this->hasVardumper = class_exists(ClassStub::class);
    }
    public function supports(Request $request): ?bool
    {
        return $this->authenticationManagerListener->supports($request);
    }
    public function authenticate(RequestEvent $event): void
    {
        $request = $event->getRequest();
        if (!$authenticators = $request->attributes->get('_security_authenticators')) {
            return;
        }
        foreach ($request->attributes->get('_security_skipped_authenticators') as $skippedAuthenticator) {
            $this->authenticatorsInfo[] = ['supports' => \false, 'stub' => $this->hasVardumper ? new ClassStub($skippedAuthenticator::class) : $skippedAuthenticator::class, 'passport' => null, 'duration' => 0, 'authenticated' => null, 'badges' => []];
        }
        foreach ($authenticators as $key => $authenticator) {
            $authenticators[$key] = new TraceableAuthenticator($authenticator);
        }
        $request->attributes->set('_security_authenticators', $authenticators);
        $this->authenticationManagerListener->authenticate($event);
        foreach ($authenticators as $authenticator) {
            $this->authenticatorsInfo[] = $authenticator->getInfo();
        }
    }
    public function getAuthenticatorManagerListener(): AuthenticatorManagerListener
    {
        return $this->authenticationManagerListener;
    }
    public function getAuthenticatorsInfo(): array
    {
        return $this->authenticatorsInfo;
    }
    public function reset(): void
    {
        $this->authenticatorsInfo = [];
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Security\Http\Authenticator;

use _ContaoManager\Psr\Log\LoggerInterface;
use _ContaoManager\Symfony\Component\HttpFoundation\Request;
use _ContaoManager\Symfony\Component\HttpFoundation\Response;
use _ContaoManager\Symfony\Component\Security\Core\Authentication\Token\RememberMeToken;
use _ContaoManager\Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
use _ContaoManager\Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use _ContaoManager\Symfony\Component\Security\Core\Exception\AuthenticationException;
use _ContaoManager\Symfony\Component\Security\Core\Exception\CookieTheftException;
use _ContaoManager\Symfony\Component\Security\Core\Exception\InvalidArgumentException;
use _ContaoManager\Symfony\Component\Security\Core\Exception\UnsupportedUserException;
use _ContaoManager\Symfony\Component\Security\Core\Exception\UserNotFoundException;
use _ContaoManager\Symfony\Component\Security\Http\Authenticator\Passport\Badge\UserBadge;
use _ContaoManager\Symfony\Component\Security\Http\Authenticator\Passport\Passport;
use _ContaoManager\Symfony\Component\Security\Http\Authenticator\Passport\SelfValidatingPassport;
use _ContaoManager\Symfony\Component\Security\Http\RememberMe\RememberMeDetails;
use _ContaoManager\Symfony\Component\Security\Http\RememberMe\RememberMeHandlerInterface;
use _ContaoManager\Symfony\Component\Security\Http\RememberMe\ResponseListener;
/**
 * The RememberMe *Authenticator* performs remember me authentication.
 *
 * This authenticator is executed whenever a user's session
 * expired and a remember-me cookie was found. This authenticator
 * then "re-authenticates" the user using the information in the
 * cookie.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 * @author Wouter de Jong <wouter@wouterj.nl>
 *
 * @final
 */
class RememberMeAuthenticator implements InteractiveAuthenticatorInterface
{
    private RememberMeHandlerInterface $rememberMeHandler;
    private string $secret;
    private TokenStorageInterface $tokenStorage;
    private string $cookieName;
    private ?LoggerInterface $logger;
    public function __construct(
        RememberMeHandlerInterface $rememberMeHandler,
        #[\SensitiveParameter]
        string $secret,
        TokenStorageInterface $tokenStorage,
        string $cookieName,
        ?LoggerInterface $logger = null
    )
    {
        if (!$secret) {
            throw new InvalidArgumentException('A non-empty secret is required.');
        }
        $this->rememberMeHandler = $rememberMeHandler;
        $this->secret = $secret;
        $this->tokenStorage = $tokenStorage;
        $this->cookieName = $cookieName;
        $this->logger = $logger;
    }
    public function supports(Request $request): ?bool
    {
        // do not overwrite already stored tokens (i.e. from the session)
        if (null !== $this->tokenStorage->getToken()) {
            return \false;
        }
        if (($cookie = $request->attributes->get(ResponseListener::COOKIE_ATTR_NAME)) && null === $cookie->getValue()) {
            return \false;
        }
        if (!$request->cookies->has($this->cookieName) || !\is_scalar($request->cookies->all()[$this->cookieName] ?: null)) {
            return \false;
        }
        $this->logger?->debug('Remember-me cookie detected.');
        // the `null` return value indicates that this authenticator supports lazy firewalls
        return null;
    }
    public function authenticate(Request $request): Passport
    {
        if (!$rawCookie = $request->cookies->get($this->cookieName)) {
            throw new \LogicException('No remember-me cookie is found.');
        }
        $rememberMeCookie = RememberMeDetails::fromRawCookie($rawCookie);
        $userBadge = new UserBadge($rememberMeCookie->getUserIdentifier(), fn() => $this->rememberMeHandler->consumeRememberMeCookie($rememberMeCookie));
        return new SelfValidatingPassport($userBadge);
    }
    public function createToken(Passport $passport, string $firewallName): TokenInterface
    {
        return new RememberMeToken($passport->getUser(), $firewallName, $this->secret);
    }
    public function onAuthenticationSuccess(Request $request, TokenInterface $token, string $firewallName): ?Response
    {
        return null;
        // let the original request continue
    }
    public function onAuthenticationFailure(Request $request, AuthenticationException $exception): ?Response
    {
        if (null !== $this->logger) {
            if ($exception instanceof UserNotFoundException) {
                $this->logger->info('User for remember-me cookie not found.', ['exception' => $exception]);
            } elseif ($exception instanceof UnsupportedUserException) {
                $this->logger->warning('User class for remember-me cookie not supported.', ['exception' => $exception]);
            } elseif (!$exception instanceof CookieTheftException) {
                $this->logger->debug('Remember me authentication failed.', ['exception' => $exception]);
            }
        }
        return null;
    }
    public function isInteractive(): bool
    {
        return \true;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Security\Http\Authorization;

use _ContaoManager\Symfony\Component\HttpFoundation\Request;
use _ContaoManager\Symfony\Component\HttpFoundation\Response;
use _ContaoManager\Symfony\Component\Security\Core\Exception\AccessDeniedException;
/**
 * This is used by the ExceptionListener to translate an AccessDeniedException
 * to a Response object.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
interface AccessDeniedHandlerInterface
{
    /**
     * Handles an access denied failure.
     */
    public function handle(Request $request, AccessDeniedException $accessDeniedException): ?Response;
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Security\Http;

use _ContaoManager\Symfony\Component\HttpFoundation\Request;
/**
 * AccessMap allows configuration of different access control rules for
 * specific parts of the website.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 * @author Kris Wallsmith <kris@symfony.com>
 */
interface AccessMapInterface
{
    /**
     * Returns security attributes and required channel for the supplied request.
     *
     * @return array{0: array|null, 1: string|null} A tuple of security attributes and the required channel
     */
    public function getPatterns(Request $request): array;
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Security\Http\LoginLink;

/**
 * @author Ryan Weaver <ryan@symfonycasts.com>
 */
class LoginLinkDetails
{
    private string $url;
    private \DateTimeImmutable $expiresAt;
    public function __construct(string $url, \DateTimeImmutable $expiresAt)
    {
        $this->url = $url;
        $this->expiresAt = $expiresAt;
    }
    public function getUrl(): string
    {
        return $this->url;
    }
    public function getExpiresAt(): \DateTimeImmutable
    {
        return $this->expiresAt;
    }
    public function __toString(): string
    {
        return $this->url;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Security\Http\LoginLink;

use _ContaoManager\Symfony\Component\HttpFoundation\Request;
use _ContaoManager\Symfony\Component\Routing\Generator\UrlGeneratorInterface;
use _ContaoManager\Symfony\Component\Routing\RequestContext;
use _ContaoManager\Symfony\Component\Security\Core\Exception\UserNotFoundException;
use _ContaoManager\Symfony\Component\Security\Core\Signature\Exception\ExpiredSignatureException;
use _ContaoManager\Symfony\Component\Security\Core\Signature\Exception\InvalidSignatureException;
use _ContaoManager\Symfony\Component\Security\Core\Signature\SignatureHasher;
use _ContaoManager\Symfony\Component\Security\Core\User\UserInterface;
use _ContaoManager\Symfony\Component\Security\Core\User\UserProviderInterface;
use _ContaoManager\Symfony\Component\Security\Http\LoginLink\Exception\ExpiredLoginLinkException;
use _ContaoManager\Symfony\Component\Security\Http\LoginLink\Exception\InvalidLoginLinkException;
/**
 * @author Ryan Weaver <ryan@symfonycasts.com>
 */
final class LoginLinkHandler implements LoginLinkHandlerInterface
{
    private UrlGeneratorInterface $urlGenerator;
    private UserProviderInterface $userProvider;
    private array $options;
    private SignatureHasher $signatureHasher;
    public function __construct(UrlGeneratorInterface $urlGenerator, UserProviderInterface $userProvider, SignatureHasher $signatureHasher, array $options)
    {
        $this->urlGenerator = $urlGenerator;
        $this->userProvider = $userProvider;
        $this->signatureHasher = $signatureHasher;
        $this->options = array_merge(['route_name' => null, 'lifetime' => 600], $options);
    }
    public function createLoginLink(UserInterface $user, ?Request $request = null, ?int $lifetime = null): LoginLinkDetails
    {
        $expires = time() + ($lifetime ?: $this->options['lifetime']);
        $expiresAt = new \DateTimeImmutable('@' . $expires);
        $parameters = ['user' => $user->getUserIdentifier(), 'expires' => $expires, 'hash' => $this->signatureHasher->computeSignatureHash($user, $expires)];
        if ($request) {
            $currentRequestContext = $this->urlGenerator->getContext();
            $this->urlGenerator->setContext((new RequestContext())->fromRequest($request)->setParameter('_locale', $request->getLocale()));
        }
        try {
            $url = $this->urlGenerator->generate($this->options['route_name'], $parameters, UrlGeneratorInterface::ABSOLUTE_URL);
        } finally {
            if ($request) {
                $this->urlGenerator->setContext($currentRequestContext);
            }
        }
        return new LoginLinkDetails($url, $expiresAt);
    }
    public function consumeLoginLink(Request $request): UserInterface
    {
        $userIdentifier = $request->get('user');
        if (!$hash = $request->get('hash')) {
            throw new InvalidLoginLinkException('Missing "hash" parameter.');
        }
        if (!\is_string($hash)) {
            throw new InvalidLoginLinkException('Invalid "hash" parameter.');
        }
        if (!$expires = $request->get('expires')) {
            throw new InvalidLoginLinkException('Missing "expires" parameter.');
        }
        if (!preg_match('/^\d+$/', $expires)) {
            throw new InvalidLoginLinkException('Invalid "expires" parameter.');
        }
        try {
            $this->signatureHasher->acceptSignatureHash($userIdentifier, $expires, $hash);
            $user = $this->userProvider->loadUserByIdentifier($userIdentifier);
            $this->signatureHasher->verifySignatureHash($user, $expires, $hash);
        } catch (UserNotFoundException $e) {
            throw new InvalidLoginLinkException('User not found.', 0, $e);
        } catch (ExpiredSignatureException $e) {
            throw new ExpiredLoginLinkException(ucfirst(str_ireplace('signature', 'login link', $e->getMessage())), 0, $e);
        } catch (InvalidSignatureException $e) {
            throw new InvalidLoginLinkException(ucfirst(str_ireplace('signature', 'login link', $e->getMessage())), 0, $e);
        }
        return $user;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Security\Http\LoginLink;

use _ContaoManager\Symfony\Bridge\Twig\Mime\NotificationEmail;
use _ContaoManager\Symfony\Component\Notifier\Message\EmailMessage;
use _ContaoManager\Symfony\Component\Notifier\Message\SmsMessage;
use _ContaoManager\Symfony\Component\Notifier\Notification\EmailNotificationInterface;
use _ContaoManager\Symfony\Component\Notifier\Notification\Notification;
use _ContaoManager\Symfony\Component\Notifier\Notification\SmsNotificationInterface;
use _ContaoManager\Symfony\Component\Notifier\Recipient\EmailRecipientInterface;
use _ContaoManager\Symfony\Component\Notifier\Recipient\SmsRecipientInterface;
/**
 * Use this notification to ease sending login link
 * emails/SMS using the Notifier component.
 *
 * @author Wouter de Jong <wouter@wouterj.nl>
 */
class LoginLinkNotification extends Notification implements EmailNotificationInterface, SmsNotificationInterface
{
    private LoginLinkDetails $loginLinkDetails;
    public function __construct(LoginLinkDetails $loginLinkDetails, string $subject, array $channels = [])
    {
        parent::__construct($subject, $channels);
        $this->loginLinkDetails = $loginLinkDetails;
    }
    public function asEmailMessage(EmailRecipientInterface $recipient, ?string $transport = null): ?EmailMessage
    {
        if (!class_exists(NotificationEmail::class)) {
            throw new \LogicException(\sprintf('The "%s" method requires "symfony/twig-bridge:>4.4".', __METHOD__));
        }
        $email = NotificationEmail::asPublicEmail()->to($recipient->getEmail())->subject($this->getSubject())->content($this->getContent() ?: $this->getDefaultContent('button below'))->action('Sign in', $this->loginLinkDetails->getUrl());
        return new EmailMessage($email);
    }
    public function asSmsMessage(SmsRecipientInterface $recipient, ?string $transport = null): ?SmsMessage
    {
        return new SmsMessage($recipient->getPhone(), $this->getDefaultContent('link') . ' ' . $this->loginLinkDetails->getUrl());
    }
    private function getDefaultContent(string $target): string
    {
        $duration = $this->loginLinkDetails->getExpiresAt()->getTimestamp() - time();
        $durationString = floor($duration / 60) . ' minute' . ($duration > 60 ? 's' : '');
        if (($hours = $duration / 3600) >= 1) {
            $durationString = floor($hours) . ' hour' . ($hours >= 2 ? 's' : '');
        }
        return \sprintf('Click on the %s to confirm you want to sign in. This link will expire in %s.', $target, $durationString);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Security\Http\LoginLink;

use _ContaoManager\Symfony\Component\HttpFoundation\Request;
use _ContaoManager\Symfony\Component\Security\Core\User\UserInterface;
/**
 * A class that is able to create and handle "magic" login links.
 *
 * @author Ryan Weaver <ryan@symfonycasts.com>
 */
interface LoginLinkHandlerInterface
{
    /**
     * Generate a link that can be used to authenticate as the given user.
     *
     * @param int|null $lifetime When not null, the argument overrides any default lifetime previously set
     */
    public function createLoginLink(UserInterface $user, ?Request $request = null): LoginLinkDetails;
    /**
     * Validates if this request contains a login link and returns the associated User.
     *
     * Throw InvalidLoginLinkExceptionInterface if the link is invalid.
     */
    public function consumeLoginLink(Request $request): UserInterface;
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Security\Http\LoginLink\Exception;

/**
 * @author Ryan Weaver <ryan@symfonycasts.com>
 */
interface InvalidLoginLinkExceptionInterface extends \Throwable
{
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Security\Http\LoginLink\Exception;

/**
 * @author Ryan Weaver <ryan@symfonycasts.com>
 */
class InvalidLoginLinkException extends \RuntimeException implements InvalidLoginLinkExceptionInterface
{
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Security\Http\LoginLink\Exception;

use _ContaoManager\Symfony\Component\Security\Core\Exception\AuthenticationException;
/**
 * Thrown when a login link is invalid.
 *
 * @author Ryan Weaver <ryan@symfonycasts.com>
 */
class InvalidLoginLinkAuthenticationException extends AuthenticationException
{
    public function getMessageKey(): string
    {
        return 'Invalid or expired login link.';
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Security\Http\LoginLink\Exception;

use _ContaoManager\Symfony\Component\Security\Core\Signature\Exception\ExpiredSignatureException;
/**
 * @author Ryan Weaver <ryan@symfonycasts.com>
 */
class ExpiredLoginLinkException extends ExpiredSignatureException implements InvalidLoginLinkExceptionInterface
{
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Security\Http\Authentication;

use _ContaoManager\Psr\Log\LoggerInterface;
use _ContaoManager\Symfony\Component\HttpFoundation\Request;
use _ContaoManager\Symfony\Component\HttpFoundation\Response;
use _ContaoManager\Symfony\Component\HttpKernel\HttpKernelInterface;
use _ContaoManager\Symfony\Component\Security\Core\Exception\AuthenticationException;
use _ContaoManager\Symfony\Component\Security\Http\HttpUtils;
use _ContaoManager\Symfony\Component\Security\Http\ParameterBagUtils;
use _ContaoManager\Symfony\Component\Security\Http\SecurityRequestAttributes;
/**
 * Class with the default authentication failure handling logic.
 *
 * Can be optionally be extended from by the developer to alter the behavior
 * while keeping the default behavior.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 * @author Alexander <iam.asm89@gmail.com>
 */
class DefaultAuthenticationFailureHandler implements AuthenticationFailureHandlerInterface
{
    protected $httpKernel;
    protected $httpUtils;
    protected $logger;
    protected $options;
    protected $defaultOptions = ['failure_path' => null, 'failure_forward' => \false, 'login_path' => '/login', 'failure_path_parameter' => '_failure_path'];
    public function __construct(HttpKernelInterface $httpKernel, HttpUtils $httpUtils, array $options = [], ?LoggerInterface $logger = null)
    {
        $this->httpKernel = $httpKernel;
        $this->httpUtils = $httpUtils;
        $this->logger = $logger;
        $this->setOptions($options);
    }
    /**
     * Gets the options.
     */
    public function getOptions(): array
    {
        return $this->options;
    }
    /**
     * @return void
     */
    public function setOptions(array $options)
    {
        $this->options = array_merge($this->defaultOptions, $options);
    }
    public function onAuthenticationFailure(Request $request, AuthenticationException $exception): Response
    {
        $options = $this->options;
        $failureUrl = ParameterBagUtils::getRequestParameterValue($request, $options['failure_path_parameter']);
        if (\is_string($failureUrl) && (str_starts_with($failureUrl, '/') || str_starts_with($failureUrl, 'http'))) {
            $options['failure_path'] = $failureUrl;
        } elseif ($this->logger && $failureUrl) {
            $this->logger->debug(\sprintf('Ignoring query parameter "%s": not a valid URL.', $options['failure_path_parameter']));
        }
        $options['failure_path'] ??= $options['login_path'];
        if ($options['failure_forward']) {
            $this->logger?->debug('Authentication failure, forward triggered.', ['failure_path' => $options['failure_path']]);
            $subRequest = $this->httpUtils->createRequest($request, $options['failure_path']);
            $subRequest->attributes->set(SecurityRequestAttributes::AUTHENTICATION_ERROR, $exception);
            return $this->httpKernel->handle($subRequest, HttpKernelInterface::SUB_REQUEST);
        }
        $this->logger?->debug('Authentication failure, redirect triggered.', ['failure_path' => $options['failure_path']]);
        if (!$request->attributes->getBoolean('_stateless')) {
            $request->getSession()->set(SecurityRequestAttributes::AUTHENTICATION_ERROR, $exception);
        }
        return $this->httpUtils->createRedirectResponse($request, $options['failure_path']);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Security\Http\Authentication;

use _ContaoManager\Symfony\Component\HttpFoundation\Request;
use _ContaoManager\Symfony\Component\HttpFoundation\Response;
use _ContaoManager\Symfony\Component\Security\Http\Firewall\FirewallListenerInterface;
/**
 * @author Wouter de Jong <wouter@wouterj.nl>
 * @author Ryan Weaver <ryan@symfonycasts.com>
 */
interface AuthenticatorManagerInterface
{
    /**
     * Called to see if authentication should be attempted on this request.
     *
     * @see FirewallListenerInterface::supports()
     */
    public function supports(Request $request): ?bool;
    /**
     * Tries to authenticate the request and returns a response - if any authenticator set one.
     */
    public function authenticateRequest(Request $request): ?Response;
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Security\Http\Authentication;

use _ContaoManager\Symfony\Component\HttpFoundation\Request;
use _ContaoManager\Symfony\Component\HttpFoundation\Response;
use _ContaoManager\Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
/**
 * @author Fabien Potencier <fabien@symfony.com>
 */
class CustomAuthenticationSuccessHandler implements AuthenticationSuccessHandlerInterface
{
    private AuthenticationSuccessHandlerInterface $handler;
    /**
     * @param array $options Options for processing a successful authentication attempt
     */
    public function __construct(AuthenticationSuccessHandlerInterface $handler, array $options, string $firewallName)
    {
        $this->handler = $handler;
        if (method_exists($handler, 'setOptions')) {
            $this->handler->setOptions($options);
        }
        if (method_exists($handler, 'setFirewallName')) {
            $this->handler->setFirewallName($firewallName);
        }
    }
    public function onAuthenticationSuccess(Request $request, TokenInterface $token): ?Response
    {
        return $this->handler->onAuthenticationSuccess($request, $token);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Security\Http\Authentication;

use _ContaoManager\Symfony\Component\HttpFoundation\Request;
use _ContaoManager\Symfony\Component\HttpFoundation\Response;
use _ContaoManager\Symfony\Component\Security\Core\Exception\AuthenticationException;
/**
 * Interface for custom authentication failure handlers.
 *
 * If you want to customize the failure handling process, instead of
 * overwriting the respective listener globally, you can set a custom failure
 * handler which implements this interface.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
interface AuthenticationFailureHandlerInterface
{
    /**
     * This is called when an interactive authentication attempt fails.
     */
    public function onAuthenticationFailure(Request $request, AuthenticationException $exception): Response;
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Security\Http\Authentication;

use _ContaoManager\Symfony\Component\HttpFoundation\Request;
use _ContaoManager\Symfony\Component\HttpFoundation\RequestStack;
use _ContaoManager\Symfony\Component\Security\Core\Exception\AuthenticationException;
use _ContaoManager\Symfony\Component\Security\Http\SecurityRequestAttributes;
/**
 * Extracts Security Errors from Request.
 *
 * @author Boris Vujicic <boris.vujicic@gmail.com>
 */
class AuthenticationUtils
{
    private RequestStack $requestStack;
    public function __construct(RequestStack $requestStack)
    {
        $this->requestStack = $requestStack;
    }
    public function getLastAuthenticationError(bool $clearSession = \true): ?AuthenticationException
    {
        $request = $this->getRequest();
        $authenticationException = null;
        if ($request->attributes->has(SecurityRequestAttributes::AUTHENTICATION_ERROR)) {
            $authenticationException = $request->attributes->get(SecurityRequestAttributes::AUTHENTICATION_ERROR);
        } elseif ($request->hasSession() && ($session = $request->getSession())->has(SecurityRequestAttributes::AUTHENTICATION_ERROR)) {
            $authenticationException = $session->get(SecurityRequestAttributes::AUTHENTICATION_ERROR);
            if ($clearSession) {
                $session->remove(SecurityRequestAttributes::AUTHENTICATION_ERROR);
            }
        }
        return $authenticationException;
    }
    public function getLastUsername(): string
    {
        $request = $this->getRequest();
        if ($request->attributes->has(SecurityRequestAttributes::LAST_USERNAME)) {
            return $request->attributes->get(SecurityRequestAttributes::LAST_USERNAME) ?? '';
        }
        return $request->hasSession() ? $request->getSession()->get(SecurityRequestAttributes::LAST_USERNAME) ?? '' : '';
    }
    /**
     * @throws \LogicException
     */
    private function getRequest(): Request
    {
        $request = $this->requestStack->getCurrentRequest();
        if (null === $request) {
            throw new \LogicException('Request should exist so it can be processed for error.');
        }
        return $request;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Security\Http\Authentication;

use _ContaoManager\Symfony\Component\HttpFoundation\Request;
use _ContaoManager\Symfony\Component\HttpFoundation\Response;
use _ContaoManager\Symfony\Component\Security\Core\Exception\AuthenticationException;
/**
 * @author Fabien Potencier <fabien@symfony.com>
 */
class CustomAuthenticationFailureHandler implements AuthenticationFailureHandlerInterface
{
    private AuthenticationFailureHandlerInterface $handler;
    /**
     * @param array $options Options for processing a successful authentication attempt
     */
    public function __construct(AuthenticationFailureHandlerInterface $handler, array $options)
    {
        $this->handler = $handler;
        if (method_exists($handler, 'setOptions')) {
            $this->handler->setOptions($options);
        }
    }
    public function onAuthenticationFailure(Request $request, AuthenticationException $exception): Response
    {
        return $this->handler->onAuthenticationFailure($request, $exception);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Security\Http\Authentication;

use _ContaoManager\Symfony\Component\HttpFoundation\Request;
use _ContaoManager\Symfony\Component\HttpFoundation\Response;
use _ContaoManager\Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
/**
 * Interface for a custom authentication success handler.
 *
 * If you want to customize the success handling process, instead of
 * overwriting the respective listener globally, you can set a custom success
 * handler which implements this interface.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
interface AuthenticationSuccessHandlerInterface
{
    /**
     * Usually called by AuthenticatorInterface::onAuthenticationSuccess() implementations.
     */
    public function onAuthenticationSuccess(Request $request, TokenInterface $token): ?Response;
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Security\Http\Authentication;

use _ContaoManager\Symfony\Component\HttpFoundation\Request;
use _ContaoManager\Symfony\Component\HttpFoundation\Response;
use _ContaoManager\Symfony\Component\Security\Core\User\UserInterface;
use _ContaoManager\Symfony\Component\Security\Http\Authenticator\AuthenticatorInterface;
use _ContaoManager\Symfony\Component\Security\Http\Authenticator\Passport\Badge\BadgeInterface;
/**
 * @author Wouter de Jong <wouter@wouterj.nl>
 */
interface UserAuthenticatorInterface
{
    /**
     * Convenience method to programmatically login a user and return a
     * Response *if any* for success.
     *
     * @param BadgeInterface[] $badges Optionally, pass some Passport badges to use for the manual login
     */
    public function authenticateUser(UserInterface $user, AuthenticatorInterface $authenticator, Request $request, array $badges = []): ?Response;
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Security\Http\Authentication;

use _ContaoManager\Psr\Log\LoggerInterface;
use _ContaoManager\Symfony\Component\HttpFoundation\Request;
use _ContaoManager\Symfony\Component\HttpFoundation\Response;
use _ContaoManager\Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
use _ContaoManager\Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use _ContaoManager\Symfony\Component\Security\Core\AuthenticationEvents;
use _ContaoManager\Symfony\Component\Security\Core\Event\AuthenticationSuccessEvent;
use _ContaoManager\Symfony\Component\Security\Core\Exception\AccountStatusException;
use _ContaoManager\Symfony\Component\Security\Core\Exception\AuthenticationException;
use _ContaoManager\Symfony\Component\Security\Core\Exception\BadCredentialsException;
use _ContaoManager\Symfony\Component\Security\Core\Exception\CustomUserMessageAccountStatusException;
use _ContaoManager\Symfony\Component\Security\Core\Exception\UserNotFoundException;
use _ContaoManager\Symfony\Component\Security\Core\User\UserInterface;
use _ContaoManager\Symfony\Component\Security\Http\Authenticator\AuthenticatorInterface;
use _ContaoManager\Symfony\Component\Security\Http\Authenticator\Debug\TraceableAuthenticator;
use _ContaoManager\Symfony\Component\Security\Http\Authenticator\InteractiveAuthenticatorInterface;
use _ContaoManager\Symfony\Component\Security\Http\Authenticator\Passport\Badge\BadgeInterface;
use _ContaoManager\Symfony\Component\Security\Http\Authenticator\Passport\Badge\UserBadge;
use _ContaoManager\Symfony\Component\Security\Http\Authenticator\Passport\Passport;
use _ContaoManager\Symfony\Component\Security\Http\Authenticator\Passport\SelfValidatingPassport;
use _ContaoManager\Symfony\Component\Security\Http\Event\AuthenticationTokenCreatedEvent;
use _ContaoManager\Symfony\Component\Security\Http\Event\CheckPassportEvent;
use _ContaoManager\Symfony\Component\Security\Http\Event\InteractiveLoginEvent;
use _ContaoManager\Symfony\Component\Security\Http\Event\LoginFailureEvent;
use _ContaoManager\Symfony\Component\Security\Http\Event\LoginSuccessEvent;
use _ContaoManager\Symfony\Component\Security\Http\SecurityEvents;
use _ContaoManager\Symfony\Contracts\EventDispatcher\EventDispatcherInterface;
/**
 * @author Wouter de Jong <wouter@wouterj.nl>
 * @author Ryan Weaver <ryan@symfonycasts.com>
 * @author Amaury Leroux de Lens <amaury@lerouxdelens.com>
 */
class AuthenticatorManager implements AuthenticatorManagerInterface, UserAuthenticatorInterface
{
    private iterable $authenticators;
    private TokenStorageInterface $tokenStorage;
    private EventDispatcherInterface $eventDispatcher;
    private bool $eraseCredentials;
    private ?LoggerInterface $logger;
    private string $firewallName;
    private bool $hideUserNotFoundExceptions;
    private array $requiredBadges;
    /**
     * @param iterable<mixed, AuthenticatorInterface> $authenticators
     */
    public function __construct(iterable $authenticators, TokenStorageInterface $tokenStorage, EventDispatcherInterface $eventDispatcher, string $firewallName, ?LoggerInterface $logger = null, bool $eraseCredentials = \true, bool $hideUserNotFoundExceptions = \true, array $requiredBadges = [])
    {
        $this->authenticators = $authenticators;
        $this->tokenStorage = $tokenStorage;
        $this->eventDispatcher = $eventDispatcher;
        $this->firewallName = $firewallName;
        $this->logger = $logger;
        $this->eraseCredentials = $eraseCredentials;
        $this->hideUserNotFoundExceptions = $hideUserNotFoundExceptions;
        $this->requiredBadges = $requiredBadges;
    }
    /**
     * @param BadgeInterface[] $badges Optionally, pass some Passport badges to use for the manual login
     */
    public function authenticateUser(UserInterface $user, AuthenticatorInterface $authenticator, Request $request, array $badges = []): ?Response
    {
        // create an authentication token for the User
        $passport = new SelfValidatingPassport(new UserBadge($user->getUserIdentifier(), fn() => $user), $badges);
        $token = $authenticator->createToken($passport, $this->firewallName);
        // announce the authentication token
        $token = $this->eventDispatcher->dispatch(new AuthenticationTokenCreatedEvent($token, $passport))->getAuthenticatedToken();
        // authenticate this in the system
        return $this->handleAuthenticationSuccess($token, $passport, $request, $authenticator, $this->tokenStorage->getToken());
    }
    public function supports(Request $request): ?bool
    {
        if (null !== $this->logger) {
            $context = ['firewall_name' => $this->firewallName];
            if (is_countable($this->authenticators)) {
                $context['authenticators'] = \count($this->authenticators);
            }
            $this->logger->debug('Checking for authenticator support.', $context);
        }
        $authenticators = [];
        $skippedAuthenticators = [];
        $lazy = \true;
        foreach ($this->authenticators as $authenticator) {
            $this->logger?->debug('Checking support on authenticator.', ['firewall_name' => $this->firewallName, 'authenticator' => $authenticator::class]);
            if (!$authenticator instanceof AuthenticatorInterface) {
                throw new \InvalidArgumentException(\sprintf('Authenticator "%s" must implement "%s".', get_debug_type($authenticator), AuthenticatorInterface::class));
            }
            if (\false !== $supports = $authenticator->supports($request)) {
                $authenticators[] = $authenticator;
                $lazy = $lazy && null === $supports;
            } else {
                $this->logger?->debug('Authenticator does not support the request.', ['firewall_name' => $this->firewallName, 'authenticator' => $authenticator::class]);
                $skippedAuthenticators[] = $authenticator;
            }
        }
        if (!$authenticators) {
            return \false;
        }
        $request->attributes->set('_security_authenticators', $authenticators);
        $request->attributes->set('_security_skipped_authenticators', $skippedAuthenticators);
        return $lazy ? null : \true;
    }
    public function authenticateRequest(Request $request): ?Response
    {
        $authenticators = $request->attributes->get('_security_authenticators');
        $request->attributes->remove('_security_authenticators');
        $request->attributes->remove('_security_skipped_authenticators');
        if (!$authenticators) {
            return null;
        }
        return $this->executeAuthenticators($authenticators, $request);
    }
    /**
     * @param AuthenticatorInterface[] $authenticators
     */
    private function executeAuthenticators(array $authenticators, Request $request): ?Response
    {
        foreach ($authenticators as $authenticator) {
            // recheck if the authenticator still supports the listener. supports() is called
            // eagerly (before token storage is initialized), whereas authenticate() is called
            // lazily (after initialization).
            if (\false === $authenticator->supports($request)) {
                $this->logger?->debug('Skipping the "{authenticator}" authenticator as it did not support the request.', ['authenticator' => ($authenticator instanceof TraceableAuthenticator ? $authenticator->getAuthenticator() : $authenticator)::class]);
                continue;
            }
            $response = $this->executeAuthenticator($authenticator, $request);
            if (null !== $response) {
                $this->logger?->debug('The "{authenticator}" authenticator set the response. Any later authenticator will not be called', ['authenticator' => ($authenticator instanceof TraceableAuthenticator ? $authenticator->getAuthenticator() : $authenticator)::class]);
                return $response;
            }
        }
        return null;
    }
    private function executeAuthenticator(AuthenticatorInterface $authenticator, Request $request): ?Response
    {
        $passport = null;
        $previousToken = $this->tokenStorage->getToken();
        try {
            // get the passport from the Authenticator
            $passport = $authenticator->authenticate($request);
            // check the passport (e.g. password checking)
            $event = new CheckPassportEvent($authenticator, $passport);
            $this->eventDispatcher->dispatch($event);
            // check if all badges are resolved
            $resolvedBadges = [];
            foreach ($passport->getBadges() as $badge) {
                if (!$badge->isResolved()) {
                    throw new BadCredentialsException(\sprintf('Authentication failed: Security badge "%s" is not resolved, did you forget to register the correct listeners?', get_debug_type($badge)));
                }
                $resolvedBadges[] = $badge::class;
            }
            $missingRequiredBadges = array_diff($this->requiredBadges, $resolvedBadges);
            if ($missingRequiredBadges) {
                throw new BadCredentialsException(\sprintf('Authentication failed; Some badges marked as required by the firewall config are not available on the passport: "%s".', implode('", "', $missingRequiredBadges)));
            }
            // create the authentication token
            $authenticatedToken = $authenticator->createToken($passport, $this->firewallName);
            // announce the authentication token
            $authenticatedToken = $this->eventDispatcher->dispatch(new AuthenticationTokenCreatedEvent($authenticatedToken, $passport))->getAuthenticatedToken();
            if (\true === $this->eraseCredentials) {
                $authenticatedToken->eraseCredentials();
            }
            $this->eventDispatcher->dispatch(new AuthenticationSuccessEvent($authenticatedToken), AuthenticationEvents::AUTHENTICATION_SUCCESS);
            $this->logger?->info('Authenticator successful!', ['token' => $authenticatedToken, 'authenticator' => ($authenticator instanceof TraceableAuthenticator ? $authenticator->getAuthenticator() : $authenticator)::class]);
        } catch (AuthenticationException $e) {
            // oh no! Authentication failed!
            $response = $this->handleAuthenticationFailure($e, $request, $authenticator, $passport);
            if ($response instanceof Response) {
                return $response;
            }
            return null;
        }
        // success! (sets the token on the token storage, etc)
        $response = $this->handleAuthenticationSuccess($authenticatedToken, $passport, $request, $authenticator, $previousToken);
        if ($response instanceof Response) {
            return $response;
        }
        $this->logger?->debug('Authenticator set no success response: request continues.', ['authenticator' => ($authenticator instanceof TraceableAuthenticator ? $authenticator->getAuthenticator() : $authenticator)::class]);
        return null;
    }
    private function handleAuthenticationSuccess(TokenInterface $authenticatedToken, Passport $passport, Request $request, AuthenticatorInterface $authenticator, ?TokenInterface $previousToken): ?Response
    {
        $this->tokenStorage->setToken($authenticatedToken);
        $response = $authenticator->onAuthenticationSuccess($request, $authenticatedToken, $this->firewallName);
        if ($authenticator instanceof InteractiveAuthenticatorInterface && $authenticator->isInteractive()) {
            $loginEvent = new InteractiveLoginEvent($request, $authenticatedToken);
            $this->eventDispatcher->dispatch($loginEvent, SecurityEvents::INTERACTIVE_LOGIN);
        }
        $this->eventDispatcher->dispatch($loginSuccessEvent = new LoginSuccessEvent($authenticator, $passport, $authenticatedToken, $request, $response, $this->firewallName, $previousToken));
        return $loginSuccessEvent->getResponse();
    }
    /**
     * Handles an authentication failure and returns the Response for the authenticator.
     */
    private function handleAuthenticationFailure(AuthenticationException $authenticationException, Request $request, AuthenticatorInterface $authenticator, ?Passport $passport): ?Response
    {
        $this->logger?->info('Authenticator failed.', ['exception' => $authenticationException, 'authenticator' => ($authenticator instanceof TraceableAuthenticator ? $authenticator->getAuthenticator() : $authenticator)::class]);
        // Avoid leaking error details in case of invalid user (e.g. user not found or invalid account status)
        // to prevent user enumeration via response content comparison
        if ($this->hideUserNotFoundExceptions && ($authenticationException instanceof UserNotFoundException || $authenticationException instanceof AccountStatusException && !$authenticationException instanceof CustomUserMessageAccountStatusException)) {
            $authenticationException = new BadCredentialsException('Bad credentials.', 0, $authenticationException);
        }
        $response = $authenticator->onAuthenticationFailure($request, $authenticationException);
        if (null !== $response && null !== $this->logger) {
            $this->logger->debug('The "{authenticator}" authenticator set the failure response.', ['authenticator' => ($authenticator instanceof TraceableAuthenticator ? $authenticator->getAuthenticator() : $authenticator)::class]);
        }
        $this->eventDispatcher->dispatch($loginFailureEvent = new LoginFailureEvent($authenticationException, $authenticator, $request, $response, $this->firewallName, $passport));
        // returning null is ok, it means they want the request to continue
        return $loginFailureEvent->getResponse();
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Security\Http\Authentication;

use _ContaoManager\Psr\Log\LoggerInterface;
use _ContaoManager\Symfony\Component\HttpFoundation\Request;
use _ContaoManager\Symfony\Component\HttpFoundation\Response;
use _ContaoManager\Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use _ContaoManager\Symfony\Component\Security\Http\HttpUtils;
use _ContaoManager\Symfony\Component\Security\Http\ParameterBagUtils;
use _ContaoManager\Symfony\Component\Security\Http\Util\TargetPathTrait;
/**
 * Class with the default authentication success handling logic.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 * @author Alexander <iam.asm89@gmail.com>
 */
class DefaultAuthenticationSuccessHandler implements AuthenticationSuccessHandlerInterface
{
    use TargetPathTrait;
    protected $httpUtils;
    protected $logger;
    protected $options;
    protected $firewallName;
    protected $defaultOptions = ['always_use_default_target_path' => \false, 'default_target_path' => '/', 'login_path' => '/login', 'target_path_parameter' => '_target_path', 'use_referer' => \false];
    /**
     * @param array $options Options for processing a successful authentication attempt
     */
    public function __construct(HttpUtils $httpUtils, array $options = [], ?LoggerInterface $logger = null)
    {
        $this->httpUtils = $httpUtils;
        $this->logger = $logger;
        $this->setOptions($options);
    }
    public function onAuthenticationSuccess(Request $request, TokenInterface $token): ?Response
    {
        return $this->httpUtils->createRedirectResponse($request, $this->determineTargetUrl($request));
    }
    /**
     * Gets the options.
     */
    public function getOptions(): array
    {
        return $this->options;
    }
    /**
     * @return void
     */
    public function setOptions(array $options)
    {
        $this->options = array_merge($this->defaultOptions, $options);
    }
    public function getFirewallName(): ?string
    {
        return $this->firewallName;
    }
    public function setFirewallName(string $firewallName): void
    {
        $this->firewallName = $firewallName;
    }
    /**
     * Builds the target URL according to the defined options.
     */
    protected function determineTargetUrl(Request $request): string
    {
        if ($this->options['always_use_default_target_path']) {
            return $this->options['default_target_path'];
        }
        $targetUrl = ParameterBagUtils::getRequestParameterValue($request, $this->options['target_path_parameter']);
        if (\is_string($targetUrl) && (str_starts_with($targetUrl, '/') || str_starts_with($targetUrl, 'http'))) {
            return $targetUrl;
        }
        if ($this->logger && $targetUrl) {
            $this->logger->debug(\sprintf('Ignoring query parameter "%s": not a valid URL.', $this->options['target_path_parameter']));
        }
        $firewallName = $this->getFirewallName();
        if (null !== $firewallName && !$request->attributes->getBoolean('_stateless') && $targetUrl = $this->getTargetPath($request->getSession(), $firewallName)) {
            $this->removeTargetPath($request->getSession(), $firewallName);
            return $targetUrl;
        }
        if ($this->options['use_referer'] && $targetUrl = $request->headers->get('Referer')) {
            if (\false !== $pos = strpos($targetUrl, '?')) {
                $targetUrl = substr($targetUrl, 0, $pos);
            }
            if ($targetUrl && $targetUrl !== $this->httpUtils->generateUri($request, $this->options['login_path'])) {
                return $targetUrl;
            }
        }
        return $this->options['default_target_path'];
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Security\Http;

use _ContaoManager\Symfony\Component\HttpFoundation\Request;
use _ContaoManager\Symfony\Component\HttpFoundation\RequestMatcherInterface;
/**
 * AccessMap allows configuration of different access control rules for
 * specific parts of the website.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class AccessMap implements AccessMapInterface
{
    private array $map = [];
    /**
     * @param array       $attributes An array of attributes to pass to the access decision manager (like roles)
     * @param string|null $channel    The channel to enforce (http, https, or null)
     *
     * @return void
     */
    public function add(RequestMatcherInterface $requestMatcher, array $attributes = [], ?string $channel = null)
    {
        $this->map[] = [$requestMatcher, $attributes, $channel];
    }
    public function getPatterns(Request $request): array
    {
        foreach ($this->map as $elements) {
            if (null === $elements[0] || $elements[0]->matches($request)) {
                return [$elements[1], $elements[2]];
            }
        }
        return [null, null];
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Security\Http\Event;

use _ContaoManager\Symfony\Component\HttpFoundation\Request;
use _ContaoManager\Symfony\Component\HttpFoundation\Response;
use _ContaoManager\Symfony\Component\Security\Core\Exception\AuthenticationException;
use _ContaoManager\Symfony\Component\Security\Http\Authenticator\AuthenticatorInterface;
use _ContaoManager\Symfony\Component\Security\Http\Authenticator\Debug\TraceableAuthenticator;
use _ContaoManager\Symfony\Component\Security\Http\Authenticator\Passport\Passport;
use _ContaoManager\Symfony\Contracts\EventDispatcher\Event;
/**
 * This event is dispatched after an error during authentication.
 *
 * Listeners to this event can change state based on authentication
 * failure (e.g. to implement login throttling).
 *
 * @author Wouter de Jong <wouter@wouterj.nl>
 */
class LoginFailureEvent extends Event
{
    private AuthenticationException $exception;
    private AuthenticatorInterface $authenticator;
    private Request $request;
    private ?Response $response;
    private string $firewallName;
    private ?Passport $passport;
    public function __construct(AuthenticationException $exception, AuthenticatorInterface $authenticator, Request $request, ?Response $response, string $firewallName, ?Passport $passport = null)
    {
        $this->exception = $exception;
        $this->authenticator = $authenticator;
        $this->request = $request;
        $this->response = $response;
        $this->firewallName = $firewallName;
        $this->passport = $passport;
    }
    public function getException(): AuthenticationException
    {
        return $this->exception;
    }
    public function getAuthenticator(): AuthenticatorInterface
    {
        return $this->authenticator instanceof TraceableAuthenticator ? $this->authenticator->getAuthenticator() : $this->authenticator;
    }
    public function getFirewallName(): string
    {
        return $this->firewallName;
    }
    public function getRequest(): Request
    {
        return $this->request;
    }
    /**
     * @return void
     */
    public function setResponse(?Response $response)
    {
        $this->response = $response;
    }
    public function getResponse(): ?Response
    {
        return $this->response;
    }
    public function getPassport(): ?Passport
    {
        return $this->passport;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Security\Http\Event;

use _ContaoManager\Symfony\Component\HttpFoundation\Request;
use _ContaoManager\Symfony\Component\HttpFoundation\Response;
use _ContaoManager\Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use _ContaoManager\Symfony\Component\Security\Core\User\UserInterface;
use _ContaoManager\Symfony\Component\Security\Http\Authenticator\AuthenticatorInterface;
use _ContaoManager\Symfony\Component\Security\Http\Authenticator\Debug\TraceableAuthenticator;
use _ContaoManager\Symfony\Component\Security\Http\Authenticator\Passport\Passport;
use _ContaoManager\Symfony\Contracts\EventDispatcher\Event;
/**
 * This event is dispatched after authentication has successfully completed.
 *
 * At this stage, the authenticator created a token and
 * generated an authentication success response. Listeners to
 * this event can do actions related to successful authentication
 * (such as migrating the password).
 *
 * @author Wouter de Jong <wouter@wouterj.nl>
 */
class LoginSuccessEvent extends Event
{
    private AuthenticatorInterface $authenticator;
    private Passport $passport;
    private TokenInterface $authenticatedToken;
    private ?TokenInterface $previousToken;
    private Request $request;
    private ?Response $response;
    private string $firewallName;
    public function __construct(AuthenticatorInterface $authenticator, Passport $passport, TokenInterface $authenticatedToken, Request $request, ?Response $response, string $firewallName, ?TokenInterface $previousToken = null)
    {
        $this->authenticator = $authenticator;
        $this->passport = $passport;
        $this->authenticatedToken = $authenticatedToken;
        $this->previousToken = $previousToken;
        $this->request = $request;
        $this->response = $response;
        $this->firewallName = $firewallName;
    }
    public function getAuthenticator(): AuthenticatorInterface
    {
        return $this->authenticator instanceof TraceableAuthenticator ? $this->authenticator->getAuthenticator() : $this->authenticator;
    }
    public function getPassport(): Passport
    {
        return $this->passport;
    }
    public function getUser(): UserInterface
    {
        return $this->passport->getUser();
    }
    public function getAuthenticatedToken(): TokenInterface
    {
        return $this->authenticatedToken;
    }
    public function getPreviousToken(): ?TokenInterface
    {
        return $this->previousToken;
    }
    public function getRequest(): Request
    {
        return $this->request;
    }
    public function getFirewallName(): string
    {
        return $this->firewallName;
    }
    public function setResponse(?Response $response): void
    {
        $this->response = $response;
    }
    public function getResponse(): ?Response
    {
        return $this->response;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Security\Http\Event;

use _ContaoManager\Symfony\Component\HttpFoundation\Request;
use _ContaoManager\Symfony\Component\HttpFoundation\Response;
use _ContaoManager\Symfony\Component\HttpKernel\Event\RequestEvent;
use _ContaoManager\Symfony\Component\HttpKernel\HttpKernelInterface;
use _ContaoManager\Symfony\Component\Security\Core\Exception\LazyResponseException;
/**
 * Wraps a lazily computed response in a signaling exception.
 *
 * @author Nicolas Grekas <p@tchwork.com>
 */
final class LazyResponseEvent extends RequestEvent
{
    private parent $event;
    public function __construct(parent $event)
    {
        $this->event = $event;
    }
    public function setResponse(Response $response): never
    {
        $this->stopPropagation();
        $this->event->stopPropagation();
        throw new LazyResponseException($response);
    }
    public function getKernel(): HttpKernelInterface
    {
        return $this->event->getKernel();
    }
    public function getRequest(): Request
    {
        return $this->event->getRequest();
    }
    public function getRequestType(): int
    {
        return $this->event->getRequestType();
    }
    public function isMainRequest(): bool
    {
        return $this->event->isMainRequest();
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Security\Http\Event;

use _ContaoManager\Symfony\Component\HttpFoundation\Request;
use _ContaoManager\Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use _ContaoManager\Symfony\Component\Security\Core\User\UserInterface;
use _ContaoManager\Symfony\Contracts\EventDispatcher\Event;
/**
 * SwitchUserEvent.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
final class SwitchUserEvent extends Event
{
    private Request $request;
    private UserInterface $targetUser;
    private ?TokenInterface $token;
    public function __construct(Request $request, UserInterface $targetUser, ?TokenInterface $token = null)
    {
        $this->request = $request;
        $this->targetUser = $targetUser;
        $this->token = $token;
    }
    public function getRequest(): Request
    {
        return $this->request;
    }
    public function getTargetUser(): UserInterface
    {
        return $this->targetUser;
    }
    public function getToken(): ?TokenInterface
    {
        return $this->token;
    }
    public function setToken(TokenInterface $token): void
    {
        $this->token = $token;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Security\Http\Event;

use _ContaoManager\Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use _ContaoManager\Symfony\Component\Security\Http\Authenticator\Passport\Passport;
use _ContaoManager\Symfony\Contracts\EventDispatcher\Event;
/**
 * When a newly authenticated security token was created, before it becomes effective in the security system.
 *
 * @author Christian Scheb <me@christianscheb.de>
 */
class AuthenticationTokenCreatedEvent extends Event
{
    private TokenInterface $authenticatedToken;
    private Passport $passport;
    public function __construct(TokenInterface $token, Passport $passport)
    {
        $this->authenticatedToken = $token;
        $this->passport = $passport;
    }
    public function getAuthenticatedToken(): TokenInterface
    {
        return $this->authenticatedToken;
    }
    public function setAuthenticatedToken(TokenInterface $authenticatedToken): void
    {
        $this->authenticatedToken = $authenticatedToken;
    }
    public function getPassport(): Passport
    {
        return $this->passport;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Security\Http\Event;

use _ContaoManager\Symfony\Component\Security\Http\Authenticator\AuthenticatorInterface;
use _ContaoManager\Symfony\Component\Security\Http\Authenticator\Debug\TraceableAuthenticator;
use _ContaoManager\Symfony\Component\Security\Http\Authenticator\Passport\Passport;
use _ContaoManager\Symfony\Contracts\EventDispatcher\Event;
/**
 * This event is dispatched when the credentials have to be checked.
 *
 * Listeners to this event must validate the user and the
 * credentials (e.g. default listeners do password verification and
 * user checking)
 *
 * @author Wouter de Jong <wouter@wouterj.nl>
 */
class CheckPassportEvent extends Event
{
    private AuthenticatorInterface $authenticator;
    private Passport $passport;
    public function __construct(AuthenticatorInterface $authenticator, Passport $passport)
    {
        $this->authenticator = $authenticator;
        $this->passport = $passport;
    }
    public function getAuthenticator(): AuthenticatorInterface
    {
        return $this->authenticator instanceof TraceableAuthenticator ? $this->authenticator->getAuthenticator() : $this->authenticator;
    }
    public function getPassport(): Passport
    {
        return $this->passport;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Security\Http\Event;

use _ContaoManager\Symfony\Component\HttpFoundation\Request;
use _ContaoManager\Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use _ContaoManager\Symfony\Contracts\EventDispatcher\Event;
/**
 * @author Fabien Potencier <fabien@symfony.com>
 */
final class InteractiveLoginEvent extends Event
{
    private Request $request;
    private TokenInterface $authenticationToken;
    public function __construct(Request $request, TokenInterface $authenticationToken)
    {
        $this->request = $request;
        $this->authenticationToken = $authenticationToken;
    }
    public function getRequest(): Request
    {
        return $this->request;
    }
    public function getAuthenticationToken(): TokenInterface
    {
        return $this->authenticationToken;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Security\Http\Event;

use _ContaoManager\Symfony\Component\HttpFoundation\Request;
use _ContaoManager\Symfony\Component\HttpFoundation\Response;
use _ContaoManager\Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use _ContaoManager\Symfony\Contracts\EventDispatcher\Event;
/**
 * @author Wouter de Jong <wouter@wouterj.nl>
 */
class LogoutEvent extends Event
{
    private Request $request;
    private ?Response $response = null;
    private ?TokenInterface $token;
    public function __construct(Request $request, ?TokenInterface $token)
    {
        $this->request = $request;
        $this->token = $token;
    }
    public function getRequest(): Request
    {
        return $this->request;
    }
    public function getToken(): ?TokenInterface
    {
        return $this->token;
    }
    public function setResponse(Response $response): void
    {
        $this->response = $response;
    }
    public function getResponse(): ?Response
    {
        return $this->response;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Security\Http\Event;

use _ContaoManager\Symfony\Component\HttpFoundation\Request;
use _ContaoManager\Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use _ContaoManager\Symfony\Contracts\EventDispatcher\Event;
/**
 * This event is dispatched when the current security token is deauthenticated
 * when trying to reference the token.
 *
 * This includes changes in the user ({@see DeauthenticatedEvent}), but
 * also cases where there is no user provider available to refresh the user.
 *
 * Use this event if you want to trigger some actions whenever a user is
 * deauthenticated and redirected back to the authentication entry point
 * (e.g. clearing all remember-me cookies).
 *
 * @author Wouter de Jong <wouter@wouterj.nl>
 */
final class TokenDeauthenticatedEvent extends Event
{
    private TokenInterface $originalToken;
    private Request $request;
    public function __construct(TokenInterface $originalToken, Request $request)
    {
        $this->originalToken = $originalToken;
        $this->request = $request;
    }
    public function getOriginalToken(): TokenInterface
    {
        return $this->originalToken;
    }
    public function getRequest(): Request
    {
        return $this->request;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Security\Http\Impersonate;

use _ContaoManager\Symfony\Bundle\SecurityBundle\Security\FirewallMap;
use _ContaoManager\Symfony\Component\HttpFoundation\RequestStack;
use _ContaoManager\Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
use _ContaoManager\Symfony\Component\Security\Core\Authentication\Token\SwitchUserToken;
use _ContaoManager\Symfony\Component\Security\Http\Firewall\SwitchUserListener;
/**
 * Provides generator functions for the impersonation urls.
 *
 * @author Amrouche Hamza <hamza.simperfit@gmail.com>
 * @author Damien Fayet <damienf1521@gmail.com>
 */
class ImpersonateUrlGenerator
{
    private RequestStack $requestStack;
    private TokenStorageInterface $tokenStorage;
    private FirewallMap $firewallMap;
    public function __construct(RequestStack $requestStack, FirewallMap $firewallMap, TokenStorageInterface $tokenStorage)
    {
        $this->requestStack = $requestStack;
        $this->tokenStorage = $tokenStorage;
        $this->firewallMap = $firewallMap;
    }
    public function generateImpersonationPath(string $identifier): string
    {
        return $this->buildPath(null, $identifier);
    }
    public function generateImpersonationUrl(string $identifier): string
    {
        if (null === $request = $this->requestStack->getCurrentRequest()) {
            return '';
        }
        return $request->getUriForPath($this->buildPath(null, $identifier));
    }
    public function generateExitPath(?string $targetUri = null): string
    {
        return $this->buildPath($targetUri);
    }
    public function generateExitUrl(?string $targetUri = null): string
    {
        if (null === $request = $this->requestStack->getCurrentRequest()) {
            return '';
        }
        return $request->getUriForPath($this->buildPath($targetUri));
    }
    private function isImpersonatedUser(): bool
    {
        return $this->tokenStorage->getToken() instanceof SwitchUserToken;
    }
    private function buildPath(?string $targetUri = null, string $identifier = SwitchUserListener::EXIT_VALUE): string
    {
        if (null === $request = $this->requestStack->getCurrentRequest()) {
            return '';
        }
        if (!$this->isImpersonatedUser() && SwitchUserListener::EXIT_VALUE == $identifier) {
            return '';
        }
        if (null === $switchUserConfig = $this->firewallMap->getFirewallConfig($request)->getSwitchUser()) {
            throw new \LogicException('Unable to generate the impersonate URLs without a firewall configured for the user switch.');
        }
        $targetUri ??= $request->getRequestUri();
        $targetUri .= (str_contains($targetUri, '?') ? '&' : '?') . http_build_query([$switchUserConfig['parameter'] => $identifier], '', '&');
        return $targetUri;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Security\Http;

use _ContaoManager\Symfony\Component\HttpFoundation\ParameterBag;
use _ContaoManager\Symfony\Component\HttpFoundation\Request;
use _ContaoManager\Symfony\Component\PropertyAccess\Exception\AccessException;
use _ContaoManager\Symfony\Component\PropertyAccess\Exception\InvalidArgumentException;
use _ContaoManager\Symfony\Component\PropertyAccess\PropertyAccess;
use _ContaoManager\Symfony\Component\PropertyAccess\PropertyAccessorInterface;
/**
 * @internal
 */
final class ParameterBagUtils
{
    private static PropertyAccessorInterface $propertyAccessor;
    /**
     * Returns a "parameter" value.
     *
     * Paths like foo[bar] will be evaluated to find deeper items in nested data structures.
     *
     * @throws InvalidArgumentException when the given path is malformed
     */
    public static function getParameterBagValue(ParameterBag $parameters, string $path): mixed
    {
        if (\false === $pos = strpos($path, '[')) {
            return $parameters->all()[$path] ?? null;
        }
        $root = substr($path, 0, $pos);
        if (null === $value = $parameters->all()[$root] ?? null) {
            return null;
        }
        self::$propertyAccessor ??= PropertyAccess::createPropertyAccessor();
        try {
            return self::$propertyAccessor->getValue($value, substr($path, $pos));
        } catch (AccessException) {
            return null;
        }
    }
    /**
     * Returns a request "parameter" value.
     *
     * Paths like foo[bar] will be evaluated to find deeper items in nested data structures.
     *
     * @throws InvalidArgumentException when the given path is malformed
     */
    public static function getRequestParameterValue(Request $request, string $path, array $parameters = []): mixed
    {
        if (\false === $pos = strpos($path, '[')) {
            return $parameters[$path] ?? $request->get($path);
        }
        $root = substr($path, 0, $pos);
        if (null === $value = $parameters[$root] ?? $request->get($root)) {
            return null;
        }
        self::$propertyAccessor ??= PropertyAccess::createPropertyAccessor();
        try {
            $value = self::$propertyAccessor->getValue($value, substr($path, $pos));
            if (null === $value && isset($parameters[$root]) && null !== $value = $request->get($root)) {
                $value = self::$propertyAccessor->getValue($value, substr($path, $pos));
            }
            return $value;
        } catch (AccessException) {
            return null;
        }
    }
}
{
    "name": "symfony\/security-http",
    "type": "library",
    "description": "Symfony Security Component - HTTP Integration",
    "keywords": [],
    "homepage": "https:\/\/symfony.com",
    "license": "MIT",
    "authors": [
        {
            "name": "Fabien Potencier",
            "email": "fabien@symfony.com"
        },
        {
            "name": "Symfony Community",
            "homepage": "https:\/\/symfony.com\/contributors"
        }
    ],
    "require": {
        "php": ">=8.1",
        "symfony\/deprecation-contracts": "^2.5|^3",
        "symfony\/http-foundation": "^6.2|^7.0",
        "symfony\/http-kernel": "^6.3|^7.0",
        "symfony\/polyfill-mbstring": "~1.0",
        "symfony\/property-access": "^5.4|^6.0|^7.0",
        "symfony\/security-core": "^6.4|^7.0",
        "symfony\/service-contracts": "^2.5|^3"
    },
    "require-dev": {
        "symfony\/cache": "^5.4|^6.0|^7.0",
        "symfony\/clock": "^6.3|^7.0",
        "symfony\/expression-language": "^5.4|^6.0|^7.0",
        "symfony\/http-client-contracts": "^3.0",
        "symfony\/rate-limiter": "^5.4|^6.0|^7.0",
        "symfony\/routing": "^5.4|^6.0|^7.0",
        "symfony\/security-csrf": "^5.4|^6.0|^7.0",
        "symfony\/translation": "^5.4|^6.0|^7.0",
        "psr\/log": "^1|^2|^3",
        "web-token\/jwt-checker": "^3.1",
        "web-token\/jwt-signature-algorithm-ecdsa": "^3.1"
    },
    "conflict": {
        "symfony\/clock": "<6.3",
        "symfony\/event-dispatcher": "<5.4.9|>=6,<6.0.9",
        "symfony\/http-client-contracts": "<3.0",
        "symfony\/security-bundle": "<5.4",
        "symfony\/security-csrf": "<5.4"
    },
    "autoload": {
        "psr-4": {
            "_ContaoManager\\Symfony\\Component\\Security\\Http\\": ""
        },
        "exclude-from-classmap": [
            "\/Tests\/"
        ]
    },
    "minimum-stability": "dev"
}<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Security\Http;

/**
 * List of request attributes used along the security flow.
 *
 * @author Robin Chalas <robin.chalas@gmail.com>
 */
final class SecurityRequestAttributes
{
    public const ACCESS_DENIED_ERROR = '_security.403_error';
    public const AUTHENTICATION_ERROR = '_security.last_error';
    public const LAST_USERNAME = '_security.last_username';
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Security\Http\EventListener;

use _ContaoManager\Symfony\Component\EventDispatcher\EventSubscriberInterface;
use _ContaoManager\Symfony\Component\Security\Http\Event\LogoutEvent;
/**
 * Handler for Clear-Site-Data header during logout.
 *
 * @author Max Beckers <beckers.maximilian@gmail.com>
 *
 * @final
 */
class ClearSiteDataLogoutListener implements EventSubscriberInterface
{
    private const HEADER_NAME = 'Clear-Site-Data';
    /**
     * @param string[] $cookieValue The value for the Clear-Site-Data header.
     *                              Can be '*' or a subset of 'cache', 'cookies', 'storage', 'executionContexts'.
     */
    public function __construct(private readonly array $cookieValue)
    {
    }
    public function onLogout(LogoutEvent $event): void
    {
        if (!$event->getResponse()?->headers->has(static::HEADER_NAME)) {
            $event->getResponse()->headers->set(static::HEADER_NAME, implode(', ', array_map(fn($v) => '"' . $v . '"', $this->cookieValue)));
        }
    }
    public static function getSubscribedEvents(): array
    {
        return [LogoutEvent::class => 'onLogout'];
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Security\Http\EventListener;

use _ContaoManager\Symfony\Component\EventDispatcher\EventSubscriberInterface;
use _ContaoManager\Symfony\Component\Security\Http\Event\LogoutEvent;
/**
 * Handler for clearing invalidating the current session.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 *
 * @final
 */
class SessionLogoutListener implements EventSubscriberInterface
{
    public function onLogout(LogoutEvent $event): void
    {
        if ($event->getRequest()->hasSession()) {
            $event->getRequest()->getSession()->invalidate();
        }
    }
    public static function getSubscribedEvents(): array
    {
        return [LogoutEvent::class => 'onLogout'];
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Security\Http\EventListener;

use _ContaoManager\Symfony\Component\EventDispatcher\EventSubscriberInterface;
use _ContaoManager\Symfony\Component\Security\Http\Event\LogoutEvent;
use _ContaoManager\Symfony\Component\Security\Http\HttpUtils;
/**
 * Default logout listener will redirect users to a configured path.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 * @author Alexander <iam.asm89@gmail.com>
 *
 * @final
 */
class DefaultLogoutListener implements EventSubscriberInterface
{
    private HttpUtils $httpUtils;
    private string $targetUrl;
    public function __construct(HttpUtils $httpUtils, string $targetUrl = '/')
    {
        $this->httpUtils = $httpUtils;
        $this->targetUrl = $targetUrl;
    }
    public function onLogout(LogoutEvent $event): void
    {
        if (null !== $event->getResponse()) {
            return;
        }
        $event->setResponse($this->httpUtils->createRedirectResponse($event->getRequest(), $this->targetUrl));
    }
    public static function getSubscribedEvents(): array
    {
        return [LogoutEvent::class => ['onLogout', 64]];
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Security\Http\EventListener;

use _ContaoManager\Symfony\Component\EventDispatcher\EventSubscriberInterface;
use _ContaoManager\Symfony\Component\PasswordHasher\Hasher\PasswordHasherFactoryInterface;
use _ContaoManager\Symfony\Component\Security\Core\User\LegacyPasswordAuthenticatedUserInterface;
use _ContaoManager\Symfony\Component\Security\Core\User\PasswordAuthenticatedUserInterface;
use _ContaoManager\Symfony\Component\Security\Core\User\PasswordUpgraderInterface;
use _ContaoManager\Symfony\Component\Security\Http\Authenticator\Passport\Badge\PasswordUpgradeBadge;
use _ContaoManager\Symfony\Component\Security\Http\Authenticator\Passport\Badge\UserBadge;
use _ContaoManager\Symfony\Component\Security\Http\Event\LoginSuccessEvent;
/**
 * @author Wouter de Jong <wouter@wouterj.nl>
 *
 * @final
 */
class PasswordMigratingListener implements EventSubscriberInterface
{
    private PasswordHasherFactoryInterface $hasherFactory;
    public function __construct(PasswordHasherFactoryInterface $hasherFactory)
    {
        $this->hasherFactory = $hasherFactory;
    }
    public function onLoginSuccess(LoginSuccessEvent $event): void
    {
        $passport = $event->getPassport();
        if (!$passport->hasBadge(PasswordUpgradeBadge::class)) {
            return;
        }
        /** @var PasswordUpgradeBadge $badge */
        $badge = $passport->getBadge(PasswordUpgradeBadge::class);
        $plaintextPassword = $badge->getAndErasePlaintextPassword();
        if ('' === $plaintextPassword) {
            return;
        }
        $user = $passport->getUser();
        if (!$user instanceof PasswordAuthenticatedUserInterface || null === $user->getPassword()) {
            return;
        }
        $passwordHasher = $this->hasherFactory->getPasswordHasher($user);
        if (!$passwordHasher->needsRehash($user->getPassword())) {
            return;
        }
        $passwordUpgrader = $badge->getPasswordUpgrader();
        if (null === $passwordUpgrader) {
            if (!$passport->hasBadge(UserBadge::class)) {
                return;
            }
            /** @var UserBadge $userBadge */
            $userBadge = $passport->getBadge(UserBadge::class);
            $userLoader = $userBadge->getUserLoader();
            if (\is_array($userLoader) && $userLoader[0] instanceof PasswordUpgraderInterface) {
                $passwordUpgrader = $userLoader[0];
            } elseif (!$userLoader instanceof \Closure || !($passwordUpgrader = (new \ReflectionFunction($userLoader))->getClosureThis()) instanceof PasswordUpgraderInterface) {
                return;
            }
        }
        $salt = null;
        if ($user instanceof LegacyPasswordAuthenticatedUserInterface) {
            $salt = $user->getSalt();
        }
        $passwordUpgrader->upgradePassword($user, $passwordHasher->hash($plaintextPassword, $salt));
    }
    public static function getSubscribedEvents(): array
    {
        return [LoginSuccessEvent::class => 'onLoginSuccess'];
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Security\Http\EventListener;

use _ContaoManager\Psr\Log\LoggerInterface;
use _ContaoManager\Symfony\Component\EventDispatcher\EventSubscriberInterface;
use _ContaoManager\Symfony\Component\Security\Http\Authenticator\Passport\Badge\RememberMeBadge;
use _ContaoManager\Symfony\Component\Security\Http\Event\LoginFailureEvent;
use _ContaoManager\Symfony\Component\Security\Http\Event\LoginSuccessEvent;
use _ContaoManager\Symfony\Component\Security\Http\Event\LogoutEvent;
use _ContaoManager\Symfony\Component\Security\Http\Event\TokenDeauthenticatedEvent;
use _ContaoManager\Symfony\Component\Security\Http\RememberMe\RememberMeHandlerInterface;
/**
 * The RememberMe *listener* creates and deletes remember-me cookies.
 *
 * Upon login success or failure and support for remember me
 * in the firewall and authenticator, this listener will create
 * a remember-me cookie.
 * Upon login failure, all remember-me cookies are removed.
 *
 * @author Wouter de Jong <wouter@wouterj.nl>
 *
 * @final
 */
class RememberMeListener implements EventSubscriberInterface
{
    private RememberMeHandlerInterface $rememberMeHandler;
    private ?LoggerInterface $logger;
    public function __construct(RememberMeHandlerInterface $rememberMeHandler, ?LoggerInterface $logger = null)
    {
        $this->rememberMeHandler = $rememberMeHandler;
        $this->logger = $logger;
    }
    public function onSuccessfulLogin(LoginSuccessEvent $event): void
    {
        $passport = $event->getPassport();
        if (!$passport->hasBadge(RememberMeBadge::class)) {
            $this->logger?->debug('Remember me skipped: your authenticator does not support it.', ['authenticator' => $event->getAuthenticator()::class]);
            return;
        }
        // Make sure any old remember-me cookies are cancelled
        $this->rememberMeHandler->clearRememberMeCookie();
        /** @var RememberMeBadge $badge */
        $badge = $passport->getBadge(RememberMeBadge::class);
        if (!$badge->isEnabled()) {
            $this->logger?->debug('Remember me skipped: the RememberMeBadge is not enabled.');
            return;
        }
        $this->logger?->debug('Remember-me was requested; setting cookie.');
        $this->rememberMeHandler->createRememberMeCookie($event->getUser());
    }
    public function clearCookie(): void
    {
        $this->rememberMeHandler->clearRememberMeCookie();
    }
    public static function getSubscribedEvents(): array
    {
        return [LoginSuccessEvent::class => ['onSuccessfulLogin', -64], LoginFailureEvent::class => 'clearCookie', LogoutEvent::class => 'clearCookie', TokenDeauthenticatedEvent::class => 'clearCookie'];
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Security\Http\EventListener;

use _ContaoManager\Symfony\Component\EventDispatcher\EventSubscriberInterface;
use _ContaoManager\Symfony\Component\HttpFoundation\RateLimiter\PeekableRequestRateLimiterInterface;
use _ContaoManager\Symfony\Component\HttpFoundation\RateLimiter\RequestRateLimiterInterface;
use _ContaoManager\Symfony\Component\HttpFoundation\RequestStack;
use _ContaoManager\Symfony\Component\Security\Core\Exception\TooManyLoginAttemptsAuthenticationException;
use _ContaoManager\Symfony\Component\Security\Http\Authenticator\Passport\Badge\UserBadge;
use _ContaoManager\Symfony\Component\Security\Http\Event\CheckPassportEvent;
use _ContaoManager\Symfony\Component\Security\Http\Event\LoginFailureEvent;
use _ContaoManager\Symfony\Component\Security\Http\Event\LoginSuccessEvent;
use _ContaoManager\Symfony\Component\Security\Http\SecurityRequestAttributes;
/**
 * @author Wouter de Jong <wouter@wouterj.nl>
 */
final class LoginThrottlingListener implements EventSubscriberInterface
{
    private RequestStack $requestStack;
    private RequestRateLimiterInterface $limiter;
    public function __construct(RequestStack $requestStack, RequestRateLimiterInterface $limiter)
    {
        $this->requestStack = $requestStack;
        $this->limiter = $limiter;
    }
    public function checkPassport(CheckPassportEvent $event): void
    {
        $passport = $event->getPassport();
        if (!$passport->hasBadge(UserBadge::class)) {
            return;
        }
        $request = $this->requestStack->getMainRequest();
        $request->attributes->set(SecurityRequestAttributes::LAST_USERNAME, $passport->getBadge(UserBadge::class)->getUserIdentifier());
        if ($this->limiter instanceof PeekableRequestRateLimiterInterface) {
            $limit = $this->limiter->peek($request);
            // Checking isAccepted here is not enough as peek consumes 0 token, it will
            // be accepted even if there are 0 tokens remaining to be consumed. We check both
            // anyway for safety in case third party implementations behave unexpectedly.
            if (!$limit->isAccepted() || 0 === $limit->getRemainingTokens()) {
                throw new TooManyLoginAttemptsAuthenticationException(ceil(($limit->getRetryAfter()->getTimestamp() - time()) / 60));
            }
        } else {
            $limit = $this->limiter->consume($request);
            if (!$limit->isAccepted()) {
                throw new TooManyLoginAttemptsAuthenticationException(ceil(($limit->getRetryAfter()->getTimestamp() - time()) / 60));
            }
        }
    }
    public function onSuccessfulLogin(LoginSuccessEvent $event): void
    {
        if (!$this->limiter instanceof PeekableRequestRateLimiterInterface) {
            $this->limiter->reset($event->getRequest());
        }
    }
    public function onFailedLogin(LoginFailureEvent $event): void
    {
        if ($this->limiter instanceof PeekableRequestRateLimiterInterface) {
            $this->limiter->consume($event->getRequest());
        }
    }
    public static function getSubscribedEvents(): array
    {
        return [CheckPassportEvent::class => ['checkPassport', 2080], LoginFailureEvent::class => 'onFailedLogin', LoginSuccessEvent::class => 'onSuccessfulLogin'];
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Security\Http\EventListener;

use _ContaoManager\Symfony\Component\Security\Core\User\UserProviderInterface;
use _ContaoManager\Symfony\Component\Security\Http\Authenticator\Passport\Badge\UserBadge;
use _ContaoManager\Symfony\Component\Security\Http\Event\CheckPassportEvent;
/**
 * Configures the user provider as user loader, if no user load
 * has been explicitly set.
 *
 * @author Wouter de Jong <wouter@wouterj.nl>
 *
 * @final
 */
class UserProviderListener
{
    private UserProviderInterface $userProvider;
    public function __construct(UserProviderInterface $userProvider)
    {
        $this->userProvider = $userProvider;
    }
    public function checkPassport(CheckPassportEvent $event): void
    {
        $passport = $event->getPassport();
        if (!$passport->hasBadge(UserBadge::class)) {
            return;
        }
        /** @var UserBadge $badge */
        $badge = $passport->getBadge(UserBadge::class);
        if (null !== $badge->getUserLoader()) {
            return;
        }
        $badge->setUserLoader($this->userProvider->loadUserByIdentifier(...));
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Security\Http\EventListener;

use _ContaoManager\Symfony\Component\EventDispatcher\EventSubscriberInterface;
use _ContaoManager\Symfony\Component\Security\Http\Event\LogoutEvent;
/**
 * This listener clears the passed cookies when a user logs out.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 *
 * @final
 */
class CookieClearingLogoutListener implements EventSubscriberInterface
{
    private array $cookies;
    /**
     * @param array $cookies An array of cookies (keys are names, values contain path and domain) to unset
     */
    public function __construct(array $cookies)
    {
        $this->cookies = $cookies;
    }
    public function onLogout(LogoutEvent $event): void
    {
        if (!$response = $event->getResponse()) {
            return;
        }
        foreach ($this->cookies as $cookieName => $cookieData) {
            $response->headers->clearCookie($cookieName, $cookieData['path'], $cookieData['domain'], $cookieData['secure'] ?? \false, \true, $cookieData['samesite'] ?? null, $cookieData['partitioned'] ?? \false);
        }
    }
    public static function getSubscribedEvents(): array
    {
        return [LogoutEvent::class => ['onLogout', -255]];
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Security\Http\EventListener;

use _ContaoManager\Symfony\Component\EventDispatcher\EventSubscriberInterface;
use _ContaoManager\Symfony\Component\PasswordHasher\Hasher\PasswordHasherFactoryInterface;
use _ContaoManager\Symfony\Component\Security\Core\Exception\BadCredentialsException;
use _ContaoManager\Symfony\Component\Security\Core\User\LegacyPasswordAuthenticatedUserInterface;
use _ContaoManager\Symfony\Component\Security\Core\User\PasswordAuthenticatedUserInterface;
use _ContaoManager\Symfony\Component\Security\Http\Authenticator\Passport\Badge\PasswordUpgradeBadge;
use _ContaoManager\Symfony\Component\Security\Http\Authenticator\Passport\Credentials\CustomCredentials;
use _ContaoManager\Symfony\Component\Security\Http\Authenticator\Passport\Credentials\PasswordCredentials;
use _ContaoManager\Symfony\Component\Security\Http\Event\CheckPassportEvent;
/**
 * This listeners uses the interfaces of authenticators to
 * determine how to check credentials.
 *
 * @author Wouter de Jong <wouter@driveamber.com>
 *
 * @final
 */
class CheckCredentialsListener implements EventSubscriberInterface
{
    private PasswordHasherFactoryInterface $hasherFactory;
    public function __construct(PasswordHasherFactoryInterface $hasherFactory)
    {
        $this->hasherFactory = $hasherFactory;
    }
    public function checkPassport(CheckPassportEvent $event): void
    {
        $passport = $event->getPassport();
        if ($passport->hasBadge(PasswordCredentials::class)) {
            // Use the password hasher to validate the credentials
            $user = $passport->getUser();
            if (!$user instanceof PasswordAuthenticatedUserInterface) {
                throw new \LogicException(\sprintf('Class "%s" must implement "%s" for using password-based authentication.', get_debug_type($user), PasswordAuthenticatedUserInterface::class));
            }
            /** @var PasswordCredentials $badge */
            $badge = $passport->getBadge(PasswordCredentials::class);
            if ($badge->isResolved()) {
                return;
            }
            $presentedPassword = $badge->getPassword();
            if ('' === $presentedPassword) {
                throw new BadCredentialsException('The presented password cannot be empty.');
            }
            if (null === $user->getPassword()) {
                throw new BadCredentialsException('The presented password is invalid.');
            }
            if (!$this->hasherFactory->getPasswordHasher($user)->verify($user->getPassword(), $presentedPassword, $user instanceof LegacyPasswordAuthenticatedUserInterface ? $user->getSalt() : null)) {
                throw new BadCredentialsException('The presented password is invalid.');
            }
            $badge->markResolved();
            if (!$passport->hasBadge(PasswordUpgradeBadge::class)) {
                $passport->addBadge(new PasswordUpgradeBadge($presentedPassword));
            }
            return;
        }
        if ($passport->hasBadge(CustomCredentials::class)) {
            /** @var CustomCredentials $badge */
            $badge = $passport->getBadge(CustomCredentials::class);
            if ($badge->isResolved()) {
                return;
            }
            $badge->executeCustomChecker($passport->getUser());
            return;
        }
    }
    public static function getSubscribedEvents(): array
    {
        return [CheckPassportEvent::class => 'checkPassport'];
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Security\Http\EventListener;

use _ContaoManager\Symfony\Component\EventDispatcher\EventSubscriberInterface;
use _ContaoManager\Symfony\Component\Security\Http\Event\LoginSuccessEvent;
use _ContaoManager\Symfony\Component\Security\Http\Session\SessionAuthenticationStrategy;
use _ContaoManager\Symfony\Component\Security\Http\Session\SessionAuthenticationStrategyInterface;
/**
 * Migrates/invalidates the session after successful login.
 *
 * This should be registered as subscriber to any "stateful" firewalls.
 *
 * @see SessionAuthenticationStrategy
 *
 * @author Wouter de Jong <wouter@wouterj.nl>
 */
class SessionStrategyListener implements EventSubscriberInterface
{
    private SessionAuthenticationStrategyInterface $sessionAuthenticationStrategy;
    public function __construct(SessionAuthenticationStrategyInterface $sessionAuthenticationStrategy)
    {
        $this->sessionAuthenticationStrategy = $sessionAuthenticationStrategy;
    }
    public function onSuccessfulLogin(LoginSuccessEvent $event): void
    {
        $request = $event->getRequest();
        $token = $event->getAuthenticatedToken();
        if (!$request->hasPreviousSession()) {
            return;
        }
        if ($previousToken = $event->getPreviousToken()) {
            $user = $token->getUserIdentifier();
            $previousUser = $previousToken->getUserIdentifier();
            if ('' !== ($user ?? '') && $user === $previousUser && $token::class === $previousToken::class) {
                return;
            }
        }
        $this->sessionAuthenticationStrategy->onAuthentication($request, $token);
    }
    public static function getSubscribedEvents(): array
    {
        return [LoginSuccessEvent::class => 'onSuccessfulLogin'];
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Security\Http\EventListener;

use _ContaoManager\Symfony\Component\EventDispatcher\EventSubscriberInterface;
use _ContaoManager\Symfony\Component\Security\Csrf\TokenStorage\ClearableTokenStorageInterface;
use _ContaoManager\Symfony\Component\Security\Csrf\TokenStorage\SessionTokenStorage;
use _ContaoManager\Symfony\Component\Security\Http\Event\LogoutEvent;
/**
 * @author Christian Flothmann <christian.flothmann@sensiolabs.de>
 *
 * @final
 */
class CsrfTokenClearingLogoutListener implements EventSubscriberInterface
{
    private ClearableTokenStorageInterface $csrfTokenStorage;
    public function __construct(ClearableTokenStorageInterface $csrfTokenStorage)
    {
        $this->csrfTokenStorage = $csrfTokenStorage;
    }
    public function onLogout(LogoutEvent $event): void
    {
        if ($this->csrfTokenStorage instanceof SessionTokenStorage && !$event->getRequest()->hasPreviousSession()) {
            return;
        }
        $this->csrfTokenStorage->clear();
    }
    public static function getSubscribedEvents(): array
    {
        return [LogoutEvent::class => 'onLogout'];
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Security\Http\EventListener;

use _ContaoManager\Symfony\Component\EventDispatcher\EventSubscriberInterface;
use _ContaoManager\Symfony\Component\Security\Core\Event\AuthenticationSuccessEvent;
use _ContaoManager\Symfony\Component\Security\Core\User\UserCheckerInterface;
use _ContaoManager\Symfony\Component\Security\Core\User\UserInterface;
use _ContaoManager\Symfony\Component\Security\Http\Authenticator\Passport\Badge\PreAuthenticatedUserBadge;
use _ContaoManager\Symfony\Component\Security\Http\Event\CheckPassportEvent;
/**
 * @author Wouter de Jong <wouter@wouterj.nl>
 *
 * @final
 */
class UserCheckerListener implements EventSubscriberInterface
{
    private UserCheckerInterface $userChecker;
    public function __construct(UserCheckerInterface $userChecker)
    {
        $this->userChecker = $userChecker;
    }
    public function preCheckCredentials(CheckPassportEvent $event): void
    {
        $passport = $event->getPassport();
        if ($passport->hasBadge(PreAuthenticatedUserBadge::class)) {
            return;
        }
        $this->userChecker->checkPreAuth($passport->getUser());
    }
    public function postCheckCredentials(AuthenticationSuccessEvent $event): void
    {
        $user = $event->getAuthenticationToken()->getUser();
        if (!$user instanceof UserInterface) {
            return;
        }
        $this->userChecker->checkPostAuth($user);
    }
    public static function getSubscribedEvents(): array
    {
        return [CheckPassportEvent::class => ['preCheckCredentials', 256], AuthenticationSuccessEvent::class => ['postCheckCredentials', 256]];
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Security\Http\EventListener;

use _ContaoManager\Symfony\Component\EventDispatcher\EventSubscriberInterface;
use _ContaoManager\Symfony\Component\ExpressionLanguage\Expression;
use _ContaoManager\Symfony\Component\ExpressionLanguage\ExpressionLanguage;
use _ContaoManager\Symfony\Component\HttpFoundation\Request;
use _ContaoManager\Symfony\Component\HttpKernel\Event\ControllerArgumentsEvent;
use _ContaoManager\Symfony\Component\HttpKernel\Exception\HttpException;
use _ContaoManager\Symfony\Component\HttpKernel\KernelEvents;
use _ContaoManager\Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface;
use _ContaoManager\Symfony\Component\Security\Core\Exception\AccessDeniedException;
use _ContaoManager\Symfony\Component\Security\Core\Exception\RuntimeException;
use _ContaoManager\Symfony\Component\Security\Http\Attribute\IsGranted;
/**
 * Handles the IsGranted attribute on controllers.
 *
 * @author Ryan Weaver <ryan@knpuniversity.com>
 */
class IsGrantedAttributeListener implements EventSubscriberInterface
{
    public function __construct(private readonly AuthorizationCheckerInterface $authChecker, private ?ExpressionLanguage $expressionLanguage = null)
    {
    }
    /**
     * @return void
     */
    public function onKernelControllerArguments(ControllerArgumentsEvent $event)
    {
        /** @var IsGranted[] $attributes */
        if (!\is_array($attributes = $event->getAttributes()[IsGranted::class] ?? null)) {
            return;
        }
        $request = $event->getRequest();
        $arguments = $event->getNamedArguments();
        foreach ($attributes as $attribute) {
            $subject = null;
            if ($subjectRef = $attribute->subject) {
                if (\is_array($subjectRef)) {
                    foreach ($subjectRef as $refKey => $ref) {
                        $subject[\is_string($refKey) ? $refKey : (string) $ref] = $this->getIsGrantedSubject($ref, $request, $arguments);
                    }
                } else {
                    $subject = $this->getIsGrantedSubject($subjectRef, $request, $arguments);
                }
            }
            if (!$this->authChecker->isGranted($attribute->attribute, $subject)) {
                $message = $attribute->message ?: \sprintf('Access Denied by #[IsGranted(%s)] on controller', $this->getIsGrantedString($attribute));
                if ($statusCode = $attribute->statusCode) {
                    throw new HttpException($statusCode, $message, code: $attribute->exceptionCode ?? 0);
                }
                $accessDeniedException = new AccessDeniedException($message, code: $attribute->exceptionCode ?? 403);
                $accessDeniedException->setAttributes($attribute->attribute);
                $accessDeniedException->setSubject($subject);
                throw $accessDeniedException;
            }
        }
    }
    public static function getSubscribedEvents(): array
    {
        return [KernelEvents::CONTROLLER_ARGUMENTS => ['onKernelControllerArguments', 20]];
    }
    private function getIsGrantedSubject(string|Expression $subjectRef, Request $request, array $arguments): mixed
    {
        if ($subjectRef instanceof Expression) {
            $this->expressionLanguage ??= new ExpressionLanguage();
            return $this->expressionLanguage->evaluate($subjectRef, ['request' => $request, 'args' => $arguments]);
        }
        if (!\array_key_exists($subjectRef, $arguments)) {
            throw new RuntimeException(\sprintf('Could not find the subject "%s" for the #[IsGranted] attribute. Try adding a "$%s" argument to your controller method.', $subjectRef, $subjectRef));
        }
        return $arguments[$subjectRef];
    }
    private function getIsGrantedString(IsGranted $isGranted): string
    {
        $processValue = fn($value) => \sprintf($value instanceof Expression ? 'new Expression("%s")' : '"%s"', $value);
        $argsString = $processValue($isGranted->attribute);
        if (null !== $subject = $isGranted->subject) {
            $subject = !\is_array($subject) ? $processValue($subject) : array_map(function ($key, $value) use ($processValue) {
                $value = $processValue($value);
                return \is_string($key) ? \sprintf('"%s" => %s', $key, $value) : $value;
            }, array_keys($subject), $subject);
            $argsString .= ', ' . (!\is_array($subject) ? $subject : '[' . implode(', ', $subject) . ']');
        }
        return $argsString;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Security\Http\EventListener;

use _ContaoManager\Symfony\Component\EventDispatcher\EventSubscriberInterface;
use _ContaoManager\Symfony\Component\Security\Core\Exception\InvalidCsrfTokenException;
use _ContaoManager\Symfony\Component\Security\Csrf\CsrfToken;
use _ContaoManager\Symfony\Component\Security\Csrf\CsrfTokenManagerInterface;
use _ContaoManager\Symfony\Component\Security\Http\Authenticator\Passport\Badge\CsrfTokenBadge;
use _ContaoManager\Symfony\Component\Security\Http\Event\CheckPassportEvent;
/**
 * @author Wouter de Jong <wouter@wouterj.nl>
 *
 * @final
 */
class CsrfProtectionListener implements EventSubscriberInterface
{
    private CsrfTokenManagerInterface $csrfTokenManager;
    public function __construct(CsrfTokenManagerInterface $csrfTokenManager)
    {
        $this->csrfTokenManager = $csrfTokenManager;
    }
    public function checkPassport(CheckPassportEvent $event): void
    {
        $passport = $event->getPassport();
        if (!$passport->hasBadge(CsrfTokenBadge::class)) {
            return;
        }
        /** @var CsrfTokenBadge $badge */
        $badge = $passport->getBadge(CsrfTokenBadge::class);
        if ($badge->isResolved()) {
            return;
        }
        $csrfToken = new CsrfToken($badge->getCsrfTokenId(), $badge->getCsrfToken());
        if (\false === $this->csrfTokenManager->isTokenValid($csrfToken)) {
            throw new InvalidCsrfTokenException('Invalid CSRF token.');
        }
        $badge->markResolved();
    }
    public static function getSubscribedEvents(): array
    {
        return [CheckPassportEvent::class => ['checkPassport', 512]];
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Security\Http\EventListener;

use _ContaoManager\Psr\Log\LoggerInterface;
use _ContaoManager\Symfony\Component\EventDispatcher\EventSubscriberInterface;
use _ContaoManager\Symfony\Component\Security\Http\Authenticator\Passport\Badge\RememberMeBadge;
use _ContaoManager\Symfony\Component\Security\Http\Event\LoginSuccessEvent;
use _ContaoManager\Symfony\Component\Security\Http\ParameterBagUtils;
/**
 * Checks if all conditions are met for remember me.
 *
 * The conditions that must be met for this listener to enable remember me:
 *  A) This badge is present in the Passport
 *  B) The remember_me key under your firewall is configured
 *  C) The "remember me" functionality is activated. This is usually
 *      done by having a _remember_me checkbox in your form, but
 *      can be configured by the "always_remember_me" and "remember_me_parameter"
 *      parameters under the "remember_me" firewall key (or "always_remember_me"
 *      is enabled)
 *
 * @author Wouter de Jong <wouter@wouterj.nl>
 *
 * @final
 */
class CheckRememberMeConditionsListener implements EventSubscriberInterface
{
    private array $options;
    private ?LoggerInterface $logger;
    public function __construct(array $options = [], ?LoggerInterface $logger = null)
    {
        $this->options = $options + ['always_remember_me' => \false, 'remember_me_parameter' => '_remember_me'];
        $this->logger = $logger;
    }
    public function onSuccessfulLogin(LoginSuccessEvent $event): void
    {
        $passport = $event->getPassport();
        if (!$passport->hasBadge(RememberMeBadge::class)) {
            return;
        }
        /** @var RememberMeBadge $badge */
        $badge = $passport->getBadge(RememberMeBadge::class);
        if (!$this->options['always_remember_me']) {
            $parameter = ParameterBagUtils::getRequestParameterValue($event->getRequest(), $this->options['remember_me_parameter'], $badge->parameters);
            if (!filter_var($parameter, \FILTER_VALIDATE_BOOL)) {
                $this->logger?->debug('Remember me disabled; request does not contain remember me parameter ("{parameter}").', ['parameter' => $this->options['remember_me_parameter']]);
                return;
            }
        }
        $badge->enable();
    }
    public static function getSubscribedEvents(): array
    {
        return [LoginSuccessEvent::class => ['onSuccessfulLogin', -32]];
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Security\Http\Session;

use _ContaoManager\Symfony\Component\HttpFoundation\Request;
use _ContaoManager\Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
/**
 * SessionAuthenticationStrategyInterface.
 *
 * Implementation are responsible for updating the session after an interactive
 * authentication attempt was successful.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
interface SessionAuthenticationStrategyInterface
{
    /**
     * This performs any necessary changes to the session.
     *
     * This method should be called before the TokenStorage is populated with a
     * Token. It should be used by authentication listeners when a session is used.
     *
     * @return void
     */
    public function onAuthentication(Request $request, TokenInterface $token);
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Security\Http\Session;

use _ContaoManager\Symfony\Component\HttpFoundation\Request;
use _ContaoManager\Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use _ContaoManager\Symfony\Component\Security\Csrf\TokenStorage\ClearableTokenStorageInterface;
/**
 * The default session strategy implementation.
 *
 * Supports the following strategies:
 * NONE: the session is not changed
 * MIGRATE: the session id is updated, attributes are kept
 * INVALIDATE: the session id is updated, attributes are lost
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
class SessionAuthenticationStrategy implements SessionAuthenticationStrategyInterface
{
    public const NONE = 'none';
    public const MIGRATE = 'migrate';
    public const INVALIDATE = 'invalidate';
    private string $strategy;
    private ?ClearableTokenStorageInterface $csrfTokenStorage = null;
    public function __construct(string $strategy, ?ClearableTokenStorageInterface $csrfTokenStorage = null)
    {
        $this->strategy = $strategy;
        if (self::MIGRATE === $strategy) {
            $this->csrfTokenStorage = $csrfTokenStorage;
        }
    }
    /**
     * @return void
     */
    public function onAuthentication(Request $request, TokenInterface $token)
    {
        switch ($this->strategy) {
            case self::NONE:
                return;
            case self::MIGRATE:
                $request->getSession()->migrate(\true);
                if ($this->csrfTokenStorage) {
                    $this->csrfTokenStorage->clear();
                }
                return;
            case self::INVALIDATE:
                $request->getSession()->invalidate();
                return;
            default:
                throw new \RuntimeException(\sprintf('Invalid session authentication strategy "%s".', $this->strategy));
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Uid;

/**
 * A v8 UUID has no explicit requirements except embedding its version + variant bits.
 *
 * @author Nicolas Grekas <p@tchwork.com>
 */
class UuidV8 extends Uuid
{
    protected const TYPE = 8;
    public function __construct(string $uuid)
    {
        parent::__construct($uuid, \true);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Uid;

/**
 * @internal
 *
 * @author Nicolas Grekas <p@tchwork.com>
 */
class BinaryUtil
{
    public const BASE10 = ['' => '0123456789', 0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
    public const BASE58 = ['' => '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz', 1 => 0, 1, 2, 3, 4, 5, 6, 7, 8, 'A' => 9, 'B' => 10, 'C' => 11, 'D' => 12, 'E' => 13, 'F' => 14, 'G' => 15, 'H' => 16, 'J' => 17, 'K' => 18, 'L' => 19, 'M' => 20, 'N' => 21, 'P' => 22, 'Q' => 23, 'R' => 24, 'S' => 25, 'T' => 26, 'U' => 27, 'V' => 28, 'W' => 29, 'X' => 30, 'Y' => 31, 'Z' => 32, 'a' => 33, 'b' => 34, 'c' => 35, 'd' => 36, 'e' => 37, 'f' => 38, 'g' => 39, 'h' => 40, 'i' => 41, 'j' => 42, 'k' => 43, 'm' => 44, 'n' => 45, 'o' => 46, 'p' => 47, 'q' => 48, 'r' => 49, 's' => 50, 't' => 51, 'u' => 52, 'v' => 53, 'w' => 54, 'x' => 55, 'y' => 56, 'z' => 57];
    // https://datatracker.ietf.org/doc/html/rfc9562#section-5.1
    // 0x01b21dd213814000 is the number of 100-ns intervals between the
    // UUID epoch 1582-10-15 00:00:00 and the Unix epoch 1970-01-01 00:00:00.
    private const TIME_OFFSET_INT = 0x1b21dd213814000;
    private const TIME_OFFSET_BIN = "\x01\xb2\x1d\xd2\x13\x81@\x00";
    private const TIME_OFFSET_COM1 = "\xfeM\xe2-\xec~\xbf\xff";
    private const TIME_OFFSET_COM2 = "\xfeM\xe2-\xec~\xc0\x00";
    public static function toBase(string $bytes, array $map): string
    {
        $base = \strlen($alphabet = $map['']);
        $bytes = array_values(unpack(\PHP_INT_SIZE >= 8 ? 'n*' : 'C*', $bytes));
        $digits = '';
        while ($count = \count($bytes)) {
            $quotient = [];
            $remainder = 0;
            for ($i = 0; $i !== $count; ++$i) {
                $carry = $bytes[$i] + ($remainder << (\PHP_INT_SIZE >= 8 ? 16 : 8));
                $digit = intdiv($carry, $base);
                $remainder = $carry % $base;
                if ($digit || $quotient) {
                    $quotient[] = $digit;
                }
            }
            $digits = $alphabet[$remainder] . $digits;
            $bytes = $quotient;
        }
        return $digits;
    }
    public static function fromBase(string $digits, array $map): string
    {
        $base = \strlen($map['']);
        $count = \strlen($digits);
        $bytes = [];
        while ($count) {
            $quotient = [];
            $remainder = 0;
            for ($i = 0; $i !== $count; ++$i) {
                $carry = ($bytes ? $digits[$i] : $map[$digits[$i]]) + $remainder * $base;
                if (\PHP_INT_SIZE >= 8) {
                    $digit = $carry >> 16;
                    $remainder = $carry & 0xffff;
                } else {
                    $digit = $carry >> 8;
                    $remainder = $carry & 0xff;
                }
                if ($digit || $quotient) {
                    $quotient[] = $digit;
                }
            }
            $bytes[] = $remainder;
            $count = \count($digits = $quotient);
        }
        return pack(\PHP_INT_SIZE >= 8 ? 'n*' : 'C*', ...array_reverse($bytes));
    }
    public static function add(string $a, string $b): string
    {
        $carry = 0;
        for ($i = 7; 0 <= $i; --$i) {
            $carry += \ord($a[$i]) + \ord($b[$i]);
            $a[$i] = \chr($carry & 0xff);
            $carry >>= 8;
        }
        return $a;
    }
    /**
     * @param string $time Count of 100-nanosecond intervals since the UUID epoch 1582-10-15 00:00:00 in hexadecimal
     */
    public static function hexToDateTime(string $time): \DateTimeImmutable
    {
        if (\PHP_INT_SIZE >= 8) {
            $time = (string) (hexdec($time) - self::TIME_OFFSET_INT);
        } else {
            $time = str_pad(hex2bin($time), 8, "\x00", \STR_PAD_LEFT);
            if (self::TIME_OFFSET_BIN <= $time) {
                $time = self::add($time, self::TIME_OFFSET_COM2);
                $time[0] = $time[0] & "";
                $time = self::toBase($time, self::BASE10);
            } else {
                $time = self::add($time, self::TIME_OFFSET_COM1);
                $time = '-' . self::toBase($time ^ "\xff\xff\xff\xff\xff\xff\xff\xff", self::BASE10);
            }
        }
        if (9 > \strlen($time)) {
            $time = '-' === $time[0] ? '-' . str_pad(substr($time, 1), 8, '0', \STR_PAD_LEFT) : str_pad($time, 8, '0', \STR_PAD_LEFT);
        }
        return \DateTimeImmutable::createFromFormat('U.u?', substr_replace($time, '.', -7, 0));
    }
    /**
     * @return string Count of 100-nanosecond intervals since the UUID epoch 1582-10-15 00:00:00 in hexadecimal
     */
    public static function dateTimeToHex(\DateTimeInterface $time): string
    {
        if (\PHP_INT_SIZE >= 8) {
            if (-self::TIME_OFFSET_INT > $time = (int) $time->format('Uu0')) {
                throw new \InvalidArgumentException('The given UUID date cannot be earlier than 1582-10-15.');
            }
            return str_pad(dechex(self::TIME_OFFSET_INT + $time), 16, '0', \STR_PAD_LEFT);
        }
        $time = $time->format('Uu0');
        $negative = '-' === $time[0];
        if ($negative && self::TIME_OFFSET_INT < $time = substr($time, 1)) {
            throw new \InvalidArgumentException('The given UUID date cannot be earlier than 1582-10-15.');
        }
        $time = self::fromBase($time, self::BASE10);
        $time = str_pad($time, 8, "\x00", \STR_PAD_LEFT);
        if ($negative) {
            $time = self::add($time, self::TIME_OFFSET_COM1) ^ "\xff\xff\xff\xff\xff\xff\xff\xff";
        } else {
            $time = self::add($time, self::TIME_OFFSET_BIN);
        }
        return bin2hex($time);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Uid;

/**
 * @author Grégoire Pineau <lyrixx@lyrixx.info>
 */
class NilUuid extends Uuid
{
    protected const TYPE = -1;
    public function __construct()
    {
        $this->uid = parent::NIL;
    }
}
Copyright (c) 2020-present Fabien Potencier

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is furnished
to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Uid;

class NilUlid extends Ulid
{
    public function __construct()
    {
        $this->uid = parent::NIL;
    }
}
CHANGELOG
=========

6.2
---

 * Add `UuidV7` and `UuidV8`
 * Add `TimeBasedUidInterface` to describe UIDs that embed a timestamp
 * Add `MaxUuid` and `MaxUlid`

5.4
---

 * Add `NilUlid`

5.3
---

 * The component is not marked as `@experimental` anymore
 * Add `AbstractUid::fromBinary()`, `AbstractUid::fromBase58()`, `AbstractUid::fromBase32()` and `AbstractUid::fromRfc4122()`
 * [BC BREAK] Replace `UuidV1::getTime()`, `UuidV6::getTime()` and `Ulid::getTime()` by `UuidV1::getDateTime()`, `UuidV6::getDateTime()` and `Ulid::getDateTime()`
 * Add `Uuid::NAMESPACE_*` constants from RFC4122
 * Add `UlidFactory`, `UuidFactory`, `RandomBasedUuidFactory`, `TimeBasedUuidFactory` and `NameBasedUuidFactory`
 * Add commands to generate and inspect UUIDs and ULIDs

5.2.0
-----

 * made UUIDv6 always return truly random node fields to prevent leaking the MAC of the host

5.1.0
-----

 * added support for UUID
 * added support for ULID
 * added the component
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Uid;

/**
 * @author Nicolas Grekas <p@tchwork.com>
 */
abstract class AbstractUid implements \JsonSerializable, \Stringable
{
    /**
     * The identifier in its canonic representation.
     */
    protected $uid;
    /**
     * Whether the passed value is valid for the constructor of the current class.
     */
    abstract public static function isValid(string $uid): bool;
    /**
     * Creates an AbstractUid from an identifier represented in any of the supported formats.
     *
     * @throws \InvalidArgumentException When the passed value is not valid
     */
    abstract public static function fromString(string $uid): static;
    /**
     * @throws \InvalidArgumentException When the passed value is not valid
     */
    public static function fromBinary(string $uid): static
    {
        if (16 !== \strlen($uid)) {
            throw new \InvalidArgumentException('Invalid binary uid provided.');
        }
        return static::fromString($uid);
    }
    /**
     * @throws \InvalidArgumentException When the passed value is not valid
     */
    public static function fromBase58(string $uid): static
    {
        if (22 !== \strlen($uid)) {
            throw new \InvalidArgumentException('Invalid base-58 uid provided.');
        }
        return static::fromString($uid);
    }
    /**
     * @throws \InvalidArgumentException When the passed value is not valid
     */
    public static function fromBase32(string $uid): static
    {
        if (26 !== \strlen($uid)) {
            throw new \InvalidArgumentException('Invalid base-32 uid provided.');
        }
        return static::fromString($uid);
    }
    /**
     * @param string $uid A valid RFC 9562/4122 uid
     *
     * @throws \InvalidArgumentException When the passed value is not valid
     */
    public static function fromRfc4122(string $uid): static
    {
        if (36 !== \strlen($uid)) {
            throw new \InvalidArgumentException('Invalid RFC4122 uid provided.');
        }
        return static::fromString($uid);
    }
    /**
     * Returns the identifier as a raw binary string.
     */
    abstract public function toBinary(): string;
    /**
     * Returns the identifier as a base58 case sensitive string.
     *
     * @example 2AifFTC3zXgZzK5fPrrprL (len=22)
     */
    public function toBase58(): string
    {
        return strtr(\sprintf('%022s', BinaryUtil::toBase($this->toBinary(), BinaryUtil::BASE58)), '0', '1');
    }
    /**
     * Returns the identifier as a base32 case insensitive string.
     *
     * @see https://tools.ietf.org/html/rfc4648#section-6
     *
     * @example 09EJ0S614A9FXVG9C5537Q9ZE1 (len=26)
     */
    public function toBase32(): string
    {
        $uid = bin2hex($this->toBinary());
        $uid = \sprintf('%02s%04s%04s%04s%04s%04s%04s', base_convert(substr($uid, 0, 2), 16, 32), base_convert(substr($uid, 2, 5), 16, 32), base_convert(substr($uid, 7, 5), 16, 32), base_convert(substr($uid, 12, 5), 16, 32), base_convert(substr($uid, 17, 5), 16, 32), base_convert(substr($uid, 22, 5), 16, 32), base_convert(substr($uid, 27, 5), 16, 32));
        return strtr($uid, 'abcdefghijklmnopqrstuv', 'ABCDEFGHJKMNPQRSTVWXYZ');
    }
    /**
     * Returns the identifier as a RFC 9562/4122 case insensitive string.
     *
     * @see https://datatracker.ietf.org/doc/html/rfc9562/#section-4
     *
     * @example 09748193-048a-4bfb-b825-8528cf74fdc1 (len=36)
     */
    public function toRfc4122(): string
    {
        // don't use uuid_unparse(), it's slower
        $uuid = bin2hex($this->toBinary());
        $uuid = substr_replace($uuid, '-', 8, 0);
        $uuid = substr_replace($uuid, '-', 13, 0);
        $uuid = substr_replace($uuid, '-', 18, 0);
        return substr_replace($uuid, '-', 23, 0);
    }
    /**
     * Returns the identifier as a prefixed hexadecimal case insensitive string.
     *
     * @example 0x09748193048a4bfbb8258528cf74fdc1 (len=34)
     */
    public function toHex(): string
    {
        return '0x' . bin2hex($this->toBinary());
    }
    /**
     * Returns whether the argument is an AbstractUid and contains the same value as the current instance.
     */
    public function equals(mixed $other): bool
    {
        if (!$other instanceof self) {
            return \false;
        }
        return $this->uid === $other->uid;
    }
    public function compare(self $other): int
    {
        return \strlen($this->uid) - \strlen($other->uid) ?: $this->uid <=> $other->uid;
    }
    public function __toString(): string
    {
        return $this->uid;
    }
    public function jsonSerialize(): string
    {
        return $this->uid;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Uid;

/**
 * A ULID is lexicographically sortable and contains a 48-bit timestamp and 80-bit of crypto-random entropy.
 *
 * @see https://github.com/ulid/spec
 *
 * @author Nicolas Grekas <p@tchwork.com>
 */
class Ulid extends AbstractUid implements TimeBasedUidInterface
{
    protected const NIL = '00000000000000000000000000';
    protected const MAX = '7ZZZZZZZZZZZZZZZZZZZZZZZZZ';
    private static string $time = '';
    private static array $rand = [];
    public function __construct(?string $ulid = null)
    {
        if (null === $ulid) {
            $this->uid = static::generate();
        } elseif (self::NIL === $ulid) {
            $this->uid = $ulid;
        } elseif (self::MAX === strtr($ulid, 'z', 'Z')) {
            $this->uid = $ulid;
        } else {
            if (!self::isValid($ulid)) {
                throw new \InvalidArgumentException('Invalid ULID.');
            }
            $this->uid = strtoupper($ulid);
        }
    }
    public static function isValid(string $ulid): bool
    {
        if (26 !== \strlen($ulid)) {
            return \false;
        }
        if (26 !== strspn($ulid, '0123456789ABCDEFGHJKMNPQRSTVWXYZabcdefghjkmnpqrstvwxyz')) {
            return \false;
        }
        return $ulid[0] <= '7';
    }
    public static function fromString(string $ulid): static
    {
        if (36 === \strlen($ulid) && preg_match('{^[0-9a-f]{8}(?:-[0-9a-f]{4}){3}-[0-9a-f]{12}$}Di', $ulid)) {
            $ulid = uuid_parse($ulid);
        } elseif (22 === \strlen($ulid) && 22 === strspn($ulid, BinaryUtil::BASE58[''])) {
            $ulid = str_pad(BinaryUtil::fromBase($ulid, BinaryUtil::BASE58), 16, "\x00", \STR_PAD_LEFT);
        }
        if (16 !== \strlen($ulid)) {
            return match (strtr($ulid, 'z', 'Z')) {
                self::NIL => new NilUlid(),
                self::MAX => new MaxUlid(),
                default => new static($ulid),
            };
        }
        $ulid = bin2hex($ulid);
        $ulid = \sprintf('%02s%04s%04s%04s%04s%04s%04s', base_convert(substr($ulid, 0, 2), 16, 32), base_convert(substr($ulid, 2, 5), 16, 32), base_convert(substr($ulid, 7, 5), 16, 32), base_convert(substr($ulid, 12, 5), 16, 32), base_convert(substr($ulid, 17, 5), 16, 32), base_convert(substr($ulid, 22, 5), 16, 32), base_convert(substr($ulid, 27, 5), 16, 32));
        if (self::NIL === $ulid) {
            return new NilUlid();
        }
        if (self::MAX === $ulid = strtr($ulid, 'abcdefghijklmnopqrstuv', 'ABCDEFGHJKMNPQRSTVWXYZ')) {
            return new MaxUlid();
        }
        $u = new static(self::NIL);
        $u->uid = $ulid;
        return $u;
    }
    public function toBinary(): string
    {
        $ulid = strtr($this->uid, 'ABCDEFGHJKMNPQRSTVWXYZ', 'abcdefghijklmnopqrstuv');
        $ulid = \sprintf('%02s%05s%05s%05s%05s%05s%05s', base_convert(substr($ulid, 0, 2), 32, 16), base_convert(substr($ulid, 2, 4), 32, 16), base_convert(substr($ulid, 6, 4), 32, 16), base_convert(substr($ulid, 10, 4), 32, 16), base_convert(substr($ulid, 14, 4), 32, 16), base_convert(substr($ulid, 18, 4), 32, 16), base_convert(substr($ulid, 22, 4), 32, 16));
        return hex2bin($ulid);
    }
    /**
     * Returns the identifier as a base32 case insensitive string.
     *
     * @see https://tools.ietf.org/html/rfc4648#section-6
     *
     * @example 09EJ0S614A9FXVG9C5537Q9ZE1 (len=26)
     */
    public function toBase32(): string
    {
        return $this->uid;
    }
    public function getDateTime(): \DateTimeImmutable
    {
        $time = strtr(substr($this->uid, 0, 10), 'ABCDEFGHJKMNPQRSTVWXYZ', 'abcdefghijklmnopqrstuv');
        if (\PHP_INT_SIZE >= 8) {
            $time = (string) hexdec(base_convert($time, 32, 16));
        } else {
            $time = \sprintf('%02s%05s%05s', base_convert(substr($time, 0, 2), 32, 16), base_convert(substr($time, 2, 4), 32, 16), base_convert(substr($time, 6, 4), 32, 16));
            $time = BinaryUtil::toBase(hex2bin($time), BinaryUtil::BASE10);
        }
        if (4 > \strlen($time)) {
            $time = '000' . $time;
        }
        return \DateTimeImmutable::createFromFormat('U.u', substr_replace($time, '.', -3, 0));
    }
    public static function generate(?\DateTimeInterface $time = null): string
    {
        if (null === $mtime = $time) {
            $time = microtime(\false);
            $time = substr($time, 11) . substr($time, 2, 3);
        } elseif (0 > $time = $time->format('Uv')) {
            throw new \InvalidArgumentException('The timestamp must be positive.');
        }
        if ($time > self::$time || null !== $mtime && $time !== self::$time) {
            randomize:
            $r = unpack('n*', random_bytes(10));
            $r[1] |= ($r[5] <<= 4) & 0xf0000;
            $r[2] |= ($r[5] <<= 4) & 0xf0000;
            $r[3] |= ($r[5] <<= 4) & 0xf0000;
            $r[4] |= ($r[5] <<= 4) & 0xf0000;
            unset($r[5]);
            self::$rand = $r;
            self::$time = $time;
        } elseif ([1 => 0xfffff, 0xfffff, 0xfffff, 0xfffff] === self::$rand) {
            if (\PHP_INT_SIZE >= 8 || 10 > \strlen($time = self::$time)) {
                $time = (string) (1 + $time);
            } elseif ('999999999' === $mtime = substr($time, -9)) {
                $time = 1 + substr($time, 0, -9) . '000000000';
            } else {
                $time = substr_replace($time, str_pad(++$mtime, 9, '0', \STR_PAD_LEFT), -9);
            }
            goto randomize;
        } else {
            for ($i = 4; $i > 0 && 0xfffff === self::$rand[$i]; --$i) {
                self::$rand[$i] = 0;
            }
            ++self::$rand[$i];
            $time = self::$time;
        }
        if (\PHP_INT_SIZE >= 8) {
            $time = base_convert($time, 10, 32);
        } else {
            $time = str_pad(bin2hex(BinaryUtil::fromBase($time, BinaryUtil::BASE10)), 12, '0', \STR_PAD_LEFT);
            $time = \sprintf('%s%04s%04s', base_convert(substr($time, 0, 2), 16, 32), base_convert(substr($time, 2, 5), 16, 32), base_convert(substr($time, 7, 5), 16, 32));
        }
        return strtr(\sprintf('%010s%04s%04s%04s%04s', $time, base_convert(self::$rand[1], 10, 32), base_convert(self::$rand[2], 10, 32), base_convert(self::$rand[3], 10, 32), base_convert(self::$rand[4], 10, 32)), 'abcdefghijklmnopqrstuv', 'ABCDEFGHJKMNPQRSTVWXYZ');
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Uid;

/**
 * @author Grégoire Pineau <lyrixx@lyrixx.info>
 *
 * @see https://datatracker.ietf.org/doc/html/rfc9562/#section-6.6 for details about namespaces
 */
class Uuid extends AbstractUid
{
    public const NAMESPACE_DNS = '6ba7b810-9dad-11d1-80b4-00c04fd430c8';
    public const NAMESPACE_URL = '6ba7b811-9dad-11d1-80b4-00c04fd430c8';
    public const NAMESPACE_OID = '6ba7b812-9dad-11d1-80b4-00c04fd430c8';
    public const NAMESPACE_X500 = '6ba7b814-9dad-11d1-80b4-00c04fd430c8';
    protected const TYPE = 0;
    protected const NIL = '00000000-0000-0000-0000-000000000000';
    protected const MAX = 'ffffffff-ffff-ffff-ffff-ffffffffffff';
    public function __construct(string $uuid, bool $checkVariant = \false)
    {
        $type = preg_match('{^[0-9a-f]{8}(?:-[0-9a-f]{4}){3}-[0-9a-f]{12}$}Di', $uuid) ? (int) $uuid[14] : \false;
        if (\false === $type || (static::TYPE ?: $type) !== $type) {
            throw new \InvalidArgumentException(\sprintf('Invalid UUID%s.', static::TYPE ? 'v' . static::TYPE : ''));
        }
        $this->uid = strtolower($uuid);
        if ($checkVariant && !\in_array($this->uid[19], ['8', '9', 'a', 'b'], \true)) {
            throw new \InvalidArgumentException(\sprintf('Invalid UUID%s.', static::TYPE ? 'v' . static::TYPE : ''));
        }
    }
    public static function fromString(string $uuid): static
    {
        if (22 === \strlen($uuid) && 22 === strspn($uuid, BinaryUtil::BASE58[''])) {
            $uuid = str_pad(BinaryUtil::fromBase($uuid, BinaryUtil::BASE58), 16, "\x00", \STR_PAD_LEFT);
        }
        if (16 === \strlen($uuid)) {
            // don't use uuid_unparse(), it's slower
            $uuid = bin2hex($uuid);
            $uuid = substr_replace($uuid, '-', 8, 0);
            $uuid = substr_replace($uuid, '-', 13, 0);
            $uuid = substr_replace($uuid, '-', 18, 0);
            $uuid = substr_replace($uuid, '-', 23, 0);
        } elseif (26 === \strlen($uuid) && Ulid::isValid($uuid)) {
            $ulid = new NilUlid();
            $ulid->uid = strtoupper($uuid);
            $uuid = $ulid->toRfc4122();
        }
        if (__CLASS__ !== static::class || 36 !== \strlen($uuid)) {
            return new static($uuid);
        }
        if (self::NIL === $uuid) {
            return new NilUuid();
        }
        if (self::MAX === $uuid = strtr($uuid, 'F', 'f')) {
            return new MaxUuid();
        }
        if (!\in_array($uuid[19], ['8', '9', 'a', 'b', 'A', 'B'], \true)) {
            return new self($uuid);
        }
        return match ((int) $uuid[14]) {
            UuidV1::TYPE => new UuidV1($uuid),
            UuidV3::TYPE => new UuidV3($uuid),
            UuidV4::TYPE => new UuidV4($uuid),
            UuidV5::TYPE => new UuidV5($uuid),
            UuidV6::TYPE => new UuidV6($uuid),
            UuidV7::TYPE => new UuidV7($uuid),
            UuidV8::TYPE => new UuidV8($uuid),
            default => new self($uuid),
        };
    }
    final public static function v1(): UuidV1
    {
        return new UuidV1();
    }
    final public static function v3(self $namespace, string $name): UuidV3
    {
        // don't use uuid_generate_md5(), some versions are buggy
        $uuid = md5(hex2bin(str_replace('-', '', $namespace->uid)) . $name, \true);
        return new UuidV3(self::format($uuid, '-3'));
    }
    final public static function v4(): UuidV4
    {
        return new UuidV4();
    }
    final public static function v5(self $namespace, string $name): UuidV5
    {
        // don't use uuid_generate_sha1(), some versions are buggy
        $uuid = substr(sha1(hex2bin(str_replace('-', '', $namespace->uid)) . $name, \true), 0, 16);
        return new UuidV5(self::format($uuid, '-5'));
    }
    final public static function v6(): UuidV6
    {
        return new UuidV6();
    }
    final public static function v7(): UuidV7
    {
        return new UuidV7();
    }
    final public static function v8(string $uuid): UuidV8
    {
        return new UuidV8($uuid);
    }
    public static function isValid(string $uuid): bool
    {
        if (self::NIL === $uuid && \in_array(static::class, [__CLASS__, NilUuid::class], \true)) {
            return \true;
        }
        if (self::MAX === strtr($uuid, 'F', 'f') && \in_array(static::class, [__CLASS__, MaxUuid::class], \true)) {
            return \true;
        }
        if (!preg_match('{^[0-9a-f]{8}(?:-[0-9a-f]{4}){2}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$}Di', $uuid)) {
            return \false;
        }
        return __CLASS__ === static::class || static::TYPE === (int) $uuid[14];
    }
    public function toBinary(): string
    {
        return uuid_parse($this->uid);
    }
    /**
     * Returns the identifier as a RFC 9562/4122 case insensitive string.
     *
     * @see https://datatracker.ietf.org/doc/html/rfc9562/#section-4
     *
     * @example 09748193-048a-4bfb-b825-8528cf74fdc1 (len=36)
     */
    public function toRfc4122(): string
    {
        return $this->uid;
    }
    public function compare(AbstractUid $other): int
    {
        if (\false !== $cmp = uuid_compare($this->uid, $other->uid)) {
            return $cmp;
        }
        return parent::compare($other);
    }
    private static function format(string $uuid, string $version): string
    {
        $uuid[8] = $uuid[8] & "?" | "\x80";
        $uuid = substr_replace(bin2hex($uuid), '-', 8, 0);
        $uuid = substr_replace($uuid, $version, 13, 1);
        $uuid = substr_replace($uuid, '-', 18, 0);
        return substr_replace($uuid, '-', 23, 0);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Uid;

class MaxUlid extends Ulid
{
    public function __construct()
    {
        $this->uid = parent::MAX;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Uid;

class MaxUuid extends Uuid
{
    protected const TYPE = -1;
    public function __construct()
    {
        $this->uid = parent::MAX;
    }
}
Uid Component
=============

The UID component provides an object-oriented API to generate and represent UIDs.

It provides implementations that work on 32-bit and 64-bit CPUs
for ULIDs and for UUIDs version 1 and versions 3 to 8.

Resources
---------

 * [Documentation](https://symfony.com/doc/current/components/uid.html)
 * [Contributing](https://symfony.com/doc/current/contributing/index.html)
 * [Report issues](https://github.com/symfony/symfony/issues) and
   [send Pull Requests](https://github.com/symfony/symfony/pulls)
   in the [main Symfony repository](https://github.com/symfony/symfony)
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Uid\Command;

use _ContaoManager\Symfony\Component\Console\Attribute\AsCommand;
use _ContaoManager\Symfony\Component\Console\Command\Command;
use _ContaoManager\Symfony\Component\Console\Completion\CompletionInput;
use _ContaoManager\Symfony\Component\Console\Completion\CompletionSuggestions;
use _ContaoManager\Symfony\Component\Console\Input\InputInterface;
use _ContaoManager\Symfony\Component\Console\Input\InputOption;
use _ContaoManager\Symfony\Component\Console\Output\ConsoleOutputInterface;
use _ContaoManager\Symfony\Component\Console\Output\OutputInterface;
use _ContaoManager\Symfony\Component\Console\Style\SymfonyStyle;
use _ContaoManager\Symfony\Component\Uid\Factory\UuidFactory;
use _ContaoManager\Symfony\Component\Uid\Uuid;
#[AsCommand(name: 'uuid:generate', description: 'Generate a UUID')]
class GenerateUuidCommand extends Command
{
    private UuidFactory $factory;
    public function __construct(?UuidFactory $factory = null)
    {
        $this->factory = $factory ?? new UuidFactory();
        parent::__construct();
    }
    protected function configure(): void
    {
        $this->setDefinition([new InputOption('time-based', null, InputOption::VALUE_REQUIRED, 'The timestamp, to generate a time-based UUID: a parsable date/time string'), new InputOption('node', null, InputOption::VALUE_REQUIRED, 'The UUID whose node part should be used as the node of the generated UUID'), new InputOption('name-based', null, InputOption::VALUE_REQUIRED, 'The name, to generate a name-based UUID'), new InputOption('namespace', null, InputOption::VALUE_REQUIRED, 'The UUID to use at the namespace for named-based UUIDs, predefined namespaces keywords "dns", "url", "oid" and "x500" are accepted'), new InputOption('random-based', null, InputOption::VALUE_NONE, 'To generate a random-based UUID'), new InputOption('count', 'c', InputOption::VALUE_REQUIRED, 'The number of UUID to generate', 1), new InputOption('format', 'f', InputOption::VALUE_REQUIRED, \sprintf('The UUID output format ("%s")', implode('", "', $this->getAvailableFormatOptions())), 'rfc4122')])->setHelp(<<<'EOF'
The <info>%command.name%</info> generates a UUID.

    <info>php %command.full_name%</info>

To generate a time-based UUID:

    <info>php %command.full_name% --time-based=now</info>

To specify a time-based UUID's node:

    <info>php %command.full_name% --time-based=@1613480254 --node=fb3502dc-137e-4849-8886-ac90d07f64a7</info>

To generate a name-based UUID:

    <info>php %command.full_name% --name-based=foo</info>

To specify a name-based UUID's namespace:

    <info>php %command.full_name% --name-based=bar --namespace=fb3502dc-137e-4849-8886-ac90d07f64a7</info>

To generate a random-based UUID:

    <info>php %command.full_name% --random-based</info>

To generate several UUIDs:

    <info>php %command.full_name% --count=10</info>

To output a specific format:

    <info>php %command.full_name% --format=base58</info>
EOF
);
    }
    protected function execute(InputInterface $input, OutputInterface $output): int
    {
        $io = new SymfonyStyle($input, $output instanceof ConsoleOutputInterface ? $output->getErrorOutput() : $output);
        $time = $input->getOption('time-based');
        $node = $input->getOption('node');
        $name = $input->getOption('name-based');
        $namespace = $input->getOption('namespace');
        $random = $input->getOption('random-based');
        if (\false !== ($time ?? $name ?? $random) && 1 < (null !== $time) + (null !== $name) + $random) {
            $io->error('Only one of "--time-based", "--name-based" or "--random-based" can be provided at a time.');
            return 1;
        }
        if (null === $time && null !== $node) {
            $io->error('Option "--node" can only be used with "--time-based".');
            return 1;
        }
        if (null === $name && null !== $namespace) {
            $io->error('Option "--namespace" can only be used with "--name-based".');
            return 1;
        }
        switch (\true) {
            case null !== $time:
                if (null !== $node) {
                    try {
                        $node = Uuid::fromString($node);
                    } catch (\InvalidArgumentException $e) {
                        $io->error(\sprintf('Invalid node "%s": %s', $node, $e->getMessage()));
                        return 1;
                    }
                }
                try {
                    new \DateTimeImmutable($time);
                } catch (\Exception $e) {
                    $io->error(\sprintf('Invalid timestamp "%s": %s', $time, str_replace('DateTimeImmutable::__construct(): ', '', $e->getMessage())));
                    return 1;
                }
                $create = fn(): Uuid => $this->factory->timeBased($node)->create(new \DateTimeImmutable($time));
                break;
            case null !== $name:
                if ($namespace && !\in_array($namespace, ['dns', 'url', 'oid', 'x500'], \true)) {
                    try {
                        $namespace = Uuid::fromString($namespace);
                    } catch (\InvalidArgumentException $e) {
                        $io->error(\sprintf('Invalid namespace "%s": %s', $namespace, $e->getMessage()));
                        return 1;
                    }
                }
                $create = function () use ($namespace, $name): Uuid {
                    try {
                        $factory = $this->factory->nameBased($namespace);
                    } catch (\LogicException) {
                        throw new \InvalidArgumentException('Missing namespace: use the "--namespace" option or configure a default namespace in the underlying factory.');
                    }
                    return $factory->create($name);
                };
                break;
            case $random:
                $create = $this->factory->randomBased()->create(...);
                break;
            default:
                $create = $this->factory->create(...);
                break;
        }
        $formatOption = $input->getOption('format');
        if (\in_array($formatOption, $this->getAvailableFormatOptions())) {
            $format = 'to' . ucfirst($formatOption);
        } else {
            $io->error(\sprintf('Invalid format "%s", supported formats are "%s".', $formatOption, implode('", "', $this->getAvailableFormatOptions())));
            return 1;
        }
        $count = (int) $input->getOption('count');
        try {
            for ($i = 0; $i < $count; ++$i) {
                $output->writeln($create()->{$format}());
            }
        } catch (\Exception $e) {
            $io->error($e->getMessage());
            return 1;
        }
        return 0;
    }
    public function complete(CompletionInput $input, CompletionSuggestions $suggestions): void
    {
        if ($input->mustSuggestOptionValuesFor('format')) {
            $suggestions->suggestValues($this->getAvailableFormatOptions());
        }
    }
    private function getAvailableFormatOptions(): array
    {
        return ['base32', 'base58', 'rfc4122'];
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Uid\Command;

use _ContaoManager\Symfony\Component\Console\Attribute\AsCommand;
use _ContaoManager\Symfony\Component\Console\Command\Command;
use _ContaoManager\Symfony\Component\Console\Completion\CompletionInput;
use _ContaoManager\Symfony\Component\Console\Completion\CompletionSuggestions;
use _ContaoManager\Symfony\Component\Console\Input\InputInterface;
use _ContaoManager\Symfony\Component\Console\Input\InputOption;
use _ContaoManager\Symfony\Component\Console\Output\ConsoleOutputInterface;
use _ContaoManager\Symfony\Component\Console\Output\OutputInterface;
use _ContaoManager\Symfony\Component\Console\Style\SymfonyStyle;
use _ContaoManager\Symfony\Component\Uid\Factory\UlidFactory;
#[AsCommand(name: 'ulid:generate', description: 'Generate a ULID')]
class GenerateUlidCommand extends Command
{
    private UlidFactory $factory;
    public function __construct(?UlidFactory $factory = null)
    {
        $this->factory = $factory ?? new UlidFactory();
        parent::__construct();
    }
    protected function configure(): void
    {
        $this->setDefinition([new InputOption('time', null, InputOption::VALUE_REQUIRED, 'The ULID timestamp: a parsable date/time string'), new InputOption('count', 'c', InputOption::VALUE_REQUIRED, 'The number of ULID to generate', 1), new InputOption('format', 'f', InputOption::VALUE_REQUIRED, \sprintf('The ULID output format ("%s")', implode('", "', $this->getAvailableFormatOptions())), 'base32')])->setHelp(<<<'EOF'
The <info>%command.name%</info> command generates a ULID.

    <info>php %command.full_name%</info>

To specify the timestamp:

    <info>php %command.full_name% --time="2021-02-16 14:09:08"</info>

To generate several ULIDs:

    <info>php %command.full_name% --count=10</info>

To output a specific format:

    <info>php %command.full_name% --format=rfc4122</info>
EOF
);
    }
    protected function execute(InputInterface $input, OutputInterface $output): int
    {
        $io = new SymfonyStyle($input, $output instanceof ConsoleOutputInterface ? $output->getErrorOutput() : $output);
        if (null !== $time = $input->getOption('time')) {
            try {
                $time = new \DateTimeImmutable($time);
            } catch (\Exception $e) {
                $io->error(\sprintf('Invalid timestamp "%s": %s', $time, str_replace('DateTimeImmutable::__construct(): ', '', $e->getMessage())));
                return 1;
            }
        }
        $formatOption = $input->getOption('format');
        if (\in_array($formatOption, $this->getAvailableFormatOptions())) {
            $format = 'to' . ucfirst($formatOption);
        } else {
            $io->error(\sprintf('Invalid format "%s", supported formats are "%s".', $formatOption, implode('", "', $this->getAvailableFormatOptions())));
            return 1;
        }
        $count = (int) $input->getOption('count');
        try {
            for ($i = 0; $i < $count; ++$i) {
                $output->writeln($this->factory->create($time)->{$format}());
            }
        } catch (\Exception $e) {
            $io->error($e->getMessage());
            return 1;
        }
        return 0;
    }
    public function complete(CompletionInput $input, CompletionSuggestions $suggestions): void
    {
        if ($input->mustSuggestOptionValuesFor('format')) {
            $suggestions->suggestValues($this->getAvailableFormatOptions());
        }
    }
    private function getAvailableFormatOptions(): array
    {
        return ['base32', 'base58', 'rfc4122'];
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Uid\Command;

use _ContaoManager\Symfony\Component\Console\Attribute\AsCommand;
use _ContaoManager\Symfony\Component\Console\Command\Command;
use _ContaoManager\Symfony\Component\Console\Helper\TableSeparator;
use _ContaoManager\Symfony\Component\Console\Input\InputArgument;
use _ContaoManager\Symfony\Component\Console\Input\InputInterface;
use _ContaoManager\Symfony\Component\Console\Output\ConsoleOutputInterface;
use _ContaoManager\Symfony\Component\Console\Output\OutputInterface;
use _ContaoManager\Symfony\Component\Console\Style\SymfonyStyle;
use _ContaoManager\Symfony\Component\Uid\MaxUuid;
use _ContaoManager\Symfony\Component\Uid\NilUuid;
use _ContaoManager\Symfony\Component\Uid\TimeBasedUidInterface;
use _ContaoManager\Symfony\Component\Uid\Uuid;
#[AsCommand(name: 'uuid:inspect', description: 'Inspect a UUID')]
class InspectUuidCommand extends Command
{
    protected function configure(): void
    {
        $this->setDefinition([new InputArgument('uuid', InputArgument::REQUIRED, 'The UUID to inspect')])->setHelp(<<<'EOF'
The <info>%command.name%</info> displays information about a UUID.

    <info>php %command.full_name% a7613e0a-5986-11eb-a861-2bf05af69e52</info>
    <info>php %command.full_name% MfnmaUvvQ1h8B14vTwt6dX</info>
    <info>php %command.full_name% 57C4Z0MPC627NTGR9BY1DFD7JJ</info>
EOF
);
    }
    protected function execute(InputInterface $input, OutputInterface $output): int
    {
        $io = new SymfonyStyle($input, $output instanceof ConsoleOutputInterface ? $output->getErrorOutput() : $output);
        try {
            /** @var Uuid $uuid */
            $uuid = Uuid::fromString($input->getArgument('uuid'));
        } catch (\InvalidArgumentException $e) {
            $io->error($e->getMessage());
            return 1;
        }
        if (new NilUuid() == $uuid) {
            $version = 'nil';
        } elseif (new MaxUuid() == $uuid) {
            $version = 'max';
        } else {
            $version = uuid_type($uuid);
        }
        $rows = [['Version', $version], ['toRfc4122 (canonical)', (string) $uuid], ['toBase58', $uuid->toBase58()], ['toBase32', $uuid->toBase32()], ['toHex', $uuid->toHex()]];
        if ($uuid instanceof TimeBasedUidInterface) {
            $rows[] = new TableSeparator();
            $rows[] = ['Time', $uuid->getDateTime()->format('Y-m-d H:i:s.u \U\T\C')];
        }
        $io->table(['Label', 'Value'], $rows);
        return 0;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Uid\Command;

use _ContaoManager\Symfony\Component\Console\Attribute\AsCommand;
use _ContaoManager\Symfony\Component\Console\Command\Command;
use _ContaoManager\Symfony\Component\Console\Helper\TableSeparator;
use _ContaoManager\Symfony\Component\Console\Input\InputArgument;
use _ContaoManager\Symfony\Component\Console\Input\InputInterface;
use _ContaoManager\Symfony\Component\Console\Output\ConsoleOutputInterface;
use _ContaoManager\Symfony\Component\Console\Output\OutputInterface;
use _ContaoManager\Symfony\Component\Console\Style\SymfonyStyle;
use _ContaoManager\Symfony\Component\Uid\Ulid;
#[AsCommand(name: 'ulid:inspect', description: 'Inspect a ULID')]
class InspectUlidCommand extends Command
{
    protected function configure(): void
    {
        $this->setDefinition([new InputArgument('ulid', InputArgument::REQUIRED, 'The ULID to inspect')])->setHelp(<<<'EOF'
The <info>%command.name%</info> displays information about a ULID.

    <info>php %command.full_name% 01EWAKBCMWQ2C94EXNN60ZBS0Q</info>
    <info>php %command.full_name% 1BVdfLn3ERmbjYBLCdaaLW</info>
    <info>php %command.full_name% 01771535-b29c-b898-923b-b5a981f5e417</info>
EOF
);
    }
    protected function execute(InputInterface $input, OutputInterface $output): int
    {
        $io = new SymfonyStyle($input, $output instanceof ConsoleOutputInterface ? $output->getErrorOutput() : $output);
        try {
            $ulid = Ulid::fromString($input->getArgument('ulid'));
        } catch (\InvalidArgumentException $e) {
            $io->error($e->getMessage());
            return 1;
        }
        $io->table(['Label', 'Value'], [['toBase32 (canonical)', (string) $ulid], ['toBase58', $ulid->toBase58()], ['toRfc4122', $ulid->toRfc4122()], ['toHex', $ulid->toHex()], new TableSeparator(), ['Time', $ulid->getDateTime()->format('Y-m-d H:i:s.v \U\T\C')]]);
        return 0;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Uid;

/**
 * A v1 UUID contains a 60-bit timestamp and 62 extra unique bits.
 *
 * @author Grégoire Pineau <lyrixx@lyrixx.info>
 */
class UuidV1 extends Uuid implements TimeBasedUidInterface
{
    protected const TYPE = 1;
    private static string $clockSeq;
    public function __construct(?string $uuid = null)
    {
        if (null === $uuid) {
            $this->uid = strtolower(uuid_create(static::TYPE));
        } else {
            parent::__construct($uuid, \true);
        }
    }
    public function getDateTime(): \DateTimeImmutable
    {
        return BinaryUtil::hexToDateTime('0' . substr($this->uid, 15, 3) . substr($this->uid, 9, 4) . substr($this->uid, 0, 8));
    }
    public function getNode(): string
    {
        return uuid_mac($this->uid);
    }
    public static function generate(?\DateTimeInterface $time = null, ?Uuid $node = null): string
    {
        $uuid = !$time || !$node ? uuid_create(static::TYPE) : parent::NIL;
        if ($time) {
            if ($node) {
                // use clock_seq from the node
                $seq = substr($node->uid, 19, 4);
            } elseif (!$seq = self::$clockSeq ?? '') {
                // generate a static random clock_seq to prevent any collisions with the real one
                $seq = substr($uuid, 19, 4);
                do {
                    self::$clockSeq = \sprintf('%04x', random_int(0, 0x3fff) | 0x8000);
                } while ($seq === self::$clockSeq);
                $seq = self::$clockSeq;
            }
            $time = BinaryUtil::dateTimeToHex($time);
            $uuid = substr($time, 8) . '-' . substr($time, 4, 4) . '-1' . substr($time, 1, 3) . '-' . $seq . substr($uuid, 23);
        }
        if ($node) {
            $uuid = substr($uuid, 0, 24) . substr($node->uid, 24);
        }
        return $uuid;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Uid;

/**
 * A v3 UUID contains an MD5 hash of another UUID and a name.
 *
 * Use Uuid::v3() to compute one.
 *
 * @author Grégoire Pineau <lyrixx@lyrixx.info>
 */
class UuidV3 extends Uuid
{
    protected const TYPE = 3;
    public function __construct(string $uuid)
    {
        parent::__construct($uuid, \true);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Uid;

/**
 * A v6 UUID is lexicographically sortable and contains a 60-bit timestamp and 62 extra unique bits.
 *
 * Unlike UUIDv1, this implementation of UUIDv6 doesn't leak the MAC address of the host.
 *
 * @author Nicolas Grekas <p@tchwork.com>
 */
class UuidV6 extends Uuid implements TimeBasedUidInterface
{
    protected const TYPE = 6;
    private static string $node;
    public function __construct(?string $uuid = null)
    {
        if (null === $uuid) {
            $this->uid = static::generate();
        } else {
            parent::__construct($uuid, \true);
        }
    }
    public function getDateTime(): \DateTimeImmutable
    {
        return BinaryUtil::hexToDateTime('0' . substr($this->uid, 0, 8) . substr($this->uid, 9, 4) . substr($this->uid, 15, 3));
    }
    public function getNode(): string
    {
        return substr($this->uid, 24);
    }
    public static function generate(?\DateTimeInterface $time = null, ?Uuid $node = null): string
    {
        $uuidV1 = UuidV1::generate($time, $node);
        $uuid = substr($uuidV1, 15, 3) . substr($uuidV1, 9, 4) . $uuidV1[0] . '-' . substr($uuidV1, 1, 4) . '-6' . substr($uuidV1, 5, 3) . substr($uuidV1, 18, 6);
        if ($node) {
            return $uuid . substr($uuidV1, 24);
        }
        // uuid_create() returns a stable "node" that can leak the MAC of the host, but
        // UUIDv6 prefers a truly random number here, let's XOR both to preserve the entropy
        if (!isset(self::$node)) {
            $seed = [random_int(0, 0xffffff), random_int(0, 0xffffff)];
            $node = unpack('N2', hex2bin('00' . substr($uuidV1, 24, 6)) . hex2bin('00' . substr($uuidV1, 30)));
            self::$node = \sprintf('%06x%06x', $seed[0] ^ $node[1] | 0x10000, $seed[1] ^ $node[2]);
        }
        return $uuid . self::$node;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Uid;

/**
 * A v7 UUID is lexicographically sortable and contains a 48-bit timestamp and 74 extra unique bits.
 *
 * Within the same millisecond, monotonicity is ensured by incrementing the random part by a random increment.
 *
 * @author Nicolas Grekas <p@tchwork.com>
 */
class UuidV7 extends Uuid implements TimeBasedUidInterface
{
    protected const TYPE = 7;
    private static string $time = '';
    private static array $rand = [];
    private static string $seed;
    private static array $seedParts;
    private static int $seedIndex = 0;
    public function __construct(?string $uuid = null)
    {
        if (null === $uuid) {
            $this->uid = static::generate();
        } else {
            parent::__construct($uuid, \true);
        }
    }
    public function getDateTime(): \DateTimeImmutable
    {
        $time = substr($this->uid, 0, 8) . substr($this->uid, 9, 4);
        $time = \PHP_INT_SIZE >= 8 ? (string) hexdec($time) : BinaryUtil::toBase(hex2bin($time), BinaryUtil::BASE10);
        if (4 > \strlen($time)) {
            $time = '000' . $time;
        }
        return \DateTimeImmutable::createFromFormat('U.v', substr_replace($time, '.', -3, 0));
    }
    public static function generate(?\DateTimeInterface $time = null): string
    {
        if (null === $mtime = $time) {
            $time = microtime(\false);
            $time = substr($time, 11) . substr($time, 2, 3);
        } elseif (0 > $time = $time->format('Uv')) {
            throw new \InvalidArgumentException('The timestamp must be positive.');
        }
        if ($time > self::$time || null !== $mtime && $time !== self::$time) {
            randomize:
            self::$rand = unpack('S*', isset(self::$seed) ? random_bytes(10) : self::$seed = random_bytes(16));
            self::$rand[1] &= 0x3ff;
            self::$time = $time;
        } else {
            // Within the same ms, we increment the rand part by a random 24-bit number.
            // Instead of getting this number from random_bytes(), which is slow, we get
            // it by sha512-hashing self::$seed. This produces 64 bytes of entropy,
            // which we need to split in a list of 24-bit numbers. unpack() first splits
            // them into 16 x 32-bit numbers; we take the first byte of each of these
            // numbers to get 5 extra 24-bit numbers. Then, we consume those numbers
            // one-by-one and run this logic every 21 iterations.
            // self::$rand holds the random part of the UUID, split into 5 x 16-bit
            // numbers for x86 portability. We increment this random part by the next
            // 24-bit number in the self::$seedParts list and decrement self::$seedIndex.
            if (!self::$seedIndex) {
                $s = unpack(\PHP_INT_SIZE >= 8 ? 'L*' : 'l*', self::$seed = hash('sha512', self::$seed, \true));
                $s[] = $s[1] >> 8 & 0xff0000 | $s[2] >> 16 & 0xff00 | $s[3] >> 24 & 0xff;
                $s[] = $s[4] >> 8 & 0xff0000 | $s[5] >> 16 & 0xff00 | $s[6] >> 24 & 0xff;
                $s[] = $s[7] >> 8 & 0xff0000 | $s[8] >> 16 & 0xff00 | $s[9] >> 24 & 0xff;
                $s[] = $s[10] >> 8 & 0xff0000 | $s[11] >> 16 & 0xff00 | $s[12] >> 24 & 0xff;
                $s[] = $s[13] >> 8 & 0xff0000 | $s[14] >> 16 & 0xff00 | $s[15] >> 24 & 0xff;
                self::$seedParts = $s;
                self::$seedIndex = 21;
            }
            self::$rand[5] = 0xffff & $carry = self::$rand[5] + 1 + (self::$seedParts[self::$seedIndex--] & 0xffffff);
            self::$rand[4] = 0xffff & $carry = self::$rand[4] + ($carry >> 16);
            self::$rand[3] = 0xffff & $carry = self::$rand[3] + ($carry >> 16);
            self::$rand[2] = 0xffff & $carry = self::$rand[2] + ($carry >> 16);
            self::$rand[1] += $carry >> 16;
            if (0xfc00 & self::$rand[1]) {
                if (\PHP_INT_SIZE >= 8 || 10 > \strlen($time = self::$time)) {
                    $time = (string) (1 + $time);
                } elseif ('999999999' === $mtime = substr($time, -9)) {
                    $time = 1 + substr($time, 0, -9) . '000000000';
                } else {
                    $time = substr_replace($time, str_pad(++$mtime, 9, '0', \STR_PAD_LEFT), -9);
                }
                goto randomize;
            }
            $time = self::$time;
        }
        if (\PHP_INT_SIZE >= 8) {
            $time = dechex($time);
        } else {
            $time = bin2hex(BinaryUtil::fromBase($time, BinaryUtil::BASE10));
        }
        return substr_replace(\sprintf('%012s-%04x-%04x-%04x%04x%04x', $time, 0x7000 | self::$rand[1] << 2 | self::$rand[2] >> 14, 0x8000 | self::$rand[2] & 0x3fff, self::$rand[3], self::$rand[4], self::$rand[5]), '-', 8, 0);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Uid\Factory;

use _ContaoManager\Symfony\Component\Uid\TimeBasedUidInterface;
use _ContaoManager\Symfony\Component\Uid\Uuid;
class TimeBasedUuidFactory
{
    /**
     * @var class-string<Uuid&TimeBasedUidInterface>
     */
    private string $class;
    private ?Uuid $node;
    /**
     * @param class-string<Uuid&TimeBasedUidInterface> $class
     */
    public function __construct(string $class, ?Uuid $node = null)
    {
        $this->class = $class;
        $this->node = $node;
    }
    public function create(?\DateTimeInterface $time = null): Uuid&TimeBasedUidInterface
    {
        $class = $this->class;
        if (null === $time && null === $this->node) {
            return new $class();
        }
        return new $class($class::generate($time, $this->node));
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Uid\Factory;

use _ContaoManager\Symfony\Component\Uid\Uuid;
use _ContaoManager\Symfony\Component\Uid\UuidV1;
use _ContaoManager\Symfony\Component\Uid\UuidV4;
use _ContaoManager\Symfony\Component\Uid\UuidV5;
use _ContaoManager\Symfony\Component\Uid\UuidV6;
class UuidFactory
{
    private string $defaultClass;
    private string $timeBasedClass;
    private string $nameBasedClass;
    private string $randomBasedClass;
    private ?Uuid $timeBasedNode;
    private ?Uuid $nameBasedNamespace;
    public function __construct(string|int $defaultClass = UuidV6::class, string|int $timeBasedClass = UuidV6::class, string|int $nameBasedClass = UuidV5::class, string|int $randomBasedClass = UuidV4::class, Uuid|string|null $timeBasedNode = null, Uuid|string|null $nameBasedNamespace = null)
    {
        if (null !== $timeBasedNode && !$timeBasedNode instanceof Uuid) {
            $timeBasedNode = Uuid::fromString($timeBasedNode);
        }
        if (null !== $nameBasedNamespace) {
            $nameBasedNamespace = $this->getNamespace($nameBasedNamespace);
        }
        $this->defaultClass = is_numeric($defaultClass) ? Uuid::class . 'V' . $defaultClass : $defaultClass;
        $this->timeBasedClass = is_numeric($timeBasedClass) ? Uuid::class . 'V' . $timeBasedClass : $timeBasedClass;
        $this->nameBasedClass = is_numeric($nameBasedClass) ? Uuid::class . 'V' . $nameBasedClass : $nameBasedClass;
        $this->randomBasedClass = is_numeric($randomBasedClass) ? Uuid::class . 'V' . $randomBasedClass : $randomBasedClass;
        $this->timeBasedNode = $timeBasedNode;
        $this->nameBasedNamespace = $nameBasedNamespace;
    }
    public function create(): Uuid
    {
        $class = $this->defaultClass;
        return new $class();
    }
    public function randomBased(): RandomBasedUuidFactory
    {
        return new RandomBasedUuidFactory($this->randomBasedClass);
    }
    public function timeBased(Uuid|string|null $node = null): TimeBasedUuidFactory
    {
        $node ??= $this->timeBasedNode;
        if (null !== $node && !$node instanceof Uuid) {
            $node = Uuid::fromString($node);
        }
        return new TimeBasedUuidFactory($this->timeBasedClass, $node);
    }
    public function nameBased(Uuid|string|null $namespace = null): NameBasedUuidFactory
    {
        $namespace ??= $this->nameBasedNamespace;
        if (null === $namespace) {
            throw new \LogicException(\sprintf('A namespace should be defined when using "%s()".', __METHOD__));
        }
        return new NameBasedUuidFactory($this->nameBasedClass, $this->getNamespace($namespace));
    }
    private function getNamespace(Uuid|string $namespace): Uuid
    {
        if ($namespace instanceof Uuid) {
            return $namespace;
        }
        return match ($namespace) {
            'dns' => new UuidV1(Uuid::NAMESPACE_DNS),
            'url' => new UuidV1(Uuid::NAMESPACE_URL),
            'oid' => new UuidV1(Uuid::NAMESPACE_OID),
            'x500' => new UuidV1(Uuid::NAMESPACE_X500),
            default => Uuid::fromString($namespace),
        };
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Uid\Factory;

use _ContaoManager\Symfony\Component\Uid\UuidV4;
class RandomBasedUuidFactory
{
    private string $class;
    public function __construct(string $class)
    {
        $this->class = $class;
    }
    public function create(): UuidV4
    {
        $class = $this->class;
        return new $class();
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Uid\Factory;

use _ContaoManager\Symfony\Component\Uid\Ulid;
class UlidFactory
{
    public function create(?\DateTimeInterface $time = null): Ulid
    {
        return new Ulid(null === $time ? null : Ulid::generate($time));
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Uid\Factory;

use _ContaoManager\Symfony\Component\Uid\Uuid;
use _ContaoManager\Symfony\Component\Uid\UuidV3;
use _ContaoManager\Symfony\Component\Uid\UuidV5;
class NameBasedUuidFactory
{
    private string $class;
    private Uuid $namespace;
    public function __construct(string $class, Uuid $namespace)
    {
        $this->class = $class;
        $this->namespace = $namespace;
    }
    public function create(string $name): UuidV5|UuidV3
    {
        switch ($class = $this->class) {
            case UuidV5::class:
                return Uuid::v5($this->namespace, $name);
            case UuidV3::class:
                return Uuid::v3($this->namespace, $name);
        }
        if (is_subclass_of($class, UuidV5::class)) {
            $uuid = Uuid::v5($this->namespace, $name);
        } else {
            $uuid = Uuid::v3($this->namespace, $name);
        }
        return new $class($uuid);
    }
}
{
    "name": "symfony\/uid",
    "type": "library",
    "description": "Provides an object-oriented API to generate and represent UIDs",
    "keywords": [
        "uid",
        "uuid",
        "ulid"
    ],
    "homepage": "https:\/\/symfony.com",
    "license": "MIT",
    "authors": [
        {
            "name": "Gr\u00e9goire Pineau",
            "email": "lyrixx@lyrixx.info"
        },
        {
            "name": "Nicolas Grekas",
            "email": "p@tchwork.com"
        },
        {
            "name": "Symfony Community",
            "homepage": "https:\/\/symfony.com\/contributors"
        }
    ],
    "require": {
        "php": ">=8.1",
        "symfony\/polyfill-uuid": "^1.15"
    },
    "require-dev": {
        "symfony\/console": "^5.4|^6.0|^7.0"
    },
    "autoload": {
        "psr-4": {
            "_ContaoManager\\Symfony\\Component\\Uid\\": ""
        },
        "exclude-from-classmap": [
            "\/Tests\/"
        ]
    },
    "minimum-stability": "dev"
}<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Uid;

/**
 * Interface to describe UIDs that contain a DateTimeImmutable as part of their behaviour.
 *
 * @author Barney Hanlon <barney.hanlon@cushon.co.uk>
 */
interface TimeBasedUidInterface
{
    public function getDateTime(): \DateTimeImmutable;
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Uid;

/**
 * A v5 UUID contains a SHA1 hash of another UUID and a name.
 *
 * Use Uuid::v5() to compute one.
 *
 * @author Grégoire Pineau <lyrixx@lyrixx.info>
 */
class UuidV5 extends Uuid
{
    protected const TYPE = 5;
    public function __construct(string $uuid)
    {
        parent::__construct($uuid, \true);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Uid;

/**
 * A v4 UUID contains a 122-bit random number.
 *
 * @author Grégoire Pineau <lyrixx@lyrixx.info>
 */
class UuidV4 extends Uuid
{
    protected const TYPE = 4;
    public function __construct(?string $uuid = null)
    {
        if (null === $uuid) {
            $uuid = random_bytes(16);
            $uuid[6] = $uuid[6] & "\x0f" | "@";
            $uuid[8] = $uuid[8] & "?" | "\x80";
            $uuid = bin2hex($uuid);
            $this->uid = substr($uuid, 0, 8) . '-' . substr($uuid, 8, 4) . '-' . substr($uuid, 12, 4) . '-' . substr($uuid, 16, 4) . '-' . substr($uuid, 20, 12);
        } else {
            parent::__construct($uuid, \true);
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\EventDispatcher;

use _ContaoManager\Symfony\Contracts\EventDispatcher\EventDispatcherInterface as ContractsEventDispatcherInterface;
/**
 * The EventDispatcherInterface is the central point of Symfony's event listener system.
 * Listeners are registered on the manager and events are dispatched through the
 * manager.
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
interface EventDispatcherInterface extends ContractsEventDispatcherInterface
{
    /**
     * Adds an event listener that listens on the specified events.
     *
     * @param int $priority The higher this value, the earlier an event
     *                      listener will be triggered in the chain (defaults to 0)
     *
     * @return void
     */
    public function addListener(string $eventName, callable $listener, int $priority = 0);
    /**
     * Adds an event subscriber.
     *
     * The subscriber is asked for all the events it is
     * interested in and added as a listener for these events.
     *
     * @return void
     */
    public function addSubscriber(EventSubscriberInterface $subscriber);
    /**
     * Removes an event listener from the specified events.
     *
     * @return void
     */
    public function removeListener(string $eventName, callable $listener);
    /**
     * @return void
     */
    public function removeSubscriber(EventSubscriberInterface $subscriber);
    /**
     * Gets the listeners of a specific event or all listeners sorted by descending priority.
     *
     * @return array<callable[]|callable>
     */
    public function getListeners(?string $eventName = null): array;
    /**
     * Gets the listener priority for a specific event.
     *
     * Returns null if the event or the listener does not exist.
     */
    public function getListenerPriority(string $eventName, callable $listener): ?int;
    /**
     * Checks whether an event has any registered listeners.
     */
    public function hasListeners(?string $eventName = null): bool;
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\EventDispatcher\Attribute;

/**
 * Service tag to autoconfigure event listeners.
 *
 * @author Alexander M. Turek <me@derrabus.de>
 */
#[\Attribute(\Attribute::TARGET_CLASS | \Attribute::TARGET_METHOD | \Attribute::IS_REPEATABLE)]
class AsEventListener
{
    public function __construct(public ?string $event = null, public ?string $method = null, public int $priority = 0, public ?string $dispatcher = null)
    {
    }
}
Copyright (c) 2004-present Fabien Potencier

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is furnished
to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
CHANGELOG
=========

6.0
---

 * Remove `LegacyEventDispatcherProxy`

5.4
---

 * Allow `#[AsEventListener]` attribute on methods

5.3
---

 * Add `#[AsEventListener]` attribute for declaring listeners on PHP 8

5.1.0
-----

 * The `LegacyEventDispatcherProxy` class has been deprecated.
 * Added an optional `dispatcher` attribute to the listener and subscriber tags in `RegisterListenerPass`.

5.0.0
-----

 * The signature of the `EventDispatcherInterface::dispatch()` method has been changed to `dispatch($event, string $eventName = null): object`.
 * The `Event` class has been removed in favor of `Symfony\Contracts\EventDispatcher\Event`.
 * The `TraceableEventDispatcherInterface` has been removed.
 * The `WrappedListener` class is now final.

4.4.0
-----

 * `AddEventAliasesPass` has been added, allowing applications and bundles to extend the event alias mapping used by `RegisterListenersPass`.
 * Made the `event` attribute of the `kernel.event_listener` tag optional for FQCN events.

4.3.0
-----

 * The signature of the `EventDispatcherInterface::dispatch()` method should be updated to `dispatch($event, string $eventName = null)`, not doing so is deprecated
 * deprecated the `Event` class, use `Symfony\Contracts\EventDispatcher\Event` instead

4.1.0
-----

 * added support for invokable event listeners tagged with `kernel.event_listener` by default
 * The `TraceableEventDispatcher::getOrphanedEvents()` method has been added.
 * The `TraceableEventDispatcherInterface` has been deprecated.

4.0.0
-----

 * removed the `ContainerAwareEventDispatcher` class
 * added the `reset()` method to the `TraceableEventDispatcherInterface`

3.4.0
-----

 * Implementing `TraceableEventDispatcherInterface` without the `reset()` method has been deprecated.

3.3.0
-----

 * The ContainerAwareEventDispatcher class has been deprecated. Use EventDispatcher with closure factories instead.

3.0.0
-----

 * The method `getListenerPriority($eventName, $listener)` has been added to the
   `EventDispatcherInterface`.
 * The methods `Event::setDispatcher()`, `Event::getDispatcher()`, `Event::setName()`
   and `Event::getName()` have been removed.
   The event dispatcher and the event name are passed to the listener call.

2.5.0
-----

 * added Debug\TraceableEventDispatcher (originally in HttpKernel)
 * changed Debug\TraceableEventDispatcherInterface to extend EventDispatcherInterface
 * added RegisterListenersPass (originally in HttpKernel)

2.1.0
-----

 * added TraceableEventDispatcherInterface
 * added ContainerAwareEventDispatcher
 * added a reference to the EventDispatcher on the Event
 * added a reference to the Event name on the event
 * added fluid interface to the dispatch() method which now returns the Event
   object
 * added GenericEvent event class
 * added the possibility for subscribers to subscribe several times for the
   same event
 * added ImmutableEventDispatcher
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\EventDispatcher;

use _ContaoManager\Psr\EventDispatcher\StoppableEventInterface;
use _ContaoManager\Symfony\Component\EventDispatcher\Debug\WrappedListener;
/**
 * The EventDispatcherInterface is the central point of Symfony's event listener system.
 *
 * Listeners are registered on the manager and events are dispatched through the
 * manager.
 *
 * @author Guilherme Blanco <guilhermeblanco@hotmail.com>
 * @author Jonathan Wage <jonwage@gmail.com>
 * @author Roman Borschel <roman@code-factory.org>
 * @author Bernhard Schussek <bschussek@gmail.com>
 * @author Fabien Potencier <fabien@symfony.com>
 * @author Jordi Boggiano <j.boggiano@seld.be>
 * @author Jordan Alliot <jordan.alliot@gmail.com>
 * @author Nicolas Grekas <p@tchwork.com>
 */
class EventDispatcher implements EventDispatcherInterface
{
    private array $listeners = [];
    private array $sorted = [];
    private array $optimized;
    public function __construct()
    {
        if (__CLASS__ === static::class) {
            $this->optimized = [];
        }
    }
    public function dispatch(object $event, ?string $eventName = null): object
    {
        $eventName ??= $event::class;
        if (isset($this->optimized)) {
            $listeners = $this->optimized[$eventName] ?? (empty($this->listeners[$eventName]) ? [] : $this->optimizeListeners($eventName));
        } else {
            $listeners = $this->getListeners($eventName);
        }
        if ($listeners) {
            $this->callListeners($listeners, $eventName, $event);
        }
        return $event;
    }
    public function getListeners(?string $eventName = null): array
    {
        if (null !== $eventName) {
            if (empty($this->listeners[$eventName])) {
                return [];
            }
            if (!isset($this->sorted[$eventName])) {
                $this->sortListeners($eventName);
            }
            return $this->sorted[$eventName];
        }
        foreach ($this->listeners as $eventName => $eventListeners) {
            if (!isset($this->sorted[$eventName])) {
                $this->sortListeners($eventName);
            }
        }
        return array_filter($this->sorted);
    }
    public function getListenerPriority(string $eventName, callable|array $listener): ?int
    {
        if (empty($this->listeners[$eventName])) {
            return null;
        }
        if (\is_array($listener) && isset($listener[0]) && $listener[0] instanceof \Closure && 2 >= \count($listener)) {
            $listener[0] = $listener[0]();
            $listener[1] ??= '__invoke';
        }
        foreach ($this->listeners[$eventName] as $priority => &$listeners) {
            foreach ($listeners as &$v) {
                if ($v !== $listener && \is_array($v) && isset($v[0]) && $v[0] instanceof \Closure && 2 >= \count($v)) {
                    $v[0] = $v[0]();
                    $v[1] ??= '__invoke';
                }
                if ($v === $listener || $listener instanceof \Closure && $v == $listener) {
                    return $priority;
                }
            }
        }
        return null;
    }
    public function hasListeners(?string $eventName = null): bool
    {
        if (null !== $eventName) {
            return !empty($this->listeners[$eventName]);
        }
        foreach ($this->listeners as $eventListeners) {
            if ($eventListeners) {
                return \true;
            }
        }
        return \false;
    }
    /**
     * @return void
     */
    public function addListener(string $eventName, callable|array $listener, int $priority = 0)
    {
        $this->listeners[$eventName][$priority][] = $listener;
        unset($this->sorted[$eventName], $this->optimized[$eventName]);
    }
    /**
     * @return void
     */
    public function removeListener(string $eventName, callable|array $listener)
    {
        if (empty($this->listeners[$eventName])) {
            return;
        }
        if (\is_array($listener) && isset($listener[0]) && $listener[0] instanceof \Closure && 2 >= \count($listener)) {
            $listener[0] = $listener[0]();
            $listener[1] ??= '__invoke';
        }
        foreach ($this->listeners[$eventName] as $priority => &$listeners) {
            foreach ($listeners as $k => &$v) {
                if ($v !== $listener && \is_array($v) && isset($v[0]) && $v[0] instanceof \Closure && 2 >= \count($v)) {
                    $v[0] = $v[0]();
                    $v[1] ??= '__invoke';
                }
                if ($v === $listener || $listener instanceof \Closure && $v == $listener) {
                    unset($listeners[$k], $this->sorted[$eventName], $this->optimized[$eventName]);
                }
            }
            if (!$listeners) {
                unset($this->listeners[$eventName][$priority]);
            }
        }
    }
    /**
     * @return void
     */
    public function addSubscriber(EventSubscriberInterface $subscriber)
    {
        foreach ($subscriber->getSubscribedEvents() as $eventName => $params) {
            if (\is_string($params)) {
                $this->addListener($eventName, [$subscriber, $params]);
            } elseif (\is_string($params[0])) {
                $this->addListener($eventName, [$subscriber, $params[0]], $params[1] ?? 0);
            } else {
                foreach ($params as $listener) {
                    $this->addListener($eventName, [$subscriber, $listener[0]], $listener[1] ?? 0);
                }
            }
        }
    }
    /**
     * @return void
     */
    public function removeSubscriber(EventSubscriberInterface $subscriber)
    {
        foreach ($subscriber->getSubscribedEvents() as $eventName => $params) {
            if (\is_array($params) && \is_array($params[0])) {
                foreach ($params as $listener) {
                    $this->removeListener($eventName, [$subscriber, $listener[0]]);
                }
            } else {
                $this->removeListener($eventName, [$subscriber, \is_string($params) ? $params : $params[0]]);
            }
        }
    }
    /**
     * Triggers the listeners of an event.
     *
     * This method can be overridden to add functionality that is executed
     * for each listener.
     *
     * @param callable[] $listeners The event listeners
     * @param string     $eventName The name of the event to dispatch
     * @param object     $event     The event object to pass to the event handlers/listeners
     *
     * @return void
     */
    protected function callListeners(iterable $listeners, string $eventName, object $event)
    {
        $stoppable = $event instanceof StoppableEventInterface;
        foreach ($listeners as $listener) {
            if ($stoppable && $event->isPropagationStopped()) {
                break;
            }
            $listener($event, $eventName, $this);
        }
    }
    /**
     * Sorts the internal list of listeners for the given event by priority.
     */
    private function sortListeners(string $eventName): void
    {
        krsort($this->listeners[$eventName]);
        $this->sorted[$eventName] = [];
        foreach ($this->listeners[$eventName] as &$listeners) {
            foreach ($listeners as &$listener) {
                if (\is_array($listener) && isset($listener[0]) && $listener[0] instanceof \Closure && 2 >= \count($listener)) {
                    $listener[0] = $listener[0]();
                    $listener[1] ??= '__invoke';
                }
                $this->sorted[$eventName][] = $listener;
            }
        }
    }
    /**
     * Optimizes the internal list of listeners for the given event by priority.
     */
    private function optimizeListeners(string $eventName): array
    {
        krsort($this->listeners[$eventName]);
        $this->optimized[$eventName] = [];
        foreach ($this->listeners[$eventName] as &$listeners) {
            foreach ($listeners as &$listener) {
                $closure =& $this->optimized[$eventName][];
                if (\is_array($listener) && isset($listener[0]) && $listener[0] instanceof \Closure && 2 >= \count($listener)) {
                    $closure = static function (...$args) use (&$listener, &$closure) {
                        if ($listener[0] instanceof \Closure) {
                            $listener[0] = $listener[0]();
                            $listener[1] ??= '__invoke';
                        }
                        ($closure = $listener(...))(...$args);
                    };
                } else {
                    $closure = $listener instanceof WrappedListener ? $listener : $listener(...);
                }
            }
        }
        return $this->optimized[$eventName];
    }
}
EventDispatcher Component
=========================

The EventDispatcher component provides tools that allow your application
components to communicate with each other by dispatching events and listening to
them.

Resources
---------

 * [Documentation](https://symfony.com/doc/current/components/event_dispatcher.html)
 * [Contributing](https://symfony.com/doc/current/contributing/index.html)
 * [Report issues](https://github.com/symfony/symfony/issues) and
   [send Pull Requests](https://github.com/symfony/symfony/pulls)
   in the [main Symfony repository](https://github.com/symfony/symfony)
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\EventDispatcher;

/**
 * An EventSubscriber knows itself what events it is interested in.
 * If an EventSubscriber is added to an EventDispatcherInterface, the manager invokes
 * {@link getSubscribedEvents} and registers the subscriber as a listener for all
 * returned events.
 *
 * @author Guilherme Blanco <guilhermeblanco@hotmail.com>
 * @author Jonathan Wage <jonwage@gmail.com>
 * @author Roman Borschel <roman@code-factory.org>
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
interface EventSubscriberInterface
{
    /**
     * Returns an array of event names this subscriber wants to listen to.
     *
     * The array keys are event names and the value can be:
     *
     *  * The method name to call (priority defaults to 0)
     *  * An array composed of the method name to call and the priority
     *  * An array of arrays composed of the method names to call and respective
     *    priorities, or 0 if unset
     *
     * For instance:
     *
     *  * ['eventName' => 'methodName']
     *  * ['eventName' => ['methodName', $priority]]
     *  * ['eventName' => [['methodName1', $priority], ['methodName2']]]
     *
     * The code must not depend on runtime state as it will only be called at compile time.
     * All logic depending on runtime state must be put into the individual methods handling the events.
     *
     * @return array<string, string|array{0: string, 1: int}|list<array{0: string, 1?: int}>>
     */
    public static function getSubscribedEvents();
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\EventDispatcher;

/**
 * A read-only proxy for an event dispatcher.
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
class ImmutableEventDispatcher implements EventDispatcherInterface
{
    private EventDispatcherInterface $dispatcher;
    public function __construct(EventDispatcherInterface $dispatcher)
    {
        $this->dispatcher = $dispatcher;
    }
    public function dispatch(object $event, ?string $eventName = null): object
    {
        return $this->dispatcher->dispatch($event, $eventName);
    }
    /**
     * @return never
     */
    public function addListener(string $eventName, callable|array $listener, int $priority = 0)
    {
        throw new \BadMethodCallException('Unmodifiable event dispatchers must not be modified.');
    }
    /**
     * @return never
     */
    public function addSubscriber(EventSubscriberInterface $subscriber)
    {
        throw new \BadMethodCallException('Unmodifiable event dispatchers must not be modified.');
    }
    /**
     * @return never
     */
    public function removeListener(string $eventName, callable|array $listener)
    {
        throw new \BadMethodCallException('Unmodifiable event dispatchers must not be modified.');
    }
    /**
     * @return never
     */
    public function removeSubscriber(EventSubscriberInterface $subscriber)
    {
        throw new \BadMethodCallException('Unmodifiable event dispatchers must not be modified.');
    }
    public function getListeners(?string $eventName = null): array
    {
        return $this->dispatcher->getListeners($eventName);
    }
    public function getListenerPriority(string $eventName, callable|array $listener): ?int
    {
        return $this->dispatcher->getListenerPriority($eventName, $listener);
    }
    public function hasListeners(?string $eventName = null): bool
    {
        return $this->dispatcher->hasListeners($eventName);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\EventDispatcher;

use _ContaoManager\Symfony\Contracts\EventDispatcher\Event;
/**
 * Event encapsulation class.
 *
 * Encapsulates events thus decoupling the observer from the subject they encapsulate.
 *
 * @author Drak <drak@zikula.org>
 *
 * @implements \ArrayAccess<string, mixed>
 * @implements \IteratorAggregate<string, mixed>
 */
class GenericEvent extends Event implements \ArrayAccess, \IteratorAggregate
{
    protected $subject;
    protected $arguments;
    /**
     * Encapsulate an event with $subject and $arguments.
     *
     * @param mixed $subject   The subject of the event, usually an object or a callable
     * @param array $arguments Arguments to store in the event
     */
    public function __construct(mixed $subject = null, array $arguments = [])
    {
        $this->subject = $subject;
        $this->arguments = $arguments;
    }
    /**
     * Getter for subject property.
     */
    public function getSubject(): mixed
    {
        return $this->subject;
    }
    /**
     * Get argument by key.
     *
     * @throws \InvalidArgumentException if key is not found
     */
    public function getArgument(string $key): mixed
    {
        if ($this->hasArgument($key)) {
            return $this->arguments[$key];
        }
        throw new \InvalidArgumentException(\sprintf('Argument "%s" not found.', $key));
    }
    /**
     * Add argument to event.
     *
     * @return $this
     */
    public function setArgument(string $key, mixed $value): static
    {
        $this->arguments[$key] = $value;
        return $this;
    }
    /**
     * Getter for all arguments.
     */
    public function getArguments(): array
    {
        return $this->arguments;
    }
    /**
     * Set args property.
     *
     * @return $this
     */
    public function setArguments(array $args = []): static
    {
        $this->arguments = $args;
        return $this;
    }
    /**
     * Has argument.
     */
    public function hasArgument(string $key): bool
    {
        return \array_key_exists($key, $this->arguments);
    }
    /**
     * ArrayAccess for argument getter.
     *
     * @param string $key Array key
     *
     * @throws \InvalidArgumentException if key does not exist in $this->args
     */
    public function offsetGet(mixed $key): mixed
    {
        return $this->getArgument($key);
    }
    /**
     * ArrayAccess for argument setter.
     *
     * @param string $key Array key to set
     */
    public function offsetSet(mixed $key, mixed $value): void
    {
        $this->setArgument($key, $value);
    }
    /**
     * ArrayAccess for unset argument.
     *
     * @param string $key Array key
     */
    public function offsetUnset(mixed $key): void
    {
        if ($this->hasArgument($key)) {
            unset($this->arguments[$key]);
        }
    }
    /**
     * ArrayAccess has argument.
     *
     * @param string $key Array key
     */
    public function offsetExists(mixed $key): bool
    {
        return $this->hasArgument($key);
    }
    /**
     * IteratorAggregate for iterating over the object like an array.
     *
     * @return \ArrayIterator<string, mixed>
     */
    public function getIterator(): \ArrayIterator
    {
        return new \ArrayIterator($this->arguments);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\EventDispatcher\DependencyInjection;

use _ContaoManager\Symfony\Component\DependencyInjection\Argument\ServiceClosureArgument;
use _ContaoManager\Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerBuilder;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
use _ContaoManager\Symfony\Component\DependencyInjection\Reference;
use _ContaoManager\Symfony\Component\EventDispatcher\EventDispatcher;
use _ContaoManager\Symfony\Component\EventDispatcher\EventSubscriberInterface;
use _ContaoManager\Symfony\Contracts\EventDispatcher\Event;
/**
 * Compiler pass to register tagged services for an event dispatcher.
 */
class RegisterListenersPass implements CompilerPassInterface
{
    private array $hotPathEvents = [];
    private array $noPreloadEvents = [];
    /**
     * @return $this
     */
    public function setHotPathEvents(array $hotPathEvents): static
    {
        $this->hotPathEvents = array_flip($hotPathEvents);
        return $this;
    }
    /**
     * @return $this
     */
    public function setNoPreloadEvents(array $noPreloadEvents): static
    {
        $this->noPreloadEvents = array_flip($noPreloadEvents);
        return $this;
    }
    /**
     * @return void
     */
    public function process(ContainerBuilder $container)
    {
        if (!$container->hasDefinition('event_dispatcher') && !$container->hasAlias('event_dispatcher')) {
            return;
        }
        $aliases = [];
        if ($container->hasParameter('event_dispatcher.event_aliases')) {
            $aliases = $container->getParameter('event_dispatcher.event_aliases');
        }
        $globalDispatcherDefinition = $container->findDefinition('event_dispatcher');
        foreach ($container->findTaggedServiceIds('kernel.event_listener', \true) as $id => $events) {
            $noPreload = 0;
            foreach ($events as $event) {
                $priority = $event['priority'] ?? 0;
                if (!isset($event['event'])) {
                    if ($container->getDefinition($id)->hasTag('kernel.event_subscriber')) {
                        continue;
                    }
                    $event['method'] ??= '__invoke';
                    $event['event'] = $this->getEventFromTypeDeclaration($container, $id, $event['method']);
                }
                $event['event'] = $aliases[$event['event']] ?? $event['event'];
                if (!isset($event['method'])) {
                    $event['method'] = 'on' . preg_replace_callback(['/(?<=\b|_)[a-z]/i', '/[^a-z0-9]/i'], fn($matches) => strtoupper($matches[0]), $event['event']);
                    $event['method'] = preg_replace('/[^a-z0-9]/i', '', $event['method']);
                    if (null !== ($class = $container->getDefinition($id)->getClass()) && ($r = $container->getReflectionClass($class, \false)) && !$r->hasMethod($event['method'])) {
                        if (!$r->hasMethod('__invoke')) {
                            throw new InvalidArgumentException(\sprintf('None of the "%s" or "__invoke" methods exist for the service "%s". Please define the "method" attribute on "kernel.event_listener" tags.', $event['method'], $id));
                        }
                        $event['method'] = '__invoke';
                    }
                }
                $dispatcherDefinition = $globalDispatcherDefinition;
                if (isset($event['dispatcher'])) {
                    $dispatcherDefinition = $container->findDefinition($event['dispatcher']);
                }
                $dispatcherDefinition->addMethodCall('addListener', [$event['event'], [new ServiceClosureArgument(new Reference($id)), $event['method']], $priority]);
                if (isset($this->hotPathEvents[$event['event']])) {
                    $container->getDefinition($id)->addTag('container.hot_path');
                } elseif (isset($this->noPreloadEvents[$event['event']])) {
                    ++$noPreload;
                }
            }
            if ($noPreload && \count($events) === $noPreload) {
                $container->getDefinition($id)->addTag('container.no_preload');
            }
        }
        $extractingDispatcher = new ExtractingEventDispatcher();
        foreach ($container->findTaggedServiceIds('kernel.event_subscriber', \true) as $id => $tags) {
            $def = $container->getDefinition($id);
            // We must assume that the class value has been correctly filled, even if the service is created by a factory
            $class = $def->getClass();
            if (!$r = $container->getReflectionClass($class)) {
                throw new InvalidArgumentException(\sprintf('Class "%s" used for service "%s" cannot be found.', $class, $id));
            }
            if (!$r->isSubclassOf(EventSubscriberInterface::class)) {
                throw new InvalidArgumentException(\sprintf('Service "%s" must implement interface "%s".', $id, EventSubscriberInterface::class));
            }
            $class = $r->name;
            $dispatcherDefinitions = [];
            foreach ($tags as $attributes) {
                if (!isset($attributes['dispatcher']) || isset($dispatcherDefinitions[$attributes['dispatcher']])) {
                    continue;
                }
                $dispatcherDefinitions[$attributes['dispatcher']] = $container->findDefinition($attributes['dispatcher']);
            }
            if (!$dispatcherDefinitions) {
                $dispatcherDefinitions = [$globalDispatcherDefinition];
            }
            $noPreload = 0;
            ExtractingEventDispatcher::$aliases = $aliases;
            ExtractingEventDispatcher::$subscriber = $class;
            $extractingDispatcher->addSubscriber($extractingDispatcher);
            foreach ($extractingDispatcher->listeners as $args) {
                $args[1] = [new ServiceClosureArgument(new Reference($id)), $args[1]];
                foreach ($dispatcherDefinitions as $dispatcherDefinition) {
                    $dispatcherDefinition->addMethodCall('addListener', $args);
                }
                if (isset($this->hotPathEvents[$args[0]])) {
                    $container->getDefinition($id)->addTag('container.hot_path');
                } elseif (isset($this->noPreloadEvents[$args[0]])) {
                    ++$noPreload;
                }
            }
            if ($noPreload && \count($extractingDispatcher->listeners) === $noPreload) {
                $container->getDefinition($id)->addTag('container.no_preload');
            }
            $extractingDispatcher->listeners = [];
            ExtractingEventDispatcher::$aliases = [];
        }
    }
    private function getEventFromTypeDeclaration(ContainerBuilder $container, string $id, string $method): string
    {
        if (null === ($class = $container->getDefinition($id)->getClass()) || !($r = $container->getReflectionClass($class, \false)) || !$r->hasMethod($method) || 1 > ($m = $r->getMethod($method))->getNumberOfParameters() || !($type = $m->getParameters()[0]->getType()) instanceof \ReflectionNamedType || $type->isBuiltin() || Event::class === $name = $type->getName()) {
            throw new InvalidArgumentException(\sprintf('Service "%s" must define the "event" attribute on "kernel.event_listener" tags.', $id));
        }
        return $name;
    }
}
/**
 * @internal
 */
class ExtractingEventDispatcher extends EventDispatcher implements EventSubscriberInterface
{
    public array $listeners = [];
    public static array $aliases = [];
    public static string $subscriber;
    public function addListener(string $eventName, callable|array $listener, int $priority = 0): void
    {
        $this->listeners[] = [$eventName, $listener[1], $priority];
    }
    public static function getSubscribedEvents(): array
    {
        $events = [];
        foreach ([self::$subscriber, 'getSubscribedEvents']() as $eventName => $params) {
            $events[self::$aliases[$eventName] ?? $eventName] = $params;
        }
        return $events;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\EventDispatcher\DependencyInjection;

use _ContaoManager\Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerBuilder;
/**
 * This pass allows bundles to extend the list of event aliases.
 *
 * @author Alexander M. Turek <me@derrabus.de>
 */
class AddEventAliasesPass implements CompilerPassInterface
{
    private array $eventAliases;
    public function __construct(array $eventAliases)
    {
        $this->eventAliases = $eventAliases;
    }
    public function process(ContainerBuilder $container): void
    {
        $eventAliases = $container->hasParameter('event_dispatcher.event_aliases') ? $container->getParameter('event_dispatcher.event_aliases') : [];
        $container->setParameter('event_dispatcher.event_aliases', array_merge($eventAliases, $this->eventAliases));
    }
}
{
    "name": "symfony\/event-dispatcher",
    "type": "library",
    "description": "Provides tools that allow your application components to communicate with each other by dispatching events and listening to them",
    "keywords": [],
    "homepage": "https:\/\/symfony.com",
    "license": "MIT",
    "authors": [
        {
            "name": "Fabien Potencier",
            "email": "fabien@symfony.com"
        },
        {
            "name": "Symfony Community",
            "homepage": "https:\/\/symfony.com\/contributors"
        }
    ],
    "require": {
        "php": ">=8.1",
        "symfony\/event-dispatcher-contracts": "^2.5|^3"
    },
    "require-dev": {
        "symfony\/dependency-injection": "^5.4|^6.0|^7.0",
        "symfony\/expression-language": "^5.4|^6.0|^7.0",
        "symfony\/config": "^5.4|^6.0|^7.0",
        "symfony\/error-handler": "^5.4|^6.0|^7.0",
        "symfony\/http-foundation": "^5.4|^6.0|^7.0",
        "symfony\/service-contracts": "^2.5|^3",
        "symfony\/stopwatch": "^5.4|^6.0|^7.0",
        "psr\/log": "^1|^2|^3"
    },
    "conflict": {
        "symfony\/dependency-injection": "<5.4",
        "symfony\/service-contracts": "<2.5"
    },
    "provide": {
        "psr\/event-dispatcher-implementation": "1.0",
        "symfony\/event-dispatcher-implementation": "2.0|3.0"
    },
    "autoload": {
        "psr-4": {
            "_ContaoManager\\Symfony\\Component\\EventDispatcher\\": ""
        },
        "exclude-from-classmap": [
            "\/Tests\/"
        ]
    },
    "minimum-stability": "dev"
}<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\EventDispatcher\Debug;

use _ContaoManager\Psr\EventDispatcher\StoppableEventInterface;
use _ContaoManager\Psr\Log\LoggerInterface;
use _ContaoManager\Symfony\Component\EventDispatcher\EventDispatcher;
use _ContaoManager\Symfony\Component\EventDispatcher\EventDispatcherInterface;
use _ContaoManager\Symfony\Component\EventDispatcher\EventSubscriberInterface;
use _ContaoManager\Symfony\Component\HttpFoundation\Request;
use _ContaoManager\Symfony\Component\HttpFoundation\RequestStack;
use _ContaoManager\Symfony\Component\Stopwatch\Stopwatch;
use _ContaoManager\Symfony\Contracts\Service\ResetInterface;
/**
 * Collects some data about event listeners.
 *
 * This event dispatcher delegates the dispatching to another one.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class TraceableEventDispatcher implements EventDispatcherInterface, ResetInterface
{
    protected $logger;
    protected $stopwatch;
    /**
     * @var \SplObjectStorage<WrappedListener, array{string, string}>|null
     */
    private ?\SplObjectStorage $callStack = null;
    private EventDispatcherInterface $dispatcher;
    private array $wrappedListeners = [];
    private array $orphanedEvents = [];
    private array $dispatchDepth = [];
    private array $calledListenerInfos = [];
    private array $calledOriginalListeners = [];
    private ?RequestStack $requestStack;
    private string $currentRequestHash = '';
    public function __construct(EventDispatcherInterface $dispatcher, Stopwatch $stopwatch, ?LoggerInterface $logger = null, ?RequestStack $requestStack = null)
    {
        $this->dispatcher = $dispatcher;
        $this->stopwatch = $stopwatch;
        $this->logger = $logger;
        $this->requestStack = $requestStack;
    }
    /**
     * @return void
     */
    public function addListener(string $eventName, callable|array $listener, int $priority = 0)
    {
        $this->dispatcher->addListener($eventName, $listener, $priority);
    }
    /**
     * @return void
     */
    public function addSubscriber(EventSubscriberInterface $subscriber)
    {
        $this->dispatcher->addSubscriber($subscriber);
    }
    /**
     * @return void
     */
    public function removeListener(string $eventName, callable|array $listener)
    {
        if (isset($this->wrappedListeners[$eventName])) {
            foreach ($this->wrappedListeners[$eventName] as $index => $wrappedListener) {
                if ($wrappedListener->getWrappedListener() === $listener || $listener instanceof \Closure && $wrappedListener->getWrappedListener() == $listener) {
                    $listener = $wrappedListener;
                    unset($this->wrappedListeners[$eventName][$index]);
                    break;
                }
            }
        }
        $this->dispatcher->removeListener($eventName, $listener);
    }
    /**
     * @return void
     */
    public function removeSubscriber(EventSubscriberInterface $subscriber)
    {
        $this->dispatcher->removeSubscriber($subscriber);
    }
    public function getListeners(?string $eventName = null): array
    {
        return $this->dispatcher->getListeners($eventName);
    }
    public function getListenerPriority(string $eventName, callable|array $listener): ?int
    {
        // we might have wrapped listeners for the event (if called while dispatching)
        // in that case get the priority by wrapper
        if (isset($this->wrappedListeners[$eventName])) {
            foreach ($this->wrappedListeners[$eventName] as $wrappedListener) {
                if ($wrappedListener->getWrappedListener() === $listener || $listener instanceof \Closure && $wrappedListener->getWrappedListener() == $listener) {
                    return $this->dispatcher->getListenerPriority($eventName, $wrappedListener);
                }
            }
        }
        return $this->dispatcher->getListenerPriority($eventName, $listener);
    }
    public function hasListeners(?string $eventName = null): bool
    {
        return $this->dispatcher->hasListeners($eventName);
    }
    public function dispatch(object $event, ?string $eventName = null): object
    {
        $eventName ??= $event::class;
        $this->callStack ??= new \SplObjectStorage();
        $currentRequestHash = $this->currentRequestHash = $this->requestStack && ($request = $this->requestStack->getCurrentRequest()) ? spl_object_hash($request) : '';
        if (null !== $this->logger && $event instanceof StoppableEventInterface && $event->isPropagationStopped()) {
            $this->logger->debug(\sprintf('The "%s" event is already stopped. No listeners have been called.', $eventName));
        }
        $this->preProcess($eventName);
        try {
            $this->beforeDispatch($eventName, $event);
            try {
                $e = $this->stopwatch->start($eventName, 'section');
                try {
                    $this->dispatcher->dispatch($event, $eventName);
                } finally {
                    if ($e->isStarted()) {
                        $e->stop();
                    }
                }
            } finally {
                $this->afterDispatch($eventName, $event);
            }
        } finally {
            $this->currentRequestHash = $currentRequestHash;
            $this->postProcess($eventName);
        }
        return $event;
    }
    public function getCalledListeners(?Request $request = null): array
    {
        if (!$this->calledListenerInfos) {
            return [];
        }
        $hash = $request ? spl_object_hash($request) : null;
        $called = [];
        foreach ($this->calledListenerInfos as $requestHash => $infos) {
            if (null === $hash || $hash === $requestHash) {
                $called[] = $infos;
            }
        }
        return $called ? array_merge(...$called) : [];
    }
    public function getNotCalledListeners(?Request $request = null): array
    {
        try {
            $allListeners = $this->dispatcher instanceof EventDispatcher ? $this->getListenersWithPriority() : $this->getListenersWithoutPriority();
        } catch (\Exception $e) {
            $this->logger?->info('An exception was thrown while getting the uncalled listeners.', ['exception' => $e]);
            // unable to retrieve the uncalled listeners
            return [];
        }
        $hash = $request ? spl_object_hash($request) : null;
        $calledListeners = [];
        foreach ($this->calledOriginalListeners as $requestHash => $eventListeners) {
            if (null === $hash || $hash === $requestHash) {
                $calledListeners[] = array_merge(...array_values($eventListeners));
            }
        }
        $calledListeners = $calledListeners ? array_merge(...$calledListeners) : [];
        $notCalled = [];
        foreach ($allListeners as $eventName => $listeners) {
            foreach ($listeners as [$listener, $priority]) {
                if (!\in_array($listener, $calledListeners, \true)) {
                    if (!$listener instanceof WrappedListener) {
                        $listener = new WrappedListener($listener, null, $this->stopwatch, $this, $priority);
                    }
                    $notCalled[] = $listener->getInfo($eventName);
                }
            }
        }
        uasort($notCalled, $this->sortNotCalledListeners(...));
        return $notCalled;
    }
    public function getOrphanedEvents(?Request $request = null): array
    {
        if ($request) {
            return $this->orphanedEvents[spl_object_hash($request)] ?? [];
        }
        if (!$this->orphanedEvents) {
            return [];
        }
        return array_merge(...array_values($this->orphanedEvents));
    }
    /**
     * @return void
     */
    public function reset()
    {
        $this->callStack = null;
        $this->orphanedEvents = [];
        $this->currentRequestHash = '';
        $this->dispatchDepth = [];
        $this->calledListenerInfos = [];
        $this->calledOriginalListeners = [];
    }
    /**
     * Proxies all method calls to the original event dispatcher.
     *
     * @param string $method    The method name
     * @param array  $arguments The method arguments
     */
    public function __call(string $method, array $arguments): mixed
    {
        return $this->dispatcher->{$method}(...$arguments);
    }
    /**
     * Called before dispatching the event.
     *
     * @return void
     */
    protected function beforeDispatch(string $eventName, object $event)
    {
    }
    /**
     * Called after dispatching the event.
     *
     * @return void
     */
    protected function afterDispatch(string $eventName, object $event)
    {
    }
    private function preProcess(string $eventName): void
    {
        $this->dispatchDepth[$eventName] = ($this->dispatchDepth[$eventName] ?? 0) + 1;
        if (!$this->dispatcher->hasListeners($eventName)) {
            $this->orphanedEvents[$this->currentRequestHash][] = $eventName;
            return;
        }
        foreach ($this->dispatcher->getListeners($eventName) as $listener) {
            $priority = $this->getListenerPriority($eventName, $listener);
            $wrappedListener = new WrappedListener($listener instanceof WrappedListener ? $listener->getWrappedListener() : $listener, null, $this->stopwatch, $this);
            $this->wrappedListeners[$eventName][] = $wrappedListener;
            $this->dispatcher->removeListener($eventName, $listener);
            $this->dispatcher->addListener($eventName, $wrappedListener, $priority);
            $this->callStack[$wrappedListener] = [$eventName, $this->currentRequestHash];
        }
    }
    private function postProcess(string $eventName): void
    {
        --$this->dispatchDepth[$eventName];
        unset($this->wrappedListeners[$eventName]);
        $skipped = \false;
        foreach ($this->dispatcher->getListeners($eventName) as $listener) {
            if (!$listener instanceof WrappedListener) {
                // #12845: a new listener was added during dispatch.
                continue;
            }
            // Unwrap listener
            $priority = $this->getListenerPriority($eventName, $listener);
            $this->dispatcher->removeListener($eventName, $listener);
            $this->dispatcher->addListener($eventName, $listener->getWrappedListener(), $priority);
            if (null !== $this->logger) {
                $context = ['event' => $eventName, 'listener' => $listener->getPretty()];
            }
            if ($listener->wasCalled()) {
                $this->logger?->debug('Notified event "{event}" to listener "{listener}".', $context);
                $original = $listener->getWrappedListener();
                if (!\in_array($original, $this->calledOriginalListeners[$this->currentRequestHash][$eventName] ?? [], \true)) {
                    $this->calledOriginalListeners[$this->currentRequestHash][$eventName][] = $original;
                    $this->calledListenerInfos[$this->currentRequestHash][] = $listener->getInfo($eventName);
                }
            }
            unset($this->callStack[$listener]);
            if (null !== $this->logger && $skipped) {
                $this->logger->debug('Listener "{listener}" was not called for event "{event}".', $context);
            }
            if ($listener->stoppedPropagation()) {
                $this->logger?->debug('Listener "{listener}" stopped propagation of the event "{event}".', $context);
                $skipped = \true;
            }
        }
        if (0 < $this->dispatchDepth[$eventName]) {
            return;
        }
        // Clean up stale callStack entries left by nested same-event dispatches
        $stale = [];
        foreach ($this->callStack as $listener) {
            if ($this->callStack->getInfo()[0] === $eventName) {
                $stale[] = $listener;
            }
        }
        foreach ($stale as $listener) {
            if ($listener->wasCalled()) {
                $original = $listener->getWrappedListener();
                if (!\in_array($original, $this->calledOriginalListeners[$this->currentRequestHash][$eventName] ?? [], \true)) {
                    $this->calledOriginalListeners[$this->currentRequestHash][$eventName][] = $original;
                    $this->calledListenerInfos[$this->currentRequestHash][] = $listener->getInfo($eventName);
                }
            }
            unset($this->callStack[$listener]);
        }
    }
    private function sortNotCalledListeners(array $a, array $b): int
    {
        if (0 !== $cmp = strcmp($a['event'], $b['event'])) {
            return $cmp;
        }
        if (\is_int($a['priority']) && !\is_int($b['priority'])) {
            return 1;
        }
        if (!\is_int($a['priority']) && \is_int($b['priority'])) {
            return -1;
        }
        if ($a['priority'] === $b['priority']) {
            return 0;
        }
        if ($a['priority'] > $b['priority']) {
            return -1;
        }
        return 1;
    }
    private function getListenersWithPriority(): array
    {
        $result = [];
        $allListeners = new \ReflectionProperty(EventDispatcher::class, 'listeners');
        foreach ($allListeners->getValue($this->dispatcher) as $eventName => $listenersByPriority) {
            foreach ($listenersByPriority as $priority => $listeners) {
                foreach ($listeners as $listener) {
                    $result[$eventName][] = [$listener, $priority];
                }
            }
        }
        return $result;
    }
    private function getListenersWithoutPriority(): array
    {
        $result = [];
        foreach ($this->getListeners() as $eventName => $listeners) {
            foreach ($listeners as $listener) {
                $result[$eventName][] = [$listener, null];
            }
        }
        return $result;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\EventDispatcher\Debug;

use _ContaoManager\Psr\EventDispatcher\StoppableEventInterface;
use _ContaoManager\Symfony\Component\EventDispatcher\EventDispatcherInterface;
use _ContaoManager\Symfony\Component\Stopwatch\Stopwatch;
use _ContaoManager\Symfony\Component\VarDumper\Caster\ClassStub;
/**
 * @author Fabien Potencier <fabien@symfony.com>
 */
final class WrappedListener
{
    private string|array|object $listener;
    private ?\Closure $optimizedListener;
    private string $name;
    private bool $called = \false;
    private bool $stoppedPropagation = \false;
    private Stopwatch $stopwatch;
    private ?EventDispatcherInterface $dispatcher;
    private string $pretty;
    private string $callableRef;
    private ClassStub|string $stub;
    private ?int $priority = null;
    private static bool $hasClassStub;
    public function __construct(callable|array $listener, ?string $name, Stopwatch $stopwatch, ?EventDispatcherInterface $dispatcher = null, ?int $priority = null)
    {
        $this->listener = $listener;
        $this->optimizedListener = $listener instanceof \Closure ? $listener : (\is_callable($listener) ? $listener(...) : null);
        $this->stopwatch = $stopwatch;
        $this->dispatcher = $dispatcher;
        $this->priority = $priority;
        if (\is_array($listener)) {
            [$this->name, $this->callableRef] = $this->parseListener($listener);
            $this->pretty = $this->name . '::' . $listener[1];
            $this->callableRef .= '::' . $listener[1];
        } elseif ($listener instanceof \Closure) {
            $r = new \ReflectionFunction($listener);
            if (str_contains($r->name, '{closure')) {
                $this->pretty = $this->name = 'closure';
            } elseif ($class = \PHP_VERSION_ID >= 80111 ? $r->getClosureCalledClass() : $r->getClosureScopeClass()) {
                $this->name = $class->name;
                $this->pretty = $this->name . '::' . $r->name;
            } else {
                $this->pretty = $this->name = $r->name;
            }
        } elseif (\is_string($listener)) {
            $this->pretty = $this->name = $listener;
        } else {
            $this->name = get_debug_type($listener);
            $this->pretty = $this->name . '::__invoke';
            $this->callableRef = $listener::class . '::__invoke';
        }
        if (null !== $name) {
            $this->name = $name;
        }
        self::$hasClassStub ??= class_exists(ClassStub::class);
    }
    public function getWrappedListener(): callable|array
    {
        return $this->listener;
    }
    public function wasCalled(): bool
    {
        return $this->called;
    }
    public function stoppedPropagation(): bool
    {
        return $this->stoppedPropagation;
    }
    public function getPretty(): string
    {
        return $this->pretty;
    }
    public function getInfo(string $eventName): array
    {
        $this->stub ??= self::$hasClassStub ? new ClassStub($this->pretty . '()', $this->callableRef ?? $this->listener) : $this->pretty . '()';
        return ['event' => $eventName, 'priority' => $this->priority ??= $this->dispatcher?->getListenerPriority($eventName, $this->listener), 'pretty' => $this->pretty, 'stub' => $this->stub];
    }
    public function __invoke(object $event, string $eventName, EventDispatcherInterface $dispatcher): void
    {
        $dispatcher = $this->dispatcher ?: $dispatcher;
        $this->called = \true;
        $this->priority ??= $dispatcher->getListenerPriority($eventName, $this->listener);
        $e = $this->stopwatch->start($this->name, 'event_listener');
        try {
            ($this->optimizedListener ?? $this->listener)($event, $eventName, $dispatcher);
        } finally {
            if ($e->isStarted()) {
                $e->stop();
            }
        }
        if ($event instanceof StoppableEventInterface && $event->isPropagationStopped()) {
            $this->stoppedPropagation = \true;
        }
    }
    private function parseListener(array $listener): array
    {
        if ($listener[0] instanceof \Closure) {
            foreach ((new \ReflectionFunction($listener[0]))->getAttributes(\Closure::class) as $attribute) {
                if ($name = $attribute->getArguments()['name'] ?? \false) {
                    return [$name, $attribute->getArguments()['class'] ?? $name];
                }
            }
        }
        if (\is_object($listener[0])) {
            return [get_debug_type($listener[0]), $listener[0]::class];
        }
        return [$listener[0], $listener[0]];
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\VarDumper\Cloner;

/**
 * Represents the current state of a dumper while dumping.
 *
 * @author Nicolas Grekas <p@tchwork.com>
 */
class Cursor
{
    public const HASH_INDEXED = Stub::ARRAY_INDEXED;
    public const HASH_ASSOC = Stub::ARRAY_ASSOC;
    public const HASH_OBJECT = Stub::TYPE_OBJECT;
    public const HASH_RESOURCE = Stub::TYPE_RESOURCE;
    public $depth = 0;
    public $refIndex = 0;
    public $softRefTo = 0;
    public $softRefCount = 0;
    public $softRefHandle = 0;
    public $hardRefTo = 0;
    public $hardRefCount = 0;
    public $hardRefHandle = 0;
    public $hashType;
    public $hashKey;
    public $hashKeyIsBinary;
    public $hashIndex = 0;
    public $hashLength = 0;
    public $hashCut = 0;
    public $stop = \false;
    public $attr = [];
    public $skipChildren = \false;
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\VarDumper\Cloner;

/**
 * @author Nicolas Grekas <p@tchwork.com>
 */
class VarCloner extends AbstractCloner
{
    private static array $arrayCache = [];
    protected function doClone(mixed $var): array
    {
        $len = 1;
        // Length of $queue
        $pos = 0;
        // Number of cloned items past the minimum depth
        $refsCounter = 0;
        // Hard references counter
        $queue = [[$var]];
        // This breadth-first queue is the return value
        $hardRefs = [];
        // Map of original zval ids to stub objects
        $objRefs = [];
        // Map of original object handles to their stub object counterpart
        $objects = [];
        // Keep a ref to objects to ensure their handle cannot be reused while cloning
        $resRefs = [];
        // Map of original resource handles to their stub object counterpart
        $values = [];
        // Map of stub objects' ids to original values
        $maxItems = $this->maxItems;
        $maxString = $this->maxString;
        $minDepth = $this->minDepth;
        $currentDepth = 0;
        // Current tree depth
        $currentDepthFinalIndex = 0;
        // Final $queue index for current tree depth
        $minimumDepthReached = 0 === $minDepth;
        // Becomes true when minimum tree depth has been reached
        $cookie = (object) [];
        // Unique object used to detect hard references
        $a = null;
        // Array cast for nested structures
        $stub = null;
        // Stub capturing the main properties of an original item value
        // or null if the original value is used directly
        $arrayStub = new Stub();
        $arrayStub->type = Stub::TYPE_ARRAY;
        $fromObjCast = \false;
        for ($i = 0; $i < $len; ++$i) {
            // Detect when we move on to the next tree depth
            if ($i > $currentDepthFinalIndex) {
                ++$currentDepth;
                $currentDepthFinalIndex = $len - 1;
                if ($currentDepth >= $minDepth) {
                    $minimumDepthReached = \true;
                }
            }
            $refs = $vals = $queue[$i];
            foreach ($vals as $k => $v) {
                // $v is the original value or a stub object in case of hard references
                $zvalRef = ($r = \ReflectionReference::fromArrayElement($vals, $k)) ? $r->getId() : null;
                if ($zvalRef) {
                    $vals[$k] =& $stub;
                    // Break hard references to make $queue completely
                    unset($stub);
                    // independent from the original structure
                    if (null !== $vals[$k] = $hardRefs[$zvalRef] ?? null) {
                        $v = $vals[$k];
                        if ($v->value instanceof Stub && (Stub::TYPE_OBJECT === $v->value->type || Stub::TYPE_RESOURCE === $v->value->type)) {
                            ++$v->value->refCount;
                        }
                        ++$v->refCount;
                        continue;
                    }
                    $vals[$k] = new Stub();
                    $vals[$k]->value = $v;
                    $vals[$k]->handle = ++$refsCounter;
                    $hardRefs[$zvalRef] = $vals[$k];
                }
                // Create $stub when the original value $v cannot be used directly
                // If $v is a nested structure, put that structure in array $a
                switch (\true) {
                    case null === $v:
                    case \is_bool($v):
                    case \is_int($v):
                    case \is_float($v):
                        continue 2;
                    case \is_string($v):
                        if ('' === $v) {
                            continue 2;
                        }
                        if (!preg_match('//u', $v)) {
                            $stub = new Stub();
                            $stub->type = Stub::TYPE_STRING;
                            $stub->class = Stub::STRING_BINARY;
                            if (0 <= $maxString && 0 < $cut = \strlen($v) - $maxString) {
                                $stub->cut = $cut;
                                $stub->value = substr($v, 0, -$cut);
                            } else {
                                $stub->value = $v;
                            }
                        } elseif (0 <= $maxString && isset($v[1 + ($maxString >> 2)]) && 0 < $cut = mb_strlen($v, 'UTF-8') - $maxString) {
                            $stub = new Stub();
                            $stub->type = Stub::TYPE_STRING;
                            $stub->class = Stub::STRING_UTF8;
                            $stub->cut = $cut;
                            $stub->value = mb_substr($v, 0, $maxString, 'UTF-8');
                        } else {
                            continue 2;
                        }
                        $a = null;
                        break;
                    case \is_array($v):
                        if (!$v) {
                            continue 2;
                        }
                        $stub = $arrayStub;
                        $stub->class = array_is_list($v) ? Stub::ARRAY_INDEXED : Stub::ARRAY_ASSOC;
                        $a = $v;
                        break;
                    case \is_object($v):
                        if (empty($objRefs[$h = spl_object_id($v)])) {
                            $stub = new Stub();
                            $stub->type = Stub::TYPE_OBJECT;
                            $stub->class = $v::class;
                            $stub->value = $v;
                            $stub->handle = $h;
                            $a = $this->castObject($stub, 0 < $i);
                            if ($v !== $stub->value) {
                                if (Stub::TYPE_OBJECT !== $stub->type || null === $stub->value) {
                                    break;
                                }
                                $stub->handle = $h = spl_object_id($stub->value);
                            }
                            $stub->value = null;
                            if (0 <= $maxItems && $maxItems <= $pos && $minimumDepthReached) {
                                $stub->cut = \count($a);
                                $a = null;
                            }
                        }
                        if (empty($objRefs[$h])) {
                            $objRefs[$h] = $stub;
                            $objects[] = $v;
                        } else {
                            $stub = $objRefs[$h];
                            ++$stub->refCount;
                            $a = null;
                        }
                        break;
                    default:
                        // resource
                        if (empty($resRefs[$h = (int) $v])) {
                            $stub = new Stub();
                            $stub->type = Stub::TYPE_RESOURCE;
                            if ('Unknown' === $stub->class = @get_resource_type($v)) {
                                $stub->class = 'Closed';
                            }
                            $stub->value = $v;
                            $stub->handle = $h;
                            $a = $this->castResource($stub, 0 < $i);
                            $stub->value = null;
                            if (0 <= $maxItems && $maxItems <= $pos && $minimumDepthReached) {
                                $stub->cut = \count($a);
                                $a = null;
                            }
                        }
                        if (empty($resRefs[$h])) {
                            $resRefs[$h] = $stub;
                        } else {
                            $stub = $resRefs[$h];
                            ++$stub->refCount;
                            $a = null;
                        }
                        break;
                }
                if ($a) {
                    if (!$minimumDepthReached || 0 > $maxItems) {
                        $queue[$len] = $a;
                        $stub->position = $len++;
                    } elseif ($pos < $maxItems) {
                        if ($maxItems < $pos += \count($a)) {
                            $a = \array_slice($a, 0, $maxItems - $pos, \true);
                            if ($stub->cut >= 0) {
                                $stub->cut += $pos - $maxItems;
                            }
                        }
                        $queue[$len] = $a;
                        $stub->position = $len++;
                    } elseif ($stub->cut >= 0) {
                        $stub->cut += \count($a);
                        $stub->position = 0;
                    }
                }
                if ($arrayStub === $stub) {
                    if ($arrayStub->cut) {
                        $stub = [$arrayStub->cut, $arrayStub->class => $arrayStub->position];
                        $arrayStub->cut = 0;
                    } elseif (isset(self::$arrayCache[$arrayStub->class][$arrayStub->position])) {
                        $stub = self::$arrayCache[$arrayStub->class][$arrayStub->position];
                    } else {
                        self::$arrayCache[$arrayStub->class][$arrayStub->position] = $stub = [$arrayStub->class => $arrayStub->position];
                    }
                }
                if (!$zvalRef) {
                    $vals[$k] = $stub;
                } else {
                    $hardRefs[$zvalRef]->value = $stub;
                }
            }
            if ($fromObjCast) {
                $fromObjCast = \false;
                $refs = $vals;
                $vals = [];
                $j = -1;
                foreach ($queue[$i] as $k => $v) {
                    foreach ([$k => \true] as $gk => $gv) {
                    }
                    if ($gk !== $k) {
                        $vals = (object) $vals;
                        $vals->{$k} = $refs[++$j];
                        $vals = (array) $vals;
                    } else {
                        $vals[$k] = $refs[++$j];
                    }
                }
            }
            $queue[$i] = $vals;
        }
        foreach ($values as $h => $v) {
            $hardRefs[$h] = $v;
        }
        return $queue;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\VarDumper\Cloner;

/**
 * @author Nicolas Grekas <p@tchwork.com>
 */
interface ClonerInterface
{
    /**
     * Clones a PHP variable.
     */
    public function cloneVar(mixed $var): Data;
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\VarDumper\Cloner;

/**
 * DumperInterface used by Data objects.
 *
 * @author Nicolas Grekas <p@tchwork.com>
 */
interface DumperInterface
{
    /**
     * Dumps a scalar value.
     *
     * @return void
     */
    public function dumpScalar(Cursor $cursor, string $type, string|int|float|bool|null $value);
    /**
     * Dumps a string.
     *
     * @param string $str The string being dumped
     * @param bool   $bin Whether $str is UTF-8 or binary encoded
     * @param int    $cut The number of characters $str has been cut by
     *
     * @return void
     */
    public function dumpString(Cursor $cursor, string $str, bool $bin, int $cut);
    /**
     * Dumps while entering an hash.
     *
     * @param int             $type     A Cursor::HASH_* const for the type of hash
     * @param string|int|null $class    The object class, resource type or array count
     * @param bool            $hasChild When the dump of the hash has child item
     *
     * @return void
     */
    public function enterHash(Cursor $cursor, int $type, string|int|null $class, bool $hasChild);
    /**
     * Dumps while leaving an hash.
     *
     * @param int             $type     A Cursor::HASH_* const for the type of hash
     * @param string|int|null $class    The object class, resource type or array count
     * @param bool            $hasChild When the dump of the hash has child item
     * @param int             $cut      The number of items the hash has been cut by
     *
     * @return void
     */
    public function leaveHash(Cursor $cursor, int $type, string|int|null $class, bool $hasChild, int $cut);
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\VarDumper\Cloner;

use _ContaoManager\Symfony\Component\VarDumper\Caster\Caster;
use _ContaoManager\Symfony\Component\VarDumper\Exception\ThrowingCasterException;
/**
 * AbstractCloner implements a generic caster mechanism for objects and resources.
 *
 * @author Nicolas Grekas <p@tchwork.com>
 */
abstract class AbstractCloner implements ClonerInterface
{
    public static $defaultCasters = ['__PHP_Incomplete_Class' => ['_ContaoManager\Symfony\Component\VarDumper\Caster\Caster', 'castPhpIncompleteClass'], '_ContaoManager\Symfony\Component\VarDumper\Caster\CutStub' => ['_ContaoManager\Symfony\Component\VarDumper\Caster\StubCaster', 'castStub'], '_ContaoManager\Symfony\Component\VarDumper\Caster\CutArrayStub' => ['_ContaoManager\Symfony\Component\VarDumper\Caster\StubCaster', 'castCutArray'], '_ContaoManager\Symfony\Component\VarDumper\Caster\ConstStub' => ['_ContaoManager\Symfony\Component\VarDumper\Caster\StubCaster', 'castStub'], '_ContaoManager\Symfony\Component\VarDumper\Caster\EnumStub' => ['_ContaoManager\Symfony\Component\VarDumper\Caster\StubCaster', 'castEnum'], '_ContaoManager\Symfony\Component\VarDumper\Caster\ScalarStub' => ['_ContaoManager\Symfony\Component\VarDumper\Caster\StubCaster', 'castScalar'], 'Fiber' => ['_ContaoManager\Symfony\Component\VarDumper\Caster\FiberCaster', 'castFiber'], 'Closure' => ['_ContaoManager\Symfony\Component\VarDumper\Caster\ReflectionCaster', 'castClosure'], 'Generator' => ['_ContaoManager\Symfony\Component\VarDumper\Caster\ReflectionCaster', 'castGenerator'], 'ReflectionType' => ['_ContaoManager\Symfony\Component\VarDumper\Caster\ReflectionCaster', 'castType'], 'ReflectionAttribute' => ['_ContaoManager\Symfony\Component\VarDumper\Caster\ReflectionCaster', 'castAttribute'], 'ReflectionGenerator' => ['_ContaoManager\Symfony\Component\VarDumper\Caster\ReflectionCaster', 'castReflectionGenerator'], 'ReflectionClass' => ['_ContaoManager\Symfony\Component\VarDumper\Caster\ReflectionCaster', 'castClass'], 'ReflectionClassConstant' => ['_ContaoManager\Symfony\Component\VarDumper\Caster\ReflectionCaster', 'castClassConstant'], 'ReflectionFunctionAbstract' => ['_ContaoManager\Symfony\Component\VarDumper\Caster\ReflectionCaster', 'castFunctionAbstract'], 'ReflectionMethod' => ['_ContaoManager\Symfony\Component\VarDumper\Caster\ReflectionCaster', 'castMethod'], 'ReflectionParameter' => ['_ContaoManager\Symfony\Component\VarDumper\Caster\ReflectionCaster', 'castParameter'], 'ReflectionProperty' => ['_ContaoManager\Symfony\Component\VarDumper\Caster\ReflectionCaster', 'castProperty'], 'ReflectionReference' => ['_ContaoManager\Symfony\Component\VarDumper\Caster\ReflectionCaster', 'castReference'], 'ReflectionExtension' => ['_ContaoManager\Symfony\Component\VarDumper\Caster\ReflectionCaster', 'castExtension'], 'ReflectionZendExtension' => ['_ContaoManager\Symfony\Component\VarDumper\Caster\ReflectionCaster', 'castZendExtension'], '_ContaoManager\Doctrine\Common\Persistence\ObjectManager' => ['_ContaoManager\Symfony\Component\VarDumper\Caster\StubCaster', 'cutInternals'], '_ContaoManager\Doctrine\Common\Proxy\Proxy' => ['_ContaoManager\Symfony\Component\VarDumper\Caster\DoctrineCaster', 'castCommonProxy'], '_ContaoManager\Doctrine\ORM\Proxy\Proxy' => ['_ContaoManager\Symfony\Component\VarDumper\Caster\DoctrineCaster', 'castOrmProxy'], '_ContaoManager\Doctrine\ORM\PersistentCollection' => ['_ContaoManager\Symfony\Component\VarDumper\Caster\DoctrineCaster', 'castPersistentCollection'], '_ContaoManager\Doctrine\Persistence\ObjectManager' => ['_ContaoManager\Symfony\Component\VarDumper\Caster\StubCaster', 'cutInternals'], 'DOMException' => ['_ContaoManager\Symfony\Component\VarDumper\Caster\DOMCaster', 'castException'], 'DOMStringList' => ['_ContaoManager\Symfony\Component\VarDumper\Caster\DOMCaster', 'castLength'], 'DOMNameList' => ['_ContaoManager\Symfony\Component\VarDumper\Caster\DOMCaster', 'castLength'], 'DOMImplementation' => ['_ContaoManager\Symfony\Component\VarDumper\Caster\DOMCaster', 'castImplementation'], 'DOMImplementationList' => ['_ContaoManager\Symfony\Component\VarDumper\Caster\DOMCaster', 'castLength'], 'DOMNode' => ['_ContaoManager\Symfony\Component\VarDumper\Caster\DOMCaster', 'castNode'], 'DOMNameSpaceNode' => ['_ContaoManager\Symfony\Component\VarDumper\Caster\DOMCaster', 'castNameSpaceNode'], 'DOMDocument' => ['_ContaoManager\Symfony\Component\VarDumper\Caster\DOMCaster', 'castDocument'], 'DOMNodeList' => ['_ContaoManager\Symfony\Component\VarDumper\Caster\DOMCaster', 'castLength'], 'DOMNamedNodeMap' => ['_ContaoManager\Symfony\Component\VarDumper\Caster\DOMCaster', 'castLength'], 'DOMCharacterData' => ['_ContaoManager\Symfony\Component\VarDumper\Caster\DOMCaster', 'castCharacterData'], 'DOMAttr' => ['_ContaoManager\Symfony\Component\VarDumper\Caster\DOMCaster', 'castAttr'], 'DOMElement' => ['_ContaoManager\Symfony\Component\VarDumper\Caster\DOMCaster', 'castElement'], 'DOMText' => ['_ContaoManager\Symfony\Component\VarDumper\Caster\DOMCaster', 'castText'], 'DOMDocumentType' => ['_ContaoManager\Symfony\Component\VarDumper\Caster\DOMCaster', 'castDocumentType'], 'DOMNotation' => ['_ContaoManager\Symfony\Component\VarDumper\Caster\DOMCaster', 'castNotation'], 'DOMEntity' => ['_ContaoManager\Symfony\Component\VarDumper\Caster\DOMCaster', 'castEntity'], 'DOMProcessingInstruction' => ['_ContaoManager\Symfony\Component\VarDumper\Caster\DOMCaster', 'castProcessingInstruction'], 'DOMXPath' => ['_ContaoManager\Symfony\Component\VarDumper\Caster\DOMCaster', 'castXPath'], 'XMLReader' => ['_ContaoManager\Symfony\Component\VarDumper\Caster\XmlReaderCaster', 'castXmlReader'], 'ErrorException' => ['_ContaoManager\Symfony\Component\VarDumper\Caster\ExceptionCaster', 'castErrorException'], 'Exception' => ['_ContaoManager\Symfony\Component\VarDumper\Caster\ExceptionCaster', 'castException'], 'Error' => ['_ContaoManager\Symfony\Component\VarDumper\Caster\ExceptionCaster', 'castError'], '_ContaoManager\Symfony\Bridge\Monolog\Logger' => ['_ContaoManager\Symfony\Component\VarDumper\Caster\StubCaster', 'cutInternals'], '_ContaoManager\Symfony\Component\DependencyInjection\ContainerInterface' => ['_ContaoManager\Symfony\Component\VarDumper\Caster\StubCaster', 'cutInternals'], '_ContaoManager\Symfony\Component\EventDispatcher\EventDispatcherInterface' => ['_ContaoManager\Symfony\Component\VarDumper\Caster\StubCaster', 'cutInternals'], '_ContaoManager\Symfony\Component\HttpClient\AmpHttpClient' => ['_ContaoManager\Symfony\Component\VarDumper\Caster\SymfonyCaster', 'castHttpClient'], '_ContaoManager\Symfony\Component\HttpClient\CurlHttpClient' => ['_ContaoManager\Symfony\Component\VarDumper\Caster\SymfonyCaster', 'castHttpClient'], '_ContaoManager\Symfony\Component\HttpClient\NativeHttpClient' => ['_ContaoManager\Symfony\Component\VarDumper\Caster\SymfonyCaster', 'castHttpClient'], '_ContaoManager\Symfony\Component\HttpClient\Response\AmpResponse' => ['_ContaoManager\Symfony\Component\VarDumper\Caster\SymfonyCaster', 'castHttpClientResponse'], '_ContaoManager\Symfony\Component\HttpClient\Response\CurlResponse' => ['_ContaoManager\Symfony\Component\VarDumper\Caster\SymfonyCaster', 'castHttpClientResponse'], '_ContaoManager\Symfony\Component\HttpClient\Response\NativeResponse' => ['_ContaoManager\Symfony\Component\VarDumper\Caster\SymfonyCaster', 'castHttpClientResponse'], '_ContaoManager\Symfony\Component\HttpFoundation\Request' => ['_ContaoManager\Symfony\Component\VarDumper\Caster\SymfonyCaster', 'castRequest'], '_ContaoManager\Symfony\Component\Uid\Ulid' => ['_ContaoManager\Symfony\Component\VarDumper\Caster\SymfonyCaster', 'castUlid'], '_ContaoManager\Symfony\Component\Uid\Uuid' => ['_ContaoManager\Symfony\Component\VarDumper\Caster\SymfonyCaster', 'castUuid'], '_ContaoManager\Symfony\Component\VarExporter\Internal\LazyObjectState' => ['_ContaoManager\Symfony\Component\VarDumper\Caster\SymfonyCaster', 'castLazyObjectState'], '_ContaoManager\Symfony\Component\VarDumper\Exception\ThrowingCasterException' => ['_ContaoManager\Symfony\Component\VarDumper\Caster\ExceptionCaster', 'castThrowingCasterException'], '_ContaoManager\Symfony\Component\VarDumper\Caster\TraceStub' => ['_ContaoManager\Symfony\Component\VarDumper\Caster\ExceptionCaster', 'castTraceStub'], '_ContaoManager\Symfony\Component\VarDumper\Caster\FrameStub' => ['_ContaoManager\Symfony\Component\VarDumper\Caster\ExceptionCaster', 'castFrameStub'], '_ContaoManager\Symfony\Component\VarDumper\Cloner\AbstractCloner' => ['_ContaoManager\Symfony\Component\VarDumper\Caster\StubCaster', 'cutInternals'], '_ContaoManager\Symfony\Component\ErrorHandler\Exception\FlattenException' => ['_ContaoManager\Symfony\Component\VarDumper\Caster\ExceptionCaster', 'castFlattenException'], '_ContaoManager\Symfony\Component\ErrorHandler\Exception\SilencedErrorContext' => ['_ContaoManager\Symfony\Component\VarDumper\Caster\ExceptionCaster', 'castSilencedErrorContext'], '_ContaoManager\Imagine\Image\ImageInterface' => ['_ContaoManager\Symfony\Component\VarDumper\Caster\ImagineCaster', 'castImage'], '_ContaoManager\Ramsey\Uuid\UuidInterface' => ['_ContaoManager\Symfony\Component\VarDumper\Caster\UuidCaster', 'castRamseyUuid'], '_ContaoManager\ProxyManager\Proxy\ProxyInterface' => ['_ContaoManager\Symfony\Component\VarDumper\Caster\ProxyManagerCaster', 'castProxy'], 'PHPUnit_Framework_MockObject_MockObject' => ['_ContaoManager\Symfony\Component\VarDumper\Caster\StubCaster', 'cutInternals'], '_ContaoManager\PHPUnit\Framework\MockObject\MockObject' => ['_ContaoManager\Symfony\Component\VarDumper\Caster\StubCaster', 'cutInternals'], '_ContaoManager\PHPUnit\Framework\MockObject\Stub' => ['_ContaoManager\Symfony\Component\VarDumper\Caster\StubCaster', 'cutInternals'], '_ContaoManager\Prophecy\Prophecy\ProphecySubjectInterface' => ['_ContaoManager\Symfony\Component\VarDumper\Caster\StubCaster', 'cutInternals'], '_ContaoManager\Mockery\MockInterface' => ['_ContaoManager\Symfony\Component\VarDumper\Caster\StubCaster', 'cutInternals'], 'PDO' => ['_ContaoManager\Symfony\Component\VarDumper\Caster\PdoCaster', 'castPdo'], 'PDOStatement' => ['_ContaoManager\Symfony\Component\VarDumper\Caster\PdoCaster', 'castPdoStatement'], 'AMQPConnection' => ['_ContaoManager\Symfony\Component\VarDumper\Caster\AmqpCaster', 'castConnection'], 'AMQPChannel' => ['_ContaoManager\Symfony\Component\VarDumper\Caster\AmqpCaster', 'castChannel'], 'AMQPQueue' => ['_ContaoManager\Symfony\Component\VarDumper\Caster\AmqpCaster', 'castQueue'], 'AMQPExchange' => ['_ContaoManager\Symfony\Component\VarDumper\Caster\AmqpCaster', 'castExchange'], 'AMQPEnvelope' => ['_ContaoManager\Symfony\Component\VarDumper\Caster\AmqpCaster', 'castEnvelope'], 'ArrayObject' => ['_ContaoManager\Symfony\Component\VarDumper\Caster\SplCaster', 'castArrayObject'], 'ArrayIterator' => ['_ContaoManager\Symfony\Component\VarDumper\Caster\SplCaster', 'castArrayIterator'], 'SplDoublyLinkedList' => ['_ContaoManager\Symfony\Component\VarDumper\Caster\SplCaster', 'castDoublyLinkedList'], 'SplFileInfo' => ['_ContaoManager\Symfony\Component\VarDumper\Caster\SplCaster', 'castFileInfo'], 'SplFileObject' => ['_ContaoManager\Symfony\Component\VarDumper\Caster\SplCaster', 'castFileObject'], 'SplHeap' => ['_ContaoManager\Symfony\Component\VarDumper\Caster\SplCaster', 'castHeap'], 'SplObjectStorage' => ['_ContaoManager\Symfony\Component\VarDumper\Caster\SplCaster', 'castObjectStorage'], 'SplPriorityQueue' => ['_ContaoManager\Symfony\Component\VarDumper\Caster\SplCaster', 'castHeap'], 'OuterIterator' => ['_ContaoManager\Symfony\Component\VarDumper\Caster\SplCaster', 'castOuterIterator'], 'WeakMap' => ['_ContaoManager\Symfony\Component\VarDumper\Caster\SplCaster', 'castWeakMap'], 'WeakReference' => ['_ContaoManager\Symfony\Component\VarDumper\Caster\SplCaster', 'castWeakReference'], 'Redis' => ['_ContaoManager\Symfony\Component\VarDumper\Caster\RedisCaster', 'castRedis'], '_ContaoManager\Relay\Relay' => ['_ContaoManager\Symfony\Component\VarDumper\Caster\RedisCaster', 'castRedis'], 'RedisArray' => ['_ContaoManager\Symfony\Component\VarDumper\Caster\RedisCaster', 'castRedisArray'], 'RedisCluster' => ['_ContaoManager\Symfony\Component\VarDumper\Caster\RedisCaster', 'castRedisCluster'], 'DateTimeInterface' => ['_ContaoManager\Symfony\Component\VarDumper\Caster\DateCaster', 'castDateTime'], 'DateInterval' => ['_ContaoManager\Symfony\Component\VarDumper\Caster\DateCaster', 'castInterval'], 'DateTimeZone' => ['_ContaoManager\Symfony\Component\VarDumper\Caster\DateCaster', 'castTimeZone'], 'DatePeriod' => ['_ContaoManager\Symfony\Component\VarDumper\Caster\DateCaster', 'castPeriod'], 'GMP' => ['_ContaoManager\Symfony\Component\VarDumper\Caster\GmpCaster', 'castGmp'], 'MessageFormatter' => ['_ContaoManager\Symfony\Component\VarDumper\Caster\IntlCaster', 'castMessageFormatter'], 'NumberFormatter' => ['_ContaoManager\Symfony\Component\VarDumper\Caster\IntlCaster', 'castNumberFormatter'], 'IntlTimeZone' => ['_ContaoManager\Symfony\Component\VarDumper\Caster\IntlCaster', 'castIntlTimeZone'], 'IntlCalendar' => ['_ContaoManager\Symfony\Component\VarDumper\Caster\IntlCaster', 'castIntlCalendar'], 'IntlDateFormatter' => ['_ContaoManager\Symfony\Component\VarDumper\Caster\IntlCaster', 'castIntlDateFormatter'], 'Memcached' => ['_ContaoManager\Symfony\Component\VarDumper\Caster\MemcachedCaster', 'castMemcached'], '_ContaoManager\Ds\Collection' => ['_ContaoManager\Symfony\Component\VarDumper\Caster\DsCaster', 'castCollection'], '_ContaoManager\Ds\Map' => ['_ContaoManager\Symfony\Component\VarDumper\Caster\DsCaster', 'castMap'], '_ContaoManager\Ds\Pair' => ['_ContaoManager\Symfony\Component\VarDumper\Caster\DsCaster', 'castPair'], '_ContaoManager\Symfony\Component\VarDumper\Caster\DsPairStub' => ['_ContaoManager\Symfony\Component\VarDumper\Caster\DsCaster', 'castPairStub'], 'mysqli_driver' => ['_ContaoManager\Symfony\Component\VarDumper\Caster\MysqliCaster', 'castMysqliDriver'], 'CurlHandle' => ['_ContaoManager\Symfony\Component\VarDumper\Caster\ResourceCaster', 'castCurl'], ':dba' => ['_ContaoManager\Symfony\Component\VarDumper\Caster\ResourceCaster', 'castDba'], ':dba persistent' => ['_ContaoManager\Symfony\Component\VarDumper\Caster\ResourceCaster', 'castDba'], 'GdImage' => ['_ContaoManager\Symfony\Component\VarDumper\Caster\ResourceCaster', 'castGd'], ':gd' => ['_ContaoManager\Symfony\Component\VarDumper\Caster\ResourceCaster', 'castGd'], ':pgsql large object' => ['_ContaoManager\Symfony\Component\VarDumper\Caster\PgSqlCaster', 'castLargeObject'], ':pgsql link' => ['_ContaoManager\Symfony\Component\VarDumper\Caster\PgSqlCaster', 'castLink'], ':pgsql link persistent' => ['_ContaoManager\Symfony\Component\VarDumper\Caster\PgSqlCaster', 'castLink'], ':pgsql result' => ['_ContaoManager\Symfony\Component\VarDumper\Caster\PgSqlCaster', 'castResult'], ':process' => ['_ContaoManager\Symfony\Component\VarDumper\Caster\ResourceCaster', 'castProcess'], ':stream' => ['_ContaoManager\Symfony\Component\VarDumper\Caster\ResourceCaster', 'castStream'], 'OpenSSLCertificate' => ['_ContaoManager\Symfony\Component\VarDumper\Caster\ResourceCaster', 'castOpensslX509'], ':OpenSSL X.509' => ['_ContaoManager\Symfony\Component\VarDumper\Caster\ResourceCaster', 'castOpensslX509'], ':persistent stream' => ['_ContaoManager\Symfony\Component\VarDumper\Caster\ResourceCaster', 'castStream'], ':stream-context' => ['_ContaoManager\Symfony\Component\VarDumper\Caster\ResourceCaster', 'castStreamContext'], 'XmlParser' => ['_ContaoManager\Symfony\Component\VarDumper\Caster\XmlResourceCaster', 'castXml'], ':xml' => ['_ContaoManager\Symfony\Component\VarDumper\Caster\XmlResourceCaster', 'castXml'], 'RdKafka' => ['_ContaoManager\Symfony\Component\VarDumper\Caster\RdKafkaCaster', 'castRdKafka'], '_ContaoManager\RdKafka\Conf' => ['_ContaoManager\Symfony\Component\VarDumper\Caster\RdKafkaCaster', 'castConf'], '_ContaoManager\RdKafka\KafkaConsumer' => ['_ContaoManager\Symfony\Component\VarDumper\Caster\RdKafkaCaster', 'castKafkaConsumer'], '_ContaoManager\RdKafka\Metadata\Broker' => ['_ContaoManager\Symfony\Component\VarDumper\Caster\RdKafkaCaster', 'castBrokerMetadata'], '_ContaoManager\RdKafka\Metadata\Collection' => ['_ContaoManager\Symfony\Component\VarDumper\Caster\RdKafkaCaster', 'castCollectionMetadata'], '_ContaoManager\RdKafka\Metadata\Partition' => ['_ContaoManager\Symfony\Component\VarDumper\Caster\RdKafkaCaster', 'castPartitionMetadata'], '_ContaoManager\RdKafka\Metadata\Topic' => ['_ContaoManager\Symfony\Component\VarDumper\Caster\RdKafkaCaster', 'castTopicMetadata'], '_ContaoManager\RdKafka\Message' => ['_ContaoManager\Symfony\Component\VarDumper\Caster\RdKafkaCaster', 'castMessage'], '_ContaoManager\RdKafka\Topic' => ['_ContaoManager\Symfony\Component\VarDumper\Caster\RdKafkaCaster', 'castTopic'], '_ContaoManager\RdKafka\TopicPartition' => ['_ContaoManager\Symfony\Component\VarDumper\Caster\RdKafkaCaster', 'castTopicPartition'], '_ContaoManager\RdKafka\TopicConf' => ['_ContaoManager\Symfony\Component\VarDumper\Caster\RdKafkaCaster', 'castTopicConf'], '_ContaoManager\FFI\CData' => ['_ContaoManager\Symfony\Component\VarDumper\Caster\FFICaster', 'castCTypeOrCData'], '_ContaoManager\FFI\CType' => ['_ContaoManager\Symfony\Component\VarDumper\Caster\FFICaster', 'castCTypeOrCData']];
    protected $maxItems = 2500;
    protected $maxString = -1;
    protected $minDepth = 1;
    /**
     * @var array<string, list<callable>>
     */
    private array $casters = [];
    /**
     * @var callable|null
     */
    private $prevErrorHandler;
    private array $classInfo = [];
    private int $filter = 0;
    /**
     * @param callable[]|null $casters A map of casters
     *
     * @see addCasters
     */
    public function __construct(?array $casters = null)
    {
        $this->addCasters($casters ?? static::$defaultCasters);
    }
    /**
     * Adds casters for resources and objects.
     *
     * Maps resources or objects types to a callback.
     * Types are in the key, with a callable caster for value.
     * Resource types are to be prefixed with a `:`,
     * see e.g. static::$defaultCasters.
     *
     * @param callable[] $casters A map of casters
     *
     * @return void
     */
    public function addCasters(array $casters)
    {
        foreach ($casters as $type => $callback) {
            $this->casters[$type][] = $callback;
        }
    }
    /**
     * Sets the maximum number of items to clone past the minimum depth in nested structures.
     *
     * @return void
     */
    public function setMaxItems(int $maxItems)
    {
        $this->maxItems = $maxItems;
    }
    /**
     * Sets the maximum cloned length for strings.
     *
     * @return void
     */
    public function setMaxString(int $maxString)
    {
        $this->maxString = $maxString;
    }
    /**
     * Sets the minimum tree depth where we are guaranteed to clone all the items.  After this
     * depth is reached, only setMaxItems items will be cloned.
     *
     * @return void
     */
    public function setMinDepth(int $minDepth)
    {
        $this->minDepth = $minDepth;
    }
    /**
     * Clones a PHP variable.
     *
     * @param int $filter A bit field of Caster::EXCLUDE_* constants
     */
    public function cloneVar(mixed $var, int $filter = 0): Data
    {
        $this->prevErrorHandler = set_error_handler(function ($type, $msg, $file, $line, $context = []) {
            if (\E_RECOVERABLE_ERROR === $type || \E_USER_ERROR === $type) {
                // Cloner never dies
                throw new \ErrorException($msg, 0, $type, $file, $line);
            }
            if ($this->prevErrorHandler) {
                return ($this->prevErrorHandler)($type, $msg, $file, $line, $context);
            }
            return \false;
        });
        $this->filter = $filter;
        if ($gc = gc_enabled()) {
            gc_disable();
        }
        try {
            return new Data($this->doClone($var));
        } finally {
            if ($gc) {
                gc_enable();
            }
            restore_error_handler();
            $this->prevErrorHandler = null;
        }
    }
    /**
     * Effectively clones the PHP variable.
     */
    abstract protected function doClone(mixed $var): array;
    /**
     * Casts an object to an array representation.
     *
     * @param bool $isNested True if the object is nested in the dumped structure
     */
    protected function castObject(Stub $stub, bool $isNested): array
    {
        $obj = $stub->value;
        $class = $stub->class;
        if (str_contains($class, "@anonymous\x00")) {
            $stub->class = get_debug_type($obj);
        }
        if (isset($this->classInfo[$class])) {
            [$i, $parents, $hasDebugInfo, $fileInfo] = $this->classInfo[$class];
        } else {
            $i = 2;
            $parents = [$class];
            $hasDebugInfo = method_exists($class, '__debugInfo');
            foreach (class_parents($class) as $p) {
                $parents[] = $p;
                ++$i;
            }
            foreach (class_implements($class) as $p) {
                $parents[] = $p;
                ++$i;
            }
            $parents[] = '*';
            $r = new \ReflectionClass($class);
            $fileInfo = $r->isInternal() || $r->isSubclassOf(Stub::class) ? [] : ['file' => $r->getFileName(), 'line' => $r->getStartLine()];
            $this->classInfo[$class] = [$i, $parents, $hasDebugInfo, $fileInfo];
        }
        $stub->attr += $fileInfo;
        $a = Caster::castObject($obj, $class, $hasDebugInfo, $stub->class);
        try {
            while ($i--) {
                if (!empty($this->casters[$p = $parents[$i]])) {
                    foreach ($this->casters[$p] as $callback) {
                        $a = $callback($obj, $a, $stub, $isNested, $this->filter);
                    }
                }
            }
        } catch (\Exception $e) {
            $a = [(Stub::TYPE_OBJECT === $stub->type ? Caster::PREFIX_VIRTUAL : '') . '⚠' => new ThrowingCasterException($e)] + $a;
        }
        return $a;
    }
    /**
     * Casts a resource to an array representation.
     *
     * @param bool $isNested True if the object is nested in the dumped structure
     */
    protected function castResource(Stub $stub, bool $isNested): array
    {
        $a = [];
        $res = $stub->value;
        $type = $stub->class;
        try {
            if (!empty($this->casters[':' . $type])) {
                foreach ($this->casters[':' . $type] as $callback) {
                    $a = $callback($res, $a, $stub, $isNested, $this->filter);
                }
            }
        } catch (\Exception $e) {
            $a = [(Stub::TYPE_OBJECT === $stub->type ? Caster::PREFIX_VIRTUAL : '') . '⚠' => new ThrowingCasterException($e)] + $a;
        }
        return $a;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\VarDumper\Cloner;

use _ContaoManager\Symfony\Component\VarDumper\Caster\Caster;
use _ContaoManager\Symfony\Component\VarDumper\Dumper\ContextProvider\SourceContextProvider;
/**
 * @author Nicolas Grekas <p@tchwork.com>
 */
class Data implements \ArrayAccess, \Countable, \IteratorAggregate, \Stringable
{
    private array $data;
    private int $position = 0;
    private int|string $key = 0;
    private int $maxDepth = 20;
    private int $maxItemsPerDepth = -1;
    private int $useRefHandles = -1;
    private array $context = [];
    /**
     * @param array $data An array as returned by ClonerInterface::cloneVar()
     */
    public function __construct(array $data)
    {
        $this->data = $data;
    }
    public function getType(): ?string
    {
        $item = $this->data[$this->position][$this->key];
        if ($item instanceof Stub && Stub::TYPE_REF === $item->type && !$item->position) {
            $item = $item->value;
        }
        if (!$item instanceof Stub) {
            return \gettype($item);
        }
        if (Stub::TYPE_STRING === $item->type) {
            return 'string';
        }
        if (Stub::TYPE_ARRAY === $item->type) {
            return 'array';
        }
        if (Stub::TYPE_OBJECT === $item->type) {
            return $item->class;
        }
        if (Stub::TYPE_RESOURCE === $item->type) {
            return $item->class . ' resource';
        }
        return null;
    }
    /**
     * Returns a native representation of the original value.
     *
     * @param array|bool $recursive Whether values should be resolved recursively or not
     *
     * @return string|int|float|bool|array|Data[]|null
     */
    public function getValue(array|bool $recursive = \false): string|int|float|bool|array|null
    {
        $item = $this->data[$this->position][$this->key];
        if ($item instanceof Stub && Stub::TYPE_REF === $item->type && !$item->position) {
            $item = $item->value;
        }
        if (!($item = $this->getStub($item)) instanceof Stub) {
            return $item;
        }
        if (Stub::TYPE_STRING === $item->type) {
            return $item->value;
        }
        $children = $item->position ? $this->data[$item->position] : [];
        foreach ($children as $k => $v) {
            if ($recursive && !($v = $this->getStub($v)) instanceof Stub) {
                continue;
            }
            $children[$k] = clone $this;
            $children[$k]->key = $k;
            $children[$k]->position = $item->position;
            if ($recursive) {
                if (Stub::TYPE_REF === $v->type && ($v = $this->getStub($v->value)) instanceof Stub) {
                    $recursive = (array) $recursive;
                    if (isset($recursive[$v->position])) {
                        continue;
                    }
                    $recursive[$v->position] = \true;
                }
                $children[$k] = $children[$k]->getValue($recursive);
            }
        }
        return $children;
    }
    public function count(): int
    {
        return \count($this->getValue());
    }
    public function getIterator(): \Traversable
    {
        if (!\is_array($value = $this->getValue())) {
            throw new \LogicException(\sprintf('"%s" object holds non-iterable type "%s".', self::class, get_debug_type($value)));
        }
        yield from $value;
    }
    /**
     * @return mixed
     */
    public function __get(string $key)
    {
        if (null !== $data = $this->seek($key)) {
            $item = $this->getStub($data->data[$data->position][$data->key]);
            return $item instanceof Stub || [] === $item ? $data : $item;
        }
        return null;
    }
    public function __isset(string $key): bool
    {
        return null !== $this->seek($key);
    }
    public function offsetExists(mixed $key): bool
    {
        return $this->__isset($key);
    }
    public function offsetGet(mixed $key): mixed
    {
        return $this->__get($key);
    }
    public function offsetSet(mixed $key, mixed $value): void
    {
        throw new \BadMethodCallException(self::class . ' objects are immutable.');
    }
    public function offsetUnset(mixed $key): void
    {
        throw new \BadMethodCallException(self::class . ' objects are immutable.');
    }
    public function __toString(): string
    {
        $value = $this->getValue();
        if (!\is_array($value)) {
            return (string) $value;
        }
        return \sprintf('%s (count=%d)', $this->getType(), \count($value));
    }
    /**
     * Returns a depth limited clone of $this.
     */
    public function withMaxDepth(int $maxDepth): static
    {
        $data = clone $this;
        $data->maxDepth = $maxDepth;
        return $data;
    }
    /**
     * Limits the number of elements per depth level.
     */
    public function withMaxItemsPerDepth(int $maxItemsPerDepth): static
    {
        $data = clone $this;
        $data->maxItemsPerDepth = $maxItemsPerDepth;
        return $data;
    }
    /**
     * Enables/disables objects' identifiers tracking.
     *
     * @param bool $useRefHandles False to hide global ref. handles
     */
    public function withRefHandles(bool $useRefHandles): static
    {
        $data = clone $this;
        $data->useRefHandles = $useRefHandles ? -1 : 0;
        return $data;
    }
    public function withContext(array $context): static
    {
        $data = clone $this;
        $data->context = $context;
        return $data;
    }
    public function getContext(): array
    {
        return $this->context;
    }
    /**
     * Seeks to a specific key in nested data structures.
     */
    public function seek(string|int $key): ?static
    {
        $item = $this->data[$this->position][$this->key];
        if ($item instanceof Stub && Stub::TYPE_REF === $item->type && !$item->position) {
            $item = $item->value;
        }
        if (!($item = $this->getStub($item)) instanceof Stub || !$item->position) {
            return null;
        }
        $keys = [$key];
        switch ($item->type) {
            case Stub::TYPE_OBJECT:
                $keys[] = Caster::PREFIX_DYNAMIC . $key;
                $keys[] = Caster::PREFIX_PROTECTED . $key;
                $keys[] = Caster::PREFIX_VIRTUAL . $key;
                $keys[] = "\x00{$item->class}\x00{$key}";
            // no break
            case Stub::TYPE_ARRAY:
            case Stub::TYPE_RESOURCE:
                break;
            default:
                return null;
        }
        $data = null;
        $children = $this->data[$item->position];
        foreach ($keys as $key) {
            if (isset($children[$key]) || \array_key_exists($key, $children)) {
                $data = clone $this;
                $data->key = $key;
                $data->position = $item->position;
                break;
            }
        }
        return $data;
    }
    /**
     * Dumps data with a DumperInterface dumper.
     *
     * @return void
     */
    public function dump(DumperInterface $dumper)
    {
        $refs = [0];
        $cursor = new Cursor();
        $cursor->hashType = -1;
        $cursor->attr = $this->context[SourceContextProvider::class] ?? [];
        $label = $this->context['label'] ?? '';
        if ($cursor->attr || '' !== $label) {
            $dumper->dumpScalar($cursor, 'label', $label);
        }
        $cursor->hashType = 0;
        $this->dumpItem($dumper, $cursor, $refs, $this->data[$this->position][$this->key]);
    }
    /**
     * Depth-first dumping of items.
     *
     * @param mixed $item A Stub object or the original value being dumped
     */
    private function dumpItem(DumperInterface $dumper, Cursor $cursor, array &$refs, mixed $item): void
    {
        $cursor->refIndex = 0;
        $cursor->softRefTo = $cursor->softRefHandle = $cursor->softRefCount = 0;
        $cursor->hardRefTo = $cursor->hardRefHandle = $cursor->hardRefCount = 0;
        $firstSeen = \true;
        if (!$item instanceof Stub) {
            $cursor->attr = [];
            $type = \gettype($item);
            if ('array' === $type && $item) {
                $item = $this->getStub($item);
            }
        } elseif (Stub::TYPE_REF === $item->type) {
            if ($item->handle) {
                if (!isset($refs[$r = $item->handle - (\PHP_INT_MAX >> 1)])) {
                    $cursor->refIndex = $refs[$r] = $cursor->refIndex ?: ++$refs[0];
                } else {
                    $firstSeen = \false;
                }
                $cursor->hardRefTo = $refs[$r];
                $cursor->hardRefHandle = $this->useRefHandles & $item->handle;
                $cursor->hardRefCount = 0 < $item->handle ? $item->refCount : 0;
            }
            $cursor->attr = $item->attr;
            $type = $item->class ?: \gettype($item->value);
            $item = $this->getStub($item->value);
        }
        if ($item instanceof Stub) {
            if ($item->refCount) {
                if (!isset($refs[$r = $item->handle])) {
                    $cursor->refIndex = $refs[$r] = $cursor->refIndex ?: ++$refs[0];
                } else {
                    $firstSeen = \false;
                }
                $cursor->softRefTo = $refs[$r];
            }
            $cursor->softRefHandle = $this->useRefHandles & $item->handle;
            $cursor->softRefCount = $item->refCount;
            $cursor->attr = $item->attr;
            $cut = $item->cut;
            if ($item->position && $firstSeen) {
                $children = $this->data[$item->position];
                if ($cursor->stop) {
                    if ($cut >= 0) {
                        $cut += \count($children);
                    }
                    $children = [];
                }
            } else {
                $children = [];
            }
            switch ($item->type) {
                case Stub::TYPE_STRING:
                    $dumper->dumpString($cursor, $item->value, Stub::STRING_BINARY === $item->class, $cut);
                    break;
                case Stub::TYPE_ARRAY:
                    $item = clone $item;
                    $item->type = $item->class;
                    $item->class = $item->value;
                // no break
                case Stub::TYPE_OBJECT:
                case Stub::TYPE_RESOURCE:
                    $withChildren = $children && $cursor->depth !== $this->maxDepth && $this->maxItemsPerDepth;
                    $dumper->enterHash($cursor, $item->type, $item->class, $withChildren);
                    if ($withChildren) {
                        if ($cursor->skipChildren) {
                            $withChildren = \false;
                            $cut = -1;
                        } else {
                            $cut = $this->dumpChildren($dumper, $cursor, $refs, $children, $cut, $item->type, null !== $item->class);
                        }
                    } elseif ($children && 0 <= $cut) {
                        $cut += \count($children);
                    }
                    $cursor->skipChildren = \false;
                    $dumper->leaveHash($cursor, $item->type, $item->class, $withChildren, $cut);
                    break;
                case Stub::TYPE_SCALAR:
                    $dumper->dumpScalar($cursor, 'default', $item->attr['value']);
                    break;
                default:
                    throw new \RuntimeException(\sprintf('Unexpected Stub type: "%s".', $item->type));
            }
        } elseif ('array' === $type) {
            $dumper->enterHash($cursor, Cursor::HASH_INDEXED, 0, \false);
            $dumper->leaveHash($cursor, Cursor::HASH_INDEXED, 0, \false, 0);
        } elseif ('string' === $type) {
            $dumper->dumpString($cursor, $item, \false, 0);
        } else {
            $dumper->dumpScalar($cursor, $type, $item);
        }
    }
    /**
     * Dumps children of hash structures.
     *
     * @return int The final number of removed items
     */
    private function dumpChildren(DumperInterface $dumper, Cursor $parentCursor, array &$refs, array $children, int $hashCut, int $hashType, bool $dumpKeys): int
    {
        $cursor = clone $parentCursor;
        ++$cursor->depth;
        $cursor->hashType = $hashType;
        $cursor->hashIndex = 0;
        $cursor->hashLength = \count($children);
        $cursor->hashCut = $hashCut;
        foreach ($children as $key => $child) {
            $cursor->hashKeyIsBinary = isset($key[0]) && !preg_match('//u', $key);
            $cursor->hashKey = $dumpKeys ? $key : null;
            $this->dumpItem($dumper, $cursor, $refs, $child);
            if (++$cursor->hashIndex === $this->maxItemsPerDepth || $cursor->stop) {
                $parentCursor->stop = \true;
                return $hashCut >= 0 ? $hashCut + $cursor->hashLength - $cursor->hashIndex : $hashCut;
            }
        }
        return $hashCut;
    }
    private function getStub(mixed $item): mixed
    {
        if (!$item || !\is_array($item)) {
            return $item;
        }
        $stub = new Stub();
        $stub->type = Stub::TYPE_ARRAY;
        foreach ($item as $stub->class => $stub->position) {
        }
        if (isset($item[0])) {
            $stub->cut = $item[0];
        }
        $stub->value = $stub->cut + ($stub->position ? \count($this->data[$stub->position]) : 0);
        return $stub;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\VarDumper\Cloner;

/**
 * Represents the main properties of a PHP variable.
 *
 * @author Nicolas Grekas <p@tchwork.com>
 */
class Stub
{
    public const TYPE_REF = 1;
    public const TYPE_STRING = 2;
    public const TYPE_ARRAY = 3;
    public const TYPE_OBJECT = 4;
    public const TYPE_RESOURCE = 5;
    public const TYPE_SCALAR = 6;
    public const STRING_BINARY = 1;
    public const STRING_UTF8 = 2;
    public const ARRAY_ASSOC = 1;
    public const ARRAY_INDEXED = 2;
    public $type = self::TYPE_REF;
    public $class = '';
    public $value;
    public $cut = 0;
    public $handle = 0;
    public $refCount = 0;
    public $position = 0;
    public $attr = [];
    /**
     * @internal
     */
    protected static array $propertyDefaults = [];
    public function __serialize(): array
    {
        static $noDefault = new \stdClass();
        if (self::class === static::class) {
            $data = [];
            foreach ($this as $k => $v) {
                $default = self::$propertyDefaults[$this::class][$k] ??= ($p = new \ReflectionProperty($this, $k))->hasDefaultValue() ? $p->getDefaultValue() : ($p->hasType() ? $noDefault : null);
                if ($noDefault === $default || $default !== $v) {
                    $data[$k] = $v;
                }
            }
            return $data;
        }
        return \Closure::bind(function () use ($noDefault) {
            $data = [];
            foreach ($this as $k => $v) {
                $default = self::$propertyDefaults[$this::class][$k] ??= ($p = new \ReflectionProperty($this, $k))->hasDefaultValue() ? $p->getDefaultValue() : ($p->hasType() ? $noDefault : null);
                if ($noDefault === $default || $default !== $v) {
                    $data[$k] = $v;
                }
            }
            return $data;
        }, $this, $this::class)();
    }
}
Copyright (c) 2014-present Fabien Potencier

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is furnished
to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\VarDumper\Test;

use _ContaoManager\Symfony\Component\VarDumper\Cloner\VarCloner;
use _ContaoManager\Symfony\Component\VarDumper\Dumper\CliDumper;
/**
 * @author Nicolas Grekas <p@tchwork.com>
 */
trait VarDumperTestTrait
{
    /**
     * @internal
     */
    private array $varDumperConfig = ['casters' => [], 'flags' => null];
    protected function setUpVarDumper(array $casters, ?int $flags = null): void
    {
        $this->varDumperConfig['casters'] = $casters;
        $this->varDumperConfig['flags'] = $flags;
    }
    /**
     * @after
     */
    protected function tearDownVarDumper(): void
    {
        $this->varDumperConfig['casters'] = [];
        $this->varDumperConfig['flags'] = null;
    }
    public function assertDumpEquals(mixed $expected, mixed $data, int $filter = 0, string $message = '')
    {
        $this->assertSame($this->prepareExpectation($expected, $filter), $this->getDump($data, null, $filter), $message);
    }
    public function assertDumpMatchesFormat(mixed $expected, mixed $data, int $filter = 0, string $message = '')
    {
        $this->assertStringMatchesFormat($this->prepareExpectation($expected, $filter), $this->getDump($data, null, $filter), $message);
    }
    protected function getDump(mixed $data, string|int|null $key = null, int $filter = 0): ?string
    {
        if (null === $flags = $this->varDumperConfig['flags']) {
            $flags = getenv('DUMP_LIGHT_ARRAY') ? CliDumper::DUMP_LIGHT_ARRAY : 0;
            $flags |= getenv('DUMP_STRING_LENGTH') ? CliDumper::DUMP_STRING_LENGTH : 0;
            $flags |= getenv('DUMP_COMMA_SEPARATOR') ? CliDumper::DUMP_COMMA_SEPARATOR : 0;
        }
        $cloner = new VarCloner();
        $cloner->addCasters($this->varDumperConfig['casters']);
        $cloner->setMaxItems(-1);
        $dumper = new CliDumper(null, null, $flags);
        $dumper->setColors(\false);
        $data = $cloner->cloneVar($data, $filter)->withRefHandles(\false);
        if (null !== $key && null === $data = $data->seek($key)) {
            return null;
        }
        return rtrim($dumper->dump($data, \true));
    }
    private function prepareExpectation(mixed $expected, int $filter): string
    {
        if (!\is_string($expected)) {
            $expected = $this->getDump($expected, null, $filter);
        }
        return rtrim($expected);
    }
}
CHANGELOG
=========

6.4
---

 * Dump uninitialized properties

6.3
---

 * Add caster for `WeakMap`
 * Add support of named arguments to `dd()` and `dump()` to display the argument name
 * Add support for `Relay\Relay`
 * Add display of invisible characters

6.2
---

 * Add support for `FFI\CData` and `FFI\CType`
 * Deprecate calling `VarDumper::setHandler()` without arguments

5.4
---

 * Add ability to style integer and double values independently
 * Add casters for Symfony's UUIDs and ULIDs
 * Add support for `Fiber`

5.2.0
-----

 * added support for PHPUnit `--colors` option
 * added `VAR_DUMPER_FORMAT=server` env var value support
 * prevent replacing the handler when the `VAR_DUMPER_FORMAT` env var is set

5.1.0
-----

 * added `RdKafka` support

4.4.0
-----

 * added `VarDumperTestTrait::setUpVarDumper()` and `VarDumperTestTrait::tearDownVarDumper()`
   to configure casters & flags to use in tests
 * added `ImagineCaster` and infrastructure to dump images
 * added the stamps of a message after it is dispatched in `TraceableMessageBus` and `MessengerDataCollector` collected data
 * added `UuidCaster`
 * made all casters final
 * added support for the `NO_COLOR` env var (https://no-color.org/)

4.3.0
-----

 * added `DsCaster` to support dumping the contents of data structures from the Ds extension

4.2.0
-----

 * support selecting the format to use by setting the environment variable `VAR_DUMPER_FORMAT` to `html` or `cli`

4.1.0
-----

 * added a `ServerDumper` to send serialized Data clones to a server
 * added a `ServerDumpCommand` and `DumpServer` to run a server collecting
   and displaying dumps on a single place with multiple formats support
 * added `CliDescriptor` and `HtmlDescriptor` descriptors for `server:dump` CLI and HTML formats support

4.0.0
-----

 * support for passing `\ReflectionClass` instances to the `Caster::castObject()`
   method has been dropped, pass class names as strings instead
 * the `Data::getRawData()` method has been removed
 * the `VarDumperTestTrait::assertDumpEquals()` method expects a 3rd `$filter = 0`
   argument and moves `$message = ''` argument at 4th position.
 * the `VarDumperTestTrait::assertDumpMatchesFormat()` method expects a 3rd `$filter = 0`
   argument and moves `$message = ''` argument at 4th position.

3.4.0
-----

 * added `AbstractCloner::setMinDepth()` function to ensure minimum tree depth
 * deprecated `MongoCaster`

2.7.0
-----

 * deprecated `Cloner\Data::getLimitedClone()`. Use `withMaxDepth`, `withMaxItemsPerDepth` or `withRefHandles` instead.
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\VarDumper\Caster;

use _ContaoManager\Symfony\Component\VarDumper\Cloner\Stub;
/**
 * Casts GMP objects to array representation.
 *
 * @author Hamza Amrouche <hamza.simperfit@gmail.com>
 * @author Nicolas Grekas <p@tchwork.com>
 *
 * @final
 */
class GmpCaster
{
    public static function castGmp(\GMP $gmp, array $a, Stub $stub, bool $isNested, int $filter): array
    {
        $a[Caster::PREFIX_VIRTUAL . 'value'] = new ConstStub(gmp_strval($gmp), gmp_strval($gmp));
        return $a;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\VarDumper\Caster;

use _ContaoManager\Symfony\Component\VarDumper\Cloner\Stub;
/**
 * Casts Reflector related classes to array representation.
 *
 * @author Nicolas Grekas <p@tchwork.com>
 *
 * @final
 */
class ReflectionCaster
{
    public const UNSET_CLOSURE_FILE_INFO = ['Closure' => __CLASS__ . '::unsetClosureFileInfo'];
    private const EXTRA_MAP = ['docComment' => 'getDocComment', 'extension' => 'getExtensionName', 'isDisabled' => 'isDisabled', 'isDeprecated' => 'isDeprecated', 'isInternal' => 'isInternal', 'isUserDefined' => 'isUserDefined', 'isGenerator' => 'isGenerator', 'isVariadic' => 'isVariadic'];
    /**
     * @return array
     */
    public static function castClosure(\Closure $c, array $a, Stub $stub, bool $isNested, int $filter = 0)
    {
        $prefix = Caster::PREFIX_VIRTUAL;
        $c = new \ReflectionFunction($c);
        $a = static::castFunctionAbstract($c, $a, $stub, $isNested, $filter);
        if (!str_contains($c->name, '{closure')) {
            $stub->class = isset($a[$prefix . 'class']) ? $a[$prefix . 'class']->value . '::' . $c->name : $c->name;
            unset($a[$prefix . 'class']);
        }
        unset($a[$prefix . 'extra']);
        $stub->class .= self::getSignature($a);
        if ($f = $c->getFileName()) {
            $stub->attr['file'] = $f;
            $stub->attr['line'] = $c->getStartLine();
        }
        unset($a[$prefix . 'parameters']);
        if ($filter & Caster::EXCLUDE_VERBOSE) {
            $stub->cut += ($c->getFileName() ? 2 : 0) + \count($a);
            return [];
        }
        if ($f) {
            $a[$prefix . 'file'] = new LinkStub($f, $c->getStartLine());
            $a[$prefix . 'line'] = $c->getStartLine() . ' to ' . $c->getEndLine();
        }
        return $a;
    }
    /**
     * @return array
     */
    public static function unsetClosureFileInfo(\Closure $c, array $a)
    {
        unset($a[Caster::PREFIX_VIRTUAL . 'file'], $a[Caster::PREFIX_VIRTUAL . 'line']);
        return $a;
    }
    public static function castGenerator(\Generator $c, array $a, Stub $stub, bool $isNested): array
    {
        // Cannot create ReflectionGenerator based on a terminated Generator
        try {
            $reflectionGenerator = new \ReflectionGenerator($c);
            return self::castReflectionGenerator($reflectionGenerator, $a, $stub, $isNested);
        } catch (\Exception) {
            $a[Caster::PREFIX_VIRTUAL . 'closed'] = \true;
            return $a;
        }
    }
    /**
     * @return array
     */
    public static function castType(\ReflectionType $c, array $a, Stub $stub, bool $isNested)
    {
        $prefix = Caster::PREFIX_VIRTUAL;
        if ($c instanceof \ReflectionNamedType) {
            $a += [$prefix . 'name' => $c instanceof \ReflectionNamedType ? $c->getName() : (string) $c, $prefix . 'allowsNull' => $c->allowsNull(), $prefix . 'isBuiltin' => $c->isBuiltin()];
        } elseif ($c instanceof \ReflectionUnionType || $c instanceof \ReflectionIntersectionType) {
            $a[$prefix . 'allowsNull'] = $c->allowsNull();
            self::addMap($a, $c, ['types' => 'getTypes']);
        } else {
            $a[$prefix . 'allowsNull'] = $c->allowsNull();
        }
        return $a;
    }
    /**
     * @return array
     */
    public static function castAttribute(\ReflectionAttribute $c, array $a, Stub $stub, bool $isNested)
    {
        $map = ['name' => 'getName', 'arguments' => 'getArguments'];
        if (\PHP_VERSION_ID >= 80400) {
            unset($map['name']);
        }
        self::addMap($a, $c, $map);
        return $a;
    }
    /**
     * @return array
     */
    public static function castReflectionGenerator(\ReflectionGenerator $c, array $a, Stub $stub, bool $isNested)
    {
        $prefix = Caster::PREFIX_VIRTUAL;
        if ($c->getThis()) {
            $a[$prefix . 'this'] = new CutStub($c->getThis());
        }
        $function = $c->getFunction();
        $frame = ['class' => $function->class ?? null, 'type' => isset($function->class) ? $function->isStatic() ? '::' : '->' : null, 'function' => $function->name, 'file' => $c->getExecutingFile(), 'line' => $c->getExecutingLine()];
        if ($trace = $c->getTrace(\DEBUG_BACKTRACE_IGNORE_ARGS)) {
            $function = new \ReflectionGenerator($c->getExecutingGenerator());
            array_unshift($trace, ['function' => 'yield', 'file' => $function->getExecutingFile(), 'line' => $function->getExecutingLine()]);
            $trace[] = $frame;
            $a[$prefix . 'trace'] = new TraceStub($trace, \false, 0, -1, -1);
        } else {
            $function = new FrameStub($frame, \false, \true);
            $function = ExceptionCaster::castFrameStub($function, [], $function, \true);
            $a[$prefix . 'executing'] = $function[$prefix . 'src'];
        }
        $a[Caster::PREFIX_VIRTUAL . 'closed'] = \false;
        return $a;
    }
    /**
     * @return array
     */
    public static function castClass(\ReflectionClass $c, array $a, Stub $stub, bool $isNested, int $filter = 0)
    {
        $prefix = Caster::PREFIX_VIRTUAL;
        if ($n = \Reflection::getModifierNames($c->getModifiers())) {
            $a[$prefix . 'modifiers'] = implode(' ', $n);
        }
        self::addMap($a, $c, ['extends' => 'getParentClass', 'implements' => 'getInterfaceNames', 'constants' => 'getReflectionConstants']);
        foreach ($c->getProperties() as $n) {
            $a[$prefix . 'properties'][$n->name] = $n;
        }
        foreach ($c->getMethods() as $n) {
            $a[$prefix . 'methods'][$n->name] = $n;
        }
        self::addAttributes($a, $c, $prefix);
        if (!($filter & Caster::EXCLUDE_VERBOSE) && !$isNested) {
            self::addExtra($a, $c);
        }
        return $a;
    }
    /**
     * @return array
     */
    public static function castFunctionAbstract(\ReflectionFunctionAbstract $c, array $a, Stub $stub, bool $isNested, int $filter = 0)
    {
        $prefix = Caster::PREFIX_VIRTUAL;
        self::addMap($a, $c, ['returnsReference' => 'returnsReference', 'returnType' => 'getReturnType', 'class' => \PHP_VERSION_ID >= 80111 ? 'getClosureCalledClass' : 'getClosureScopeClass', 'this' => 'getClosureThis']);
        if (isset($a[$prefix . 'returnType'])) {
            $v = $a[$prefix . 'returnType'];
            $v = $v instanceof \ReflectionNamedType ? $v->getName() : (string) $v;
            $a[$prefix . 'returnType'] = new ClassStub($a[$prefix . 'returnType'] instanceof \ReflectionNamedType && $a[$prefix . 'returnType']->allowsNull() && !\in_array($v, ['mixed', 'null'], \true) ? '?' . $v : $v, [class_exists($v, \false) || interface_exists($v, \false) || trait_exists($v, \false) ? $v : '', '']);
        }
        if (isset($a[$prefix . 'class'])) {
            $a[$prefix . 'class'] = new ClassStub($a[$prefix . 'class']);
        }
        if (isset($a[$prefix . 'this'])) {
            $a[$prefix . 'this'] = new CutStub($a[$prefix . 'this']);
        }
        foreach ($c->getParameters() as $v) {
            $k = '$' . $v->name;
            if ($v->isVariadic()) {
                $k = '...' . $k;
            }
            if ($v->isPassedByReference()) {
                $k = '&' . $k;
            }
            $a[$prefix . 'parameters'][$k] = $v;
        }
        if (isset($a[$prefix . 'parameters'])) {
            $a[$prefix . 'parameters'] = new EnumStub($a[$prefix . 'parameters']);
        }
        self::addAttributes($a, $c, $prefix);
        if (!($filter & Caster::EXCLUDE_VERBOSE) && $v = $c->getStaticVariables()) {
            foreach ($v as $k => &$v) {
                if (\is_object($v)) {
                    $a[$prefix . 'use']['$' . $k] = new CutStub($v);
                } else {
                    $a[$prefix . 'use']['$' . $k] =& $v;
                }
            }
            unset($v);
            $a[$prefix . 'use'] = new EnumStub($a[$prefix . 'use']);
        }
        if (!($filter & Caster::EXCLUDE_VERBOSE) && !$isNested) {
            self::addExtra($a, $c);
        }
        return $a;
    }
    /**
     * @return array
     */
    public static function castClassConstant(\ReflectionClassConstant $c, array $a, Stub $stub, bool $isNested)
    {
        $a[Caster::PREFIX_VIRTUAL . 'modifiers'] = implode(' ', \Reflection::getModifierNames($c->getModifiers()));
        $a[Caster::PREFIX_VIRTUAL . 'value'] = $c->getValue();
        self::addAttributes($a, $c);
        return $a;
    }
    /**
     * @return array
     */
    public static function castMethod(\ReflectionMethod $c, array $a, Stub $stub, bool $isNested)
    {
        $a[Caster::PREFIX_VIRTUAL . 'modifiers'] = implode(' ', \Reflection::getModifierNames($c->getModifiers()));
        return $a;
    }
    /**
     * @return array
     */
    public static function castParameter(\ReflectionParameter $c, array $a, Stub $stub, bool $isNested)
    {
        $prefix = Caster::PREFIX_VIRTUAL;
        self::addMap($a, $c, ['position' => 'getPosition', 'isVariadic' => 'isVariadic', 'byReference' => 'isPassedByReference', 'allowsNull' => 'allowsNull']);
        self::addAttributes($a, $c, $prefix);
        if ($v = $c->getType()) {
            $a[$prefix . 'typeHint'] = $v instanceof \ReflectionNamedType ? $v->getName() : (string) $v;
        }
        if (isset($a[$prefix . 'typeHint'])) {
            $v = $a[$prefix . 'typeHint'];
            $a[$prefix . 'typeHint'] = new ClassStub($v, [class_exists($v, \false) || interface_exists($v, \false) || trait_exists($v, \false) ? $v : '', '']);
        } else {
            unset($a[$prefix . 'allowsNull']);
        }
        if ($c->isOptional()) {
            try {
                $a[$prefix . 'default'] = $v = $c->getDefaultValue();
                if ($c->isDefaultValueConstant() && !\is_object($v)) {
                    $a[$prefix . 'default'] = new ConstStub($c->getDefaultValueConstantName(), $v);
                }
                if (null === $v) {
                    unset($a[$prefix . 'allowsNull']);
                }
            } catch (\ReflectionException) {
            }
        }
        return $a;
    }
    /**
     * @return array
     */
    public static function castProperty(\ReflectionProperty $c, array $a, Stub $stub, bool $isNested)
    {
        $a[Caster::PREFIX_VIRTUAL . 'modifiers'] = implode(' ', \Reflection::getModifierNames($c->getModifiers()));
        self::addAttributes($a, $c);
        self::addExtra($a, $c);
        return $a;
    }
    /**
     * @return array
     */
    public static function castReference(\ReflectionReference $c, array $a, Stub $stub, bool $isNested)
    {
        $a[Caster::PREFIX_VIRTUAL . 'id'] = $c->getId();
        return $a;
    }
    /**
     * @return array
     */
    public static function castExtension(\ReflectionExtension $c, array $a, Stub $stub, bool $isNested)
    {
        self::addMap($a, $c, ['version' => 'getVersion', 'dependencies' => 'getDependencies', 'iniEntries' => 'getIniEntries', 'isPersistent' => 'isPersistent', 'isTemporary' => 'isTemporary', 'constants' => 'getConstants', 'functions' => 'getFunctions', 'classes' => 'getClasses']);
        return $a;
    }
    /**
     * @return array
     */
    public static function castZendExtension(\ReflectionZendExtension $c, array $a, Stub $stub, bool $isNested)
    {
        self::addMap($a, $c, ['version' => 'getVersion', 'author' => 'getAuthor', 'copyright' => 'getCopyright', 'url' => 'getURL']);
        return $a;
    }
    /**
     * @return string
     */
    public static function getSignature(array $a)
    {
        $prefix = Caster::PREFIX_VIRTUAL;
        $signature = '';
        if (isset($a[$prefix . 'parameters'])) {
            foreach ($a[$prefix . 'parameters']->value as $k => $param) {
                $signature .= ', ';
                if ($type = $param->getType()) {
                    if (!$type instanceof \ReflectionNamedType) {
                        $signature .= $type . ' ';
                    } else {
                        if ($param->allowsNull() && !\in_array($type->getName(), ['mixed', 'null'], \true)) {
                            $signature .= '?';
                        }
                        $signature .= substr(strrchr('\\' . $type->getName(), '\\'), 1) . ' ';
                    }
                }
                $signature .= $k;
                if (!$param->isDefaultValueAvailable()) {
                    continue;
                }
                $v = $param->getDefaultValue();
                $signature .= ' = ';
                if ($param->isDefaultValueConstant()) {
                    $signature .= substr(strrchr('\\' . $param->getDefaultValueConstantName(), '\\'), 1);
                } elseif (null === $v) {
                    $signature .= 'null';
                } elseif (\is_array($v)) {
                    $signature .= $v ? '[…' . \count($v) . ']' : '[]';
                } elseif (\is_string($v)) {
                    $signature .= 10 > \strlen($v) && !str_contains($v, '\\') ? "'{$v}'" : "'…" . \strlen($v) . "'";
                } elseif (\is_bool($v)) {
                    $signature .= $v ? 'true' : 'false';
                } elseif (\is_object($v)) {
                    $signature .= 'new ' . substr(strrchr('\\' . get_debug_type($v), '\\'), 1);
                } else {
                    $signature .= $v;
                }
            }
        }
        $signature = (empty($a[$prefix . 'returnsReference']) ? '' : '&') . '(' . substr($signature, 2) . ')';
        if (isset($a[$prefix . 'returnType'])) {
            $signature .= ': ' . substr(strrchr('\\' . $a[$prefix . 'returnType'], '\\'), 1);
        }
        return $signature;
    }
    private static function addExtra(array &$a, \Reflector $c): void
    {
        $x = isset($a[Caster::PREFIX_VIRTUAL . 'extra']) ? $a[Caster::PREFIX_VIRTUAL . 'extra']->value : [];
        if (method_exists($c, 'getFileName') && $m = $c->getFileName()) {
            $x['file'] = new LinkStub($m, $c->getStartLine());
            $x['line'] = $c->getStartLine() . ' to ' . $c->getEndLine();
        }
        self::addMap($x, $c, self::EXTRA_MAP, '');
        if ($x) {
            $a[Caster::PREFIX_VIRTUAL . 'extra'] = new EnumStub($x);
        }
    }
    private static function addMap(array &$a, object $c, array $map, string $prefix = Caster::PREFIX_VIRTUAL): void
    {
        foreach ($map as $k => $m) {
            if ('isDisabled' === $k) {
                continue;
            }
            if (method_exists($c, $m) && \false !== ($m = $c->{$m}()) && null !== $m) {
                $a[$prefix . $k] = $m instanceof \Reflector ? $m->name : $m;
            }
        }
    }
    private static function addAttributes(array &$a, \Reflector $c, string $prefix = Caster::PREFIX_VIRTUAL): void
    {
        foreach ($c->getAttributes() as $n) {
            $a[$prefix . 'attributes'][] = $n;
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\VarDumper\Caster;

use _ContaoManager\Symfony\Component\VarDumper\Cloner\Stub;
/**
 * Casts a caster's Stub.
 *
 * @author Nicolas Grekas <p@tchwork.com>
 *
 * @final
 */
class StubCaster
{
    /**
     * @return array
     */
    public static function castStub(Stub $c, array $a, Stub $stub, bool $isNested)
    {
        if ($isNested) {
            $stub->type = $c->type;
            $stub->class = $c->class;
            $stub->value = $c->value;
            $stub->handle = $c->handle;
            $stub->cut = $c->cut;
            $stub->attr = $c->attr;
            if (Stub::TYPE_REF === $c->type && !$c->class && \is_string($c->value) && !preg_match('//u', $c->value)) {
                $stub->type = Stub::TYPE_STRING;
                $stub->class = Stub::STRING_BINARY;
            }
            $a = [];
        }
        return $a;
    }
    /**
     * @return array
     */
    public static function castCutArray(CutArrayStub $c, array $a, Stub $stub, bool $isNested)
    {
        return $isNested ? $c->preservedSubset : $a;
    }
    /**
     * @return array
     */
    public static function cutInternals($obj, array $a, Stub $stub, bool $isNested)
    {
        if ($isNested) {
            $stub->cut += \count($a);
            return [];
        }
        return $a;
    }
    /**
     * @return array
     */
    public static function castEnum(EnumStub $c, array $a, Stub $stub, bool $isNested)
    {
        if ($isNested) {
            $stub->class = $c->dumpKeys ? '' : null;
            $stub->handle = 0;
            $stub->value = null;
            $stub->cut = $c->cut;
            $stub->attr = $c->attr;
            $a = [];
            if ($c->value) {
                foreach (array_keys($c->value) as $k) {
                    $keys[] = !isset($k[0]) || "\x00" !== $k[0] ? Caster::PREFIX_VIRTUAL . $k : $k;
                }
                // Preserve references with array_combine()
                $a = array_combine($keys, $c->value);
            }
        }
        return $a;
    }
    /**
     * @return array
     */
    public static function castScalar(ScalarStub $scalarStub, array $a, Stub $stub)
    {
        $stub->type = Stub::TYPE_SCALAR;
        $stub->attr['value'] = $scalarStub->value;
        return $a;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\VarDumper\Caster;

use _ContaoManager\Symfony\Component\HttpFoundation\Request;
use _ContaoManager\Symfony\Component\Uid\Ulid;
use _ContaoManager\Symfony\Component\Uid\Uuid;
use _ContaoManager\Symfony\Component\VarDumper\Cloner\Stub;
use _ContaoManager\Symfony\Component\VarExporter\Internal\LazyObjectState;
/**
 * @final
 */
class SymfonyCaster
{
    private const REQUEST_GETTERS = ['pathInfo' => 'getPathInfo', 'requestUri' => 'getRequestUri', 'baseUrl' => 'getBaseUrl', 'basePath' => 'getBasePath', 'method' => 'getMethod', 'format' => 'getRequestFormat'];
    /**
     * @return array
     */
    public static function castRequest(Request $request, array $a, Stub $stub, bool $isNested)
    {
        $clone = null;
        foreach (self::REQUEST_GETTERS as $prop => $getter) {
            $key = Caster::PREFIX_PROTECTED . $prop;
            if (\array_key_exists($key, $a) && null === $a[$key]) {
                $clone ??= clone $request;
                $a[Caster::PREFIX_VIRTUAL . $prop] = $clone->{$getter}();
            }
        }
        return $a;
    }
    /**
     * @return array
     */
    public static function castHttpClient($client, array $a, Stub $stub, bool $isNested)
    {
        $multiKey = \sprintf("\x00%s\x00multi", $client::class);
        if (isset($a[$multiKey])) {
            $a[$multiKey] = new CutStub($a[$multiKey]);
        }
        return $a;
    }
    /**
     * @return array
     */
    public static function castHttpClientResponse($response, array $a, Stub $stub, bool $isNested)
    {
        $stub->cut += \count($a);
        $a = [];
        foreach ($response->getInfo() as $k => $v) {
            $a[Caster::PREFIX_VIRTUAL . $k] = $v;
        }
        return $a;
    }
    /**
     * @return array
     */
    public static function castLazyObjectState($state, array $a, Stub $stub, bool $isNested)
    {
        if (!$isNested) {
            return $a;
        }
        $stub->cut += \count($a) - 1;
        $instance = $a['realInstance'] ?? null;
        if (isset($a['status'])) {
            // forward-compat with Symfony 8
            $a = ['status' => new ConstStub(match ($a['status']) {
                LazyObjectState::STATUS_INITIALIZED_FULL => 'INITIALIZED_FULL',
                LazyObjectState::STATUS_INITIALIZED_PARTIAL => 'INITIALIZED_PARTIAL',
                LazyObjectState::STATUS_UNINITIALIZED_FULL => 'UNINITIALIZED_FULL',
                LazyObjectState::STATUS_UNINITIALIZED_PARTIAL => 'UNINITIALIZED_PARTIAL',
            }, $a['status'])];
        }
        if ($instance) {
            $a['realInstance'] = $instance;
            --$stub->cut;
        }
        return $a;
    }
    /**
     * @return array
     */
    public static function castUuid(Uuid $uuid, array $a, Stub $stub, bool $isNested)
    {
        $a[Caster::PREFIX_VIRTUAL . 'toBase58'] = $uuid->toBase58();
        $a[Caster::PREFIX_VIRTUAL . 'toBase32'] = $uuid->toBase32();
        // symfony/uid >= 5.3
        if (method_exists($uuid, 'getDateTime')) {
            $a[Caster::PREFIX_VIRTUAL . 'time'] = $uuid->getDateTime()->format('Y-m-d H:i:s.u \U\T\C');
        }
        return $a;
    }
    /**
     * @return array
     */
    public static function castUlid(Ulid $ulid, array $a, Stub $stub, bool $isNested)
    {
        $a[Caster::PREFIX_VIRTUAL . 'toBase58'] = $ulid->toBase58();
        $a[Caster::PREFIX_VIRTUAL . 'toRfc4122'] = $ulid->toRfc4122();
        // symfony/uid >= 5.3
        if (method_exists($ulid, 'getDateTime')) {
            $a[Caster::PREFIX_VIRTUAL . 'time'] = $ulid->getDateTime()->format('Y-m-d H:i:s.v \U\T\C');
        }
        return $a;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\VarDumper\Caster;

/**
 * Represents a single backtrace frame as returned by debug_backtrace() or Exception->getTrace().
 *
 * @author Nicolas Grekas <p@tchwork.com>
 */
class FrameStub extends EnumStub
{
    public $keepArgs;
    public $inTraceStub;
    public function __construct(array $frame, bool $keepArgs = \true, bool $inTraceStub = \false)
    {
        $this->value = $frame;
        $this->keepArgs = $keepArgs;
        $this->inTraceStub = $inTraceStub;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\VarDumper\Caster;

use _ContaoManager\ProxyManager\Proxy\ProxyInterface;
use _ContaoManager\Symfony\Component\VarDumper\Cloner\Stub;
/**
 * @author Nicolas Grekas <p@tchwork.com>
 *
 * @final
 */
class ProxyManagerCaster
{
    /**
     * @return array
     */
    public static function castProxy(ProxyInterface $c, array $a, Stub $stub, bool $isNested)
    {
        if ($parent = get_parent_class($c)) {
            $stub->class .= ' - ' . $parent;
        }
        $stub->class .= '@proxy';
        return $a;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\VarDumper\Caster;

use FFI\CData;
use FFI\CType;
use _ContaoManager\Symfony\Component\VarDumper\Cloner\Stub;
/**
 * Casts FFI extension classes to array representation.
 *
 * @author Nesmeyanov Kirill <nesk@xakep.ru>
 */
final class FFICaster
{
    /**
     * In case of "char*" contains a string, the length of which depends on
     * some other parameter, then during the generation of the string it is
     * possible to go beyond the allowable memory area.
     *
     * This restriction serves to ensure that processing does not take
     * up the entire allowable PHP memory limit.
     */
    private const MAX_STRING_LENGTH = 255;
    public static function castCTypeOrCData(CData|CType $data, array $args, Stub $stub): array
    {
        if ($data instanceof CType) {
            $type = $data;
            $data = null;
        } else {
            $type = \FFI::typeof($data);
        }
        $stub->class = \sprintf('%s<%s> size %d align %d', ($data ?? $type)::class, $type->getName(), $type->getSize(), $type->getAlignment());
        return match ($type->getKind()) {
            CType::TYPE_FLOAT, CType::TYPE_DOUBLE, \defined('_ContaoManager\FFI\CType::TYPE_LONGDOUBLE') ? CType::TYPE_LONGDOUBLE : -1, CType::TYPE_UINT8, CType::TYPE_SINT8, CType::TYPE_UINT16, CType::TYPE_SINT16, CType::TYPE_UINT32, CType::TYPE_SINT32, CType::TYPE_UINT64, CType::TYPE_SINT64, CType::TYPE_BOOL, CType::TYPE_CHAR, CType::TYPE_ENUM => null !== $data ? [Caster::PREFIX_VIRTUAL . 'cdata' => $data->cdata] : [],
            CType::TYPE_POINTER => self::castFFIPointer($stub, $type, $data),
            CType::TYPE_STRUCT => self::castFFIStructLike($type, $data),
            CType::TYPE_FUNC => self::castFFIFunction($stub, $type),
            default => $args,
        };
    }
    private static function castFFIFunction(Stub $stub, CType $type): array
    {
        $arguments = [];
        for ($i = 0, $count = $type->getFuncParameterCount(); $i < $count; ++$i) {
            $param = $type->getFuncParameterType($i);
            $arguments[] = $param->getName();
        }
        $abi = match ($type->getFuncABI()) {
            CType::ABI_DEFAULT, CType::ABI_CDECL => '[cdecl]',
            CType::ABI_FASTCALL => '[fastcall]',
            CType::ABI_THISCALL => '[thiscall]',
            CType::ABI_STDCALL => '[stdcall]',
            CType::ABI_PASCAL => '[pascal]',
            CType::ABI_REGISTER => '[register]',
            CType::ABI_MS => '[ms]',
            CType::ABI_SYSV => '[sysv]',
            CType::ABI_VECTORCALL => '[vectorcall]',
            default => '[unknown abi]',
        };
        $returnType = $type->getFuncReturnType();
        $stub->class = $abi . ' callable(' . implode(', ', $arguments) . '): ' . $returnType->getName();
        return [Caster::PREFIX_VIRTUAL . 'returnType' => $returnType];
    }
    private static function castFFIPointer(Stub $stub, CType $type, ?CData $data = null): array
    {
        $ptr = $type->getPointerType();
        if (null === $data) {
            return [Caster::PREFIX_VIRTUAL . '0' => $ptr];
        }
        return match ($ptr->getKind()) {
            CType::TYPE_CHAR => [Caster::PREFIX_VIRTUAL . 'cdata' => self::castFFIStringValue($data)],
            CType::TYPE_FUNC => self::castFFIFunction($stub, $ptr),
            default => [Caster::PREFIX_VIRTUAL . 'cdata' => $data[0]],
        };
    }
    private static function castFFIStringValue(CData $data): string|CutStub
    {
        $result = [];
        $ffi = \FFI::cdef(<<<C
    size_t zend_get_page_size(void);
C
);
        $pageSize = $ffi->zend_get_page_size();
        // get cdata address
        $start = $ffi->cast('uintptr_t', $ffi->cast('char*', $data))->cdata;
        // accessing memory in the same page as $start is safe
        $max = min(self::MAX_STRING_LENGTH, ($start | $pageSize - 1) - $start);
        for ($i = 0; $i < $max; ++$i) {
            $result[$i] = $data[$i];
            if ("\x00" === $data[$i]) {
                return implode('', $result);
            }
        }
        $string = implode('', $result);
        $stub = new CutStub($string);
        $stub->cut = -1;
        $stub->value = $string;
        return $stub;
    }
    private static function castFFIStructLike(CType $type, ?CData $data = null): array
    {
        $isUnion = ($type->getAttributes() & CType::ATTR_UNION) === CType::ATTR_UNION;
        $result = [];
        foreach ($type->getStructFieldNames() as $name) {
            $field = $type->getStructFieldType($name);
            // Retrieving the value of a field from a union containing
            // a pointer is not a safe operation, because may contain
            // incorrect data.
            $isUnsafe = $isUnion && CType::TYPE_POINTER === $field->getKind();
            if ($isUnsafe) {
                $result[Caster::PREFIX_VIRTUAL . $name . '?'] = $field;
            } elseif (null === $data) {
                $result[Caster::PREFIX_VIRTUAL . $name] = $field;
            } else {
                $fieldName = $data->{$name} instanceof CData ? '' : $field->getName() . ' ';
                $result[Caster::PREFIX_VIRTUAL . $fieldName . $name] = $data->{$name};
            }
        }
        return $result;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\VarDumper\Caster;

use _ContaoManager\Symfony\Component\VarDumper\Cloner\Stub;
/**
 * Casts DateTimeInterface related classes to array representation.
 *
 * @author Dany Maillard <danymaillard93b@gmail.com>
 *
 * @final
 */
class DateCaster
{
    private const PERIOD_LIMIT = 3;
    /**
     * @return array
     */
    public static function castDateTime(\DateTimeInterface $d, array $a, Stub $stub, bool $isNested, int $filter)
    {
        $prefix = Caster::PREFIX_VIRTUAL;
        $location = $d->getTimezone() ? $d->getTimezone()->getLocation() : null;
        $fromNow = (new \DateTimeImmutable())->diff($d);
        $title = $d->format('l, F j, Y') . "\n" . self::formatInterval($fromNow) . ' from now' . ($location ? $d->format('I') ? "\nDST On" : "\nDST Off" : '');
        unset($a[Caster::PREFIX_DYNAMIC . 'date'], $a[Caster::PREFIX_DYNAMIC . 'timezone'], $a[Caster::PREFIX_DYNAMIC . 'timezone_type']);
        $a[$prefix . 'date'] = new ConstStub(self::formatDateTime($d, $location ? ' e (P)' : ' P'), $title);
        $stub->class .= $d->format(' @U');
        return $a;
    }
    /**
     * @return array
     */
    public static function castInterval(\DateInterval $interval, array $a, Stub $stub, bool $isNested, int $filter)
    {
        $now = new \DateTimeImmutable('@0', new \DateTimeZone('UTC'));
        $numberOfSeconds = $now->add($interval)->getTimestamp() - $now->getTimestamp();
        $title = number_format($numberOfSeconds, 0, '.', ' ') . 's';
        $i = [Caster::PREFIX_VIRTUAL . 'interval' => new ConstStub(self::formatInterval($interval), $title)];
        return $filter & Caster::EXCLUDE_VERBOSE ? $i : $i + $a;
    }
    private static function formatInterval(\DateInterval $i): string
    {
        $format = '%R ';
        if (0 === $i->y && 0 === $i->m && ($i->h >= 24 || $i->i >= 60 || $i->s >= 60)) {
            $d = new \DateTimeImmutable('@0', new \DateTimeZone('UTC'));
            $i = $d->diff($d->add($i));
            // recalculate carry over points
            $format .= 0 < $i->days ? '%ad ' : '';
        } else {
            $format .= ($i->y ? '%yy ' : '') . ($i->m ? '%mm ' : '') . ($i->d ? '%dd ' : '');
        }
        $format .= $i->h || $i->i || $i->s || $i->f ? '%H:%I:' . self::formatSeconds($i->s, substr($i->f, 2)) : '';
        $format = '%R ' === $format ? '0s' : $format;
        return $i->format(rtrim($format));
    }
    /**
     * @return array
     */
    public static function castTimeZone(\DateTimeZone $timeZone, array $a, Stub $stub, bool $isNested, int $filter)
    {
        $location = $timeZone->getLocation();
        $formatted = (new \DateTimeImmutable('now', $timeZone))->format($location ? 'e (P)' : 'P');
        $title = $location && \extension_loaded('intl') ? \Locale::getDisplayRegion('-' . $location['country_code']) : '';
        $z = [Caster::PREFIX_VIRTUAL . 'timezone' => new ConstStub($formatted, $title)];
        return $filter & Caster::EXCLUDE_VERBOSE ? $z : $z + $a;
    }
    /**
     * @return array
     */
    public static function castPeriod(\DatePeriod $p, array $a, Stub $stub, bool $isNested, int $filter)
    {
        $dates = [];
        foreach (clone $p as $i => $d) {
            if (self::PERIOD_LIMIT === $i) {
                $now = new \DateTimeImmutable('now', new \DateTimeZone('UTC'));
                $dates[] = \sprintf('%s more', ($end = $p->getEndDate()) ? ceil(($end->format('U.u') - $d->format('U.u')) / ((int) $now->add($p->getDateInterval())->format('U.u') - (int) $now->format('U.u'))) : $p->recurrences - $i);
                break;
            }
            $dates[] = \sprintf('%s) %s', $i + 1, self::formatDateTime($d));
        }
        $period = \sprintf('every %s, from %s%s %s', self::formatInterval($p->getDateInterval()), $p->include_start_date ? '[' : ']', self::formatDateTime($p->getStartDate()), ($end = $p->getEndDate()) ? 'to ' . self::formatDateTime($end) . (\PHP_VERSION_ID >= 80200 && $p->include_end_date ? ']' : '[') : 'recurring ' . $p->recurrences . ' time/s');
        $p = [Caster::PREFIX_VIRTUAL . 'period' => new ConstStub($period, implode("\n", $dates))];
        return $filter & Caster::EXCLUDE_VERBOSE ? $p : $p + $a;
    }
    private static function formatDateTime(\DateTimeInterface $d, string $extra = ''): string
    {
        return $d->format('Y-m-d H:i:' . self::formatSeconds($d->format('s'), $d->format('u')) . $extra);
    }
    private static function formatSeconds(string $s, string $us): string
    {
        return \sprintf('%02d.%s', $s, 0 === ($len = \strlen($t = rtrim($us, '0'))) ? '0' : ($len <= 3 ? str_pad($t, 3, '0') : $us));
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\VarDumper\Caster;

use _ContaoManager\Symfony\Component\VarDumper\Cloner\Stub;
/**
 * Casts PDO related classes to array representation.
 *
 * @author Nicolas Grekas <p@tchwork.com>
 *
 * @final
 */
class PdoCaster
{
    private const PDO_ATTRIBUTES = ['CASE' => [\PDO::CASE_LOWER => 'LOWER', \PDO::CASE_NATURAL => 'NATURAL', \PDO::CASE_UPPER => 'UPPER'], 'ERRMODE' => [\PDO::ERRMODE_SILENT => 'SILENT', \PDO::ERRMODE_WARNING => 'WARNING', \PDO::ERRMODE_EXCEPTION => 'EXCEPTION'], 'TIMEOUT', 'PREFETCH', 'AUTOCOMMIT', 'PERSISTENT', 'DRIVER_NAME', 'SERVER_INFO', 'ORACLE_NULLS' => [\PDO::NULL_NATURAL => 'NATURAL', \PDO::NULL_EMPTY_STRING => 'EMPTY_STRING', \PDO::NULL_TO_STRING => 'TO_STRING'], 'CLIENT_VERSION', 'SERVER_VERSION', 'STATEMENT_CLASS', 'EMULATE_PREPARES', 'CONNECTION_STATUS', 'STRINGIFY_FETCHES', 'DEFAULT_FETCH_MODE' => [\PDO::FETCH_ASSOC => 'ASSOC', \PDO::FETCH_BOTH => 'BOTH', \PDO::FETCH_LAZY => 'LAZY', \PDO::FETCH_NUM => 'NUM', \PDO::FETCH_OBJ => 'OBJ']];
    /**
     * @return array
     */
    public static function castPdo(\PDO $c, array $a, Stub $stub, bool $isNested)
    {
        $attr = [];
        $errmode = $c->getAttribute(\PDO::ATTR_ERRMODE);
        $c->setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION);
        foreach (self::PDO_ATTRIBUTES as $k => $v) {
            if (!isset($k[0])) {
                $k = $v;
                $v = [];
            }
            try {
                $attr[$k] = 'ERRMODE' === $k ? $errmode : $c->getAttribute(\constant('PDO::ATTR_' . $k));
                if ($v && isset($v[$attr[$k]])) {
                    $attr[$k] = new ConstStub($v[$attr[$k]], $attr[$k]);
                }
            } catch (\Exception) {
            }
        }
        if (isset($attr[$k = 'STATEMENT_CLASS'][1])) {
            if ($attr[$k][1]) {
                $attr[$k][1] = new ArgsStub($attr[$k][1], '__construct', $attr[$k][0]);
            }
            $attr[$k][0] = new ClassStub($attr[$k][0]);
        }
        $prefix = Caster::PREFIX_VIRTUAL;
        $a += [$prefix . 'inTransaction' => method_exists($c, 'inTransaction'), $prefix . 'errorInfo' => $c->errorInfo(), $prefix . 'attributes' => new EnumStub($attr)];
        if ($a[$prefix . 'inTransaction']) {
            $a[$prefix . 'inTransaction'] = $c->inTransaction();
        } else {
            unset($a[$prefix . 'inTransaction']);
        }
        if (!isset($a[$prefix . 'errorInfo'][1], $a[$prefix . 'errorInfo'][2])) {
            unset($a[$prefix . 'errorInfo']);
        }
        $c->setAttribute(\PDO::ATTR_ERRMODE, $errmode);
        return $a;
    }
    /**
     * @return array
     */
    public static function castPdoStatement(\PDOStatement $c, array $a, Stub $stub, bool $isNested)
    {
        $prefix = Caster::PREFIX_VIRTUAL;
        $a[$prefix . 'errorInfo'] = $c->errorInfo();
        if (!isset($a[$prefix . 'errorInfo'][1], $a[$prefix . 'errorInfo'][2])) {
            unset($a[$prefix . 'errorInfo']);
        }
        return $a;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\VarDumper\Caster;

use _ContaoManager\Symfony\Component\VarDumper\Cloner\Stub;
/**
 * Casts XML resources to array representation.
 *
 * @author Nicolas Grekas <p@tchwork.com>
 *
 * @final
 */
class XmlResourceCaster
{
    private const XML_ERRORS = [\XML_ERROR_NONE => 'XML_ERROR_NONE', \XML_ERROR_NO_MEMORY => 'XML_ERROR_NO_MEMORY', \XML_ERROR_SYNTAX => 'XML_ERROR_SYNTAX', \XML_ERROR_NO_ELEMENTS => 'XML_ERROR_NO_ELEMENTS', \XML_ERROR_INVALID_TOKEN => 'XML_ERROR_INVALID_TOKEN', \XML_ERROR_UNCLOSED_TOKEN => 'XML_ERROR_UNCLOSED_TOKEN', \XML_ERROR_PARTIAL_CHAR => 'XML_ERROR_PARTIAL_CHAR', \XML_ERROR_TAG_MISMATCH => 'XML_ERROR_TAG_MISMATCH', \XML_ERROR_DUPLICATE_ATTRIBUTE => 'XML_ERROR_DUPLICATE_ATTRIBUTE', \XML_ERROR_JUNK_AFTER_DOC_ELEMENT => 'XML_ERROR_JUNK_AFTER_DOC_ELEMENT', \XML_ERROR_PARAM_ENTITY_REF => 'XML_ERROR_PARAM_ENTITY_REF', \XML_ERROR_UNDEFINED_ENTITY => 'XML_ERROR_UNDEFINED_ENTITY', \XML_ERROR_RECURSIVE_ENTITY_REF => 'XML_ERROR_RECURSIVE_ENTITY_REF', \XML_ERROR_ASYNC_ENTITY => 'XML_ERROR_ASYNC_ENTITY', \XML_ERROR_BAD_CHAR_REF => 'XML_ERROR_BAD_CHAR_REF', \XML_ERROR_BINARY_ENTITY_REF => 'XML_ERROR_BINARY_ENTITY_REF', \XML_ERROR_ATTRIBUTE_EXTERNAL_ENTITY_REF => 'XML_ERROR_ATTRIBUTE_EXTERNAL_ENTITY_REF', \XML_ERROR_MISPLACED_XML_PI => 'XML_ERROR_MISPLACED_XML_PI', \XML_ERROR_UNKNOWN_ENCODING => 'XML_ERROR_UNKNOWN_ENCODING', \XML_ERROR_INCORRECT_ENCODING => 'XML_ERROR_INCORRECT_ENCODING', \XML_ERROR_UNCLOSED_CDATA_SECTION => 'XML_ERROR_UNCLOSED_CDATA_SECTION', \XML_ERROR_EXTERNAL_ENTITY_HANDLING => 'XML_ERROR_EXTERNAL_ENTITY_HANDLING'];
    /**
     * @return array
     */
    public static function castXml($h, array $a, Stub $stub, bool $isNested)
    {
        $a['current_byte_index'] = xml_get_current_byte_index($h);
        $a['current_column_number'] = xml_get_current_column_number($h);
        $a['current_line_number'] = xml_get_current_line_number($h);
        $a['error_code'] = xml_get_error_code($h);
        if (isset(self::XML_ERRORS[$a['error_code']])) {
            $a['error_code'] = new ConstStub(self::XML_ERRORS[$a['error_code']], $a['error_code']);
        }
        return $a;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\VarDumper\Caster;

use _ContaoManager\Symfony\Component\VarDumper\Cloner\Stub;
/**
 * Casts common resource types to array representation.
 *
 * @author Nicolas Grekas <p@tchwork.com>
 *
 * @final
 */
class ResourceCaster
{
    public static function castCurl(\CurlHandle $h, array $a, Stub $stub, bool $isNested): array
    {
        return curl_getinfo($h);
    }
    /**
     * @return array
     */
    public static function castDba($dba, array $a, Stub $stub, bool $isNested)
    {
        $list = dba_list();
        $a['file'] = $list[(int) $dba];
        return $a;
    }
    /**
     * @return array
     */
    public static function castProcess($process, array $a, Stub $stub, bool $isNested)
    {
        return proc_get_status($process);
    }
    public static function castStream($stream, array $a, Stub $stub, bool $isNested): array
    {
        $a = stream_get_meta_data($stream) + static::castStreamContext($stream, $a, $stub, $isNested);
        if ($a['uri'] ?? \false) {
            $a['uri'] = new LinkStub($a['uri']);
        }
        return $a;
    }
    /**
     * @return array
     */
    public static function castStreamContext($stream, array $a, Stub $stub, bool $isNested)
    {
        return @stream_context_get_params($stream) ?: $a;
    }
    /**
     * @return array
     */
    public static function castGd($gd, array $a, Stub $stub, bool $isNested)
    {
        $a['size'] = imagesx($gd) . 'x' . imagesy($gd);
        $a['trueColor'] = imageistruecolor($gd);
        return $a;
    }
    /**
     * @return array
     */
    public static function castOpensslX509($h, array $a, Stub $stub, bool $isNested)
    {
        $stub->cut = -1;
        $info = openssl_x509_parse($h, \false);
        $pin = openssl_pkey_get_public($h);
        $pin = openssl_pkey_get_details($pin)['key'];
        $pin = \array_slice(explode("\n", $pin), 1, -2);
        $pin = base64_decode(implode('', $pin));
        $pin = base64_encode(hash('sha256', $pin, \true));
        $a += ['subject' => new EnumStub(array_intersect_key($info['subject'], ['organizationName' => \true, 'commonName' => \true])), 'issuer' => new EnumStub(array_intersect_key($info['issuer'], ['organizationName' => \true, 'commonName' => \true])), 'expiry' => new ConstStub(date(\DateTimeInterface::ISO8601, $info['validTo_time_t']), $info['validTo_time_t']), 'fingerprint' => new EnumStub(['md5' => new ConstStub(wordwrap(strtoupper(openssl_x509_fingerprint($h, 'md5')), 2, ':', \true)), 'sha1' => new ConstStub(wordwrap(strtoupper(openssl_x509_fingerprint($h, 'sha1')), 2, ':', \true)), 'sha256' => new ConstStub(wordwrap(strtoupper(openssl_x509_fingerprint($h, 'sha256')), 2, ':', \true)), 'pin-sha256' => new ConstStub($pin)])];
        return $a;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\VarDumper\Caster;

use _ContaoManager\Symfony\Component\ErrorHandler\Exception\FlattenException;
use _ContaoManager\Symfony\Component\ErrorHandler\Exception\SilencedErrorContext;
use _ContaoManager\Symfony\Component\VarDumper\Cloner\Stub;
use _ContaoManager\Symfony\Component\VarDumper\Exception\ThrowingCasterException;
/**
 * Casts common Exception classes to array representation.
 *
 * @author Nicolas Grekas <p@tchwork.com>
 *
 * @final
 */
class ExceptionCaster
{
    public static int $srcContext = 1;
    public static bool $traceArgs = \true;
    public static array $errorTypes = [\E_DEPRECATED => 'E_DEPRECATED', \E_USER_DEPRECATED => 'E_USER_DEPRECATED', \E_RECOVERABLE_ERROR => 'E_RECOVERABLE_ERROR', \E_ERROR => 'E_ERROR', \E_WARNING => 'E_WARNING', \E_PARSE => 'E_PARSE', \E_NOTICE => 'E_NOTICE', \E_CORE_ERROR => 'E_CORE_ERROR', \E_CORE_WARNING => 'E_CORE_WARNING', \E_COMPILE_ERROR => 'E_COMPILE_ERROR', \E_COMPILE_WARNING => 'E_COMPILE_WARNING', \E_USER_ERROR => 'E_USER_ERROR', \E_USER_WARNING => 'E_USER_WARNING', \E_USER_NOTICE => 'E_USER_NOTICE', 2048 => 'E_STRICT'];
    private static array $framesCache = [];
    /**
     * @return array
     */
    public static function castError(\Error $e, array $a, Stub $stub, bool $isNested, int $filter = 0)
    {
        return self::filterExceptionArray($stub->class, $a, "\x00Error\x00", $filter);
    }
    /**
     * @return array
     */
    public static function castException(\Exception $e, array $a, Stub $stub, bool $isNested, int $filter = 0)
    {
        return self::filterExceptionArray($stub->class, $a, "\x00Exception\x00", $filter);
    }
    /**
     * @return array
     */
    public static function castErrorException(\ErrorException $e, array $a, Stub $stub, bool $isNested)
    {
        if (isset($a[$s = Caster::PREFIX_PROTECTED . 'severity'], self::$errorTypes[$a[$s]])) {
            $a[$s] = new ConstStub(self::$errorTypes[$a[$s]], $a[$s]);
        }
        return $a;
    }
    /**
     * @return array
     */
    public static function castThrowingCasterException(ThrowingCasterException $e, array $a, Stub $stub, bool $isNested)
    {
        $trace = Caster::PREFIX_VIRTUAL . 'trace';
        $prefix = Caster::PREFIX_PROTECTED;
        $xPrefix = "\x00Exception\x00";
        if (isset($a[$xPrefix . 'previous'], $a[$trace]) && $a[$xPrefix . 'previous'] instanceof \Exception) {
            $b = (array) $a[$xPrefix . 'previous'];
            $class = get_debug_type($a[$xPrefix . 'previous']);
            self::traceUnshift($b[$xPrefix . 'trace'], $class, $b[$prefix . 'file'], $b[$prefix . 'line']);
            $a[$trace] = new TraceStub($b[$xPrefix . 'trace'], \false, 0, -\count($a[$trace]->value));
        }
        unset($a[$xPrefix . 'previous'], $a[$prefix . 'code'], $a[$prefix . 'file'], $a[$prefix . 'line']);
        return $a;
    }
    /**
     * @return array
     */
    public static function castSilencedErrorContext(SilencedErrorContext $e, array $a, Stub $stub, bool $isNested)
    {
        $sPrefix = "\x00" . SilencedErrorContext::class . "\x00";
        if (!isset($a[$s = $sPrefix . 'severity'])) {
            return $a;
        }
        if (isset(self::$errorTypes[$a[$s]])) {
            $a[$s] = new ConstStub(self::$errorTypes[$a[$s]], $a[$s]);
        }
        $trace = [['file' => $a[$sPrefix . 'file'], 'line' => $a[$sPrefix . 'line']]];
        if (isset($a[$sPrefix . 'trace'])) {
            $trace = array_merge($trace, $a[$sPrefix . 'trace']);
        }
        unset($a[$sPrefix . 'file'], $a[$sPrefix . 'line'], $a[$sPrefix . 'trace']);
        $a[Caster::PREFIX_VIRTUAL . 'trace'] = new TraceStub($trace, self::$traceArgs);
        return $a;
    }
    /**
     * @return array
     */
    public static function castTraceStub(TraceStub $trace, array $a, Stub $stub, bool $isNested)
    {
        if (!$isNested) {
            return $a;
        }
        $stub->class = '';
        $stub->handle = 0;
        $frames = $trace->value;
        $prefix = Caster::PREFIX_VIRTUAL;
        $a = [];
        $j = \count($frames);
        if (0 > $i = $trace->sliceOffset) {
            $i = max(0, $j + $i);
        }
        if (!isset($trace->value[$i])) {
            return [];
        }
        $lastCall = isset($frames[$i]['function']) ? (isset($frames[$i]['class']) ? $frames[0]['class'] . $frames[$i]['type'] : '') . $frames[$i]['function'] . '()' : '';
        $frames[] = ['function' => ''];
        $collapse = \false;
        for ($j += $trace->numberingOffset - $i++; isset($frames[$i]); ++$i, --$j) {
            $f = $frames[$i];
            $call = isset($f['function']) ? (isset($f['class']) ? $f['class'] . $f['type'] : '') . $f['function'] : '???';
            $frame = new FrameStub(['object' => $f['object'] ?? null, 'class' => $f['class'] ?? null, 'type' => $f['type'] ?? null, 'function' => $f['function'] ?? null] + $frames[$i - 1], \false, \true);
            $f = self::castFrameStub($frame, [], $frame, \true);
            if (isset($f[$prefix . 'src'])) {
                foreach ($f[$prefix . 'src']->value as $label => $frame) {
                    if (str_starts_with($label, "\x00~collapse=0")) {
                        if ($collapse) {
                            $label = substr_replace($label, '1', 11, 1);
                        } else {
                            $collapse = \true;
                        }
                    }
                    $label = substr_replace($label, "title=Stack level {$j}.&", 2, 0);
                }
                $f = $frames[$i - 1];
                if ($trace->keepArgs && !empty($f['args']) && $frame instanceof EnumStub) {
                    $frame->value['arguments'] = new ArgsStub($f['args'], $f['function'] ?? null, $f['class'] ?? null);
                }
            } elseif ('???' !== $lastCall) {
                $label = new ClassStub($lastCall);
                if (isset($label->attr['ellipsis'])) {
                    $label->attr['ellipsis'] += 2;
                    $label = substr_replace($prefix, "ellipsis-type=class&ellipsis={$label->attr['ellipsis']}&ellipsis-tail=1&title=Stack level {$j}.", 2, 0) . $label->value . '()';
                } else {
                    $label = substr_replace($prefix, "title=Stack level {$j}.", 2, 0) . $label->value . '()';
                }
            } else {
                $label = substr_replace($prefix, "title=Stack level {$j}.", 2, 0) . $lastCall;
            }
            $a[substr_replace($label, \sprintf('separator=%s&', $frame instanceof EnumStub ? ' ' : ':'), 2, 0)] = $frame;
            $lastCall = $call;
        }
        if (null !== $trace->sliceLength) {
            $a = \array_slice($a, 0, $trace->sliceLength, \true);
        }
        return $a;
    }
    /**
     * @return array
     */
    public static function castFrameStub(FrameStub $frame, array $a, Stub $stub, bool $isNested)
    {
        if (!$isNested) {
            return $a;
        }
        $f = $frame->value;
        $prefix = Caster::PREFIX_VIRTUAL;
        if (isset($f['file'], $f['line'])) {
            $cacheKey = $f;
            unset($cacheKey['object'], $cacheKey['args']);
            $cacheKey[] = self::$srcContext;
            $cacheKey = implode('-', $cacheKey);
            if (isset(self::$framesCache[$cacheKey])) {
                $a[$prefix . 'src'] = self::$framesCache[$cacheKey];
            } else {
                if (preg_match('/\((\d+)\)(?:\([\da-f]{32}\))? : (?:eval\(\)\'d code|runtime-created function)$/', $f['file'], $match)) {
                    $f['file'] = substr($f['file'], 0, -\strlen($match[0]));
                    $f['line'] = (int) $match[1];
                }
                $src = $f['line'];
                $srcKey = $f['file'];
                $ellipsis = new LinkStub($srcKey, 0);
                $srcAttr = 'collapse=' . (int) $ellipsis->inVendor;
                $ellipsisTail = $ellipsis->attr['ellipsis-tail'] ?? 0;
                $ellipsis = $ellipsis->attr['ellipsis'] ?? 0;
                if (is_file($f['file']) && 0 <= self::$srcContext) {
                    if (!empty($f['class']) && (is_subclass_of($f['class'], '_ContaoManager\Twig\Template') || is_subclass_of($f['class'], '_ContaoManager\Twig_Template')) && method_exists($f['class'], 'getDebugInfo')) {
                        $template = null;
                        if (isset($f['object'])) {
                            $template = $f['object'];
                        } elseif ((new \ReflectionClass($f['class']))->isInstantiable()) {
                            $template = unserialize(\sprintf('O:%d:"%s":0:{}', \strlen($f['class']), $f['class']));
                        }
                        if (null !== $template) {
                            $ellipsis = 0;
                            $templateSrc = method_exists($template, 'getSourceContext') ? $template->getSourceContext()->getCode() : (method_exists($template, 'getSource') ? $template->getSource() : '');
                            $templateInfo = $template->getDebugInfo();
                            if (isset($templateInfo[$f['line']])) {
                                if (!method_exists($template, 'getSourceContext') || !is_file($templatePath = $template->getSourceContext()->getPath())) {
                                    $templatePath = null;
                                }
                                if ($templateSrc) {
                                    $src = self::extractSource($templateSrc, $templateInfo[$f['line']], self::$srcContext, 'twig', $templatePath, $f);
                                    $srcKey = ($templatePath ?: $template->getTemplateName()) . ':' . $templateInfo[$f['line']];
                                }
                            }
                        }
                    }
                    if ($srcKey == $f['file']) {
                        $src = self::extractSource(file_get_contents($f['file']), $f['line'], self::$srcContext, 'php', $f['file'], $f);
                        $srcKey .= ':' . $f['line'];
                        if ($ellipsis) {
                            $ellipsis += 1 + \strlen($f['line']);
                        }
                    }
                    $srcAttr .= \sprintf('&separator= &file=%s&line=%d', rawurlencode($f['file']), $f['line']);
                } else {
                    $srcAttr .= '&separator=:';
                }
                $srcAttr .= $ellipsis ? '&ellipsis-type=path&ellipsis=' . $ellipsis . '&ellipsis-tail=' . $ellipsisTail : '';
                self::$framesCache[$cacheKey] = $a[$prefix . 'src'] = new EnumStub(["\x00~{$srcAttr}\x00{$srcKey}" => $src]);
            }
        }
        unset($a[$prefix . 'args'], $a[$prefix . 'line'], $a[$prefix . 'file']);
        if ($frame->inTraceStub) {
            unset($a[$prefix . 'class'], $a[$prefix . 'type'], $a[$prefix . 'function']);
        }
        foreach ($a as $k => $v) {
            if (!$v) {
                unset($a[$k]);
            }
        }
        if ($frame->keepArgs && !empty($f['args'])) {
            $a[$prefix . 'arguments'] = new ArgsStub($f['args'], $f['function'], $f['class']);
        }
        return $a;
    }
    /**
     * @return array
     */
    public static function castFlattenException(FlattenException $e, array $a, Stub $stub, bool $isNested)
    {
        if ($isNested) {
            $k = \sprintf(Caster::PATTERN_PRIVATE, FlattenException::class, 'traceAsString');
            $a[$k] = new CutStub($a[$k]);
        }
        return $a;
    }
    private static function filterExceptionArray(string $xClass, array $a, string $xPrefix, int $filter): array
    {
        if (isset($a[$xPrefix . 'trace'])) {
            $trace = $a[$xPrefix . 'trace'];
            unset($a[$xPrefix . 'trace']);
            // Ensures the trace is always last
        } else {
            $trace = [];
        }
        if (!($filter & Caster::EXCLUDE_VERBOSE) && $trace) {
            if (isset($a[Caster::PREFIX_PROTECTED . 'file'], $a[Caster::PREFIX_PROTECTED . 'line'])) {
                self::traceUnshift($trace, $xClass, $a[Caster::PREFIX_PROTECTED . 'file'], $a[Caster::PREFIX_PROTECTED . 'line']);
            }
            $a[Caster::PREFIX_VIRTUAL . 'trace'] = new TraceStub($trace, self::$traceArgs);
        }
        if (empty($a[$xPrefix . 'previous'])) {
            unset($a[$xPrefix . 'previous']);
        }
        unset($a[$xPrefix . 'string'], $a[Caster::PREFIX_DYNAMIC . 'xdebug_message']);
        if (isset($a[Caster::PREFIX_PROTECTED . 'message']) && str_contains($a[Caster::PREFIX_PROTECTED . 'message'], "@anonymous\x00")) {
            $a[Caster::PREFIX_PROTECTED . 'message'] = preg_replace_callback('/[a-zA-Z_\x7f-\xff][\\\\a-zA-Z0-9_\x7f-\xff]*+@anonymous\x00.*?\.php(?:0x?|:[0-9]++\$)?[0-9a-fA-F]++/', fn($m) => class_exists($m[0], \false) ? ((get_parent_class($m[0]) ?: key(class_implements($m[0]))) ?: 'class') . '@anonymous' : $m[0], $a[Caster::PREFIX_PROTECTED . 'message']);
        }
        if (isset($a[Caster::PREFIX_PROTECTED . 'file'], $a[Caster::PREFIX_PROTECTED . 'line'])) {
            $a[Caster::PREFIX_PROTECTED . 'file'] = new LinkStub($a[Caster::PREFIX_PROTECTED . 'file'], $a[Caster::PREFIX_PROTECTED . 'line']);
        }
        return $a;
    }
    private static function traceUnshift(array &$trace, ?string $class, string $file, int $line): void
    {
        if (isset($trace[0]['file'], $trace[0]['line']) && $trace[0]['file'] === $file && $trace[0]['line'] === $line) {
            return;
        }
        array_unshift($trace, ['function' => $class ? 'new ' . $class : null, 'file' => $file, 'line' => $line]);
    }
    private static function extractSource(string $srcLines, int $line, int $srcContext, string $lang, ?string $file, array $frame): EnumStub
    {
        $srcLines = explode("\n", $srcLines);
        $src = [];
        for ($i = $line - 1 - $srcContext; $i <= $line - 1 + $srcContext; ++$i) {
            $src[] = ($srcLines[$i] ?? '') . "\n";
        }
        if ($frame['function'] ?? \false) {
            $stub = new CutStub(new \stdClass());
            $stub->class = (isset($frame['class']) ? $frame['class'] . $frame['type'] : '') . $frame['function'];
            $stub->type = Stub::TYPE_OBJECT;
            $stub->attr['cut_hash'] = \true;
            $stub->attr['file'] = $frame['file'];
            $stub->attr['line'] = $frame['line'];
            try {
                $caller = isset($frame['class']) ? new \ReflectionMethod($frame['class'], $frame['function']) : new \ReflectionFunction($frame['function']);
                $stub->class .= ReflectionCaster::getSignature(ReflectionCaster::castFunctionAbstract($caller, [], $stub, \true, Caster::EXCLUDE_VERBOSE));
                if ($f = $caller->getFileName()) {
                    $stub->attr['file'] = $f;
                    $stub->attr['line'] = $caller->getStartLine();
                }
            } catch (\ReflectionException) {
                // ignore fake class/function
            }
            $srcLines = ["\x00~separator=\x00" => $stub];
        } else {
            $stub = null;
            $srcLines = [];
        }
        $ltrim = 0;
        do {
            $pad = null;
            for ($i = $srcContext << 1; $i >= 0; --$i) {
                if (isset($src[$i][$ltrim]) && "\r" !== ($c = $src[$i][$ltrim]) && "\n" !== $c) {
                    $pad ??= $c;
                    if (' ' !== $c && "\t" !== $c || $pad !== $c) {
                        break;
                    }
                }
            }
            ++$ltrim;
        } while (0 > $i && null !== $pad);
        --$ltrim;
        foreach ($src as $i => $c) {
            if ($ltrim) {
                $c = isset($c[$ltrim]) && "\r" !== $c[$ltrim] ? substr($c, $ltrim) : ltrim($c, " \t");
            }
            $c = substr($c, 0, -1);
            if ($i !== $srcContext) {
                $c = new ConstStub('default', $c);
            } else {
                $c = new ConstStub($c, $stub ? 'in ' . $stub->class : '');
                if (null !== $file) {
                    $c->attr['file'] = $file;
                    $c->attr['line'] = $line;
                }
            }
            $c->attr['lang'] = $lang;
            $srcLines[\sprintf("\x00~separator=› &%d\x00", $i + $line - $srcContext)] = $c;
        }
        return new EnumStub($srcLines);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\VarDumper\Caster;

/**
 * Represents an uninitialized property.
 *
 * @author Nicolas Grekas <p@tchwork.com>
 */
class UninitializedStub extends ConstStub
{
    public function __construct(\ReflectionProperty $property)
    {
        parent::__construct('?' . ($property->hasType() ? ' ' . $property->getType() : ''), 'Uninitialized property');
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\VarDumper\Caster;

use Ds\Collection;
use Ds\Map;
use Ds\Pair;
use _ContaoManager\Symfony\Component\VarDumper\Cloner\Stub;
/**
 * Casts Ds extension classes to array representation.
 *
 * @author Jáchym Toušek <enumag@gmail.com>
 *
 * @final
 */
class DsCaster
{
    public static function castCollection(Collection $c, array $a, Stub $stub, bool $isNested): array
    {
        $a[Caster::PREFIX_VIRTUAL . 'count'] = $c->count();
        $a[Caster::PREFIX_VIRTUAL . 'capacity'] = $c->capacity();
        if (!$c instanceof Map) {
            $a += $c->toArray();
        }
        return $a;
    }
    public static function castMap(Map $c, array $a, Stub $stub, bool $isNested): array
    {
        foreach ($c as $k => $v) {
            $a[] = new DsPairStub($k, $v);
        }
        return $a;
    }
    public static function castPair(Pair $c, array $a, Stub $stub, bool $isNested): array
    {
        foreach ($c->toArray() as $k => $v) {
            $a[Caster::PREFIX_VIRTUAL . $k] = $v;
        }
        return $a;
    }
    public static function castPairStub(DsPairStub $c, array $a, Stub $stub, bool $isNested): array
    {
        if ($isNested) {
            $stub->class = Pair::class;
            $stub->value = null;
            $stub->handle = 0;
            $a = $c->value;
        }
        return $a;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\VarDumper\Caster;

/**
 * Represents a file or a URL.
 *
 * @author Nicolas Grekas <p@tchwork.com>
 */
class LinkStub extends ConstStub
{
    public $inVendor = \false;
    private static array $vendorRoots;
    private static array $composerRoots = [];
    public function __construct(string $label, int $line = 0, ?string $href = null)
    {
        $this->value = $label;
        if (!\is_string($href ??= $label)) {
            return;
        }
        if (str_starts_with($href, 'file://')) {
            if ($href === $label) {
                $label = substr($label, 7);
            }
            $href = substr($href, 7);
        } elseif (str_contains($href, '://')) {
            $this->attr['href'] = $href;
            return;
        }
        if (!is_file($href)) {
            return;
        }
        if ($line) {
            $this->attr['line'] = $line;
        }
        if ($label !== $this->attr['file'] = realpath($href) ?: $href) {
            return;
        }
        if ($composerRoot = $this->getComposerRoot($href, $this->inVendor)) {
            $this->attr['ellipsis'] = \strlen($href) - \strlen($composerRoot) + 1;
            $this->attr['ellipsis-type'] = 'path';
            $this->attr['ellipsis-tail'] = 1 + ($this->inVendor ? 2 + \strlen(implode('', \array_slice(explode(\DIRECTORY_SEPARATOR, substr($href, 1 - $this->attr['ellipsis'])), 0, 2))) : 0);
        } elseif (3 < \count($ellipsis = explode(\DIRECTORY_SEPARATOR, $href))) {
            $this->attr['ellipsis'] = 2 + \strlen(implode('', \array_slice($ellipsis, -2)));
            $this->attr['ellipsis-type'] = 'path';
            $this->attr['ellipsis-tail'] = 1;
        }
    }
    private function getComposerRoot(string $file, bool &$inVendor): string|false
    {
        if (!isset(self::$vendorRoots)) {
            self::$vendorRoots = [];
            foreach (get_declared_classes() as $class) {
                if ('C' === $class[0] && str_starts_with($class, 'ComposerAutoloaderInit')) {
                    $r = new \ReflectionClass($class);
                    $v = \dirname($r->getFileName(), 2);
                    if (is_file($v . '/composer/installed.json')) {
                        self::$vendorRoots[] = $v . \DIRECTORY_SEPARATOR;
                    }
                }
            }
        }
        $inVendor = \false;
        if (isset(self::$composerRoots[$dir = \dirname($file)])) {
            return self::$composerRoots[$dir];
        }
        foreach (self::$vendorRoots as $root) {
            if ($inVendor = str_starts_with($file, $root)) {
                return $root;
            }
        }
        $parent = $dir;
        while (!@is_file($parent . '/composer.json')) {
            if (!@file_exists($parent)) {
                // open_basedir restriction in effect
                break;
            }
            if ($parent === \dirname($parent)) {
                return self::$composerRoots[$dir] = \false;
            }
            $parent = \dirname($parent);
        }
        return self::$composerRoots[$dir] = $parent . \DIRECTORY_SEPARATOR;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\VarDumper\Caster;

use _ContaoManager\Symfony\Component\VarDumper\Cloner\Stub;
/**
 * @author Jan Schädlich <jan.schaedlich@sensiolabs.de>
 *
 * @final
 */
class MemcachedCaster
{
    private static array $optionConstants;
    private static array $defaultOptions;
    /**
     * @return array
     */
    public static function castMemcached(\Memcached $c, array $a, Stub $stub, bool $isNested)
    {
        $a += [Caster::PREFIX_VIRTUAL . 'servers' => $c->getServerList(), Caster::PREFIX_VIRTUAL . 'options' => new EnumStub(self::getNonDefaultOptions($c))];
        return $a;
    }
    private static function getNonDefaultOptions(\Memcached $c): array
    {
        self::$defaultOptions ??= self::discoverDefaultOptions();
        self::$optionConstants ??= self::getOptionConstants();
        $nonDefaultOptions = [];
        foreach (self::$optionConstants as $constantKey => $value) {
            if (self::$defaultOptions[$constantKey] !== $option = $c->getOption($value)) {
                $nonDefaultOptions[$constantKey] = $option;
            }
        }
        return $nonDefaultOptions;
    }
    private static function discoverDefaultOptions(): array
    {
        $defaultMemcached = new \Memcached();
        $defaultMemcached->addServer('127.0.0.1', 11211);
        $defaultOptions = [];
        self::$optionConstants ??= self::getOptionConstants();
        foreach (self::$optionConstants as $constantKey => $value) {
            $defaultOptions[$constantKey] = $defaultMemcached->getOption($value);
        }
        return $defaultOptions;
    }
    private static function getOptionConstants(): array
    {
        $reflectedMemcached = new \ReflectionClass(\Memcached::class);
        $optionConstants = [];
        foreach ($reflectedMemcached->getConstants() as $constantKey => $value) {
            if (str_starts_with($constantKey, 'OPT_')) {
                $optionConstants[$constantKey] = $value;
            }
        }
        return $optionConstants;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\VarDumper\Caster;

use _ContaoManager\Doctrine\Common\Proxy\Proxy as CommonProxy;
use _ContaoManager\Doctrine\ORM\PersistentCollection;
use _ContaoManager\Doctrine\ORM\Proxy\Proxy as OrmProxy;
use _ContaoManager\Symfony\Component\VarDumper\Cloner\Stub;
/**
 * Casts Doctrine related classes to array representation.
 *
 * @author Nicolas Grekas <p@tchwork.com>
 *
 * @final
 */
class DoctrineCaster
{
    /**
     * @return array
     */
    public static function castCommonProxy(CommonProxy $proxy, array $a, Stub $stub, bool $isNested)
    {
        foreach (['__cloner__', '__initializer__'] as $k) {
            if (\array_key_exists($k, $a)) {
                unset($a[$k]);
                ++$stub->cut;
            }
        }
        return $a;
    }
    /**
     * @return array
     */
    public static function castOrmProxy(OrmProxy $proxy, array $a, Stub $stub, bool $isNested)
    {
        foreach (['_entityPersister', '_identifier'] as $k) {
            if (\array_key_exists($k = "\x00Doctrine\\ORM\\Proxy\\Proxy\x00" . $k, $a)) {
                unset($a[$k]);
                ++$stub->cut;
            }
        }
        return $a;
    }
    /**
     * @return array
     */
    public static function castPersistentCollection(PersistentCollection $coll, array $a, Stub $stub, bool $isNested)
    {
        foreach (['snapshot', 'association', 'typeClass'] as $k) {
            if (\array_key_exists($k = "\x00Doctrine\\ORM\\PersistentCollection\x00" . $k, $a)) {
                $a[$k] = new CutStub($a[$k]);
            }
        }
        return $a;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\VarDumper\Caster;

use RdKafka\Conf;
use RdKafka\Exception as RdKafkaException;
use RdKafka\KafkaConsumer;
use RdKafka\Message;
use RdKafka\Metadata\Broker as BrokerMetadata;
use RdKafka\Metadata\Collection as CollectionMetadata;
use RdKafka\Metadata\Partition as PartitionMetadata;
use RdKafka\Metadata\Topic as TopicMetadata;
use RdKafka\Topic;
use RdKafka\TopicConf;
use RdKafka\TopicPartition;
use _ContaoManager\Symfony\Component\VarDumper\Cloner\Stub;
/**
 * Casts RdKafka related classes to array representation.
 *
 * @author Romain Neutron <imprec@gmail.com>
 */
class RdKafkaCaster
{
    /**
     * @return array
     */
    public static function castKafkaConsumer(KafkaConsumer $c, array $a, Stub $stub, bool $isNested)
    {
        $prefix = Caster::PREFIX_VIRTUAL;
        try {
            $assignment = $c->getAssignment();
        } catch (RdKafkaException) {
            $assignment = [];
        }
        $a += [$prefix . 'subscription' => $c->getSubscription(), $prefix . 'assignment' => $assignment];
        $a += self::extractMetadata($c);
        return $a;
    }
    /**
     * @return array
     */
    public static function castTopic(Topic $c, array $a, Stub $stub, bool $isNested)
    {
        $prefix = Caster::PREFIX_VIRTUAL;
        $a += [$prefix . 'name' => $c->getName()];
        return $a;
    }
    /**
     * @return array
     */
    public static function castTopicPartition(TopicPartition $c, array $a)
    {
        $prefix = Caster::PREFIX_VIRTUAL;
        $a += [$prefix . 'offset' => $c->getOffset(), $prefix . 'partition' => $c->getPartition(), $prefix . 'topic' => $c->getTopic()];
        return $a;
    }
    /**
     * @return array
     */
    public static function castMessage(Message $c, array $a, Stub $stub, bool $isNested)
    {
        $prefix = Caster::PREFIX_VIRTUAL;
        $a += [$prefix . 'errstr' => $c->errstr()];
        return $a;
    }
    /**
     * @return array
     */
    public static function castConf(Conf $c, array $a, Stub $stub, bool $isNested)
    {
        $prefix = Caster::PREFIX_VIRTUAL;
        foreach ($c->dump() as $key => $value) {
            $a[$prefix . $key] = $value;
        }
        return $a;
    }
    /**
     * @return array
     */
    public static function castTopicConf(TopicConf $c, array $a, Stub $stub, bool $isNested)
    {
        $prefix = Caster::PREFIX_VIRTUAL;
        foreach ($c->dump() as $key => $value) {
            $a[$prefix . $key] = $value;
        }
        return $a;
    }
    /**
     * @return array
     */
    public static function castRdKafka(\RdKafka $c, array $a, Stub $stub, bool $isNested)
    {
        $prefix = Caster::PREFIX_VIRTUAL;
        $a += [$prefix . 'out_q_len' => $c->getOutQLen()];
        $a += self::extractMetadata($c);
        return $a;
    }
    /**
     * @return array
     */
    public static function castCollectionMetadata(CollectionMetadata $c, array $a, Stub $stub, bool $isNested)
    {
        $a += iterator_to_array($c);
        return $a;
    }
    /**
     * @return array
     */
    public static function castTopicMetadata(TopicMetadata $c, array $a, Stub $stub, bool $isNested)
    {
        $prefix = Caster::PREFIX_VIRTUAL;
        $a += [$prefix . 'name' => $c->getTopic(), $prefix . 'partitions' => $c->getPartitions()];
        return $a;
    }
    /**
     * @return array
     */
    public static function castPartitionMetadata(PartitionMetadata $c, array $a, Stub $stub, bool $isNested)
    {
        $prefix = Caster::PREFIX_VIRTUAL;
        $a += [$prefix . 'id' => $c->getId(), $prefix . 'err' => $c->getErr(), $prefix . 'leader' => $c->getLeader()];
        return $a;
    }
    /**
     * @return array
     */
    public static function castBrokerMetadata(BrokerMetadata $c, array $a, Stub $stub, bool $isNested)
    {
        $prefix = Caster::PREFIX_VIRTUAL;
        $a += [$prefix . 'id' => $c->getId(), $prefix . 'host' => $c->getHost(), $prefix . 'port' => $c->getPort()];
        return $a;
    }
    /**
     * @return array
     */
    private static function extractMetadata(KafkaConsumer|\RdKafka $c)
    {
        $prefix = Caster::PREFIX_VIRTUAL;
        try {
            $m = $c->getMetadata(\true, null, 500);
        } catch (RdKafkaException) {
            return [];
        }
        return [$prefix . 'orig_broker_id' => $m->getOrigBrokerId(), $prefix . 'orig_broker_name' => $m->getOrigBrokerName(), $prefix . 'brokers' => $m->getBrokers(), $prefix . 'topics' => $m->getTopics()];
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\VarDumper\Caster;

use _ContaoManager\Symfony\Component\VarDumper\Cloner\Stub;
/**
 * @author Nicolas Grekas <p@tchwork.com>
 *
 * @internal
 */
final class MysqliCaster
{
    public static function castMysqliDriver(\mysqli_driver $c, array $a, Stub $stub, bool $isNested): array
    {
        foreach ($a as $k => $v) {
            if (isset($c->{$k})) {
                $a[$k] = $c->{$k};
            }
        }
        return $a;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\VarDumper\Caster;

/**
 * @author Grégoire Pineau <lyrixx@lyrixx.info>
 */
class ImgStub extends ConstStub
{
    public function __construct(string $data, string $contentType, string $size = '')
    {
        $this->value = '';
        $this->attr['img-data'] = $data;
        $this->attr['img-size'] = $size;
        $this->attr['content-type'] = $contentType;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\VarDumper\Caster;

use _ContaoManager\Symfony\Component\VarDumper\Cloner\Stub;
/**
 * Represents a PHP class identifier.
 *
 * @author Nicolas Grekas <p@tchwork.com>
 */
class ClassStub extends ConstStub
{
    /**
     * @param string   $identifier A PHP identifier, e.g. a class, method, interface, etc. name
     * @param callable $callable   The callable targeted by the identifier when it is ambiguous or not a real PHP identifier
     */
    public function __construct(string $identifier, callable|array|string|null $callable = null)
    {
        $this->value = $identifier;
        try {
            if (null !== $callable) {
                if ($callable instanceof \Closure) {
                    $r = new \ReflectionFunction($callable);
                } elseif (\is_object($callable)) {
                    $r = [$callable, '__invoke'];
                } elseif (\is_array($callable)) {
                    $r = $callable;
                } elseif (\false !== $i = strpos($callable, '::')) {
                    $r = [substr($callable, 0, $i), substr($callable, 2 + $i)];
                } else {
                    $r = new \ReflectionFunction($callable);
                }
            } elseif (0 < $i = strpos($identifier, '::') ?: strpos($identifier, '->')) {
                $r = [substr($identifier, 0, $i), substr($identifier, 2 + $i)];
            } else {
                $r = new \ReflectionClass($identifier);
            }
            if (\is_array($r)) {
                try {
                    $r = new \ReflectionMethod($r[0], $r[1]);
                } catch (\ReflectionException) {
                    $r = new \ReflectionClass($r[0]);
                }
            }
            if (str_contains($identifier, "@anonymous\x00")) {
                $this->value = $identifier = preg_replace_callback('/[a-zA-Z_\x7f-\xff][\\\\a-zA-Z0-9_\x7f-\xff]*+@anonymous\x00.*?\.php(?:0x?|:[0-9]++\$)?[0-9a-fA-F]++/', fn($m) => class_exists($m[0], \false) ? ((get_parent_class($m[0]) ?: key(class_implements($m[0]))) ?: 'class') . '@anonymous' : $m[0], $identifier);
            }
            if (null !== $callable && $r instanceof \ReflectionFunctionAbstract) {
                $s = ReflectionCaster::castFunctionAbstract($r, [], new Stub(), \true, Caster::EXCLUDE_VERBOSE);
                $s = ReflectionCaster::getSignature($s);
                if (str_ends_with($identifier, '()')) {
                    $this->value = substr_replace($identifier, $s, -2);
                } else {
                    $this->value .= $s;
                }
            }
        } catch (\ReflectionException) {
            return;
        } finally {
            if (0 < $i = strrpos($this->value, '\\')) {
                $this->attr['ellipsis'] = \strlen($this->value) - $i;
                $this->attr['ellipsis-type'] = 'class';
                $this->attr['ellipsis-tail'] = 1;
            }
        }
        if ($f = $r->getFileName()) {
            $this->attr['file'] = $f;
            $this->attr['line'] = $r->getStartLine();
        }
    }
    /**
     * @return mixed
     */
    public static function wrapCallable(mixed $callable)
    {
        if (\is_object($callable) || !\is_callable($callable)) {
            return $callable;
        }
        if (!\is_array($callable)) {
            $callable = new static($callable, $callable);
        } elseif (\is_string($callable[0])) {
            $callable[0] = new static($callable[0], $callable);
        } else {
            $callable[1] = new static($callable[1], $callable);
        }
        return $callable;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\VarDumper\Caster;

use _ContaoManager\Symfony\Component\VarDumper\Cloner\Stub;
/**
 * Represents a backtrace as returned by debug_backtrace() or Exception->getTrace().
 *
 * @author Nicolas Grekas <p@tchwork.com>
 */
class TraceStub extends Stub
{
    public $keepArgs;
    public $sliceOffset;
    public $sliceLength;
    public $numberingOffset;
    public function __construct(array $trace, bool $keepArgs = \true, int $sliceOffset = 0, ?int $sliceLength = null, int $numberingOffset = 0)
    {
        $this->value = $trace;
        $this->keepArgs = $keepArgs;
        $this->sliceOffset = $sliceOffset;
        $this->sliceLength = $sliceLength;
        $this->numberingOffset = $numberingOffset;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\VarDumper\Caster;

/**
 * Represents a cut array.
 *
 * @author Nicolas Grekas <p@tchwork.com>
 */
class CutArrayStub extends CutStub
{
    public $preservedSubset;
    public function __construct(array $value, array $preservedKeys)
    {
        parent::__construct($value);
        $this->preservedSubset = array_intersect_key($value, array_flip($preservedKeys));
        $this->cut -= \count($this->preservedSubset);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\VarDumper\Caster;

use _ContaoManager\Symfony\Component\VarDumper\Cloner\Stub;
/**
 * Casts pgsql resources to array representation.
 *
 * @author Nicolas Grekas <p@tchwork.com>
 *
 * @final
 */
class PgSqlCaster
{
    private const PARAM_CODES = ['server_encoding', 'client_encoding', 'is_superuser', 'session_authorization', 'DateStyle', 'TimeZone', 'IntervalStyle', 'integer_datetimes', 'application_name', 'standard_conforming_strings'];
    private const TRANSACTION_STATUS = [\PGSQL_TRANSACTION_IDLE => 'PGSQL_TRANSACTION_IDLE', \PGSQL_TRANSACTION_ACTIVE => 'PGSQL_TRANSACTION_ACTIVE', \PGSQL_TRANSACTION_INTRANS => 'PGSQL_TRANSACTION_INTRANS', \PGSQL_TRANSACTION_INERROR => 'PGSQL_TRANSACTION_INERROR', \PGSQL_TRANSACTION_UNKNOWN => 'PGSQL_TRANSACTION_UNKNOWN'];
    private const RESULT_STATUS = [\PGSQL_EMPTY_QUERY => 'PGSQL_EMPTY_QUERY', \PGSQL_COMMAND_OK => 'PGSQL_COMMAND_OK', \PGSQL_TUPLES_OK => 'PGSQL_TUPLES_OK', \PGSQL_COPY_OUT => 'PGSQL_COPY_OUT', \PGSQL_COPY_IN => 'PGSQL_COPY_IN', \PGSQL_BAD_RESPONSE => 'PGSQL_BAD_RESPONSE', \PGSQL_NONFATAL_ERROR => 'PGSQL_NONFATAL_ERROR', \PGSQL_FATAL_ERROR => 'PGSQL_FATAL_ERROR'];
    private const DIAG_CODES = ['severity' => \PGSQL_DIAG_SEVERITY, 'sqlstate' => \PGSQL_DIAG_SQLSTATE, 'message' => \PGSQL_DIAG_MESSAGE_PRIMARY, 'detail' => \PGSQL_DIAG_MESSAGE_DETAIL, 'hint' => \PGSQL_DIAG_MESSAGE_HINT, 'statement position' => \PGSQL_DIAG_STATEMENT_POSITION, 'internal position' => \PGSQL_DIAG_INTERNAL_POSITION, 'internal query' => \PGSQL_DIAG_INTERNAL_QUERY, 'context' => \PGSQL_DIAG_CONTEXT, 'file' => \PGSQL_DIAG_SOURCE_FILE, 'line' => \PGSQL_DIAG_SOURCE_LINE, 'function' => \PGSQL_DIAG_SOURCE_FUNCTION];
    /**
     * @return array
     */
    public static function castLargeObject($lo, array $a, Stub $stub, bool $isNested)
    {
        $a['seek position'] = pg_lo_tell($lo);
        return $a;
    }
    /**
     * @return array
     */
    public static function castLink($link, array $a, Stub $stub, bool $isNested)
    {
        $a['status'] = pg_connection_status($link);
        $a['status'] = new ConstStub(\PGSQL_CONNECTION_OK === $a['status'] ? 'PGSQL_CONNECTION_OK' : 'PGSQL_CONNECTION_BAD', $a['status']);
        $a['busy'] = pg_connection_busy($link);
        $a['transaction'] = pg_transaction_status($link);
        if (isset(self::TRANSACTION_STATUS[$a['transaction']])) {
            $a['transaction'] = new ConstStub(self::TRANSACTION_STATUS[$a['transaction']], $a['transaction']);
        }
        $a['pid'] = pg_get_pid($link);
        $a['last error'] = pg_last_error($link);
        $a['last notice'] = pg_last_notice($link);
        $a['host'] = pg_host($link);
        $a['port'] = pg_port($link);
        $a['dbname'] = pg_dbname($link);
        $a['options'] = pg_options($link);
        $a['version'] = pg_version($link);
        foreach (self::PARAM_CODES as $v) {
            if (\false !== $s = pg_parameter_status($link, $v)) {
                $a['param'][$v] = $s;
            }
        }
        $a['param']['client_encoding'] = pg_client_encoding($link);
        $a['param'] = new EnumStub($a['param']);
        return $a;
    }
    /**
     * @return array
     */
    public static function castResult($result, array $a, Stub $stub, bool $isNested)
    {
        $a['num rows'] = pg_num_rows($result);
        $a['status'] = pg_result_status($result);
        if (isset(self::RESULT_STATUS[$a['status']])) {
            $a['status'] = new ConstStub(self::RESULT_STATUS[$a['status']], $a['status']);
        }
        $a['command-completion tag'] = pg_result_status($result, \PGSQL_STATUS_STRING);
        if (-1 === $a['num rows']) {
            foreach (self::DIAG_CODES as $k => $v) {
                $a['error'][$k] = pg_result_error_field($result, $v);
            }
        }
        $a['affected rows'] = pg_affected_rows($result);
        $a['last OID'] = pg_last_oid($result);
        $fields = pg_num_fields($result);
        for ($i = 0; $i < $fields; ++$i) {
            $field = ['name' => pg_field_name($result, $i), 'table' => \sprintf('%s (OID: %s)', pg_field_table($result, $i), pg_field_table($result, $i, \true)), 'type' => \sprintf('%s (OID: %s)', pg_field_type($result, $i), pg_field_type_oid($result, $i)), 'nullable' => (bool) (\PHP_VERSION_ID >= 80300 ? pg_field_is_null($result, null, $i) : pg_field_is_null($result, $i)), 'storage' => pg_field_size($result, $i) . ' bytes', 'display' => (\PHP_VERSION_ID >= 80300 ? pg_field_prtlen($result, null, $i) : pg_field_prtlen($result, $i)) . ' chars'];
            if (' (OID: )' === $field['table']) {
                $field['table'] = null;
            }
            if ('-1 bytes' === $field['storage']) {
                $field['storage'] = 'variable size';
            } elseif ('1 bytes' === $field['storage']) {
                $field['storage'] = '1 byte';
            }
            if ('1 chars' === $field['display']) {
                $field['display'] = '1 char';
            }
            $a['fields'][] = new EnumStub($field);
        }
        return $a;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\VarDumper\Caster;

use _ContaoManager\Symfony\Component\VarDumper\Cloner\Stub;
/**
 * Helper for filtering out properties in casters.
 *
 * @author Nicolas Grekas <p@tchwork.com>
 *
 * @final
 */
class Caster
{
    public const EXCLUDE_VERBOSE = 1;
    public const EXCLUDE_VIRTUAL = 2;
    public const EXCLUDE_DYNAMIC = 4;
    public const EXCLUDE_PUBLIC = 8;
    public const EXCLUDE_PROTECTED = 16;
    public const EXCLUDE_PRIVATE = 32;
    public const EXCLUDE_NULL = 64;
    public const EXCLUDE_EMPTY = 128;
    public const EXCLUDE_NOT_IMPORTANT = 256;
    public const EXCLUDE_STRICT = 512;
    public const EXCLUDE_UNINITIALIZED = 1024;
    public const PREFIX_VIRTUAL = "\x00~\x00";
    public const PREFIX_DYNAMIC = "\x00+\x00";
    public const PREFIX_PROTECTED = "\x00*\x00";
    // usage: sprintf(Caster::PATTERN_PRIVATE, $class, $property)
    public const PATTERN_PRIVATE = "\x00%s\x00%s";
    private static array $classProperties = [];
    /**
     * Casts objects to arrays and adds the dynamic property prefix.
     *
     * @param bool $hasDebugInfo Whether the __debugInfo method exists on $obj or not
     */
    public static function castObject(object $obj, string $class, bool $hasDebugInfo = \false, ?string $debugClass = null): array
    {
        if ($hasDebugInfo) {
            try {
                $debugInfo = $obj->__debugInfo();
            } catch (\Throwable) {
                // ignore failing __debugInfo()
                $hasDebugInfo = \false;
            }
        }
        $a = $obj instanceof \Closure ? [] : (array) $obj;
        if ($obj instanceof \__PHP_Incomplete_Class) {
            return $a;
        }
        $classProperties = self::$classProperties[$class] ??= self::getClassProperties(new \ReflectionClass($class));
        $a = array_replace($classProperties, $a);
        if ($a) {
            $debugClass ??= get_debug_type($obj);
            $i = 0;
            $prefixedKeys = [];
            foreach ($a as $k => $v) {
                if ("\x00" !== ($k[0] ?? '')) {
                    if (!isset($classProperties[$k])) {
                        $prefixedKeys[$i] = self::PREFIX_DYNAMIC . $k;
                    }
                } elseif ($debugClass !== $class && 1 === strpos($k, $class)) {
                    $prefixedKeys[$i] = "\x00" . $debugClass . strrchr($k, "\x00");
                }
                ++$i;
            }
            if ($prefixedKeys) {
                $keys = array_keys($a);
                foreach ($prefixedKeys as $i => $k) {
                    $keys[$i] = $k;
                }
                $a = array_combine($keys, $a);
            }
        }
        if ($hasDebugInfo && \is_array($debugInfo)) {
            foreach ($debugInfo as $k => $v) {
                if (!isset($k[0]) || "\x00" !== $k[0]) {
                    if (\array_key_exists(self::PREFIX_DYNAMIC . $k, $a)) {
                        continue;
                    }
                    $k = self::PREFIX_VIRTUAL . $k;
                }
                unset($a[$k]);
                $a[$k] = $v;
            }
        }
        return $a;
    }
    /**
     * Filters out the specified properties.
     *
     * By default, a single match in the $filter bit field filters properties out, following an "or" logic.
     * When EXCLUDE_STRICT is set, an "and" logic is applied: all bits must match for a property to be removed.
     *
     * @param array    $a                The array containing the properties to filter
     * @param int      $filter           A bit field of Caster::EXCLUDE_* constants specifying which properties to filter out
     * @param string[] $listedProperties List of properties to exclude when Caster::EXCLUDE_VERBOSE is set, and to preserve when Caster::EXCLUDE_NOT_IMPORTANT is set
     * @param int|null &$count           Set to the number of removed properties
     */
    public static function filter(array $a, int $filter, array $listedProperties = [], ?int &$count = 0): array
    {
        $count = 0;
        foreach ($a as $k => $v) {
            $type = self::EXCLUDE_STRICT & $filter;
            if (null === $v) {
                $type |= self::EXCLUDE_NULL & $filter;
                $type |= self::EXCLUDE_EMPTY & $filter;
            } elseif (\false === $v || '' === $v || '0' === $v || 0 === $v || 0.0 === $v || [] === $v) {
                $type |= self::EXCLUDE_EMPTY & $filter;
            } elseif ($v instanceof UninitializedStub) {
                $type |= self::EXCLUDE_UNINITIALIZED & $filter;
            }
            if (self::EXCLUDE_NOT_IMPORTANT & $filter && !\in_array($k, $listedProperties, \true)) {
                $type |= self::EXCLUDE_NOT_IMPORTANT;
            }
            if (self::EXCLUDE_VERBOSE & $filter && \in_array($k, $listedProperties, \true)) {
                $type |= self::EXCLUDE_VERBOSE;
            }
            if (!isset($k[1]) || "\x00" !== $k[0]) {
                $type |= self::EXCLUDE_PUBLIC & $filter;
            } elseif ('~' === $k[1]) {
                $type |= self::EXCLUDE_VIRTUAL & $filter;
            } elseif ('+' === $k[1]) {
                $type |= self::EXCLUDE_DYNAMIC & $filter;
            } elseif ('*' === $k[1]) {
                $type |= self::EXCLUDE_PROTECTED & $filter;
            } else {
                $type |= self::EXCLUDE_PRIVATE & $filter;
            }
            if (self::EXCLUDE_STRICT & $filter ? $type === $filter : $type) {
                unset($a[$k]);
                ++$count;
            }
        }
        return $a;
    }
    public static function castPhpIncompleteClass(\__PHP_Incomplete_Class $c, array $a, Stub $stub, bool $isNested): array
    {
        if (isset($a['__PHP_Incomplete_Class_Name'])) {
            $stub->class .= '(' . $a['__PHP_Incomplete_Class_Name'] . ')';
            unset($a['__PHP_Incomplete_Class_Name']);
        }
        return $a;
    }
    private static function getClassProperties(\ReflectionClass $class): array
    {
        $classProperties = [];
        $className = $class->name;
        if ($parent = $class->getParentClass()) {
            $classProperties += self::$classProperties[$parent->name] ??= self::getClassProperties($parent);
        }
        foreach ($class->getProperties() as $p) {
            if ($p->isStatic()) {
                continue;
            }
            $classProperties[match (\true) {
                $p->isPublic() => $p->name,
                $p->isProtected() => self::PREFIX_PROTECTED . $p->name,
                default => "\x00" . $className . "\x00" . $p->name,
            }] = new UninitializedStub($p);
        }
        return $classProperties;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\VarDumper\Caster;

use _ContaoManager\Symfony\Component\VarDumper\Cloner\Stub;
/**
 * Casts SPL related classes to array representation.
 *
 * @author Nicolas Grekas <p@tchwork.com>
 *
 * @final
 */
class SplCaster
{
    private const SPL_FILE_OBJECT_FLAGS = [\SplFileObject::DROP_NEW_LINE => 'DROP_NEW_LINE', \SplFileObject::READ_AHEAD => 'READ_AHEAD', \SplFileObject::SKIP_EMPTY => 'SKIP_EMPTY', \SplFileObject::READ_CSV => 'READ_CSV'];
    /**
     * @return array
     */
    public static function castArrayObject(\ArrayObject $c, array $a, Stub $stub, bool $isNested)
    {
        return self::castSplArray($c, $a, $stub, $isNested);
    }
    /**
     * @return array
     */
    public static function castArrayIterator(\ArrayIterator $c, array $a, Stub $stub, bool $isNested)
    {
        return self::castSplArray($c, $a, $stub, $isNested);
    }
    /**
     * @return array
     */
    public static function castHeap(\Iterator $c, array $a, Stub $stub, bool $isNested)
    {
        $a += [Caster::PREFIX_VIRTUAL . 'heap' => iterator_to_array(clone $c)];
        return $a;
    }
    /**
     * @return array
     */
    public static function castDoublyLinkedList(\SplDoublyLinkedList $c, array $a, Stub $stub, bool $isNested)
    {
        $prefix = Caster::PREFIX_VIRTUAL;
        $mode = $c->getIteratorMode();
        $c->setIteratorMode(\SplDoublyLinkedList::IT_MODE_KEEP | $mode & ~\SplDoublyLinkedList::IT_MODE_DELETE);
        $a += [$prefix . 'mode' => new ConstStub(($mode & \SplDoublyLinkedList::IT_MODE_LIFO ? 'IT_MODE_LIFO' : 'IT_MODE_FIFO') . ' | ' . ($mode & \SplDoublyLinkedList::IT_MODE_DELETE ? 'IT_MODE_DELETE' : 'IT_MODE_KEEP'), $mode), $prefix . 'dllist' => iterator_to_array($c)];
        $c->setIteratorMode($mode);
        return $a;
    }
    /**
     * @return array
     */
    public static function castFileInfo(\SplFileInfo $c, array $a, Stub $stub, bool $isNested)
    {
        static $map = ['path' => 'getPath', 'filename' => 'getFilename', 'basename' => 'getBasename', 'pathname' => 'getPathname', 'extension' => 'getExtension', 'realPath' => 'getRealPath', 'aTime' => 'getATime', 'mTime' => 'getMTime', 'cTime' => 'getCTime', 'inode' => 'getInode', 'size' => 'getSize', 'perms' => 'getPerms', 'owner' => 'getOwner', 'group' => 'getGroup', 'type' => 'getType', 'writable' => 'isWritable', 'readable' => 'isReadable', 'executable' => 'isExecutable', 'file' => 'isFile', 'dir' => 'isDir', 'link' => 'isLink', 'linkTarget' => 'getLinkTarget'];
        $prefix = Caster::PREFIX_VIRTUAL;
        unset($a["\x00SplFileInfo\x00fileName"]);
        unset($a["\x00SplFileInfo\x00pathName"]);
        try {
            $c->isReadable();
        } catch (\RuntimeException $e) {
            if ('Object not initialized' !== $e->getMessage()) {
                throw $e;
            }
            $a[$prefix . '⚠'] = 'The parent constructor was not called: the object is in an invalid state';
            return $a;
        } catch (\Error $e) {
            if ('Object not initialized' !== $e->getMessage()) {
                throw $e;
            }
            $a[$prefix . '⚠'] = 'The parent constructor was not called: the object is in an invalid state';
            return $a;
        }
        foreach ($map as $key => $accessor) {
            try {
                $a[$prefix . $key] = $c->{$accessor}();
            } catch (\Exception) {
            }
        }
        if ($a[$prefix . 'realPath'] ?? \false) {
            $a[$prefix . 'realPath'] = new LinkStub($a[$prefix . 'realPath']);
        }
        if (isset($a[$prefix . 'perms'])) {
            $a[$prefix . 'perms'] = new ConstStub(\sprintf('0%o', $a[$prefix . 'perms']), $a[$prefix . 'perms']);
        }
        static $mapDate = ['aTime', 'mTime', 'cTime'];
        foreach ($mapDate as $key) {
            if (isset($a[$prefix . $key])) {
                $a[$prefix . $key] = new ConstStub(date('Y-m-d H:i:s', $a[$prefix . $key]), $a[$prefix . $key]);
            }
        }
        return $a;
    }
    /**
     * @return array
     */
    public static function castFileObject(\SplFileObject $c, array $a, Stub $stub, bool $isNested)
    {
        static $map = ['csvControl' => 'getCsvControl', 'flags' => 'getFlags', 'maxLineLen' => 'getMaxLineLen', 'fstat' => 'fstat', 'eof' => 'eof', 'key' => 'key'];
        $prefix = Caster::PREFIX_VIRTUAL;
        foreach ($map as $key => $accessor) {
            try {
                $a[$prefix . $key] = $c->{$accessor}();
            } catch (\Exception) {
            }
        }
        if (isset($a[$prefix . 'flags'])) {
            $flagsArray = [];
            foreach (self::SPL_FILE_OBJECT_FLAGS as $value => $name) {
                if ($a[$prefix . 'flags'] & $value) {
                    $flagsArray[] = $name;
                }
            }
            $a[$prefix . 'flags'] = new ConstStub(implode('|', $flagsArray), $a[$prefix . 'flags']);
        }
        if (isset($a[$prefix . 'fstat'])) {
            $a[$prefix . 'fstat'] = new CutArrayStub($a[$prefix . 'fstat'], ['dev', 'ino', 'nlink', 'rdev', 'blksize', 'blocks']);
        }
        return $a;
    }
    /**
     * @return array
     */
    public static function castObjectStorage(\SplObjectStorage $c, array $a, Stub $stub, bool $isNested)
    {
        $storage = [];
        unset($a[Caster::PREFIX_DYNAMIC . "\x00gcdata"]);
        // Don't hit https://bugs.php.net/65967
        unset($a["\x00SplObjectStorage\x00storage"]);
        $clone = clone $c;
        foreach ($clone as $obj) {
            $storage[] = new EnumStub(['object' => $obj, 'info' => $clone->getInfo()]);
        }
        $a += [Caster::PREFIX_VIRTUAL . 'storage' => $storage];
        return $a;
    }
    /**
     * @return array
     */
    public static function castOuterIterator(\OuterIterator $c, array $a, Stub $stub, bool $isNested)
    {
        $a[Caster::PREFIX_VIRTUAL . 'innerIterator'] = $c->getInnerIterator();
        return $a;
    }
    /**
     * @return array
     */
    public static function castWeakReference(\WeakReference $c, array $a, Stub $stub, bool $isNested)
    {
        $a[Caster::PREFIX_VIRTUAL . 'object'] = $c->get();
        return $a;
    }
    /**
     * @return array
     */
    public static function castWeakMap(\WeakMap $c, array $a, Stub $stub, bool $isNested)
    {
        $map = [];
        foreach (clone $c as $obj => $data) {
            $map[] = new EnumStub(['object' => $obj, 'data' => $data]);
        }
        $a += [Caster::PREFIX_VIRTUAL . 'map' => $map];
        return $a;
    }
    private static function castSplArray(\ArrayObject|\ArrayIterator $c, array $a, Stub $stub, bool $isNested): array
    {
        $prefix = Caster::PREFIX_VIRTUAL;
        $flags = $c->getFlags();
        if (!($flags & \ArrayObject::STD_PROP_LIST)) {
            $c->setFlags(\ArrayObject::STD_PROP_LIST);
            $a = Caster::castObject($c, $c::class, method_exists($c, '__debugInfo'), $stub->class);
            $c->setFlags($flags);
        }
        unset($a["\x00ArrayObject\x00storage"], $a["\x00ArrayIterator\x00storage"]);
        $a += [$prefix . 'storage' => $c->getArrayCopy(), $prefix . 'flag::STD_PROP_LIST' => (bool) ($flags & \ArrayObject::STD_PROP_LIST), $prefix . 'flag::ARRAY_AS_PROPS' => (bool) ($flags & \ArrayObject::ARRAY_AS_PROPS)];
        if ($c instanceof \ArrayObject) {
            $a[$prefix . 'iteratorClass'] = new ClassStub($c->getIteratorClass());
        }
        return $a;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\VarDumper\Caster;

use _ContaoManager\Symfony\Component\VarDumper\Cloner\Stub;
/**
 * Represents a PHP constant and its value.
 *
 * @author Nicolas Grekas <p@tchwork.com>
 */
class ConstStub extends Stub
{
    public function __construct(string $name, string|int|float|null $value = null)
    {
        $this->class = $name;
        $this->value = 1 < \func_num_args() ? $value : $name;
    }
    public function __toString(): string
    {
        return (string) $this->value;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\VarDumper\Caster;

use _ContaoManager\Symfony\Component\VarDumper\Cloner\Stub;
/**
 * Represents any arbitrary value.
 *
 * @author Alexandre Daubois <alex.daubois@gmail.com>
 */
class ScalarStub extends Stub
{
    public function __construct(mixed $value)
    {
        $this->value = $value;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\VarDumper\Caster;

use _ContaoManager\Symfony\Component\VarDumper\Cloner\Stub;
/**
 * @author Nicolas Grekas <p@tchwork.com>
 */
class DsPairStub extends Stub
{
    public function __construct(mixed $key, mixed $value)
    {
        $this->value = [Caster::PREFIX_VIRTUAL . 'key' => $key, Caster::PREFIX_VIRTUAL . 'value' => $value];
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\VarDumper\Caster;

use _ContaoManager\Symfony\Component\VarDumper\Cloner\Stub;
/**
 * @author Nicolas Grekas <p@tchwork.com>
 * @author Jan Schädlich <jan.schaedlich@sensiolabs.de>
 *
 * @final
 */
class IntlCaster
{
    /**
     * @return array
     */
    public static function castMessageFormatter(\MessageFormatter $c, array $a, Stub $stub, bool $isNested)
    {
        $a += [Caster::PREFIX_VIRTUAL . 'locale' => $c->getLocale(), Caster::PREFIX_VIRTUAL . 'pattern' => $c->getPattern()];
        return self::castError($c, $a);
    }
    /**
     * @return array
     */
    public static function castNumberFormatter(\NumberFormatter $c, array $a, Stub $stub, bool $isNested, int $filter = 0)
    {
        $a += [Caster::PREFIX_VIRTUAL . 'locale' => $c->getLocale(), Caster::PREFIX_VIRTUAL . 'pattern' => $c->getPattern()];
        if ($filter & Caster::EXCLUDE_VERBOSE) {
            $stub->cut += 3;
            return self::castError($c, $a);
        }
        $a += [Caster::PREFIX_VIRTUAL . 'attributes' => new EnumStub(['PARSE_INT_ONLY' => $c->getAttribute(\NumberFormatter::PARSE_INT_ONLY), 'GROUPING_USED' => $c->getAttribute(\NumberFormatter::GROUPING_USED), 'DECIMAL_ALWAYS_SHOWN' => $c->getAttribute(\NumberFormatter::DECIMAL_ALWAYS_SHOWN), 'MAX_INTEGER_DIGITS' => $c->getAttribute(\NumberFormatter::MAX_INTEGER_DIGITS), 'MIN_INTEGER_DIGITS' => $c->getAttribute(\NumberFormatter::MIN_INTEGER_DIGITS), 'INTEGER_DIGITS' => $c->getAttribute(\NumberFormatter::INTEGER_DIGITS), 'MAX_FRACTION_DIGITS' => $c->getAttribute(\NumberFormatter::MAX_FRACTION_DIGITS), 'MIN_FRACTION_DIGITS' => $c->getAttribute(\NumberFormatter::MIN_FRACTION_DIGITS), 'FRACTION_DIGITS' => $c->getAttribute(\NumberFormatter::FRACTION_DIGITS), 'MULTIPLIER' => $c->getAttribute(\NumberFormatter::MULTIPLIER), 'GROUPING_SIZE' => $c->getAttribute(\NumberFormatter::GROUPING_SIZE), 'ROUNDING_MODE' => $c->getAttribute(\NumberFormatter::ROUNDING_MODE), 'ROUNDING_INCREMENT' => $c->getAttribute(\NumberFormatter::ROUNDING_INCREMENT), 'FORMAT_WIDTH' => $c->getAttribute(\NumberFormatter::FORMAT_WIDTH), 'PADDING_POSITION' => $c->getAttribute(\NumberFormatter::PADDING_POSITION), 'SECONDARY_GROUPING_SIZE' => $c->getAttribute(\NumberFormatter::SECONDARY_GROUPING_SIZE), 'SIGNIFICANT_DIGITS_USED' => $c->getAttribute(\NumberFormatter::SIGNIFICANT_DIGITS_USED), 'MIN_SIGNIFICANT_DIGITS' => $c->getAttribute(\NumberFormatter::MIN_SIGNIFICANT_DIGITS), 'MAX_SIGNIFICANT_DIGITS' => $c->getAttribute(\NumberFormatter::MAX_SIGNIFICANT_DIGITS), 'LENIENT_PARSE' => $c->getAttribute(\NumberFormatter::LENIENT_PARSE)]), Caster::PREFIX_VIRTUAL . 'text_attributes' => new EnumStub(['POSITIVE_PREFIX' => $c->getTextAttribute(\NumberFormatter::POSITIVE_PREFIX), 'POSITIVE_SUFFIX' => $c->getTextAttribute(\NumberFormatter::POSITIVE_SUFFIX), 'NEGATIVE_PREFIX' => $c->getTextAttribute(\NumberFormatter::NEGATIVE_PREFIX), 'NEGATIVE_SUFFIX' => $c->getTextAttribute(\NumberFormatter::NEGATIVE_SUFFIX), 'PADDING_CHARACTER' => $c->getTextAttribute(\NumberFormatter::PADDING_CHARACTER), 'CURRENCY_CODE' => $c->getTextAttribute(\NumberFormatter::CURRENCY_CODE), 'DEFAULT_RULESET' => $c->getTextAttribute(\NumberFormatter::DEFAULT_RULESET), 'PUBLIC_RULESETS' => $c->getTextAttribute(\NumberFormatter::PUBLIC_RULESETS)]), Caster::PREFIX_VIRTUAL . 'symbols' => new EnumStub(['DECIMAL_SEPARATOR_SYMBOL' => $c->getSymbol(\NumberFormatter::DECIMAL_SEPARATOR_SYMBOL), 'GROUPING_SEPARATOR_SYMBOL' => $c->getSymbol(\NumberFormatter::GROUPING_SEPARATOR_SYMBOL), 'PATTERN_SEPARATOR_SYMBOL' => $c->getSymbol(\NumberFormatter::PATTERN_SEPARATOR_SYMBOL), 'PERCENT_SYMBOL' => $c->getSymbol(\NumberFormatter::PERCENT_SYMBOL), 'ZERO_DIGIT_SYMBOL' => $c->getSymbol(\NumberFormatter::ZERO_DIGIT_SYMBOL), 'DIGIT_SYMBOL' => $c->getSymbol(\NumberFormatter::DIGIT_SYMBOL), 'MINUS_SIGN_SYMBOL' => $c->getSymbol(\NumberFormatter::MINUS_SIGN_SYMBOL), 'PLUS_SIGN_SYMBOL' => $c->getSymbol(\NumberFormatter::PLUS_SIGN_SYMBOL), 'CURRENCY_SYMBOL' => $c->getSymbol(\NumberFormatter::CURRENCY_SYMBOL), 'INTL_CURRENCY_SYMBOL' => $c->getSymbol(\NumberFormatter::INTL_CURRENCY_SYMBOL), 'MONETARY_SEPARATOR_SYMBOL' => $c->getSymbol(\NumberFormatter::MONETARY_SEPARATOR_SYMBOL), 'EXPONENTIAL_SYMBOL' => $c->getSymbol(\NumberFormatter::EXPONENTIAL_SYMBOL), 'PERMILL_SYMBOL' => $c->getSymbol(\NumberFormatter::PERMILL_SYMBOL), 'PAD_ESCAPE_SYMBOL' => $c->getSymbol(\NumberFormatter::PAD_ESCAPE_SYMBOL), 'INFINITY_SYMBOL' => $c->getSymbol(\NumberFormatter::INFINITY_SYMBOL), 'NAN_SYMBOL' => $c->getSymbol(\NumberFormatter::NAN_SYMBOL), 'SIGNIFICANT_DIGIT_SYMBOL' => $c->getSymbol(\NumberFormatter::SIGNIFICANT_DIGIT_SYMBOL), 'MONETARY_GROUPING_SEPARATOR_SYMBOL' => $c->getSymbol(\NumberFormatter::MONETARY_GROUPING_SEPARATOR_SYMBOL)])];
        return self::castError($c, $a);
    }
    /**
     * @return array
     */
    public static function castIntlTimeZone(\IntlTimeZone $c, array $a, Stub $stub, bool $isNested)
    {
        $a += [Caster::PREFIX_VIRTUAL . 'display_name' => $c->getDisplayName(), Caster::PREFIX_VIRTUAL . 'id' => $c->getID(), Caster::PREFIX_VIRTUAL . 'raw_offset' => $c->getRawOffset()];
        if ($c->useDaylightTime()) {
            $a += [Caster::PREFIX_VIRTUAL . 'dst_savings' => $c->getDSTSavings()];
        }
        return self::castError($c, $a);
    }
    /**
     * @return array
     */
    public static function castIntlCalendar(\IntlCalendar $c, array $a, Stub $stub, bool $isNested, int $filter = 0)
    {
        $a += [Caster::PREFIX_VIRTUAL . 'type' => $c->getType(), Caster::PREFIX_VIRTUAL . 'first_day_of_week' => $c->getFirstDayOfWeek(), Caster::PREFIX_VIRTUAL . 'minimal_days_in_first_week' => $c->getMinimalDaysInFirstWeek(), Caster::PREFIX_VIRTUAL . 'repeated_wall_time_option' => $c->getRepeatedWallTimeOption(), Caster::PREFIX_VIRTUAL . 'skipped_wall_time_option' => $c->getSkippedWallTimeOption(), Caster::PREFIX_VIRTUAL . 'time' => $c->getTime(), Caster::PREFIX_VIRTUAL . 'in_daylight_time' => $c->inDaylightTime(), Caster::PREFIX_VIRTUAL . 'is_lenient' => $c->isLenient(), Caster::PREFIX_VIRTUAL . 'time_zone' => $filter & Caster::EXCLUDE_VERBOSE ? new CutStub($c->getTimeZone()) : $c->getTimeZone()];
        return self::castError($c, $a);
    }
    /**
     * @return array
     */
    public static function castIntlDateFormatter(\IntlDateFormatter $c, array $a, Stub $stub, bool $isNested, int $filter = 0)
    {
        $a += [Caster::PREFIX_VIRTUAL . 'locale' => $c->getLocale(), Caster::PREFIX_VIRTUAL . 'pattern' => $c->getPattern(), Caster::PREFIX_VIRTUAL . 'calendar' => $c->getCalendar(), Caster::PREFIX_VIRTUAL . 'time_zone_id' => $c->getTimeZoneId(), Caster::PREFIX_VIRTUAL . 'time_type' => $c->getTimeType(), Caster::PREFIX_VIRTUAL . 'date_type' => $c->getDateType(), Caster::PREFIX_VIRTUAL . 'calendar_object' => $filter & Caster::EXCLUDE_VERBOSE ? new CutStub($c->getCalendarObject()) : $c->getCalendarObject(), Caster::PREFIX_VIRTUAL . 'time_zone' => $filter & Caster::EXCLUDE_VERBOSE ? new CutStub($c->getTimeZone()) : $c->getTimeZone()];
        return self::castError($c, $a);
    }
    private static function castError(object $c, array $a): array
    {
        if ($errorCode = $c->getErrorCode()) {
            $a += [Caster::PREFIX_VIRTUAL . 'error_code' => $errorCode, Caster::PREFIX_VIRTUAL . 'error_message' => $c->getErrorMessage()];
        }
        return $a;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\VarDumper\Caster;

use Relay\Relay;
use _ContaoManager\Symfony\Component\VarDumper\Cloner\Stub;
/**
 * Casts Redis class from ext-redis to array representation.
 *
 * @author Nicolas Grekas <p@tchwork.com>
 *
 * @final
 */
class RedisCaster
{
    private const SERIALIZERS = [
        0 => 'NONE',
        // Redis::SERIALIZER_NONE
        1 => 'PHP',
        // Redis::SERIALIZER_PHP
        2 => 'IGBINARY',
    ];
    private const MODES = [
        0 => 'ATOMIC',
        // Redis::ATOMIC
        1 => 'MULTI',
        // Redis::MULTI
        2 => 'PIPELINE',
    ];
    private const COMPRESSION_MODES = [
        0 => 'NONE',
        // Redis::COMPRESSION_NONE
        1 => 'LZF',
    ];
    private const FAILOVER_OPTIONS = [\RedisCluster::FAILOVER_NONE => 'NONE', \RedisCluster::FAILOVER_ERROR => 'ERROR', \RedisCluster::FAILOVER_DISTRIBUTE => 'DISTRIBUTE', \RedisCluster::FAILOVER_DISTRIBUTE_SLAVES => 'DISTRIBUTE_SLAVES'];
    /**
     * @return array
     */
    public static function castRedis(\Redis|Relay $c, array $a, Stub $stub, bool $isNested)
    {
        $prefix = Caster::PREFIX_VIRTUAL;
        if (!$connected = $c->isConnected()) {
            return $a + [$prefix . 'isConnected' => $connected];
        }
        $mode = $c->getMode();
        return $a + [$prefix . 'isConnected' => $connected, $prefix . 'host' => $c->getHost(), $prefix . 'port' => $c->getPort(), $prefix . 'auth' => $c->getAuth(), $prefix . 'mode' => isset(self::MODES[$mode]) ? new ConstStub(self::MODES[$mode], $mode) : $mode, $prefix . 'dbNum' => $c->getDbNum(), $prefix . 'timeout' => $c->getTimeout(), $prefix . 'lastError' => $c->getLastError(), $prefix . 'persistentId' => $c->getPersistentID(), $prefix . 'options' => self::getRedisOptions($c)];
    }
    /**
     * @return array
     */
    public static function castRedisArray(\RedisArray $c, array $a, Stub $stub, bool $isNested)
    {
        $prefix = Caster::PREFIX_VIRTUAL;
        return $a + [$prefix . 'hosts' => $c->_hosts(), $prefix . 'function' => ClassStub::wrapCallable($c->_function()), $prefix . 'lastError' => $c->getLastError(), $prefix . 'options' => self::getRedisOptions($c)];
    }
    /**
     * @return array
     */
    public static function castRedisCluster(\RedisCluster $c, array $a, Stub $stub, bool $isNested)
    {
        $prefix = Caster::PREFIX_VIRTUAL;
        $failover = $c->getOption(\RedisCluster::OPT_SLAVE_FAILOVER);
        $a += [$prefix . '_masters' => $c->_masters(), $prefix . '_redir' => $c->_redir(), $prefix . 'mode' => new ConstStub($c->getMode() ? 'MULTI' : 'ATOMIC', $c->getMode()), $prefix . 'lastError' => $c->getLastError(), $prefix . 'options' => self::getRedisOptions($c, ['SLAVE_FAILOVER' => isset(self::FAILOVER_OPTIONS[$failover]) ? new ConstStub(self::FAILOVER_OPTIONS[$failover], $failover) : $failover])];
        return $a;
    }
    private static function getRedisOptions(\Redis|Relay|\RedisArray|\RedisCluster $redis, array $options = []): EnumStub
    {
        $serializer = $redis->getOption(\defined('Redis::OPT_SERIALIZER') ? \Redis::OPT_SERIALIZER : 1);
        if (\is_array($serializer)) {
            foreach ($serializer as &$v) {
                if (isset(self::SERIALIZERS[$v])) {
                    $v = new ConstStub(self::SERIALIZERS[$v], $v);
                }
            }
        } elseif (isset(self::SERIALIZERS[$serializer])) {
            $serializer = new ConstStub(self::SERIALIZERS[$serializer], $serializer);
        }
        $compression = \defined('Redis::OPT_COMPRESSION') ? $redis->getOption(\Redis::OPT_COMPRESSION) : 0;
        if (\is_array($compression)) {
            foreach ($compression as &$v) {
                if (isset(self::COMPRESSION_MODES[$v])) {
                    $v = new ConstStub(self::COMPRESSION_MODES[$v], $v);
                }
            }
        } elseif (isset(self::COMPRESSION_MODES[$compression])) {
            $compression = new ConstStub(self::COMPRESSION_MODES[$compression], $compression);
        }
        $retry = \defined('Redis::OPT_SCAN') ? $redis->getOption(\Redis::OPT_SCAN) : 0;
        if (\is_array($retry)) {
            foreach ($retry as &$v) {
                $v = new ConstStub($v ? 'RETRY' : 'NORETRY', $v);
            }
        } else {
            $retry = new ConstStub($retry ? 'RETRY' : 'NORETRY', $retry);
        }
        $options += ['TCP_KEEPALIVE' => \defined('Redis::OPT_TCP_KEEPALIVE') ? $redis->getOption(\Redis::OPT_TCP_KEEPALIVE) : Relay::OPT_TCP_KEEPALIVE, 'READ_TIMEOUT' => $redis->getOption(\defined('Redis::OPT_READ_TIMEOUT') ? \Redis::OPT_READ_TIMEOUT : Relay::OPT_READ_TIMEOUT), 'COMPRESSION' => $compression, 'SERIALIZER' => $serializer, 'PREFIX' => $redis->getOption(\defined('Redis::OPT_PREFIX') ? \Redis::OPT_PREFIX : Relay::OPT_PREFIX), 'SCAN' => $retry];
        return new EnumStub($options);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\VarDumper\Caster;

use _ContaoManager\Symfony\Component\VarDumper\Cloner\Stub;
/**
 * Casts Fiber related classes to array representation.
 *
 * @author Grégoire Pineau <lyrixx@lyrixx.info>
 */
final class FiberCaster
{
    /**
     * @return array
     */
    public static function castFiber(\Fiber $fiber, array $a, Stub $stub, bool $isNested, int $filter = 0)
    {
        $prefix = Caster::PREFIX_VIRTUAL;
        if ($fiber->isTerminated()) {
            $status = 'terminated';
        } elseif ($fiber->isRunning()) {
            $status = 'running';
        } elseif ($fiber->isSuspended()) {
            $status = 'suspended';
        } elseif ($fiber->isStarted()) {
            $status = 'started';
        } else {
            $status = 'not started';
        }
        $a[$prefix . 'status'] = $status;
        return $a;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\VarDumper\Caster;

use _ContaoManager\Imagine\Image\ImageInterface;
use _ContaoManager\Symfony\Component\VarDumper\Cloner\Stub;
/**
 * @author Grégoire Pineau <lyrixx@lyrixx.info>
 */
final class ImagineCaster
{
    public static function castImage(ImageInterface $c, array $a, Stub $stub, bool $isNested): array
    {
        $imgData = $c->get('png');
        if (\strlen($imgData) > 1 * 1000 * 1000) {
            $a += [Caster::PREFIX_VIRTUAL . 'image' => new ConstStub($c->getSize())];
        } else {
            $a += [Caster::PREFIX_VIRTUAL . 'image' => new ImgStub($imgData, 'image/png', $c->getSize())];
        }
        return $a;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\VarDumper\Caster;

use _ContaoManager\Symfony\Component\VarDumper\Cloner\Stub;
/**
 * Casts Amqp related classes to array representation.
 *
 * @author Grégoire Pineau <lyrixx@lyrixx.info>
 *
 * @final
 */
class AmqpCaster
{
    private const FLAGS = [\AMQP_DURABLE => 'AMQP_DURABLE', \AMQP_PASSIVE => 'AMQP_PASSIVE', \AMQP_EXCLUSIVE => 'AMQP_EXCLUSIVE', \AMQP_AUTODELETE => 'AMQP_AUTODELETE', \AMQP_INTERNAL => 'AMQP_INTERNAL', \AMQP_NOLOCAL => 'AMQP_NOLOCAL', \AMQP_AUTOACK => 'AMQP_AUTOACK', \AMQP_IFEMPTY => 'AMQP_IFEMPTY', \AMQP_IFUNUSED => 'AMQP_IFUNUSED', \AMQP_MANDATORY => 'AMQP_MANDATORY', \AMQP_IMMEDIATE => 'AMQP_IMMEDIATE', \AMQP_MULTIPLE => 'AMQP_MULTIPLE', \AMQP_NOWAIT => 'AMQP_NOWAIT', \AMQP_REQUEUE => 'AMQP_REQUEUE'];
    private const EXCHANGE_TYPES = [\AMQP_EX_TYPE_DIRECT => 'AMQP_EX_TYPE_DIRECT', \AMQP_EX_TYPE_FANOUT => 'AMQP_EX_TYPE_FANOUT', \AMQP_EX_TYPE_TOPIC => 'AMQP_EX_TYPE_TOPIC', \AMQP_EX_TYPE_HEADERS => 'AMQP_EX_TYPE_HEADERS'];
    /**
     * @return array
     */
    public static function castConnection(\AMQPConnection $c, array $a, Stub $stub, bool $isNested)
    {
        $prefix = Caster::PREFIX_VIRTUAL;
        $a += [$prefix . 'is_connected' => $c->isConnected()];
        // Recent version of the extension already expose private properties
        if (isset($a["\x00AMQPConnection\x00login"])) {
            return $a;
        }
        // BC layer in the amqp lib
        if (method_exists($c, 'getReadTimeout')) {
            $timeout = $c->getReadTimeout();
        } else {
            $timeout = $c->getTimeout();
        }
        $a += [$prefix . 'is_connected' => $c->isConnected(), $prefix . 'login' => $c->getLogin(), $prefix . 'password' => $c->getPassword(), $prefix . 'host' => $c->getHost(), $prefix . 'vhost' => $c->getVhost(), $prefix . 'port' => $c->getPort(), $prefix . 'read_timeout' => $timeout];
        return $a;
    }
    /**
     * @return array
     */
    public static function castChannel(\AMQPChannel $c, array $a, Stub $stub, bool $isNested)
    {
        $prefix = Caster::PREFIX_VIRTUAL;
        $a += [$prefix . 'is_connected' => $c->isConnected(), $prefix . 'channel_id' => $c->getChannelId()];
        // Recent version of the extension already expose private properties
        if (isset($a["\x00AMQPChannel\x00connection"])) {
            return $a;
        }
        $a += [$prefix . 'connection' => $c->getConnection(), $prefix . 'prefetch_size' => $c->getPrefetchSize(), $prefix . 'prefetch_count' => $c->getPrefetchCount()];
        return $a;
    }
    /**
     * @return array
     */
    public static function castQueue(\AMQPQueue $c, array $a, Stub $stub, bool $isNested)
    {
        $prefix = Caster::PREFIX_VIRTUAL;
        $a += [$prefix . 'flags' => self::extractFlags($c->getFlags())];
        // Recent version of the extension already expose private properties
        if (isset($a["\x00AMQPQueue\x00name"])) {
            return $a;
        }
        $a += [$prefix . 'connection' => $c->getConnection(), $prefix . 'channel' => $c->getChannel(), $prefix . 'name' => $c->getName(), $prefix . 'arguments' => $c->getArguments()];
        return $a;
    }
    /**
     * @return array
     */
    public static function castExchange(\AMQPExchange $c, array $a, Stub $stub, bool $isNested)
    {
        $prefix = Caster::PREFIX_VIRTUAL;
        $a += [$prefix . 'flags' => self::extractFlags($c->getFlags())];
        $type = isset(self::EXCHANGE_TYPES[$c->getType()]) ? new ConstStub(self::EXCHANGE_TYPES[$c->getType()], $c->getType()) : $c->getType();
        // Recent version of the extension already expose private properties
        if (isset($a["\x00AMQPExchange\x00name"])) {
            $a["\x00AMQPExchange\x00type"] = $type;
            return $a;
        }
        $a += [$prefix . 'connection' => $c->getConnection(), $prefix . 'channel' => $c->getChannel(), $prefix . 'name' => $c->getName(), $prefix . 'type' => $type, $prefix . 'arguments' => $c->getArguments()];
        return $a;
    }
    /**
     * @return array
     */
    public static function castEnvelope(\AMQPEnvelope $c, array $a, Stub $stub, bool $isNested, int $filter = 0)
    {
        $prefix = Caster::PREFIX_VIRTUAL;
        $deliveryMode = new ConstStub($c->getDeliveryMode() . (2 === $c->getDeliveryMode() ? ' (persistent)' : ' (non-persistent)'), $c->getDeliveryMode());
        // Recent version of the extension already expose private properties
        if (isset($a["\x00AMQPEnvelope\x00body"])) {
            $a["\x00AMQPEnvelope\x00delivery_mode"] = $deliveryMode;
            return $a;
        }
        if (!($filter & Caster::EXCLUDE_VERBOSE)) {
            $a += [$prefix . 'body' => $c->getBody()];
        }
        $a += [$prefix . 'delivery_tag' => $c->getDeliveryTag(), $prefix . 'is_redelivery' => $c->isRedelivery(), $prefix . 'exchange_name' => $c->getExchangeName(), $prefix . 'routing_key' => $c->getRoutingKey(), $prefix . 'content_type' => $c->getContentType(), $prefix . 'content_encoding' => $c->getContentEncoding(), $prefix . 'headers' => $c->getHeaders(), $prefix . 'delivery_mode' => $deliveryMode, $prefix . 'priority' => $c->getPriority(), $prefix . 'correlation_id' => $c->getCorrelationId(), $prefix . 'reply_to' => $c->getReplyTo(), $prefix . 'expiration' => $c->getExpiration(), $prefix . 'message_id' => $c->getMessageId(), $prefix . 'timestamp' => $c->getTimeStamp(), $prefix . 'type' => $c->getType(), $prefix . 'user_id' => $c->getUserId(), $prefix . 'app_id' => $c->getAppId()];
        return $a;
    }
    private static function extractFlags(int $flags): ConstStub
    {
        $flagsArray = [];
        foreach (self::FLAGS as $value => $name) {
            if ($flags & $value) {
                $flagsArray[] = $name;
            }
        }
        if (!$flagsArray) {
            $flagsArray = ['AMQP_NOPARAM'];
        }
        return new ConstStub(implode('|', $flagsArray), $flags);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\VarDumper\Caster;

use _ContaoManager\Symfony\Component\VarDumper\Cloner\Stub;
/**
 * Casts DOM related classes to array representation.
 *
 * @author Nicolas Grekas <p@tchwork.com>
 *
 * @final
 */
class DOMCaster
{
    private const ERROR_CODES = [0 => 'DOM_PHP_ERR', \DOM_INDEX_SIZE_ERR => 'DOM_INDEX_SIZE_ERR', \DOMSTRING_SIZE_ERR => 'DOMSTRING_SIZE_ERR', \DOM_HIERARCHY_REQUEST_ERR => 'DOM_HIERARCHY_REQUEST_ERR', \DOM_WRONG_DOCUMENT_ERR => 'DOM_WRONG_DOCUMENT_ERR', \DOM_INVALID_CHARACTER_ERR => 'DOM_INVALID_CHARACTER_ERR', \DOM_NO_DATA_ALLOWED_ERR => 'DOM_NO_DATA_ALLOWED_ERR', \DOM_NO_MODIFICATION_ALLOWED_ERR => 'DOM_NO_MODIFICATION_ALLOWED_ERR', \DOM_NOT_FOUND_ERR => 'DOM_NOT_FOUND_ERR', \DOM_NOT_SUPPORTED_ERR => 'DOM_NOT_SUPPORTED_ERR', \DOM_INUSE_ATTRIBUTE_ERR => 'DOM_INUSE_ATTRIBUTE_ERR', \DOM_INVALID_STATE_ERR => 'DOM_INVALID_STATE_ERR', \DOM_SYNTAX_ERR => 'DOM_SYNTAX_ERR', \DOM_INVALID_MODIFICATION_ERR => 'DOM_INVALID_MODIFICATION_ERR', \DOM_NAMESPACE_ERR => 'DOM_NAMESPACE_ERR', \DOM_INVALID_ACCESS_ERR => 'DOM_INVALID_ACCESS_ERR', \DOM_VALIDATION_ERR => 'DOM_VALIDATION_ERR'];
    private const NODE_TYPES = [\XML_ELEMENT_NODE => 'XML_ELEMENT_NODE', \XML_ATTRIBUTE_NODE => 'XML_ATTRIBUTE_NODE', \XML_TEXT_NODE => 'XML_TEXT_NODE', \XML_CDATA_SECTION_NODE => 'XML_CDATA_SECTION_NODE', \XML_ENTITY_REF_NODE => 'XML_ENTITY_REF_NODE', \XML_ENTITY_NODE => 'XML_ENTITY_NODE', \XML_PI_NODE => 'XML_PI_NODE', \XML_COMMENT_NODE => 'XML_COMMENT_NODE', \XML_DOCUMENT_NODE => 'XML_DOCUMENT_NODE', \XML_DOCUMENT_TYPE_NODE => 'XML_DOCUMENT_TYPE_NODE', \XML_DOCUMENT_FRAG_NODE => 'XML_DOCUMENT_FRAG_NODE', \XML_NOTATION_NODE => 'XML_NOTATION_NODE', \XML_HTML_DOCUMENT_NODE => 'XML_HTML_DOCUMENT_NODE', \XML_DTD_NODE => 'XML_DTD_NODE', \XML_ELEMENT_DECL_NODE => 'XML_ELEMENT_DECL_NODE', \XML_ATTRIBUTE_DECL_NODE => 'XML_ATTRIBUTE_DECL_NODE', \XML_ENTITY_DECL_NODE => 'XML_ENTITY_DECL_NODE', \XML_NAMESPACE_DECL_NODE => 'XML_NAMESPACE_DECL_NODE'];
    /**
     * @return array
     */
    public static function castException(\DOMException $e, array $a, Stub $stub, bool $isNested)
    {
        $k = Caster::PREFIX_PROTECTED . 'code';
        if (isset($a[$k], self::ERROR_CODES[$a[$k]])) {
            $a[$k] = new ConstStub(self::ERROR_CODES[$a[$k]], $a[$k]);
        }
        return $a;
    }
    /**
     * @return array
     */
    public static function castLength($dom, array $a, Stub $stub, bool $isNested)
    {
        $a += ['length' => $dom->length];
        return $a;
    }
    /**
     * @return array
     */
    public static function castImplementation(\DOMImplementation $dom, array $a, Stub $stub, bool $isNested)
    {
        $a += [Caster::PREFIX_VIRTUAL . 'Core' => '1.0', Caster::PREFIX_VIRTUAL . 'XML' => '2.0'];
        return $a;
    }
    /**
     * @return array
     */
    public static function castNode(\DOMNode $dom, array $a, Stub $stub, bool $isNested)
    {
        $a += ['nodeName' => $dom->nodeName, 'nodeValue' => new CutStub($dom->nodeValue), 'nodeType' => new ConstStub(self::NODE_TYPES[$dom->nodeType], $dom->nodeType), 'parentNode' => new CutStub($dom->parentNode), 'childNodes' => $dom->childNodes, 'firstChild' => new CutStub($dom->firstChild), 'lastChild' => new CutStub($dom->lastChild), 'previousSibling' => new CutStub($dom->previousSibling), 'nextSibling' => new CutStub($dom->nextSibling), 'attributes' => $dom->attributes, 'ownerDocument' => new CutStub($dom->ownerDocument), 'namespaceURI' => $dom->namespaceURI, 'prefix' => $dom->prefix, 'localName' => $dom->localName, 'baseURI' => $dom->baseURI ? new LinkStub($dom->baseURI) : $dom->baseURI, 'textContent' => new CutStub($dom->textContent)];
        return $a;
    }
    /**
     * @return array
     */
    public static function castNameSpaceNode(\DOMNameSpaceNode $dom, array $a, Stub $stub, bool $isNested)
    {
        $a += ['nodeName' => $dom->nodeName, 'nodeValue' => new CutStub($dom->nodeValue), 'nodeType' => new ConstStub(self::NODE_TYPES[$dom->nodeType], $dom->nodeType), 'prefix' => $dom->prefix, 'localName' => $dom->localName, 'namespaceURI' => $dom->namespaceURI, 'ownerDocument' => new CutStub($dom->ownerDocument), 'parentNode' => new CutStub($dom->parentNode)];
        return $a;
    }
    /**
     * @return array
     */
    public static function castDocument(\DOMDocument $dom, array $a, Stub $stub, bool $isNested, int $filter = 0)
    {
        $a += ['doctype' => $dom->doctype, 'implementation' => $dom->implementation, 'documentElement' => new CutStub($dom->documentElement), 'encoding' => $dom->encoding, 'xmlEncoding' => $dom->xmlEncoding, 'xmlStandalone' => $dom->xmlStandalone, 'xmlVersion' => $dom->xmlVersion, 'strictErrorChecking' => $dom->strictErrorChecking, 'documentURI' => $dom->documentURI ? new LinkStub($dom->documentURI) : $dom->documentURI, 'formatOutput' => $dom->formatOutput, 'validateOnParse' => $dom->validateOnParse, 'resolveExternals' => $dom->resolveExternals, 'preserveWhiteSpace' => $dom->preserveWhiteSpace, 'recover' => $dom->recover, 'substituteEntities' => $dom->substituteEntities];
        if (!($filter & Caster::EXCLUDE_VERBOSE)) {
            $formatOutput = $dom->formatOutput;
            $dom->formatOutput = \true;
            $a += [Caster::PREFIX_VIRTUAL . 'xml' => $dom->saveXML()];
            $dom->formatOutput = $formatOutput;
        }
        return $a;
    }
    /**
     * @return array
     */
    public static function castCharacterData(\DOMCharacterData $dom, array $a, Stub $stub, bool $isNested)
    {
        $a += ['data' => $dom->data, 'length' => $dom->length];
        return $a;
    }
    /**
     * @return array
     */
    public static function castAttr(\DOMAttr $dom, array $a, Stub $stub, bool $isNested)
    {
        $a += ['name' => $dom->name, 'specified' => $dom->specified, 'value' => $dom->value, 'ownerElement' => $dom->ownerElement, 'schemaTypeInfo' => $dom->schemaTypeInfo];
        return $a;
    }
    /**
     * @return array
     */
    public static function castElement(\DOMElement $dom, array $a, Stub $stub, bool $isNested)
    {
        $a += ['tagName' => $dom->tagName, 'schemaTypeInfo' => $dom->schemaTypeInfo];
        return $a;
    }
    /**
     * @return array
     */
    public static function castText(\DOMText $dom, array $a, Stub $stub, bool $isNested)
    {
        $a += ['wholeText' => $dom->wholeText];
        return $a;
    }
    /**
     * @return array
     */
    public static function castDocumentType(\DOMDocumentType $dom, array $a, Stub $stub, bool $isNested)
    {
        $a += ['name' => $dom->name, 'entities' => $dom->entities, 'notations' => $dom->notations, 'publicId' => $dom->publicId, 'systemId' => $dom->systemId, 'internalSubset' => $dom->internalSubset];
        return $a;
    }
    /**
     * @return array
     */
    public static function castNotation(\DOMNotation $dom, array $a, Stub $stub, bool $isNested)
    {
        $a += ['publicId' => $dom->publicId, 'systemId' => $dom->systemId];
        return $a;
    }
    /**
     * @return array
     */
    public static function castEntity(\DOMEntity $dom, array $a, Stub $stub, bool $isNested)
    {
        $a += ['publicId' => $dom->publicId, 'systemId' => $dom->systemId, 'notationName' => $dom->notationName];
        return $a;
    }
    /**
     * @return array
     */
    public static function castProcessingInstruction(\DOMProcessingInstruction $dom, array $a, Stub $stub, bool $isNested)
    {
        $a += ['target' => $dom->target, 'data' => $dom->data];
        return $a;
    }
    /**
     * @return array
     */
    public static function castXPath(\DOMXPath $dom, array $a, Stub $stub, bool $isNested)
    {
        $a += ['document' => $dom->document];
        return $a;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\VarDumper\Caster;

use _ContaoManager\Ramsey\Uuid\UuidInterface;
use _ContaoManager\Symfony\Component\VarDumper\Cloner\Stub;
/**
 * @author Grégoire Pineau <lyrixx@lyrixx.info>
 */
final class UuidCaster
{
    public static function castRamseyUuid(UuidInterface $c, array $a, Stub $stub, bool $isNested): array
    {
        $a += [Caster::PREFIX_VIRTUAL . 'uuid' => (string) $c];
        return $a;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\VarDumper\Caster;

use _ContaoManager\Symfony\Component\VarDumper\Cloner\Stub;
/**
 * Casts XmlReader class to array representation.
 *
 * @author Baptiste Clavié <clavie.b@gmail.com>
 *
 * @final
 */
class XmlReaderCaster
{
    private const NODE_TYPES = [\XMLReader::NONE => 'NONE', \XMLReader::ELEMENT => 'ELEMENT', \XMLReader::ATTRIBUTE => 'ATTRIBUTE', \XMLReader::TEXT => 'TEXT', \XMLReader::CDATA => 'CDATA', \XMLReader::ENTITY_REF => 'ENTITY_REF', \XMLReader::ENTITY => 'ENTITY', \XMLReader::PI => 'PI (Processing Instruction)', \XMLReader::COMMENT => 'COMMENT', \XMLReader::DOC => 'DOC', \XMLReader::DOC_TYPE => 'DOC_TYPE', \XMLReader::DOC_FRAGMENT => 'DOC_FRAGMENT', \XMLReader::NOTATION => 'NOTATION', \XMLReader::WHITESPACE => 'WHITESPACE', \XMLReader::SIGNIFICANT_WHITESPACE => 'SIGNIFICANT_WHITESPACE', \XMLReader::END_ELEMENT => 'END_ELEMENT', \XMLReader::END_ENTITY => 'END_ENTITY', \XMLReader::XML_DECLARATION => 'XML_DECLARATION'];
    /**
     * @return array
     */
    public static function castXmlReader(\XMLReader $reader, array $a, Stub $stub, bool $isNested)
    {
        try {
            $properties = ['LOADDTD' => @$reader->getParserProperty(\XMLReader::LOADDTD), 'DEFAULTATTRS' => @$reader->getParserProperty(\XMLReader::DEFAULTATTRS), 'VALIDATE' => @$reader->getParserProperty(\XMLReader::VALIDATE), 'SUBST_ENTITIES' => @$reader->getParserProperty(\XMLReader::SUBST_ENTITIES)];
        } catch (\Error) {
            $properties = ['LOADDTD' => \false, 'DEFAULTATTRS' => \false, 'VALIDATE' => \false, 'SUBST_ENTITIES' => \false];
        }
        $props = Caster::PREFIX_VIRTUAL . 'parserProperties';
        $info = ['localName' => $reader->localName, 'prefix' => $reader->prefix, 'nodeType' => new ConstStub(self::NODE_TYPES[$reader->nodeType], $reader->nodeType), 'depth' => $reader->depth, 'isDefault' => $reader->isDefault, 'isEmptyElement' => \XMLReader::NONE === $reader->nodeType ? null : $reader->isEmptyElement, 'xmlLang' => $reader->xmlLang, 'attributeCount' => $reader->attributeCount, 'value' => $reader->value, 'namespaceURI' => $reader->namespaceURI, 'baseURI' => $reader->baseURI ? new LinkStub($reader->baseURI) : $reader->baseURI, $props => $properties];
        if ($info[$props] = Caster::filter($info[$props], Caster::EXCLUDE_EMPTY, [], $count)) {
            $info[$props] = new EnumStub($info[$props]);
            $info[$props]->cut = $count;
        }
        $a = Caster::filter($a, Caster::EXCLUDE_UNINITIALIZED, [], $count);
        $info = Caster::filter($info, Caster::EXCLUDE_EMPTY, [], $count);
        // +2 because hasValue and hasAttributes are always filtered
        $stub->cut += $count + 2;
        return $a + $info;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\VarDumper\Caster;

use _ContaoManager\Symfony\Component\VarDumper\Cloner\Stub;
/**
 * Represents a list of function arguments.
 *
 * @author Nicolas Grekas <p@tchwork.com>
 */
class ArgsStub extends EnumStub
{
    private static array $parameters = [];
    public function __construct(array $args, string $function, ?string $class)
    {
        [$variadic, $params] = self::getParameters($function, $class);
        $values = [];
        foreach ($args as $k => $v) {
            $values[$k] = !\is_scalar($v) && !$v instanceof Stub ? new CutStub($v) : $v;
        }
        if (null === $params) {
            parent::__construct($values, \false);
            return;
        }
        if (\count($values) < \count($params)) {
            $params = \array_slice($params, 0, \count($values));
        } elseif (\count($values) > \count($params)) {
            $values[] = new EnumStub(array_splice($values, \count($params)), \false);
            $params[] = $variadic;
        }
        if (['...'] === $params) {
            $this->dumpKeys = \false;
            $this->value = $values[0]->value;
        } else {
            $this->value = array_combine($params, $values);
        }
    }
    private static function getParameters(string $function, ?string $class): array
    {
        if (isset(self::$parameters[$k = $class . '::' . $function])) {
            return self::$parameters[$k];
        }
        try {
            $r = null !== $class ? new \ReflectionMethod($class, $function) : new \ReflectionFunction($function);
        } catch (\ReflectionException) {
            return [null, null];
        }
        $variadic = '...';
        $params = [];
        foreach ($r->getParameters() as $v) {
            $k = '$' . $v->name;
            if ($v->isPassedByReference()) {
                $k = '&' . $k;
            }
            if ($v->isVariadic()) {
                $variadic .= $k;
            } else {
                $params[] = $k;
            }
        }
        return self::$parameters[$k] = [$variadic, $params];
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\VarDumper\Caster;

use _ContaoManager\Symfony\Component\VarDumper\Cloner\Stub;
/**
 * Represents an enumeration of values.
 *
 * @author Nicolas Grekas <p@tchwork.com>
 */
class EnumStub extends Stub
{
    public $dumpKeys = \true;
    public function __construct(array $values, bool $dumpKeys = \true)
    {
        $this->value = $values;
        $this->dumpKeys = $dumpKeys;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\VarDumper\Caster;

use _ContaoManager\Symfony\Component\VarDumper\Cloner\Stub;
/**
 * Represents the main properties of a PHP variable, pre-casted by a caster.
 *
 * @author Nicolas Grekas <p@tchwork.com>
 */
class CutStub extends Stub
{
    public function __construct(mixed $value)
    {
        $this->value = $value;
        switch (\gettype($value)) {
            case 'object':
                $this->type = self::TYPE_OBJECT;
                $this->class = get_debug_type($value);
                if ($value instanceof \Closure) {
                    ReflectionCaster::castClosure($value, [], $this, \true, Caster::EXCLUDE_VERBOSE);
                }
                $this->cut = -1;
                break;
            case 'array':
                $this->type = self::TYPE_ARRAY;
                $this->class = self::ARRAY_ASSOC;
                $this->cut = $this->value = \count($value);
                break;
            case 'resource':
            case 'unknown type':
            case 'resource (closed)':
                $this->type = self::TYPE_RESOURCE;
                $this->handle = (int) $value;
                if ('Unknown' === $this->class = @get_resource_type($value)) {
                    $this->class = 'Closed';
                }
                $this->cut = -1;
                break;
            case 'string':
                $this->type = self::TYPE_STRING;
                $this->class = preg_match('//u', $value) ? self::STRING_UTF8 : self::STRING_BINARY;
                $this->cut = self::STRING_BINARY === $this->class ? \strlen($value) : mb_strlen($value, 'UTF-8');
                $this->value = '';
                break;
        }
    }
}
#!/usr/bin/env php
<?php 
namespace _ContaoManager;

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
if ('cli' !== \PHP_SAPI) {
    throw new \Exception('This script must be run from the command line.');
}
/**
 * Starts a dump server to collect and output dumps on a single place with multiple formats support.
 *
 * @author Maxime Steinhausser <maxime.steinhausser@gmail.com>
 */
use _ContaoManager\Psr\Log\LoggerInterface;
use _ContaoManager\Symfony\Component\Console\Application;
use _ContaoManager\Symfony\Component\Console\Input\ArgvInput;
use _ContaoManager\Symfony\Component\Console\Input\InputOption;
use _ContaoManager\Symfony\Component\Console\Logger\ConsoleLogger;
use _ContaoManager\Symfony\Component\Console\Output\ConsoleOutput;
use _ContaoManager\Symfony\Component\VarDumper\Command\ServerDumpCommand;
use _ContaoManager\Symfony\Component\VarDumper\Server\DumpServer;
function includeIfExists(string $file): bool
{
    return \file_exists($file) && include $file;
}
if (!includeIfExists(__DIR__ . '/../../../../autoload.php') && !includeIfExists(__DIR__ . '/../../vendor/autoload.php') && !includeIfExists(__DIR__ . '/../../../../../../vendor/autoload.php')) {
    \fwrite(\STDERR, 'Install dependencies using Composer.' . \PHP_EOL);
    exit(1);
}
if (!\class_exists(Application::class)) {
    \fwrite(\STDERR, 'You need the "symfony/console" component in order to run the VarDumper server.' . \PHP_EOL);
    exit(1);
}
$input = new ArgvInput();
$output = new ConsoleOutput();
$defaultHost = '127.0.0.1:9912';
$host = $input->getParameterOption(['--host'], $_SERVER['VAR_DUMPER_SERVER'] ?? $defaultHost, \true);
$logger = \interface_exists(LoggerInterface::class) ? new ConsoleLogger($output->getErrorOutput()) : null;
$app = new Application();
$app->getDefinition()->addOption(new InputOption('--host', null, InputOption::VALUE_REQUIRED, 'The address the server should listen to', $defaultHost));
$app->add($command = new ServerDumpCommand(new DumpServer($host, $logger)))->getApplication()->setDefaultCommand($command->getName(), \true)->run($input, $output);
body {
    display: flex;
    flex-direction: column-reverse;
    justify-content: flex-end;
    max-width: 1140px;
    margin: auto;
    padding: 15px;
    word-wrap: break-word;
    background-color: #F9F9F9;
    color: #222;
    font-family: Helvetica, Arial, sans-serif;
    font-size: 14px;
    line-height: 1.4;
}
p {
    margin: 0;
}
a {
    color: #218BC3;
    text-decoration: none;
}
a:hover {
    text-decoration: underline;
}
.text-small {
    font-size: 12px !important;
}
article {
    margin: 5px;
    margin-bottom: 10px;
}
article > header > .row {
    display: flex;
    flex-direction: row;
    align-items: baseline;
    margin-bottom: 10px;
}
article > header > .row > .col {
    flex: 1;
    display: flex;
    align-items: baseline;
}
article > header > .row > h2 {
    font-size: 14px;
    color: #222;
    font-weight: normal;
    font-family: "Lucida Console", monospace, sans-serif;
    word-break: break-all;
    margin: 20px 5px 0 0;
    user-select: all;
}
article > header > .row > h2 > code {
    white-space: nowrap;
    user-select: none;
    color: #cc2255;
    background-color: #f7f7f9;
    border: 1px solid #e1e1e8;
    border-radius: 3px;
    margin-right: 5px;
    padding: 0 3px;
}
article > header > .row > time.col {
    flex: 0;
    text-align: right;
    white-space: nowrap;
    color: #999;
    font-style: italic;
}
article > header ul.tags {
    list-style: none;
    padding: 0;
    margin: 0;
    font-size: 12px;
}
article > header ul.tags > li {
    user-select: all;
    margin-bottom: 2px;
}
article > header ul.tags > li > span.badge {
    display: inline-block;
    padding: .25em .4em;
    margin-right: 5px;
    border-radius: 4px;
    background-color: #6c757d3b;
    color: #524d4d;
    font-size: 12px;
    text-align: center;
    font-weight: 700;
    line-height: 1;
    white-space: nowrap;
    vertical-align: baseline;
    user-select: none;
}
article > section.body {
    border: 1px solid #d8d8d8;
    background: #FFF;
    padding: 10px;
    border-radius: 3px;
}
pre.sf-dump {
    border-radius: 3px;
    margin-bottom: 0;
}
.hidden {
    display: none !important;
}
.dumped-tag > .sf-dump {
    display: inline-block;
    margin: 0;
    padding: 1px 5px;
    line-height: 1.4;
    vertical-align: top;
    background-color: transparent;
    user-select: auto;
}
.dumped-tag > pre.sf-dump,
.dumped-tag > .sf-dump-default {
    color: #CC7832;
    background: none;
}
.dumped-tag > .sf-dump .sf-dump-str { color: #629755; }
.dumped-tag > .sf-dump .sf-dump-private,
.dumped-tag > .sf-dump .sf-dump-protected,
.dumped-tag > .sf-dump .sf-dump-public { color: #262626; }
.dumped-tag > .sf-dump .sf-dump-note { color: #6897BB; }
.dumped-tag > .sf-dump .sf-dump-key { color: #789339; }
.dumped-tag > .sf-dump .sf-dump-ref { color: #6E6E6E; }
.dumped-tag > .sf-dump .sf-dump-ellipsis { color: #CC7832; max-width: 100em; }
.dumped-tag > .sf-dump .sf-dump-ellipsis-path { max-width: 5em; }
.dumped-tag > .sf-dump .sf-dump-ns { user-select: none; }
document.addEventListener('DOMContentLoaded', function() {
  let prev = null;
  Array.from(document.getElementsByTagName('article')).reverse().forEach(function (article) {
    const dedupId = article.dataset.dedupId;
    if (dedupId === prev) {
      article.getElementsByTagName('header')[0].classList.add('hidden');
    }
    prev = dedupId;
  });
});
<?php

namespace _ContaoManager;

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
use _ContaoManager\Symfony\Component\VarDumper\Caster\ScalarStub;
use _ContaoManager\Symfony\Component\VarDumper\VarDumper;
if (!\function_exists('_ContaoManager\dump')) {
    /**
     * @author Nicolas Grekas <p@tchwork.com>
     * @author Alexandre Daubois <alex.daubois@gmail.com>
     */
    function dump(mixed ...$vars): mixed
    {
        if (!$vars) {
            VarDumper::dump(new ScalarStub('🐛'));
            return null;
        }
        if (\array_key_exists(0, $vars) && 1 === \count($vars)) {
            VarDumper::dump($vars[0]);
            $k = 0;
        } else {
            foreach ($vars as $k => $v) {
                VarDumper::dump($v, \is_int($k) ? 1 + $k : $k);
            }
        }
        if (1 < \count($vars)) {
            return $vars;
        }
        return $vars[$k];
    }
}
if (!\function_exists('_ContaoManager\dd')) {
    function dd(mixed ...$vars): never
    {
        if (!\in_array(\PHP_SAPI, ['cli', 'phpdbg', 'embed'], \true) && !\headers_sent()) {
            \header('HTTP/1.1 500 Internal Server Error');
        }
        if (\array_key_exists(0, $vars) && 1 === \count($vars)) {
            VarDumper::dump($vars[0]);
        } else {
            foreach ($vars as $k => $v) {
                VarDumper::dump($v, \is_int($k) ? 1 + $k : $k);
            }
        }
        exit(1);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\VarDumper\Server;

use _ContaoManager\Symfony\Component\VarDumper\Cloner\Data;
use _ContaoManager\Symfony\Component\VarDumper\Dumper\ContextProvider\ContextProviderInterface;
/**
 * Forwards serialized Data clones to a server.
 *
 * @author Maxime Steinhausser <maxime.steinhausser@gmail.com>
 */
class Connection
{
    private string $host;
    private array $contextProviders;
    /**
     * @var resource|null
     */
    private $socket;
    /**
     * @param string                     $host             The server host
     * @param ContextProviderInterface[] $contextProviders Context providers indexed by context name
     */
    public function __construct(string $host, array $contextProviders = [])
    {
        if (!str_contains($host, '://')) {
            $host = 'tcp://' . $host;
        }
        $this->host = $host;
        $this->contextProviders = $contextProviders;
    }
    public function getContextProviders(): array
    {
        return $this->contextProviders;
    }
    public function write(Data $data): bool
    {
        $socketIsFresh = !$this->socket;
        if (!$this->socket = $this->socket ?: $this->createSocket()) {
            return \false;
        }
        $context = ['timestamp' => microtime(\true)];
        foreach ($this->contextProviders as $name => $provider) {
            $context[$name] = $provider->getContext();
        }
        $context = array_filter($context);
        $encodedPayload = base64_encode(serialize([$data, $context])) . "\n";
        set_error_handler(static fn() => null);
        try {
            if (-1 !== stream_socket_sendto($this->socket, $encodedPayload)) {
                return \true;
            }
            if (!$socketIsFresh) {
                stream_socket_shutdown($this->socket, \STREAM_SHUT_RDWR);
                fclose($this->socket);
                $this->socket = $this->createSocket();
            }
            if (-1 !== stream_socket_sendto($this->socket, $encodedPayload)) {
                return \true;
            }
        } finally {
            restore_error_handler();
        }
        return \false;
    }
    /**
     * @return resource|null
     */
    private function createSocket()
    {
        set_error_handler(static fn() => null);
        try {
            return stream_socket_client($this->host, $errno, $errstr, 3) ?: null;
        } finally {
            restore_error_handler();
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\VarDumper\Server;

use _ContaoManager\Psr\Log\LoggerInterface;
use _ContaoManager\Symfony\Component\VarDumper\Cloner\Data;
use _ContaoManager\Symfony\Component\VarDumper\Cloner\Stub;
/**
 * A server collecting Data clones sent by a ServerDumper.
 *
 * @author Maxime Steinhausser <maxime.steinhausser@gmail.com>
 *
 * @final
 */
class DumpServer
{
    private string $host;
    private ?LoggerInterface $logger;
    /**
     * @var resource|null
     */
    private $socket;
    public function __construct(string $host, ?LoggerInterface $logger = null)
    {
        if (!str_contains($host, '://')) {
            $host = 'tcp://' . $host;
        }
        $this->host = $host;
        $this->logger = $logger;
    }
    public function start(): void
    {
        if (!$this->socket = stream_socket_server($this->host, $errno, $errstr)) {
            throw new \RuntimeException(\sprintf('Server start failed on "%s": ', $this->host) . $errstr . ' ' . $errno);
        }
    }
    public function listen(callable $callback): void
    {
        if (null === $this->socket) {
            $this->start();
        }
        foreach ($this->getMessages() as $clientId => $message) {
            $this->logger?->info('Received a payload from client {clientId}', ['clientId' => $clientId]);
            $payload = @unserialize(base64_decode($message), ['allowed_classes' => [Data::class, Stub::class]]);
            // Impossible to decode the message, give up.
            if (\false === $payload) {
                $this->logger?->warning('Unable to decode a message from {clientId} client.', ['clientId' => $clientId]);
                continue;
            }
            if (!\is_array($payload) || \count($payload) < 2 || !$payload[0] instanceof Data || !\is_array($payload[1])) {
                $this->logger?->warning('Invalid payload from {clientId} client. Expected an array of two elements (Data $data, array $context)', ['clientId' => $clientId]);
                continue;
            }
            [$data, $context] = $payload;
            $callback($data, $context, $clientId);
        }
    }
    public function getHost(): string
    {
        return $this->host;
    }
    private function getMessages(): iterable
    {
        $sockets = [(int) $this->socket => $this->socket];
        $write = [];
        while (\true) {
            $read = $sockets;
            stream_select($read, $write, $write, null);
            foreach ($read as $stream) {
                if ($this->socket === $stream) {
                    $stream = stream_socket_accept($this->socket);
                    $sockets[(int) $stream] = $stream;
                } elseif (feof($stream)) {
                    unset($sockets[(int) $stream]);
                    fclose($stream);
                } else {
                    yield (int) $stream => fgets($stream);
                }
            }
        }
    }
}
VarDumper Component
===================

The VarDumper component provides mechanisms for walking through any arbitrary
PHP variable. It provides a better `dump()` function that you can use instead
of `var_dump()`.

Resources
---------

 * [Documentation](https://symfony.com/doc/current/components/var_dumper/introduction.html)
 * [Contributing](https://symfony.com/doc/current/contributing/index.html)
 * [Report issues](https://github.com/symfony/symfony/issues) and
   [send Pull Requests](https://github.com/symfony/symfony/pulls)
   in the [main Symfony repository](https://github.com/symfony/symfony)
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\VarDumper\Command;

use _ContaoManager\Symfony\Component\Console\Attribute\AsCommand;
use _ContaoManager\Symfony\Component\Console\Command\Command;
use _ContaoManager\Symfony\Component\Console\Completion\CompletionInput;
use _ContaoManager\Symfony\Component\Console\Completion\CompletionSuggestions;
use _ContaoManager\Symfony\Component\Console\Exception\InvalidArgumentException;
use _ContaoManager\Symfony\Component\Console\Input\InputInterface;
use _ContaoManager\Symfony\Component\Console\Input\InputOption;
use _ContaoManager\Symfony\Component\Console\Output\OutputInterface;
use _ContaoManager\Symfony\Component\Console\Style\SymfonyStyle;
use _ContaoManager\Symfony\Component\VarDumper\Cloner\Data;
use _ContaoManager\Symfony\Component\VarDumper\Command\Descriptor\CliDescriptor;
use _ContaoManager\Symfony\Component\VarDumper\Command\Descriptor\DumpDescriptorInterface;
use _ContaoManager\Symfony\Component\VarDumper\Command\Descriptor\HtmlDescriptor;
use _ContaoManager\Symfony\Component\VarDumper\Dumper\CliDumper;
use _ContaoManager\Symfony\Component\VarDumper\Dumper\HtmlDumper;
use _ContaoManager\Symfony\Component\VarDumper\Server\DumpServer;
/**
 * Starts a dump server to collect and output dumps on a single place with multiple formats support.
 *
 * @author Maxime Steinhausser <maxime.steinhausser@gmail.com>
 *
 * @final
 */
#[AsCommand(name: 'server:dump', description: 'Start a dump server that collects and displays dumps in a single place')]
class ServerDumpCommand extends Command
{
    private DumpServer $server;
    /** @var DumpDescriptorInterface[] */
    private array $descriptors;
    public function __construct(DumpServer $server, array $descriptors = [])
    {
        $this->server = $server;
        $this->descriptors = $descriptors + ['cli' => new CliDescriptor(new CliDumper()), 'html' => new HtmlDescriptor(new HtmlDumper())];
        parent::__construct();
    }
    protected function configure(): void
    {
        $this->addOption('format', null, InputOption::VALUE_REQUIRED, \sprintf('The output format (%s)', implode(', ', $this->getAvailableFormats())), 'cli')->setHelp(<<<'EOF'
<info>%command.name%</info> starts a dump server that collects and displays
dumps in a single place for debugging you application:

  <info>php %command.full_name%</info>

You can consult dumped data in HTML format in your browser by providing the <comment>--format=html</comment> option
and redirecting the output to a file:

  <info>php %command.full_name% --format="html" > dump.html</info>

EOF
);
    }
    protected function execute(InputInterface $input, OutputInterface $output): int
    {
        $io = new SymfonyStyle($input, $output);
        $format = $input->getOption('format');
        if (!$descriptor = $this->descriptors[$format] ?? null) {
            throw new InvalidArgumentException(\sprintf('Unsupported format "%s".', $format));
        }
        $errorIo = $io->getErrorStyle();
        $errorIo->title('Symfony Var Dumper Server');
        $this->server->start();
        $errorIo->success(\sprintf('Server listening on %s', $this->server->getHost()));
        $errorIo->comment('Quit the server with CONTROL-C.');
        $this->server->listen(function (Data $data, array $context, int $clientId) use ($descriptor, $io) {
            $descriptor->describe($io, $data, $context, $clientId);
        });
        return 0;
    }
    public function complete(CompletionInput $input, CompletionSuggestions $suggestions): void
    {
        if ($input->mustSuggestOptionValuesFor('format')) {
            $suggestions->suggestValues($this->getAvailableFormats());
        }
    }
    private function getAvailableFormats(): array
    {
        return array_keys($this->descriptors);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\VarDumper\Command\Descriptor;

use _ContaoManager\Symfony\Component\Console\Output\OutputInterface;
use _ContaoManager\Symfony\Component\VarDumper\Cloner\Data;
/**
 * @author Maxime Steinhausser <maxime.steinhausser@gmail.com>
 */
interface DumpDescriptorInterface
{
    public function describe(OutputInterface $output, Data $data, array $context, int $clientId): void;
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\VarDumper\Command\Descriptor;

use _ContaoManager\Symfony\Component\Console\Input\ArrayInput;
use _ContaoManager\Symfony\Component\Console\Output\OutputInterface;
use _ContaoManager\Symfony\Component\Console\Style\SymfonyStyle;
use _ContaoManager\Symfony\Component\VarDumper\Cloner\Data;
use _ContaoManager\Symfony\Component\VarDumper\Dumper\CliDumper;
/**
 * Describe collected data clones for cli output.
 *
 * @author Maxime Steinhausser <maxime.steinhausser@gmail.com>
 *
 * @final
 */
class CliDescriptor implements DumpDescriptorInterface
{
    private CliDumper $dumper;
    private mixed $lastIdentifier = null;
    public function __construct(CliDumper $dumper)
    {
        $this->dumper = $dumper;
    }
    public function describe(OutputInterface $output, Data $data, array $context, int $clientId): void
    {
        $io = $output instanceof SymfonyStyle ? $output : new SymfonyStyle(new ArrayInput([]), $output);
        $this->dumper->setColors($output->isDecorated());
        $rows = [['date', date('r', (int) $context['timestamp'])]];
        $lastIdentifier = $this->lastIdentifier;
        $this->lastIdentifier = $clientId;
        $section = "Received from client #{$clientId}";
        if (isset($context['request'])) {
            $request = $context['request'];
            $this->lastIdentifier = $request['identifier'];
            $section = \sprintf('%s %s', $request['method'], $request['uri']);
            if ($controller = $request['controller']) {
                $rows[] = ['controller', rtrim($this->dumper->dump($controller, \true), "\n")];
            }
        } elseif (isset($context['cli'])) {
            $this->lastIdentifier = $context['cli']['identifier'];
            $section = '$ ' . $context['cli']['command_line'];
        }
        if ($this->lastIdentifier !== $lastIdentifier) {
            $io->section($section);
        }
        if (isset($context['source'])) {
            $source = $context['source'];
            $sourceInfo = \sprintf('%s on line %d', $source['name'], $source['line']);
            if ($fileLink = $source['file_link'] ?? null) {
                $sourceInfo = \sprintf('<href=%s>%s</>', $fileLink, $sourceInfo);
            }
            $rows[] = ['source', $sourceInfo];
            $file = $source['file_relative'] ?? $source['file'];
            $rows[] = ['file', $file];
        }
        $io->table([], $rows);
        $this->dumper->dump($data);
        $io->newLine();
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\VarDumper\Command\Descriptor;

use _ContaoManager\Symfony\Component\Console\Output\OutputInterface;
use _ContaoManager\Symfony\Component\VarDumper\Cloner\Data;
use _ContaoManager\Symfony\Component\VarDumper\Dumper\HtmlDumper;
/**
 * Describe collected data clones for html output.
 *
 * @author Maxime Steinhausser <maxime.steinhausser@gmail.com>
 *
 * @final
 */
class HtmlDescriptor implements DumpDescriptorInterface
{
    private HtmlDumper $dumper;
    private bool $initialized = \false;
    public function __construct(HtmlDumper $dumper)
    {
        $this->dumper = $dumper;
    }
    public function describe(OutputInterface $output, Data $data, array $context, int $clientId): void
    {
        if (!$this->initialized) {
            $styles = file_get_contents(__DIR__ . '/../../Resources/css/htmlDescriptor.css');
            $scripts = file_get_contents(__DIR__ . '/../../Resources/js/htmlDescriptor.js');
            $output->writeln("<style>{$styles}</style><script>{$scripts}</script>");
            $this->initialized = \true;
        }
        $title = '-';
        if (isset($context['request'])) {
            $request = $context['request'];
            $controller = "<span class='dumped-tag'>{$this->dumper->dump($request['controller'], \true, ['maxDepth' => 0])}</span>";
            $title = \sprintf('<code>%s</code> <a href="%s">%s</a>', $request['method'], $uri = $request['uri'], $uri);
            $dedupIdentifier = $request['identifier'];
        } elseif (isset($context['cli'])) {
            $title = '<code>$ </code>' . $context['cli']['command_line'];
            $dedupIdentifier = $context['cli']['identifier'];
        } else {
            $dedupIdentifier = uniqid('', \true);
        }
        $sourceDescription = '';
        if (isset($context['source'])) {
            $source = $context['source'];
            $projectDir = $source['project_dir'] ?? null;
            $sourceDescription = \sprintf('%s on line %d', $source['name'], $source['line']);
            if (isset($source['file_link'])) {
                $sourceDescription = \sprintf('<a href="%s">%s</a>', $source['file_link'], $sourceDescription);
            }
        }
        $isoDate = $this->extractDate($context, 'c');
        $tags = array_filter(['controller' => $controller ?? null, 'project dir' => $projectDir ?? null]);
        $output->writeln(<<<HTML
<article data-dedup-id="{$dedupIdentifier}">
    <header>
        <div class="row">
            <h2 class="col">{$title}</h2>
            <time class="col text-small" title="{$isoDate}" datetime="{$isoDate}">
                {$this->extractDate($context)}
            </time>
        </div>
        {$this->renderTags($tags)}
    </header>
    <section class="body">
        <p class="text-small">
            {$sourceDescription}
        </p>
        {$this->dumper->dump($data, \true)}
    </section>
</article>
HTML
);
    }
    private function extractDate(array $context, string $format = 'r'): string
    {
        return date($format, (int) $context['timestamp']);
    }
    private function renderTags(array $tags): string
    {
        if (!$tags) {
            return '';
        }
        $renderedTags = '';
        foreach ($tags as $key => $value) {
            $renderedTags .= \sprintf('<li><span class="badge">%s</span>%s</li>', $key, $value);
        }
        return <<<HTML
<div class="row">
    <ul class="tags">
        {$renderedTags}
    </ul>
</div>
HTML;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\VarDumper\Exception;

/**
 * @author Nicolas Grekas <p@tchwork.com>
 */
class ThrowingCasterException extends \Exception
{
    /**
     * @param \Throwable $prev The exception thrown from the caster
     */
    public function __construct(\Throwable $prev)
    {
        parent::__construct('Unexpected ' . $prev::class . ' thrown from a caster: ' . $prev->getMessage(), 0, $prev);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\VarDumper\Dumper;

use _ContaoManager\Symfony\Component\VarDumper\Cloner\Data;
use _ContaoManager\Symfony\Component\VarDumper\Dumper\ContextProvider\ContextProviderInterface;
use _ContaoManager\Symfony\Component\VarDumper\Server\Connection;
/**
 * ServerDumper forwards serialized Data clones to a server.
 *
 * @author Maxime Steinhausser <maxime.steinhausser@gmail.com>
 */
class ServerDumper implements DataDumperInterface
{
    private Connection $connection;
    private ?DataDumperInterface $wrappedDumper;
    /**
     * @param string                     $host             The server host
     * @param DataDumperInterface|null   $wrappedDumper    A wrapped instance used whenever we failed contacting the server
     * @param ContextProviderInterface[] $contextProviders Context providers indexed by context name
     */
    public function __construct(string $host, ?DataDumperInterface $wrappedDumper = null, array $contextProviders = [])
    {
        $this->connection = new Connection($host, $contextProviders);
        $this->wrappedDumper = $wrappedDumper;
    }
    public function getContextProviders(): array
    {
        return $this->connection->getContextProviders();
    }
    /**
     * @return string|null
     */
    public function dump(Data $data)
    {
        if (!$this->connection->write($data) && $this->wrappedDumper) {
            return $this->wrappedDumper->dump($data);
        }
        return null;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\VarDumper\Dumper;

use _ContaoManager\Symfony\Component\VarDumper\Cloner\Data;
/**
 * DataDumperInterface for dumping Data objects.
 *
 * @author Nicolas Grekas <p@tchwork.com>
 */
interface DataDumperInterface
{
    /**
     * @return string|null
     */
    public function dump(Data $data);
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\VarDumper\Dumper\ContextProvider;

/**
 * Interface to provide contextual data about dump data clones sent to a server.
 *
 * @author Maxime Steinhausser <maxime.steinhausser@gmail.com>
 */
interface ContextProviderInterface
{
    public function getContext(): ?array;
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\VarDumper\Dumper\ContextProvider;

use _ContaoManager\Symfony\Component\HttpFoundation\RequestStack;
use _ContaoManager\Symfony\Component\VarDumper\Caster\ReflectionCaster;
use _ContaoManager\Symfony\Component\VarDumper\Cloner\VarCloner;
/**
 * Tries to provide context from a request.
 *
 * @author Maxime Steinhausser <maxime.steinhausser@gmail.com>
 */
final class RequestContextProvider implements ContextProviderInterface
{
    private RequestStack $requestStack;
    private VarCloner $cloner;
    public function __construct(RequestStack $requestStack)
    {
        $this->requestStack = $requestStack;
        $this->cloner = new VarCloner();
        $this->cloner->setMaxItems(0);
        $this->cloner->addCasters(ReflectionCaster::UNSET_CLOSURE_FILE_INFO);
    }
    public function getContext(): ?array
    {
        if (null === $request = $this->requestStack->getCurrentRequest()) {
            return null;
        }
        $controller = $request->attributes->get('_controller');
        return ['uri' => $request->getUri(), 'method' => $request->getMethod(), 'controller' => $controller ? $this->cloner->cloneVar($controller) : $controller, 'identifier' => hash('xxh128', spl_object_id($request) . '@' . $_SERVER['REQUEST_TIME_FLOAT'])];
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\VarDumper\Dumper\ContextProvider;

/**
 * Tries to provide context on CLI.
 *
 * @author Maxime Steinhausser <maxime.steinhausser@gmail.com>
 */
final class CliContextProvider implements ContextProviderInterface
{
    public function getContext(): ?array
    {
        if ('cli' !== \PHP_SAPI) {
            return null;
        }
        return ['command_line' => $commandLine = implode(' ', $_SERVER['argv'] ?? []), 'identifier' => hash('xxh128', $commandLine . '@' . $_SERVER['REQUEST_TIME_FLOAT'])];
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\VarDumper\Dumper\ContextProvider;

use _ContaoManager\Symfony\Component\ErrorHandler\ErrorRenderer\FileLinkFormatter;
use _ContaoManager\Symfony\Component\HttpKernel\Debug\FileLinkFormatter as LegacyFileLinkFormatter;
use _ContaoManager\Symfony\Component\VarDumper\Cloner\VarCloner;
use _ContaoManager\Symfony\Component\VarDumper\Dumper\HtmlDumper;
use _ContaoManager\Symfony\Component\VarDumper\VarDumper;
use _ContaoManager\Twig\Template;
/**
 * Tries to provide context from sources (class name, file, line, code excerpt, ...).
 *
 * @author Nicolas Grekas <p@tchwork.com>
 * @author Maxime Steinhausser <maxime.steinhausser@gmail.com>
 */
final class SourceContextProvider implements ContextProviderInterface
{
    private int $limit;
    private ?string $charset;
    private ?string $projectDir;
    private FileLinkFormatter|LegacyFileLinkFormatter|null $fileLinkFormatter;
    public function __construct(?string $charset = null, ?string $projectDir = null, FileLinkFormatter|LegacyFileLinkFormatter|null $fileLinkFormatter = null, int $limit = 9)
    {
        $this->charset = $charset;
        $this->projectDir = $projectDir;
        $this->fileLinkFormatter = $fileLinkFormatter;
        $this->limit = $limit;
    }
    public function getContext(): ?array
    {
        $trace = debug_backtrace(\DEBUG_BACKTRACE_PROVIDE_OBJECT | \DEBUG_BACKTRACE_IGNORE_ARGS, $this->limit);
        $file = $trace[1]['file'];
        $line = $trace[1]['line'];
        $name = '-' === $file || 'Standard input code' === $file ? 'Standard input code' : \false;
        $fileExcerpt = \false;
        for ($i = 2; $i < $this->limit; ++$i) {
            if (isset($trace[$i]['class'], $trace[$i]['function']) && 'dump' === $trace[$i]['function'] && VarDumper::class === $trace[$i]['class']) {
                $file = $trace[$i]['file'] ?? $file;
                $line = $trace[$i]['line'] ?? $line;
                while (++$i < $this->limit) {
                    if (isset($trace[$i]['function'], $trace[$i]['file']) && empty($trace[$i]['class']) && !str_starts_with($trace[$i]['function'], 'call_user_func')) {
                        $file = $trace[$i]['file'];
                        $line = $trace[$i]['line'];
                        break;
                    } elseif (isset($trace[$i]['object']) && $trace[$i]['object'] instanceof Template) {
                        $template = $trace[$i]['object'];
                        $name = $template->getTemplateName();
                        $src = method_exists($template, 'getSourceContext') ? $template->getSourceContext()->getCode() : (method_exists($template, 'getSource') ? $template->getSource() : \false);
                        $info = $template->getDebugInfo();
                        if (isset($info[$trace[$i - 1]['line']])) {
                            $line = $info[$trace[$i - 1]['line']];
                            $file = method_exists($template, 'getSourceContext') ? $template->getSourceContext()->getPath() : null;
                            if ($src) {
                                $src = explode("\n", $src);
                                $fileExcerpt = [];
                                for ($i = max($line - 3, 1), $max = min($line + 3, \count($src)); $i <= $max; ++$i) {
                                    $fileExcerpt[] = '<li' . ($i === $line ? ' class="selected"' : '') . '><code>' . $this->htmlEncode($src[$i - 1]) . '</code></li>';
                                }
                                $fileExcerpt = '<ol start="' . max($line - 3, 1) . '">' . implode("\n", $fileExcerpt) . '</ol>';
                            }
                        }
                        break;
                    }
                }
                break;
            }
        }
        if (\false === $name) {
            $name = str_replace('\\', '/', $file);
            $name = substr($name, strrpos($name, '/') + 1);
        }
        $context = ['name' => $name, 'file' => $file, 'line' => $line];
        $context['file_excerpt'] = $fileExcerpt;
        if (null !== $this->projectDir) {
            $context['project_dir'] = $this->projectDir;
            if (str_starts_with($file, $this->projectDir)) {
                $context['file_relative'] = ltrim(substr($file, \strlen($this->projectDir)), \DIRECTORY_SEPARATOR);
            }
        }
        if ($this->fileLinkFormatter && $fileLink = $this->fileLinkFormatter->format($context['file'], $context['line'])) {
            $context['file_link'] = $fileLink;
        }
        return $context;
    }
    private function htmlEncode(string $s): string
    {
        $html = '';
        $dumper = new HtmlDumper(function ($line) use (&$html) {
            $html .= $line;
        }, $this->charset);
        $dumper->setDumpHeader('');
        $dumper->setDumpBoundaries('', '');
        $cloner = new VarCloner();
        $dumper->dump($cloner->cloneVar($s));
        return substr(strip_tags($html), 1, -1);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\VarDumper\Dumper;

use _ContaoManager\Symfony\Component\VarDumper\Cloner\Data;
use _ContaoManager\Symfony\Component\VarDumper\Cloner\DumperInterface;
/**
 * Abstract mechanism for dumping a Data object.
 *
 * @author Nicolas Grekas <p@tchwork.com>
 */
abstract class AbstractDumper implements DataDumperInterface, DumperInterface
{
    public const DUMP_LIGHT_ARRAY = 1;
    public const DUMP_STRING_LENGTH = 2;
    public const DUMP_COMMA_SEPARATOR = 4;
    public const DUMP_TRAILING_COMMA = 8;
    /** @var callable|resource|string|null */
    public static $defaultOutput = 'php://output';
    protected $line = '';
    /** @var callable|null */
    protected $lineDumper;
    /** @var resource|null */
    protected $outputStream;
    protected $decimalPoint = '.';
    protected $indentPad = '  ';
    protected $flags;
    private string $charset = '';
    /**
     * @param callable|resource|string|null $output  A line dumper callable, an opened stream or an output path, defaults to static::$defaultOutput
     * @param string|null                   $charset The default character encoding to use for non-UTF8 strings
     * @param int                           $flags   A bit field of static::DUMP_* constants to fine tune dumps representation
     */
    public function __construct($output = null, ?string $charset = null, int $flags = 0)
    {
        $this->flags = $flags;
        $this->setCharset((($charset ?: \ini_get('php.output_encoding')) ?: \ini_get('default_charset')) ?: 'UTF-8');
        $this->setOutput($output ?: static::$defaultOutput);
        if (!$output && \is_string(static::$defaultOutput)) {
            static::$defaultOutput = $this->outputStream;
        }
    }
    /**
     * Sets the output destination of the dumps.
     *
     * @param callable|resource|string|null $output A line dumper callable, an opened stream or an output path
     *
     * @return callable|resource|string|null The previous output destination
     */
    public function setOutput($output)
    {
        $prev = $this->outputStream ?? $this->lineDumper;
        if (\is_callable($output)) {
            $this->outputStream = null;
            $this->lineDumper = $output;
        } else {
            if (\is_string($output)) {
                $output = fopen($output, 'w');
            }
            $this->outputStream = $output;
            $this->lineDumper = $this->echoLine(...);
        }
        return $prev;
    }
    /**
     * Sets the default character encoding to use for non-UTF8 strings.
     *
     * @return string The previous charset
     */
    public function setCharset(string $charset): string
    {
        $prev = $this->charset;
        $charset = strtoupper($charset);
        $charset = null === $charset || 'UTF-8' === $charset || 'UTF8' === $charset ? 'CP1252' : $charset;
        $this->charset = $charset;
        return $prev;
    }
    /**
     * Sets the indentation pad string.
     *
     * @param string $pad A string that will be prepended to dumped lines, repeated by nesting level
     *
     * @return string The previous indent pad
     */
    public function setIndentPad(string $pad): string
    {
        $prev = $this->indentPad;
        $this->indentPad = $pad;
        return $prev;
    }
    /**
     * Dumps a Data object.
     *
     * @param callable|resource|string|true|null $output A line dumper callable, an opened stream, an output path or true to return the dump
     *
     * @return string|null The dump as string when $output is true
     */
    public function dump(Data $data, $output = null): ?string
    {
        if ($locale = $this->flags & (self::DUMP_COMMA_SEPARATOR | self::DUMP_TRAILING_COMMA) ? setlocale(\LC_NUMERIC, 0) : null) {
            setlocale(\LC_NUMERIC, 'C');
        }
        if ($returnDump = \true === $output) {
            $output = fopen('php://memory', 'r+');
        }
        if ($output) {
            $prevOutput = $this->setOutput($output);
        }
        try {
            $data->dump($this);
            $this->dumpLine(-1);
            if ($returnDump) {
                $result = stream_get_contents($output, -1, 0);
                fclose($output);
                return $result;
            }
        } finally {
            if ($output) {
                $this->setOutput($prevOutput);
            }
            if ($locale) {
                setlocale(\LC_NUMERIC, $locale);
            }
        }
        return null;
    }
    /**
     * Dumps the current line.
     *
     * @param int $depth The recursive depth in the dumped structure for the line being dumped,
     *                   or -1 to signal the end-of-dump to the line dumper callable
     *
     * @return void
     */
    protected function dumpLine(int $depth)
    {
        ($this->lineDumper)($this->line, $depth, $this->indentPad);
        $this->line = '';
    }
    /**
     * Generic line dumper callback.
     *
     * @return void
     */
    protected function echoLine(string $line, int $depth, string $indentPad)
    {
        if (-1 !== $depth) {
            fwrite($this->outputStream, str_repeat($indentPad, $depth) . $line . "\n");
        }
    }
    /**
     * Converts a non-UTF-8 string to UTF-8.
     */
    protected function utf8Encode(?string $s): ?string
    {
        if (null === $s || preg_match('//u', $s)) {
            return $s;
        }
        if (\function_exists('iconv')) {
            if (\false !== $c = @iconv($this->charset, 'UTF-8', $s)) {
                return $c;
            }
            if ('CP1252' !== $this->charset && \false !== $c = @iconv('CP1252', 'UTF-8', $s)) {
                return $c;
            }
        }
        $s .= $s;
        $len = \strlen($s);
        $mapCp1252 = \false;
        for ($i = $len >> 1, $j = 0; $i < $len; ++$i, ++$j) {
            if ($s[$i] < "\x80") {
                $s[$j] = $s[$i];
            } elseif ($s[$i] < "\xc0") {
                $s[$j] = "\xc2";
                $s[++$j] = $s[$i];
                if ($s[$i] < "\xa0") {
                    $mapCp1252 = \true;
                }
            } else {
                $s[$j] = "\xc3";
                $s[++$j] = \chr(\ord($s[$i]) - 64);
            }
        }
        $s = substr($s, 0, $j);
        if (!$mapCp1252) {
            return $s;
        }
        return strtr($s, ["" => '€', "" => '‚', "" => 'ƒ', "" => '„', "" => '…', "" => '†', "" => '‡', "" => 'ˆ', "" => '‰', "" => 'Š', "" => '‹', "" => 'Œ', "" => 'Ž', "" => '‘', "" => '’', "" => '“', "" => '”', "" => '•', "" => '–', "" => '—', "" => '˜', "" => '™', "" => 'š', "" => '›', "" => 'œ', "" => 'ž']);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\VarDumper\Dumper;

use _ContaoManager\Symfony\Component\ErrorHandler\ErrorRenderer\FileLinkFormatter;
use _ContaoManager\Symfony\Component\VarDumper\Cloner\Cursor;
use _ContaoManager\Symfony\Component\VarDumper\Cloner\Stub;
/**
 * CliDumper dumps variables for command line output.
 *
 * @author Nicolas Grekas <p@tchwork.com>
 */
class CliDumper extends AbstractDumper
{
    public static $defaultColors;
    /** @var callable|resource|string|null */
    public static $defaultOutput = 'php://stdout';
    protected $colors;
    protected $maxStringWidth = 0;
    protected $styles = [
        // See http://en.wikipedia.org/wiki/ANSI_escape_code#graphics
        'default' => '0;38;5;208',
        'num' => '1;38;5;38',
        'const' => '1;38;5;208',
        'str' => '1;38;5;113',
        'note' => '38;5;38',
        'ref' => '38;5;247',
        'public' => '',
        'protected' => '',
        'private' => '',
        'meta' => '38;5;170',
        'key' => '38;5;113',
        'index' => '38;5;38',
    ];
    protected static $controlCharsRx = '/[\x00-\x1F\x7F]+/';
    protected static $controlCharsMap = ["\t" => '\t', "\n" => '\n', "\v" => '\v', "\f" => '\f', "\r" => '\r', "\x1b" => '\e'];
    protected static $unicodeCharsRx = "/[ ­͏؜ᅟᅠ឴឵᠎ -‏  ⁠-⁤⁪-⁯　⠀ㅤ﻿ﾠ𝅙𝅳-𝅺]/u";
    protected $collapseNextHash = \false;
    protected $expandNextHash = \false;
    private array $displayOptions = ['fileLinkFormat' => null];
    private bool $handlesHrefGracefully;
    public function __construct($output = null, ?string $charset = null, int $flags = 0)
    {
        parent::__construct($output, $charset, $flags);
        if ('\\' === \DIRECTORY_SEPARATOR && !$this->isWindowsTrueColor()) {
            // Use only the base 16 xterm colors when using ANSICON or standard Windows 10 CLI
            $this->setStyles(['default' => '31', 'num' => '1;34', 'const' => '1;31', 'str' => '1;32', 'note' => '34', 'ref' => '1;30', 'meta' => '35', 'key' => '32', 'index' => '34']);
        }
        $this->displayOptions['fileLinkFormat'] = class_exists(FileLinkFormatter::class) ? new FileLinkFormatter() : ((\ini_get('xdebug.file_link_format') ?: get_cfg_var('xdebug.file_link_format')) ?: 'file://%f#L%l');
    }
    /**
     * Enables/disables colored output.
     *
     * @return void
     */
    public function setColors(bool $colors)
    {
        $this->colors = $colors;
    }
    /**
     * Sets the maximum number of characters per line for dumped strings.
     *
     * @return void
     */
    public function setMaxStringWidth(int $maxStringWidth)
    {
        $this->maxStringWidth = $maxStringWidth;
    }
    /**
     * Configures styles.
     *
     * @param array $styles A map of style names to style definitions
     *
     * @return void
     */
    public function setStyles(array $styles)
    {
        $this->styles = $styles + $this->styles;
    }
    /**
     * Configures display options.
     *
     * @param array $displayOptions A map of display options to customize the behavior
     *
     * @return void
     */
    public function setDisplayOptions(array $displayOptions)
    {
        $this->displayOptions = $displayOptions + $this->displayOptions;
    }
    /**
     * @return void
     */
    public function dumpScalar(Cursor $cursor, string $type, string|int|float|bool|null $value)
    {
        $this->dumpKey($cursor);
        $this->collapseNextHash = $this->expandNextHash = \false;
        $style = 'const';
        $attr = $cursor->attr;
        switch ($type) {
            case 'default':
                $style = 'default';
                break;
            case 'label':
                $this->styles += ['label' => $this->styles['default']];
                $style = 'label';
                break;
            case 'integer':
                $style = 'num';
                if (isset($this->styles['integer'])) {
                    $style = 'integer';
                }
                break;
            case 'double':
                $style = 'num';
                if (isset($this->styles['float'])) {
                    $style = 'float';
                }
                $value = match (\true) {
                    \INF === $value => 'INF',
                    -\INF === $value => '-INF',
                    is_nan($value) => 'NAN',
                    default => !str_contains($value = (string) $value, $this->decimalPoint) ? $value .= $this->decimalPoint . '0' : $value,
                };
                break;
            case 'NULL':
                $value = 'null';
                break;
            case 'boolean':
                $value = $value ? 'true' : 'false';
                break;
            default:
                $attr += ['value' => $this->utf8Encode($value)];
                $value = $this->utf8Encode($type);
                break;
        }
        $this->line .= $this->style($style, $value, $attr);
        $this->endValue($cursor);
    }
    /**
     * @return void
     */
    public function dumpString(Cursor $cursor, string $str, bool $bin, int $cut)
    {
        $this->dumpKey($cursor);
        $this->collapseNextHash = $this->expandNextHash = \false;
        $attr = $cursor->attr;
        if ($bin) {
            $str = $this->utf8Encode($str);
        }
        if ('' === $str) {
            $this->line .= '""';
            if ($cut) {
                $this->line .= '…' . $cut;
            }
            $this->endValue($cursor);
        } else {
            $attr += ['length' => 0 <= $cut ? mb_strlen($str, 'UTF-8') + $cut : 0, 'binary' => $bin];
            $str = $bin && str_contains($str, "\x00") ? [$str] : explode("\n", $str);
            if (isset($str[1]) && !isset($str[2]) && !isset($str[1][0])) {
                unset($str[1]);
                $str[0] .= "\n";
            }
            $m = \count($str) - 1;
            $i = $lineCut = 0;
            if (self::DUMP_STRING_LENGTH & $this->flags) {
                $this->line .= '(' . $attr['length'] . ') ';
            }
            if ($bin) {
                $this->line .= 'b';
            }
            if ($m) {
                $this->line .= '"""';
                $this->dumpLine($cursor->depth);
            } else {
                $this->line .= '"';
            }
            foreach ($str as $str) {
                if ($i < $m) {
                    $str .= "\n";
                }
                if (0 < $this->maxStringWidth && $this->maxStringWidth < $len = mb_strlen($str, 'UTF-8')) {
                    $str = mb_substr($str, 0, $this->maxStringWidth, 'UTF-8');
                    $lineCut = $len - $this->maxStringWidth;
                }
                if ($m && 0 < $cursor->depth) {
                    $this->line .= $this->indentPad;
                }
                if ('' !== $str) {
                    $this->line .= $this->style('str', $str, $attr);
                }
                if ($i++ == $m) {
                    if ($m) {
                        if ('' !== $str) {
                            $this->dumpLine($cursor->depth);
                            if (0 < $cursor->depth) {
                                $this->line .= $this->indentPad;
                            }
                        }
                        $this->line .= '"""';
                    } else {
                        $this->line .= '"';
                    }
                    if ($cut < 0) {
                        $this->line .= '…';
                        $lineCut = 0;
                    } elseif ($cut) {
                        $lineCut += $cut;
                    }
                }
                if ($lineCut) {
                    $this->line .= '…' . $lineCut;
                    $lineCut = 0;
                }
                if ($i > $m) {
                    $this->endValue($cursor);
                } else {
                    $this->dumpLine($cursor->depth);
                }
            }
        }
    }
    /**
     * @return void
     */
    public function enterHash(Cursor $cursor, int $type, string|int|null $class, bool $hasChild)
    {
        $this->colors ??= $this->supportsColors();
        $this->dumpKey($cursor);
        $this->expandNextHash = \false;
        $attr = $cursor->attr;
        if ($this->collapseNextHash) {
            $cursor->skipChildren = \true;
            $this->collapseNextHash = $hasChild = \false;
        }
        $class = $this->utf8Encode($class);
        if (Cursor::HASH_OBJECT === $type) {
            $prefix = $class && 'stdClass' !== $class ? $this->style('note', $class, $attr) . (empty($attr['cut_hash']) ? ' {' : '') : '{';
        } elseif (Cursor::HASH_RESOURCE === $type) {
            $prefix = $this->style('note', $class . ' resource', $attr) . ($hasChild ? ' {' : ' ');
        } else {
            $prefix = $class && !(self::DUMP_LIGHT_ARRAY & $this->flags) ? $this->style('note', 'array:' . $class) . ' [' : '[';
        }
        if (($cursor->softRefCount || 0 < $cursor->softRefHandle) && empty($attr['cut_hash'])) {
            $prefix .= $this->style('ref', (Cursor::HASH_RESOURCE === $type ? '@' : '#') . (0 < $cursor->softRefHandle ? $cursor->softRefHandle : $cursor->softRefTo), ['count' => $cursor->softRefCount]);
        } elseif ($cursor->hardRefTo && !$cursor->refIndex && $class) {
            $prefix .= $this->style('ref', '&' . $cursor->hardRefTo, ['count' => $cursor->hardRefCount]);
        } elseif (!$hasChild && Cursor::HASH_RESOURCE === $type) {
            $prefix = substr($prefix, 0, -1);
        }
        $this->line .= $prefix;
        if ($hasChild) {
            $this->dumpLine($cursor->depth);
        }
    }
    /**
     * @return void
     */
    public function leaveHash(Cursor $cursor, int $type, string|int|null $class, bool $hasChild, int $cut)
    {
        if (empty($cursor->attr['cut_hash'])) {
            $this->dumpEllipsis($cursor, $hasChild, $cut);
            $this->line .= Cursor::HASH_OBJECT === $type ? '}' : (Cursor::HASH_RESOURCE !== $type ? ']' : ($hasChild ? '}' : ''));
        }
        $this->endValue($cursor);
    }
    /**
     * Dumps an ellipsis for cut children.
     *
     * @param bool $hasChild When the dump of the hash has child item
     * @param int  $cut      The number of items the hash has been cut by
     *
     * @return void
     */
    protected function dumpEllipsis(Cursor $cursor, bool $hasChild, int $cut)
    {
        if ($cut) {
            $this->line .= ' …';
            if (0 < $cut) {
                $this->line .= $cut;
            }
            if ($hasChild) {
                $this->dumpLine($cursor->depth + 1);
            }
        }
    }
    /**
     * Dumps a key in a hash structure.
     *
     * @return void
     */
    protected function dumpKey(Cursor $cursor)
    {
        if (null !== $key = $cursor->hashKey) {
            if ($cursor->hashKeyIsBinary) {
                $key = $this->utf8Encode($key);
            }
            $attr = ['binary' => $cursor->hashKeyIsBinary];
            $bin = $cursor->hashKeyIsBinary ? 'b' : '';
            $style = 'key';
            switch ($cursor->hashType) {
                default:
                case Cursor::HASH_INDEXED:
                    if (self::DUMP_LIGHT_ARRAY & $this->flags) {
                        break;
                    }
                    $style = 'index';
                // no break
                case Cursor::HASH_ASSOC:
                    if (\is_int($key)) {
                        $this->line .= $this->style($style, $key) . ' => ';
                    } else {
                        $this->line .= $bin . '"' . $this->style($style, $key) . '" => ';
                    }
                    break;
                case Cursor::HASH_RESOURCE:
                    $key = "\x00~\x00" . $key;
                // no break
                case Cursor::HASH_OBJECT:
                    if (!isset($key[0]) || "\x00" !== $key[0]) {
                        $this->line .= '+' . $bin . $this->style('public', $key) . ': ';
                    } elseif (0 < strpos($key, "\x00", 1)) {
                        $key = explode("\x00", substr($key, 1), 2);
                        switch ($key[0][0]) {
                            case '+':
                                // User inserted keys
                                $attr['dynamic'] = \true;
                                $this->line .= '+' . $bin . '"' . $this->style('public', $key[1], $attr) . '": ';
                                break 2;
                            case '~':
                                $style = 'meta';
                                if (isset($key[0][1])) {
                                    parse_str(substr($key[0], 1), $attr);
                                    $attr += ['binary' => $cursor->hashKeyIsBinary];
                                }
                                break;
                            case '*':
                                $style = 'protected';
                                $bin = '#' . $bin;
                                break;
                            default:
                                $attr['class'] = $key[0];
                                $style = 'private';
                                $bin = '-' . $bin;
                                break;
                        }
                        if (isset($attr['collapse'])) {
                            if ($attr['collapse']) {
                                $this->collapseNextHash = \true;
                            } else {
                                $this->expandNextHash = \true;
                            }
                        }
                        $this->line .= $bin . $this->style($style, $key[1], $attr) . ($attr['separator'] ?? ': ');
                    } else {
                        // This case should not happen
                        $this->line .= '-' . $bin . '"' . $this->style('private', $key, ['class' => '']) . '": ';
                    }
                    break;
            }
            if ($cursor->hardRefTo) {
                $this->line .= $this->style('ref', '&' . ($cursor->hardRefCount ? $cursor->hardRefTo : ''), ['count' => $cursor->hardRefCount]) . ' ';
            }
        }
    }
    /**
     * Decorates a value with some style.
     *
     * @param string $style The type of style being applied
     * @param string $value The value being styled
     * @param array  $attr  Optional context information
     */
    protected function style(string $style, string $value, array $attr = []): string
    {
        $this->colors ??= $this->supportsColors();
        $this->handlesHrefGracefully ??= 'JetBrains-JediTerm' !== getenv('TERMINAL_EMULATOR') && (!getenv('KONSOLE_VERSION') || (int) getenv('KONSOLE_VERSION') > 201100) && !isset($_SERVER['IDEA_INITIAL_DIRECTORY']);
        if (isset($attr['ellipsis'], $attr['ellipsis-type'])) {
            $prefix = substr($value, 0, -$attr['ellipsis']);
            if ('cli' === \PHP_SAPI && 'path' === $attr['ellipsis-type'] && isset($_SERVER[$pwd = '\\' === \DIRECTORY_SEPARATOR ? 'CD' : 'PWD']) && str_starts_with($prefix, $_SERVER[$pwd])) {
                $prefix = '.' . substr($prefix, \strlen($_SERVER[$pwd]));
            }
            if (!empty($attr['ellipsis-tail'])) {
                $prefix .= substr($value, -$attr['ellipsis'], $attr['ellipsis-tail']);
                $value = substr($value, -$attr['ellipsis'] + $attr['ellipsis-tail']);
            } else {
                $value = substr($value, -$attr['ellipsis']);
            }
            $value = $this->style('default', $prefix) . $this->style($style, $value);
            goto href;
        }
        $map = static::$controlCharsMap;
        $startCchr = $this->colors ? "\x1b[m\x1b[{$this->styles['default']}m" : '';
        $endCchr = $this->colors ? "\x1b[m\x1b[{$this->styles[$style]}m" : '';
        $value = preg_replace_callback(static::$controlCharsRx, function ($c) use ($map, $startCchr, $endCchr) {
            $s = $startCchr;
            $c = $c[$i = 0];
            do {
                $s .= $map[$c[$i]] ?? \sprintf('\x%02X', \ord($c[$i]));
            } while (isset($c[++$i]));
            return $s . $endCchr;
        }, $value, -1, $cchrCount);
        if (!($attr['binary'] ?? \false)) {
            $value = preg_replace_callback(static::$unicodeCharsRx, function ($c) use (&$cchrCount, $startCchr, $endCchr) {
                ++$cchrCount;
                return $startCchr . '\u{' . strtoupper(dechex(mb_ord($c[0]))) . '}' . $endCchr;
            }, $value);
        }
        if ($this->colors && '' !== $value) {
            if ($cchrCount && "\x1b" === $value[0]) {
                $value = substr($value, \strlen($startCchr));
            } else {
                $value = "\x1b[{$this->styles[$style]}m" . $value;
            }
            if ($cchrCount && str_ends_with($value, $endCchr)) {
                $value = substr($value, 0, -\strlen($endCchr));
            } else {
                $value .= "\x1b[{$this->styles['default']}m";
            }
        }
        href:
        if ($this->colors && $this->handlesHrefGracefully) {
            if (isset($attr['file']) && $href = $this->getSourceLink($attr['file'], $attr['line'] ?? 0)) {
                if ('note' === $style) {
                    $value .= "\x1b]8;;{$href}\x1b\\^\x1b]8;;\x1b\\";
                } else {
                    $attr['href'] = $href;
                }
            }
            if (isset($attr['href'])) {
                if ('label' === $style) {
                    $value .= '^';
                }
                $value = "\x1b]8;;{$attr['href']}\x1b\\{$value}\x1b]8;;\x1b\\";
            }
        }
        if ('label' === $style && '' !== $value) {
            $value .= ' ';
        }
        return $value;
    }
    protected function supportsColors(): bool
    {
        if ($this->outputStream !== static::$defaultOutput) {
            return $this->hasColorSupport($this->outputStream);
        }
        if (isset(static::$defaultColors)) {
            return static::$defaultColors;
        }
        if (isset($_SERVER['argv'][1])) {
            $colors = $_SERVER['argv'];
            $i = \count($colors);
            while (--$i > 0) {
                if (isset($colors[$i][5])) {
                    switch ($colors[$i]) {
                        case '--ansi':
                        case '--color':
                        case '--color=yes':
                        case '--color=force':
                        case '--color=always':
                        case '--colors=always':
                            return static::$defaultColors = \true;
                        case '--no-ansi':
                        case '--color=no':
                        case '--color=none':
                        case '--color=never':
                        case '--colors=never':
                            return static::$defaultColors = \false;
                    }
                }
            }
        }
        $h = stream_get_meta_data($this->outputStream) + ['wrapper_type' => null];
        $h = 'Output' === $h['stream_type'] && 'PHP' === $h['wrapper_type'] ? fopen('php://stdout', 'w') : $this->outputStream;
        return static::$defaultColors = $this->hasColorSupport($h);
    }
    /**
     * @return void
     */
    protected function dumpLine(int $depth, bool $endOfValue = \false)
    {
        if (null === $this->colors) {
            $this->colors = $this->supportsColors();
        }
        if ($this->colors) {
            $this->line = \sprintf("\x1b[%sm%s\x1b[m", $this->styles['default'], $this->line);
        }
        parent::dumpLine($depth);
    }
    /**
     * @return void
     */
    protected function endValue(Cursor $cursor)
    {
        if (-1 === $cursor->hashType) {
            return;
        }
        if (Stub::ARRAY_INDEXED === $cursor->hashType || Stub::ARRAY_ASSOC === $cursor->hashType) {
            if (self::DUMP_TRAILING_COMMA & $this->flags && 0 < $cursor->depth) {
                $this->line .= ',';
            } elseif (self::DUMP_COMMA_SEPARATOR & $this->flags && 1 < $cursor->hashLength - $cursor->hashIndex) {
                $this->line .= ',';
            }
        }
        $this->dumpLine($cursor->depth, \true);
    }
    /**
     * Returns true if the stream supports colorization.
     *
     * Reference: Composer\XdebugHandler\Process::supportsColor
     * https://github.com/composer/xdebug-handler
     */
    private function hasColorSupport(mixed $stream): bool
    {
        if (!\is_resource($stream) || 'stream' !== get_resource_type($stream)) {
            return \false;
        }
        // Follow https://no-color.org/
        if ('' !== (($_SERVER['NO_COLOR'] ?? getenv('NO_COLOR'))[0] ?? '')) {
            return \false;
        }
        // Detect msysgit/mingw and assume this is a tty because detection
        // does not work correctly, see https://github.com/composer/composer/issues/9690
        if (!@stream_isatty($stream) && !\in_array(strtoupper((string) getenv('MSYSTEM')), ['MINGW32', 'MINGW64'], \true)) {
            return \false;
        }
        if ('\\' === \DIRECTORY_SEPARATOR && @sapi_windows_vt100_support($stream)) {
            return \true;
        }
        if ('Hyper' === getenv('TERM_PROGRAM') || \false !== getenv('COLORTERM') || \false !== getenv('ANSICON') || 'ON' === getenv('ConEmuANSI')) {
            return \true;
        }
        if ('dumb' === $term = (string) getenv('TERM')) {
            return \false;
        }
        // See https://github.com/chalk/supports-color/blob/d4f413efaf8da045c5ab440ed418ef02dbb28bf1/index.js#L157
        return preg_match('/^((screen|xterm|vt100|vt220|putty|rxvt|ansi|cygwin|linux).*)|(.*-256(color)?(-bce)?)$/', $term);
    }
    /**
     * Returns true if the Windows terminal supports true color.
     *
     * Note that this does not check an output stream, but relies on environment
     * variables from known implementations, or a PHP and Windows version that
     * supports true color.
     */
    private function isWindowsTrueColor(): bool
    {
        $result = 183 <= getenv('ANSICON_VER') || 'ON' === getenv('ConEmuANSI') || 'xterm' === getenv('TERM') || 'Hyper' === getenv('TERM_PROGRAM');
        if (!$result) {
            $version = \sprintf('%s.%s.%s', \PHP_WINDOWS_VERSION_MAJOR, \PHP_WINDOWS_VERSION_MINOR, \PHP_WINDOWS_VERSION_BUILD);
            $result = $version >= '10.0.15063';
        }
        return $result;
    }
    private function getSourceLink(string $file, int $line): string|false
    {
        if ($fmt = $this->displayOptions['fileLinkFormat']) {
            return \is_string($fmt) ? strtr($fmt, ['%f' => $file, '%l' => $line]) : ($fmt->format($file, $line) ?: 'file://' . $file . '#L' . $line);
        }
        return \false;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\VarDumper\Dumper;

use _ContaoManager\Symfony\Component\VarDumper\Cloner\Data;
use _ContaoManager\Symfony\Component\VarDumper\Dumper\ContextProvider\ContextProviderInterface;
/**
 * @author Kévin Thérage <therage.kevin@gmail.com>
 */
class ContextualizedDumper implements DataDumperInterface
{
    private DataDumperInterface $wrappedDumper;
    private array $contextProviders;
    /**
     * @param ContextProviderInterface[] $contextProviders
     */
    public function __construct(DataDumperInterface $wrappedDumper, array $contextProviders)
    {
        $this->wrappedDumper = $wrappedDumper;
        $this->contextProviders = $contextProviders;
    }
    /**
     * @return string|null
     */
    public function dump(Data $data)
    {
        $context = $data->getContext();
        foreach ($this->contextProviders as $contextProvider) {
            $context[$contextProvider::class] = $contextProvider->getContext();
        }
        return $this->wrappedDumper->dump($data->withContext($context));
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\VarDumper\Dumper;

use _ContaoManager\Symfony\Component\VarDumper\Cloner\Cursor;
use _ContaoManager\Symfony\Component\VarDumper\Cloner\Data;
/**
 * HtmlDumper dumps variables as HTML.
 *
 * @author Nicolas Grekas <p@tchwork.com>
 */
class HtmlDumper extends CliDumper
{
    /** @var callable|resource|string|null */
    public static $defaultOutput = 'php://output';
    protected static $themes = ['dark' => ['default' => 'background-color:#18171B; color:#FF8400; line-height:1.2em; font:12px Menlo, Monaco, Consolas, monospace; word-wrap: break-word; white-space: pre-wrap; position:relative; z-index:99999; word-break: break-all', 'num' => 'font-weight:bold; color:#1299DA', 'const' => 'font-weight:bold', 'str' => 'font-weight:bold; color:#56DB3A', 'note' => 'color:#1299DA', 'ref' => 'color:#A0A0A0', 'public' => 'color:#FFFFFF', 'protected' => 'color:#FFFFFF', 'private' => 'color:#FFFFFF', 'meta' => 'color:#B729D9', 'key' => 'color:#56DB3A', 'index' => 'color:#1299DA', 'ellipsis' => 'color:#FF8400', 'ns' => 'user-select:none;'], 'light' => ['default' => 'background:none; color:#CC7832; line-height:1.2em; font:12px Menlo, Monaco, Consolas, monospace; word-wrap: break-word; white-space: pre-wrap; position:relative; z-index:99999; word-break: break-all', 'num' => 'font-weight:bold; color:#1299DA', 'const' => 'font-weight:bold', 'str' => 'font-weight:bold; color:#629755;', 'note' => 'color:#6897BB', 'ref' => 'color:#6E6E6E', 'public' => 'color:#262626', 'protected' => 'color:#262626', 'private' => 'color:#262626', 'meta' => 'color:#B729D9', 'key' => 'color:#789339', 'index' => 'color:#1299DA', 'ellipsis' => 'color:#CC7832', 'ns' => 'user-select:none;']];
    protected $dumpHeader;
    protected $dumpPrefix = '<pre class=sf-dump id=%s data-indent-pad="%s">';
    protected $dumpSuffix = '</pre><script>Sfdump(%s)</script>';
    protected $dumpId = 'sf-dump';
    protected $colors = \true;
    protected $headerIsDumped = \false;
    protected $lastDepth = -1;
    protected $styles;
    private array $displayOptions = ['maxDepth' => 1, 'maxStringLength' => 160, 'fileLinkFormat' => null];
    private array $extraDisplayOptions = [];
    public function __construct($output = null, ?string $charset = null, int $flags = 0)
    {
        AbstractDumper::__construct($output, $charset, $flags);
        $this->dumpId = 'sf-dump-' . mt_rand();
        $this->displayOptions['fileLinkFormat'] = \ini_get('xdebug.file_link_format') ?: get_cfg_var('xdebug.file_link_format');
        $this->styles = static::$themes['dark'] ?? self::$themes['dark'];
    }
    /**
     * @return void
     */
    public function setStyles(array $styles)
    {
        $this->headerIsDumped = \false;
        $this->styles = $styles + $this->styles;
    }
    /**
     * @return void
     */
    public function setTheme(string $themeName)
    {
        if (!isset(static::$themes[$themeName])) {
            throw new \InvalidArgumentException(\sprintf('Theme "%s" does not exist in class "%s".', $themeName, static::class));
        }
        $this->setStyles(static::$themes[$themeName]);
    }
    /**
     * Configures display options.
     *
     * @param array $displayOptions A map of display options to customize the behavior
     *
     * @return void
     */
    public function setDisplayOptions(array $displayOptions)
    {
        $this->headerIsDumped = \false;
        $this->displayOptions = $displayOptions + $this->displayOptions;
    }
    /**
     * Sets an HTML header that will be dumped once in the output stream.
     *
     * @return void
     */
    public function setDumpHeader(?string $header)
    {
        $this->dumpHeader = $header;
    }
    /**
     * Sets an HTML prefix and suffix that will encapse every single dump.
     *
     * @return void
     */
    public function setDumpBoundaries(string $prefix, string $suffix)
    {
        $this->dumpPrefix = $prefix;
        $this->dumpSuffix = $suffix;
    }
    public function dump(Data $data, $output = null, array $extraDisplayOptions = []): ?string
    {
        $this->extraDisplayOptions = $extraDisplayOptions;
        $result = parent::dump($data, $output);
        $this->dumpId = 'sf-dump-' . mt_rand();
        return $result;
    }
    /**
     * Dumps the HTML header.
     *
     * @return string
     */
    protected function getDumpHeader()
    {
        $this->headerIsDumped = $this->outputStream ?? $this->lineDumper;
        if (null !== $this->dumpHeader) {
            return $this->dumpHeader;
        }
        $line = str_replace('{$options}', json_encode($this->displayOptions, \JSON_FORCE_OBJECT), <<<'EOHTML'
<script>
Sfdump = window.Sfdump || (function (doc) {

doc.documentElement.classList.add('sf-js-enabled');

var rxEsc = /([.*+?^${}()|\[\]\/\\])/g,
    idRx = /\bsf-dump-\d+-ref[012]\w+\b/,
    keyHint = 0 <= navigator.platform.toUpperCase().indexOf('MAC') ? 'Cmd' : 'Ctrl',
    addEventListener = function (e, n, cb) {
        e.addEventListener(n, cb, false);
    };

if (!doc.addEventListener) {
    addEventListener = function (element, eventName, callback) {
        element.attachEvent('on' + eventName, function (e) {
            e.preventDefault = function () {e.returnValue = false;};
            e.target = e.srcElement;
            callback(e);
        });
    };
}

function toggle(a, recursive) {
    var s = a.nextSibling || {}, oldClass = s.className, arrow, newClass;

    if (/\bsf-dump-compact\b/.test(oldClass)) {
        arrow = '▼';
        newClass = 'sf-dump-expanded';
    } else if (/\bsf-dump-expanded\b/.test(oldClass)) {
        arrow = '▶';
        newClass = 'sf-dump-compact';
    } else {
        return false;
    }

    if (doc.createEvent && s.dispatchEvent) {
        var event = doc.createEvent('Event');
        event.initEvent('sf-dump-expanded' === newClass ? 'sfbeforedumpexpand' : 'sfbeforedumpcollapse', true, false);

        s.dispatchEvent(event);
    }

    a.lastChild.innerHTML = arrow;
    s.className = s.className.replace(/\bsf-dump-(compact|expanded)\b/, newClass);

    if (recursive) {
        try {
            a = s.querySelectorAll('.'+oldClass);
            for (s = 0; s < a.length; ++s) {
                if (-1 == a[s].className.indexOf(newClass)) {
                    a[s].className = newClass;
                    a[s].previousSibling.lastChild.innerHTML = arrow;
                }
            }
        } catch (e) {
        }
    }

    return true;
};

function collapse(a, recursive) {
    var s = a.nextSibling || {}, oldClass = s.className;

    if (/\bsf-dump-expanded\b/.test(oldClass)) {
        toggle(a, recursive);

        return true;
    }

    return false;
};

function expand(a, recursive) {
    var s = a.nextSibling || {}, oldClass = s.className;

    if (/\bsf-dump-compact\b/.test(oldClass)) {
        toggle(a, recursive);

        return true;
    }

    return false;
};

function collapseAll(root) {
    var a = root.querySelector('a.sf-dump-toggle');
    if (a) {
        collapse(a, true);
        expand(a);

        return true;
    }

    return false;
}

function reveal(node) {
    var previous, parents = [];

    while ((node = node.parentNode || {}) && (previous = node.previousSibling) && 'A' === previous.tagName) {
        parents.push(previous);
    }

    if (0 !== parents.length) {
        parents.forEach(function (parent) {
            expand(parent);
        });

        return true;
    }

    return false;
}

function highlight(root, activeNode, nodes) {
    resetHighlightedNodes(root);

    Array.from(nodes||[]).forEach(function (node) {
        if (!/\bsf-dump-highlight\b/.test(node.className)) {
            node.className = node.className + ' sf-dump-highlight';
        }
    });

    if (!/\bsf-dump-highlight-active\b/.test(activeNode.className)) {
        activeNode.className = activeNode.className + ' sf-dump-highlight-active';
    }
}

function resetHighlightedNodes(root) {
    Array.from(root.querySelectorAll('.sf-dump-str, .sf-dump-key, .sf-dump-public, .sf-dump-protected, .sf-dump-private')).forEach(function (strNode) {
        strNode.className = strNode.className.replace(/\bsf-dump-highlight\b/, '');
        strNode.className = strNode.className.replace(/\bsf-dump-highlight-active\b/, '');
    });
}

return function (root, x) {
    root = doc.getElementById(root);

    var indentRx = new RegExp('^('+(root.getAttribute('data-indent-pad') || '  ').replace(rxEsc, '\\$1')+')+', 'm'),
        options = {$options},
        elt = root.getElementsByTagName('A'),
        len = elt.length,
        i = 0, s, h,
        t = [];

    while (i < len) t.push(elt[i++]);

    for (i in x) {
        options[i] = x[i];
    }

    function a(e, f) {
        addEventListener(root, e, function (e, n) {
            if ('A' == e.target.tagName) {
                f(e.target, e);
            } else if ('A' == e.target.parentNode.tagName) {
                f(e.target.parentNode, e);
            } else {
                n = /\bsf-dump-ellipsis\b/.test(e.target.className) ? e.target.parentNode : e.target;

                if ((n = n.nextElementSibling) && 'A' == n.tagName) {
                    if (!/\bsf-dump-toggle\b/.test(n.className)) {
                        n = n.nextElementSibling || n;
                    }

                    f(n, e, true);
                }
            }
        });
    };
    function isCtrlKey(e) {
        return e.ctrlKey || e.metaKey;
    }
    function xpathString(str) {
        var parts = str.match(/[^'"]+|['"]/g).map(function (part) {
            if ("'" == part)  {
                return '"\'"';
            }
            if ('"' == part) {
                return "'\"'";
            }

            return "'" + part + "'";
        });

        return "concat(" + parts.join(",") + ", '')";
    }
    function xpathHasClass(className) {
        return "contains(concat(' ', normalize-space(@class), ' '), ' " + className +" ')";
    }
    a('mouseover', function (a, e, c) {
        if (c) {
            e.target.style.cursor = "pointer";
        }
    });
    a('click', function (a, e, c) {
        if (/\bsf-dump-toggle\b/.test(a.className)) {
            e.preventDefault();
            if (!toggle(a, isCtrlKey(e))) {
                var r = doc.getElementById(a.getAttribute('href').slice(1)),
                    s = r.previousSibling,
                    f = r.parentNode,
                    t = a.parentNode;
                t.replaceChild(r, a);
                f.replaceChild(a, s);
                t.insertBefore(s, r);
                f = f.firstChild.nodeValue.match(indentRx);
                t = t.firstChild.nodeValue.match(indentRx);
                if (f && t && f[0] !== t[0]) {
                    r.innerHTML = r.innerHTML.replace(new RegExp('^'+f[0].replace(rxEsc, '\\$1'), 'mg'), t[0]);
                }
                if (/\bsf-dump-compact\b/.test(r.className)) {
                    toggle(s, isCtrlKey(e));
                }
            }

            if (c) {
            } else if (doc.getSelection) {
                try {
                    doc.getSelection().removeAllRanges();
                } catch (e) {
                    doc.getSelection().empty();
                }
            } else {
                doc.selection.empty();
            }
        } else if (/\bsf-dump-str-toggle\b/.test(a.className)) {
            e.preventDefault();
            e = a.parentNode.parentNode;
            e.className = e.className.replace(/\bsf-dump-str-(expand|collapse)\b/, a.parentNode.className);
        }
    });

    elt = root.getElementsByTagName('SAMP');
    len = elt.length;
    i = 0;

    while (i < len) t.push(elt[i++]);
    len = t.length;

    for (i = 0; i < len; ++i) {
        elt = t[i];
        if ('SAMP' == elt.tagName) {
            a = elt.previousSibling || {};
            if ('A' != a.tagName) {
                a = doc.createElement('A');
                a.className = 'sf-dump-ref';
                elt.parentNode.insertBefore(a, elt);
            } else {
                a.innerHTML += ' ';
            }
            a.title = (a.title ? a.title+'\n[' : '[')+keyHint+'+click] Expand all children';
            a.innerHTML += elt.className == 'sf-dump-compact' ? '<span>▶</span>' : '<span>▼</span>';
            a.className += ' sf-dump-toggle';

            x = 1;
            if ('sf-dump' != elt.parentNode.className) {
                x += elt.parentNode.getAttribute('data-depth')/1;
            }
        } else if (/\bsf-dump-ref\b/.test(elt.className) && (a = elt.getAttribute('href'))) {
            a = a.slice(1);
            elt.className += ' sf-dump-hover';
            elt.className += ' '+a;

            if (/[\[{]$/.test(elt.previousSibling.nodeValue)) {
                a = a != elt.nextSibling.id && doc.getElementById(a);
                try {
                    s = a.nextSibling;
                    elt.appendChild(a);
                    s.parentNode.insertBefore(a, s);
                    if (/^[@#]/.test(elt.innerHTML)) {
                        elt.innerHTML += ' <span>▶</span>';
                    } else {
                        elt.innerHTML = '<span>▶</span>';
                        elt.className = 'sf-dump-ref';
                    }
                    elt.className += ' sf-dump-toggle';
                } catch (e) {
                    if ('&' == elt.innerHTML.charAt(0)) {
                        elt.innerHTML = '…';
                        elt.className = 'sf-dump-ref';
                    }
                }
            }
        }
    }

    if (doc.evaluate && Array.from && root.children.length > 1) {
        root.setAttribute('tabindex', 0);

        SearchState = function () {
            this.nodes = [];
            this.idx = 0;
        };
        SearchState.prototype = {
            next: function () {
                if (this.isEmpty()) {
                    return this.current();
                }
                this.idx = this.idx < (this.nodes.length - 1) ? this.idx + 1 : 0;

                return this.current();
            },
            previous: function () {
                if (this.isEmpty()) {
                    return this.current();
                }
                this.idx = this.idx > 0 ? this.idx - 1 : (this.nodes.length - 1);

                return this.current();
            },
            isEmpty: function () {
                return 0 === this.count();
            },
            current: function () {
                if (this.isEmpty()) {
                    return null;
                }
                return this.nodes[this.idx];
            },
            reset: function () {
                this.nodes = [];
                this.idx = 0;
            },
            count: function () {
                return this.nodes.length;
            },
        };

        function showCurrent(state)
        {
            var currentNode = state.current(), currentRect, searchRect;
            if (currentNode) {
                reveal(currentNode);
                highlight(root, currentNode, state.nodes);
                if ('scrollIntoView' in currentNode) {
                    currentNode.scrollIntoView(true);
                    currentRect = currentNode.getBoundingClientRect();
                    searchRect = search.getBoundingClientRect();
                    if (currentRect.top < (searchRect.top + searchRect.height)) {
                        window.scrollBy(0, -(searchRect.top + searchRect.height + 5));
                    }
                }
            }
            counter.textContent = (state.isEmpty() ? 0 : state.idx + 1) + ' of ' + state.count();
        }

        var search = doc.createElement('div');
        search.className = 'sf-dump-search-wrapper sf-dump-search-hidden';
        search.innerHTML = '
            <input type="text" class="sf-dump-search-input">
            <span class="sf-dump-search-count">0 of 0<\/span>
            <button type="button" class="sf-dump-search-input-previous" tabindex="-1">
                <svg viewBox="0 0 1792 1792" xmlns="http://www.w3.org/2000/svg"><path d="M1683 1331l-166 165q-19 19-45 19t-45-19L896 965l-531 531q-19 19-45 19t-45-19l-166-165q-19-19-19-45.5t19-45.5l742-741q19-19 45-19t45 19l742 741q19 19 19 45.5t-19 45.5z"\/><\/svg>
            <\/button>
            <button type="button" class="sf-dump-search-input-next" tabindex="-1">
                <svg viewBox="0 0 1792 1792" xmlns="http://www.w3.org/2000/svg"><path d="M1683 808l-742 741q-19 19-45 19t-45-19L109 808q-19-19-19-45.5t19-45.5l166-165q19-19 45-19t45 19l531 531 531-531q19-19 45-19t45 19l166 165q19 19 19 45.5t-19 45.5z"\/><\/svg>
            <\/button>
        ';
        root.insertBefore(search, root.firstChild);

        var state = new SearchState();
        var searchInput = search.querySelector('.sf-dump-search-input');
        var counter = search.querySelector('.sf-dump-search-count');
        var searchInputTimer = 0;
        var previousSearchQuery = '';

        addEventListener(searchInput, 'keyup', function (e) {
            var searchQuery = e.target.value;
            /* Don't perform anything if the pressed key didn't change the query */
            if (searchQuery === previousSearchQuery) {
                return;
            }
            previousSearchQuery = searchQuery;
            clearTimeout(searchInputTimer);
            searchInputTimer = setTimeout(function () {
                state.reset();
                collapseAll(root);
                resetHighlightedNodes(root);
                if ('' === searchQuery) {
                    counter.textContent = '0 of 0';

                    return;
                }

                var classMatches = [
                    "sf-dump-str",
                    "sf-dump-key",
                    "sf-dump-public",
                    "sf-dump-protected",
                    "sf-dump-private",
                ].map(xpathHasClass).join(' or ');

                var xpathResult = doc.evaluate('.//span[' + classMatches + '][contains(translate(child::text(), ' + xpathString(searchQuery.toUpperCase()) + ', ' + xpathString(searchQuery.toLowerCase()) + '), ' + xpathString(searchQuery.toLowerCase()) + ')]', root, null, XPathResult.ORDERED_NODE_ITERATOR_TYPE, null);

                while (node = xpathResult.iterateNext()) state.nodes.push(node);

                showCurrent(state);
            }, 400);
        });

        Array.from(search.querySelectorAll('.sf-dump-search-input-next, .sf-dump-search-input-previous')).forEach(function (btn) {
            addEventListener(btn, 'click', function (e) {
                e.preventDefault();
                -1 !== e.target.className.indexOf('next') ? state.next() : state.previous();
                searchInput.focus();
                collapseAll(root);
                showCurrent(state);
            })
        });

        addEventListener(root, 'keydown', function (e) {
            var isSearchActive = !/\bsf-dump-search-hidden\b/.test(search.className);
            if ((114 === e.keyCode && !isSearchActive) || (isCtrlKey(e) && 70 === e.keyCode)) {
                /* F3 or CMD/CTRL + F */
                if (70 === e.keyCode && document.activeElement === searchInput) {
                   /*
                    * If CMD/CTRL + F is hit while having focus on search input,
                    * the user probably meant to trigger browser search instead.
                    * Let the browser execute its behavior:
                    */
                    return;
                }

                e.preventDefault();
                search.className = search.className.replace(/\bsf-dump-search-hidden\b/, '');
                searchInput.focus();
            } else if (isSearchActive) {
                if (27 === e.keyCode) {
                    /* ESC key */
                    search.className += ' sf-dump-search-hidden';
                    e.preventDefault();
                    resetHighlightedNodes(root);
                    searchInput.value = '';
                } else if (
                    (isCtrlKey(e) && 71 === e.keyCode) /* CMD/CTRL + G */
                    || 13 === e.keyCode /* Enter */
                    || 114 === e.keyCode /* F3 */
                ) {
                    e.preventDefault();
                    e.shiftKey ? state.previous() : state.next();
                    collapseAll(root);
                    showCurrent(state);
                }
            }
        });
    }

    if (0 >= options.maxStringLength) {
        return;
    }
    try {
        elt = root.querySelectorAll('.sf-dump-str');
        len = elt.length;
        i = 0;
        t = [];

        while (i < len) t.push(elt[i++]);
        len = t.length;

        for (i = 0; i < len; ++i) {
            elt = t[i];
            s = elt.innerText || elt.textContent;
            x = s.length - options.maxStringLength;
            if (0 < x) {
                h = elt.innerHTML;
                elt[elt.innerText ? 'innerText' : 'textContent'] = s.substring(0, options.maxStringLength);
                elt.className += ' sf-dump-str-collapse';
                elt.innerHTML = '<span class=sf-dump-str-collapse>'+h+'<a class="sf-dump-ref sf-dump-str-toggle" title="Collapse"> ◀</a></span>'+
                    '<span class=sf-dump-str-expand>'+elt.innerHTML+'<a class="sf-dump-ref sf-dump-str-toggle" title="'+x+' remaining characters"> ▶</a></span>';
            }
        }
    } catch (e) {
    }
};

})(document);
</script><style>
.sf-js-enabled pre.sf-dump .sf-dump-compact,
.sf-js-enabled .sf-dump-str-collapse .sf-dump-str-collapse,
.sf-js-enabled .sf-dump-str-expand .sf-dump-str-expand {
    display: none;
}
.sf-dump-hover:hover {
    background-color: #B729D9;
    color: #FFF !important;
    border-radius: 2px;
}
pre.sf-dump {
    display: block;
    white-space: pre;
    padding: 5px;
    overflow: initial !important;
}
pre.sf-dump:after {
   content: "";
   visibility: hidden;
   display: block;
   height: 0;
   clear: both;
}
pre.sf-dump .sf-dump-ellipsization {
    display: inline-flex;
}
pre.sf-dump a {
    text-decoration: none;
    cursor: pointer;
    border: 0;
    outline: none;
    color: inherit;
}
pre.sf-dump img {
    max-width: 50em;
    max-height: 50em;
    margin: .5em 0 0 0;
    padding: 0;
    background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAAAAAA6mKC9AAAAHUlEQVQY02O8zAABilCaiQEN0EeA8QuUcX9g3QEAAjcC5piyhyEAAAAASUVORK5CYII=) #D3D3D3;
}
pre.sf-dump .sf-dump-ellipsis {
    text-overflow: ellipsis;
    white-space: nowrap;
    overflow: hidden;
}
pre.sf-dump .sf-dump-ellipsis-tail {
    flex-shrink: 0;
}
pre.sf-dump code {
    display:inline;
    padding:0;
    background:none;
}
.sf-dump-public.sf-dump-highlight,
.sf-dump-protected.sf-dump-highlight,
.sf-dump-private.sf-dump-highlight,
.sf-dump-str.sf-dump-highlight,
.sf-dump-key.sf-dump-highlight {
    background: rgba(111, 172, 204, 0.3);
    border: 1px solid #7DA0B1;
    border-radius: 3px;
}
.sf-dump-public.sf-dump-highlight-active,
.sf-dump-protected.sf-dump-highlight-active,
.sf-dump-private.sf-dump-highlight-active,
.sf-dump-str.sf-dump-highlight-active,
.sf-dump-key.sf-dump-highlight-active {
    background: rgba(253, 175, 0, 0.4);
    border: 1px solid #ffa500;
    border-radius: 3px;
}
pre.sf-dump .sf-dump-search-hidden {
    display: none !important;
}
pre.sf-dump .sf-dump-search-wrapper {
    font-size: 0;
    white-space: nowrap;
    margin-bottom: 5px;
    display: flex;
    position: -webkit-sticky;
    position: sticky;
    top: 5px;
}
pre.sf-dump .sf-dump-search-wrapper > * {
    vertical-align: top;
    box-sizing: border-box;
    height: 21px;
    font-weight: normal;
    border-radius: 0;
    background: #FFF;
    color: #757575;
    border: 1px solid #BBB;
}
pre.sf-dump .sf-dump-search-wrapper > input.sf-dump-search-input {
    padding: 3px;
    height: 21px;
    font-size: 12px;
    border-right: none;
    border-top-left-radius: 3px;
    border-bottom-left-radius: 3px;
    color: #000;
    min-width: 15px;
    width: 100%;
}
pre.sf-dump .sf-dump-search-wrapper > .sf-dump-search-input-next,
pre.sf-dump .sf-dump-search-wrapper > .sf-dump-search-input-previous {
    background: #F2F2F2;
    outline: none;
    border-left: none;
    font-size: 0;
    line-height: 0;
}
pre.sf-dump .sf-dump-search-wrapper > .sf-dump-search-input-next {
    border-top-right-radius: 3px;
    border-bottom-right-radius: 3px;
}
pre.sf-dump .sf-dump-search-wrapper > .sf-dump-search-input-next > svg,
pre.sf-dump .sf-dump-search-wrapper > .sf-dump-search-input-previous > svg {
    pointer-events: none;
    width: 12px;
    height: 12px;
}
pre.sf-dump .sf-dump-search-wrapper > .sf-dump-search-count {
    display: inline-block;
    padding: 0 5px;
    margin: 0;
    border-left: none;
    line-height: 21px;
    font-size: 12px;
}
EOHTML
);
        foreach ($this->styles as $class => $style) {
            $line .= 'pre.sf-dump' . ('default' === $class ? ', pre.sf-dump' : '') . ' .sf-dump-' . $class . '{' . $style . '}';
        }
        $line .= 'pre.sf-dump .sf-dump-ellipsis-note{' . $this->styles['note'] . '}';
        return $this->dumpHeader = preg_replace('/\s+/', ' ', $line) . '</style>' . $this->dumpHeader;
    }
    /**
     * @return void
     */
    public function dumpString(Cursor $cursor, string $str, bool $bin, int $cut)
    {
        if ('' === $str && isset($cursor->attr['img-data'], $cursor->attr['content-type'])) {
            $this->dumpKey($cursor);
            $this->line .= $this->style('default', $cursor->attr['img-size'] ?? '', []);
            $this->line .= $cursor->depth >= $this->displayOptions['maxDepth'] ? ' <samp class=sf-dump-compact>' : ' <samp class=sf-dump-expanded>';
            $this->endValue($cursor);
            $this->line .= $this->indentPad;
            $this->line .= \sprintf('<img src="data:%s;base64,%s" /></samp>', $cursor->attr['content-type'], base64_encode($cursor->attr['img-data']));
            $this->endValue($cursor);
        } else {
            parent::dumpString($cursor, $str, $bin, $cut);
        }
    }
    /**
     * @return void
     */
    public function enterHash(Cursor $cursor, int $type, string|int|null $class, bool $hasChild)
    {
        if (Cursor::HASH_OBJECT === $type) {
            $cursor->attr['depth'] = $cursor->depth;
        }
        parent::enterHash($cursor, $type, $class, \false);
        if ($cursor->skipChildren || $cursor->depth >= $this->displayOptions['maxDepth']) {
            $cursor->skipChildren = \false;
            $eol = ' class=sf-dump-compact>';
        } else {
            $this->expandNextHash = \false;
            $eol = ' class=sf-dump-expanded>';
        }
        if ($hasChild) {
            $this->line .= '<samp data-depth=' . ($cursor->depth + 1);
            if ($cursor->refIndex) {
                $r = Cursor::HASH_OBJECT !== $type ? 1 - (Cursor::HASH_RESOURCE !== $type) : 2;
                $r .= $r && 0 < $cursor->softRefHandle ? $cursor->softRefHandle : $cursor->refIndex;
                $this->line .= \sprintf(' id=%s-ref%s', $this->dumpId, $r);
            }
            $this->line .= $eol;
            $this->dumpLine($cursor->depth);
        }
    }
    /**
     * @return void
     */
    public function leaveHash(Cursor $cursor, int $type, string|int|null $class, bool $hasChild, int $cut)
    {
        $this->dumpEllipsis($cursor, $hasChild, $cut);
        if ($hasChild) {
            $this->line .= '</samp>';
        }
        parent::leaveHash($cursor, $type, $class, $hasChild, 0);
    }
    protected function style(string $style, string $value, array $attr = []): string
    {
        if ('' === $value && ('label' !== $style || !isset($attr['file']) && !isset($attr['href']))) {
            return '';
        }
        $v = esc($value);
        if ('ref' === $style) {
            if (empty($attr['count'])) {
                return \sprintf('<a class=sf-dump-ref>%s</a>', $v);
            }
            $r = ('#' !== $v[0] ? 1 - ('@' !== $v[0]) : 2) . substr($value, 1);
            return \sprintf('<a class=sf-dump-ref href=#%s-ref%s title="%d occurrences">%s</a>', $this->dumpId, $r, 1 + $attr['count'], $v);
        }
        $dumpClasses = ['sf-dump-' . $style];
        $dumpTitle = '';
        if ('const' === $style && isset($attr['value'])) {
            $dumpTitle = esc(\is_scalar($attr['value']) ? $attr['value'] : json_encode($attr['value']));
        } elseif ('public' === $style) {
            $dumpTitle = empty($attr['dynamic']) ? 'Public property' : 'Runtime added dynamic property';
        } elseif ('str' === $style && 1 < $attr['length']) {
            $dumpTitle = \sprintf('%d%s characters', $attr['length'], $attr['binary'] ? ' binary or non-UTF-8' : '');
        } elseif ('note' === $style && 0 < ($attr['depth'] ?? 0) && \false !== $c = strrpos($value, '\\')) {
            $attr += ['ellipsis' => \strlen($value) - $c, 'ellipsis-type' => 'note', 'ellipsis-tail' => 1];
        } elseif ('protected' === $style) {
            $dumpTitle = 'Protected property';
        } elseif ('meta' === $style && isset($attr['title'])) {
            $dumpTitle = esc($this->utf8Encode($attr['title']));
        } elseif ('private' === $style) {
            $dumpTitle = \sprintf('Private property defined in class:&#10;`%s`', esc($this->utf8Encode($attr['class'])));
        }
        if (isset($attr['ellipsis'])) {
            $dumpClasses[] = 'sf-dump-ellipsization';
            $ellipsisClass = 'sf-dump-ellipsis';
            if (isset($attr['ellipsis-type'])) {
                $ellipsisClass .= ' sf-dump-ellipsis-' . $attr['ellipsis-type'];
            }
            $label = esc(substr($value, -$attr['ellipsis']));
            $dumpTitle = $v . "\n" . $dumpTitle;
            $v = \sprintf('<span class="%s">%s</span>', $ellipsisClass, substr($v, 0, -\strlen($label)));
            if (!empty($attr['ellipsis-tail'])) {
                $tail = \strlen(esc(substr($value, -$attr['ellipsis'], $attr['ellipsis-tail'])));
                $v .= \sprintf('<span class="%s">%s</span><span class="sf-dump-ellipsis-tail">%s</span>', $ellipsisClass, substr($label, 0, $tail), substr($label, $tail));
            } else {
                $v .= \sprintf('<span class="sf-dump-ellipsis-tail">%s</span>', $label);
            }
        }
        $map = static::$controlCharsMap;
        $v = \sprintf('<span class=%s%s%1$s%s>%s</span>', 1 === \count($dumpClasses) ? '' : '"', implode(' ', $dumpClasses), $dumpTitle ? ' title="' . $dumpTitle . '"' : '', preg_replace_callback(static::$controlCharsRx, function ($c) use ($map) {
            $s = $b = '<span class="sf-dump-default';
            $c = $c[$i = 0];
            if ($ns = "\r" === $c[$i] || "\n" === $c[$i]) {
                $s .= ' sf-dump-ns';
            }
            $s .= '">';
            do {
                if (("\r" === $c[$i] || "\n" === $c[$i]) !== $ns) {
                    $s .= '</span>' . $b;
                    if ($ns = !$ns) {
                        $s .= ' sf-dump-ns';
                    }
                    $s .= '">';
                }
                $s .= $map[$c[$i]] ?? \sprintf('\x%02X', \ord($c[$i]));
            } while (isset($c[++$i]));
            return $s . '</span>';
        }, $v));
        if (!($attr['binary'] ?? \false)) {
            $v = preg_replace_callback(static::$unicodeCharsRx, function ($c) {
                return '<span class=sf-dump-default>\u{' . strtoupper(dechex(mb_ord($c[0]))) . '}</span>';
            }, $v);
        }
        if (isset($attr['file']) && $href = $this->getSourceLink($attr['file'], $attr['line'] ?? 0)) {
            $attr['href'] = $href;
        }
        if (isset($attr['href'])) {
            if ('label' === $style) {
                $v .= '^';
            }
            $target = isset($attr['file']) ? '' : ' target="_blank"';
            $v = \sprintf('<a href="%s"%s rel="noopener noreferrer">%s</a>', esc($this->utf8Encode($attr['href'])), $target, $v);
        }
        if (isset($attr['lang'])) {
            $v = \sprintf('<code class="%s">%s</code>', esc($attr['lang']), $v);
        }
        if ('label' === $style) {
            $v .= ' ';
        }
        return $v;
    }
    /**
     * @return void
     */
    protected function dumpLine(int $depth, bool $endOfValue = \false)
    {
        if (-1 === $this->lastDepth) {
            $this->line = \sprintf($this->dumpPrefix, $this->dumpId, $this->indentPad) . $this->line;
        }
        if ($this->headerIsDumped !== ($this->outputStream ?? $this->lineDumper)) {
            $this->line = $this->getDumpHeader() . $this->line;
        }
        if (-1 === $depth) {
            $args = ['"' . $this->dumpId . '"'];
            if ($this->extraDisplayOptions) {
                $args[] = json_encode($this->extraDisplayOptions, \JSON_FORCE_OBJECT);
            }
            // Replace is for BC
            $this->line .= \sprintf(str_replace('"%s"', '%s', $this->dumpSuffix), implode(', ', $args));
        }
        $this->lastDepth = $depth;
        $this->line = mb_encode_numericentity($this->line, [0x80, 0x10ffff, 0, 0x1fffff], 'UTF-8');
        if (-1 === $depth) {
            AbstractDumper::dumpLine(0);
        }
        AbstractDumper::dumpLine($depth);
    }
    private function getSourceLink(string $file, int $line): string|false
    {
        $options = $this->extraDisplayOptions + $this->displayOptions;
        if ($fmt = $options['fileLinkFormat']) {
            return \is_string($fmt) ? strtr($fmt, ['%f' => $file, '%l' => $line]) : $fmt->format($file, $line);
        }
        return \false;
    }
}
function esc(string $str): string
{
    return htmlspecialchars($str, \ENT_QUOTES, 'UTF-8');
}
{
    "name": "symfony\/var-dumper",
    "type": "library",
    "description": "Provides mechanisms for walking through any arbitrary PHP variable",
    "keywords": [
        "dump",
        "debug"
    ],
    "homepage": "https:\/\/symfony.com",
    "license": "MIT",
    "authors": [
        {
            "name": "Nicolas Grekas",
            "email": "p@tchwork.com"
        },
        {
            "name": "Symfony Community",
            "homepage": "https:\/\/symfony.com\/contributors"
        }
    ],
    "require": {
        "php": ">=8.1",
        "symfony\/deprecation-contracts": "^2.5|^3",
        "symfony\/polyfill-mbstring": "~1.0"
    },
    "require-dev": {
        "symfony\/console": "^5.4|^6.0|^7.0",
        "symfony\/error-handler": "^6.3|^7.0",
        "symfony\/http-kernel": "^5.4|^6.0|^7.0",
        "symfony\/process": "^5.4|^6.0|^7.0",
        "symfony\/uid": "^5.4|^6.0|^7.0",
        "twig\/twig": "^2.13|^3.0.4"
    },
    "conflict": {
        "symfony\/console": "<5.4"
    },
    "autoload": {
        "files": [
            "Resources\/functions\/dump.php"
        ],
        "psr-4": {
            "_ContaoManager\\Symfony\\Component\\VarDumper\\": ""
        },
        "exclude-from-classmap": [
            "\/Tests\/"
        ]
    },
    "bin": [
        "Resources\/bin\/var-dump-server"
    ],
    "minimum-stability": "dev"
}<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\VarDumper;

use _ContaoManager\Symfony\Component\ErrorHandler\ErrorRenderer\FileLinkFormatter;
use _ContaoManager\Symfony\Component\HttpFoundation\Request;
use _ContaoManager\Symfony\Component\HttpFoundation\RequestStack;
use _ContaoManager\Symfony\Component\VarDumper\Caster\ReflectionCaster;
use _ContaoManager\Symfony\Component\VarDumper\Cloner\VarCloner;
use _ContaoManager\Symfony\Component\VarDumper\Dumper\CliDumper;
use _ContaoManager\Symfony\Component\VarDumper\Dumper\ContextProvider\CliContextProvider;
use _ContaoManager\Symfony\Component\VarDumper\Dumper\ContextProvider\RequestContextProvider;
use _ContaoManager\Symfony\Component\VarDumper\Dumper\ContextProvider\SourceContextProvider;
use _ContaoManager\Symfony\Component\VarDumper\Dumper\ContextualizedDumper;
use _ContaoManager\Symfony\Component\VarDumper\Dumper\HtmlDumper;
use _ContaoManager\Symfony\Component\VarDumper\Dumper\ServerDumper;
// Load the global dump() function
require_once __DIR__ . '/Resources/functions/dump.php';
/**
 * @author Nicolas Grekas <p@tchwork.com>
 */
class VarDumper
{
    /**
     * @var callable|null
     */
    private static $handler;
    /**
     * @param string|null $label
     *
     * @return mixed
     */
    public static function dump(mixed $var)
    {
        $label = 2 <= \func_num_args() ? func_get_arg(1) : null;
        if (null === self::$handler) {
            self::register();
        }
        return (self::$handler)($var, $label);
    }
    public static function setHandler(?callable $callable = null): ?callable
    {
        if (1 > \func_num_args()) {
            trigger_deprecation('symfony/var-dumper', '6.2', 'Calling "%s()" without any arguments is deprecated, pass null explicitly instead.', __METHOD__);
        }
        $prevHandler = self::$handler;
        // Prevent replacing the handler with expected format as soon as the env var was set:
        if (isset($_SERVER['VAR_DUMPER_FORMAT'])) {
            return $prevHandler;
        }
        self::$handler = $callable;
        return $prevHandler;
    }
    private static function register(): void
    {
        $cloner = new VarCloner();
        $cloner->addCasters(ReflectionCaster::UNSET_CLOSURE_FILE_INFO);
        $format = $_SERVER['VAR_DUMPER_FORMAT'] ?? null;
        switch (\true) {
            case 'html' === $format:
                $dumper = new HtmlDumper();
                break;
            case 'cli' === $format:
                $dumper = new CliDumper();
                break;
            case 'server' === $format:
            case $format && 'tcp' === parse_url($format, \PHP_URL_SCHEME):
                $host = 'server' === $format ? $_SERVER['VAR_DUMPER_SERVER'] ?? '127.0.0.1:9912' : $format;
                $dumper = \in_array(\PHP_SAPI, ['cli', 'phpdbg', 'embed'], \true) ? new CliDumper() : new HtmlDumper();
                $dumper = new ServerDumper($host, $dumper, self::getDefaultContextProviders());
                break;
            default:
                $dumper = \in_array(\PHP_SAPI, ['cli', 'phpdbg', 'embed'], \true) ? new CliDumper() : new HtmlDumper();
        }
        if (!$dumper instanceof ServerDumper) {
            $dumper = new ContextualizedDumper($dumper, [new SourceContextProvider()]);
        }
        self::$handler = function ($var, ?string $label = null) use ($cloner, $dumper) {
            $var = $cloner->cloneVar($var);
            if (null !== $label) {
                $var = $var->withContext(['label' => $label]);
            }
            $dumper->dump($var);
        };
    }
    private static function getDefaultContextProviders(): array
    {
        $contextProviders = [];
        if (!\in_array(\PHP_SAPI, ['cli', 'phpdbg', 'embed'], \true) && class_exists(Request::class)) {
            $requestStack = new RequestStack();
            $requestStack->push(Request::createFromGlobals());
            $contextProviders['request'] = new RequestContextProvider($requestStack);
        }
        $fileLinkFormatter = class_exists(FileLinkFormatter::class) ? new FileLinkFormatter(null, $requestStack ?? null) : null;
        return $contextProviders + ['cli' => new CliContextProvider(), 'source' => new SourceContextProvider(null, null, $fileLinkFormatter)];
    }
}
Copyright (c) 2004-present Fabien Potencier

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is furnished
to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
CHANGELOG
=========

5.4
---

 * Add `Path` class
 * Add `$lock` argument to `Filesystem::appendToFile()`

5.0.0
-----

 * `Filesystem::dumpFile()` and `appendToFile()` don't accept arrays anymore

4.4.0
-----

 * support for passing a `null` value to `Filesystem::isAbsolutePath()` is deprecated and will be removed in 5.0
 * `tempnam()` now accepts a third argument `$suffix`.

4.3.0
-----

 * support for passing arrays to `Filesystem::dumpFile()` is deprecated and will be removed in 5.0
 * support for passing arrays to `Filesystem::appendToFile()` is deprecated and will be removed in 5.0

4.0.0
-----

 * removed `LockHandler`
 * Support for passing relative paths to `Filesystem::makePathRelative()` has been removed.

3.4.0
-----

 * support for passing relative paths to `Filesystem::makePathRelative()` is deprecated and will be removed in 4.0

3.3.0
-----

 * added `appendToFile()` to append contents to existing files

3.2.0
-----

 * added `readlink()` as a platform independent method to read links

3.0.0
-----

 * removed `$mode` argument from `Filesystem::dumpFile()`

2.8.0
-----

 * added tempnam() a stream aware version of PHP's native tempnam()

2.6.0
-----

 * added LockHandler

2.3.12
------

 * deprecated dumpFile() file mode argument.

2.3.0
-----

 * added the dumpFile() method to atomically write files

2.2.0
-----

 * added a delete option for the mirror() method

2.1.0
-----

 * 24eb396 : BC Break : mkdir() function now throws exception in case of failure instead of returning Boolean value
 * created the component
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Filesystem;

use _ContaoManager\Symfony\Component\Filesystem\Exception\FileNotFoundException;
use _ContaoManager\Symfony\Component\Filesystem\Exception\InvalidArgumentException;
use _ContaoManager\Symfony\Component\Filesystem\Exception\IOException;
/**
 * Provides basic utility to manipulate the file system.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class Filesystem
{
    private static ?string $lastError = null;
    /**
     * Copies a file.
     *
     * If the target file is older than the origin file, it's always overwritten.
     * If the target file is newer, it is overwritten only when the
     * $overwriteNewerFiles option is set to true.
     *
     * @return void
     *
     * @throws FileNotFoundException When originFile doesn't exist
     * @throws IOException           When copy fails
     */
    public function copy(string $originFile, string $targetFile, bool $overwriteNewerFiles = \false)
    {
        $originIsLocal = stream_is_local($originFile) || 0 === stripos($originFile, 'file://');
        if ($originIsLocal && !is_file($originFile)) {
            throw new FileNotFoundException(\sprintf('Failed to copy "%s" because file does not exist.', $originFile), 0, null, $originFile);
        }
        $this->mkdir(\dirname($targetFile));
        $doCopy = \true;
        if (!$overwriteNewerFiles && !parse_url($originFile, \PHP_URL_HOST) && is_file($targetFile)) {
            $doCopy = filemtime($originFile) > filemtime($targetFile);
        }
        if ($doCopy) {
            // https://bugs.php.net/64634
            if (!$source = self::box('fopen', $originFile, 'r')) {
                throw new IOException(\sprintf('Failed to copy "%s" to "%s" because source file could not be opened for reading: ', $originFile, $targetFile) . self::$lastError, 0, null, $originFile);
            }
            // Stream context created to allow files overwrite when using FTP stream wrapper - disabled by default
            if (!$target = self::box('fopen', $targetFile, 'w', \false, stream_context_create(['ftp' => ['overwrite' => \true]]))) {
                throw new IOException(\sprintf('Failed to copy "%s" to "%s" because target file could not be opened for writing: ', $originFile, $targetFile) . self::$lastError, 0, null, $originFile);
            }
            $bytesCopied = stream_copy_to_stream($source, $target);
            fclose($source);
            fclose($target);
            unset($source, $target);
            if (!is_file($targetFile)) {
                throw new IOException(\sprintf('Failed to copy "%s" to "%s".', $originFile, $targetFile), 0, null, $originFile);
            }
            if ($originIsLocal) {
                // Like `cp`, preserve executable permission bits
                self::box('chmod', $targetFile, fileperms($targetFile) | fileperms($originFile) & 0111);
                // Like `cp`, preserve the file modification time
                self::box('touch', $targetFile, filemtime($originFile));
                if ($bytesCopied !== $bytesOrigin = filesize($originFile)) {
                    throw new IOException(\sprintf('Failed to copy the whole content of "%s" to "%s" (%g of %g bytes copied).', $originFile, $targetFile, $bytesCopied, $bytesOrigin), 0, null, $originFile);
                }
            }
        }
    }
    /**
     * Creates a directory recursively.
     *
     * @return void
     *
     * @throws IOException On any directory creation failure
     */
    public function mkdir(string|iterable $dirs, int $mode = 0777)
    {
        foreach ($this->toIterable($dirs) as $dir) {
            if (is_dir($dir)) {
                continue;
            }
            if (!self::box('mkdir', $dir, $mode, \true) && !is_dir($dir)) {
                throw new IOException(\sprintf('Failed to create "%s": ', $dir) . self::$lastError, 0, null, $dir);
            }
        }
    }
    /**
     * Checks the existence of files or directories.
     */
    public function exists(string|iterable $files): bool
    {
        $maxPathLength = \PHP_MAXPATHLEN - 2;
        foreach ($this->toIterable($files) as $file) {
            if (\strlen($file) > $maxPathLength) {
                throw new IOException(\sprintf('Could not check if file exist because path length exceeds %d characters.', $maxPathLength), 0, null, $file);
            }
            if (!file_exists($file)) {
                return \false;
            }
        }
        return \true;
    }
    /**
     * Sets access and modification time of file.
     *
     * @param int|null $time  The touch time as a Unix timestamp, if not supplied the current system time is used
     * @param int|null $atime The access time as a Unix timestamp, if not supplied the current system time is used
     *
     * @return void
     *
     * @throws IOException When touch fails
     */
    public function touch(string|iterable $files, ?int $time = null, ?int $atime = null)
    {
        foreach ($this->toIterable($files) as $file) {
            if (!($time ? self::box('touch', $file, $time, $atime) : self::box('touch', $file))) {
                throw new IOException(\sprintf('Failed to touch "%s": ', $file) . self::$lastError, 0, null, $file);
            }
        }
    }
    /**
     * Removes files or directories.
     *
     * @return void
     *
     * @throws IOException When removal fails
     */
    public function remove(string|iterable $files)
    {
        if ($files instanceof \Traversable) {
            $files = iterator_to_array($files, \false);
        } elseif (!\is_array($files)) {
            $files = [$files];
        }
        self::doRemove($files, \false);
    }
    private static function doRemove(array $files, bool $isRecursive): void
    {
        $files = array_reverse($files);
        foreach ($files as $file) {
            if (is_link($file)) {
                // See https://bugs.php.net/52176
                if (!(self::box('unlink', $file) || '\\' !== \DIRECTORY_SEPARATOR || self::box('rmdir', $file)) && file_exists($file)) {
                    throw new IOException(\sprintf('Failed to remove symlink "%s": ', $file) . self::$lastError);
                }
            } elseif (is_dir($file)) {
                if (!$isRecursive) {
                    $tmpName = \dirname(realpath($file)) . '/.!' . strrev(strtr(base64_encode(random_bytes(2)), '/=', '-!'));
                    if (file_exists($tmpName)) {
                        try {
                            self::doRemove([$tmpName], \true);
                        } catch (IOException) {
                        }
                    }
                    if (!file_exists($tmpName) && self::box('rename', $file, $tmpName)) {
                        $origFile = $file;
                        $file = $tmpName;
                    } else {
                        $origFile = null;
                    }
                }
                $filesystemIterator = new \FilesystemIterator($file, \FilesystemIterator::CURRENT_AS_PATHNAME | \FilesystemIterator::SKIP_DOTS);
                self::doRemove(iterator_to_array($filesystemIterator, \true), \true);
                if (!self::box('rmdir', $file) && file_exists($file) && !$isRecursive) {
                    $lastError = self::$lastError;
                    if (null !== $origFile && self::box('rename', $file, $origFile)) {
                        $file = $origFile;
                    }
                    throw new IOException(\sprintf('Failed to remove directory "%s": ', $file) . $lastError);
                }
            } elseif (!self::box('unlink', $file) && (self::$lastError && str_contains(self::$lastError, 'Permission denied') || file_exists($file))) {
                throw new IOException(\sprintf('Failed to remove file "%s": ', $file) . self::$lastError);
            }
        }
    }
    /**
     * Change mode for an array of files or directories.
     *
     * @param int  $mode      The new mode (octal)
     * @param int  $umask     The mode mask (octal)
     * @param bool $recursive Whether change the mod recursively or not
     *
     * @return void
     *
     * @throws IOException When the change fails
     */
    public function chmod(string|iterable $files, int $mode, int $umask = 00, bool $recursive = \false)
    {
        foreach ($this->toIterable($files) as $file) {
            if (!self::box('chmod', $file, $mode & ~$umask)) {
                throw new IOException(\sprintf('Failed to chmod file "%s": ', $file) . self::$lastError, 0, null, $file);
            }
            if ($recursive && is_dir($file) && !is_link($file)) {
                $this->chmod(new \FilesystemIterator($file), $mode, $umask, \true);
            }
        }
    }
    /**
     * Change the owner of an array of files or directories.
     *
     * This method always throws on Windows, as the underlying PHP function is not supported.
     *
     * @see https://php.net/chown
     *
     * @param string|int $user      A user name or number
     * @param bool       $recursive Whether change the owner recursively or not
     *
     * @return void
     *
     * @throws IOException When the change fails
     */
    public function chown(string|iterable $files, string|int $user, bool $recursive = \false)
    {
        foreach ($this->toIterable($files) as $file) {
            if ($recursive && is_dir($file) && !is_link($file)) {
                $this->chown(new \FilesystemIterator($file), $user, \true);
            }
            if (is_link($file) && \function_exists('lchown')) {
                if (!self::box('lchown', $file, $user)) {
                    throw new IOException(\sprintf('Failed to chown file "%s": ', $file) . self::$lastError, 0, null, $file);
                }
            } else if (!self::box('chown', $file, $user)) {
                throw new IOException(\sprintf('Failed to chown file "%s": ', $file) . self::$lastError, 0, null, $file);
            }
        }
    }
    /**
     * Change the group of an array of files or directories.
     *
     * This method always throws on Windows, as the underlying PHP function is not supported.
     *
     * @see https://php.net/chgrp
     *
     * @param string|int $group     A group name or number
     * @param bool       $recursive Whether change the group recursively or not
     *
     * @return void
     *
     * @throws IOException When the change fails
     */
    public function chgrp(string|iterable $files, string|int $group, bool $recursive = \false)
    {
        foreach ($this->toIterable($files) as $file) {
            if ($recursive && is_dir($file) && !is_link($file)) {
                $this->chgrp(new \FilesystemIterator($file), $group, \true);
            }
            if (is_link($file) && \function_exists('lchgrp')) {
                if (!self::box('lchgrp', $file, $group)) {
                    throw new IOException(\sprintf('Failed to chgrp file "%s": ', $file) . self::$lastError, 0, null, $file);
                }
            } else if (!self::box('chgrp', $file, $group)) {
                throw new IOException(\sprintf('Failed to chgrp file "%s": ', $file) . self::$lastError, 0, null, $file);
            }
        }
    }
    /**
     * Renames a file or a directory.
     *
     * @return void
     *
     * @throws IOException When target file or directory already exists
     * @throws IOException When origin cannot be renamed
     */
    public function rename(string $origin, string $target, bool $overwrite = \false)
    {
        // we check that target does not exist
        if (!$overwrite && $this->isReadable($target)) {
            throw new IOException(\sprintf('Cannot rename because the target "%s" already exists.', $target), 0, null, $target);
        }
        if (!self::box('rename', $origin, $target)) {
            if (is_dir($origin)) {
                // See https://bugs.php.net/54097 & https://php.net/rename#113943
                $this->mirror($origin, $target, null, ['override' => $overwrite, 'delete' => $overwrite]);
                $this->remove($origin);
                return;
            }
            throw new IOException(\sprintf('Cannot rename "%s" to "%s": ', $origin, $target) . self::$lastError, 0, null, $target);
        }
    }
    /**
     * Tells whether a file exists and is readable.
     *
     * @throws IOException When windows path is longer than 258 characters
     */
    private function isReadable(string $filename): bool
    {
        $maxPathLength = \PHP_MAXPATHLEN - 2;
        if (\strlen($filename) > $maxPathLength) {
            throw new IOException(\sprintf('Could not check if file is readable because path length exceeds %d characters.', $maxPathLength), 0, null, $filename);
        }
        return is_readable($filename);
    }
    /**
     * Creates a symbolic link or copy a directory.
     *
     * @return void
     *
     * @throws IOException When symlink fails
     */
    public function symlink(string $originDir, string $targetDir, bool $copyOnWindows = \false)
    {
        self::assertFunctionExists('symlink');
        if ('\\' === \DIRECTORY_SEPARATOR) {
            $originDir = strtr($originDir, '/', '\\');
            $targetDir = strtr($targetDir, '/', '\\');
            if ($copyOnWindows) {
                $this->mirror($originDir, $targetDir);
                return;
            }
        }
        $this->mkdir(\dirname($targetDir));
        if (is_link($targetDir)) {
            if (readlink($targetDir) === $originDir) {
                return;
            }
            $this->remove($targetDir);
        }
        if (!self::box('symlink', $originDir, $targetDir)) {
            $this->linkException($originDir, $targetDir, 'symbolic');
        }
    }
    /**
     * Creates a hard link, or several hard links to a file.
     *
     * @param string|string[] $targetFiles The target file(s)
     *
     * @return void
     *
     * @throws FileNotFoundException When original file is missing or not a file
     * @throws IOException           When link fails, including if link already exists
     */
    public function hardlink(string $originFile, string|iterable $targetFiles)
    {
        self::assertFunctionExists('link');
        if (!$this->exists($originFile)) {
            throw new FileNotFoundException(null, 0, null, $originFile);
        }
        if (!is_file($originFile)) {
            throw new FileNotFoundException(\sprintf('Origin file "%s" is not a file.', $originFile));
        }
        foreach ($this->toIterable($targetFiles) as $targetFile) {
            if (is_file($targetFile)) {
                if (fileinode($originFile) === fileinode($targetFile)) {
                    continue;
                }
                $this->remove($targetFile);
            }
            if (!self::box('link', $originFile, $targetFile)) {
                $this->linkException($originFile, $targetFile, 'hard');
            }
        }
    }
    /**
     * @param string $linkType Name of the link type, typically 'symbolic' or 'hard'
     */
    private function linkException(string $origin, string $target, string $linkType): never
    {
        if (self::$lastError) {
            if ('\\' === \DIRECTORY_SEPARATOR && str_contains(self::$lastError, 'error code(1314)')) {
                throw new IOException(\sprintf('Unable to create "%s" link due to error code 1314: \'A required privilege is not held by the client\'. Do you have the required Administrator-rights?', $linkType), 0, null, $target);
            }
        }
        throw new IOException(\sprintf('Failed to create "%s" link from "%s" to "%s": ', $linkType, $origin, $target) . self::$lastError, 0, null, $target);
    }
    /**
     * Resolves links in paths.
     *
     * With $canonicalize = false (default)
     *      - if $path does not exist or is not a link, returns null
     *      - if $path is a link, returns the next direct target of the link without considering the existence of the target
     *
     * With $canonicalize = true
     *      - if $path does not exist, returns null
     *      - if $path exists, returns its absolute fully resolved final version
     */
    public function readlink(string $path, bool $canonicalize = \false): ?string
    {
        if (!$canonicalize && !is_link($path)) {
            return null;
        }
        if ($canonicalize) {
            if (!$this->exists($path)) {
                return null;
            }
            return realpath($path);
        }
        return readlink($path);
    }
    /**
     * Given an existing path, convert it to a path relative to a given starting path.
     */
    public function makePathRelative(string $endPath, string $startPath): string
    {
        if (!$this->isAbsolutePath($startPath)) {
            throw new InvalidArgumentException(\sprintf('The start path "%s" is not absolute.', $startPath));
        }
        if (!$this->isAbsolutePath($endPath)) {
            throw new InvalidArgumentException(\sprintf('The end path "%s" is not absolute.', $endPath));
        }
        $originalEndPath = $endPath;
        // Normalize separators on Windows
        if ('\\' === \DIRECTORY_SEPARATOR) {
            $endPath = str_replace('\\', '/', $endPath);
            $startPath = str_replace('\\', '/', $startPath);
        }
        $splitDriveLetter = fn($path) => \strlen($path) > 2 && ':' === $path[1] && '/' === $path[2] && ctype_alpha($path[0]) ? [substr($path, 2), strtoupper($path[0])] : [$path, null];
        $splitPath = function ($path) {
            $result = [];
            foreach (explode('/', trim($path, '/')) as $segment) {
                if ('..' === $segment) {
                    array_pop($result);
                } elseif ('.' !== $segment && '' !== $segment) {
                    $result[] = $segment;
                }
            }
            return $result;
        };
        [$endPath, $endDriveLetter] = $splitDriveLetter($endPath);
        [$startPath, $startDriveLetter] = $splitDriveLetter($startPath);
        $startPathArr = $splitPath($startPath);
        $endPathArr = $splitPath($endPath);
        if ($endDriveLetter && $startDriveLetter && $endDriveLetter != $startDriveLetter) {
            // End path is on another drive, so no relative path exists
            return $endDriveLetter . ':/' . ($endPathArr ? implode('/', $endPathArr) . '/' : '');
        }
        // Find for which directory the common path stops
        $index = 0;
        while (isset($startPathArr[$index]) && isset($endPathArr[$index]) && $startPathArr[$index] === $endPathArr[$index]) {
            ++$index;
        }
        // Determine how deep the start path is relative to the common path (ie, "web/bundles" = 2 levels)
        if (1 === \count($startPathArr) && '' === $startPathArr[0]) {
            $depth = 0;
        } else {
            $depth = \count($startPathArr) - $index;
        }
        // Repeated "../" for each level need to reach the common path
        $traverser = str_repeat('../', $depth);
        $endPathRemainder = implode('/', \array_slice($endPathArr, $index));
        // Construct $endPath from traversing to the common path, then to the remaining $endPath
        $relativePath = $traverser . ('' !== $endPathRemainder ? $endPathRemainder . '/' : '');
        // Remove ending "/" if $endPath points to an existing file
        if (str_ends_with($relativePath, '/') && is_file($originalEndPath)) {
            $relativePath = substr($relativePath, 0, -1);
        }
        return '' === $relativePath ? './' : $relativePath;
    }
    /**
     * Mirrors a directory to another.
     *
     * Copies files and directories from the origin directory into the target directory. By default:
     *
     *  - existing files in the target directory will be overwritten, except if they are newer (see the `override` option)
     *  - files in the target directory that do not exist in the source directory will not be deleted (see the `delete` option)
     *
     * @param \Traversable|null $iterator Iterator that filters which files and directories to copy, if null a recursive iterator is created
     * @param array             $options  An array of boolean options
     *                                    Valid options are:
     *                                    - $options['override'] If true, target files newer than origin files are overwritten (see copy(), defaults to false)
     *                                    - $options['copy_on_windows'] Whether to copy files instead of links on Windows (see symlink(), defaults to false)
     *                                    - $options['delete'] Whether to delete files that are not in the source directory (defaults to false)
     *
     * @return void
     *
     * @throws IOException When file type is unknown
     */
    public function mirror(string $originDir, string $targetDir, ?\Traversable $iterator = null, array $options = [])
    {
        $targetDir = rtrim($targetDir, '/\\');
        $originDir = rtrim($originDir, '/\\');
        $originDirLen = \strlen($originDir);
        if (!$this->exists($originDir)) {
            throw new IOException(\sprintf('The origin directory specified "%s" was not found.', $originDir), 0, null, $originDir);
        }
        // Iterate in destination folder to remove obsolete entries
        if ($this->exists($targetDir) && isset($options['delete']) && $options['delete']) {
            $deleteIterator = $iterator;
            if (null === $deleteIterator) {
                $flags = \FilesystemIterator::SKIP_DOTS;
                $deleteIterator = new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($targetDir, $flags), \RecursiveIteratorIterator::CHILD_FIRST);
            }
            $targetDirLen = \strlen($targetDir);
            foreach ($deleteIterator as $file) {
                $origin = $originDir . substr($file->getPathname(), $targetDirLen);
                if (!$this->exists($origin)) {
                    $this->remove($file);
                }
            }
        }
        $copyOnWindows = $options['copy_on_windows'] ?? \false;
        if (null === $iterator) {
            $flags = $copyOnWindows ? \FilesystemIterator::SKIP_DOTS | \FilesystemIterator::FOLLOW_SYMLINKS : \FilesystemIterator::SKIP_DOTS;
            $iterator = new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($originDir, $flags), \RecursiveIteratorIterator::SELF_FIRST);
        }
        $this->mkdir($targetDir);
        $filesCreatedWhileMirroring = [];
        foreach ($iterator as $file) {
            if ($file->getPathname() === $targetDir || $file->getRealPath() === $targetDir || isset($filesCreatedWhileMirroring[$file->getRealPath()])) {
                continue;
            }
            $target = $targetDir . substr($file->getPathname(), $originDirLen);
            $filesCreatedWhileMirroring[$target] = \true;
            if (!$copyOnWindows && is_link($file)) {
                $this->symlink($file->getLinkTarget(), $target);
            } elseif (is_dir($file)) {
                $this->mkdir($target);
            } elseif (is_file($file)) {
                $this->copy($file, $target, $options['override'] ?? \false);
            } else {
                throw new IOException(\sprintf('Unable to guess "%s" file type.', $file), 0, null, $file);
            }
        }
    }
    /**
     * Returns whether the file path is an absolute path.
     */
    public function isAbsolutePath(string $file): bool
    {
        return '' !== $file && (strspn($file, '/\\', 0, 1) || \strlen($file) > 3 && ctype_alpha($file[0]) && ':' === $file[1] && strspn($file, '/\\', 2, 1) || null !== parse_url($file, \PHP_URL_SCHEME));
    }
    /**
     * Creates a temporary file with support for custom stream wrappers.
     *
     * @param string $prefix The prefix of the generated temporary filename
     *                       Note: Windows uses only the first three characters of prefix
     * @param string $suffix The suffix of the generated temporary filename
     *
     * @return string The new temporary filename (with path), or throw an exception on failure
     */
    public function tempnam(string $dir, string $prefix, string $suffix = ''): string
    {
        [$scheme, $hierarchy] = $this->getSchemeAndHierarchy($dir);
        // If no scheme or scheme is "file" or "gs" (Google Cloud) create temp file in local filesystem
        if ((null === $scheme || 'file' === $scheme || 'gs' === $scheme) && '' === $suffix) {
            // If tempnam failed or no scheme return the filename otherwise prepend the scheme
            if ($tmpFile = self::box('tempnam', $hierarchy, $prefix)) {
                if (null !== $scheme && 'gs' !== $scheme) {
                    return $scheme . '://' . $tmpFile;
                }
                return $tmpFile;
            }
            throw new IOException('A temporary file could not be created: ' . self::$lastError);
        }
        // Loop until we create a valid temp file or have reached 10 attempts
        for ($i = 0; $i < 10; ++$i) {
            // Create a unique filename
            $tmpFile = $dir . '/' . $prefix . uniqid(mt_rand(), \true) . $suffix;
            // Use fopen instead of file_exists as some streams do not support stat
            // Use mode 'x+' to atomically check existence and create to avoid a TOCTOU vulnerability
            if (!$handle = self::box('fopen', $tmpFile, 'x+')) {
                continue;
            }
            // Close the file if it was successfully opened
            self::box('fclose', $handle);
            return $tmpFile;
        }
        throw new IOException('A temporary file could not be created: ' . self::$lastError);
    }
    /**
     * Atomically dumps content into a file.
     *
     * @param string|resource $content The data to write into the file
     *
     * @return void
     *
     * @throws IOException if the file cannot be written to
     */
    public function dumpFile(string $filename, $content)
    {
        if (\is_array($content)) {
            throw new \TypeError(\sprintf('Argument 2 passed to "%s()" must be string or resource, array given.', __METHOD__));
        }
        $dir = \dirname($filename);
        if (is_link($filename) && $linkTarget = $this->readlink($filename)) {
            $this->dumpFile(Path::makeAbsolute($linkTarget, $dir), $content);
            return;
        }
        if (!is_dir($dir)) {
            $this->mkdir($dir);
        }
        // Will create a temp file with 0600 access rights
        // when the filesystem supports chmod.
        $tmpFile = $this->tempnam($dir, basename($filename));
        try {
            if (\false === self::box('file_put_contents', $tmpFile, $content)) {
                throw new IOException(\sprintf('Failed to write file "%s": ', $filename) . self::$lastError, 0, null, $filename);
            }
            self::box('chmod', $tmpFile, self::box('fileperms', $filename) ?: 0666 & ~umask());
            $this->rename($tmpFile, $filename, \true);
        } finally {
            if (file_exists($tmpFile)) {
                if ('\\' === \DIRECTORY_SEPARATOR && !is_writable($tmpFile)) {
                    self::box('chmod', $tmpFile, self::box('fileperms', $tmpFile) | 0200);
                }
                self::box('unlink', $tmpFile);
            }
        }
    }
    /**
     * Appends content to an existing file.
     *
     * @param string|resource $content The content to append
     * @param bool            $lock    Whether the file should be locked when writing to it
     *
     * @return void
     *
     * @throws IOException If the file is not writable
     */
    public function appendToFile(string $filename, $content)
    {
        if (\is_array($content)) {
            throw new \TypeError(\sprintf('Argument 2 passed to "%s()" must be string or resource, array given.', __METHOD__));
        }
        $dir = \dirname($filename);
        if (!is_dir($dir)) {
            $this->mkdir($dir);
        }
        $lock = \func_num_args() > 2 && func_get_arg(2);
        if (\false === self::box('file_put_contents', $filename, $content, \FILE_APPEND | ($lock ? \LOCK_EX : 0))) {
            throw new IOException(\sprintf('Failed to write file "%s": ', $filename) . self::$lastError, 0, null, $filename);
        }
    }
    private function toIterable(string|iterable $files): iterable
    {
        return is_iterable($files) ? $files : [$files];
    }
    /**
     * Gets a 2-tuple of scheme (may be null) and hierarchical part of a filename (e.g. file:///tmp -> [file, tmp]).
     */
    private function getSchemeAndHierarchy(string $filename): array
    {
        $components = explode('://', $filename, 2);
        return 2 === \count($components) ? [$components[0], $components[1]] : [null, $components[0]];
    }
    private static function assertFunctionExists(string $func): void
    {
        if (!\function_exists($func)) {
            throw new IOException(\sprintf('Unable to perform filesystem operation because the "%s()" function has been disabled.', $func));
        }
    }
    private static function box(string $func, mixed ...$args): mixed
    {
        self::assertFunctionExists($func);
        self::$lastError = null;
        set_error_handler(self::handleError(...));
        try {
            return $func(...$args);
        } finally {
            restore_error_handler();
        }
    }
    /**
     * @internal
     */
    public static function handleError(int $type, string $msg): void
    {
        self::$lastError = $msg;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Filesystem;

use _ContaoManager\Symfony\Component\Filesystem\Exception\InvalidArgumentException;
use _ContaoManager\Symfony\Component\Filesystem\Exception\RuntimeException;
/**
 * Contains utility methods for handling path strings.
 *
 * The methods in this class are able to deal with both UNIX and Windows paths
 * with both forward and backward slashes. All methods return normalized parts
 * containing only forward slashes and no excess "." and ".." segments.
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 * @author Thomas Schulz <mail@king2500.net>
 * @author Théo Fidry <theo.fidry@gmail.com>
 */
final class Path
{
    /**
     * The number of buffer entries that triggers a cleanup operation.
     */
    private const CLEANUP_THRESHOLD = 1250;
    /**
     * The buffer size after the cleanup operation.
     */
    private const CLEANUP_SIZE = 1000;
    /**
     * Buffers input/output of {@link canonicalize()}.
     *
     * @var array<string, string>
     */
    private static array $buffer = [];
    private static int $bufferSize = 0;
    /**
     * Canonicalizes the given path.
     *
     * During normalization, all slashes are replaced by forward slashes ("/").
     * Furthermore, all "." and ".." segments are removed as far as possible.
     * ".." segments at the beginning of relative paths are not removed.
     *
     * ```php
     * echo Path::canonicalize("\symfony\puli\..\css\style.css");
     * // => /symfony/css/style.css
     *
     * echo Path::canonicalize("../css/./style.css");
     * // => ../css/style.css
     * ```
     *
     * This method is able to deal with both UNIX and Windows paths.
     */
    public static function canonicalize(string $path): string
    {
        if ('' === $path) {
            return '';
        }
        // This method is called by many other methods in this class. Buffer
        // the canonicalized paths to make up for the severe performance
        // decrease.
        if (isset(self::$buffer[$path])) {
            return self::$buffer[$path];
        }
        // Replace "~" with user's home directory.
        if ('~' === $path[0]) {
            $path = self::getHomeDirectory() . substr($path, 1);
        }
        $path = self::normalize($path);
        [$root, $pathWithoutRoot] = self::split($path);
        $canonicalParts = self::findCanonicalParts($root, $pathWithoutRoot);
        // Add the root directory again
        self::$buffer[$path] = $canonicalPath = $root . implode('/', $canonicalParts);
        ++self::$bufferSize;
        // Clean up regularly to prevent memory leaks
        if (self::$bufferSize > self::CLEANUP_THRESHOLD) {
            self::$buffer = \array_slice(self::$buffer, -self::CLEANUP_SIZE, null, \true);
            self::$bufferSize = self::CLEANUP_SIZE;
        }
        return $canonicalPath;
    }
    /**
     * Normalizes the given path.
     *
     * During normalization, all slashes are replaced by forward slashes ("/").
     * Contrary to {@link canonicalize()}, this method does not remove invalid
     * or dot path segments. Consequently, it is much more efficient and should
     * be used whenever the given path is known to be a valid, absolute system
     * path.
     *
     * This method is able to deal with both UNIX and Windows paths.
     */
    public static function normalize(string $path): string
    {
        return str_replace('\\', '/', $path);
    }
    /**
     * Returns the directory part of the path.
     *
     * This method is similar to PHP's dirname(), but handles various cases
     * where dirname() returns a weird result:
     *
     *  - dirname() does not accept backslashes on UNIX
     *  - dirname("C:/symfony") returns "C:", not "C:/"
     *  - dirname("C:/") returns ".", not "C:/"
     *  - dirname("C:") returns ".", not "C:/"
     *  - dirname("symfony") returns ".", not ""
     *  - dirname() does not canonicalize the result
     *
     * This method fixes these shortcomings and behaves like dirname()
     * otherwise.
     *
     * The result is a canonical path.
     *
     * @return string The canonical directory part. Returns the root directory
     *                if the root directory is passed. Returns an empty string
     *                if a relative path is passed that contains no slashes.
     *                Returns an empty string if an empty string is passed.
     */
    public static function getDirectory(string $path): string
    {
        if ('' === $path) {
            return '';
        }
        $path = self::canonicalize($path);
        // Maintain scheme
        if (\false !== $schemeSeparatorPosition = strpos($path, '://')) {
            $scheme = substr($path, 0, $schemeSeparatorPosition + 3);
            $path = substr($path, $schemeSeparatorPosition + 3);
        } else {
            $scheme = '';
        }
        if (\false === $dirSeparatorPosition = strrpos($path, '/')) {
            return '';
        }
        // Directory equals root directory "/"
        if (0 === $dirSeparatorPosition) {
            return $scheme . '/';
        }
        // Directory equals Windows root "C:/"
        if (2 === $dirSeparatorPosition && ctype_alpha($path[0]) && ':' === $path[1]) {
            return $scheme . substr($path, 0, 3);
        }
        return $scheme . substr($path, 0, $dirSeparatorPosition);
    }
    /**
     * Returns canonical path of the user's home directory.
     *
     * Supported operating systems:
     *
     *  - UNIX
     *  - Windows8 and upper
     *
     * If your operating system or environment isn't supported, an exception is thrown.
     *
     * The result is a canonical path.
     *
     * @throws RuntimeException If your operating system or environment isn't supported
     */
    public static function getHomeDirectory(): string
    {
        // For UNIX support
        if (getenv('HOME')) {
            return self::canonicalize(getenv('HOME'));
        }
        // For >= Windows8 support
        if (getenv('HOMEDRIVE') && getenv('HOMEPATH')) {
            return self::canonicalize(getenv('HOMEDRIVE') . getenv('HOMEPATH'));
        }
        throw new RuntimeException("Cannot find the home directory path: Your environment or operating system isn't supported.");
    }
    /**
     * Returns the root directory of a path.
     *
     * The result is a canonical path.
     *
     * @return string The canonical root directory. Returns an empty string if
     *                the given path is relative or empty.
     */
    public static function getRoot(string $path): string
    {
        if ('' === $path) {
            return '';
        }
        // Maintain scheme
        if (\false !== $schemeSeparatorPosition = strpos($path, '://')) {
            $scheme = substr($path, 0, $schemeSeparatorPosition + 3);
            $path = substr($path, $schemeSeparatorPosition + 3);
        } else {
            $scheme = '';
        }
        $firstCharacter = $path[0];
        // UNIX root "/" or "\" (Windows style)
        if ('/' === $firstCharacter || '\\' === $firstCharacter) {
            return $scheme . '/';
        }
        $length = \strlen($path);
        // Windows root
        if ($length > 1 && ':' === $path[1] && ctype_alpha($firstCharacter)) {
            // Special case: "C:"
            if (2 === $length) {
                return $scheme . $path . '/';
            }
            // Normal case: "C:/ or "C:\"
            if ('/' === $path[2] || '\\' === $path[2]) {
                return $scheme . $firstCharacter . $path[1] . '/';
            }
        }
        return '';
    }
    /**
     * Returns the file name without the extension from a file path.
     *
     * @param string|null $extension if specified, only that extension is cut
     *                               off (may contain leading dot)
     */
    public static function getFilenameWithoutExtension(string $path, ?string $extension = null): string
    {
        if ('' === $path) {
            return '';
        }
        if (null !== $extension) {
            // remove extension and trailing dot
            return rtrim(basename($path, $extension), '.');
        }
        return pathinfo($path, \PATHINFO_FILENAME);
    }
    /**
     * Returns the extension from a file path (without leading dot).
     *
     * @param bool $forceLowerCase forces the extension to be lower-case
     */
    public static function getExtension(string $path, bool $forceLowerCase = \false): string
    {
        if ('' === $path) {
            return '';
        }
        $extension = pathinfo($path, \PATHINFO_EXTENSION);
        if ($forceLowerCase) {
            $extension = self::toLower($extension);
        }
        return $extension;
    }
    /**
     * Returns whether the path has an (or the specified) extension.
     *
     * @param string               $path       the path string
     * @param string|string[]|null $extensions if null or not provided, checks if
     *                                         an extension exists, otherwise
     *                                         checks for the specified extension
     *                                         or array of extensions (with or
     *                                         without leading dot)
     * @param bool                 $ignoreCase whether to ignore case-sensitivity
     */
    public static function hasExtension(string $path, $extensions = null, bool $ignoreCase = \false): bool
    {
        if ('' === $path) {
            return \false;
        }
        $actualExtension = self::getExtension($path, $ignoreCase);
        // Only check if path has any extension
        if ([] === $extensions || null === $extensions) {
            return '' !== $actualExtension;
        }
        if (\is_string($extensions)) {
            $extensions = [$extensions];
        }
        foreach ($extensions as $key => $extension) {
            if ($ignoreCase) {
                $extension = self::toLower($extension);
            }
            // remove leading '.' in extensions array
            $extensions[$key] = ltrim($extension, '.');
        }
        return \in_array($actualExtension, $extensions, \true);
    }
    /**
     * Changes the extension of a path string.
     *
     * @param string $path      The path string with filename.ext to change.
     * @param string $extension new extension (with or without leading dot)
     *
     * @return string the path string with new file extension
     */
    public static function changeExtension(string $path, string $extension): string
    {
        if ('' === $path) {
            return '';
        }
        $actualExtension = self::getExtension($path);
        $extension = ltrim($extension, '.');
        // No extension for paths
        if ('/' === substr($path, -1)) {
            return $path;
        }
        // No actual extension in path
        if (empty($actualExtension)) {
            return $path . ('.' === substr($path, -1) ? '' : '.') . $extension;
        }
        return substr($path, 0, -\strlen($actualExtension)) . $extension;
    }
    public static function isAbsolute(string $path): bool
    {
        if ('' === $path) {
            return \false;
        }
        // Strip scheme
        if (\false !== ($schemeSeparatorPosition = strpos($path, '://')) && 1 !== $schemeSeparatorPosition) {
            $path = substr($path, $schemeSeparatorPosition + 3);
        }
        $firstCharacter = $path[0];
        // UNIX root "/" or "\" (Windows style)
        if ('/' === $firstCharacter || '\\' === $firstCharacter) {
            return \true;
        }
        // Windows root
        if (\strlen($path) > 1 && ctype_alpha($firstCharacter) && ':' === $path[1]) {
            // Special case: "C:"
            if (2 === \strlen($path)) {
                return \true;
            }
            // Normal case: "C:/ or "C:\"
            if ('/' === $path[2] || '\\' === $path[2]) {
                return \true;
            }
        }
        return \false;
    }
    public static function isRelative(string $path): bool
    {
        return !self::isAbsolute($path);
    }
    /**
     * Turns a relative path into an absolute path in canonical form.
     *
     * Usually, the relative path is appended to the given base path. Dot
     * segments ("." and "..") are removed/collapsed and all slashes turned
     * into forward slashes.
     *
     * ```php
     * echo Path::makeAbsolute("../style.css", "/symfony/puli/css");
     * // => /symfony/puli/style.css
     * ```
     *
     * If an absolute path is passed, that path is returned unless its root
     * directory is different than the one of the base path. In that case, an
     * exception is thrown.
     *
     * ```php
     * Path::makeAbsolute("/style.css", "/symfony/puli/css");
     * // => /style.css
     *
     * Path::makeAbsolute("C:/style.css", "C:/symfony/puli/css");
     * // => C:/style.css
     *
     * Path::makeAbsolute("C:/style.css", "/symfony/puli/css");
     * // InvalidArgumentException
     * ```
     *
     * If the base path is not an absolute path, an exception is thrown.
     *
     * The result is a canonical path.
     *
     * @param string $basePath an absolute base path
     *
     * @throws InvalidArgumentException if the base path is not absolute or if
     *                                  the given path is an absolute path with
     *                                  a different root than the base path
     */
    public static function makeAbsolute(string $path, string $basePath): string
    {
        if ('' === $basePath) {
            throw new InvalidArgumentException(\sprintf('The base path must be a non-empty string. Got: "%s".', $basePath));
        }
        if (!self::isAbsolute($basePath)) {
            throw new InvalidArgumentException(\sprintf('The base path "%s" is not an absolute path.', $basePath));
        }
        if (self::isAbsolute($path)) {
            return self::canonicalize($path);
        }
        if (\false !== $schemeSeparatorPosition = strpos($basePath, '://')) {
            $scheme = substr($basePath, 0, $schemeSeparatorPosition + 3);
            $basePath = substr($basePath, $schemeSeparatorPosition + 3);
        } else {
            $scheme = '';
        }
        return $scheme . self::canonicalize(rtrim($basePath, '/\\') . '/' . $path);
    }
    /**
     * Turns a path into a relative path.
     *
     * The relative path is created relative to the given base path:
     *
     * ```php
     * echo Path::makeRelative("/symfony/style.css", "/symfony/puli");
     * // => ../style.css
     * ```
     *
     * If a relative path is passed and the base path is absolute, the relative
     * path is returned unchanged:
     *
     * ```php
     * Path::makeRelative("style.css", "/symfony/puli/css");
     * // => style.css
     * ```
     *
     * If both paths are relative, the relative path is created with the
     * assumption that both paths are relative to the same directory:
     *
     * ```php
     * Path::makeRelative("style.css", "symfony/puli/css");
     * // => ../../../style.css
     * ```
     *
     * If both paths are absolute, their root directory must be the same,
     * otherwise an exception is thrown:
     *
     * ```php
     * Path::makeRelative("C:/symfony/style.css", "/symfony/puli");
     * // InvalidArgumentException
     * ```
     *
     * If the passed path is absolute, but the base path is not, an exception
     * is thrown as well:
     *
     * ```php
     * Path::makeRelative("/symfony/style.css", "symfony/puli");
     * // InvalidArgumentException
     * ```
     *
     * If the base path is not an absolute path, an exception is thrown.
     *
     * The result is a canonical path.
     *
     * @throws InvalidArgumentException if the base path is not absolute or if
     *                                  the given path has a different root
     *                                  than the base path
     */
    public static function makeRelative(string $path, string $basePath): string
    {
        $path = self::canonicalize($path);
        $basePath = self::canonicalize($basePath);
        [$root, $relativePath] = self::split($path);
        [$baseRoot, $relativeBasePath] = self::split($basePath);
        // If the base path is given as absolute path and the path is already
        // relative, consider it to be relative to the given absolute path
        // already
        if ('' === $root && '' !== $baseRoot) {
            // If base path is already in its root
            if ('' === $relativeBasePath) {
                $relativePath = ltrim($relativePath, './\\');
            }
            return $relativePath;
        }
        // If the passed path is absolute, but the base path is not, we
        // cannot generate a relative path
        if ('' !== $root && '' === $baseRoot) {
            throw new InvalidArgumentException(\sprintf('The absolute path "%s" cannot be made relative to the relative path "%s". You should provide an absolute base path instead.', $path, $basePath));
        }
        // Fail if the roots of the two paths are different
        if ($baseRoot && $root !== $baseRoot) {
            throw new InvalidArgumentException(\sprintf('The path "%s" cannot be made relative to "%s", because they have different roots ("%s" and "%s").', $path, $basePath, $root, $baseRoot));
        }
        if ('' === $relativeBasePath) {
            return $relativePath;
        }
        // Build a "../../" prefix with as many "../" parts as necessary
        $parts = explode('/', $relativePath);
        $baseParts = explode('/', $relativeBasePath);
        $dotDotPrefix = '';
        // Once we found a non-matching part in the prefix, we need to add
        // "../" parts for all remaining parts
        $match = \true;
        foreach ($baseParts as $index => $basePart) {
            if ($match && isset($parts[$index]) && $basePart === $parts[$index]) {
                unset($parts[$index]);
                continue;
            }
            $match = \false;
            $dotDotPrefix .= '../';
        }
        return rtrim($dotDotPrefix . implode('/', $parts), '/');
    }
    /**
     * Returns whether the given path is on the local filesystem.
     */
    public static function isLocal(string $path): bool
    {
        return '' !== $path && !str_contains($path, '://');
    }
    /**
     * Returns the longest common base path in canonical form of a set of paths or
     * `null` if the paths are on different Windows partitions.
     *
     * Dot segments ("." and "..") are removed/collapsed and all slashes turned
     * into forward slashes.
     *
     * ```php
     * $basePath = Path::getLongestCommonBasePath(
     *     '/symfony/css/style.css',
     *     '/symfony/css/..'
     * );
     * // => /symfony
     * ```
     *
     * The root is returned if no common base path can be found:
     *
     * ```php
     * $basePath = Path::getLongestCommonBasePath(
     *     '/symfony/css/style.css',
     *     '/puli/css/..'
     * );
     * // => /
     * ```
     *
     * If the paths are located on different Windows partitions, `null` is
     * returned.
     *
     * ```php
     * $basePath = Path::getLongestCommonBasePath(
     *     'C:/symfony/css/style.css',
     *     'D:/symfony/css/..'
     * );
     * // => null
     * ```
     */
    public static function getLongestCommonBasePath(string ...$paths): ?string
    {
        [$bpRoot, $basePath] = self::split(self::canonicalize(reset($paths)));
        for (next($paths); null !== key($paths) && '' !== $basePath; next($paths)) {
            [$root, $path] = self::split(self::canonicalize(current($paths)));
            // If we deal with different roots (e.g. C:/ vs. D:/), it's time
            // to quit
            if ($root !== $bpRoot) {
                return null;
            }
            // Make the base path shorter until it fits into path
            while (\true) {
                if ('.' === $basePath) {
                    // No more base paths
                    $basePath = '';
                    // next path
                    continue 2;
                }
                // Prevent false positives for common prefixes
                // see isBasePath()
                if (str_starts_with($path . '/', $basePath . '/')) {
                    // next path
                    continue 2;
                }
                $basePath = \dirname($basePath);
            }
        }
        return $bpRoot . $basePath;
    }
    /**
     * Joins two or more path strings into a canonical path.
     */
    public static function join(string ...$paths): string
    {
        $finalPath = null;
        $wasScheme = \false;
        foreach ($paths as $path) {
            if ('' === $path) {
                continue;
            }
            if (null === $finalPath) {
                // For first part we keep slashes, like '/top', 'C:\' or 'phar://'
                $finalPath = $path;
                $wasScheme = str_contains($path, '://');
                continue;
            }
            // Only add slash if previous part didn't end with '/' or '\'
            if (!\in_array(substr($finalPath, -1), ['/', '\\'])) {
                $finalPath .= '/';
            }
            // If first part included a scheme like 'phar://' we allow \current part to start with '/', otherwise trim
            $finalPath .= $wasScheme ? $path : ltrim($path, '/');
            $wasScheme = \false;
        }
        if (null === $finalPath) {
            return '';
        }
        return self::canonicalize($finalPath);
    }
    /**
     * Returns whether a path is a base path of another path.
     *
     * Dot segments ("." and "..") are removed/collapsed and all slashes turned
     * into forward slashes.
     *
     * ```php
     * Path::isBasePath('/symfony', '/symfony/css');
     * // => true
     *
     * Path::isBasePath('/symfony', '/symfony');
     * // => true
     *
     * Path::isBasePath('/symfony', '/symfony/..');
     * // => false
     *
     * Path::isBasePath('/symfony', '/puli');
     * // => false
     * ```
     */
    public static function isBasePath(string $basePath, string $ofPath): bool
    {
        $basePath = self::canonicalize($basePath);
        $ofPath = self::canonicalize($ofPath);
        // Append slashes to prevent false positives when two paths have
        // a common prefix, for example /base/foo and /base/foobar.
        // Don't append a slash for the root "/", because then that root
        // won't be discovered as common prefix ("//" is not a prefix of
        // "/foobar/").
        return str_starts_with($ofPath . '/', rtrim($basePath, '/') . '/');
    }
    /**
     * @return string[]
     */
    private static function findCanonicalParts(string $root, string $pathWithoutRoot): array
    {
        $parts = explode('/', $pathWithoutRoot);
        $canonicalParts = [];
        // Collapse "." and "..", if possible
        foreach ($parts as $part) {
            if ('.' === $part || '' === $part) {
                continue;
            }
            // Collapse ".." with the previous part, if one exists
            // Don't collapse ".." if the previous part is also ".."
            if ('..' === $part && \count($canonicalParts) > 0 && '..' !== $canonicalParts[\count($canonicalParts) - 1]) {
                array_pop($canonicalParts);
                continue;
            }
            // Only add ".." prefixes for relative paths
            if ('..' !== $part || '' === $root) {
                $canonicalParts[] = $part;
            }
        }
        return $canonicalParts;
    }
    /**
     * Splits a canonical path into its root directory and the remainder.
     *
     * If the path has no root directory, an empty root directory will be
     * returned.
     *
     * If the root directory is a Windows style partition, the resulting root
     * will always contain a trailing slash.
     *
     * list ($root, $path) = Path::split("C:/symfony")
     * // => ["C:/", "symfony"]
     *
     * list ($root, $path) = Path::split("C:")
     * // => ["C:/", ""]
     *
     * @return array{string, string} an array with the root directory and the remaining relative path
     */
    private static function split(string $path): array
    {
        if ('' === $path) {
            return ['', ''];
        }
        // Remember scheme as part of the root, if any
        if (\false !== $schemeSeparatorPosition = strpos($path, '://')) {
            $root = substr($path, 0, $schemeSeparatorPosition + 3);
            $path = substr($path, $schemeSeparatorPosition + 3);
        } else {
            $root = '';
        }
        $length = \strlen($path);
        // Remove and remember root directory
        if (str_starts_with($path, '/')) {
            $root .= '/';
            $path = $length > 1 ? substr($path, 1) : '';
        } elseif ($length > 1 && ctype_alpha($path[0]) && ':' === $path[1]) {
            if (2 === $length) {
                // Windows special case: "C:"
                $root .= $path . '/';
                $path = '';
            } elseif ('/' === $path[2]) {
                // Windows normal case: "C:/"..
                $root .= substr($path, 0, 3);
                $path = $length > 3 ? substr($path, 3) : '';
            }
        }
        return [$root, $path];
    }
    private static function toLower(string $string): string
    {
        if (\false !== $encoding = mb_detect_encoding($string, null, \true)) {
            return mb_strtolower($string, $encoding);
        }
        return strtolower($string);
    }
    private function __construct()
    {
    }
}
Filesystem Component
====================

The Filesystem component provides basic utilities for the filesystem.

Resources
---------

 * [Documentation](https://symfony.com/doc/current/components/filesystem.html)
 * [Contributing](https://symfony.com/doc/current/contributing/index.html)
 * [Report issues](https://github.com/symfony/symfony/issues) and
   [send Pull Requests](https://github.com/symfony/symfony/pulls)
   in the [main Symfony repository](https://github.com/symfony/symfony)
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Filesystem\Exception;

/**
 * IOException interface for file and input/output stream related exceptions thrown by the component.
 *
 * @author Christian Gärtner <christiangaertner.film@googlemail.com>
 */
interface IOExceptionInterface extends ExceptionInterface
{
    /**
     * Returns the associated path for the exception.
     */
    public function getPath(): ?string;
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Filesystem\Exception;

/**
 * Exception interface for all exceptions thrown by the component.
 *
 * @author Romain Neutron <imprec@gmail.com>
 */
interface ExceptionInterface extends \Throwable
{
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Filesystem\Exception;

/**
 * @author Théo Fidry <theo.fidry@gmail.com>
 */
class RuntimeException extends \RuntimeException implements ExceptionInterface
{
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Filesystem\Exception;

/**
 * Exception class thrown when a filesystem operation failure happens.
 *
 * @author Romain Neutron <imprec@gmail.com>
 * @author Christian Gärtner <christiangaertner.film@googlemail.com>
 * @author Fabien Potencier <fabien@symfony.com>
 */
class IOException extends \RuntimeException implements IOExceptionInterface
{
    private ?string $path;
    public function __construct(string $message, int $code = 0, ?\Throwable $previous = null, ?string $path = null)
    {
        $this->path = $path;
        parent::__construct($message, $code, $previous);
    }
    public function getPath(): ?string
    {
        return $this->path;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Filesystem\Exception;

/**
 * @author Christian Flothmann <christian.flothmann@sensiolabs.de>
 */
class InvalidArgumentException extends \InvalidArgumentException implements ExceptionInterface
{
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Filesystem\Exception;

/**
 * Exception class thrown when a file couldn't be found.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 * @author Christian Gärtner <christiangaertner.film@googlemail.com>
 */
class FileNotFoundException extends IOException
{
    public function __construct(?string $message = null, int $code = 0, ?\Throwable $previous = null, ?string $path = null)
    {
        if (null === $message) {
            if (null === $path) {
                $message = 'File could not be found.';
            } else {
                $message = \sprintf('File "%s" could not be found.', $path);
            }
        }
        parent::__construct($message, $code, $previous, $path);
    }
}
{
    "name": "symfony\/filesystem",
    "type": "library",
    "description": "Provides basic utilities for the filesystem",
    "keywords": [],
    "homepage": "https:\/\/symfony.com",
    "license": "MIT",
    "authors": [
        {
            "name": "Fabien Potencier",
            "email": "fabien@symfony.com"
        },
        {
            "name": "Symfony Community",
            "homepage": "https:\/\/symfony.com\/contributors"
        }
    ],
    "require": {
        "php": ">=8.1",
        "symfony\/polyfill-ctype": "~1.8",
        "symfony\/polyfill-mbstring": "~1.8"
    },
    "require-dev": {
        "symfony\/process": "^5.4|^6.4|^7.0"
    },
    "autoload": {
        "psr-4": {
            "_ContaoManager\\Symfony\\Component\\Filesystem\\": ""
        },
        "exclude-from-classmap": [
            "\/Tests\/"
        ]
    },
    "minimum-stability": "dev"
}<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Security\Csrf\TokenStorage;

use _ContaoManager\Symfony\Component\Security\Csrf\Exception\TokenNotFoundException;
/**
 * Token storage that uses PHP's native session handling.
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
class NativeSessionTokenStorage implements ClearableTokenStorageInterface
{
    /**
     * The namespace used to store values in the session.
     */
    public const SESSION_NAMESPACE = '_csrf';
    private bool $sessionStarted = \false;
    private string $namespace;
    /**
     * Initializes the storage with a session namespace.
     *
     * @param string $namespace The namespace under which the token is stored in the session
     */
    public function __construct(string $namespace = self::SESSION_NAMESPACE)
    {
        $this->namespace = $namespace;
    }
    public function getToken(string $tokenId): string
    {
        if (!$this->sessionStarted) {
            $this->startSession();
        }
        if (!isset($_SESSION[$this->namespace][$tokenId])) {
            throw new TokenNotFoundException('The CSRF token with ID ' . $tokenId . ' does not exist.');
        }
        return (string) $_SESSION[$this->namespace][$tokenId];
    }
    /**
     * @return void
     */
    public function setToken(
        string $tokenId,
        #[\SensitiveParameter]
        string $token
    )
    {
        if (!$this->sessionStarted) {
            $this->startSession();
        }
        $_SESSION[$this->namespace][$tokenId] = $token;
    }
    public function hasToken(string $tokenId): bool
    {
        if (!$this->sessionStarted) {
            $this->startSession();
        }
        return isset($_SESSION[$this->namespace][$tokenId]);
    }
    public function removeToken(string $tokenId): ?string
    {
        if (!$this->sessionStarted) {
            $this->startSession();
        }
        if (!isset($_SESSION[$this->namespace][$tokenId])) {
            return null;
        }
        $token = (string) $_SESSION[$this->namespace][$tokenId];
        unset($_SESSION[$this->namespace][$tokenId]);
        if (!$_SESSION[$this->namespace]) {
            unset($_SESSION[$this->namespace]);
        }
        return $token;
    }
    /**
     * @return void
     */
    public function clear()
    {
        unset($_SESSION[$this->namespace]);
    }
    private function startSession(): void
    {
        if (\PHP_SESSION_NONE === session_status()) {
            session_start();
        }
        $this->sessionStarted = \true;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Security\Csrf\TokenStorage;

use _ContaoManager\Symfony\Component\HttpFoundation\Exception\SessionNotFoundException;
use _ContaoManager\Symfony\Component\HttpFoundation\RequestStack;
use _ContaoManager\Symfony\Component\HttpFoundation\Session\SessionInterface;
use _ContaoManager\Symfony\Component\Security\Csrf\Exception\TokenNotFoundException;
/**
 * Token storage that uses a Symfony Session object.
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
class SessionTokenStorage implements ClearableTokenStorageInterface
{
    /**
     * The namespace used to store values in the session.
     */
    public const SESSION_NAMESPACE = '_csrf';
    private RequestStack $requestStack;
    private string $namespace;
    /**
     * Initializes the storage with a RequestStack object and a session namespace.
     *
     * @param string $namespace The namespace under which the token is stored in the requestStack
     */
    public function __construct(RequestStack $requestStack, string $namespace = self::SESSION_NAMESPACE)
    {
        $this->requestStack = $requestStack;
        $this->namespace = $namespace;
    }
    public function getToken(string $tokenId): string
    {
        $session = $this->getSession();
        if (!$session->isStarted()) {
            $session->start();
        }
        if (!$session->has($this->namespace . '/' . $tokenId)) {
            throw new TokenNotFoundException('The CSRF token with ID ' . $tokenId . ' does not exist.');
        }
        return (string) $session->get($this->namespace . '/' . $tokenId);
    }
    /**
     * @return void
     */
    public function setToken(
        string $tokenId,
        #[\SensitiveParameter]
        string $token
    )
    {
        $session = $this->getSession();
        if (!$session->isStarted()) {
            $session->start();
        }
        $session->set($this->namespace . '/' . $tokenId, $token);
    }
    public function hasToken(string $tokenId): bool
    {
        $session = $this->getSession();
        if (!$session->isStarted()) {
            $session->start();
        }
        return $session->has($this->namespace . '/' . $tokenId);
    }
    public function removeToken(string $tokenId): ?string
    {
        $session = $this->getSession();
        if (!$session->isStarted()) {
            $session->start();
        }
        return $session->remove($this->namespace . '/' . $tokenId);
    }
    /**
     * @return void
     */
    public function clear()
    {
        $session = $this->getSession();
        foreach (array_keys($session->all()) as $key) {
            if (str_starts_with($key, $this->namespace . '/')) {
                $session->remove($key);
            }
        }
    }
    /**
     * @throws SessionNotFoundException
     */
    private function getSession(): SessionInterface
    {
        return $this->requestStack->getSession();
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Security\Csrf\TokenStorage;

/**
 * @author Christian Flothmann <christian.flothmann@sensiolabs.de>
 */
interface ClearableTokenStorageInterface extends TokenStorageInterface
{
    /**
     * Removes all CSRF tokens.
     *
     * @return void
     */
    public function clear();
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Security\Csrf\TokenStorage;

/**
 * Stores CSRF tokens.
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
interface TokenStorageInterface
{
    /**
     * Reads a stored CSRF token.
     *
     * @throws \Symfony\Component\Security\Csrf\Exception\TokenNotFoundException If the token ID does not exist
     */
    public function getToken(string $tokenId): string;
    /**
     * Stores a CSRF token.
     *
     * @return void
     */
    public function setToken(
        string $tokenId,
        #[\SensitiveParameter]
        string $token
    );
    /**
     * Removes a CSRF token.
     *
     * @return string|null Returns the removed token if one existed, NULL
     *                     otherwise
     */
    public function removeToken(string $tokenId): ?string;
    /**
     * Checks whether a token with the given token ID exists.
     */
    public function hasToken(string $tokenId): bool;
}
Copyright (c) 2004-present Fabien Potencier

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is furnished
to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
CHANGELOG
=========

6.0
---

 * Remove the `SessionInterface $session` constructor argument of `SessionTokenStorage`, inject a `\Symfony\Component\HttpFoundation\RequestStack $requestStack` instead
 * Using `SessionTokenStorage` outside a request context throws a `SessionNotFoundException`

5.3
---

The CHANGELOG for version 5.3 and earlier can be found at https://github.com/symfony/symfony/blob/5.3/src/Symfony/Component/Security/CHANGELOG.md
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Security\Csrf;

/**
 * A CSRF token.
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
class CsrfToken
{
    private string $id;
    private string $value;
    public function __construct(
        string $id,
        #[\SensitiveParameter]
        ?string $value
    )
    {
        $this->id = $id;
        $this->value = $value ?? '';
    }
    /**
     * Returns the ID of the CSRF token.
     */
    public function getId(): string
    {
        return $this->id;
    }
    /**
     * Returns the value of the CSRF token.
     */
    public function getValue(): string
    {
        return $this->value;
    }
    /**
     * Returns the value of the CSRF token.
     */
    public function __toString(): string
    {
        return $this->value;
    }
}
Security Component - CSRF
=========================

The Security CSRF (cross-site request forgery) component provides a class
`CsrfTokenManager` for generating and validating CSRF tokens.

Sponsor
-------

The Security component for Symfony 6.4 is [backed][1] by [SymfonyCasts][2].

Learn Symfony faster by watching real projects being built and actively coding
along with them. SymfonyCasts bridges that learning gap, bringing you video
tutorials and coding challenges. Code on!

Help Symfony by [sponsoring][3] its development!

Resources
---------

 * [Documentation](https://symfony.com/doc/current/components/security.html)
 * [Contributing](https://symfony.com/doc/current/contributing/index.html)
 * [Report issues](https://github.com/symfony/symfony/issues) and
   [send Pull Requests](https://github.com/symfony/symfony/pulls)
   in the [main Symfony repository](https://github.com/symfony/symfony)

[1]: https://symfony.com/backers
[2]: https://symfonycasts.com
[3]: https://symfony.com/sponsor
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Security\Csrf;

/**
 * Manages CSRF tokens.
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
interface CsrfTokenManagerInterface
{
    /**
     * Returns a CSRF token for the given ID.
     *
     * If previously no token existed for the given ID, a new token is
     * generated. Otherwise the existing token is returned (with the same value,
     * not the same instance).
     *
     * @param string $tokenId The token ID. You may choose an arbitrary value
     *                        for the ID
     */
    public function getToken(string $tokenId): CsrfToken;
    /**
     * Generates a new token value for the given ID.
     *
     * This method will generate a new token for the given token ID, independent
     * of whether a token value previously existed or not. It can be used to
     * enforce once-only tokens in environments with high security needs.
     *
     * @param string $tokenId The token ID. You may choose an arbitrary value
     *                        for the ID
     */
    public function refreshToken(string $tokenId): CsrfToken;
    /**
     * Invalidates the CSRF token with the given ID, if one exists.
     *
     * @return string|null Returns the removed token value if one existed, NULL
     *                     otherwise
     */
    public function removeToken(string $tokenId): ?string;
    /**
     * Returns whether the given CSRF token is valid.
     */
    public function isTokenValid(CsrfToken $token): bool;
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Security\Csrf\TokenGenerator;

/**
 * Generates CSRF tokens.
 *
 * @author Bernhard Schussek <bernhard.schussek@symfony.com>
 */
class UriSafeTokenGenerator implements TokenGeneratorInterface
{
    private int $entropy;
    /**
     * Generates URI-safe CSRF tokens.
     *
     * @param int $entropy The amount of entropy collected for each token (in bits)
     */
    public function __construct(int $entropy = 256)
    {
        if ($entropy <= 7) {
            throw new \InvalidArgumentException('Entropy should be greater than 7.');
        }
        $this->entropy = $entropy;
    }
    public function generateToken(): string
    {
        // Generate an URI safe base64 encoded string that does not contain "+",
        // "/" or "=" which need to be URL encoded and make URLs unnecessarily
        // longer.
        $bytes = random_bytes(intdiv($this->entropy, 8));
        return rtrim(strtr(base64_encode($bytes), '+/', '-_'), '=');
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Security\Csrf\TokenGenerator;

/**
 * Generates CSRF tokens.
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
interface TokenGeneratorInterface
{
    /**
     * Generates a CSRF token.
     */
    public function generateToken(): string;
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Security\Csrf;

use _ContaoManager\Symfony\Component\HttpFoundation\RequestStack;
use _ContaoManager\Symfony\Component\Security\Core\Exception\InvalidArgumentException;
use _ContaoManager\Symfony\Component\Security\Csrf\TokenGenerator\TokenGeneratorInterface;
use _ContaoManager\Symfony\Component\Security\Csrf\TokenGenerator\UriSafeTokenGenerator;
use _ContaoManager\Symfony\Component\Security\Csrf\TokenStorage\NativeSessionTokenStorage;
use _ContaoManager\Symfony\Component\Security\Csrf\TokenStorage\TokenStorageInterface;
/**
 * Default implementation of {@link CsrfTokenManagerInterface}.
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 * @author Kévin Dunglas <dunglas@gmail.com>
 */
class CsrfTokenManager implements CsrfTokenManagerInterface
{
    private TokenGeneratorInterface $generator;
    private TokenStorageInterface $storage;
    private \Closure|string $namespace;
    /**
     * @param $namespace
     *                   * null: generates a namespace using $_SERVER['HTTPS']
     *                   * string: uses the given string
     *                   * RequestStack: generates a namespace using the current main request
     *                   * callable: uses the result of this callable (must return a string)
     */
    public function __construct(?TokenGeneratorInterface $generator = null, ?TokenStorageInterface $storage = null, string|RequestStack|callable|null $namespace = null)
    {
        $this->generator = $generator ?? new UriSafeTokenGenerator();
        $this->storage = $storage ?? new NativeSessionTokenStorage();
        $superGlobalNamespaceGenerator = fn() => !empty($_SERVER['HTTPS']) && 'off' !== strtolower($_SERVER['HTTPS']) ? 'https-' : '';
        if (null === $namespace) {
            $this->namespace = $superGlobalNamespaceGenerator;
        } elseif ($namespace instanceof RequestStack) {
            $this->namespace = function () use ($namespace, $superGlobalNamespaceGenerator) {
                if ($request = $namespace->getMainRequest()) {
                    return $request->isSecure() ? 'https-' : '';
                }
                return $superGlobalNamespaceGenerator();
            };
        } elseif ($namespace instanceof \Closure || \is_string($namespace)) {
            $this->namespace = $namespace;
        } elseif (\is_callable($namespace)) {
            $this->namespace = $namespace(...);
        } else {
            throw new InvalidArgumentException(\sprintf('$namespace must be a string, a callable returning a string, null or an instance of "RequestStack". "%s" given.', get_debug_type($namespace)));
        }
    }
    public function getToken(string $tokenId): CsrfToken
    {
        $namespacedId = $this->getNamespace() . $tokenId;
        if ($this->storage->hasToken($namespacedId)) {
            $value = $this->storage->getToken($namespacedId);
        } else {
            $value = $this->generator->generateToken();
            $this->storage->setToken($namespacedId, $value);
        }
        return new CsrfToken($tokenId, $this->randomize($value));
    }
    public function refreshToken(string $tokenId): CsrfToken
    {
        $namespacedId = $this->getNamespace() . $tokenId;
        $value = $this->generator->generateToken();
        $this->storage->setToken($namespacedId, $value);
        return new CsrfToken($tokenId, $this->randomize($value));
    }
    public function removeToken(string $tokenId): ?string
    {
        return $this->storage->removeToken($this->getNamespace() . $tokenId);
    }
    public function isTokenValid(CsrfToken $token): bool
    {
        $namespacedId = $this->getNamespace() . $token->getId();
        if (!$this->storage->hasToken($namespacedId)) {
            return \false;
        }
        return hash_equals($this->storage->getToken($namespacedId), $this->derandomize($token->getValue()));
    }
    private function getNamespace(): string
    {
        return \is_callable($ns = $this->namespace) ? $ns() : $ns;
    }
    private function randomize(string $value): string
    {
        $key = random_bytes(32);
        $value = $this->xor($value, $key);
        return \sprintf('%s.%s.%s', substr(hash('xxh128', $key), 0, 1 + \ord($key[0]) % 32), rtrim(strtr(base64_encode($key), '+/', '-_'), '='), rtrim(strtr(base64_encode($value), '+/', '-_'), '='));
    }
    private function derandomize(string $value): string
    {
        $parts = explode('.', $value);
        if (3 !== \count($parts)) {
            return $value;
        }
        $key = base64_decode(strtr($parts[1], '-_', '+/'));
        if ('' === $key || \false === $key) {
            return $value;
        }
        $value = base64_decode(strtr($parts[2], '-_', '+/'));
        return $this->xor($value, $key);
    }
    private function xor(string $value, string $key): string
    {
        if (\strlen($value) > \strlen($key)) {
            $key = str_repeat($key, ceil(\strlen($value) / \strlen($key)));
        }
        return $value ^ $key;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Security\Csrf\Exception;

use _ContaoManager\Symfony\Component\Security\Core\Exception\RuntimeException;
/**
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
class TokenNotFoundException extends RuntimeException
{
}
{
    "name": "symfony\/security-csrf",
    "type": "library",
    "description": "Symfony Security Component - CSRF Library",
    "keywords": [],
    "homepage": "https:\/\/symfony.com",
    "license": "MIT",
    "authors": [
        {
            "name": "Fabien Potencier",
            "email": "fabien@symfony.com"
        },
        {
            "name": "Symfony Community",
            "homepage": "https:\/\/symfony.com\/contributors"
        }
    ],
    "require": {
        "php": ">=8.1",
        "symfony\/security-core": "^5.4|^6.0|^7.0"
    },
    "require-dev": {
        "symfony\/http-foundation": "^5.4|^6.0|^7.0"
    },
    "conflict": {
        "symfony\/http-foundation": "<5.4"
    },
    "autoload": {
        "psr-4": {
            "_ContaoManager\\Symfony\\Component\\Security\\Csrf\\": ""
        },
        "exclude-from-classmap": [
            "\/Tests\/"
        ]
    },
    "minimum-stability": "dev"
}<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

use Symfony\Polyfill\Uuid as p;

if (!defined('UUID_VARIANT_NCS')) {
    define('UUID_VARIANT_NCS', 0);
}
if (!defined('UUID_VARIANT_DCE')) {
    define('UUID_VARIANT_DCE', 1);
}
if (!defined('UUID_VARIANT_MICROSOFT')) {
    define('UUID_VARIANT_MICROSOFT', 2);
}
if (!defined('UUID_VARIANT_OTHER')) {
    define('UUID_VARIANT_OTHER', 3);
}
if (!defined('UUID_TYPE_DEFAULT')) {
    define('UUID_TYPE_DEFAULT', 0);
}
if (!defined('UUID_TYPE_TIME')) {
    define('UUID_TYPE_TIME', 1);
}
if (!defined('UUID_TYPE_MD5')) {
    define('UUID_TYPE_MD5', 3);
}
if (!defined('UUID_TYPE_DCE')) {
    define('UUID_TYPE_DCE', 4); // Deprecated alias
}
if (!defined('UUID_TYPE_NAME')) {
    define('UUID_TYPE_NAME', 1); // Deprecated alias
}
if (!defined('UUID_TYPE_RANDOM')) {
    define('UUID_TYPE_RANDOM', 4);
}
if (!defined('UUID_TYPE_SHA1')) {
    define('UUID_TYPE_SHA1', 5);
}
if (!defined('UUID_TYPE_NULL')) {
    define('UUID_TYPE_NULL', -1);
}
if (!defined('UUID_TYPE_INVALID')) {
    define('UUID_TYPE_INVALID', -42);
}

if (!function_exists('uuid_create')) {
    function uuid_create(?int $uuid_type = \UUID_TYPE_DEFAULT): string { return p\Uuid::uuid_create((int) $uuid_type); }
}
if (!function_exists('uuid_generate_md5')) {
    function uuid_generate_md5(?string $uuid_ns, ?string $name): string { return p\Uuid::uuid_generate_md5((string) $uuid_ns, (string) $name); }
}
if (!function_exists('uuid_generate_sha1')) {
    function uuid_generate_sha1(?string $uuid_ns, ?string $name): string { return p\Uuid::uuid_generate_sha1((string) $uuid_ns, (string) $name); }
}
if (!function_exists('uuid_is_valid')) {
    function uuid_is_valid(?string $uuid): bool { return p\Uuid::uuid_is_valid((string) $uuid); }
}
if (!function_exists('uuid_compare')) {
    function uuid_compare(?string $uuid1, ?string $uuid2): int { return p\Uuid::uuid_compare((string) $uuid1, (string) $uuid2); }
}
if (!function_exists('uuid_is_null')) {
    function uuid_is_null(?string $uuid): bool { return p\Uuid::uuid_is_null((string) $uuid); }
}
if (!function_exists('uuid_type')) {
    function uuid_type(?string $uuid): int { return p\Uuid::uuid_type((string) $uuid); }
}
if (!function_exists('uuid_variant')) {
    function uuid_variant(?string $uuid): int { return p\Uuid::uuid_variant((string) $uuid); }
}
if (!function_exists('uuid_time')) {
    function uuid_time(?string $uuid): int { return p\Uuid::uuid_time((string) $uuid); }
}
if (!function_exists('uuid_mac')) {
    function uuid_mac(?string $uuid): string { return p\Uuid::uuid_mac((string) $uuid); }
}
if (!function_exists('uuid_parse')) {
    function uuid_parse(?string $uuid): string { return p\Uuid::uuid_parse((string) $uuid); }
}
if (!function_exists('uuid_unparse')) {
    function uuid_unparse(?string $uuid): string { return p\Uuid::uuid_unparse((string) $uuid); }
}
Copyright (c) 2018-present Fabien Potencier

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is furnished
to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Symfony\Polyfill\Uuid;

/**
 * @internal
 *
 * @author Grégoire Pineau <lyrixx@lyrixx.info>
 */
final class Uuid
{
    public const UUID_VARIANT_NCS = 0;
    public const UUID_VARIANT_DCE = 1;
    public const UUID_VARIANT_MICROSOFT = 2;
    public const UUID_VARIANT_OTHER = 3;
    public const UUID_TYPE_DEFAULT = 0;
    public const UUID_TYPE_TIME = 1;
    public const UUID_TYPE_MD5 = 3;
    public const UUID_TYPE_DCE = 4;
    // Deprecated alias
    public const UUID_TYPE_NAME = 1;
    // Deprecated alias
    public const UUID_TYPE_RANDOM = 4;
    public const UUID_TYPE_SHA1 = 5;
    public const UUID_TYPE_NULL = -1;
    public const UUID_TYPE_INVALID = -42;
    // https://tools.ietf.org/html/rfc4122#section-4.1.4
    // 0x01b21dd213814000 is the number of 100-ns intervals between the
    // UUID epoch 1582-10-15 00:00:00 and the Unix epoch 1970-01-01 00:00:00.
    public const TIME_OFFSET_INT = 0x1b21dd213814000;
    public const TIME_OFFSET_BIN = "\x01\xb2\x1d\xd2\x13\x81@\x00";
    public const TIME_OFFSET_COM = "\xfeM\xe2-\xec~\xc0\x00";
    public static function uuid_create($uuid_type = \UUID_TYPE_DEFAULT)
    {
        if (!is_numeric($uuid_type) && null !== $uuid_type) {
            trigger_error(\sprintf('uuid_create() expects parameter 1 to be int, %s given', \gettype($uuid_type)), \E_USER_WARNING);
            return null;
        }
        switch ((int) $uuid_type) {
            case self::UUID_TYPE_NAME:
            case self::UUID_TYPE_TIME:
                return self::uuid_generate_time();
            case self::UUID_TYPE_DCE:
            case self::UUID_TYPE_RANDOM:
            case self::UUID_TYPE_DEFAULT:
                return self::uuid_generate_random();
            default:
                trigger_error(\sprintf("Unknown/invalid UUID type '%d' requested, using default type instead", $uuid_type), \E_USER_WARNING);
                return self::uuid_generate_random();
        }
    }
    public static function uuid_generate_md5($uuid_ns, $name)
    {
        if (!\is_string($uuid_ns = self::toString($uuid_ns))) {
            trigger_error(\sprintf('uuid_generate_md5() expects parameter 1 to be string, %s given', \gettype($uuid_ns)), \E_USER_WARNING);
            return null;
        }
        if (!\is_string($name = self::toString($name))) {
            trigger_error(\sprintf('uuid_generate_md5() expects parameter 2 to be string, %s given', \gettype($name)), \E_USER_WARNING);
            return null;
        }
        if (!self::isValid($uuid_ns)) {
            if (80000 > \PHP_VERSION_ID) {
                return \false;
            }
            throw new \ValueError('uuid_generate_md5(): Argument #1 ($uuid_ns) UUID expected');
        }
        $hash = md5(hex2bin(str_replace('-', '', $uuid_ns)) . $name);
        return \sprintf(
            '%08s-%04s-3%03s-%04x-%012s',
            // 32 bits for "time_low"
            substr($hash, 0, 8),
            // 16 bits for "time_mid"
            substr($hash, 8, 4),
            // 16 bits for "time_hi_and_version",
            // four most significant bits holds version number 3
            substr($hash, 13, 3),
            // 16 bits:
            // * 8 bits for "clk_seq_hi_res",
            // * 8 bits for "clk_seq_low",
            hexdec(substr($hash, 16, 4)) & 0x3fff | 0x8000,
            // 48 bits for "node"
            substr($hash, 20, 12)
        );
    }
    public static function uuid_generate_sha1($uuid_ns, $name)
    {
        if (!\is_string($uuid_ns = self::toString($uuid_ns))) {
            trigger_error(\sprintf('uuid_generate_sha1() expects parameter 1 to be string, %s given', \gettype($uuid_ns)), \E_USER_WARNING);
            return null;
        }
        if (!\is_string($name = self::toString($name))) {
            trigger_error(\sprintf('uuid_generate_sha1() expects parameter 2 to be string, %s given', \gettype($name)), \E_USER_WARNING);
            return null;
        }
        if (!self::isValid($uuid_ns)) {
            if (80000 > \PHP_VERSION_ID) {
                return \false;
            }
            throw new \ValueError('uuid_generate_sha1(): Argument #1 ($uuid_ns) UUID expected');
        }
        $hash = sha1(hex2bin(str_replace('-', '', $uuid_ns)) . $name);
        return \sprintf(
            '%08s-%04s-5%03s-%04x-%012s',
            // 32 bits for "time_low"
            substr($hash, 0, 8),
            // 16 bits for "time_mid"
            substr($hash, 8, 4),
            // 16 bits for "time_hi_and_version",
            // four most significant bits holds version number 5
            substr($hash, 13, 3),
            // 16 bits:
            // * 8 bits for "clk_seq_hi_res",
            // * 8 bits for "clk_seq_low",
            // WARNING: On old libuuid version, there is a bug. 0x0fff is used instead of 0x3fff
            // See https://github.com/karelzak/util-linux/commit/d6ddf07d31dfdc894eb8e7e6842aa856342c526e
            hexdec(substr($hash, 16, 4)) & 0x3fff | 0x8000,
            // 48 bits for "node"
            substr($hash, 20, 12)
        );
    }
    public static function uuid_is_valid($uuid)
    {
        if (!\is_string($uuid = self::toString($uuid))) {
            trigger_error(\sprintf('uuid_is_valid() expects parameter 1 to be string, %s given', \gettype($uuid)), \E_USER_WARNING);
            return null;
        }
        return self::isValid($uuid);
    }
    public static function uuid_compare($uuid1, $uuid2)
    {
        if (!\is_string($uuid1 = self::toString($uuid1))) {
            trigger_error(\sprintf('uuid_compare() expects parameter 1 to be string, %s given', \gettype($uuid1)), \E_USER_WARNING);
            return null;
        }
        if (!\is_string($uuid2 = self::toString($uuid2))) {
            trigger_error(\sprintf('uuid_compare() expects parameter 2 to be string, %s given', \gettype($uuid2)), \E_USER_WARNING);
            return null;
        }
        if (!self::isValid($uuid1)) {
            if (80000 > \PHP_VERSION_ID) {
                return \false;
            }
            throw new \ValueError('uuid_compare(): Argument #1 ($uuid1) UUID expected');
        }
        if (!self::isValid($uuid2)) {
            if (80000 > \PHP_VERSION_ID) {
                return \false;
            }
            throw new \ValueError('uuid_compare(): Argument #2 ($uuid2) UUID expected');
        }
        return strcasecmp($uuid1, $uuid2);
    }
    public static function uuid_is_null($uuid)
    {
        if (!\is_string($uuid = self::toString($uuid))) {
            trigger_error(\sprintf('uuid_is_null() expects parameter 1 to be string, %s given', \gettype($uuid)), \E_USER_WARNING);
            return null;
        }
        if (80000 <= \PHP_VERSION_ID && !self::isValid($uuid)) {
            throw new \ValueError('uuid_is_null(): Argument #1 ($uuid) UUID expected');
        }
        return '00000000-0000-0000-0000-000000000000' === $uuid;
    }
    public static function uuid_type($uuid)
    {
        if (!\is_string($uuid = self::toString($uuid))) {
            trigger_error(\sprintf('uuid_type() expects parameter 1 to be string, %s given', \gettype($uuid)), \E_USER_WARNING);
            return null;
        }
        if ('00000000-0000-0000-0000-000000000000' === $uuid) {
            return self::UUID_TYPE_NULL;
        }
        if (null === $parsed = self::parse($uuid)) {
            if (80000 > \PHP_VERSION_ID) {
                return \false;
            }
            throw new \ValueError('uuid_type(): Argument #1 ($uuid) UUID expected');
        }
        return $parsed['version'];
    }
    public static function uuid_variant($uuid)
    {
        if (!\is_string($uuid = self::toString($uuid))) {
            trigger_error(\sprintf('uuid_variant() expects parameter 1 to be string, %s given', \gettype($uuid)), \E_USER_WARNING);
            return null;
        }
        if ('00000000-0000-0000-0000-000000000000' === $uuid) {
            return self::UUID_TYPE_NULL;
        }
        if (null === $parsed = self::parse($uuid)) {
            if (80000 > \PHP_VERSION_ID) {
                return \false;
            }
            throw new \ValueError('uuid_variant(): Argument #1 ($uuid) UUID expected');
        }
        if (($parsed['clock_seq'] & 0x8000) === 0) {
            return self::UUID_VARIANT_NCS;
        }
        if (($parsed['clock_seq'] & 0x4000) === 0) {
            return self::UUID_VARIANT_DCE;
        }
        if (($parsed['clock_seq'] & 0x2000) === 0) {
            return self::UUID_VARIANT_MICROSOFT;
        }
        return self::UUID_VARIANT_OTHER;
    }
    public static function uuid_time($uuid)
    {
        if (!\is_string($uuid = self::toString($uuid))) {
            trigger_error(\sprintf('uuid_time() expects parameter 1 to be string, %s given', \gettype($uuid)), \E_USER_WARNING);
            return null;
        }
        $parsed = self::parse($uuid);
        if (self::UUID_TYPE_TIME !== ($parsed['version'] ?? null)) {
            if (80000 > \PHP_VERSION_ID) {
                return \false;
            }
            throw new \ValueError('uuid_time(): Argument #1 ($uuid) UUID DCE TIME expected');
        }
        if (\PHP_INT_SIZE >= 8) {
            return intdiv(hexdec($parsed['time']) - self::TIME_OFFSET_INT, 10000000);
        }
        $time = str_pad(hex2bin($parsed['time']), 8, "\x00", \STR_PAD_LEFT);
        $time = self::binaryAdd($time, self::TIME_OFFSET_COM);
        $time[0] = $time[0] & "";
        return (int) substr(self::toDecimal($time), 0, -7);
    }
    public static function uuid_mac($uuid)
    {
        if (!\is_string($uuid = self::toString($uuid))) {
            trigger_error(\sprintf('uuid_mac() expects parameter 1 to be string, %s given', \gettype($uuid)), \E_USER_WARNING);
            return null;
        }
        $parsed = self::parse($uuid);
        if (self::UUID_TYPE_TIME !== ($parsed['version'] ?? null)) {
            if (80000 > \PHP_VERSION_ID) {
                return \false;
            }
            throw new \ValueError('uuid_mac(): Argument #1 ($uuid) UUID DCE TIME expected');
        }
        return strtr($parsed['node'], 'ABCDEF', 'abcdef');
    }
    public static function uuid_parse($uuid)
    {
        if (!\is_string($uuid = self::toString($uuid))) {
            trigger_error(\sprintf('uuid_parse() expects parameter 1 to be string, %s given', \gettype($uuid)), \E_USER_WARNING);
            return null;
        }
        if (!self::isValid($uuid)) {
            if (80000 > \PHP_VERSION_ID) {
                return \false;
            }
            throw new \ValueError('uuid_parse(): Argument #1 ($uuid) UUID expected');
        }
        return hex2bin(str_replace('-', '', $uuid));
    }
    public static function uuid_unparse($bytes)
    {
        if (!\is_string($bytes = self::toString($bytes))) {
            trigger_error(\sprintf('uuid_unparse() expects parameter 1 to be string, %s given', \gettype($bytes)), \E_USER_WARNING);
            return null;
        }
        if (16 !== \strlen($bytes)) {
            if (80000 > \PHP_VERSION_ID) {
                return \false;
            }
            throw new \ValueError('uuid_unparse(): Argument #1 ($uuid) UUID expected');
        }
        $uuid = bin2hex($bytes);
        $uuid = substr_replace($uuid, '-', 8, 0);
        $uuid = substr_replace($uuid, '-', 13, 0);
        $uuid = substr_replace($uuid, '-', 18, 0);
        return substr_replace($uuid, '-', 23, 0);
    }
    private static function uuid_generate_random()
    {
        $uuid = bin2hex(random_bytes(16));
        return \sprintf(
            '%08s-%04s-4%03s-%04x-%012s',
            // 32 bits for "time_low"
            substr($uuid, 0, 8),
            // 16 bits for "time_mid"
            substr($uuid, 8, 4),
            // 16 bits for "time_hi_and_version",
            // four most significant bits holds version number 4
            substr($uuid, 13, 3),
            // 16 bits:
            // * 8 bits for "clk_seq_hi_res",
            // * 8 bits for "clk_seq_low",
            // two most significant bits holds zero and one for variant DCE1.1
            hexdec(substr($uuid, 16, 4)) & 0x3fff | 0x8000,
            // 48 bits for "node"
            substr($uuid, 20, 12)
        );
    }
    /**
     * @see http://tools.ietf.org/html/rfc4122#section-4.2.2
     */
    private static function uuid_generate_time()
    {
        $time = microtime(\false);
        $time = substr($time, 11) . substr($time, 2, 7);
        if (\PHP_INT_SIZE >= 8) {
            $time = str_pad(dechex($time + self::TIME_OFFSET_INT), 16, '0', \STR_PAD_LEFT);
        } else {
            $time = str_pad(self::toBinary($time), 8, "\x00", \STR_PAD_LEFT);
            $time = self::binaryAdd($time, self::TIME_OFFSET_BIN);
            $time = bin2hex($time);
        }
        // https://tools.ietf.org/html/rfc4122#section-4.1.5
        // We are using a random data for the sake of simplicity: since we are
        // not able to get a super precise timeOfDay as a unique sequence
        $clockSeq = random_int(0, 0x3fff);
        static $node;
        if (null === $node) {
            if (\function_exists('apcu_fetch')) {
                $node = apcu_fetch('__symfony_uuid_node');
                if (\false === $node) {
                    $node = \sprintf('%06x%06x', random_int(0, 0xffffff) | 0x10000, random_int(0, 0xffffff));
                    apcu_store('__symfony_uuid_node', $node);
                }
            } else {
                $node = \sprintf('%06x%06x', random_int(0, 0xffffff) | 0x10000, random_int(0, 0xffffff));
            }
        }
        return \sprintf(
            '%08s-%04s-1%03s-%04x-%012s',
            // 32 bits for "time_low"
            substr($time, -8),
            // 16 bits for "time_mid"
            substr($time, -12, 4),
            // 16 bits for "time_hi_and_version",
            // four most significant bits holds version number 1
            substr($time, -15, 3),
            // 16 bits:
            // * 8 bits for "clk_seq_hi_res",
            // * 8 bits for "clk_seq_low",
            // two most significant bits holds zero and one for variant DCE1.1
            $clockSeq | 0x8000,
            // 48 bits for "node"
            $node
        );
    }
    private static function isValid($uuid)
    {
        return (bool) preg_match('{^[0-9a-f]{8}(?:-[0-9a-f]{4}){3}-[0-9a-f]{12}$}Di', $uuid);
    }
    private static function parse($uuid)
    {
        if (!preg_match('{^(?<time_low>[0-9a-f]{8})-(?<time_mid>[0-9a-f]{4})-(?<version>[0-9a-f])(?<time_hi>[0-9a-f]{3})-(?<clock_seq>[0-9a-f]{4})-(?<node>[0-9a-f]{12})$}Di', $uuid, $matches)) {
            return null;
        }
        return ['time' => '0' . $matches['time_hi'] . $matches['time_mid'] . $matches['time_low'], 'version' => hexdec($matches['version']), 'clock_seq' => hexdec($matches['clock_seq']), 'node' => $matches['node']];
    }
    private static function toString($v)
    {
        if (\is_string($v) || null === $v || (\is_object($v) ? method_exists($v, '__toString') : \is_scalar($v))) {
            return (string) $v;
        }
        return $v;
    }
    private static function toBinary($digits)
    {
        $bytes = '';
        $count = \strlen($digits);
        while ($count) {
            $quotient = [];
            $remainder = 0;
            for ($i = 0; $i !== $count; ++$i) {
                $carry = $digits[$i] + $remainder * 10;
                $digit = $carry >> 8;
                $remainder = $carry & 0xff;
                if ($digit || $quotient) {
                    $quotient[] = $digit;
                }
            }
            $bytes = \chr($remainder) . $bytes;
            $count = \count($digits = $quotient);
        }
        return $bytes;
    }
    private static function toDecimal($bytes)
    {
        $digits = '';
        $bytes = array_values(unpack('C*', $bytes));
        while ($count = \count($bytes)) {
            $quotient = [];
            $remainder = 0;
            for ($i = 0; $i !== $count; ++$i) {
                $carry = $bytes[$i] + ($remainder << 8);
                $digit = (int) ($carry / 10);
                $remainder = $carry % 10;
                if ($digit || $quotient) {
                    $quotient[] = $digit;
                }
            }
            $digits = $remainder . $digits;
            $bytes = $quotient;
        }
        return $digits;
    }
    private static function binaryAdd($a, $b)
    {
        $sum = 0;
        for ($i = 7; 0 <= $i; --$i) {
            $sum += \ord($a[$i]) + \ord($b[$i]);
            $a[$i] = \chr($sum & 0xff);
            $sum >>= 8;
        }
        return $a;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

use Symfony\Polyfill\Uuid as p;

if (extension_loaded('uuid')) {
    return;
}

if (\PHP_VERSION_ID >= 80000) {
    return require __DIR__.'/bootstrap80.php';
}

if (!defined('UUID_VARIANT_NCS')) {
    define('UUID_VARIANT_NCS', 0);
}
if (!defined('UUID_VARIANT_DCE')) {
    define('UUID_VARIANT_DCE', 1);
}
if (!defined('UUID_VARIANT_MICROSOFT')) {
    define('UUID_VARIANT_MICROSOFT', 2);
}
if (!defined('UUID_VARIANT_OTHER')) {
    define('UUID_VARIANT_OTHER', 3);
}
if (!defined('UUID_TYPE_DEFAULT')) {
    define('UUID_TYPE_DEFAULT', 0);
}
if (!defined('UUID_TYPE_TIME')) {
    define('UUID_TYPE_TIME', 1);
}
if (!defined('UUID_TYPE_MD5')) {
    define('UUID_TYPE_MD5', 3);
}
if (!defined('UUID_TYPE_DCE')) {
    define('UUID_TYPE_DCE', 4); // Deprecated alias
}
if (!defined('UUID_TYPE_NAME')) {
    define('UUID_TYPE_NAME', 1); // Deprecated alias
}
if (!defined('UUID_TYPE_RANDOM')) {
    define('UUID_TYPE_RANDOM', 4);
}
if (!defined('UUID_TYPE_SHA1')) {
    define('UUID_TYPE_SHA1', 5);
}
if (!defined('UUID_TYPE_NULL')) {
    define('UUID_TYPE_NULL', -1);
}
if (!defined('UUID_TYPE_INVALID')) {
    define('UUID_TYPE_INVALID', -42);
}

if (!function_exists('uuid_create')) {
    function uuid_create($uuid_type = \UUID_TYPE_DEFAULT) { return p\Uuid::uuid_create($uuid_type); }
}
if (!function_exists('uuid_generate_md5')) {
    function uuid_generate_md5($uuid_ns, $name) { return p\Uuid::uuid_generate_md5($uuid_ns, $name); }
}
if (!function_exists('uuid_generate_sha1')) {
    function uuid_generate_sha1($uuid_ns, $name) { return p\Uuid::uuid_generate_sha1($uuid_ns, $name); }
}
if (!function_exists('uuid_is_valid')) {
    function uuid_is_valid($uuid) { return p\Uuid::uuid_is_valid($uuid); }
}
if (!function_exists('uuid_compare')) {
    function uuid_compare($uuid1, $uuid2) { return p\Uuid::uuid_compare($uuid1, $uuid2); }
}
if (!function_exists('uuid_is_null')) {
    function uuid_is_null($uuid) { return p\Uuid::uuid_is_null($uuid); }
}
if (!function_exists('uuid_type')) {
    function uuid_type($uuid) { return p\Uuid::uuid_type($uuid); }
}
if (!function_exists('uuid_variant')) {
    function uuid_variant($uuid) { return p\Uuid::uuid_variant($uuid); }
}
if (!function_exists('uuid_time')) {
    function uuid_time($uuid) { return p\Uuid::uuid_time($uuid); }
}
if (!function_exists('uuid_mac')) {
    function uuid_mac($uuid) { return p\Uuid::uuid_mac($uuid); }
}
if (!function_exists('uuid_parse')) {
    function uuid_parse($uuid) { return p\Uuid::uuid_parse($uuid); }
}
if (!function_exists('uuid_unparse')) {
    function uuid_unparse($uuid) { return p\Uuid::uuid_unparse($uuid); }
}
Symfony Polyfill / Uuid
========================

This component provides `uuid_*` functions to users who run PHP versions without the uuid extension.

More information can be found in the
[main Polyfill README](https://github.com/symfony/polyfill/blob/main/README.md).

License
=======

This library is released under the [MIT license](LICENSE).
{
    "name": "symfony\/polyfill-uuid",
    "type": "library",
    "description": "Symfony polyfill for uuid functions",
    "keywords": [
        "polyfill",
        "compatibility",
        "portable",
        "uuid"
    ],
    "homepage": "https:\/\/symfony.com",
    "license": "MIT",
    "authors": [
        {
            "name": "Gr\u00e9goire Pineau",
            "email": "lyrixx@lyrixx.info"
        },
        {
            "name": "Symfony Community",
            "homepage": "https:\/\/symfony.com\/contributors"
        }
    ],
    "require": {
        "php": ">=7.2"
    },
    "provide": {
        "ext-uuid": "*"
    },
    "autoload": {
        "psr-4": {
            "Symfony\\Polyfill\\Uuid\\": ""
        },
        "files": [
            "bootstrap.php"
        ]
    },
    "suggest": {
        "ext-uuid": "For best performance"
    },
    "minimum-stability": "dev",
    "extra": {
        "thanks": {
            "name": "symfony\/polyfill",
            "url": "https:\/\/github.com\/symfony\/polyfill"
        }
    }
}<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

use Symfony\Polyfill\Intl\Normalizer as p;

if (!function_exists('normalizer_is_normalized')) {
    function normalizer_is_normalized(?string $string, ?int $form = p\Normalizer::FORM_C): bool { return p\Normalizer::isNormalized((string) $string, (int) $form); }
}
if (!function_exists('normalizer_normalize')) {
    function normalizer_normalize(?string $string, ?int $form = p\Normalizer::FORM_C): string|false { return p\Normalizer::normalize((string) $string, (int) $form); }
}
Copyright (c) 2015-present Fabien Potencier

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is furnished
to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Symfony\Polyfill\Intl\Normalizer;

/**
 * Normalizer is a PHP fallback implementation of the Normalizer class provided by the intl extension.
 *
 * It has been validated with Unicode 6.3 Normalization Conformance Test.
 * See http://www.unicode.org/reports/tr15/ for detailed info about Unicode normalizations.
 *
 * @author Nicolas Grekas <p@tchwork.com>
 *
 * @internal
 */
class Normalizer
{
    public const FORM_D = \Normalizer::FORM_D;
    public const FORM_KD = \Normalizer::FORM_KD;
    public const FORM_C = \Normalizer::FORM_C;
    public const FORM_KC = \Normalizer::FORM_KC;
    public const NFD = \Normalizer::NFD;
    public const NFKD = \Normalizer::NFKD;
    public const NFC = \Normalizer::NFC;
    public const NFKC = \Normalizer::NFKC;
    private static $C;
    private static $D;
    private static $KD;
    private static $cC;
    private static $ulenMask = ["\xc0" => 2, "\xd0" => 2, "\xe0" => 3, "\xf0" => 4];
    private static $ASCII = " eiasntrolud][cmp'\ng|hv.fb,:=-q10C2*yx)(L9AS/P\"EjMIk3>5T<D4}B{8FwR67UGN;JzV#HOW_&!K?XQ%Y\\\tZ+~^\$@`\x00\x01\x02\x03\x04\x05\x06\x07\x08\v\f\r\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f";
    public static function isNormalized(string $s, int $form = self::FORM_C)
    {
        if (!\in_array($form, [self::NFD, self::NFKD, self::NFC, self::NFKC])) {
            return \false;
        }
        if (!isset($s[strspn($s, self::$ASCII)])) {
            return \true;
        }
        if (self::NFC == $form && preg_match('//u', $s) && !preg_match('/[^\x00-\x{2FF}]/u', $s)) {
            return \true;
        }
        return self::normalize($s, $form) === $s;
    }
    public static function normalize(string $s, int $form = self::FORM_C)
    {
        if (!preg_match('//u', $s)) {
            return \false;
        }
        switch ($form) {
            case self::NFC:
                $C = \true;
                $K = \false;
                break;
            case self::NFD:
                $C = \false;
                $K = \false;
                break;
            case self::NFKC:
                $C = \true;
                $K = \true;
                break;
            case self::NFKD:
                $C = \false;
                $K = \true;
                break;
            default:
                if (\defined('Normalizer::NONE') && \Normalizer::NONE == $form) {
                    return $s;
                }
                if (80000 > \PHP_VERSION_ID) {
                    return \false;
                }
                throw new \ValueError('normalizer_normalize(): Argument #2 ($form) must be a a valid normalization form');
        }
        if ('' === $s) {
            return '';
        }
        if ($K && null === self::$KD) {
            self::$KD = self::getData('compatibilityDecomposition');
        }
        if (null === self::$D) {
            self::$D = self::getData('canonicalDecomposition');
            self::$cC = self::getData('combiningClass');
        }
        if (null !== $mbEncoding = 2 & (int) \ini_get('mbstring.func_overload') ? mb_internal_encoding() : null) {
            mb_internal_encoding('8bit');
        }
        $r = self::decompose($s, $K);
        if ($C) {
            if (null === self::$C) {
                self::$C = self::getData('canonicalComposition');
            }
            $r = self::recompose($r);
        }
        if (null !== $mbEncoding) {
            mb_internal_encoding($mbEncoding);
        }
        return $r;
    }
    private static function recompose($s)
    {
        $ASCII = self::$ASCII;
        $compMap = self::$C;
        $combClass = self::$cC;
        $ulenMask = self::$ulenMask;
        $result = $tail = '';
        $i = $s[0] < "\x80" ? 1 : $ulenMask[$s[0] & "\xf0"];
        $len = \strlen($s);
        $lastUchr = substr($s, 0, $i);
        $lastUcls = isset($combClass[$lastUchr]) ? 256 : 0;
        while ($i < $len) {
            if ($s[$i] < "\x80") {
                // ASCII chars
                if ($tail) {
                    $lastUchr .= $tail;
                    $tail = '';
                }
                if ($j = strspn($s, $ASCII, $i + 1)) {
                    $lastUchr .= substr($s, $i, $j);
                    $i += $j;
                }
                $result .= $lastUchr;
                $lastUchr = $s[$i];
                $lastUcls = 0;
                ++$i;
                continue;
            }
            $ulen = $ulenMask[$s[$i] & "\xf0"];
            $uchr = substr($s, $i, $ulen);
            if ($lastUchr < "ᄀ" || "ᄒ" < $lastUchr || $uchr < "ᅡ" || "ᅵ" < $uchr || $lastUcls) {
                // Table lookup and combining chars composition
                $ucls = $combClass[$uchr] ?? 0;
                if (isset($compMap[$lastUchr . $uchr]) && (!$lastUcls || $lastUcls < $ucls)) {
                    $lastUchr = $compMap[$lastUchr . $uchr];
                } elseif ($lastUcls = $ucls) {
                    $tail .= $uchr;
                } else {
                    if ($tail) {
                        $lastUchr .= $tail;
                        $tail = '';
                    }
                    $result .= $lastUchr;
                    $lastUchr = $uchr;
                }
            } else {
                // Hangul chars
                $L = \ord($lastUchr[2]) - 0x80;
                $V = \ord($uchr[2]) - 0xa1;
                $T = 0;
                $uchr = substr($s, $i + $ulen, 3);
                if ("ᆧ" <= $uchr && $uchr <= "ᇂ") {
                    $T = \ord($uchr[2]) - 0xa7;
                    0 > $T && $T += 0x40;
                    $ulen += 3;
                }
                $L = 0xac00 + ($L * 21 + $V) * 28 + $T;
                $lastUchr = \chr(0xe0 | $L >> 12) . \chr(0x80 | $L >> 6 & 0x3f) . \chr(0x80 | $L & 0x3f);
            }
            $i += $ulen;
        }
        return $result . $lastUchr . $tail;
    }
    private static function decompose($s, $c)
    {
        $result = '';
        $ASCII = self::$ASCII;
        $decompMap = self::$D;
        $combClass = self::$cC;
        $ulenMask = self::$ulenMask;
        if ($c) {
            $compatMap = self::$KD;
        }
        $c = [];
        $i = 0;
        $len = \strlen($s);
        while ($i < $len) {
            if ($s[$i] < "\x80") {
                // ASCII chars
                if ($c) {
                    ksort($c);
                    $result .= implode('', $c);
                    $c = [];
                }
                $j = 1 + strspn($s, $ASCII, $i + 1);
                $result .= substr($s, $i, $j);
                $i += $j;
                continue;
            }
            $ulen = $ulenMask[$s[$i] & "\xf0"];
            $uchr = substr($s, $i, $ulen);
            $i += $ulen;
            if ($uchr < "가" || "힣" < $uchr) {
                // Table lookup
                if ($uchr !== $j = $compatMap[$uchr] ?? $decompMap[$uchr] ?? $uchr) {
                    $uchr = $j;
                    $j = \strlen($uchr);
                    $ulen = $uchr[0] < "\x80" ? 1 : $ulenMask[$uchr[0] & "\xf0"];
                    if ($ulen != $j) {
                        // Put trailing chars in $s
                        $j -= $ulen;
                        $i -= $j;
                        if (0 > $i) {
                            $s = str_repeat(' ', -$i) . $s;
                            $len -= $i;
                            $i = 0;
                        }
                        while ($j--) {
                            $s[$i + $j] = $uchr[$ulen + $j];
                        }
                        $uchr = substr($uchr, 0, $ulen);
                    }
                }
                if (isset($combClass[$uchr])) {
                    // Combining chars, for sorting
                    if (!isset($c[$combClass[$uchr]])) {
                        $c[$combClass[$uchr]] = '';
                    }
                    $c[$combClass[$uchr]] .= $uchr;
                    continue;
                }
            } else {
                // Hangul chars
                $uchr = unpack('C*', $uchr);
                $j = ($uchr[1] - 224 << 12) + ($uchr[2] - 128 << 6) + $uchr[3] - 0xac80;
                $uchr = "\xe1\x84" . \chr(0x80 + (int) ($j / 588)) . "\xe1\x85" . \chr(0xa1 + (int) ($j % 588 / 28));
                if ($j %= 28) {
                    $uchr .= $j < 25 ? "\xe1\x86" . \chr(0xa7 + $j) : "\xe1\x87" . \chr(0x67 + $j);
                }
            }
            if ($c) {
                ksort($c);
                $result .= implode('', $c);
                $c = [];
            }
            $result .= $uchr;
        }
        if ($c) {
            ksort($c);
            $result .= implode('', $c);
        }
        return $result;
    }
    private static function getData($file)
    {
        if (file_exists($file = __DIR__ . '/Resources/unidata/' . $file . '.php')) {
            return require $file;
        }
        return \false;
    }
}
<?php

class Normalizer extends Symfony\Polyfill\Intl\Normalizer\Normalizer
{
    /**
     * @deprecated since ICU 56 and removed in PHP 8
     */
    public const NONE = 2;
    public const FORM_D = 4;
    public const FORM_KD = 8;
    public const FORM_C = 16;
    public const FORM_KC = 32;
    public const NFD = 4;
    public const NFKD = 8;
    public const NFC = 16;
    public const NFKC = 32;
}
<?php

namespace _ContaoManager;

return array('̀' => 230, '́' => 230, '̂' => 230, '̃' => 230, '̄' => 230, '̅' => 230, '̆' => 230, '̇' => 230, '̈' => 230, '̉' => 230, '̊' => 230, '̋' => 230, '̌' => 230, '̍' => 230, '̎' => 230, '̏' => 230, '̐' => 230, '̑' => 230, '̒' => 230, '̓' => 230, '̔' => 230, '̕' => 232, '̖' => 220, '̗' => 220, '̘' => 220, '̙' => 220, '̚' => 232, '̛' => 216, '̜' => 220, '̝' => 220, '̞' => 220, '̟' => 220, '̠' => 220, '̡' => 202, '̢' => 202, '̣' => 220, '̤' => 220, '̥' => 220, '̦' => 220, '̧' => 202, '̨' => 202, '̩' => 220, '̪' => 220, '̫' => 220, '̬' => 220, '̭' => 220, '̮' => 220, '̯' => 220, '̰' => 220, '̱' => 220, '̲' => 220, '̳' => 220, '̴' => 1, '̵' => 1, '̶' => 1, '̷' => 1, '̸' => 1, '̹' => 220, '̺' => 220, '̻' => 220, '̼' => 220, '̽' => 230, '̾' => 230, '̿' => 230, '̀' => 230, '́' => 230, '͂' => 230, '̓' => 230, '̈́' => 230, 'ͅ' => 240, '͆' => 230, '͇' => 220, '͈' => 220, '͉' => 220, '͊' => 230, '͋' => 230, '͌' => 230, '͍' => 220, '͎' => 220, '͐' => 230, '͑' => 230, '͒' => 230, '͓' => 220, '͔' => 220, '͕' => 220, '͖' => 220, '͗' => 230, '͘' => 232, '͙' => 220, '͚' => 220, '͛' => 230, '͜' => 233, '͝' => 234, '͞' => 234, '͟' => 233, '͠' => 234, '͡' => 234, '͢' => 233, 'ͣ' => 230, 'ͤ' => 230, 'ͥ' => 230, 'ͦ' => 230, 'ͧ' => 230, 'ͨ' => 230, 'ͩ' => 230, 'ͪ' => 230, 'ͫ' => 230, 'ͬ' => 230, 'ͭ' => 230, 'ͮ' => 230, 'ͯ' => 230, '҃' => 230, '҄' => 230, '҅' => 230, '҆' => 230, '҇' => 230, '֑' => 220, '֒' => 230, '֓' => 230, '֔' => 230, '֕' => 230, '֖' => 220, '֗' => 230, '֘' => 230, '֙' => 230, '֚' => 222, '֛' => 220, '֜' => 230, '֝' => 230, '֞' => 230, '֟' => 230, '֠' => 230, '֡' => 230, '֢' => 220, '֣' => 220, '֤' => 220, '֥' => 220, '֦' => 220, '֧' => 220, '֨' => 230, '֩' => 230, '֪' => 220, '֫' => 230, '֬' => 230, '֭' => 222, '֮' => 228, '֯' => 230, 'ְ' => 10, 'ֱ' => 11, 'ֲ' => 12, 'ֳ' => 13, 'ִ' => 14, 'ֵ' => 15, 'ֶ' => 16, 'ַ' => 17, 'ָ' => 18, 'ֹ' => 19, 'ֺ' => 19, 'ֻ' => 20, 'ּ' => 21, 'ֽ' => 22, 'ֿ' => 23, 'ׁ' => 24, 'ׂ' => 25, 'ׄ' => 230, 'ׅ' => 220, 'ׇ' => 18, 'ؐ' => 230, 'ؑ' => 230, 'ؒ' => 230, 'ؓ' => 230, 'ؔ' => 230, 'ؕ' => 230, 'ؖ' => 230, 'ؗ' => 230, 'ؘ' => 30, 'ؙ' => 31, 'ؚ' => 32, 'ً' => 27, 'ٌ' => 28, 'ٍ' => 29, 'َ' => 30, 'ُ' => 31, 'ِ' => 32, 'ّ' => 33, 'ْ' => 34, 'ٓ' => 230, 'ٔ' => 230, 'ٕ' => 220, 'ٖ' => 220, 'ٗ' => 230, '٘' => 230, 'ٙ' => 230, 'ٚ' => 230, 'ٛ' => 230, 'ٜ' => 220, 'ٝ' => 230, 'ٞ' => 230, 'ٟ' => 220, 'ٰ' => 35, 'ۖ' => 230, 'ۗ' => 230, 'ۘ' => 230, 'ۙ' => 230, 'ۚ' => 230, 'ۛ' => 230, 'ۜ' => 230, '۟' => 230, '۠' => 230, 'ۡ' => 230, 'ۢ' => 230, 'ۣ' => 220, 'ۤ' => 230, 'ۧ' => 230, 'ۨ' => 230, '۪' => 220, '۫' => 230, '۬' => 230, 'ۭ' => 220, 'ܑ' => 36, 'ܰ' => 230, 'ܱ' => 220, 'ܲ' => 230, 'ܳ' => 230, 'ܴ' => 220, 'ܵ' => 230, 'ܶ' => 230, 'ܷ' => 220, 'ܸ' => 220, 'ܹ' => 220, 'ܺ' => 230, 'ܻ' => 220, 'ܼ' => 220, 'ܽ' => 230, 'ܾ' => 220, 'ܿ' => 230, '݀' => 230, '݁' => 230, '݂' => 220, '݃' => 230, '݄' => 220, '݅' => 230, '݆' => 220, '݇' => 230, '݈' => 220, '݉' => 230, '݊' => 230, '߫' => 230, '߬' => 230, '߭' => 230, '߮' => 230, '߯' => 230, '߰' => 230, '߱' => 230, '߲' => 220, '߳' => 230, '߽' => 220, 'ࠖ' => 230, 'ࠗ' => 230, '࠘' => 230, '࠙' => 230, 'ࠛ' => 230, 'ࠜ' => 230, 'ࠝ' => 230, 'ࠞ' => 230, 'ࠟ' => 230, 'ࠠ' => 230, 'ࠡ' => 230, 'ࠢ' => 230, 'ࠣ' => 230, 'ࠥ' => 230, 'ࠦ' => 230, 'ࠧ' => 230, 'ࠩ' => 230, 'ࠪ' => 230, 'ࠫ' => 230, 'ࠬ' => 230, '࠭' => 230, '࡙' => 220, '࡚' => 220, '࡛' => 220, '࣓' => 220, 'ࣔ' => 230, 'ࣕ' => 230, 'ࣖ' => 230, 'ࣗ' => 230, 'ࣘ' => 230, 'ࣙ' => 230, 'ࣚ' => 230, 'ࣛ' => 230, 'ࣜ' => 230, 'ࣝ' => 230, 'ࣞ' => 230, 'ࣟ' => 230, '࣠' => 230, '࣡' => 230, 'ࣣ' => 220, 'ࣤ' => 230, 'ࣥ' => 230, 'ࣦ' => 220, 'ࣧ' => 230, 'ࣨ' => 230, 'ࣩ' => 220, '࣪' => 230, '࣫' => 230, '࣬' => 230, '࣭' => 220, '࣮' => 220, '࣯' => 220, 'ࣰ' => 27, 'ࣱ' => 28, 'ࣲ' => 29, 'ࣳ' => 230, 'ࣴ' => 230, 'ࣵ' => 230, 'ࣶ' => 220, 'ࣷ' => 230, 'ࣸ' => 230, 'ࣹ' => 220, 'ࣺ' => 220, 'ࣻ' => 230, 'ࣼ' => 230, 'ࣽ' => 230, 'ࣾ' => 230, 'ࣿ' => 230, '़' => 7, '्' => 9, '॑' => 230, '॒' => 220, '॓' => 230, '॔' => 230, '়' => 7, '্' => 9, '৾' => 230, '਼' => 7, '੍' => 9, '઼' => 7, '્' => 9, '଼' => 7, '୍' => 9, '்' => 9, '్' => 9, 'ౕ' => 84, 'ౖ' => 91, '಼' => 7, '್' => 9, '഻' => 9, '഼' => 9, '്' => 9, '්' => 9, 'ุ' => 103, 'ู' => 103, 'ฺ' => 9, '่' => 107, '้' => 107, '๊' => 107, '๋' => 107, 'ຸ' => 118, 'ູ' => 118, '຺' => 9, '່' => 122, '້' => 122, '໊' => 122, '໋' => 122, '༘' => 220, '༙' => 220, '༵' => 220, '༷' => 220, '༹' => 216, 'ཱ' => 129, 'ི' => 130, 'ུ' => 132, 'ེ' => 130, 'ཻ' => 130, 'ོ' => 130, 'ཽ' => 130, 'ྀ' => 130, 'ྂ' => 230, 'ྃ' => 230, '྄' => 9, '྆' => 230, '྇' => 230, '࿆' => 220, '့' => 7, '္' => 9, '်' => 9, 'ႍ' => 220, '፝' => 230, '፞' => 230, '፟' => 230, '᜔' => 9, '᜴' => 9, '្' => 9, '៝' => 230, 'ᢩ' => 228, '᤹' => 222, '᤺' => 230, '᤻' => 220, 'ᨗ' => 230, 'ᨘ' => 220, '᩠' => 9, '᩵' => 230, '᩶' => 230, '᩷' => 230, '᩸' => 230, '᩹' => 230, '᩺' => 230, '᩻' => 230, '᩼' => 230, '᩿' => 220, '᪰' => 230, '᪱' => 230, '᪲' => 230, '᪳' => 230, '᪴' => 230, '᪵' => 220, '᪶' => 220, '᪷' => 220, '᪸' => 220, '᪹' => 220, '᪺' => 220, '᪻' => 230, '᪼' => 230, '᪽' => 220, 'ᪿ' => 220, 'ᫀ' => 220, '᬴' => 7, '᭄' => 9, '᭫' => 230, '᭬' => 220, '᭭' => 230, '᭮' => 230, '᭯' => 230, '᭰' => 230, '᭱' => 230, '᭲' => 230, '᭳' => 230, '᮪' => 9, '᮫' => 9, '᯦' => 7, '᯲' => 9, '᯳' => 9, '᰷' => 7, '᳐' => 230, '᳑' => 230, '᳒' => 230, '᳔' => 1, '᳕' => 220, '᳖' => 220, '᳗' => 220, '᳘' => 220, '᳙' => 220, '᳚' => 230, '᳛' => 230, '᳜' => 220, '᳝' => 220, '᳞' => 220, '᳟' => 220, '᳠' => 230, '᳢' => 1, '᳣' => 1, '᳤' => 1, '᳥' => 1, '᳦' => 1, '᳧' => 1, '᳨' => 1, '᳭' => 220, '᳴' => 230, '᳸' => 230, '᳹' => 230, '᷀' => 230, '᷁' => 230, '᷂' => 220, '᷃' => 230, '᷄' => 230, '᷅' => 230, '᷆' => 230, '᷇' => 230, '᷈' => 230, '᷉' => 230, '᷊' => 220, '᷋' => 230, '᷌' => 230, '᷍' => 234, '᷎' => 214, '᷏' => 220, '᷐' => 202, '᷑' => 230, '᷒' => 230, 'ᷓ' => 230, 'ᷔ' => 230, 'ᷕ' => 230, 'ᷖ' => 230, 'ᷗ' => 230, 'ᷘ' => 230, 'ᷙ' => 230, 'ᷚ' => 230, 'ᷛ' => 230, 'ᷜ' => 230, 'ᷝ' => 230, 'ᷞ' => 230, 'ᷟ' => 230, 'ᷠ' => 230, 'ᷡ' => 230, 'ᷢ' => 230, 'ᷣ' => 230, 'ᷤ' => 230, 'ᷥ' => 230, 'ᷦ' => 230, 'ᷧ' => 230, 'ᷨ' => 230, 'ᷩ' => 230, 'ᷪ' => 230, 'ᷫ' => 230, 'ᷬ' => 230, 'ᷭ' => 230, 'ᷮ' => 230, 'ᷯ' => 230, 'ᷰ' => 230, 'ᷱ' => 230, 'ᷲ' => 230, 'ᷳ' => 230, 'ᷴ' => 230, '᷵' => 230, '᷶' => 232, '᷷' => 228, '᷸' => 228, '᷹' => 220, '᷻' => 230, '᷼' => 233, '᷽' => 220, '᷾' => 230, '᷿' => 220, '⃐' => 230, '⃑' => 230, '⃒' => 1, '⃓' => 1, '⃔' => 230, '⃕' => 230, '⃖' => 230, '⃗' => 230, '⃘' => 1, '⃙' => 1, '⃚' => 1, '⃛' => 230, '⃜' => 230, '⃡' => 230, '⃥' => 1, '⃦' => 1, '⃧' => 230, '⃨' => 220, '⃩' => 230, '⃪' => 1, '⃫' => 1, '⃬' => 220, '⃭' => 220, '⃮' => 220, '⃯' => 220, '⃰' => 230, '⳯' => 230, '⳰' => 230, '⳱' => 230, '⵿' => 9, 'ⷠ' => 230, 'ⷡ' => 230, 'ⷢ' => 230, 'ⷣ' => 230, 'ⷤ' => 230, 'ⷥ' => 230, 'ⷦ' => 230, 'ⷧ' => 230, 'ⷨ' => 230, 'ⷩ' => 230, 'ⷪ' => 230, 'ⷫ' => 230, 'ⷬ' => 230, 'ⷭ' => 230, 'ⷮ' => 230, 'ⷯ' => 230, 'ⷰ' => 230, 'ⷱ' => 230, 'ⷲ' => 230, 'ⷳ' => 230, 'ⷴ' => 230, 'ⷵ' => 230, 'ⷶ' => 230, 'ⷷ' => 230, 'ⷸ' => 230, 'ⷹ' => 230, 'ⷺ' => 230, 'ⷻ' => 230, 'ⷼ' => 230, 'ⷽ' => 230, 'ⷾ' => 230, 'ⷿ' => 230, '〪' => 218, '〫' => 228, '〬' => 232, '〭' => 222, '〮' => 224, '〯' => 224, '゙' => 8, '゚' => 8, '꙯' => 230, 'ꙴ' => 230, 'ꙵ' => 230, 'ꙶ' => 230, 'ꙷ' => 230, 'ꙸ' => 230, 'ꙹ' => 230, 'ꙺ' => 230, 'ꙻ' => 230, '꙼' => 230, '꙽' => 230, 'ꚞ' => 230, 'ꚟ' => 230, '꛰' => 230, '꛱' => 230, '꠆' => 9, '꠬' => 9, '꣄' => 9, '꣠' => 230, '꣡' => 230, '꣢' => 230, '꣣' => 230, '꣤' => 230, '꣥' => 230, '꣦' => 230, '꣧' => 230, '꣨' => 230, '꣩' => 230, '꣪' => 230, '꣫' => 230, '꣬' => 230, '꣭' => 230, '꣮' => 230, '꣯' => 230, '꣰' => 230, '꣱' => 230, '꤫' => 220, '꤬' => 220, '꤭' => 220, '꥓' => 9, '꦳' => 7, '꧀' => 9, 'ꪰ' => 230, 'ꪲ' => 230, 'ꪳ' => 230, 'ꪴ' => 220, 'ꪷ' => 230, 'ꪸ' => 230, 'ꪾ' => 230, '꪿' => 230, '꫁' => 230, '꫶' => 9, '꯭' => 9, 'ﬞ' => 26, '︠' => 230, '︡' => 230, '︢' => 230, '︣' => 230, '︤' => 230, '︥' => 230, '︦' => 230, '︧' => 220, '︨' => 220, '︩' => 220, '︪' => 220, '︫' => 220, '︬' => 220, '︭' => 220, '︮' => 230, '︯' => 230, '𐇽' => 220, '𐋠' => 220, '𐍶' => 230, '𐍷' => 230, '𐍸' => 230, '𐍹' => 230, '𐍺' => 230, '𐨍' => 220, '𐨏' => 230, '𐨸' => 230, '𐨹' => 1, '𐨺' => 220, '𐨿' => 9, '𐫥' => 230, '𐫦' => 220, '𐴤' => 230, '𐴥' => 230, '𐴦' => 230, '𐴧' => 230, '𐺫' => 230, '𐺬' => 230, '𐽆' => 220, '𐽇' => 220, '𐽈' => 230, '𐽉' => 230, '𐽊' => 230, '𐽋' => 220, '𐽌' => 230, '𐽍' => 220, '𐽎' => 220, '𐽏' => 220, '𐽐' => 220, '𑁆' => 9, '𑁿' => 9, '𑂹' => 9, '𑂺' => 7, '𑄀' => 230, '𑄁' => 230, '𑄂' => 230, '𑄳' => 9, '𑄴' => 9, '𑅳' => 7, '𑇀' => 9, '𑇊' => 7, '𑈵' => 9, '𑈶' => 7, '𑋩' => 7, '𑋪' => 9, '𑌻' => 7, '𑌼' => 7, '𑍍' => 9, '𑍦' => 230, '𑍧' => 230, '𑍨' => 230, '𑍩' => 230, '𑍪' => 230, '𑍫' => 230, '𑍬' => 230, '𑍰' => 230, '𑍱' => 230, '𑍲' => 230, '𑍳' => 230, '𑍴' => 230, '𑑂' => 9, '𑑆' => 7, '𑑞' => 230, '𑓂' => 9, '𑓃' => 7, '𑖿' => 9, '𑗀' => 7, '𑘿' => 9, '𑚶' => 9, '𑚷' => 7, '𑜫' => 9, '𑠹' => 9, '𑠺' => 7, '𑤽' => 9, '𑤾' => 9, '𑥃' => 7, '𑧠' => 9, '𑨴' => 9, '𑩇' => 9, '𑪙' => 9, '𑰿' => 9, '𑵂' => 7, '𑵄' => 9, '𑵅' => 9, '𑶗' => 9, '𖫰' => 1, '𖫱' => 1, '𖫲' => 1, '𖫳' => 1, '𖫴' => 1, '𖬰' => 230, '𖬱' => 230, '𖬲' => 230, '𖬳' => 230, '𖬴' => 230, '𖬵' => 230, '𖬶' => 230, '𖿰' => 6, '𖿱' => 6, '𛲞' => 1, '𝅥' => 216, '𝅦' => 216, '𝅧' => 1, '𝅨' => 1, '𝅩' => 1, '𝅭' => 226, '𝅮' => 216, '𝅯' => 216, '𝅰' => 216, '𝅱' => 216, '𝅲' => 216, '𝅻' => 220, '𝅼' => 220, '𝅽' => 220, '𝅾' => 220, '𝅿' => 220, '𝆀' => 220, '𝆁' => 220, '𝆂' => 220, '𝆅' => 230, '𝆆' => 230, '𝆇' => 230, '𝆈' => 230, '𝆉' => 230, '𝆊' => 220, '𝆋' => 220, '𝆪' => 230, '𝆫' => 230, '𝆬' => 230, '𝆭' => 230, '𝉂' => 230, '𝉃' => 230, '𝉄' => 230, '𞀀' => 230, '𞀁' => 230, '𞀂' => 230, '𞀃' => 230, '𞀄' => 230, '𞀅' => 230, '𞀆' => 230, '𞀈' => 230, '𞀉' => 230, '𞀊' => 230, '𞀋' => 230, '𞀌' => 230, '𞀍' => 230, '𞀎' => 230, '𞀏' => 230, '𞀐' => 230, '𞀑' => 230, '𞀒' => 230, '𞀓' => 230, '𞀔' => 230, '𞀕' => 230, '𞀖' => 230, '𞀗' => 230, '𞀘' => 230, '𞀛' => 230, '𞀜' => 230, '𞀝' => 230, '𞀞' => 230, '𞀟' => 230, '𞀠' => 230, '𞀡' => 230, '𞀣' => 230, '𞀤' => 230, '𞀦' => 230, '𞀧' => 230, '𞀨' => 230, '𞀩' => 230, '𞀪' => 230, '𞄰' => 230, '𞄱' => 230, '𞄲' => 230, '𞄳' => 230, '𞄴' => 230, '𞄵' => 230, '𞄶' => 230, '𞋬' => 230, '𞋭' => 230, '𞋮' => 230, '𞋯' => 230, '𞣐' => 220, '𞣑' => 220, '𞣒' => 220, '𞣓' => 220, '𞣔' => 220, '𞣕' => 220, '𞣖' => 220, '𞥄' => 230, '𞥅' => 230, '𞥆' => 230, '𞥇' => 230, '𞥈' => 230, '𞥉' => 230, '𞥊' => 7);
<?php

namespace _ContaoManager;

return array('À' => 'À', 'Á' => 'Á', 'Â' => 'Â', 'Ã' => 'Ã', 'Ä' => 'Ä', 'Å' => 'Å', 'Ç' => 'Ç', 'È' => 'È', 'É' => 'É', 'Ê' => 'Ê', 'Ë' => 'Ë', 'Ì' => 'Ì', 'Í' => 'Í', 'Î' => 'Î', 'Ï' => 'Ï', 'Ñ' => 'Ñ', 'Ò' => 'Ò', 'Ó' => 'Ó', 'Ô' => 'Ô', 'Õ' => 'Õ', 'Ö' => 'Ö', 'Ù' => 'Ù', 'Ú' => 'Ú', 'Û' => 'Û', 'Ü' => 'Ü', 'Ý' => 'Ý', 'à' => 'à', 'á' => 'á', 'â' => 'â', 'ã' => 'ã', 'ä' => 'ä', 'å' => 'å', 'ç' => 'ç', 'è' => 'è', 'é' => 'é', 'ê' => 'ê', 'ë' => 'ë', 'ì' => 'ì', 'í' => 'í', 'î' => 'î', 'ï' => 'ï', 'ñ' => 'ñ', 'ò' => 'ò', 'ó' => 'ó', 'ô' => 'ô', 'õ' => 'õ', 'ö' => 'ö', 'ù' => 'ù', 'ú' => 'ú', 'û' => 'û', 'ü' => 'ü', 'ý' => 'ý', 'ÿ' => 'ÿ', 'Ā' => 'Ā', 'ā' => 'ā', 'Ă' => 'Ă', 'ă' => 'ă', 'Ą' => 'Ą', 'ą' => 'ą', 'Ć' => 'Ć', 'ć' => 'ć', 'Ĉ' => 'Ĉ', 'ĉ' => 'ĉ', 'Ċ' => 'Ċ', 'ċ' => 'ċ', 'Č' => 'Č', 'č' => 'č', 'Ď' => 'Ď', 'ď' => 'ď', 'Ē' => 'Ē', 'ē' => 'ē', 'Ĕ' => 'Ĕ', 'ĕ' => 'ĕ', 'Ė' => 'Ė', 'ė' => 'ė', 'Ę' => 'Ę', 'ę' => 'ę', 'Ě' => 'Ě', 'ě' => 'ě', 'Ĝ' => 'Ĝ', 'ĝ' => 'ĝ', 'Ğ' => 'Ğ', 'ğ' => 'ğ', 'Ġ' => 'Ġ', 'ġ' => 'ġ', 'Ģ' => 'Ģ', 'ģ' => 'ģ', 'Ĥ' => 'Ĥ', 'ĥ' => 'ĥ', 'Ĩ' => 'Ĩ', 'ĩ' => 'ĩ', 'Ī' => 'Ī', 'ī' => 'ī', 'Ĭ' => 'Ĭ', 'ĭ' => 'ĭ', 'Į' => 'Į', 'į' => 'į', 'İ' => 'İ', 'Ĵ' => 'Ĵ', 'ĵ' => 'ĵ', 'Ķ' => 'Ķ', 'ķ' => 'ķ', 'Ĺ' => 'Ĺ', 'ĺ' => 'ĺ', 'Ļ' => 'Ļ', 'ļ' => 'ļ', 'Ľ' => 'Ľ', 'ľ' => 'ľ', 'Ń' => 'Ń', 'ń' => 'ń', 'Ņ' => 'Ņ', 'ņ' => 'ņ', 'Ň' => 'Ň', 'ň' => 'ň', 'Ō' => 'Ō', 'ō' => 'ō', 'Ŏ' => 'Ŏ', 'ŏ' => 'ŏ', 'Ő' => 'Ő', 'ő' => 'ő', 'Ŕ' => 'Ŕ', 'ŕ' => 'ŕ', 'Ŗ' => 'Ŗ', 'ŗ' => 'ŗ', 'Ř' => 'Ř', 'ř' => 'ř', 'Ś' => 'Ś', 'ś' => 'ś', 'Ŝ' => 'Ŝ', 'ŝ' => 'ŝ', 'Ş' => 'Ş', 'ş' => 'ş', 'Š' => 'Š', 'š' => 'š', 'Ţ' => 'Ţ', 'ţ' => 'ţ', 'Ť' => 'Ť', 'ť' => 'ť', 'Ũ' => 'Ũ', 'ũ' => 'ũ', 'Ū' => 'Ū', 'ū' => 'ū', 'Ŭ' => 'Ŭ', 'ŭ' => 'ŭ', 'Ů' => 'Ů', 'ů' => 'ů', 'Ű' => 'Ű', 'ű' => 'ű', 'Ų' => 'Ų', 'ų' => 'ų', 'Ŵ' => 'Ŵ', 'ŵ' => 'ŵ', 'Ŷ' => 'Ŷ', 'ŷ' => 'ŷ', 'Ÿ' => 'Ÿ', 'Ź' => 'Ź', 'ź' => 'ź', 'Ż' => 'Ż', 'ż' => 'ż', 'Ž' => 'Ž', 'ž' => 'ž', 'Ơ' => 'Ơ', 'ơ' => 'ơ', 'Ư' => 'Ư', 'ư' => 'ư', 'Ǎ' => 'Ǎ', 'ǎ' => 'ǎ', 'Ǐ' => 'Ǐ', 'ǐ' => 'ǐ', 'Ǒ' => 'Ǒ', 'ǒ' => 'ǒ', 'Ǔ' => 'Ǔ', 'ǔ' => 'ǔ', 'Ǖ' => 'Ǖ', 'ǖ' => 'ǖ', 'Ǘ' => 'Ǘ', 'ǘ' => 'ǘ', 'Ǚ' => 'Ǚ', 'ǚ' => 'ǚ', 'Ǜ' => 'Ǜ', 'ǜ' => 'ǜ', 'Ǟ' => 'Ǟ', 'ǟ' => 'ǟ', 'Ǡ' => 'Ǡ', 'ǡ' => 'ǡ', 'Ǣ' => 'Ǣ', 'ǣ' => 'ǣ', 'Ǧ' => 'Ǧ', 'ǧ' => 'ǧ', 'Ǩ' => 'Ǩ', 'ǩ' => 'ǩ', 'Ǫ' => 'Ǫ', 'ǫ' => 'ǫ', 'Ǭ' => 'Ǭ', 'ǭ' => 'ǭ', 'Ǯ' => 'Ǯ', 'ǯ' => 'ǯ', 'ǰ' => 'ǰ', 'Ǵ' => 'Ǵ', 'ǵ' => 'ǵ', 'Ǹ' => 'Ǹ', 'ǹ' => 'ǹ', 'Ǻ' => 'Ǻ', 'ǻ' => 'ǻ', 'Ǽ' => 'Ǽ', 'ǽ' => 'ǽ', 'Ǿ' => 'Ǿ', 'ǿ' => 'ǿ', 'Ȁ' => 'Ȁ', 'ȁ' => 'ȁ', 'Ȃ' => 'Ȃ', 'ȃ' => 'ȃ', 'Ȅ' => 'Ȅ', 'ȅ' => 'ȅ', 'Ȇ' => 'Ȇ', 'ȇ' => 'ȇ', 'Ȉ' => 'Ȉ', 'ȉ' => 'ȉ', 'Ȋ' => 'Ȋ', 'ȋ' => 'ȋ', 'Ȍ' => 'Ȍ', 'ȍ' => 'ȍ', 'Ȏ' => 'Ȏ', 'ȏ' => 'ȏ', 'Ȑ' => 'Ȑ', 'ȑ' => 'ȑ', 'Ȓ' => 'Ȓ', 'ȓ' => 'ȓ', 'Ȕ' => 'Ȕ', 'ȕ' => 'ȕ', 'Ȗ' => 'Ȗ', 'ȗ' => 'ȗ', 'Ș' => 'Ș', 'ș' => 'ș', 'Ț' => 'Ț', 'ț' => 'ț', 'Ȟ' => 'Ȟ', 'ȟ' => 'ȟ', 'Ȧ' => 'Ȧ', 'ȧ' => 'ȧ', 'Ȩ' => 'Ȩ', 'ȩ' => 'ȩ', 'Ȫ' => 'Ȫ', 'ȫ' => 'ȫ', 'Ȭ' => 'Ȭ', 'ȭ' => 'ȭ', 'Ȯ' => 'Ȯ', 'ȯ' => 'ȯ', 'Ȱ' => 'Ȱ', 'ȱ' => 'ȱ', 'Ȳ' => 'Ȳ', 'ȳ' => 'ȳ', '̀' => '̀', '́' => '́', '̓' => '̓', '̈́' => '̈́', 'ʹ' => 'ʹ', ';' => ';', '΅' => '΅', 'Ά' => 'Ά', '·' => '·', 'Έ' => 'Έ', 'Ή' => 'Ή', 'Ί' => 'Ί', 'Ό' => 'Ό', 'Ύ' => 'Ύ', 'Ώ' => 'Ώ', 'ΐ' => 'ΐ', 'Ϊ' => 'Ϊ', 'Ϋ' => 'Ϋ', 'ά' => 'ά', 'έ' => 'έ', 'ή' => 'ή', 'ί' => 'ί', 'ΰ' => 'ΰ', 'ϊ' => 'ϊ', 'ϋ' => 'ϋ', 'ό' => 'ό', 'ύ' => 'ύ', 'ώ' => 'ώ', 'ϓ' => 'ϓ', 'ϔ' => 'ϔ', 'Ѐ' => 'Ѐ', 'Ё' => 'Ё', 'Ѓ' => 'Ѓ', 'Ї' => 'Ї', 'Ќ' => 'Ќ', 'Ѝ' => 'Ѝ', 'Ў' => 'Ў', 'Й' => 'Й', 'й' => 'й', 'ѐ' => 'ѐ', 'ё' => 'ё', 'ѓ' => 'ѓ', 'ї' => 'ї', 'ќ' => 'ќ', 'ѝ' => 'ѝ', 'ў' => 'ў', 'Ѷ' => 'Ѷ', 'ѷ' => 'ѷ', 'Ӂ' => 'Ӂ', 'ӂ' => 'ӂ', 'Ӑ' => 'Ӑ', 'ӑ' => 'ӑ', 'Ӓ' => 'Ӓ', 'ӓ' => 'ӓ', 'Ӗ' => 'Ӗ', 'ӗ' => 'ӗ', 'Ӛ' => 'Ӛ', 'ӛ' => 'ӛ', 'Ӝ' => 'Ӝ', 'ӝ' => 'ӝ', 'Ӟ' => 'Ӟ', 'ӟ' => 'ӟ', 'Ӣ' => 'Ӣ', 'ӣ' => 'ӣ', 'Ӥ' => 'Ӥ', 'ӥ' => 'ӥ', 'Ӧ' => 'Ӧ', 'ӧ' => 'ӧ', 'Ӫ' => 'Ӫ', 'ӫ' => 'ӫ', 'Ӭ' => 'Ӭ', 'ӭ' => 'ӭ', 'Ӯ' => 'Ӯ', 'ӯ' => 'ӯ', 'Ӱ' => 'Ӱ', 'ӱ' => 'ӱ', 'Ӳ' => 'Ӳ', 'ӳ' => 'ӳ', 'Ӵ' => 'Ӵ', 'ӵ' => 'ӵ', 'Ӹ' => 'Ӹ', 'ӹ' => 'ӹ', 'آ' => 'آ', 'أ' => 'أ', 'ؤ' => 'ؤ', 'إ' => 'إ', 'ئ' => 'ئ', 'ۀ' => 'ۀ', 'ۂ' => 'ۂ', 'ۓ' => 'ۓ', 'ऩ' => 'ऩ', 'ऱ' => 'ऱ', 'ऴ' => 'ऴ', 'क़' => 'क़', 'ख़' => 'ख़', 'ग़' => 'ग़', 'ज़' => 'ज़', 'ड़' => 'ड़', 'ढ़' => 'ढ़', 'फ़' => 'फ़', 'य़' => 'य़', 'ো' => 'ো', 'ৌ' => 'ৌ', 'ড়' => 'ড়', 'ঢ়' => 'ঢ়', 'য়' => 'য়', 'ਲ਼' => 'ਲ਼', 'ਸ਼' => 'ਸ਼', 'ਖ਼' => 'ਖ਼', 'ਗ਼' => 'ਗ਼', 'ਜ਼' => 'ਜ਼', 'ਫ਼' => 'ਫ਼', 'ୈ' => 'ୈ', 'ୋ' => 'ୋ', 'ୌ' => 'ୌ', 'ଡ଼' => 'ଡ଼', 'ଢ଼' => 'ଢ଼', 'ஔ' => 'ஔ', 'ொ' => 'ொ', 'ோ' => 'ோ', 'ௌ' => 'ௌ', 'ై' => 'ై', 'ೀ' => 'ೀ', 'ೇ' => 'ೇ', 'ೈ' => 'ೈ', 'ೊ' => 'ೊ', 'ೋ' => 'ೋ', 'ൊ' => 'ൊ', 'ോ' => 'ോ', 'ൌ' => 'ൌ', 'ේ' => 'ේ', 'ො' => 'ො', 'ෝ' => 'ෝ', 'ෞ' => 'ෞ', 'གྷ' => 'གྷ', 'ཌྷ' => 'ཌྷ', 'དྷ' => 'དྷ', 'བྷ' => 'བྷ', 'ཛྷ' => 'ཛྷ', 'ཀྵ' => 'ཀྵ', 'ཱི' => 'ཱི', 'ཱུ' => 'ཱུ', 'ྲྀ' => 'ྲྀ', 'ླྀ' => 'ླྀ', 'ཱྀ' => 'ཱྀ', 'ྒྷ' => 'ྒྷ', 'ྜྷ' => 'ྜྷ', 'ྡྷ' => 'ྡྷ', 'ྦྷ' => 'ྦྷ', 'ྫྷ' => 'ྫྷ', 'ྐྵ' => 'ྐྵ', 'ဦ' => 'ဦ', 'ᬆ' => 'ᬆ', 'ᬈ' => 'ᬈ', 'ᬊ' => 'ᬊ', 'ᬌ' => 'ᬌ', 'ᬎ' => 'ᬎ', 'ᬒ' => 'ᬒ', 'ᬻ' => 'ᬻ', 'ᬽ' => 'ᬽ', 'ᭀ' => 'ᭀ', 'ᭁ' => 'ᭁ', 'ᭃ' => 'ᭃ', 'Ḁ' => 'Ḁ', 'ḁ' => 'ḁ', 'Ḃ' => 'Ḃ', 'ḃ' => 'ḃ', 'Ḅ' => 'Ḅ', 'ḅ' => 'ḅ', 'Ḇ' => 'Ḇ', 'ḇ' => 'ḇ', 'Ḉ' => 'Ḉ', 'ḉ' => 'ḉ', 'Ḋ' => 'Ḋ', 'ḋ' => 'ḋ', 'Ḍ' => 'Ḍ', 'ḍ' => 'ḍ', 'Ḏ' => 'Ḏ', 'ḏ' => 'ḏ', 'Ḑ' => 'Ḑ', 'ḑ' => 'ḑ', 'Ḓ' => 'Ḓ', 'ḓ' => 'ḓ', 'Ḕ' => 'Ḕ', 'ḕ' => 'ḕ', 'Ḗ' => 'Ḗ', 'ḗ' => 'ḗ', 'Ḙ' => 'Ḙ', 'ḙ' => 'ḙ', 'Ḛ' => 'Ḛ', 'ḛ' => 'ḛ', 'Ḝ' => 'Ḝ', 'ḝ' => 'ḝ', 'Ḟ' => 'Ḟ', 'ḟ' => 'ḟ', 'Ḡ' => 'Ḡ', 'ḡ' => 'ḡ', 'Ḣ' => 'Ḣ', 'ḣ' => 'ḣ', 'Ḥ' => 'Ḥ', 'ḥ' => 'ḥ', 'Ḧ' => 'Ḧ', 'ḧ' => 'ḧ', 'Ḩ' => 'Ḩ', 'ḩ' => 'ḩ', 'Ḫ' => 'Ḫ', 'ḫ' => 'ḫ', 'Ḭ' => 'Ḭ', 'ḭ' => 'ḭ', 'Ḯ' => 'Ḯ', 'ḯ' => 'ḯ', 'Ḱ' => 'Ḱ', 'ḱ' => 'ḱ', 'Ḳ' => 'Ḳ', 'ḳ' => 'ḳ', 'Ḵ' => 'Ḵ', 'ḵ' => 'ḵ', 'Ḷ' => 'Ḷ', 'ḷ' => 'ḷ', 'Ḹ' => 'Ḹ', 'ḹ' => 'ḹ', 'Ḻ' => 'Ḻ', 'ḻ' => 'ḻ', 'Ḽ' => 'Ḽ', 'ḽ' => 'ḽ', 'Ḿ' => 'Ḿ', 'ḿ' => 'ḿ', 'Ṁ' => 'Ṁ', 'ṁ' => 'ṁ', 'Ṃ' => 'Ṃ', 'ṃ' => 'ṃ', 'Ṅ' => 'Ṅ', 'ṅ' => 'ṅ', 'Ṇ' => 'Ṇ', 'ṇ' => 'ṇ', 'Ṉ' => 'Ṉ', 'ṉ' => 'ṉ', 'Ṋ' => 'Ṋ', 'ṋ' => 'ṋ', 'Ṍ' => 'Ṍ', 'ṍ' => 'ṍ', 'Ṏ' => 'Ṏ', 'ṏ' => 'ṏ', 'Ṑ' => 'Ṑ', 'ṑ' => 'ṑ', 'Ṓ' => 'Ṓ', 'ṓ' => 'ṓ', 'Ṕ' => 'Ṕ', 'ṕ' => 'ṕ', 'Ṗ' => 'Ṗ', 'ṗ' => 'ṗ', 'Ṙ' => 'Ṙ', 'ṙ' => 'ṙ', 'Ṛ' => 'Ṛ', 'ṛ' => 'ṛ', 'Ṝ' => 'Ṝ', 'ṝ' => 'ṝ', 'Ṟ' => 'Ṟ', 'ṟ' => 'ṟ', 'Ṡ' => 'Ṡ', 'ṡ' => 'ṡ', 'Ṣ' => 'Ṣ', 'ṣ' => 'ṣ', 'Ṥ' => 'Ṥ', 'ṥ' => 'ṥ', 'Ṧ' => 'Ṧ', 'ṧ' => 'ṧ', 'Ṩ' => 'Ṩ', 'ṩ' => 'ṩ', 'Ṫ' => 'Ṫ', 'ṫ' => 'ṫ', 'Ṭ' => 'Ṭ', 'ṭ' => 'ṭ', 'Ṯ' => 'Ṯ', 'ṯ' => 'ṯ', 'Ṱ' => 'Ṱ', 'ṱ' => 'ṱ', 'Ṳ' => 'Ṳ', 'ṳ' => 'ṳ', 'Ṵ' => 'Ṵ', 'ṵ' => 'ṵ', 'Ṷ' => 'Ṷ', 'ṷ' => 'ṷ', 'Ṹ' => 'Ṹ', 'ṹ' => 'ṹ', 'Ṻ' => 'Ṻ', 'ṻ' => 'ṻ', 'Ṽ' => 'Ṽ', 'ṽ' => 'ṽ', 'Ṿ' => 'Ṿ', 'ṿ' => 'ṿ', 'Ẁ' => 'Ẁ', 'ẁ' => 'ẁ', 'Ẃ' => 'Ẃ', 'ẃ' => 'ẃ', 'Ẅ' => 'Ẅ', 'ẅ' => 'ẅ', 'Ẇ' => 'Ẇ', 'ẇ' => 'ẇ', 'Ẉ' => 'Ẉ', 'ẉ' => 'ẉ', 'Ẋ' => 'Ẋ', 'ẋ' => 'ẋ', 'Ẍ' => 'Ẍ', 'ẍ' => 'ẍ', 'Ẏ' => 'Ẏ', 'ẏ' => 'ẏ', 'Ẑ' => 'Ẑ', 'ẑ' => 'ẑ', 'Ẓ' => 'Ẓ', 'ẓ' => 'ẓ', 'Ẕ' => 'Ẕ', 'ẕ' => 'ẕ', 'ẖ' => 'ẖ', 'ẗ' => 'ẗ', 'ẘ' => 'ẘ', 'ẙ' => 'ẙ', 'ẛ' => 'ẛ', 'Ạ' => 'Ạ', 'ạ' => 'ạ', 'Ả' => 'Ả', 'ả' => 'ả', 'Ấ' => 'Ấ', 'ấ' => 'ấ', 'Ầ' => 'Ầ', 'ầ' => 'ầ', 'Ẩ' => 'Ẩ', 'ẩ' => 'ẩ', 'Ẫ' => 'Ẫ', 'ẫ' => 'ẫ', 'Ậ' => 'Ậ', 'ậ' => 'ậ', 'Ắ' => 'Ắ', 'ắ' => 'ắ', 'Ằ' => 'Ằ', 'ằ' => 'ằ', 'Ẳ' => 'Ẳ', 'ẳ' => 'ẳ', 'Ẵ' => 'Ẵ', 'ẵ' => 'ẵ', 'Ặ' => 'Ặ', 'ặ' => 'ặ', 'Ẹ' => 'Ẹ', 'ẹ' => 'ẹ', 'Ẻ' => 'Ẻ', 'ẻ' => 'ẻ', 'Ẽ' => 'Ẽ', 'ẽ' => 'ẽ', 'Ế' => 'Ế', 'ế' => 'ế', 'Ề' => 'Ề', 'ề' => 'ề', 'Ể' => 'Ể', 'ể' => 'ể', 'Ễ' => 'Ễ', 'ễ' => 'ễ', 'Ệ' => 'Ệ', 'ệ' => 'ệ', 'Ỉ' => 'Ỉ', 'ỉ' => 'ỉ', 'Ị' => 'Ị', 'ị' => 'ị', 'Ọ' => 'Ọ', 'ọ' => 'ọ', 'Ỏ' => 'Ỏ', 'ỏ' => 'ỏ', 'Ố' => 'Ố', 'ố' => 'ố', 'Ồ' => 'Ồ', 'ồ' => 'ồ', 'Ổ' => 'Ổ', 'ổ' => 'ổ', 'Ỗ' => 'Ỗ', 'ỗ' => 'ỗ', 'Ộ' => 'Ộ', 'ộ' => 'ộ', 'Ớ' => 'Ớ', 'ớ' => 'ớ', 'Ờ' => 'Ờ', 'ờ' => 'ờ', 'Ở' => 'Ở', 'ở' => 'ở', 'Ỡ' => 'Ỡ', 'ỡ' => 'ỡ', 'Ợ' => 'Ợ', 'ợ' => 'ợ', 'Ụ' => 'Ụ', 'ụ' => 'ụ', 'Ủ' => 'Ủ', 'ủ' => 'ủ', 'Ứ' => 'Ứ', 'ứ' => 'ứ', 'Ừ' => 'Ừ', 'ừ' => 'ừ', 'Ử' => 'Ử', 'ử' => 'ử', 'Ữ' => 'Ữ', 'ữ' => 'ữ', 'Ự' => 'Ự', 'ự' => 'ự', 'Ỳ' => 'Ỳ', 'ỳ' => 'ỳ', 'Ỵ' => 'Ỵ', 'ỵ' => 'ỵ', 'Ỷ' => 'Ỷ', 'ỷ' => 'ỷ', 'Ỹ' => 'Ỹ', 'ỹ' => 'ỹ', 'ἀ' => 'ἀ', 'ἁ' => 'ἁ', 'ἂ' => 'ἂ', 'ἃ' => 'ἃ', 'ἄ' => 'ἄ', 'ἅ' => 'ἅ', 'ἆ' => 'ἆ', 'ἇ' => 'ἇ', 'Ἀ' => 'Ἀ', 'Ἁ' => 'Ἁ', 'Ἂ' => 'Ἂ', 'Ἃ' => 'Ἃ', 'Ἄ' => 'Ἄ', 'Ἅ' => 'Ἅ', 'Ἆ' => 'Ἆ', 'Ἇ' => 'Ἇ', 'ἐ' => 'ἐ', 'ἑ' => 'ἑ', 'ἒ' => 'ἒ', 'ἓ' => 'ἓ', 'ἔ' => 'ἔ', 'ἕ' => 'ἕ', 'Ἐ' => 'Ἐ', 'Ἑ' => 'Ἑ', 'Ἒ' => 'Ἒ', 'Ἓ' => 'Ἓ', 'Ἔ' => 'Ἔ', 'Ἕ' => 'Ἕ', 'ἠ' => 'ἠ', 'ἡ' => 'ἡ', 'ἢ' => 'ἢ', 'ἣ' => 'ἣ', 'ἤ' => 'ἤ', 'ἥ' => 'ἥ', 'ἦ' => 'ἦ', 'ἧ' => 'ἧ', 'Ἠ' => 'Ἠ', 'Ἡ' => 'Ἡ', 'Ἢ' => 'Ἢ', 'Ἣ' => 'Ἣ', 'Ἤ' => 'Ἤ', 'Ἥ' => 'Ἥ', 'Ἦ' => 'Ἦ', 'Ἧ' => 'Ἧ', 'ἰ' => 'ἰ', 'ἱ' => 'ἱ', 'ἲ' => 'ἲ', 'ἳ' => 'ἳ', 'ἴ' => 'ἴ', 'ἵ' => 'ἵ', 'ἶ' => 'ἶ', 'ἷ' => 'ἷ', 'Ἰ' => 'Ἰ', 'Ἱ' => 'Ἱ', 'Ἲ' => 'Ἲ', 'Ἳ' => 'Ἳ', 'Ἴ' => 'Ἴ', 'Ἵ' => 'Ἵ', 'Ἶ' => 'Ἶ', 'Ἷ' => 'Ἷ', 'ὀ' => 'ὀ', 'ὁ' => 'ὁ', 'ὂ' => 'ὂ', 'ὃ' => 'ὃ', 'ὄ' => 'ὄ', 'ὅ' => 'ὅ', 'Ὀ' => 'Ὀ', 'Ὁ' => 'Ὁ', 'Ὂ' => 'Ὂ', 'Ὃ' => 'Ὃ', 'Ὄ' => 'Ὄ', 'Ὅ' => 'Ὅ', 'ὐ' => 'ὐ', 'ὑ' => 'ὑ', 'ὒ' => 'ὒ', 'ὓ' => 'ὓ', 'ὔ' => 'ὔ', 'ὕ' => 'ὕ', 'ὖ' => 'ὖ', 'ὗ' => 'ὗ', 'Ὑ' => 'Ὑ', 'Ὓ' => 'Ὓ', 'Ὕ' => 'Ὕ', 'Ὗ' => 'Ὗ', 'ὠ' => 'ὠ', 'ὡ' => 'ὡ', 'ὢ' => 'ὢ', 'ὣ' => 'ὣ', 'ὤ' => 'ὤ', 'ὥ' => 'ὥ', 'ὦ' => 'ὦ', 'ὧ' => 'ὧ', 'Ὠ' => 'Ὠ', 'Ὡ' => 'Ὡ', 'Ὢ' => 'Ὢ', 'Ὣ' => 'Ὣ', 'Ὤ' => 'Ὤ', 'Ὥ' => 'Ὥ', 'Ὦ' => 'Ὦ', 'Ὧ' => 'Ὧ', 'ὰ' => 'ὰ', 'ά' => 'ά', 'ὲ' => 'ὲ', 'έ' => 'έ', 'ὴ' => 'ὴ', 'ή' => 'ή', 'ὶ' => 'ὶ', 'ί' => 'ί', 'ὸ' => 'ὸ', 'ό' => 'ό', 'ὺ' => 'ὺ', 'ύ' => 'ύ', 'ὼ' => 'ὼ', 'ώ' => 'ώ', 'ᾀ' => 'ᾀ', 'ᾁ' => 'ᾁ', 'ᾂ' => 'ᾂ', 'ᾃ' => 'ᾃ', 'ᾄ' => 'ᾄ', 'ᾅ' => 'ᾅ', 'ᾆ' => 'ᾆ', 'ᾇ' => 'ᾇ', 'ᾈ' => 'ᾈ', 'ᾉ' => 'ᾉ', 'ᾊ' => 'ᾊ', 'ᾋ' => 'ᾋ', 'ᾌ' => 'ᾌ', 'ᾍ' => 'ᾍ', 'ᾎ' => 'ᾎ', 'ᾏ' => 'ᾏ', 'ᾐ' => 'ᾐ', 'ᾑ' => 'ᾑ', 'ᾒ' => 'ᾒ', 'ᾓ' => 'ᾓ', 'ᾔ' => 'ᾔ', 'ᾕ' => 'ᾕ', 'ᾖ' => 'ᾖ', 'ᾗ' => 'ᾗ', 'ᾘ' => 'ᾘ', 'ᾙ' => 'ᾙ', 'ᾚ' => 'ᾚ', 'ᾛ' => 'ᾛ', 'ᾜ' => 'ᾜ', 'ᾝ' => 'ᾝ', 'ᾞ' => 'ᾞ', 'ᾟ' => 'ᾟ', 'ᾠ' => 'ᾠ', 'ᾡ' => 'ᾡ', 'ᾢ' => 'ᾢ', 'ᾣ' => 'ᾣ', 'ᾤ' => 'ᾤ', 'ᾥ' => 'ᾥ', 'ᾦ' => 'ᾦ', 'ᾧ' => 'ᾧ', 'ᾨ' => 'ᾨ', 'ᾩ' => 'ᾩ', 'ᾪ' => 'ᾪ', 'ᾫ' => 'ᾫ', 'ᾬ' => 'ᾬ', 'ᾭ' => 'ᾭ', 'ᾮ' => 'ᾮ', 'ᾯ' => 'ᾯ', 'ᾰ' => 'ᾰ', 'ᾱ' => 'ᾱ', 'ᾲ' => 'ᾲ', 'ᾳ' => 'ᾳ', 'ᾴ' => 'ᾴ', 'ᾶ' => 'ᾶ', 'ᾷ' => 'ᾷ', 'Ᾰ' => 'Ᾰ', 'Ᾱ' => 'Ᾱ', 'Ὰ' => 'Ὰ', 'Ά' => 'Ά', 'ᾼ' => 'ᾼ', 'ι' => 'ι', '῁' => '῁', 'ῂ' => 'ῂ', 'ῃ' => 'ῃ', 'ῄ' => 'ῄ', 'ῆ' => 'ῆ', 'ῇ' => 'ῇ', 'Ὲ' => 'Ὲ', 'Έ' => 'Έ', 'Ὴ' => 'Ὴ', 'Ή' => 'Ή', 'ῌ' => 'ῌ', '῍' => '῍', '῎' => '῎', '῏' => '῏', 'ῐ' => 'ῐ', 'ῑ' => 'ῑ', 'ῒ' => 'ῒ', 'ΐ' => 'ΐ', 'ῖ' => 'ῖ', 'ῗ' => 'ῗ', 'Ῐ' => 'Ῐ', 'Ῑ' => 'Ῑ', 'Ὶ' => 'Ὶ', 'Ί' => 'Ί', '῝' => '῝', '῞' => '῞', '῟' => '῟', 'ῠ' => 'ῠ', 'ῡ' => 'ῡ', 'ῢ' => 'ῢ', 'ΰ' => 'ΰ', 'ῤ' => 'ῤ', 'ῥ' => 'ῥ', 'ῦ' => 'ῦ', 'ῧ' => 'ῧ', 'Ῠ' => 'Ῠ', 'Ῡ' => 'Ῡ', 'Ὺ' => 'Ὺ', 'Ύ' => 'Ύ', 'Ῥ' => 'Ῥ', '῭' => '῭', '΅' => '΅', '`' => '`', 'ῲ' => 'ῲ', 'ῳ' => 'ῳ', 'ῴ' => 'ῴ', 'ῶ' => 'ῶ', 'ῷ' => 'ῷ', 'Ὸ' => 'Ὸ', 'Ό' => 'Ό', 'Ὼ' => 'Ὼ', 'Ώ' => 'Ώ', 'ῼ' => 'ῼ', '´' => '´', ' ' => ' ', ' ' => ' ', 'Ω' => 'Ω', 'K' => 'K', 'Å' => 'Å', '↚' => '↚', '↛' => '↛', '↮' => '↮', '⇍' => '⇍', '⇎' => '⇎', '⇏' => '⇏', '∄' => '∄', '∉' => '∉', '∌' => '∌', '∤' => '∤', '∦' => '∦', '≁' => '≁', '≄' => '≄', '≇' => '≇', '≉' => '≉', '≠' => '≠', '≢' => '≢', '≭' => '≭', '≮' => '≮', '≯' => '≯', '≰' => '≰', '≱' => '≱', '≴' => '≴', '≵' => '≵', '≸' => '≸', '≹' => '≹', '⊀' => '⊀', '⊁' => '⊁', '⊄' => '⊄', '⊅' => '⊅', '⊈' => '⊈', '⊉' => '⊉', '⊬' => '⊬', '⊭' => '⊭', '⊮' => '⊮', '⊯' => '⊯', '⋠' => '⋠', '⋡' => '⋡', '⋢' => '⋢', '⋣' => '⋣', '⋪' => '⋪', '⋫' => '⋫', '⋬' => '⋬', '⋭' => '⋭', '〈' => '〈', '〉' => '〉', '⫝̸' => '⫝̸', 'が' => 'が', 'ぎ' => 'ぎ', 'ぐ' => 'ぐ', 'げ' => 'げ', 'ご' => 'ご', 'ざ' => 'ざ', 'じ' => 'じ', 'ず' => 'ず', 'ぜ' => 'ぜ', 'ぞ' => 'ぞ', 'だ' => 'だ', 'ぢ' => 'ぢ', 'づ' => 'づ', 'で' => 'で', 'ど' => 'ど', 'ば' => 'ば', 'ぱ' => 'ぱ', 'び' => 'び', 'ぴ' => 'ぴ', 'ぶ' => 'ぶ', 'ぷ' => 'ぷ', 'べ' => 'べ', 'ぺ' => 'ぺ', 'ぼ' => 'ぼ', 'ぽ' => 'ぽ', 'ゔ' => 'ゔ', 'ゞ' => 'ゞ', 'ガ' => 'ガ', 'ギ' => 'ギ', 'グ' => 'グ', 'ゲ' => 'ゲ', 'ゴ' => 'ゴ', 'ザ' => 'ザ', 'ジ' => 'ジ', 'ズ' => 'ズ', 'ゼ' => 'ゼ', 'ゾ' => 'ゾ', 'ダ' => 'ダ', 'ヂ' => 'ヂ', 'ヅ' => 'ヅ', 'デ' => 'デ', 'ド' => 'ド', 'バ' => 'バ', 'パ' => 'パ', 'ビ' => 'ビ', 'ピ' => 'ピ', 'ブ' => 'ブ', 'プ' => 'プ', 'ベ' => 'ベ', 'ペ' => 'ペ', 'ボ' => 'ボ', 'ポ' => 'ポ', 'ヴ' => 'ヴ', 'ヷ' => 'ヷ', 'ヸ' => 'ヸ', 'ヹ' => 'ヹ', 'ヺ' => 'ヺ', 'ヾ' => 'ヾ', '豈' => '豈', '更' => '更', '車' => '車', '賈' => '賈', '滑' => '滑', '串' => '串', '句' => '句', '龜' => '龜', '龜' => '龜', '契' => '契', '金' => '金', '喇' => '喇', '奈' => '奈', '懶' => '懶', '癩' => '癩', '羅' => '羅', '蘿' => '蘿', '螺' => '螺', '裸' => '裸', '邏' => '邏', '樂' => '樂', '洛' => '洛', '烙' => '烙', '珞' => '珞', '落' => '落', '酪' => '酪', '駱' => '駱', '亂' => '亂', '卵' => '卵', '欄' => '欄', '爛' => '爛', '蘭' => '蘭', '鸞' => '鸞', '嵐' => '嵐', '濫' => '濫', '藍' => '藍', '襤' => '襤', '拉' => '拉', '臘' => '臘', '蠟' => '蠟', '廊' => '廊', '朗' => '朗', '浪' => '浪', '狼' => '狼', '郎' => '郎', '來' => '來', '冷' => '冷', '勞' => '勞', '擄' => '擄', '櫓' => '櫓', '爐' => '爐', '盧' => '盧', '老' => '老', '蘆' => '蘆', '虜' => '虜', '路' => '路', '露' => '露', '魯' => '魯', '鷺' => '鷺', '碌' => '碌', '祿' => '祿', '綠' => '綠', '菉' => '菉', '錄' => '錄', '鹿' => '鹿', '論' => '論', '壟' => '壟', '弄' => '弄', '籠' => '籠', '聾' => '聾', '牢' => '牢', '磊' => '磊', '賂' => '賂', '雷' => '雷', '壘' => '壘', '屢' => '屢', '樓' => '樓', '淚' => '淚', '漏' => '漏', '累' => '累', '縷' => '縷', '陋' => '陋', '勒' => '勒', '肋' => '肋', '凜' => '凜', '凌' => '凌', '稜' => '稜', '綾' => '綾', '菱' => '菱', '陵' => '陵', '讀' => '讀', '拏' => '拏', '樂' => '樂', '諾' => '諾', '丹' => '丹', '寧' => '寧', '怒' => '怒', '率' => '率', '異' => '異', '北' => '北', '磻' => '磻', '便' => '便', '復' => '復', '不' => '不', '泌' => '泌', '數' => '數', '索' => '索', '參' => '參', '塞' => '塞', '省' => '省', '葉' => '葉', '說' => '說', '殺' => '殺', '辰' => '辰', '沈' => '沈', '拾' => '拾', '若' => '若', '掠' => '掠', '略' => '略', '亮' => '亮', '兩' => '兩', '凉' => '凉', '梁' => '梁', '糧' => '糧', '良' => '良', '諒' => '諒', '量' => '量', '勵' => '勵', '呂' => '呂', '女' => '女', '廬' => '廬', '旅' => '旅', '濾' => '濾', '礪' => '礪', '閭' => '閭', '驪' => '驪', '麗' => '麗', '黎' => '黎', '力' => '力', '曆' => '曆', '歷' => '歷', '轢' => '轢', '年' => '年', '憐' => '憐', '戀' => '戀', '撚' => '撚', '漣' => '漣', '煉' => '煉', '璉' => '璉', '秊' => '秊', '練' => '練', '聯' => '聯', '輦' => '輦', '蓮' => '蓮', '連' => '連', '鍊' => '鍊', '列' => '列', '劣' => '劣', '咽' => '咽', '烈' => '烈', '裂' => '裂', '說' => '說', '廉' => '廉', '念' => '念', '捻' => '捻', '殮' => '殮', '簾' => '簾', '獵' => '獵', '令' => '令', '囹' => '囹', '寧' => '寧', '嶺' => '嶺', '怜' => '怜', '玲' => '玲', '瑩' => '瑩', '羚' => '羚', '聆' => '聆', '鈴' => '鈴', '零' => '零', '靈' => '靈', '領' => '領', '例' => '例', '禮' => '禮', '醴' => '醴', '隸' => '隸', '惡' => '惡', '了' => '了', '僚' => '僚', '寮' => '寮', '尿' => '尿', '料' => '料', '樂' => '樂', '燎' => '燎', '療' => '療', '蓼' => '蓼', '遼' => '遼', '龍' => '龍', '暈' => '暈', '阮' => '阮', '劉' => '劉', '杻' => '杻', '柳' => '柳', '流' => '流', '溜' => '溜', '琉' => '琉', '留' => '留', '硫' => '硫', '紐' => '紐', '類' => '類', '六' => '六', '戮' => '戮', '陸' => '陸', '倫' => '倫', '崙' => '崙', '淪' => '淪', '輪' => '輪', '律' => '律', '慄' => '慄', '栗' => '栗', '率' => '率', '隆' => '隆', '利' => '利', '吏' => '吏', '履' => '履', '易' => '易', '李' => '李', '梨' => '梨', '泥' => '泥', '理' => '理', '痢' => '痢', '罹' => '罹', '裏' => '裏', '裡' => '裡', '里' => '里', '離' => '離', '匿' => '匿', '溺' => '溺', '吝' => '吝', '燐' => '燐', '璘' => '璘', '藺' => '藺', '隣' => '隣', '鱗' => '鱗', '麟' => '麟', '林' => '林', '淋' => '淋', '臨' => '臨', '立' => '立', '笠' => '笠', '粒' => '粒', '狀' => '狀', '炙' => '炙', '識' => '識', '什' => '什', '茶' => '茶', '刺' => '刺', '切' => '切', '度' => '度', '拓' => '拓', '糖' => '糖', '宅' => '宅', '洞' => '洞', '暴' => '暴', '輻' => '輻', '行' => '行', '降' => '降', '見' => '見', '廓' => '廓', '兀' => '兀', '嗀' => '嗀', '塚' => '塚', '晴' => '晴', '凞' => '凞', '猪' => '猪', '益' => '益', '礼' => '礼', '神' => '神', '祥' => '祥', '福' => '福', '靖' => '靖', '精' => '精', '羽' => '羽', '蘒' => '蘒', '諸' => '諸', '逸' => '逸', '都' => '都', '飯' => '飯', '飼' => '飼', '館' => '館', '鶴' => '鶴', '郞' => '郞', '隷' => '隷', '侮' => '侮', '僧' => '僧', '免' => '免', '勉' => '勉', '勤' => '勤', '卑' => '卑', '喝' => '喝', '嘆' => '嘆', '器' => '器', '塀' => '塀', '墨' => '墨', '層' => '層', '屮' => '屮', '悔' => '悔', '慨' => '慨', '憎' => '憎', '懲' => '懲', '敏' => '敏', '既' => '既', '暑' => '暑', '梅' => '梅', '海' => '海', '渚' => '渚', '漢' => '漢', '煮' => '煮', '爫' => '爫', '琢' => '琢', '碑' => '碑', '社' => '社', '祉' => '祉', '祈' => '祈', '祐' => '祐', '祖' => '祖', '祝' => '祝', '禍' => '禍', '禎' => '禎', '穀' => '穀', '突' => '突', '節' => '節', '練' => '練', '縉' => '縉', '繁' => '繁', '署' => '署', '者' => '者', '臭' => '臭', '艹' => '艹', '艹' => '艹', '著' => '著', '褐' => '褐', '視' => '視', '謁' => '謁', '謹' => '謹', '賓' => '賓', '贈' => '贈', '辶' => '辶', '逸' => '逸', '難' => '難', '響' => '響', '頻' => '頻', '恵' => '恵', '𤋮' => '𤋮', '舘' => '舘', '並' => '並', '况' => '况', '全' => '全', '侀' => '侀', '充' => '充', '冀' => '冀', '勇' => '勇', '勺' => '勺', '喝' => '喝', '啕' => '啕', '喙' => '喙', '嗢' => '嗢', '塚' => '塚', '墳' => '墳', '奄' => '奄', '奔' => '奔', '婢' => '婢', '嬨' => '嬨', '廒' => '廒', '廙' => '廙', '彩' => '彩', '徭' => '徭', '惘' => '惘', '慎' => '慎', '愈' => '愈', '憎' => '憎', '慠' => '慠', '懲' => '懲', '戴' => '戴', '揄' => '揄', '搜' => '搜', '摒' => '摒', '敖' => '敖', '晴' => '晴', '朗' => '朗', '望' => '望', '杖' => '杖', '歹' => '歹', '殺' => '殺', '流' => '流', '滛' => '滛', '滋' => '滋', '漢' => '漢', '瀞' => '瀞', '煮' => '煮', '瞧' => '瞧', '爵' => '爵', '犯' => '犯', '猪' => '猪', '瑱' => '瑱', '甆' => '甆', '画' => '画', '瘝' => '瘝', '瘟' => '瘟', '益' => '益', '盛' => '盛', '直' => '直', '睊' => '睊', '着' => '着', '磌' => '磌', '窱' => '窱', '節' => '節', '类' => '类', '絛' => '絛', '練' => '練', '缾' => '缾', '者' => '者', '荒' => '荒', '華' => '華', '蝹' => '蝹', '襁' => '襁', '覆' => '覆', '視' => '視', '調' => '調', '諸' => '諸', '請' => '請', '謁' => '謁', '諾' => '諾', '諭' => '諭', '謹' => '謹', '變' => '變', '贈' => '贈', '輸' => '輸', '遲' => '遲', '醙' => '醙', '鉶' => '鉶', '陼' => '陼', '難' => '難', '靖' => '靖', '韛' => '韛', '響' => '響', '頋' => '頋', '頻' => '頻', '鬒' => '鬒', '龜' => '龜', '𢡊' => '𢡊', '𢡄' => '𢡄', '𣏕' => '𣏕', '㮝' => '㮝', '䀘' => '䀘', '䀹' => '䀹', '𥉉' => '𥉉', '𥳐' => '𥳐', '𧻓' => '𧻓', '齃' => '齃', '龎' => '龎', 'יִ' => 'יִ', 'ײַ' => 'ײַ', 'שׁ' => 'שׁ', 'שׂ' => 'שׂ', 'שּׁ' => 'שּׁ', 'שּׂ' => 'שּׂ', 'אַ' => 'אַ', 'אָ' => 'אָ', 'אּ' => 'אּ', 'בּ' => 'בּ', 'גּ' => 'גּ', 'דּ' => 'דּ', 'הּ' => 'הּ', 'וּ' => 'וּ', 'זּ' => 'זּ', 'טּ' => 'טּ', 'יּ' => 'יּ', 'ךּ' => 'ךּ', 'כּ' => 'כּ', 'לּ' => 'לּ', 'מּ' => 'מּ', 'נּ' => 'נּ', 'סּ' => 'סּ', 'ףּ' => 'ףּ', 'פּ' => 'פּ', 'צּ' => 'צּ', 'קּ' => 'קּ', 'רּ' => 'רּ', 'שּ' => 'שּ', 'תּ' => 'תּ', 'וֹ' => 'וֹ', 'בֿ' => 'בֿ', 'כֿ' => 'כֿ', 'פֿ' => 'פֿ', '𑂚' => '𑂚', '𑂜' => '𑂜', '𑂫' => '𑂫', '𑄮' => '𑄮', '𑄯' => '𑄯', '𑍋' => '𑍋', '𑍌' => '𑍌', '𑒻' => '𑒻', '𑒼' => '𑒼', '𑒾' => '𑒾', '𑖺' => '𑖺', '𑖻' => '𑖻', '𑤸' => '𑤸', '𝅗𝅥' => '𝅗𝅥', '𝅘𝅥' => '𝅘𝅥', '𝅘𝅥𝅮' => '𝅘𝅥𝅮', '𝅘𝅥𝅯' => '𝅘𝅥𝅯', '𝅘𝅥𝅰' => '𝅘𝅥𝅰', '𝅘𝅥𝅱' => '𝅘𝅥𝅱', '𝅘𝅥𝅲' => '𝅘𝅥𝅲', '𝆹𝅥' => '𝆹𝅥', '𝆺𝅥' => '𝆺𝅥', '𝆹𝅥𝅮' => '𝆹𝅥𝅮', '𝆺𝅥𝅮' => '𝆺𝅥𝅮', '𝆹𝅥𝅯' => '𝆹𝅥𝅯', '𝆺𝅥𝅯' => '𝆺𝅥𝅯', '丽' => '丽', '丸' => '丸', '乁' => '乁', '𠄢' => '𠄢', '你' => '你', '侮' => '侮', '侻' => '侻', '倂' => '倂', '偺' => '偺', '備' => '備', '僧' => '僧', '像' => '像', '㒞' => '㒞', '𠘺' => '𠘺', '免' => '免', '兔' => '兔', '兤' => '兤', '具' => '具', '𠔜' => '𠔜', '㒹' => '㒹', '內' => '內', '再' => '再', '𠕋' => '𠕋', '冗' => '冗', '冤' => '冤', '仌' => '仌', '冬' => '冬', '况' => '况', '𩇟' => '𩇟', '凵' => '凵', '刃' => '刃', '㓟' => '㓟', '刻' => '刻', '剆' => '剆', '割' => '割', '剷' => '剷', '㔕' => '㔕', '勇' => '勇', '勉' => '勉', '勤' => '勤', '勺' => '勺', '包' => '包', '匆' => '匆', '北' => '北', '卉' => '卉', '卑' => '卑', '博' => '博', '即' => '即', '卽' => '卽', '卿' => '卿', '卿' => '卿', '卿' => '卿', '𠨬' => '𠨬', '灰' => '灰', '及' => '及', '叟' => '叟', '𠭣' => '𠭣', '叫' => '叫', '叱' => '叱', '吆' => '吆', '咞' => '咞', '吸' => '吸', '呈' => '呈', '周' => '周', '咢' => '咢', '哶' => '哶', '唐' => '唐', '啓' => '啓', '啣' => '啣', '善' => '善', '善' => '善', '喙' => '喙', '喫' => '喫', '喳' => '喳', '嗂' => '嗂', '圖' => '圖', '嘆' => '嘆', '圗' => '圗', '噑' => '噑', '噴' => '噴', '切' => '切', '壮' => '壮', '城' => '城', '埴' => '埴', '堍' => '堍', '型' => '型', '堲' => '堲', '報' => '報', '墬' => '墬', '𡓤' => '𡓤', '売' => '売', '壷' => '壷', '夆' => '夆', '多' => '多', '夢' => '夢', '奢' => '奢', '𡚨' => '𡚨', '𡛪' => '𡛪', '姬' => '姬', '娛' => '娛', '娧' => '娧', '姘' => '姘', '婦' => '婦', '㛮' => '㛮', '㛼' => '㛼', '嬈' => '嬈', '嬾' => '嬾', '嬾' => '嬾', '𡧈' => '𡧈', '寃' => '寃', '寘' => '寘', '寧' => '寧', '寳' => '寳', '𡬘' => '𡬘', '寿' => '寿', '将' => '将', '当' => '当', '尢' => '尢', '㞁' => '㞁', '屠' => '屠', '屮' => '屮', '峀' => '峀', '岍' => '岍', '𡷤' => '𡷤', '嵃' => '嵃', '𡷦' => '𡷦', '嵮' => '嵮', '嵫' => '嵫', '嵼' => '嵼', '巡' => '巡', '巢' => '巢', '㠯' => '㠯', '巽' => '巽', '帨' => '帨', '帽' => '帽', '幩' => '幩', '㡢' => '㡢', '𢆃' => '𢆃', '㡼' => '㡼', '庰' => '庰', '庳' => '庳', '庶' => '庶', '廊' => '廊', '𪎒' => '𪎒', '廾' => '廾', '𢌱' => '𢌱', '𢌱' => '𢌱', '舁' => '舁', '弢' => '弢', '弢' => '弢', '㣇' => '㣇', '𣊸' => '𣊸', '𦇚' => '𦇚', '形' => '形', '彫' => '彫', '㣣' => '㣣', '徚' => '徚', '忍' => '忍', '志' => '志', '忹' => '忹', '悁' => '悁', '㤺' => '㤺', '㤜' => '㤜', '悔' => '悔', '𢛔' => '𢛔', '惇' => '惇', '慈' => '慈', '慌' => '慌', '慎' => '慎', '慌' => '慌', '慺' => '慺', '憎' => '憎', '憲' => '憲', '憤' => '憤', '憯' => '憯', '懞' => '懞', '懲' => '懲', '懶' => '懶', '成' => '成', '戛' => '戛', '扝' => '扝', '抱' => '抱', '拔' => '拔', '捐' => '捐', '𢬌' => '𢬌', '挽' => '挽', '拼' => '拼', '捨' => '捨', '掃' => '掃', '揤' => '揤', '𢯱' => '𢯱', '搢' => '搢', '揅' => '揅', '掩' => '掩', '㨮' => '㨮', '摩' => '摩', '摾' => '摾', '撝' => '撝', '摷' => '摷', '㩬' => '㩬', '敏' => '敏', '敬' => '敬', '𣀊' => '𣀊', '旣' => '旣', '書' => '書', '晉' => '晉', '㬙' => '㬙', '暑' => '暑', '㬈' => '㬈', '㫤' => '㫤', '冒' => '冒', '冕' => '冕', '最' => '最', '暜' => '暜', '肭' => '肭', '䏙' => '䏙', '朗' => '朗', '望' => '望', '朡' => '朡', '杞' => '杞', '杓' => '杓', '𣏃' => '𣏃', '㭉' => '㭉', '柺' => '柺', '枅' => '枅', '桒' => '桒', '梅' => '梅', '𣑭' => '𣑭', '梎' => '梎', '栟' => '栟', '椔' => '椔', '㮝' => '㮝', '楂' => '楂', '榣' => '榣', '槪' => '槪', '檨' => '檨', '𣚣' => '𣚣', '櫛' => '櫛', '㰘' => '㰘', '次' => '次', '𣢧' => '𣢧', '歔' => '歔', '㱎' => '㱎', '歲' => '歲', '殟' => '殟', '殺' => '殺', '殻' => '殻', '𣪍' => '𣪍', '𡴋' => '𡴋', '𣫺' => '𣫺', '汎' => '汎', '𣲼' => '𣲼', '沿' => '沿', '泍' => '泍', '汧' => '汧', '洖' => '洖', '派' => '派', '海' => '海', '流' => '流', '浩' => '浩', '浸' => '浸', '涅' => '涅', '𣴞' => '𣴞', '洴' => '洴', '港' => '港', '湮' => '湮', '㴳' => '㴳', '滋' => '滋', '滇' => '滇', '𣻑' => '𣻑', '淹' => '淹', '潮' => '潮', '𣽞' => '𣽞', '𣾎' => '𣾎', '濆' => '濆', '瀹' => '瀹', '瀞' => '瀞', '瀛' => '瀛', '㶖' => '㶖', '灊' => '灊', '災' => '災', '灷' => '灷', '炭' => '炭', '𠔥' => '𠔥', '煅' => '煅', '𤉣' => '𤉣', '熜' => '熜', '𤎫' => '𤎫', '爨' => '爨', '爵' => '爵', '牐' => '牐', '𤘈' => '𤘈', '犀' => '犀', '犕' => '犕', '𤜵' => '𤜵', '𤠔' => '𤠔', '獺' => '獺', '王' => '王', '㺬' => '㺬', '玥' => '玥', '㺸' => '㺸', '㺸' => '㺸', '瑇' => '瑇', '瑜' => '瑜', '瑱' => '瑱', '璅' => '璅', '瓊' => '瓊', '㼛' => '㼛', '甤' => '甤', '𤰶' => '𤰶', '甾' => '甾', '𤲒' => '𤲒', '異' => '異', '𢆟' => '𢆟', '瘐' => '瘐', '𤾡' => '𤾡', '𤾸' => '𤾸', '𥁄' => '𥁄', '㿼' => '㿼', '䀈' => '䀈', '直' => '直', '𥃳' => '𥃳', '𥃲' => '𥃲', '𥄙' => '𥄙', '𥄳' => '𥄳', '眞' => '眞', '真' => '真', '真' => '真', '睊' => '睊', '䀹' => '䀹', '瞋' => '瞋', '䁆' => '䁆', '䂖' => '䂖', '𥐝' => '𥐝', '硎' => '硎', '碌' => '碌', '磌' => '磌', '䃣' => '䃣', '𥘦' => '𥘦', '祖' => '祖', '𥚚' => '𥚚', '𥛅' => '𥛅', '福' => '福', '秫' => '秫', '䄯' => '䄯', '穀' => '穀', '穊' => '穊', '穏' => '穏', '𥥼' => '𥥼', '𥪧' => '𥪧', '𥪧' => '𥪧', '竮' => '竮', '䈂' => '䈂', '𥮫' => '𥮫', '篆' => '篆', '築' => '築', '䈧' => '䈧', '𥲀' => '𥲀', '糒' => '糒', '䊠' => '䊠', '糨' => '糨', '糣' => '糣', '紀' => '紀', '𥾆' => '𥾆', '絣' => '絣', '䌁' => '䌁', '緇' => '緇', '縂' => '縂', '繅' => '繅', '䌴' => '䌴', '𦈨' => '𦈨', '𦉇' => '𦉇', '䍙' => '䍙', '𦋙' => '𦋙', '罺' => '罺', '𦌾' => '𦌾', '羕' => '羕', '翺' => '翺', '者' => '者', '𦓚' => '𦓚', '𦔣' => '𦔣', '聠' => '聠', '𦖨' => '𦖨', '聰' => '聰', '𣍟' => '𣍟', '䏕' => '䏕', '育' => '育', '脃' => '脃', '䐋' => '䐋', '脾' => '脾', '媵' => '媵', '𦞧' => '𦞧', '𦞵' => '𦞵', '𣎓' => '𣎓', '𣎜' => '𣎜', '舁' => '舁', '舄' => '舄', '辞' => '辞', '䑫' => '䑫', '芑' => '芑', '芋' => '芋', '芝' => '芝', '劳' => '劳', '花' => '花', '芳' => '芳', '芽' => '芽', '苦' => '苦', '𦬼' => '𦬼', '若' => '若', '茝' => '茝', '荣' => '荣', '莭' => '莭', '茣' => '茣', '莽' => '莽', '菧' => '菧', '著' => '著', '荓' => '荓', '菊' => '菊', '菌' => '菌', '菜' => '菜', '𦰶' => '𦰶', '𦵫' => '𦵫', '𦳕' => '𦳕', '䔫' => '䔫', '蓱' => '蓱', '蓳' => '蓳', '蔖' => '蔖', '𧏊' => '𧏊', '蕤' => '蕤', '𦼬' => '𦼬', '䕝' => '䕝', '䕡' => '䕡', '𦾱' => '𦾱', '𧃒' => '𧃒', '䕫' => '䕫', '虐' => '虐', '虜' => '虜', '虧' => '虧', '虩' => '虩', '蚩' => '蚩', '蚈' => '蚈', '蜎' => '蜎', '蛢' => '蛢', '蝹' => '蝹', '蜨' => '蜨', '蝫' => '蝫', '螆' => '螆', '䗗' => '䗗', '蟡' => '蟡', '蠁' => '蠁', '䗹' => '䗹', '衠' => '衠', '衣' => '衣', '𧙧' => '𧙧', '裗' => '裗', '裞' => '裞', '䘵' => '䘵', '裺' => '裺', '㒻' => '㒻', '𧢮' => '𧢮', '𧥦' => '𧥦', '䚾' => '䚾', '䛇' => '䛇', '誠' => '誠', '諭' => '諭', '變' => '變', '豕' => '豕', '𧲨' => '𧲨', '貫' => '貫', '賁' => '賁', '贛' => '贛', '起' => '起', '𧼯' => '𧼯', '𠠄' => '𠠄', '跋' => '跋', '趼' => '趼', '跰' => '跰', '𠣞' => '𠣞', '軔' => '軔', '輸' => '輸', '𨗒' => '𨗒', '𨗭' => '𨗭', '邔' => '邔', '郱' => '郱', '鄑' => '鄑', '𨜮' => '𨜮', '鄛' => '鄛', '鈸' => '鈸', '鋗' => '鋗', '鋘' => '鋘', '鉼' => '鉼', '鏹' => '鏹', '鐕' => '鐕', '𨯺' => '𨯺', '開' => '開', '䦕' => '䦕', '閷' => '閷', '𨵷' => '𨵷', '䧦' => '䧦', '雃' => '雃', '嶲' => '嶲', '霣' => '霣', '𩅅' => '𩅅', '𩈚' => '𩈚', '䩮' => '䩮', '䩶' => '䩶', '韠' => '韠', '𩐊' => '𩐊', '䪲' => '䪲', '𩒖' => '𩒖', '頋' => '頋', '頋' => '頋', '頩' => '頩', '𩖶' => '𩖶', '飢' => '飢', '䬳' => '䬳', '餩' => '餩', '馧' => '馧', '駂' => '駂', '駾' => '駾', '䯎' => '䯎', '𩬰' => '𩬰', '鬒' => '鬒', '鱀' => '鱀', '鳽' => '鳽', '䳎' => '䳎', '䳭' => '䳭', '鵧' => '鵧', '𪃎' => '𪃎', '䳸' => '䳸', '𪄅' => '𪄅', '𪈎' => '𪈎', '𪊑' => '𪊑', '麻' => '麻', '䵖' => '䵖', '黹' => '黹', '黾' => '黾', '鼅' => '鼅', '鼏' => '鼏', '鼖' => '鼖', '鼻' => '鼻', '𪘀' => '𪘀');
<?php

namespace _ContaoManager;

return array('À' => 'À', 'Á' => 'Á', 'Â' => 'Â', 'Ã' => 'Ã', 'Ä' => 'Ä', 'Å' => 'Å', 'Ç' => 'Ç', 'È' => 'È', 'É' => 'É', 'Ê' => 'Ê', 'Ë' => 'Ë', 'Ì' => 'Ì', 'Í' => 'Í', 'Î' => 'Î', 'Ï' => 'Ï', 'Ñ' => 'Ñ', 'Ò' => 'Ò', 'Ó' => 'Ó', 'Ô' => 'Ô', 'Õ' => 'Õ', 'Ö' => 'Ö', 'Ù' => 'Ù', 'Ú' => 'Ú', 'Û' => 'Û', 'Ü' => 'Ü', 'Ý' => 'Ý', 'à' => 'à', 'á' => 'á', 'â' => 'â', 'ã' => 'ã', 'ä' => 'ä', 'å' => 'å', 'ç' => 'ç', 'è' => 'è', 'é' => 'é', 'ê' => 'ê', 'ë' => 'ë', 'ì' => 'ì', 'í' => 'í', 'î' => 'î', 'ï' => 'ï', 'ñ' => 'ñ', 'ò' => 'ò', 'ó' => 'ó', 'ô' => 'ô', 'õ' => 'õ', 'ö' => 'ö', 'ù' => 'ù', 'ú' => 'ú', 'û' => 'û', 'ü' => 'ü', 'ý' => 'ý', 'ÿ' => 'ÿ', 'Ā' => 'Ā', 'ā' => 'ā', 'Ă' => 'Ă', 'ă' => 'ă', 'Ą' => 'Ą', 'ą' => 'ą', 'Ć' => 'Ć', 'ć' => 'ć', 'Ĉ' => 'Ĉ', 'ĉ' => 'ĉ', 'Ċ' => 'Ċ', 'ċ' => 'ċ', 'Č' => 'Č', 'č' => 'č', 'Ď' => 'Ď', 'ď' => 'ď', 'Ē' => 'Ē', 'ē' => 'ē', 'Ĕ' => 'Ĕ', 'ĕ' => 'ĕ', 'Ė' => 'Ė', 'ė' => 'ė', 'Ę' => 'Ę', 'ę' => 'ę', 'Ě' => 'Ě', 'ě' => 'ě', 'Ĝ' => 'Ĝ', 'ĝ' => 'ĝ', 'Ğ' => 'Ğ', 'ğ' => 'ğ', 'Ġ' => 'Ġ', 'ġ' => 'ġ', 'Ģ' => 'Ģ', 'ģ' => 'ģ', 'Ĥ' => 'Ĥ', 'ĥ' => 'ĥ', 'Ĩ' => 'Ĩ', 'ĩ' => 'ĩ', 'Ī' => 'Ī', 'ī' => 'ī', 'Ĭ' => 'Ĭ', 'ĭ' => 'ĭ', 'Į' => 'Į', 'į' => 'į', 'İ' => 'İ', 'Ĵ' => 'Ĵ', 'ĵ' => 'ĵ', 'Ķ' => 'Ķ', 'ķ' => 'ķ', 'Ĺ' => 'Ĺ', 'ĺ' => 'ĺ', 'Ļ' => 'Ļ', 'ļ' => 'ļ', 'Ľ' => 'Ľ', 'ľ' => 'ľ', 'Ń' => 'Ń', 'ń' => 'ń', 'Ņ' => 'Ņ', 'ņ' => 'ņ', 'Ň' => 'Ň', 'ň' => 'ň', 'Ō' => 'Ō', 'ō' => 'ō', 'Ŏ' => 'Ŏ', 'ŏ' => 'ŏ', 'Ő' => 'Ő', 'ő' => 'ő', 'Ŕ' => 'Ŕ', 'ŕ' => 'ŕ', 'Ŗ' => 'Ŗ', 'ŗ' => 'ŗ', 'Ř' => 'Ř', 'ř' => 'ř', 'Ś' => 'Ś', 'ś' => 'ś', 'Ŝ' => 'Ŝ', 'ŝ' => 'ŝ', 'Ş' => 'Ş', 'ş' => 'ş', 'Š' => 'Š', 'š' => 'š', 'Ţ' => 'Ţ', 'ţ' => 'ţ', 'Ť' => 'Ť', 'ť' => 'ť', 'Ũ' => 'Ũ', 'ũ' => 'ũ', 'Ū' => 'Ū', 'ū' => 'ū', 'Ŭ' => 'Ŭ', 'ŭ' => 'ŭ', 'Ů' => 'Ů', 'ů' => 'ů', 'Ű' => 'Ű', 'ű' => 'ű', 'Ų' => 'Ų', 'ų' => 'ų', 'Ŵ' => 'Ŵ', 'ŵ' => 'ŵ', 'Ŷ' => 'Ŷ', 'ŷ' => 'ŷ', 'Ÿ' => 'Ÿ', 'Ź' => 'Ź', 'ź' => 'ź', 'Ż' => 'Ż', 'ż' => 'ż', 'Ž' => 'Ž', 'ž' => 'ž', 'Ơ' => 'Ơ', 'ơ' => 'ơ', 'Ư' => 'Ư', 'ư' => 'ư', 'Ǎ' => 'Ǎ', 'ǎ' => 'ǎ', 'Ǐ' => 'Ǐ', 'ǐ' => 'ǐ', 'Ǒ' => 'Ǒ', 'ǒ' => 'ǒ', 'Ǔ' => 'Ǔ', 'ǔ' => 'ǔ', 'Ǖ' => 'Ǖ', 'ǖ' => 'ǖ', 'Ǘ' => 'Ǘ', 'ǘ' => 'ǘ', 'Ǚ' => 'Ǚ', 'ǚ' => 'ǚ', 'Ǜ' => 'Ǜ', 'ǜ' => 'ǜ', 'Ǟ' => 'Ǟ', 'ǟ' => 'ǟ', 'Ǡ' => 'Ǡ', 'ǡ' => 'ǡ', 'Ǣ' => 'Ǣ', 'ǣ' => 'ǣ', 'Ǧ' => 'Ǧ', 'ǧ' => 'ǧ', 'Ǩ' => 'Ǩ', 'ǩ' => 'ǩ', 'Ǫ' => 'Ǫ', 'ǫ' => 'ǫ', 'Ǭ' => 'Ǭ', 'ǭ' => 'ǭ', 'Ǯ' => 'Ǯ', 'ǯ' => 'ǯ', 'ǰ' => 'ǰ', 'Ǵ' => 'Ǵ', 'ǵ' => 'ǵ', 'Ǹ' => 'Ǹ', 'ǹ' => 'ǹ', 'Ǻ' => 'Ǻ', 'ǻ' => 'ǻ', 'Ǽ' => 'Ǽ', 'ǽ' => 'ǽ', 'Ǿ' => 'Ǿ', 'ǿ' => 'ǿ', 'Ȁ' => 'Ȁ', 'ȁ' => 'ȁ', 'Ȃ' => 'Ȃ', 'ȃ' => 'ȃ', 'Ȅ' => 'Ȅ', 'ȅ' => 'ȅ', 'Ȇ' => 'Ȇ', 'ȇ' => 'ȇ', 'Ȉ' => 'Ȉ', 'ȉ' => 'ȉ', 'Ȋ' => 'Ȋ', 'ȋ' => 'ȋ', 'Ȍ' => 'Ȍ', 'ȍ' => 'ȍ', 'Ȏ' => 'Ȏ', 'ȏ' => 'ȏ', 'Ȑ' => 'Ȑ', 'ȑ' => 'ȑ', 'Ȓ' => 'Ȓ', 'ȓ' => 'ȓ', 'Ȕ' => 'Ȕ', 'ȕ' => 'ȕ', 'Ȗ' => 'Ȗ', 'ȗ' => 'ȗ', 'Ș' => 'Ș', 'ș' => 'ș', 'Ț' => 'Ț', 'ț' => 'ț', 'Ȟ' => 'Ȟ', 'ȟ' => 'ȟ', 'Ȧ' => 'Ȧ', 'ȧ' => 'ȧ', 'Ȩ' => 'Ȩ', 'ȩ' => 'ȩ', 'Ȫ' => 'Ȫ', 'ȫ' => 'ȫ', 'Ȭ' => 'Ȭ', 'ȭ' => 'ȭ', 'Ȯ' => 'Ȯ', 'ȯ' => 'ȯ', 'Ȱ' => 'Ȱ', 'ȱ' => 'ȱ', 'Ȳ' => 'Ȳ', 'ȳ' => 'ȳ', '΅' => '΅', 'Ά' => 'Ά', 'Έ' => 'Έ', 'Ή' => 'Ή', 'Ί' => 'Ί', 'Ό' => 'Ό', 'Ύ' => 'Ύ', 'Ώ' => 'Ώ', 'ΐ' => 'ΐ', 'Ϊ' => 'Ϊ', 'Ϋ' => 'Ϋ', 'ά' => 'ά', 'έ' => 'έ', 'ή' => 'ή', 'ί' => 'ί', 'ΰ' => 'ΰ', 'ϊ' => 'ϊ', 'ϋ' => 'ϋ', 'ό' => 'ό', 'ύ' => 'ύ', 'ώ' => 'ώ', 'ϓ' => 'ϓ', 'ϔ' => 'ϔ', 'Ѐ' => 'Ѐ', 'Ё' => 'Ё', 'Ѓ' => 'Ѓ', 'Ї' => 'Ї', 'Ќ' => 'Ќ', 'Ѝ' => 'Ѝ', 'Ў' => 'Ў', 'Й' => 'Й', 'й' => 'й', 'ѐ' => 'ѐ', 'ё' => 'ё', 'ѓ' => 'ѓ', 'ї' => 'ї', 'ќ' => 'ќ', 'ѝ' => 'ѝ', 'ў' => 'ў', 'Ѷ' => 'Ѷ', 'ѷ' => 'ѷ', 'Ӂ' => 'Ӂ', 'ӂ' => 'ӂ', 'Ӑ' => 'Ӑ', 'ӑ' => 'ӑ', 'Ӓ' => 'Ӓ', 'ӓ' => 'ӓ', 'Ӗ' => 'Ӗ', 'ӗ' => 'ӗ', 'Ӛ' => 'Ӛ', 'ӛ' => 'ӛ', 'Ӝ' => 'Ӝ', 'ӝ' => 'ӝ', 'Ӟ' => 'Ӟ', 'ӟ' => 'ӟ', 'Ӣ' => 'Ӣ', 'ӣ' => 'ӣ', 'Ӥ' => 'Ӥ', 'ӥ' => 'ӥ', 'Ӧ' => 'Ӧ', 'ӧ' => 'ӧ', 'Ӫ' => 'Ӫ', 'ӫ' => 'ӫ', 'Ӭ' => 'Ӭ', 'ӭ' => 'ӭ', 'Ӯ' => 'Ӯ', 'ӯ' => 'ӯ', 'Ӱ' => 'Ӱ', 'ӱ' => 'ӱ', 'Ӳ' => 'Ӳ', 'ӳ' => 'ӳ', 'Ӵ' => 'Ӵ', 'ӵ' => 'ӵ', 'Ӹ' => 'Ӹ', 'ӹ' => 'ӹ', 'آ' => 'آ', 'أ' => 'أ', 'ؤ' => 'ؤ', 'إ' => 'إ', 'ئ' => 'ئ', 'ۀ' => 'ۀ', 'ۂ' => 'ۂ', 'ۓ' => 'ۓ', 'ऩ' => 'ऩ', 'ऱ' => 'ऱ', 'ऴ' => 'ऴ', 'ো' => 'ো', 'ৌ' => 'ৌ', 'ୈ' => 'ୈ', 'ୋ' => 'ୋ', 'ୌ' => 'ୌ', 'ஔ' => 'ஔ', 'ொ' => 'ொ', 'ோ' => 'ோ', 'ௌ' => 'ௌ', 'ై' => 'ై', 'ೀ' => 'ೀ', 'ೇ' => 'ೇ', 'ೈ' => 'ೈ', 'ೊ' => 'ೊ', 'ೋ' => 'ೋ', 'ൊ' => 'ൊ', 'ോ' => 'ോ', 'ൌ' => 'ൌ', 'ේ' => 'ේ', 'ො' => 'ො', 'ෝ' => 'ෝ', 'ෞ' => 'ෞ', 'ဦ' => 'ဦ', 'ᬆ' => 'ᬆ', 'ᬈ' => 'ᬈ', 'ᬊ' => 'ᬊ', 'ᬌ' => 'ᬌ', 'ᬎ' => 'ᬎ', 'ᬒ' => 'ᬒ', 'ᬻ' => 'ᬻ', 'ᬽ' => 'ᬽ', 'ᭀ' => 'ᭀ', 'ᭁ' => 'ᭁ', 'ᭃ' => 'ᭃ', 'Ḁ' => 'Ḁ', 'ḁ' => 'ḁ', 'Ḃ' => 'Ḃ', 'ḃ' => 'ḃ', 'Ḅ' => 'Ḅ', 'ḅ' => 'ḅ', 'Ḇ' => 'Ḇ', 'ḇ' => 'ḇ', 'Ḉ' => 'Ḉ', 'ḉ' => 'ḉ', 'Ḋ' => 'Ḋ', 'ḋ' => 'ḋ', 'Ḍ' => 'Ḍ', 'ḍ' => 'ḍ', 'Ḏ' => 'Ḏ', 'ḏ' => 'ḏ', 'Ḑ' => 'Ḑ', 'ḑ' => 'ḑ', 'Ḓ' => 'Ḓ', 'ḓ' => 'ḓ', 'Ḕ' => 'Ḕ', 'ḕ' => 'ḕ', 'Ḗ' => 'Ḗ', 'ḗ' => 'ḗ', 'Ḙ' => 'Ḙ', 'ḙ' => 'ḙ', 'Ḛ' => 'Ḛ', 'ḛ' => 'ḛ', 'Ḝ' => 'Ḝ', 'ḝ' => 'ḝ', 'Ḟ' => 'Ḟ', 'ḟ' => 'ḟ', 'Ḡ' => 'Ḡ', 'ḡ' => 'ḡ', 'Ḣ' => 'Ḣ', 'ḣ' => 'ḣ', 'Ḥ' => 'Ḥ', 'ḥ' => 'ḥ', 'Ḧ' => 'Ḧ', 'ḧ' => 'ḧ', 'Ḩ' => 'Ḩ', 'ḩ' => 'ḩ', 'Ḫ' => 'Ḫ', 'ḫ' => 'ḫ', 'Ḭ' => 'Ḭ', 'ḭ' => 'ḭ', 'Ḯ' => 'Ḯ', 'ḯ' => 'ḯ', 'Ḱ' => 'Ḱ', 'ḱ' => 'ḱ', 'Ḳ' => 'Ḳ', 'ḳ' => 'ḳ', 'Ḵ' => 'Ḵ', 'ḵ' => 'ḵ', 'Ḷ' => 'Ḷ', 'ḷ' => 'ḷ', 'Ḹ' => 'Ḹ', 'ḹ' => 'ḹ', 'Ḻ' => 'Ḻ', 'ḻ' => 'ḻ', 'Ḽ' => 'Ḽ', 'ḽ' => 'ḽ', 'Ḿ' => 'Ḿ', 'ḿ' => 'ḿ', 'Ṁ' => 'Ṁ', 'ṁ' => 'ṁ', 'Ṃ' => 'Ṃ', 'ṃ' => 'ṃ', 'Ṅ' => 'Ṅ', 'ṅ' => 'ṅ', 'Ṇ' => 'Ṇ', 'ṇ' => 'ṇ', 'Ṉ' => 'Ṉ', 'ṉ' => 'ṉ', 'Ṋ' => 'Ṋ', 'ṋ' => 'ṋ', 'Ṍ' => 'Ṍ', 'ṍ' => 'ṍ', 'Ṏ' => 'Ṏ', 'ṏ' => 'ṏ', 'Ṑ' => 'Ṑ', 'ṑ' => 'ṑ', 'Ṓ' => 'Ṓ', 'ṓ' => 'ṓ', 'Ṕ' => 'Ṕ', 'ṕ' => 'ṕ', 'Ṗ' => 'Ṗ', 'ṗ' => 'ṗ', 'Ṙ' => 'Ṙ', 'ṙ' => 'ṙ', 'Ṛ' => 'Ṛ', 'ṛ' => 'ṛ', 'Ṝ' => 'Ṝ', 'ṝ' => 'ṝ', 'Ṟ' => 'Ṟ', 'ṟ' => 'ṟ', 'Ṡ' => 'Ṡ', 'ṡ' => 'ṡ', 'Ṣ' => 'Ṣ', 'ṣ' => 'ṣ', 'Ṥ' => 'Ṥ', 'ṥ' => 'ṥ', 'Ṧ' => 'Ṧ', 'ṧ' => 'ṧ', 'Ṩ' => 'Ṩ', 'ṩ' => 'ṩ', 'Ṫ' => 'Ṫ', 'ṫ' => 'ṫ', 'Ṭ' => 'Ṭ', 'ṭ' => 'ṭ', 'Ṯ' => 'Ṯ', 'ṯ' => 'ṯ', 'Ṱ' => 'Ṱ', 'ṱ' => 'ṱ', 'Ṳ' => 'Ṳ', 'ṳ' => 'ṳ', 'Ṵ' => 'Ṵ', 'ṵ' => 'ṵ', 'Ṷ' => 'Ṷ', 'ṷ' => 'ṷ', 'Ṹ' => 'Ṹ', 'ṹ' => 'ṹ', 'Ṻ' => 'Ṻ', 'ṻ' => 'ṻ', 'Ṽ' => 'Ṽ', 'ṽ' => 'ṽ', 'Ṿ' => 'Ṿ', 'ṿ' => 'ṿ', 'Ẁ' => 'Ẁ', 'ẁ' => 'ẁ', 'Ẃ' => 'Ẃ', 'ẃ' => 'ẃ', 'Ẅ' => 'Ẅ', 'ẅ' => 'ẅ', 'Ẇ' => 'Ẇ', 'ẇ' => 'ẇ', 'Ẉ' => 'Ẉ', 'ẉ' => 'ẉ', 'Ẋ' => 'Ẋ', 'ẋ' => 'ẋ', 'Ẍ' => 'Ẍ', 'ẍ' => 'ẍ', 'Ẏ' => 'Ẏ', 'ẏ' => 'ẏ', 'Ẑ' => 'Ẑ', 'ẑ' => 'ẑ', 'Ẓ' => 'Ẓ', 'ẓ' => 'ẓ', 'Ẕ' => 'Ẕ', 'ẕ' => 'ẕ', 'ẖ' => 'ẖ', 'ẗ' => 'ẗ', 'ẘ' => 'ẘ', 'ẙ' => 'ẙ', 'ẛ' => 'ẛ', 'Ạ' => 'Ạ', 'ạ' => 'ạ', 'Ả' => 'Ả', 'ả' => 'ả', 'Ấ' => 'Ấ', 'ấ' => 'ấ', 'Ầ' => 'Ầ', 'ầ' => 'ầ', 'Ẩ' => 'Ẩ', 'ẩ' => 'ẩ', 'Ẫ' => 'Ẫ', 'ẫ' => 'ẫ', 'Ậ' => 'Ậ', 'ậ' => 'ậ', 'Ắ' => 'Ắ', 'ắ' => 'ắ', 'Ằ' => 'Ằ', 'ằ' => 'ằ', 'Ẳ' => 'Ẳ', 'ẳ' => 'ẳ', 'Ẵ' => 'Ẵ', 'ẵ' => 'ẵ', 'Ặ' => 'Ặ', 'ặ' => 'ặ', 'Ẹ' => 'Ẹ', 'ẹ' => 'ẹ', 'Ẻ' => 'Ẻ', 'ẻ' => 'ẻ', 'Ẽ' => 'Ẽ', 'ẽ' => 'ẽ', 'Ế' => 'Ế', 'ế' => 'ế', 'Ề' => 'Ề', 'ề' => 'ề', 'Ể' => 'Ể', 'ể' => 'ể', 'Ễ' => 'Ễ', 'ễ' => 'ễ', 'Ệ' => 'Ệ', 'ệ' => 'ệ', 'Ỉ' => 'Ỉ', 'ỉ' => 'ỉ', 'Ị' => 'Ị', 'ị' => 'ị', 'Ọ' => 'Ọ', 'ọ' => 'ọ', 'Ỏ' => 'Ỏ', 'ỏ' => 'ỏ', 'Ố' => 'Ố', 'ố' => 'ố', 'Ồ' => 'Ồ', 'ồ' => 'ồ', 'Ổ' => 'Ổ', 'ổ' => 'ổ', 'Ỗ' => 'Ỗ', 'ỗ' => 'ỗ', 'Ộ' => 'Ộ', 'ộ' => 'ộ', 'Ớ' => 'Ớ', 'ớ' => 'ớ', 'Ờ' => 'Ờ', 'ờ' => 'ờ', 'Ở' => 'Ở', 'ở' => 'ở', 'Ỡ' => 'Ỡ', 'ỡ' => 'ỡ', 'Ợ' => 'Ợ', 'ợ' => 'ợ', 'Ụ' => 'Ụ', 'ụ' => 'ụ', 'Ủ' => 'Ủ', 'ủ' => 'ủ', 'Ứ' => 'Ứ', 'ứ' => 'ứ', 'Ừ' => 'Ừ', 'ừ' => 'ừ', 'Ử' => 'Ử', 'ử' => 'ử', 'Ữ' => 'Ữ', 'ữ' => 'ữ', 'Ự' => 'Ự', 'ự' => 'ự', 'Ỳ' => 'Ỳ', 'ỳ' => 'ỳ', 'Ỵ' => 'Ỵ', 'ỵ' => 'ỵ', 'Ỷ' => 'Ỷ', 'ỷ' => 'ỷ', 'Ỹ' => 'Ỹ', 'ỹ' => 'ỹ', 'ἀ' => 'ἀ', 'ἁ' => 'ἁ', 'ἂ' => 'ἂ', 'ἃ' => 'ἃ', 'ἄ' => 'ἄ', 'ἅ' => 'ἅ', 'ἆ' => 'ἆ', 'ἇ' => 'ἇ', 'Ἀ' => 'Ἀ', 'Ἁ' => 'Ἁ', 'Ἂ' => 'Ἂ', 'Ἃ' => 'Ἃ', 'Ἄ' => 'Ἄ', 'Ἅ' => 'Ἅ', 'Ἆ' => 'Ἆ', 'Ἇ' => 'Ἇ', 'ἐ' => 'ἐ', 'ἑ' => 'ἑ', 'ἒ' => 'ἒ', 'ἓ' => 'ἓ', 'ἔ' => 'ἔ', 'ἕ' => 'ἕ', 'Ἐ' => 'Ἐ', 'Ἑ' => 'Ἑ', 'Ἒ' => 'Ἒ', 'Ἓ' => 'Ἓ', 'Ἔ' => 'Ἔ', 'Ἕ' => 'Ἕ', 'ἠ' => 'ἠ', 'ἡ' => 'ἡ', 'ἢ' => 'ἢ', 'ἣ' => 'ἣ', 'ἤ' => 'ἤ', 'ἥ' => 'ἥ', 'ἦ' => 'ἦ', 'ἧ' => 'ἧ', 'Ἠ' => 'Ἠ', 'Ἡ' => 'Ἡ', 'Ἢ' => 'Ἢ', 'Ἣ' => 'Ἣ', 'Ἤ' => 'Ἤ', 'Ἥ' => 'Ἥ', 'Ἦ' => 'Ἦ', 'Ἧ' => 'Ἧ', 'ἰ' => 'ἰ', 'ἱ' => 'ἱ', 'ἲ' => 'ἲ', 'ἳ' => 'ἳ', 'ἴ' => 'ἴ', 'ἵ' => 'ἵ', 'ἶ' => 'ἶ', 'ἷ' => 'ἷ', 'Ἰ' => 'Ἰ', 'Ἱ' => 'Ἱ', 'Ἲ' => 'Ἲ', 'Ἳ' => 'Ἳ', 'Ἴ' => 'Ἴ', 'Ἵ' => 'Ἵ', 'Ἶ' => 'Ἶ', 'Ἷ' => 'Ἷ', 'ὀ' => 'ὀ', 'ὁ' => 'ὁ', 'ὂ' => 'ὂ', 'ὃ' => 'ὃ', 'ὄ' => 'ὄ', 'ὅ' => 'ὅ', 'Ὀ' => 'Ὀ', 'Ὁ' => 'Ὁ', 'Ὂ' => 'Ὂ', 'Ὃ' => 'Ὃ', 'Ὄ' => 'Ὄ', 'Ὅ' => 'Ὅ', 'ὐ' => 'ὐ', 'ὑ' => 'ὑ', 'ὒ' => 'ὒ', 'ὓ' => 'ὓ', 'ὔ' => 'ὔ', 'ὕ' => 'ὕ', 'ὖ' => 'ὖ', 'ὗ' => 'ὗ', 'Ὑ' => 'Ὑ', 'Ὓ' => 'Ὓ', 'Ὕ' => 'Ὕ', 'Ὗ' => 'Ὗ', 'ὠ' => 'ὠ', 'ὡ' => 'ὡ', 'ὢ' => 'ὢ', 'ὣ' => 'ὣ', 'ὤ' => 'ὤ', 'ὥ' => 'ὥ', 'ὦ' => 'ὦ', 'ὧ' => 'ὧ', 'Ὠ' => 'Ὠ', 'Ὡ' => 'Ὡ', 'Ὢ' => 'Ὢ', 'Ὣ' => 'Ὣ', 'Ὤ' => 'Ὤ', 'Ὥ' => 'Ὥ', 'Ὦ' => 'Ὦ', 'Ὧ' => 'Ὧ', 'ὰ' => 'ὰ', 'ὲ' => 'ὲ', 'ὴ' => 'ὴ', 'ὶ' => 'ὶ', 'ὸ' => 'ὸ', 'ὺ' => 'ὺ', 'ὼ' => 'ὼ', 'ᾀ' => 'ᾀ', 'ᾁ' => 'ᾁ', 'ᾂ' => 'ᾂ', 'ᾃ' => 'ᾃ', 'ᾄ' => 'ᾄ', 'ᾅ' => 'ᾅ', 'ᾆ' => 'ᾆ', 'ᾇ' => 'ᾇ', 'ᾈ' => 'ᾈ', 'ᾉ' => 'ᾉ', 'ᾊ' => 'ᾊ', 'ᾋ' => 'ᾋ', 'ᾌ' => 'ᾌ', 'ᾍ' => 'ᾍ', 'ᾎ' => 'ᾎ', 'ᾏ' => 'ᾏ', 'ᾐ' => 'ᾐ', 'ᾑ' => 'ᾑ', 'ᾒ' => 'ᾒ', 'ᾓ' => 'ᾓ', 'ᾔ' => 'ᾔ', 'ᾕ' => 'ᾕ', 'ᾖ' => 'ᾖ', 'ᾗ' => 'ᾗ', 'ᾘ' => 'ᾘ', 'ᾙ' => 'ᾙ', 'ᾚ' => 'ᾚ', 'ᾛ' => 'ᾛ', 'ᾜ' => 'ᾜ', 'ᾝ' => 'ᾝ', 'ᾞ' => 'ᾞ', 'ᾟ' => 'ᾟ', 'ᾠ' => 'ᾠ', 'ᾡ' => 'ᾡ', 'ᾢ' => 'ᾢ', 'ᾣ' => 'ᾣ', 'ᾤ' => 'ᾤ', 'ᾥ' => 'ᾥ', 'ᾦ' => 'ᾦ', 'ᾧ' => 'ᾧ', 'ᾨ' => 'ᾨ', 'ᾩ' => 'ᾩ', 'ᾪ' => 'ᾪ', 'ᾫ' => 'ᾫ', 'ᾬ' => 'ᾬ', 'ᾭ' => 'ᾭ', 'ᾮ' => 'ᾮ', 'ᾯ' => 'ᾯ', 'ᾰ' => 'ᾰ', 'ᾱ' => 'ᾱ', 'ᾲ' => 'ᾲ', 'ᾳ' => 'ᾳ', 'ᾴ' => 'ᾴ', 'ᾶ' => 'ᾶ', 'ᾷ' => 'ᾷ', 'Ᾰ' => 'Ᾰ', 'Ᾱ' => 'Ᾱ', 'Ὰ' => 'Ὰ', 'ᾼ' => 'ᾼ', '῁' => '῁', 'ῂ' => 'ῂ', 'ῃ' => 'ῃ', 'ῄ' => 'ῄ', 'ῆ' => 'ῆ', 'ῇ' => 'ῇ', 'Ὲ' => 'Ὲ', 'Ὴ' => 'Ὴ', 'ῌ' => 'ῌ', '῍' => '῍', '῎' => '῎', '῏' => '῏', 'ῐ' => 'ῐ', 'ῑ' => 'ῑ', 'ῒ' => 'ῒ', 'ῖ' => 'ῖ', 'ῗ' => 'ῗ', 'Ῐ' => 'Ῐ', 'Ῑ' => 'Ῑ', 'Ὶ' => 'Ὶ', '῝' => '῝', '῞' => '῞', '῟' => '῟', 'ῠ' => 'ῠ', 'ῡ' => 'ῡ', 'ῢ' => 'ῢ', 'ῤ' => 'ῤ', 'ῥ' => 'ῥ', 'ῦ' => 'ῦ', 'ῧ' => 'ῧ', 'Ῠ' => 'Ῠ', 'Ῡ' => 'Ῡ', 'Ὺ' => 'Ὺ', 'Ῥ' => 'Ῥ', '῭' => '῭', 'ῲ' => 'ῲ', 'ῳ' => 'ῳ', 'ῴ' => 'ῴ', 'ῶ' => 'ῶ', 'ῷ' => 'ῷ', 'Ὸ' => 'Ὸ', 'Ὼ' => 'Ὼ', 'ῼ' => 'ῼ', '↚' => '↚', '↛' => '↛', '↮' => '↮', '⇍' => '⇍', '⇎' => '⇎', '⇏' => '⇏', '∄' => '∄', '∉' => '∉', '∌' => '∌', '∤' => '∤', '∦' => '∦', '≁' => '≁', '≄' => '≄', '≇' => '≇', '≉' => '≉', '≠' => '≠', '≢' => '≢', '≭' => '≭', '≮' => '≮', '≯' => '≯', '≰' => '≰', '≱' => '≱', '≴' => '≴', '≵' => '≵', '≸' => '≸', '≹' => '≹', '⊀' => '⊀', '⊁' => '⊁', '⊄' => '⊄', '⊅' => '⊅', '⊈' => '⊈', '⊉' => '⊉', '⊬' => '⊬', '⊭' => '⊭', '⊮' => '⊮', '⊯' => '⊯', '⋠' => '⋠', '⋡' => '⋡', '⋢' => '⋢', '⋣' => '⋣', '⋪' => '⋪', '⋫' => '⋫', '⋬' => '⋬', '⋭' => '⋭', 'が' => 'が', 'ぎ' => 'ぎ', 'ぐ' => 'ぐ', 'げ' => 'げ', 'ご' => 'ご', 'ざ' => 'ざ', 'じ' => 'じ', 'ず' => 'ず', 'ぜ' => 'ぜ', 'ぞ' => 'ぞ', 'だ' => 'だ', 'ぢ' => 'ぢ', 'づ' => 'づ', 'で' => 'で', 'ど' => 'ど', 'ば' => 'ば', 'ぱ' => 'ぱ', 'び' => 'び', 'ぴ' => 'ぴ', 'ぶ' => 'ぶ', 'ぷ' => 'ぷ', 'べ' => 'べ', 'ぺ' => 'ぺ', 'ぼ' => 'ぼ', 'ぽ' => 'ぽ', 'ゔ' => 'ゔ', 'ゞ' => 'ゞ', 'ガ' => 'ガ', 'ギ' => 'ギ', 'グ' => 'グ', 'ゲ' => 'ゲ', 'ゴ' => 'ゴ', 'ザ' => 'ザ', 'ジ' => 'ジ', 'ズ' => 'ズ', 'ゼ' => 'ゼ', 'ゾ' => 'ゾ', 'ダ' => 'ダ', 'ヂ' => 'ヂ', 'ヅ' => 'ヅ', 'デ' => 'デ', 'ド' => 'ド', 'バ' => 'バ', 'パ' => 'パ', 'ビ' => 'ビ', 'ピ' => 'ピ', 'ブ' => 'ブ', 'プ' => 'プ', 'ベ' => 'ベ', 'ペ' => 'ペ', 'ボ' => 'ボ', 'ポ' => 'ポ', 'ヴ' => 'ヴ', 'ヷ' => 'ヷ', 'ヸ' => 'ヸ', 'ヹ' => 'ヹ', 'ヺ' => 'ヺ', 'ヾ' => 'ヾ', '𑂚' => '𑂚', '𑂜' => '𑂜', '𑂫' => '𑂫', '𑄮' => '𑄮', '𑄯' => '𑄯', '𑍋' => '𑍋', '𑍌' => '𑍌', '𑒻' => '𑒻', '𑒼' => '𑒼', '𑒾' => '𑒾', '𑖺' => '𑖺', '𑖻' => '𑖻', '𑤸' => '𑤸');
<?php

namespace _ContaoManager;

return array(' ' => ' ', '¨' => ' ̈', 'ª' => 'a', '¯' => ' ̄', '²' => '2', '³' => '3', '´' => ' ́', 'µ' => 'μ', '¸' => ' ̧', '¹' => '1', 'º' => 'o', '¼' => '1⁄4', '½' => '1⁄2', '¾' => '3⁄4', 'Ĳ' => 'IJ', 'ĳ' => 'ij', 'Ŀ' => 'L·', 'ŀ' => 'l·', 'ŉ' => 'ʼn', 'ſ' => 's', 'Ǆ' => 'DŽ', 'ǅ' => 'Dž', 'ǆ' => 'dž', 'Ǉ' => 'LJ', 'ǈ' => 'Lj', 'ǉ' => 'lj', 'Ǌ' => 'NJ', 'ǋ' => 'Nj', 'ǌ' => 'nj', 'Ǳ' => 'DZ', 'ǲ' => 'Dz', 'ǳ' => 'dz', 'ʰ' => 'h', 'ʱ' => 'ɦ', 'ʲ' => 'j', 'ʳ' => 'r', 'ʴ' => 'ɹ', 'ʵ' => 'ɻ', 'ʶ' => 'ʁ', 'ʷ' => 'w', 'ʸ' => 'y', '˘' => ' ̆', '˙' => ' ̇', '˚' => ' ̊', '˛' => ' ̨', '˜' => ' ̃', '˝' => ' ̋', 'ˠ' => 'ɣ', 'ˡ' => 'l', 'ˢ' => 's', 'ˣ' => 'x', 'ˤ' => 'ʕ', 'ͺ' => ' ͅ', '΄' => ' ́', '΅' => ' ̈́', 'ϐ' => 'β', 'ϑ' => 'θ', 'ϒ' => 'Υ', 'ϓ' => 'Ύ', 'ϔ' => 'Ϋ', 'ϕ' => 'φ', 'ϖ' => 'π', 'ϰ' => 'κ', 'ϱ' => 'ρ', 'ϲ' => 'ς', 'ϴ' => 'Θ', 'ϵ' => 'ε', 'Ϲ' => 'Σ', 'և' => 'եւ', 'ٵ' => 'اٴ', 'ٶ' => 'وٴ', 'ٷ' => 'ۇٴ', 'ٸ' => 'يٴ', 'ำ' => 'ํา', 'ຳ' => 'ໍາ', 'ໜ' => 'ຫນ', 'ໝ' => 'ຫມ', '༌' => '་', 'ཷ' => 'ྲཱྀ', 'ཹ' => 'ླཱྀ', 'ჼ' => 'ნ', 'ᴬ' => 'A', 'ᴭ' => 'Æ', 'ᴮ' => 'B', 'ᴰ' => 'D', 'ᴱ' => 'E', 'ᴲ' => 'Ǝ', 'ᴳ' => 'G', 'ᴴ' => 'H', 'ᴵ' => 'I', 'ᴶ' => 'J', 'ᴷ' => 'K', 'ᴸ' => 'L', 'ᴹ' => 'M', 'ᴺ' => 'N', 'ᴼ' => 'O', 'ᴽ' => 'Ȣ', 'ᴾ' => 'P', 'ᴿ' => 'R', 'ᵀ' => 'T', 'ᵁ' => 'U', 'ᵂ' => 'W', 'ᵃ' => 'a', 'ᵄ' => 'ɐ', 'ᵅ' => 'ɑ', 'ᵆ' => 'ᴂ', 'ᵇ' => 'b', 'ᵈ' => 'd', 'ᵉ' => 'e', 'ᵊ' => 'ə', 'ᵋ' => 'ɛ', 'ᵌ' => 'ɜ', 'ᵍ' => 'g', 'ᵏ' => 'k', 'ᵐ' => 'm', 'ᵑ' => 'ŋ', 'ᵒ' => 'o', 'ᵓ' => 'ɔ', 'ᵔ' => 'ᴖ', 'ᵕ' => 'ᴗ', 'ᵖ' => 'p', 'ᵗ' => 't', 'ᵘ' => 'u', 'ᵙ' => 'ᴝ', 'ᵚ' => 'ɯ', 'ᵛ' => 'v', 'ᵜ' => 'ᴥ', 'ᵝ' => 'β', 'ᵞ' => 'γ', 'ᵟ' => 'δ', 'ᵠ' => 'φ', 'ᵡ' => 'χ', 'ᵢ' => 'i', 'ᵣ' => 'r', 'ᵤ' => 'u', 'ᵥ' => 'v', 'ᵦ' => 'β', 'ᵧ' => 'γ', 'ᵨ' => 'ρ', 'ᵩ' => 'φ', 'ᵪ' => 'χ', 'ᵸ' => 'н', 'ᶛ' => 'ɒ', 'ᶜ' => 'c', 'ᶝ' => 'ɕ', 'ᶞ' => 'ð', 'ᶟ' => 'ɜ', 'ᶠ' => 'f', 'ᶡ' => 'ɟ', 'ᶢ' => 'ɡ', 'ᶣ' => 'ɥ', 'ᶤ' => 'ɨ', 'ᶥ' => 'ɩ', 'ᶦ' => 'ɪ', 'ᶧ' => 'ᵻ', 'ᶨ' => 'ʝ', 'ᶩ' => 'ɭ', 'ᶪ' => 'ᶅ', 'ᶫ' => 'ʟ', 'ᶬ' => 'ɱ', 'ᶭ' => 'ɰ', 'ᶮ' => 'ɲ', 'ᶯ' => 'ɳ', 'ᶰ' => 'ɴ', 'ᶱ' => 'ɵ', 'ᶲ' => 'ɸ', 'ᶳ' => 'ʂ', 'ᶴ' => 'ʃ', 'ᶵ' => 'ƫ', 'ᶶ' => 'ʉ', 'ᶷ' => 'ʊ', 'ᶸ' => 'ᴜ', 'ᶹ' => 'ʋ', 'ᶺ' => 'ʌ', 'ᶻ' => 'z', 'ᶼ' => 'ʐ', 'ᶽ' => 'ʑ', 'ᶾ' => 'ʒ', 'ᶿ' => 'θ', 'ẚ' => 'aʾ', 'ẛ' => 'ṡ', '᾽' => ' ̓', '᾿' => ' ̓', '῀' => ' ͂', '῁' => ' ̈͂', '῍' => ' ̓̀', '῎' => ' ̓́', '῏' => ' ̓͂', '῝' => ' ̔̀', '῞' => ' ̔́', '῟' => ' ̔͂', '῭' => ' ̈̀', '΅' => ' ̈́', '´' => ' ́', '῾' => ' ̔', ' ' => ' ', ' ' => ' ', ' ' => ' ', ' ' => ' ', ' ' => ' ', ' ' => ' ', ' ' => ' ', ' ' => ' ', ' ' => ' ', ' ' => ' ', ' ' => ' ', '‑' => '‐', '‗' => ' ̳', '․' => '.', '‥' => '..', '…' => '...', ' ' => ' ', '″' => '′′', '‴' => '′′′', '‶' => '‵‵', '‷' => '‵‵‵', '‼' => '!!', '‾' => ' ̅', '⁇' => '??', '⁈' => '?!', '⁉' => '!?', '⁗' => '′′′′', ' ' => ' ', '⁰' => '0', 'ⁱ' => 'i', '⁴' => '4', '⁵' => '5', '⁶' => '6', '⁷' => '7', '⁸' => '8', '⁹' => '9', '⁺' => '+', '⁻' => '−', '⁼' => '=', '⁽' => '(', '⁾' => ')', 'ⁿ' => 'n', '₀' => '0', '₁' => '1', '₂' => '2', '₃' => '3', '₄' => '4', '₅' => '5', '₆' => '6', '₇' => '7', '₈' => '8', '₉' => '9', '₊' => '+', '₋' => '−', '₌' => '=', '₍' => '(', '₎' => ')', 'ₐ' => 'a', 'ₑ' => 'e', 'ₒ' => 'o', 'ₓ' => 'x', 'ₔ' => 'ə', 'ₕ' => 'h', 'ₖ' => 'k', 'ₗ' => 'l', 'ₘ' => 'm', 'ₙ' => 'n', 'ₚ' => 'p', 'ₛ' => 's', 'ₜ' => 't', '₨' => 'Rs', '℀' => 'a/c', '℁' => 'a/s', 'ℂ' => 'C', '℃' => '°C', '℅' => 'c/o', '℆' => 'c/u', 'ℇ' => 'Ɛ', '℉' => '°F', 'ℊ' => 'g', 'ℋ' => 'H', 'ℌ' => 'H', 'ℍ' => 'H', 'ℎ' => 'h', 'ℏ' => 'ħ', 'ℐ' => 'I', 'ℑ' => 'I', 'ℒ' => 'L', 'ℓ' => 'l', 'ℕ' => 'N', '№' => 'No', 'ℙ' => 'P', 'ℚ' => 'Q', 'ℛ' => 'R', 'ℜ' => 'R', 'ℝ' => 'R', '℠' => 'SM', '℡' => 'TEL', '™' => 'TM', 'ℤ' => 'Z', 'ℨ' => 'Z', 'ℬ' => 'B', 'ℭ' => 'C', 'ℯ' => 'e', 'ℰ' => 'E', 'ℱ' => 'F', 'ℳ' => 'M', 'ℴ' => 'o', 'ℵ' => 'א', 'ℶ' => 'ב', 'ℷ' => 'ג', 'ℸ' => 'ד', 'ℹ' => 'i', '℻' => 'FAX', 'ℼ' => 'π', 'ℽ' => 'γ', 'ℾ' => 'Γ', 'ℿ' => 'Π', '⅀' => '∑', 'ⅅ' => 'D', 'ⅆ' => 'd', 'ⅇ' => 'e', 'ⅈ' => 'i', 'ⅉ' => 'j', '⅐' => '1⁄7', '⅑' => '1⁄9', '⅒' => '1⁄10', '⅓' => '1⁄3', '⅔' => '2⁄3', '⅕' => '1⁄5', '⅖' => '2⁄5', '⅗' => '3⁄5', '⅘' => '4⁄5', '⅙' => '1⁄6', '⅚' => '5⁄6', '⅛' => '1⁄8', '⅜' => '3⁄8', '⅝' => '5⁄8', '⅞' => '7⁄8', '⅟' => '1⁄', 'Ⅰ' => 'I', 'Ⅱ' => 'II', 'Ⅲ' => 'III', 'Ⅳ' => 'IV', 'Ⅴ' => 'V', 'Ⅵ' => 'VI', 'Ⅶ' => 'VII', 'Ⅷ' => 'VIII', 'Ⅸ' => 'IX', 'Ⅹ' => 'X', 'Ⅺ' => 'XI', 'Ⅻ' => 'XII', 'Ⅼ' => 'L', 'Ⅽ' => 'C', 'Ⅾ' => 'D', 'Ⅿ' => 'M', 'ⅰ' => 'i', 'ⅱ' => 'ii', 'ⅲ' => 'iii', 'ⅳ' => 'iv', 'ⅴ' => 'v', 'ⅵ' => 'vi', 'ⅶ' => 'vii', 'ⅷ' => 'viii', 'ⅸ' => 'ix', 'ⅹ' => 'x', 'ⅺ' => 'xi', 'ⅻ' => 'xii', 'ⅼ' => 'l', 'ⅽ' => 'c', 'ⅾ' => 'd', 'ⅿ' => 'm', '↉' => '0⁄3', '∬' => '∫∫', '∭' => '∫∫∫', '∯' => '∮∮', '∰' => '∮∮∮', '①' => '1', '②' => '2', '③' => '3', '④' => '4', '⑤' => '5', '⑥' => '6', '⑦' => '7', '⑧' => '8', '⑨' => '9', '⑩' => '10', '⑪' => '11', '⑫' => '12', '⑬' => '13', '⑭' => '14', '⑮' => '15', '⑯' => '16', '⑰' => '17', '⑱' => '18', '⑲' => '19', '⑳' => '20', '⑴' => '(1)', '⑵' => '(2)', '⑶' => '(3)', '⑷' => '(4)', '⑸' => '(5)', '⑹' => '(6)', '⑺' => '(7)', '⑻' => '(8)', '⑼' => '(9)', '⑽' => '(10)', '⑾' => '(11)', '⑿' => '(12)', '⒀' => '(13)', '⒁' => '(14)', '⒂' => '(15)', '⒃' => '(16)', '⒄' => '(17)', '⒅' => '(18)', '⒆' => '(19)', '⒇' => '(20)', '⒈' => '1.', '⒉' => '2.', '⒊' => '3.', '⒋' => '4.', '⒌' => '5.', '⒍' => '6.', '⒎' => '7.', '⒏' => '8.', '⒐' => '9.', '⒑' => '10.', '⒒' => '11.', '⒓' => '12.', '⒔' => '13.', '⒕' => '14.', '⒖' => '15.', '⒗' => '16.', '⒘' => '17.', '⒙' => '18.', '⒚' => '19.', '⒛' => '20.', '⒜' => '(a)', '⒝' => '(b)', '⒞' => '(c)', '⒟' => '(d)', '⒠' => '(e)', '⒡' => '(f)', '⒢' => '(g)', '⒣' => '(h)', '⒤' => '(i)', '⒥' => '(j)', '⒦' => '(k)', '⒧' => '(l)', '⒨' => '(m)', '⒩' => '(n)', '⒪' => '(o)', '⒫' => '(p)', '⒬' => '(q)', '⒭' => '(r)', '⒮' => '(s)', '⒯' => '(t)', '⒰' => '(u)', '⒱' => '(v)', '⒲' => '(w)', '⒳' => '(x)', '⒴' => '(y)', '⒵' => '(z)', 'Ⓐ' => 'A', 'Ⓑ' => 'B', 'Ⓒ' => 'C', 'Ⓓ' => 'D', 'Ⓔ' => 'E', 'Ⓕ' => 'F', 'Ⓖ' => 'G', 'Ⓗ' => 'H', 'Ⓘ' => 'I', 'Ⓙ' => 'J', 'Ⓚ' => 'K', 'Ⓛ' => 'L', 'Ⓜ' => 'M', 'Ⓝ' => 'N', 'Ⓞ' => 'O', 'Ⓟ' => 'P', 'Ⓠ' => 'Q', 'Ⓡ' => 'R', 'Ⓢ' => 'S', 'Ⓣ' => 'T', 'Ⓤ' => 'U', 'Ⓥ' => 'V', 'Ⓦ' => 'W', 'Ⓧ' => 'X', 'Ⓨ' => 'Y', 'Ⓩ' => 'Z', 'ⓐ' => 'a', 'ⓑ' => 'b', 'ⓒ' => 'c', 'ⓓ' => 'd', 'ⓔ' => 'e', 'ⓕ' => 'f', 'ⓖ' => 'g', 'ⓗ' => 'h', 'ⓘ' => 'i', 'ⓙ' => 'j', 'ⓚ' => 'k', 'ⓛ' => 'l', 'ⓜ' => 'm', 'ⓝ' => 'n', 'ⓞ' => 'o', 'ⓟ' => 'p', 'ⓠ' => 'q', 'ⓡ' => 'r', 'ⓢ' => 's', 'ⓣ' => 't', 'ⓤ' => 'u', 'ⓥ' => 'v', 'ⓦ' => 'w', 'ⓧ' => 'x', 'ⓨ' => 'y', 'ⓩ' => 'z', '⓪' => '0', '⨌' => '∫∫∫∫', '⩴' => '::=', '⩵' => '==', '⩶' => '===', 'ⱼ' => 'j', 'ⱽ' => 'V', 'ⵯ' => 'ⵡ', '⺟' => '母', '⻳' => '龟', '⼀' => '一', '⼁' => '丨', '⼂' => '丶', '⼃' => '丿', '⼄' => '乙', '⼅' => '亅', '⼆' => '二', '⼇' => '亠', '⼈' => '人', '⼉' => '儿', '⼊' => '入', '⼋' => '八', '⼌' => '冂', '⼍' => '冖', '⼎' => '冫', '⼏' => '几', '⼐' => '凵', '⼑' => '刀', '⼒' => '力', '⼓' => '勹', '⼔' => '匕', '⼕' => '匚', '⼖' => '匸', '⼗' => '十', '⼘' => '卜', '⼙' => '卩', '⼚' => '厂', '⼛' => '厶', '⼜' => '又', '⼝' => '口', '⼞' => '囗', '⼟' => '土', '⼠' => '士', '⼡' => '夂', '⼢' => '夊', '⼣' => '夕', '⼤' => '大', '⼥' => '女', '⼦' => '子', '⼧' => '宀', '⼨' => '寸', '⼩' => '小', '⼪' => '尢', '⼫' => '尸', '⼬' => '屮', '⼭' => '山', '⼮' => '巛', '⼯' => '工', '⼰' => '己', '⼱' => '巾', '⼲' => '干', '⼳' => '幺', '⼴' => '广', '⼵' => '廴', '⼶' => '廾', '⼷' => '弋', '⼸' => '弓', '⼹' => '彐', '⼺' => '彡', '⼻' => '彳', '⼼' => '心', '⼽' => '戈', '⼾' => '戶', '⼿' => '手', '⽀' => '支', '⽁' => '攴', '⽂' => '文', '⽃' => '斗', '⽄' => '斤', '⽅' => '方', '⽆' => '无', '⽇' => '日', '⽈' => '曰', '⽉' => '月', '⽊' => '木', '⽋' => '欠', '⽌' => '止', '⽍' => '歹', '⽎' => '殳', '⽏' => '毋', '⽐' => '比', '⽑' => '毛', '⽒' => '氏', '⽓' => '气', '⽔' => '水', '⽕' => '火', '⽖' => '爪', '⽗' => '父', '⽘' => '爻', '⽙' => '爿', '⽚' => '片', '⽛' => '牙', '⽜' => '牛', '⽝' => '犬', '⽞' => '玄', '⽟' => '玉', '⽠' => '瓜', '⽡' => '瓦', '⽢' => '甘', '⽣' => '生', '⽤' => '用', '⽥' => '田', '⽦' => '疋', '⽧' => '疒', '⽨' => '癶', '⽩' => '白', '⽪' => '皮', '⽫' => '皿', '⽬' => '目', '⽭' => '矛', '⽮' => '矢', '⽯' => '石', '⽰' => '示', '⽱' => '禸', '⽲' => '禾', '⽳' => '穴', '⽴' => '立', '⽵' => '竹', '⽶' => '米', '⽷' => '糸', '⽸' => '缶', '⽹' => '网', '⽺' => '羊', '⽻' => '羽', '⽼' => '老', '⽽' => '而', '⽾' => '耒', '⽿' => '耳', '⾀' => '聿', '⾁' => '肉', '⾂' => '臣', '⾃' => '自', '⾄' => '至', '⾅' => '臼', '⾆' => '舌', '⾇' => '舛', '⾈' => '舟', '⾉' => '艮', '⾊' => '色', '⾋' => '艸', '⾌' => '虍', '⾍' => '虫', '⾎' => '血', '⾏' => '行', '⾐' => '衣', '⾑' => '襾', '⾒' => '見', '⾓' => '角', '⾔' => '言', '⾕' => '谷', '⾖' => '豆', '⾗' => '豕', '⾘' => '豸', '⾙' => '貝', '⾚' => '赤', '⾛' => '走', '⾜' => '足', '⾝' => '身', '⾞' => '車', '⾟' => '辛', '⾠' => '辰', '⾡' => '辵', '⾢' => '邑', '⾣' => '酉', '⾤' => '釆', '⾥' => '里', '⾦' => '金', '⾧' => '長', '⾨' => '門', '⾩' => '阜', '⾪' => '隶', '⾫' => '隹', '⾬' => '雨', '⾭' => '靑', '⾮' => '非', '⾯' => '面', '⾰' => '革', '⾱' => '韋', '⾲' => '韭', '⾳' => '音', '⾴' => '頁', '⾵' => '風', '⾶' => '飛', '⾷' => '食', '⾸' => '首', '⾹' => '香', '⾺' => '馬', '⾻' => '骨', '⾼' => '高', '⾽' => '髟', '⾾' => '鬥', '⾿' => '鬯', '⿀' => '鬲', '⿁' => '鬼', '⿂' => '魚', '⿃' => '鳥', '⿄' => '鹵', '⿅' => '鹿', '⿆' => '麥', '⿇' => '麻', '⿈' => '黃', '⿉' => '黍', '⿊' => '黑', '⿋' => '黹', '⿌' => '黽', '⿍' => '鼎', '⿎' => '鼓', '⿏' => '鼠', '⿐' => '鼻', '⿑' => '齊', '⿒' => '齒', '⿓' => '龍', '⿔' => '龜', '⿕' => '龠', '　' => ' ', '〶' => '〒', '〸' => '十', '〹' => '卄', '〺' => '卅', '゛' => ' ゙', '゜' => ' ゚', 'ゟ' => 'より', 'ヿ' => 'コト', 'ㄱ' => 'ᄀ', 'ㄲ' => 'ᄁ', 'ㄳ' => 'ᆪ', 'ㄴ' => 'ᄂ', 'ㄵ' => 'ᆬ', 'ㄶ' => 'ᆭ', 'ㄷ' => 'ᄃ', 'ㄸ' => 'ᄄ', 'ㄹ' => 'ᄅ', 'ㄺ' => 'ᆰ', 'ㄻ' => 'ᆱ', 'ㄼ' => 'ᆲ', 'ㄽ' => 'ᆳ', 'ㄾ' => 'ᆴ', 'ㄿ' => 'ᆵ', 'ㅀ' => 'ᄚ', 'ㅁ' => 'ᄆ', 'ㅂ' => 'ᄇ', 'ㅃ' => 'ᄈ', 'ㅄ' => 'ᄡ', 'ㅅ' => 'ᄉ', 'ㅆ' => 'ᄊ', 'ㅇ' => 'ᄋ', 'ㅈ' => 'ᄌ', 'ㅉ' => 'ᄍ', 'ㅊ' => 'ᄎ', 'ㅋ' => 'ᄏ', 'ㅌ' => 'ᄐ', 'ㅍ' => 'ᄑ', 'ㅎ' => 'ᄒ', 'ㅏ' => 'ᅡ', 'ㅐ' => 'ᅢ', 'ㅑ' => 'ᅣ', 'ㅒ' => 'ᅤ', 'ㅓ' => 'ᅥ', 'ㅔ' => 'ᅦ', 'ㅕ' => 'ᅧ', 'ㅖ' => 'ᅨ', 'ㅗ' => 'ᅩ', 'ㅘ' => 'ᅪ', 'ㅙ' => 'ᅫ', 'ㅚ' => 'ᅬ', 'ㅛ' => 'ᅭ', 'ㅜ' => 'ᅮ', 'ㅝ' => 'ᅯ', 'ㅞ' => 'ᅰ', 'ㅟ' => 'ᅱ', 'ㅠ' => 'ᅲ', 'ㅡ' => 'ᅳ', 'ㅢ' => 'ᅴ', 'ㅣ' => 'ᅵ', 'ㅤ' => 'ᅠ', 'ㅥ' => 'ᄔ', 'ㅦ' => 'ᄕ', 'ㅧ' => 'ᇇ', 'ㅨ' => 'ᇈ', 'ㅩ' => 'ᇌ', 'ㅪ' => 'ᇎ', 'ㅫ' => 'ᇓ', 'ㅬ' => 'ᇗ', 'ㅭ' => 'ᇙ', 'ㅮ' => 'ᄜ', 'ㅯ' => 'ᇝ', 'ㅰ' => 'ᇟ', 'ㅱ' => 'ᄝ', 'ㅲ' => 'ᄞ', 'ㅳ' => 'ᄠ', 'ㅴ' => 'ᄢ', 'ㅵ' => 'ᄣ', 'ㅶ' => 'ᄧ', 'ㅷ' => 'ᄩ', 'ㅸ' => 'ᄫ', 'ㅹ' => 'ᄬ', 'ㅺ' => 'ᄭ', 'ㅻ' => 'ᄮ', 'ㅼ' => 'ᄯ', 'ㅽ' => 'ᄲ', 'ㅾ' => 'ᄶ', 'ㅿ' => 'ᅀ', 'ㆀ' => 'ᅇ', 'ㆁ' => 'ᅌ', 'ㆂ' => 'ᇱ', 'ㆃ' => 'ᇲ', 'ㆄ' => 'ᅗ', 'ㆅ' => 'ᅘ', 'ㆆ' => 'ᅙ', 'ㆇ' => 'ᆄ', 'ㆈ' => 'ᆅ', 'ㆉ' => 'ᆈ', 'ㆊ' => 'ᆑ', 'ㆋ' => 'ᆒ', 'ㆌ' => 'ᆔ', 'ㆍ' => 'ᆞ', 'ㆎ' => 'ᆡ', '㆒' => '一', '㆓' => '二', '㆔' => '三', '㆕' => '四', '㆖' => '上', '㆗' => '中', '㆘' => '下', '㆙' => '甲', '㆚' => '乙', '㆛' => '丙', '㆜' => '丁', '㆝' => '天', '㆞' => '地', '㆟' => '人', '㈀' => '(ᄀ)', '㈁' => '(ᄂ)', '㈂' => '(ᄃ)', '㈃' => '(ᄅ)', '㈄' => '(ᄆ)', '㈅' => '(ᄇ)', '㈆' => '(ᄉ)', '㈇' => '(ᄋ)', '㈈' => '(ᄌ)', '㈉' => '(ᄎ)', '㈊' => '(ᄏ)', '㈋' => '(ᄐ)', '㈌' => '(ᄑ)', '㈍' => '(ᄒ)', '㈎' => '(가)', '㈏' => '(나)', '㈐' => '(다)', '㈑' => '(라)', '㈒' => '(마)', '㈓' => '(바)', '㈔' => '(사)', '㈕' => '(아)', '㈖' => '(자)', '㈗' => '(차)', '㈘' => '(카)', '㈙' => '(타)', '㈚' => '(파)', '㈛' => '(하)', '㈜' => '(주)', '㈝' => '(오전)', '㈞' => '(오후)', '㈠' => '(一)', '㈡' => '(二)', '㈢' => '(三)', '㈣' => '(四)', '㈤' => '(五)', '㈥' => '(六)', '㈦' => '(七)', '㈧' => '(八)', '㈨' => '(九)', '㈩' => '(十)', '㈪' => '(月)', '㈫' => '(火)', '㈬' => '(水)', '㈭' => '(木)', '㈮' => '(金)', '㈯' => '(土)', '㈰' => '(日)', '㈱' => '(株)', '㈲' => '(有)', '㈳' => '(社)', '㈴' => '(名)', '㈵' => '(特)', '㈶' => '(財)', '㈷' => '(祝)', '㈸' => '(労)', '㈹' => '(代)', '㈺' => '(呼)', '㈻' => '(学)', '㈼' => '(監)', '㈽' => '(企)', '㈾' => '(資)', '㈿' => '(協)', '㉀' => '(祭)', '㉁' => '(休)', '㉂' => '(自)', '㉃' => '(至)', '㉄' => '問', '㉅' => '幼', '㉆' => '文', '㉇' => '箏', '㉐' => 'PTE', '㉑' => '21', '㉒' => '22', '㉓' => '23', '㉔' => '24', '㉕' => '25', '㉖' => '26', '㉗' => '27', '㉘' => '28', '㉙' => '29', '㉚' => '30', '㉛' => '31', '㉜' => '32', '㉝' => '33', '㉞' => '34', '㉟' => '35', '㉠' => 'ᄀ', '㉡' => 'ᄂ', '㉢' => 'ᄃ', '㉣' => 'ᄅ', '㉤' => 'ᄆ', '㉥' => 'ᄇ', '㉦' => 'ᄉ', '㉧' => 'ᄋ', '㉨' => 'ᄌ', '㉩' => 'ᄎ', '㉪' => 'ᄏ', '㉫' => 'ᄐ', '㉬' => 'ᄑ', '㉭' => 'ᄒ', '㉮' => '가', '㉯' => '나', '㉰' => '다', '㉱' => '라', '㉲' => '마', '㉳' => '바', '㉴' => '사', '㉵' => '아', '㉶' => '자', '㉷' => '차', '㉸' => '카', '㉹' => '타', '㉺' => '파', '㉻' => '하', '㉼' => '참고', '㉽' => '주의', '㉾' => '우', '㊀' => '一', '㊁' => '二', '㊂' => '三', '㊃' => '四', '㊄' => '五', '㊅' => '六', '㊆' => '七', '㊇' => '八', '㊈' => '九', '㊉' => '十', '㊊' => '月', '㊋' => '火', '㊌' => '水', '㊍' => '木', '㊎' => '金', '㊏' => '土', '㊐' => '日', '㊑' => '株', '㊒' => '有', '㊓' => '社', '㊔' => '名', '㊕' => '特', '㊖' => '財', '㊗' => '祝', '㊘' => '労', '㊙' => '秘', '㊚' => '男', '㊛' => '女', '㊜' => '適', '㊝' => '優', '㊞' => '印', '㊟' => '注', '㊠' => '項', '㊡' => '休', '㊢' => '写', '㊣' => '正', '㊤' => '上', '㊥' => '中', '㊦' => '下', '㊧' => '左', '㊨' => '右', '㊩' => '医', '㊪' => '宗', '㊫' => '学', '㊬' => '監', '㊭' => '企', '㊮' => '資', '㊯' => '協', '㊰' => '夜', '㊱' => '36', '㊲' => '37', '㊳' => '38', '㊴' => '39', '㊵' => '40', '㊶' => '41', '㊷' => '42', '㊸' => '43', '㊹' => '44', '㊺' => '45', '㊻' => '46', '㊼' => '47', '㊽' => '48', '㊾' => '49', '㊿' => '50', '㋀' => '1月', '㋁' => '2月', '㋂' => '3月', '㋃' => '4月', '㋄' => '5月', '㋅' => '6月', '㋆' => '7月', '㋇' => '8月', '㋈' => '9月', '㋉' => '10月', '㋊' => '11月', '㋋' => '12月', '㋌' => 'Hg', '㋍' => 'erg', '㋎' => 'eV', '㋏' => 'LTD', '㋐' => 'ア', '㋑' => 'イ', '㋒' => 'ウ', '㋓' => 'エ', '㋔' => 'オ', '㋕' => 'カ', '㋖' => 'キ', '㋗' => 'ク', '㋘' => 'ケ', '㋙' => 'コ', '㋚' => 'サ', '㋛' => 'シ', '㋜' => 'ス', '㋝' => 'セ', '㋞' => 'ソ', '㋟' => 'タ', '㋠' => 'チ', '㋡' => 'ツ', '㋢' => 'テ', '㋣' => 'ト', '㋤' => 'ナ', '㋥' => 'ニ', '㋦' => 'ヌ', '㋧' => 'ネ', '㋨' => 'ノ', '㋩' => 'ハ', '㋪' => 'ヒ', '㋫' => 'フ', '㋬' => 'ヘ', '㋭' => 'ホ', '㋮' => 'マ', '㋯' => 'ミ', '㋰' => 'ム', '㋱' => 'メ', '㋲' => 'モ', '㋳' => 'ヤ', '㋴' => 'ユ', '㋵' => 'ヨ', '㋶' => 'ラ', '㋷' => 'リ', '㋸' => 'ル', '㋹' => 'レ', '㋺' => 'ロ', '㋻' => 'ワ', '㋼' => 'ヰ', '㋽' => 'ヱ', '㋾' => 'ヲ', '㋿' => '令和', '㌀' => 'アパート', '㌁' => 'アルファ', '㌂' => 'アンペア', '㌃' => 'アール', '㌄' => 'イニング', '㌅' => 'インチ', '㌆' => 'ウォン', '㌇' => 'エスクード', '㌈' => 'エーカー', '㌉' => 'オンス', '㌊' => 'オーム', '㌋' => 'カイリ', '㌌' => 'カラット', '㌍' => 'カロリー', '㌎' => 'ガロン', '㌏' => 'ガンマ', '㌐' => 'ギガ', '㌑' => 'ギニー', '㌒' => 'キュリー', '㌓' => 'ギルダー', '㌔' => 'キロ', '㌕' => 'キログラム', '㌖' => 'キロメートル', '㌗' => 'キロワット', '㌘' => 'グラム', '㌙' => 'グラムトン', '㌚' => 'クルゼイロ', '㌛' => 'クローネ', '㌜' => 'ケース', '㌝' => 'コルナ', '㌞' => 'コーポ', '㌟' => 'サイクル', '㌠' => 'サンチーム', '㌡' => 'シリング', '㌢' => 'センチ', '㌣' => 'セント', '㌤' => 'ダース', '㌥' => 'デシ', '㌦' => 'ドル', '㌧' => 'トン', '㌨' => 'ナノ', '㌩' => 'ノット', '㌪' => 'ハイツ', '㌫' => 'パーセント', '㌬' => 'パーツ', '㌭' => 'バーレル', '㌮' => 'ピアストル', '㌯' => 'ピクル', '㌰' => 'ピコ', '㌱' => 'ビル', '㌲' => 'ファラッド', '㌳' => 'フィート', '㌴' => 'ブッシェル', '㌵' => 'フラン', '㌶' => 'ヘクタール', '㌷' => 'ペソ', '㌸' => 'ペニヒ', '㌹' => 'ヘルツ', '㌺' => 'ペンス', '㌻' => 'ページ', '㌼' => 'ベータ', '㌽' => 'ポイント', '㌾' => 'ボルト', '㌿' => 'ホン', '㍀' => 'ポンド', '㍁' => 'ホール', '㍂' => 'ホーン', '㍃' => 'マイクロ', '㍄' => 'マイル', '㍅' => 'マッハ', '㍆' => 'マルク', '㍇' => 'マンション', '㍈' => 'ミクロン', '㍉' => 'ミリ', '㍊' => 'ミリバール', '㍋' => 'メガ', '㍌' => 'メガトン', '㍍' => 'メートル', '㍎' => 'ヤード', '㍏' => 'ヤール', '㍐' => 'ユアン', '㍑' => 'リットル', '㍒' => 'リラ', '㍓' => 'ルピー', '㍔' => 'ルーブル', '㍕' => 'レム', '㍖' => 'レントゲン', '㍗' => 'ワット', '㍘' => '0点', '㍙' => '1点', '㍚' => '2点', '㍛' => '3点', '㍜' => '4点', '㍝' => '5点', '㍞' => '6点', '㍟' => '7点', '㍠' => '8点', '㍡' => '9点', '㍢' => '10点', '㍣' => '11点', '㍤' => '12点', '㍥' => '13点', '㍦' => '14点', '㍧' => '15点', '㍨' => '16点', '㍩' => '17点', '㍪' => '18点', '㍫' => '19点', '㍬' => '20点', '㍭' => '21点', '㍮' => '22点', '㍯' => '23点', '㍰' => '24点', '㍱' => 'hPa', '㍲' => 'da', '㍳' => 'AU', '㍴' => 'bar', '㍵' => 'oV', '㍶' => 'pc', '㍷' => 'dm', '㍸' => 'dm2', '㍹' => 'dm3', '㍺' => 'IU', '㍻' => '平成', '㍼' => '昭和', '㍽' => '大正', '㍾' => '明治', '㍿' => '株式会社', '㎀' => 'pA', '㎁' => 'nA', '㎂' => 'μA', '㎃' => 'mA', '㎄' => 'kA', '㎅' => 'KB', '㎆' => 'MB', '㎇' => 'GB', '㎈' => 'cal', '㎉' => 'kcal', '㎊' => 'pF', '㎋' => 'nF', '㎌' => 'μF', '㎍' => 'μg', '㎎' => 'mg', '㎏' => 'kg', '㎐' => 'Hz', '㎑' => 'kHz', '㎒' => 'MHz', '㎓' => 'GHz', '㎔' => 'THz', '㎕' => 'μl', '㎖' => 'ml', '㎗' => 'dl', '㎘' => 'kl', '㎙' => 'fm', '㎚' => 'nm', '㎛' => 'μm', '㎜' => 'mm', '㎝' => 'cm', '㎞' => 'km', '㎟' => 'mm2', '㎠' => 'cm2', '㎡' => 'm2', '㎢' => 'km2', '㎣' => 'mm3', '㎤' => 'cm3', '㎥' => 'm3', '㎦' => 'km3', '㎧' => 'm∕s', '㎨' => 'm∕s2', '㎩' => 'Pa', '㎪' => 'kPa', '㎫' => 'MPa', '㎬' => 'GPa', '㎭' => 'rad', '㎮' => 'rad∕s', '㎯' => 'rad∕s2', '㎰' => 'ps', '㎱' => 'ns', '㎲' => 'μs', '㎳' => 'ms', '㎴' => 'pV', '㎵' => 'nV', '㎶' => 'μV', '㎷' => 'mV', '㎸' => 'kV', '㎹' => 'MV', '㎺' => 'pW', '㎻' => 'nW', '㎼' => 'μW', '㎽' => 'mW', '㎾' => 'kW', '㎿' => 'MW', '㏀' => 'kΩ', '㏁' => 'MΩ', '㏂' => 'a.m.', '㏃' => 'Bq', '㏄' => 'cc', '㏅' => 'cd', '㏆' => 'C∕kg', '㏇' => 'Co.', '㏈' => 'dB', '㏉' => 'Gy', '㏊' => 'ha', '㏋' => 'HP', '㏌' => 'in', '㏍' => 'KK', '㏎' => 'KM', '㏏' => 'kt', '㏐' => 'lm', '㏑' => 'ln', '㏒' => 'log', '㏓' => 'lx', '㏔' => 'mb', '㏕' => 'mil', '㏖' => 'mol', '㏗' => 'PH', '㏘' => 'p.m.', '㏙' => 'PPM', '㏚' => 'PR', '㏛' => 'sr', '㏜' => 'Sv', '㏝' => 'Wb', '㏞' => 'V∕m', '㏟' => 'A∕m', '㏠' => '1日', '㏡' => '2日', '㏢' => '3日', '㏣' => '4日', '㏤' => '5日', '㏥' => '6日', '㏦' => '7日', '㏧' => '8日', '㏨' => '9日', '㏩' => '10日', '㏪' => '11日', '㏫' => '12日', '㏬' => '13日', '㏭' => '14日', '㏮' => '15日', '㏯' => '16日', '㏰' => '17日', '㏱' => '18日', '㏲' => '19日', '㏳' => '20日', '㏴' => '21日', '㏵' => '22日', '㏶' => '23日', '㏷' => '24日', '㏸' => '25日', '㏹' => '26日', '㏺' => '27日', '㏻' => '28日', '㏼' => '29日', '㏽' => '30日', '㏾' => '31日', '㏿' => 'gal', 'ꚜ' => 'ъ', 'ꚝ' => 'ь', 'ꝰ' => 'ꝯ', 'ꟸ' => 'Ħ', 'ꟹ' => 'œ', 'ꭜ' => 'ꜧ', 'ꭝ' => 'ꬷ', 'ꭞ' => 'ɫ', 'ꭟ' => 'ꭒ', 'ꭩ' => 'ʍ', 'ﬀ' => 'ff', 'ﬁ' => 'fi', 'ﬂ' => 'fl', 'ﬃ' => 'ffi', 'ﬄ' => 'ffl', 'ﬅ' => 'st', 'ﬆ' => 'st', 'ﬓ' => 'մն', 'ﬔ' => 'մե', 'ﬕ' => 'մի', 'ﬖ' => 'վն', 'ﬗ' => 'մխ', 'ﬠ' => 'ע', 'ﬡ' => 'א', 'ﬢ' => 'ד', 'ﬣ' => 'ה', 'ﬤ' => 'כ', 'ﬥ' => 'ל', 'ﬦ' => 'ם', 'ﬧ' => 'ר', 'ﬨ' => 'ת', '﬩' => '+', 'ﭏ' => 'אל', 'ﭐ' => 'ٱ', 'ﭑ' => 'ٱ', 'ﭒ' => 'ٻ', 'ﭓ' => 'ٻ', 'ﭔ' => 'ٻ', 'ﭕ' => 'ٻ', 'ﭖ' => 'پ', 'ﭗ' => 'پ', 'ﭘ' => 'پ', 'ﭙ' => 'پ', 'ﭚ' => 'ڀ', 'ﭛ' => 'ڀ', 'ﭜ' => 'ڀ', 'ﭝ' => 'ڀ', 'ﭞ' => 'ٺ', 'ﭟ' => 'ٺ', 'ﭠ' => 'ٺ', 'ﭡ' => 'ٺ', 'ﭢ' => 'ٿ', 'ﭣ' => 'ٿ', 'ﭤ' => 'ٿ', 'ﭥ' => 'ٿ', 'ﭦ' => 'ٹ', 'ﭧ' => 'ٹ', 'ﭨ' => 'ٹ', 'ﭩ' => 'ٹ', 'ﭪ' => 'ڤ', 'ﭫ' => 'ڤ', 'ﭬ' => 'ڤ', 'ﭭ' => 'ڤ', 'ﭮ' => 'ڦ', 'ﭯ' => 'ڦ', 'ﭰ' => 'ڦ', 'ﭱ' => 'ڦ', 'ﭲ' => 'ڄ', 'ﭳ' => 'ڄ', 'ﭴ' => 'ڄ', 'ﭵ' => 'ڄ', 'ﭶ' => 'ڃ', 'ﭷ' => 'ڃ', 'ﭸ' => 'ڃ', 'ﭹ' => 'ڃ', 'ﭺ' => 'چ', 'ﭻ' => 'چ', 'ﭼ' => 'چ', 'ﭽ' => 'چ', 'ﭾ' => 'ڇ', 'ﭿ' => 'ڇ', 'ﮀ' => 'ڇ', 'ﮁ' => 'ڇ', 'ﮂ' => 'ڍ', 'ﮃ' => 'ڍ', 'ﮄ' => 'ڌ', 'ﮅ' => 'ڌ', 'ﮆ' => 'ڎ', 'ﮇ' => 'ڎ', 'ﮈ' => 'ڈ', 'ﮉ' => 'ڈ', 'ﮊ' => 'ژ', 'ﮋ' => 'ژ', 'ﮌ' => 'ڑ', 'ﮍ' => 'ڑ', 'ﮎ' => 'ک', 'ﮏ' => 'ک', 'ﮐ' => 'ک', 'ﮑ' => 'ک', 'ﮒ' => 'گ', 'ﮓ' => 'گ', 'ﮔ' => 'گ', 'ﮕ' => 'گ', 'ﮖ' => 'ڳ', 'ﮗ' => 'ڳ', 'ﮘ' => 'ڳ', 'ﮙ' => 'ڳ', 'ﮚ' => 'ڱ', 'ﮛ' => 'ڱ', 'ﮜ' => 'ڱ', 'ﮝ' => 'ڱ', 'ﮞ' => 'ں', 'ﮟ' => 'ں', 'ﮠ' => 'ڻ', 'ﮡ' => 'ڻ', 'ﮢ' => 'ڻ', 'ﮣ' => 'ڻ', 'ﮤ' => 'ۀ', 'ﮥ' => 'ۀ', 'ﮦ' => 'ہ', 'ﮧ' => 'ہ', 'ﮨ' => 'ہ', 'ﮩ' => 'ہ', 'ﮪ' => 'ھ', 'ﮫ' => 'ھ', 'ﮬ' => 'ھ', 'ﮭ' => 'ھ', 'ﮮ' => 'ے', 'ﮯ' => 'ے', 'ﮰ' => 'ۓ', 'ﮱ' => 'ۓ', 'ﯓ' => 'ڭ', 'ﯔ' => 'ڭ', 'ﯕ' => 'ڭ', 'ﯖ' => 'ڭ', 'ﯗ' => 'ۇ', 'ﯘ' => 'ۇ', 'ﯙ' => 'ۆ', 'ﯚ' => 'ۆ', 'ﯛ' => 'ۈ', 'ﯜ' => 'ۈ', 'ﯝ' => 'ۇٴ', 'ﯞ' => 'ۋ', 'ﯟ' => 'ۋ', 'ﯠ' => 'ۅ', 'ﯡ' => 'ۅ', 'ﯢ' => 'ۉ', 'ﯣ' => 'ۉ', 'ﯤ' => 'ې', 'ﯥ' => 'ې', 'ﯦ' => 'ې', 'ﯧ' => 'ې', 'ﯨ' => 'ى', 'ﯩ' => 'ى', 'ﯪ' => 'ئا', 'ﯫ' => 'ئا', 'ﯬ' => 'ئە', 'ﯭ' => 'ئە', 'ﯮ' => 'ئو', 'ﯯ' => 'ئو', 'ﯰ' => 'ئۇ', 'ﯱ' => 'ئۇ', 'ﯲ' => 'ئۆ', 'ﯳ' => 'ئۆ', 'ﯴ' => 'ئۈ', 'ﯵ' => 'ئۈ', 'ﯶ' => 'ئې', 'ﯷ' => 'ئې', 'ﯸ' => 'ئې', 'ﯹ' => 'ئى', 'ﯺ' => 'ئى', 'ﯻ' => 'ئى', 'ﯼ' => 'ی', 'ﯽ' => 'ی', 'ﯾ' => 'ی', 'ﯿ' => 'ی', 'ﰀ' => 'ئج', 'ﰁ' => 'ئح', 'ﰂ' => 'ئم', 'ﰃ' => 'ئى', 'ﰄ' => 'ئي', 'ﰅ' => 'بج', 'ﰆ' => 'بح', 'ﰇ' => 'بخ', 'ﰈ' => 'بم', 'ﰉ' => 'بى', 'ﰊ' => 'بي', 'ﰋ' => 'تج', 'ﰌ' => 'تح', 'ﰍ' => 'تخ', 'ﰎ' => 'تم', 'ﰏ' => 'تى', 'ﰐ' => 'تي', 'ﰑ' => 'ثج', 'ﰒ' => 'ثم', 'ﰓ' => 'ثى', 'ﰔ' => 'ثي', 'ﰕ' => 'جح', 'ﰖ' => 'جم', 'ﰗ' => 'حج', 'ﰘ' => 'حم', 'ﰙ' => 'خج', 'ﰚ' => 'خح', 'ﰛ' => 'خم', 'ﰜ' => 'سج', 'ﰝ' => 'سح', 'ﰞ' => 'سخ', 'ﰟ' => 'سم', 'ﰠ' => 'صح', 'ﰡ' => 'صم', 'ﰢ' => 'ضج', 'ﰣ' => 'ضح', 'ﰤ' => 'ضخ', 'ﰥ' => 'ضم', 'ﰦ' => 'طح', 'ﰧ' => 'طم', 'ﰨ' => 'ظم', 'ﰩ' => 'عج', 'ﰪ' => 'عم', 'ﰫ' => 'غج', 'ﰬ' => 'غم', 'ﰭ' => 'فج', 'ﰮ' => 'فح', 'ﰯ' => 'فخ', 'ﰰ' => 'فم', 'ﰱ' => 'فى', 'ﰲ' => 'في', 'ﰳ' => 'قح', 'ﰴ' => 'قم', 'ﰵ' => 'قى', 'ﰶ' => 'قي', 'ﰷ' => 'كا', 'ﰸ' => 'كج', 'ﰹ' => 'كح', 'ﰺ' => 'كخ', 'ﰻ' => 'كل', 'ﰼ' => 'كم', 'ﰽ' => 'كى', 'ﰾ' => 'كي', 'ﰿ' => 'لج', 'ﱀ' => 'لح', 'ﱁ' => 'لخ', 'ﱂ' => 'لم', 'ﱃ' => 'لى', 'ﱄ' => 'لي', 'ﱅ' => 'مج', 'ﱆ' => 'مح', 'ﱇ' => 'مخ', 'ﱈ' => 'مم', 'ﱉ' => 'مى', 'ﱊ' => 'مي', 'ﱋ' => 'نج', 'ﱌ' => 'نح', 'ﱍ' => 'نخ', 'ﱎ' => 'نم', 'ﱏ' => 'نى', 'ﱐ' => 'ني', 'ﱑ' => 'هج', 'ﱒ' => 'هم', 'ﱓ' => 'هى', 'ﱔ' => 'هي', 'ﱕ' => 'يج', 'ﱖ' => 'يح', 'ﱗ' => 'يخ', 'ﱘ' => 'يم', 'ﱙ' => 'يى', 'ﱚ' => 'يي', 'ﱛ' => 'ذٰ', 'ﱜ' => 'رٰ', 'ﱝ' => 'ىٰ', 'ﱞ' => ' ٌّ', 'ﱟ' => ' ٍّ', 'ﱠ' => ' َّ', 'ﱡ' => ' ُّ', 'ﱢ' => ' ِّ', 'ﱣ' => ' ّٰ', 'ﱤ' => 'ئر', 'ﱥ' => 'ئز', 'ﱦ' => 'ئم', 'ﱧ' => 'ئن', 'ﱨ' => 'ئى', 'ﱩ' => 'ئي', 'ﱪ' => 'بر', 'ﱫ' => 'بز', 'ﱬ' => 'بم', 'ﱭ' => 'بن', 'ﱮ' => 'بى', 'ﱯ' => 'بي', 'ﱰ' => 'تر', 'ﱱ' => 'تز', 'ﱲ' => 'تم', 'ﱳ' => 'تن', 'ﱴ' => 'تى', 'ﱵ' => 'تي', 'ﱶ' => 'ثر', 'ﱷ' => 'ثز', 'ﱸ' => 'ثم', 'ﱹ' => 'ثن', 'ﱺ' => 'ثى', 'ﱻ' => 'ثي', 'ﱼ' => 'فى', 'ﱽ' => 'في', 'ﱾ' => 'قى', 'ﱿ' => 'قي', 'ﲀ' => 'كا', 'ﲁ' => 'كل', 'ﲂ' => 'كم', 'ﲃ' => 'كى', 'ﲄ' => 'كي', 'ﲅ' => 'لم', 'ﲆ' => 'لى', 'ﲇ' => 'لي', 'ﲈ' => 'ما', 'ﲉ' => 'مم', 'ﲊ' => 'نر', 'ﲋ' => 'نز', 'ﲌ' => 'نم', 'ﲍ' => 'نن', 'ﲎ' => 'نى', 'ﲏ' => 'ني', 'ﲐ' => 'ىٰ', 'ﲑ' => 'ير', 'ﲒ' => 'يز', 'ﲓ' => 'يم', 'ﲔ' => 'ين', 'ﲕ' => 'يى', 'ﲖ' => 'يي', 'ﲗ' => 'ئج', 'ﲘ' => 'ئح', 'ﲙ' => 'ئخ', 'ﲚ' => 'ئم', 'ﲛ' => 'ئه', 'ﲜ' => 'بج', 'ﲝ' => 'بح', 'ﲞ' => 'بخ', 'ﲟ' => 'بم', 'ﲠ' => 'به', 'ﲡ' => 'تج', 'ﲢ' => 'تح', 'ﲣ' => 'تخ', 'ﲤ' => 'تم', 'ﲥ' => 'ته', 'ﲦ' => 'ثم', 'ﲧ' => 'جح', 'ﲨ' => 'جم', 'ﲩ' => 'حج', 'ﲪ' => 'حم', 'ﲫ' => 'خج', 'ﲬ' => 'خم', 'ﲭ' => 'سج', 'ﲮ' => 'سح', 'ﲯ' => 'سخ', 'ﲰ' => 'سم', 'ﲱ' => 'صح', 'ﲲ' => 'صخ', 'ﲳ' => 'صم', 'ﲴ' => 'ضج', 'ﲵ' => 'ضح', 'ﲶ' => 'ضخ', 'ﲷ' => 'ضم', 'ﲸ' => 'طح', 'ﲹ' => 'ظم', 'ﲺ' => 'عج', 'ﲻ' => 'عم', 'ﲼ' => 'غج', 'ﲽ' => 'غم', 'ﲾ' => 'فج', 'ﲿ' => 'فح', 'ﳀ' => 'فخ', 'ﳁ' => 'فم', 'ﳂ' => 'قح', 'ﳃ' => 'قم', 'ﳄ' => 'كج', 'ﳅ' => 'كح', 'ﳆ' => 'كخ', 'ﳇ' => 'كل', 'ﳈ' => 'كم', 'ﳉ' => 'لج', 'ﳊ' => 'لح', 'ﳋ' => 'لخ', 'ﳌ' => 'لم', 'ﳍ' => 'له', 'ﳎ' => 'مج', 'ﳏ' => 'مح', 'ﳐ' => 'مخ', 'ﳑ' => 'مم', 'ﳒ' => 'نج', 'ﳓ' => 'نح', 'ﳔ' => 'نخ', 'ﳕ' => 'نم', 'ﳖ' => 'نه', 'ﳗ' => 'هج', 'ﳘ' => 'هم', 'ﳙ' => 'هٰ', 'ﳚ' => 'يج', 'ﳛ' => 'يح', 'ﳜ' => 'يخ', 'ﳝ' => 'يم', 'ﳞ' => 'يه', 'ﳟ' => 'ئم', 'ﳠ' => 'ئه', 'ﳡ' => 'بم', 'ﳢ' => 'به', 'ﳣ' => 'تم', 'ﳤ' => 'ته', 'ﳥ' => 'ثم', 'ﳦ' => 'ثه', 'ﳧ' => 'سم', 'ﳨ' => 'سه', 'ﳩ' => 'شم', 'ﳪ' => 'شه', 'ﳫ' => 'كل', 'ﳬ' => 'كم', 'ﳭ' => 'لم', 'ﳮ' => 'نم', 'ﳯ' => 'نه', 'ﳰ' => 'يم', 'ﳱ' => 'يه', 'ﳲ' => 'ـَّ', 'ﳳ' => 'ـُّ', 'ﳴ' => 'ـِّ', 'ﳵ' => 'طى', 'ﳶ' => 'طي', 'ﳷ' => 'عى', 'ﳸ' => 'عي', 'ﳹ' => 'غى', 'ﳺ' => 'غي', 'ﳻ' => 'سى', 'ﳼ' => 'سي', 'ﳽ' => 'شى', 'ﳾ' => 'شي', 'ﳿ' => 'حى', 'ﴀ' => 'حي', 'ﴁ' => 'جى', 'ﴂ' => 'جي', 'ﴃ' => 'خى', 'ﴄ' => 'خي', 'ﴅ' => 'صى', 'ﴆ' => 'صي', 'ﴇ' => 'ضى', 'ﴈ' => 'ضي', 'ﴉ' => 'شج', 'ﴊ' => 'شح', 'ﴋ' => 'شخ', 'ﴌ' => 'شم', 'ﴍ' => 'شر', 'ﴎ' => 'سر', 'ﴏ' => 'صر', 'ﴐ' => 'ضر', 'ﴑ' => 'طى', 'ﴒ' => 'طي', 'ﴓ' => 'عى', 'ﴔ' => 'عي', 'ﴕ' => 'غى', 'ﴖ' => 'غي', 'ﴗ' => 'سى', 'ﴘ' => 'سي', 'ﴙ' => 'شى', 'ﴚ' => 'شي', 'ﴛ' => 'حى', 'ﴜ' => 'حي', 'ﴝ' => 'جى', 'ﴞ' => 'جي', 'ﴟ' => 'خى', 'ﴠ' => 'خي', 'ﴡ' => 'صى', 'ﴢ' => 'صي', 'ﴣ' => 'ضى', 'ﴤ' => 'ضي', 'ﴥ' => 'شج', 'ﴦ' => 'شح', 'ﴧ' => 'شخ', 'ﴨ' => 'شم', 'ﴩ' => 'شر', 'ﴪ' => 'سر', 'ﴫ' => 'صر', 'ﴬ' => 'ضر', 'ﴭ' => 'شج', 'ﴮ' => 'شح', 'ﴯ' => 'شخ', 'ﴰ' => 'شم', 'ﴱ' => 'سه', 'ﴲ' => 'شه', 'ﴳ' => 'طم', 'ﴴ' => 'سج', 'ﴵ' => 'سح', 'ﴶ' => 'سخ', 'ﴷ' => 'شج', 'ﴸ' => 'شح', 'ﴹ' => 'شخ', 'ﴺ' => 'طم', 'ﴻ' => 'ظم', 'ﴼ' => 'اً', 'ﴽ' => 'اً', 'ﵐ' => 'تجم', 'ﵑ' => 'تحج', 'ﵒ' => 'تحج', 'ﵓ' => 'تحم', 'ﵔ' => 'تخم', 'ﵕ' => 'تمج', 'ﵖ' => 'تمح', 'ﵗ' => 'تمخ', 'ﵘ' => 'جمح', 'ﵙ' => 'جمح', 'ﵚ' => 'حمي', 'ﵛ' => 'حمى', 'ﵜ' => 'سحج', 'ﵝ' => 'سجح', 'ﵞ' => 'سجى', 'ﵟ' => 'سمح', 'ﵠ' => 'سمح', 'ﵡ' => 'سمج', 'ﵢ' => 'سمم', 'ﵣ' => 'سمم', 'ﵤ' => 'صحح', 'ﵥ' => 'صحح', 'ﵦ' => 'صمم', 'ﵧ' => 'شحم', 'ﵨ' => 'شحم', 'ﵩ' => 'شجي', 'ﵪ' => 'شمخ', 'ﵫ' => 'شمخ', 'ﵬ' => 'شمم', 'ﵭ' => 'شمم', 'ﵮ' => 'ضحى', 'ﵯ' => 'ضخم', 'ﵰ' => 'ضخم', 'ﵱ' => 'طمح', 'ﵲ' => 'طمح', 'ﵳ' => 'طمم', 'ﵴ' => 'طمي', 'ﵵ' => 'عجم', 'ﵶ' => 'عمم', 'ﵷ' => 'عمم', 'ﵸ' => 'عمى', 'ﵹ' => 'غمم', 'ﵺ' => 'غمي', 'ﵻ' => 'غمى', 'ﵼ' => 'فخم', 'ﵽ' => 'فخم', 'ﵾ' => 'قمح', 'ﵿ' => 'قمم', 'ﶀ' => 'لحم', 'ﶁ' => 'لحي', 'ﶂ' => 'لحى', 'ﶃ' => 'لجج', 'ﶄ' => 'لجج', 'ﶅ' => 'لخم', 'ﶆ' => 'لخم', 'ﶇ' => 'لمح', 'ﶈ' => 'لمح', 'ﶉ' => 'محج', 'ﶊ' => 'محم', 'ﶋ' => 'محي', 'ﶌ' => 'مجح', 'ﶍ' => 'مجم', 'ﶎ' => 'مخج', 'ﶏ' => 'مخم', 'ﶒ' => 'مجخ', 'ﶓ' => 'همج', 'ﶔ' => 'همم', 'ﶕ' => 'نحم', 'ﶖ' => 'نحى', 'ﶗ' => 'نجم', 'ﶘ' => 'نجم', 'ﶙ' => 'نجى', 'ﶚ' => 'نمي', 'ﶛ' => 'نمى', 'ﶜ' => 'يمم', 'ﶝ' => 'يمم', 'ﶞ' => 'بخي', 'ﶟ' => 'تجي', 'ﶠ' => 'تجى', 'ﶡ' => 'تخي', 'ﶢ' => 'تخى', 'ﶣ' => 'تمي', 'ﶤ' => 'تمى', 'ﶥ' => 'جمي', 'ﶦ' => 'جحى', 'ﶧ' => 'جمى', 'ﶨ' => 'سخى', 'ﶩ' => 'صحي', 'ﶪ' => 'شحي', 'ﶫ' => 'ضحي', 'ﶬ' => 'لجي', 'ﶭ' => 'لمي', 'ﶮ' => 'يحي', 'ﶯ' => 'يجي', 'ﶰ' => 'يمي', 'ﶱ' => 'ممي', 'ﶲ' => 'قمي', 'ﶳ' => 'نحي', 'ﶴ' => 'قمح', 'ﶵ' => 'لحم', 'ﶶ' => 'عمي', 'ﶷ' => 'كمي', 'ﶸ' => 'نجح', 'ﶹ' => 'مخي', 'ﶺ' => 'لجم', 'ﶻ' => 'كمم', 'ﶼ' => 'لجم', 'ﶽ' => 'نجح', 'ﶾ' => 'جحي', 'ﶿ' => 'حجي', 'ﷀ' => 'مجي', 'ﷁ' => 'فمي', 'ﷂ' => 'بحي', 'ﷃ' => 'كمم', 'ﷄ' => 'عجم', 'ﷅ' => 'صمم', 'ﷆ' => 'سخي', 'ﷇ' => 'نجي', 'ﷰ' => 'صلے', 'ﷱ' => 'قلے', 'ﷲ' => 'الله', 'ﷳ' => 'اكبر', 'ﷴ' => 'محمد', 'ﷵ' => 'صلعم', 'ﷶ' => 'رسول', 'ﷷ' => 'عليه', 'ﷸ' => 'وسلم', 'ﷹ' => 'صلى', 'ﷺ' => 'صلى الله عليه وسلم', 'ﷻ' => 'جل جلاله', '﷼' => 'ریال', '︐' => ',', '︑' => '、', '︒' => '。', '︓' => ':', '︔' => ';', '︕' => '!', '︖' => '?', '︗' => '〖', '︘' => '〗', '︙' => '...', '︰' => '..', '︱' => '—', '︲' => '–', '︳' => '_', '︴' => '_', '︵' => '(', '︶' => ')', '︷' => '{', '︸' => '}', '︹' => '〔', '︺' => '〕', '︻' => '【', '︼' => '】', '︽' => '《', '︾' => '》', '︿' => '〈', '﹀' => '〉', '﹁' => '「', '﹂' => '」', '﹃' => '『', '﹄' => '』', '﹇' => '[', '﹈' => ']', '﹉' => ' ̅', '﹊' => ' ̅', '﹋' => ' ̅', '﹌' => ' ̅', '﹍' => '_', '﹎' => '_', '﹏' => '_', '﹐' => ',', '﹑' => '、', '﹒' => '.', '﹔' => ';', '﹕' => ':', '﹖' => '?', '﹗' => '!', '﹘' => '—', '﹙' => '(', '﹚' => ')', '﹛' => '{', '﹜' => '}', '﹝' => '〔', '﹞' => '〕', '﹟' => '#', '﹠' => '&', '﹡' => '*', '﹢' => '+', '﹣' => '-', '﹤' => '<', '﹥' => '>', '﹦' => '=', '﹨' => '\\', '﹩' => '$', '﹪' => '%', '﹫' => '@', 'ﹰ' => ' ً', 'ﹱ' => 'ـً', 'ﹲ' => ' ٌ', 'ﹴ' => ' ٍ', 'ﹶ' => ' َ', 'ﹷ' => 'ـَ', 'ﹸ' => ' ُ', 'ﹹ' => 'ـُ', 'ﹺ' => ' ِ', 'ﹻ' => 'ـِ', 'ﹼ' => ' ّ', 'ﹽ' => 'ـّ', 'ﹾ' => ' ْ', 'ﹿ' => 'ـْ', 'ﺀ' => 'ء', 'ﺁ' => 'آ', 'ﺂ' => 'آ', 'ﺃ' => 'أ', 'ﺄ' => 'أ', 'ﺅ' => 'ؤ', 'ﺆ' => 'ؤ', 'ﺇ' => 'إ', 'ﺈ' => 'إ', 'ﺉ' => 'ئ', 'ﺊ' => 'ئ', 'ﺋ' => 'ئ', 'ﺌ' => 'ئ', 'ﺍ' => 'ا', 'ﺎ' => 'ا', 'ﺏ' => 'ب', 'ﺐ' => 'ب', 'ﺑ' => 'ب', 'ﺒ' => 'ب', 'ﺓ' => 'ة', 'ﺔ' => 'ة', 'ﺕ' => 'ت', 'ﺖ' => 'ت', 'ﺗ' => 'ت', 'ﺘ' => 'ت', 'ﺙ' => 'ث', 'ﺚ' => 'ث', 'ﺛ' => 'ث', 'ﺜ' => 'ث', 'ﺝ' => 'ج', 'ﺞ' => 'ج', 'ﺟ' => 'ج', 'ﺠ' => 'ج', 'ﺡ' => 'ح', 'ﺢ' => 'ح', 'ﺣ' => 'ح', 'ﺤ' => 'ح', 'ﺥ' => 'خ', 'ﺦ' => 'خ', 'ﺧ' => 'خ', 'ﺨ' => 'خ', 'ﺩ' => 'د', 'ﺪ' => 'د', 'ﺫ' => 'ذ', 'ﺬ' => 'ذ', 'ﺭ' => 'ر', 'ﺮ' => 'ر', 'ﺯ' => 'ز', 'ﺰ' => 'ز', 'ﺱ' => 'س', 'ﺲ' => 'س', 'ﺳ' => 'س', 'ﺴ' => 'س', 'ﺵ' => 'ش', 'ﺶ' => 'ش', 'ﺷ' => 'ش', 'ﺸ' => 'ش', 'ﺹ' => 'ص', 'ﺺ' => 'ص', 'ﺻ' => 'ص', 'ﺼ' => 'ص', 'ﺽ' => 'ض', 'ﺾ' => 'ض', 'ﺿ' => 'ض', 'ﻀ' => 'ض', 'ﻁ' => 'ط', 'ﻂ' => 'ط', 'ﻃ' => 'ط', 'ﻄ' => 'ط', 'ﻅ' => 'ظ', 'ﻆ' => 'ظ', 'ﻇ' => 'ظ', 'ﻈ' => 'ظ', 'ﻉ' => 'ع', 'ﻊ' => 'ع', 'ﻋ' => 'ع', 'ﻌ' => 'ع', 'ﻍ' => 'غ', 'ﻎ' => 'غ', 'ﻏ' => 'غ', 'ﻐ' => 'غ', 'ﻑ' => 'ف', 'ﻒ' => 'ف', 'ﻓ' => 'ف', 'ﻔ' => 'ف', 'ﻕ' => 'ق', 'ﻖ' => 'ق', 'ﻗ' => 'ق', 'ﻘ' => 'ق', 'ﻙ' => 'ك', 'ﻚ' => 'ك', 'ﻛ' => 'ك', 'ﻜ' => 'ك', 'ﻝ' => 'ل', 'ﻞ' => 'ل', 'ﻟ' => 'ل', 'ﻠ' => 'ل', 'ﻡ' => 'م', 'ﻢ' => 'م', 'ﻣ' => 'م', 'ﻤ' => 'م', 'ﻥ' => 'ن', 'ﻦ' => 'ن', 'ﻧ' => 'ن', 'ﻨ' => 'ن', 'ﻩ' => 'ه', 'ﻪ' => 'ه', 'ﻫ' => 'ه', 'ﻬ' => 'ه', 'ﻭ' => 'و', 'ﻮ' => 'و', 'ﻯ' => 'ى', 'ﻰ' => 'ى', 'ﻱ' => 'ي', 'ﻲ' => 'ي', 'ﻳ' => 'ي', 'ﻴ' => 'ي', 'ﻵ' => 'لآ', 'ﻶ' => 'لآ', 'ﻷ' => 'لأ', 'ﻸ' => 'لأ', 'ﻹ' => 'لإ', 'ﻺ' => 'لإ', 'ﻻ' => 'لا', 'ﻼ' => 'لا', '！' => '!', '＂' => '"', '＃' => '#', '＄' => '$', '％' => '%', '＆' => '&', '＇' => '\'', '（' => '(', '）' => ')', '＊' => '*', '＋' => '+', '，' => ',', '－' => '-', '．' => '.', '／' => '/', '０' => '0', '１' => '1', '２' => '2', '３' => '3', '４' => '4', '５' => '5', '６' => '6', '７' => '7', '８' => '8', '９' => '9', '：' => ':', '；' => ';', '＜' => '<', '＝' => '=', '＞' => '>', '？' => '?', '＠' => '@', 'Ａ' => 'A', 'Ｂ' => 'B', 'Ｃ' => 'C', 'Ｄ' => 'D', 'Ｅ' => 'E', 'Ｆ' => 'F', 'Ｇ' => 'G', 'Ｈ' => 'H', 'Ｉ' => 'I', 'Ｊ' => 'J', 'Ｋ' => 'K', 'Ｌ' => 'L', 'Ｍ' => 'M', 'Ｎ' => 'N', 'Ｏ' => 'O', 'Ｐ' => 'P', 'Ｑ' => 'Q', 'Ｒ' => 'R', 'Ｓ' => 'S', 'Ｔ' => 'T', 'Ｕ' => 'U', 'Ｖ' => 'V', 'Ｗ' => 'W', 'Ｘ' => 'X', 'Ｙ' => 'Y', 'Ｚ' => 'Z', '［' => '[', '＼' => '\\', '］' => ']', '＾' => '^', '＿' => '_', '｀' => '`', 'ａ' => 'a', 'ｂ' => 'b', 'ｃ' => 'c', 'ｄ' => 'd', 'ｅ' => 'e', 'ｆ' => 'f', 'ｇ' => 'g', 'ｈ' => 'h', 'ｉ' => 'i', 'ｊ' => 'j', 'ｋ' => 'k', 'ｌ' => 'l', 'ｍ' => 'm', 'ｎ' => 'n', 'ｏ' => 'o', 'ｐ' => 'p', 'ｑ' => 'q', 'ｒ' => 'r', 'ｓ' => 's', 'ｔ' => 't', 'ｕ' => 'u', 'ｖ' => 'v', 'ｗ' => 'w', 'ｘ' => 'x', 'ｙ' => 'y', 'ｚ' => 'z', '｛' => '{', '｜' => '|', '｝' => '}', '～' => '~', '｟' => '⦅', '｠' => '⦆', '｡' => '。', '｢' => '「', '｣' => '」', '､' => '、', '･' => '・', 'ｦ' => 'ヲ', 'ｧ' => 'ァ', 'ｨ' => 'ィ', 'ｩ' => 'ゥ', 'ｪ' => 'ェ', 'ｫ' => 'ォ', 'ｬ' => 'ャ', 'ｭ' => 'ュ', 'ｮ' => 'ョ', 'ｯ' => 'ッ', 'ｰ' => 'ー', 'ｱ' => 'ア', 'ｲ' => 'イ', 'ｳ' => 'ウ', 'ｴ' => 'エ', 'ｵ' => 'オ', 'ｶ' => 'カ', 'ｷ' => 'キ', 'ｸ' => 'ク', 'ｹ' => 'ケ', 'ｺ' => 'コ', 'ｻ' => 'サ', 'ｼ' => 'シ', 'ｽ' => 'ス', 'ｾ' => 'セ', 'ｿ' => 'ソ', 'ﾀ' => 'タ', 'ﾁ' => 'チ', 'ﾂ' => 'ツ', 'ﾃ' => 'テ', 'ﾄ' => 'ト', 'ﾅ' => 'ナ', 'ﾆ' => 'ニ', 'ﾇ' => 'ヌ', 'ﾈ' => 'ネ', 'ﾉ' => 'ノ', 'ﾊ' => 'ハ', 'ﾋ' => 'ヒ', 'ﾌ' => 'フ', 'ﾍ' => 'ヘ', 'ﾎ' => 'ホ', 'ﾏ' => 'マ', 'ﾐ' => 'ミ', 'ﾑ' => 'ム', 'ﾒ' => 'メ', 'ﾓ' => 'モ', 'ﾔ' => 'ヤ', 'ﾕ' => 'ユ', 'ﾖ' => 'ヨ', 'ﾗ' => 'ラ', 'ﾘ' => 'リ', 'ﾙ' => 'ル', 'ﾚ' => 'レ', 'ﾛ' => 'ロ', 'ﾜ' => 'ワ', 'ﾝ' => 'ン', 'ﾞ' => '゙', 'ﾟ' => '゚', 'ﾠ' => 'ᅠ', 'ﾡ' => 'ᄀ', 'ﾢ' => 'ᄁ', 'ﾣ' => 'ᆪ', 'ﾤ' => 'ᄂ', 'ﾥ' => 'ᆬ', 'ﾦ' => 'ᆭ', 'ﾧ' => 'ᄃ', 'ﾨ' => 'ᄄ', 'ﾩ' => 'ᄅ', 'ﾪ' => 'ᆰ', 'ﾫ' => 'ᆱ', 'ﾬ' => 'ᆲ', 'ﾭ' => 'ᆳ', 'ﾮ' => 'ᆴ', 'ﾯ' => 'ᆵ', 'ﾰ' => 'ᄚ', 'ﾱ' => 'ᄆ', 'ﾲ' => 'ᄇ', 'ﾳ' => 'ᄈ', 'ﾴ' => 'ᄡ', 'ﾵ' => 'ᄉ', 'ﾶ' => 'ᄊ', 'ﾷ' => 'ᄋ', 'ﾸ' => 'ᄌ', 'ﾹ' => 'ᄍ', 'ﾺ' => 'ᄎ', 'ﾻ' => 'ᄏ', 'ﾼ' => 'ᄐ', 'ﾽ' => 'ᄑ', 'ﾾ' => 'ᄒ', 'ￂ' => 'ᅡ', 'ￃ' => 'ᅢ', 'ￄ' => 'ᅣ', 'ￅ' => 'ᅤ', 'ￆ' => 'ᅥ', 'ￇ' => 'ᅦ', 'ￊ' => 'ᅧ', 'ￋ' => 'ᅨ', 'ￌ' => 'ᅩ', 'ￍ' => 'ᅪ', 'ￎ' => 'ᅫ', 'ￏ' => 'ᅬ', 'ￒ' => 'ᅭ', 'ￓ' => 'ᅮ', 'ￔ' => 'ᅯ', 'ￕ' => 'ᅰ', 'ￖ' => 'ᅱ', 'ￗ' => 'ᅲ', 'ￚ' => 'ᅳ', 'ￛ' => 'ᅴ', 'ￜ' => 'ᅵ', '￠' => '¢', '￡' => '£', '￢' => '¬', '￣' => ' ̄', '￤' => '¦', '￥' => '¥', '￦' => '₩', '￨' => '│', '￩' => '←', '￪' => '↑', '￫' => '→', '￬' => '↓', '￭' => '■', '￮' => '○', '𝐀' => 'A', '𝐁' => 'B', '𝐂' => 'C', '𝐃' => 'D', '𝐄' => 'E', '𝐅' => 'F', '𝐆' => 'G', '𝐇' => 'H', '𝐈' => 'I', '𝐉' => 'J', '𝐊' => 'K', '𝐋' => 'L', '𝐌' => 'M', '𝐍' => 'N', '𝐎' => 'O', '𝐏' => 'P', '𝐐' => 'Q', '𝐑' => 'R', '𝐒' => 'S', '𝐓' => 'T', '𝐔' => 'U', '𝐕' => 'V', '𝐖' => 'W', '𝐗' => 'X', '𝐘' => 'Y', '𝐙' => 'Z', '𝐚' => 'a', '𝐛' => 'b', '𝐜' => 'c', '𝐝' => 'd', '𝐞' => 'e', '𝐟' => 'f', '𝐠' => 'g', '𝐡' => 'h', '𝐢' => 'i', '𝐣' => 'j', '𝐤' => 'k', '𝐥' => 'l', '𝐦' => 'm', '𝐧' => 'n', '𝐨' => 'o', '𝐩' => 'p', '𝐪' => 'q', '𝐫' => 'r', '𝐬' => 's', '𝐭' => 't', '𝐮' => 'u', '𝐯' => 'v', '𝐰' => 'w', '𝐱' => 'x', '𝐲' => 'y', '𝐳' => 'z', '𝐴' => 'A', '𝐵' => 'B', '𝐶' => 'C', '𝐷' => 'D', '𝐸' => 'E', '𝐹' => 'F', '𝐺' => 'G', '𝐻' => 'H', '𝐼' => 'I', '𝐽' => 'J', '𝐾' => 'K', '𝐿' => 'L', '𝑀' => 'M', '𝑁' => 'N', '𝑂' => 'O', '𝑃' => 'P', '𝑄' => 'Q', '𝑅' => 'R', '𝑆' => 'S', '𝑇' => 'T', '𝑈' => 'U', '𝑉' => 'V', '𝑊' => 'W', '𝑋' => 'X', '𝑌' => 'Y', '𝑍' => 'Z', '𝑎' => 'a', '𝑏' => 'b', '𝑐' => 'c', '𝑑' => 'd', '𝑒' => 'e', '𝑓' => 'f', '𝑔' => 'g', '𝑖' => 'i', '𝑗' => 'j', '𝑘' => 'k', '𝑙' => 'l', '𝑚' => 'm', '𝑛' => 'n', '𝑜' => 'o', '𝑝' => 'p', '𝑞' => 'q', '𝑟' => 'r', '𝑠' => 's', '𝑡' => 't', '𝑢' => 'u', '𝑣' => 'v', '𝑤' => 'w', '𝑥' => 'x', '𝑦' => 'y', '𝑧' => 'z', '𝑨' => 'A', '𝑩' => 'B', '𝑪' => 'C', '𝑫' => 'D', '𝑬' => 'E', '𝑭' => 'F', '𝑮' => 'G', '𝑯' => 'H', '𝑰' => 'I', '𝑱' => 'J', '𝑲' => 'K', '𝑳' => 'L', '𝑴' => 'M', '𝑵' => 'N', '𝑶' => 'O', '𝑷' => 'P', '𝑸' => 'Q', '𝑹' => 'R', '𝑺' => 'S', '𝑻' => 'T', '𝑼' => 'U', '𝑽' => 'V', '𝑾' => 'W', '𝑿' => 'X', '𝒀' => 'Y', '𝒁' => 'Z', '𝒂' => 'a', '𝒃' => 'b', '𝒄' => 'c', '𝒅' => 'd', '𝒆' => 'e', '𝒇' => 'f', '𝒈' => 'g', '𝒉' => 'h', '𝒊' => 'i', '𝒋' => 'j', '𝒌' => 'k', '𝒍' => 'l', '𝒎' => 'm', '𝒏' => 'n', '𝒐' => 'o', '𝒑' => 'p', '𝒒' => 'q', '𝒓' => 'r', '𝒔' => 's', '𝒕' => 't', '𝒖' => 'u', '𝒗' => 'v', '𝒘' => 'w', '𝒙' => 'x', '𝒚' => 'y', '𝒛' => 'z', '𝒜' => 'A', '𝒞' => 'C', '𝒟' => 'D', '𝒢' => 'G', '𝒥' => 'J', '𝒦' => 'K', '𝒩' => 'N', '𝒪' => 'O', '𝒫' => 'P', '𝒬' => 'Q', '𝒮' => 'S', '𝒯' => 'T', '𝒰' => 'U', '𝒱' => 'V', '𝒲' => 'W', '𝒳' => 'X', '𝒴' => 'Y', '𝒵' => 'Z', '𝒶' => 'a', '𝒷' => 'b', '𝒸' => 'c', '𝒹' => 'd', '𝒻' => 'f', '𝒽' => 'h', '𝒾' => 'i', '𝒿' => 'j', '𝓀' => 'k', '𝓁' => 'l', '𝓂' => 'm', '𝓃' => 'n', '𝓅' => 'p', '𝓆' => 'q', '𝓇' => 'r', '𝓈' => 's', '𝓉' => 't', '𝓊' => 'u', '𝓋' => 'v', '𝓌' => 'w', '𝓍' => 'x', '𝓎' => 'y', '𝓏' => 'z', '𝓐' => 'A', '𝓑' => 'B', '𝓒' => 'C', '𝓓' => 'D', '𝓔' => 'E', '𝓕' => 'F', '𝓖' => 'G', '𝓗' => 'H', '𝓘' => 'I', '𝓙' => 'J', '𝓚' => 'K', '𝓛' => 'L', '𝓜' => 'M', '𝓝' => 'N', '𝓞' => 'O', '𝓟' => 'P', '𝓠' => 'Q', '𝓡' => 'R', '𝓢' => 'S', '𝓣' => 'T', '𝓤' => 'U', '𝓥' => 'V', '𝓦' => 'W', '𝓧' => 'X', '𝓨' => 'Y', '𝓩' => 'Z', '𝓪' => 'a', '𝓫' => 'b', '𝓬' => 'c', '𝓭' => 'd', '𝓮' => 'e', '𝓯' => 'f', '𝓰' => 'g', '𝓱' => 'h', '𝓲' => 'i', '𝓳' => 'j', '𝓴' => 'k', '𝓵' => 'l', '𝓶' => 'm', '𝓷' => 'n', '𝓸' => 'o', '𝓹' => 'p', '𝓺' => 'q', '𝓻' => 'r', '𝓼' => 's', '𝓽' => 't', '𝓾' => 'u', '𝓿' => 'v', '𝔀' => 'w', '𝔁' => 'x', '𝔂' => 'y', '𝔃' => 'z', '𝔄' => 'A', '𝔅' => 'B', '𝔇' => 'D', '𝔈' => 'E', '𝔉' => 'F', '𝔊' => 'G', '𝔍' => 'J', '𝔎' => 'K', '𝔏' => 'L', '𝔐' => 'M', '𝔑' => 'N', '𝔒' => 'O', '𝔓' => 'P', '𝔔' => 'Q', '𝔖' => 'S', '𝔗' => 'T', '𝔘' => 'U', '𝔙' => 'V', '𝔚' => 'W', '𝔛' => 'X', '𝔜' => 'Y', '𝔞' => 'a', '𝔟' => 'b', '𝔠' => 'c', '𝔡' => 'd', '𝔢' => 'e', '𝔣' => 'f', '𝔤' => 'g', '𝔥' => 'h', '𝔦' => 'i', '𝔧' => 'j', '𝔨' => 'k', '𝔩' => 'l', '𝔪' => 'm', '𝔫' => 'n', '𝔬' => 'o', '𝔭' => 'p', '𝔮' => 'q', '𝔯' => 'r', '𝔰' => 's', '𝔱' => 't', '𝔲' => 'u', '𝔳' => 'v', '𝔴' => 'w', '𝔵' => 'x', '𝔶' => 'y', '𝔷' => 'z', '𝔸' => 'A', '𝔹' => 'B', '𝔻' => 'D', '𝔼' => 'E', '𝔽' => 'F', '𝔾' => 'G', '𝕀' => 'I', '𝕁' => 'J', '𝕂' => 'K', '𝕃' => 'L', '𝕄' => 'M', '𝕆' => 'O', '𝕊' => 'S', '𝕋' => 'T', '𝕌' => 'U', '𝕍' => 'V', '𝕎' => 'W', '𝕏' => 'X', '𝕐' => 'Y', '𝕒' => 'a', '𝕓' => 'b', '𝕔' => 'c', '𝕕' => 'd', '𝕖' => 'e', '𝕗' => 'f', '𝕘' => 'g', '𝕙' => 'h', '𝕚' => 'i', '𝕛' => 'j', '𝕜' => 'k', '𝕝' => 'l', '𝕞' => 'm', '𝕟' => 'n', '𝕠' => 'o', '𝕡' => 'p', '𝕢' => 'q', '𝕣' => 'r', '𝕤' => 's', '𝕥' => 't', '𝕦' => 'u', '𝕧' => 'v', '𝕨' => 'w', '𝕩' => 'x', '𝕪' => 'y', '𝕫' => 'z', '𝕬' => 'A', '𝕭' => 'B', '𝕮' => 'C', '𝕯' => 'D', '𝕰' => 'E', '𝕱' => 'F', '𝕲' => 'G', '𝕳' => 'H', '𝕴' => 'I', '𝕵' => 'J', '𝕶' => 'K', '𝕷' => 'L', '𝕸' => 'M', '𝕹' => 'N', '𝕺' => 'O', '𝕻' => 'P', '𝕼' => 'Q', '𝕽' => 'R', '𝕾' => 'S', '𝕿' => 'T', '𝖀' => 'U', '𝖁' => 'V', '𝖂' => 'W', '𝖃' => 'X', '𝖄' => 'Y', '𝖅' => 'Z', '𝖆' => 'a', '𝖇' => 'b', '𝖈' => 'c', '𝖉' => 'd', '𝖊' => 'e', '𝖋' => 'f', '𝖌' => 'g', '𝖍' => 'h', '𝖎' => 'i', '𝖏' => 'j', '𝖐' => 'k', '𝖑' => 'l', '𝖒' => 'm', '𝖓' => 'n', '𝖔' => 'o', '𝖕' => 'p', '𝖖' => 'q', '𝖗' => 'r', '𝖘' => 's', '𝖙' => 't', '𝖚' => 'u', '𝖛' => 'v', '𝖜' => 'w', '𝖝' => 'x', '𝖞' => 'y', '𝖟' => 'z', '𝖠' => 'A', '𝖡' => 'B', '𝖢' => 'C', '𝖣' => 'D', '𝖤' => 'E', '𝖥' => 'F', '𝖦' => 'G', '𝖧' => 'H', '𝖨' => 'I', '𝖩' => 'J', '𝖪' => 'K', '𝖫' => 'L', '𝖬' => 'M', '𝖭' => 'N', '𝖮' => 'O', '𝖯' => 'P', '𝖰' => 'Q', '𝖱' => 'R', '𝖲' => 'S', '𝖳' => 'T', '𝖴' => 'U', '𝖵' => 'V', '𝖶' => 'W', '𝖷' => 'X', '𝖸' => 'Y', '𝖹' => 'Z', '𝖺' => 'a', '𝖻' => 'b', '𝖼' => 'c', '𝖽' => 'd', '𝖾' => 'e', '𝖿' => 'f', '𝗀' => 'g', '𝗁' => 'h', '𝗂' => 'i', '𝗃' => 'j', '𝗄' => 'k', '𝗅' => 'l', '𝗆' => 'm', '𝗇' => 'n', '𝗈' => 'o', '𝗉' => 'p', '𝗊' => 'q', '𝗋' => 'r', '𝗌' => 's', '𝗍' => 't', '𝗎' => 'u', '𝗏' => 'v', '𝗐' => 'w', '𝗑' => 'x', '𝗒' => 'y', '𝗓' => 'z', '𝗔' => 'A', '𝗕' => 'B', '𝗖' => 'C', '𝗗' => 'D', '𝗘' => 'E', '𝗙' => 'F', '𝗚' => 'G', '𝗛' => 'H', '𝗜' => 'I', '𝗝' => 'J', '𝗞' => 'K', '𝗟' => 'L', '𝗠' => 'M', '𝗡' => 'N', '𝗢' => 'O', '𝗣' => 'P', '𝗤' => 'Q', '𝗥' => 'R', '𝗦' => 'S', '𝗧' => 'T', '𝗨' => 'U', '𝗩' => 'V', '𝗪' => 'W', '𝗫' => 'X', '𝗬' => 'Y', '𝗭' => 'Z', '𝗮' => 'a', '𝗯' => 'b', '𝗰' => 'c', '𝗱' => 'd', '𝗲' => 'e', '𝗳' => 'f', '𝗴' => 'g', '𝗵' => 'h', '𝗶' => 'i', '𝗷' => 'j', '𝗸' => 'k', '𝗹' => 'l', '𝗺' => 'm', '𝗻' => 'n', '𝗼' => 'o', '𝗽' => 'p', '𝗾' => 'q', '𝗿' => 'r', '𝘀' => 's', '𝘁' => 't', '𝘂' => 'u', '𝘃' => 'v', '𝘄' => 'w', '𝘅' => 'x', '𝘆' => 'y', '𝘇' => 'z', '𝘈' => 'A', '𝘉' => 'B', '𝘊' => 'C', '𝘋' => 'D', '𝘌' => 'E', '𝘍' => 'F', '𝘎' => 'G', '𝘏' => 'H', '𝘐' => 'I', '𝘑' => 'J', '𝘒' => 'K', '𝘓' => 'L', '𝘔' => 'M', '𝘕' => 'N', '𝘖' => 'O', '𝘗' => 'P', '𝘘' => 'Q', '𝘙' => 'R', '𝘚' => 'S', '𝘛' => 'T', '𝘜' => 'U', '𝘝' => 'V', '𝘞' => 'W', '𝘟' => 'X', '𝘠' => 'Y', '𝘡' => 'Z', '𝘢' => 'a', '𝘣' => 'b', '𝘤' => 'c', '𝘥' => 'd', '𝘦' => 'e', '𝘧' => 'f', '𝘨' => 'g', '𝘩' => 'h', '𝘪' => 'i', '𝘫' => 'j', '𝘬' => 'k', '𝘭' => 'l', '𝘮' => 'm', '𝘯' => 'n', '𝘰' => 'o', '𝘱' => 'p', '𝘲' => 'q', '𝘳' => 'r', '𝘴' => 's', '𝘵' => 't', '𝘶' => 'u', '𝘷' => 'v', '𝘸' => 'w', '𝘹' => 'x', '𝘺' => 'y', '𝘻' => 'z', '𝘼' => 'A', '𝘽' => 'B', '𝘾' => 'C', '𝘿' => 'D', '𝙀' => 'E', '𝙁' => 'F', '𝙂' => 'G', '𝙃' => 'H', '𝙄' => 'I', '𝙅' => 'J', '𝙆' => 'K', '𝙇' => 'L', '𝙈' => 'M', '𝙉' => 'N', '𝙊' => 'O', '𝙋' => 'P', '𝙌' => 'Q', '𝙍' => 'R', '𝙎' => 'S', '𝙏' => 'T', '𝙐' => 'U', '𝙑' => 'V', '𝙒' => 'W', '𝙓' => 'X', '𝙔' => 'Y', '𝙕' => 'Z', '𝙖' => 'a', '𝙗' => 'b', '𝙘' => 'c', '𝙙' => 'd', '𝙚' => 'e', '𝙛' => 'f', '𝙜' => 'g', '𝙝' => 'h', '𝙞' => 'i', '𝙟' => 'j', '𝙠' => 'k', '𝙡' => 'l', '𝙢' => 'm', '𝙣' => 'n', '𝙤' => 'o', '𝙥' => 'p', '𝙦' => 'q', '𝙧' => 'r', '𝙨' => 's', '𝙩' => 't', '𝙪' => 'u', '𝙫' => 'v', '𝙬' => 'w', '𝙭' => 'x', '𝙮' => 'y', '𝙯' => 'z', '𝙰' => 'A', '𝙱' => 'B', '𝙲' => 'C', '𝙳' => 'D', '𝙴' => 'E', '𝙵' => 'F', '𝙶' => 'G', '𝙷' => 'H', '𝙸' => 'I', '𝙹' => 'J', '𝙺' => 'K', '𝙻' => 'L', '𝙼' => 'M', '𝙽' => 'N', '𝙾' => 'O', '𝙿' => 'P', '𝚀' => 'Q', '𝚁' => 'R', '𝚂' => 'S', '𝚃' => 'T', '𝚄' => 'U', '𝚅' => 'V', '𝚆' => 'W', '𝚇' => 'X', '𝚈' => 'Y', '𝚉' => 'Z', '𝚊' => 'a', '𝚋' => 'b', '𝚌' => 'c', '𝚍' => 'd', '𝚎' => 'e', '𝚏' => 'f', '𝚐' => 'g', '𝚑' => 'h', '𝚒' => 'i', '𝚓' => 'j', '𝚔' => 'k', '𝚕' => 'l', '𝚖' => 'm', '𝚗' => 'n', '𝚘' => 'o', '𝚙' => 'p', '𝚚' => 'q', '𝚛' => 'r', '𝚜' => 's', '𝚝' => 't', '𝚞' => 'u', '𝚟' => 'v', '𝚠' => 'w', '𝚡' => 'x', '𝚢' => 'y', '𝚣' => 'z', '𝚤' => 'ı', '𝚥' => 'ȷ', '𝚨' => 'Α', '𝚩' => 'Β', '𝚪' => 'Γ', '𝚫' => 'Δ', '𝚬' => 'Ε', '𝚭' => 'Ζ', '𝚮' => 'Η', '𝚯' => 'Θ', '𝚰' => 'Ι', '𝚱' => 'Κ', '𝚲' => 'Λ', '𝚳' => 'Μ', '𝚴' => 'Ν', '𝚵' => 'Ξ', '𝚶' => 'Ο', '𝚷' => 'Π', '𝚸' => 'Ρ', '𝚹' => 'Θ', '𝚺' => 'Σ', '𝚻' => 'Τ', '𝚼' => 'Υ', '𝚽' => 'Φ', '𝚾' => 'Χ', '𝚿' => 'Ψ', '𝛀' => 'Ω', '𝛁' => '∇', '𝛂' => 'α', '𝛃' => 'β', '𝛄' => 'γ', '𝛅' => 'δ', '𝛆' => 'ε', '𝛇' => 'ζ', '𝛈' => 'η', '𝛉' => 'θ', '𝛊' => 'ι', '𝛋' => 'κ', '𝛌' => 'λ', '𝛍' => 'μ', '𝛎' => 'ν', '𝛏' => 'ξ', '𝛐' => 'ο', '𝛑' => 'π', '𝛒' => 'ρ', '𝛓' => 'ς', '𝛔' => 'σ', '𝛕' => 'τ', '𝛖' => 'υ', '𝛗' => 'φ', '𝛘' => 'χ', '𝛙' => 'ψ', '𝛚' => 'ω', '𝛛' => '∂', '𝛜' => 'ε', '𝛝' => 'θ', '𝛞' => 'κ', '𝛟' => 'φ', '𝛠' => 'ρ', '𝛡' => 'π', '𝛢' => 'Α', '𝛣' => 'Β', '𝛤' => 'Γ', '𝛥' => 'Δ', '𝛦' => 'Ε', '𝛧' => 'Ζ', '𝛨' => 'Η', '𝛩' => 'Θ', '𝛪' => 'Ι', '𝛫' => 'Κ', '𝛬' => 'Λ', '𝛭' => 'Μ', '𝛮' => 'Ν', '𝛯' => 'Ξ', '𝛰' => 'Ο', '𝛱' => 'Π', '𝛲' => 'Ρ', '𝛳' => 'Θ', '𝛴' => 'Σ', '𝛵' => 'Τ', '𝛶' => 'Υ', '𝛷' => 'Φ', '𝛸' => 'Χ', '𝛹' => 'Ψ', '𝛺' => 'Ω', '𝛻' => '∇', '𝛼' => 'α', '𝛽' => 'β', '𝛾' => 'γ', '𝛿' => 'δ', '𝜀' => 'ε', '𝜁' => 'ζ', '𝜂' => 'η', '𝜃' => 'θ', '𝜄' => 'ι', '𝜅' => 'κ', '𝜆' => 'λ', '𝜇' => 'μ', '𝜈' => 'ν', '𝜉' => 'ξ', '𝜊' => 'ο', '𝜋' => 'π', '𝜌' => 'ρ', '𝜍' => 'ς', '𝜎' => 'σ', '𝜏' => 'τ', '𝜐' => 'υ', '𝜑' => 'φ', '𝜒' => 'χ', '𝜓' => 'ψ', '𝜔' => 'ω', '𝜕' => '∂', '𝜖' => 'ε', '𝜗' => 'θ', '𝜘' => 'κ', '𝜙' => 'φ', '𝜚' => 'ρ', '𝜛' => 'π', '𝜜' => 'Α', '𝜝' => 'Β', '𝜞' => 'Γ', '𝜟' => 'Δ', '𝜠' => 'Ε', '𝜡' => 'Ζ', '𝜢' => 'Η', '𝜣' => 'Θ', '𝜤' => 'Ι', '𝜥' => 'Κ', '𝜦' => 'Λ', '𝜧' => 'Μ', '𝜨' => 'Ν', '𝜩' => 'Ξ', '𝜪' => 'Ο', '𝜫' => 'Π', '𝜬' => 'Ρ', '𝜭' => 'Θ', '𝜮' => 'Σ', '𝜯' => 'Τ', '𝜰' => 'Υ', '𝜱' => 'Φ', '𝜲' => 'Χ', '𝜳' => 'Ψ', '𝜴' => 'Ω', '𝜵' => '∇', '𝜶' => 'α', '𝜷' => 'β', '𝜸' => 'γ', '𝜹' => 'δ', '𝜺' => 'ε', '𝜻' => 'ζ', '𝜼' => 'η', '𝜽' => 'θ', '𝜾' => 'ι', '𝜿' => 'κ', '𝝀' => 'λ', '𝝁' => 'μ', '𝝂' => 'ν', '𝝃' => 'ξ', '𝝄' => 'ο', '𝝅' => 'π', '𝝆' => 'ρ', '𝝇' => 'ς', '𝝈' => 'σ', '𝝉' => 'τ', '𝝊' => 'υ', '𝝋' => 'φ', '𝝌' => 'χ', '𝝍' => 'ψ', '𝝎' => 'ω', '𝝏' => '∂', '𝝐' => 'ε', '𝝑' => 'θ', '𝝒' => 'κ', '𝝓' => 'φ', '𝝔' => 'ρ', '𝝕' => 'π', '𝝖' => 'Α', '𝝗' => 'Β', '𝝘' => 'Γ', '𝝙' => 'Δ', '𝝚' => 'Ε', '𝝛' => 'Ζ', '𝝜' => 'Η', '𝝝' => 'Θ', '𝝞' => 'Ι', '𝝟' => 'Κ', '𝝠' => 'Λ', '𝝡' => 'Μ', '𝝢' => 'Ν', '𝝣' => 'Ξ', '𝝤' => 'Ο', '𝝥' => 'Π', '𝝦' => 'Ρ', '𝝧' => 'Θ', '𝝨' => 'Σ', '𝝩' => 'Τ', '𝝪' => 'Υ', '𝝫' => 'Φ', '𝝬' => 'Χ', '𝝭' => 'Ψ', '𝝮' => 'Ω', '𝝯' => '∇', '𝝰' => 'α', '𝝱' => 'β', '𝝲' => 'γ', '𝝳' => 'δ', '𝝴' => 'ε', '𝝵' => 'ζ', '𝝶' => 'η', '𝝷' => 'θ', '𝝸' => 'ι', '𝝹' => 'κ', '𝝺' => 'λ', '𝝻' => 'μ', '𝝼' => 'ν', '𝝽' => 'ξ', '𝝾' => 'ο', '𝝿' => 'π', '𝞀' => 'ρ', '𝞁' => 'ς', '𝞂' => 'σ', '𝞃' => 'τ', '𝞄' => 'υ', '𝞅' => 'φ', '𝞆' => 'χ', '𝞇' => 'ψ', '𝞈' => 'ω', '𝞉' => '∂', '𝞊' => 'ε', '𝞋' => 'θ', '𝞌' => 'κ', '𝞍' => 'φ', '𝞎' => 'ρ', '𝞏' => 'π', '𝞐' => 'Α', '𝞑' => 'Β', '𝞒' => 'Γ', '𝞓' => 'Δ', '𝞔' => 'Ε', '𝞕' => 'Ζ', '𝞖' => 'Η', '𝞗' => 'Θ', '𝞘' => 'Ι', '𝞙' => 'Κ', '𝞚' => 'Λ', '𝞛' => 'Μ', '𝞜' => 'Ν', '𝞝' => 'Ξ', '𝞞' => 'Ο', '𝞟' => 'Π', '𝞠' => 'Ρ', '𝞡' => 'Θ', '𝞢' => 'Σ', '𝞣' => 'Τ', '𝞤' => 'Υ', '𝞥' => 'Φ', '𝞦' => 'Χ', '𝞧' => 'Ψ', '𝞨' => 'Ω', '𝞩' => '∇', '𝞪' => 'α', '𝞫' => 'β', '𝞬' => 'γ', '𝞭' => 'δ', '𝞮' => 'ε', '𝞯' => 'ζ', '𝞰' => 'η', '𝞱' => 'θ', '𝞲' => 'ι', '𝞳' => 'κ', '𝞴' => 'λ', '𝞵' => 'μ', '𝞶' => 'ν', '𝞷' => 'ξ', '𝞸' => 'ο', '𝞹' => 'π', '𝞺' => 'ρ', '𝞻' => 'ς', '𝞼' => 'σ', '𝞽' => 'τ', '𝞾' => 'υ', '𝞿' => 'φ', '𝟀' => 'χ', '𝟁' => 'ψ', '𝟂' => 'ω', '𝟃' => '∂', '𝟄' => 'ε', '𝟅' => 'θ', '𝟆' => 'κ', '𝟇' => 'φ', '𝟈' => 'ρ', '𝟉' => 'π', '𝟊' => 'Ϝ', '𝟋' => 'ϝ', '𝟎' => '0', '𝟏' => '1', '𝟐' => '2', '𝟑' => '3', '𝟒' => '4', '𝟓' => '5', '𝟔' => '6', '𝟕' => '7', '𝟖' => '8', '𝟗' => '9', '𝟘' => '0', '𝟙' => '1', '𝟚' => '2', '𝟛' => '3', '𝟜' => '4', '𝟝' => '5', '𝟞' => '6', '𝟟' => '7', '𝟠' => '8', '𝟡' => '9', '𝟢' => '0', '𝟣' => '1', '𝟤' => '2', '𝟥' => '3', '𝟦' => '4', '𝟧' => '5', '𝟨' => '6', '𝟩' => '7', '𝟪' => '8', '𝟫' => '9', '𝟬' => '0', '𝟭' => '1', '𝟮' => '2', '𝟯' => '3', '𝟰' => '4', '𝟱' => '5', '𝟲' => '6', '𝟳' => '7', '𝟴' => '8', '𝟵' => '9', '𝟶' => '0', '𝟷' => '1', '𝟸' => '2', '𝟹' => '3', '𝟺' => '4', '𝟻' => '5', '𝟼' => '6', '𝟽' => '7', '𝟾' => '8', '𝟿' => '9', '𞸀' => 'ا', '𞸁' => 'ب', '𞸂' => 'ج', '𞸃' => 'د', '𞸅' => 'و', '𞸆' => 'ز', '𞸇' => 'ح', '𞸈' => 'ط', '𞸉' => 'ي', '𞸊' => 'ك', '𞸋' => 'ل', '𞸌' => 'م', '𞸍' => 'ن', '𞸎' => 'س', '𞸏' => 'ع', '𞸐' => 'ف', '𞸑' => 'ص', '𞸒' => 'ق', '𞸓' => 'ر', '𞸔' => 'ش', '𞸕' => 'ت', '𞸖' => 'ث', '𞸗' => 'خ', '𞸘' => 'ذ', '𞸙' => 'ض', '𞸚' => 'ظ', '𞸛' => 'غ', '𞸜' => 'ٮ', '𞸝' => 'ں', '𞸞' => 'ڡ', '𞸟' => 'ٯ', '𞸡' => 'ب', '𞸢' => 'ج', '𞸤' => 'ه', '𞸧' => 'ح', '𞸩' => 'ي', '𞸪' => 'ك', '𞸫' => 'ل', '𞸬' => 'م', '𞸭' => 'ن', '𞸮' => 'س', '𞸯' => 'ع', '𞸰' => 'ف', '𞸱' => 'ص', '𞸲' => 'ق', '𞸴' => 'ش', '𞸵' => 'ت', '𞸶' => 'ث', '𞸷' => 'خ', '𞸹' => 'ض', '𞸻' => 'غ', '𞹂' => 'ج', '𞹇' => 'ح', '𞹉' => 'ي', '𞹋' => 'ل', '𞹍' => 'ن', '𞹎' => 'س', '𞹏' => 'ع', '𞹑' => 'ص', '𞹒' => 'ق', '𞹔' => 'ش', '𞹗' => 'خ', '𞹙' => 'ض', '𞹛' => 'غ', '𞹝' => 'ں', '𞹟' => 'ٯ', '𞹡' => 'ب', '𞹢' => 'ج', '𞹤' => 'ه', '𞹧' => 'ح', '𞹨' => 'ط', '𞹩' => 'ي', '𞹪' => 'ك', '𞹬' => 'م', '𞹭' => 'ن', '𞹮' => 'س', '𞹯' => 'ع', '𞹰' => 'ف', '𞹱' => 'ص', '𞹲' => 'ق', '𞹴' => 'ش', '𞹵' => 'ت', '𞹶' => 'ث', '𞹷' => 'خ', '𞹹' => 'ض', '𞹺' => 'ظ', '𞹻' => 'غ', '𞹼' => 'ٮ', '𞹾' => 'ڡ', '𞺀' => 'ا', '𞺁' => 'ب', '𞺂' => 'ج', '𞺃' => 'د', '𞺄' => 'ه', '𞺅' => 'و', '𞺆' => 'ز', '𞺇' => 'ح', '𞺈' => 'ط', '𞺉' => 'ي', '𞺋' => 'ل', '𞺌' => 'م', '𞺍' => 'ن', '𞺎' => 'س', '𞺏' => 'ع', '𞺐' => 'ف', '𞺑' => 'ص', '𞺒' => 'ق', '𞺓' => 'ر', '𞺔' => 'ش', '𞺕' => 'ت', '𞺖' => 'ث', '𞺗' => 'خ', '𞺘' => 'ذ', '𞺙' => 'ض', '𞺚' => 'ظ', '𞺛' => 'غ', '𞺡' => 'ب', '𞺢' => 'ج', '𞺣' => 'د', '𞺥' => 'و', '𞺦' => 'ز', '𞺧' => 'ح', '𞺨' => 'ط', '𞺩' => 'ي', '𞺫' => 'ل', '𞺬' => 'م', '𞺭' => 'ن', '𞺮' => 'س', '𞺯' => 'ع', '𞺰' => 'ف', '𞺱' => 'ص', '𞺲' => 'ق', '𞺳' => 'ر', '𞺴' => 'ش', '𞺵' => 'ت', '𞺶' => 'ث', '𞺷' => 'خ', '𞺸' => 'ذ', '𞺹' => 'ض', '𞺺' => 'ظ', '𞺻' => 'غ', '🄀' => '0.', '🄁' => '0,', '🄂' => '1,', '🄃' => '2,', '🄄' => '3,', '🄅' => '4,', '🄆' => '5,', '🄇' => '6,', '🄈' => '7,', '🄉' => '8,', '🄊' => '9,', '🄐' => '(A)', '🄑' => '(B)', '🄒' => '(C)', '🄓' => '(D)', '🄔' => '(E)', '🄕' => '(F)', '🄖' => '(G)', '🄗' => '(H)', '🄘' => '(I)', '🄙' => '(J)', '🄚' => '(K)', '🄛' => '(L)', '🄜' => '(M)', '🄝' => '(N)', '🄞' => '(O)', '🄟' => '(P)', '🄠' => '(Q)', '🄡' => '(R)', '🄢' => '(S)', '🄣' => '(T)', '🄤' => '(U)', '🄥' => '(V)', '🄦' => '(W)', '🄧' => '(X)', '🄨' => '(Y)', '🄩' => '(Z)', '🄪' => '〔S〕', '🄫' => 'C', '🄬' => 'R', '🄭' => 'CD', '🄮' => 'WZ', '🄰' => 'A', '🄱' => 'B', '🄲' => 'C', '🄳' => 'D', '🄴' => 'E', '🄵' => 'F', '🄶' => 'G', '🄷' => 'H', '🄸' => 'I', '🄹' => 'J', '🄺' => 'K', '🄻' => 'L', '🄼' => 'M', '🄽' => 'N', '🄾' => 'O', '🄿' => 'P', '🅀' => 'Q', '🅁' => 'R', '🅂' => 'S', '🅃' => 'T', '🅄' => 'U', '🅅' => 'V', '🅆' => 'W', '🅇' => 'X', '🅈' => 'Y', '🅉' => 'Z', '🅊' => 'HV', '🅋' => 'MV', '🅌' => 'SD', '🅍' => 'SS', '🅎' => 'PPV', '🅏' => 'WC', '🅪' => 'MC', '🅫' => 'MD', '🅬' => 'MR', '🆐' => 'DJ', '🈀' => 'ほか', '🈁' => 'ココ', '🈂' => 'サ', '🈐' => '手', '🈑' => '字', '🈒' => '双', '🈓' => 'デ', '🈔' => '二', '🈕' => '多', '🈖' => '解', '🈗' => '天', '🈘' => '交', '🈙' => '映', '🈚' => '無', '🈛' => '料', '🈜' => '前', '🈝' => '後', '🈞' => '再', '🈟' => '新', '🈠' => '初', '🈡' => '終', '🈢' => '生', '🈣' => '販', '🈤' => '声', '🈥' => '吹', '🈦' => '演', '🈧' => '投', '🈨' => '捕', '🈩' => '一', '🈪' => '三', '🈫' => '遊', '🈬' => '左', '🈭' => '中', '🈮' => '右', '🈯' => '指', '🈰' => '走', '🈱' => '打', '🈲' => '禁', '🈳' => '空', '🈴' => '合', '🈵' => '満', '🈶' => '有', '🈷' => '月', '🈸' => '申', '🈹' => '割', '🈺' => '営', '🈻' => '配', '🉀' => '〔本〕', '🉁' => '〔三〕', '🉂' => '〔二〕', '🉃' => '〔安〕', '🉄' => '〔点〕', '🉅' => '〔打〕', '🉆' => '〔盗〕', '🉇' => '〔勝〕', '🉈' => '〔敗〕', '🉐' => '得', '🉑' => '可', '🯰' => '0', '🯱' => '1', '🯲' => '2', '🯳' => '3', '🯴' => '4', '🯵' => '5', '🯶' => '6', '🯷' => '7', '🯸' => '8', '🯹' => '9');
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

use Symfony\Polyfill\Intl\Normalizer as p;

if (\PHP_VERSION_ID >= 80000) {
    return require __DIR__.'/bootstrap80.php';
}

if (!function_exists('normalizer_is_normalized')) {
    function normalizer_is_normalized($string, $form = p\Normalizer::FORM_C) { return p\Normalizer::isNormalized($string, $form); }
}
if (!function_exists('normalizer_normalize')) {
    function normalizer_normalize($string, $form = p\Normalizer::FORM_C) { return p\Normalizer::normalize($string, $form); }
}
Symfony Polyfill / Intl: Normalizer
===================================

This component provides a fallback implementation for the
[`Normalizer`](https://php.net/Normalizer) class provided
by the [Intl](https://php.net/intl) extension.

More information can be found in the
[main Polyfill README](https://github.com/symfony/polyfill/blob/main/README.md).

License
=======

This library is released under the [MIT license](LICENSE).
{
    "name": "symfony\/polyfill-intl-normalizer",
    "type": "library",
    "description": "Symfony polyfill for intl's Normalizer class and related functions",
    "keywords": [
        "polyfill",
        "shim",
        "compatibility",
        "portable",
        "intl",
        "normalizer"
    ],
    "homepage": "https:\/\/symfony.com",
    "license": "MIT",
    "authors": [
        {
            "name": "Nicolas Grekas",
            "email": "p@tchwork.com"
        },
        {
            "name": "Symfony Community",
            "homepage": "https:\/\/symfony.com\/contributors"
        }
    ],
    "require": {
        "php": ">=7.2"
    },
    "autoload": {
        "psr-4": {
            "Symfony\\Polyfill\\Intl\\Normalizer\\": ""
        },
        "files": [
            "bootstrap.php"
        ],
        "classmap": [
            "Resources\/stubs"
        ]
    },
    "suggest": {
        "ext-intl": "For best performance"
    },
    "minimum-stability": "dev",
    "extra": {
        "thanks": {
            "name": "symfony\/polyfill",
            "url": "https:\/\/github.com\/symfony\/polyfill"
        }
    }
}<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Contracts\EventDispatcher;

use _ContaoManager\Psr\EventDispatcher\EventDispatcherInterface as PsrEventDispatcherInterface;
/**
 * Allows providing hooks on domain-specific lifecycles by dispatching events.
 */
interface EventDispatcherInterface extends PsrEventDispatcherInterface
{
    /**
     * Dispatches an event to all registered listeners.
     *
     * @template T of object
     *
     * @param T           $event     The event to pass to the event handlers/listeners
     * @param string|null $eventName The name of the event to dispatch. If not supplied,
     *                               the class of $event should be used instead.
     *
     * @return T The passed $event MUST be returned
     */
    public function dispatch(object $event, ?string $eventName = null): object;
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Contracts\EventDispatcher;

use _ContaoManager\Psr\EventDispatcher\StoppableEventInterface;
/**
 * Event is the base class for classes containing event data.
 *
 * This class contains no event data. It is used by events that do not pass
 * state information to an event handler when an event is raised.
 *
 * You can call the method stopPropagation() to abort the execution of
 * further listeners in your event listener.
 *
 * @author Guilherme Blanco <guilhermeblanco@hotmail.com>
 * @author Jonathan Wage <jonwage@gmail.com>
 * @author Roman Borschel <roman@code-factory.org>
 * @author Bernhard Schussek <bschussek@gmail.com>
 * @author Nicolas Grekas <p@tchwork.com>
 */
class Event implements StoppableEventInterface
{
    private bool $propagationStopped = \false;
    public function isPropagationStopped(): bool
    {
        return $this->propagationStopped;
    }
    /**
     * Stops the propagation of the event to further event listeners.
     *
     * If multiple event listeners are connected to the same event, no
     * further event listener will be triggered once any trigger calls
     * stopPropagation().
     */
    public function stopPropagation(): void
    {
        $this->propagationStopped = \true;
    }
}
Copyright (c) 2018-present Fabien Potencier

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is furnished
to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
CHANGELOG
=========

The changelog is maintained for all Symfony contracts at the following URL:
https://github.com/symfony/contracts/blob/main/CHANGELOG.md
Symfony EventDispatcher Contracts
=================================

A set of abstractions extracted out of the Symfony components.

Can be used to build on semantics that the Symfony components proved useful and
that already have battle tested implementations.

See https://github.com/symfony/contracts/blob/main/README.md for more information.
{
    "name": "symfony\/event-dispatcher-contracts",
    "type": "library",
    "description": "Generic abstractions related to dispatching event",
    "keywords": [
        "abstractions",
        "contracts",
        "decoupling",
        "interfaces",
        "interoperability",
        "standards"
    ],
    "homepage": "https:\/\/symfony.com",
    "license": "MIT",
    "authors": [
        {
            "name": "Nicolas Grekas",
            "email": "p@tchwork.com"
        },
        {
            "name": "Symfony Community",
            "homepage": "https:\/\/symfony.com\/contributors"
        }
    ],
    "require": {
        "php": ">=8.1",
        "psr\/event-dispatcher": "^1"
    },
    "autoload": {
        "psr-4": {
            "_ContaoManager\\Symfony\\Contracts\\EventDispatcher\\": ""
        }
    },
    "minimum-stability": "dev",
    "extra": {
        "branch-alias": {
            "dev-main": "3.6-dev"
        },
        "thanks": {
            "name": "symfony\/contracts",
            "url": "https:\/\/github.com\/symfony\/contracts"
        }
    }
}<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\PropertyAccess;

/**
 * A sequence of property names or array indices.
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 *
 * @method bool isNullSafe(int $index) Returns whether the element at the given index is null safe. Not implementing it is deprecated since Symfony 6.2
 *
 * @extends \Traversable<int, string>
 */
interface PropertyPathInterface extends \Traversable, \Stringable
{
    /**
     * Returns the string representation of the property path.
     */
    public function __toString(): string;
    /**
     * Returns the length of the property path, i.e. the number of elements.
     *
     * @return int
     */
    public function getLength();
    /**
     * Returns the parent property path.
     *
     * The parent property path is the one that contains the same items as
     * this one except for the last one.
     *
     * If this property path only contains one item, null is returned.
     *
     * @return self|null
     */
    public function getParent();
    /**
     * Returns the elements of the property path as array.
     *
     * @return list<string>
     */
    public function getElements();
    /**
     * Returns the element at the given index in the property path.
     *
     * @param int $index The index key
     *
     * @return string
     *
     * @throws Exception\OutOfBoundsException If the offset is invalid
     */
    public function getElement(int $index);
    /**
     * Returns whether the element at the given index is a property.
     *
     * @param int $index The index in the property path
     *
     * @return bool
     *
     * @throws Exception\OutOfBoundsException If the offset is invalid
     */
    public function isProperty(int $index);
    /**
     * Returns whether the element at the given index is an array index.
     *
     * @param int $index The index in the property path
     *
     * @return bool
     *
     * @throws Exception\OutOfBoundsException If the offset is invalid
     */
    public function isIndex(int $index);
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\PropertyAccess;

/**
 * Traverses a property path and provides additional methods to find out
 * information about the current element.
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 *
 * @extends \ArrayIterator<int, string>
 */
class PropertyPathIterator extends \ArrayIterator implements PropertyPathIteratorInterface
{
    protected $path;
    public function __construct(PropertyPathInterface $path)
    {
        parent::__construct($path->getElements());
        $this->path = $path;
    }
    public function isIndex(): bool
    {
        return $this->path->isIndex($this->key());
    }
    public function isProperty(): bool
    {
        return $this->path->isProperty($this->key());
    }
}
Copyright (c) 2004-present Fabien Potencier

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is furnished
to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\PropertyAccess;

/**
 * @author Bernhard Schussek <bschussek@gmail.com>
 *
 * @extends \SeekableIterator<int, string>
 */
interface PropertyPathIteratorInterface extends \SeekableIterator
{
    /**
     * Returns whether the current element in the property path is an array
     * index.
     */
    public function isIndex(): bool;
    /**
     * Returns whether the current element in the property path is a property
     * name.
     */
    public function isProperty(): bool;
}
CHANGELOG
=========

6.3
---

 * Allow escaping `.` and `[` with `\` in `PropertyPath`

6.2
---

 * Deprecate calling `PropertyAccessorBuilder::setCacheItemPool()` without arguments
 * Added method `isNullSafe()` to `PropertyPathInterface`, implementing the interface without implementing this method
   is deprecated
 * Add support for the null-coalesce operator in property paths

6.0
---

 * make `PropertyAccessor::__construct()` accept a combination of bitwise flags as first and second arguments

5.3.0
-----

 * deprecate passing a boolean as the second argument of `PropertyAccessor::__construct()`, expecting a combination of bitwise flags instead

5.2.0
-----

 * deprecated passing a boolean as the first argument of `PropertyAccessor::__construct()`, expecting a combination of bitwise flags instead
 * added the ability to disable usage of the magic `__get` & `__set` methods

5.1.0
-----

 * Added an `UninitializedPropertyException`
 * Linking to PropertyInfo extractor to remove a lot of duplicate code

4.4.0
-----

 * deprecated passing `null` as `$defaultLifetime` 2nd argument of `PropertyAccessor::createCache()` method,
   pass `0` instead

4.3.0
-----

 * added a `$throwExceptionOnInvalidPropertyPath` argument to the PropertyAccessor constructor.
 * added `enableExceptionOnInvalidPropertyPath()`, `disableExceptionOnInvalidPropertyPath()` and
   `isExceptionOnInvalidPropertyPath()` methods to `PropertyAccessorBuilder`

4.0.0
-----

 * removed the `StringUtil` class, use `Symfony\Component\Inflector\Inflector`

3.1.0
-----

 * deprecated the `StringUtil` class, use `Symfony\Component\Inflector\Inflector`
   instead

2.7.0
------

 * `UnexpectedTypeException` now expects three constructor arguments: The invalid property value,
   the `PropertyPathInterface` object and the current index of the property path.

2.5.0
------

 * allowed non alpha numeric characters in second level and deeper object properties names
 * [BC BREAK] when accessing an index on an object that does not implement
   ArrayAccess, a NoSuchIndexException is now thrown instead of the
   semantically wrong NoSuchPropertyException
 * [BC BREAK] added isReadable() and isWritable() to PropertyAccessorInterface

2.3.0
------

 * added PropertyAccessorBuilder, to enable or disable the support of "__call"
 * added support for "__call" in the PropertyAccessor (disabled by default)
 * [BC BREAK] changed PropertyAccessor to continue its search for a property or
   method even if a non-public match was found. Before, a PropertyAccessDeniedException
   was thrown in this case. Class PropertyAccessDeniedException was removed
   now.
 * deprecated PropertyAccess::getPropertyAccessor
 * added PropertyAccess::createPropertyAccessor and PropertyAccess::createPropertyAccessorBuilder
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\PropertyAccess;

/**
 * Writes and reads values to/from an object/array graph.
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
interface PropertyAccessorInterface
{
    /**
     * Sets the value at the end of the property path of the object graph.
     *
     * Example:
     *
     *     use Symfony\Component\PropertyAccess\PropertyAccess;
     *
     *     $propertyAccessor = PropertyAccess::createPropertyAccessor();
     *
     *     echo $propertyAccessor->setValue($object, 'child.name', 'Fabien');
     *     // equals echo $object->getChild()->setName('Fabien');
     *
     * This method first tries to find a public setter for each property in the
     * path. The name of the setter must be the camel-cased property name
     * prefixed with "set".
     *
     * If the setter does not exist, this method tries to find a public
     * property. The value of the property is then changed.
     *
     * If neither is found, an exception is thrown.
     *
     * @return void
     *
     * @throws Exception\InvalidArgumentException If the property path is invalid
     * @throws Exception\AccessException          If a property/index does not exist or is not public
     * @throws Exception\UnexpectedTypeException  If a value within the path is neither object nor array
     */
    public function setValue(object|array &$objectOrArray, string|PropertyPathInterface $propertyPath, mixed $value);
    /**
     * Returns the value at the end of the property path of the object graph.
     *
     * Example:
     *
     *     use Symfony\Component\PropertyAccess\PropertyAccess;
     *
     *     $propertyAccessor = PropertyAccess::createPropertyAccessor();
     *
     *     echo $propertyAccessor->getValue($object, 'child.name');
     *     // equals echo $object->getChild()->getName();
     *
     * This method first tries to find a public getter for each property in the
     * path. The name of the getter must be the camel-cased property name
     * prefixed with "get", "is", or "has".
     *
     * If the getter does not exist, this method tries to find a public
     * property. The value of the property is then returned.
     *
     * If none of them are found, an exception is thrown.
     *
     * @throws Exception\InvalidArgumentException If the property path is invalid
     * @throws Exception\AccessException          If a property/index does not exist or is not public
     * @throws Exception\UnexpectedTypeException  If a value within the path is neither object
     *                                            nor array
     */
    public function getValue(object|array $objectOrArray, string|PropertyPathInterface $propertyPath): mixed;
    /**
     * Returns whether a value can be written at a given property path.
     *
     * Whenever this method returns true, {@link setValue()} is guaranteed not
     * to throw an exception when called with the same arguments.
     *
     * @throws Exception\InvalidArgumentException If the property path is invalid
     */
    public function isWritable(object|array $objectOrArray, string|PropertyPathInterface $propertyPath): bool;
    /**
     * Returns whether a property path can be read from an object graph.
     *
     * Whenever this method returns true, {@link getValue()} is guaranteed not
     * to throw an exception when called with the same arguments.
     *
     * @throws Exception\InvalidArgumentException If the property path is invalid
     */
    public function isReadable(object|array $objectOrArray, string|PropertyPathInterface $propertyPath): bool;
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\PropertyAccess;

use _ContaoManager\Symfony\Component\PropertyAccess\Exception\InvalidArgumentException;
use _ContaoManager\Symfony\Component\PropertyAccess\Exception\InvalidPropertyPathException;
use _ContaoManager\Symfony\Component\PropertyAccess\Exception\OutOfBoundsException;
/**
 * Default implementation of {@link PropertyPathInterface}.
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 *
 * @implements \IteratorAggregate<int, string>
 */
class PropertyPath implements \IteratorAggregate, PropertyPathInterface
{
    /**
     * Character used for separating between plural and singular of an element.
     */
    public const SINGULAR_SEPARATOR = '|';
    /**
     * The elements of the property path.
     *
     * @var list<string>
     */
    private array $elements = [];
    /**
     * The number of elements in the property path.
     */
    private int $length;
    /**
     * Contains a Boolean for each property in $elements denoting whether this
     * element is an index. It is a property otherwise.
     *
     * @var array<bool>
     */
    private array $isIndex = [];
    /**
     * Contains a Boolean for each property in $elements denoting whether this
     * element is optional or not.
     *
     * @var array<bool>
     */
    private array $isNullSafe = [];
    /**
     * String representation of the path.
     */
    private string $pathAsString;
    /**
     * Constructs a property path from a string.
     *
     * @throws InvalidArgumentException     If the given path is not a string
     * @throws InvalidPropertyPathException If the syntax of the property path is not valid
     */
    public function __construct(self|string $propertyPath)
    {
        // Can be used as copy constructor
        if ($propertyPath instanceof self) {
            $this->elements = $propertyPath->elements;
            $this->length = $propertyPath->length;
            $this->isIndex = $propertyPath->isIndex;
            $this->isNullSafe = $propertyPath->isNullSafe;
            $this->pathAsString = $propertyPath->pathAsString;
            return;
        }
        if ('' === $propertyPath) {
            throw new InvalidPropertyPathException('The property path should not be empty.');
        }
        $this->pathAsString = $propertyPath;
        $position = 0;
        $remaining = $propertyPath;
        // first element is evaluated differently - no leading dot for properties
        $pattern = '/^(((?:[^\\\\.\[]|\\\\.)++)|\[([^\]]++)\])(.*)/';
        while (preg_match($pattern, $remaining, $matches)) {
            if ('' !== $matches[2]) {
                $element = $matches[2];
                $this->isIndex[] = \false;
            } else {
                $element = $matches[3];
                $this->isIndex[] = \true;
            }
            // Mark as optional when last character is "?".
            if (str_ends_with($element, '?')) {
                $this->isNullSafe[] = \true;
                $element = substr($element, 0, -1);
            } else {
                $this->isNullSafe[] = \false;
            }
            $element = preg_replace('/\\\\([.[])/', '$1', $element);
            if (str_ends_with($element, '\\\\')) {
                $element = substr($element, 0, -1);
            }
            $this->elements[] = $element;
            $position += \strlen($matches[1]);
            $remaining = $matches[4];
            $pattern = '/^(\.((?:[^\\\\.\[]|\\\\.)++)|\[([^\]]++)\])(.*)/';
        }
        if ('' !== $remaining) {
            throw new InvalidPropertyPathException(\sprintf('Could not parse property path "%s". Unexpected token "%s" at position %d.', $propertyPath, $remaining[0], $position));
        }
        $this->length = \count($this->elements);
    }
    public function __toString(): string
    {
        return $this->pathAsString;
    }
    public function getLength(): int
    {
        return $this->length;
    }
    public function getParent(): ?PropertyPathInterface
    {
        if ($this->length <= 1) {
            return null;
        }
        $parent = clone $this;
        --$parent->length;
        $parent->pathAsString = substr($parent->pathAsString, 0, max(strrpos($parent->pathAsString, '.'), strrpos($parent->pathAsString, '[')));
        array_pop($parent->elements);
        array_pop($parent->isIndex);
        array_pop($parent->isNullSafe);
        return $parent;
    }
    /**
     * Returns a new iterator for this path.
     */
    public function getIterator(): PropertyPathIteratorInterface
    {
        return new PropertyPathIterator($this);
    }
    public function getElements(): array
    {
        return $this->elements;
    }
    public function getElement(int $index): string
    {
        if (!isset($this->elements[$index])) {
            throw new OutOfBoundsException(\sprintf('The index "%s" is not within the property path.', $index));
        }
        return $this->elements[$index];
    }
    public function isProperty(int $index): bool
    {
        if (!isset($this->isIndex[$index])) {
            throw new OutOfBoundsException(\sprintf('The index "%s" is not within the property path.', $index));
        }
        return !$this->isIndex[$index];
    }
    public function isIndex(int $index): bool
    {
        if (!isset($this->isIndex[$index])) {
            throw new OutOfBoundsException(\sprintf('The index "%s" is not within the property path.', $index));
        }
        return $this->isIndex[$index];
    }
    public function isNullSafe(int $index): bool
    {
        if (!isset($this->isNullSafe[$index])) {
            throw new OutOfBoundsException(\sprintf('The index "%s" is not within the property path.', $index));
        }
        return $this->isNullSafe[$index];
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\PropertyAccess;

use _ContaoManager\Psr\Cache\CacheItemPoolInterface;
use _ContaoManager\Symfony\Component\PropertyInfo\PropertyReadInfoExtractorInterface;
use _ContaoManager\Symfony\Component\PropertyInfo\PropertyWriteInfoExtractorInterface;
/**
 * A configurable builder to create a PropertyAccessor.
 *
 * @author Jérémie Augustin <jeremie.augustin@pixel-cookers.com>
 */
class PropertyAccessorBuilder
{
    private int $magicMethods = PropertyAccessor::MAGIC_GET | PropertyAccessor::MAGIC_SET;
    private bool $throwExceptionOnInvalidIndex = \false;
    private bool $throwExceptionOnInvalidPropertyPath = \true;
    private ?CacheItemPoolInterface $cacheItemPool = null;
    private ?PropertyReadInfoExtractorInterface $readInfoExtractor = null;
    private ?PropertyWriteInfoExtractorInterface $writeInfoExtractor = null;
    /**
     * Enables the use of all magic methods by the PropertyAccessor.
     *
     * @return $this
     */
    public function enableMagicMethods(): static
    {
        $this->magicMethods = PropertyAccessor::MAGIC_GET | PropertyAccessor::MAGIC_SET | PropertyAccessor::MAGIC_CALL;
        return $this;
    }
    /**
     * Disable the use of all magic methods by the PropertyAccessor.
     *
     * @return $this
     */
    public function disableMagicMethods(): static
    {
        $this->magicMethods = PropertyAccessor::DISALLOW_MAGIC_METHODS;
        return $this;
    }
    /**
     * Enables the use of "__call" by the PropertyAccessor.
     *
     * @return $this
     */
    public function enableMagicCall(): static
    {
        $this->magicMethods |= PropertyAccessor::MAGIC_CALL;
        return $this;
    }
    /**
     * Enables the use of "__get" by the PropertyAccessor.
     */
    public function enableMagicGet(): self
    {
        $this->magicMethods |= PropertyAccessor::MAGIC_GET;
        return $this;
    }
    /**
     * Enables the use of "__set" by the PropertyAccessor.
     *
     * @return $this
     */
    public function enableMagicSet(): static
    {
        $this->magicMethods |= PropertyAccessor::MAGIC_SET;
        return $this;
    }
    /**
     * Disables the use of "__call" by the PropertyAccessor.
     *
     * @return $this
     */
    public function disableMagicCall(): static
    {
        $this->magicMethods &= ~PropertyAccessor::MAGIC_CALL;
        return $this;
    }
    /**
     * Disables the use of "__get" by the PropertyAccessor.
     *
     * @return $this
     */
    public function disableMagicGet(): static
    {
        $this->magicMethods &= ~PropertyAccessor::MAGIC_GET;
        return $this;
    }
    /**
     * Disables the use of "__set" by the PropertyAccessor.
     *
     * @return $this
     */
    public function disableMagicSet(): static
    {
        $this->magicMethods &= ~PropertyAccessor::MAGIC_SET;
        return $this;
    }
    /**
     * @return bool whether the use of "__call" by the PropertyAccessor is enabled
     */
    public function isMagicCallEnabled(): bool
    {
        return $this->magicMethods & PropertyAccessor::MAGIC_CALL;
    }
    /**
     * @return bool whether the use of "__get" by the PropertyAccessor is enabled
     */
    public function isMagicGetEnabled(): bool
    {
        return $this->magicMethods & PropertyAccessor::MAGIC_GET;
    }
    /**
     * @return bool whether the use of "__set" by the PropertyAccessor is enabled
     */
    public function isMagicSetEnabled(): bool
    {
        return $this->magicMethods & PropertyAccessor::MAGIC_SET;
    }
    /**
     * Enables exceptions when reading a non-existing index.
     *
     * This has no influence on writing non-existing indices with PropertyAccessorInterface::setValue()
     * which are always created on-the-fly.
     *
     * @return $this
     */
    public function enableExceptionOnInvalidIndex(): static
    {
        $this->throwExceptionOnInvalidIndex = \true;
        return $this;
    }
    /**
     * Disables exceptions when reading a non-existing index.
     *
     * Instead, null is returned when calling PropertyAccessorInterface::getValue() on a non-existing index.
     *
     * @return $this
     */
    public function disableExceptionOnInvalidIndex(): static
    {
        $this->throwExceptionOnInvalidIndex = \false;
        return $this;
    }
    /**
     * @return bool whether an exception is thrown or null is returned when reading a non-existing index
     */
    public function isExceptionOnInvalidIndexEnabled(): bool
    {
        return $this->throwExceptionOnInvalidIndex;
    }
    /**
     * Enables exceptions when reading a non-existing property.
     *
     * This has no influence on writing non-existing indices with PropertyAccessorInterface::setValue()
     * which are always created on-the-fly.
     *
     * @return $this
     */
    public function enableExceptionOnInvalidPropertyPath(): static
    {
        $this->throwExceptionOnInvalidPropertyPath = \true;
        return $this;
    }
    /**
     * Disables exceptions when reading a non-existing index.
     *
     * Instead, null is returned when calling PropertyAccessorInterface::getValue() on a non-existing index.
     *
     * @return $this
     */
    public function disableExceptionOnInvalidPropertyPath(): static
    {
        $this->throwExceptionOnInvalidPropertyPath = \false;
        return $this;
    }
    /**
     * @return bool whether an exception is thrown or null is returned when reading a non-existing property
     */
    public function isExceptionOnInvalidPropertyPath(): bool
    {
        return $this->throwExceptionOnInvalidPropertyPath;
    }
    /**
     * Sets a cache system.
     *
     * @return $this
     */
    public function setCacheItemPool(?CacheItemPoolInterface $cacheItemPool = null): static
    {
        if (1 > \func_num_args()) {
            trigger_deprecation('symfony/property-access', '6.2', 'Calling "%s()" without any arguments is deprecated, pass null explicitly instead.', __METHOD__);
        }
        $this->cacheItemPool = $cacheItemPool;
        return $this;
    }
    /**
     * Gets the used cache system.
     */
    public function getCacheItemPool(): ?CacheItemPoolInterface
    {
        return $this->cacheItemPool;
    }
    /**
     * @return $this
     */
    public function setReadInfoExtractor(?PropertyReadInfoExtractorInterface $readInfoExtractor): static
    {
        $this->readInfoExtractor = $readInfoExtractor;
        return $this;
    }
    public function getReadInfoExtractor(): ?PropertyReadInfoExtractorInterface
    {
        return $this->readInfoExtractor;
    }
    /**
     * @return $this
     */
    public function setWriteInfoExtractor(?PropertyWriteInfoExtractorInterface $writeInfoExtractor): static
    {
        $this->writeInfoExtractor = $writeInfoExtractor;
        return $this;
    }
    public function getWriteInfoExtractor(): ?PropertyWriteInfoExtractorInterface
    {
        return $this->writeInfoExtractor;
    }
    /**
     * Builds and returns a new PropertyAccessor object.
     */
    public function getPropertyAccessor(): PropertyAccessorInterface
    {
        $throw = PropertyAccessor::DO_NOT_THROW;
        if ($this->throwExceptionOnInvalidIndex) {
            $throw |= PropertyAccessor::THROW_ON_INVALID_INDEX;
        }
        if ($this->throwExceptionOnInvalidPropertyPath) {
            $throw |= PropertyAccessor::THROW_ON_INVALID_PROPERTY_PATH;
        }
        return new PropertyAccessor($this->magicMethods, $throw, $this->cacheItemPool, $this->readInfoExtractor, $this->writeInfoExtractor);
    }
}
PropertyAccess Component
========================

The PropertyAccess component provides functions to read and write from/to an
object or array using a simple string notation.

Resources
---------

 * [Documentation](https://symfony.com/doc/current/components/property_access.html)
 * [Contributing](https://symfony.com/doc/current/contributing/index.html)
 * [Report issues](https://github.com/symfony/symfony/issues) and
   [send Pull Requests](https://github.com/symfony/symfony/pulls)
   in the [main Symfony repository](https://github.com/symfony/symfony)
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\PropertyAccess;

use _ContaoManager\Psr\Cache\CacheItemPoolInterface;
use _ContaoManager\Psr\Log\LoggerInterface;
use _ContaoManager\Psr\Log\NullLogger;
use _ContaoManager\Symfony\Component\Cache\Adapter\AdapterInterface;
use _ContaoManager\Symfony\Component\Cache\Adapter\ApcuAdapter;
use _ContaoManager\Symfony\Component\Cache\Adapter\NullAdapter;
use _ContaoManager\Symfony\Component\PropertyAccess\Exception\AccessException;
use _ContaoManager\Symfony\Component\PropertyAccess\Exception\InvalidArgumentException;
use _ContaoManager\Symfony\Component\PropertyAccess\Exception\NoSuchIndexException;
use _ContaoManager\Symfony\Component\PropertyAccess\Exception\NoSuchPropertyException;
use _ContaoManager\Symfony\Component\PropertyAccess\Exception\UnexpectedTypeException;
use _ContaoManager\Symfony\Component\PropertyAccess\Exception\UninitializedPropertyException;
use _ContaoManager\Symfony\Component\PropertyInfo\Extractor\ReflectionExtractor;
use _ContaoManager\Symfony\Component\PropertyInfo\PropertyReadInfo;
use _ContaoManager\Symfony\Component\PropertyInfo\PropertyReadInfoExtractorInterface;
use _ContaoManager\Symfony\Component\PropertyInfo\PropertyWriteInfo;
use _ContaoManager\Symfony\Component\PropertyInfo\PropertyWriteInfoExtractorInterface;
/**
 * Default implementation of {@link PropertyAccessorInterface}.
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 * @author Kévin Dunglas <dunglas@gmail.com>
 * @author Nicolas Grekas <p@tchwork.com>
 */
class PropertyAccessor implements PropertyAccessorInterface
{
    /** @var int Allow none of the magic methods */
    public const DISALLOW_MAGIC_METHODS = ReflectionExtractor::DISALLOW_MAGIC_METHODS;
    /** @var int Allow magic __get methods */
    public const MAGIC_GET = ReflectionExtractor::ALLOW_MAGIC_GET;
    /** @var int Allow magic __set methods */
    public const MAGIC_SET = ReflectionExtractor::ALLOW_MAGIC_SET;
    /** @var int Allow magic __call methods */
    public const MAGIC_CALL = ReflectionExtractor::ALLOW_MAGIC_CALL;
    public const DO_NOT_THROW = 0;
    public const THROW_ON_INVALID_INDEX = 1;
    public const THROW_ON_INVALID_PROPERTY_PATH = 2;
    private const VALUE = 0;
    private const REF = 1;
    private const IS_REF_CHAINED = 2;
    private const CACHE_PREFIX_READ = 'r';
    private const CACHE_PREFIX_WRITE = 'w';
    private const CACHE_PREFIX_PROPERTY_PATH = 'p';
    private const RESULT_PROTO = [self::VALUE => null];
    private int $magicMethodsFlags;
    private bool $ignoreInvalidIndices;
    private bool $ignoreInvalidProperty;
    private ?CacheItemPoolInterface $cacheItemPool;
    private array $propertyPathCache = [];
    private PropertyReadInfoExtractorInterface $readInfoExtractor;
    private PropertyWriteInfoExtractorInterface $writeInfoExtractor;
    private array $readPropertyCache = [];
    private array $writePropertyCache = [];
    /**
     * Should not be used by application code. Use
     * {@link PropertyAccess::createPropertyAccessor()} instead.
     *
     * @param int $magicMethods A bitwise combination of the MAGIC_* constants
     *                          to specify the allowed magic methods (__get, __set, __call)
     *                          or self::DISALLOW_MAGIC_METHODS for none
     * @param int $throw        A bitwise combination of the THROW_* constants
     *                          to specify when exceptions should be thrown
     */
    public function __construct(int $magicMethods = self::MAGIC_GET | self::MAGIC_SET, int $throw = self::THROW_ON_INVALID_PROPERTY_PATH, ?CacheItemPoolInterface $cacheItemPool = null, ?PropertyReadInfoExtractorInterface $readInfoExtractor = null, ?PropertyWriteInfoExtractorInterface $writeInfoExtractor = null)
    {
        $this->magicMethodsFlags = $magicMethods;
        $this->ignoreInvalidIndices = 0 === ($throw & self::THROW_ON_INVALID_INDEX);
        $this->cacheItemPool = $cacheItemPool instanceof NullAdapter ? null : $cacheItemPool;
        // Replace the NullAdapter by the null value
        $this->ignoreInvalidProperty = 0 === ($throw & self::THROW_ON_INVALID_PROPERTY_PATH);
        $this->readInfoExtractor = $readInfoExtractor ?? new ReflectionExtractor([], null, null, \false);
        $this->writeInfoExtractor = $writeInfoExtractor ?? new ReflectionExtractor(['set'], null, null, \false);
    }
    public function getValue(object|array $objectOrArray, string|PropertyPathInterface $propertyPath): mixed
    {
        $zval = [self::VALUE => $objectOrArray];
        if (\is_object($objectOrArray) && (\false === strpbrk((string) $propertyPath, '.[?') || $objectOrArray instanceof \stdClass && property_exists($objectOrArray, $propertyPath))) {
            return $this->readProperty($zval, $propertyPath, $this->ignoreInvalidProperty)[self::VALUE];
        }
        $propertyPath = $this->getPropertyPath($propertyPath);
        $propertyValues = $this->readPropertiesUntil($zval, $propertyPath, $propertyPath->getLength(), $this->ignoreInvalidIndices);
        return $propertyValues[\count($propertyValues) - 1][self::VALUE];
    }
    /**
     * @return void
     */
    public function setValue(object|array &$objectOrArray, string|PropertyPathInterface $propertyPath, mixed $value)
    {
        if (\is_object($objectOrArray) && (\false === strpbrk((string) $propertyPath, '.[') || $objectOrArray instanceof \stdClass && property_exists($objectOrArray, $propertyPath))) {
            $zval = [self::VALUE => $objectOrArray];
            try {
                $this->writeProperty($zval, $propertyPath, $value);
                return;
            } catch (\TypeError $e) {
                self::throwInvalidArgumentException($e->getMessage(), $e->getTrace(), 0, $propertyPath, $e);
                // It wasn't thrown in this class so rethrow it
                throw $e;
            }
        }
        $propertyPath = $this->getPropertyPath($propertyPath);
        $zval = [self::VALUE => $objectOrArray, self::REF => &$objectOrArray];
        $propertyValues = $this->readPropertiesUntil($zval, $propertyPath, $propertyPath->getLength() - 1);
        $overwrite = \true;
        try {
            for ($i = \count($propertyValues) - 1; 0 <= $i; --$i) {
                $zval = $propertyValues[$i];
                unset($propertyValues[$i]);
                // You only need set value for current element if:
                // 1. it's the parent of the last index element
                // OR
                // 2. its child is not passed by reference
                //
                // This may avoid unnecessary value setting process for array elements.
                // For example:
                // '[a][b][c]' => 'old-value'
                // If you want to change its value to 'new-value',
                // you only need set value for '[a][b][c]' and it's safe to ignore '[a][b]' and '[a]'
                if ($overwrite) {
                    $property = $propertyPath->getElement($i);
                    if ($propertyPath->isIndex($i)) {
                        if ($overwrite = !isset($zval[self::REF])) {
                            $ref =& $zval[self::REF];
                            $ref = $zval[self::VALUE];
                        }
                        $this->writeIndex($zval, $property, $value);
                        if ($overwrite) {
                            $zval[self::VALUE] = $zval[self::REF];
                        }
                    } else {
                        $this->writeProperty($zval, $property, $value);
                    }
                    // if current element is an object
                    // OR
                    // if current element's reference chain is not broken - current element
                    // as well as all its ancients in the property path are all passed by reference,
                    // then there is no need to continue the value setting process
                    if (\is_object($zval[self::VALUE]) || isset($zval[self::IS_REF_CHAINED])) {
                        break;
                    }
                }
                $value = $zval[self::VALUE];
            }
        } catch (\TypeError $e) {
            self::throwInvalidArgumentException($e->getMessage(), $e->getTrace(), 0, $propertyPath, $e);
            // It wasn't thrown in this class so rethrow it
            throw $e;
        }
    }
    private static function throwInvalidArgumentException(string $message, array $trace, int $i, string $propertyPath, ?\Throwable $previous = null): void
    {
        if (!isset($trace[$i]['file']) || __FILE__ !== $trace[$i]['file']) {
            return;
        }
        if (preg_match('/^\S+::\S+\(\): Argument #\d+ \(\$\S+\) must be of type (\S+), (\S+) given/', $message, $matches)) {
            [, $expectedType, $actualType] = $matches;
            throw new InvalidArgumentException(\sprintf('Expected argument of type "%s", "%s" given at property path "%s".', $expectedType, 'NULL' === $actualType ? 'null' : $actualType, $propertyPath), 0, $previous);
        }
        if (preg_match('/^Cannot assign (\S+) to property \S+::\$\S+ of type (\S+)$/', $message, $matches)) {
            [, $actualType, $expectedType] = $matches;
            throw new InvalidArgumentException(\sprintf('Expected argument of type "%s", "%s" given at property path "%s".', $expectedType, 'NULL' === $actualType ? 'null' : $actualType, $propertyPath), 0, $previous);
        }
    }
    public function isReadable(object|array $objectOrArray, string|PropertyPathInterface $propertyPath): bool
    {
        if (!$propertyPath instanceof PropertyPathInterface) {
            $propertyPath = new PropertyPath($propertyPath);
        }
        try {
            $zval = [self::VALUE => $objectOrArray];
            // handle stdClass with properties with a dot in the name
            if ($objectOrArray instanceof \stdClass && str_contains($propertyPath, '.') && property_exists($objectOrArray, $propertyPath)) {
                $this->readProperty($zval, $propertyPath, $this->ignoreInvalidProperty);
            } else {
                $this->readPropertiesUntil($zval, $propertyPath, $propertyPath->getLength(), $this->ignoreInvalidIndices);
            }
            return \true;
        } catch (AccessException) {
            return \false;
        } catch (UnexpectedTypeException) {
            return \false;
        }
    }
    public function isWritable(object|array $objectOrArray, string|PropertyPathInterface $propertyPath): bool
    {
        $propertyPath = $this->getPropertyPath($propertyPath);
        try {
            $zval = [self::VALUE => $objectOrArray];
            // handle stdClass with properties with a dot in the name
            if ($objectOrArray instanceof \stdClass && str_contains($propertyPath, '.') && property_exists($objectOrArray, $propertyPath)) {
                $this->readProperty($zval, $propertyPath, $this->ignoreInvalidProperty);
                return \true;
            }
            $propertyValues = $this->readPropertiesUntil($zval, $propertyPath, $propertyPath->getLength() - 1);
            for ($i = \count($propertyValues) - 1; 0 <= $i; --$i) {
                $zval = $propertyValues[$i];
                unset($propertyValues[$i]);
                if ($propertyPath->isIndex($i)) {
                    if (!$zval[self::VALUE] instanceof \ArrayAccess && !\is_array($zval[self::VALUE])) {
                        return \false;
                    }
                } elseif (!\is_object($zval[self::VALUE]) || !$this->isPropertyWritable($zval[self::VALUE], $propertyPath->getElement($i))) {
                    return \false;
                }
                if (\is_object($zval[self::VALUE])) {
                    return \true;
                }
            }
            return \true;
        } catch (AccessException) {
            return \false;
        } catch (UnexpectedTypeException) {
            return \false;
        }
    }
    /**
     * Reads the path from an object up to a given path index.
     *
     * @throws UnexpectedTypeException if a value within the path is neither object nor array
     * @throws NoSuchIndexException    If a non-existing index is accessed
     */
    private function readPropertiesUntil(array $zval, PropertyPathInterface $propertyPath, int $lastIndex, bool $ignoreInvalidIndices = \true): array
    {
        if (!\is_object($zval[self::VALUE]) && !\is_array($zval[self::VALUE])) {
            throw new UnexpectedTypeException($zval[self::VALUE], $propertyPath, 0);
        }
        // Add the root object to the list
        $propertyValues = [$zval];
        for ($i = 0; $i < $lastIndex; ++$i) {
            $property = $propertyPath->getElement($i);
            $isIndex = $propertyPath->isIndex($i);
            $isNullSafe = \false;
            if (method_exists($propertyPath, 'isNullSafe')) {
                // To be removed in symfony 7 once we are sure isNullSafe is always implemented.
                $isNullSafe = $propertyPath->isNullSafe($i);
            } else {
                trigger_deprecation('symfony/property-access', '6.2', 'The "%s()" method in class "%s" needs to be implemented in version 7.0, not defining it is deprecated.', 'isNullSafe', PropertyPathInterface::class);
            }
            if ($isIndex) {
                // Create missing nested arrays on demand
                if ($zval[self::VALUE] instanceof \ArrayAccess && !$zval[self::VALUE]->offsetExists($property) || \is_array($zval[self::VALUE]) && !isset($zval[self::VALUE][$property]) && !\array_key_exists($property, $zval[self::VALUE])) {
                    if (!$ignoreInvalidIndices && !$isNullSafe) {
                        if (!\is_array($zval[self::VALUE])) {
                            if (!$zval[self::VALUE] instanceof \Traversable) {
                                throw new NoSuchIndexException(\sprintf('Cannot read index "%s" while trying to traverse path "%s".', $property, (string) $propertyPath));
                            }
                            $zval[self::VALUE] = iterator_to_array($zval[self::VALUE]);
                        }
                        throw new NoSuchIndexException(\sprintf('Cannot read index "%s" while trying to traverse path "%s". Available indices are "%s".', $property, (string) $propertyPath, print_r(array_keys($zval[self::VALUE]), \true)));
                    }
                    if ($i + 1 < $propertyPath->getLength()) {
                        if (isset($zval[self::REF])) {
                            $zval[self::VALUE][$property] = [];
                            $zval[self::REF] = $zval[self::VALUE];
                        } else {
                            $zval[self::VALUE] = [$property => []];
                        }
                    }
                }
                $zval = $this->readIndex($zval, $property);
            } elseif ($isNullSafe && !\is_object($zval[self::VALUE])) {
                $zval[self::VALUE] = null;
            } else {
                $zval = $this->readProperty($zval, $property, $this->ignoreInvalidProperty, $isNullSafe);
            }
            // the final value of the path must not be validated
            if ($i + 1 < $propertyPath->getLength() && !\is_object($zval[self::VALUE]) && !\is_array($zval[self::VALUE]) && !$isNullSafe) {
                throw new UnexpectedTypeException($zval[self::VALUE], $propertyPath, $i + 1);
            }
            if (isset($zval[self::REF]) && (0 === $i || isset($propertyValues[$i - 1][self::IS_REF_CHAINED]))) {
                // Set the IS_REF_CHAINED flag to true if:
                // current property is passed by reference and
                // it is the first element in the property path or
                // the IS_REF_CHAINED flag of its parent element is true
                // Basically, this flag is true only when the reference chain from the top element to current element is not broken
                $zval[self::IS_REF_CHAINED] = \true;
            }
            $propertyValues[] = $zval;
            if ($isNullSafe && null === $zval[self::VALUE]) {
                break;
            }
        }
        return $propertyValues;
    }
    /**
     * Reads a key from an array-like structure.
     *
     * @throws NoSuchIndexException If the array does not implement \ArrayAccess or it is not an array
     */
    private function readIndex(array $zval, string|int $index): array
    {
        if (!$zval[self::VALUE] instanceof \ArrayAccess && !\is_array($zval[self::VALUE])) {
            throw new NoSuchIndexException(\sprintf('Cannot read index "%s" from object of type "%s" because it doesn\'t implement \ArrayAccess.', $index, get_debug_type($zval[self::VALUE])));
        }
        $result = self::RESULT_PROTO;
        if (isset($zval[self::VALUE][$index])) {
            $result[self::VALUE] = $zval[self::VALUE][$index];
            if (!isset($zval[self::REF])) {
                // Save creating references when doing read-only lookups
            } elseif (\is_array($zval[self::VALUE])) {
                $result[self::REF] =& $zval[self::REF][$index];
            } elseif (\is_object($result[self::VALUE])) {
                $result[self::REF] = $result[self::VALUE];
            }
        }
        return $result;
    }
    /**
     * Reads the value of a property from an object.
     *
     * @throws NoSuchPropertyException If $ignoreInvalidProperty is false and the property does not exist or is not public
     */
    private function readProperty(array $zval, string $property, bool $ignoreInvalidProperty = \false, bool $isNullSafe = \false): array
    {
        if (!\is_object($zval[self::VALUE])) {
            throw new NoSuchPropertyException(\sprintf('Cannot read property "%s" from an array. Maybe you intended to write the property path as "[%1$s]" instead.', $property));
        }
        $result = self::RESULT_PROTO;
        $object = $zval[self::VALUE];
        $class = $object::class;
        $access = $this->getReadInfo($class, $property);
        if (null !== $access) {
            $name = $access->getName();
            $type = $access->getType();
            try {
                if (PropertyReadInfo::TYPE_METHOD === $type) {
                    try {
                        $result[self::VALUE] = $object->{$name}();
                    } catch (\TypeError $e) {
                        [$trace] = $e->getTrace();
                        // handle uninitialized properties in PHP >= 7
                        if (__FILE__ === ($trace['file'] ?? null) && $name === $trace['function'] && $object instanceof $trace['class'] && preg_match('/Return value (?:of .*::\w+\(\) )?must be of (?:the )?type (\w+), null returned$/', $e->getMessage(), $matches)) {
                            throw new UninitializedPropertyException(\sprintf('The method "%s::%s()" returned "null", but expected type "%3$s". Did you forget to initialize a property or to make the return type nullable using "?%3$s"?', get_debug_type($object), $name, $matches[1]), 0, $e);
                        }
                        throw $e;
                    }
                } elseif (PropertyReadInfo::TYPE_PROPERTY === $type) {
                    if (!isset($object->{$name}) && !\array_key_exists($name, (array) $object)) {
                        try {
                            $r = new \ReflectionProperty($class, $name);
                            if ($r->isPublic() && !$r->hasType()) {
                                throw new UninitializedPropertyException(\sprintf('The property "%s::$%s" is not initialized.', $class, $name));
                            }
                        } catch (\ReflectionException $e) {
                            if (!$ignoreInvalidProperty) {
                                throw new NoSuchPropertyException(\sprintf('Can\'t get a way to read the property "%s" in class "%s".', $property, $class));
                            }
                        }
                    }
                    $result[self::VALUE] = $object->{$name};
                    if (isset($zval[self::REF]) && $access->canBeReference()) {
                        $result[self::REF] =& $object->{$name};
                    }
                }
            } catch (\Error $e) {
                // handle uninitialized properties in PHP >= 7.4
                if (preg_match('/^Typed property ([\w\\\\@]+)::\$(\w+) must not be accessed before initialization$/', $e->getMessage(), $matches) || preg_match('/^Cannot access uninitialized non-nullable property ([\w\\\\@]+)::\$(\w+) by reference$/', $e->getMessage(), $matches)) {
                    $r = new \ReflectionProperty(str_contains($matches[1], '@anonymous') ? $class : $matches[1], $matches[2]);
                    $type = ($type = $r->getType()) instanceof \ReflectionNamedType ? $type->getName() : (string) $type;
                    throw new UninitializedPropertyException(\sprintf('The property "%s::$%s" is not readable because it is typed "%s". You should initialize it or declare a default value instead.', $matches[1], $r->getName(), $type), 0, $e);
                }
                throw $e;
            }
        } elseif (property_exists($object, $property) && \array_key_exists($property, (array) $object)) {
            $result[self::VALUE] = $object->{$property};
            if (isset($zval[self::REF])) {
                $result[self::REF] =& $object->{$property};
            }
        } elseif ($isNullSafe) {
            $result[self::VALUE] = null;
        } elseif (!$ignoreInvalidProperty) {
            throw new NoSuchPropertyException(\sprintf('Can\'t get a way to read the property "%s" in class "%s".', $property, $class));
        }
        // Objects are always passed around by reference
        if (isset($zval[self::REF]) && \is_object($result[self::VALUE])) {
            $result[self::REF] = $result[self::VALUE];
        }
        return $result;
    }
    /**
     * Guesses how to read the property value.
     */
    private function getReadInfo(string $class, string $property): ?PropertyReadInfo
    {
        $key = str_replace('\\', '.', $class) . '..' . $property;
        if (isset($this->readPropertyCache[$key])) {
            return $this->readPropertyCache[$key];
        }
        if ($this->cacheItemPool) {
            $item = $this->cacheItemPool->getItem(self::CACHE_PREFIX_READ . rawurlencode($key));
            if ($item->isHit()) {
                return $this->readPropertyCache[$key] = $item->get();
            }
        }
        $accessor = $this->readInfoExtractor->getReadInfo($class, $property, ['enable_getter_setter_extraction' => \true, 'enable_magic_methods_extraction' => $this->magicMethodsFlags, 'enable_constructor_extraction' => \false]);
        if (isset($item)) {
            $this->cacheItemPool->save($item->set($accessor));
        }
        return $this->readPropertyCache[$key] = $accessor;
    }
    /**
     * Sets the value of an index in a given array-accessible value.
     *
     * @throws NoSuchIndexException If the array does not implement \ArrayAccess or it is not an array
     */
    private function writeIndex(array $zval, string|int $index, mixed $value): void
    {
        if (!$zval[self::VALUE] instanceof \ArrayAccess && !\is_array($zval[self::VALUE])) {
            throw new NoSuchIndexException(\sprintf('Cannot modify index "%s" in object of type "%s" because it doesn\'t implement \ArrayAccess.', $index, get_debug_type($zval[self::VALUE])));
        }
        $zval[self::REF][$index] = $value;
    }
    /**
     * Sets the value of a property in the given object.
     *
     * @throws NoSuchPropertyException if the property does not exist or is not public
     */
    private function writeProperty(array $zval, string $property, mixed $value, bool $recursive = \false): void
    {
        if (!\is_object($zval[self::VALUE])) {
            throw new NoSuchPropertyException(\sprintf('Cannot write property "%s" to an array. Maybe you should write the property path as "[%1$s]" instead?', $property));
        }
        $object = $zval[self::VALUE];
        $class = $object::class;
        $mutator = $this->getWriteInfo($class, $property, $value);
        try {
            if (PropertyWriteInfo::TYPE_NONE !== $mutator->getType()) {
                $type = $mutator->getType();
                if (PropertyWriteInfo::TYPE_METHOD === $type) {
                    $object->{$mutator->getName()}($value);
                } elseif (PropertyWriteInfo::TYPE_PROPERTY === $type) {
                    $object->{$mutator->getName()} = $value;
                } elseif (PropertyWriteInfo::TYPE_ADDER_AND_REMOVER === $type) {
                    $this->writeCollection($zval, $property, $value, $mutator->getAdderInfo(), $mutator->getRemoverInfo());
                }
            } elseif ($object instanceof \stdClass && property_exists($object, $property)) {
                $object->{$property} = $value;
            } elseif (!$this->ignoreInvalidProperty) {
                if ($mutator->hasErrors()) {
                    throw new NoSuchPropertyException(implode('. ', $mutator->getErrors()) . '.');
                }
                throw new NoSuchPropertyException(\sprintf('Could not determine access type for property "%s" in class "%s".', $property, get_debug_type($object)));
            }
        } catch (\TypeError $e) {
            if ($recursive || !$value instanceof \DateTimeInterface || !\in_array($value::class, ['DateTime', 'DateTimeImmutable'], \true) || __FILE__ !== ($e->getTrace()[0]['file'] ?? null)) {
                throw $e;
            }
            $value = $value instanceof \DateTimeImmutable ? \DateTime::createFromImmutable($value) : \DateTimeImmutable::createFromMutable($value);
            try {
                $this->writeProperty($zval, $property, $value, \true);
            } catch (\TypeError) {
                throw $e;
                // throw the previous error
            }
        }
    }
    /**
     * Adjusts a collection-valued property by calling add*() and remove*() methods.
     */
    private function writeCollection(array $zval, string $property, iterable $collection, PropertyWriteInfo $addMethod, PropertyWriteInfo $removeMethod): void
    {
        // At this point the add and remove methods have been found
        $previousValue = $this->readProperty($zval, $property);
        $previousValue = $previousValue[self::VALUE];
        $removeMethodName = $removeMethod->getName();
        $addMethodName = $addMethod->getName();
        if ($previousValue instanceof \Traversable) {
            $previousValue = iterator_to_array($previousValue);
        }
        if ($previousValue && \is_array($previousValue)) {
            if (\is_object($collection)) {
                $collection = iterator_to_array($collection);
            }
            foreach ($previousValue as $key => $item) {
                if (!\in_array($item, $collection, \true)) {
                    unset($previousValue[$key]);
                    $zval[self::VALUE]->{$removeMethodName}($item);
                }
            }
        } else {
            $previousValue = \false;
        }
        foreach ($collection as $item) {
            if (!$previousValue || !\in_array($item, $previousValue, \true)) {
                $zval[self::VALUE]->{$addMethodName}($item);
            }
        }
    }
    private function getWriteInfo(string $class, string $property, mixed $value): PropertyWriteInfo
    {
        $useAdderAndRemover = is_iterable($value);
        $key = str_replace('\\', '.', $class) . '..' . $property . '..' . (int) $useAdderAndRemover;
        if (isset($this->writePropertyCache[$key])) {
            return $this->writePropertyCache[$key];
        }
        if ($this->cacheItemPool) {
            $item = $this->cacheItemPool->getItem(self::CACHE_PREFIX_WRITE . rawurlencode($key));
            if ($item->isHit()) {
                return $this->writePropertyCache[$key] = $item->get();
            }
        }
        $mutator = $this->writeInfoExtractor->getWriteInfo($class, $property, ['enable_getter_setter_extraction' => \true, 'enable_magic_methods_extraction' => $this->magicMethodsFlags, 'enable_constructor_extraction' => \false, 'enable_adder_remover_extraction' => $useAdderAndRemover]);
        if (isset($item)) {
            $this->cacheItemPool->save($item->set($mutator));
        }
        return $this->writePropertyCache[$key] = $mutator;
    }
    /**
     * Returns whether a property is writable in the given object.
     */
    private function isPropertyWritable(object $object, string $property): bool
    {
        if ($object instanceof \stdClass && property_exists($object, $property)) {
            return \true;
        }
        $mutatorForArray = $this->getWriteInfo($object::class, $property, []);
        if (PropertyWriteInfo::TYPE_PROPERTY === $mutatorForArray->getType()) {
            return 'public' === $mutatorForArray->getVisibility();
        }
        if (PropertyWriteInfo::TYPE_NONE !== $mutatorForArray->getType()) {
            return \true;
        }
        $mutator = $this->getWriteInfo($object::class, $property, '');
        return PropertyWriteInfo::TYPE_NONE !== $mutator->getType();
    }
    /**
     * Gets a PropertyPath instance and caches it.
     */
    private function getPropertyPath(string|PropertyPath $propertyPath): PropertyPath
    {
        if ($propertyPath instanceof PropertyPathInterface) {
            // Don't call the copy constructor has it is not needed here
            return $propertyPath;
        }
        if (isset($this->propertyPathCache[$propertyPath])) {
            return $this->propertyPathCache[$propertyPath];
        }
        if ($this->cacheItemPool) {
            $item = $this->cacheItemPool->getItem(self::CACHE_PREFIX_PROPERTY_PATH . rawurlencode($propertyPath));
            if ($item->isHit()) {
                return $this->propertyPathCache[$propertyPath] = $item->get();
            }
        }
        $propertyPathInstance = new PropertyPath($propertyPath);
        if (isset($item)) {
            $item->set($propertyPathInstance);
            $this->cacheItemPool->save($item);
        }
        return $this->propertyPathCache[$propertyPath] = $propertyPathInstance;
    }
    /**
     * Creates the APCu adapter if applicable.
     *
     * @throws \LogicException When the Cache Component isn't available
     */
    public static function createCache(string $namespace, int $defaultLifetime, string $version, ?LoggerInterface $logger = null): AdapterInterface
    {
        if (!class_exists(ApcuAdapter::class)) {
            throw new \LogicException(\sprintf('The Symfony Cache component must be installed to use "%s()".', __METHOD__));
        }
        if (!ApcuAdapter::isSupported()) {
            return new NullAdapter();
        }
        $apcu = new ApcuAdapter($namespace, $defaultLifetime / 5, $version);
        if ('cli' === \PHP_SAPI && !filter_var(\ini_get('apc.enable_cli'), \FILTER_VALIDATE_BOOL)) {
            $apcu->setLogger(new NullLogger());
        } elseif (null !== $logger) {
            $apcu->setLogger($logger);
        }
        return $apcu;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\PropertyAccess;

/**
 * Entry point of the PropertyAccess component.
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
final class PropertyAccess
{
    /**
     * Creates a property accessor with the default configuration.
     */
    public static function createPropertyAccessor(): PropertyAccessor
    {
        return self::createPropertyAccessorBuilder()->getPropertyAccessor();
    }
    public static function createPropertyAccessorBuilder(): PropertyAccessorBuilder
    {
        return new PropertyAccessorBuilder();
    }
    /**
     * This class cannot be instantiated.
     */
    private function __construct()
    {
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\PropertyAccess;

use _ContaoManager\Symfony\Component\PropertyAccess\Exception\OutOfBoundsException;
/**
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
class PropertyPathBuilder
{
    private array $elements = [];
    private array $isIndex = [];
    public function __construct(PropertyPathInterface|string|null $path = null)
    {
        if (null !== $path) {
            $this->append($path);
        }
    }
    /**
     * Appends a (sub-) path to the current path.
     *
     * @param int $offset The offset where the appended piece starts in $path
     * @param int $length The length of the appended piece; if 0, the full path is appended
     *
     * @return void
     */
    public function append(PropertyPathInterface|string $path, int $offset = 0, int $length = 0)
    {
        if (\is_string($path)) {
            $path = new PropertyPath($path);
        }
        if (0 === $length) {
            $end = $path->getLength();
        } else {
            $end = $offset + $length;
        }
        for (; $offset < $end; ++$offset) {
            $this->elements[] = $path->getElement($offset);
            $this->isIndex[] = $path->isIndex($offset);
        }
    }
    /**
     * Appends an index element to the current path.
     *
     * @return void
     */
    public function appendIndex(string $name)
    {
        $this->elements[] = $name;
        $this->isIndex[] = \true;
    }
    /**
     * Appends a property element to the current path.
     *
     * @return void
     */
    public function appendProperty(string $name)
    {
        $this->elements[] = $name;
        $this->isIndex[] = \false;
    }
    /**
     * Removes elements from the current path.
     *
     * @return void
     *
     * @throws OutOfBoundsException if offset is invalid
     */
    public function remove(int $offset, int $length = 1)
    {
        if (!isset($this->elements[$offset])) {
            throw new OutOfBoundsException(\sprintf('The offset "%s" is not within the property path.', $offset));
        }
        $this->resize($offset, $length, 0);
    }
    /**
     * Replaces a sub-path by a different (sub-) path.
     *
     * @param int $pathOffset The offset where the inserted piece starts in $path
     * @param int $pathLength The length of the inserted piece; if 0, the full path is inserted
     *
     * @return void
     *
     * @throws OutOfBoundsException If the offset is invalid
     */
    public function replace(int $offset, int $length, PropertyPathInterface|string $path, int $pathOffset = 0, int $pathLength = 0)
    {
        if (\is_string($path)) {
            $path = new PropertyPath($path);
        }
        if ($offset < 0 && abs($offset) <= $this->getLength()) {
            $offset = $this->getLength() + $offset;
        } elseif (!isset($this->elements[$offset])) {
            throw new OutOfBoundsException('The offset ' . $offset . ' is not within the property path');
        }
        if (0 === $pathLength) {
            $pathLength = $path->getLength() - $pathOffset;
        }
        $this->resize($offset, $length, $pathLength);
        for ($i = 0; $i < $pathLength; ++$i) {
            $this->elements[$offset + $i] = $path->getElement($pathOffset + $i);
            $this->isIndex[$offset + $i] = $path->isIndex($pathOffset + $i);
        }
        ksort($this->elements);
    }
    /**
     * Replaces a property element by an index element.
     *
     * @return void
     *
     * @throws OutOfBoundsException If the offset is invalid
     */
    public function replaceByIndex(int $offset, ?string $name = null)
    {
        if (!isset($this->elements[$offset])) {
            throw new OutOfBoundsException(\sprintf('The offset "%s" is not within the property path.', $offset));
        }
        if (null !== $name) {
            $this->elements[$offset] = $name;
        }
        $this->isIndex[$offset] = \true;
    }
    /**
     * Replaces an index element by a property element.
     *
     * @return void
     *
     * @throws OutOfBoundsException If the offset is invalid
     */
    public function replaceByProperty(int $offset, ?string $name = null)
    {
        if (!isset($this->elements[$offset])) {
            throw new OutOfBoundsException(\sprintf('The offset "%s" is not within the property path.', $offset));
        }
        if (null !== $name) {
            $this->elements[$offset] = $name;
        }
        $this->isIndex[$offset] = \false;
    }
    /**
     * Returns the length of the current path.
     */
    public function getLength(): int
    {
        return \count($this->elements);
    }
    /**
     * Returns the current property path.
     */
    public function getPropertyPath(): ?PropertyPathInterface
    {
        $pathAsString = $this->__toString();
        return '' !== $pathAsString ? new PropertyPath($pathAsString) : null;
    }
    /**
     * Returns the current property path as string.
     */
    public function __toString(): string
    {
        $string = '';
        foreach ($this->elements as $offset => $element) {
            if ($this->isIndex[$offset]) {
                $element = '[' . $element . ']';
            } elseif ('' !== $string) {
                $string .= '.';
            }
            $string .= $element;
        }
        return $string;
    }
    /**
     * Resizes the path so that a chunk of length $cutLength is
     * removed at $offset and another chunk of length $insertionLength
     * can be inserted.
     */
    private function resize(int $offset, int $cutLength, int $insertionLength): void
    {
        // Nothing else to do in this case
        if ($insertionLength === $cutLength) {
            return;
        }
        $length = \count($this->elements);
        if ($cutLength > $insertionLength) {
            // More elements should be removed than inserted
            $diff = $cutLength - $insertionLength;
            $newLength = $length - $diff;
            // Shift elements to the left (left-to-right until the new end)
            // Max allowed offset to be shifted is such that
            // $offset + $diff < $length (otherwise invalid index access)
            // i.e. $offset < $length - $diff = $newLength
            for ($i = $offset; $i < $newLength; ++$i) {
                $this->elements[$i] = $this->elements[$i + $diff];
                $this->isIndex[$i] = $this->isIndex[$i + $diff];
            }
            // All remaining elements should be removed
            $this->elements = \array_slice($this->elements, 0, $i);
            $this->isIndex = \array_slice($this->isIndex, 0, $i);
        } else {
            $diff = $insertionLength - $cutLength;
            $newLength = $length + $diff;
            $indexAfterInsertion = $offset + $insertionLength;
            // $diff <= $insertionLength
            // $indexAfterInsertion >= $insertionLength
            // => $diff <= $indexAfterInsertion
            // In each of the following loops, $i >= $diff must hold,
            // otherwise ($i - $diff) becomes negative.
            // Shift old elements to the right to make up space for the
            // inserted elements. This needs to be done left-to-right in
            // order to preserve an ascending array index order
            // Since $i = max($length, $indexAfterInsertion) and $indexAfterInsertion >= $diff,
            // $i >= $diff is guaranteed.
            for ($i = max($length, $indexAfterInsertion); $i < $newLength; ++$i) {
                $this->elements[$i] = $this->elements[$i - $diff];
                $this->isIndex[$i] = $this->isIndex[$i - $diff];
            }
            // Shift remaining elements to the right. Do this right-to-left
            // so we don't overwrite elements before copying them
            // The last written index is the immediate index after the inserted
            // string, because the indices before that will be overwritten
            // anyway.
            // Since $i >= $indexAfterInsertion and $indexAfterInsertion >= $diff,
            // $i >= $diff is guaranteed.
            for ($i = $length - 1; $i >= $indexAfterInsertion; --$i) {
                $this->elements[$i] = $this->elements[$i - $diff];
                $this->isIndex[$i] = $this->isIndex[$i - $diff];
            }
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\PropertyAccess\Exception;

/**
 * Thrown when a property path is not available.
 *
 * @author Stéphane Escandell <stephane.escandell@gmail.com>
 */
class AccessException extends RuntimeException
{
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\PropertyAccess\Exception;

/**
 * Thrown when a property is not initialized.
 *
 * @author Jules Pietri <jules@heahprod.com>
 */
class UninitializedPropertyException extends AccessException
{
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\PropertyAccess\Exception;

/**
 * Marker interface for the PropertyAccess component.
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
interface ExceptionInterface extends \Throwable
{
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\PropertyAccess\Exception;

/**
 * Base OutOfBoundsException for the PropertyAccess component.
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
class OutOfBoundsException extends \OutOfBoundsException implements ExceptionInterface
{
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\PropertyAccess\Exception;

/**
 * Base RuntimeException for the PropertyAccess component.
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
class RuntimeException extends \RuntimeException implements ExceptionInterface
{
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\PropertyAccess\Exception;

/**
 * Base InvalidArgumentException for the PropertyAccess component.
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
class InvalidArgumentException extends \InvalidArgumentException implements ExceptionInterface
{
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\PropertyAccess\Exception;

/**
 * Thrown when a property path is malformed.
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
class InvalidPropertyPathException extends RuntimeException
{
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\PropertyAccess\Exception;

use _ContaoManager\Symfony\Component\PropertyAccess\PropertyPathInterface;
/**
 * Thrown when a value does not match an expected type.
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
class UnexpectedTypeException extends RuntimeException
{
    /**
     * @param mixed $value     The unexpected value found while traversing property path
     * @param int   $pathIndex The property path index when the unexpected value was found
     */
    public function __construct(mixed $value, PropertyPathInterface $path, int $pathIndex)
    {
        $message = \sprintf('PropertyAccessor requires a graph of objects or arrays to operate on, ' . 'but it found type "%s" while trying to traverse path "%s" at property "%s".', \gettype($value), (string) $path, $path->getElement($pathIndex));
        parent::__construct($message);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\PropertyAccess\Exception;

/**
 * Thrown when an index cannot be found.
 *
 * @author Stéphane Escandell <stephane.escandell@gmail.com>
 */
class NoSuchIndexException extends AccessException
{
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\PropertyAccess\Exception;

/**
 * Thrown when a property cannot be found.
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
class NoSuchPropertyException extends AccessException
{
}
{
    "name": "symfony\/property-access",
    "type": "library",
    "description": "Provides functions to read and write from\/to an object or array using a simple string notation",
    "keywords": [
        "property",
        "index",
        "access",
        "object",
        "array",
        "extraction",
        "injection",
        "reflection",
        "property-path"
    ],
    "homepage": "https:\/\/symfony.com",
    "license": "MIT",
    "authors": [
        {
            "name": "Fabien Potencier",
            "email": "fabien@symfony.com"
        },
        {
            "name": "Symfony Community",
            "homepage": "https:\/\/symfony.com\/contributors"
        }
    ],
    "require": {
        "php": ">=8.1",
        "symfony\/deprecation-contracts": "^2.5|^3",
        "symfony\/property-info": "^6.4.32|~7.3.10|^7.4.4"
    },
    "require-dev": {
        "symfony\/cache": "^5.4|^6.0|^7.0"
    },
    "autoload": {
        "psr-4": {
            "_ContaoManager\\Symfony\\Component\\PropertyAccess\\": ""
        },
        "exclude-from-classmap": [
            "\/Tests\/"
        ]
    },
    "minimum-stability": "dev"
}<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Finder;

/**
 * Extends \SplFileInfo to support relative paths.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class SplFileInfo extends \SplFileInfo
{
    private string $relativePath;
    private string $relativePathname;
    /**
     * @param string $file             The file name
     * @param string $relativePath     The relative path
     * @param string $relativePathname The relative path name
     */
    public function __construct(string $file, string $relativePath, string $relativePathname)
    {
        parent::__construct($file);
        $this->relativePath = $relativePath;
        $this->relativePathname = $relativePathname;
    }
    /**
     * Returns the relative path.
     *
     * This path does not contain the file name.
     */
    public function getRelativePath(): string
    {
        return $this->relativePath;
    }
    /**
     * Returns the relative path name.
     *
     * This path contains the file name.
     */
    public function getRelativePathname(): string
    {
        return $this->relativePathname;
    }
    public function getFilenameWithoutExtension(): string
    {
        $filename = $this->getFilename();
        return pathinfo($filename, \PATHINFO_FILENAME);
    }
    /**
     * Returns the contents of the file.
     *
     * @throws \RuntimeException
     */
    public function getContents(): string
    {
        set_error_handler(function ($type, $msg) use (&$error) {
            $error = $msg;
        });
        try {
            $content = file_get_contents($this->getPathname());
        } finally {
            restore_error_handler();
        }
        if (\false === $content) {
            throw new \RuntimeException($error);
        }
        return $content;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Finder\Comparator;

/**
 * NumberComparator compiles a simple comparison to an anonymous
 * subroutine, which you can call with a value to be tested again.
 *
 * Now this would be very pointless, if NumberCompare didn't understand
 * magnitudes.
 *
 * The target value may use magnitudes of kilobytes (k, ki),
 * megabytes (m, mi), or gigabytes (g, gi).  Those suffixed
 * with an i use the appropriate 2**n version in accordance with the
 * IEC standard: http://physics.nist.gov/cuu/Units/binary.html
 *
 * Based on the Perl Number::Compare module.
 *
 * @author    Fabien Potencier <fabien@symfony.com> PHP port
 * @author    Richard Clamp <richardc@unixbeard.net> Perl version
 * @copyright 2004-2005 Fabien Potencier <fabien@symfony.com>
 * @copyright 2002 Richard Clamp <richardc@unixbeard.net>
 *
 * @see http://physics.nist.gov/cuu/Units/binary.html
 */
class NumberComparator extends Comparator
{
    /**
     * @param string|null $test A comparison string or null
     *
     * @throws \InvalidArgumentException If the test is not understood
     */
    public function __construct(?string $test)
    {
        if (null === $test || !preg_match('#^\s*(==|!=|[<>]=?)?\s*([0-9\.]+)\s*([kmg]i?)?\s*$#i', $test, $matches)) {
            throw new \InvalidArgumentException(\sprintf('Don\'t understand "%s" as a number test.', $test ?? 'null'));
        }
        $target = $matches[2];
        if (!is_numeric($target)) {
            throw new \InvalidArgumentException(\sprintf('Invalid number "%s".', $target));
        }
        if (isset($matches[3])) {
            // magnitude
            switch (strtolower($matches[3])) {
                case 'k':
                    $target *= 1000;
                    break;
                case 'ki':
                    $target *= 1024;
                    break;
                case 'm':
                    $target *= 1000000;
                    break;
                case 'mi':
                    $target *= 1024 * 1024;
                    break;
                case 'g':
                    $target *= 1000000000;
                    break;
                case 'gi':
                    $target *= 1024 * 1024 * 1024;
                    break;
            }
        }
        parent::__construct($target, $matches[1] ?: '==');
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Finder\Comparator;

/**
 * @author Fabien Potencier <fabien@symfony.com>
 */
class Comparator
{
    private string $target;
    private string $operator;
    public function __construct(string $target, string $operator = '==')
    {
        if (!\in_array($operator, ['>', '<', '>=', '<=', '==', '!='])) {
            throw new \InvalidArgumentException(\sprintf('Invalid operator "%s".', $operator));
        }
        $this->target = $target;
        $this->operator = $operator;
    }
    /**
     * Gets the target value.
     */
    public function getTarget(): string
    {
        return $this->target;
    }
    /**
     * Gets the comparison operator.
     */
    public function getOperator(): string
    {
        return $this->operator;
    }
    /**
     * Tests against the target.
     */
    public function test(mixed $test): bool
    {
        return match ($this->operator) {
            '>' => $test > $this->target,
            '>=' => $test >= $this->target,
            '<' => $test < $this->target,
            '<=' => $test <= $this->target,
            '!=' => $test != $this->target,
            default => $test == $this->target,
        };
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Finder\Comparator;

/**
 * DateCompare compiles date comparisons.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class DateComparator extends Comparator
{
    /**
     * @param string $test A comparison string
     *
     * @throws \InvalidArgumentException If the test is not understood
     */
    public function __construct(string $test)
    {
        if (!preg_match('#^\s*(==|!=|[<>]=?|after|since|before|until)?\s*(.+?)\s*$#i', $test, $matches)) {
            throw new \InvalidArgumentException(\sprintf('Don\'t understand "%s" as a date test.', $test));
        }
        try {
            $date = new \DateTimeImmutable($matches[2]);
            $target = $date->format('U');
        } catch (\Exception) {
            throw new \InvalidArgumentException(\sprintf('"%s" is not a valid date.', $matches[2]));
        }
        $operator = $matches[1] ?: '==';
        if ('since' === $operator || 'after' === $operator) {
            $operator = '>';
        }
        if ('until' === $operator || 'before' === $operator) {
            $operator = '<';
        }
        parent::__construct($target, $operator);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Finder;

use _ContaoManager\Symfony\Component\Finder\Comparator\DateComparator;
use _ContaoManager\Symfony\Component\Finder\Comparator\NumberComparator;
use _ContaoManager\Symfony\Component\Finder\Exception\DirectoryNotFoundException;
use _ContaoManager\Symfony\Component\Finder\Iterator\CustomFilterIterator;
use _ContaoManager\Symfony\Component\Finder\Iterator\DateRangeFilterIterator;
use _ContaoManager\Symfony\Component\Finder\Iterator\DepthRangeFilterIterator;
use _ContaoManager\Symfony\Component\Finder\Iterator\ExcludeDirectoryFilterIterator;
use _ContaoManager\Symfony\Component\Finder\Iterator\FilecontentFilterIterator;
use _ContaoManager\Symfony\Component\Finder\Iterator\FilenameFilterIterator;
use _ContaoManager\Symfony\Component\Finder\Iterator\LazyIterator;
use _ContaoManager\Symfony\Component\Finder\Iterator\SizeRangeFilterIterator;
use _ContaoManager\Symfony\Component\Finder\Iterator\SortableIterator;
/**
 * Finder allows to build rules to find files and directories.
 *
 * It is a thin wrapper around several specialized iterator classes.
 *
 * All rules may be invoked several times.
 *
 * All methods return the current Finder object to allow chaining:
 *
 *     $finder = Finder::create()->files()->name('*.php')->in(__DIR__);
 *
 * @author Fabien Potencier <fabien@symfony.com>
 *
 * @implements \IteratorAggregate<string, SplFileInfo>
 */
class Finder implements \IteratorAggregate, \Countable
{
    public const IGNORE_VCS_FILES = 1;
    public const IGNORE_DOT_FILES = 2;
    public const IGNORE_VCS_IGNORED_FILES = 4;
    private int $mode = 0;
    private array $names = [];
    private array $notNames = [];
    private array $exclude = [];
    private array $filters = [];
    private array $pruneFilters = [];
    private array $depths = [];
    private array $sizes = [];
    private bool $followLinks = \false;
    private bool $reverseSorting = \false;
    private \Closure|int|false $sort = \false;
    private int $ignore = 0;
    /** @var list<string> */
    private array $dirs = [];
    private array $dates = [];
    /** @var list<iterable<SplFileInfo|\SplFileInfo|string>> */
    private array $iterators = [];
    private array $contains = [];
    private array $notContains = [];
    private array $paths = [];
    private array $notPaths = [];
    private bool $ignoreUnreadableDirs = \false;
    private static array $vcsPatterns = ['.svn', '_svn', 'CVS', '_darcs', '.arch-params', '.monotone', '.bzr', '.git', '.hg'];
    public function __construct()
    {
        $this->ignore = static::IGNORE_VCS_FILES | static::IGNORE_DOT_FILES;
    }
    /**
     * Creates a new Finder.
     */
    public static function create(): static
    {
        return new static();
    }
    /**
     * Restricts the matching to directories only.
     *
     * @return $this
     */
    public function directories(): static
    {
        $this->mode = Iterator\FileTypeFilterIterator::ONLY_DIRECTORIES;
        return $this;
    }
    /**
     * Restricts the matching to files only.
     *
     * @return $this
     */
    public function files(): static
    {
        $this->mode = Iterator\FileTypeFilterIterator::ONLY_FILES;
        return $this;
    }
    /**
     * Adds tests for the directory depth.
     *
     * Usage:
     *
     *     $finder->depth('> 1') // the Finder will start matching at level 1.
     *     $finder->depth('< 3') // the Finder will descend at most 3 levels of directories below the starting point.
     *     $finder->depth(['>= 1', '< 3'])
     *
     * @param string|int|string[]|int[] $levels The depth level expression or an array of depth levels
     *
     * @return $this
     *
     * @see DepthRangeFilterIterator
     * @see NumberComparator
     */
    public function depth(string|int|array $levels): static
    {
        foreach ((array) $levels as $level) {
            $this->depths[] = new NumberComparator($level);
        }
        return $this;
    }
    /**
     * Adds tests for file dates (last modified).
     *
     * The date must be something that strtotime() is able to parse:
     *
     *     $finder->date('since yesterday');
     *     $finder->date('until 2 days ago');
     *     $finder->date('> now - 2 hours');
     *     $finder->date('>= 2005-10-15');
     *     $finder->date(['>= 2005-10-15', '<= 2006-05-27']);
     *
     * @param string|string[] $dates A date range string or an array of date ranges
     *
     * @return $this
     *
     * @see strtotime
     * @see DateRangeFilterIterator
     * @see DateComparator
     */
    public function date(string|array $dates): static
    {
        foreach ((array) $dates as $date) {
            $this->dates[] = new DateComparator($date);
        }
        return $this;
    }
    /**
     * Adds rules that files must match.
     *
     * You can use patterns (delimited with / sign), globs or simple strings.
     *
     *     $finder->name('/\.php$/')
     *     $finder->name('*.php') // same as above, without dot files
     *     $finder->name('test.php')
     *     $finder->name(['test.py', 'test.php'])
     *
     * @param string|string[] $patterns A pattern (a regexp, a glob, or a string) or an array of patterns
     *
     * @return $this
     *
     * @see FilenameFilterIterator
     */
    public function name(string|array $patterns): static
    {
        $this->names = array_merge($this->names, (array) $patterns);
        return $this;
    }
    /**
     * Adds rules that files must not match.
     *
     * @param string|string[] $patterns A pattern (a regexp, a glob, or a string) or an array of patterns
     *
     * @return $this
     *
     * @see FilenameFilterIterator
     */
    public function notName(string|array $patterns): static
    {
        $this->notNames = array_merge($this->notNames, (array) $patterns);
        return $this;
    }
    /**
     * Adds tests that file contents must match.
     *
     * Strings or PCRE patterns can be used:
     *
     *     $finder->contains('Lorem ipsum')
     *     $finder->contains('/Lorem ipsum/i')
     *     $finder->contains(['dolor', '/ipsum/i'])
     *
     * @param string|string[] $patterns A pattern (string or regexp) or an array of patterns
     *
     * @return $this
     *
     * @see FilecontentFilterIterator
     */
    public function contains(string|array $patterns): static
    {
        $this->contains = array_merge($this->contains, (array) $patterns);
        return $this;
    }
    /**
     * Adds tests that file contents must not match.
     *
     * Strings or PCRE patterns can be used:
     *
     *     $finder->notContains('Lorem ipsum')
     *     $finder->notContains('/Lorem ipsum/i')
     *     $finder->notContains(['lorem', '/dolor/i'])
     *
     * @param string|string[] $patterns A pattern (string or regexp) or an array of patterns
     *
     * @return $this
     *
     * @see FilecontentFilterIterator
     */
    public function notContains(string|array $patterns): static
    {
        $this->notContains = array_merge($this->notContains, (array) $patterns);
        return $this;
    }
    /**
     * Adds rules that filenames must match.
     *
     * You can use patterns (delimited with / sign) or simple strings.
     *
     *     $finder->path('some/special/dir')
     *     $finder->path('/some\/special\/dir/') // same as above
     *     $finder->path(['some dir', 'another/dir'])
     *
     * Use only / as dirname separator.
     *
     * @param string|string[] $patterns A pattern (a regexp or a string) or an array of patterns
     *
     * @return $this
     *
     * @see FilenameFilterIterator
     */
    public function path(string|array $patterns): static
    {
        $this->paths = array_merge($this->paths, (array) $patterns);
        return $this;
    }
    /**
     * Adds rules that filenames must not match.
     *
     * You can use patterns (delimited with / sign) or simple strings.
     *
     *     $finder->notPath('some/special/dir')
     *     $finder->notPath('/some\/special\/dir/') // same as above
     *     $finder->notPath(['some/file.txt', 'another/file.log'])
     *
     * Use only / as dirname separator.
     *
     * @param string|string[] $patterns A pattern (a regexp or a string) or an array of patterns
     *
     * @return $this
     *
     * @see FilenameFilterIterator
     */
    public function notPath(string|array $patterns): static
    {
        $this->notPaths = array_merge($this->notPaths, (array) $patterns);
        return $this;
    }
    /**
     * Adds tests for file sizes.
     *
     *     $finder->size('> 10K');
     *     $finder->size('<= 1Ki');
     *     $finder->size(4);
     *     $finder->size(['> 10K', '< 20K'])
     *
     * @param string|int|string[]|int[] $sizes A size range string or an integer or an array of size ranges
     *
     * @return $this
     *
     * @see SizeRangeFilterIterator
     * @see NumberComparator
     */
    public function size(string|int|array $sizes): static
    {
        foreach ((array) $sizes as $size) {
            $this->sizes[] = new NumberComparator($size);
        }
        return $this;
    }
    /**
     * Excludes directories.
     *
     * Directories passed as argument must be relative to the ones defined with the `in()` method. For example:
     *
     *     $finder->in(__DIR__)->exclude('ruby');
     *
     * @param string|array $dirs A directory path or an array of directories
     *
     * @return $this
     *
     * @see ExcludeDirectoryFilterIterator
     */
    public function exclude(string|array $dirs): static
    {
        $this->exclude = array_merge($this->exclude, (array) $dirs);
        return $this;
    }
    /**
     * Excludes "hidden" directories and files (starting with a dot).
     *
     * This option is enabled by default.
     *
     * @return $this
     *
     * @see ExcludeDirectoryFilterIterator
     */
    public function ignoreDotFiles(bool $ignoreDotFiles): static
    {
        if ($ignoreDotFiles) {
            $this->ignore |= static::IGNORE_DOT_FILES;
        } else {
            $this->ignore &= ~static::IGNORE_DOT_FILES;
        }
        return $this;
    }
    /**
     * Forces the finder to ignore version control directories.
     *
     * This option is enabled by default.
     *
     * @return $this
     *
     * @see ExcludeDirectoryFilterIterator
     */
    public function ignoreVCS(bool $ignoreVCS): static
    {
        if ($ignoreVCS) {
            $this->ignore |= static::IGNORE_VCS_FILES;
        } else {
            $this->ignore &= ~static::IGNORE_VCS_FILES;
        }
        return $this;
    }
    /**
     * Forces Finder to obey .gitignore and ignore files based on rules listed there.
     *
     * This option is disabled by default.
     *
     * @return $this
     */
    public function ignoreVCSIgnored(bool $ignoreVCSIgnored): static
    {
        if ($ignoreVCSIgnored) {
            $this->ignore |= static::IGNORE_VCS_IGNORED_FILES;
        } else {
            $this->ignore &= ~static::IGNORE_VCS_IGNORED_FILES;
        }
        return $this;
    }
    /**
     * Adds VCS patterns.
     *
     * @see ignoreVCS()
     *
     * @param string|string[] $pattern VCS patterns to ignore
     *
     * @return void
     */
    public static function addVCSPattern(string|array $pattern)
    {
        foreach ((array) $pattern as $p) {
            self::$vcsPatterns[] = $p;
        }
        self::$vcsPatterns = array_unique(self::$vcsPatterns);
    }
    /**
     * Sorts files and directories by an anonymous function.
     *
     * The anonymous function receives two \SplFileInfo instances to compare.
     *
     * This can be slow as all the matching files and directories must be retrieved for comparison.
     *
     * @return $this
     *
     * @see SortableIterator
     */
    public function sort(\Closure $closure): static
    {
        $this->sort = $closure;
        return $this;
    }
    /**
     * Sorts files and directories by extension.
     *
     * This can be slow as all the matching files and directories must be retrieved for comparison.
     *
     * @return $this
     *
     * @see SortableIterator
     */
    public function sortByExtension(): static
    {
        $this->sort = SortableIterator::SORT_BY_EXTENSION;
        return $this;
    }
    /**
     * Sorts files and directories by name.
     *
     * This can be slow as all the matching files and directories must be retrieved for comparison.
     *
     * @return $this
     *
     * @see SortableIterator
     */
    public function sortByName(bool $useNaturalSort = \false): static
    {
        $this->sort = $useNaturalSort ? SortableIterator::SORT_BY_NAME_NATURAL : SortableIterator::SORT_BY_NAME;
        return $this;
    }
    /**
     * Sorts files and directories by name case insensitive.
     *
     * This can be slow as all the matching files and directories must be retrieved for comparison.
     *
     * @return $this
     *
     * @see SortableIterator
     */
    public function sortByCaseInsensitiveName(bool $useNaturalSort = \false): static
    {
        $this->sort = $useNaturalSort ? SortableIterator::SORT_BY_NAME_NATURAL_CASE_INSENSITIVE : SortableIterator::SORT_BY_NAME_CASE_INSENSITIVE;
        return $this;
    }
    /**
     * Sorts files and directories by size.
     *
     * This can be slow as all the matching files and directories must be retrieved for comparison.
     *
     * @return $this
     *
     * @see SortableIterator
     */
    public function sortBySize(): static
    {
        $this->sort = SortableIterator::SORT_BY_SIZE;
        return $this;
    }
    /**
     * Sorts files and directories by type (directories before files), then by name.
     *
     * This can be slow as all the matching files and directories must be retrieved for comparison.
     *
     * @return $this
     *
     * @see SortableIterator
     */
    public function sortByType(): static
    {
        $this->sort = SortableIterator::SORT_BY_TYPE;
        return $this;
    }
    /**
     * Sorts files and directories by the last accessed time.
     *
     * This is the time that the file was last accessed, read or written to.
     *
     * This can be slow as all the matching files and directories must be retrieved for comparison.
     *
     * @return $this
     *
     * @see SortableIterator
     */
    public function sortByAccessedTime(): static
    {
        $this->sort = SortableIterator::SORT_BY_ACCESSED_TIME;
        return $this;
    }
    /**
     * Reverses the sorting.
     *
     * @return $this
     */
    public function reverseSorting(): static
    {
        $this->reverseSorting = \true;
        return $this;
    }
    /**
     * Sorts files and directories by the last inode changed time.
     *
     * This is the time that the inode information was last modified (permissions, owner, group or other metadata).
     *
     * On Windows, since inode is not available, changed time is actually the file creation time.
     *
     * This can be slow as all the matching files and directories must be retrieved for comparison.
     *
     * @return $this
     *
     * @see SortableIterator
     */
    public function sortByChangedTime(): static
    {
        $this->sort = SortableIterator::SORT_BY_CHANGED_TIME;
        return $this;
    }
    /**
     * Sorts files and directories by the last modified time.
     *
     * This is the last time the actual contents of the file were last modified.
     *
     * This can be slow as all the matching files and directories must be retrieved for comparison.
     *
     * @return $this
     *
     * @see SortableIterator
     */
    public function sortByModifiedTime(): static
    {
        $this->sort = SortableIterator::SORT_BY_MODIFIED_TIME;
        return $this;
    }
    /**
     * Filters the iterator with an anonymous function.
     *
     * The anonymous function receives a \SplFileInfo and must return false
     * to remove files.
     *
     * @param \Closure(SplFileInfo): bool $closure
     * @param bool                        $prune   Whether to skip traversing directories further
     *
     * @return $this
     *
     * @see CustomFilterIterator
     */
    public function filter(\Closure $closure): static
    {
        $prune = 1 < \func_num_args() ? func_get_arg(1) : \false;
        $this->filters[] = $closure;
        if ($prune) {
            $this->pruneFilters[] = $closure;
        }
        return $this;
    }
    /**
     * Forces the following of symlinks.
     *
     * @return $this
     */
    public function followLinks(): static
    {
        $this->followLinks = \true;
        return $this;
    }
    /**
     * Tells finder to ignore unreadable directories.
     *
     * By default, scanning unreadable directories content throws an AccessDeniedException.
     *
     * @return $this
     */
    public function ignoreUnreadableDirs(bool $ignore = \true): static
    {
        $this->ignoreUnreadableDirs = $ignore;
        return $this;
    }
    /**
     * Searches files and directories which match defined rules.
     *
     * @param string|string[] $dirs A directory path or an array of directories
     *
     * @return $this
     *
     * @throws DirectoryNotFoundException if one of the directories does not exist
     */
    public function in(string|array $dirs): static
    {
        $resolvedDirs = [];
        foreach ((array) $dirs as $dir) {
            if (is_dir($dir)) {
                $resolvedDirs[] = [$this->normalizeDir($dir)];
            } elseif ($glob = glob($dir, (\defined('GLOB_BRACE') ? \GLOB_BRACE : 0) | \GLOB_ONLYDIR | \GLOB_NOSORT)) {
                sort($glob);
                $resolvedDirs[] = array_map($this->normalizeDir(...), $glob);
            } else {
                throw new DirectoryNotFoundException(\sprintf('The "%s" directory does not exist.', $dir));
            }
        }
        $this->dirs = array_merge($this->dirs, ...$resolvedDirs);
        return $this;
    }
    /**
     * Returns an Iterator for the current Finder configuration.
     *
     * This method implements the IteratorAggregate interface.
     *
     * @return \Iterator<string, SplFileInfo>
     *
     * @throws \LogicException if the in() method has not been called
     */
    public function getIterator(): \Iterator
    {
        if (!$this->dirs && !$this->iterators) {
            throw new \LogicException('You must call one of in() or append() methods before iterating over a Finder.');
        }
        if (1 === \count($this->dirs) && !$this->iterators) {
            $iterator = $this->searchInDirectory($this->dirs[0]);
        } else {
            $iterator = new \AppendIterator();
            foreach ($this->dirs as $dir) {
                $iterator->append(new \IteratorIterator(new LazyIterator(fn() => $this->searchInDirectory($dir))));
            }
            foreach ($this->iterators as $it) {
                $iterator->append(new \IteratorIterator(new LazyIterator(static function () use ($it) {
                    foreach ($it as $file) {
                        if (!$file instanceof \SplFileInfo) {
                            $file = new \SplFileInfo($file);
                        }
                        $key = $file->getPathname();
                        if (!$file instanceof SplFileInfo) {
                            $file = new SplFileInfo($key, $file->getPath(), $key);
                        }
                        yield $key => $file;
                    }
                })));
            }
        }
        if ($this->sort || $this->reverseSorting) {
            $iterator = (new SortableIterator($iterator, $this->sort, $this->reverseSorting))->getIterator();
        }
        return $iterator;
    }
    /**
     * Appends an existing set of files/directories to the finder.
     *
     * The set can be another Finder, an Iterator, an IteratorAggregate, or even a plain array.
     *
     * @param iterable<SplFileInfo|\SplFileInfo|string> $iterator
     *
     * @return $this
     */
    public function append(iterable $iterator): static
    {
        $this->iterators[] = $iterator;
        return $this;
    }
    /**
     * Check if any results were found.
     */
    public function hasResults(): bool
    {
        foreach ($this->getIterator() as $_) {
            return \true;
        }
        return \false;
    }
    /**
     * Counts all the results collected by the iterators.
     */
    public function count(): int
    {
        return iterator_count($this->getIterator());
    }
    private function searchInDirectory(string $dir): \Iterator
    {
        $exclude = $this->exclude;
        $notPaths = $this->notPaths;
        if ($this->pruneFilters) {
            $exclude = array_merge($exclude, $this->pruneFilters);
        }
        if (static::IGNORE_VCS_FILES === (static::IGNORE_VCS_FILES & $this->ignore)) {
            $exclude = array_merge($exclude, self::$vcsPatterns);
        }
        if (static::IGNORE_DOT_FILES === (static::IGNORE_DOT_FILES & $this->ignore)) {
            $notPaths[] = '#(^|/)\..+(/|$)#';
        }
        $minDepth = 0;
        $maxDepth = \PHP_INT_MAX;
        foreach ($this->depths as $comparator) {
            switch ($comparator->getOperator()) {
                case '>':
                    $minDepth = $comparator->getTarget() + 1;
                    break;
                case '>=':
                    $minDepth = $comparator->getTarget();
                    break;
                case '<':
                    $maxDepth = $comparator->getTarget() - 1;
                    break;
                case '<=':
                    $maxDepth = $comparator->getTarget();
                    break;
                default:
                    $minDepth = $maxDepth = $comparator->getTarget();
            }
        }
        $flags = \RecursiveDirectoryIterator::SKIP_DOTS;
        if ($this->followLinks) {
            $flags |= \RecursiveDirectoryIterator::FOLLOW_SYMLINKS;
        }
        $iterator = new Iterator\RecursiveDirectoryIterator($dir, $flags, $this->ignoreUnreadableDirs);
        if ($exclude) {
            $iterator = new ExcludeDirectoryFilterIterator($iterator, $exclude);
        }
        $iterator = new \RecursiveIteratorIterator($iterator, \RecursiveIteratorIterator::SELF_FIRST);
        if ($minDepth > 0 || $maxDepth < \PHP_INT_MAX) {
            $iterator = new DepthRangeFilterIterator($iterator, $minDepth, $maxDepth);
        }
        if ($this->mode) {
            $iterator = new Iterator\FileTypeFilterIterator($iterator, $this->mode);
        }
        if ($this->names || $this->notNames) {
            $iterator = new FilenameFilterIterator($iterator, $this->names, $this->notNames);
        }
        if ($this->contains || $this->notContains) {
            $iterator = new FilecontentFilterIterator($iterator, $this->contains, $this->notContains);
        }
        if ($this->sizes) {
            $iterator = new SizeRangeFilterIterator($iterator, $this->sizes);
        }
        if ($this->dates) {
            $iterator = new DateRangeFilterIterator($iterator, $this->dates);
        }
        if ($this->filters) {
            $iterator = new CustomFilterIterator($iterator, $this->filters);
        }
        if ($this->paths || $notPaths) {
            $iterator = new Iterator\PathFilterIterator($iterator, $this->paths, $notPaths);
        }
        if (static::IGNORE_VCS_IGNORED_FILES === (static::IGNORE_VCS_IGNORED_FILES & $this->ignore)) {
            $iterator = new Iterator\VcsIgnoredFilterIterator($iterator, $dir);
        }
        return $iterator;
    }
    /**
     * Normalizes given directory names by removing trailing slashes.
     *
     * Excluding: (s)ftp:// or ssh2.(s)ftp:// wrapper
     */
    private function normalizeDir(string $dir): string
    {
        if ('/' === $dir) {
            return $dir;
        }
        $dir = rtrim($dir, '/' . \DIRECTORY_SEPARATOR);
        if (preg_match('#^(ssh2\.)?s?ftp://#', $dir)) {
            $dir .= '/';
        }
        return $dir;
    }
}
/**
 * Finder allows to build rules to find files and directories.
 *
 * It is a thin wrapper around several specialized iterator classes.
 *
 * All rules may be invoked several times.
 *
 * All methods return the current Finder object to allow chaining:
 *
 *     $finder = Finder::create()->files()->name('*.php')->in(__DIR__);
 *
 * @author Fabien Potencier <fabien@symfony.com>
 *
 * @implements \IteratorAggregate<string, SplFileInfo>
 */
\class_alias('_ContaoManager\Symfony\Component\Finder\Finder', 'Symfony\Component\Finder\Finder', \false);
Copyright (c) 2004-present Fabien Potencier

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is furnished
to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
CHANGELOG
=========

6.4
---

 * Add early directory pruning to `Finder::filter()`

6.2
---

 * Add `Finder::sortByExtension()` and `Finder::sortBySize()`
 * Add `Finder::sortByCaseInsensitiveName()` to sort by name with case insensitive sorting methods

6.0
---

 * Remove `Comparator::setTarget()` and `Comparator::setOperator()`

5.4.0
-----

 * Deprecate `Comparator::setTarget()` and `Comparator::setOperator()`
 * Add a constructor to `Comparator` that allows setting target and operator
 * Finder's iterator has now `Symfony\Component\Finder\SplFileInfo` inner type specified
 * Add recursive .gitignore files support

5.0.0
-----

 * added `$useNaturalSort` argument to `Finder::sortByName()`

4.3.0
-----

 * added Finder::ignoreVCSIgnored() to ignore files based on rules listed in .gitignore

4.2.0
-----

 * added $useNaturalSort option to Finder::sortByName() method
 * the `Finder::sortByName()` method will have a new `$useNaturalSort`
   argument in version 5.0, not defining it is deprecated
 * added `Finder::reverseSorting()` to reverse the sorting

4.0.0
-----

 * removed `ExceptionInterface`
 * removed `Symfony\Component\Finder\Iterator\FilterIterator`

3.4.0
-----

 * deprecated `Symfony\Component\Finder\Iterator\FilterIterator`
 * added Finder::hasResults() method to check if any results were found

3.3.0
-----

 * added double-star matching to Glob::toRegex()

3.0.0
-----

 * removed deprecated classes

2.8.0
-----

 * deprecated adapters and related classes

2.5.0
-----
 * added support for GLOB_BRACE in the paths passed to Finder::in()

2.3.0
-----

 * added a way to ignore unreadable directories (via Finder::ignoreUnreadableDirs())
 * unified the way subfolders that are not executable are handled by always throwing an AccessDeniedException exception

2.2.0
-----

 * added Finder::path() and Finder::notPath() methods
 * added finder adapters to improve performance on specific platforms
 * added support for wildcard characters (glob patterns) in the paths passed
   to Finder::in()

2.1.0
-----

 * added Finder::sortByAccessedTime(), Finder::sortByChangedTime(), and
   Finder::sortByModifiedTime()
 * added Countable to Finder
 * added support for an array of directories as an argument to
   Finder::exclude()
 * added searching based on the file content via Finder::contains() and
   Finder::notContains()
 * added support for the != operator in the Comparator
 * [BC BREAK] filter expressions (used for file name and content) are no more
   considered as regexps but glob patterns when they are enclosed in '*' or '?'
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Finder;

/**
 * Glob matches globbing patterns against text.
 *
 *     if match_glob("foo.*", "foo.bar") echo "matched\n";
 *
 *     // prints foo.bar and foo.baz
 *     $regex = glob_to_regex("foo.*");
 *     for (['foo.bar', 'foo.baz', 'foo', 'bar'] as $t)
 *     {
 *         if (/$regex/) echo "matched: $car\n";
 *     }
 *
 * Glob implements glob(3) style matching that can be used to match
 * against text, rather than fetching names from a filesystem.
 *
 * Based on the Perl Text::Glob module.
 *
 * @author Fabien Potencier <fabien@symfony.com> PHP port
 * @author     Richard Clamp <richardc@unixbeard.net> Perl version
 * @copyright  2004-2005 Fabien Potencier <fabien@symfony.com>
 * @copyright  2002 Richard Clamp <richardc@unixbeard.net>
 */
class Glob
{
    /**
     * Returns a regexp which is the equivalent of the glob pattern.
     */
    public static function toRegex(string $glob, bool $strictLeadingDot = \true, bool $strictWildcardSlash = \true, string $delimiter = '#'): string
    {
        $firstByte = \true;
        $escaping = \false;
        $inCurlies = 0;
        $regex = '';
        if ($unanchored = str_starts_with($glob, '**/')) {
            $glob = '/' . $glob;
        }
        $sizeGlob = \strlen($glob);
        for ($i = 0; $i < $sizeGlob; ++$i) {
            $car = $glob[$i];
            if ($firstByte && $strictLeadingDot && '.' !== $car) {
                $regex .= '(?=[^\.])';
            }
            $firstByte = '/' === $car;
            if ($firstByte && $strictWildcardSlash && isset($glob[$i + 2]) && '**' === $glob[$i + 1] . $glob[$i + 2] && (!isset($glob[$i + 3]) || '/' === $glob[$i + 3])) {
                $car = '[^/]++/';
                if (!isset($glob[$i + 3])) {
                    $car .= '?';
                }
                if ($strictLeadingDot) {
                    $car = '(?=[^\.])' . $car;
                }
                $car = '/(?:' . $car . ')*';
                $i += 2 + isset($glob[$i + 3]);
                if ('/' === $delimiter) {
                    $car = str_replace('/', '\/', $car);
                }
            }
            if ($delimiter === $car || '.' === $car || '(' === $car || ')' === $car || '|' === $car || '+' === $car || '^' === $car || '$' === $car) {
                $regex .= "\\{$car}";
            } elseif ('*' === $car) {
                $regex .= $escaping ? '\*' : ($strictWildcardSlash ? '[^/]*' : '.*');
            } elseif ('?' === $car) {
                $regex .= $escaping ? '\?' : ($strictWildcardSlash ? '[^/]' : '.');
            } elseif ('{' === $car) {
                $regex .= $escaping ? '\{' : '(';
                if (!$escaping) {
                    ++$inCurlies;
                }
            } elseif ('}' === $car && $inCurlies) {
                $regex .= $escaping ? '}' : ')';
                if (!$escaping) {
                    --$inCurlies;
                }
            } elseif (',' === $car && $inCurlies) {
                $regex .= $escaping ? ',' : '|';
            } elseif ('\\' === $car) {
                if ($escaping) {
                    $regex .= '\\\\';
                    $escaping = \false;
                } else {
                    $escaping = \true;
                }
                continue;
            } else {
                $regex .= $car;
            }
            $escaping = \false;
        }
        if ($unanchored) {
            $regex = substr_replace($regex, '?', 1 + ('/' === $delimiter) + ($strictLeadingDot ? \strlen('(?=[^\.])') : 0), 0);
        }
        return $delimiter . '^' . $regex . '$' . $delimiter;
    }
}
Finder Component
================

The Finder component finds files and directories via an intuitive fluent
interface.

Resources
---------

 * [Documentation](https://symfony.com/doc/current/components/finder.html)
 * [Contributing](https://symfony.com/doc/current/contributing/index.html)
 * [Report issues](https://github.com/symfony/symfony/issues) and
   [send Pull Requests](https://github.com/symfony/symfony/pulls)
   in the [main Symfony repository](https://github.com/symfony/symfony)
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Finder\Iterator;

/**
 * @author Jérémy Derussé <jeremy@derusse.com>
 *
 * @internal
 */
class LazyIterator implements \IteratorAggregate
{
    private \Closure $iteratorFactory;
    public function __construct(callable $iteratorFactory)
    {
        $this->iteratorFactory = $iteratorFactory(...);
    }
    public function getIterator(): \Traversable
    {
        yield from ($this->iteratorFactory)();
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Finder\Iterator;

use _ContaoManager\Symfony\Component\Finder\Gitignore;
/**
 * @extends \FilterIterator<string, \SplFileInfo>
 */
final class VcsIgnoredFilterIterator extends \FilterIterator
{
    private string $baseDir;
    /**
     * @var array<string, array{0: string, 1: string}|null>
     */
    private array $gitignoreFilesCache = [];
    /**
     * @var array<string, bool>
     */
    private array $ignoredPathsCache = [];
    /**
     * @param \Iterator<string, \SplFileInfo> $iterator
     */
    public function __construct(\Iterator $iterator, string $baseDir)
    {
        $this->baseDir = $this->normalizePath($baseDir);
        foreach ([$this->baseDir, ...$this->parentDirectoriesUpwards($this->baseDir)] as $directory) {
            if (@is_dir("{$directory}/.git")) {
                $this->baseDir = $directory;
                break;
            }
        }
        parent::__construct($iterator);
    }
    public function accept(): bool
    {
        $file = $this->current();
        $fileRealPath = $this->normalizePath($file->getRealPath());
        return !$this->isIgnored($fileRealPath);
    }
    private function isIgnored(string $fileRealPath): bool
    {
        if (is_dir($fileRealPath) && !str_ends_with($fileRealPath, '/')) {
            $fileRealPath .= '/';
        }
        if (isset($this->ignoredPathsCache[$fileRealPath])) {
            return $this->ignoredPathsCache[$fileRealPath];
        }
        $ignored = \false;
        foreach ($this->parentDirectoriesDownwards($fileRealPath) as $parentDirectory) {
            if ($this->isIgnored($parentDirectory)) {
                // rules in ignored directories are ignored, no need to check further.
                break;
            }
            $fileRelativePath = substr($fileRealPath, \strlen($parentDirectory) + 1);
            if (null === $regexps = $this->readGitignoreFile("{$parentDirectory}/.gitignore")) {
                continue;
            }
            [$exclusionRegex, $inclusionRegex] = $regexps;
            if (preg_match($exclusionRegex, $fileRelativePath)) {
                $ignored = \true;
                continue;
            }
            if (preg_match($inclusionRegex, $fileRelativePath)) {
                $ignored = \false;
            }
        }
        return $this->ignoredPathsCache[$fileRealPath] = $ignored;
    }
    /**
     * @return list<string>
     */
    private function parentDirectoriesUpwards(string $from): array
    {
        $parentDirectories = [];
        $parentDirectory = $from;
        while (\true) {
            $newParentDirectory = \dirname($parentDirectory);
            // dirname('/') = '/'
            if ($newParentDirectory === $parentDirectory) {
                break;
            }
            $parentDirectories[] = $parentDirectory = $newParentDirectory;
        }
        return $parentDirectories;
    }
    private function parentDirectoriesUpTo(string $from, string $upTo): array
    {
        return array_filter($this->parentDirectoriesUpwards($from), static fn(string $directory): bool => str_starts_with($directory, $upTo));
    }
    /**
     * @return list<string>
     */
    private function parentDirectoriesDownwards(string $fileRealPath): array
    {
        return array_reverse($this->parentDirectoriesUpTo($fileRealPath, $this->baseDir));
    }
    /**
     * @return array{0: string, 1: string}|null
     */
    private function readGitignoreFile(string $path): ?array
    {
        if (\array_key_exists($path, $this->gitignoreFilesCache)) {
            return $this->gitignoreFilesCache[$path];
        }
        if (!file_exists($path)) {
            return $this->gitignoreFilesCache[$path] = null;
        }
        if (!is_file($path) || !is_readable($path)) {
            throw new \RuntimeException("The \"ignoreVCSIgnored\" option cannot be used by the Finder as the \"{$path}\" file is not readable.");
        }
        $gitignoreFileContent = file_get_contents($path);
        return $this->gitignoreFilesCache[$path] = [Gitignore::toRegex($gitignoreFileContent), Gitignore::toRegexMatchingNegatedPatterns($gitignoreFileContent)];
    }
    private function normalizePath(string $path): string
    {
        if ('\\' === \DIRECTORY_SEPARATOR) {
            return str_replace('\\', '/', $path);
        }
        return $path;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Finder\Iterator;

use _ContaoManager\Symfony\Component\Finder\SplFileInfo;
/**
 * FilecontentFilterIterator filters files by their contents using patterns (regexps or strings).
 *
 * @author Fabien Potencier  <fabien@symfony.com>
 * @author Włodzimierz Gajda <gajdaw@gajdaw.pl>
 *
 * @extends MultiplePcreFilterIterator<string, SplFileInfo>
 */
class FilecontentFilterIterator extends MultiplePcreFilterIterator
{
    /**
     * Filters the iterator values.
     */
    public function accept(): bool
    {
        if (!$this->matchRegexps && !$this->noMatchRegexps) {
            return \true;
        }
        $fileinfo = $this->current();
        if ($fileinfo->isDir() || !$fileinfo->isReadable()) {
            return \false;
        }
        $content = $fileinfo->getContents();
        if (!$content) {
            return \false;
        }
        return $this->isAccepted($content);
    }
    /**
     * Converts string to regexp if necessary.
     *
     * @param string $str Pattern: string or regexp
     */
    protected function toRegex(string $str): string
    {
        return $this->isRegex($str) ? $str : '/' . preg_quote($str, '/') . '/';
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Finder\Iterator;

/**
 * MultiplePcreFilterIterator filters files using patterns (regexps, globs or strings).
 *
 * @author Fabien Potencier <fabien@symfony.com>
 *
 * @template-covariant TKey
 * @template-covariant TValue
 *
 * @extends \FilterIterator<TKey, TValue>
 */
abstract class MultiplePcreFilterIterator extends \FilterIterator
{
    protected $matchRegexps = [];
    protected $noMatchRegexps = [];
    /**
     * @param \Iterator<TKey, TValue> $iterator        The Iterator to filter
     * @param string[]                $matchPatterns   An array of patterns that need to match
     * @param string[]                $noMatchPatterns An array of patterns that need to not match
     */
    public function __construct(\Iterator $iterator, array $matchPatterns, array $noMatchPatterns)
    {
        foreach ($matchPatterns as $pattern) {
            $this->matchRegexps[] = $this->toRegex($pattern);
        }
        foreach ($noMatchPatterns as $pattern) {
            $this->noMatchRegexps[] = $this->toRegex($pattern);
        }
        parent::__construct($iterator);
    }
    /**
     * Checks whether the string is accepted by the regex filters.
     *
     * If there is no regexps defined in the class, this method will accept the string.
     * Such case can be handled by child classes before calling the method if they want to
     * apply a different behavior.
     */
    protected function isAccepted(string $string): bool
    {
        // should at least not match one rule to exclude
        foreach ($this->noMatchRegexps as $regex) {
            if (preg_match($regex, $string)) {
                return \false;
            }
        }
        // should at least match one rule
        if ($this->matchRegexps) {
            foreach ($this->matchRegexps as $regex) {
                if (preg_match($regex, $string)) {
                    return \true;
                }
            }
            return \false;
        }
        // If there is no match rules, the file is accepted
        return \true;
    }
    /**
     * Checks whether the string is a regex.
     */
    protected function isRegex(string $str): bool
    {
        $availableModifiers = 'imsxuADU';
        if (\PHP_VERSION_ID >= 80200) {
            $availableModifiers .= 'n';
        }
        if (preg_match('/^(.{3,}?)[' . $availableModifiers . ']*$/', $str, $m)) {
            $start = substr($m[1], 0, 1);
            $end = substr($m[1], -1);
            if ($start === $end) {
                return !preg_match('/[*?[:alnum:] \\\\]/', $start);
            }
            foreach ([['{', '}'], ['(', ')'], ['[', ']'], ['<', '>']] as $delimiters) {
                if ($start === $delimiters[0] && $end === $delimiters[1]) {
                    return \true;
                }
            }
        }
        return \false;
    }
    /**
     * Converts string into regexp.
     */
    abstract protected function toRegex(string $str): string;
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Finder\Iterator;

use _ContaoManager\Symfony\Component\Finder\Comparator\NumberComparator;
/**
 * SizeRangeFilterIterator filters out files that are not in the given size range.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 *
 * @extends \FilterIterator<string, \SplFileInfo>
 */
class SizeRangeFilterIterator extends \FilterIterator
{
    private array $comparators = [];
    /**
     * @param \Iterator<string, \SplFileInfo> $iterator
     * @param NumberComparator[]              $comparators
     */
    public function __construct(\Iterator $iterator, array $comparators)
    {
        $this->comparators = $comparators;
        parent::__construct($iterator);
    }
    /**
     * Filters the iterator values.
     */
    public function accept(): bool
    {
        $fileinfo = $this->current();
        if (!$fileinfo->isFile()) {
            return \true;
        }
        $filesize = $fileinfo->getSize();
        foreach ($this->comparators as $compare) {
            if (!$compare->test($filesize)) {
                return \false;
            }
        }
        return \true;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Finder\Iterator;

use _ContaoManager\Symfony\Component\Finder\Glob;
/**
 * FilenameFilterIterator filters files by patterns (a regexp, a glob, or a string).
 *
 * @author Fabien Potencier <fabien@symfony.com>
 *
 * @extends MultiplePcreFilterIterator<string, \SplFileInfo>
 */
class FilenameFilterIterator extends MultiplePcreFilterIterator
{
    /**
     * Filters the iterator values.
     */
    public function accept(): bool
    {
        return $this->isAccepted($this->current()->getFilename());
    }
    /**
     * Converts glob to regexp.
     *
     * PCRE patterns are left unchanged.
     * Glob strings are transformed with Glob::toRegex().
     *
     * @param string $str Pattern: glob or regexp
     */
    protected function toRegex(string $str): string
    {
        return $this->isRegex($str) ? $str : Glob::toRegex($str);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Finder\Iterator;

use _ContaoManager\Symfony\Component\Finder\Comparator\DateComparator;
/**
 * DateRangeFilterIterator filters out files that are not in the given date range (last modified dates).
 *
 * @author Fabien Potencier <fabien@symfony.com>
 *
 * @extends \FilterIterator<string, \SplFileInfo>
 */
class DateRangeFilterIterator extends \FilterIterator
{
    private array $comparators = [];
    /**
     * @param \Iterator<string, \SplFileInfo> $iterator
     * @param DateComparator[]                $comparators
     */
    public function __construct(\Iterator $iterator, array $comparators)
    {
        $this->comparators = $comparators;
        parent::__construct($iterator);
    }
    /**
     * Filters the iterator values.
     */
    public function accept(): bool
    {
        $fileinfo = $this->current();
        if (!file_exists($fileinfo->getPathname())) {
            return \false;
        }
        $filedate = $fileinfo->getMTime();
        foreach ($this->comparators as $compare) {
            if (!$compare->test($filedate)) {
                return \false;
            }
        }
        return \true;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Finder\Iterator;

/**
 * CustomFilterIterator filters files by applying anonymous functions.
 *
 * The anonymous function receives a \SplFileInfo and must return false
 * to remove files.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 *
 * @extends \FilterIterator<string, \SplFileInfo>
 */
class CustomFilterIterator extends \FilterIterator
{
    private array $filters = [];
    /**
     * @param \Iterator<string, \SplFileInfo> $iterator The Iterator to filter
     * @param callable[]                      $filters  An array of PHP callbacks
     *
     * @throws \InvalidArgumentException
     */
    public function __construct(\Iterator $iterator, array $filters)
    {
        foreach ($filters as $filter) {
            if (!\is_callable($filter)) {
                throw new \InvalidArgumentException('Invalid PHP callback.');
            }
        }
        $this->filters = $filters;
        parent::__construct($iterator);
    }
    /**
     * Filters the iterator values.
     */
    public function accept(): bool
    {
        $fileinfo = $this->current();
        foreach ($this->filters as $filter) {
            if (\false === $filter($fileinfo)) {
                return \false;
            }
        }
        return \true;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Finder\Iterator;

use _ContaoManager\Symfony\Component\Finder\Exception\AccessDeniedException;
use _ContaoManager\Symfony\Component\Finder\SplFileInfo;
/**
 * Extends the \RecursiveDirectoryIterator to support relative paths.
 *
 * @author Victor Berchet <victor@suumit.com>
 *
 * @extends \RecursiveDirectoryIterator<string, SplFileInfo>
 */
class RecursiveDirectoryIterator extends \RecursiveDirectoryIterator
{
    private bool $ignoreUnreadableDirs;
    private bool $ignoreFirstRewind = \true;
    // these 3 properties take part of the performance optimization to avoid redoing the same work in all iterations
    private string $rootPath;
    private string $subPath;
    private string $directorySeparator = '/';
    /**
     * @throws \RuntimeException
     */
    public function __construct(string $path, int $flags, bool $ignoreUnreadableDirs = \false)
    {
        if ($flags & (self::CURRENT_AS_PATHNAME | self::CURRENT_AS_SELF)) {
            throw new \RuntimeException('This iterator only support returning current as fileinfo.');
        }
        parent::__construct($path, $flags);
        $this->ignoreUnreadableDirs = $ignoreUnreadableDirs;
        $this->rootPath = $path;
        if ('/' !== \DIRECTORY_SEPARATOR && !($flags & self::UNIX_PATHS)) {
            $this->directorySeparator = \DIRECTORY_SEPARATOR;
        }
    }
    /**
     * Return an instance of SplFileInfo with support for relative paths.
     */
    public function current(): SplFileInfo
    {
        // the logic here avoids redoing the same work in all iterations
        if (!isset($this->subPath)) {
            $this->subPath = $this->getSubPath();
        }
        $subPathname = $this->subPath;
        if ('' !== $subPathname) {
            $subPathname .= $this->directorySeparator;
        }
        $subPathname .= $this->getFilename();
        $basePath = $this->rootPath;
        if ('/' !== $basePath && !str_ends_with($basePath, $this->directorySeparator) && !str_ends_with($basePath, '/')) {
            $basePath .= $this->directorySeparator;
        }
        return new SplFileInfo($basePath . $subPathname, $this->subPath, $subPathname);
    }
    public function hasChildren(bool $allowLinks = \false): bool
    {
        $hasChildren = parent::hasChildren($allowLinks);
        if (!$hasChildren || !$this->ignoreUnreadableDirs) {
            return $hasChildren;
        }
        try {
            parent::getChildren();
            return \true;
        } catch (\UnexpectedValueException) {
            // If directory is unreadable and finder is set to ignore it, skip children
            return \false;
        }
    }
    /**
     * @throws AccessDeniedException
     */
    public function getChildren(): \RecursiveDirectoryIterator
    {
        try {
            $children = parent::getChildren();
            if ($children instanceof self) {
                // parent method will call the constructor with default arguments, so unreadable dirs won't be ignored anymore
                $children->ignoreUnreadableDirs = $this->ignoreUnreadableDirs;
                // performance optimization to avoid redoing the same work in all children
                $children->rootPath = $this->rootPath;
            }
            return $children;
        } catch (\UnexpectedValueException $e) {
            throw new AccessDeniedException($e->getMessage(), $e->getCode(), $e);
        }
    }
    public function next(): void
    {
        $this->ignoreFirstRewind = \false;
        parent::next();
    }
    public function rewind(): void
    {
        // some streams like FTP are not rewindable, ignore the first rewind after creation,
        // as newly created DirectoryIterator does not need to be rewound
        if ($this->ignoreFirstRewind) {
            $this->ignoreFirstRewind = \false;
            return;
        }
        parent::rewind();
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Finder\Iterator;

use _ContaoManager\Symfony\Component\Finder\SplFileInfo;
/**
 * ExcludeDirectoryFilterIterator filters out directories.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 *
 * @extends \FilterIterator<string, SplFileInfo>
 *
 * @implements \RecursiveIterator<string, SplFileInfo>
 */
class ExcludeDirectoryFilterIterator extends \FilterIterator implements \RecursiveIterator
{
    /** @var \Iterator<string, SplFileInfo> */
    private \Iterator $iterator;
    private bool $isRecursive;
    /** @var array<string, true> */
    private array $excludedDirs = [];
    private ?string $excludedPattern = null;
    /** @var list<callable(SplFileInfo):bool> */
    private array $pruneFilters = [];
    /**
     * @param \Iterator<string, SplFileInfo>          $iterator    The Iterator to filter
     * @param list<string|callable(SplFileInfo):bool> $directories An array of directories to exclude
     */
    public function __construct(\Iterator $iterator, array $directories)
    {
        $this->iterator = $iterator;
        $this->isRecursive = $iterator instanceof \RecursiveIterator;
        $patterns = [];
        foreach ($directories as $directory) {
            if (!\is_string($directory)) {
                if (!\is_callable($directory)) {
                    throw new \InvalidArgumentException('Invalid PHP callback.');
                }
                $this->pruneFilters[] = $directory;
                continue;
            }
            $directory = rtrim($directory, '/');
            if (!$this->isRecursive || str_contains($directory, '/')) {
                $patterns[] = preg_quote($directory, '#');
            } else {
                $this->excludedDirs[$directory] = \true;
            }
        }
        if ($patterns) {
            $this->excludedPattern = '#(?:^|/)(?:' . implode('|', $patterns) . ')(?:/|$)#';
        }
        parent::__construct($iterator);
    }
    /**
     * Filters the iterator values.
     */
    public function accept(): bool
    {
        if ($this->isRecursive && isset($this->excludedDirs[$this->getFilename()]) && $this->isDir()) {
            return \false;
        }
        if ($this->excludedPattern) {
            $path = $this->isDir() ? $this->current()->getRelativePathname() : $this->current()->getRelativePath();
            $path = str_replace('\\', '/', $path);
            return !preg_match($this->excludedPattern, $path);
        }
        if ($this->pruneFilters && $this->hasChildren()) {
            foreach ($this->pruneFilters as $pruneFilter) {
                if (!$pruneFilter($this->current())) {
                    return \false;
                }
            }
        }
        return \true;
    }
    public function hasChildren(): bool
    {
        return $this->isRecursive && $this->iterator->hasChildren();
    }
    public function getChildren(): self
    {
        $children = new self($this->iterator->getChildren(), []);
        $children->excludedDirs = $this->excludedDirs;
        $children->excludedPattern = $this->excludedPattern;
        return $children;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Finder\Iterator;

/**
 * SortableIterator applies a sort on a given Iterator.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 *
 * @implements \IteratorAggregate<string, \SplFileInfo>
 */
class SortableIterator implements \IteratorAggregate
{
    public const SORT_BY_NONE = 0;
    public const SORT_BY_NAME = 1;
    public const SORT_BY_TYPE = 2;
    public const SORT_BY_ACCESSED_TIME = 3;
    public const SORT_BY_CHANGED_TIME = 4;
    public const SORT_BY_MODIFIED_TIME = 5;
    public const SORT_BY_NAME_NATURAL = 6;
    public const SORT_BY_NAME_CASE_INSENSITIVE = 7;
    public const SORT_BY_NAME_NATURAL_CASE_INSENSITIVE = 8;
    public const SORT_BY_EXTENSION = 9;
    public const SORT_BY_SIZE = 10;
    /** @var \Traversable<string, \SplFileInfo> */
    private \Traversable $iterator;
    private \Closure|int $sort;
    /**
     * @param \Traversable<string, \SplFileInfo> $iterator
     * @param int|callable                       $sort     The sort type (SORT_BY_NAME, SORT_BY_TYPE, or a PHP callback)
     *
     * @throws \InvalidArgumentException
     */
    public function __construct(\Traversable $iterator, int|callable $sort, bool $reverseOrder = \false)
    {
        $this->iterator = $iterator;
        $order = $reverseOrder ? -1 : 1;
        if (self::SORT_BY_NAME === $sort) {
            $this->sort = static fn(\SplFileInfo $a, \SplFileInfo $b) => $order * strcmp($a->getRealPath() ?: $a->getPathname(), $b->getRealPath() ?: $b->getPathname());
        } elseif (self::SORT_BY_NAME_NATURAL === $sort) {
            $this->sort = static fn(\SplFileInfo $a, \SplFileInfo $b) => $order * strnatcmp($a->getRealPath() ?: $a->getPathname(), $b->getRealPath() ?: $b->getPathname());
        } elseif (self::SORT_BY_NAME_CASE_INSENSITIVE === $sort) {
            $this->sort = static fn(\SplFileInfo $a, \SplFileInfo $b) => $order * strcasecmp($a->getRealPath() ?: $a->getPathname(), $b->getRealPath() ?: $b->getPathname());
        } elseif (self::SORT_BY_NAME_NATURAL_CASE_INSENSITIVE === $sort) {
            $this->sort = static fn(\SplFileInfo $a, \SplFileInfo $b) => $order * strnatcasecmp($a->getRealPath() ?: $a->getPathname(), $b->getRealPath() ?: $b->getPathname());
        } elseif (self::SORT_BY_TYPE === $sort) {
            $this->sort = static function (\SplFileInfo $a, \SplFileInfo $b) use ($order) {
                if ($a->isDir() && $b->isFile()) {
                    return -$order;
                } elseif ($a->isFile() && $b->isDir()) {
                    return $order;
                }
                return $order * strcmp($a->getRealPath() ?: $a->getPathname(), $b->getRealPath() ?: $b->getPathname());
            };
        } elseif (self::SORT_BY_ACCESSED_TIME === $sort) {
            $this->sort = static fn(\SplFileInfo $a, \SplFileInfo $b) => $order * ($a->getATime() - $b->getATime());
        } elseif (self::SORT_BY_CHANGED_TIME === $sort) {
            $this->sort = static fn(\SplFileInfo $a, \SplFileInfo $b) => $order * ($a->getCTime() - $b->getCTime());
        } elseif (self::SORT_BY_MODIFIED_TIME === $sort) {
            $this->sort = static fn(\SplFileInfo $a, \SplFileInfo $b) => $order * ($a->getMTime() - $b->getMTime());
        } elseif (self::SORT_BY_EXTENSION === $sort) {
            $this->sort = static fn(\SplFileInfo $a, \SplFileInfo $b) => $order * strnatcmp($a->getExtension(), $b->getExtension());
        } elseif (self::SORT_BY_SIZE === $sort) {
            $this->sort = static fn(\SplFileInfo $a, \SplFileInfo $b) => $order * ($a->getSize() - $b->getSize());
        } elseif (self::SORT_BY_NONE === $sort) {
            $this->sort = $order;
        } elseif (\is_callable($sort)) {
            $this->sort = $reverseOrder ? static fn(\SplFileInfo $a, \SplFileInfo $b) => -$sort($a, $b) : $sort(...);
        } else {
            throw new \InvalidArgumentException('The SortableIterator takes a PHP callable or a valid built-in sort algorithm as an argument.');
        }
    }
    public function getIterator(): \Traversable
    {
        if (1 === $this->sort) {
            yield from $this->iterator;
            return;
        }
        $keys = $values = [];
        foreach ($this->iterator as $key => $value) {
            $keys[] = $key;
            $values[] = $value;
        }
        if (-1 === $this->sort) {
            for ($i = \count($values) - 1; $i >= 0; --$i) {
                yield $keys[$i] => $values[$i];
            }
            return;
        }
        uasort($values, $this->sort);
        foreach ($values as $i => $v) {
            yield $keys[$i] => $v;
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Finder\Iterator;

/**
 * DepthRangeFilterIterator limits the directory depth.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 *
 * @template-covariant TKey
 * @template-covariant TValue
 *
 * @extends \FilterIterator<TKey, TValue>
 */
class DepthRangeFilterIterator extends \FilterIterator
{
    private int $minDepth = 0;
    /**
     * @param \RecursiveIteratorIterator<\RecursiveIterator<TKey, TValue>> $iterator The Iterator to filter
     * @param int                                                          $minDepth The min depth
     * @param int                                                          $maxDepth The max depth
     */
    public function __construct(\RecursiveIteratorIterator $iterator, int $minDepth = 0, int $maxDepth = \PHP_INT_MAX)
    {
        $this->minDepth = $minDepth;
        $iterator->setMaxDepth(\PHP_INT_MAX === $maxDepth ? -1 : $maxDepth);
        parent::__construct($iterator);
    }
    /**
     * Filters the iterator values.
     */
    public function accept(): bool
    {
        return $this->getInnerIterator()->getDepth() >= $this->minDepth;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Finder\Iterator;

/**
 * FileTypeFilterIterator only keeps files, directories, or both.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 *
 * @extends \FilterIterator<string, \SplFileInfo>
 */
class FileTypeFilterIterator extends \FilterIterator
{
    public const ONLY_FILES = 1;
    public const ONLY_DIRECTORIES = 2;
    private int $mode;
    /**
     * @param \Iterator<string, \SplFileInfo> $iterator The Iterator to filter
     * @param int                             $mode     The mode (self::ONLY_FILES or self::ONLY_DIRECTORIES)
     */
    public function __construct(\Iterator $iterator, int $mode)
    {
        $this->mode = $mode;
        parent::__construct($iterator);
    }
    /**
     * Filters the iterator values.
     */
    public function accept(): bool
    {
        $fileinfo = $this->current();
        if (self::ONLY_DIRECTORIES === (self::ONLY_DIRECTORIES & $this->mode) && $fileinfo->isFile()) {
            return \false;
        } elseif (self::ONLY_FILES === (self::ONLY_FILES & $this->mode) && $fileinfo->isDir()) {
            return \false;
        }
        return \true;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Finder\Iterator;

use _ContaoManager\Symfony\Component\Finder\SplFileInfo;
/**
 * PathFilterIterator filters files by path patterns (e.g. some/special/dir).
 *
 * @author Fabien Potencier  <fabien@symfony.com>
 * @author Włodzimierz Gajda <gajdaw@gajdaw.pl>
 *
 * @extends MultiplePcreFilterIterator<string, SplFileInfo>
 */
class PathFilterIterator extends MultiplePcreFilterIterator
{
    /**
     * Filters the iterator values.
     */
    public function accept(): bool
    {
        $filename = $this->current()->getRelativePathname();
        if ('\\' === \DIRECTORY_SEPARATOR) {
            $filename = str_replace('\\', '/', $filename);
        }
        return $this->isAccepted($filename);
    }
    /**
     * Converts strings to regexp.
     *
     * PCRE patterns are left unchanged.
     *
     * Default conversion:
     *     'lorem/ipsum/dolor' ==>  'lorem\/ipsum\/dolor/'
     *
     * Use only / as directory separator (on Windows also).
     *
     * @param string $str Pattern: regexp or dirname
     */
    protected function toRegex(string $str): string
    {
        return $this->isRegex($str) ? $str : '/' . preg_quote($str, '/') . '/';
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Finder;

/**
 * Gitignore matches against text.
 *
 * @author Michael Voříšek <vorismi3@fel.cvut.cz>
 * @author Ahmed Abdou <mail@ahmd.io>
 */
class Gitignore
{
    /**
     * Returns a regexp which is the equivalent of the gitignore pattern.
     *
     * Format specification: https://git-scm.com/docs/gitignore#_pattern_format
     */
    public static function toRegex(string $gitignoreFileContent): string
    {
        return self::buildRegex($gitignoreFileContent, \false);
    }
    public static function toRegexMatchingNegatedPatterns(string $gitignoreFileContent): string
    {
        return self::buildRegex($gitignoreFileContent, \true);
    }
    private static function buildRegex(string $gitignoreFileContent, bool $inverted): string
    {
        $gitignoreFileContent = preg_replace('~(?<!\\\\)#[^\n\r]*~', '', $gitignoreFileContent);
        $gitignoreLines = preg_split('~\r\n?|\n~', $gitignoreFileContent);
        $res = self::lineToRegex('');
        foreach ($gitignoreLines as $line) {
            $line = preg_replace('~(?<!\\\\)[ \t]+$~', '', $line);
            if (str_starts_with($line, '!')) {
                $line = substr($line, 1);
                $isNegative = \true;
            } else {
                $isNegative = \false;
            }
            if ('' !== $line) {
                if ($isNegative xor $inverted) {
                    $res = '(?!' . self::lineToRegex($line) . '$)' . $res;
                } else {
                    $res = '(?:' . $res . '|' . self::lineToRegex($line) . ')';
                }
            }
        }
        return '~^(?:' . $res . ')~s';
    }
    private static function lineToRegex(string $gitignoreLine): string
    {
        if ('' === $gitignoreLine) {
            return '$f';
            // always false
        }
        $slashPos = strpos($gitignoreLine, '/');
        if (\false !== $slashPos && \strlen($gitignoreLine) - 1 !== $slashPos) {
            if (0 === $slashPos) {
                $gitignoreLine = substr($gitignoreLine, 1);
            }
            $isAbsolute = \true;
        } else {
            $isAbsolute = \false;
        }
        $regex = preg_quote(str_replace('\\', '', $gitignoreLine), '~');
        $regex = preg_replace_callback('~\\\\\\[((?:\\\\!)?)([^\[\]]*)\\\\\\]~', fn(array $matches): string => '[' . ('' !== $matches[1] ? '^' : '') . str_replace('\-', '-', $matches[2]) . ']', $regex);
        $regex = preg_replace('~(?:(?:\\\\\\*){2,}(/?))+~', '(?:(?:(?!//).(?<!//))+$1)?', $regex);
        $regex = preg_replace('~\\\\\\*~', '[^/]*', $regex);
        $regex = preg_replace('~\\\\\\?~', '[^/]', $regex);
        return ($isAbsolute ? '' : '(?:[^/]+/)*') . $regex . (!str_ends_with($gitignoreLine, '/') ? '(?:$|/)' : '');
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Finder\Exception;

/**
 * @author Jean-François Simon <jeanfrancois.simon@sensiolabs.com>
 */
class AccessDeniedException extends \UnexpectedValueException
{
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Finder\Exception;

/**
 * @author Andreas Erhard <andreas.erhard@i-med.ac.at>
 */
class DirectoryNotFoundException extends \InvalidArgumentException
{
}
{
    "name": "symfony\/finder",
    "type": "library",
    "description": "Finds files and directories via an intuitive fluent interface",
    "keywords": [],
    "homepage": "https:\/\/symfony.com",
    "license": "MIT",
    "authors": [
        {
            "name": "Fabien Potencier",
            "email": "fabien@symfony.com"
        },
        {
            "name": "Symfony Community",
            "homepage": "https:\/\/symfony.com\/contributors"
        }
    ],
    "require": {
        "php": ">=8.1"
    },
    "require-dev": {
        "symfony\/filesystem": "^6.0|^7.0"
    },
    "autoload": {
        "psr-4": {
            "_ContaoManager\\Symfony\\Component\\Finder\\": ""
        },
        "exclude-from-classmap": [
            "\/Tests\/"
        ]
    },
    "minimum-stability": "dev"
}<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

use Symfony\Polyfill\Php83 as p;

if (extension_loaded('mbstring')) {
    if (!function_exists('mb_str_pad')) {
        function mb_str_pad(string $string, int $length, string $pad_string = ' ', int $pad_type = STR_PAD_RIGHT, ?string $encoding = null): string { return p\Php83::mb_str_pad($string, $length, $pad_string, $pad_type, $encoding); }
    }
}

if (\PHP_VERSION_ID >= 80100) {
    return require __DIR__.'/bootstrap81.php';
}

if (!function_exists('ldap_exop_sync') && function_exists('ldap_exop')) {
    function ldap_exop_sync($ldap, string $request_oid, ?string $request_data = null, ?array $controls = null, &$response_data = null, &$response_oid = null): bool { return ldap_exop($ldap, $request_oid, $request_data, $controls, $response_data, $response_oid); }
}

if (!function_exists('ldap_connect_wallet') && function_exists('ldap_connect')) {
    function ldap_connect_wallet(?string $uri, string $wallet, string $password, int $auth_mode = \GSLC_SSL_NO_AUTH) { return ldap_connect($uri, $wallet, $password, $auth_mode); }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

if (\PHP_VERSION_ID >= 80300) {
    return;
}

if (!function_exists('ldap_exop_sync') && function_exists('ldap_exop')) {
    function ldap_exop_sync(\LDAP\Connection $ldap, string $request_oid, ?string $request_data = null, ?array $controls = null, &$response_data = null, &$response_oid = null): bool { return ldap_exop($ldap, $request_oid, $request_data, $controls, $response_data, $response_oid); }
}

if (!function_exists('ldap_connect_wallet') && function_exists('ldap_connect')) {
    function ldap_connect_wallet(?string $uri, string $wallet, #[\SensitiveParameter] string $password, int $auth_mode = \GSLC_SSL_NO_AUTH): \LDAP\Connection|false { return ldap_connect($uri, $wallet, $password, $auth_mode); }
}
Copyright (c) 2022-present Fabien Potencier

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is furnished
to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

if (\PHP_VERSION_ID < 80300) {
    class SQLite3Exception extends Exception
    {
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

if (\PHP_VERSION_ID < 80300) {
    class DateError extends Error
    {
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

if (\PHP_VERSION_ID < 80300) {
    #[Attribute(Attribute::TARGET_METHOD)]
    final class Override
    {
        public function __construct()
        {
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

if (\PHP_VERSION_ID < 80300) {
    class DateException extends Exception
    {
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

if (\PHP_VERSION_ID < 80300) {
    class DateInvalidOperationException extends DateException
    {
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

if (\PHP_VERSION_ID < 80300) {
    class DateObjectError extends DateError
    {
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

if (\PHP_VERSION_ID < 80300) {
    class DateMalformedPeriodStringException extends DateException
    {
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

if (\PHP_VERSION_ID < 80300) {
    class DateMalformedStringException extends DateException
    {
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

if (\PHP_VERSION_ID < 80300) {
    class DateRangeError extends DateError
    {
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

if (\PHP_VERSION_ID < 80300) {
    class DateInvalidTimeZoneException extends DateException
    {
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

if (\PHP_VERSION_ID < 80300) {
    class DateMalformedIntervalStringException extends DateException
    {
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

use Symfony\Polyfill\Php83 as p;

if (\PHP_VERSION_ID >= 80300) {
    return;
}

if (!function_exists('json_validate')) {
    function json_validate(string $json, int $depth = 512, int $flags = 0): bool { return p\Php83::json_validate($json, $depth, $flags); }
}

if (!function_exists('stream_context_set_options')) {
    function stream_context_set_options($context, array $options): bool { return stream_context_set_option($context, $options); }
}

if (!function_exists('str_increment')) {
    function str_increment(string $string): string { return p\Php83::str_increment($string); }
}

if (!function_exists('str_decrement')) {
    function str_decrement(string $string): string { return p\Php83::str_decrement($string); }
}

if (\PHP_VERSION_ID >= 80000) {
    return require __DIR__.'/bootstrap80.php';
}

if (extension_loaded('mbstring')) {
    if (!function_exists('mb_str_pad')) {
        function mb_str_pad(string $string, int $length, string $pad_string = ' ', int $pad_type = STR_PAD_RIGHT, ?string $encoding = null) { return p\Php83::mb_str_pad($string, $length, $pad_string, $pad_type, $encoding); }
    }
}

if (!function_exists('ldap_exop_sync') && function_exists('ldap_exop')) {
    function ldap_exop_sync($ldap, string $request_oid, ?string $request_data = null, ?array $controls = null, &$response_data = null, &$response_oid = null): bool { return ldap_exop($ldap, $request_oid, $request_data, $controls, $response_data, $response_oid); }
}

if (!function_exists('ldap_connect_wallet') && function_exists('ldap_connect')) {
    function ldap_connect_wallet(?string $uri, string $wallet, string $password, int $auth_mode = \GSLC_SSL_NO_AUTH) { return ldap_connect($uri, $wallet, $password, $auth_mode); }
}
Symfony Polyfill / Php83
========================

This component provides features added to PHP 8.3 core:

- [`json_validate`](https://wiki.php.net/rfc/json_validate)
- [`Override`](https://wiki.php.net/rfc/marking_overriden_methods)
- [`mb_str_pad`](https://wiki.php.net/rfc/mb_str_pad)
- [`ldap_exop_sync`](https://wiki.php.net/rfc/deprecate_functions_with_overloaded_signatures)
- [`ldap_connect_wallet`](https://wiki.php.net/rfc/deprecate_functions_with_overloaded_signatures)
- [`stream_context_set_options`](https://wiki.php.net/rfc/deprecate_functions_with_overloaded_signatures)
- [`str_increment` and `str_decrement`](https://wiki.php.net/rfc/saner-inc-dec-operators)
- [`Date*Exception/Error classes`](https://wiki.php.net/rfc/datetime-exceptions)
- [`SQLite3Exception`](https://wiki.php.net/rfc/sqlite3_exceptions)

More information can be found in the
[main Polyfill README](https://github.com/symfony/polyfill/blob/main/README.md).

License
=======

This library is released under the [MIT license](LICENSE).
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Symfony\Polyfill\Php83;

/**
 * @author Ion Bazan <ion.bazan@gmail.com>
 * @author Pierre Ambroise <pierre27.ambroise@gmail.com>
 *
 * @internal
 */
final class Php83
{
    private const JSON_MAX_DEPTH = 0x7fffffff;
    // see https://www.php.net/manual/en/function.json-decode.php
    public static function json_validate(string $json, int $depth = 512, int $flags = 0): bool
    {
        if (0 !== $flags && \defined('JSON_INVALID_UTF8_IGNORE') && \JSON_INVALID_UTF8_IGNORE !== $flags) {
            throw new \ValueError('json_validate(): Argument #3 ($flags) must be a valid flag (allowed flags: JSON_INVALID_UTF8_IGNORE)');
        }
        if ($depth <= 0) {
            throw new \ValueError('json_validate(): Argument #2 ($depth) must be greater than 0');
        }
        if ($depth > self::JSON_MAX_DEPTH) {
            throw new \ValueError(\sprintf('json_validate(): Argument #2 ($depth) must be less than %d', self::JSON_MAX_DEPTH));
        }
        json_decode($json, \true, $depth, $flags);
        return \JSON_ERROR_NONE === json_last_error();
    }
    /** @return string|false */
    public static function mb_str_pad(string $string, int $length, string $pad_string = ' ', int $pad_type = \STR_PAD_RIGHT, ?string $encoding = null)
    {
        if (!\in_array($pad_type, [\STR_PAD_RIGHT, \STR_PAD_LEFT, \STR_PAD_BOTH], \true)) {
            throw new \ValueError('mb_str_pad(): Argument #4 ($pad_type) must be STR_PAD_LEFT, STR_PAD_RIGHT, or STR_PAD_BOTH');
        }
        if (null === $encoding) {
            $encoding = mb_internal_encoding();
        }
        $errorToTrigger = null;
        try {
            if (!@mb_check_encoding('', $encoding)) {
                $errorToTrigger = \sprintf('mb_str_pad(): Argument #5 ($encoding) must be a valid encoding, "%s" given', $encoding);
            }
        } catch (\ValueError $e) {
            $errorToTrigger = \sprintf('mb_str_pad(): Argument #5 ($encoding) must be a valid encoding, "%s" given', $encoding);
        }
        if (mb_strlen($pad_string, $encoding) <= 0) {
            $errorToTrigger = 'mb_str_pad(): Argument #3 ($pad_string) must be a non-empty string';
        }
        if (null !== $errorToTrigger) {
            if (80000 > \PHP_VERSION_ID) {
                trigger_error($errorToTrigger, \E_USER_WARNING);
                return \false;
            }
            throw new \ValueError($errorToTrigger);
        }
        $paddingRequired = $length - mb_strlen($string, $encoding);
        if ($paddingRequired < 1) {
            return $string;
        }
        switch ($pad_type) {
            case \STR_PAD_LEFT:
                return mb_substr(str_repeat($pad_string, $paddingRequired), 0, $paddingRequired, $encoding) . $string;
            case \STR_PAD_RIGHT:
                return $string . mb_substr(str_repeat($pad_string, $paddingRequired), 0, $paddingRequired, $encoding);
            default:
                $leftPaddingLength = floor($paddingRequired / 2);
                $rightPaddingLength = $paddingRequired - $leftPaddingLength;
                return mb_substr(str_repeat($pad_string, $leftPaddingLength), 0, $leftPaddingLength, $encoding) . $string . mb_substr(str_repeat($pad_string, $rightPaddingLength), 0, $rightPaddingLength, $encoding);
        }
    }
    public static function str_increment(string $string): string
    {
        if ('' === $string) {
            throw new \ValueError('str_increment(): Argument #1 ($string) cannot be empty');
        }
        if (!preg_match('/^[a-zA-Z0-9]+$/', $string)) {
            throw new \ValueError('str_increment(): Argument #1 ($string) must be composed only of alphanumeric ASCII characters');
        }
        if (is_numeric($string)) {
            $offset = stripos($string, 'e');
            if (\false !== $offset) {
                $char = $string[$offset];
                ++$char;
                $string[$offset] = $char;
                ++$string;
                switch ($string[$offset]) {
                    case 'f':
                        $string[$offset] = 'e';
                        break;
                    case 'F':
                        $string[$offset] = 'E';
                        break;
                    case 'g':
                        $string[$offset] = 'f';
                        break;
                    case 'G':
                        $string[$offset] = 'F';
                        break;
                }
                return $string;
            }
        }
        return ++$string;
    }
    public static function str_decrement(string $string): string
    {
        if ('' === $string) {
            throw new \ValueError('str_decrement(): Argument #1 ($string) cannot be empty');
        }
        if (!preg_match('/^[a-zA-Z0-9]+$/', $string)) {
            throw new \ValueError('str_decrement(): Argument #1 ($string) must be composed only of alphanumeric ASCII characters');
        }
        if (preg_match('/\A(?:0[aA0]?|[aA])\z/', $string)) {
            throw new \ValueError(\sprintf('str_decrement(): Argument #1 ($string) "%s" is out of decrement range', $string));
        }
        if (!\in_array(substr($string, -1), ['A', 'a', '0'], \true)) {
            return implode('', \array_slice(str_split($string), 0, -1)) . \chr(\ord(substr($string, -1)) - 1);
        }
        $carry = '';
        $decremented = '';
        for ($i = \strlen($string) - 1; $i >= 0; --$i) {
            $char = $string[$i];
            switch ($char) {
                case 'A':
                    if ('' !== $carry) {
                        $decremented = $carry . $decremented;
                        $carry = '';
                    }
                    $carry = 'Z';
                    break;
                case 'a':
                    if ('' !== $carry) {
                        $decremented = $carry . $decremented;
                        $carry = '';
                    }
                    $carry = 'z';
                    break;
                case '0':
                    if ('' !== $carry) {
                        $decremented = $carry . $decremented;
                        $carry = '';
                    }
                    $carry = '9';
                    break;
                case '1':
                    if ('' !== $carry) {
                        $decremented = $carry . $decremented;
                        $carry = '';
                    }
                    break;
                default:
                    if ('' !== $carry) {
                        $decremented = $carry . $decremented;
                        $carry = '';
                    }
                    if (!\in_array($char, ['A', 'a', '0'], \true)) {
                        $decremented = \chr(\ord($char) - 1) . $decremented;
                    }
            }
        }
        return $decremented;
    }
}
{
    "name": "symfony\/polyfill-php83",
    "type": "library",
    "description": "Symfony polyfill backporting some PHP 8.3+ features to lower PHP versions",
    "keywords": [
        "polyfill",
        "shim",
        "compatibility",
        "portable"
    ],
    "homepage": "https:\/\/symfony.com",
    "license": "MIT",
    "authors": [
        {
            "name": "Nicolas Grekas",
            "email": "p@tchwork.com"
        },
        {
            "name": "Symfony Community",
            "homepage": "https:\/\/symfony.com\/contributors"
        }
    ],
    "require": {
        "php": ">=7.2"
    },
    "autoload": {
        "psr-4": {
            "Symfony\\Polyfill\\Php83\\": ""
        },
        "files": [
            "bootstrap.php"
        ],
        "classmap": [
            "Resources\/stubs"
        ]
    },
    "minimum-stability": "dev",
    "extra": {
        "thanks": {
            "name": "symfony\/polyfill",
            "url": "https:\/\/github.com\/symfony\/polyfill"
        }
    }
}<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

use Symfony\Polyfill\Php84 as p;

if (extension_loaded('mbstring')) {
    if (!function_exists('mb_ucfirst')) {
        function mb_ucfirst(string $string, ?string $encoding = null): string { return p\Php84::mb_ucfirst($string, $encoding); }
    }

    if (!function_exists('mb_lcfirst')) {
        function mb_lcfirst(string $string, ?string $encoding = null): string { return p\Php84::mb_lcfirst($string, $encoding); }
    }

    if (!function_exists('mb_trim')) {
        function mb_trim(string $string, ?string $characters = null, ?string $encoding = null): string { return p\Php84::mb_trim($string, $characters, $encoding); }
    }

    if (!function_exists('mb_ltrim')) {
        function mb_ltrim(string $string, ?string $characters = null, ?string $encoding = null): string { return p\Php84::mb_ltrim($string, $characters, $encoding); }
    }

    if (!function_exists('mb_rtrim')) {
        function mb_rtrim(string $string, ?string $characters = null, ?string $encoding = null): string { return p\Php84::mb_rtrim($string, $characters, $encoding); }
    }
}

if (extension_loaded('bcmath')) {
    if (!function_exists('bcceil')) {
        function bcceil(string $num): string { return p\Php84::bcceil($num); }
    }
    if (!function_exists('bcdivmod')) {
        function bcdivmod(string $num1, string $num2, ?int $scale = null): ?array { return p\Php84::bcdivmod($num1, $num2, $scale); }
    }
    if (!function_exists('bcfloor')) {
        function bcfloor(string $num): string { return p\Php84::bcfloor($num); }
    }
    if (!function_exists('bcround')) {
        function bcround(string $num, int $precision = 0, $mode = RoundingMode::HalfAwayFromZero): string { return p\Php84::bcround($num, $precision, $mode); }
    }
}

if (\PHP_VERSION_ID >= 80200) {
    return require __DIR__.'/bootstrap82.php';
}

if (extension_loaded('intl') && !function_exists('grapheme_str_split')) {
    function grapheme_str_split(string $string, int $length = 1) { return p\Php84::grapheme_str_split($string, $length); }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

use Symfony\Polyfill\Php84 as p;

if (\PHP_VERSION_ID >= 80400) {
    return;
}

if (extension_loaded('intl') && !function_exists('grapheme_str_split')) {
    function grapheme_str_split(string $string, int $length = 1): array|false { return p\Php84::grapheme_str_split($string, $length); }
}
Copyright (c) 2024-present Fabien Potencier

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is furnished
to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

if (\PHP_VERSION_ID < 80100) {
    final class RoundingMode
    {
        const HalfAwayFromZero = 0;
        const HalfTowardsZero = 1;
        const HalfEven = 2;
        const HalfOdd = 3;
        const TowardsZero = 4;
        const AwayFromZero = 5;
        const NegativeInfinity = 6;
        const PositiveInfinity = 7;

        private function __construct()
        {
        }

        public static function cases(): array
        {
            return [
                self::HalfAwayFromZero,
                self::HalfTowardsZero,
                self::HalfEven,
                self::HalfOdd,
                self::TowardsZero,
                self::AwayFromZero,
                self::NegativeInfinity,
                self::PositiveInfinity,
            ];
        }
    }
} elseif (\PHP_VERSION_ID < 80400) {
    require dirname(__DIR__).'/RoundingMode.php';
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Pdo;

use PDO;

if (\PHP_VERSION_ID < 80400 && \extension_loaded('pdo_mysql')) {
    // Feature detection for non-mysqlnd; see also https://www.php.net/manual/en/class.pdo-mysql.php#pdo-mysql.constants.attr-max-buffer-size
    if (\defined('PDO::MYSQL_ATTR_MAX_BUFFER_SIZE') && \defined('PDO::MYSQL_ATTR_READ_DEFAULT_FILE') && \defined('PDO::MYSQL_ATTR_READ_DEFAULT_GROUP')) {
        class Mysql extends \PDO
        {
            public const ATTR_COMPRESS = \PDO::MYSQL_ATTR_COMPRESS;
            public const ATTR_DIRECT_QUERY = \PDO::MYSQL_ATTR_DIRECT_QUERY;
            public const ATTR_FOUND_ROWS = \PDO::MYSQL_ATTR_FOUND_ROWS;
            public const ATTR_IGNORE_SPACE = \PDO::MYSQL_ATTR_IGNORE_SPACE;
            public const ATTR_INIT_COMMAND = \PDO::MYSQL_ATTR_INIT_COMMAND;
            public const ATTR_LOCAL_INFILE = \PDO::MYSQL_ATTR_LOCAL_INFILE;
            public const ATTR_LOCAL_INFILE_DIRECTORY = \PHP_VERSION_ID >= 80100 ? \PDO::MYSQL_ATTR_LOCAL_INFILE_DIRECTORY : 1015;
            public const ATTR_MAX_BUFFER_SIZE = \PDO::MYSQL_ATTR_MAX_BUFFER_SIZE;
            public const ATTR_MULTI_STATEMENTS = \PDO::MYSQL_ATTR_MULTI_STATEMENTS;
            public const ATTR_READ_DEFAULT_FILE = \PDO::MYSQL_ATTR_READ_DEFAULT_FILE;
            public const ATTR_READ_DEFAULT_GROUP = \PDO::MYSQL_ATTR_READ_DEFAULT_GROUP;
            public const ATTR_SERVER_PUBLIC_KEY = \PDO::MYSQL_ATTR_SERVER_PUBLIC_KEY;
            public const ATTR_SSL_CA = \PDO::MYSQL_ATTR_SSL_CA;
            public const ATTR_SSL_CAPATH = \PDO::MYSQL_ATTR_SSL_CAPATH;
            public const ATTR_SSL_CERT = \PDO::MYSQL_ATTR_SSL_CERT;
            public const ATTR_SSL_CIPHER = \PDO::MYSQL_ATTR_SSL_CIPHER;
            public const ATTR_SSL_KEY = \PDO::MYSQL_ATTR_SSL_KEY;
            public const ATTR_SSL_VERIFY_SERVER_CERT = \PDO::MYSQL_ATTR_SSL_VERIFY_SERVER_CERT;
            public const ATTR_USE_BUFFERED_QUERY = \PDO::MYSQL_ATTR_USE_BUFFERED_QUERY;

            public function __construct(string $dsn, ?string $username = null, ?string $password = null, ?array $options = null)
            {
                parent::__construct($dsn, $username, $password, $options);

                if ('mysql' !== $driver = $this->getAttribute(\PDO::ATTR_DRIVER_NAME)) {
                    throw new \PDOException(\sprintf('Pdo\Mysql::__construct() cannot be used for connecting to the "%s" driver', $driver));
                }
            }

            public static function connect(string $dsn, ?string $username = null, ?string $password = null, ?array $options = null): self
            {
                try {
                    return new self($dsn, $username, $password, $options);
                } catch (\PDOException $e) {
                    throw preg_match('/^Pdo\\\\Mysql::__construct\(\) cannot be used for connecting to the "([a-z]+)" driver/', $e->getMessage(), $matches) ? new \PDOException(\sprintf('Pdo\Mysql::connect() cannot be used for connecting to the "%s" driver', $matches[1])) : $e;
                }
            }
        }
    } else {
        class Mysql extends \PDO
        {
            public const ATTR_COMPRESS = \PDO::MYSQL_ATTR_COMPRESS;
            public const ATTR_DIRECT_QUERY = \PDO::MYSQL_ATTR_DIRECT_QUERY;
            public const ATTR_FOUND_ROWS = \PDO::MYSQL_ATTR_FOUND_ROWS;
            public const ATTR_IGNORE_SPACE = \PDO::MYSQL_ATTR_IGNORE_SPACE;
            public const ATTR_INIT_COMMAND = \PDO::MYSQL_ATTR_INIT_COMMAND;
            public const ATTR_LOCAL_INFILE = \PDO::MYSQL_ATTR_LOCAL_INFILE;
            public const ATTR_LOCAL_INFILE_DIRECTORY = \PHP_VERSION_ID >= 80100 ? \PDO::MYSQL_ATTR_LOCAL_INFILE_DIRECTORY : 1015;
            // public const ATTR_MAX_BUFFER_SIZE = PDO::MYSQL_ATTR_MAX_BUFFER_SIZE; // disabled for mysqlnd
            public const ATTR_MULTI_STATEMENTS = \PDO::MYSQL_ATTR_MULTI_STATEMENTS;
            // public const ATTR_READ_DEFAULT_FILE = PDO::MYSQL_ATTR_READ_DEFAULT_FILE; // disabled for mysqlnd
            // public const ATTR_READ_DEFAULT_GROUP = PDO::MYSQL_ATTR_READ_DEFAULT_GROUP; // disabled for mysqlnd
            public const ATTR_SERVER_PUBLIC_KEY = \PDO::MYSQL_ATTR_SERVER_PUBLIC_KEY;
            public const ATTR_SSL_CA = \PDO::MYSQL_ATTR_SSL_CA;
            public const ATTR_SSL_CAPATH = \PDO::MYSQL_ATTR_SSL_CAPATH;
            public const ATTR_SSL_CERT = \PDO::MYSQL_ATTR_SSL_CERT;
            public const ATTR_SSL_CIPHER = \PDO::MYSQL_ATTR_SSL_CIPHER;
            public const ATTR_SSL_KEY = \PDO::MYSQL_ATTR_SSL_KEY;
            public const ATTR_SSL_VERIFY_SERVER_CERT = \PDO::MYSQL_ATTR_SSL_VERIFY_SERVER_CERT;
            public const ATTR_USE_BUFFERED_QUERY = \PDO::MYSQL_ATTR_USE_BUFFERED_QUERY;

            public function __construct(string $dsn, ?string $username = null, ?string $password = null, ?array $options = null)
            {
                parent::__construct($dsn, $username, $password, $options);

                if ('mysql' !== $driver = $this->getAttribute(\PDO::ATTR_DRIVER_NAME)) {
                    throw new \PDOException(\sprintf('Pdo\Mysql::__construct() cannot be used for connecting to the "%s" driver', $driver));
                }
            }

            public static function connect(string $dsn, ?string $username = null, ?string $password = null, ?array $options = null): self
            {
                try {
                    return new self($dsn, $username, $password, $options);
                } catch (\PDOException $e) {
                    throw preg_match('/^Pdo\\\\Mysql::__construct\(\) cannot be used for connecting to the "([a-z]+)" driver/', $e->getMessage(), $matches) ? new \PDOException(\sprintf('Pdo\Mysql::connect() cannot be used for connecting to the "%s" driver', $matches[1])) : $e;
                }
            }
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Pdo;

if (\PHP_VERSION_ID < 80400 && \extension_loaded('pdo_firebird')) {
    class Firebird extends \PDO
    {
        public const ATTR_DATE_FORMAT = \PDO::FB_ATTR_DATE_FORMAT;
        public const ATTR_TIME_FORMAT = \PDO::FB_ATTR_TIME_FORMAT;
        public const ATTR_TIMESTAMP_FORMAT = \PDO::FB_ATTR_TIMESTAMP_FORMAT;

        public function __construct(string $dsn, ?string $username = null, ?string $password = null, ?array $options = null)
        {
            parent::__construct($dsn, $username, $password, $options);

            if ('firebird' !== $driver = $this->getAttribute(\PDO::ATTR_DRIVER_NAME)) {
                throw new \PDOException(\sprintf('Pdo\Firebird::__construct() cannot be used for connecting to the "%s" driver', $driver));
            }
        }

        public static function connect(string $dsn, ?string $username = null, ?string $password = null, ?array $options = null): self
        {
            try {
                return new self($dsn, $username, $password, $options);
            } catch (\PDOException $e) {
                throw preg_match('/^Pdo\\\\Firebird::__construct\(\) cannot be used for connecting to the "([a-z]+)" driver/', $e->getMessage(), $matches) ? new \PDOException(\sprintf('Pdo\Firebird::connect() cannot be used for connecting to the "%s" driver', $matches[1])) : $e;
            }
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Pdo;

if (\PHP_VERSION_ID < 80400 && \extension_loaded('pdo_dblib')) {
    class Dblib extends \PDO
    {
        public const ATTR_CONNECTION_TIMEOUT = \PDO::DBLIB_ATTR_CONNECTION_TIMEOUT;
        public const ATTR_QUERY_TIMEOUT = \PDO::DBLIB_ATTR_QUERY_TIMEOUT;
        public const ATTR_STRINGIFY_UNIQUEIDENTIFIER = \PDO::DBLIB_ATTR_STRINGIFY_UNIQUEIDENTIFIER;
        public const ATTR_VERSION = \PDO::DBLIB_ATTR_VERSION;
        public const ATTR_TDS_VERSION = \PHP_VERSION_ID >= 70300 ? \PDO::DBLIB_ATTR_TDS_VERSION : 1004;
        public const ATTR_SKIP_EMPTY_ROWSETS = \PHP_VERSION_ID >= 70300 ? \PDO::DBLIB_ATTR_SKIP_EMPTY_ROWSETS : 1005;
        public const ATTR_DATETIME_CONVERT = \PHP_VERSION_ID >= 70300 ? \PDO::DBLIB_ATTR_DATETIME_CONVERT : 1006;

        public function __construct(string $dsn, ?string $username = null, ?string $password = null, ?array $options = null)
        {
            parent::__construct($dsn, $username, $password, $options);

            if ('dblib' !== $driver = $this->getAttribute(\PDO::ATTR_DRIVER_NAME)) {
                throw new \PDOException(\sprintf('Pdo\Dblib::__construct() cannot be used for connecting to the "%s" driver', $driver));
            }
        }

        public static function connect(string $dsn, ?string $username = null, ?string $password = null, ?array $options = null): self
        {
            try {
                return new self($dsn, $username, $password, $options);
            } catch (\PDOException $e) {
                throw preg_match('/^Pdo\\\\Dblib::__construct\(\) cannot be used for connecting to the "([a-z]+)" driver/', $e->getMessage(), $matches) ? new \PDOException(\sprintf('Pdo\Dblib::connect() cannot be used for connecting to the "%s" driver', $matches[1])) : $e;
            }
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Pdo;

if (\PHP_VERSION_ID < 80400 && \extension_loaded('pdo_pgsql')) {
    class Pgsql extends \PDO
    {
        public const ATTR_DISABLE_PREPARES = \PDO::PGSQL_ATTR_DISABLE_PREPARES;

        public function __construct(string $dsn, ?string $username = null, ?string $password = null, ?array $options = null)
        {
            parent::__construct($dsn, $username, $password, $options);

            if ('pgsql' !== $driver = $this->getAttribute(\PDO::ATTR_DRIVER_NAME)) {
                throw new \PDOException(\sprintf('Pdo\Pgsql::__construct() cannot be used for connecting to the "%s" driver', $driver));
            }
        }

        public static function connect(string $dsn, ?string $username = null, ?string $password = null, ?array $options = null): self
        {
            try {
                return new self($dsn, $username, $password, $options);
            } catch (\PDOException $e) {
                throw preg_match('/^Pdo\\\\Pgsql::__construct\(\) cannot be used for connecting to the "([a-z]+)" driver/', $e->getMessage(), $matches) ? new \PDOException(\sprintf('Pdo\Pgsql::connect() cannot be used for connecting to the "%s" driver', $matches[1])) : $e;
            }
        }

        public function copyFromArray(string $tableName, array $rows, string $separator = "\t", string $nullAs = '\\\\N', ?string $fields = null): bool
        {
            return $this->pgsqlCopyFromArray($tableName, $rows, $separator, $nullAs, $fields);
        }

        public function copyFromFile(string $tableName, string $filename, string $separator = "\t", string $nullAs = '\\\\N', ?string $fields = null): bool
        {
            return $this->pgsqlCopyFromFile($tableName, $filename, $separator, $nullAs, $fields);
        }

        /**
         * @return array|false
         */
        public function copyToArray(string $tableName, string $separator = "\t", string $nullAs = '\\\\N', ?string $fields = null)
        {
            return $this->pgsqlCopyToArray($tableName, $separator, $nullAs, $fields);
        }

        public function copyToFile(string $tableName, string $filename, string $separator = "\t", string $nullAs = '\\\\N', ?string $fields = null): bool
        {
            return $this->pgsqlCopyToFile($tableName, $filename, $separator, $nullAs, $fields);
        }

        /**
         * @return array|false
         */
        public function getNotify(int $fetchMode = \PDO::FETCH_DEFAULT, int $timeoutMilliseconds = 0)
        {
            return $this->pgsqlGetNotify($fetchMode, $timeoutMilliseconds);
        }

        public function getPid(): int
        {
            return $this->pgsqlGetPid();
        }

        /**
         * @return string|false
         */
        public function lobCreate()
        {
            return $this->pgsqlLOBCreate();
        }

        /**
         * @return resource|false
         */
        public function lobOpen(string $oid, string $mode = 'rb')
        {
            return $this->pgsqlLOBOpen($oid, $mode);
        }

        public function lobUnlink(string $oid): bool
        {
            return $this->pgsqlLOBUnlink($oid);
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Pdo;

if (\PHP_VERSION_ID < 80400 && \extension_loaded('pdo_odbc')) {
    class Odbc extends \PDO
    {
        public const ATTR_USE_CURSOR_LIBRARY = \PDO::ODBC_ATTR_USE_CURSOR_LIBRARY;
        public const ATTR_ASSUME_UTF8 = \PDO::ODBC_ATTR_ASSUME_UTF8;
        public const SQL_USE_IF_NEEDED = \PDO::ODBC_SQL_USE_IF_NEEDED;
        public const SQL_USE_DRIVER = \PDO::ODBC_SQL_USE_DRIVER;
        public const SQL_USE_ODBC = \PDO::ODBC_SQL_USE_ODBC;

        public function __construct(string $dsn, ?string $username = null, ?string $password = null, ?array $options = null)
        {
            parent::__construct($dsn, $username, $password, $options);

            if ('odbc' !== $driver = $this->getAttribute(\PDO::ATTR_DRIVER_NAME)) {
                throw new \PDOException(\sprintf('Pdo\Odbc::__construct() cannot be used for connecting to the "%s" driver', $driver));
            }
        }

        public static function connect(string $dsn, ?string $username = null, ?string $password = null, ?array $options = null): self
        {
            try {
                return new self($dsn, $username, $password, $options);
            } catch (\PDOException $e) {
                throw preg_match('/^Pdo\\\\Odbc::__construct\(\) cannot be used for connecting to the "([a-z]+)" driver/', $e->getMessage(), $matches) ? new \PDOException(\sprintf('Pdo\Odbc::connect() cannot be used for connecting to the "%s" driver', $matches[1])) : $e;
            }
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Pdo;

if (\PHP_VERSION_ID < 80400 && \extension_loaded('pdo_sqlite')) {
    class Sqlite extends \PDO
    {
        public const ATTR_EXTENDED_RESULT_CODES = \PHP_VERSION_ID >= 70400 ? \PDO::SQLITE_ATTR_EXTENDED_RESULT_CODES : 1002;
        public const ATTR_OPEN_FLAGS = \PHP_VERSION_ID >= 70300 ? \PDO::SQLITE_ATTR_OPEN_FLAGS : 1000;
        public const ATTR_READONLY_STATEMENT = \PHP_VERSION_ID >= 70400 ? \PDO::SQLITE_ATTR_READONLY_STATEMENT : 1001;
        public const DETERMINISTIC = \PDO::SQLITE_DETERMINISTIC;
        public const OPEN_READONLY = \PHP_VERSION_ID >= 70300 ? \PDO::SQLITE_OPEN_READONLY : 1;
        public const OPEN_READWRITE = \PHP_VERSION_ID >= 70300 ? \PDO::SQLITE_OPEN_READWRITE : 2;
        public const OPEN_CREATE = \PHP_VERSION_ID >= 70300 ? \PDO::SQLITE_OPEN_CREATE : 4;

        public function __construct(string $dsn, ?string $username = null, ?string $password = null, ?array $options = null)
        {
            parent::__construct($dsn, $username, $password, $options);

            if ('sqlite' !== $driver = $this->getAttribute(\PDO::ATTR_DRIVER_NAME)) {
                throw new \PDOException(\sprintf('Pdo\Sqlite::__construct() cannot be used for connecting to the "%s" driver', $driver));
            }
        }

        public static function connect(string $dsn, ?string $username = null, ?string $password = null, ?array $options = null): self
        {
            try {
                return new self($dsn, $username, $password, $options);
            } catch (\PDOException $e) {
                throw preg_match('/^Pdo\\\\Sqlite::__construct\(\) cannot be used for connecting to the "([a-z]+)" driver/', $e->getMessage(), $matches) ? new \PDOException(\sprintf('Pdo\Sqlite::connect() cannot be used for connecting to the "%s" driver', $matches[1])) : $e;
            }
        }

        public function createAggregate(string $name, callable $step, callable $finalize, int $numArgs = -1): bool
        {
            return $this->sqliteCreateAggregate($name, $step, $finalize, $numArgs);
        }

        public function createCollation(string $name, callable $callback): bool
        {
            return $this->sqliteCreateCollation($name, $callback);
        }

        public function createFunction(string $function_name, callable $callback, int $num_args = -1, int $flags = 0): bool
        {
            return $this->sqliteCreateFunction($function_name, $callback, $num_args, $flags);
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

if (\PHP_VERSION_ID < 80400) {
    // @author Daniel Scherzer <daniel.e.scherzer@gmail.com>
    final class ReflectionConstant
    {
        /**
         * @var string
         *
         * @readonly
         */
        public $name;

        private $value;
        private $deprecated;

        private static $persistentConstants = [];

        public function __construct(string $name)
        {
            if (!defined($name) || false !== strpos($name, '::')) {
                throw new ReflectionException("Constant \"$name\" does not exist");
            }

            $this->name = ltrim($name, '\\');
            $deprecated = false;
            $eh = set_error_handler(static function ($type, $msg, $file, $line) use ($name, &$deprecated, &$eh) {
                if (\E_DEPRECATED === $type && "Constant $name is deprecated" === $msg) {
                    return $deprecated = true;
                }

                return $eh && $eh($type, $msg, $file, $line);
            });

            try {
                $this->value = constant($name);
                $this->deprecated = $deprecated;
            } finally {
                restore_error_handler();
            }
        }

        public function getName(): string
        {
            return $this->name;
        }

        public function getValue()
        {
            return $this->value;
        }

        public function getNamespaceName(): string
        {
            if (false === $slashPos = strrpos($this->name, '\\')) {
                return '';
            }

            return substr($this->name, 0, $slashPos);
        }

        public function getShortName(): string
        {
            if (false === $slashPos = strrpos($this->name, '\\')) {
                return $this->name;
            }

            return substr($this->name, $slashPos + 1);
        }

        public function isDeprecated(): bool
        {
            return $this->deprecated;
        }

        public function __toString(): string
        {
            // A constant is persistent if provided by PHP itself rather than
            // being defined by users. If we got here, we know that it *is*
            // defined, so we just need to figure out if it is defined by the
            // user or not
            if (!self::$persistentConstants) {
                $persistentConstants = get_defined_constants(true);
                unset($persistentConstants['user']);
                foreach ($persistentConstants as $constants) {
                    self::$persistentConstants += $constants;
                }
            }
            $persistent = array_key_exists($this->name, self::$persistentConstants);

            // Can't match the inclusion of `no_file_cache` but the rest is
            // possible to match
            $result = 'Constant [ ';
            if ($persistent || $this->deprecated) {
                $result .= '<';
                if ($persistent) {
                    $result .= 'persistent';
                    if ($this->deprecated) {
                        $result .= ', ';
                    }
                }
                if ($this->deprecated) {
                    $result .= 'deprecated';
                }
                $result .= '> ';
            }
            // Cannot just use gettype() to match zend_zval_type_name()
            if (is_object($this->value)) {
                $result .= \PHP_VERSION_ID >= 80000 ? get_debug_type($this->value) : gettype($this->value);
            } elseif (is_bool($this->value)) {
                $result .= 'bool';
            } elseif (is_int($this->value)) {
                $result .= 'int';
            } elseif (is_float($this->value)) {
                $result .= 'float';
            } elseif (null === $this->value) {
                $result .= 'null';
            } else {
                $result .= gettype($this->value);
            }
            $result .= ' ';
            $result .= $this->name;
            $result .= ' ] { ';
            if (is_array($this->value)) {
                $result .= 'Array';
            } else {
                // This will throw an exception if the value is an object that
                // cannot be converted to string; that is expected and matches
                // the behavior of zval_get_string_func()
                $result .= (string) $this->value;
            }
            $result .= " }\n";

            return $result;
        }

        public function __sleep(): array
        {
            throw new Exception("Serialization of 'ReflectionConstant' is not allowed");
        }

        public function __wakeup(): void
        {
            throw new Exception("Unserialization of 'ReflectionConstant' is not allowed");
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

if (\PHP_VERSION_ID < 80100) {
    #[Attribute(Attribute::TARGET_METHOD | Attribute::TARGET_FUNCTION | Attribute::TARGET_CLASS_CONSTANT)]
    final class Deprecated
    {
        /**
         * @readonly
         */
        public ?string $message;

        /**
         * @readonly
         */
        public ?string $since;

        public function __construct(?string $message = null, ?string $since = null)
        {
            $this->message = $message;
            $this->since = $since;
        }
    }
} elseif (\PHP_VERSION_ID < 80400) {
    require dirname(__DIR__).'/Deprecated.php';
}
<?php

namespace _ContaoManager;

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
if (\PHP_VERSION_ID < 80400) {
    enum RoundingMode
    {
        case HalfAwayFromZero;
        case HalfTowardsZero;
        case HalfEven;
        case HalfOdd;
        case TowardsZero;
        case AwayFromZero;
        case NegativeInfinity;
        case PositiveInfinity;
    }
}
<?php

namespace _ContaoManager;

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
if (\PHP_VERSION_ID < 80400) {
    #[\Attribute(\Attribute::TARGET_METHOD | \Attribute::TARGET_FUNCTION | \Attribute::TARGET_CLASS_CONSTANT)]
    final class Deprecated
    {
        public readonly ?string $message;
        public readonly ?string $since;
        public function __construct(?string $message = null, ?string $since = null)
        {
            $this->message = $message;
            $this->since = $since;
        }
    }
    \class_alias('_ContaoManager\Deprecated', 'Deprecated', \false);
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

use Symfony\Polyfill\Php84 as p;

if (\PHP_VERSION_ID >= 80400) {
    return;
}

if (defined('CURL_VERSION_HTTP3') || \PHP_VERSION_ID < 80200 && function_exists('curl_version') && curl_version()['version'] >= 0x074200) { // libcurl >= 7.66.0
    if (!defined('CURL_HTTP_VERSION_3')) {
        define('CURL_HTTP_VERSION_3', 30);
    }

    if (!defined('CURL_HTTP_VERSION_3ONLY') && defined('CURLOPT_SSH_HOST_PUBLIC_KEY_SHA256')) { // libcurl >= 7.80.0 (7.88 would be better but is slow to check)
        define('CURL_HTTP_VERSION_3ONLY', 31);
    }
}

if (!function_exists('array_find')) {
    function array_find(array $array, callable $callback) { return p\Php84::array_find($array, $callback); }
}

if (!function_exists('array_find_key')) {
    function array_find_key(array $array, callable $callback) { return p\Php84::array_find_key($array, $callback); }
}

if (!function_exists('array_any')) {
    function array_any(array $array, callable $callback): bool { return p\Php84::array_any($array, $callback); }
}

if (!function_exists('array_all')) {
    function array_all(array $array, callable $callback): bool { return p\Php84::array_all($array, $callback); }
}

if (!function_exists('fpow')) {
    function fpow(float $num, float $exponent): float { return p\Php84::fpow($num, $exponent); }
}

if (\PHP_VERSION_ID >= 80000) {
    return require __DIR__.'/bootstrap80.php';
}

if (extension_loaded('mbstring')) {
    if (!function_exists('mb_ucfirst')) {
        function mb_ucfirst(string $string, ?string $encoding = null) { return p\Php84::mb_ucfirst($string, $encoding); }
    }

    if (!function_exists('mb_lcfirst')) {
        function mb_lcfirst(string $string, ?string $encoding = null) { return p\Php84::mb_lcfirst($string, $encoding); }
    }

    if (!function_exists('mb_trim')) {
        function mb_trim(string $string, ?string $characters = null, ?string $encoding = null) { return p\Php84::mb_trim($string, $characters, $encoding); }
    }

    if (!function_exists('mb_ltrim')) {
        function mb_ltrim(string $string, ?string $characters = null, ?string $encoding = null) { return p\Php84::mb_ltrim($string, $characters, $encoding); }
    }

    if (!function_exists('mb_rtrim')) {
        function mb_rtrim(string $string, ?string $characters = null, ?string $encoding = null) { return p\Php84::mb_rtrim($string, $characters, $encoding); }
    }
}

if (extension_loaded('bcmath')) {
    if (!function_exists('bcceil')) {
        function bcceil(string $num): string { return p\Php84::bcceil($num); }
    }
    if (!function_exists('bcdivmod')) {
        function bcdivmod(string $num1, string $num2, ?int $scale = null): ?array { return p\Php84::bcdivmod($num1, $num2, $scale); }
    }
    if (!function_exists('bcfloor')) {
        function bcfloor(string $num): string { return p\Php84::bcfloor($num); }
    }
    if (!function_exists('bcround')) {
        function bcround(string $num, int $precision = 0, $mode = RoundingMode::HalfAwayFromZero): string { return p\Php84::bcround($num, $precision, $mode); }
    }
}

if (extension_loaded('intl') && !function_exists('grapheme_str_split')) {
    function grapheme_str_split(string $string, int $length = 1) { return p\Php84::grapheme_str_split($string, $length); }
}
Symfony Polyfill / Php84
========================

This component provides features added to PHP 8.4 core:

- [`array_find`, `array_find_key`, `array_any` and `array_all`](https://wiki.php.net/rfc/array_find)
- [`bcdivmod`](https://wiki.php.net/rfc/add_bcdivmod_to_bcmath)
- [`Deprecated`](https://wiki.php.net/rfc/deprecated_attribute)
- `CURL_HTTP_VERSION_3` and `CURL_HTTP_VERSION_3ONLY` constants
- [`fpow`](https://wiki.php.net/rfc/raising_zero_to_power_of_negative_number)
- [`grapheme_str_split`](https://wiki.php.net/rfc/grapheme_str_split)
- [`mb_trim`, `mb_ltrim` and `mb_rtrim`](https://wiki.php.net/rfc/mb_trim)
- [`mb_ucfirst` and `mb_lcfirst`](https://wiki.php.net/rfc/mb_ucfirst)
- [`PDO` driver specific sub-classes](https://wiki.php.net/rfc/pdo_driver_specific_subclasses)
- [`ReflectionConstant`](https://github.com/php/php-src/pull/13669)

More information can be found in the
[main Polyfill README](https://github.com/symfony/polyfill/blob/main/README.md).

License
=======

This library is released under the [MIT license](LICENSE).
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Symfony\Polyfill\Php84;

/**
 * @author Ayesh Karunaratne <ayesh@aye.sh>
 * @author Pierre Ambroise <pierre27.ambroise@gmail.com>
 *
 * @internal
 */
final class Php84
{
    /** @return string|false */
    public static function mb_ucfirst(string $string, ?string $encoding = null)
    {
        if (null === $encoding) {
            $encoding = mb_internal_encoding();
        }
        try {
            $validEncoding = @mb_check_encoding('', $encoding);
        } catch (\ValueError $e) {
            throw new \ValueError(\sprintf('mb_ucfirst(): Argument #2 ($encoding) must be a valid encoding, "%s" given', $encoding));
        }
        if (!$validEncoding) {
            if (80000 > \PHP_VERSION_ID) {
                trigger_error(\sprintf('mb_ucfirst(): Argument #2 ($encoding) must be a valid encoding, "%s" given', $encoding), \E_USER_WARNING);
                return \false;
            }
            throw new \ValueError(\sprintf('mb_ucfirst(): Argument #2 ($encoding) must be a valid encoding, "%s" given', $encoding));
        }
        $firstChar = mb_substr($string, 0, 1, $encoding);
        $firstChar = mb_convert_case($firstChar, \MB_CASE_TITLE, $encoding);
        return $firstChar . mb_substr($string, 1, null, $encoding);
    }
    /** @return string|false */
    public static function mb_lcfirst(string $string, ?string $encoding = null)
    {
        if (null === $encoding) {
            $encoding = mb_internal_encoding();
        }
        try {
            $validEncoding = @mb_check_encoding('', $encoding);
        } catch (\ValueError $e) {
            throw new \ValueError(\sprintf('mb_lcfirst(): Argument #2 ($encoding) must be a valid encoding, "%s" given', $encoding));
        }
        if (!$validEncoding) {
            if (80000 > \PHP_VERSION_ID) {
                trigger_error(\sprintf('mb_lcfirst(): Argument #2 ($encoding) must be a valid encoding, "%s" given', $encoding), \E_USER_WARNING);
                return \false;
            }
            throw new \ValueError(\sprintf('mb_lcfirst(): Argument #2 ($encoding) must be a valid encoding, "%s" given', $encoding));
        }
        $firstChar = mb_substr($string, 0, 1, $encoding);
        $firstChar = mb_convert_case($firstChar, \MB_CASE_LOWER, $encoding);
        return $firstChar . mb_substr($string, 1, null, $encoding);
    }
    public static function array_find(array $array, callable $callback)
    {
        foreach ($array as $key => $value) {
            if ($callback($value, $key)) {
                return $value;
            }
        }
        return null;
    }
    public static function array_find_key(array $array, callable $callback)
    {
        foreach ($array as $key => $value) {
            if ($callback($value, $key)) {
                return $key;
            }
        }
        return null;
    }
    public static function array_any(array $array, callable $callback): bool
    {
        foreach ($array as $key => $value) {
            if ($callback($value, $key)) {
                return \true;
            }
        }
        return \false;
    }
    public static function array_all(array $array, callable $callback): bool
    {
        foreach ($array as $key => $value) {
            if (!$callback($value, $key)) {
                return \false;
            }
        }
        return \true;
    }
    public static function fpow(float $num, float $exponent): float
    {
        return $num ** $exponent;
    }
    /** @return string|false */
    public static function mb_trim(string $string, ?string $characters = null, ?string $encoding = null)
    {
        return self::mb_internal_trim('{^[%s]+|[%1$s]+$}Du', $string, $characters, $encoding, __FUNCTION__);
    }
    /** @return string|false */
    public static function mb_ltrim(string $string, ?string $characters = null, ?string $encoding = null)
    {
        return self::mb_internal_trim('{^[%s]+}Du', $string, $characters, $encoding, __FUNCTION__);
    }
    /** @return string|false */
    public static function mb_rtrim(string $string, ?string $characters = null, ?string $encoding = null)
    {
        return self::mb_internal_trim('{[%s]+$}D', $string, $characters, $encoding, __FUNCTION__);
    }
    /** @return string|false */
    private static function mb_internal_trim(string $regex, string $string, ?string $characters, ?string $encoding, string $function)
    {
        if (null === $encoding) {
            $encoding = mb_internal_encoding();
        }
        try {
            $validEncoding = @mb_check_encoding('', $encoding);
        } catch (\ValueError $e) {
            throw new \ValueError(\sprintf('%s(): Argument #3 ($encoding) must be a valid encoding, "%s" given', $function, $encoding));
        }
        if (!$validEncoding) {
            if (80000 > \PHP_VERSION_ID) {
                trigger_error(\sprintf('%s(): Argument #3 ($encoding) must be a valid encoding, "%s" given', $function, $encoding), \E_USER_WARNING);
                return \false;
            }
            throw new \ValueError(\sprintf('%s(): Argument #3 ($encoding) must be a valid encoding, "%s" given', $function, $encoding));
        }
        if ('' === $characters) {
            return null === $encoding ? $string : mb_convert_encoding($string, $encoding);
        }
        if ('UTF-8' === $encoding || \in_array(strtolower($encoding), ['utf-8', 'utf8'], \true)) {
            $encoding = 'UTF-8';
        }
        $string = mb_convert_encoding($string, 'UTF-8', $encoding);
        if (null !== $characters) {
            $characters = mb_convert_encoding($characters, 'UTF-8', $encoding);
        }
        if (null === $characters) {
            $characters = "\\0 \f\n\r\t\v                 　᠎";
        } else {
            $characters = preg_quote($characters);
        }
        $string = preg_replace(\sprintf($regex, $characters), '', $string);
        if ('UTF-8' === $encoding) {
            return $string;
        }
        return mb_convert_encoding($string, $encoding, 'UTF-8');
    }
    public static function grapheme_str_split(string $string, int $length)
    {
        if (0 > $length || 1073741823 < $length) {
            throw new \ValueError('grapheme_str_split(): Argument #2 ($length) must be greater than 0 and less than or equal to 1073741823.');
        }
        if ('' === $string) {
            return [];
        }
        $regex = ((float) \PCRE_VERSION < 10 ? (float) \PCRE_VERSION >= 8.32 : (float) \PCRE_VERSION >= 10.39) ? '\X' : '(?:\r\n|(?:[ -~\x{200C}\x{200D}]|[ᆨ-ᇹ]+|[ᄀ-ᅟ]*(?:[가개갸걔거게겨계고과괘괴교구궈궤귀규그긔기까깨꺄꺠꺼께껴꼐꼬꽈꽤꾀꾜꾸꿔꿰뀌뀨끄끠끼나내냐냬너네녀녜노놔놰뇌뇨누눠눼뉘뉴느늬니다대댜댸더데뎌뎨도돠돼되됴두둬뒈뒤듀드듸디따때땨떄떠떼뗘뗴또똬뙈뙤뚀뚜뚸뛔뛰뜌뜨띄띠라래랴럐러레려례로롸뢔뢰료루뤄뤠뤼류르릐리마매먀먜머메며몌모뫄뫠뫼묘무뭐뭬뮈뮤므믜미바배뱌뱨버베벼볘보봐봬뵈뵤부붜붸뷔뷰브븨비빠빼뺘뺴뻐뻬뼈뼤뽀뽜뽸뾔뾰뿌뿨쀄쀠쀼쁘쁴삐사새샤섀서세셔셰소솨쇄쇠쇼수숴쉐쉬슈스싀시싸쌔쌰썌써쎄쎠쎼쏘쏴쐐쐬쑈쑤쒀쒜쒸쓔쓰씌씨아애야얘어에여예오와왜외요우워웨위유으의이자재쟈쟤저제져졔조좌좨죄죠주줘줴쥐쥬즈즤지짜째쨔쨰쩌쩨쪄쪠쪼쫘쫴쬐쬬쭈쭤쮀쮜쮸쯔쯰찌차채챠챼처체쳐쳬초촤쵀최쵸추춰췌취츄츠츼치카캐캬컈커케켜켸코콰쾌쾨쿄쿠쿼퀘퀴큐크킈키타태탸턔터테텨톄토톼퇘퇴툐투퉈퉤튀튜트틔티파패퍄퍠퍼페펴폐포퐈퐤푀표푸풔풰퓌퓨프픠피하해햐햬허헤혀혜호화홰회효후훠훼휘휴흐희히]?[ᅠ-ᆢ]+|[가-힣])[ᆨ-ᇹ]*|[ᄀ-ᅟ]+|[^\p{Cc}\p{Cf}\p{Zl}\p{Zp}])[\p{Mn}\p{Me}\x{09BE}\x{09D7}\x{0B3E}\x{0B57}\x{0BBE}\x{0BD7}\x{0CC2}\x{0CD5}\x{0CD6}\x{0D3E}\x{0D57}\x{0DCF}\x{0DDF}\x{200C}\x{200D}\x{1D165}\x{1D16E}-\x{1D172}]*|[\p{Cc}\p{Cf}\p{Zl}\p{Zp}])';
        if (!preg_match_all('/' . $regex . '/u', $string, $matches)) {
            return \false;
        }
        if (1 === $length) {
            return $matches[0];
        }
        $chunks = array_chunk($matches[0], $length);
        foreach ($chunks as &$chunk) {
            $chunk = implode('', $chunk);
        }
        return $chunks;
    }
    public static function bcceil(string $num): string
    {
        if (!is_numeric($num)) {
            throw new \ValueError('bcceil(): Argument #1 ($num) is not well-formed');
        }
        return self::bcround($num, 0, \RoundingMode::PositiveInfinity);
    }
    public static function bcdivmod(string $num1, string $num2, ?int $scale = null): ?array
    {
        if (null === $quot = @bcdiv($num1, $num2, 0)) {
            throw new \DivisionByZeroError('Division by zero');
        }
        $scale = $scale ?? (\PHP_VERSION_ID >= 70300 ? bcscale() : (\ini_get('bcmath.scale') ?: 0));
        return [$quot, bcmod($num1, $num2, $scale)];
    }
    public static function bcfloor(string $num): string
    {
        if (!is_numeric($num)) {
            throw new \ValueError('bcfloor(): Argument #1 ($num) is not well-formed');
        }
        return self::bcround($num, 0, \RoundingMode::NegativeInfinity);
    }
    /**
     * @param \RoundingMode|\RoundingMode::* $mode
     */
    public static function bcround(string $num, int $precision = 0, $mode = \RoundingMode::HalfAwayFromZero): string
    {
        if (!is_numeric($num)) {
            throw new \ValueError('bcround(): Argument #1 ($num) is not well-formed');
        }
        $sign = 1;
        if ('' !== $num && ('-' === $num[0] || '+' === $num[0])) {
            if ('-' === $num[0]) {
                $sign = -1;
            }
            $num = substr($num, 1);
        }
        if (\false !== strpos($num, '.')) {
            [$intPart, $fracPart] = array_pad(explode('.', $num, 2), 2, '');
        } else {
            $intPart = $num;
            $fracPart = '';
        }
        if ('' === $intPart) {
            $intPart = '0';
        }
        $intPart = self::trimLeadingZeros($intPart);
        $fracPart = (string) $fracPart;
        if ($precision >= 0) {
            $fracLength = \strlen($fracPart);
            if ($precision <= $fracLength) {
                $scaledInt = $intPart . (string) substr($fracPart, 0, $precision);
                $scaledFrac = (string) substr($fracPart, $precision);
            } else {
                $scaledInt = $intPart . $fracPart . str_repeat('0', $precision - $fracLength);
                $scaledFrac = '';
            }
        } else {
            $shift = -$precision;
            $intLength = \strlen($intPart);
            if ($shift <= $intLength) {
                $splitPos = $intLength - $shift;
                $scaledInt = substr($intPart, 0, $splitPos);
                $scaledInt = '' === $scaledInt ? '0' : $scaledInt;
                $scaledFrac = substr($intPart, $splitPos) . $fracPart;
            } else {
                $scaledInt = '0';
                $scaledFrac = str_repeat('0', $shift - $intLength) . $intPart . $fracPart;
            }
        }
        $roundedInt = self::roundIntegerPart($scaledInt, $scaledFrac, $sign, $mode);
        $isZero = '' === trim($roundedInt, '0');
        $absResult = self::formatRoundedDigits($roundedInt, $precision);
        if (-1 === $sign && !$isZero) {
            $absResult = '-' . $absResult;
        }
        return $absResult;
    }
    private static function roundIntegerPart(string $intPart, string $fracPart, int $sign, $mode): string
    {
        $intPart = self::trimLeadingZeros($intPart);
        if ('' === $fracPart || '' === trim($fracPart, '0')) {
            return $intPart;
        }
        $firstDigit = $fracPart[0];
        $tail = (string) substr($fracPart, 1);
        $tailNonZero = '' !== trim($tail, '0');
        $isGreaterThanHalf = $firstDigit > '5' || '5' === $firstDigit && $tailNonZero;
        $isExactlyHalf = '5' === $firstDigit && !$tailNonZero;
        $shouldIncrease = \false;
        switch ($mode) {
            case \RoundingMode::TowardsZero:
                break;
            case \RoundingMode::AwayFromZero:
                $shouldIncrease = \true;
                break;
            case \RoundingMode::PositiveInfinity:
                $shouldIncrease = $sign > 0;
                break;
            case \RoundingMode::NegativeInfinity:
                $shouldIncrease = $sign < 0;
                break;
            case \RoundingMode::HalfAwayFromZero:
                $shouldIncrease = $isGreaterThanHalf || $isExactlyHalf;
                break;
            case \RoundingMode::HalfTowardsZero:
                $shouldIncrease = $isGreaterThanHalf;
                break;
            case \RoundingMode::HalfEven:
                if ($isGreaterThanHalf) {
                    $shouldIncrease = \true;
                } elseif ($isExactlyHalf && 1 === self::lastDigit($intPart) % 2) {
                    $shouldIncrease = \true;
                }
                break;
            case \RoundingMode::HalfOdd:
                if ($isGreaterThanHalf) {
                    $shouldIncrease = \true;
                } elseif ($isExactlyHalf && 0 === self::lastDigit($intPart) % 2) {
                    $shouldIncrease = \true;
                }
                break;
        }
        if ($shouldIncrease) {
            $intPart = self::incrementDigits($intPart);
        }
        return self::trimLeadingZeros($intPart);
    }
    private static function formatRoundedDigits(string $roundedInt, int $precision): string
    {
        if ($precision > 0) {
            if (\strlen($roundedInt) <= $precision) {
                $roundedInt = str_pad($roundedInt, $precision + 1, '0', \STR_PAD_LEFT);
            }
            $intDigits = substr($roundedInt, 0, -$precision);
            $fracDigits = substr($roundedInt, -$precision);
            $intDigits = self::trimLeadingZeros('' === $intDigits ? '0' : $intDigits);
            $fracDigits = str_pad($fracDigits, $precision, '0', \STR_PAD_LEFT);
            return $intDigits . '.' . $fracDigits;
        }
        if (0 === $precision) {
            return self::trimLeadingZeros($roundedInt);
        }
        $shift = -$precision;
        $digits = $roundedInt . str_repeat('0', $shift);
        return self::trimLeadingZeros($digits);
    }
    private static function incrementDigits(string $digits): string
    {
        $digits = '' === $digits ? '0' : $digits;
        $index = \strlen($digits) - 1;
        $result = $digits;
        $carry = 1;
        while ($index >= 0 && $carry) {
            $value = \ord($result[$index]) - 48 + $carry;
            $carry = $value >= 10 ? 1 : 0;
            $result[$index] = \chr(48 + $value % 10);
            --$index;
        }
        return $carry ? '1' . $result : $result;
    }
    private static function trimLeadingZeros(string $digits): string
    {
        $digits = ltrim($digits, '0');
        return '' === $digits ? '0' : $digits;
    }
    private static function lastDigit(string $digits): int
    {
        $length = \strlen($digits);
        return $length ? \ord($digits[$length - 1]) - 48 : 0;
    }
}
{
    "name": "symfony\/polyfill-php84",
    "type": "library",
    "description": "Symfony polyfill backporting some PHP 8.4+ features to lower PHP versions",
    "keywords": [
        "polyfill",
        "shim",
        "compatibility",
        "portable"
    ],
    "homepage": "https:\/\/symfony.com",
    "license": "MIT",
    "authors": [
        {
            "name": "Nicolas Grekas",
            "email": "p@tchwork.com"
        },
        {
            "name": "Symfony Community",
            "homepage": "https:\/\/symfony.com\/contributors"
        }
    ],
    "require": {
        "php": ">=7.2"
    },
    "autoload": {
        "psr-4": {
            "Symfony\\Polyfill\\Php84\\": ""
        },
        "files": [
            "bootstrap.php"
        ],
        "classmap": [
            "Resources\/stubs"
        ]
    },
    "minimum-stability": "dev",
    "extra": {
        "thanks": {
            "name": "symfony\/polyfill",
            "url": "https:\/\/github.com\/symfony\/polyfill"
        }
    }
}<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\HttpKernel\DataCollector;

use _ContaoManager\Symfony\Component\ErrorHandler\ErrorRenderer\FileLinkFormatter;
use _ContaoManager\Symfony\Component\HttpFoundation\Request;
use _ContaoManager\Symfony\Component\HttpFoundation\RequestStack;
use _ContaoManager\Symfony\Component\HttpFoundation\Response;
use _ContaoManager\Symfony\Component\Stopwatch\Stopwatch;
use _ContaoManager\Symfony\Component\VarDumper\Cloner\Data;
use _ContaoManager\Symfony\Component\VarDumper\Cloner\VarCloner;
use _ContaoManager\Symfony\Component\VarDumper\Dumper\CliDumper;
use _ContaoManager\Symfony\Component\VarDumper\Dumper\ContextProvider\SourceContextProvider;
use _ContaoManager\Symfony\Component\VarDumper\Dumper\DataDumperInterface;
use _ContaoManager\Symfony\Component\VarDumper\Dumper\HtmlDumper;
use _ContaoManager\Symfony\Component\VarDumper\Server\Connection;
/**
 * @author Nicolas Grekas <p@tchwork.com>
 *
 * @final
 */
class DumpDataCollector extends DataCollector implements DataDumperInterface
{
    private ?Stopwatch $stopwatch = null;
    private string|FileLinkFormatter|false $fileLinkFormat;
    private int $dataCount = 0;
    private bool $isCollected = \true;
    private int $clonesCount = 0;
    private int $clonesIndex = 0;
    private array $rootRefs;
    private string $charset;
    private ?RequestStack $requestStack;
    private DataDumperInterface|Connection|null $dumper;
    private mixed $sourceContextProvider;
    private bool $webMode;
    public function __construct(?Stopwatch $stopwatch = null, string|FileLinkFormatter|null $fileLinkFormat = null, ?string $charset = null, ?RequestStack $requestStack = null, DataDumperInterface|Connection|null $dumper = null, ?bool $webMode = null)
    {
        $fileLinkFormat = ($fileLinkFormat ?: \ini_get('xdebug.file_link_format')) ?: get_cfg_var('xdebug.file_link_format');
        $this->stopwatch = $stopwatch;
        $this->fileLinkFormat = $fileLinkFormat instanceof FileLinkFormatter && \false === $fileLinkFormat->format('', 0) ? \false : $fileLinkFormat;
        $this->charset = (($charset ?: \ini_get('php.output_encoding')) ?: \ini_get('default_charset')) ?: 'UTF-8';
        $this->requestStack = $requestStack;
        $this->dumper = $dumper;
        $this->webMode = $webMode ?? !\in_array(\PHP_SAPI, ['cli', 'phpdbg', 'embed'], \true);
        // All clones share these properties by reference:
        $this->rootRefs = [&$this->data, &$this->dataCount, &$this->isCollected, &$this->clonesCount];
        $this->sourceContextProvider = $dumper instanceof Connection && isset($dumper->getContextProviders()['source']) ? $dumper->getContextProviders()['source'] : new SourceContextProvider($this->charset);
    }
    public function __clone()
    {
        $this->clonesIndex = ++$this->clonesCount;
    }
    public function dump(Data $data): ?string
    {
        $this->stopwatch?->start('dump');
        ['name' => $name, 'file' => $file, 'line' => $line, 'file_excerpt' => $fileExcerpt] = $this->sourceContextProvider->getContext();
        if (!$this->dumper || $this->dumper instanceof Connection && !$this->dumper->write($data)) {
            $this->isCollected = \false;
        }
        $context = $data->getContext();
        $label = $context['label'] ?? '';
        unset($context['label']);
        $data = $data->withContext($context);
        if ($this->dumper && !$this->dumper instanceof Connection) {
            $this->doDump($this->dumper, $data, $name, $file, $line, $label);
        }
        if (!$this->dataCount) {
            $this->data = [];
        }
        $this->data[] = compact('data', 'name', 'file', 'line', 'fileExcerpt', 'label');
        ++$this->dataCount;
        $this->stopwatch?->stop('dump');
        return null;
    }
    public function collect(Request $request, Response $response, ?\Throwable $exception = null): void
    {
        if (!$this->dataCount) {
            $this->data = [];
        }
        // Sub-requests and programmatic calls stay in the collected profile.
        if ($this->dumper || $this->requestStack && $this->requestStack->getMainRequest() !== $request || $request->isXmlHttpRequest() || $request->headers->has('Origin')) {
            return;
        }
        // In all other conditions that remove the web debug toolbar, dumps are written on the output.
        if (!$this->requestStack || !$response->headers->has('X-Debug-Token') || $response->isRedirection() || $response->headers->has('Content-Type') && !str_contains($response->headers->get('Content-Type') ?? '', 'html') || 'html' !== $request->getRequestFormat() || \false === strripos($response->getContent(), '</body>')) {
            if ($response->headers->has('Content-Type') && str_contains($response->headers->get('Content-Type') ?? '', 'html')) {
                $dumper = new HtmlDumper('php://output', $this->charset);
                $dumper->setDisplayOptions(['fileLinkFormat' => $this->fileLinkFormat]);
            } else {
                $dumper = new CliDumper('php://output', $this->charset);
                $dumper->setDisplayOptions(['fileLinkFormat' => $this->fileLinkFormat]);
            }
            foreach ($this->data as $dump) {
                $this->doDump($dumper, $dump['data'], $dump['name'], $dump['file'], $dump['line'], $dump['label'] ?? '');
            }
        }
    }
    public function reset(): void
    {
        $this->stopwatch?->reset();
        parent::reset();
        $this->dataCount = 0;
        $this->isCollected = \true;
        $this->clonesCount = 0;
        $this->clonesIndex = 0;
    }
    public function __serialize(): array
    {
        if (!$this->dataCount) {
            $this->data = [];
        }
        if ($this->clonesCount !== $this->clonesIndex) {
            return [];
        }
        $this->data[] = $this->fileLinkFormat;
        $this->data[] = $this->charset;
        $this->dataCount = 0;
        $this->isCollected = \true;
        return ['data' => $this->data];
    }
    public function __unserialize(array $data): void
    {
        $this->data = array_pop($data) ?? [];
        $charset = array_pop($this->data);
        $fileLinkFormat = array_pop($this->data);
        $this->dataCount = \count($this->data);
        foreach ($this->data as $dump) {
            if (!\is_string($dump['name']) || !\is_string($dump['file']) || !\is_int($dump['line'])) {
                throw new \BadMethodCallException('Cannot unserialize ' . __CLASS__);
            }
        }
        self::__construct($this->stopwatch ?? null, \is_string($fileLinkFormat) || $fileLinkFormat instanceof FileLinkFormatter ? $fileLinkFormat : null, \is_string($charset) ? $charset : null);
    }
    public function getDumpsCount(): int
    {
        return $this->dataCount;
    }
    public function getDumps(string $format, int $maxDepthLimit = -1, int $maxItemsPerDepth = -1): array
    {
        $data = fopen('php://memory', 'r+');
        if ('html' === $format) {
            $dumper = new HtmlDumper($data, $this->charset);
            $dumper->setDisplayOptions(['fileLinkFormat' => $this->fileLinkFormat]);
        } else {
            throw new \InvalidArgumentException(\sprintf('Invalid dump format: "%s".', $format));
        }
        $dumps = [];
        if (!$this->dataCount) {
            return $this->data = [];
        }
        foreach ($this->data as $dump) {
            $dumper->dump($dump['data']->withMaxDepth($maxDepthLimit)->withMaxItemsPerDepth($maxItemsPerDepth));
            $dump['data'] = stream_get_contents($data, -1, 0);
            ftruncate($data, 0);
            rewind($data);
            $dumps[] = $dump;
        }
        return $dumps;
    }
    public function getName(): string
    {
        return 'dump';
    }
    public function __destruct()
    {
        if (0 === $this->clonesCount-- && !$this->isCollected && $this->dataCount) {
            $this->clonesCount = 0;
            $this->isCollected = \true;
            $h = headers_list();
            $i = \count($h);
            array_unshift($h, 'Content-Type: ' . \ini_get('default_mimetype'));
            while (0 !== stripos($h[$i], 'Content-Type:')) {
                --$i;
            }
            if ($this->webMode) {
                $dumper = new HtmlDumper('php://output', $this->charset);
                $dumper->setDisplayOptions(['fileLinkFormat' => $this->fileLinkFormat]);
            } else {
                $dumper = new CliDumper('php://output', $this->charset);
                $dumper->setDisplayOptions(['fileLinkFormat' => $this->fileLinkFormat]);
            }
            foreach ($this->data as $i => $dump) {
                $this->data[$i] = null;
                $this->doDump($dumper, $dump['data'], $dump['name'], $dump['file'], $dump['line'], $dump['label'] ?? '');
            }
            $this->data = [];
            $this->dataCount = 0;
        }
    }
    private function doDump(DataDumperInterface $dumper, Data $data, string $name, string $file, int $line, string $label): void
    {
        if ($dumper instanceof CliDumper) {
            $contextDumper = function ($name, $file, $line, $fmt, $label) {
                $this->line = '' !== $label ? $this->style('meta', $label) . ' in ' : '';
                if ($this instanceof HtmlDumper) {
                    if ($file) {
                        $s = $this->style('meta', '%s');
                        $f = strip_tags($this->style('', $file));
                        $name = strip_tags($this->style('', $name));
                        if ($fmt && $link = \is_string($fmt) ? strtr($fmt, ['%f' => $file, '%l' => $line]) : $fmt->format($file, $line)) {
                            $name = \sprintf('<a href="%s" title="%s">' . $s . '</a>', strip_tags($this->style('', $link)), $f, $name);
                        } else {
                            $name = \sprintf('<abbr title="%s">' . $s . '</abbr>', $f, $name);
                        }
                    } else {
                        $name = $this->style('meta', $name);
                    }
                    $this->line .= $name . ' on line ' . $this->style('meta', $line) . ':';
                } else {
                    $this->line .= $this->style('meta', $name) . ' on line ' . $this->style('meta', $line) . ':';
                }
                $this->dumpLine(0);
            };
            $contextDumper = $contextDumper->bindTo($dumper, $dumper);
            $contextDumper($name, $file, $line, $this->fileLinkFormat, $label);
        } else {
            $cloner = new VarCloner();
            $dumper->dump($cloner->cloneVar(('' !== $label ? $label . ' in ' : '') . $name . ' on line ' . $line . ':'));
        }
        $dumper->dump($data);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\HttpKernel\DataCollector;

use _ContaoManager\Symfony\Component\HttpFoundation\Request;
use _ContaoManager\Symfony\Component\HttpFoundation\Response;
/**
 * @author Fabien Potencier <fabien@symfony.com>
 *
 * @final
 */
class MemoryDataCollector extends DataCollector implements LateDataCollectorInterface
{
    public function __construct()
    {
        $this->reset();
    }
    public function collect(Request $request, Response $response, ?\Throwable $exception = null): void
    {
        $this->updateMemoryUsage();
    }
    public function reset(): void
    {
        $this->data = ['memory' => 0, 'memory_limit' => $this->convertToBytes(\ini_get('memory_limit'))];
    }
    public function lateCollect(): void
    {
        $this->updateMemoryUsage();
    }
    public function getMemory(): int
    {
        return $this->data['memory'];
    }
    public function getMemoryLimit(): int|float
    {
        return $this->data['memory_limit'];
    }
    public function updateMemoryUsage(): void
    {
        $this->data['memory'] = memory_get_peak_usage(\true);
    }
    public function getName(): string
    {
        return 'memory';
    }
    private function convertToBytes(string $memoryLimit): int|float
    {
        if ('-1' === $memoryLimit) {
            return -1;
        }
        $memoryLimit = strtolower($memoryLimit);
        $max = strtolower(ltrim($memoryLimit, '+'));
        if (str_starts_with($max, '0x')) {
            $max = \intval($max, 16);
        } elseif (str_starts_with($max, '0')) {
            $max = \intval($max, 8);
        } else {
            $max = (int) $max;
        }
        switch (substr($memoryLimit, -1)) {
            case 't':
                $max *= 1024;
            // no break
            case 'g':
                $max *= 1024;
            // no break
            case 'm':
                $max *= 1024;
            // no break
            case 'k':
                $max *= 1024;
        }
        return $max;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\HttpKernel\DataCollector;

/**
 * LateDataCollectorInterface.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
interface LateDataCollectorInterface
{
    /**
     * Collects data as late as possible.
     *
     * @return void
     */
    public function lateCollect();
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\HttpKernel\DataCollector;

use _ContaoManager\Symfony\Component\HttpFoundation\RedirectResponse;
use _ContaoManager\Symfony\Component\HttpFoundation\Request;
use _ContaoManager\Symfony\Component\HttpFoundation\Response;
use _ContaoManager\Symfony\Component\HttpKernel\Event\ControllerEvent;
/**
 * @author Fabien Potencier <fabien@symfony.com>
 */
class RouterDataCollector extends DataCollector
{
    /**
     * @var \SplObjectStorage<Request, callable>
     */
    protected $controllers;
    public function __construct()
    {
        $this->reset();
    }
    /**
     * @final
     */
    public function collect(Request $request, Response $response, ?\Throwable $exception = null): void
    {
        if ($response instanceof RedirectResponse) {
            $this->data['redirect'] = \true;
            $this->data['url'] = $response->getTargetUrl();
            if ($this->controllers->offsetExists($request)) {
                $this->data['route'] = $this->guessRoute($request, $this->controllers[$request]);
            }
        }
        unset($this->controllers[$request]);
    }
    /**
     * @return void
     */
    public function reset()
    {
        $this->controllers = new \SplObjectStorage();
        $this->data = ['redirect' => \false, 'url' => null, 'route' => null];
    }
    /**
     * @return string
     */
    protected function guessRoute(Request $request, string|object|array $controller)
    {
        return 'n/a';
    }
    /**
     * Remembers the controller associated to each request.
     *
     * @return void
     */
    public function onKernelController(ControllerEvent $event)
    {
        $this->controllers[$event->getRequest()] = $event->getController();
    }
    /**
     * @return bool Whether this request will result in a redirect
     */
    public function getRedirect(): bool
    {
        return $this->data['redirect'];
    }
    public function getTargetUrl(): ?string
    {
        return $this->data['url'];
    }
    public function getTargetRoute(): ?string
    {
        return $this->data['route'];
    }
    public function getName(): string
    {
        return 'router';
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\HttpKernel\DataCollector;

use _ContaoManager\Symfony\Component\HttpFoundation\Request;
use _ContaoManager\Symfony\Component\HttpFoundation\Response;
use _ContaoManager\Symfony\Component\HttpKernel\KernelInterface;
use _ContaoManager\Symfony\Component\Stopwatch\Stopwatch;
use _ContaoManager\Symfony\Component\Stopwatch\StopwatchEvent;
/**
 * @author Fabien Potencier <fabien@symfony.com>
 *
 * @final
 */
class TimeDataCollector extends DataCollector implements LateDataCollectorInterface
{
    private ?KernelInterface $kernel;
    private ?Stopwatch $stopwatch;
    public function __construct(?KernelInterface $kernel = null, ?Stopwatch $stopwatch = null)
    {
        $this->kernel = $kernel;
        $this->stopwatch = $stopwatch;
        $this->data = ['events' => [], 'stopwatch_installed' => \false, 'start_time' => 0];
    }
    public function collect(Request $request, Response $response, ?\Throwable $exception = null): void
    {
        if (null !== $this->kernel) {
            $startTime = $this->kernel->getStartTime();
        } else {
            $startTime = $request->server->get('REQUEST_TIME_FLOAT');
        }
        $this->data = ['token' => $request->attributes->get('_stopwatch_token'), 'start_time' => $startTime * 1000, 'events' => [], 'stopwatch_installed' => class_exists(Stopwatch::class, \false)];
    }
    public function reset(): void
    {
        $this->data = ['events' => [], 'stopwatch_installed' => \false, 'start_time' => 0];
        $this->stopwatch?->reset();
    }
    public function lateCollect(): void
    {
        if (null !== $this->stopwatch && isset($this->data['token'])) {
            $this->setEvents($this->stopwatch->getSectionEvents($this->data['token']));
        }
        unset($this->data['token']);
    }
    /**
     * @param StopwatchEvent[] $events The request events
     */
    public function setEvents(array $events): void
    {
        foreach ($events as $event) {
            $event->ensureStopped();
        }
        $this->data['events'] = $events;
    }
    /**
     * @return StopwatchEvent[]
     */
    public function getEvents(): array
    {
        return $this->data['events'];
    }
    /**
     * Gets the request elapsed time.
     */
    public function getDuration(): float
    {
        if (!isset($this->data['events']['__section__'])) {
            return 0;
        }
        $lastEvent = $this->data['events']['__section__'];
        return $lastEvent->getOrigin() + $lastEvent->getDuration() - $this->getStartTime();
    }
    /**
     * Gets the initialization time.
     *
     * This is the time spent until the beginning of the request handling.
     */
    public function getInitTime(): float
    {
        if (!isset($this->data['events']['__section__'])) {
            return 0;
        }
        return $this->data['events']['__section__']->getOrigin() - $this->getStartTime();
    }
    public function getStartTime(): float
    {
        return $this->data['start_time'];
    }
    public function isStopwatchInstalled(): bool
    {
        return $this->data['stopwatch_installed'];
    }
    public function getName(): string
    {
        return 'time';
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\HttpKernel\DataCollector;

use _ContaoManager\Symfony\Component\HttpFoundation\Request;
use _ContaoManager\Symfony\Component\HttpFoundation\Response;
use _ContaoManager\Symfony\Contracts\Service\ResetInterface;
/**
 * DataCollectorInterface.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
interface DataCollectorInterface extends ResetInterface
{
    /**
     * Collects data for the given Request and Response.
     *
     * @return void
     */
    public function collect(Request $request, Response $response, ?\Throwable $exception = null);
    /**
     * Returns the name of the collector.
     *
     * @return string
     */
    public function getName();
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\HttpKernel\DataCollector;

use _ContaoManager\Symfony\Component\EventDispatcher\EventSubscriberInterface;
use _ContaoManager\Symfony\Component\HttpFoundation\Cookie;
use _ContaoManager\Symfony\Component\HttpFoundation\ParameterBag;
use _ContaoManager\Symfony\Component\HttpFoundation\Request;
use _ContaoManager\Symfony\Component\HttpFoundation\RequestStack;
use _ContaoManager\Symfony\Component\HttpFoundation\Response;
use _ContaoManager\Symfony\Component\HttpFoundation\Session\SessionBagInterface;
use _ContaoManager\Symfony\Component\HttpFoundation\Session\SessionInterface;
use _ContaoManager\Symfony\Component\HttpKernel\Event\ControllerEvent;
use _ContaoManager\Symfony\Component\HttpKernel\Event\ResponseEvent;
use _ContaoManager\Symfony\Component\HttpKernel\KernelEvents;
use _ContaoManager\Symfony\Component\VarDumper\Cloner\Data;
/**
 * @author Fabien Potencier <fabien@symfony.com>
 *
 * @final
 */
class RequestDataCollector extends DataCollector implements EventSubscriberInterface, LateDataCollectorInterface
{
    /**
     * @var \SplObjectStorage<Request, callable>
     */
    private \SplObjectStorage $controllers;
    private array $sessionUsages = [];
    private ?RequestStack $requestStack;
    public function __construct(?RequestStack $requestStack = null)
    {
        $this->controllers = new \SplObjectStorage();
        $this->requestStack = $requestStack;
    }
    public function collect(Request $request, Response $response, ?\Throwable $exception = null): void
    {
        // attributes are serialized and as they can be anything, they need to be converted to strings.
        $attributes = [];
        $route = '';
        foreach ($request->attributes->all() as $key => $value) {
            if ('_route' === $key) {
                $route = \is_object($value) ? $value->getPath() : $value;
                $attributes[$key] = $route;
            } else {
                $attributes[$key] = $value;
            }
        }
        $content = $request->getContent();
        $sessionMetadata = [];
        $sessionAttributes = [];
        $flashes = [];
        if (!$request->attributes->getBoolean('_stateless') && $request->hasSession()) {
            $session = $request->getSession();
            if ($session->isStarted()) {
                $sessionMetadata['Created'] = date(\DATE_RFC822, $session->getMetadataBag()->getCreated());
                $sessionMetadata['Last used'] = date(\DATE_RFC822, $session->getMetadataBag()->getLastUsed());
                $sessionMetadata['Lifetime'] = $session->getMetadataBag()->getLifetime();
                $sessionAttributes = $session->all();
                $flashes = $session->getFlashBag()->peekAll();
            }
        }
        $statusCode = $response->getStatusCode();
        $responseCookies = [];
        foreach ($response->headers->getCookies() as $cookie) {
            $responseCookies[$cookie->getName()] = $cookie;
        }
        $dotenvVars = [];
        foreach (explode(',', $_SERVER['SYMFONY_DOTENV_VARS'] ?? $_ENV['SYMFONY_DOTENV_VARS'] ?? '') as $name) {
            if ('' !== $name && isset($_ENV[$name])) {
                $dotenvVars[$name] = $_ENV[$name];
            }
        }
        $this->data = ['method' => $request->getMethod(), 'format' => $request->getRequestFormat(), 'content_type' => $response->headers->get('Content-Type', 'text/html'), 'status_text' => Response::$statusTexts[$statusCode] ?? '', 'status_code' => $statusCode, 'request_query' => $request->query->all(), 'request_request' => $request->request->all(), 'request_files' => $request->files->all(), 'request_headers' => $request->headers->all(), 'request_server' => $request->server->all(), 'request_cookies' => $request->cookies->all(), 'request_attributes' => $attributes, 'route' => $route, 'response_headers' => $response->headers->all(), 'response_cookies' => $responseCookies, 'session_metadata' => $sessionMetadata, 'session_attributes' => $sessionAttributes, 'session_usages' => array_values($this->sessionUsages), 'stateless_check' => $this->requestStack?->getMainRequest()?->attributes->get('_stateless') ?? \false, 'flashes' => $flashes, 'path_info' => $request->getPathInfo(), 'controller' => 'n/a', 'locale' => $request->getLocale(), 'dotenv_vars' => $dotenvVars];
        if (isset($this->data['request_headers']['php-auth-pw'])) {
            $this->data['request_headers']['php-auth-pw'] = '******';
        }
        if (isset($this->data['request_server']['PHP_AUTH_PW'])) {
            $this->data['request_server']['PHP_AUTH_PW'] = '******';
        }
        if (isset($this->data['request_request']['_password'])) {
            $encodedPassword = rawurlencode($this->data['request_request']['_password']);
            $content = str_replace('_password=' . $encodedPassword, '_password=******', $content);
            $this->data['request_request']['_password'] = '******';
        }
        $this->data['content'] = $content;
        foreach ($this->data as $key => $value) {
            if (!\is_array($value)) {
                continue;
            }
            if ('request_headers' === $key || 'response_headers' === $key) {
                $this->data[$key] = array_map(fn($v) => isset($v[0]) && !isset($v[1]) ? $v[0] : $v, $value);
            }
        }
        if (isset($this->controllers[$request])) {
            $this->data['controller'] = $this->parseController($this->controllers[$request]);
            unset($this->controllers[$request]);
        }
        if ($request->attributes->has('_redirected') && $redirectCookie = $request->cookies->get('sf_redirect')) {
            $this->data['redirect'] = json_decode($redirectCookie, \true);
            $response->headers->clearCookie('sf_redirect');
        }
        if ($response->isRedirect()) {
            $response->headers->setCookie(new Cookie('sf_redirect', json_encode(['token' => $response->headers->get('x-debug-token'), 'route' => $request->attributes->get('_route', 'n/a'), 'method' => $request->getMethod(), 'controller' => $this->parseController($request->attributes->get('_controller')), 'status_code' => $statusCode, 'status_text' => Response::$statusTexts[$statusCode]]), 0, '/', null, $request->isSecure(), \true, \false, 'lax'));
        }
        $this->data['identifier'] = $this->data['route'] ?: (\is_array($this->data['controller']) ? $this->data['controller']['class'] . '::' . $this->data['controller']['method'] . '()' : $this->data['controller']);
        if ($response->headers->has('x-previous-debug-token')) {
            $this->data['forward_token'] = $response->headers->get('x-previous-debug-token');
        }
    }
    public function lateCollect(): void
    {
        $this->data = $this->cloneVar($this->data);
    }
    public function reset(): void
    {
        parent::reset();
        $this->controllers = new \SplObjectStorage();
        $this->sessionUsages = [];
    }
    public function getMethod(): string
    {
        return $this->data['method'];
    }
    public function getPathInfo(): string
    {
        return $this->data['path_info'];
    }
    /**
     * @return ParameterBag
     */
    public function getRequestRequest()
    {
        return new ParameterBag($this->data['request_request']->getValue());
    }
    /**
     * @return ParameterBag
     */
    public function getRequestQuery()
    {
        return new ParameterBag($this->data['request_query']->getValue());
    }
    /**
     * @return ParameterBag
     */
    public function getRequestFiles()
    {
        return new ParameterBag($this->data['request_files']->getValue());
    }
    /**
     * @return ParameterBag
     */
    public function getRequestHeaders()
    {
        return new ParameterBag($this->data['request_headers']->getValue());
    }
    /**
     * @return ParameterBag
     */
    public function getRequestServer(bool $raw = \false)
    {
        return new ParameterBag($this->data['request_server']->getValue($raw));
    }
    /**
     * @return ParameterBag
     */
    public function getRequestCookies(bool $raw = \false)
    {
        return new ParameterBag($this->data['request_cookies']->getValue($raw));
    }
    /**
     * @return ParameterBag
     */
    public function getRequestAttributes()
    {
        return new ParameterBag($this->data['request_attributes']->getValue());
    }
    /**
     * @return ParameterBag
     */
    public function getResponseHeaders()
    {
        return new ParameterBag($this->data['response_headers']->getValue());
    }
    /**
     * @return ParameterBag
     */
    public function getResponseCookies()
    {
        return new ParameterBag($this->data['response_cookies']->getValue());
    }
    public function getSessionMetadata(): array
    {
        return $this->data['session_metadata']->getValue();
    }
    public function getSessionAttributes(): array
    {
        return $this->data['session_attributes']->getValue();
    }
    public function getStatelessCheck(): bool
    {
        return $this->data['stateless_check'];
    }
    public function getSessionUsages(): Data|array
    {
        return $this->data['session_usages'];
    }
    public function getFlashes(): array
    {
        return $this->data['flashes']->getValue();
    }
    /**
     * @return string|resource
     */
    public function getContent()
    {
        return $this->data['content'];
    }
    /**
     * @return bool
     */
    public function isJsonRequest()
    {
        return 1 === preg_match('{^application/(?:\w+\++)*json$}i', $this->data['request_headers']['content-type']);
    }
    /**
     * @return string|null
     */
    public function getPrettyJson()
    {
        $decoded = json_decode($this->getContent());
        return \JSON_ERROR_NONE === json_last_error() ? json_encode($decoded, \JSON_PRETTY_PRINT) : null;
    }
    public function getContentType(): string
    {
        return $this->data['content_type'];
    }
    public function getStatusText(): string
    {
        return $this->data['status_text'];
    }
    public function getStatusCode(): int
    {
        return $this->data['status_code'];
    }
    public function getFormat(): string
    {
        return $this->data['format'];
    }
    public function getLocale(): string
    {
        return $this->data['locale'];
    }
    /**
     * @return ParameterBag
     */
    public function getDotenvVars()
    {
        return new ParameterBag($this->data['dotenv_vars']->getValue());
    }
    /**
     * Gets the route name.
     *
     * The _route request attributes is automatically set by the Router Matcher.
     */
    public function getRoute(): string
    {
        return $this->data['route'];
    }
    public function getIdentifier(): string
    {
        return $this->data['identifier'];
    }
    /**
     * Gets the route parameters.
     *
     * The _route_params request attributes is automatically set by the RouterListener.
     */
    public function getRouteParams(): array
    {
        return isset($this->data['request_attributes']['_route_params']) ? $this->data['request_attributes']['_route_params']->getValue() : [];
    }
    /**
     * Gets the parsed controller.
     *
     * @return array|string|Data The controller as a string or array of data
     *                           with keys 'class', 'method', 'file' and 'line'
     */
    public function getController(): array|string|Data
    {
        return $this->data['controller'];
    }
    /**
     * Gets the previous request attributes.
     *
     * @return array|Data|false A legacy array of data from the previous redirection response
     *                          or false otherwise
     */
    public function getRedirect(): array|Data|false
    {
        return $this->data['redirect'] ?? \false;
    }
    public function getForwardToken(): ?string
    {
        return $this->data['forward_token'] ?? null;
    }
    public function onKernelController(ControllerEvent $event): void
    {
        $this->controllers[$event->getRequest()] = $event->getController();
    }
    public function onKernelResponse(ResponseEvent $event): void
    {
        if (!$event->isMainRequest()) {
            return;
        }
        if ($event->getRequest()->cookies->has('sf_redirect')) {
            $event->getRequest()->attributes->set('_redirected', \true);
        }
    }
    public static function getSubscribedEvents(): array
    {
        return [KernelEvents::CONTROLLER => 'onKernelController', KernelEvents::RESPONSE => 'onKernelResponse'];
    }
    public function getName(): string
    {
        return 'request';
    }
    public function collectSessionUsage(): void
    {
        $trace = debug_backtrace(\DEBUG_BACKTRACE_IGNORE_ARGS);
        $traceEndIndex = \count($trace) - 1;
        for ($i = $traceEndIndex; $i > 0; --$i) {
            if (null !== ($class = $trace[$i]['class'] ?? null) && (is_subclass_of($class, SessionInterface::class) || is_subclass_of($class, SessionBagInterface::class))) {
                $traceEndIndex = $i;
                break;
            }
        }
        if (\count($trace) - 1 === $traceEndIndex) {
            return;
        }
        // Remove part of the backtrace that belongs to session only
        array_splice($trace, 0, $traceEndIndex);
        // Merge identical backtraces generated by internal call reports
        $name = \sprintf('%s:%s', $trace[1]['class'] ?? $trace[0]['file'], $trace[0]['line']);
        if (!\array_key_exists($name, $this->sessionUsages)) {
            $this->sessionUsages[$name] = ['name' => $name, 'file' => $trace[0]['file'], 'line' => $trace[0]['line'], 'trace' => $trace];
        }
    }
    /**
     * @return array|string An array of controller data or a simple string
     */
    private function parseController(array|object|string|null $controller): array|string
    {
        if (\is_string($controller) && str_contains($controller, '::')) {
            $controller = explode('::', $controller);
        }
        if (\is_array($controller)) {
            try {
                $r = new \ReflectionMethod($controller[0], $controller[1]);
                return ['class' => \is_object($controller[0]) ? get_debug_type($controller[0]) : $controller[0], 'method' => $controller[1], 'file' => $r->getFileName(), 'line' => $r->getStartLine()];
            } catch (\ReflectionException) {
                if (\is_callable($controller)) {
                    // using __call or  __callStatic
                    return ['class' => \is_object($controller[0]) ? get_debug_type($controller[0]) : $controller[0], 'method' => $controller[1], 'file' => 'n/a', 'line' => 'n/a'];
                }
            }
        }
        if ($controller instanceof \Closure) {
            $r = new \ReflectionFunction($controller);
            $controller = ['class' => $r->getName(), 'method' => null, 'file' => $r->getFileName(), 'line' => $r->getStartLine()];
            if (str_contains($r->name, '{closure')) {
                return $controller;
            }
            $controller['method'] = $r->name;
            if ($class = \PHP_VERSION_ID >= 80111 ? $r->getClosureCalledClass() : $r->getClosureScopeClass()) {
                $controller['class'] = $class->name;
            } else {
                return $r->name;
            }
            return $controller;
        }
        if (\is_object($controller)) {
            $r = new \ReflectionClass($controller);
            return ['class' => $r->getName(), 'method' => null, 'file' => $r->getFileName(), 'line' => $r->getStartLine()];
        }
        return \is_string($controller) ? $controller : 'n/a';
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\HttpKernel\DataCollector;

use _ContaoManager\Symfony\Component\HttpFoundation\Request;
use _ContaoManager\Symfony\Component\HttpFoundation\Response;
/**
 * @author Bart van den Burg <bart@burgov.nl>
 *
 * @final
 */
class AjaxDataCollector extends DataCollector
{
    public function collect(Request $request, Response $response, ?\Throwable $exception = null): void
    {
        // all collecting is done client side
    }
    public function reset(): void
    {
        // all collecting is done client side
    }
    public function getName(): string
    {
        return 'ajax';
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\HttpKernel\DataCollector;

use _ContaoManager\Symfony\Component\VarDumper\Caster\CutStub;
use _ContaoManager\Symfony\Component\VarDumper\Caster\ReflectionCaster;
use _ContaoManager\Symfony\Component\VarDumper\Cloner\ClonerInterface;
use _ContaoManager\Symfony\Component\VarDumper\Cloner\Data;
use _ContaoManager\Symfony\Component\VarDumper\Cloner\Stub;
use _ContaoManager\Symfony\Component\VarDumper\Cloner\VarCloner;
/**
 * DataCollector.
 *
 * Children of this class must store the collected data in the data property.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 * @author Bernhard Schussek <bschussek@symfony.com>
 */
abstract class DataCollector implements DataCollectorInterface
{
    /**
     * @var array|Data
     */
    protected $data = [];
    private ClonerInterface $cloner;
    /**
     * Converts the variable into a serializable Data instance.
     *
     * This array can be displayed in the template using
     * the VarDumper component.
     */
    protected function cloneVar(mixed $var): Data
    {
        if ($var instanceof Data) {
            return $var;
        }
        if (!isset($this->cloner)) {
            $this->cloner = new VarCloner();
            $this->cloner->setMaxItems(-1);
            $this->cloner->addCasters($this->getCasters());
        }
        return $this->cloner->cloneVar($var);
    }
    /**
     * @return callable[] The casters to add to the cloner
     */
    protected function getCasters()
    {
        $casters = ['*' => function ($v, array $a, Stub $s, $isNested) {
            if (!$v instanceof Stub) {
                $b = $a;
                foreach ($a as $k => $v) {
                    if (!\is_object($v) || $v instanceof \DateTimeInterface || $v instanceof Stub) {
                        continue;
                    }
                    try {
                        $a[$k] = $s = new CutStub($v);
                        if ($b[$k] === $s) {
                            // we've hit a non-typed reference
                            $a[$k] = $v;
                        }
                    } catch (\TypeError $e) {
                        // we've hit a typed reference
                    }
                }
            }
            return $a;
        }] + ReflectionCaster::UNSET_CLOSURE_FILE_INFO;
        return $casters;
    }
    public function __sleep(): array
    {
        return ['data'];
    }
    /**
     * @return void
     */
    public function __wakeup()
    {
    }
    /**
     * @internal to prevent implementing \Serializable
     */
    final protected function serialize(): void
    {
    }
    /**
     * @internal to prevent implementing \Serializable
     */
    final protected function unserialize(string $data): void
    {
    }
    /**
     * @return void
     */
    public function reset()
    {
        $this->data = [];
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\HttpKernel\DataCollector;

use _ContaoManager\Symfony\Component\ErrorHandler\Exception\SilencedErrorContext;
use _ContaoManager\Symfony\Component\HttpFoundation\Request;
use _ContaoManager\Symfony\Component\HttpFoundation\RequestStack;
use _ContaoManager\Symfony\Component\HttpFoundation\Response;
use _ContaoManager\Symfony\Component\HttpKernel\Log\DebugLoggerConfigurator;
use _ContaoManager\Symfony\Component\HttpKernel\Log\DebugLoggerInterface;
use _ContaoManager\Symfony\Component\VarDumper\Cloner\Data;
/**
 * @author Fabien Potencier <fabien@symfony.com>
 *
 * @final
 */
class LoggerDataCollector extends DataCollector implements LateDataCollectorInterface
{
    private ?DebugLoggerInterface $logger;
    private ?string $containerPathPrefix;
    private ?Request $currentRequest = null;
    private ?RequestStack $requestStack;
    private ?array $processedLogs = null;
    public function __construct(?object $logger = null, ?string $containerPathPrefix = null, ?RequestStack $requestStack = null)
    {
        $this->logger = DebugLoggerConfigurator::getDebugLogger($logger);
        $this->containerPathPrefix = $containerPathPrefix;
        $this->requestStack = $requestStack;
    }
    public function collect(Request $request, Response $response, ?\Throwable $exception = null): void
    {
        $this->currentRequest = $this->requestStack && $this->requestStack->getMainRequest() !== $request ? $request : null;
    }
    public function lateCollect(): void
    {
        if ($this->logger) {
            $containerDeprecationLogs = $this->getContainerDeprecationLogs();
            $this->data = $this->computeErrorsCount($containerDeprecationLogs);
            // get compiler logs later (only when they are needed) to improve performance
            $this->data['compiler_logs'] = [];
            $this->data['compiler_logs_filepath'] = $this->containerPathPrefix . 'Compiler.log';
            $this->data['logs'] = $this->sanitizeLogs(array_merge($this->logger->getLogs($this->currentRequest), $containerDeprecationLogs));
            $this->data = $this->cloneVar($this->data);
        }
        $this->currentRequest = null;
    }
    public function getLogs(): Data|array
    {
        return $this->data['logs'] ?? [];
    }
    public function getProcessedLogs(): array
    {
        if (null !== $this->processedLogs) {
            return $this->processedLogs;
        }
        $rawLogs = $this->getLogs();
        if ([] === $rawLogs) {
            return $this->processedLogs = $rawLogs;
        }
        $logs = [];
        foreach ($this->getLogs()->getValue() as $rawLog) {
            $rawLogData = $rawLog->getValue();
            if ($rawLogData['priority']->getValue() > 300) {
                $logType = 'error';
            } elseif (isset($rawLogData['scream']) && \false === $rawLogData['scream']->getValue()) {
                $logType = 'deprecation';
            } elseif (isset($rawLogData['scream']) && \true === $rawLogData['scream']->getValue()) {
                $logType = 'silenced';
            } else {
                $logType = 'regular';
            }
            $logs[] = ['type' => $logType, 'errorCount' => $rawLog['errorCount'] ?? 1, 'timestamp' => $rawLogData['timestamp_rfc3339']->getValue(), 'priority' => $rawLogData['priority']->getValue(), 'priorityName' => $rawLogData['priorityName']->getValue(), 'channel' => $rawLogData['channel']->getValue(), 'message' => $rawLogData['message'], 'context' => $rawLogData['context']];
        }
        // sort logs from oldest to newest
        usort($logs, static fn($logA, $logB) => $logA['timestamp'] <=> $logB['timestamp']);
        return $this->processedLogs = $logs;
    }
    public function getFilters(): array
    {
        $filters = ['channel' => [], 'priority' => ['Debug' => 100, 'Info' => 200, 'Notice' => 250, 'Warning' => 300, 'Error' => 400, 'Critical' => 500, 'Alert' => 550, 'Emergency' => 600]];
        $allChannels = [];
        foreach ($this->getProcessedLogs() as $log) {
            if ('' === trim($log['channel'] ?? '')) {
                continue;
            }
            $allChannels[] = $log['channel'];
        }
        $channels = array_unique($allChannels);
        sort($channels);
        $filters['channel'] = $channels;
        return $filters;
    }
    public function getPriorities(): Data|array
    {
        return $this->data['priorities'] ?? [];
    }
    public function countErrors(): int
    {
        return $this->data['error_count'] ?? 0;
    }
    public function countDeprecations(): int
    {
        return $this->data['deprecation_count'] ?? 0;
    }
    public function countWarnings(): int
    {
        return $this->data['warning_count'] ?? 0;
    }
    public function countScreams(): int
    {
        return $this->data['scream_count'] ?? 0;
    }
    public function getCompilerLogs(): Data
    {
        return $this->cloneVar($this->getContainerCompilerLogs($this->data['compiler_logs_filepath'] ?? null));
    }
    public function getName(): string
    {
        return 'logger';
    }
    private function getContainerDeprecationLogs(): array
    {
        if (null === $this->containerPathPrefix || !is_file($file = $this->containerPathPrefix . 'Deprecations.log')) {
            return [];
        }
        if ('' === $logContent = trim(file_get_contents($file))) {
            return [];
        }
        $bootTime = filemtime($file);
        $logs = [];
        foreach (unserialize($logContent) as $log) {
            $log['context'] = ['exception' => new SilencedErrorContext($log['type'], $log['file'], $log['line'], $log['trace'], $log['count'])];
            $log['timestamp'] = $bootTime;
            $log['timestamp_rfc3339'] = (new \DateTimeImmutable())->setTimestamp($bootTime)->format(\DateTimeInterface::RFC3339_EXTENDED);
            $log['priority'] = 100;
            $log['priorityName'] = 'DEBUG';
            $log['channel'] = null;
            $log['scream'] = \false;
            unset($log['type'], $log['file'], $log['line'], $log['trace'], $log['trace'], $log['count']);
            $logs[] = $log;
        }
        return $logs;
    }
    private function getContainerCompilerLogs(?string $compilerLogsFilepath = null): array
    {
        if (!$compilerLogsFilepath || !is_file($compilerLogsFilepath)) {
            return [];
        }
        $logs = [];
        foreach (file($compilerLogsFilepath, \FILE_IGNORE_NEW_LINES) as $log) {
            $log = explode(': ', $log, 2);
            if (!isset($log[1]) || !preg_match('/^[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*+(?:\\\\[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*+)++$/', $log[0])) {
                $log = ['Unknown Compiler Pass', implode(': ', $log)];
            }
            $logs[$log[0]][] = ['message' => $log[1]];
        }
        return $logs;
    }
    private function sanitizeLogs(array $logs): array
    {
        $sanitizedLogs = [];
        $silencedLogs = [];
        foreach ($logs as $log) {
            if (!$this->isSilencedOrDeprecationErrorLog($log)) {
                $sanitizedLogs[] = $log;
                continue;
            }
            $message = '_' . $log['message'];
            $exception = $log['context']['exception'];
            if ($exception instanceof SilencedErrorContext) {
                if (isset($silencedLogs[$h = spl_object_hash($exception)])) {
                    continue;
                }
                $silencedLogs[$h] = \true;
                if (!isset($sanitizedLogs[$message])) {
                    $sanitizedLogs[$message] = $log + ['errorCount' => 0, 'scream' => \true];
                }
                $sanitizedLogs[$message]['errorCount'] += $exception->count;
                continue;
            }
            $errorId = hash('xxh128', "{$exception->getSeverity()}/{$exception->getLine()}/{$exception->getFile()}\x00{$message}", \true);
            if (isset($sanitizedLogs[$errorId])) {
                ++$sanitizedLogs[$errorId]['errorCount'];
            } else {
                $log += ['errorCount' => 1, 'scream' => \false];
                $sanitizedLogs[$errorId] = $log;
            }
        }
        return array_values($sanitizedLogs);
    }
    private function isSilencedOrDeprecationErrorLog(array $log): bool
    {
        if (!isset($log['context']['exception'])) {
            return \false;
        }
        $exception = $log['context']['exception'];
        if ($exception instanceof SilencedErrorContext) {
            return \true;
        }
        if ($exception instanceof \ErrorException && \in_array($exception->getSeverity(), [\E_DEPRECATED, \E_USER_DEPRECATED], \true)) {
            return \true;
        }
        return \false;
    }
    private function computeErrorsCount(array $containerDeprecationLogs): array
    {
        $silencedLogs = [];
        $count = ['error_count' => $this->logger->countErrors($this->currentRequest), 'deprecation_count' => 0, 'warning_count' => 0, 'scream_count' => 0, 'priorities' => []];
        foreach ($this->logger->getLogs($this->currentRequest) as $log) {
            if (isset($count['priorities'][$log['priority']])) {
                ++$count['priorities'][$log['priority']]['count'];
            } else {
                $count['priorities'][$log['priority']] = ['count' => 1, 'name' => $log['priorityName']];
            }
            if ('WARNING' === $log['priorityName']) {
                ++$count['warning_count'];
            }
            if ($this->isSilencedOrDeprecationErrorLog($log)) {
                $exception = $log['context']['exception'];
                if ($exception instanceof SilencedErrorContext) {
                    if (isset($silencedLogs[$h = spl_object_hash($exception)])) {
                        continue;
                    }
                    $silencedLogs[$h] = \true;
                    $count['scream_count'] += $exception->count;
                } else {
                    ++$count['deprecation_count'];
                }
            }
        }
        foreach ($containerDeprecationLogs as $deprecationLog) {
            $count['deprecation_count'] += $deprecationLog['context']['exception']->count;
        }
        ksort($count['priorities']);
        return $count;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\HttpKernel\DataCollector;

use _ContaoManager\Symfony\Component\HttpFoundation\Request;
use _ContaoManager\Symfony\Component\HttpFoundation\Response;
use _ContaoManager\Symfony\Component\HttpKernel\Kernel;
use _ContaoManager\Symfony\Component\HttpKernel\KernelInterface;
use _ContaoManager\Symfony\Component\VarDumper\Caster\ClassStub;
use _ContaoManager\Symfony\Component\VarDumper\Cloner\Data;
/**
 * @author Fabien Potencier <fabien@symfony.com>
 *
 * @final
 */
class ConfigDataCollector extends DataCollector implements LateDataCollectorInterface
{
    private KernelInterface $kernel;
    /**
     * Sets the Kernel associated with this Request.
     */
    public function setKernel(?KernelInterface $kernel = null): void
    {
        if (1 > \func_num_args()) {
            trigger_deprecation('symfony/http-kernel', '6.2', 'Calling "%s()" without any arguments is deprecated, pass null explicitly instead.', __METHOD__);
        }
        $this->kernel = $kernel;
    }
    public function collect(Request $request, Response $response, ?\Throwable $exception = null): void
    {
        $eom = \DateTimeImmutable::createFromFormat('d/m/Y', '01/' . Kernel::END_OF_MAINTENANCE);
        $eol = \DateTimeImmutable::createFromFormat('d/m/Y', '01/' . Kernel::END_OF_LIFE);
        $this->data = ['token' => $response->headers->get('X-Debug-Token'), 'symfony_version' => Kernel::VERSION, 'symfony_minor_version' => \sprintf('%s.%s', Kernel::MAJOR_VERSION, Kernel::MINOR_VERSION), 'symfony_lts' => 4 === Kernel::MINOR_VERSION, 'symfony_state' => $this->determineSymfonyState(), 'symfony_eom' => $eom->format('F Y'), 'symfony_eol' => $eol->format('F Y'), 'env' => isset($this->kernel) ? $this->kernel->getEnvironment() : 'n/a', 'debug' => isset($this->kernel) ? $this->kernel->isDebug() : 'n/a', 'php_version' => \PHP_VERSION, 'php_architecture' => \PHP_INT_SIZE * 8, 'php_intl_locale' => class_exists(\Locale::class, \false) && \Locale::getDefault() ? \Locale::getDefault() : 'n/a', 'php_timezone' => date_default_timezone_get(), 'xdebug_enabled' => \extension_loaded('xdebug'), 'apcu_enabled' => \extension_loaded('apcu') && filter_var(\ini_get('apc.enabled'), \FILTER_VALIDATE_BOOL), 'zend_opcache_enabled' => \extension_loaded('Zend OPcache') && filter_var(\ini_get('opcache.enable'), \FILTER_VALIDATE_BOOL), 'bundles' => [], 'sapi_name' => \PHP_SAPI];
        if (isset($this->kernel)) {
            foreach ($this->kernel->getBundles() as $name => $bundle) {
                $this->data['bundles'][$name] = new ClassStub($bundle::class);
            }
        }
        if (preg_match('~^(\d+(?:\.\d+)*)(.+)?$~', $this->data['php_version'], $matches) && isset($matches[2])) {
            $this->data['php_version'] = $matches[1];
            $this->data['php_version_extra'] = $matches[2];
        }
    }
    public function lateCollect(): void
    {
        $this->data = $this->cloneVar($this->data);
    }
    /**
     * Gets the token.
     */
    public function getToken(): ?string
    {
        return $this->data['token'];
    }
    /**
     * Gets the Symfony version.
     */
    public function getSymfonyVersion(): string
    {
        return $this->data['symfony_version'];
    }
    /**
     * Returns the state of the current Symfony release
     * as one of: unknown, dev, stable, eom, eol.
     */
    public function getSymfonyState(): string
    {
        return $this->data['symfony_state'];
    }
    /**
     * Returns the minor Symfony version used (without patch numbers of extra
     * suffix like "RC", "beta", etc.).
     */
    public function getSymfonyMinorVersion(): string
    {
        return $this->data['symfony_minor_version'];
    }
    public function isSymfonyLts(): bool
    {
        return $this->data['symfony_lts'];
    }
    /**
     * Returns the human readable date when this Symfony version ends its
     * maintenance period.
     */
    public function getSymfonyEom(): string
    {
        return $this->data['symfony_eom'];
    }
    /**
     * Returns the human readable date when this Symfony version reaches its
     * "end of life" and won't receive bugs or security fixes.
     */
    public function getSymfonyEol(): string
    {
        return $this->data['symfony_eol'];
    }
    /**
     * Gets the PHP version.
     */
    public function getPhpVersion(): string
    {
        return $this->data['php_version'];
    }
    /**
     * Gets the PHP version extra part.
     */
    public function getPhpVersionExtra(): ?string
    {
        return $this->data['php_version_extra'] ?? null;
    }
    public function getPhpArchitecture(): int
    {
        return $this->data['php_architecture'];
    }
    public function getPhpIntlLocale(): string
    {
        return $this->data['php_intl_locale'];
    }
    public function getPhpTimezone(): string
    {
        return $this->data['php_timezone'];
    }
    /**
     * Gets the environment.
     */
    public function getEnv(): string
    {
        return $this->data['env'];
    }
    /**
     * Returns true if the debug is enabled.
     *
     * @return bool|string true if debug is enabled, false otherwise or a string if no kernel was set
     */
    public function isDebug(): bool|string
    {
        return $this->data['debug'];
    }
    /**
     * Returns true if the Xdebug is enabled.
     */
    public function hasXdebug(): bool
    {
        return $this->data['xdebug_enabled'];
    }
    /**
     * Returns true if the function xdebug_info is available.
     */
    public function hasXdebugInfo(): bool
    {
        return \function_exists('xdebug_info');
    }
    /**
     * Returns true if APCu is enabled.
     */
    public function hasApcu(): bool
    {
        return $this->data['apcu_enabled'];
    }
    /**
     * Returns true if Zend OPcache is enabled.
     */
    public function hasZendOpcache(): bool
    {
        return $this->data['zend_opcache_enabled'];
    }
    public function getBundles(): array|Data
    {
        return $this->data['bundles'];
    }
    /**
     * Gets the PHP SAPI name.
     */
    public function getSapiName(): string
    {
        return $this->data['sapi_name'];
    }
    public function getName(): string
    {
        return 'config';
    }
    private function determineSymfonyState(): string
    {
        $now = new \DateTimeImmutable();
        $eom = \DateTimeImmutable::createFromFormat('d/m/Y', '01/' . Kernel::END_OF_MAINTENANCE)->modify('last day of this month');
        $eol = \DateTimeImmutable::createFromFormat('d/m/Y', '01/' . Kernel::END_OF_LIFE)->modify('last day of this month');
        if ($now > $eol) {
            $versionState = 'eol';
        } elseif ($now > $eom) {
            $versionState = 'eom';
        } elseif ('' !== Kernel::EXTRA_VERSION) {
            $versionState = 'dev';
        } else {
            $versionState = 'stable';
        }
        return $versionState;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\HttpKernel\DataCollector;

use _ContaoManager\Symfony\Component\EventDispatcher\Debug\TraceableEventDispatcher;
use _ContaoManager\Symfony\Component\HttpFoundation\Request;
use _ContaoManager\Symfony\Component\HttpFoundation\RequestStack;
use _ContaoManager\Symfony\Component\HttpFoundation\Response;
use _ContaoManager\Symfony\Component\VarDumper\Cloner\Data;
use _ContaoManager\Symfony\Contracts\EventDispatcher\EventDispatcherInterface;
use _ContaoManager\Symfony\Contracts\Service\ResetInterface;
/**
 * @author Fabien Potencier <fabien@symfony.com>
 *
 * @see TraceableEventDispatcher
 *
 * @final
 */
class EventDataCollector extends DataCollector implements LateDataCollectorInterface
{
    /** @var iterable<EventDispatcherInterface> */
    private iterable $dispatchers;
    private ?Request $currentRequest = null;
    /**
     * @param iterable<EventDispatcherInterface>|EventDispatcherInterface|null $dispatchers
     */
    public function __construct(iterable|EventDispatcherInterface|null $dispatchers = null, private ?RequestStack $requestStack = null, private string $defaultDispatcher = 'event_dispatcher')
    {
        if ($dispatchers instanceof EventDispatcherInterface) {
            $dispatchers = [$this->defaultDispatcher => $dispatchers];
        }
        $this->dispatchers = $dispatchers ?? [];
    }
    public function collect(Request $request, Response $response, ?\Throwable $exception = null): void
    {
        $this->currentRequest = $this->requestStack && $this->requestStack->getMainRequest() !== $request ? $request : null;
        $this->data = [];
    }
    public function reset(): void
    {
        parent::reset();
        foreach ($this->dispatchers as $dispatcher) {
            if ($dispatcher instanceof ResetInterface) {
                $dispatcher->reset();
            }
        }
    }
    public function lateCollect(): void
    {
        foreach ($this->dispatchers as $name => $dispatcher) {
            if (!$dispatcher instanceof TraceableEventDispatcher) {
                continue;
            }
            $this->setCalledListeners($dispatcher->getCalledListeners($this->currentRequest), $name);
            $this->setNotCalledListeners($dispatcher->getNotCalledListeners($this->currentRequest), $name);
            $this->setOrphanedEvents($dispatcher->getOrphanedEvents($this->currentRequest), $name);
        }
        $this->data = $this->cloneVar($this->data);
    }
    public function getData(): array|Data
    {
        return $this->data;
    }
    /**
     * @see TraceableEventDispatcher
     */
    public function setCalledListeners(array $listeners, ?string $dispatcher = null): void
    {
        $this->data[$dispatcher ?? $this->defaultDispatcher]['called_listeners'] = $listeners;
    }
    /**
     * @see TraceableEventDispatcher
     */
    public function getCalledListeners(?string $dispatcher = null): array|Data
    {
        return $this->data[$dispatcher ?? $this->defaultDispatcher]['called_listeners'] ?? [];
    }
    /**
     * @see TraceableEventDispatcher
     */
    public function setNotCalledListeners(array $listeners, ?string $dispatcher = null): void
    {
        $this->data[$dispatcher ?? $this->defaultDispatcher]['not_called_listeners'] = $listeners;
    }
    /**
     * @see TraceableEventDispatcher
     */
    public function getNotCalledListeners(?string $dispatcher = null): array|Data
    {
        return $this->data[$dispatcher ?? $this->defaultDispatcher]['not_called_listeners'] ?? [];
    }
    /**
     * @param array $events An array of orphaned events
     *
     * @see TraceableEventDispatcher
     */
    public function setOrphanedEvents(array $events, ?string $dispatcher = null): void
    {
        $this->data[$dispatcher ?? $this->defaultDispatcher]['orphaned_events'] = $events;
    }
    /**
     * @see TraceableEventDispatcher
     */
    public function getOrphanedEvents(?string $dispatcher = null): array|Data
    {
        return $this->data[$dispatcher ?? $this->defaultDispatcher]['orphaned_events'] ?? [];
    }
    public function getName(): string
    {
        return 'events';
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\HttpKernel\DataCollector;

use _ContaoManager\Symfony\Component\ErrorHandler\Exception\FlattenException;
use _ContaoManager\Symfony\Component\HttpFoundation\Request;
use _ContaoManager\Symfony\Component\HttpFoundation\Response;
/**
 * @author Fabien Potencier <fabien@symfony.com>
 *
 * @final
 */
class ExceptionDataCollector extends DataCollector
{
    public function collect(Request $request, Response $response, ?\Throwable $exception = null): void
    {
        if (null !== $exception) {
            $this->data = ['exception' => FlattenException::createWithDataRepresentation($exception)];
        }
    }
    public function hasException(): bool
    {
        return isset($this->data['exception']);
    }
    public function getException(): \Exception|FlattenException
    {
        return $this->data['exception'];
    }
    public function getMessage(): string
    {
        return $this->data['exception']->getMessage();
    }
    public function getCode(): int|string
    {
        return $this->data['exception']->getCode();
    }
    public function getStatusCode(): int
    {
        return $this->data['exception']->getStatusCode();
    }
    public function getTrace(): array
    {
        return $this->data['exception']->getTrace();
    }
    public function getName(): string
    {
        return 'exception';
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\HttpKernel\Attribute;

/**
 * Autoconfigures controllers as services by applying
 * the `controller.service_arguments` tag to them.
 *
 * This enables injecting services as method arguments in addition
 * to other conventional dependency injection strategies.
 */
#[\Attribute(\Attribute::TARGET_CLASS | \Attribute::TARGET_FUNCTION)]
class AsController
{
    public function __construct()
    {
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\HttpKernel\Attribute;

/**
 * Service tag to autoconfigure targeted value resolvers.
 */
#[\Attribute(\Attribute::TARGET_CLASS)]
class AsTargetedValueResolver
{
    public function __construct(public readonly ?string $name = null)
    {
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\HttpKernel\Attribute;

/**
 * Describes the default HTTP cache headers on controllers.
 * Headers defined in the Cache attribute are ignored if they are already set
 * by the controller.
 *
 * @see https://symfony.com/doc/current/http_cache.html#making-your-responses-http-cacheable
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
#[\Attribute(\Attribute::TARGET_CLASS | \Attribute::TARGET_METHOD | \Attribute::TARGET_FUNCTION)]
final class Cache
{
    public function __construct(
        /**
         * The expiration date as a valid date for the strtotime() function.
         */
        public ?string $expires = null,
        /**
         * The number of seconds that the response is considered fresh by a private
         * cache like a web browser.
         */
        public int|string|null $maxage = null,
        /**
         * The number of seconds that the response is considered fresh by a public
         * cache like a reverse proxy cache.
         */
        public int|string|null $smaxage = null,
        /**
         * If true, the contents will be stored in a public cache and served to all
         * the next requests.
         */
        public ?bool $public = null,
        /**
         * If true, the response is not served stale by a cache in any circumstance
         * without first revalidating with the origin.
         */
        public bool $mustRevalidate = \false,
        /**
         * Set "Vary" header.
         *
         * Example:
         * ['Accept-Encoding', 'User-Agent']
         *
         * @see https://symfony.com/doc/current/http_cache/cache_vary.html
         *
         * @var string[]
         */
        public array $vary = [],
        /**
         * An expression to compute the Last-Modified HTTP header.
         *
         * The expression is evaluated by the ExpressionLanguage component, it
         * receives all the request attributes and the resolved controller arguments.
         *
         * The result of the expression must be a DateTimeInterface.
         */
        public ?string $lastModified = null,
        /**
         * An expression to compute the ETag HTTP header.
         *
         * The expression is evaluated by the ExpressionLanguage component, it
         * receives all the request attributes and the resolved controller arguments.
         *
         * The result must be a string that will be hashed.
         */
        public ?string $etag = null,
        /**
         * max-stale Cache-Control header
         * It can be expressed in seconds or with a relative time format (1 day, 2 weeks, ...).
         */
        public int|string|null $maxStale = null,
        /**
         * stale-while-revalidate Cache-Control header
         * It can be expressed in seconds or with a relative time format (1 day, 2 weeks, ...).
         */
        public int|string|null $staleWhileRevalidate = null,
        /**
         * stale-if-error Cache-Control header
         * It can be expressed in seconds or with a relative time format (1 day, 2 weeks, ...).
         */
        public int|string|null $staleIfError = null
    )
    {
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\HttpKernel\Attribute;

use _ContaoManager\Symfony\Component\HttpFoundation\Response;
use _ContaoManager\Symfony\Component\HttpKernel\Controller\ArgumentResolver\RequestPayloadValueResolver;
use _ContaoManager\Symfony\Component\HttpKernel\ControllerMetadata\ArgumentMetadata;
use _ContaoManager\Symfony\Component\Validator\Constraints\GroupSequence;
/**
 * Controller parameter tag to map the query string of the request to typed object and validate it.
 *
 * @author Konstantin Myakshin <molodchick@gmail.com>
 */
#[\Attribute(\Attribute::TARGET_PARAMETER)]
class MapQueryString extends ValueResolver
{
    public ArgumentMetadata $metadata;
    public function __construct(public readonly array $serializationContext = [], public readonly string|GroupSequence|array|null $validationGroups = null, string $resolver = RequestPayloadValueResolver::class, public readonly int $validationFailedStatusCode = Response::HTTP_NOT_FOUND)
    {
        parent::__construct($resolver);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\HttpKernel\Attribute;

/**
 * @author Dejan Angelov <angelovdejan@protonmail.com>
 */
#[\Attribute(\Attribute::TARGET_CLASS)]
class WithHttpStatus
{
    /**
     * @param array<string, string> $headers
     */
    public function __construct(public readonly int $statusCode, public readonly array $headers = [])
    {
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\HttpKernel\Attribute;

use _ContaoManager\Symfony\Component\HttpKernel\Controller\ArgumentResolver\DateTimeValueResolver;
/**
 * Controller parameter tag to configure DateTime arguments.
 */
#[\Attribute(\Attribute::TARGET_PARAMETER)]
class MapDateTime extends ValueResolver
{
    public function __construct(public readonly ?string $format = null, bool $disabled = \false, string $resolver = DateTimeValueResolver::class)
    {
        parent::__construct($resolver, $disabled);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\HttpKernel\Attribute;

use _ContaoManager\Symfony\Component\HttpFoundation\Response;
use _ContaoManager\Symfony\Component\HttpKernel\Controller\ArgumentResolver\RequestPayloadValueResolver;
use _ContaoManager\Symfony\Component\HttpKernel\ControllerMetadata\ArgumentMetadata;
use _ContaoManager\Symfony\Component\Validator\Constraints\GroupSequence;
/**
 * Controller parameter tag to map the request content to typed object and validate it.
 *
 * @author Konstantin Myakshin <molodchick@gmail.com>
 */
#[\Attribute(\Attribute::TARGET_PARAMETER)]
class MapRequestPayload extends ValueResolver
{
    public ArgumentMetadata $metadata;
    public function __construct(public readonly array|string|null $acceptFormat = null, public readonly array $serializationContext = [], public readonly string|GroupSequence|array|null $validationGroups = null, string $resolver = RequestPayloadValueResolver::class, public readonly int $validationFailedStatusCode = Response::HTTP_UNPROCESSABLE_ENTITY)
    {
        parent::__construct($resolver);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\HttpKernel\Attribute;

use _ContaoManager\Psr\Log\LogLevel;
/**
 * @author Dejan Angelov <angelovdejan@protonmail.com>
 */
#[\Attribute(\Attribute::TARGET_CLASS)]
final class WithLogLevel
{
    /**
     * @param LogLevel::* $level
     */
    public function __construct(public readonly string $level)
    {
        if (!\defined('Psr\Log\LogLevel::' . strtoupper($this->level))) {
            throw new \InvalidArgumentException(\sprintf('Invalid log level "%s".', $this->level));
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\HttpKernel\Attribute;

use _ContaoManager\Symfony\Component\HttpKernel\Controller\ValueResolverInterface;
#[\Attribute(\Attribute::TARGET_PARAMETER | \Attribute::IS_REPEATABLE)]
class ValueResolver
{
    /**
     * @param class-string<ValueResolverInterface>|string $resolver
     */
    public function __construct(public string $resolver, public bool $disabled = \false)
    {
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\HttpKernel\Attribute;

use _ContaoManager\Symfony\Component\HttpKernel\Controller\ArgumentResolver\QueryParameterValueResolver;
/**
 * Can be used to pass a query parameter to a controller argument.
 *
 * @author Ruud Kamphuis <ruud@ticketswap.com>
 */
#[\Attribute(\Attribute::TARGET_PARAMETER)]
final class MapQueryParameter extends ValueResolver
{
    /**
     * @see https://php.net/manual/filter.constants for filter, flags and options
     *
     * @param string|null $name The name of the query parameter. If null, the name of the argument in the controller will be used.
     */
    public function __construct(public ?string $name = null, public ?int $filter = null, public int $flags = 0, public array $options = [], string $resolver = QueryParameterValueResolver::class)
    {
        parent::__construct($resolver);
    }
}
Copyright (c) 2004-present Fabien Potencier

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is furnished
to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\HttpKernel\ControllerMetadata;

/**
 * Builds method argument data.
 *
 * @author Iltar van der Berg <kjarli@gmail.com>
 */
interface ArgumentMetadataFactoryInterface
{
    /**
     * @param \ReflectionFunctionAbstract|null $reflector
     *
     * @return ArgumentMetadata[]
     */
    public function createArgumentMetadata(string|object|array $controller): array;
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\HttpKernel\ControllerMetadata;

/**
 * Responsible for storing metadata of an argument.
 *
 * @author Iltar van der Berg <kjarli@gmail.com>
 */
class ArgumentMetadata
{
    public const IS_INSTANCEOF = 2;
    private string $name;
    private ?string $type;
    private bool $isVariadic;
    private bool $hasDefaultValue;
    private mixed $defaultValue;
    private bool $isNullable;
    private array $attributes;
    /**
     * @param object[] $attributes
     */
    public function __construct(string $name, ?string $type, bool $isVariadic, bool $hasDefaultValue, mixed $defaultValue, bool $isNullable = \false, array $attributes = [])
    {
        $this->name = $name;
        $this->type = $type;
        $this->isVariadic = $isVariadic;
        $this->hasDefaultValue = $hasDefaultValue;
        $this->defaultValue = $defaultValue;
        $this->isNullable = $isNullable || null === $type || $hasDefaultValue && null === $defaultValue;
        $this->attributes = $attributes;
    }
    /**
     * Returns the name as given in PHP, $foo would yield "foo".
     */
    public function getName(): string
    {
        return $this->name;
    }
    /**
     * Returns the type of the argument.
     *
     * The type is the PHP class in 5.5+ and additionally the basic type in PHP 7.0+.
     */
    public function getType(): ?string
    {
        return $this->type;
    }
    /**
     * Returns whether the argument is defined as "...$variadic".
     */
    public function isVariadic(): bool
    {
        return $this->isVariadic;
    }
    /**
     * Returns whether the argument has a default value.
     *
     * Implies whether an argument is optional.
     */
    public function hasDefaultValue(): bool
    {
        return $this->hasDefaultValue;
    }
    /**
     * Returns whether the argument accepts null values.
     */
    public function isNullable(): bool
    {
        return $this->isNullable;
    }
    /**
     * Returns the default value of the argument.
     *
     * @throws \LogicException if no default value is present; {@see self::hasDefaultValue()}
     */
    public function getDefaultValue(): mixed
    {
        if (!$this->hasDefaultValue) {
            throw new \LogicException(\sprintf('Argument $%s does not have a default value. Use "%s::hasDefaultValue()" to avoid this exception.', $this->name, __CLASS__));
        }
        return $this->defaultValue;
    }
    /**
     * @param class-string          $name
     * @param self::IS_INSTANCEOF|0 $flags
     *
     * @return array<object>
     */
    public function getAttributes(?string $name = null, int $flags = 0): array
    {
        if (!$name) {
            return $this->attributes;
        }
        return $this->getAttributesOfType($name, $flags);
    }
    /**
     * @template T of object
     *
     * @param class-string<T>       $name
     * @param self::IS_INSTANCEOF|0 $flags
     *
     * @return array<T>
     */
    public function getAttributesOfType(string $name, int $flags = 0): array
    {
        $attributes = [];
        if ($flags & self::IS_INSTANCEOF) {
            foreach ($this->attributes as $attribute) {
                if ($attribute instanceof $name) {
                    $attributes[] = $attribute;
                }
            }
        } else {
            foreach ($this->attributes as $attribute) {
                if ($attribute::class === $name) {
                    $attributes[] = $attribute;
                }
            }
        }
        return $attributes;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\HttpKernel\ControllerMetadata;

/**
 * Builds {@see ArgumentMetadata} objects based on the given Controller.
 *
 * @author Iltar van der Berg <kjarli@gmail.com>
 */
final class ArgumentMetadataFactory implements ArgumentMetadataFactoryInterface
{
    public function createArgumentMetadata(string|object|array $controller, ?\ReflectionFunctionAbstract $reflector = null): array
    {
        $arguments = [];
        $reflector ??= new \ReflectionFunction($controller(...));
        foreach ($reflector->getParameters() as $param) {
            $attributes = [];
            foreach ($param->getAttributes() as $reflectionAttribute) {
                if (class_exists($reflectionAttribute->getName())) {
                    $attributes[] = $reflectionAttribute->newInstance();
                }
            }
            $arguments[] = new ArgumentMetadata($param->getName(), $this->getType($param), $param->isVariadic(), $param->isDefaultValueAvailable(), $param->isDefaultValueAvailable() ? $param->getDefaultValue() : null, $param->allowsNull(), $attributes);
        }
        return $arguments;
    }
    /**
     * Returns an associated type to the given parameter if available.
     */
    private function getType(\ReflectionParameter $parameter): ?string
    {
        if (!$type = $parameter->getType()) {
            return null;
        }
        $name = $type instanceof \ReflectionNamedType ? $type->getName() : (string) $type;
        return match (strtolower($name)) {
            'self' => $parameter->getDeclaringClass()?->name,
            'parent' => get_parent_class($parameter->getDeclaringClass()?->name ?? '') ?: null,
            default => $name,
        };
    }
}
CHANGELOG
=========

6.4
---

 * Support backed enums in #[MapQueryParameter]
 * `BundleInterface` no longer extends `ContainerAwareInterface`
 * Add optional `$className` parameter to `ControllerEvent::getAttributes()`
 * Add native return types to `TraceableEventDispatcher` and to `MergeExtensionConfigurationPass`
 * Add argument `$validationFailedStatusCode` to `#[MapQueryString]` and `#[MapRequestPayload]`
 * Add argument `$debug` to `Logger`
 * Add class `DebugLoggerConfigurator`
 * Add parameters `kernel.runtime_mode` and `kernel.runtime_mode.*`, all set from env var `APP_RUNTIME_MODE`
 * Deprecate `Kernel::stripComments()`
 * Support the `!` character at the beginning of a string as a negation operator in the url filter of the profiler
 * Deprecate `UriSigner`, use `UriSigner` from the HttpFoundation component instead
 * Deprecate `FileLinkFormatter`, use `FileLinkFormatter` from the ErrorHandler component instead
 * Add argument `$buildDir` to `WarmableInterface`
 * Add argument `$filter` to `Profiler::find()` and `FileProfilerStorage::find()`
 * Add `ControllerResolver::allowControllers()` to define which callables are legit controllers when the `_check_controller_is_allowed` request attribute is set

6.3
---

 * Deprecate parameters `container.dumper.inline_factories` and `container.dumper.inline_class_loader`, use `.container.dumper.inline_factories` and `.container.dumper.inline_class_loader` instead
 * `FileProfilerStorage` removes profiles automatically after two days
 * Add `#[WithHttpStatus]` for defining status codes for exceptions
 * Use an instance of `Psr\Clock\ClockInterface` to generate the current date time in `DateTimeValueResolver`
 * Add `#[WithLogLevel]` for defining log levels for exceptions
 * Add `skip_response_headers` to the `HttpCache` options
 * Introduce targeted value resolvers with `#[ValueResolver]` and `#[AsTargetedValueResolver]`
 * Add `#[MapRequestPayload]` to map and validate request payload from `Request::getContent()` or `Request::$request->all()` to typed objects
 * Add `#[MapQueryString]` to map and validate request query string from `Request::$query->all()` to typed objects
 * Add `#[MapQueryParameter]` to map and validate individual query parameters to controller arguments
 * Collect data from every event dispatcher

6.2
---

 * Add constructor argument `bool $handleAllThrowable` to `HttpKernel`
 * Add `ControllerEvent::getAttributes()` to handle attributes on controllers
 * Add `#[Cache]` to describe the default HTTP cache headers on controllers
 * Add `absolute_uri` option to surrogate fragment renderers
 * Add `ValueResolverInterface` and deprecate `ArgumentValueResolverInterface`
 * Add argument `$reflector` to `ArgumentResolverInterface` and `ArgumentMetadataFactoryInterface`
 * Deprecate calling `ConfigDataCollector::setKernel()`, `RouterListener::setCurrentRequest()` without arguments

6.1
---

 * Add `BackedEnumValueResolver` to resolve backed enum cases from request attributes in controller arguments
 * Add `DateTimeValueResolver` to resolve request attributes into DateTime objects in controller arguments
 * Deprecate StreamedResponseListener, it's not needed anymore
 * Add `Profiler::isEnabled()` so collaborating collector services may elect to omit themselves
 * Add the `UidValueResolver` argument value resolver
 * Add `AbstractBundle` class for DI configuration/definition on a single file
 * Update the path of a bundle placed in the `src/` directory to the parent directory when `AbstractBundle` is used

6.0
---

 * Remove `ArgumentInterface`
 * Remove `ArgumentMetadata::getAttribute()`, use `getAttributes()` instead
 * Remove support for returning a `ContainerBuilder` from `KernelInterface::registerContainerConfiguration()`
 * Remove `KernelEvent::isMasterRequest()`, use `isMainRequest()` instead
 * Remove support for `service:action` syntax to reference controllers, use `serviceOrFqcn::method` instead

5.4
---

 * Add the ability to enable the profiler using a request query parameter, body parameter or attribute
 * Deprecate `AbstractTestSessionListener` and `TestSessionListener`, use `AbstractSessionListener` and `SessionListener` instead
 * Deprecate the `fileLinkFormat` parameter of `DebugHandlersListener`
 * Add support for configuring log level, and status code by exception class
 * Allow ignoring "kernel.reset" methods that don't exist with "on_invalid" attribute

5.3
---

 * Deprecate `ArgumentInterface`
 * Add `ArgumentMetadata::getAttributes()`
 * Deprecate `ArgumentMetadata::getAttribute()`, use `getAttributes()` instead
 * Mark the class `Symfony\Component\HttpKernel\EventListener\DebugHandlersListener` as internal
 * Deprecate returning a `ContainerBuilder` from `KernelInterface::registerContainerConfiguration()`
 * Deprecate `HttpKernelInterface::MASTER_REQUEST` and add `HttpKernelInterface::MAIN_REQUEST` as replacement
 * Deprecate `KernelEvent::isMasterRequest()` and add `isMainRequest()` as replacement
 * Add `#[AsController]` attribute for declaring standalone controllers on PHP 8
 * Add `FragmentUriGeneratorInterface` and `FragmentUriGenerator` to generate the URI of a fragment

5.2.0
-----

 * added session usage
 * made the public `http_cache` service handle requests when available
 * allowed enabling trusted hosts and proxies using new `kernel.trusted_hosts`,
   `kernel.trusted_proxies` and `kernel.trusted_headers` parameters
 * content of request parameter `_password` is now also hidden
   in the request profiler raw content section
 * Allowed adding attributes on controller arguments that will be passed to argument resolvers.
 * kernels implementing the `ExtensionInterface` will now be auto-registered to the container
 * added parameter `kernel.runtime_environment`, defined as `%env(default:kernel.environment:APP_RUNTIME_ENV)%`
 * do not set a default `Accept` HTTP header when using `HttpKernelBrowser`

5.1.0
-----

 * allowed to use a specific logger channel for deprecations
 * made `WarmableInterface::warmUp()` return a list of classes or files to preload on PHP 7.4+;
   not returning an array is deprecated
 * made kernels implementing `WarmableInterface` be part of the cache warmup stage
 * deprecated support for `service:action` syntax to reference controllers, use `serviceOrFqcn::method` instead
 * allowed using public aliases to reference controllers
 * added session usage reporting when the `_stateless` attribute of the request is set to `true`
 * added `AbstractSessionListener::onSessionUsage()` to report when the session is used while a request is stateless

5.0.0
-----

 * removed support for getting the container from a non-booted kernel
 * removed the first and second constructor argument of `ConfigDataCollector`
 * removed `ConfigDataCollector::getApplicationName()`
 * removed `ConfigDataCollector::getApplicationVersion()`
 * removed support for `Symfony\Component\Templating\EngineInterface` in `HIncludeFragmentRenderer`, use a `Twig\Environment` only
 * removed `TranslatorListener` in favor of `LocaleAwareListener`
 * removed `getRootDir()` and `getName()` from `Kernel` and `KernelInterface`
 * removed `FilterControllerArgumentsEvent`, use `ControllerArgumentsEvent` instead
 * removed `FilterControllerEvent`, use `ControllerEvent` instead
 * removed `FilterResponseEvent`, use `ResponseEvent` instead
 * removed `GetResponseEvent`, use `RequestEvent` instead
 * removed `GetResponseForControllerResultEvent`, use `ViewEvent` instead
 * removed `GetResponseForExceptionEvent`, use `ExceptionEvent` instead
 * removed `PostResponseEvent`, use `TerminateEvent` instead
 * removed `SaveSessionListener` in favor of `AbstractSessionListener`
 * removed `Client`, use `HttpKernelBrowser` instead
 * added method `getProjectDir()` to `KernelInterface`
 * removed methods `serialize` and `unserialize` from `DataCollector`, store the serialized state in the data property instead
 * made `ProfilerStorageInterface` internal
 * removed the second and third argument of `KernelInterface::locateResource`
 * removed the second and third argument of `FileLocator::__construct`
 * removed loading resources from `%kernel.root_dir%/Resources` and `%kernel.root_dir%` as
   fallback directories.
 * removed class `ExceptionListener`, use `ErrorListener` instead

4.4.0
-----

 * The `DebugHandlersListener` class has been marked as `final`
 * Added new Bundle directory convention consistent with standard skeletons
 * Deprecated the second and third argument of `KernelInterface::locateResource`
 * Deprecated the second and third argument of `FileLocator::__construct`
 * Deprecated loading resources from `%kernel.root_dir%/Resources` and `%kernel.root_dir%` as
   fallback directories. Resources like service definitions are usually loaded relative to the
   current directory or with a glob pattern. The fallback directories have never been advocated
   so you likely do not use those in any app based on the SF Standard or Flex edition.
 * Marked all dispatched event classes as `@final`
 * Added `ErrorController` to enable the preview and error rendering mechanism
 * Getting the container from a non-booted kernel is deprecated.
 * Marked the `AjaxDataCollector`, `ConfigDataCollector`, `EventDataCollector`,
   `ExceptionDataCollector`, `LoggerDataCollector`, `MemoryDataCollector`,
   `RequestDataCollector` and `TimeDataCollector` classes as `@final`.
 * Marked the `RouterDataCollector::collect()` method as `@final`.
 * The `DataCollectorInterface::collect()` and `Profiler::collect()` methods third parameter signature
   will be `\Throwable $exception = null` instead of `\Exception $exception = null` in Symfony 5.0.
 * Deprecated methods `ExceptionEvent::get/setException()`, use `get/setThrowable()` instead
 * Deprecated class `ExceptionListener`, use `ErrorListener` instead

4.3.0
-----

 * renamed `Client` to `HttpKernelBrowser`
 * `KernelInterface` doesn't extend `Serializable` anymore
 * deprecated the `Kernel::serialize()` and `unserialize()` methods
 * increased the priority of `Symfony\Component\HttpKernel\EventListener\AddRequestFormatsListener`
 * made `Symfony\Component\HttpKernel\EventListener\LocaleListener` set the default locale early
 * deprecated `TranslatorListener` in favor of `LocaleAwareListener`
 * added the registration of all `LocaleAwareInterface` implementations into the `LocaleAwareListener`
 * made `FileLinkFormatter` final and not implement `Serializable` anymore
 * the base `DataCollector` doesn't implement `Serializable` anymore, you should
   store all the serialized state in the data property instead
 * `DumpDataCollector` has been marked as `final`
 * added an event listener to prevent search engines from indexing applications in debug mode.
 * renamed `FilterControllerArgumentsEvent` to `ControllerArgumentsEvent`
 * renamed `FilterControllerEvent` to `ControllerEvent`
 * renamed `FilterResponseEvent` to `ResponseEvent`
 * renamed `GetResponseEvent` to `RequestEvent`
 * renamed `GetResponseForControllerResultEvent` to `ViewEvent`
 * renamed `GetResponseForExceptionEvent` to `ExceptionEvent`
 * renamed `PostResponseEvent` to `TerminateEvent`
 * added `HttpClientKernel` for handling requests with an `HttpClientInterface` instance
 * added `trace_header` and `trace_level` configuration options to `HttpCache`

4.2.0
-----

 * deprecated `KernelInterface::getRootDir()` and the `kernel.root_dir` parameter
 * deprecated `KernelInterface::getName()` and the `kernel.name` parameter
 * deprecated the first and second constructor argument of `ConfigDataCollector`
 * deprecated `ConfigDataCollector::getApplicationName()`
 * deprecated `ConfigDataCollector::getApplicationVersion()`

4.1.0
-----

 * added orphaned events support to `EventDataCollector`
 * `ExceptionListener` now logs exceptions at priority `0` (previously logged at `-128`)
 * Added support for using `service::method` to reference controllers, making it consistent with other cases. It is recommended over the `service:action` syntax with a single colon, which will be deprecated in the future.
 * Added the ability to profile individual argument value resolvers via the
   `Symfony\Component\HttpKernel\Controller\ArgumentResolver\TraceableValueResolver`

4.0.0
-----

 * removed the `DataCollector::varToString()` method, use `DataCollector::cloneVar()`
   instead
 * using the `DataCollector::cloneVar()` method requires the VarDumper component
 * removed the `ValueExporter` class
 * removed `ControllerResolverInterface::getArguments()`
 * removed `TraceableControllerResolver::getArguments()`
 * removed `ControllerResolver::getArguments()` and the ability to resolve arguments
 * removed the `argument_resolver` service dependency from the `debug.controller_resolver`
 * removed `LazyLoadingFragmentHandler::addRendererService()`
 * removed `Psr6CacheClearer::addPool()`
 * removed `Extension::addClassesToCompile()` and `Extension::getClassesToCompile()`
 * removed `Kernel::loadClassCache()`, `Kernel::doLoadClassCache()`, `Kernel::setClassCache()`,
   and `Kernel::getEnvParameters()`
 * support for the `X-Status-Code` when handling exceptions in the `HttpKernel`
   has been dropped, use the `HttpKernel::allowCustomResponseCode()` method
   instead
 * removed convention-based commands registration
 * removed the `ChainCacheClearer::add()` method
 * removed the `CacheaWarmerAggregate::add()` and `setWarmers()` methods
 * made `CacheWarmerAggregate` and `ChainCacheClearer` classes final

3.4.0
-----

 * added a minimalist PSR-3 `Logger` class that writes in `stderr`
 * made kernels implementing `CompilerPassInterface` able to process the container
 * deprecated bundle inheritance
 * added `RebootableInterface` and implemented it in `Kernel`
 * deprecated commands auto registration
 * deprecated `EnvParametersResource`
 * added `Symfony\Component\HttpKernel\Client::catchExceptions()`
 * deprecated the `ChainCacheClearer::add()` method
 * deprecated the `CacheaWarmerAggregate::add()` and `setWarmers()` methods
 * made `CacheWarmerAggregate` and `ChainCacheClearer` classes final
 * added the possibility to reset the profiler to its initial state
 * deprecated data collectors without a `reset()` method
 * deprecated implementing `DebugLoggerInterface` without a `clear()` method

3.3.0
-----

 * added `kernel.project_dir` and `Kernel::getProjectDir()`
 * deprecated `kernel.root_dir` and `Kernel::getRootDir()`
 * deprecated `Kernel::getEnvParameters()`
 * deprecated the special `SYMFONY__` environment variables
 * added the possibility to change the query string parameter used by `UriSigner`
 * deprecated `LazyLoadingFragmentHandler::addRendererService()`
 * deprecated `Extension::addClassesToCompile()` and `Extension::getClassesToCompile()`
 * deprecated `Psr6CacheClearer::addPool()`

3.2.0
-----

 * deprecated `DataCollector::varToString()`, use `cloneVar()` instead
 * changed surrogate capability name in `AbstractSurrogate::addSurrogateCapability` to 'symfony'
 * Added `ControllerArgumentValueResolverPass`

3.1.0
-----
 * deprecated passing objects as URI attributes to the ESI and SSI renderers
 * deprecated `ControllerResolver::getArguments()`
 * added `Symfony\Component\HttpKernel\Controller\ArgumentResolverInterface`
 * added `Symfony\Component\HttpKernel\Controller\ArgumentResolverInterface` as argument to `HttpKernel`
 * added `Symfony\Component\HttpKernel\Controller\ArgumentResolver`
 * added `Symfony\Component\HttpKernel\DataCollector\RequestDataCollector::getMethod()`
 * added `Symfony\Component\HttpKernel\DataCollector\RequestDataCollector::getRedirect()`
 * added the `kernel.controller_arguments` event, triggered after controller arguments have been resolved

3.0.0
-----

 * removed `Symfony\Component\HttpKernel\Kernel::init()`
 * removed `Symfony\Component\HttpKernel\Kernel::isClassInActiveBundle()` and `Symfony\Component\HttpKernel\KernelInterface::isClassInActiveBundle()`
 * removed `Symfony\Component\HttpKernel\Debug\TraceableEventDispatcher::setProfiler()`
 * removed `Symfony\Component\HttpKernel\EventListener\FragmentListener::getLocalIpAddresses()`
 * removed `Symfony\Component\HttpKernel\EventListener\LocaleListener::setRequest()`
 * removed `Symfony\Component\HttpKernel\EventListener\RouterListener::setRequest()`
 * removed `Symfony\Component\HttpKernel\EventListener\ProfilerListener::onKernelRequest()`
 * removed `Symfony\Component\HttpKernel\Fragment\FragmentHandler::setRequest()`
 * removed `Symfony\Component\HttpKernel\HttpCache\Esi::hasSurrogateEsiCapability()`
 * removed `Symfony\Component\HttpKernel\HttpCache\Esi::addSurrogateEsiCapability()`
 * removed `Symfony\Component\HttpKernel\HttpCache\Esi::needsEsiParsing()`
 * removed `Symfony\Component\HttpKernel\HttpCache\HttpCache::getEsi()`
 * removed `Symfony\Component\HttpKernel\DependencyInjection\ContainerAwareHttpKernel`
 * removed `Symfony\Component\HttpKernel\DependencyInjection\RegisterListenersPass`
 * removed `Symfony\Component\HttpKernel\EventListener\ErrorsLoggerListener`
 * removed `Symfony\Component\HttpKernel\EventListener\EsiListener`
 * removed `Symfony\Component\HttpKernel\HttpCache\EsiResponseCacheStrategy`
 * removed `Symfony\Component\HttpKernel\HttpCache\EsiResponseCacheStrategyInterface`
 * removed `Symfony\Component\HttpKernel\Log\LoggerInterface`
 * removed `Symfony\Component\HttpKernel\Log\NullLogger`
 * removed `Symfony\Component\HttpKernel\Profiler::import()`
 * removed `Symfony\Component\HttpKernel\Profiler::export()`

2.8.0
-----

 * deprecated `Profiler::import` and `Profiler::export`

2.7.0
-----

 * added the HTTP status code to profiles

2.6.0
-----

 * deprecated `Symfony\Component\HttpKernel\EventListener\ErrorsLoggerListener`, use `Symfony\Component\HttpKernel\EventListener\DebugHandlersListener` instead
 * deprecated unused method `Symfony\Component\HttpKernel\Kernel::isClassInActiveBundle` and `Symfony\Component\HttpKernel\KernelInterface::isClassInActiveBundle`

2.5.0
-----

 * deprecated `Symfony\Component\HttpKernel\DependencyInjection\RegisterListenersPass`, use `Symfony\Component\EventDispatcher\DependencyInjection\RegisterListenersPass` instead

2.4.0
-----

 * added event listeners for the session
 * added the KernelEvents::FINISH_REQUEST event

2.3.0
-----

 * [BC BREAK] renamed `Symfony\Component\HttpKernel\EventListener\DeprecationLoggerListener` to `Symfony\Component\HttpKernel\EventListener\ErrorsLoggerListener` and changed its constructor
 * deprecated `Symfony\Component\HttpKernel\Debug\ErrorHandler`, `Symfony\Component\HttpKernel\Debug\ExceptionHandler`,
   `Symfony\Component\HttpKernel\Exception\FatalErrorException` and `Symfony\Component\HttpKernel\Exception\FlattenException`
 * deprecated `Symfony\Component\HttpKernel\Kernel::init()`
 * added the possibility to specify an id an extra attributes to hinclude tags
 * added the collect of data if a controller is a Closure in the Request collector
 * pass exceptions from the ExceptionListener to the logger using the logging context to allow for more
   detailed messages

2.2.0
-----

 * [BC BREAK] the path info for sub-request is now always _fragment (or whatever you configured instead of the default)
 * added Symfony\Component\HttpKernel\EventListener\FragmentListener
 * added Symfony\Component\HttpKernel\UriSigner
 * added Symfony\Component\HttpKernel\FragmentRenderer and rendering strategies (in Symfony\Component\HttpKernel\Fragment\FragmentRendererInterface)
 * added Symfony\Component\HttpKernel\DependencyInjection\ContainerAwareHttpKernel
 * added ControllerReference to create reference of Controllers (used in the FragmentRenderer class)
 * [BC BREAK] renamed TimeDataCollector::getTotalTime() to
   TimeDataCollector::getDuration()
 * updated the MemoryDataCollector to include the memory used in the
   kernel.terminate event listeners
 * moved the Stopwatch classes to a new component
 * added TraceableControllerResolver
 * added TraceableEventDispatcher (removed ContainerAwareTraceableEventDispatcher)
 * added support for WinCache opcode cache in ConfigDataCollector

2.1.0
-----

 * [BC BREAK] the charset is now configured via the Kernel::getCharset() method
 * [BC BREAK] the current locale for the user is not stored anymore in the session
 * added the HTTP method to the profiler storage
 * updated all listeners to implement EventSubscriberInterface
 * added TimeDataCollector
 * added ContainerAwareTraceableEventDispatcher
 * moved TraceableEventDispatcherInterface to the EventDispatcher component
 * added RouterListener, LocaleListener, and StreamedResponseListener
 * added CacheClearerInterface (and ChainCacheClearer)
 * added a kernel.terminate event (via TerminableInterface and PostResponseEvent)
 * added a Stopwatch class
 * added WarmableInterface
 * improved extensibility between bundles
 * added profiler storages for Memcache(d), File-based, MongoDB, Redis
 * moved Filesystem class to its own component
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\HttpKernel\Config;

use _ContaoManager\Symfony\Component\Config\FileLocator as BaseFileLocator;
use _ContaoManager\Symfony\Component\HttpKernel\KernelInterface;
/**
 * FileLocator uses the KernelInterface to locate resources in bundles.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class FileLocator extends BaseFileLocator
{
    private KernelInterface $kernel;
    public function __construct(KernelInterface $kernel)
    {
        $this->kernel = $kernel;
        parent::__construct();
    }
    public function locate(string $file, ?string $currentPath = null, bool $first = \true): string|array
    {
        if (isset($file[0]) && '@' === $file[0]) {
            $resource = $this->kernel->locateResource($file);
            return $first ? $resource : [$resource];
        }
        return parent::locate($file, $currentPath, $first);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\HttpKernel;

use _ContaoManager\Symfony\Component\HttpClient\HttpClient;
use _ContaoManager\Symfony\Component\HttpFoundation\Request;
use _ContaoManager\Symfony\Component\HttpFoundation\Response;
use _ContaoManager\Symfony\Component\HttpFoundation\ResponseHeaderBag;
use _ContaoManager\Symfony\Component\Mime\Part\AbstractPart;
use _ContaoManager\Symfony\Component\Mime\Part\DataPart;
use _ContaoManager\Symfony\Component\Mime\Part\Multipart\FormDataPart;
use _ContaoManager\Symfony\Component\Mime\Part\TextPart;
use _ContaoManager\Symfony\Contracts\HttpClient\HttpClientInterface;
// Help opcache.preload discover always-needed symbols
class_exists(ResponseHeaderBag::class);
/**
 * An implementation of a Symfony HTTP kernel using a "real" HTTP client.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
final class HttpClientKernel implements HttpKernelInterface
{
    private HttpClientInterface $client;
    public function __construct(?HttpClientInterface $client = null)
    {
        if (null === $client && !class_exists(HttpClient::class)) {
            throw new \LogicException(\sprintf('You cannot use "%s" as the HttpClient component is not installed. Try running "composer require symfony/http-client".', __CLASS__));
        }
        $this->client = $client ?? HttpClient::create();
    }
    public function handle(Request $request, int $type = HttpKernelInterface::MAIN_REQUEST, bool $catch = \true): Response
    {
        $headers = $this->getHeaders($request);
        $body = '';
        if (null !== $part = $this->getBody($request)) {
            $headers = array_merge($headers, $part->getPreparedHeaders()->toArray());
            $body = $part->bodyToIterable();
        }
        $response = $this->client->request($request->getMethod(), $request->getUri(), ['headers' => $headers, 'body' => $body] + $request->attributes->get('http_client_options', []));
        $response = new Response($response->getContent(!$catch), $response->getStatusCode(), $response->getHeaders(!$catch));
        $response->headers->remove('X-Body-File');
        $response->headers->remove('X-Body-Eval');
        $response->headers->remove('X-Content-Digest');
        $response->headers = new class($response->headers->all()) extends ResponseHeaderBag
        {
            protected function computeCacheControlValue(): string
            {
                return $this->getCacheControlHeader();
                // preserve the original value
            }
        };
        return $response;
    }
    private function getBody(Request $request): ?AbstractPart
    {
        if (\in_array($request->getMethod(), ['GET', 'HEAD'])) {
            return null;
        }
        if (!class_exists(AbstractPart::class)) {
            throw new \LogicException('You cannot pass non-empty bodies as the Mime component is not installed. Try running "composer require symfony/mime".');
        }
        if ($content = $request->getContent()) {
            return new TextPart($content, 'utf-8', 'plain', '8bit');
        }
        $fields = $request->request->all();
        foreach ($request->files->all() as $name => $file) {
            $fields[$name] = DataPart::fromPath($file->getPathname(), $file->getClientOriginalName(), $file->getClientMimeType());
        }
        return new FormDataPart($fields);
    }
    private function getHeaders(Request $request): array
    {
        $headers = [];
        foreach ($request->headers as $key => $value) {
            $headers[$key] = $value;
        }
        $cookies = [];
        foreach ($request->cookies->all() as $name => $value) {
            $cookies[] = $name . '=' . $value;
        }
        if ($cookies) {
            $headers['cookie'] = implode('; ', $cookies);
        }
        return $headers;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\HttpKernel;

use _ContaoManager\Symfony\Component\HttpFoundation\Request;
use _ContaoManager\Symfony\Component\HttpFoundation\Response;
/**
 * Terminable extends the Kernel request/response cycle with dispatching a post
 * response event after sending the response and before shutting down the kernel.
 *
 * @author Jordi Boggiano <j.boggiano@seld.be>
 * @author Pierre Minnieur <pierre.minnieur@sensiolabs.de>
 */
interface TerminableInterface
{
    /**
     * Terminates a request/response cycle.
     *
     * Should be called after sending the response and before shutting down the kernel.
     *
     * @return void
     */
    public function terminate(Request $request, Response $response);
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\HttpKernel\CacheClearer;

/**
 * CacheClearerInterface.
 *
 * @author Dustin Dobervich <ddobervich@gmail.com>
 */
interface CacheClearerInterface
{
    /**
     * Clears any caches necessary.
     *
     * @return void
     */
    public function clear(string $cacheDir);
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\HttpKernel\CacheClearer;

/**
 * ChainCacheClearer.
 *
 * @author Dustin Dobervich <ddobervich@gmail.com>
 *
 * @final
 */
class ChainCacheClearer implements CacheClearerInterface
{
    private iterable $clearers;
    /**
     * @param iterable<mixed, CacheClearerInterface> $clearers
     */
    public function __construct(iterable $clearers = [])
    {
        $this->clearers = $clearers;
    }
    public function clear(string $cacheDir): void
    {
        foreach ($this->clearers as $clearer) {
            $clearer->clear($cacheDir);
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\HttpKernel\CacheClearer;

use _ContaoManager\Psr\Cache\CacheItemPoolInterface;
/**
 * @author Nicolas Grekas <p@tchwork.com>
 */
class Psr6CacheClearer implements CacheClearerInterface
{
    private array $pools = [];
    /**
     * @param array<string, CacheItemPoolInterface> $pools
     */
    public function __construct(array $pools = [])
    {
        $this->pools = $pools;
    }
    public function hasPool(string $name): bool
    {
        return isset($this->pools[$name]);
    }
    /**
     * @throws \InvalidArgumentException If the cache pool with the given name does not exist
     */
    public function getPool(string $name): CacheItemPoolInterface
    {
        if (!$this->hasPool($name)) {
            throw new \InvalidArgumentException(\sprintf('Cache pool not found: "%s".', $name));
        }
        return $this->pools[$name];
    }
    /**
     * @throws \InvalidArgumentException If the cache pool with the given name does not exist
     */
    public function clearPool(string $name): bool
    {
        if (!isset($this->pools[$name])) {
            throw new \InvalidArgumentException(\sprintf('Cache pool not found: "%s".', $name));
        }
        return $this->pools[$name]->clear();
    }
    /**
     * @return void
     */
    public function clear(string $cacheDir)
    {
        foreach ($this->pools as $pool) {
            $pool->clear();
        }
    }
}
<!DOCTYPE html>
<html dir="ltr" lang="en">
<head>
    <meta charset="UTF-8" />
    <meta name="robots" content="noindex,nofollow,noarchive,nosnippet,noodp,notranslate,noimageindex" />
    <title>Welcome to Symfony!</title>
    <link rel="icon" href="data:image/svg+xml,<svg xmlns=%22http://www.w3.org/2000/svg%22 viewBox=%220 0 128 128%22><text y=%221.2em%22 font-size=%2296%22>👋</text></svg>" />
    <style>
        <?php 
namespace _ContaoManager;

$hue = \random_int(0, 360);
?>
        <?php 
$darkColor = static fn(float $alpha = 1) => "hsla({$hue}, 20%, 45%, {$alpha})";
?>
        <?php 
$lightColor = static fn(float $alpha = 1) => "hsla({$hue}, 20%, 95%, {$alpha})";
?>
        body { background: <?php 
echo $lightColor();
?>; color: <?php 
echo $darkColor();
?>; display: flex; font: 16px/1.5 sans-serif; justify-content: center; margin: 0; }
        h1, h2 { line-height: 1.2; margin: 0 0 .5em; }
        h1 { font-size: 36px; }
        h2 { font-size: 21px; margin-bottom: 1em; }
        a { color: <?php 
echo $darkColor(0.75);
?> }
        a:hover { text-decoration: none; }
        code { border-radius: 25px; background: <?php 
echo $lightColor();
?>; box-shadow: 0 0 45px -15px hsl(<?php 
echo $hue;
?>, 20%, 2%); color: <?php 
echo $darkColor();
?>; font-family: SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace; align-items: center; padding-right: 20px; position: relative; word-wrap: break-word; z-index: 1; }
        svg { overflow: hidden; vertical-align: text-bottom; }
        .wrapper { text-align: center; width: 100%; }
        .container { position: relative; background: radial-gradient(ellipse at bottom, <?php 
echo $darkColor();
?> 0%, hsl(<?php 
echo $hue;
?>, 20%, 13%) 100%); background-attachment: fixed; color: <?php 
echo $lightColor();
?>; }
        .container:after { content: ""; position: absolute; height: 2px; width: 2px; top: -2px; left: 0; background: white; box-shadow: 778px 1019px 0 0 rgba(255, 255, 255, 0.826) , 1075px 1688px 0 0 rgba(255,255,255, 0.275) , 388px 1021px 0 0 rgba(255,255,255, 0.259) , 1238px 626px 0 0 rgba(255,255,255, 0.469) , 997px 904px 0 0 rgba(255,255,255, 0.925) , 921px 1345px 0 0 rgba(255,255,255, 0.698) , 337px 1236px 0 0 rgba(255,255,255, 0.838) , 460px 569px 0 0 rgba(255,255,255, 0.01) , 690px 1488px 0 0 rgba(255,255,255, 0.154) , 859px 926px 0 0 rgba(255,255,255, 0.515) , 1272px 791px 0 0 rgba(255,255,255, 1) , 238px 1256px 0 0 rgba(255,255,255, 0.633) , 1486px 897px 0 0 rgba(255,255,255, 0.88) , 667px 6px 0 0 rgba(255,255,255, 0.508) , 853px 504px 0 0 rgba(255,255,255, 0.248) , 1329px 1778px 0 0 rgba(255,255,255, 0.217) , 768px 1340px 0 0 rgba(255,255,255, 0.792) , 631px 1383px 0 0 rgba(255,255,255, 0.698) , 991px 1603px 0 0 rgba(255,255,255, 0.939) , 1778px 1767px 0 0 rgba(255,255,255, 0.784) , 285px 546px 0 0 rgba(255,255,255, 0.8) , 1224px 1333px 0 0 rgba(255,255,255, 0.676) , 1154px 397px 0 0 rgba(255,255,255, 0.974) , 1210px 1004px 0 0 rgba(255,255,255, 0.894) , 1632px 953px 0 0 rgba(255,255,255, 0.281) , 449px 1144px 0 0 rgba(255,255,255, 0.706) , 1426px 771px 0 0 rgba(255,255,255, 0.737) , 1438px 1634px 0 0 rgba(255,255,255, 0.984) , 806px 168px 0 0 rgba(255,255,255, 0.807) , 731px 1067px 0 0 rgba(255,255,255, 0.734) , 1731px 1785px 0 0 rgba(255,255,255, 0.528) , 23px 975px 0 0 rgba(255,255,255, 0.068) , 575px 1088px 0 0 rgba(255,255,255, 0.876) , 1205px 1668px 0 0 rgba(255,255,255, 0.601) , 18px 1457px 0 0 rgba(255,255,255, 0.176) , 252px 1163px 0 0 rgba(255,255,255, 0.416) , 1752px 1px 0 0 rgba(255,255,255, 0.374) , 382px 767px 0 0 rgba(255,255,255, 0.073) , 133px 1462px 0 0 rgba(255,255,255, 0.706) , 851px 1166px 0 0 rgba(255,255,255, 0.535) , 374px 921px 0 0 rgba(255,255,255, 0.548) , 554px 1598px 0 0 rgba(255,255,255, 0.062) , 314px 685px 0 0 rgba(255,255,255, 0.187) , 1443px 209px 0 0 rgba(255,255,255, 0.097) , 1774px 1625px 0 0 rgba(255,255,255, 0.32) , 58px 278px 0 0 rgba(255,255,255, 0.684) , 986px 338px 0 0 rgba(255,255,255, 0.272) , 718px 1357px 0 0 rgba(255,255,255, 0.317) , 722px 983px 0 0 rgba(255,255,255, 0.568) , 1124px 992px 0 0 rgba(255,255,255, 0.199) , 581px 619px 0 0 rgba(255,255,255, 0.44) , 1120px 285px 0 0 rgba(255,255,255, 0.425) , 702px 138px 0 0 rgba(255,255,255, 0.816) , 262px 767px 0 0 rgba(255,255,255, 0.92) , 1204px 38px 0 0 rgba(255,255,255, 0.197) , 1196px 410px 0 0 rgba(255,255,255, 0.453) , 707px 699px 0 0 rgba(255,255,255, 0.481) , 1590px 1488px 0 0 rgba(255,255,255, 0.559) , 879px 1763px 0 0 rgba(255,255,255, 0.241) , 106px 686px 0 0 rgba(255,255,255, 0.175) , 158px 569px 0 0 rgba(255,255,255, 0.549) , 711px 1219px 0 0 rgba(255,255,255, 0.476) , 1339px 53px 0 0 rgba(255,255,255, 0.275) , 1410px 172px 0 0 rgba(255,255,255, 0.449) , 1601px 1484px 0 0 rgba(255,255,255, 0.988) , 1328px 1752px 0 0 rgba(255,255,255, 0.827) , 1733px 1475px 0 0 rgba(255,255,255, 0.567) , 559px 742px 0 0 rgba(255,255,255, 0.423) , 772px 844px 0 0 rgba(255,255,255, 0.039) , 602px 520px 0 0 rgba(255,255,255, 0.284) , 1158px 1067px 0 0 rgba(255,255,255, 0.066) , 1562px 730px 0 0 rgba(255,255,255, 0.086) , 1792px 615px 0 0 rgba(255,255,255, 0.438) , 1085px 1191px 0 0 rgba(255,255,255, 0.157) , 1402px 1087px 0 0 rgba(255,255,255, 0.797) , 569px 1685px 0 0 rgba(255,255,255, 0.992) , 1608px 52px 0 0 rgba(255,255,255, 0.302) , 1697px 1246px 0 0 rgba(255,255,255, 0.295) , 899px 1490px 0 0 rgba(255,255,255, 0.73) , 993px 901px 0 0 rgba(255,255,255, 0.961) , 1193px 1023px 0 0 rgba(255,255,255, 0.671) , 1224px 176px 0 0 rgba(255,255,255, 0.786) , 721px 1308px 0 0 rgba(255,255,255, 0.691) , 1702px 730px 0 0 rgba(255,255,255, 0.841) , 1480px 1498px 0 0 rgba(255,255,255, 0.655) , 181px 1612px 0 0 rgba(255,255,255, 0.588) , 1776px 679px 0 0 rgba(255,255,255, 0.821) , 892px 706px 0 0 rgba(255,255,255, 0.056) , 859px 267px 0 0 rgba(255,255,255, 0.565) , 784px 1285px 0 0 rgba(255,255,255, 0.029) , 1561px 1198px 0 0 rgba(255,255,255, 0.315) , 205px 421px 0 0 rgba(255,255,255, 0.584) , 236px 406px 0 0 rgba(255,255,255, 0.166) , 1259px 689px 0 0 rgba(255,255,255, 0.321) , 448px 317px 0 0 rgba(255,255,255, 0.495) , 1318px 466px 0 0 rgba(255,255,255, 0.275) , 1053px 297px 0 0 rgba(255,255,255, 0.035) , 716px 538px 0 0 rgba(255,255,255, 0.764) , 381px 207px 0 0 rgba(255,255,255, 0.692) , 871px 1140px 0 0 rgba(255,255,255, 0.342) , 361px 53px 0 0 rgba(255,255,255, 0.984) , 1565px 1593px 0 0 rgba(255,255,255, 0.102) , 145px 277px 0 0 rgba(255,255,255, 0.866) , 220px 1503px 0 0 rgba(255,255,255, 0.936) , 1068px 1475px 0 0 rgba(255,255,255, 0.156) , 1548px 483px 0 0 rgba(255,255,255, 0.768) , 710px 103px 0 0 rgba(255,255,255, 0.809) , 1660px 921px 0 0 rgba(255,255,255, 0.952) , 462px 1252px 0 0 rgba(255,255,255, 0.825) , 1123px 1628px 0 0 rgba(255,255,255, 0.409) , 1274px 729px 0 0 rgba(255,255,255, 0.26) , 1739px 679px 0 0 rgba(255,255,255, 0.83) , 1550px 1518px 0 0 rgba(255,255,255, 0.25) , 1624px 346px 0 0 rgba(255,255,255, 0.557) , 1023px 579px 0 0 rgba(255,255,255, 0.854) , 217px 661px 0 0 rgba(255,255,255, 0.731) , 1504px 549px 0 0 rgba(255,255,255, 0.705) , 939px 5px 0 0 rgba(255,255,255, 0.389) , 284px 735px 0 0 rgba(255,255,255, 0.355) , 13px 1679px 0 0 rgba(255,255,255, 0.712) , 137px 1592px 0 0 rgba(255,255,255, 0.619) , 1113px 505px 0 0 rgba(255,255,255, 0.651) , 1584px 510px 0 0 rgba(255,255,255, 0.41) , 346px 913px 0 0 rgba(255,255,255, 0.09) , 198px 1490px 0 0 rgba(255,255,255, 0.103) , 447px 1128px 0 0 rgba(255,255,255, 0.314) , 1356px 324px 0 0 rgba(255,255,255, 0.324) , 648px 667px 0 0 rgba(255,255,255, 0.155) , 442px 260px 0 0 rgba(255,255,255, 0.22) , 210px 401px 0 0 rgba(255,255,255, 0.682) , 422px 1772px 0 0 rgba(255,255,255, 0.671) , 276px 349px 0 0 rgba(255,255,255, 0.683) , 131px 539px 0 0 rgba(255,255,255, 0.977) , 892px 94px 0 0 rgba(255,255,255, 0.081) , 1295px 222px 0 0 rgba(255,255,255, 0.961) , 5px 1727px 0 0 rgba(255,255,255, 0.311) , 714px 1148px 0 0 rgba(255,255,255, 0.846) , 1455px 1182px 0 0 rgba(255,255,255, 0.313) , 1370px 708px 0 0 rgba(255,255,255, 0.824) , 812px 433px 0 0 rgba(255,255,255, 0.75) , 1110px 558px 0 0 rgba(255,255,255, 0.709) , 1132px 1543px 0 0 rgba(255,255,255, 0.868) , 644px 610px 0 0 rgba(255,255,255, 0.166) , 269px 1481px 0 0 rgba(255,255,255, 0.889) , 1712px 590px 0 0 rgba(255,255,255, 0.139) , 1159px 599px 0 0 rgba(255,255,255, 0.992) , 1551px 209px 0 0 rgba(255,255,255, 0.033) , 1020px 1721px 0 0 rgba(255,255,255, 0.028) , 216px 373px 0 0 rgba(255,255,255, 0.665) , 877px 532px 0 0 rgba(255,255,255, 0.686) , 1326px 885px 0 0 rgba(255,255,255, 0.517) , 972px 1704px 0 0 rgba(255,255,255, 0.499) , 749px 181px 0 0 rgba(255,255,255, 0.712) , 1511px 1650px 0 0 rgba(255,255,255, 0.101) , 1432px 183px 0 0 rgba(255,255,255, 0.545) , 1541px 1338px 0 0 rgba(255,255,255, 0.71) , 513px 1406px 0 0 rgba(255,255,255, 0.17) , 1314px 1197px 0 0 rgba(255,255,255, 0.789) , 824px 1659px 0 0 rgba(255,255,255, 0.597) , 308px 298px 0 0 rgba(255,255,255, 0.917) , 1225px 659px 0 0 rgba(255,255,255, 0.229) , 1253px 257px 0 0 rgba(255,255,255, 0.631) , 1653px 185px 0 0 rgba(255,255,255, 0.113) , 336px 614px 0 0 rgba(255,255,255, 0.045) , 1093px 898px 0 0 rgba(255,255,255, 0.617) , 730px 5px 0 0 rgba(255,255,255, 0.11) , 785px 645px 0 0 rgba(255,255,255, 0.516) , 989px 678px 0 0 rgba(255,255,255, 0.917) , 1511px 1614px 0 0 rgba(255,255,255, 0.938) , 584px 1117px 0 0 rgba(255,255,255, 0.631) , 534px 1012px 0 0 rgba(255,255,255, 0.668) , 1325px 1778px 0 0 rgba(255,255,255, 0.293) , 1632px 754px 0 0 rgba(255,255,255, 0.26) , 78px 1258px 0 0 rgba(255,255,255, 0.52) , 779px 1691px 0 0 rgba(255,255,255, 0.878) , 253px 1706px 0 0 rgba(255,255,255, 0.75) , 1358px 245px 0 0 rgba(255,255,255, 0.027) , 361px 1629px 0 0 rgba(255,255,255, 0.238) , 1134px 232px 0 0 rgba(255,255,255, 0.387) , 1685px 777px 0 0 rgba(255,255,255, 0.156) , 515px 724px 0 0 rgba(255,255,255, 0.863) , 588px 1728px 0 0 rgba(255,255,255, 0.159) , 1132px 47px 0 0 rgba(255,255,255, 0.691) , 315px 1446px 0 0 rgba(255,255,255, 0.782) , 79px 233px 0 0 rgba(255,255,255, 0.317) , 1498px 1050px 0 0 rgba(255,255,255, 0.358) , 30px 1073px 0 0 rgba(255,255,255, 0.939) , 1637px 620px 0 0 rgba(255,255,255, 0.141) , 1736px 1683px 0 0 rgba(255,255,255, 0.682) , 1298px 1505px 0 0 rgba(255,255,255, 0.863) , 972px 85px 0 0 rgba(255,255,255, 0.941) , 349px 1356px 0 0 rgba(255,255,255, 0.672) , 1545px 1429px 0 0 rgba(255,255,255, 0.859) , 1076px 467px 0 0 rgba(255,255,255, 0.024) , 189px 1647px 0 0 rgba(255,255,255, 0.838) , 423px 1722px 0 0 rgba(255,255,255, 0.771) , 1691px 1719px 0 0 rgba(255,255,255, 0.676) , 1747px 658px 0 0 rgba(255,255,255, 0.255) , 149px 1492px 0 0 rgba(255,255,255, 0.911) , 1203px 1138px 0 0 rgba(255,255,255, 0.964) , 781px 1584px 0 0 rgba(255,255,255, 0.465) , 1609px 1595px 0 0 rgba(255,255,255, 0.688) , 447px 1655px 0 0 rgba(255,255,255, 0.166) , 914px 1153px 0 0 rgba(255,255,255, 0.085) , 600px 1058px 0 0 rgba(255,255,255, 0.821) , 804px 505px 0 0 rgba(255,255,255, 0.608) , 1506px 584px 0 0 rgba(255,255,255, 0.618) , 587px 1290px 0 0 rgba(255,255,255, 0.071) , 258px 600px 0 0 rgba(255,255,255, 0.243) , 328px 395px 0 0 rgba(255,255,255, 0.065) , 846px 783px 0 0 rgba(255,255,255, 0.995) , 1138px 1294px 0 0 rgba(255,255,255, 0.703) , 1668px 633px 0 0 rgba(255,255,255, 0.27) , 337px 103px 0 0 rgba(255,255,255, 0.202) , 132px 986px 0 0 rgba(255,255,255, 0.726) , 414px 757px 0 0 rgba(255,255,255, 0.752) , 8px 1311px 0 0 rgba(255,255,255, 0.307) , 1791px 910px 0 0 rgba(255,255,255, 0.346) , 844px 216px 0 0 rgba(255,255,255, 0.156) , 1547px 1723px 0 0 rgba(255,255,255, 0.73) , 1187px 398px 0 0 rgba(255,255,255, 0.698) , 1550px 1520px 0 0 rgba(255,255,255, 0.462) , 1346px 655px 0 0 rgba(255,255,255, 0.58) , 668px 770px 0 0 rgba(255,255,255, 0.422) , 1774px 1435px 0 0 rgba(255,255,255, 0.089) , 693px 1061px 0 0 rgba(255,255,255, 0.893) , 132px 1689px 0 0 rgba(255,255,255, 0.937) , 894px 1561px 0 0 rgba(255,255,255, 0.88) , 906px 1706px 0 0 rgba(255,255,255, 0.567) , 1140px 297px 0 0 rgba(255,255,255, 0.358) , 13px 1288px 0 0 rgba(255,255,255, 0.464) , 1744px 423px 0 0 rgba(255,255,255, 0.845) , 119px 1548px 0 0 rgba(255,255,255, 0.769) , 1249px 1321px 0 0 rgba(255,255,255, 0.29) , 123px 795px 0 0 rgba(255,255,255, 0.597) , 390px 1542px 0 0 rgba(255,255,255, 0.47) , 825px 667px 0 0 rgba(255,255,255, 0.049) , 1071px 875px 0 0 rgba(255,255,255, 0.06) , 1428px 1786px 0 0 rgba(255,255,255, 0.222) , 993px 696px 0 0 rgba(255,255,255, 0.399) , 1585px 247px 0 0 rgba(255,255,255, 0.094) , 1340px 1312px 0 0 rgba(255,255,255, 0.603) , 1640px 725px 0 0 rgba(255,255,255, 0.026) , 1161px 1397px 0 0 rgba(255,255,255, 0.222) , 966px 1132px 0 0 rgba(255,255,255, 0.69) , 1782px 1275px 0 0 rgba(255,255,255, 0.606) , 1117px 1533px 0 0 rgba(255,255,255, 0.248) , 1027px 959px 0 0 rgba(255,255,255, 0.46) , 459px 839px 0 0 rgba(255,255,255, 0.98) , 1192px 265px 0 0 rgba(255,255,255, 0.523) , 175px 501px 0 0 rgba(255,255,255, 0.371) , 626px 19px 0 0 rgba(255,255,255, 0.246) , 46px 1173px 0 0 rgba(255,255,255, 0.124) , 573px 925px 0 0 rgba(255,255,255, 0.621) , 1px 283px 0 0 rgba(255,255,255, 0.943) , 778px 1213px 0 0 rgba(255,255,255, 0.128) , 435px 593px 0 0 rgba(255,255,255, 0.378) , 32px 394px 0 0 rgba(255,255,255, 0.451) , 1019px 1055px 0 0 rgba(255,255,255, 0.685) , 1423px 1233px 0 0 rgba(255,255,255, 0.354) , 494px 841px 0 0 rgba(255,255,255, 0.322) , 667px 194px 0 0 rgba(255,255,255, 0.655) , 1671px 195px 0 0 rgba(255,255,255, 0.502) , 403px 1710px 0 0 rgba(255,255,255, 0.623) , 665px 1597px 0 0 rgba(255,255,255, 0.839) , 61px 1742px 0 0 rgba(255,255,255, 0.566) , 1490px 1654px 0 0 rgba(255,255,255, 0.646) , 1361px 1604px 0 0 rgba(255,255,255, 0.101) , 1191px 1023px 0 0 rgba(255,255,255, 0.881) , 550px 378px 0 0 rgba(255,255,255, 0.573) , 1332px 1234px 0 0 rgba(255,255,255, 0.922) , 760px 1205px 0 0 rgba(255,255,255, 0.992) , 1506px 1328px 0 0 rgba(255,255,255, 0.723) , 1126px 813px 0 0 rgba(255,255,255, 0.549) , 67px 240px 0 0 rgba(255,255,255, 0.901) , 125px 1301px 0 0 rgba(255,255,255, 0.464) , 643px 391px 0 0 rgba(255,255,255, 0.589) , 1114px 1756px 0 0 rgba(255,255,255, 0.321) , 1602px 699px 0 0 rgba(255,255,255, 0.274) , 510px 393px 0 0 rgba(255,255,255, 0.185) , 171px 1217px 0 0 rgba(255,255,255, 0.932) , 1202px 1362px 0 0 rgba(255,255,255, 0.726) , 1160px 1324px 0 0 rgba(255,255,255, 0.867) , 121px 319px 0 0 rgba(255,255,255, 0.992) , 1474px 835px 0 0 rgba(255,255,255, 0.89) , 357px 1213px 0 0 rgba(255,255,255, 0.91) , 783px 976px 0 0 rgba(255,255,255, 0.941) , 750px 1599px 0 0 rgba(255,255,255, 0.515) , 323px 450px 0 0 rgba(255,255,255, 0.966) , 1078px 282px 0 0 rgba(255,255,255, 0.947) , 1164px 46px 0 0 rgba(255,255,255, 0.296) , 1792px 705px 0 0 rgba(255,255,255, 0.485) , 880px 1287px 0 0 rgba(255,255,255, 0.894) , 60px 1402px 0 0 rgba(255,255,255, 0.816) , 752px 894px 0 0 rgba(255,255,255, 0.803) , 285px 1535px 0 0 rgba(255,255,255, 0.93) , 1528px 401px 0 0 rgba(255,255,255, 0.727) , 651px 1767px 0 0 rgba(255,255,255, 0.146) , 1498px 1190px 0 0 rgba(255,255,255, 0.042) , 394px 1786px 0 0 rgba(255,255,255, 0.159) , 1318px 9px 0 0 rgba(255,255,255, 0.575) , 1699px 1675px 0 0 rgba(255,255,255, 0.511) , 82px 986px 0 0 rgba(255,255,255, 0.906) , 940px 970px 0 0 rgba(255,255,255, 0.562) , 1624px 259px 0 0 rgba(255,255,255, 0.537) , 1782px 222px 0 0 rgba(255,255,255, 0.259) , 1572px 1725px 0 0 rgba(255,255,255, 0.716) , 1080px 1557px 0 0 rgba(255,255,255, 0.245) , 1727px 648px 0 0 rgba(255,255,255, 0.471) , 899px 231px 0 0 rgba(255,255,255, 0.445) , 1061px 1074px 0 0 rgba(255,255,255, 0.079) , 556px 478px 0 0 rgba(255,255,255, 0.524) , 343px 359px 0 0 rgba(255,255,255, 0.162) , 711px 1254px 0 0 rgba(255,255,255, 0.323) , 1335px 242px 0 0 rgba(255,255,255, 0.936) , 933px 39px 0 0 rgba(255,255,255, 0.784) , 1629px 908px 0 0 rgba(255,255,255, 0.289) , 1800px 229px 0 0 rgba(255,255,255, 0.399) , 1589px 926px 0 0 rgba(255,255,255, 0.709) , 976px 694px 0 0 rgba(255,255,255, 0.855) , 1163px 1240px 0 0 rgba(255,255,255, 0.754) , 1662px 1784px 0 0 rgba(255,255,255, 0.088) , 656px 1388px 0 0 rgba(255,255,255, 0.688) , 1190px 1100px 0 0 rgba(255,255,255, 0.769) , 33px 392px 0 0 rgba(255,255,255, 0.301) , 56px 1405px 0 0 rgba(255,255,255, 0.969) , 1491px 118px 0 0 rgba(255,255,255, 0.991) , 1216px 997px 0 0 rgba(255,255,255, 0.727) , 1617px 712px 0 0 rgba(255,255,255, 0.45) , 163px 553px 0 0 rgba(255,255,255, 0.977) , 103px 140px 0 0 rgba(255,255,255, 0.916) , 1099px 1404px 0 0 rgba(255,255,255, 0.167) , 1423px 587px 0 0 rgba(255,255,255, 0.792) , 1797px 309px 0 0 rgba(255,255,255, 0.526) , 381px 141px 0 0 rgba(255,255,255, 0.005) , 1214px 802px 0 0 rgba(255,255,255, 0.887) , 211px 829px 0 0 rgba(255,255,255, 0.72) , 1103px 1507px 0 0 rgba(255,255,255, 0.642) , 244px 1231px 0 0 rgba(255,255,255, 0.184) , 118px 1747px 0 0 rgba(255,255,255, 0.475) , 183px 1293px 0 0 rgba(255,255,255, 0.148) , 911px 1362px 0 0 rgba(255,255,255, 0.073) , 817px 457px 0 0 rgba(255,255,255, 0.459) , 756px 18px 0 0 rgba(255,255,255, 0.544) , 481px 1118px 0 0 rgba(255,255,255, 0.878) , 380px 138px 0 0 rgba(255,255,255, 0.132) , 320px 646px 0 0 rgba(255,255,255, 0.04) , 1724px 1716px 0 0 rgba(255,255,255, 0.381) , 978px 1269px 0 0 rgba(255,255,255, 0.431) , 1530px 255px 0 0 rgba(255,255,255, 0.31) , 664px 204px 0 0 rgba(255,255,255, 0.913) , 474px 703px 0 0 rgba(255,255,255, 0.832) , 1722px 1204px 0 0 rgba(255,255,255, 0.356) , 1453px 821px 0 0 rgba(255,255,255, 0.195) , 730px 1468px 0 0 rgba(255,255,255, 0.696) , 928px 1610px 0 0 rgba(255,255,255, 0.894) , 1036px 304px 0 0 rgba(255,255,255, 0.696) , 1590px 172px 0 0 rgba(255,255,255, 0.729) , 249px 1590px 0 0 rgba(255,255,255, 0.277) , 357px 81px 0 0 rgba(255,255,255, 0.526) , 726px 1261px 0 0 rgba(255,255,255, 0.149) , 643px 946px 0 0 rgba(255,255,255, 0.005) , 1263px 995px 0 0 rgba(255,255,255, 0.124) , 1564px 1107px 0 0 rgba(255,255,255, 0.789) , 388px 83px 0 0 rgba(255,255,255, 0.498) , 715px 681px 0 0 rgba(255,255,255, 0.655) , 1618px 1624px 0 0 rgba(255,255,255, 0.63) , 1423px 1576px 0 0 rgba(255,255,255, 0.52) , 564px 1786px 0 0 rgba(255,255,255, 0.482) , 1066px 735px 0 0 rgba(255,255,255, 0.276) , 714px 1179px 0 0 rgba(255,255,255, 0.395) , 967px 1006px 0 0 rgba(255,255,255, 0.923) , 1136px 1790px 0 0 rgba(255,255,255, 0.801) , 215px 1690px 0 0 rgba(255,255,255, 0.957) , 1500px 1338px 0 0 rgba(255,255,255, 0.541) , 1679px 1065px 0 0 rgba(255,255,255, 0.925) , 426px 1489px 0 0 rgba(255,255,255, 0.193) , 1273px 853px 0 0 rgba(255,255,255, 0.317) , 665px 1189px 0 0 rgba(255,255,255, 0.512) , 520px 552px 0 0 rgba(255,255,255, 0.925) , 253px 438px 0 0 rgba(255,255,255, 0.588) , 369px 1354px 0 0 rgba(255,255,255, 0.889) , 749px 205px 0 0 rgba(255,255,255, 0.243) , 820px 145px 0 0 rgba(255,255,255, 0.207) , 1739px 228px 0 0 rgba(255,255,255, 0.267) , 392px 495px 0 0 rgba(255,255,255, 0.504) , 721px 1044px 0 0 rgba(255,255,255, 0.823) , 833px 912px 0 0 rgba(255,255,255, 0.222) , 865px 1499px 0 0 rgba(255,255,255, 0.003) , 313px 756px 0 0 rgba(255,255,255, 0.727) , 439px 1187px 0 0 rgba(255,255,255, 0.572) , 6px 1238px 0 0 rgba(255,255,255, 0.676) , 1567px 11px 0 0 rgba(255,255,255, 0.701) , 1216px 757px 0 0 rgba(255,255,255, 0.87) , 916px 588px 0 0 rgba(255,255,255, 0.565) , 831px 215px 0 0 rgba(255,255,255, 0.597) , 1289px 697px 0 0 rgba(255,255,255, 0.964) , 307px 34px 0 0 rgba(255,255,255, 0.462) , 3px 1685px 0 0 rgba(255,255,255, 0.464) , 1115px 1421px 0 0 rgba(255,255,255, 0.303) , 1451px 473px 0 0 rgba(255,255,255, 0.142) , 1374px 1205px 0 0 rgba(255,255,255, 0.086) , 1564px 317px 0 0 rgba(255,255,255, 0.773) , 304px 1127px 0 0 rgba(255,255,255, 0.653) , 446px 214px 0 0 rgba(255,255,255, 0.135) , 1541px 459px 0 0 rgba(255,255,255, 0.725) , 1387px 880px 0 0 rgba(255,255,255, 0.157) , 1172px 224px 0 0 rgba(255,255,255, 0.088) , 1420px 637px 0 0 rgba(255,255,255, 0.916) , 1385px 932px 0 0 rgba(255,255,255, 0.225) , 174px 1472px 0 0 rgba(255,255,255, 0.649) , 252px 750px 0 0 rgba(255,255,255, 0.277) , 825px 1042px 0 0 rgba(255,255,255, 0.707) , 840px 703px 0 0 rgba(255,255,255, 0.948) , 1478px 1800px 0 0 rgba(255,255,255, 0.151) , 95px 1303px 0 0 rgba(255,255,255, 0.332) , 1198px 740px 0 0 rgba(255,255,255, 0.443) , 141px 312px 0 0 rgba(255,255,255, 0.04) , 291px 729px 0 0 rgba(255,255,255, 0.284) , 1209px 1506px 0 0 rgba(255,255,255, 0.741) , 1188px 307px 0 0 rgba(255,255,255, 0.141) , 958px 41px 0 0 rgba(255,255,255, 0.858) , 1311px 1484px 0 0 rgba(255,255,255, 0.097) , 846px 1153px 0 0 rgba(255,255,255, 0.862) , 1238px 1376px 0 0 rgba(255,255,255, 0.071) , 1499px 342px 0 0 rgba(255,255,255, 0.719) , 640px 833px 0 0 rgba(255,255,255, 0.966) , 712px 545px 0 0 rgba(255,255,255, 0.194) , 1655px 1542px 0 0 rgba(255,255,255, 0.82) , 616px 353px 0 0 rgba(255,255,255, 0.871) , 1591px 1631px 0 0 rgba(255,255,255, 0.61) , 1664px 591px 0 0 rgba(255,255,255, 0.35) , 934px 454px 0 0 rgba(255,255,255, 0.58) , 1175px 477px 0 0 rgba(255,255,255, 0.966) , 299px 914px 0 0 rgba(255,255,255, 0.839) , 534px 243px 0 0 rgba(255,255,255, 0.194) , 773px 1135px 0 0 rgba(255,255,255, 0.42) , 1696px 1472px 0 0 rgba(255,255,255, 0.552) , 125px 523px 0 0 rgba(255,255,255, 0.591) , 1195px 382px 0 0 rgba(255,255,255, 0.904) , 1609px 1374px 0 0 rgba(255,255,255, 0.579) , 843px 82px 0 0 rgba(255,255,255, 0.072) , 1604px 451px 0 0 rgba(255,255,255, 0.545) , 1322px 190px 0 0 rgba(255,255,255, 0.034) , 528px 228px 0 0 rgba(255,255,255, 0.146) , 1470px 1169px 0 0 rgba(255,255,255, 0.912) , 502px 1350px 0 0 rgba(255,255,255, 0.594) , 1031px 298px 0 0 rgba(255,255,255, 0.368) , 1100px 1427px 0 0 rgba(255,255,255, 0.79) , 979px 1105px 0 0 rgba(255,255,255, 0.973) , 643px 1184px 0 0 rgba(255,255,255, 0.813) , 1636px 1701px 0 0 rgba(255,255,255, 0.013) , 1004px 245px 0 0 rgba(255,255,255, 0.412) , 680px 740px 0 0 rgba(255,255,255, 0.967) , 1599px 562px 0 0 rgba(255,255,255, 0.66) , 256px 1617px 0 0 rgba(255,255,255, 0.463) , 314px 1092px 0 0 rgba(255,255,255, 0.734) , 870px 900px 0 0 rgba(255,255,255, 0.512) , 530px 60px 0 0 rgba(255,255,255, 0.198) , 1786px 896px 0 0 rgba(255,255,255, 0.392) , 636px 212px 0 0 rgba(255,255,255, 0.997) , 672px 540px 0 0 rgba(255,255,255, 0.632) , 1118px 1649px 0 0 rgba(255,255,255, 0.377) , 433px 647px 0 0 rgba(255,255,255, 0.902) , 1200px 1737px 0 0 rgba(255,255,255, 0.262) , 1258px 143px 0 0 rgba(255,255,255, 0.729) , 1603px 1364px 0 0 rgba(255,255,255, 0.192) , 66px 1756px 0 0 rgba(255,255,255, 0.681) , 946px 263px 0 0 rgba(255,255,255, 0.105) , 1216px 1082px 0 0 rgba(255,255,255, 0.287) , 6px 1143px 0 0 rgba(255,255,255, 0.017) , 1631px 126px 0 0 rgba(255,255,255, 0.449) , 357px 1565px 0 0 rgba(255,255,255, 0.163) , 1752px 261px 0 0 rgba(255,255,255, 0.423) , 1247px 1631px 0 0 rgba(255,255,255, 0.312) , 320px 671px 0 0 rgba(255,255,255, 0.695) , 1375px 596px 0 0 rgba(255,255,255, 0.856) , 1456px 1340px 0 0 rgba(255,255,255, 0.564) , 447px 1044px 0 0 rgba(255,255,255, 0.623) , 1732px 447px 0 0 rgba(255,255,255, 0.216) , 174px 1509px 0 0 rgba(255,255,255, 0.398) , 16px 861px 0 0 rgba(255,255,255, 0.904) , 878px 1296px 0 0 rgba(255,255,255, 0.205) , 1725px 1483px 0 0 rgba(255,255,255, 0.704) , 255px 48px 0 0 rgba(255,255,255, 0.7) , 610px 1669px 0 0 rgba(255,255,255, 0.865) , 1044px 1251px 0 0 rgba(255,255,255, 0.98) , 884px 862px 0 0 rgba(255,255,255, 0.198) , 986px 545px 0 0 rgba(255,255,255, 0.379) , 1620px 217px 0 0 rgba(255,255,255, 0.159) , 383px 1763px 0 0 rgba(255,255,255, 0.518) , 595px 974px 0 0 rgba(255,255,255, 0.347) , 359px 14px 0 0 rgba(255,255,255, 0.863) , 95px 1385px 0 0 rgba(255,255,255, 0.011) , 411px 1030px 0 0 rgba(255,255,255, 0.038) , 345px 789px 0 0 rgba(255,255,255, 0.771) , 421px 460px 0 0 rgba(255,255,255, 0.133) , 972px 1160px 0 0 rgba(255,255,255, 0.342) , 597px 1061px 0 0 rgba(255,255,255, 0.781) , 1017px 1092px 0 0 rgba(255,255,255, 0.437); }
        .warning { background: <?php 
echo $lightColor();
?>; display: flex; align-items: center; padding: 10px; text-align: left; justify-content: center; }
        .warning svg { flex-shrink: 0; height: 32px; width: 32px; margin-right: 10px; }
        .warning p { line-height:  1.4; margin: 0; }
        .container svg.wave { position: absolute; bottom: -2px; left: 0; z-index: 1; }
        .container .logo { margin-bottom: 1em; }
        .container .logo svg { fill: hsl(<?php 
echo $hue;
?>, 20%, 26%); }
        .welcome { padding-top: 4em; margin-bottom: 3em; }
        .welcome small { display: block; font-size: 85%; }
        .status { padding-bottom: 2em; }
        .status code, .status .status-ready { display: none; }
        .version { font-size: 34px; }
        .check { background: <?php 
echo $darkColor();
?>; border-radius: 20px; width: 50px; display: flex; align-items: center; justify-content: center; height: 37px; margin: 6px 8px 6px 6px; }
        .check svg { fill: <?php 
echo $lightColor();
?>; }
        .status-ready { margin: 28px 0 0; }
        .resources { margin: 0 auto; max-width: 1366px; padding: 2.5em 0 3.5em; }
        .resources .row { margin-left: 30px; margin-right: 30px; display: flex; justify-content: space-evenly; }
        .resource { padding: 0 10px; position: relative; }
        .resource svg { height: 48px; width: 48px; fill: <?php 
echo $darkColor();
?>; margin-bottom: 5px; }
        .resource h2 { font-size: 18px; font-weight: normal; margin-bottom: 5px; }
        .resource p { margin-top: 5px; }
        .resource a { display: block; font-size: 14px; }

        @media (min-width: 768px) {
            @-webkit-keyframes fade-in { 0% { opacity: 0; } 100% { opacity: 1; } }
            @keyframes fade-in { 0% { opacity: 0; } 100% { opacity: 1; } }
            .sf-toolbar { opacity: 0; -webkit-animation: fade-in 1s .2s forwards; animation: fade-in 1s .2s forwards; z-index: 99999; }

            .resources .row { margin-left: 50px; margin-right: 50px; }
            .resource { padding: 0 30px; }

            .status { padding-bottom: 4em; }
            .status code { display: inline-flex; }
            .status .status-ready { display: block; }

            .resource svg { height: 64px; width: 64px; }
            .resource h2 { font-size: 22px; }
            .resource a { font-size: 16px; margin-top: 0; }
        }
        @media (min-width: 992px) {
            body { font-size: 20px; }
            .warning { text-align: center; }
        }
    </style>
</head>
<body>
<div class="wrapper">
    <div class="warning">
        <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 576 512" width="32"><path fill="currentColor" d="M569.517 440.013C587.975 472.007 564.806 512 527.94 512H48.054c-36.937 0-59.999-40.055-41.577-71.987L246.423 23.985c18.467-32.009 64.72-31.951 83.154 0l239.94 416.028zM288 354c-25.405 0-46 20.595-46 46s20.595 46 46 46 46-20.595 46-46-20.595-46-46-46zm-43.673-165.346l7.418 136c.347 6.364 5.609 11.346 11.982 11.346h48.546c6.373 0 11.635-4.982 11.982-11.346l7.418-136c.375-6.874-5.098-12.654-11.982-12.654h-63.383c-6.884 0-12.356 5.78-11.981 12.654z" class=""></path></svg>
        <p>
            You're seeing this page because you haven't configured any homepage URL and <a href="https://symfony.com/doc/<?php 
echo $docVersion;
?>/debug-mode">debug mode</a> is enabled.
        </p>
    </div>

    <div class="container">
        <div class="welcome">
            <div class="logo">
                <svg xmlns="http://www.w3.org/2000/svg" width="112.165" height="112.166"><path d="M112.165 56.079c0 30.976-25.109 56.087-56.084 56.087C25.108 112.166 0 87.055 0 56.079 0 25.108 25.107 0 56.081 0c30.975 0 56.084 25.108 56.084 56.079z" style="fill: <?php 
echo $lightColor();
?>;"/><path d="M80.603 20.75c-5.697.195-10.67 3.34-14.373 7.68-4.1 4.765-6.824 10.411-8.791 16.18-3.514-2.882-6.223-6.611-11.864-8.233-4.359-1.253-8.936-.737-13.146 2.399-1.992 1.489-3.367 3.738-4.02 5.859-1.692 5.498 1.778 10.396 3.354 12.151l3.447 3.691c.709.725 2.422 2.613 1.584 5.319-.9 2.947-4.451 4.85-8.092 3.731-1.627-.499-3.963-1.71-3.439-3.413.215-.699.715-1.225.984-1.821.244-.521.363-.907.438-1.14.665-2.169-.245-4.994-2.57-5.713-2.171-.666-4.391-.138-5.252 2.655-.977 3.174.543 8.935 8.681 11.441 9.535 2.935 17.597-2.259 18.742-9.026.721-4.239-1.195-7.392-4.701-11.441l-2.859-3.163c-1.73-1.729-2.324-4.677-.533-6.942 1.512-1.912 3.664-2.726 7.191-1.768 5.15 1.396 7.443 4.969 11.271 7.851-1.578 5.187-2.613 10.392-3.547 15.059l-.574 3.481c-2.736 14.352-4.826 22.235-10.256 26.76-1.094.779-2.658 1.943-5.014 2.027-1.238.037-1.637-.814-1.654-1.186-.027-.865.703-1.264 1.188-1.652.727-.396 1.824-1.053 1.748-3.156-.078-2.484-2.137-4.639-5.111-4.541-2.229.075-5.625 2.171-5.497 6.011.131 3.967 3.827 6.938 9.401 6.75 2.979-.102 9.633-1.312 16.188-9.105 7.631-8.935 9.766-19.175 11.372-26.671l1.793-9.897c.992.119 2.059.2 3.217.228 9.504.201 14.256-4.72 14.328-8.302.049-2.167-1.42-4.302-3.479-4.251-1.471.041-3.32 1.022-3.762 3.057-.436 1.995 3.023 3.798.32 5.553-1.92 1.242-5.361 2.116-10.209 1.407l.881-4.872c1.799-9.238 4.018-20.6 12.436-20.878.615-.029 2.857.026 2.91 1.512.014.493-.109.623-.689 1.757-.592.884-.814 1.64-.785 2.504.08 2.356 1.873 3.908 4.471 3.818 3.473-.116 4.469-3.496 4.412-5.233-.146-4.085-4.449-6.665-10.14-6.477z"/></svg>
            </div>
            <h1><small>Welcome to</small> Symfony <span class="version"><?php 
echo $version;
?></span></h1>
        </div>

        <div class="status">
            <code>
                <span class="check">
                    <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path d="M0 0h24v24H0z" fill="none"/><path d="M9 16.17L4.83 12l-1.42 1.41L9 19 21 7l-1.41-1.41z"/></svg>
                </span>
                <span><?php 
echo $projectDir;
?></span>
            </code>
            <p class="status-ready">Your application is now ready and you can start working on it.</p>
        </div>

        <svg style="pointer-events: none" class="wave" width="100%" height="50px" preserveAspectRatio="none" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 1920 75"><defs><style>.a{fill:none}.b{clip-path:url(#a)}.c,.d {fill: <?php 
echo $lightColor();
?>}.d{opacity:0.5;isolation:isolate;}</style><clipPath id="a"><rect class="a" width="1920" height="75"></rect></clipPath></defs><g class="b"><path class="c" d="M1963,327H-105V65A2647.49,2647.49,0,0,1,431,19c217.7,3.5,239.6,30.8,470,36,297.3,6.7,367.5-36.2,642-28a2511.41,2511.41,0,0,1,420,48"></path></g><g class="b"><path class="d" d="M-127,404H1963V44c-140.1-28-343.3-46.7-566,22-75.5,23.3-118.5,45.9-162,64-48.6,20.2-404.7,128-784,0C355.2,97.7,341.6,78.3,235,50,86.6,10.6-41.8,6.9-127,10"></path></g><g class="b"><path class="d" d="M1979,462-155,446V106C251.8,20.2,576.6,15.9,805,30c167.4,10.3,322.3,32.9,680,56,207,13.4,378,20.3,494,24"></path></g><g class="b"><path class="d" d="M1998,484H-243V100c445.8,26.8,794.2-4.1,1035-39,141-20.4,231.1-40.1,378-45,349.6-11.6,636.7,73.8,828,150"></path></g></svg>
    </div>

    <div class="resources">
        <div class="row">
            <div class="resource">
                <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path d="M0 0h24v24H0z" fill="none"/><path d="M12 11.55C9.64 9.35 6.48 8 3 8v11c3.48 0 6.64 1.35 9 3.55 2.36-2.19 5.52-3.55 9-3.55V8c-3.48 0-6.64 1.35-9 3.55zM12 8c1.66 0 3-1.34 3-3s-1.34-3-3-3-3 1.34-3 3 1.34 3 3 3z"/></svg>
                <h2>Documentation</h2>
                <a href="https://symfony.com/doc/<?php 
echo $docVersion;
?>/index.html">
                    Guides, components, references
                </a>
            </div>
            <div class="resource">
                <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path fill="none" d="M0 0h24v24H0V0z"/><path d="M9.4 16.6L4.8 12l4.6-4.6L8 6l-6 6 6 6 1.4-1.4zm5.2 0l4.6-4.6-4.6-4.6L16 6l6 6-6 6-1.4-1.4z"/></svg>
                <h2>Tutorials</h2>
                <a href="https://symfony.com/doc/<?php 
echo $docVersion;
?>/page_creation.html">
                    Create your first page
                </a>
            </div>
            <div class="resource">
                <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path d="M0 0h24v24H0z" fill="none"/><path d="M16 11c1.66 0 2.99-1.34 2.99-3S17.66 5 16 5c-1.66 0-3 1.34-3 3s1.34 3 3 3zm-8 0c1.66 0 2.99-1.34 2.99-3S9.66 5 8 5C6.34 5 5 6.34 5 8s1.34 3 3 3zm0 2c-2.33 0-7 1.17-7 3.5V19h14v-2.5c0-2.33-4.67-3.5-7-3.5zm8 0c-.29 0-.62.02-.97.05 1.16.84 1.97 1.97 1.97 3.45V19h6v-2.5c0-2.33-4.67-3.5-7-3.5z"/></svg>
                <h2>Community</h2>
                <a href="https://symfony.com/community">
                    Connect, get help, or contribute
                </a>
            </div>
        </div>
    </div>
</div>
</body>
</html>
<?php 
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\HttpKernel;

use _ContaoManager\Symfony\Component\HttpFoundation\Exception\RequestExceptionInterface;
use _ContaoManager\Symfony\Component\HttpFoundation\Request;
use _ContaoManager\Symfony\Component\HttpFoundation\RequestStack;
use _ContaoManager\Symfony\Component\HttpFoundation\Response;
use _ContaoManager\Symfony\Component\HttpFoundation\StreamedResponse;
use _ContaoManager\Symfony\Component\HttpKernel\Controller\ArgumentResolver;
use _ContaoManager\Symfony\Component\HttpKernel\Controller\ArgumentResolverInterface;
use _ContaoManager\Symfony\Component\HttpKernel\Controller\ControllerResolverInterface;
use _ContaoManager\Symfony\Component\HttpKernel\Event\ControllerArgumentsEvent;
use _ContaoManager\Symfony\Component\HttpKernel\Event\ControllerEvent;
use _ContaoManager\Symfony\Component\HttpKernel\Event\ExceptionEvent;
use _ContaoManager\Symfony\Component\HttpKernel\Event\FinishRequestEvent;
use _ContaoManager\Symfony\Component\HttpKernel\Event\RequestEvent;
use _ContaoManager\Symfony\Component\HttpKernel\Event\ResponseEvent;
use _ContaoManager\Symfony\Component\HttpKernel\Event\TerminateEvent;
use _ContaoManager\Symfony\Component\HttpKernel\Event\ViewEvent;
use _ContaoManager\Symfony\Component\HttpKernel\Exception\BadRequestHttpException;
use _ContaoManager\Symfony\Component\HttpKernel\Exception\ControllerDoesNotReturnResponseException;
use _ContaoManager\Symfony\Component\HttpKernel\Exception\HttpExceptionInterface;
use _ContaoManager\Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
use _ContaoManager\Symfony\Contracts\EventDispatcher\EventDispatcherInterface;
// Help opcache.preload discover always-needed symbols
class_exists(ControllerArgumentsEvent::class);
class_exists(ControllerEvent::class);
class_exists(ExceptionEvent::class);
class_exists(FinishRequestEvent::class);
class_exists(RequestEvent::class);
class_exists(ResponseEvent::class);
class_exists(TerminateEvent::class);
class_exists(ViewEvent::class);
class_exists(KernelEvents::class);
/**
 * HttpKernel notifies events to convert a Request object to a Response one.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class HttpKernel implements HttpKernelInterface, TerminableInterface
{
    protected $dispatcher;
    protected $resolver;
    protected $requestStack;
    private ArgumentResolverInterface $argumentResolver;
    private bool $handleAllThrowables;
    public function __construct(EventDispatcherInterface $dispatcher, ControllerResolverInterface $resolver, ?RequestStack $requestStack = null, ?ArgumentResolverInterface $argumentResolver = null, bool $handleAllThrowables = \false)
    {
        $this->dispatcher = $dispatcher;
        $this->resolver = $resolver;
        $this->requestStack = $requestStack ?? new RequestStack();
        $this->argumentResolver = $argumentResolver ?? new ArgumentResolver();
        $this->handleAllThrowables = $handleAllThrowables;
    }
    public function handle(Request $request, int $type = HttpKernelInterface::MAIN_REQUEST, bool $catch = \true): Response
    {
        $request->headers->set('X-Php-Ob-Level', (string) ob_get_level());
        $this->requestStack->push($request);
        $response = null;
        try {
            return $response = $this->handleRaw($request, $type);
        } catch (\Throwable $e) {
            if ($e instanceof \Error && !$this->handleAllThrowables) {
                throw $e;
            }
            if ($e instanceof RequestExceptionInterface) {
                $e = new BadRequestHttpException($e->getMessage(), $e);
            }
            if (\false === $catch) {
                $this->finishRequest($request, $type);
                throw $e;
            }
            return $response = $this->handleThrowable($e, $request, $type);
        } finally {
            $this->requestStack->pop();
            if ($response instanceof StreamedResponse && $callback = $response->getCallback()) {
                $requestStack = $this->requestStack;
                $response->setCallback(static function () use ($request, $callback, $requestStack) {
                    $requestStack->push($request);
                    try {
                        $callback();
                    } finally {
                        $requestStack->pop();
                    }
                });
            }
        }
    }
    /**
     * @return void
     */
    public function terminate(Request $request, Response $response)
    {
        $this->dispatcher->dispatch(new TerminateEvent($this, $request, $response), KernelEvents::TERMINATE);
    }
    /**
     * @internal
     */
    public function terminateWithException(\Throwable $exception, ?Request $request = null): void
    {
        if (!$request ??= $this->requestStack->getMainRequest()) {
            throw $exception;
        }
        if ($pop = $request !== $this->requestStack->getMainRequest()) {
            $this->requestStack->push($request);
        }
        try {
            $response = $this->handleThrowable($exception, $request, self::MAIN_REQUEST);
        } finally {
            if ($pop) {
                $this->requestStack->pop();
            }
        }
        $response->sendHeaders();
        $response->sendContent();
        $this->terminate($request, $response);
    }
    /**
     * Handles a request to convert it to a response.
     *
     * Exceptions are not caught.
     *
     * @throws \LogicException       If one of the listener does not behave as expected
     * @throws NotFoundHttpException When controller cannot be found
     */
    private function handleRaw(Request $request, int $type = self::MAIN_REQUEST): Response
    {
        // request
        $event = new RequestEvent($this, $request, $type);
        $this->dispatcher->dispatch($event, KernelEvents::REQUEST);
        if ($event->hasResponse()) {
            return $this->filterResponse($event->getResponse(), $request, $type);
        }
        // load controller
        if (\false === $controller = $this->resolver->getController($request)) {
            throw new NotFoundHttpException(\sprintf('Unable to find the controller for path "%s". The route is wrongly configured.', $request->getPathInfo()));
        }
        $event = new ControllerEvent($this, $controller, $request, $type);
        $this->dispatcher->dispatch($event, KernelEvents::CONTROLLER);
        $controller = $event->getController();
        // controller arguments
        $arguments = $this->argumentResolver->getArguments($request, $controller, $event->getControllerReflector());
        $event = new ControllerArgumentsEvent($this, $event, $arguments, $request, $type);
        $this->dispatcher->dispatch($event, KernelEvents::CONTROLLER_ARGUMENTS);
        $controller = $event->getController();
        $arguments = $event->getArguments();
        // call controller
        $response = $controller(...$arguments);
        // view
        if (!$response instanceof Response) {
            $event = new ViewEvent($this, $request, $type, $response, $event);
            $this->dispatcher->dispatch($event, KernelEvents::VIEW);
            if ($event->hasResponse()) {
                $response = $event->getResponse();
            } else {
                $msg = \sprintf('The controller must return a "Symfony\Component\HttpFoundation\Response" object but it returned %s.', $this->varToString($response));
                // the user may have forgotten to return something
                if (null === $response) {
                    $msg .= ' Did you forget to add a return statement somewhere in your controller?';
                }
                throw new ControllerDoesNotReturnResponseException($msg, $controller, __FILE__, __LINE__ - 17);
            }
        }
        return $this->filterResponse($response, $request, $type);
    }
    /**
     * Filters a response object.
     *
     * @throws \RuntimeException if the passed object is not a Response instance
     */
    private function filterResponse(Response $response, Request $request, int $type): Response
    {
        $event = new ResponseEvent($this, $request, $type, $response);
        $this->dispatcher->dispatch($event, KernelEvents::RESPONSE);
        $this->finishRequest($request, $type);
        return $event->getResponse();
    }
    /**
     * Publishes the finish request event, then pop the request from the stack.
     *
     * Note that the order of the operations is important here, otherwise
     * operations such as {@link RequestStack::getParentRequest()} can lead to
     * weird results.
     */
    private function finishRequest(Request $request, int $type): void
    {
        $this->dispatcher->dispatch(new FinishRequestEvent($this, $request, $type), KernelEvents::FINISH_REQUEST);
    }
    /**
     * Handles a throwable by trying to convert it to a Response.
     */
    private function handleThrowable(\Throwable $e, Request $request, int $type): Response
    {
        $event = new ExceptionEvent($this, $request, $type, $e);
        $this->dispatcher->dispatch($event, KernelEvents::EXCEPTION);
        // a listener might have replaced the exception
        $e = $event->getThrowable();
        if (!$event->hasResponse()) {
            $this->finishRequest($request, $type);
            throw $e;
        }
        $response = $event->getResponse();
        // the developer asked for a specific status code
        if (!$event->isAllowingCustomResponseCode() && !$response->isClientError() && !$response->isServerError() && !$response->isRedirect()) {
            // ensure that we actually have an error response
            if ($e instanceof HttpExceptionInterface) {
                // keep the HTTP status code and headers
                $response->setStatusCode($e->getStatusCode());
                $response->headers->add($e->getHeaders());
            } else {
                $response->setStatusCode(500);
            }
        }
        try {
            return $this->filterResponse($response, $request, $type);
        } catch (\Throwable $e) {
            if ($e instanceof \Error && !$this->handleAllThrowables) {
                throw $e;
            }
            return $response;
        }
    }
    /**
     * Returns a human-readable string for the specified variable.
     */
    private function varToString(mixed $var): string
    {
        if (\is_object($var)) {
            return \sprintf('an object of type %s', $var::class);
        }
        if (\is_array($var)) {
            $a = [];
            foreach ($var as $k => $v) {
                $a[] = \sprintf('%s => ...', $k);
            }
            return \sprintf('an array ([%s])', mb_substr(implode(', ', $a), 0, 255));
        }
        if (\is_resource($var)) {
            return \sprintf('a resource (%s)', get_resource_type($var));
        }
        if (null === $var) {
            return 'null';
        }
        if (\false === $var) {
            return 'a boolean value (false)';
        }
        if (\true === $var) {
            return 'a boolean value (true)';
        }
        if (\is_string($var)) {
            return \sprintf('a string ("%s%s")', mb_substr($var, 0, 255), mb_strlen($var) > 255 ? '...' : '');
        }
        if (is_numeric($var)) {
            return \sprintf('a number (%s)', (string) $var);
        }
        return (string) $var;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\HttpKernel\CacheWarmer;

use _ContaoManager\Symfony\Component\Console\Style\SymfonyStyle;
/**
 * Aggregates several cache warmers into a single one.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 *
 * @final
 */
class CacheWarmerAggregate implements CacheWarmerInterface
{
    private iterable $warmers;
    private bool $debug;
    private ?string $deprecationLogsFilepath;
    private bool $optionalsEnabled = \false;
    private bool $onlyOptionalsEnabled = \false;
    /**
     * @param iterable<mixed, CacheWarmerInterface> $warmers
     */
    public function __construct(iterable $warmers = [], bool $debug = \false, ?string $deprecationLogsFilepath = null)
    {
        $this->warmers = $warmers;
        $this->debug = $debug;
        $this->deprecationLogsFilepath = $deprecationLogsFilepath;
    }
    public function enableOptionalWarmers(): void
    {
        $this->optionalsEnabled = \true;
    }
    public function enableOnlyOptionalWarmers(): void
    {
        $this->onlyOptionalsEnabled = $this->optionalsEnabled = \true;
    }
    /**
     * @param string|null $buildDir
     */
    public function warmUp(string $cacheDir, string|SymfonyStyle|null $buildDir = null, ?SymfonyStyle $io = null): array
    {
        if ($buildDir instanceof SymfonyStyle) {
            trigger_deprecation('symfony/http-kernel', '6.4', 'Passing a "%s" as second argument of "%s()" is deprecated, pass it as third argument instead, after the build directory.', SymfonyStyle::class, __METHOD__);
            $io = $buildDir;
            $buildDir = null;
        }
        if ($collectDeprecations = $this->debug && !\defined('PHPUNIT_COMPOSER_INSTALL')) {
            $collectedLogs = [];
            $previousHandler = set_error_handler(function ($type, $message, $file, $line) use (&$collectedLogs, &$previousHandler) {
                if (\E_USER_DEPRECATED !== $type && \E_DEPRECATED !== $type) {
                    return $previousHandler ? $previousHandler($type, $message, $file, $line) : \false;
                }
                if (isset($collectedLogs[$message])) {
                    ++$collectedLogs[$message]['count'];
                    return null;
                }
                $backtrace = debug_backtrace(\DEBUG_BACKTRACE_IGNORE_ARGS, 3);
                // Clean the trace by removing first frames added by the error handler itself.
                for ($i = 0; isset($backtrace[$i]); ++$i) {
                    if (isset($backtrace[$i]['file'], $backtrace[$i]['line']) && $backtrace[$i]['line'] === $line && $backtrace[$i]['file'] === $file) {
                        $backtrace = \array_slice($backtrace, 1 + $i);
                        break;
                    }
                }
                $collectedLogs[$message] = ['type' => $type, 'message' => $message, 'file' => $file, 'line' => $line, 'trace' => $backtrace, 'count' => 1];
                return null;
            });
        }
        $preload = [];
        try {
            foreach ($this->warmers as $warmer) {
                if (!$this->optionalsEnabled && $warmer->isOptional()) {
                    continue;
                }
                if ($this->onlyOptionalsEnabled && !$warmer->isOptional()) {
                    continue;
                }
                $start = microtime(\true);
                foreach ((array) $warmer->warmUp($cacheDir, $buildDir) as $item) {
                    if (is_dir($item) || str_starts_with($item, \dirname($cacheDir)) && !is_file($item) || $buildDir && str_starts_with($item, \dirname($buildDir)) && !is_file($item)) {
                        throw new \LogicException(\sprintf('"%s::warmUp()" should return a list of files or classes but "%s" is none of them.', $warmer::class, $item));
                    }
                    $preload[] = $item;
                }
                if ($io?->isDebug()) {
                    $io->info(\sprintf('"%s" completed in %0.2fms.', $warmer::class, 1000 * (microtime(\true) - $start)));
                }
            }
        } finally {
            if ($collectDeprecations) {
                restore_error_handler();
                if (is_file($this->deprecationLogsFilepath)) {
                    $previousLogs = unserialize(file_get_contents($this->deprecationLogsFilepath));
                    if (\is_array($previousLogs)) {
                        $collectedLogs = array_merge($previousLogs, $collectedLogs);
                    }
                }
                file_put_contents($this->deprecationLogsFilepath, serialize(array_values($collectedLogs)));
            }
        }
        return array_values(array_unique($preload));
    }
    public function isOptional(): bool
    {
        return \false;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\HttpKernel\CacheWarmer;

/**
 * Abstract cache warmer that knows how to write a file to the cache.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
abstract class CacheWarmer implements CacheWarmerInterface
{
    /**
     * @return void
     */
    protected function writeCacheFile(string $file, $content)
    {
        $tmpFile = @tempnam(\dirname($file), basename($file));
        if (\false !== @file_put_contents($tmpFile, $content) && @rename($tmpFile, $file)) {
            @chmod($file, 0666 & ~umask());
            return;
        }
        throw new \RuntimeException(\sprintf('Failed to write cache file "%s".', $file));
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\HttpKernel\CacheWarmer;

/**
 * Interface for classes that support warming their cache.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
interface WarmableInterface
{
    /**
     * Warms up the cache.
     *
     * @param string      $cacheDir Where warm-up artifacts should be stored
     * @param string|null $buildDir Where read-only artifacts should go; null when called after compile-time
     *
     * @return string[] A list of classes or files to preload on PHP 7.4+
     */
    public function warmUp(string $cacheDir);
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\HttpKernel\CacheWarmer;

/**
 * Interface for classes able to warm up the cache.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
interface CacheWarmerInterface extends WarmableInterface
{
    /**
     * Checks whether this warmer is optional or not.
     *
     * Optional warmers can be ignored on certain conditions.
     *
     * A warmer should return true if the cache can be
     * generated incrementally and on-demand.
     *
     * @return bool
     */
    public function isOptional();
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\HttpKernel\Bundle;

use _ContaoManager\Symfony\Component\Console\Application;
use _ContaoManager\Symfony\Component\DependencyInjection\Container;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerBuilder;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Extension\ExtensionInterface;
/**
 * An implementation of BundleInterface that adds a few conventions for DependencyInjection extensions.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
abstract class Bundle implements BundleInterface
{
    protected $name;
    protected $extension;
    protected $path;
    private string $namespace;
    /**
     * @var ContainerInterface|null
     */
    protected $container;
    /**
     * @return void
     */
    public function boot()
    {
    }
    /**
     * @return void
     */
    public function shutdown()
    {
    }
    /**
     * This method can be overridden to register compilation passes,
     * other extensions, ...
     *
     * @return void
     */
    public function build(ContainerBuilder $container)
    {
    }
    /**
     * Returns the bundle's container extension.
     *
     * @throws \LogicException
     */
    public function getContainerExtension(): ?ExtensionInterface
    {
        if (!isset($this->extension)) {
            $extension = $this->createContainerExtension();
            if (null !== $extension) {
                if (!$extension instanceof ExtensionInterface) {
                    throw new \LogicException(\sprintf('Extension "%s" must implement Symfony\Component\DependencyInjection\Extension\ExtensionInterface.', get_debug_type($extension)));
                }
                // check naming convention
                $basename = preg_replace('/Bundle$/', '', $this->getName());
                $expectedAlias = Container::underscore($basename);
                if ($expectedAlias != $extension->getAlias()) {
                    throw new \LogicException(\sprintf('Users will expect the alias of the default extension of a bundle to be the underscored version of the bundle name ("%s"). You can override "Bundle::getContainerExtension()" if you want to use "%s" or another alias.', $expectedAlias, $extension->getAlias()));
                }
                $this->extension = $extension;
            } else {
                $this->extension = \false;
            }
        }
        return $this->extension ?: null;
    }
    public function getNamespace(): string
    {
        if (!isset($this->namespace)) {
            $this->parseClassName();
        }
        return $this->namespace;
    }
    public function getPath(): string
    {
        if (!isset($this->path)) {
            $reflected = new \ReflectionObject($this);
            $this->path = \dirname($reflected->getFileName());
        }
        return $this->path;
    }
    /**
     * Returns the bundle name (the class short name).
     */
    final public function getName(): string
    {
        if (!isset($this->name)) {
            $this->parseClassName();
        }
        return $this->name;
    }
    /**
     * @return void
     */
    public function registerCommands(Application $application)
    {
    }
    /**
     * Returns the bundle's container extension class.
     */
    protected function getContainerExtensionClass(): string
    {
        $basename = preg_replace('/Bundle$/', '', $this->getName());
        return $this->getNamespace() . '\DependencyInjection\\' . $basename . 'Extension';
    }
    /**
     * Creates the bundle's container extension.
     */
    protected function createContainerExtension(): ?ExtensionInterface
    {
        return class_exists($class = $this->getContainerExtensionClass()) ? new $class() : null;
    }
    private function parseClassName(): void
    {
        $pos = strrpos(static::class, '\\');
        $this->namespace = \false === $pos ? '' : substr(static::class, 0, $pos);
        $this->name ??= \false === $pos ? static::class : substr(static::class, $pos + 1);
    }
    public function setContainer(?ContainerInterface $container): void
    {
        $this->container = $container;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\HttpKernel\Bundle;

use _ContaoManager\Symfony\Component\DependencyInjection\ContainerBuilder;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Extension\ExtensionInterface;
/**
 * BundleInterface.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
interface BundleInterface
{
    /**
     * Boots the Bundle.
     *
     * @return void
     */
    public function boot();
    /**
     * Shutdowns the Bundle.
     *
     * @return void
     */
    public function shutdown();
    /**
     * Builds the bundle.
     *
     * It is only ever called once when the cache is empty.
     *
     * @return void
     */
    public function build(ContainerBuilder $container);
    /**
     * Returns the container extension that should be implicitly loaded.
     */
    public function getContainerExtension(): ?ExtensionInterface;
    /**
     * Returns the bundle name (the class short name).
     */
    public function getName(): string;
    /**
     * Gets the Bundle namespace.
     */
    public function getNamespace(): string;
    /**
     * Gets the Bundle directory path.
     *
     * The path should always be returned as a Unix path (with /).
     */
    public function getPath(): string;
    /**
     * @return void
     */
    public function setContainer(?ContainerInterface $container);
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\HttpKernel\Bundle;

use _ContaoManager\Symfony\Component\Config\Definition\Configurator\DefinitionConfigurator;
use _ContaoManager\Symfony\Component\DependencyInjection\Container;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerBuilder;
use _ContaoManager\Symfony\Component\DependencyInjection\Extension\ConfigurableExtensionInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Extension\ExtensionInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;
/**
 * A Bundle that provides configuration hooks.
 *
 * @author Yonel Ceruto <yonelceruto@gmail.com>
 */
abstract class AbstractBundle extends Bundle implements ConfigurableExtensionInterface
{
    protected string $extensionAlias = '';
    public function configure(DefinitionConfigurator $definition): void
    {
    }
    public function prependExtension(ContainerConfigurator $container, ContainerBuilder $builder): void
    {
    }
    public function loadExtension(array $config, ContainerConfigurator $container, ContainerBuilder $builder): void
    {
    }
    public function getContainerExtension(): ?ExtensionInterface
    {
        if ('' === $this->extensionAlias) {
            $this->extensionAlias = Container::underscore(preg_replace('/Bundle$/', '', $this->getName()));
        }
        return $this->extension ??= new BundleExtension($this, $this->extensionAlias);
    }
    public function getPath(): string
    {
        if (null === $this->path) {
            $reflected = new \ReflectionObject($this);
            // assume the modern directory structure by default
            $this->path = \dirname($reflected->getFileName(), 2);
        }
        return $this->path;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\HttpKernel\Bundle;

use _ContaoManager\Symfony\Component\Config\Definition\Configuration;
use _ContaoManager\Symfony\Component\Config\Definition\ConfigurationInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerBuilder;
use _ContaoManager\Symfony\Component\DependencyInjection\Extension\ConfigurableExtensionInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Extension\Extension;
use _ContaoManager\Symfony\Component\DependencyInjection\Extension\ExtensionTrait;
use _ContaoManager\Symfony\Component\DependencyInjection\Extension\PrependExtensionInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;
/**
 * @author Yonel Ceruto <yonelceruto@gmail.com>
 *
 * @internal
 */
class BundleExtension extends Extension implements PrependExtensionInterface
{
    use ExtensionTrait;
    public function __construct(private ConfigurableExtensionInterface $subject, private string $alias)
    {
    }
    public function getConfiguration(array $config, ContainerBuilder $container): ?ConfigurationInterface
    {
        return new Configuration($this->subject, $container, $this->getAlias());
    }
    public function getAlias(): string
    {
        return $this->alias;
    }
    public function prepend(ContainerBuilder $container): void
    {
        $callback = function (ContainerConfigurator $configurator) use ($container) {
            $this->subject->prependExtension($configurator, $container);
        };
        $this->executeConfiguratorCallback($container, $callback, $this->subject);
    }
    public function load(array $configs, ContainerBuilder $container): void
    {
        $config = $this->processConfiguration($this->getConfiguration([], $container), $configs);
        $callback = function (ContainerConfigurator $configurator) use ($config, $container) {
            $this->subject->loadExtension($config, $configurator, $container);
        };
        $this->executeConfiguratorCallback($container, $callback, $this->subject);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\HttpKernel;

use _ContaoManager\Symfony\Component\Config\Loader\LoaderInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerInterface;
use _ContaoManager\Symfony\Component\HttpKernel\Bundle\BundleInterface;
/**
 * The Kernel is the heart of the Symfony system.
 *
 * It manages an environment made of application kernel and bundles.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
interface KernelInterface extends HttpKernelInterface
{
    /**
     * Returns an array of bundles to register.
     *
     * @return iterable<mixed, BundleInterface>
     */
    public function registerBundles(): iterable;
    /**
     * Loads the container configuration.
     *
     * @return void
     */
    public function registerContainerConfiguration(LoaderInterface $loader);
    /**
     * Boots the current kernel.
     *
     * @return void
     */
    public function boot();
    /**
     * Shutdowns the kernel.
     *
     * This method is mainly useful when doing functional testing.
     *
     * @return void
     */
    public function shutdown();
    /**
     * Gets the registered bundle instances.
     *
     * @return array<string, BundleInterface>
     */
    public function getBundles(): array;
    /**
     * Returns a bundle.
     *
     * @throws \InvalidArgumentException when the bundle is not enabled
     */
    public function getBundle(string $name): BundleInterface;
    /**
     * Returns the file path for a given bundle resource.
     *
     * A Resource can be a file or a directory.
     *
     * The resource name must follow the following pattern:
     *
     *     "@BundleName/path/to/a/file.something"
     *
     * where BundleName is the name of the bundle
     * and the remaining part is the relative path in the bundle.
     *
     * @throws \InvalidArgumentException if the file cannot be found or the name is not valid
     * @throws \RuntimeException         if the name contains invalid/unsafe characters
     */
    public function locateResource(string $name): string;
    /**
     * Gets the environment.
     */
    public function getEnvironment(): string;
    /**
     * Checks if debug mode is enabled.
     */
    public function isDebug(): bool;
    /**
     * Gets the project dir (path of the project's composer file).
     */
    public function getProjectDir(): string;
    /**
     * Gets the current container.
     */
    public function getContainer(): ContainerInterface;
    /**
     * Gets the request start time (not available if debug is disabled).
     */
    public function getStartTime(): float;
    /**
     * Gets the cache directory.
     *
     * Since Symfony 5.2, the cache directory should be used for caches that are written at runtime.
     * For caches and artifacts that can be warmed at compile-time and deployed as read-only,
     * use the new "build directory" returned by the {@see getBuildDir()} method.
     */
    public function getCacheDir(): string;
    /**
     * Returns the build directory.
     *
     * This directory should be used to store build artifacts, and can be read-only at runtime.
     * Caches written at runtime should be stored in the "cache directory" ({@see KernelInterface::getCacheDir()}).
     */
    public function getBuildDir(): string;
    /**
     * Gets the log directory.
     */
    public function getLogDir(): string;
    /**
     * Gets the charset of the application.
     */
    public function getCharset(): string;
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\HttpKernel\Controller;

use _ContaoManager\Psr\Container\ContainerInterface;
use _ContaoManager\Symfony\Component\HttpFoundation\Request;
use _ContaoManager\Symfony\Component\HttpKernel\Attribute\ValueResolver;
use _ContaoManager\Symfony\Component\HttpKernel\Controller\ArgumentResolver\DefaultValueResolver;
use _ContaoManager\Symfony\Component\HttpKernel\Controller\ArgumentResolver\RequestAttributeValueResolver;
use _ContaoManager\Symfony\Component\HttpKernel\Controller\ArgumentResolver\RequestValueResolver;
use _ContaoManager\Symfony\Component\HttpKernel\Controller\ArgumentResolver\SessionValueResolver;
use _ContaoManager\Symfony\Component\HttpKernel\Controller\ArgumentResolver\TraceableValueResolver;
use _ContaoManager\Symfony\Component\HttpKernel\Controller\ArgumentResolver\VariadicValueResolver;
use _ContaoManager\Symfony\Component\HttpKernel\ControllerMetadata\ArgumentMetadataFactory;
use _ContaoManager\Symfony\Component\HttpKernel\ControllerMetadata\ArgumentMetadataFactoryInterface;
use _ContaoManager\Symfony\Component\HttpKernel\Exception\ResolverNotFoundException;
use _ContaoManager\Symfony\Contracts\Service\ServiceProviderInterface;
/**
 * Responsible for resolving the arguments passed to an action.
 *
 * @author Iltar van der Berg <kjarli@gmail.com>
 */
final class ArgumentResolver implements ArgumentResolverInterface
{
    private ArgumentMetadataFactoryInterface $argumentMetadataFactory;
    private iterable $argumentValueResolvers;
    private ?ContainerInterface $namedResolvers;
    /**
     * @param iterable<mixed, ArgumentValueResolverInterface|ValueResolverInterface> $argumentValueResolvers
     */
    public function __construct(?ArgumentMetadataFactoryInterface $argumentMetadataFactory = null, iterable $argumentValueResolvers = [], ?ContainerInterface $namedResolvers = null)
    {
        $this->argumentMetadataFactory = $argumentMetadataFactory ?? new ArgumentMetadataFactory();
        $this->argumentValueResolvers = $argumentValueResolvers ?: self::getDefaultArgumentValueResolvers();
        $this->namedResolvers = $namedResolvers;
    }
    public function getArguments(Request $request, callable $controller, ?\ReflectionFunctionAbstract $reflector = null): array
    {
        $arguments = [];
        foreach ($this->argumentMetadataFactory->createArgumentMetadata($controller, $reflector) as $metadata) {
            $argumentValueResolvers = $this->argumentValueResolvers;
            $disabledResolvers = [];
            if ($this->namedResolvers && $attributes = $metadata->getAttributesOfType(ValueResolver::class, $metadata::IS_INSTANCEOF)) {
                $resolverName = null;
                foreach ($attributes as $attribute) {
                    if ($attribute->disabled) {
                        $disabledResolvers[$attribute->resolver] = \true;
                    } elseif ($resolverName) {
                        throw new \LogicException(\sprintf('You can only pin one resolver per argument, but argument "$%s" of "%s()" has more.', $metadata->getName(), $this->getPrettyName($controller)));
                    } else {
                        $resolverName = $attribute->resolver;
                    }
                }
                if ($resolverName) {
                    if (!$this->namedResolvers->has($resolverName)) {
                        throw new ResolverNotFoundException($resolverName, $this->namedResolvers instanceof ServiceProviderInterface ? array_keys($this->namedResolvers->getProvidedServices()) : []);
                    }
                    $argumentValueResolvers = [$this->namedResolvers->get($resolverName), new RequestAttributeValueResolver(), new DefaultValueResolver()];
                }
            }
            foreach ($argumentValueResolvers as $name => $resolver) {
                if ((!$resolver instanceof ValueResolverInterface || $resolver instanceof TraceableValueResolver) && !$resolver->supports($request, $metadata)) {
                    continue;
                }
                if (isset($disabledResolvers[\is_int($name) ? $resolver::class : $name])) {
                    continue;
                }
                $count = 0;
                foreach ($resolver->resolve($request, $metadata) as $argument) {
                    ++$count;
                    $arguments[] = $argument;
                }
                if (1 < $count && !$metadata->isVariadic()) {
                    throw new \InvalidArgumentException(\sprintf('"%s::resolve()" must yield at most one value for non-variadic arguments.', get_debug_type($resolver)));
                }
                if ($count) {
                    // continue to the next controller argument
                    continue 2;
                }
                if (!$resolver instanceof ValueResolverInterface) {
                    throw new \InvalidArgumentException(\sprintf('"%s::resolve()" must yield at least one value.', get_debug_type($resolver)));
                }
            }
            throw new \RuntimeException(\sprintf('Controller "%s" requires that you provide a value for the "$%s" argument. Either the argument is nullable and no null value has been provided, no default value has been provided or there is a non-optional argument after this one.', $this->getPrettyName($controller), $metadata->getName()));
        }
        return $arguments;
    }
    /**
     * @return iterable<int, ArgumentValueResolverInterface>
     */
    public static function getDefaultArgumentValueResolvers(): iterable
    {
        return [new RequestAttributeValueResolver(), new RequestValueResolver(), new SessionValueResolver(), new DefaultValueResolver(), new VariadicValueResolver()];
    }
    private function getPrettyName($controller): string
    {
        if (\is_array($controller)) {
            if (\is_object($controller[0])) {
                $controller[0] = get_debug_type($controller[0]);
            }
            return $controller[0] . '::' . $controller[1];
        }
        if (\is_object($controller)) {
            return get_debug_type($controller);
        }
        return $controller;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\HttpKernel\Controller;

use _ContaoManager\Symfony\Component\HttpKernel\Fragment\FragmentRendererInterface;
/**
 * Acts as a marker and a data holder for a Controller.
 *
 * Some methods in Symfony accept both a URI (as a string) or a controller as
 * an argument. In the latter case, instead of passing an array representing
 * the controller, you can use an instance of this class.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 *
 * @see FragmentRendererInterface
 */
class ControllerReference
{
    public $controller;
    public $attributes = [];
    public $query = [];
    /**
     * @param string $controller The controller name
     * @param array  $attributes An array of parameters to add to the Request attributes
     * @param array  $query      An array of parameters to add to the Request query string
     */
    public function __construct(string $controller, array $attributes = [], array $query = [])
    {
        $this->controller = $controller;
        $this->attributes = $attributes;
        $this->query = $query;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\HttpKernel\Controller;

use _ContaoManager\Symfony\Component\ErrorHandler\ErrorRenderer\ErrorRendererInterface;
use _ContaoManager\Symfony\Component\HttpFoundation\Request;
use _ContaoManager\Symfony\Component\HttpFoundation\Response;
use _ContaoManager\Symfony\Component\HttpKernel\Exception\HttpException;
use _ContaoManager\Symfony\Component\HttpKernel\HttpKernelInterface;
/**
 * Renders error or exception pages from a given FlattenException.
 *
 * @author Yonel Ceruto <yonelceruto@gmail.com>
 * @author Matthias Pigulla <mp@webfactory.de>
 */
class ErrorController
{
    private HttpKernelInterface $kernel;
    private string|object|array|null $controller;
    private ErrorRendererInterface $errorRenderer;
    public function __construct(HttpKernelInterface $kernel, string|object|array|null $controller, ErrorRendererInterface $errorRenderer)
    {
        $this->kernel = $kernel;
        $this->controller = $controller;
        $this->errorRenderer = $errorRenderer;
    }
    public function __invoke(\Throwable $exception): Response
    {
        $exception = $this->errorRenderer->render($exception);
        return new Response($exception->getAsString(), $exception->getStatusCode(), $exception->getHeaders());
    }
    public function preview(Request $request, int $code): Response
    {
        /*
         * This Request mimics the parameters set by
         * \Symfony\Component\HttpKernel\EventListener\ErrorListener::duplicateRequest, with
         * the additional "showException" flag.
         */
        $subRequest = $request->duplicate(null, null, ['_controller' => $this->controller, 'exception' => new HttpException($code, 'This is a sample exception.'), 'logger' => null, 'showException' => \false]);
        return $this->kernel->handle($subRequest, HttpKernelInterface::SUB_REQUEST);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\HttpKernel\Controller;

use _ContaoManager\Psr\Container\ContainerInterface;
use _ContaoManager\Psr\Log\LoggerInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Container;
/**
 * A controller resolver searching for a controller in a psr-11 container when using the "service::method" notation.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 * @author Maxime Steinhausser <maxime.steinhausser@gmail.com>
 */
class ContainerControllerResolver extends ControllerResolver
{
    protected $container;
    public function __construct(ContainerInterface $container, ?LoggerInterface $logger = null)
    {
        $this->container = $container;
        parent::__construct($logger);
    }
    protected function instantiateController(string $class): object
    {
        $class = ltrim($class, '\\');
        if ($this->container->has($class)) {
            return $this->container->get($class);
        }
        try {
            return parent::instantiateController($class);
        } catch (\Error $e) {
        }
        $this->throwExceptionIfControllerWasRemoved($class, $e);
        if ($e instanceof \ArgumentCountError) {
            throw new \InvalidArgumentException(\sprintf('Controller "%s" has required constructor arguments and does not exist in the container. Did you forget to define the controller as a service?', $class), 0, $e);
        }
        throw new \InvalidArgumentException(\sprintf('Controller "%s" does neither exist as service nor as class.', $class), 0, $e);
    }
    private function throwExceptionIfControllerWasRemoved(string $controller, \Throwable $previous): void
    {
        if ($this->container instanceof Container && isset($this->container->getRemovedIds()[$controller])) {
            throw new \InvalidArgumentException(\sprintf('Controller "%s" cannot be fetched from the container because it is private. Did you forget to tag the service with "controller.service_arguments"?', $controller), 0, $previous);
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\HttpKernel\Controller\ArgumentResolver;

use _ContaoManager\Symfony\Component\HttpFoundation\Request;
use _ContaoManager\Symfony\Component\HttpKernel\Controller\ArgumentValueResolverInterface;
use _ContaoManager\Symfony\Component\HttpKernel\Controller\ValueResolverInterface;
use _ContaoManager\Symfony\Component\HttpKernel\ControllerMetadata\ArgumentMetadata;
/**
 * Yields a variadic argument's values from the request attributes.
 *
 * @author Iltar van der Berg <kjarli@gmail.com>
 */
final class VariadicValueResolver implements ArgumentValueResolverInterface, ValueResolverInterface
{
    /**
     * @deprecated since Symfony 6.2, use resolve() instead
     */
    public function supports(Request $request, ArgumentMetadata $argument): bool
    {
        @trigger_deprecation('symfony/http-kernel', '6.2', 'The "%s()" method is deprecated, use "resolve()" instead.', __METHOD__);
        return $argument->isVariadic() && $request->attributes->has($argument->getName());
    }
    public function resolve(Request $request, ArgumentMetadata $argument): array
    {
        if (!$argument->isVariadic() || !$request->attributes->has($argument->getName())) {
            return [];
        }
        $values = $request->attributes->get($argument->getName());
        if (!\is_array($values)) {
            throw new \InvalidArgumentException(\sprintf('The action argument "...$%1$s" is required to be an array, the request attribute "%1$s" contains a type of "%2$s" instead.', $argument->getName(), get_debug_type($values)));
        }
        return $values;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\HttpKernel\Controller\ArgumentResolver;

use _ContaoManager\Psr\Container\ContainerInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\RuntimeException;
use _ContaoManager\Symfony\Component\HttpFoundation\Request;
use _ContaoManager\Symfony\Component\HttpKernel\Controller\ArgumentValueResolverInterface;
use _ContaoManager\Symfony\Component\HttpKernel\Controller\ValueResolverInterface;
use _ContaoManager\Symfony\Component\HttpKernel\ControllerMetadata\ArgumentMetadata;
/**
 * Yields a service keyed by _controller and argument name.
 *
 * @author Nicolas Grekas <p@tchwork.com>
 */
final class ServiceValueResolver implements ArgumentValueResolverInterface, ValueResolverInterface
{
    private ContainerInterface $container;
    public function __construct(ContainerInterface $container)
    {
        $this->container = $container;
    }
    /**
     * @deprecated since Symfony 6.2, use resolve() instead
     */
    public function supports(Request $request, ArgumentMetadata $argument): bool
    {
        @trigger_deprecation('symfony/http-kernel', '6.2', 'The "%s()" method is deprecated, use "resolve()" instead.', __METHOD__);
        $controller = $request->attributes->get('_controller');
        if (\is_array($controller) && \is_callable($controller, \true) && \is_string($controller[0])) {
            $controller = $controller[0] . '::' . $controller[1];
        } elseif (!\is_string($controller) || '' === $controller) {
            return \false;
        }
        if ('\\' === $controller[0]) {
            $controller = ltrim($controller, '\\');
        }
        if (!$this->container->has($controller) && \false !== $i = strrpos($controller, ':')) {
            $controller = substr($controller, 0, $i) . strtolower(substr($controller, $i));
        }
        return $this->container->has($controller) && $this->container->get($controller)->has($argument->getName());
    }
    public function resolve(Request $request, ArgumentMetadata $argument): array
    {
        $controller = $request->attributes->get('_controller');
        if (\is_array($controller) && \is_callable($controller, \true) && \is_string($controller[0])) {
            $controller = $controller[0] . '::' . $controller[1];
        } elseif (!\is_string($controller) || '' === $controller) {
            return [];
        }
        if ('\\' === $controller[0]) {
            $controller = ltrim($controller, '\\');
        }
        if (!$this->container->has($controller) && \false !== $i = strrpos($controller, ':')) {
            $controller = substr($controller, 0, $i) . strtolower(substr($controller, $i));
        }
        if (!$this->container->has($controller) || !$this->container->get($controller)->has($argument->getName())) {
            return [];
        }
        try {
            return [$this->container->get($controller)->get($argument->getName())];
        } catch (RuntimeException $e) {
            $what = \sprintf('argument $%s of "%s()"', $argument->getName(), $controller);
            $message = preg_replace('/service "\.service_locator\.[^"]++"/', $what, $e->getMessage());
            if ($e->getMessage() === $message) {
                $message = \sprintf('Cannot resolve %s: %s', $what, $message);
            }
            $r = new \ReflectionProperty($e, 'message');
            $r->setValue($e, $message);
            throw $e;
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\HttpKernel\Controller\ArgumentResolver;

use _ContaoManager\Symfony\Component\HttpFoundation\Request;
use _ContaoManager\Symfony\Component\HttpKernel\Controller\ArgumentValueResolverInterface;
use _ContaoManager\Symfony\Component\HttpKernel\Controller\ValueResolverInterface;
use _ContaoManager\Symfony\Component\HttpKernel\ControllerMetadata\ArgumentMetadata;
/**
 * Yields the default value defined in the action signature when no value has been given.
 *
 * @author Iltar van der Berg <kjarli@gmail.com>
 */
final class DefaultValueResolver implements ArgumentValueResolverInterface, ValueResolverInterface
{
    /**
     * @deprecated since Symfony 6.2, use resolve() instead
     */
    public function supports(Request $request, ArgumentMetadata $argument): bool
    {
        @trigger_deprecation('symfony/http-kernel', '6.2', 'The "%s()" method is deprecated, use "resolve()" instead.', __METHOD__);
        return $argument->hasDefaultValue() || null !== $argument->getType() && $argument->isNullable() && !$argument->isVariadic();
    }
    public function resolve(Request $request, ArgumentMetadata $argument): array
    {
        if ($argument->hasDefaultValue()) {
            return [$argument->getDefaultValue()];
        }
        if (null !== $argument->getType() && $argument->isNullable() && !$argument->isVariadic()) {
            return [null];
        }
        return [];
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\HttpKernel\Controller\ArgumentResolver;

use _ContaoManager\Symfony\Component\HttpFoundation\Request;
use _ContaoManager\Symfony\Component\HttpKernel\Attribute\MapQueryParameter;
use _ContaoManager\Symfony\Component\HttpKernel\Controller\ValueResolverInterface;
use _ContaoManager\Symfony\Component\HttpKernel\ControllerMetadata\ArgumentMetadata;
use _ContaoManager\Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
/**
 * Resolve arguments of type: array, string, int, float, bool, \BackedEnum from query parameters.
 *
 * @author Ruud Kamphuis <ruud@ticketswap.com>
 * @author Nicolas Grekas <p@tchwork.com>
 * @author Mateusz Anders <anders_mateusz@outlook.com>
 */
final class QueryParameterValueResolver implements ValueResolverInterface
{
    public function resolve(Request $request, ArgumentMetadata $argument): array
    {
        if (!$attribute = $argument->getAttributesOfType(MapQueryParameter::class)[0] ?? null) {
            return [];
        }
        $name = $attribute->name ?? $argument->getName();
        if (!$request->query->has($name)) {
            if ($argument->isNullable() || $argument->hasDefaultValue()) {
                return [];
            }
            throw new NotFoundHttpException(\sprintf('Missing query parameter "%s".', $name));
        }
        $value = $request->query->all()[$name];
        $type = $argument->getType();
        if (null === $attribute->filter && 'array' === $type) {
            if (!$argument->isVariadic()) {
                return [(array) $value];
            }
            $filtered = array_values(array_filter((array) $value, \is_array(...)));
            if ($filtered !== $value && !($attribute->flags & \FILTER_NULL_ON_FAILURE)) {
                throw new NotFoundHttpException(\sprintf('Invalid query parameter "%s".', $name));
            }
            return $filtered;
        }
        $options = ['flags' => $attribute->flags | \FILTER_NULL_ON_FAILURE, 'options' => $attribute->options];
        if ('array' === $type || $argument->isVariadic()) {
            $value = (array) $value;
            $options['flags'] |= \FILTER_REQUIRE_ARRAY;
        } else {
            $options['flags'] |= \FILTER_REQUIRE_SCALAR;
        }
        $enumType = null;
        $filter = match ($type) {
            'array' => \FILTER_DEFAULT,
            'string' => \FILTER_DEFAULT,
            'int' => \FILTER_VALIDATE_INT,
            'float' => \FILTER_VALIDATE_FLOAT,
            'bool' => \FILTER_VALIDATE_BOOL,
            default => match ($enumType = is_subclass_of($type, \BackedEnum::class) ? (new \ReflectionEnum($type))->getBackingType()->getName() : null) {
                'int' => \FILTER_VALIDATE_INT,
                'string' => \FILTER_DEFAULT,
                default => throw new \LogicException(\sprintf('#[MapQueryParameter] cannot be used on controller argument "%s$%s" of type "%s"; one of array, string, int, float, bool or \BackedEnum should be used.', $argument->isVariadic() ? '...' : '', $argument->getName(), $type ?? 'mixed')),
            },
        };
        $value = filter_var($value, $attribute->filter ?? $filter, $options);
        if (null !== $enumType && null !== $value) {
            $enumFrom = static function ($value) use ($type) {
                if (!\is_string($value) && !\is_int($value)) {
                    return null;
                }
                try {
                    return $type::from($value);
                } catch (\ValueError) {
                    return null;
                }
            };
            $value = \is_array($value) ? array_map($enumFrom, $value) : $enumFrom($value);
        }
        if (null === $value && !($attribute->flags & \FILTER_NULL_ON_FAILURE)) {
            throw new NotFoundHttpException(\sprintf('Invalid query parameter "%s".', $name));
        }
        if (!\is_array($value)) {
            return [$value];
        }
        $filtered = array_filter($value, static fn($v) => null !== $v);
        if ($argument->isVariadic()) {
            $filtered = array_values($filtered);
        }
        if ($filtered !== $value && !($attribute->flags & \FILTER_NULL_ON_FAILURE)) {
            throw new NotFoundHttpException(\sprintf('Invalid query parameter "%s".', $name));
        }
        return $argument->isVariadic() ? $filtered : [$filtered];
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\HttpKernel\Controller\ArgumentResolver;

use _ContaoManager\Symfony\Component\HttpFoundation\Request;
use _ContaoManager\Symfony\Component\HttpKernel\Controller\ArgumentValueResolverInterface;
use _ContaoManager\Symfony\Component\HttpKernel\Controller\ValueResolverInterface;
use _ContaoManager\Symfony\Component\HttpKernel\ControllerMetadata\ArgumentMetadata;
use _ContaoManager\Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
use _ContaoManager\Symfony\Component\Uid\AbstractUid;
final class UidValueResolver implements ArgumentValueResolverInterface, ValueResolverInterface
{
    /**
     * @deprecated since Symfony 6.2, use resolve() instead
     */
    public function supports(Request $request, ArgumentMetadata $argument): bool
    {
        @trigger_deprecation('symfony/http-kernel', '6.2', 'The "%s()" method is deprecated, use "resolve()" instead.', __METHOD__);
        return !$argument->isVariadic() && \is_string($request->attributes->get($argument->getName())) && null !== $argument->getType() && is_subclass_of($argument->getType(), AbstractUid::class, \true);
    }
    public function resolve(Request $request, ArgumentMetadata $argument): array
    {
        if ($argument->isVariadic() || !\is_string($value = $request->attributes->get($argument->getName())) || null === ($uidClass = $argument->getType()) || !is_subclass_of($uidClass, AbstractUid::class, \true)) {
            return [];
        }
        try {
            return [$uidClass::fromString($value)];
        } catch (\InvalidArgumentException $e) {
            throw new NotFoundHttpException(\sprintf('The uid for the "%s" parameter is invalid.', $argument->getName()), $e);
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\HttpKernel\Controller\ArgumentResolver;

use _ContaoManager\Symfony\Component\HttpFoundation\Request;
use _ContaoManager\Symfony\Component\HttpKernel\Controller\ArgumentValueResolverInterface;
use _ContaoManager\Symfony\Component\HttpKernel\Controller\ValueResolverInterface;
use _ContaoManager\Symfony\Component\HttpKernel\ControllerMetadata\ArgumentMetadata;
use _ContaoManager\Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
/**
 * Attempt to resolve backed enum cases from request attributes, for a route path parameter,
 * leading to a 404 Not Found if the attribute value isn't a valid backing value for the enum type.
 *
 * @author Maxime Steinhausser <maxime.steinhausser@gmail.com>
 *
 * @final since Symfony 6.2
 */
class BackedEnumValueResolver implements ArgumentValueResolverInterface, ValueResolverInterface
{
    /**
     * @deprecated since Symfony 6.2, use resolve() instead
     */
    public function supports(Request $request, ArgumentMetadata $argument): bool
    {
        @trigger_deprecation('symfony/http-kernel', '6.2', 'The "%s()" method is deprecated, use "resolve()" instead.', __METHOD__);
        if (!is_subclass_of($argument->getType(), \BackedEnum::class)) {
            return \false;
        }
        if ($argument->isVariadic()) {
            // only target route path parameters, which cannot be variadic.
            return \false;
        }
        // do not support if no value can be resolved at all
        // letting the \Symfony\Component\HttpKernel\Controller\ArgumentResolver\DefaultValueResolver be used
        // or \Symfony\Component\HttpKernel\Controller\ArgumentResolver fail with a meaningful error.
        return $request->attributes->has($argument->getName());
    }
    public function resolve(Request $request, ArgumentMetadata $argument): iterable
    {
        if (!is_subclass_of($argument->getType(), \BackedEnum::class)) {
            return [];
        }
        if ($argument->isVariadic()) {
            // only target route path parameters, which cannot be variadic.
            return [];
        }
        // do not support if no value can be resolved at all
        // letting the \Symfony\Component\HttpKernel\Controller\ArgumentResolver\DefaultValueResolver be used
        // or \Symfony\Component\HttpKernel\Controller\ArgumentResolver fail with a meaningful error.
        if (!$request->attributes->has($argument->getName())) {
            return [];
        }
        $value = $request->attributes->get($argument->getName());
        if (null === $value) {
            return [null];
        }
        if ($value instanceof \BackedEnum) {
            return [$value];
        }
        if (!\is_int($value) && !\is_string($value)) {
            throw new \LogicException(\sprintf('Could not resolve the "%s $%s" controller argument: expecting an int or string, got "%s".', $argument->getType(), $argument->getName(), get_debug_type($value)));
        }
        /** @var class-string<\BackedEnum> $enumType */
        $enumType = $argument->getType();
        try {
            return [$enumType::from($value)];
        } catch (\ValueError|\TypeError $e) {
            throw new NotFoundHttpException(\sprintf('Could not resolve the "%s $%s" controller argument: ', $argument->getType(), $argument->getName()) . $e->getMessage(), $e);
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\HttpKernel\Controller\ArgumentResolver;

use _ContaoManager\Symfony\Component\EventDispatcher\EventSubscriberInterface;
use _ContaoManager\Symfony\Component\HttpFoundation\Request;
use _ContaoManager\Symfony\Component\HttpFoundation\Response;
use _ContaoManager\Symfony\Component\HttpKernel\Attribute\MapQueryString;
use _ContaoManager\Symfony\Component\HttpKernel\Attribute\MapRequestPayload;
use _ContaoManager\Symfony\Component\HttpKernel\Controller\ValueResolverInterface;
use _ContaoManager\Symfony\Component\HttpKernel\ControllerMetadata\ArgumentMetadata;
use _ContaoManager\Symfony\Component\HttpKernel\Event\ControllerArgumentsEvent;
use _ContaoManager\Symfony\Component\HttpKernel\Exception\HttpException;
use _ContaoManager\Symfony\Component\HttpKernel\KernelEvents;
use _ContaoManager\Symfony\Component\Serializer\Exception\InvalidArgumentException as SerializerInvalidArgumentException;
use _ContaoManager\Symfony\Component\Serializer\Exception\NotEncodableValueException;
use _ContaoManager\Symfony\Component\Serializer\Exception\PartialDenormalizationException;
use _ContaoManager\Symfony\Component\Serializer\Exception\UnsupportedFormatException;
use _ContaoManager\Symfony\Component\Serializer\Normalizer\DenormalizerInterface;
use _ContaoManager\Symfony\Component\Serializer\SerializerInterface;
use _ContaoManager\Symfony\Component\Validator\ConstraintViolation;
use _ContaoManager\Symfony\Component\Validator\ConstraintViolationList;
use _ContaoManager\Symfony\Component\Validator\Exception\ValidationFailedException;
use _ContaoManager\Symfony\Component\Validator\Validator\ValidatorInterface;
use _ContaoManager\Symfony\Contracts\Translation\TranslatorInterface;
/**
 * @author Konstantin Myakshin <molodchick@gmail.com>
 *
 * @final
 */
class RequestPayloadValueResolver implements ValueResolverInterface, EventSubscriberInterface
{
    /**
     * @see DenormalizerInterface::COLLECT_DENORMALIZATION_ERRORS
     */
    private const CONTEXT_DENORMALIZE = ['collect_denormalization_errors' => \true];
    /**
     * @see DenormalizerInterface::COLLECT_DENORMALIZATION_ERRORS
     */
    private const CONTEXT_DESERIALIZE = ['collect_denormalization_errors' => \true];
    public function __construct(private readonly SerializerInterface&DenormalizerInterface $serializer, private readonly ?ValidatorInterface $validator = null, private readonly ?TranslatorInterface $translator = null)
    {
    }
    public function resolve(Request $request, ArgumentMetadata $argument): iterable
    {
        $attribute = $argument->getAttributesOfType(MapQueryString::class, ArgumentMetadata::IS_INSTANCEOF)[0] ?? $argument->getAttributesOfType(MapRequestPayload::class, ArgumentMetadata::IS_INSTANCEOF)[0] ?? null;
        if (!$attribute) {
            return [];
        }
        if ($argument->isVariadic()) {
            throw new \LogicException(\sprintf('Mapping variadic argument "$%s" is not supported.', $argument->getName()));
        }
        $attribute->metadata = $argument;
        return [$attribute];
    }
    public function onKernelControllerArguments(ControllerArgumentsEvent $event): void
    {
        $arguments = $event->getArguments();
        foreach ($arguments as $i => $argument) {
            if ($argument instanceof MapQueryString) {
                $payloadMapper = 'mapQueryString';
                $validationFailedCode = $argument->validationFailedStatusCode;
            } elseif ($argument instanceof MapRequestPayload) {
                $payloadMapper = 'mapRequestPayload';
                $validationFailedCode = $argument->validationFailedStatusCode;
            } else {
                continue;
            }
            $request = $event->getRequest();
            if (!$type = $argument->metadata->getType()) {
                throw new \LogicException(\sprintf('Could not resolve the "$%s" controller argument: argument should be typed.', $argument->metadata->getName()));
            }
            if ($this->validator) {
                $violations = new ConstraintViolationList();
                try {
                    $payload = $this->{$payloadMapper}($request, $type, $argument);
                } catch (PartialDenormalizationException $e) {
                    $trans = $this->translator ? $this->translator->trans(...) : static fn($m, $p) => strtr($m, $p);
                    foreach ($e->getErrors() as $error) {
                        $parameters = [];
                        $template = 'This value was of an unexpected type.';
                        if ($expectedTypes = $error->getExpectedTypes()) {
                            $template = 'This value should be of type {{ type }}.';
                            $parameters['{{ type }}'] = implode('|', $expectedTypes);
                        }
                        if ($error->canUseMessageForUser()) {
                            $parameters['hint'] = $error->getMessage();
                        }
                        $message = $trans($template, $parameters, 'validators');
                        $violations->add(new ConstraintViolation($message, $template, $parameters, null, $error->getPath(), null));
                    }
                    $payload = $e->getData();
                } catch (SerializerInvalidArgumentException $e) {
                    $violations->add(new ConstraintViolation($e->getMessage(), $e->getMessage(), [], null, '', null));
                    $payload = null;
                }
                if (null !== $payload && !\count($violations)) {
                    $violations->addAll($this->validator->validate($payload, null, $argument->validationGroups ?? null));
                }
                if (\count($violations)) {
                    throw new HttpException($validationFailedCode, implode("\n", array_map(static fn($e) => $e->getMessage(), iterator_to_array($violations))), new ValidationFailedException($payload, $violations));
                }
            } else {
                try {
                    $payload = $this->{$payloadMapper}($request, $type, $argument);
                } catch (PartialDenormalizationException $e) {
                    throw new HttpException($validationFailedCode, implode("\n", array_map(static fn($e) => $e->getMessage(), $e->getErrors())), $e);
                } catch (SerializerInvalidArgumentException $e) {
                    throw new HttpException($validationFailedCode, $e->getMessage(), $e);
                }
            }
            if (null === $payload) {
                $payload = match (\true) {
                    $argument->metadata->hasDefaultValue() => $argument->metadata->getDefaultValue(),
                    $argument->metadata->isNullable() => null,
                    default => throw new HttpException($validationFailedCode),
                };
            }
            $arguments[$i] = $payload;
        }
        $event->setArguments($arguments);
    }
    public static function getSubscribedEvents(): array
    {
        return [KernelEvents::CONTROLLER_ARGUMENTS => 'onKernelControllerArguments'];
    }
    private function mapQueryString(Request $request, string $type, MapQueryString $attribute): ?object
    {
        if (!$data = $request->query->all()) {
            return null;
        }
        return $this->serializer->denormalize($data, $type, 'csv', $attribute->serializationContext + self::CONTEXT_DENORMALIZE);
    }
    private function mapRequestPayload(Request $request, string $type, MapRequestPayload $attribute): ?object
    {
        if ('' === $data = $request->request->all() ?: $request->getContent()) {
            return null;
        }
        if (null === $format = $request->getContentTypeFormat()) {
            throw new HttpException(Response::HTTP_UNSUPPORTED_MEDIA_TYPE, 'Unsupported format.');
        }
        if ($attribute->acceptFormat && !\in_array($format, (array) $attribute->acceptFormat, \true)) {
            throw new HttpException(Response::HTTP_UNSUPPORTED_MEDIA_TYPE, \sprintf('Unsupported format, expects "%s", but "%s" given.', implode('", "', (array) $attribute->acceptFormat), $format));
        }
        if (\is_array($data)) {
            return $this->serializer->denormalize($data, $type, self::hasNonStringScalar($data) ? $format : 'csv', $attribute->serializationContext + self::CONTEXT_DENORMALIZE);
        }
        if ('form' === $format) {
            throw new HttpException(Response::HTTP_BAD_REQUEST, 'Request payload contains invalid "form" data.');
        }
        try {
            return $this->serializer->deserialize($data, $type, $format, self::CONTEXT_DESERIALIZE + $attribute->serializationContext);
        } catch (UnsupportedFormatException $e) {
            throw new HttpException(Response::HTTP_UNSUPPORTED_MEDIA_TYPE, \sprintf('Unsupported format: "%s".', $format), $e);
        } catch (NotEncodableValueException $e) {
            throw new HttpException(Response::HTTP_BAD_REQUEST, \sprintf('Request payload contains invalid "%s" data.', $format), $e);
        }
    }
    private static function hasNonStringScalar(array $data): bool
    {
        $stack = [$data];
        while ($stack) {
            foreach (array_pop($stack) as $v) {
                if (\is_array($v)) {
                    $stack[] = $v;
                } elseif (!\is_string($v)) {
                    return \true;
                }
            }
        }
        return \false;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\HttpKernel\Controller\ArgumentResolver;

use _ContaoManager\Psr\Clock\ClockInterface;
use _ContaoManager\Symfony\Component\HttpFoundation\Request;
use _ContaoManager\Symfony\Component\HttpKernel\Attribute\MapDateTime;
use _ContaoManager\Symfony\Component\HttpKernel\Controller\ArgumentValueResolverInterface;
use _ContaoManager\Symfony\Component\HttpKernel\Controller\ValueResolverInterface;
use _ContaoManager\Symfony\Component\HttpKernel\ControllerMetadata\ArgumentMetadata;
use _ContaoManager\Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
/**
 * Convert DateTime instances from request attribute variable.
 *
 * @author Benjamin Eberlei <kontakt@beberlei.de>
 * @author Tim Goudriaan <tim@codedmonkey.com>
 */
final class DateTimeValueResolver implements ArgumentValueResolverInterface, ValueResolverInterface
{
    public function __construct(private readonly ?ClockInterface $clock = null)
    {
    }
    /**
     * @deprecated since Symfony 6.2, use resolve() instead
     */
    public function supports(Request $request, ArgumentMetadata $argument): bool
    {
        @trigger_deprecation('symfony/http-kernel', '6.2', 'The "%s()" method is deprecated, use "resolve()" instead.', __METHOD__);
        return is_a($argument->getType(), \DateTimeInterface::class, \true) && $request->attributes->has($argument->getName());
    }
    public function resolve(Request $request, ArgumentMetadata $argument): array
    {
        if (!is_a($argument->getType(), \DateTimeInterface::class, \true) || !$request->attributes->has($argument->getName())) {
            return [];
        }
        $value = $request->attributes->get($argument->getName());
        $class = \DateTimeInterface::class === $argument->getType() ? \DateTimeImmutable::class : $argument->getType();
        if (!$value) {
            if ($argument->isNullable()) {
                return [null];
            }
            if (!$this->clock) {
                return [new $class()];
            }
            $value = $this->clock->now();
        }
        if ($value instanceof \DateTimeInterface) {
            return [$value instanceof $class ? $value : $class::createFromInterface($value)];
        }
        $format = null;
        if ($attributes = $argument->getAttributes(MapDateTime::class, ArgumentMetadata::IS_INSTANCEOF)) {
            $attribute = $attributes[0];
            $format = $attribute->format;
        }
        if (null !== $format) {
            $date = $class::createFromFormat($format, $value, $this->clock?->now()->getTimeZone());
            if (($class::getLastErrors() ?: ['warning_count' => 0])['warning_count']) {
                $date = \false;
            }
        } else {
            if (\false !== filter_var($value, \FILTER_VALIDATE_INT, ['options' => ['min_range' => 0]])) {
                $value = '@' . $value;
            }
            try {
                $date = new $class($value, $this->clock?->now()->getTimeZone());
            } catch (\Exception) {
                $date = \false;
            }
        }
        if (!$date) {
            throw new NotFoundHttpException(\sprintf('Invalid date given for parameter "%s".', $argument->getName()));
        }
        return [$date];
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\HttpKernel\Controller\ArgumentResolver;

use _ContaoManager\Symfony\Component\HttpFoundation\Request;
use _ContaoManager\Symfony\Component\HttpKernel\Controller\ArgumentValueResolverInterface;
use _ContaoManager\Symfony\Component\HttpKernel\Controller\ValueResolverInterface;
use _ContaoManager\Symfony\Component\HttpKernel\ControllerMetadata\ArgumentMetadata;
/**
 * Yields the same instance as the request object passed along.
 *
 * @author Iltar van der Berg <kjarli@gmail.com>
 */
final class RequestValueResolver implements ArgumentValueResolverInterface, ValueResolverInterface
{
    /**
     * @deprecated since Symfony 6.2, use resolve() instead
     */
    public function supports(Request $request, ArgumentMetadata $argument): bool
    {
        @trigger_deprecation('symfony/http-kernel', '6.2', 'The "%s()" method is deprecated, use "resolve()" instead.', __METHOD__);
        return Request::class === $argument->getType() || is_subclass_of($argument->getType(), Request::class);
    }
    public function resolve(Request $request, ArgumentMetadata $argument): array
    {
        return Request::class === $argument->getType() || is_subclass_of($argument->getType(), Request::class) ? [$request] : [];
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\HttpKernel\Controller\ArgumentResolver;

use _ContaoManager\Symfony\Component\HttpFoundation\Request;
use _ContaoManager\Symfony\Component\HttpFoundation\Session\SessionInterface;
use _ContaoManager\Symfony\Component\HttpKernel\Controller\ArgumentValueResolverInterface;
use _ContaoManager\Symfony\Component\HttpKernel\Controller\ValueResolverInterface;
use _ContaoManager\Symfony\Component\HttpKernel\ControllerMetadata\ArgumentMetadata;
/**
 * Yields the Session.
 *
 * @author Iltar van der Berg <kjarli@gmail.com>
 */
final class SessionValueResolver implements ArgumentValueResolverInterface, ValueResolverInterface
{
    /**
     * @deprecated since Symfony 6.2, use resolve() instead
     */
    public function supports(Request $request, ArgumentMetadata $argument): bool
    {
        @trigger_deprecation('symfony/http-kernel', '6.2', 'The "%s()" method is deprecated, use "resolve()" instead.', __METHOD__);
        if (!$request->hasSession()) {
            return \false;
        }
        $type = $argument->getType();
        if (SessionInterface::class !== $type && !is_subclass_of($type, SessionInterface::class)) {
            return \false;
        }
        return $request->getSession() instanceof $type;
    }
    public function resolve(Request $request, ArgumentMetadata $argument): array
    {
        if (!$request->hasSession()) {
            return [];
        }
        $type = $argument->getType();
        if (SessionInterface::class !== $type && !is_subclass_of($type, SessionInterface::class)) {
            return [];
        }
        return $request->getSession() instanceof $type ? [$request->getSession()] : [];
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\HttpKernel\Controller\ArgumentResolver;

use _ContaoManager\Symfony\Component\HttpFoundation\Request;
use _ContaoManager\Symfony\Component\HttpKernel\Controller\ArgumentValueResolverInterface;
use _ContaoManager\Symfony\Component\HttpKernel\Controller\ValueResolverInterface;
use _ContaoManager\Symfony\Component\HttpKernel\ControllerMetadata\ArgumentMetadata;
/**
 * Yields a non-variadic argument's value from the request attributes.
 *
 * @author Iltar van der Berg <kjarli@gmail.com>
 */
final class RequestAttributeValueResolver implements ArgumentValueResolverInterface, ValueResolverInterface
{
    /**
     * @deprecated since Symfony 6.2, use resolve() instead
     */
    public function supports(Request $request, ArgumentMetadata $argument): bool
    {
        @trigger_deprecation('symfony/http-kernel', '6.2', 'The "%s()" method is deprecated, use "resolve()" instead.', __METHOD__);
        return !$argument->isVariadic() && $request->attributes->has($argument->getName());
    }
    public function resolve(Request $request, ArgumentMetadata $argument): array
    {
        return !$argument->isVariadic() && $request->attributes->has($argument->getName()) ? [$request->attributes->get($argument->getName())] : [];
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\HttpKernel\Controller\ArgumentResolver;

use _ContaoManager\Psr\Container\ContainerInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\RuntimeException;
use _ContaoManager\Symfony\Component\HttpFoundation\Request;
use _ContaoManager\Symfony\Component\HttpKernel\Controller\ArgumentValueResolverInterface;
use _ContaoManager\Symfony\Component\HttpKernel\Controller\ValueResolverInterface;
use _ContaoManager\Symfony\Component\HttpKernel\ControllerMetadata\ArgumentMetadata;
/**
 * Provides an intuitive error message when controller fails because it is not registered as a service.
 *
 * @author Simeon Kolev <simeon.kolev9@gmail.com>
 */
final class NotTaggedControllerValueResolver implements ArgumentValueResolverInterface, ValueResolverInterface
{
    private ContainerInterface $container;
    public function __construct(ContainerInterface $container)
    {
        $this->container = $container;
    }
    /**
     * @deprecated since Symfony 6.2, use resolve() instead
     */
    public function supports(Request $request, ArgumentMetadata $argument): bool
    {
        @trigger_deprecation('symfony/http-kernel', '6.2', 'The "%s()" method is deprecated, use "resolve()" instead.', __METHOD__);
        $controller = $request->attributes->get('_controller');
        if (\is_array($controller) && \is_callable($controller, \true) && \is_string($controller[0])) {
            $controller = $controller[0] . '::' . $controller[1];
        } elseif (!\is_string($controller) || '' === $controller) {
            return \false;
        }
        if ('\\' === $controller[0]) {
            $controller = ltrim($controller, '\\');
        }
        if (!$this->container->has($controller) && \false !== $i = strrpos($controller, ':')) {
            $controller = substr($controller, 0, $i) . strtolower(substr($controller, $i));
        }
        return \false === $this->container->has($controller);
    }
    public function resolve(Request $request, ArgumentMetadata $argument): array
    {
        $controller = $request->attributes->get('_controller');
        if (\is_array($controller) && \is_callable($controller, \true) && \is_string($controller[0])) {
            $controller = $controller[0] . '::' . $controller[1];
        } elseif (!\is_string($controller) || '' === $controller) {
            return [];
        }
        if ('\\' === $controller[0]) {
            $controller = ltrim($controller, '\\');
        }
        if (!$this->container->has($controller)) {
            $controller = \false !== ($i = strrpos($controller, ':')) ? substr($controller, 0, $i) . strtolower(substr($controller, $i)) : $controller . '::__invoke';
        }
        if ($this->container->has($controller)) {
            return [];
        }
        $what = \sprintf('argument $%s of "%s()"', $argument->getName(), $controller);
        $message = \sprintf('Could not resolve %s, maybe you forgot to register the controller as a service or missed tagging it with the "controller.service_arguments"?', $what);
        throw new RuntimeException($message);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\HttpKernel\Controller\ArgumentResolver;

use _ContaoManager\Symfony\Component\HttpFoundation\Request;
use _ContaoManager\Symfony\Component\HttpKernel\Controller\ArgumentValueResolverInterface;
use _ContaoManager\Symfony\Component\HttpKernel\Controller\ValueResolverInterface;
use _ContaoManager\Symfony\Component\HttpKernel\ControllerMetadata\ArgumentMetadata;
use _ContaoManager\Symfony\Component\Stopwatch\Stopwatch;
/**
 * Provides timing information via the stopwatch.
 *
 * @author Iltar van der Berg <kjarli@gmail.com>
 */
final class TraceableValueResolver implements ArgumentValueResolverInterface, ValueResolverInterface
{
    private ArgumentValueResolverInterface|ValueResolverInterface $inner;
    private Stopwatch $stopwatch;
    public function __construct(ArgumentValueResolverInterface|ValueResolverInterface $inner, Stopwatch $stopwatch)
    {
        $this->inner = $inner;
        $this->stopwatch = $stopwatch;
    }
    /**
     * @deprecated since Symfony 6.2, use resolve() instead
     */
    public function supports(Request $request, ArgumentMetadata $argument): bool
    {
        if ($this->inner instanceof ValueResolverInterface) {
            return \true;
        }
        $method = $this->inner::class . '::' . __FUNCTION__;
        $this->stopwatch->start($method, 'controller.argument_value_resolver');
        $return = $this->inner->supports($request, $argument);
        $this->stopwatch->stop($method);
        return $return;
    }
    public function resolve(Request $request, ArgumentMetadata $argument): iterable
    {
        $method = $this->inner::class . '::' . __FUNCTION__;
        $this->stopwatch->start($method, 'controller.argument_value_resolver');
        yield from $this->inner->resolve($request, $argument);
        $this->stopwatch->stop($method);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\HttpKernel\Controller;

use _ContaoManager\Symfony\Component\HttpFoundation\Request;
/**
 * An ArgumentResolverInterface instance knows how to determine the
 * arguments for a specific action.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
interface ArgumentResolverInterface
{
    /**
     * Returns the arguments to pass to the controller.
     *
     * @param \ReflectionFunctionAbstract|null $reflector
     *
     * @throws \RuntimeException When no value could be provided for a required argument
     */
    public function getArguments(Request $request, callable $controller): array;
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\HttpKernel\Controller;

use _ContaoManager\Symfony\Component\HttpFoundation\Request;
/**
 * A ControllerResolverInterface implementation knows how to determine the
 * controller to execute based on a Request object.
 *
 * A Controller can be any valid PHP callable.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
interface ControllerResolverInterface
{
    /**
     * Returns the Controller instance associated with a Request.
     *
     * As several resolvers can exist for a single application, a resolver must
     * return false when it is not able to determine the controller.
     *
     * The resolver must only throw an exception when it should be able to load a
     * controller but cannot because of some errors made by the developer.
     *
     * @return callable|false A PHP callable representing the Controller,
     *                        or false if this resolver is not able to determine the controller
     *
     * @throws \LogicException If a controller was found based on the request but it is not callable
     */
    public function getController(Request $request): callable|false;
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\HttpKernel\Controller;

use _ContaoManager\Symfony\Component\HttpFoundation\Request;
use _ContaoManager\Symfony\Component\Stopwatch\Stopwatch;
/**
 * @author Fabien Potencier <fabien@symfony.com>
 */
class TraceableArgumentResolver implements ArgumentResolverInterface
{
    private ArgumentResolverInterface $resolver;
    private Stopwatch $stopwatch;
    public function __construct(ArgumentResolverInterface $resolver, Stopwatch $stopwatch)
    {
        $this->resolver = $resolver;
        $this->stopwatch = $stopwatch;
    }
    /**
     * @param \ReflectionFunctionAbstract|null $reflector
     */
    public function getArguments(Request $request, callable $controller): array
    {
        $reflector = 2 < \func_num_args() ? func_get_arg(2) : null;
        $e = $this->stopwatch->start('controller.get_arguments');
        try {
            return $this->resolver->getArguments($request, $controller, $reflector);
        } finally {
            $e->stop();
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\HttpKernel\Controller;

use _ContaoManager\Symfony\Component\HttpFoundation\Request;
use _ContaoManager\Symfony\Component\HttpKernel\ControllerMetadata\ArgumentMetadata;
/**
 * Responsible for resolving the value of an argument based on its metadata.
 *
 * @author Nicolas Grekas <p@tchwork.com>
 */
interface ValueResolverInterface
{
    /**
     * Returns the possible value(s).
     */
    public function resolve(Request $request, ArgumentMetadata $argument): iterable;
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\HttpKernel\Controller;

use _ContaoManager\Psr\Log\LoggerInterface;
use _ContaoManager\Symfony\Component\HttpFoundation\Exception\BadRequestException;
use _ContaoManager\Symfony\Component\HttpFoundation\Request;
use _ContaoManager\Symfony\Component\HttpKernel\Attribute\AsController;
/**
 * This implementation uses the '_controller' request attribute to determine
 * the controller to execute.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 * @author Tobias Schultze <http://tobion.de>
 */
class ControllerResolver implements ControllerResolverInterface
{
    private ?LoggerInterface $logger;
    private array $allowedControllerTypes = [];
    private array $allowedControllerAttributes = [AsController::class => AsController::class];
    public function __construct(?LoggerInterface $logger = null)
    {
        $this->logger = $logger;
    }
    /**
     * @param array<class-string> $types
     * @param array<class-string> $attributes
     */
    public function allowControllers(array $types = [], array $attributes = []): void
    {
        foreach ($types as $type) {
            $this->allowedControllerTypes[$type] = $type;
        }
        foreach ($attributes as $attribute) {
            $this->allowedControllerAttributes[$attribute] = $attribute;
        }
    }
    /**
     * @throws BadRequestException when the request has attribute "_check_controller_is_allowed" set to true and the controller is not allowed
     */
    public function getController(Request $request): callable|false
    {
        if (!$controller = $request->attributes->get('_controller')) {
            $this->logger?->warning('Unable to look for the controller as the "_controller" parameter is missing.');
            return \false;
        }
        if (\is_array($controller)) {
            if (isset($controller[0]) && \is_string($controller[0]) && isset($controller[1])) {
                try {
                    $controller[0] = $this->instantiateController($controller[0]);
                } catch (\Error|\LogicException $e) {
                    if (\is_callable($controller)) {
                        return $this->checkController($request, $controller);
                    }
                    throw $e;
                }
            }
            if (!\is_callable($controller)) {
                throw new \InvalidArgumentException(\sprintf('The controller for URI "%s" is not callable: ', $request->getPathInfo()) . $this->getControllerError($controller));
            }
            return $this->checkController($request, $controller);
        }
        if (\is_object($controller)) {
            if (!\is_callable($controller)) {
                throw new \InvalidArgumentException(\sprintf('The controller for URI "%s" is not callable: ', $request->getPathInfo()) . $this->getControllerError($controller));
            }
            return $this->checkController($request, $controller);
        }
        if (\function_exists($controller)) {
            return $this->checkController($request, $controller);
        }
        try {
            $callable = $this->createController($controller);
        } catch (\InvalidArgumentException $e) {
            throw new \InvalidArgumentException(\sprintf('The controller for URI "%s" is not callable: ', $request->getPathInfo()) . $e->getMessage(), 0, $e);
        }
        if (!\is_callable($callable)) {
            throw new \InvalidArgumentException(\sprintf('The controller for URI "%s" is not callable: ', $request->getPathInfo()) . $this->getControllerError($callable));
        }
        return $this->checkController($request, $callable);
    }
    /**
     * Returns a callable for the given controller.
     *
     * @throws \InvalidArgumentException When the controller cannot be created
     */
    protected function createController(string $controller): callable
    {
        if (!str_contains($controller, '::')) {
            $controller = $this->instantiateController($controller);
            if (!\is_callable($controller)) {
                throw new \InvalidArgumentException($this->getControllerError($controller));
            }
            return $controller;
        }
        [$class, $method] = explode('::', $controller, 2);
        try {
            $controller = [$this->instantiateController($class), $method];
        } catch (\Error|\LogicException $e) {
            try {
                if ((new \ReflectionMethod($class, $method))->isStatic()) {
                    return $class . '::' . $method;
                }
            } catch (\ReflectionException) {
                throw $e;
            }
            throw $e;
        }
        if (!\is_callable($controller)) {
            throw new \InvalidArgumentException($this->getControllerError($controller));
        }
        return $controller;
    }
    /**
     * Returns an instantiated controller.
     */
    protected function instantiateController(string $class): object
    {
        return new $class();
    }
    private function getControllerError(mixed $callable): string
    {
        if (\is_string($callable)) {
            if (str_contains($callable, '::')) {
                $callable = explode('::', $callable, 2);
            } else {
                return \sprintf('Function "%s" does not exist.', $callable);
            }
        }
        if (\is_object($callable)) {
            $availableMethods = $this->getClassMethodsWithoutMagicMethods($callable);
            $alternativeMsg = $availableMethods ? \sprintf(' or use one of the available methods: "%s"', implode('", "', $availableMethods)) : '';
            return \sprintf('Controller class "%s" cannot be called without a method name. You need to implement "__invoke"%s.', get_debug_type($callable), $alternativeMsg);
        }
        if (!\is_array($callable)) {
            return \sprintf('Invalid type for controller given, expected string, array or object, got "%s".', get_debug_type($callable));
        }
        if (!isset($callable[0]) || !isset($callable[1]) || 2 !== \count($callable)) {
            return 'Invalid array callable, expected [controller, method].';
        }
        [$controller, $method] = $callable;
        if (\is_string($controller) && !class_exists($controller)) {
            return \sprintf('Class "%s" does not exist.', $controller);
        }
        $className = \is_object($controller) ? get_debug_type($controller) : $controller;
        if (method_exists($controller, $method)) {
            return \sprintf('Method "%s" on class "%s" should be public and non-abstract.', $method, $className);
        }
        $collection = $this->getClassMethodsWithoutMagicMethods($controller);
        $alternatives = [];
        foreach ($collection as $item) {
            $lev = levenshtein($method, $item);
            if ($lev <= \strlen($method) / 3 || str_contains($item, $method)) {
                $alternatives[] = $item;
            }
        }
        asort($alternatives);
        $message = \sprintf('Expected method "%s" on class "%s"', $method, $className);
        if (\count($alternatives) > 0) {
            $message .= \sprintf(', did you mean "%s"?', implode('", "', $alternatives));
        } else {
            $message .= \sprintf('. Available methods: "%s".', implode('", "', $collection));
        }
        return $message;
    }
    private function getClassMethodsWithoutMagicMethods($classOrObject): array
    {
        $methods = get_class_methods($classOrObject);
        return array_filter($methods, fn(string $method) => 0 !== strncmp($method, '__', 2));
    }
    private function checkController(Request $request, callable $controller): callable
    {
        if (!$request->attributes->get('_check_controller_is_allowed', \false)) {
            return $controller;
        }
        $r = null;
        if (\is_array($controller)) {
            [$class, $name] = $controller;
            $name = (\is_string($class) ? $class : $class::class) . '::' . $name;
        } elseif (\is_object($controller) && !$controller instanceof \Closure) {
            $class = $controller;
            $name = $class::class . '::__invoke';
        } else {
            $r = new \ReflectionFunction($controller);
            $name = $r->name;
            if (str_contains($name, '{closure')) {
                $name = $class = \Closure::class;
            } elseif ($class = \PHP_VERSION_ID >= 80111 ? $r->getClosureCalledClass() : $r->getClosureScopeClass()) {
                $class = $class->name;
                $name = $class . '::' . $name;
            }
        }
        if ($class) {
            foreach ($this->allowedControllerTypes as $type) {
                if (is_a($class, $type, \true)) {
                    return $controller;
                }
            }
        }
        $r ??= new \ReflectionClass($class);
        foreach ($r->getAttributes() as $attribute) {
            if (isset($this->allowedControllerAttributes[$attribute->getName()])) {
                return $controller;
            }
        }
        if (str_contains($name, '@anonymous')) {
            $name = preg_replace_callback('/[a-zA-Z_\x7f-\xff][\\\\a-zA-Z0-9_\x7f-\xff]*+@anonymous\x00.*?\.php(?:0x?|:[0-9]++\$)?[0-9a-fA-F]++/', fn($m) => class_exists($m[0], \false) ? ((get_parent_class($m[0]) ?: key(class_implements($m[0]))) ?: 'class') . '@anonymous' : $m[0], $name);
        }
        if (-1 === $request->attributes->get('_check_controller_is_allowed')) {
            trigger_deprecation('symfony/http-kernel', '6.4', 'Callable "%s()" is not allowed as a controller. Did you miss tagging it with "#[AsController]" or registering its type with "%s::allowControllers()"?', $name, self::class);
            return $controller;
        }
        throw new BadRequestException(\sprintf('Callable "%s()" is not allowed as a controller. Did you miss tagging it with "#[AsController]" or registering its type with "%s::allowControllers()"?', $name, self::class));
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\HttpKernel\Controller;

use _ContaoManager\Symfony\Component\HttpFoundation\Request;
use _ContaoManager\Symfony\Component\Stopwatch\Stopwatch;
/**
 * @author Fabien Potencier <fabien@symfony.com>
 */
class TraceableControllerResolver implements ControllerResolverInterface
{
    private ControllerResolverInterface $resolver;
    private Stopwatch $stopwatch;
    public function __construct(ControllerResolverInterface $resolver, Stopwatch $stopwatch)
    {
        $this->resolver = $resolver;
        $this->stopwatch = $stopwatch;
    }
    public function getController(Request $request): callable|false
    {
        $e = $this->stopwatch->start('controller.get_callable');
        try {
            return $this->resolver->getController($request);
        } finally {
            $e->stop();
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\HttpKernel\Controller;

use _ContaoManager\Symfony\Component\HttpFoundation\Request;
use _ContaoManager\Symfony\Component\HttpKernel\ControllerMetadata\ArgumentMetadata;
/**
 * Responsible for resolving the value of an argument based on its metadata.
 *
 * @author Iltar van der Berg <kjarli@gmail.com>
 *
 * @deprecated since Symfony 6.2, implement ValueResolverInterface instead
 */
interface ArgumentValueResolverInterface
{
    /**
     * Whether this resolver can resolve the value for the given ArgumentMetadata.
     */
    public function supports(Request $request, ArgumentMetadata $argument): bool;
    /**
     * Returns the possible value(s).
     */
    public function resolve(Request $request, ArgumentMetadata $argument): iterable;
}
HttpKernel Component
====================

The HttpKernel component provides a structured process for converting a Request
into a Response by making use of the EventDispatcher component. It's flexible
enough to create full-stack frameworks, micro-frameworks or advanced CMS systems like Drupal.

Resources
---------

 * [Documentation](https://symfony.com/doc/current/components/http_kernel.html)
 * [Contributing](https://symfony.com/doc/current/contributing/index.html)
 * [Report issues](https://github.com/symfony/symfony/issues) and
   [send Pull Requests](https://github.com/symfony/symfony/pulls)
   in the [main Symfony repository](https://github.com/symfony/symfony)
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\HttpKernel\Fragment;

use _ContaoManager\Symfony\Component\HttpFoundation\Request;
use _ContaoManager\Symfony\Component\HttpKernel\Controller\ControllerReference;
/**
 * Interface implemented by rendering strategies able to generate a URL for a fragment.
 *
 * @author Kévin Dunglas <kevin@dunglas.fr>
 */
interface FragmentUriGeneratorInterface
{
    /**
     * Generates a fragment URI for a given controller.
     *
     * @param bool $absolute Whether to generate an absolute URL or not
     * @param bool $strict   Whether to allow non-scalar attributes or not
     * @param bool $sign     Whether to sign the URL or not
     */
    public function generate(ControllerReference $controller, ?Request $request = null, bool $absolute = \false, bool $strict = \true, bool $sign = \true): string;
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\HttpKernel\Fragment;

use _ContaoManager\Symfony\Component\HttpFoundation\Request;
use _ContaoManager\Symfony\Component\HttpFoundation\Response;
use _ContaoManager\Symfony\Component\HttpKernel\Controller\ControllerReference;
use _ContaoManager\Symfony\Component\HttpKernel\Event\ExceptionEvent;
use _ContaoManager\Symfony\Component\HttpKernel\HttpCache\SubRequestHandler;
use _ContaoManager\Symfony\Component\HttpKernel\HttpKernelInterface;
use _ContaoManager\Symfony\Component\HttpKernel\KernelEvents;
use _ContaoManager\Symfony\Contracts\EventDispatcher\EventDispatcherInterface;
/**
 * Implements the inline rendering strategy where the Request is rendered by the current HTTP kernel.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class InlineFragmentRenderer extends RoutableFragmentRenderer
{
    private HttpKernelInterface $kernel;
    private ?EventDispatcherInterface $dispatcher;
    public function __construct(HttpKernelInterface $kernel, ?EventDispatcherInterface $dispatcher = null)
    {
        $this->kernel = $kernel;
        $this->dispatcher = $dispatcher;
    }
    /**
     * Additional available options:
     *
     *  * alt: an alternative URI to render in case of an error
     */
    public function render(string|ControllerReference $uri, Request $request, array $options = []): Response
    {
        $reference = null;
        if ($uri instanceof ControllerReference) {
            $reference = $uri;
            // Remove attributes from the generated URI because if not, the Symfony
            // routing system will use them to populate the Request attributes. We don't
            // want that as we want to preserve objects (so we manually set Request attributes
            // below instead)
            $attributes = $reference->attributes;
            $reference->attributes = [];
            // The request format and locale might have been overridden by the user
            foreach (['_format', '_locale'] as $key) {
                if (isset($attributes[$key])) {
                    $reference->attributes[$key] = $attributes[$key];
                }
            }
            $uri = $this->generateFragmentUri($uri, $request, \false, \false);
            $reference->attributes = array_merge($attributes, $reference->attributes);
        }
        $subRequest = $this->createSubRequest($uri, $request);
        // override Request attributes as they can be objects (which are not supported by the generated URI)
        if (null !== $reference) {
            $subRequest->attributes->add($reference->attributes);
        }
        $level = ob_get_level();
        try {
            return SubRequestHandler::handle($this->kernel, $subRequest, HttpKernelInterface::SUB_REQUEST, \false);
        } catch (\Exception $e) {
            // we dispatch the exception event to trigger the logging
            // the response that comes back is ignored
            if (isset($options['ignore_errors']) && $options['ignore_errors'] && $this->dispatcher) {
                $event = new ExceptionEvent($this->kernel, $request, HttpKernelInterface::SUB_REQUEST, $e);
                $this->dispatcher->dispatch($event, KernelEvents::EXCEPTION);
            }
            // let's clean up the output buffers that were created by the sub-request
            Response::closeOutputBuffers($level, \false);
            if (isset($options['alt'])) {
                $alt = $options['alt'];
                unset($options['alt']);
                return $this->render($alt, $request, $options);
            }
            if (!isset($options['ignore_errors']) || !$options['ignore_errors']) {
                throw $e;
            }
            return new Response();
        }
    }
    /**
     * @return Request
     */
    protected function createSubRequest(string $uri, Request $request)
    {
        $cookies = $request->cookies->all();
        $server = $request->server->all();
        unset($server['HTTP_IF_MODIFIED_SINCE']);
        unset($server['HTTP_IF_NONE_MATCH']);
        $subRequest = Request::create($uri, 'get', [], $cookies, [], $server);
        if ($request->headers->has('Surrogate-Capability')) {
            $subRequest->headers->set('Surrogate-Capability', $request->headers->get('Surrogate-Capability'));
        }
        static $setSession;
        $setSession ??= \Closure::bind(static function ($subRequest, $request) {
            $subRequest->session = $request->session;
        }, null, Request::class);
        $setSession($subRequest, $request);
        if ($request->get('_format')) {
            $subRequest->attributes->set('_format', $request->get('_format'));
        }
        if ($request->getDefaultLocale() !== $request->getLocale()) {
            $subRequest->setLocale($request->getLocale());
        }
        if ($request->attributes->has('_stateless')) {
            $subRequest->attributes->set('_stateless', $request->attributes->get('_stateless'));
        }
        if ($request->attributes->has('_check_controller_is_allowed')) {
            $subRequest->attributes->set('_check_controller_is_allowed', $request->attributes->get('_check_controller_is_allowed'));
        }
        return $subRequest;
    }
    public function getName(): string
    {
        return 'inline';
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\HttpKernel\Fragment;

/**
 * Implements the SSI rendering strategy.
 *
 * @author Sebastian Krebs <krebs.seb@gmail.com>
 */
class SsiFragmentRenderer extends AbstractSurrogateFragmentRenderer
{
    public function getName(): string
    {
        return 'ssi';
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\HttpKernel\Fragment;

use _ContaoManager\Symfony\Component\HttpFoundation\Request;
use _ContaoManager\Symfony\Component\HttpFoundation\Response;
use _ContaoManager\Symfony\Component\HttpFoundation\UriSigner;
use _ContaoManager\Symfony\Component\HttpKernel\Controller\ControllerReference;
use _ContaoManager\Symfony\Component\HttpKernel\HttpCache\SurrogateInterface;
/**
 * Implements Surrogate rendering strategy.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
abstract class AbstractSurrogateFragmentRenderer extends RoutableFragmentRenderer
{
    private ?SurrogateInterface $surrogate;
    private FragmentRendererInterface $inlineStrategy;
    private ?UriSigner $signer;
    /**
     * The "fallback" strategy when surrogate is not available should always be an
     * instance of InlineFragmentRenderer.
     *
     * @param FragmentRendererInterface $inlineStrategy The inline strategy to use when the surrogate is not supported
     */
    public function __construct(?SurrogateInterface $surrogate, FragmentRendererInterface $inlineStrategy, ?UriSigner $signer = null)
    {
        $this->surrogate = $surrogate;
        $this->inlineStrategy = $inlineStrategy;
        $this->signer = $signer;
    }
    /**
     * Note that if the current Request has no surrogate capability, this method
     * falls back to use the inline rendering strategy.
     *
     * Additional available options:
     *
     *  * alt: an alternative URI to render in case of an error
     *  * comment: a comment to add when returning the surrogate tag
     *  * absolute_uri: whether to generate an absolute URI or not. Default is false
     *
     * Note, that not all surrogate strategies support all options. For now
     * 'alt' and 'comment' are only supported by ESI.
     *
     * @see Symfony\Component\HttpKernel\HttpCache\SurrogateInterface
     */
    public function render(string|ControllerReference $uri, Request $request, array $options = []): Response
    {
        if (!$this->surrogate || !$this->surrogate->hasSurrogateCapability($request)) {
            $request->attributes->set('_check_controller_is_allowed', -1);
            // @deprecated, switch to true in Symfony 7
            if ($uri instanceof ControllerReference && $this->containsNonScalars($uri->attributes)) {
                throw new \InvalidArgumentException('Passing non-scalar values as part of URI attributes to the ESI and SSI rendering strategies is not supported. Use a different rendering strategy or pass scalar values.');
            }
            return $this->inlineStrategy->render($uri, $request, $options);
        }
        $absolute = $options['absolute_uri'] ?? \false;
        if ($uri instanceof ControllerReference) {
            $uri = $this->generateSignedFragmentUri($uri, $request, $absolute);
        }
        $alt = $options['alt'] ?? null;
        if ($alt instanceof ControllerReference) {
            $alt = $this->generateSignedFragmentUri($alt, $request, $absolute);
        }
        $tag = $this->surrogate->renderIncludeTag($uri, $alt, $options['ignore_errors'] ?? \false, $options['comment'] ?? '');
        return new Response($tag);
    }
    private function generateSignedFragmentUri(ControllerReference $uri, Request $request, bool $absolute): string
    {
        return (new FragmentUriGenerator($this->fragmentPath, $this->signer))->generate($uri, $request, $absolute);
    }
    private function containsNonScalars(array $values): bool
    {
        foreach ($values as $value) {
            if (\is_scalar($value) || null === $value) {
                continue;
            }
            if (!\is_array($value) || $this->containsNonScalars($value)) {
                return \true;
            }
        }
        return \false;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\HttpKernel\Fragment;

use _ContaoManager\Symfony\Component\HttpFoundation\Request;
use _ContaoManager\Symfony\Component\HttpFoundation\Response;
use _ContaoManager\Symfony\Component\HttpKernel\Controller\ControllerReference;
/**
 * Interface implemented by all rendering strategies.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
interface FragmentRendererInterface
{
    /**
     * Renders a URI and returns the Response content.
     */
    public function render(string|ControllerReference $uri, Request $request, array $options = []): Response;
    /**
     * Gets the name of the strategy.
     */
    public function getName(): string;
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\HttpKernel\Fragment;

use _ContaoManager\Symfony\Component\HttpFoundation\Request;
use _ContaoManager\Symfony\Component\HttpFoundation\RequestStack;
use _ContaoManager\Symfony\Component\HttpFoundation\UriSigner;
use _ContaoManager\Symfony\Component\HttpKernel\Controller\ControllerReference;
/**
 * Generates a fragment URI.
 *
 * @author Kévin Dunglas <kevin@dunglas.fr>
 * @author Fabien Potencier <fabien@symfony.com>
 */
final class FragmentUriGenerator implements FragmentUriGeneratorInterface
{
    private string $fragmentPath;
    private ?UriSigner $signer;
    private ?RequestStack $requestStack;
    public function __construct(string $fragmentPath, ?UriSigner $signer = null, ?RequestStack $requestStack = null)
    {
        $this->fragmentPath = $fragmentPath;
        $this->signer = $signer;
        $this->requestStack = $requestStack;
    }
    public function generate(ControllerReference $controller, ?Request $request = null, bool $absolute = \false, bool $strict = \true, bool $sign = \true): string
    {
        if (null === $request && (null === $this->requestStack || null === $request = $this->requestStack->getCurrentRequest())) {
            throw new \LogicException('Generating a fragment URL can only be done when handling a Request.');
        }
        if ($sign && null === $this->signer) {
            throw new \LogicException('You must use a URI when using the ESI rendering strategy or set a URL signer.');
        }
        if ($strict) {
            $this->checkNonScalar($controller->attributes);
        }
        // We need to forward the current _format and _locale values as we don't have
        // a proper routing pattern to do the job for us.
        // This makes things inconsistent if you switch from rendering a controller
        // to rendering a route if the route pattern does not contain the special
        // _format and _locale placeholders.
        if (!isset($controller->attributes['_format'])) {
            $controller->attributes['_format'] = $request->getRequestFormat();
        }
        if (!isset($controller->attributes['_locale'])) {
            $controller->attributes['_locale'] = $request->getLocale();
        }
        $controller->attributes['_controller'] = $controller->controller;
        $controller->query['_path'] = http_build_query($controller->attributes, '', '&');
        $path = $this->fragmentPath . '?' . http_build_query($controller->query, '', '&');
        // we need to sign the absolute URI, but want to return the path only.
        $fragmentUri = $sign || $absolute ? $request->getUriForPath($path) : $request->getBaseUrl() . $path;
        if (!$sign) {
            return $fragmentUri;
        }
        $fragmentUri = $this->signer->sign($fragmentUri);
        return $absolute ? $fragmentUri : substr($fragmentUri, \strlen($request->getSchemeAndHttpHost()));
    }
    private function checkNonScalar(array $values): void
    {
        foreach ($values as $key => $value) {
            if (\is_array($value)) {
                $this->checkNonScalar($value);
            } elseif (!\is_scalar($value) && null !== $value) {
                throw new \LogicException(\sprintf('Controller attributes cannot contain non-scalar/non-null values (value for key "%s" is not a scalar or null).', $key));
            }
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\HttpKernel\Fragment;

/**
 * Implements the ESI rendering strategy.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class EsiFragmentRenderer extends AbstractSurrogateFragmentRenderer
{
    public function getName(): string
    {
        return 'esi';
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\HttpKernel\Fragment;

use _ContaoManager\Symfony\Component\HttpFoundation\Request;
use _ContaoManager\Symfony\Component\HttpFoundation\Response;
use _ContaoManager\Symfony\Component\HttpFoundation\UriSigner;
use _ContaoManager\Symfony\Component\HttpKernel\Controller\ControllerReference;
use _ContaoManager\Twig\Environment;
/**
 * Implements the Hinclude rendering strategy.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class HIncludeFragmentRenderer extends RoutableFragmentRenderer
{
    private ?string $globalDefaultTemplate;
    private ?UriSigner $signer;
    private ?Environment $twig;
    private string $charset;
    /**
     * @param string|null $globalDefaultTemplate The global default content (it can be a template name or the content)
     */
    public function __construct(?Environment $twig = null, ?UriSigner $signer = null, ?string $globalDefaultTemplate = null, string $charset = 'utf-8')
    {
        $this->twig = $twig;
        $this->globalDefaultTemplate = $globalDefaultTemplate;
        $this->signer = $signer;
        $this->charset = $charset;
    }
    /**
     * Checks if a templating engine has been set.
     */
    public function hasTemplating(): bool
    {
        return null !== $this->twig;
    }
    /**
     * Additional available options:
     *
     *  * default:    The default content (it can be a template name or the content)
     *  * id:         An optional hx:include tag id attribute
     *  * attributes: An optional array of hx:include tag attributes
     */
    public function render(string|ControllerReference $uri, Request $request, array $options = []): Response
    {
        if ($uri instanceof ControllerReference) {
            $uri = (new FragmentUriGenerator($this->fragmentPath, $this->signer))->generate($uri, $request);
        }
        // We need to replace ampersands in the URI with the encoded form in order to return valid html/xml content.
        $uri = str_replace('&', '&amp;', $uri);
        $template = $options['default'] ?? $this->globalDefaultTemplate;
        if (null !== $this->twig && $template && $this->twig->getLoader()->exists($template)) {
            $content = $this->twig->render($template);
        } else {
            $content = $template;
        }
        $attributes = isset($options['attributes']) && \is_array($options['attributes']) ? $options['attributes'] : [];
        if (isset($options['id']) && $options['id']) {
            $attributes['id'] = $options['id'];
        }
        $renderedAttributes = '';
        if (\count($attributes) > 0) {
            $flags = \ENT_QUOTES | \ENT_SUBSTITUTE;
            foreach ($attributes as $attribute => $value) {
                $renderedAttributes .= \sprintf(' %s="%s"', htmlspecialchars($attribute, $flags, $this->charset, \false), htmlspecialchars($value, $flags, $this->charset, \false));
            }
        }
        return new Response(\sprintf('<hx:include src="%s"%s>%s</hx:include>', $uri, $renderedAttributes, $content));
    }
    public function getName(): string
    {
        return 'hinclude';
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\HttpKernel\Fragment;

use _ContaoManager\Symfony\Component\HttpFoundation\RequestStack;
use _ContaoManager\Symfony\Component\HttpFoundation\Response;
use _ContaoManager\Symfony\Component\HttpFoundation\StreamedResponse;
use _ContaoManager\Symfony\Component\HttpKernel\Controller\ControllerReference;
use _ContaoManager\Symfony\Component\HttpKernel\Exception\HttpException;
/**
 * Renders a URI that represents a resource fragment.
 *
 * This class handles the rendering of resource fragments that are included into
 * a main resource. The handling of the rendering is managed by specialized renderers.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 *
 * @see FragmentRendererInterface
 */
class FragmentHandler
{
    private bool $debug;
    private array $renderers = [];
    private RequestStack $requestStack;
    /**
     * @param FragmentRendererInterface[] $renderers An array of FragmentRendererInterface instances
     * @param bool                        $debug     Whether the debug mode is enabled or not
     */
    public function __construct(RequestStack $requestStack, array $renderers = [], bool $debug = \false)
    {
        $this->requestStack = $requestStack;
        foreach ($renderers as $renderer) {
            $this->addRenderer($renderer);
        }
        $this->debug = $debug;
    }
    /**
     * Adds a renderer.
     *
     * @return void
     */
    public function addRenderer(FragmentRendererInterface $renderer)
    {
        $this->renderers[$renderer->getName()] = $renderer;
    }
    /**
     * Renders a URI and returns the Response content.
     *
     * Available options:
     *
     *  * ignore_errors: true to return an empty string in case of an error
     *
     * @throws \InvalidArgumentException when the renderer does not exist
     * @throws \LogicException           when no main request is being handled
     */
    public function render(string|ControllerReference $uri, string $renderer = 'inline', array $options = []): ?string
    {
        if (!isset($options['ignore_errors'])) {
            $options['ignore_errors'] = !$this->debug;
        }
        if (!isset($this->renderers[$renderer])) {
            throw new \InvalidArgumentException(\sprintf('The "%s" renderer does not exist.', $renderer));
        }
        if (!$request = $this->requestStack->getCurrentRequest()) {
            throw new \LogicException('Rendering a fragment can only be done when handling a Request.');
        }
        return $this->deliver($this->renderers[$renderer]->render($uri, $request, $options));
    }
    /**
     * Delivers the Response as a string.
     *
     * When the Response is a StreamedResponse, the content is streamed immediately
     * instead of being returned.
     *
     * @return string|null The Response content or null when the Response is streamed
     *
     * @throws \RuntimeException when the Response is not successful
     */
    protected function deliver(Response $response): ?string
    {
        if (!$response->isSuccessful()) {
            $responseStatusCode = $response->getStatusCode();
            throw new \RuntimeException(\sprintf('Error when rendering "%s" (Status code is %d).', $this->requestStack->getCurrentRequest()->getUri(), $responseStatusCode), 0, new HttpException($responseStatusCode));
        }
        if (!$response instanceof StreamedResponse) {
            return $response->getContent();
        }
        $response->sendContent();
        return null;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\HttpKernel\Fragment;

use _ContaoManager\Symfony\Component\HttpFoundation\Request;
use _ContaoManager\Symfony\Component\HttpKernel\Controller\ControllerReference;
use _ContaoManager\Symfony\Component\HttpKernel\EventListener\FragmentListener;
/**
 * Adds the possibility to generate a fragment URI for a given Controller.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
abstract class RoutableFragmentRenderer implements FragmentRendererInterface
{
    /**
     * @internal
     */
    protected string $fragmentPath = '/_fragment';
    /**
     * Sets the fragment path that triggers the fragment listener.
     *
     * @see FragmentListener
     *
     * @return void
     */
    public function setFragmentPath(string $path)
    {
        $this->fragmentPath = $path;
    }
    /**
     * Generates a fragment URI for a given controller.
     *
     * @param bool $absolute Whether to generate an absolute URL or not
     * @param bool $strict   Whether to allow non-scalar attributes or not
     */
    protected function generateFragmentUri(ControllerReference $reference, Request $request, bool $absolute = \false, bool $strict = \true): string
    {
        return (new FragmentUriGenerator($this->fragmentPath))->generate($reference, $request, $absolute, $strict, \false);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\HttpKernel;

use _ContaoManager\Symfony\Component\HttpKernel\Event\ControllerArgumentsEvent;
use _ContaoManager\Symfony\Component\HttpKernel\Event\ControllerEvent;
use _ContaoManager\Symfony\Component\HttpKernel\Event\ExceptionEvent;
use _ContaoManager\Symfony\Component\HttpKernel\Event\FinishRequestEvent;
use _ContaoManager\Symfony\Component\HttpKernel\Event\RequestEvent;
use _ContaoManager\Symfony\Component\HttpKernel\Event\ResponseEvent;
use _ContaoManager\Symfony\Component\HttpKernel\Event\TerminateEvent;
use _ContaoManager\Symfony\Component\HttpKernel\Event\ViewEvent;
/**
 * Contains all events thrown in the HttpKernel component.
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
final class KernelEvents
{
    /**
     * The REQUEST event occurs at the very beginning of request
     * dispatching.
     *
     * This event allows you to create a response for a request before any
     * other code in the framework is executed.
     *
     * @Event("Symfony\Component\HttpKernel\Event\RequestEvent")
     */
    public const REQUEST = 'kernel.request';
    /**
     * The EXCEPTION event occurs when an uncaught exception appears.
     *
     * This event allows you to create a response for a thrown exception or
     * to modify the thrown exception.
     *
     * @Event("Symfony\Component\HttpKernel\Event\ExceptionEvent")
     */
    public const EXCEPTION = 'kernel.exception';
    /**
     * The CONTROLLER event occurs once a controller was found for
     * handling a request.
     *
     * This event allows you to change the controller that will handle the
     * request.
     *
     * @Event("Symfony\Component\HttpKernel\Event\ControllerEvent")
     */
    public const CONTROLLER = 'kernel.controller';
    /**
     * The CONTROLLER_ARGUMENTS event occurs once controller arguments have been resolved.
     *
     * This event allows you to change the arguments that will be passed to
     * the controller.
     *
     * @Event("Symfony\Component\HttpKernel\Event\ControllerArgumentsEvent")
     */
    public const CONTROLLER_ARGUMENTS = 'kernel.controller_arguments';
    /**
     * The VIEW event occurs when the return value of a controller
     * is not a Response instance.
     *
     * This event allows you to create a response for the return value of the
     * controller.
     *
     * @Event("Symfony\Component\HttpKernel\Event\ViewEvent")
     */
    public const VIEW = 'kernel.view';
    /**
     * The RESPONSE event occurs once a response was created for
     * replying to a request.
     *
     * This event allows you to modify or replace the response that will be
     * replied.
     *
     * @Event("Symfony\Component\HttpKernel\Event\ResponseEvent")
     */
    public const RESPONSE = 'kernel.response';
    /**
     * The FINISH_REQUEST event occurs when a response was generated for a request.
     *
     * This event allows you to reset the global and environmental state of
     * the application, when it was changed during the request.
     *
     * @Event("Symfony\Component\HttpKernel\Event\FinishRequestEvent")
     */
    public const FINISH_REQUEST = 'kernel.finish_request';
    /**
     * The TERMINATE event occurs once a response was sent.
     *
     * This event allows you to run expensive post-response jobs.
     *
     * @Event("Symfony\Component\HttpKernel\Event\TerminateEvent")
     */
    public const TERMINATE = 'kernel.terminate';
    /**
     * Event aliases.
     *
     * These aliases can be consumed by RegisterListenersPass.
     */
    public const ALIASES = [ControllerArgumentsEvent::class => self::CONTROLLER_ARGUMENTS, ControllerEvent::class => self::CONTROLLER, ResponseEvent::class => self::RESPONSE, FinishRequestEvent::class => self::FINISH_REQUEST, RequestEvent::class => self::REQUEST, ViewEvent::class => self::VIEW, ExceptionEvent::class => self::EXCEPTION, TerminateEvent::class => self::TERMINATE];
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\HttpKernel\HttpCache;

use _ContaoManager\Symfony\Component\HttpFoundation\Request;
use _ContaoManager\Symfony\Component\HttpFoundation\Response;
/**
 * Esi implements the ESI capabilities to Request and Response instances.
 *
 * For more information, read the following W3C notes:
 *
 *  * ESI Language Specification 1.0 (http://www.w3.org/TR/esi-lang)
 *
 *  * Edge Architecture Specification (http://www.w3.org/TR/edge-arch)
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class Esi extends AbstractSurrogate
{
    public function getName(): string
    {
        return 'esi';
    }
    /**
     * @return void
     */
    public function addSurrogateControl(Response $response)
    {
        if (str_contains($response->getContent(), '<esi:include')) {
            $response->headers->set('Surrogate-Control', 'content="ESI/1.0"');
        }
    }
    public function renderIncludeTag(string $uri, ?string $alt = null, bool $ignoreErrors = \true, string $comment = ''): string
    {
        $html = \sprintf('<esi:include src="%s"%s%s />', $uri, $ignoreErrors ? ' onerror="continue"' : '', $alt ? \sprintf(' alt="%s"', $alt) : '');
        if (!empty($comment)) {
            return \sprintf("<esi:comment text=\"%s\" />\n%s", $comment, $html);
        }
        return $html;
    }
    public function process(Request $request, Response $response): Response
    {
        $type = $response->headers->get('Content-Type');
        if (empty($type)) {
            $type = 'text/html';
        }
        $parts = explode(';', $type);
        if (!\in_array($parts[0], $this->contentTypes)) {
            return $response;
        }
        // we don't use a proper XML parser here as we can have ESI tags in a plain text response
        $content = $response->getContent();
        $content = preg_replace('#<esi\:remove>.*?</esi\:remove>#s', '', $content);
        $content = preg_replace('#<esi\:comment[^>]+>#s', '', $content);
        $boundary = self::generateBodyEvalBoundary();
        $chunks = preg_split('#<esi\:include\s+(.*?)\s*(?:/|</esi\:include)>#', $content, -1, \PREG_SPLIT_DELIM_CAPTURE);
        $i = 1;
        while (isset($chunks[$i])) {
            $options = [];
            preg_match_all('/(src|onerror|alt)="([^"]*?)"/', $chunks[$i], $matches, \PREG_SET_ORDER);
            foreach ($matches as $set) {
                $options[$set[1]] = $set[2];
            }
            if (!isset($options['src'])) {
                throw new \RuntimeException('Unable to process an ESI tag without a "src" attribute.');
            }
            $chunks[$i] = $boundary . $options['src'] . "\n" . ($options['alt'] ?? '') . "\n" . ('continue' === ($options['onerror'] ?? '')) . "\n";
            $i += 2;
        }
        $content = $boundary . implode('', $chunks) . $boundary;
        $response->setContent($content);
        $response->headers->set('X-Body-Eval', 'ESI');
        // remove ESI/1.0 from the Surrogate-Control header
        $this->removeFromControl($response);
        return $response;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
/*
 * This code is partially based on the Rack-Cache library by Ryan Tomayko,
 * which is released under the MIT license.
 * (based on commit 02d2b48d75bcb63cf1c0c7149c077ad256542801)
 */
namespace _ContaoManager\Symfony\Component\HttpKernel\HttpCache;

use _ContaoManager\Symfony\Component\HttpFoundation\Exception\SuspiciousOperationException;
use _ContaoManager\Symfony\Component\HttpFoundation\Request;
use _ContaoManager\Symfony\Component\HttpFoundation\Response;
use _ContaoManager\Symfony\Component\HttpKernel\HttpKernelInterface;
use _ContaoManager\Symfony\Component\HttpKernel\TerminableInterface;
/**
 * Cache provides HTTP caching.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class HttpCache implements HttpKernelInterface, TerminableInterface
{
    public const BODY_EVAL_BOUNDARY_LENGTH = 24;
    private HttpKernelInterface $kernel;
    private StoreInterface $store;
    private Request $request;
    private ?SurrogateInterface $surrogate;
    private ?ResponseCacheStrategyInterface $surrogateCacheStrategy = null;
    private array $options = [];
    private array $traces = [];
    /**
     * Constructor.
     *
     * The available options are:
     *
     *   * debug                  If true, exceptions are thrown when things go wrong. Otherwise, the cache
     *                            will try to carry on and deliver a meaningful response.
     *
     *   * trace_level            May be one of 'none', 'short' and 'full'. For 'short', a concise trace of the
     *                            main request will be added as an HTTP header. 'full' will add traces for all
     *                            requests (including ESI subrequests). (default: 'full' if in debug; 'none' otherwise)
     *
     *   * trace_header           Header name to use for traces. (default: X-Symfony-Cache)
     *
     *   * default_ttl            The number of seconds that a cache entry should be considered
     *                            fresh when no explicit freshness information is provided in
     *                            a response. Explicit Cache-Control or Expires headers
     *                            override this value. (default: 0)
     *
     *   * private_headers        Set of request headers that trigger "private" cache-control behavior
     *                            on responses that don't explicitly state whether the response is
     *                            public or private via a Cache-Control directive. (default: Authorization and Cookie)
     *
     *   * skip_response_headers  Set of response headers that are never cached even if a response is cacheable (public).
     *                            (default: Set-Cookie)
     *
     *   * allow_reload           Specifies whether the client can force a cache reload by including a
     *                            Cache-Control "no-cache" directive in the request. Set it to ``true``
     *                            for compliance with RFC 2616. (default: false)
     *
     *   * allow_revalidate       Specifies whether the client can force a cache revalidate by including
     *                            a Cache-Control "max-age=0" directive in the request. Set it to ``true``
     *                            for compliance with RFC 2616. (default: false)
     *
     *   * stale_while_revalidate Specifies the default number of seconds (the granularity is the second as the
     *                            Response TTL precision is a second) during which the cache can immediately return
     *                            a stale response while it revalidates it in the background (default: 2).
     *                            This setting is overridden by the stale-while-revalidate HTTP Cache-Control
     *                            extension (see RFC 5861).
     *
     *   * stale_if_error         Specifies the default number of seconds (the granularity is the second) during which
     *                            the cache can serve a stale response when an error is encountered (default: 60).
     *                            This setting is overridden by the stale-if-error HTTP Cache-Control extension
     *                            (see RFC 5861).
     *
     *   * terminate_on_cache_hit Specifies if the kernel.terminate event should be dispatched even when the cache
     *                            was hit (default: true).
     *                            Unless your application needs to process events on cache hits, it is recommended
     *                            to set this to false to avoid having to bootstrap the Symfony framework on a cache hit.
     */
    public function __construct(HttpKernelInterface $kernel, StoreInterface $store, ?SurrogateInterface $surrogate = null, array $options = [])
    {
        $this->store = $store;
        $this->kernel = $kernel;
        $this->surrogate = $surrogate;
        // needed in case there is a fatal error because the backend is too slow to respond
        register_shutdown_function($this->store->cleanup(...));
        $this->options = array_merge(['debug' => \false, 'default_ttl' => 0, 'private_headers' => ['Authorization', 'Cookie'], 'skip_response_headers' => ['Set-Cookie'], 'allow_reload' => \false, 'allow_revalidate' => \false, 'stale_while_revalidate' => 2, 'stale_if_error' => 60, 'trace_level' => 'none', 'trace_header' => 'X-Symfony-Cache', 'terminate_on_cache_hit' => \true], $options);
        if (!isset($options['trace_level'])) {
            $this->options['trace_level'] = $this->options['debug'] ? 'full' : 'none';
        }
    }
    /**
     * Gets the current store.
     */
    public function getStore(): StoreInterface
    {
        return $this->store;
    }
    /**
     * Returns an array of events that took place during processing of the last request.
     */
    public function getTraces(): array
    {
        return $this->traces;
    }
    private function addTraces(Response $response): void
    {
        $traceString = null;
        if ('full' === $this->options['trace_level']) {
            $traceString = $this->getLog();
        }
        if ('short' === $this->options['trace_level'] && $masterId = array_key_first($this->traces)) {
            $traceString = implode('/', $this->traces[$masterId]);
        }
        if (null !== $traceString) {
            $response->headers->add([$this->options['trace_header'] => $traceString]);
        }
    }
    /**
     * Returns a log message for the events of the last request processing.
     */
    public function getLog(): string
    {
        $log = [];
        foreach ($this->traces as $request => $traces) {
            $log[] = \sprintf('%s: %s', $request, implode(', ', $traces));
        }
        return implode('; ', $log);
    }
    /**
     * Gets the Request instance associated with the main request.
     */
    public function getRequest(): Request
    {
        return $this->request;
    }
    /**
     * Gets the Kernel instance.
     */
    public function getKernel(): HttpKernelInterface
    {
        return $this->kernel;
    }
    /**
     * Gets the Surrogate instance.
     *
     * @throws \LogicException
     */
    public function getSurrogate(): SurrogateInterface
    {
        return $this->surrogate;
    }
    public function handle(Request $request, int $type = HttpKernelInterface::MAIN_REQUEST, bool $catch = \true): Response
    {
        // FIXME: catch exceptions and implement a 500 error page here? -> in Varnish, there is a built-in error page mechanism
        if (HttpKernelInterface::MAIN_REQUEST === $type) {
            $this->traces = [];
            // Keep a clone of the original request for surrogates so they can access it.
            // We must clone here to get a separate instance because the application will modify the request during
            // the application flow (we know it always does because we do ourselves by setting REMOTE_ADDR to 127.0.0.1
            // and adding the X-Forwarded-For header, see HttpCache::forward()).
            $this->request = clone $request;
            if (null !== $this->surrogate) {
                $this->surrogateCacheStrategy = $this->surrogate->createCacheStrategy();
            }
        }
        $this->traces[$this->getTraceKey($request)] = [];
        if (!$request->isMethodSafe()) {
            $response = $this->invalidate($request, $catch);
        } elseif ($request->headers->has('expect') || !$request->isMethodCacheable()) {
            $response = $this->pass($request, $catch);
        } elseif ($this->options['allow_reload'] && $request->isNoCache()) {
            /*
                If allow_reload is configured and the client requests "Cache-Control: no-cache",
                reload the cache by fetching a fresh response and caching it (if possible).
            */
            $this->record($request, 'reload');
            $response = $this->fetch($request, $catch);
        } else {
            $response = null;
            do {
                try {
                    $response = $this->lookup($request, $catch);
                } catch (CacheWasLockedException) {
                }
            } while (null === $response);
        }
        $this->restoreResponseBody($request, $response);
        if (HttpKernelInterface::MAIN_REQUEST === $type) {
            $this->addTraces($response);
        }
        if (null !== $this->surrogate) {
            if (HttpKernelInterface::MAIN_REQUEST === $type) {
                $this->surrogateCacheStrategy->update($response);
            } else {
                $this->surrogateCacheStrategy->add($response);
            }
        }
        $response->prepare($request);
        if (HttpKernelInterface::MAIN_REQUEST === $type) {
            $response->isNotModified($request);
        }
        return $response;
    }
    /**
     * @return void
     */
    public function terminate(Request $request, Response $response)
    {
        // Do not call any listeners in case of a cache hit.
        // This ensures identical behavior as if you had a separate
        // reverse caching proxy such as Varnish and the like.
        if ($this->options['terminate_on_cache_hit']) {
            trigger_deprecation('symfony/http-kernel', '6.2', 'Setting "terminate_on_cache_hit" to "true" is deprecated and will be changed to "false" in Symfony 7.0.');
        } elseif (\in_array('fresh', $this->traces[$this->getTraceKey($request)] ?? [], \true)) {
            return;
        }
        if ($this->getKernel() instanceof TerminableInterface) {
            $this->getKernel()->terminate($request, $response);
        }
    }
    /**
     * Forwards the Request to the backend without storing the Response in the cache.
     *
     * @param bool $catch Whether to process exceptions
     */
    protected function pass(Request $request, bool $catch = \false): Response
    {
        $this->record($request, 'pass');
        return $this->forward($request, $catch);
    }
    /**
     * Invalidates non-safe methods (like POST, PUT, and DELETE).
     *
     * @param bool $catch Whether to process exceptions
     *
     * @throws \Exception
     *
     * @see RFC2616 13.10
     */
    protected function invalidate(Request $request, bool $catch = \false): Response
    {
        $response = $this->pass($request, $catch);
        // invalidate only when the response is successful
        if ($response->isSuccessful() || $response->isRedirect()) {
            try {
                $this->store->invalidate($request);
                // As per the RFC, invalidate Location and Content-Location URLs if present
                foreach (['Location', 'Content-Location'] as $header) {
                    if ($uri = $response->headers->get($header)) {
                        $subRequest = Request::create($uri, 'get', [], [], [], $request->server->all());
                        $this->store->invalidate($subRequest);
                    }
                }
                $this->record($request, 'invalidate');
            } catch (\Exception $e) {
                $this->record($request, 'invalidate-failed');
                if ($this->options['debug']) {
                    throw $e;
                }
            }
        }
        return $response;
    }
    /**
     * Lookups a Response from the cache for the given Request.
     *
     * When a matching cache entry is found and is fresh, it uses it as the
     * response without forwarding any request to the backend. When a matching
     * cache entry is found but is stale, it attempts to "validate" the entry with
     * the backend using conditional GET. When no matching cache entry is found,
     * it triggers "miss" processing.
     *
     * @param bool $catch Whether to process exceptions
     *
     * @throws \Exception
     */
    protected function lookup(Request $request, bool $catch = \false): Response
    {
        try {
            $entry = $this->store->lookup($request);
        } catch (\Exception $e) {
            $this->record($request, 'lookup-failed');
            if ($this->options['debug']) {
                throw $e;
            }
            return $this->pass($request, $catch);
        }
        if (null === $entry) {
            $this->record($request, 'miss');
            return $this->fetch($request, $catch);
        }
        if (!$this->isFreshEnough($request, $entry)) {
            $this->record($request, 'stale');
            return $this->validate($request, $entry, $catch);
        }
        if ($entry->headers->hasCacheControlDirective('no-cache')) {
            return $this->validate($request, $entry, $catch);
        }
        $this->record($request, 'fresh');
        $entry->headers->set('Age', $entry->getAge());
        return $entry;
    }
    /**
     * Validates that a cache entry is fresh.
     *
     * The original request is used as a template for a conditional
     * GET request with the backend.
     *
     * @param bool $catch Whether to process exceptions
     */
    protected function validate(Request $request, Response $entry, bool $catch = \false): Response
    {
        $subRequest = clone $request;
        // send no head requests because we want content
        if ('HEAD' === $request->getMethod()) {
            $subRequest->setMethod('GET');
        }
        // add our cached last-modified validator
        if ($entry->headers->has('Last-Modified')) {
            $subRequest->headers->set('If-Modified-Since', $entry->headers->get('Last-Modified'));
        }
        // Add our cached etag validator to the environment.
        // We keep the etags from the client to handle the case when the client
        // has a different private valid entry which is not cached here.
        $cachedEtags = $entry->getEtag() ? [$entry->getEtag()] : [];
        $requestEtags = $request->getETags();
        if ($etags = array_unique(array_merge($cachedEtags, $requestEtags))) {
            $subRequest->headers->set('If-None-Match', implode(', ', $etags));
        }
        $response = $this->forward($subRequest, $catch, $entry);
        if (304 == $response->getStatusCode()) {
            $this->record($request, 'valid');
            // return the response and not the cache entry if the response is valid but not cached
            $etag = $response->getEtag();
            if ($etag && \in_array($etag, $requestEtags) && !\in_array($etag, $cachedEtags)) {
                return $response;
            }
            $entry = clone $entry;
            $entry->headers->remove('Date');
            foreach (['Date', 'Expires', 'Cache-Control', 'ETag', 'Last-Modified'] as $name) {
                if ($response->headers->has($name)) {
                    $entry->headers->set($name, $response->headers->get($name));
                }
            }
            $response = $entry;
        } else {
            $this->record($request, 'invalid');
        }
        if ($response->isCacheable()) {
            $this->store($request, $response);
        }
        return $response;
    }
    /**
     * Unconditionally fetches a fresh response from the backend and
     * stores it in the cache if is cacheable.
     *
     * @param bool $catch Whether to process exceptions
     */
    protected function fetch(Request $request, bool $catch = \false): Response
    {
        $subRequest = clone $request;
        // send no head requests because we want content
        if ('HEAD' === $request->getMethod()) {
            $subRequest->setMethod('GET');
        }
        // avoid that the backend sends no content
        $subRequest->headers->remove('If-Modified-Since');
        $subRequest->headers->remove('If-None-Match');
        $response = $this->forward($subRequest, $catch);
        if ($response->isCacheable()) {
            $this->store($request, $response);
        }
        return $response;
    }
    /**
     * Forwards the Request to the backend and returns the Response.
     *
     * All backend requests (cache passes, fetches, cache validations)
     * run through this method.
     *
     * @param bool          $catch Whether to catch exceptions or not
     * @param Response|null $entry A Response instance (the stale entry if present, null otherwise)
     *
     * @return Response
     */
    protected function forward(Request $request, bool $catch = \false, ?Response $entry = null)
    {
        $this->surrogate?->addSurrogateCapability($request);
        // always a "master" request (as the real master request can be in cache)
        $response = SubRequestHandler::handle($this->kernel, $request, HttpKernelInterface::MAIN_REQUEST, $catch);
        /*
         * Support stale-if-error given on Responses or as a config option.
         * RFC 7234 summarizes in Section 4.2.4 (but also mentions with the individual
         * Cache-Control directives) that
         *
         *      A cache MUST NOT generate a stale response if it is prohibited by an
         *      explicit in-protocol directive (e.g., by a "no-store" or "no-cache"
         *      cache directive, a "must-revalidate" cache-response-directive, or an
         *      applicable "s-maxage" or "proxy-revalidate" cache-response-directive;
         *      see Section 5.2.2).
         *
         * https://tools.ietf.org/html/rfc7234#section-4.2.4
         *
         * We deviate from this in one detail, namely that we *do* serve entries in the
         * stale-if-error case even if they have a `s-maxage` Cache-Control directive.
         */
        if (null !== $entry && \in_array($response->getStatusCode(), [500, 502, 503, 504]) && !$entry->headers->hasCacheControlDirective('no-cache') && !$entry->mustRevalidate()) {
            if (null === $age = $entry->headers->getCacheControlDirective('stale-if-error')) {
                $age = $this->options['stale_if_error'];
            }
            /*
             * stale-if-error gives the (extra) time that the Response may be used *after* it has become stale.
             * So we compare the time the $entry has been sitting in the cache already with the
             * time it was fresh plus the allowed grace period.
             */
            if ($entry->getAge() <= $entry->getMaxAge() + $age) {
                $this->record($request, 'stale-if-error');
                return $entry;
            }
        }
        /*
            RFC 7231 Sect. 7.1.1.2 says that a server that does not have a reasonably accurate
            clock MUST NOT send a "Date" header, although it MUST send one in most other cases
            except for 1xx or 5xx responses where it MAY do so.
        
            Anyway, a client that received a message without a "Date" header MUST add it.
        */
        if (!$response->headers->has('Date')) {
            $response->setDate(\DateTimeImmutable::createFromFormat('U', time()));
        }
        $this->processResponseBody($request, $response);
        if ($this->isPrivateRequest($request) && !$response->headers->hasCacheControlDirective('public')) {
            $response->setPrivate();
        } elseif ($this->options['default_ttl'] > 0 && null === $response->getTtl() && !$response->headers->getCacheControlDirective('must-revalidate')) {
            $response->setTtl($this->options['default_ttl']);
        }
        return $response;
    }
    /**
     * Checks whether the cache entry is "fresh enough" to satisfy the Request.
     */
    protected function isFreshEnough(Request $request, Response $entry): bool
    {
        if (!$entry->isFresh()) {
            return $this->lock($request, $entry);
        }
        if ($this->options['allow_revalidate'] && null !== $maxAge = $request->headers->getCacheControlDirective('max-age')) {
            return $maxAge > 0 && $maxAge >= $entry->getAge();
        }
        return \true;
    }
    /**
     * Locks a Request during the call to the backend.
     *
     * @return bool true if the cache entry can be returned even if it is staled, false otherwise
     */
    protected function lock(Request $request, Response $entry): bool
    {
        // try to acquire a lock to call the backend
        $lock = $this->store->lock($request);
        if (\true === $lock) {
            // we have the lock, call the backend
            return \false;
        }
        // there is already another process calling the backend
        // May we serve a stale response?
        if ($this->mayServeStaleWhileRevalidate($entry)) {
            $this->record($request, 'stale-while-revalidate');
            return \true;
        }
        // wait for the lock to be released
        if ($this->waitForLock($request)) {
            throw new CacheWasLockedException();
            // unwind back to handle(), try again
        } else {
            // backend is slow as hell, send a 503 response (to avoid the dog pile effect)
            $entry->setStatusCode(503);
            $entry->setContent('503 Service Unavailable');
            $entry->headers->set('Retry-After', 10);
        }
        return \true;
    }
    /**
     * Writes the Response to the cache.
     *
     * @return void
     *
     * @throws \Exception
     */
    protected function store(Request $request, Response $response)
    {
        try {
            $restoreHeaders = [];
            foreach ($this->options['skip_response_headers'] as $header) {
                if (!$response->headers->has($header)) {
                    continue;
                }
                $restoreHeaders[$header] = $response->headers->all($header);
                $response->headers->remove($header);
            }
            $this->store->write($request, $response);
            $this->record($request, 'store');
            $response->headers->set('Age', $response->getAge());
        } catch (\Exception $e) {
            $this->record($request, 'store-failed');
            if ($this->options['debug']) {
                throw $e;
            }
        } finally {
            foreach ($restoreHeaders as $header => $values) {
                $response->headers->set($header, $values);
            }
        }
        // now that the response is cached, release the lock
        $this->store->unlock($request);
    }
    /**
     * Restores the Response body.
     */
    private function restoreResponseBody(Request $request, Response $response): void
    {
        if ($response->headers->has('X-Body-Eval')) {
            \assert(self::BODY_EVAL_BOUNDARY_LENGTH === 24);
            ob_start();
            $content = $response->getContent();
            $boundary = substr($content, 0, 24);
            $j = strpos($content, $boundary, 24);
            echo substr($content, 24, $j - 24);
            $i = $j + 24;
            while (\false !== $j = strpos($content, $boundary, $i)) {
                [$uri, $alt, $ignoreErrors, $part] = explode("\n", substr($content, $i, $j - $i), 4);
                $i = $j + 24;
                echo $this->surrogate->handle($this, $uri, $alt, $ignoreErrors);
                echo $part;
            }
            $response->setContent(ob_get_clean());
            $response->headers->remove('X-Body-Eval');
            if (!$response->headers->has('Transfer-Encoding')) {
                $response->headers->set('Content-Length', \strlen($response->getContent()));
            }
        } elseif ($response->headers->has('X-Body-File')) {
            // Response does not include possibly dynamic content (ESI, SSI), so we need
            // not handle the content for HEAD requests
            if (!$request->isMethod('HEAD')) {
                $response->setContent(file_get_contents($response->headers->get('X-Body-File')));
            }
        } else {
            return;
        }
        $response->headers->remove('X-Body-File');
    }
    /**
     * @return void
     */
    protected function processResponseBody(Request $request, Response $response)
    {
        if ($this->surrogate?->needsParsing($response)) {
            $this->surrogate->process($request, $response);
        }
    }
    /**
     * Checks if the Request includes authorization or other sensitive information
     * that should cause the Response to be considered private by default.
     */
    private function isPrivateRequest(Request $request): bool
    {
        foreach ($this->options['private_headers'] as $key) {
            $key = strtolower(str_replace('HTTP_', '', $key));
            if ('cookie' === $key) {
                if (\count($request->cookies->all())) {
                    return \true;
                }
            } elseif ($request->headers->has($key)) {
                return \true;
            }
        }
        return \false;
    }
    /**
     * Records that an event took place.
     */
    private function record(Request $request, string $event): void
    {
        $this->traces[$this->getTraceKey($request)][] = $event;
    }
    /**
     * Calculates the key we use in the "trace" array for a given request.
     */
    private function getTraceKey(Request $request): string
    {
        $path = $request->getPathInfo();
        if ($qs = $request->getQueryString()) {
            $path .= '?' . $qs;
        }
        try {
            return $request->getMethod() . ' ' . $path;
        } catch (SuspiciousOperationException $e) {
            return '_BAD_METHOD_ ' . $path;
        }
    }
    /**
     * Checks whether the given (cached) response may be served as "stale" when a revalidation
     * is currently in progress.
     */
    private function mayServeStaleWhileRevalidate(Response $entry): bool
    {
        $timeout = $entry->headers->getCacheControlDirective('stale-while-revalidate');
        $timeout ??= $this->options['stale_while_revalidate'];
        $age = $entry->getAge();
        $maxAge = $entry->getMaxAge() ?? 0;
        $ttl = $maxAge - $age;
        return abs($ttl) < $timeout;
    }
    /**
     * Waits for the store to release a locked entry.
     */
    private function waitForLock(Request $request): bool
    {
        $wait = 0;
        while ($this->store->isLocked($request) && $wait < 100) {
            usleep(50000);
            ++$wait;
        }
        return $wait < 100;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * This code is partially based on the Rack-Cache library by Ryan Tomayko,
 * which is released under the MIT license.
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\HttpKernel\HttpCache;

use _ContaoManager\Symfony\Component\HttpFoundation\Request;
use _ContaoManager\Symfony\Component\HttpFoundation\Response;
/**
 * Store implements all the logic for storing cache metadata (Request and Response headers).
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class Store implements StoreInterface
{
    protected $root;
    /** @var \SplObjectStorage<Request, string> */
    private \SplObjectStorage $keyCache;
    /** @var array<string, resource> */
    private array $locks = [];
    private array $options;
    /**
     * Constructor.
     *
     * The available options are:
     *
     *   * private_headers  Set of response headers that should not be stored
     *                      when a response is cached. (default: Set-Cookie)
     *
     * @throws \RuntimeException
     */
    public function __construct(string $root, array $options = [])
    {
        $this->root = $root;
        if (!is_dir($this->root) && !@mkdir($this->root, 0777, \true) && !is_dir($this->root)) {
            throw new \RuntimeException(\sprintf('Unable to create the store directory (%s).', $this->root));
        }
        $this->keyCache = new \SplObjectStorage();
        $this->options = array_merge(['private_headers' => ['Set-Cookie']], $options);
    }
    /**
     * Cleanups storage.
     *
     * @return void
     */
    public function cleanup()
    {
        // unlock everything
        foreach ($this->locks as $lock) {
            flock($lock, \LOCK_UN);
            fclose($lock);
        }
        $this->locks = [];
    }
    /**
     * Tries to lock the cache for a given Request, without blocking.
     *
     * @return bool|string true if the lock is acquired, the path to the current lock otherwise
     */
    public function lock(Request $request): bool|string
    {
        $key = $this->getCacheKey($request);
        if (!isset($this->locks[$key])) {
            $path = $this->getPath($key);
            if (!is_dir(\dirname($path)) && \false === @mkdir(\dirname($path), 0777, \true) && !is_dir(\dirname($path))) {
                return $path;
            }
            $h = fopen($path, 'c');
            if (!flock($h, \LOCK_EX | \LOCK_NB)) {
                fclose($h);
                return $path;
            }
            $this->locks[$key] = $h;
        }
        return \true;
    }
    /**
     * Releases the lock for the given Request.
     *
     * @return bool False if the lock file does not exist or cannot be unlocked, true otherwise
     */
    public function unlock(Request $request): bool
    {
        $key = $this->getCacheKey($request);
        if (isset($this->locks[$key])) {
            flock($this->locks[$key], \LOCK_UN);
            fclose($this->locks[$key]);
            unset($this->locks[$key]);
            return \true;
        }
        return \false;
    }
    public function isLocked(Request $request): bool
    {
        $key = $this->getCacheKey($request);
        if (isset($this->locks[$key])) {
            return \true;
            // shortcut if lock held by this process
        }
        if (!is_file($path = $this->getPath($key))) {
            return \false;
        }
        $h = fopen($path, 'r');
        flock($h, \LOCK_EX | \LOCK_NB, $wouldBlock);
        flock($h, \LOCK_UN);
        // release the lock we just acquired
        fclose($h);
        return (bool) $wouldBlock;
    }
    /**
     * Locates a cached Response for the Request provided.
     */
    public function lookup(Request $request): ?Response
    {
        $key = $this->getCacheKey($request);
        if (!$entries = $this->getMetadata($key)) {
            return null;
        }
        // find a cached entry that matches the request.
        $match = null;
        foreach ($entries as $entry) {
            if ($this->requestsMatch(isset($entry[1]['vary'][0]) ? implode(', ', $entry[1]['vary']) : '', $request->headers->all(), $entry[0])) {
                $match = $entry;
                break;
            }
        }
        if (null === $match) {
            return null;
        }
        $headers = $match[1];
        if (file_exists($path = $this->getPath($headers['x-content-digest'][0]))) {
            return $this->restoreResponse($headers, $path);
        }
        // TODO the metaStore referenced an entity that doesn't exist in
        // the entityStore. We definitely want to return nil but we should
        // also purge the entry from the meta-store when this is detected.
        return null;
    }
    /**
     * Writes a cache entry to the store for the given Request and Response.
     *
     * Existing entries are read and any that match the response are removed. This
     * method calls write with the new list of cache entries.
     *
     * @throws \RuntimeException
     */
    public function write(Request $request, Response $response): string
    {
        $key = $this->getCacheKey($request);
        $storedEnv = $this->persistRequest($request);
        if ($response->headers->has('X-Body-File')) {
            // Assume the response came from disk, but at least perform some safeguard checks
            if (!$response->headers->has('X-Content-Digest')) {
                throw new \RuntimeException('A restored response must have the X-Content-Digest header.');
            }
            $digest = $response->headers->get('X-Content-Digest');
            if ($this->getPath($digest) !== $response->headers->get('X-Body-File')) {
                throw new \RuntimeException('X-Body-File and X-Content-Digest do not match.');
            }
            // Everything seems ok, omit writing content to disk
        } else {
            $digest = $this->generateContentDigest($response);
            $response->headers->set('X-Content-Digest', $digest);
            if (!$this->save($digest, $response->getContent(), \false)) {
                throw new \RuntimeException('Unable to store the entity.');
            }
            if (!$response->headers->has('Transfer-Encoding')) {
                $response->headers->set('Content-Length', \strlen($response->getContent()));
            }
        }
        // read existing cache entries, remove non-varying, and add this one to the list
        $entries = [];
        $vary = implode(', ', $response->headers->all('vary'));
        foreach ($this->getMetadata($key) as $entry) {
            if (!$this->requestsMatch($vary ?? '', $entry[0], $storedEnv)) {
                $entries[] = $entry;
            }
        }
        $headers = $this->persistResponse($response);
        unset($headers['age']);
        foreach ($this->options['private_headers'] as $h) {
            unset($headers[strtolower($h)]);
        }
        array_unshift($entries, [$storedEnv, $headers]);
        if (!$this->save($key, serialize($entries))) {
            throw new \RuntimeException('Unable to store the metadata.');
        }
        return $key;
    }
    /**
     * Returns content digest for $response.
     */
    protected function generateContentDigest(Response $response): string
    {
        return 'en' . hash('xxh128', $response->getContent());
    }
    /**
     * Invalidates all cache entries that match the request.
     *
     * @return void
     *
     * @throws \RuntimeException
     */
    public function invalidate(Request $request)
    {
        $modified = \false;
        $key = $this->getCacheKey($request);
        $entries = [];
        foreach ($this->getMetadata($key) as $entry) {
            $response = $this->restoreResponse($entry[1]);
            if ($response->isFresh()) {
                $response->expire();
                $modified = \true;
                $entries[] = [$entry[0], $this->persistResponse($response)];
            } else {
                $entries[] = $entry;
            }
        }
        if ($modified && !$this->save($key, serialize($entries))) {
            throw new \RuntimeException('Unable to store the metadata.');
        }
    }
    /**
     * Determines whether two Request HTTP header sets are non-varying based on
     * the vary response header value provided.
     *
     * @param string|null $vary A Response vary header
     * @param array       $env1 A Request HTTP header array
     * @param array       $env2 A Request HTTP header array
     */
    private function requestsMatch(?string $vary, array $env1, array $env2): bool
    {
        if ('' === ($vary ?? '')) {
            return \true;
        }
        foreach (preg_split('/[\s,]+/', $vary) as $header) {
            $key = str_replace('_', '-', strtolower($header));
            $v1 = $env1[$key] ?? null;
            $v2 = $env2[$key] ?? null;
            if ($v1 !== $v2) {
                return \false;
            }
        }
        return \true;
    }
    /**
     * Gets all data associated with the given key.
     *
     * Use this method only if you know what you are doing.
     */
    private function getMetadata(string $key): array
    {
        if (!$entries = $this->load($key)) {
            return [];
        }
        return unserialize($entries) ?: [];
    }
    /**
     * Purges data for the given URL.
     *
     * This method purges both the HTTP and the HTTPS version of the cache entry.
     *
     * @return bool true if the URL exists with either HTTP or HTTPS scheme and has been purged, false otherwise
     */
    public function purge(string $url): bool
    {
        $http = preg_replace('#^https:#', 'http:', $url);
        $https = preg_replace('#^http:#', 'https:', $url);
        $purgedHttp = $this->doPurge($http);
        $purgedHttps = $this->doPurge($https);
        return $purgedHttp || $purgedHttps;
    }
    /**
     * Purges data for the given URL.
     */
    private function doPurge(string $url): bool
    {
        $key = $this->getCacheKey(Request::create($url));
        if (isset($this->locks[$key])) {
            flock($this->locks[$key], \LOCK_UN);
            fclose($this->locks[$key]);
            unset($this->locks[$key]);
        }
        if (is_file($path = $this->getPath($key))) {
            unlink($path);
            return \true;
        }
        return \false;
    }
    /**
     * Loads data for the given key.
     */
    private function load(string $key): ?string
    {
        $path = $this->getPath($key);
        return is_file($path) && \false !== ($contents = @file_get_contents($path)) ? $contents : null;
    }
    /**
     * Save data for the given key.
     */
    private function save(string $key, string $data, bool $overwrite = \true): bool
    {
        $path = $this->getPath($key);
        if (!$overwrite && file_exists($path)) {
            return \true;
        }
        if (isset($this->locks[$key])) {
            $fp = $this->locks[$key];
            @ftruncate($fp, 0);
            @fseek($fp, 0);
            $len = @fwrite($fp, $data);
            if (\strlen($data) !== $len) {
                @ftruncate($fp, 0);
                return \false;
            }
        } else {
            if (!is_dir(\dirname($path)) && \false === @mkdir(\dirname($path), 0777, \true) && !is_dir(\dirname($path))) {
                return \false;
            }
            $tmpFile = tempnam(\dirname($path), basename($path));
            if (\false === $fp = @fopen($tmpFile, 'w')) {
                @unlink($tmpFile);
                return \false;
            }
            @fwrite($fp, $data);
            @fclose($fp);
            if ($data != file_get_contents($tmpFile)) {
                @unlink($tmpFile);
                return \false;
            }
            if (\false === @rename($tmpFile, $path)) {
                @unlink($tmpFile);
                return \false;
            }
        }
        @chmod($path, 0666 & ~umask());
        return \true;
    }
    /**
     * @return string
     */
    public function getPath(string $key)
    {
        return $this->root . \DIRECTORY_SEPARATOR . substr($key, 0, 2) . \DIRECTORY_SEPARATOR . substr($key, 2, 2) . \DIRECTORY_SEPARATOR . substr($key, 4, 2) . \DIRECTORY_SEPARATOR . substr($key, 6);
    }
    /**
     * Generates a cache key for the given Request.
     *
     * This method should return a key that must only depend on a
     * normalized version of the request URI.
     *
     * If the same URI can have more than one representation, based on some
     * headers, use a Vary header to indicate them, and each representation will
     * be stored independently under the same cache key.
     */
    protected function generateCacheKey(Request $request): string
    {
        return 'md' . hash('sha256', $request->getUri());
    }
    /**
     * Returns a cache key for the given Request.
     */
    private function getCacheKey(Request $request): string
    {
        if (isset($this->keyCache[$request])) {
            return $this->keyCache[$request];
        }
        return $this->keyCache[$request] = $this->generateCacheKey($request);
    }
    /**
     * Persists the Request HTTP headers.
     */
    private function persistRequest(Request $request): array
    {
        return $request->headers->all();
    }
    /**
     * Persists the Response HTTP headers.
     */
    private function persistResponse(Response $response): array
    {
        $headers = $response->headers->all();
        $headers['X-Status'] = [$response->getStatusCode()];
        return $headers;
    }
    /**
     * Restores a Response from the HTTP headers and body.
     */
    private function restoreResponse(array $headers, ?string $path = null): ?Response
    {
        $status = $headers['X-Status'][0];
        unset($headers['X-Status']);
        $content = null;
        if (null !== $path) {
            $headers['X-Body-File'] = [$path];
            unset($headers['x-body-file']);
            if ($headers['X-Body-Eval'] ?? $headers['x-body-eval'] ?? \false) {
                $content = file_get_contents($path);
                \assert(HttpCache::BODY_EVAL_BOUNDARY_LENGTH === 24);
                if (48 > \strlen($content) || substr($content, -24) !== substr($content, 0, 24)) {
                    return null;
                }
            }
        }
        return new Response($content, $status, $headers);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\HttpKernel\HttpCache;

use _ContaoManager\Symfony\Component\HttpFoundation\Request;
use _ContaoManager\Symfony\Component\HttpFoundation\Response;
interface SurrogateInterface
{
    /**
     * Returns surrogate name.
     */
    public function getName(): string;
    /**
     * Returns a new cache strategy instance.
     */
    public function createCacheStrategy(): ResponseCacheStrategyInterface;
    /**
     * Checks that at least one surrogate has Surrogate capability.
     */
    public function hasSurrogateCapability(Request $request): bool;
    /**
     * Adds Surrogate-capability to the given Request.
     *
     * @return void
     */
    public function addSurrogateCapability(Request $request);
    /**
     * Adds HTTP headers to specify that the Response needs to be parsed for Surrogate.
     *
     * This method only adds an Surrogate HTTP header if the Response has some Surrogate tags.
     *
     * @return void
     */
    public function addSurrogateControl(Response $response);
    /**
     * Checks that the Response needs to be parsed for Surrogate tags.
     */
    public function needsParsing(Response $response): bool;
    /**
     * Renders a Surrogate tag.
     *
     * @param string|null $alt     An alternate URI
     * @param string      $comment A comment to add as an esi:include tag
     */
    public function renderIncludeTag(string $uri, ?string $alt = null, bool $ignoreErrors = \true, string $comment = ''): string;
    /**
     * Replaces a Response Surrogate tags with the included resource content.
     */
    public function process(Request $request, Response $response): Response;
    /**
     * Handles a Surrogate from the cache.
     *
     * @param string $alt An alternative URI
     *
     * @throws \RuntimeException
     * @throws \Exception
     */
    public function handle(HttpCache $cache, string $uri, string $alt, bool $ignoreErrors): string;
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * This code is partially based on the Rack-Cache library by Ryan Tomayko,
 * which is released under the MIT license.
 * (based on commit 02d2b48d75bcb63cf1c0c7149c077ad256542801)
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\HttpKernel\HttpCache;

use _ContaoManager\Symfony\Component\HttpFoundation\Response;
/**
 * ResponseCacheStrategyInterface implementations know how to compute the
 * Response cache HTTP header based on the different response cache headers.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
interface ResponseCacheStrategyInterface
{
    /**
     * Adds a Response.
     *
     * @return void
     */
    public function add(Response $response);
    /**
     * Updates the Response HTTP headers based on the embedded Responses.
     *
     * @return void
     */
    public function update(Response $response);
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\HttpKernel\HttpCache;

use _ContaoManager\Symfony\Component\HttpFoundation\Response;
/**
 * ResponseCacheStrategy knows how to compute the Response cache HTTP header
 * based on the different response cache headers.
 *
 * This implementation changes the main response TTL to the smallest TTL received
 * or force validation if one of the surrogates has validation cache strategy.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class ResponseCacheStrategy implements ResponseCacheStrategyInterface
{
    /**
     * Cache-Control headers that are sent to the final response if they appear in ANY of the responses.
     */
    private const OVERRIDE_DIRECTIVES = ['private', 'no-cache', 'no-store', 'no-transform', 'must-revalidate', 'proxy-revalidate'];
    /**
     * Cache-Control headers that are sent to the final response if they appear in ALL of the responses.
     */
    private const INHERIT_DIRECTIVES = ['public', 'immutable'];
    private int $embeddedResponses = 0;
    private bool $isNotCacheableResponseEmbedded = \false;
    private int $age = 0;
    private \DateTimeInterface|false|null $lastModified = null;
    private array $flagDirectives = ['no-cache' => null, 'no-store' => null, 'no-transform' => null, 'must-revalidate' => null, 'proxy-revalidate' => null, 'public' => null, 'private' => null, 'immutable' => null];
    private array $ageDirectives = ['max-age' => null, 's-maxage' => null, 'expires' => \false];
    /**
     * @return void
     */
    public function add(Response $response)
    {
        ++$this->embeddedResponses;
        foreach (self::OVERRIDE_DIRECTIVES as $directive) {
            if ($response->headers->hasCacheControlDirective($directive)) {
                $this->flagDirectives[$directive] = \true;
            }
        }
        foreach (self::INHERIT_DIRECTIVES as $directive) {
            if (\false !== $this->flagDirectives[$directive]) {
                $this->flagDirectives[$directive] = $response->headers->hasCacheControlDirective($directive);
            }
        }
        $age = $response->getAge();
        $this->age = max($this->age, $age);
        if ($this->willMakeFinalResponseUncacheable($response)) {
            $this->isNotCacheableResponseEmbedded = \true;
            return;
        }
        $maxAge = $response->headers->hasCacheControlDirective('max-age') ? (int) $response->headers->getCacheControlDirective('max-age') : null;
        $sharedMaxAge = $response->headers->hasCacheControlDirective('s-maxage') ? (int) $response->headers->getCacheControlDirective('s-maxage') : $maxAge;
        $expires = $response->getExpires();
        $expires = null !== $expires ? (int) $expires->format('U') - (int) $response->getDate()->format('U') : null;
        // See https://datatracker.ietf.org/doc/html/rfc7234#section-4.2.2
        // If a response is "public" but does not have maximum lifetime, heuristics might be applied.
        // Do not store NULL values so the final response can have more limiting value from other responses.
        $isHeuristicallyCacheable = $response->headers->hasCacheControlDirective('public') && null === $maxAge && null === $sharedMaxAge && null === $expires;
        if (!$isHeuristicallyCacheable || null !== $maxAge || null !== $expires) {
            $this->storeRelativeAgeDirective('max-age', $maxAge, $expires, $age);
        }
        if (!$isHeuristicallyCacheable || null !== $sharedMaxAge || null !== $expires) {
            $this->storeRelativeAgeDirective('s-maxage', $sharedMaxAge, $expires, $age);
        }
        if (null !== $expires) {
            $this->ageDirectives['expires'] = \true;
        }
        if (\false !== $this->lastModified) {
            $lastModified = $response->getLastModified();
            $this->lastModified = $lastModified ? max($this->lastModified, $lastModified) : \false;
        }
    }
    /**
     * @return void
     */
    public function update(Response $response)
    {
        // if we have no embedded Response, do nothing
        if (0 === $this->embeddedResponses) {
            return;
        }
        // Remove Etag since it cannot be merged from embedded responses.
        $response->setEtag(null);
        $this->add($response);
        $response->headers->set('Age', $this->age);
        if ($this->isNotCacheableResponseEmbedded) {
            $response->setLastModified(null);
            if ($this->flagDirectives['no-store']) {
                $response->headers->set('Cache-Control', 'no-cache, no-store, must-revalidate');
            } else {
                $response->headers->set('Cache-Control', 'no-cache, must-revalidate');
            }
            return;
        }
        $response->setLastModified($this->lastModified ?: null);
        $flags = array_filter($this->flagDirectives);
        if (isset($flags['must-revalidate'])) {
            $flags['no-cache'] = \true;
        }
        $response->headers->set('Cache-Control', implode(', ', array_keys($flags)));
        $maxAge = null;
        if (is_numeric($this->ageDirectives['max-age'])) {
            $maxAge = $this->ageDirectives['max-age'] + $this->age;
            $response->headers->addCacheControlDirective('max-age', $maxAge);
        }
        if (is_numeric($this->ageDirectives['s-maxage'])) {
            $sMaxage = $this->ageDirectives['s-maxage'] + $this->age;
            if ($maxAge !== $sMaxage) {
                $response->headers->addCacheControlDirective('s-maxage', $sMaxage);
            }
        }
        if ($this->ageDirectives['expires'] && null !== $maxAge) {
            $date = clone $response->getDate();
            $date = $date->modify('+' . $maxAge . ' seconds');
            $response->setExpires($date);
        }
    }
    /**
     * RFC2616, Section 13.4.
     *
     * @see https://www.w3.org/Protocols/rfc2616/rfc2616-sec13.html#sec13.4
     */
    private function willMakeFinalResponseUncacheable(Response $response): bool
    {
        // RFC2616: A response received with a status code of 200, 203, 300, 301 or 410
        // MAY be stored by a cache […] unless a cache-control directive prohibits caching.
        if ($response->headers->hasCacheControlDirective('no-cache') || $response->headers->hasCacheControlDirective('no-store')) {
            return \true;
        }
        // Etag headers cannot be merged, they render the response uncacheable
        // by default (except if the response also has max-age etc.).
        if (null === $response->getEtag() && \in_array($response->getStatusCode(), [200, 203, 300, 301, 410])) {
            return \false;
        }
        // RFC2616: A response received with any other status code (e.g. status codes 302 and 307)
        // MUST NOT be returned in a reply to a subsequent request unless there are
        // cache-control directives or another header(s) that explicitly allow it.
        $cacheControl = ['max-age', 's-maxage', 'must-revalidate', 'proxy-revalidate', 'public', 'private'];
        foreach ($cacheControl as $key) {
            if ($response->headers->hasCacheControlDirective($key)) {
                return \false;
            }
        }
        if ($response->headers->has('Expires')) {
            return \false;
        }
        return \true;
    }
    /**
     * Store lowest max-age/s-maxage/expires for the final response.
     *
     * The response might have been stored in cache a while ago. To keep things comparable,
     * we have to subtract the age so that the value is normalized for an age of 0.
     *
     * If the value is lower than the currently stored value, we update the value, to keep a rolling
     * minimal value of each instruction. If the value is NULL, the directive will not be set on the final response.
     */
    private function storeRelativeAgeDirective(string $directive, ?int $value, ?int $expires, int $age): void
    {
        if (null === $value && null === $expires) {
            $this->ageDirectives[$directive] = \false;
        }
        if (\false !== $this->ageDirectives[$directive]) {
            $value = min($value ?? \PHP_INT_MAX, $expires ?? \PHP_INT_MAX);
            $value -= $age;
            $this->ageDirectives[$directive] = null !== $this->ageDirectives[$directive] ? min($this->ageDirectives[$directive], $value) : $value;
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * This code is partially based on the Rack-Cache library by Ryan Tomayko,
 * which is released under the MIT license.
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\HttpKernel\HttpCache;

use _ContaoManager\Symfony\Component\HttpFoundation\Request;
use _ContaoManager\Symfony\Component\HttpFoundation\Response;
/**
 * Interface implemented by HTTP cache stores.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
interface StoreInterface
{
    /**
     * Locates a cached Response for the Request provided.
     */
    public function lookup(Request $request): ?Response;
    /**
     * Writes a cache entry to the store for the given Request and Response.
     *
     * Existing entries are read and any that match the response are removed. This
     * method calls write with the new list of cache entries.
     *
     * @return string The key under which the response is stored
     */
    public function write(Request $request, Response $response): string;
    /**
     * Invalidates all cache entries that match the request.
     *
     * @return void
     */
    public function invalidate(Request $request);
    /**
     * Locks the cache for a given Request.
     *
     * @return bool|string true if the lock is acquired, the path to the current lock otherwise
     */
    public function lock(Request $request): bool|string;
    /**
     * Releases the lock for the given Request.
     *
     * @return bool False if the lock file does not exist or cannot be unlocked, true otherwise
     */
    public function unlock(Request $request): bool;
    /**
     * Returns whether or not a lock exists.
     *
     * @return bool true if lock exists, false otherwise
     */
    public function isLocked(Request $request): bool;
    /**
     * Purges data for the given URL.
     *
     * @return bool true if the URL exists and has been purged, false otherwise
     */
    public function purge(string $url): bool;
    /**
     * Cleanups storage.
     *
     * @return void
     */
    public function cleanup();
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\HttpKernel\HttpCache;

use _ContaoManager\Symfony\Component\HttpFoundation\Request;
use _ContaoManager\Symfony\Component\HttpFoundation\Response;
/**
 * Ssi implements the SSI capabilities to Request and Response instances.
 *
 * @author Sebastian Krebs <krebs.seb@gmail.com>
 */
class Ssi extends AbstractSurrogate
{
    public function getName(): string
    {
        return 'ssi';
    }
    /**
     * @return void
     */
    public function addSurrogateControl(Response $response)
    {
        if (str_contains($response->getContent(), '<!--#include')) {
            $response->headers->set('Surrogate-Control', 'content="SSI/1.0"');
        }
    }
    public function renderIncludeTag(string $uri, ?string $alt = null, bool $ignoreErrors = \true, string $comment = ''): string
    {
        return \sprintf('<!--#include virtual="%s" -->', $uri);
    }
    public function process(Request $request, Response $response): Response
    {
        $type = $response->headers->get('Content-Type');
        if (empty($type)) {
            $type = 'text/html';
        }
        $parts = explode(';', $type);
        if (!\in_array($parts[0], $this->contentTypes)) {
            return $response;
        }
        // we don't use a proper XML parser here as we can have SSI tags in a plain text response
        $content = $response->getContent();
        $boundary = self::generateBodyEvalBoundary();
        $chunks = preg_split('#<!--\#include\s+(.*?)\s*-->#', $content, -1, \PREG_SPLIT_DELIM_CAPTURE);
        $i = 1;
        while (isset($chunks[$i])) {
            $options = [];
            preg_match_all('/(virtual)="([^"]*?)"/', $chunks[$i], $matches, \PREG_SET_ORDER);
            foreach ($matches as $set) {
                $options[$set[1]] = $set[2];
            }
            if (!isset($options['virtual'])) {
                throw new \RuntimeException('Unable to process an SSI tag without a "virtual" attribute.');
            }
            $chunks[$i] = $boundary . $options['virtual'] . "\n\n\n";
            $i += 2;
        }
        $content = $boundary . implode('', $chunks) . $boundary;
        $response->setContent($content);
        $response->headers->set('X-Body-Eval', 'SSI');
        // remove SSI/1.0 from the Surrogate-Control header
        $this->removeFromControl($response);
        return $response;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\HttpKernel\HttpCache;

/**
 * @internal
 */
class CacheWasLockedException extends \Exception
{
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\HttpKernel\HttpCache;

use _ContaoManager\Symfony\Component\HttpFoundation\Request;
use _ContaoManager\Symfony\Component\HttpFoundation\Response;
use _ContaoManager\Symfony\Component\HttpKernel\HttpKernelInterface;
/**
 * Abstract class implementing Surrogate capabilities to Request and Response instances.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 * @author Robin Chalas <robin.chalas@gmail.com>
 */
abstract class AbstractSurrogate implements SurrogateInterface
{
    protected $contentTypes;
    /**
     * @deprecated since Symfony 6.3
     */
    protected $phpEscapeMap = [['<?', '<%', '<s', '<S'], ['<?php echo "<?"; ?>', '<?php echo "<%"; ?>', '<?php echo "<s"; ?>', '<?php echo "<S"; ?>']];
    /**
     * @param array $contentTypes An array of content-type that should be parsed for Surrogate information
     *                            (default: text/html, text/xml, application/xhtml+xml, and application/xml)
     */
    public function __construct(array $contentTypes = ['text/html', 'text/xml', 'application/xhtml+xml', 'application/xml'])
    {
        $this->contentTypes = $contentTypes;
    }
    /**
     * Returns a new cache strategy instance.
     */
    public function createCacheStrategy(): ResponseCacheStrategyInterface
    {
        return new ResponseCacheStrategy();
    }
    public function hasSurrogateCapability(Request $request): bool
    {
        if (null === $value = $request->headers->get('Surrogate-Capability')) {
            return \false;
        }
        return str_contains($value, \sprintf('%s/1.0', strtoupper($this->getName())));
    }
    /**
     * @return void
     */
    public function addSurrogateCapability(Request $request)
    {
        $current = $request->headers->get('Surrogate-Capability');
        $new = \sprintf('symfony="%s/1.0"', strtoupper($this->getName()));
        $request->headers->set('Surrogate-Capability', $current ? $current . ', ' . $new : $new);
    }
    public function needsParsing(Response $response): bool
    {
        if (!$control = $response->headers->get('Surrogate-Control')) {
            return \false;
        }
        $pattern = \sprintf('#content="[^"]*%s/1.0[^"]*"#', strtoupper($this->getName()));
        return (bool) preg_match($pattern, $control);
    }
    public function handle(HttpCache $cache, string $uri, string $alt, bool $ignoreErrors): string
    {
        $subRequest = Request::create($uri, Request::METHOD_GET, [], $cache->getRequest()->cookies->all(), [], $cache->getRequest()->server->all());
        try {
            $response = $cache->handle($subRequest, HttpKernelInterface::SUB_REQUEST, \true);
            if (!$response->isSuccessful() && Response::HTTP_NOT_MODIFIED !== $response->getStatusCode()) {
                throw new \RuntimeException(\sprintf('Error when rendering "%s" (Status code is %d).', $subRequest->getUri(), $response->getStatusCode()));
            }
            return $response->getContent();
        } catch (\Exception $e) {
            if ($alt) {
                return $this->handle($cache, $alt, '', $ignoreErrors);
            }
            if (!$ignoreErrors) {
                throw $e;
            }
        }
        return '';
    }
    /**
     * Remove the Surrogate from the Surrogate-Control header.
     *
     * @return void
     */
    protected function removeFromControl(Response $response)
    {
        if (!$response->headers->has('Surrogate-Control')) {
            return;
        }
        $value = $response->headers->get('Surrogate-Control');
        $upperName = strtoupper($this->getName());
        if (\sprintf('content="%s/1.0"', $upperName) == $value) {
            $response->headers->remove('Surrogate-Control');
        } elseif (preg_match(\sprintf('#,\s*content="%s/1.0"#', $upperName), $value)) {
            $response->headers->set('Surrogate-Control', preg_replace(\sprintf('#,\s*content="%s/1.0"#', $upperName), '', $value));
        } elseif (preg_match(\sprintf('#content="%s/1.0",\s*#', $upperName), $value)) {
            $response->headers->set('Surrogate-Control', preg_replace(\sprintf('#content="%s/1.0",\s*#', $upperName), '', $value));
        }
    }
    protected static function generateBodyEvalBoundary(): string
    {
        static $cookie;
        $cookie = hash('xxh128', $cookie ?? $cookie = random_bytes(16), \true);
        $boundary = base64_encode($cookie);
        \assert(HttpCache::BODY_EVAL_BOUNDARY_LENGTH === \strlen($boundary));
        return $boundary;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\HttpKernel\HttpCache;

use _ContaoManager\Symfony\Component\HttpFoundation\IpUtils;
use _ContaoManager\Symfony\Component\HttpFoundation\Request;
use _ContaoManager\Symfony\Component\HttpFoundation\Response;
use _ContaoManager\Symfony\Component\HttpKernel\HttpKernelInterface;
/**
 * @author Nicolas Grekas <p@tchwork.com>
 *
 * @internal
 */
class SubRequestHandler
{
    public static function handle(HttpKernelInterface $kernel, Request $request, int $type, bool $catch): Response
    {
        // save global state related to trusted headers and proxies
        $trustedProxies = Request::getTrustedProxies();
        $trustedHeaderSet = Request::getTrustedHeaderSet();
        // remove untrusted values
        $remoteAddr = $request->server->get('REMOTE_ADDR');
        if (!$remoteAddr || !IpUtils::checkIp($remoteAddr, $trustedProxies)) {
            $trustedHeaders = ['FORWARDED' => $trustedHeaderSet & Request::HEADER_FORWARDED, 'X_FORWARDED_FOR' => $trustedHeaderSet & Request::HEADER_X_FORWARDED_FOR, 'X_FORWARDED_HOST' => $trustedHeaderSet & Request::HEADER_X_FORWARDED_HOST, 'X_FORWARDED_PROTO' => $trustedHeaderSet & Request::HEADER_X_FORWARDED_PROTO, 'X_FORWARDED_PORT' => $trustedHeaderSet & Request::HEADER_X_FORWARDED_PORT, 'X_FORWARDED_PREFIX' => $trustedHeaderSet & Request::HEADER_X_FORWARDED_PREFIX];
            foreach (array_filter($trustedHeaders) as $name => $key) {
                $request->headers->remove($name);
                $request->server->remove('HTTP_' . $name);
            }
        }
        // compute trusted values, taking any trusted proxies into account
        $trustedIps = [];
        $trustedValues = [];
        foreach (array_reverse($request->getClientIps()) as $ip) {
            $trustedIps[] = $ip;
            $trustedValues[] = \sprintf('for="%s"', $ip);
        }
        if ($ip !== $remoteAddr) {
            $trustedIps[] = $remoteAddr;
            $trustedValues[] = \sprintf('for="%s"', $remoteAddr);
        }
        // set trusted values, reusing as much as possible the global trusted settings
        if (Request::HEADER_FORWARDED & $trustedHeaderSet) {
            $trustedValues[0] .= \sprintf(';host="%s";proto=%s', $request->getHttpHost(), $request->getScheme());
            $request->headers->set('Forwarded', $v = implode(', ', $trustedValues));
            $request->server->set('HTTP_FORWARDED', $v);
        }
        if (Request::HEADER_X_FORWARDED_FOR & $trustedHeaderSet) {
            $request->headers->set('X-Forwarded-For', $v = implode(', ', $trustedIps));
            $request->server->set('HTTP_X_FORWARDED_FOR', $v);
        } elseif (!(Request::HEADER_FORWARDED & $trustedHeaderSet)) {
            Request::setTrustedProxies($trustedProxies, $trustedHeaderSet | Request::HEADER_X_FORWARDED_FOR);
            $request->headers->set('X-Forwarded-For', $v = implode(', ', $trustedIps));
            $request->server->set('HTTP_X_FORWARDED_FOR', $v);
        }
        // fix the client IP address by setting it to 127.0.0.1,
        // which is the core responsibility of this method
        $request->server->set('REMOTE_ADDR', '127.0.0.1');
        // ensure 127.0.0.1 is set as trusted proxy
        if (!IpUtils::checkIp('127.0.0.1', $trustedProxies)) {
            Request::setTrustedProxies(array_merge($trustedProxies, ['127.0.0.1']), Request::getTrustedHeaderSet());
        }
        try {
            return $kernel->handle($request, $type, $catch);
        } finally {
            // restore global state
            Request::setTrustedProxies($trustedProxies, $trustedHeaderSet);
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\HttpKernel;

use _ContaoManager\Symfony\Component\HttpFoundation\Request;
use _ContaoManager\Symfony\Component\HttpFoundation\Response;
/**
 * HttpKernelInterface handles a Request to convert it to a Response.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
interface HttpKernelInterface
{
    public const MAIN_REQUEST = 1;
    public const SUB_REQUEST = 2;
    /**
     * @deprecated since symfony/http-kernel 5.3, use MAIN_REQUEST instead.
     *             To ease the migration, this constant won't be removed until Symfony 7.0.
     */
    public const MASTER_REQUEST = self::MAIN_REQUEST;
    /**
     * Handles a Request to convert it to a Response.
     *
     * When $catch is true, the implementation must catch all exceptions
     * and do its best to convert them to a Response instance.
     *
     * @param int  $type  The type of the request
     *                    (one of HttpKernelInterface::MAIN_REQUEST or HttpKernelInterface::SUB_REQUEST)
     * @param bool $catch Whether to catch exceptions or not
     *
     * @throws \Exception When an Exception occurs during processing
     */
    public function handle(Request $request, int $type = self::MAIN_REQUEST, bool $catch = \true): Response;
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\HttpKernel\Log;

use _ContaoManager\Psr\Log\AbstractLogger;
use _ContaoManager\Psr\Log\InvalidArgumentException;
use _ContaoManager\Psr\Log\LogLevel;
use _ContaoManager\Symfony\Component\HttpFoundation\Request;
use _ContaoManager\Symfony\Component\HttpFoundation\RequestStack;
/**
 * Minimalist PSR-3 logger designed to write in stderr or any other stream.
 *
 * @author Kévin Dunglas <dunglas@gmail.com>
 */
class Logger extends AbstractLogger implements DebugLoggerInterface
{
    private const LEVELS = [LogLevel::DEBUG => 0, LogLevel::INFO => 1, LogLevel::NOTICE => 2, LogLevel::WARNING => 3, LogLevel::ERROR => 4, LogLevel::CRITICAL => 5, LogLevel::ALERT => 6, LogLevel::EMERGENCY => 7];
    private const PRIORITIES = [LogLevel::DEBUG => 100, LogLevel::INFO => 200, LogLevel::NOTICE => 250, LogLevel::WARNING => 300, LogLevel::ERROR => 400, LogLevel::CRITICAL => 500, LogLevel::ALERT => 550, LogLevel::EMERGENCY => 600];
    private int $minLevelIndex;
    private \Closure $formatter;
    private bool $debug = \false;
    private array $logs = [];
    private array $errorCount = [];
    /** @var resource|null */
    private $handle;
    /**
     * @param string|resource|null $output
     */
    public function __construct(?string $minLevel = null, $output = null, ?callable $formatter = null, private readonly ?RequestStack $requestStack = null, bool $debug = \false)
    {
        if (null === $minLevel) {
            $minLevel = null === $output || 'php://stdout' === $output || 'php://stderr' === $output ? LogLevel::ERROR : LogLevel::WARNING;
            if (isset($_ENV['SHELL_VERBOSITY']) || isset($_SERVER['SHELL_VERBOSITY'])) {
                $minLevel = match ((int) ($_ENV['SHELL_VERBOSITY'] ?? $_SERVER['SHELL_VERBOSITY'])) {
                    -1 => LogLevel::ERROR,
                    1 => LogLevel::NOTICE,
                    2 => LogLevel::INFO,
                    3 => LogLevel::DEBUG,
                    default => $minLevel,
                };
            }
        }
        if (!isset(self::LEVELS[$minLevel])) {
            throw new InvalidArgumentException(\sprintf('The log level "%s" does not exist.', $minLevel));
        }
        $this->minLevelIndex = self::LEVELS[$minLevel];
        $this->formatter = null !== $formatter ? $formatter(...) : $this->format(...);
        if ($output && \false === $this->handle = \is_string($output) ? @fopen($output, 'a') : $output) {
            throw new InvalidArgumentException(\sprintf('Unable to open "%s".', $output));
        }
        $this->debug = $debug;
    }
    public function enableDebug(): void
    {
        $this->debug = \true;
    }
    public function log($level, $message, array $context = []): void
    {
        if (!isset(self::LEVELS[$level])) {
            throw new InvalidArgumentException(\sprintf('The log level "%s" does not exist.', $level));
        }
        if (self::LEVELS[$level] < $this->minLevelIndex) {
            return;
        }
        $formatter = $this->formatter;
        if ($this->handle) {
            @fwrite($this->handle, $formatter($level, $message, $context) . \PHP_EOL);
        } else {
            error_log($formatter($level, $message, $context, \false));
        }
        if ($this->debug && $this->requestStack) {
            $this->record($level, $message, $context);
        }
    }
    public function getLogs(?Request $request = null): array
    {
        if ($request) {
            return $this->logs[spl_object_id($request)] ?? [];
        }
        return array_merge(...array_values($this->logs));
    }
    public function countErrors(?Request $request = null): int
    {
        if ($request) {
            return $this->errorCount[spl_object_id($request)] ?? 0;
        }
        return array_sum($this->errorCount);
    }
    public function clear(): void
    {
        $this->logs = [];
        $this->errorCount = [];
    }
    private function format(string $level, string $message, array $context, bool $prefixDate = \true): string
    {
        if (str_contains($message, '{')) {
            $replacements = [];
            foreach ($context as $key => $val) {
                if (null === $val || \is_scalar($val) || $val instanceof \Stringable) {
                    $replacements["{{$key}}"] = $val;
                } elseif ($val instanceof \DateTimeInterface) {
                    $replacements["{{$key}}"] = $val->format(\DateTimeInterface::RFC3339);
                } elseif (\is_object($val)) {
                    $replacements["{{$key}}"] = '[object ' . $val::class . ']';
                } else {
                    $replacements["{{$key}}"] = '[' . \gettype($val) . ']';
                }
            }
            $message = strtr($message, $replacements);
        }
        $log = \sprintf('[%s] %s', $level, $message);
        if ($prefixDate) {
            $log = date(\DateTimeInterface::RFC3339) . ' ' . $log;
        }
        return $log;
    }
    private function record($level, $message, array $context): void
    {
        $request = $this->requestStack->getCurrentRequest();
        $key = $request ? spl_object_id($request) : '';
        $this->logs[$key][] = ['channel' => null, 'context' => $context, 'message' => $message, 'priority' => self::PRIORITIES[$level], 'priorityName' => $level, 'timestamp' => time(), 'timestamp_rfc3339' => date(\DATE_RFC3339_EXTENDED)];
        $this->errorCount[$key] ??= 0;
        switch ($level) {
            case LogLevel::ERROR:
            case LogLevel::CRITICAL:
            case LogLevel::ALERT:
            case LogLevel::EMERGENCY:
                ++$this->errorCount[$key];
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\HttpKernel\Log;

use _ContaoManager\Symfony\Component\HttpFoundation\Request;
/**
 * DebugLoggerInterface.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
interface DebugLoggerInterface
{
    /**
     * Returns an array of logs.
     *
     * @return array<array{
     *     channel: ?string,
     *     context: array<string, mixed>,
     *     message: string,
     *     priority: int,
     *     priorityName: string,
     *     timestamp: int,
     *     timestamp_rfc3339: string,
     * }>
     */
    public function getLogs(?Request $request = null);
    /**
     * Returns the number of errors.
     *
     * @return int
     */
    public function countErrors(?Request $request = null);
    /**
     * Removes all log records.
     *
     * @return void
     */
    public function clear();
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\HttpKernel\Log;

use _ContaoManager\Monolog\Logger;
/**
 * @author Nicolas Grekas <p@tchwork.com>
 */
class DebugLoggerConfigurator
{
    private ?object $processor = null;
    public function __construct(callable $processor, ?bool $enable = null)
    {
        if ($enable ?? !\in_array(\PHP_SAPI, ['cli', 'phpdbg', 'embed'], \true)) {
            $this->processor = \is_object($processor) ? $processor : $processor(...);
        }
    }
    public function pushDebugLogger(Logger $logger): void
    {
        if ($this->processor) {
            $logger->pushProcessor($this->processor);
        }
    }
    public static function getDebugLogger(mixed $logger): ?DebugLoggerInterface
    {
        if ($logger instanceof DebugLoggerInterface) {
            return $logger;
        }
        if (!$logger instanceof Logger) {
            return null;
        }
        foreach ($logger->getProcessors() as $processor) {
            if ($processor instanceof DebugLoggerInterface) {
                return $processor;
            }
        }
        return null;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\HttpKernel\Profiler;

/**
 * Storage for profiler using files.
 *
 * @author Alexandre Salomé <alexandre.salome@gmail.com>
 */
class FileProfilerStorage implements ProfilerStorageInterface
{
    /**
     * Folder where profiler data are stored.
     */
    private string $folder;
    /**
     * Constructs the file storage using a "dsn-like" path.
     *
     * Example : "file:/path/to/the/storage/folder"
     *
     * @throws \RuntimeException
     */
    public function __construct(string $dsn)
    {
        if (!str_starts_with($dsn, 'file:')) {
            throw new \RuntimeException(\sprintf('Please check your configuration. You are trying to use FileStorage with an invalid dsn "%s". The expected format is "file:/path/to/the/storage/folder".', $dsn));
        }
        $this->folder = substr($dsn, 5);
        if (!is_dir($this->folder) && \false === @mkdir($this->folder, 0777, \true) && !is_dir($this->folder)) {
            throw new \RuntimeException(\sprintf('Unable to create the storage directory (%s).', $this->folder));
        }
    }
    /**
     * @param \Closure|null $filter A filter to apply on the list of tokens
     */
    public function find(?string $ip, ?string $url, ?int $limit, ?string $method, ?int $start = null, ?int $end = null, ?string $statusCode = null): array
    {
        $filter = 7 < \func_num_args() ? func_get_arg(7) : null;
        $file = $this->getIndexFilename();
        if (!file_exists($file)) {
            return [];
        }
        $file = fopen($file, 'r');
        fseek($file, 0, \SEEK_END);
        $result = [];
        while (\count($result) < $limit && $line = $this->readLineFromFile($file)) {
            $values = str_getcsv($line, ',', '"', '\\');
            if (7 > \count($values)) {
                // skip invalid lines
                continue;
            }
            [$csvToken, $csvIp, $csvMethod, $csvUrl, $csvTime, $csvParent, $csvStatusCode, $csvVirtualType] = $values + [7 => null];
            $csvTime = (int) $csvTime;
            $urlFilter = \false;
            if ($url) {
                $urlFilter = str_starts_with($url, '!') ? str_contains($csvUrl, substr($url, 1)) : !str_contains($csvUrl, $url);
            }
            if ($ip && !str_contains($csvIp, $ip) || $urlFilter || $method && !str_contains($csvMethod, $method) || $statusCode && !str_contains($csvStatusCode, $statusCode)) {
                continue;
            }
            if (!empty($start) && $csvTime < $start) {
                continue;
            }
            if (!empty($end) && $csvTime > $end) {
                continue;
            }
            $profile = ['token' => $csvToken, 'ip' => $csvIp, 'method' => $csvMethod, 'url' => $csvUrl, 'time' => $csvTime, 'parent' => $csvParent, 'status_code' => $csvStatusCode, 'virtual_type' => $csvVirtualType ?: 'request'];
            if ($filter && !$filter($profile)) {
                continue;
            }
            $result[$csvToken] = $profile;
        }
        fclose($file);
        return array_values($result);
    }
    /**
     * @return void
     */
    public function purge()
    {
        $flags = \FilesystemIterator::SKIP_DOTS;
        $iterator = new \RecursiveDirectoryIterator($this->folder, $flags);
        $iterator = new \RecursiveIteratorIterator($iterator, \RecursiveIteratorIterator::CHILD_FIRST);
        foreach ($iterator as $file) {
            if (is_file($file)) {
                unlink($file);
            } else {
                rmdir($file);
            }
        }
    }
    public function read(string $token): ?Profile
    {
        return $this->doRead($token);
    }
    /**
     * @throws \RuntimeException
     */
    public function write(Profile $profile): bool
    {
        $file = $this->getFilename($profile->getToken());
        $profileIndexed = is_file($file);
        if (!$profileIndexed) {
            // Create directory
            $dir = \dirname($file);
            if (!is_dir($dir) && \false === @mkdir($dir, 0777, \true) && !is_dir($dir)) {
                throw new \RuntimeException(\sprintf('Unable to create the storage directory (%s).', $dir));
            }
        }
        $profileToken = $profile->getToken();
        // when there are errors in sub-requests, the parent and/or children tokens
        // may equal the profile token, resulting in infinite loops
        $parentToken = $profile->getParentToken() !== $profileToken ? $profile->getParentToken() : null;
        $childrenToken = array_filter(array_map(fn(Profile $p) => $profileToken !== $p->getToken() ? $p->getToken() : null, $profile->getChildren()));
        // Store profile
        $data = ['token' => $profileToken, 'parent' => $parentToken, 'children' => $childrenToken, 'data' => $profile->getCollectors(), 'ip' => $profile->getIp(), 'method' => $profile->getMethod(), 'url' => $profile->getUrl(), 'time' => $profile->getTime(), 'status_code' => $profile->getStatusCode(), 'virtual_type' => $profile->getVirtualType() ?? 'request'];
        $data = serialize($data);
        if (\function_exists('gzencode')) {
            $data = gzencode($data, 3);
        }
        if (\false === file_put_contents($file, $data, \LOCK_EX)) {
            return \false;
        }
        if (!$profileIndexed) {
            // Add to index
            if (\false === $file = fopen($this->getIndexFilename(), 'a')) {
                return \false;
            }
            fputcsv($file, [$profile->getToken(), $profile->getIp(), $profile->getMethod(), $profile->getUrl(), $profile->getTime() ?: time(), $profile->getParentToken(), $profile->getStatusCode(), $profile->getVirtualType() ?? 'request'], ',', '"', '\\');
            fclose($file);
            if (1 === mt_rand(1, 10)) {
                $this->removeExpiredProfiles();
            }
        }
        return \true;
    }
    /**
     * Gets filename to store data, associated to the token.
     */
    protected function getFilename(string $token): string
    {
        // Uses 4 last characters, because first are mostly the same.
        $folderA = substr($token, -2, 2);
        $folderB = substr($token, -4, 2);
        return $this->folder . '/' . $folderA . '/' . $folderB . '/' . $token;
    }
    /**
     * Gets the index filename.
     */
    protected function getIndexFilename(): string
    {
        return $this->folder . '/index.csv';
    }
    /**
     * Reads a line in the file, backward.
     *
     * This function automatically skips the empty lines and do not include the line return in result value.
     *
     * @param resource $file The file resource, with the pointer placed at the end of the line to read
     */
    protected function readLineFromFile($file): mixed
    {
        $line = '';
        $position = ftell($file);
        if (0 === $position) {
            return null;
        }
        while (\true) {
            $chunkSize = min($position, 1024);
            $position -= $chunkSize;
            fseek($file, $position);
            if (0 === $chunkSize) {
                // bof reached
                break;
            }
            $buffer = fread($file, $chunkSize);
            if (\false === $upTo = strrpos($buffer, "\n")) {
                $line = $buffer . $line;
                continue;
            }
            $position += $upTo;
            $line = substr($buffer, $upTo + 1) . $line;
            fseek($file, max(0, $position), \SEEK_SET);
            if ('' !== $line) {
                break;
            }
        }
        return '' === $line ? null : $line;
    }
    /**
     * @return Profile
     */
    protected function createProfileFromData(string $token, array $data, ?Profile $parent = null)
    {
        $profile = new Profile($token);
        $profile->setIp($data['ip']);
        $profile->setMethod($data['method']);
        $profile->setUrl($data['url']);
        $profile->setTime($data['time']);
        $profile->setStatusCode($data['status_code']);
        $profile->setVirtualType($data['virtual_type'] ?: 'request');
        $profile->setCollectors($data['data']);
        if (!$parent && $data['parent']) {
            $parent = $this->read($data['parent']);
        }
        if ($parent) {
            $profile->setParent($parent);
        }
        foreach ($data['children'] as $token) {
            if (null !== $childProfile = $this->doRead($token, $profile)) {
                $profile->addChild($childProfile);
            }
        }
        return $profile;
    }
    private function doRead($token, ?Profile $profile = null): ?Profile
    {
        if (!$token || !file_exists($file = $this->getFilename($token))) {
            return null;
        }
        $h = fopen($file, 'r');
        flock($h, \LOCK_SH);
        $data = stream_get_contents($h);
        flock($h, \LOCK_UN);
        fclose($h);
        if (\function_exists('gzdecode')) {
            $data = @gzdecode($data) ?: $data;
        }
        if (!$data = unserialize($data)) {
            return null;
        }
        return $this->createProfileFromData($token, $data, $profile);
    }
    private function removeExpiredProfiles(): void
    {
        $minimalProfileTimestamp = time() - 2 * 86400;
        $file = $this->getIndexFilename();
        $handle = fopen($file, 'r');
        if ($offset = is_file($file . '.offset') ? (int) file_get_contents($file . '.offset') : 0) {
            fseek($handle, $offset);
        }
        while ($line = fgets($handle)) {
            $values = str_getcsv($line, ',', '"', '\\');
            if (7 > \count($values)) {
                // skip invalid lines
                $offset += \strlen($line);
                continue;
            }
            [$csvToken, , , , $csvTime] = $values;
            if ($csvTime >= $minimalProfileTimestamp) {
                break;
            }
            @unlink($this->getFilename($csvToken));
            $offset += \strlen($line);
        }
        fclose($handle);
        file_put_contents($file . '.offset', $offset);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\HttpKernel\Profiler;

use _ContaoManager\Symfony\Component\HttpKernel\DataCollector\DataCollectorInterface;
/**
 * Profile.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class Profile
{
    private string $token;
    /**
     * @var DataCollectorInterface[]
     */
    private array $collectors = [];
    private ?string $ip = null;
    private ?string $method = null;
    private ?string $url = null;
    private ?int $time = null;
    private ?int $statusCode = null;
    private ?self $parent = null;
    private ?string $virtualType = null;
    /**
     * @var Profile[]
     */
    private array $children = [];
    public function __construct(string $token)
    {
        $this->token = $token;
    }
    /**
     * @return void
     */
    public function setToken(string $token)
    {
        $this->token = $token;
    }
    /**
     * Gets the token.
     */
    public function getToken(): string
    {
        return $this->token;
    }
    /**
     * Sets the parent token.
     *
     * @return void
     */
    public function setParent(self $parent)
    {
        $this->parent = $parent;
    }
    /**
     * Returns the parent profile.
     */
    public function getParent(): ?self
    {
        return $this->parent;
    }
    /**
     * Returns the parent token.
     */
    public function getParentToken(): ?string
    {
        return $this->parent?->getToken();
    }
    /**
     * Returns the IP.
     */
    public function getIp(): ?string
    {
        return $this->ip;
    }
    /**
     * @return void
     */
    public function setIp(?string $ip)
    {
        $this->ip = $ip;
    }
    /**
     * Returns the request method.
     */
    public function getMethod(): ?string
    {
        return $this->method;
    }
    /**
     * @return void
     */
    public function setMethod(string $method)
    {
        $this->method = $method;
    }
    /**
     * Returns the URL.
     */
    public function getUrl(): ?string
    {
        return $this->url;
    }
    /**
     * @return void
     */
    public function setUrl(?string $url)
    {
        $this->url = $url;
    }
    public function getTime(): int
    {
        return $this->time ?? 0;
    }
    /**
     * @return void
     */
    public function setTime(int $time)
    {
        $this->time = $time;
    }
    /**
     * @return void
     */
    public function setStatusCode(int $statusCode)
    {
        $this->statusCode = $statusCode;
    }
    public function getStatusCode(): ?int
    {
        return $this->statusCode;
    }
    /**
     * @internal
     */
    public function setVirtualType(?string $virtualType): void
    {
        $this->virtualType = $virtualType;
    }
    /**
     * @internal
     */
    public function getVirtualType(): ?string
    {
        return $this->virtualType;
    }
    /**
     * Finds children profilers.
     *
     * @return self[]
     */
    public function getChildren(): array
    {
        return $this->children;
    }
    /**
     * Sets children profiler.
     *
     * @param Profile[] $children
     *
     * @return void
     */
    public function setChildren(array $children)
    {
        $this->children = [];
        foreach ($children as $child) {
            $this->addChild($child);
        }
    }
    /**
     * Adds the child token.
     *
     * @return void
     */
    public function addChild(self $child)
    {
        $this->children[] = $child;
        $child->setParent($this);
    }
    public function getChildByToken(string $token): ?self
    {
        foreach ($this->children as $child) {
            if ($token === $child->getToken()) {
                return $child;
            }
        }
        return null;
    }
    /**
     * Gets a Collector by name.
     *
     * @throws \InvalidArgumentException if the collector does not exist
     */
    public function getCollector(string $name): DataCollectorInterface
    {
        if (!isset($this->collectors[$name])) {
            throw new \InvalidArgumentException(\sprintf('Collector "%s" does not exist.', $name));
        }
        return $this->collectors[$name];
    }
    /**
     * Gets the Collectors associated with this profile.
     *
     * @return DataCollectorInterface[]
     */
    public function getCollectors(): array
    {
        return $this->collectors;
    }
    /**
     * Sets the Collectors associated with this profile.
     *
     * @param DataCollectorInterface[] $collectors
     *
     * @return void
     */
    public function setCollectors(array $collectors)
    {
        $this->collectors = [];
        foreach ($collectors as $collector) {
            $this->addCollector($collector);
        }
    }
    /**
     * Adds a Collector.
     *
     * @return void
     */
    public function addCollector(DataCollectorInterface $collector)
    {
        $this->collectors[$collector->getName()] = $collector;
    }
    public function hasCollector(string $name): bool
    {
        return isset($this->collectors[$name]);
    }
    public function __sleep(): array
    {
        return ['token', 'parent', 'children', 'collectors', 'ip', 'method', 'url', 'time', 'statusCode', 'virtualType'];
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\HttpKernel\Profiler;

use _ContaoManager\Psr\Log\LoggerInterface;
use _ContaoManager\Symfony\Component\HttpFoundation\Exception\ConflictingHeadersException;
use _ContaoManager\Symfony\Component\HttpFoundation\Request;
use _ContaoManager\Symfony\Component\HttpFoundation\Response;
use _ContaoManager\Symfony\Component\HttpKernel\DataCollector\DataCollectorInterface;
use _ContaoManager\Symfony\Component\HttpKernel\DataCollector\LateDataCollectorInterface;
use _ContaoManager\Symfony\Contracts\Service\ResetInterface;
/**
 * Profiler.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class Profiler implements ResetInterface
{
    private ProfilerStorageInterface $storage;
    /**
     * @var DataCollectorInterface[]
     */
    private array $collectors = [];
    private ?LoggerInterface $logger;
    private bool $initiallyEnabled = \true;
    private bool $enabled = \true;
    public function __construct(ProfilerStorageInterface $storage, ?LoggerInterface $logger = null, bool $enable = \true)
    {
        $this->storage = $storage;
        $this->logger = $logger;
        $this->initiallyEnabled = $this->enabled = $enable;
    }
    /**
     * Disables the profiler.
     *
     * @return void
     */
    public function disable()
    {
        $this->enabled = \false;
    }
    /**
     * Enables the profiler.
     *
     * @return void
     */
    public function enable()
    {
        $this->enabled = \true;
    }
    public function isEnabled(): bool
    {
        return $this->enabled;
    }
    /**
     * Loads the Profile for the given Response.
     */
    public function loadProfileFromResponse(Response $response): ?Profile
    {
        if (!$token = $response->headers->get('X-Debug-Token')) {
            return null;
        }
        return $this->loadProfile($token);
    }
    /**
     * Loads the Profile for the given token.
     */
    public function loadProfile(string $token): ?Profile
    {
        return $this->storage->read($token);
    }
    /**
     * Saves a Profile.
     */
    public function saveProfile(Profile $profile): bool
    {
        // late collect
        foreach ($profile->getCollectors() as $collector) {
            if ($collector instanceof LateDataCollectorInterface) {
                $collector->lateCollect();
            }
        }
        if (!($ret = $this->storage->write($profile)) && null !== $this->logger) {
            $this->logger->warning('Unable to store the profiler information.', ['configured_storage' => $this->storage::class]);
        }
        return $ret;
    }
    /**
     * Purges all data from the storage.
     *
     * @return void
     */
    public function purge()
    {
        $this->storage->purge();
    }
    /**
     * Finds profiler tokens for the given criteria.
     *
     * @param int|null      $limit  The maximum number of tokens to return
     * @param string|null   $start  The start date to search from
     * @param string|null   $end    The end date to search to
     * @param \Closure|null $filter A filter to apply on the list of tokens
     *
     * @see https://php.net/datetime.formats for the supported date/time formats
     */
    public function find(?string $ip, ?string $url, ?int $limit, ?string $method, ?string $start, ?string $end, ?string $statusCode = null): array
    {
        $filter = 7 < \func_num_args() ? func_get_arg(7) : null;
        return $this->storage->find($ip, $url, $limit, $method, $this->getTimestamp($start), $this->getTimestamp($end), $statusCode, $filter);
    }
    /**
     * Collects data for the given Response.
     */
    public function collect(Request $request, Response $response, ?\Throwable $exception = null): ?Profile
    {
        if (\false === $this->enabled) {
            return null;
        }
        $profile = new Profile(substr(hash('sha256', uniqid(mt_rand(), \true)), 0, 6));
        $profile->setTime(time());
        $profile->setUrl($request->getUri());
        $profile->setMethod($request->getMethod());
        $profile->setStatusCode($response->getStatusCode());
        try {
            $profile->setIp($request->getClientIp());
        } catch (ConflictingHeadersException) {
            $profile->setIp('Unknown');
        }
        if ($request->attributes->has('_virtual_type')) {
            $profile->setVirtualType($request->attributes->get('_virtual_type'));
        }
        if ($prevToken = $response->headers->get('X-Debug-Token')) {
            $response->headers->set('X-Previous-Debug-Token', $prevToken);
        }
        $response->headers->set('X-Debug-Token', $profile->getToken());
        foreach ($this->collectors as $collector) {
            $collector->collect($request, $response, $exception);
            // we need to clone for sub-requests
            $profile->addCollector(clone $collector);
        }
        return $profile;
    }
    /**
     * @return void
     */
    public function reset()
    {
        foreach ($this->collectors as $collector) {
            $collector->reset();
        }
        $this->enabled = $this->initiallyEnabled;
    }
    /**
     * Gets the Collectors associated with this profiler.
     */
    public function all(): array
    {
        return $this->collectors;
    }
    /**
     * Sets the Collectors associated with this profiler.
     *
     * @param DataCollectorInterface[] $collectors An array of collectors
     *
     * @return void
     */
    public function set(array $collectors = [])
    {
        $this->collectors = [];
        foreach ($collectors as $collector) {
            $this->add($collector);
        }
    }
    /**
     * Adds a Collector.
     *
     * @return void
     */
    public function add(DataCollectorInterface $collector)
    {
        $this->collectors[$collector->getName()] = $collector;
    }
    /**
     * Returns true if a Collector for the given name exists.
     *
     * @param string $name A collector name
     */
    public function has(string $name): bool
    {
        return isset($this->collectors[$name]);
    }
    /**
     * Gets a Collector by name.
     *
     * @param string $name A collector name
     *
     * @throws \InvalidArgumentException if the collector does not exist
     */
    public function get(string $name): DataCollectorInterface
    {
        if (!isset($this->collectors[$name])) {
            throw new \InvalidArgumentException(\sprintf('Collector "%s" does not exist.', $name));
        }
        return $this->collectors[$name];
    }
    private function getTimestamp(?string $value): ?int
    {
        if (null === $value || '' === $value) {
            return null;
        }
        try {
            $value = new \DateTimeImmutable(is_numeric($value) ? '@' . $value : $value);
        } catch (\Exception) {
            return null;
        }
        return $value->getTimestamp();
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\HttpKernel\Profiler;

/**
 * ProfilerStorageInterface.
 *
 * This interface exists for historical reasons. The only supported
 * implementation is FileProfilerStorage.
 *
 * As the profiler must only be used on non-production servers, the file storage
 * is more than enough and no other implementations will ever be supported.
 *
 * @internal
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
interface ProfilerStorageInterface
{
    /**
     * Finds profiler tokens for the given criteria.
     *
     * @param int|null      $limit      The maximum number of tokens to return
     * @param int|null      $start      The start date to search from
     * @param int|null      $end        The end date to search to
     * @param string|null   $statusCode The response status code
     * @param \Closure|null $filter     A filter to apply on the list of tokens
     */
    public function find(?string $ip, ?string $url, ?int $limit, ?string $method, ?int $start = null, ?int $end = null): array;
    /**
     * Reads data associated with the given token.
     *
     * The method returns false if the token does not exist in the storage.
     */
    public function read(string $token): ?Profile;
    /**
     * Saves a Profile.
     */
    public function write(Profile $profile): bool;
    /**
     * Purges all data from the database.
     *
     * @return void
     */
    public function purge();
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\HttpKernel\DependencyInjection;

use _ContaoManager\Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Compiler\ServiceLocatorTagPass;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerBuilder;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
use _ContaoManager\Symfony\Component\DependencyInjection\Reference;
use _ContaoManager\Symfony\Component\HttpKernel\Fragment\FragmentRendererInterface;
/**
 * Adds services tagged kernel.fragment_renderer as HTTP content rendering strategies.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class FragmentRendererPass implements CompilerPassInterface
{
    /**
     * @return void
     */
    public function process(ContainerBuilder $container)
    {
        if (!$container->hasDefinition('fragment.handler')) {
            return;
        }
        $definition = $container->getDefinition('fragment.handler');
        $renderers = [];
        foreach ($container->findTaggedServiceIds('kernel.fragment_renderer', \true) as $id => $tags) {
            $def = $container->getDefinition($id);
            $class = $container->getParameterBag()->resolveValue($def->getClass());
            if (!$r = $container->getReflectionClass($class)) {
                throw new InvalidArgumentException(\sprintf('Class "%s" used for service "%s" cannot be found.', $class, $id));
            }
            if (!$r->isSubclassOf(FragmentRendererInterface::class)) {
                throw new InvalidArgumentException(\sprintf('Service "%s" must implement interface "%s".', $id, FragmentRendererInterface::class));
            }
            foreach ($tags as $tag) {
                $renderers[$tag['alias']] = new Reference($id);
            }
        }
        $definition->replaceArgument(0, ServiceLocatorTagPass::register($container, $renderers));
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\HttpKernel\DependencyInjection;

use _ContaoManager\ProxyManager\Proxy\LazyLoadingInterface;
use _ContaoManager\Symfony\Component\VarExporter\LazyObjectInterface;
use _ContaoManager\Symfony\Contracts\Service\ResetInterface;
/**
 * Resets provided services.
 *
 * @author Alexander M. Turek <me@derrabus.de>
 * @author Nicolas Grekas <p@tchwork.com>
 *
 * @internal
 */
class ServicesResetter implements ResetInterface
{
    private \Traversable $resettableServices;
    private array $resetMethods;
    /**
     * @param \Traversable<string, object>   $resettableServices
     * @param array<string, string|string[]> $resetMethods
     */
    public function __construct(\Traversable $resettableServices, array $resetMethods)
    {
        $this->resettableServices = $resettableServices;
        $this->resetMethods = $resetMethods;
    }
    public function reset(): void
    {
        foreach ($this->resettableServices as $id => $service) {
            if ($service instanceof LazyObjectInterface && !$service->isLazyObjectInitialized(\true)) {
                continue;
            }
            if ($service instanceof LazyLoadingInterface && !$service->isProxyInitialized()) {
                continue;
            }
            foreach ((array) $this->resetMethods[$id] as $resetMethod) {
                if ('?' === $resetMethod[0] && !method_exists($service, $resetMethod = substr($resetMethod, 1))) {
                    continue;
                }
                $service->{$resetMethod}();
            }
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\HttpKernel\DependencyInjection;

use _ContaoManager\Symfony\Component\DependencyInjection\Argument\IteratorArgument;
use _ContaoManager\Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerBuilder;
use _ContaoManager\Symfony\Component\DependencyInjection\Reference;
/**
 * Register all services that have the "kernel.locale_aware" tag into the listener.
 *
 * @author Pierre Bobiet <pierrebobiet@gmail.com>
 */
class RegisterLocaleAwareServicesPass implements CompilerPassInterface
{
    /**
     * @return void
     */
    public function process(ContainerBuilder $container)
    {
        if (!$container->hasDefinition('locale_aware_listener')) {
            return;
        }
        $services = [];
        foreach ($container->findTaggedServiceIds('kernel.locale_aware') as $id => $tags) {
            $services[] = new Reference($id);
        }
        if (!$services) {
            $container->removeDefinition('locale_aware_listener');
            return;
        }
        $container->getDefinition('locale_aware_listener')->setArgument(0, new IteratorArgument($services));
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\HttpKernel\DependencyInjection;

use _ContaoManager\Symfony\Component\DependencyInjection\Argument\IteratorArgument;
use _ContaoManager\Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerBuilder;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\RuntimeException;
use _ContaoManager\Symfony\Component\DependencyInjection\Reference;
/**
 * @author Alexander M. Turek <me@derrabus.de>
 */
class ResettableServicePass implements CompilerPassInterface
{
    /**
     * @return void
     */
    public function process(ContainerBuilder $container)
    {
        if (!$container->has('services_resetter')) {
            return;
        }
        $services = $methods = [];
        foreach ($container->findTaggedServiceIds('kernel.reset', \true) as $id => $tags) {
            $services[$id] = new Reference($id, ContainerInterface::IGNORE_ON_UNINITIALIZED_REFERENCE);
            foreach ($tags as $attributes) {
                if (!isset($attributes['method'])) {
                    throw new RuntimeException(\sprintf('Tag "kernel.reset" requires the "method" attribute to be set on service "%s".', $id));
                }
                if (!isset($methods[$id])) {
                    $methods[$id] = [];
                }
                if ('ignore' === ($attributes['on_invalid'] ?? null)) {
                    $attributes['method'] = '?' . $attributes['method'];
                }
                $methods[$id][] = $attributes['method'];
            }
        }
        if (!$services) {
            $container->removeAlias('services_resetter');
            $container->removeDefinition('services_resetter');
            return;
        }
        $container->findDefinition('services_resetter')->setArgument(0, new IteratorArgument($services))->setArgument(1, $methods);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\HttpKernel\DependencyInjection;

use _ContaoManager\Symfony\Component\DependencyInjection\Compiler\MergeExtensionConfigurationPass as BaseMergeExtensionConfigurationPass;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerBuilder;
/**
 * Ensures certain extensions are always loaded.
 *
 * @author Kris Wallsmith <kris@symfony.com>
 */
class MergeExtensionConfigurationPass extends BaseMergeExtensionConfigurationPass
{
    private array $extensions;
    /**
     * @param string[] $extensions
     */
    public function __construct(array $extensions)
    {
        $this->extensions = $extensions;
    }
    public function process(ContainerBuilder $container): void
    {
        foreach ($this->extensions as $extension) {
            if (!\count($container->getExtensionConfig($extension))) {
                $container->loadFromExtension($extension, []);
            }
        }
        parent::process($container);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\HttpKernel\DependencyInjection;

use Composer\Autoload\ClassLoader;
use _ContaoManager\Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerBuilder;
use _ContaoManager\Symfony\Component\ErrorHandler\DebugClassLoader;
use _ContaoManager\Symfony\Component\HttpKernel\Kernel;
/**
 * Sets the classes to compile in the cache for the container.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class AddAnnotatedClassesToCachePass implements CompilerPassInterface
{
    private Kernel $kernel;
    public function __construct(Kernel $kernel)
    {
        $this->kernel = $kernel;
    }
    /**
     * @return void
     */
    public function process(ContainerBuilder $container)
    {
        $annotatedClasses = [];
        foreach ($container->getExtensions() as $extension) {
            if ($extension instanceof Extension) {
                $annotatedClasses[] = $extension->getAnnotatedClassesToCompile();
            }
        }
        $annotatedClasses = array_merge($this->kernel->getAnnotatedClassesToCompile(), ...$annotatedClasses);
        $existingClasses = $this->getClassesInComposerClassMaps();
        $annotatedClasses = $container->getParameterBag()->resolveValue($annotatedClasses);
        $this->kernel->setAnnotatedClassCache($this->expandClasses($annotatedClasses, $existingClasses));
    }
    /**
     * Expands the given class patterns using a list of existing classes.
     *
     * @param array $patterns The class patterns to expand
     * @param array $classes  The existing classes to match against the patterns
     */
    private function expandClasses(array $patterns, array $classes): array
    {
        $expanded = [];
        // Explicit classes declared in the patterns are returned directly
        foreach ($patterns as $key => $pattern) {
            if (!str_ends_with($pattern, '\\') && !str_contains($pattern, '*')) {
                unset($patterns[$key]);
                $expanded[] = ltrim($pattern, '\\');
            }
        }
        // Match patterns with the classes list
        $regexps = $this->patternsToRegexps($patterns);
        foreach ($classes as $class) {
            $class = ltrim($class, '\\');
            if ($this->matchAnyRegexps($class, $regexps)) {
                $expanded[] = $class;
            }
        }
        return array_unique($expanded);
    }
    private function getClassesInComposerClassMaps(): array
    {
        $classes = [];
        foreach (spl_autoload_functions() as $function) {
            if (!\is_array($function)) {
                continue;
            }
            if ($function[0] instanceof DebugClassLoader) {
                $function = $function[0]->getClassLoader();
            }
            if (\is_array($function) && $function[0] instanceof ClassLoader) {
                $classes += array_filter($function[0]->getClassMap());
            }
        }
        return array_keys($classes);
    }
    private function patternsToRegexps(array $patterns): array
    {
        $regexps = [];
        foreach ($patterns as $pattern) {
            // Escape user input
            $regex = preg_quote(ltrim($pattern, '\\'));
            // Wildcards * and **
            $regex = strtr($regex, ['\*\*' => '.*?', '\*' => '[^\\\\]*?']);
            // If this class does not end by a slash, anchor the end
            if (!str_ends_with($regex, '\\')) {
                $regex .= '$';
            }
            $regexps[] = '{^\\\\' . $regex . '}';
        }
        return $regexps;
    }
    private function matchAnyRegexps(string $class, array $regexps): bool
    {
        $isTest = str_contains($class, 'Test');
        foreach ($regexps as $regex) {
            if ($isTest && !str_contains($regex, 'Test')) {
                continue;
            }
            if (preg_match($regex, '\\' . $class)) {
                return \true;
            }
        }
        return \false;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\HttpKernel\DependencyInjection;

use _ContaoManager\Symfony\Component\DependencyInjection\ContainerBuilder;
/**
 * This extension sub-class provides first-class integration with the
 * Config/Definition Component.
 *
 * You can use this as base class if
 *
 *    a) you use the Config/Definition component for configuration,
 *    b) your configuration class is named "Configuration", and
 *    c) the configuration class resides in the DependencyInjection sub-folder.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
abstract class ConfigurableExtension extends Extension
{
    final public function load(array $configs, ContainerBuilder $container): void
    {
        $this->loadInternal($this->processConfiguration($this->getConfiguration($configs, $container), $configs), $container);
    }
    /**
     * Configures the passed container according to the merged configuration.
     *
     * @return void
     */
    abstract protected function loadInternal(array $mergedConfig, ContainerBuilder $container);
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\HttpKernel\DependencyInjection;

use _ContaoManager\Psr\Log\LoggerInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerBuilder;
use _ContaoManager\Symfony\Component\DependencyInjection\Reference;
use _ContaoManager\Symfony\Component\HttpFoundation\RequestStack;
use _ContaoManager\Symfony\Component\HttpKernel\Log\Logger;
/**
 * Registers the default logger if necessary.
 *
 * @author Kévin Dunglas <dunglas@gmail.com>
 */
class LoggerPass implements CompilerPassInterface
{
    /**
     * @return void
     */
    public function process(ContainerBuilder $container)
    {
        if (!$container->has(LoggerInterface::class)) {
            $container->setAlias(LoggerInterface::class, 'logger');
        }
        if ($container->has('logger')) {
            return;
        }
        if ($debug = $container->getParameter('kernel.debug')) {
            $debug = $container->hasParameter('kernel.runtime_mode.web') ? $container->getParameter('kernel.runtime_mode.web') : !\in_array(\PHP_SAPI, ['cli', 'phpdbg', 'embed'], \true);
        }
        $container->register('logger', Logger::class)->setArguments([null, null, null, new Reference(RequestStack::class), $debug]);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\HttpKernel\DependencyInjection;

use _ContaoManager\Symfony\Component\DependencyInjection\Extension\Extension as BaseExtension;
/**
 * Allow adding classes to the class cache.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
abstract class Extension extends BaseExtension
{
    private array $annotatedClasses = [];
    /**
     * Gets the annotated classes to cache.
     */
    public function getAnnotatedClassesToCompile(): array
    {
        return $this->annotatedClasses;
    }
    /**
     * Adds annotated classes to the class cache.
     *
     * @param array $annotatedClasses An array of class patterns
     *
     * @return void
     */
    public function addAnnotatedClassesToCompile(array $annotatedClasses)
    {
        $this->annotatedClasses = array_merge($this->annotatedClasses, $annotatedClasses);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\HttpKernel\DependencyInjection;

use _ContaoManager\Symfony\Component\DependencyInjection\Argument\IteratorArgument;
use _ContaoManager\Symfony\Component\DependencyInjection\Argument\ServiceLocatorArgument;
use _ContaoManager\Symfony\Component\DependencyInjection\Argument\TaggedIteratorArgument;
use _ContaoManager\Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Compiler\PriorityTaggedServiceTrait;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerBuilder;
use _ContaoManager\Symfony\Component\DependencyInjection\Reference;
use _ContaoManager\Symfony\Component\HttpKernel\Controller\ArgumentResolver\TraceableValueResolver;
use _ContaoManager\Symfony\Component\Stopwatch\Stopwatch;
/**
 * Gathers and configures the argument value resolvers.
 *
 * @author Iltar van der Berg <kjarli@gmail.com>
 */
class ControllerArgumentValueResolverPass implements CompilerPassInterface
{
    use PriorityTaggedServiceTrait;
    /**
     * @return void
     */
    public function process(ContainerBuilder $container)
    {
        if (!$container->hasDefinition('argument_resolver')) {
            return;
        }
        $definitions = $container->getDefinitions();
        $namedResolvers = $this->findAndSortTaggedServices(new TaggedIteratorArgument('controller.targeted_value_resolver', 'name', needsIndexes: \true), $container);
        $resolvers = $this->findAndSortTaggedServices(new TaggedIteratorArgument('controller.argument_value_resolver', 'name', needsIndexes: \true), $container);
        foreach ($resolvers as $name => $resolver) {
            if ($definitions[(string) $resolver]->hasTag('controller.targeted_value_resolver')) {
                unset($resolvers[$name]);
            } else {
                $namedResolvers[$name] ??= clone $resolver;
            }
        }
        if ($container->getParameter('kernel.debug') && class_exists(Stopwatch::class) && $container->has('debug.stopwatch')) {
            foreach ($resolvers as $name => $resolver) {
                $resolvers[$name] = new Reference('.debug.value_resolver.' . $resolver);
                $container->register('.debug.value_resolver.' . $resolver, TraceableValueResolver::class)->setArguments([$resolver, new Reference('debug.stopwatch')]);
            }
            foreach ($namedResolvers as $name => $resolver) {
                $namedResolvers[$name] = new Reference('.debug.value_resolver.' . $resolver);
                $container->register('.debug.value_resolver.' . $resolver, TraceableValueResolver::class)->setArguments([$resolver, new Reference('debug.stopwatch')]);
            }
        }
        $container->getDefinition('argument_resolver')->replaceArgument(1, new IteratorArgument(array_values($resolvers)))->setArgument(2, new ServiceLocatorArgument($namedResolvers));
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\HttpKernel\DependencyInjection;

use _ContaoManager\Symfony\Component\DependencyInjection\Attribute\Autowire;
use _ContaoManager\Symfony\Component\DependencyInjection\Attribute\AutowireCallable;
use _ContaoManager\Symfony\Component\DependencyInjection\Attribute\Target;
use _ContaoManager\Symfony\Component\DependencyInjection\ChildDefinition;
use _ContaoManager\Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Compiler\ServiceLocatorTagPass;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerBuilder;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
use _ContaoManager\Symfony\Component\DependencyInjection\Reference;
use _ContaoManager\Symfony\Component\DependencyInjection\TypedReference;
use _ContaoManager\Symfony\Component\HttpFoundation\Request;
use _ContaoManager\Symfony\Component\HttpFoundation\Response;
use _ContaoManager\Symfony\Component\HttpFoundation\Session\SessionInterface;
use _ContaoManager\Symfony\Component\VarExporter\ProxyHelper;
/**
 * Creates the service-locators required by ServiceValueResolver.
 *
 * @author Nicolas Grekas <p@tchwork.com>
 */
class RegisterControllerArgumentLocatorsPass implements CompilerPassInterface
{
    /**
     * @return void
     */
    public function process(ContainerBuilder $container)
    {
        if (!$container->hasDefinition('argument_resolver.service') && !$container->hasDefinition('argument_resolver.not_tagged_controller')) {
            return;
        }
        $parameterBag = $container->getParameterBag();
        $controllers = [];
        $controllerClasses = [];
        $publicAliases = [];
        foreach ($container->getAliases() as $id => $alias) {
            if ($alias->isPublic() && !$alias->isPrivate()) {
                $publicAliases[(string) $alias][] = $id;
            }
        }
        $emptyAutowireAttributes = class_exists(Autowire::class) ? null : [];
        foreach ($container->findTaggedServiceIds('controller.service_arguments', \true) as $id => $tags) {
            $def = $container->getDefinition($id);
            $def->setPublic(\true);
            $def->setLazy(\false);
            $class = $def->getClass();
            $autowire = $def->isAutowired();
            $bindings = $def->getBindings();
            // resolve service class, taking parent definitions into account
            while ($def instanceof ChildDefinition) {
                $def = $container->findDefinition($def->getParent());
                $class = $class ?: $def->getClass();
                $bindings += $def->getBindings();
            }
            $class = $parameterBag->resolveValue($class);
            if (!$r = $container->getReflectionClass($class)) {
                throw new InvalidArgumentException(\sprintf('Class "%s" used for service "%s" cannot be found.', $class, $id));
            }
            $controllerClasses[] = $class;
            // get regular public methods
            $methods = [];
            $arguments = [];
            foreach ($r->getMethods(\ReflectionMethod::IS_PUBLIC) as $r) {
                if ('setContainer' === $r->name) {
                    continue;
                }
                if (!$r->isConstructor() && !$r->isDestructor() && !$r->isAbstract()) {
                    $methods[strtolower($r->name)] = [$r, $r->getParameters()];
                }
            }
            // validate and collect explicit per-actions and per-arguments service references
            foreach ($tags as $attributes) {
                if (!isset($attributes['action']) && !isset($attributes['argument']) && !isset($attributes['id'])) {
                    $autowire = \true;
                    continue;
                }
                foreach (['action', 'argument', 'id'] as $k) {
                    if (!isset($attributes[$k][0])) {
                        throw new InvalidArgumentException(\sprintf('Missing "%s" attribute on tag "controller.service_arguments" %s for service "%s".', $k, json_encode($attributes, \JSON_UNESCAPED_UNICODE), $id));
                    }
                }
                if (!isset($methods[$action = strtolower($attributes['action'])])) {
                    throw new InvalidArgumentException(\sprintf('Invalid "action" attribute on tag "controller.service_arguments" for service "%s": no public "%s()" method found on class "%s".', $id, $attributes['action'], $class));
                }
                [$r, $parameters] = $methods[$action];
                $found = \false;
                foreach ($parameters as $p) {
                    if ($attributes['argument'] === $p->name) {
                        if (!isset($arguments[$r->name][$p->name])) {
                            $arguments[$r->name][$p->name] = $attributes['id'];
                        }
                        $found = \true;
                        break;
                    }
                }
                if (!$found) {
                    throw new InvalidArgumentException(\sprintf('Invalid "controller.service_arguments" tag for service "%s": method "%s()" has no "%s" argument on class "%s".', $id, $r->name, $attributes['argument'], $class));
                }
            }
            foreach ($methods as [$r, $parameters]) {
                /** @var \ReflectionMethod $r */
                // create a per-method map of argument-names to service/type-references
                $args = [];
                foreach ($parameters as $p) {
                    /** @var \ReflectionParameter $p */
                    $type = preg_replace('/(^|[(|&])\\\\/', '\1', $target = ltrim(ProxyHelper::exportType($p) ?? '', '?'));
                    $invalidBehavior = ContainerInterface::IGNORE_ON_INVALID_REFERENCE;
                    $autowireAttributes = $autowire ? $emptyAutowireAttributes : [];
                    $parsedName = $p->name;
                    $k = null;
                    if (isset($arguments[$r->name][$p->name])) {
                        $target = $arguments[$r->name][$p->name];
                        if ('?' !== $target[0]) {
                            $invalidBehavior = ContainerInterface::RUNTIME_EXCEPTION_ON_INVALID_REFERENCE;
                        } elseif ('' === $target = (string) substr($target, 1)) {
                            throw new InvalidArgumentException(\sprintf('A "controller.service_arguments" tag must have non-empty "id" attributes for service "%s".', $id));
                        } elseif ($p->allowsNull() && !$p->isOptional()) {
                            $invalidBehavior = ContainerInterface::NULL_ON_INVALID_REFERENCE;
                        }
                    } elseif (isset($bindings[$bindingName = $type . ' $' . $name = Target::parseName($p, $k, $parsedName)]) || isset($bindings[$bindingName = $type . ' $' . $parsedName]) || isset($bindings[$bindingName = '$' . $name]) || isset($bindings[$bindingName = $type])) {
                        $binding = $bindings[$bindingName];
                        [$bindingValue, $bindingId, , $bindingType, $bindingFile] = $binding->getValues();
                        $binding->setValues([$bindingValue, $bindingId, \true, $bindingType, $bindingFile]);
                        $args[$p->name] = $bindingValue;
                        continue;
                    } elseif (!$autowire || !($autowireAttributes ??= $p->getAttributes(Autowire::class, \ReflectionAttribute::IS_INSTANCEOF)) && (!$type || '\\' !== $target[0])) {
                        continue;
                    } elseif (!$autowireAttributes && is_subclass_of($type, \UnitEnum::class)) {
                        // do not attempt to register enum typed arguments if not already present in bindings
                        continue;
                    } elseif (!$p->allowsNull()) {
                        $invalidBehavior = ContainerInterface::RUNTIME_EXCEPTION_ON_INVALID_REFERENCE;
                    }
                    if (Request::class === $type || SessionInterface::class === $type || Response::class === $type) {
                        continue;
                    }
                    if ($autowireAttributes) {
                        $invalidBehavior = ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE;
                        $attribute = $autowireAttributes[0]->newInstance();
                        $value = $parameterBag->resolveValue($attribute->value);
                        if ($attribute instanceof AutowireCallable) {
                            $value = $attribute->buildDefinition($value, $type, $p);
                        }
                        if ($value instanceof Reference) {
                            $args[$p->name] = $type ? new TypedReference($value, $type, $invalidBehavior, $p->name) : new Reference($value, $invalidBehavior);
                        } else {
                            $args[$p->name] = new Reference('.value.' . $container->hash($value));
                            $container->register((string) $args[$p->name], 'mixed')->setFactory('current')->addArgument([$value]);
                        }
                        continue;
                    }
                    if ($type && !$p->isOptional() && !$p->allowsNull() && !class_exists($type) && !interface_exists($type, \false)) {
                        $message = \sprintf('Cannot determine controller argument for "%s::%s()": the $%s argument is type-hinted with the non-existent class or interface: "%s".', $class, $r->name, $p->name, $type);
                        // see if the type-hint lives in the same namespace as the controller
                        if (0 === strncmp($type, $class, strrpos($class, '\\'))) {
                            $message .= ' Did you forget to add a use statement?';
                        }
                        $container->register($erroredId = '.errored.' . $container->hash($message), $type)->addError($message);
                        $args[$p->name] = new Reference($erroredId, ContainerInterface::RUNTIME_EXCEPTION_ON_INVALID_REFERENCE);
                    } else {
                        $targetAttribute = null;
                        $name = Target::parseName($p, $targetAttribute);
                        $target = preg_replace('/(^|[(|&])\\\\/', '\1', $target);
                        $args[$p->name] = $type ? new TypedReference($target, $type, $invalidBehavior, $name, $targetAttribute ? [$targetAttribute] : []) : new Reference($target, $invalidBehavior);
                    }
                }
                // register the maps as a per-method service-locators
                if ($args) {
                    $controllers[$id . '::' . $r->name] = ServiceLocatorTagPass::register($container, $args);
                    foreach ($publicAliases[$id] ?? [] as $alias) {
                        $controllers[$alias . '::' . $r->name] = clone $controllers[$id . '::' . $r->name];
                    }
                }
            }
        }
        $controllerLocatorRef = ServiceLocatorTagPass::register($container, $controllers);
        if ($container->hasDefinition('argument_resolver.service')) {
            $container->getDefinition('argument_resolver.service')->replaceArgument(0, $controllerLocatorRef);
        }
        if ($container->hasDefinition('argument_resolver.not_tagged_controller')) {
            $container->getDefinition('argument_resolver.not_tagged_controller')->replaceArgument(0, $controllerLocatorRef);
        }
        $container->setAlias('argument_resolver.controller_locator', (string) $controllerLocatorRef);
        if ($container->hasDefinition('controller_resolver')) {
            $container->getDefinition('controller_resolver')->addMethodCall('allowControllers', [array_unique($controllerClasses)]);
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\HttpKernel\DependencyInjection;

use _ContaoManager\Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerBuilder;
/**
 * Removes empty service-locators registered for ServiceValueResolver.
 *
 * @author Nicolas Grekas <p@tchwork.com>
 */
class RemoveEmptyControllerArgumentLocatorsPass implements CompilerPassInterface
{
    /**
     * @return void
     */
    public function process(ContainerBuilder $container)
    {
        $controllerLocator = $container->findDefinition('argument_resolver.controller_locator');
        $controllers = $controllerLocator->getArgument(0);
        foreach ($controllers as $controller => $argumentRef) {
            $argumentLocator = $container->getDefinition((string) $argumentRef->getValues()[0]);
            if (!$argumentLocator->getArgument(0)) {
                // remove empty argument locators
                $reason = \sprintf('Removing service-argument resolver for controller "%s": no corresponding services exist for the referenced types.', $controller);
            } else {
                // any methods listed for call-at-instantiation cannot be actions
                $reason = \false;
                [$id, $action] = explode('::', $controller);
                if ($container->hasAlias($id)) {
                    continue;
                }
                $controllerDef = $container->getDefinition($id);
                foreach ($controllerDef->getMethodCalls() as [$method]) {
                    if (0 === strcasecmp($action, $method)) {
                        $reason = \sprintf('Removing method "%s" of service "%s" from controller candidates: the method is called at instantiation, thus cannot be an action.', $action, $id);
                        break;
                    }
                }
                if (!$reason) {
                    // see Symfony\Component\HttpKernel\Controller\ContainerControllerResolver
                    $controllers[$id . ':' . $action] = $argumentRef;
                    if ('__invoke' === $action) {
                        $controllers[$id] = $argumentRef;
                    }
                    continue;
                }
            }
            unset($controllers[$controller]);
            $container->log($this, $reason);
        }
        $controllerLocator->replaceArgument(0, $controllers);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\HttpKernel\DependencyInjection;

use _ContaoManager\Psr\Container\ContainerInterface;
use _ContaoManager\Symfony\Component\HttpFoundation\RequestStack;
use _ContaoManager\Symfony\Component\HttpKernel\Controller\ControllerReference;
use _ContaoManager\Symfony\Component\HttpKernel\Fragment\FragmentHandler;
/**
 * Lazily loads fragment renderers from the dependency injection container.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class LazyLoadingFragmentHandler extends FragmentHandler
{
    private ContainerInterface $container;
    /**
     * @var array<string, bool>
     */
    private array $initialized = [];
    public function __construct(ContainerInterface $container, RequestStack $requestStack, bool $debug = \false)
    {
        $this->container = $container;
        parent::__construct($requestStack, [], $debug);
    }
    public function render(string|ControllerReference $uri, string $renderer = 'inline', array $options = []): ?string
    {
        if (!isset($this->initialized[$renderer]) && $this->container->has($renderer)) {
            $this->addRenderer($this->container->get($renderer));
            $this->initialized[$renderer] = \true;
        }
        return parent::render($uri, $renderer, $options);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\HttpKernel\Exception;

/**
 * @author Ben Ramsey <ben@benramsey.com>
 *
 * @see http://tools.ietf.org/html/rfc6585
 */
class TooManyRequestsHttpException extends HttpException
{
    /**
     * @param int|string|null $retryAfter The number of seconds or HTTP-date after which the request may be retried
     */
    public function __construct(int|string|null $retryAfter = null, string $message = '', ?\Throwable $previous = null, int $code = 0, array $headers = [])
    {
        if ($retryAfter) {
            $headers['Retry-After'] = $retryAfter;
        }
        parent::__construct(429, $message, $previous, $headers, $code);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\HttpKernel\Exception;

/**
 * @author Ben Ramsey <ben@benramsey.com>
 */
class ConflictHttpException extends HttpException
{
    public function __construct(string $message = '', ?\Throwable $previous = null, int $code = 0, array $headers = [])
    {
        parent::__construct(409, $message, $previous, $headers, $code);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\HttpKernel\Exception;

/**
 * HttpException.
 *
 * @author Kris Wallsmith <kris@symfony.com>
 */
class HttpException extends \RuntimeException implements HttpExceptionInterface
{
    private int $statusCode;
    private array $headers;
    public function __construct(int $statusCode, string $message = '', ?\Throwable $previous = null, array $headers = [], int $code = 0)
    {
        $this->statusCode = $statusCode;
        $this->headers = $headers;
        parent::__construct($message, $code, $previous);
    }
    public function getStatusCode(): int
    {
        return $this->statusCode;
    }
    public function getHeaders(): array
    {
        return $this->headers;
    }
    /**
     * @return void
     */
    public function setHeaders(array $headers)
    {
        $this->headers = $headers;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\HttpKernel\Exception;

/**
 * @author Ben Ramsey <ben@benramsey.com>
 */
class UnauthorizedHttpException extends HttpException
{
    /**
     * @param string $challenge WWW-Authenticate challenge string
     */
    public function __construct(string $challenge, string $message = '', ?\Throwable $previous = null, int $code = 0, array $headers = [])
    {
        $headers['WWW-Authenticate'] = $challenge;
        parent::__construct(401, $message, $previous, $headers, $code);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\HttpKernel\Exception;

class InvalidMetadataException extends \LogicException
{
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\HttpKernel\Exception;

/**
 * @author Ben Ramsey <ben@benramsey.com>
 */
class LengthRequiredHttpException extends HttpException
{
    public function __construct(string $message = '', ?\Throwable $previous = null, int $code = 0, array $headers = [])
    {
        parent::__construct(411, $message, $previous, $headers, $code);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\HttpKernel\Exception;

/**
 * @author Steve Hutchins <hutchinsteve@gmail.com>
 */
class UnprocessableEntityHttpException extends HttpException
{
    public function __construct(string $message = '', ?\Throwable $previous = null, int $code = 0, array $headers = [])
    {
        parent::__construct(422, $message, $previous, $headers, $code);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\HttpKernel\Exception;

/**
 * @author Ben Ramsey <ben@benramsey.com>
 */
class PreconditionFailedHttpException extends HttpException
{
    public function __construct(string $message = '', ?\Throwable $previous = null, int $code = 0, array $headers = [])
    {
        parent::__construct(412, $message, $previous, $headers, $code);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\HttpKernel\Exception;

/**
 * @author Ben Ramsey <ben@benramsey.com>
 */
class GoneHttpException extends HttpException
{
    public function __construct(string $message = '', ?\Throwable $previous = null, int $code = 0, array $headers = [])
    {
        parent::__construct(410, $message, $previous, $headers, $code);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\HttpKernel\Exception;

/**
 * @author Ben Ramsey <ben@benramsey.com>
 */
class UnsupportedMediaTypeHttpException extends HttpException
{
    public function __construct(string $message = '', ?\Throwable $previous = null, int $code = 0, array $headers = [])
    {
        parent::__construct(415, $message, $previous, $headers, $code);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\HttpKernel\Exception;

/**
 * @author Mathias Arlaud <mathias.arlaud@gmail.com>
 */
class UnexpectedSessionUsageException extends \LogicException
{
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\HttpKernel\Exception;

/**
 * @author Peter Dietrich <xosofox@gmail.com>
 */
class LockedHttpException extends HttpException
{
    public function __construct(string $message = '', ?\Throwable $previous = null, int $code = 0, array $headers = [])
    {
        parent::__construct(423, $message, $previous, $headers, $code);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\HttpKernel\Exception;

/**
 * @author Ben Ramsey <ben@benramsey.com>
 */
class ServiceUnavailableHttpException extends HttpException
{
    /**
     * @param int|string|null $retryAfter The number of seconds or HTTP-date after which the request may be retried
     */
    public function __construct(int|string|null $retryAfter = null, string $message = '', ?\Throwable $previous = null, int $code = 0, array $headers = [])
    {
        if ($retryAfter) {
            $headers['Retry-After'] = $retryAfter;
        }
        parent::__construct(503, $message, $previous, $headers, $code);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\HttpKernel\Exception;

/**
 * Interface for HTTP error exceptions.
 *
 * @author Kris Wallsmith <kris@symfony.com>
 */
interface HttpExceptionInterface extends \Throwable
{
    /**
     * Returns the status code.
     */
    public function getStatusCode(): int;
    /**
     * Returns response headers.
     */
    public function getHeaders(): array;
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\HttpKernel\Exception;

/**
 * @author Fabien Potencier <fabien@symfony.com>
 * @author Christophe Coevoet <stof@notk.org>
 */
class AccessDeniedHttpException extends HttpException
{
    public function __construct(string $message = '', ?\Throwable $previous = null, int $code = 0, array $headers = [])
    {
        parent::__construct(403, $message, $previous, $headers, $code);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\HttpKernel\Exception;

/**
 * @author Ben Ramsey <ben@benramsey.com>
 */
class BadRequestHttpException extends HttpException
{
    public function __construct(string $message = '', ?\Throwable $previous = null, int $code = 0, array $headers = [])
    {
        parent::__construct(400, $message, $previous, $headers, $code);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\HttpKernel\Exception;

/**
 * @author Grégoire Pineau <lyrixx@lyrixx.info>
 */
class ControllerDoesNotReturnResponseException extends \LogicException
{
    public function __construct(string $message, callable $controller, string $file, int $line)
    {
        parent::__construct($message);
        if (!$controllerDefinition = $this->parseControllerDefinition($controller)) {
            return;
        }
        $this->file = $controllerDefinition['file'];
        $this->line = $controllerDefinition['line'];
        $r = new \ReflectionProperty(\Exception::class, 'trace');
        $r->setValue($this, array_merge([['line' => $line, 'file' => $file]], $this->getTrace()));
    }
    private function parseControllerDefinition(callable $controller): ?array
    {
        if (\is_string($controller) && str_contains($controller, '::')) {
            $controller = explode('::', $controller);
        }
        if (\is_array($controller)) {
            try {
                $r = new \ReflectionMethod($controller[0], $controller[1]);
                return ['file' => $r->getFileName(), 'line' => $r->getEndLine()];
            } catch (\ReflectionException) {
                return null;
            }
        }
        if ($controller instanceof \Closure) {
            $r = new \ReflectionFunction($controller);
            return ['file' => $r->getFileName(), 'line' => $r->getEndLine()];
        }
        if (\is_object($controller)) {
            $r = new \ReflectionClass($controller);
            try {
                $line = $r->getMethod('__invoke')->getEndLine();
            } catch (\ReflectionException) {
                $line = $r->getEndLine();
            }
            return ['file' => $r->getFileName(), 'line' => $line];
        }
        return null;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\HttpKernel\Exception;

/**
 * @author Ben Ramsey <ben@benramsey.com>
 */
class NotAcceptableHttpException extends HttpException
{
    public function __construct(string $message = '', ?\Throwable $previous = null, int $code = 0, array $headers = [])
    {
        parent::__construct(406, $message, $previous, $headers, $code);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\HttpKernel\Exception;

/**
 * @author Ben Ramsey <ben@benramsey.com>
 *
 * @see http://tools.ietf.org/html/rfc6585
 */
class PreconditionRequiredHttpException extends HttpException
{
    public function __construct(string $message = '', ?\Throwable $previous = null, int $code = 0, array $headers = [])
    {
        parent::__construct(428, $message, $previous, $headers, $code);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\HttpKernel\Exception;

/**
 * @author Fabien Potencier <fabien@symfony.com>
 */
class NotFoundHttpException extends HttpException
{
    public function __construct(string $message = '', ?\Throwable $previous = null, int $code = 0, array $headers = [])
    {
        parent::__construct(404, $message, $previous, $headers, $code);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\HttpKernel\Exception;

/**
 * @author Kris Wallsmith <kris@symfony.com>
 */
class MethodNotAllowedHttpException extends HttpException
{
    /**
     * @param string[] $allow An array of allowed methods
     */
    public function __construct(array $allow, string $message = '', ?\Throwable $previous = null, int $code = 0, array $headers = [])
    {
        $headers['Allow'] = strtoupper(implode(', ', $allow));
        parent::__construct(405, $message, $previous, $headers, $code);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\HttpKernel\Exception;

class ResolverNotFoundException extends \RuntimeException
{
    /**
     * @param string[] $alternatives
     */
    public function __construct(string $name, array $alternatives = [])
    {
        $msg = \sprintf('You have requested a non-existent resolver "%s".', $name);
        if ($alternatives) {
            if (1 === \count($alternatives)) {
                $msg .= ' Did you mean this: "';
            } else {
                $msg .= ' Did you mean one of these: "';
            }
            $msg .= implode('", "', $alternatives) . '"?';
        }
        parent::__construct($msg);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\HttpKernel\Event;

use _ContaoManager\Symfony\Component\HttpFoundation\Request;
use _ContaoManager\Symfony\Component\HttpKernel\HttpKernelInterface;
/**
 * Allows filtering of a controller callable.
 *
 * You can call getController() to retrieve the current controller. With
 * setController() you can set a new controller that is used in the processing
 * of the request.
 *
 * Controllers should be callables.
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
final class ControllerEvent extends KernelEvent
{
    private string|array|object $controller;
    private \ReflectionFunctionAbstract $controllerReflector;
    private array $attributes;
    public function __construct(HttpKernelInterface $kernel, callable $controller, Request $request, ?int $requestType)
    {
        parent::__construct($kernel, $request, $requestType);
        $this->setController($controller);
    }
    public function getController(): callable
    {
        return $this->controller;
    }
    public function getControllerReflector(): \ReflectionFunctionAbstract
    {
        return $this->controllerReflector;
    }
    /**
     * @param array<class-string, list<object>>|null $attributes
     */
    public function setController(callable $controller, ?array $attributes = null): void
    {
        if (null !== $attributes) {
            $this->attributes = $attributes;
        }
        if (isset($this->controller) && ($controller instanceof \Closure ? $controller == $this->controller : $controller === $this->controller)) {
            $this->controller = $controller;
            return;
        }
        if (null === $attributes) {
            unset($this->attributes);
        }
        if (\is_array($controller) && method_exists(...$controller)) {
            $this->controllerReflector = new \ReflectionMethod(...$controller);
        } elseif (\is_string($controller) && str_contains($controller, '::')) {
            $this->controllerReflector = new \ReflectionMethod(...explode('::', $controller, 2));
        } else {
            $this->controllerReflector = new \ReflectionFunction($controller(...));
        }
        $this->controller = $controller;
    }
    /**
     * @template T of class-string|null
     *
     * @param T $className
     *
     * @return array<class-string, list<object>>|list<object>
     *
     * @psalm-return (T is null ? array<class-string, list<object>> : list<object>)
     */
    public function getAttributes(?string $className = null): array
    {
        if (isset($this->attributes)) {
            return null === $className ? $this->attributes : $this->attributes[$className] ?? [];
        }
        if (\is_array($this->controller) && method_exists(...$this->controller)) {
            $class = new \ReflectionClass($this->controller[0]);
        } elseif (\is_string($this->controller) && \false !== $i = strpos($this->controller, '::')) {
            $class = new \ReflectionClass(substr($this->controller, 0, $i));
        } else {
            $class = str_contains($this->controllerReflector->name, '{closure') ? null : (\PHP_VERSION_ID >= 80111 ? $this->controllerReflector->getClosureCalledClass() : $this->controllerReflector->getClosureScopeClass());
        }
        $this->attributes = [];
        foreach (array_merge($class?->getAttributes() ?? [], $this->controllerReflector->getAttributes()) as $attribute) {
            if (class_exists($attribute->getName())) {
                $this->attributes[$attribute->getName()][] = $attribute->newInstance();
            }
        }
        return null === $className ? $this->attributes : $this->attributes[$className] ?? [];
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\HttpKernel\Event;

use _ContaoManager\Symfony\Component\HttpFoundation\Request;
use _ContaoManager\Symfony\Component\HttpKernel\HttpKernelInterface;
/**
 * Allows to create a response for a thrown exception.
 *
 * Call setResponse() to set the response that will be returned for the
 * current request. The propagation of this event is stopped as soon as a
 * response is set.
 *
 * You can also call setThrowable() to replace the thrown exception. This
 * exception will be thrown if no response is set during processing of this
 * event.
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
final class ExceptionEvent extends RequestEvent
{
    private \Throwable $throwable;
    private bool $allowCustomResponseCode = \false;
    public function __construct(HttpKernelInterface $kernel, Request $request, int $requestType, \Throwable $e)
    {
        parent::__construct($kernel, $request, $requestType);
        $this->setThrowable($e);
    }
    public function getThrowable(): \Throwable
    {
        return $this->throwable;
    }
    /**
     * Replaces the thrown exception.
     *
     * This exception will be thrown if no response is set in the event.
     */
    public function setThrowable(\Throwable $exception): void
    {
        $this->throwable = $exception;
    }
    /**
     * Mark the event as allowing a custom response code.
     */
    public function allowCustomResponseCode(): void
    {
        $this->allowCustomResponseCode = \true;
    }
    /**
     * Returns true if the event allows a custom response code.
     */
    public function isAllowingCustomResponseCode(): bool
    {
        return $this->allowCustomResponseCode;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\HttpKernel\Event;

/**
 * Triggered whenever a request is fully processed.
 *
 * @author Benjamin Eberlei <kontakt@beberlei.de>
 */
final class FinishRequestEvent extends KernelEvent
{
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\HttpKernel\Event;

use _ContaoManager\Symfony\Component\HttpFoundation\Request;
use _ContaoManager\Symfony\Component\HttpFoundation\Response;
use _ContaoManager\Symfony\Component\HttpKernel\HttpKernelInterface;
/**
 * Allows to filter a Response object.
 *
 * You can call getResponse() to retrieve the current response. With
 * setResponse() you can set a new response that will be returned to the
 * browser.
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
final class ResponseEvent extends KernelEvent
{
    private Response $response;
    public function __construct(HttpKernelInterface $kernel, Request $request, int $requestType, Response $response)
    {
        parent::__construct($kernel, $request, $requestType);
        $this->setResponse($response);
    }
    public function getResponse(): Response
    {
        return $this->response;
    }
    public function setResponse(Response $response): void
    {
        $this->response = $response;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\HttpKernel\Event;

use _ContaoManager\Symfony\Component\HttpFoundation\Request;
use _ContaoManager\Symfony\Component\HttpFoundation\Response;
use _ContaoManager\Symfony\Component\HttpKernel\HttpKernelInterface;
/**
 * Allows to execute logic after a response was sent.
 *
 * Since it's only triggered on main requests, the `getRequestType()` method
 * will always return the value of `HttpKernelInterface::MAIN_REQUEST`.
 *
 * @author Jordi Boggiano <j.boggiano@seld.be>
 */
final class TerminateEvent extends KernelEvent
{
    private Response $response;
    public function __construct(HttpKernelInterface $kernel, Request $request, Response $response)
    {
        parent::__construct($kernel, $request, HttpKernelInterface::MAIN_REQUEST);
        $this->response = $response;
    }
    public function getResponse(): Response
    {
        return $this->response;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\HttpKernel\Event;

use _ContaoManager\Symfony\Component\HttpFoundation\Request;
use _ContaoManager\Symfony\Component\HttpKernel\HttpKernelInterface;
/**
 * Allows filtering of controller arguments.
 *
 * You can call getController() to retrieve the controller and getArguments
 * to retrieve the current arguments. With setArguments() you can replace
 * arguments that are used to call the controller.
 *
 * Arguments set in the event must be compatible with the signature of the
 * controller.
 *
 * @author Christophe Coevoet <stof@notk.org>
 */
final class ControllerArgumentsEvent extends KernelEvent
{
    private ControllerEvent $controllerEvent;
    private array $arguments;
    private array $namedArguments;
    public function __construct(HttpKernelInterface $kernel, callable|ControllerEvent $controller, array $arguments, Request $request, ?int $requestType)
    {
        parent::__construct($kernel, $request, $requestType);
        if (!$controller instanceof ControllerEvent) {
            $controller = new ControllerEvent($kernel, $controller, $request, $requestType);
        }
        $this->controllerEvent = $controller;
        $this->arguments = $arguments;
    }
    public function getController(): callable
    {
        return $this->controllerEvent->getController();
    }
    /**
     * @param array<class-string, list<object>>|null $attributes
     */
    public function setController(callable $controller, ?array $attributes = null): void
    {
        $this->controllerEvent->setController($controller, $attributes);
        unset($this->namedArguments);
    }
    public function getArguments(): array
    {
        return $this->arguments;
    }
    public function setArguments(array $arguments): void
    {
        $this->arguments = $arguments;
        unset($this->namedArguments);
    }
    public function getNamedArguments(): array
    {
        if (isset($this->namedArguments)) {
            return $this->namedArguments;
        }
        $namedArguments = [];
        $arguments = $this->arguments;
        foreach ($this->controllerEvent->getControllerReflector()->getParameters() as $i => $param) {
            if ($param->isVariadic()) {
                $namedArguments[$param->name] = \array_slice($arguments, $i);
                break;
            }
            if (\array_key_exists($i, $arguments)) {
                $namedArguments[$param->name] = $arguments[$i];
            } elseif ($param->isDefaultvalueAvailable()) {
                $namedArguments[$param->name] = $param->getDefaultValue();
            }
        }
        return $this->namedArguments = $namedArguments;
    }
    /**
     * @template T of class-string|null
     *
     * @param T $className
     *
     * @return array<class-string, list<object>>|list<object>
     *
     * @psalm-return (T is null ? array<class-string, list<object>> : list<object>)
     */
    public function getAttributes(?string $className = null): array
    {
        return $this->controllerEvent->getAttributes($className);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\HttpKernel\Event;

use _ContaoManager\Symfony\Component\HttpFoundation\Request;
use _ContaoManager\Symfony\Component\HttpKernel\HttpKernelInterface;
use _ContaoManager\Symfony\Contracts\EventDispatcher\Event;
/**
 * Base class for events dispatched in the HttpKernel component.
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
class KernelEvent extends Event
{
    private HttpKernelInterface $kernel;
    private Request $request;
    private ?int $requestType;
    /**
     * @param int $requestType The request type the kernel is currently processing; one of
     *                         HttpKernelInterface::MAIN_REQUEST or HttpKernelInterface::SUB_REQUEST
     */
    public function __construct(HttpKernelInterface $kernel, Request $request, ?int $requestType)
    {
        $this->kernel = $kernel;
        $this->request = $request;
        $this->requestType = $requestType;
    }
    /**
     * Returns the kernel in which this event was thrown.
     */
    public function getKernel(): HttpKernelInterface
    {
        return $this->kernel;
    }
    /**
     * Returns the request the kernel is currently processing.
     */
    public function getRequest(): Request
    {
        return $this->request;
    }
    /**
     * Returns the request type the kernel is currently processing.
     *
     * @return int One of HttpKernelInterface::MAIN_REQUEST and
     *             HttpKernelInterface::SUB_REQUEST
     */
    public function getRequestType(): int
    {
        return $this->requestType;
    }
    /**
     * Checks if this is the main request.
     */
    public function isMainRequest(): bool
    {
        return HttpKernelInterface::MAIN_REQUEST === $this->requestType;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\HttpKernel\Event;

use _ContaoManager\Symfony\Component\HttpFoundation\Response;
/**
 * Allows to create a response for a request.
 *
 * Call setResponse() to set the response that will be returned for the
 * current request. The propagation of this event is stopped as soon as a
 * response is set.
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
class RequestEvent extends KernelEvent
{
    private ?Response $response = null;
    /**
     * Returns the response object.
     */
    public function getResponse(): ?Response
    {
        return $this->response;
    }
    /**
     * Sets a response and stops event propagation.
     *
     * @return void
     */
    public function setResponse(Response $response)
    {
        $this->response = $response;
        $this->stopPropagation();
    }
    /**
     * Returns whether a response was set.
     */
    public function hasResponse(): bool
    {
        return null !== $this->response;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\HttpKernel\Event;

use _ContaoManager\Symfony\Component\HttpFoundation\Request;
use _ContaoManager\Symfony\Component\HttpKernel\HttpKernelInterface;
/**
 * Allows to create a response for the return value of a controller.
 *
 * Call setResponse() to set the response that will be returned for the
 * current request. The propagation of this event is stopped as soon as a
 * response is set.
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
final class ViewEvent extends RequestEvent
{
    public readonly ?ControllerArgumentsEvent $controllerArgumentsEvent;
    private mixed $controllerResult;
    public function __construct(HttpKernelInterface $kernel, Request $request, int $requestType, mixed $controllerResult, ?ControllerArgumentsEvent $controllerArgumentsEvent = null)
    {
        parent::__construct($kernel, $request, $requestType);
        $this->controllerResult = $controllerResult;
        $this->controllerArgumentsEvent = $controllerArgumentsEvent;
    }
    public function getControllerResult(): mixed
    {
        return $this->controllerResult;
    }
    public function setControllerResult(mixed $controllerResult): void
    {
        $this->controllerResult = $controllerResult;
    }
}
{
    "name": "symfony\/http-kernel",
    "type": "library",
    "description": "Provides a structured process for converting a Request into a Response",
    "keywords": [],
    "homepage": "https:\/\/symfony.com",
    "license": "MIT",
    "authors": [
        {
            "name": "Fabien Potencier",
            "email": "fabien@symfony.com"
        },
        {
            "name": "Symfony Community",
            "homepage": "https:\/\/symfony.com\/contributors"
        }
    ],
    "require": {
        "php": ">=8.1",
        "symfony\/deprecation-contracts": "^2.5|^3",
        "symfony\/error-handler": "^6.4|^7.0",
        "symfony\/event-dispatcher": "^5.4|^6.0|^7.0",
        "symfony\/http-foundation": "^6.4|^7.0",
        "symfony\/polyfill-ctype": "^1.8",
        "psr\/log": "^1|^2|^3"
    },
    "require-dev": {
        "symfony\/browser-kit": "^5.4|^6.0|^7.0",
        "symfony\/clock": "^6.2|^7.0",
        "symfony\/config": "^6.1|^7.0",
        "symfony\/console": "^5.4|^6.0|^7.0",
        "symfony\/css-selector": "^5.4|^6.0|^7.0",
        "symfony\/dependency-injection": "^6.4.1|^7.0.1",
        "symfony\/dom-crawler": "^5.4|^6.0|^7.0",
        "symfony\/expression-language": "^5.4|^6.0|^7.0",
        "symfony\/finder": "^5.4|^6.0|^7.0",
        "symfony\/http-client-contracts": "^2.5|^3",
        "symfony\/process": "^5.4|^6.0|^7.0",
        "symfony\/property-access": "^5.4.5|^6.0.5|^7.0",
        "symfony\/routing": "^5.4|^6.0|^7.0",
        "symfony\/serializer": "^6.4.4|^7.0.4",
        "symfony\/stopwatch": "^5.4|^6.0|^7.0",
        "symfony\/translation": "^5.4|^6.0|^7.0",
        "symfony\/translation-contracts": "^2.5|^3",
        "symfony\/uid": "^5.4|^6.0|^7.0",
        "symfony\/validator": "^6.4|^7.0",
        "symfony\/var-dumper": "^5.4|^6.4|^7.0",
        "symfony\/var-exporter": "^6.2|^7.0",
        "psr\/cache": "^1.0|^2.0|^3.0",
        "twig\/twig": "^2.13|^3.0.4"
    },
    "provide": {
        "psr\/log-implementation": "1.0|2.0|3.0"
    },
    "conflict": {
        "symfony\/browser-kit": "<5.4",
        "symfony\/cache": "<5.4",
        "symfony\/config": "<6.1",
        "symfony\/console": "<5.4",
        "symfony\/form": "<5.4",
        "symfony\/dependency-injection": "<6.4",
        "symfony\/doctrine-bridge": "<5.4",
        "symfony\/http-client": "<5.4",
        "symfony\/http-client-contracts": "<2.5",
        "symfony\/mailer": "<5.4",
        "symfony\/messenger": "<5.4",
        "symfony\/translation": "<5.4",
        "symfony\/translation-contracts": "<2.5",
        "symfony\/twig-bridge": "<5.4",
        "symfony\/validator": "<6.4",
        "symfony\/var-dumper": "<6.3",
        "twig\/twig": "<2.13"
    },
    "autoload": {
        "psr-4": {
            "_ContaoManager\\Symfony\\Component\\HttpKernel\\": ""
        },
        "exclude-from-classmap": [
            "\/Tests\/"
        ]
    },
    "minimum-stability": "dev"
}<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\HttpKernel;

/**
 * Allows the Kernel to be rebooted using a temporary cache directory.
 *
 * @author Nicolas Grekas <p@tchwork.com>
 */
interface RebootableInterface
{
    /**
     * Reboots a kernel.
     *
     * The getBuildDir() method of a rebootable kernel should not be called
     * while building the container. Use the %kernel.build_dir% parameter instead.
     *
     * @param string|null $warmupDir pass null to reboot in the regular build directory
     *
     * @return void
     */
    public function reboot(?string $warmupDir);
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\HttpKernel;

use _ContaoManager\Symfony\Component\Config\Builder\ConfigBuilderGenerator;
use _ContaoManager\Symfony\Component\Config\ConfigCache;
use _ContaoManager\Symfony\Component\Config\Loader\DelegatingLoader;
use _ContaoManager\Symfony\Component\Config\Loader\LoaderResolver;
use _ContaoManager\Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Compiler\PassConfig;
use _ContaoManager\Symfony\Component\DependencyInjection\Compiler\RemoveBuildParametersPass;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerBuilder;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Dumper\PhpDumper;
use _ContaoManager\Symfony\Component\DependencyInjection\Dumper\Preloader;
use _ContaoManager\Symfony\Component\DependencyInjection\Extension\ExtensionInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Loader\ClosureLoader;
use _ContaoManager\Symfony\Component\DependencyInjection\Loader\DirectoryLoader;
use _ContaoManager\Symfony\Component\DependencyInjection\Loader\GlobFileLoader;
use _ContaoManager\Symfony\Component\DependencyInjection\Loader\IniFileLoader;
use _ContaoManager\Symfony\Component\DependencyInjection\Loader\PhpFileLoader;
use _ContaoManager\Symfony\Component\DependencyInjection\Loader\XmlFileLoader;
use _ContaoManager\Symfony\Component\DependencyInjection\Loader\YamlFileLoader;
use _ContaoManager\Symfony\Component\ErrorHandler\DebugClassLoader;
use _ContaoManager\Symfony\Component\Filesystem\Filesystem;
use _ContaoManager\Symfony\Component\HttpFoundation\Request;
use _ContaoManager\Symfony\Component\HttpFoundation\Response;
use _ContaoManager\Symfony\Component\HttpKernel\Bundle\BundleInterface;
use _ContaoManager\Symfony\Component\HttpKernel\CacheWarmer\WarmableInterface;
use _ContaoManager\Symfony\Component\HttpKernel\Config\FileLocator;
use _ContaoManager\Symfony\Component\HttpKernel\DependencyInjection\AddAnnotatedClassesToCachePass;
use _ContaoManager\Symfony\Component\HttpKernel\DependencyInjection\MergeExtensionConfigurationPass;
// Help opcache.preload discover always-needed symbols
class_exists(ConfigCache::class);
/**
 * The Kernel is the heart of the Symfony system.
 *
 * It manages an environment made of bundles.
 *
 * Environment names must always start with a letter and
 * they must only contain letters and numbers.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
abstract class Kernel implements KernelInterface, RebootableInterface, TerminableInterface
{
    /**
     * @var array<string, BundleInterface>
     */
    protected $bundles = [];
    protected $container;
    protected $environment;
    protected $debug;
    protected $booted = \false;
    protected $startTime;
    private string $projectDir;
    private ?string $warmupDir = null;
    private int $requestStackSize = 0;
    private bool $resetServices = \false;
    private bool $handlingHttpCache = \false;
    /**
     * @var array<string, bool>
     */
    private static array $freshCache = [];
    public const VERSION = '6.4.36';
    public const VERSION_ID = 60436;
    public const MAJOR_VERSION = 6;
    public const MINOR_VERSION = 4;
    public const RELEASE_VERSION = 36;
    public const EXTRA_VERSION = '';
    public const END_OF_MAINTENANCE = '11/2026';
    public const END_OF_LIFE = '11/2027';
    public function __construct(string $environment, bool $debug)
    {
        if (!$this->environment = $environment) {
            throw new \InvalidArgumentException(\sprintf('Invalid environment provided to "%s": the environment cannot be empty.', get_debug_type($this)));
        }
        $this->debug = $debug;
    }
    public function __clone()
    {
        $this->booted = \false;
        $this->container = null;
        $this->requestStackSize = 0;
        $this->resetServices = \false;
        $this->handlingHttpCache = \false;
    }
    /**
     * @return void
     */
    public function boot()
    {
        if ($this->booted) {
            if (!$this->requestStackSize && $this->resetServices) {
                if ($this->container->has('services_resetter')) {
                    $this->container->get('services_resetter')->reset();
                }
                $this->resetServices = \false;
                if ($this->debug) {
                    $this->startTime = microtime(\true);
                }
            }
            return;
        }
        if (!$this->container) {
            $this->preBoot();
        }
        foreach ($this->getBundles() as $bundle) {
            $bundle->setContainer($this->container);
            $bundle->boot();
        }
        $this->booted = \true;
    }
    /**
     * @return void
     */
    public function reboot(?string $warmupDir)
    {
        $this->shutdown();
        $this->warmupDir = $warmupDir;
        $this->boot();
    }
    /**
     * @return void
     */
    public function terminate(Request $request, Response $response)
    {
        if (!$this->booted) {
            return;
        }
        if ($this->getHttpKernel() instanceof TerminableInterface) {
            $this->getHttpKernel()->terminate($request, $response);
        }
    }
    /**
     * @return void
     */
    public function shutdown()
    {
        if (!$this->booted) {
            return;
        }
        $this->booted = \false;
        foreach ($this->getBundles() as $bundle) {
            $bundle->shutdown();
            $bundle->setContainer(null);
        }
        $this->container = null;
        $this->requestStackSize = 0;
        $this->resetServices = \false;
    }
    public function handle(Request $request, int $type = HttpKernelInterface::MAIN_REQUEST, bool $catch = \true): Response
    {
        if (!$this->container) {
            $this->preBoot();
        }
        if (HttpKernelInterface::MAIN_REQUEST === $type && !$this->handlingHttpCache && $this->container->has('http_cache')) {
            $this->handlingHttpCache = \true;
            try {
                return $this->container->get('http_cache')->handle($request, $type, $catch);
            } finally {
                $this->handlingHttpCache = \false;
                $this->resetServices = \true;
            }
        }
        $this->boot();
        ++$this->requestStackSize;
        if (!$this->handlingHttpCache) {
            $this->resetServices = \true;
        }
        try {
            return $this->getHttpKernel()->handle($request, $type, $catch);
        } finally {
            --$this->requestStackSize;
        }
    }
    /**
     * Gets an HTTP kernel from the container.
     */
    protected function getHttpKernel(): HttpKernelInterface
    {
        return $this->container->get('http_kernel');
    }
    public function getBundles(): array
    {
        return $this->bundles;
    }
    public function getBundle(string $name): BundleInterface
    {
        if (!isset($this->bundles[$name])) {
            throw new \InvalidArgumentException(\sprintf('Bundle "%s" does not exist or it is not enabled. Maybe you forgot to add it in the "registerBundles()" method of your "%s.php" file?', $name, get_debug_type($this)));
        }
        return $this->bundles[$name];
    }
    public function locateResource(string $name): string
    {
        if ('@' !== $name[0]) {
            throw new \InvalidArgumentException(\sprintf('A resource name must start with @ ("%s" given).', $name));
        }
        if (str_contains($name, '..')) {
            throw new \RuntimeException(\sprintf('File name "%s" contains invalid characters (..).', $name));
        }
        $bundleName = substr($name, 1);
        $path = '';
        if (str_contains($bundleName, '/')) {
            [$bundleName, $path] = explode('/', $bundleName, 2);
        }
        $bundle = $this->getBundle($bundleName);
        if (file_exists($file = $bundle->getPath() . '/' . $path)) {
            return $file;
        }
        throw new \InvalidArgumentException(\sprintf('Unable to find file "%s".', $name));
    }
    public function getEnvironment(): string
    {
        return $this->environment;
    }
    public function isDebug(): bool
    {
        return $this->debug;
    }
    /**
     * Gets the application root dir (path of the project's composer file).
     */
    public function getProjectDir(): string
    {
        if (!isset($this->projectDir)) {
            $r = new \ReflectionObject($this);
            if (!is_file($dir = $r->getFileName())) {
                throw new \LogicException(\sprintf('Cannot auto-detect project dir for kernel of class "%s".', $r->name));
            }
            $dir = $rootDir = \dirname($dir);
            while (!is_file($dir . '/composer.json')) {
                if ($dir === \dirname($dir)) {
                    return $this->projectDir = $rootDir;
                }
                $dir = \dirname($dir);
            }
            $this->projectDir = $dir;
        }
        return $this->projectDir;
    }
    public function getContainer(): ContainerInterface
    {
        if (!$this->container) {
            throw new \LogicException('Cannot retrieve the container from a non-booted kernel.');
        }
        return $this->container;
    }
    /**
     * @internal
     */
    public function setAnnotatedClassCache(array $annotatedClasses): void
    {
        file_put_contents(($this->warmupDir ?: $this->getBuildDir()) . '/annotations.map', \sprintf('<?php return %s;', var_export($annotatedClasses, \true)));
    }
    public function getStartTime(): float
    {
        return $this->debug && null !== $this->startTime ? $this->startTime : -\INF;
    }
    public function getCacheDir(): string
    {
        return $this->getProjectDir() . '/var/cache/' . $this->environment;
    }
    public function getBuildDir(): string
    {
        // Returns $this->getCacheDir() for backward compatibility
        return $this->getCacheDir();
    }
    public function getLogDir(): string
    {
        return $this->getProjectDir() . '/var/log';
    }
    public function getCharset(): string
    {
        return 'UTF-8';
    }
    /**
     * Gets the patterns defining the classes to parse and cache for annotations.
     */
    public function getAnnotatedClassesToCompile(): array
    {
        return [];
    }
    /**
     * Initializes bundles.
     *
     * @return void
     *
     * @throws \LogicException if two bundles share a common name
     */
    protected function initializeBundles()
    {
        // init bundles
        $this->bundles = [];
        foreach ($this->registerBundles() as $bundle) {
            $name = $bundle->getName();
            if (isset($this->bundles[$name])) {
                throw new \LogicException(\sprintf('Trying to register two bundles with the same name "%s".', $name));
            }
            $this->bundles[$name] = $bundle;
        }
    }
    /**
     * The extension point similar to the Bundle::build() method.
     *
     * Use this method to register compiler passes and manipulate the container during the building process.
     *
     * @return void
     */
    protected function build(ContainerBuilder $container)
    {
    }
    /**
     * Gets the container class.
     *
     * @throws \InvalidArgumentException If the generated classname is invalid
     */
    protected function getContainerClass(): string
    {
        $class = static::class;
        $class = str_contains($class, "@anonymous\x00") ? get_parent_class($class) . str_replace('.', '_', ContainerBuilder::hash($class)) : $class;
        $class = str_replace('\\', '_', $class) . ucfirst($this->environment) . ($this->debug ? 'Debug' : '') . 'Container';
        if (!preg_match('/^[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*$/', $class)) {
            throw new \InvalidArgumentException(\sprintf('The environment "%s" contains invalid characters, it can only contain characters allowed in PHP class names.', $this->environment));
        }
        return $class;
    }
    /**
     * Gets the container's base class.
     *
     * All names except Container must be fully qualified.
     */
    protected function getContainerBaseClass(): string
    {
        return 'Container';
    }
    /**
     * Initializes the service container.
     *
     * The built version of the service container is used when fresh, otherwise the
     * container is built.
     *
     * @return void
     */
    protected function initializeContainer()
    {
        $class = $this->getContainerClass();
        $buildDir = $this->warmupDir ?: $this->getBuildDir();
        $cache = new ConfigCache($buildDir.'/'.str_replace('_ContaoManager_', '', $class).'.php', $this->debug);
        $cachePath = $cache->getPath();
        // Silence E_WARNING to ignore "include" failures - don't use "@" to prevent silencing fatal errors
        $errorLevel = error_reporting();
        error_reporting($errorLevel & ~\E_WARNING);
        try {
            if (is_file($cachePath) && \is_object($this->container = include $cachePath) && (!$this->debug || (self::$freshCache[$cachePath] ?? $cache->isFresh()))) {
                self::$freshCache[$cachePath] = \true;
                $this->container->set('kernel', $this);
                error_reporting($errorLevel);
                return;
            }
        } catch (\Throwable $e) {
        }
        $oldContainer = \is_object($this->container) ? new \ReflectionClass($this->container) : $this->container = null;
        try {
            is_dir($buildDir) ?: mkdir($buildDir, 0777, \true);
            if ($lock = fopen($cachePath . '.lock', 'w+')) {
                if (!flock($lock, \LOCK_EX | \LOCK_NB, $wouldBlock) && !flock($lock, $wouldBlock ? \LOCK_SH : \LOCK_EX)) {
                    fclose($lock);
                    $lock = null;
                } elseif (!is_file($cachePath) || !\is_object($this->container = include $cachePath)) {
                    $this->container = null;
                } elseif (!$oldContainer || $this->container::class !== $oldContainer->name) {
                    flock($lock, \LOCK_UN);
                    fclose($lock);
                    $this->container->set('kernel', $this);
                    return;
                }
            }
        } catch (\Throwable $e) {
        } finally {
            error_reporting($errorLevel);
        }
        if ($collectDeprecations = $this->debug && !\defined('PHPUNIT_COMPOSER_INSTALL')) {
            $collectedLogs = [];
            $previousHandler = set_error_handler(function ($type, $message, $file, $line) use (&$collectedLogs, &$previousHandler) {
                if (\E_USER_DEPRECATED !== $type && \E_DEPRECATED !== $type) {
                    return $previousHandler ? $previousHandler($type, $message, $file, $line) : \false;
                }
                if (isset($collectedLogs[$message])) {
                    ++$collectedLogs[$message]['count'];
                    return null;
                }
                $backtrace = debug_backtrace(\DEBUG_BACKTRACE_IGNORE_ARGS, 5);
                // Clean the trace by removing first frames added by the error handler itself.
                for ($i = 0; isset($backtrace[$i]); ++$i) {
                    if (isset($backtrace[$i]['file'], $backtrace[$i]['line']) && $backtrace[$i]['line'] === $line && $backtrace[$i]['file'] === $file) {
                        $backtrace = \array_slice($backtrace, 1 + $i);
                        break;
                    }
                }
                for ($i = 0; isset($backtrace[$i]); ++$i) {
                    if (!isset($backtrace[$i]['file'], $backtrace[$i]['line'], $backtrace[$i]['function'])) {
                        continue;
                    }
                    if (!isset($backtrace[$i]['class']) && 'trigger_deprecation' === $backtrace[$i]['function']) {
                        $file = $backtrace[$i]['file'];
                        $line = $backtrace[$i]['line'];
                        $backtrace = \array_slice($backtrace, 1 + $i);
                        break;
                    }
                }
                // Remove frames added by DebugClassLoader.
                for ($i = \count($backtrace) - 2; 0 < $i; --$i) {
                    if (DebugClassLoader::class === ($backtrace[$i]['class'] ?? null)) {
                        $backtrace = [$backtrace[$i + 1]];
                        break;
                    }
                }
                $collectedLogs[$message] = ['type' => $type, 'message' => $message, 'file' => $file, 'line' => $line, 'trace' => [$backtrace[0]], 'count' => 1];
                return null;
            });
        }
        try {
            $container = null;
            $container = $this->buildContainer();
            $container->compile();
        } finally {
            if ($collectDeprecations) {
                restore_error_handler();
                @file_put_contents($buildDir . '/' . $class . 'Deprecations.log', serialize(array_values($collectedLogs)));
                @file_put_contents($buildDir . '/' . $class . 'Compiler.log', null !== $container ? implode("\n", $container->getCompiler()->getLog()) : '');
            }
        }
        $this->dumpContainer($cache, $container, $class, $this->getContainerBaseClass());
        if ($lock) {
            flock($lock, \LOCK_UN);
            fclose($lock);
        }
        $this->container = require $cachePath;
        $this->container->set('kernel', $this);
        if ($oldContainer && $this->container::class !== $oldContainer->name) {
            // Because concurrent requests might still be using them,
            // old container files are not removed immediately,
            // but on a next dump of the container.
            static $legacyContainers = [];
            $oldContainerDir = \dirname($oldContainer->getFileName());
            $legacyContainers[$oldContainerDir . '.legacy'] = \true;
            foreach (glob(\dirname($oldContainerDir) . \DIRECTORY_SEPARATOR . '*.legacy', \GLOB_NOSORT) as $legacyContainer) {
                if (!isset($legacyContainers[$legacyContainer]) && @unlink($legacyContainer)) {
                    (new Filesystem())->remove(substr($legacyContainer, 0, -7));
                }
            }
            touch($oldContainerDir . '.legacy');
        }
        $buildDir = $this->container->getParameter('kernel.build_dir');
        $cacheDir = $this->container->getParameter('kernel.cache_dir');
        $preload = $this instanceof WarmableInterface ? (array) $this->warmUp($cacheDir, $buildDir) : [];
        if ($this->container->has('cache_warmer')) {
            $cacheWarmer = $this->container->get('cache_warmer');
            if ($cacheDir !== $buildDir) {
                $cacheWarmer->enableOptionalWarmers();
            }
            $preload = array_merge($preload, (array) $cacheWarmer->warmUp($cacheDir, $buildDir));
        }
        if ($preload && file_exists($preloadFile = $buildDir . '/' . $class . '.preload.php')) {
            Preloader::append($preloadFile, $preload);
        }
    }
    /**
     * Returns the kernel parameters.
     */
    protected function getKernelParameters(): array
    {
        $bundles = [];
        $bundlesMetadata = [];
        foreach ($this->bundles as $name => $bundle) {
            $bundles[$name] = $bundle::class;
            $bundlesMetadata[$name] = ['path' => $bundle->getPath(), 'namespace' => $bundle->getNamespace()];
        }
        return ['kernel.project_dir' => realpath($this->getProjectDir()) ?: $this->getProjectDir(), 'kernel.environment' => $this->environment, 'kernel.runtime_environment' => '%env(default:kernel.environment:APP_RUNTIME_ENV)%', 'kernel.runtime_mode' => '%env(query_string:default:container.runtime_mode:APP_RUNTIME_MODE)%', 'kernel.runtime_mode.web' => '%env(bool:default::key:web:default:kernel.runtime_mode:)%', 'kernel.runtime_mode.cli' => '%env(not:default:kernel.runtime_mode.web:)%', 'kernel.runtime_mode.worker' => '%env(bool:default::key:worker:default:kernel.runtime_mode:)%', 'kernel.debug' => $this->debug, 'kernel.build_dir' => realpath($buildDir = $this->warmupDir ?: $this->getBuildDir()) ?: $buildDir, 'kernel.cache_dir' => realpath($cacheDir = $this->getCacheDir() === $this->getBuildDir() ? $this->warmupDir ?: $this->getCacheDir() : $this->getCacheDir()) ?: $cacheDir, 'kernel.logs_dir' => realpath($this->getLogDir()) ?: $this->getLogDir(), 'kernel.bundles' => $bundles, 'kernel.bundles_metadata' => $bundlesMetadata, 'kernel.charset' => $this->getCharset(), 'kernel.container_class' => $this->getContainerClass()];
    }
    /**
     * Builds the service container.
     *
     * @throws \RuntimeException
     */
    protected function buildContainer(): ContainerBuilder
    {
        foreach (['cache' => $this->getCacheDir(), 'build' => $this->warmupDir ?: $this->getBuildDir(), 'logs' => $this->getLogDir()] as $name => $dir) {
            if (!is_dir($dir)) {
                if (!@mkdir($dir, 0777, \true) && !is_dir($dir)) {
                    throw new \RuntimeException(\sprintf('Unable to create the "%s" directory (%s).', $name, $dir));
                }
            } elseif (!is_writable($dir)) {
                throw new \RuntimeException(\sprintf('Unable to write in the "%s" directory (%s).', $name, $dir));
            }
        }
        $container = $this->getContainerBuilder();
        $container->addObjectResource($this);
        $this->prepareContainer($container);
        $this->registerContainerConfiguration($this->getContainerLoader($container));
        $container->addCompilerPass(new AddAnnotatedClassesToCachePass($this));
        return $container;
    }
    /**
     * Prepares the ContainerBuilder before it is compiled.
     *
     * @return void
     */
    protected function prepareContainer(ContainerBuilder $container)
    {
        $extensions = [];
        foreach ($this->bundles as $bundle) {
            if ($extension = $bundle->getContainerExtension()) {
                $container->registerExtension($extension);
            }
            if ($this->debug) {
                $container->addObjectResource($bundle);
            }
        }
        foreach ($this->bundles as $bundle) {
            $bundle->build($container);
        }
        $this->build($container);
        foreach ($container->getExtensions() as $extension) {
            $extensions[] = $extension->getAlias();
        }
        // ensure these extensions are implicitly loaded
        $container->getCompilerPassConfig()->setMergePass(new MergeExtensionConfigurationPass($extensions));
    }
    /**
     * Gets a new ContainerBuilder instance used to build the service container.
     */
    protected function getContainerBuilder(): ContainerBuilder
    {
        $container = new ContainerBuilder();
        $container->getParameterBag()->add($this->getKernelParameters());
        if ($this instanceof ExtensionInterface) {
            $container->registerExtension($this);
        }
        if ($this instanceof CompilerPassInterface) {
            $container->addCompilerPass($this, PassConfig::TYPE_BEFORE_OPTIMIZATION, -10000);
        }
        return $container;
    }
    /**
     * Dumps the service container to PHP code in the cache.
     *
     * @param string $class     The name of the class to generate
     * @param string $baseClass The name of the container's base class
     *
     * @return void
     */
    protected function dumpContainer(ConfigCache $cache, ContainerBuilder $container, string $class, string $baseClass)
    {
        // cache the container
        $dumper = new PhpDumper($container);
        $buildParameters = [];
        foreach ($container->getCompilerPassConfig()->getPasses() as $pass) {
            if ($pass instanceof RemoveBuildParametersPass) {
                $buildParameters = array_merge($buildParameters, $pass->getRemovedParameters());
            }
        }
        $inlineFactories = \false;
        if (isset($buildParameters['.container.dumper.inline_factories'])) {
            $inlineFactories = $buildParameters['.container.dumper.inline_factories'];
        } elseif ($container->hasParameter('container.dumper.inline_factories')) {
            trigger_deprecation('symfony/http-kernel', '6.3', 'Parameter "%s" is deprecated, use ".%1$s" instead.', 'container.dumper.inline_factories');
            $inlineFactories = $container->getParameter('container.dumper.inline_factories');
        }
        $inlineClassLoader = $this->debug;
        if (isset($buildParameters['.container.dumper.inline_class_loader'])) {
            $inlineClassLoader = $buildParameters['.container.dumper.inline_class_loader'];
        } elseif ($container->hasParameter('container.dumper.inline_class_loader')) {
            trigger_deprecation('symfony/http-kernel', '6.3', 'Parameter "%s" is deprecated, use ".%1$s" instead.', 'container.dumper.inline_class_loader');
            $inlineClassLoader = $container->getParameter('container.dumper.inline_class_loader');
        }
        $content = $dumper->dump(['class' => $class, 'base_class' => $baseClass, 'file' => $cache->getPath(), 'as_files' => \true, 'debug' => $this->debug, 'inline_factories' => $inlineFactories, 'inline_class_loader' => $inlineClassLoader, 'build_time' => $container->hasParameter('kernel.container_build_time') ? $container->getParameter('kernel.container_build_time') : time(), 'preload_classes' => array_map('get_class', $this->bundles)]);
        $rootCode = array_pop($content);
        $dir = \dirname($cache->getPath()) . '/';
        $fs = new Filesystem();
        foreach ($content as $file => $code) {
            $fs->dumpFile($dir . $file, $code);
            @chmod($dir . $file, 0666 & ~umask());
        }
        $legacyFile = \dirname($dir . key($content)) . '.legacy';
        if (is_file($legacyFile)) {
            @unlink($legacyFile);
        }
        $cache->write($rootCode, $container->getResources());
    }
    /**
     * Returns a loader for the container.
     */
    protected function getContainerLoader(ContainerInterface $container): DelegatingLoader
    {
        $env = $this->getEnvironment();
        $locator = new FileLocator($this);
        $resolver = new LoaderResolver([new XmlFileLoader($container, $locator, $env), new YamlFileLoader($container, $locator, $env), new IniFileLoader($container, $locator, $env), new PhpFileLoader($container, $locator, $env, class_exists(ConfigBuilderGenerator::class) ? new ConfigBuilderGenerator($this->getBuildDir()) : null), new GlobFileLoader($container, $locator, $env), new DirectoryLoader($container, $locator, $env), new ClosureLoader($container, $env)]);
        return new DelegatingLoader($resolver);
    }
    private function preBoot(): ContainerInterface
    {
        if ($this->debug) {
            $this->startTime = microtime(\true);
        }
        if ($this->debug && !isset($_ENV['SHELL_VERBOSITY']) && !isset($_SERVER['SHELL_VERBOSITY'])) {
            if (\function_exists('putenv')) {
                putenv('SHELL_VERBOSITY=3');
            }
            $_ENV['SHELL_VERBOSITY'] = 3;
            $_SERVER['SHELL_VERBOSITY'] = 3;
        }
        $this->initializeBundles();
        $this->initializeContainer();
        $container = $this->container;
        if ($container->hasParameter('kernel.trusted_hosts') && $trustedHosts = $container->getParameter('kernel.trusted_hosts')) {
            Request::setTrustedHosts($trustedHosts);
        }
        if ($container->hasParameter('kernel.trusted_proxies') && $container->hasParameter('kernel.trusted_headers') && $trustedProxies = $container->getParameter('kernel.trusted_proxies')) {
            Request::setTrustedProxies(\is_array($trustedProxies) ? $trustedProxies : array_map('trim', explode(',', $trustedProxies)), $container->getParameter('kernel.trusted_headers'));
        }
        return $container;
    }
    /**
     * Removes comments from a PHP source string.
     *
     * We don't use the PHP php_strip_whitespace() function
     * as we want the content to be readable and well-formatted.
     *
     * @deprecated since Symfony 6.4 without replacement
     */
    public static function stripComments(string $source): string
    {
        trigger_deprecation('symfony/http-kernel', '6.4', 'Method "%s()" is deprecated without replacement.', __METHOD__);
        if (!\function_exists('token_get_all') && !\function_exists('_ContaoManager\token_get_all')) {
            return $source;
        }
        $rawChunk = '';
        $output = '';
        $tokens = token_get_all($source);
        $ignoreSpace = \false;
        for ($i = 0; isset($tokens[$i]); ++$i) {
            $token = $tokens[$i];
            if (!isset($token[1]) || 'b"' === $token) {
                $rawChunk .= $token;
            } elseif (\T_START_HEREDOC === $token[0]) {
                $output .= $rawChunk . $token[1];
                do {
                    $token = $tokens[++$i];
                    $output .= isset($token[1]) && 'b"' !== $token ? $token[1] : $token;
                } while (\T_END_HEREDOC !== $token[0]);
                $rawChunk = '';
            } elseif (\T_WHITESPACE === $token[0]) {
                if ($ignoreSpace) {
                    $ignoreSpace = \false;
                    continue;
                }
                // replace multiple new lines with a single newline
                $rawChunk .= preg_replace(['/\n{2,}/S'], "\n", $token[1]);
            } elseif (\in_array($token[0], [\T_COMMENT, \T_DOC_COMMENT])) {
                if (!\in_array($rawChunk[\strlen($rawChunk) - 1], [' ', "\n", "\r", "\t"], \true)) {
                    $rawChunk .= ' ';
                }
                $ignoreSpace = \true;
            } else {
                $rawChunk .= $token[1];
                // The PHP-open tag already has a new-line
                if (\T_OPEN_TAG === $token[0]) {
                    $ignoreSpace = \true;
                } else {
                    $ignoreSpace = \false;
                }
            }
        }
        $output .= $rawChunk;
        unset($tokens, $rawChunk);
        gc_mem_caches();
        return $output;
    }
    public function __sleep(): array
    {
        return ['environment', 'debug'];
    }
    /**
     * @return void
     */
    public function __wakeup()
    {
        if (\is_object($this->environment) || \is_object($this->debug)) {
            throw new \BadMethodCallException('Cannot unserialize ' . __CLASS__);
        }
        $this->__construct($this->environment, $this->debug);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\HttpKernel;

use _ContaoManager\Symfony\Component\HttpFoundation\UriSigner as HttpFoundationUriSigner;
trigger_deprecation('symfony/http-kernel', '6.4', 'The "%s" class is deprecated, use "%s" instead.', UriSigner::class, HttpFoundationUriSigner::class);
class_exists(HttpFoundationUriSigner::class);
if (\false) {
    /**
     * @deprecated since Symfony 6.4, to be removed in 7.0, use {@link HttpFoundationUriSigner} instead
     */
    class UriSigner extends HttpFoundationUriSigner
    {
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\HttpKernel\Debug;

use _ContaoManager\Symfony\Component\HttpFoundation\Request;
use _ContaoManager\Symfony\Component\HttpFoundation\RequestStack;
/**
 * A stack able to deal with virtual requests.
 *
 * @internal
 *
 * @author Jules Pietri <jules@heahprod.com>
 */
final class VirtualRequestStack extends RequestStack
{
    public function __construct(private readonly RequestStack $decorated)
    {
    }
    public function push(Request $request): void
    {
        if ($request->attributes->has('_virtual_type')) {
            if ($this->decorated->getCurrentRequest()) {
                throw new \LogicException('Cannot mix virtual and HTTP requests.');
            }
            parent::push($request);
            return;
        }
        $this->decorated->push($request);
    }
    public function pop(): ?Request
    {
        return $this->decorated->pop() ?? parent::pop();
    }
    public function getCurrentRequest(): ?Request
    {
        return $this->decorated->getCurrentRequest() ?? parent::getCurrentRequest();
    }
    public function getMainRequest(): ?Request
    {
        return $this->decorated->getMainRequest() ?? parent::getMainRequest();
    }
    public function getParentRequest(): ?Request
    {
        return $this->decorated->getParentRequest() ?? parent::getParentRequest();
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\HttpKernel\Debug;

use _ContaoManager\Psr\Log\LoggerInterface;
use _ContaoManager\Symfony\Component\ErrorHandler\ErrorHandler;
/**
 * Configures the error handler.
 *
 * @final
 *
 * @internal
 */
class ErrorHandlerConfigurator
{
    private ?LoggerInterface $logger;
    private ?LoggerInterface $deprecationLogger;
    private array|int|null $levels;
    private ?int $throwAt;
    private bool $scream;
    private bool $scope;
    /**
     * @param array|int|null $levels  An array map of E_* to LogLevel::* or an integer bit field of E_* constants
     * @param int|null       $throwAt Thrown errors in a bit field of E_* constants, or null to keep the current value
     * @param bool           $scream  Enables/disables screaming mode, where even silenced errors are logged
     * @param bool           $scope   Enables/disables scoping mode
     */
    public function __construct(?LoggerInterface $logger = null, array|int|null $levels = \E_ALL, ?int $throwAt = \E_ALL, bool $scream = \true, bool $scope = \true, ?LoggerInterface $deprecationLogger = null)
    {
        $this->logger = $logger;
        $this->levels = $levels ?? \E_ALL;
        $this->throwAt = \is_int($throwAt) ? $throwAt : (null === $throwAt ? null : ($throwAt ? \E_ALL : null));
        $this->scream = $scream;
        $this->scope = $scope;
        $this->deprecationLogger = $deprecationLogger;
    }
    /**
     * Configures the error handler.
     */
    public function configure(ErrorHandler $handler): void
    {
        if ($this->logger || $this->deprecationLogger) {
            $this->setDefaultLoggers($handler);
            if (\is_array($this->levels)) {
                $levels = 0;
                foreach ($this->levels as $type => $log) {
                    $levels |= $type;
                }
            } else {
                $levels = $this->levels;
            }
            if ($this->scream) {
                $handler->screamAt($levels);
            }
            if ($this->scope) {
                $handler->scopeAt($levels & ~\E_USER_DEPRECATED & ~\E_DEPRECATED);
            } else {
                $handler->scopeAt(0, \true);
            }
            $this->logger = $this->deprecationLogger = $this->levels = null;
        }
        if (null !== $this->throwAt) {
            $handler->throwAt($this->throwAt, \true);
        }
    }
    private function setDefaultLoggers(ErrorHandler $handler): void
    {
        if (\is_array($this->levels)) {
            $levelsDeprecatedOnly = [];
            $levelsWithoutDeprecated = [];
            foreach ($this->levels as $type => $log) {
                if (\E_DEPRECATED == $type || \E_USER_DEPRECATED == $type) {
                    $levelsDeprecatedOnly[$type] = $log;
                } else {
                    $levelsWithoutDeprecated[$type] = $log;
                }
            }
        } else {
            $levelsDeprecatedOnly = $this->levels & (\E_DEPRECATED | \E_USER_DEPRECATED);
            $levelsWithoutDeprecated = $this->levels & ~\E_DEPRECATED & ~\E_USER_DEPRECATED;
        }
        $defaultLoggerLevels = $this->levels;
        if ($this->deprecationLogger && $levelsDeprecatedOnly) {
            $handler->setDefaultLogger($this->deprecationLogger, $levelsDeprecatedOnly);
            $defaultLoggerLevels = $levelsWithoutDeprecated;
        }
        if ($this->logger && $defaultLoggerLevels) {
            $handler->setDefaultLogger($this->logger, $defaultLoggerLevels);
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\HttpKernel\Debug;

use _ContaoManager\Symfony\Component\EventDispatcher\Debug\TraceableEventDispatcher as BaseTraceableEventDispatcher;
use _ContaoManager\Symfony\Component\HttpKernel\KernelEvents;
/**
 * Collects some data about event listeners.
 *
 * This event dispatcher delegates the dispatching to another one.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class TraceableEventDispatcher extends BaseTraceableEventDispatcher
{
    protected function beforeDispatch(string $eventName, object $event): void
    {
        switch ($eventName) {
            case KernelEvents::REQUEST:
                $event->getRequest()->attributes->set('_stopwatch_token', substr(hash('sha256', uniqid(mt_rand(), \true)), 0, 6));
                $this->stopwatch->openSection();
                break;
            case KernelEvents::VIEW:
            case KernelEvents::RESPONSE:
                // stop only if a controller has been executed
                if ($this->stopwatch->isStarted('controller')) {
                    $this->stopwatch->stop('controller');
                }
                break;
            case KernelEvents::TERMINATE:
                $sectionId = $event->getRequest()->attributes->get('_stopwatch_token');
                if (null === $sectionId) {
                    break;
                }
                // There is a very special case when using built-in AppCache class as kernel wrapper, in the case
                // of an ESI request leading to a `stale` response [B]  inside a `fresh` cached response [A].
                // In this case, `$token` contains the [B] debug token, but the  open `stopwatch` section ID
                // is equal to the [A] debug token. Trying to reopen section with the [B] token throws an exception
                // which must be caught.
                try {
                    $this->stopwatch->openSection($sectionId);
                } catch (\LogicException) {
                }
                break;
        }
    }
    protected function afterDispatch(string $eventName, object $event): void
    {
        switch ($eventName) {
            case KernelEvents::CONTROLLER_ARGUMENTS:
                $this->stopwatch->start('controller', 'section');
                break;
            case KernelEvents::RESPONSE:
                $sectionId = $event->getRequest()->attributes->get('_stopwatch_token');
                if (null === $sectionId) {
                    break;
                }
                try {
                    $this->stopwatch->stopSection($sectionId);
                } catch (\LogicException) {
                    // The stop watch service might have been reset in the meantime
                }
                break;
            case KernelEvents::TERMINATE:
                // In the special case described in the `preDispatch` method above, the `$token` section
                // does not exist, then closing it throws an exception which must be caught.
                $sectionId = $event->getRequest()->attributes->get('_stopwatch_token');
                if (null === $sectionId) {
                    break;
                }
                try {
                    $this->stopwatch->stopSection($sectionId);
                } catch (\LogicException) {
                }
                break;
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\HttpKernel\Debug;

use _ContaoManager\Symfony\Component\ErrorHandler\ErrorRenderer\FileLinkFormatter as ErrorHandlerFileLinkFormatter;
trigger_deprecation('symfony/http-kernel', '6.4', 'The "%s" class is deprecated, use "%s" instead.', FileLinkFormatter::class, ErrorHandlerFileLinkFormatter::class);
class_exists(ErrorHandlerFileLinkFormatter::class);
if (!class_exists(FileLinkFormatter::class, \false)) {
    class_alias(ErrorHandlerFileLinkFormatter::class, FileLinkFormatter::class);
}
if (\false) {
    /**
     * @deprecated since Symfony 6.4, use FileLinkFormatter from the ErrorHandler component instead
     */
    class FileLinkFormatter extends ErrorHandlerFileLinkFormatter
    {
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\HttpKernel;

use _ContaoManager\Symfony\Component\BrowserKit\AbstractBrowser;
use _ContaoManager\Symfony\Component\BrowserKit\CookieJar;
use _ContaoManager\Symfony\Component\BrowserKit\History;
use _ContaoManager\Symfony\Component\BrowserKit\Request as DomRequest;
use _ContaoManager\Symfony\Component\BrowserKit\Response as DomResponse;
use _ContaoManager\Symfony\Component\HttpFoundation\File\UploadedFile;
use _ContaoManager\Symfony\Component\HttpFoundation\Request;
use _ContaoManager\Symfony\Component\HttpFoundation\Response;
/**
 * Simulates a browser and makes requests to an HttpKernel instance.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 *
 * @method Request  getRequest()
 * @method Response getResponse()
 */
class HttpKernelBrowser extends AbstractBrowser
{
    protected $kernel;
    private bool $catchExceptions = \true;
    /**
     * @param array $server The server parameters (equivalent of $_SERVER)
     */
    public function __construct(HttpKernelInterface $kernel, array $server = [], ?History $history = null, ?CookieJar $cookieJar = null)
    {
        // These class properties must be set before calling the parent constructor, as it may depend on it.
        $this->kernel = $kernel;
        $this->followRedirects = \false;
        parent::__construct($server, $history, $cookieJar);
    }
    /**
     * Sets whether to catch exceptions when the kernel is handling a request.
     *
     * @return void
     */
    public function catchExceptions(bool $catchExceptions)
    {
        $this->catchExceptions = $catchExceptions;
    }
    /**
     * @param Request $request
     *
     * @return Response
     */
    protected function doRequest(object $request)
    {
        $response = $this->kernel->handle($request, HttpKernelInterface::MAIN_REQUEST, $this->catchExceptions);
        if ($this->kernel instanceof TerminableInterface) {
            $this->kernel->terminate($request, $response);
        }
        return $response;
    }
    /**
     * @param Request $request
     *
     * @return string
     */
    protected function getScript(object $request)
    {
        $kernel = var_export(serialize($this->kernel), \true);
        $request = var_export(serialize($request), \true);
        $errorReporting = error_reporting();
        $requires = '';
        foreach (get_declared_classes() as $class) {
            if (str_starts_with($class, 'ComposerAutoloaderInit')) {
                $r = new \ReflectionClass($class);
                $file = \dirname($r->getFileName(), 2) . '/autoload.php';
                if (file_exists($file)) {
                    $requires .= 'require_once ' . var_export($file, \true) . ";\n";
                }
            }
        }
        if (!$requires) {
            throw new \RuntimeException('Composer autoloader not found.');
        }
        $code = <<<EOF
<?php

error_reporting({$errorReporting});

{$requires}

\$kernel = unserialize({$kernel});
\$request = unserialize({$request});
EOF;
        return $code . $this->getHandleScript();
    }
    /**
     * @return string
     */
    protected function getHandleScript()
    {
        return <<<'EOF'
$response = $kernel->handle($request);

if ($kernel instanceof Symfony\Component\HttpKernel\TerminableInterface) {
    $kernel->terminate($request, $response);
}

echo serialize($response);
EOF;
    }
    protected function filterRequest(DomRequest $request): Request
    {
        $httpRequest = Request::create($request->getUri(), $request->getMethod(), $request->getParameters(), $request->getCookies(), $request->getFiles(), $server = $request->getServer(), $request->getContent());
        if (!isset($server['HTTP_ACCEPT'])) {
            $httpRequest->headers->remove('Accept');
        }
        foreach ($this->filterFiles($httpRequest->files->all()) as $key => $value) {
            $httpRequest->files->set($key, $value);
        }
        return $httpRequest;
    }
    /**
     * Filters an array of files.
     *
     * This method created test instances of UploadedFile so that the move()
     * method can be called on those instances.
     *
     * If the size of a file is greater than the allowed size (from php.ini) then
     * an invalid UploadedFile is returned with an error set to UPLOAD_ERR_INI_SIZE.
     *
     * @see UploadedFile
     */
    protected function filterFiles(array $files): array
    {
        $filtered = [];
        foreach ($files as $key => $value) {
            if (\is_array($value)) {
                $filtered[$key] = $this->filterFiles($value);
            } elseif ($value instanceof UploadedFile) {
                if ($value->isValid() && $value->getSize() > UploadedFile::getMaxFilesize()) {
                    $filtered[$key] = new UploadedFile('', $value->getClientOriginalName(), $value->getClientMimeType(), \UPLOAD_ERR_INI_SIZE, \true);
                } else {
                    $filtered[$key] = new UploadedFile($value->getPathname(), $value->getClientOriginalName(), $value->getClientMimeType(), $value->getError(), \true);
                }
            }
        }
        return $filtered;
    }
    /**
     * @param Response $response
     */
    protected function filterResponse(object $response): DomResponse
    {
        // this is needed to support StreamedResponse
        ob_start();
        $response->sendContent();
        $content = ob_get_clean();
        return new DomResponse($content, $response->getStatusCode(), $response->headers->all());
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\HttpKernel\EventListener;

use _ContaoManager\Symfony\Component\EventDispatcher\EventSubscriberInterface;
use _ContaoManager\Symfony\Component\HttpFoundation\StreamedResponse;
use _ContaoManager\Symfony\Component\HttpKernel\Event\ResponseEvent;
use _ContaoManager\Symfony\Component\HttpKernel\KernelEvents;
trigger_deprecation('symfony/http-kernel', '6.1', 'The "%s" class is deprecated.', StreamedResponseListener::class);
/**
 * StreamedResponseListener is responsible for sending the Response
 * to the client.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 *
 * @final
 *
 * @deprecated since Symfony 6.1
 */
class StreamedResponseListener implements EventSubscriberInterface
{
    /**
     * Filters the Response.
     */
    public function onKernelResponse(ResponseEvent $event): void
    {
        if (!$event->isMainRequest()) {
            return;
        }
        $response = $event->getResponse();
        if ($response instanceof StreamedResponse) {
            $response->send();
        }
    }
    public static function getSubscribedEvents(): array
    {
        return [KernelEvents::RESPONSE => ['onKernelResponse', -1024]];
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\HttpKernel\EventListener;

use _ContaoManager\Symfony\Component\EventDispatcher\EventSubscriberInterface;
use _ContaoManager\Symfony\Component\HttpKernel\Event\ResponseEvent;
use _ContaoManager\Symfony\Component\HttpKernel\KernelEvents;
/**
 * ResponseListener fixes the Response headers based on the Request.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 *
 * @final
 */
class ResponseListener implements EventSubscriberInterface
{
    private string $charset;
    private bool $addContentLanguageHeader;
    public function __construct(string $charset, bool $addContentLanguageHeader = \false)
    {
        $this->charset = $charset;
        $this->addContentLanguageHeader = $addContentLanguageHeader;
    }
    /**
     * Filters the Response.
     */
    public function onKernelResponse(ResponseEvent $event): void
    {
        if (!$event->isMainRequest()) {
            return;
        }
        $response = $event->getResponse();
        if (null === $response->getCharset()) {
            $response->setCharset($this->charset);
        }
        if ($this->addContentLanguageHeader && !$response->isInformational() && !$response->isEmpty() && !$response->headers->has('Content-Language')) {
            $response->headers->set('Content-Language', $event->getRequest()->getLocale());
        }
        if ($event->getRequest()->attributes->get('_vary_by_language')) {
            $response->setVary('Accept-Language', \false);
        }
        $response->prepare($event->getRequest());
    }
    public static function getSubscribedEvents(): array
    {
        return [KernelEvents::RESPONSE => 'onKernelResponse'];
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\HttpKernel\EventListener;

use _ContaoManager\Symfony\Component\EventDispatcher\EventSubscriberInterface;
use _ContaoManager\Symfony\Component\HttpFoundation\Request;
use _ContaoManager\Symfony\Component\HttpFoundation\RequestStack;
use _ContaoManager\Symfony\Component\HttpKernel\Event\FinishRequestEvent;
use _ContaoManager\Symfony\Component\HttpKernel\Event\KernelEvent;
use _ContaoManager\Symfony\Component\HttpKernel\Event\RequestEvent;
use _ContaoManager\Symfony\Component\HttpKernel\KernelEvents;
use _ContaoManager\Symfony\Component\Routing\RequestContextAwareInterface;
/**
 * Initializes the locale based on the current request.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 *
 * @final
 */
class LocaleListener implements EventSubscriberInterface
{
    private ?RequestContextAwareInterface $router;
    private string $defaultLocale;
    private RequestStack $requestStack;
    private bool $useAcceptLanguageHeader;
    private array $enabledLocales;
    public function __construct(RequestStack $requestStack, string $defaultLocale = 'en', ?RequestContextAwareInterface $router = null, bool $useAcceptLanguageHeader = \false, array $enabledLocales = [])
    {
        $this->defaultLocale = $defaultLocale;
        $this->requestStack = $requestStack;
        $this->router = $router;
        $this->useAcceptLanguageHeader = $useAcceptLanguageHeader;
        $this->enabledLocales = $enabledLocales ? array_values(array_unique(array_merge([$defaultLocale], $enabledLocales))) : [];
    }
    public function setDefaultLocale(KernelEvent $event): void
    {
        $event->getRequest()->setDefaultLocale($this->defaultLocale);
        $this->setRouterLocale($this->defaultLocale);
    }
    public function onKernelRequest(RequestEvent $event): void
    {
        $request = $event->getRequest();
        $this->setLocale($request);
        $this->setRouterLocale($request->getLocale());
    }
    public function onKernelFinishRequest(FinishRequestEvent $event): void
    {
        $this->setRouterLocale($this->requestStack->getParentRequest()?->getLocale() ?? $this->defaultLocale);
    }
    private function setLocale(Request $request): void
    {
        if ($locale = $request->attributes->get('_locale')) {
            $request->setLocale($locale);
        } elseif ($this->useAcceptLanguageHeader) {
            if ($request->getLanguages() && $preferredLanguage = $request->getPreferredLanguage($this->enabledLocales)) {
                $request->setLocale($preferredLanguage);
            }
            $request->attributes->set('_vary_by_language', \true);
        }
    }
    private function setRouterLocale(string $locale): void
    {
        $this->router?->getContext()->setParameter('_locale', $locale);
    }
    public static function getSubscribedEvents(): array
    {
        return [KernelEvents::REQUEST => [
            ['setDefaultLocale', 100],
            // must be registered after the Router to have access to the _locale
            ['onKernelRequest', 16],
        ], KernelEvents::FINISH_REQUEST => [['onKernelFinishRequest', 0]]];
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\HttpKernel\EventListener;

use _ContaoManager\Symfony\Component\EventDispatcher\EventSubscriberInterface;
use _ContaoManager\Symfony\Component\HttpFoundation\Request;
use _ContaoManager\Symfony\Component\HttpFoundation\UriSigner;
use _ContaoManager\Symfony\Component\HttpKernel\Event\RequestEvent;
use _ContaoManager\Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;
use _ContaoManager\Symfony\Component\HttpKernel\KernelEvents;
/**
 * Handles content fragments represented by special URIs.
 *
 * All URL paths starting with /_fragment are handled as
 * content fragments by this listener.
 *
 * Throws an AccessDeniedHttpException exception if the request
 * is not signed or if it is not an internal sub-request.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 *
 * @final
 */
class FragmentListener implements EventSubscriberInterface
{
    private UriSigner $signer;
    private string $fragmentPath;
    /**
     * @param string $fragmentPath The path that triggers this listener
     */
    public function __construct(UriSigner $signer, string $fragmentPath = '/_fragment')
    {
        $this->signer = $signer;
        $this->fragmentPath = $fragmentPath;
    }
    /**
     * Fixes request attributes when the path is '/_fragment'.
     *
     * @throws AccessDeniedHttpException if the request does not come from a trusted IP
     */
    public function onKernelRequest(RequestEvent $event): void
    {
        $request = $event->getRequest();
        if ($this->fragmentPath !== rawurldecode($request->getPathInfo())) {
            return;
        }
        if ($request->attributes->has('_controller')) {
            // Is a sub-request: no need to parse _path but it should still be removed from query parameters as below.
            $request->query->remove('_path');
            return;
        }
        if ($event->isMainRequest()) {
            $this->validateRequest($request);
        }
        parse_str($request->query->get('_path', ''), $attributes);
        $attributes['_check_controller_is_allowed'] = -1;
        // @deprecated, switch to true in Symfony 7
        $request->attributes->add($attributes);
        $request->attributes->set('_route_params', array_replace($request->attributes->get('_route_params', []), $attributes));
        $request->query->remove('_path');
    }
    protected function validateRequest(Request $request): void
    {
        // is the Request safe?
        if (!$request->isMethodSafe()) {
            throw new AccessDeniedHttpException();
        }
        // is the Request signed?
        if ($this->signer->checkRequest($request)) {
            return;
        }
        throw new AccessDeniedHttpException();
    }
    public static function getSubscribedEvents(): array
    {
        return [KernelEvents::REQUEST => [['onKernelRequest', 48]]];
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\HttpKernel\EventListener;

use _ContaoManager\Symfony\Component\EventDispatcher\EventSubscriberInterface;
use _ContaoManager\Symfony\Component\ExpressionLanguage\ExpressionLanguage;
use _ContaoManager\Symfony\Component\HttpFoundation\HeaderBag;
use _ContaoManager\Symfony\Component\HttpFoundation\Request;
use _ContaoManager\Symfony\Component\HttpFoundation\Response;
use _ContaoManager\Symfony\Component\HttpKernel\Attribute\Cache;
use _ContaoManager\Symfony\Component\HttpKernel\Event\ControllerArgumentsEvent;
use _ContaoManager\Symfony\Component\HttpKernel\Event\ResponseEvent;
use _ContaoManager\Symfony\Component\HttpKernel\KernelEvents;
/**
 * Handles HTTP cache headers configured via the Cache attribute.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class CacheAttributeListener implements EventSubscriberInterface
{
    /**
     * @var \SplObjectStorage<Request, \DateTimeInterface>
     */
    private \SplObjectStorage $lastModified;
    /**
     * @var \SplObjectStorage<Request, string>
     */
    private \SplObjectStorage $etags;
    public function __construct(private ?ExpressionLanguage $expressionLanguage = null)
    {
        $this->lastModified = new \SplObjectStorage();
        $this->etags = new \SplObjectStorage();
    }
    /**
     * Handles HTTP validation headers.
     *
     * @return void
     */
    public function onKernelControllerArguments(ControllerArgumentsEvent $event)
    {
        $request = $event->getRequest();
        if (!\is_array($attributes = $request->attributes->get('_cache') ?? $event->getAttributes()[Cache::class] ?? null)) {
            return;
        }
        $request->attributes->set('_cache', $attributes);
        $response = null;
        $lastModified = null;
        $etag = null;
        /** @var Cache[] $attributes */
        foreach ($attributes as $cache) {
            if (null !== $cache->lastModified) {
                $lastModified = $this->getExpressionLanguage()->evaluate($cache->lastModified, array_merge($request->attributes->all(), $event->getNamedArguments()));
                ($response ??= new Response())->setLastModified($lastModified);
            }
            if (null !== $cache->etag) {
                $etag = hash('sha256', $this->getExpressionLanguage()->evaluate($cache->etag, array_merge($request->attributes->all(), $event->getNamedArguments())));
                ($response ??= new Response())->setEtag($etag);
            }
        }
        if ($response?->isNotModified($request)) {
            $event->setController(static fn() => $response);
            $event->stopPropagation();
            return;
        }
        if (null !== $etag) {
            $this->etags[$request] = $etag;
        }
        if (null !== $lastModified) {
            $this->lastModified[$request] = $lastModified;
        }
    }
    /**
     * Modifies the response to apply HTTP cache headers when needed.
     *
     * @return void
     */
    public function onKernelResponse(ResponseEvent $event)
    {
        $request = $event->getRequest();
        /** @var Cache[] $attributes */
        if (!\is_array($attributes = $request->attributes->get('_cache'))) {
            return;
        }
        $response = $event->getResponse();
        // http://tools.ietf.org/html/draft-ietf-httpbis-p4-conditional-12#section-3.1
        if (!\in_array($response->getStatusCode(), [200, 203, 300, 301, 302, 304, 404, 410])) {
            unset($this->lastModified[$request]);
            unset($this->etags[$request]);
            return;
        }
        if (isset($this->lastModified[$request]) && !$response->headers->has('Last-Modified')) {
            $response->setLastModified($this->lastModified[$request]);
        }
        if (isset($this->etags[$request]) && !$response->headers->has('Etag')) {
            $response->setEtag($this->etags[$request]);
        }
        unset($this->lastModified[$request]);
        unset($this->etags[$request]);
        // Check if the response has a Vary header that should be considered, ignoring cases where
        // it's only 'Accept-Language' and the request has the '_vary_by_language' attribute
        $hasVary = ['Accept-Language'] === $response->getVary() ? !$request->attributes->get('_vary_by_language') : $response->hasVary();
        //Check if cache-control directive was set manually in cacheControl (not auto computed)
        $hasCacheControlDirective = new class($response->headers) extends HeaderBag
        {
            public function __construct(private parent $headerBag)
            {
            }
            public function __invoke(string $key): bool
            {
                return \array_key_exists($key, $this->headerBag->cacheControl);
            }
        };
        foreach (array_reverse($attributes) as $cache) {
            if (null !== $cache->smaxage && !$hasCacheControlDirective('s-maxage')) {
                $response->setSharedMaxAge($this->toSeconds($cache->smaxage));
            }
            if ($cache->mustRevalidate) {
                $response->headers->addCacheControlDirective('must-revalidate');
            }
            if (null !== $cache->maxage && !$hasCacheControlDirective('max-age')) {
                $response->setMaxAge($this->toSeconds($cache->maxage));
            }
            if (null !== $cache->maxStale && !$hasCacheControlDirective('max-stale')) {
                $response->headers->addCacheControlDirective('max-stale', $this->toSeconds($cache->maxStale));
            }
            if (null !== $cache->staleWhileRevalidate && !$hasCacheControlDirective('stale-while-revalidate')) {
                $response->headers->addCacheControlDirective('stale-while-revalidate', $this->toSeconds($cache->staleWhileRevalidate));
            }
            if (null !== $cache->staleIfError && !$hasCacheControlDirective('stale-if-error')) {
                $response->headers->addCacheControlDirective('stale-if-error', $this->toSeconds($cache->staleIfError));
            }
            if (null !== $cache->expires && !$response->headers->has('Expires')) {
                $response->setExpires(new \DateTimeImmutable('@' . strtotime($cache->expires, time())));
            }
            if (!$hasVary && $cache->vary) {
                $response->setVary($cache->vary, \false);
            }
        }
        $hasPublicOrPrivateCacheControlDirective = $hasCacheControlDirective('public') || $hasCacheControlDirective('private');
        foreach ($attributes as $cache) {
            if (\true === $cache->public && !$hasPublicOrPrivateCacheControlDirective) {
                $response->setPublic();
            }
            if (\false === $cache->public && !$hasPublicOrPrivateCacheControlDirective) {
                $response->setPrivate();
            }
        }
    }
    public static function getSubscribedEvents(): array
    {
        return [KernelEvents::CONTROLLER_ARGUMENTS => ['onKernelControllerArguments', 10], KernelEvents::RESPONSE => ['onKernelResponse', -10]];
    }
    private function getExpressionLanguage(): ExpressionLanguage
    {
        return $this->expressionLanguage ??= class_exists(ExpressionLanguage::class) ? new ExpressionLanguage() : throw new \LogicException('Unable to use expressions as the Symfony ExpressionLanguage component is not installed. Try running "composer require symfony/expression-language".');
    }
    private function toSeconds(int|string $time): int
    {
        if (!is_numeric($time)) {
            $now = time();
            $time = strtotime($time, $now) - $now;
        }
        return $time;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\HttpKernel\EventListener;

use _ContaoManager\Psr\Container\ContainerInterface;
use _ContaoManager\Symfony\Component\EventDispatcher\EventSubscriberInterface;
use _ContaoManager\Symfony\Component\HttpFoundation\Cookie;
use _ContaoManager\Symfony\Component\HttpFoundation\Session\Session;
use _ContaoManager\Symfony\Component\HttpFoundation\Session\SessionInterface;
use _ContaoManager\Symfony\Component\HttpFoundation\Session\SessionUtils;
use _ContaoManager\Symfony\Component\HttpKernel\Event\RequestEvent;
use _ContaoManager\Symfony\Component\HttpKernel\Event\ResponseEvent;
use _ContaoManager\Symfony\Component\HttpKernel\Exception\UnexpectedSessionUsageException;
use _ContaoManager\Symfony\Component\HttpKernel\KernelEvents;
use _ContaoManager\Symfony\Contracts\Service\ResetInterface;
/**
 * Sets the session onto the request on the "kernel.request" event and saves
 * it on the "kernel.response" event.
 *
 * In addition, if the session has been started it overrides the Cache-Control
 * header in such a way that all caching is disabled in that case.
 * If you have a scenario where caching responses with session information in
 * them makes sense, you can disable this behaviour by setting the header
 * AbstractSessionListener::NO_AUTO_CACHE_CONTROL_HEADER on the response.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 * @author Tobias Schultze <http://tobion.de>
 */
abstract class AbstractSessionListener implements EventSubscriberInterface, ResetInterface
{
    public const NO_AUTO_CACHE_CONTROL_HEADER = 'Symfony-Session-NoAutoCacheControl';
    /**
     * @internal
     */
    protected ?ContainerInterface $container;
    private bool $debug;
    /**
     * @var array<string, mixed>
     */
    private array $sessionOptions;
    /**
     * @internal
     */
    public function __construct(?ContainerInterface $container = null, bool $debug = \false, array $sessionOptions = [])
    {
        $this->container = $container;
        $this->debug = $debug;
        $this->sessionOptions = $sessionOptions;
    }
    /**
     * @internal
     */
    public function onKernelRequest(RequestEvent $event): void
    {
        if (!$event->isMainRequest()) {
            return;
        }
        $request = $event->getRequest();
        if (!$request->hasSession()) {
            $request->setSessionFactory(function () use ($request) {
                // Prevent calling `$this->getSession()` twice in case the Request (and the below factory) is cloned
                static $sess;
                if (!$sess) {
                    $sess = $this->getSession();
                    $request->setSession($sess);
                    /*
                     * For supporting sessions in php runtime with runners like roadrunner or swoole, the session
                     * cookie needs to be read from the cookie bag and set on the session storage.
                     *
                     * Do not set it when a native php session is active.
                     */
                    if ($sess && !$sess->isStarted() && \PHP_SESSION_ACTIVE !== session_status()) {
                        $sessionId = $sess->getId() ?: $request->cookies->get($sess->getName(), '');
                        $sess->setId($sessionId);
                    }
                }
                return $sess;
            });
        }
    }
    /**
     * @internal
     */
    public function onKernelResponse(ResponseEvent $event): void
    {
        if (!$event->isMainRequest() || !$this->container->has('initialized_session') && !$event->getRequest()->hasSession()) {
            return;
        }
        $response = $event->getResponse();
        $autoCacheControl = !$response->headers->has(self::NO_AUTO_CACHE_CONTROL_HEADER);
        // Always remove the internal header if present
        $response->headers->remove(self::NO_AUTO_CACHE_CONTROL_HEADER);
        if (!$event->getRequest()->hasSession(\true)) {
            return;
        }
        $session = $event->getRequest()->getSession();
        if ($session->isStarted()) {
            /*
             * Saves the session, in case it is still open, before sending the response/headers.
             *
             * This ensures several things in case the developer did not save the session explicitly:
             *
             *  * If a session save handler without locking is used, it ensures the data is available
             *    on the next request, e.g. after a redirect. PHPs auto-save at script end via
             *    session_register_shutdown is executed after fastcgi_finish_request. So in this case
             *    the data could be missing the next request because it might not be saved the moment
             *    the new request is processed.
             *  * A locking save handler (e.g. the native 'files') circumvents concurrency problems like
             *    the one above. But by saving the session before long-running things in the terminate event,
             *    we ensure the session is not blocked longer than needed.
             *  * When regenerating the session ID no locking is involved in PHPs session design. See
             *    https://bugs.php.net/61470 for a discussion. So in this case, the session must
             *    be saved anyway before sending the headers with the new session ID. Otherwise session
             *    data could get lost again for concurrent requests with the new ID. One result could be
             *    that you get logged out after just logging in.
             *
             * This listener should be executed as one of the last listeners, so that previous listeners
             * can still operate on the open session. This prevents the overhead of restarting it.
             * Listeners after closing the session can still work with the session as usual because
             * Symfonys session implementation starts the session on demand. So writing to it after
             * it is saved will just restart it.
             */
            $session->save();
            /*
             * For supporting sessions in php runtime with runners like roadrunner or swoole the session
             * cookie need to be written on the response object and should not be written by PHP itself.
             */
            $sessionName = $session->getName();
            $sessionId = $session->getId();
            $sessionOptions = $this->getSessionOptions($this->sessionOptions);
            $sessionCookiePath = $sessionOptions['cookie_path'] ?? '/';
            $sessionCookieDomain = $sessionOptions['cookie_domain'] ?? null;
            $sessionCookieSecure = $sessionOptions['cookie_secure'] ?? \false;
            $sessionCookieHttpOnly = $sessionOptions['cookie_httponly'] ?? \true;
            $sessionCookieSameSite = $sessionOptions['cookie_samesite'] ?? Cookie::SAMESITE_LAX;
            $sessionUseCookies = $sessionOptions['use_cookies'] ?? \true;
            SessionUtils::popSessionCookie($sessionName, $sessionId);
            if ($sessionUseCookies) {
                $request = $event->getRequest();
                $requestSessionCookieId = $request->cookies->get($sessionName);
                $isSessionEmpty = ($session instanceof Session ? $session->isEmpty() : !$session->all()) && empty($_SESSION);
                // checking $_SESSION to keep compatibility with native sessions
                if ($requestSessionCookieId && $isSessionEmpty) {
                    // PHP internally sets the session cookie value to "deleted" when setcookie() is called with empty string $value argument
                    // which happens in \Symfony\Component\HttpFoundation\Session\Storage\Handler\AbstractSessionHandler::destroy
                    // when the session gets invalidated (for example on logout) so we must handle this case here too
                    // otherwise we would send two Set-Cookie headers back with the response
                    SessionUtils::popSessionCookie($sessionName, 'deleted');
                    $response->headers->clearCookie($sessionName, $sessionCookiePath, $sessionCookieDomain, $sessionCookieSecure, $sessionCookieHttpOnly, $sessionCookieSameSite);
                } elseif ($sessionId !== $requestSessionCookieId && !$isSessionEmpty) {
                    $expire = 0;
                    $lifetime = $sessionOptions['cookie_lifetime'] ?? null;
                    if ($lifetime) {
                        $expire = time() + $lifetime;
                    }
                    $response->headers->setCookie(Cookie::create($sessionName, $sessionId, $expire, $sessionCookiePath, $sessionCookieDomain, $sessionCookieSecure, $sessionCookieHttpOnly, \false, $sessionCookieSameSite));
                }
            }
        }
        if ($session instanceof Session ? 0 === $session->getUsageIndex() : !$session->isStarted()) {
            return;
        }
        if ($autoCacheControl) {
            $maxAge = $response->headers->hasCacheControlDirective('public') ? 0 : (int) $response->getMaxAge();
            $response->setExpires(new \DateTimeImmutable('+' . $maxAge . ' seconds'))->setPrivate()->setMaxAge($maxAge)->headers->addCacheControlDirective('must-revalidate');
        }
        if (!$event->getRequest()->attributes->get('_stateless', \false)) {
            return;
        }
        if ($this->debug) {
            throw new UnexpectedSessionUsageException('Session was used while the request was declared stateless.');
        }
        if ($this->container->has('logger')) {
            $this->container->get('logger')->warning('Session was used while the request was declared stateless.');
        }
    }
    /**
     * @internal
     */
    public function onSessionUsage(): void
    {
        if (!$this->debug) {
            return;
        }
        if ($this->container?->has('session_collector')) {
            $this->container->get('session_collector')();
        }
        if (!$requestStack = $this->container?->has('request_stack') ? $this->container->get('request_stack') : null) {
            return;
        }
        $stateless = \false;
        $clonedRequestStack = clone $requestStack;
        while (null !== ($request = $clonedRequestStack->pop()) && !$stateless) {
            $stateless = $request->attributes->get('_stateless');
        }
        if (!$stateless) {
            return;
        }
        if (!$session = $requestStack->getCurrentRequest()->getSession()) {
            return;
        }
        if ($session->isStarted()) {
            $session->save();
        }
        throw new UnexpectedSessionUsageException('Session was used while the request was declared stateless.');
    }
    /**
     * @internal
     */
    public static function getSubscribedEvents(): array
    {
        return [
            KernelEvents::REQUEST => ['onKernelRequest', 128],
            // low priority to come after regular response listeners
            KernelEvents::RESPONSE => ['onKernelResponse', -1000],
        ];
    }
    /**
     * @internal
     */
    public function reset(): void
    {
        if (\PHP_SESSION_ACTIVE === session_status()) {
            session_abort();
        }
        session_unset();
        $_SESSION = [];
        if (!headers_sent()) {
            // session id can only be reset when no headers were so we check for headers_sent first
            session_id('');
        }
    }
    /**
     * Gets the session object.
     *
     * @internal
     */
    abstract protected function getSession(): ?SessionInterface;
    private function getSessionOptions(array $sessionOptions): array
    {
        $mergedSessionOptions = [];
        foreach (session_get_cookie_params() as $key => $value) {
            $mergedSessionOptions['cookie_' . $key] = $value;
        }
        foreach ($sessionOptions as $key => $value) {
            // do the same logic as in the NativeSessionStorage
            if ('cookie_secure' === $key && 'auto' === $value) {
                continue;
            }
            $mergedSessionOptions[$key] = $value;
        }
        return $mergedSessionOptions;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\HttpKernel\EventListener;

use _ContaoManager\Symfony\Component\EventDispatcher\EventSubscriberInterface;
use _ContaoManager\Symfony\Component\HttpKernel\Event\RequestEvent;
use _ContaoManager\Symfony\Component\HttpKernel\KernelEvents;
/**
 * Validates Requests.
 *
 * @author Magnus Nordlander <magnus@fervo.se>
 *
 * @final
 */
class ValidateRequestListener implements EventSubscriberInterface
{
    /**
     * Performs the validation.
     */
    public function onKernelRequest(RequestEvent $event): void
    {
        if (!$event->isMainRequest()) {
            return;
        }
        $request = $event->getRequest();
        if ($request::getTrustedProxies()) {
            $request->getClientIps();
        }
        $request->getHost();
    }
    public static function getSubscribedEvents(): array
    {
        return [KernelEvents::REQUEST => [['onKernelRequest', 256]]];
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\HttpKernel\EventListener;

use _ContaoManager\Symfony\Component\EventDispatcher\EventSubscriberInterface;
use _ContaoManager\Symfony\Component\HttpKernel\Event\ResponseEvent;
use _ContaoManager\Symfony\Component\HttpKernel\KernelEvents;
/**
 * Ensures that the application is not indexed by search engines.
 *
 * @author Gary PEGEOT <garypegeot@gmail.com>
 */
class DisallowRobotsIndexingListener implements EventSubscriberInterface
{
    private const HEADER_NAME = 'X-Robots-Tag';
    public function onResponse(ResponseEvent $event): void
    {
        if (!$event->getResponse()->headers->has(static::HEADER_NAME)) {
            $event->getResponse()->headers->set(static::HEADER_NAME, 'noindex');
        }
    }
    public static function getSubscribedEvents(): array
    {
        return [KernelEvents::RESPONSE => ['onResponse', -255]];
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\HttpKernel\EventListener;

use _ContaoManager\Symfony\Component\EventDispatcher\EventSubscriberInterface;
use _ContaoManager\Symfony\Component\HttpKernel\Event\RequestEvent;
use _ContaoManager\Symfony\Component\HttpKernel\KernelEvents;
/**
 * Adds configured formats to each request.
 *
 * @author Gildas Quemener <gildas.quemener@gmail.com>
 *
 * @final
 */
class AddRequestFormatsListener implements EventSubscriberInterface
{
    private array $formats;
    public function __construct(array $formats)
    {
        $this->formats = $formats;
    }
    /**
     * Adds request formats.
     */
    public function onKernelRequest(RequestEvent $event): void
    {
        $request = $event->getRequest();
        foreach ($this->formats as $format => $mimeTypes) {
            $request->setFormat($format, $mimeTypes);
        }
    }
    public static function getSubscribedEvents(): array
    {
        return [KernelEvents::REQUEST => ['onKernelRequest', 100]];
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\HttpKernel\EventListener;

use _ContaoManager\Symfony\Component\EventDispatcher\EventSubscriberInterface;
use _ContaoManager\Symfony\Component\HttpFoundation\Request;
use _ContaoManager\Symfony\Component\HttpFoundation\RequestMatcherInterface;
use _ContaoManager\Symfony\Component\HttpFoundation\RequestStack;
use _ContaoManager\Symfony\Component\HttpFoundation\Session\Session;
use _ContaoManager\Symfony\Component\HttpKernel\Event\ExceptionEvent;
use _ContaoManager\Symfony\Component\HttpKernel\Event\ResponseEvent;
use _ContaoManager\Symfony\Component\HttpKernel\Event\TerminateEvent;
use _ContaoManager\Symfony\Component\HttpKernel\KernelEvents;
use _ContaoManager\Symfony\Component\HttpKernel\Profiler\Profile;
use _ContaoManager\Symfony\Component\HttpKernel\Profiler\Profiler;
/**
 * ProfilerListener collects data for the current request by listening to the kernel events.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 *
 * @final
 */
class ProfilerListener implements EventSubscriberInterface
{
    private Profiler $profiler;
    private ?RequestMatcherInterface $matcher;
    private bool $onlyException;
    private bool $onlyMainRequests;
    private ?\Throwable $exception = null;
    /** @var \SplObjectStorage<Request, Profile> */
    private \SplObjectStorage $profiles;
    private RequestStack $requestStack;
    private ?string $collectParameter;
    /** @var \SplObjectStorage<Request, Request|null> */
    private \SplObjectStorage $parents;
    /**
     * @param bool $onlyException    True if the profiler only collects data when an exception occurs, false otherwise
     * @param bool $onlyMainRequests True if the profiler only collects data when the request is the main request, false otherwise
     */
    public function __construct(Profiler $profiler, RequestStack $requestStack, ?RequestMatcherInterface $matcher = null, bool $onlyException = \false, bool $onlyMainRequests = \false, ?string $collectParameter = null)
    {
        $this->profiler = $profiler;
        $this->matcher = $matcher;
        $this->onlyException = $onlyException;
        $this->onlyMainRequests = $onlyMainRequests;
        $this->profiles = new \SplObjectStorage();
        $this->parents = new \SplObjectStorage();
        $this->requestStack = $requestStack;
        $this->collectParameter = $collectParameter;
    }
    /**
     * Handles the onKernelException event.
     */
    public function onKernelException(ExceptionEvent $event): void
    {
        if ($this->onlyMainRequests && !$event->isMainRequest()) {
            return;
        }
        $this->exception = $event->getThrowable();
    }
    /**
     * Handles the onKernelResponse event.
     */
    public function onKernelResponse(ResponseEvent $event): void
    {
        if ($this->onlyMainRequests && !$event->isMainRequest()) {
            return;
        }
        if ($this->onlyException && null === $this->exception) {
            return;
        }
        $request = $event->getRequest();
        if (null !== $this->collectParameter && null !== $collectParameterValue = $request->get($this->collectParameter)) {
            \true === $collectParameterValue || filter_var($collectParameterValue, \FILTER_VALIDATE_BOOL) ? $this->profiler->enable() : $this->profiler->disable();
        }
        $exception = $this->exception;
        $this->exception = null;
        if (null !== $this->matcher && !$this->matcher->matches($request)) {
            return;
        }
        $session = !$request->attributes->getBoolean('_stateless') && $request->hasPreviousSession() ? $request->getSession() : null;
        if ($session instanceof Session) {
            $usageIndexValue = $usageIndexReference =& $session->getUsageIndex();
            $usageIndexReference = \PHP_INT_MIN;
        }
        try {
            if (!$profile = $this->profiler->collect($request, $event->getResponse(), $exception)) {
                return;
            }
        } finally {
            if ($session instanceof Session) {
                $usageIndexReference = $usageIndexValue;
            }
        }
        $this->profiles[$request] = $profile;
        $this->parents[$request] = $this->requestStack->getParentRequest();
    }
    public function onKernelTerminate(TerminateEvent $event): void
    {
        // attach children to parents
        foreach ($this->profiles as $request) {
            if (null !== $parentRequest = $this->parents[$request]) {
                if (isset($this->profiles[$parentRequest])) {
                    $this->profiles[$parentRequest]->addChild($this->profiles[$request]);
                }
            }
        }
        // save profiles
        foreach ($this->profiles as $request) {
            $this->profiler->saveProfile($this->profiles[$request]);
        }
        $this->profiles = new \SplObjectStorage();
        $this->parents = new \SplObjectStorage();
    }
    public static function getSubscribedEvents(): array
    {
        return [KernelEvents::RESPONSE => ['onKernelResponse', -100], KernelEvents::EXCEPTION => ['onKernelException', 0], KernelEvents::TERMINATE => ['onKernelTerminate', -1024]];
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\HttpKernel\EventListener;

use _ContaoManager\Symfony\Component\EventDispatcher\EventSubscriberInterface;
use _ContaoManager\Symfony\Component\HttpKernel\Event\ResponseEvent;
use _ContaoManager\Symfony\Component\HttpKernel\HttpCache\HttpCache;
use _ContaoManager\Symfony\Component\HttpKernel\HttpCache\SurrogateInterface;
use _ContaoManager\Symfony\Component\HttpKernel\KernelEvents;
/**
 * SurrogateListener adds a Surrogate-Control HTTP header when the Response needs to be parsed for Surrogates.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 *
 * @final
 */
class SurrogateListener implements EventSubscriberInterface
{
    private ?SurrogateInterface $surrogate;
    public function __construct(?SurrogateInterface $surrogate = null)
    {
        $this->surrogate = $surrogate;
    }
    /**
     * Filters the Response.
     */
    public function onKernelResponse(ResponseEvent $event): void
    {
        if (!$event->isMainRequest()) {
            return;
        }
        $kernel = $event->getKernel();
        $surrogate = $this->surrogate;
        if ($kernel instanceof HttpCache) {
            $surrogate = $kernel->getSurrogate();
            if (null !== $this->surrogate && $this->surrogate->getName() !== $surrogate->getName()) {
                $surrogate = $this->surrogate;
            }
        }
        if (null === $surrogate) {
            return;
        }
        $surrogate->addSurrogateControl($event->getResponse());
    }
    public static function getSubscribedEvents(): array
    {
        return [KernelEvents::RESPONSE => 'onKernelResponse'];
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\HttpKernel\EventListener;

use _ContaoManager\Psr\Log\LoggerInterface;
use _ContaoManager\Symfony\Component\Console\ConsoleEvents;
use _ContaoManager\Symfony\Component\Console\Event\ConsoleEvent;
use _ContaoManager\Symfony\Component\Console\Output\ConsoleOutputInterface;
use _ContaoManager\Symfony\Component\ErrorHandler\ErrorHandler;
use _ContaoManager\Symfony\Component\EventDispatcher\EventSubscriberInterface;
use _ContaoManager\Symfony\Component\HttpKernel\Event\KernelEvent;
use _ContaoManager\Symfony\Component\HttpKernel\KernelEvents;
/**
 * Sets an exception handler.
 *
 * @author Nicolas Grekas <p@tchwork.com>
 *
 * @final
 *
 * @internal
 */
class DebugHandlersListener implements EventSubscriberInterface
{
    private string|object|null $earlyHandler;
    private ?\Closure $exceptionHandler;
    private bool $webMode;
    private bool $firstCall = \true;
    private bool $hasTerminatedWithException = \false;
    /**
     * @param bool          $webMode
     * @param callable|null $exceptionHandler A handler that must support \Throwable instances that will be called on Exception
     */
    public function __construct(?callable $exceptionHandler = null, bool|LoggerInterface|null $webMode = null)
    {
        if ($webMode instanceof LoggerInterface) {
            // BC with Symfony 5
            $webMode = null;
        }
        $handler = set_exception_handler('var_dump');
        $this->earlyHandler = \is_array($handler) ? $handler[0] : null;
        restore_exception_handler();
        $this->exceptionHandler = null === $exceptionHandler ? null : $exceptionHandler(...);
        $this->webMode = $webMode ?? !\in_array(\PHP_SAPI, ['cli', 'phpdbg', 'embed'], \true);
    }
    /**
     * Configures the error handler.
     */
    public function configure(?object $event = null): void
    {
        if ($event instanceof ConsoleEvent && $this->webMode) {
            return;
        }
        if (!$event instanceof KernelEvent ? !$this->firstCall : !$event->isMainRequest()) {
            return;
        }
        $this->firstCall = $this->hasTerminatedWithException = \false;
        $hasRun = null;
        if (!$this->exceptionHandler) {
            if ($event instanceof KernelEvent) {
                if (method_exists($kernel = $event->getKernel(), 'terminateWithException')) {
                    $request = $event->getRequest();
                    $hasRun =& $this->hasTerminatedWithException;
                    $this->exceptionHandler = static function (\Throwable $e) use ($kernel, $request, &$hasRun) {
                        if ($hasRun) {
                            throw $e;
                        }
                        $hasRun = \true;
                        $kernel->terminateWithException($e, $request);
                    };
                }
            } elseif ($event instanceof ConsoleEvent && $app = $event->getCommand()->getApplication()) {
                $output = $event->getOutput();
                if ($output instanceof ConsoleOutputInterface) {
                    $output = $output->getErrorOutput();
                }
                $this->exceptionHandler = static function (\Throwable $e) use ($app, $output) {
                    $app->renderThrowable($e, $output);
                };
            }
        }
        if ($this->exceptionHandler) {
            $handler = set_exception_handler('var_dump');
            $handler = \is_array($handler) ? $handler[0] : null;
            restore_exception_handler();
            if (!$handler instanceof ErrorHandler) {
                $handler = $this->earlyHandler;
            }
            if ($handler instanceof ErrorHandler) {
                $handler->setExceptionHandler($this->exceptionHandler);
                if (null !== $hasRun) {
                    $throwAt = $handler->throwAt(0) | \E_ERROR | \E_CORE_ERROR | \E_COMPILE_ERROR | \E_USER_ERROR | \E_RECOVERABLE_ERROR | \E_PARSE;
                    $loggers = [];
                    foreach ($handler->setLoggers([]) as $type => $log) {
                        if ($type & $throwAt) {
                            $loggers[$type] = [null, $log[1]];
                        }
                    }
                    // Assume $kernel->terminateWithException() will log uncaught exceptions appropriately
                    $handler->setLoggers($loggers);
                }
            }
            $this->exceptionHandler = null;
        }
    }
    public static function getSubscribedEvents(): array
    {
        $events = [KernelEvents::REQUEST => ['configure', 2048]];
        if (\defined('_ContaoManager\Symfony\Component\Console\ConsoleEvents::COMMAND')) {
            $events[ConsoleEvents::COMMAND] = ['configure', 2048];
        }
        return $events;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\HttpKernel\EventListener;

use _ContaoManager\Symfony\Component\EventDispatcher\EventSubscriberInterface;
use _ContaoManager\Symfony\Component\HttpFoundation\RequestStack;
use _ContaoManager\Symfony\Component\HttpKernel\Event\FinishRequestEvent;
use _ContaoManager\Symfony\Component\HttpKernel\Event\RequestEvent;
use _ContaoManager\Symfony\Component\HttpKernel\KernelEvents;
use _ContaoManager\Symfony\Contracts\Translation\LocaleAwareInterface;
/**
 * Pass the current locale to the provided services.
 *
 * @author Pierre Bobiet <pierrebobiet@gmail.com>
 */
class LocaleAwareListener implements EventSubscriberInterface
{
    private iterable $localeAwareServices;
    private RequestStack $requestStack;
    /**
     * @param iterable<mixed, LocaleAwareInterface> $localeAwareServices
     */
    public function __construct(iterable $localeAwareServices, RequestStack $requestStack)
    {
        $this->localeAwareServices = $localeAwareServices;
        $this->requestStack = $requestStack;
    }
    public function onKernelRequest(RequestEvent $event): void
    {
        $this->setLocale($event->getRequest()->getLocale(), $event->getRequest()->getDefaultLocale());
    }
    public function onKernelFinishRequest(FinishRequestEvent $event): void
    {
        if (null === $parentRequest = $this->requestStack->getParentRequest()) {
            foreach ($this->localeAwareServices as $service) {
                $service->setLocale($event->getRequest()->getDefaultLocale());
            }
            return;
        }
        $this->setLocale($parentRequest->getLocale(), $parentRequest->getDefaultLocale());
    }
    public static function getSubscribedEvents(): array
    {
        return [
            // must be registered after the Locale listener
            KernelEvents::REQUEST => [['onKernelRequest', 15]],
            KernelEvents::FINISH_REQUEST => [['onKernelFinishRequest', -15]],
        ];
    }
    private function setLocale(string $locale, string $defaultLocale): void
    {
        foreach ($this->localeAwareServices as $service) {
            try {
                $service->setLocale($locale);
            } catch (\InvalidArgumentException) {
                $service->setLocale($defaultLocale);
            }
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\HttpKernel\EventListener;

use _ContaoManager\Symfony\Component\Console\ConsoleEvents;
use _ContaoManager\Symfony\Component\EventDispatcher\EventSubscriberInterface;
use _ContaoManager\Symfony\Component\VarDumper\Cloner\ClonerInterface;
use _ContaoManager\Symfony\Component\VarDumper\Dumper\DataDumperInterface;
use _ContaoManager\Symfony\Component\VarDumper\Server\Connection;
use _ContaoManager\Symfony\Component\VarDumper\VarDumper;
/**
 * Configures dump() handler.
 *
 * @author Nicolas Grekas <p@tchwork.com>
 */
class DumpListener implements EventSubscriberInterface
{
    private ClonerInterface $cloner;
    private DataDumperInterface $dumper;
    private ?Connection $connection;
    public function __construct(ClonerInterface $cloner, DataDumperInterface $dumper, ?Connection $connection = null)
    {
        $this->cloner = $cloner;
        $this->dumper = $dumper;
        $this->connection = $connection;
    }
    /**
     * @return void
     */
    public function configure()
    {
        $cloner = $this->cloner;
        $dumper = $this->dumper;
        $connection = $this->connection;
        VarDumper::setHandler(static function ($var, ?string $label = null) use ($cloner, $dumper, $connection) {
            $data = $cloner->cloneVar($var);
            if (null !== $label) {
                $data = $data->withContext(['label' => $label]);
            }
            if (!$connection || !$connection->write($data)) {
                $dumper->dump($data);
            }
        });
    }
    public static function getSubscribedEvents(): array
    {
        if (!class_exists(ConsoleEvents::class)) {
            return [];
        }
        // Register early to have a working dump() as early as possible
        return [ConsoleEvents::COMMAND => ['configure', 1024]];
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\HttpKernel\EventListener;

use _ContaoManager\Psr\Log\LoggerInterface;
use _ContaoManager\Psr\Log\LogLevel;
use _ContaoManager\Symfony\Component\ErrorHandler\ErrorHandler;
use _ContaoManager\Symfony\Component\ErrorHandler\Exception\FlattenException;
use _ContaoManager\Symfony\Component\EventDispatcher\EventSubscriberInterface;
use _ContaoManager\Symfony\Component\HttpFoundation\Request;
use _ContaoManager\Symfony\Component\HttpKernel\Attribute\WithHttpStatus;
use _ContaoManager\Symfony\Component\HttpKernel\Attribute\WithLogLevel;
use _ContaoManager\Symfony\Component\HttpKernel\Event\ControllerArgumentsEvent;
use _ContaoManager\Symfony\Component\HttpKernel\Event\ExceptionEvent;
use _ContaoManager\Symfony\Component\HttpKernel\Event\ResponseEvent;
use _ContaoManager\Symfony\Component\HttpKernel\Exception\HttpException;
use _ContaoManager\Symfony\Component\HttpKernel\Exception\HttpExceptionInterface;
use _ContaoManager\Symfony\Component\HttpKernel\HttpKernelInterface;
use _ContaoManager\Symfony\Component\HttpKernel\KernelEvents;
use _ContaoManager\Symfony\Component\HttpKernel\Log\DebugLoggerConfigurator;
/**
 * @author Fabien Potencier <fabien@symfony.com>
 */
class ErrorListener implements EventSubscriberInterface
{
    protected $controller;
    protected $logger;
    protected $debug;
    /**
     * @var array<class-string, array{log_level: string|null, status_code: int<100,599>|null}>
     */
    protected $exceptionsMapping;
    /**
     * @param array<class-string, array{log_level: string|null, status_code: int<100,599>|null}> $exceptionsMapping
     */
    public function __construct(string|object|array|null $controller, ?LoggerInterface $logger = null, bool $debug = \false, array $exceptionsMapping = [])
    {
        $this->controller = $controller;
        $this->logger = $logger;
        $this->debug = $debug;
        $this->exceptionsMapping = $exceptionsMapping;
    }
    /**
     * @return void
     */
    public function logKernelException(ExceptionEvent $event)
    {
        $throwable = $event->getThrowable();
        $logLevel = $this->resolveLogLevel($throwable);
        foreach ($this->exceptionsMapping as $class => $config) {
            if (!$throwable instanceof $class || !$config['status_code']) {
                continue;
            }
            if (!$throwable instanceof HttpExceptionInterface || $throwable->getStatusCode() !== $config['status_code']) {
                $headers = $throwable instanceof HttpExceptionInterface ? $throwable->getHeaders() : [];
                $throwable = new HttpException($config['status_code'], $throwable->getMessage(), $throwable, $headers);
                $event->setThrowable($throwable);
            }
            break;
        }
        // There's no specific status code defined in the configuration for this exception
        if (!$throwable instanceof HttpExceptionInterface) {
            $class = new \ReflectionClass($throwable);
            do {
                if ($attributes = $class->getAttributes(WithHttpStatus::class, \ReflectionAttribute::IS_INSTANCEOF)) {
                    /** @var WithHttpStatus $instance */
                    $instance = $attributes[0]->newInstance();
                    $throwable = new HttpException($instance->statusCode, $throwable->getMessage(), $throwable, $instance->headers);
                    $event->setThrowable($throwable);
                    break;
                }
            } while ($class = $class->getParentClass());
        }
        $e = FlattenException::createFromThrowable($throwable);
        $this->logException($throwable, \sprintf('Uncaught PHP Exception %s: "%s" at %s line %s', $e->getClass(), $e->getMessage(), basename($e->getFile()), $e->getLine()), $logLevel);
    }
    /**
     * @return void
     */
    public function onKernelException(ExceptionEvent $event)
    {
        if (null === $this->controller) {
            return;
        }
        $throwable = $event->getThrowable();
        $exceptionHandler = set_exception_handler('var_dump');
        restore_exception_handler();
        if (\is_array($exceptionHandler) && $exceptionHandler[0] instanceof ErrorHandler) {
            $throwable = $exceptionHandler[0]->enhanceError($event->getThrowable());
        }
        $request = $this->duplicateRequest($throwable, $event->getRequest());
        try {
            $response = $event->getKernel()->handle($request, HttpKernelInterface::SUB_REQUEST, \false);
        } catch (\Exception $e) {
            $f = FlattenException::createFromThrowable($e);
            $this->logException($e, \sprintf('Exception thrown when handling an exception (%s: %s at %s line %s)', $f->getClass(), $f->getMessage(), basename($e->getFile()), $e->getLine()));
            $prev = $e;
            do {
                if ($throwable === $wrapper = $prev) {
                    throw $e;
                }
            } while ($prev = $wrapper->getPrevious());
            $prev = new \ReflectionProperty($wrapper instanceof \Exception ? \Exception::class : \Error::class, 'previous');
            $prev->setValue($wrapper, $throwable);
            throw $e;
        }
        $event->setResponse($response);
        if ($this->debug) {
            $event->getRequest()->attributes->set('_remove_csp_headers', \true);
        }
    }
    public function removeCspHeader(ResponseEvent $event): void
    {
        if ($this->debug && $event->getRequest()->attributes->get('_remove_csp_headers', \false)) {
            $event->getResponse()->headers->remove('Content-Security-Policy');
        }
    }
    /**
     * @return void
     */
    public function onControllerArguments(ControllerArgumentsEvent $event)
    {
        $e = $event->getRequest()->attributes->get('exception');
        if (!$e instanceof \Throwable || \false === $k = array_search($e, $event->getArguments(), \true)) {
            return;
        }
        $r = new \ReflectionFunction($event->getController()(...));
        $r = $r->getParameters()[$k] ?? null;
        if ($r && (!($r = $r->getType()) instanceof \ReflectionNamedType || FlattenException::class === $r->getName())) {
            $arguments = $event->getArguments();
            $arguments[$k] = FlattenException::createFromThrowable($e);
            $event->setArguments($arguments);
        }
    }
    public static function getSubscribedEvents(): array
    {
        return [KernelEvents::CONTROLLER_ARGUMENTS => 'onControllerArguments', KernelEvents::EXCEPTION => [['logKernelException', 0], ['onKernelException', -128]], KernelEvents::RESPONSE => ['removeCspHeader', -128]];
    }
    /**
     * Logs an exception.
     */
    protected function logException(\Throwable $exception, string $message, ?string $logLevel = null): void
    {
        if (null === $this->logger) {
            return;
        }
        $logLevel ??= $this->resolveLogLevel($exception);
        $this->logger->log($logLevel, $message, ['exception' => $exception]);
    }
    /**
     * Resolves the level to be used when logging the exception.
     */
    private function resolveLogLevel(\Throwable $throwable): string
    {
        foreach ($this->exceptionsMapping as $class => $config) {
            if ($throwable instanceof $class && $config['log_level']) {
                return $config['log_level'];
            }
        }
        $class = new \ReflectionClass($throwable);
        do {
            if ($attributes = $class->getAttributes(WithLogLevel::class)) {
                /** @var WithLogLevel $instance */
                $instance = $attributes[0]->newInstance();
                return $instance->level;
            }
        } while ($class = $class->getParentClass());
        if (!$throwable instanceof HttpExceptionInterface || $throwable->getStatusCode() >= 500) {
            return LogLevel::CRITICAL;
        }
        return LogLevel::ERROR;
    }
    /**
     * Clones the request for the exception.
     */
    protected function duplicateRequest(\Throwable $exception, Request $request): Request
    {
        $attributes = ['_controller' => $this->controller, 'exception' => $exception, 'logger' => DebugLoggerConfigurator::getDebugLogger($this->logger)];
        $request = $request->duplicate(null, null, $attributes);
        $request->setMethod('GET');
        return $request;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\HttpKernel\EventListener;

use _ContaoManager\Symfony\Component\HttpFoundation\Session\SessionInterface;
/**
 * Sets the session in the request.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 *
 * @final
 */
class SessionListener extends AbstractSessionListener
{
    protected function getSession(): ?SessionInterface
    {
        if ($this->container->has('session_factory')) {
            return $this->container->get('session_factory')->createSession();
        }
        return null;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\HttpKernel\EventListener;

use _ContaoManager\Psr\Log\LoggerInterface;
use _ContaoManager\Symfony\Component\EventDispatcher\EventSubscriberInterface;
use _ContaoManager\Symfony\Component\HttpFoundation\Request;
use _ContaoManager\Symfony\Component\HttpFoundation\RequestStack;
use _ContaoManager\Symfony\Component\HttpFoundation\Response;
use _ContaoManager\Symfony\Component\HttpKernel\Event\ExceptionEvent;
use _ContaoManager\Symfony\Component\HttpKernel\Event\RequestEvent;
use _ContaoManager\Symfony\Component\HttpKernel\Exception\BadRequestHttpException;
use _ContaoManager\Symfony\Component\HttpKernel\Exception\MethodNotAllowedHttpException;
use _ContaoManager\Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
use _ContaoManager\Symfony\Component\HttpKernel\Kernel;
use _ContaoManager\Symfony\Component\HttpKernel\KernelEvents;
use _ContaoManager\Symfony\Component\Routing\Exception\MethodNotAllowedException;
use _ContaoManager\Symfony\Component\Routing\Exception\NoConfigurationException;
use _ContaoManager\Symfony\Component\Routing\Exception\ResourceNotFoundException;
use _ContaoManager\Symfony\Component\Routing\Matcher\RequestMatcherInterface;
use _ContaoManager\Symfony\Component\Routing\Matcher\UrlMatcherInterface;
use _ContaoManager\Symfony\Component\Routing\RequestContext;
use _ContaoManager\Symfony\Component\Routing\RequestContextAwareInterface;
/**
 * Initializes the context from the request and sets request attributes based on a matching route.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 * @author Yonel Ceruto <yonelceruto@gmail.com>
 *
 * @final
 */
class RouterListener implements EventSubscriberInterface
{
    private RequestMatcherInterface|UrlMatcherInterface $matcher;
    private RequestContext $context;
    private ?LoggerInterface $logger;
    private RequestStack $requestStack;
    private ?string $projectDir;
    private bool $debug;
    /**
     * @param RequestContext|null $context The RequestContext (can be null when $matcher implements RequestContextAwareInterface)
     *
     * @throws \InvalidArgumentException
     */
    public function __construct(UrlMatcherInterface|RequestMatcherInterface $matcher, RequestStack $requestStack, ?RequestContext $context = null, ?LoggerInterface $logger = null, ?string $projectDir = null, bool $debug = \true)
    {
        if (null === $context && !$matcher instanceof RequestContextAwareInterface) {
            throw new \InvalidArgumentException('You must either pass a RequestContext or the matcher must implement RequestContextAwareInterface.');
        }
        $this->matcher = $matcher;
        $this->context = $context ?? $matcher->getContext();
        $this->requestStack = $requestStack;
        $this->logger = $logger;
        $this->projectDir = $projectDir;
        $this->debug = $debug;
    }
    private function setCurrentRequest(?Request $request): void
    {
        if (null !== $request) {
            try {
                $this->context->fromRequest($request);
            } catch (\UnexpectedValueException $e) {
                throw new BadRequestHttpException($e->getMessage(), $e, $e->getCode());
            }
        }
    }
    /**
     * After a sub-request is done, we need to reset the routing context to the parent request so that the URL generator
     * operates on the correct context again.
     */
    public function onKernelFinishRequest(): void
    {
        $this->setCurrentRequest($this->requestStack->getParentRequest());
    }
    public function onKernelRequest(RequestEvent $event): void
    {
        $request = $event->getRequest();
        $this->setCurrentRequest($request);
        if ($request->attributes->has('_controller')) {
            // routing is already done
            return;
        }
        // add attributes based on the request (routing)
        try {
            // matching a request is more powerful than matching a URL path + context, so try that first
            if ($this->matcher instanceof RequestMatcherInterface) {
                $parameters = $this->matcher->matchRequest($request);
            } else {
                $parameters = $this->matcher->match($request->getPathInfo());
            }
            $this->logger?->info('Matched route "{route}".', ['route' => $parameters['_route'] ?? 'n/a', 'route_parameters' => $parameters, 'request_uri' => $request->getUri(), 'method' => $request->getMethod()]);
            $request->attributes->add($parameters);
            unset($parameters['_route'], $parameters['_controller']);
            $request->attributes->set('_route_params', $parameters);
        } catch (ResourceNotFoundException $e) {
            $message = \sprintf('No route found for "%s %s"', $request->getMethod(), $request->getUriForPath($request->getPathInfo()));
            if ($referer = $request->headers->get('referer')) {
                $message .= \sprintf(' (from "%s")', $referer);
            }
            throw new NotFoundHttpException($message, $e);
        } catch (MethodNotAllowedException $e) {
            $message = \sprintf('No route found for "%s %s": Method Not Allowed (Allow: %s)', $request->getMethod(), $request->getUriForPath($request->getPathInfo()), implode(', ', $e->getAllowedMethods()));
            throw new MethodNotAllowedHttpException($e->getAllowedMethods(), $message, $e);
        }
    }
    public function onKernelException(ExceptionEvent $event): void
    {
        if (!$this->debug || !($e = $event->getThrowable()) instanceof NotFoundHttpException) {
            return;
        }
        if ($e->getPrevious() instanceof NoConfigurationException) {
            $event->setResponse($this->createWelcomeResponse());
        }
    }
    public static function getSubscribedEvents(): array
    {
        return [KernelEvents::REQUEST => [['onKernelRequest', 32]], KernelEvents::FINISH_REQUEST => [['onKernelFinishRequest', 0]], KernelEvents::EXCEPTION => ['onKernelException', -64]];
    }
    private function createWelcomeResponse(): Response
    {
        $version = Kernel::VERSION;
        $projectDir = realpath((string) $this->projectDir) . \DIRECTORY_SEPARATOR;
        $docVersion = substr(Kernel::VERSION, 0, 3);
        ob_start();
        include \dirname(__DIR__) . '/Resources/welcome.html.php';
        return new Response(ob_get_clean(), Response::HTTP_NOT_FOUND);
    }
}
Copyright (c) 2004-present Fabien Potencier

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is furnished
to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Yaml;

use _ContaoManager\Symfony\Component\Yaml\Exception\ParseException;
use _ContaoManager\Symfony\Component\Yaml\Tag\TaggedValue;
/**
 * Parser parses YAML strings to convert them to PHP arrays.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 *
 * @final
 */
class Parser
{
    public const TAG_PATTERN = '(?P<tag>![\w!.\/:-]+)';
    public const BLOCK_SCALAR_HEADER_PATTERN = '(?P<separator>\||>)(?P<modifiers>\+|\-|\d+|\+\d+|\-\d+|\d+\+|\d+\-)?(?P<comments> +#.*)?';
    public const REFERENCE_PATTERN = '#^&(?P<ref>[^ ]++) *+(?P<value>.*)#u';
    private ?string $filename = null;
    private int $offset = 0;
    private int $numberOfParsedLines = 0;
    private ?int $totalNumberOfLines = null;
    private array $lines = [];
    private int $currentLineNb = -1;
    private string $currentLine = '';
    private array $refs = [];
    private array $skippedLineNumbers = [];
    private array $locallySkippedLineNumbers = [];
    private array $refsBeingParsed = [];
    /**
     * Parses a YAML file into a PHP value.
     *
     * @param string $filename The path to the YAML file to be parsed
     * @param int    $flags    A bit field of Yaml::PARSE_* constants to customize the YAML parser behavior
     *
     * @throws ParseException If the file could not be read or the YAML is not valid
     */
    public function parseFile(string $filename, int $flags = 0): mixed
    {
        if (!is_file($filename)) {
            throw new ParseException(\sprintf('File "%s" does not exist.', $filename));
        }
        if (!is_readable($filename)) {
            throw new ParseException(\sprintf('File "%s" cannot be read.', $filename));
        }
        $this->filename = $filename;
        try {
            return $this->parse(file_get_contents($filename), $flags);
        } finally {
            $this->filename = null;
        }
    }
    /**
     * Parses a YAML string to a PHP value.
     *
     * @param string $value A YAML string
     * @param int    $flags A bit field of Yaml::PARSE_* constants to customize the YAML parser behavior
     *
     * @throws ParseException If the YAML is not valid
     */
    public function parse(string $value, int $flags = 0): mixed
    {
        if (\false === preg_match('//u', $value)) {
            throw new ParseException('The YAML value does not appear to be valid UTF-8.', -1, null, $this->filename);
        }
        $this->refs = [];
        try {
            $data = $this->doParse($value, $flags);
        } finally {
            $this->refsBeingParsed = [];
            $this->offset = 0;
            $this->lines = [];
            $this->currentLine = '';
            $this->numberOfParsedLines = 0;
            $this->refs = [];
            $this->skippedLineNumbers = [];
            $this->locallySkippedLineNumbers = [];
            $this->totalNumberOfLines = null;
        }
        return $data;
    }
    private function doParse(string $value, int $flags): mixed
    {
        $this->currentLineNb = -1;
        $this->currentLine = '';
        $value = $this->cleanup($value);
        $this->lines = explode("\n", $value);
        $this->numberOfParsedLines = \count($this->lines);
        $this->locallySkippedLineNumbers = [];
        $this->totalNumberOfLines ??= $this->numberOfParsedLines;
        if (!$this->moveToNextLine()) {
            return null;
        }
        $data = [];
        $context = null;
        $allowOverwrite = \false;
        while ($this->isCurrentLineEmpty()) {
            if (!$this->moveToNextLine()) {
                return null;
            }
        }
        // Resolves the tag and returns if end of the document
        if (null !== ($tag = $this->getLineTag($this->currentLine, $flags, \false)) && !$this->moveToNextLine()) {
            return new TaggedValue($tag, '');
        }
        do {
            if ($this->isCurrentLineEmpty()) {
                continue;
            }
            // tab?
            if ("\t" === $this->currentLine[0]) {
                throw new ParseException('A YAML file cannot contain tabs as indentation.', $this->getRealCurrentLineNb() + 1, $this->currentLine, $this->filename);
            }
            Inline::initialize($flags, $this->getRealCurrentLineNb(), $this->filename);
            $isRef = $mergeNode = \false;
            if ('-' === $this->currentLine[0] && self::preg_match('#^\-((?P<leadspaces>\s+)(?P<value>.+))?$#u', rtrim($this->currentLine), $values)) {
                if ($context && 'mapping' == $context) {
                    throw new ParseException('You cannot define a sequence item when in a mapping.', $this->getRealCurrentLineNb() + 1, $this->currentLine, $this->filename);
                }
                $context = 'sequence';
                if (isset($values['value']) && '&' === $values['value'][0] && self::preg_match(self::REFERENCE_PATTERN, $values['value'], $matches)) {
                    $isRef = $matches['ref'];
                    $this->refsBeingParsed[] = $isRef;
                    $values['value'] = $matches['value'];
                }
                if (isset($values['value'][1]) && '?' === $values['value'][0] && ' ' === $values['value'][1]) {
                    throw new ParseException('Complex mappings are not supported.', $this->getRealCurrentLineNb() + 1, $this->currentLine);
                }
                // array
                if (isset($values['value']) && str_starts_with(ltrim($values['value'], ' '), '-')) {
                    // Inline first child
                    $currentLineNumber = $this->getRealCurrentLineNb();
                    $sequenceIndentation = \strlen($values['leadspaces']) + 1;
                    $sequenceYaml = substr($this->currentLine, $sequenceIndentation);
                    $sequenceYaml .= "\n" . $this->getNextEmbedBlock($sequenceIndentation, \true);
                    $data[] = $this->parseBlock($currentLineNumber, rtrim($sequenceYaml), $flags);
                } elseif (!isset($values['value']) || '' == trim($values['value'], ' ') || str_starts_with(ltrim($values['value'], ' '), '#')) {
                    $data[] = $this->parseBlock($this->getRealCurrentLineNb() + 1, $this->getNextEmbedBlock(null, \true) ?? '', $flags);
                } elseif (null !== $subTag = $this->getLineTag(ltrim($values['value'], ' '), $flags)) {
                    $data[] = new TaggedValue($subTag, $this->parseBlock($this->getRealCurrentLineNb() + 1, $this->getNextEmbedBlock(null, \true), $flags));
                } else if (isset($values['leadspaces']) && ('!' === $values['value'][0] || self::preg_match('#^(?P<key>' . Inline::REGEX_QUOTED_STRING . '|[^ \'"\{\[].*?) *\:(\s+(?P<value>.+?))?\s*$#u', $this->trimTag($values['value']), $matches))) {
                    $block = $values['value'];
                    if ($this->isNextLineIndented() || isset($matches['value']) && '>-' === $matches['value']) {
                        $block .= "\n" . $this->getNextEmbedBlock($this->getCurrentLineIndentation() + \strlen($values['leadspaces']) + 1);
                    }
                    $data[] = $this->parseBlock($this->getRealCurrentLineNb(), $block, $flags);
                } else {
                    $data[] = $this->parseValue($values['value'], $flags, $context);
                }
                if ($isRef) {
                    $this->refs[$isRef] = end($data);
                    array_pop($this->refsBeingParsed);
                }
            } elseif (self::preg_match('#^(?P<key>(?:![^\s]++\s++)?(?:' . Inline::REGEX_QUOTED_STRING . '|(?:!?!php/const:)?[^ \'"\[\{!].*?)) *\:(( |\t)++(?P<value>.+))?$#u', rtrim($this->currentLine), $values) && (!str_contains($values['key'], ' #') || \in_array($values['key'][0], ['"', "'"]))) {
                if (str_starts_with($values['key'], '!php/const:')) {
                    trigger_deprecation('symfony/yaml', '6.2', 'YAML syntax for key "%s" is deprecated and replaced by "!php/const %s".', $values['key'], substr($values['key'], 11));
                }
                if ($context && 'sequence' == $context) {
                    throw new ParseException('You cannot define a mapping item when in a sequence.', $this->currentLineNb + 1, $this->currentLine, $this->filename);
                }
                $context = 'mapping';
                try {
                    $key = Inline::parseScalar($values['key']);
                } catch (ParseException $e) {
                    $e->setParsedLine($this->getRealCurrentLineNb() + 1);
                    $e->setSnippet($this->currentLine);
                    throw $e;
                }
                if (!\is_string($key) && !\is_int($key)) {
                    throw new ParseException((is_numeric($key) ? 'Numeric' : 'Non-string') . ' keys are not supported. Quote your evaluable mapping keys instead.', $this->getRealCurrentLineNb() + 1, $this->currentLine);
                }
                // Convert float keys to strings, to avoid being converted to integers by PHP
                if (\is_float($key)) {
                    $key = (string) $key;
                }
                if ('<<' === $key && (!isset($values['value']) || '&' !== $values['value'][0] || !self::preg_match('#^&(?P<ref>[^ ]+)#u', $values['value'], $refMatches))) {
                    $mergeNode = \true;
                    $allowOverwrite = \true;
                    if (isset($values['value'][0]) && '*' === $values['value'][0]) {
                        $refName = substr(rtrim($values['value']), 1);
                        if (!\array_key_exists($refName, $this->refs)) {
                            if (\false !== $pos = array_search($refName, $this->refsBeingParsed, \true)) {
                                throw new ParseException(\sprintf('Circular reference [%s] detected for reference "%s".', implode(', ', array_merge(\array_slice($this->refsBeingParsed, $pos), [$refName])), $refName), $this->currentLineNb + 1, $this->currentLine, $this->filename);
                            }
                            throw new ParseException(\sprintf('Reference "%s" does not exist.', $refName), $this->getRealCurrentLineNb() + 1, $this->currentLine, $this->filename);
                        }
                        $refValue = $this->refs[$refName];
                        if (Yaml::PARSE_OBJECT_FOR_MAP & $flags && $refValue instanceof \stdClass) {
                            $refValue = (array) $refValue;
                        }
                        if (!\is_array($refValue)) {
                            throw new ParseException('YAML merge keys used with a scalar value instead of an array.', $this->getRealCurrentLineNb() + 1, $this->currentLine, $this->filename);
                        }
                        $data += $refValue;
                        // array union
                    } else {
                        if (isset($values['value']) && '' !== $values['value']) {
                            $value = $values['value'];
                        } else {
                            $value = $this->getNextEmbedBlock();
                        }
                        $parsed = $this->parseBlock($this->getRealCurrentLineNb() + 1, $value, $flags);
                        if (Yaml::PARSE_OBJECT_FOR_MAP & $flags && $parsed instanceof \stdClass) {
                            $parsed = (array) $parsed;
                        }
                        if (!\is_array($parsed)) {
                            throw new ParseException('YAML merge keys used with a scalar value instead of an array.', $this->getRealCurrentLineNb() + 1, $this->currentLine, $this->filename);
                        }
                        if (isset($parsed[0])) {
                            // If the value associated with the merge key is a sequence, then this sequence is expected to contain mapping nodes
                            // and each of these nodes is merged in turn according to its order in the sequence. Keys in mapping nodes earlier
                            // in the sequence override keys specified in later mapping nodes.
                            foreach ($parsed as $parsedItem) {
                                if (Yaml::PARSE_OBJECT_FOR_MAP & $flags && $parsedItem instanceof \stdClass) {
                                    $parsedItem = (array) $parsedItem;
                                }
                                if (!\is_array($parsedItem)) {
                                    throw new ParseException('Merge items must be arrays.', $this->getRealCurrentLineNb() + 1, $parsedItem, $this->filename);
                                }
                                $data += $parsedItem;
                                // array union
                            }
                        } else {
                            // If the value associated with the key is a single mapping node, each of its key/value pairs is inserted into the
                            // current mapping, unless the key already exists in it.
                            $data += $parsed;
                            // array union
                        }
                    }
                } elseif ('<<' !== $key && isset($values['value']) && '&' === $values['value'][0] && self::preg_match(self::REFERENCE_PATTERN, $values['value'], $matches)) {
                    $isRef = $matches['ref'];
                    $this->refsBeingParsed[] = $isRef;
                    $values['value'] = $matches['value'];
                }
                $subTag = null;
                if ($mergeNode) {
                    // Merge keys
                } elseif (!isset($values['value']) || '' === $values['value'] || str_starts_with($values['value'], '#') || null !== ($subTag = $this->getLineTag($values['value'], $flags)) || '<<' === $key) {
                    // hash
                    // if next line is less indented or equal, then it means that the current value is null
                    if (!$this->isNextLineIndented() && !$this->isNextLineUnIndentedCollection()) {
                        // Spec: Keys MUST be unique; first one wins.
                        // But overwriting is allowed when a merge node is used in current block.
                        if ($allowOverwrite || !isset($data[$key])) {
                            if (null !== $subTag) {
                                $data[$key] = new TaggedValue($subTag, '');
                            } else {
                                $data[$key] = null;
                            }
                        } else {
                            throw new ParseException(\sprintf('Duplicate key "%s" detected.', $key), $this->getRealCurrentLineNb() + 1, $this->currentLine);
                        }
                    } else {
                        // remember the parsed line number here in case we need it to provide some contexts in error messages below
                        $realCurrentLineNbKey = $this->getRealCurrentLineNb();
                        $value = $this->parseBlock($this->getRealCurrentLineNb() + 1, $this->getNextEmbedBlock(), $flags);
                        if ('<<' === $key) {
                            $this->refs[$refMatches['ref']] = $value;
                            if (Yaml::PARSE_OBJECT_FOR_MAP & $flags && $value instanceof \stdClass) {
                                $value = (array) $value;
                            }
                            $data += $value;
                        } elseif ($allowOverwrite || !isset($data[$key])) {
                            // Spec: Keys MUST be unique; first one wins.
                            // But overwriting is allowed when a merge node is used in current block.
                            if (null !== $subTag) {
                                $data[$key] = new TaggedValue($subTag, $value);
                            } else {
                                $data[$key] = $value;
                            }
                        } else {
                            throw new ParseException(\sprintf('Duplicate key "%s" detected.', $key), $realCurrentLineNbKey + 1, $this->currentLine);
                        }
                    }
                } else {
                    $value = $this->parseValue(rtrim($values['value']), $flags, $context);
                    // Spec: Keys MUST be unique; first one wins.
                    // But overwriting is allowed when a merge node is used in current block.
                    if ($allowOverwrite || !isset($data[$key])) {
                        $data[$key] = $value;
                    } else {
                        throw new ParseException(\sprintf('Duplicate key "%s" detected.', $key), $this->getRealCurrentLineNb() + 1, $this->currentLine);
                    }
                }
                if ($isRef) {
                    $this->refs[$isRef] = $data[$key];
                    array_pop($this->refsBeingParsed);
                }
            } elseif ('"' === $this->currentLine[0] || "'" === $this->currentLine[0]) {
                if (null !== $context) {
                    throw new ParseException('Unable to parse.', $this->getRealCurrentLineNb() + 1, $this->currentLine, $this->filename);
                }
                try {
                    return Inline::parse($this->lexInlineQuotedString(), $flags, $this->refs);
                } catch (ParseException $e) {
                    $e->setParsedLine($this->getRealCurrentLineNb() + 1);
                    $e->setSnippet($this->currentLine);
                    throw $e;
                }
            } elseif ('{' === $this->currentLine[0]) {
                if (null !== $context) {
                    throw new ParseException('Unable to parse.', $this->getRealCurrentLineNb() + 1, $this->currentLine, $this->filename);
                }
                try {
                    $parsedMapping = Inline::parse($this->lexInlineMapping(), $flags, $this->refs);
                    while ($this->moveToNextLine()) {
                        if (!$this->isCurrentLineEmpty()) {
                            throw new ParseException('Unable to parse.', $this->getRealCurrentLineNb() + 1, $this->currentLine, $this->filename);
                        }
                    }
                    return $parsedMapping;
                } catch (ParseException $e) {
                    $e->setParsedLine($this->getRealCurrentLineNb() + 1);
                    $e->setSnippet($this->currentLine);
                    throw $e;
                }
            } elseif ('[' === $this->currentLine[0]) {
                if (null !== $context) {
                    throw new ParseException('Unable to parse.', $this->getRealCurrentLineNb() + 1, $this->currentLine, $this->filename);
                }
                try {
                    $parsedSequence = Inline::parse($this->lexInlineSequence(), $flags, $this->refs);
                    while ($this->moveToNextLine()) {
                        if (!$this->isCurrentLineEmpty()) {
                            throw new ParseException('Unable to parse.', $this->getRealCurrentLineNb() + 1, $this->currentLine, $this->filename);
                        }
                    }
                    return $parsedSequence;
                } catch (ParseException $e) {
                    $e->setParsedLine($this->getRealCurrentLineNb() + 1);
                    $e->setSnippet($this->currentLine);
                    throw $e;
                }
            } else {
                // multiple documents are not supported
                if ('---' === $this->currentLine) {
                    throw new ParseException('Multiple documents are not supported.', $this->currentLineNb + 1, $this->currentLine, $this->filename);
                }
                if ($deprecatedUsage = isset($this->currentLine[1]) && '?' === $this->currentLine[0] && ' ' === $this->currentLine[1]) {
                    throw new ParseException('Complex mappings are not supported.', $this->getRealCurrentLineNb() + 1, $this->currentLine);
                }
                // 1-liner optionally followed by newline(s)
                if (\is_string($value) && $this->lines[0] === trim($value)) {
                    try {
                        $value = Inline::parse($this->lines[0], $flags, $this->refs);
                    } catch (ParseException $e) {
                        $e->setParsedLine($this->getRealCurrentLineNb() + 1);
                        $e->setSnippet($this->currentLine);
                        throw $e;
                    }
                    return $value;
                }
                // try to parse the value as a multi-line string as a last resort
                if (0 === $this->currentLineNb) {
                    $previousLineWasNewline = \false;
                    $previousLineWasTerminatedWithBackslash = \false;
                    $value = '';
                    foreach ($this->lines as $line) {
                        $trimmedLine = trim($line);
                        if ('#' === ($trimmedLine[0] ?? '')) {
                            continue;
                        }
                        // If the indentation is not consistent at offset 0, it is to be considered as a ParseError
                        if (0 === $this->offset && !$deprecatedUsage && isset($line[0]) && ' ' === $line[0]) {
                            throw new ParseException('Unable to parse.', $this->getRealCurrentLineNb() + 1, $this->currentLine, $this->filename);
                        }
                        if (str_contains($line, ': ')) {
                            throw new ParseException('Mapping values are not allowed in multi-line blocks.', $this->getRealCurrentLineNb() + 1, $this->currentLine, $this->filename);
                        }
                        if ('' === $trimmedLine) {
                            $value .= "\n";
                        } elseif (!$previousLineWasNewline && !$previousLineWasTerminatedWithBackslash) {
                            $value .= ' ';
                        }
                        if ('' !== $trimmedLine && str_ends_with($line, '\\')) {
                            $value .= ltrim(substr($line, 0, -1));
                        } elseif ('' !== $trimmedLine) {
                            $value .= $trimmedLine;
                        }
                        if ('' === $trimmedLine) {
                            $previousLineWasNewline = \true;
                            $previousLineWasTerminatedWithBackslash = \false;
                        } elseif (str_ends_with($line, '\\')) {
                            $previousLineWasNewline = \false;
                            $previousLineWasTerminatedWithBackslash = \true;
                        } else {
                            $previousLineWasNewline = \false;
                            $previousLineWasTerminatedWithBackslash = \false;
                        }
                    }
                    try {
                        return Inline::parse(trim($value));
                    } catch (ParseException) {
                        // fall-through to the ParseException thrown below
                    }
                }
                throw new ParseException('Unable to parse.', $this->getRealCurrentLineNb() + 1, $this->currentLine, $this->filename);
            }
        } while ($this->moveToNextLine());
        if (null !== $tag) {
            $data = new TaggedValue($tag, $data);
        }
        if (Yaml::PARSE_OBJECT_FOR_MAP & $flags && 'mapping' === $context && !\is_object($data)) {
            $object = new \stdClass();
            foreach ($data as $key => $value) {
                $object->{$key} = $value;
            }
            $data = $object;
        }
        return empty($data) ? null : $data;
    }
    private function parseBlock(int $offset, string $yaml, int $flags): mixed
    {
        $skippedLineNumbers = $this->skippedLineNumbers;
        foreach ($this->locallySkippedLineNumbers as $lineNumber) {
            if ($lineNumber < $offset) {
                continue;
            }
            $skippedLineNumbers[] = $lineNumber;
        }
        $parser = new self();
        $parser->offset = $offset;
        $parser->totalNumberOfLines = $this->totalNumberOfLines;
        $parser->skippedLineNumbers = $skippedLineNumbers;
        $parser->refs =& $this->refs;
        $parser->refsBeingParsed = $this->refsBeingParsed;
        return $parser->doParse($yaml, $flags);
    }
    /**
     * Returns the current line number (takes the offset into account).
     *
     * @internal
     */
    public function getRealCurrentLineNb(): int
    {
        $realCurrentLineNumber = $this->currentLineNb + $this->offset;
        foreach ($this->skippedLineNumbers as $skippedLineNumber) {
            if ($skippedLineNumber > $realCurrentLineNumber) {
                break;
            }
            ++$realCurrentLineNumber;
        }
        return $realCurrentLineNumber;
    }
    private function getCurrentLineIndentation(): int
    {
        if (' ' !== ($this->currentLine[0] ?? '')) {
            return 0;
        }
        return \strlen($this->currentLine) - \strlen(ltrim($this->currentLine, ' '));
    }
    /**
     * Returns the next embed block of YAML.
     *
     * @param int|null $indentation The indent level at which the block is to be read, or null for default
     * @param bool     $inSequence  True if the enclosing data structure is a sequence
     *
     * @throws ParseException When indentation problem are detected
     */
    private function getNextEmbedBlock(?int $indentation = null, bool $inSequence = \false): string
    {
        $oldLineIndentation = $this->getCurrentLineIndentation();
        if (!$this->moveToNextLine()) {
            return '';
        }
        if (null === $indentation) {
            $newIndent = null;
            $movements = 0;
            do {
                $EOF = \false;
                // empty and comment-like lines do not influence the indentation depth
                if ($this->isCurrentLineEmpty() || $this->isCurrentLineComment()) {
                    $EOF = !$this->moveToNextLine();
                    if (!$EOF) {
                        ++$movements;
                    }
                } else {
                    $newIndent = $this->getCurrentLineIndentation();
                }
            } while (!$EOF && null === $newIndent);
            for ($i = 0; $i < $movements; ++$i) {
                $this->moveToPreviousLine();
            }
            $unindentedEmbedBlock = $this->isStringUnIndentedCollectionItem();
            if (!$this->isCurrentLineEmpty() && 0 === $newIndent && !$unindentedEmbedBlock) {
                throw new ParseException('Indentation problem.', $this->getRealCurrentLineNb() + 1, $this->currentLine, $this->filename);
            }
        } else {
            $newIndent = $indentation;
        }
        $data = [];
        if ($this->getCurrentLineIndentation() >= $newIndent) {
            $data[] = substr($this->currentLine, $newIndent ?? 0);
        } elseif ($this->isCurrentLineEmpty() || $this->isCurrentLineComment()) {
            $data[] = $this->currentLine;
        } else {
            $this->moveToPreviousLine();
            return '';
        }
        if ($inSequence && $oldLineIndentation === $newIndent && isset($data[0][0]) && '-' === $data[0][0]) {
            // the previous line contained a dash but no item content, this line is a sequence item with the same indentation
            // and therefore no nested list or mapping
            $this->moveToPreviousLine();
            return '';
        }
        $isItUnindentedCollection = $this->isStringUnIndentedCollectionItem();
        $isItComment = $this->isCurrentLineComment();
        while ($this->moveToNextLine()) {
            if ($isItComment && !$isItUnindentedCollection) {
                $isItUnindentedCollection = $this->isStringUnIndentedCollectionItem();
                $isItComment = $this->isCurrentLineComment();
            }
            $indent = $this->getCurrentLineIndentation();
            if ($isItUnindentedCollection && !$this->isCurrentLineEmpty() && !$this->isStringUnIndentedCollectionItem() && $newIndent === $indent) {
                $this->moveToPreviousLine();
                break;
            }
            if ($this->isCurrentLineBlank()) {
                $data[] = substr($this->currentLine, $newIndent ?? 0);
                continue;
            }
            if ($indent >= $newIndent) {
                $data[] = substr($this->currentLine, $newIndent ?? 0);
            } elseif ($this->isCurrentLineComment()) {
                $data[] = $this->currentLine;
            } elseif (0 == $indent) {
                $this->moveToPreviousLine();
                break;
            } else {
                throw new ParseException('Indentation problem.', $this->getRealCurrentLineNb() + 1, $this->currentLine, $this->filename);
            }
        }
        return implode("\n", $data);
    }
    private function hasMoreLines(): bool
    {
        return \count($this->lines) - 1 > $this->currentLineNb;
    }
    /**
     * Moves the parser to the next line.
     */
    private function moveToNextLine(): bool
    {
        if ($this->currentLineNb >= $this->numberOfParsedLines - 1) {
            return \false;
        }
        $this->currentLine = $this->lines[++$this->currentLineNb];
        return \true;
    }
    /**
     * Moves the parser to the previous line.
     */
    private function moveToPreviousLine(): bool
    {
        if ($this->currentLineNb < 1) {
            return \false;
        }
        $this->currentLine = $this->lines[--$this->currentLineNb];
        return \true;
    }
    /**
     * Parses a YAML value.
     *
     * @param string $value   A YAML value
     * @param int    $flags   A bit field of Yaml::PARSE_* constants to customize the YAML parser behavior
     * @param string $context The parser context (either sequence or mapping)
     *
     * @throws ParseException When reference does not exist
     */
    private function parseValue(string $value, int $flags, string $context): mixed
    {
        if (str_starts_with($value, '*')) {
            if (\false !== $pos = strpos($value, '#')) {
                $value = substr($value, 1, $pos - 2);
            } else {
                $value = substr($value, 1);
            }
            if (!\array_key_exists($value, $this->refs)) {
                if (\false !== $pos = array_search($value, $this->refsBeingParsed, \true)) {
                    throw new ParseException(\sprintf('Circular reference [%s] detected for reference "%s".', implode(', ', array_merge(\array_slice($this->refsBeingParsed, $pos), [$value])), $value), $this->currentLineNb + 1, $this->currentLine, $this->filename);
                }
                throw new ParseException(\sprintf('Reference "%s" does not exist.', $value), $this->currentLineNb + 1, $this->currentLine, $this->filename);
            }
            return $this->refs[$value];
        }
        if (\in_array($value[0], ['!', '|', '>'], \true) && self::preg_match('/^(?:' . self::TAG_PATTERN . ' +)?' . self::BLOCK_SCALAR_HEADER_PATTERN . '$/', $value, $matches)) {
            $modifiers = $matches['modifiers'] ?? '';
            $data = $this->parseBlockScalar($matches['separator'], preg_replace('#\d+#', '', $modifiers), abs((int) $modifiers));
            if ('' !== $matches['tag'] && '!' !== $matches['tag']) {
                if ('!!binary' === $matches['tag']) {
                    return Inline::evaluateBinaryScalar($data);
                }
                return new TaggedValue(substr($matches['tag'], 1), $data);
            }
            return $data;
        }
        try {
            if ('' !== $value && '{' === $value[0]) {
                $cursor = \strlen(rtrim($this->currentLine)) - \strlen(rtrim($value));
                return Inline::parse($this->lexInlineMapping($cursor), $flags, $this->refs);
            } elseif ('' !== $value && '[' === $value[0]) {
                $cursor = \strlen(rtrim($this->currentLine)) - \strlen(rtrim($value));
                return Inline::parse($this->lexInlineSequence($cursor), $flags, $this->refs);
            }
            switch ($value[0] ?? '') {
                case '"':
                case "'":
                    $cursor = \strlen(rtrim($this->currentLine)) - \strlen(rtrim($value));
                    $parsedValue = Inline::parse($this->lexInlineQuotedString($cursor), $flags, $this->refs);
                    if (isset($this->currentLine[$cursor]) && preg_replace('/\s*(#.*)?$/A', '', substr($this->currentLine, $cursor))) {
                        throw new ParseException(\sprintf('Unexpected characters near "%s".', substr($this->currentLine, $cursor)));
                    }
                    return $parsedValue;
                default:
                    $lines = [];
                    while ($this->moveToNextLine()) {
                        // unquoted strings end before the first unindented line
                        if (0 === $this->getCurrentLineIndentation()) {
                            $this->moveToPreviousLine();
                            break;
                        }
                        if ($this->isCurrentLineComment()) {
                            break;
                        }
                        if ('mapping' === $context && str_contains($this->currentLine, ': ') && !$this->isCurrentLineComment()) {
                            throw new ParseException('A colon cannot be used in an unquoted mapping value.', $this->getRealCurrentLineNb() + 1, $this->currentLine, $this->filename);
                        }
                        $lines[] = trim($this->currentLine);
                    }
                    for ($i = 0, $linesCount = \count($lines), $previousLineBlank = \false; $i < $linesCount; ++$i) {
                        if ('' === $lines[$i]) {
                            $value .= "\n";
                            $previousLineBlank = \true;
                        } elseif ($previousLineBlank) {
                            $value .= $lines[$i];
                            $previousLineBlank = \false;
                        } else {
                            $value .= ' ' . $lines[$i];
                            $previousLineBlank = \false;
                        }
                    }
                    Inline::$parsedLineNumber = $this->getRealCurrentLineNb();
                    $parsedValue = Inline::parse($value, $flags, $this->refs);
                    if ('mapping' === $context && \is_string($parsedValue) && '"' !== $value[0] && "'" !== $value[0] && '[' !== $value[0] && '{' !== $value[0] && '!' !== $value[0] && str_contains($parsedValue, ': ')) {
                        throw new ParseException('A colon cannot be used in an unquoted mapping value.', $this->getRealCurrentLineNb() + 1, $value, $this->filename);
                    }
                    return $parsedValue;
            }
        } catch (ParseException $e) {
            $e->setParsedLine($this->getRealCurrentLineNb() + 1);
            $e->setSnippet($this->currentLine);
            throw $e;
        }
    }
    /**
     * Parses a block scalar.
     *
     * @param string $style       The style indicator that was used to begin this block scalar (| or >)
     * @param string $chomping    The chomping indicator that was used to begin this block scalar (+ or -)
     * @param int    $indentation The indentation indicator that was used to begin this block scalar
     */
    private function parseBlockScalar(string $style, string $chomping = '', int $indentation = 0): string
    {
        $notEOF = $this->moveToNextLine();
        if (!$notEOF) {
            return '';
        }
        $isCurrentLineBlank = $this->isCurrentLineBlank();
        $blockLines = [];
        // leading blank lines are consumed before determining indentation
        while ($notEOF && $isCurrentLineBlank) {
            // newline only if not EOF
            if ($notEOF = $this->moveToNextLine()) {
                $blockLines[] = '';
                $isCurrentLineBlank = $this->isCurrentLineBlank();
            }
        }
        // determine indentation if not specified
        if (0 === $indentation) {
            $currentLineLength = \strlen($this->currentLine);
            for ($i = 0; $i < $currentLineLength && ' ' === $this->currentLine[$i]; ++$i) {
                ++$indentation;
            }
        }
        if ($indentation > 0) {
            $pattern = \sprintf('/^ {%d}(.*)$/', $indentation);
            while ($notEOF && ($isCurrentLineBlank || self::preg_match($pattern, $this->currentLine, $matches))) {
                if ($isCurrentLineBlank && \strlen($this->currentLine) > $indentation) {
                    $blockLines[] = substr($this->currentLine, $indentation);
                } elseif ($isCurrentLineBlank) {
                    $blockLines[] = '';
                } else {
                    $blockLines[] = $matches[1];
                }
                // newline only if not EOF
                if ($notEOF = $this->moveToNextLine()) {
                    $isCurrentLineBlank = $this->isCurrentLineBlank();
                }
            }
        } elseif ($notEOF) {
            $blockLines[] = '';
        }
        if ($notEOF) {
            $blockLines[] = '';
            $this->moveToPreviousLine();
        } elseif (!$notEOF && !$this->isCurrentLineLastLineInDocument()) {
            $blockLines[] = '';
        }
        // folded style
        if ('>' === $style) {
            $text = '';
            $previousLineIndented = \false;
            $previousLineBlank = \false;
            for ($i = 0, $blockLinesCount = \count($blockLines); $i < $blockLinesCount; ++$i) {
                if ('' === $blockLines[$i]) {
                    $text .= "\n";
                    $previousLineIndented = \false;
                    $previousLineBlank = \true;
                } elseif (' ' === $blockLines[$i][0]) {
                    $text .= "\n" . $blockLines[$i];
                    $previousLineIndented = \true;
                    $previousLineBlank = \false;
                } elseif ($previousLineIndented) {
                    $text .= "\n" . $blockLines[$i];
                    $previousLineIndented = \false;
                    $previousLineBlank = \false;
                } elseif ($previousLineBlank || 0 === $i) {
                    $text .= $blockLines[$i];
                    $previousLineIndented = \false;
                    $previousLineBlank = \false;
                } else {
                    $text .= ' ' . $blockLines[$i];
                    $previousLineIndented = \false;
                    $previousLineBlank = \false;
                }
            }
        } else {
            $text = implode("\n", $blockLines);
        }
        // deal with trailing newlines
        if ('' === $chomping) {
            $text = preg_replace('/\n+$/', "\n", $text);
        } elseif ('-' === $chomping) {
            $text = preg_replace('/\n+$/', '', $text);
        }
        return $text;
    }
    /**
     * Returns true if the next line is indented.
     */
    private function isNextLineIndented(): bool
    {
        $currentIndentation = $this->getCurrentLineIndentation();
        $movements = 0;
        do {
            $EOF = !$this->moveToNextLine();
            if (!$EOF) {
                ++$movements;
            }
        } while (!$EOF && ($this->isCurrentLineEmpty() || $this->isCurrentLineComment()));
        if ($EOF) {
            for ($i = 0; $i < $movements; ++$i) {
                $this->moveToPreviousLine();
            }
            return \false;
        }
        $ret = $this->getCurrentLineIndentation() > $currentIndentation;
        for ($i = 0; $i < $movements; ++$i) {
            $this->moveToPreviousLine();
        }
        return $ret;
    }
    private function isCurrentLineEmpty(): bool
    {
        return $this->isCurrentLineBlank() || $this->isCurrentLineComment();
    }
    private function isCurrentLineBlank(): bool
    {
        return '' === $this->currentLine || '' === trim($this->currentLine, ' ');
    }
    private function isCurrentLineComment(): bool
    {
        // checking explicitly the first char of the trim is faster than loops or strpos
        $ltrimmedLine = '' !== $this->currentLine && ' ' === $this->currentLine[0] ? ltrim($this->currentLine, ' ') : $this->currentLine;
        return '' !== $ltrimmedLine && '#' === $ltrimmedLine[0];
    }
    private function isCurrentLineLastLineInDocument(): bool
    {
        return $this->offset + $this->currentLineNb >= $this->totalNumberOfLines - 1;
    }
    private function cleanup(string $value): string
    {
        $value = str_replace(["\r\n", "\r"], "\n", $value);
        // strip YAML header
        $count = 0;
        $value = preg_replace('#^\%YAML[: ][\d\.]+.*\n#u', '', $value, -1, $count);
        $this->offset += $count;
        // remove leading comments
        $trimmedValue = preg_replace('#^(\#.*?\n)+#s', '', $value, -1, $count);
        if (1 === $count) {
            // items have been removed, update the offset
            $this->offset += substr_count($value, "\n") - substr_count($trimmedValue, "\n");
            $value = $trimmedValue;
        }
        // remove start of the document marker (---)
        $trimmedValue = preg_replace('#^\-\-\-.*?\n#s', '', $value, -1, $count);
        if (1 === $count) {
            // items have been removed, update the offset
            $this->offset += substr_count($value, "\n") - substr_count($trimmedValue, "\n");
            $value = $trimmedValue;
            // remove end of the document marker (...)
            $value = preg_replace('#\.\.\.\s*$#', '', $value);
        }
        return $value;
    }
    private function isNextLineUnIndentedCollection(): bool
    {
        $currentIndentation = $this->getCurrentLineIndentation();
        $movements = 0;
        do {
            $EOF = !$this->moveToNextLine();
            if (!$EOF) {
                ++$movements;
            }
        } while (!$EOF && ($this->isCurrentLineEmpty() || $this->isCurrentLineComment()));
        if ($EOF) {
            return \false;
        }
        $ret = $this->getCurrentLineIndentation() === $currentIndentation && $this->isStringUnIndentedCollectionItem();
        for ($i = 0; $i < $movements; ++$i) {
            $this->moveToPreviousLine();
        }
        return $ret;
    }
    private function isStringUnIndentedCollectionItem(): bool
    {
        return '-' === rtrim($this->currentLine) || str_starts_with($this->currentLine, '- ');
    }
    /**
     * A local wrapper for "preg_match" which will throw a ParseException if there
     * is an internal error in the PCRE engine.
     *
     * This avoids us needing to check for "false" every time PCRE is used
     * in the YAML engine
     *
     * @throws ParseException on a PCRE internal error
     *
     * @internal
     */
    public static function preg_match(string $pattern, string $subject, ?array &$matches = null, int $flags = 0, int $offset = 0): int
    {
        if (\false === $ret = preg_match($pattern, $subject, $matches, $flags, $offset)) {
            throw new ParseException(preg_last_error_msg());
        }
        return $ret;
    }
    /**
     * Trim the tag on top of the value.
     *
     * Prevent values such as "!foo {quz: bar}" to be considered as
     * a mapping block.
     */
    private function trimTag(string $value): string
    {
        if ('!' === $value[0]) {
            return ltrim(substr($value, 1, strcspn($value, " \r\n", 1)), ' ');
        }
        return $value;
    }
    private function getLineTag(string $value, int $flags, bool $nextLineCheck = \true): ?string
    {
        if ('' === $value || '!' !== $value[0] || 1 !== self::preg_match('/^' . self::TAG_PATTERN . ' *( +#.*)?$/', $value, $matches)) {
            return null;
        }
        if ($nextLineCheck && !$this->isNextLineIndented()) {
            return null;
        }
        $tag = substr($matches['tag'], 1);
        // Built-in tags
        if ($tag && '!' === $tag[0]) {
            throw new ParseException(\sprintf('The built-in tag "!%s" is not implemented.', $tag), $this->getRealCurrentLineNb() + 1, $value, $this->filename);
        }
        if (Yaml::PARSE_CUSTOM_TAGS & $flags) {
            return $tag;
        }
        throw new ParseException(\sprintf('Tags support is not enabled. You must use the flag "Yaml::PARSE_CUSTOM_TAGS" to use "%s".', $matches['tag']), $this->getRealCurrentLineNb() + 1, $value, $this->filename);
    }
    private function lexInlineQuotedString(int &$cursor = 0): string
    {
        $quotation = $this->currentLine[$cursor];
        $value = $quotation;
        ++$cursor;
        $previousLineWasNewline = \true;
        $previousLineWasTerminatedWithBackslash = \false;
        $lineNumber = 0;
        do {
            if (++$lineNumber > 1) {
                $cursor += strspn($this->currentLine, ' ', $cursor);
            }
            if ($this->isCurrentLineBlank()) {
                $value .= "\n";
            } elseif (!$previousLineWasNewline && !$previousLineWasTerminatedWithBackslash) {
                $value .= ' ';
            }
            for (; \strlen($this->currentLine) > $cursor; ++$cursor) {
                switch ($this->currentLine[$cursor]) {
                    case '\\':
                        if ("'" === $quotation) {
                            $value .= '\\';
                        } elseif (isset($this->currentLine[++$cursor])) {
                            $value .= '\\' . $this->currentLine[$cursor];
                        }
                        break;
                    case $quotation:
                        ++$cursor;
                        if ("'" === $quotation && isset($this->currentLine[$cursor]) && "'" === $this->currentLine[$cursor]) {
                            $value .= "''";
                            break;
                        }
                        return $value . $quotation;
                    default:
                        $value .= $this->currentLine[$cursor];
                }
            }
            if ($this->isCurrentLineBlank()) {
                $previousLineWasNewline = \true;
                $previousLineWasTerminatedWithBackslash = \false;
            } elseif ('\\' === $this->currentLine[-1]) {
                $previousLineWasNewline = \false;
                $previousLineWasTerminatedWithBackslash = \true;
            } else {
                $previousLineWasNewline = \false;
                $previousLineWasTerminatedWithBackslash = \false;
            }
            if ($this->hasMoreLines()) {
                $cursor = 0;
            }
        } while ($this->moveToNextLine());
        throw new ParseException('Malformed inline YAML string.');
    }
    private function lexUnquotedString(int &$cursor): string
    {
        $offset = $cursor;
        while ($cursor < \strlen($this->currentLine)) {
            if (\in_array($this->currentLine[$cursor], ['[', ']', '{', '}', ',', ':'], \true)) {
                break;
            }
            if (\in_array($this->currentLine[$cursor], [' ', "\t"], \true) && '#' === ($this->currentLine[$cursor + 1] ?? '')) {
                break;
            }
            ++$cursor;
        }
        if ($cursor === $offset) {
            throw new ParseException('Malformed unquoted YAML string.');
        }
        return substr($this->currentLine, $offset, $cursor - $offset);
    }
    private function lexInlineMapping(int &$cursor = 0, bool $consumeUntilEol = \true): string
    {
        return $this->lexInlineStructure($cursor, '}', $consumeUntilEol);
    }
    private function lexInlineSequence(int &$cursor = 0, bool $consumeUntilEol = \true): string
    {
        return $this->lexInlineStructure($cursor, ']', $consumeUntilEol);
    }
    private function lexInlineStructure(int &$cursor, string $closingTag, bool $consumeUntilEol = \true): string
    {
        $value = $this->currentLine[$cursor];
        ++$cursor;
        do {
            $this->consumeWhitespaces($cursor);
            while (isset($this->currentLine[$cursor])) {
                switch ($this->currentLine[$cursor]) {
                    case '"':
                    case "'":
                        $value .= $this->lexInlineQuotedString($cursor);
                        break;
                    case ':':
                    case ',':
                        $value .= $this->currentLine[$cursor];
                        ++$cursor;
                        break;
                    case '{':
                        $value .= $this->lexInlineMapping($cursor, \false);
                        break;
                    case '[':
                        $value .= $this->lexInlineSequence($cursor, \false);
                        break;
                    case $closingTag:
                        $value .= $this->currentLine[$cursor];
                        ++$cursor;
                        if ($consumeUntilEol && isset($this->currentLine[$cursor]) && ($whitespaces = strspn($this->currentLine, ' ', $cursor) + $cursor) < \strlen($this->currentLine) && '#' !== $this->currentLine[$whitespaces]) {
                            throw new ParseException(\sprintf('Unexpected token "%s".', trim(substr($this->currentLine, $cursor))));
                        }
                        return $value;
                    case '#':
                        break 2;
                    default:
                        $value .= $this->lexUnquotedString($cursor);
                }
                if ($this->consumeWhitespaces($cursor)) {
                    $value .= ' ';
                }
            }
            if ($this->hasMoreLines()) {
                $cursor = 0;
            }
        } while ($this->moveToNextLine());
        throw new ParseException('Malformed inline YAML string.');
    }
    private function consumeWhitespaces(int &$cursor): bool
    {
        $whitespacesConsumed = 0;
        do {
            $whitespaceOnlyTokenLength = strspn($this->currentLine, " \t", $cursor);
            $whitespacesConsumed += $whitespaceOnlyTokenLength;
            $cursor += $whitespaceOnlyTokenLength;
            if (isset($this->currentLine[$cursor])) {
                return 0 < $whitespacesConsumed;
            }
            if ($this->hasMoreLines()) {
                $cursor = 0;
            }
        } while ($this->moveToNextLine());
        return 0 < $whitespacesConsumed;
    }
}
CHANGELOG
=========

6.3
---

 * Add support to dump int keys as strings by using the `Yaml::DUMP_NUMERIC_KEY_AS_STRING` flag

6.2
---

 * Add support for `!php/enum` and `!php/enum *->value`
 * Deprecate the `!php/const:` tag in key which will be replaced by the `!php/const` tag (without the colon) since 3.4

6.1
---

 * In cases where it will likely improve readability, strings containing single quotes will be double-quoted

5.4
---

 * Add new `lint:yaml dirname --exclude=/dirname/foo.yaml --exclude=/dirname/bar.yaml`
   option to exclude one or more specific files from multiple file list
 * Allow negatable for the parse tags option with `--no-parse-tags`

5.3
---

 * Added `github` format support & autodetection to render errors as annotations
   when running the YAML linter command in a Github Action environment.

5.1.0
-----

 * Added support for parsing numbers prefixed with `0o` as octal numbers.
 * Deprecated support for parsing numbers starting with `0` as octal numbers. They will be parsed as strings as of Symfony 6.0. Prefix numbers with `0o`
   so that they are parsed as octal numbers.

   Before:

   ```yaml
   Yaml::parse('072');
   ```

   After:

   ```yaml
   Yaml::parse('0o72');
   ```

 * Added `yaml-lint` binary.
 * Deprecated using the `!php/object` and `!php/const` tags without a value.

5.0.0
-----

 * Removed support for mappings inside multi-line strings.
 * removed support for implicit STDIN usage in the `lint:yaml` command, use `lint:yaml -` (append a dash) instead to make it explicit.

4.4.0
-----

 * Added support for parsing the inline notation spanning multiple lines.
 * Added support to dump `null` as `~` by using the `Yaml::DUMP_NULL_AS_TILDE` flag.
 * deprecated accepting STDIN implicitly when using the `lint:yaml` command, use `lint:yaml -` (append a dash) instead to make it explicit.

4.3.0
-----

 * Using a mapping inside a multi-line string is deprecated and will throw a `ParseException` in 5.0.

4.2.0
-----

 * added support for multiple files or directories in `LintCommand`

4.0.0
-----

 * The behavior of the non-specific tag `!` is changed and now forces
   non-evaluating your values.
 * complex mappings will throw a `ParseException`
 * support for the comma as a group separator for floats has been dropped, use
   the underscore instead
 * support for the `!!php/object` tag has been dropped, use the `!php/object`
   tag instead
 * duplicate mapping keys throw a `ParseException`
 * non-string mapping keys throw a `ParseException`, use the `Yaml::PARSE_KEYS_AS_STRINGS`
   flag to cast them to strings
 * `%` at the beginning of an unquoted string throw a `ParseException`
 * mappings with a colon (`:`) that is not followed by a whitespace throw a
   `ParseException`
 * the `Dumper::setIndentation()` method has been removed
 * being able to pass boolean options to the `Yaml::parse()`, `Yaml::dump()`,
   `Parser::parse()`, and `Dumper::dump()` methods to configure the behavior of
   the parser and dumper is no longer supported, pass bitmask flags instead
 * the constructor arguments of the `Parser` class have been removed
 * the `Inline` class is internal and no longer part of the BC promise
 * removed support for the `!str` tag, use the `!!str` tag instead
 * added support for tagged scalars.

   ```yml
   Yaml::parse('!foo bar', Yaml::PARSE_CUSTOM_TAGS);
   // returns TaggedValue('foo', 'bar');
   ```

3.4.0
-----

 * added support for parsing YAML files using the `Yaml::parseFile()` or `Parser::parseFile()` method

 * the `Dumper`, `Parser`, and `Yaml` classes are marked as final

 * Deprecated the `!php/object:` tag which will be replaced by the
   `!php/object` tag (without the colon) in 4.0.

 * Deprecated the `!php/const:` tag which will be replaced by the
   `!php/const` tag (without the colon) in 4.0.

 * Support for the `!str` tag is deprecated, use the `!!str` tag instead.

 * Deprecated using the non-specific tag `!` as its behavior will change in 4.0.
   It will force non-evaluating your values in 4.0. Use plain integers or `!!float` instead.

3.3.0
-----

 * Starting an unquoted string with a question mark followed by a space is
   deprecated and will throw a `ParseException` in Symfony 4.0.

 * Deprecated support for implicitly parsing non-string mapping keys as strings.
   Mapping keys that are no strings will lead to a `ParseException` in Symfony
   4.0. Use quotes to opt-in for keys to be parsed as strings.

   Before:

   ```php
   $yaml = <<<YAML
   null: null key
   true: boolean true
   2.0: float key
   YAML;

   Yaml::parse($yaml);
   ```

   After:

   ```php

   $yaml = <<<YAML
   "null": null key
   "true": boolean true
   "2.0": float key
   YAML;

   Yaml::parse($yaml);
   ```

 * Omitted mapping values will be parsed as `null`.

 * Omitting the key of a mapping is deprecated and will throw a `ParseException` in Symfony 4.0.

 * Added support for dumping empty PHP arrays as YAML sequences:

   ```php
   Yaml::dump([], 0, 0, Yaml::DUMP_EMPTY_ARRAY_AS_SEQUENCE);
   ```

3.2.0
-----

 * Mappings with a colon (`:`) that is not followed by a whitespace are deprecated
   when the mapping key is not quoted and will lead to a `ParseException` in
   Symfony 4.0 (e.g. `foo:bar` must be `foo: bar`).

 * Added support for parsing PHP constants:

   ```php
   Yaml::parse('!php/const:PHP_INT_MAX', Yaml::PARSE_CONSTANT);
   ```

 * Support for silently ignoring duplicate mapping keys in YAML has been
   deprecated and will lead to a `ParseException` in Symfony 4.0.

3.1.0
-----

 * Added support to dump `stdClass` and `ArrayAccess` objects as YAML mappings
   through the `Yaml::DUMP_OBJECT_AS_MAP` flag.

 * Strings that are not UTF-8 encoded will be dumped as base64 encoded binary
   data.

 * Added support for dumping multi line strings as literal blocks.

 * Added support for parsing base64 encoded binary data when they are tagged
   with the `!!binary` tag.

 * Added support for parsing timestamps as `\DateTime` objects:

   ```php
   Yaml::parse('2001-12-15 21:59:43.10 -5', Yaml::PARSE_DATETIME);
   ```

 * `\DateTime` and `\DateTimeImmutable` objects are dumped as YAML timestamps.

 * Deprecated usage of `%` at the beginning of an unquoted string.

 * Added support for customizing the YAML parser behavior through an optional bit field:

   ```php
   Yaml::parse('{ "foo": "bar", "fiz": "cat" }', Yaml::PARSE_EXCEPTION_ON_INVALID_TYPE | Yaml::PARSE_OBJECT | Yaml::PARSE_OBJECT_FOR_MAP);
   ```

 * Added support for customizing the dumped YAML string through an optional bit field:

   ```php
   Yaml::dump(['foo' => new A(), 'bar' => 1], 0, 0, Yaml::DUMP_EXCEPTION_ON_INVALID_TYPE | Yaml::DUMP_OBJECT);
   ```

3.0.0
-----

 * Yaml::parse() now throws an exception when a blackslash is not escaped
   in double-quoted strings

2.8.0
-----

 * Deprecated usage of a colon in an unquoted mapping value
 * Deprecated usage of @, \`, | and > at the beginning of an unquoted string
 * When surrounding strings with double-quotes, you must now escape `\` characters. Not
   escaping those characters (when surrounded by double-quotes) is deprecated.

   Before:

   ```yml
   class: "Foo\Var"
   ```

   After:

   ```yml
   class: "Foo\\Var"
   ```

2.1.0
-----

 * Yaml::parse() does not evaluate loaded files as PHP files by default
   anymore (call Yaml::enablePhpParsing() to get back the old behavior)
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Yaml;

/**
 * Escaper encapsulates escaping rules for single and double-quoted
 * YAML strings.
 *
 * @author Matthew Lewinski <matthew@lewinski.org>
 *
 * @internal
 */
class Escaper
{
    // Characters that would cause a dumped string to require double quoting.
    public const REGEX_CHARACTER_TO_ESCAPE = "[\\x00-\\x1f]||| | | ";
    // Mapping arrays for escaping a double quoted string. The backslash is
    // first to ensure proper escaping because str_replace operates iteratively
    // on the input arrays. This ordering of the characters avoids the use of strtr,
    // which performs more slowly.
    private const ESCAPEES = ['\\', '\\\\', '\"', '"', "\x00", "\x01", "\x02", "\x03", "\x04", "\x05", "\x06", "\x07", "\x08", "\t", "\n", "\v", "\f", "\r", "\x0e", "\x0f", "\x10", "\x11", "\x12", "\x13", "\x14", "\x15", "\x16", "\x17", "\x18", "\x19", "\x1a", "\x1b", "\x1c", "\x1d", "\x1e", "\x1f", "", "", " ", " ", " "];
    private const ESCAPED = ['\\\\', '\"', '\\\\', '\"', '\0', '\x01', '\x02', '\x03', '\x04', '\x05', '\x06', '\a', '\b', '\t', '\n', '\v', '\f', '\r', '\x0e', '\x0f', '\x10', '\x11', '\x12', '\x13', '\x14', '\x15', '\x16', '\x17', '\x18', '\x19', '\x1a', '\e', '\x1c', '\x1d', '\x1e', '\x1f', '\x7f', '\N', '\_', '\L', '\P'];
    /**
     * Determines if a PHP value would require double quoting in YAML.
     *
     * @param string $value A PHP value
     */
    public static function requiresDoubleQuoting(string $value): bool
    {
        return 0 < preg_match('/' . self::REGEX_CHARACTER_TO_ESCAPE . '/u', $value);
    }
    /**
     * Escapes and surrounds a PHP value with double quotes.
     *
     * @param string $value A PHP value
     */
    public static function escapeWithDoubleQuotes(string $value): string
    {
        return \sprintf('"%s"', str_replace(self::ESCAPEES, self::ESCAPED, $value));
    }
    /**
     * Determines if a PHP value would require single quoting in YAML.
     *
     * @param string $value A PHP value
     */
    public static function requiresSingleQuoting(string $value): bool
    {
        // Determines if a PHP value is entirely composed of a value that would
        // require single quoting in YAML.
        if (\in_array(strtolower($value), ['null', '~', 'true', 'false', 'y', 'n', 'yes', 'no', 'on', 'off'])) {
            return \true;
        }
        // Determines if the PHP value contains any single characters that would
        // cause it to require single quoting in YAML.
        return 0 < preg_match('/[ \s \' " \: \{ \} \[ \] , & \* \# \?] | \A[ \- ? | < > = ! % @ ` \p{Zs}]/xu', $value);
    }
    /**
     * Escapes and surrounds a PHP value with single quotes.
     *
     * @param string $value A PHP value
     */
    public static function escapeWithSingleQuotes(string $value): string
    {
        return \sprintf("'%s'", str_replace('\'', '\'\'', $value));
    }
}
#!/usr/bin/env php
<?php 
namespace _ContaoManager;

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
if ('cli' !== \PHP_SAPI) {
    throw new \Exception('This script must be run from the command line.');
}
/**
 * Runs the Yaml lint command.
 *
 * @author Jan Schädlich <jan.schaedlich@sensiolabs.de>
 */
use _ContaoManager\Symfony\Component\Console\Application;
use _ContaoManager\Symfony\Component\Yaml\Command\LintCommand;
function includeIfExists(string $file): bool
{
    return \file_exists($file) && include $file;
}
if (!includeIfExists(__DIR__ . '/../../../../autoload.php') && !includeIfExists(__DIR__ . '/../../vendor/autoload.php') && !includeIfExists(__DIR__ . '/../../../../../../vendor/autoload.php')) {
    \fwrite(\STDERR, 'Install dependencies using Composer.' . \PHP_EOL);
    exit(1);
}
if (!\class_exists(Application::class)) {
    \fwrite(\STDERR, 'You need the "symfony/console" component in order to run the Yaml linter.' . \PHP_EOL);
    exit(1);
}
(new Application())->add($command = new LintCommand())->getApplication()->setDefaultCommand($command->getName(), \true)->run();
Yaml Component
==============

The Yaml component loads and dumps YAML files.

Resources
---------

 * [Documentation](https://symfony.com/doc/current/components/yaml.html)
 * [Contributing](https://symfony.com/doc/current/contributing/index.html)
 * [Report issues](https://github.com/symfony/symfony/issues) and
   [send Pull Requests](https://github.com/symfony/symfony/pulls)
   in the [main Symfony repository](https://github.com/symfony/symfony)
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Yaml;

use _ContaoManager\Symfony\Component\Yaml\Exception\ParseException;
/**
 * Unescaper encapsulates unescaping rules for single and double-quoted
 * YAML strings.
 *
 * @author Matthew Lewinski <matthew@lewinski.org>
 *
 * @internal
 */
class Unescaper
{
    /**
     * Regex fragment that matches an escaped character in a double quoted string.
     */
    public const REGEX_ESCAPED_CHARACTER = '\\\\(x[0-9a-fA-F]{2}|u[0-9a-fA-F]{4}|U[0-9a-fA-F]{8}|.)';
    /**
     * Unescapes a single quoted string.
     *
     * @param string $value A single quoted string
     */
    public function unescapeSingleQuotedString(string $value): string
    {
        return str_replace('\'\'', '\'', $value);
    }
    /**
     * Unescapes a double quoted string.
     *
     * @param string $value A double quoted string
     */
    public function unescapeDoubleQuotedString(string $value): string
    {
        $callback = fn($match) => $this->unescapeCharacter($match[0]);
        // evaluate the string
        return preg_replace_callback('/' . self::REGEX_ESCAPED_CHARACTER . '/u', $callback, $value);
    }
    /**
     * Unescapes a character that was found in a double-quoted string.
     *
     * @param string $value An escaped character
     */
    private function unescapeCharacter(string $value): string
    {
        return match ($value[1]) {
            '0' => "\x00",
            'a' => "\x07",
            'b' => "\x08",
            't' => "\t",
            "\t" => "\t",
            'n' => "\n",
            'v' => "\v",
            'f' => "\f",
            'r' => "\r",
            'e' => "\x1b",
            ' ' => ' ',
            '"' => '"',
            '/' => '/',
            '\\' => '\\',
            // U+0085 NEXT LINE
            'N' => "",
            // U+00A0 NO-BREAK SPACE
            '_' => " ",
            // U+2028 LINE SEPARATOR
            'L' => " ",
            // U+2029 PARAGRAPH SEPARATOR
            'P' => " ",
            'x' => self::utf8chr(hexdec(substr($value, 2, 2))),
            'u' => self::utf8chr(hexdec(substr($value, 2, 4))),
            'U' => self::utf8chr(hexdec(substr($value, 2, 8))),
            default => throw new ParseException(\sprintf('Found unknown escape character "%s".', $value)),
        };
    }
    /**
     * Get the UTF-8 character for the given code point.
     */
    private static function utf8chr(int $c): string
    {
        if (0x80 > $c %= 0x200000) {
            return \chr($c);
        }
        if (0x800 > $c) {
            return \chr(0xc0 | $c >> 6) . \chr(0x80 | $c & 0x3f);
        }
        if (0x10000 > $c) {
            return \chr(0xe0 | $c >> 12) . \chr(0x80 | $c >> 6 & 0x3f) . \chr(0x80 | $c & 0x3f);
        }
        return \chr(0xf0 | $c >> 18) . \chr(0x80 | $c >> 12 & 0x3f) . \chr(0x80 | $c >> 6 & 0x3f) . \chr(0x80 | $c & 0x3f);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Yaml;

use _ContaoManager\Symfony\Component\Yaml\Tag\TaggedValue;
/**
 * Dumper dumps PHP variables to YAML strings.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 *
 * @final
 */
class Dumper
{
    /**
     * The amount of spaces to use for indentation of nested nodes.
     */
    private int $indentation;
    public function __construct(int $indentation = 4)
    {
        if ($indentation < 1) {
            throw new \InvalidArgumentException('The indentation must be greater than zero.');
        }
        $this->indentation = $indentation;
    }
    /**
     * Dumps a PHP value to YAML.
     *
     * @param mixed $input  The PHP value
     * @param int   $inline The level where you switch to inline YAML
     * @param int   $indent The level of indentation (used internally)
     * @param int   $flags  A bit field of Yaml::DUMP_* constants to customize the dumped YAML string
     */
    public function dump(mixed $input, int $inline = 0, int $indent = 0, int $flags = 0): string
    {
        $output = '';
        $prefix = $indent ? str_repeat(' ', $indent) : '';
        $dumpObjectAsInlineMap = \true;
        if (Yaml::DUMP_OBJECT_AS_MAP & $flags && ($input instanceof \ArrayObject || $input instanceof \stdClass)) {
            $dumpObjectAsInlineMap = empty((array) $input);
        }
        if ($inline <= 0 || !\is_array($input) && !$input instanceof TaggedValue && $dumpObjectAsInlineMap || empty($input)) {
            $output .= $prefix . Inline::dump($input, $flags);
        } elseif ($input instanceof TaggedValue) {
            $output .= $this->dumpTaggedValue($input, $inline, $indent, $flags, $prefix);
        } else {
            $dumpAsMap = Inline::isHash($input);
            foreach ($input as $key => $value) {
                if ('' !== $output && "\n" !== $output[-1]) {
                    $output .= "\n";
                }
                if (\is_int($key) && Yaml::DUMP_NUMERIC_KEY_AS_STRING & $flags) {
                    $key = (string) $key;
                }
                if (Yaml::DUMP_MULTI_LINE_LITERAL_BLOCK & $flags && \is_string($value) && str_contains($value, "\n") && !str_contains($value, "\r")) {
                    $blockIndentationIndicator = $this->getBlockIndentationIndicator($value);
                    if (isset($value[-2]) && "\n" === $value[-2] && "\n" === $value[-1]) {
                        $blockChompingIndicator = '+';
                    } elseif ("\n" === $value[-1]) {
                        $blockChompingIndicator = '';
                    } else {
                        $blockChompingIndicator = '-';
                    }
                    $output .= \sprintf('%s%s%s |%s%s', $prefix, $dumpAsMap ? Inline::dump($key, $flags) . ':' : '-', '', $blockIndentationIndicator, $blockChompingIndicator);
                    foreach (explode("\n", $value) as $row) {
                        if ('' === $row) {
                            $output .= "\n";
                        } else {
                            $output .= \sprintf("\n%s%s%s", $prefix, str_repeat(' ', $this->indentation), $row);
                        }
                    }
                    continue;
                }
                if ($value instanceof TaggedValue) {
                    $output .= \sprintf('%s%s !%s', $prefix, $dumpAsMap ? Inline::dump($key, $flags) . ':' : '-', $value->getTag());
                    if (Yaml::DUMP_MULTI_LINE_LITERAL_BLOCK & $flags && \is_string($value->getValue()) && str_contains($value->getValue(), "\n") && !str_contains($value->getValue(), "\r\n")) {
                        $blockIndentationIndicator = $this->getBlockIndentationIndicator($value->getValue());
                        $output .= \sprintf(' |%s', $blockIndentationIndicator);
                        foreach (explode("\n", $value->getValue()) as $row) {
                            $output .= \sprintf("\n%s%s%s", $prefix, str_repeat(' ', $this->indentation), $row);
                        }
                        continue;
                    }
                    if ($inline - 1 <= 0 || null === $value->getValue() || \is_scalar($value->getValue())) {
                        $output .= ' ' . $this->dump($value->getValue(), $inline - 1, 0, $flags) . "\n";
                    } else {
                        $output .= "\n";
                        $output .= $this->dump($value->getValue(), $inline - 1, $dumpAsMap ? $indent + $this->indentation : $indent + 2, $flags);
                    }
                    continue;
                }
                $dumpObjectAsInlineMap = \true;
                if (Yaml::DUMP_OBJECT_AS_MAP & $flags && ($value instanceof \ArrayObject || $value instanceof \stdClass)) {
                    $dumpObjectAsInlineMap = empty((array) $value);
                }
                $willBeInlined = $inline - 1 <= 0 || !\is_array($value) && $dumpObjectAsInlineMap || empty($value);
                $output .= \sprintf('%s%s%s%s', $prefix, $dumpAsMap ? Inline::dump($key, $flags) . ':' : '-', $willBeInlined ? ' ' : "\n", $this->dump($value, $inline - 1, $willBeInlined ? 0 : $indent + $this->indentation, $flags)) . ($willBeInlined ? "\n" : '');
            }
        }
        return $output;
    }
    private function dumpTaggedValue(TaggedValue $value, int $inline, int $indent, int $flags, string $prefix): string
    {
        $output = \sprintf('%s!%s', $prefix ? $prefix . ' ' : '', $value->getTag());
        if (Yaml::DUMP_MULTI_LINE_LITERAL_BLOCK & $flags && \is_string($value->getValue()) && str_contains($value->getValue(), "\n") && !str_contains($value->getValue(), "\r\n")) {
            $blockIndentationIndicator = $this->getBlockIndentationIndicator($value->getValue());
            $output .= \sprintf(' |%s', $blockIndentationIndicator);
            foreach (explode("\n", $value->getValue()) as $row) {
                $output .= \sprintf("\n%s%s%s", $prefix, str_repeat(' ', $this->indentation), $row);
            }
            return $output;
        }
        if ($inline - 1 <= 0 || null === $value->getValue() || \is_scalar($value->getValue())) {
            return $output . ' ' . $this->dump($value->getValue(), $inline - 1, 0, $flags) . "\n";
        }
        return $output . "\n" . $this->dump($value->getValue(), $inline - 1, $indent, $flags);
    }
    private function getBlockIndentationIndicator(string $value): string
    {
        $lines = explode("\n", $value);
        // If the first line (that is neither empty nor contains only spaces)
        // starts with a space character, the spec requires a block indentation indicator
        // http://www.yaml.org/spec/1.2/spec.html#id2793979
        foreach ($lines as $line) {
            if ('' !== trim($line, ' ')) {
                return ' ' === substr($line, 0, 1) ? (string) $this->indentation : '';
            }
        }
        return '';
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Yaml;

use _ContaoManager\Symfony\Component\Yaml\Exception\DumpException;
use _ContaoManager\Symfony\Component\Yaml\Exception\ParseException;
use _ContaoManager\Symfony\Component\Yaml\Tag\TaggedValue;
/**
 * Inline implements a YAML parser/dumper for the YAML inline syntax.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 *
 * @internal
 */
class Inline
{
    public const REGEX_QUOTED_STRING = '(?:"([^"\\\\]*+(?:\\\\.[^"\\\\]*+)*+)"|\'([^\']*+(?:\'\'[^\']*+)*+)\')';
    public static int $parsedLineNumber = -1;
    public static ?string $parsedFilename = null;
    private static bool $exceptionOnInvalidType = \false;
    private static bool $objectSupport = \false;
    private static bool $objectForMap = \false;
    private static bool $constantSupport = \false;
    public static function initialize(int $flags, ?int $parsedLineNumber = null, ?string $parsedFilename = null): void
    {
        self::$exceptionOnInvalidType = (bool) (Yaml::PARSE_EXCEPTION_ON_INVALID_TYPE & $flags);
        self::$objectSupport = (bool) (Yaml::PARSE_OBJECT & $flags);
        self::$objectForMap = (bool) (Yaml::PARSE_OBJECT_FOR_MAP & $flags);
        self::$constantSupport = (bool) (Yaml::PARSE_CONSTANT & $flags);
        self::$parsedFilename = $parsedFilename;
        if (null !== $parsedLineNumber) {
            self::$parsedLineNumber = $parsedLineNumber;
        }
    }
    /**
     * Converts a YAML string to a PHP value.
     *
     * @param int   $flags      A bit field of Yaml::PARSE_* constants to customize the YAML parser behavior
     * @param array $references Mapping of variable names to values
     *
     * @throws ParseException
     */
    public static function parse(string $value, int $flags = 0, array &$references = []): mixed
    {
        self::initialize($flags);
        $value = trim($value);
        if ('' === $value) {
            return '';
        }
        $i = 0;
        $tag = self::parseTag($value, $i, $flags);
        switch ($value[$i]) {
            case '[':
                $result = self::parseSequence($value, $flags, $i, $references);
                ++$i;
                break;
            case '{':
                $result = self::parseMapping($value, $flags, $i, $references);
                ++$i;
                break;
            default:
                $result = self::parseScalar($value, $flags, null, $i, \true, $references);
        }
        // some comments are allowed at the end
        if (preg_replace('/\s*#.*$/A', '', substr($value, $i))) {
            throw new ParseException(\sprintf('Unexpected characters near "%s".', substr($value, $i)), self::$parsedLineNumber + 1, $value, self::$parsedFilename);
        }
        if (null !== $tag && '' !== $tag) {
            return new TaggedValue($tag, $result);
        }
        return $result;
    }
    /**
     * Dumps a given PHP variable to a YAML string.
     *
     * @param mixed $value The PHP variable to convert
     * @param int   $flags A bit field of Yaml::DUMP_* constants to customize the dumped YAML string
     *
     * @throws DumpException When trying to dump PHP resource
     */
    public static function dump(mixed $value, int $flags = 0): string
    {
        switch (\true) {
            case \is_resource($value):
                if (Yaml::DUMP_EXCEPTION_ON_INVALID_TYPE & $flags) {
                    throw new DumpException(\sprintf('Unable to dump PHP resources in a YAML file ("%s").', get_resource_type($value)));
                }
                return self::dumpNull($flags);
            case $value instanceof \DateTimeInterface:
                return $value->format(match (\true) {
                    !$length = \strlen(rtrim($value->format('u'), '0')) => 'c',
                    $length < 4 => 'Y-m-d\TH:i:s.vP',
                    default => 'Y-m-d\TH:i:s.uP',
                });
            case $value instanceof \UnitEnum:
                return \sprintf('!php/const %s::%s', $value::class, $value->name);
            case \is_object($value):
                if ($value instanceof TaggedValue) {
                    return '!' . $value->getTag() . ' ' . self::dump($value->getValue(), $flags);
                }
                if (Yaml::DUMP_OBJECT & $flags) {
                    return '!php/object ' . self::dump(serialize($value));
                }
                if (Yaml::DUMP_OBJECT_AS_MAP & $flags && ($value instanceof \stdClass || $value instanceof \ArrayObject)) {
                    return self::dumpHashArray($value, $flags);
                }
                if (Yaml::DUMP_EXCEPTION_ON_INVALID_TYPE & $flags) {
                    throw new DumpException('Object support when dumping a YAML file has been disabled.');
                }
                return self::dumpNull($flags);
            case \is_array($value):
                return self::dumpArray($value, $flags);
            case null === $value:
                return self::dumpNull($flags);
            case \true === $value:
                return 'true';
            case \false === $value:
                return 'false';
            case \is_int($value):
                return $value;
            case is_numeric($value) && \false === strpbrk($value, "\f\n\r\t\v"):
                $locale = setlocale(\LC_NUMERIC, 0);
                if (\false !== $locale) {
                    setlocale(\LC_NUMERIC, 'C');
                }
                if (\is_float($value)) {
                    $repr = (string) $value;
                    if (is_infinite($value)) {
                        $repr = str_ireplace('INF', '.Inf', $repr);
                    } elseif (floor($value) == $value && $repr == $value) {
                        // Preserve float data type since storing a whole number will result in integer value.
                        if (!str_contains($repr, 'E')) {
                            $repr .= '.0';
                        }
                    }
                } else {
                    $repr = \is_string($value) ? "'{$value}'" : (string) $value;
                }
                if (\false !== $locale) {
                    setlocale(\LC_NUMERIC, $locale);
                }
                return $repr;
            case '' == $value:
                return "''";
            case self::isBinaryString($value):
                return '!!binary ' . base64_encode($value);
            case Escaper::requiresDoubleQuoting($value):
                return Escaper::escapeWithDoubleQuotes($value);
            case Escaper::requiresSingleQuoting($value):
                $singleQuoted = Escaper::escapeWithSingleQuotes($value);
                if (!str_contains($value, "'")) {
                    return $singleQuoted;
                }
                // Attempt double-quoting the string instead to see if it's more efficient.
                $doubleQuoted = Escaper::escapeWithDoubleQuotes($value);
                return \strlen($doubleQuoted) < \strlen($singleQuoted) ? $doubleQuoted : $singleQuoted;
            case Parser::preg_match('{^[0-9]+[_0-9]*$}', $value):
            case Parser::preg_match(self::getHexRegex(), $value):
            case Parser::preg_match(self::getTimestampRegex(), $value):
                return Escaper::escapeWithSingleQuotes($value);
            default:
                return $value;
        }
    }
    /**
     * Check if given array is hash or just normal indexed array.
     */
    public static function isHash(array|\ArrayObject|\stdClass $value): bool
    {
        if ($value instanceof \stdClass || $value instanceof \ArrayObject) {
            return \true;
        }
        $expectedKey = 0;
        foreach ($value as $key => $val) {
            if ($key !== $expectedKey++) {
                return \true;
            }
        }
        return \false;
    }
    /**
     * Dumps a PHP array to a YAML string.
     *
     * @param array $value The PHP array to dump
     * @param int   $flags A bit field of Yaml::DUMP_* constants to customize the dumped YAML string
     */
    private static function dumpArray(array $value, int $flags): string
    {
        // array
        if (($value || Yaml::DUMP_EMPTY_ARRAY_AS_SEQUENCE & $flags) && !self::isHash($value)) {
            $output = [];
            foreach ($value as $val) {
                $output[] = self::dump($val, $flags);
            }
            return \sprintf('[%s]', implode(', ', $output));
        }
        return self::dumpHashArray($value, $flags);
    }
    /**
     * Dumps hash array to a YAML string.
     *
     * @param array|\ArrayObject|\stdClass $value The hash array to dump
     * @param int                          $flags A bit field of Yaml::DUMP_* constants to customize the dumped YAML string
     */
    private static function dumpHashArray(array|\ArrayObject|\stdClass $value, int $flags): string
    {
        $output = [];
        foreach ($value as $key => $val) {
            if (\is_int($key) && Yaml::DUMP_NUMERIC_KEY_AS_STRING & $flags) {
                $key = (string) $key;
            }
            $output[] = \sprintf('%s: %s', self::dump($key, $flags), self::dump($val, $flags));
        }
        return \sprintf('{ %s }', implode(', ', $output));
    }
    private static function dumpNull(int $flags): string
    {
        if (Yaml::DUMP_NULL_AS_TILDE & $flags) {
            return '~';
        }
        return 'null';
    }
    /**
     * Parses a YAML scalar.
     *
     * @throws ParseException When malformed inline YAML string is parsed
     */
    public static function parseScalar(string $scalar, int $flags = 0, ?array $delimiters = null, int &$i = 0, bool $evaluate = \true, array &$references = [], ?bool &$isQuoted = null): mixed
    {
        if (\in_array($scalar[$i], ['"', "'"], \true)) {
            // quoted scalar
            $isQuoted = \true;
            $output = self::parseQuotedScalar($scalar, $i);
            if (null !== $delimiters) {
                $tmp = ltrim(substr($scalar, $i), " \n");
                if ('' === $tmp) {
                    throw new ParseException(\sprintf('Unexpected end of line, expected one of "%s".', implode('', $delimiters)), self::$parsedLineNumber + 1, $scalar, self::$parsedFilename);
                }
                if (!\in_array($tmp[0], $delimiters)) {
                    throw new ParseException(\sprintf('Unexpected characters (%s).', substr($scalar, $i)), self::$parsedLineNumber + 1, $scalar, self::$parsedFilename);
                }
            }
        } else {
            // "normal" string
            $isQuoted = \false;
            if (!$delimiters) {
                $output = substr($scalar, $i);
                $i += \strlen($output);
                // remove comments
                if (Parser::preg_match('/[ \t]+#/', $output, $match, \PREG_OFFSET_CAPTURE)) {
                    $output = substr($output, 0, $match[0][1]);
                }
            } elseif (Parser::preg_match('/^(.*?)(' . implode('|', $delimiters) . ')/', substr($scalar, $i), $match)) {
                $output = $match[1];
                $i += \strlen($output);
                $output = trim($output);
            } else {
                throw new ParseException(\sprintf('Malformed inline YAML string: "%s".', $scalar), self::$parsedLineNumber + 1, null, self::$parsedFilename);
            }
            // a non-quoted string cannot start with @ or ` (reserved) nor with a scalar indicator (| or >)
            if ($output && ('@' === $output[0] || '`' === $output[0] || '|' === $output[0] || '>' === $output[0] || '%' === $output[0])) {
                throw new ParseException(\sprintf('The reserved indicator "%s" cannot start a plain scalar; you need to quote the scalar.', $output[0]), self::$parsedLineNumber + 1, $output, self::$parsedFilename);
            }
            if ($evaluate) {
                $output = self::evaluateScalar($output, $flags, $references, $isQuoted);
            }
        }
        return $output;
    }
    /**
     * Parses a YAML quoted scalar.
     *
     * @throws ParseException When malformed inline YAML string is parsed
     */
    private static function parseQuotedScalar(string $scalar, int &$i = 0): string
    {
        if (!Parser::preg_match('/' . self::REGEX_QUOTED_STRING . '/Au', substr($scalar, $i), $match)) {
            throw new ParseException(\sprintf('Malformed inline YAML string: "%s".', substr($scalar, $i)), self::$parsedLineNumber + 1, $scalar, self::$parsedFilename);
        }
        $output = substr($match[0], 1, -1);
        $unescaper = new Unescaper();
        if ('"' == $scalar[$i]) {
            $output = $unescaper->unescapeDoubleQuotedString($output);
        } else {
            $output = $unescaper->unescapeSingleQuotedString($output);
        }
        $i += \strlen($match[0]);
        return $output;
    }
    /**
     * Parses a YAML sequence.
     *
     * @throws ParseException When malformed inline YAML string is parsed
     */
    private static function parseSequence(string $sequence, int $flags, int &$i = 0, array &$references = []): array
    {
        $output = [];
        $len = \strlen($sequence);
        ++$i;
        // [foo, bar, ...]
        $lastToken = null;
        while ($i < $len) {
            if (']' === $sequence[$i]) {
                return $output;
            }
            if (',' === $sequence[$i] || ' ' === $sequence[$i]) {
                if (',' === $sequence[$i] && (null === $lastToken || 'separator' === $lastToken)) {
                    $output[] = null;
                } elseif (',' === $sequence[$i]) {
                    $lastToken = 'separator';
                }
                ++$i;
                continue;
            }
            $tag = self::parseTag($sequence, $i, $flags);
            switch ($sequence[$i]) {
                case '[':
                    // nested sequence
                    $value = self::parseSequence($sequence, $flags, $i, $references);
                    break;
                case '{':
                    // nested mapping
                    $value = self::parseMapping($sequence, $flags, $i, $references);
                    break;
                default:
                    $value = self::parseScalar($sequence, $flags, [',', ']'], $i, null === $tag, $references, $isQuoted);
                    // the value can be an array if a reference has been resolved to an array var
                    if (\is_string($value) && !$isQuoted && str_contains($value, ': ')) {
                        // embedded mapping?
                        $j = $i;
                        $mappingValue = $value;
                        $mappingException = null;
                        do {
                            try {
                                $pos = 0;
                                $value = self::parseMapping('{' . $mappingValue . '}', $flags, $pos, $references);
                                $i = $j;
                                $mappingException = null;
                                break;
                            } catch (ParseException $exception) {
                                $mappingException = $exception;
                                if ($j >= $len) {
                                    break;
                                }
                                $mappingValue .= $sequence[$j++];
                                if ($j >= $len) {
                                    break;
                                }
                                $mappingValue .= self::parseScalar($sequence, $flags, [',', ']'], $j, null === $tag, $references);
                            }
                        } while ($j < $len);
                        if ($mappingException) {
                            throw $mappingException;
                        }
                    }
                    if (!$isQuoted && \is_string($value) && '' !== $value && '&' === $value[0] && Parser::preg_match(Parser::REFERENCE_PATTERN, $value, $matches)) {
                        $references[$matches['ref']] = $matches['value'];
                        $value = $matches['value'];
                    }
                    --$i;
            }
            if (null !== $tag && '' !== $tag) {
                $value = new TaggedValue($tag, $value);
            }
            $output[] = $value;
            $lastToken = 'value';
            ++$i;
        }
        throw new ParseException(\sprintf('Malformed inline YAML string: "%s".', $sequence), self::$parsedLineNumber + 1, null, self::$parsedFilename);
    }
    /**
     * Parses a YAML mapping.
     *
     * @throws ParseException When malformed inline YAML string is parsed
     */
    private static function parseMapping(string $mapping, int $flags, int &$i = 0, array &$references = []): array|\stdClass
    {
        $output = [];
        $len = \strlen($mapping);
        ++$i;
        $allowOverwrite = \false;
        // {foo: bar, bar:foo, ...}
        while ($i < $len) {
            switch ($mapping[$i]) {
                case ' ':
                case ',':
                case "\n":
                    ++$i;
                    continue 2;
                case '}':
                    if (self::$objectForMap) {
                        return (object) $output;
                    }
                    return $output;
            }
            // key
            $offsetBeforeKeyParsing = $i;
            $isKeyQuoted = \in_array($mapping[$i], ['"', "'"], \true);
            $key = self::parseScalar($mapping, $flags, [':', ' '], $i, \false);
            if ($offsetBeforeKeyParsing === $i) {
                throw new ParseException('Missing mapping key.', self::$parsedLineNumber + 1, $mapping);
            }
            if ('!php/const' === $key || '!php/enum' === $key) {
                $key .= ' ' . self::parseScalar($mapping, $flags, ['(?<!:):(?!:)'], $i, \false);
                $key = self::evaluateScalar($key, $flags);
            }
            if (\false === $i = strpos($mapping, ':', $i)) {
                break;
            }
            if (!$isKeyQuoted) {
                $evaluatedKey = self::evaluateScalar($key, $flags, $references);
                if ('' !== $key && $evaluatedKey !== $key && !\is_string($evaluatedKey) && !\is_int($evaluatedKey)) {
                    throw new ParseException('Implicit casting of incompatible mapping keys to strings is not supported. Quote your evaluable mapping keys instead.', self::$parsedLineNumber + 1, $mapping);
                }
            }
            if (!$isKeyQuoted && (!isset($mapping[$i + 1]) || !\in_array($mapping[$i + 1], [' ', ',', '[', ']', '{', '}', "\n"], \true))) {
                throw new ParseException('Colons must be followed by a space or an indication character (i.e. " ", ",", "[", "]", "{", "}").', self::$parsedLineNumber + 1, $mapping);
            }
            if ('<<' === $key) {
                $allowOverwrite = \true;
            }
            while ($i < $len) {
                if (':' === $mapping[$i] || ' ' === $mapping[$i] || "\n" === $mapping[$i]) {
                    ++$i;
                    continue;
                }
                $tag = self::parseTag($mapping, $i, $flags);
                switch ($mapping[$i]) {
                    case '[':
                        // nested sequence
                        $value = self::parseSequence($mapping, $flags, $i, $references);
                        // Spec: Keys MUST be unique; first one wins.
                        // Parser cannot abort this mapping earlier, since lines
                        // are processed sequentially.
                        // But overwriting is allowed when a merge node is used in current block.
                        if ('<<' === $key) {
                            foreach ($value as $parsedValue) {
                                $output += $parsedValue;
                            }
                        } elseif ($allowOverwrite || !isset($output[$key])) {
                            if (null !== $tag) {
                                $output[$key] = new TaggedValue($tag, $value);
                            } else {
                                $output[$key] = $value;
                            }
                        } elseif (isset($output[$key])) {
                            throw new ParseException(\sprintf('Duplicate key "%s" detected.', $key), self::$parsedLineNumber + 1, $mapping);
                        }
                        break;
                    case '{':
                        // nested mapping
                        $value = self::parseMapping($mapping, $flags, $i, $references);
                        // Spec: Keys MUST be unique; first one wins.
                        // Parser cannot abort this mapping earlier, since lines
                        // are processed sequentially.
                        // But overwriting is allowed when a merge node is used in current block.
                        if ('<<' === $key) {
                            $output += $value;
                        } elseif ($allowOverwrite || !isset($output[$key])) {
                            if (null !== $tag) {
                                $output[$key] = new TaggedValue($tag, $value);
                            } else {
                                $output[$key] = $value;
                            }
                        } elseif (isset($output[$key])) {
                            throw new ParseException(\sprintf('Duplicate key "%s" detected.', $key), self::$parsedLineNumber + 1, $mapping);
                        }
                        break;
                    default:
                        $value = self::parseScalar($mapping, $flags, [',', '}', "\n"], $i, null === $tag, $references, $isValueQuoted);
                        // Spec: Keys MUST be unique; first one wins.
                        // Parser cannot abort this mapping earlier, since lines
                        // are processed sequentially.
                        // But overwriting is allowed when a merge node is used in current block.
                        if ('<<' === $key) {
                            $output += $value;
                        } elseif ($allowOverwrite || !isset($output[$key])) {
                            if (!$isValueQuoted && \is_string($value) && '' !== $value && '&' === $value[0] && !self::isBinaryString($value) && Parser::preg_match(Parser::REFERENCE_PATTERN, $value, $matches)) {
                                $references[$matches['ref']] = $matches['value'];
                                $value = $matches['value'];
                            }
                            if (null !== $tag) {
                                $output[$key] = new TaggedValue($tag, $value);
                            } else {
                                $output[$key] = $value;
                            }
                        } elseif (isset($output[$key])) {
                            throw new ParseException(\sprintf('Duplicate key "%s" detected.', $key), self::$parsedLineNumber + 1, $mapping);
                        }
                        --$i;
                }
                ++$i;
                continue 2;
            }
        }
        throw new ParseException(\sprintf('Malformed inline YAML string: "%s".', $mapping), self::$parsedLineNumber + 1, null, self::$parsedFilename);
    }
    /**
     * Evaluates scalars and replaces magic values.
     *
     * @throws ParseException when object parsing support was disabled and the parser detected a PHP object or when a reference could not be resolved
     */
    private static function evaluateScalar(string $scalar, int $flags, array &$references = [], ?bool &$isQuotedString = null): mixed
    {
        $isQuotedString = \false;
        $scalar = trim($scalar);
        if (str_starts_with($scalar, '*')) {
            if (\false !== $pos = strpos($scalar, '#')) {
                $value = substr($scalar, 1, $pos - 2);
            } else {
                $value = substr($scalar, 1);
            }
            // an unquoted *
            if (\false === $value || '' === $value) {
                throw new ParseException('A reference must contain at least one character.', self::$parsedLineNumber + 1, $value, self::$parsedFilename);
            }
            if (!\array_key_exists($value, $references)) {
                throw new ParseException(\sprintf('Reference "%s" does not exist.', $value), self::$parsedLineNumber + 1, $value, self::$parsedFilename);
            }
            return $references[$value];
        }
        $scalarLower = strtolower($scalar);
        switch (\true) {
            case 'null' === $scalarLower:
            case '' === $scalar:
            case '~' === $scalar:
                return null;
            case 'true' === $scalarLower:
                return \true;
            case 'false' === $scalarLower:
                return \false;
            case '!' === $scalar[0]:
                switch (\true) {
                    case str_starts_with($scalar, '!!str '):
                        $s = (string) substr($scalar, 6);
                        if (\in_array($s[0] ?? '', ['"', "'"], \true)) {
                            $isQuotedString = \true;
                            $s = self::parseQuotedScalar($s);
                        }
                        return $s;
                    case str_starts_with($scalar, '! '):
                        return substr($scalar, 2);
                    case str_starts_with($scalar, '!php/object'):
                        if (self::$objectSupport) {
                            if (!isset($scalar[12])) {
                                throw new ParseException('Missing value for tag "!php/object".', self::$parsedLineNumber + 1, $scalar, self::$parsedFilename);
                            }
                            return unserialize(self::parseScalar(substr($scalar, 12)));
                        }
                        if (self::$exceptionOnInvalidType) {
                            throw new ParseException('Object support when parsing a YAML file has been disabled.', self::$parsedLineNumber + 1, $scalar, self::$parsedFilename);
                        }
                        return null;
                    case str_starts_with($scalar, '!php/const'):
                        if (self::$constantSupport) {
                            if (!isset($scalar[11])) {
                                throw new ParseException('Missing value for tag "!php/const".', self::$parsedLineNumber + 1, $scalar, self::$parsedFilename);
                            }
                            $i = 0;
                            if (\defined($const = self::parseScalar(substr($scalar, 11), 0, null, $i, \false))) {
                                return \constant($const);
                            }
                            throw new ParseException(\sprintf('The constant "%s" is not defined.', $const), self::$parsedLineNumber + 1, $scalar, self::$parsedFilename);
                        }
                        if (self::$exceptionOnInvalidType) {
                            throw new ParseException(\sprintf('The string "%s" could not be parsed as a constant. Did you forget to pass the "Yaml::PARSE_CONSTANT" flag to the parser?', $scalar), self::$parsedLineNumber + 1, $scalar, self::$parsedFilename);
                        }
                        return null;
                    case str_starts_with($scalar, '!php/enum'):
                        if (self::$constantSupport) {
                            if (!isset($scalar[11])) {
                                throw new ParseException('Missing value for tag "!php/enum".', self::$parsedLineNumber + 1, $scalar, self::$parsedFilename);
                            }
                            $i = 0;
                            $enum = self::parseScalar(substr($scalar, 10), 0, null, $i, \false);
                            if ($useValue = str_ends_with($enum, '->value')) {
                                $enum = substr($enum, 0, -7);
                            }
                            if (!\defined($enum)) {
                                throw new ParseException(\sprintf('The enum "%s" is not defined.', $enum), self::$parsedLineNumber + 1, $scalar, self::$parsedFilename);
                            }
                            $value = \constant($enum);
                            if (!$value instanceof \UnitEnum) {
                                throw new ParseException(\sprintf('The string "%s" is not the name of a valid enum.', $enum), self::$parsedLineNumber + 1, $scalar, self::$parsedFilename);
                            }
                            if (!$useValue) {
                                return $value;
                            }
                            if (!$value instanceof \BackedEnum) {
                                throw new ParseException(\sprintf('The enum "%s" defines no value next to its name.', $enum), self::$parsedLineNumber + 1, $scalar, self::$parsedFilename);
                            }
                            return $value->value;
                        }
                        if (self::$exceptionOnInvalidType) {
                            throw new ParseException(\sprintf('The string "%s" could not be parsed as an enum. Did you forget to pass the "Yaml::PARSE_CONSTANT" flag to the parser?', $scalar), self::$parsedLineNumber + 1, $scalar, self::$parsedFilename);
                        }
                        return null;
                    case str_starts_with($scalar, '!!float '):
                        return (float) substr($scalar, 8);
                    case str_starts_with($scalar, '!!binary '):
                        return self::evaluateBinaryScalar(substr($scalar, 9));
                }
                throw new ParseException(\sprintf('The string "%s" could not be parsed as it uses an unsupported built-in tag.', $scalar), self::$parsedLineNumber, $scalar, self::$parsedFilename);
            case preg_match('/^(?:\+|-)?0o(?P<value>[0-7_]++)$/', $scalar, $matches):
                $value = str_replace('_', '', $matches['value']);
                if ('-' === $scalar[0]) {
                    return -octdec($value);
                }
                return octdec($value);
            case \in_array($scalar[0], ['+', '-', '.'], \true) || is_numeric($scalar[0]):
                if (Parser::preg_match('{^[+-]?[0-9][0-9_]*$}', $scalar)) {
                    $scalar = str_replace('_', '', $scalar);
                }
                switch (\true) {
                    case ctype_digit($scalar):
                    case '-' === $scalar[0] && ctype_digit(substr($scalar, 1)):
                        if ($scalar < \PHP_INT_MIN || \PHP_INT_MAX < $scalar) {
                            return $scalar;
                        }
                        $cast = (int) $scalar;
                        return $scalar === (string) $cast ? $cast : $scalar;
                    case is_numeric($scalar):
                    case Parser::preg_match(self::getHexRegex(), $scalar):
                        $scalar = str_replace('_', '', $scalar);
                        return '0x' === $scalar[0] . $scalar[1] ? hexdec($scalar) : (float) $scalar;
                    case '.inf' === $scalarLower:
                    case '.nan' === $scalarLower:
                        return -log(0);
                    case '-.inf' === $scalarLower:
                        return log(0);
                    case Parser::preg_match('/^(-|\+)?[0-9][0-9_]*(\.[0-9_]+)?$/', $scalar):
                        return (float) str_replace('_', '', $scalar);
                    case Parser::preg_match(self::getTimestampRegex(), $scalar):
                        try {
                            // When no timezone is provided in the parsed date, YAML spec says we must assume UTC.
                            $time = new \DateTimeImmutable($scalar, new \DateTimeZone('UTC'));
                        } catch (\Exception $e) {
                            // Some dates accepted by the regex are not valid dates.
                            throw new ParseException(\sprintf('The date "%s" could not be parsed as it is an invalid date.', $scalar), self::$parsedLineNumber + 1, $scalar, self::$parsedFilename, $e);
                        }
                        if (Yaml::PARSE_DATETIME & $flags) {
                            return $time;
                        }
                        if ('' !== rtrim($time->format('u'), '0')) {
                            return (float) $time->format('U.u');
                        }
                        try {
                            if (\false !== $scalar = $time->getTimestamp()) {
                                return $scalar;
                            }
                        } catch (\DateRangeError|\ValueError) {
                            // no-op
                        }
                        return $time->format('U');
                }
        }
        return (string) $scalar;
    }
    private static function parseTag(string $value, int &$i, int $flags): ?string
    {
        if ('!' !== $value[$i]) {
            return null;
        }
        $tagLength = strcspn($value, " \t\n[]{},", $i + 1);
        $tag = substr($value, $i + 1, $tagLength);
        $nextOffset = $i + $tagLength + 1;
        $nextOffset += strspn($value, ' ', $nextOffset);
        if ('' === $tag && (!isset($value[$nextOffset]) || \in_array($value[$nextOffset], [']', '}', ','], \true))) {
            throw new ParseException('Using the unquoted scalar value "!" is not supported. You must quote it.', self::$parsedLineNumber + 1, $value, self::$parsedFilename);
        }
        // Is followed by a scalar and is a built-in tag
        if ('' !== $tag && (!isset($value[$nextOffset]) || !\in_array($value[$nextOffset], ['[', '{'], \true)) && ('!' === $tag[0] || \in_array($tag, ['str', 'php/const', 'php/enum', 'php/object'], \true))) {
            // Manage in {@link self::evaluateScalar()}
            return null;
        }
        $i = $nextOffset;
        // Built-in tags
        if ('' !== $tag && '!' === $tag[0]) {
            throw new ParseException(\sprintf('The built-in tag "!%s" is not implemented.', $tag), self::$parsedLineNumber + 1, $value, self::$parsedFilename);
        }
        if ('' !== $tag && !isset($value[$i])) {
            throw new ParseException(\sprintf('Missing value for tag "%s".', $tag), self::$parsedLineNumber + 1, $value, self::$parsedFilename);
        }
        if ('' === $tag || Yaml::PARSE_CUSTOM_TAGS & $flags) {
            return $tag;
        }
        throw new ParseException(\sprintf('Tags support is not enabled. Enable the "Yaml::PARSE_CUSTOM_TAGS" flag to use "!%s".', $tag), self::$parsedLineNumber + 1, $value, self::$parsedFilename);
    }
    public static function evaluateBinaryScalar(string $scalar): string
    {
        $parsedBinaryData = self::parseScalar(preg_replace('/\s/', '', $scalar));
        if (0 !== \strlen($parsedBinaryData) % 4) {
            throw new ParseException(\sprintf('The normalized base64 encoded data (data without whitespace characters) length must be a multiple of four (%d bytes given).', \strlen($parsedBinaryData)), self::$parsedLineNumber + 1, $scalar, self::$parsedFilename);
        }
        if (!Parser::preg_match('#^[A-Z0-9+/]+={0,2}$#i', $parsedBinaryData)) {
            throw new ParseException(\sprintf('The base64 encoded data (%s) contains invalid characters.', $parsedBinaryData), self::$parsedLineNumber + 1, $scalar, self::$parsedFilename);
        }
        return base64_decode($parsedBinaryData, \true);
    }
    private static function isBinaryString(string $value): bool
    {
        return !preg_match('//u', $value) || preg_match('/[^\x00\x07-\x0d\x1B\x20-\xff]/', $value);
    }
    /**
     * Gets a regex that matches a YAML date.
     *
     * @see http://www.yaml.org/spec/1.2/spec.html#id2761573
     */
    private static function getTimestampRegex(): string
    {
        return <<<EOF
        ~^
        (?P<year>[0-9][0-9][0-9][0-9])
        -(?P<month>[0-9][0-9]?)
        -(?P<day>[0-9][0-9]?)
        (?:(?:[Tt]|[ \t]+)
        (?P<hour>[0-9][0-9]?)
        :(?P<minute>[0-9][0-9])
        :(?P<second>[0-9][0-9])
        (?:\\.(?P<fraction>[0-9]*))?
        (?:[ \t]*(?P<tz>Z|(?P<tz_sign>[-+])(?P<tz_hour>[0-9][0-9]?)
        (?::(?P<tz_minute>[0-9][0-9]))?))?)?
        \$~x
EOF;
    }
    /**
     * Gets a regex that matches a YAML number in hexadecimal notation.
     */
    private static function getHexRegex(): string
    {
        return '~^0x[0-9a-f_]++$~i';
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Yaml;

use _ContaoManager\Symfony\Component\Yaml\Exception\ParseException;
/**
 * Yaml offers convenience methods to load and dump YAML.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 *
 * @final
 */
class Yaml
{
    public const DUMP_OBJECT = 1;
    public const PARSE_EXCEPTION_ON_INVALID_TYPE = 2;
    public const PARSE_OBJECT = 4;
    public const PARSE_OBJECT_FOR_MAP = 8;
    public const DUMP_EXCEPTION_ON_INVALID_TYPE = 16;
    public const PARSE_DATETIME = 32;
    public const DUMP_OBJECT_AS_MAP = 64;
    public const DUMP_MULTI_LINE_LITERAL_BLOCK = 128;
    public const PARSE_CONSTANT = 256;
    public const PARSE_CUSTOM_TAGS = 512;
    public const DUMP_EMPTY_ARRAY_AS_SEQUENCE = 1024;
    public const DUMP_NULL_AS_TILDE = 2048;
    public const DUMP_NUMERIC_KEY_AS_STRING = 4096;
    /**
     * Parses a YAML file into a PHP value.
     *
     * Usage:
     *
     *     $array = Yaml::parseFile('config.yml');
     *     print_r($array);
     *
     * @param string $filename The path to the YAML file to be parsed
     * @param int    $flags    A bit field of PARSE_* constants to customize the YAML parser behavior
     *
     * @throws ParseException If the file could not be read or the YAML is not valid
     */
    public static function parseFile(string $filename, int $flags = 0): mixed
    {
        $yaml = new Parser();
        return $yaml->parseFile($filename, $flags);
    }
    /**
     * Parses YAML into a PHP value.
     *
     *  Usage:
     *  <code>
     *   $array = Yaml::parse(file_get_contents('config.yml'));
     *   print_r($array);
     *  </code>
     *
     * @param string $input A string containing YAML
     * @param int    $flags A bit field of PARSE_* constants to customize the YAML parser behavior
     *
     * @throws ParseException If the YAML is not valid
     */
    public static function parse(string $input, int $flags = 0): mixed
    {
        $yaml = new Parser();
        return $yaml->parse($input, $flags);
    }
    /**
     * Dumps a PHP value to a YAML string.
     *
     * The dump method, when supplied with an array, will do its best
     * to convert the array into friendly YAML.
     *
     * @param mixed $input  The PHP value
     * @param int   $inline The level where you switch to inline YAML
     * @param int   $indent The amount of spaces to use for indentation of nested nodes
     * @param int   $flags  A bit field of DUMP_* constants to customize the dumped YAML string
     */
    public static function dump(mixed $input, int $inline = 2, int $indent = 4, int $flags = 0): string
    {
        $yaml = new Dumper($indent);
        return $yaml->dump($input, $inline, 0, $flags);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Yaml\Command;

use _ContaoManager\Symfony\Component\Console\Attribute\AsCommand;
use _ContaoManager\Symfony\Component\Console\CI\GithubActionReporter;
use _ContaoManager\Symfony\Component\Console\Command\Command;
use _ContaoManager\Symfony\Component\Console\Completion\CompletionInput;
use _ContaoManager\Symfony\Component\Console\Completion\CompletionSuggestions;
use _ContaoManager\Symfony\Component\Console\Exception\InvalidArgumentException;
use _ContaoManager\Symfony\Component\Console\Exception\RuntimeException;
use _ContaoManager\Symfony\Component\Console\Input\InputArgument;
use _ContaoManager\Symfony\Component\Console\Input\InputInterface;
use _ContaoManager\Symfony\Component\Console\Input\InputOption;
use _ContaoManager\Symfony\Component\Console\Output\OutputInterface;
use _ContaoManager\Symfony\Component\Console\Style\SymfonyStyle;
use _ContaoManager\Symfony\Component\Yaml\Exception\ParseException;
use _ContaoManager\Symfony\Component\Yaml\Parser;
use _ContaoManager\Symfony\Component\Yaml\Yaml;
/**
 * Validates YAML files syntax and outputs encountered errors.
 *
 * @author Grégoire Pineau <lyrixx@lyrixx.info>
 * @author Robin Chalas <robin.chalas@gmail.com>
 */
#[AsCommand(name: 'lint:yaml', description: 'Lint a YAML file and outputs encountered errors')]
class LintCommand extends Command
{
    private Parser $parser;
    private ?string $format = null;
    private bool $displayCorrectFiles;
    private ?\Closure $directoryIteratorProvider;
    private ?\Closure $isReadableProvider;
    public function __construct(?string $name = null, ?callable $directoryIteratorProvider = null, ?callable $isReadableProvider = null)
    {
        parent::__construct($name);
        $this->directoryIteratorProvider = null === $directoryIteratorProvider ? null : $directoryIteratorProvider(...);
        $this->isReadableProvider = null === $isReadableProvider ? null : $isReadableProvider(...);
    }
    /**
     * @return void
     */
    protected function configure()
    {
        $this->addArgument('filename', InputArgument::IS_ARRAY, 'A file, a directory or "-" for reading from STDIN')->addOption('format', null, InputOption::VALUE_REQUIRED, \sprintf('The output format ("%s")', implode('", "', $this->getAvailableFormatOptions())))->addOption('exclude', null, InputOption::VALUE_REQUIRED | InputOption::VALUE_IS_ARRAY, 'Path(s) to exclude')->addOption('parse-tags', null, InputOption::VALUE_NEGATABLE, 'Parse custom tags', null)->setHelp(<<<EOF
The <info>%command.name%</info> command lints a YAML file and outputs to STDOUT
the first encountered syntax error.

You can validates YAML contents passed from STDIN:

  <info>cat filename | php %command.full_name% -</info>

You can also validate the syntax of a file:

  <info>php %command.full_name% filename</info>

Or of a whole directory:

  <info>php %command.full_name% dirname</info>
  <info>php %command.full_name% dirname --format=json</info>

You can also exclude one or more specific files:

  <info>php %command.full_name% dirname --exclude="dirname/foo.yaml" --exclude="dirname/bar.yaml"</info>

EOF
);
    }
    protected function execute(InputInterface $input, OutputInterface $output): int
    {
        $io = new SymfonyStyle($input, $output);
        $filenames = (array) $input->getArgument('filename');
        $excludes = $input->getOption('exclude');
        $this->format = $input->getOption('format');
        $flags = $input->getOption('parse-tags');
        if (null === $this->format) {
            // Autodetect format according to CI environment
            $this->format = class_exists(GithubActionReporter::class) && GithubActionReporter::isGithubActionEnvironment() ? 'github' : 'txt';
        }
        $flags = $flags ? Yaml::PARSE_CUSTOM_TAGS : 0;
        $this->displayCorrectFiles = $output->isVerbose();
        if (['-'] === $filenames) {
            return $this->display($io, [$this->validate(file_get_contents('php://stdin'), $flags)]);
        }
        if (!$filenames) {
            throw new RuntimeException('Please provide a filename or pipe file content to STDIN.');
        }
        $filesInfo = [];
        foreach ($filenames as $filename) {
            if (!$this->isReadable($filename)) {
                throw new RuntimeException(\sprintf('File or directory "%s" is not readable.', $filename));
            }
            foreach ($this->getFiles($filename) as $file) {
                if (!\in_array($file->getPathname(), $excludes, \true)) {
                    $filesInfo[] = $this->validate(file_get_contents($file), $flags, $file);
                }
            }
        }
        return $this->display($io, $filesInfo);
    }
    private function validate(string $content, int $flags, ?string $file = null): array
    {
        $prevErrorHandler = set_error_handler(function ($level, $message, $file, $line) use (&$prevErrorHandler) {
            if (\E_USER_DEPRECATED === $level) {
                throw new ParseException($message, $this->getParser()->getRealCurrentLineNb() + 1);
            }
            return $prevErrorHandler ? $prevErrorHandler($level, $message, $file, $line) : \false;
        });
        try {
            $this->getParser()->parse($content, Yaml::PARSE_CONSTANT | $flags);
        } catch (ParseException $e) {
            return ['file' => $file, 'line' => $e->getParsedLine(), 'valid' => \false, 'message' => $e->getMessage()];
        } finally {
            restore_error_handler();
        }
        return ['file' => $file, 'valid' => \true];
    }
    private function display(SymfonyStyle $io, array $files): int
    {
        return match ($this->format) {
            'txt' => $this->displayTxt($io, $files),
            'json' => $this->displayJson($io, $files),
            'github' => $this->displayTxt($io, $files, \true),
            default => throw new InvalidArgumentException(\sprintf('Supported formats are "%s".', implode('", "', $this->getAvailableFormatOptions()))),
        };
    }
    private function displayTxt(SymfonyStyle $io, array $filesInfo, bool $errorAsGithubAnnotations = \false): int
    {
        $countFiles = \count($filesInfo);
        $erroredFiles = 0;
        $suggestTagOption = \false;
        if ($errorAsGithubAnnotations) {
            $githubReporter = new GithubActionReporter($io);
        }
        foreach ($filesInfo as $info) {
            if ($info['valid'] && $this->displayCorrectFiles) {
                $io->comment('<info>OK</info>' . ($info['file'] ? \sprintf(' in %s', $info['file']) : ''));
            } elseif (!$info['valid']) {
                ++$erroredFiles;
                $io->text('<error> ERROR </error>' . ($info['file'] ? \sprintf(' in %s', $info['file']) : ''));
                $io->text(\sprintf('<error> >> %s</error>', $info['message']));
                if (str_contains($info['message'], 'PARSE_CUSTOM_TAGS')) {
                    $suggestTagOption = \true;
                }
                if ($errorAsGithubAnnotations) {
                    $githubReporter->error($info['message'], $info['file'] ?? 'php://stdin', $info['line']);
                }
            }
        }
        if (0 === $erroredFiles) {
            $io->success(\sprintf('All %d YAML files contain valid syntax.', $countFiles));
        } else {
            $io->warning(\sprintf('%d YAML files have valid syntax and %d contain errors.%s', $countFiles - $erroredFiles, $erroredFiles, $suggestTagOption ? ' Use the --parse-tags option if you want parse custom tags.' : ''));
        }
        return min($erroredFiles, 1);
    }
    private function displayJson(SymfonyStyle $io, array $filesInfo): int
    {
        $errors = 0;
        array_walk($filesInfo, function (&$v) use (&$errors) {
            $v['file'] = (string) $v['file'];
            if (!$v['valid']) {
                ++$errors;
            }
            if (isset($v['message']) && str_contains($v['message'], 'PARSE_CUSTOM_TAGS')) {
                $v['message'] .= ' Use the --parse-tags option if you want parse custom tags.';
            }
        });
        $io->writeln(json_encode($filesInfo, \JSON_PRETTY_PRINT | \JSON_UNESCAPED_SLASHES));
        return min($errors, 1);
    }
    private function getFiles(string $fileOrDirectory): iterable
    {
        if (is_file($fileOrDirectory)) {
            yield new \SplFileInfo($fileOrDirectory);
            return;
        }
        foreach ($this->getDirectoryIterator($fileOrDirectory) as $file) {
            if (!\in_array($file->getExtension(), ['yml', 'yaml'])) {
                continue;
            }
            yield $file;
        }
    }
    private function getParser(): Parser
    {
        return $this->parser ??= new Parser();
    }
    private function getDirectoryIterator(string $directory): iterable
    {
        $default = fn($directory) => new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($directory, \FilesystemIterator::SKIP_DOTS | \FilesystemIterator::FOLLOW_SYMLINKS), \RecursiveIteratorIterator::LEAVES_ONLY);
        if (null !== $this->directoryIteratorProvider) {
            return ($this->directoryIteratorProvider)($directory, $default);
        }
        return $default($directory);
    }
    private function isReadable(string $fileOrDirectory): bool
    {
        $default = is_readable(...);
        if (null !== $this->isReadableProvider) {
            return ($this->isReadableProvider)($fileOrDirectory, $default);
        }
        return $default($fileOrDirectory);
    }
    public function complete(CompletionInput $input, CompletionSuggestions $suggestions): void
    {
        if ($input->mustSuggestOptionValuesFor('format')) {
            $suggestions->suggestValues($this->getAvailableFormatOptions());
        }
    }
    private function getAvailableFormatOptions(): array
    {
        return ['txt', 'json', 'github'];
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Yaml\Exception;

/**
 * Exception class thrown when an error occurs during dumping.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class DumpException extends RuntimeException
{
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Yaml\Exception;

/**
 * Exception interface for all exceptions thrown by the component.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
interface ExceptionInterface extends \Throwable
{
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Yaml\Exception;

/**
 * Exception class thrown when an error occurs during parsing.
 *
 * @author Romain Neutron <imprec@gmail.com>
 */
class RuntimeException extends \RuntimeException implements ExceptionInterface
{
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Yaml\Exception;

/**
 * Exception class thrown when an error occurs during parsing.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class ParseException extends RuntimeException
{
    private ?string $parsedFile;
    private int $parsedLine;
    private ?string $snippet;
    private string $rawMessage;
    /**
     * @param string      $message    The error message
     * @param int         $parsedLine The line where the error occurred
     * @param string|null $snippet    The snippet of code near the problem
     * @param string|null $parsedFile The file name where the error occurred
     */
    public function __construct(string $message, int $parsedLine = -1, ?string $snippet = null, ?string $parsedFile = null, ?\Throwable $previous = null)
    {
        $this->parsedFile = $parsedFile;
        $this->parsedLine = $parsedLine;
        $this->snippet = $snippet;
        $this->rawMessage = $message;
        $this->updateRepr();
        parent::__construct($this->message, 0, $previous);
    }
    /**
     * Gets the snippet of code near the error.
     */
    public function getSnippet(): string
    {
        return $this->snippet;
    }
    /**
     * Sets the snippet of code near the error.
     *
     * @return void
     */
    public function setSnippet(string $snippet)
    {
        $this->snippet = $snippet;
        $this->updateRepr();
    }
    /**
     * Gets the filename where the error occurred.
     *
     * This method returns null if a string is parsed.
     */
    public function getParsedFile(): string
    {
        return $this->parsedFile;
    }
    /**
     * Sets the filename where the error occurred.
     *
     * @return void
     */
    public function setParsedFile(string $parsedFile)
    {
        $this->parsedFile = $parsedFile;
        $this->updateRepr();
    }
    /**
     * Gets the line where the error occurred.
     */
    public function getParsedLine(): int
    {
        return $this->parsedLine;
    }
    /**
     * Sets the line where the error occurred.
     *
     * @return void
     */
    public function setParsedLine(int $parsedLine)
    {
        $this->parsedLine = $parsedLine;
        $this->updateRepr();
    }
    private function updateRepr(): void
    {
        $this->message = $this->rawMessage;
        $dot = \false;
        if (str_ends_with($this->message, '.')) {
            $this->message = substr($this->message, 0, -1);
            $dot = \true;
        }
        if (null !== $this->parsedFile) {
            $this->message .= \sprintf(' in %s', json_encode($this->parsedFile, \JSON_UNESCAPED_SLASHES | \JSON_UNESCAPED_UNICODE));
        }
        if ($this->parsedLine >= 0) {
            $this->message .= \sprintf(' at line %d', $this->parsedLine);
        }
        if ($this->snippet) {
            $this->message .= \sprintf(' (near "%s")', $this->snippet);
        }
        if ($dot) {
            $this->message .= '.';
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Yaml\Tag;

/**
 * @author Nicolas Grekas <p@tchwork.com>
 * @author Guilhem N. <egetick@gmail.com>
 */
final class TaggedValue
{
    private string $tag;
    private mixed $value;
    public function __construct(string $tag, mixed $value)
    {
        $this->tag = $tag;
        $this->value = $value;
    }
    public function getTag(): string
    {
        return $this->tag;
    }
    public function getValue(): mixed
    {
        return $this->value;
    }
}
{
    "name": "symfony\/yaml",
    "type": "library",
    "description": "Loads and dumps YAML files",
    "keywords": [],
    "homepage": "https:\/\/symfony.com",
    "license": "MIT",
    "authors": [
        {
            "name": "Fabien Potencier",
            "email": "fabien@symfony.com"
        },
        {
            "name": "Symfony Community",
            "homepage": "https:\/\/symfony.com\/contributors"
        }
    ],
    "require": {
        "php": ">=8.1",
        "symfony\/deprecation-contracts": "^2.5|^3",
        "symfony\/polyfill-ctype": "^1.8"
    },
    "require-dev": {
        "symfony\/console": "^5.4|^6.0|^7.0"
    },
    "conflict": {
        "symfony\/console": "<5.4"
    },
    "autoload": {
        "psr-4": {
            "_ContaoManager\\Symfony\\Component\\Yaml\\": ""
        },
        "exclude-from-classmap": [
            "\/Tests\/"
        ]
    },
    "bin": [
        "Resources\/bin\/yaml-lint"
    ],
    "minimum-stability": "dev"
}<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\String;

use _ContaoManager\Symfony\Component\String\Exception\ExceptionInterface;
use _ContaoManager\Symfony\Component\String\Exception\InvalidArgumentException;
/**
 * Represents a string of Unicode code points encoded as UTF-8.
 *
 * @author Nicolas Grekas <p@tchwork.com>
 * @author Hugo Hamon <hugohamon@neuf.fr>
 *
 * @throws ExceptionInterface
 */
class CodePointString extends AbstractUnicodeString
{
    public function __construct(string $string = '')
    {
        if ('' !== $string && !preg_match('//u', $string)) {
            throw new InvalidArgumentException('Invalid UTF-8 string.');
        }
        $this->string = $string;
    }
    public function append(string ...$suffix): static
    {
        $str = clone $this;
        $str->string .= 1 >= \count($suffix) ? $suffix[0] ?? '' : implode('', $suffix);
        if (!preg_match('//u', $str->string)) {
            throw new InvalidArgumentException('Invalid UTF-8 string.');
        }
        return $str;
    }
    public function chunk(int $length = 1): array
    {
        if (1 > $length) {
            throw new InvalidArgumentException('The chunk length must be greater than zero.');
        }
        if ('' === $this->string) {
            return [];
        }
        $rx = '/(';
        while (65535 < $length) {
            $rx .= '.{65535}';
            $length -= 65535;
        }
        $rx .= '.{' . $length . '})/us';
        $str = clone $this;
        $chunks = [];
        foreach (preg_split($rx, $this->string, -1, \PREG_SPLIT_DELIM_CAPTURE | \PREG_SPLIT_NO_EMPTY) as $chunk) {
            $str->string = $chunk;
            $chunks[] = clone $str;
        }
        return $chunks;
    }
    public function codePointsAt(int $offset): array
    {
        $str = $offset ? $this->slice($offset, 1) : $this;
        return '' === $str->string ? [] : [mb_ord($str->string, 'UTF-8')];
    }
    public function endsWith(string|iterable|AbstractString $suffix): bool
    {
        if ($suffix instanceof AbstractString) {
            $suffix = $suffix->string;
        } elseif (!\is_string($suffix)) {
            return parent::endsWith($suffix);
        }
        if ('' === $suffix || !preg_match('//u', $suffix)) {
            return \false;
        }
        if ($this->ignoreCase) {
            return preg_match('{' . preg_quote($suffix) . '$}iuD', $this->string);
        }
        return \strlen($this->string) >= \strlen($suffix) && 0 === substr_compare($this->string, $suffix, -\strlen($suffix));
    }
    public function equalsTo(string|iterable|AbstractString $string): bool
    {
        if ($string instanceof AbstractString) {
            $string = $string->string;
        } elseif (!\is_string($string)) {
            return parent::equalsTo($string);
        }
        if ('' !== $string && $this->ignoreCase) {
            return \strlen($string) === \strlen($this->string) && 0 === mb_stripos($this->string, $string, 0, 'UTF-8');
        }
        return $string === $this->string;
    }
    public function indexOf(string|iterable|AbstractString $needle, int $offset = 0): ?int
    {
        if ($needle instanceof AbstractString) {
            $needle = $needle->string;
        } elseif (!\is_string($needle)) {
            return parent::indexOf($needle, $offset);
        }
        if ('' === $needle) {
            return null;
        }
        $i = $this->ignoreCase ? mb_stripos($this->string, $needle, $offset, 'UTF-8') : mb_strpos($this->string, $needle, $offset, 'UTF-8');
        return \false === $i ? null : $i;
    }
    public function indexOfLast(string|iterable|AbstractString $needle, int $offset = 0): ?int
    {
        if ($needle instanceof AbstractString) {
            $needle = $needle->string;
        } elseif (!\is_string($needle)) {
            return parent::indexOfLast($needle, $offset);
        }
        if ('' === $needle) {
            return null;
        }
        $i = $this->ignoreCase ? mb_strripos($this->string, $needle, $offset, 'UTF-8') : mb_strrpos($this->string, $needle, $offset, 'UTF-8');
        return \false === $i ? null : $i;
    }
    public function length(): int
    {
        return mb_strlen($this->string, 'UTF-8');
    }
    public function prepend(string ...$prefix): static
    {
        $str = clone $this;
        $str->string = (1 >= \count($prefix) ? $prefix[0] ?? '' : implode('', $prefix)) . $this->string;
        if (!preg_match('//u', $str->string)) {
            throw new InvalidArgumentException('Invalid UTF-8 string.');
        }
        return $str;
    }
    public function replace(string $from, string $to): static
    {
        $str = clone $this;
        if ('' === $from || !preg_match('//u', $from)) {
            return $str;
        }
        if ('' !== $to && !preg_match('//u', $to)) {
            throw new InvalidArgumentException('Invalid UTF-8 string.');
        }
        if ($this->ignoreCase) {
            $str->string = implode($to, preg_split('{' . preg_quote($from) . '}iuD', $this->string));
        } else {
            $str->string = str_replace($from, $to, $this->string);
        }
        return $str;
    }
    public function slice(int $start = 0, ?int $length = null): static
    {
        $str = clone $this;
        $str->string = mb_substr($this->string, $start, $length, 'UTF-8');
        return $str;
    }
    public function splice(string $replacement, int $start = 0, ?int $length = null): static
    {
        if (!preg_match('//u', $replacement)) {
            throw new InvalidArgumentException('Invalid UTF-8 string.');
        }
        $str = clone $this;
        $start = $start ? \strlen(mb_substr($this->string, 0, $start, 'UTF-8')) : 0;
        $length = $length ? \strlen(mb_substr($this->string, $start, $length, 'UTF-8')) : $length;
        $str->string = substr_replace($this->string, $replacement, $start, $length ?? \PHP_INT_MAX);
        return $str;
    }
    public function split(string $delimiter, ?int $limit = null, ?int $flags = null): array
    {
        if (1 > $limit ??= \PHP_INT_MAX) {
            throw new InvalidArgumentException('Split limit must be a positive integer.');
        }
        if ('' === $delimiter) {
            throw new InvalidArgumentException('Split delimiter is empty.');
        }
        if (null !== $flags) {
            return parent::split($delimiter . 'u', $limit, $flags);
        }
        if (!preg_match('//u', $delimiter)) {
            throw new InvalidArgumentException('Split delimiter is not a valid UTF-8 string.');
        }
        $str = clone $this;
        $chunks = $this->ignoreCase ? preg_split('{' . preg_quote($delimiter) . '}iuD', $this->string, $limit) : explode($delimiter, $this->string, $limit);
        foreach ($chunks as &$chunk) {
            $str->string = $chunk;
            $chunk = clone $str;
        }
        return $chunks;
    }
    public function startsWith(string|iterable|AbstractString $prefix): bool
    {
        if ($prefix instanceof AbstractString) {
            $prefix = $prefix->string;
        } elseif (!\is_string($prefix)) {
            return parent::startsWith($prefix);
        }
        if ('' === $prefix || !preg_match('//u', $prefix)) {
            return \false;
        }
        if ($this->ignoreCase) {
            return 0 === mb_stripos($this->string, $prefix, 0, 'UTF-8');
        }
        return 0 === strncmp($this->string, $prefix, \strlen($prefix));
    }
}
Copyright (c) 2019-present Fabien Potencier

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is furnished
to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
CHANGELOG
=========

6.2
---

  * Add support for emoji in `AsciiSlugger`

5.4
---

 * Add `trimSuffix()` and `trimPrefix()` methods

5.3
---

 * Made `AsciiSlugger` fallback to parent locale's symbolsMap

5.2.0
-----

 * added a `FrenchInflector` class

5.1.0
-----

 * added the `AbstractString::reverse()` method
 * made `AbstractString::width()` follow POSIX.1-2001
 * added `LazyString` which provides memoizing stringable objects
 * The component is not marked as `@experimental` anymore
 * added the `s()` helper method to get either an `UnicodeString` or `ByteString` instance,
   depending of the input string UTF-8 compliancy
 * added `$cut` parameter to `Symfony\Component\String\AbstractString::truncate()`
 * added `AbstractString::containsAny()`
 * allow passing a string of custom characters to `ByteString::fromRandom()`

5.0.0
-----

 * added the component as experimental
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\String;

use _ContaoManager\Symfony\Component\String\Exception\ExceptionInterface;
use _ContaoManager\Symfony\Component\String\Exception\InvalidArgumentException;
use _ContaoManager\Symfony\Component\String\Exception\RuntimeException;
/**
 * Represents a string of abstract characters.
 *
 * Unicode defines 3 types of "characters" (bytes, code points and grapheme clusters).
 * This class is the abstract type to use as a type-hint when the logic you want to
 * implement doesn't care about the exact variant it deals with.
 *
 * @author Nicolas Grekas <p@tchwork.com>
 * @author Hugo Hamon <hugohamon@neuf.fr>
 *
 * @throws ExceptionInterface
 */
abstract class AbstractString implements \Stringable, \JsonSerializable
{
    public const PREG_PATTERN_ORDER = \PREG_PATTERN_ORDER;
    public const PREG_SET_ORDER = \PREG_SET_ORDER;
    public const PREG_OFFSET_CAPTURE = \PREG_OFFSET_CAPTURE;
    public const PREG_UNMATCHED_AS_NULL = \PREG_UNMATCHED_AS_NULL;
    public const PREG_SPLIT = 0;
    public const PREG_SPLIT_NO_EMPTY = \PREG_SPLIT_NO_EMPTY;
    public const PREG_SPLIT_DELIM_CAPTURE = \PREG_SPLIT_DELIM_CAPTURE;
    public const PREG_SPLIT_OFFSET_CAPTURE = \PREG_SPLIT_OFFSET_CAPTURE;
    protected $string = '';
    protected $ignoreCase = \false;
    abstract public function __construct(string $string = '');
    /**
     * Unwraps instances of AbstractString back to strings.
     *
     * @return string[]|array
     */
    public static function unwrap(array $values): array
    {
        foreach ($values as $k => $v) {
            if ($v instanceof self) {
                $values[$k] = $v->__toString();
            } elseif (\is_array($v) && $values[$k] !== $v = static::unwrap($v)) {
                $values[$k] = $v;
            }
        }
        return $values;
    }
    /**
     * Wraps (and normalizes) strings in instances of AbstractString.
     *
     * @return static[]|array
     */
    public static function wrap(array $values): array
    {
        $i = 0;
        $keys = null;
        foreach ($values as $k => $v) {
            if (\is_string($k) && '' !== $k && $k !== $j = (string) new static($k)) {
                $keys ??= array_keys($values);
                $keys[$i] = $j;
            }
            if (\is_string($v)) {
                $values[$k] = new static($v);
            } elseif (\is_array($v) && $values[$k] !== $v = static::wrap($v)) {
                $values[$k] = $v;
            }
            ++$i;
        }
        return null !== $keys ? array_combine($keys, $values) : $values;
    }
    /**
     * @param string|string[] $needle
     */
    public function after(string|iterable $needle, bool $includeNeedle = \false, int $offset = 0): static
    {
        $str = clone $this;
        $i = \PHP_INT_MAX;
        if (\is_string($needle)) {
            $needle = [$needle];
        }
        foreach ($needle as $n) {
            $n = (string) $n;
            $j = $this->indexOf($n, $offset);
            if (null !== $j && $j < $i) {
                $i = $j;
                $str->string = $n;
            }
        }
        if (\PHP_INT_MAX === $i) {
            return $str;
        }
        if (!$includeNeedle) {
            $i += $str->length();
        }
        return $this->slice($i);
    }
    /**
     * @param string|string[] $needle
     */
    public function afterLast(string|iterable $needle, bool $includeNeedle = \false, int $offset = 0): static
    {
        $str = clone $this;
        $i = null;
        if (\is_string($needle)) {
            $needle = [$needle];
        }
        foreach ($needle as $n) {
            $n = (string) $n;
            $j = $this->indexOfLast($n, $offset);
            if (null !== $j && $j >= $i) {
                $i = $offset = $j;
                $str->string = $n;
            }
        }
        if (null === $i) {
            return $str;
        }
        if (!$includeNeedle) {
            $i += $str->length();
        }
        return $this->slice($i);
    }
    abstract public function append(string ...$suffix): static;
    /**
     * @param string|string[] $needle
     */
    public function before(string|iterable $needle, bool $includeNeedle = \false, int $offset = 0): static
    {
        $str = clone $this;
        $i = \PHP_INT_MAX;
        if (\is_string($needle)) {
            $needle = [$needle];
        }
        foreach ($needle as $n) {
            $n = (string) $n;
            $j = $this->indexOf($n, $offset);
            if (null !== $j && $j < $i) {
                $i = $j;
                $str->string = $n;
            }
        }
        if (\PHP_INT_MAX === $i) {
            return $str;
        }
        if ($includeNeedle) {
            $i += $str->length();
        }
        return $this->slice(0, $i);
    }
    /**
     * @param string|string[] $needle
     */
    public function beforeLast(string|iterable $needle, bool $includeNeedle = \false, int $offset = 0): static
    {
        $str = clone $this;
        $i = null;
        if (\is_string($needle)) {
            $needle = [$needle];
        }
        foreach ($needle as $n) {
            $n = (string) $n;
            $j = $this->indexOfLast($n, $offset);
            if (null !== $j && $j >= $i) {
                $i = $offset = $j;
                $str->string = $n;
            }
        }
        if (null === $i) {
            return $str;
        }
        if ($includeNeedle) {
            $i += $str->length();
        }
        return $this->slice(0, $i);
    }
    /**
     * @return int[]
     */
    public function bytesAt(int $offset): array
    {
        $str = $this->slice($offset, 1);
        return '' === $str->string ? [] : array_values(unpack('C*', $str->string));
    }
    abstract public function camel(): static;
    /**
     * @return static[]
     */
    abstract public function chunk(int $length = 1): array;
    public function collapseWhitespace(): static
    {
        $str = clone $this;
        $str->string = trim(preg_replace("/(?:[ \n\r\t\f]{2,}+|[\n\r\t\f])/", ' ', $str->string), " \n\r\t\f");
        return $str;
    }
    /**
     * @param string|string[] $needle
     */
    public function containsAny(string|iterable $needle): bool
    {
        return null !== $this->indexOf($needle);
    }
    /**
     * @param string|string[] $suffix
     */
    public function endsWith(string|iterable $suffix): bool
    {
        if (\is_string($suffix)) {
            throw new \TypeError(\sprintf('Method "%s()" must be overridden by class "%s" to deal with non-iterable values.', __FUNCTION__, static::class));
        }
        foreach ($suffix as $s) {
            if ($this->endsWith((string) $s)) {
                return \true;
            }
        }
        return \false;
    }
    public function ensureEnd(string $suffix): static
    {
        if (!$this->endsWith($suffix)) {
            return $this->append($suffix);
        }
        $suffix = preg_quote($suffix);
        $regex = '{(' . $suffix . ')(?:' . $suffix . ')++$}D';
        return $this->replaceMatches($regex . ($this->ignoreCase ? 'i' : ''), '$1');
    }
    public function ensureStart(string $prefix): static
    {
        $prefix = new static($prefix);
        if (!$this->startsWith($prefix)) {
            return $this->prepend($prefix);
        }
        $str = clone $this;
        $i = $prefixLen = $prefix->length();
        while ($this->indexOf($prefix, $i) === $i) {
            $str = $str->slice($prefixLen);
            $i += $prefixLen;
        }
        return $str;
    }
    /**
     * @param string|string[] $string
     */
    public function equalsTo(string|iterable $string): bool
    {
        if (\is_string($string)) {
            throw new \TypeError(\sprintf('Method "%s()" must be overridden by class "%s" to deal with non-iterable values.', __FUNCTION__, static::class));
        }
        foreach ($string as $s) {
            if ($this->equalsTo((string) $s)) {
                return \true;
            }
        }
        return \false;
    }
    abstract public function folded(): static;
    public function ignoreCase(): static
    {
        $str = clone $this;
        $str->ignoreCase = \true;
        return $str;
    }
    /**
     * @param string|string[] $needle
     */
    public function indexOf(string|iterable $needle, int $offset = 0): ?int
    {
        if (\is_string($needle)) {
            throw new \TypeError(\sprintf('Method "%s()" must be overridden by class "%s" to deal with non-iterable values.', __FUNCTION__, static::class));
        }
        $i = \PHP_INT_MAX;
        foreach ($needle as $n) {
            $j = $this->indexOf((string) $n, $offset);
            if (null !== $j && $j < $i) {
                $i = $j;
            }
        }
        return \PHP_INT_MAX === $i ? null : $i;
    }
    /**
     * @param string|string[] $needle
     */
    public function indexOfLast(string|iterable $needle, int $offset = 0): ?int
    {
        if (\is_string($needle)) {
            throw new \TypeError(\sprintf('Method "%s()" must be overridden by class "%s" to deal with non-iterable values.', __FUNCTION__, static::class));
        }
        $i = null;
        foreach ($needle as $n) {
            $j = $this->indexOfLast((string) $n, $offset);
            if (null !== $j && $j >= $i) {
                $i = $offset = $j;
            }
        }
        return $i;
    }
    public function isEmpty(): bool
    {
        return '' === $this->string;
    }
    abstract public function join(array $strings, ?string $lastGlue = null): static;
    public function jsonSerialize(): string
    {
        return $this->string;
    }
    abstract public function length(): int;
    abstract public function lower(): static;
    /**
     * Matches the string using a regular expression.
     *
     * Pass PREG_PATTERN_ORDER or PREG_SET_ORDER as $flags to get all occurrences matching the regular expression.
     *
     * @return array All matches in a multi-dimensional array ordered according to flags
     */
    abstract public function match(string $regexp, int $flags = 0, int $offset = 0): array;
    abstract public function padBoth(int $length, string $padStr = ' '): static;
    abstract public function padEnd(int $length, string $padStr = ' '): static;
    abstract public function padStart(int $length, string $padStr = ' '): static;
    abstract public function prepend(string ...$prefix): static;
    public function repeat(int $multiplier): static
    {
        if (0 > $multiplier) {
            throw new InvalidArgumentException(\sprintf('Multiplier must be positive, %d given.', $multiplier));
        }
        $str = clone $this;
        $str->string = str_repeat($str->string, $multiplier);
        return $str;
    }
    abstract public function replace(string $from, string $to): static;
    abstract public function replaceMatches(string $fromRegexp, string|callable $to): static;
    abstract public function reverse(): static;
    abstract public function slice(int $start = 0, ?int $length = null): static;
    abstract public function snake(): static;
    abstract public function splice(string $replacement, int $start = 0, ?int $length = null): static;
    /**
     * @return static[]
     */
    public function split(string $delimiter, ?int $limit = null, ?int $flags = null): array
    {
        if (null === $flags) {
            throw new \TypeError('Split behavior when $flags is null must be implemented by child classes.');
        }
        if ($this->ignoreCase) {
            $delimiter .= 'i';
        }
        set_error_handler(static fn($t, $m) => throw new InvalidArgumentException($m));
        try {
            if (\false === $chunks = preg_split($delimiter, $this->string, $limit, $flags)) {
                throw new RuntimeException('Splitting failed with error: ' . preg_last_error_msg());
            }
        } finally {
            restore_error_handler();
        }
        $str = clone $this;
        if (self::PREG_SPLIT_OFFSET_CAPTURE & $flags) {
            foreach ($chunks as &$chunk) {
                $str->string = $chunk[0];
                $chunk[0] = clone $str;
            }
        } else {
            foreach ($chunks as &$chunk) {
                $str->string = $chunk;
                $chunk = clone $str;
            }
        }
        return $chunks;
    }
    /**
     * @param string|string[] $prefix
     */
    public function startsWith(string|iterable $prefix): bool
    {
        if (\is_string($prefix)) {
            throw new \TypeError(\sprintf('Method "%s()" must be overridden by class "%s" to deal with non-iterable values.', __FUNCTION__, static::class));
        }
        foreach ($prefix as $prefix) {
            if ($this->startsWith((string) $prefix)) {
                return \true;
            }
        }
        return \false;
    }
    abstract public function title(bool $allWords = \false): static;
    public function toByteString(?string $toEncoding = null): ByteString
    {
        $b = new ByteString();
        $toEncoding = \in_array($toEncoding, ['utf8', 'utf-8', 'UTF8'], \true) ? 'UTF-8' : $toEncoding;
        if (null === $toEncoding || $toEncoding === $fromEncoding = $this instanceof AbstractUnicodeString || preg_match('//u', $b->string) ? 'UTF-8' : 'Windows-1252') {
            $b->string = $this->string;
            return $b;
        }
        try {
            $b->string = mb_convert_encoding($this->string, $toEncoding, 'UTF-8');
        } catch (\ValueError $e) {
            if (!\function_exists('iconv') && !\function_exists('_ContaoManager\iconv')) {
                throw new InvalidArgumentException($e->getMessage(), $e->getCode(), $e);
            }
            $b->string = iconv('UTF-8', $toEncoding, $this->string);
        }
        return $b;
    }
    public function toCodePointString(): CodePointString
    {
        return new CodePointString($this->string);
    }
    public function toString(): string
    {
        return $this->string;
    }
    public function toUnicodeString(): UnicodeString
    {
        return new UnicodeString($this->string);
    }
    abstract public function trim(string $chars = " \t\n\r\x00\v\f ﻿"): static;
    abstract public function trimEnd(string $chars = " \t\n\r\x00\v\f ﻿"): static;
    /**
     * @param string|string[] $prefix
     */
    public function trimPrefix($prefix): static
    {
        if (\is_array($prefix) || $prefix instanceof \Traversable) {
            // don't use is_iterable(), it's slow
            foreach ($prefix as $s) {
                $t = $this->trimPrefix($s);
                if ($t->string !== $this->string) {
                    return $t;
                }
            }
            return clone $this;
        }
        $str = clone $this;
        if ($prefix instanceof self) {
            $prefix = $prefix->string;
        } else {
            $prefix = (string) $prefix;
        }
        if ('' !== $prefix && \strlen($this->string) >= \strlen($prefix) && 0 === substr_compare($this->string, $prefix, 0, \strlen($prefix), $this->ignoreCase)) {
            $str->string = substr($this->string, \strlen($prefix));
        }
        return $str;
    }
    abstract public function trimStart(string $chars = " \t\n\r\x00\v\f ﻿"): static;
    /**
     * @param string|string[] $suffix
     */
    public function trimSuffix($suffix): static
    {
        if (\is_array($suffix) || $suffix instanceof \Traversable) {
            // don't use is_iterable(), it's slow
            foreach ($suffix as $s) {
                $t = $this->trimSuffix($s);
                if ($t->string !== $this->string) {
                    return $t;
                }
            }
            return clone $this;
        }
        $str = clone $this;
        if ($suffix instanceof self) {
            $suffix = $suffix->string;
        } else {
            $suffix = (string) $suffix;
        }
        if ('' !== $suffix && \strlen($this->string) >= \strlen($suffix) && 0 === substr_compare($this->string, $suffix, -\strlen($suffix), null, $this->ignoreCase)) {
            $str->string = substr($this->string, 0, -\strlen($suffix));
        }
        return $str;
    }
    public function truncate(int $length, string $ellipsis = '', bool $cut = \true): static
    {
        $stringLength = $this->length();
        if ($stringLength <= $length) {
            return clone $this;
        }
        $ellipsisLength = '' !== $ellipsis ? (new static($ellipsis))->length() : 0;
        if ($length < $ellipsisLength) {
            $ellipsisLength = 0;
        }
        if (!$cut) {
            if (null === $length = $this->indexOf([' ', "\r", "\n", "\t"], ($length ?: 1) - 1)) {
                return clone $this;
            }
            $length += $ellipsisLength;
        }
        $str = $this->slice(0, $length - $ellipsisLength);
        return $ellipsisLength ? $str->trimEnd()->append($ellipsis) : $str;
    }
    abstract public function upper(): static;
    /**
     * Returns the printable length on a terminal.
     */
    abstract public function width(bool $ignoreAnsiDecoration = \true): int;
    public function wordwrap(int $width = 75, string $break = "\n", bool $cut = \false): static
    {
        $lines = '' !== $break ? $this->split($break) : [clone $this];
        $chars = [];
        $mask = '';
        if (1 === \count($lines) && '' === $lines[0]->string) {
            return $lines[0];
        }
        foreach ($lines as $i => $line) {
            if ($i) {
                $chars[] = $break;
                $mask .= '#';
            }
            foreach ($line->chunk() as $char) {
                $chars[] = $char->string;
                $mask .= ' ' === $char->string ? ' ' : '?';
            }
        }
        $string = '';
        $j = 0;
        $b = $i = -1;
        $mask = wordwrap($mask, $width, '#', $cut);
        while (\false !== $b = strpos($mask, '#', $b + 1)) {
            for (++$i; $i < $b; ++$i) {
                $string .= $chars[$j];
                unset($chars[$j++]);
            }
            if ($break === $chars[$j] || ' ' === $chars[$j]) {
                unset($chars[$j++]);
            }
            $string .= $break;
        }
        $str = clone $this;
        $str->string = $string . implode('', $chars);
        return $str;
    }
    public function __sleep(): array
    {
        return ['string'];
    }
    public function __clone()
    {
        $this->ignoreCase = \false;
    }
    public function __toString(): string
    {
        return $this->string;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\String;

if (!\function_exists(u::class)) {
    function u(?string $string = ''): UnicodeString
    {
        return new UnicodeString($string ?? '');
    }
}
if (!\function_exists(b::class)) {
    function b(?string $string = ''): ByteString
    {
        return new ByteString($string ?? '');
    }
}
if (!\function_exists(s::class)) {
    /**
     * @return UnicodeString|ByteString
     */
    function s(?string $string = ''): AbstractString
    {
        $string ??= '';
        return preg_match('//u', $string) ? new UnicodeString($string) : new ByteString($string);
    }
}
<?php

namespace _ContaoManager;

/*
 * This file has been auto-generated by the Symfony String Component for internal use.
 *
 * Unicode version: 16.0.0
 * Date: 2024-09-11T08:21:22+00:00
 */
return [[768, 879], [1155, 1159], [1160, 1161], [1425, 1469], [1471, 1471], [1473, 1474], [1476, 1477], [1479, 1479], [1552, 1562], [1611, 1631], [1648, 1648], [1750, 1756], [1759, 1764], [1767, 1768], [1770, 1773], [1809, 1809], [1840, 1866], [1958, 1968], [2027, 2035], [2045, 2045], [2070, 2073], [2075, 2083], [2085, 2087], [2089, 2093], [2137, 2139], [2199, 2207], [2250, 2273], [2275, 2306], [2362, 2362], [2364, 2364], [2369, 2376], [2381, 2381], [2385, 2391], [2402, 2403], [2433, 2433], [2492, 2492], [2497, 2500], [2509, 2509], [2530, 2531], [2558, 2558], [2561, 2562], [2620, 2620], [2625, 2626], [2631, 2632], [2635, 2637], [2641, 2641], [2672, 2673], [2677, 2677], [2689, 2690], [2748, 2748], [2753, 2757], [2759, 2760], [2765, 2765], [2786, 2787], [2810, 2815], [2817, 2817], [2876, 2876], [2879, 2879], [2881, 2884], [2893, 2893], [2901, 2902], [2914, 2915], [2946, 2946], [3008, 3008], [3021, 3021], [3072, 3072], [3076, 3076], [3132, 3132], [3134, 3136], [3142, 3144], [3146, 3149], [3157, 3158], [3170, 3171], [3201, 3201], [3260, 3260], [3263, 3263], [3270, 3270], [3276, 3277], [3298, 3299], [3328, 3329], [3387, 3388], [3393, 3396], [3405, 3405], [3426, 3427], [3457, 3457], [3530, 3530], [3538, 3540], [3542, 3542], [3633, 3633], [3636, 3642], [3655, 3662], [3761, 3761], [3764, 3772], [3784, 3790], [3864, 3865], [3893, 3893], [3895, 3895], [3897, 3897], [3953, 3966], [3968, 3972], [3974, 3975], [3981, 3991], [3993, 4028], [4038, 4038], [4141, 4144], [4146, 4151], [4153, 4154], [4157, 4158], [4184, 4185], [4190, 4192], [4209, 4212], [4226, 4226], [4229, 4230], [4237, 4237], [4253, 4253], [4957, 4959], [5906, 5908], [5938, 5939], [5970, 5971], [6002, 6003], [6068, 6069], [6071, 6077], [6086, 6086], [6089, 6099], [6109, 6109], [6155, 6157], [6159, 6159], [6277, 6278], [6313, 6313], [6432, 6434], [6439, 6440], [6450, 6450], [6457, 6459], [6679, 6680], [6683, 6683], [6742, 6742], [6744, 6750], [6752, 6752], [6754, 6754], [6757, 6764], [6771, 6780], [6783, 6783], [6832, 6845], [6846, 6846], [6847, 6862], [6912, 6915], [6964, 6964], [6966, 6970], [6972, 6972], [6978, 6978], [7019, 7027], [7040, 7041], [7074, 7077], [7080, 7081], [7083, 7085], [7142, 7142], [7144, 7145], [7149, 7149], [7151, 7153], [7212, 7219], [7222, 7223], [7376, 7378], [7380, 7392], [7394, 7400], [7405, 7405], [7412, 7412], [7416, 7417], [7616, 7679], [8400, 8412], [8413, 8416], [8417, 8417], [8418, 8420], [8421, 8432], [11503, 11505], [11647, 11647], [11744, 11775], [12330, 12333], [12441, 12442], [42607, 42607], [42608, 42610], [42612, 42621], [42654, 42655], [42736, 42737], [43010, 43010], [43014, 43014], [43019, 43019], [43045, 43046], [43052, 43052], [43204, 43205], [43232, 43249], [43263, 43263], [43302, 43309], [43335, 43345], [43392, 43394], [43443, 43443], [43446, 43449], [43452, 43453], [43493, 43493], [43561, 43566], [43569, 43570], [43573, 43574], [43587, 43587], [43596, 43596], [43644, 43644], [43696, 43696], [43698, 43700], [43703, 43704], [43710, 43711], [43713, 43713], [43756, 43757], [43766, 43766], [44005, 44005], [44008, 44008], [44013, 44013], [64286, 64286], [65024, 65039], [65056, 65071], [66045, 66045], [66272, 66272], [66422, 66426], [68097, 68099], [68101, 68102], [68108, 68111], [68152, 68154], [68159, 68159], [68325, 68326], [68900, 68903], [68969, 68973], [69291, 69292], [69372, 69375], [69446, 69456], [69506, 69509], [69633, 69633], [69688, 69702], [69744, 69744], [69747, 69748], [69759, 69761], [69811, 69814], [69817, 69818], [69826, 69826], [69888, 69890], [69927, 69931], [69933, 69940], [70003, 70003], [70016, 70017], [70070, 70078], [70089, 70092], [70095, 70095], [70191, 70193], [70196, 70196], [70198, 70199], [70206, 70206], [70209, 70209], [70367, 70367], [70371, 70378], [70400, 70401], [70459, 70460], [70464, 70464], [70502, 70508], [70512, 70516], [70587, 70592], [70606, 70606], [70608, 70608], [70610, 70610], [70625, 70626], [70712, 70719], [70722, 70724], [70726, 70726], [70750, 70750], [70835, 70840], [70842, 70842], [70847, 70848], [70850, 70851], [71090, 71093], [71100, 71101], [71103, 71104], [71132, 71133], [71219, 71226], [71229, 71229], [71231, 71232], [71339, 71339], [71341, 71341], [71344, 71349], [71351, 71351], [71453, 71453], [71455, 71455], [71458, 71461], [71463, 71467], [71727, 71735], [71737, 71738], [71995, 71996], [71998, 71998], [72003, 72003], [72148, 72151], [72154, 72155], [72160, 72160], [72193, 72202], [72243, 72248], [72251, 72254], [72263, 72263], [72273, 72278], [72281, 72283], [72330, 72342], [72344, 72345], [72752, 72758], [72760, 72765], [72767, 72767], [72850, 72871], [72874, 72880], [72882, 72883], [72885, 72886], [73009, 73014], [73018, 73018], [73020, 73021], [73023, 73029], [73031, 73031], [73104, 73105], [73109, 73109], [73111, 73111], [73459, 73460], [73472, 73473], [73526, 73530], [73536, 73536], [73538, 73538], [73562, 73562], [78912, 78912], [78919, 78933], [90398, 90409], [90413, 90415], [92912, 92916], [92976, 92982], [94031, 94031], [94095, 94098], [94180, 94180], [113821, 113822], [118528, 118573], [118576, 118598], [119143, 119145], [119163, 119170], [119173, 119179], [119210, 119213], [119362, 119364], [121344, 121398], [121403, 121452], [121461, 121461], [121476, 121476], [121499, 121503], [121505, 121519], [122880, 122886], [122888, 122904], [122907, 122913], [122915, 122916], [122918, 122922], [123023, 123023], [123184, 123190], [123566, 123566], [123628, 123631], [124140, 124143], [124398, 124399], [125136, 125142], [125252, 125258], [917760, 917999]];
<?php

namespace _ContaoManager;

/*
 * This file has been auto-generated by the Symfony String Component for internal use.
 *
 * Unicode version: 16.0.0
 * Date: 2024-09-11T08:21:22+00:00
 */
return [[4352, 4447], [8986, 8987], [9001, 9001], [9002, 9002], [9193, 9196], [9200, 9200], [9203, 9203], [9725, 9726], [9748, 9749], [9776, 9783], [9800, 9811], [9855, 9855], [9866, 9871], [9875, 9875], [9889, 9889], [9898, 9899], [9917, 9918], [9924, 9925], [9934, 9934], [9940, 9940], [9962, 9962], [9970, 9971], [9973, 9973], [9978, 9978], [9981, 9981], [9989, 9989], [9994, 9995], [10024, 10024], [10060, 10060], [10062, 10062], [10067, 10069], [10071, 10071], [10133, 10135], [10160, 10160], [10175, 10175], [11035, 11036], [11088, 11088], [11093, 11093], [11904, 11929], [11931, 12019], [12032, 12245], [12272, 12287], [12288, 12288], [12289, 12291], [12292, 12292], [12293, 12293], [12294, 12294], [12295, 12295], [12296, 12296], [12297, 12297], [12298, 12298], [12299, 12299], [12300, 12300], [12301, 12301], [12302, 12302], [12303, 12303], [12304, 12304], [12305, 12305], [12306, 12307], [12308, 12308], [12309, 12309], [12310, 12310], [12311, 12311], [12312, 12312], [12313, 12313], [12314, 12314], [12315, 12315], [12316, 12316], [12317, 12317], [12318, 12319], [12320, 12320], [12321, 12329], [12330, 12333], [12334, 12335], [12336, 12336], [12337, 12341], [12342, 12343], [12344, 12346], [12347, 12347], [12348, 12348], [12349, 12349], [12350, 12350], [12353, 12438], [12441, 12442], [12443, 12444], [12445, 12446], [12447, 12447], [12448, 12448], [12449, 12538], [12539, 12539], [12540, 12542], [12543, 12543], [12549, 12591], [12593, 12686], [12688, 12689], [12690, 12693], [12694, 12703], [12704, 12735], [12736, 12773], [12783, 12783], [12784, 12799], [12800, 12830], [12832, 12841], [12842, 12871], [12880, 12880], [12881, 12895], [12896, 12927], [12928, 12937], [12938, 12976], [12977, 12991], [12992, 13055], [13056, 13311], [13312, 19903], [19904, 19967], [19968, 40959], [40960, 40980], [40981, 40981], [40982, 42124], [42128, 42182], [43360, 43388], [44032, 55203], [63744, 64109], [64110, 64111], [64112, 64217], [64218, 64255], [65040, 65046], [65047, 65047], [65048, 65048], [65049, 65049], [65072, 65072], [65073, 65074], [65075, 65076], [65077, 65077], [65078, 65078], [65079, 65079], [65080, 65080], [65081, 65081], [65082, 65082], [65083, 65083], [65084, 65084], [65085, 65085], [65086, 65086], [65087, 65087], [65088, 65088], [65089, 65089], [65090, 65090], [65091, 65091], [65092, 65092], [65093, 65094], [65095, 65095], [65096, 65096], [65097, 65100], [65101, 65103], [65104, 65106], [65108, 65111], [65112, 65112], [65113, 65113], [65114, 65114], [65115, 65115], [65116, 65116], [65117, 65117], [65118, 65118], [65119, 65121], [65122, 65122], [65123, 65123], [65124, 65126], [65128, 65128], [65129, 65129], [65130, 65131], [65281, 65283], [65284, 65284], [65285, 65287], [65288, 65288], [65289, 65289], [65290, 65290], [65291, 65291], [65292, 65292], [65293, 65293], [65294, 65295], [65296, 65305], [65306, 65307], [65308, 65310], [65311, 65312], [65313, 65338], [65339, 65339], [65340, 65340], [65341, 65341], [65342, 65342], [65343, 65343], [65344, 65344], [65345, 65370], [65371, 65371], [65372, 65372], [65373, 65373], [65374, 65374], [65375, 65375], [65376, 65376], [65504, 65505], [65506, 65506], [65507, 65507], [65508, 65508], [65509, 65510], [94176, 94177], [94178, 94178], [94179, 94179], [94180, 94180], [94192, 94193], [94208, 100343], [100352, 101119], [101120, 101589], [101631, 101631], [101632, 101640], [110576, 110579], [110581, 110587], [110589, 110590], [110592, 110847], [110848, 110882], [110898, 110898], [110928, 110930], [110933, 110933], [110948, 110951], [110960, 111355], [119552, 119638], [119648, 119670], [126980, 126980], [127183, 127183], [127374, 127374], [127377, 127386], [127488, 127490], [127504, 127547], [127552, 127560], [127568, 127569], [127584, 127589], [127744, 127776], [127789, 127797], [127799, 127868], [127870, 127891], [127904, 127946], [127951, 127955], [127968, 127984], [127988, 127988], [127992, 127994], [127995, 127999], [128000, 128062], [128064, 128064], [128066, 128252], [128255, 128317], [128331, 128334], [128336, 128359], [128378, 128378], [128405, 128406], [128420, 128420], [128507, 128511], [128512, 128591], [128640, 128709], [128716, 128716], [128720, 128722], [128725, 128727], [128732, 128735], [128747, 128748], [128756, 128764], [128992, 129003], [129008, 129008], [129292, 129338], [129340, 129349], [129351, 129535], [129648, 129660], [129664, 129673], [129679, 129734], [129742, 129756], [129759, 129769], [129776, 129784], [131072, 173791], [173792, 173823], [173824, 177977], [177978, 177983], [177984, 178205], [178206, 178207], [178208, 183969], [183970, 183983], [183984, 191456], [191457, 191471], [191472, 192093], [192094, 194559], [194560, 195101], [195102, 195103], [195104, 196605], [196608, 201546], [201547, 201551], [201552, 205743], [205744, 262141]];
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\String\Inflector;

/**
 * French inflector.
 *
 * This class does only inflect nouns; not adjectives nor composed words like "soixante-dix".
 */
final class FrenchInflector implements InflectorInterface
{
    /**
     * A list of all rules for pluralise.
     *
     * @see https://la-conjugaison.nouvelobs.com/regles/grammaire/le-pluriel-des-noms-121.php
     */
    private const PLURALIZE_REGEXP = [
        // First entry: regexp
        // Second entry: replacement
        // Words finishing with "s", "x" or "z" are invariables
        // Les mots finissant par "s", "x" ou "z" sont invariables
        ['/(s|x|z)$/i', '\1'],
        // Words finishing with "eau" are pluralized with a "x"
        // Les mots finissant par "eau" prennent tous un "x" au pluriel
        ['/(eau)$/i', '\1x'],
        // Words finishing with "au" are pluralized with a "x" excepted "landau"
        // Les mots finissant par "au" prennent un "x" au pluriel sauf "landau"
        ['/^(landau)$/i', '\1s'],
        ['/(au)$/i', '\1x'],
        // Words finishing with "eu" are pluralized with a "x" excepted "pneu", "bleu", "émeu"
        // Les mots finissant en "eu" prennent un "x" au pluriel sauf "pneu", "bleu", "émeu"
        ['/^(pneu|bleu|émeu)$/i', '\1s'],
        ['/(eu)$/i', '\1x'],
        // Words finishing with "al" are pluralized with a "aux" excepted
        // Les mots finissant en "al" se terminent en "aux" sauf
        ['/^(bal|carnaval|caracal|chacal|choral|corral|étal|festival|récital|val)$/i', '\1s'],
        ['/al$/i', '\1aux'],
        // Aspirail, bail, corail, émail, fermail, soupirail, travail, vantail et vitrail font leur pluriel en -aux
        ['/^(aspir|b|cor|ém|ferm|soupir|trav|vant|vitr)ail$/i', '\1aux'],
        // Bijou, caillou, chou, genou, hibou, joujou et pou qui prennent un x au pluriel
        ['/^(bij|caill|ch|gen|hib|jouj|p)ou$/i', '\1oux'],
        // Invariable words
        ['/^(cinquante|soixante|mille)$/i', '\1'],
        // French titles
        ['/^(mon|ma)(sieur|dame|demoiselle|seigneur)$/', '_ContaoManager\mes\2s'],
        ['/^(Mon|Ma)(sieur|dame|demoiselle|seigneur)$/', '_ContaoManager\Mes\2s'],
    ];
    /**
     * A list of all rules for singularize.
     */
    private const SINGULARIZE_REGEXP = [
        // First entry: regexp
        // Second entry: replacement
        // Aspirail, bail, corail, émail, fermail, soupirail, travail, vantail et vitrail font leur pluriel en -aux
        ['/((aspir|b|cor|ém|ferm|soupir|trav|vant|vitr))aux$/i', '\1ail'],
        // Words finishing with "eau" are pluralized with a "x"
        // Les mots finissant par "eau" prennent tous un "x" au pluriel
        ['/(eau)x$/i', '\1'],
        // Words finishing with "al" are pluralized with a "aux" expected
        // Les mots finissant en "al" se terminent en "aux" sauf
        ['/(amir|anim|arsen|boc|can|capit|capor|chev|crist|génér|hopit|hôpit|idé|journ|littor|loc|m|mét|minér|princip|radic|termin)aux$/i', '\1al'],
        // Words finishing with "au" are pluralized with a "x" excepted "landau"
        // Les mots finissant par "au" prennent un "x" au pluriel sauf "landau"
        ['/(au)x$/i', '\1'],
        // Words finishing with "eu" are pluralized with a "x" excepted "pneu", "bleu", "émeu"
        // Les mots finissant en "eu" prennent un "x" au pluriel sauf "pneu", "bleu", "émeu"
        ['/(eu)x$/i', '\1'],
        //  Words finishing with "ou" are pluralized with a "s" excepted bijou, caillou, chou, genou, hibou, joujou, pou
        // Les mots finissant par "ou" prennent un "s" sauf bijou, caillou, chou, genou, hibou, joujou, pou
        ['/(bij|caill|ch|gen|hib|jouj|p)oux$/i', '\1ou'],
        // French titles
        ['/^mes(dame|demoiselle)s$/', '_ContaoManager\ma\1'],
        ['/^Mes(dame|demoiselle)s$/', '_ContaoManager\Ma\1'],
        ['/^mes(sieur|seigneur)s$/', '_ContaoManager\mon\1'],
        ['/^Mes(sieur|seigneur)s$/', '_ContaoManager\Mon\1'],
        // Default rule
        ['/s$/i', ''],
    ];
    /**
     * A list of words which should not be inflected.
     * This list is only used by singularize.
     */
    private const UNINFLECTED = '/^(abcès|accès|abus|albatros|anchois|anglais|autobus|bois|brebis|carquois|cas|chas|colis|concours|corps|cours|cyprès|décès|devis|discours|dos|embarras|engrais|entrelacs|excès|fils|fois|gâchis|gars|glas|héros|intrus|jars|jus|kermès|lacis|legs|lilas|marais|mars|matelas|mépris|mets|mois|mors|obus|os|palais|paradis|parcours|pardessus|pays|plusieurs|poids|pois|pouls|printemps|processus|progrès|puits|pus|rabais|radis|recors|recours|refus|relais|remords|remous|rictus|rhinocéros|repas|rubis|sans|sas|secours|sens|souris|succès|talus|tapis|tas|taudis|temps|tiers|univers|velours|verglas|vernis|virus)$/i';
    public function singularize(string $plural): array
    {
        if ($this->isInflectedWord($plural)) {
            return [$plural];
        }
        foreach (self::SINGULARIZE_REGEXP as $rule) {
            [$regexp, $replace] = $rule;
            if (1 === preg_match($regexp, $plural)) {
                return [preg_replace($regexp, $replace, $plural)];
            }
        }
        return [$plural];
    }
    public function pluralize(string $singular): array
    {
        if ($this->isInflectedWord($singular)) {
            return [$singular];
        }
        foreach (self::PLURALIZE_REGEXP as $rule) {
            [$regexp, $replace] = $rule;
            if (1 === preg_match($regexp, $singular)) {
                return [preg_replace($regexp, $replace, $singular)];
            }
        }
        return [$singular . 's'];
    }
    private function isInflectedWord(string $word): bool
    {
        return 1 === preg_match(self::UNINFLECTED, $word);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\String\Inflector;

interface InflectorInterface
{
    /**
     * Returns the singular forms of a string.
     *
     * If the method can't determine the form with certainty, several possible singulars are returned.
     *
     * @return string[]
     */
    public function singularize(string $plural): array;
    /**
     * Returns the plural forms of a string.
     *
     * If the method can't determine the form with certainty, several possible plurals are returned.
     *
     * @return string[]
     */
    public function pluralize(string $singular): array;
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\String\Inflector;

final class EnglishInflector implements InflectorInterface
{
    /**
     * Map English plural to singular suffixes.
     *
     * @see http://english-zone.com/spelling/plurals.html
     */
    private const PLURAL_MAP = [
        // First entry: plural suffix, reversed
        // Second entry: length of plural suffix
        // Third entry: Whether the suffix may succeed a vowel
        // Fourth entry: Whether the suffix may succeed a consonant
        // Fifth entry: singular suffix, normal
        // insignias (insigne), insignia (insigne)
        ['saingisni', 9, \true, \true, 'insigne'],
        ['aingisni', 8, \true, \true, 'insigne'],
        // passersby (passerby)
        ['ybsressap', 9, \true, \true, 'passerby'],
        // nodes (node)
        ['sedon', 5, \true, \true, 'node'],
        // bacteria (bacterium)
        ['airetcab', 8, \true, \true, 'bacterium'],
        // issues (issue)
        ['seussi', 6, \true, \true, 'issue'],
        // corpora (corpus)
        ['aroproc', 7, \true, \true, 'corpus'],
        // criteria (criterion)
        ['airetirc', 8, \true, \true, 'criterion'],
        // curricula (curriculum)
        ['alucirruc', 9, \true, \true, 'curriculum'],
        // quora (quorum)
        ['arouq', 5, \true, \true, 'quorum'],
        // genera (genus)
        ['areneg', 6, \true, \true, 'genus'],
        // media (medium)
        ['aidem', 5, \true, \true, 'medium'],
        // memoranda (memorandum)
        ['adnaromem', 9, \true, \true, 'memorandum'],
        // phenomena (phenomenon)
        ['anemonehp', 9, \true, \true, 'phenomenon'],
        // strata (stratum)
        ['atarts', 6, \true, \true, 'stratum'],
        // nebulae (nebula)
        ['ea', 2, \true, \true, 'a'],
        // services (service)
        ['secivres', 8, \true, \true, 'service'],
        // mice (mouse), lice (louse)
        ['eci', 3, \false, \true, 'ouse'],
        // geese (goose)
        ['esee', 4, \false, \true, 'oose'],
        // fungi (fungus), alumni (alumnus), syllabi (syllabus), radii (radius)
        ['i', 1, \true, \true, 'us'],
        // men (man), women (woman)
        ['nem', 3, \true, \true, 'man'],
        // children (child)
        ['nerdlihc', 8, \true, \true, 'child'],
        // oxen (ox)
        ['nexo', 4, \false, \false, 'ox'],
        // indices (index), appendices (appendix), prices (price)
        ['seci', 4, \false, \true, ['ex', 'ix', 'ice']],
        // codes (code)
        ['sedoc', 5, \false, \true, 'code'],
        // selfies (selfie)
        ['seifles', 7, \true, \true, 'selfie'],
        // zombies (zombie)
        ['seibmoz', 7, \true, \true, 'zombie'],
        // movies (movie)
        ['seivom', 6, \true, \true, 'movie'],
        // names (name)
        ['seman', 5, \true, \false, 'name'],
        // conspectuses (conspectus), prospectuses (prospectus)
        ['sesutcep', 8, \true, \true, 'pectus'],
        // feet (foot)
        ['teef', 4, \true, \true, 'foot'],
        // geese (goose)
        ['eseeg', 5, \true, \true, 'goose'],
        // teeth (tooth)
        ['hteet', 5, \true, \true, 'tooth'],
        // news (news)
        ['swen', 4, \true, \true, 'news'],
        // series (series)
        ['seires', 6, \true, \true, 'series'],
        // babies (baby)
        ['sei', 3, \false, \true, 'y'],
        // accesses (access), addresses (address), kisses (kiss)
        ['sess', 4, \true, \false, 'ss'],
        // statuses (status)
        ['sesutats', 8, \true, \true, 'status'],
        // article (articles), ancle (ancles)
        ['sel', 3, \true, \true, 'le'],
        // analyses (analysis), ellipses (ellipsis), fungi (fungus),
        // neuroses (neurosis), theses (thesis), emphases (emphasis),
        // oases (oasis), crises (crisis), houses (house), bases (base),
        // atlases (atlas)
        ['ses', 3, \true, \true, ['s', 'se', 'sis']],
        // objectives (objective), alternative (alternatives)
        ['sevit', 5, \true, \true, 'tive'],
        // drives (drive)
        ['sevird', 6, \false, \true, 'drive'],
        // lives (life), wives (wife)
        ['sevi', 4, \false, \true, 'ife'],
        // moves (move)
        ['sevom', 5, \true, \true, 'move'],
        // hooves (hoof), dwarves (dwarf), elves (elf), leaves (leaf), caves (cave), staves (staff)
        ['sev', 3, \true, \true, ['f', 've', 'ff']],
        // axes (axis), axes (ax), axes (axe)
        ['sexa', 4, \false, \false, ['ax', 'axe', 'axis']],
        // indexes (index), matrixes (matrix)
        ['sex', 3, \true, \false, 'x'],
        // quizzes (quiz)
        ['sezz', 4, \true, \false, 'z'],
        // bureaus (bureau)
        ['suae', 4, \false, \true, 'eau'],
        // fees (fee), trees (tree), employees (employee)
        ['see', 3, \true, \true, 'ee'],
        // edges (edge)
        ['segd', 4, \true, \true, 'dge'],
        // outages (outage) - specific fix to avoid 'outag'
        ['segatuo', 7, \true, \true, 'outage'],
        // roses (rose), garages (garage), cassettes (cassette),
        // waltzes (waltz), heroes (hero), bushes (bush), arches (arch),
        // shoes (shoe)
        ['se', 2, \true, \true, ['', 'e']],
        // status (status)
        ['sutats', 6, \true, \true, 'status'],
        // tags (tag)
        ['s', 1, \true, \true, ''],
        // chateaux (chateau)
        ['xuae', 4, \false, \true, 'eau'],
        // people (person)
        ['elpoep', 6, \true, \true, 'person'],
    ];
    /**
     * Map English singular to plural suffixes.
     *
     * @see http://english-zone.com/spelling/plurals.html
     */
    private const SINGULAR_MAP = [
        // First entry: singular suffix, reversed
        // Second entry: length of singular suffix
        // Third entry: Whether the suffix may succeed a vowel
        // Fourth entry: Whether the suffix may succeed a consonant
        // Fifth entry: plural suffix, normal
        // passerby (passersby)
        ['ybressap', 8, \true, \true, 'passersby'],
        // insigne (insignia, insignias)
        ['engisni', 7, \true, \true, ['insignia', 'insignias']],
        // nodes (node)
        ['edon', 4, \true, \true, 'nodes'],
        // axes (axis)
        ['sixa', 4, \false, \false, 'axes'],
        // criterion (criteria)
        ['airetirc', 8, \false, \false, 'criterion'],
        // nebulae (nebula)
        ['aluben', 6, \false, \false, 'nebulae'],
        // children (child)
        ['dlihc', 5, \true, \true, 'children'],
        // prices (price)
        ['eci', 3, \false, \true, 'ices'],
        // services (service)
        ['ecivres', 7, \true, \true, 'services'],
        // lives (life), wives (wife)
        ['efi', 3, \false, \true, 'ives'],
        // selfies (selfie)
        ['eifles', 6, \true, \true, 'selfies'],
        // movies (movie)
        ['eivom', 5, \true, \true, 'movies'],
        // lice (louse)
        ['esuol', 5, \false, \true, 'lice'],
        // mice (mouse)
        ['esuom', 5, \false, \true, 'mice'],
        // geese (goose)
        ['esoo', 4, \false, \true, 'eese'],
        // houses (house), bases (base)
        ['es', 2, \true, \true, 'ses'],
        // geese (goose)
        ['esoog', 5, \true, \true, 'geese'],
        // caves (cave)
        ['ev', 2, \true, \true, 'ves'],
        // drives (drive)
        ['evird', 5, \false, \true, 'drives'],
        // objectives (objective), alternative (alternatives)
        ['evit', 4, \true, \true, 'tives'],
        // moves (move)
        ['evom', 4, \true, \true, 'moves'],
        // staves (staff)
        ['ffats', 5, \true, \true, 'staves'],
        // hooves (hoof), dwarves (dwarf), elves (elf), leaves (leaf)
        ['ff', 2, \true, \true, 'ffs'],
        // hooves (hoof), dwarves (dwarf), elves (elf), leaves (leaf)
        ['f', 1, \true, \true, ['fs', 'ves']],
        // arches (arch)
        ['hc', 2, \true, \true, 'ches'],
        // bushes (bush)
        ['hs', 2, \true, \true, 'shes'],
        // teeth (tooth)
        ['htoot', 5, \true, \true, 'teeth'],
        // albums (album)
        ['mubla', 5, \true, \true, 'albums'],
        // quorums (quorum)
        ['murouq', 6, \true, \true, ['quora', 'quorums']],
        // bacteria (bacterium), curricula (curriculum), media (medium), memoranda (memorandum), phenomena (phenomenon), strata (stratum)
        ['mu', 2, \true, \true, 'a'],
        // men (man), women (woman)
        ['nam', 3, \true, \true, 'men'],
        // people (person)
        ['nosrep', 6, \true, \true, ['persons', 'people']],
        // criteria (criterion)
        ['noiretirc', 9, \true, \true, 'criteria'],
        // phenomena (phenomenon)
        ['nonemonehp', 10, \true, \true, 'phenomena'],
        // echoes (echo)
        ['ohce', 4, \true, \true, 'echoes'],
        // heroes (hero)
        ['oreh', 4, \true, \true, 'heroes'],
        // atlases (atlas)
        ['salta', 5, \true, \true, 'atlases'],
        // aliases (alias)
        ['saila', 5, \true, \true, 'aliases'],
        // irises (iris)
        ['siri', 4, \true, \true, 'irises'],
        // analyses (analysis), ellipses (ellipsis), neuroses (neurosis)
        // theses (thesis), emphases (emphasis), oases (oasis),
        // crises (crisis)
        ['sis', 3, \true, \true, 'ses'],
        // accesses (access), addresses (address), kisses (kiss)
        ['ss', 2, \true, \false, 'sses'],
        // syllabi (syllabus)
        ['suballys', 8, \true, \true, 'syllabi'],
        // buses (bus)
        ['sub', 3, \true, \true, 'buses'],
        // circuses (circus)
        ['suc', 3, \true, \true, 'cuses'],
        // hippocampi (hippocampus)
        ['supmacoppih', 11, \false, \false, 'hippocampi'],
        // campuses (campus)
        ['sup', 3, \true, \true, 'puses'],
        // status (status)
        ['sutats', 6, \true, \true, ['status', 'statuses']],
        // conspectuses (conspectus), prospectuses (prospectus)
        ['sutcep', 6, \true, \true, 'pectuses'],
        // nexuses (nexus)
        ['suxen', 5, \false, \false, 'nexuses'],
        // fungi (fungus), alumni (alumnus), syllabi (syllabus), radii (radius)
        ['su', 2, \true, \true, 'i'],
        // news (news)
        ['swen', 4, \true, \true, 'news'],
        // feet (foot)
        ['toof', 4, \true, \true, 'feet'],
        // chateaux (chateau), bureaus (bureau)
        ['uae', 3, \false, \true, ['eaus', 'eaux']],
        // oxen (ox)
        ['xo', 2, \false, \false, 'oxen'],
        // hoaxes (hoax)
        ['xaoh', 4, \true, \false, 'hoaxes'],
        // indices (index)
        ['xedni', 5, \false, \true, ['indicies', 'indexes']],
        // fax (faxes, faxxes)
        ['xaf', 3, \true, \true, ['faxes', 'faxxes']],
        // boxes (box)
        ['xo', 2, \false, \true, 'oxes'],
        // indexes (index), matrixes (matrix), appendices (appendix)
        ['x', 1, \true, \false, ['ces', 'xes']],
        // babies (baby)
        ['y', 1, \false, \true, 'ies'],
        // quizzes (quiz)
        ['ziuq', 4, \true, \false, 'quizzes'],
        // waltzes (waltz)
        ['z', 1, \true, \true, 'zes'],
    ];
    /**
     * A list of words which should not be inflected, reversed.
     */
    private const UNINFLECTED = [
        '',
        // data
        'atad',
        // deer
        'reed',
        // equipment
        'tnempiuqe',
        // feedback
        'kcabdeef',
        // fish
        'hsif',
        // health
        'htlaeh',
        // history
        'yrotsih',
        // info
        'ofni',
        // information
        'noitamrofni',
        // money
        'yenom',
        // moose
        'esoom',
        // series
        'seires',
        // sheep
        'peehs',
        // species
        'seiceps',
        // traffic
        'ciffart',
        // aircraft
        'tfarcria',
        // hardware
        'erawdrah',
    ];
    public function singularize(string $plural): array
    {
        $pluralRev = strrev($plural);
        $lowerPluralRev = strtolower($pluralRev);
        $pluralLength = \strlen($lowerPluralRev);
        // Check if the word is one which is not inflected, return early if so
        if (\in_array($lowerPluralRev, self::UNINFLECTED, \true)) {
            return [$plural];
        }
        // The outer loop iterates over the entries of the plural table
        // The inner loop $j iterates over the characters of the plural suffix
        // in the plural table to compare them with the characters of the actual
        // given plural suffix
        foreach (self::PLURAL_MAP as $map) {
            $suffix = $map[0];
            $suffixLength = $map[1];
            $j = 0;
            // Compare characters in the plural table and of the suffix of the
            // given plural one by one
            while ($suffix[$j] === $lowerPluralRev[$j]) {
                // Let $j point to the next character
                ++$j;
                // Successfully compared the last character
                // Add an entry with the singular suffix to the singular array
                if ($j === $suffixLength) {
                    // Is there any character preceding the suffix in the plural string?
                    if ($j < $pluralLength) {
                        $nextIsVowel = str_contains('aeiou', $lowerPluralRev[$j]);
                        if (!$map[2] && $nextIsVowel) {
                            // suffix may not succeed a vowel but next char is one
                            break;
                        }
                        if (!$map[3] && !$nextIsVowel) {
                            // suffix may not succeed a consonant but next char is one
                            break;
                        }
                    }
                    $newBase = substr($plural, 0, $pluralLength - $suffixLength);
                    $newSuffix = $map[4];
                    // Check whether the first character in the plural suffix
                    // is uppercased. If yes, uppercase the first character in
                    // the singular suffix too
                    $firstUpper = ctype_upper($pluralRev[$j - 1]);
                    if (\is_array($newSuffix)) {
                        $singulars = [];
                        foreach ($newSuffix as $newSuffixEntry) {
                            $singulars[] = $newBase . ($firstUpper ? ucfirst($newSuffixEntry) : $newSuffixEntry);
                        }
                        return $singulars;
                    }
                    return [$newBase . ($firstUpper ? ucfirst($newSuffix) : $newSuffix)];
                }
                // Suffix is longer than word
                if ($j === $pluralLength) {
                    break;
                }
            }
        }
        // Assume that plural and singular is identical
        return [$plural];
    }
    public function pluralize(string $singular): array
    {
        $singularRev = strrev($singular);
        $lowerSingularRev = strtolower($singularRev);
        $singularLength = \strlen($lowerSingularRev);
        // Check if the word is one which is not inflected, return early if so
        if (\in_array($lowerSingularRev, self::UNINFLECTED, \true)) {
            return [$singular];
        }
        // The outer loop iterates over the entries of the singular table
        // The inner loop $j iterates over the characters of the singular suffix
        // in the singular table to compare them with the characters of the actual
        // given singular suffix
        foreach (self::SINGULAR_MAP as $map) {
            $suffix = $map[0];
            $suffixLength = $map[1];
            $j = 0;
            // Compare characters in the singular table and of the suffix of the
            // given plural one by one
            while ($suffix[$j] === $lowerSingularRev[$j]) {
                // Let $j point to the next character
                ++$j;
                // Successfully compared the last character
                // Add an entry with the plural suffix to the plural array
                if ($j === $suffixLength) {
                    // Is there any character preceding the suffix in the plural string?
                    if ($j < $singularLength) {
                        $nextIsVowel = str_contains('aeiou', $lowerSingularRev[$j]);
                        if (!$map[2] && $nextIsVowel) {
                            // suffix may not succeed a vowel but next char is one
                            break;
                        }
                        if (!$map[3] && !$nextIsVowel) {
                            // suffix may not succeed a consonant but next char is one
                            break;
                        }
                    }
                    $newBase = substr($singular, 0, $singularLength - $suffixLength);
                    $newSuffix = $map[4];
                    // Check whether the first character in the singular suffix
                    // is uppercased. If yes, uppercase the first character in
                    // the singular suffix too
                    $firstUpper = ctype_upper($singularRev[$j - 1]);
                    if (\is_array($newSuffix)) {
                        $plurals = [];
                        foreach ($newSuffix as $newSuffixEntry) {
                            $plurals[] = $newBase . ($firstUpper ? ucfirst($newSuffixEntry) : $newSuffixEntry);
                        }
                        return $plurals;
                    }
                    return [$newBase . ($firstUpper ? ucfirst($newSuffix) : $newSuffix)];
                }
                // Suffix is longer than word
                if ($j === $singularLength) {
                    break;
                }
            }
        }
        // Assume that plural is singular with a trailing `s`
        return [$singular . 's'];
    }
}
String Component
================

The String component provides an object-oriented API to strings and deals
with bytes, UTF-8 code points and grapheme clusters in a unified way.

Resources
---------

 * [Documentation](https://symfony.com/doc/current/components/string.html)
 * [Contributing](https://symfony.com/doc/current/contributing/index.html)
 * [Report issues](https://github.com/symfony/symfony/issues) and
   [send Pull Requests](https://github.com/symfony/symfony/pulls)
   in the [main Symfony repository](https://github.com/symfony/symfony)
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\String;

use _ContaoManager\Symfony\Component\String\Exception\ExceptionInterface;
use _ContaoManager\Symfony\Component\String\Exception\InvalidArgumentException;
use _ContaoManager\Symfony\Component\String\Exception\RuntimeException;
/**
 * Represents a string of abstract Unicode characters.
 *
 * Unicode defines 3 types of "characters" (bytes, code points and grapheme clusters).
 * This class is the abstract type to use as a type-hint when the logic you want to
 * implement is Unicode-aware but doesn't care about code points vs grapheme clusters.
 *
 * @author Nicolas Grekas <p@tchwork.com>
 *
 * @throws ExceptionInterface
 */
abstract class AbstractUnicodeString extends AbstractString
{
    public const NFC = \Normalizer::NFC;
    public const NFD = \Normalizer::NFD;
    public const NFKC = \Normalizer::NFKC;
    public const NFKD = \Normalizer::NFKD;
    // all ASCII letters sorted by typical frequency of occurrence
    private const ASCII = " eiasntrolud][cmp'\ng|hv.fb,:=-q10C2*yx)(L9AS/P\"EjMIk3>5T<D4}B{8FwR67UGN;JzV#HOW_&!K?XQ%Y\\\tZ+~^\$@`\x00\x01\x02\x03\x04\x05\x06\x07\x08\v\f\r\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f";
    // the subset of folded case mappings that is not in lower case mappings
    private const FOLD_FROM = ['İ', 'µ', 'ſ', "ͅ", 'ς', 'ϐ', 'ϑ', 'ϕ', 'ϖ', 'ϰ', 'ϱ', 'ϵ', 'ẛ', "ι", 'ß', 'ŉ', 'ǰ', 'ΐ', 'ΰ', 'և', 'ẖ', 'ẗ', 'ẘ', 'ẙ', 'ẚ', 'ẞ', 'ὐ', 'ὒ', 'ὔ', 'ὖ', 'ᾀ', 'ᾁ', 'ᾂ', 'ᾃ', 'ᾄ', 'ᾅ', 'ᾆ', 'ᾇ', 'ᾈ', 'ᾉ', 'ᾊ', 'ᾋ', 'ᾌ', 'ᾍ', 'ᾎ', 'ᾏ', 'ᾐ', 'ᾑ', 'ᾒ', 'ᾓ', 'ᾔ', 'ᾕ', 'ᾖ', 'ᾗ', 'ᾘ', 'ᾙ', 'ᾚ', 'ᾛ', 'ᾜ', 'ᾝ', 'ᾞ', 'ᾟ', 'ᾠ', 'ᾡ', 'ᾢ', 'ᾣ', 'ᾤ', 'ᾥ', 'ᾦ', 'ᾧ', 'ᾨ', 'ᾩ', 'ᾪ', 'ᾫ', 'ᾬ', 'ᾭ', 'ᾮ', 'ᾯ', 'ᾲ', 'ᾳ', 'ᾴ', 'ᾶ', 'ᾷ', 'ᾼ', 'ῂ', 'ῃ', 'ῄ', 'ῆ', 'ῇ', 'ῌ', 'ῒ', 'ῖ', 'ῗ', 'ῢ', 'ῤ', 'ῦ', 'ῧ', 'ῲ', 'ῳ', 'ῴ', 'ῶ', 'ῷ', 'ῼ', 'ﬀ', 'ﬁ', 'ﬂ', 'ﬃ', 'ﬄ', 'ﬅ', 'ﬆ', 'ﬓ', 'ﬔ', 'ﬕ', 'ﬖ', 'ﬗ'];
    private const FOLD_TO = ['i̇', 'μ', 's', 'ι', 'σ', 'β', 'θ', 'φ', 'π', 'κ', 'ρ', 'ε', 'ṡ', 'ι', 'ss', 'ʼn', 'ǰ', 'ΐ', 'ΰ', 'եւ', 'ẖ', 'ẗ', 'ẘ', 'ẙ', 'aʾ', 'ss', 'ὐ', 'ὒ', 'ὔ', 'ὖ', 'ἀι', 'ἁι', 'ἂι', 'ἃι', 'ἄι', 'ἅι', 'ἆι', 'ἇι', 'ἀι', 'ἁι', 'ἂι', 'ἃι', 'ἄι', 'ἅι', 'ἆι', 'ἇι', 'ἠι', 'ἡι', 'ἢι', 'ἣι', 'ἤι', 'ἥι', 'ἦι', 'ἧι', 'ἠι', 'ἡι', 'ἢι', 'ἣι', 'ἤι', 'ἥι', 'ἦι', 'ἧι', 'ὠι', 'ὡι', 'ὢι', 'ὣι', 'ὤι', 'ὥι', 'ὦι', 'ὧι', 'ὠι', 'ὡι', 'ὢι', 'ὣι', 'ὤι', 'ὥι', 'ὦι', 'ὧι', 'ὰι', 'αι', 'άι', 'ᾶ', 'ᾶι', 'αι', 'ὴι', 'ηι', 'ήι', 'ῆ', 'ῆι', 'ηι', 'ῒ', 'ῖ', 'ῗ', 'ῢ', 'ῤ', 'ῦ', 'ῧ', 'ὼι', 'ωι', 'ώι', 'ῶ', 'ῶι', 'ωι', 'ff', 'fi', 'fl', 'ffi', 'ffl', 'st', 'st', 'մն', 'մե', 'մի', 'վն', 'մխ'];
    // the subset of https://github.com/unicode-org/cldr/blob/master/common/transforms/Latin-ASCII.xml that is not in NFKD
    private const TRANSLIT_FROM = ['Æ', 'Ð', 'Ø', 'Þ', 'ß', 'æ', 'ð', 'ø', 'þ', 'Đ', 'đ', 'Ħ', 'ħ', 'ı', 'ĸ', 'Ŀ', 'ŀ', 'Ł', 'ł', 'ŉ', 'Ŋ', 'ŋ', 'Œ', 'œ', 'Ŧ', 'ŧ', 'ƀ', 'Ɓ', 'Ƃ', 'ƃ', 'Ƈ', 'ƈ', 'Ɖ', 'Ɗ', 'Ƌ', 'ƌ', 'Ɛ', 'Ƒ', 'ƒ', 'Ɠ', 'ƕ', 'Ɩ', 'Ɨ', 'Ƙ', 'ƙ', 'ƚ', 'Ɲ', 'ƞ', 'Ƣ', 'ƣ', 'Ƥ', 'ƥ', 'ƫ', 'Ƭ', 'ƭ', 'Ʈ', 'Ʋ', 'Ƴ', 'ƴ', 'Ƶ', 'ƶ', 'Ǆ', 'ǅ', 'ǆ', 'Ǥ', 'ǥ', 'ȡ', 'Ȥ', 'ȥ', 'ȴ', 'ȵ', 'ȶ', 'ȷ', 'ȸ', 'ȹ', 'Ⱥ', 'Ȼ', 'ȼ', 'Ƚ', 'Ⱦ', 'ȿ', 'ɀ', 'Ƀ', 'Ʉ', 'Ɇ', 'ɇ', 'Ɉ', 'ɉ', 'Ɍ', 'ɍ', 'Ɏ', 'ɏ', 'ɓ', 'ɕ', 'ɖ', 'ɗ', 'ɛ', 'ɟ', 'ɠ', 'ɡ', 'ɢ', 'ɦ', 'ɧ', 'ɨ', 'ɪ', 'ɫ', 'ɬ', 'ɭ', 'ɱ', 'ɲ', 'ɳ', 'ɴ', 'ɶ', 'ɼ', 'ɽ', 'ɾ', 'ʀ', 'ʂ', 'ʈ', 'ʉ', 'ʋ', 'ʏ', 'ʐ', 'ʑ', 'ʙ', 'ʛ', 'ʜ', 'ʝ', 'ʟ', 'ʠ', 'ʣ', 'ʥ', 'ʦ', 'ʪ', 'ʫ', 'ᴀ', 'ᴁ', 'ᴃ', 'ᴄ', 'ᴅ', 'ᴆ', 'ᴇ', 'ᴊ', 'ᴋ', 'ᴌ', 'ᴍ', 'ᴏ', 'ᴘ', 'ᴛ', 'ᴜ', 'ᴠ', 'ᴡ', 'ᴢ', 'ᵫ', 'ᵬ', 'ᵭ', 'ᵮ', 'ᵯ', 'ᵰ', 'ᵱ', 'ᵲ', 'ᵳ', 'ᵴ', 'ᵵ', 'ᵶ', 'ᵺ', 'ᵻ', 'ᵽ', 'ᵾ', 'ᶀ', 'ᶁ', 'ᶂ', 'ᶃ', 'ᶄ', 'ᶅ', 'ᶆ', 'ᶇ', 'ᶈ', 'ᶉ', 'ᶊ', 'ᶌ', 'ᶍ', 'ᶎ', 'ᶏ', 'ᶑ', 'ᶒ', 'ᶓ', 'ᶖ', 'ᶙ', 'ẚ', 'ẜ', 'ẝ', 'ẞ', 'Ỻ', 'ỻ', 'Ỽ', 'ỽ', 'Ỿ', 'ỿ', '©', '®', '₠', '₢', '₣', '₤', '₧', '₺', '₹', 'ℌ', '℞', '㎧', '㎮', '㏆', '㏗', '㏞', '㏟', '¼', '½', '¾', '⅓', '⅔', '⅕', '⅖', '⅗', '⅘', '⅙', '⅚', '⅛', '⅜', '⅝', '⅞', '⅟', '〇', '‘', '’', '‚', '‛', '“', '”', '„', '‟', '′', '″', '〝', '〞', '«', '»', '‹', '›', '‐', '‑', '‒', '–', '—', '―', '︱', '︲', '﹘', '‖', '⁄', '⁅', '⁆', '⁎', '、', '。', '〈', '〉', '《', '》', '〔', '〕', '〘', '〙', '〚', '〛', '︑', '︒', '︹', '︺', '︽', '︾', '︿', '﹀', '﹑', '﹝', '﹞', '｟', '｠', '｡', '､', '×', '÷', '−', '∕', '∖', '∣', '∥', '≪', '≫', '⦅', '⦆'];
    private const TRANSLIT_TO = ['AE', 'D', 'O', 'TH', 'ss', 'ae', 'd', 'o', 'th', 'D', 'd', 'H', 'h', 'i', 'q', 'L', 'l', 'L', 'l', '\'n', 'N', 'n', 'OE', 'oe', 'T', 't', 'b', 'B', 'B', 'b', 'C', 'c', 'D', 'D', 'D', 'd', 'E', 'F', 'f', 'G', 'hv', 'I', 'I', 'K', 'k', 'l', 'N', 'n', 'OI', 'oi', 'P', 'p', 't', 'T', 't', 'T', 'V', 'Y', 'y', 'Z', 'z', 'DZ', 'Dz', 'dz', 'G', 'g', 'd', 'Z', 'z', 'l', 'n', 't', 'j', 'db', 'qp', 'A', 'C', 'c', 'L', 'T', 's', 'z', 'B', 'U', 'E', 'e', 'J', 'j', 'R', 'r', 'Y', 'y', 'b', 'c', 'd', 'd', 'e', 'j', 'g', 'g', 'G', 'h', 'h', 'i', 'I', 'l', 'l', 'l', 'm', 'n', 'n', 'N', 'OE', 'r', 'r', 'r', 'R', 's', 't', 'u', 'v', 'Y', 'z', 'z', 'B', 'G', 'H', 'j', 'L', 'q', 'dz', 'dz', 'ts', 'ls', 'lz', 'A', 'AE', 'B', 'C', 'D', 'D', 'E', 'J', 'K', 'L', 'M', 'O', 'P', 'T', 'U', 'V', 'W', 'Z', 'ue', 'b', 'd', 'f', 'm', 'n', 'p', 'r', 'r', 's', 't', 'z', 'th', 'I', 'p', 'U', 'b', 'd', 'f', 'g', 'k', 'l', 'm', 'n', 'p', 'r', 's', 'v', 'x', 'z', 'a', 'd', 'e', 'e', 'i', 'u', 'a', 's', 's', 'SS', 'LL', 'll', 'V', 'v', 'Y', 'y', '(C)', '(R)', 'CE', 'Cr', 'Fr.', 'L.', 'Pts', 'TL', 'Rs', 'x', 'Rx', 'm/s', 'rad/s', 'C/kg', 'pH', 'V/m', 'A/m', ' 1/4', ' 1/2', ' 3/4', ' 1/3', ' 2/3', ' 1/5', ' 2/5', ' 3/5', ' 4/5', ' 1/6', ' 5/6', ' 1/8', ' 3/8', ' 5/8', ' 7/8', ' 1/', '0', '\'', '\'', ',', '\'', '"', '"', ',,', '"', '\'', '"', '"', '"', '<<', '>>', '<', '>', '-', '-', '-', '-', '-', '-', '-', '-', '-', '||', '/', '[', ']', '*', ',', '.', '<', '>', '<<', '>>', '[', ']', '[', ']', '[', ']', ',', '.', '[', ']', '<<', '>>', '<', '>', ',', '[', ']', '((', '))', '.', ',', '*', '/', '-', '/', '\\', '|', '||', '<<', '>>', '((', '))'];
    private static array $transliterators = [];
    private static array $tableZero;
    private static array $tableWide;
    public static function fromCodePoints(int ...$codes): static
    {
        $string = '';
        foreach ($codes as $code) {
            if (0x80 > $code %= 0x200000) {
                $string .= \chr($code);
            } elseif (0x800 > $code) {
                $string .= \chr(0xc0 | $code >> 6) . \chr(0x80 | $code & 0x3f);
            } elseif (0x10000 > $code) {
                $string .= \chr(0xe0 | $code >> 12) . \chr(0x80 | $code >> 6 & 0x3f) . \chr(0x80 | $code & 0x3f);
            } else {
                $string .= \chr(0xf0 | $code >> 18) . \chr(0x80 | $code >> 12 & 0x3f) . \chr(0x80 | $code >> 6 & 0x3f) . \chr(0x80 | $code & 0x3f);
            }
        }
        return new static($string);
    }
    /**
     * Generic UTF-8 to ASCII transliteration.
     *
     * Install the intl extension for best results.
     *
     * @param string[]|\Transliterator[]|\Closure[] $rules See "*-Latin" rules from Transliterator::listIDs()
     */
    public function ascii(array $rules = []): self
    {
        $str = clone $this;
        $s = $str->string;
        $str->string = '';
        array_unshift($rules, 'nfd');
        $rules[] = 'latin-ascii';
        if (\function_exists('transliterator_transliterate')) {
            $rules[] = 'any-latin/bgn';
        }
        $rules[] = 'nfkd';
        $rules[] = '[:nonspacing mark:] remove';
        while (\strlen($s) - 1 > $i = strspn($s, self::ASCII)) {
            if (0 < --$i) {
                $str->string .= substr($s, 0, $i);
                $s = substr($s, $i);
            }
            if (!$rule = array_shift($rules)) {
                $rules = [];
                // An empty rule interrupts the next ones
            }
            if ($rule instanceof \Transliterator) {
                $s = $rule->transliterate($s);
            } elseif ($rule instanceof \Closure) {
                $s = $rule($s);
            } elseif ($rule) {
                if ('nfd' === $rule = strtolower($rule)) {
                    normalizer_is_normalized($s, self::NFD) ?: $s = normalizer_normalize($s, self::NFD);
                } elseif ('nfkd' === $rule) {
                    normalizer_is_normalized($s, self::NFKD) ?: $s = normalizer_normalize($s, self::NFKD);
                } elseif ('[:nonspacing mark:] remove' === $rule) {
                    $s = preg_replace('/\p{Mn}++/u', '', $s);
                } elseif ('latin-ascii' === $rule) {
                    $s = str_replace(self::TRANSLIT_FROM, self::TRANSLIT_TO, $s);
                } elseif ('de-ascii' === $rule) {
                    $s = preg_replace("/([AUO])̈(?=\\p{Ll})/u", '$1e', $s);
                    $s = str_replace(["ä", "ö", "ü", "Ä", "Ö", "Ü"], ['ae', 'oe', 'ue', 'AE', 'OE', 'UE'], $s);
                } elseif (\function_exists('transliterator_transliterate')) {
                    if (null === $transliterator = self::$transliterators[$rule] ??= \Transliterator::create($rule)) {
                        if ('any-latin/bgn' === $rule) {
                            $rule = 'any-latin';
                            $transliterator = self::$transliterators[$rule] ??= \Transliterator::create($rule);
                        }
                        if (null === $transliterator) {
                            throw new InvalidArgumentException(\sprintf('Unknown transliteration rule "%s".', $rule));
                        }
                        self::$transliterators['any-latin/bgn'] = $transliterator;
                    }
                    $s = $transliterator->transliterate($s);
                }
            } elseif (!\function_exists('iconv')) {
                $s = preg_replace('/[^\x00-\x7F]/u', '?', $s);
            } else {
                $previousLocale = setlocale(\LC_CTYPE, 0);
                try {
                    setlocale(\LC_CTYPE, 'C');
                    $s = @preg_replace_callback('/[^\x00-\x7F]/u', static function ($c) {
                        $c = (string) iconv('UTF-8', 'ASCII//TRANSLIT', $c[0]);
                        if ('' === $c && '' === iconv('UTF-8', 'ASCII//TRANSLIT', '²')) {
                            throw new \LogicException(\sprintf('"%s" requires a translit-able iconv implementation, try installing "gnu-libiconv" if you\'re using Alpine Linux.', static::class));
                        }
                        return 1 < \strlen($c) ? ltrim($c, '\'`"^~') : ('' !== $c ? $c : '?');
                    }, $s);
                } finally {
                    setlocale(\LC_CTYPE, $previousLocale);
                }
            }
        }
        $str->string .= $s;
        return $str;
    }
    public function camel(): static
    {
        $str = clone $this;
        $str->string = str_replace(' ', '', preg_replace_callback('/\b.(?!\p{Lu})/u', static function ($m) {
            static $i = 0;
            return 1 === ++$i ? 'İ' === $m[0] ? 'i̇' : mb_strtolower($m[0], 'UTF-8') : mb_convert_case($m[0], \MB_CASE_TITLE, 'UTF-8');
        }, preg_replace('/[^\pL0-9]++/u', ' ', $this->string)));
        return $str;
    }
    /**
     * @return int[]
     */
    public function codePointsAt(int $offset): array
    {
        $str = $this->slice($offset, 1);
        if ('' === $str->string) {
            return [];
        }
        $codePoints = [];
        foreach (preg_split('//u', $str->string, -1, \PREG_SPLIT_NO_EMPTY) as $c) {
            $codePoints[] = mb_ord($c, 'UTF-8');
        }
        return $codePoints;
    }
    public function folded(bool $compat = \true): static
    {
        $str = clone $this;
        if (!$compat || !\defined('Normalizer::NFKC_CF')) {
            $str->string = normalizer_normalize($str->string, $compat ? \Normalizer::NFKC : \Normalizer::NFC);
            $str->string = mb_strtolower(str_replace(self::FOLD_FROM, self::FOLD_TO, $str->string), 'UTF-8');
        } else {
            $str->string = normalizer_normalize($str->string, \Normalizer::NFKC_CF);
        }
        return $str;
    }
    public function join(array $strings, ?string $lastGlue = null): static
    {
        $str = clone $this;
        $tail = null !== $lastGlue && 1 < \count($strings) ? $lastGlue . array_pop($strings) : '';
        $str->string = implode($this->string, $strings) . $tail;
        if (!preg_match('//u', $str->string)) {
            throw new InvalidArgumentException('Invalid UTF-8 string.');
        }
        return $str;
    }
    public function lower(): static
    {
        $str = clone $this;
        $str->string = mb_strtolower(str_replace('İ', 'i̇', $str->string), 'UTF-8');
        return $str;
    }
    public function match(string $regexp, int $flags = 0, int $offset = 0): array
    {
        $match = (\PREG_PATTERN_ORDER | \PREG_SET_ORDER) & $flags ? 'preg_match_all' : 'preg_match';
        if ($this->ignoreCase) {
            $regexp .= 'i';
        }
        set_error_handler(static fn($t, $m) => throw new InvalidArgumentException($m));
        try {
            if (\false === $match($regexp . 'u', $this->string, $matches, $flags | \PREG_UNMATCHED_AS_NULL, $offset)) {
                throw new RuntimeException('Matching failed with error: ' . preg_last_error_msg());
            }
        } finally {
            restore_error_handler();
        }
        return $matches;
    }
    public function normalize(int $form = self::NFC): static
    {
        if (!\in_array($form, [self::NFC, self::NFD, self::NFKC, self::NFKD])) {
            throw new InvalidArgumentException('Unsupported normalization form.');
        }
        $str = clone $this;
        normalizer_is_normalized($str->string, $form) ?: $str->string = normalizer_normalize($str->string, $form);
        return $str;
    }
    public function padBoth(int $length, string $padStr = ' '): static
    {
        if ('' === $padStr || !preg_match('//u', $padStr)) {
            throw new InvalidArgumentException('Invalid UTF-8 string.');
        }
        $pad = clone $this;
        $pad->string = $padStr;
        return $this->pad($length, $pad, \STR_PAD_BOTH);
    }
    public function padEnd(int $length, string $padStr = ' '): static
    {
        if ('' === $padStr || !preg_match('//u', $padStr)) {
            throw new InvalidArgumentException('Invalid UTF-8 string.');
        }
        $pad = clone $this;
        $pad->string = $padStr;
        return $this->pad($length, $pad, \STR_PAD_RIGHT);
    }
    public function padStart(int $length, string $padStr = ' '): static
    {
        if ('' === $padStr || !preg_match('//u', $padStr)) {
            throw new InvalidArgumentException('Invalid UTF-8 string.');
        }
        $pad = clone $this;
        $pad->string = $padStr;
        return $this->pad($length, $pad, \STR_PAD_LEFT);
    }
    public function replaceMatches(string $fromRegexp, string|callable $to): static
    {
        if ($this->ignoreCase) {
            $fromRegexp .= 'i';
        }
        if (\is_array($to) || $to instanceof \Closure) {
            $replace = 'preg_replace_callback';
            $to = static function (array $m) use ($to): string {
                $to = $to($m);
                if ('' !== $to && (!\is_string($to) || !preg_match('//u', $to))) {
                    throw new InvalidArgumentException('Replace callback must return a valid UTF-8 string.');
                }
                return $to;
            };
        } elseif ('' !== $to && !preg_match('//u', $to)) {
            throw new InvalidArgumentException('Invalid UTF-8 string.');
        } else {
            $replace = 'preg_replace';
        }
        set_error_handler(static fn($t, $m) => throw new InvalidArgumentException($m));
        try {
            if (null === $string = $replace($fromRegexp . 'u', $to, $this->string)) {
                $lastError = preg_last_error();
                foreach (get_defined_constants(\true)['pcre'] as $k => $v) {
                    if ($lastError === $v && str_ends_with($k, '_ERROR')) {
                        throw new RuntimeException('Matching failed with ' . $k . '.');
                    }
                }
                throw new RuntimeException('Matching failed with unknown error code.');
            }
        } finally {
            restore_error_handler();
        }
        $str = clone $this;
        $str->string = $string;
        return $str;
    }
    public function reverse(): static
    {
        $str = clone $this;
        $str->string = implode('', array_reverse(preg_split('/(\X)/u', $str->string, -1, \PREG_SPLIT_DELIM_CAPTURE | \PREG_SPLIT_NO_EMPTY)));
        return $str;
    }
    public function snake(): static
    {
        $str = $this->camel();
        $str->string = mb_strtolower(preg_replace(['/(\p{Lu}+)(\p{Lu}\p{Ll})/u', '/([\p{Ll}0-9])(\p{Lu})/u'], '\1_\2', $str->string), 'UTF-8');
        return $str;
    }
    public function title(bool $allWords = \false): static
    {
        $str = clone $this;
        $limit = $allWords ? -1 : 1;
        $str->string = preg_replace_callback('/\b./u', static fn(array $m): string => mb_convert_case($m[0], \MB_CASE_TITLE, 'UTF-8'), $str->string, $limit);
        return $str;
    }
    public function trim(string $chars = " \t\n\r\x00\v\f ﻿"): static
    {
        if (" \t\n\r\x00\v\f ﻿" !== $chars && !preg_match('//u', $chars)) {
            throw new InvalidArgumentException('Invalid UTF-8 chars.');
        }
        $chars = preg_quote($chars);
        $str = clone $this;
        $str->string = preg_replace("{^[{$chars}]++|[{$chars}]++\$}uD", '', $str->string);
        return $str;
    }
    public function trimEnd(string $chars = " \t\n\r\x00\v\f ﻿"): static
    {
        if (" \t\n\r\x00\v\f ﻿" !== $chars && !preg_match('//u', $chars)) {
            throw new InvalidArgumentException('Invalid UTF-8 chars.');
        }
        $chars = preg_quote($chars);
        $str = clone $this;
        $str->string = preg_replace("{[{$chars}]++\$}uD", '', $str->string);
        return $str;
    }
    public function trimPrefix($prefix): static
    {
        if (!$this->ignoreCase) {
            return parent::trimPrefix($prefix);
        }
        $str = clone $this;
        if ($prefix instanceof \Traversable) {
            $prefix = iterator_to_array($prefix, \false);
        } elseif ($prefix instanceof parent) {
            $prefix = $prefix->string;
        }
        $prefix = implode('|', array_map('preg_quote', (array) $prefix));
        $str->string = preg_replace("{^(?:{$prefix})}iuD", '', $this->string);
        return $str;
    }
    public function trimStart(string $chars = " \t\n\r\x00\v\f ﻿"): static
    {
        if (" \t\n\r\x00\v\f ﻿" !== $chars && !preg_match('//u', $chars)) {
            throw new InvalidArgumentException('Invalid UTF-8 chars.');
        }
        $chars = preg_quote($chars);
        $str = clone $this;
        $str->string = preg_replace("{^[{$chars}]++}uD", '', $str->string);
        return $str;
    }
    public function trimSuffix($suffix): static
    {
        if (!$this->ignoreCase) {
            return parent::trimSuffix($suffix);
        }
        $str = clone $this;
        if ($suffix instanceof \Traversable) {
            $suffix = iterator_to_array($suffix, \false);
        } elseif ($suffix instanceof parent) {
            $suffix = $suffix->string;
        }
        $suffix = implode('|', array_map('preg_quote', (array) $suffix));
        $str->string = preg_replace("{(?:{$suffix})\$}iuD", '', $this->string);
        return $str;
    }
    public function upper(): static
    {
        $str = clone $this;
        $str->string = mb_strtoupper($str->string, 'UTF-8');
        return $str;
    }
    public function width(bool $ignoreAnsiDecoration = \true): int
    {
        $width = 0;
        $s = str_replace(["\x00", "\x05", "\x07"], '', $this->string);
        if (str_contains($s, "\r")) {
            $s = str_replace(["\r\n", "\r"], "\n", $s);
        }
        if (!$ignoreAnsiDecoration) {
            $s = preg_replace('/[\p{Cc}\x7F]++/u', '', $s);
        }
        foreach (explode("\n", $s) as $s) {
            if ($ignoreAnsiDecoration) {
                $s = preg_replace('/(?:\x1B(?:
                    \[ [\x30-\x3F]*+ [\x20-\x2F]*+ [\x40-\x7E]
                    | [P\]X^_] .*? \x1B\\\\
                    | [\x41-\x7E]
                )|[\p{Cc}\x7F]++)/xu', '', $s);
            }
            $lineWidth = $this->wcswidth($s);
            if ($lineWidth > $width) {
                $width = $lineWidth;
            }
        }
        return $width;
    }
    private function pad(int $len, self $pad, int $type): static
    {
        $sLen = $this->length();
        if ($len <= $sLen) {
            return clone $this;
        }
        $padLen = $pad->length();
        $freeLen = $len - $sLen;
        $len = $freeLen % $padLen;
        switch ($type) {
            case \STR_PAD_RIGHT:
                return $this->append(str_repeat($pad->string, intdiv($freeLen, $padLen)) . ($len ? $pad->slice(0, $len) : ''));
            case \STR_PAD_LEFT:
                return $this->prepend(str_repeat($pad->string, intdiv($freeLen, $padLen)) . ($len ? $pad->slice(0, $len) : ''));
            case \STR_PAD_BOTH:
                $freeLen /= 2;
                $rightLen = ceil($freeLen);
                $len = $rightLen % $padLen;
                $str = $this->append(str_repeat($pad->string, intdiv($rightLen, $padLen)) . ($len ? $pad->slice(0, $len) : ''));
                $leftLen = floor($freeLen);
                $len = $leftLen % $padLen;
                return $str->prepend(str_repeat($pad->string, intdiv($leftLen, $padLen)) . ($len ? $pad->slice(0, $len) : ''));
            default:
                throw new InvalidArgumentException('Invalid padding type.');
        }
    }
    /**
     * Based on https://github.com/jquast/wcwidth, a Python implementation of https://www.cl.cam.ac.uk/~mgk25/ucs/wcwidth.c.
     */
    private function wcswidth(string $string): int
    {
        $width = 0;
        $lastChar = null;
        $lastWidth = null;
        foreach (preg_split('//u', $string, -1, \PREG_SPLIT_NO_EMPTY) as $c) {
            $codePoint = mb_ord($c, 'UTF-8');
            if (0 === $codePoint || 0x34f === $codePoint || 0x200b <= $codePoint && 0x200f >= $codePoint || 0x2028 === $codePoint || 0x2029 === $codePoint || 0x202a <= $codePoint && 0x202e >= $codePoint || 0x2060 <= $codePoint && 0x2063 >= $codePoint) {
                continue;
            }
            // Non printable characters
            if (32 > $codePoint || 0x7f <= $codePoint && 0xa0 > $codePoint) {
                return -1;
            }
            if (0xfe0f === $codePoint) {
                if (\PCRE_VERSION_MAJOR < 10 || \PCRE_VERSION_MAJOR === 10 && \PCRE_VERSION_MINOR < 40) {
                    $regex = '/\p{So}/u';
                } else {
                    $regex = '/\p{Emoji}/u';
                }
                if (null !== $lastChar && 1 === $lastWidth && preg_match($regex, $lastChar)) {
                    ++$width;
                    $lastWidth = 2;
                }
                continue;
            }
            self::$tableZero ??= require __DIR__ . '/Resources/data/wcswidth_table_zero.php';
            if ($codePoint >= self::$tableZero[0][0] && $codePoint <= self::$tableZero[$ubound = \count(self::$tableZero) - 1][1]) {
                $lbound = 0;
                while ($ubound >= $lbound) {
                    $mid = floor(($lbound + $ubound) / 2);
                    if ($codePoint > self::$tableZero[$mid][1]) {
                        $lbound = $mid + 1;
                    } elseif ($codePoint < self::$tableZero[$mid][0]) {
                        $ubound = $mid - 1;
                    } else {
                        continue 2;
                    }
                }
            }
            self::$tableWide ??= require __DIR__ . '/Resources/data/wcswidth_table_wide.php';
            if ($codePoint >= self::$tableWide[0][0] && $codePoint <= self::$tableWide[$ubound = \count(self::$tableWide) - 1][1]) {
                $lbound = 0;
                while ($ubound >= $lbound) {
                    $mid = floor(($lbound + $ubound) / 2);
                    if ($codePoint > self::$tableWide[$mid][1]) {
                        $lbound = $mid + 1;
                    } elseif ($codePoint < self::$tableWide[$mid][0]) {
                        $ubound = $mid - 1;
                    } else {
                        $width += 2;
                        $lastChar = $c;
                        $lastWidth = 2;
                        continue 2;
                    }
                }
            }
            ++$width;
            $lastChar = $c;
            $lastWidth = 1;
        }
        return $width;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\String;

/**
 * A string whose value is computed lazily by a callback.
 *
 * @author Nicolas Grekas <p@tchwork.com>
 */
class LazyString implements \Stringable, \JsonSerializable
{
    private \Closure|string $value;
    /**
     * @param callable|array $callback A callable or a [Closure, method] lazy-callable
     */
    public static function fromCallable(callable|array $callback, mixed ...$arguments): static
    {
        if (\is_array($callback) && !\is_callable($callback) && !(($callback[0] ?? null) instanceof \Closure || 2 < \count($callback))) {
            throw new \TypeError(\sprintf('Argument 1 passed to "%s()" must be a callable or a [Closure, method] lazy-callable, "%s" given.', __METHOD__, '[' . implode(', ', array_map('get_debug_type', $callback)) . ']'));
        }
        $lazyString = new static();
        $lazyString->value = static function () use (&$callback, &$arguments): string {
            static $value;
            if (null !== $arguments) {
                if (!\is_callable($callback)) {
                    $callback[0] = $callback[0]();
                    $callback[1] ??= '__invoke';
                }
                $value = $callback(...$arguments);
                $callback = !\is_scalar($value) && !$value instanceof \Stringable ? self::getPrettyName($callback) : 'callable';
                $arguments = null;
            }
            return $value ?? '';
        };
        return $lazyString;
    }
    public static function fromStringable(string|int|float|bool|\Stringable $value): static
    {
        if (\is_object($value)) {
            return static::fromCallable($value->__toString(...));
        }
        $lazyString = new static();
        $lazyString->value = (string) $value;
        return $lazyString;
    }
    /**
     * Tells whether the provided value can be cast to string.
     */
    final public static function isStringable(mixed $value): bool
    {
        return \is_string($value) || $value instanceof \Stringable || \is_scalar($value);
    }
    /**
     * Casts scalars and stringable objects to strings.
     *
     * @throws \TypeError When the provided value is not stringable
     */
    final public static function resolve(\Stringable|string|int|float|bool $value): string
    {
        return $value;
    }
    public function __toString(): string
    {
        if (\is_string($this->value)) {
            return $this->value;
        }
        try {
            return $this->value = ($this->value)();
        } catch (\Throwable $e) {
            if (\TypeError::class === $e::class && __FILE__ === $e->getFile()) {
                $type = explode(', ', $e->getMessage());
                $type = substr(array_pop($type), 0, -\strlen(' returned'));
                $r = new \ReflectionFunction($this->value);
                $callback = $r->getStaticVariables()['callback'];
                $e = new \TypeError(\sprintf('Return value of %s() passed to %s::fromCallable() must be of the type string, %s returned.', $callback, static::class, $type));
            }
            throw $e;
        }
    }
    public function __sleep(): array
    {
        $this->__toString();
        return ['value'];
    }
    public function jsonSerialize(): string
    {
        return $this->__toString();
    }
    private function __construct()
    {
    }
    private static function getPrettyName(callable $callback): string
    {
        if (\is_string($callback)) {
            return $callback;
        }
        if (\is_array($callback)) {
            $class = \is_object($callback[0]) ? get_debug_type($callback[0]) : $callback[0];
            $method = $callback[1];
        } elseif ($callback instanceof \Closure) {
            $r = new \ReflectionFunction($callback);
            if (str_contains($r->name, '{closure') || !$class = \PHP_VERSION_ID >= 80111 ? $r->getClosureCalledClass() : $r->getClosureScopeClass()) {
                return $r->name;
            }
            $class = $class->name;
            $method = $r->name;
        } else {
            $class = get_debug_type($callback);
            $method = '__invoke';
        }
        return $class . '::' . $method;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\String;

use _ContaoManager\Symfony\Component\String\Exception\ExceptionInterface;
use _ContaoManager\Symfony\Component\String\Exception\InvalidArgumentException;
use _ContaoManager\Symfony\Component\String\Exception\RuntimeException;
/**
 * Represents a binary-safe string of bytes.
 *
 * @author Nicolas Grekas <p@tchwork.com>
 * @author Hugo Hamon <hugohamon@neuf.fr>
 *
 * @throws ExceptionInterface
 */
class ByteString extends AbstractString
{
    private const ALPHABET_ALPHANUMERIC = '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz';
    public function __construct(string $string = '')
    {
        $this->string = $string;
    }
    /*
     * The following method was derived from code of the Hack Standard Library (v4.40 - 2020-05-03)
     *
     * https://github.com/hhvm/hsl/blob/80a42c02f036f72a42f0415e80d6b847f4bf62d5/src/random/private.php#L16
     *
     * Code subject to the MIT license (https://github.com/hhvm/hsl/blob/master/LICENSE).
     *
     * Copyright (c) 2004-2020, Facebook, Inc. (https://www.facebook.com/)
     */
    public static function fromRandom(int $length = 16, ?string $alphabet = null): self
    {
        if ($length <= 0) {
            throw new InvalidArgumentException(\sprintf('A strictly positive length is expected, "%d" given.', $length));
        }
        $alphabet ??= self::ALPHABET_ALPHANUMERIC;
        $alphabetSize = \strlen($alphabet);
        $bits = (int) ceil(log($alphabetSize, 2.0));
        if ($bits <= 0 || $bits > 56) {
            throw new InvalidArgumentException('The length of the alphabet must in the [2^1, 2^56] range.');
        }
        $ret = '';
        while ($length > 0) {
            $urandomLength = (int) ceil(2 * $length * $bits / 8.0);
            $data = random_bytes($urandomLength);
            $unpackedData = 0;
            $unpackedBits = 0;
            for ($i = 0; $i < $urandomLength && $length > 0; ++$i) {
                // Unpack 8 bits
                $unpackedData = $unpackedData << 8 | \ord($data[$i]);
                $unpackedBits += 8;
                // While we have enough bits to select a character from the alphabet, keep
                // consuming the random data
                for (; $unpackedBits >= $bits && $length > 0; $unpackedBits -= $bits) {
                    $index = $unpackedData & (1 << $bits) - 1;
                    $unpackedData >>= $bits;
                    // Unfortunately, the alphabet size is not necessarily a power of two.
                    // Worst case, it is 2^k + 1, which means we need (k+1) bits and we
                    // have around a 50% chance of missing as k gets larger
                    if ($index < $alphabetSize) {
                        $ret .= $alphabet[$index];
                        --$length;
                    }
                }
            }
        }
        return new static($ret);
    }
    public function bytesAt(int $offset): array
    {
        $str = $this->string[$offset] ?? '';
        return '' === $str ? [] : [\ord($str)];
    }
    public function append(string ...$suffix): static
    {
        $str = clone $this;
        $str->string .= 1 >= \count($suffix) ? $suffix[0] ?? '' : implode('', $suffix);
        return $str;
    }
    public function camel(): static
    {
        $str = clone $this;
        $parts = explode(' ', trim(ucwords(preg_replace('/[^a-zA-Z0-9\x7f-\xff]++/', ' ', $this->string))));
        $parts[0] = 1 !== \strlen($parts[0]) && ctype_upper($parts[0]) ? $parts[0] : lcfirst($parts[0]);
        $str->string = implode('', $parts);
        return $str;
    }
    public function chunk(int $length = 1): array
    {
        if (1 > $length) {
            throw new InvalidArgumentException('The chunk length must be greater than zero.');
        }
        if ('' === $this->string) {
            return [];
        }
        $str = clone $this;
        $chunks = [];
        foreach (str_split($this->string, $length) as $chunk) {
            $str->string = $chunk;
            $chunks[] = clone $str;
        }
        return $chunks;
    }
    public function endsWith(string|iterable|AbstractString $suffix): bool
    {
        if ($suffix instanceof AbstractString) {
            $suffix = $suffix->string;
        } elseif (!\is_string($suffix)) {
            return parent::endsWith($suffix);
        }
        return '' !== $suffix && \strlen($this->string) >= \strlen($suffix) && 0 === substr_compare($this->string, $suffix, -\strlen($suffix), null, $this->ignoreCase);
    }
    public function equalsTo(string|iterable|AbstractString $string): bool
    {
        if ($string instanceof AbstractString) {
            $string = $string->string;
        } elseif (!\is_string($string)) {
            return parent::equalsTo($string);
        }
        if ('' !== $string && $this->ignoreCase) {
            return 0 === strcasecmp($string, $this->string);
        }
        return $string === $this->string;
    }
    public function folded(): static
    {
        $str = clone $this;
        $str->string = strtolower($str->string);
        return $str;
    }
    public function indexOf(string|iterable|AbstractString $needle, int $offset = 0): ?int
    {
        if ($needle instanceof AbstractString) {
            $needle = $needle->string;
        } elseif (!\is_string($needle)) {
            return parent::indexOf($needle, $offset);
        }
        if ('' === $needle) {
            return null;
        }
        $i = $this->ignoreCase ? stripos($this->string, $needle, $offset) : strpos($this->string, $needle, $offset);
        return \false === $i ? null : $i;
    }
    public function indexOfLast(string|iterable|AbstractString $needle, int $offset = 0): ?int
    {
        if ($needle instanceof AbstractString) {
            $needle = $needle->string;
        } elseif (!\is_string($needle)) {
            return parent::indexOfLast($needle, $offset);
        }
        if ('' === $needle) {
            return null;
        }
        $i = $this->ignoreCase ? strripos($this->string, $needle, $offset) : strrpos($this->string, $needle, $offset);
        return \false === $i ? null : $i;
    }
    public function isUtf8(): bool
    {
        return '' === $this->string || preg_match('//u', $this->string);
    }
    public function join(array $strings, ?string $lastGlue = null): static
    {
        $str = clone $this;
        $tail = null !== $lastGlue && 1 < \count($strings) ? $lastGlue . array_pop($strings) : '';
        $str->string = implode($this->string, $strings) . $tail;
        return $str;
    }
    public function length(): int
    {
        return \strlen($this->string);
    }
    public function lower(): static
    {
        $str = clone $this;
        $str->string = strtolower($str->string);
        return $str;
    }
    public function match(string $regexp, int $flags = 0, int $offset = 0): array
    {
        $match = (\PREG_PATTERN_ORDER | \PREG_SET_ORDER) & $flags ? 'preg_match_all' : 'preg_match';
        if ($this->ignoreCase) {
            $regexp .= 'i';
        }
        set_error_handler(static fn($t, $m) => throw new InvalidArgumentException($m));
        try {
            if (\false === $match($regexp, $this->string, $matches, $flags | \PREG_UNMATCHED_AS_NULL, $offset)) {
                throw new RuntimeException('Matching failed with error: ' . preg_last_error_msg());
            }
        } finally {
            restore_error_handler();
        }
        return $matches;
    }
    public function padBoth(int $length, string $padStr = ' '): static
    {
        $str = clone $this;
        $str->string = str_pad($this->string, $length, $padStr, \STR_PAD_BOTH);
        return $str;
    }
    public function padEnd(int $length, string $padStr = ' '): static
    {
        $str = clone $this;
        $str->string = str_pad($this->string, $length, $padStr, \STR_PAD_RIGHT);
        return $str;
    }
    public function padStart(int $length, string $padStr = ' '): static
    {
        $str = clone $this;
        $str->string = str_pad($this->string, $length, $padStr, \STR_PAD_LEFT);
        return $str;
    }
    public function prepend(string ...$prefix): static
    {
        $str = clone $this;
        $str->string = (1 >= \count($prefix) ? $prefix[0] ?? '' : implode('', $prefix)) . $str->string;
        return $str;
    }
    public function replace(string $from, string $to): static
    {
        $str = clone $this;
        if ('' !== $from) {
            $str->string = $this->ignoreCase ? str_ireplace($from, $to, $this->string) : str_replace($from, $to, $this->string);
        }
        return $str;
    }
    public function replaceMatches(string $fromRegexp, string|callable $to): static
    {
        if ($this->ignoreCase) {
            $fromRegexp .= 'i';
        }
        $replace = \is_array($to) || $to instanceof \Closure ? 'preg_replace_callback' : 'preg_replace';
        set_error_handler(static fn($t, $m) => throw new InvalidArgumentException($m));
        try {
            if (null === $string = $replace($fromRegexp, $to, $this->string)) {
                $lastError = preg_last_error();
                foreach (get_defined_constants(\true)['pcre'] as $k => $v) {
                    if ($lastError === $v && str_ends_with($k, '_ERROR')) {
                        throw new RuntimeException('Matching failed with ' . $k . '.');
                    }
                }
                throw new RuntimeException('Matching failed with unknown error code.');
            }
        } finally {
            restore_error_handler();
        }
        $str = clone $this;
        $str->string = $string;
        return $str;
    }
    public function reverse(): static
    {
        $str = clone $this;
        $str->string = strrev($str->string);
        return $str;
    }
    public function slice(int $start = 0, ?int $length = null): static
    {
        $str = clone $this;
        $str->string = (string) substr($this->string, $start, $length ?? \PHP_INT_MAX);
        return $str;
    }
    public function snake(): static
    {
        $str = $this->camel();
        $str->string = strtolower(preg_replace(['/([A-Z]+)([A-Z][a-z])/', '/([a-z\d])([A-Z])/'], '\1_\2', $str->string));
        return $str;
    }
    public function splice(string $replacement, int $start = 0, ?int $length = null): static
    {
        $str = clone $this;
        $str->string = substr_replace($this->string, $replacement, $start, $length ?? \PHP_INT_MAX);
        return $str;
    }
    public function split(string $delimiter, ?int $limit = null, ?int $flags = null): array
    {
        if (1 > $limit ??= \PHP_INT_MAX) {
            throw new InvalidArgumentException('Split limit must be a positive integer.');
        }
        if ('' === $delimiter) {
            throw new InvalidArgumentException('Split delimiter is empty.');
        }
        if (null !== $flags) {
            return parent::split($delimiter, $limit, $flags);
        }
        $str = clone $this;
        $chunks = $this->ignoreCase ? preg_split('{' . preg_quote($delimiter) . '}iD', $this->string, $limit) : explode($delimiter, $this->string, $limit);
        foreach ($chunks as &$chunk) {
            $str->string = $chunk;
            $chunk = clone $str;
        }
        return $chunks;
    }
    public function startsWith(string|iterable|AbstractString $prefix): bool
    {
        if ($prefix instanceof AbstractString) {
            $prefix = $prefix->string;
        } elseif (!\is_string($prefix)) {
            return parent::startsWith($prefix);
        }
        return '' !== $prefix && 0 === ($this->ignoreCase ? strncasecmp($this->string, $prefix, \strlen($prefix)) : strncmp($this->string, $prefix, \strlen($prefix)));
    }
    public function title(bool $allWords = \false): static
    {
        $str = clone $this;
        $str->string = $allWords ? ucwords($str->string) : ucfirst($str->string);
        return $str;
    }
    public function toUnicodeString(?string $fromEncoding = null): UnicodeString
    {
        return new UnicodeString($this->toCodePointString($fromEncoding)->string);
    }
    public function toCodePointString(?string $fromEncoding = null): CodePointString
    {
        $u = new CodePointString();
        if (\in_array($fromEncoding, [null, 'utf8', 'utf-8', 'UTF8', 'UTF-8'], \true) && preg_match('//u', $this->string)) {
            $u->string = $this->string;
            return $u;
        }
        set_error_handler(static fn($t, $m) => throw new InvalidArgumentException($m));
        try {
            try {
                $validEncoding = \false !== mb_detect_encoding($this->string, $fromEncoding ?? 'Windows-1252', \true);
            } catch (InvalidArgumentException $e) {
                if (!\function_exists('iconv') && !\function_exists('_ContaoManager\iconv')) {
                    throw $e;
                }
                $u->string = iconv($fromEncoding ?? 'Windows-1252', 'UTF-8', $this->string);
                return $u;
            }
        } finally {
            restore_error_handler();
        }
        if (!$validEncoding) {
            throw new InvalidArgumentException(\sprintf('Invalid "%s" string.', $fromEncoding ?? 'Windows-1252'));
        }
        $u->string = mb_convert_encoding($this->string, 'UTF-8', $fromEncoding ?? 'Windows-1252');
        return $u;
    }
    public function trim(string $chars = " \t\n\r\x00\v\f"): static
    {
        $str = clone $this;
        $str->string = trim($str->string, $chars);
        return $str;
    }
    public function trimEnd(string $chars = " \t\n\r\x00\v\f"): static
    {
        $str = clone $this;
        $str->string = rtrim($str->string, $chars);
        return $str;
    }
    public function trimStart(string $chars = " \t\n\r\x00\v\f"): static
    {
        $str = clone $this;
        $str->string = ltrim($str->string, $chars);
        return $str;
    }
    public function upper(): static
    {
        $str = clone $this;
        $str->string = strtoupper($str->string);
        return $str;
    }
    public function width(bool $ignoreAnsiDecoration = \true): int
    {
        $string = preg_match('//u', $this->string) ? $this->string : preg_replace('/[\x80-\xFF]/', '?', $this->string);
        return (new CodePointString($string))->width($ignoreAnsiDecoration);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\String;

use _ContaoManager\Symfony\Component\String\Exception\ExceptionInterface;
use _ContaoManager\Symfony\Component\String\Exception\InvalidArgumentException;
/**
 * Represents a string of Unicode grapheme clusters encoded as UTF-8.
 *
 * A letter followed by combining characters (accents typically) form what Unicode defines
 * as a grapheme cluster: a character as humans mean it in written texts. This class knows
 * about the concept and won't split a letter apart from its combining accents. It also
 * ensures all string comparisons happen on their canonically-composed representation,
 * ignoring e.g. the order in which accents are listed when a letter has many of them.
 *
 * @see https://unicode.org/reports/tr15/
 *
 * @author Nicolas Grekas <p@tchwork.com>
 * @author Hugo Hamon <hugohamon@neuf.fr>
 *
 * @throws ExceptionInterface
 */
class UnicodeString extends AbstractUnicodeString
{
    public function __construct(string $string = '')
    {
        if ('' === $string || normalizer_is_normalized($this->string = $string)) {
            return;
        }
        if (\false === $string = normalizer_normalize($string)) {
            throw new InvalidArgumentException('Invalid UTF-8 string.');
        }
        $this->string = $string;
    }
    public function append(string ...$suffix): static
    {
        $str = clone $this;
        $str->string = $this->string . (1 >= \count($suffix) ? $suffix[0] ?? '' : implode('', $suffix));
        if (normalizer_is_normalized($str->string)) {
            return $str;
        }
        if (\false === $string = normalizer_normalize($str->string)) {
            throw new InvalidArgumentException('Invalid UTF-8 string.');
        }
        $str->string = $string;
        return $str;
    }
    public function chunk(int $length = 1): array
    {
        if (1 > $length) {
            throw new InvalidArgumentException('The chunk length must be greater than zero.');
        }
        if ('' === $this->string) {
            return [];
        }
        $rx = '/(';
        while (65535 < $length) {
            $rx .= '\X{65535}';
            $length -= 65535;
        }
        $rx .= '\X{' . $length . '})/u';
        $str = clone $this;
        $chunks = [];
        foreach (preg_split($rx, $this->string, -1, \PREG_SPLIT_DELIM_CAPTURE | \PREG_SPLIT_NO_EMPTY) as $chunk) {
            $str->string = $chunk;
            $chunks[] = clone $str;
        }
        return $chunks;
    }
    public function endsWith(string|iterable|AbstractString $suffix): bool
    {
        if ($suffix instanceof AbstractString) {
            $suffix = $suffix->string;
        } elseif (!\is_string($suffix)) {
            return parent::endsWith($suffix);
        }
        $form = null === $this->ignoreCase ? \Normalizer::NFD : \Normalizer::NFC;
        normalizer_is_normalized($suffix, $form) ?: $suffix = normalizer_normalize($suffix, $form);
        if ('' === $suffix || \false === $suffix) {
            return \false;
        }
        if ($this->ignoreCase) {
            return 0 === mb_stripos(grapheme_extract($this->string, \strlen($suffix), \GRAPHEME_EXTR_MAXBYTES, \strlen($this->string) - \strlen($suffix)), $suffix, 0, 'UTF-8');
        }
        return $suffix === grapheme_extract($this->string, \strlen($suffix), \GRAPHEME_EXTR_MAXBYTES, \strlen($this->string) - \strlen($suffix));
    }
    public function equalsTo(string|iterable|AbstractString $string): bool
    {
        if ($string instanceof AbstractString) {
            $string = $string->string;
        } elseif (!\is_string($string)) {
            return parent::equalsTo($string);
        }
        $form = null === $this->ignoreCase ? \Normalizer::NFD : \Normalizer::NFC;
        normalizer_is_normalized($string, $form) ?: $string = normalizer_normalize($string, $form);
        if ('' !== $string && \false !== $string && $this->ignoreCase) {
            return \strlen($string) === \strlen($this->string) && 0 === mb_stripos($this->string, $string, 0, 'UTF-8');
        }
        return $string === $this->string;
    }
    public function indexOf(string|iterable|AbstractString $needle, int $offset = 0): ?int
    {
        if ($needle instanceof AbstractString) {
            $needle = $needle->string;
        } elseif (!\is_string($needle)) {
            return parent::indexOf($needle, $offset);
        }
        $form = null === $this->ignoreCase ? \Normalizer::NFD : \Normalizer::NFC;
        normalizer_is_normalized($needle, $form) ?: $needle = normalizer_normalize($needle, $form);
        if ('' === $needle || \false === $needle) {
            return null;
        }
        try {
            $i = $this->ignoreCase ? grapheme_stripos($this->string, $needle, $offset) : grapheme_strpos($this->string, $needle, $offset);
        } catch (\ValueError) {
            return null;
        }
        return \false === $i ? null : $i;
    }
    public function indexOfLast(string|iterable|AbstractString $needle, int $offset = 0): ?int
    {
        if ($needle instanceof AbstractString) {
            $needle = $needle->string;
        } elseif (!\is_string($needle)) {
            return parent::indexOfLast($needle, $offset);
        }
        $form = null === $this->ignoreCase ? \Normalizer::NFD : \Normalizer::NFC;
        normalizer_is_normalized($needle, $form) ?: $needle = normalizer_normalize($needle, $form);
        if ('' === $needle || \false === $needle) {
            return null;
        }
        $string = $this->string;
        if (0 > $offset) {
            // workaround https://bugs.php.net/74264
            if (0 > $offset += grapheme_strlen($needle)) {
                $string = grapheme_substr($string, 0, $offset);
            }
            $offset = 0;
        }
        $i = $this->ignoreCase ? grapheme_strripos($string, $needle, $offset) : grapheme_strrpos($string, $needle, $offset);
        return \false === $i ? null : $i;
    }
    public function join(array $strings, ?string $lastGlue = null): static
    {
        $str = parent::join($strings, $lastGlue);
        normalizer_is_normalized($str->string) ?: $str->string = normalizer_normalize($str->string);
        return $str;
    }
    public function length(): int
    {
        return grapheme_strlen($this->string);
    }
    public function normalize(int $form = self::NFC): static
    {
        $str = clone $this;
        if (\in_array($form, [self::NFC, self::NFKC], \true)) {
            normalizer_is_normalized($str->string, $form) ?: $str->string = normalizer_normalize($str->string, $form);
        } elseif (!\in_array($form, [self::NFD, self::NFKD], \true)) {
            throw new InvalidArgumentException('Unsupported normalization form.');
        } elseif (!normalizer_is_normalized($str->string, $form)) {
            $str->string = normalizer_normalize($str->string, $form);
            $str->ignoreCase = null;
        }
        return $str;
    }
    public function prepend(string ...$prefix): static
    {
        $str = clone $this;
        $str->string = (1 >= \count($prefix) ? $prefix[0] ?? '' : implode('', $prefix)) . $this->string;
        if (normalizer_is_normalized($str->string)) {
            return $str;
        }
        if (\false === $string = normalizer_normalize($str->string)) {
            throw new InvalidArgumentException('Invalid UTF-8 string.');
        }
        $str->string = $string;
        return $str;
    }
    public function replace(string $from, string $to): static
    {
        $str = clone $this;
        normalizer_is_normalized($from) ?: $from = normalizer_normalize($from);
        if ('' !== $from && \false !== $from) {
            $tail = $str->string;
            $result = '';
            $indexOf = $this->ignoreCase ? 'grapheme_stripos' : 'grapheme_strpos';
            while ('' !== $tail && \false !== $i = $indexOf($tail, $from)) {
                $slice = grapheme_substr($tail, 0, $i);
                $result .= $slice . $to;
                $tail = substr($tail, \strlen($slice) + \strlen($from));
            }
            $str->string = $result . $tail;
            if (normalizer_is_normalized($str->string)) {
                return $str;
            }
            if (\false === $string = normalizer_normalize($str->string)) {
                throw new InvalidArgumentException('Invalid UTF-8 string.');
            }
            $str->string = $string;
        }
        return $str;
    }
    public function replaceMatches(string $fromRegexp, string|callable $to): static
    {
        $str = parent::replaceMatches($fromRegexp, $to);
        normalizer_is_normalized($str->string) ?: $str->string = normalizer_normalize($str->string);
        return $str;
    }
    public function slice(int $start = 0, ?int $length = null): static
    {
        $str = clone $this;
        $str->string = (string) grapheme_substr($this->string, $start, $length ?? 2147483647);
        return $str;
    }
    public function splice(string $replacement, int $start = 0, ?int $length = null): static
    {
        $str = clone $this;
        $start = $start ? \strlen(grapheme_substr($this->string, 0, $start)) : 0;
        $length = $length ? \strlen(grapheme_substr($this->string, $start, $length ?? 2147483647)) : $length;
        $str->string = substr_replace($this->string, $replacement, $start, $length ?? 2147483647);
        if (normalizer_is_normalized($str->string)) {
            return $str;
        }
        if (\false === $string = normalizer_normalize($str->string)) {
            throw new InvalidArgumentException('Invalid UTF-8 string.');
        }
        $str->string = $string;
        return $str;
    }
    public function split(string $delimiter, ?int $limit = null, ?int $flags = null): array
    {
        if (1 > $limit ??= 2147483647) {
            throw new InvalidArgumentException('Split limit must be a positive integer.');
        }
        if ('' === $delimiter) {
            throw new InvalidArgumentException('Split delimiter is empty.');
        }
        if (null !== $flags) {
            return parent::split($delimiter . 'u', $limit, $flags);
        }
        normalizer_is_normalized($delimiter) ?: $delimiter = normalizer_normalize($delimiter);
        if (\false === $delimiter) {
            throw new InvalidArgumentException('Split delimiter is not a valid UTF-8 string.');
        }
        $str = clone $this;
        $tail = $this->string;
        $chunks = [];
        $indexOf = $this->ignoreCase ? 'grapheme_stripos' : 'grapheme_strpos';
        while (1 < $limit && \false !== $i = $indexOf($tail, $delimiter)) {
            $str->string = grapheme_substr($tail, 0, $i);
            $chunks[] = clone $str;
            $tail = substr($tail, \strlen($str->string) + \strlen($delimiter));
            --$limit;
        }
        $str->string = $tail;
        $chunks[] = clone $str;
        return $chunks;
    }
    public function startsWith(string|iterable|AbstractString $prefix): bool
    {
        if ($prefix instanceof AbstractString) {
            $prefix = $prefix->string;
        } elseif (!\is_string($prefix)) {
            return parent::startsWith($prefix);
        }
        $form = null === $this->ignoreCase ? \Normalizer::NFD : \Normalizer::NFC;
        normalizer_is_normalized($prefix, $form) ?: $prefix = normalizer_normalize($prefix, $form);
        if ('' === $prefix || \false === $prefix) {
            return \false;
        }
        if ($this->ignoreCase) {
            return 0 === mb_stripos(grapheme_extract($this->string, \strlen($prefix), \GRAPHEME_EXTR_MAXBYTES), $prefix, 0, 'UTF-8');
        }
        return $prefix === grapheme_extract($this->string, \strlen($prefix), \GRAPHEME_EXTR_MAXBYTES);
    }
    public function trimPrefix($prefix): static
    {
        if (\is_array($prefix) || $prefix instanceof \Traversable) {
            return parent::trimPrefix($prefix);
        }
        if ($prefix instanceof AbstractString) {
            $prefix = $prefix->string;
        } else {
            $prefix = (string) $prefix;
        }
        if (!normalizer_is_normalized($prefix, \Normalizer::NFC)) {
            $prefix = normalizer_normalize($prefix, \Normalizer::NFC);
        }
        return parent::trimPrefix($prefix);
    }
    public function trimSuffix($suffix): static
    {
        if (\is_array($suffix) || $suffix instanceof \Traversable) {
            return parent::trimSuffix($suffix);
        }
        if ($suffix instanceof AbstractString) {
            $suffix = $suffix->string;
        } else {
            $suffix = (string) $suffix;
        }
        if (!normalizer_is_normalized($suffix, \Normalizer::NFC)) {
            $suffix = normalizer_normalize($suffix, \Normalizer::NFC);
        }
        return parent::trimSuffix($suffix);
    }
    /**
     * @return void
     */
    public function __wakeup()
    {
        if (!\is_string($this->string)) {
            throw new \BadMethodCallException('Cannot unserialize ' . __CLASS__);
        }
        normalizer_is_normalized($this->string) ?: $this->string = normalizer_normalize($this->string);
    }
    public function __clone()
    {
        if (null === $this->ignoreCase) {
            normalizer_is_normalized($this->string) ?: $this->string = normalizer_normalize($this->string);
        }
        $this->ignoreCase = \false;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\String\Exception;

interface ExceptionInterface extends \Throwable
{
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\String\Exception;

class RuntimeException extends \RuntimeException implements ExceptionInterface
{
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\String\Exception;

class InvalidArgumentException extends \InvalidArgumentException implements ExceptionInterface
{
}
{
    "name": "symfony\/string",
    "type": "library",
    "description": "Provides an object-oriented API to strings and deals with bytes, UTF-8 code points and grapheme clusters in a unified way",
    "keywords": [
        "string",
        "utf8",
        "utf-8",
        "grapheme",
        "i18n",
        "unicode"
    ],
    "homepage": "https:\/\/symfony.com",
    "license": "MIT",
    "authors": [
        {
            "name": "Nicolas Grekas",
            "email": "p@tchwork.com"
        },
        {
            "name": "Symfony Community",
            "homepage": "https:\/\/symfony.com\/contributors"
        }
    ],
    "require": {
        "php": ">=8.1",
        "symfony\/polyfill-ctype": "~1.8",
        "symfony\/polyfill-intl-grapheme": "~1.0",
        "symfony\/polyfill-intl-normalizer": "~1.0",
        "symfony\/polyfill-mbstring": "~1.0"
    },
    "require-dev": {
        "symfony\/http-client": "^5.4|^6.0|^7.0",
        "symfony\/intl": "^6.2|^7.0",
        "symfony\/translation-contracts": "^2.5|^3.0",
        "symfony\/var-exporter": "^5.4|^6.0|^7.0"
    },
    "conflict": {
        "symfony\/translation-contracts": "<2.5"
    },
    "autoload": {
        "psr-4": {
            "_ContaoManager\\Symfony\\Component\\String\\": ""
        },
        "files": [
            "Resources\/functions.php"
        ],
        "exclude-from-classmap": [
            "\/Tests\/"
        ]
    },
    "minimum-stability": "dev"
}<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\String\Slugger;

use _ContaoManager\Symfony\Component\String\AbstractUnicodeString;
/**
 * Creates a URL-friendly slug from a given string.
 *
 * @author Titouan Galopin <galopintitouan@gmail.com>
 */
interface SluggerInterface
{
    /**
     * Creates a slug for the given string and locale, using appropriate transliteration when needed.
     */
    public function slug(string $string, string $separator = '-', ?string $locale = null): AbstractUnicodeString;
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\String\Slugger;

use _ContaoManager\Symfony\Component\Intl\Transliterator\EmojiTransliterator;
use _ContaoManager\Symfony\Component\String\AbstractUnicodeString;
use _ContaoManager\Symfony\Component\String\UnicodeString;
use _ContaoManager\Symfony\Contracts\Translation\LocaleAwareInterface;
if (!interface_exists(LocaleAwareInterface::class)) {
    throw new \LogicException('You cannot use the "Symfony\Component\String\Slugger\AsciiSlugger" as the "symfony/translation-contracts" package is not installed. Try running "composer require symfony/translation-contracts".');
}
/**
 * @author Titouan Galopin <galopintitouan@gmail.com>
 */
class AsciiSlugger implements SluggerInterface, LocaleAwareInterface
{
    private const LOCALE_TO_TRANSLITERATOR_ID = ['am' => 'Amharic-Latin', 'ar' => 'Arabic-Latin', 'az' => 'Azerbaijani-Latin', 'be' => 'Belarusian-Latin', 'bg' => 'Bulgarian-Latin', 'bn' => 'Bengali-Latin', 'de' => 'de-ASCII', 'el' => 'Greek-Latin', 'fa' => 'Persian-Latin', 'he' => 'Hebrew-Latin', 'hy' => 'Armenian-Latin', 'ka' => 'Georgian-Latin', 'kk' => 'Kazakh-Latin', 'ky' => 'Kirghiz-Latin', 'ko' => 'Korean-Latin', 'mk' => 'Macedonian-Latin', 'mn' => 'Mongolian-Latin', 'or' => 'Oriya-Latin', 'ps' => 'Pashto-Latin', 'ru' => 'Russian-Latin', 'sr' => 'Serbian-Latin', 'sr_Cyrl' => 'Serbian-Latin', 'th' => 'Thai-Latin', 'tk' => 'Turkmen-Latin', 'uk' => 'Ukrainian-Latin', 'uz' => 'Uzbek-Latin', 'zh' => 'Han-Latin'];
    private ?string $defaultLocale;
    private \Closure|array $symbolsMap = ['en' => ['@' => 'at', '&' => 'and']];
    private bool|string $emoji = \false;
    /**
     * Cache of transliterators per locale.
     *
     * @var \Transliterator[]
     */
    private array $transliterators = [];
    public function __construct(?string $defaultLocale = null, array|\Closure|null $symbolsMap = null)
    {
        $this->defaultLocale = $defaultLocale;
        $this->symbolsMap = $symbolsMap ?? $this->symbolsMap;
    }
    /**
     * @return void
     */
    public function setLocale(string $locale)
    {
        $this->defaultLocale = $locale;
    }
    public function getLocale(): string
    {
        return $this->defaultLocale;
    }
    /**
     * @param bool|string $emoji true will use the same locale,
     *                           false will disable emoji,
     *                           and a string to use a specific locale
     */
    public function withEmoji(bool|string $emoji = \true): static
    {
        if (\false !== $emoji && !class_exists(EmojiTransliterator::class)) {
            throw new \LogicException(\sprintf('You cannot use the "%s()" method as the "symfony/intl" package is not installed. Try running "composer require symfony/intl".', __METHOD__));
        }
        $new = clone $this;
        $new->emoji = $emoji;
        return $new;
    }
    public function slug(string $string, string $separator = '-', ?string $locale = null): AbstractUnicodeString
    {
        $locale ??= $this->defaultLocale;
        $transliterator = [];
        if ($locale && ('de' === $locale || str_starts_with($locale, 'de_'))) {
            // Use the shortcut for German in UnicodeString::ascii() if possible (faster and no requirement on intl)
            $transliterator = ['de-ASCII'];
        } elseif (\function_exists('transliterator_transliterate') && $locale) {
            $transliterator = (array) $this->createTransliterator($locale);
        }
        if ($emojiTransliterator = $this->createEmojiTransliterator($locale)) {
            $transliterator[] = $emojiTransliterator;
        }
        if ($this->symbolsMap instanceof \Closure) {
            // If the symbols map is passed as a closure, there is no need to fallback to the parent locale
            // as the closure can just provide substitutions for all locales of interest.
            $symbolsMap = $this->symbolsMap;
            array_unshift($transliterator, static fn($s) => $symbolsMap($s, $locale));
        }
        $unicodeString = (new UnicodeString($string))->ascii($transliterator);
        if (\is_array($this->symbolsMap)) {
            $map = null;
            if (isset($this->symbolsMap[$locale ?? ''])) {
                $map = $this->symbolsMap[$locale ?? ''];
            } else {
                $parent = self::getParentLocale($locale);
                if ($parent && isset($this->symbolsMap[$parent])) {
                    $map = $this->symbolsMap[$parent];
                }
            }
            if ($map) {
                foreach ($map as $char => $replace) {
                    $unicodeString = $unicodeString->replace($char, ' ' . $replace . ' ');
                }
            }
        }
        return $unicodeString->replaceMatches('/[^A-Za-z0-9]++/', $separator)->trim($separator);
    }
    private function createTransliterator(string $locale): ?\Transliterator
    {
        if (\array_key_exists($locale, $this->transliterators)) {
            return $this->transliterators[$locale];
        }
        // Exact locale supported, cache and return
        if ($id = self::LOCALE_TO_TRANSLITERATOR_ID[$locale] ?? null) {
            return $this->transliterators[$locale] = \Transliterator::create($id . '/BGN') ?? \Transliterator::create($id);
        }
        // Locale not supported and no parent, fallback to any-latin
        if (!$parent = self::getParentLocale($locale)) {
            return $this->transliterators[$locale] = null;
        }
        // Try to use the parent locale (ie. try "de" for "de_AT") and cache both locales
        if ($id = self::LOCALE_TO_TRANSLITERATOR_ID[$parent] ?? null) {
            $transliterator = \Transliterator::create($id . '/BGN') ?? \Transliterator::create($id);
        }
        return $this->transliterators[$locale] = $this->transliterators[$parent] = $transliterator ?? null;
    }
    private function createEmojiTransliterator(?string $locale): ?EmojiTransliterator
    {
        if (\is_string($this->emoji)) {
            $locale = $this->emoji;
        } elseif (!$this->emoji) {
            return null;
        }
        while (null !== $locale) {
            try {
                return EmojiTransliterator::create("emoji-{$locale}");
            } catch (\IntlException) {
                $locale = self::getParentLocale($locale);
            }
        }
        return null;
    }
    private static function getParentLocale(?string $locale): ?string
    {
        if (!$locale) {
            return null;
        }
        if (\false === $str = strrchr($locale, '_')) {
            // no parent locale
            return null;
        }
        return substr($locale, 0, -\strlen($str));
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Security\Core\Role;

/**
 * Allows migrating session payloads from v4.
 *
 * @internal
 */
class SwitchUserRole extends Role
{
    private $deprecationTriggered;
    private $source;
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Security\Core\Role;

/**
 * RoleHierarchyInterface is the interface for a role hierarchy.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
interface RoleHierarchyInterface
{
    /**
     * @param string[] $roles
     *
     * @return string[]
     */
    public function getReachableRoleNames(array $roles): array;
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Security\Core\Role;

/**
 * Allows migrating session payloads from v4.
 *
 * @internal
 */
class Role
{
    private $role;
    private function __construct()
    {
    }
    public function __toString(): string
    {
        return $this->role;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Security\Core\Role;

/**
 * RoleHierarchy defines a role hierarchy.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class RoleHierarchy implements RoleHierarchyInterface
{
    private array $hierarchy;
    /** @var array<string, list<string>> */
    protected $map;
    /**
     * @param array<string, list<string>> $hierarchy
     */
    public function __construct(array $hierarchy)
    {
        $this->hierarchy = $hierarchy;
        $this->buildRoleMap();
    }
    public function getReachableRoleNames(array $roles): array
    {
        $reachableRoles = $roles;
        foreach ($roles as $role) {
            if (!isset($this->map[$role])) {
                continue;
            }
            foreach ($this->map[$role] as $r) {
                $reachableRoles[] = $r;
            }
        }
        return array_values(array_unique($reachableRoles));
    }
    /**
     * @return void
     */
    protected function buildRoleMap()
    {
        $this->map = [];
        foreach ($this->hierarchy as $main => $roles) {
            $this->map[$main] = $roles;
            $visited = [];
            $additionalRoles = $roles;
            while ($role = array_shift($additionalRoles)) {
                if (!isset($this->hierarchy[$role])) {
                    continue;
                }
                $visited[] = $role;
                foreach ($this->hierarchy[$role] as $roleToAdd) {
                    $this->map[$main][] = $roleToAdd;
                }
                foreach (array_diff($this->hierarchy[$role], $visited) as $additionalRole) {
                    $additionalRoles[] = $additionalRole;
                }
            }
            $this->map[$main] = array_unique($this->map[$main]);
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Security\Core\Validator\Constraints;

use _ContaoManager\Symfony\Component\Validator\Constraint;
/**
 * @Annotation
 * @Target({"PROPERTY", "METHOD", "ANNOTATION"})
 */
#[\Attribute(\Attribute::TARGET_PROPERTY | \Attribute::TARGET_METHOD | \Attribute::IS_REPEATABLE)]
class UserPassword extends Constraint
{
    public const INVALID_PASSWORD_ERROR = '2d2a8bb4-ddc8-45e4-9b0f-8670d3a3e290';
    protected const ERROR_NAMES = [self::INVALID_PASSWORD_ERROR => 'INVALID_PASSWORD_ERROR'];
    public $message = 'This value should be the user\'s current password.';
    public $service = 'security.validator.user_password';
    public function __construct(?array $options = null, ?string $message = null, ?string $service = null, ?array $groups = null, mixed $payload = null)
    {
        parent::__construct($options, $groups, $payload);
        $this->message = $message ?? $this->message;
        $this->service = $service ?? $this->service;
    }
    public function validatedBy(): string
    {
        return $this->service;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Security\Core\Validator\Constraints;

use _ContaoManager\Symfony\Component\PasswordHasher\Hasher\PasswordHasherFactoryInterface;
use _ContaoManager\Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
use _ContaoManager\Symfony\Component\Security\Core\User\LegacyPasswordAuthenticatedUserInterface;
use _ContaoManager\Symfony\Component\Security\Core\User\PasswordAuthenticatedUserInterface;
use _ContaoManager\Symfony\Component\Validator\Constraint;
use _ContaoManager\Symfony\Component\Validator\ConstraintValidator;
use _ContaoManager\Symfony\Component\Validator\Exception\ConstraintDefinitionException;
use _ContaoManager\Symfony\Component\Validator\Exception\UnexpectedTypeException;
class UserPasswordValidator extends ConstraintValidator
{
    private TokenStorageInterface $tokenStorage;
    private PasswordHasherFactoryInterface $hasherFactory;
    public function __construct(TokenStorageInterface $tokenStorage, PasswordHasherFactoryInterface $hasherFactory)
    {
        $this->tokenStorage = $tokenStorage;
        $this->hasherFactory = $hasherFactory;
    }
    /**
     * @return void
     */
    public function validate(mixed $password, Constraint $constraint)
    {
        if (!$constraint instanceof UserPassword) {
            throw new UnexpectedTypeException($constraint, UserPassword::class);
        }
        if (null === $password || '' === $password) {
            $this->context->buildViolation($constraint->message)->setCode(UserPassword::INVALID_PASSWORD_ERROR)->addViolation();
            return;
        }
        if (!\is_string($password)) {
            throw new UnexpectedTypeException($password, 'string');
        }
        $user = $this->tokenStorage->getToken()->getUser();
        if (!$user instanceof PasswordAuthenticatedUserInterface) {
            throw new ConstraintDefinitionException(\sprintf('The "%s" class must implement the "%s" interface.', get_debug_type($user), PasswordAuthenticatedUserInterface::class));
        }
        $hasher = $this->hasherFactory->getPasswordHasher($user);
        if (null === $user->getPassword() || !$hasher->verify($user->getPassword(), $password, $user instanceof LegacyPasswordAuthenticatedUserInterface ? $user->getSalt() : null)) {
            $this->context->buildViolation($constraint->message)->setCode(UserPassword::INVALID_PASSWORD_ERROR)->addViolation();
        }
    }
}
Copyright (c) 2004-present Fabien Potencier

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is furnished
to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Security\Core\Test;

use _ContaoManager\PHPUnit\Framework\TestCase;
use _ContaoManager\Symfony\Component\Security\Core\Authentication\Token\NullToken;
use _ContaoManager\Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use _ContaoManager\Symfony\Component\Security\Core\Authorization\AccessDecisionManager;
use _ContaoManager\Symfony\Component\Security\Core\Authorization\Strategy\AccessDecisionStrategyInterface;
use _ContaoManager\Symfony\Component\Security\Core\Authorization\Voter\VoterInterface;
/**
 * Abstract test case for access decision strategies.
 *
 * @author Alexander M. Turek <me@derrabus.de>
 */
abstract class AccessDecisionStrategyTestCase extends TestCase
{
    /**
     * @dataProvider provideStrategyTests
     *
     * @param VoterInterface[] $voters
     */
    final public function testDecide(AccessDecisionStrategyInterface $strategy, array $voters, bool $expected)
    {
        $manager = new AccessDecisionManager($voters, $strategy);
        $this->assertSame($expected, $manager->decide(new NullToken(), ['ROLE_FOO']));
    }
    /**
     * @return iterable<array{AccessDecisionStrategyInterface, VoterInterface[], bool}>
     */
    abstract public static function provideStrategyTests(): iterable;
    /**
     * @return VoterInterface[]
     */
    final protected static function getVoters(int $grants, int $denies, int $abstains): array
    {
        $voters = [];
        for ($i = 0; $i < $grants; ++$i) {
            $voters[] = static::getVoter(VoterInterface::ACCESS_GRANTED);
        }
        for ($i = 0; $i < $denies; ++$i) {
            $voters[] = static::getVoter(VoterInterface::ACCESS_DENIED);
        }
        for ($i = 0; $i < $abstains; ++$i) {
            $voters[] = static::getVoter(VoterInterface::ACCESS_ABSTAIN);
        }
        return $voters;
    }
    final protected static function getVoter(int $vote): VoterInterface
    {
        return new class($vote) implements VoterInterface
        {
            private int $vote;
            public function __construct(int $vote)
            {
                $this->vote = $vote;
            }
            public function vote(TokenInterface $token, $subject, array $attributes): int
            {
                return $this->vote;
            }
        };
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Security\Core\Signature;

use _ContaoManager\Psr\Cache\CacheItemPoolInterface;
/**
 * @author Ryan Weaver <ryan@symfonycasts.com>
 */
final class ExpiredSignatureStorage
{
    private CacheItemPoolInterface $cache;
    private int $lifetime;
    public function __construct(CacheItemPoolInterface $cache, int $lifetime)
    {
        $this->cache = $cache;
        $this->lifetime = $lifetime;
    }
    public function countUsages(string $hash): int
    {
        $key = rawurlencode($hash);
        if (!$this->cache->hasItem($key)) {
            return 0;
        }
        return $this->cache->getItem($key)->get();
    }
    public function incrementUsages(string $hash): void
    {
        $item = $this->cache->getItem(rawurlencode($hash));
        if (!$item->isHit()) {
            $item->expiresAfter($this->lifetime);
        }
        $item->set($this->countUsages($hash) + 1);
        $this->cache->save($item);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Security\Core\Signature\Exception;

use _ContaoManager\Symfony\Component\Security\Core\Exception\RuntimeException;
/**
 * @author Wouter de Jong <wouter@wouterj.nl>
 */
class InvalidSignatureException extends RuntimeException
{
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Security\Core\Signature\Exception;

use _ContaoManager\Symfony\Component\Security\Core\Exception\RuntimeException;
/**
 * @author Wouter de Jong <wouter@wouterj.nl>
 */
class ExpiredSignatureException extends RuntimeException
{
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Security\Core\Signature;

use _ContaoManager\Symfony\Component\PropertyAccess\PropertyAccessorInterface;
use _ContaoManager\Symfony\Component\Security\Core\Exception\InvalidArgumentException;
use _ContaoManager\Symfony\Component\Security\Core\Signature\Exception\ExpiredSignatureException;
use _ContaoManager\Symfony\Component\Security\Core\Signature\Exception\InvalidSignatureException;
use _ContaoManager\Symfony\Component\Security\Core\User\UserInterface;
/**
 * Creates and validates secure hashes used in login links and remember-me cookies.
 *
 * @author Wouter de Jong <wouter@wouterj.nl>
 * @author Ryan Weaver <ryan@symfonycasts.com>
 */
class SignatureHasher
{
    private PropertyAccessorInterface $propertyAccessor;
    private array $signatureProperties;
    private string $secret;
    private ?ExpiredSignatureStorage $expiredSignaturesStorage;
    private ?int $maxUses;
    /**
     * @param array                        $signatureProperties      Properties of the User; the hash is invalidated if these properties change
     * @param ExpiredSignatureStorage|null $expiredSignaturesStorage If provided, secures a sequence of hashes that are expired
     * @param int|null                     $maxUses                  Used together with $expiredSignatureStorage to allow a maximum usage of a hash
     */
    public function __construct(
        PropertyAccessorInterface $propertyAccessor,
        array $signatureProperties,
        #[\SensitiveParameter]
        string $secret,
        ?ExpiredSignatureStorage $expiredSignaturesStorage = null,
        ?int $maxUses = null
    )
    {
        if (!$secret) {
            throw new InvalidArgumentException('A non-empty secret is required.');
        }
        $this->propertyAccessor = $propertyAccessor;
        $this->signatureProperties = $signatureProperties;
        $this->secret = $secret;
        $this->expiredSignaturesStorage = $expiredSignaturesStorage;
        $this->maxUses = $maxUses;
    }
    /**
     * Verifies the hash using the provided user identifier and expire time.
     *
     * This method must be called before the user object is loaded from a provider.
     *
     * @param int    $expires The expiry time as a unix timestamp
     * @param string $hash    The plaintext hash provided by the request
     *
     * @throws InvalidSignatureException If the signature does not match the provided parameters
     * @throws ExpiredSignatureException If the signature is no longer valid
     */
    public function acceptSignatureHash(string $userIdentifier, int $expires, string $hash): void
    {
        if ($expires < time()) {
            throw new ExpiredSignatureException('Signature has expired.');
        }
        $hmac = substr($hash, 0, 44);
        $payload = substr($hash, 44) . ':' . $expires . ':' . $userIdentifier;
        if (!hash_equals($hmac, $this->generateHash($payload))) {
            throw new InvalidSignatureException('Invalid or expired signature.');
        }
    }
    /**
     * Verifies the hash using the provided user and expire time.
     *
     * @param int    $expires The expiry time as a unix timestamp
     * @param string $hash    The plaintext hash provided by the request
     *
     * @throws InvalidSignatureException If the signature does not match the provided parameters
     * @throws ExpiredSignatureException If the signature is no longer valid
     */
    public function verifySignatureHash(UserInterface $user, int $expires, string $hash): void
    {
        if ($expires < time()) {
            throw new ExpiredSignatureException('Signature has expired.');
        }
        if (!hash_equals($hash, $this->computeSignatureHash($user, $expires))) {
            throw new InvalidSignatureException('Invalid or expired signature.');
        }
        if ($this->expiredSignaturesStorage && $this->maxUses) {
            if ($this->expiredSignaturesStorage->countUsages($hash) >= $this->maxUses) {
                throw new ExpiredSignatureException(\sprintf('Signature can only be used "%d" times.', $this->maxUses));
            }
            $this->expiredSignaturesStorage->incrementUsages($hash);
        }
    }
    /**
     * Computes the secure hash for the provided user and expire time.
     *
     * @param int $expires The expiry time as a unix timestamp
     */
    public function computeSignatureHash(UserInterface $user, int $expires): string
    {
        $userIdentifier = $user->getUserIdentifier();
        $fieldsHash = hash_init('sha256');
        foreach ($this->signatureProperties as $property) {
            $value = $this->propertyAccessor->getValue($user, $property) ?? '';
            if ($value instanceof \DateTimeInterface) {
                $value = $value->format('c');
            }
            if (!\is_scalar($value) && !$value instanceof \Stringable) {
                throw new \InvalidArgumentException(\sprintf('The property path "%s" on the user object "%s" must return a value that can be cast to a string, but "%s" was returned.', $property, $user::class, get_debug_type($value)));
            }
            hash_update($fieldsHash, ':' . base64_encode($value));
        }
        $fieldsHash = strtr(base64_encode(hash_final($fieldsHash, \true)), '+/=', '-_~');
        return $this->generateHash($fieldsHash . ':' . $expires . ':' . $userIdentifier) . $fieldsHash;
    }
    private function generateHash(string $tokenValue): string
    {
        return strtr(base64_encode(hash_hmac('sha256', $tokenValue, $this->secret, \true)), '+/=', '-_~');
    }
}
CHANGELOG
=========

6.4
---

 * Make `PersistentToken` immutable
 * Deprecate accepting only `DateTime` for `TokenProviderInterface::updateToken()`, use `DateTimeInterface` instead

6.3
---

 * Add `AttributesBasedUserProviderInterface` to allow `$attributes` optional argument on `loadUserByIdentifier`
 * Add `OidcUser` with OIDC support for `OidcUserInfoTokenHandler`

6.2
---

 * Deprecate the `Security` class, use `Symfony\Bundle\SecurityBundle\Security` instead
 * Change the signature of `TokenStorageInterface::setToken()` to `setToken(?TokenInterface $token)`
 * Deprecate calling `TokenStorage::setToken()` without arguments
 * Add a `ChainUserChecker` to allow calling multiple user checkers for a firewall

6.0
---

 * `TokenInterface` does not extend `Serializable` anymore
 * Remove all classes in the `Core\Encoder\`  sub-namespace, use the `PasswordHasher` component instead
 * Remove methods `getPassword()` and `getSalt()` from `UserInterface`, use `PasswordAuthenticatedUserInterface`
   or `LegacyPasswordAuthenticatedUserInterface` instead
* `AccessDecisionManager` requires the strategy to be passed as in instance of `AccessDecisionStrategyInterface`

5.4.21
------

 * [BC BREAK] `AccessDecisionStrategyTestCase::provideStrategyTests()` is now static

5.4
---

 * Add a `CacheableVoterInterface` for voters that vote only on identified attributes and subjects
 * Deprecate `AuthenticationEvents::AUTHENTICATION_FAILURE`, use the `LoginFailureEvent` instead
 * Deprecate `AnonymousToken`, as the related authenticator was deprecated in 5.3
 * Deprecate `Token::getCredentials()`, tokens should no longer contain credentials (as they represent authenticated sessions)
 * Deprecate returning `string|\Stringable` from `Token::getUser()` (it must return a `UserInterface`)
 * Deprecate `AuthenticatedVoter::IS_AUTHENTICATED_ANONYMOUSLY` and `AuthenticatedVoter::IS_ANONYMOUS`,
   use `AuthenticatedVoter::IS_AUTHENTICATED_FULLY` or `AuthenticatedVoter::IS_AUTHENTICATED` instead.
 * Deprecate `AuthenticationTrustResolverInterface::isAnonymous()` and the `is_anonymous()` expression
   function as anonymous no longer exists in version 6, use the `isFullFledged()` or the new
   `isAuthenticated()` instead if you want to check if the request is (fully) authenticated.
 * Deprecate the `$authenticationManager` argument of the `AuthorizationChecker` constructor
 * Deprecate setting the `$alwaysAuthenticate` argument to `true` and not setting the
   `$exceptionOnNoToken` argument to `false` of `AuthorizationChecker`
 * Deprecate methods `TokenInterface::isAuthenticated()` and `setAuthenticated`,
   return null from "getUser()" instead when a token is not authenticated
 * Add `AccessDecisionStrategyInterface` to allow custom access decision strategies
 * Add access decision strategies `AffirmativeStrategy`, `ConsensusStrategy`, `PriorityStrategy`, `UnanimousStrategy`
 * Deprecate passing the strategy as string to `AccessDecisionManager`,
   pass an instance of `AccessDecisionStrategyInterface` instead
 * Flag `AccessDecisionManager` as `@final`

5.3
---

The CHANGELOG for version 5.3 and earlier can be found at https://github.com/symfony/symfony/blob/5.3/src/Symfony/Component/Security/CHANGELOG.md
<?xml version="1.0" encoding="utf-8"?>
<xliff xmlns="urn:oasis:names:tc:xliff:document:1.2" version="1.2">
    <file source-language="en" target-language="sq" datatype="plaintext" original="file.ext">
        <body>
            <trans-unit id="1">
                <source>An authentication exception occurred.</source>
                <target>Ndodhi një problem në autentikim.</target>
            </trans-unit>
            <trans-unit id="2">
                <source>Authentication credentials could not be found.</source>
                <target>Kredencialet e autentikimit nuk mund të gjendeshin.</target>
            </trans-unit>
            <trans-unit id="3">
                <source>Authentication request could not be processed due to a system problem.</source>
                <target>Kërkesa për autentikim nuk mund të përpunohej për shkak të një problemi në sistem.</target>
            </trans-unit>
            <trans-unit id="4">
                <source>Invalid credentials.</source>
                <target>Kredenciale të pavlefshme.</target>
            </trans-unit>
            <trans-unit id="5">
                <source>Cookie has already been used by someone else.</source>
                <target>“Cookie” është përdorur tashmë nga dikush tjetër.</target>
            </trans-unit>
            <trans-unit id="6">
                <source>Not privileged to request the resource.</source>
                <target>Nuk është i privilegjuar të kërkojë burimin.</target>
            </trans-unit>
            <trans-unit id="7">
                <source>Invalid CSRF token.</source>
                <target>Identifikues i pavlefshëm CSRF.</target>
            </trans-unit>
            <trans-unit id="9">
                <source>No authentication provider found to support the authentication token.</source>
                <target>Asnjë ofrues i vërtetimit nuk u gjet që të mbështesë simbolin e vërtetimit.</target>
            </trans-unit>
            <trans-unit id="10">
                <source>No session available, it either timed out or cookies are not enabled.</source>
                <target>Nuk ka asnjë sesion të vlefshëm, i ka skaduar koha ose cookies nuk janë aktivizuar.</target>
            </trans-unit>
            <trans-unit id="11">
                <source>No token could be found.</source>
                <target>Asnjë simbol identifikimi nuk mund të gjendej.</target>
            </trans-unit>
            <trans-unit id="12">
                <source>Username could not be found.</source>
                <target>Emri i përdoruesit nuk mund të gjendej.</target>
            </trans-unit>
            <trans-unit id="13">
                <source>Account has expired.</source>
                <target>Llogaria ka skaduar.</target>
            </trans-unit>
            <trans-unit id="14">
                <source>Credentials have expired.</source>
                <target>Kredencialet kanë skaduar.</target>
            </trans-unit>
            <trans-unit id="15">
                <source>Account is disabled.</source>
                <target>Llogaria është çaktivizuar.</target>
            </trans-unit>
            <trans-unit id="16">
                <source>Account is locked.</source>
                <target>Llogaria është e kyçur.</target>
            </trans-unit>
            <trans-unit id="17">
                <source>Too many failed login attempts, please try again later.</source>
                <target>Shumë përpjekje të dështuara autentikimi, provo përsëri më vonë.</target>
            </trans-unit>
            <trans-unit id="18">
                <source>Invalid or expired login link.</source>
                <target>Link hyrje i pavlefshëm ose i skaduar.</target>
            </trans-unit>
            <trans-unit id="19">
                <source>Too many failed login attempts, please try again in %minutes% minute.</source>
                <target>Shumë përpjekje të dështuara për identifikim; provo sërish pas %minutes% minutë.</target>
            </trans-unit>
            <trans-unit id="20">
                <source>Too many failed login attempts, please try again in %minutes% minutes.</source>
                <target>Shumë përpjekje të dështuara për identifikim, ju lutemi provoni përsëri pas %minutes% minutash.</target>
            </trans-unit>
        </body>
    </file>
</xliff>
<?xml version="1.0" encoding="utf-8"?>
<xliff xmlns="urn:oasis:names:tc:xliff:document:1.2" version="1.2">
    <file source-language="en" target-language="ru" datatype="plaintext" original="file.ext">
        <body>
            <trans-unit id="1">
                <source>An authentication exception occurred.</source>
                <target>Ошибка аутентификации.</target>
            </trans-unit>
            <trans-unit id="2">
                <source>Authentication credentials could not be found.</source>
                <target>Аутентификационные данные не найдены.</target>
            </trans-unit>
            <trans-unit id="3">
                <source>Authentication request could not be processed due to a system problem.</source>
                <target>Запрос аутентификации не может быть обработан в связи с проблемой в системе.</target>
            </trans-unit>
            <trans-unit id="4">
                <source>Invalid credentials.</source>
                <target>Недействительные аутентификационные данные.</target>
            </trans-unit>
            <trans-unit id="5">
                <source>Cookie has already been used by someone else.</source>
                <target>Cookie уже был использован кем-то другим.</target>
            </trans-unit>
            <trans-unit id="6">
                <source>Not privileged to request the resource.</source>
                <target>Отсутствуют права на запрос этого ресурса.</target>
            </trans-unit>
            <trans-unit id="7">
                <source>Invalid CSRF token.</source>
                <target>Недействительный токен CSRF.</target>
            </trans-unit>
            <trans-unit id="9">
                <source>No authentication provider found to support the authentication token.</source>
                <target>Не найден провайдер аутентификации, поддерживающий токен аутентификации.</target>
            </trans-unit>
            <trans-unit id="10">
                <source>No session available, it either timed out or cookies are not enabled.</source>
                <target>Сессия не найдена, ее время истекло, либо cookies не включены.</target>
            </trans-unit>
            <trans-unit id="11">
                <source>No token could be found.</source>
                <target>Токен не найден.</target>
            </trans-unit>
            <trans-unit id="12">
                <source>Username could not be found.</source>
                <target>Имя пользователя не найдено.</target>
            </trans-unit>
            <trans-unit id="13">
                <source>Account has expired.</source>
                <target>Время действия учетной записи истекло.</target>
            </trans-unit>
            <trans-unit id="14">
                <source>Credentials have expired.</source>
                <target>Время действия аутентификационных данных истекло.</target>
            </trans-unit>
            <trans-unit id="15">
                <source>Account is disabled.</source>
                <target>Учетная запись отключена.</target>
            </trans-unit>
            <trans-unit id="16">
                <source>Account is locked.</source>
                <target>Учетная запись заблокирована.</target>
            </trans-unit>
            <trans-unit id="17">
                <source>Too many failed login attempts, please try again later.</source>
                <target>Слишком много неудачных попыток входа, пожалуйста, попробуйте позже.</target>
            </trans-unit>
            <trans-unit id="18">
                <source>Invalid or expired login link.</source>
                <target>Ссылка для входа недействительна или просрочена.</target>
            </trans-unit>
            <trans-unit id="19">
                <source>Too many failed login attempts, please try again in %minutes% minute.</source>
                <target>Слишком много неудачных попыток входа, повторите попытку через %minutes% минуту.</target>
            </trans-unit>
            <trans-unit id="20">
                <source>Too many failed login attempts, please try again in %minutes% minutes.</source>
                <target>Слишком много неудачных попыток входа, повторите попытку через %minutes% минуту.|Слишком много неудачных попыток входа, повторите попытку через %minutes% минуты.|Слишком много неудачных попыток входа, повторите попытку через %minutes% минут.</target>
            </trans-unit>
        </body>
    </file>
</xliff>
<?xml version="1.0" encoding="utf-8"?>
<xliff xmlns="urn:oasis:names:tc:xliff:document:1.2" version="1.2">
    <file source-language="en" target-language="hy" datatype="plaintext" original="file.ext">
        <body>
            <trans-unit id="1">
                <source>An authentication exception occurred.</source>
                <target>Նույնականացման սխալ։</target>
            </trans-unit>
            <trans-unit id="2">
                <source>Authentication credentials could not be found.</source>
                <target>Նույնականացման տվյալները չեն գտնվել։</target>
            </trans-unit>
            <trans-unit id="3">
                <source>Authentication request could not be processed due to a system problem.</source>
                <target>Համակարգային սխալ՝ նույնականացման հացրման պրոցեսինգի ժամանակ։</target>
            </trans-unit>
            <trans-unit id="4">
                <source>Invalid credentials.</source>
                <target>Սխալ մուտքային տվյալներ</target>
            </trans-unit>
            <trans-unit id="5">
                <source>Cookie has already been used by someone else.</source>
                <target>Cookie-ն արդեն օգտագործվում է ուրիշի կողմից։</target>
            </trans-unit>
            <trans-unit id="6">
                <source>Not privileged to request the resource.</source>
                <target>Ռեսուրսի հարցման համար չկա թույլատվություն։</target>
            </trans-unit>
            <trans-unit id="7">
                <source>Invalid CSRF token.</source>
                <target>Անվավեր CSRF թոքեն։</target>
            </trans-unit>
            <trans-unit id="9">
                <source>No authentication provider found to support the authentication token.</source>
                <target>Նույնականացման ոչ մի մատակարար չի գտնվել, որ աջակցի նույնականացման թոքենը։</target>
            </trans-unit>
            <trans-unit id="10">
                <source>No session available, it either timed out or cookies are not enabled.</source>
                <target>Հասանելի սեսիա չկա, կամ այն սպառվել է կամ cookie-ները անջատված են:</target>
            </trans-unit>
            <trans-unit id="11">
                <source>No token could be found.</source>
                <target>Թոքենը չի գտնվել։</target>
            </trans-unit>
            <trans-unit id="12">
                <source>Username could not be found.</source>
                <target>Օգտանունը չի գտնվել։</target>
            </trans-unit>
            <trans-unit id="13">
                <source>Account has expired.</source>
                <target>Հաշիվը ժամկետանց է։</target>
            </trans-unit>
            <trans-unit id="14">
                <source>Credentials have expired.</source>
                <target>Մուտքային տվյալները ժամկետանց են։</target>
            </trans-unit>
            <trans-unit id="15">
                <source>Account is disabled.</source>
                <target>Հաշիվը դեկատիվացված է։</target>
            </trans-unit>
            <trans-unit id="16">
                <source>Account is locked.</source>
                <target>Հաշիվն արգելափակված է։</target>
            </trans-unit>
            <trans-unit id="17">
                <source>Too many failed login attempts, please try again later.</source>
                <target>Չափից շատ մուտքի փորձեր, խնդրում ենք փորձել մի փոքր ուշ</target>
            </trans-unit>
            <trans-unit id="18">
                <source>Invalid or expired login link.</source>
                <target>Անվավեր կամ ժամկետանց մուտքի հղում։</target>
            </trans-unit>
            <trans-unit id="19">
                <source>Too many failed login attempts, please try again in %minutes% minute.</source>
                <target>Մուտքի չափազանց շատ անհաջող փորձեր: Խնդրում ենք կրկին փորձել %minutes րոպե:</target>
            </trans-unit>
            <trans-unit id="20">
                <source>Too many failed login attempts, please try again in %minutes% minutes.</source>
                <target>Չափազանց շատ անհաջող մուտքի փորձեր, խնդրում ենք փորձել կրկին %minutes% րոպեից.</target>
            </trans-unit>
        </body>
    </file>
</xliff>
<?xml version="1.0" encoding="utf-8"?>
<xliff xmlns="urn:oasis:names:tc:xliff:document:1.2" version="1.2">
    <file source-language="en" target-language="fr" datatype="plaintext" original="file.ext">
        <body>
            <trans-unit id="1">
                <source>An authentication exception occurred.</source>
                <target>Une exception d'authentification s'est produite.</target>
            </trans-unit>
            <trans-unit id="2">
                <source>Authentication credentials could not be found.</source>
                <target>Les identifiants d'authentification n'ont pas pu être trouvés.</target>
            </trans-unit>
            <trans-unit id="3">
                <source>Authentication request could not be processed due to a system problem.</source>
                <target>La requête d'authentification n'a pas pu être executée à cause d'un problème système.</target>
            </trans-unit>
            <trans-unit id="4">
                <source>Invalid credentials.</source>
                <target>Identifiants invalides.</target>
            </trans-unit>
            <trans-unit id="5">
                <source>Cookie has already been used by someone else.</source>
                <target>Le cookie a déjà été utilisé par quelqu'un d'autre.</target>
            </trans-unit>
            <trans-unit id="6">
                <source>Not privileged to request the resource.</source>
                <target>Privilèges insuffisants pour accéder à la ressource.</target>
            </trans-unit>
            <trans-unit id="7">
                <source>Invalid CSRF token.</source>
                <target>Jeton CSRF invalide.</target>
            </trans-unit>
            <trans-unit id="9">
                <source>No authentication provider found to support the authentication token.</source>
                <target>Aucun fournisseur d'authentification n'a été trouvé pour supporter le jeton d'authentification.</target>
            </trans-unit>
            <trans-unit id="10">
                <source>No session available, it either timed out or cookies are not enabled.</source>
                <target>Aucune session disponible, celle-ci a expiré ou les cookies ne sont pas activés.</target>
            </trans-unit>
            <trans-unit id="11">
                <source>No token could be found.</source>
                <target>Aucun jeton n'a pu être trouvé.</target>
            </trans-unit>
            <trans-unit id="12">
                <source>Username could not be found.</source>
                <target>Le nom d'utilisateur n'a pas pu être trouvé.</target>
            </trans-unit>
            <trans-unit id="13">
                <source>Account has expired.</source>
                <target>Le compte a expiré.</target>
            </trans-unit>
            <trans-unit id="14">
                <source>Credentials have expired.</source>
                <target>Les identifiants ont expiré.</target>
            </trans-unit>
            <trans-unit id="15">
                <source>Account is disabled.</source>
                <target>Le compte est désactivé.</target>
            </trans-unit>
            <trans-unit id="16">
                <source>Account is locked.</source>
                <target>Le compte est bloqué.</target>
            </trans-unit>
            <trans-unit id="17">
                <source>Too many failed login attempts, please try again later.</source>
                <target>Plusieurs tentatives de connexion ont échoué, veuillez réessayer plus tard.</target>
            </trans-unit>
            <trans-unit id="18">
                <source>Invalid or expired login link.</source>
                <target>Lien de connexion invalide ou expiré.</target>
            </trans-unit>
            <trans-unit id="19">
                <source>Too many failed login attempts, please try again in %minutes% minute.</source>
                <target>Plusieurs tentatives de connexion ont échoué, veuillez réessayer dans %minutes% minute.</target>
            </trans-unit>
            <trans-unit id="20">
                <source>Too many failed login attempts, please try again in %minutes% minutes.</source>
                <target>Trop de tentatives de connexion échouées, veuillez réessayer dans %minutes% minutes.</target>
            </trans-unit>
        </body>
    </file>
</xliff>
<?xml version="1.0" encoding="utf-8"?>
<xliff xmlns="urn:oasis:names:tc:xliff:document:1.2" version="1.2">
    <file source-language="en" target-language="fa" datatype="plaintext" original="file.ext">
        <body>
            <trans-unit id="1">
                <source>An authentication exception occurred.</source>
                <target>خطایی هنگام احراز هویت رخ داده است.</target>
            </trans-unit>
            <trans-unit id="2">
                <source>Authentication credentials could not be found.</source>
                <target>شرایط احراز هویت یافت نشد.</target>
            </trans-unit>
            <trans-unit id="3">
                <source>Authentication request could not be processed due to a system problem.</source>
                <target>درخواست احراز هویت به دلیل  وجود مشکل در سیستم قابل پردازش نمی باشد.</target>
            </trans-unit>
            <trans-unit id="4">
                <source>Invalid credentials.</source>
                <target>احراز هویت نامعتبر می باشد.</target>
            </trans-unit>
            <trans-unit id="5">
                <source>Cookie has already been used by someone else.</source>
                <target>Cookie قبلا توسط شخص دیگری استفاده گردیده است.</target>
            </trans-unit>
            <trans-unit id="6">
                <source>Not privileged to request the resource.</source>
                <target>دسترسی لازم برای درخواست از این منبع را دارا نمی باشید.</target>
            </trans-unit>
            <trans-unit id="7">
                <source>Invalid CSRF token.</source>
                <target>توکن CSRF معتبر نمی باشد.</target>
            </trans-unit>
            <trans-unit id="9">
                <source>No authentication provider found to support the authentication token.</source>
                <target>هیچ ارائه دهنده احراز هویتی برای پشتیبانی از توکن احراز هویت پیدا نشد.</target>
            </trans-unit>
            <trans-unit id="10">
                <source>No session available, it either timed out or cookies are not enabled.</source>
                <target>هیچ جلسه‌ای در دسترس نمی باشد. این میتواند به دلیل پایان یافتن زمان و یا فعال نبودن کوکی ها باشد.</target>
            </trans-unit>
            <trans-unit id="11">
                <source>No token could be found.</source>
                <target>هیچ توکنی پیدا نشد.</target>
            </trans-unit>
            <trans-unit id="12">
                <source>Username could not be found.</source>
                <target>نام ‌کاربری پیدا نشد.</target>
            </trans-unit>
            <trans-unit id="13">
                <source>Account has expired.</source>
                <target>حساب کاربری منقضی گردیده است.</target>
            </trans-unit>
            <trans-unit id="14">
                <source>Credentials have expired.</source>
                <target>مجوزهای احراز هویت منقضی گردیده‌اند.</target>
            </trans-unit>
            <trans-unit id="15">
                <source>Account is disabled.</source>
                <target>حساب کاربری غیرفعال می باشد.</target>
            </trans-unit>
            <trans-unit id="16">
                <source>Account is locked.</source>
                <target>حساب کاربری قفل گردیده است.</target>
            </trans-unit>
            <trans-unit id="17">
                <source>Too many failed login attempts, please try again later.</source>
                <target>تلاش‌های ناموفق زیادی برای ورود صورت گرفته است، لطفاً بعداً دوباره امتحان کنید.</target>
            </trans-unit>
            <trans-unit id="18">
                <source>Invalid or expired login link.</source>
                <target>لینک ورود نامعتبر یا تاریخ‌گذشته است.</target>
            </trans-unit>
            <trans-unit id="19">
                <source>Too many failed login attempts, please try again in %minutes% minute.</source>
                <target>تلاش‌های ناموفق زیادی برای ورود صورت گرفته است، لطفاً %minutes% دقیقه دیگر دوباره امتحان کنید.</target>
            </trans-unit>
            <trans-unit id="20">
                <source>Too many failed login attempts, please try again in %minutes% minutes.</source>
                <target>تعداد دفعات تلاش برای ورود بیش از حد زیاد است، لطفا پس از %minutes% دقیقه دوباره تلاش کنید.</target>
            </trans-unit>
        </body>
    </file>
</xliff>
<?xml version="1.0" encoding="utf-8"?>
<xliff xmlns="urn:oasis:names:tc:xliff:document:1.2" version="1.2">
    <file source-language="en" target-language="pl" datatype="plaintext" original="file.ext">
        <body>
            <trans-unit id="1">
                <source>An authentication exception occurred.</source>
                <target>Wystąpił błąd uwierzytelniania.</target>
            </trans-unit>
            <trans-unit id="2">
                <source>Authentication credentials could not be found.</source>
                <target>Dane uwierzytelniania nie zostały znalezione.</target>
            </trans-unit>
            <trans-unit id="3">
                <source>Authentication request could not be processed due to a system problem.</source>
                <target>Żądanie uwierzytelniania nie mogło zostać pomyślnie zakończone z powodu problemu z systemem.</target>
            </trans-unit>
            <trans-unit id="4">
                <source>Invalid credentials.</source>
                <target>Nieprawidłowe dane.</target>
            </trans-unit>
            <trans-unit id="5">
                <source>Cookie has already been used by someone else.</source>
                <target>To ciasteczko jest używane przez kogoś innego.</target>
            </trans-unit>
            <trans-unit id="6">
                <source>Not privileged to request the resource.</source>
                <target>Brak uprawnień dla żądania wskazanego zasobu.</target>
            </trans-unit>
            <trans-unit id="7">
                <source>Invalid CSRF token.</source>
                <target>Nieprawidłowy token CSRF.</target>
            </trans-unit>
            <trans-unit id="9">
                <source>No authentication provider found to support the authentication token.</source>
                <target>Nie znaleziono mechanizmu uwierzytelniania zdolnego do obsługi przesłanego tokenu.</target>
            </trans-unit>
            <trans-unit id="10">
                <source>No session available, it either timed out or cookies are not enabled.</source>
                <target>Brak danych sesji, sesja wygasła lub ciasteczka nie są włączone.</target>
            </trans-unit>
            <trans-unit id="11">
                <source>No token could be found.</source>
                <target>Nie znaleziono tokenu.</target>
            </trans-unit>
            <trans-unit id="12">
                <source>Username could not be found.</source>
                <target>Użytkownik o podanej nazwie nie istnieje.</target>
            </trans-unit>
            <trans-unit id="13">
                <source>Account has expired.</source>
                <target>Konto wygasło.</target>
            </trans-unit>
            <trans-unit id="14">
                <source>Credentials have expired.</source>
                <target>Dane uwierzytelniania wygasły.</target>
            </trans-unit>
            <trans-unit id="15">
                <source>Account is disabled.</source>
                <target>Konto jest wyłączone.</target>
            </trans-unit>
            <trans-unit id="16">
                <source>Account is locked.</source>
                <target>Konto jest zablokowane.</target>
            </trans-unit>
            <trans-unit id="17">
                <source>Too many failed login attempts, please try again later.</source>
                <target>Zbyt dużo nieudanych prób logowania, proszę spróbować ponownie później.</target>
            </trans-unit>
            <trans-unit id="18">
                <source>Invalid or expired login link.</source>
                <target>Nieprawidłowy lub wygasły link logowania.</target>
            </trans-unit>
            <trans-unit id="19">
                <source>Too many failed login attempts, please try again in %minutes% minute.</source>
                <target>Zbyt wiele nieudanych prób logowania, spróbuj ponownie po upływie %minutes% minut.</target>
            </trans-unit>
            <trans-unit id="20">
                <source>Too many failed login attempts, please try again in %minutes% minutes.</source>
                <target>Zbyt wiele nieudanych prób logowania, spróbuj ponownie za %minutes% minutę.|Zbyt wiele nieudanych prób logowania, spróbuj ponownie za %minutes% minuty.|Zbyt wiele nieudanych prób logowania, spróbuj ponownie za %minutes% minut.</target>
            </trans-unit>
        </body>
    </file>
</xliff>
<?xml version="1.0" encoding="utf-8"?>
<xliff xmlns="urn:oasis:names:tc:xliff:document:1.2" version="1.2">
    <file source-language="en" target-language="sv" datatype="plaintext" original="file.ext">
        <body>
            <trans-unit id="1">
                <source>An authentication exception occurred.</source>
                <target>Ett autentiseringsfel har inträffat.</target>
            </trans-unit>
            <trans-unit id="2">
                <source>Authentication credentials could not be found.</source>
                <target>Uppgifterna för autentisering kunde inte hittas.</target>
            </trans-unit>
            <trans-unit id="3">
                <source>Authentication request could not be processed due to a system problem.</source>
                <target>Autentiseringen kunde inte genomföras på grund av systemfel.</target>
            </trans-unit>
            <trans-unit id="4">
                <source>Invalid credentials.</source>
                <target>Felaktiga uppgifter.</target>
            </trans-unit>
            <trans-unit id="5">
                <source>Cookie has already been used by someone else.</source>
                <target>Cookien har redan använts av någon annan.</target>
            </trans-unit>
            <trans-unit id="6">
                <source>Not privileged to request the resource.</source>
                <target>Saknar rättigheter för resursen.</target>
            </trans-unit>
            <trans-unit id="7">
                <source>Invalid CSRF token.</source>
                <target>Ogiltig CSRF-token.</target>
            </trans-unit>
            <trans-unit id="9">
                <source>No authentication provider found to support the authentication token.</source>
                <target>Ingen leverantör för autentisering hittades för angiven autentiseringstoken.</target>
            </trans-unit>
            <trans-unit id="10">
                <source>No session available, it either timed out or cookies are not enabled.</source>
                <target>Ingen session finns tillgänglig, antingen har den förfallit eller är cookies inte aktiverat.</target>
            </trans-unit>
            <trans-unit id="11">
                <source>No token could be found.</source>
                <target>Ingen token kunde hittas.</target>
            </trans-unit>
            <trans-unit id="12">
                <source>Username could not be found.</source>
                <target>Användarnamnet kunde inte hittas.</target>
            </trans-unit>
            <trans-unit id="13">
                <source>Account has expired.</source>
                <target>Kontot har förfallit.</target>
            </trans-unit>
            <trans-unit id="14">
                <source>Credentials have expired.</source>
                <target>Uppgifterna har förfallit.</target>
            </trans-unit>
            <trans-unit id="15">
                <source>Account is disabled.</source>
                <target>Kontot är inaktiverat.</target>
            </trans-unit>
            <trans-unit id="16">
                <source>Account is locked.</source>
                <target>Kontot är låst.</target>
            </trans-unit>
            <trans-unit id="17">
                <source>Too many failed login attempts, please try again later.</source>
                <target>För många misslyckade inloggningsförsök, försök igen senare.</target>
            </trans-unit>
            <trans-unit id="18">
                <source>Invalid or expired login link.</source>
                <target>Ogiltig eller utgången inloggningslänk.</target>
            </trans-unit>
            <trans-unit id="19">
                <source>Too many failed login attempts, please try again in %minutes% minute.</source>
                <target>För många misslyckade inloggningsförsök, försök igen om %minutes% minut.</target>
            </trans-unit>
            <trans-unit id="20">
                <source>Too many failed login attempts, please try again in %minutes% minutes.</source>
                <target>För många misslyckade inloggningsförsök, försök igen om %minutes% minuter.</target>
            </trans-unit>
        </body>
    </file>
</xliff>
<?xml version="1.0" encoding="utf-8"?>
<xliff xmlns="urn:oasis:names:tc:xliff:document:1.2" version="1.2">
    <file source-language="en" target-language="el" datatype="plaintext" original="file.ext">
        <body>
            <trans-unit id="1">
                <source>An authentication exception occurred.</source>
                <target>Συνέβη ένα σφάλμα πιστοποίησης.</target>
            </trans-unit>
            <trans-unit id="2">
                <source>Authentication credentials could not be found.</source>
                <target>Τα στοιχεία πιστοποίησης δε βρέθηκαν.</target>
            </trans-unit>
            <trans-unit id="3">
                <source>Authentication request could not be processed due to a system problem.</source>
                <target>Το αίτημα πιστοποίησης δε μπορεί να επεξεργαστεί λόγω σφάλματος του συστήματος.</target>
            </trans-unit>
            <trans-unit id="4">
                <source>Invalid credentials.</source>
                <target>Λανθασμένα στοιχεία σύνδεσης.</target>
            </trans-unit>
            <trans-unit id="5">
                <source>Cookie has already been used by someone else.</source>
                <target>Το Cookie έχει ήδη χρησιμοποιηθεί από κάποιον άλλο.</target>
            </trans-unit>
            <trans-unit id="6">
                <source>Not privileged to request the resource.</source>
                <target>Δεν είστε εξουσιοδοτημένος για πρόσβαση στο συγκεκριμένο περιεχόμενο.</target>
            </trans-unit>
            <trans-unit id="7">
                <source>Invalid CSRF token.</source>
                <target>Μη έγκυρο CSRF token.</target>
            </trans-unit>
            <trans-unit id="9">
                <source>No authentication provider found to support the authentication token.</source>
                <target>Δε βρέθηκε κάποιος πάροχος πιστοποίησης που να υποστηρίζει το token πιστοποίησης.</target>
            </trans-unit>
            <trans-unit id="10">
                <source>No session available, it either timed out or cookies are not enabled.</source>
                <target>Δεν υπάρχει ενεργή σύνοδος (session), είτε έχει λήξει ή τα cookies δεν είναι ενεργοποιημένα.</target>
            </trans-unit>
            <trans-unit id="11">
                <source>No token could be found.</source>
                <target>Δεν ήταν δυνατόν να βρεθεί κάποιο token.</target>
            </trans-unit>
            <trans-unit id="12">
                <source>Username could not be found.</source>
                <target>Το όνομα χρήστη δε βρέθηκε.</target>
            </trans-unit>
            <trans-unit id="13">
                <source>Account has expired.</source>
                <target>Ο λογαριασμός έχει λήξει.</target>
            </trans-unit>
            <trans-unit id="14">
                <source>Credentials have expired.</source>
                <target>Τα στοιχεία σύνδεσης έχουν λήξει.</target>
            </trans-unit>
            <trans-unit id="15">
                <source>Account is disabled.</source>
                <target>Ο λογαριασμός είναι απενεργοποιημένος.</target>
            </trans-unit>
            <trans-unit id="16">
                <source>Account is locked.</source>
                <target>Ο λογαριασμός είναι κλειδωμένος.</target>
            </trans-unit>
            <trans-unit id="17">
                <source>Too many failed login attempts, please try again later.</source>
                <target>Πολλαπλές αποτυχημένες απόπειρες σύνδεσης, παρακαλούμε ξαναδοκιμάστε αργότερα.</target>
            </trans-unit>
            <trans-unit id="18">
                <source>Invalid or expired login link.</source>
                <target>Μη έγκυρος ή ληγμένος σύνδεσμος σύνδεσης.</target>
            </trans-unit>
            <trans-unit id="19">
                <source>Too many failed login attempts, please try again in %minutes% minute.</source>
                <target>Πολλαπλές αποτυχημένες απόπειρες σύνδεσης, παρακαλούμε ξαναδοκιμάστε σε %minutes% λεπτό.</target>
            </trans-unit>
            <trans-unit id="20">
                <source>Too many failed login attempts, please try again in %minutes% minutes.</source>
                <target>Πολλές αποτυχημένες προσπάθειες σύνδεσης, δοκιμάστε ξανά σε %minutes% λεπτά.</target>
            </trans-unit>
        </body>
    </file>
</xliff>
<?xml version="1.0" encoding="utf-8"?>
<xliff xmlns="urn:oasis:names:tc:xliff:document:1.2" version="1.2">
    <file source-language="en" target-language="sr-Cyrl" datatype="plaintext" original="file.ext">
        <body>
            <trans-unit id="1">
                <source>An authentication exception occurred.</source>
                <target>Изузетак при аутентификацији.</target>
            </trans-unit>
            <trans-unit id="2">
                <source>Authentication credentials could not be found.</source>
                <target>Аутентификациони подаци нису пронађени.</target>
            </trans-unit>
            <trans-unit id="3">
                <source>Authentication request could not be processed due to a system problem.</source>
                <target>Захтев за аутентификацију не може бити обрађен због системских проблема.</target>
            </trans-unit>
            <trans-unit id="4">
                <source>Invalid credentials.</source>
                <target>Невалидни подаци за аутентификацију.</target>
            </trans-unit>
            <trans-unit id="5">
                <source>Cookie has already been used by someone else.</source>
                <target>Колачић је већ искоришћен од стране неког другог.</target>
            </trans-unit>
            <trans-unit id="6">
                <source>Not privileged to request the resource.</source>
                <target>Немате права приступа овом ресурсу.</target>
            </trans-unit>
            <trans-unit id="7">
                <source>Invalid CSRF token.</source>
                <target>Невалидан CSRF токен.</target>
            </trans-unit>
            <trans-unit id="9">
                <source>No authentication provider found to support the authentication token.</source>
                <target>Аутентификациони провајдер за подршку токена није пронађен.</target>
            </trans-unit>
            <trans-unit id="10">
                <source>No session available, it either timed out or cookies are not enabled.</source>
                <target>Сесија није доступна, истекла је или су колачићи искључени.</target>
            </trans-unit>
            <trans-unit id="11">
                <source>No token could be found.</source>
                <target>Токен не може бити пронађен.</target>
            </trans-unit>
            <trans-unit id="12">
                <source>Username could not be found.</source>
                <target>Корисничко име не може бити пронађено.</target>
            </trans-unit>
            <trans-unit id="13">
                <source>Account has expired.</source>
                <target>Налог је истекао.</target>
            </trans-unit>
            <trans-unit id="14">
                <source>Credentials have expired.</source>
                <target>Подаци за аутентификацију су истекли.</target>
            </trans-unit>
            <trans-unit id="15">
                <source>Account is disabled.</source>
                <target>Налог је онемогућен.</target>
            </trans-unit>
            <trans-unit id="16">
                <source>Account is locked.</source>
                <target>Налог је закључан.</target>
            </trans-unit>
            <trans-unit id="17">
                <source>Too many failed login attempts, please try again later.</source>
                <target>Превише неуспешних покушаја пријављивања, молим покушајте поново касније.</target>
            </trans-unit>
            <trans-unit id="18">
                <source>Invalid or expired login link.</source>
                <target>Линк за пријављивање је истекао или је неисправан.</target>
            </trans-unit>
            <trans-unit id="19">
                <source>Too many failed login attempts, please try again in %minutes% minute.</source>
                <target>Превише неуспешних покушаја пријављивања, молим покушајте поново за %minutes% минут.</target>
            </trans-unit>
            <trans-unit id="20">
                <source>Too many failed login attempts, please try again in %minutes% minutes.</source>
                <target>Превише неуспешних покушаја пријављивања, покушајте поново за %minutes% минут.|Превише неуспешних покушаја пријављивања, покушајте поново за %minutes% минута.</target>
            </trans-unit>
        </body>
    </file>
</xliff>
<?xml version="1.0" encoding="utf-8"?>
<xliff xmlns="urn:oasis:names:tc:xliff:document:1.2" version="1.2">
    <file source-language="en" target-language="en" datatype="plaintext" original="file.ext">
        <body>
            <trans-unit id="1">
                <source>An authentication exception occurred.</source>
                <target>An authentication exception occurred.</target>
            </trans-unit>
            <trans-unit id="2">
                <source>Authentication credentials could not be found.</source>
                <target>Authentication credentials could not be found.</target>
            </trans-unit>
            <trans-unit id="3">
                <source>Authentication request could not be processed due to a system problem.</source>
                <target>Authentication request could not be processed due to a system problem.</target>
            </trans-unit>
            <trans-unit id="4">
                <source>Invalid credentials.</source>
                <target>Invalid credentials.</target>
            </trans-unit>
            <trans-unit id="5">
                <source>Cookie has already been used by someone else.</source>
                <target>Cookie has already been used by someone else.</target>
            </trans-unit>
            <trans-unit id="6">
                <source>Not privileged to request the resource.</source>
                <target>Not privileged to request the resource.</target>
            </trans-unit>
            <trans-unit id="7">
                <source>Invalid CSRF token.</source>
                <target>Invalid CSRF token.</target>
            </trans-unit>
            <trans-unit id="9">
                <source>No authentication provider found to support the authentication token.</source>
                <target>No authentication provider found to support the authentication token.</target>
            </trans-unit>
            <trans-unit id="10">
                <source>No session available, it either timed out or cookies are not enabled.</source>
                <target>No session available, it either timed out or cookies are not enabled.</target>
            </trans-unit>
            <trans-unit id="11">
                <source>No token could be found.</source>
                <target>No token could be found.</target>
            </trans-unit>
            <trans-unit id="12">
                <source>Username could not be found.</source>
                <target>Username could not be found.</target>
            </trans-unit>
            <trans-unit id="13">
                <source>Account has expired.</source>
                <target>Account has expired.</target>
            </trans-unit>
            <trans-unit id="14">
                <source>Credentials have expired.</source>
                <target>Credentials have expired.</target>
            </trans-unit>
            <trans-unit id="15">
                <source>Account is disabled.</source>
                <target>Account is disabled.</target>
            </trans-unit>
            <trans-unit id="16">
                <source>Account is locked.</source>
                <target>Account is locked.</target>
            </trans-unit>
            <trans-unit id="17">
                <source>Too many failed login attempts, please try again later.</source>
                <target>Too many failed login attempts, please try again later.</target>
            </trans-unit>
            <trans-unit id="18">
                <source>Invalid or expired login link.</source>
                <target>Invalid or expired login link.</target>
            </trans-unit>
            <trans-unit id="19">
                <source>Too many failed login attempts, please try again in %minutes% minute.</source>
                <target>Too many failed login attempts, please try again in %minutes% minute.</target>
            </trans-unit>
            <trans-unit id="20">
                <source>Too many failed login attempts, please try again in %minutes% minutes.</source>
                <target>Too many failed login attempts, please try again in %minutes% minutes.</target>
            </trans-unit>
        </body>
    </file>
</xliff>
<?xml version="1.0" encoding="utf-8"?>
<xliff xmlns="urn:oasis:names:tc:xliff:document:1.2" version="1.2">
    <file source-language="en" target-language="ja" datatype="plaintext" original="file.ext">
        <body>
            <trans-unit id="1">
                <source>An authentication exception occurred.</source>
                <target>認証エラーが発生しました。</target>
            </trans-unit>
            <trans-unit id="2">
                <source>Authentication credentials could not be found.</source>
                <target>認証資格がありません。</target>
            </trans-unit>
            <trans-unit id="3">
                <source>Authentication request could not be processed due to a system problem.</source>
                <target>システムの問題により認証要求を処理できませんでした。</target>
            </trans-unit>
            <trans-unit id="4">
                <source>Invalid credentials.</source>
                <target>資格が無効です。</target>
            </trans-unit>
            <trans-unit id="5">
                <source>Cookie has already been used by someone else.</source>
                <target>Cookie が別のユーザーで使用されています。</target>
            </trans-unit>
            <trans-unit id="6">
                <source>Not privileged to request the resource.</source>
                <target>リソースをリクエストする権限がありません。</target>
            </trans-unit>
            <trans-unit id="7">
                <source>Invalid CSRF token.</source>
                <target>CSRF トークンが無効です。</target>
            </trans-unit>
            <trans-unit id="9">
                <source>No authentication provider found to support the authentication token.</source>
                <target>認証トークンをサポートする認証プロバイダーが見つかりません。</target>
            </trans-unit>
            <trans-unit id="10">
                <source>No session available, it either timed out or cookies are not enabled.</source>
                <target>利用可能なセッションがありません。タイムアウトしたか、Cookie が無効になっています。</target>
            </trans-unit>
            <trans-unit id="11">
                <source>No token could be found.</source>
                <target>トークンが見つかりません。</target>
            </trans-unit>
            <trans-unit id="12">
                <source>Username could not be found.</source>
                <target>ユーザー名が見つかりません。</target>
            </trans-unit>
            <trans-unit id="13">
                <source>Account has expired.</source>
                <target>アカウントが有効期限切れです。</target>
            </trans-unit>
            <trans-unit id="14">
                <source>Credentials have expired.</source>
                <target>資格が有効期限切れです。</target>
            </trans-unit>
            <trans-unit id="15">
                <source>Account is disabled.</source>
                <target>アカウントが無効です。</target>
            </trans-unit>
            <trans-unit id="16">
                <source>Account is locked.</source>
                <target>アカウントはロックされています。</target>
            </trans-unit>
            <trans-unit id="17">
                <source>Too many failed login attempts, please try again later.</source>
                <target>ログイン試行回数を超えました。しばらくして再度お試しください。</target>
            </trans-unit>
            <trans-unit id="18">
                <source>Invalid or expired login link.</source>
                <target>ログインリンクが有効期限切れ、もしくは無効です。</target>
            </trans-unit>
            <trans-unit id="19">
                <source>Too many failed login attempts, please try again in %minutes% minute.</source>
                <target>ログイン試行回数が多すぎます。%minutes%分後に再度お試しください。</target>
            </trans-unit>
            <trans-unit id="20">
                <source>Too many failed login attempts, please try again in %minutes% minutes.</source>
                <target>ログイン試行回数が多すぎます。%minutes%分後に再度お試しください。</target>
            </trans-unit>
        </body>
    </file>
</xliff>
<?xml version="1.0" encoding="utf-8"?>
<xliff xmlns="urn:oasis:names:tc:xliff:document:1.2" version="1.2">
    <file source-language="en" target-language="pt-BR" datatype="plaintext" original="file.ext">
        <body>
            <trans-unit id="1">
                <source>An authentication exception occurred.</source>
                <target>Uma exceção ocorreu durante a autenticação.</target>
            </trans-unit>
            <trans-unit id="2">
                <source>Authentication credentials could not be found.</source>
                <target>As credenciais de autenticação não foram encontradas.</target>
            </trans-unit>
            <trans-unit id="3">
                <source>Authentication request could not be processed due to a system problem.</source>
                <target>A solicitação de autenticação não pôde ser processada devido a um problema no sistema.</target>
            </trans-unit>
            <trans-unit id="4">
                <source>Invalid credentials.</source>
                <target>Credenciais inválidas.</target>
            </trans-unit>
            <trans-unit id="5">
                <source>Cookie has already been used by someone else.</source>
                <target>Este cookie já foi usado por outra pessoa.</target>
            </trans-unit>
            <trans-unit id="6">
                <source>Not privileged to request the resource.</source>
                <target>Sem privilégio para solicitar o recurso.</target>
            </trans-unit>
            <trans-unit id="7">
                <source>Invalid CSRF token.</source>
                <target>Token CSRF inválido.</target>
            </trans-unit>
            <trans-unit id="9">
                <source>No authentication provider found to support the authentication token.</source>
                <target>Nenhum provedor de autenticação encontrado para suportar o token de autenticação.</target>
            </trans-unit>
            <trans-unit id="10">
                <source>No session available, it either timed out or cookies are not enabled.</source>
                <target>Nenhuma sessão disponível, ela expirou ou os cookies não estão habilitados.</target>
            </trans-unit>
            <trans-unit id="11">
                <source>No token could be found.</source>
                <target>Nenhum token foi encontrado.</target>
            </trans-unit>
            <trans-unit id="12">
                <source>Username could not be found.</source>
                <target>Nome de usuário não encontrado.</target>
            </trans-unit>
            <trans-unit id="13">
                <source>Account has expired.</source>
                <target>A conta está expirada.</target>
            </trans-unit>
            <trans-unit id="14">
                <source>Credentials have expired.</source>
                <target>As credenciais estão expiradas.</target>
            </trans-unit>
            <trans-unit id="15">
                <source>Account is disabled.</source>
                <target>Conta desativada.</target>
            </trans-unit>
            <trans-unit id="16">
                <source>Account is locked.</source>
                <target>A conta está travada.</target>
            </trans-unit>
            <trans-unit id="17">
                <source>Too many failed login attempts, please try again later.</source>
                <target>Muitas tentativas de login malsucedidas, por favor, tente novamente mais tarde.</target>
            </trans-unit>
            <trans-unit id="18">
                <source>Invalid or expired login link.</source>
                <target>Link de login inválido ou expirado.</target>
            </trans-unit>
            <trans-unit id="19">
                <source>Too many failed login attempts, please try again in %minutes% minute.</source>
                <target>Muitas tentativas de login inválidas, por favor, tente novamente em um minuto.</target>
            </trans-unit>
            <trans-unit id="20">
                <source>Too many failed login attempts, please try again in %minutes% minutes.</source>
                <target>Muitas tentativas de login sem sucesso, por favor, tente novamente em %minutes% minutos.</target>
            </trans-unit>
        </body>
    </file>
</xliff>
<?xml version="1.0" encoding="utf-8"?>
<xliff xmlns="urn:oasis:names:tc:xliff:document:1.2" version="1.2">
    <file source-language="en" target-language="nb" datatype="plaintext" original="file.ext">
        <body>
            <trans-unit id="1">
                <source>An authentication exception occurred.</source>
                <target>En autentiseringsfeil har skjedd.</target>
            </trans-unit>
            <trans-unit id="2">
                <source>Authentication credentials could not be found.</source>
                <target>Påloggingsinformasjonen kunne ikke bli funnet.</target>
            </trans-unit>
            <trans-unit id="3">
                <source>Authentication request could not be processed due to a system problem.</source>
                <target>Autentiserings forespørselen kunne ikke bli prosessert grunnet en system feil.</target>
            </trans-unit>
            <trans-unit id="4">
                <source>Invalid credentials.</source>
                <target>Ugyldig påloggingsinformasjon.</target>
            </trans-unit>
            <trans-unit id="5">
                <source>Cookie has already been used by someone else.</source>
                <target>Cookie har allerede blitt brukt av noen andre.</target>
            </trans-unit>
            <trans-unit id="6">
                <source>Not privileged to request the resource.</source>
                <target>Ingen tilgang til å be om gitt ressurs.</target>
            </trans-unit>
            <trans-unit id="7">
                <source>Invalid CSRF token.</source>
                <target>Ugyldig CSRF token.</target>
            </trans-unit>
            <trans-unit id="9">
                <source>No authentication provider found to support the authentication token.</source>
                <target>Ingen autentiserings tilbyder funnet som støtter gitt autentiserings token.</target>
            </trans-unit>
            <trans-unit id="10">
                <source>No session available, it either timed out or cookies are not enabled.</source>
                <target>Ingen sesjon tilgjengelig, sesjonen er enten utløpt eller cookies ikke skrudd på.</target>
            </trans-unit>
            <trans-unit id="11">
                <source>No token could be found.</source>
                <target>Ingen token kunne bli funnet.</target>
            </trans-unit>
            <trans-unit id="12">
                <source>Username could not be found.</source>
                <target>Brukernavn kunne ikke bli funnet.</target>
            </trans-unit>
            <trans-unit id="13">
                <source>Account has expired.</source>
                <target>Brukerkonto har utgått.</target>
            </trans-unit>
            <trans-unit id="14">
                <source>Credentials have expired.</source>
                <target>Påloggingsinformasjon har utløpt.</target>
            </trans-unit>
            <trans-unit id="15">
                <source>Account is disabled.</source>
                <target>Brukerkonto er deaktivert.</target>
            </trans-unit>
            <trans-unit id="16">
                <source>Account is locked.</source>
                <target>Brukerkonto er sperret.</target>
            </trans-unit>
            <trans-unit id="17">
                <source>Too many failed login attempts, please try again later.</source>
                <target>For mange mislykkede påloggingsforsøk. Prøv igjen senere.</target>
            </trans-unit>
            <trans-unit id="18">
                <source>Invalid or expired login link.</source>
                <target>Ugyldig eller utløpt påloggingskobling.</target>
            </trans-unit>
            <trans-unit id="19">
                <source>Too many failed login attempts, please try again in %minutes% minute.</source>
                <target>For mange mislykkede påloggingsforsøk, prøv igjen om %minutes% minutt.</target>
            </trans-unit>
            <trans-unit id="20">
                <source>Too many failed login attempts, please try again in %minutes% minutes.</source>
                <target>For mange mislykkede påloggingsforsøk, prøv igjen om %minutes% minutter.</target>
            </trans-unit>
        </body>
    </file>
</xliff>
<?xml version="1.0" encoding="utf-8"?>
<xliff xmlns="urn:oasis:names:tc:xliff:document:1.2" version="1.2">
    <file source-language="en" target-language="vi" datatype="plaintext" original="file.ext">
        <body>
            <trans-unit id="1">
                <source>An authentication exception occurred.</source>
                <target>Có lỗi trong quá trình xác thực.</target>
            </trans-unit>
            <trans-unit id="2">
                <source>Authentication credentials could not be found.</source>
                <target>Thông tin dùng để xác thực không tìm thấy.</target>
            </trans-unit>
            <trans-unit id="3">
                <source>Authentication request could not be processed due to a system problem.</source>
                <target>Yêu cầu xác thực không thể thực hiện do lỗi của hệ thống.</target>
            </trans-unit>
            <trans-unit id="4">
                <source>Invalid credentials.</source>
                <target>Thông tin dùng để xác thực không hợp lệ.</target>
            </trans-unit>
            <trans-unit id="5">
                <source>Cookie has already been used by someone else.</source>
                <target>Cookie đã được dùng bởi người dùng khác.</target>
            </trans-unit>
            <trans-unit id="6">
                <source>Not privileged to request the resource.</source>
                <target>Không được phép yêu cầu tài nguyên.</target>
            </trans-unit>
            <trans-unit id="7">
                <source>Invalid CSRF token.</source>
                <target>Mã CSRF không hợp lệ.</target>
            </trans-unit>
            <trans-unit id="9">
                <source>No authentication provider found to support the authentication token.</source>
                <target>Không tìm thấy nhà cung cấp dịch vụ xác thực nào cho mã xác thực mà bạn sử dụng.</target>
            </trans-unit>
            <trans-unit id="10">
                <source>No session available, it either timed out or cookies are not enabled.</source>
                <target>Không tìm thấy phiên làm việc. Phiên làm việc hoặc cookie có thể bị tắt.</target>
            </trans-unit>
            <trans-unit id="11">
                <source>No token could be found.</source>
                <target>Không tìm thấy mã token.</target>
            </trans-unit>
            <trans-unit id="12">
                <source>Username could not be found.</source>
                <target>Không tìm thấy tên người dùng.</target>
            </trans-unit>
            <trans-unit id="13">
                <source>Account has expired.</source>
                <target>Tài khoản đã hết hạn.</target>
            </trans-unit>
            <trans-unit id="14">
                <source>Credentials have expired.</source>
                <target>Thông tin xác thực đã hết hạn.</target>
            </trans-unit>
            <trans-unit id="15">
                <source>Account is disabled.</source>
                <target>Tài khoản bị tạm ngừng.</target>
            </trans-unit>
            <trans-unit id="16">
                <source>Account is locked.</source>
                <target>Tài khoản bị khóa.</target>
            </trans-unit>
            <trans-unit id="17">
                <source>Too many failed login attempts, please try again later.</source>
                <target>Đăng nhập sai quá nhiều lần, vui lòng thử lại lần nữa.</target>
            </trans-unit>
            <trans-unit id="18">
                <source>Invalid or expired login link.</source>
                <target>Liên kết đăng nhập không hợp lệ hoặc quá hạn.</target>
            </trans-unit>
            <trans-unit id="19">
                <source>Too many failed login attempts, please try again in %minutes% minute.</source>
                <target>Quá nhiều lần thử đăng nhập không thành công, vui lòng thử lại sau %minutes% phút.</target>
            </trans-unit>
            <trans-unit id="20">
                <source>Too many failed login attempts, please try again in %minutes% minutes.</source>
                <target state="needs-review-translation">Quá nhiều lần đăng nhập không thành công, vui lòng thử lại sau %minutes% phút.|Quá nhiều lần đăng nhập không thành công, vui lòng thử lại sau %minutes% phút.</target>
            </trans-unit>
        </body>
    </file>
</xliff>
<?xml version="1.0" encoding="utf-8"?>
<xliff xmlns="urn:oasis:names:tc:xliff:document:1.2" version="1.2">
    <file source-language="en" target-language="ur" datatype="plaintext" original="file.ext">
        <body>
            <trans-unit id="1">
                <source>An authentication exception occurred.</source>
                <target>ایک تصدیقي خرابی پیش آگئی ۓ</target>
            </trans-unit>
            <trans-unit id="2">
                <source>Authentication credentials could not be found.</source>
                <target>درج کردھ ریکارڈ نہیں مل سکا</target>
            </trans-unit>
            <trans-unit id="3">
                <source>Authentication request could not be processed due to a system problem.</source>
                <target>سسٹم کی خرابی کی وجہ سے تصدیق کی درخواست پر کارروائی نہیں ہو سکی</target>
            </trans-unit>
            <trans-unit id="4">
                <source>Invalid credentials.</source>
                <target>غلط ڈیٹا</target>
            </trans-unit>
            <trans-unit id="5">
                <source>Cookie has already been used by someone else.</source>
                <target>کوکی پہلے ہی کسی اور کے ذریعہ استعمال ہو چکی ہے</target>
            </trans-unit>
            <trans-unit id="6">
                <source>Not privileged to request the resource.</source>
                <target>وسائل کی درخواست کرنے کا اختیار نہیں ہے</target>
            </trans-unit>
            <trans-unit id="7">
                <source>Invalid CSRF token.</source>
                <target>ٹوکن غلط ہے CSRF</target>
            </trans-unit>
            <trans-unit id="9">
                <source>No authentication provider found to support the authentication token.</source>
                <target>تصدیقی ٹوکن کو سپورٹ کرنے کے لیے کوئی تصدیقی کنندہ نہیں ملا</target>
            </trans-unit>
            <trans-unit id="10">
                <source>No session available, it either timed out or cookies are not enabled.</source>
                <target>کوئی سیشن دستیاب نہیں ہے، یا تو اس کا وقت ختم ہو گیا ہے یا کوکیز فعال نہیں ہیں</target>
            </trans-unit>
            <trans-unit id="11">
                <source>No token could be found.</source>
                <target>کوئی ٹوکن نہیں مل سکا</target>
            </trans-unit>
            <trans-unit id="12">
                <source>Username could not be found.</source>
                <target>يوذر نہیں مل سکا</target>
            </trans-unit>
            <trans-unit id="13">
                <source>Account has expired.</source>
                <target>اکاؤنٹ کی میعاد ختم ہو گئی ہے</target>
            </trans-unit>
            <trans-unit id="14">
                <source>Credentials have expired.</source>
                <target>اسناد کی میعاد ختم ہو چکی ہے</target>
            </trans-unit>
            <trans-unit id="15">
                <source>Account is disabled.</source>
                <target>اکاؤنٹ بند کر دیا گیا ہے</target>
            </trans-unit>
            <trans-unit id="16">
                <source>Account is locked.</source>
                <target>اکاؤنٹ لاک ہے</target>
            </trans-unit>
            <trans-unit id="17">
                <source>Too many failed login attempts, please try again later.</source>
                <target>لاگ ان کی بہت زیادہ ناکام کوششیں ہو چکی ہیں، براۓ کرم بعد میں دوبارہ کوشش کریں</target>
            </trans-unit>
            <trans-unit id="18">
                <source>Invalid or expired login link.</source>
                <target>غلط یا ختم شدھ لاگ ان لنک</target>
            </trans-unit>
            <trans-unit id="19">
                <source>Too many failed login attempts, please try again in %minutes% minute.</source>
                <target>منٹ باد %minutes% لاگ ان کی بہت زیادہ ناکام کوششیں ہو چکی ہیں، براۓ کرم دوبارھ کوشيش کريں </target>
            </trans-unit>
            <trans-unit id="20">
                <source>Too many failed login attempts, please try again in %minutes% minutes.</source>
                <target state="needs-review-translation">بہت زیادہ ناکام لاگ ان کوششیں، براہ کرم %minutes% منٹ میں دوبارہ کوشش کریں۔</target>
            </trans-unit>
        </body>
    </file>
</xliff>
<?xml version="1.0" encoding="utf-8"?>
<xliff xmlns="urn:oasis:names:tc:xliff:document:1.2" version="1.2">
    <file source-language="en" target-language="nn" datatype="plaintext" original="file.ext">
        <body>
            <trans-unit id="1">
                <source>An authentication exception occurred.</source>
                <target>Innlogginga har feila.</target>
            </trans-unit>
            <trans-unit id="2">
                <source>Authentication credentials could not be found.</source>
                <target>Innloggingsinformasjonen vart ikkje funnen.</target>
            </trans-unit>
            <trans-unit id="3">
                <source>Authentication request could not be processed due to a system problem.</source>
                <target>Innlogginga vart ikkje fullført på grunn av ein systemfeil.</target>
            </trans-unit>
            <trans-unit id="4">
                <source>Invalid credentials.</source>
                <target>Ugyldig innloggingsinformasjon.</target>
            </trans-unit>
            <trans-unit id="5">
                <source>Cookie has already been used by someone else.</source>
                <target>Informasjonskapselen er allereie brukt av ein annan brukar.</target>
            </trans-unit>
            <trans-unit id="6">
                <source>Not privileged to request the resource.</source>
                <target>Du har ikkje åtgang til å be om denne ressursen.</target>
            </trans-unit>
            <trans-unit id="7">
                <source>Invalid CSRF token.</source>
                <target>Ugyldig CSRF-teikn.</target>
            </trans-unit>
            <trans-unit id="9">
                <source>No authentication provider found to support the authentication token.</source>
                <target>Fann ingen innloggingstilbydar som støttar dette innloggingsteiknet.</target>
            </trans-unit>
            <trans-unit id="10">
                <source>No session available, it either timed out or cookies are not enabled.</source>
                <target>Ingen sesjon tilgjengeleg. Sesjonen er anten ikkje lenger gyldig, eller informasjonskapslar er ikkje skrudd på i nettlesaren.</target>
            </trans-unit>
            <trans-unit id="11">
                <source>No token could be found.</source>
                <target>Fann ingen innloggingsteikn.</target>
            </trans-unit>
            <trans-unit id="12">
                <source>Username could not be found.</source>
                <target>Fann ikkje brukarnamnet.</target>
            </trans-unit>
            <trans-unit id="13">
                <source>Account has expired.</source>
                <target>Brukarkontoen er utgjengen.</target>
            </trans-unit>
            <trans-unit id="14">
                <source>Credentials have expired.</source>
                <target>Innloggingsinformasjonen er utgjengen.</target>
            </trans-unit>
            <trans-unit id="15">
                <source>Account is disabled.</source>
                <target>Brukarkontoen er sperra.</target>
            </trans-unit>
            <trans-unit id="16">
                <source>Account is locked.</source>
                <target>Brukarkontoen er sperra.</target>
            </trans-unit>
            <trans-unit id="17">
                <source>Too many failed login attempts, please try again later.</source>
                <target>For mange innloggingsforsøk har feila, prøv igjen seinare.</target>
            </trans-unit>
            <trans-unit id="18">
                <source>Invalid or expired login link.</source>
                <target>Innloggingslenka er ugyldig eller utgjengen.</target>
            </trans-unit>
            <trans-unit id="19">
                <source>Too many failed login attempts, please try again in %minutes% minute.</source>
                <target>For mange mislykkede påloggingsforsøk, prøv igjen om %minutes% minutt.</target>
            </trans-unit>
            <trans-unit id="20">
                <source>Too many failed login attempts, please try again in %minutes% minutes.</source>
                <target state="needs-review-translation">For mange mislukka innloggingsforsøk, prøv igjen om %minutes% minutt.</target>
            </trans-unit>
        </body>
    </file>
</xliff>
<?xml version="1.0" encoding="utf-8"?>
<xliff xmlns="urn:oasis:names:tc:xliff:document:1.2" version="1.2">
    <file source-language="en" target-language="nl" datatype="plaintext" original="file.ext">
        <body>
            <trans-unit id="1">
                <source>An authentication exception occurred.</source>
                <target>Er heeft zich een authenticatieprobleem voorgedaan.</target>
            </trans-unit>
            <trans-unit id="2">
                <source>Authentication credentials could not be found.</source>
                <target>Authenticatiegegevens konden niet worden gevonden.</target>
            </trans-unit>
            <trans-unit id="3">
                <source>Authentication request could not be processed due to a system problem.</source>
                <target>Authenticatieaanvraag kon niet worden verwerkt door een technisch probleem.</target>
            </trans-unit>
            <trans-unit id="4">
                <source>Invalid credentials.</source>
                <target>Ongeldige inloggegevens.</target>
            </trans-unit>
            <trans-unit id="5">
                <source>Cookie has already been used by someone else.</source>
                <target>Cookie is al door een ander persoon gebruikt.</target>
            </trans-unit>
            <trans-unit id="6">
                <source>Not privileged to request the resource.</source>
                <target>Onvoldoende rechten om de aanvraag te verwerken.</target>
            </trans-unit>
            <trans-unit id="7">
                <source>Invalid CSRF token.</source>
                <target>CSRF-code is ongeldig.</target>
            </trans-unit>
            <trans-unit id="9">
                <source>No authentication provider found to support the authentication token.</source>
                <target>Geen authenticatieprovider gevonden die de authenticatietoken ondersteunt.</target>
            </trans-unit>
            <trans-unit id="10">
                <source>No session available, it either timed out or cookies are not enabled.</source>
                <target>Geen sessie beschikbaar, mogelijk is deze verlopen of cookies zijn uitgeschakeld.</target>
            </trans-unit>
            <trans-unit id="11">
                <source>No token could be found.</source>
                <target>Er kon geen authenticatietoken worden gevonden.</target>
            </trans-unit>
            <trans-unit id="12">
                <source>Username could not be found.</source>
                <target>Gebruikersnaam kon niet worden gevonden.</target>
            </trans-unit>
            <trans-unit id="13">
                <source>Account has expired.</source>
                <target>Account is verlopen.</target>
            </trans-unit>
            <trans-unit id="14">
                <source>Credentials have expired.</source>
                <target>Authenticatiegegevens zijn verlopen.</target>
            </trans-unit>
            <trans-unit id="15">
                <source>Account is disabled.</source>
                <target>Account is gedeactiveerd.</target>
            </trans-unit>
            <trans-unit id="16">
                <source>Account is locked.</source>
                <target>Account is geblokkeerd.</target>
            </trans-unit>
            <trans-unit id="17">
                <source>Too many failed login attempts, please try again later.</source>
                <target>Te veel onjuiste inlogpogingen, probeer het later nogmaals.</target>
            </trans-unit>
            <trans-unit id="18">
                <source>Invalid or expired login link.</source>
                <target>Ongeldige of verlopen inloglink.</target>
            </trans-unit>
            <trans-unit id="19">
                <source>Too many failed login attempts, please try again in %minutes% minute.</source>
                <target>Te veel onjuiste inlogpogingen, probeer het opnieuw over %minutes% minuut.</target>
            </trans-unit>
            <trans-unit id="20">
                <source>Too many failed login attempts, please try again in %minutes% minutes.</source>
                <target>Te veel onjuiste inlogpogingen, probeer het opnieuw over %minutes% minuten.</target>
            </trans-unit>
        </body>
    </file>
</xliff>
<?xml version="1.0" encoding="utf-8"?>
<xliff xmlns="urn:oasis:names:tc:xliff:document:1.2" version="1.2">
    <file source-language="en" target-language="cy" datatype="plaintext" original="file.ext">
        <body>
            <trans-unit id="1">
                <source>An authentication exception occurred.</source>
                <target state="needs-review-translation">Digwyddodd eithriad dilysu.</target>
            </trans-unit>
            <trans-unit id="2">
                <source>Authentication credentials could not be found.</source>
                <target state="needs-review-translation">Ni ellid dod o hyd i ddogfennau dilysu.</target>
            </trans-unit>
            <trans-unit id="3">
                <source>Authentication request could not be processed due to a system problem.</source>
                <target state="needs-review-translation">Ni ellid prosesu cais dilysu oherwydd problem gyda'r system.</target>
            </trans-unit>
            <trans-unit id="4">
                <source>Invalid credentials.</source>
                <target state="needs-review-translation">Dogfennau annilys.</target>
            </trans-unit>
            <trans-unit id="5">
                <source>Cookie has already been used by someone else.</source>
                <target state="needs-review-translation">Mae rhywun arall eisoes wedi defnyddio'r cwcis.</target>
            </trans-unit>
            <trans-unit id="6">
                <source>Not privileged to request the resource.</source>
                <target state="needs-review-translation">Heb y fraint i ofyn am yr adnodd.</target>
            </trans-unit>
            <trans-unit id="7">
                <source>Invalid CSRF token.</source>
                <target state="needs-review-translation">Tocyn CSRF annilys.</target>
            </trans-unit>
            <trans-unit id="9">
                <source>No authentication provider found to support the authentication token.</source>
                <target state="needs-review-translation">Heb ddod o hyd i ddarparwr dilysu i gefnogi'r tocyn dilysu.</target>
            </trans-unit>
            <trans-unit id="10">
                <source>No session available, it either timed out or cookies are not enabled.</source>
                <target state="needs-review-translation">Dim sesiwn ar gael, naill ai mae wedi dod i ben neu nid yw cwcis wedi'u galluogi.</target>
            </trans-unit>
            <trans-unit id="11">
                <source>No token could be found.</source>
                <target state="needs-review-translation">Heb ddod o hyd i docyn.</target>
            </trans-unit>
            <trans-unit id="12">
                <source>Username could not be found.</source>
                <target state="needs-review-translation">Heb ddod o hyd i enw defnyddiwr.</target>
            </trans-unit>
            <trans-unit id="13">
                <source>Account has expired.</source>
                <target state="needs-review-translation">Mae'r cyfrif wedi dod i ben.</target>
            </trans-unit>
            <trans-unit id="14">
                <source>Credentials have expired.</source>
                <target state="needs-review-translation">Mae'r dogfennau wedi dod i ben.</target>
            </trans-unit>
            <trans-unit id="15">
                <source>Account is disabled.</source>
                <target state="needs-review-translation">Mae'r cyfrif wedi'i analluogi.</target>
            </trans-unit>
            <trans-unit id="16">
                <source>Account is locked.</source>
                <target state="needs-review-translation">Mae'r cyfrif wedi'i gloi.</target>
            </trans-unit>
            <trans-unit id="17">
                <source>Too many failed login attempts, please try again later.</source>
                <target state="needs-review-translation">Gormod o ymdrechion mewngofnodi wedi methu, ceisiwch eto'n hwyrach.</target>
            </trans-unit>
            <trans-unit id="18">
                <source>Invalid or expired login link.</source>
                <target state="needs-review-translation">Dolen mewngofnodi annilys neu wedi dod i ben.</target>
            </trans-unit>
            <trans-unit id="19">
                <source>Too many failed login attempts, please try again in %minutes% minute.</source>
                <target state="needs-review-translation">Gormod o ymdrechion mewngofnodi wedi methu, ceisiwch eto ymhen %minutes% munud.</target>
            </trans-unit>
            <trans-unit id="20">
                <source>Too many failed login attempts, please try again in %minutes% minutes.</source>
                <target state="needs-review-translation">Gormod o ymdrechion mewngofnodi wedi methu, rhowch gynnig arall arni mewn %minutes% munud.|Gormod o ymdrechion mewngofnodi wedi methu, rhowch gynnig arall arni mewn %minutes% munud.</target>
            </trans-unit>
        </body>
    </file>
</xliff>
<?xml version="1.0" encoding="utf-8"?>
<xliff xmlns="urn:oasis:names:tc:xliff:document:1.2" version="1.2">
    <file source-language="en" target-language="af" datatype="plaintext" original="file.ext">
        <body>
            <trans-unit id="1">
                <source>An authentication exception occurred.</source>
                <target>'n Verifikasie probleem het voorgekom.</target>
            </trans-unit>
            <trans-unit id="2">
                <source>Authentication credentials could not be found.</source>
                <target>Verifikasiebewyse kon nie gevind word nie.</target>
            </trans-unit>
            <trans-unit id="3">
                <source>Authentication request could not be processed due to a system problem.</source>
                <target>Verifikasieversoek kon weens 'n stelselprobleem nie verwerk word nie.</target>
            </trans-unit>
            <trans-unit id="4">
                <source>Invalid credentials.</source>
                <target>Ongedige verifikasiebewyse.</target>
            </trans-unit>
            <trans-unit id="5">
                <source>Cookie has already been used by someone else.</source>
                <target>Die koekie is alreeds deur iemand anders gebruik.</target>
            </trans-unit>
            <trans-unit id="6">
                <source>Not privileged to request the resource.</source>
                <target>Nie bevoorreg om die hulpbron aan te vra nie.</target>
            </trans-unit>
            <trans-unit id="7">
                <source>Invalid CSRF token.</source>
                <target>Ongeldige CSRF-teken.</target>
            </trans-unit>
            <trans-unit id="9">
                <source>No authentication provider found to support the authentication token.</source>
                <target>Geen verifikasieverskaffer is gevind wat die verifikasietoken kan ondersteun nie.</target>
            </trans-unit>
            <trans-unit id="10">
                <source>No session available, it either timed out or cookies are not enabled.</source>
                <target>Geen sessie is beskikbaar, die het verval of koekies is nie geaktiveer nie.</target>
            </trans-unit>
            <trans-unit id="11">
                <source>No token could be found.</source>
                <target>Geen teken kon gevind word nie.</target>
            </trans-unit>
            <trans-unit id="12">
                <source>Username could not be found.</source>
                <target>Gebruikersnaam kon nie gevind word nie.</target>
            </trans-unit>
            <trans-unit id="13">
                <source>Account has expired.</source>
                <target>Rekening het verval.</target>
            </trans-unit>
            <trans-unit id="14">
                <source>Credentials have expired.</source>
                <target>Verifikasiebewyse het verval.</target>
            </trans-unit>
            <trans-unit id="15">
                <source>Account is disabled.</source>
                <target>Rekening is deaktiveer.</target>
            </trans-unit>
            <trans-unit id="16">
                <source>Account is locked.</source>
                <target>Rekening is gesluit.</target>
            </trans-unit>
            <trans-unit id="17">
                <source>Too many failed login attempts, please try again later.</source>
                <target>Te veel mislukte aanmeldpogings, probeer asseblief later weer.</target>
            </trans-unit>
            <trans-unit id="18">
                <source>Invalid or expired login link.</source>
                <target>Ongeldige of vervalde aanmeldskakel.</target>
            </trans-unit>
            <trans-unit id="19">
                <source>Too many failed login attempts, please try again in %minutes% minute.</source>
                <target>Te veel mislukte aanmeldpogings, probeer asseblief weer oor %minutes% minute.</target>
            </trans-unit>
            <trans-unit id="20">
                <source>Too many failed login attempts, please try again in %minutes% minutes.</source>
                <target>Te veel mislukte aanmeldpogings, probeer asseblief weer oor %minutes% minute.</target>
            </trans-unit>
        </body>
    </file>
</xliff>
<?xml version="1.0" encoding="utf-8"?>
<xliff xmlns="urn:oasis:names:tc:xliff:document:1.2" version="1.2">
    <file source-language="en" target-language="lv" datatype="plaintext" original="file.ext">
        <body>
            <trans-unit id="1">
                <source>An authentication exception occurred.</source>
                <target>Radās autentifikācijas kļūda.</target>
            </trans-unit>
            <trans-unit id="2">
                <source>Authentication credentials could not be found.</source>
                <target>Autentifikācijas dati nav atrasti.</target>
            </trans-unit>
            <trans-unit id="3">
                <source>Authentication request could not be processed due to a system problem.</source>
                <target>Autentifikācijas pieprasījums nevar tikt apstrādāts sistēmas problēmas dēļ.</target>
            </trans-unit>
            <trans-unit id="4">
                <source>Invalid credentials.</source>
                <target>Nederīgi autentifikācijas dati.</target>
            </trans-unit>
            <trans-unit id="5">
                <source>Cookie has already been used by someone else.</source>
                <target>Kāds cits jau izmantoja sīkdatni.</target>
            </trans-unit>
            <trans-unit id="6">
                <source>Not privileged to request the resource.</source>
                <target>Nav tiesību šī resursa izsaukšanai.</target>
            </trans-unit>
            <trans-unit id="7">
                <source>Invalid CSRF token.</source>
                <target>Nederīgs CSRF talons.</target>
            </trans-unit>
            <trans-unit id="9">
                <source>No authentication provider found to support the authentication token.</source>
                <target>Nav atrasts, autentifikācijas talonu atbalstošs, autentifikācijas sniedzējs.</target>
            </trans-unit>
            <trans-unit id="10">
                <source>No session available, it either timed out or cookies are not enabled.</source>
                <target>Sesija nav pieejama - vai nu tā beidzās, vai nu sīkdatnes nav iespējotas.</target>
            </trans-unit>
            <trans-unit id="11">
                <source>No token could be found.</source>
                <target>Nevar atrast nevienu talonu.</target>
            </trans-unit>
            <trans-unit id="12">
                <source>Username could not be found.</source>
                <target>Nevar atrast lietotājvārdu.</target>
            </trans-unit>
            <trans-unit id="13">
                <source>Account has expired.</source>
                <target>Konta derīguma termiņš ir beidzies.</target>
            </trans-unit>
            <trans-unit id="14">
                <source>Credentials have expired.</source>
                <target>Autentifikācijas datu derīguma termiņš ir beidzies.</target>
            </trans-unit>
            <trans-unit id="15">
                <source>Account is disabled.</source>
                <target>Konts ir atspējots.</target>
            </trans-unit>
            <trans-unit id="16">
                <source>Account is locked.</source>
                <target>Konts ir slēgts.</target>
            </trans-unit>
            <trans-unit id="17">
                <source>Too many failed login attempts, please try again later.</source>
                <target>Pārāk daudz atteiktu autentifikācijas mēģinājumu, lūdzu, mēģiniet vēlreiz vēlāk.</target>
            </trans-unit>
            <trans-unit id="18">
                <source>Invalid or expired login link.</source>
                <target>Autentifikācijas saite ir nederīga vai arī tai ir beidzies derīguma termiņš.</target>
            </trans-unit>
            <trans-unit id="19">
                <source>Too many failed login attempts, please try again in %minutes% minute.</source>
                <target>Pārāk daudz nesekmīgu autentifikācijas mēģinājumu, lūdzu mēģiniet vēlreiz pēc %minutes% minūtes.</target>
            </trans-unit>
            <trans-unit id="20">
                <source>Too many failed login attempts, please try again in %minutes% minutes.</source>
                <target>Pārāk daudz neveiksmīgu autentifikācijas mēģinājumu, lūdzu, mēģiniet vēlreiz pēc %minutes% minūtēm.</target>
            </trans-unit>
        </body>
    </file>
</xliff>
<?xml version="1.0" encoding="utf-8"?>
<xliff xmlns="urn:oasis:names:tc:xliff:document:1.2" version="1.2">
    <file source-language="en" target-language="ar" datatype="plaintext" original="file.ext">
        <body>
            <trans-unit id="1">
                <source>An authentication exception occurred.</source>
                <target>حدث خطأ اثناء الدخول.</target>
            </trans-unit>
            <trans-unit id="2">
                <source>Authentication credentials could not be found.</source>
                <target>لم استطع العثور على معلومات الدخول.</target>
            </trans-unit>
            <trans-unit id="3">
                <source>Authentication request could not be processed due to a system problem.</source>
                <target>لم يكتمل طلب الدخول نتيجه عطل فى النظام.</target>
            </trans-unit>
            <trans-unit id="4">
                <source>Invalid credentials.</source>
                <target>معلومات الدخول خاطئة.</target>
            </trans-unit>
            <trans-unit id="5">
                <source>Cookie has already been used by someone else.</source>
                <target>ملفات تعريف الارتباط(cookies) تم استخدامها من قبل شخص اخر.</target>
            </trans-unit>
            <trans-unit id="6">
                <source>Not privileged to request the resource.</source>
                <target>ليست لديك الصلاحيات الكافية لهذا الطلب.</target>
            </trans-unit>
            <trans-unit id="7">
                <source>Invalid CSRF token.</source>
                <target>رمز الموقع غير صحيح.</target>
            </trans-unit>
            <trans-unit id="9">
                <source>No authentication provider found to support the authentication token.</source>
                <target>لا يوجد معرف للدخول يدعم الرمز المستخدم للدخول.</target>
            </trans-unit>
            <trans-unit id="10">
                <source>No session available, it either timed out or cookies are not enabled.</source>
                <target>لا يوجد صلة بينك و بين الموقع اما انها انتهت او ان متصفحك لا يدعم خاصية ملفات تعريف الارتباط (cookies).</target>
            </trans-unit>
            <trans-unit id="11">
                <source>No token could be found.</source>
                <target>لم استطع العثور على الرمز.</target>
            </trans-unit>
            <trans-unit id="12">
                <source>Username could not be found.</source>
                <target>لم استطع العثور على اسم الدخول.</target>
            </trans-unit>
            <trans-unit id="13">
                <source>Account has expired.</source>
                <target>انتهت صلاحية الحساب.</target>
            </trans-unit>
            <trans-unit id="14">
                <source>Credentials have expired.</source>
                <target>انتهت صلاحية معلومات الدخول.</target>
            </trans-unit>
            <trans-unit id="15">
                <source>Account is disabled.</source>
                <target>الحساب موقوف.</target>
            </trans-unit>
            <trans-unit id="16">
                <source>Account is locked.</source>
                <target>الحساب مغلق.</target>
            </trans-unit>
            <trans-unit id="17">
                <source>Too many failed login attempts, please try again later.</source>
                <target>العديد من محاولات الدخول الفاشلة، يرجى المحاولة مرة أخرى في وقت لاحق.</target>
            </trans-unit>
            <trans-unit id="18">
                <source>Invalid or expired login link.</source>
                <target>رابط تسجيل الدخول غير صالح أو منتهي الصلاحية.</target>
            </trans-unit>
            <trans-unit id="19">
                <source>Too many failed login attempts, please try again in %minutes% minute.</source>
                <target>العديد من محاولات الدخول الفاشلة، يرجى اعادة المحاولة بعد %minutes% دقيقة.</target>
            </trans-unit>
            <trans-unit id="20">
                <source>Too many failed login attempts, please try again in %minutes% minutes.</source>
                <target>العديد من محاولات الدخول الفاشلة ، يرجى اعادة المحاولة بعد %minutes% دقائق.</target>
            </trans-unit>
        </body>
    </file>
</xliff>
<?xml version="1.0" encoding="utf-8"?>
<xliff xmlns="urn:oasis:names:tc:xliff:document:1.2" version="1.2">
    <file source-language="en" target-language="lb" datatype="plaintext" original="file.ext">
        <body>
            <trans-unit id="1">
                <source>An authentication exception occurred.</source>
                <target>Bei der Authentifikatioun ass e Feeler opgetrueden.</target>
            </trans-unit>
            <trans-unit id="2">
                <source>Authentication credentials could not be found.</source>
                <target>Et konnte keng Zouganksdate fonnt ginn.</target>
            </trans-unit>
            <trans-unit id="3">
                <source>Authentication request could not be processed due to a system problem.</source>
                <target>D'Ufro fir eng Authentifikatioun konnt wéinst engem Problem vum System net beaarbecht ginn.</target>
            </trans-unit>
            <trans-unit id="4">
                <source>Invalid credentials.</source>
                <target>Ongëlteg Zouganksdaten.</target>
            </trans-unit>
            <trans-unit id="5">
                <source>Cookie has already been used by someone else.</source>
                <target>De Cookie gouf scho vun engem anere benotzt.</target>
            </trans-unit>
            <trans-unit id="6">
                <source>Not privileged to request the resource.</source>
                <target>Keng Rechter fir d'Ressource unzefroen.</target>
            </trans-unit>
            <trans-unit id="7">
                <source>Invalid CSRF token.</source>
                <target>Ongëltegen CSRF-Token.</target>
            </trans-unit>
            <trans-unit id="9">
                <source>No authentication provider found to support the authentication token.</source>
                <target>Et gouf keen Authentifizéierungs-Provider fonnt deen den Authentifizéierungs-Token ënnerstëtzt.</target>
            </trans-unit>
            <trans-unit id="10">
                <source>No session available, it either timed out or cookies are not enabled.</source>
                <target>Keng Sëtzung disponibel. Entweder ass se ofgelaf oder Cookies sinn net aktivéiert.</target>
            </trans-unit>
            <trans-unit id="11">
                <source>No token could be found.</source>
                <target>Et konnt keen Token fonnt ginn.</target>
            </trans-unit>
            <trans-unit id="12">
                <source>Username could not be found.</source>
                <target>De Benotzernumm konnt net fonnt ginn.</target>
            </trans-unit>
            <trans-unit id="13">
                <source>Account has expired.</source>
                <target>Den Account ass ofgelaf.</target>
            </trans-unit>
            <trans-unit id="14">
                <source>Credentials have expired.</source>
                <target>D'Zouganksdate sinn ofgelaf.</target>
            </trans-unit>
            <trans-unit id="15">
                <source>Account is disabled.</source>
                <target>De Konto ass deaktivéiert.</target>
            </trans-unit>
            <trans-unit id="16">
                <source>Account is locked.</source>
                <target>De Konto ass gespaart.</target>
            </trans-unit>
            <trans-unit id="17">
                <source>Too many failed login attempts, please try again later.</source>
                <target>Ze vill mësslonge Login-Versich, w.e.g. méi spéit nach emol probéieren.</target>
            </trans-unit>
            <trans-unit id="18">
                <source>Invalid or expired login link.</source>
                <target>Ongëltegen oder ofgelafene Login-Link.</target>
            </trans-unit>
            <trans-unit id="19">
                <source>Too many failed login attempts, please try again in %minutes% minute.</source>
                <target>Zu vill fehlgeschloen Loginversich, w. e. g. probéiert nach am %minutes% Minutt.</target>
            </trans-unit>
            <trans-unit id="20">
                <source>Too many failed login attempts, please try again in %minutes% minutes.</source>
                <target>Ze vill Feeler beim Umellen, versicht weg erëm an %minutes% Minutten.</target>
            </trans-unit>
        </body>
    </file>
</xliff>
<?xml version="1.0" encoding="utf-8"?>
<xliff xmlns="urn:oasis:names:tc:xliff:document:1.2" version="1.2">
    <file source-language="en" target-language="tr" datatype="plaintext" original="file.ext">
        <body>
            <trans-unit id="1">
                <source>An authentication exception occurred.</source>
                <target>Bir yetkilendirme istisnası oluştu.</target>
            </trans-unit>
            <trans-unit id="2">
                <source>Authentication credentials could not be found.</source>
                <target>Kimlik bilgileri bulunamadı.</target>
            </trans-unit>
            <trans-unit id="3">
                <source>Authentication request could not be processed due to a system problem.</source>
                <target>Bir sistem hatası nedeniyle yetkilendirme isteği işleme alınamıyor.</target>
            </trans-unit>
            <trans-unit id="4">
                <source>Invalid credentials.</source>
                <target>Geçersiz kimlik bilgileri.</target>
            </trans-unit>
            <trans-unit id="5">
                <source>Cookie has already been used by someone else.</source>
                <target>Çerez bir başkası tarafından zaten kullanılmıştı.</target>
            </trans-unit>
            <trans-unit id="6">
                <source>Not privileged to request the resource.</source>
                <target>Kaynak talebi için imtiyaz bulunamadı.</target>
            </trans-unit>
            <trans-unit id="7">
                <source>Invalid CSRF token.</source>
                <target>Geçersiz CSRF fişi.</target>
            </trans-unit>
            <trans-unit id="9">
                <source>No authentication provider found to support the authentication token.</source>
                <target>Yetkilendirme fişini destekleyecek yetkilendirme sağlayıcısı bulunamadı.</target>
            </trans-unit>
            <trans-unit id="10">
                <source>No session available, it either timed out or cookies are not enabled.</source>
                <target>Oturum bulunamadı, zaman aşımına uğradı veya çerezler etkin değil.</target>
            </trans-unit>
            <trans-unit id="11">
                <source>No token could be found.</source>
                <target>Fiş bulunamadı.</target>
            </trans-unit>
            <trans-unit id="12">
                <source>Username could not be found.</source>
                <target>Kullanıcı adı bulunamadı.</target>
            </trans-unit>
            <trans-unit id="13">
                <source>Account has expired.</source>
                <target>Hesap zaman aşımına uğradı.</target>
            </trans-unit>
            <trans-unit id="14">
                <source>Credentials have expired.</source>
                <target>Kimlik bilgileri zaman aşımına uğradı.</target>
            </trans-unit>
            <trans-unit id="15">
                <source>Account is disabled.</source>
                <target>Hesap engellenmiş.</target>
            </trans-unit>
            <trans-unit id="16">
                <source>Account is locked.</source>
                <target>Hesap kilitlenmiş.</target>
            </trans-unit>
            <trans-unit id="17">
                <source>Too many failed login attempts, please try again later.</source>
                <target>Çok fazla başarısız giriş denemesi, lütfen daha sonra tekrar deneyin.</target>
            </trans-unit>
            <trans-unit id="18">
                <source>Invalid or expired login link.</source>
                <target>Geçersiz veya süresi dolmuş oturum açma bağlantısı.</target>
            </trans-unit>
            <trans-unit id="19">
                <source>Too many failed login attempts, please try again in %minutes% minute.</source>
                <target>Çok fazla başarısız giriş denemesi, lütfen %minutes% dakika sonra tekrar deneyin.</target>
            </trans-unit>
            <trans-unit id="20">
                <source>Too many failed login attempts, please try again in %minutes% minutes.</source>
                <target>Çok fazla başarısız giriş denemesi, lütfen %minutes% dakika sonra tekrar deneyin.</target>
            </trans-unit>
        </body>
    </file>
</xliff>
<?xml version="1.0" encoding="utf-8"?>
<xliff xmlns="urn:oasis:names:tc:xliff:document:1.2" version="1.2">
    <file source-language="en" target-language="lt" datatype="plaintext" original="file.ext">
        <body>
            <trans-unit id="1">
                <source>An authentication exception occurred.</source>
                <target>Įvyko autentifikacijos klaida.</target>
            </trans-unit>
            <trans-unit id="2">
                <source>Authentication credentials could not be found.</source>
                <target>Nepavyko rasti autentifikacijos duomenų.</target>
            </trans-unit>
            <trans-unit id="3">
                <source>Authentication request could not be processed due to a system problem.</source>
                <target>Autentifikacijos užklausos nepavyko įvykdyti dėl sistemos klaidų.</target>
            </trans-unit>
            <trans-unit id="4">
                <source>Invalid credentials.</source>
                <target>Klaidingi duomenys.</target>
            </trans-unit>
            <trans-unit id="5">
                <source>Cookie has already been used by someone else.</source>
                <target>Slapukas buvo panaudotas kažkam kitam.</target>
            </trans-unit>
            <trans-unit id="6">
                <source>Not privileged to request the resource.</source>
                <target>Neturite teisių pasiektį resursą.</target>
            </trans-unit>
            <trans-unit id="7">
                <source>Invalid CSRF token.</source>
                <target>Neteisingas CSRF raktas.</target>
            </trans-unit>
            <trans-unit id="9">
                <source>No authentication provider found to support the authentication token.</source>
                <target>Nerastas autentifikacijos tiekėjas, kuris palaikytų autentifikacijos raktą.</target>
            </trans-unit>
            <trans-unit id="10">
                <source>No session available, it either timed out or cookies are not enabled.</source>
                <target>Sesija yra nepasiekiama, pasibaigė galiojimo laikas arba slapukai yra išjungti.</target>
            </trans-unit>
            <trans-unit id="11">
                <source>No token could be found.</source>
                <target>Nepavyko rasti rakto.</target>
            </trans-unit>
            <trans-unit id="12">
                <source>Username could not be found.</source>
                <target>Tokio naudotojo vardo nepavyko rasti.</target>
            </trans-unit>
            <trans-unit id="13">
                <source>Account has expired.</source>
                <target>Paskyros galiojimo laikas baigėsi.</target>
            </trans-unit>
            <trans-unit id="14">
                <source>Credentials have expired.</source>
                <target>Autentifikacijos duomenų galiojimo laikas baigėsi.</target>
            </trans-unit>
            <trans-unit id="15">
                <source>Account is disabled.</source>
                <target>Paskyra yra išjungta.</target>
            </trans-unit>
            <trans-unit id="16">
                <source>Account is locked.</source>
                <target>Paskyra yra užblokuota.</target>
            </trans-unit>
            <trans-unit id="17">
                <source>Too many failed login attempts, please try again later.</source>
                <target>Per daug nepavykusių prisijungimo bandymų, pabandykite dar kartą vėliau.</target>
            </trans-unit>
            <trans-unit id="18">
                <source>Invalid or expired login link.</source>
                <target>Netinkama arba pasibaigusio galiojimo laiko prisijungimo nuoroda.</target>
            </trans-unit>
            <trans-unit id="19">
                <source>Too many failed login attempts, please try again in %minutes% minute.</source>
                <target>Per daug nepavykusių prisijungimo bandymų, pabandykite dar kartą po %minutes% minutės.</target>
            </trans-unit>
            <trans-unit id="20">
                <source>Too many failed login attempts, please try again in %minutes% minutes.</source>
                <target>Per daug nesėkmingų prisijungimo bandymų, bandykite vėl po %minutes% minutės.|Per daug nesėkmingų prisijungimo bandymų, bandykite vėl po %minutes% minučių.</target>
            </trans-unit>
        </body>
    </file>
</xliff>
<?xml version="1.0" encoding="utf-8"?>
<xliff xmlns="urn:oasis:names:tc:xliff:document:1.2" version="1.2">
    <file source-language="en" target-language="zh-CN" datatype="plaintext" original="file.ext">
        <body>
            <trans-unit id="1">
                <source>An authentication exception occurred.</source>
                <target>身份验证发生异常。</target>
            </trans-unit>
            <trans-unit id="2">
                <source>Authentication credentials could not be found.</source>
                <target>没有找到身份验证的凭证。</target>
            </trans-unit>
            <trans-unit id="3">
                <source>Authentication request could not be processed due to a system problem.</source>
                <target>由于系统故障，身份验证的请求无法被处理。</target>
            </trans-unit>
            <trans-unit id="4">
                <source>Invalid credentials.</source>
                <target>无效的凭证。</target>
            </trans-unit>
            <trans-unit id="5">
                <source>Cookie has already been used by someone else.</source>
                <target>Cookie 已经被其他人使用。</target>
            </trans-unit>
            <trans-unit id="6">
                <source>Not privileged to request the resource.</source>
                <target>没有权限请求此资源。</target>
            </trans-unit>
            <trans-unit id="7">
                <source>Invalid CSRF token.</source>
                <target>无效的 CSRF token 。</target>
            </trans-unit>
            <trans-unit id="9">
                <source>No authentication provider found to support the authentication token.</source>
                <target>没有找到支持此 token 的身份验证服务提供方。</target>
            </trans-unit>
            <trans-unit id="10">
                <source>No session available, it either timed out or cookies are not enabled.</source>
                <target>Session 不可用。会话超时或没有启用 cookies 。</target>
            </trans-unit>
            <trans-unit id="11">
                <source>No token could be found.</source>
                <target>找不到 token 。</target>
            </trans-unit>
            <trans-unit id="12">
                <source>Username could not be found.</source>
                <target>找不到用户名。</target>
            </trans-unit>
            <trans-unit id="13">
                <source>Account has expired.</source>
                <target>帐号已过期。</target>
            </trans-unit>
            <trans-unit id="14">
                <source>Credentials have expired.</source>
                <target>凭证已过期。</target>
            </trans-unit>
            <trans-unit id="15">
                <source>Account is disabled.</source>
                <target>帐号已被禁用。</target>
            </trans-unit>
            <trans-unit id="16">
                <source>Account is locked.</source>
                <target>帐号已被锁定。</target>
            </trans-unit>
            <trans-unit id="17">
                <source>Too many failed login attempts, please try again later.</source>
                <target>登入失败的次数过多，请稍后再试。</target>
            </trans-unit>
            <trans-unit id="18">
                <source>Invalid or expired login link.</source>
                <target>失效或过期的登入链接。</target>
            </trans-unit>
            <trans-unit id="19">
                <source>Too many failed login attempts, please try again in %minutes% minute.</source>
                <target>登入失败的次数过多，请在%minutes%分钟后再试。</target>
            </trans-unit>
            <trans-unit id="20">
                <source>Too many failed login attempts, please try again in %minutes% minutes.</source>
                <target>登录尝试失败次数过多，请在 %minutes% 分钟后重试。</target>
            </trans-unit>
        </body>
    </file>
</xliff>
<?xml version="1.0" encoding="utf-8"?>
<xliff xmlns="urn:oasis:names:tc:xliff:document:1.2" version="1.2">
    <file source-language="en" target-language="ca" datatype="plaintext" original="file.ext">
        <body>
            <trans-unit id="1">
                <source>An authentication exception occurred.</source>
                <target>Ha succeït un error d'autenticació.</target>
            </trans-unit>
            <trans-unit id="2">
                <source>Authentication credentials could not be found.</source>
                <target>No s'han trobat les credencials d'autenticació.</target>
            </trans-unit>
            <trans-unit id="3">
                <source>Authentication request could not be processed due to a system problem.</source>
                <target>La solicitud d'autenticació no s'ha pogut processar per un problema del sistema.</target>
            </trans-unit>
            <trans-unit id="4">
                <source>Invalid credentials.</source>
                <target>Credencials no vàlides.</target>
            </trans-unit>
            <trans-unit id="5">
                <source>Cookie has already been used by someone else.</source>
                <target>La cookie ja ha estat utilitzada per una altra persona.</target>
            </trans-unit>
            <trans-unit id="6">
                <source>Not privileged to request the resource.</source>
                <target>No té privilegis per solicitar el recurs.</target>
            </trans-unit>
            <trans-unit id="7">
                <source>Invalid CSRF token.</source>
                <target>Token CSRF no vàlid.</target>
            </trans-unit>
            <trans-unit id="9">
                <source>No authentication provider found to support the authentication token.</source>
                <target>No s'ha trobat un proveïdor d'autenticació que suporti el token d'autenticació.</target>
            </trans-unit>
            <trans-unit id="10">
                <source>No session available, it either timed out or cookies are not enabled.</source>
                <target>No hi ha sessió disponible, ha expirat o les cookies no estan habilitades.</target>
            </trans-unit>
            <trans-unit id="11">
                <source>No token could be found.</source>
                <target>No s'ha trobat cap token.</target>
            </trans-unit>
            <trans-unit id="12">
                <source>Username could not be found.</source>
                <target>No s'ha trobat el nom d'usuari.</target>
            </trans-unit>
            <trans-unit id="13">
                <source>Account has expired.</source>
                <target>El compte ha expirat.</target>
            </trans-unit>
            <trans-unit id="14">
                <source>Credentials have expired.</source>
                <target>Les credencials han expirat.</target>
            </trans-unit>
            <trans-unit id="15">
                <source>Account is disabled.</source>
                <target>El compte està deshabilitat.</target>
            </trans-unit>
            <trans-unit id="16">
                <source>Account is locked.</source>
                <target>El compte està bloquejat.</target>
            </trans-unit>
            <trans-unit id="17">
                <source>Too many failed login attempts, please try again later.</source>
                <target>Massa intents d'inici de sessió fallits, si us plau torneu-ho a provar més tard.</target>
            </trans-unit>
            <trans-unit id="18">
                <source>Invalid or expired login link.</source>
                <target>Enllaç d'inici de sessió no vàlid o caducat.</target>
            </trans-unit>
            <trans-unit id="19">
                <source>Too many failed login attempts, please try again in %minutes% minute.</source>
                <target>Massa intents d'inici de sessió fallits, si us plau torneu-ho a provar en %minutes% minut.</target>
            </trans-unit>
            <trans-unit id="20">
                <source>Too many failed login attempts, please try again in %minutes% minutes.</source>
                <target>Massa intents d'inici de sessió fallits, si us plau torneu-ho a provar en %minutes% minuts.</target>
            </trans-unit>
        </body>
    </file>
</xliff>
<?xml version="1.0" encoding="utf-8"?>
<xliff xmlns="urn:oasis:names:tc:xliff:document:1.2" version="1.2">
    <file source-language="en" target-language="be" datatype="plaintext" original="file.ext">
        <body>
            <trans-unit id="1">
                <source>An authentication exception occurred.</source>
                <target>Памылка аўтэнтыфікацыі.</target>
            </trans-unit>
            <trans-unit id="2">
                <source>Authentication credentials could not be found.</source>
                <target>Дадзеныя аўтэнтыфікацыі не знойдзены.</target>
            </trans-unit>
            <trans-unit id="3">
                <source>Authentication request could not be processed due to a system problem.</source>
                <target>Запыт аўтэнтыфікацыі не можа быць апрацаваны ў сувязі з праблемай у сістэме.</target>
            </trans-unit>
            <trans-unit id="4">
                <source>Invalid credentials.</source>
                <target>Несапраўдныя дадзеныя аўтэнтыфікацыі.</target>
            </trans-unit>
            <trans-unit id="5">
                <source>Cookie has already been used by someone else.</source>
                <target>Нехта іншы ўжо выкарыстаў гэтыя кукі (cookie).</target>
            </trans-unit>
            <trans-unit id="6">
                <source>Not privileged to request the resource.</source>
                <target>Адсутнічаюць правы на запыт гэтага рэсурсу.</target>
            </trans-unit>
            <trans-unit id="7">
                <source>Invalid CSRF token.</source>
                <target>Несапраўдны CSRF-токен.</target>
            </trans-unit>
            <trans-unit id="9">
                <source>No authentication provider found to support the authentication token.</source>
                <target>Не знойдзен правайдар аўтэнтыфікацыі, які можа падтрымліваць гэты токен аўтэнтыфікацыі.</target>
            </trans-unit>
            <trans-unit id="10">
                <source>No session available, it either timed out or cookies are not enabled.</source>
                <target>Сесія не даступна, яе час скончыўся, або кукі (cookies) выключаны.</target>
            </trans-unit>
            <trans-unit id="11">
                <source>No token could be found.</source>
                <target>Токен не знойдзен.</target>
            </trans-unit>
            <trans-unit id="12">
                <source>Username could not be found.</source>
                <target>Імя карыстальніка не знойдзена.</target>
            </trans-unit>
            <trans-unit id="13">
                <source>Account has expired.</source>
                <target>Скончыўся тэрмін дзеяння акаўнта.</target>
            </trans-unit>
            <trans-unit id="14">
                <source>Credentials have expired.</source>
                <target>Скончыўся тэрмін дзеяння дадзеных аўтэнтыфікацыі.</target>
            </trans-unit>
            <trans-unit id="15">
                <source>Account is disabled.</source>
                <target>Акаўнт адключан.</target>
            </trans-unit>
            <trans-unit id="16">
                <source>Account is locked.</source>
                <target>Акаўнт заблакіраван.</target>
            </trans-unit>
            <trans-unit id="17">
                <source>Too many failed login attempts, please try again later.</source>
                <target>Зашмат няўдалых спроб уваходу, калі ласка, паспрабуйце пазней.</target>
            </trans-unit>
            <trans-unit id="18">
                <source>Invalid or expired login link.</source>
                <target>Спасылка для ўваходу несапраўдная або пратэрмінаваная.</target>
            </trans-unit>
            <trans-unit id="19">
                <source>Too many failed login attempts, please try again in %minutes% minute.</source>
                <target>Занадта шмат няўдалых спроб уваходу ў сістэму, паспрабуйце спробу праз %minutes% хвіліну.</target>
            </trans-unit>
            <trans-unit id="20">
                <source>Too many failed login attempts, please try again in %minutes% minutes.</source>
                <target>Занадта вялікая колькасць няўдалых спробаў уваходу. Калі ласка, паспрабуйце зноў праз %minutes% хвіліну.|Занадта вялікая колькасць няўдалых спробаў уваходу. Калі ласка, паспрабуйце зноў праз %minutes% хвіліны.|Занадта вялікая колькасць няўдалых спробаў уваходу. Калі ласка, паспрабуйце зноў праз %minutes% хвілін.</target>
            </trans-unit>
        </body>
    </file>
</xliff>
<?xml version="1.0" encoding="utf-8"?>
<xliff xmlns="urn:oasis:names:tc:xliff:document:1.2" version="1.2">
    <file source-language="en" target-language="th" datatype="plaintext" original="file.ext">
        <body>
            <trans-unit id="1">
                <source>An authentication exception occurred.</source>
                <target>พบความผิดพลาดในการรับรองตัวตน</target>
            </trans-unit>
            <trans-unit id="2">
                <source>Authentication credentials could not be found.</source>
                <target>ไม่พบข้อมูลในการรับรองตัวตน (credentials) </target>
            </trans-unit>
            <trans-unit id="3">
                <source>Authentication request could not be processed due to a system problem.</source>
                <target>คำร้องในการรับรองตัวตนไม่สามารถดำเนินการได้ เนื่องมาจากปัญหาของระบบ</target>
            </trans-unit>
            <trans-unit id="4">
                <source>Invalid credentials.</source>
                <target>ข้อมูลการรับรองตัวตนไม่ถูกต้อง</target>
            </trans-unit>
            <trans-unit id="5">
                <source>Cookie has already been used by someone else.</source>
                <target>Cookie ถูกใช้งานไปแล้วด้วยผู้อื่น</target>
            </trans-unit>
            <trans-unit id="6">
                <source>Not privileged to request the resource.</source>
                <target>ไม่ได้รับสิทธิ์ให้ใช้งานส่วนนี้ได้</target>
            </trans-unit>
            <trans-unit id="7">
                <source>Invalid CSRF token.</source>
                <target>CSRF token ไม่ถูกต้อง</target>
            </trans-unit>
            <trans-unit id="9">
                <source>No authentication provider found to support the authentication token.</source>
                <target>ไม่พบ authentication provider ที่รองรับสำหรับ authentication token</target>
            </trans-unit>
            <trans-unit id="10">
                <source>No session available, it either timed out or cookies are not enabled.</source>
                <target>ไม่มี session ที่พร้อมใช้งาน, Session หมดอายุไปแล้วหรือ cookies ไม่ถูกเปิดใช้งาน</target>
            </trans-unit>
            <trans-unit id="11">
                <source>No token could be found.</source>
                <target>ไม่พบ token</target>
            </trans-unit>
            <trans-unit id="12">
                <source>Username could not be found.</source>
                <target>ไม่พบ Username</target>
            </trans-unit>
            <trans-unit id="13">
                <source>Account has expired.</source>
                <target>บัญชีหมดอายุไปแล้ว</target>
            </trans-unit>
            <trans-unit id="14">
                <source>Credentials have expired.</source>
                <target>ข้อมูลการระบุตัวตนหมดอายุแล้ว</target>
            </trans-unit>
            <trans-unit id="15">
                <source>Account is disabled.</source>
                <target>บัญชีถูกระงับแล้ว</target>
            </trans-unit>
            <trans-unit id="16">
                <source>Account is locked.</source>
                <target>บัญชีถูกล็อกแล้ว</target>
            </trans-unit>
            <trans-unit id="17">
                <source>Too many failed login attempts, please try again later.</source>
                <target>มีความพยายามเข้าสู่ระบบล้มเหลวมากเกินไป กรุณาลองใหม่ภายหลัง</target>
            </trans-unit>
            <trans-unit id="18">
                <source>Invalid or expired login link.</source>
                <target>ลิงค์เข้าสู่ระบบไม่ถูกต้องหรือหมดอายุไปแล้ว</target>
            </trans-unit>
            <trans-unit id="19">
                <source>Too many failed login attempts, please try again in %minutes% minute.</source>
                <target>มีความพยายามเข้าสู่ระบบล้มเหลวมากเกินไป โปรดลองอีกครั้งใน %minutes% นาที</target>
            </trans-unit>
            <trans-unit id="20">
                <source>Too many failed login attempts, please try again in %minutes% minutes.</source>
                <target state="needs-review-translation">มีความพยายามในการเข้าสู่ระบบล้มเหลวมากเกินไป โปรดลองอีกครั้งใน %minutes% นาที.|มีความพยายามในการเข้าสู่ระบบล้มเหลวมากเกินไป โปรดลองอีกครั้งใน %minutes% นาที.</target>
            </trans-unit>
        </body>
    </file>
</xliff>
<?xml version="1.0" encoding="utf-8"?>
<xliff xmlns="urn:oasis:names:tc:xliff:document:1.2" version="1.2">
    <file source-language="en" target-language="uz" datatype="plaintext" original="file.ext">
        <body>
            <trans-unit id="1">
                <source>An authentication exception occurred.</source>
                <target>Autentifikatsiyada xatolik.</target>
            </trans-unit>
            <trans-unit id="2">
                <source>Authentication credentials could not be found.</source>
                <target>Autentifikatsiya ma'lumotlari topilmadi.</target>
            </trans-unit>
            <trans-unit id="3">
                <source>Authentication request could not be processed due to a system problem.</source>
                <target>Tizimdagi muammo tufayli autentifikatsiya so'rovi bajarilmadi.</target>
            </trans-unit>
            <trans-unit id="4">
                <source>Invalid credentials.</source>
                <target>Noto'g'ri ma'lumot.</target>
            </trans-unit>
            <trans-unit id="5">
                <source>Cookie has already been used by someone else.</source>
                <target>Cookie faylini allaqachon kimdir ishlatgan.</target>
            </trans-unit>
            <trans-unit id="6">
                <source>Not privileged to request the resource.</source>
                <target>Sizda ushbu manbani talab qilishga ruxsat yo'q..</target>
            </trans-unit>
            <trans-unit id="7">
                <source>Invalid CSRF token.</source>
                <target>Noto'g'ri CSRF belgisi.</target>
            </trans-unit>
            <trans-unit id="9">
                <source>No authentication provider found to support the authentication token.</source>
                <target>Haqiqiylikni tasdiqlovchi belgini qo'llab-quvvatlovchi biron bir autentifikatsiya provayderi topilmadi.</target>
            </trans-unit>
            <trans-unit id="10">
                <source>No session available, it either timed out or cookies are not enabled.</source>
                <target>Sessiya topilmadi, muddati tugamadi yoki cookie-fayllar yoqilmagan.</target>
            </trans-unit>
            <trans-unit id="11">
                <source>No token could be found.</source>
                <target>To'ken topilmadi.</target>
            </trans-unit>
            <trans-unit id="12">
                <source>Username could not be found.</source>
                <target>Foydalanuvchi nomi topilmadi.</target>
            </trans-unit>
            <trans-unit id="13">
                <source>Account has expired.</source>
                <target>Akkunt muddati tugagan.</target>
            </trans-unit>
            <trans-unit id="14">
                <source>Credentials have expired.</source>
                <target>Autentifikatsiya ma'lumotlari muddati tugagan.</target>
            </trans-unit>
            <trans-unit id="15">
                <source>Account is disabled.</source>
                <target>Akkunt o'chirilgan.</target>
            </trans-unit>
            <trans-unit id="16">
                <source>Account is locked.</source>
                <target>Akkunt bloklangan.</target>
            </trans-unit>
            <trans-unit id="17">
                <source>Too many failed login attempts, please try again later.</source>
                <target>Kirish urinishlari muvaffaqiyatsiz tugadi, keyinroq qayta urinib ko'ring.</target>
            </trans-unit>
            <trans-unit id="18">
                <source>Invalid or expired login link.</source>
                <target>Kirish havolasi yaroqsiz yoki muddati tugagan.</target>
            </trans-unit>
            <trans-unit id="19">
                <source>Too many failed login attempts, please try again in %minutes% minute.</source>
                <target>Kirish uchun muvaffaqiyatsiz urinishlar, %minutes% daqiqadan so'ng qayta urinib ko'ring.</target>
            </trans-unit>
            <trans-unit id="20">
                <source>Too many failed login attempts, please try again in %minutes% minutes.</source>
                <target>Koʻplab muvaffaqiyatsiz kirish urinishlari, iltimos, %minutes% daqiqadan so'ng qayta urinib koʻring.|Koʻplab muvaffaqiyatsiz kirish urinishlari, iltimos, %minutes% daqiqadan so'ng qayta urinib koʻring.</target>
            </trans-unit>
        </body>
    </file>
</xliff>
<?xml version="1.0" encoding="utf-8"?>
<xliff xmlns="urn:oasis:names:tc:xliff:document:1.2" version="1.2">
    <file source-language="en" target-language="mk" datatype="plaintext" original="file.ext">
        <body>
            <trans-unit id="1">
                <source>An authentication exception occurred.</source>
                <target>Настана грешка во автентикацијата.</target>
            </trans-unit>
            <trans-unit id="2">
                <source>Authentication credentials could not be found.</source>
                <target>Акредитивите за автентикација не се пронајдени.</target>
            </trans-unit>
            <trans-unit id="3">
                <source>Authentication request could not be processed due to a system problem.</source>
                <target>Барањето за автентикација не можеше да биде процесуирано заради системски проблем.</target>
            </trans-unit>
            <trans-unit id="4">
                <source>Invalid credentials.</source>
                <target>Невалидни акредитиви.</target>
            </trans-unit>
            <trans-unit id="5">
                <source>Cookie has already been used by someone else.</source>
                <target>Колачето е веќе користено од некој друг.</target>
            </trans-unit>
            <trans-unit id="6">
                <source>Not privileged to request the resource.</source>
                <target>Немате привилегии за да го побарате ресурсот.</target>
            </trans-unit>
            <trans-unit id="7">
                <source>Invalid CSRF token.</source>
                <target>Невалиден CSRF токен.</target>
            </trans-unit>
            <trans-unit id="9">
                <source>No authentication provider found to support the authentication token.</source>
                <target>Не е пронајден провајдер за автентикација кој го поддржува токенот за автентикација.</target>
            </trans-unit>
            <trans-unit id="10">
                <source>No session available, it either timed out or cookies are not enabled.</source>
                <target>Сесијата е недостапна, или е истечена, или колачињата не се овозможени.</target>
            </trans-unit>
            <trans-unit id="11">
                <source>No token could be found.</source>
                <target>Токенот не е најден.</target>
            </trans-unit>
            <trans-unit id="12">
                <source>Username could not be found.</source>
                <target>Корисничкото име не е најдено.</target>
            </trans-unit>
            <trans-unit id="13">
                <source>Account has expired.</source>
                <target>Корисничката сметка е истечена.</target>
            </trans-unit>
            <trans-unit id="14">
                <source>Credentials have expired.</source>
                <target>Акредитивите се истечени.</target>
            </trans-unit>
            <trans-unit id="15">
                <source>Account is disabled.</source>
                <target>Корисничката сметка е деактивирана.</target>
            </trans-unit>
            <trans-unit id="16">
                <source>Account is locked.</source>
                <target>Корисничката сметка е заклучена.</target>
            </trans-unit>
            <trans-unit id="17">
                <source>Too many failed login attempts, please try again later.</source>
                <target>Премногу неуспешни обиди за најавување, ве молиме обидете се повторно подоцна.</target>
            </trans-unit>
            <trans-unit id="18">
                <source>Invalid or expired login link.</source>
                <target>Неважечка или истечена врска за најавување.</target>
            </trans-unit>
            <trans-unit id="19">
                <source>Too many failed login attempts, please try again in %minutes% minute.</source>
                <target>Премногу неуспешни обиди за најавување, обидете се повторно за %minutes% минута.</target>
            </trans-unit>
            <trans-unit id="20">
                <source>Too many failed login attempts, please try again in %minutes% minutes.</source>
                <target state="needs-review-translation">Претерано многу неуспешни обиди за најавување, ве молиме обидете се повторно за %minutes% минута.|Претерано многу неуспешни обиди за најавување, ве молиме обидете се повторно за %minutes% минути.</target>
            </trans-unit>
        </body>
    </file>
</xliff>
<?xml version="1.0" encoding="utf-8"?>
<xliff xmlns="urn:oasis:names:tc:xliff:document:1.2" version="1.2">
    <file source-language="en" target-language="bs" datatype="plaintext" original="file.ext">
        <body>
            <trans-unit id="1">
                <source>An authentication exception occurred.</source>
                <target>Došlo je do autentifikacijskog izuzetka (exception).</target>
            </trans-unit>
            <trans-unit id="2">
                <source>Authentication credentials could not be found.</source>
                <target>Autentifikacijski podaci nisu pronađeni.</target>
            </trans-unit>
            <trans-unit id="3">
                <source>Authentication request could not be processed due to a system problem.</source>
                <target>Autentifikacijski zahtjev ne može biti obrađen zbog sistemskog problema.</target>
            </trans-unit>
            <trans-unit id="4">
                <source>Invalid credentials.</source>
                <target>Autentifikacijski podaci su neispravni.</target>
            </trans-unit>
            <trans-unit id="5">
                <source>Cookie has already been used by someone else.</source>
                <target>Neko drugi je već iskoristio ovaj kolačić (cookie).</target>
            </trans-unit>
            <trans-unit id="6">
                <source>Not privileged to request the resource.</source>
                <target>Nemate privilegije potrebne za pristup ovom resursu.</target>
            </trans-unit>
            <trans-unit id="7">
                <source>Invalid CSRF token.</source>
                <target>CSRF žeton (token) je neispravan.</target>
            </trans-unit>
            <trans-unit id="9">
                <source>No authentication provider found to support the authentication token.</source>
                <target>Nije pronađen autentifikacijski provajder koji bi podržao dati autentifikacijski žeton (token).</target>
            </trans-unit>
            <trans-unit id="10">
                <source>No session available, it either timed out or cookies are not enabled.</source>
                <target>Nema dostupnih sesija; ili je istekla ili su kolačići (cookies) iksljučeni.</target>
            </trans-unit>
            <trans-unit id="11">
                <source>No token could be found.</source>
                <target>Nije pronađen nijedan žeton (token).</target>
            </trans-unit>
            <trans-unit id="12">
                <source>Username could not be found.</source>
                <target>Korisničko ime nije pronađeno.</target>
            </trans-unit>
            <trans-unit id="13">
                <source>Account has expired.</source>
                <target>Nalog je istekao.</target>
            </trans-unit>
            <trans-unit id="14">
                <source>Credentials have expired.</source>
                <target>Autentifikacijski podaci su istekli.</target>
            </trans-unit>
            <trans-unit id="15">
                <source>Account is disabled.</source>
                <target>Nalog je onemogućen.</target>
            </trans-unit>
            <trans-unit id="16">
                <source>Account is locked.</source>
                <target>Nalog je zaključan.</target>
            </trans-unit>
            <trans-unit id="17">
                <source>Too many failed login attempts, please try again later.</source>
                <target>Previše neuspješnih pokušaja prijavljivanja, molim pokušajte ponovo kasnije.</target>
            </trans-unit>
            <trans-unit id="18">
                <source>Invalid or expired login link.</source>
                <target>Link za prijavljivanje je istekao ili je neispravan.</target>
            </trans-unit>
            <trans-unit id="19">
                <source>Too many failed login attempts, please try again in %minutes% minute.</source>
                <target>Previše neuspjelih pokušaja prijave, pokušajte ponovo za %minutes% minuta.</target>
            </trans-unit>
            <trans-unit id="20">
                <source>Too many failed login attempts, please try again in %minutes% minutes.</source>
                <target state="needs-review-translation">Previše neuspješnih pokušaja prijave, pokušajte ponovo za %minutes% minut.|Previše neuspješnih pokušaja prijave, pokušajte ponovo za %minutes% minuta.</target>
            </trans-unit>
        </body>
    </file>
</xliff>
<?xml version="1.0" encoding="utf-8"?>
<xliff xmlns="urn:oasis:names:tc:xliff:document:1.2" version="1.2">
    <file source-language="en" target-language="bg" datatype="plaintext" original="file.ext">
        <body>
            <trans-unit id="1">
                <source>An authentication exception occurred.</source>
                <target>Грешка при автентикация.</target>
            </trans-unit>
            <trans-unit id="2">
                <source>Authentication credentials could not be found.</source>
                <target>Удостоверението за автентикация не е открито.</target>
            </trans-unit>
            <trans-unit id="3">
                <source>Authentication request could not be processed due to a system problem.</source>
                <target>Заявката за автентикация не може да бъде обработената поради системна грешка.</target>
            </trans-unit>
            <trans-unit id="4">
                <source>Invalid credentials.</source>
                <target>Невалидно удостоверение за автентикация.</target>
            </trans-unit>
            <trans-unit id="5">
                <source>Cookie has already been used by someone else.</source>
                <target>Тази бисквитка вече се ползва от някой друг.</target>
            </trans-unit>
            <trans-unit id="6">
                <source>Not privileged to request the resource.</source>
                <target>Нямате права за достъп до този ресурс.</target>
            </trans-unit>
            <trans-unit id="7">
                <source>Invalid CSRF token.</source>
                <target>Невалиден CSRF токен.</target>
            </trans-unit>
            <trans-unit id="9">
                <source>No authentication provider found to support the authentication token.</source>
                <target>Не е открит провайдър, който да поддържа този токен за автентикация.</target>
            </trans-unit>
            <trans-unit id="10">
                <source>No session available, it either timed out or cookies are not enabled.</source>
                <target>Сесията не е достъпна, или времето за достъп е изтекло, или бисквитките не са разрешени.</target>
            </trans-unit>
            <trans-unit id="11">
                <source>No token could be found.</source>
                <target>Токенът не е открит.</target>
            </trans-unit>
            <trans-unit id="12">
                <source>Username could not be found.</source>
                <target>Потребителското име не е открито.</target>
            </trans-unit>
            <trans-unit id="13">
                <source>Account has expired.</source>
                <target>Акаунтът е изтекъл.</target>
            </trans-unit>
            <trans-unit id="14">
                <source>Credentials have expired.</source>
                <target>Удостоверението за автентикация е изтекло.</target>
            </trans-unit>
            <trans-unit id="15">
                <source>Account is disabled.</source>
                <target>Акаунтът е деактивиран.</target>
            </trans-unit>
            <trans-unit id="16">
                <source>Account is locked.</source>
                <target>Акаунтът е заключен.</target>
            </trans-unit>
            <trans-unit id="17">
                <source>Too many failed login attempts, please try again later.</source>
                <target>Твърде много неуспешни опити за вход, моля опитайте по-късно.</target>
            </trans-unit>
            <trans-unit id="18">
                <source>Invalid or expired login link.</source>
                <target>Невалиден или изтекъл линк за вход.</target>
            </trans-unit>
            <trans-unit id="19">
                <source>Too many failed login attempts, please try again in %minutes% minute.</source>
                <target>Твърде много неуспешни опити за вход, моля опитайте отново след %minutes% минута.</target>
            </trans-unit>
            <trans-unit id="20">
                <source>Too many failed login attempts, please try again in %minutes% minutes.</source>
                <target>Твърде много неуспешни опити за вход, моля опитайте отново след %minutes% минути.</target>
            </trans-unit>
        </body>
    </file>
</xliff>
<?xml version="1.0" encoding="utf-8"?>
<xliff xmlns="urn:oasis:names:tc:xliff:document:1.2" version="1.2">
    <file source-language="en" target-language="sr-Latn" datatype="plaintext" original="file.ext">
        <body>
            <trans-unit id="1">
                <source>An authentication exception occurred.</source>
                <target>Izuzetak pri autentifikaciji.</target>
            </trans-unit>
            <trans-unit id="2">
                <source>Authentication credentials could not be found.</source>
                <target>Autentifikacioni podaci nisu pronađeni.</target>
            </trans-unit>
            <trans-unit id="3">
                <source>Authentication request could not be processed due to a system problem.</source>
                <target>Zahtev za autentifikaciju ne može biti obrađen zbog sistemskih problema.</target>
            </trans-unit>
            <trans-unit id="4">
                <source>Invalid credentials.</source>
                <target>Nevalidni podaci za autentifikaciju.</target>
            </trans-unit>
            <trans-unit id="5">
                <source>Cookie has already been used by someone else.</source>
                <target>Kolačić je već iskorišćen od strane nekog drugog.</target>
            </trans-unit>
            <trans-unit id="6">
                <source>Not privileged to request the resource.</source>
                <target>Nemate prava pristupa ovom resursu.</target>
            </trans-unit>
            <trans-unit id="7">
                <source>Invalid CSRF token.</source>
                <target>Nevalidan CSRF token.</target>
            </trans-unit>
            <trans-unit id="9">
                <source>No authentication provider found to support the authentication token.</source>
                <target>Autentifikacioni provajder za podršku tokena nije pronađen.</target>
            </trans-unit>
            <trans-unit id="10">
                <source>No session available, it either timed out or cookies are not enabled.</source>
                <target>Sesija nije dostupna, istekla je ili su kolačići isključeni.</target>
            </trans-unit>
            <trans-unit id="11">
                <source>No token could be found.</source>
                <target>Token ne može biti pronađen.</target>
            </trans-unit>
            <trans-unit id="12">
                <source>Username could not be found.</source>
                <target>Korisničko ime ne može biti pronađeno.</target>
            </trans-unit>
            <trans-unit id="13">
                <source>Account has expired.</source>
                <target>Nalog je istekao.</target>
            </trans-unit>
            <trans-unit id="14">
                <source>Credentials have expired.</source>
                <target>Podaci za autentifikaciju su istekli.</target>
            </trans-unit>
            <trans-unit id="15">
                <source>Account is disabled.</source>
                <target>Nalog je onemogućen.</target>
            </trans-unit>
            <trans-unit id="16">
                <source>Account is locked.</source>
                <target>Nalog je zaključan.</target>
            </trans-unit>
            <trans-unit id="17">
                <source>Too many failed login attempts, please try again later.</source>
                <target>Previše neuspešnih pokušaja prijavljivanja, molim pokušajte ponovo kasnije.</target>
            </trans-unit>
            <trans-unit id="18">
                <source>Invalid or expired login link.</source>
                <target>Link za prijavljivanje je istekao ili je neispravan.</target>
            </trans-unit>
            <trans-unit id="19">
                <source>Too many failed login attempts, please try again in %minutes% minute.</source>
                <target>Previše neuspešnih pokušaja prijavljivanja, molim pokušajte ponovo za %minutes% minut.</target>
            </trans-unit>
            <trans-unit id="20">
                <source>Too many failed login attempts, please try again in %minutes% minutes.</source>
                <target>Previše neuspešnih pokušaja prijavljivanja, pokušajte ponovo za %minutes% minut.|Previše neuspešnih pokušaja prijavljivanja, pokušajte ponovo za %minutes% minuta.</target>
            </trans-unit>
        </body>
    </file>
</xliff>
<?xml version="1.0" encoding="utf-8"?>
<xliff xmlns="urn:oasis:names:tc:xliff:document:1.2" version="1.2">
    <file source-language="en" target-language="uk" datatype="plaintext" original="file.ext">
        <body>
            <trans-unit id="1">
                <source>An authentication exception occurred.</source>
                <target>Помилка автентифікації.</target>
            </trans-unit>
            <trans-unit id="2">
                <source>Authentication credentials could not be found.</source>
                <target>Автентифікаційні дані не знайдено.</target>
            </trans-unit>
            <trans-unit id="3">
                <source>Authentication request could not be processed due to a system problem.</source>
                <target>Запит на автентифікацію не може бути опрацьовано у зв’язку з проблемою в системі.</target>
            </trans-unit>
            <trans-unit id="4">
                <source>Invalid credentials.</source>
                <target>Невірні автентифікаційні дані.</target>
            </trans-unit>
            <trans-unit id="5">
                <source>Cookie has already been used by someone else.</source>
                <target>Хтось інший вже використав цей сookie.</target>
            </trans-unit>
            <trans-unit id="6">
                <source>Not privileged to request the resource.</source>
                <target>Відсутні права на запит цього ресурсу.</target>
            </trans-unit>
            <trans-unit id="7">
                <source>Invalid CSRF token.</source>
                <target>Невірний токен CSRF.</target>
            </trans-unit>
            <trans-unit id="9">
                <source>No authentication provider found to support the authentication token.</source>
                <target>Не знайдено провайдера автентифікації, що підтримує токен автентифікаціії.</target>
            </trans-unit>
            <trans-unit id="10">
                <source>No session available, it either timed out or cookies are not enabled.</source>
                <target>Сесія недоступна, її час вийшов, або cookies вимкнено.</target>
            </trans-unit>
            <trans-unit id="11">
                <source>No token could be found.</source>
                <target>Токен не знайдено.</target>
            </trans-unit>
            <trans-unit id="12">
                <source>Username could not be found.</source>
                <target>Ім’я користувача не знайдено.</target>
            </trans-unit>
            <trans-unit id="13">
                <source>Account has expired.</source>
                <target>Термін дії облікового запису вичерпано.</target>
            </trans-unit>
            <trans-unit id="14">
                <source>Credentials have expired.</source>
                <target>Термін дії автентифікаційних даних вичерпано.</target>
            </trans-unit>
            <trans-unit id="15">
                <source>Account is disabled.</source>
                <target>Обліковий запис відключено.</target>
            </trans-unit>
            <trans-unit id="16">
                <source>Account is locked.</source>
                <target>Обліковий запис заблоковано.</target>
            </trans-unit>
            <trans-unit id="17">
                <source>Too many failed login attempts, please try again later.</source>
                <target>Забагато невдалих спроб входу. Будь ласка, спробуйте пізніше.</target>
            </trans-unit>
            <trans-unit id="18">
                <source>Invalid or expired login link.</source>
                <target>Посилання для входу недійсне, або термін його дії закінчився.</target>
            </trans-unit>
            <trans-unit id="19">
                <source>Too many failed login attempts, please try again in %minutes% minute.</source>
                <target>Забагато невдалих спроб входу. Будь ласка, спробуйте знову через %minutes% хвилину.</target>
            </trans-unit>
            <trans-unit id="20">
                <source>Too many failed login attempts, please try again in %minutes% minutes.</source>
                <target>Забагато невдалих спроб входу, будь ласка, спробуйте ще раз через %minutes% хвилину.|Забагато невдалих спроб входу, будь ласка, спробуйте ще раз через %minutes% хвилини.|Забагато невдалих спроб входу, будь ласка, спробуйте ще раз через %minutes% хвилин.</target>
            </trans-unit>
        </body>
    </file>
</xliff>
<?xml version="1.0" encoding="utf-8"?>
<xliff xmlns="urn:oasis:names:tc:xliff:document:1.2" version="1.2">
    <file source-language="en" target-language="zh-TW" datatype="plaintext" original="file.ext">
        <body>
            <trans-unit id="1">
                <source>An authentication exception occurred.</source>
                <target>身份驗證發生異常。</target>
            </trans-unit>
            <trans-unit id="2">
                <source>Authentication credentials could not be found.</source>
                <target>沒有找到身份驗證的憑證。</target>
            </trans-unit>
            <trans-unit id="3">
                <source>Authentication request could not be processed due to a system problem.</source>
                <target>由於系統故障，身份驗證的請求無法被處理。</target>
            </trans-unit>
            <trans-unit id="4">
                <source>Invalid credentials.</source>
                <target>登入憑證無效。</target>
            </trans-unit>
            <trans-unit id="5">
                <source>Cookie has already been used by someone else.</source>
                <target>Cookie 已經被其他人使用。</target>
            </trans-unit>
            <trans-unit id="6">
                <source>Not privileged to request the resource.</source>
                <target>無權請求此資源。</target>
            </trans-unit>
            <trans-unit id="7">
                <source>Invalid CSRF token.</source>
                <target>無效的 CSRF token。</target>
            </trans-unit>
            <trans-unit id="9">
                <source>No authentication provider found to support the authentication token.</source>
                <target>找不到支援此 token 的身分驗證服務提供方。</target>
            </trans-unit>
            <trans-unit id="10">
                <source>No session available, it either timed out or cookies are not enabled.</source>
                <target>沒有工作階段，可能是超過時間，或者是未啟用 Cookies。</target>
            </trans-unit>
            <trans-unit id="11">
                <source>No token could be found.</source>
                <target>找不到 token。</target>
            </trans-unit>
            <trans-unit id="12">
                <source>Username could not be found.</source>
                <target>找不到使用者名稱。</target>
            </trans-unit>
            <trans-unit id="13">
                <source>Account has expired.</source>
                <target>帳號已經過期。</target>
            </trans-unit>
            <trans-unit id="14">
                <source>Credentials have expired.</source>
                <target>憑證已經過期。</target>
            </trans-unit>
            <trans-unit id="15">
                <source>Account is disabled.</source>
                <target>帳號已被停用。</target>
            </trans-unit>
            <trans-unit id="16">
                <source>Account is locked.</source>
                <target>帳號已被鎖定。</target>
            </trans-unit>
            <trans-unit id="17">
                <source>Too many failed login attempts, please try again later.</source>
                <target>登入失敗的次數過多，請稍後再試。</target>
            </trans-unit>
            <trans-unit id="18">
                <source>Invalid or expired login link.</source>
                <target>登入連結無效或過期。</target>
            </trans-unit>
            <trans-unit id="19">
                <source>Too many failed login attempts, please try again in %minutes% minute.</source>
                <target>登入失敗的次數過多，請 %minutes% 分鐘後再試。</target>
            </trans-unit>
            <trans-unit id="20">
                <source>Too many failed login attempts, please try again in %minutes% minutes.</source>
                <target>登入嘗試次數過多，請 %minutes% 分鐘後再試。</target>
            </trans-unit>
        </body>
    </file>
</xliff>
<?xml version="1.0" encoding="utf-8"?>
<xliff xmlns="urn:oasis:names:tc:xliff:document:1.2" version="1.2">
    <file source-language="en" target-language="cs" datatype="plaintext" original="file.ext">
        <body>
            <trans-unit id="1">
                <source>An authentication exception occurred.</source>
                <target>Při ověřování došlo k chybě.</target>
            </trans-unit>
            <trans-unit id="2">
                <source>Authentication credentials could not be found.</source>
                <target>Ověřovací údaje nebyly nalezeny.</target>
            </trans-unit>
            <trans-unit id="3">
                <source>Authentication request could not be processed due to a system problem.</source>
                <target>Požadavek na ověření nemohl být zpracován kvůli systémové chybě.</target>
            </trans-unit>
            <trans-unit id="4">
                <source>Invalid credentials.</source>
                <target>Neplatné přihlašovací údaje.</target>
            </trans-unit>
            <trans-unit id="5">
                <source>Cookie has already been used by someone else.</source>
                <target>Cookie již bylo použité někým jiným.</target>
            </trans-unit>
            <trans-unit id="6">
                <source>Not privileged to request the resource.</source>
                <target>Nemáte oprávnění přistupovat k prostředku.</target>
            </trans-unit>
            <trans-unit id="7">
                <source>Invalid CSRF token.</source>
                <target>Neplatný CSRF token.</target>
            </trans-unit>
            <trans-unit id="9">
                <source>No authentication provider found to support the authentication token.</source>
                <target>Poskytovatel pro ověřovací token nebyl nalezen.</target>
            </trans-unit>
            <trans-unit id="10">
                <source>No session available, it either timed out or cookies are not enabled.</source>
                <target>Session není k dispozici, vypršela její platnost, nebo jsou zakázané cookies.</target>
            </trans-unit>
            <trans-unit id="11">
                <source>No token could be found.</source>
                <target>Token nebyl nalezen.</target>
            </trans-unit>
            <trans-unit id="12">
                <source>Username could not be found.</source>
                <target>Přihlašovací jméno nebylo nalezeno.</target>
            </trans-unit>
            <trans-unit id="13">
                <source>Account has expired.</source>
                <target>Platnost účtu vypršela.</target>
            </trans-unit>
            <trans-unit id="14">
                <source>Credentials have expired.</source>
                <target>Platnost přihlašovacích údajů vypršela.</target>
            </trans-unit>
            <trans-unit id="15">
                <source>Account is disabled.</source>
                <target>Účet je zakázaný.</target>
            </trans-unit>
            <trans-unit id="16">
                <source>Account is locked.</source>
                <target>Účet je zablokovaný.</target>
            </trans-unit>
            <trans-unit id="17">
                <source>Too many failed login attempts, please try again later.</source>
                <target>Příliš mnoho nepovedených pokusů přihlášení. Zkuste to prosím později.</target>
            </trans-unit>
            <trans-unit id="18">
                <source>Invalid or expired login link.</source>
                <target>Neplatný nebo expirovaný odkaz na přihlášení.</target>
            </trans-unit>
            <trans-unit id="19">
                <source>Too many failed login attempts, please try again in %minutes% minute.</source>
                <target>Příliš mnoho neúspěšných pokusů o přihlášení, zkuste to prosím znovu za %minutes% minutu.</target>
            </trans-unit>
            <trans-unit id="20">
                <source>Too many failed login attempts, please try again in %minutes% minutes.</source>
                <target>Příliš mnoho neúspěšných pokusů o přihlášení, zkuste to prosím znovu za %minutes% minutu.|Příliš mnoho neúspěšných pokusů o přihlášení, zkuste to prosím znovu za %minutes% minuty.|Příliš mnoho neúspěšných pokusů o přihlášení, zkuste to prosím znovu za %minutes% minut.</target>
            </trans-unit>
        </body>
    </file>
</xliff>
<?xml version="1.0" encoding="utf-8"?>
<xliff xmlns="urn:oasis:names:tc:xliff:document:1.2" version="1.2">
    <file source-language="en" target-language="tl" datatype="plaintext" original="file.ext">
        <body>
            <trans-unit id="1">
                <source>An authentication exception occurred.</source>
                <target>Nagkaroon ng isang pagbubukod sa pagpapatotoo.</target>
            </trans-unit>
            <trans-unit id="2">
                <source>Authentication credentials could not be found.</source>
                <target>Hindi matagpuan ang mga kredensyal ng pagpapatotoo.</target>
            </trans-unit>
            <trans-unit id="3">
                <source>Authentication request could not be processed due to a system problem.</source>
                <target>Ang kahilingan sa pagpapatotoo ay hindi naproseso dahil sa isang problema sa system.</target>
            </trans-unit>
            <trans-unit id="4">
                <source>Invalid credentials.</source>
                <target>Di-wastong mga kredensyal.</target>
            </trans-unit>
            <trans-unit id="5">
                <source>Cookie has already been used by someone else.</source>
                <target>Ang Cookie ay ginamit na ng ibang tao.</target>
            </trans-unit>
            <trans-unit id="6">
                <source>Not privileged to request the resource.</source>
                <target>Walang pribilehiyo upang humingi ng mga bagong mapagkukunan.</target>
            </trans-unit>
            <trans-unit id="7">
                <source>Invalid CSRF token.</source>
                <target>Di-wastong token ng CSRF.</target>
            </trans-unit>
            <trans-unit id="9">
                <source>No authentication provider found to support the authentication token.</source>
                <target>Walang nahanap na provider ng pagpapatotoo upang suportahan ang token ng pagpapatotoo.</target>
            </trans-unit>
            <trans-unit id="10">
                <source>No session available, it either timed out or cookies are not enabled.</source>
                <target>Walang magagamit na session, alinman sa nag-time out o ang cookies ay hindi pinagana.</target>
            </trans-unit>
            <trans-unit id="11">
                <source>No token could be found.</source>
                <target>Walang makitang token.</target>
            </trans-unit>
            <trans-unit id="12">
                <source>Username could not be found.</source>
                <target>Hindi makita ang username.</target>
            </trans-unit>
            <trans-unit id="13">
                <source>Account has expired.</source>
                <target>Nag-expire na ang account.</target>
            </trans-unit>
            <trans-unit id="14">
                <source>Credentials have expired.</source>
                <target>Nag-expire na ang mga kredensyal.</target>
            </trans-unit>
            <trans-unit id="15">
                <source>Account is disabled.</source>
                <target>Ang account ay hindi pinagana.</target>
            </trans-unit>
            <trans-unit id="16">
                <source>Account is locked.</source>
                <target>Ang account ay naka-lock.</target>
            </trans-unit>
            <trans-unit id="17">
                <source>Too many failed login attempts, please try again later.</source>
                <target>Napakaraming nabigong mga pagtatangka sa pag-login, mangyaring subukang muli sa ibang pagkakataon.</target>
            </trans-unit>
            <trans-unit id="18">
                <source>Invalid or expired login link.</source>
                <target>Inbalido o nagexpire na ang link para makapaglogin.</target>
            </trans-unit>
            <trans-unit id="19">
                <source>Too many failed login attempts, please try again in %minutes% minute.</source>
                <target>Napakaraming nabigong mga pagtatangka sa pag-login, pakisubukan ulit matapos ang %minutes% minuto.</target>
            </trans-unit>
            <trans-unit id="20">
                <source>Too many failed login attempts, please try again in %minutes% minutes.</source>
                <target>Napakaraming nabigong mga pagtatangka sa pag-login, pakisubukan ulit matapos ang %minutes% minuto.</target>
            </trans-unit>
        </body>
    </file>
</xliff>
<?xml version="1.0" encoding="utf-8"?>
<xliff xmlns="urn:oasis:names:tc:xliff:document:1.2" version="1.2">
    <file source-language="en" target-language="my" datatype="plaintext" original="file.ext">
        <body>
            <trans-unit id="1">
                <source>An authentication exception occurred.</source>
                <target>အသုံးပြုခွင့် ခြွင်းချက်တစ်ခုဖြစ်သွားသည်။</target>
            </trans-unit>
            <trans-unit id="2">
                <source>Authentication credentials could not be found.</source>
                <target>အသုံးပြုခွင့် အထောက်အထားများ ရှာမတွေ့ပါ။</target>
            </trans-unit>
            <trans-unit id="3">
                <source>Authentication request could not be processed due to a system problem.</source>
                <target>System ပြဿနာအခက်အခဲရှိ နေပါသဖြင့် အသုံးပြုခွင့်တောင်းဆိုချက်ကို ဆောင်ရွက်၍မရ နိုင်ပါ။</target>
            </trans-unit>
            <trans-unit id="4">
                <source>Invalid credentials.</source>
                <target>သင့်လျှော်သော် အထောက်အထားမဟုတ်ပါ။</target>
            </trans-unit>
            <trans-unit id="5">
                <source>Cookie has already been used by someone else.</source>
                <target>Cookie ကို တစ်စုံတစ်ယောက်မှ အသုံးပြုပြီးဖြစ်သည်။</target>
            </trans-unit>
            <trans-unit id="6">
                <source>Not privileged to request the resource.</source>
                <target>အရင်းအမြစ်ကိုတောင်းဆိုရန်အခွင့်ထူးမရပါ။</target>
            </trans-unit>
            <trans-unit id="7">
                <source>Invalid CSRF token.</source>
                <target>သင့်လျှော်သော် CSRF token မဟုတ်ပါ။</target>
            </trans-unit>
            <trans-unit id="9">
                <source>No authentication provider found to support the authentication token.</source>
                <target>အထောက်အထားစိစစ်ခြင်းသင်္ကေတကိုပံ့ပိုးရန် မည်သည့်အထောက်အထားစိစစ်ရေး ၀န်ဆောင်မှုမှမတွေ့ပါ။</target>
            </trans-unit>
            <trans-unit id="10">
                <source>No session available, it either timed out or cookies are not enabled.</source>
                <target>Session မအားလပ်ပါ။ Session အချိန်ကုန်သွားခြင်း (သို့မဟုတ်) cookies များကိုဖွင့်ထားခြင်းမရှိပါ။</target>
            </trans-unit>
            <trans-unit id="11">
                <source>No token could be found.</source>
                <target>Toke  ရှာမတွေ့ပါ။</target>
            </trans-unit>
            <trans-unit id="12">
                <source>Username could not be found.</source>
                <target>အသုံးပြုသူအမည် ရှာဖွေတွေ့ရှိချင်းမရှိပါ။</target>
            </trans-unit>
            <trans-unit id="13">
                <source>Account has expired.</source>
                <target>အကောင့် သက်တမ်းကုန်လွန်သွားပါပြီ။</target>
            </trans-unit>
            <trans-unit id="14">
                <source>Credentials have expired.</source>
                <target>အထောက်အထားသက်တန်း ကုန်လွန်သွားပါပြီ။</target>
            </trans-unit>
            <trans-unit id="15">
                <source>Account is disabled.</source>
                <target>အကောင့်ပိတ်ထားပါသည်။</target>
            </trans-unit>
            <trans-unit id="16">
                <source>Account is locked.</source>
                <target>အကောင့် လောခ်ကျသွားပါပြီ။</target>
            </trans-unit>
            <trans-unit id="17">
                <source>Too many failed login attempts, please try again later.</source>
                <target>Login ၀င်ရန်ကြိုးစားမှုများလွန်းပါသည်၊ ကျေးဇူးပြု၍ နောက်မှထပ်ကြိုးစားပါ။</target>
            </trans-unit>
            <trans-unit id="18">
                <source>Invalid or expired login link.</source>
                <target>မသင့်လျှော်သော် (သို့မဟုတ်) သက်တန်းကုန်သော login link ဖြစ်ပါသည်။</target>
            </trans-unit>
            <trans-unit id="19">
                <source>Too many failed login attempts, please try again in %minutes% minute.</source>
                <target>Login ၀င်ရန်ကြိုးစားမှုများလွန်းပါသည်၊ ကျေးဇူးပြု၍ နောက် %minutes% မှထပ်မံကြိုးစားပါ။</target>
            </trans-unit>
            <trans-unit id="20">
                <source>Too many failed login attempts, please try again in %minutes% minutes.</source>
                <target state="needs-review-translation">ဝင်ရောက်မှု မအောင်မြင်သော ကြိုးပမ်းမှုများအတွက် တစ်ခါတည်း ပြန်လုပ်မည်။ ထပ်မံကြိုးစားကြည့်ပါ။ %minutes% မိနစ်အတွင်း|ဝင်ရောက်မှု မအောင်မြင်သော ကြိုးပမ်းမှုများအတွက် တစ်ခါတည်း ပြန်လုပ်မည်။ ထပ်မံကြိုးစားကြည့်ပါ။ %minutes% မိနစ်အတွင်း</target>
            </trans-unit>
        </body>
    </file>
</xliff>
<?xml version="1.0" encoding="utf-8"?>
<xliff xmlns="urn:oasis:names:tc:xliff:document:1.2" version="1.2">
    <file source-language="en" target-language="nb" datatype="plaintext" original="file.ext">
        <body>
            <trans-unit id="1">
                <source>An authentication exception occurred.</source>
                <target>En autentiseringsfeil har skjedd.</target>
            </trans-unit>
            <trans-unit id="2">
                <source>Authentication credentials could not be found.</source>
                <target>Påloggingsinformasjonen kunne ikke bli funnet.</target>
            </trans-unit>
            <trans-unit id="3">
                <source>Authentication request could not be processed due to a system problem.</source>
                <target>Autentiserings forespørselen kunne ikke bli prosessert grunnet en system feil.</target>
            </trans-unit>
            <trans-unit id="4">
                <source>Invalid credentials.</source>
                <target>Ugyldig påloggingsinformasjon.</target>
            </trans-unit>
            <trans-unit id="5">
                <source>Cookie has already been used by someone else.</source>
                <target>Cookie har allerede blitt brukt av noen andre.</target>
            </trans-unit>
            <trans-unit id="6">
                <source>Not privileged to request the resource.</source>
                <target>Ingen tilgang til å be om gitt ressurs.</target>
            </trans-unit>
            <trans-unit id="7">
                <source>Invalid CSRF token.</source>
                <target>Ugyldig CSRF token.</target>
            </trans-unit>
            <trans-unit id="9">
                <source>No authentication provider found to support the authentication token.</source>
                <target>Ingen autentiserings tilbyder funnet som støtter gitt autentiserings token.</target>
            </trans-unit>
            <trans-unit id="10">
                <source>No session available, it either timed out or cookies are not enabled.</source>
                <target>Ingen sesjon tilgjengelig, sesjonen er enten utløpt eller cookies ikke skrudd på.</target>
            </trans-unit>
            <trans-unit id="11">
                <source>No token could be found.</source>
                <target>Ingen token kunne bli funnet.</target>
            </trans-unit>
            <trans-unit id="12">
                <source>Username could not be found.</source>
                <target>Brukernavn kunne ikke bli funnet.</target>
            </trans-unit>
            <trans-unit id="13">
                <source>Account has expired.</source>
                <target>Brukerkonto har utgått.</target>
            </trans-unit>
            <trans-unit id="14">
                <source>Credentials have expired.</source>
                <target>Påloggingsinformasjon har utløpt.</target>
            </trans-unit>
            <trans-unit id="15">
                <source>Account is disabled.</source>
                <target>Brukerkonto er deaktivert.</target>
            </trans-unit>
            <trans-unit id="16">
                <source>Account is locked.</source>
                <target>Brukerkonto er sperret.</target>
            </trans-unit>
            <trans-unit id="17">
                <source>Too many failed login attempts, please try again later.</source>
                <target>For mange mislykkede påloggingsforsøk. Prøv igjen senere.</target>
            </trans-unit>
            <trans-unit id="18">
                <source>Invalid or expired login link.</source>
                <target>Ugyldig eller utløpt påloggingskobling.</target>
            </trans-unit>
            <trans-unit id="19">
                <source>Too many failed login attempts, please try again in %minutes% minute.</source>
                <target>For mange mislykkede påloggingsforsøk, prøv igjen om %minutes% minutt.</target>
            </trans-unit>
            <trans-unit id="20">
                <source>Too many failed login attempts, please try again in %minutes% minutes.</source>
                <target>For mange mislykkede påloggingsforsøk, prøv igjen om %minutes% minutter.</target>
            </trans-unit>
        </body>
    </file>
</xliff>
<?xml version="1.0" encoding="utf-8"?>
<xliff xmlns="urn:oasis:names:tc:xliff:document:1.2" version="1.2">
    <file source-language="en" target-language="mn" datatype="plaintext" original="file.ext">
        <body>
            <trans-unit id="1">
                <source>An authentication exception occurred.</source>
                <target>Нэвтрэх хүсэлтийн алдаа гарав.</target>
            </trans-unit>
            <trans-unit id="2">
                <source>Authentication credentials could not be found.</source>
                <target>Нэвтрэх эрхийн мэдээлэл олдсонгүй.</target>
            </trans-unit>
            <trans-unit id="3">
                <source>Authentication request could not be processed due to a system problem.</source>
                <target>Системийн алдаанаас болон нэвтрэх хүсэлтийг гүйцэтгэх боломжгүй байна.</target>
            </trans-unit>
            <trans-unit id="4">
                <source>Invalid credentials.</source>
                <target>Буруу нэвтрэх эрхийн мэдээлэл.</target>
            </trans-unit>
            <trans-unit id="5">
                <source>Cookie has already been used by someone else.</source>
                <target>Күүки файлыг аль хэдийн өөр хүн хэрэглэж байна.</target>
            </trans-unit>
            <trans-unit id="6">
                <source>Not privileged to request the resource.</source>
                <target>Энэхүү мэдээллийг авах эрх хүрэхгүй байна.</target>
            </trans-unit>
            <trans-unit id="7">
                <source>Invalid CSRF token.</source>
                <target>Тохиромжгүй CSRF токен.</target>
            </trans-unit>
            <trans-unit id="9">
                <source>No authentication provider found to support the authentication token.</source>
                <target>Нэвтрэх токенг дэмжих нэвтрэх эрхийн хангагч олдсонгүй.</target>
            </trans-unit>
            <trans-unit id="10">
                <source>No session available, it either timed out or cookies are not enabled.</source>
                <target>Хэрэглэгчийн session олдсонгүй, хугацаа нь дууссан эсвэл күүки идэвхижүүлээгүй байна.</target>
            </trans-unit>
            <trans-unit id="11">
                <source>No token could be found.</source>
                <target>Токен олдсонгүй.</target>
            </trans-unit>
            <trans-unit id="12">
                <source>Username could not be found.</source>
                <target>Нэвтрэх нэр олсонгүй.</target>
            </trans-unit>
            <trans-unit id="13">
                <source>Account has expired.</source>
                <target>Бүртгэлийн хугацаа дууссан байна.</target>
            </trans-unit>
            <trans-unit id="14">
                <source>Credentials have expired.</source>
                <target>Нэвтрэх эрхийн хугацаа дууссан байна.</target>
            </trans-unit>
            <trans-unit id="15">
                <source>Account is disabled.</source>
                <target>Бүртгэлийг хаасан байна.</target>
            </trans-unit>
            <trans-unit id="16">
                <source>Account is locked.</source>
                <target>Бүртгэлийг цоожилсон байна.</target>
            </trans-unit>
            <trans-unit id="17">
                <source>Too many failed login attempts, please try again later.</source>
                <target>Хэтэрхий олон амжилтгүй оролдлого, түр хүлээгээд дахин оролдоно уу.</target>
            </trans-unit>
            <trans-unit id="18">
                <source>Invalid or expired login link.</source>
                <target>Буруу эсвэл хугацаа нь дууссан нэвтрэх зам.</target>
            </trans-unit>
            <trans-unit id="19">
                <source>Too many failed login attempts, please try again in %minutes% minute.</source>
                <target state="needs-review-translation">Нэвтрэх оролдлого ихээр амжилтгүй болсон, %minutes% минутын дараа дахин оролдоно уу.</target>
            </trans-unit>
            <trans-unit id="20">
                <source>Too many failed login attempts, please try again in %minutes% minutes.</source>
                <target state="needs-review-translation">Хэт олон бүтэлгүй нэвтрэх оролдлого, %minutes% минутын дараа дахин оролдоно уу.</target>
            </trans-unit>
        </body>
    </file>
</xliff>
<?xml version="1.0" encoding="utf-8"?>
<xliff xmlns="urn:oasis:names:tc:xliff:document:1.2" version="1.2">
    <file source-language="en" target-language="az" datatype="plaintext" original="file.ext">
        <body>
            <trans-unit id="1">
                <source>An authentication exception occurred.</source>
                <target>Doğrulama istisnası baş verdi.</target>
            </trans-unit>
            <trans-unit id="2">
                <source>Authentication credentials could not be found.</source>
                <target>Doğrulama məlumatları tapılmadı.</target>
            </trans-unit>
            <trans-unit id="3">
                <source>Authentication request could not be processed due to a system problem.</source>
                <target>Sistem xətası səbəbilə doğrulama istəyi emal edilə bilmədi.</target>
            </trans-unit>
            <trans-unit id="4">
                <source>Invalid credentials.</source>
                <target>Yanlış məlumat.</target>
            </trans-unit>
            <trans-unit id="5">
                <source>Cookie has already been used by someone else.</source>
                <target>Kuki başqası tərəfindən istifadə edilib.</target>
            </trans-unit>
            <trans-unit id="6">
                <source>Not privileged to request the resource.</source>
                <target>Resurs istəyi üçün imtiyaz yoxdur.</target>
            </trans-unit>
            <trans-unit id="7">
                <source>Invalid CSRF token.</source>
                <target>Yanlış CSRF nişanı.</target>
            </trans-unit>
            <trans-unit id="9">
                <source>No authentication provider found to support the authentication token.</source>
                <target>Doğrulama nişanını dəstəkləyəcək provayder tapılmadı.</target>
            </trans-unit>
            <trans-unit id="10">
                <source>No session available, it either timed out or cookies are not enabled.</source>
                <target>Uyğun seans yoxdur, vaxtı keçib və ya kuki aktiv deyil.</target>
            </trans-unit>
            <trans-unit id="11">
                <source>No token could be found.</source>
                <target>Nişan tapılmadı.</target>
            </trans-unit>
            <trans-unit id="12">
                <source>Username could not be found.</source>
                <target>İstifadəçi adı tapılmadı.</target>
            </trans-unit>
            <trans-unit id="13">
                <source>Account has expired.</source>
                <target>Hesabın istifadə müddəti bitib.</target>
            </trans-unit>
            <trans-unit id="14">
                <source>Credentials have expired.</source>
                <target>Məlumatların istifadə müddəti bitib.</target>
            </trans-unit>
            <trans-unit id="15">
                <source>Account is disabled.</source>
                <target>Hesab qeyri-aktiv edilib.</target>
            </trans-unit>
            <trans-unit id="16">
                <source>Account is locked.</source>
                <target>Hesab kilitlənib.</target>
            </trans-unit>
            <trans-unit id="17">
                <source>Too many failed login attempts, please try again later.</source>
                <target>Çoxlu uğursuz giriş təşəbbüsü, zəhmət olmasa daha sonra yeniden yoxlayın.</target>
            </trans-unit>
            <trans-unit id="18">
                <source>Invalid or expired login link.</source>
                <target>Yanlış və ya müddəti keçmiş giriş keçidi.</target>
            </trans-unit>
            <trans-unit id="19">
                <source>Too many failed login attempts, please try again in %minutes% minute.</source>
                <target>Həddindən artıq uğursuz giriş cəhdi, lütfən %minutes% dəqiqə ərzində yenidən yoxlayın.</target>
            </trans-unit>
            <trans-unit id="20">
                <source>Too many failed login attempts, please try again in %minutes% minutes.</source>
                <target>Çox sayda uğursuz giriş cəhdi, zəhmət olmasa %minutes% dəqiqə sonra yenidən cəhd edin.|Çox sayda uğursuz giriş cəhdi, zəhmət olmasa %minutes% dəqiqə sonra yenidən cəhd edin.</target>
            </trans-unit>
        </body>
    </file>
</xliff>
<?xml version="1.0" encoding="utf-8"?>
<xliff xmlns="urn:oasis:names:tc:xliff:document:1.2" version="1.2">
    <file source-language="en" target-language="eu" datatype="plaintext" original="file.ext">
        <body>
            <trans-unit id="1">
                <source>An authentication exception occurred.</source>
                <target>Autentifikazio-errorea gertatu da.</target>
            </trans-unit>
            <trans-unit id="2">
                <source>Authentication credentials could not be found.</source>
                <target>Ez dira aurkitu autentifikazio-kredentzialak.</target>
            </trans-unit>
            <trans-unit id="3">
                <source>Authentication request could not be processed due to a system problem.</source>
                <target>Ezin izan da autentifikazio-eskaera prozesatu, sistema-arazo bat gertatu da eta.</target>
            </trans-unit>
            <trans-unit id="4">
                <source>Invalid credentials.</source>
                <target>Kredentzialak okerrak dira.</target>
            </trans-unit>
            <trans-unit id="5">
                <source>Cookie has already been used by someone else.</source>
                <target>Dagoeneko beste pertsona batek erabili du cookiea.</target>
            </trans-unit>
            <trans-unit id="6">
                <source>Not privileged to request the resource.</source>
                <target>Ez duzu baliabidea eskatzeko aukerarik.</target>
            </trans-unit>
            <trans-unit id="7">
                <source>Invalid CSRF token.</source>
                <target>CSRF tokena okerra da.</target>
            </trans-unit>
            <trans-unit id="9">
                <source>No authentication provider found to support the authentication token.</source>
                <target>Ez da aurkitu autentifikazio-tokena eutsi dezakeen autentifikazio-hornitzailerik.</target>
            </trans-unit>
            <trans-unit id="10">
                <source>No session available, it either timed out or cookies are not enabled.</source>
                <target>Ez dago saiorik erabilgarri, iraungi egin da edo cookieak ez daude gaituta.</target>
            </trans-unit>
            <trans-unit id="11">
                <source>No token could be found.</source>
                <target>Ez da tokenik aurkitu.</target>
            </trans-unit>
            <trans-unit id="12">
                <source>Username could not be found.</source>
                <target>Ez da erabiltzaile-izena aurkitu.</target>
            </trans-unit>
            <trans-unit id="13">
                <source>Account has expired.</source>
                <target>Kontua iraungi da.</target>
            </trans-unit>
            <trans-unit id="14">
                <source>Credentials have expired.</source>
                <target>Kredentzialak iraungi dira.</target>
            </trans-unit>
            <trans-unit id="15">
                <source>Account is disabled.</source>
                <target>Kontua desgaituta dago.</target>
            </trans-unit>
            <trans-unit id="16">
                <source>Account is locked.</source>
                <target>Kontua blokeatuta dago.</target>
            </trans-unit>
            <trans-unit id="17">
                <source>Too many failed login attempts, please try again later.</source>
                <target>Saioa hasteko saio huts gehiegi, saiatu berriro geroago.</target>
            </trans-unit>
            <trans-unit id="18">
                <source>Invalid or expired login link.</source>
                <target>Sartzeko esteka baliogabea edo iraungia.</target>
            </trans-unit>
            <trans-unit id="19">
                <source>Too many failed login attempts, please try again in %minutes% minute.</source>
                <target>Saioa hasteko huts gehiegi egin dira, saiatu berriro minutu %minutes% geroago.</target>
            </trans-unit>
            <trans-unit id="20">
                <source>Too many failed login attempts, please try again in %minutes% minutes.</source>
                <target state="needs-review-translation">Saioa hasteko saiakera huts gehiegi, saiatu berriro %minutes% minututan.</target>
            </trans-unit>
        </body>
    </file>
</xliff>
<?xml version="1.0" encoding="utf-8"?>
<xliff xmlns="urn:oasis:names:tc:xliff:document:1.2" version="1.2">
    <file source-language="en" target-language="he" datatype="plaintext" original="file.ext">
        <body>
            <trans-unit id="1">
                <source>An authentication exception occurred.</source>
                <target>התרחשה שגיאה באימות.</target>
            </trans-unit>
            <trans-unit id="2">
                <source>Authentication credentials could not be found.</source>
                <target>פרטי הזיהוי לא נמצאו.</target>
            </trans-unit>
            <trans-unit id="3">
                <source>Authentication request could not be processed due to a system problem.</source>
                <target>לא ניתן היה לעבד את בקשת האימות בגלל בעיית מערכת.</target>
            </trans-unit>
            <trans-unit id="4">
                <source>Invalid credentials.</source>
                <target>שם משתמש או סיסמא שגויים.</target>
            </trans-unit>
            <trans-unit id="5">
                <source>Cookie has already been used by someone else.</source>
                <target>עוגיה כבר שומשה על ידי מישהו אחר.</target>
            </trans-unit>
            <trans-unit id="6">
                <source>Not privileged to request the resource.</source>
                <target>אין הרשאה מתאימה.</target>
            </trans-unit>
            <trans-unit id="7">
                <source>Invalid CSRF token.</source>
                <target>אסימון CSRF לא חוקי.</target>
            </trans-unit>
            <trans-unit id="9">
                <source>No authentication provider found to support the authentication token.</source>
                <target>לא נמצא ספק אימות המתאים לבקשה.</target>
            </trans-unit>
            <trans-unit id="10">
                <source>No session available, it either timed out or cookies are not enabled.</source>
                <target>אין מפגש זמין, תם הזמן הקצוב או שהעוגיות אינן מופעלות.</target>
            </trans-unit>
            <trans-unit id="11">
                <source>No token could be found.</source>
                <target>אסימון לא נמצא.</target>
            </trans-unit>
            <trans-unit id="12">
                <source>Username could not be found.</source>
                <target>שם משתמש לא נמצא.</target>
            </trans-unit>
            <trans-unit id="13">
                <source>Account has expired.</source>
                <target>החשבון פג תוקף.</target>
            </trans-unit>
            <trans-unit id="14">
                <source>Credentials have expired.</source>
                <target>פרטי התחברות פקעו תוקף.</target>
            </trans-unit>
            <trans-unit id="15">
                <source>Account is disabled.</source>
                <target>החשבון מבוטל.</target>
            </trans-unit>
            <trans-unit id="16">
                <source>Account is locked.</source>
                <target>החשבון נעול.</target>
            </trans-unit>
            <trans-unit id="17">
                <source>Too many failed login attempts, please try again later.</source>
                <target>יותר מדי ניסיונות כניסה כושלים, אנא נסה שוב מאוחר יותר.</target>
            </trans-unit>
            <trans-unit id="18">
                <source>Invalid or expired login link.</source>
                <target>קישור כניסה לא חוקי או שפג תוקפו.</target>
            </trans-unit>
            <trans-unit id="19">
                <source>Too many failed login attempts, please try again in %minutes% minute.</source>
                <target>יותר מדי ניסיונות כניסה כושלים, אנא נסה שוב בעוד %minutes% דקה.</target>
            </trans-unit>
            <trans-unit id="20">
                <source>Too many failed login attempts, please try again in %minutes% minutes.</source>
                <target>יותר מדי ניסיונות כניסה כושלים, אנא נסה שוב בעוד %minutes% דקות.</target>
            </trans-unit>
        </body>
    </file>
</xliff>
<?xml version="1.0" encoding="utf-8"?>
<xliff xmlns="urn:oasis:names:tc:xliff:document:1.2" version="1.2">
    <file source-language="en" target-language="hr" datatype="plaintext" original="file.ext">
        <body>
            <trans-unit id="1">
                <source>An authentication exception occurred.</source>
                <target>Dogodila se autentifikacijske iznimka.</target>
            </trans-unit>
            <trans-unit id="2">
                <source>Authentication credentials could not be found.</source>
                <target>Autentifikacijski podaci nisu pronađeni.</target>
            </trans-unit>
            <trans-unit id="3">
                <source>Authentication request could not be processed due to a system problem.</source>
                <target>Autentifikacijski zahtjev nije moguće provesti uslijed sistemskog problema.</target>
            </trans-unit>
            <trans-unit id="4">
                <source>Invalid credentials.</source>
                <target>Neispravni akreditacijski podaci.</target>
            </trans-unit>
            <trans-unit id="5">
                <source>Cookie has already been used by someone else.</source>
                <target>Cookie je već netko drugi iskoristio.</target>
            </trans-unit>
            <trans-unit id="6">
                <source>Not privileged to request the resource.</source>
                <target>Nemate privilegije zahtijevati resurs.</target>
            </trans-unit>
            <trans-unit id="7">
                <source>Invalid CSRF token.</source>
                <target>Neispravan CSRF token.</target>
            </trans-unit>
            <trans-unit id="9">
                <source>No authentication provider found to support the authentication token.</source>
                <target>Nije pronađen autentifikacijski provider koji bi podržao autentifikacijski token.</target>
            </trans-unit>
            <trans-unit id="10">
                <source>No session available, it either timed out or cookies are not enabled.</source>
                <target>Sesija nije dostupna, ili je istekla ili cookies nisu omogućeni.</target>
            </trans-unit>
            <trans-unit id="11">
                <source>No token could be found.</source>
                <target>Token nije pronađen.</target>
            </trans-unit>
            <trans-unit id="12">
                <source>Username could not be found.</source>
                <target>Korisničko ime nije pronađeno.</target>
            </trans-unit>
            <trans-unit id="13">
                <source>Account has expired.</source>
                <target>Račun je isteko.</target>
            </trans-unit>
            <trans-unit id="14">
                <source>Credentials have expired.</source>
                <target>Akreditacijski podaci su istekli.</target>
            </trans-unit>
            <trans-unit id="15">
                <source>Account is disabled.</source>
                <target>Račun je onemogućen.</target>
            </trans-unit>
            <trans-unit id="16">
                <source>Account is locked.</source>
                <target>Račun je zaključan.</target>
            </trans-unit>
            <trans-unit id="17">
                <source>Too many failed login attempts, please try again later.</source>
                <target>Previše neuspjelih pokušaja prijave, molim pokušajte ponovo kasnije.</target>
            </trans-unit>
            <trans-unit id="18">
                <source>Invalid or expired login link.</source>
                <target>Link za prijavu je isteako ili je neispravan.</target>
            </trans-unit>
            <trans-unit id="19">
                <source>Too many failed login attempts, please try again in %minutes% minute.</source>
                <target>Previše neuspjelih pokušaja prijave, molim pokušajte ponovo za %minutes% minutu.</target>
            </trans-unit>
            <trans-unit id="20">
                <source>Too many failed login attempts, please try again in %minutes% minutes.</source>
                <target>Previše neuspjelih pokušaja prijave, pokušajte ponovo za %minutes% minutu.|Previše neuspjelih pokušaja prijave, pokušajte ponovo za %minutes% minute.|Previše neuspjelih pokušaja prijave, pokušajte ponovo za %minutes% minuta.</target>
            </trans-unit>
        </body>
    </file>
</xliff>
<?xml version="1.0" encoding="utf-8"?>
<xliff xmlns="urn:oasis:names:tc:xliff:document:1.2" version="1.2">
    <file source-language="en" target-language="pt" datatype="plaintext" original="file.ext">
        <body>
            <trans-unit id="1">
                <source>An authentication exception occurred.</source>
                <target>Ocorreu uma exceção durante a autenticação.</target>
            </trans-unit>
            <trans-unit id="2">
                <source>Authentication credentials could not be found.</source>
                <target>As credenciais de autenticação não foram encontradas.</target>
            </trans-unit>
            <trans-unit id="3">
                <source>Authentication request could not be processed due to a system problem.</source>
                <target>A autenticação não foi concluída devido a um problema no sistema.</target>
            </trans-unit>
            <trans-unit id="4">
                <source>Invalid credentials.</source>
                <target>Credenciais inválidas.</target>
            </trans-unit>
            <trans-unit id="5">
                <source>Cookie has already been used by someone else.</source>
                <target>Este cookie já está em uso.</target>
            </trans-unit>
            <trans-unit id="6">
                <source>Not privileged to request the resource.</source>
                <target>Sem privilégios para solicitar este recurso.</target>
            </trans-unit>
            <trans-unit id="7">
                <source>Invalid CSRF token.</source>
                <target>Token CSRF inválido.</target>
            </trans-unit>
            <trans-unit id="9">
                <source>No authentication provider found to support the authentication token.</source>
                <target>Nenhum fornecedor de autenticação encontrado para suportar o token de autenticação.</target>
            </trans-unit>
            <trans-unit id="10">
                <source>No session available, it either timed out or cookies are not enabled.</source>
                <target>Nenhuma sessão disponível, esta expirou ou os cookies estão desativados.</target>
            </trans-unit>
            <trans-unit id="11">
                <source>No token could be found.</source>
                <target>O token não foi encontrado.</target>
            </trans-unit>
            <trans-unit id="12">
                <source>Username could not be found.</source>
                <target>Nome de usuário não encontrado.</target>
            </trans-unit>
            <trans-unit id="13">
                <source>Account has expired.</source>
                <target>A conta expirou.</target>
            </trans-unit>
            <trans-unit id="14">
                <source>Credentials have expired.</source>
                <target>As credenciais expiraram.</target>
            </trans-unit>
            <trans-unit id="15">
                <source>Account is disabled.</source>
                <target>Conta desativada.</target>
            </trans-unit>
            <trans-unit id="16">
                <source>Account is locked.</source>
                <target>A conta está bloqueada.</target>
            </trans-unit>
            <trans-unit id="17">
                <source>Too many failed login attempts, please try again later.</source>
                <target>Muitas tentativas de login sem sucesso, por favor, tente mais tarde.</target>
            </trans-unit>
            <trans-unit id="18">
                <source>Invalid or expired login link.</source>
                <target>Ligação de login inválida ou expirada.</target>
            </trans-unit>
            <trans-unit id="19">
                <source>Too many failed login attempts, please try again in %minutes% minute.</source>
                <target>Muitas tentativas de login sem sucesso, por favor, tente novamente novamente em 1 minuto.</target>
            </trans-unit>
            <trans-unit id="20">
                <source>Too many failed login attempts, please try again in %minutes% minutes.</source>
                <target>Muitas tentativas de login sem sucesso, por favor, tente novamente em %minutes% minutos.</target>
            </trans-unit>
        </body>
    </file>
</xliff>
<?xml version="1.0" encoding="utf-8"?>
<xliff xmlns="urn:oasis:names:tc:xliff:document:1.2" version="1.2">
    <file source-language="en" target-language="et" datatype="plaintext" original="file.ext">
        <body>
            <trans-unit id="1">
                <source>An authentication exception occurred.</source>
                <target>Autentimisel juhtus ootamatu viga.</target>
            </trans-unit>
            <trans-unit id="2">
                <source>Authentication credentials could not be found.</source>
                <target>Autentimisandmeid ei leitud.</target>
            </trans-unit>
            <trans-unit id="3">
                <source>Authentication request could not be processed due to a system problem.</source>
                <target>Autentimispäring ei õnnestunud süsteemi probleemi tõttu.</target>
            </trans-unit>
            <trans-unit id="4">
                <source>Invalid credentials.</source>
                <target>Vigased autentimisandmed.</target>
            </trans-unit>
            <trans-unit id="5">
                <source>Cookie has already been used by someone else.</source>
                <target>Küpsis on juba kellegi teise poolt kasutuses.</target>
            </trans-unit>
            <trans-unit id="6">
                <source>Not privileged to request the resource.</source>
                <target>Ressursi pärimiseks pole piisavalt õiguseid.</target>
            </trans-unit>
            <trans-unit id="7">
                <source>Invalid CSRF token.</source>
                <target>Vigane CSRF märgis.</target>
            </trans-unit>
            <trans-unit id="9">
                <source>No authentication provider found to support the authentication token.</source>
                <target>Ei leitud sobivat autentimismeetodit, mis toetaks autentimismärgist.</target>
            </trans-unit>
            <trans-unit id="10">
                <source>No session available, it either timed out or cookies are not enabled.</source>
                <target>Seanss puudub, see on kas aegunud või pole küpsised lubatud.</target>
            </trans-unit>
            <trans-unit id="11">
                <source>No token could be found.</source>
                <target>Identsustõendit ei leitud.</target>
            </trans-unit>
            <trans-unit id="12">
                <source>Username could not be found.</source>
                <target>Kasutajanime ei leitud.</target>
            </trans-unit>
            <trans-unit id="13">
                <source>Account has expired.</source>
                <target>Kasutajakonto on aegunud.</target>
            </trans-unit>
            <trans-unit id="14">
                <source>Credentials have expired.</source>
                <target>Autentimistunnused on aegunud.</target>
            </trans-unit>
            <trans-unit id="15">
                <source>Account is disabled.</source>
                <target>Kasutajakonto on keelatud.</target>
            </trans-unit>
            <trans-unit id="16">
                <source>Account is locked.</source>
                <target>Kasutajakonto on lukustatud.</target>
            </trans-unit>
            <trans-unit id="17">
                <source>Too many failed login attempts, please try again later.</source>
                <target>Liiga palju ebaõnnestunud autentimise katseid, palun proovi hiljem uuesti.</target>
            </trans-unit>
            <trans-unit id="18">
                <source>Invalid or expired login link.</source>
                <target>Vigane või aegunud sisselogimise link.</target>
            </trans-unit>
            <trans-unit id="19">
                <source>Too many failed login attempts, please try again in %minutes% minute.</source>
                <target>Liiga palju ebaõnnestunud autentimise katseid, palun proovi uuesti %minutes% minuti pärast.</target>
            </trans-unit>
            <trans-unit id="20">
                <source>Too many failed login attempts, please try again in %minutes% minutes.</source>
                <target>Liiga palju nurjunud sisselogimiskatseid, proovige uuesti %minutes% minuti pärast.</target>
            </trans-unit>
        </body>
    </file>
</xliff>
<?xml version="1.0" encoding="utf-8"?>
<xliff xmlns="urn:oasis:names:tc:xliff:document:1.2" version="1.2">
    <file source-language="en" target-language="de" datatype="plaintext" original="file.ext">
        <body>
            <trans-unit id="1">
                <source>An authentication exception occurred.</source>
                <target>Es ist ein Fehler bei der Authentifikation aufgetreten.</target>
            </trans-unit>
            <trans-unit id="2">
                <source>Authentication credentials could not be found.</source>
                <target>Es konnten keine Zugangsdaten gefunden werden.</target>
            </trans-unit>
            <trans-unit id="3">
                <source>Authentication request could not be processed due to a system problem.</source>
                <target>Die Authentifikation konnte wegen eines Systemproblems nicht bearbeitet werden.</target>
            </trans-unit>
            <trans-unit id="4">
                <source>Invalid credentials.</source>
                <target>Fehlerhafte Zugangsdaten.</target>
            </trans-unit>
            <trans-unit id="5">
                <source>Cookie has already been used by someone else.</source>
                <target>Cookie wurde bereits von jemand anderem verwendet.</target>
            </trans-unit>
            <trans-unit id="6">
                <source>Not privileged to request the resource.</source>
                <target>Keine Rechte, um die Ressource anzufragen.</target>
            </trans-unit>
            <trans-unit id="7">
                <source>Invalid CSRF token.</source>
                <target>Ungültiges CSRF-Token.</target>
            </trans-unit>
            <trans-unit id="9">
                <source>No authentication provider found to support the authentication token.</source>
                <target>Es wurde kein Authentifizierungs-Provider gefunden, der das Authentifizierungs-Token unterstützt.</target>
            </trans-unit>
            <trans-unit id="10">
                <source>No session available, it either timed out or cookies are not enabled.</source>
                <target>Keine Session verfügbar, entweder ist diese abgelaufen oder Cookies sind nicht aktiviert.</target>
            </trans-unit>
            <trans-unit id="11">
                <source>No token could be found.</source>
                <target>Es wurde kein Token gefunden.</target>
            </trans-unit>
            <trans-unit id="12">
                <source>Username could not be found.</source>
                <target>Der Benutzername wurde nicht gefunden.</target>
            </trans-unit>
            <trans-unit id="13">
                <source>Account has expired.</source>
                <target>Der Account ist abgelaufen.</target>
            </trans-unit>
            <trans-unit id="14">
                <source>Credentials have expired.</source>
                <target>Die Zugangsdaten sind abgelaufen.</target>
            </trans-unit>
            <trans-unit id="15">
                <source>Account is disabled.</source>
                <target>Der Account ist deaktiviert.</target>
            </trans-unit>
            <trans-unit id="16">
                <source>Account is locked.</source>
                <target>Der Account ist gesperrt.</target>
            </trans-unit>
            <trans-unit id="17">
                <source>Too many failed login attempts, please try again later.</source>
                <target>Zu viele fehlgeschlagene Anmeldeversuche, bitte versuchen Sie es später noch einmal.</target>
            </trans-unit>
            <trans-unit id="18">
                <source>Invalid or expired login link.</source>
                <target>Ungültiger oder abgelaufener Anmelde-Link.</target>
            </trans-unit>
            <trans-unit id="19">
                <source>Too many failed login attempts, please try again in %minutes% minute.</source>
                <target>Zu viele fehlgeschlagene Anmeldeversuche, bitte versuchen Sie es in einer Minute noch einmal.</target>
            </trans-unit>
            <trans-unit id="20">
                <source>Too many failed login attempts, please try again in %minutes% minutes.</source>
                <target>Zu viele fehlgeschlagene Anmeldeversuche, bitte versuchen Sie es in %minutes% Minuten noch einmal.</target>
            </trans-unit>
        </body>
    </file>
</xliff>
<?xml version="1.0" encoding="utf-8"?>
<xliff xmlns="urn:oasis:names:tc:xliff:document:1.2" version="1.2">
    <file source-language="en" target-language="sl" datatype="plaintext" original="file.ext">
        <body>
            <trans-unit id="1">
                <source>An authentication exception occurred.</source>
                <target>Prišlo je do izjeme pri preverjanju avtentikacije.</target>
            </trans-unit>
            <trans-unit id="2">
                <source>Authentication credentials could not be found.</source>
                <target>Poverilnic za avtentikacijo ni bilo mogoče najti.</target>
            </trans-unit>
            <trans-unit id="3">
                <source>Authentication request could not be processed due to a system problem.</source>
                <target>Zahteve za avtentikacijo ni bilo mogoče izvesti zaradi sistemske težave.</target>
            </trans-unit>
            <trans-unit id="4">
                <source>Invalid credentials.</source>
                <target>Neveljavne pravice.</target>
            </trans-unit>
            <trans-unit id="5">
                <source>Cookie has already been used by someone else.</source>
                <target>Piškotek je uporabil že nekdo drug.</target>
            </trans-unit>
            <trans-unit id="6">
                <source>Not privileged to request the resource.</source>
                <target>Nimate privilegijev za zahtevani vir.</target>
            </trans-unit>
            <trans-unit id="7">
                <source>Invalid CSRF token.</source>
                <target>Neveljaven CSRF žeton.</target>
            </trans-unit>
            <trans-unit id="9">
                <source>No authentication provider found to support the authentication token.</source>
                <target>Ponudnika avtentikacije za podporo prijavnega žetona ni bilo mogoče najti.</target>
            </trans-unit>
            <trans-unit id="10">
                <source>No session available, it either timed out or cookies are not enabled.</source>
                <target>Seja ni na voljo, ali je potekla ali pa piškotki niso omogočeni.</target>
            </trans-unit>
            <trans-unit id="11">
                <source>No token could be found.</source>
                <target>Žetona ni bilo mogoče najti.</target>
            </trans-unit>
            <trans-unit id="12">
                <source>Username could not be found.</source>
                <target>Uporabniškega imena ni bilo mogoče najti.</target>
            </trans-unit>
            <trans-unit id="13">
                <source>Account has expired.</source>
                <target>Račun je potekel.</target>
            </trans-unit>
            <trans-unit id="14">
                <source>Credentials have expired.</source>
                <target>Poverilnice so potekle.</target>
            </trans-unit>
            <trans-unit id="15">
                <source>Account is disabled.</source>
                <target>Račun je onemogočen.</target>
            </trans-unit>
            <trans-unit id="16">
                <source>Account is locked.</source>
                <target>Račun je zaklenjen.</target>
            </trans-unit>
            <trans-unit id="17">
                <source>Too many failed login attempts, please try again later.</source>
                <target>Preveč neuspelih poskusov prijave, poskusite znova pozneje.</target>
            </trans-unit>
            <trans-unit id="18">
                <source>Invalid or expired login link.</source>
                <target>Neveljavna ali potekla povezava prijave.</target>
            </trans-unit>
            <trans-unit id="19">
                <source>Too many failed login attempts, please try again in %minutes% minute.</source>
                <target>Preveč neuspelih poskusov prijave, poskusite znova čez %minutes% minuto.</target>
            </trans-unit>
            <trans-unit id="20">
                <source>Too many failed login attempts, please try again in %minutes% minutes.</source>
                <target>Preveč neuspešnih poskusov prijave, poskusite znova čez %minutes% minuto.|Preveč neuspešnih poskusov prijave, poskusite znova čez %minutes% minuti.|Preveč neuspešnih poskusov prijave, poskusite znova čez %minutes% minute.|Preveč neuspešnih poskusov prijave, poskusite znova čez %minutes% minut.</target>
            </trans-unit>
        </body>
    </file>
</xliff>
<?xml version="1.0" encoding="utf-8"?>
<xliff xmlns="urn:oasis:names:tc:xliff:document:1.2" version="1.2">
    <file source-language="en" target-language="it" datatype="plaintext" original="file.ext">
        <body>
            <trans-unit id="1">
                <source>An authentication exception occurred.</source>
                <target>Si è verificato un errore di autenticazione.</target>
            </trans-unit>
            <trans-unit id="2">
                <source>Authentication credentials could not be found.</source>
                <target>Impossibile trovare le credenziali di autenticazione.</target>
            </trans-unit>
            <trans-unit id="3">
                <source>Authentication request could not be processed due to a system problem.</source>
                <target>La richiesta di autenticazione non può essere processata a causa di un errore di sistema.</target>
            </trans-unit>
            <trans-unit id="4">
                <source>Invalid credentials.</source>
                <target>Credenziali non valide.</target>
            </trans-unit>
            <trans-unit id="5">
                <source>Cookie has already been used by someone else.</source>
                <target>Il cookie è già stato usato da qualcun altro.</target>
            </trans-unit>
            <trans-unit id="6">
                <source>Not privileged to request the resource.</source>
                <target>Non hai i privilegi per richiedere questa risorsa.</target>
            </trans-unit>
            <trans-unit id="7">
                <source>Invalid CSRF token.</source>
                <target>CSRF token non valido.</target>
            </trans-unit>
            <trans-unit id="9">
                <source>No authentication provider found to support the authentication token.</source>
                <target>Non è stato trovato un valido fornitore di autenticazione per supportare il token.</target>
            </trans-unit>
            <trans-unit id="10">
                <source>No session available, it either timed out or cookies are not enabled.</source>
                <target>Nessuna sessione disponibile, può essere scaduta o i cookie non sono abilitati.</target>
            </trans-unit>
            <trans-unit id="11">
                <source>No token could be found.</source>
                <target>Nessun token trovato.</target>
            </trans-unit>
            <trans-unit id="12">
                <source>Username could not be found.</source>
                <target>Username non trovato.</target>
            </trans-unit>
            <trans-unit id="13">
                <source>Account has expired.</source>
                <target>Account scaduto.</target>
            </trans-unit>
            <trans-unit id="14">
                <source>Credentials have expired.</source>
                <target>Credenziali scadute.</target>
            </trans-unit>
            <trans-unit id="15">
                <source>Account is disabled.</source>
                <target>L'account è disabilitato.</target>
            </trans-unit>
            <trans-unit id="16">
                <source>Account is locked.</source>
                <target>L'account è bloccato.</target>
            </trans-unit>
            <trans-unit id="17">
                <source>Too many failed login attempts, please try again later.</source>
                <target>Troppi tentativi di login falliti, riprova tra un po'.</target>
            </trans-unit>
            <trans-unit id="18">
                <source>Invalid or expired login link.</source>
                <target>Link di login scaduto o non valido.</target>
            </trans-unit>
            <trans-unit id="19">
                <source>Too many failed login attempts, please try again in %minutes% minute.</source>
                <target>Troppi tentativi di login falliti, riprova tra %minutes% minuto.</target>
            </trans-unit>
            <trans-unit id="20">
                <source>Too many failed login attempts, please try again in %minutes% minutes.</source>
                <target>Troppi tentativi di login falliti, riprova tra %minutes% minuti.</target>
            </trans-unit>
        </body>
    </file>
</xliff>
<?xml version="1.0" encoding="utf-8"?>
<xliff xmlns="urn:oasis:names:tc:xliff:document:1.2" version="1.2">
    <file source-language="en" target-language="gl" datatype="plaintext" original="file.ext">
        <body>
            <trans-unit id="1">
                <source>An authentication exception occurred.</source>
                <target>Ocorreu un erro de autenticación.</target>
            </trans-unit>
            <trans-unit id="2">
                <source>Authentication credentials could not be found.</source>
                <target>Non se atoparon as credenciais de autenticación.</target>
            </trans-unit>
            <trans-unit id="3">
                <source>Authentication request could not be processed due to a system problem.</source>
                <target>A solicitude de autenticación no puido ser procesada debido a un problema do sistema.</target>
            </trans-unit>
            <trans-unit id="4">
                <source>Invalid credentials.</source>
                <target>Credenciais non válidas.</target>
            </trans-unit>
            <trans-unit id="5">
                <source>Cookie has already been used by someone else.</source>
                <target>A cookie xa foi empregado por outro usuario.</target>
            </trans-unit>
            <trans-unit id="6">
                <source>Not privileged to request the resource.</source>
                <target>Non ten privilexios para solicitar o recurso.</target>
            </trans-unit>
            <trans-unit id="7">
                <source>Invalid CSRF token.</source>
                <target>Token CSRF non válido.</target>
            </trans-unit>
            <trans-unit id="9">
                <source>No authentication provider found to support the authentication token.</source>
                <target>Non se atopou un provedor de autenticación que soporte o token de autenticación.</target>
            </trans-unit>
            <trans-unit id="10">
                <source>No session available, it either timed out or cookies are not enabled.</source>
                <target>Non hai ningunha sesión dispoñible, expirou ou as cookies non están habilitadas.</target>
            </trans-unit>
            <trans-unit id="11">
                <source>No token could be found.</source>
                <target>Non se atopou ningún token.</target>
            </trans-unit>
            <trans-unit id="12">
                <source>Username could not be found.</source>
                <target>Non se atopou o nome de usuario.</target>
            </trans-unit>
            <trans-unit id="13">
                <source>Account has expired.</source>
                <target>A conta expirou.</target>
            </trans-unit>
            <trans-unit id="14">
                <source>Credentials have expired.</source>
                <target>As credenciais expiraron.</target>
            </trans-unit>
            <trans-unit id="15">
                <source>Account is disabled.</source>
                <target>A conta está deshabilitada.</target>
            </trans-unit>
            <trans-unit id="16">
                <source>Account is locked.</source>
                <target>A conta está bloqueada.</target>
            </trans-unit>
            <trans-unit id="17">
                <source>Too many failed login attempts, please try again later.</source>
                <target>Demasiados intentos de inicio de sesión fallados. Téntao de novo máis tarde.</target>
            </trans-unit>
            <trans-unit id="18">
                <source>Invalid or expired login link.</source>
                <target>Ligazón de inicio de sesión non válida ou caducada.</target>
            </trans-unit>
            <trans-unit id="19">
                <source>Too many failed login attempts, please try again in %minutes% minute.</source>
                <target>Demasiados intentos de inicio de sesión errados, por favor, ténteo de novo en %minutes% minuto.</target>
            </trans-unit>
            <trans-unit id="20">
                <source>Too many failed login attempts, please try again in %minutes% minutes.</source>
                <target>Demasiados intentos errados de inicio de sesión, inténtao de novo en %minutes% minutos.</target>
            </trans-unit>
        </body>
    </file>
</xliff>
<?xml version="1.0" encoding="utf-8"?>
<xliff xmlns="urn:oasis:names:tc:xliff:document:1.2" version="1.2">
    <file source-language="en" target-language="es" datatype="plaintext" original="file.ext">
        <body>
            <trans-unit id="1">
                <source>An authentication exception occurred.</source>
                <target>Ocurrió un error de autenticación.</target>
            </trans-unit>
            <trans-unit id="2">
                <source>Authentication credentials could not be found.</source>
                <target>No se encontraron las credenciales de autenticación.</target>
            </trans-unit>
            <trans-unit id="3">
                <source>Authentication request could not be processed due to a system problem.</source>
                <target>La solicitud de autenticación no se pudo procesar debido a un problema del sistema.</target>
            </trans-unit>
            <trans-unit id="4">
                <source>Invalid credentials.</source>
                <target>Credenciales no válidas.</target>
            </trans-unit>
            <trans-unit id="5">
                <source>Cookie has already been used by someone else.</source>
                <target>La cookie ya ha sido usada por otra persona.</target>
            </trans-unit>
            <trans-unit id="6">
                <source>Not privileged to request the resource.</source>
                <target>No tiene privilegios para solicitar el recurso.</target>
            </trans-unit>
            <trans-unit id="7">
                <source>Invalid CSRF token.</source>
                <target>Token CSRF no válido.</target>
            </trans-unit>
            <trans-unit id="9">
                <source>No authentication provider found to support the authentication token.</source>
                <target>No se encontró un proveedor de autenticación que soporte el token de autenticación.</target>
            </trans-unit>
            <trans-unit id="10">
                <source>No session available, it either timed out or cookies are not enabled.</source>
                <target>No hay ninguna sesión disponible, ha expirado o las cookies no están habilitados.</target>
            </trans-unit>
            <trans-unit id="11">
                <source>No token could be found.</source>
                <target>No se encontró ningún token.</target>
            </trans-unit>
            <trans-unit id="12">
                <source>Username could not be found.</source>
                <target>No se encontró el nombre de usuario.</target>
            </trans-unit>
            <trans-unit id="13">
                <source>Account has expired.</source>
                <target>La cuenta ha expirado.</target>
            </trans-unit>
            <trans-unit id="14">
                <source>Credentials have expired.</source>
                <target>Las credenciales han expirado.</target>
            </trans-unit>
            <trans-unit id="15">
                <source>Account is disabled.</source>
                <target>La cuenta está deshabilitada.</target>
            </trans-unit>
            <trans-unit id="16">
                <source>Account is locked.</source>
                <target>La cuenta está bloqueada.</target>
            </trans-unit>
            <trans-unit id="17">
                <source>Too many failed login attempts, please try again later.</source>
                <target>Demasiados intentos fallidos de inicio de sesión, inténtelo de nuevo más tarde.</target>
            </trans-unit>
            <trans-unit id="18">
                <source>Invalid or expired login link.</source>
                <target>Enlace de inicio de sesión inválido o expirado.</target>
            </trans-unit>
            <trans-unit id="19">
                <source>Too many failed login attempts, please try again in %minutes% minute.</source>
                <target>Demasiados intentos fallidos de inicio de sesión, inténtelo de nuevo en %minutes% minuto.</target>
            </trans-unit>
            <trans-unit id="20">
                <source>Too many failed login attempts, please try again in %minutes% minutes.</source>
                <target>Demasiados intentos fallidos de inicio de sesión, inténtelo de nuevo en %minutes% minutos.</target>
            </trans-unit>
        </body>
    </file>
</xliff>
<?xml version="1.0" encoding="utf-8"?>
<xliff xmlns="urn:oasis:names:tc:xliff:document:1.2" version="1.2">
    <file source-language="en" target-language="hu" datatype="plaintext" original="file.ext">
        <body>
            <trans-unit id="1">
                <source>An authentication exception occurred.</source>
                <target>Hitelesítési hiba lépett fel.</target>
            </trans-unit>
            <trans-unit id="2">
                <source>Authentication credentials could not be found.</source>
                <target>Nem találhatók hitelesítési információk.</target>
            </trans-unit>
            <trans-unit id="3">
                <source>Authentication request could not be processed due to a system problem.</source>
                <target>A hitelesítési kérést rendszerhiba miatt nem lehet feldolgozni.</target>
            </trans-unit>
            <trans-unit id="4">
                <source>Invalid credentials.</source>
                <target>Érvénytelen hitelesítési információk.</target>
            </trans-unit>
            <trans-unit id="5">
                <source>Cookie has already been used by someone else.</source>
                <target>Ezt a sütit valaki más már felhasználta.</target>
            </trans-unit>
            <trans-unit id="6">
                <source>Not privileged to request the resource.</source>
                <target>Nem rendelkezik az erőforrás eléréséhez szükséges jogosultsággal.</target>
            </trans-unit>
            <trans-unit id="7">
                <source>Invalid CSRF token.</source>
                <target>Érvénytelen CSRF token.</target>
            </trans-unit>
            <trans-unit id="9">
                <source>No authentication provider found to support the authentication token.</source>
                <target>Nem található a hitelesítési tokent támogató hitelesítési szolgáltatás.</target>
            </trans-unit>
            <trans-unit id="10">
                <source>No session available, it either timed out or cookies are not enabled.</source>
                <target>Munkamenet nem áll rendelkezésre, túllépte az időkeretet vagy a sütik le vannak tiltva.</target>
            </trans-unit>
            <trans-unit id="11">
                <source>No token could be found.</source>
                <target>Nem található token.</target>
            </trans-unit>
            <trans-unit id="12">
                <source>Username could not be found.</source>
                <target>A felhasználónév nem található.</target>
            </trans-unit>
            <trans-unit id="13">
                <source>Account has expired.</source>
                <target>A fiók lejárt.</target>
            </trans-unit>
            <trans-unit id="14">
                <source>Credentials have expired.</source>
                <target>A hitelesítési információk lejártak.</target>
            </trans-unit>
            <trans-unit id="15">
                <source>Account is disabled.</source>
                <target>Felfüggesztett fiók.</target>
            </trans-unit>
            <trans-unit id="16">
                <source>Account is locked.</source>
                <target>Zárolt fiók.</target>
            </trans-unit>
            <trans-unit id="17">
                <source>Too many failed login attempts, please try again later.</source>
                <target>Túl sok sikertelen bejelentkezési kísérlet, kérjük próbálja újra később.</target>
            </trans-unit>
            <trans-unit id="18">
                <source>Invalid or expired login link.</source>
                <target>Érvénytelen vagy lejárt bejelentkezési link.</target>
            </trans-unit>
            <trans-unit id="19">
                <source>Too many failed login attempts, please try again in %minutes% minute.</source>
                <target>Túl sok sikertelen bejelentkezési kísérlet, kérjük próbálja újra %minutes% perc múlva.</target>
            </trans-unit>
            <trans-unit id="20">
                <source>Too many failed login attempts, please try again in %minutes% minutes.</source>
                <target>Túl sok sikertelen bejelentkezési kísérlet, kérjük, próbálja újra %minutes% perc múlva.</target>
            </trans-unit>
        </body>
    </file>
</xliff>
<?xml version="1.0" encoding="utf-8"?>
<xliff xmlns="urn:oasis:names:tc:xliff:document:1.2" version="1.2">
    <file source-language="en" target-language="da" datatype="plaintext" original="file.ext">
        <body>
            <trans-unit id="1">
                <source>An authentication exception occurred.</source>
                <target>En fejl indtraf ved godkendelse.</target>
            </trans-unit>
            <trans-unit id="2">
                <source>Authentication credentials could not be found.</source>
                <target>Loginoplysninger kunne ikke findes.</target>
            </trans-unit>
            <trans-unit id="3">
                <source>Authentication request could not be processed due to a system problem.</source>
                <target>Godkendelsesanmodningen kunne ikke behandles på grund af en systemfejl.</target>
            </trans-unit>
            <trans-unit id="4">
                <source>Invalid credentials.</source>
                <target>Ugyldige loginoplysninger.</target>
            </trans-unit>
            <trans-unit id="5">
                <source>Cookie has already been used by someone else.</source>
                <target>Cookie er allerede blevet brugt af en anden.</target>
            </trans-unit>
            <trans-unit id="6">
                <source>Not privileged to request the resource.</source>
                <target>Ingen adgang til at forespørge ressourcen.</target>
            </trans-unit>
            <trans-unit id="7">
                <source>Invalid CSRF token.</source>
                <target>Ugyldig CSRF-token.</target>
            </trans-unit>
            <trans-unit id="9">
                <source>No authentication provider found to support the authentication token.</source>
                <target>Ingen godkendelsesudbyder blev fundet til at understøtte godkendelsestoken.</target>
            </trans-unit>
            <trans-unit id="10">
                <source>No session available, it either timed out or cookies are not enabled.</source>
                <target>Ingen session er tilgængelig. Den er enten udløbet eller cookies er ikke aktiveret.</target>
            </trans-unit>
            <trans-unit id="11">
                <source>No token could be found.</source>
                <target>Ingen token kunne findes.</target>
            </trans-unit>
            <trans-unit id="12">
                <source>Username could not be found.</source>
                <target>Brugernavn kunne ikke findes.</target>
            </trans-unit>
            <trans-unit id="13">
                <source>Account has expired.</source>
                <target>Brugerkonto er udløbet.</target>
            </trans-unit>
            <trans-unit id="14">
                <source>Credentials have expired.</source>
                <target>Loginoplysninger er udløbet.</target>
            </trans-unit>
            <trans-unit id="15">
                <source>Account is disabled.</source>
                <target>Brugerkonto er deaktiveret.</target>
            </trans-unit>
            <trans-unit id="16">
                <source>Account is locked.</source>
                <target>Brugerkonto er låst.</target>
            </trans-unit>
            <trans-unit id="17">
                <source>Too many failed login attempts, please try again later.</source>
                <target>For mange mislykkede loginforsøg. Prøv venligst igen senere.</target>
            </trans-unit>
            <trans-unit id="18">
                <source>Invalid or expired login link.</source>
                <target>Ugyldigt eller udløbet login-link.</target>
            </trans-unit>
            <trans-unit id="19">
                <source>Too many failed login attempts, please try again in %minutes% minute.</source>
                <target>For mange mislykkede loginforsøg. Prøv venligst igen om %minutes% minut.</target>
            </trans-unit>
            <trans-unit id="20">
                <source>Too many failed login attempts, please try again in %minutes% minutes.</source>
                <target>For mange mislykkede loginforsøg, prøv igen om %minutes% minutter.</target>
            </trans-unit>
        </body>
    </file>
</xliff>
<?xml version="1.0" encoding="utf-8"?>
<xliff xmlns="urn:oasis:names:tc:xliff:document:1.2" version="1.2">
    <file source-language="en" target-language="fi" datatype="plaintext" original="file.ext">
        <body>
            <trans-unit id="1">
                <source>An authentication exception occurred.</source>
                <target>Autentikointipoikkeus tapahtui.</target>
            </trans-unit>
            <trans-unit id="2">
                <source>Authentication credentials could not be found.</source>
                <target>Autentikoinnin tunnistetietoja ei löydetty.</target>
            </trans-unit>
            <trans-unit id="3">
                <source>Authentication request could not be processed due to a system problem.</source>
                <target>Autentikointipyyntöä ei voitu käsitellä järjestelmäongelman vuoksi.</target>
            </trans-unit>
            <trans-unit id="4">
                <source>Invalid credentials.</source>
                <target>Virheelliset tunnistetiedot.</target>
            </trans-unit>
            <trans-unit id="5">
                <source>Cookie has already been used by someone else.</source>
                <target>Eväste on jo jonkun muun käytössä.</target>
            </trans-unit>
            <trans-unit id="6">
                <source>Not privileged to request the resource.</source>
                <target>Ei oikeutta resurssiin.</target>
            </trans-unit>
            <trans-unit id="7">
                <source>Invalid CSRF token.</source>
                <target>Virheellinen CSRF-tunnus.</target>
            </trans-unit>
            <trans-unit id="9">
                <source>No authentication provider found to support the authentication token.</source>
                <target>Autentikointitunnukselle ei löydetty tuettua autentikoinnintarjoajaa.</target>
            </trans-unit>
            <trans-unit id="10">
                <source>No session available, it either timed out or cookies are not enabled.</source>
                <target>Sessio ei ole saatavilla, se on joko vanhentunut tai evästeet eivät ole käytössä.</target>
            </trans-unit>
            <trans-unit id="11">
                <source>No token could be found.</source>
                <target>Tunnusta ei löytynyt.</target>
            </trans-unit>
            <trans-unit id="12">
                <source>Username could not be found.</source>
                <target>Käyttäjätunnusta ei löytynyt.</target>
            </trans-unit>
            <trans-unit id="13">
                <source>Account has expired.</source>
                <target>Tili on vanhentunut.</target>
            </trans-unit>
            <trans-unit id="14">
                <source>Credentials have expired.</source>
                <target>Tunnistetiedot ovat vanhentuneet.</target>
            </trans-unit>
            <trans-unit id="15">
                <source>Account is disabled.</source>
                <target>Tili on poistettu käytöstä.</target>
            </trans-unit>
            <trans-unit id="16">
                <source>Account is locked.</source>
                <target>Tili on lukittu.</target>
            </trans-unit>
            <trans-unit id="17">
                <source>Too many failed login attempts, please try again later.</source>
                <target>Liian monta epäonnistunutta kirjautumisyritystä, yritä myöhemmin uudelleen.</target>
            </trans-unit>
            <trans-unit id="18">
                <source>Invalid or expired login link.</source>
                <target>Virheellinen tai vanhentunut kirjautumislinkki.</target>
            </trans-unit>
            <trans-unit id="19">
                <source>Too many failed login attempts, please try again in %minutes% minute.</source>
                <target>Liian monta epäonnistunutta kirjautumisyritystä, yritä uudelleen %minutes% minuutin kuluttua.</target>
            </trans-unit>
            <trans-unit id="20">
                <source>Too many failed login attempts, please try again in %minutes% minutes.</source>
                <target>Liian monta epäonnistunutta kirjautumisyritystä, yritä uudelleen %minutes% minuutin kuluttua.</target>
            </trans-unit>
        </body>
    </file>
</xliff>
<?xml version="1.0" encoding="utf-8"?>
<xliff xmlns="urn:oasis:names:tc:xliff:document:1.2" version="1.2">
    <file source-language="en" target-language="id" datatype="plaintext" original="file.ext">
        <body>
            <trans-unit id="1">
                <source>An authentication exception occurred.</source>
                <target>Terjadi kesalahan otentikasi.</target>
            </trans-unit>
            <trans-unit id="2">
                <source>Authentication credentials could not be found.</source>
                <target>Kredensial otentikasi tidak bisa ditemukan.</target>
            </trans-unit>
            <trans-unit id="3">
                <source>Authentication request could not be processed due to a system problem.</source>
                <target>Permintaan otentikasi tidak bisa diproses karena masalah sistem.</target>
            </trans-unit>
            <trans-unit id="4">
                <source>Invalid credentials.</source>
                <target>Kredensial tidak valid.</target>
            </trans-unit>
            <trans-unit id="5">
                <source>Cookie has already been used by someone else.</source>
                <target>Cookie sudah digunakan oleh orang lain.</target>
            </trans-unit>
            <trans-unit id="6">
                <source>Not privileged to request the resource.</source>
                <target>Tidak berhak untuk meminta sumber daya.</target>
            </trans-unit>
            <trans-unit id="7">
                <source>Invalid CSRF token.</source>
                <target>Token CSRF tidak valid.</target>
            </trans-unit>
            <trans-unit id="9">
                <source>No authentication provider found to support the authentication token.</source>
                <target>Tidak ditemukan penyedia otentikasi untuk mendukung token otentikasi.</target>
            </trans-unit>
            <trans-unit id="10">
                <source>No session available, it either timed out or cookies are not enabled.</source>
                <target>Tidak ada sesi yang tersedia, mungkin waktu sudah habis atau cookie tidak diaktifkan</target>
            </trans-unit>
            <trans-unit id="11">
                <source>No token could be found.</source>
                <target>Tidak ada token yang bisa ditemukan.</target>
            </trans-unit>
            <trans-unit id="12">
                <source>Username could not be found.</source>
                <target>Username tidak bisa ditemukan.</target>
            </trans-unit>
            <trans-unit id="13">
                <source>Account has expired.</source>
                <target>Akun telah berakhir.</target>
            </trans-unit>
            <trans-unit id="14">
                <source>Credentials have expired.</source>
                <target>Kredensial telah berakhir.</target>
            </trans-unit>
            <trans-unit id="15">
                <source>Account is disabled.</source>
                <target>Akun dinonaktifkan.</target>
            </trans-unit>
            <trans-unit id="16">
                <source>Account is locked.</source>
                <target>Akun terkunci.</target>
            </trans-unit>
            <trans-unit id="17">
                <source>Too many failed login attempts, please try again later.</source>
                <target>Terlalu banyak percobaan login yang gagal, silahkan coba lagi nanti.</target>
            </trans-unit>
            <trans-unit id="18">
                <source>Invalid or expired login link.</source>
                <target>Link login tidak valid atau sudah kedaluwarsa.</target>
            </trans-unit>
            <trans-unit id="19">
                <source>Too many failed login attempts, please try again in %minutes% minute.</source>
                <target>Terlalu banyak percobaan login yang gagal, silahkan coba lagi dalam %minutes% menit.</target>
            </trans-unit>
            <trans-unit id="20">
                <source>Too many failed login attempts, please try again in %minutes% minutes.</source>
                <target>Terlalu banyak upaya login yang gagal, silakan coba lagi dalam beberapa %minutes% menit.</target>
            </trans-unit>
        </body>
    </file>
</xliff>
<?xml version="1.0" encoding="utf-8"?>
<xliff xmlns="urn:oasis:names:tc:xliff:document:1.2" version="1.2">
    <file source-language="en" target-language="sk" datatype="plaintext" original="file.ext">
        <body>
            <trans-unit id="1">
                <source>An authentication exception occurred.</source>
                <target>Pri overovaní došlo k chybe.</target>
            </trans-unit>
            <trans-unit id="2">
                <source>Authentication credentials could not be found.</source>
                <target>Overovacie údaje neboli nájdené.</target>
            </trans-unit>
            <trans-unit id="3">
                <source>Authentication request could not be processed due to a system problem.</source>
                <target>Požiadavok na overenie nemohol byť spracovaný kvôli systémovej chybe.</target>
            </trans-unit>
            <trans-unit id="4">
                <source>Invalid credentials.</source>
                <target>Neplatné prihlasovacie údaje.</target>
            </trans-unit>
            <trans-unit id="5">
                <source>Cookie has already been used by someone else.</source>
                <target>Cookie už bolo použité niekým iným.</target>
            </trans-unit>
            <trans-unit id="6">
                <source>Not privileged to request the resource.</source>
                <target>Nemáte oprávnenie pristupovať k prostriedku.</target>
            </trans-unit>
            <trans-unit id="7">
                <source>Invalid CSRF token.</source>
                <target>Neplatný CSRF token.</target>
            </trans-unit>
            <trans-unit id="9">
                <source>No authentication provider found to support the authentication token.</source>
                <target>Poskytovateľ pre overovací token nebol nájdený.</target>
            </trans-unit>
            <trans-unit id="10">
                <source>No session available, it either timed out or cookies are not enabled.</source>
                <target>Session nie je k dispozíci, vypršala jej platnosť, alebo sú zakázané cookies.</target>
            </trans-unit>
            <trans-unit id="11">
                <source>No token could be found.</source>
                <target>Token nebol nájdený.</target>
            </trans-unit>
            <trans-unit id="12">
                <source>Username could not be found.</source>
                <target>Prihlasovacie meno nebolo nájdené.</target>
            </trans-unit>
            <trans-unit id="13">
                <source>Account has expired.</source>
                <target>Platnosť účtu skončila.</target>
            </trans-unit>
            <trans-unit id="14">
                <source>Credentials have expired.</source>
                <target>Platnosť prihlasovacích údajov skončila.</target>
            </trans-unit>
            <trans-unit id="15">
                <source>Account is disabled.</source>
                <target>Účet je zakázaný.</target>
            </trans-unit>
            <trans-unit id="16">
                <source>Account is locked.</source>
                <target>Účet je zablokovaný.</target>
            </trans-unit>
            <trans-unit id="17">
                <source>Too many failed login attempts, please try again later.</source>
                <target>Príliš mnoho neúspešných pokusov o prihlásenie. Skúste to prosím znovu neskôr.</target>
            </trans-unit>
            <trans-unit id="18">
                <source>Invalid or expired login link.</source>
                <target>Neplatný alebo expirovaný odkaz na prihlásenie.</target>
            </trans-unit>
            <trans-unit id="19">
                <source>Too many failed login attempts, please try again in %minutes% minute.</source>
                <target>Príliš veľa neúspešných pokusov o prihlásenie. Skúste to znova o %minutes% minútu.</target>
            </trans-unit>
            <trans-unit id="20">
                <source>Too many failed login attempts, please try again in %minutes% minutes.</source>
                <target>Príliš veľa neúspešných pokusov o prihlásenie, skúste to prosím znova o %minutes% minútu.|Príliš veľa neúspešných pokusov o prihlásenie, skúste to prosím znova o %minutes% minúty.|Príliš veľa neúspešných pokusov o prihlásenie, skúste to prosím znova o %minutes% minút.</target>
            </trans-unit>
        </body>
    </file>
</xliff>
<?xml version="1.0" encoding="utf-8"?>
<xliff xmlns="urn:oasis:names:tc:xliff:document:1.2" version="1.2">
    <file source-language="en" target-language="ro" datatype="plaintext" original="file.ext">
        <body>
            <trans-unit id="1">
                <source>An authentication exception occurred.</source>
                <target>A apărut o eroare de autentificare.</target>
            </trans-unit>
            <trans-unit id="2">
                <source>Authentication credentials could not be found.</source>
                <target>Informațiile de autentificare nu au fost găsite.</target>
            </trans-unit>
            <trans-unit id="3">
                <source>Authentication request could not be processed due to a system problem.</source>
                <target>Sistemul nu a putut procesa cererea de autentificare din cauza unei erori.</target>
            </trans-unit>
            <trans-unit id="4">
                <source>Invalid credentials.</source>
                <target>Date de autentificare invalide.</target>
            </trans-unit>
            <trans-unit id="5">
                <source>Cookie has already been used by someone else.</source>
                <target>Cookie este folosit deja de altcineva.</target>
            </trans-unit>
            <trans-unit id="6">
                <source>Not privileged to request the resource.</source>
                <target>Permisiuni insuficiente pentru resursa cerută.</target>
            </trans-unit>
            <trans-unit id="7">
                <source>Invalid CSRF token.</source>
                <target>Token CSRF este invalid.</target>
            </trans-unit>
            <trans-unit id="9">
                <source>No authentication provider found to support the authentication token.</source>
                <target>Nu a fost găsit nici un agent de autentificare pentru tokenul specificat.</target>
            </trans-unit>
            <trans-unit id="10">
                <source>No session available, it either timed out or cookies are not enabled.</source>
                <target>Sesiunea nu mai este disponibilă, a expirat sau suportul pentru cookies nu este activat.</target>
            </trans-unit>
            <trans-unit id="11">
                <source>No token could be found.</source>
                <target>Tokenul nu a putut fi găsit.</target>
            </trans-unit>
            <trans-unit id="12">
                <source>Username could not be found.</source>
                <target>Numele de utilizator nu a fost găsit.</target>
            </trans-unit>
            <trans-unit id="13">
                <source>Account has expired.</source>
                <target>Contul a expirat.</target>
            </trans-unit>
            <trans-unit id="14">
                <source>Credentials have expired.</source>
                <target>Datele de autentificare au expirat.</target>
            </trans-unit>
            <trans-unit id="15">
                <source>Account is disabled.</source>
                <target>Contul este dezactivat.</target>
            </trans-unit>
            <trans-unit id="16">
                <source>Account is locked.</source>
                <target>Contul este blocat.</target>
            </trans-unit>
            <trans-unit id="17">
                <source>Too many failed login attempts, please try again later.</source>
                <target>Prea multe încercări de autentificare eșuate, vă rugăm să încercați mai târziu.</target>
            </trans-unit>
            <trans-unit id="18">
                <source>Invalid or expired login link.</source>
                <target>Link de autentificare invalid sau expirat.</target>
            </trans-unit>
            <trans-unit id="19">
                <source>Too many failed login attempts, please try again in %minutes% minute.</source>
                <target>Prea multe încercări nereușite, încearcă din nou în %minutes% minut.</target>
            </trans-unit>
            <trans-unit id="20">
                <source>Too many failed login attempts, please try again in %minutes% minutes.</source>
                <target>Prea multe încercări eșuate de autentificare, vă rugăm să încercați din nou peste %minutes% minut.|Prea multe încercări eșuate de autentificare, vă rugăm să încercați din nou peste %minutes% minute.</target>
            </trans-unit>
        </body>
    </file>
</xliff>
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Security\Core\User;

use _ContaoManager\Symfony\Component\Security\Core\Exception\UserNotFoundException;
/**
 * Overrides UserProviderInterface to add an "attributes" argument on loadUserByIdentifier.
 * This is particularly useful with self-contained access tokens.
 *
 * @template-covariant TUser of UserInterface
 *
 * @template-extends UserProviderInterface<TUser>
 */
interface AttributesBasedUserProviderInterface extends UserProviderInterface
{
    /**
     * Loads the user for the given user identifier (e.g. username or email) and attributes.
     *
     * This method must throw UserNotFoundException if the user is not found.
     *
     * @return TUser
     *
     * @throws UserNotFoundException
     */
    public function loadUserByIdentifier(string $identifier, array $attributes = []): UserInterface;
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Security\Core\User;

/**
 * UserInterface implementation used by the access-token security workflow with an OIDC server.
 */
class OidcUser implements UserInterface
{
    private array $additionalClaims = [];
    public function __construct(
        private ?string $userIdentifier = null,
        private array $roles = ['ROLE_USER'],
        // Standard Claims (https://openid.net/specs/openid-connect-core-1_0.html#StandardClaims)
        private ?string $sub = null,
        private ?string $name = null,
        private ?string $givenName = null,
        private ?string $familyName = null,
        private ?string $middleName = null,
        private ?string $nickname = null,
        private ?string $preferredUsername = null,
        private ?string $profile = null,
        private ?string $picture = null,
        private ?string $website = null,
        private ?string $email = null,
        private ?bool $emailVerified = null,
        private ?string $gender = null,
        private ?string $birthdate = null,
        private ?string $zoneinfo = null,
        private ?string $locale = null,
        private ?string $phoneNumber = null,
        private ?bool $phoneNumberVerified = null,
        private ?array $address = null,
        private ?\DateTimeInterface $updatedAt = null,
        // Additional Claims (https://openid.net/specs/openid-connect-core-1_0.html#AdditionalClaims)
        ...$additionalClaims
    )
    {
        if (null === $sub || '' === $sub) {
            throw new \InvalidArgumentException('The "sub" claim cannot be empty.');
        }
        $this->additionalClaims = $additionalClaims['additionalClaims'] ?? $additionalClaims;
    }
    /**
     * OIDC or OAuth specs don't have any "role" notion.
     *
     * If you want to implement "roles" from your OIDC server,
     * send a "roles" constructor argument to this object
     * (e.g.: using a custom UserProvider).
     */
    public function getRoles(): array
    {
        return $this->roles;
    }
    public function getUserIdentifier(): string
    {
        return (string) ($this->userIdentifier ?? $this->getSub());
    }
    public function eraseCredentials(): void
    {
    }
    public function getSub(): ?string
    {
        return $this->sub;
    }
    public function getName(): ?string
    {
        return $this->name;
    }
    public function getGivenName(): ?string
    {
        return $this->givenName;
    }
    public function getFamilyName(): ?string
    {
        return $this->familyName;
    }
    public function getMiddleName(): ?string
    {
        return $this->middleName;
    }
    public function getNickname(): ?string
    {
        return $this->nickname;
    }
    public function getPreferredUsername(): ?string
    {
        return $this->preferredUsername;
    }
    public function getProfile(): ?string
    {
        return $this->profile;
    }
    public function getPicture(): ?string
    {
        return $this->picture;
    }
    public function getWebsite(): ?string
    {
        return $this->website;
    }
    public function getEmail(): ?string
    {
        return $this->email;
    }
    public function getEmailVerified(): ?bool
    {
        return $this->emailVerified;
    }
    public function getGender(): ?string
    {
        return $this->gender;
    }
    public function getBirthdate(): ?string
    {
        return $this->birthdate;
    }
    public function getZoneinfo(): ?string
    {
        return $this->zoneinfo;
    }
    public function getLocale(): ?string
    {
        return $this->locale;
    }
    public function getPhoneNumber(): ?string
    {
        return $this->phoneNumber;
    }
    public function getphoneNumberVerified(): ?bool
    {
        return $this->phoneNumberVerified;
    }
    public function getAddress(): ?array
    {
        return $this->address;
    }
    public function getUpdatedAt(): ?\DateTimeInterface
    {
        return $this->updatedAt;
    }
    public function getAdditionalClaims(): array
    {
        return $this->additionalClaims;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Security\Core\User;

use _ContaoManager\Symfony\Component\Security\Core\Exception\DisabledException;
/**
 * Checks the state of the in-memory user account.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class InMemoryUserChecker implements UserCheckerInterface
{
    /**
     * @return void
     */
    public function checkPreAuth(UserInterface $user)
    {
        if (!$user instanceof InMemoryUser) {
            return;
        }
        if (!$user->isEnabled()) {
            $ex = new DisabledException('User account is disabled.');
            $ex->setUser($user);
            throw $ex;
        }
    }
    /**
     * @return void
     */
    public function checkPostAuth(UserInterface $user)
    {
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Security\Core\User;

/**
 * Represents the interface that all user classes must implement.
 *
 * This interface is useful because the authentication layer can deal with
 * the object through its lifecycle, assigning roles and so on.
 *
 * Regardless of how your users are loaded or where they come from (a database,
 * configuration, web service, etc.), you will have a class that implements
 * this interface. Objects that implement this interface are created and
 * loaded by different objects that implement UserProviderInterface.
 *
 * @see UserProviderInterface
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
interface UserInterface
{
    /**
     * Returns the roles granted to the user.
     *
     *     public function getRoles()
     *     {
     *         return ['ROLE_USER'];
     *     }
     *
     * Alternatively, the roles might be stored in a ``roles`` property,
     * and populated in any number of different ways when the user object
     * is created.
     *
     * @return string[]
     */
    public function getRoles(): array;
    /**
     * Removes sensitive data from the user.
     *
     * This is important if, at any given point, sensitive information like
     * the plain-text password is stored on this object.
     *
     * @return void
     */
    public function eraseCredentials();
    /**
     * Returns the identifier for this user (e.g. username or email address).
     */
    public function getUserIdentifier(): string;
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Security\Core\User;

use _ContaoManager\Symfony\Component\Security\Core\Exception\UnsupportedUserException;
use _ContaoManager\Symfony\Component\Security\Core\Exception\UserNotFoundException;
/**
 * Represents a class that loads UserInterface objects from some source for the authentication system.
 *
 * In a typical authentication configuration, a user identifier (e.g. a
 * username or email address) credential enters the system (via form login, or
 * any method). The user provider that is configured with that authentication
 * method is asked to load the UserInterface object for the given identifier (via
 * loadUserByIdentifier) so that the rest of the process can continue.
 *
 * Internally, a user provider can load users from any source (databases,
 * configuration, web service). This is totally independent of how the authentication
 * information is submitted or what the UserInterface object looks like.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 *
 * @template-covariant TUser of UserInterface
 */
interface UserProviderInterface
{
    /**
     * Refreshes the user.
     *
     * It is up to the implementation to decide if the user data should be
     * totally reloaded (e.g. from the database), or if the UserInterface
     * object can just be merged into some internal array of users / identity
     * map.
     *
     * @return UserInterface
     *
     * @psalm-return TUser
     *
     * @throws UnsupportedUserException if the user is not supported
     * @throws UserNotFoundException    if the user is not found
     */
    public function refreshUser(UserInterface $user);
    /**
     * Whether this provider supports the given user class.
     *
     * @return bool
     */
    public function supportsClass(string $class);
    /**
     * Loads the user for the given user identifier (e.g. username or email).
     *
     * This method must throw UserNotFoundException if the user is not found.
     *
     * @return TUser
     *
     * @throws UserNotFoundException
     */
    public function loadUserByIdentifier(string $identifier): UserInterface;
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Security\Core\User;

use _ContaoManager\Symfony\Component\Config\Definition\Exception\InvalidConfigurationException;
/**
 * MissingUserProvider is a dummy user provider used to throw proper exception
 * when a firewall requires a user provider but none was defined.
 *
 * @internal
 *
 * @template-implements UserProviderInterface<never>
 */
class MissingUserProvider implements UserProviderInterface
{
    /**
     * @param string $firewall the firewall missing a provider
     */
    public function __construct(string $firewall)
    {
        throw new InvalidConfigurationException(\sprintf('"%s" firewall requires a user provider but none was defined.', $firewall));
    }
    public function loadUserByUsername(string $username): UserInterface
    {
        throw new \BadMethodCallException();
    }
    public function loadUserByIdentifier(string $identifier): UserInterface
    {
        throw new \BadMethodCallException();
    }
    public function refreshUser(UserInterface $user): UserInterface
    {
        throw new \BadMethodCallException();
    }
    public function supportsClass(string $class): bool
    {
        throw new \BadMethodCallException();
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Security\Core\User;

final class ChainUserChecker implements UserCheckerInterface
{
    /**
     * @param iterable<UserCheckerInterface> $checkers
     */
    public function __construct(private readonly iterable $checkers)
    {
    }
    public function checkPreAuth(UserInterface $user): void
    {
        foreach ($this->checkers as $checker) {
            $checker->checkPreAuth($user);
        }
    }
    public function checkPostAuth(UserInterface $user): void
    {
        foreach ($this->checkers as $checker) {
            $checker->checkPostAuth($user);
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Security\Core\User;

/**
 * For users that can be authenticated using a password/salt couple.
 *
 * Once all password hashes have been upgraded to a modern algorithm via password migrations,
 * implement {@see PasswordAuthenticatedUserInterface} instead.
 *
 * @author Robin Chalas <robin.chalas@gmail.com>
 */
interface LegacyPasswordAuthenticatedUserInterface extends PasswordAuthenticatedUserInterface
{
    /**
     * Returns the salt that was originally used to hash the password.
     */
    public function getSalt(): ?string;
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Security\Core\User;

/**
 * @author Nicolas Grekas <p@tchwork.com>
 */
interface PasswordUpgraderInterface
{
    /**
     * Upgrades the hashed password of a user, typically for using a better hash algorithm.
     *
     * This method should persist the new password in the user storage and update the $user object accordingly.
     * Because you don't want your users not being able to log in, this method should be opportunistic:
     * it's fine if it does nothing or if it fails without throwing any exception.
     */
    public function upgradePassword(PasswordAuthenticatedUserInterface $user, string $newHashedPassword): void;
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Security\Core\User;

/**
 * UserInterface implementation used by the in-memory user provider.
 *
 * This should not be used for anything else.
 *
 * @author Robin Chalas <robin.chalas@gmail.com>
 * @author Fabien Potencier <fabien@symfony.com>
 */
final class InMemoryUser implements UserInterface, PasswordAuthenticatedUserInterface, EquatableInterface, \Stringable
{
    private string $username;
    private ?string $password;
    private bool $enabled;
    private array $roles;
    public function __construct(?string $username, ?string $password, array $roles = [], bool $enabled = \true)
    {
        if ('' === $username || null === $username) {
            throw new \InvalidArgumentException('The username cannot be empty.');
        }
        $this->username = $username;
        $this->password = $password;
        $this->enabled = $enabled;
        $this->roles = $roles;
    }
    public function __toString(): string
    {
        return $this->getUserIdentifier();
    }
    public function getRoles(): array
    {
        return $this->roles;
    }
    public function getPassword(): ?string
    {
        return $this->password;
    }
    /**
     * Returns the identifier for this user (e.g. its username or email address).
     */
    public function getUserIdentifier(): string
    {
        return $this->username;
    }
    /**
     * Checks whether the user is enabled.
     *
     * Internally, if this method returns false, the authentication system
     * will throw a DisabledException and prevent login.
     *
     * @return bool true if the user is enabled, false otherwise
     *
     * @see DisabledException
     */
    public function isEnabled(): bool
    {
        return $this->enabled;
    }
    public function eraseCredentials(): void
    {
    }
    public function isEqualTo(UserInterface $user): bool
    {
        if (!$user instanceof self) {
            return \false;
        }
        if ($this->getPassword() !== $user->getPassword()) {
            return \false;
        }
        $currentRoles = array_map('strval', (array) $this->getRoles());
        $newRoles = array_map('strval', (array) $user->getRoles());
        $rolesChanged = \count($currentRoles) !== \count($newRoles) || \count($currentRoles) !== \count(array_intersect($currentRoles, $newRoles));
        if ($rolesChanged) {
            return \false;
        }
        if ($this->getUserIdentifier() !== $user->getUserIdentifier()) {
            return \false;
        }
        if ($this->isEnabled() !== $user->isEnabled()) {
            return \false;
        }
        return \true;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Security\Core\User;

use _ContaoManager\Symfony\Component\Security\Core\Exception\UnsupportedUserException;
use _ContaoManager\Symfony\Component\Security\Core\Exception\UserNotFoundException;
/**
 * InMemoryUserProvider is a simple non persistent user provider.
 *
 * Useful for testing, demonstration, prototyping, and for simple needs
 * (a backend with a unique admin for instance)
 *
 * @author Fabien Potencier <fabien@symfony.com>
 *
 * @template-implements UserProviderInterface<InMemoryUser>
 */
class InMemoryUserProvider implements UserProviderInterface
{
    /**
     * @var array<string, UserInterface>
     */
    private array $users = [];
    /**
     * The user array is a hash where the keys are usernames and the values are
     * an array of attributes: 'password', 'enabled', and 'roles'.
     *
     * @param array<string, array{password?: string, enabled?: bool, roles?: list<string>}> $users An array of users
     */
    public function __construct(array $users = [])
    {
        foreach ($users as $username => $attributes) {
            $password = $attributes['password'] ?? null;
            $enabled = $attributes['enabled'] ?? \true;
            $roles = $attributes['roles'] ?? [];
            $user = new InMemoryUser($username, $password, $roles, $enabled);
            $this->createUser($user);
        }
    }
    /**
     * Adds a new User to the provider.
     *
     * @return void
     *
     * @throws \LogicException
     */
    public function createUser(UserInterface $user)
    {
        if (!$user instanceof InMemoryUser) {
            trigger_deprecation('symfony/security-core', '6.3', 'Passing users that are not instance of "%s" to "%s" is deprecated, "%s" given.', InMemoryUser::class, __METHOD__, get_debug_type($user));
        }
        $userIdentifier = strtolower($user->getUserIdentifier());
        if (isset($this->users[$userIdentifier])) {
            throw new \LogicException('Another user with the same username already exists.');
        }
        $this->users[$userIdentifier] = $user;
    }
    public function loadUserByIdentifier(string $identifier): UserInterface
    {
        $user = $this->getUser($identifier);
        return new InMemoryUser($user->getUserIdentifier(), $user->getPassword(), $user->getRoles(), $user->isEnabled());
    }
    public function refreshUser(UserInterface $user): UserInterface
    {
        if (!$user instanceof InMemoryUser) {
            throw new UnsupportedUserException(\sprintf('Instances of "%s" are not supported.', get_debug_type($user)));
        }
        $storedUser = $this->getUser($user->getUserIdentifier());
        $userIdentifier = $storedUser->getUserIdentifier();
        return new InMemoryUser($userIdentifier, $storedUser->getPassword(), $storedUser->getRoles(), $storedUser->isEnabled());
    }
    public function supportsClass(string $class): bool
    {
        return InMemoryUser::class == $class;
    }
    /**
     * Returns the user by given username.
     *
     * @return InMemoryUser change return type on 7.0
     *
     * @throws UserNotFoundException if user whose given username does not exist
     */
    private function getUser(string $username): UserInterface
    {
        if (!isset($this->users[strtolower($username)])) {
            $ex = new UserNotFoundException(\sprintf('Username "%s" does not exist.', $username));
            $ex->setUserIdentifier($username);
            throw $ex;
        }
        return $this->users[strtolower($username)];
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Security\Core\User;

/**
 * EquatableInterface used to test if two objects are equal in security
 * and re-authentication context.
 *
 * @author Dariusz Górecki <darek.krk@gmail.com>
 */
interface EquatableInterface
{
    /**
     * The equality comparison should neither be done by referential equality
     * nor by comparing identities (i.e. getId() === getId()).
     *
     * However, you do not need to compare every attribute, but only those that
     * are relevant for assessing whether re-authentication is required.
     */
    public function isEqualTo(UserInterface $user): bool;
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Security\Core\User;

/**
 * For users that can be authenticated using a password.
 *
 * @author Robin Chalas <robin.chalas@gmail.com>
 * @author Wouter de Jong <wouter@wouterj.nl>
 */
interface PasswordAuthenticatedUserInterface
{
    /**
     * Returns the hashed password used to authenticate the user.
     *
     * Usually on authentication, a plain-text password will be compared to this value.
     */
    public function getPassword(): ?string;
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Security\Core\User;

use _ContaoManager\Symfony\Component\Security\Core\Exception\AccountStatusException;
/**
 * Implement to throw AccountStatusException during the authentication process.
 *
 * Can be used when you want to check the account status, e.g when the account is
 * disabled or blocked. This should not be used to make authentication decisions.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
interface UserCheckerInterface
{
    /**
     * Checks the user account before authentication.
     *
     * @return void
     *
     * @throws AccountStatusException
     */
    public function checkPreAuth(UserInterface $user);
    /**
     * Checks the user account after authentication.
     *
     * @return void
     *
     * @throws AccountStatusException
     */
    public function checkPostAuth(UserInterface $user);
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Security\Core\User;

use _ContaoManager\Symfony\Component\Security\Core\Exception\UnsupportedUserException;
use _ContaoManager\Symfony\Component\Security\Core\Exception\UserNotFoundException;
/**
 * Chain User Provider.
 *
 * This provider calls several leaf providers in a chain until one is able to
 * handle the request.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 *
 * @template-implements UserProviderInterface<UserInterface>
 */
class ChainUserProvider implements UserProviderInterface, PasswordUpgraderInterface
{
    private iterable $providers;
    /**
     * @param iterable<array-key, UserProviderInterface> $providers
     */
    public function __construct(iterable $providers)
    {
        $this->providers = $providers;
    }
    /**
     * @return UserProviderInterface[]
     */
    public function getProviders(): array
    {
        if ($this->providers instanceof \Traversable) {
            return iterator_to_array($this->providers);
        }
        return $this->providers;
    }
    /**
     * @internal for compatibility with Symfony 5.4
     */
    public function loadUserByUsername(string $username): UserInterface
    {
        return $this->loadUserByIdentifier($username);
    }
    /**
     * @param array $attributes
     */
    public function loadUserByIdentifier(string $identifier): UserInterface
    {
        $attributes = \func_num_args() > 1 ? func_get_arg(1) : [];
        foreach ($this->providers as $provider) {
            try {
                if ($provider instanceof AttributesBasedUserProviderInterface || $provider instanceof self) {
                    return $provider->loadUserByIdentifier($identifier, $attributes);
                }
                return $provider->loadUserByIdentifier($identifier);
            } catch (UserNotFoundException) {
                // try next one
            }
        }
        $ex = new UserNotFoundException(\sprintf('There is no user with identifier "%s".', $identifier));
        $ex->setUserIdentifier($identifier);
        throw $ex;
    }
    public function refreshUser(UserInterface $user): UserInterface
    {
        $supportedUserFound = \false;
        foreach ($this->providers as $provider) {
            try {
                if (!$provider->supportsClass(get_debug_type($user))) {
                    continue;
                }
                return $provider->refreshUser($user);
            } catch (UnsupportedUserException) {
                // try next one
            } catch (UserNotFoundException) {
                $supportedUserFound = \true;
                // try next one
            }
        }
        if ($supportedUserFound) {
            $username = $user->getUserIdentifier();
            $e = new UserNotFoundException(\sprintf('There is no user with name "%s".', $username));
            $e->setUserIdentifier($username);
            throw $e;
        } else {
            throw new UnsupportedUserException(\sprintf('There is no user provider for user "%s". Shouldn\'t the "supportsClass()" method of your user provider return true for this classname?', get_debug_type($user)));
        }
    }
    public function supportsClass(string $class): bool
    {
        foreach ($this->providers as $provider) {
            if ($provider->supportsClass($class)) {
                return \true;
            }
        }
        return \false;
    }
    public function upgradePassword(PasswordAuthenticatedUserInterface $user, string $newHashedPassword): void
    {
        foreach ($this->providers as $provider) {
            if ($provider instanceof PasswordUpgraderInterface) {
                try {
                    $provider->upgradePassword($user, $newHashedPassword);
                } catch (UnsupportedUserException) {
                    // ignore: password upgrades are opportunistic
                }
            }
        }
    }
}
Security Component - Core
=========================

Security provides an infrastructure for sophisticated authorization systems,
which makes it possible to easily separate the actual authorization logic from
so called user providers that hold the users credentials.

Getting Started
---------------

```
$ composer require symfony/security-core
```

```php
use Symfony\Component\Security\Core\Authentication\AuthenticationTrustResolver;
use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken;
use Symfony\Component\Security\Core\Authorization\AccessDecisionManager;
use Symfony\Component\Security\Core\Authorization\Voter\AuthenticatedVoter;
use Symfony\Component\Security\Core\Authorization\Voter\RoleVoter;
use Symfony\Component\Security\Core\Authorization\Voter\RoleHierarchyVoter;
use Symfony\Component\Security\Core\Exception\AccessDeniedException;
use Symfony\Component\Security\Core\Role\RoleHierarchy;

$accessDecisionManager = new AccessDecisionManager([
    new AuthenticatedVoter(new AuthenticationTrustResolver()),
    new RoleVoter(),
    new RoleHierarchyVoter(new RoleHierarchy([
        'ROLE_ADMIN' => ['ROLE_USER'],
    ]))
]);

$user = new \App\Entity\User(...);
$token = new UsernamePasswordToken($user, 'main', $user->getRoles());

if (!$accessDecisionManager->decide($token, ['ROLE_ADMIN'])) {
    throw new AccessDeniedException();
}
```

Sponsor
-------

The Security component for Symfony 6.4 is [backed][1] by [SymfonyCasts][2].

Learn Symfony faster by watching real projects being built and actively coding
along with them. SymfonyCasts bridges that learning gap, bringing you video
tutorials and coding challenges. Code on!

Help Symfony by [sponsoring][3] its development!

Resources
---------

 * [Documentation](https://symfony.com/doc/current/components/security.html)
 * [Contributing](https://symfony.com/doc/current/contributing/index.html)
 * [Report issues](https://github.com/symfony/symfony/issues) and
   [send Pull Requests](https://github.com/symfony/symfony/pulls)
   in the [main Symfony repository](https://github.com/symfony/symfony)

[1]: https://symfony.com/backers
[2]: https://symfonycasts.com
[3]: https://symfony.com/sponsor
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Security\Core\Authorization;

/**
 * The AuthorizationCheckerInterface.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
interface AuthorizationCheckerInterface
{
    /**
     * Checks if the attribute is granted against the current authentication token and optionally supplied subject.
     *
     * @param mixed $attribute A single attribute to vote on (can be of any type, string and instance of Expression are supported by the core)
     */
    public function isGranted(mixed $attribute, mixed $subject = null): bool;
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Security\Core\Authorization;

use _ContaoManager\Symfony\Component\ExpressionLanguage\ExpressionFunction;
use _ContaoManager\Symfony\Component\ExpressionLanguage\ExpressionFunctionProviderInterface;
/**
 * Define some ExpressionLanguage functions.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class ExpressionLanguageProvider implements ExpressionFunctionProviderInterface
{
    public function getFunctions(): array
    {
        return [new ExpressionFunction('is_authenticated', fn() => '$auth_checker->isGranted("IS_AUTHENTICATED")', fn(array $variables) => $variables['auth_checker']->isGranted('IS_AUTHENTICATED')), new ExpressionFunction('is_fully_authenticated', fn() => '$token && $auth_checker->isGranted("IS_AUTHENTICATED_FULLY")', fn(array $variables) => $variables['token'] && $variables['auth_checker']->isGranted('IS_AUTHENTICATED_FULLY')), new ExpressionFunction('is_granted', fn($attributes, $object = 'null') => \sprintf('$auth_checker->isGranted(%s, %s)', $attributes, $object), fn(array $variables, $attributes, $object = null) => $variables['auth_checker']->isGranted($attributes, $object)), new ExpressionFunction('is_remember_me', fn() => '$token && $auth_checker->isGranted("IS_REMEMBERED")', fn(array $variables) => $variables['token'] && $variables['auth_checker']->isGranted('IS_REMEMBERED'))];
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Security\Core\Authorization;

use _ContaoManager\Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use _ContaoManager\Symfony\Component\Security\Core\Authorization\Strategy\AccessDecisionStrategyInterface;
use _ContaoManager\Symfony\Component\Security\Core\Authorization\Voter\VoterInterface;
/**
 * Decorates the original AccessDecisionManager class to log information
 * about the security voters and the decisions made by them.
 *
 * @author Javier Eguiluz <javier.eguiluz@gmail.com>
 *
 * @internal
 */
class TraceableAccessDecisionManager implements AccessDecisionManagerInterface
{
    private AccessDecisionManagerInterface $manager;
    private ?AccessDecisionStrategyInterface $strategy = null;
    /** @var iterable<mixed, VoterInterface> */
    private iterable $voters = [];
    private array $decisionLog = [];
    // All decision logs
    private array $currentLog = [];
    // Logs being filled in
    public function __construct(AccessDecisionManagerInterface $manager)
    {
        $this->manager = $manager;
        // The strategy and voters are stored in a private properties of the decorated service
        if (property_exists($manager, 'strategy')) {
            $reflection = new \ReflectionProperty($manager::class, 'strategy');
            $this->strategy = $reflection->getValue($manager);
        }
        if (property_exists($manager, 'voters')) {
            $reflection = new \ReflectionProperty($manager::class, 'voters');
            $this->voters = $reflection->getValue($manager);
        }
    }
    public function decide(TokenInterface $token, array $attributes, mixed $object = null, bool $allowMultipleAttributes = \false): bool
    {
        $currentDecisionLog = ['attributes' => $attributes, 'object' => $object, 'voterDetails' => []];
        $this->currentLog[] =& $currentDecisionLog;
        $result = $this->manager->decide($token, $attributes, $object, $allowMultipleAttributes);
        $currentDecisionLog['result'] = $result;
        $this->decisionLog[] = array_pop($this->currentLog);
        // Using a stack since decide can be called by voters
        return $result;
    }
    /**
     * Adds voter vote and class to the voter details.
     *
     * @param array $attributes attributes used for the vote
     * @param int   $vote       vote of the voter
     */
    public function addVoterVote(VoterInterface $voter, array $attributes, int $vote): void
    {
        $currentLogIndex = \count($this->currentLog) - 1;
        $this->currentLog[$currentLogIndex]['voterDetails'][] = ['voter' => $voter, 'attributes' => $attributes, 'vote' => $vote];
    }
    public function getStrategy(): string
    {
        if (null === $this->strategy) {
            return '-';
        }
        if (method_exists($this->strategy, '__toString')) {
            return (string) $this->strategy;
        }
        return get_debug_type($this->strategy);
    }
    /**
     * @return iterable<mixed, VoterInterface>
     */
    public function getVoters(): iterable
    {
        return $this->voters;
    }
    public function getDecisionLog(): array
    {
        return $this->decisionLog;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Security\Core\Authorization;

use _ContaoManager\Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use _ContaoManager\Symfony\Component\Security\Core\Authorization\Strategy\AccessDecisionStrategyInterface;
use _ContaoManager\Symfony\Component\Security\Core\Authorization\Strategy\AffirmativeStrategy;
use _ContaoManager\Symfony\Component\Security\Core\Authorization\Voter\CacheableVoterInterface;
use _ContaoManager\Symfony\Component\Security\Core\Authorization\Voter\VoterInterface;
use _ContaoManager\Symfony\Component\Security\Core\Exception\InvalidArgumentException;
/**
 * AccessDecisionManager is the base class for all access decision managers
 * that use decision voters.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
final class AccessDecisionManager implements AccessDecisionManagerInterface
{
    private const VALID_VOTES = [VoterInterface::ACCESS_GRANTED => \true, VoterInterface::ACCESS_DENIED => \true, VoterInterface::ACCESS_ABSTAIN => \true];
    private iterable $voters;
    private array $votersCacheAttributes = [];
    private array $votersCacheObject = [];
    private AccessDecisionStrategyInterface $strategy;
    /**
     * @param iterable<mixed, VoterInterface> $voters An array or an iterator of VoterInterface instances
     */
    public function __construct(iterable $voters = [], ?AccessDecisionStrategyInterface $strategy = null)
    {
        $this->voters = $voters;
        $this->strategy = $strategy ?? new AffirmativeStrategy();
    }
    /**
     * @param bool $allowMultipleAttributes Whether to allow passing multiple values to the $attributes array
     */
    public function decide(TokenInterface $token, array $attributes, mixed $object = null, bool $allowMultipleAttributes = \false): bool
    {
        // Special case for AccessListener, do not remove the right side of the condition before 6.0
        if (\count($attributes) > 1 && !$allowMultipleAttributes) {
            throw new InvalidArgumentException(\sprintf('Passing more than one Security attribute to "%s()" is not supported.', __METHOD__));
        }
        return $this->strategy->decide($this->collectResults($token, $attributes, $object));
    }
    /**
     * @return \Traversable<int, int>
     */
    private function collectResults(TokenInterface $token, array $attributes, mixed $object): \Traversable
    {
        foreach ($this->getVoters($attributes, $object) as $voter) {
            $result = $voter->vote($token, $object, $attributes);
            if (!\is_int($result) || !(self::VALID_VOTES[$result] ?? \false)) {
                throw new \LogicException(\sprintf('"%s::vote()" must return one of "%s" constants ("ACCESS_GRANTED", "ACCESS_DENIED" or "ACCESS_ABSTAIN"), "%s" returned.', get_debug_type($voter), VoterInterface::class, var_export($result, \true)));
            }
            yield $result;
        }
    }
    /**
     * @return iterable<mixed, VoterInterface>
     */
    private function getVoters(array $attributes, $object = null): iterable
    {
        $keyAttributes = [];
        foreach ($attributes as $attribute) {
            $keyAttributes[] = \is_string($attribute) ? $attribute : null;
        }
        // use `get_class` to handle anonymous classes
        $keyObject = \is_object($object) ? $object::class : get_debug_type($object);
        foreach ($this->voters as $key => $voter) {
            if (!$voter instanceof CacheableVoterInterface) {
                yield $voter;
                continue;
            }
            $supports = \true;
            // The voter supports the attributes if it supports at least one attribute of the list
            foreach ($keyAttributes as $keyAttribute) {
                if (null === $keyAttribute) {
                    $supports = \true;
                } elseif (!isset($this->votersCacheAttributes[$keyAttribute][$key])) {
                    $this->votersCacheAttributes[$keyAttribute][$key] = $supports = $voter->supportsAttribute($keyAttribute);
                } else {
                    $supports = $this->votersCacheAttributes[$keyAttribute][$key];
                }
                if ($supports) {
                    break;
                }
            }
            if (!$supports) {
                continue;
            }
            if (!isset($this->votersCacheObject[$keyObject][$key])) {
                $this->votersCacheObject[$keyObject][$key] = $supports = $voter->supportsType($keyObject);
            } else {
                $supports = $this->votersCacheObject[$keyObject][$key];
            }
            if (!$supports) {
                continue;
            }
            yield $voter;
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Security\Core\Authorization;

use _ContaoManager\Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
/**
 * AccessDecisionManagerInterface makes authorization decisions.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
interface AccessDecisionManagerInterface
{
    /**
     * Decides whether the access is possible or not.
     *
     * @param array $attributes An array of attributes associated with the method being invoked
     * @param mixed $object     The object to secure
     */
    public function decide(TokenInterface $token, array $attributes, mixed $object = null): bool;
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Security\Core\Authorization\Voter;

use _ContaoManager\Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
/**
 * VoterInterface is the interface implemented by all voters.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
interface VoterInterface
{
    public const ACCESS_GRANTED = 1;
    public const ACCESS_ABSTAIN = 0;
    public const ACCESS_DENIED = -1;
    /**
     * Returns the vote for the given parameters.
     *
     * This method must return one of the following constants:
     * ACCESS_GRANTED, ACCESS_DENIED, or ACCESS_ABSTAIN.
     *
     * @param mixed $subject    The subject to secure
     * @param array $attributes An array of attributes associated with the method being invoked
     *
     * @return int either ACCESS_GRANTED, ACCESS_ABSTAIN, or ACCESS_DENIED
     *
     * @psalm-return self::ACCESS_* must be transformed into @return on Symfony 7
     */
    public function vote(TokenInterface $token, mixed $subject, array $attributes);
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Security\Core\Authorization\Voter;

/**
 * Let voters expose the attributes and types they care about.
 *
 * By returning false to either `supportsAttribute` or `supportsType`, the
 * voter will never be called for the specified attribute or subject.
 *
 * @author Jérémy Derussé <jeremy@derusse.com>
 */
interface CacheableVoterInterface extends VoterInterface
{
    public function supportsAttribute(string $attribute): bool;
    /**
     * @param string $subjectType The type of the subject inferred by `get_class` or `get_debug_type`
     */
    public function supportsType(string $subjectType): bool;
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Security\Core\Authorization\Voter;

use _ContaoManager\Symfony\Component\ExpressionLanguage\Expression;
use _ContaoManager\Symfony\Component\HttpFoundation\Request;
use _ContaoManager\Symfony\Component\Security\Core\Authentication\AuthenticationTrustResolverInterface;
use _ContaoManager\Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use _ContaoManager\Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface;
use _ContaoManager\Symfony\Component\Security\Core\Authorization\ExpressionLanguage;
use _ContaoManager\Symfony\Component\Security\Core\Role\RoleHierarchyInterface;
/**
 * ExpressionVoter votes based on the evaluation of an expression.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class ExpressionVoter implements CacheableVoterInterface
{
    private ExpressionLanguage $expressionLanguage;
    private AuthenticationTrustResolverInterface $trustResolver;
    private AuthorizationCheckerInterface $authChecker;
    private ?RoleHierarchyInterface $roleHierarchy;
    public function __construct(ExpressionLanguage $expressionLanguage, AuthenticationTrustResolverInterface $trustResolver, AuthorizationCheckerInterface $authChecker, ?RoleHierarchyInterface $roleHierarchy = null)
    {
        $this->expressionLanguage = $expressionLanguage;
        $this->trustResolver = $trustResolver;
        $this->authChecker = $authChecker;
        $this->roleHierarchy = $roleHierarchy;
    }
    public function supportsAttribute(string $attribute): bool
    {
        return \false;
    }
    public function supportsType(string $subjectType): bool
    {
        return \true;
    }
    public function vote(TokenInterface $token, mixed $subject, array $attributes): int
    {
        $result = VoterInterface::ACCESS_ABSTAIN;
        $variables = null;
        foreach ($attributes as $attribute) {
            if (!$attribute instanceof Expression) {
                continue;
            }
            $variables ??= $this->getVariables($token, $subject);
            $result = VoterInterface::ACCESS_DENIED;
            if ($this->expressionLanguage->evaluate($attribute, $variables)) {
                return VoterInterface::ACCESS_GRANTED;
            }
        }
        return $result;
    }
    private function getVariables(TokenInterface $token, mixed $subject): array
    {
        $roleNames = $token->getRoleNames();
        if (null !== $this->roleHierarchy) {
            $roleNames = $this->roleHierarchy->getReachableRoleNames($roleNames);
        }
        $variables = ['token' => $token, 'user' => $token->getUser(), 'object' => $subject, 'subject' => $subject, 'role_names' => $roleNames, 'trust_resolver' => $this->trustResolver, 'auth_checker' => $this->authChecker];
        // this is mainly to propose a better experience when the expression is used
        // in an access control rule, as the developer does not know that it's going
        // to be handled by this voter
        if ($subject instanceof Request) {
            $variables['request'] = $subject;
        }
        return $variables;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Security\Core\Authorization\Voter;

use _ContaoManager\Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use _ContaoManager\Symfony\Component\Security\Core\Role\RoleHierarchyInterface;
/**
 * RoleHierarchyVoter uses a RoleHierarchy to determine the roles granted to
 * the user before voting.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class RoleHierarchyVoter extends RoleVoter
{
    private RoleHierarchyInterface $roleHierarchy;
    public function __construct(RoleHierarchyInterface $roleHierarchy, string $prefix = 'ROLE_')
    {
        $this->roleHierarchy = $roleHierarchy;
        parent::__construct($prefix);
    }
    /**
     * @return array
     */
    protected function extractRoles(TokenInterface $token)
    {
        return $this->roleHierarchy->getReachableRoleNames($token->getRoleNames());
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Security\Core\Authorization\Voter;

use _ContaoManager\Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use _ContaoManager\Symfony\Component\Security\Core\Event\VoteEvent;
use _ContaoManager\Symfony\Contracts\EventDispatcher\EventDispatcherInterface;
/**
 * Decorates voter classes to send result events.
 *
 * @author Laurent VOULLEMIER <laurent.voullemier@gmail.com>
 *
 * @internal
 */
class TraceableVoter implements CacheableVoterInterface
{
    private VoterInterface $voter;
    private EventDispatcherInterface $eventDispatcher;
    public function __construct(VoterInterface $voter, EventDispatcherInterface $eventDispatcher)
    {
        $this->voter = $voter;
        $this->eventDispatcher = $eventDispatcher;
    }
    public function vote(TokenInterface $token, mixed $subject, array $attributes): int
    {
        $result = $this->voter->vote($token, $subject, $attributes);
        $this->eventDispatcher->dispatch(new VoteEvent($this->voter, $subject, $attributes, $result), 'debug.security.authorization.vote');
        return $result;
    }
    public function getDecoratedVoter(): VoterInterface
    {
        return $this->voter;
    }
    public function supportsAttribute(string $attribute): bool
    {
        return !$this->voter instanceof CacheableVoterInterface || $this->voter->supportsAttribute($attribute);
    }
    public function supportsType(string $subjectType): bool
    {
        return !$this->voter instanceof CacheableVoterInterface || $this->voter->supportsType($subjectType);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Security\Core\Authorization\Voter;

use _ContaoManager\Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
/**
 * Voter is an abstract default implementation of a voter.
 *
 * @author Roman Marintšenko <inoryy@gmail.com>
 * @author Grégoire Pineau <lyrixx@lyrixx.info>
 *
 * @template TAttribute of string
 * @template TSubject of mixed
 */
abstract class Voter implements VoterInterface, CacheableVoterInterface
{
    public function vote(TokenInterface $token, mixed $subject, array $attributes): int
    {
        // abstain vote by default in case none of the attributes are supported
        $vote = self::ACCESS_ABSTAIN;
        foreach ($attributes as $attribute) {
            try {
                if (!$this->supports($attribute, $subject)) {
                    continue;
                }
            } catch (\TypeError $e) {
                if (str_contains($e->getMessage(), 'supports(): Argument #1')) {
                    continue;
                }
                throw $e;
            }
            // as soon as at least one attribute is supported, default is to deny access
            $vote = self::ACCESS_DENIED;
            if ($this->voteOnAttribute($attribute, $subject, $token)) {
                // grant access as soon as at least one attribute returns a positive response
                return self::ACCESS_GRANTED;
            }
        }
        return $vote;
    }
    /**
     * Return false if your voter doesn't support the given attribute. Symfony will cache
     * that decision and won't call your voter again for that attribute.
     */
    public function supportsAttribute(string $attribute): bool
    {
        return \true;
    }
    /**
     * Return false if your voter doesn't support the given subject type. Symfony will cache
     * that decision and won't call your voter again for that subject type.
     *
     * @param string $subjectType The type of the subject inferred by `get_class()` or `get_debug_type()`
     */
    public function supportsType(string $subjectType): bool
    {
        return \true;
    }
    /**
     * Determines if the attribute and subject are supported by this voter.
     *
     * @param mixed $subject The subject to secure, e.g. an object the user wants to access or any other PHP type
     *
     * @psalm-assert-if-true TSubject $subject
     * @psalm-assert-if-true TAttribute $attribute
     */
    abstract protected function supports(string $attribute, mixed $subject): bool;
    /**
     * Perform a single access check operation on a given attribute, subject and token.
     * It is safe to assume that $attribute and $subject already passed the "supports()" method check.
     *
     * @param TAttribute $attribute
     * @param TSubject   $subject
     */
    abstract protected function voteOnAttribute(string $attribute, mixed $subject, TokenInterface $token): bool;
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Security\Core\Authorization\Voter;

use _ContaoManager\Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
/**
 * RoleVoter votes if any attribute starts with a given prefix.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class RoleVoter implements CacheableVoterInterface
{
    private string $prefix;
    public function __construct(string $prefix = 'ROLE_')
    {
        $this->prefix = $prefix;
    }
    public function vote(TokenInterface $token, mixed $subject, array $attributes): int
    {
        $result = VoterInterface::ACCESS_ABSTAIN;
        $roles = $this->extractRoles($token);
        foreach ($attributes as $attribute) {
            if (!\is_string($attribute) || !str_starts_with($attribute, $this->prefix)) {
                continue;
            }
            $result = VoterInterface::ACCESS_DENIED;
            foreach ($roles as $role) {
                if ($attribute === $role) {
                    return VoterInterface::ACCESS_GRANTED;
                }
            }
        }
        return $result;
    }
    public function supportsAttribute(string $attribute): bool
    {
        return str_starts_with($attribute, $this->prefix);
    }
    public function supportsType(string $subjectType): bool
    {
        return \true;
    }
    /**
     * @return array
     */
    protected function extractRoles(TokenInterface $token)
    {
        return $token->getRoleNames();
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Security\Core\Authorization\Voter;

use _ContaoManager\Symfony\Component\Security\Core\Authentication\AuthenticationTrustResolverInterface;
use _ContaoManager\Symfony\Component\Security\Core\Authentication\Token\SwitchUserToken;
use _ContaoManager\Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
/**
 * AuthenticatedVoter votes if an attribute like IS_AUTHENTICATED_FULLY,
 * IS_AUTHENTICATED_REMEMBERED, IS_AUTHENTICATED is present.
 *
 * This list is most restrictive to least restrictive checking.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
class AuthenticatedVoter implements CacheableVoterInterface
{
    public const IS_AUTHENTICATED_FULLY = 'IS_AUTHENTICATED_FULLY';
    public const IS_AUTHENTICATED_REMEMBERED = 'IS_AUTHENTICATED_REMEMBERED';
    public const IS_AUTHENTICATED = 'IS_AUTHENTICATED';
    public const IS_IMPERSONATOR = 'IS_IMPERSONATOR';
    public const IS_REMEMBERED = 'IS_REMEMBERED';
    public const PUBLIC_ACCESS = 'PUBLIC_ACCESS';
    private AuthenticationTrustResolverInterface $authenticationTrustResolver;
    public function __construct(AuthenticationTrustResolverInterface $authenticationTrustResolver)
    {
        $this->authenticationTrustResolver = $authenticationTrustResolver;
    }
    public function vote(TokenInterface $token, mixed $subject, array $attributes): int
    {
        if ($attributes === [self::PUBLIC_ACCESS]) {
            return VoterInterface::ACCESS_GRANTED;
        }
        $result = VoterInterface::ACCESS_ABSTAIN;
        foreach ($attributes as $attribute) {
            if (null === $attribute || self::IS_AUTHENTICATED_FULLY !== $attribute && self::IS_AUTHENTICATED_REMEMBERED !== $attribute && self::IS_AUTHENTICATED !== $attribute && self::IS_IMPERSONATOR !== $attribute && self::IS_REMEMBERED !== $attribute) {
                continue;
            }
            $result = VoterInterface::ACCESS_DENIED;
            if (self::IS_AUTHENTICATED_FULLY === $attribute && $this->authenticationTrustResolver->isFullFledged($token)) {
                return VoterInterface::ACCESS_GRANTED;
            }
            if (self::IS_AUTHENTICATED_REMEMBERED === $attribute && ($this->authenticationTrustResolver->isRememberMe($token) || $this->authenticationTrustResolver->isFullFledged($token))) {
                return VoterInterface::ACCESS_GRANTED;
            }
            if (self::IS_AUTHENTICATED === $attribute && $this->authenticationTrustResolver->isAuthenticated($token)) {
                return VoterInterface::ACCESS_GRANTED;
            }
            if (self::IS_REMEMBERED === $attribute && $this->authenticationTrustResolver->isRememberMe($token)) {
                return VoterInterface::ACCESS_GRANTED;
            }
            if (self::IS_IMPERSONATOR === $attribute && $token instanceof SwitchUserToken) {
                return VoterInterface::ACCESS_GRANTED;
            }
        }
        return $result;
    }
    public function supportsAttribute(string $attribute): bool
    {
        return \in_array($attribute, [self::IS_AUTHENTICATED_FULLY, self::IS_AUTHENTICATED_REMEMBERED, self::IS_AUTHENTICATED, self::IS_IMPERSONATOR, self::IS_REMEMBERED, self::PUBLIC_ACCESS], \true);
    }
    public function supportsType(string $subjectType): bool
    {
        return \true;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Security\Core\Authorization;

use _ContaoManager\Psr\Cache\CacheItemPoolInterface;
use _ContaoManager\Symfony\Component\ExpressionLanguage\ExpressionLanguage as BaseExpressionLanguage;
if (!class_exists(BaseExpressionLanguage::class)) {
    throw new \LogicException(\sprintf('The "%s" class requires the "ExpressionLanguage" component. Try running "composer require symfony/expression-language".', ExpressionLanguage::class));
} else {
    // Help opcache.preload discover always-needed symbols
    class_exists(ExpressionLanguageProvider::class);
    /**
     * Adds some function to the default ExpressionLanguage.
     *
     * @author Fabien Potencier <fabien@symfony.com>
     *
     * @see ExpressionLanguageProvider
     */
    class ExpressionLanguage extends BaseExpressionLanguage
    {
        public function __construct(?CacheItemPoolInterface $cache = null, array $providers = [])
        {
            // prepend the default provider to let users override it easily
            array_unshift($providers, new ExpressionLanguageProvider());
            parent::__construct($cache, $providers);
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Security\Core\Authorization;

use _ContaoManager\Symfony\Component\Security\Core\Authentication\Token\NullToken;
use _ContaoManager\Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
/**
 * AuthorizationChecker is the main authorization point of the Security component.
 *
 * It gives access to the token representing the current user authentication.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
class AuthorizationChecker implements AuthorizationCheckerInterface
{
    private TokenStorageInterface $tokenStorage;
    private AccessDecisionManagerInterface $accessDecisionManager;
    public function __construct(TokenStorageInterface $tokenStorage, AccessDecisionManagerInterface $accessDecisionManager, bool $exceptionOnNoToken = \false)
    {
        if ($exceptionOnNoToken) {
            throw new \LogicException(\sprintf('Argument $exceptionOnNoToken of "%s()" must be set to "false".', __METHOD__));
        }
        $this->tokenStorage = $tokenStorage;
        $this->accessDecisionManager = $accessDecisionManager;
    }
    final public function isGranted(mixed $attribute, mixed $subject = null): bool
    {
        $token = $this->tokenStorage->getToken();
        if (!$token || !$token->getUser()) {
            $token = new NullToken();
        }
        return $this->accessDecisionManager->decide($token, [$attribute], $subject);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Security\Core\Authorization\Strategy;

use _ContaoManager\Symfony\Component\Security\Core\Authorization\Voter\VoterInterface;
/**
 * Grant or deny access depending on the first voter that does not abstain.
 * The priority of voters can be used to overrule a decision.
 *
 * If all voters abstained from voting, the decision will be based on the
 * allowIfAllAbstainDecisions property value (defaults to false).
 *
 * @author Fabien Potencier <fabien@symfony.com>
 * @author Alexander M. Turek <me@derrabus.de>
 */
final class PriorityStrategy implements AccessDecisionStrategyInterface, \Stringable
{
    private bool $allowIfAllAbstainDecisions;
    public function __construct(bool $allowIfAllAbstainDecisions = \false)
    {
        $this->allowIfAllAbstainDecisions = $allowIfAllAbstainDecisions;
    }
    public function decide(\Traversable $results): bool
    {
        foreach ($results as $result) {
            if (VoterInterface::ACCESS_GRANTED === $result) {
                return \true;
            }
            if (VoterInterface::ACCESS_DENIED === $result) {
                return \false;
            }
        }
        return $this->allowIfAllAbstainDecisions;
    }
    public function __toString(): string
    {
        return 'priority';
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Security\Core\Authorization\Strategy;

use _ContaoManager\Symfony\Component\Security\Core\Authorization\Voter\VoterInterface;
/**
 * Grants access if only grant (or abstain) votes were received.
 *
 * If all voters abstained from voting, the decision will be based on the
 * allowIfAllAbstainDecisions property value (defaults to false).
 *
 * @author Fabien Potencier <fabien@symfony.com>
 * @author Alexander M. Turek <me@derrabus.de>
 */
final class UnanimousStrategy implements AccessDecisionStrategyInterface, \Stringable
{
    private bool $allowIfAllAbstainDecisions;
    public function __construct(bool $allowIfAllAbstainDecisions = \false)
    {
        $this->allowIfAllAbstainDecisions = $allowIfAllAbstainDecisions;
    }
    public function decide(\Traversable $results): bool
    {
        $grant = 0;
        foreach ($results as $result) {
            if (VoterInterface::ACCESS_DENIED === $result) {
                return \false;
            }
            if (VoterInterface::ACCESS_GRANTED === $result) {
                ++$grant;
            }
        }
        // no deny votes
        if ($grant > 0) {
            return \true;
        }
        return $this->allowIfAllAbstainDecisions;
    }
    public function __toString(): string
    {
        return 'unanimous';
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Security\Core\Authorization\Strategy;

use _ContaoManager\Symfony\Component\Security\Core\Authorization\Voter\VoterInterface;
/**
 * Grants access if any voter returns an affirmative response.
 *
 * If all voters abstained from voting, the decision will be based on the
 * allowIfAllAbstainDecisions property value (defaults to false).
 *
 * @author Fabien Potencier <fabien@symfony.com>
 * @author Alexander M. Turek <me@derrabus.de>
 */
final class AffirmativeStrategy implements AccessDecisionStrategyInterface, \Stringable
{
    private bool $allowIfAllAbstainDecisions;
    public function __construct(bool $allowIfAllAbstainDecisions = \false)
    {
        $this->allowIfAllAbstainDecisions = $allowIfAllAbstainDecisions;
    }
    public function decide(\Traversable $results): bool
    {
        $deny = 0;
        foreach ($results as $result) {
            if (VoterInterface::ACCESS_GRANTED === $result) {
                return \true;
            }
            if (VoterInterface::ACCESS_DENIED === $result) {
                ++$deny;
            }
        }
        if ($deny > 0) {
            return \false;
        }
        return $this->allowIfAllAbstainDecisions;
    }
    public function __toString(): string
    {
        return 'affirmative';
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Security\Core\Authorization\Strategy;

use _ContaoManager\Symfony\Component\Security\Core\Authorization\Voter\VoterInterface;
/**
 * Grants access if there is consensus of granted against denied responses.
 *
 * Consensus means majority-rule (ignoring abstains) rather than unanimous
 * agreement (ignoring abstains). If you require unanimity, see
 * UnanimousBased.
 *
 * If there were an equal number of grant and deny votes, the decision will
 * be based on the allowIfEqualGrantedDeniedDecisions property value
 * (defaults to true).
 *
 * If all voters abstained from voting, the decision will be based on the
 * allowIfAllAbstainDecisions property value (defaults to false).
 *
 * @author Fabien Potencier <fabien@symfony.com>
 * @author Alexander M. Turek <me@derrabus.de>
 */
final class ConsensusStrategy implements AccessDecisionStrategyInterface, \Stringable
{
    private bool $allowIfAllAbstainDecisions;
    private bool $allowIfEqualGrantedDeniedDecisions;
    public function __construct(bool $allowIfAllAbstainDecisions = \false, bool $allowIfEqualGrantedDeniedDecisions = \true)
    {
        $this->allowIfAllAbstainDecisions = $allowIfAllAbstainDecisions;
        $this->allowIfEqualGrantedDeniedDecisions = $allowIfEqualGrantedDeniedDecisions;
    }
    public function decide(\Traversable $results): bool
    {
        $grant = 0;
        $deny = 0;
        foreach ($results as $result) {
            if (VoterInterface::ACCESS_GRANTED === $result) {
                ++$grant;
            } elseif (VoterInterface::ACCESS_DENIED === $result) {
                ++$deny;
            }
        }
        if ($grant > $deny) {
            return \true;
        }
        if ($deny > $grant) {
            return \false;
        }
        if ($grant > 0) {
            return $this->allowIfEqualGrantedDeniedDecisions;
        }
        return $this->allowIfAllAbstainDecisions;
    }
    public function __toString(): string
    {
        return 'consensus';
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Security\Core\Authorization\Strategy;

/**
 * A strategy for turning a stream of votes into a final decision.
 *
 * @author Alexander M. Turek <me@derrabus.de>
 */
interface AccessDecisionStrategyInterface
{
    /**
     * @param \Traversable<int> $results
     */
    public function decide(\Traversable $results): bool;
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Security\Core;

use _ContaoManager\Psr\Container\ContainerInterface;
use _ContaoManager\Symfony\Bundle\SecurityBundle\Security as NewSecurityHelper;
use _ContaoManager\Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use _ContaoManager\Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface;
use _ContaoManager\Symfony\Component\Security\Core\User\UserInterface;
/**
 * Helper class for commonly-needed security tasks.
 *
 * @deprecated since Symfony 6.2, use \Symfony\Bundle\SecurityBundle\Security instead
 */
class Security implements AuthorizationCheckerInterface
{
    public const ACCESS_DENIED_ERROR = '_security.403_error';
    public const AUTHENTICATION_ERROR = '_security.last_error';
    public const LAST_USERNAME = '_security.last_username';
    /**
     * @deprecated since Symfony 6.2, use \Symfony\Component\Security\Http\Authenticator\Passport\Badge\UserBadge::MAX_USERNAME_LENGTH instead
     */
    public const MAX_USERNAME_LENGTH = 4096;
    private ContainerInterface $container;
    public function __construct(ContainerInterface $container, bool $triggerDeprecation = \true)
    {
        $this->container = $container;
        if ($triggerDeprecation) {
            trigger_deprecation('symfony/security-core', '6.2', 'The "%s" class is deprecated, use "%s" instead.', __CLASS__, NewSecurityHelper::class);
        }
    }
    public function getUser(): ?UserInterface
    {
        if (!$token = $this->getToken()) {
            return null;
        }
        return $token->getUser();
    }
    /**
     * Checks if the attributes are granted against the current authentication token and optionally supplied subject.
     */
    public function isGranted(mixed $attributes, mixed $subject = null): bool
    {
        return $this->container->get('security.authorization_checker')->isGranted($attributes, $subject);
    }
    public function getToken(): ?TokenInterface
    {
        return $this->container->get('security.token_storage')->getToken();
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Security\Core\Exception;

use _ContaoManager\Symfony\Component\HttpKernel\Attribute\WithHttpStatus;
/**
 * AccessDeniedException is thrown when the account has not the required role.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
#[WithHttpStatus(403)]
class AccessDeniedException extends RuntimeException
{
    private array $attributes = [];
    private mixed $subject = null;
    public function __construct(string $message = 'Access Denied.', ?\Throwable $previous = null, int $code = 403)
    {
        parent::__construct($message, $code, $previous);
    }
    public function getAttributes(): array
    {
        return $this->attributes;
    }
    /**
     * @return void
     */
    public function setAttributes(array|string $attributes)
    {
        $this->attributes = (array) $attributes;
    }
    public function getSubject(): mixed
    {
        return $this->subject;
    }
    /**
     * @return void
     */
    public function setSubject(mixed $subject)
    {
        $this->subject = $subject;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Security\Core\Exception;

/**
 * This exception is thrown when the csrf token is invalid.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 * @author Alexander <iam.asm89@gmail.com>
 */
class InvalidCsrfTokenException extends AuthenticationException
{
    public function getMessageKey(): string
    {
        return 'Invalid CSRF token.';
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Security\Core\Exception;

/**
 * LogoutException is thrown when the account cannot be logged out.
 *
 * @author Jeremy Mikola <jmikola@gmail.com>
 */
class LogoutException extends RuntimeException
{
    public function __construct(string $message = 'Logout Exception', ?\Throwable $previous = null)
    {
        parent::__construct($message, 403, $previous);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Security\Core\Exception;

/**
 * Base LogicException for the Security component.
 *
 * @author Iltar van der Berg <kjarli@gmail.com>
 */
class LogicException extends \LogicException implements ExceptionInterface
{
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Security\Core\Exception;

use _ContaoManager\Symfony\Component\HttpFoundation\Response;
/**
 * A signaling exception that wraps a lazily computed response.
 *
 * @author Nicolas Grekas <p@tchwork.com>
 */
class LazyResponseException extends \Exception implements ExceptionInterface
{
    private Response $response;
    public function __construct(Response $response)
    {
        $this->response = $response;
    }
    public function getResponse(): Response
    {
        return $this->response;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Security\Core\Exception;

/**
 * An authentication exception where you can control the message shown to the user.
 *
 * Be sure that the message passed to this exception is something that
 * can be shown safely to your user. In other words, avoid catching
 * other exceptions and passing their message directly to this class.
 *
 * @author Ryan Weaver <ryan@knpuniversity.com>
 */
class CustomUserMessageAuthenticationException extends AuthenticationException
{
    private string $messageKey;
    private array $messageData = [];
    public function __construct(string $message = '', array $messageData = [], int $code = 0, ?\Throwable $previous = null)
    {
        parent::__construct($message, $code, $previous);
        $this->setSafeMessage($message, $messageData);
    }
    /**
     * Set a message that will be shown to the user.
     *
     * @param string $messageKey  The message or message key
     * @param array  $messageData Data to be passed into the translator
     *
     * @return void
     */
    public function setSafeMessage(string $messageKey, array $messageData = [])
    {
        $this->messageKey = $messageKey;
        $this->messageData = $messageData;
    }
    public function getMessageKey(): string
    {
        return $this->messageKey;
    }
    public function getMessageData(): array
    {
        return $this->messageData;
    }
    public function __serialize(): array
    {
        return [parent::__serialize(), $this->messageKey, $this->messageData];
    }
    public function __unserialize(array $data): void
    {
        [$parentData, $this->messageKey, $this->messageData] = $data;
        $parentData = \is_array($parentData) ? $parentData : unserialize($parentData);
        parent::__unserialize($parentData);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Security\Core\Exception;

/**
 * Base ExceptionInterface for the Security component.
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
interface ExceptionInterface extends \Throwable
{
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Security\Core\Exception;

/**
 * BadCredentialsException is thrown when the user credentials are invalid.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 * @author Alexander <iam.asm89@gmail.com>
 */
class BadCredentialsException extends AuthenticationException
{
    public function getMessageKey(): string
    {
        return 'Invalid credentials.';
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Security\Core\Exception;

/**
 * Base RuntimeException for the Security component.
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
class RuntimeException extends \RuntimeException implements ExceptionInterface
{
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Security\Core\Exception;

/**
 * DisabledException is thrown when the user account is disabled.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 * @author Alexander <iam.asm89@gmail.com>
 */
class DisabledException extends AccountStatusException
{
    public function getMessageKey(): string
    {
        return 'Account is disabled.';
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Security\Core\Exception;

/**
 * TokenNotFoundException is thrown if a Token cannot be found.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 * @author Alexander <iam.asm89@gmail.com>
 */
class TokenNotFoundException extends AuthenticationException
{
    public function getMessageKey(): string
    {
        return 'No token could be found.';
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Security\Core\Exception;

/**
 * ProviderNotFoundException is thrown when no AuthenticationProviderInterface instance
 * supports an authentication Token.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 * @author Alexander <iam.asm89@gmail.com>
 */
class ProviderNotFoundException extends AuthenticationException
{
    public function getMessageKey(): string
    {
        return 'No authentication provider found to support the authentication token.';
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Security\Core\Exception;

/**
 * This exception is thrown when no session is available.
 *
 * Possible reasons for this are:
 *
 *     a) The session timed out because the user waited too long.
 *     b) The user has disabled cookies, and a new session is started on each
 *        request.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 * @author Alexander <iam.asm89@gmail.com>
 */
class SessionUnavailableException extends AuthenticationException
{
    public function getMessageKey(): string
    {
        return 'No session available, it either timed out or cookies are not enabled.';
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Security\Core\Exception;

/**
 * Base InvalidArgumentException for the Security component.
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
class InvalidArgumentException extends \InvalidArgumentException implements ExceptionInterface
{
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Security\Core\Exception;

/**
 * AccountExpiredException is thrown when the user account has expired.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 * @author Alexander <iam.asm89@gmail.com>
 */
class AccountExpiredException extends AccountStatusException
{
    public function getMessageKey(): string
    {
        return 'Account has expired.';
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Security\Core\Exception;

/**
 * AuthenticationExpiredException is thrown when an authentication token becomes un-authenticated between requests.
 *
 * In practice, this is due to the User changing between requests (e.g. password changes),
 * causes the token to become un-authenticated.
 *
 * @author Ryan Weaver <ryan@knpuniversity.com>
 */
class AuthenticationExpiredException extends AccountStatusException
{
    public function getMessageKey(): string
    {
        return 'Authentication expired because your account information has changed.';
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Security\Core\Exception;

/**
 * This exception is thrown if there where too many failed login attempts in
 * this session.
 *
 * @author Wouter de Jong <wouter@wouterj.nl>
 */
class TooManyLoginAttemptsAuthenticationException extends AuthenticationException
{
    private ?int $threshold;
    public function __construct(?int $threshold = null)
    {
        $this->threshold = $threshold;
    }
    public function getMessageData(): array
    {
        return ['%minutes%' => $this->threshold, '%count%' => (int) $this->threshold];
    }
    public function getMessageKey(): string
    {
        return 'Too many failed login attempts, please try again ' . ($this->threshold ? 'in %minutes% minute' . ($this->threshold > 1 ? 's' : '') . '.' : 'later.');
    }
    public function __serialize(): array
    {
        return [$this->threshold, parent::__serialize()];
    }
    public function __unserialize(array $data): void
    {
        [$this->threshold, $parentData] = $data;
        $parentData = \is_array($parentData) ? $parentData : unserialize($parentData);
        parent::__unserialize($parentData);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Security\Core\Exception;

/**
 * This exception is thrown when the RememberMeServices implementation
 * detects that a presented cookie has already been used by someone else.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 * @author Alexander <iam.asm89@gmail.com>
 */
class CookieTheftException extends AuthenticationException
{
    public function getMessageKey(): string
    {
        return 'Cookie has already been used by someone else.';
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Security\Core\Exception;

/**
 * AuthenticationServiceException is thrown when an authentication request could not be processed due to a system problem.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 * @author Alexander <iam.asm89@gmail.com>
 */
class AuthenticationServiceException extends AuthenticationException
{
    public function getMessageKey(): string
    {
        return 'Authentication request could not be processed due to a system problem.';
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Security\Core\Exception;

/**
 * This exception is thrown when an account is reloaded from a provider which
 * doesn't support the passed implementation of UserInterface.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
class UnsupportedUserException extends AuthenticationServiceException
{
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Security\Core\Exception;

use _ContaoManager\Symfony\Component\Security\Core\User\UserInterface;
/**
 * AccountStatusException is the base class for authentication exceptions
 * caused by the user account status.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 * @author Alexander <iam.asm89@gmail.com>
 */
abstract class AccountStatusException extends AuthenticationException
{
    private ?UserInterface $user = null;
    /**
     * Get the user.
     */
    public function getUser(): ?UserInterface
    {
        return $this->user;
    }
    /**
     * @return void
     */
    public function setUser(UserInterface $user)
    {
        $this->user = $user;
    }
    public function __serialize(): array
    {
        return [$this->user, parent::__serialize()];
    }
    public function __unserialize(array $data): void
    {
        [$this->user, $parentData] = $data;
        $parentData = \is_array($parentData) ? $parentData : unserialize($parentData);
        parent::__unserialize($parentData);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Security\Core\Exception;

/**
 * An authentication exception caused by the user account status
 * where you can control the message shown to the user.
 *
 * Be sure that the message passed to this exception is something that
 * can be shown safely to your user. In other words, avoid catching
 * other exceptions and passing their message directly to this class.
 *
 * @author Vincent Langlet <vincentlanglet@github.com>
 */
class CustomUserMessageAccountStatusException extends AccountStatusException
{
    private string $messageKey;
    private array $messageData = [];
    public function __construct(string $message = '', array $messageData = [], int $code = 0, ?\Throwable $previous = null)
    {
        parent::__construct($message, $code, $previous);
        $this->setSafeMessage($message, $messageData);
    }
    /**
     * Sets a message that will be shown to the user.
     *
     * @param string $messageKey  The message or message key
     * @param array  $messageData Data to be passed into the translator
     *
     * @return void
     */
    public function setSafeMessage(string $messageKey, array $messageData = [])
    {
        $this->messageKey = $messageKey;
        $this->messageData = $messageData;
    }
    public function getMessageKey(): string
    {
        return $this->messageKey;
    }
    public function getMessageData(): array
    {
        return $this->messageData;
    }
    public function __serialize(): array
    {
        return [parent::__serialize(), $this->messageKey, $this->messageData];
    }
    public function __unserialize(array $data): void
    {
        [$parentData, $this->messageKey, $this->messageData] = $data;
        parent::__unserialize($parentData);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Security\Core\Exception;

/**
 * InsufficientAuthenticationException is thrown if the user credentials are not sufficiently trusted.
 *
 * This is the case when a user is anonymous and the resource to be displayed has an access role.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 * @author Alexander <iam.asm89@gmail.com>
 */
class InsufficientAuthenticationException extends AuthenticationException
{
    public function getMessageKey(): string
    {
        return 'Not privileged to request the resource.';
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Security\Core\Exception;

/**
 * LockedException is thrown if the user account is locked.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 * @author Alexander <iam.asm89@gmail.com>
 */
class LockedException extends AccountStatusException
{
    public function getMessageKey(): string
    {
        return 'Account is locked.';
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Security\Core\Exception;

use _ContaoManager\Symfony\Component\HttpKernel\Attribute\WithHttpStatus;
use _ContaoManager\Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
/**
 * AuthenticationException is the base class for all authentication exceptions.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 * @author Alexander <iam.asm89@gmail.com>
 */
#[WithHttpStatus(401)]
class AuthenticationException extends RuntimeException
{
    private ?TokenInterface $token = null;
    public function getToken(): ?TokenInterface
    {
        return $this->token;
    }
    /**
     * @return void
     */
    public function setToken(TokenInterface $token)
    {
        $this->token = $token;
    }
    /**
     * Returns all the necessary state of the object for serialization purposes.
     *
     * There is no need to serialize any entry, they should be returned as-is.
     * If you extend this method, keep in mind you MUST guarantee parent data is present in the state.
     * Here is an example of how to extend this method:
     * <code>
     *     public function __serialize(): array
     *     {
     *         return [$this->childAttribute, parent::__serialize()];
     *     }
     * </code>
     *
     * @see __unserialize()
     */
    public function __serialize(): array
    {
        return [$this->token, $this->code, $this->message, $this->file, $this->line];
    }
    /**
     * Restores the object state from an array given by __serialize().
     *
     * There is no need to unserialize any entry in $data, they are already ready-to-use.
     * If you extend this method, keep in mind you MUST pass the parent data to its respective class.
     * Here is an example of how to extend this method:
     * <code>
     *     public function __unserialize(array $data): void
     *     {
     *         [$this->childAttribute, $parentData] = $data;
     *         parent::__unserialize($parentData);
     *     }
     * </code>
     *
     * @see __serialize()
     */
    public function __unserialize(array $data): void
    {
        [$this->token, $this->code, $this->message, $this->file, $this->line] = $data;
    }
    /**
     * Message key to be used by the translation component.
     *
     * @return string
     */
    public function getMessageKey()
    {
        return 'An authentication exception occurred.';
    }
    /**
     * Message data to be used by the translation component.
     */
    public function getMessageData(): array
    {
        return [];
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Security\Core\Exception;

/**
 * UserNotFoundException is thrown if a User cannot be found for the given identifier.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 * @author Alexander <iam.asm89@gmail.com>
 */
class UserNotFoundException extends AuthenticationException
{
    private ?string $identifier = null;
    public function getMessageKey(): string
    {
        return 'Username could not be found.';
    }
    /**
     * Get the user identifier (e.g. username or email address).
     */
    public function getUserIdentifier(): ?string
    {
        return $this->identifier;
    }
    /**
     * Set the user identifier (e.g. username or email address).
     */
    public function setUserIdentifier(string $identifier): void
    {
        $this->identifier = $identifier;
    }
    public function getMessageData(): array
    {
        return ['{{ username }}' => $this->identifier, '{{ user_identifier }}' => $this->identifier];
    }
    public function __serialize(): array
    {
        return [$this->identifier, parent::__serialize()];
    }
    public function __unserialize(array $data): void
    {
        [$this->identifier, $parentData] = $data;
        $parentData = \is_array($parentData) ? $parentData : unserialize($parentData);
        parent::__unserialize($parentData);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Security\Core\Exception;

/**
 * AuthenticationCredentialsNotFoundException is thrown when an authentication is rejected
 * because no Token is available.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 * @author Alexander <iam.asm89@gmail.com>
 */
class AuthenticationCredentialsNotFoundException extends AuthenticationException
{
    public function getMessageKey(): string
    {
        return 'Authentication credentials could not be found.';
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Security\Core\Exception;

/**
 * CredentialsExpiredException is thrown when the user account credentials have expired.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 * @author Alexander <iam.asm89@gmail.com>
 */
class CredentialsExpiredException extends AccountStatusException
{
    public function getMessageKey(): string
    {
        return 'Credentials have expired.';
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Security\Core\Authentication\Token;

use _ContaoManager\Symfony\Component\Security\Core\User\InMemoryUser;
use _ContaoManager\Symfony\Component\Security\Core\User\UserInterface;
/**
 * Base class for Token instances.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
abstract class AbstractToken implements TokenInterface, \Serializable
{
    private ?UserInterface $user = null;
    private array $roleNames = [];
    private array $attributes = [];
    /**
     * @param string[] $roles An array of roles
     *
     * @throws \InvalidArgumentException
     */
    public function __construct(array $roles = [])
    {
        foreach ($roles as $role) {
            $this->roleNames[] = $role;
        }
    }
    public function getRoleNames(): array
    {
        return $this->roleNames;
    }
    public function getUserIdentifier(): string
    {
        return $this->user ? $this->user->getUserIdentifier() : '';
    }
    public function getUser(): ?UserInterface
    {
        return $this->user;
    }
    /**
     * @return void
     */
    public function setUser(UserInterface $user)
    {
        $this->user = $user;
    }
    /**
     * @return void
     */
    public function eraseCredentials()
    {
        if ($this->getUser() instanceof UserInterface) {
            $this->getUser()->eraseCredentials();
        }
    }
    /**
     * Returns all the necessary state of the object for serialization purposes.
     *
     * There is no need to serialize any entry, they should be returned as-is.
     * If you extend this method, keep in mind you MUST guarantee parent data is present in the state.
     * Here is an example of how to extend this method:
     * <code>
     *     public function __serialize(): array
     *     {
     *         return [$this->childAttribute, parent::__serialize()];
     *     }
     * </code>
     *
     * @see __unserialize()
     */
    public function __serialize(): array
    {
        return [$this->user, \true, null, $this->attributes, $this->roleNames];
    }
    /**
     * Restores the object state from an array given by __serialize().
     *
     * There is no need to unserialize any entry in $data, they are already ready-to-use.
     * If you extend this method, keep in mind you MUST pass the parent data to its respective class.
     * Here is an example of how to extend this method:
     * <code>
     *     public function __unserialize(array $data): void
     *     {
     *         [$this->childAttribute, $parentData] = $data;
     *         parent::__unserialize($parentData);
     *     }
     * </code>
     *
     * @see __serialize()
     */
    public function __unserialize(array $data): void
    {
        [$user, , , $this->attributes, $this->roleNames] = $data;
        $this->user = \is_string($user) ? new InMemoryUser($user, '', $this->roleNames, \false) : $user;
    }
    public function getAttributes(): array
    {
        return $this->attributes;
    }
    /**
     * @return void
     */
    public function setAttributes(array $attributes)
    {
        $this->attributes = $attributes;
    }
    public function hasAttribute(string $name): bool
    {
        return \array_key_exists($name, $this->attributes);
    }
    public function getAttribute(string $name): mixed
    {
        if (!\array_key_exists($name, $this->attributes)) {
            throw new \InvalidArgumentException(\sprintf('This token has no "%s" attribute.', $name));
        }
        return $this->attributes[$name];
    }
    /**
     * @return void
     */
    public function setAttribute(string $name, mixed $value)
    {
        $this->attributes[$name] = $value;
    }
    public function __toString(): string
    {
        $class = static::class;
        $class = substr($class, strrpos($class, '\\') + 1);
        $roles = [];
        foreach ($this->roleNames as $role) {
            $roles[] = $role;
        }
        return \sprintf('%s(user="%s", roles="%s")', $class, $this->getUserIdentifier(), implode(', ', $roles));
    }
    /**
     * @internal
     */
    final public function serialize(): string
    {
        throw new \BadMethodCallException('Cannot serialize ' . __CLASS__);
    }
    /**
     * @internal
     */
    final public function unserialize(string $serialized): void
    {
        $this->__unserialize(unserialize($serialized));
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Security\Core\Authentication\Token;

use _ContaoManager\Symfony\Component\Security\Core\User\UserInterface;
/**
 * @author Wouter de Jong <wouter@wouterj.nl>
 */
class NullToken implements TokenInterface
{
    public function __toString(): string
    {
        return '';
    }
    public function getRoleNames(): array
    {
        return [];
    }
    public function getUser(): ?UserInterface
    {
        return null;
    }
    /**
     * @return never
     */
    public function setUser(UserInterface $user)
    {
        throw new \BadMethodCallException('Cannot set user on a NullToken.');
    }
    public function getUserIdentifier(): string
    {
        return '';
    }
    /**
     * @return void
     */
    public function eraseCredentials()
    {
    }
    public function getAttributes(): array
    {
        return [];
    }
    /**
     * @return never
     */
    public function setAttributes(array $attributes)
    {
        throw new \BadMethodCallException('Cannot set attributes of NullToken.');
    }
    public function hasAttribute(string $name): bool
    {
        return \false;
    }
    public function getAttribute(string $name): mixed
    {
        return null;
    }
    /**
     * @return never
     */
    public function setAttribute(string $name, mixed $value)
    {
        throw new \BadMethodCallException('Cannot add attribute to NullToken.');
    }
    public function __serialize(): array
    {
        return [];
    }
    public function __unserialize(array $data): void
    {
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Security\Core\Authentication\Token\Storage;

use _ContaoManager\Psr\Container\ContainerInterface;
use _ContaoManager\Symfony\Component\HttpFoundation\RequestStack;
use _ContaoManager\Symfony\Component\HttpFoundation\Session\SessionInterface;
use _ContaoManager\Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use _ContaoManager\Symfony\Contracts\Service\ServiceSubscriberInterface;
/**
 * A token storage that increments the session usage index when the token is accessed.
 *
 * @author Nicolas Grekas <p@tchwork.com>
 */
final class UsageTrackingTokenStorage implements TokenStorageInterface, ServiceSubscriberInterface
{
    private TokenStorageInterface $storage;
    private ContainerInterface $container;
    private bool $enableUsageTracking = \false;
    public function __construct(TokenStorageInterface $storage, ContainerInterface $container)
    {
        $this->storage = $storage;
        $this->container = $container;
    }
    public function getToken(): ?TokenInterface
    {
        if ($this->shouldTrackUsage()) {
            // increments the internal session usage index
            $this->getSession()->getMetadataBag();
        }
        return $this->storage->getToken();
    }
    public function setToken(?TokenInterface $token = null): void
    {
        $this->storage->setToken($token);
        if ($token && $this->shouldTrackUsage()) {
            // increments the internal session usage index
            $this->getSession()->getMetadataBag();
        }
    }
    public function enableUsageTracking(): void
    {
        $this->enableUsageTracking = \true;
    }
    public function disableUsageTracking(): void
    {
        $this->enableUsageTracking = \false;
    }
    public static function getSubscribedServices(): array
    {
        return ['request_stack' => RequestStack::class];
    }
    private function getSession(): SessionInterface
    {
        return $this->container->get('request_stack')->getSession();
    }
    private function shouldTrackUsage(): bool
    {
        return $this->enableUsageTracking && $this->container->get('request_stack')->getMainRequest();
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Security\Core\Authentication\Token\Storage;

use _ContaoManager\Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use _ContaoManager\Symfony\Contracts\Service\ResetInterface;
/**
 * TokenStorage contains a TokenInterface.
 *
 * It gives access to the token representing the current user authentication.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
class TokenStorage implements TokenStorageInterface, ResetInterface
{
    private ?TokenInterface $token = null;
    private ?\Closure $initializer = null;
    public function getToken(): ?TokenInterface
    {
        if ($initializer = $this->initializer) {
            $this->initializer = null;
            $initializer();
        }
        return $this->token;
    }
    /**
     * @return void
     */
    public function setToken(?TokenInterface $token = null)
    {
        if (1 > \func_num_args()) {
            trigger_deprecation('symfony/security-core', '6.2', 'Calling "%s()" without any arguments is deprecated, pass null explicitly instead.', __METHOD__);
        }
        if ($token) {
            // ensure any initializer is called
            $this->getToken();
        }
        $this->initializer = null;
        $this->token = $token;
    }
    public function setInitializer(?callable $initializer): void
    {
        $this->initializer = null === $initializer ? null : $initializer(...);
    }
    /**
     * @return void
     */
    public function reset()
    {
        $this->setToken(null);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Security\Core\Authentication\Token\Storage;

use _ContaoManager\Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
/**
 * The TokenStorageInterface.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
interface TokenStorageInterface
{
    /**
     * Returns the current security token.
     */
    public function getToken(): ?TokenInterface;
    /**
     * Sets the authentication token.
     *
     * @param TokenInterface|null $token A TokenInterface token, or null if no further authentication information should be stored
     *
     * @return void
     */
    public function setToken(?TokenInterface $token);
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Security\Core\Authentication\Token;

use _ContaoManager\Symfony\Component\Security\Core\Exception\InvalidArgumentException;
use _ContaoManager\Symfony\Component\Security\Core\User\UserInterface;
/**
 * Authentication Token for "Remember-Me".
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
class RememberMeToken extends AbstractToken
{
    private string $secret;
    private string $firewallName;
    /**
     * @param string $secret A secret used to make sure the token is created by the app and not by a malicious client
     *
     * @throws \InvalidArgumentException
     */
    public function __construct(
        UserInterface $user,
        string $firewallName,
        #[\SensitiveParameter]
        string $secret
    )
    {
        parent::__construct($user->getRoles());
        if (!$secret) {
            throw new InvalidArgumentException('A non-empty secret is required.');
        }
        if (!$firewallName) {
            throw new InvalidArgumentException('$firewallName must not be empty.');
        }
        $this->firewallName = $firewallName;
        $this->secret = $secret;
        $this->setUser($user);
    }
    public function getFirewallName(): string
    {
        return $this->firewallName;
    }
    public function getSecret(): string
    {
        return $this->secret;
    }
    public function __serialize(): array
    {
        return [$this->secret, $this->firewallName, parent::__serialize()];
    }
    public function __unserialize(array $data): void
    {
        [$this->secret, $this->firewallName, $parentData] = $data;
        $parentData = \is_array($parentData) ? $parentData : unserialize($parentData);
        parent::__unserialize($parentData);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Security\Core\Authentication\Token;

use _ContaoManager\Symfony\Component\Security\Core\User\UserInterface;
/**
 * Token representing a user who temporarily impersonates another one.
 *
 * @author Christian Flothmann <christian.flothmann@sensiolabs.de>
 */
class SwitchUserToken extends UsernamePasswordToken
{
    private TokenInterface $originalToken;
    private ?string $originatedFromUri = null;
    /**
     * @param $user              The username (like a nickname, email address, etc.), or a UserInterface instance or an object implementing a __toString method
     * @param $originatedFromUri The URI where was the user at the switch
     *
     * @throws \InvalidArgumentException
     */
    public function __construct(UserInterface $user, string $firewallName, array $roles, TokenInterface $originalToken, ?string $originatedFromUri = null)
    {
        parent::__construct($user, $firewallName, $roles);
        $this->originalToken = $originalToken;
        $this->originatedFromUri = $originatedFromUri;
    }
    public function getOriginalToken(): TokenInterface
    {
        return $this->originalToken;
    }
    public function getOriginatedFromUri(): ?string
    {
        return $this->originatedFromUri;
    }
    public function __serialize(): array
    {
        return [$this->originalToken, $this->originatedFromUri, parent::__serialize()];
    }
    public function __unserialize(array $data): void
    {
        if (3 > \count($data)) {
            // Support for tokens serialized with version 5.1 or lower of symfony/security-core.
            [$this->originalToken, $parentData] = $data;
        } else {
            [$this->originalToken, $this->originatedFromUri, $parentData] = $data;
        }
        $parentData = \is_array($parentData) ? $parentData : unserialize($parentData);
        parent::__unserialize($parentData);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Security\Core\Authentication\Token;

use _ContaoManager\Symfony\Component\Security\Core\User\UserInterface;
/**
 * PreAuthenticatedToken implements a pre-authenticated token.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class PreAuthenticatedToken extends AbstractToken
{
    private string $firewallName;
    /**
     * @param string[] $roles
     */
    public function __construct(UserInterface $user, string $firewallName, array $roles = [])
    {
        parent::__construct($roles);
        if ('' === $firewallName) {
            throw new \InvalidArgumentException('$firewallName must not be empty.');
        }
        $this->setUser($user);
        $this->firewallName = $firewallName;
    }
    public function getFirewallName(): string
    {
        return $this->firewallName;
    }
    public function __serialize(): array
    {
        return [null, $this->firewallName, parent::__serialize()];
    }
    public function __unserialize(array $data): void
    {
        [, $this->firewallName, $parentData] = $data;
        $parentData = \is_array($parentData) ? $parentData : unserialize($parentData);
        parent::__unserialize($parentData);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Security\Core\Authentication\Token;

use _ContaoManager\Symfony\Component\Security\Core\User\UserInterface;
/**
 * TokenInterface is the interface for the user authentication information.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
interface TokenInterface extends \Stringable
{
    /**
     * Returns a string representation of the Token.
     *
     * This is only to be used for debugging purposes.
     */
    public function __toString(): string;
    /**
     * Returns the user identifier used during authentication (e.g. a user's email address or username).
     */
    public function getUserIdentifier(): string;
    /**
     * Returns the user roles.
     *
     * @return string[]
     */
    public function getRoleNames(): array;
    /**
     * Returns a user representation.
     *
     * @see AbstractToken::setUser()
     */
    public function getUser(): ?UserInterface;
    /**
     * Sets the authenticated user in the token.
     *
     * @return void
     *
     * @throws \InvalidArgumentException
     */
    public function setUser(UserInterface $user);
    /**
     * Removes sensitive information from the token.
     *
     * @return void
     */
    public function eraseCredentials();
    public function getAttributes(): array;
    /**
     * @param array $attributes The token attributes
     *
     * @return void
     */
    public function setAttributes(array $attributes);
    public function hasAttribute(string $name): bool;
    /**
     * @throws \InvalidArgumentException When attribute doesn't exist for this token
     */
    public function getAttribute(string $name): mixed;
    /**
     * @return void
     */
    public function setAttribute(string $name, mixed $value);
    /**
     * Returns all the necessary state of the object for serialization purposes.
     */
    public function __serialize(): array;
    /**
     * Restores the object state from an array given by __serialize().
     */
    public function __unserialize(array $data): void;
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Security\Core\Authentication\Token;

use _ContaoManager\Symfony\Component\Security\Core\User\UserInterface;
/**
 * UsernamePasswordToken implements a username and password token.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class UsernamePasswordToken extends AbstractToken
{
    private string $firewallName;
    public function __construct(UserInterface $user, string $firewallName, array $roles = [])
    {
        parent::__construct($roles);
        if ('' === $firewallName) {
            throw new \InvalidArgumentException('$firewallName must not be empty.');
        }
        $this->setUser($user);
        $this->firewallName = $firewallName;
    }
    public function getFirewallName(): string
    {
        return $this->firewallName;
    }
    public function __serialize(): array
    {
        return [null, $this->firewallName, parent::__serialize()];
    }
    public function __unserialize(array $data): void
    {
        [, $this->firewallName, $parentData] = $data;
        $parentData = \is_array($parentData) ? $parentData : unserialize($parentData);
        parent::__unserialize($parentData);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Security\Core\Authentication;

use _ContaoManager\Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
/**
 * Interface for resolving the authentication status of a given token.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
interface AuthenticationTrustResolverInterface
{
    /**
     * Resolves whether the passed token implementation is authenticated.
     */
    public function isAuthenticated(?TokenInterface $token = null): bool;
    /**
     * Resolves whether the passed token implementation is authenticated
     * using remember-me capabilities.
     */
    public function isRememberMe(?TokenInterface $token = null): bool;
    /**
     * Resolves whether the passed token implementation is fully authenticated.
     */
    public function isFullFledged(?TokenInterface $token = null): bool;
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Security\Core\Authentication;

use _ContaoManager\Symfony\Component\Security\Core\Authentication\Token\RememberMeToken;
use _ContaoManager\Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
/**
 * The default implementation of the authentication trust resolver.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
class AuthenticationTrustResolver implements AuthenticationTrustResolverInterface
{
    public function isAuthenticated(?TokenInterface $token = null): bool
    {
        return $token && $token->getUser();
    }
    public function isRememberMe(?TokenInterface $token = null): bool
    {
        return $token && $token instanceof RememberMeToken;
    }
    public function isFullFledged(?TokenInterface $token = null): bool
    {
        return $this->isAuthenticated($token) && !$this->isRememberMe($token);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Security\Core\Authentication\RememberMe;

/**
 * Interface to be implemented by persistent token classes (such as
 * Doctrine entities representing a remember-me token).
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
interface PersistentTokenInterface
{
    /**
     * Returns the class of the user.
     */
    public function getClass(): string;
    /**
     * Returns the series.
     */
    public function getSeries(): string;
    /**
     * Returns the token value.
     */
    public function getTokenValue(): string;
    /**
     * Returns the time the token was last used.
     *
     * Each call SHOULD return a new distinct DateTime instance.
     */
    public function getLastUsed(): \DateTime;
    /**
     * Returns the identifier used to authenticate (e.g. their email address or username).
     */
    public function getUserIdentifier(): string;
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Security\Core\Authentication\RememberMe;

use _ContaoManager\Symfony\Component\Security\Core\Exception\TokenNotFoundException;
/**
 * This class is used for testing purposes, and is not really suited for production.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 *
 * @final since Symfony 6.4
 */
class InMemoryTokenProvider implements TokenProviderInterface
{
    private array $tokens = [];
    public function loadTokenBySeries(string $series): PersistentTokenInterface
    {
        if (!isset($this->tokens[$series])) {
            throw new TokenNotFoundException('No token found.');
        }
        return $this->tokens[$series];
    }
    /**
     * @param \DateTimeInterface $lastUsed Accepting only DateTime is deprecated since Symfony 6.4
     *
     * @return void
     */
    public function updateToken(
        string $series,
        #[\SensitiveParameter]
        string $tokenValue,
        \DateTime $lastUsed
    )
    {
        if (!isset($this->tokens[$series])) {
            throw new TokenNotFoundException('No token found.');
        }
        $token = new PersistentToken($this->tokens[$series]->getClass(), $this->tokens[$series]->getUserIdentifier(), $series, $tokenValue, $lastUsed);
        $this->tokens[$series] = $token;
    }
    /**
     * @return void
     */
    public function deleteTokenBySeries(string $series)
    {
        unset($this->tokens[$series]);
    }
    /**
     * @return void
     */
    public function createNewToken(PersistentTokenInterface $token)
    {
        $this->tokens[$token->getSeries()] = $token;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Security\Core\Authentication\RememberMe;

use _ContaoManager\Psr\Cache\CacheItemPoolInterface;
/**
 * @author Jordi Boggiano <j.boggiano@seld.be>
 */
class CacheTokenVerifier implements TokenVerifierInterface
{
    private CacheItemPoolInterface $cache;
    private int $outdatedTokenTtl;
    private string $cacheKeyPrefix;
    /**
     * @param int $outdatedTokenTtl How long the outdated token should still be considered valid. Defaults
     *                              to 60, which matches how often the PersistentRememberMeHandler will at
     *                              most refresh tokens. Increasing to more than that is not recommended,
     *                              but you may use a lower value.
     */
    public function __construct(CacheItemPoolInterface $cache, int $outdatedTokenTtl = 60, string $cacheKeyPrefix = 'rememberme-stale-')
    {
        $this->cache = $cache;
        $this->outdatedTokenTtl = $outdatedTokenTtl;
        $this->cacheKeyPrefix = $cacheKeyPrefix;
    }
    public function verifyToken(
        PersistentTokenInterface $token,
        #[\SensitiveParameter]
        string $tokenValue
    ): bool
    {
        if (hash_equals($token->getTokenValue(), $tokenValue)) {
            return \true;
        }
        $cacheKey = $this->getCacheKey($token);
        $item = $this->cache->getItem($cacheKey);
        if (!$item->isHit()) {
            return \false;
        }
        $outdatedToken = $item->get();
        return hash_equals($outdatedToken, $tokenValue);
    }
    public function updateExistingToken(
        PersistentTokenInterface $token,
        #[\SensitiveParameter]
        string $tokenValue,
        \DateTimeInterface $lastUsed
    ): void
    {
        // When a token gets updated, persist the outdated token for $outdatedTokenTtl seconds so we can
        // still accept it as valid in verifyToken
        $item = $this->cache->getItem($this->getCacheKey($token));
        $item->set($token->getTokenValue());
        $item->expiresAfter($this->outdatedTokenTtl);
        $this->cache->save($item);
    }
    private function getCacheKey(PersistentTokenInterface $token): string
    {
        return $this->cacheKeyPrefix . rawurlencode($token->getSeries());
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Security\Core\Authentication\RememberMe;

/**
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 *
 * @internal
 */
final class PersistentToken implements PersistentTokenInterface
{
    private string $class;
    private string $userIdentifier;
    private string $series;
    private string $tokenValue;
    private \DateTimeImmutable $lastUsed;
    public function __construct(
        string $class,
        string $userIdentifier,
        string $series,
        #[\SensitiveParameter]
        string $tokenValue,
        \DateTimeInterface $lastUsed
    )
    {
        if (empty($class)) {
            throw new \InvalidArgumentException('$class must not be empty.');
        }
        if ('' === $userIdentifier) {
            throw new \InvalidArgumentException('$userIdentifier must not be empty.');
        }
        if (empty($series)) {
            throw new \InvalidArgumentException('$series must not be empty.');
        }
        if (empty($tokenValue)) {
            throw new \InvalidArgumentException('$tokenValue must not be empty.');
        }
        $this->class = $class;
        $this->userIdentifier = $userIdentifier;
        $this->series = $series;
        $this->tokenValue = $tokenValue;
        $this->lastUsed = \DateTimeImmutable::createFromInterface($lastUsed);
    }
    public function getClass(): string
    {
        return $this->class;
    }
    public function getUserIdentifier(): string
    {
        return $this->userIdentifier;
    }
    public function getSeries(): string
    {
        return $this->series;
    }
    public function getTokenValue(): string
    {
        return $this->tokenValue;
    }
    public function getLastUsed(): \DateTime
    {
        return \DateTime::createFromImmutable($this->lastUsed);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Security\Core\Authentication\RememberMe;

/**
 * @author Jordi Boggiano <j.boggiano@seld.be>
 */
interface TokenVerifierInterface
{
    /**
     * Verifies that the given $token is valid.
     *
     * This lets you override the token check logic to for example accept slightly outdated tokens.
     *
     * Do not forget to implement token comparisons using hash_equals for a secure implementation.
     */
    public function verifyToken(
        PersistentTokenInterface $token,
        #[\SensitiveParameter]
        string $tokenValue
    ): bool;
    /**
     * Updates an existing token with a new token value and lastUsed time.
     */
    public function updateExistingToken(
        PersistentTokenInterface $token,
        #[\SensitiveParameter]
        string $tokenValue,
        \DateTimeInterface $lastUsed
    ): void;
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Security\Core\Authentication\RememberMe;

use _ContaoManager\Symfony\Component\Security\Core\Exception\TokenNotFoundException;
/**
 * Interface for TokenProviders.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
interface TokenProviderInterface
{
    /**
     * Loads the active token for the given series.
     *
     * @return PersistentTokenInterface
     *
     * @throws TokenNotFoundException if the token is not found
     */
    public function loadTokenBySeries(string $series);
    /**
     * Deletes all tokens belonging to series.
     *
     * @return void
     */
    public function deleteTokenBySeries(string $series);
    /**
     * Updates the token according to this data.
     *
     * @param \DateTimeInterface $lastUsed Accepting only DateTime is deprecated since Symfony 6.4
     *
     * @return void
     *
     * @throws TokenNotFoundException if the token is not found
     */
    public function updateToken(
        string $series,
        #[\SensitiveParameter]
        string $tokenValue,
        \DateTime $lastUsed
    );
    /**
     * Creates a new token.
     *
     * @return void
     */
    public function createNewToken(PersistentTokenInterface $token);
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Security\Core\Event;

final class AuthenticationSuccessEvent extends AuthenticationEvent
{
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Security\Core\Event;

use _ContaoManager\Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use _ContaoManager\Symfony\Contracts\EventDispatcher\Event;
/**
 * This is a general purpose authentication event.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
class AuthenticationEvent extends Event
{
    private TokenInterface $authenticationToken;
    public function __construct(TokenInterface $token)
    {
        $this->authenticationToken = $token;
    }
    /**
     * @return TokenInterface
     */
    public function getAuthenticationToken()
    {
        return $this->authenticationToken;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Security\Core\Event;

use _ContaoManager\Symfony\Component\Security\Core\Authorization\Voter\VoterInterface;
use _ContaoManager\Symfony\Contracts\EventDispatcher\Event;
/**
 * This event is dispatched on voter vote.
 *
 * @author Laurent VOULLEMIER <laurent.voullemier@gmail.com>
 *
 * @internal
 */
final class VoteEvent extends Event
{
    private VoterInterface $voter;
    private mixed $subject;
    private array $attributes;
    private int $vote;
    public function __construct(VoterInterface $voter, mixed $subject, array $attributes, int $vote)
    {
        $this->voter = $voter;
        $this->subject = $subject;
        $this->attributes = $attributes;
        $this->vote = $vote;
    }
    public function getVoter(): VoterInterface
    {
        return $this->voter;
    }
    public function getSubject(): mixed
    {
        return $this->subject;
    }
    public function getAttributes(): array
    {
        return $this->attributes;
    }
    public function getVote(): int
    {
        return $this->vote;
    }
}
{
    "name": "symfony\/security-core",
    "type": "library",
    "description": "Symfony Security Component - Core Library",
    "keywords": [],
    "homepage": "https:\/\/symfony.com",
    "license": "MIT",
    "authors": [
        {
            "name": "Fabien Potencier",
            "email": "fabien@symfony.com"
        },
        {
            "name": "Symfony Community",
            "homepage": "https:\/\/symfony.com\/contributors"
        }
    ],
    "require": {
        "php": ">=8.1",
        "symfony\/deprecation-contracts": "^2.5|^3",
        "symfony\/event-dispatcher-contracts": "^2.5|^3",
        "symfony\/service-contracts": "^2.5|^3",
        "symfony\/password-hasher": "^5.4|^6.0|^7.0"
    },
    "require-dev": {
        "psr\/container": "^1.1|^2.0",
        "psr\/cache": "^1.0|^2.0|^3.0",
        "symfony\/cache": "^5.4|^6.0|^7.0",
        "symfony\/event-dispatcher": "^5.4|^6.0|^7.0",
        "symfony\/expression-language": "^5.4|^6.0|^7.0",
        "symfony\/http-foundation": "^5.4|^6.0|^7.0",
        "symfony\/ldap": "^5.4|^6.0|^7.0",
        "symfony\/string": "^5.4|^6.0|^7.0",
        "symfony\/translation": "^5.4.35|~6.3.12|^6.4.3|^7.0.3",
        "symfony\/validator": "^6.4|^7.0",
        "psr\/log": "^1|^2|^3"
    },
    "conflict": {
        "symfony\/event-dispatcher": "<5.4",
        "symfony\/http-foundation": "<5.4",
        "symfony\/security-guard": "<5.4",
        "symfony\/ldap": "<5.4",
        "symfony\/translation": "<5.4.35|>=6.0,<6.3.12|>=6.4,<6.4.3|>=7.0,<7.0.3",
        "symfony\/validator": "<5.4"
    },
    "autoload": {
        "psr-4": {
            "_ContaoManager\\Symfony\\Component\\Security\\Core\\": ""
        },
        "exclude-from-classmap": [
            "\/Tests\/"
        ]
    },
    "minimum-stability": "dev"
}<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Security\Core;

use _ContaoManager\Symfony\Component\Security\Core\Event\AuthenticationSuccessEvent;
final class AuthenticationEvents
{
    /**
     * The AUTHENTICATION_SUCCESS event occurs after a user is authenticated
     * by one provider.
     *
     * @Event("Symfony\Component\Security\Core\Event\AuthenticationSuccessEvent")
     */
    public const AUTHENTICATION_SUCCESS = 'security.authentication.success';
    /**
     * Event aliases.
     *
     * These aliases can be consumed by RegisterListenersPass.
     */
    public const ALIASES = [AuthenticationSuccessEvent::class => self::AUTHENTICATION_SUCCESS];
}
Copyright (c) 2020-present Fabien Potencier

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is furnished
to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
CHANGELOG
=========

The changelog is maintained for all Symfony contracts at the following URL:
https://github.com/symfony/contracts/blob/main/CHANGELOG.md
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

if (!function_exists('trigger_deprecation')) {
    /**
     * Triggers a silenced deprecation notice.
     *
     * @param string $package The name of the Composer package that is triggering the deprecation
     * @param string $version The version of the package that introduced the deprecation
     * @param string $message The message of the deprecation
     * @param mixed  ...$args Values to insert in the message using printf() formatting
     *
     * @author Nicolas Grekas <p@tchwork.com>
     */
    function trigger_deprecation(string $package, string $version, string $message, mixed ...$args): void
    {
        @trigger_error(($package || $version ? "Since $package $version: " : '').($args ? vsprintf($message, $args) : $message), \E_USER_DEPRECATED);
    }
}
Symfony Deprecation Contracts
=============================

A generic function and convention to trigger deprecation notices.

This package provides a single global function named `trigger_deprecation()` that triggers silenced deprecation notices.

By using a custom PHP error handler such as the one provided by the Symfony ErrorHandler component,
the triggered deprecations can be caught and logged for later discovery, both on dev and prod environments.

The function requires at least 3 arguments:
 - the name of the Composer package that is triggering the deprecation
 - the version of the package that introduced the deprecation
 - the message of the deprecation
 - more arguments can be provided: they will be inserted in the message using `printf()` formatting

Example:
```php
trigger_deprecation('symfony/blockchain', '8.9', 'Using "%s" is deprecated, use "%s" instead.', 'bitcoin', 'fabcoin');
```

This will generate the following message:
`Since symfony/blockchain 8.9: Using "bitcoin" is deprecated, use "fabcoin" instead.`

While not recommended, the deprecation notices can be completely ignored by declaring an empty
`function trigger_deprecation() {}` in your application.
{
    "name": "symfony\/deprecation-contracts",
    "type": "library",
    "description": "A generic function and convention to trigger deprecation notices",
    "homepage": "https:\/\/symfony.com",
    "license": "MIT",
    "authors": [
        {
            "name": "Nicolas Grekas",
            "email": "p@tchwork.com"
        },
        {
            "name": "Symfony Community",
            "homepage": "https:\/\/symfony.com\/contributors"
        }
    ],
    "require": {
        "php": ">=8.1"
    },
    "autoload": {
        "files": [
            "function.php"
        ]
    },
    "minimum-stability": "dev",
    "extra": {
        "branch-alias": {
            "dev-main": "3.6-dev"
        },
        "thanks": {
            "name": "symfony\/contracts",
            "url": "https:\/\/github.com\/symfony\/contracts"
        }
    }
}<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Routing;

/**
 * CompiledRoutes are returned by the RouteCompiler class.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class CompiledRoute implements \Serializable
{
    private array $variables;
    private array $tokens;
    private string $staticPrefix;
    private string $regex;
    private array $pathVariables;
    private array $hostVariables;
    private ?string $hostRegex;
    private array $hostTokens;
    /**
     * @param string      $staticPrefix  The static prefix of the compiled route
     * @param string      $regex         The regular expression to use to match this route
     * @param array       $tokens        An array of tokens to use to generate URL for this route
     * @param array       $pathVariables An array of path variables
     * @param string|null $hostRegex     Host regex
     * @param array       $hostTokens    Host tokens
     * @param array       $hostVariables An array of host variables
     * @param array       $variables     An array of variables (variables defined in the path and in the host patterns)
     */
    public function __construct(string $staticPrefix, string $regex, array $tokens, array $pathVariables, ?string $hostRegex = null, array $hostTokens = [], array $hostVariables = [], array $variables = [])
    {
        $this->staticPrefix = $staticPrefix;
        $this->regex = $regex;
        $this->tokens = $tokens;
        $this->pathVariables = $pathVariables;
        $this->hostRegex = $hostRegex;
        $this->hostTokens = $hostTokens;
        $this->hostVariables = $hostVariables;
        $this->variables = $variables;
    }
    public function __serialize(): array
    {
        return ['vars' => $this->variables, 'path_prefix' => $this->staticPrefix, 'path_regex' => $this->regex, 'path_tokens' => $this->tokens, 'path_vars' => $this->pathVariables, 'host_regex' => $this->hostRegex, 'host_tokens' => $this->hostTokens, 'host_vars' => $this->hostVariables];
    }
    /**
     * @internal
     */
    final public function serialize(): string
    {
        throw new \BadMethodCallException('Cannot serialize ' . __CLASS__);
    }
    public function __unserialize(array $data): void
    {
        $this->variables = $data['vars'];
        $this->staticPrefix = $data['path_prefix'];
        $this->regex = $data['path_regex'];
        $this->tokens = $data['path_tokens'];
        $this->pathVariables = $data['path_vars'];
        $this->hostRegex = $data['host_regex'];
        $this->hostTokens = $data['host_tokens'];
        $this->hostVariables = $data['host_vars'];
    }
    /**
     * @internal
     */
    final public function unserialize(string $serialized): void
    {
        $this->__unserialize(unserialize($serialized, ['allowed_classes' => \false]));
    }
    /**
     * Returns the static prefix.
     */
    public function getStaticPrefix(): string
    {
        return $this->staticPrefix;
    }
    /**
     * Returns the regex.
     */
    public function getRegex(): string
    {
        return $this->regex;
    }
    /**
     * Returns the host regex.
     */
    public function getHostRegex(): ?string
    {
        return $this->hostRegex;
    }
    /**
     * Returns the tokens.
     */
    public function getTokens(): array
    {
        return $this->tokens;
    }
    /**
     * Returns the host tokens.
     */
    public function getHostTokens(): array
    {
        return $this->hostTokens;
    }
    /**
     * Returns the variables.
     */
    public function getVariables(): array
    {
        return $this->variables;
    }
    /**
     * Returns the path variables.
     */
    public function getPathVariables(): array
    {
        return $this->pathVariables;
    }
    /**
     * Returns the host variables.
     */
    public function getHostVariables(): array
    {
        return $this->hostVariables;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Routing\Attribute;

/**
 * Annotation class for @Route().
 *
 * @Annotation
 * @NamedArgumentConstructor
 * @Target({"CLASS", "METHOD"})
 *
 * @author Fabien Potencier <fabien@symfony.com>
 * @author Alexander M. Turek <me@derrabus.de>
 */
#[\Attribute(\Attribute::IS_REPEATABLE | \Attribute::TARGET_CLASS | \Attribute::TARGET_METHOD)]
class Route
{
    private ?string $path = null;
    private array $localizedPaths = [];
    private array $methods;
    private array $schemes;
    /**
     * @param array<string|\Stringable> $requirements
     * @param string[]|string           $methods
     * @param string[]|string           $schemes
     */
    public function __construct(string|array|null $path = null, private ?string $name = null, private array $requirements = [], private array $options = [], private array $defaults = [], private ?string $host = null, array|string $methods = [], array|string $schemes = [], private ?string $condition = null, private ?int $priority = null, ?string $locale = null, ?string $format = null, ?bool $utf8 = null, ?bool $stateless = null, private ?string $env = null)
    {
        if (\is_array($path)) {
            $this->localizedPaths = $path;
        } else {
            $this->path = $path;
        }
        $this->setMethods($methods);
        $this->setSchemes($schemes);
        if (null !== $locale) {
            $this->defaults['_locale'] = $locale;
        }
        if (null !== $format) {
            $this->defaults['_format'] = $format;
        }
        if (null !== $utf8) {
            $this->options['utf8'] = $utf8;
        }
        if (null !== $stateless) {
            $this->defaults['_stateless'] = $stateless;
        }
    }
    /**
     * @return void
     */
    public function setPath(string $path)
    {
        $this->path = $path;
    }
    /**
     * @return string|null
     */
    public function getPath()
    {
        return $this->path;
    }
    /**
     * @return void
     */
    public function setLocalizedPaths(array $localizedPaths)
    {
        $this->localizedPaths = $localizedPaths;
    }
    public function getLocalizedPaths(): array
    {
        return $this->localizedPaths;
    }
    /**
     * @return void
     */
    public function setHost(string $pattern)
    {
        $this->host = $pattern;
    }
    /**
     * @return string|null
     */
    public function getHost()
    {
        return $this->host;
    }
    /**
     * @return void
     */
    public function setName(string $name)
    {
        $this->name = $name;
    }
    /**
     * @return string|null
     */
    public function getName()
    {
        return $this->name;
    }
    /**
     * @return void
     */
    public function setRequirements(array $requirements)
    {
        $this->requirements = $requirements;
    }
    /**
     * @return array
     */
    public function getRequirements()
    {
        return $this->requirements;
    }
    /**
     * @return void
     */
    public function setOptions(array $options)
    {
        $this->options = $options;
    }
    /**
     * @return array
     */
    public function getOptions()
    {
        return $this->options;
    }
    /**
     * @return void
     */
    public function setDefaults(array $defaults)
    {
        $this->defaults = $defaults;
    }
    /**
     * @return array
     */
    public function getDefaults()
    {
        return $this->defaults;
    }
    /**
     * @return void
     */
    public function setSchemes(array|string $schemes)
    {
        $this->schemes = (array) $schemes;
    }
    /**
     * @return array
     */
    public function getSchemes()
    {
        return $this->schemes;
    }
    /**
     * @return void
     */
    public function setMethods(array|string $methods)
    {
        $this->methods = (array) $methods;
    }
    /**
     * @return array
     */
    public function getMethods()
    {
        return $this->methods;
    }
    /**
     * @return void
     */
    public function setCondition(?string $condition)
    {
        $this->condition = $condition;
    }
    /**
     * @return string|null
     */
    public function getCondition()
    {
        return $this->condition;
    }
    public function setPriority(int $priority): void
    {
        $this->priority = $priority;
    }
    public function getPriority(): ?int
    {
        return $this->priority;
    }
    public function setEnv(?string $env): void
    {
        $this->env = $env;
    }
    public function getEnv(): ?string
    {
        return $this->env;
    }
}
if (!class_exists(\_ContaoManager\Symfony\Component\Routing\Annotation\Route::class, \false)) {
    class_alias(Route::class, \_ContaoManager\Symfony\Component\Routing\Annotation\Route::class);
}
Copyright (c) 2004-present Fabien Potencier

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is furnished
to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Routing;

/**
 * RouteCompiler compiles Route instances to CompiledRoute instances.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 * @author Tobias Schultze <http://tobion.de>
 */
class RouteCompiler implements RouteCompilerInterface
{
    /**
     * This string defines the characters that are automatically considered separators in front of
     * optional placeholders (with default and no static text following). Such a single separator
     * can be left out together with the optional placeholder from matching and generating URLs.
     */
    public const SEPARATORS = '/,;.:-_~+*=@|';
    /**
     * The maximum supported length of a PCRE subpattern name
     * http://pcre.org/current/doc/html/pcre2pattern.html#SEC16.
     *
     * @internal
     */
    public const VARIABLE_MAXIMUM_LENGTH = 32;
    /**
     * @throws \InvalidArgumentException if a path variable is named _fragment
     * @throws \LogicException           if a variable is referenced more than once
     * @throws \DomainException          if a variable name starts with a digit or if it is too long to be successfully used as
     *                                   a PCRE subpattern
     */
    public static function compile(Route $route): CompiledRoute
    {
        $hostVariables = [];
        $variables = [];
        $hostRegex = null;
        $hostTokens = [];
        if ('' !== $host = $route->getHost()) {
            $result = self::compilePattern($route, $host, \true);
            $hostVariables = $result['variables'];
            $variables = $hostVariables;
            $hostTokens = $result['tokens'];
            $hostRegex = $result['regex'];
        }
        $locale = $route->getDefault('_locale');
        if (null !== $locale && null !== $route->getDefault('_canonical_route') && preg_quote($locale) === $route->getRequirement('_locale')) {
            $requirements = $route->getRequirements();
            unset($requirements['_locale']);
            $route->setRequirements($requirements);
            $route->setPath(str_replace('{_locale}', $locale, $route->getPath()));
        }
        $path = $route->getPath();
        $result = self::compilePattern($route, $path, \false);
        $staticPrefix = $result['staticPrefix'];
        $pathVariables = $result['variables'];
        foreach ($pathVariables as $pathParam) {
            if ('_fragment' === $pathParam) {
                throw new \InvalidArgumentException(\sprintf('Route pattern "%s" cannot contain "_fragment" as a path parameter.', $route->getPath()));
            }
        }
        $variables = array_merge($variables, $pathVariables);
        $tokens = $result['tokens'];
        $regex = $result['regex'];
        return new CompiledRoute($staticPrefix, $regex, $tokens, $pathVariables, $hostRegex, $hostTokens, $hostVariables, array_unique($variables));
    }
    private static function compilePattern(Route $route, string $pattern, bool $isHost): array
    {
        $tokens = [];
        $variables = [];
        $matches = [];
        $pos = 0;
        $defaultSeparator = $isHost ? '.' : '/';
        $useUtf8 = preg_match('//u', $pattern);
        $needsUtf8 = $route->getOption('utf8');
        if (!$needsUtf8 && $useUtf8 && preg_match('/[\x80-\xFF]/', $pattern)) {
            throw new \LogicException(\sprintf('Cannot use UTF-8 route patterns without setting the "utf8" option for route "%s".', $route->getPath()));
        }
        if (!$useUtf8 && $needsUtf8) {
            throw new \LogicException(\sprintf('Cannot mix UTF-8 requirements with non-UTF-8 pattern "%s".', $pattern));
        }
        // Match all variables enclosed in "{}" and iterate over them. But we only want to match the innermost variable
        // in case of nested "{}", e.g. {foo{bar}}. This in ensured because \w does not match "{" or "}" itself.
        preg_match_all('#\{(!)?([\w\x80-\xFF]+)\}#', $pattern, $matches, \PREG_OFFSET_CAPTURE | \PREG_SET_ORDER);
        foreach ($matches as $match) {
            $important = $match[1][1] >= 0;
            $varName = $match[2][0];
            // get all static text preceding the current variable
            $precedingText = substr($pattern, $pos, $match[0][1] - $pos);
            $pos = $match[0][1] + \strlen($match[0][0]);
            if (!\strlen($precedingText)) {
                $precedingChar = '';
            } elseif ($useUtf8) {
                preg_match('/.$/u', $precedingText, $precedingChar);
                $precedingChar = $precedingChar[0];
            } else {
                $precedingChar = substr($precedingText, -1);
            }
            $isSeparator = '' !== $precedingChar && str_contains(static::SEPARATORS, $precedingChar);
            // A PCRE subpattern name must start with a non-digit. Also a PHP variable cannot start with a digit so the
            // variable would not be usable as a Controller action argument.
            if (preg_match('/^\d/', $varName)) {
                throw new \DomainException(\sprintf('Variable name "%s" cannot start with a digit in route pattern "%s". Please use a different name.', $varName, $pattern));
            }
            if (\in_array($varName, $variables)) {
                throw new \LogicException(\sprintf('Route pattern "%s" cannot reference variable name "%s" more than once.', $pattern, $varName));
            }
            if (\strlen($varName) > self::VARIABLE_MAXIMUM_LENGTH) {
                throw new \DomainException(\sprintf('Variable name "%s" cannot be longer than %d characters in route pattern "%s". Please use a shorter name.', $varName, self::VARIABLE_MAXIMUM_LENGTH, $pattern));
            }
            if ($isSeparator && $precedingText !== $precedingChar) {
                $tokens[] = ['text', substr($precedingText, 0, -\strlen($precedingChar))];
            } elseif (!$isSeparator && '' !== $precedingText) {
                $tokens[] = ['text', $precedingText];
            }
            $regexp = $route->getRequirement($varName);
            if (null === $regexp) {
                $followingPattern = (string) substr($pattern, $pos);
                // Find the next static character after the variable that functions as a separator. By default, this separator and '/'
                // are disallowed for the variable. This default requirement makes sure that optional variables can be matched at all
                // and that the generating-matching-combination of URLs unambiguous, i.e. the params used for generating the URL are
                // the same that will be matched. Example: new Route('/{page}.{_format}', ['_format' => 'html'])
                // If {page} would also match the separating dot, {_format} would never match as {page} will eagerly consume everything.
                // Also even if {_format} was not optional the requirement prevents that {page} matches something that was originally
                // part of {_format} when generating the URL, e.g. _format = 'mobile.html'.
                $nextSeparator = self::findNextSeparator($followingPattern, $useUtf8);
                $regexp = \sprintf('[^%s%s]+', preg_quote($defaultSeparator), $defaultSeparator !== $nextSeparator && '' !== $nextSeparator ? preg_quote($nextSeparator) : '');
                if ('' !== $nextSeparator && !preg_match('#^\{[\w\x80-\xFF]+\}#', $followingPattern) || '' === $followingPattern) {
                    // When we have a separator, which is disallowed for the variable, we can optimize the regex with a possessive
                    // quantifier. This prevents useless backtracking of PCRE and improves performance by 20% for matching those patterns.
                    // Given the above example, there is no point in backtracking into {page} (that forbids the dot) when a dot must follow
                    // after it. This optimization cannot be applied when the next char is no real separator or when the next variable is
                    // directly adjacent, e.g. '/{x}{y}'.
                    $regexp .= '+';
                }
            } else {
                if (!preg_match('//u', $regexp)) {
                    $useUtf8 = \false;
                } elseif (!$needsUtf8 && preg_match('/[\x80-\xFF]|(?<!\\\\)\\\\(?:\\\\\\\\)*+(?-i:X|[pP][\{CLMNPSZ]|x\{[A-Fa-f0-9]{3})/', $regexp)) {
                    throw new \LogicException(\sprintf('Cannot use UTF-8 route requirements without setting the "utf8" option for variable "%s" in pattern "%s".', $varName, $pattern));
                }
                if (!$useUtf8 && $needsUtf8) {
                    throw new \LogicException(\sprintf('Cannot mix UTF-8 requirement with non-UTF-8 charset for variable "%s" in pattern "%s".', $varName, $pattern));
                }
                $regexp = self::transformCapturingGroupsToNonCapturings($regexp);
            }
            if ($important) {
                $token = ['variable', $isSeparator ? $precedingChar : '', $regexp, $varName, \false, \true];
            } else {
                $token = ['variable', $isSeparator ? $precedingChar : '', $regexp, $varName];
            }
            $tokens[] = $token;
            $variables[] = $varName;
        }
        if ($pos < \strlen($pattern)) {
            $tokens[] = ['text', substr($pattern, $pos)];
        }
        // find the first optional token
        $firstOptional = \PHP_INT_MAX;
        if (!$isHost) {
            for ($i = \count($tokens) - 1; $i >= 0; --$i) {
                $token = $tokens[$i];
                // variable is optional when it is not important and has a default value
                if ('variable' === $token[0] && !($token[5] ?? \false) && $route->hasDefault($token[3])) {
                    $firstOptional = $i;
                } else {
                    break;
                }
            }
        }
        // compute the matching regexp
        $regexp = '';
        for ($i = 0, $nbToken = \count($tokens); $i < $nbToken; ++$i) {
            $regexp .= self::computeRegexp($tokens, $i, $firstOptional);
        }
        $regexp = '{^' . $regexp . '$}sD' . ($isHost ? 'i' : '');
        // enable Utf8 matching if really required
        if ($needsUtf8) {
            $regexp .= 'u';
            for ($i = 0, $nbToken = \count($tokens); $i < $nbToken; ++$i) {
                if ('variable' === $tokens[$i][0]) {
                    $tokens[$i][4] = \true;
                }
            }
        }
        return ['staticPrefix' => self::determineStaticPrefix($route, $tokens), 'regex' => $regexp, 'tokens' => array_reverse($tokens), 'variables' => $variables];
    }
    /**
     * Determines the longest static prefix possible for a route.
     */
    private static function determineStaticPrefix(Route $route, array $tokens): string
    {
        if ('text' !== $tokens[0][0]) {
            return $route->hasDefault($tokens[0][3]) || '/' === $tokens[0][1] ? '' : $tokens[0][1];
        }
        $prefix = $tokens[0][1];
        if (isset($tokens[1][1]) && '/' !== $tokens[1][1] && \false === $route->hasDefault($tokens[1][3])) {
            $prefix .= $tokens[1][1];
        }
        return $prefix;
    }
    /**
     * Returns the next static character in the Route pattern that will serve as a separator (or the empty string when none available).
     */
    private static function findNextSeparator(string $pattern, bool $useUtf8): string
    {
        if ('' == $pattern) {
            // return empty string if pattern is empty or false (false which can be returned by substr)
            return '';
        }
        // first remove all placeholders from the pattern so we can find the next real static character
        if ('' === $pattern = preg_replace('#\{[\w\x80-\xFF]+\}#', '', $pattern)) {
            return '';
        }
        if ($useUtf8) {
            preg_match('/^./u', $pattern, $pattern);
        }
        return str_contains(static::SEPARATORS, $pattern[0]) ? $pattern[0] : '';
    }
    /**
     * Computes the regexp used to match a specific token. It can be static text or a subpattern.
     *
     * @param array $tokens        The route tokens
     * @param int   $index         The index of the current token
     * @param int   $firstOptional The index of the first optional token
     */
    private static function computeRegexp(array $tokens, int $index, int $firstOptional): string
    {
        $token = $tokens[$index];
        if ('text' === $token[0]) {
            // Text tokens
            return preg_quote($token[1]);
        } else if (0 === $index && 0 === $firstOptional) {
            // When the only token is an optional variable token, the separator is required
            return \sprintf('%s(?P<%s>%s)?', preg_quote($token[1]), $token[3], $token[2]);
        } else {
            $regexp = \sprintf('%s(?P<%s>%s)', preg_quote($token[1]), $token[3], $token[2]);
            if ($index >= $firstOptional) {
                // Enclose each optional token in a subpattern to make it optional.
                // "?:" means it is non-capturing, i.e. the portion of the subject string that
                // matched the optional subpattern is not passed back.
                $regexp = "(?:{$regexp}";
                $nbTokens = \count($tokens);
                if ($nbTokens - 1 == $index) {
                    // Close the optional subpatterns
                    $regexp .= str_repeat(')?', $nbTokens - $firstOptional - (0 === $firstOptional ? 1 : 0));
                }
            }
            return $regexp;
        }
    }
    private static function transformCapturingGroupsToNonCapturings(string $regexp): string
    {
        for ($i = 0; $i < \strlen($regexp); ++$i) {
            if ('\\' === $regexp[$i]) {
                ++$i;
                continue;
            }
            if ('(' !== $regexp[$i] || !isset($regexp[$i + 2])) {
                continue;
            }
            if ('*' === $regexp[++$i] || '?' === $regexp[$i]) {
                ++$i;
                continue;
            }
            $regexp = substr_replace($regexp, '?:', $i, 0);
            ++$i;
        }
        return $regexp;
    }
}
CHANGELOG
=========

6.4
---

 * Add FQCN and FQCN::method aliases for routes loaded from attributes/annotations when applicable
 * Add native return type to `AnnotationClassLoader::setResolver()`
 * Deprecate Doctrine annotations support in favor of native attributes
 * Change the constructor signature of `AnnotationClassLoader` to `__construct(?string $env = null)`, passing an annotation reader as first argument is deprecated
 * Deprecate `AnnotationClassLoader`, use `AttributeClassLoader` instead
 * Deprecate `AnnotationDirectoryLoader`, use `AttributeDirectoryLoader` instead
 * Deprecate `AnnotationFileLoader`, use `AttributeFileLoader` instead
 * Add `AddExpressionLanguageProvidersPass` (moved from `FrameworkBundle`)
 * Add aliases for all classes in the `Annotation` namespace to `Attribute`

6.2
---

 * Add `Requirement::POSITIVE_INT` for common ids and pagination

6.1
---

 * Add `getMissingParameters` and `getRouteName` methods on `MissingMandatoryParametersException`
 * Allow using UTF-8 parameter names
 * Support the `attribute` type (alias of `annotation`) in annotation loaders
 * Already encoded slashes are not decoded nor double-encoded anymore when generating URLs (query parameters)
 * Add `EnumRequirement` to help generate route requirements from a `\BackedEnum`
 * Add `Requirement`, a collection of universal regular-expression constants to use as route parameter requirements
 * Add `params` variable to condition expression
 * Deprecate not passing route parameters as the fourth argument to `UrlMatcher::handleRouteRequirements()`

5.3
---

 * Already encoded slashes are not decoded nor double-encoded anymore when generating URLs
 * Add support for per-env configuration in XML and Yaml loaders
 * Deprecate creating instances of the `Route` annotation class by passing an array of parameters
 * Add `RoutingConfigurator::env()` to get the current environment

5.2.0
-----

 * Added support for inline definition of requirements and defaults for host
 * Added support for `\A` and `\z` as regex start and end for route requirement
 * Added support for `#[Route]` attributes

5.1.0
-----

 * added the protected method `PhpFileLoader::callConfigurator()` as extension point to ease custom routing configuration
 * deprecated `RouteCollectionBuilder` in favor of `RoutingConfigurator`.
 * added "priority" option to annotated routes
 * added argument `$priority` to `RouteCollection::add()`
 * deprecated the `RouteCompiler::REGEX_DELIMITER` constant
 * added `ExpressionLanguageProvider` to expose extra functions to route conditions
 * added support for a `stateless` keyword for configuring route stateless in PHP, YAML and XML configurations.
 * added the "hosts" option to be able to configure the host per locale.
 * added `RequestContext::fromUri()` to ease building the default context

5.0.0
-----

 * removed `PhpGeneratorDumper` and `PhpMatcherDumper`
 * removed `generator_base_class`, `generator_cache_class`, `matcher_base_class` and `matcher_cache_class` router options
 * `Serializable` implementing methods for `Route` and `CompiledRoute` are final
 * removed referencing service route loaders with a single colon
 * Removed `ServiceRouterLoader` and `ObjectRouteLoader`.

4.4.0
-----

 * Deprecated `ServiceRouterLoader` in favor of `ContainerLoader`.
 * Deprecated `ObjectRouteLoader` in favor of `ObjectLoader`.
 * Added a way to exclude patterns of resources from being imported by the `import()` method

4.3.0
-----

 * added `CompiledUrlMatcher` and `CompiledUrlMatcherDumper`
 * added `CompiledUrlGenerator` and `CompiledUrlGeneratorDumper`
 * deprecated `PhpGeneratorDumper` and `PhpMatcherDumper`
 * deprecated `generator_base_class`, `generator_cache_class`, `matcher_base_class` and `matcher_cache_class` router options
 * `Serializable` implementing methods for `Route` and `CompiledRoute` are marked as `@internal` and `@final`.
   Instead of overwriting them, use `__serialize` and `__unserialize` as extension points which are forward compatible
   with the new serialization methods in PHP 7.4.
 * exposed `utf8` Route option, defaults "locale" and "format" in configuration loaders and configurators
 * added support for invokable service route loaders

4.2.0
-----

 * added fallback to cultureless locale for internationalized routes

4.0.0
-----

 * dropped support for using UTF-8 route patterns without using the `utf8` option
 * dropped support for using UTF-8 route requirements without using the `utf8` option

3.4.0
-----

 * Added `NoConfigurationException`.
 * Added the possibility to define a prefix for all routes of a controller via @Route(name="prefix_")
 * Added support for prioritized routing loaders.
 * Add matched and default parameters to redirect responses
 * Added support for a `controller` keyword for configuring route controllers in YAML and XML configurations.

3.3.0
-----

 * [DEPRECATION] Class parameters have been deprecated and will be removed in 4.0.
   * router.options.generator_class
   * router.options.generator_base_class
   * router.options.generator_dumper_class
   * router.options.matcher_class
   * router.options.matcher_base_class
   * router.options.matcher_dumper_class
   * router.options.matcher.cache_class
   * router.options.generator.cache_class

3.2.0
-----

 * Added support for `bool`, `int`, `float`, `string`, `list` and `map` defaults in XML configurations.
 * Added support for UTF-8 requirements

2.8.0
-----

 * allowed specifying a directory to recursively load all routing configuration files it contains
 * Added ObjectRouteLoader and ServiceRouteLoader that allow routes to be loaded
   by calling a method on an object/service.
 * [DEPRECATION] Deprecated the hardcoded value for the `$referenceType` argument of the `UrlGeneratorInterface::generate` method.
   Use the constants defined in the `UrlGeneratorInterface` instead.

   Before:

   ```php
   $router->generate('blog_show', ['slug' => 'my-blog-post'], true);
   ```

   After:

   ```php
   use Symfony\Component\Routing\Generator\UrlGeneratorInterface;

   $router->generate('blog_show', ['slug' => 'my-blog-post'], UrlGeneratorInterface::ABSOLUTE_URL);
   ```

2.5.0
-----

 * [DEPRECATION] The `ApacheMatcherDumper` and `ApacheUrlMatcher` were deprecated and
   will be removed in Symfony 3.0, since the performance gains were minimal and
   it's hard to replicate the behavior of PHP implementation.

2.3.0
-----

 * added RequestContext::getQueryString()

2.2.0
-----

 * [DEPRECATION] Several route settings have been renamed (the old ones will be removed in 3.0):

    * The `pattern` setting for a route has been deprecated in favor of `path`
    * The `_scheme` and `_method` requirements have been moved to the `schemes` and `methods` settings

   Before:

   ```yaml
   article_edit:
       pattern: /article/{id}
       requirements: { '_method': 'POST|PUT', '_scheme': 'https', 'id': '\d+' }
   ```

   ```xml
   <route id="article_edit" pattern="/article/{id}">
       <requirement key="_method">POST|PUT</requirement>
       <requirement key="_scheme">https</requirement>
       <requirement key="id">\d+</requirement>
   </route>
   ```

   ```php
   $route = new Route();
   $route->setPattern('/article/{id}');
   $route->setRequirement('_method', 'POST|PUT');
   $route->setRequirement('_scheme', 'https');
   ```

   After:

   ```yaml
   article_edit:
       path: /article/{id}
       methods: [POST, PUT]
       schemes: https
       requirements: { 'id': '\d+' }
   ```

   ```xml
   <route id="article_edit" pattern="/article/{id}" methods="POST PUT" schemes="https">
       <requirement key="id">\d+</requirement>
   </route>
   ```

   ```php
   $route = new Route();
   $route->setPath('/article/{id}');
   $route->setMethods(['POST', 'PUT']);
   $route->setSchemes('https');
   ```

 * [BC BREAK] RouteCollection does not behave like a tree structure anymore but as
   a flat array of Routes. So when using PHP to build the RouteCollection, you must
   make sure to add routes to the sub-collection before adding it to the parent
   collection (this is not relevant when using YAML or XML for Route definitions).

   Before:

   ```php
   $rootCollection = new RouteCollection();
   $subCollection = new RouteCollection();
   $rootCollection->addCollection($subCollection);
   $subCollection->add('foo', new Route('/foo'));
   ```

   After:

   ```php
   $rootCollection = new RouteCollection();
   $subCollection = new RouteCollection();
   $subCollection->add('foo', new Route('/foo'));
   $rootCollection->addCollection($subCollection);
   ```

   Also one must call `addCollection` from the bottom to the top hierarchy.
   So the correct sequence is the following (and not the reverse):

   ```php
   $childCollection->addCollection($grandchildCollection);
   $rootCollection->addCollection($childCollection);
   ```

 * [DEPRECATION] The methods `RouteCollection::getParent()` and `RouteCollection::getRoot()`
   have been deprecated and will be removed in Symfony 2.3.
 * [BC BREAK] Misusing the `RouteCollection::addPrefix` method to add defaults, requirements
   or options without adding a prefix is not supported anymore. So if you called `addPrefix`
   with an empty prefix or `/` only (both have no relevance), like
   `addPrefix('', $defaultsArray, $requirementsArray, $optionsArray)`
   you need to use the new dedicated methods `addDefaults($defaultsArray)`,
   `addRequirements($requirementsArray)` or `addOptions($optionsArray)` instead.
 * [DEPRECATION] The `$options` parameter to `RouteCollection::addPrefix()` has been deprecated
   because adding options has nothing to do with adding a path prefix. If you want to add options
   to all child routes of a RouteCollection, you can use `addOptions()`.
 * [DEPRECATION] The method `RouteCollection::getPrefix()` has been deprecated
   because it suggested that all routes in the collection would have this prefix, which is
   not necessarily true. On top of that, since there is no tree structure anymore, this method
   is also useless. Don't worry about performance, prefix optimization for matching is still done
   in the dumper, which was also improved in 2.2.0 to find even more grouping possibilities.
 * [DEPRECATION] `RouteCollection::addCollection(RouteCollection $collection)` should now only be
   used with a single parameter. The other params `$prefix`, `$default`, `$requirements` and `$options`
   will still work, but have been deprecated. The `addPrefix` method should be used for this
   use-case instead.
   Before: `$parentCollection->addCollection($collection, '/prefix', [...], [...])`
   After:
   ```php
   $collection->addPrefix('/prefix', [...], [...]);
   $parentCollection->addCollection($collection);
   ```
 * added support for the method default argument values when defining a @Route
 * Adjacent placeholders without separator work now, e.g. `/{x}{y}{z}.{_format}`.
 * Characters that function as separator between placeholders are now whitelisted
   to fix routes with normal text around a variable, e.g. `/prefix{var}suffix`.
 * [BC BREAK] The default requirement of a variable has been changed slightly.
   Previously it disallowed the previous and the next char around a variable. Now
   it disallows the slash (`/`) and the next char. Using the previous char added
   no value and was problematic because the route `/index.{_format}` would be
   matched by `/index.ht/ml`.
 * The default requirement now uses possessive quantifiers when possible which
   improves matching performance by up to 20% because it prevents backtracking
   when it's not needed.
 * The ConfigurableRequirementsInterface can now also be used to disable the requirements
   check on URL generation completely by calling `setStrictRequirements(null)`. It
   improves performance in production environment as you should know that params always
   pass the requirements (otherwise it would break your link anyway).
 * There is no restriction on the route name anymore. So non-alphanumeric characters
   are now also allowed.
 * [BC BREAK] `RouteCompilerInterface::compile(Route $route)` was made static
   (only relevant if you implemented your own RouteCompiler).
 * Added possibility to generate relative paths and network paths in the UrlGenerator, e.g.
   "../parent-file" and "//example.com/dir/file". The third parameter in
   `UrlGeneratorInterface::generate($name, $parameters = [], $referenceType = self::ABSOLUTE_PATH)`
   now accepts more values and you should use the constants defined in `UrlGeneratorInterface` for
   claritiy. The old method calls with a Boolean parameter will continue to work because they
   equal the signature using the constants.

2.1.0
-----

 * added RequestMatcherInterface
 * added RequestContext::fromRequest()
 * the UrlMatcher does not throw a \LogicException anymore when the required
   scheme is not the current one
 * added TraceableUrlMatcher
 * added the possibility to define options, default values and requirements
   for placeholders in prefix, including imported routes
 * added RouterInterface::getRouteCollection
 * [BC BREAK] the UrlMatcher urldecodes the route parameters only once, they
   were decoded twice before. Note that the `urldecode()` calls have been
   changed for a single `rawurldecode()` in order to support `+` for input
   paths.
 * added RouteCollection::getRoot method to retrieve the root of a
   RouteCollection tree
 * [BC BREAK] made RouteCollection::setParent private which could not have
   been used anyway without creating inconsistencies
 * [BC BREAK] RouteCollection::remove also removes a route from parent
   collections (not only from its children)
 * added ConfigurableRequirementsInterface that allows to disable exceptions
   (and generate empty URLs instead) when generating a route with an invalid
   parameter value
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Routing;

use _ContaoManager\Symfony\Component\HttpFoundation\Request;
/**
 * Holds information about the current request.
 *
 * This class implements a fluent interface.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 * @author Tobias Schultze <http://tobion.de>
 */
class RequestContext
{
    private string $baseUrl;
    private string $pathInfo;
    private string $method;
    private string $host;
    private string $scheme;
    private int $httpPort;
    private int $httpsPort;
    private string $queryString;
    private array $parameters = [];
    public function __construct(string $baseUrl = '', string $method = 'GET', string $host = 'localhost', string $scheme = 'http', int $httpPort = 80, int $httpsPort = 443, string $path = '/', string $queryString = '')
    {
        $this->setBaseUrl($baseUrl);
        $this->setMethod($method);
        $this->setHost($host);
        $this->setScheme($scheme);
        $this->setHttpPort($httpPort);
        $this->setHttpsPort($httpsPort);
        $this->setPathInfo($path);
        $this->setQueryString($queryString);
    }
    public static function fromUri(string $uri, string $host = 'localhost', string $scheme = 'http', int $httpPort = 80, int $httpsPort = 443): self
    {
        $uri = parse_url($uri);
        $scheme = $uri['scheme'] ?? $scheme;
        $host = $uri['host'] ?? $host;
        if (isset($uri['port'])) {
            if ('http' === $scheme) {
                $httpPort = $uri['port'];
            } elseif ('https' === $scheme) {
                $httpsPort = $uri['port'];
            }
        }
        return new self($uri['path'] ?? '', 'GET', $host, $scheme, $httpPort, $httpsPort);
    }
    /**
     * Updates the RequestContext information based on a HttpFoundation Request.
     *
     * @return $this
     */
    public function fromRequest(Request $request): static
    {
        $this->setBaseUrl($request->getBaseUrl());
        $this->setPathInfo($request->getPathInfo());
        $this->setMethod($request->getMethod());
        $this->setHost($request->getHost());
        $this->setScheme($request->getScheme());
        $this->setHttpPort($request->isSecure() || null === $request->getPort() ? $this->httpPort : $request->getPort());
        $this->setHttpsPort($request->isSecure() && null !== $request->getPort() ? $request->getPort() : $this->httpsPort);
        $this->setQueryString($request->server->get('QUERY_STRING', ''));
        return $this;
    }
    /**
     * Gets the base URL.
     */
    public function getBaseUrl(): string
    {
        return $this->baseUrl;
    }
    /**
     * Sets the base URL.
     *
     * @return $this
     */
    public function setBaseUrl(string $baseUrl): static
    {
        $this->baseUrl = rtrim($baseUrl, '/');
        return $this;
    }
    /**
     * Gets the path info.
     */
    public function getPathInfo(): string
    {
        return $this->pathInfo;
    }
    /**
     * Sets the path info.
     *
     * @return $this
     */
    public function setPathInfo(string $pathInfo): static
    {
        $this->pathInfo = $pathInfo;
        return $this;
    }
    /**
     * Gets the HTTP method.
     *
     * The method is always an uppercased string.
     */
    public function getMethod(): string
    {
        return $this->method;
    }
    /**
     * Sets the HTTP method.
     *
     * @return $this
     */
    public function setMethod(string $method): static
    {
        $this->method = strtoupper($method);
        return $this;
    }
    /**
     * Gets the HTTP host.
     *
     * The host is always lowercased because it must be treated case-insensitive.
     */
    public function getHost(): string
    {
        return $this->host;
    }
    /**
     * Sets the HTTP host.
     *
     * @return $this
     */
    public function setHost(string $host): static
    {
        $this->host = strtolower($host);
        return $this;
    }
    /**
     * Gets the HTTP scheme.
     */
    public function getScheme(): string
    {
        return $this->scheme;
    }
    /**
     * Sets the HTTP scheme.
     *
     * @return $this
     */
    public function setScheme(string $scheme): static
    {
        $this->scheme = strtolower($scheme);
        return $this;
    }
    /**
     * Gets the HTTP port.
     */
    public function getHttpPort(): int
    {
        return $this->httpPort;
    }
    /**
     * Sets the HTTP port.
     *
     * @return $this
     */
    public function setHttpPort(int $httpPort): static
    {
        $this->httpPort = $httpPort;
        return $this;
    }
    /**
     * Gets the HTTPS port.
     */
    public function getHttpsPort(): int
    {
        return $this->httpsPort;
    }
    /**
     * Sets the HTTPS port.
     *
     * @return $this
     */
    public function setHttpsPort(int $httpsPort): static
    {
        $this->httpsPort = $httpsPort;
        return $this;
    }
    /**
     * Gets the query string without the "?".
     */
    public function getQueryString(): string
    {
        return $this->queryString;
    }
    /**
     * Sets the query string.
     *
     * @return $this
     */
    public function setQueryString(?string $queryString): static
    {
        // string cast to be fault-tolerant, accepting null
        $this->queryString = (string) $queryString;
        return $this;
    }
    /**
     * Returns the parameters.
     */
    public function getParameters(): array
    {
        return $this->parameters;
    }
    /**
     * Sets the parameters.
     *
     * @param array $parameters The parameters
     *
     * @return $this
     */
    public function setParameters(array $parameters): static
    {
        $this->parameters = $parameters;
        return $this;
    }
    /**
     * Gets a parameter value.
     */
    public function getParameter(string $name): mixed
    {
        return $this->parameters[$name] ?? null;
    }
    /**
     * Checks if a parameter value is set for the given parameter.
     */
    public function hasParameter(string $name): bool
    {
        return \array_key_exists($name, $this->parameters);
    }
    /**
     * Sets a parameter value.
     *
     * @return $this
     */
    public function setParameter(string $name, mixed $parameter): static
    {
        $this->parameters[$name] = $parameter;
        return $this;
    }
    public function isSecure(): bool
    {
        return 'https' === $this->scheme;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Routing\Annotation;

// do not deprecate in 6.4/7.0, to make it easier for the ecosystem to support 6.4, 7.4 and 8.0 simultaneously
class_exists(\_ContaoManager\Symfony\Component\Routing\Attribute\Route::class);
if (\false) {
    #[\Attribute(\Attribute::IS_REPEATABLE | \Attribute::TARGET_CLASS | \Attribute::TARGET_METHOD)]
    class Route extends \_ContaoManager\Symfony\Component\Routing\Attribute\Route
    {
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Routing\Matcher;

use _ContaoManager\Symfony\Component\HttpFoundation\Request;
use _ContaoManager\Symfony\Component\Routing\Exception\MethodNotAllowedException;
use _ContaoManager\Symfony\Component\Routing\Exception\NoConfigurationException;
use _ContaoManager\Symfony\Component\Routing\Exception\ResourceNotFoundException;
/**
 * RequestMatcherInterface is the interface that all request matcher classes must implement.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
interface RequestMatcherInterface
{
    /**
     * Tries to match a request with a set of routes.
     *
     * If the matcher cannot find information, it must throw one of the exceptions documented
     * below.
     *
     * @throws NoConfigurationException  If no routing configuration could be found
     * @throws ResourceNotFoundException If no matching resource could be found
     * @throws MethodNotAllowedException If a matching resource was found but the request method is not allowed
     */
    public function matchRequest(Request $request): array;
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Routing\Matcher;

use _ContaoManager\Symfony\Component\ExpressionLanguage\ExpressionFunction;
use _ContaoManager\Symfony\Component\ExpressionLanguage\ExpressionFunctionProviderInterface;
use _ContaoManager\Symfony\Contracts\Service\ServiceProviderInterface;
/**
 * Exposes functions defined in the request context to route conditions.
 *
 * @author Ahmed TAILOULOUTE <ahmed.tailouloute@gmail.com>
 */
class ExpressionLanguageProvider implements ExpressionFunctionProviderInterface
{
    private ServiceProviderInterface $functions;
    public function __construct(ServiceProviderInterface $functions)
    {
        $this->functions = $functions;
    }
    public function getFunctions(): array
    {
        $functions = [];
        foreach ($this->functions->getProvidedServices() as $function => $type) {
            $functions[] = new ExpressionFunction($function, static fn(...$args) => \sprintf('($context->getParameter(\'_functions\')->get(%s)(%s))', var_export($function, \true), implode(', ', $args)), fn($values, ...$args) => $values['context']->getParameter('_functions')->get($function)(...$args));
        }
        return $functions;
    }
    public function get(string $function): callable
    {
        return $this->functions->get($function);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Routing\Matcher;

use _ContaoManager\Symfony\Component\ExpressionLanguage\ExpressionFunctionProviderInterface;
use _ContaoManager\Symfony\Component\ExpressionLanguage\ExpressionLanguage;
use _ContaoManager\Symfony\Component\HttpFoundation\Request;
use _ContaoManager\Symfony\Component\Routing\Exception\MethodNotAllowedException;
use _ContaoManager\Symfony\Component\Routing\Exception\NoConfigurationException;
use _ContaoManager\Symfony\Component\Routing\Exception\ResourceNotFoundException;
use _ContaoManager\Symfony\Component\Routing\RequestContext;
use _ContaoManager\Symfony\Component\Routing\Route;
use _ContaoManager\Symfony\Component\Routing\RouteCollection;
/**
 * UrlMatcher matches URL based on a set of routes.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class UrlMatcher implements UrlMatcherInterface, RequestMatcherInterface
{
    public const REQUIREMENT_MATCH = 0;
    public const REQUIREMENT_MISMATCH = 1;
    public const ROUTE_MATCH = 2;
    /** @var RequestContext */
    protected $context;
    /**
     * Collects HTTP methods that would be allowed for the request.
     */
    protected $allow = [];
    /**
     * Collects URI schemes that would be allowed for the request.
     *
     * @internal
     */
    protected array $allowSchemes = [];
    protected $routes;
    protected $request;
    protected $expressionLanguage;
    /**
     * @var ExpressionFunctionProviderInterface[]
     */
    protected $expressionLanguageProviders = [];
    public function __construct(RouteCollection $routes, RequestContext $context)
    {
        $this->routes = $routes;
        $this->context = $context;
    }
    /**
     * @return void
     */
    public function setContext(RequestContext $context)
    {
        $this->context = $context;
    }
    public function getContext(): RequestContext
    {
        return $this->context;
    }
    public function match(string $pathinfo): array
    {
        $this->allow = $this->allowSchemes = [];
        $pathinfo = '' === ($pathinfo = rawurldecode($pathinfo)) ? '/' : $pathinfo;
        if ($ret = $this->matchCollection($pathinfo, $this->routes)) {
            return $ret;
        }
        if ('/' === $pathinfo && !$this->allow && !$this->allowSchemes) {
            throw new NoConfigurationException();
        }
        throw 0 < \count($this->allow) ? new MethodNotAllowedException(array_unique($this->allow)) : new ResourceNotFoundException(\sprintf('No routes found for "%s".', $pathinfo));
    }
    public function matchRequest(Request $request): array
    {
        $this->request = $request;
        $ret = $this->match($request->getPathInfo());
        $this->request = null;
        return $ret;
    }
    /**
     * @return void
     */
    public function addExpressionLanguageProvider(ExpressionFunctionProviderInterface $provider)
    {
        $this->expressionLanguageProviders[] = $provider;
    }
    /**
     * Tries to match a URL with a set of routes.
     *
     * @param string $pathinfo The path info to be parsed
     *
     * @throws NoConfigurationException  If no routing configuration could be found
     * @throws ResourceNotFoundException If the resource could not be found
     * @throws MethodNotAllowedException If the resource was found but the request method is not allowed
     */
    protected function matchCollection(string $pathinfo, RouteCollection $routes): array
    {
        // HEAD and GET are equivalent as per RFC
        if ('HEAD' === $method = $this->context->getMethod()) {
            $method = 'GET';
        }
        $supportsTrailingSlash = 'GET' === $method && $this instanceof RedirectableUrlMatcherInterface;
        $trimmedPathinfo = '' === ($trimmedPathinfo = rtrim($pathinfo, '/')) ? '/' : $trimmedPathinfo;
        foreach ($routes as $name => $route) {
            $compiledRoute = $route->compile();
            $staticPrefix = rtrim($compiledRoute->getStaticPrefix(), '/');
            $requiredMethods = $route->getMethods();
            // check the static prefix of the URL first. Only use the more expensive preg_match when it matches
            if ('' !== $staticPrefix && !str_starts_with($trimmedPathinfo, $staticPrefix)) {
                continue;
            }
            $regex = $compiledRoute->getRegex();
            $pos = strrpos($regex, '$');
            $hasTrailingSlash = '/' === $regex[$pos - 1];
            $regex = substr_replace($regex, '/?$', $pos - $hasTrailingSlash, 1 + $hasTrailingSlash);
            if (!preg_match($regex, $pathinfo, $matches)) {
                continue;
            }
            $hasTrailingVar = $trimmedPathinfo !== $pathinfo && preg_match('#\{[\w\x80-\xFF]+\}/?$#', $route->getPath());
            if ($hasTrailingVar && ($hasTrailingSlash || null === ($m = $matches[\count($compiledRoute->getPathVariables())] ?? null) || '/' !== ($m[-1] ?? '/')) && preg_match($regex, $trimmedPathinfo, $m)) {
                if ($hasTrailingSlash) {
                    $matches = $m;
                } else {
                    $hasTrailingVar = \false;
                }
            }
            $hostMatches = [];
            if ($compiledRoute->getHostRegex() && !preg_match($compiledRoute->getHostRegex(), $this->context->getHost(), $hostMatches)) {
                continue;
            }
            $attributes = $this->getAttributes($route, $name, array_replace($matches, $hostMatches));
            $status = $this->handleRouteRequirements($pathinfo, $name, $route, $attributes);
            if (self::REQUIREMENT_MISMATCH === $status[0]) {
                continue;
            }
            if ('/' !== $pathinfo && !$hasTrailingVar && $hasTrailingSlash === ($trimmedPathinfo === $pathinfo)) {
                if ($supportsTrailingSlash && (!$requiredMethods || \in_array('GET', $requiredMethods))) {
                    return $this->allow = $this->allowSchemes = [];
                }
                continue;
            }
            if ($route->getSchemes() && !$route->hasScheme($this->context->getScheme())) {
                $this->allowSchemes = array_merge($this->allowSchemes, $route->getSchemes());
                continue;
            }
            if ($requiredMethods && !\in_array($method, $requiredMethods)) {
                $this->allow = array_merge($this->allow, $requiredMethods);
                continue;
            }
            return array_replace($attributes, $status[1] ?? []);
        }
        return [];
    }
    /**
     * Returns an array of values to use as request attributes.
     *
     * As this method requires the Route object, it is not available
     * in matchers that do not have access to the matched Route instance
     * (like the PHP and Apache matcher dumpers).
     */
    protected function getAttributes(Route $route, string $name, array $attributes): array
    {
        $defaults = $route->getDefaults();
        if (isset($defaults['_canonical_route'])) {
            $name = $defaults['_canonical_route'];
            unset($defaults['_canonical_route']);
        }
        $attributes['_route'] = $name;
        return $this->mergeDefaults($attributes, $defaults);
    }
    /**
     * Handles specific route requirements.
     *
     * @return array The first element represents the status, the second contains additional information
     */
    protected function handleRouteRequirements(string $pathinfo, string $name, Route $route): array
    {
        if (\func_num_args() < 4) {
            trigger_deprecation('symfony/routing', '6.1', 'The "%s()" method will have a new "array $routeParameters" argument in version 7.0, not defining it is deprecated.', __METHOD__);
            $routeParameters = [];
        } else {
            $routeParameters = func_get_arg(3);
            if (!\is_array($routeParameters)) {
                throw new \TypeError(\sprintf('"%s": Argument $routeParameters is expected to be an array, got "%s".', __METHOD__, get_debug_type($routeParameters)));
            }
        }
        // expression condition
        if ($route->getCondition() && !$this->getExpressionLanguage()->evaluate($route->getCondition(), ['context' => $this->context, 'request' => $this->request ?: $this->createRequest($pathinfo), 'params' => $routeParameters])) {
            return [self::REQUIREMENT_MISMATCH, null];
        }
        return [self::REQUIREMENT_MATCH, null];
    }
    /**
     * Get merged default parameters.
     */
    protected function mergeDefaults(array $params, array $defaults): array
    {
        foreach ($params as $key => $value) {
            if (!\is_int($key) && null !== $value) {
                $defaults[$key] = $value;
            }
        }
        return $defaults;
    }
    /**
     * @return ExpressionLanguage
     */
    protected function getExpressionLanguage()
    {
        if (!isset($this->expressionLanguage)) {
            if (!class_exists(ExpressionLanguage::class)) {
                throw new \LogicException('Unable to use expressions as the Symfony ExpressionLanguage component is not installed. Try running "composer require symfony/expression-language".');
            }
            $this->expressionLanguage = new ExpressionLanguage(null, $this->expressionLanguageProviders);
        }
        return $this->expressionLanguage;
    }
    /**
     * @internal
     */
    protected function createRequest(string $pathinfo): ?Request
    {
        if (!class_exists(Request::class)) {
            return null;
        }
        return Request::create($this->context->getScheme() . '://' . $this->context->getHost() . $this->context->getBaseUrl() . $pathinfo, $this->context->getMethod(), $this->context->getParameters(), [], [], ['SCRIPT_FILENAME' => $this->context->getBaseUrl(), 'SCRIPT_NAME' => $this->context->getBaseUrl()]);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Routing\Matcher;

/**
 * RedirectableUrlMatcherInterface knows how to redirect the user.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
interface RedirectableUrlMatcherInterface
{
    /**
     * Redirects the user to another URL and returns the parameters for the redirection.
     *
     * @param string      $path   The path info to redirect to
     * @param string      $route  The route name that matched
     * @param string|null $scheme The URL scheme (null to keep the current one)
     */
    public function redirect(string $path, string $route, ?string $scheme = null): array;
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Routing\Matcher;

use _ContaoManager\Symfony\Component\Routing\Exception\MethodNotAllowedException;
use _ContaoManager\Symfony\Component\Routing\Exception\NoConfigurationException;
use _ContaoManager\Symfony\Component\Routing\Exception\ResourceNotFoundException;
use _ContaoManager\Symfony\Component\Routing\RequestContextAwareInterface;
/**
 * UrlMatcherInterface is the interface that all URL matcher classes must implement.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
interface UrlMatcherInterface extends RequestContextAwareInterface
{
    /**
     * Tries to match a URL path with a set of routes.
     *
     * If the matcher cannot find information, it must throw one of the exceptions documented
     * below.
     *
     * @param string $pathinfo The path info to be parsed (raw format, i.e. not urldecoded)
     *
     * @throws NoConfigurationException  If no routing configuration could be found
     * @throws ResourceNotFoundException If the resource could not be found
     * @throws MethodNotAllowedException If the resource was found but the request method is not allowed
     */
    public function match(string $pathinfo): array;
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Routing\Matcher;

use _ContaoManager\Symfony\Component\Routing\Matcher\Dumper\CompiledUrlMatcherTrait;
use _ContaoManager\Symfony\Component\Routing\RequestContext;
/**
 * Matches URLs based on rules dumped by CompiledUrlMatcherDumper.
 *
 * @author Nicolas Grekas <p@tchwork.com>
 */
class CompiledUrlMatcher extends UrlMatcher
{
    use CompiledUrlMatcherTrait;
    public function __construct(array $compiledRoutes, RequestContext $context)
    {
        $this->context = $context;
        [$this->matchHost, $this->staticRoutes, $this->regexpList, $this->dynamicRoutes, $this->checkCondition] = $compiledRoutes;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Routing\Matcher;

use _ContaoManager\Symfony\Component\HttpFoundation\Request;
use _ContaoManager\Symfony\Component\Routing\Exception\ExceptionInterface;
use _ContaoManager\Symfony\Component\Routing\Route;
use _ContaoManager\Symfony\Component\Routing\RouteCollection;
/**
 * TraceableUrlMatcher helps debug path info matching by tracing the match.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class TraceableUrlMatcher extends UrlMatcher
{
    public const ROUTE_DOES_NOT_MATCH = 0;
    public const ROUTE_ALMOST_MATCHES = 1;
    public const ROUTE_MATCHES = 2;
    protected $traces;
    /**
     * @return array
     */
    public function getTraces(string $pathinfo)
    {
        $this->traces = [];
        try {
            $this->match($pathinfo);
        } catch (ExceptionInterface) {
        }
        return $this->traces;
    }
    /**
     * @return array
     */
    public function getTracesForRequest(Request $request)
    {
        $this->request = $request;
        $traces = $this->getTraces($request->getPathInfo());
        $this->request = null;
        return $traces;
    }
    protected function matchCollection(string $pathinfo, RouteCollection $routes): array
    {
        // HEAD and GET are equivalent as per RFC
        if ('HEAD' === $method = $this->context->getMethod()) {
            $method = 'GET';
        }
        $supportsTrailingSlash = 'GET' === $method && $this instanceof RedirectableUrlMatcherInterface;
        $trimmedPathinfo = '' === ($trimmedPathinfo = rtrim($pathinfo, '/')) ? '/' : $trimmedPathinfo;
        foreach ($routes as $name => $route) {
            $compiledRoute = $route->compile();
            $staticPrefix = rtrim($compiledRoute->getStaticPrefix(), '/');
            $requiredMethods = $route->getMethods();
            // check the static prefix of the URL first. Only use the more expensive preg_match when it matches
            if ('' !== $staticPrefix && !str_starts_with($trimmedPathinfo, $staticPrefix)) {
                $this->addTrace(\sprintf('Path "%s" does not match', $route->getPath()), self::ROUTE_DOES_NOT_MATCH, $name, $route);
                continue;
            }
            $regex = $compiledRoute->getRegex();
            $pos = strrpos($regex, '$');
            $hasTrailingSlash = '/' === $regex[$pos - 1];
            $regex = substr_replace($regex, '/?$', $pos - $hasTrailingSlash, 1 + $hasTrailingSlash);
            if (!preg_match($regex, $pathinfo, $matches)) {
                // does it match without any requirements?
                $r = new Route($route->getPath(), $route->getDefaults(), [], $route->getOptions());
                $cr = $r->compile();
                if (!preg_match($cr->getRegex(), $pathinfo)) {
                    $this->addTrace(\sprintf('Path "%s" does not match', $route->getPath()), self::ROUTE_DOES_NOT_MATCH, $name, $route);
                    continue;
                }
                foreach ($route->getRequirements() as $n => $regex) {
                    $r = new Route($route->getPath(), $route->getDefaults(), [$n => $regex], $route->getOptions());
                    $cr = $r->compile();
                    if (\in_array($n, $cr->getVariables()) && !preg_match($cr->getRegex(), $pathinfo)) {
                        $this->addTrace(\sprintf('Requirement for "%s" does not match (%s)', $n, $regex), self::ROUTE_ALMOST_MATCHES, $name, $route);
                        continue 2;
                    }
                }
                continue;
            }
            $hasTrailingVar = $trimmedPathinfo !== $pathinfo && preg_match('#\{[\w\x80-\xFF]+\}/?$#', $route->getPath());
            if ($hasTrailingVar && ($hasTrailingSlash || null === ($m = $matches[\count($compiledRoute->getPathVariables())] ?? null) || '/' !== ($m[-1] ?? '/')) && preg_match($regex, $trimmedPathinfo, $m)) {
                if ($hasTrailingSlash) {
                    $matches = $m;
                } else {
                    $hasTrailingVar = \false;
                }
            }
            $hostMatches = [];
            if ($compiledRoute->getHostRegex() && !preg_match($compiledRoute->getHostRegex(), $this->context->getHost(), $hostMatches)) {
                $this->addTrace(\sprintf('Host "%s" does not match the requirement ("%s")', $this->context->getHost(), $route->getHost()), self::ROUTE_ALMOST_MATCHES, $name, $route);
                continue;
            }
            $attributes = $this->getAttributes($route, $name, array_replace($matches, $hostMatches));
            $status = $this->handleRouteRequirements($pathinfo, $name, $route, $attributes);
            if (self::REQUIREMENT_MISMATCH === $status[0]) {
                $this->addTrace(\sprintf('Condition "%s" does not evaluate to "true"', $route->getCondition()), self::ROUTE_ALMOST_MATCHES, $name, $route);
                continue;
            }
            if ('/' !== $pathinfo && !$hasTrailingVar && $hasTrailingSlash === ($trimmedPathinfo === $pathinfo)) {
                if ($supportsTrailingSlash && (!$requiredMethods || \in_array('GET', $requiredMethods))) {
                    $this->addTrace('Route matches!', self::ROUTE_MATCHES, $name, $route);
                    return $this->allow = $this->allowSchemes = [];
                }
                $this->addTrace(\sprintf('Path "%s" does not match', $route->getPath()), self::ROUTE_DOES_NOT_MATCH, $name, $route);
                continue;
            }
            if ($route->getSchemes() && !$route->hasScheme($this->context->getScheme())) {
                $this->allowSchemes = array_merge($this->allowSchemes, $route->getSchemes());
                $this->addTrace(\sprintf('Scheme "%s" does not match any of the required schemes (%s)', $this->context->getScheme(), implode(', ', $route->getSchemes())), self::ROUTE_ALMOST_MATCHES, $name, $route);
                continue;
            }
            if ($requiredMethods && !\in_array($method, $requiredMethods)) {
                $this->allow = array_merge($this->allow, $requiredMethods);
                $this->addTrace(\sprintf('Method "%s" does not match any of the required methods (%s)', $this->context->getMethod(), implode(', ', $requiredMethods)), self::ROUTE_ALMOST_MATCHES, $name, $route);
                continue;
            }
            $this->addTrace('Route matches!', self::ROUTE_MATCHES, $name, $route);
            return array_replace($attributes, $status[1] ?? []);
        }
        return [];
    }
    private function addTrace(string $log, int $level = self::ROUTE_DOES_NOT_MATCH, ?string $name = null, ?Route $route = null): void
    {
        $this->traces[] = ['log' => $log, 'name' => $name, 'level' => $level, 'path' => $route?->getPath()];
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Routing\Matcher\Dumper;

use _ContaoManager\Symfony\Component\ExpressionLanguage\ExpressionFunctionProviderInterface;
use _ContaoManager\Symfony\Component\ExpressionLanguage\ExpressionLanguage;
use _ContaoManager\Symfony\Component\Routing\Route;
use _ContaoManager\Symfony\Component\Routing\RouteCollection;
/**
 * CompiledUrlMatcherDumper creates PHP arrays to be used with CompiledUrlMatcher.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 * @author Tobias Schultze <http://tobion.de>
 * @author Arnaud Le Blanc <arnaud.lb@gmail.com>
 * @author Nicolas Grekas <p@tchwork.com>
 */
class CompiledUrlMatcherDumper extends MatcherDumper
{
    private ExpressionLanguage $expressionLanguage;
    private ?\Exception $signalingException = null;
    /**
     * @var ExpressionFunctionProviderInterface[]
     */
    private array $expressionLanguageProviders = [];
    public function dump(array $options = []): string
    {
        return <<<EOF
<?php

/**
 * This file has been auto-generated
 * by the Symfony Routing Component.
 */

return [
{$this->generateCompiledRoutes()}];

EOF;
    }
    /**
     * @return void
     */
    public function addExpressionLanguageProvider(ExpressionFunctionProviderInterface $provider)
    {
        $this->expressionLanguageProviders[] = $provider;
    }
    /**
     * Generates the arrays for CompiledUrlMatcher's constructor.
     */
    public function getCompiledRoutes(bool $forDump = \false): array
    {
        // Group hosts by same-suffix, re-order when possible
        $matchHost = \false;
        $routes = new StaticPrefixCollection();
        foreach ($this->getRoutes()->all() as $name => $route) {
            if ($host = $route->getHost()) {
                $matchHost = \true;
                $host = '/' . strtr(strrev($host), '}.{', '(/)');
            }
            $routes->addRoute($host ?: '/(.*)', [$name, $route]);
        }
        if ($matchHost) {
            $compiledRoutes = [\true];
            $routes = $routes->populateCollection(new RouteCollection());
        } else {
            $compiledRoutes = [\false];
            $routes = $this->getRoutes();
        }
        [$staticRoutes, $dynamicRoutes] = $this->groupStaticRoutes($routes);
        $conditions = [null];
        $compiledRoutes[] = $this->compileStaticRoutes($staticRoutes, $conditions);
        $chunkLimit = \count($dynamicRoutes);
        while (\true) {
            try {
                $this->signalingException = new \RuntimeException('Compilation failed: regular expression is too large');
                $compiledRoutes = array_merge($compiledRoutes, $this->compileDynamicRoutes($dynamicRoutes, $matchHost, $chunkLimit, $conditions));
                break;
            } catch (\Exception $e) {
                if (1 < $chunkLimit && $this->signalingException === $e) {
                    $chunkLimit = 1 + ($chunkLimit >> 1);
                    continue;
                }
                throw $e;
            }
        }
        if ($forDump) {
            $compiledRoutes[2] = $compiledRoutes[4];
        }
        unset($conditions[0]);
        if ($conditions) {
            foreach ($conditions as $expression => $condition) {
                $conditions[$expression] = "case {$condition}: return {$expression};";
            }
            $checkConditionCode = <<<EOF
    static function (\$condition, \$context, \$request, \$params) { // \$checkCondition
        switch (\$condition) {
{$this->indent(implode("\n", $conditions), 3)}
        }
    }
EOF;
            $compiledRoutes[4] = $forDump ? $checkConditionCode . ",\n" : eval('return ' . $checkConditionCode . ';');
        } else {
            $compiledRoutes[4] = $forDump ? "    null, // \$checkCondition\n" : null;
        }
        return $compiledRoutes;
    }
    private function generateCompiledRoutes(): string
    {
        [$matchHost, $staticRoutes, $regexpCode, $dynamicRoutes, $checkConditionCode] = $this->getCompiledRoutes(\true);
        $code = self::export($matchHost) . ', // $matchHost' . "\n";
        $code .= '[ // $staticRoutes' . "\n";
        foreach ($staticRoutes as $path => $routes) {
            $code .= \sprintf("    %s => [\n", self::export($path));
            foreach ($routes as $route) {
                $code .= vsprintf("        [%s, %s, %s, %s, %s, %s, %s],\n", array_map([__CLASS__, 'export'], $route));
            }
            $code .= "    ],\n";
        }
        $code .= "],\n";
        $code .= \sprintf("[ // \$regexpList%s\n],\n", $regexpCode);
        $code .= '[ // $dynamicRoutes' . "\n";
        foreach ($dynamicRoutes as $path => $routes) {
            $code .= \sprintf("    %s => [\n", self::export($path));
            foreach ($routes as $route) {
                $code .= vsprintf("        [%s, %s, %s, %s, %s, %s, %s],\n", array_map([__CLASS__, 'export'], $route));
            }
            $code .= "    ],\n";
        }
        $code .= "],\n";
        $code = preg_replace('/ => \[\n        (\[.+?),\n    \],/', ' => [$1],', $code);
        return $this->indent($code, 1) . $checkConditionCode;
    }
    /**
     * Splits static routes from dynamic routes, so that they can be matched first, using a simple switch.
     */
    private function groupStaticRoutes(RouteCollection $collection): array
    {
        $staticRoutes = $dynamicRegex = [];
        $dynamicRoutes = new RouteCollection();
        foreach ($collection->all() as $name => $route) {
            $compiledRoute = $route->compile();
            $staticPrefix = rtrim($compiledRoute->getStaticPrefix(), '/');
            $hostRegex = $compiledRoute->getHostRegex();
            $regex = $compiledRoute->getRegex();
            if ($hasTrailingSlash = '/' !== $route->getPath()) {
                $pos = strrpos($regex, '$');
                $hasTrailingSlash = '/' === $regex[$pos - 1];
                $regex = substr_replace($regex, '/?$', $pos - $hasTrailingSlash, 1 + $hasTrailingSlash);
            }
            if (!$compiledRoute->getPathVariables()) {
                $host = !$compiledRoute->getHostVariables() ? $route->getHost() : '';
                $url = $route->getPath();
                if ($hasTrailingSlash) {
                    $url = substr($url, 0, -1);
                }
                foreach ($dynamicRegex as [$hostRx, $rx, $prefix]) {
                    if (('' === $prefix || str_starts_with($url, $prefix)) && (preg_match($rx, $url) || preg_match($rx, $url . '/')) && (!$host || !$hostRx || preg_match($hostRx, $host))) {
                        $dynamicRegex[] = [$hostRegex, $regex, $staticPrefix];
                        $dynamicRoutes->add($name, $route);
                        continue 2;
                    }
                }
                $staticRoutes[$url][$name] = [$route, $hasTrailingSlash];
            } else {
                $dynamicRegex[] = [$hostRegex, $regex, $staticPrefix];
                $dynamicRoutes->add($name, $route);
            }
        }
        return [$staticRoutes, $dynamicRoutes];
    }
    /**
     * Compiles static routes in a switch statement.
     *
     * Condition-less paths are put in a static array in the switch's default, with generic matching logic.
     * Paths that can match two or more routes, or have user-specified conditions are put in separate switch's cases.
     *
     * @throws \LogicException
     */
    private function compileStaticRoutes(array $staticRoutes, array &$conditions): array
    {
        if (!$staticRoutes) {
            return [];
        }
        $compiledRoutes = [];
        foreach ($staticRoutes as $url => $routes) {
            $compiledRoutes[$url] = [];
            foreach ($routes as $name => [$route, $hasTrailingSlash]) {
                if ($route->compile()->getHostVariables()) {
                    $host = $route->compile()->getHostRegex();
                } elseif ($host = $route->getHost()) {
                    $host = strtolower($host);
                }
                $compiledRoutes[$url][] = $this->compileRoute($route, $name, $host ?: null, $hasTrailingSlash, \false, $conditions);
            }
        }
        return $compiledRoutes;
    }
    /**
     * Compiles a regular expression followed by a switch statement to match dynamic routes.
     *
     * The regular expression matches both the host and the pathinfo at the same time. For stellar performance,
     * it is built as a tree of patterns, with re-ordering logic to group same-prefix routes together when possible.
     *
     * Patterns are named so that we know which one matched (https://pcre.org/current/doc/html/pcre2syntax.html#SEC23).
     * This name is used to "switch" to the additional logic required to match the final route.
     *
     * Condition-less paths are put in a static array in the switch's default, with generic matching logic.
     * Paths that can match two or more routes, or have user-specified conditions are put in separate switch's cases.
     *
     * Last but not least:
     *  - Because it is not possible to mix unicode/non-unicode patterns in a single regexp, several of them can be generated.
     *  - The same regexp can be used several times when the logic in the switch rejects the match. When this happens, the
     *    matching-but-failing subpattern is excluded by replacing its name by "(*F)", which forces a failure-to-match.
     *    To ease this backlisting operation, the name of subpatterns is also the string offset where the replacement should occur.
     */
    private function compileDynamicRoutes(RouteCollection $collection, bool $matchHost, int $chunkLimit, array &$conditions): array
    {
        if (!$collection->all()) {
            return [[], [], ''];
        }
        $regexpList = [];
        $code = '';
        $state = (object) ['regexMark' => 0, 'regex' => [], 'routes' => [], 'mark' => 0, 'markTail' => 0, 'hostVars' => [], 'vars' => []];
        $state->getVars = static function ($m) use ($state) {
            if ('_route' === $m[1]) {
                return '?:';
            }
            $state->vars[] = $m[1];
            return '';
        };
        $chunkSize = 0;
        $prev = null;
        $perModifiers = [];
        foreach ($collection->all() as $name => $route) {
            preg_match('#[a-zA-Z]*$#', $route->compile()->getRegex(), $rx);
            if ($chunkLimit < ++$chunkSize || $prev !== $rx[0] && $route->compile()->getPathVariables()) {
                $chunkSize = 1;
                $routes = new RouteCollection();
                $perModifiers[] = [$rx[0], $routes];
                $prev = $rx[0];
            }
            $routes->add($name, $route);
        }
        foreach ($perModifiers as [$modifiers, $routes]) {
            $prev = \false;
            $perHost = [];
            foreach ($routes->all() as $name => $route) {
                $regex = $route->compile()->getHostRegex();
                if ($prev !== $regex) {
                    $routes = new RouteCollection();
                    $perHost[] = [$regex, $routes];
                    $prev = $regex;
                }
                $routes->add($name, $route);
            }
            $prev = \false;
            $rx = '{^(?';
            $code .= "\n    {$state->mark} => " . self::export($rx);
            $startingMark = $state->mark;
            $state->mark += \strlen($rx);
            $state->regex = $rx;
            foreach ($perHost as [$hostRegex, $routes]) {
                if ($matchHost) {
                    if ($hostRegex) {
                        preg_match('#^.\^(.*)\$.[a-zA-Z]*$#', $hostRegex, $rx);
                        $state->vars = [];
                        $hostRegex = '(?i:' . preg_replace_callback('#\?P<([^>]++)>#', $state->getVars, $rx[1]) . ')\.';
                        $state->hostVars = $state->vars;
                    } else {
                        $hostRegex = '(?:(?:[^./]*+\.)++)';
                        $state->hostVars = [];
                    }
                    $state->mark += \strlen($rx = ($prev ? ')' : '') . "|{$hostRegex}(?");
                    $code .= "\n        ." . self::export($rx);
                    $state->regex .= $rx;
                    $prev = \true;
                }
                $tree = new StaticPrefixCollection();
                foreach ($routes->all() as $name => $route) {
                    preg_match('#^.\^(.*)\$.[a-zA-Z]*$#', $route->compile()->getRegex(), $rx);
                    $state->vars = [];
                    $regex = preg_replace_callback('#\?P<([^>]++)>#', $state->getVars, $rx[1]);
                    if ($hasTrailingSlash = '/' !== $regex && '/' === $regex[-1]) {
                        $regex = substr($regex, 0, -1);
                    }
                    $hasTrailingVar = (bool) preg_match('#\{[\w\x80-\xFF]+\}/?$#', $route->getPath());
                    $tree->addRoute($regex, [$name, $regex, $state->vars, $route, $hasTrailingSlash, $hasTrailingVar]);
                }
                $code .= $this->compileStaticPrefixCollection($tree, $state, 0, $conditions);
            }
            if ($matchHost) {
                $code .= "\n        .')'";
                $state->regex .= ')';
            }
            $rx = ")/?\$}{$modifiers}";
            $code .= "\n        .'{$rx}',";
            $state->regex .= $rx;
            $state->markTail = 0;
            // if the regex is too large, throw a signaling exception to recompute with smaller chunk size
            set_error_handler(fn($type, $message) => throw str_contains($message, $this->signalingException->getMessage()) ? $this->signalingException : new \ErrorException($message));
            try {
                preg_match($state->regex, '');
            } finally {
                restore_error_handler();
            }
            $regexpList[$startingMark] = $state->regex;
        }
        $state->routes[$state->mark][] = [null, null, null, null, \false, \false, 0];
        unset($state->getVars);
        return [$regexpList, $state->routes, $code];
    }
    /**
     * Compiles a regexp tree of subpatterns that matches nested same-prefix routes.
     *
     * @param \stdClass $state A simple state object that keeps track of the progress of the compilation,
     *                         and gathers the generated switch's "case" and "default" statements
     */
    private function compileStaticPrefixCollection(StaticPrefixCollection $tree, \stdClass $state, int $prefixLen, array &$conditions): string
    {
        $code = '';
        $prevRegex = null;
        $routes = $tree->getRoutes();
        foreach ($routes as $i => $route) {
            if ($route instanceof StaticPrefixCollection) {
                $prevRegex = null;
                $prefix = substr($route->getPrefix(), $prefixLen);
                $state->mark += \strlen($rx = "|{$prefix}(?");
                $code .= "\n            ." . self::export($rx);
                $state->regex .= $rx;
                $code .= $this->indent($this->compileStaticPrefixCollection($route, $state, $prefixLen + \strlen($prefix), $conditions));
                $code .= "\n            .')'";
                $state->regex .= ')';
                ++$state->markTail;
                continue;
            }
            [$name, $regex, $vars, $route, $hasTrailingSlash, $hasTrailingVar] = $route;
            $compiledRoute = $route->compile();
            $vars = array_merge($state->hostVars, $vars);
            if ($compiledRoute->getRegex() === $prevRegex) {
                $state->routes[$state->mark][] = $this->compileRoute($route, $name, $vars, $hasTrailingSlash, $hasTrailingVar, $conditions);
                continue;
            }
            $state->mark += 3 + $state->markTail + \strlen($regex) - $prefixLen;
            $state->markTail = 2 + \strlen($state->mark);
            $rx = \sprintf('|%s(*:%s)', substr($regex, $prefixLen), $state->mark);
            $code .= "\n            ." . self::export($rx);
            $state->regex .= $rx;
            $prevRegex = $compiledRoute->getRegex();
            $state->routes[$state->mark] = [$this->compileRoute($route, $name, $vars, $hasTrailingSlash, $hasTrailingVar, $conditions)];
        }
        return $code;
    }
    /**
     * Compiles a single Route to PHP code used to match it against the path info.
     */
    private function compileRoute(Route $route, string $name, string|array|null $vars, bool $hasTrailingSlash, bool $hasTrailingVar, array &$conditions): array
    {
        $defaults = $route->getDefaults();
        if (isset($defaults['_canonical_route'])) {
            $name = $defaults['_canonical_route'];
            unset($defaults['_canonical_route']);
        }
        if ($condition = $route->getCondition()) {
            $condition = $this->getExpressionLanguage()->compile($condition, ['context', 'request', 'params']);
            $condition = $conditions[$condition] ??= (str_contains($condition, '$request') ? 1 : -1) * \count($conditions);
        } else {
            $condition = null;
        }
        return [['_route' => $name] + $defaults, $vars, array_flip($route->getMethods()) ?: null, array_flip($route->getSchemes()) ?: null, $hasTrailingSlash, $hasTrailingVar, $condition];
    }
    private function getExpressionLanguage(): ExpressionLanguage
    {
        if (!isset($this->expressionLanguage)) {
            if (!class_exists(ExpressionLanguage::class)) {
                throw new \LogicException('Unable to use expressions as the Symfony ExpressionLanguage component is not installed. Try running "composer require symfony/expression-language".');
            }
            $this->expressionLanguage = new ExpressionLanguage(null, $this->expressionLanguageProviders);
        }
        return $this->expressionLanguage;
    }
    private function indent(string $code, int $level = 1): string
    {
        return preg_replace('/^./m', str_repeat('    ', $level) . '$0', $code);
    }
    /**
     * @internal
     */
    public static function export(mixed $value): string
    {
        if (null === $value) {
            return 'null';
        }
        if (!\is_array($value)) {
            if (\is_object($value)) {
                throw new \InvalidArgumentException('Symfony\Component\Routing\Route cannot contain objects.');
            }
            return str_replace("\n", '\'."\n".\'', var_export($value, \true));
        }
        if (!$value) {
            return '[]';
        }
        $i = 0;
        $export = '[';
        foreach ($value as $k => $v) {
            if ($i === $k) {
                ++$i;
            } else {
                $export .= self::export($k) . ' => ';
                if (\is_int($k) && $i < $k) {
                    $i = 1 + $k;
                }
            }
            $export .= self::export($v) . ', ';
        }
        return substr_replace($export, ']', -2);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Routing\Matcher\Dumper;

use _ContaoManager\Symfony\Component\Routing\RouteCollection;
/**
 * MatcherDumper is the abstract class for all built-in matcher dumpers.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
abstract class MatcherDumper implements MatcherDumperInterface
{
    private RouteCollection $routes;
    public function __construct(RouteCollection $routes)
    {
        $this->routes = $routes;
    }
    public function getRoutes(): RouteCollection
    {
        return $this->routes;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Routing\Matcher\Dumper;

use _ContaoManager\Symfony\Component\Routing\RouteCollection;
/**
 * MatcherDumperInterface is the interface that all matcher dumper classes must implement.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
interface MatcherDumperInterface
{
    /**
     * Dumps a set of routes to a string representation of executable code
     * that can then be used to match a request against these routes.
     */
    public function dump(array $options = []): string;
    /**
     * Gets the routes to dump.
     */
    public function getRoutes(): RouteCollection;
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Routing\Matcher\Dumper;

use _ContaoManager\Symfony\Component\Routing\Exception\MethodNotAllowedException;
use _ContaoManager\Symfony\Component\Routing\Exception\NoConfigurationException;
use _ContaoManager\Symfony\Component\Routing\Exception\ResourceNotFoundException;
use _ContaoManager\Symfony\Component\Routing\Matcher\RedirectableUrlMatcherInterface;
use _ContaoManager\Symfony\Component\Routing\RequestContext;
/**
 * @author Nicolas Grekas <p@tchwork.com>
 *
 * @internal
 *
 * @property RequestContext $context
 */
trait CompiledUrlMatcherTrait
{
    private bool $matchHost = \false;
    private array $staticRoutes = [];
    private array $regexpList = [];
    private array $dynamicRoutes = [];
    private ?\Closure $checkCondition;
    public function match(string $pathinfo): array
    {
        $allow = $allowSchemes = [];
        if ($ret = $this->doMatch($pathinfo, $allow, $allowSchemes)) {
            return $ret;
        }
        if ($allow) {
            throw new MethodNotAllowedException(array_keys($allow));
        }
        if (!$this instanceof RedirectableUrlMatcherInterface) {
            throw new ResourceNotFoundException(\sprintf('No routes found for "%s".', $pathinfo));
        }
        if (!\in_array($this->context->getMethod(), ['HEAD', 'GET'], \true)) {
            // no-op
        } elseif ($allowSchemes) {
            redirect_scheme:
            $scheme = $this->context->getScheme();
            $this->context->setScheme(key($allowSchemes));
            try {
                if ($ret = $this->doMatch($pathinfo)) {
                    return $this->redirect($pathinfo, $ret['_route'], $this->context->getScheme()) + $ret;
                }
            } finally {
                $this->context->setScheme($scheme);
            }
        } elseif ('' !== $trimmedPathinfo = rtrim($pathinfo, '/')) {
            $pathinfo = $trimmedPathinfo === $pathinfo ? $pathinfo . '/' : $trimmedPathinfo;
            if ($ret = $this->doMatch($pathinfo, $allow, $allowSchemes)) {
                return $this->redirect($pathinfo, $ret['_route']) + $ret;
            }
            if ($allowSchemes) {
                goto redirect_scheme;
            }
        }
        throw new ResourceNotFoundException(\sprintf('No routes found for "%s".', $pathinfo));
    }
    private function doMatch(string $pathinfo, array &$allow = [], array &$allowSchemes = []): array
    {
        $allow = $allowSchemes = [];
        $pathinfo = '' === ($pathinfo = rawurldecode($pathinfo)) ? '/' : $pathinfo;
        $trimmedPathinfo = '' === ($trimmedPathinfo = rtrim($pathinfo, '/')) ? '/' : $trimmedPathinfo;
        $context = $this->context;
        $requestMethod = $canonicalMethod = $context->getMethod();
        if ($this->matchHost) {
            $host = strtolower($context->getHost());
        }
        if ('HEAD' === $requestMethod) {
            $canonicalMethod = 'GET';
        }
        $supportsRedirections = 'GET' === $canonicalMethod && $this instanceof RedirectableUrlMatcherInterface;
        foreach ($this->staticRoutes[$trimmedPathinfo] ?? [] as [$ret, $requiredHost, $requiredMethods, $requiredSchemes, $hasTrailingSlash, , $condition]) {
            if ($requiredHost) {
                if ('{' !== $requiredHost[0] ? $requiredHost !== $host : !preg_match($requiredHost, $host, $hostMatches)) {
                    continue;
                }
                if ('{' === $requiredHost[0] && $hostMatches) {
                    $hostMatches['_route'] = $ret['_route'];
                    $ret = $this->mergeDefaults($hostMatches, $ret);
                }
            }
            if ($condition && !($this->checkCondition)($condition, $context, 0 < $condition ? $request ??= $this->request ?: $this->createRequest($pathinfo) : null, $ret)) {
                continue;
            }
            if ('/' !== $pathinfo && $hasTrailingSlash === ($trimmedPathinfo === $pathinfo)) {
                if ($supportsRedirections && (!$requiredMethods || isset($requiredMethods['GET']))) {
                    return $allow = $allowSchemes = [];
                }
                continue;
            }
            $hasRequiredScheme = !$requiredSchemes || isset($requiredSchemes[$context->getScheme()]);
            if ($hasRequiredScheme && $requiredMethods && !isset($requiredMethods[$canonicalMethod]) && !isset($requiredMethods[$requestMethod])) {
                $allow += $requiredMethods;
                continue;
            }
            if (!$hasRequiredScheme) {
                $allowSchemes += $requiredSchemes;
                continue;
            }
            return $ret;
        }
        $matchedPathinfo = $this->matchHost ? $host . '.' . $pathinfo : $pathinfo;
        foreach ($this->regexpList as $offset => $regex) {
            while (preg_match($regex, $matchedPathinfo, $matches)) {
                foreach ($this->dynamicRoutes[$m = (int) $matches['MARK']] as [$ret, $vars, $requiredMethods, $requiredSchemes, $hasTrailingSlash, $hasTrailingVar, $condition]) {
                    if (0 === $condition) {
                        // marks the last route in the regexp
                        continue 3;
                    }
                    $hasTrailingVar = $trimmedPathinfo !== $pathinfo && $hasTrailingVar;
                    if ($hasTrailingVar && ($hasTrailingSlash || null === ($n = $matches[\count($vars)] ?? null) || '/' !== ($n[-1] ?? '/')) && preg_match($regex, $this->matchHost ? $host . '.' . $trimmedPathinfo : $trimmedPathinfo, $n) && $m === (int) $n['MARK']) {
                        if ($hasTrailingSlash) {
                            $matches = $n;
                        } else {
                            $hasTrailingVar = \false;
                        }
                    }
                    foreach ($vars as $i => $v) {
                        if (isset($matches[1 + $i])) {
                            $ret[$v] = $matches[1 + $i];
                        }
                    }
                    if ($condition && !($this->checkCondition)($condition, $context, 0 < $condition ? $request ??= $this->request ?: $this->createRequest($pathinfo) : null, $ret)) {
                        continue;
                    }
                    if ('/' !== $pathinfo && !$hasTrailingVar && $hasTrailingSlash === ($trimmedPathinfo === $pathinfo)) {
                        if ($supportsRedirections && (!$requiredMethods || isset($requiredMethods['GET']))) {
                            return $allow = $allowSchemes = [];
                        }
                        continue;
                    }
                    if ($requiredSchemes && !isset($requiredSchemes[$context->getScheme()])) {
                        $allowSchemes += $requiredSchemes;
                        continue;
                    }
                    if ($requiredMethods && !isset($requiredMethods[$canonicalMethod]) && !isset($requiredMethods[$requestMethod])) {
                        $allow += $requiredMethods;
                        continue;
                    }
                    return $ret;
                }
                $regex = substr_replace($regex, 'F', $m - $offset, 1 + \strlen($m));
                $offset += \strlen($m);
            }
        }
        if ('/' === $pathinfo && !$allow && !$allowSchemes) {
            throw new NoConfigurationException();
        }
        return [];
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Routing\Matcher\Dumper;

use _ContaoManager\Symfony\Component\Routing\RouteCollection;
/**
 * Prefix tree of routes preserving routes order.
 *
 * @author Frank de Jonge <info@frankdejonge.nl>
 * @author Nicolas Grekas <p@tchwork.com>
 *
 * @internal
 */
class StaticPrefixCollection
{
    private string $prefix;
    /**
     * @var string[]
     */
    private array $staticPrefixes = [];
    /**
     * @var string[]
     */
    private array $prefixes = [];
    /**
     * @var array[]|self[]
     */
    private array $items = [];
    public function __construct(string $prefix = '/')
    {
        $this->prefix = $prefix;
    }
    public function getPrefix(): string
    {
        return $this->prefix;
    }
    /**
     * @return array[]|self[]
     */
    public function getRoutes(): array
    {
        return $this->items;
    }
    /**
     * Adds a route to a group.
     */
    public function addRoute(string $prefix, array|self $route): void
    {
        [$prefix, $staticPrefix] = $this->getCommonPrefix($prefix, $prefix);
        for ($i = \count($this->items) - 1; 0 <= $i; --$i) {
            $item = $this->items[$i];
            [$commonPrefix, $commonStaticPrefix] = $this->getCommonPrefix($prefix, $this->prefixes[$i]);
            if ($this->prefix === $commonPrefix) {
                // the new route and a previous one have no common prefix, let's see if they are exclusive to each others
                if ($this->prefix !== $staticPrefix && $this->prefix !== $this->staticPrefixes[$i]) {
                    // the new route and the previous one have exclusive static prefixes
                    continue;
                }
                if ($this->prefix === $staticPrefix && $this->prefix === $this->staticPrefixes[$i]) {
                    // the new route and the previous one have no static prefix
                    break;
                }
                if ($this->prefixes[$i] !== $this->staticPrefixes[$i] && $this->prefix === $this->staticPrefixes[$i]) {
                    // the previous route is non-static and has no static prefix
                    break;
                }
                if ($prefix !== $staticPrefix && $this->prefix === $staticPrefix) {
                    // the new route is non-static and has no static prefix
                    break;
                }
                continue;
            }
            if ($item instanceof self && $this->prefixes[$i] === $commonPrefix) {
                // the new route is a child of a previous one, let's nest it
                $item->addRoute($prefix, $route);
            } else {
                // the new route and a previous one have a common prefix, let's merge them
                $child = new self($commonPrefix);
                [$child->prefixes[0], $child->staticPrefixes[0]] = $child->getCommonPrefix($this->prefixes[$i], $this->prefixes[$i]);
                [$child->prefixes[1], $child->staticPrefixes[1]] = $child->getCommonPrefix($prefix, $prefix);
                $child->items = [$this->items[$i], $route];
                $this->staticPrefixes[$i] = $commonStaticPrefix;
                $this->prefixes[$i] = $commonPrefix;
                $this->items[$i] = $child;
            }
            return;
        }
        // No optimised case was found, in this case we simple add the route for possible
        // grouping when new routes are added.
        $this->staticPrefixes[] = $staticPrefix;
        $this->prefixes[] = $prefix;
        $this->items[] = $route;
    }
    /**
     * Linearizes back a set of nested routes into a collection.
     */
    public function populateCollection(RouteCollection $routes): RouteCollection
    {
        foreach ($this->items as $route) {
            if ($route instanceof self) {
                $route->populateCollection($routes);
            } else {
                $routes->add(...$route);
            }
        }
        return $routes;
    }
    /**
     * Gets the full and static common prefixes between two route patterns.
     *
     * The static prefix stops at last at the first opening bracket.
     */
    private function getCommonPrefix(string $prefix, string $anotherPrefix): array
    {
        $baseLength = \strlen($this->prefix);
        $end = min(\strlen($prefix), \strlen($anotherPrefix));
        $staticLength = null;
        set_error_handler(self::handleError(...));
        try {
            for ($i = $baseLength; $i < $end && $prefix[$i] === $anotherPrefix[$i]; ++$i) {
                if ('(' === $prefix[$i]) {
                    $staticLength ??= $i;
                    for ($j = 1 + $i, $n = 1; $j < $end && 0 < $n; ++$j) {
                        if ($prefix[$j] !== $anotherPrefix[$j]) {
                            break 2;
                        }
                        if ('(' === $prefix[$j]) {
                            ++$n;
                        } elseif (')' === $prefix[$j]) {
                            --$n;
                        } elseif ('\\' === $prefix[$j] && (++$j === $end || $prefix[$j] !== $anotherPrefix[$j])) {
                            --$j;
                            break;
                        }
                    }
                    if (0 < $n) {
                        break;
                    }
                    if (('?' === ($prefix[$j] ?? '') || '?' === ($anotherPrefix[$j] ?? '')) && ($prefix[$j] ?? '') !== ($anotherPrefix[$j] ?? '')) {
                        break;
                    }
                    $subPattern = substr($prefix, $i, $j - $i);
                    if ($prefix !== $anotherPrefix && !preg_match('/^\(\[[^\]]++\]\+\+\)$/', $subPattern) && !preg_match('{(?<!' . $subPattern . ')}', '')) {
                        // sub-patterns of variable length are not considered as common prefixes because their greediness would break in-order matching
                        break;
                    }
                    $i = $j - 1;
                } elseif ('\\' === $prefix[$i] && (++$i === $end || $prefix[$i] !== $anotherPrefix[$i])) {
                    --$i;
                    break;
                }
            }
        } finally {
            restore_error_handler();
        }
        if ($i < $end && 0b10 === \ord($prefix[$i]) >> 6 && preg_match('//u', $prefix . ' ' . $anotherPrefix)) {
            do {
                // Prevent cutting in the middle of an UTF-8 characters
                --$i;
            } while (0b10 === \ord($prefix[$i]) >> 6);
        }
        return [substr($prefix, 0, $i), substr($prefix, 0, $staticLength ?? $i)];
    }
    public static function handleError(int $type, string $msg): bool
    {
        return str_contains($msg, 'Compilation failed: lookbehind assertion is not fixed length') || str_contains($msg, 'Compilation failed: length of lookbehind assertion is not limited');
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Routing\Matcher;

use _ContaoManager\Symfony\Component\Routing\Exception\ExceptionInterface;
use _ContaoManager\Symfony\Component\Routing\Exception\ResourceNotFoundException;
/**
 * @author Fabien Potencier <fabien@symfony.com>
 */
abstract class RedirectableUrlMatcher extends UrlMatcher implements RedirectableUrlMatcherInterface
{
    public function match(string $pathinfo): array
    {
        try {
            return parent::match($pathinfo);
        } catch (ResourceNotFoundException $e) {
            if (!\in_array($this->context->getMethod(), ['HEAD', 'GET'], \true)) {
                throw $e;
            }
            if ($this->allowSchemes) {
                redirect_scheme:
                $scheme = $this->context->getScheme();
                $this->context->setScheme(current($this->allowSchemes));
                try {
                    $ret = parent::match($pathinfo);
                    return $this->redirect($pathinfo, $ret['_route'] ?? null, $this->context->getScheme()) + $ret;
                } catch (ExceptionInterface) {
                    throw $e;
                } finally {
                    $this->context->setScheme($scheme);
                }
            } elseif ('' === $trimmedPathinfo = rtrim($pathinfo, '/')) {
                throw $e;
            } else {
                try {
                    $pathinfo = $trimmedPathinfo === $pathinfo ? $pathinfo . '/' : $trimmedPathinfo;
                    $ret = parent::match($pathinfo);
                    return $this->redirect($pathinfo, $ret['_route'] ?? null) + $ret;
                } catch (ExceptionInterface) {
                    if ($this->allowSchemes) {
                        goto redirect_scheme;
                    }
                    throw $e;
                }
            }
        }
    }
}
Routing Component
=================

The Routing component maps an HTTP request to a set of configuration variables.

Getting Started
---------------

```
$ composer require symfony/routing
```

```php
use App\Controller\BlogController;
use Symfony\Component\Routing\Generator\UrlGenerator;
use Symfony\Component\Routing\Matcher\UrlMatcher;
use Symfony\Component\Routing\RequestContext;
use Symfony\Component\Routing\Route;
use Symfony\Component\Routing\RouteCollection;

$route = new Route('/blog/{slug}', ['_controller' => BlogController::class]);
$routes = new RouteCollection();
$routes->add('blog_show', $route);

$context = new RequestContext();

// Routing can match routes with incoming requests
$matcher = new UrlMatcher($routes, $context);
$parameters = $matcher->match('/blog/lorem-ipsum');
// $parameters = [
//     '_controller' => 'App\Controller\BlogController',
//     'slug' => 'lorem-ipsum',
//     '_route' => 'blog_show'
// ]

// Routing can also generate URLs for a given route
$generator = new UrlGenerator($routes, $context);
$url = $generator->generate('blog_show', [
    'slug' => 'my-blog-post',
]);
// $url = '/blog/my-blog-post'
```

Sponsor
-------

The Routing component for Symfony 6.4 is [backed][1] by [redirection.io][2].

redirection.io logs all your website’s HTTP traffic, and lets you fix errors
with redirect rules in seconds. Give your marketing, SEO and IT teams the
right tool to manage your website traffic efficiently!

Help Symfony by [sponsoring][3] its development!

Resources
---------

 * [Documentation](https://symfony.com/doc/current/routing.html)
 * [Contributing](https://symfony.com/doc/current/contributing/index.html)
 * [Report issues](https://github.com/symfony/symfony/issues) and
   [send Pull Requests](https://github.com/symfony/symfony/pulls)
   in the [main Symfony repository](https://github.com/symfony/symfony)

[1]: https://symfony.com/backers
[2]: https://redirection.io
[3]: https://symfony.com/sponsor
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Routing\Generator;

use _ContaoManager\Psr\Log\LoggerInterface;
use _ContaoManager\Symfony\Component\Routing\Exception\RouteNotFoundException;
use _ContaoManager\Symfony\Component\Routing\RequestContext;
/**
 * Generates URLs based on rules dumped by CompiledUrlGeneratorDumper.
 */
class CompiledUrlGenerator extends UrlGenerator
{
    private array $compiledRoutes = [];
    private ?string $defaultLocale;
    public function __construct(array $compiledRoutes, RequestContext $context, ?LoggerInterface $logger = null, ?string $defaultLocale = null)
    {
        $this->compiledRoutes = $compiledRoutes;
        $this->context = $context;
        $this->logger = $logger;
        $this->defaultLocale = $defaultLocale;
    }
    public function generate(string $name, array $parameters = [], int $referenceType = self::ABSOLUTE_PATH): string
    {
        $locale = $parameters['_locale'] ?? $this->context->getParameter('_locale') ?: $this->defaultLocale;
        if (null !== $locale) {
            do {
                if (($this->compiledRoutes[$name . '.' . $locale][1]['_canonical_route'] ?? null) === $name) {
                    $name .= '.' . $locale;
                    break;
                }
            } while (\false !== $locale = strstr($locale, '_', \true));
        }
        if (!isset($this->compiledRoutes[$name])) {
            throw new RouteNotFoundException(\sprintf('Unable to generate a URL for the named route "%s" as such route does not exist.', $name));
        }
        [$variables, $defaults, $requirements, $tokens, $hostTokens, $requiredSchemes, $deprecations] = $this->compiledRoutes[$name] + [6 => []];
        foreach ($deprecations as $deprecation) {
            trigger_deprecation($deprecation['package'], $deprecation['version'], $deprecation['message']);
        }
        if (isset($defaults['_canonical_route']) && isset($defaults['_locale'])) {
            if (!\in_array('_locale', $variables, \true)) {
                unset($parameters['_locale']);
            } elseif (!isset($parameters['_locale'])) {
                $parameters['_locale'] = $defaults['_locale'];
            }
        }
        return $this->doGenerate($variables, $defaults, $requirements, $tokens, $parameters, $name, $referenceType, $hostTokens, $requiredSchemes);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Routing\Generator;

use _ContaoManager\Psr\Log\LoggerInterface;
use _ContaoManager\Symfony\Component\Routing\Exception\InvalidParameterException;
use _ContaoManager\Symfony\Component\Routing\Exception\MissingMandatoryParametersException;
use _ContaoManager\Symfony\Component\Routing\Exception\RouteNotFoundException;
use _ContaoManager\Symfony\Component\Routing\RequestContext;
use _ContaoManager\Symfony\Component\Routing\RouteCollection;
/**
 * UrlGenerator can generate a URL or a path for any route in the RouteCollection
 * based on the passed parameters.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 * @author Tobias Schultze <http://tobion.de>
 */
class UrlGenerator implements UrlGeneratorInterface, ConfigurableRequirementsInterface
{
    private const QUERY_FRAGMENT_DECODED = [
        // RFC 3986 explicitly allows those in the query/fragment to reference other URIs unencoded
        '%2F' => '/',
        '%252F' => '%2F',
        '%3F' => '?',
        // reserved chars that have no special meaning for HTTP URIs in a query or fragment
        // this excludes esp. "&", "=" and also "+" because PHP would treat it as a space (form-encoded)
        '%40' => '@',
        '%3A' => ':',
        '%21' => '!',
        '%3B' => ';',
        '%2C' => ',',
        '%2A' => '*',
    ];
    protected $routes;
    protected $context;
    /**
     * @var bool|null
     */
    protected $strictRequirements = \true;
    protected $logger;
    private ?string $defaultLocale;
    /**
     * This array defines the characters (besides alphanumeric ones) that will not be percent-encoded in the path segment of the generated URL.
     *
     * PHP's rawurlencode() encodes all chars except "a-zA-Z0-9-._~" according to RFC 3986. But we want to allow some chars
     * to be used in their literal form (reasons below). Other chars inside the path must of course be encoded, e.g.
     * "?" and "#" (would be interpreted wrongly as query and fragment identifier),
     * "'" and """ (are used as delimiters in HTML).
     */
    protected $decodedChars = [
        // the slash can be used to designate a hierarchical structure and we want allow using it with this meaning
        // some webservers don't allow the slash in encoded form in the path for security reasons anyway
        // see http://stackoverflow.com/questions/4069002/http-400-if-2f-part-of-get-url-in-jboss
        '%2F' => '/',
        '%252F' => '%2F',
        // the following chars are general delimiters in the URI specification but have only special meaning in the authority component
        // so they can safely be used in the path in unencoded form
        '%40' => '@',
        '%3A' => ':',
        // these chars are only sub-delimiters that have no predefined meaning and can therefore be used literally
        // so URI producing applications can use these chars to delimit subcomponents in a path segment without being encoded for better readability
        '%3B' => ';',
        '%2C' => ',',
        '%3D' => '=',
        '%2B' => '+',
        '%21' => '!',
        '%2A' => '*',
        '%7C' => '|',
    ];
    public function __construct(RouteCollection $routes, RequestContext $context, ?LoggerInterface $logger = null, ?string $defaultLocale = null)
    {
        $this->routes = $routes;
        $this->context = $context;
        $this->logger = $logger;
        $this->defaultLocale = $defaultLocale;
    }
    /**
     * @return void
     */
    public function setContext(RequestContext $context)
    {
        $this->context = $context;
    }
    public function getContext(): RequestContext
    {
        return $this->context;
    }
    /**
     * @return void
     */
    public function setStrictRequirements(?bool $enabled)
    {
        $this->strictRequirements = $enabled;
    }
    public function isStrictRequirements(): ?bool
    {
        return $this->strictRequirements;
    }
    public function generate(string $name, array $parameters = [], int $referenceType = self::ABSOLUTE_PATH): string
    {
        $route = null;
        $locale = $parameters['_locale'] ?? $this->context->getParameter('_locale') ?: $this->defaultLocale;
        if (null !== $locale) {
            do {
                if (null !== ($route = $this->routes->get($name . '.' . $locale)) && $route->getDefault('_canonical_route') === $name) {
                    break;
                }
            } while (\false !== $locale = strstr($locale, '_', \true));
        }
        if (null === $route ??= $this->routes->get($name)) {
            throw new RouteNotFoundException(\sprintf('Unable to generate a URL for the named route "%s" as such route does not exist.', $name));
        }
        // the Route has a cache of its own and is not recompiled as long as it does not get modified
        $compiledRoute = $route->compile();
        $defaults = $route->getDefaults();
        $variables = $compiledRoute->getVariables();
        if (isset($defaults['_canonical_route']) && isset($defaults['_locale'])) {
            if (!\in_array('_locale', $variables, \true)) {
                unset($parameters['_locale']);
            } elseif (!isset($parameters['_locale'])) {
                $parameters['_locale'] = $defaults['_locale'];
            }
        }
        return $this->doGenerate($variables, $defaults, $route->getRequirements(), $compiledRoute->getTokens(), $parameters, $name, $referenceType, $compiledRoute->getHostTokens(), $route->getSchemes());
    }
    /**
     * @throws MissingMandatoryParametersException When some parameters are missing that are mandatory for the route
     * @throws InvalidParameterException           When a parameter value for a placeholder is not correct because
     *                                             it does not match the requirement
     */
    protected function doGenerate(array $variables, array $defaults, array $requirements, array $tokens, array $parameters, string $name, int $referenceType, array $hostTokens, array $requiredSchemes = []): string
    {
        $variables = array_flip($variables);
        $mergedParams = array_replace($defaults, $this->context->getParameters(), $parameters);
        // all params must be given
        if ($diff = array_diff_key($variables, $mergedParams)) {
            throw new MissingMandatoryParametersException($name, array_keys($diff));
        }
        $url = '';
        $optional = \true;
        $message = 'Parameter "{parameter}" for route "{route}" must match "{expected}" ("{given}" given) to generate a corresponding URL.';
        foreach ($tokens as $token) {
            if ('variable' === $token[0]) {
                $varName = $token[3];
                // variable is not important by default
                $important = $token[5] ?? \false;
                if (!$optional || $important || !\array_key_exists($varName, $defaults) || null !== $mergedParams[$varName] && (string) $mergedParams[$varName] !== (string) $defaults[$varName]) {
                    // check requirement (while ignoring look-around patterns)
                    if (null !== $this->strictRequirements && !preg_match('#^' . preg_replace('/\(\?(?:=|<=|!|<!)((?:[^()\\\\]+|\\\\.|\((?1)\))*)\)/', '', $token[2]) . '$#i' . (empty($token[4]) ? '' : 'u'), $mergedParams[$token[3]] ?? '')) {
                        if ($this->strictRequirements) {
                            throw new InvalidParameterException(strtr($message, ['{parameter}' => $varName, '{route}' => $name, '{expected}' => $token[2], '{given}' => $mergedParams[$varName]]));
                        }
                        $this->logger?->error($message, ['parameter' => $varName, 'route' => $name, 'expected' => $token[2], 'given' => $mergedParams[$varName]]);
                        return '';
                    }
                    $url = $token[1] . $mergedParams[$varName] . $url;
                    $optional = \false;
                }
            } else {
                // static text
                $url = $token[1] . $url;
                $optional = \false;
            }
        }
        if ('' === $url) {
            $url = '/';
        }
        // the contexts base URL is already encoded (see Symfony\Component\HttpFoundation\Request)
        $url = strtr(rawurlencode($url), $this->decodedChars);
        // the path segments "." and ".." are interpreted as relative reference when resolving a URI; see http://tools.ietf.org/html/rfc3986#section-3.3
        // so we need to encode them as they are not used for this purpose here
        // otherwise we would generate a URI that, when followed by a user agent (e.g. browser), does not match this route
        $url = strtr($url, ['/../' => '/%2E%2E/', '/./' => '/%2E/']);
        if (str_ends_with($url, '/..')) {
            $url = substr($url, 0, -2) . '%2E%2E';
        } elseif (str_ends_with($url, '/.')) {
            $url = substr($url, 0, -1) . '%2E';
        }
        $schemeAuthority = '';
        $host = $this->context->getHost();
        $scheme = $this->context->getScheme();
        if ($requiredSchemes) {
            if (!\in_array($scheme, $requiredSchemes, \true)) {
                $referenceType = self::ABSOLUTE_URL;
                $scheme = current($requiredSchemes);
            }
        }
        if ($hostTokens) {
            $routeHost = '';
            foreach ($hostTokens as $token) {
                if ('variable' === $token[0]) {
                    // check requirement (while ignoring look-around patterns)
                    if (null !== $this->strictRequirements && !preg_match('#^' . preg_replace('/\(\?(?:=|<=|!|<!)((?:[^()\\\\]+|\\\\.|\((?1)\))*)\)/', '', $token[2]) . '$#i' . (empty($token[4]) ? '' : 'u'), $mergedParams[$token[3]])) {
                        if ($this->strictRequirements) {
                            throw new InvalidParameterException(strtr($message, ['{parameter}' => $token[3], '{route}' => $name, '{expected}' => $token[2], '{given}' => $mergedParams[$token[3]]]));
                        }
                        $this->logger?->error($message, ['parameter' => $token[3], 'route' => $name, 'expected' => $token[2], 'given' => $mergedParams[$token[3]]]);
                        return '';
                    }
                    $routeHost = $token[1] . $mergedParams[$token[3]] . $routeHost;
                } else {
                    $routeHost = $token[1] . $routeHost;
                }
            }
            if ($routeHost !== $host) {
                $host = $routeHost;
                if (self::ABSOLUTE_URL !== $referenceType) {
                    $referenceType = self::NETWORK_PATH;
                }
            }
        }
        if (self::ABSOLUTE_URL === $referenceType || self::NETWORK_PATH === $referenceType) {
            if ('' !== $host || '' !== $scheme && 'http' !== $scheme && 'https' !== $scheme) {
                $port = '';
                if ('http' === $scheme && 80 !== $this->context->getHttpPort()) {
                    $port = ':' . $this->context->getHttpPort();
                } elseif ('https' === $scheme && 443 !== $this->context->getHttpsPort()) {
                    $port = ':' . $this->context->getHttpsPort();
                }
                $schemeAuthority = self::NETWORK_PATH === $referenceType || '' === $scheme ? '//' : "{$scheme}://";
                $schemeAuthority .= $host . $port;
            }
        }
        if (self::RELATIVE_PATH === $referenceType) {
            $url = self::getRelativePath($this->context->getPathInfo(), $url);
        } else {
            $url = $schemeAuthority . $this->context->getBaseUrl() . $url;
        }
        // add a query string if needed
        $extra = array_udiff_assoc(array_diff_key($parameters, $variables), $defaults, fn($a, $b) => $a == $b ? 0 : 1);
        array_walk_recursive($extra, $caster = static function (&$v) use (&$caster) {
            if (\is_object($v)) {
                if ($vars = get_object_vars($v)) {
                    array_walk_recursive($vars, $caster);
                    $v = $vars;
                } elseif (method_exists($v, '__toString')) {
                    $v = (string) $v;
                }
            }
        });
        // extract fragment
        $fragment = $defaults['_fragment'] ?? '';
        if (isset($extra['_fragment'])) {
            $fragment = $extra['_fragment'];
            unset($extra['_fragment']);
        }
        if ($extra && $query = http_build_query($extra, '', '&', \PHP_QUERY_RFC3986)) {
            $url .= '?' . strtr($query, self::QUERY_FRAGMENT_DECODED);
        }
        if ('' !== $fragment) {
            $url .= '#' . strtr(rawurlencode($fragment), self::QUERY_FRAGMENT_DECODED);
        }
        return $url;
    }
    /**
     * Returns the target path as relative reference from the base path.
     *
     * Only the URIs path component (no schema, host etc.) is relevant and must be given, starting with a slash.
     * Both paths must be absolute and not contain relative parts.
     * Relative URLs from one resource to another are useful when generating self-contained downloadable document archives.
     * Furthermore, they can be used to reduce the link size in documents.
     *
     * Example target paths, given a base path of "/a/b/c/d":
     * - "/a/b/c/d"     -> ""
     * - "/a/b/c/"      -> "./"
     * - "/a/b/"        -> "../"
     * - "/a/b/c/other" -> "other"
     * - "/a/x/y"       -> "../../x/y"
     *
     * @param string $basePath   The base path
     * @param string $targetPath The target path
     */
    public static function getRelativePath(string $basePath, string $targetPath): string
    {
        if ($basePath === $targetPath) {
            return '';
        }
        $sourceDirs = explode('/', isset($basePath[0]) && '/' === $basePath[0] ? substr($basePath, 1) : $basePath);
        $targetDirs = explode('/', isset($targetPath[0]) && '/' === $targetPath[0] ? substr($targetPath, 1) : $targetPath);
        array_pop($sourceDirs);
        $targetFile = array_pop($targetDirs);
        foreach ($sourceDirs as $i => $dir) {
            if (isset($targetDirs[$i]) && $dir === $targetDirs[$i]) {
                unset($sourceDirs[$i], $targetDirs[$i]);
            } else {
                break;
            }
        }
        $targetDirs[] = $targetFile;
        $path = str_repeat('../', \count($sourceDirs)) . implode('/', $targetDirs);
        // A reference to the same base directory or an empty subdirectory must be prefixed with "./".
        // This also applies to a segment with a colon character (e.g., "file:colon") that cannot be used
        // as the first segment of a relative-path reference, as it would be mistaken for a scheme name
        // (see http://tools.ietf.org/html/rfc3986#section-4.2).
        return '' === $path || '/' === $path[0] || \false !== ($colonPos = strpos($path, ':')) && ($colonPos < ($slashPos = strpos($path, '/')) || \false === $slashPos) ? "./{$path}" : $path;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Routing\Generator;

/**
 * ConfigurableRequirementsInterface must be implemented by URL generators that
 * can be configured whether an exception should be generated when the parameters
 * do not match the requirements. It is also possible to disable the requirements
 * check for URL generation completely.
 *
 * The possible configurations and use-cases:
 * - setStrictRequirements(true): Throw an exception for mismatching requirements. This
 *   is mostly useful in development environment.
 * - setStrictRequirements(false): Don't throw an exception but return an empty string as URL for
 *   mismatching requirements and log the problem. Useful when you cannot control all
 *   params because they come from third party libs but don't want to have a 404 in
 *   production environment. It should log the mismatch so one can review it.
 * - setStrictRequirements(null): Return the URL with the given parameters without
 *   checking the requirements at all. When generating a URL you should either trust
 *   your params or you validated them beforehand because otherwise it would break your
 *   link anyway. So in production environment you should know that params always pass
 *   the requirements. Thus this option allows to disable the check on URL generation for
 *   performance reasons (saving a preg_match for each requirement every time a URL is
 *   generated).
 *
 * @author Fabien Potencier <fabien@symfony.com>
 * @author Tobias Schultze <http://tobion.de>
 */
interface ConfigurableRequirementsInterface
{
    /**
     * Enables or disables the exception on incorrect parameters.
     * Passing null will deactivate the requirements check completely.
     *
     * @return void
     */
    public function setStrictRequirements(?bool $enabled);
    /**
     * Returns whether to throw an exception on incorrect parameters.
     * Null means the requirements check is deactivated completely.
     */
    public function isStrictRequirements(): ?bool;
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Routing\Generator;

use _ContaoManager\Symfony\Component\Routing\Exception\InvalidParameterException;
use _ContaoManager\Symfony\Component\Routing\Exception\MissingMandatoryParametersException;
use _ContaoManager\Symfony\Component\Routing\Exception\RouteNotFoundException;
use _ContaoManager\Symfony\Component\Routing\RequestContextAwareInterface;
/**
 * UrlGeneratorInterface is the interface that all URL generator classes must implement.
 *
 * The constants in this interface define the different types of resource references that
 * are declared in RFC 3986: http://tools.ietf.org/html/rfc3986
 * We are using the term "URL" instead of "URI" as this is more common in web applications
 * and we do not need to distinguish them as the difference is mostly semantical and
 * less technical. Generating URIs, i.e. representation-independent resource identifiers,
 * is also possible.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 * @author Tobias Schultze <http://tobion.de>
 */
interface UrlGeneratorInterface extends RequestContextAwareInterface
{
    /**
     * Generates an absolute URL, e.g. "http://example.com/dir/file".
     */
    public const ABSOLUTE_URL = 0;
    /**
     * Generates an absolute path, e.g. "/dir/file".
     */
    public const ABSOLUTE_PATH = 1;
    /**
     * Generates a relative path based on the current request path, e.g. "../parent-file".
     *
     * @see UrlGenerator::getRelativePath()
     */
    public const RELATIVE_PATH = 2;
    /**
     * Generates a network path, e.g. "//example.com/dir/file".
     * Such reference reuses the current scheme but specifies the host.
     */
    public const NETWORK_PATH = 3;
    /**
     * Generates a URL or path for a specific route based on the given parameters.
     *
     * Parameters that reference placeholders in the route pattern will substitute them in the
     * path or host. Extra params are added as query string to the URL.
     *
     * When the passed reference type cannot be generated for the route because it requires a different
     * host or scheme than the current one, the method will return a more comprehensive reference
     * that includes the required params. For example, when you call this method with $referenceType = ABSOLUTE_PATH
     * but the route requires the https scheme whereas the current scheme is http, it will instead return an
     * ABSOLUTE_URL with the https scheme and the current host. This makes sure the generated URL matches
     * the route in any case.
     *
     * If there is no route with the given name, the generator must throw the RouteNotFoundException.
     *
     * The special parameter _fragment will be used as the document fragment suffixed to the final URL.
     *
     * @throws RouteNotFoundException              If the named route doesn't exist
     * @throws MissingMandatoryParametersException When some parameters are missing that are mandatory for the route
     * @throws InvalidParameterException           When a parameter value for a placeholder is not correct because
     *                                             it does not match the requirement
     */
    public function generate(string $name, array $parameters = [], int $referenceType = self::ABSOLUTE_PATH): string;
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Routing\Generator\Dumper;

use _ContaoManager\Symfony\Component\Routing\RouteCollection;
/**
 * GeneratorDumperInterface is the interface that all generator dumper classes must implement.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
interface GeneratorDumperInterface
{
    /**
     * Dumps a set of routes to a string representation of executable code
     * that can then be used to generate a URL of such a route.
     */
    public function dump(array $options = []): string;
    /**
     * Gets the routes to dump.
     */
    public function getRoutes(): RouteCollection;
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Routing\Generator\Dumper;

use _ContaoManager\Symfony\Component\Routing\Exception\RouteCircularReferenceException;
use _ContaoManager\Symfony\Component\Routing\Exception\RouteNotFoundException;
use _ContaoManager\Symfony\Component\Routing\Matcher\Dumper\CompiledUrlMatcherDumper;
/**
 * CompiledUrlGeneratorDumper creates a PHP array to be used with CompiledUrlGenerator.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 * @author Tobias Schultze <http://tobion.de>
 * @author Nicolas Grekas <p@tchwork.com>
 */
class CompiledUrlGeneratorDumper extends GeneratorDumper
{
    public function getCompiledRoutes(): array
    {
        $compiledRoutes = [];
        foreach ($this->getRoutes()->all() as $name => $route) {
            $compiledRoute = $route->compile();
            $compiledRoutes[$name] = [$compiledRoute->getVariables(), $route->getDefaults(), $route->getRequirements(), $compiledRoute->getTokens(), $compiledRoute->getHostTokens(), $route->getSchemes(), []];
        }
        return $compiledRoutes;
    }
    public function getCompiledAliases(): array
    {
        $routes = $this->getRoutes();
        $compiledAliases = [];
        foreach ($routes->getAliases() as $name => $alias) {
            $deprecations = $alias->isDeprecated() ? [$alias->getDeprecation($name)] : [];
            $currentId = $alias->getId();
            $visited = [];
            while (null !== $alias = $routes->getAlias($currentId) ?? null) {
                if (\false !== $searchKey = array_search($currentId, $visited)) {
                    $visited[] = $currentId;
                    throw new RouteCircularReferenceException($currentId, \array_slice($visited, $searchKey));
                }
                if ($alias->isDeprecated()) {
                    $deprecations[] = $deprecation = $alias->getDeprecation($currentId);
                    trigger_deprecation($deprecation['package'], $deprecation['version'], $deprecation['message']);
                }
                $visited[] = $currentId;
                $currentId = $alias->getId();
            }
            if (null === $target = $routes->get($currentId)) {
                throw new RouteNotFoundException(\sprintf('Target route "%s" for alias "%s" does not exist.', $currentId, $name));
            }
            $compiledTarget = $target->compile();
            $compiledAliases[$name] = [$compiledTarget->getVariables(), $target->getDefaults(), $target->getRequirements(), $compiledTarget->getTokens(), $compiledTarget->getHostTokens(), $target->getSchemes(), $deprecations];
        }
        return $compiledAliases;
    }
    public function dump(array $options = []): string
    {
        return <<<EOF
<?php

// This file has been auto-generated by the Symfony Routing Component.

return [{$this->generateDeclaredRoutes()}
];

EOF;
    }
    /**
     * Generates PHP code representing an array of defined routes
     * together with the routes properties (e.g. requirements).
     */
    private function generateDeclaredRoutes(): string
    {
        $routes = '';
        foreach ($this->getCompiledRoutes() as $name => $properties) {
            $routes .= \sprintf("\n    '%s' => %s,", $name, CompiledUrlMatcherDumper::export($properties));
        }
        foreach ($this->getCompiledAliases() as $alias => $properties) {
            $routes .= \sprintf("\n    '%s' => %s,", $alias, CompiledUrlMatcherDumper::export($properties));
        }
        return $routes;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Routing\Generator\Dumper;

use _ContaoManager\Symfony\Component\Routing\RouteCollection;
/**
 * GeneratorDumper is the base class for all built-in generator dumpers.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
abstract class GeneratorDumper implements GeneratorDumperInterface
{
    private RouteCollection $routes;
    public function __construct(RouteCollection $routes)
    {
        $this->routes = $routes;
    }
    public function getRoutes(): RouteCollection
    {
        return $this->routes;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Routing;

use _ContaoManager\Symfony\Component\Config\Resource\ResourceInterface;
use _ContaoManager\Symfony\Component\Routing\Exception\InvalidArgumentException;
use _ContaoManager\Symfony\Component\Routing\Exception\RouteCircularReferenceException;
/**
 * A RouteCollection represents a set of Route instances.
 *
 * When adding a route at the end of the collection, an existing route
 * with the same name is removed first. So there can only be one route
 * with a given name.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 * @author Tobias Schultze <http://tobion.de>
 *
 * @implements \IteratorAggregate<string, Route>
 */
class RouteCollection implements \IteratorAggregate, \Countable
{
    /**
     * @var array<string, Route>
     */
    private array $routes = [];
    /**
     * @var array<string, Alias>
     */
    private array $aliases = [];
    /**
     * @var array<string, ResourceInterface>
     */
    private array $resources = [];
    /**
     * @var array<string, int>
     */
    private array $priorities = [];
    public function __clone()
    {
        foreach ($this->routes as $name => $route) {
            $this->routes[$name] = clone $route;
        }
        foreach ($this->aliases as $name => $alias) {
            $this->aliases[$name] = clone $alias;
        }
    }
    /**
     * Gets the current RouteCollection as an Iterator that includes all routes.
     *
     * It implements \IteratorAggregate.
     *
     * @see all()
     *
     * @return \ArrayIterator<string, Route>
     */
    public function getIterator(): \ArrayIterator
    {
        return new \ArrayIterator($this->all());
    }
    /**
     * Gets the number of Routes in this collection.
     */
    public function count(): int
    {
        return \count($this->routes);
    }
    /**
     * @return void
     */
    public function add(string $name, Route $route, int $priority = 0)
    {
        unset($this->routes[$name], $this->priorities[$name], $this->aliases[$name]);
        $this->routes[$name] = $route;
        if ($priority) {
            $this->priorities[$name] = $priority;
        }
    }
    /**
     * Returns all routes in this collection.
     *
     * @return array<string, Route>
     */
    public function all(): array
    {
        if ($this->priorities) {
            $priorities = $this->priorities;
            $keysOrder = array_flip(array_keys($this->routes));
            uksort($this->routes, static fn($n1, $n2) => ($priorities[$n2] ?? 0) <=> ($priorities[$n1] ?? 0) ?: $keysOrder[$n1] <=> $keysOrder[$n2]);
        }
        return $this->routes;
    }
    /**
     * Gets a route by name.
     */
    public function get(string $name): ?Route
    {
        $visited = [];
        while (null !== $alias = $this->aliases[$name] ?? null) {
            if (\false !== $searchKey = array_search($name, $visited)) {
                $visited[] = $name;
                throw new RouteCircularReferenceException($name, \array_slice($visited, $searchKey));
            }
            if ($alias->isDeprecated()) {
                $deprecation = $alias->getDeprecation($name);
                trigger_deprecation($deprecation['package'], $deprecation['version'], $deprecation['message']);
            }
            $visited[] = $name;
            $name = $alias->getId();
        }
        return $this->routes[$name] ?? null;
    }
    /**
     * Removes a route or an array of routes by name from the collection.
     *
     * @param string|string[] $name The route name or an array of route names
     *
     * @return void
     */
    public function remove(string|array $name)
    {
        $routes = [];
        foreach ((array) $name as $n) {
            if (isset($this->routes[$n])) {
                $routes[] = $n;
            }
            unset($this->routes[$n], $this->priorities[$n], $this->aliases[$n]);
        }
        if (!$routes) {
            return;
        }
        foreach ($this->aliases as $k => $alias) {
            if (\in_array($alias->getId(), $routes, \true)) {
                unset($this->aliases[$k]);
            }
        }
    }
    /**
     * Adds a route collection at the end of the current set by appending all
     * routes of the added collection.
     *
     * @return void
     */
    public function addCollection(self $collection)
    {
        // we need to remove all routes with the same names first because just replacing them
        // would not place the new route at the end of the merged array
        foreach ($collection->all() as $name => $route) {
            unset($this->routes[$name], $this->priorities[$name], $this->aliases[$name]);
            $this->routes[$name] = $route;
            if (isset($collection->priorities[$name])) {
                $this->priorities[$name] = $collection->priorities[$name];
            }
        }
        foreach ($collection->getAliases() as $name => $alias) {
            unset($this->routes[$name], $this->priorities[$name], $this->aliases[$name]);
            $this->aliases[$name] = $alias;
        }
        foreach ($collection->getResources() as $resource) {
            $this->addResource($resource);
        }
    }
    /**
     * Adds a prefix to the path of all child routes.
     *
     * @return void
     */
    public function addPrefix(string $prefix, array $defaults = [], array $requirements = [])
    {
        $prefix = trim(trim($prefix), '/');
        if ('' === $prefix) {
            return;
        }
        foreach ($this->routes as $route) {
            $route->setPath('/' . $prefix . $route->getPath());
            $route->addDefaults($defaults);
            $route->addRequirements($requirements);
        }
    }
    /**
     * Adds a prefix to the name of all the routes within in the collection.
     *
     * @return void
     */
    public function addNamePrefix(string $prefix)
    {
        $prefixedRoutes = [];
        $prefixedPriorities = [];
        $prefixedAliases = [];
        foreach ($this->routes as $name => $route) {
            $prefixedRoutes[$prefix . $name] = $route;
            if (null !== $canonicalName = $route->getDefault('_canonical_route')) {
                $route->setDefault('_canonical_route', $prefix . $canonicalName);
            }
            if (isset($this->priorities[$name])) {
                $prefixedPriorities[$prefix . $name] = $this->priorities[$name];
            }
        }
        foreach ($this->aliases as $name => $alias) {
            $targetId = $alias->getId();
            if (isset($this->routes[$targetId]) || isset($this->aliases[$targetId])) {
                $targetId = $prefix . $targetId;
            }
            $prefixedAliases[$prefix . $name] = $alias->withId($targetId);
        }
        $this->routes = $prefixedRoutes;
        $this->priorities = $prefixedPriorities;
        $this->aliases = $prefixedAliases;
    }
    /**
     * Sets the host pattern on all routes.
     *
     * @return void
     */
    public function setHost(?string $pattern, array $defaults = [], array $requirements = [])
    {
        foreach ($this->routes as $route) {
            $route->setHost($pattern);
            $route->addDefaults($defaults);
            $route->addRequirements($requirements);
        }
    }
    /**
     * Sets a condition on all routes.
     *
     * Existing conditions will be overridden.
     *
     * @return void
     */
    public function setCondition(?string $condition)
    {
        foreach ($this->routes as $route) {
            $route->setCondition($condition);
        }
    }
    /**
     * Adds defaults to all routes.
     *
     * An existing default value under the same name in a route will be overridden.
     *
     * @return void
     */
    public function addDefaults(array $defaults)
    {
        if ($defaults) {
            foreach ($this->routes as $route) {
                $route->addDefaults($defaults);
            }
        }
    }
    /**
     * Adds requirements to all routes.
     *
     * An existing requirement under the same name in a route will be overridden.
     *
     * @return void
     */
    public function addRequirements(array $requirements)
    {
        if ($requirements) {
            foreach ($this->routes as $route) {
                $route->addRequirements($requirements);
            }
        }
    }
    /**
     * Adds options to all routes.
     *
     * An existing option value under the same name in a route will be overridden.
     *
     * @return void
     */
    public function addOptions(array $options)
    {
        if ($options) {
            foreach ($this->routes as $route) {
                $route->addOptions($options);
            }
        }
    }
    /**
     * Sets the schemes (e.g. 'https') all child routes are restricted to.
     *
     * @param string|string[] $schemes The scheme or an array of schemes
     *
     * @return void
     */
    public function setSchemes(string|array $schemes)
    {
        foreach ($this->routes as $route) {
            $route->setSchemes($schemes);
        }
    }
    /**
     * Sets the HTTP methods (e.g. 'POST') all child routes are restricted to.
     *
     * @param string|string[] $methods The method or an array of methods
     *
     * @return void
     */
    public function setMethods(string|array $methods)
    {
        foreach ($this->routes as $route) {
            $route->setMethods($methods);
        }
    }
    /**
     * Returns an array of resources loaded to build this collection.
     *
     * @return ResourceInterface[]
     */
    public function getResources(): array
    {
        return array_values($this->resources);
    }
    /**
     * Adds a resource for this collection. If the resource already exists
     * it is not added.
     *
     * @return void
     */
    public function addResource(ResourceInterface $resource)
    {
        $key = (string) $resource;
        if (!isset($this->resources[$key])) {
            $this->resources[$key] = $resource;
        }
    }
    /**
     * Sets an alias for an existing route.
     *
     * @param string $name  The alias to create
     * @param string $alias The route to alias
     *
     * @throws InvalidArgumentException if the alias is for itself
     */
    public function addAlias(string $name, string $alias): Alias
    {
        if ($name === $alias) {
            throw new InvalidArgumentException(\sprintf('Route alias "%s" can not reference itself.', $name));
        }
        unset($this->routes[$name], $this->priorities[$name]);
        return $this->aliases[$name] = new Alias($alias);
    }
    /**
     * @return array<string, Alias>
     */
    public function getAliases(): array
    {
        return $this->aliases;
    }
    public function getAlias(string $name): ?Alias
    {
        return $this->aliases[$name] ?? null;
    }
    public function getPriority(string $name): ?int
    {
        return $this->priorities[$name] ?? null;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Routing\Requirement;

use _ContaoManager\Symfony\Component\Routing\Exception\InvalidArgumentException;
final class EnumRequirement implements \Stringable
{
    private string $requirement;
    /**
     * @template T of \BackedEnum
     *
     * @param class-string<T>|list<T> $cases
     */
    public function __construct(string|array $cases = [])
    {
        if (\is_string($cases)) {
            if (!is_subclass_of($cases, \BackedEnum::class, \true)) {
                throw new InvalidArgumentException(\sprintf('"%s" is not a "BackedEnum" class.', $cases));
            }
            $cases = $cases::cases();
        } else {
            $class = null;
            foreach ($cases as $case) {
                if (!$case instanceof \BackedEnum) {
                    throw new InvalidArgumentException(\sprintf('Case must be a "BackedEnum" instance, "%s" given.', get_debug_type($case)));
                }
                $class ??= $case::class;
                if (!$case instanceof $class) {
                    throw new InvalidArgumentException(\sprintf('"%s::%s" is not a case of "%s".', get_debug_type($case), $case->name, $class));
                }
            }
        }
        $this->requirement = implode('|', array_map(static fn($e) => preg_quote($e->value), $cases));
    }
    public function __toString(): string
    {
        return $this->requirement;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Routing\Requirement;

/*
 * A collection of universal regular-expression constants to use as route parameter requirements.
 */
enum Requirement
{
    public const ASCII_SLUG = '[A-Za-z0-9]+(?:-[A-Za-z0-9]+)*';
    // symfony/string AsciiSlugger default implementation
    public const CATCH_ALL = '.+';
    public const DATE_YMD = '[0-9]{4}-(?:0[1-9]|1[012])-(?:0[1-9]|[12][0-9]|(?<!02-)3[01])';
    // YYYY-MM-DD
    public const DIGITS = '[0-9]+';
    public const POSITIVE_INT = '[1-9][0-9]*';
    public const UID_BASE32 = '[0-9A-HJKMNP-TV-Z]{26}';
    public const UID_BASE58 = '[1-9A-HJ-NP-Za-km-z]{22}';
    public const UID_RFC4122 = '[0-9a-f]{8}(?:-[0-9a-f]{4}){3}-[0-9a-f]{12}';
    // RFC 9562 obsoleted RFC 4122 but the format is the same
    public const ULID = '[0-7][0-9A-HJKMNP-TV-Z]{25}';
    public const UUID = '[0-9a-f]{8}-[0-9a-f]{4}-[13-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}';
    public const UUID_V1 = '[0-9a-f]{8}-[0-9a-f]{4}-1[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}';
    public const UUID_V3 = '[0-9a-f]{8}-[0-9a-f]{4}-3[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}';
    public const UUID_V4 = '[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}';
    public const UUID_V5 = '[0-9a-f]{8}-[0-9a-f]{4}-5[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}';
    public const UUID_V6 = '[0-9a-f]{8}-[0-9a-f]{4}-6[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}';
    public const UUID_V7 = '[0-9a-f]{8}-[0-9a-f]{4}-7[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}';
    public const UUID_V8 = '[0-9a-f]{8}-[0-9a-f]{4}-8[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}';
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Routing;

interface RequestContextAwareInterface
{
    /**
     * Sets the request context.
     *
     * @return void
     */
    public function setContext(RequestContext $context);
    /**
     * Gets the request context.
     */
    public function getContext(): RequestContext;
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Routing\Loader;

trigger_deprecation('symfony/routing', '6.4', 'The "%s" class is deprecated, use "%s" instead.', AnnotationClassLoader::class, AttributeClassLoader::class);
class_exists(AttributeClassLoader::class);
if (\false) {
    /**
     * @deprecated since Symfony 6.4, to be removed in 7.0, use {@link AttributeClassLoader} instead
     */
    abstract class AnnotationClassLoader extends AttributeClassLoader
    {
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Routing\Loader;

use _ContaoManager\Symfony\Component\Config\Resource\DirectoryResource;
use _ContaoManager\Symfony\Component\Routing\RouteCollection;
/**
 * AttributeDirectoryLoader loads routing information from attributes set
 * on PHP classes and methods.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 * @author Alexandre Daubois <alex.daubois@gmail.com>
 */
class AttributeDirectoryLoader extends AttributeFileLoader
{
    /**
     * @throws \InvalidArgumentException When the directory does not exist or its routes cannot be parsed
     */
    public function load(mixed $path, ?string $type = null): ?RouteCollection
    {
        if (!is_dir($dir = $this->locator->locate($path))) {
            return parent::supports($path, $type) ? parent::load($path, $type) : new RouteCollection();
        }
        $collection = new RouteCollection();
        $collection->addResource(new DirectoryResource($dir, '/\.php$/'));
        $files = iterator_to_array(new \RecursiveIteratorIterator(new \RecursiveCallbackFilterIterator(new \RecursiveDirectoryIterator($dir, \FilesystemIterator::SKIP_DOTS | \FilesystemIterator::FOLLOW_SYMLINKS), fn(\SplFileInfo $current) => !str_starts_with($current->getBasename(), '.')), \RecursiveIteratorIterator::LEAVES_ONLY));
        usort($files, fn(\SplFileInfo $a, \SplFileInfo $b) => (string) $a > (string) $b ? 1 : -1);
        foreach ($files as $file) {
            if (!$file->isFile() || !str_ends_with($file->getFilename(), '.php')) {
                continue;
            }
            if ($class = $this->findClass($file)) {
                $refl = new \ReflectionClass($class);
                if ($refl->isAbstract()) {
                    continue;
                }
                $collection->addCollection($this->loader->load($class, $type));
            }
        }
        return $collection;
    }
    public function supports(mixed $resource, ?string $type = null): bool
    {
        if (!\is_string($resource)) {
            return \false;
        }
        if (\in_array($type, ['annotation', 'attribute'], \true)) {
            if ('annotation' === $type) {
                trigger_deprecation('symfony/routing', '6.4', 'The "annotation" route type is deprecated, use the "attribute" route type instead.');
            }
            return \true;
        }
        if ($type) {
            return \false;
        }
        try {
            return is_dir($this->locator->locate($resource));
        } catch (\Exception) {
            return \false;
        }
    }
}
if (!class_exists(AnnotationDirectoryLoader::class, \false)) {
    class_alias(AttributeDirectoryLoader::class, AnnotationDirectoryLoader::class);
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Routing\Loader;

use _ContaoManager\Symfony\Component\Config\FileLocatorInterface;
use _ContaoManager\Symfony\Component\Config\Loader\FileLoader;
use _ContaoManager\Symfony\Component\Config\Resource\FileResource;
use _ContaoManager\Symfony\Component\Routing\RouteCollection;
/**
 * AttributeFileLoader loads routing information from attributes set
 * on a PHP class and its methods.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 * @author Alexandre Daubois <alex.daubois@gmail.com>
 */
class AttributeFileLoader extends FileLoader
{
    protected $loader;
    public function __construct(FileLocatorInterface $locator, AttributeClassLoader $loader)
    {
        if (!\function_exists('token_get_all') && !\function_exists('_ContaoManager\token_get_all')) {
            throw new \LogicException('The Tokenizer extension is required for the routing attribute loader.');
        }
        parent::__construct($locator);
        $this->loader = $loader;
    }
    /**
     * Loads from attributes from a file.
     *
     * @throws \InvalidArgumentException When the file does not exist or its routes cannot be parsed
     */
    public function load(mixed $file, ?string $type = null): ?RouteCollection
    {
        $path = $this->locator->locate($file);
        $collection = new RouteCollection();
        if ($class = $this->findClass($path)) {
            $refl = new \ReflectionClass($class);
            if ($refl->isAbstract()) {
                return null;
            }
            $collection->addResource(new FileResource($path));
            $collection->addCollection($this->loader->load($class, $type));
        }
        gc_mem_caches();
        return $collection;
    }
    public function supports(mixed $resource, ?string $type = null): bool
    {
        if ('annotation' === $type) {
            trigger_deprecation('symfony/routing', '6.4', 'The "annotation" route type is deprecated, use the "attribute" route type instead.');
        }
        return \is_string($resource) && 'php' === pathinfo($resource, \PATHINFO_EXTENSION) && (!$type || \in_array($type, ['annotation', 'attribute'], \true));
    }
    /**
     * Returns the full class name for the first class in the file.
     */
    protected function findClass(string $file): string|false
    {
        $class = \false;
        $namespace = \false;
        $tokens = token_get_all(file_get_contents($file));
        if (1 === \count($tokens) && \T_INLINE_HTML === $tokens[0][0]) {
            throw new \InvalidArgumentException(\sprintf('The file "%s" does not contain PHP code. Did you forget to add the "<?php" start tag at the beginning of the file?', $file));
        }
        $nsTokens = [\T_NS_SEPARATOR => \true, \T_STRING => \true];
        if (\defined('T_NAME_QUALIFIED')) {
            $nsTokens[\T_NAME_QUALIFIED] = \true;
        }
        for ($i = 0; isset($tokens[$i]); ++$i) {
            $token = $tokens[$i];
            if (!isset($token[1])) {
                continue;
            }
            if (\true === $class && \T_STRING === $token[0]) {
                return $namespace . '\\' . $token[1];
            }
            if (\true === $namespace && isset($nsTokens[$token[0]])) {
                $namespace = $token[1];
                while (isset($tokens[++$i][1], $nsTokens[$tokens[$i][0]])) {
                    $namespace .= $tokens[$i][1];
                }
                $token = $tokens[$i];
            }
            if (\T_CLASS === $token[0]) {
                // Skip usage of ::class constant and anonymous classes
                $skipClassToken = \false;
                for ($j = $i - 1; $j > 0; --$j) {
                    if (!isset($tokens[$j][1])) {
                        if ('(' === $tokens[$j] || ',' === $tokens[$j]) {
                            $skipClassToken = \true;
                        }
                        break;
                    }
                    if (\T_DOUBLE_COLON === $tokens[$j][0] || \T_NEW === $tokens[$j][0]) {
                        $skipClassToken = \true;
                        break;
                    } elseif (!\in_array($tokens[$j][0], [\T_WHITESPACE, \T_DOC_COMMENT, \T_COMMENT])) {
                        break;
                    }
                }
                if (!$skipClassToken) {
                    $class = \true;
                }
            }
            if (\T_NAMESPACE === $token[0]) {
                $namespace = \true;
            }
        }
        return \false;
    }
}
if (!class_exists(AnnotationFileLoader::class, \false)) {
    class_alias(AttributeFileLoader::class, AnnotationFileLoader::class);
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Routing\Loader;

use _ContaoManager\Symfony\Component\Config\Loader\FileLoader;
use _ContaoManager\Symfony\Component\Config\Resource\FileResource;
use _ContaoManager\Symfony\Component\Routing\Loader\Configurator\Traits\HostTrait;
use _ContaoManager\Symfony\Component\Routing\Loader\Configurator\Traits\LocalizedRouteTrait;
use _ContaoManager\Symfony\Component\Routing\Loader\Configurator\Traits\PrefixTrait;
use _ContaoManager\Symfony\Component\Routing\RouteCollection;
use _ContaoManager\Symfony\Component\Yaml\Exception\ParseException;
use _ContaoManager\Symfony\Component\Yaml\Parser as YamlParser;
use _ContaoManager\Symfony\Component\Yaml\Yaml;
/**
 * YamlFileLoader loads Yaml routing files.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 * @author Tobias Schultze <http://tobion.de>
 */
class YamlFileLoader extends FileLoader
{
    use HostTrait;
    use LocalizedRouteTrait;
    use PrefixTrait;
    private const AVAILABLE_KEYS = ['resource', 'type', 'prefix', 'path', 'host', 'schemes', 'methods', 'defaults', 'requirements', 'options', 'condition', 'controller', 'name_prefix', 'trailing_slash_on_root', 'locale', 'format', 'utf8', 'exclude', 'stateless'];
    private YamlParser $yamlParser;
    /**
     * @throws \InvalidArgumentException When a route can't be parsed because YAML is invalid
     */
    public function load(mixed $file, ?string $type = null): RouteCollection
    {
        $path = $this->locator->locate($file);
        if (!stream_is_local($path)) {
            throw new \InvalidArgumentException(\sprintf('This is not a local file "%s".', $path));
        }
        if (!file_exists($path)) {
            throw new \InvalidArgumentException(\sprintf('File "%s" not found.', $path));
        }
        $this->yamlParser ??= new YamlParser();
        try {
            $parsedConfig = $this->yamlParser->parseFile($path, Yaml::PARSE_CONSTANT);
        } catch (ParseException $e) {
            throw new \InvalidArgumentException(\sprintf('The file "%s" does not contain valid YAML: ', $path) . $e->getMessage(), 0, $e);
        }
        $collection = new RouteCollection();
        $collection->addResource(new FileResource($path));
        // empty file
        if (null === $parsedConfig) {
            return $collection;
        }
        // not an array
        if (!\is_array($parsedConfig)) {
            throw new \InvalidArgumentException(\sprintf('The file "%s" must contain a YAML array.', $path));
        }
        foreach ($parsedConfig as $name => $config) {
            if (str_starts_with($name, 'when@')) {
                if (!$this->env || 'when@' . $this->env !== $name) {
                    continue;
                }
                foreach ($config as $name => $config) {
                    $this->validate($config, $name . '" when "@' . $this->env, $path);
                    if (isset($config['resource'])) {
                        $this->parseImport($collection, $config, $path, $file);
                    } else {
                        $this->parseRoute($collection, $name, $config, $path);
                    }
                }
                continue;
            }
            $this->validate($config, $name, $path);
            if (isset($config['resource'])) {
                $this->parseImport($collection, $config, $path, $file);
            } else {
                $this->parseRoute($collection, $name, $config, $path);
            }
        }
        return $collection;
    }
    public function supports(mixed $resource, ?string $type = null): bool
    {
        return \is_string($resource) && \in_array(pathinfo($resource, \PATHINFO_EXTENSION), ['yml', 'yaml'], \true) && (!$type || 'yaml' === $type);
    }
    /**
     * Parses a route and adds it to the RouteCollection.
     *
     * @return void
     */
    protected function parseRoute(RouteCollection $collection, string $name, array $config, string $path)
    {
        if (isset($config['alias'])) {
            $alias = $collection->addAlias($name, $config['alias']);
            $deprecation = $config['deprecated'] ?? null;
            if (null !== $deprecation) {
                $alias->setDeprecated($deprecation['package'], $deprecation['version'], $deprecation['message'] ?? '');
            }
            return;
        }
        $defaults = $config['defaults'] ?? [];
        $requirements = $config['requirements'] ?? [];
        $options = $config['options'] ?? [];
        foreach ($requirements as $placeholder => $requirement) {
            if (\is_int($placeholder)) {
                throw new \InvalidArgumentException(\sprintf('A placeholder name must be a string (%d given). Did you forget to specify the placeholder key for the requirement "%s" of route "%s" in "%s"?', $placeholder, $requirement, $name, $path));
            }
        }
        if (isset($config['controller'])) {
            $defaults['_controller'] = $config['controller'];
        }
        if (isset($config['locale'])) {
            $defaults['_locale'] = $config['locale'];
        }
        if (isset($config['format'])) {
            $defaults['_format'] = $config['format'];
        }
        if (isset($config['utf8'])) {
            $options['utf8'] = $config['utf8'];
        }
        if (isset($config['stateless'])) {
            $defaults['_stateless'] = $config['stateless'];
        }
        $routes = $this->createLocalizedRoute(new RouteCollection(), $name, $config['path']);
        $routes->addDefaults($defaults);
        $routes->addRequirements($requirements);
        $routes->addOptions($options);
        $routes->setSchemes($config['schemes'] ?? []);
        $routes->setMethods($config['methods'] ?? []);
        $routes->setCondition($config['condition'] ?? null);
        if (isset($config['host'])) {
            $this->addHost($routes, $config['host']);
        }
        $collection->addCollection($routes);
    }
    /**
     * Parses an import and adds the routes in the resource to the RouteCollection.
     *
     * @return void
     */
    protected function parseImport(RouteCollection $collection, array $config, string $path, string $file)
    {
        $type = $config['type'] ?? null;
        $prefix = $config['prefix'] ?? '';
        $defaults = $config['defaults'] ?? [];
        $requirements = $config['requirements'] ?? [];
        $options = $config['options'] ?? [];
        $host = $config['host'] ?? null;
        $condition = $config['condition'] ?? null;
        $schemes = $config['schemes'] ?? null;
        $methods = $config['methods'] ?? null;
        $trailingSlashOnRoot = $config['trailing_slash_on_root'] ?? \true;
        $namePrefix = $config['name_prefix'] ?? null;
        $exclude = $config['exclude'] ?? null;
        if (isset($config['controller'])) {
            $defaults['_controller'] = $config['controller'];
        }
        if (isset($config['locale'])) {
            $defaults['_locale'] = $config['locale'];
        }
        if (isset($config['format'])) {
            $defaults['_format'] = $config['format'];
        }
        if (isset($config['utf8'])) {
            $options['utf8'] = $config['utf8'];
        }
        if (isset($config['stateless'])) {
            $defaults['_stateless'] = $config['stateless'];
        }
        $this->setCurrentDir(\dirname($path));
        /** @var RouteCollection[] $imported */
        $imported = $this->import($config['resource'], $type, \false, $file, $exclude) ?: [];
        if (!\is_array($imported)) {
            $imported = [$imported];
        }
        foreach ($imported as $subCollection) {
            $this->addPrefix($subCollection, $prefix, $trailingSlashOnRoot);
            if (null !== $host) {
                $this->addHost($subCollection, $host);
            }
            if (null !== $condition) {
                $subCollection->setCondition($condition);
            }
            if (null !== $schemes) {
                $subCollection->setSchemes($schemes);
            }
            if (null !== $methods) {
                $subCollection->setMethods($methods);
            }
            if (null !== $namePrefix) {
                $subCollection->addNamePrefix($namePrefix);
            }
            $subCollection->addDefaults($defaults);
            $subCollection->addRequirements($requirements);
            $subCollection->addOptions($options);
            $collection->addCollection($subCollection);
        }
    }
    /**
     * @return void
     *
     * @throws \InvalidArgumentException If one of the provided config keys is not supported,
     *                                   something is missing or the combination is nonsense
     */
    protected function validate(mixed $config, string $name, string $path)
    {
        if (!\is_array($config)) {
            throw new \InvalidArgumentException(\sprintf('The definition of "%s" in "%s" must be a YAML array.', $name, $path));
        }
        if (isset($config['alias'])) {
            $this->validateAlias($config, $name, $path);
            return;
        }
        if ($extraKeys = array_diff(array_keys($config), self::AVAILABLE_KEYS)) {
            throw new \InvalidArgumentException(\sprintf('The routing file "%s" contains unsupported keys for "%s": "%s". Expected one of: "%s".', $path, $name, implode('", "', $extraKeys), implode('", "', self::AVAILABLE_KEYS)));
        }
        if (isset($config['resource']) && isset($config['path'])) {
            throw new \InvalidArgumentException(\sprintf('The routing file "%s" must not specify both the "resource" key and the "path" key for "%s". Choose between an import and a route definition.', $path, $name));
        }
        if (!isset($config['resource']) && isset($config['type'])) {
            throw new \InvalidArgumentException(\sprintf('The "type" key for the route definition "%s" in "%s" is unsupported. It is only available for imports in combination with the "resource" key.', $name, $path));
        }
        if (!isset($config['resource']) && !isset($config['path'])) {
            throw new \InvalidArgumentException(\sprintf('You must define a "path" for the route "%s" in file "%s".', $name, $path));
        }
        if (isset($config['controller']) && isset($config['defaults']['_controller'])) {
            throw new \InvalidArgumentException(\sprintf('The routing file "%s" must not specify both the "controller" key and the defaults key "_controller" for "%s".', $path, $name));
        }
        if (isset($config['stateless']) && isset($config['defaults']['_stateless'])) {
            throw new \InvalidArgumentException(\sprintf('The routing file "%s" must not specify both the "stateless" key and the defaults key "_stateless" for "%s".', $path, $name));
        }
    }
    /**
     * @throws \InvalidArgumentException If one of the provided config keys is not supported,
     *                                   something is missing or the combination is nonsense
     */
    private function validateAlias(array $config, string $name, string $path): void
    {
        foreach ($config as $key => $value) {
            if (!\in_array($key, ['alias', 'deprecated'], \true)) {
                throw new \InvalidArgumentException(\sprintf('The routing file "%s" must not specify other keys than "alias" and "deprecated" for "%s".', $path, $name));
            }
            if ('deprecated' === $key) {
                if (!isset($value['package'])) {
                    throw new \InvalidArgumentException(\sprintf('The routing file "%s" must specify the attribute "package" of the "deprecated" option for "%s".', $path, $name));
                }
                if (!isset($value['version'])) {
                    throw new \InvalidArgumentException(\sprintf('The routing file "%s" must specify the attribute "version" of the "deprecated" option for "%s".', $path, $name));
                }
            }
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Routing\Loader;

trigger_deprecation('symfony/routing', '6.4', 'The "%s" class is deprecated, use "%s" instead.', AnnotationFileLoader::class, AttributeFileLoader::class);
class_exists(AttributeFileLoader::class);
if (\false) {
    /**
     * @deprecated since Symfony 6.4, to be removed in 7.0, use {@link AttributeFileLoader} instead
     */
    class AnnotationFileLoader extends AttributeFileLoader
    {
    }
}
<?xml version="1.0" encoding="UTF-8" ?>

<xsd:schema xmlns="http://symfony.com/schema/routing"
    xmlns:xsd="http://www.w3.org/2001/XMLSchema"
    targetNamespace="http://symfony.com/schema/routing"
    elementFormDefault="qualified">

  <xsd:annotation>
    <xsd:documentation><![CDATA[
      Symfony XML Routing Schema, version 1.0
      Authors: Fabien Potencier, Tobias Schultze

      This scheme defines the elements and attributes that can be used to define
      routes. A route maps an HTTP request to a set of configuration variables.
    ]]></xsd:documentation>
  </xsd:annotation>

  <xsd:element name="routes" type="routes" />

  <xsd:complexType name="routes">
    <xsd:choice minOccurs="0" maxOccurs="unbounded">
      <xsd:element name="import" type="import" />
      <xsd:element name="route" type="route" />
      <xsd:element name="when" type="when" />
    </xsd:choice>
  </xsd:complexType>

  <xsd:complexType name="when">
    <xsd:choice minOccurs="0" maxOccurs="unbounded">
      <xsd:element name="import" type="import" />
      <xsd:element name="route" type="route" />
    </xsd:choice>
    <xsd:attribute name="env" type="xsd:string" use="required" />
  </xsd:complexType>

  <xsd:complexType name="localized-path">
    <xsd:simpleContent>
      <xsd:extension base="xsd:string">
        <xsd:attribute name="locale" type="xsd:string" use="required" />
      </xsd:extension>
    </xsd:simpleContent>
  </xsd:complexType>

  <xsd:group name="configs">
    <xsd:choice>
      <xsd:element name="default" nillable="true" type="default" />
      <xsd:element name="requirement" type="element" />
      <xsd:element name="option" type="element" />
      <xsd:element name="condition" type="xsd:string" />
    </xsd:choice>
  </xsd:group>

  <xsd:complexType name="route">
    <xsd:sequence>
      <xsd:group ref="configs" minOccurs="0" maxOccurs="unbounded" />
      <xsd:element name="path" type="localized-path" minOccurs="0" maxOccurs="unbounded" />
      <xsd:element name="host" type="localized-path" minOccurs="0" maxOccurs="unbounded" />
      <xsd:element name="deprecated" type="deprecated" minOccurs="0" maxOccurs="1" />
    </xsd:sequence>
    <xsd:attribute name="id" type="xsd:string" use="required" />
    <xsd:attribute name="path" type="xsd:string" />
    <xsd:attribute name="host" type="xsd:string" />
    <xsd:attribute name="schemes" type="xsd:string" />
    <xsd:attribute name="methods" type="xsd:string" />
    <xsd:attribute name="controller" type="xsd:string" />
    <xsd:attribute name="locale" type="xsd:string" />
    <xsd:attribute name="format" type="xsd:string" />
    <xsd:attribute name="utf8" type="xsd:boolean" />
    <xsd:attribute name="stateless" type="xsd:boolean" />
    <xsd:attribute name="alias" type="xsd:string" />
  </xsd:complexType>

  <xsd:complexType name="import">
    <xsd:sequence maxOccurs="unbounded" minOccurs="0">
      <xsd:group ref="configs" minOccurs="0" maxOccurs="unbounded" />
      <xsd:element name="prefix" type="localized-path" minOccurs="0" maxOccurs="unbounded" />
      <xsd:element name="exclude" type="xsd:string" minOccurs="0" maxOccurs="unbounded" />
      <xsd:element name="host" type="localized-path" minOccurs="0" maxOccurs="unbounded" />
      <xsd:element name="resource" type="resource" minOccurs="0" maxOccurs="1" />
    </xsd:sequence>
    <xsd:attribute name="resource" type="xsd:string" />
    <xsd:attribute name="type" type="xsd:string" />
    <xsd:attribute name="exclude" type="xsd:string" />
    <xsd:attribute name="prefix" type="xsd:string" />
    <xsd:attribute name="name-prefix" type="xsd:string" />
    <xsd:attribute name="host" type="xsd:string" />
    <xsd:attribute name="schemes" type="xsd:string" />
    <xsd:attribute name="methods" type="xsd:string" />
    <xsd:attribute name="controller" type="xsd:string" />
    <xsd:attribute name="locale" type="xsd:string" />
    <xsd:attribute name="format" type="xsd:string" />
    <xsd:attribute name="trailing-slash-on-root" type="xsd:boolean" />
    <xsd:attribute name="utf8" type="xsd:boolean" />
    <xsd:attribute name="stateless" type="xsd:boolean" />
  </xsd:complexType>

  <xsd:complexType name="resource">
    <xsd:attribute name="path" type="xsd:string" />
    <xsd:attribute name="namespace" type="xsd:string" />
    <xsd:anyAttribute />
  </xsd:complexType>

  <xsd:complexType name="default" mixed="true">
    <xsd:choice minOccurs="0" maxOccurs="1">
      <xsd:element name="bool" type="xsd:boolean" />
      <xsd:element name="int" type="xsd:integer" />
      <xsd:element name="float" type="xsd:float" />
      <xsd:element name="string" type="xsd:string" />
      <xsd:element name="list" type="list" />
      <xsd:element name="map" type="map" />
    </xsd:choice>
    <xsd:attribute name="key" type="xsd:string" use="required" />
  </xsd:complexType>

  <xsd:complexType name="element">
    <xsd:simpleContent>
      <xsd:extension base="xsd:string">
        <xsd:attribute name="key" type="xsd:string" use="required" />
      </xsd:extension>
    </xsd:simpleContent>
  </xsd:complexType>

  <xsd:complexType name="list">
    <xsd:choice minOccurs="0" maxOccurs="unbounded">
      <xsd:element name="bool" nillable="true" type="xsd:boolean" />
      <xsd:element name="int" nillable="true" type="xsd:integer" />
      <xsd:element name="float" nillable="true" type="xsd:float" />
      <xsd:element name="string" nillable="true" type="xsd:string" />
      <xsd:element name="list" nillable="true" type="list" />
      <xsd:element name="map" nillable="true" type="map" />
    </xsd:choice>
  </xsd:complexType>

  <xsd:complexType name="map">
      <xsd:choice minOccurs="0" maxOccurs="unbounded">
          <xsd:element name="bool" nillable="true" type="map-bool-entry" />
          <xsd:element name="int" nillable="true" type="map-int-entry" />
          <xsd:element name="float" nillable="true" type="map-float-entry" />
          <xsd:element name="string" nillable="true" type="map-string-entry" />
          <xsd:element name="list" nillable="true" type="map-list-entry" />
          <xsd:element name="map" nillable="true" type="map-map-entry" />
      </xsd:choice>
  </xsd:complexType>

  <xsd:complexType name="map-bool-entry">
    <xsd:simpleContent>
      <xsd:extension base="xsd:boolean">
        <xsd:attribute name="key" type="xsd:string" use="required" />
      </xsd:extension>
    </xsd:simpleContent>
  </xsd:complexType>

  <xsd:complexType name="map-int-entry">
    <xsd:simpleContent>
      <xsd:extension base="xsd:integer">
        <xsd:attribute name="key" type="xsd:string" use="required" />
      </xsd:extension>
    </xsd:simpleContent>
  </xsd:complexType>

  <xsd:complexType name="map-float-entry">
    <xsd:simpleContent>
      <xsd:extension base="xsd:float">
        <xsd:attribute name="key" type="xsd:string" use="required" />
      </xsd:extension>
    </xsd:simpleContent>
  </xsd:complexType>

  <xsd:complexType name="map-string-entry">
    <xsd:simpleContent>
      <xsd:extension base="xsd:string">
        <xsd:attribute name="key" type="xsd:string" use="required" />
      </xsd:extension>
    </xsd:simpleContent>
  </xsd:complexType>

  <xsd:complexType name="map-list-entry">
    <xsd:complexContent>
      <xsd:extension base="list">
        <xsd:attribute name="key" type="xsd:string" use="required" />
      </xsd:extension>
    </xsd:complexContent>
  </xsd:complexType>

  <xsd:complexType name="map-map-entry">
    <xsd:complexContent>
      <xsd:extension base="map">
        <xsd:attribute name="key" type="xsd:string" use="required" />
      </xsd:extension>
    </xsd:complexContent>
  </xsd:complexType>

  <xsd:complexType name="deprecated">
    <xsd:simpleContent>
      <xsd:extension base="xsd:string">
        <xsd:attribute name="package" type="xsd:string" use="required" />
        <xsd:attribute name="version" type="xsd:string" use="required" />
      </xsd:extension>
    </xsd:simpleContent>
  </xsd:complexType>
</xsd:schema>
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Routing\Loader;

use _ContaoManager\Symfony\Component\Config\Loader\FileLoader;
use _ContaoManager\Symfony\Component\Config\Resource\FileResource;
use _ContaoManager\Symfony\Component\Routing\Loader\Configurator\RoutingConfigurator;
use _ContaoManager\Symfony\Component\Routing\RouteCollection;
/**
 * PhpFileLoader loads routes from a PHP file.
 *
 * The file must return a RouteCollection instance.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 * @author Nicolas grekas <p@tchwork.com>
 * @author Jules Pietri <jules@heahprod.com>
 */
class PhpFileLoader extends FileLoader
{
    /**
     * Loads a PHP file.
     */
    public function load(mixed $file, ?string $type = null): RouteCollection
    {
        $path = $this->locator->locate($file);
        $this->setCurrentDir(\dirname($path));
        // the closure forbids access to the private scope in the included file
        $loader = $this;
        $load = \Closure::bind(static function ($file) use ($loader) {
            return include $file;
        }, null, ProtectedPhpFileLoader::class);
        $result = $load($path);
        if (\is_object($result) && \is_callable($result)) {
            $collection = $this->callConfigurator($result, $path, $file);
        } else {
            $collection = $result;
        }
        $collection->addResource(new FileResource($path));
        return $collection;
    }
    public function supports(mixed $resource, ?string $type = null): bool
    {
        return \is_string($resource) && 'php' === pathinfo($resource, \PATHINFO_EXTENSION) && (!$type || 'php' === $type);
    }
    protected function callConfigurator(callable $result, string $path, string $file): RouteCollection
    {
        $collection = new RouteCollection();
        $result(new RoutingConfigurator($collection, $this, $path, $file, $this->env));
        return $collection;
    }
}
/**
 * @internal
 */
final class ProtectedPhpFileLoader extends PhpFileLoader
{
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Routing\Loader;

use _ContaoManager\Symfony\Component\Config\FileLocatorInterface;
use _ContaoManager\Symfony\Component\Config\Loader\DirectoryAwareLoaderInterface;
use _ContaoManager\Symfony\Component\Config\Loader\Loader;
use _ContaoManager\Symfony\Component\Config\Resource\DirectoryResource;
use _ContaoManager\Symfony\Component\Routing\RouteCollection;
/**
 * A loader that discovers controller classes in a directory that follows PSR-4.
 *
 * @author Alexander M. Turek <me@derrabus.de>
 */
final class Psr4DirectoryLoader extends Loader implements DirectoryAwareLoaderInterface
{
    private ?string $currentDirectory = null;
    public function __construct(private readonly FileLocatorInterface $locator)
    {
        // PSR-4 directory loader has no env-aware logic, so we drop the $env constructor parameter.
        parent::__construct();
    }
    /**
     * @param array{path: string, namespace: string} $resource
     */
    public function load(mixed $resource, ?string $type = null): ?RouteCollection
    {
        $excluded = $resource['_excluded'] ?? [];
        $path = $this->locator->locate($resource['path'], $this->currentDirectory);
        if (!is_dir($path)) {
            return new RouteCollection();
        }
        return $this->loadFromDirectory($path, trim($resource['namespace'], '\\'), $excluded);
    }
    public function supports(mixed $resource, ?string $type = null): bool
    {
        return ('attribute' === $type || 'annotation' === $type) && \is_array($resource) && isset($resource['path'], $resource['namespace']);
    }
    public function forDirectory(string $currentDirectory): static
    {
        $loader = clone $this;
        $loader->currentDirectory = $currentDirectory;
        return $loader;
    }
    private function loadFromDirectory(string $directory, string $psr4Prefix, array $excluded = []): RouteCollection
    {
        $collection = new RouteCollection();
        $collection->addResource(new DirectoryResource($directory, '/\.php$/'));
        $files = iterator_to_array(new \RecursiveIteratorIterator(new \RecursiveCallbackFilterIterator(new \RecursiveDirectoryIterator($directory, \FilesystemIterator::SKIP_DOTS | \FilesystemIterator::FOLLOW_SYMLINKS), fn(\SplFileInfo $current) => !str_starts_with($current->getBasename(), '.')), \RecursiveIteratorIterator::SELF_FIRST));
        usort($files, fn(\SplFileInfo $a, \SplFileInfo $b) => (string) $a > (string) $b ? 1 : -1);
        /** @var \SplFileInfo $file */
        foreach ($files as $file) {
            $normalizedPath = rtrim(str_replace('\\', '/', $file->getPathname()), '/');
            if (isset($excluded[$normalizedPath])) {
                continue;
            }
            if ($file->isDir()) {
                $collection->addCollection($this->loadFromDirectory($file->getPathname(), $psr4Prefix . '\\' . $file->getFilename(), $excluded));
                continue;
            }
            if ('php' !== $file->getExtension() || !class_exists($className = $psr4Prefix . '\\' . $file->getBasename('.php')) || (new \ReflectionClass($className))->isAbstract()) {
                continue;
            }
            $collection->addCollection($this->import($className, 'attribute'));
        }
        return $collection;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Routing\Loader;

use _ContaoManager\Symfony\Component\Config\Loader\FileLoader;
use _ContaoManager\Symfony\Component\Config\Resource\FileResource;
use _ContaoManager\Symfony\Component\Config\Util\XmlUtils;
use _ContaoManager\Symfony\Component\Routing\Loader\Configurator\Traits\HostTrait;
use _ContaoManager\Symfony\Component\Routing\Loader\Configurator\Traits\LocalizedRouteTrait;
use _ContaoManager\Symfony\Component\Routing\Loader\Configurator\Traits\PrefixTrait;
use _ContaoManager\Symfony\Component\Routing\RouteCollection;
/**
 * XmlFileLoader loads XML routing files.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 * @author Tobias Schultze <http://tobion.de>
 */
class XmlFileLoader extends FileLoader
{
    use HostTrait;
    use LocalizedRouteTrait;
    use PrefixTrait;
    public const NAMESPACE_URI = 'http://symfony.com/schema/routing';
    public const SCHEME_PATH = '/schema/routing/routing-1.0.xsd';
    /**
     * @throws \InvalidArgumentException when the file cannot be loaded or when the XML cannot be
     *                                   parsed because it does not validate against the scheme
     */
    public function load(mixed $file, ?string $type = null): RouteCollection
    {
        $path = $this->locator->locate($file);
        $xml = $this->loadFile($path);
        $collection = new RouteCollection();
        $collection->addResource(new FileResource($path));
        // process routes and imports
        foreach ($xml->documentElement->childNodes as $node) {
            if (!$node instanceof \DOMElement) {
                continue;
            }
            $this->parseNode($collection, $node, $path, $file);
        }
        return $collection;
    }
    /**
     * Parses a node from a loaded XML file.
     *
     * @return void
     *
     * @throws \InvalidArgumentException When the XML is invalid
     */
    protected function parseNode(RouteCollection $collection, \DOMElement $node, string $path, string $file)
    {
        if (self::NAMESPACE_URI !== $node->namespaceURI) {
            return;
        }
        switch ($node->localName) {
            case 'route':
                $this->parseRoute($collection, $node, $path);
                break;
            case 'import':
                $this->parseImport($collection, $node, $path, $file);
                break;
            case 'when':
                if (!$this->env || $node->getAttribute('env') !== $this->env) {
                    break;
                }
                foreach ($node->childNodes as $node) {
                    if ($node instanceof \DOMElement) {
                        $this->parseNode($collection, $node, $path, $file);
                    }
                }
                break;
            default:
                throw new \InvalidArgumentException(\sprintf('Unknown tag "%s" used in file "%s". Expected "route" or "import".', $node->localName, $path));
        }
    }
    public function supports(mixed $resource, ?string $type = null): bool
    {
        return \is_string($resource) && 'xml' === pathinfo($resource, \PATHINFO_EXTENSION) && (!$type || 'xml' === $type);
    }
    /**
     * Parses a route and adds it to the RouteCollection.
     *
     * @return void
     *
     * @throws \InvalidArgumentException When the XML is invalid
     */
    protected function parseRoute(RouteCollection $collection, \DOMElement $node, string $path)
    {
        if ('' === $id = $node->getAttribute('id')) {
            throw new \InvalidArgumentException(\sprintf('The <route> element in file "%s" must have an "id" attribute.', $path));
        }
        if ('' !== $alias = $node->getAttribute('alias')) {
            $alias = $collection->addAlias($id, $alias);
            if ($deprecationInfo = $this->parseDeprecation($node, $path)) {
                $alias->setDeprecated($deprecationInfo['package'], $deprecationInfo['version'], $deprecationInfo['message']);
            }
            return;
        }
        $schemes = preg_split('/[\s,\|]++/', $node->getAttribute('schemes'), -1, \PREG_SPLIT_NO_EMPTY);
        $methods = preg_split('/[\s,\|]++/', $node->getAttribute('methods'), -1, \PREG_SPLIT_NO_EMPTY);
        [$defaults, $requirements, $options, $condition, $paths, , $hosts] = $this->parseConfigs($node, $path);
        if (!$paths && '' === $node->getAttribute('path')) {
            throw new \InvalidArgumentException(\sprintf('The <route> element in file "%s" must have a "path" attribute or <path> child nodes.', $path));
        }
        if ($paths && '' !== $node->getAttribute('path')) {
            throw new \InvalidArgumentException(\sprintf('The <route> element in file "%s" must not have both a "path" attribute and <path> child nodes.', $path));
        }
        $routes = $this->createLocalizedRoute(new RouteCollection(), $id, $paths ?: $node->getAttribute('path'));
        $routes->addDefaults($defaults);
        $routes->addRequirements($requirements);
        $routes->addOptions($options);
        $routes->setSchemes($schemes);
        $routes->setMethods($methods);
        $routes->setCondition($condition);
        if (null !== $hosts) {
            $this->addHost($routes, $hosts);
        }
        $collection->addCollection($routes);
    }
    /**
     * Parses an import and adds the routes in the resource to the RouteCollection.
     *
     * @return void
     *
     * @throws \InvalidArgumentException When the XML is invalid
     */
    protected function parseImport(RouteCollection $collection, \DOMElement $node, string $path, string $file)
    {
        /** @var \DOMElement $resourceElement */
        if (!($resource = $node->getAttribute('resource') ?: null) && $resourceElement = $node->getElementsByTagName('resource')[0] ?? null) {
            $resource = [];
            /** @var \DOMAttr $attribute */
            foreach ($resourceElement->attributes as $attribute) {
                $resource[$attribute->name] = $attribute->value;
            }
        }
        if (!$resource) {
            throw new \InvalidArgumentException(\sprintf('The <import> element in file "%s" must have a "resource" attribute or element.', $path));
        }
        $type = $node->getAttribute('type');
        $prefix = $node->getAttribute('prefix');
        $schemes = $node->hasAttribute('schemes') ? preg_split('/[\s,\|]++/', $node->getAttribute('schemes'), -1, \PREG_SPLIT_NO_EMPTY) : null;
        $methods = $node->hasAttribute('methods') ? preg_split('/[\s,\|]++/', $node->getAttribute('methods'), -1, \PREG_SPLIT_NO_EMPTY) : null;
        $trailingSlashOnRoot = $node->hasAttribute('trailing-slash-on-root') ? XmlUtils::phpize($node->getAttribute('trailing-slash-on-root')) : \true;
        $namePrefix = $node->getAttribute('name-prefix') ?: null;
        [$defaults, $requirements, $options, $condition, , $prefixes, $hosts] = $this->parseConfigs($node, $path);
        if ('' !== $prefix && $prefixes) {
            throw new \InvalidArgumentException(\sprintf('The <route> element in file "%s" must not have both a "prefix" attribute and <prefix> child nodes.', $path));
        }
        $exclude = [];
        foreach ($node->childNodes as $child) {
            if ($child instanceof \DOMElement && $child->localName === $exclude && self::NAMESPACE_URI === $child->namespaceURI) {
                $exclude[] = $child->nodeValue;
            }
        }
        if ($node->hasAttribute('exclude')) {
            if ($exclude) {
                throw new \InvalidArgumentException('You cannot use both the attribute "exclude" and <exclude> tags at the same time.');
            }
            $exclude = [$node->getAttribute('exclude')];
        }
        $this->setCurrentDir(\dirname($path));
        /** @var RouteCollection[] $imported */
        $imported = $this->import($resource, '' !== $type ? $type : null, \false, $file, $exclude) ?: [];
        if (!\is_array($imported)) {
            $imported = [$imported];
        }
        foreach ($imported as $subCollection) {
            $this->addPrefix($subCollection, $prefixes ?: $prefix, $trailingSlashOnRoot);
            if (null !== $hosts) {
                $this->addHost($subCollection, $hosts);
            }
            if (null !== $condition) {
                $subCollection->setCondition($condition);
            }
            if (null !== $schemes) {
                $subCollection->setSchemes($schemes);
            }
            if (null !== $methods) {
                $subCollection->setMethods($methods);
            }
            if (null !== $namePrefix) {
                $subCollection->addNamePrefix($namePrefix);
            }
            $subCollection->addDefaults($defaults);
            $subCollection->addRequirements($requirements);
            $subCollection->addOptions($options);
            $collection->addCollection($subCollection);
        }
    }
    /**
     * @throws \InvalidArgumentException When loading of XML file fails because of syntax errors
     *                                   or when the XML structure is not as expected by the scheme -
     *                                   see validate()
     */
    protected function loadFile(string $file): \DOMDocument
    {
        return XmlUtils::loadFile($file, __DIR__ . static::SCHEME_PATH);
    }
    /**
     * Parses the config elements (default, requirement, option).
     *
     * @throws \InvalidArgumentException When the XML is invalid
     */
    private function parseConfigs(\DOMElement $node, string $path): array
    {
        $defaults = [];
        $requirements = [];
        $options = [];
        $condition = null;
        $prefixes = [];
        $paths = [];
        $hosts = [];
        /** @var \DOMElement $n */
        foreach ($node->getElementsByTagNameNS(self::NAMESPACE_URI, '*') as $n) {
            if ($node !== $n->parentNode) {
                continue;
            }
            switch ($n->localName) {
                case 'path':
                    $paths[$n->getAttribute('locale')] = trim($n->textContent);
                    break;
                case 'host':
                    $hosts[$n->getAttribute('locale')] = trim($n->textContent);
                    break;
                case 'prefix':
                    $prefixes[$n->getAttribute('locale')] = trim($n->textContent);
                    break;
                case 'default':
                    if ($this->isElementValueNull($n)) {
                        $defaults[$n->getAttribute('key')] = null;
                    } else {
                        $defaults[$n->getAttribute('key')] = $this->parseDefaultsConfig($n, $path);
                    }
                    break;
                case 'requirement':
                    $requirements[$n->getAttribute('key')] = trim($n->textContent);
                    break;
                case 'option':
                    $options[$n->getAttribute('key')] = XmlUtils::phpize(trim($n->textContent));
                    break;
                case 'condition':
                    $condition = trim($n->textContent);
                    break;
                case 'resource':
                    break;
                default:
                    throw new \InvalidArgumentException(\sprintf('Unknown tag "%s" used in file "%s". Expected "default", "requirement", "option" or "condition".', $n->localName, $path));
            }
        }
        if ($controller = $node->getAttribute('controller')) {
            if (isset($defaults['_controller'])) {
                $name = $node->hasAttribute('id') ? \sprintf('"%s".', $node->getAttribute('id')) : \sprintf('the "%s" tag.', $node->tagName);
                throw new \InvalidArgumentException(\sprintf('The routing file "%s" must not specify both the "controller" attribute and the defaults key "_controller" for ', $path) . $name);
            }
            $defaults['_controller'] = $controller;
        }
        if ($node->hasAttribute('locale')) {
            $defaults['_locale'] = $node->getAttribute('locale');
        }
        if ($node->hasAttribute('format')) {
            $defaults['_format'] = $node->getAttribute('format');
        }
        if ($node->hasAttribute('utf8')) {
            $options['utf8'] = XmlUtils::phpize($node->getAttribute('utf8'));
        }
        if ($stateless = $node->getAttribute('stateless')) {
            if (isset($defaults['_stateless'])) {
                $name = $node->hasAttribute('id') ? \sprintf('"%s".', $node->getAttribute('id')) : \sprintf('the "%s" tag.', $node->tagName);
                throw new \InvalidArgumentException(\sprintf('The routing file "%s" must not specify both the "stateless" attribute and the defaults key "_stateless" for ', $path) . $name);
            }
            $defaults['_stateless'] = XmlUtils::phpize($stateless);
        }
        if (!$hosts) {
            $hosts = $node->hasAttribute('host') ? $node->getAttribute('host') : null;
        }
        return [$defaults, $requirements, $options, $condition, $paths, $prefixes, $hosts];
    }
    /**
     * Parses the "default" elements.
     */
    private function parseDefaultsConfig(\DOMElement $element, string $path): array|bool|float|int|string|null
    {
        if ($this->isElementValueNull($element)) {
            return null;
        }
        // Check for existing element nodes in the default element. There can
        // only be a single element inside a default element. So this element
        // (if one was found) can safely be returned.
        foreach ($element->childNodes as $child) {
            if (!$child instanceof \DOMElement) {
                continue;
            }
            if (self::NAMESPACE_URI !== $child->namespaceURI) {
                continue;
            }
            return $this->parseDefaultNode($child, $path);
        }
        // If the default element doesn't contain a nested "bool", "int", "float",
        // "string", "list", or "map" element, the element contents will be treated
        // as the string value of the associated default option.
        return trim($element->textContent);
    }
    /**
     * Recursively parses the value of a "default" element.
     *
     * @throws \InvalidArgumentException when the XML is invalid
     */
    private function parseDefaultNode(\DOMElement $node, string $path): array|bool|float|int|string|null
    {
        if ($this->isElementValueNull($node)) {
            return null;
        }
        switch ($node->localName) {
            case 'bool':
                return 'true' === trim($node->nodeValue) || '1' === trim($node->nodeValue);
            case 'int':
                return (int) trim($node->nodeValue);
            case 'float':
                return (float) trim($node->nodeValue);
            case 'string':
                return trim($node->nodeValue);
            case 'list':
                $list = [];
                foreach ($node->childNodes as $element) {
                    if (!$element instanceof \DOMElement) {
                        continue;
                    }
                    if (self::NAMESPACE_URI !== $element->namespaceURI) {
                        continue;
                    }
                    $list[] = $this->parseDefaultNode($element, $path);
                }
                return $list;
            case 'map':
                $map = [];
                foreach ($node->childNodes as $element) {
                    if (!$element instanceof \DOMElement) {
                        continue;
                    }
                    if (self::NAMESPACE_URI !== $element->namespaceURI) {
                        continue;
                    }
                    $map[$element->getAttribute('key')] = $this->parseDefaultNode($element, $path);
                }
                return $map;
            default:
                throw new \InvalidArgumentException(\sprintf('Unknown tag "%s" used in file "%s". Expected "bool", "int", "float", "string", "list", or "map".', $node->localName, $path));
        }
    }
    private function isElementValueNull(\DOMElement $element): bool
    {
        $namespaceUri = 'http://www.w3.org/2001/XMLSchema-instance';
        if (!$element->hasAttributeNS($namespaceUri, 'nil')) {
            return \false;
        }
        return 'true' === $element->getAttributeNS($namespaceUri, 'nil') || '1' === $element->getAttributeNS($namespaceUri, 'nil');
    }
    /**
     * Parses the deprecation elements.
     *
     * @throws \InvalidArgumentException When the XML is invalid
     */
    private function parseDeprecation(\DOMElement $node, string $path): array
    {
        $deprecatedNode = null;
        foreach ($node->childNodes as $child) {
            if (!$child instanceof \DOMElement || self::NAMESPACE_URI !== $child->namespaceURI) {
                continue;
            }
            if ('deprecated' !== $child->localName) {
                throw new \InvalidArgumentException(\sprintf('Invalid child element "%s" defined for alias "%s" in "%s".', $child->localName, $node->getAttribute('id'), $path));
            }
            $deprecatedNode = $child;
        }
        if (null === $deprecatedNode) {
            return [];
        }
        if (!$deprecatedNode->hasAttribute('package')) {
            throw new \InvalidArgumentException(\sprintf('The <deprecated> element in file "%s" must have a "package" attribute.', $path));
        }
        if (!$deprecatedNode->hasAttribute('version')) {
            throw new \InvalidArgumentException(\sprintf('The <deprecated> element in file "%s" must have a "version" attribute.', $path));
        }
        return ['package' => $deprecatedNode->getAttribute('package'), 'version' => $deprecatedNode->getAttribute('version'), 'message' => trim($deprecatedNode->nodeValue)];
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Routing\Loader;

use _ContaoManager\Symfony\Component\Config\Loader\Loader;
use _ContaoManager\Symfony\Component\Config\Resource\FileResource;
use _ContaoManager\Symfony\Component\Routing\RouteCollection;
/**
 * A route loader that calls a method on an object to load the routes.
 *
 * @author Ryan Weaver <ryan@knpuniversity.com>
 */
abstract class ObjectLoader extends Loader
{
    /**
     * Returns the object that the method will be called on to load routes.
     *
     * For example, if your application uses a service container,
     * the $id may be a service id.
     */
    abstract protected function getObject(string $id): object;
    /**
     * Calls the object method that will load the routes.
     */
    public function load(mixed $resource, ?string $type = null): RouteCollection
    {
        if (!preg_match('/^[^\:]+(?:::(?:[^\:]+))?$/', $resource)) {
            throw new \InvalidArgumentException(\sprintf('Invalid resource "%s" passed to the %s route loader: use the format "object_id::method" or "object_id" if your object class has an "__invoke" method.', $resource, \is_string($type) ? '"' . $type . '"' : 'object'));
        }
        $parts = explode('::', $resource);
        $method = $parts[1] ?? '__invoke';
        $loaderObject = $this->getObject($parts[0]);
        if (!\is_object($loaderObject)) {
            throw new \TypeError(\sprintf('"%s:getObject()" must return an object: "%s" returned.', static::class, get_debug_type($loaderObject)));
        }
        if (!\is_callable([$loaderObject, $method])) {
            throw new \BadMethodCallException(\sprintf('Method "%s" not found on "%s" when importing routing resource "%s".', $method, get_debug_type($loaderObject), $resource));
        }
        $routeCollection = $loaderObject->{$method}($this, $this->env);
        if (!$routeCollection instanceof RouteCollection) {
            $type = get_debug_type($routeCollection);
            throw new \LogicException(\sprintf('The "%s::%s()" method must return a RouteCollection: "%s" returned.', get_debug_type($loaderObject), $method, $type));
        }
        // make the object file tracked so that if it changes, the cache rebuilds
        $this->addClassResource(new \ReflectionClass($loaderObject), $routeCollection);
        return $routeCollection;
    }
    private function addClassResource(\ReflectionClass $class, RouteCollection $collection): void
    {
        do {
            if (is_file($class->getFileName())) {
                $collection->addResource(new FileResource($class->getFileName()));
            }
        } while ($class = $class->getParentClass());
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Routing\Loader\Configurator\Traits;

use _ContaoManager\Symfony\Component\Routing\RouteCollection;
/**
 * @internal
 */
trait HostTrait
{
    final protected function addHost(RouteCollection $routes, string|array $hosts): void
    {
        if (!$hosts || !\is_array($hosts)) {
            $routes->setHost($hosts ?: '');
            return;
        }
        foreach ($routes->all() as $name => $route) {
            if (null === $locale = $route->getDefault('_locale')) {
                $priority = $routes->getPriority($name) ?? 0;
                $routes->remove($name);
                foreach ($hosts as $locale => $host) {
                    $localizedRoute = clone $route;
                    $localizedRoute->setDefault('_locale', $locale);
                    $localizedRoute->setRequirement('_locale', preg_quote($locale));
                    $localizedRoute->setDefault('_canonical_route', $name);
                    $localizedRoute->setHost($host);
                    $routes->add($name . '.' . $locale, $localizedRoute, $priority);
                }
            } elseif (!isset($hosts[$locale])) {
                throw new \InvalidArgumentException(\sprintf('Route "%s" with locale "%s" is missing a corresponding host in its parent collection.', $name, $locale));
            } else {
                $route->setHost($hosts[$locale]);
                $route->setRequirement('_locale', preg_quote($locale));
                $routes->add($name, $route, $routes->getPriority($name) ?? 0);
            }
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Routing\Loader\Configurator\Traits;

use _ContaoManager\Symfony\Component\Routing\Route;
use _ContaoManager\Symfony\Component\Routing\RouteCollection;
/**
 * @internal
 *
 * @author Nicolas Grekas <p@tchwork.com>
 */
trait PrefixTrait
{
    final protected function addPrefix(RouteCollection $routes, string|array $prefix, bool $trailingSlashOnRoot): void
    {
        if (\is_array($prefix)) {
            foreach ($prefix as $locale => $localePrefix) {
                $prefix[$locale] = trim(trim($localePrefix), '/');
            }
            $aliases = [];
            foreach ($routes->getAliases() as $name => $alias) {
                $aliases[$alias->getId()][] = $name;
            }
            foreach ($routes->all() as $name => $route) {
                if (null === $locale = $route->getDefault('_locale')) {
                    $priority = $routes->getPriority($name) ?? 0;
                    $routes->remove($name);
                    foreach ($aliases[$name] ?? [] as $aliasName) {
                        $routes->remove($aliasName);
                    }
                    foreach ($prefix as $locale => $localePrefix) {
                        $localizedRoute = clone $route;
                        $localizedRoute->setDefault('_locale', $locale);
                        $localizedRoute->setRequirement('_locale', preg_quote($locale));
                        $localizedRoute->setDefault('_canonical_route', $name);
                        $localizedRoute->setPath($localePrefix . (!$trailingSlashOnRoot && '/' === $route->getPath() ? '' : $route->getPath()));
                        $routes->add($name . '.' . $locale, $localizedRoute, $priority);
                        foreach ($aliases[$name] ?? [] as $aliasName) {
                            $routes->addAlias($aliasName . '.' . $locale, $name . '.' . $locale);
                        }
                    }
                } elseif (!isset($prefix[$locale])) {
                    throw new \InvalidArgumentException(\sprintf('Route "%s" with locale "%s" is missing a corresponding prefix in its parent collection.', $name, $locale));
                } else {
                    $route->setPath($prefix[$locale] . (!$trailingSlashOnRoot && '/' === $route->getPath() ? '' : $route->getPath()));
                    $routes->add($name, $route, $routes->getPriority($name) ?? 0);
                }
            }
            return;
        }
        $routes->addPrefix($prefix);
        if (!$trailingSlashOnRoot) {
            $rootPath = (new Route(trim(trim($prefix), '/') . '/'))->getPath();
            foreach ($routes->all() as $route) {
                if ($route->getPath() === $rootPath) {
                    $route->setPath(rtrim($rootPath, '/'));
                }
            }
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Routing\Loader\Configurator\Traits;

use _ContaoManager\Symfony\Component\Routing\Route;
use _ContaoManager\Symfony\Component\Routing\RouteCollection;
/**
 * @internal
 *
 * @author Nicolas Grekas <p@tchwork.com>
 * @author Jules Pietri <jules@heahprod.com>
 */
trait LocalizedRouteTrait
{
    /**
     * Creates one or many routes.
     *
     * @param string|array $path the path, or the localized paths of the route
     */
    final protected function createLocalizedRoute(RouteCollection $collection, string $name, string|array $path, string $namePrefix = '', ?array $prefixes = null): RouteCollection
    {
        $paths = [];
        $routes = new RouteCollection();
        if (\is_array($path)) {
            if (null === $prefixes) {
                $paths = $path;
            } elseif ($missing = array_diff_key($prefixes, $path)) {
                throw new \LogicException(\sprintf('Route "%s" is missing routes for locale(s) "%s".', $name, implode('", "', array_keys($missing))));
            } else {
                foreach ($path as $locale => $localePath) {
                    if (!isset($prefixes[$locale])) {
                        throw new \LogicException(\sprintf('Route "%s" with locale "%s" is missing a corresponding prefix in its parent collection.', $name, $locale));
                    }
                    $paths[$locale] = $prefixes[$locale] . $localePath;
                }
            }
        } elseif (null !== $prefixes) {
            foreach ($prefixes as $locale => $prefix) {
                $paths[$locale] = $prefix . $path;
            }
        } else {
            $routes->add($namePrefix . $name, $route = $this->createRoute($path));
            $collection->add($namePrefix . $name, $route);
            return $routes;
        }
        foreach ($paths as $locale => $path) {
            $routes->add($name . '.' . $locale, $route = $this->createRoute($path));
            $collection->add($namePrefix . $name . '.' . $locale, $route);
            $route->setDefault('_locale', $locale);
            $route->setRequirement('_locale', preg_quote($locale));
            $route->setDefault('_canonical_route', $namePrefix . $name);
        }
        return $routes;
    }
    private function createRoute(string $path): Route
    {
        return new Route($path);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Routing\Loader\Configurator\Traits;

use _ContaoManager\Symfony\Component\Routing\Route;
use _ContaoManager\Symfony\Component\Routing\RouteCollection;
trait RouteTrait
{
    /**
     * @var RouteCollection|Route
     */
    protected $route;
    /**
     * Adds defaults.
     *
     * @return $this
     */
    final public function defaults(array $defaults): static
    {
        $this->route->addDefaults($defaults);
        return $this;
    }
    /**
     * Adds requirements.
     *
     * @return $this
     */
    final public function requirements(array $requirements): static
    {
        $this->route->addRequirements($requirements);
        return $this;
    }
    /**
     * Adds options.
     *
     * @return $this
     */
    final public function options(array $options): static
    {
        $this->route->addOptions($options);
        return $this;
    }
    /**
     * Whether paths should accept utf8 encoding.
     *
     * @return $this
     */
    final public function utf8(bool $utf8 = \true): static
    {
        $this->route->addOptions(['utf8' => $utf8]);
        return $this;
    }
    /**
     * Sets the condition.
     *
     * @return $this
     */
    final public function condition(string $condition): static
    {
        $this->route->setCondition($condition);
        return $this;
    }
    /**
     * Sets the pattern for the host.
     *
     * @return $this
     */
    final public function host(string $pattern): static
    {
        $this->route->setHost($pattern);
        return $this;
    }
    /**
     * Sets the schemes (e.g. 'https') this route is restricted to.
     * So an empty array means that any scheme is allowed.
     *
     * @param string[] $schemes
     *
     * @return $this
     */
    final public function schemes(array $schemes): static
    {
        $this->route->setSchemes($schemes);
        return $this;
    }
    /**
     * Sets the HTTP methods (e.g. 'POST') this route is restricted to.
     * So an empty array means that any method is allowed.
     *
     * @param string[] $methods
     *
     * @return $this
     */
    final public function methods(array $methods): static
    {
        $this->route->setMethods($methods);
        return $this;
    }
    /**
     * Adds the "_controller" entry to defaults.
     *
     * @param callable|string|array $controller a callable or parseable pseudo-callable
     *
     * @return $this
     */
    final public function controller(callable|string|array $controller): static
    {
        $this->route->addDefaults(['_controller' => $controller]);
        return $this;
    }
    /**
     * Adds the "_locale" entry to defaults.
     *
     * @return $this
     */
    final public function locale(string $locale): static
    {
        $this->route->addDefaults(['_locale' => $locale]);
        return $this;
    }
    /**
     * Adds the "_format" entry to defaults.
     *
     * @return $this
     */
    final public function format(string $format): static
    {
        $this->route->addDefaults(['_format' => $format]);
        return $this;
    }
    /**
     * Adds the "_stateless" entry to defaults.
     *
     * @return $this
     */
    final public function stateless(bool $stateless = \true): static
    {
        $this->route->addDefaults(['_stateless' => $stateless]);
        return $this;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Routing\Loader\Configurator\Traits;

use _ContaoManager\Symfony\Component\Routing\Loader\Configurator\AliasConfigurator;
use _ContaoManager\Symfony\Component\Routing\Loader\Configurator\CollectionConfigurator;
use _ContaoManager\Symfony\Component\Routing\Loader\Configurator\RouteConfigurator;
use _ContaoManager\Symfony\Component\Routing\RouteCollection;
/**
 * @author Nicolas Grekas <p@tchwork.com>
 */
trait AddTrait
{
    use LocalizedRouteTrait;
    /**
     * @var RouteCollection
     */
    protected $collection;
    protected $name = '';
    protected $prefixes;
    /**
     * Adds a route.
     *
     * @param string|array $path the path, or the localized paths of the route
     */
    public function add(string $name, string|array $path): RouteConfigurator
    {
        $parentConfigurator = $this instanceof CollectionConfigurator ? $this : ($this instanceof RouteConfigurator ? $this->parentConfigurator : null);
        $route = $this->createLocalizedRoute($this->collection, $name, $path, $this->name, $this->prefixes);
        return new RouteConfigurator($this->collection, $route, $this->name, $parentConfigurator, $this->prefixes);
    }
    public function alias(string $name, string $alias): AliasConfigurator
    {
        return new AliasConfigurator($this->collection->addAlias($name, $alias));
    }
    /**
     * Adds a route.
     *
     * @param string|array $path the path, or the localized paths of the route
     */
    public function __invoke(string $name, string|array $path): RouteConfigurator
    {
        return $this->add($name, $path);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Routing\Loader\Configurator;

use _ContaoManager\Symfony\Component\Routing\RouteCollection;
/**
 * @author Nicolas Grekas <p@tchwork.com>
 */
class RouteConfigurator
{
    use Traits\AddTrait;
    use Traits\HostTrait;
    use Traits\RouteTrait;
    protected $parentConfigurator;
    public function __construct(RouteCollection $collection, RouteCollection $route, string $name = '', ?CollectionConfigurator $parentConfigurator = null, ?array $prefixes = null)
    {
        $this->collection = $collection;
        $this->route = $route;
        $this->name = $name;
        $this->parentConfigurator = $parentConfigurator;
        // for GC control
        $this->prefixes = $prefixes;
    }
    /**
     * Sets the host to use for all child routes.
     *
     * @param string|array $host the host, or the localized hosts
     *
     * @return $this
     */
    final public function host(string|array $host): static
    {
        $previousRoutes = clone $this->route;
        $this->addHost($this->route, $host);
        foreach ($previousRoutes as $name => $route) {
            if (!$this->route->get($name)) {
                $this->collection->remove($name);
            }
        }
        $this->collection->addCollection($this->route);
        return $this;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Routing\Loader\Configurator;

use _ContaoManager\Symfony\Component\Routing\Route;
use _ContaoManager\Symfony\Component\Routing\RouteCollection;
/**
 * @author Nicolas Grekas <p@tchwork.com>
 */
class CollectionConfigurator
{
    use Traits\AddTrait;
    use Traits\HostTrait;
    use Traits\RouteTrait;
    private RouteCollection $parent;
    private ?CollectionConfigurator $parentConfigurator;
    private ?array $parentPrefixes;
    private string|array|null $host = null;
    public function __construct(RouteCollection $parent, string $name, ?self $parentConfigurator = null, ?array $parentPrefixes = null)
    {
        $this->parent = $parent;
        $this->name = $name;
        $this->collection = new RouteCollection();
        $this->route = new Route('');
        $this->parentConfigurator = $parentConfigurator;
        // for GC control
        $this->parentPrefixes = $parentPrefixes;
    }
    public function __serialize(): array
    {
        throw new \BadMethodCallException('Cannot serialize ' . __CLASS__);
    }
    public function __unserialize(array $data): void
    {
        throw new \BadMethodCallException('Cannot unserialize ' . __CLASS__);
    }
    public function __destruct()
    {
        if (null === $this->prefixes) {
            $this->collection->addPrefix($this->route->getPath());
        }
        if (null !== $this->host) {
            $this->addHost($this->collection, $this->host);
        }
        $this->parent->addCollection($this->collection);
    }
    /**
     * Creates a sub-collection.
     */
    final public function collection(string $name = ''): self
    {
        return new self($this->collection, $this->name . $name, $this, $this->prefixes);
    }
    /**
     * Sets the prefix to add to the path of all child routes.
     *
     * @param string|array $prefix the prefix, or the localized prefixes
     *
     * @return $this
     */
    final public function prefix(string|array $prefix): static
    {
        if (\is_array($prefix)) {
            if (null === $this->parentPrefixes) {
                // no-op
            } elseif ($missing = array_diff_key($this->parentPrefixes, $prefix)) {
                throw new \LogicException(\sprintf('Collection "%s" is missing prefixes for locale(s) "%s".', $this->name, implode('", "', array_keys($missing))));
            } else {
                foreach ($prefix as $locale => $localePrefix) {
                    if (!isset($this->parentPrefixes[$locale])) {
                        throw new \LogicException(\sprintf('Collection "%s" with locale "%s" is missing a corresponding prefix in its parent collection.', $this->name, $locale));
                    }
                    $prefix[$locale] = $this->parentPrefixes[$locale] . $localePrefix;
                }
            }
            $this->prefixes = $prefix;
            $this->route->setPath('/');
        } else {
            $this->prefixes = null;
            $this->route->setPath($prefix);
        }
        return $this;
    }
    /**
     * Sets the host to use for all child routes.
     *
     * @param string|array $host the host, or the localized hosts
     *
     * @return $this
     */
    final public function host(string|array $host): static
    {
        $this->host = $host;
        return $this;
    }
    /**
     * This method overrides the one from LocalizedRouteTrait.
     */
    private function createRoute(string $path): Route
    {
        return (clone $this->route)->setPath($path);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Routing\Loader\Configurator;

use _ContaoManager\Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
use _ContaoManager\Symfony\Component\Routing\Alias;
class AliasConfigurator
{
    private Alias $alias;
    public function __construct(Alias $alias)
    {
        $this->alias = $alias;
    }
    /**
     * Whether this alias is deprecated, that means it should not be called anymore.
     *
     * @param string $package The name of the composer package that is triggering the deprecation
     * @param string $version The version of the package that introduced the deprecation
     * @param string $message The deprecation message to use
     *
     * @return $this
     *
     * @throws InvalidArgumentException when the message template is invalid
     */
    public function deprecate(string $package, string $version, string $message): static
    {
        $this->alias->setDeprecated($package, $version, $message);
        return $this;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Routing\Loader\Configurator;

use _ContaoManager\Symfony\Component\Routing\Loader\PhpFileLoader;
use _ContaoManager\Symfony\Component\Routing\RouteCollection;
/**
 * @author Nicolas Grekas <p@tchwork.com>
 */
class RoutingConfigurator
{
    use Traits\AddTrait;
    private PhpFileLoader $loader;
    private string $path;
    private string $file;
    private ?string $env;
    public function __construct(RouteCollection $collection, PhpFileLoader $loader, string $path, string $file, ?string $env = null)
    {
        $this->collection = $collection;
        $this->loader = $loader;
        $this->path = $path;
        $this->file = $file;
        $this->env = $env;
    }
    /**
     * @param string|string[]|null $exclude Glob patterns to exclude from the import
     */
    final public function import(string|array $resource, ?string $type = null, bool $ignoreErrors = \false, string|array|null $exclude = null): ImportConfigurator
    {
        $this->loader->setCurrentDir(\dirname($this->path));
        $imported = $this->loader->import($resource, $type, $ignoreErrors, $this->file, $exclude) ?: [];
        if (!\is_array($imported)) {
            return new ImportConfigurator($this->collection, $imported);
        }
        $mergedCollection = new RouteCollection();
        foreach ($imported as $subCollection) {
            $mergedCollection->addCollection($subCollection);
        }
        return new ImportConfigurator($this->collection, $mergedCollection);
    }
    final public function collection(string $name = ''): CollectionConfigurator
    {
        return new CollectionConfigurator($this->collection, $name);
    }
    /**
     * Get the current environment to be able to write conditional configuration.
     */
    final public function env(): ?string
    {
        return $this->env;
    }
    final public function withPath(string $path): static
    {
        $clone = clone $this;
        $clone->path = $clone->file = $path;
        return $clone;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Routing\Loader\Configurator;

use _ContaoManager\Symfony\Component\Routing\RouteCollection;
/**
 * @author Nicolas Grekas <p@tchwork.com>
 */
class ImportConfigurator
{
    use Traits\HostTrait;
    use Traits\PrefixTrait;
    use Traits\RouteTrait;
    private RouteCollection $parent;
    public function __construct(RouteCollection $parent, RouteCollection $route)
    {
        $this->parent = $parent;
        $this->route = $route;
    }
    public function __serialize(): array
    {
        throw new \BadMethodCallException('Cannot serialize ' . __CLASS__);
    }
    public function __unserialize(array $data): void
    {
        throw new \BadMethodCallException('Cannot unserialize ' . __CLASS__);
    }
    public function __destruct()
    {
        $this->parent->addCollection($this->route);
    }
    /**
     * Sets the prefix to add to the path of all child routes.
     *
     * @param string|array $prefix the prefix, or the localized prefixes
     *
     * @return $this
     */
    final public function prefix(string|array $prefix, bool $trailingSlashOnRoot = \true): static
    {
        $this->addPrefix($this->route, $prefix, $trailingSlashOnRoot);
        return $this;
    }
    /**
     * Sets the prefix to add to the name of all child routes.
     *
     * @return $this
     */
    final public function namePrefix(string $namePrefix): static
    {
        $this->route->addNamePrefix($namePrefix);
        return $this;
    }
    /**
     * Sets the host to use for all child routes.
     *
     * @param string|array $host the host, or the localized hosts
     *
     * @return $this
     */
    final public function host(string|array $host): static
    {
        $this->addHost($this->route, $host);
        return $this;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Routing\Loader;

use _ContaoManager\Doctrine\Common\Annotations\Reader;
use _ContaoManager\Symfony\Component\Config\Loader\LoaderInterface;
use _ContaoManager\Symfony\Component\Config\Loader\LoaderResolverInterface;
use _ContaoManager\Symfony\Component\Config\Resource\FileResource;
use _ContaoManager\Symfony\Component\Routing\Attribute\Route as RouteAnnotation;
use _ContaoManager\Symfony\Component\Routing\Route;
use _ContaoManager\Symfony\Component\Routing\RouteCollection;
/**
 * AttributeClassLoader loads routing information from a PHP class and its methods.
 *
 * You need to define an implementation for the configureRoute() method. Most of the
 * time, this method should define some PHP callable to be called for the route
 * (a controller in MVC speak).
 *
 * The #[Route] attribute can be set on the class (for global parameters),
 * and on each method.
 *
 * The #[Route] attribute main value is the route path. The attribute also
 * recognizes several parameters: requirements, options, defaults, schemes,
 * methods, host, and name. The name parameter is mandatory.
 * Here is an example of how you should be able to use it:
 *
 *     #[Route('/Blog')]
 *     class Blog
 *     {
 *         #[Route('/', name: 'blog_index')]
 *         public function index()
 *         {
 *         }
 *         #[Route('/{id}', name: 'blog_post', requirements: ["id" => '\d+'])]
 *         public function show()
 *         {
 *         }
 *     }
 *
 * @author Fabien Potencier <fabien@symfony.com>
 * @author Alexander M. Turek <me@derrabus.de>
 * @author Alexandre Daubois <alex.daubois@gmail.com>
 */
abstract class AttributeClassLoader implements LoaderInterface
{
    /**
     * @var Reader|null
     *
     * @deprecated in Symfony 6.4, this property will be removed in Symfony 7.
     */
    protected $reader;
    /**
     * @var string|null
     */
    protected $env;
    /**
     * @var string
     */
    protected $routeAnnotationClass = RouteAnnotation::class;
    /**
     * @var int
     */
    protected $defaultRouteIndex = 0;
    private bool $hasDeprecatedAnnotations = \false;
    /**
     * @param string|null $env
     */
    public function __construct($env = null)
    {
        if ($env instanceof Reader || null === $env && \func_num_args() > 1 && null !== func_get_arg(1)) {
            trigger_deprecation('symfony/routing', '6.4', 'Passing an instance of "%s" as first and the environment as second argument to "%s" is deprecated. Pass the environment as first argument instead.', Reader::class, __METHOD__);
            $this->reader = $env;
            $env = \func_num_args() > 1 ? func_get_arg(1) : null;
        }
        if (\is_string($env) || null === $env) {
            $this->env = $env;
        } elseif ($env instanceof \Stringable || \is_scalar($env)) {
            $this->env = (string) $env;
        } else {
            throw new \TypeError(__METHOD__ . \sprintf(': Parameter $env was expected to be a string or null, "%s" given.', get_debug_type($env)));
        }
    }
    /**
     * Sets the annotation class to read route properties from.
     *
     * @return void
     */
    public function setRouteAnnotationClass(string $class)
    {
        $this->routeAnnotationClass = $class;
    }
    /**
     * @throws \InvalidArgumentException When route can't be parsed
     */
    public function load(mixed $class, ?string $type = null): RouteCollection
    {
        if (!class_exists($class)) {
            throw new \InvalidArgumentException(\sprintf('Class "%s" does not exist.', $class));
        }
        $class = new \ReflectionClass($class);
        if ($class->isAbstract()) {
            throw new \InvalidArgumentException(\sprintf('Attributes from class "%s" cannot be read as it is abstract.', $class->getName()));
        }
        $this->hasDeprecatedAnnotations = \false;
        try {
            $globals = $this->getGlobals($class);
            $collection = new RouteCollection();
            $collection->addResource(new FileResource($class->getFileName()));
            if ($globals['env'] && $this->env !== $globals['env']) {
                return $collection;
            }
            $fqcnAlias = \false;
            foreach ($class->getMethods() as $method) {
                $this->defaultRouteIndex = 0;
                $routeNamesBefore = array_keys($collection->all());
                foreach ($this->getAnnotations($method) as $annot) {
                    $this->addRoute($collection, $annot, $globals, $class, $method);
                    if ('__invoke' === $method->name) {
                        $fqcnAlias = \true;
                    }
                }
                if (1 === $collection->count() - \count($routeNamesBefore)) {
                    $newRouteName = current(array_diff(array_keys($collection->all()), $routeNamesBefore));
                    if ($newRouteName !== $aliasName = \sprintf('%s::%s', $class->name, $method->name)) {
                        $collection->addAlias($aliasName, $newRouteName);
                    }
                }
            }
            if (0 === $collection->count() && $class->hasMethod('__invoke')) {
                $globals = $this->resetGlobals();
                foreach ($this->getAnnotations($class) as $annot) {
                    $this->addRoute($collection, $annot, $globals, $class, $class->getMethod('__invoke'));
                    $fqcnAlias = \true;
                }
            }
            if ($fqcnAlias && 1 === $collection->count()) {
                $invokeRouteName = key($collection->all());
                if ($invokeRouteName !== $class->name) {
                    $collection->addAlias($class->name, $invokeRouteName);
                }
                if ($invokeRouteName !== $aliasName = \sprintf('%s::__invoke', $class->name)) {
                    $collection->addAlias($aliasName, $invokeRouteName);
                }
            }
            if ($this->hasDeprecatedAnnotations) {
                trigger_deprecation('symfony/routing', '6.4', 'Class "%s" uses Doctrine Annotations to configure routes, which is deprecated. Use PHP attributes instead.', $class->getName());
            }
        } finally {
            $this->hasDeprecatedAnnotations = \false;
        }
        return $collection;
    }
    /**
     * @param RouteAnnotation $annot or an object that exposes a similar interface
     *
     * @return void
     */
    protected function addRoute(RouteCollection $collection, object $annot, array $globals, \ReflectionClass $class, \ReflectionMethod $method)
    {
        if ($annot->getEnv() && $annot->getEnv() !== $this->env) {
            return;
        }
        $name = $annot->getName() ?? $this->getDefaultRouteName($class, $method);
        $name = $globals['name'] . $name;
        $requirements = $annot->getRequirements();
        foreach ($requirements as $placeholder => $requirement) {
            if (\is_int($placeholder)) {
                throw new \InvalidArgumentException(\sprintf('A placeholder name must be a string (%d given). Did you forget to specify the placeholder key for the requirement "%s" of route "%s" in "%s::%s()"?', $placeholder, $requirement, $name, $class->getName(), $method->getName()));
            }
        }
        $defaults = array_replace($globals['defaults'], $annot->getDefaults());
        $requirements = array_replace($globals['requirements'], $requirements);
        $options = array_replace($globals['options'], $annot->getOptions());
        $schemes = array_unique(array_merge($globals['schemes'], $annot->getSchemes()));
        $methods = array_unique(array_merge($globals['methods'], $annot->getMethods()));
        $host = $annot->getHost() ?? $globals['host'];
        $condition = $annot->getCondition() ?? $globals['condition'];
        $priority = $annot->getPriority() ?? $globals['priority'];
        $path = $annot->getLocalizedPaths() ?: $annot->getPath();
        $prefix = $globals['localized_paths'] ?: $globals['path'];
        $paths = [];
        if (\is_array($path)) {
            if (!\is_array($prefix)) {
                foreach ($path as $locale => $localePath) {
                    $paths[$locale] = $prefix . $localePath;
                }
            } elseif ($missing = array_diff_key($prefix, $path)) {
                throw new \LogicException(\sprintf('Route to "%s" is missing paths for locale(s) "%s".', $class->name . '::' . $method->name, implode('", "', array_keys($missing))));
            } else {
                foreach ($path as $locale => $localePath) {
                    if (!isset($prefix[$locale])) {
                        throw new \LogicException(\sprintf('Route to "%s" with locale "%s" is missing a corresponding prefix in class "%s".', $method->name, $locale, $class->name));
                    }
                    $paths[$locale] = $prefix[$locale] . $localePath;
                }
            }
        } elseif (\is_array($prefix)) {
            foreach ($prefix as $locale => $localePrefix) {
                $paths[$locale] = $localePrefix . $path;
            }
        } else {
            $paths[] = $prefix . $path;
        }
        foreach ($method->getParameters() as $param) {
            if (isset($defaults[$param->name]) || !$param->isDefaultValueAvailable()) {
                continue;
            }
            foreach ($paths as $locale => $path) {
                if (preg_match(\sprintf('/\{%s(?:<.*?>)?\}/', preg_quote($param->name)), $path)) {
                    if (\is_scalar($defaultValue = $param->getDefaultValue()) || null === $defaultValue) {
                        $defaults[$param->name] = $defaultValue;
                    } elseif ($defaultValue instanceof \BackedEnum) {
                        $defaults[$param->name] = $defaultValue->value;
                    }
                    break;
                }
            }
        }
        foreach ($paths as $locale => $path) {
            $route = $this->createRoute($path, $defaults, $requirements, $options, $host, $schemes, $methods, $condition);
            $this->configureRoute($route, $class, $method, $annot);
            if (0 !== $locale) {
                $route->setDefault('_locale', $locale);
                $route->setRequirement('_locale', preg_quote($locale));
                $route->setDefault('_canonical_route', $name);
                $collection->add($name . '.' . $locale, $route, $priority);
            } else {
                $collection->add($name, $route, $priority);
            }
        }
    }
    public function supports(mixed $resource, ?string $type = null): bool
    {
        if ('annotation' === $type) {
            trigger_deprecation('symfony/routing', '6.4', 'The "annotation" route type is deprecated, use the "attribute" route type instead.');
        }
        return \is_string($resource) && preg_match('/^(?:\\\\?[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*)+$/', $resource) && (!$type || \in_array($type, ['annotation', 'attribute'], \true));
    }
    public function setResolver(LoaderResolverInterface $resolver): void
    {
    }
    public function getResolver(): LoaderResolverInterface
    {
    }
    /**
     * Gets the default route name for a class method.
     *
     * @return string
     */
    protected function getDefaultRouteName(\ReflectionClass $class, \ReflectionMethod $method)
    {
        $name = str_replace('\\', '_', $class->name) . '_' . $method->name;
        $name = \function_exists('mb_strtolower') && preg_match('//u', $name) ? mb_strtolower($name, 'UTF-8') : strtolower($name);
        if ($this->defaultRouteIndex > 0) {
            $name .= '_' . $this->defaultRouteIndex;
        }
        ++$this->defaultRouteIndex;
        return $name;
    }
    /**
     * @return array<string, mixed>
     */
    protected function getGlobals(\ReflectionClass $class)
    {
        $globals = $this->resetGlobals();
        $annot = null;
        if ($attribute = $class->getAttributes($this->routeAnnotationClass, \ReflectionAttribute::IS_INSTANCEOF)[0] ?? null) {
            $annot = $attribute->newInstance();
        }
        if (!$annot && $annot = $this->reader?->getClassAnnotation($class, $this->routeAnnotationClass)) {
            $this->hasDeprecatedAnnotations = \true;
        }
        if ($annot) {
            if (null !== $annot->getName()) {
                $globals['name'] = $annot->getName();
            }
            if (null !== $annot->getPath()) {
                $globals['path'] = $annot->getPath();
            }
            $globals['localized_paths'] = $annot->getLocalizedPaths();
            if (null !== $annot->getRequirements()) {
                $globals['requirements'] = $annot->getRequirements();
            }
            if (null !== $annot->getOptions()) {
                $globals['options'] = $annot->getOptions();
            }
            if (null !== $annot->getDefaults()) {
                $globals['defaults'] = $annot->getDefaults();
            }
            if (null !== $annot->getSchemes()) {
                $globals['schemes'] = $annot->getSchemes();
            }
            if (null !== $annot->getMethods()) {
                $globals['methods'] = $annot->getMethods();
            }
            if (null !== $annot->getHost()) {
                $globals['host'] = $annot->getHost();
            }
            if (null !== $annot->getCondition()) {
                $globals['condition'] = $annot->getCondition();
            }
            $globals['priority'] = $annot->getPriority() ?? 0;
            $globals['env'] = $annot->getEnv();
            foreach ($globals['requirements'] as $placeholder => $requirement) {
                if (\is_int($placeholder)) {
                    throw new \InvalidArgumentException(\sprintf('A placeholder name must be a string (%d given). Did you forget to specify the placeholder key for the requirement "%s" in "%s"?', $placeholder, $requirement, $class->getName()));
                }
            }
        }
        return $globals;
    }
    private function resetGlobals(): array
    {
        return ['path' => null, 'localized_paths' => [], 'requirements' => [], 'options' => [], 'defaults' => [], 'schemes' => [], 'methods' => [], 'host' => '', 'condition' => '', 'name' => '', 'priority' => 0, 'env' => null];
    }
    /**
     * @return Route
     */
    protected function createRoute(string $path, array $defaults, array $requirements, array $options, ?string $host, array $schemes, array $methods, ?string $condition)
    {
        return new Route($path, $defaults, $requirements, $options, $host, $schemes, $methods, $condition);
    }
    /**
     * @return void
     */
    abstract protected function configureRoute(Route $route, \ReflectionClass $class, \ReflectionMethod $method, object $annot);
    /**
     * @return iterable<int, RouteAnnotation>
     */
    private function getAnnotations(\ReflectionClass|\ReflectionMethod $reflection): iterable
    {
        foreach ($reflection->getAttributes($this->routeAnnotationClass, \ReflectionAttribute::IS_INSTANCEOF) as $attribute) {
            yield $attribute->newInstance();
        }
        if (!$this->reader) {
            return;
        }
        $annotations = $reflection instanceof \ReflectionClass ? $this->reader->getClassAnnotations($reflection) : $this->reader->getMethodAnnotations($reflection);
        foreach ($annotations as $annotation) {
            if ($annotation instanceof $this->routeAnnotationClass) {
                $this->hasDeprecatedAnnotations = \true;
                yield $annotation;
            }
        }
    }
}
if (!class_exists(AnnotationClassLoader::class, \false)) {
    class_alias(AttributeClassLoader::class, AnnotationClassLoader::class);
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Routing\Loader;

use _ContaoManager\Psr\Container\ContainerInterface;
/**
 * A route loader that executes a service from a PSR-11 container to load the routes.
 *
 * @author Ryan Weaver <ryan@knpuniversity.com>
 */
class ContainerLoader extends ObjectLoader
{
    private ContainerInterface $container;
    public function __construct(ContainerInterface $container, ?string $env = null)
    {
        $this->container = $container;
        parent::__construct($env);
    }
    public function supports(mixed $resource, ?string $type = null): bool
    {
        return 'service' === $type && \is_string($resource);
    }
    protected function getObject(string $id): object
    {
        return $this->container->get($id);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Routing\Loader;

use _ContaoManager\Symfony\Component\Config\Loader\FileLoader;
use _ContaoManager\Symfony\Component\Config\Resource\DirectoryResource;
use _ContaoManager\Symfony\Component\Routing\RouteCollection;
class DirectoryLoader extends FileLoader
{
    public function load(mixed $file, ?string $type = null): mixed
    {
        $path = $this->locator->locate($file);
        $collection = new RouteCollection();
        $collection->addResource(new DirectoryResource($path));
        foreach (scandir($path) as $dir) {
            if ('.' !== $dir[0]) {
                $this->setCurrentDir($path);
                $subPath = $path . '/' . $dir;
                $subType = null;
                if (is_dir($subPath)) {
                    $subPath .= '/';
                    $subType = 'directory';
                }
                $subCollection = $this->import($subPath, $subType, \false, $path);
                $collection->addCollection($subCollection);
            }
        }
        return $collection;
    }
    public function supports(mixed $resource, ?string $type = null): bool
    {
        // only when type is forced to directory, not to conflict with AttributeLoader
        return 'directory' === $type;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Routing\Loader;

use _ContaoManager\Symfony\Component\Config\Loader\FileLoader;
use _ContaoManager\Symfony\Component\Routing\RouteCollection;
/**
 * GlobFileLoader loads files from a glob pattern.
 *
 * @author Nicolas Grekas <p@tchwork.com>
 */
class GlobFileLoader extends FileLoader
{
    public function load(mixed $resource, ?string $type = null): mixed
    {
        $collection = new RouteCollection();
        foreach ($this->glob($resource, \false, $globResource) as $path => $info) {
            $collection->addCollection($this->import($path));
        }
        $collection->addResource($globResource);
        return $collection;
    }
    public function supports(mixed $resource, ?string $type = null): bool
    {
        return 'glob' === $type;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Routing\Loader;

use _ContaoManager\Symfony\Component\Config\Loader\Loader;
use _ContaoManager\Symfony\Component\Routing\RouteCollection;
/**
 * ClosureLoader loads routes from a PHP closure.
 *
 * The Closure must return a RouteCollection instance.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class ClosureLoader extends Loader
{
    /**
     * Loads a Closure.
     */
    public function load(mixed $closure, ?string $type = null): RouteCollection
    {
        return $closure($this->env);
    }
    public function supports(mixed $resource, ?string $type = null): bool
    {
        return $resource instanceof \Closure && (!$type || 'closure' === $type);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Routing\Loader;

trigger_deprecation('symfony/routing', '6.4', 'The "%s" class is deprecated, use "%s" instead.', AnnotationDirectoryLoader::class, AttributeDirectoryLoader::class);
class_exists(AttributeDirectoryLoader::class);
if (\false) {
    /**
     * @deprecated since Symfony 6.4, to be removed in 7.0, use {@link AttributeDirectoryLoader} instead
     */
    class AnnotationDirectoryLoader extends AttributeDirectoryLoader
    {
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Routing;

/**
 * A Route describes a route and its parameters.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 * @author Tobias Schultze <http://tobion.de>
 */
class Route implements \Serializable
{
    private string $path = '/';
    private string $host = '';
    private array $schemes = [];
    private array $methods = [];
    private array $defaults = [];
    private array $requirements = [];
    private array $options = [];
    private string $condition = '';
    private ?CompiledRoute $compiled = null;
    /**
     * Constructor.
     *
     * Available options:
     *
     *  * compiler_class: A class name able to compile this route instance (RouteCompiler by default)
     *  * utf8:           Whether UTF-8 matching is enforced or not
     *
     * @param string                    $path         The path pattern to match
     * @param array                     $defaults     An array of default parameter values
     * @param array<string|\Stringable> $requirements An array of requirements for parameters (regexes)
     * @param array                     $options      An array of options
     * @param string|null               $host         The host pattern to match
     * @param string|string[]           $schemes      A required URI scheme or an array of restricted schemes
     * @param string|string[]           $methods      A required HTTP method or an array of restricted methods
     * @param string|null               $condition    A condition that should evaluate to true for the route to match
     */
    public function __construct(string $path, array $defaults = [], array $requirements = [], array $options = [], ?string $host = '', string|array $schemes = [], string|array $methods = [], ?string $condition = '')
    {
        $this->setPath($path);
        $this->addDefaults($defaults);
        $this->addRequirements($requirements);
        $this->setOptions($options);
        $this->setHost($host);
        $this->setSchemes($schemes);
        $this->setMethods($methods);
        $this->setCondition($condition);
    }
    public function __serialize(): array
    {
        return ['path' => $this->path, 'host' => $this->host, 'defaults' => $this->defaults, 'requirements' => $this->requirements, 'options' => $this->options, 'schemes' => $this->schemes, 'methods' => $this->methods, 'condition' => $this->condition, 'compiled' => $this->compiled];
    }
    /**
     * @internal
     */
    final public function serialize(): string
    {
        throw new \BadMethodCallException('Cannot serialize ' . __CLASS__);
    }
    public function __unserialize(array $data): void
    {
        $this->path = $data['path'];
        $this->host = $data['host'];
        $this->defaults = $data['defaults'];
        $this->requirements = $data['requirements'];
        $this->options = $data['options'];
        $this->schemes = $data['schemes'];
        $this->methods = $data['methods'];
        if (isset($data['condition'])) {
            $this->condition = $data['condition'];
        }
        if (isset($data['compiled'])) {
            $this->compiled = $data['compiled'];
        }
    }
    /**
     * @internal
     */
    final public function unserialize(string $serialized): void
    {
        $this->__unserialize(unserialize($serialized));
    }
    public function getPath(): string
    {
        return $this->path;
    }
    /**
     * @return $this
     */
    public function setPath(string $pattern): static
    {
        $pattern = $this->extractInlineDefaultsAndRequirements($pattern);
        // A pattern must start with a slash and must not have multiple slashes at the beginning because the
        // generated path for this route would be confused with a network path, e.g. '//domain.com/path'.
        $this->path = '/' . ltrim(trim($pattern), '/');
        $this->compiled = null;
        return $this;
    }
    public function getHost(): string
    {
        return $this->host;
    }
    /**
     * @return $this
     */
    public function setHost(?string $pattern): static
    {
        $this->host = $this->extractInlineDefaultsAndRequirements((string) $pattern);
        $this->compiled = null;
        return $this;
    }
    /**
     * Returns the lowercased schemes this route is restricted to.
     * So an empty array means that any scheme is allowed.
     *
     * @return string[]
     */
    public function getSchemes(): array
    {
        return $this->schemes;
    }
    /**
     * Sets the schemes (e.g. 'https') this route is restricted to.
     * So an empty array means that any scheme is allowed.
     *
     * @param string|string[] $schemes The scheme or an array of schemes
     *
     * @return $this
     */
    public function setSchemes(string|array $schemes): static
    {
        $this->schemes = array_map('strtolower', (array) $schemes);
        $this->compiled = null;
        return $this;
    }
    /**
     * Checks if a scheme requirement has been set.
     */
    public function hasScheme(string $scheme): bool
    {
        return \in_array(strtolower($scheme), $this->schemes, \true);
    }
    /**
     * Returns the uppercased HTTP methods this route is restricted to.
     * So an empty array means that any method is allowed.
     *
     * @return string[]
     */
    public function getMethods(): array
    {
        return $this->methods;
    }
    /**
     * Sets the HTTP methods (e.g. 'POST') this route is restricted to.
     * So an empty array means that any method is allowed.
     *
     * @param string|string[] $methods The method or an array of methods
     *
     * @return $this
     */
    public function setMethods(string|array $methods): static
    {
        $this->methods = array_map('strtoupper', (array) $methods);
        $this->compiled = null;
        return $this;
    }
    public function getOptions(): array
    {
        return $this->options;
    }
    /**
     * @return $this
     */
    public function setOptions(array $options): static
    {
        $this->options = ['compiler_class' => RouteCompiler::class];
        return $this->addOptions($options);
    }
    /**
     * @return $this
     */
    public function addOptions(array $options): static
    {
        foreach ($options as $name => $option) {
            $this->options[$name] = $option;
        }
        $this->compiled = null;
        return $this;
    }
    /**
     * Sets an option value.
     *
     * @return $this
     */
    public function setOption(string $name, mixed $value): static
    {
        $this->options[$name] = $value;
        $this->compiled = null;
        return $this;
    }
    /**
     * Returns the option value or null when not found.
     */
    public function getOption(string $name): mixed
    {
        return $this->options[$name] ?? null;
    }
    public function hasOption(string $name): bool
    {
        return \array_key_exists($name, $this->options);
    }
    public function getDefaults(): array
    {
        return $this->defaults;
    }
    /**
     * @return $this
     */
    public function setDefaults(array $defaults): static
    {
        $this->defaults = [];
        return $this->addDefaults($defaults);
    }
    /**
     * @return $this
     */
    public function addDefaults(array $defaults): static
    {
        if (isset($defaults['_locale']) && $this->isLocalized()) {
            unset($defaults['_locale']);
        }
        foreach ($defaults as $name => $default) {
            $this->defaults[$name] = $default;
        }
        $this->compiled = null;
        return $this;
    }
    public function getDefault(string $name): mixed
    {
        return $this->defaults[$name] ?? null;
    }
    public function hasDefault(string $name): bool
    {
        return \array_key_exists($name, $this->defaults);
    }
    /**
     * @return $this
     */
    public function setDefault(string $name, mixed $default): static
    {
        if ('_locale' === $name && $this->isLocalized()) {
            return $this;
        }
        $this->defaults[$name] = $default;
        $this->compiled = null;
        return $this;
    }
    public function getRequirements(): array
    {
        return $this->requirements;
    }
    /**
     * @return $this
     */
    public function setRequirements(array $requirements): static
    {
        $this->requirements = [];
        return $this->addRequirements($requirements);
    }
    /**
     * @return $this
     */
    public function addRequirements(array $requirements): static
    {
        if (isset($requirements['_locale']) && $this->isLocalized()) {
            unset($requirements['_locale']);
        }
        foreach ($requirements as $key => $regex) {
            $this->requirements[$key] = $this->sanitizeRequirement($key, $regex);
        }
        $this->compiled = null;
        return $this;
    }
    public function getRequirement(string $key): ?string
    {
        return $this->requirements[$key] ?? null;
    }
    public function hasRequirement(string $key): bool
    {
        return \array_key_exists($key, $this->requirements);
    }
    /**
     * @return $this
     */
    public function setRequirement(string $key, string $regex): static
    {
        if ('_locale' === $key && $this->isLocalized()) {
            return $this;
        }
        $this->requirements[$key] = $this->sanitizeRequirement($key, $regex);
        $this->compiled = null;
        return $this;
    }
    public function getCondition(): string
    {
        return $this->condition;
    }
    /**
     * @return $this
     */
    public function setCondition(?string $condition): static
    {
        $this->condition = (string) $condition;
        $this->compiled = null;
        return $this;
    }
    /**
     * Compiles the route.
     *
     * @throws \LogicException If the Route cannot be compiled because the
     *                         path or host pattern is invalid
     *
     * @see RouteCompiler which is responsible for the compilation process
     */
    public function compile(): CompiledRoute
    {
        if (null !== $this->compiled) {
            return $this->compiled;
        }
        $class = $this->getOption('compiler_class');
        return $this->compiled = $class::compile($this);
    }
    private function extractInlineDefaultsAndRequirements(string $pattern): string
    {
        if (\false === strpbrk($pattern, '?<')) {
            return $pattern;
        }
        return preg_replace_callback('#\{(!?)([\w\x80-\xFF]++)(<.*?>)?(\?[^\}]*+)?\}#', function ($m) {
            if (isset($m[4][0])) {
                $this->setDefault($m[2], '?' !== $m[4] ? substr($m[4], 1) : null);
            }
            if (isset($m[3][0])) {
                $this->setRequirement($m[2], substr($m[3], 1, -1));
            }
            return '{' . $m[1] . $m[2] . '}';
        }, $pattern);
    }
    private function sanitizeRequirement(string $key, string $regex): string
    {
        if ('' !== $regex) {
            if ('^' === $regex[0]) {
                $regex = substr($regex, 1);
            } elseif (str_starts_with($regex, '\A')) {
                $regex = substr($regex, 2);
            }
        }
        if (str_ends_with($regex, '$')) {
            $regex = substr($regex, 0, -1);
        } elseif (\strlen($regex) - 2 === strpos($regex, '\z')) {
            $regex = substr($regex, 0, -2);
        }
        if ('' === $regex) {
            throw new \InvalidArgumentException(\sprintf('Routing requirement for "%s" cannot be empty.', $key));
        }
        return $regex;
    }
    private function isLocalized(): bool
    {
        return isset($this->defaults['_locale']) && isset($this->defaults['_canonical_route']) && ($this->requirements['_locale'] ?? null) === preg_quote($this->defaults['_locale']);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Routing;

use _ContaoManager\Symfony\Component\Routing\Generator\UrlGeneratorInterface;
use _ContaoManager\Symfony\Component\Routing\Matcher\UrlMatcherInterface;
/**
 * RouterInterface is the interface that all Router classes must implement.
 *
 * This interface is the concatenation of UrlMatcherInterface and UrlGeneratorInterface.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
interface RouterInterface extends UrlMatcherInterface, UrlGeneratorInterface
{
    /**
     * Gets the RouteCollection instance associated with this Router.
     *
     * WARNING: This method should never be used at runtime as it is SLOW.
     *          You might use it in a cache warmer though.
     *
     * @return RouteCollection
     */
    public function getRouteCollection();
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Routing;

use _ContaoManager\Psr\Log\LoggerInterface;
use _ContaoManager\Symfony\Component\Config\ConfigCacheFactory;
use _ContaoManager\Symfony\Component\Config\ConfigCacheFactoryInterface;
use _ContaoManager\Symfony\Component\Config\ConfigCacheInterface;
use _ContaoManager\Symfony\Component\Config\Loader\LoaderInterface;
use _ContaoManager\Symfony\Component\ExpressionLanguage\ExpressionFunctionProviderInterface;
use _ContaoManager\Symfony\Component\HttpFoundation\Request;
use _ContaoManager\Symfony\Component\Routing\Generator\CompiledUrlGenerator;
use _ContaoManager\Symfony\Component\Routing\Generator\ConfigurableRequirementsInterface;
use _ContaoManager\Symfony\Component\Routing\Generator\Dumper\CompiledUrlGeneratorDumper;
use _ContaoManager\Symfony\Component\Routing\Generator\Dumper\GeneratorDumperInterface;
use _ContaoManager\Symfony\Component\Routing\Generator\UrlGeneratorInterface;
use _ContaoManager\Symfony\Component\Routing\Matcher\CompiledUrlMatcher;
use _ContaoManager\Symfony\Component\Routing\Matcher\Dumper\CompiledUrlMatcherDumper;
use _ContaoManager\Symfony\Component\Routing\Matcher\Dumper\MatcherDumperInterface;
use _ContaoManager\Symfony\Component\Routing\Matcher\RequestMatcherInterface;
use _ContaoManager\Symfony\Component\Routing\Matcher\UrlMatcherInterface;
/**
 * The Router class is an example of the integration of all pieces of the
 * routing system for easier use.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class Router implements RouterInterface, RequestMatcherInterface
{
    /**
     * @var UrlMatcherInterface|null
     */
    protected $matcher;
    /**
     * @var UrlGeneratorInterface|null
     */
    protected $generator;
    /**
     * @var RequestContext
     */
    protected $context;
    /**
     * @var LoaderInterface
     */
    protected $loader;
    /**
     * @var RouteCollection|null
     */
    protected $collection;
    /**
     * @var mixed
     */
    protected $resource;
    /**
     * @var array
     */
    protected $options = [];
    /**
     * @var LoggerInterface|null
     */
    protected $logger;
    /**
     * @var string|null
     */
    protected $defaultLocale;
    private ConfigCacheFactoryInterface $configCacheFactory;
    /**
     * @var ExpressionFunctionProviderInterface[]
     */
    private array $expressionLanguageProviders = [];
    private static ?array $cache = [];
    public function __construct(LoaderInterface $loader, mixed $resource, array $options = [], ?RequestContext $context = null, ?LoggerInterface $logger = null, ?string $defaultLocale = null)
    {
        $this->loader = $loader;
        $this->resource = $resource;
        $this->logger = $logger;
        $this->context = $context ?? new RequestContext();
        $this->setOptions($options);
        $this->defaultLocale = $defaultLocale;
    }
    /**
     * Sets options.
     *
     * Available options:
     *
     *   * cache_dir:              The cache directory (or null to disable caching)
     *   * debug:                  Whether to enable debugging or not (false by default)
     *   * generator_class:        The name of a UrlGeneratorInterface implementation
     *   * generator_dumper_class: The name of a GeneratorDumperInterface implementation
     *   * matcher_class:          The name of a UrlMatcherInterface implementation
     *   * matcher_dumper_class:   The name of a MatcherDumperInterface implementation
     *   * resource_type:          Type hint for the main resource (optional)
     *   * strict_requirements:    Configure strict requirement checking for generators
     *                             implementing ConfigurableRequirementsInterface (default is true)
     *
     * @return void
     *
     * @throws \InvalidArgumentException When unsupported option is provided
     */
    public function setOptions(array $options)
    {
        $this->options = ['cache_dir' => null, 'debug' => \false, 'generator_class' => CompiledUrlGenerator::class, 'generator_dumper_class' => CompiledUrlGeneratorDumper::class, 'matcher_class' => CompiledUrlMatcher::class, 'matcher_dumper_class' => CompiledUrlMatcherDumper::class, 'resource_type' => null, 'strict_requirements' => \true];
        // check option names and live merge, if errors are encountered Exception will be thrown
        $invalid = [];
        foreach ($options as $key => $value) {
            if (\array_key_exists($key, $this->options)) {
                $this->options[$key] = $value;
            } else {
                $invalid[] = $key;
            }
        }
        if ($invalid) {
            throw new \InvalidArgumentException(\sprintf('The Router does not support the following options: "%s".', implode('", "', $invalid)));
        }
    }
    /**
     * Sets an option.
     *
     * @return void
     *
     * @throws \InvalidArgumentException
     */
    public function setOption(string $key, mixed $value)
    {
        if (!\array_key_exists($key, $this->options)) {
            throw new \InvalidArgumentException(\sprintf('The Router does not support the "%s" option.', $key));
        }
        $this->options[$key] = $value;
    }
    /**
     * Gets an option value.
     *
     * @throws \InvalidArgumentException
     */
    public function getOption(string $key): mixed
    {
        if (!\array_key_exists($key, $this->options)) {
            throw new \InvalidArgumentException(\sprintf('The Router does not support the "%s" option.', $key));
        }
        return $this->options[$key];
    }
    /**
     * @return RouteCollection
     */
    public function getRouteCollection()
    {
        return $this->collection ??= $this->loader->load($this->resource, $this->options['resource_type']);
    }
    /**
     * @return void
     */
    public function setContext(RequestContext $context)
    {
        $this->context = $context;
        if (isset($this->matcher)) {
            $this->getMatcher()->setContext($context);
        }
        if (isset($this->generator)) {
            $this->getGenerator()->setContext($context);
        }
    }
    public function getContext(): RequestContext
    {
        return $this->context;
    }
    /**
     * Sets the ConfigCache factory to use.
     *
     * @return void
     */
    public function setConfigCacheFactory(ConfigCacheFactoryInterface $configCacheFactory)
    {
        $this->configCacheFactory = $configCacheFactory;
    }
    public function generate(string $name, array $parameters = [], int $referenceType = self::ABSOLUTE_PATH): string
    {
        return $this->getGenerator()->generate($name, $parameters, $referenceType);
    }
    public function match(string $pathinfo): array
    {
        return $this->getMatcher()->match($pathinfo);
    }
    public function matchRequest(Request $request): array
    {
        $matcher = $this->getMatcher();
        if (!$matcher instanceof RequestMatcherInterface) {
            // fallback to the default UrlMatcherInterface
            return $matcher->match($request->getPathInfo());
        }
        return $matcher->matchRequest($request);
    }
    /**
     * Gets the UrlMatcher or RequestMatcher instance associated with this Router.
     */
    public function getMatcher(): UrlMatcherInterface|RequestMatcherInterface
    {
        if (isset($this->matcher)) {
            return $this->matcher;
        }
        if (null === $this->options['cache_dir']) {
            $routes = $this->getRouteCollection();
            $compiled = is_a($this->options['matcher_class'], CompiledUrlMatcher::class, \true);
            if ($compiled) {
                $routes = (new CompiledUrlMatcherDumper($routes))->getCompiledRoutes();
            }
            $this->matcher = new $this->options['matcher_class']($routes, $this->context);
            if (method_exists($this->matcher, 'addExpressionLanguageProvider')) {
                foreach ($this->expressionLanguageProviders as $provider) {
                    $this->matcher->addExpressionLanguageProvider($provider);
                }
            }
            return $this->matcher;
        }
        $cache = $this->getConfigCacheFactory()->cache($this->options['cache_dir'] . '/url_matching_routes.php', function (ConfigCacheInterface $cache) {
            $dumper = $this->getMatcherDumperInstance();
            if (method_exists($dumper, 'addExpressionLanguageProvider')) {
                foreach ($this->expressionLanguageProviders as $provider) {
                    $dumper->addExpressionLanguageProvider($provider);
                }
            }
            $cache->write($dumper->dump(), $this->getRouteCollection()->getResources());
            unset(self::$cache[$cache->getPath()]);
        });
        return $this->matcher = new $this->options['matcher_class'](self::getCompiledRoutes($cache->getPath()), $this->context);
    }
    /**
     * Gets the UrlGenerator instance associated with this Router.
     */
    public function getGenerator(): UrlGeneratorInterface
    {
        if (isset($this->generator)) {
            return $this->generator;
        }
        if (null === $this->options['cache_dir']) {
            $routes = $this->getRouteCollection();
            $compiled = is_a($this->options['generator_class'], CompiledUrlGenerator::class, \true);
            if ($compiled) {
                $generatorDumper = new CompiledUrlGeneratorDumper($routes);
                $routes = array_merge($generatorDumper->getCompiledRoutes(), $generatorDumper->getCompiledAliases());
            }
            $this->generator = new $this->options['generator_class']($routes, $this->context, $this->logger, $this->defaultLocale);
        } else {
            $cache = $this->getConfigCacheFactory()->cache($this->options['cache_dir'] . '/url_generating_routes.php', function (ConfigCacheInterface $cache) {
                $dumper = $this->getGeneratorDumperInstance();
                $cache->write($dumper->dump(), $this->getRouteCollection()->getResources());
                unset(self::$cache[$cache->getPath()]);
            });
            $this->generator = new $this->options['generator_class'](self::getCompiledRoutes($cache->getPath()), $this->context, $this->logger, $this->defaultLocale);
        }
        if ($this->generator instanceof ConfigurableRequirementsInterface) {
            $this->generator->setStrictRequirements($this->options['strict_requirements']);
        }
        return $this->generator;
    }
    /**
     * @return void
     */
    public function addExpressionLanguageProvider(ExpressionFunctionProviderInterface $provider)
    {
        $this->expressionLanguageProviders[] = $provider;
    }
    protected function getGeneratorDumperInstance(): GeneratorDumperInterface
    {
        return new $this->options['generator_dumper_class']($this->getRouteCollection());
    }
    protected function getMatcherDumperInstance(): MatcherDumperInterface
    {
        return new $this->options['matcher_dumper_class']($this->getRouteCollection());
    }
    /**
     * Provides the ConfigCache factory implementation, falling back to a
     * default implementation if necessary.
     */
    private function getConfigCacheFactory(): ConfigCacheFactoryInterface
    {
        return $this->configCacheFactory ??= new ConfigCacheFactory($this->options['debug']);
    }
    private static function getCompiledRoutes(string $path): array
    {
        if ([] === self::$cache && \function_exists('opcache_invalidate') && filter_var(\ini_get('opcache.enable'), \FILTER_VALIDATE_BOOL) && (!\in_array(\PHP_SAPI, ['cli', 'phpdbg', 'embed'], \true) || filter_var(\ini_get('opcache.enable_cli'), \FILTER_VALIDATE_BOOL))) {
            self::$cache = null;
        }
        if (null === self::$cache) {
            return require $path;
        }
        return self::$cache[$path] ??= require $path;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Routing;

/**
 * RouteCompilerInterface is the interface that all RouteCompiler classes must implement.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
interface RouteCompilerInterface
{
    /**
     * Compiles the current route instance.
     *
     * @throws \LogicException If the Route cannot be compiled because the
     *                         path or host pattern is invalid
     */
    public static function compile(Route $route): CompiledRoute;
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Routing;

use _ContaoManager\Symfony\Component\Routing\Exception\InvalidArgumentException;
class Alias
{
    private string $id;
    private array $deprecation = [];
    public function __construct(string $id)
    {
        $this->id = $id;
    }
    public function withId(string $id): static
    {
        $new = clone $this;
        $new->id = $id;
        return $new;
    }
    /**
     * Returns the target name of this alias.
     *
     * @return string The target name
     */
    public function getId(): string
    {
        return $this->id;
    }
    /**
     * Whether this alias is deprecated, that means it should not be referenced anymore.
     *
     * @param string $package The name of the composer package that is triggering the deprecation
     * @param string $version The version of the package that introduced the deprecation
     * @param string $message The deprecation message to use
     *
     * @return $this
     *
     * @throws InvalidArgumentException when the message template is invalid
     */
    public function setDeprecated(string $package, string $version, string $message): static
    {
        if ('' !== $message) {
            if (preg_match('#[\r\n]|\*/#', $message)) {
                throw new InvalidArgumentException('Invalid characters found in deprecation template.');
            }
            if (!str_contains($message, '%alias_id%')) {
                throw new InvalidArgumentException('The deprecation template must contain the "%alias_id%" placeholder.');
            }
        }
        $this->deprecation = ['package' => $package, 'version' => $version, 'message' => $message ?: 'The "%alias_id%" route alias is deprecated. You should stop using it, as it will be removed in the future.'];
        return $this;
    }
    public function isDeprecated(): bool
    {
        return (bool) $this->deprecation;
    }
    /**
     * @param string $name Route name relying on this alias
     */
    public function getDeprecation(string $name): array
    {
        return ['package' => $this->deprecation['package'], 'version' => $this->deprecation['version'], 'message' => str_replace('%alias_id%', $name, $this->deprecation['message'])];
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Routing\DependencyInjection;

use _ContaoManager\Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerBuilder;
use _ContaoManager\Symfony\Component\DependencyInjection\Reference;
/**
 * Registers the expression language providers.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class AddExpressionLanguageProvidersPass implements CompilerPassInterface
{
    public function process(ContainerBuilder $container): void
    {
        if (!$container->has('router.default')) {
            return;
        }
        $definition = $container->findDefinition('router.default');
        foreach ($container->findTaggedServiceIds('routing.expression_language_provider', \true) as $id => $attributes) {
            $definition->addMethodCall('addExpressionLanguageProvider', [new Reference($id)]);
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Routing\DependencyInjection;

use _ContaoManager\Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Compiler\PriorityTaggedServiceTrait;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerBuilder;
use _ContaoManager\Symfony\Component\DependencyInjection\Reference;
/**
 * Adds tagged routing.loader services to routing.resolver service.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class RoutingResolverPass implements CompilerPassInterface
{
    use PriorityTaggedServiceTrait;
    /**
     * @return void
     */
    public function process(ContainerBuilder $container)
    {
        if (\false === $container->hasDefinition('routing.resolver')) {
            return;
        }
        $definition = $container->getDefinition('routing.resolver');
        foreach ($this->findAndSortTaggedServices('routing.loader', $container) as $id) {
            $definition->addMethodCall('addLoader', [new Reference($id)]);
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Routing\Exception;

/**
 * The resource was not found.
 *
 * This exception should trigger an HTTP 404 response in your application code.
 *
 * @author Kris Wallsmith <kris@symfony.com>
 */
class ResourceNotFoundException extends \RuntimeException implements ExceptionInterface
{
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Routing\Exception;

/**
 * ExceptionInterface.
 *
 * @author Alexandre Salomé <alexandre.salome@gmail.com>
 */
interface ExceptionInterface extends \Throwable
{
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Routing\Exception;

/**
 * Exception thrown when a route does not exist.
 *
 * @author Alexandre Salomé <alexandre.salome@gmail.com>
 */
class RouteNotFoundException extends \InvalidArgumentException implements ExceptionInterface
{
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Routing\Exception;

class RuntimeException extends \RuntimeException implements ExceptionInterface
{
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Routing\Exception;

/**
 * Exception thrown when a route cannot be generated because of missing
 * mandatory parameters.
 *
 * @author Alexandre Salomé <alexandre.salome@gmail.com>
 */
class MissingMandatoryParametersException extends \InvalidArgumentException implements ExceptionInterface
{
    private string $routeName = '';
    private array $missingParameters = [];
    /**
     * @param string[] $missingParameters
     * @param int      $code
     */
    public function __construct(string $routeName = '', $missingParameters = null, $code = 0, ?\Throwable $previous = null)
    {
        if (\is_array($missingParameters)) {
            $this->routeName = $routeName;
            $this->missingParameters = $missingParameters;
            $message = \sprintf('Some mandatory parameters are missing ("%s") to generate a URL for route "%s".', implode('", "', $missingParameters), $routeName);
        } else {
            trigger_deprecation('symfony/routing', '6.1', 'Construction of "%s" with an exception message is deprecated, provide the route name and an array of missing parameters instead.', __CLASS__);
            $message = $routeName;
            $previous = $code instanceof \Throwable ? $code : null;
            $code = (int) $missingParameters;
        }
        parent::__construct($message, $code, $previous);
    }
    /**
     * @return string[]
     */
    public function getMissingParameters(): array
    {
        return $this->missingParameters;
    }
    public function getRouteName(): string
    {
        return $this->routeName;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Routing\Exception;

class InvalidArgumentException extends \InvalidArgumentException implements ExceptionInterface
{
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Routing\Exception;

/**
 * The resource was found but the request method is not allowed.
 *
 * This exception should trigger an HTTP 405 response in your application code.
 *
 * @author Kris Wallsmith <kris@symfony.com>
 */
class MethodNotAllowedException extends \RuntimeException implements ExceptionInterface
{
    protected $allowedMethods = [];
    /**
     * @param string[] $allowedMethods
     */
    public function __construct(array $allowedMethods, string $message = '', int $code = 0, ?\Throwable $previous = null)
    {
        $this->allowedMethods = array_map('strtoupper', $allowedMethods);
        parent::__construct($message, $code, $previous);
    }
    /**
     * Gets the allowed HTTP methods.
     *
     * @return string[]
     */
    public function getAllowedMethods(): array
    {
        return $this->allowedMethods;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Routing\Exception;

/**
 * Exception thrown when no routes are configured.
 *
 * @author Yonel Ceruto <yonelceruto@gmail.com>
 */
class NoConfigurationException extends ResourceNotFoundException
{
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Routing\Exception;

class RouteCircularReferenceException extends RuntimeException
{
    public function __construct(string $routeId, array $path)
    {
        parent::__construct(\sprintf('Circular reference detected for route "%s", path: "%s".', $routeId, implode(' -> ', $path)));
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Routing\Exception;

/**
 * Exception thrown when a parameter is not valid.
 *
 * @author Alexandre Salomé <alexandre.salome@gmail.com>
 */
class InvalidParameterException extends \InvalidArgumentException implements ExceptionInterface
{
}
{
    "name": "symfony\/routing",
    "type": "library",
    "description": "Maps an HTTP request to a set of configuration variables",
    "keywords": [
        "routing",
        "router",
        "url",
        "uri"
    ],
    "homepage": "https:\/\/symfony.com",
    "license": "MIT",
    "authors": [
        {
            "name": "Fabien Potencier",
            "email": "fabien@symfony.com"
        },
        {
            "name": "Symfony Community",
            "homepage": "https:\/\/symfony.com\/contributors"
        }
    ],
    "require": {
        "php": ">=8.1",
        "symfony\/deprecation-contracts": "^2.5|^3"
    },
    "require-dev": {
        "symfony\/config": "^6.2|^7.0",
        "symfony\/http-foundation": "^5.4|^6.0|^7.0",
        "symfony\/yaml": "^5.4|^6.0|^7.0",
        "symfony\/expression-language": "^5.4|^6.0|^7.0",
        "symfony\/dependency-injection": "^5.4|^6.0|^7.0",
        "doctrine\/annotations": "^1.12|^2",
        "psr\/log": "^1|^2|^3"
    },
    "conflict": {
        "doctrine\/annotations": "<1.12",
        "symfony\/config": "<6.2",
        "symfony\/dependency-injection": "<5.4",
        "symfony\/yaml": "<5.4"
    },
    "autoload": {
        "psr-4": {
            "_ContaoManager\\Symfony\\Component\\Routing\\": ""
        },
        "exclude-from-classmap": [
            "\/Tests\/"
        ]
    },
    "minimum-stability": "dev"
}<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Contracts\Service;

use _ContaoManager\Symfony\Contracts\Service\Attribute\SubscribedService;
/**
 * A ServiceSubscriber exposes its dependencies via the static {@link getSubscribedServices} method.
 *
 * The getSubscribedServices method returns an array of service types required by such instances,
 * optionally keyed by the service names used internally. Service types that start with an interrogation
 * mark "?" are optional, while the other ones are mandatory service dependencies.
 *
 * The injected service locators SHOULD NOT allow access to any other services not specified by the method.
 *
 * It is expected that ServiceSubscriber instances consume PSR-11-based service locators internally.
 * This interface does not dictate any injection method for these service locators, although constructor
 * injection is recommended.
 *
 * @author Nicolas Grekas <p@tchwork.com>
 */
interface ServiceSubscriberInterface
{
    /**
     * Returns an array of service types (or {@see SubscribedService} objects) required
     * by such instances, optionally keyed by the service names used internally.
     *
     * For mandatory dependencies:
     *
     *  * ['logger' => 'Psr\Log\LoggerInterface'] means the objects use the "logger" name
     *    internally to fetch a service which must implement Psr\Log\LoggerInterface.
     *  * ['loggers' => 'Psr\Log\LoggerInterface[]'] means the objects use the "loggers" name
     *    internally to fetch an iterable of Psr\Log\LoggerInterface instances.
     *  * ['Psr\Log\LoggerInterface'] is a shortcut for
     *  * ['Psr\Log\LoggerInterface' => 'Psr\Log\LoggerInterface']
     *
     * otherwise:
     *
     *  * ['logger' => '?Psr\Log\LoggerInterface'] denotes an optional dependency
     *  * ['loggers' => '?Psr\Log\LoggerInterface[]'] denotes an optional iterable dependency
     *  * ['?Psr\Log\LoggerInterface'] is a shortcut for
     *  * ['Psr\Log\LoggerInterface' => '?Psr\Log\LoggerInterface']
     *
     * additionally, an array of {@see SubscribedService}'s can be returned:
     *
     *  * [new SubscribedService('logger', Psr\Log\LoggerInterface::class)]
     *  * [new SubscribedService(type: Psr\Log\LoggerInterface::class, nullable: true)]
     *  * [new SubscribedService('http_client', HttpClientInterface::class, attributes: new Target('githubApi'))]
     *
     * @return string[]|SubscribedService[] The required service types, optionally keyed by service names
     */
    public static function getSubscribedServices(): array;
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Contracts\Service;

/**
 * A ServiceProviderInterface that is also countable and iterable.
 *
 * @author Kevin Bond <kevinbond@gmail.com>
 *
 * @template-covariant T of mixed
 *
 * @extends ServiceProviderInterface<T>
 * @extends \IteratorAggregate<string, T>
 */
interface ServiceCollectionInterface extends ServiceProviderInterface, \Countable, \IteratorAggregate
{
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Contracts\Service\Attribute;

use _ContaoManager\Symfony\Contracts\Service\ServiceMethodsSubscriberTrait;
use _ContaoManager\Symfony\Contracts\Service\ServiceSubscriberInterface;
/**
 * For use as the return value for {@see ServiceSubscriberInterface}.
 *
 * @example new SubscribedService('http_client', HttpClientInterface::class, false, new Target('githubApi'))
 *
 * Use with {@see ServiceMethodsSubscriberTrait} to mark a method's return type
 * as a subscribed service.
 *
 * @author Kevin Bond <kevinbond@gmail.com>
 */
#[\Attribute(\Attribute::TARGET_METHOD)]
final class SubscribedService
{
    /** @var object[] */
    public array $attributes;
    /**
     * @param string|null       $key        The key to use for the service
     * @param class-string|null $type       The service class
     * @param bool              $nullable   Whether the service is optional
     * @param object|object[]   $attributes One or more dependency injection attributes to use
     */
    public function __construct(public ?string $key = null, public ?string $type = null, public bool $nullable = \false, array|object $attributes = [])
    {
        $this->attributes = \is_array($attributes) ? $attributes : [$attributes];
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Contracts\Service\Attribute;

/**
 * A required dependency.
 *
 * This attribute indicates that a property holds a required dependency. The annotated property or method should be
 * considered during the instantiation process of the containing class.
 *
 * @author Alexander M. Turek <me@derrabus.de>
 */
#[\Attribute(\Attribute::TARGET_METHOD | \Attribute::TARGET_PROPERTY)]
final class Required
{
}
Copyright (c) 2018-present Fabien Potencier

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is furnished
to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Contracts\Service\Test;

use _ContaoManager\PHPUnit\Framework\TestCase;
use _ContaoManager\Psr\Container\ContainerExceptionInterface;
use _ContaoManager\Psr\Container\ContainerInterface;
use _ContaoManager\Psr\Container\NotFoundExceptionInterface;
use _ContaoManager\Symfony\Contracts\Service\ServiceLocatorTrait;
abstract class ServiceLocatorTestCase extends TestCase
{
    /**
     * @param array<string, callable> $factories
     */
    protected function getServiceLocator(array $factories): ContainerInterface
    {
        return new class($factories) implements ContainerInterface
        {
            use ServiceLocatorTrait;
        };
    }
    public function testHas()
    {
        $locator = $this->getServiceLocator(['foo' => fn() => 'bar', 'bar' => fn() => 'baz', fn() => 'dummy']);
        $this->assertTrue($locator->has('foo'));
        $this->assertTrue($locator->has('bar'));
        $this->assertFalse($locator->has('dummy'));
    }
    public function testGet()
    {
        $locator = $this->getServiceLocator(['foo' => fn() => 'bar', 'bar' => fn() => 'baz']);
        $this->assertSame('bar', $locator->get('foo'));
        $this->assertSame('baz', $locator->get('bar'));
    }
    public function testGetDoesNotMemoize()
    {
        $i = 0;
        $locator = $this->getServiceLocator(['foo' => function () use (&$i) {
            ++$i;
            return 'bar';
        }]);
        $this->assertSame('bar', $locator->get('foo'));
        $this->assertSame('bar', $locator->get('foo'));
        $this->assertSame(2, $i);
    }
    public function testThrowsOnUndefinedInternalService()
    {
        $locator = $this->getServiceLocator(['foo' => function () use (&$locator) {
            return $locator->get('bar');
        }]);
        $this->expectException(NotFoundExceptionInterface::class);
        $this->expectExceptionMessage('The service "foo" has a dependency on a non-existent service "bar". This locator only knows about the "foo" service.');
        $locator->get('foo');
    }
    public function testThrowsOnCircularReference()
    {
        $locator = $this->getServiceLocator(['foo' => function () use (&$locator) {
            return $locator->get('bar');
        }, 'bar' => function () use (&$locator) {
            return $locator->get('baz');
        }, 'baz' => function () use (&$locator) {
            return $locator->get('bar');
        }]);
        $this->expectException(ContainerExceptionInterface::class);
        $this->expectExceptionMessage('Circular reference detected for service "bar", path: "bar -> baz -> bar".');
        $locator->get('foo');
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Contracts\Service\Test;

class_alias(ServiceLocatorTestCase::class, ServiceLocatorTest::class);
if (\false) {
    /**
     * @deprecated since PHPUnit 9.6
     */
    class ServiceLocatorTest
    {
    }
}
CHANGELOG
=========

The changelog is maintained for all Symfony contracts at the following URL:
https://github.com/symfony/contracts/blob/main/CHANGELOG.md
Symfony Service Contracts
=========================

A set of abstractions extracted out of the Symfony components.

Can be used to build on semantics that the Symfony components proved useful and
that already have battle tested implementations.

See https://github.com/symfony/contracts/blob/main/README.md for more information.
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Contracts\Service;

/**
 * Provides a way to reset an object to its initial state.
 *
 * When calling the "reset()" method on an object, it should be put back to its
 * initial state. This usually means clearing any internal buffers and forwarding
 * the call to internal dependencies. All properties of the object should be put
 * back to the same state it had when it was first ready to use.
 *
 * This method could be called, for example, to recycle objects that are used as
 * services, so that they can be used to handle several requests in the same
 * process loop (note that we advise making your services stateless instead of
 * implementing this interface when possible.)
 */
interface ResetInterface
{
    /**
     * @return void
     */
    public function reset();
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Contracts\Service;

use _ContaoManager\Psr\Container\ContainerInterface;
/**
 * A ServiceProviderInterface exposes the identifiers and the types of services provided by a container.
 *
 * @author Nicolas Grekas <p@tchwork.com>
 * @author Mateusz Sip <mateusz.sip@gmail.com>
 *
 * @template-covariant T of mixed
 */
interface ServiceProviderInterface extends ContainerInterface
{
    /**
     * @return T
     */
    public function get(string $id): mixed;
    public function has(string $id): bool;
    /**
     * Returns an associative array of service types keyed by the identifiers provided by the current container.
     *
     * Examples:
     *
     *  * ['logger' => 'Psr\Log\LoggerInterface'] means the object provides a service named "logger" that implements Psr\Log\LoggerInterface
     *  * ['foo' => '?'] means the container provides service name "foo" of unspecified type
     *  * ['bar' => '?Bar\Baz'] means the container provides a service "bar" of type Bar\Baz|null
     *
     * @return array<string, string> The provided service types, keyed by service names
     */
    public function getProvidedServices(): array;
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Contracts\Service;

use _ContaoManager\Psr\Container\ContainerInterface;
use _ContaoManager\Symfony\Contracts\Service\Attribute\Required;
use _ContaoManager\Symfony\Contracts\Service\Attribute\SubscribedService;
trigger_deprecation('symfony/contracts', 'v3.5', '"%s" is deprecated, use "ServiceMethodsSubscriberTrait" instead.', ServiceSubscriberTrait::class);
/**
 * Implementation of ServiceSubscriberInterface that determines subscribed services
 * from methods that have the #[SubscribedService] attribute.
 *
 * Service ids are available as "ClassName::methodName" so that the implementation
 * of subscriber methods can be just `return $this->container->get(__METHOD__);`.
 *
 * @property ContainerInterface $container
 *
 * @author Kevin Bond <kevinbond@gmail.com>
 *
 * @deprecated since symfony/contracts v3.5, use ServiceMethodsSubscriberTrait instead
 */
trait ServiceSubscriberTrait
{
    public static function getSubscribedServices(): array
    {
        $services = method_exists(get_parent_class(self::class) ?: '', __FUNCTION__) ? parent::getSubscribedServices() : [];
        foreach ((new \ReflectionClass(self::class))->getMethods() as $method) {
            if (self::class !== $method->getDeclaringClass()->name) {
                continue;
            }
            if (!$attribute = $method->getAttributes(SubscribedService::class)[0] ?? null) {
                continue;
            }
            if ($method->isStatic() || $method->isAbstract() || $method->isGenerator() || $method->isInternal() || $method->getNumberOfRequiredParameters()) {
                throw new \LogicException(\sprintf('Cannot use "%s" on method "%s::%s()" (can only be used on non-static, non-abstract methods with no parameters).', SubscribedService::class, self::class, $method->name));
            }
            if (!$returnType = $method->getReturnType()) {
                throw new \LogicException(\sprintf('Cannot use "%s" on methods without a return type in "%s::%s()".', SubscribedService::class, $method->name, self::class));
            }
            /** @var SubscribedService $attribute */
            $attribute = $attribute->newInstance();
            $attribute->key ??= self::class . '::' . $method->name;
            $attribute->type ??= $returnType instanceof \ReflectionNamedType ? $returnType->getName() : (string) $returnType;
            $attribute->nullable = $attribute->nullable ?: $returnType->allowsNull();
            if ($attribute->attributes) {
                $services[] = $attribute;
            } else {
                $services[$attribute->key] = ($attribute->nullable ? '?' : '') . $attribute->type;
            }
        }
        return $services;
    }
    #[Required]
    public function setContainer(ContainerInterface $container): ?ContainerInterface
    {
        $ret = null;
        if (method_exists(get_parent_class(self::class) ?: '', __FUNCTION__)) {
            $ret = parent::setContainer($container);
        }
        $this->container = $container;
        return $ret;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Contracts\Service;

use _ContaoManager\Psr\Container\ContainerInterface;
use _ContaoManager\Symfony\Contracts\Service\Attribute\Required;
use _ContaoManager\Symfony\Contracts\Service\Attribute\SubscribedService;
/**
 * Implementation of ServiceSubscriberInterface that determines subscribed services
 * from methods that have the #[SubscribedService] attribute.
 *
 * Service ids are available as "ClassName::methodName" so that the implementation
 * of subscriber methods can be just `return $this->container->get(__METHOD__);`.
 *
 * @author Kevin Bond <kevinbond@gmail.com>
 */
trait ServiceMethodsSubscriberTrait
{
    protected ContainerInterface $container;
    public static function getSubscribedServices(): array
    {
        $services = method_exists(get_parent_class(self::class) ?: '', __FUNCTION__) ? parent::getSubscribedServices() : [];
        foreach ((new \ReflectionClass(self::class))->getMethods() as $method) {
            if (self::class !== $method->getDeclaringClass()->name) {
                continue;
            }
            if (!$attribute = $method->getAttributes(SubscribedService::class)[0] ?? null) {
                continue;
            }
            if ($method->isStatic() || $method->isAbstract() || $method->isGenerator() || $method->isInternal() || $method->getNumberOfRequiredParameters()) {
                throw new \LogicException(\sprintf('Cannot use "%s" on method "%s::%s()" (can only be used on non-static, non-abstract methods with no parameters).', SubscribedService::class, self::class, $method->name));
            }
            if (!$returnType = $method->getReturnType()) {
                throw new \LogicException(\sprintf('Cannot use "%s" on methods without a return type in "%s::%s()".', SubscribedService::class, $method->name, self::class));
            }
            /* @var SubscribedService $attribute */
            $attribute = $attribute->newInstance();
            $attribute->key ??= self::class . '::' . $method->name;
            $attribute->type ??= $returnType instanceof \ReflectionNamedType ? $returnType->getName() : (string) $returnType;
            $attribute->nullable = $attribute->nullable ?: $returnType->allowsNull();
            if ($attribute->attributes) {
                $services[] = $attribute;
            } else {
                $services[$attribute->key] = ($attribute->nullable ? '?' : '') . $attribute->type;
            }
        }
        return $services;
    }
    #[Required]
    public function setContainer(ContainerInterface $container): ?ContainerInterface
    {
        $ret = null;
        if (method_exists(get_parent_class(self::class) ?: '', __FUNCTION__)) {
            $ret = parent::setContainer($container);
        }
        $this->container = $container;
        return $ret;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Contracts\Service;

use _ContaoManager\Psr\Container\ContainerExceptionInterface;
use _ContaoManager\Psr\Container\NotFoundExceptionInterface;
// Help opcache.preload discover always-needed symbols
class_exists(ContainerExceptionInterface::class);
class_exists(NotFoundExceptionInterface::class);
/**
 * A trait to help implement ServiceProviderInterface.
 *
 * @author Robin Chalas <robin.chalas@gmail.com>
 * @author Nicolas Grekas <p@tchwork.com>
 */
trait ServiceLocatorTrait
{
    private array $loading = [];
    private array $providedTypes;
    /**
     * @param array<string, callable> $factories
     */
    public function __construct(private array $factories)
    {
    }
    public function has(string $id): bool
    {
        return isset($this->factories[$id]);
    }
    public function get(string $id): mixed
    {
        if (!isset($this->factories[$id])) {
            throw $this->createNotFoundException($id);
        }
        if (isset($this->loading[$id])) {
            $ids = array_values($this->loading);
            $ids = \array_slice($this->loading, array_search($id, $ids));
            $ids[] = $id;
            throw $this->createCircularReferenceException($id, $ids);
        }
        $this->loading[$id] = $id;
        try {
            return $this->factories[$id]($this);
        } finally {
            unset($this->loading[$id]);
        }
    }
    public function getProvidedServices(): array
    {
        if (!isset($this->providedTypes)) {
            $this->providedTypes = [];
            foreach ($this->factories as $name => $factory) {
                if (!\is_callable($factory)) {
                    $this->providedTypes[$name] = '?';
                } else {
                    $type = (new \ReflectionFunction($factory))->getReturnType();
                    $this->providedTypes[$name] = $type ? ($type->allowsNull() ? '?' : '') . ($type instanceof \ReflectionNamedType ? $type->getName() : $type) : '?';
                }
            }
        }
        return $this->providedTypes;
    }
    private function createNotFoundException(string $id): NotFoundExceptionInterface
    {
        if (!$alternatives = array_keys($this->factories)) {
            $message = 'is empty...';
        } else {
            $last = array_pop($alternatives);
            if ($alternatives) {
                $message = \sprintf('only knows about the "%s" and "%s" services.', implode('", "', $alternatives), $last);
            } else {
                $message = \sprintf('only knows about the "%s" service.', $last);
            }
        }
        if ($this->loading) {
            $message = \sprintf('The service "%s" has a dependency on a non-existent service "%s". This locator %s', end($this->loading), $id, $message);
        } else {
            $message = \sprintf('Service "%s" not found: the current service locator %s', $id, $message);
        }
        return new class($message) extends \InvalidArgumentException implements NotFoundExceptionInterface
        {
        };
    }
    private function createCircularReferenceException(string $id, array $path): ContainerExceptionInterface
    {
        return new class(\sprintf('Circular reference detected for service "%s", path: "%s".', $id, implode(' -> ', $path))) extends \RuntimeException implements ContainerExceptionInterface
        {
        };
    }
}
{
    "name": "symfony\/service-contracts",
    "type": "library",
    "description": "Generic abstractions related to writing services",
    "keywords": [
        "abstractions",
        "contracts",
        "decoupling",
        "interfaces",
        "interoperability",
        "standards"
    ],
    "homepage": "https:\/\/symfony.com",
    "license": "MIT",
    "authors": [
        {
            "name": "Nicolas Grekas",
            "email": "p@tchwork.com"
        },
        {
            "name": "Symfony Community",
            "homepage": "https:\/\/symfony.com\/contributors"
        }
    ],
    "require": {
        "php": ">=8.1",
        "psr\/container": "^1.1|^2.0",
        "symfony\/deprecation-contracts": "^2.5|^3"
    },
    "conflict": {
        "ext-psr": "<1.1|>=2"
    },
    "autoload": {
        "psr-4": {
            "_ContaoManager\\Symfony\\Contracts\\Service\\": ""
        },
        "exclude-from-classmap": [
            "\/Test\/"
        ]
    },
    "minimum-stability": "dev",
    "extra": {
        "branch-alias": {
            "dev-main": "3.6-dev"
        },
        "thanks": {
            "name": "symfony\/contracts",
            "url": "https:\/\/github.com\/symfony\/contracts"
        }
    }
}<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\PropertyInfo\PhpStan;

use _ContaoManager\phpDocumentor\Reflection\Types\ContextFactory;
/**
 * @author Baptiste Leduc <baptiste.leduc@gmail.com>
 *
 * @internal
 */
final class NameScopeFactory
{
    public function create(string $calledClassName, ?string $declaringClassName = null): NameScope
    {
        $declaringClassName ??= $calledClassName;
        $path = explode('\\', $calledClassName);
        $calledClassName = array_pop($path);
        $declaringReflection = new \ReflectionClass($declaringClassName);
        [$declaringNamespace, $declaringUses] = $this->extractFromFullClassName($declaringReflection);
        $declaringUses = array_merge($declaringUses, $this->collectUses($declaringReflection));
        return new NameScope($calledClassName, $declaringNamespace, $declaringUses);
    }
    private function collectUses(\ReflectionClass $reflection): array
    {
        $uses = [$this->extractFromFullClassName($reflection)[1]];
        foreach ($reflection->getTraits() as $traitReflection) {
            $uses[] = $this->extractFromFullClassName($traitReflection)[1];
        }
        if (\false !== $parentClass = $reflection->getParentClass()) {
            $uses[] = $this->collectUses($parentClass);
        }
        return $uses ? array_merge(...$uses) : [];
    }
    private function extractFromFullClassName(\ReflectionClass $reflection): array
    {
        $namespace = trim($reflection->getNamespaceName(), '\\');
        $fileName = $reflection->getFileName();
        if (\is_string($fileName) && is_file($fileName)) {
            if (\false === $contents = file_get_contents($fileName)) {
                throw new \RuntimeException(\sprintf('Unable to read file "%s".', $fileName));
            }
            $factory = new ContextFactory();
            $context = $factory->createForNamespace($namespace, $contents);
            return [$namespace, $context->getNamespaceAliases()];
        }
        return [$namespace, []];
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\PropertyInfo\PhpStan;

/**
 * NameScope class adapted from PHPStan code.
 *
 * @copyright Copyright (c) 2016, PHPStan https://github.com/phpstan/phpstan-src
 * @copyright Copyright (c) 2016, Ondřej Mirtes
 * @author Baptiste Leduc <baptiste.leduc@gmail.com>
 *
 * @internal
 */
final class NameScope
{
    private string $calledClassName;
    private string $namespace;
    /** @var array<string, string> alias(string) => fullName(string) */
    private array $uses;
    public function __construct(string $calledClassName, string $namespace, array $uses = [])
    {
        $this->calledClassName = $calledClassName;
        $this->namespace = $namespace;
        $this->uses = $uses;
    }
    public function resolveStringName(string $name): string
    {
        if (str_starts_with($name, '\\')) {
            return ltrim($name, '\\');
        }
        $nameParts = explode('\\', $name);
        $firstNamePart = $nameParts[0];
        if (isset($this->uses[$firstNamePart])) {
            if (1 === \count($nameParts)) {
                return $this->uses[$firstNamePart];
            }
            array_shift($nameParts);
            return \sprintf('%s\%s', $this->uses[$firstNamePart], implode('\\', $nameParts));
        }
        if (null !== $this->namespace) {
            return \sprintf('%s\%s', $this->namespace, $name);
        }
        return $name;
    }
    public function resolveRootClass(): string
    {
        return $this->resolveStringName($this->calledClassName);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\PropertyInfo;

/**
 * Gets info about PHP class properties.
 *
 * A convenient interface inheriting all specific info interfaces.
 *
 * @author Kévin Dunglas <dunglas@gmail.com>
 */
interface PropertyInfoExtractorInterface extends PropertyTypeExtractorInterface, PropertyDescriptionExtractorInterface, PropertyAccessExtractorInterface, PropertyListExtractorInterface
{
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\PropertyInfo;

/**
 * Type value object (immutable).
 *
 * @author Kévin Dunglas <dunglas@gmail.com>
 *
 * @final
 */
class Type
{
    public const BUILTIN_TYPE_INT = 'int';
    public const BUILTIN_TYPE_FLOAT = 'float';
    public const BUILTIN_TYPE_STRING = 'string';
    public const BUILTIN_TYPE_BOOL = 'bool';
    public const BUILTIN_TYPE_RESOURCE = 'resource';
    public const BUILTIN_TYPE_OBJECT = 'object';
    public const BUILTIN_TYPE_ARRAY = 'array';
    public const BUILTIN_TYPE_NULL = 'null';
    public const BUILTIN_TYPE_FALSE = 'false';
    public const BUILTIN_TYPE_TRUE = 'true';
    public const BUILTIN_TYPE_CALLABLE = 'callable';
    public const BUILTIN_TYPE_ITERABLE = 'iterable';
    /**
     * List of PHP builtin types.
     *
     * @var string[]
     */
    public static $builtinTypes = [self::BUILTIN_TYPE_INT, self::BUILTIN_TYPE_FLOAT, self::BUILTIN_TYPE_STRING, self::BUILTIN_TYPE_BOOL, self::BUILTIN_TYPE_RESOURCE, self::BUILTIN_TYPE_OBJECT, self::BUILTIN_TYPE_ARRAY, self::BUILTIN_TYPE_CALLABLE, self::BUILTIN_TYPE_FALSE, self::BUILTIN_TYPE_TRUE, self::BUILTIN_TYPE_NULL, self::BUILTIN_TYPE_ITERABLE];
    /**
     * List of PHP builtin collection types.
     *
     * @var string[]
     */
    public static $builtinCollectionTypes = [self::BUILTIN_TYPE_ARRAY, self::BUILTIN_TYPE_ITERABLE];
    private string $builtinType;
    private bool $nullable;
    private ?string $class;
    private bool $collection;
    private array $collectionKeyType;
    private array $collectionValueType;
    /**
     * @param Type[]|Type|null $collectionKeyType
     * @param Type[]|Type|null $collectionValueType
     *
     * @throws \InvalidArgumentException
     */
    public function __construct(string $builtinType, bool $nullable = \false, ?string $class = null, bool $collection = \false, array|self|null $collectionKeyType = null, array|self|null $collectionValueType = null)
    {
        if (!\in_array($builtinType, self::$builtinTypes)) {
            throw new \InvalidArgumentException(\sprintf('"%s" is not a valid PHP type.', $builtinType));
        }
        $this->builtinType = $builtinType;
        $this->nullable = $nullable;
        $this->class = $class;
        $this->collection = $collection;
        $this->collectionKeyType = $this->validateCollectionArgument($collectionKeyType, 5, '$collectionKeyType') ?? [];
        $this->collectionValueType = $this->validateCollectionArgument($collectionValueType, 6, '$collectionValueType') ?? [];
    }
    private function validateCollectionArgument(array|self|null $collectionArgument, int $argumentIndex, string $argumentName): ?array
    {
        if (null === $collectionArgument) {
            return null;
        }
        if (\is_array($collectionArgument)) {
            foreach ($collectionArgument as $type) {
                if (!$type instanceof self) {
                    throw new \TypeError(\sprintf('"%s()": Argument #%d (%s) must be of type "%s[]", "%s" or "null", array value "%s" given.', __METHOD__, $argumentIndex, $argumentName, self::class, self::class, get_debug_type($collectionArgument)));
                }
            }
            return $collectionArgument;
        }
        return [$collectionArgument];
    }
    /**
     * Gets built-in type.
     *
     * Can be bool, int, float, string, array, object, resource, null, callback or iterable.
     */
    public function getBuiltinType(): string
    {
        return $this->builtinType;
    }
    public function isNullable(): bool
    {
        return $this->nullable;
    }
    /**
     * Gets the class name.
     *
     * Only applicable if the built-in type is object.
     */
    public function getClassName(): ?string
    {
        return $this->class;
    }
    public function isCollection(): bool
    {
        return $this->collection;
    }
    /**
     * Gets collection key types.
     *
     * Only applicable for a collection type.
     *
     * @return Type[]
     */
    public function getCollectionKeyTypes(): array
    {
        return $this->collectionKeyType;
    }
    /**
     * Gets collection value types.
     *
     * Only applicable for a collection type.
     *
     * @return Type[]
     */
    public function getCollectionValueTypes(): array
    {
        return $this->collectionValueType;
    }
}
Copyright (c) 2015-present Fabien Potencier

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is furnished
to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\PropertyInfo\Util;

use _ContaoManager\phpDocumentor\Reflection\PseudoType;
use _ContaoManager\phpDocumentor\Reflection\PseudoTypes\ConstExpression;
use _ContaoManager\phpDocumentor\Reflection\PseudoTypes\List_;
use _ContaoManager\phpDocumentor\Reflection\Type as DocType;
use _ContaoManager\phpDocumentor\Reflection\Types\Array_;
use _ContaoManager\phpDocumentor\Reflection\Types\Collection;
use _ContaoManager\phpDocumentor\Reflection\Types\Compound;
use _ContaoManager\phpDocumentor\Reflection\Types\Integer;
use _ContaoManager\phpDocumentor\Reflection\Types\Mixed_;
use _ContaoManager\phpDocumentor\Reflection\Types\Null_;
use _ContaoManager\phpDocumentor\Reflection\Types\Nullable;
use _ContaoManager\phpDocumentor\Reflection\Types\Scalar;
use _ContaoManager\phpDocumentor\Reflection\Types\String_;
use _ContaoManager\Symfony\Component\PropertyInfo\Type;
// Workaround for phpdocumentor/type-resolver < 1.6
// We trigger the autoloader here, so we don't need to trigger it inside the loop later.
class_exists(List_::class);
/**
 * Transforms a php doc type to a {@link Type} instance.
 *
 * @author Kévin Dunglas <dunglas@gmail.com>
 * @author Guilhem N. <egetick@gmail.com>
 */
final class PhpDocTypeHelper
{
    /**
     * Creates a {@see Type} from a PHPDoc type.
     *
     * @return Type[]
     */
    public function getTypes(DocType $varType): array
    {
        if ($varType instanceof ConstExpression) {
            // It's safer to fall back to other extractors here, as resolving const types correctly is not easy at the moment
            return [];
        }
        $types = [];
        $nullable = \false;
        if ($varType instanceof Nullable) {
            $nullable = \true;
            $varType = $varType->getActualType();
        }
        if ($varType instanceof Scalar) {
            return [new Type(Type::BUILTIN_TYPE_BOOL), new Type(Type::BUILTIN_TYPE_FLOAT), new Type(Type::BUILTIN_TYPE_INT), new Type(Type::BUILTIN_TYPE_STRING)];
        }
        if (!$varType instanceof Compound) {
            if ($varType instanceof Null_) {
                $nullable = \true;
            }
            $type = $this->createType($varType, $nullable);
            if (null !== $type) {
                $types[] = $type;
            }
            return $types;
        }
        $varTypes = [];
        for ($typeIndex = 0; $varType->has($typeIndex); ++$typeIndex) {
            $type = $varType->get($typeIndex);
            if ($type instanceof Mixed_) {
                return [];
            }
            if ($type instanceof ConstExpression) {
                // It's safer to fall back to other extractors here, as resolving const types correctly is not easy at the moment
                return [];
            }
            // If null is present, all types are nullable
            if ($type instanceof Null_) {
                $nullable = \true;
                continue;
            }
            if ($type instanceof Nullable) {
                $nullable = \true;
                $type = $type->getActualType();
            }
            $varTypes[] = $type;
        }
        foreach ($varTypes as $varType) {
            $type = $this->createType($varType, $nullable);
            if (null !== $type) {
                $types[] = $type;
            }
        }
        return $types;
    }
    /**
     * Creates a {@see Type} from a PHPDoc type.
     */
    private function createType(DocType $type, bool $nullable): ?Type
    {
        $docType = (string) $type;
        if ('mixed[]' === $docType) {
            $docType = 'array';
        }
        if ($type instanceof Collection) {
            $fqsen = $type->getFqsen();
            if ($fqsen && 'list' === $fqsen->getName() && !class_exists(List_::class, \false) && !class_exists((string) $fqsen)) {
                // Workaround for phpdocumentor/type-resolver < 1.6
                return new Type(Type::BUILTIN_TYPE_ARRAY, $nullable, null, \true, new Type(Type::BUILTIN_TYPE_INT), $this->getTypes($type->getValueType()));
            }
            [$phpType, $class] = $this->getPhpTypeAndClass((string) $fqsen);
            $collection = is_a($class, \Traversable::class, \true) || is_a($class, \ArrayAccess::class, \true);
            // it's safer to fall back to other extractors if the generic type is too abstract
            if (!$collection && !class_exists($class)) {
                return null;
            }
            $keys = $this->getTypes($type->getKeyType());
            $values = $this->getTypes($type->getValueType());
            return new Type($phpType, $nullable, $class, $collection, $keys, $values);
        }
        // Cannot guess
        if (!$docType || 'mixed' === $docType) {
            return null;
        }
        if (str_ends_with($docType, '[]') && $type instanceof Array_) {
            $collectionKeyTypes = new Type(Type::BUILTIN_TYPE_INT);
            $collectionValueTypes = $this->getTypes($type->getValueType());
            return new Type(Type::BUILTIN_TYPE_ARRAY, $nullable, null, \true, $collectionKeyTypes, $collectionValueTypes);
        }
        if ((str_starts_with($docType, 'list<') || str_starts_with($docType, 'array<')) && $type instanceof Array_) {
            // array<value> is converted to x[] which is handled above
            // so it's only necessary to handle array<key, value> here
            $collectionKeyTypes = $this->getTypes($type->getKeyType());
            $collectionValueTypes = $this->getTypes($type->getValueType());
            return new Type(Type::BUILTIN_TYPE_ARRAY, $nullable, null, \true, $collectionKeyTypes, $collectionValueTypes);
        }
        $docType = $this->normalizeType($docType);
        [$phpType, $class] = $this->getPhpTypeAndClass($docType);
        if ('array' === $docType) {
            return new Type(Type::BUILTIN_TYPE_ARRAY, $nullable, null, \true, null, null);
        }
        if (null === $class) {
            return new Type($phpType, $nullable, $class);
        }
        if ($type instanceof PseudoType) {
            if ($type->underlyingType() instanceof Integer) {
                return new Type(Type::BUILTIN_TYPE_INT, $nullable, null);
            } elseif ($type->underlyingType() instanceof String_) {
                return new Type(Type::BUILTIN_TYPE_STRING, $nullable, null);
            } else {
                // It's safer to fall back to other extractors here, as resolving pseudo types correctly is not easy at the moment
                return null;
            }
        }
        return new Type($phpType, $nullable, $class);
    }
    private function normalizeType(string $docType): string
    {
        return match ($docType) {
            'integer' => 'int',
            'boolean' => 'bool',
            // real is not part of the PHPDoc standard, so we ignore it
            'double' => 'float',
            'callback' => 'callable',
            'void' => 'null',
            default => $docType,
        };
    }
    private function getPhpTypeAndClass(string $docType): array
    {
        if (\in_array($docType, Type::$builtinTypes)) {
            return [$docType, null];
        }
        if (\in_array($docType, ['parent', 'self', 'static'], \true)) {
            return ['object', $docType];
        }
        return ['object', ltrim($docType, '\\')];
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\PropertyInfo\Util;

use _ContaoManager\PHPStan\PhpDocParser\Ast\PhpDoc\ParamTagValueNode;
use _ContaoManager\PHPStan\PhpDocParser\Ast\PhpDoc\PhpDocTagValueNode;
use _ContaoManager\PHPStan\PhpDocParser\Ast\PhpDoc\ReturnTagValueNode;
use _ContaoManager\PHPStan\PhpDocParser\Ast\PhpDoc\VarTagValueNode;
use _ContaoManager\PHPStan\PhpDocParser\Ast\Type\ArrayShapeNode;
use _ContaoManager\PHPStan\PhpDocParser\Ast\Type\ArrayTypeNode;
use _ContaoManager\PHPStan\PhpDocParser\Ast\Type\CallableTypeNode;
use _ContaoManager\PHPStan\PhpDocParser\Ast\Type\CallableTypeParameterNode;
use _ContaoManager\PHPStan\PhpDocParser\Ast\Type\ConstTypeNode;
use _ContaoManager\PHPStan\PhpDocParser\Ast\Type\GenericTypeNode;
use _ContaoManager\PHPStan\PhpDocParser\Ast\Type\IdentifierTypeNode;
use _ContaoManager\PHPStan\PhpDocParser\Ast\Type\NullableTypeNode;
use _ContaoManager\PHPStan\PhpDocParser\Ast\Type\ThisTypeNode;
use _ContaoManager\PHPStan\PhpDocParser\Ast\Type\TypeNode;
use _ContaoManager\PHPStan\PhpDocParser\Ast\Type\UnionTypeNode;
use _ContaoManager\Symfony\Component\PropertyInfo\PhpStan\NameScope;
use _ContaoManager\Symfony\Component\PropertyInfo\Type;
/**
 * Transforms a php doc tag value to a {@link Type} instance.
 *
 * @author Baptiste Leduc <baptiste.leduc@gmail.com>
 *
 * @internal
 */
final class PhpStanTypeHelper
{
    /**
     * Creates a {@see Type} from a PhpDocTagValueNode type.
     *
     * @return Type[]
     */
    public function getTypes(PhpDocTagValueNode $node, NameScope $nameScope): array
    {
        if ($node instanceof ParamTagValueNode || $node instanceof ReturnTagValueNode || $node instanceof VarTagValueNode) {
            return $this->compressNullableType($this->extractTypes($node->type, $nameScope));
        }
        return [];
    }
    /**
     * Because PhpStan extract null as a separated type when Symfony / PHP compress it in the first available type we
     * need this method to mimic how Symfony want null types.
     *
     * @param Type[] $types
     *
     * @return Type[]
     */
    private function compressNullableType(array $types): array
    {
        $firstTypeIndex = null;
        $nullableTypeIndex = null;
        foreach ($types as $k => $type) {
            if (null === $firstTypeIndex && Type::BUILTIN_TYPE_NULL !== $type->getBuiltinType() && !$type->isNullable()) {
                $firstTypeIndex = $k;
            }
            if (null === $nullableTypeIndex && Type::BUILTIN_TYPE_NULL === $type->getBuiltinType()) {
                $nullableTypeIndex = $k;
            }
            if (null !== $firstTypeIndex && null !== $nullableTypeIndex) {
                break;
            }
        }
        if (null !== $firstTypeIndex && null !== $nullableTypeIndex) {
            $firstType = $types[$firstTypeIndex];
            $types[$firstTypeIndex] = new Type($firstType->getBuiltinType(), \true, $firstType->getClassName(), $firstType->isCollection(), $firstType->getCollectionKeyTypes(), $firstType->getCollectionValueTypes());
            unset($types[$nullableTypeIndex]);
        }
        return array_values($types);
    }
    /**
     * @return Type[]
     */
    private function extractTypes(TypeNode $node, NameScope $nameScope): array
    {
        if ($node instanceof UnionTypeNode) {
            $types = [];
            foreach ($node->types as $type) {
                if ($type instanceof ConstTypeNode) {
                    // It's safer to fall back to other extractors here, as resolving const types correctly is not easy at the moment
                    return [];
                }
                foreach ($this->extractTypes($type, $nameScope) as $subType) {
                    $types[] = $subType;
                }
            }
            return $this->compressNullableType($types);
        }
        if ($node instanceof GenericTypeNode) {
            if ('class-string' === $node->type->name) {
                return [new Type(Type::BUILTIN_TYPE_STRING)];
            }
            [$mainType] = $this->extractTypes($node->type, $nameScope);
            if (Type::BUILTIN_TYPE_INT === $mainType->getBuiltinType()) {
                return [$mainType];
            }
            $collection = $mainType->isCollection() || is_a($mainType->getClassName(), \Traversable::class, \true) || is_a($mainType->getClassName(), \ArrayAccess::class, \true);
            // it's safer to fall back to other extractors if the generic type is too abstract
            if (!$collection && !class_exists($mainType->getClassName()) && !interface_exists($mainType->getClassName(), \false)) {
                return [];
            }
            $collectionKeyTypes = $mainType->getCollectionKeyTypes();
            $collectionKeyValues = [];
            if (1 === \count($node->genericTypes)) {
                foreach ($this->extractTypes($node->genericTypes[0], $nameScope) as $subType) {
                    $collectionKeyValues[] = $subType;
                }
            } elseif (2 === \count($node->genericTypes)) {
                foreach ($this->extractTypes($node->genericTypes[0], $nameScope) as $keySubType) {
                    $collectionKeyTypes[] = $keySubType;
                }
                foreach ($this->extractTypes($node->genericTypes[1], $nameScope) as $valueSubType) {
                    $collectionKeyValues[] = $valueSubType;
                }
            }
            return [new Type($mainType->getBuiltinType(), $mainType->isNullable(), $mainType->getClassName(), $collection, $collectionKeyTypes, $collectionKeyValues)];
        }
        if ($node instanceof ArrayShapeNode) {
            return [new Type(Type::BUILTIN_TYPE_ARRAY, \false, null, \true)];
        }
        if ($node instanceof ArrayTypeNode) {
            return [new Type(Type::BUILTIN_TYPE_ARRAY, \false, null, \true, [new Type(Type::BUILTIN_TYPE_INT)], $this->extractTypes($node->type, $nameScope))];
        }
        if ($node instanceof CallableTypeNode || $node instanceof CallableTypeParameterNode) {
            return [new Type(Type::BUILTIN_TYPE_CALLABLE)];
        }
        if ($node instanceof NullableTypeNode) {
            $subTypes = $this->extractTypes($node->type, $nameScope);
            if (\count($subTypes) > 1) {
                $subTypes[] = new Type(Type::BUILTIN_TYPE_NULL);
                return $subTypes;
            }
            return [new Type($subTypes[0]->getBuiltinType(), \true, $subTypes[0]->getClassName(), $subTypes[0]->isCollection(), $subTypes[0]->getCollectionKeyTypes(), $subTypes[0]->getCollectionValueTypes())];
        }
        if ($node instanceof ThisTypeNode) {
            return [new Type(Type::BUILTIN_TYPE_OBJECT, \false, $nameScope->resolveRootClass())];
        }
        if ($node instanceof IdentifierTypeNode) {
            if (\in_array($node->name, Type::$builtinTypes)) {
                return [new Type($node->name, \false, null, \in_array($node->name, Type::$builtinCollectionTypes))];
            }
            return match ($node->name) {
                'integer', 'positive-int', 'negative-int' => [new Type(Type::BUILTIN_TYPE_INT)],
                'double' => [new Type(Type::BUILTIN_TYPE_FLOAT)],
                'list', 'non-empty-list' => [new Type(Type::BUILTIN_TYPE_ARRAY, \false, null, \true, new Type(Type::BUILTIN_TYPE_INT))],
                'non-empty-array' => [new Type(Type::BUILTIN_TYPE_ARRAY, \false, null, \true)],
                'mixed' => [],
                // mixed seems to be ignored in all other extractors
                'parent' => [new Type(Type::BUILTIN_TYPE_OBJECT, \false, $node->name)],
                'static', 'self' => [new Type(Type::BUILTIN_TYPE_OBJECT, \false, $nameScope->resolveRootClass())],
                'class-string', 'html-escaped-string', 'lowercase-string', 'non-empty-lowercase-string', 'non-empty-string', 'numeric-string', 'trait-string', 'interface-string', 'literal-string' => [new Type(Type::BUILTIN_TYPE_STRING)],
                'void' => [new Type(Type::BUILTIN_TYPE_NULL)],
                'scalar' => [new Type(Type::BUILTIN_TYPE_INT), new Type(Type::BUILTIN_TYPE_FLOAT), new Type(Type::BUILTIN_TYPE_STRING), new Type(Type::BUILTIN_TYPE_BOOL)],
                'number' => [new Type(Type::BUILTIN_TYPE_INT), new Type(Type::BUILTIN_TYPE_FLOAT)],
                'numeric' => [new Type(Type::BUILTIN_TYPE_INT), new Type(Type::BUILTIN_TYPE_FLOAT), new Type(Type::BUILTIN_TYPE_STRING)],
                'array-key' => [new Type(Type::BUILTIN_TYPE_STRING), new Type(Type::BUILTIN_TYPE_INT)],
                default => [new Type(Type::BUILTIN_TYPE_OBJECT, \false, $nameScope->resolveStringName($node->name))],
            };
        }
        return [];
    }
}
CHANGELOG
=========

6.4
---

 * Make properties writable when a setter in camelCase exists, similar to the camelCase getter

6.1
---

 * Add support for phpDocumentor and PHPStan pseudo-types
 * Add PHP 8.0 promoted properties `@param` mutation support to `PhpDocExtractor`
 * Add PHP 8.0 promoted properties `@param` mutation support to `PhpStanExtractor`

6.0
---

 * Remove the `Type::getCollectionKeyType()` and `Type::getCollectionValueType()` methods, use `Type::getCollectionKeyTypes()` and `Type::getCollectionValueTypes()` instead
 * Remove the `enable_magic_call_extraction` context option in `ReflectionExtractor::getWriteInfo()` and `ReflectionExtractor::getReadInfo()` in favor of `enable_magic_methods_extraction`

5.4
---

 * Add PhpStanExtractor

5.3
---

 * Add support for multiple types for collection keys & values
 * Deprecate the `Type::getCollectionKeyType()` and `Type::getCollectionValueType()` methods, use `Type::getCollectionKeyTypes()` and `Type::getCollectionValueTypes()` instead

5.2.0
-----

 * deprecated the `enable_magic_call_extraction` context option in `ReflectionExtractor::getWriteInfo()` and `ReflectionExtractor::getReadInfo()` in favor of `enable_magic_methods_extraction`

5.1.0
-----

 * Add support for extracting accessor and mutator via PHP Reflection

4.3.0
-----

 * Added the ability to extract private and protected properties and methods on `ReflectionExtractor`
 * Added the ability to extract property type based on its initial value

4.2.0
-----

 * added `PropertyInitializableExtractorInterface` to test if a property can be initialized through the constructor (implemented by `ReflectionExtractor`)

3.3.0
-----

 * Added `PropertyInfoPass`
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\PropertyInfo;

use _ContaoManager\Psr\Cache\CacheItemPoolInterface;
/**
 * Adds a PSR-6 cache layer on top of an extractor.
 *
 * @author Kévin Dunglas <dunglas@gmail.com>
 *
 * @final
 */
class PropertyInfoCacheExtractor implements PropertyInfoExtractorInterface, PropertyInitializableExtractorInterface
{
    private array $arrayCache = [];
    public function __construct(private readonly PropertyInfoExtractorInterface $propertyInfoExtractor, private readonly CacheItemPoolInterface $cacheItemPool)
    {
    }
    public function isReadable(string $class, string $property, array $context = []): ?bool
    {
        return $this->extract('isReadable', [$class, $property, $context]);
    }
    public function isWritable(string $class, string $property, array $context = []): ?bool
    {
        return $this->extract('isWritable', [$class, $property, $context]);
    }
    public function getShortDescription(string $class, string $property, array $context = []): ?string
    {
        return $this->extract('getShortDescription', [$class, $property, $context]);
    }
    public function getLongDescription(string $class, string $property, array $context = []): ?string
    {
        return $this->extract('getLongDescription', [$class, $property, $context]);
    }
    public function getProperties(string $class, array $context = []): ?array
    {
        return $this->extract('getProperties', [$class, $context]);
    }
    public function getTypes(string $class, string $property, array $context = []): ?array
    {
        return $this->extract('getTypes', [$class, $property, $context]);
    }
    public function isInitializable(string $class, string $property, array $context = []): ?bool
    {
        return $this->extract('isInitializable', [$class, $property, $context]);
    }
    /**
     * Retrieves the cached data if applicable or delegates to the decorated extractor.
     */
    private function extract(string $method, array $arguments): mixed
    {
        try {
            $serializedArguments = serialize($arguments);
        } catch (\Exception) {
            // If arguments are not serializable, skip the cache
            return $this->propertyInfoExtractor->{$method}(...$arguments);
        }
        // Calling rawurlencode escapes special characters not allowed in PSR-6's keys
        $key = rawurlencode($method . '.' . $serializedArguments);
        if (\array_key_exists($key, $this->arrayCache)) {
            return $this->arrayCache[$key];
        }
        $item = $this->cacheItemPool->getItem($key);
        if ($item->isHit()) {
            return $this->arrayCache[$key] = $item->get();
        }
        $value = $this->propertyInfoExtractor->{$method}(...$arguments);
        $item->set($value);
        $this->cacheItemPool->save($item);
        return $this->arrayCache[$key] = $value;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\PropertyInfo;

/**
 * Extract write information for the property of a class.
 *
 * @author Joel Wurtz <jwurtz@jolicode.com>
 */
interface PropertyWriteInfoExtractorInterface
{
    /**
     * Get write information object for a given property of a class.
     */
    public function getWriteInfo(string $class, string $property, array $context = []): ?PropertyWriteInfo;
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\PropertyInfo;

/**
 * Guesses if the property can be accessed or mutated.
 *
 * @author Kévin Dunglas <dunglas@gmail.com>
 */
interface PropertyAccessExtractorInterface
{
    /**
     * Is the property readable?
     *
     * @return bool|null
     */
    public function isReadable(string $class, string $property, array $context = []);
    /**
     * Is the property writable?
     *
     * @return bool|null
     */
    public function isWritable(string $class, string $property, array $context = []);
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\PropertyInfo;

/**
 * Type Extractor Interface.
 *
 * @author Kévin Dunglas <dunglas@gmail.com>
 */
interface PropertyTypeExtractorInterface
{
    /**
     * Gets types of a property.
     *
     * @return Type[]|null
     */
    public function getTypes(string $class, string $property, array $context = []);
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\PropertyInfo;

/**
 * The property read info tells how a property can be read.
 *
 * @author Joel Wurtz <jwurtz@jolicode.com>
 */
final class PropertyReadInfo
{
    public const TYPE_METHOD = 'method';
    public const TYPE_PROPERTY = 'property';
    public const VISIBILITY_PUBLIC = 'public';
    public const VISIBILITY_PROTECTED = 'protected';
    public const VISIBILITY_PRIVATE = 'private';
    public function __construct(private readonly string $type, private readonly string $name, private readonly string $visibility, private readonly bool $static, private readonly bool $byRef)
    {
    }
    /**
     * Get type of access.
     */
    public function getType(): string
    {
        return $this->type;
    }
    /**
     * Get name of the access, which can be a method name or a property name, depending on the type.
     */
    public function getName(): string
    {
        return $this->name;
    }
    public function getVisibility(): string
    {
        return $this->visibility;
    }
    public function isStatic(): bool
    {
        return $this->static;
    }
    /**
     * Whether this accessor can be accessed by reference.
     */
    public function canBeReference(): bool
    {
        return $this->byRef;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\PropertyInfo\Extractor;

use _ContaoManager\phpDocumentor\Reflection\Types\ContextFactory;
use _ContaoManager\PHPStan\PhpDocParser\Ast\PhpDoc\InvalidTagValueNode;
use _ContaoManager\PHPStan\PhpDocParser\Ast\PhpDoc\ParamTagValueNode;
use _ContaoManager\PHPStan\PhpDocParser\Ast\PhpDoc\PhpDocNode;
use _ContaoManager\PHPStan\PhpDocParser\Ast\PhpDoc\PhpDocTagNode;
use _ContaoManager\PHPStan\PhpDocParser\Lexer\Lexer;
use _ContaoManager\PHPStan\PhpDocParser\Parser\ConstExprParser;
use _ContaoManager\PHPStan\PhpDocParser\Parser\PhpDocParser;
use _ContaoManager\PHPStan\PhpDocParser\Parser\TokenIterator;
use _ContaoManager\PHPStan\PhpDocParser\Parser\TypeParser;
use _ContaoManager\PHPStan\PhpDocParser\ParserConfig;
use _ContaoManager\Symfony\Component\PropertyInfo\PhpStan\NameScopeFactory;
use _ContaoManager\Symfony\Component\PropertyInfo\PropertyTypeExtractorInterface;
use _ContaoManager\Symfony\Component\PropertyInfo\Type;
use _ContaoManager\Symfony\Component\PropertyInfo\Util\PhpStanTypeHelper;
/**
 * Extracts data using PHPStan parser.
 *
 * @author Baptiste Leduc <baptiste.leduc@gmail.com>
 */
final class PhpStanExtractor implements PropertyTypeExtractorInterface, ConstructorArgumentTypeExtractorInterface
{
    private const PROPERTY = 0;
    private const ACCESSOR = 1;
    private const MUTATOR = 2;
    private PhpDocParser $phpDocParser;
    private Lexer $lexer;
    private NameScopeFactory $nameScopeFactory;
    /** @var array<string, array{PhpDocNode|null, int|null, string|null, string|null}> */
    private array $docBlocks = [];
    private PhpStanTypeHelper $phpStanTypeHelper;
    private array $mutatorPrefixes;
    private array $accessorPrefixes;
    private array $arrayMutatorPrefixes;
    /**
     * @param list<string>|null $mutatorPrefixes
     * @param list<string>|null $accessorPrefixes
     * @param list<string>|null $arrayMutatorPrefixes
     */
    public function __construct(?array $mutatorPrefixes = null, ?array $accessorPrefixes = null, ?array $arrayMutatorPrefixes = null)
    {
        if (!class_exists(ContextFactory::class)) {
            throw new \LogicException(\sprintf('Unable to use the "%s" class as the "phpdocumentor/type-resolver" package is not installed. Try running composer require "phpdocumentor/type-resolver".', __CLASS__));
        }
        if (!class_exists(PhpDocParser::class)) {
            throw new \LogicException(\sprintf('Unable to use the "%s" class as the "phpstan/phpdoc-parser" package is not installed. Try running composer require "phpstan/phpdoc-parser".', __CLASS__));
        }
        $this->phpStanTypeHelper = new PhpStanTypeHelper();
        $this->mutatorPrefixes = $mutatorPrefixes ?? ReflectionExtractor::$defaultMutatorPrefixes;
        $this->accessorPrefixes = $accessorPrefixes ?? ReflectionExtractor::$defaultAccessorPrefixes;
        $this->arrayMutatorPrefixes = $arrayMutatorPrefixes ?? ReflectionExtractor::$defaultArrayMutatorPrefixes;
        if (class_exists(ParserConfig::class)) {
            $parserConfig = new ParserConfig([]);
            $this->phpDocParser = new PhpDocParser($parserConfig, new TypeParser($parserConfig, new ConstExprParser($parserConfig)), new ConstExprParser($parserConfig));
            $this->lexer = new Lexer($parserConfig);
        } else {
            $this->phpDocParser = new PhpDocParser(new TypeParser(new ConstExprParser()), new ConstExprParser());
            $this->lexer = new Lexer();
        }
        $this->nameScopeFactory = new NameScopeFactory();
    }
    public function getTypes(string $class, string $property, array $context = []): ?array
    {
        /** @var PhpDocNode|null $docNode */
        [$docNode, $source, $prefix, $declaringClass] = $this->getDocBlock($class, $property);
        $nameScope = $this->nameScopeFactory->create($class, $declaringClass);
        if (null === $docNode) {
            return null;
        }
        switch ($source) {
            case self::PROPERTY:
                $tag = '@var';
                break;
            case self::ACCESSOR:
                $tag = '@return';
                break;
            case self::MUTATOR:
                $tag = '@param';
                break;
        }
        $parentClass = null;
        $types = [];
        foreach ($docNode->getTagsByName($tag) as $tagDocNode) {
            if ($tagDocNode->value instanceof InvalidTagValueNode) {
                continue;
            }
            if ($tagDocNode->value instanceof ParamTagValueNode && null === $prefix && $tagDocNode->value->parameterName !== '$' . $property) {
                continue;
            }
            foreach ($this->phpStanTypeHelper->getTypes($tagDocNode->value, $nameScope) as $type) {
                switch ($type->getClassName()) {
                    case 'self':
                    case 'static':
                        $resolvedClass = $class;
                        break;
                    case 'parent':
                        if (\false !== $resolvedClass = $parentClass ??= get_parent_class($class)) {
                            break;
                        }
                    // no break
                    default:
                        $types[] = $type;
                        continue 2;
                }
                $types[] = new Type(Type::BUILTIN_TYPE_OBJECT, $type->isNullable(), $resolvedClass, $type->isCollection(), $type->getCollectionKeyTypes(), $type->getCollectionValueTypes());
            }
        }
        if (!isset($types[0])) {
            return null;
        }
        if (!\in_array($prefix, $this->arrayMutatorPrefixes, \true)) {
            return $types;
        }
        return [new Type(Type::BUILTIN_TYPE_ARRAY, \false, null, \true, new Type(Type::BUILTIN_TYPE_INT), $types[0])];
    }
    public function getTypesFromConstructor(string $class, string $property): ?array
    {
        if (null === $tagDocNode = $this->getDocBlockFromConstructor($class, $property)) {
            return $this->getTypes($class, $property);
        }
        $types = [];
        foreach ($this->phpStanTypeHelper->getTypes($tagDocNode, $this->nameScopeFactory->create($class)) as $type) {
            $types[] = $type;
        }
        if (!isset($types[0])) {
            return null;
        }
        return $types;
    }
    private function getDocBlockFromConstructor(string $class, string $property): ?ParamTagValueNode
    {
        try {
            $reflectionClass = new \ReflectionClass($class);
        } catch (\ReflectionException) {
            return null;
        }
        if (null === $reflectionConstructor = $reflectionClass->getConstructor()) {
            return null;
        }
        if (!$rawDocNode = $reflectionConstructor->getDocComment()) {
            return null;
        }
        $phpDocNode = $this->getPhpDocNode($rawDocNode);
        return $this->filterDocBlockParams($phpDocNode, $property);
    }
    private function filterDocBlockParams(PhpDocNode $docNode, string $allowedParam): ?ParamTagValueNode
    {
        $tags = array_values(array_filter($docNode->getTagsByName('@param'), fn($tagNode) => $tagNode instanceof PhpDocTagNode && '$' . $allowedParam === $tagNode->value->parameterName));
        if (!$tags) {
            return null;
        }
        return $tags[0]->value;
    }
    /**
     * @return array{PhpDocNode|null, int|null, string|null, string|null}
     */
    private function getDocBlock(string $class, string $property): array
    {
        $propertyHash = $class . '::' . $property;
        if (isset($this->docBlocks[$propertyHash])) {
            return $this->docBlocks[$propertyHash];
        }
        $ucFirstProperty = ucfirst($property);
        if ([$docBlock, $source, $declaringClass] = $this->getDocBlockFromProperty($class, $property)) {
            $data = [$docBlock, $source, null, $declaringClass];
        } elseif ([$docBlock, $_, $declaringClass] = $this->getDocBlockFromMethod($class, $ucFirstProperty, self::ACCESSOR)) {
            $data = [$docBlock, self::ACCESSOR, null, $declaringClass];
        } elseif ([$docBlock, $prefix, $declaringClass] = $this->getDocBlockFromMethod($class, $ucFirstProperty, self::MUTATOR)) {
            $data = [$docBlock, self::MUTATOR, $prefix, $declaringClass];
        } else {
            $data = [null, null, null, null];
        }
        return $this->docBlocks[$propertyHash] = $data;
    }
    /**
     * @return array{PhpDocNode, int, string}|null
     */
    private function getDocBlockFromProperty(string $class, string $property): ?array
    {
        // Use a ReflectionProperty instead of $class to get the parent class if applicable
        try {
            $reflectionProperty = new \ReflectionProperty($class, $property);
        } catch (\ReflectionException) {
            return null;
        }
        $reflector = $reflectionProperty->getDeclaringClass();
        foreach ($reflector->getTraits() as $trait) {
            if ($trait->hasProperty($property)) {
                return $this->getDocBlockFromProperty($trait->getName(), $property);
            }
        }
        // Type can be inside property docblock as `@var`
        $rawDocNode = $reflectionProperty->getDocComment();
        $phpDocNode = $rawDocNode ? $this->getPhpDocNode($rawDocNode) : null;
        $source = self::PROPERTY;
        if (!$phpDocNode?->getTagsByName('@var')) {
            $phpDocNode = null;
        }
        // or in the constructor as `@param` for promoted properties
        if (!$phpDocNode && $reflectionProperty->isPromoted()) {
            $constructor = new \ReflectionMethod($class, '__construct');
            $rawDocNode = $constructor->getDocComment();
            $phpDocNode = $rawDocNode ? $this->getPhpDocNode($rawDocNode) : null;
            $source = self::MUTATOR;
        }
        if (!$phpDocNode) {
            return null;
        }
        return [$phpDocNode, $source, $reflectionProperty->class];
    }
    /**
     * @return array{PhpDocNode, string, string}|null
     */
    private function getDocBlockFromMethod(string $class, string $ucFirstProperty, int $type): ?array
    {
        $prefixes = self::ACCESSOR === $type ? $this->accessorPrefixes : $this->mutatorPrefixes;
        $prefix = null;
        $method = null;
        foreach ($prefixes as $prefix) {
            $methodName = $prefix . $ucFirstProperty;
            try {
                $method = new \ReflectionMethod($class, $methodName);
                if ($method->isStatic()) {
                    continue;
                }
                if (self::ACCESSOR === $type && \in_array((string) $method->getReturnType(), ['void', 'never'], \true)) {
                    continue;
                }
                if (self::ACCESSOR === $type && !$method->getNumberOfRequiredParameters() || self::MUTATOR === $type && $method->getNumberOfParameters() >= 1) {
                    break;
                }
            } catch (\ReflectionException) {
                // Try the next prefix if the method doesn't exist
            }
        }
        if (!$method) {
            return null;
        }
        if (null === $rawDocNode = $method->getDocComment() ?: null) {
            return null;
        }
        $phpDocNode = $this->getPhpDocNode($rawDocNode);
        return [$phpDocNode, $prefix, $method->class];
    }
    private function getPhpDocNode(string $rawDocNode): PhpDocNode
    {
        $tokens = new TokenIterator($this->lexer->tokenize($rawDocNode));
        $phpDocNode = $this->phpDocParser->parse($tokens);
        $tokens->consumeTokenType(Lexer::TOKEN_END);
        return $phpDocNode;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\PropertyInfo\Extractor;

use _ContaoManager\Symfony\Component\PropertyInfo\PropertyListExtractorInterface;
use _ContaoManager\Symfony\Component\Serializer\Mapping\Factory\ClassMetadataFactoryInterface;
/**
 * Lists available properties using Symfony Serializer Component metadata.
 *
 * @author Kévin Dunglas <dunglas@gmail.com>
 *
 * @final
 */
class SerializerExtractor implements PropertyListExtractorInterface
{
    public function __construct(private readonly ClassMetadataFactoryInterface $classMetadataFactory)
    {
    }
    public function getProperties(string $class, array $context = []): ?array
    {
        if (!\array_key_exists('serializer_groups', $context) || null !== $context['serializer_groups'] && !\is_array($context['serializer_groups'])) {
            return null;
        }
        if (!$this->classMetadataFactory->hasMetadataFor($class)) {
            return null;
        }
        $properties = [];
        $serializerClassMetadata = $this->classMetadataFactory->getMetadataFor($class);
        foreach ($serializerClassMetadata->getAttributesMetadata() as $serializerAttributeMetadata) {
            if (!$serializerAttributeMetadata->isIgnored() && (null === $context['serializer_groups'] || array_intersect($context['serializer_groups'], $serializerAttributeMetadata->getGroups()))) {
                $properties[] = $serializerAttributeMetadata->getName();
            }
        }
        return $properties;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\PropertyInfo\Extractor;

use _ContaoManager\Symfony\Component\PropertyInfo\PropertyTypeExtractorInterface;
/**
 * Extracts the constructor argument type using ConstructorArgumentTypeExtractorInterface implementations.
 *
 * @author Dmitrii Poddubnyi <dpoddubny@gmail.com>
 */
final class ConstructorExtractor implements PropertyTypeExtractorInterface
{
    /**
     * @param iterable<int, ConstructorArgumentTypeExtractorInterface> $extractors
     */
    public function __construct(private readonly iterable $extractors = [])
    {
    }
    public function getTypes(string $class, string $property, array $context = []): ?array
    {
        foreach ($this->extractors as $extractor) {
            $value = $extractor->getTypesFromConstructor($class, $property);
            if (null !== $value) {
                return $value;
            }
        }
        return null;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\PropertyInfo\Extractor;

use _ContaoManager\Symfony\Component\PropertyInfo\Type;
/**
 * Infers the constructor argument type.
 *
 * @author Dmitrii Poddubnyi <dpoddubny@gmail.com>
 *
 * @internal
 */
interface ConstructorArgumentTypeExtractorInterface
{
    /**
     * Gets types of an argument from constructor.
     *
     * @return Type[]|null
     *
     * @internal
     */
    public function getTypesFromConstructor(string $class, string $property): ?array;
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\PropertyInfo\Extractor;

use _ContaoManager\Symfony\Component\PropertyInfo\PropertyAccessExtractorInterface;
use _ContaoManager\Symfony\Component\PropertyInfo\PropertyInitializableExtractorInterface;
use _ContaoManager\Symfony\Component\PropertyInfo\PropertyListExtractorInterface;
use _ContaoManager\Symfony\Component\PropertyInfo\PropertyReadInfo;
use _ContaoManager\Symfony\Component\PropertyInfo\PropertyReadInfoExtractorInterface;
use _ContaoManager\Symfony\Component\PropertyInfo\PropertyTypeExtractorInterface;
use _ContaoManager\Symfony\Component\PropertyInfo\PropertyWriteInfo;
use _ContaoManager\Symfony\Component\PropertyInfo\PropertyWriteInfoExtractorInterface;
use _ContaoManager\Symfony\Component\PropertyInfo\Type;
use _ContaoManager\Symfony\Component\String\Inflector\EnglishInflector;
use _ContaoManager\Symfony\Component\String\Inflector\InflectorInterface;
/**
 * Extracts data using the reflection API.
 *
 * @author Kévin Dunglas <dunglas@gmail.com>
 *
 * @final
 */
class ReflectionExtractor implements PropertyListExtractorInterface, PropertyTypeExtractorInterface, PropertyAccessExtractorInterface, PropertyInitializableExtractorInterface, PropertyReadInfoExtractorInterface, PropertyWriteInfoExtractorInterface, ConstructorArgumentTypeExtractorInterface
{
    /**
     * @internal
     */
    public static array $defaultMutatorPrefixes = ['add', 'remove', 'set'];
    /**
     * @internal
     */
    public static array $defaultAccessorPrefixes = ['get', 'is', 'has', 'can'];
    /**
     * @internal
     */
    public static array $defaultArrayMutatorPrefixes = ['add', 'remove'];
    public const ALLOW_PRIVATE = 1;
    public const ALLOW_PROTECTED = 2;
    public const ALLOW_PUBLIC = 4;
    /** @var int Allow none of the magic methods */
    public const DISALLOW_MAGIC_METHODS = 0;
    /** @var int Allow magic __get methods */
    public const ALLOW_MAGIC_GET = 1 << 0;
    /** @var int Allow magic __set methods */
    public const ALLOW_MAGIC_SET = 1 << 1;
    /** @var int Allow magic __call methods */
    public const ALLOW_MAGIC_CALL = 1 << 2;
    private const MAP_TYPES = ['integer' => Type::BUILTIN_TYPE_INT, 'boolean' => Type::BUILTIN_TYPE_BOOL, 'double' => Type::BUILTIN_TYPE_FLOAT];
    private array $mutatorPrefixes;
    private array $accessorPrefixes;
    private array $arrayMutatorPrefixes;
    private bool $enableConstructorExtraction;
    private int $methodReflectionFlags;
    private int $magicMethodsFlags;
    private int $propertyReflectionFlags;
    private InflectorInterface $inflector;
    private array $arrayMutatorPrefixesFirst;
    private array $arrayMutatorPrefixesLast;
    /**
     * @param string[]|null $mutatorPrefixes
     * @param string[]|null $accessorPrefixes
     * @param string[]|null $arrayMutatorPrefixes
     */
    public function __construct(?array $mutatorPrefixes = null, ?array $accessorPrefixes = null, ?array $arrayMutatorPrefixes = null, bool $enableConstructorExtraction = \true, int $accessFlags = self::ALLOW_PUBLIC, ?InflectorInterface $inflector = null, int $magicMethodsFlags = self::ALLOW_MAGIC_GET | self::ALLOW_MAGIC_SET)
    {
        $this->mutatorPrefixes = $mutatorPrefixes ?? self::$defaultMutatorPrefixes;
        $this->accessorPrefixes = $accessorPrefixes ?? self::$defaultAccessorPrefixes;
        $this->arrayMutatorPrefixes = $arrayMutatorPrefixes ?? self::$defaultArrayMutatorPrefixes;
        $this->enableConstructorExtraction = $enableConstructorExtraction;
        $this->methodReflectionFlags = $this->getMethodsFlags($accessFlags);
        $this->propertyReflectionFlags = $this->getPropertyFlags($accessFlags);
        $this->magicMethodsFlags = $magicMethodsFlags;
        $this->inflector = $inflector ?? new EnglishInflector();
        $this->arrayMutatorPrefixesFirst = array_merge($this->arrayMutatorPrefixes, array_diff($this->mutatorPrefixes, $this->arrayMutatorPrefixes));
        $this->arrayMutatorPrefixesLast = array_reverse($this->arrayMutatorPrefixesFirst);
    }
    public function getProperties(string $class, array $context = []): ?array
    {
        try {
            $reflectionClass = new \ReflectionClass($class);
        } catch (\ReflectionException) {
            return null;
        }
        $reflectionProperties = $reflectionClass->getProperties();
        $properties = [];
        foreach ($reflectionProperties as $reflectionProperty) {
            if ($reflectionProperty->getModifiers() & $this->propertyReflectionFlags) {
                $properties[$reflectionProperty->name] = $reflectionProperty->name;
            }
        }
        foreach ($reflectionClass->getMethods($this->methodReflectionFlags) as $reflectionMethod) {
            if ($reflectionMethod->isStatic()) {
                continue;
            }
            $propertyName = $this->getPropertyName($reflectionMethod->name, $reflectionProperties);
            if (!$propertyName || isset($properties[$propertyName])) {
                continue;
            }
            if ($reflectionClass->hasProperty($lowerCasedPropertyName = lcfirst($propertyName)) || !$reflectionClass->hasProperty($propertyName) && !preg_match('/^[A-Z]{2,}/', $propertyName)) {
                $propertyName = $lowerCasedPropertyName;
            }
            $properties[$propertyName] = $propertyName;
        }
        return $properties ? array_values($properties) : null;
    }
    public function getTypes(string $class, string $property, array $context = []): ?array
    {
        if ($fromMutator = $this->extractFromMutator($class, $property)) {
            return $fromMutator;
        }
        $allowedPrefixes = array_diff($this->accessorPrefixes, ['is', 'can', 'has']);
        if ($fromAccessor = $this->extractFromAccessor($class, $property, $allowedPrefixes)) {
            return $fromAccessor;
        }
        if (($context['enable_constructor_extraction'] ?? $this->enableConstructorExtraction) && $fromConstructor = $this->extractFromConstructor($class, $property)) {
            return $fromConstructor;
        }
        if ($fromPropertyDeclaration = $this->extractFromPropertyDeclaration($class, $property)) {
            return $fromPropertyDeclaration;
        }
        $allowedPrefixes = array_diff($this->accessorPrefixes, $allowedPrefixes);
        if ($fromAccessor = $this->extractFromAccessor($class, $property, $allowedPrefixes)) {
            return $fromAccessor;
        }
        return null;
    }
    public function getTypesFromConstructor(string $class, string $property): ?array
    {
        try {
            $reflection = new \ReflectionClass($class);
        } catch (\ReflectionException) {
            return null;
        }
        if (!$reflectionConstructor = $reflection->getConstructor()) {
            return null;
        }
        if (!$reflectionParameter = $this->getReflectionParameterFromConstructor($property, $reflectionConstructor)) {
            return null;
        }
        if (!$reflectionType = $reflectionParameter->getType()) {
            return null;
        }
        if (!$types = $this->extractFromReflectionType($reflectionType, $reflectionConstructor->getDeclaringClass())) {
            return null;
        }
        return $types;
    }
    private function getReflectionParameterFromConstructor(string $property, \ReflectionMethod $reflectionConstructor): ?\ReflectionParameter
    {
        foreach ($reflectionConstructor->getParameters() as $reflectionParameter) {
            if ($reflectionParameter->getName() === $property) {
                return $reflectionParameter;
            }
        }
        return null;
    }
    public function isReadable(string $class, string $property, array $context = []): ?bool
    {
        if ($this->isAllowedProperty($class, $property)) {
            return \true;
        }
        return null !== $this->getReadInfo($class, $property, $context);
    }
    public function isWritable(string $class, string $property, array $context = []): ?bool
    {
        if ($this->isAllowedProperty($class, $property, \true)) {
            return \true;
        }
        // First test with the camelized property name
        [$reflectionMethod] = $this->getMutatorMethod($class, $this->camelize($property));
        if (null !== $reflectionMethod) {
            return \true;
        }
        // Otherwise check for the old way
        [$reflectionMethod] = $this->getMutatorMethod($class, $property);
        return null !== $reflectionMethod;
    }
    public function isInitializable(string $class, string $property, array $context = []): ?bool
    {
        try {
            $reflectionClass = new \ReflectionClass($class);
        } catch (\ReflectionException) {
            return null;
        }
        if (!$reflectionClass->isInstantiable()) {
            return \false;
        }
        if ($constructor = $reflectionClass->getConstructor()) {
            foreach ($constructor->getParameters() as $parameter) {
                if ($property === $parameter->name) {
                    return \true;
                }
            }
        } elseif ($parentClass = $reflectionClass->getParentClass()) {
            return $this->isInitializable($parentClass->getName(), $property);
        }
        return \false;
    }
    public function getReadInfo(string $class, string $property, array $context = []): ?PropertyReadInfo
    {
        try {
            $reflClass = new \ReflectionClass($class);
        } catch (\ReflectionException) {
            return null;
        }
        $allowGetterSetter = $context['enable_getter_setter_extraction'] ?? \false;
        $magicMethods = $context['enable_magic_methods_extraction'] ?? $this->magicMethodsFlags;
        $allowMagicCall = (bool) ($magicMethods & self::ALLOW_MAGIC_CALL);
        $allowMagicGet = (bool) ($magicMethods & self::ALLOW_MAGIC_GET);
        $hasProperty = $reflClass->hasProperty($property);
        $camelProp = $this->camelize($property);
        $getsetter = lcfirst($camelProp);
        // jQuery style, e.g. read: last(), write: last($item)
        foreach ($this->accessorPrefixes as $prefix) {
            $methodName = $prefix . $camelProp;
            if ($reflClass->hasMethod($methodName) && ($m = $reflClass->getMethod($methodName))->getModifiers() & $this->methodReflectionFlags && !$m->getNumberOfRequiredParameters() && !\in_array((string) $m->getReturnType(), ['void', 'never'], \true)) {
                return new PropertyReadInfo(PropertyReadInfo::TYPE_METHOD, $methodName, $this->getReadVisibilityForMethod($m), $m->isStatic(), \false);
            }
        }
        if ($allowGetterSetter && $reflClass->hasMethod($getsetter) && ($m = $reflClass->getMethod($getsetter))->getModifiers() & $this->methodReflectionFlags && !$m->getNumberOfRequiredParameters() && !\in_array((string) $m->getReturnType(), ['void', 'never'], \true)) {
            return new PropertyReadInfo(PropertyReadInfo::TYPE_METHOD, $getsetter, $this->getReadVisibilityForMethod($m), $m->isStatic(), \false);
        }
        if ($allowMagicGet && $reflClass->hasMethod('__get') && ($r = $reflClass->getMethod('__get'))->getModifiers() & $this->methodReflectionFlags) {
            return new PropertyReadInfo(PropertyReadInfo::TYPE_PROPERTY, $property, PropertyReadInfo::VISIBILITY_PUBLIC, \false, $r->returnsReference());
        }
        if ($hasProperty && ($r = $reflClass->getProperty($property))->getModifiers() & $this->propertyReflectionFlags) {
            return new PropertyReadInfo(PropertyReadInfo::TYPE_PROPERTY, $property, $this->getReadVisibilityForProperty($r), $r->isStatic(), \true);
        }
        if ($allowMagicCall && $reflClass->hasMethod('__call') && $reflClass->getMethod('__call')->getModifiers() & $this->methodReflectionFlags) {
            return new PropertyReadInfo(PropertyReadInfo::TYPE_METHOD, 'get' . $camelProp, PropertyReadInfo::VISIBILITY_PUBLIC, \false, \false);
        }
        return null;
    }
    public function getWriteInfo(string $class, string $property, array $context = []): ?PropertyWriteInfo
    {
        try {
            $reflClass = new \ReflectionClass($class);
        } catch (\ReflectionException) {
            return null;
        }
        $allowGetterSetter = $context['enable_getter_setter_extraction'] ?? \false;
        $magicMethods = $context['enable_magic_methods_extraction'] ?? $this->magicMethodsFlags;
        $allowMagicCall = (bool) ($magicMethods & self::ALLOW_MAGIC_CALL);
        $allowMagicSet = (bool) ($magicMethods & self::ALLOW_MAGIC_SET);
        $allowConstruct = $context['enable_constructor_extraction'] ?? $this->enableConstructorExtraction;
        $allowAdderRemover = $context['enable_adder_remover_extraction'] ?? \true;
        $camelized = $this->camelize($property);
        $nonCamelized = ucfirst($property);
        $constructor = $reflClass->getConstructor();
        $singulars = $this->inflector->singularize($camelized);
        $errors = [];
        if (null !== $constructor && $allowConstruct) {
            foreach ($constructor->getParameters() as $parameter) {
                if ($parameter->getName() === $property) {
                    return new PropertyWriteInfo(PropertyWriteInfo::TYPE_CONSTRUCTOR, $property);
                }
            }
        }
        [$adderAccessName, $removerAccessName, $adderAndRemoverErrors] = $this->findAdderAndRemover($reflClass, $singulars);
        if ($allowAdderRemover && null !== $adderAccessName && null !== $removerAccessName) {
            $adderMethod = $reflClass->getMethod($adderAccessName);
            $removerMethod = $reflClass->getMethod($removerAccessName);
            $mutator = new PropertyWriteInfo(PropertyWriteInfo::TYPE_ADDER_AND_REMOVER);
            $mutator->setAdderInfo(new PropertyWriteInfo(PropertyWriteInfo::TYPE_METHOD, $adderAccessName, $this->getWriteVisibilityForMethod($adderMethod), $adderMethod->isStatic()));
            $mutator->setRemoverInfo(new PropertyWriteInfo(PropertyWriteInfo::TYPE_METHOD, $removerAccessName, $this->getWriteVisibilityForMethod($removerMethod), $removerMethod->isStatic()));
            return $mutator;
        }
        $errors[] = $adderAndRemoverErrors;
        foreach ($this->mutatorPrefixes as $mutatorPrefix) {
            $methodName = $mutatorPrefix . $camelized;
            [$accessible, $methodAccessibleErrors] = $this->isMethodAccessible($reflClass, $methodName, 1);
            if (!$accessible) {
                $errors[] = $methodAccessibleErrors;
                continue;
            }
            $method = $reflClass->getMethod($methodName);
            if (!\in_array($mutatorPrefix, $this->arrayMutatorPrefixes, \true)) {
                return new PropertyWriteInfo(PropertyWriteInfo::TYPE_METHOD, $methodName, $this->getWriteVisibilityForMethod($method), $method->isStatic());
            }
        }
        if ($camelized !== $nonCamelized) {
            foreach ($this->mutatorPrefixes as $mutatorPrefix) {
                $methodName = $mutatorPrefix . $nonCamelized;
                [$accessible, $methodAccessibleErrors] = $this->isMethodAccessible($reflClass, $methodName, 1);
                if (!$accessible) {
                    $errors[] = $methodAccessibleErrors;
                    continue;
                }
                $method = $reflClass->getMethod($methodName);
                if (!\in_array($mutatorPrefix, $this->arrayMutatorPrefixes, \true)) {
                    return new PropertyWriteInfo(PropertyWriteInfo::TYPE_METHOD, $methodName, $this->getWriteVisibilityForMethod($method), $method->isStatic());
                }
            }
        }
        $getsetter = lcfirst($camelized);
        $getsetterNonCamelized = lcfirst($nonCamelized);
        if ($allowGetterSetter) {
            [$accessible, $methodAccessibleErrors] = $this->isMethodAccessible($reflClass, $getsetter, 1);
            if ($accessible) {
                $method = $reflClass->getMethod($getsetter);
                return new PropertyWriteInfo(PropertyWriteInfo::TYPE_METHOD, $getsetter, $this->getWriteVisibilityForMethod($method), $method->isStatic());
            }
            $errors[] = $methodAccessibleErrors;
            if ($getsetter !== $getsetterNonCamelized) {
                [$accessible, $methodAccessibleErrors] = $this->isMethodAccessible($reflClass, $getsetterNonCamelized, 1);
                if ($accessible) {
                    $method = $reflClass->getMethod($getsetterNonCamelized);
                    return new PropertyWriteInfo(PropertyWriteInfo::TYPE_METHOD, $getsetterNonCamelized, $this->getWriteVisibilityForMethod($method), $method->isStatic());
                }
                $errors[] = $methodAccessibleErrors;
            }
        }
        if ($reflClass->hasProperty($property) && $reflClass->getProperty($property)->getModifiers() & $this->propertyReflectionFlags) {
            $reflProperty = $reflClass->getProperty($property);
            if (!$reflProperty->isReadOnly()) {
                return new PropertyWriteInfo(PropertyWriteInfo::TYPE_PROPERTY, $property, $this->getWriteVisibilityForProperty($reflProperty), $reflProperty->isStatic());
            }
            $errors[] = [\sprintf('The property "%s" in class "%s" is a promoted readonly property.', $property, $reflClass->getName())];
            $allowMagicSet = $allowMagicCall = \false;
        }
        if ($allowMagicSet) {
            [$accessible, $methodAccessibleErrors] = $this->isMethodAccessible($reflClass, '__set', 2);
            if ($accessible) {
                return new PropertyWriteInfo(PropertyWriteInfo::TYPE_PROPERTY, $property, PropertyWriteInfo::VISIBILITY_PUBLIC, \false);
            }
            $errors[] = $methodAccessibleErrors;
        }
        if ($allowMagicCall) {
            [$accessible, $methodAccessibleErrors] = $this->isMethodAccessible($reflClass, '__call', 2);
            if ($accessible) {
                return new PropertyWriteInfo(PropertyWriteInfo::TYPE_METHOD, 'set' . $camelized, PropertyWriteInfo::VISIBILITY_PUBLIC, \false);
            }
            $errors[] = $methodAccessibleErrors;
        }
        if (!$allowAdderRemover && null !== $adderAccessName && null !== $removerAccessName) {
            $errors[] = [\sprintf('The property "%s" in class "%s" can be defined with the methods "%s()" but ' . 'the new value must be an array or an instance of \Traversable', $property, $reflClass->getName(), implode('()", "', [$adderAccessName, $removerAccessName]))];
        }
        $noneProperty = new PropertyWriteInfo();
        $noneProperty->setErrors(array_merge([], ...$errors));
        return $noneProperty;
    }
    /**
     * @return Type[]|null
     */
    private function extractFromMutator(string $class, string $property): ?array
    {
        [$reflectionMethod, $prefix] = $this->getMutatorMethod($class, $property);
        if (null === $reflectionMethod) {
            return null;
        }
        $reflectionParameters = $reflectionMethod->getParameters();
        $reflectionParameter = $reflectionParameters[0];
        if (!$reflectionType = $reflectionParameter->getType()) {
            return null;
        }
        $type = $this->extractFromReflectionType($reflectionType, $reflectionMethod->getDeclaringClass());
        if (1 === \count($type) && \in_array($prefix, $this->arrayMutatorPrefixes)) {
            $type = [new Type(Type::BUILTIN_TYPE_ARRAY, $this->isNullableProperty($class, $property), null, \true, new Type(Type::BUILTIN_TYPE_INT), $type[0])];
        }
        return $type;
    }
    /**
     * Tries to extract type information from accessors.
     *
     * @return Type[]|null
     */
    private function extractFromAccessor(string $class, string $property, array $allowedPrefixes): ?array
    {
        [$reflectionMethod, $prefix] = $this->getAccessorMethod($class, $property);
        if (null === $reflectionMethod) {
            return null;
        }
        if (!\in_array($prefix, $allowedPrefixes, \true)) {
            return null;
        }
        if ($reflectionType = $reflectionMethod->getReturnType()) {
            return $this->extractFromReflectionType($reflectionType, $reflectionMethod->getDeclaringClass());
        }
        if (\in_array($prefix, ['is', 'can', 'has'])) {
            return [new Type(Type::BUILTIN_TYPE_BOOL)];
        }
        return null;
    }
    /**
     * Tries to extract type information from constructor.
     *
     * @return Type[]|null
     */
    private function extractFromConstructor(string $class, string $property): ?array
    {
        try {
            $reflectionClass = new \ReflectionClass($class);
        } catch (\ReflectionException) {
            return null;
        }
        $constructor = $reflectionClass->getConstructor();
        if (!$constructor) {
            return null;
        }
        foreach ($constructor->getParameters() as $parameter) {
            if ($property !== $parameter->name) {
                continue;
            }
            $reflectionType = $parameter->getType();
            return $reflectionType ? $this->extractFromReflectionType($reflectionType, $constructor->getDeclaringClass()) : null;
        }
        if ($parentClass = $reflectionClass->getParentClass()) {
            return $this->extractFromConstructor($parentClass->getName(), $property);
        }
        return null;
    }
    private function extractFromPropertyDeclaration(string $class, string $property): ?array
    {
        try {
            $reflectionClass = new \ReflectionClass($class);
            $reflectionProperty = $reflectionClass->getProperty($property);
            $reflectionPropertyType = $reflectionProperty->getType();
            if (null !== $reflectionPropertyType && $types = $this->extractFromReflectionType($reflectionPropertyType, $reflectionProperty->getDeclaringClass())) {
                return $types;
            }
        } catch (\ReflectionException) {
            return null;
        }
        $defaultValue = $reflectionClass->getDefaultProperties()[$property] ?? null;
        if (null === $defaultValue) {
            return null;
        }
        $type = \gettype($defaultValue);
        $type = static::MAP_TYPES[$type] ?? $type;
        return [new Type($type, $this->isNullableProperty($class, $property), null, Type::BUILTIN_TYPE_ARRAY === $type)];
    }
    private function extractFromReflectionType(\ReflectionType $reflectionType, \ReflectionClass $declaringClass): array
    {
        $types = [];
        $nullable = $reflectionType->allowsNull();
        foreach ($reflectionType instanceof \ReflectionUnionType || $reflectionType instanceof \ReflectionIntersectionType ? $reflectionType->getTypes() : [$reflectionType] as $type) {
            if (!$type instanceof \ReflectionNamedType) {
                // Nested composite types are not supported yet.
                return [];
            }
            $phpTypeOrClass = $type->getName();
            if ('null' === $phpTypeOrClass || 'mixed' === $phpTypeOrClass || 'never' === $phpTypeOrClass) {
                continue;
            }
            if (Type::BUILTIN_TYPE_ARRAY === $phpTypeOrClass) {
                $types[] = new Type(Type::BUILTIN_TYPE_ARRAY, $nullable, null, \true);
            } elseif ('void' === $phpTypeOrClass) {
                $types[] = new Type(Type::BUILTIN_TYPE_NULL, $nullable);
            } elseif ($type->isBuiltin()) {
                $types[] = new Type($phpTypeOrClass, $nullable);
            } else {
                $types[] = new Type(Type::BUILTIN_TYPE_OBJECT, $nullable, $this->resolveTypeName($phpTypeOrClass, $declaringClass));
            }
        }
        return $types;
    }
    private function resolveTypeName(string $name, \ReflectionClass $declaringClass): string
    {
        if ('self' === $lcName = strtolower($name)) {
            return $declaringClass->name;
        }
        if ('parent' === $lcName && $parent = $declaringClass->getParentClass()) {
            return $parent->name;
        }
        return $name;
    }
    private function isNullableProperty(string $class, string $property): bool
    {
        try {
            $reflectionProperty = new \ReflectionProperty($class, $property);
            $reflectionPropertyType = $reflectionProperty->getType();
            return null !== $reflectionPropertyType && $reflectionPropertyType->allowsNull();
        } catch (\ReflectionException) {
            // Return false if the property doesn't exist
        }
        return \false;
    }
    private function isAllowedProperty(string $class, string $property, bool $writeAccessRequired = \false): bool
    {
        try {
            $reflectionProperty = new \ReflectionProperty($class, $property);
            if ($writeAccessRequired) {
                if ($reflectionProperty->isReadOnly()) {
                    return \false;
                }
                if (\PHP_VERSION_ID >= 80400 && $reflectionProperty->isProtectedSet()) {
                    return (bool) ($this->propertyReflectionFlags & \ReflectionProperty::IS_PROTECTED);
                }
                if (\PHP_VERSION_ID >= 80400 && $reflectionProperty->isPrivateSet()) {
                    return (bool) ($this->propertyReflectionFlags & \ReflectionProperty::IS_PRIVATE);
                }
                if (\PHP_VERSION_ID >= 80400 && $reflectionProperty->isVirtual() && !$reflectionProperty->hasHook(\PropertyHookType::Set)) {
                    return \false;
                }
            }
            return (bool) ($reflectionProperty->getModifiers() & $this->propertyReflectionFlags);
        } catch (\ReflectionException) {
            // Return false if the property doesn't exist
        }
        return \false;
    }
    /**
     * Gets the accessor method.
     *
     * Returns an array with a the instance of \ReflectionMethod as first key
     * and the prefix of the method as second or null if not found.
     */
    private function getAccessorMethod(string $class, string $property): ?array
    {
        $ucProperty = ucfirst($property);
        foreach ($this->accessorPrefixes as $prefix) {
            try {
                $reflectionMethod = new \ReflectionMethod($class, $prefix . $ucProperty);
                if ($reflectionMethod->isStatic()) {
                    continue;
                }
                if (0 === $reflectionMethod->getNumberOfRequiredParameters()) {
                    return [$reflectionMethod, $prefix];
                }
            } catch (\ReflectionException) {
                // Return null if the property doesn't exist
            }
        }
        return null;
    }
    /**
     * Returns an array with a the instance of \ReflectionMethod as first key
     * and the prefix of the method as second or null if not found.
     */
    private function getMutatorMethod(string $class, string $property): ?array
    {
        $ucProperty = ucfirst($property);
        $ucSingulars = $this->inflector->singularize($ucProperty);
        $mutatorPrefixes = \in_array($ucProperty, $ucSingulars, \true) ? $this->arrayMutatorPrefixesLast : $this->arrayMutatorPrefixesFirst;
        foreach ($mutatorPrefixes as $prefix) {
            $names = [$ucProperty];
            if (\in_array($prefix, $this->arrayMutatorPrefixes)) {
                $names = array_merge($names, $ucSingulars);
            }
            foreach ($names as $name) {
                try {
                    $reflectionMethod = new \ReflectionMethod($class, $prefix . $name);
                    if ($reflectionMethod->isStatic()) {
                        continue;
                    }
                    // Parameter can be optional to allow things like: method(?array $foo = null)
                    if ($reflectionMethod->getNumberOfParameters() >= 1) {
                        return [$reflectionMethod, $prefix];
                    }
                } catch (\ReflectionException) {
                    // Try the next prefix if the method doesn't exist
                }
            }
        }
        return null;
    }
    private function getPropertyName(string $methodName, array $reflectionProperties): ?string
    {
        $pattern = implode('|', array_merge($this->accessorPrefixes, $this->mutatorPrefixes));
        if ('' !== $pattern && preg_match('/^(' . $pattern . ')(.+)$/i', $methodName, $matches)) {
            if (!\in_array($matches[1], $this->arrayMutatorPrefixes)) {
                return $matches[2];
            }
            foreach ($reflectionProperties as $reflectionProperty) {
                foreach ($this->inflector->singularize($reflectionProperty->name) as $name) {
                    if (strtolower($name) === strtolower($matches[2])) {
                        return $reflectionProperty->name;
                    }
                }
            }
            return $matches[2];
        }
        return null;
    }
    /**
     * Searches for add and remove methods.
     *
     * @param \ReflectionClass $reflClass The reflection class for the given object
     * @param array            $singulars The singular form of the property name or null
     *
     * @return array An array containing the adder and remover when found and errors
     */
    private function findAdderAndRemover(\ReflectionClass $reflClass, array $singulars): array
    {
        if (!\is_array($this->arrayMutatorPrefixes) && 2 !== \count($this->arrayMutatorPrefixes)) {
            return [null, null, []];
        }
        [$addPrefix, $removePrefix] = $this->arrayMutatorPrefixes;
        $errors = [];
        foreach ($singulars as $singular) {
            $addMethod = $addPrefix . $singular;
            $removeMethod = $removePrefix . $singular;
            [$addMethodFound, $addMethodAccessibleErrors] = $this->isMethodAccessible($reflClass, $addMethod, 1);
            [$removeMethodFound, $removeMethodAccessibleErrors] = $this->isMethodAccessible($reflClass, $removeMethod, 1);
            $errors[] = $addMethodAccessibleErrors;
            $errors[] = $removeMethodAccessibleErrors;
            if ($addMethodFound && $removeMethodFound) {
                return [$addMethod, $removeMethod, []];
            }
            if ($addMethodFound && !$removeMethodFound) {
                $errors[] = [\sprintf('The add method "%s" in class "%s" was found, but the corresponding remove method "%s" was not found', $addMethod, $reflClass->getName(), $removeMethod)];
            } elseif (!$addMethodFound && $removeMethodFound) {
                $errors[] = [\sprintf('The remove method "%s" in class "%s" was found, but the corresponding add method "%s" was not found', $removeMethod, $reflClass->getName(), $addMethod)];
            }
        }
        return [null, null, array_merge([], ...$errors)];
    }
    /**
     * Returns whether a method is public and has the number of required parameters and errors.
     */
    private function isMethodAccessible(\ReflectionClass $class, string $methodName, int $parameters): array
    {
        $errors = [];
        if ($class->hasMethod($methodName)) {
            $method = $class->getMethod($methodName);
            if (\ReflectionMethod::IS_PUBLIC === $this->methodReflectionFlags && !$method->isPublic()) {
                $errors[] = \sprintf('The method "%s" in class "%s" was found but does not have public access.', $methodName, $class->getName());
            } elseif ($method->getNumberOfRequiredParameters() > $parameters || $method->getNumberOfParameters() < $parameters) {
                $errors[] = \sprintf('The method "%s" in class "%s" requires %d arguments, but should accept only %d.', $methodName, $class->getName(), $method->getNumberOfRequiredParameters(), $parameters);
            } else {
                return [\true, $errors];
            }
        }
        return [\false, $errors];
    }
    /**
     * Camelizes a given string.
     */
    private function camelize(string $string): string
    {
        if ('' === ltrim($string, '_')) {
            return $string;
        }
        return str_replace(' ', '', ucwords(str_replace('_', ' ', $string)));
    }
    /**
     * Return allowed reflection method flags.
     */
    private function getMethodsFlags(int $accessFlags): int
    {
        $methodFlags = 0;
        if ($accessFlags & self::ALLOW_PUBLIC) {
            $methodFlags |= \ReflectionMethod::IS_PUBLIC;
        }
        if ($accessFlags & self::ALLOW_PRIVATE) {
            $methodFlags |= \ReflectionMethod::IS_PRIVATE;
        }
        if ($accessFlags & self::ALLOW_PROTECTED) {
            $methodFlags |= \ReflectionMethod::IS_PROTECTED;
        }
        return $methodFlags;
    }
    /**
     * Return allowed reflection property flags.
     */
    private function getPropertyFlags(int $accessFlags): int
    {
        $propertyFlags = 0;
        if ($accessFlags & self::ALLOW_PUBLIC) {
            $propertyFlags |= \ReflectionProperty::IS_PUBLIC;
        }
        if ($accessFlags & self::ALLOW_PRIVATE) {
            $propertyFlags |= \ReflectionProperty::IS_PRIVATE;
        }
        if ($accessFlags & self::ALLOW_PROTECTED) {
            $propertyFlags |= \ReflectionProperty::IS_PROTECTED;
        }
        return $propertyFlags;
    }
    private function getReadVisibilityForProperty(\ReflectionProperty $reflectionProperty): string
    {
        if ($reflectionProperty->isPrivate()) {
            return PropertyReadInfo::VISIBILITY_PRIVATE;
        }
        if ($reflectionProperty->isProtected()) {
            return PropertyReadInfo::VISIBILITY_PROTECTED;
        }
        return PropertyReadInfo::VISIBILITY_PUBLIC;
    }
    private function getReadVisibilityForMethod(\ReflectionMethod $reflectionMethod): string
    {
        if ($reflectionMethod->isPrivate()) {
            return PropertyReadInfo::VISIBILITY_PRIVATE;
        }
        if ($reflectionMethod->isProtected()) {
            return PropertyReadInfo::VISIBILITY_PROTECTED;
        }
        return PropertyReadInfo::VISIBILITY_PUBLIC;
    }
    private function getWriteVisibilityForProperty(\ReflectionProperty $reflectionProperty): string
    {
        if (\PHP_VERSION_ID >= 80400) {
            if ($reflectionProperty->isVirtual() && !$reflectionProperty->hasHook(\PropertyHookType::Set)) {
                return PropertyWriteInfo::VISIBILITY_PRIVATE;
            }
            if ($reflectionProperty->isPrivateSet()) {
                return PropertyWriteInfo::VISIBILITY_PRIVATE;
            }
            if ($reflectionProperty->isProtectedSet()) {
                return PropertyWriteInfo::VISIBILITY_PROTECTED;
            }
        }
        if ($reflectionProperty->isPrivate()) {
            return PropertyWriteInfo::VISIBILITY_PRIVATE;
        }
        if ($reflectionProperty->isProtected()) {
            return PropertyWriteInfo::VISIBILITY_PROTECTED;
        }
        return PropertyWriteInfo::VISIBILITY_PUBLIC;
    }
    private function getWriteVisibilityForMethod(\ReflectionMethod $reflectionMethod): string
    {
        if ($reflectionMethod->isPrivate()) {
            return PropertyWriteInfo::VISIBILITY_PRIVATE;
        }
        if ($reflectionMethod->isProtected()) {
            return PropertyWriteInfo::VISIBILITY_PROTECTED;
        }
        return PropertyWriteInfo::VISIBILITY_PUBLIC;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\PropertyInfo\Extractor;

use _ContaoManager\phpDocumentor\Reflection\DocBlock;
use _ContaoManager\phpDocumentor\Reflection\DocBlock\Tags\Factory\StaticMethod;
use _ContaoManager\phpDocumentor\Reflection\DocBlock\Tags\Generic;
use _ContaoManager\phpDocumentor\Reflection\DocBlock\Tags\InvalidTag;
use _ContaoManager\phpDocumentor\Reflection\DocBlockFactory;
use _ContaoManager\phpDocumentor\Reflection\DocBlockFactoryInterface;
use _ContaoManager\phpDocumentor\Reflection\Types\Context;
use _ContaoManager\phpDocumentor\Reflection\Types\ContextFactory;
use _ContaoManager\Symfony\Component\PropertyInfo\PropertyDescriptionExtractorInterface;
use _ContaoManager\Symfony\Component\PropertyInfo\PropertyTypeExtractorInterface;
use _ContaoManager\Symfony\Component\PropertyInfo\Type;
use _ContaoManager\Symfony\Component\PropertyInfo\Util\PhpDocTypeHelper;
/**
 * Extracts data using a PHPDoc parser.
 *
 * @author Kévin Dunglas <dunglas@gmail.com>
 *
 * @final
 */
class PhpDocExtractor implements PropertyDescriptionExtractorInterface, PropertyTypeExtractorInterface, ConstructorArgumentTypeExtractorInterface
{
    public const PROPERTY = 0;
    public const ACCESSOR = 1;
    public const MUTATOR = 2;
    /**
     * @var array<string, array{DocBlock|null, int|null, string|null, string|null}>
     */
    private array $docBlocks = [];
    /**
     * @var Context[]
     */
    private array $contexts = [];
    private DocBlockFactoryInterface $docBlockFactory;
    private ContextFactory $contextFactory;
    private PhpDocTypeHelper $phpDocTypeHelper;
    private array $mutatorPrefixes;
    private array $accessorPrefixes;
    private array $arrayMutatorPrefixes;
    /**
     * @param string[]|null $mutatorPrefixes
     * @param string[]|null $accessorPrefixes
     * @param string[]|null $arrayMutatorPrefixes
     */
    public function __construct(?DocBlockFactoryInterface $docBlockFactory = null, ?array $mutatorPrefixes = null, ?array $accessorPrefixes = null, ?array $arrayMutatorPrefixes = null)
    {
        if (!class_exists(DocBlockFactory::class)) {
            throw new \LogicException(\sprintf('Unable to use the "%s" class as the "phpdocumentor/reflection-docblock" package is not installed. Try running composer require "phpdocumentor/reflection-docblock".', __CLASS__));
        }
        if (!is_subclass_of(Generic::class, StaticMethod::class)) {
            throw new \LogicException('symfony/property-info v6 does not support phpdocumentor/reflection-docblock v6. Please stick to ^5.2 in your composer.json file.');
        }
        $this->docBlockFactory = $docBlockFactory ?: DocBlockFactory::createInstance();
        $this->contextFactory = new ContextFactory();
        $this->phpDocTypeHelper = new PhpDocTypeHelper();
        $this->mutatorPrefixes = $mutatorPrefixes ?? ReflectionExtractor::$defaultMutatorPrefixes;
        $this->accessorPrefixes = $accessorPrefixes ?? ReflectionExtractor::$defaultAccessorPrefixes;
        $this->arrayMutatorPrefixes = $arrayMutatorPrefixes ?? ReflectionExtractor::$defaultArrayMutatorPrefixes;
    }
    public function getShortDescription(string $class, string $property, array $context = []): ?string
    {
        /** @var DocBlock $docBlock */
        [$docBlock] = $this->getDocBlock($class, $property);
        if (!$docBlock) {
            return null;
        }
        $shortDescription = $docBlock->getSummary();
        if (!empty($shortDescription)) {
            return $shortDescription;
        }
        foreach ($docBlock->getTagsByName('var') as $var) {
            if ($var && !$var instanceof InvalidTag) {
                $varDescription = $var->getDescription()->render();
                if (!empty($varDescription)) {
                    return $varDescription;
                }
            }
        }
        return null;
    }
    public function getLongDescription(string $class, string $property, array $context = []): ?string
    {
        /** @var DocBlock $docBlock */
        [$docBlock] = $this->getDocBlock($class, $property);
        if (!$docBlock) {
            return null;
        }
        $contents = $docBlock->getDescription()->render();
        return '' === $contents ? null : $contents;
    }
    public function getTypes(string $class, string $property, array $context = []): ?array
    {
        /** @var DocBlock $docBlock */
        [$docBlock, $source, $prefix, $declaringClass] = $this->getDocBlock($class, $property);
        if (!$docBlock) {
            return null;
        }
        $tag = match ($source) {
            self::PROPERTY => 'var',
            self::ACCESSOR => 'return',
            self::MUTATOR => 'param',
        };
        $parentClass = null;
        $types = [];
        /** @var DocBlock\Tags\Var_|DocBlock\Tags\Return_|DocBlock\Tags\Param $tag */
        foreach ($docBlock->getTagsByName($tag) as $tag) {
            if ($tag && !$tag instanceof InvalidTag && null !== $tag->getType()) {
                foreach ($this->phpDocTypeHelper->getTypes($tag->getType()) as $type) {
                    switch ($type->getClassName()) {
                        case 'self':
                            $resolvedClass = $declaringClass ?? $class;
                            break;
                        case 'static':
                            $resolvedClass = $class;
                            break;
                        case 'parent':
                            if (\false !== $resolvedClass = $parentClass ??= get_parent_class($declaringClass ?? $class)) {
                                break;
                            }
                        // no break
                        default:
                            $types[] = $type;
                            continue 2;
                    }
                    $types[] = new Type(Type::BUILTIN_TYPE_OBJECT, $type->isNullable(), $resolvedClass, $type->isCollection(), $type->getCollectionKeyTypes(), $type->getCollectionValueTypes());
                }
            }
        }
        if (!isset($types[0])) {
            return null;
        }
        if (!\in_array($prefix, $this->arrayMutatorPrefixes)) {
            return $types;
        }
        return [new Type(Type::BUILTIN_TYPE_ARRAY, \false, null, \true, new Type(Type::BUILTIN_TYPE_INT), $types[0])];
    }
    public function getTypesFromConstructor(string $class, string $property): ?array
    {
        $docBlock = $this->getDocBlockFromConstructor($class, $property);
        if (!$docBlock) {
            return null;
        }
        $types = [];
        /** @var DocBlock\Tags\Var_|DocBlock\Tags\Return_|DocBlock\Tags\Param $tag */
        foreach ($docBlock->getTagsByName('param') as $tag) {
            if ($tag && null !== $tag->getType()) {
                $types[] = $this->phpDocTypeHelper->getTypes($tag->getType());
            }
        }
        if (!isset($types[0]) || [] === $types[0]) {
            return null;
        }
        return array_merge([], ...$types);
    }
    private function getDocBlockFromConstructor(string $class, string $property): ?DocBlock
    {
        try {
            $reflectionClass = new \ReflectionClass($class);
        } catch (\ReflectionException) {
            return null;
        }
        $reflectionConstructor = $reflectionClass->getConstructor();
        if (!$reflectionConstructor) {
            return null;
        }
        try {
            $docBlock = $this->docBlockFactory->create($reflectionConstructor, $this->contextFactory->createFromReflector($reflectionConstructor));
            return $this->filterDocBlockParams($docBlock, $property);
        } catch (\InvalidArgumentException) {
            return null;
        }
    }
    private function filterDocBlockParams(DocBlock $docBlock, string $allowedParam): DocBlock
    {
        $tags = array_values(array_filter($docBlock->getTagsByName('param'), fn($tag) => $tag instanceof DocBlock\Tags\Param && $allowedParam === $tag->getVariableName()));
        return new DocBlock($docBlock->getSummary(), $docBlock->getDescription(), $tags, $docBlock->getContext(), $docBlock->getLocation(), $docBlock->isTemplateStart(), $docBlock->isTemplateEnd());
    }
    /**
     * @return array{DocBlock|null, int|null, string|null, string|null}
     */
    private function getDocBlock(string $class, string $property): array
    {
        $propertyHash = \sprintf('%s::%s', $class, $property);
        if (isset($this->docBlocks[$propertyHash])) {
            return $this->docBlocks[$propertyHash];
        }
        try {
            $reflectionProperty = new \ReflectionProperty($class, $property);
        } catch (\ReflectionException) {
            $reflectionProperty = null;
        }
        $ucFirstProperty = ucfirst($property);
        switch (\true) {
            case $reflectionProperty?->isPromoted() && $docBlock = $this->getDocBlockFromConstructor($reflectionProperty->class, $property):
                $data = [$docBlock, self::MUTATOR, null, $reflectionProperty->class];
                break;
            case [$docBlock, $declaringClass] = $this->getDocBlockFromProperty($class, $property):
                $data = [$docBlock, self::PROPERTY, null, $declaringClass];
                break;
            case [$docBlock, , $declaringClass] = $this->getDocBlockFromMethod($class, $ucFirstProperty, self::ACCESSOR):
                $data = [$docBlock, self::ACCESSOR, null, $declaringClass];
                break;
            case [$docBlock, $prefix, $declaringClass] = $this->getDocBlockFromMethod($class, $ucFirstProperty, self::MUTATOR):
                $data = [$docBlock, self::MUTATOR, $prefix, $declaringClass];
                break;
            default:
                $data = [null, null, null, null];
        }
        return $this->docBlocks[$propertyHash] = $data;
    }
    /**
     * @return array{DocBlock, string}|null
     */
    private function getDocBlockFromProperty(string $class, string $property, ?string $originalClass = null): ?array
    {
        $originalClass ??= $class;
        // Use a ReflectionProperty instead of $class to get the parent class if applicable
        try {
            $reflectionProperty = new \ReflectionProperty($class, $property);
        } catch (\ReflectionException) {
            return null;
        }
        $reflector = $reflectionProperty->getDeclaringClass();
        foreach ($reflector->getTraits() as $trait) {
            if ($trait->hasProperty($property)) {
                return $this->getDocBlockFromProperty($trait->getName(), $property, $reflector->isTrait() ? $originalClass : $reflector->getName());
            }
        }
        try {
            $declaringClass = $reflector->isTrait() ? $originalClass : $reflector->getName();
            return [$this->docBlockFactory->create($reflectionProperty, $this->createFromReflector($reflector)), $declaringClass];
        } catch (\InvalidArgumentException|\RuntimeException) {
            return null;
        }
    }
    /**
     * @return array{DocBlock, string, string}|null
     */
    private function getDocBlockFromMethod(string $class, string $ucFirstProperty, int $type, ?string $originalClass = null): ?array
    {
        $originalClass ??= $class;
        $prefixes = self::ACCESSOR === $type ? $this->accessorPrefixes : $this->mutatorPrefixes;
        $prefix = null;
        $method = null;
        foreach ($prefixes as $prefix) {
            $methodName = $prefix . $ucFirstProperty;
            try {
                $method = new \ReflectionMethod($class, $methodName);
                if ($method->isStatic()) {
                    continue;
                }
                if (self::ACCESSOR === $type && \in_array((string) $method->getReturnType(), ['void', 'never'], \true)) {
                    continue;
                }
                if (self::ACCESSOR === $type && !$method->getNumberOfRequiredParameters() || self::MUTATOR === $type && $method->getNumberOfParameters() >= 1) {
                    break;
                }
            } catch (\ReflectionException) {
                // Try the next prefix if the method doesn't exist
            }
        }
        if (!$method) {
            return null;
        }
        $reflector = $method->getDeclaringClass();
        foreach ($reflector->getTraits() as $trait) {
            if ($trait->hasMethod($methodName)) {
                return $this->getDocBlockFromMethod($trait->getName(), $ucFirstProperty, $type, $reflector->isTrait() ? $originalClass : $reflector->getName());
            }
        }
        try {
            $declaringClass = $reflector->isTrait() ? $originalClass : $reflector->getName();
            return [$this->docBlockFactory->create($method, $this->createFromReflector($reflector)), $prefix, $declaringClass];
        } catch (\InvalidArgumentException|\RuntimeException) {
            return null;
        }
    }
    /**
     * Prevents a lot of redundant calls to ContextFactory::createForNamespace().
     */
    private function createFromReflector(\ReflectionClass $reflector): Context
    {
        $cacheKey = $reflector->getNamespaceName() . ':' . $reflector->getFileName();
        if (isset($this->contexts[$cacheKey])) {
            return $this->contexts[$cacheKey];
        }
        $this->contexts[$cacheKey] = $this->contextFactory->createFromReflector($reflector);
        return $this->contexts[$cacheKey];
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\PropertyInfo;

/**
 * Guesses the property's human readable description.
 *
 * @author Kévin Dunglas <dunglas@gmail.com>
 */
interface PropertyDescriptionExtractorInterface
{
    /**
     * Gets the short description of the property.
     */
    public function getShortDescription(string $class, string $property, array $context = []): ?string;
    /**
     * Gets the long description of the property.
     */
    public function getLongDescription(string $class, string $property, array $context = []): ?string;
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\PropertyInfo;

/**
 * The write mutator defines how a property can be written.
 *
 * @author Joel Wurtz <jwurtz@jolicode.com>
 */
final class PropertyWriteInfo
{
    public const TYPE_NONE = 'none';
    public const TYPE_METHOD = 'method';
    public const TYPE_PROPERTY = 'property';
    public const TYPE_ADDER_AND_REMOVER = 'adder_and_remover';
    public const TYPE_CONSTRUCTOR = 'constructor';
    public const VISIBILITY_PUBLIC = 'public';
    public const VISIBILITY_PROTECTED = 'protected';
    public const VISIBILITY_PRIVATE = 'private';
    private ?self $adderInfo = null;
    private ?self $removerInfo = null;
    private array $errors = [];
    public function __construct(private readonly string $type = self::TYPE_NONE, private readonly ?string $name = null, private readonly ?string $visibility = null, private readonly ?bool $static = null)
    {
    }
    public function getType(): string
    {
        return $this->type;
    }
    public function getName(): string
    {
        if (null === $this->name) {
            throw new \LogicException("Calling getName() when having a mutator of type {$this->type} is not tolerated.");
        }
        return $this->name;
    }
    public function setAdderInfo(self $adderInfo): void
    {
        $this->adderInfo = $adderInfo;
    }
    public function getAdderInfo(): self
    {
        if (null === $this->adderInfo) {
            throw new \LogicException("Calling getAdderInfo() when having a mutator of type {$this->type} is not tolerated.");
        }
        return $this->adderInfo;
    }
    public function setRemoverInfo(self $removerInfo): void
    {
        $this->removerInfo = $removerInfo;
    }
    public function getRemoverInfo(): self
    {
        if (null === $this->removerInfo) {
            throw new \LogicException("Calling getRemoverInfo() when having a mutator of type {$this->type} is not tolerated.");
        }
        return $this->removerInfo;
    }
    public function getVisibility(): string
    {
        if (null === $this->visibility) {
            throw new \LogicException("Calling getVisibility() when having a mutator of type {$this->type} is not tolerated.");
        }
        return $this->visibility;
    }
    public function isStatic(): bool
    {
        if (null === $this->static) {
            throw new \LogicException("Calling isStatic() when having a mutator of type {$this->type} is not tolerated.");
        }
        return $this->static;
    }
    public function setErrors(array $errors): void
    {
        $this->errors = $errors;
    }
    public function getErrors(): array
    {
        return $this->errors;
    }
    public function hasErrors(): bool
    {
        return (bool) \count($this->errors);
    }
}
PropertyInfo Component
======================

The PropertyInfo component extracts information about PHP class' properties
using metadata of popular sources.

Resources
---------

 * [Documentation](https://symfony.com/doc/current/components/property_info.html)
 * [Contributing](https://symfony.com/doc/current/contributing/index.html)
 * [Report issues](https://github.com/symfony/symfony/issues) and
   [send Pull Requests](https://github.com/symfony/symfony/pulls)
   in the [main Symfony repository](https://github.com/symfony/symfony)
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\PropertyInfo;

/**
 * Extract read information for the property of a class.
 *
 * @author Joel Wurtz <jwurtz@jolicode.com>
 */
interface PropertyReadInfoExtractorInterface
{
    /**
     * Get read information object for a given property of a class.
     */
    public function getReadInfo(string $class, string $property, array $context = []): ?PropertyReadInfo;
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\PropertyInfo;

/**
 * Guesses if the property can be initialized through the constructor.
 *
 * @author Kévin Dunglas <dunglas@gmail.com>
 */
interface PropertyInitializableExtractorInterface
{
    /**
     * Is the property initializable? Returns true if a constructor's parameter matches the given property name.
     */
    public function isInitializable(string $class, string $property, array $context = []): ?bool;
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\PropertyInfo;

/**
 * Default {@see PropertyInfoExtractorInterface} implementation.
 *
 * @author Kévin Dunglas <dunglas@gmail.com>
 *
 * @final
 */
class PropertyInfoExtractor implements PropertyInfoExtractorInterface, PropertyInitializableExtractorInterface
{
    /**
     * @param iterable<mixed, PropertyListExtractorInterface>          $listExtractors
     * @param iterable<mixed, PropertyTypeExtractorInterface>          $typeExtractors
     * @param iterable<mixed, PropertyDescriptionExtractorInterface>   $descriptionExtractors
     * @param iterable<mixed, PropertyAccessExtractorInterface>        $accessExtractors
     * @param iterable<mixed, PropertyInitializableExtractorInterface> $initializableExtractors
     */
    public function __construct(private readonly iterable $listExtractors = [], private readonly iterable $typeExtractors = [], private readonly iterable $descriptionExtractors = [], private readonly iterable $accessExtractors = [], private readonly iterable $initializableExtractors = [])
    {
    }
    public function getProperties(string $class, array $context = []): ?array
    {
        return $this->extract($this->listExtractors, 'getProperties', [$class, $context]);
    }
    public function getShortDescription(string $class, string $property, array $context = []): ?string
    {
        return $this->extract($this->descriptionExtractors, 'getShortDescription', [$class, $property, $context]);
    }
    public function getLongDescription(string $class, string $property, array $context = []): ?string
    {
        return $this->extract($this->descriptionExtractors, 'getLongDescription', [$class, $property, $context]);
    }
    public function getTypes(string $class, string $property, array $context = []): ?array
    {
        return $this->extract($this->typeExtractors, 'getTypes', [$class, $property, $context]);
    }
    public function isReadable(string $class, string $property, array $context = []): ?bool
    {
        return $this->extract($this->accessExtractors, 'isReadable', [$class, $property, $context]);
    }
    public function isWritable(string $class, string $property, array $context = []): ?bool
    {
        return $this->extract($this->accessExtractors, 'isWritable', [$class, $property, $context]);
    }
    public function isInitializable(string $class, string $property, array $context = []): ?bool
    {
        return $this->extract($this->initializableExtractors, 'isInitializable', [$class, $property, $context]);
    }
    /**
     * Iterates over registered extractors and return the first value found.
     *
     * @param iterable<mixed, object> $extractors
     * @param list<mixed>             $arguments
     */
    private function extract(iterable $extractors, string $method, array $arguments): mixed
    {
        foreach ($extractors as $extractor) {
            if (null !== $value = $extractor->{$method}(...$arguments)) {
                return $value;
            }
        }
        return null;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\PropertyInfo;

/**
 * Extracts the list of properties available for the given class.
 *
 * @author Kévin Dunglas <dunglas@gmail.com>
 */
interface PropertyListExtractorInterface
{
    /**
     * Gets the list of properties available for the given class.
     *
     * @return string[]|null
     */
    public function getProperties(string $class, array $context = []);
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\PropertyInfo\DependencyInjection;

use _ContaoManager\Symfony\Component\DependencyInjection\Argument\IteratorArgument;
use _ContaoManager\Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Compiler\PriorityTaggedServiceTrait;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerBuilder;
/**
 * Adds extractors to the property_info.constructor_extractor service.
 *
 * @author Dmitrii Poddubnyi <dpoddubny@gmail.com>
 */
final class PropertyInfoConstructorPass implements CompilerPassInterface
{
    use PriorityTaggedServiceTrait;
    public function process(ContainerBuilder $container): void
    {
        if (!$container->hasDefinition('property_info.constructor_extractor')) {
            return;
        }
        $definition = $container->getDefinition('property_info.constructor_extractor');
        $listExtractors = $this->findAndSortTaggedServices('property_info.constructor_extractor', $container);
        $definition->replaceArgument(0, new IteratorArgument($listExtractors));
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\PropertyInfo\DependencyInjection;

use _ContaoManager\Symfony\Component\DependencyInjection\Argument\IteratorArgument;
use _ContaoManager\Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Compiler\PriorityTaggedServiceTrait;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerBuilder;
/**
 * Adds extractors to the property_info service.
 *
 * @author Kévin Dunglas <dunglas@gmail.com>
 */
class PropertyInfoPass implements CompilerPassInterface
{
    use PriorityTaggedServiceTrait;
    /**
     * @return void
     */
    public function process(ContainerBuilder $container)
    {
        if (!$container->hasDefinition('property_info')) {
            return;
        }
        $definition = $container->getDefinition('property_info');
        $listExtractors = $this->findAndSortTaggedServices('property_info.list_extractor', $container);
        $definition->replaceArgument(0, new IteratorArgument($listExtractors));
        $typeExtractors = $this->findAndSortTaggedServices('property_info.type_extractor', $container);
        $definition->replaceArgument(1, new IteratorArgument($typeExtractors));
        $descriptionExtractors = $this->findAndSortTaggedServices('property_info.description_extractor', $container);
        $definition->replaceArgument(2, new IteratorArgument($descriptionExtractors));
        $accessExtractors = $this->findAndSortTaggedServices('property_info.access_extractor', $container);
        $definition->replaceArgument(3, new IteratorArgument($accessExtractors));
        $initializableExtractors = $this->findAndSortTaggedServices('property_info.initializable_extractor', $container);
        $definition->setArgument(4, new IteratorArgument($initializableExtractors));
    }
}
{
    "name": "symfony\/property-info",
    "type": "library",
    "description": "Extracts information about PHP class' properties using metadata of popular sources",
    "keywords": [
        "property",
        "type",
        "phpdoc",
        "symfony",
        "validator",
        "doctrine"
    ],
    "homepage": "https:\/\/symfony.com",
    "license": "MIT",
    "authors": [
        {
            "name": "K\u00e9vin Dunglas",
            "email": "dunglas@gmail.com"
        },
        {
            "name": "Symfony Community",
            "homepage": "https:\/\/symfony.com\/contributors"
        }
    ],
    "require": {
        "php": ">=8.1",
        "symfony\/string": "^5.4|^6.0|^7.0"
    },
    "require-dev": {
        "doctrine\/annotations": "^1.12|^2",
        "symfony\/serializer": "^5.4|^6.4|^7.0",
        "symfony\/cache": "^5.4|^6.0|^7.0",
        "symfony\/dependency-injection": "^5.4|^6.0|^7.0",
        "phpdocumentor\/reflection-docblock": "^5.2",
        "phpstan\/phpdoc-parser": "^1.0|^2.0"
    },
    "conflict": {
        "doctrine\/annotations": "<1.12",
        "phpdocumentor\/reflection-docblock": "<5.2|>=6",
        "phpdocumentor\/type-resolver": "<1.5.1",
        "symfony\/dependency-injection": "<5.4|>=6.0,<6.4",
        "symfony\/cache": "<5.4",
        "symfony\/serializer": "<5.4"
    },
    "autoload": {
        "psr-4": {
            "_ContaoManager\\Symfony\\Component\\PropertyInfo\\": ""
        },
        "exclude-from-classmap": [
            "\/Tests\/"
        ]
    },
    "minimum-stability": "dev"
}<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\HttpFoundation;

/**
 * StreamedResponse represents a streamed HTTP response.
 *
 * A StreamedResponse uses a callback for its content.
 *
 * The callback should use the standard PHP functions like echo
 * to stream the response back to the client. The flush() function
 * can also be used if needed.
 *
 * @see flush()
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class StreamedResponse extends Response
{
    protected $callback;
    protected $streamed;
    private bool $headersSent;
    /**
     * @param int $status The HTTP status code (200 "OK" by default)
     */
    public function __construct(?callable $callback = null, int $status = 200, array $headers = [])
    {
        parent::__construct(null, $status, $headers);
        if (null !== $callback) {
            $this->setCallback($callback);
        }
        $this->streamed = \false;
        $this->headersSent = \false;
    }
    /**
     * Sets the PHP callback associated with this Response.
     *
     * @return $this
     */
    public function setCallback(callable $callback): static
    {
        $this->callback = $callback(...);
        return $this;
    }
    public function getCallback(): ?\Closure
    {
        if (!isset($this->callback)) {
            return null;
        }
        return ($this->callback)(...);
    }
    /**
     * This method only sends the headers once.
     *
     * @param positive-int|null $statusCode The status code to use, override the statusCode property if set and not null
     *
     * @return $this
     */
    public function sendHeaders(): static
    {
        if ($this->headersSent) {
            return $this;
        }
        $statusCode = \func_num_args() > 0 ? func_get_arg(0) : null;
        if ($statusCode < 100 || $statusCode >= 200) {
            $this->headersSent = \true;
        }
        return parent::sendHeaders($statusCode);
    }
    /**
     * This method only sends the content once.
     *
     * @return $this
     */
    public function sendContent(): static
    {
        if ($this->streamed) {
            return $this;
        }
        $this->streamed = \true;
        if (!isset($this->callback)) {
            throw new \LogicException('The Response callback must be set.');
        }
        ($this->callback)();
        return $this;
    }
    /**
     * @return $this
     *
     * @throws \LogicException when the content is not null
     */
    public function setContent(?string $content): static
    {
        if (null !== $content) {
            throw new \LogicException('The content cannot be set on a StreamedResponse instance.');
        }
        $this->streamed = \true;
        return $this;
    }
    public function getContent(): string|false
    {
        return \false;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\HttpFoundation;

/**
 * RequestMatcherInterface is an interface for strategies to match a Request.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
interface RequestMatcherInterface
{
    /**
     * Decides whether the rule(s) implemented by the strategy matches the supplied request.
     */
    public function matches(Request $request): bool;
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\HttpFoundation;

use _ContaoManager\Symfony\Component\HttpFoundation\File\Exception\FileException;
use _ContaoManager\Symfony\Component\HttpFoundation\File\File;
/**
 * BinaryFileResponse represents an HTTP response delivering a file.
 *
 * @author Niklas Fiekas <niklas.fiekas@tu-clausthal.de>
 * @author stealth35 <stealth35-php@live.fr>
 * @author Igor Wiedler <igor@wiedler.ch>
 * @author Jordan Alliot <jordan.alliot@gmail.com>
 * @author Sergey Linnik <linniksa@gmail.com>
 */
class BinaryFileResponse extends Response
{
    protected static $trustXSendfileTypeHeader = \false;
    /**
     * @var File
     */
    protected $file;
    protected $offset = 0;
    protected $maxlen = -1;
    protected $deleteFileAfterSend = \false;
    protected $chunkSize = 16 * 1024;
    /**
     * @param \SplFileInfo|string $file               The file to stream
     * @param int                 $status             The response status code (200 "OK" by default)
     * @param array               $headers            An array of response headers
     * @param bool                $public             Files are public by default
     * @param string|null         $contentDisposition The type of Content-Disposition to set automatically with the filename
     * @param bool                $autoEtag           Whether the ETag header should be automatically set
     * @param bool                $autoLastModified   Whether the Last-Modified header should be automatically set
     */
    public function __construct(\SplFileInfo|string $file, int $status = 200, array $headers = [], bool $public = \true, ?string $contentDisposition = null, bool $autoEtag = \false, bool $autoLastModified = \true)
    {
        parent::__construct(null, $status, $headers);
        $this->setFile($file, $contentDisposition, $autoEtag, $autoLastModified);
        if ($public) {
            $this->setPublic();
        }
    }
    /**
     * Sets the file to stream.
     *
     * @return $this
     *
     * @throws FileException
     */
    public function setFile(\SplFileInfo|string $file, ?string $contentDisposition = null, bool $autoEtag = \false, bool $autoLastModified = \true): static
    {
        if (!$file instanceof File) {
            if ($file instanceof \SplFileInfo) {
                $file = new File($file->getPathname());
            } else {
                $file = new File((string) $file);
            }
        }
        if (!$file->isReadable()) {
            throw new FileException('File must be readable.');
        }
        $this->file = $file;
        if ($autoEtag) {
            $this->setAutoEtag();
        }
        if ($autoLastModified) {
            $this->setAutoLastModified();
        }
        if ($contentDisposition) {
            $this->setContentDisposition($contentDisposition);
        }
        return $this;
    }
    /**
     * Gets the file.
     */
    public function getFile(): File
    {
        return $this->file;
    }
    /**
     * Sets the response stream chunk size.
     *
     * @return $this
     */
    public function setChunkSize(int $chunkSize): static
    {
        if ($chunkSize < 1 || $chunkSize > \PHP_INT_MAX) {
            throw new \LogicException('The chunk size of a BinaryFileResponse cannot be less than 1 or greater than PHP_INT_MAX.');
        }
        $this->chunkSize = $chunkSize;
        return $this;
    }
    /**
     * Automatically sets the Last-Modified header according the file modification date.
     *
     * @return $this
     */
    public function setAutoLastModified(): static
    {
        $this->setLastModified(\DateTimeImmutable::createFromFormat('U', $this->file->getMTime()));
        return $this;
    }
    /**
     * Automatically sets the ETag header according to the checksum of the file.
     *
     * @return $this
     */
    public function setAutoEtag(): static
    {
        $this->setEtag(base64_encode(hash_file('sha256', $this->file->getPathname(), \true)));
        return $this;
    }
    /**
     * Sets the Content-Disposition header with the given filename.
     *
     * @param string $disposition      ResponseHeaderBag::DISPOSITION_INLINE or ResponseHeaderBag::DISPOSITION_ATTACHMENT
     * @param string $filename         Optionally use this UTF-8 encoded filename instead of the real name of the file
     * @param string $filenameFallback A fallback filename, containing only ASCII characters. Defaults to an automatically encoded filename
     *
     * @return $this
     */
    public function setContentDisposition(string $disposition, string $filename = '', string $filenameFallback = ''): static
    {
        if ('' === $filename) {
            $filename = $this->file->getFilename();
        }
        if ('' === $filenameFallback && (!preg_match('/^[\x20-\x7e]*$/', $filename) || str_contains($filename, '%'))) {
            $encoding = mb_detect_encoding($filename, null, \true) ?: '8bit';
            for ($i = 0, $filenameLength = mb_strlen($filename, $encoding); $i < $filenameLength; ++$i) {
                $char = mb_substr($filename, $i, 1, $encoding);
                if ('%' === $char || \ord($char[0]) < 32 || \ord($char[0]) > 126) {
                    $filenameFallback .= '_';
                } else {
                    $filenameFallback .= $char;
                }
            }
        }
        $dispositionHeader = $this->headers->makeDisposition($disposition, $filename, $filenameFallback);
        $this->headers->set('Content-Disposition', $dispositionHeader);
        return $this;
    }
    public function prepare(Request $request): static
    {
        if ($this->isInformational() || $this->isEmpty()) {
            parent::prepare($request);
            $this->maxlen = 0;
            return $this;
        }
        if (!$this->headers->has('Content-Type')) {
            $this->headers->set('Content-Type', $this->file->getMimeType() ?: 'application/octet-stream');
        }
        parent::prepare($request);
        $this->offset = 0;
        $this->maxlen = -1;
        if (\false === $fileSize = $this->file->getSize()) {
            return $this;
        }
        $this->headers->remove('Transfer-Encoding');
        $this->headers->set('Content-Length', $fileSize);
        if (!$this->headers->has('Accept-Ranges')) {
            // Only accept ranges on safe HTTP methods
            $this->headers->set('Accept-Ranges', $request->isMethodSafe() ? 'bytes' : 'none');
        }
        if (self::$trustXSendfileTypeHeader && $request->headers->has('X-Sendfile-Type')) {
            // Use X-Sendfile, do not send any content.
            $type = $request->headers->get('X-Sendfile-Type');
            $path = $this->file->getRealPath();
            // Fall back to scheme://path for stream wrapped locations.
            if (\false === $path) {
                $path = $this->file->getPathname();
            }
            if ('x-accel-redirect' === strtolower($type)) {
                // Do X-Accel-Mapping substitutions.
                // @link https://github.com/rack/rack/blob/main/lib/rack/sendfile.rb
                // @link https://mattbrictson.com/blog/accelerated-rails-downloads
                if (!$request->headers->has('X-Accel-Mapping')) {
                    throw new \LogicException('The "X-Accel-Mapping" header must be set when "X-Sendfile-Type" is set to "X-Accel-Redirect".');
                }
                $parts = HeaderUtils::split($request->headers->get('X-Accel-Mapping'), ',=');
                foreach ($parts as $part) {
                    [$pathPrefix, $location] = $part;
                    if (str_starts_with($path, $pathPrefix)) {
                        $path = $location . substr($path, \strlen($pathPrefix));
                        // Only set X-Accel-Redirect header if a valid URI can be produced
                        // as nginx does not serve arbitrary file paths.
                        $this->headers->set($type, rawurlencode($path));
                        $this->maxlen = 0;
                        break;
                    }
                }
            } else {
                $this->headers->set($type, $path);
                $this->maxlen = 0;
            }
        } elseif ($request->headers->has('Range') && $request->isMethod('GET')) {
            // Process the range headers.
            if (!$request->headers->has('If-Range') || $this->hasValidIfRangeHeader($request->headers->get('If-Range'))) {
                $range = $request->headers->get('Range');
                if (str_starts_with($range, 'bytes=')) {
                    [$start, $end] = explode('-', substr($range, 6), 2) + [1 => 0];
                    $end = '' === $end ? $fileSize - 1 : (int) $end;
                    if ('' === $start) {
                        $start = $fileSize - $end;
                        $end = $fileSize - 1;
                    } else {
                        $start = (int) $start;
                    }
                    if ($start <= $end) {
                        $end = min($end, $fileSize - 1);
                        if ($start < 0 || $start > $end) {
                            $this->setStatusCode(416);
                            $this->headers->set('Content-Range', \sprintf('bytes */%s', $fileSize));
                        } else {
                            $this->maxlen = $end < $fileSize ? $end - $start + 1 : -1;
                            $this->offset = $start;
                            $this->setStatusCode(206);
                            $this->headers->set('Content-Range', \sprintf('bytes %s-%s/%s', $start, $end, $fileSize));
                            $this->headers->set('Content-Length', $end - $start + 1);
                        }
                    }
                }
            }
        }
        if ($request->isMethod('HEAD')) {
            $this->maxlen = 0;
        }
        return $this;
    }
    private function hasValidIfRangeHeader(?string $header): bool
    {
        if ($this->getEtag() === $header) {
            return \true;
        }
        if (null === $lastModified = $this->getLastModified()) {
            return \false;
        }
        return $lastModified->format('D, d M Y H:i:s') . ' GMT' === $header;
    }
    public function sendContent(): static
    {
        try {
            if (!$this->isSuccessful()) {
                return $this;
            }
            if (0 === $this->maxlen) {
                return $this;
            }
            $out = fopen('php://output', 'w');
            $file = fopen($this->file->getPathname(), 'r');
            ignore_user_abort(\true);
            if (0 !== $this->offset) {
                fseek($file, $this->offset);
            }
            $length = $this->maxlen;
            while ($length && !feof($file)) {
                $read = $length > $this->chunkSize || 0 > $length ? $this->chunkSize : $length;
                if (\false === $data = fread($file, $read)) {
                    break;
                }
                while ('' !== $data) {
                    $read = fwrite($out, $data);
                    if (\false === $read || connection_aborted()) {
                        break 2;
                    }
                    if (0 < $length) {
                        $length -= $read;
                    }
                    $data = substr($data, $read);
                }
            }
            fclose($out);
            fclose($file);
        } finally {
            if ($this->deleteFileAfterSend && is_file($this->file->getPathname())) {
                unlink($this->file->getPathname());
            }
        }
        return $this;
    }
    /**
     * @throws \LogicException when the content is not null
     */
    public function setContent(?string $content): static
    {
        if (null !== $content) {
            throw new \LogicException('The content cannot be set on a BinaryFileResponse instance.');
        }
        return $this;
    }
    public function getContent(): string|false
    {
        return \false;
    }
    /**
     * Trust X-Sendfile-Type header.
     *
     * @return void
     */
    public static function trustXSendfileTypeHeader()
    {
        self::$trustXSendfileTypeHeader = \true;
    }
    /**
     * If this is set to true, the file will be unlinked after the request is sent
     * Note: If the X-Sendfile header is used, the deleteFileAfterSend setting will not be used.
     *
     * @return $this
     */
    public function deleteFileAfterSend(bool $shouldDelete = \true): static
    {
        $this->deleteFileAfterSend = $shouldDelete;
        return $this;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\HttpFoundation;

use _ContaoManager\Symfony\Component\HttpFoundation\Exception\BadRequestException;
use _ContaoManager\Symfony\Component\HttpFoundation\Exception\UnexpectedValueException;
/**
 * InputBag is a container for user input values such as $_GET, $_POST, $_REQUEST, and $_COOKIE.
 *
 * @author Saif Eddin Gmati <azjezz@protonmail.com>
 */
final class InputBag extends ParameterBag
{
    /**
     * Returns a scalar input value by name.
     *
     * @param string|int|float|bool|null $default The default value if the input key does not exist
     */
    public function get(string $key, mixed $default = null): string|int|float|bool|null
    {
        if (null !== $default && !\is_scalar($default) && !$default instanceof \Stringable) {
            throw new \InvalidArgumentException(\sprintf('Expected a scalar value as a 2nd argument to "%s()", "%s" given.', __METHOD__, get_debug_type($default)));
        }
        $value = parent::get($key, $this);
        if (null !== $value && $this !== $value && !\is_scalar($value) && !$value instanceof \Stringable) {
            throw new BadRequestException(\sprintf('Input value "%s" contains a non-scalar value.', $key));
        }
        return $this === $value ? $default : $value;
    }
    /**
     * Replaces the current input values by a new set.
     */
    public function replace(array $inputs = []): void
    {
        $this->parameters = [];
        $this->add($inputs);
    }
    /**
     * Adds input values.
     */
    public function add(array $inputs = []): void
    {
        foreach ($inputs as $input => $value) {
            $this->set($input, $value);
        }
    }
    /**
     * Sets an input by name.
     *
     * @param string|int|float|bool|array|null $value
     */
    public function set(string $key, mixed $value): void
    {
        if (null !== $value && !\is_scalar($value) && !\is_array($value) && !$value instanceof \Stringable) {
            throw new \InvalidArgumentException(\sprintf('Expected a scalar, or an array as a 2nd argument to "%s()", "%s" given.', __METHOD__, get_debug_type($value)));
        }
        $this->parameters[$key] = $value;
    }
    /**
     * Returns the parameter value converted to an enum.
     *
     * @template T of \BackedEnum
     *
     * @param class-string<T> $class
     * @param ?T              $default
     *
     * @return ?T
     */
    public function getEnum(string $key, string $class, ?\BackedEnum $default = null): ?\BackedEnum
    {
        try {
            return parent::getEnum($key, $class, $default);
        } catch (UnexpectedValueException $e) {
            throw new BadRequestException($e->getMessage(), $e->getCode(), $e);
        }
    }
    /**
     * Returns the parameter value converted to string.
     */
    public function getString(string $key, string $default = ''): string
    {
        // Shortcuts the parent method because the validation on scalar is already done in get().
        return (string) $this->get($key, $default);
    }
    public function filter(string $key, mixed $default = null, int $filter = \FILTER_DEFAULT, mixed $options = []): mixed
    {
        $value = $this->has($key) ? $this->all()[$key] : $default;
        // Always turn $options into an array - this allows filter_var option shortcuts.
        if (!\is_array($options) && $options) {
            $options = ['flags' => $options];
        }
        if (\is_array($value) && !(($options['flags'] ?? 0) & (\FILTER_REQUIRE_ARRAY | \FILTER_FORCE_ARRAY))) {
            throw new BadRequestException(\sprintf('Input value "%s" contains an array, but "FILTER_REQUIRE_ARRAY" or "FILTER_FORCE_ARRAY" flags were not set.', $key));
        }
        if (\FILTER_CALLBACK & $filter && !($options['options'] ?? null) instanceof \Closure) {
            throw new \InvalidArgumentException(\sprintf('A Closure must be passed to "%s()" when FILTER_CALLBACK is used, "%s" given.', __METHOD__, get_debug_type($options['options'] ?? null)));
        }
        $options['flags'] ??= 0;
        $nullOnFailure = $options['flags'] & \FILTER_NULL_ON_FAILURE;
        $options['flags'] |= \FILTER_NULL_ON_FAILURE;
        $value = filter_var($value, $filter, $options);
        if (null !== $value || $nullOnFailure) {
            return $value;
        }
        $method = debug_backtrace(\DEBUG_BACKTRACE_IGNORE_ARGS | \DEBUG_BACKTRACE_PROVIDE_OBJECT, 2)[1];
        $method = ($method['object'] ?? null) === $this ? $method['function'] : 'filter';
        $hint = 'filter' === $method ? 'pass' : 'use method "filter()" with';
        trigger_deprecation('symfony/http-foundation', '6.3', 'Ignoring invalid values when using "%s::%s(\'%s\')" is deprecated and will throw a "%s" in 7.0; ' . $hint . ' flag "FILTER_NULL_ON_FAILURE" to keep ignoring them.', $this::class, $method, $key, BadRequestException::class);
        return \false;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\HttpFoundation\RateLimiter;

use _ContaoManager\Symfony\Component\HttpFoundation\Request;
use _ContaoManager\Symfony\Component\RateLimiter\LimiterInterface;
use _ContaoManager\Symfony\Component\RateLimiter\Policy\NoLimiter;
use _ContaoManager\Symfony\Component\RateLimiter\RateLimit;
/**
 * An implementation of PeekableRequestRateLimiterInterface that
 * fits most use-cases.
 *
 * @author Wouter de Jong <wouter@wouterj.nl>
 */
abstract class AbstractRequestRateLimiter implements PeekableRequestRateLimiterInterface
{
    public function consume(Request $request): RateLimit
    {
        return $this->doConsume($request, 1);
    }
    public function peek(Request $request): RateLimit
    {
        return $this->doConsume($request, 0);
    }
    private function doConsume(Request $request, int $tokens): RateLimit
    {
        $limiters = $this->getLimiters($request);
        if (0 === \count($limiters)) {
            $limiters = [new NoLimiter()];
        }
        $minimalRateLimit = null;
        foreach ($limiters as $limiter) {
            $rateLimit = $limiter->consume($tokens);
            $minimalRateLimit = $minimalRateLimit ? self::getMinimalRateLimit($minimalRateLimit, $rateLimit) : $rateLimit;
        }
        return $minimalRateLimit;
    }
    public function reset(Request $request): void
    {
        foreach ($this->getLimiters($request) as $limiter) {
            $limiter->reset();
        }
    }
    /**
     * @return LimiterInterface[] a set of limiters using keys extracted from the request
     */
    abstract protected function getLimiters(Request $request): array;
    private static function getMinimalRateLimit(RateLimit $first, RateLimit $second): RateLimit
    {
        if ($first->isAccepted() !== $second->isAccepted()) {
            return $first->isAccepted() ? $second : $first;
        }
        $firstRemainingTokens = $first->getRemainingTokens();
        $secondRemainingTokens = $second->getRemainingTokens();
        if ($firstRemainingTokens === $secondRemainingTokens) {
            return $first->getRetryAfter() < $second->getRetryAfter() ? $second : $first;
        }
        return $firstRemainingTokens > $secondRemainingTokens ? $second : $first;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\HttpFoundation\RateLimiter;

use _ContaoManager\Symfony\Component\HttpFoundation\Request;
use _ContaoManager\Symfony\Component\RateLimiter\RateLimit;
/**
 * A special type of limiter that deals with requests.
 *
 * This allows to limit on different types of information
 * from the requests.
 *
 * @author Wouter de Jong <wouter@wouterj.nl>
 */
interface RequestRateLimiterInterface
{
    public function consume(Request $request): RateLimit;
    public function reset(Request $request): void;
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\HttpFoundation\RateLimiter;

use _ContaoManager\Symfony\Component\HttpFoundation\Request;
use _ContaoManager\Symfony\Component\RateLimiter\RateLimit;
/**
 * A request limiter which allows peeking ahead.
 *
 * This is valuable to reduce the cache backend load in scenarios
 * like a login when we only want to consume a token on login failure,
 * and where the majority of requests will be successful and thus not
 * need to consume a token.
 *
 * This way we can peek ahead before allowing the request through, and
 * only consume if the request failed (1 backend op). This is compared
 * to always consuming and then resetting the limit if the request
 * is successful (2 backend ops).
 *
 * @author Jordi Boggiano <j.boggiano@seld.be>
 */
interface PeekableRequestRateLimiterInterface extends RequestRateLimiterInterface
{
    public function peek(Request $request): RateLimit;
}
Copyright (c) 2004-present Fabien Potencier

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is furnished
to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\HttpFoundation\Test\Constraint;

use _ContaoManager\PHPUnit\Framework\Constraint\Constraint;
use _ContaoManager\Symfony\Component\HttpFoundation\Cookie;
use _ContaoManager\Symfony\Component\HttpFoundation\Response;
final class ResponseCookieValueSame extends Constraint
{
    private string $name;
    private string $value;
    private string $path;
    private ?string $domain;
    public function __construct(string $name, string $value, string $path = '/', ?string $domain = null)
    {
        $this->name = $name;
        $this->value = $value;
        $this->path = $path;
        $this->domain = $domain;
    }
    public function toString(): string
    {
        $str = \sprintf('has cookie "%s"', $this->name);
        if ('/' !== $this->path) {
            $str .= \sprintf(' with path "%s"', $this->path);
        }
        if ($this->domain) {
            $str .= \sprintf(' for domain "%s"', $this->domain);
        }
        $str .= \sprintf(' with value "%s"', $this->value);
        return $str;
    }
    /**
     * @param Response $response
     */
    protected function matches($response): bool
    {
        $cookie = $this->getCookie($response);
        if (!$cookie) {
            return \false;
        }
        return $this->value === (string) $cookie->getValue();
    }
    /**
     * @param Response $response
     */
    protected function failureDescription($response): string
    {
        return 'the Response ' . $this->toString();
    }
    protected function getCookie(Response $response): ?Cookie
    {
        $cookies = $response->headers->getCookies();
        $filteredCookies = array_filter($cookies, fn(Cookie $cookie) => $cookie->getName() === $this->name && $cookie->getPath() === $this->path && $cookie->getDomain() === $this->domain);
        return reset($filteredCookies) ?: null;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\HttpFoundation\Test\Constraint;

use _ContaoManager\PHPUnit\Framework\Constraint\Constraint;
use _ContaoManager\Symfony\Component\HttpFoundation\Cookie;
use _ContaoManager\Symfony\Component\HttpFoundation\Response;
final class ResponseHasCookie extends Constraint
{
    private string $name;
    private string $path;
    private ?string $domain;
    public function __construct(string $name, string $path = '/', ?string $domain = null)
    {
        $this->name = $name;
        $this->path = $path;
        $this->domain = $domain;
    }
    public function toString(): string
    {
        $str = \sprintf('has cookie "%s"', $this->name);
        if ('/' !== $this->path) {
            $str .= \sprintf(' with path "%s"', $this->path);
        }
        if ($this->domain) {
            $str .= \sprintf(' for domain "%s"', $this->domain);
        }
        return $str;
    }
    /**
     * @param Response $response
     */
    protected function matches($response): bool
    {
        return null !== $this->getCookie($response);
    }
    /**
     * @param Response $response
     */
    protected function failureDescription($response): string
    {
        return 'the Response ' . $this->toString();
    }
    private function getCookie(Response $response): ?Cookie
    {
        $cookies = $response->headers->getCookies();
        $filteredCookies = array_filter($cookies, fn(Cookie $cookie) => $cookie->getName() === $this->name && $cookie->getPath() === $this->path && $cookie->getDomain() === $this->domain);
        return reset($filteredCookies) ?: null;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\HttpFoundation\Test\Constraint;

use _ContaoManager\PHPUnit\Framework\Constraint\Constraint;
use _ContaoManager\Symfony\Component\HttpFoundation\Request;
use _ContaoManager\Symfony\Component\HttpFoundation\Response;
final class ResponseHeaderLocationSame extends Constraint
{
    public function __construct(private Request $request, private string $expectedValue)
    {
    }
    public function toString(): string
    {
        return \sprintf('has header "Location" matching "%s"', $this->expectedValue);
    }
    protected function matches($other): bool
    {
        if (!$other instanceof Response) {
            return \false;
        }
        $location = $other->headers->get('Location');
        if (null === $location) {
            return \false;
        }
        return $this->toFullUrl($this->expectedValue) === $this->toFullUrl($location);
    }
    protected function failureDescription($other): string
    {
        return 'the Response ' . $this->toString();
    }
    private function toFullUrl(string $url): string
    {
        if (null === parse_url($url, \PHP_URL_PATH)) {
            $url .= '/';
        }
        if (str_starts_with($url, '//')) {
            return \sprintf('%s:%s', $this->request->getScheme(), $url);
        }
        if (str_starts_with($url, '/')) {
            return $this->request->getSchemeAndHttpHost() . $url;
        }
        return $url;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\HttpFoundation\Test\Constraint;

use _ContaoManager\PHPUnit\Framework\Constraint\Constraint;
use _ContaoManager\Symfony\Component\HttpFoundation\Response;
final class ResponseStatusCodeSame extends Constraint
{
    private int $statusCode;
    public function __construct(int $statusCode)
    {
        $this->statusCode = $statusCode;
    }
    public function toString(): string
    {
        return 'status code is ' . $this->statusCode;
    }
    /**
     * @param Response $response
     */
    protected function matches($response): bool
    {
        return $this->statusCode === $response->getStatusCode();
    }
    /**
     * @param Response $response
     */
    protected function failureDescription($response): string
    {
        return 'the Response ' . $this->toString();
    }
    /**
     * @param Response $response
     */
    protected function additionalFailureDescription($response): string
    {
        return (string) $response;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\HttpFoundation\Test\Constraint;

use _ContaoManager\PHPUnit\Framework\Constraint\Constraint;
use _ContaoManager\Symfony\Component\HttpFoundation\Response;
final class ResponseIsSuccessful extends Constraint
{
    public function toString(): string
    {
        return 'is successful';
    }
    /**
     * @param Response $response
     */
    protected function matches($response): bool
    {
        return $response->isSuccessful();
    }
    /**
     * @param Response $response
     */
    protected function failureDescription($response): string
    {
        return 'the Response ' . $this->toString();
    }
    /**
     * @param Response $response
     */
    protected function additionalFailureDescription($response): string
    {
        return (string) $response;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\HttpFoundation\Test\Constraint;

use _ContaoManager\PHPUnit\Framework\Constraint\Constraint;
use _ContaoManager\Symfony\Component\HttpFoundation\Response;
final class ResponseIsUnprocessable extends Constraint
{
    public function toString(): string
    {
        return 'is unprocessable';
    }
    /**
     * @param Response $other
     */
    protected function matches($other): bool
    {
        return Response::HTTP_UNPROCESSABLE_ENTITY === $other->getStatusCode();
    }
    /**
     * @param Response $other
     */
    protected function failureDescription($other): string
    {
        return 'the Response ' . $this->toString();
    }
    /**
     * @param Response $other
     */
    protected function additionalFailureDescription($other): string
    {
        return (string) $other;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\HttpFoundation\Test\Constraint;

use _ContaoManager\PHPUnit\Framework\Constraint\Constraint;
use _ContaoManager\Symfony\Component\HttpFoundation\Response;
final class ResponseIsRedirected extends Constraint
{
    public function toString(): string
    {
        return 'is redirected';
    }
    /**
     * @param Response $response
     */
    protected function matches($response): bool
    {
        return $response->isRedirect();
    }
    /**
     * @param Response $response
     */
    protected function failureDescription($response): string
    {
        return 'the Response ' . $this->toString();
    }
    /**
     * @param Response $response
     */
    protected function additionalFailureDescription($response): string
    {
        return (string) $response;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\HttpFoundation\Test\Constraint;

use _ContaoManager\PHPUnit\Framework\Constraint\Constraint;
use _ContaoManager\Symfony\Component\HttpFoundation\Response;
final class ResponseHasHeader extends Constraint
{
    private string $headerName;
    public function __construct(string $headerName)
    {
        $this->headerName = $headerName;
    }
    public function toString(): string
    {
        return \sprintf('has header "%s"', $this->headerName);
    }
    /**
     * @param Response $response
     */
    protected function matches($response): bool
    {
        return $response->headers->has($this->headerName);
    }
    /**
     * @param Response $response
     */
    protected function failureDescription($response): string
    {
        return 'the Response ' . $this->toString();
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\HttpFoundation\Test\Constraint;

use _ContaoManager\PHPUnit\Framework\Constraint\Constraint;
use _ContaoManager\Symfony\Component\HttpFoundation\Request;
final class RequestAttributeValueSame extends Constraint
{
    private string $name;
    private string $value;
    public function __construct(string $name, string $value)
    {
        $this->name = $name;
        $this->value = $value;
    }
    public function toString(): string
    {
        return \sprintf('has attribute "%s" with value "%s"', $this->name, $this->value);
    }
    /**
     * @param Request $request
     */
    protected function matches($request): bool
    {
        return $this->value === $request->attributes->get($this->name);
    }
    /**
     * @param Request $request
     */
    protected function failureDescription($request): string
    {
        return 'the Request ' . $this->toString();
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\HttpFoundation\Test\Constraint;

use _ContaoManager\PHPUnit\Framework\Constraint\Constraint;
use _ContaoManager\Symfony\Component\HttpFoundation\Request;
use _ContaoManager\Symfony\Component\HttpFoundation\Response;
/**
 * Asserts that the response is in the given format.
 *
 * @author Kévin Dunglas <dunglas@gmail.com>
 */
final class ResponseFormatSame extends Constraint
{
    private Request $request;
    private ?string $format;
    public function __construct(Request $request, ?string $format)
    {
        $this->request = $request;
        $this->format = $format;
    }
    public function toString(): string
    {
        return 'format is ' . ($this->format ?? 'null');
    }
    /**
     * @param Response $response
     */
    protected function matches($response): bool
    {
        return $this->format === $this->request->getFormat($response->headers->get('Content-Type'));
    }
    /**
     * @param Response $response
     */
    protected function failureDescription($response): string
    {
        return 'the Response ' . $this->toString();
    }
    /**
     * @param Response $response
     */
    protected function additionalFailureDescription($response): string
    {
        return (string) $response;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\HttpFoundation\Test\Constraint;

use _ContaoManager\PHPUnit\Framework\Constraint\Constraint;
use _ContaoManager\Symfony\Component\HttpFoundation\Response;
final class ResponseHeaderSame extends Constraint
{
    private string $headerName;
    private string $expectedValue;
    public function __construct(string $headerName, string $expectedValue)
    {
        $this->headerName = $headerName;
        $this->expectedValue = $expectedValue;
    }
    public function toString(): string
    {
        return \sprintf('has header "%s" with value "%s"', $this->headerName, $this->expectedValue);
    }
    /**
     * @param Response $response
     */
    protected function matches($response): bool
    {
        return $this->expectedValue === $response->headers->get($this->headerName, null);
    }
    /**
     * @param Response $response
     */
    protected function failureDescription($response): string
    {
        return 'the Response ' . $this->toString();
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\HttpFoundation;

/**
 * ServerBag is a container for HTTP headers from the $_SERVER variable.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 * @author Bulat Shakirzyanov <mallluhuct@gmail.com>
 * @author Robert Kiss <kepten@gmail.com>
 */
class ServerBag extends ParameterBag
{
    /**
     * Gets the HTTP headers.
     */
    public function getHeaders(): array
    {
        $headers = [];
        foreach ($this->parameters as $key => $value) {
            if (str_starts_with($key, 'HTTP_')) {
                $headers[substr($key, 5)] = $value;
            } elseif (\in_array($key, ['CONTENT_TYPE', 'CONTENT_LENGTH', 'CONTENT_MD5'], \true) && '' !== $value) {
                $headers[$key] = $value;
            }
        }
        if (isset($this->parameters['PHP_AUTH_USER'])) {
            $headers['PHP_AUTH_USER'] = $this->parameters['PHP_AUTH_USER'];
            $headers['PHP_AUTH_PW'] = $this->parameters['PHP_AUTH_PW'] ?? '';
        } else {
            /*
             * php-cgi under Apache does not pass HTTP Basic user/pass to PHP by default
             * For this workaround to work, add these lines to your .htaccess file:
             * RewriteCond %{HTTP:Authorization} .+
             * RewriteRule ^ - [E=HTTP_AUTHORIZATION:%0]
             *
             * A sample .htaccess file:
             * RewriteEngine On
             * RewriteCond %{HTTP:Authorization} .+
             * RewriteRule ^ - [E=HTTP_AUTHORIZATION:%0]
             * RewriteCond %{REQUEST_FILENAME} !-f
             * RewriteRule ^(.*)$ index.php [QSA,L]
             */
            $authorizationHeader = null;
            if (isset($this->parameters['HTTP_AUTHORIZATION'])) {
                $authorizationHeader = $this->parameters['HTTP_AUTHORIZATION'];
            } elseif (isset($this->parameters['REDIRECT_HTTP_AUTHORIZATION'])) {
                $authorizationHeader = $this->parameters['REDIRECT_HTTP_AUTHORIZATION'];
            }
            if (null !== $authorizationHeader) {
                if (0 === stripos($authorizationHeader, 'basic ')) {
                    // Decode AUTHORIZATION header into PHP_AUTH_USER and PHP_AUTH_PW when authorization header is basic
                    $exploded = explode(':', base64_decode(substr($authorizationHeader, 6)), 2);
                    if (2 == \count($exploded)) {
                        [$headers['PHP_AUTH_USER'], $headers['PHP_AUTH_PW']] = $exploded;
                    }
                } elseif (empty($this->parameters['PHP_AUTH_DIGEST']) && 0 === stripos($authorizationHeader, 'digest ')) {
                    // In some circumstances PHP_AUTH_DIGEST needs to be set
                    $headers['PHP_AUTH_DIGEST'] = $authorizationHeader;
                    $this->parameters['PHP_AUTH_DIGEST'] = $authorizationHeader;
                } elseif (0 === stripos($authorizationHeader, 'bearer ')) {
                    /*
                     * XXX: Since there is no PHP_AUTH_BEARER in PHP predefined variables,
                     *      I'll just set $headers['AUTHORIZATION'] here.
                     *      https://php.net/reserved.variables.server
                     */
                    $headers['AUTHORIZATION'] = $authorizationHeader;
                }
            }
        }
        if (isset($headers['AUTHORIZATION'])) {
            return $headers;
        }
        // PHP_AUTH_USER/PHP_AUTH_PW
        if (isset($headers['PHP_AUTH_USER'])) {
            $headers['AUTHORIZATION'] = 'Basic ' . base64_encode($headers['PHP_AUTH_USER'] . ':' . ($headers['PHP_AUTH_PW'] ?? ''));
        } elseif (isset($headers['PHP_AUTH_DIGEST'])) {
            $headers['AUTHORIZATION'] = $headers['PHP_AUTH_DIGEST'];
        }
        return $headers;
    }
}
CHANGELOG
=========

6.4
---

 * Make `HeaderBag::getDate()`, `Response::getDate()`, `getExpires()` and `getLastModified()` return a `DateTimeImmutable`
 * Support root-level `Generator` in `StreamedJsonResponse`
 * Add `UriSigner` from the HttpKernel component
 * Add `partitioned` flag to `Cookie` (CHIPS Cookie)
 * Add argument `bool $flush = true` to `Response::send()`
* Make `MongoDbSessionHandler` instantiable with the mongodb extension directly

6.3
---

 * Calling `ParameterBag::getDigit()`, `getAlnum()`, `getAlpha()` on an `array` throws a `UnexpectedValueException` instead of a `TypeError`
 * Add `ParameterBag::getString()` to convert a parameter into string and throw an exception if the value is invalid
 * Add `ParameterBag::getEnum()`
 * Create migration for session table when pdo handler is used
 * Add support for Relay PHP extension for Redis
 * The `Response::sendHeaders()` method now takes an optional HTTP status code as parameter, allowing to send informational responses such as Early Hints responses (103 status code)
 * Add `IpUtils::isPrivateIp()`
 * Add `Request::getPayload(): InputBag`
 * Deprecate conversion of invalid values in `ParameterBag::getInt()` and `ParameterBag::getBoolean()`,
 * Deprecate ignoring invalid values when using `ParameterBag::filter()`, unless flag `FILTER_NULL_ON_FAILURE` is set

6.2
---

 * Add `StreamedJsonResponse` class for efficient JSON streaming
 * The HTTP cache store uses the `xxh128` algorithm
 * Deprecate calling `JsonResponse::setCallback()`, `Response::setExpires/setLastModified/setEtag()`, `MockArraySessionStorage/NativeSessionStorage::setMetadataBag()`, `NativeSessionStorage::setSaveHandler()` without arguments
 * Add request matchers under the `Symfony\Component\HttpFoundation\RequestMatcher` namespace
 * Deprecate `RequestMatcher` in favor of `ChainRequestMatcher`
 * Deprecate `Symfony\Component\HttpFoundation\ExpressionRequestMatcher` in favor of `Symfony\Component\HttpFoundation\RequestMatcher\ExpressionRequestMatcher`

6.1
---

 * Add stale while revalidate and stale if error cache header
 * Allow dynamic session "ttl" when using a remote storage
 * Deprecate `Request::getContentType()`, use `Request::getContentTypeFormat()` instead

6.0
---

 * Remove the `NamespacedAttributeBag` class
 * Removed `Response::create()`, `JsonResponse::create()`,
   `RedirectResponse::create()`, `StreamedResponse::create()` and
   `BinaryFileResponse::create()` methods (use `__construct()` instead)
 * Not passing a `Closure` together with `FILTER_CALLBACK` to `ParameterBag::filter()` throws an `\InvalidArgumentException`; wrap your filter in a closure instead
 * Not passing a `Closure` together with `FILTER_CALLBACK` to `InputBag::filter()` throws an `\InvalidArgumentException`; wrap your filter in a closure instead
 * Removed the `Request::HEADER_X_FORWARDED_ALL` constant, use either `Request::HEADER_X_FORWARDED_FOR | Request::HEADER_X_FORWARDED_HOST | Request::HEADER_X_FORWARDED_PORT | Request::HEADER_X_FORWARDED_PROTO` or `Request::HEADER_X_FORWARDED_AWS_ELB` or `Request::HEADER_X_FORWARDED_TRAEFIK`constants instead
 * Rename `RequestStack::getMasterRequest()` to `getMainRequest()`
 * Not passing `FILTER_REQUIRE_ARRAY` or `FILTER_FORCE_ARRAY` flags to `InputBag::filter()` when filtering an array will throw `BadRequestException`
 * Removed the `Request::HEADER_X_FORWARDED_ALL` constant
 * Retrieving non-scalar values using `InputBag::get()` will throw `BadRequestException` (use `InputBad::all()` instead to retrieve an array)
 * Passing non-scalar default value as the second argument `InputBag::get()` will throw `\InvalidArgumentException`
 * Passing non-scalar, non-array value as the second argument `InputBag::set()` will throw `\InvalidArgumentException`
 * Passing `null` as `$requestIp` to `IpUtils::__checkIp()`, `IpUtils::__checkIp4()` or `IpUtils::__checkIp6()` is not supported anymore.

5.4
---

 * Deprecate passing `null` as `$requestIp` to `IpUtils::__checkIp()`, `IpUtils::__checkIp4()` or `IpUtils::__checkIp6()`, pass an empty string instead.
 * Add the `litespeed_finish_request` method to work with Litespeed
 * Deprecate `upload_progress.*` and `url_rewriter.tags` session options
 * Allow setting session options via DSN

5.3
---

 * Add the `SessionFactory`, `NativeSessionStorageFactory`, `PhpBridgeSessionStorageFactory` and `MockFileSessionStorageFactory` classes
 * Calling `Request::getSession()` when there is no available session throws a `SessionNotFoundException`
 * Add the `RequestStack::getSession` method
 * Deprecate the `NamespacedAttributeBag` class
 * Add `ResponseFormatSame` PHPUnit constraint
 * Deprecate the `RequestStack::getMasterRequest()` method and add `getMainRequest()` as replacement

5.2.0
-----

 * added support for `X-Forwarded-Prefix` header
 * added `HeaderUtils::parseQuery()`: it does the same as `parse_str()` but preserves dots in variable names
 * added `File::getContent()`
 * added ability to use comma separated ip addresses for `RequestMatcher::matchIps()`
 * added `Request::toArray()` to parse a JSON request body to an array
 * added `RateLimiter\RequestRateLimiterInterface` and `RateLimiter\AbstractRequestRateLimiter`
 * deprecated not passing a `Closure` together with `FILTER_CALLBACK` to `ParameterBag::filter()`; wrap your filter in a closure instead.
 * Deprecated the `Request::HEADER_X_FORWARDED_ALL` constant, use either `HEADER_X_FORWARDED_FOR | HEADER_X_FORWARDED_HOST | HEADER_X_FORWARDED_PORT | HEADER_X_FORWARDED_PROTO` or `HEADER_X_FORWARDED_AWS_ELB` or `HEADER_X_FORWARDED_TRAEFIK` constants instead.
 * Deprecated `BinaryFileResponse::create()`, use `__construct()` instead

5.1.0
-----

 * added `Cookie::withValue`, `Cookie::withDomain`, `Cookie::withExpires`,
   `Cookie::withPath`, `Cookie::withSecure`, `Cookie::withHttpOnly`,
   `Cookie::withRaw`, `Cookie::withSameSite`
 * Deprecate `Response::create()`, `JsonResponse::create()`,
   `RedirectResponse::create()`, and `StreamedResponse::create()` methods (use
   `__construct()` instead)
 * added `Request::preferSafeContent()` and `Response::setContentSafe()` to handle "safe" HTTP preference
   according to [RFC 8674](https://tools.ietf.org/html/rfc8674)
 * made the Mime component an optional dependency
 * added `MarshallingSessionHandler`, `IdentityMarshaller`
 * made `Session` accept a callback to report when the session is being used
 * Add support for all core cache control directives
 * Added `Symfony\Component\HttpFoundation\InputBag`
 * Deprecated retrieving non-string values using `InputBag::get()`, use `InputBag::all()` if you need access to the collection of values

5.0.0
-----

 * made `Cookie` auto-secure and lax by default
 * removed classes in the `MimeType` namespace, use the Symfony Mime component instead
 * removed method `UploadedFile::getClientSize()` and the related constructor argument
 * made `Request::getSession()` throw if the session has not been set before
 * removed `Response::HTTP_RESERVED_FOR_WEBDAV_ADVANCED_COLLECTIONS_EXPIRED_PROPOSAL`
 * passing a null url when instantiating a `RedirectResponse` is not allowed

4.4.0
-----

 * passing arguments to `Request::isMethodSafe()` is deprecated.
 * `ApacheRequest` is deprecated, use the `Request` class instead.
 * passing a third argument to `HeaderBag::get()` is deprecated, use method `all()` instead
 * [BC BREAK] `PdoSessionHandler` with MySQL changed the type of the lifetime column,
   make sure to run `ALTER TABLE sessions MODIFY sess_lifetime INTEGER UNSIGNED NOT NULL` to
   update your database.
 * `PdoSessionHandler` now precalculates the expiry timestamp in the lifetime column,
    make sure to run `CREATE INDEX expiry ON sessions (sess_lifetime)` to update your database
    to speed up garbage collection of expired sessions.
 * added `SessionHandlerFactory` to create session handlers with a DSN
 * added `IpUtils::anonymize()` to help with GDPR compliance.

4.3.0
-----

 * added PHPUnit constraints: `RequestAttributeValueSame`, `ResponseCookieValueSame`, `ResponseHasCookie`,
   `ResponseHasHeader`, `ResponseHeaderSame`, `ResponseIsRedirected`, `ResponseIsSuccessful`, and `ResponseStatusCodeSame`
 * deprecated `MimeTypeGuesserInterface` and `ExtensionGuesserInterface` in favor of `Symfony\Component\Mime\MimeTypesInterface`.
 * deprecated `MimeType` and `MimeTypeExtensionGuesser` in favor of `Symfony\Component\Mime\MimeTypes`.
 * deprecated `FileBinaryMimeTypeGuesser` in favor of `Symfony\Component\Mime\FileBinaryMimeTypeGuesser`.
 * deprecated `FileinfoMimeTypeGuesser` in favor of `Symfony\Component\Mime\FileinfoMimeTypeGuesser`.
 * added `UrlHelper` that allows to get an absolute URL and a relative path for a given path

4.2.0
-----

 * the default value of the "$secure" and "$samesite" arguments of Cookie's constructor
   will respectively change from "false" to "null" and from "null" to "lax" in Symfony
   5.0, you should define their values explicitly or use "Cookie::create()" instead.
 * added `matchPort()` in RequestMatcher

4.1.3
-----

 * [BC BREAK] Support for the IIS-only `X_ORIGINAL_URL` and `X_REWRITE_URL`
   HTTP headers has been dropped for security reasons.

4.1.0
-----

 * Query string normalization uses `parse_str()` instead of custom parsing logic.
 * Passing the file size to the constructor of the `UploadedFile` class is deprecated.
 * The `getClientSize()` method of the `UploadedFile` class is deprecated. Use `getSize()` instead.
 * added `RedisSessionHandler` to use Redis as a session storage
 * The `get()` method of the `AcceptHeader` class now takes into account the
   `*` and `*/*` default values (if they are present in the Accept HTTP header)
   when looking for items.
 * deprecated `Request::getSession()` when no session has been set. Use `Request::hasSession()` instead.
 * added `CannotWriteFileException`, `ExtensionFileException`, `FormSizeFileException`,
   `IniSizeFileException`, `NoFileException`, `NoTmpDirFileException`, `PartialFileException` to
   handle failed `UploadedFile`.
 * added `MigratingSessionHandler` for migrating between two session handlers without losing sessions
 * added `HeaderUtils`.

4.0.0
-----

 * the `Request::setTrustedHeaderName()` and `Request::getTrustedHeaderName()`
   methods have been removed
 * the `Request::HEADER_CLIENT_IP` constant has been removed, use
   `Request::HEADER_X_FORWARDED_FOR` instead
 * the `Request::HEADER_CLIENT_HOST` constant has been removed, use
   `Request::HEADER_X_FORWARDED_HOST` instead
 * the `Request::HEADER_CLIENT_PROTO` constant has been removed, use
   `Request::HEADER_X_FORWARDED_PROTO` instead
 * the `Request::HEADER_CLIENT_PORT` constant has been removed, use
   `Request::HEADER_X_FORWARDED_PORT` instead
 * checking for cacheable HTTP methods using the `Request::isMethodSafe()`
   method (by not passing `false` as its argument) is not supported anymore and
   throws a `\BadMethodCallException`
 * the `WriteCheckSessionHandler`, `NativeSessionHandler` and `NativeProxy` classes have been removed
 * setting session save handlers that do not implement `\SessionHandlerInterface` in
   `NativeSessionStorage::setSaveHandler()` is not supported anymore and throws a
   `\TypeError`

3.4.0
-----

 * implemented PHP 7.0's `SessionUpdateTimestampHandlerInterface` with a new
   `AbstractSessionHandler` base class and a new `StrictSessionHandler` wrapper
 * deprecated the `WriteCheckSessionHandler`, `NativeSessionHandler` and `NativeProxy` classes
 * deprecated setting session save handlers that do not implement `\SessionHandlerInterface` in `NativeSessionStorage::setSaveHandler()`
 * deprecated using `MongoDbSessionHandler` with the legacy mongo extension; use it with the mongodb/mongodb package and ext-mongodb instead
 * deprecated `MemcacheSessionHandler`; use `MemcachedSessionHandler` instead

3.3.0
-----

 * the `Request::setTrustedProxies()` method takes a new `$trustedHeaderSet` argument,
   see https://symfony.com/doc/current/deployment/proxies.html for more info,
 * deprecated the `Request::setTrustedHeaderName()` and `Request::getTrustedHeaderName()` methods,
 * added `File\Stream`, to be passed to `BinaryFileResponse` when the size of the served file is unknown,
   disabling `Range` and `Content-Length` handling, switching to chunked encoding instead
 * added the `Cookie::fromString()` method that allows to create a cookie from a
   raw header string

3.1.0
-----

 * Added support for creating `JsonResponse` with a string of JSON data

3.0.0
-----

 * The precedence of parameters returned from `Request::get()` changed from "GET, PATH, BODY" to "PATH, GET, BODY"

2.8.0
-----

 * Finding deep items in `ParameterBag::get()` is deprecated since version 2.8 and
   will be removed in 3.0.

2.6.0
-----

 * PdoSessionHandler changes
   - implemented different session locking strategies to prevent loss of data by concurrent access to the same session
   - [BC BREAK] save session data in a binary column without base64_encode
   - [BC BREAK] added lifetime column to the session table which allows to have different lifetimes for each session
   - implemented lazy connections that are only opened when a session is used by either passing a dsn string
     explicitly or falling back to session.save_path ini setting
   - added a createTable method that initializes a correctly defined table depending on the database vendor

2.5.0
-----

 * added `JsonResponse::setEncodingOptions()` & `JsonResponse::getEncodingOptions()` for easier manipulation
   of the options used while encoding data to JSON format.

2.4.0
-----

 * added RequestStack
 * added Request::getEncodings()
 * added accessors methods to session handlers

2.3.0
-----

 * added support for ranges of IPs in trusted proxies
 * `UploadedFile::isValid` now returns false if the file was not uploaded via HTTP (in a non-test mode)
 * Improved error-handling of `\Symfony\Component\HttpFoundation\Session\Storage\Handler\PdoSessionHandler`
   to ensure the supplied PDO handler throws Exceptions on error (as the class expects). Added related test cases
   to verify that Exceptions are properly thrown when the PDO queries fail.

2.2.0
-----

 * fixed the Request::create() precedence (URI information always take precedence now)
 * added Request::getTrustedProxies()
 * deprecated Request::isProxyTrusted()
 * [BC BREAK] JsonResponse does not turn a top level empty array to an object anymore, use an ArrayObject to enforce objects
 * added a IpUtils class to check if an IP belongs to a CIDR
 * added Request::getRealMethod() to get the "real" HTTP method (getMethod() returns the "intended" HTTP method)
 * disabled _method request parameter support by default (call Request::enableHttpMethodParameterOverride() to
   enable it, and Request::getHttpMethodParameterOverride() to check if it is supported)
 * Request::splitHttpAcceptHeader() method is deprecated and will be removed in 2.3
 * Deprecated Flashbag::count() and \Countable interface, will be removed in 2.3

2.1.0
-----

 * added Request::getSchemeAndHttpHost() and Request::getUserInfo()
 * added a fluent interface to the Response class
 * added Request::isProxyTrusted()
 * added JsonResponse
 * added a getTargetUrl method to RedirectResponse
 * added support for streamed responses
 * made Response::prepare() method the place to enforce HTTP specification
 * [BC BREAK] moved management of the locale from the Session class to the Request class
 * added a generic access to the PHP built-in filter mechanism: ParameterBag::filter()
 * made FileBinaryMimeTypeGuesser command configurable
 * added Request::getUser() and Request::getPassword()
 * added support for the PATCH method in Request
 * removed the ContentTypeMimeTypeGuesser class as it is deprecated and never used on PHP 5.3
 * added ResponseHeaderBag::makeDisposition() (implements RFC 6266)
 * made mimetype to extension conversion configurable
 * [BC BREAK] Moved all session related classes and interfaces into own namespace, as
   `Symfony\Component\HttpFoundation\Session` and renamed classes accordingly.
   Session handlers are located in the subnamespace `Symfony\Component\HttpFoundation\Session\Handler`.
 * SessionHandlers must implement `\SessionHandlerInterface` or extend from the
   `Symfony\Component\HttpFoundation\Storage\Handler\NativeSessionHandler` base class.
 * Added internal storage driver proxy mechanism for forward compatibility with
   PHP 5.4 `\SessionHandler` class.
 * Added session handlers for custom Memcache, Memcached and Null session save handlers.
 * [BC BREAK] Removed `NativeSessionStorage` and replaced with `NativeFileSessionHandler`.
 * [BC BREAK] `SessionStorageInterface` methods removed: `write()`, `read()` and
   `remove()`.  Added `getBag()`, `registerBag()`.  The `NativeSessionStorage` class
   is a mediator for the session storage internals including the session handlers
   which do the real work of participating in the internal PHP session workflow.
 * [BC BREAK] Introduced mock implementations of `SessionStorage` to enable unit
   and functional testing without starting real PHP sessions.  Removed
   `ArraySessionStorage`, and replaced with `MockArraySessionStorage` for unit
   tests; removed `FilesystemSessionStorage`, and replaced with`MockFileSessionStorage`
   for functional tests.  These do not interact with global session ini
   configuration values, session functions or `$_SESSION` superglobal. This means
   they can be configured directly allowing multiple instances to work without
   conflicting in the same PHP process.
 * [BC BREAK] Removed the `close()` method from the `Session` class, as this is
   now redundant.
 * Deprecated the following methods from the Session class: `setFlash()`, `setFlashes()`
   `getFlash()`, `hasFlash()`, and `removeFlash()`. Use `getFlashBag()` instead
   which returns a `FlashBagInterface`.
 * `Session->clear()` now only clears session attributes as before it cleared
   flash messages and attributes. `Session->getFlashBag()->all()` clears flashes now.
 * Session data is now managed by `SessionBagInterface` to better encapsulate
   session data.
 * Refactored session attribute and flash messages system to their own
  `SessionBagInterface` implementations.
 * Added `FlashBag`. Flashes expire when retrieved by `get()` or `all()`. This
   implementation is ESI compatible.
 * Added `AutoExpireFlashBag` (default) to replicate Symfony 2.0.x auto expire
   behavior of messages auto expiring after one page page load.  Messages must
   be retrieved by `get()` or `all()`.
 * Added `Symfony\Component\HttpFoundation\Attribute\AttributeBag` to replicate
   attributes storage behavior from 2.0.x (default).
 * Added `Symfony\Component\HttpFoundation\Attribute\NamespacedAttributeBag` for
   namespace session attributes.
 * Flash API can stores messages in an array so there may be multiple messages
   per flash type.  The old `Session` class API remains without BC break as it
   will allow single messages as before.
 * Added basic session meta-data to the session to record session create time,
   last updated time, and the lifetime of the session cookie that was provided
   to the client.
 * Request::getClientIp() method doesn't take a parameter anymore but bases
   itself on the trustProxy parameter.
 * Added isMethod() to Request object.
 * [BC BREAK] The methods `getPathInfo()`, `getBaseUrl()` and `getBasePath()` of
   a `Request` now all return a raw value (vs a urldecoded value before). Any call
   to one of these methods must be checked and wrapped in a `rawurldecode()` if
   needed.
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\HttpFoundation\File;

use _ContaoManager\Symfony\Component\HttpFoundation\File\Exception\FileException;
use _ContaoManager\Symfony\Component\HttpFoundation\File\Exception\FileNotFoundException;
use _ContaoManager\Symfony\Component\Mime\MimeTypes;
/**
 * A file in the file system.
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
class File extends \SplFileInfo
{
    /**
     * Constructs a new file from the given path.
     *
     * @param string $path      The path to the file
     * @param bool   $checkPath Whether to check the path or not
     *
     * @throws FileNotFoundException If the given path is not a file
     */
    public function __construct(string $path, bool $checkPath = \true)
    {
        if ($checkPath && !is_file($path)) {
            throw new FileNotFoundException($path);
        }
        parent::__construct($path);
    }
    /**
     * Returns the extension based on the mime type.
     *
     * If the mime type is unknown, returns null.
     *
     * This method uses the mime type as guessed by getMimeType()
     * to guess the file extension.
     *
     * @see MimeTypes
     * @see getMimeType()
     */
    public function guessExtension(): ?string
    {
        if (!class_exists(MimeTypes::class)) {
            throw new \LogicException('You cannot guess the extension as the Mime component is not installed. Try running "composer require symfony/mime".');
        }
        return MimeTypes::getDefault()->getExtensions($this->getMimeType())[0] ?? null;
    }
    /**
     * Returns the mime type of the file.
     *
     * The mime type is guessed using a MimeTypeGuesserInterface instance,
     * which uses finfo_file() then the "file" system binary,
     * depending on which of those are available.
     *
     * @see MimeTypes
     */
    public function getMimeType(): ?string
    {
        if (!class_exists(MimeTypes::class)) {
            throw new \LogicException('You cannot guess the mime type as the Mime component is not installed. Try running "composer require symfony/mime".');
        }
        return MimeTypes::getDefault()->guessMimeType($this->getPathname());
    }
    /**
     * Moves the file to a new location.
     *
     * @throws FileException if the target file could not be created
     */
    public function move(string $directory, ?string $name = null): self
    {
        $target = $this->getTargetFile($directory, $name);
        set_error_handler(function ($type, $msg) use (&$error) {
            $error = $msg;
        });
        try {
            $renamed = rename($this->getPathname(), $target);
        } finally {
            restore_error_handler();
        }
        if (!$renamed) {
            throw new FileException(\sprintf('Could not move the file "%s" to "%s" (%s).', $this->getPathname(), $target, strip_tags($error)));
        }
        @chmod($target, 0666 & ~umask());
        return $target;
    }
    public function getContent(): string
    {
        $content = file_get_contents($this->getPathname());
        if (\false === $content) {
            throw new FileException(\sprintf('Could not get the content of the file "%s".', $this->getPathname()));
        }
        return $content;
    }
    protected function getTargetFile(string $directory, ?string $name = null): self
    {
        if (!is_dir($directory)) {
            if (\false === @mkdir($directory, 0777, \true) && !is_dir($directory)) {
                throw new FileException(\sprintf('Unable to create the "%s" directory.', $directory));
            }
        } elseif (!is_writable($directory)) {
            throw new FileException(\sprintf('Unable to write in the "%s" directory.', $directory));
        }
        $target = rtrim($directory, '/\\') . \DIRECTORY_SEPARATOR . (null === $name ? $this->getBasename() : $this->getName($name));
        return new self($target, \false);
    }
    /**
     * Returns locale independent base name of the given path.
     */
    protected function getName(string $name): string
    {
        $originalName = str_replace('\\', '/', $name);
        $pos = strrpos($originalName, '/');
        $originalName = \false === $pos ? $originalName : substr($originalName, $pos + 1);
        return $originalName;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\HttpFoundation\File;

/**
 * A PHP stream of unknown size.
 *
 * @author Nicolas Grekas <p@tchwork.com>
 */
class Stream extends File
{
    public function getSize(): int|false
    {
        return \false;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\HttpFoundation\File;

use _ContaoManager\Symfony\Component\HttpFoundation\File\Exception\CannotWriteFileException;
use _ContaoManager\Symfony\Component\HttpFoundation\File\Exception\ExtensionFileException;
use _ContaoManager\Symfony\Component\HttpFoundation\File\Exception\FileException;
use _ContaoManager\Symfony\Component\HttpFoundation\File\Exception\FileNotFoundException;
use _ContaoManager\Symfony\Component\HttpFoundation\File\Exception\FormSizeFileException;
use _ContaoManager\Symfony\Component\HttpFoundation\File\Exception\IniSizeFileException;
use _ContaoManager\Symfony\Component\HttpFoundation\File\Exception\NoFileException;
use _ContaoManager\Symfony\Component\HttpFoundation\File\Exception\NoTmpDirFileException;
use _ContaoManager\Symfony\Component\HttpFoundation\File\Exception\PartialFileException;
use _ContaoManager\Symfony\Component\Mime\MimeTypes;
/**
 * A file uploaded through a form.
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 * @author Florian Eckerstorfer <florian@eckerstorfer.org>
 * @author Fabien Potencier <fabien@symfony.com>
 */
class UploadedFile extends File
{
    private bool $test;
    private string $originalName;
    private string $mimeType;
    private int $error;
    /**
     * Accepts the information of the uploaded file as provided by the PHP global $_FILES.
     *
     * The file object is only created when the uploaded file is valid (i.e. when the
     * isValid() method returns true). Otherwise the only methods that could be called
     * on an UploadedFile instance are:
     *
     *   * getClientOriginalName,
     *   * getClientMimeType,
     *   * isValid,
     *   * getError.
     *
     * Calling any other method on an non-valid instance will cause an unpredictable result.
     *
     * @param string      $path         The full temporary path to the file
     * @param string      $originalName The original file name of the uploaded file
     * @param string|null $mimeType     The type of the file as provided by PHP; null defaults to application/octet-stream
     * @param int|null    $error        The error constant of the upload (one of PHP's UPLOAD_ERR_XXX constants); null defaults to UPLOAD_ERR_OK
     * @param bool        $test         Whether the test mode is active
     *                                  Local files are used in test mode hence the code should not enforce HTTP uploads
     *
     * @throws FileException         If file_uploads is disabled
     * @throws FileNotFoundException If the file does not exist
     */
    public function __construct(string $path, string $originalName, ?string $mimeType = null, ?int $error = null, bool $test = \false)
    {
        $this->originalName = $this->getName($originalName);
        $this->mimeType = $mimeType ?: 'application/octet-stream';
        $this->error = $error ?: \UPLOAD_ERR_OK;
        $this->test = $test;
        parent::__construct($path, \UPLOAD_ERR_OK === $this->error);
    }
    /**
     * Returns the original file name.
     *
     * It is extracted from the request from which the file has been uploaded.
     * This should not be considered as a safe value to use for a file name on your servers.
     */
    public function getClientOriginalName(): string
    {
        return $this->originalName;
    }
    /**
     * Returns the original file extension.
     *
     * It is extracted from the original file name that was uploaded.
     * This should not be considered as a safe value to use for a file name on your servers.
     */
    public function getClientOriginalExtension(): string
    {
        return pathinfo($this->originalName, \PATHINFO_EXTENSION);
    }
    /**
     * Returns the file mime type.
     *
     * The client mime type is extracted from the request from which the file
     * was uploaded, so it should not be considered as a safe value.
     *
     * For a trusted mime type, use getMimeType() instead (which guesses the mime
     * type based on the file content).
     *
     * @see getMimeType()
     */
    public function getClientMimeType(): string
    {
        return $this->mimeType;
    }
    /**
     * Returns the extension based on the client mime type.
     *
     * If the mime type is unknown, returns null.
     *
     * This method uses the mime type as guessed by getClientMimeType()
     * to guess the file extension. As such, the extension returned
     * by this method cannot be trusted.
     *
     * For a trusted extension, use guessExtension() instead (which guesses
     * the extension based on the guessed mime type for the file).
     *
     * @see guessExtension()
     * @see getClientMimeType()
     */
    public function guessClientExtension(): ?string
    {
        if (!class_exists(MimeTypes::class)) {
            throw new \LogicException('You cannot guess the extension as the Mime component is not installed. Try running "composer require symfony/mime".');
        }
        return MimeTypes::getDefault()->getExtensions($this->getClientMimeType())[0] ?? null;
    }
    /**
     * Returns the upload error.
     *
     * If the upload was successful, the constant UPLOAD_ERR_OK is returned.
     * Otherwise one of the other UPLOAD_ERR_XXX constants is returned.
     */
    public function getError(): int
    {
        return $this->error;
    }
    /**
     * Returns whether the file has been uploaded with HTTP and no error occurred.
     */
    public function isValid(): bool
    {
        $isOk = \UPLOAD_ERR_OK === $this->error;
        return $this->test ? $isOk : $isOk && is_uploaded_file($this->getPathname());
    }
    /**
     * Moves the file to a new location.
     *
     * @throws FileException if, for any reason, the file could not have been moved
     */
    public function move(string $directory, ?string $name = null): File
    {
        if ($this->isValid()) {
            if ($this->test) {
                return parent::move($directory, $name);
            }
            $target = $this->getTargetFile($directory, $name);
            set_error_handler(function ($type, $msg) use (&$error) {
                $error = $msg;
            });
            try {
                $moved = move_uploaded_file($this->getPathname(), $target);
            } finally {
                restore_error_handler();
            }
            if (!$moved) {
                throw new FileException(\sprintf('Could not move the file "%s" to "%s" (%s).', $this->getPathname(), $target, strip_tags($error)));
            }
            @chmod($target, 0666 & ~umask());
            return $target;
        }
        switch ($this->error) {
            case \UPLOAD_ERR_INI_SIZE:
                throw new IniSizeFileException($this->getExceptionMessage());
            case \UPLOAD_ERR_FORM_SIZE:
                throw new FormSizeFileException($this->getExceptionMessage());
            case \UPLOAD_ERR_PARTIAL:
                throw new PartialFileException($this->getExceptionMessage());
            case \UPLOAD_ERR_NO_FILE:
                throw new NoFileException($this->getExceptionMessage());
            case \UPLOAD_ERR_CANT_WRITE:
                throw new CannotWriteFileException($this->getExceptionMessage());
            case \UPLOAD_ERR_NO_TMP_DIR:
                throw new NoTmpDirFileException($this->getExceptionMessage());
            case \UPLOAD_ERR_EXTENSION:
                throw new ExtensionFileException($this->getExceptionMessage());
        }
        throw new FileException($this->getExceptionMessage());
    }
    /**
     * Retrieves a user-friendly error message for file upload issues, if any.
     */
    public function getErrorMessage(): string
    {
        return \UPLOAD_ERR_OK !== $this->error ? $this->getExceptionMessage() : '';
    }
    /**
     * Returns the maximum size of an uploaded file as configured in php.ini.
     *
     * @return int|float The maximum size of an uploaded file in bytes (returns float if size > PHP_INT_MAX)
     */
    public static function getMaxFilesize(): int|float
    {
        $sizePostMax = self::parseFilesize(\ini_get('post_max_size'));
        $sizeUploadMax = self::parseFilesize(\ini_get('upload_max_filesize'));
        return min($sizePostMax ?: \PHP_INT_MAX, $sizeUploadMax ?: \PHP_INT_MAX);
    }
    private static function parseFilesize(string $size): int|float
    {
        if ('' === $size) {
            return 0;
        }
        $size = strtolower($size);
        $max = ltrim($size, '+');
        if (str_starts_with($max, '0x')) {
            $max = \intval($max, 16);
        } elseif (str_starts_with($max, '0')) {
            $max = \intval($max, 8);
        } else {
            $max = (int) $max;
        }
        switch (substr($size, -1)) {
            case 't':
                $max *= 1024;
            // no break
            case 'g':
                $max *= 1024;
            // no break
            case 'm':
                $max *= 1024;
            // no break
            case 'k':
                $max *= 1024;
        }
        return $max;
    }
    /**
     * Returns an informative upload error message.
     */
    private function getExceptionMessage(): string
    {
        static $errors = [\UPLOAD_ERR_INI_SIZE => 'The file "%s" exceeds your upload_max_filesize ini directive (limit is %d KiB).', \UPLOAD_ERR_FORM_SIZE => 'The file "%s" exceeds the upload limit defined in your form.', \UPLOAD_ERR_PARTIAL => 'The file "%s" was only partially uploaded.', \UPLOAD_ERR_NO_FILE => 'No file was uploaded.', \UPLOAD_ERR_CANT_WRITE => 'The file "%s" could not be written on disk.', \UPLOAD_ERR_NO_TMP_DIR => 'File could not be uploaded: missing temporary directory.', \UPLOAD_ERR_EXTENSION => 'File upload was stopped by a PHP extension.'];
        $errorCode = $this->error;
        $maxFilesize = \UPLOAD_ERR_INI_SIZE === $errorCode ? self::getMaxFilesize() / 1024 : 0;
        $message = $errors[$errorCode] ?? 'The file "%s" was not uploaded due to an unknown error.';
        return \sprintf($message, $this->getClientOriginalName(), $maxFilesize);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\HttpFoundation\File\Exception;

/**
 * Thrown when the access on a file was denied.
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
class AccessDeniedException extends FileException
{
    public function __construct(string $path)
    {
        parent::__construct(\sprintf('The file %s could not be accessed', $path));
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\HttpFoundation\File\Exception;

/**
 * Thrown when an UPLOAD_ERR_NO_FILE error occurred with UploadedFile.
 *
 * @author Florent Mata <florentmata@gmail.com>
 */
class NoFileException extends FileException
{
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\HttpFoundation\File\Exception;

/**
 * Thrown when an UPLOAD_ERR_INI_SIZE error occurred with UploadedFile.
 *
 * @author Florent Mata <florentmata@gmail.com>
 */
class IniSizeFileException extends FileException
{
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\HttpFoundation\File\Exception;

/**
 * Thrown when an UPLOAD_ERR_CANT_WRITE error occurred with UploadedFile.
 *
 * @author Florent Mata <florentmata@gmail.com>
 */
class CannotWriteFileException extends FileException
{
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\HttpFoundation\File\Exception;

/**
 * Thrown when an UPLOAD_ERR_EXTENSION error occurred with UploadedFile.
 *
 * @author Florent Mata <florentmata@gmail.com>
 */
class ExtensionFileException extends FileException
{
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\HttpFoundation\File\Exception;

/**
 * Thrown when an error occurred in the component File.
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
class FileException extends \RuntimeException
{
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\HttpFoundation\File\Exception;

/**
 * Thrown when an error occurred during file upload.
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
class UploadException extends FileException
{
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\HttpFoundation\File\Exception;

class UnexpectedTypeException extends FileException
{
    public function __construct(mixed $value, string $expectedType)
    {
        parent::__construct(\sprintf('Expected argument of type %s, %s given', $expectedType, get_debug_type($value)));
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\HttpFoundation\File\Exception;

/**
 * Thrown when an UPLOAD_ERR_FORM_SIZE error occurred with UploadedFile.
 *
 * @author Florent Mata <florentmata@gmail.com>
 */
class FormSizeFileException extends FileException
{
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\HttpFoundation\File\Exception;

/**
 * Thrown when a file was not found.
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
class FileNotFoundException extends FileException
{
    public function __construct(string $path)
    {
        parent::__construct(\sprintf('The file "%s" does not exist', $path));
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\HttpFoundation\File\Exception;

/**
 * Thrown when an UPLOAD_ERR_PARTIAL error occurred with UploadedFile.
 *
 * @author Florent Mata <florentmata@gmail.com>
 */
class PartialFileException extends FileException
{
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\HttpFoundation\File\Exception;

/**
 * Thrown when an UPLOAD_ERR_NO_TMP_DIR error occurred with UploadedFile.
 *
 * @author Florent Mata <florentmata@gmail.com>
 */
class NoTmpDirFileException extends FileException
{
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\HttpFoundation;

// Help opcache.preload discover always-needed symbols
class_exists(ResponseHeaderBag::class);
/**
 * Response represents an HTTP response.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class Response
{
    public const HTTP_CONTINUE = 100;
    public const HTTP_SWITCHING_PROTOCOLS = 101;
    public const HTTP_PROCESSING = 102;
    // RFC2518
    public const HTTP_EARLY_HINTS = 103;
    // RFC8297
    public const HTTP_OK = 200;
    public const HTTP_CREATED = 201;
    public const HTTP_ACCEPTED = 202;
    public const HTTP_NON_AUTHORITATIVE_INFORMATION = 203;
    public const HTTP_NO_CONTENT = 204;
    public const HTTP_RESET_CONTENT = 205;
    public const HTTP_PARTIAL_CONTENT = 206;
    public const HTTP_MULTI_STATUS = 207;
    // RFC4918
    public const HTTP_ALREADY_REPORTED = 208;
    // RFC5842
    public const HTTP_IM_USED = 226;
    // RFC3229
    public const HTTP_MULTIPLE_CHOICES = 300;
    public const HTTP_MOVED_PERMANENTLY = 301;
    public const HTTP_FOUND = 302;
    public const HTTP_SEE_OTHER = 303;
    public const HTTP_NOT_MODIFIED = 304;
    public const HTTP_USE_PROXY = 305;
    public const HTTP_RESERVED = 306;
    public const HTTP_TEMPORARY_REDIRECT = 307;
    public const HTTP_PERMANENTLY_REDIRECT = 308;
    // RFC7238
    public const HTTP_BAD_REQUEST = 400;
    public const HTTP_UNAUTHORIZED = 401;
    public const HTTP_PAYMENT_REQUIRED = 402;
    public const HTTP_FORBIDDEN = 403;
    public const HTTP_NOT_FOUND = 404;
    public const HTTP_METHOD_NOT_ALLOWED = 405;
    public const HTTP_NOT_ACCEPTABLE = 406;
    public const HTTP_PROXY_AUTHENTICATION_REQUIRED = 407;
    public const HTTP_REQUEST_TIMEOUT = 408;
    public const HTTP_CONFLICT = 409;
    public const HTTP_GONE = 410;
    public const HTTP_LENGTH_REQUIRED = 411;
    public const HTTP_PRECONDITION_FAILED = 412;
    public const HTTP_REQUEST_ENTITY_TOO_LARGE = 413;
    public const HTTP_REQUEST_URI_TOO_LONG = 414;
    public const HTTP_UNSUPPORTED_MEDIA_TYPE = 415;
    public const HTTP_REQUESTED_RANGE_NOT_SATISFIABLE = 416;
    public const HTTP_EXPECTATION_FAILED = 417;
    public const HTTP_I_AM_A_TEAPOT = 418;
    // RFC2324
    public const HTTP_MISDIRECTED_REQUEST = 421;
    // RFC7540
    public const HTTP_UNPROCESSABLE_ENTITY = 422;
    // RFC4918
    public const HTTP_LOCKED = 423;
    // RFC4918
    public const HTTP_FAILED_DEPENDENCY = 424;
    // RFC4918
    public const HTTP_TOO_EARLY = 425;
    // RFC-ietf-httpbis-replay-04
    public const HTTP_UPGRADE_REQUIRED = 426;
    // RFC2817
    public const HTTP_PRECONDITION_REQUIRED = 428;
    // RFC6585
    public const HTTP_TOO_MANY_REQUESTS = 429;
    // RFC6585
    public const HTTP_REQUEST_HEADER_FIELDS_TOO_LARGE = 431;
    // RFC6585
    public const HTTP_UNAVAILABLE_FOR_LEGAL_REASONS = 451;
    // RFC7725
    public const HTTP_INTERNAL_SERVER_ERROR = 500;
    public const HTTP_NOT_IMPLEMENTED = 501;
    public const HTTP_BAD_GATEWAY = 502;
    public const HTTP_SERVICE_UNAVAILABLE = 503;
    public const HTTP_GATEWAY_TIMEOUT = 504;
    public const HTTP_VERSION_NOT_SUPPORTED = 505;
    public const HTTP_VARIANT_ALSO_NEGOTIATES_EXPERIMENTAL = 506;
    // RFC2295
    public const HTTP_INSUFFICIENT_STORAGE = 507;
    // RFC4918
    public const HTTP_LOOP_DETECTED = 508;
    // RFC5842
    public const HTTP_NOT_EXTENDED = 510;
    // RFC2774
    public const HTTP_NETWORK_AUTHENTICATION_REQUIRED = 511;
    // RFC6585
    /**
     * @see https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cache-Control
     */
    private const HTTP_RESPONSE_CACHE_CONTROL_DIRECTIVES = [
        'must_revalidate' => \false,
        'no_cache' => \false,
        'no_store' => \false,
        'no_transform' => \false,
        'public' => \false,
        'private' => \false,
        'proxy_revalidate' => \false,
        'max_age' => \true,
        's_maxage' => \true,
        'stale_if_error' => \true,
        // RFC5861
        'stale_while_revalidate' => \true,
        // RFC5861
        'immutable' => \false,
        'last_modified' => \true,
        'etag' => \true,
    ];
    /**
     * @var ResponseHeaderBag
     */
    public $headers;
    /**
     * @var string
     */
    protected $content;
    /**
     * @var string
     */
    protected $version;
    /**
     * @var int
     */
    protected $statusCode;
    /**
     * @var string
     */
    protected $statusText;
    /**
     * @var string
     */
    protected $charset;
    /**
     * Status codes translation table.
     *
     * The list of codes is complete according to the
     * {@link https://www.iana.org/assignments/http-status-codes/http-status-codes.xhtml Hypertext Transfer Protocol (HTTP) Status Code Registry}
     * (last updated 2021-10-01).
     *
     * Unless otherwise noted, the status code is defined in RFC2616.
     *
     * @var array
     */
    public static $statusTexts = [
        100 => 'Continue',
        101 => 'Switching Protocols',
        102 => 'Processing',
        // RFC2518
        103 => 'Early Hints',
        200 => 'OK',
        201 => 'Created',
        202 => 'Accepted',
        203 => 'Non-Authoritative Information',
        204 => 'No Content',
        205 => 'Reset Content',
        206 => 'Partial Content',
        207 => 'Multi-Status',
        // RFC4918
        208 => 'Already Reported',
        // RFC5842
        226 => 'IM Used',
        // RFC3229
        300 => 'Multiple Choices',
        301 => 'Moved Permanently',
        302 => 'Found',
        303 => 'See Other',
        304 => 'Not Modified',
        305 => 'Use Proxy',
        307 => 'Temporary Redirect',
        308 => 'Permanent Redirect',
        // RFC7238
        400 => 'Bad Request',
        401 => 'Unauthorized',
        402 => 'Payment Required',
        403 => 'Forbidden',
        404 => 'Not Found',
        405 => 'Method Not Allowed',
        406 => 'Not Acceptable',
        407 => 'Proxy Authentication Required',
        408 => 'Request Timeout',
        409 => 'Conflict',
        410 => 'Gone',
        411 => 'Length Required',
        412 => 'Precondition Failed',
        413 => 'Content Too Large',
        // RFC-ietf-httpbis-semantics
        414 => 'URI Too Long',
        415 => 'Unsupported Media Type',
        416 => 'Range Not Satisfiable',
        417 => 'Expectation Failed',
        418 => 'I\'m a teapot',
        // RFC2324
        421 => 'Misdirected Request',
        // RFC7540
        422 => 'Unprocessable Content',
        // RFC-ietf-httpbis-semantics
        423 => 'Locked',
        // RFC4918
        424 => 'Failed Dependency',
        // RFC4918
        425 => 'Too Early',
        // RFC-ietf-httpbis-replay-04
        426 => 'Upgrade Required',
        // RFC2817
        428 => 'Precondition Required',
        // RFC6585
        429 => 'Too Many Requests',
        // RFC6585
        431 => 'Request Header Fields Too Large',
        // RFC6585
        451 => 'Unavailable For Legal Reasons',
        // RFC7725
        500 => 'Internal Server Error',
        501 => 'Not Implemented',
        502 => 'Bad Gateway',
        503 => 'Service Unavailable',
        504 => 'Gateway Timeout',
        505 => 'HTTP Version Not Supported',
        506 => 'Variant Also Negotiates',
        // RFC2295
        507 => 'Insufficient Storage',
        // RFC4918
        508 => 'Loop Detected',
        // RFC5842
        510 => 'Not Extended',
        // RFC2774
        511 => 'Network Authentication Required',
    ];
    /**
     * Tracks headers already sent in informational responses.
     */
    private array $sentHeaders;
    /**
     * @param int $status The HTTP status code (200 "OK" by default)
     *
     * @throws \InvalidArgumentException When the HTTP status code is not valid
     */
    public function __construct(?string $content = '', int $status = 200, array $headers = [])
    {
        $this->headers = new ResponseHeaderBag($headers);
        $this->setContent($content);
        $this->setStatusCode($status);
        $this->setProtocolVersion('1.0');
    }
    /**
     * Returns the Response as an HTTP string.
     *
     * The string representation of the Response is the same as the
     * one that will be sent to the client only if the prepare() method
     * has been called before.
     *
     * @see prepare()
     */
    public function __toString(): string
    {
        return \sprintf('HTTP/%s %s %s', $this->version, $this->statusCode, $this->statusText) . "\r\n" . $this->headers . "\r\n" . $this->getContent();
    }
    /**
     * Clones the current Response instance.
     */
    public function __clone()
    {
        $this->headers = clone $this->headers;
    }
    /**
     * Prepares the Response before it is sent to the client.
     *
     * This method tweaks the Response to ensure that it is
     * compliant with RFC 2616. Most of the changes are based on
     * the Request that is "associated" with this Response.
     *
     * @return $this
     */
    public function prepare(Request $request): static
    {
        $headers = $this->headers;
        if ($this->isInformational() || $this->isEmpty()) {
            $this->setContent(null);
            $headers->remove('Content-Type');
            $headers->remove('Content-Length');
            // prevent PHP from sending the Content-Type header based on default_mimetype
            ini_set('default_mimetype', '');
        } else {
            // Content-type based on the Request
            if (!$headers->has('Content-Type')) {
                $format = $request->getRequestFormat(null);
                if (null !== $format && $mimeType = $request->getMimeType($format)) {
                    $headers->set('Content-Type', $mimeType);
                }
            }
            // Fix Content-Type
            $charset = $this->charset ?: 'UTF-8';
            if (!$headers->has('Content-Type')) {
                $headers->set('Content-Type', 'text/html; charset=' . $charset);
            } elseif (0 === stripos($headers->get('Content-Type') ?? '', 'text/') && \false === stripos($headers->get('Content-Type') ?? '', 'charset')) {
                // add the charset
                $headers->set('Content-Type', $headers->get('Content-Type') . '; charset=' . $charset);
            }
            // Fix Content-Length
            if ($headers->has('Transfer-Encoding')) {
                $headers->remove('Content-Length');
            }
            if ($request->isMethod('HEAD')) {
                // cf. RFC2616 14.13
                $length = $headers->get('Content-Length');
                $this->setContent(null);
                if ($length) {
                    $headers->set('Content-Length', $length);
                }
            }
        }
        // Fix protocol
        if ('HTTP/1.0' != $request->server->get('SERVER_PROTOCOL')) {
            $this->setProtocolVersion('1.1');
        }
        // Check if we need to send extra expire info headers
        if ('1.0' == $this->getProtocolVersion() && str_contains($headers->get('Cache-Control', ''), 'no-cache')) {
            $headers->set('pragma', 'no-cache');
            $headers->set('expires', -1);
        }
        $this->ensureIEOverSSLCompatibility($request);
        if ($request->isSecure()) {
            foreach ($headers->getCookies() as $cookie) {
                $cookie->setSecureDefault(\true);
            }
        }
        return $this;
    }
    /**
     * Sends HTTP headers.
     *
     * @param positive-int|null $statusCode The status code to use, override the statusCode property if set and not null
     *
     * @return $this
     */
    public function sendHeaders(): static
    {
        // headers have already been sent by the developer
        if (headers_sent()) {
            return $this;
        }
        $statusCode = \func_num_args() > 0 ? func_get_arg(0) : null;
        $informationalResponse = $statusCode >= 100 && $statusCode < 200;
        if ($informationalResponse && (!\function_exists('headers_send') && !\function_exists('_ContaoManager\headers_send'))) {
            // skip informational responses if not supported by the SAPI
            return $this;
        }
        // headers
        foreach ($this->headers->allPreserveCaseWithoutCookies() as $name => $values) {
            $newValues = $values;
            $replace = \false;
            // As recommended by RFC 8297, PHP automatically copies headers from previous 103 responses, we need to deal with that if headers changed
            $previousValues = $this->sentHeaders[$name] ?? null;
            if ($previousValues === $values) {
                // Header already sent in a previous response, it will be automatically copied in this response by PHP
                continue;
            }
            $replace = 0 === strcasecmp($name, 'Content-Type');
            if (null !== $previousValues && array_diff($previousValues, $values)) {
                header_remove($name);
                $previousValues = null;
            }
            $newValues = null === $previousValues ? $values : array_diff($values, $previousValues);
            foreach ($newValues as $value) {
                header($name . ': ' . $value, $replace, $this->statusCode);
            }
            if ($informationalResponse) {
                $this->sentHeaders[$name] = $values;
            }
        }
        // cookies
        foreach ($this->headers->getCookies() as $cookie) {
            header('Set-Cookie: ' . $cookie, \false, $this->statusCode);
        }
        if ($informationalResponse) {
            headers_send($statusCode);
            return $this;
        }
        $statusCode ??= $this->statusCode;
        // status
        header(\sprintf('HTTP/%s %s %s', $this->version, $statusCode, $this->statusText), \true, $statusCode);
        return $this;
    }
    /**
     * Sends content for the current web response.
     *
     * @return $this
     */
    public function sendContent(): static
    {
        echo $this->content;
        return $this;
    }
    /**
     * Sends HTTP headers and content.
     *
     * @param bool $flush Whether output buffers should be flushed
     *
     * @return $this
     */
    public function send(): static
    {
        $this->sendHeaders();
        $this->sendContent();
        $flush = 1 <= \func_num_args() ? func_get_arg(0) : \true;
        if (!$flush) {
            return $this;
        }
        if (\function_exists('fastcgi_finish_request')) {
            fastcgi_finish_request();
        } elseif (\function_exists('_ContaoManager\litespeed_finish_request')) {
            litespeed_finish_request();
        } elseif (!\in_array(\PHP_SAPI, ['cli', 'phpdbg', 'embed'], \true)) {
            static::closeOutputBuffers(0, \true);
            flush();
        }
        return $this;
    }
    /**
     * Sets the response content.
     *
     * @return $this
     */
    public function setContent(?string $content): static
    {
        $this->content = $content ?? '';
        return $this;
    }
    /**
     * Gets the current response content.
     */
    public function getContent(): string|false
    {
        return $this->content;
    }
    /**
     * Sets the HTTP protocol version (1.0 or 1.1).
     *
     * @return $this
     *
     * @final
     */
    public function setProtocolVersion(string $version): static
    {
        $this->version = $version;
        return $this;
    }
    /**
     * Gets the HTTP protocol version.
     *
     * @final
     */
    public function getProtocolVersion(): string
    {
        return $this->version;
    }
    /**
     * Sets the response status code.
     *
     * If the status text is null it will be automatically populated for the known
     * status codes and left empty otherwise.
     *
     * @return $this
     *
     * @throws \InvalidArgumentException When the HTTP status code is not valid
     *
     * @final
     */
    public function setStatusCode(int $code, ?string $text = null): static
    {
        $this->statusCode = $code;
        if ($this->isInvalid()) {
            throw new \InvalidArgumentException(\sprintf('The HTTP status code "%s" is not valid.', $code));
        }
        if (null === $text) {
            $this->statusText = self::$statusTexts[$code] ?? 'unknown status';
            return $this;
        }
        $this->statusText = $text;
        return $this;
    }
    /**
     * Retrieves the status code for the current web response.
     *
     * @final
     */
    public function getStatusCode(): int
    {
        return $this->statusCode;
    }
    /**
     * Sets the response charset.
     *
     * @return $this
     *
     * @final
     */
    public function setCharset(string $charset): static
    {
        $this->charset = $charset;
        return $this;
    }
    /**
     * Retrieves the response charset.
     *
     * @final
     */
    public function getCharset(): ?string
    {
        return $this->charset;
    }
    /**
     * Returns true if the response may safely be kept in a shared (surrogate) cache.
     *
     * Responses marked "private" with an explicit Cache-Control directive are
     * considered uncacheable.
     *
     * Responses with neither a freshness lifetime (Expires, max-age) nor cache
     * validator (Last-Modified, ETag) are considered uncacheable because there is
     * no way to tell when or how to remove them from the cache.
     *
     * Note that RFC 7231 and RFC 7234 possibly allow for a more permissive implementation,
     * for example "status codes that are defined as cacheable by default [...]
     * can be reused by a cache with heuristic expiration unless otherwise indicated"
     * (https://tools.ietf.org/html/rfc7231#section-6.1)
     *
     * @final
     */
    public function isCacheable(): bool
    {
        if (!\in_array($this->statusCode, [200, 203, 300, 301, 302, 404, 410])) {
            return \false;
        }
        if ($this->headers->hasCacheControlDirective('no-store') || $this->headers->getCacheControlDirective('private')) {
            return \false;
        }
        return $this->isValidateable() || $this->isFresh();
    }
    /**
     * Returns true if the response is "fresh".
     *
     * Fresh responses may be served from cache without any interaction with the
     * origin. A response is considered fresh when it includes a Cache-Control/max-age
     * indicator or Expires header and the calculated age is less than the freshness lifetime.
     *
     * @final
     */
    public function isFresh(): bool
    {
        return $this->getTtl() > 0;
    }
    /**
     * Returns true if the response includes headers that can be used to validate
     * the response with the origin server using a conditional GET request.
     *
     * @final
     */
    public function isValidateable(): bool
    {
        return $this->headers->has('Last-Modified') || $this->headers->has('ETag');
    }
    /**
     * Marks the response as "private".
     *
     * It makes the response ineligible for serving other clients.
     *
     * @return $this
     *
     * @final
     */
    public function setPrivate(): static
    {
        $this->headers->removeCacheControlDirective('public');
        $this->headers->addCacheControlDirective('private');
        return $this;
    }
    /**
     * Marks the response as "public".
     *
     * It makes the response eligible for serving other clients.
     *
     * @return $this
     *
     * @final
     */
    public function setPublic(): static
    {
        $this->headers->addCacheControlDirective('public');
        $this->headers->removeCacheControlDirective('private');
        return $this;
    }
    /**
     * Marks the response as "immutable".
     *
     * @return $this
     *
     * @final
     */
    public function setImmutable(bool $immutable = \true): static
    {
        if ($immutable) {
            $this->headers->addCacheControlDirective('immutable');
        } else {
            $this->headers->removeCacheControlDirective('immutable');
        }
        return $this;
    }
    /**
     * Returns true if the response is marked as "immutable".
     *
     * @final
     */
    public function isImmutable(): bool
    {
        return $this->headers->hasCacheControlDirective('immutable');
    }
    /**
     * Returns true if the response must be revalidated by shared caches once it has become stale.
     *
     * This method indicates that the response must not be served stale by a
     * cache in any circumstance without first revalidating with the origin.
     * When present, the TTL of the response should not be overridden to be
     * greater than the value provided by the origin.
     *
     * @final
     */
    public function mustRevalidate(): bool
    {
        return $this->headers->hasCacheControlDirective('must-revalidate') || $this->headers->hasCacheControlDirective('proxy-revalidate');
    }
    /**
     * Returns the Date header as a DateTime instance.
     *
     * @throws \RuntimeException When the header is not parseable
     *
     * @final
     */
    public function getDate(): ?\DateTimeImmutable
    {
        return $this->headers->getDate('Date');
    }
    /**
     * Sets the Date header.
     *
     * @return $this
     *
     * @final
     */
    public function setDate(\DateTimeInterface $date): static
    {
        $date = \DateTimeImmutable::createFromInterface($date);
        $date = $date->setTimezone(new \DateTimeZone('UTC'));
        $this->headers->set('Date', $date->format('D, d M Y H:i:s') . ' GMT');
        return $this;
    }
    /**
     * Returns the age of the response in seconds.
     *
     * @final
     */
    public function getAge(): int
    {
        if (null !== $age = $this->headers->get('Age')) {
            return (int) $age;
        }
        return max(time() - (int) $this->getDate()->format('U'), 0);
    }
    /**
     * Marks the response stale by setting the Age header to be equal to the maximum age of the response.
     *
     * @return $this
     */
    public function expire(): static
    {
        if ($this->isFresh()) {
            $this->headers->set('Age', $this->getMaxAge());
            $this->headers->remove('Expires');
        }
        return $this;
    }
    /**
     * Returns the value of the Expires header as a DateTime instance.
     *
     * @final
     */
    public function getExpires(): ?\DateTimeImmutable
    {
        try {
            return $this->headers->getDate('Expires');
        } catch (\RuntimeException) {
            // according to RFC 2616 invalid date formats (e.g. "0" and "-1") must be treated as in the past
            return \DateTimeImmutable::createFromFormat('U', time() - 172800);
        }
    }
    /**
     * Sets the Expires HTTP header with a DateTime instance.
     *
     * Passing null as value will remove the header.
     *
     * @return $this
     *
     * @final
     */
    public function setExpires(?\DateTimeInterface $date = null): static
    {
        if (1 > \func_num_args()) {
            trigger_deprecation('symfony/http-foundation', '6.2', 'Calling "%s()" without any arguments is deprecated, pass null explicitly instead.', __METHOD__);
        }
        if (null === $date) {
            $this->headers->remove('Expires');
            return $this;
        }
        $date = \DateTimeImmutable::createFromInterface($date);
        $date = $date->setTimezone(new \DateTimeZone('UTC'));
        $this->headers->set('Expires', $date->format('D, d M Y H:i:s') . ' GMT');
        return $this;
    }
    /**
     * Returns the number of seconds after the time specified in the response's Date
     * header when the response should no longer be considered fresh.
     *
     * First, it checks for a s-maxage directive, then a max-age directive, and then it falls
     * back on an expires header. It returns null when no maximum age can be established.
     *
     * @final
     */
    public function getMaxAge(): ?int
    {
        if ($this->headers->hasCacheControlDirective('s-maxage')) {
            return (int) $this->headers->getCacheControlDirective('s-maxage');
        }
        if ($this->headers->hasCacheControlDirective('max-age')) {
            return (int) $this->headers->getCacheControlDirective('max-age');
        }
        if (null !== $expires = $this->getExpires()) {
            $maxAge = (int) $expires->format('U') - (int) $this->getDate()->format('U');
            return max($maxAge, 0);
        }
        return null;
    }
    /**
     * Sets the number of seconds after which the response should no longer be considered fresh.
     *
     * This methods sets the Cache-Control max-age directive.
     *
     * @return $this
     *
     * @final
     */
    public function setMaxAge(int $value): static
    {
        $this->headers->addCacheControlDirective('max-age', $value);
        return $this;
    }
    /**
     * Sets the number of seconds after which the response should no longer be returned by shared caches when backend is down.
     *
     * This method sets the Cache-Control stale-if-error directive.
     *
     * @return $this
     *
     * @final
     */
    public function setStaleIfError(int $value): static
    {
        $this->headers->addCacheControlDirective('stale-if-error', $value);
        return $this;
    }
    /**
     * Sets the number of seconds after which the response should no longer return stale content by shared caches.
     *
     * This method sets the Cache-Control stale-while-revalidate directive.
     *
     * @return $this
     *
     * @final
     */
    public function setStaleWhileRevalidate(int $value): static
    {
        $this->headers->addCacheControlDirective('stale-while-revalidate', $value);
        return $this;
    }
    /**
     * Sets the number of seconds after which the response should no longer be considered fresh by shared caches.
     *
     * This methods sets the Cache-Control s-maxage directive.
     *
     * @return $this
     *
     * @final
     */
    public function setSharedMaxAge(int $value): static
    {
        $this->setPublic();
        $this->headers->addCacheControlDirective('s-maxage', $value);
        return $this;
    }
    /**
     * Returns the response's time-to-live in seconds.
     *
     * It returns null when no freshness information is present in the response.
     *
     * When the response's TTL is 0, the response may not be served from cache without first
     * revalidating with the origin.
     *
     * @final
     */
    public function getTtl(): ?int
    {
        $maxAge = $this->getMaxAge();
        return null !== $maxAge ? max($maxAge - $this->getAge(), 0) : null;
    }
    /**
     * Sets the response's time-to-live for shared caches in seconds.
     *
     * This method adjusts the Cache-Control/s-maxage directive.
     *
     * @return $this
     *
     * @final
     */
    public function setTtl(int $seconds): static
    {
        $this->setSharedMaxAge($this->getAge() + $seconds);
        return $this;
    }
    /**
     * Sets the response's time-to-live for private/client caches in seconds.
     *
     * This method adjusts the Cache-Control/max-age directive.
     *
     * @return $this
     *
     * @final
     */
    public function setClientTtl(int $seconds): static
    {
        $this->setMaxAge($this->getAge() + $seconds);
        return $this;
    }
    /**
     * Returns the Last-Modified HTTP header as a DateTime instance.
     *
     * @throws \RuntimeException When the HTTP header is not parseable
     *
     * @final
     */
    public function getLastModified(): ?\DateTimeImmutable
    {
        return $this->headers->getDate('Last-Modified');
    }
    /**
     * Sets the Last-Modified HTTP header with a DateTime instance.
     *
     * Passing null as value will remove the header.
     *
     * @return $this
     *
     * @final
     */
    public function setLastModified(?\DateTimeInterface $date = null): static
    {
        if (1 > \func_num_args()) {
            trigger_deprecation('symfony/http-foundation', '6.2', 'Calling "%s()" without any arguments is deprecated, pass null explicitly instead.', __METHOD__);
        }
        if (null === $date) {
            $this->headers->remove('Last-Modified');
            return $this;
        }
        $date = \DateTimeImmutable::createFromInterface($date);
        $date = $date->setTimezone(new \DateTimeZone('UTC'));
        $this->headers->set('Last-Modified', $date->format('D, d M Y H:i:s') . ' GMT');
        return $this;
    }
    /**
     * Returns the literal value of the ETag HTTP header.
     *
     * @final
     */
    public function getEtag(): ?string
    {
        return $this->headers->get('ETag');
    }
    /**
     * Sets the ETag value.
     *
     * @param string|null $etag The ETag unique identifier or null to remove the header
     * @param bool        $weak Whether you want a weak ETag or not
     *
     * @return $this
     *
     * @final
     */
    public function setEtag(?string $etag = null, bool $weak = \false): static
    {
        if (1 > \func_num_args()) {
            trigger_deprecation('symfony/http-foundation', '6.2', 'Calling "%s()" without any arguments is deprecated, pass null explicitly instead.', __METHOD__);
        }
        if (null === $etag) {
            $this->headers->remove('Etag');
        } else {
            if (!str_starts_with($etag, '"')) {
                $etag = '"' . $etag . '"';
            }
            $this->headers->set('ETag', (\true === $weak ? 'W/' : '') . $etag);
        }
        return $this;
    }
    /**
     * Sets the response's cache headers (validation and/or expiration).
     *
     * Available options are: must_revalidate, no_cache, no_store, no_transform, public, private, proxy_revalidate, max_age, s_maxage, immutable, last_modified and etag.
     *
     * @return $this
     *
     * @throws \InvalidArgumentException
     *
     * @final
     */
    public function setCache(array $options): static
    {
        if ($diff = array_diff(array_keys($options), array_keys(self::HTTP_RESPONSE_CACHE_CONTROL_DIRECTIVES))) {
            throw new \InvalidArgumentException(\sprintf('Response does not support the following options: "%s".', implode('", "', $diff)));
        }
        if (isset($options['etag'])) {
            $this->setEtag($options['etag']);
        }
        if (isset($options['last_modified'])) {
            $this->setLastModified($options['last_modified']);
        }
        if (isset($options['max_age'])) {
            $this->setMaxAge($options['max_age']);
        }
        if (isset($options['s_maxage'])) {
            $this->setSharedMaxAge($options['s_maxage']);
        }
        if (isset($options['stale_while_revalidate'])) {
            $this->setStaleWhileRevalidate($options['stale_while_revalidate']);
        }
        if (isset($options['stale_if_error'])) {
            $this->setStaleIfError($options['stale_if_error']);
        }
        foreach (self::HTTP_RESPONSE_CACHE_CONTROL_DIRECTIVES as $directive => $hasValue) {
            if (!$hasValue && isset($options[$directive])) {
                if ($options[$directive]) {
                    $this->headers->addCacheControlDirective(str_replace('_', '-', $directive));
                } else {
                    $this->headers->removeCacheControlDirective(str_replace('_', '-', $directive));
                }
            }
        }
        if (isset($options['public'])) {
            if ($options['public']) {
                $this->setPublic();
            } else {
                $this->setPrivate();
            }
        }
        if (isset($options['private'])) {
            if ($options['private']) {
                $this->setPrivate();
            } else {
                $this->setPublic();
            }
        }
        return $this;
    }
    /**
     * Modifies the response so that it conforms to the rules defined for a 304 status code.
     *
     * This sets the status, removes the body, and discards any headers
     * that MUST NOT be included in 304 responses.
     *
     * @return $this
     *
     * @see https://tools.ietf.org/html/rfc2616#section-10.3.5
     *
     * @final
     */
    public function setNotModified(): static
    {
        $this->setStatusCode(304);
        $this->setContent(null);
        // remove headers that MUST NOT be included with 304 Not Modified responses
        foreach (['Allow', 'Content-Encoding', 'Content-Language', 'Content-Length', 'Content-MD5', 'Content-Type', 'Last-Modified'] as $header) {
            $this->headers->remove($header);
        }
        return $this;
    }
    /**
     * Returns true if the response includes a Vary header.
     *
     * @final
     */
    public function hasVary(): bool
    {
        return null !== $this->headers->get('Vary');
    }
    /**
     * Returns an array of header names given in the Vary header.
     *
     * @final
     */
    public function getVary(): array
    {
        if (!$vary = $this->headers->all('Vary')) {
            return [];
        }
        $ret = [];
        foreach ($vary as $item) {
            $ret[] = preg_split('/[\s,]+/', $item);
        }
        return array_merge([], ...$ret);
    }
    /**
     * Sets the Vary header.
     *
     * @param bool $replace Whether to replace the actual value or not (true by default)
     *
     * @return $this
     *
     * @final
     */
    public function setVary(string|array $headers, bool $replace = \true): static
    {
        $this->headers->set('Vary', $headers, $replace);
        return $this;
    }
    /**
     * Determines if the Response validators (ETag, Last-Modified) match
     * a conditional value specified in the Request.
     *
     * If the Response is not modified, it sets the status code to 304 and
     * removes the actual content by calling the setNotModified() method.
     *
     * @final
     */
    public function isNotModified(Request $request): bool
    {
        if (!$request->isMethodCacheable()) {
            return \false;
        }
        $notModified = \false;
        $lastModified = $this->headers->get('Last-Modified');
        $modifiedSince = $request->headers->get('If-Modified-Since');
        if (($ifNoneMatchEtags = $request->getETags()) && null !== $etag = $this->getEtag()) {
            if (0 == strncmp($etag, 'W/', 2)) {
                $etag = substr($etag, 2);
            }
            // Use weak comparison as per https://tools.ietf.org/html/rfc7232#section-3.2.
            foreach ($ifNoneMatchEtags as $ifNoneMatchEtag) {
                if (0 == strncmp($ifNoneMatchEtag, 'W/', 2)) {
                    $ifNoneMatchEtag = substr($ifNoneMatchEtag, 2);
                }
                if ($ifNoneMatchEtag === $etag || '*' === $ifNoneMatchEtag) {
                    $notModified = \true;
                    break;
                }
            }
        } elseif ($modifiedSince && $lastModified) {
            $notModified = strtotime($modifiedSince) >= strtotime($lastModified);
        }
        if ($notModified) {
            $this->setNotModified();
        }
        return $notModified;
    }
    /**
     * Is response invalid?
     *
     * @see https://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html
     *
     * @final
     */
    public function isInvalid(): bool
    {
        return $this->statusCode < 100 || $this->statusCode >= 600;
    }
    /**
     * Is response informative?
     *
     * @final
     */
    public function isInformational(): bool
    {
        return $this->statusCode >= 100 && $this->statusCode < 200;
    }
    /**
     * Is response successful?
     *
     * @final
     */
    public function isSuccessful(): bool
    {
        return $this->statusCode >= 200 && $this->statusCode < 300;
    }
    /**
     * Is the response a redirect?
     *
     * @final
     */
    public function isRedirection(): bool
    {
        return $this->statusCode >= 300 && $this->statusCode < 400;
    }
    /**
     * Is there a client error?
     *
     * @final
     */
    public function isClientError(): bool
    {
        return $this->statusCode >= 400 && $this->statusCode < 500;
    }
    /**
     * Was there a server side error?
     *
     * @final
     */
    public function isServerError(): bool
    {
        return $this->statusCode >= 500 && $this->statusCode < 600;
    }
    /**
     * Is the response OK?
     *
     * @final
     */
    public function isOk(): bool
    {
        return 200 === $this->statusCode;
    }
    /**
     * Is the response forbidden?
     *
     * @final
     */
    public function isForbidden(): bool
    {
        return 403 === $this->statusCode;
    }
    /**
     * Is the response a not found error?
     *
     * @final
     */
    public function isNotFound(): bool
    {
        return 404 === $this->statusCode;
    }
    /**
     * Is the response a redirect of some form?
     *
     * @final
     */
    public function isRedirect(?string $location = null): bool
    {
        return \in_array($this->statusCode, [201, 301, 302, 303, 307, 308]) && (null === $location ?: $location == $this->headers->get('Location'));
    }
    /**
     * Is the response empty?
     *
     * @final
     */
    public function isEmpty(): bool
    {
        return \in_array($this->statusCode, [204, 304]);
    }
    /**
     * Cleans or flushes output buffers up to target level.
     *
     * Resulting level can be greater than target level if a non-removable buffer has been encountered.
     *
     * @final
     */
    public static function closeOutputBuffers(int $targetLevel, bool $flush): void
    {
        $status = ob_get_status(\true);
        $level = \count($status);
        $flags = \PHP_OUTPUT_HANDLER_REMOVABLE | ($flush ? \PHP_OUTPUT_HANDLER_FLUSHABLE : \PHP_OUTPUT_HANDLER_CLEANABLE);
        while ($level-- > $targetLevel && ($s = $status[$level]) && (!isset($s['del']) ? !isset($s['flags']) || ($s['flags'] & $flags) === $flags : $s['del'])) {
            if ($flush) {
                ob_end_flush();
            } else {
                ob_end_clean();
            }
        }
    }
    /**
     * Marks a response as safe according to RFC8674.
     *
     * @see https://tools.ietf.org/html/rfc8674
     */
    public function setContentSafe(bool $safe = \true): void
    {
        if ($safe) {
            $this->headers->set('Preference-Applied', 'safe');
        } elseif ('safe' === $this->headers->get('Preference-Applied')) {
            $this->headers->remove('Preference-Applied');
        }
        $this->setVary('Prefer', \false);
    }
    /**
     * Checks if we need to remove Cache-Control for SSL encrypted downloads when using IE < 9.
     *
     * @see http://support.microsoft.com/kb/323308
     *
     * @final
     */
    protected function ensureIEOverSSLCompatibility(Request $request): void
    {
        if (\false !== stripos($this->headers->get('Content-Disposition') ?? '', 'attachment') && 1 == preg_match('/MSIE (.*?);/i', $request->server->get('HTTP_USER_AGENT') ?? '', $match) && \true === $request->isSecure()) {
            if ((int) preg_replace('/(MSIE )(.*?);/', '$2', $match[0]) < 9) {
                $this->headers->remove('Cache-Control');
            }
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\HttpFoundation;

/**
 * Represents a cookie.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
class Cookie
{
    public const SAMESITE_NONE = 'none';
    public const SAMESITE_LAX = 'lax';
    public const SAMESITE_STRICT = 'strict';
    protected $name;
    protected $value;
    protected $domain;
    protected $expire;
    protected $path;
    protected $secure;
    protected $httpOnly;
    private bool $raw;
    private ?string $sameSite = null;
    private bool $partitioned = \false;
    private bool $secureDefault = \false;
    private const RESERVED_CHARS_LIST = "=,; \t\r\n\v\f";
    private const RESERVED_CHARS_FROM = ['=', ',', ';', ' ', "\t", "\r", "\n", "\v", "\f"];
    private const RESERVED_CHARS_TO = ['%3D', '%2C', '%3B', '%20', '%09', '%0D', '%0A', '%0B', '%0C'];
    /**
     * Creates cookie from raw header string.
     */
    public static function fromString(string $cookie, bool $decode = \false): static
    {
        $data = ['expires' => 0, 'path' => '/', 'domain' => null, 'secure' => \false, 'httponly' => \false, 'raw' => !$decode, 'samesite' => null, 'partitioned' => \false];
        $parts = HeaderUtils::split($cookie, ';=');
        $part = array_shift($parts);
        $name = $decode ? urldecode($part[0]) : $part[0];
        $value = isset($part[1]) ? $decode ? urldecode($part[1]) : $part[1] : null;
        $data = HeaderUtils::combine($parts) + $data;
        $data['expires'] = self::expiresTimestamp($data['expires']);
        if (isset($data['max-age']) && ($data['max-age'] > 0 || $data['expires'] > time())) {
            $data['expires'] = time() + (int) $data['max-age'];
        }
        return new static($name, $value, $data['expires'], $data['path'], $data['domain'], $data['secure'], $data['httponly'], $data['raw'], $data['samesite'], $data['partitioned']);
    }
    /**
     * @see self::__construct
     *
     * @param self::SAMESITE_*|''|null $sameSite
     * @param bool                     $partitioned
     */
    public static function create(string $name, ?string $value = null, int|string|\DateTimeInterface $expire = 0, ?string $path = '/', ?string $domain = null, ?bool $secure = null, bool $httpOnly = \true, bool $raw = \false, ?string $sameSite = self::SAMESITE_LAX): self
    {
        $partitioned = 9 < \func_num_args() ? func_get_arg(9) : \false;
        return new self($name, $value, $expire, $path, $domain, $secure, $httpOnly, $raw, $sameSite, $partitioned);
    }
    /**
     * @param string                        $name     The name of the cookie
     * @param string|null                   $value    The value of the cookie
     * @param int|string|\DateTimeInterface $expire   The time the cookie expires
     * @param string|null                   $path     The path on the server in which the cookie will be available on
     * @param string|null                   $domain   The domain that the cookie is available to
     * @param bool|null                     $secure   Whether the client should send back the cookie only over HTTPS or null to auto-enable this when the request is already using HTTPS
     * @param bool                          $httpOnly Whether the cookie will be made accessible only through the HTTP protocol
     * @param bool                          $raw      Whether the cookie value should be sent with no url encoding
     * @param self::SAMESITE_*|''|null      $sameSite Whether the cookie will be available for cross-site requests
     *
     * @throws \InvalidArgumentException
     */
    public function __construct(string $name, ?string $value = null, int|string|\DateTimeInterface $expire = 0, ?string $path = '/', ?string $domain = null, ?bool $secure = null, bool $httpOnly = \true, bool $raw = \false, ?string $sameSite = self::SAMESITE_LAX, bool $partitioned = \false)
    {
        // from PHP source code
        if ($raw && \false !== strpbrk($name, self::RESERVED_CHARS_LIST)) {
            throw new \InvalidArgumentException(\sprintf('The cookie name "%s" contains invalid characters.', $name));
        }
        if (empty($name)) {
            throw new \InvalidArgumentException('The cookie name cannot be empty.');
        }
        $this->name = $name;
        $this->value = $value;
        $this->domain = $domain;
        $this->expire = self::expiresTimestamp($expire);
        $this->path = empty($path) ? '/' : $path;
        $this->secure = $secure;
        $this->httpOnly = $httpOnly;
        $this->raw = $raw;
        $this->sameSite = $this->withSameSite($sameSite)->sameSite;
        $this->partitioned = $partitioned;
    }
    /**
     * Creates a cookie copy with a new value.
     */
    public function withValue(?string $value): static
    {
        $cookie = clone $this;
        $cookie->value = $value;
        return $cookie;
    }
    /**
     * Creates a cookie copy with a new domain that the cookie is available to.
     */
    public function withDomain(?string $domain): static
    {
        $cookie = clone $this;
        $cookie->domain = $domain;
        return $cookie;
    }
    /**
     * Creates a cookie copy with a new time the cookie expires.
     */
    public function withExpires(int|string|\DateTimeInterface $expire = 0): static
    {
        $cookie = clone $this;
        $cookie->expire = self::expiresTimestamp($expire);
        return $cookie;
    }
    /**
     * Converts expires formats to a unix timestamp.
     */
    private static function expiresTimestamp(int|string|\DateTimeInterface $expire = 0): int
    {
        // convert expiration time to a Unix timestamp
        if ($expire instanceof \DateTimeInterface) {
            $expire = $expire->format('U');
        } elseif (!is_numeric($expire)) {
            $expire = strtotime($expire);
            if (\false === $expire) {
                throw new \InvalidArgumentException('The cookie expiration time is not valid.');
            }
        }
        return 0 < $expire ? (int) $expire : 0;
    }
    /**
     * Creates a cookie copy with a new path on the server in which the cookie will be available on.
     */
    public function withPath(string $path): static
    {
        $cookie = clone $this;
        $cookie->path = '' === $path ? '/' : $path;
        return $cookie;
    }
    /**
     * Creates a cookie copy that only be transmitted over a secure HTTPS connection from the client.
     */
    public function withSecure(bool $secure = \true): static
    {
        $cookie = clone $this;
        $cookie->secure = $secure;
        return $cookie;
    }
    /**
     * Creates a cookie copy that be accessible only through the HTTP protocol.
     */
    public function withHttpOnly(bool $httpOnly = \true): static
    {
        $cookie = clone $this;
        $cookie->httpOnly = $httpOnly;
        return $cookie;
    }
    /**
     * Creates a cookie copy that uses no url encoding.
     */
    public function withRaw(bool $raw = \true): static
    {
        if ($raw && \false !== strpbrk($this->name, self::RESERVED_CHARS_LIST)) {
            throw new \InvalidArgumentException(\sprintf('The cookie name "%s" contains invalid characters.', $this->name));
        }
        $cookie = clone $this;
        $cookie->raw = $raw;
        return $cookie;
    }
    /**
     * Creates a cookie copy with SameSite attribute.
     *
     * @param self::SAMESITE_*|''|null $sameSite
     */
    public function withSameSite(?string $sameSite): static
    {
        if ('' === $sameSite) {
            $sameSite = null;
        } elseif (null !== $sameSite) {
            $sameSite = strtolower($sameSite);
        }
        if (!\in_array($sameSite, [self::SAMESITE_LAX, self::SAMESITE_STRICT, self::SAMESITE_NONE, null], \true)) {
            throw new \InvalidArgumentException('The "sameSite" parameter value is not valid.');
        }
        $cookie = clone $this;
        $cookie->sameSite = $sameSite;
        return $cookie;
    }
    /**
     * Creates a cookie copy that is tied to the top-level site in cross-site context.
     */
    public function withPartitioned(bool $partitioned = \true): static
    {
        $cookie = clone $this;
        $cookie->partitioned = $partitioned;
        return $cookie;
    }
    /**
     * Returns the cookie as a string.
     */
    public function __toString(): string
    {
        if ($this->isRaw()) {
            $str = $this->getName();
        } else {
            $str = str_replace(self::RESERVED_CHARS_FROM, self::RESERVED_CHARS_TO, $this->getName());
        }
        $str .= '=';
        if ('' === (string) $this->getValue()) {
            $str .= 'deleted; expires=' . gmdate('D, d M Y H:i:s T', time() - 31536001) . '; Max-Age=0';
        } else {
            $str .= $this->isRaw() ? $this->getValue() : rawurlencode($this->getValue());
            if (0 !== $this->getExpiresTime()) {
                $str .= '; expires=' . gmdate('D, d M Y H:i:s T', $this->getExpiresTime()) . '; Max-Age=' . $this->getMaxAge();
            }
        }
        if ($this->getPath()) {
            $str .= '; path=' . $this->getPath();
        }
        if ($this->getDomain()) {
            $str .= '; domain=' . $this->getDomain();
        }
        if ($this->isSecure()) {
            $str .= '; secure';
        }
        if ($this->isHttpOnly()) {
            $str .= '; httponly';
        }
        if (null !== $this->getSameSite()) {
            $str .= '; samesite=' . $this->getSameSite();
        }
        if ($this->isPartitioned()) {
            $str .= '; partitioned';
        }
        return $str;
    }
    /**
     * Gets the name of the cookie.
     */
    public function getName(): string
    {
        return $this->name;
    }
    /**
     * Gets the value of the cookie.
     */
    public function getValue(): ?string
    {
        return $this->value;
    }
    /**
     * Gets the domain that the cookie is available to.
     */
    public function getDomain(): ?string
    {
        return $this->domain;
    }
    /**
     * Gets the time the cookie expires.
     */
    public function getExpiresTime(): int
    {
        return $this->expire;
    }
    /**
     * Gets the max-age attribute.
     */
    public function getMaxAge(): int
    {
        $maxAge = $this->expire - time();
        return 0 >= $maxAge ? 0 : $maxAge;
    }
    /**
     * Gets the path on the server in which the cookie will be available on.
     */
    public function getPath(): string
    {
        return $this->path;
    }
    /**
     * Checks whether the cookie should only be transmitted over a secure HTTPS connection from the client.
     */
    public function isSecure(): bool
    {
        return $this->secure ?? $this->secureDefault;
    }
    /**
     * Checks whether the cookie will be made accessible only through the HTTP protocol.
     */
    public function isHttpOnly(): bool
    {
        return $this->httpOnly;
    }
    /**
     * Whether this cookie is about to be cleared.
     */
    public function isCleared(): bool
    {
        return 0 !== $this->expire && $this->expire < time();
    }
    /**
     * Checks if the cookie value should be sent with no url encoding.
     */
    public function isRaw(): bool
    {
        return $this->raw;
    }
    /**
     * Checks whether the cookie should be tied to the top-level site in cross-site context.
     */
    public function isPartitioned(): bool
    {
        return $this->partitioned;
    }
    /**
     * @return self::SAMESITE_*|null
     */
    public function getSameSite(): ?string
    {
        return $this->sameSite;
    }
    /**
     * @param bool $default The default value of the "secure" flag when it is set to null
     */
    public function setSecureDefault(bool $default): void
    {
        $this->secureDefault = $default;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\HttpFoundation;

// Help opcache.preload discover always-needed symbols
class_exists(AcceptHeaderItem::class);
/**
 * Represents an Accept-* header.
 *
 * An accept header is compound with a list of items,
 * sorted by descending quality.
 *
 * @author Jean-François Simon <contact@jfsimon.fr>
 */
class AcceptHeader
{
    /**
     * @var array<string, AcceptHeaderItem>
     */
    private array $items = [];
    private bool $sorted = \true;
    /**
     * @param AcceptHeaderItem[] $items
     */
    public function __construct(array $items)
    {
        foreach ($items as $item) {
            $this->add($item);
        }
    }
    /**
     * Builds an AcceptHeader instance from a string.
     */
    public static function fromString(?string $headerValue): self
    {
        $items = [];
        foreach (HeaderUtils::split($headerValue ?? '', ',;=') as $i => $parts) {
            $part = array_shift($parts);
            $item = new AcceptHeaderItem($part[0], HeaderUtils::combine($parts));
            $items[] = $item->setIndex($i);
        }
        return new self($items);
    }
    /**
     * Returns header value's string representation.
     */
    public function __toString(): string
    {
        return implode(',', $this->items);
    }
    /**
     * Tests if header has given value.
     */
    public function has(string $value): bool
    {
        $canonicalKey = $this->getCanonicalKey(AcceptHeaderItem::fromString($value));
        return isset($this->items[$canonicalKey]);
    }
    /**
     * Returns given value's item, if exists.
     */
    public function get(string $value): ?AcceptHeaderItem
    {
        $queryItem = AcceptHeaderItem::fromString($value . ';q=1');
        $canonicalKey = $this->getCanonicalKey($queryItem);
        if (isset($this->items[$canonicalKey])) {
            return $this->items[$canonicalKey];
        }
        // Collect and filter matching candidates
        if (!$candidates = array_filter($this->items, fn(AcceptHeaderItem $item) => $this->matches($item, $queryItem))) {
            return null;
        }
        usort($candidates, fn($a, $b) => ($this->getSpecificity($b, $queryItem) <=> $this->getSpecificity($a, $queryItem) ?: $b->getQuality() <=> $a->getQuality()) ?: $a->getIndex() <=> $b->getIndex());
        return reset($candidates);
    }
    /**
     * Adds an item.
     *
     * @return $this
     */
    public function add(AcceptHeaderItem $item): static
    {
        $this->items[$this->getCanonicalKey($item)] = $item;
        $this->sorted = \false;
        return $this;
    }
    /**
     * Returns all items.
     *
     * @return AcceptHeaderItem[]
     */
    public function all(): array
    {
        $this->sort();
        return $this->items;
    }
    /**
     * Filters items on their value using given regex.
     */
    public function filter(string $pattern): self
    {
        return new self(array_filter($this->items, static fn($item) => preg_match($pattern, $item->getValue())));
    }
    /**
     * Returns first item.
     */
    public function first(): ?AcceptHeaderItem
    {
        $this->sort();
        return $this->items ? reset($this->items) : null;
    }
    /**
     * Sorts items by descending quality.
     */
    private function sort(): void
    {
        if (!$this->sorted) {
            uasort($this->items, static fn($a, $b) => $b->getQuality() <=> $a->getQuality() ?: $a->getIndex() <=> $b->getIndex());
            $this->sorted = \true;
        }
    }
    /**
     * Generates the canonical key for storing/retrieving an item.
     */
    private function getCanonicalKey(AcceptHeaderItem $item): string
    {
        $parts = [];
        // Normalize and sort attributes for consistent key generation
        $attributes = $this->getMediaParams($item);
        ksort($attributes);
        foreach ($attributes as $name => $value) {
            if (null === $value) {
                $parts[] = $name;
                // Flag parameter (e.g., "flowed")
                continue;
            }
            // Quote values containing spaces, commas, semicolons, or equals per RFC 9110
            // This handles cases like 'format="value with space"' or similar.
            $quotedValue = \is_string($value) && preg_match('/[\s;,=]/', $value) ? '"' . addcslashes($value, '"\\') . '"' : $value;
            $parts[] = $name . '=' . $quotedValue;
        }
        return $item->getValue() . ($parts ? ';' . implode(';', $parts) : '');
    }
    /**
     * Checks if a given header item (range) matches a queried item (value).
     *
     * @param AcceptHeaderItem $rangeItem The item from the Accept header (e.g., text/*;format=flowed)
     * @param AcceptHeaderItem $queryItem The item being queried (e.g., text/plain;format=flowed;charset=utf-8)
     */
    private function matches(AcceptHeaderItem $rangeItem, AcceptHeaderItem $queryItem): bool
    {
        $rangeValue = strtolower($rangeItem->getValue());
        $queryValue = strtolower($queryItem->getValue());
        // Handle universal wildcard ranges
        if ('*' === $rangeValue || '*/*' === $rangeValue) {
            return $this->rangeParametersMatch($rangeItem, $queryItem);
        }
        // Queries for '*' only match wildcard ranges (handled above)
        if ('*' === $queryValue) {
            return \false;
        }
        // Ensure media vs. non-media consistency
        $isQueryMedia = str_contains($queryValue, '/');
        $isRangeMedia = str_contains($rangeValue, '/');
        if ($isQueryMedia !== $isRangeMedia) {
            return \false;
        }
        // Non-media: exact match only (wildcards handled above)
        if (!$isQueryMedia) {
            return $rangeValue === $queryValue && $this->rangeParametersMatch($rangeItem, $queryItem);
        }
        // Media type: type/subtype with wildcards
        [$queryType, $querySubtype] = explode('/', $queryValue, 2);
        [$rangeType, $rangeSubtype] = explode('/', $rangeValue, 2) + [1 => '*'];
        if ('*' !== $rangeType && $rangeType !== $queryType) {
            return \false;
        }
        if ('*' !== $rangeSubtype && $rangeSubtype !== $querySubtype) {
            return \false;
        }
        // Parameters must match
        return $this->rangeParametersMatch($rangeItem, $queryItem);
    }
    /**
     * Checks if the parameters of a range item are satisfied by the query item.
     *
     * Parameters are case-insensitive; range params must be a subset of query params.
     */
    private function rangeParametersMatch(AcceptHeaderItem $rangeItem, AcceptHeaderItem $queryItem): bool
    {
        $queryAttributes = $this->getMediaParams($queryItem);
        $rangeAttributes = $this->getMediaParams($rangeItem);
        foreach ($rangeAttributes as $name => $rangeValue) {
            if (!\array_key_exists($name, $queryAttributes)) {
                return \false;
                // Missing required param
            }
            $queryValue = $queryAttributes[$name];
            if (null === $rangeValue) {
                return null === $queryValue;
                // Both flags or neither
            }
            if (null === $queryValue || strtolower($queryValue) !== strtolower($rangeValue)) {
                return \false;
            }
        }
        return \true;
    }
    /**
     * Calculates a specificity score for sorting: media precision + param count.
     */
    private function getSpecificity(AcceptHeaderItem $item, AcceptHeaderItem $queryItem): int
    {
        $rangeValue = strtolower($item->getValue());
        $queryValue = strtolower($queryItem->getValue());
        $paramCount = \count($this->getMediaParams($item));
        $isQueryMedia = str_contains($queryValue, '/');
        $isRangeMedia = str_contains($rangeValue, '/');
        if (!$isQueryMedia && !$isRangeMedia) {
            return ('*' !== $rangeValue ? 2000 : 1000) + $paramCount;
        }
        [$rangeType, $rangeSubtype] = explode('/', $rangeValue, 2) + [1 => '*'];
        $specificity = match (\true) {
            '*' !== $rangeSubtype => 3000,
            // Exact subtype (text/plain)
            '*' !== $rangeType => 2000,
            // Type wildcard (text/*)
            default => 1000,
        };
        return $specificity + $paramCount;
    }
    /**
     * Returns normalized attributes: keys lowercased, excluding 'q'.
     */
    private function getMediaParams(AcceptHeaderItem $item): array
    {
        $attributes = array_change_key_case($item->getAttributes(), \CASE_LOWER);
        unset($attributes['q']);
        return $attributes;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\HttpFoundation;

trigger_deprecation('symfony/http-foundation', '6.2', 'The "%s" class is deprecated, use "%s" instead.', RequestMatcher::class, ChainRequestMatcher::class);
/**
 * RequestMatcher compares a pre-defined set of checks against a Request instance.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 *
 * @deprecated since Symfony 6.2, use ChainRequestMatcher instead
 */
class RequestMatcher implements RequestMatcherInterface
{
    private ?string $path = null;
    private ?string $host = null;
    private ?int $port = null;
    /**
     * @var string[]
     */
    private array $methods = [];
    /**
     * @var string[]
     */
    private array $ips = [];
    /**
     * @var string[]
     */
    private array $attributes = [];
    /**
     * @var string[]
     */
    private array $schemes = [];
    /**
     * @param string|string[]|null $methods
     * @param string|string[]|null $ips
     * @param string|string[]|null $schemes
     */
    public function __construct(?string $path = null, ?string $host = null, string|array|null $methods = null, string|array|null $ips = null, array $attributes = [], string|array|null $schemes = null, ?int $port = null)
    {
        $this->matchPath($path);
        $this->matchHost($host);
        $this->matchMethod($methods);
        $this->matchIps($ips);
        $this->matchScheme($schemes);
        $this->matchPort($port);
        foreach ($attributes as $k => $v) {
            $this->matchAttribute($k, $v);
        }
    }
    /**
     * Adds a check for the HTTP scheme.
     *
     * @param string|string[]|null $scheme An HTTP scheme or an array of HTTP schemes
     *
     * @return void
     */
    public function matchScheme(string|array|null $scheme)
    {
        $this->schemes = null !== $scheme ? array_map('strtolower', (array) $scheme) : [];
    }
    /**
     * Adds a check for the URL host name.
     *
     * @return void
     */
    public function matchHost(?string $regexp)
    {
        $this->host = $regexp;
    }
    /**
     * Adds a check for the URL port.
     *
     * @param int|null $port The port number to connect to
     *
     * @return void
     */
    public function matchPort(?int $port)
    {
        $this->port = $port;
    }
    /**
     * Adds a check for the URL path info.
     *
     * @return void
     */
    public function matchPath(?string $regexp)
    {
        $this->path = $regexp;
    }
    /**
     * Adds a check for the client IP.
     *
     * @param string $ip A specific IP address or a range specified using IP/netmask like 192.168.1.0/24
     *
     * @return void
     */
    public function matchIp(string $ip)
    {
        $this->matchIps($ip);
    }
    /**
     * Adds a check for the client IP.
     *
     * @param string|string[]|null $ips A specific IP address or a range specified using IP/netmask like 192.168.1.0/24
     *
     * @return void
     */
    public function matchIps(string|array|null $ips)
    {
        $ips = null !== $ips ? (array) $ips : [];
        $this->ips = array_reduce($ips, static fn(array $ips, string $ip) => array_merge($ips, preg_split('/\s*,\s*/', $ip)), []);
    }
    /**
     * Adds a check for the HTTP method.
     *
     * @param string|string[]|null $method An HTTP method or an array of HTTP methods
     *
     * @return void
     */
    public function matchMethod(string|array|null $method)
    {
        $this->methods = null !== $method ? array_map('strtoupper', (array) $method) : [];
    }
    /**
     * Adds a check for request attribute.
     *
     * @return void
     */
    public function matchAttribute(string $key, string $regexp)
    {
        $this->attributes[$key] = $regexp;
    }
    public function matches(Request $request): bool
    {
        if ($this->schemes && !\in_array($request->getScheme(), $this->schemes, \true)) {
            return \false;
        }
        if ($this->methods && !\in_array($request->getMethod(), $this->methods, \true)) {
            return \false;
        }
        foreach ($this->attributes as $key => $pattern) {
            $requestAttribute = $request->attributes->get($key);
            if (!\is_string($requestAttribute)) {
                return \false;
            }
            if (!preg_match('{' . $pattern . '}', $requestAttribute)) {
                return \false;
            }
        }
        if (null !== $this->path && !preg_match('{' . $this->path . '}', rawurldecode($request->getPathInfo()))) {
            return \false;
        }
        if (null !== $this->host && !preg_match('{' . $this->host . '}i', $request->getHost())) {
            return \false;
        }
        if (null !== $this->port && 0 < $this->port && $request->getPort() !== $this->port) {
            return \false;
        }
        if (IpUtils::checkIp($request->getClientIp() ?? '', $this->ips)) {
            return \true;
        }
        // Note to future implementors: add additional checks above the
        // foreach above or else your check might not be run!
        return 0 === \count($this->ips);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\HttpFoundation;

/**
 * ResponseHeaderBag is a container for Response HTTP headers.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class ResponseHeaderBag extends HeaderBag
{
    public const COOKIES_FLAT = 'flat';
    public const COOKIES_ARRAY = 'array';
    public const DISPOSITION_ATTACHMENT = 'attachment';
    public const DISPOSITION_INLINE = 'inline';
    protected $computedCacheControl = [];
    protected $cookies = [];
    protected $headerNames = [];
    public function __construct(array $headers = [])
    {
        parent::__construct($headers);
        if (!isset($this->headers['cache-control'])) {
            $this->set('Cache-Control', '');
        }
        /* RFC2616 - 14.18 says all Responses need to have a Date */
        if (!isset($this->headers['date'])) {
            $this->initDate();
        }
    }
    /**
     * Returns the headers, with original capitalizations.
     */
    public function allPreserveCase(): array
    {
        $headers = [];
        foreach ($this->all() as $name => $value) {
            $headers[$this->headerNames[$name] ?? $name] = $value;
        }
        return $headers;
    }
    /**
     * @return array
     */
    public function allPreserveCaseWithoutCookies()
    {
        $headers = $this->allPreserveCase();
        if (isset($this->headerNames['set-cookie'])) {
            unset($headers[$this->headerNames['set-cookie']]);
        }
        return $headers;
    }
    /**
     * @return void
     */
    public function replace(array $headers = [])
    {
        $this->headerNames = [];
        parent::replace($headers);
        if (!isset($this->headers['cache-control'])) {
            $this->set('Cache-Control', '');
        }
        if (!isset($this->headers['date'])) {
            $this->initDate();
        }
    }
    public function all(?string $key = null): array
    {
        $headers = parent::all();
        if (null !== $key) {
            $key = strtr($key, self::UPPER, self::LOWER);
            return 'set-cookie' !== $key ? $headers[$key] ?? [] : array_map('strval', $this->getCookies());
        }
        foreach ($this->getCookies() as $cookie) {
            $headers['set-cookie'][] = (string) $cookie;
        }
        return $headers;
    }
    /**
     * @return void
     */
    public function set(string $key, string|array|null $values, bool $replace = \true)
    {
        $uniqueKey = strtr($key, self::UPPER, self::LOWER);
        if ('set-cookie' === $uniqueKey) {
            if ($replace) {
                $this->cookies = [];
            }
            foreach ((array) $values as $cookie) {
                $this->setCookie(Cookie::fromString($cookie));
            }
            $this->headerNames[$uniqueKey] = $key;
            return;
        }
        $this->headerNames[$uniqueKey] = $key;
        parent::set($key, $values, $replace);
        // ensure the cache-control header has sensible defaults
        if (\in_array($uniqueKey, ['cache-control', 'etag', 'last-modified', 'expires'], \true) && '' !== $computed = $this->computeCacheControlValue()) {
            $this->headers['cache-control'] = [$computed];
            $this->headerNames['cache-control'] = 'Cache-Control';
            $this->computedCacheControl = $this->parseCacheControl($computed);
        }
    }
    /**
     * @return void
     */
    public function remove(string $key)
    {
        $uniqueKey = strtr($key, self::UPPER, self::LOWER);
        unset($this->headerNames[$uniqueKey]);
        if ('set-cookie' === $uniqueKey) {
            $this->cookies = [];
            return;
        }
        parent::remove($key);
        if ('cache-control' === $uniqueKey) {
            $this->computedCacheControl = [];
        }
        if ('date' === $uniqueKey) {
            $this->initDate();
        }
    }
    public function hasCacheControlDirective(string $key): bool
    {
        return \array_key_exists($key, $this->computedCacheControl);
    }
    public function getCacheControlDirective(string $key): bool|string|null
    {
        return $this->computedCacheControl[$key] ?? null;
    }
    /**
     * @return void
     */
    public function setCookie(Cookie $cookie)
    {
        $this->cookies[$cookie->getDomain() ?? ''][$cookie->getPath()][$cookie->getName()] = $cookie;
        $this->headerNames['set-cookie'] = 'Set-Cookie';
    }
    /**
     * Removes a cookie from the array, but does not unset it in the browser.
     *
     * @return void
     */
    public function removeCookie(string $name, ?string $path = '/', ?string $domain = null)
    {
        $path ??= '/';
        unset($this->cookies[$domain ?? ''][$path][$name]);
        if (empty($this->cookies[$domain ?? ''][$path])) {
            unset($this->cookies[$domain ?? ''][$path]);
            if (empty($this->cookies[$domain ?? ''])) {
                unset($this->cookies[$domain ?? '']);
            }
        }
        if (empty($this->cookies)) {
            unset($this->headerNames['set-cookie']);
        }
    }
    /**
     * Returns an array with all cookies.
     *
     * @return Cookie[]
     *
     * @throws \InvalidArgumentException When the $format is invalid
     */
    public function getCookies(string $format = self::COOKIES_FLAT): array
    {
        if (!\in_array($format, [self::COOKIES_FLAT, self::COOKIES_ARRAY])) {
            throw new \InvalidArgumentException(\sprintf('Format "%s" invalid (%s).', $format, implode(', ', [self::COOKIES_FLAT, self::COOKIES_ARRAY])));
        }
        if (self::COOKIES_ARRAY === $format) {
            return $this->cookies;
        }
        $flattenedCookies = [];
        foreach ($this->cookies as $path) {
            foreach ($path as $cookies) {
                foreach ($cookies as $cookie) {
                    $flattenedCookies[] = $cookie;
                }
            }
        }
        return $flattenedCookies;
    }
    /**
     * Clears a cookie in the browser.
     *
     * @param bool $partitioned
     *
     * @return void
     */
    public function clearCookie(string $name, ?string $path = '/', ?string $domain = null, bool $secure = \false, bool $httpOnly = \true, ?string $sameSite = null)
    {
        $partitioned = 6 < \func_num_args() ? func_get_arg(6) : \false;
        $this->setCookie(new Cookie($name, null, 1, $path, $domain, $secure, $httpOnly, \false, $sameSite, $partitioned));
    }
    /**
     * @see HeaderUtils::makeDisposition()
     *
     * @return string
     */
    public function makeDisposition(string $disposition, string $filename, string $filenameFallback = '')
    {
        return HeaderUtils::makeDisposition($disposition, $filename, $filenameFallback);
    }
    /**
     * Returns the calculated value of the cache-control header.
     *
     * This considers several other headers and calculates or modifies the
     * cache-control header to a sensible, conservative value.
     */
    protected function computeCacheControlValue(): string
    {
        if (!$this->cacheControl) {
            if ($this->has('Last-Modified') || $this->has('Expires')) {
                return 'private, must-revalidate';
                // allows for heuristic expiration (RFC 7234 Section 4.2.2) in the case of "Last-Modified"
            }
            // conservative by default
            return 'no-cache, private';
        }
        $header = $this->getCacheControlHeader();
        if (isset($this->cacheControl['public']) || isset($this->cacheControl['private'])) {
            return $header;
        }
        // public if s-maxage is defined, private otherwise
        if (!isset($this->cacheControl['s-maxage'])) {
            return $header . ', private';
        }
        return $header;
    }
    private function initDate(): void
    {
        $this->set('Date', gmdate('D, d M Y H:i:s') . ' GMT');
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\HttpFoundation;

/**
 * HTTP header utility functions.
 *
 * @author Christian Schmidt <github@chsc.dk>
 */
class HeaderUtils
{
    public const DISPOSITION_ATTACHMENT = 'attachment';
    public const DISPOSITION_INLINE = 'inline';
    /**
     * This class should not be instantiated.
     */
    private function __construct()
    {
    }
    /**
     * Splits an HTTP header by one or more separators.
     *
     * Example:
     *
     *     HeaderUtils::split('da, en-gb;q=0.8', ',;')
     *     // => ['da'], ['en-gb', 'q=0.8']]
     *
     * @param string $separators List of characters to split on, ordered by
     *                           precedence, e.g. ',', ';=', or ',;='
     *
     * @return array Nested array with as many levels as there are characters in
     *               $separators
     */
    public static function split(string $header, string $separators): array
    {
        if ('' === $separators) {
            throw new \InvalidArgumentException('At least one separator must be specified.');
        }
        $quotedSeparators = preg_quote($separators, '/');
        preg_match_all('
            /
                (?!\s)
                    (?:
                        # quoted-string
                        "(?:[^"\\\\]|\\\\.)*(?:"|\\\\|$)
                    |
                        # token
                        [^"' . $quotedSeparators . ']+
                    )+
                (?<!\s)
            |
                # separator
                \s*
                (?<separator>[' . $quotedSeparators . '])
                \s*
            /x', trim($header), $matches, \PREG_SET_ORDER);
        return self::groupParts($matches, $separators);
    }
    /**
     * Combines an array of arrays into one associative array.
     *
     * Each of the nested arrays should have one or two elements. The first
     * value will be used as the keys in the associative array, and the second
     * will be used as the values, or true if the nested array only contains one
     * element. Array keys are lowercased.
     *
     * Example:
     *
     *     HeaderUtils::combine([['foo', 'abc'], ['bar']])
     *     // => ['foo' => 'abc', 'bar' => true]
     */
    public static function combine(array $parts): array
    {
        $assoc = [];
        foreach ($parts as $part) {
            $name = strtolower($part[0]);
            $value = $part[1] ?? \true;
            $assoc[$name] = $value;
        }
        return $assoc;
    }
    /**
     * Joins an associative array into a string for use in an HTTP header.
     *
     * The key and value of each entry are joined with '=', and all entries
     * are joined with the specified separator and an additional space (for
     * readability). Values are quoted if necessary.
     *
     * Example:
     *
     *     HeaderUtils::toString(['foo' => 'abc', 'bar' => true, 'baz' => 'a b c'], ',')
     *     // => 'foo=abc, bar, baz="a b c"'
     */
    public static function toString(array $assoc, string $separator): string
    {
        $parts = [];
        foreach ($assoc as $name => $value) {
            if (\true === $value) {
                $parts[] = $name;
            } else {
                $parts[] = $name . '=' . self::quote($value);
            }
        }
        return implode($separator . ' ', $parts);
    }
    /**
     * Encodes a string as a quoted string, if necessary.
     *
     * If a string contains characters not allowed by the "token" construct in
     * the HTTP specification, it is backslash-escaped and enclosed in quotes
     * to match the "quoted-string" construct.
     */
    public static function quote(string $s): string
    {
        if (preg_match('/^[a-z0-9!#$%&\'*.^_`|~-]+$/i', $s)) {
            return $s;
        }
        return '"' . addcslashes($s, '"\"') . '"';
    }
    /**
     * Decodes a quoted string.
     *
     * If passed an unquoted string that matches the "token" construct (as
     * defined in the HTTP specification), it is passed through verbatim.
     */
    public static function unquote(string $s): string
    {
        return preg_replace('/\\\\(.)|"/', '$1', $s);
    }
    /**
     * Generates an HTTP Content-Disposition field-value.
     *
     * @param string $disposition      One of "inline" or "attachment"
     * @param string $filename         A unicode string
     * @param string $filenameFallback A string containing only ASCII characters that
     *                                 is semantically equivalent to $filename. If the filename is already ASCII,
     *                                 it can be omitted, or just copied from $filename
     *
     * @throws \InvalidArgumentException
     *
     * @see RFC 6266
     */
    public static function makeDisposition(string $disposition, string $filename, string $filenameFallback = ''): string
    {
        if (!\in_array($disposition, [self::DISPOSITION_ATTACHMENT, self::DISPOSITION_INLINE])) {
            throw new \InvalidArgumentException(\sprintf('The disposition must be either "%s" or "%s".', self::DISPOSITION_ATTACHMENT, self::DISPOSITION_INLINE));
        }
        if ('' === $filenameFallback) {
            $filenameFallback = $filename;
        }
        // filenameFallback is not ASCII.
        if (!preg_match('/^[\x20-\x7e]*$/', $filenameFallback)) {
            throw new \InvalidArgumentException('The filename fallback must only contain ASCII characters.');
        }
        // percent characters aren't safe in fallback.
        if (str_contains($filenameFallback, '%')) {
            throw new \InvalidArgumentException('The filename fallback cannot contain the "%" character.');
        }
        // path separators aren't allowed in either.
        if (str_contains($filename, '/') || str_contains($filename, '\\') || str_contains($filenameFallback, '/') || str_contains($filenameFallback, '\\')) {
            throw new \InvalidArgumentException('The filename and the fallback cannot contain the "/" and "\" characters.');
        }
        $params = ['filename' => $filenameFallback];
        if ($filename !== $filenameFallback) {
            $params['filename*'] = "utf-8''" . rawurlencode($filename);
        }
        return $disposition . '; ' . self::toString($params, ';');
    }
    /**
     * Like parse_str(), but preserves dots in variable names.
     */
    public static function parseQuery(string $query, bool $ignoreBrackets = \false, string $separator = '&'): array
    {
        $q = [];
        foreach (explode($separator, $query) as $v) {
            if (\false !== $i = strpos($v, "\x00")) {
                $v = substr($v, 0, $i);
            }
            if (\false === $i = strpos($v, '=')) {
                $k = urldecode($v);
                $v = '';
            } else {
                $k = urldecode(substr($v, 0, $i));
                $v = substr($v, $i);
            }
            if (\false !== $i = strpos($k, "\x00")) {
                $k = substr($k, 0, $i);
            }
            $k = ltrim($k, ' ');
            if ($ignoreBrackets) {
                $q[$k][] = urldecode(substr($v, 1));
                continue;
            }
            if (\false === $i = strpos($k, '[')) {
                $q[] = bin2hex($k) . $v;
            } else {
                $q[] = bin2hex(substr($k, 0, $i)) . rawurlencode(substr($k, $i)) . $v;
            }
        }
        if ($ignoreBrackets) {
            return $q;
        }
        parse_str(implode('&', $q), $q);
        $query = [];
        foreach ($q as $k => $v) {
            if (\false !== $i = strpos($k, '_')) {
                $query[substr_replace($k, hex2bin(substr($k, 0, $i)) . '[', 0, 1 + $i)] = $v;
            } else {
                $query[hex2bin($k)] = $v;
            }
        }
        return $query;
    }
    private static function groupParts(array $matches, string $separators, bool $first = \true): array
    {
        $separator = $separators[0];
        $separators = substr($separators, 1) ?: '';
        $i = 0;
        if ('' === $separators && !$first) {
            $parts = [''];
            foreach ($matches as $match) {
                if (!$i && isset($match['separator'])) {
                    $i = 1;
                    $parts[1] = '';
                } else {
                    $parts[$i] .= self::unquote($match[0]);
                }
            }
            return $parts;
        }
        $parts = [];
        $partMatches = [];
        foreach ($matches as $match) {
            if (($match['separator'] ?? null) === $separator) {
                ++$i;
            } else {
                $partMatches[$i][] = $match;
            }
        }
        foreach ($partMatches as $matches) {
            if ('' === $separators && '' !== $unquoted = self::unquote($matches[0][0])) {
                $parts[] = $unquoted;
            } elseif ($groupedParts = self::groupParts($matches, $separators, \false)) {
                $parts[] = $groupedParts;
            }
        }
        return $parts;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\HttpFoundation\RequestMatcher;

use _ContaoManager\Symfony\Component\HttpFoundation\Request;
use _ContaoManager\Symfony\Component\HttpFoundation\RequestMatcherInterface;
/**
 * Checks the HTTP method of a Request.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class MethodRequestMatcher implements RequestMatcherInterface
{
    /**
     * @var string[]
     */
    private array $methods = [];
    /**
     * @param string[]|string $methods An HTTP method or an array of HTTP methods
     *                                 Strings can contain a comma-delimited list of methods
     */
    public function __construct(array|string $methods)
    {
        $this->methods = array_reduce(array_map('strtoupper', (array) $methods), static fn(array $methods, string $method) => array_merge($methods, preg_split('/\s*,\s*/', $method)), []);
    }
    public function matches(Request $request): bool
    {
        if (!$this->methods) {
            return \true;
        }
        return \in_array($request->getMethod(), $this->methods, \true);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\HttpFoundation\RequestMatcher;

use _ContaoManager\Symfony\Component\HttpFoundation\Request;
use _ContaoManager\Symfony\Component\HttpFoundation\RequestMatcherInterface;
/**
 * Checks the Request URL path info matches a regular expression.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class PathRequestMatcher implements RequestMatcherInterface
{
    public function __construct(private string $regexp)
    {
    }
    public function matches(Request $request): bool
    {
        return preg_match('{' . $this->regexp . '}', rawurldecode($request->getPathInfo()));
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\HttpFoundation\RequestMatcher;

use _ContaoManager\Symfony\Component\HttpFoundation\Request;
use _ContaoManager\Symfony\Component\HttpFoundation\RequestMatcherInterface;
/**
 * Checks the Request content is valid JSON.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class IsJsonRequestMatcher implements RequestMatcherInterface
{
    public function matches(Request $request): bool
    {
        return json_validate($request->getContent());
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\HttpFoundation\RequestMatcher;

use _ContaoManager\Symfony\Component\HttpFoundation\Request;
use _ContaoManager\Symfony\Component\HttpFoundation\RequestMatcherInterface;
/**
 * Checks the HTTP port of a Request.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class PortRequestMatcher implements RequestMatcherInterface
{
    public function __construct(private int $port)
    {
    }
    public function matches(Request $request): bool
    {
        return $request->getPort() === $this->port;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\HttpFoundation\RequestMatcher;

use _ContaoManager\Symfony\Component\HttpFoundation\Request;
use _ContaoManager\Symfony\Component\HttpFoundation\RequestMatcherInterface;
/**
 * Checks the Request URL host name matches a regular expression.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class HostRequestMatcher implements RequestMatcherInterface
{
    public function __construct(private string $regexp)
    {
    }
    public function matches(Request $request): bool
    {
        return preg_match('{' . $this->regexp . '}i', $request->getHost());
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\HttpFoundation\RequestMatcher;

use _ContaoManager\Symfony\Component\HttpFoundation\Request;
use _ContaoManager\Symfony\Component\HttpFoundation\RequestMatcherInterface;
/**
 * Checks the Request attributes matches all regular expressions.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class AttributesRequestMatcher implements RequestMatcherInterface
{
    /**
     * @param array<string, string> $regexps
     */
    public function __construct(private array $regexps)
    {
    }
    public function matches(Request $request): bool
    {
        foreach ($this->regexps as $key => $regexp) {
            $attribute = $request->attributes->get($key);
            if (!\is_string($attribute)) {
                return \false;
            }
            if (!preg_match('{' . $regexp . '}', $attribute)) {
                return \false;
            }
        }
        return \true;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\HttpFoundation\RequestMatcher;

use _ContaoManager\Symfony\Component\ExpressionLanguage\Expression;
use _ContaoManager\Symfony\Component\ExpressionLanguage\ExpressionLanguage;
use _ContaoManager\Symfony\Component\HttpFoundation\Request;
use _ContaoManager\Symfony\Component\HttpFoundation\RequestMatcherInterface;
/**
 * ExpressionRequestMatcher uses an expression to match a Request.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class ExpressionRequestMatcher implements RequestMatcherInterface
{
    public function __construct(private ExpressionLanguage $language, private Expression|string $expression)
    {
    }
    public function matches(Request $request): bool
    {
        return $this->language->evaluate($this->expression, ['request' => $request, 'method' => $request->getMethod(), 'path' => rawurldecode($request->getPathInfo()), 'host' => $request->getHost(), 'ip' => $request->getClientIp(), 'attributes' => $request->attributes->all()]);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\HttpFoundation\RequestMatcher;

use _ContaoManager\Symfony\Component\HttpFoundation\Request;
use _ContaoManager\Symfony\Component\HttpFoundation\RequestMatcherInterface;
/**
 * Checks the HTTP scheme of a Request.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class SchemeRequestMatcher implements RequestMatcherInterface
{
    /**
     * @var string[]
     */
    private array $schemes;
    /**
     * @param string[]|string $schemes A scheme or a list of schemes
     *                                 Strings can contain a comma-delimited list of schemes
     */
    public function __construct(array|string $schemes)
    {
        $this->schemes = array_reduce(array_map('strtolower', (array) $schemes), static fn(array $schemes, string $scheme) => array_merge($schemes, preg_split('/\s*,\s*/', $scheme)), []);
    }
    public function matches(Request $request): bool
    {
        if (!$this->schemes) {
            return \true;
        }
        return \in_array($request->getScheme(), $this->schemes, \true);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\HttpFoundation\RequestMatcher;

use _ContaoManager\Symfony\Component\HttpFoundation\IpUtils;
use _ContaoManager\Symfony\Component\HttpFoundation\Request;
use _ContaoManager\Symfony\Component\HttpFoundation\RequestMatcherInterface;
/**
 * Checks the client IP of a Request.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class IpsRequestMatcher implements RequestMatcherInterface
{
    private array $ips;
    /**
     * @param string[]|string $ips A specific IP address or a range specified using IP/netmask like 192.168.1.0/24
     *                             Strings can contain a comma-delimited list of IPs/ranges
     */
    public function __construct(array|string $ips)
    {
        $this->ips = array_reduce((array) $ips, static fn(array $ips, string $ip) => array_merge($ips, preg_split('/\s*,\s*/', $ip)), []);
    }
    public function matches(Request $request): bool
    {
        if (!$this->ips) {
            return \true;
        }
        return IpUtils::checkIp($request->getClientIp() ?? '', $this->ips);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\HttpFoundation;

use _ContaoManager\Symfony\Component\HttpFoundation\Exception\SessionNotFoundException;
use _ContaoManager\Symfony\Component\HttpFoundation\Session\SessionInterface;
/**
 * Request stack that controls the lifecycle of requests.
 *
 * @author Benjamin Eberlei <kontakt@beberlei.de>
 */
class RequestStack
{
    /**
     * @var Request[]
     */
    private array $requests = [];
    /**
     * Pushes a Request on the stack.
     *
     * This method should generally not be called directly as the stack
     * management should be taken care of by the application itself.
     *
     * @return void
     */
    public function push(Request $request)
    {
        $this->requests[] = $request;
    }
    /**
     * Pops the current request from the stack.
     *
     * This operation lets the current request go out of scope.
     *
     * This method should generally not be called directly as the stack
     * management should be taken care of by the application itself.
     */
    public function pop(): ?Request
    {
        if (!$this->requests) {
            return null;
        }
        return array_pop($this->requests);
    }
    public function getCurrentRequest(): ?Request
    {
        return end($this->requests) ?: null;
    }
    /**
     * Gets the main request.
     *
     * Be warned that making your code aware of the main request
     * might make it un-compatible with other features of your framework
     * like ESI support.
     */
    public function getMainRequest(): ?Request
    {
        if (!$this->requests) {
            return null;
        }
        return $this->requests[0];
    }
    /**
     * Returns the parent request of the current.
     *
     * Be warned that making your code aware of the parent request
     * might make it un-compatible with other features of your framework
     * like ESI support.
     *
     * If current Request is the main request, it returns null.
     */
    public function getParentRequest(): ?Request
    {
        $pos = \count($this->requests) - 2;
        return $this->requests[$pos] ?? null;
    }
    /**
     * Gets the current session.
     *
     * @throws SessionNotFoundException
     */
    public function getSession(): SessionInterface
    {
        if (null !== ($request = end($this->requests) ?: null) && $request->hasSession()) {
            return $request->getSession();
        }
        throw new SessionNotFoundException();
    }
    public function resetRequestFormats(): void
    {
        static $resetRequestFormats;
        $resetRequestFormats ??= \Closure::bind(static fn() => self::$formats = null, null, Request::class);
        $resetRequestFormats();
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\HttpFoundation;

/**
 * RedirectResponse represents an HTTP response doing a redirect.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class RedirectResponse extends Response
{
    protected $targetUrl;
    /**
     * Creates a redirect response so that it conforms to the rules defined for a redirect status code.
     *
     * @param string $url     The URL to redirect to. The URL should be a full URL, with schema etc.,
     *                        but practically every browser redirects on paths only as well
     * @param int    $status  The HTTP status code (302 "Found" by default)
     * @param array  $headers The headers (Location is always set to the given URL)
     *
     * @throws \InvalidArgumentException
     *
     * @see https://tools.ietf.org/html/rfc2616#section-10.3
     */
    public function __construct(string $url, int $status = 302, array $headers = [])
    {
        parent::__construct('', $status, $headers);
        $this->setTargetUrl($url);
        if (!$this->isRedirect()) {
            throw new \InvalidArgumentException(\sprintf('The HTTP status code is not a redirect ("%s" given).', $status));
        }
        if (301 == $status && !\array_key_exists('cache-control', array_change_key_case($headers, \CASE_LOWER))) {
            $this->headers->remove('cache-control');
        }
    }
    /**
     * Returns the target URL.
     */
    public function getTargetUrl(): string
    {
        return $this->targetUrl;
    }
    /**
     * Sets the redirect target of this response.
     *
     * @return $this
     *
     * @throws \InvalidArgumentException
     */
    public function setTargetUrl(string $url): static
    {
        if ('' === $url) {
            throw new \InvalidArgumentException('Cannot redirect to an empty URL.');
        }
        $this->targetUrl = $url;
        $this->setContent(\sprintf('<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8" />
        <meta http-equiv="refresh" content="0;url=\'%1$s\'" />

        <title>Redirecting to %1$s</title>
    </head>
    <body>
        Redirecting to <a href="%1$s">%1$s</a>.
    </body>
</html>', htmlspecialchars($url, \ENT_QUOTES, 'UTF-8')));
        $this->headers->set('Location', $url);
        $this->headers->set('Content-Type', 'text/html; charset=utf-8');
        return $this;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\HttpFoundation;

/**
 * Response represents an HTTP response in JSON format.
 *
 * Note that this class does not force the returned JSON content to be an
 * object. It is however recommended that you do return an object as it
 * protects yourself against XSSI and JSON-JavaScript Hijacking.
 *
 * @see https://github.com/OWASP/CheatSheetSeries/blob/master/cheatsheets/AJAX_Security_Cheat_Sheet.md#always-return-json-with-an-object-on-the-outside
 *
 * @author Igor Wiedler <igor@wiedler.ch>
 */
class JsonResponse extends Response
{
    protected $data;
    protected $callback;
    // Encode <, >, ', &, and " characters in the JSON, making it also safe to be embedded into HTML.
    // 15 === JSON_HEX_TAG | JSON_HEX_APOS | JSON_HEX_AMP | JSON_HEX_QUOT
    public const DEFAULT_ENCODING_OPTIONS = 15;
    protected $encodingOptions = self::DEFAULT_ENCODING_OPTIONS;
    /**
     * @param bool $json If the data is already a JSON string
     */
    public function __construct(mixed $data = null, int $status = 200, array $headers = [], bool $json = \false)
    {
        parent::__construct('', $status, $headers);
        if ($json && !\is_string($data) && !is_numeric($data) && !\is_callable([$data, '__toString'])) {
            throw new \TypeError(\sprintf('"%s": If $json is set to true, argument $data must be a string or object implementing __toString(), "%s" given.', __METHOD__, get_debug_type($data)));
        }
        $data ??= new \ArrayObject();
        $json ? $this->setJson($data) : $this->setData($data);
    }
    /**
     * Factory method for chainability.
     *
     * Example:
     *
     *     return JsonResponse::fromJsonString('{"key": "value"}')
     *         ->setSharedMaxAge(300);
     *
     * @param string $data    The JSON response string
     * @param int    $status  The response status code (200 "OK" by default)
     * @param array  $headers An array of response headers
     */
    public static function fromJsonString(string $data, int $status = 200, array $headers = []): static
    {
        return new static($data, $status, $headers, \true);
    }
    /**
     * Sets the JSONP callback.
     *
     * @param string|null $callback The JSONP callback or null to use none
     *
     * @return $this
     *
     * @throws \InvalidArgumentException When the callback name is not valid
     */
    public function setCallback(?string $callback = null): static
    {
        if (1 > \func_num_args()) {
            trigger_deprecation('symfony/http-foundation', '6.2', 'Calling "%s()" without any arguments is deprecated, pass null explicitly instead.', __METHOD__);
        }
        if (null !== $callback) {
            // partially taken from https://geekality.net/2011/08/03/valid-javascript-identifier/
            // partially taken from https://github.com/willdurand/JsonpCallbackValidator
            //      JsonpCallbackValidator is released under the MIT License. See https://github.com/willdurand/JsonpCallbackValidator/blob/v1.1.0/LICENSE for details.
            //      (c) William Durand <william.durand1@gmail.com>
            $pattern = '/^[$_\p{L}][$_\p{L}\p{Mn}\p{Mc}\p{Nd}\p{Pc}\x{200C}\x{200D}]*(?:\[(?:"(?:\\\\.|[^"\\\\])*"|\'(?:\\\\.|[^\'\\\\])*\'|\d+)\])*?$/u';
            $reserved = ['break', 'do', 'instanceof', 'typeof', 'case', 'else', 'new', 'var', 'catch', 'finally', 'return', 'void', 'continue', 'for', 'switch', 'while', 'debugger', 'function', 'this', 'with', 'default', 'if', 'throw', 'delete', 'in', 'try', 'class', 'enum', 'extends', 'super', 'const', 'export', 'import', 'implements', 'let', 'private', 'public', 'yield', 'interface', 'package', 'protected', 'static', 'null', 'true', 'false'];
            $parts = explode('.', $callback);
            foreach ($parts as $part) {
                if (!preg_match($pattern, $part) || \in_array($part, $reserved, \true)) {
                    throw new \InvalidArgumentException('The callback name is not valid.');
                }
            }
        }
        $this->callback = $callback;
        return $this->update();
    }
    /**
     * Sets a raw string containing a JSON document to be sent.
     *
     * @return $this
     */
    public function setJson(string $json): static
    {
        $this->data = $json;
        return $this->update();
    }
    /**
     * Sets the data to be sent as JSON.
     *
     * @return $this
     *
     * @throws \InvalidArgumentException
     */
    public function setData(mixed $data = []): static
    {
        try {
            $data = json_encode($data, $this->encodingOptions);
        } catch (\Exception $e) {
            if ('Exception' === $e::class && str_starts_with($e->getMessage(), 'Failed calling ')) {
                throw $e->getPrevious() ?: $e;
            }
            throw $e;
        }
        if (\JSON_THROW_ON_ERROR & $this->encodingOptions) {
            return $this->setJson($data);
        }
        if (\JSON_ERROR_NONE !== json_last_error()) {
            throw new \InvalidArgumentException(json_last_error_msg());
        }
        return $this->setJson($data);
    }
    /**
     * Returns options used while encoding data to JSON.
     */
    public function getEncodingOptions(): int
    {
        return $this->encodingOptions;
    }
    /**
     * Sets options used while encoding data to JSON.
     *
     * @return $this
     */
    public function setEncodingOptions(int $encodingOptions): static
    {
        $this->encodingOptions = $encodingOptions;
        return $this->setData(json_decode($this->data));
    }
    /**
     * Updates the content and headers according to the JSON data and callback.
     *
     * @return $this
     */
    protected function update(): static
    {
        if (null !== $this->callback) {
            // Not using application/javascript for compatibility reasons with older browsers.
            $this->headers->set('Content-Type', 'text/javascript');
            return $this->setContent(\sprintf('/**/%s(%s);', $this->callback, $this->data));
        }
        // Only set the header when there is none or when it equals 'text/javascript' (from a previous update with callback)
        // in order to not overwrite a custom definition.
        if (!$this->headers->has('Content-Type') || 'text/javascript' === $this->headers->get('Content-Type')) {
            $this->headers->set('Content-Type', 'application/json');
        }
        return $this->setContent($this->data);
    }
}
HttpFoundation Component
========================

The HttpFoundation component defines an object-oriented layer for the HTTP
specification.

Resources
---------

 * [Documentation](https://symfony.com/doc/current/components/http_foundation.html)
 * [Contributing](https://symfony.com/doc/current/contributing/index.html)
 * [Report issues](https://github.com/symfony/symfony/issues) and
   [send Pull Requests](https://github.com/symfony/symfony/pulls)
   in the [main Symfony repository](https://github.com/symfony/symfony)
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\HttpFoundation;

use _ContaoManager\Symfony\Component\HttpFoundation\Exception\BadRequestException;
use _ContaoManager\Symfony\Component\HttpFoundation\Exception\ConflictingHeadersException;
use _ContaoManager\Symfony\Component\HttpFoundation\Exception\JsonException;
use _ContaoManager\Symfony\Component\HttpFoundation\Exception\SessionNotFoundException;
use _ContaoManager\Symfony\Component\HttpFoundation\Exception\SuspiciousOperationException;
use _ContaoManager\Symfony\Component\HttpFoundation\Session\SessionInterface;
// Help opcache.preload discover always-needed symbols
class_exists(AcceptHeader::class);
class_exists(FileBag::class);
class_exists(HeaderBag::class);
class_exists(HeaderUtils::class);
class_exists(InputBag::class);
class_exists(ParameterBag::class);
class_exists(ServerBag::class);
/**
 * Request represents an HTTP request.
 *
 * The methods dealing with URL accept / return a raw path (% encoded):
 *   * getBasePath
 *   * getBaseUrl
 *   * getPathInfo
 *   * getRequestUri
 *   * getUri
 *   * getUriForPath
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class Request
{
    public const HEADER_FORWARDED = 0b1;
    // When using RFC 7239
    public const HEADER_X_FORWARDED_FOR = 0b10;
    public const HEADER_X_FORWARDED_HOST = 0b100;
    public const HEADER_X_FORWARDED_PROTO = 0b1000;
    public const HEADER_X_FORWARDED_PORT = 0b10000;
    public const HEADER_X_FORWARDED_PREFIX = 0b100000;
    public const HEADER_X_FORWARDED_AWS_ELB = 0b11010;
    // AWS ELB doesn't send X-Forwarded-Host
    public const HEADER_X_FORWARDED_TRAEFIK = 0b111110;
    // All "X-Forwarded-*" headers sent by Traefik reverse proxy
    public const METHOD_HEAD = 'HEAD';
    public const METHOD_GET = 'GET';
    public const METHOD_POST = 'POST';
    public const METHOD_PUT = 'PUT';
    public const METHOD_PATCH = 'PATCH';
    public const METHOD_DELETE = 'DELETE';
    public const METHOD_PURGE = 'PURGE';
    public const METHOD_OPTIONS = 'OPTIONS';
    public const METHOD_TRACE = 'TRACE';
    public const METHOD_CONNECT = 'CONNECT';
    /**
     * @var string[]
     */
    protected static $trustedProxies = [];
    /**
     * @var string[]
     */
    protected static $trustedHostPatterns = [];
    /**
     * @var string[]
     */
    protected static $trustedHosts = [];
    protected static $httpMethodParameterOverride = \false;
    /**
     * Custom parameters.
     *
     * @var ParameterBag
     */
    public $attributes;
    /**
     * Request body parameters ($_POST).
     *
     * @see getPayload() for portability between content types
     *
     * @var InputBag
     */
    public $request;
    /**
     * Query string parameters ($_GET).
     *
     * @var InputBag
     */
    public $query;
    /**
     * Server and execution environment parameters ($_SERVER).
     *
     * @var ServerBag
     */
    public $server;
    /**
     * Uploaded files ($_FILES).
     *
     * @var FileBag
     */
    public $files;
    /**
     * Cookies ($_COOKIE).
     *
     * @var InputBag
     */
    public $cookies;
    /**
     * Headers (taken from the $_SERVER).
     *
     * @var HeaderBag
     */
    public $headers;
    /**
     * @var string|resource|false|null
     */
    protected $content;
    /**
     * @var string[]|null
     */
    protected $languages;
    /**
     * @var string[]|null
     */
    protected $charsets;
    /**
     * @var string[]|null
     */
    protected $encodings;
    /**
     * @var string[]|null
     */
    protected $acceptableContentTypes;
    /**
     * @var string|null
     */
    protected $pathInfo;
    /**
     * @var string|null
     */
    protected $requestUri;
    /**
     * @var string|null
     */
    protected $baseUrl;
    /**
     * @var string|null
     */
    protected $basePath;
    /**
     * @var string|null
     */
    protected $method;
    /**
     * @var string|null
     */
    protected $format;
    /**
     * @var SessionInterface|callable():SessionInterface|null
     */
    protected $session;
    /**
     * @var string|null
     */
    protected $locale;
    /**
     * @var string
     */
    protected $defaultLocale = 'en';
    /**
     * @var array<string, string[]>|null
     */
    protected static $formats;
    protected static $requestFactory;
    private ?string $preferredFormat = null;
    private bool $isHostValid = \true;
    private bool $isForwardedValid = \true;
    private bool $isSafeContentPreferred;
    private array $trustedValuesCache = [];
    private static int $trustedHeaderSet = -1;
    private const FORWARDED_PARAMS = [self::HEADER_X_FORWARDED_FOR => 'for', self::HEADER_X_FORWARDED_HOST => 'host', self::HEADER_X_FORWARDED_PROTO => 'proto', self::HEADER_X_FORWARDED_PORT => 'host'];
    /**
     * Names for headers that can be trusted when
     * using trusted proxies.
     *
     * The FORWARDED header is the standard as of rfc7239.
     *
     * The other headers are non-standard, but widely used
     * by popular reverse proxies (like Apache mod_proxy or Amazon EC2).
     */
    private const TRUSTED_HEADERS = [self::HEADER_FORWARDED => 'FORWARDED', self::HEADER_X_FORWARDED_FOR => 'X_FORWARDED_FOR', self::HEADER_X_FORWARDED_HOST => 'X_FORWARDED_HOST', self::HEADER_X_FORWARDED_PROTO => 'X_FORWARDED_PROTO', self::HEADER_X_FORWARDED_PORT => 'X_FORWARDED_PORT', self::HEADER_X_FORWARDED_PREFIX => 'X_FORWARDED_PREFIX'];
    /** @var bool */
    private $isIisRewrite = \false;
    /**
     * @param array                $query      The GET parameters
     * @param array                $request    The POST parameters
     * @param array                $attributes The request attributes (parameters parsed from the PATH_INFO, ...)
     * @param array                $cookies    The COOKIE parameters
     * @param array                $files      The FILES parameters
     * @param array                $server     The SERVER parameters
     * @param string|resource|null $content    The raw body data
     */
    public function __construct(array $query = [], array $request = [], array $attributes = [], array $cookies = [], array $files = [], array $server = [], $content = null)
    {
        $this->initialize($query, $request, $attributes, $cookies, $files, $server, $content);
    }
    /**
     * Sets the parameters for this request.
     *
     * This method also re-initializes all properties.
     *
     * @param array                $query      The GET parameters
     * @param array                $request    The POST parameters
     * @param array                $attributes The request attributes (parameters parsed from the PATH_INFO, ...)
     * @param array                $cookies    The COOKIE parameters
     * @param array                $files      The FILES parameters
     * @param array                $server     The SERVER parameters
     * @param string|resource|null $content    The raw body data
     *
     * @return void
     */
    public function initialize(array $query = [], array $request = [], array $attributes = [], array $cookies = [], array $files = [], array $server = [], $content = null)
    {
        $this->request = new InputBag($request);
        $this->query = new InputBag($query);
        $this->attributes = new ParameterBag($attributes);
        $this->cookies = new InputBag($cookies);
        $this->files = new FileBag($files);
        $this->server = new ServerBag($server);
        $this->headers = new HeaderBag($this->server->getHeaders());
        $this->content = $content;
        $this->languages = null;
        $this->charsets = null;
        $this->encodings = null;
        $this->acceptableContentTypes = null;
        $this->pathInfo = null;
        $this->requestUri = null;
        $this->baseUrl = null;
        $this->basePath = null;
        $this->method = null;
        $this->format = null;
    }
    /**
     * Creates a new request with values from PHP's super globals.
     */
    public static function createFromGlobals(): static
    {
        $request = self::createRequestFromFactory($_GET, $_POST, [], $_COOKIE, $_FILES, $_SERVER);
        if (str_starts_with($request->headers->get('CONTENT_TYPE', ''), 'application/x-www-form-urlencoded') && \in_array(strtoupper($request->server->get('REQUEST_METHOD', 'GET')), ['PUT', 'DELETE', 'PATCH'])) {
            parse_str($request->getContent(), $data);
            $request->request = new InputBag($data);
        }
        return $request;
    }
    /**
     * Creates a Request based on a given URI and configuration.
     *
     * The information contained in the URI always take precedence
     * over the other information (server and parameters).
     *
     * @param string               $uri        The URI
     * @param string               $method     The HTTP method
     * @param array                $parameters The query (GET) or request (POST) parameters
     * @param array                $cookies    The request cookies ($_COOKIE)
     * @param array                $files      The request files ($_FILES)
     * @param array                $server     The server parameters ($_SERVER)
     * @param string|resource|null $content    The raw body data
     *
     * @throws BadRequestException When the URI is invalid
     */
    public static function create(string $uri, string $method = 'GET', array $parameters = [], array $cookies = [], array $files = [], array $server = [], $content = null): static
    {
        $server = array_replace(['SERVER_NAME' => 'localhost', 'SERVER_PORT' => 80, 'HTTP_HOST' => 'localhost', 'HTTP_USER_AGENT' => 'Symfony', 'HTTP_ACCEPT' => 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8', 'HTTP_ACCEPT_LANGUAGE' => 'en-us,en;q=0.5', 'HTTP_ACCEPT_CHARSET' => 'ISO-8859-1,utf-8;q=0.7,*;q=0.7', 'REMOTE_ADDR' => '127.0.0.1', 'SCRIPT_NAME' => '', 'SCRIPT_FILENAME' => '', 'SERVER_PROTOCOL' => 'HTTP/1.1', 'REQUEST_TIME' => time(), 'REQUEST_TIME_FLOAT' => microtime(\true)], $server);
        $server['PATH_INFO'] = '';
        $server['REQUEST_METHOD'] = strtoupper($method);
        if (($i = strcspn($uri, ':/?#')) && ':' === ($uri[$i] ?? null) && (strspn($uri, 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789+-.') !== $i || strcspn($uri, 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'))) {
            throw new BadRequestException('Invalid URI: Scheme is malformed.');
        }
        if (\false === $components = parse_url(\strlen($uri) !== strcspn($uri, '?#') ? $uri : $uri . '#')) {
            throw new BadRequestException('Invalid URI.');
        }
        $part = ($components['user'] ?? '') . ':' . ($components['pass'] ?? '');
        if (':' !== $part && \strlen($part) !== strcspn($part, '[]')) {
            throw new BadRequestException('Invalid URI: Userinfo is malformed.');
        }
        if (($part = $components['host'] ?? '') && !self::isHostValid($part)) {
            throw new BadRequestException('Invalid URI: Host is malformed.');
        }
        if (\false !== ($i = strpos($uri, '\\')) && $i < strcspn($uri, '?#')) {
            throw new BadRequestException('Invalid URI: A URI cannot contain a backslash.');
        }
        if (\strlen($uri) !== strcspn($uri, "\r\n\t")) {
            throw new BadRequestException('Invalid URI: A URI cannot contain CR/LF/TAB characters.');
        }
        if ('' !== $uri && (\ord($uri[0]) <= 32 || \ord($uri[-1]) <= 32)) {
            throw new BadRequestException('Invalid URI: A URI must not start nor end with ASCII control characters or spaces.');
        }
        if (isset($components['host'])) {
            $server['SERVER_NAME'] = $components['host'];
            $server['HTTP_HOST'] = $components['host'];
        }
        if (isset($components['scheme'])) {
            if ('https' === $components['scheme']) {
                $server['HTTPS'] = 'on';
                $server['SERVER_PORT'] = 443;
            } else {
                unset($server['HTTPS']);
                $server['SERVER_PORT'] = 80;
            }
        }
        if (isset($components['port'])) {
            $server['SERVER_PORT'] = $components['port'];
            $server['HTTP_HOST'] .= ':' . $components['port'];
        }
        if (isset($components['user'])) {
            $server['PHP_AUTH_USER'] = $components['user'];
        }
        if (isset($components['pass'])) {
            $server['PHP_AUTH_PW'] = $components['pass'];
        }
        if ('' === $path = $components['path'] ?? '') {
            $components['path'] = '/';
        } elseif (!isset($components['scheme']) && !isset($components['host']) && '/' !== $path[0]) {
            if (\false !== $pos = strpos($path, '/')) {
                $path = substr($path, 0, $pos);
            }
            if (str_contains($path, ':')) {
                throw new BadRequestException('Invalid URI: Path is malformed.');
            }
        }
        switch (strtoupper($method)) {
            case 'POST':
            case 'PUT':
            case 'DELETE':
                if (!isset($server['CONTENT_TYPE'])) {
                    $server['CONTENT_TYPE'] = 'application/x-www-form-urlencoded';
                }
            // no break
            case 'PATCH':
                $request = $parameters;
                $query = [];
                break;
            default:
                $request = [];
                $query = $parameters;
                break;
        }
        $queryString = '';
        if (isset($components['query'])) {
            parse_str(html_entity_decode($components['query']), $qs);
            if ($query) {
                $query = array_replace($qs, $query);
                $queryString = http_build_query($query, '', '&');
            } else {
                $query = $qs;
                $queryString = $components['query'];
            }
        } elseif ($query) {
            $queryString = http_build_query($query, '', '&');
        }
        $server['REQUEST_URI'] = $components['path'] . ('' !== $queryString ? '?' . $queryString : '');
        $server['QUERY_STRING'] = $queryString;
        return self::createRequestFromFactory($query, $request, [], $cookies, $files, $server, $content);
    }
    /**
     * Sets a callable able to create a Request instance.
     *
     * This is mainly useful when you need to override the Request class
     * to keep BC with an existing system. It should not be used for any
     * other purpose.
     *
     * @return void
     */
    public static function setFactory(?callable $callable)
    {
        self::$requestFactory = $callable;
    }
    /**
     * Clones a request and overrides some of its parameters.
     *
     * @param array|null $query      The GET parameters
     * @param array|null $request    The POST parameters
     * @param array|null $attributes The request attributes (parameters parsed from the PATH_INFO, ...)
     * @param array|null $cookies    The COOKIE parameters
     * @param array|null $files      The FILES parameters
     * @param array|null $server     The SERVER parameters
     */
    public function duplicate(?array $query = null, ?array $request = null, ?array $attributes = null, ?array $cookies = null, ?array $files = null, ?array $server = null): static
    {
        $dup = clone $this;
        if (null !== $query) {
            $dup->query = new InputBag($query);
        }
        if (null !== $request) {
            $dup->request = new InputBag($request);
        }
        if (null !== $attributes) {
            $dup->attributes = new ParameterBag($attributes);
        }
        if (null !== $cookies) {
            $dup->cookies = new InputBag($cookies);
        }
        if (null !== $files) {
            $dup->files = new FileBag($files);
        }
        if (null !== $server) {
            $dup->server = new ServerBag($server);
            $dup->headers = new HeaderBag($dup->server->getHeaders());
        }
        $dup->languages = null;
        $dup->charsets = null;
        $dup->encodings = null;
        $dup->acceptableContentTypes = null;
        $dup->pathInfo = null;
        $dup->requestUri = null;
        $dup->baseUrl = null;
        $dup->basePath = null;
        $dup->method = null;
        $dup->format = null;
        if (!$dup->get('_format') && $this->get('_format')) {
            $dup->attributes->set('_format', $this->get('_format'));
        }
        if (!$dup->getRequestFormat(null)) {
            $dup->setRequestFormat($this->getRequestFormat(null));
        }
        return $dup;
    }
    /**
     * Clones the current request.
     *
     * Note that the session is not cloned as duplicated requests
     * are most of the time sub-requests of the main one.
     */
    public function __clone()
    {
        $this->query = clone $this->query;
        $this->request = clone $this->request;
        $this->attributes = clone $this->attributes;
        $this->cookies = clone $this->cookies;
        $this->files = clone $this->files;
        $this->server = clone $this->server;
        $this->headers = clone $this->headers;
    }
    public function __toString(): string
    {
        $content = $this->getContent();
        $cookieHeader = '';
        $cookies = [];
        foreach ($this->cookies as $k => $v) {
            $cookies[] = \is_array($v) ? http_build_query([$k => $v], '', '; ', \PHP_QUERY_RFC3986) : "{$k}={$v}";
        }
        if ($cookies) {
            $cookieHeader = 'Cookie: ' . implode('; ', $cookies) . "\r\n";
        }
        return \sprintf('%s %s %s', $this->getMethod(), $this->getRequestUri(), $this->server->get('SERVER_PROTOCOL')) . "\r\n" . $this->headers . $cookieHeader . "\r\n" . $content;
    }
    /**
     * Overrides the PHP global variables according to this request instance.
     *
     * It overrides $_GET, $_POST, $_REQUEST, $_SERVER, $_COOKIE.
     * $_FILES is never overridden, see rfc1867
     *
     * @return void
     */
    public function overrideGlobals()
    {
        $this->server->set('QUERY_STRING', static::normalizeQueryString(http_build_query($this->query->all(), '', '&')));
        $_GET = $this->query->all();
        $_POST = $this->request->all();
        $_SERVER = $this->server->all();
        $_COOKIE = $this->cookies->all();
        foreach ($this->headers->all() as $key => $value) {
            $key = strtoupper(str_replace('-', '_', $key));
            if (\in_array($key, ['CONTENT_TYPE', 'CONTENT_LENGTH', 'CONTENT_MD5'], \true)) {
                $_SERVER[$key] = implode(', ', $value);
            } else {
                $_SERVER['HTTP_' . $key] = implode(', ', $value);
            }
        }
        $request = ['g' => $_GET, 'p' => $_POST, 'c' => $_COOKIE];
        $requestOrder = \ini_get('request_order') ?: \ini_get('variables_order');
        $requestOrder = preg_replace('#[^cgp]#', '', strtolower($requestOrder)) ?: 'gp';
        $_REQUEST = [[]];
        foreach (str_split($requestOrder) as $order) {
            $_REQUEST[] = $request[$order];
        }
        $_REQUEST = array_merge(...$_REQUEST);
    }
    /**
     * Sets a list of trusted proxies.
     *
     * You should only list the reverse proxies that you manage directly.
     *
     * @param array $proxies          A list of trusted proxies, the string 'REMOTE_ADDR' will be replaced with $_SERVER['REMOTE_ADDR']
     * @param int   $trustedHeaderSet A bit field of Request::HEADER_*, to set which headers to trust from your proxies
     *
     * @return void
     */
    public static function setTrustedProxies(array $proxies, int $trustedHeaderSet)
    {
        self::$trustedProxies = array_reduce($proxies, function ($proxies, $proxy) {
            if ('REMOTE_ADDR' !== $proxy) {
                $proxies[] = $proxy;
            } elseif (isset($_SERVER['REMOTE_ADDR'])) {
                $proxies[] = $_SERVER['REMOTE_ADDR'];
            }
            return $proxies;
        }, []);
        self::$trustedHeaderSet = $trustedHeaderSet;
    }
    /**
     * Gets the list of trusted proxies.
     *
     * @return string[]
     */
    public static function getTrustedProxies(): array
    {
        return self::$trustedProxies;
    }
    /**
     * Gets the set of trusted headers from trusted proxies.
     *
     * @return int A bit field of Request::HEADER_* that defines which headers are trusted from your proxies
     */
    public static function getTrustedHeaderSet(): int
    {
        return self::$trustedHeaderSet;
    }
    /**
     * Sets a list of trusted host patterns.
     *
     * You should only list the hosts you manage using regexs.
     *
     * @param array $hostPatterns A list of trusted host patterns
     *
     * @return void
     */
    public static function setTrustedHosts(array $hostPatterns)
    {
        self::$trustedHostPatterns = array_map(fn($hostPattern) => \sprintf('{%s}i', $hostPattern), $hostPatterns);
        // we need to reset trusted hosts on trusted host patterns change
        self::$trustedHosts = [];
    }
    /**
     * Gets the list of trusted host patterns.
     *
     * @return string[]
     */
    public static function getTrustedHosts(): array
    {
        return self::$trustedHostPatterns;
    }
    /**
     * Normalizes a query string.
     *
     * It builds a normalized query string, where keys/value pairs are alphabetized,
     * have consistent escaping and unneeded delimiters are removed.
     */
    public static function normalizeQueryString(?string $qs): string
    {
        if ('' === ($qs ?? '')) {
            return '';
        }
        $qs = HeaderUtils::parseQuery($qs);
        ksort($qs);
        return http_build_query($qs, '', '&', \PHP_QUERY_RFC3986);
    }
    /**
     * Enables support for the _method request parameter to determine the intended HTTP method.
     *
     * Be warned that enabling this feature might lead to CSRF issues in your code.
     * Check that you are using CSRF tokens when required.
     * If the HTTP method parameter override is enabled, an html-form with method "POST" can be altered
     * and used to send a "PUT" or "DELETE" request via the _method request parameter.
     * If these methods are not protected against CSRF, this presents a possible vulnerability.
     *
     * The HTTP method can only be overridden when the real HTTP method is POST.
     *
     * @return void
     */
    public static function enableHttpMethodParameterOverride()
    {
        self::$httpMethodParameterOverride = \true;
    }
    /**
     * Checks whether support for the _method request parameter is enabled.
     */
    public static function getHttpMethodParameterOverride(): bool
    {
        return self::$httpMethodParameterOverride;
    }
    /**
     * Gets a "parameter" value from any bag.
     *
     * This method is mainly useful for libraries that want to provide some flexibility. If you don't need the
     * flexibility in controllers, it is better to explicitly get request parameters from the appropriate
     * public property instead (attributes, query, request).
     *
     * Order of precedence: PATH (routing placeholders or custom attributes), GET, POST
     *
     * @internal use explicit input sources instead
     */
    public function get(string $key, mixed $default = null): mixed
    {
        if ($this !== $result = $this->attributes->get($key, $this)) {
            return $result;
        }
        if ($this->query->has($key)) {
            return $this->query->all()[$key];
        }
        if ($this->request->has($key)) {
            return $this->request->all()[$key];
        }
        return $default;
    }
    /**
     * Gets the Session.
     *
     * @throws SessionNotFoundException When session is not set properly
     */
    public function getSession(): SessionInterface
    {
        $session = $this->session;
        if (!$session instanceof SessionInterface && null !== $session) {
            $this->setSession($session = $session());
        }
        if (null === $session) {
            throw new SessionNotFoundException('Session has not been set.');
        }
        return $session;
    }
    /**
     * Whether the request contains a Session which was started in one of the
     * previous requests.
     */
    public function hasPreviousSession(): bool
    {
        // the check for $this->session avoids malicious users trying to fake a session cookie with proper name
        return $this->hasSession() && $this->cookies->has($this->getSession()->getName());
    }
    /**
     * Whether the request contains a Session object.
     *
     * This method does not give any information about the state of the session object,
     * like whether the session is started or not. It is just a way to check if this Request
     * is associated with a Session instance.
     *
     * @param bool $skipIfUninitialized When true, ignores factories injected by `setSessionFactory`
     */
    public function hasSession(bool $skipIfUninitialized = \false): bool
    {
        return null !== $this->session && (!$skipIfUninitialized || $this->session instanceof SessionInterface);
    }
    /**
     * @return void
     */
    public function setSession(SessionInterface $session)
    {
        $this->session = $session;
    }
    /**
     * @internal
     *
     * @param callable(): SessionInterface $factory
     */
    public function setSessionFactory(callable $factory): void
    {
        $this->session = $factory(...);
    }
    /**
     * Returns the client IP addresses.
     *
     * In the returned array the most trusted IP address is first, and the
     * least trusted one last. The "real" client IP address is the last one,
     * but this is also the least trusted one. Trusted proxies are stripped.
     *
     * Use this method carefully; you should use getClientIp() instead.
     *
     * @see getClientIp()
     */
    public function getClientIps(): array
    {
        $ip = $this->server->get('REMOTE_ADDR');
        if (!$this->isFromTrustedProxy()) {
            return [$ip];
        }
        return $this->getTrustedValues(self::HEADER_X_FORWARDED_FOR, $ip) ?: [$ip];
    }
    /**
     * Returns the client IP address.
     *
     * This method can read the client IP address from the "X-Forwarded-For" header
     * when trusted proxies were set via "setTrustedProxies()". The "X-Forwarded-For"
     * header value is a comma+space separated list of IP addresses, the left-most
     * being the original client, and each successive proxy that passed the request
     * adding the IP address where it received the request from.
     *
     * If your reverse proxy uses a different header name than "X-Forwarded-For",
     * ("Client-Ip" for instance), configure it via the $trustedHeaderSet
     * argument of the Request::setTrustedProxies() method instead.
     *
     * @see getClientIps()
     * @see https://wikipedia.org/wiki/X-Forwarded-For
     */
    public function getClientIp(): ?string
    {
        $ipAddresses = $this->getClientIps();
        return $ipAddresses[0];
    }
    /**
     * Returns current script name.
     */
    public function getScriptName(): string
    {
        return $this->server->get('SCRIPT_NAME', $this->server->get('ORIG_SCRIPT_NAME', ''));
    }
    /**
     * Returns the path being requested relative to the executed script.
     *
     * The path info always starts with a /.
     *
     * Suppose this request is instantiated from /mysite on localhost:
     *
     *  * http://localhost/mysite              returns '/'
     *  * http://localhost/mysite/about        returns '/about'
     *  * http://localhost/mysite/enco%20ded   returns '/enco%20ded'
     *  * http://localhost/mysite/about?var=1  returns '/about'
     *
     * @return string The raw path (i.e. not urldecoded)
     */
    public function getPathInfo(): string
    {
        return $this->pathInfo ??= $this->preparePathInfo();
    }
    /**
     * Returns the root path from which this request is executed.
     *
     * Suppose that an index.php file instantiates this request object:
     *
     *  * http://localhost/index.php         returns an empty string
     *  * http://localhost/index.php/page    returns an empty string
     *  * http://localhost/web/index.php     returns '/web'
     *  * http://localhost/we%20b/index.php  returns '/we%20b'
     *
     * @return string The raw path (i.e. not urldecoded)
     */
    public function getBasePath(): string
    {
        return $this->basePath ??= $this->prepareBasePath();
    }
    /**
     * Returns the root URL from which this request is executed.
     *
     * The base URL never ends with a /.
     *
     * This is similar to getBasePath(), except that it also includes the
     * script filename (e.g. index.php) if one exists.
     *
     * @return string The raw URL (i.e. not urldecoded)
     */
    public function getBaseUrl(): string
    {
        $trustedPrefix = '';
        // the proxy prefix must be prepended to any prefix being needed at the webserver level
        if ($this->isFromTrustedProxy() && $trustedPrefixValues = $this->getTrustedValues(self::HEADER_X_FORWARDED_PREFIX)) {
            $trustedPrefix = rtrim($trustedPrefixValues[0], '/');
        }
        return $trustedPrefix . $this->getBaseUrlReal();
    }
    /**
     * Returns the real base URL received by the webserver from which this request is executed.
     * The URL does not include trusted reverse proxy prefix.
     *
     * @return string The raw URL (i.e. not urldecoded)
     */
    private function getBaseUrlReal(): string
    {
        return $this->baseUrl ??= $this->prepareBaseUrl();
    }
    /**
     * Gets the request's scheme.
     */
    public function getScheme(): string
    {
        return $this->isSecure() ? 'https' : 'http';
    }
    /**
     * Returns the port on which the request is made.
     *
     * This method can read the client port from the "X-Forwarded-Port" header
     * when trusted proxies were set via "setTrustedProxies()".
     *
     * The "X-Forwarded-Port" header must contain the client port.
     *
     * @return int|string|null Can be a string if fetched from the server bag
     */
    public function getPort(): int|string|null
    {
        if ($this->isFromTrustedProxy() && $host = $this->getTrustedValues(self::HEADER_X_FORWARDED_PORT)) {
            $host = $host[0];
        } elseif ($this->isFromTrustedProxy() && $host = $this->getTrustedValues(self::HEADER_X_FORWARDED_HOST)) {
            $host = $host[0];
        } elseif (!$host = $this->headers->get('HOST')) {
            return $this->server->get('SERVER_PORT');
        }
        if ('[' === $host[0]) {
            $pos = strpos($host, ':', strrpos($host, ']'));
        } else {
            $pos = strrpos($host, ':');
        }
        if (\false !== $pos && $port = substr($host, $pos + 1)) {
            return (int) $port;
        }
        return 'https' === $this->getScheme() ? 443 : 80;
    }
    /**
     * Returns the user.
     */
    public function getUser(): ?string
    {
        return $this->headers->get('PHP_AUTH_USER');
    }
    /**
     * Returns the password.
     */
    public function getPassword(): ?string
    {
        return $this->headers->get('PHP_AUTH_PW');
    }
    /**
     * Gets the user info.
     *
     * @return string|null A user name if any and, optionally, scheme-specific information about how to gain authorization to access the server
     */
    public function getUserInfo(): ?string
    {
        $userinfo = $this->getUser();
        $pass = $this->getPassword();
        if ('' != $pass) {
            $userinfo .= ":{$pass}";
        }
        return $userinfo;
    }
    /**
     * Returns the HTTP host being requested.
     *
     * The port name will be appended to the host if it's non-standard.
     */
    public function getHttpHost(): string
    {
        $scheme = $this->getScheme();
        $port = $this->getPort();
        if ('http' === $scheme && 80 == $port || 'https' === $scheme && 443 == $port) {
            return $this->getHost();
        }
        return $this->getHost() . ':' . $port;
    }
    /**
     * Returns the requested URI (path and query string).
     *
     * @return string The raw URI (i.e. not URI decoded)
     */
    public function getRequestUri(): string
    {
        return $this->requestUri ??= $this->prepareRequestUri();
    }
    /**
     * Gets the scheme and HTTP host.
     *
     * If the URL was called with basic authentication, the user
     * and the password are not added to the generated string.
     */
    public function getSchemeAndHttpHost(): string
    {
        return $this->getScheme() . '://' . $this->getHttpHost();
    }
    /**
     * Generates a normalized URI (URL) for the Request.
     *
     * @see getQueryString()
     */
    public function getUri(): string
    {
        if (null !== $qs = $this->getQueryString()) {
            $qs = '?' . $qs;
        }
        return $this->getSchemeAndHttpHost() . $this->getBaseUrl() . $this->getPathInfo() . $qs;
    }
    /**
     * Generates a normalized URI for the given path.
     *
     * @param string $path A path to use instead of the current one
     */
    public function getUriForPath(string $path): string
    {
        return $this->getSchemeAndHttpHost() . $this->getBaseUrl() . $path;
    }
    /**
     * Returns the path as relative reference from the current Request path.
     *
     * Only the URIs path component (no schema, host etc.) is relevant and must be given.
     * Both paths must be absolute and not contain relative parts.
     * Relative URLs from one resource to another are useful when generating self-contained downloadable document archives.
     * Furthermore, they can be used to reduce the link size in documents.
     *
     * Example target paths, given a base path of "/a/b/c/d":
     * - "/a/b/c/d"     -> ""
     * - "/a/b/c/"      -> "./"
     * - "/a/b/"        -> "../"
     * - "/a/b/c/other" -> "other"
     * - "/a/x/y"       -> "../../x/y"
     */
    public function getRelativeUriForPath(string $path): string
    {
        // be sure that we are dealing with an absolute path
        if (!isset($path[0]) || '/' !== $path[0]) {
            return $path;
        }
        if ($path === $basePath = $this->getPathInfo()) {
            return '';
        }
        $sourceDirs = explode('/', isset($basePath[0]) && '/' === $basePath[0] ? substr($basePath, 1) : $basePath);
        $targetDirs = explode('/', substr($path, 1));
        array_pop($sourceDirs);
        $targetFile = array_pop($targetDirs);
        foreach ($sourceDirs as $i => $dir) {
            if (isset($targetDirs[$i]) && $dir === $targetDirs[$i]) {
                unset($sourceDirs[$i], $targetDirs[$i]);
            } else {
                break;
            }
        }
        $targetDirs[] = $targetFile;
        $path = str_repeat('../', \count($sourceDirs)) . implode('/', $targetDirs);
        // A reference to the same base directory or an empty subdirectory must be prefixed with "./".
        // This also applies to a segment with a colon character (e.g., "file:colon") that cannot be used
        // as the first segment of a relative-path reference, as it would be mistaken for a scheme name
        // (see https://tools.ietf.org/html/rfc3986#section-4.2).
        return !isset($path[0]) || '/' === $path[0] || \false !== ($colonPos = strpos($path, ':')) && ($colonPos < ($slashPos = strpos($path, '/')) || \false === $slashPos) ? "./{$path}" : $path;
    }
    /**
     * Generates the normalized query string for the Request.
     *
     * It builds a normalized query string, where keys/value pairs are alphabetized
     * and have consistent escaping.
     */
    public function getQueryString(): ?string
    {
        $qs = static::normalizeQueryString($this->server->get('QUERY_STRING'));
        return '' === $qs ? null : $qs;
    }
    /**
     * Checks whether the request is secure or not.
     *
     * This method can read the client protocol from the "X-Forwarded-Proto" header
     * when trusted proxies were set via "setTrustedProxies()".
     *
     * The "X-Forwarded-Proto" header must contain the protocol: "https" or "http".
     */
    public function isSecure(): bool
    {
        if ($this->isFromTrustedProxy() && $proto = $this->getTrustedValues(self::HEADER_X_FORWARDED_PROTO)) {
            return \in_array(strtolower($proto[0]), ['https', 'on', 'ssl', '1'], \true);
        }
        $https = $this->server->get('HTTPS');
        return !empty($https) && 'off' !== strtolower($https);
    }
    /**
     * Returns the host name.
     *
     * This method can read the client host name from the "X-Forwarded-Host" header
     * when trusted proxies were set via "setTrustedProxies()".
     *
     * The "X-Forwarded-Host" header must contain the client host name.
     *
     * @throws SuspiciousOperationException when the host name is invalid or not trusted
     */
    public function getHost(): string
    {
        if ($this->isFromTrustedProxy() && $host = $this->getTrustedValues(self::HEADER_X_FORWARDED_HOST)) {
            $host = $host[0];
        } elseif (!$host = $this->headers->get('HOST')) {
            if (!$host = $this->server->get('SERVER_NAME')) {
                $host = $this->server->get('SERVER_ADDR', '');
            }
        }
        // trim and remove port number from host
        // host is lowercase as per RFC 952/2181
        $host = strtolower(preg_replace('/:\d+$/', '', trim($host)));
        // the host can come from the user (HTTP_HOST and depending on the configuration, SERVER_NAME too can come from the user)
        if ($host && !self::isHostValid($host)) {
            if (!$this->isHostValid) {
                return '';
            }
            $this->isHostValid = \false;
            throw new SuspiciousOperationException(\sprintf('Invalid Host "%s".', $host));
        }
        if (\count(self::$trustedHostPatterns) > 0) {
            // to avoid host header injection attacks, you should provide a list of trusted host patterns
            if (\in_array($host, self::$trustedHosts)) {
                return $host;
            }
            foreach (self::$trustedHostPatterns as $pattern) {
                if (preg_match($pattern, $host)) {
                    self::$trustedHosts[] = $host;
                    return $host;
                }
            }
            if (!$this->isHostValid) {
                return '';
            }
            $this->isHostValid = \false;
            throw new SuspiciousOperationException(\sprintf('Untrusted Host "%s".', $host));
        }
        return $host;
    }
    /**
     * Sets the request method.
     *
     * @return void
     */
    public function setMethod(string $method)
    {
        $this->method = null;
        $this->server->set('REQUEST_METHOD', $method);
    }
    /**
     * Gets the request "intended" method.
     *
     * If the X-HTTP-Method-Override header is set, and if the method is a POST,
     * then it is used to determine the "real" intended HTTP method.
     *
     * The _method request parameter can also be used to determine the HTTP method,
     * but only if enableHttpMethodParameterOverride() has been called.
     *
     * The method is always an uppercased string.
     *
     * @see getRealMethod()
     */
    public function getMethod(): string
    {
        if (null !== $this->method) {
            return $this->method;
        }
        $this->method = strtoupper($this->server->get('REQUEST_METHOD', 'GET'));
        if ('POST' !== $this->method) {
            return $this->method;
        }
        $method = $this->headers->get('X-HTTP-METHOD-OVERRIDE');
        if (!$method && self::$httpMethodParameterOverride) {
            $method = $this->request->get('_method', $this->query->get('_method', 'POST'));
        }
        if (!\is_string($method)) {
            return $this->method;
        }
        $method = strtoupper($method);
        if (\in_array($method, ['GET', 'HEAD', 'POST', 'PUT', 'DELETE', 'CONNECT', 'OPTIONS', 'PATCH', 'PURGE', 'TRACE'], \true)) {
            return $this->method = $method;
        }
        if (!preg_match('/^[A-Z]++$/D', $method)) {
            throw new SuspiciousOperationException('Invalid HTTP method override.');
        }
        return $this->method = $method;
    }
    /**
     * Gets the "real" request method.
     *
     * @see getMethod()
     */
    public function getRealMethod(): string
    {
        return strtoupper($this->server->get('REQUEST_METHOD', 'GET'));
    }
    /**
     * Gets the mime type associated with the format.
     */
    public function getMimeType(string $format): ?string
    {
        if (null === static::$formats) {
            static::initializeFormats();
        }
        return isset(static::$formats[$format]) ? static::$formats[$format][0] : null;
    }
    /**
     * Gets the mime types associated with the format.
     *
     * @return string[]
     */
    public static function getMimeTypes(string $format): array
    {
        if (null === static::$formats) {
            static::initializeFormats();
        }
        return static::$formats[$format] ?? [];
    }
    /**
     * Gets the format associated with the mime type.
     */
    public function getFormat(?string $mimeType): ?string
    {
        $canonicalMimeType = null;
        if ($mimeType && \false !== $pos = strpos($mimeType, ';')) {
            $canonicalMimeType = trim(substr($mimeType, 0, $pos));
        }
        if (null === static::$formats) {
            static::initializeFormats();
        }
        $exactFormat = null;
        $canonicalFormat = null;
        foreach (static::$formats as $format => $mimeTypes) {
            if (\in_array($mimeType, $mimeTypes, \true)) {
                $exactFormat = $format;
            }
            if (null !== $canonicalMimeType && \in_array($canonicalMimeType, $mimeTypes, \true)) {
                $canonicalFormat = $format;
            }
        }
        if ($format = $exactFormat ?? $canonicalFormat) {
            return $format;
        }
        return null;
    }
    /**
     * Associates a format with mime types.
     *
     * @param string|string[] $mimeTypes The associated mime types (the preferred one must be the first as it will be used as the content type)
     *
     * @return void
     */
    public function setFormat(?string $format, string|array $mimeTypes)
    {
        if (null === static::$formats) {
            static::initializeFormats();
        }
        static::$formats[$format ?? ''] = (array) $mimeTypes;
    }
    /**
     * Gets the request format.
     *
     * Here is the process to determine the format:
     *
     *  * format defined by the user (with setRequestFormat())
     *  * _format request attribute
     *  * $default
     *
     * @see getPreferredFormat
     */
    public function getRequestFormat(?string $default = 'html'): ?string
    {
        $this->format ??= $this->attributes->get('_format');
        return $this->format ?? $default;
    }
    /**
     * Sets the request format.
     *
     * @return void
     */
    public function setRequestFormat(?string $format)
    {
        $this->format = $format;
    }
    /**
     * Gets the usual name of the format associated with the request's media type (provided in the Content-Type header).
     *
     * @deprecated since Symfony 6.2, use getContentTypeFormat() instead
     */
    public function getContentType(): ?string
    {
        trigger_deprecation('symfony/http-foundation', '6.2', 'The "%s()" method is deprecated, use "getContentTypeFormat()" instead.', __METHOD__);
        return $this->getContentTypeFormat();
    }
    /**
     * Gets the usual name of the format associated with the request's media type (provided in the Content-Type header).
     *
     * @see Request::$formats
     */
    public function getContentTypeFormat(): ?string
    {
        return $this->getFormat($this->headers->get('CONTENT_TYPE', ''));
    }
    /**
     * Sets the default locale.
     *
     * @return void
     */
    public function setDefaultLocale(string $locale)
    {
        $this->defaultLocale = $locale;
        if (null === $this->locale) {
            $this->setPhpDefaultLocale($locale);
        }
    }
    /**
     * Get the default locale.
     */
    public function getDefaultLocale(): string
    {
        return $this->defaultLocale;
    }
    /**
     * Sets the locale.
     *
     * @return void
     */
    public function setLocale(string $locale)
    {
        $this->setPhpDefaultLocale($this->locale = $locale);
    }
    /**
     * Get the locale.
     */
    public function getLocale(): string
    {
        return $this->locale ?? $this->defaultLocale;
    }
    /**
     * Checks if the request method is of specified type.
     *
     * @param string $method Uppercase request method (GET, POST etc)
     */
    public function isMethod(string $method): bool
    {
        return $this->getMethod() === strtoupper($method);
    }
    /**
     * Checks whether or not the method is safe.
     *
     * @see https://tools.ietf.org/html/rfc7231#section-4.2.1
     */
    public function isMethodSafe(): bool
    {
        return \in_array($this->getMethod(), ['GET', 'HEAD', 'OPTIONS', 'TRACE']);
    }
    /**
     * Checks whether or not the method is idempotent.
     */
    public function isMethodIdempotent(): bool
    {
        return \in_array($this->getMethod(), ['HEAD', 'GET', 'PUT', 'DELETE', 'TRACE', 'OPTIONS', 'PURGE']);
    }
    /**
     * Checks whether the method is cacheable or not.
     *
     * @see https://tools.ietf.org/html/rfc7231#section-4.2.3
     */
    public function isMethodCacheable(): bool
    {
        return \in_array($this->getMethod(), ['GET', 'HEAD']);
    }
    /**
     * Returns the protocol version.
     *
     * If the application is behind a proxy, the protocol version used in the
     * requests between the client and the proxy and between the proxy and the
     * server might be different. This returns the former (from the "Via" header)
     * if the proxy is trusted (see "setTrustedProxies()"), otherwise it returns
     * the latter (from the "SERVER_PROTOCOL" server parameter).
     */
    public function getProtocolVersion(): ?string
    {
        if ($this->isFromTrustedProxy()) {
            preg_match('~^(HTTP/)?([1-9]\.[0-9])\b~', $this->headers->get('Via') ?? '', $matches);
            if ($matches) {
                return 'HTTP/' . $matches[2];
            }
        }
        return $this->server->get('SERVER_PROTOCOL');
    }
    /**
     * Returns the request body content.
     *
     * @param bool $asResource If true, a resource will be returned
     *
     * @return string|resource
     *
     * @psalm-return ($asResource is true ? resource : string)
     */
    public function getContent(bool $asResource = \false)
    {
        $currentContentIsResource = \is_resource($this->content);
        if (\true === $asResource) {
            if ($currentContentIsResource) {
                rewind($this->content);
                return $this->content;
            }
            // Content passed in parameter (test)
            if (\is_string($this->content)) {
                $resource = fopen('php://temp', 'r+');
                fwrite($resource, $this->content);
                rewind($resource);
                return $resource;
            }
            $this->content = \false;
            return fopen('php://input', 'r');
        }
        if ($currentContentIsResource) {
            rewind($this->content);
            return stream_get_contents($this->content);
        }
        if (null === $this->content || \false === $this->content) {
            $this->content = file_get_contents('php://input');
        }
        return $this->content;
    }
    /**
     * Gets the decoded form or json request body.
     *
     * @throws JsonException When the body cannot be decoded to an array
     */
    public function getPayload(): InputBag
    {
        if ($this->request->count()) {
            return clone $this->request;
        }
        if ('' === $content = $this->getContent()) {
            return new InputBag([]);
        }
        try {
            $content = json_decode($content, \true, 512, \JSON_BIGINT_AS_STRING | \JSON_THROW_ON_ERROR);
        } catch (\JsonException $e) {
            throw new JsonException('Could not decode request body.', $e->getCode(), $e);
        }
        if (!\is_array($content)) {
            throw new JsonException(\sprintf('JSON content was expected to decode to an array, "%s" returned.', get_debug_type($content)));
        }
        return new InputBag($content);
    }
    /**
     * Gets the request body decoded as array, typically from a JSON payload.
     *
     * @see getPayload() for portability between content types
     *
     * @throws JsonException When the body cannot be decoded to an array
     */
    public function toArray(): array
    {
        if ('' === $content = $this->getContent()) {
            throw new JsonException('Request body is empty.');
        }
        try {
            $content = json_decode($content, \true, 512, \JSON_BIGINT_AS_STRING | \JSON_THROW_ON_ERROR);
        } catch (\JsonException $e) {
            throw new JsonException('Could not decode request body.', $e->getCode(), $e);
        }
        if (!\is_array($content)) {
            throw new JsonException(\sprintf('JSON content was expected to decode to an array, "%s" returned.', get_debug_type($content)));
        }
        return $content;
    }
    /**
     * Gets the Etags.
     */
    public function getETags(): array
    {
        return preg_split('/\s*,\s*/', $this->headers->get('If-None-Match', ''), -1, \PREG_SPLIT_NO_EMPTY);
    }
    public function isNoCache(): bool
    {
        return $this->headers->hasCacheControlDirective('no-cache') || 'no-cache' == $this->headers->get('Pragma');
    }
    /**
     * Gets the preferred format for the response by inspecting, in the following order:
     *   * the request format set using setRequestFormat;
     *   * the values of the Accept HTTP header.
     *
     * Note that if you use this method, you should send the "Vary: Accept" header
     * in the response to prevent any issues with intermediary HTTP caches.
     */
    public function getPreferredFormat(?string $default = 'html'): ?string
    {
        if ($this->preferredFormat ??= $this->getRequestFormat(null)) {
            return $this->preferredFormat;
        }
        foreach ($this->getAcceptableContentTypes() as $mimeType) {
            if ($this->preferredFormat = $this->getFormat($mimeType)) {
                return $this->preferredFormat;
            }
        }
        return $default;
    }
    /**
     * Returns the preferred language.
     *
     * @param string[] $locales An array of ordered available locales
     */
    public function getPreferredLanguage(?array $locales = null): ?string
    {
        $preferredLanguages = $this->getLanguages();
        if (empty($locales)) {
            return $preferredLanguages[0] ?? null;
        }
        if (!$preferredLanguages) {
            return $locales[0];
        }
        $extendedPreferredLanguages = [];
        foreach ($preferredLanguages as $language) {
            $extendedPreferredLanguages[] = $language;
            if (\false !== $position = strpos($language, '_')) {
                $superLanguage = substr($language, 0, $position);
                if (!\in_array($superLanguage, $preferredLanguages)) {
                    $extendedPreferredLanguages[] = $superLanguage;
                }
            }
        }
        $preferredLanguages = array_values(array_intersect($extendedPreferredLanguages, $locales));
        return $preferredLanguages[0] ?? $locales[0];
    }
    /**
     * Gets a list of languages acceptable by the client browser ordered in the user browser preferences.
     *
     * @return string[]
     */
    public function getLanguages(): array
    {
        if (null !== $this->languages) {
            return $this->languages;
        }
        $languages = AcceptHeader::fromString($this->headers->get('Accept-Language'))->all();
        $this->languages = [];
        foreach ($languages as $acceptHeaderItem) {
            $lang = $acceptHeaderItem->getValue();
            if (str_contains($lang, '-')) {
                $codes = explode('-', $lang);
                if ('i' === $codes[0]) {
                    // Language not listed in ISO 639 that are not variants
                    // of any listed language, which can be registered with the
                    // i-prefix, such as i-cherokee
                    if (\count($codes) > 1) {
                        $lang = $codes[1];
                    }
                } else {
                    for ($i = 0, $max = \count($codes); $i < $max; ++$i) {
                        if (0 === $i) {
                            $lang = strtolower($codes[0]);
                        } else {
                            $lang .= '_' . strtoupper($codes[$i]);
                        }
                    }
                }
            }
            $this->languages[] = $lang;
        }
        return $this->languages;
    }
    /**
     * Gets a list of charsets acceptable by the client browser in preferable order.
     *
     * @return string[]
     */
    public function getCharsets(): array
    {
        return $this->charsets ??= array_map('strval', array_keys(AcceptHeader::fromString($this->headers->get('Accept-Charset'))->all()));
    }
    /**
     * Gets a list of encodings acceptable by the client browser in preferable order.
     *
     * @return string[]
     */
    public function getEncodings(): array
    {
        return $this->encodings ??= array_map('strval', array_keys(AcceptHeader::fromString($this->headers->get('Accept-Encoding'))->all()));
    }
    /**
     * Gets a list of content types acceptable by the client browser in preferable order.
     *
     * @return string[]
     */
    public function getAcceptableContentTypes(): array
    {
        return $this->acceptableContentTypes ??= array_map('strval', array_keys(AcceptHeader::fromString($this->headers->get('Accept'))->all()));
    }
    /**
     * Returns true if the request is an XMLHttpRequest.
     *
     * It works if your JavaScript library sets an X-Requested-With HTTP header.
     * It is known to work with common JavaScript frameworks:
     *
     * @see https://wikipedia.org/wiki/List_of_Ajax_frameworks#JavaScript
     */
    public function isXmlHttpRequest(): bool
    {
        return 'XMLHttpRequest' == $this->headers->get('X-Requested-With');
    }
    /**
     * Checks whether the client browser prefers safe content or not according to RFC8674.
     *
     * @see https://tools.ietf.org/html/rfc8674
     */
    public function preferSafeContent(): bool
    {
        if (isset($this->isSafeContentPreferred)) {
            return $this->isSafeContentPreferred;
        }
        if (!$this->isSecure()) {
            // see https://tools.ietf.org/html/rfc8674#section-3
            return $this->isSafeContentPreferred = \false;
        }
        return $this->isSafeContentPreferred = AcceptHeader::fromString($this->headers->get('Prefer'))->has('safe');
    }
    /*
     * The following methods are derived from code of the Zend Framework (1.10dev - 2010-01-24)
     *
     * Code subject to the new BSD license (https://framework.zend.com/license).
     *
     * Copyright (c) 2005-2010 Zend Technologies USA Inc. (https://www.zend.com/)
     */
    /**
     * @return string
     */
    protected function prepareRequestUri()
    {
        $requestUri = '';
        if ($this->isIisRewrite() && '' != $this->server->get('UNENCODED_URL')) {
            // IIS7 with URL Rewrite: make sure we get the unencoded URL (double slash problem)
            $requestUri = $this->server->get('UNENCODED_URL');
            $this->server->remove('UNENCODED_URL');
        } elseif ($this->server->has('REQUEST_URI')) {
            $requestUri = $this->server->get('REQUEST_URI');
            if ('' !== $requestUri && '/' === $requestUri[0]) {
                // To only use path and query remove the fragment.
                if (\false !== $pos = strpos($requestUri, '#')) {
                    $requestUri = substr($requestUri, 0, $pos);
                }
            } else {
                // HTTP proxy reqs setup request URI with scheme and host [and port] + the URL path,
                // only use URL path.
                $uriComponents = parse_url($requestUri);
                if (isset($uriComponents['path'])) {
                    $requestUri = $uriComponents['path'];
                }
                if (isset($uriComponents['query'])) {
                    $requestUri .= '?' . $uriComponents['query'];
                }
            }
        } elseif ($this->server->has('ORIG_PATH_INFO')) {
            // IIS 5.0, PHP as CGI
            $requestUri = $this->server->get('ORIG_PATH_INFO');
            if ('' != $this->server->get('QUERY_STRING')) {
                $requestUri .= '?' . $this->server->get('QUERY_STRING');
            }
            $this->server->remove('ORIG_PATH_INFO');
        }
        // normalize the request URI to ease creating sub-requests from this request
        $this->server->set('REQUEST_URI', $requestUri);
        return $requestUri;
    }
    /**
     * Prepares the base URL.
     */
    protected function prepareBaseUrl(): string
    {
        $filename = basename($this->server->get('SCRIPT_FILENAME', ''));
        if (basename($this->server->get('SCRIPT_NAME', '')) === $filename) {
            $baseUrl = $this->server->get('SCRIPT_NAME');
        } elseif (basename($this->server->get('PHP_SELF', '')) === $filename) {
            $baseUrl = $this->server->get('PHP_SELF');
        } elseif (basename($this->server->get('ORIG_SCRIPT_NAME', '')) === $filename) {
            $baseUrl = $this->server->get('ORIG_SCRIPT_NAME');
            // 1and1 shared hosting compatibility
        } else {
            // Backtrack up the script_filename to find the portion matching
            // php_self
            $path = $this->server->get('PHP_SELF', '');
            $file = $this->server->get('SCRIPT_FILENAME', '');
            $segs = explode('/', trim($file, '/'));
            $segs = array_reverse($segs);
            $index = 0;
            $last = \count($segs);
            $baseUrl = '';
            do {
                $seg = $segs[$index];
                $baseUrl = '/' . $seg . $baseUrl;
                ++$index;
            } while ($last > $index && \false !== ($pos = strpos($path, $baseUrl)) && 0 != $pos);
        }
        // Does the baseUrl have anything in common with the request_uri?
        $requestUri = $this->getRequestUri();
        if ('' !== $requestUri && '/' !== $requestUri[0]) {
            $requestUri = '/' . $requestUri;
        }
        if ($baseUrl && null !== $prefix = $this->getUrlencodedPrefix($requestUri, $baseUrl)) {
            // full $baseUrl matches
            return $prefix;
        }
        if ($baseUrl && null !== $prefix = $this->getUrlencodedPrefix($requestUri, rtrim(\dirname($baseUrl), '/' . \DIRECTORY_SEPARATOR) . '/')) {
            // directory portion of $baseUrl matches
            return rtrim($prefix, '/' . \DIRECTORY_SEPARATOR);
        }
        $truncatedRequestUri = $requestUri;
        if (\false !== $pos = strpos($requestUri, '?')) {
            $truncatedRequestUri = substr($requestUri, 0, $pos);
        }
        $basename = basename($baseUrl ?? '');
        if (empty($basename) || !strpos(rawurldecode($truncatedRequestUri), $basename)) {
            // no match whatsoever; set it blank
            return '';
        }
        // If using mod_rewrite or ISAPI_Rewrite strip the script filename
        // out of baseUrl. $pos !== 0 makes sure it is not matching a value
        // from PATH_INFO or QUERY_STRING
        if (\strlen($requestUri) >= \strlen($baseUrl) && \false !== ($pos = strpos($requestUri, $baseUrl)) && 0 !== $pos) {
            $baseUrl = substr($requestUri, 0, $pos + \strlen($baseUrl));
        }
        return rtrim($baseUrl, '/' . \DIRECTORY_SEPARATOR);
    }
    /**
     * Prepares the base path.
     */
    protected function prepareBasePath(): string
    {
        $baseUrl = $this->getBaseUrl();
        if (empty($baseUrl)) {
            return '';
        }
        $filename = basename($this->server->get('SCRIPT_FILENAME'));
        if (basename($baseUrl) === $filename) {
            $basePath = \dirname($baseUrl);
        } else {
            $basePath = $baseUrl;
        }
        if ('\\' === \DIRECTORY_SEPARATOR) {
            $basePath = str_replace('\\', '/', $basePath);
        }
        return rtrim($basePath, '/');
    }
    /**
     * Prepares the path info.
     */
    protected function preparePathInfo(): string
    {
        if (null === $requestUri = $this->getRequestUri()) {
            return '/';
        }
        // Remove the query string from REQUEST_URI
        if (\false !== $pos = strpos($requestUri, '?')) {
            $requestUri = substr($requestUri, 0, $pos);
        }
        if ('' !== $requestUri && '/' !== $requestUri[0]) {
            $requestUri = '/' . $requestUri;
        }
        if (null === $baseUrl = $this->getBaseUrlReal()) {
            return $requestUri;
        }
        $pathInfo = substr($requestUri, \strlen($baseUrl));
        if (\false === $pathInfo || '' === $pathInfo || '/' !== $pathInfo[0]) {
            return '/' . $pathInfo;
        }
        return $pathInfo;
    }
    /**
     * Initializes HTTP request formats.
     *
     * @return void
     */
    protected static function initializeFormats()
    {
        static::$formats = ['html' => ['text/html', 'application/xhtml+xml'], 'txt' => ['text/plain'], 'js' => ['application/javascript', 'application/x-javascript', 'text/javascript'], 'css' => ['text/css'], 'json' => ['application/json', 'application/x-json'], 'jsonld' => ['application/ld+json'], 'xml' => ['text/xml', 'application/xml', 'application/x-xml'], 'rdf' => ['application/rdf+xml'], 'atom' => ['application/atom+xml'], 'rss' => ['application/rss+xml'], 'form' => ['application/x-www-form-urlencoded', 'multipart/form-data']];
    }
    private function setPhpDefaultLocale(string $locale): void
    {
        // if either the class Locale doesn't exist, or an exception is thrown when
        // setting the default locale, the intl module is not installed, and
        // the call can be ignored:
        try {
            if (class_exists(\Locale::class, \false)) {
                \Locale::setDefault($locale);
            }
        } catch (\Exception) {
        }
    }
    /**
     * Returns the prefix as encoded in the string when the string starts with
     * the given prefix, null otherwise.
     */
    private function getUrlencodedPrefix(string $string, string $prefix): ?string
    {
        if ($this->isIisRewrite()) {
            // ISS with UrlRewriteModule might report SCRIPT_NAME/PHP_SELF with wrong case
            // see https://github.com/php/php-src/issues/11981
            if (0 !== stripos(rawurldecode($string), $prefix)) {
                return null;
            }
        } elseif (!str_starts_with(rawurldecode($string), $prefix)) {
            return null;
        }
        $len = \strlen($prefix);
        if (preg_match(\sprintf('#^(%%[[:xdigit:]]{2}|.){%d}#', $len), $string, $match)) {
            return $match[0];
        }
        return null;
    }
    private static function createRequestFromFactory(array $query = [], array $request = [], array $attributes = [], array $cookies = [], array $files = [], array $server = [], $content = null): static
    {
        if (self::$requestFactory) {
            $request = (self::$requestFactory)($query, $request, $attributes, $cookies, $files, $server, $content);
            if (!$request instanceof self) {
                throw new \LogicException('The Request factory must return an instance of Symfony\Component\HttpFoundation\Request.');
            }
            return $request;
        }
        return new static($query, $request, $attributes, $cookies, $files, $server, $content);
    }
    /**
     * Indicates whether this request originated from a trusted proxy.
     *
     * This can be useful to determine whether or not to trust the
     * contents of a proxy-specific header.
     */
    public function isFromTrustedProxy(): bool
    {
        return self::$trustedProxies && IpUtils::checkIp($this->server->get('REMOTE_ADDR', ''), self::$trustedProxies);
    }
    /**
     * This method is rather heavy because it splits and merges headers, and it's called by many other methods such as
     * getPort(), isSecure(), getHost(), getClientIps(), getBaseUrl() etc. Thus, we try to cache the results for
     * best performance.
     */
    private function getTrustedValues(int $type, ?string $ip = null): array
    {
        $cacheKey = $type . "\x00" . (self::$trustedHeaderSet & $type ? $this->headers->get(self::TRUSTED_HEADERS[$type]) : '');
        $cacheKey .= "\x00" . $ip . "\x00" . $this->headers->get(self::TRUSTED_HEADERS[self::HEADER_FORWARDED]);
        if (isset($this->trustedValuesCache[$cacheKey])) {
            return $this->trustedValuesCache[$cacheKey];
        }
        $clientValues = [];
        $forwardedValues = [];
        if (self::$trustedHeaderSet & $type && $this->headers->has(self::TRUSTED_HEADERS[$type])) {
            foreach (explode(',', $this->headers->get(self::TRUSTED_HEADERS[$type])) as $v) {
                $clientValues[] = (self::HEADER_X_FORWARDED_PORT === $type ? '0.0.0.0:' : '') . trim($v);
            }
        }
        if (self::$trustedHeaderSet & self::HEADER_FORWARDED && isset(self::FORWARDED_PARAMS[$type]) && $this->headers->has(self::TRUSTED_HEADERS[self::HEADER_FORWARDED])) {
            $forwarded = $this->headers->get(self::TRUSTED_HEADERS[self::HEADER_FORWARDED]);
            $parts = HeaderUtils::split($forwarded, ',;=');
            $param = self::FORWARDED_PARAMS[$type];
            foreach ($parts as $subParts) {
                if (null === $v = HeaderUtils::combine($subParts)[$param] ?? null) {
                    continue;
                }
                if (self::HEADER_X_FORWARDED_PORT === $type) {
                    if (str_ends_with($v, ']') || \false === $v = strrchr($v, ':')) {
                        $v = $this->isSecure() ? ':443' : ':80';
                    }
                    $v = '0.0.0.0' . $v;
                }
                $forwardedValues[] = $v;
            }
        }
        if (null !== $ip) {
            $clientValues = $this->normalizeAndFilterClientIps($clientValues, $ip);
            $forwardedValues = $this->normalizeAndFilterClientIps($forwardedValues, $ip);
        }
        if ($forwardedValues === $clientValues || !$clientValues) {
            return $this->trustedValuesCache[$cacheKey] = $forwardedValues;
        }
        if (!$forwardedValues) {
            return $this->trustedValuesCache[$cacheKey] = $clientValues;
        }
        if (!$this->isForwardedValid) {
            return $this->trustedValuesCache[$cacheKey] = null !== $ip ? ['0.0.0.0', $ip] : [];
        }
        $this->isForwardedValid = \false;
        throw new ConflictingHeadersException(\sprintf('The request has both a trusted "%s" header and a trusted "%s" header, conflicting with each other. You should either configure your proxy to remove one of them, or configure your project to distrust the offending one.', self::TRUSTED_HEADERS[self::HEADER_FORWARDED], self::TRUSTED_HEADERS[$type]));
    }
    private function normalizeAndFilterClientIps(array $clientIps, string $ip): array
    {
        if (!$clientIps) {
            return [];
        }
        $clientIps[] = $ip;
        // Complete the IP chain with the IP the request actually came from
        $firstTrustedIp = null;
        foreach ($clientIps as $key => $clientIp) {
            if (strpos($clientIp, '.')) {
                // Strip :port from IPv4 addresses. This is allowed in Forwarded
                // and may occur in X-Forwarded-For.
                $i = strpos($clientIp, ':');
                if ($i) {
                    $clientIps[$key] = $clientIp = substr($clientIp, 0, $i);
                }
            } elseif (str_starts_with($clientIp, '[')) {
                // Strip brackets and :port from IPv6 addresses.
                $i = strpos($clientIp, ']', 1);
                $clientIps[$key] = $clientIp = substr($clientIp, 1, $i - 1);
            }
            if (!filter_var($clientIp, \FILTER_VALIDATE_IP)) {
                unset($clientIps[$key]);
                continue;
            }
            if (IpUtils::checkIp($clientIp, self::$trustedProxies)) {
                unset($clientIps[$key]);
                // Fallback to this when the client IP falls into the range of trusted proxies
                $firstTrustedIp ??= $clientIp;
            }
        }
        // Now the IP chain contains only untrusted proxies and the client IP
        return $clientIps ? array_reverse($clientIps) : [$firstTrustedIp];
    }
    /**
     * Is this IIS with UrlRewriteModule?
     *
     * This method consumes, caches and removed the IIS_WasUrlRewritten env var,
     * so we don't inherit it to sub-requests.
     */
    private function isIisRewrite(): bool
    {
        if (1 === $this->server->getInt('IIS_WasUrlRewritten')) {
            $this->isIisRewrite = \true;
            $this->server->remove('IIS_WasUrlRewritten');
        }
        return $this->isIisRewrite;
    }
    /**
     * See https://url.spec.whatwg.org/.
     */
    private static function isHostValid(string $host): bool
    {
        if ('[' === $host[0]) {
            return ']' === $host[-1] && filter_var(substr($host, 1, -1), \FILTER_VALIDATE_IP, \FILTER_FLAG_IPV6);
        }
        if (preg_match('/\.[0-9]++\.?$/D', $host)) {
            return null !== filter_var($host, \FILTER_VALIDATE_IP, \FILTER_FLAG_IPV4 | \FILTER_NULL_ON_FAILURE);
        }
        // use preg_replace() instead of preg_match() to prevent DoS attacks with long host names
        return '' === preg_replace('/[-a-zA-Z0-9_]++\.?/', '', $host);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\HttpFoundation;

use _ContaoManager\Symfony\Component\ExpressionLanguage\Expression;
use _ContaoManager\Symfony\Component\ExpressionLanguage\ExpressionLanguage;
use _ContaoManager\Symfony\Component\HttpFoundation\RequestMatcher\ExpressionRequestMatcher as NewExpressionRequestMatcher;
trigger_deprecation('symfony/http-foundation', '6.2', 'The "%s" class is deprecated, use "%s" instead.', ExpressionRequestMatcher::class, NewExpressionRequestMatcher::class);
/**
 * ExpressionRequestMatcher uses an expression to match a Request.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 *
 * @deprecated since Symfony 6.2, use "Symfony\Component\HttpFoundation\RequestMatcher\ExpressionRequestMatcher" instead
 */
class ExpressionRequestMatcher extends RequestMatcher
{
    private ExpressionLanguage $language;
    private Expression|string $expression;
    /**
     * @return void
     */
    public function setExpression(ExpressionLanguage $language, Expression|string $expression)
    {
        $this->language = $language;
        $this->expression = $expression;
    }
    public function matches(Request $request): bool
    {
        if (!isset($this->language)) {
            throw new \LogicException('Unable to match the request as the expression language is not available. Try running "composer require symfony/expression-language".');
        }
        return $this->language->evaluate($this->expression, ['request' => $request, 'method' => $request->getMethod(), 'path' => rawurldecode($request->getPathInfo()), 'host' => $request->getHost(), 'ip' => $request->getClientIp(), 'attributes' => $request->attributes->all()]) && parent::matches($request);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\HttpFoundation;

use _ContaoManager\Symfony\Component\HttpFoundation\Exception\BadRequestException;
use _ContaoManager\Symfony\Component\HttpFoundation\Exception\UnexpectedValueException;
/**
 * ParameterBag is a container for key/value pairs.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 *
 * @implements \IteratorAggregate<string, mixed>
 */
class ParameterBag implements \IteratorAggregate, \Countable
{
    /**
     * Parameter storage.
     */
    protected $parameters;
    public function __construct(array $parameters = [])
    {
        $this->parameters = $parameters;
    }
    /**
     * Returns the parameters.
     *
     * @param string|null $key The name of the parameter to return or null to get them all
     */
    public function all(?string $key = null): array
    {
        if (null === $key) {
            return $this->parameters;
        }
        if (!\is_array($value = $this->parameters[$key] ?? [])) {
            throw new BadRequestException(\sprintf('Unexpected value for parameter "%s": expecting "array", got "%s".', $key, get_debug_type($value)));
        }
        return $value;
    }
    /**
     * Returns the parameter keys.
     */
    public function keys(): array
    {
        return array_keys($this->parameters);
    }
    /**
     * Replaces the current parameters by a new set.
     *
     * @return void
     */
    public function replace(array $parameters = [])
    {
        $this->parameters = $parameters;
    }
    /**
     * Adds parameters.
     *
     * @return void
     */
    public function add(array $parameters = [])
    {
        $this->parameters = array_replace($this->parameters, $parameters);
    }
    public function get(string $key, mixed $default = null): mixed
    {
        return \array_key_exists($key, $this->parameters) ? $this->parameters[$key] : $default;
    }
    /**
     * @return void
     */
    public function set(string $key, mixed $value)
    {
        $this->parameters[$key] = $value;
    }
    /**
     * Returns true if the parameter is defined.
     */
    public function has(string $key): bool
    {
        return \array_key_exists($key, $this->parameters);
    }
    /**
     * Removes a parameter.
     *
     * @return void
     */
    public function remove(string $key)
    {
        unset($this->parameters[$key]);
    }
    /**
     * Returns the alphabetic characters of the parameter value.
     */
    public function getAlpha(string $key, string $default = ''): string
    {
        return preg_replace('/[^[:alpha:]]/', '', $this->getString($key, $default));
    }
    /**
     * Returns the alphabetic characters and digits of the parameter value.
     */
    public function getAlnum(string $key, string $default = ''): string
    {
        return preg_replace('/[^[:alnum:]]/', '', $this->getString($key, $default));
    }
    /**
     * Returns the digits of the parameter value.
     */
    public function getDigits(string $key, string $default = ''): string
    {
        return preg_replace('/[^[:digit:]]/', '', $this->getString($key, $default));
    }
    /**
     * Returns the parameter as string.
     */
    public function getString(string $key, string $default = ''): string
    {
        $value = $this->get($key, $default);
        if (!\is_scalar($value) && !$value instanceof \Stringable) {
            throw new UnexpectedValueException(\sprintf('Parameter value "%s" cannot be converted to "string".', $key));
        }
        return (string) $value;
    }
    /**
     * Returns the parameter value converted to integer.
     */
    public function getInt(string $key, int $default = 0): int
    {
        // In 7.0 remove the fallback to 0, in case of failure an exception will be thrown
        return $this->filter($key, $default, \FILTER_VALIDATE_INT, ['flags' => \FILTER_REQUIRE_SCALAR]) ?: 0;
    }
    /**
     * Returns the parameter value converted to boolean.
     */
    public function getBoolean(string $key, bool $default = \false): bool
    {
        return $this->filter($key, $default, \FILTER_VALIDATE_BOOL, ['flags' => \FILTER_REQUIRE_SCALAR]);
    }
    /**
     * Returns the parameter value converted to an enum.
     *
     * @template T of \BackedEnum
     *
     * @param class-string<T> $class
     * @param ?T              $default
     *
     * @return ?T
     */
    public function getEnum(string $key, string $class, ?\BackedEnum $default = null): ?\BackedEnum
    {
        $value = $this->get($key);
        if (null === $value) {
            return $default;
        }
        try {
            return $class::from($value);
        } catch (\ValueError|\TypeError $e) {
            throw new UnexpectedValueException(\sprintf('Parameter "%s" cannot be converted to enum: %s.', $key, $e->getMessage()), $e->getCode(), $e);
        }
    }
    /**
     * Filter key.
     *
     * @param int                                     $filter  FILTER_* constant
     * @param int|array{flags?: int, options?: array} $options Flags from FILTER_* constants
     *
     * @see https://php.net/filter-var
     */
    public function filter(string $key, mixed $default = null, int $filter = \FILTER_DEFAULT, mixed $options = []): mixed
    {
        $value = $this->get($key, $default);
        // Always turn $options into an array - this allows filter_var option shortcuts.
        if (!\is_array($options) && $options) {
            $options = ['flags' => $options];
        }
        // Add a convenience check for arrays.
        if (\is_array($value) && !isset($options['flags'])) {
            $options['flags'] = \FILTER_REQUIRE_ARRAY;
        }
        if (\is_object($value) && !$value instanceof \Stringable) {
            throw new UnexpectedValueException(\sprintf('Parameter value "%s" cannot be filtered.', $key));
        }
        if (\FILTER_CALLBACK & $filter && !($options['options'] ?? null) instanceof \Closure) {
            throw new \InvalidArgumentException(\sprintf('A Closure must be passed to "%s()" when FILTER_CALLBACK is used, "%s" given.', __METHOD__, get_debug_type($options['options'] ?? null)));
        }
        $options['flags'] ??= 0;
        $nullOnFailure = $options['flags'] & \FILTER_NULL_ON_FAILURE;
        $options['flags'] |= \FILTER_NULL_ON_FAILURE;
        $value = filter_var($value, $filter, $options);
        if (null !== $value || $nullOnFailure) {
            return $value;
        }
        $method = debug_backtrace(\DEBUG_BACKTRACE_IGNORE_ARGS | \DEBUG_BACKTRACE_PROVIDE_OBJECT, 2)[1];
        $method = ($method['object'] ?? null) === $this ? $method['function'] : 'filter';
        $hint = 'filter' === $method ? 'pass' : 'use method "filter()" with';
        trigger_deprecation('symfony/http-foundation', '6.3', 'Ignoring invalid values when using "%s::%s(\'%s\')" is deprecated and will throw an "%s" in 7.0; ' . $hint . ' flag "FILTER_NULL_ON_FAILURE" to keep ignoring them.', $this::class, $method, $key, UnexpectedValueException::class);
        return \false;
    }
    /**
     * Returns an iterator for parameters.
     *
     * @return \ArrayIterator<string, mixed>
     */
    public function getIterator(): \ArrayIterator
    {
        return new \ArrayIterator($this->parameters);
    }
    /**
     * Returns the number of parameters.
     */
    public function count(): int
    {
        return \count($this->parameters);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\HttpFoundation;

/**
 * Http utility functions.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class IpUtils
{
    public const PRIVATE_SUBNETS = [
        '127.0.0.0/8',
        // RFC1700 (Loopback)
        '10.0.0.0/8',
        // RFC1918
        '192.168.0.0/16',
        // RFC1918
        '172.16.0.0/12',
        // RFC1918
        '169.254.0.0/16',
        // RFC3927
        '0.0.0.0/8',
        // RFC5735
        '240.0.0.0/4',
        // RFC1112
        '::1/128',
        // Loopback
        'fc00::/7',
        // Unique Local Address
        'fe80::/10',
        // Link Local Address
        '::ffff:0:0/96',
        // IPv4 translations
        '::/128',
    ];
    private static array $checkedIps = [];
    /**
     * This class should not be instantiated.
     */
    private function __construct()
    {
    }
    /**
     * Checks if an IPv4 or IPv6 address is contained in the list of given IPs or subnets.
     *
     * @param string|array $ips List of IPs or subnets (can be a string if only a single one)
     */
    public static function checkIp(string $requestIp, string|array $ips): bool
    {
        if (!\is_array($ips)) {
            $ips = [$ips];
        }
        $method = substr_count($requestIp, ':') > 1 ? 'checkIp6' : 'checkIp4';
        foreach ($ips as $ip) {
            if (self::$method($requestIp, $ip)) {
                return \true;
            }
        }
        return \false;
    }
    /**
     * Compares two IPv4 addresses.
     * In case a subnet is given, it checks if it contains the request IP.
     *
     * @param string $ip IPv4 address or subnet in CIDR notation
     *
     * @return bool Whether the request IP matches the IP, or whether the request IP is within the CIDR subnet
     */
    public static function checkIp4(string $requestIp, string $ip): bool
    {
        $cacheKey = $requestIp . '-' . $ip . '-v4';
        if (null !== $cacheValue = self::getCacheResult($cacheKey)) {
            return $cacheValue;
        }
        if (!filter_var($requestIp, \FILTER_VALIDATE_IP, \FILTER_FLAG_IPV4)) {
            return self::setCacheResult($cacheKey, \false);
        }
        if (str_contains($ip, '/')) {
            [$address, $netmask] = explode('/', $ip, 2);
            if ('0' === $netmask) {
                return self::setCacheResult($cacheKey, \false !== filter_var($address, \FILTER_VALIDATE_IP, \FILTER_FLAG_IPV4));
            }
            if ($netmask < 0 || $netmask > 32) {
                return self::setCacheResult($cacheKey, \false);
            }
        } else {
            $address = $ip;
            $netmask = 32;
        }
        if (\false === ip2long($address)) {
            return self::setCacheResult($cacheKey, \false);
        }
        return self::setCacheResult($cacheKey, 0 === substr_compare(\sprintf('%032b', ip2long($requestIp)), \sprintf('%032b', ip2long($address)), 0, $netmask));
    }
    /**
     * Compares two IPv6 addresses.
     * In case a subnet is given, it checks if it contains the request IP.
     *
     * @author David Soria Parra <dsp at php dot net>
     *
     * @see https://github.com/dsp/v6tools
     *
     * @param string $ip IPv6 address or subnet in CIDR notation
     *
     * @throws \RuntimeException When IPV6 support is not enabled
     */
    public static function checkIp6(string $requestIp, string $ip): bool
    {
        $cacheKey = $requestIp . '-' . $ip . '-v6';
        if (null !== $cacheValue = self::getCacheResult($cacheKey)) {
            return $cacheValue;
        }
        if (!(\extension_loaded('sockets') && \defined('AF_INET6') || @inet_pton('::1'))) {
            throw new \RuntimeException('Unable to check Ipv6. Check that PHP was not compiled with option "disable-ipv6".');
        }
        // Check to see if we were given a IP4 $requestIp or $ip by mistake
        if (!filter_var($requestIp, \FILTER_VALIDATE_IP, \FILTER_FLAG_IPV6)) {
            return self::setCacheResult($cacheKey, \false);
        }
        if (str_contains($ip, '/')) {
            [$address, $netmask] = explode('/', $ip, 2);
            if (!filter_var($address, \FILTER_VALIDATE_IP, \FILTER_FLAG_IPV6)) {
                return self::setCacheResult($cacheKey, \false);
            }
            if ('0' === $netmask) {
                return (bool) unpack('n*', @inet_pton($address));
            }
            if ($netmask < 1 || $netmask > 128) {
                return self::setCacheResult($cacheKey, \false);
            }
        } else {
            if (!filter_var($ip, \FILTER_VALIDATE_IP, \FILTER_FLAG_IPV6)) {
                return self::setCacheResult($cacheKey, \false);
            }
            $address = $ip;
            $netmask = 128;
        }
        $bytesAddr = unpack('n*', @inet_pton($address));
        $bytesTest = unpack('n*', @inet_pton($requestIp));
        if (!$bytesAddr || !$bytesTest) {
            return self::setCacheResult($cacheKey, \false);
        }
        for ($i = 1, $ceil = ceil($netmask / 16); $i <= $ceil; ++$i) {
            $left = $netmask - 16 * ($i - 1);
            $left = $left <= 16 ? $left : 16;
            $mask = ~(0xffff >> $left) & 0xffff;
            if (($bytesAddr[$i] & $mask) != ($bytesTest[$i] & $mask)) {
                return self::setCacheResult($cacheKey, \false);
            }
        }
        return self::setCacheResult($cacheKey, \true);
    }
    /**
     * Anonymizes an IP/IPv6.
     *
     * Removes the last byte for v4 and the last 8 bytes for v6 IPs
     */
    public static function anonymize(string $ip): string
    {
        /*
         * If the IP contains a % symbol, then it is a local-link address with scoping according to RFC 4007
         * In that case, we only care about the part before the % symbol, as the following functions, can only work with
         * the IP address itself. As the scope can leak information (containing interface name), we do not want to
         * include it in our anonymized IP data.
         */
        if (str_contains($ip, '%')) {
            $ip = substr($ip, 0, strpos($ip, '%'));
        }
        $wrappedIPv6 = \false;
        if (str_starts_with($ip, '[') && str_ends_with($ip, ']')) {
            $wrappedIPv6 = \true;
            $ip = substr($ip, 1, -1);
        }
        $packedAddress = inet_pton($ip);
        if (4 === \strlen($packedAddress)) {
            $mask = '255.255.255.0';
        } elseif ($ip === inet_ntop($packedAddress & inet_pton('::ffff:ffff:ffff'))) {
            $mask = '::ffff:ffff:ff00';
        } elseif ($ip === inet_ntop($packedAddress & inet_pton('::ffff:ffff'))) {
            $mask = '::ffff:ff00';
        } else {
            $mask = 'ffff:ffff:ffff:ffff:0000:0000:0000:0000';
        }
        $ip = inet_ntop($packedAddress & inet_pton($mask));
        if ($wrappedIPv6) {
            $ip = '[' . $ip . ']';
        }
        return $ip;
    }
    /**
     * Checks if an IPv4 or IPv6 address is contained in the list of private IP subnets.
     */
    public static function isPrivateIp(string $requestIp): bool
    {
        return self::checkIp($requestIp, self::PRIVATE_SUBNETS);
    }
    private static function getCacheResult(string $cacheKey): ?bool
    {
        if (isset(self::$checkedIps[$cacheKey])) {
            // Move the item last in cache (LRU)
            $value = self::$checkedIps[$cacheKey];
            unset(self::$checkedIps[$cacheKey]);
            self::$checkedIps[$cacheKey] = $value;
            return self::$checkedIps[$cacheKey];
        }
        return null;
    }
    private static function setCacheResult(string $cacheKey, bool $result): bool
    {
        if (1000 < \count(self::$checkedIps)) {
            // stop memory leak if there are many keys
            self::$checkedIps = \array_slice(self::$checkedIps, 500, null, \true);
        }
        return self::$checkedIps[$cacheKey] = $result;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\HttpFoundation;

/**
 * Represents an Accept-* header item.
 *
 * @author Jean-François Simon <contact@jfsimon.fr>
 */
class AcceptHeaderItem
{
    private string $value;
    private float $quality = 1.0;
    private int $index = 0;
    private array $attributes = [];
    public function __construct(string $value, array $attributes = [])
    {
        $this->value = $value;
        foreach ($attributes as $name => $value) {
            $this->setAttribute($name, $value);
        }
    }
    /**
     * Builds an AcceptHeaderInstance instance from a string.
     */
    public static function fromString(?string $itemValue): self
    {
        $parts = HeaderUtils::split($itemValue ?? '', ';=');
        $part = array_shift($parts);
        $attributes = HeaderUtils::combine($parts);
        return new self($part[0], $attributes);
    }
    /**
     * Returns header value's string representation.
     */
    public function __toString(): string
    {
        $string = $this->value . ($this->quality < 1 ? ';q=' . $this->quality : '');
        if (\count($this->attributes) > 0) {
            $string .= '; ' . HeaderUtils::toString($this->attributes, ';');
        }
        return $string;
    }
    /**
     * Set the item value.
     *
     * @return $this
     */
    public function setValue(string $value): static
    {
        $this->value = $value;
        return $this;
    }
    /**
     * Returns the item value.
     */
    public function getValue(): string
    {
        return $this->value;
    }
    /**
     * Set the item quality.
     *
     * @return $this
     */
    public function setQuality(float $quality): static
    {
        $this->quality = $quality;
        return $this;
    }
    /**
     * Returns the item quality.
     */
    public function getQuality(): float
    {
        return $this->quality;
    }
    /**
     * Set the item index.
     *
     * @return $this
     */
    public function setIndex(int $index): static
    {
        $this->index = $index;
        return $this;
    }
    /**
     * Returns the item index.
     */
    public function getIndex(): int
    {
        return $this->index;
    }
    /**
     * Tests if an attribute exists.
     */
    public function hasAttribute(string $name): bool
    {
        return isset($this->attributes[$name]);
    }
    /**
     * Returns an attribute by its name.
     */
    public function getAttribute(string $name, mixed $default = null): mixed
    {
        return $this->attributes[$name] ?? $default;
    }
    /**
     * Returns all attributes.
     */
    public function getAttributes(): array
    {
        return $this->attributes;
    }
    /**
     * Set an attribute.
     *
     * @return $this
     */
    public function setAttribute(string $name, string $value): static
    {
        if ('q' === $name) {
            $this->quality = (float) $value;
        } else {
            $this->attributes[$name] = $value;
        }
        return $this;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\HttpFoundation;

/**
 * StreamedJsonResponse represents a streamed HTTP response for JSON.
 *
 * A StreamedJsonResponse uses a structure and generics to create an
 * efficient resource-saving JSON response.
 *
 * It is recommended to use flush() function after a specific number of items to directly stream the data.
 *
 * @see flush()
 *
 * @author Alexander Schranz <alexander@sulu.io>
 *
 * Example usage:
 *
 *     function loadArticles(): \Generator
 *         // some streamed loading
 *         yield ['title' => 'Article 1'];
 *         yield ['title' => 'Article 2'];
 *         yield ['title' => 'Article 3'];
 *         // recommended to use flush() after every specific number of items
 *     }),
 *
 *     $response = new StreamedJsonResponse(
 *         // json structure with generators in which will be streamed
 *         [
 *             '_embedded' => [
 *                 'articles' => loadArticles(), // any generator which you want to stream as list of data
 *             ],
 *         ],
 *     );
 */
class StreamedJsonResponse extends StreamedResponse
{
    private const PLACEHOLDER = '__symfony_json__';
    /**
     * @param mixed[]                        $data            JSON Data containing PHP generators which will be streamed as list of data or a Generator
     * @param int                            $status          The HTTP status code (200 "OK" by default)
     * @param array<string, string|string[]> $headers         An array of HTTP headers
     * @param int                            $encodingOptions Flags for the json_encode() function
     */
    public function __construct(private readonly iterable $data, int $status = 200, array $headers = [], private int $encodingOptions = JsonResponse::DEFAULT_ENCODING_OPTIONS)
    {
        parent::__construct($this->stream(...), $status, $headers);
        if (!$this->headers->get('Content-Type')) {
            $this->headers->set('Content-Type', 'application/json');
        }
    }
    private function stream(): void
    {
        $jsonEncodingOptions = \JSON_THROW_ON_ERROR | $this->encodingOptions;
        $keyEncodingOptions = $jsonEncodingOptions & ~\JSON_NUMERIC_CHECK;
        $this->streamData($this->data, $jsonEncodingOptions, $keyEncodingOptions);
    }
    private function streamData(mixed $data, int $jsonEncodingOptions, int $keyEncodingOptions): void
    {
        if (\is_array($data)) {
            $this->streamArray($data, $jsonEncodingOptions, $keyEncodingOptions);
            return;
        }
        if (is_iterable($data) && !$data instanceof \JsonSerializable) {
            $this->streamIterable($data, $jsonEncodingOptions, $keyEncodingOptions);
            return;
        }
        echo json_encode($data, $jsonEncodingOptions);
    }
    private function streamArray(array $data, int $jsonEncodingOptions, int $keyEncodingOptions): void
    {
        $generators = [];
        array_walk_recursive($data, function (&$item, $key) use (&$generators) {
            if (self::PLACEHOLDER === $key) {
                // if the placeholder is already in the structure it should be replaced with a new one that explode
                // works like expected for the structure
                $generators[] = $key;
            }
            // generators should be used but for better DX all kind of Traversable and objects are supported
            if (\is_object($item)) {
                $generators[] = $item;
                $item = self::PLACEHOLDER;
            } elseif (self::PLACEHOLDER === $item) {
                // if the placeholder is already in the structure it should be replaced with a new one that explode
                // works like expected for the structure
                $generators[] = $item;
            }
        });
        $jsonParts = explode('"' . self::PLACEHOLDER . '"', json_encode($data, $jsonEncodingOptions));
        foreach ($generators as $index => $generator) {
            // send first and between parts of the structure
            echo $jsonParts[$index];
            $this->streamData($generator, $jsonEncodingOptions, $keyEncodingOptions);
        }
        // send last part of the structure
        echo $jsonParts[array_key_last($jsonParts)];
    }
    private function streamIterable(iterable $iterable, int $jsonEncodingOptions, int $keyEncodingOptions): void
    {
        $isFirstItem = \true;
        $startTag = '[';
        foreach ($iterable as $key => $item) {
            if ($isFirstItem) {
                $isFirstItem = \false;
                // depending on the first elements key the generator is detected as a list or map
                // we can not check for a whole list or map because that would hurt the performance
                // of the streamed response which is the main goal of this response class
                if (0 !== $key) {
                    $startTag = '{';
                }
                echo $startTag;
            } else {
                // if not first element of the generic, a separator is required between the elements
                echo ',';
            }
            if ('{' === $startTag) {
                echo json_encode((string) $key, $keyEncodingOptions) . ':';
            }
            $this->streamData($item, $jsonEncodingOptions, $keyEncodingOptions);
        }
        if ($isFirstItem) {
            // indicates that the generator was empty
            echo '[';
        }
        echo '[' === $startTag ? ']' : '}';
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\HttpFoundation;

use _ContaoManager\Symfony\Component\Routing\RequestContext;
use _ContaoManager\Symfony\Component\Routing\RequestContextAwareInterface;
/**
 * A helper service for manipulating URLs within and outside the request scope.
 *
 * @author Valentin Udaltsov <udaltsov.valentin@gmail.com>
 */
final class UrlHelper
{
    public function __construct(private RequestStack $requestStack, private RequestContextAwareInterface|RequestContext|null $requestContext = null)
    {
    }
    public function getAbsoluteUrl(string $path): string
    {
        if (str_contains($path, '://') || str_starts_with($path, '//')) {
            return $path;
        }
        if (null === $request = $this->requestStack->getMainRequest()) {
            return $this->getAbsoluteUrlFromContext($path);
        }
        if ('#' === $path[0]) {
            $path = $request->getRequestUri() . $path;
        } elseif ('?' === $path[0]) {
            $path = $request->getPathInfo() . $path;
        }
        if (!$path || '/' !== $path[0]) {
            $prefix = $request->getPathInfo();
            $last = \strlen($prefix) - 1;
            if ($last !== $pos = strrpos($prefix, '/')) {
                $prefix = substr($prefix, 0, $pos) . '/';
            }
            return $request->getUriForPath($prefix . $path);
        }
        return $request->getSchemeAndHttpHost() . $path;
    }
    public function getRelativePath(string $path): string
    {
        if (str_contains($path, '://') || str_starts_with($path, '//')) {
            return $path;
        }
        if (null === $request = $this->requestStack->getMainRequest()) {
            return $path;
        }
        return $request->getRelativeUriForPath($path);
    }
    private function getAbsoluteUrlFromContext(string $path): string
    {
        if (null === $context = $this->requestContext) {
            return $path;
        }
        if ($context instanceof RequestContextAwareInterface) {
            $context = $context->getContext();
        }
        if ('' === $host = $context->getHost()) {
            return $path;
        }
        $scheme = $context->getScheme();
        $port = '';
        if ('http' === $scheme && 80 !== $context->getHttpPort()) {
            $port = ':' . $context->getHttpPort();
        } elseif ('https' === $scheme && 443 !== $context->getHttpsPort()) {
            $port = ':' . $context->getHttpsPort();
        }
        if ('#' === $path[0]) {
            $queryString = $context->getQueryString();
            $path = $context->getPathInfo() . ($queryString ? '?' . $queryString : '') . $path;
        } elseif ('?' === $path[0]) {
            $path = $context->getPathInfo() . $path;
        }
        if ('/' !== $path[0]) {
            $path = rtrim($context->getBaseUrl(), '/') . '/' . $path;
        }
        return $scheme . '://' . $host . $port . $path;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\HttpFoundation;

/**
 * ChainRequestMatcher verifies that all checks match against a Request instance.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class ChainRequestMatcher implements RequestMatcherInterface
{
    /**
     * @param iterable<RequestMatcherInterface> $matchers
     */
    public function __construct(private iterable $matchers)
    {
    }
    public function matches(Request $request): bool
    {
        foreach ($this->matchers as $matcher) {
            if (!$matcher->matches($request)) {
                return \false;
            }
        }
        return \true;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\HttpFoundation;

/**
 * HeaderBag is a container for HTTP headers.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 *
 * @implements \IteratorAggregate<string, list<string|null>>
 */
class HeaderBag implements \IteratorAggregate, \Countable, \Stringable
{
    protected const UPPER = '_ABCDEFGHIJKLMNOPQRSTUVWXYZ';
    protected const LOWER = '-abcdefghijklmnopqrstuvwxyz';
    /**
     * @var array<string, list<string|null>>
     */
    protected $headers = [];
    protected $cacheControl = [];
    public function __construct(array $headers = [])
    {
        foreach ($headers as $key => $values) {
            $this->set($key, $values);
        }
    }
    /**
     * Returns the headers as a string.
     */
    public function __toString(): string
    {
        if (!$headers = $this->all()) {
            return '';
        }
        ksort($headers);
        $max = max(array_map('strlen', array_keys($headers))) + 1;
        $content = '';
        foreach ($headers as $name => $values) {
            $name = ucwords($name, '-');
            foreach ($values as $value) {
                $content .= \sprintf("%-{$max}s %s\r\n", $name . ':', $value);
            }
        }
        return $content;
    }
    /**
     * Returns the headers.
     *
     * @param string|null $key The name of the headers to return or null to get them all
     *
     * @return ($key is null ? array<string, list<string|null>> : list<string|null>)
     */
    public function all(?string $key = null): array
    {
        if (null !== $key) {
            return $this->headers[strtr($key, self::UPPER, self::LOWER)] ?? [];
        }
        return $this->headers;
    }
    /**
     * Returns the parameter keys.
     *
     * @return string[]
     */
    public function keys(): array
    {
        return array_keys($this->all());
    }
    /**
     * Replaces the current HTTP headers by a new set.
     *
     * @return void
     */
    public function replace(array $headers = [])
    {
        $this->headers = [];
        $this->add($headers);
    }
    /**
     * Adds new headers the current HTTP headers set.
     *
     * @return void
     */
    public function add(array $headers)
    {
        foreach ($headers as $key => $values) {
            $this->set($key, $values);
        }
    }
    /**
     * Returns the first header by name or the default one.
     */
    public function get(string $key, ?string $default = null): ?string
    {
        $headers = $this->all($key);
        if (!$headers) {
            return $default;
        }
        if (null === $headers[0]) {
            return null;
        }
        return (string) $headers[0];
    }
    /**
     * Sets a header by name.
     *
     * @param string|string[]|null $values  The value or an array of values
     * @param bool                 $replace Whether to replace the actual value or not (true by default)
     *
     * @return void
     */
    public function set(string $key, string|array|null $values, bool $replace = \true)
    {
        $key = strtr($key, self::UPPER, self::LOWER);
        if (\is_array($values)) {
            $values = array_values($values);
            if (\true === $replace || !isset($this->headers[$key])) {
                $this->headers[$key] = $values;
            } else {
                $this->headers[$key] = array_merge($this->headers[$key], $values);
            }
        } else if (\true === $replace || !isset($this->headers[$key])) {
            $this->headers[$key] = [$values];
        } else {
            $this->headers[$key][] = $values;
        }
        if ('cache-control' === $key) {
            $this->cacheControl = $this->parseCacheControl(implode(', ', $this->headers[$key]));
        }
    }
    /**
     * Returns true if the HTTP header is defined.
     */
    public function has(string $key): bool
    {
        return \array_key_exists(strtr($key, self::UPPER, self::LOWER), $this->all());
    }
    /**
     * Returns true if the given HTTP header contains the given value.
     */
    public function contains(string $key, string $value): bool
    {
        return \in_array($value, $this->all($key));
    }
    /**
     * Removes a header.
     *
     * @return void
     */
    public function remove(string $key)
    {
        $key = strtr($key, self::UPPER, self::LOWER);
        unset($this->headers[$key]);
        if ('cache-control' === $key) {
            $this->cacheControl = [];
        }
    }
    /**
     * Returns the HTTP header value converted to a date.
     *
     * @return \DateTimeImmutable|null
     *
     * @throws \RuntimeException When the HTTP header is not parseable
     */
    public function getDate(string $key, ?\DateTimeInterface $default = null): ?\DateTimeInterface
    {
        if (null === $value = $this->get($key)) {
            return null !== $default ? \DateTimeImmutable::createFromInterface($default) : null;
        }
        if (\false === $date = \DateTimeImmutable::createFromFormat(\DATE_RFC2822, $value)) {
            throw new \RuntimeException(\sprintf('The "%s" HTTP header is not parseable (%s).', $key, $value));
        }
        return $date;
    }
    /**
     * Adds a custom Cache-Control directive.
     *
     * @return void
     */
    public function addCacheControlDirective(string $key, bool|string $value = \true)
    {
        $this->cacheControl[$key] = $value;
        $this->set('Cache-Control', $this->getCacheControlHeader());
    }
    /**
     * Returns true if the Cache-Control directive is defined.
     */
    public function hasCacheControlDirective(string $key): bool
    {
        return \array_key_exists($key, $this->cacheControl);
    }
    /**
     * Returns a Cache-Control directive value by name.
     */
    public function getCacheControlDirective(string $key): bool|string|null
    {
        return $this->cacheControl[$key] ?? null;
    }
    /**
     * Removes a Cache-Control directive.
     *
     * @return void
     */
    public function removeCacheControlDirective(string $key)
    {
        unset($this->cacheControl[$key]);
        $this->set('Cache-Control', $this->getCacheControlHeader());
    }
    /**
     * Returns an iterator for headers.
     *
     * @return \ArrayIterator<string, list<string|null>>
     */
    public function getIterator(): \ArrayIterator
    {
        return new \ArrayIterator($this->headers);
    }
    /**
     * Returns the number of headers.
     */
    public function count(): int
    {
        return \count($this->headers);
    }
    /**
     * @return string
     */
    protected function getCacheControlHeader()
    {
        ksort($this->cacheControl);
        return HeaderUtils::toString($this->cacheControl, ',');
    }
    /**
     * Parses a Cache-Control HTTP header.
     */
    protected function parseCacheControl(string $header): array
    {
        $parts = HeaderUtils::split($header, ',=');
        return HeaderUtils::combine($parts);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\HttpFoundation;

use _ContaoManager\Symfony\Component\HttpFoundation\File\UploadedFile;
/**
 * FileBag is a container for uploaded files.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 * @author Bulat Shakirzyanov <mallluhuct@gmail.com>
 */
class FileBag extends ParameterBag
{
    private const FILE_KEYS = ['error', 'name', 'size', 'tmp_name', 'type'];
    /**
     * @param array|UploadedFile[] $parameters An array of HTTP files
     */
    public function __construct(array $parameters = [])
    {
        $this->replace($parameters);
    }
    /**
     * @return void
     */
    public function replace(array $files = [])
    {
        $this->parameters = [];
        $this->add($files);
    }
    /**
     * @return void
     */
    public function set(string $key, mixed $value)
    {
        if (!\is_array($value) && !$value instanceof UploadedFile) {
            throw new \InvalidArgumentException('An uploaded file must be an array or an instance of UploadedFile.');
        }
        parent::set($key, $this->convertFileInformation($value));
    }
    /**
     * @return void
     */
    public function add(array $files = [])
    {
        foreach ($files as $key => $file) {
            $this->set($key, $file);
        }
    }
    /**
     * Converts uploaded files to UploadedFile instances.
     *
     * @return UploadedFile[]|UploadedFile|null
     */
    protected function convertFileInformation(array|UploadedFile $file): array|UploadedFile|null
    {
        if ($file instanceof UploadedFile) {
            return $file;
        }
        $file = $this->fixPhpFilesArray($file);
        $keys = array_keys($file);
        sort($keys);
        if (self::FILE_KEYS == $keys) {
            if (\UPLOAD_ERR_NO_FILE == $file['error']) {
                $file = null;
            } else {
                $file = new UploadedFile($file['tmp_name'], $file['name'], $file['type'], $file['error'], \false);
            }
        } else {
            $file = array_map(fn($v) => $v instanceof UploadedFile || \is_array($v) ? $this->convertFileInformation($v) : $v, $file);
            if (array_keys($keys) === $keys) {
                $file = array_filter($file);
            }
        }
        return $file;
    }
    /**
     * Fixes a malformed PHP $_FILES array.
     *
     * PHP has a bug that the format of the $_FILES array differs, depending on
     * whether the uploaded file fields had normal field names or array-like
     * field names ("normal" vs. "parent[child]").
     *
     * This method fixes the array to look like the "normal" $_FILES array.
     *
     * It's safe to pass an already converted array, in which case this method
     * just returns the original array unmodified.
     */
    protected function fixPhpFilesArray(array $data): array
    {
        // Remove extra key added by PHP 8.1.
        unset($data['full_path']);
        $keys = array_keys($data);
        sort($keys);
        if (self::FILE_KEYS != $keys || !isset($data['name']) || !\is_array($data['name'])) {
            return $data;
        }
        $files = $data;
        foreach (self::FILE_KEYS as $k) {
            unset($files[$k]);
        }
        foreach ($data['name'] as $key => $name) {
            $files[$key] = $this->fixPhpFilesArray(['error' => $data['error'][$key], 'name' => $name, 'type' => $data['type'][$key], 'tmp_name' => $data['tmp_name'][$key], 'size' => $data['size'][$key]]);
        }
        return $files;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\HttpFoundation\Exception;

/**
 * The HTTP request contains headers with conflicting information.
 *
 * @author Magnus Nordlander <magnus@fervo.se>
 */
class ConflictingHeadersException extends UnexpectedValueException implements RequestExceptionInterface
{
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\HttpFoundation\Exception;

class UnexpectedValueException extends \UnexpectedValueException
{
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\HttpFoundation\Exception;

/**
 * Interface for Request exceptions.
 *
 * Exceptions implementing this interface should trigger an HTTP 400 response in the application code.
 */
interface RequestExceptionInterface
{
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\HttpFoundation\Exception;

/**
 * Raised when a user sends a malformed request.
 */
class BadRequestException extends UnexpectedValueException implements RequestExceptionInterface
{
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\HttpFoundation\Exception;

/**
 * Raised when a user has performed an operation that should be considered
 * suspicious from a security perspective.
 */
class SuspiciousOperationException extends UnexpectedValueException implements RequestExceptionInterface
{
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\HttpFoundation\Exception;

/**
 * Thrown by Request::toArray() when the content cannot be JSON-decoded.
 *
 * @author Tobias Nyholm <tobias.nyholm@gmail.com>
 */
final class JsonException extends UnexpectedValueException implements RequestExceptionInterface
{
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\HttpFoundation\Exception;

/**
 * Raised when a session does not exist. This happens in the following cases:
 * - the session is not enabled
 * - attempt to read a session outside a request context (ie. cli script).
 *
 * @author Jérémy Derussé <jeremy@derusse.com>
 */
class SessionNotFoundException extends \LogicException implements RequestExceptionInterface
{
    public function __construct(string $message = 'There is currently no session available.', int $code = 0, ?\Throwable $previous = null)
    {
        parent::__construct($message, $code, $previous);
    }
}
{
    "name": "symfony\/http-foundation",
    "type": "library",
    "description": "Defines an object-oriented layer for the HTTP specification",
    "keywords": [],
    "homepage": "https:\/\/symfony.com",
    "license": "MIT",
    "authors": [
        {
            "name": "Fabien Potencier",
            "email": "fabien@symfony.com"
        },
        {
            "name": "Symfony Community",
            "homepage": "https:\/\/symfony.com\/contributors"
        }
    ],
    "require": {
        "php": ">=8.1",
        "symfony\/deprecation-contracts": "^2.5|^3",
        "symfony\/polyfill-mbstring": "~1.1",
        "symfony\/polyfill-php83": "^1.27"
    },
    "require-dev": {
        "doctrine\/dbal": "^2.13.1|^3|^4",
        "predis\/predis": "^1.1|^2.0",
        "symfony\/cache": "^6.4.12|^7.1.5",
        "symfony\/dependency-injection": "^5.4|^6.0|^7.0",
        "symfony\/http-kernel": "^5.4.12|^6.0.12|^6.1.4|^7.0",
        "symfony\/mime": "^5.4|^6.0|^7.0",
        "symfony\/expression-language": "^5.4|^6.0|^7.0",
        "symfony\/rate-limiter": "^5.4|^6.0|^7.0"
    },
    "conflict": {
        "symfony\/cache": "<6.4.12|>=7.0,<7.1.5"
    },
    "autoload": {
        "psr-4": {
            "_ContaoManager\\Symfony\\Component\\HttpFoundation\\": ""
        },
        "exclude-from-classmap": [
            "\/Tests\/"
        ]
    },
    "minimum-stability": "dev"
}<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\HttpFoundation;

/**
 * @author Fabien Potencier <fabien@symfony.com>
 */
class UriSigner
{
    private string $secret;
    private string $parameter;
    /**
     * @param string $parameter Query string parameter to use
     */
    public function __construct(
        #[\SensitiveParameter]
        string $secret,
        string $parameter = '_hash'
    )
    {
        if (!$secret) {
            throw new \InvalidArgumentException('A non-empty secret is required.');
        }
        $this->secret = $secret;
        $this->parameter = $parameter;
    }
    /**
     * Signs a URI.
     *
     * The given URI is signed by adding the query string parameter
     * which value depends on the URI and the secret.
     */
    public function sign(string $uri): string
    {
        $url = parse_url($uri);
        $params = [];
        if (isset($url['query'])) {
            parse_str($url['query'], $params);
        }
        $uri = $this->buildUrl($url, $params);
        $params[$this->parameter] = $this->computeHash($uri);
        return $this->buildUrl($url, $params);
    }
    /**
     * Checks that a URI contains the correct hash.
     */
    public function check(string $uri): bool
    {
        $url = parse_url($uri);
        $params = [];
        if (isset($url['query'])) {
            parse_str($url['query'], $params);
        }
        if (empty($params[$this->parameter])) {
            return \false;
        }
        $hash = $params[$this->parameter];
        unset($params[$this->parameter]);
        return hash_equals($this->computeHash($this->buildUrl($url, $params)), $hash);
    }
    public function checkRequest(Request $request): bool
    {
        $qs = ($qs = $request->server->get('QUERY_STRING')) ? '?' . $qs : '';
        // we cannot use $request->getUri() here as we want to work with the original URI (no query string reordering)
        return $this->check($request->getSchemeAndHttpHost() . $request->getBaseUrl() . $request->getPathInfo() . $qs);
    }
    private function computeHash(string $uri): string
    {
        return base64_encode(hash_hmac('sha256', $uri, $this->secret, \true));
    }
    private function buildUrl(array $url, array $params = []): string
    {
        ksort($params, \SORT_STRING);
        $url['query'] = http_build_query($params, '', '&');
        $scheme = isset($url['scheme']) ? $url['scheme'] . '://' : '';
        $host = $url['host'] ?? '';
        $port = isset($url['port']) ? ':' . $url['port'] : '';
        $user = $url['user'] ?? '';
        $pass = isset($url['pass']) ? ':' . $url['pass'] : '';
        $pass = $user || $pass ? "{$pass}@" : '';
        $path = $url['path'] ?? '';
        $query = $url['query'] ? '?' . $url['query'] : '';
        $fragment = isset($url['fragment']) ? '#' . $url['fragment'] : '';
        return $scheme . $user . $pass . $host . $port . $path . $query . $fragment;
    }
}
if (!class_exists(\_ContaoManager\Symfony\Component\HttpKernel\UriSigner::class, \false)) {
    class_alias(UriSigner::class, \_ContaoManager\Symfony\Component\HttpKernel\UriSigner::class);
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\HttpFoundation\Session\Attribute;

use _ContaoManager\Symfony\Component\HttpFoundation\Session\SessionBagInterface;
/**
 * Attributes store.
 *
 * @author Drak <drak@zikula.org>
 */
interface AttributeBagInterface extends SessionBagInterface
{
    /**
     * Checks if an attribute is defined.
     */
    public function has(string $name): bool;
    /**
     * Returns an attribute.
     */
    public function get(string $name, mixed $default = null): mixed;
    /**
     * Sets an attribute.
     *
     * @return void
     */
    public function set(string $name, mixed $value);
    /**
     * Returns attributes.
     *
     * @return array<string, mixed>
     */
    public function all(): array;
    /**
     * @return void
     */
    public function replace(array $attributes);
    /**
     * Removes an attribute.
     *
     * @return mixed The removed value or null when it does not exist
     */
    public function remove(string $name): mixed;
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\HttpFoundation\Session\Attribute;

/**
 * This class relates to session attribute storage.
 *
 * @implements \IteratorAggregate<string, mixed>
 */
class AttributeBag implements AttributeBagInterface, \IteratorAggregate, \Countable
{
    private string $name = 'attributes';
    private string $storageKey;
    protected $attributes = [];
    /**
     * @param string $storageKey The key used to store attributes in the session
     */
    public function __construct(string $storageKey = '_sf2_attributes')
    {
        $this->storageKey = $storageKey;
    }
    public function getName(): string
    {
        return $this->name;
    }
    /**
     * @return void
     */
    public function setName(string $name)
    {
        $this->name = $name;
    }
    /**
     * @return void
     */
    public function initialize(array &$attributes)
    {
        $this->attributes =& $attributes;
    }
    public function getStorageKey(): string
    {
        return $this->storageKey;
    }
    public function has(string $name): bool
    {
        return \array_key_exists($name, $this->attributes);
    }
    public function get(string $name, mixed $default = null): mixed
    {
        return \array_key_exists($name, $this->attributes) ? $this->attributes[$name] : $default;
    }
    /**
     * @return void
     */
    public function set(string $name, mixed $value)
    {
        $this->attributes[$name] = $value;
    }
    public function all(): array
    {
        return $this->attributes;
    }
    /**
     * @return void
     */
    public function replace(array $attributes)
    {
        $this->attributes = [];
        foreach ($attributes as $key => $value) {
            $this->set($key, $value);
        }
    }
    public function remove(string $name): mixed
    {
        $retval = null;
        if (\array_key_exists($name, $this->attributes)) {
            $retval = $this->attributes[$name];
            unset($this->attributes[$name]);
        }
        return $retval;
    }
    public function clear(): mixed
    {
        $return = $this->attributes;
        $this->attributes = [];
        return $return;
    }
    /**
     * Returns an iterator for attributes.
     *
     * @return \ArrayIterator<string, mixed>
     */
    public function getIterator(): \ArrayIterator
    {
        return new \ArrayIterator($this->attributes);
    }
    /**
     * Returns the number of attributes.
     */
    public function count(): int
    {
        return \count($this->attributes);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\HttpFoundation\Session;

use _ContaoManager\Symfony\Component\HttpFoundation\Session\Flash\FlashBagInterface;
/**
 * Interface for session with a flashbag.
 */
interface FlashBagAwareSessionInterface extends SessionInterface
{
    public function getFlashBag(): FlashBagInterface;
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\HttpFoundation\Session;

/**
 * @author Kevin Bond <kevinbond@gmail.com>
 */
interface SessionFactoryInterface
{
    public function createSession(): SessionInterface;
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\HttpFoundation\Session;

use _ContaoManager\Symfony\Component\HttpFoundation\Session\Attribute\AttributeBag;
use _ContaoManager\Symfony\Component\HttpFoundation\Session\Attribute\AttributeBagInterface;
use _ContaoManager\Symfony\Component\HttpFoundation\Session\Flash\FlashBag;
use _ContaoManager\Symfony\Component\HttpFoundation\Session\Flash\FlashBagInterface;
use _ContaoManager\Symfony\Component\HttpFoundation\Session\Storage\MetadataBag;
use _ContaoManager\Symfony\Component\HttpFoundation\Session\Storage\NativeSessionStorage;
use _ContaoManager\Symfony\Component\HttpFoundation\Session\Storage\SessionStorageInterface;
// Help opcache.preload discover always-needed symbols
class_exists(AttributeBag::class);
class_exists(FlashBag::class);
class_exists(SessionBagProxy::class);
/**
 * @author Fabien Potencier <fabien@symfony.com>
 * @author Drak <drak@zikula.org>
 *
 * @implements \IteratorAggregate<string, mixed>
 */
class Session implements FlashBagAwareSessionInterface, \IteratorAggregate, \Countable
{
    protected $storage;
    private string $flashName;
    private string $attributeName;
    private array $data = [];
    private int $usageIndex = 0;
    private ?\Closure $usageReporter;
    public function __construct(?SessionStorageInterface $storage = null, ?AttributeBagInterface $attributes = null, ?FlashBagInterface $flashes = null, ?callable $usageReporter = null)
    {
        $this->storage = $storage ?? new NativeSessionStorage();
        $this->usageReporter = null === $usageReporter ? null : $usageReporter(...);
        $attributes ??= new AttributeBag();
        $this->attributeName = $attributes->getName();
        $this->registerBag($attributes);
        $flashes ??= new FlashBag();
        $this->flashName = $flashes->getName();
        $this->registerBag($flashes);
    }
    public function start(): bool
    {
        return $this->storage->start();
    }
    public function has(string $name): bool
    {
        return $this->getAttributeBag()->has($name);
    }
    public function get(string $name, mixed $default = null): mixed
    {
        return $this->getAttributeBag()->get($name, $default);
    }
    /**
     * @return void
     */
    public function set(string $name, mixed $value)
    {
        $this->getAttributeBag()->set($name, $value);
    }
    public function all(): array
    {
        return $this->getAttributeBag()->all();
    }
    /**
     * @return void
     */
    public function replace(array $attributes)
    {
        $this->getAttributeBag()->replace($attributes);
    }
    public function remove(string $name): mixed
    {
        return $this->getAttributeBag()->remove($name);
    }
    /**
     * @return void
     */
    public function clear()
    {
        $this->getAttributeBag()->clear();
    }
    public function isStarted(): bool
    {
        return $this->storage->isStarted();
    }
    /**
     * Returns an iterator for attributes.
     *
     * @return \ArrayIterator<string, mixed>
     */
    public function getIterator(): \ArrayIterator
    {
        return new \ArrayIterator($this->getAttributeBag()->all());
    }
    /**
     * Returns the number of attributes.
     */
    public function count(): int
    {
        return \count($this->getAttributeBag()->all());
    }
    public function &getUsageIndex(): int
    {
        return $this->usageIndex;
    }
    /**
     * @internal
     */
    public function isEmpty(): bool
    {
        if ($this->isStarted()) {
            ++$this->usageIndex;
            if ($this->usageReporter && 0 <= $this->usageIndex) {
                ($this->usageReporter)();
            }
        }
        foreach ($this->data as &$data) {
            if (!empty($data)) {
                return \false;
            }
        }
        return \true;
    }
    public function invalidate(?int $lifetime = null): bool
    {
        $this->storage->clear();
        return $this->migrate(\true, $lifetime);
    }
    public function migrate(bool $destroy = \false, ?int $lifetime = null): bool
    {
        return $this->storage->regenerate($destroy, $lifetime);
    }
    /**
     * @return void
     */
    public function save()
    {
        $this->storage->save();
    }
    public function getId(): string
    {
        return $this->storage->getId();
    }
    /**
     * @return void
     */
    public function setId(string $id)
    {
        if ($this->storage->getId() !== $id) {
            $this->storage->setId($id);
        }
    }
    public function getName(): string
    {
        return $this->storage->getName();
    }
    /**
     * @return void
     */
    public function setName(string $name)
    {
        $this->storage->setName($name);
    }
    public function getMetadataBag(): MetadataBag
    {
        ++$this->usageIndex;
        if ($this->usageReporter && 0 <= $this->usageIndex) {
            ($this->usageReporter)();
        }
        return $this->storage->getMetadataBag();
    }
    /**
     * @return void
     */
    public function registerBag(SessionBagInterface $bag)
    {
        $this->storage->registerBag(new SessionBagProxy($bag, $this->data, $this->usageIndex, $this->usageReporter));
    }
    public function getBag(string $name): SessionBagInterface
    {
        $bag = $this->storage->getBag($name);
        return method_exists($bag, 'getBag') ? $bag->getBag() : $bag;
    }
    /**
     * Gets the flashbag interface.
     */
    public function getFlashBag(): FlashBagInterface
    {
        return $this->getBag($this->flashName);
    }
    /**
     * Gets the attributebag interface.
     *
     * Note that this method was added to help with IDE autocompletion.
     */
    private function getAttributeBag(): AttributeBagInterface
    {
        return $this->getBag($this->attributeName);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\HttpFoundation\Session;

/**
 * Session utility functions.
 *
 * @author Nicolas Grekas <p@tchwork.com>
 * @author Rémon van de Kamp <rpkamp@gmail.com>
 *
 * @internal
 */
final class SessionUtils
{
    /**
     * Finds the session header amongst the headers that are to be sent, removes it, and returns
     * it so the caller can process it further.
     */
    public static function popSessionCookie(
        string $sessionName,
        #[\SensitiveParameter]
        string $sessionId
    ): ?string
    {
        $sessionCookie = null;
        $sessionCookiePrefix = \sprintf(' %s=', urlencode($sessionName));
        $sessionCookieWithId = \sprintf('%s%s;', $sessionCookiePrefix, urlencode($sessionId));
        $otherCookies = [];
        foreach (headers_list() as $h) {
            if (0 !== stripos($h, 'Set-Cookie:')) {
                continue;
            }
            if (11 === strpos($h, $sessionCookiePrefix, 11)) {
                $sessionCookie = $h;
                if (11 !== strpos($h, $sessionCookieWithId, 11)) {
                    $otherCookies[] = $h;
                }
            } else {
                $otherCookies[] = $h;
            }
        }
        if (null === $sessionCookie) {
            return null;
        }
        header_remove('Set-Cookie');
        foreach ($otherCookies as $h) {
            header($h, \false);
        }
        return $sessionCookie;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\HttpFoundation\Session\Storage\Handler;

/**
 * Can be used in unit testing or in a situations where persisted sessions are not desired.
 *
 * @author Drak <drak@zikula.org>
 */
class NullSessionHandler extends AbstractSessionHandler
{
    public function close(): bool
    {
        return \true;
    }
    public function validateId(
        #[\SensitiveParameter]
        string $sessionId
    ): bool
    {
        return \true;
    }
    protected function doRead(
        #[\SensitiveParameter]
        string $sessionId
    ): string
    {
        return '';
    }
    public function updateTimestamp(
        #[\SensitiveParameter]
        string $sessionId,
        string $data
    ): bool
    {
        return \true;
    }
    protected function doWrite(
        #[\SensitiveParameter]
        string $sessionId,
        string $data
    ): bool
    {
        return \true;
    }
    protected function doDestroy(
        #[\SensitiveParameter]
        string $sessionId
    ): bool
    {
        return \true;
    }
    public function gc(int $maxlifetime): int|false
    {
        return 0;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\HttpFoundation\Session\Storage\Handler;

use _ContaoManager\Symfony\Component\HttpFoundation\Session\SessionUtils;
/**
 * This abstract session handler provides a generic implementation
 * of the PHP 7.0 SessionUpdateTimestampHandlerInterface,
 * enabling strict and lazy session handling.
 *
 * @author Nicolas Grekas <p@tchwork.com>
 */
abstract class AbstractSessionHandler implements \SessionHandlerInterface, \SessionUpdateTimestampHandlerInterface
{
    private string $sessionName;
    private string $prefetchId;
    private string $prefetchData;
    private ?string $newSessionId = null;
    private string $igbinaryEmptyData;
    public function open(string $savePath, string $sessionName): bool
    {
        $this->sessionName = $sessionName;
        if (!headers_sent() && !\ini_get('session.cache_limiter') && '0' !== \ini_get('session.cache_limiter')) {
            header(\sprintf('Cache-Control: max-age=%d, private, must-revalidate', 60 * (int) \ini_get('session.cache_expire')));
        }
        return \true;
    }
    abstract protected function doRead(
        #[\SensitiveParameter]
        string $sessionId
    ): string;
    abstract protected function doWrite(
        #[\SensitiveParameter]
        string $sessionId,
        string $data
    ): bool;
    abstract protected function doDestroy(
        #[\SensitiveParameter]
        string $sessionId
    ): bool;
    public function validateId(
        #[\SensitiveParameter]
        string $sessionId
    ): bool
    {
        $this->prefetchData = $this->read($sessionId);
        $this->prefetchId = $sessionId;
        return '' !== $this->prefetchData;
    }
    public function read(
        #[\SensitiveParameter]
        string $sessionId
    ): string
    {
        if (isset($this->prefetchId)) {
            $prefetchId = $this->prefetchId;
            $prefetchData = $this->prefetchData;
            unset($this->prefetchId, $this->prefetchData);
            if ($prefetchId === $sessionId || '' === $prefetchData) {
                $this->newSessionId = '' === $prefetchData ? $sessionId : null;
                return $prefetchData;
            }
        }
        $data = $this->doRead($sessionId);
        $this->newSessionId = '' === $data ? $sessionId : null;
        return $data;
    }
    public function updateTimestamp(
        #[\SensitiveParameter]
        string $sessionId,
        string $data
    ): bool
    {
        $this->igbinaryEmptyData ??= \function_exists('igbinary_serialize') ? igbinary_serialize([]) : '';
        if ('' === $data || $this->igbinaryEmptyData === $data) {
            return $this->destroy($sessionId);
        }
        return \true;
    }
    public function write(
        #[\SensitiveParameter]
        string $sessionId,
        string $data
    ): bool
    {
        // see https://github.com/igbinary/igbinary/issues/146
        $this->igbinaryEmptyData ??= \function_exists('igbinary_serialize') ? igbinary_serialize([]) : '';
        if ('' === $data || $this->igbinaryEmptyData === $data) {
            return $this->destroy($sessionId);
        }
        $this->newSessionId = null;
        return $this->doWrite($sessionId, $data);
    }
    public function destroy(
        #[\SensitiveParameter]
        string $sessionId
    ): bool
    {
        if (!headers_sent() && filter_var(\ini_get('session.use_cookies'), \FILTER_VALIDATE_BOOL)) {
            if (!isset($this->sessionName)) {
                throw new \LogicException(\sprintf('Session name cannot be empty, did you forget to call "parent::open()" in "%s"?.', static::class));
            }
            $cookie = SessionUtils::popSessionCookie($this->sessionName, $sessionId);
            /*
             * We send an invalidation Set-Cookie header (zero lifetime)
             * when either the session was started or a cookie with
             * the session name was sent by the client (in which case
             * we know it's invalid as a valid session cookie would've
             * started the session).
             */
            if (null === $cookie || isset($_COOKIE[$this->sessionName])) {
                $params = session_get_cookie_params();
                unset($params['lifetime']);
                setcookie($this->sessionName, '', $params);
            }
        }
        return $this->newSessionId === $sessionId || $this->doDestroy($sessionId);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\HttpFoundation\Session\Storage\Handler;

use _ContaoManager\Doctrine\DBAL\Configuration;
use _ContaoManager\Doctrine\DBAL\DriverManager;
use _ContaoManager\Doctrine\DBAL\Schema\DefaultSchemaManagerFactory;
use _ContaoManager\Doctrine\DBAL\Tools\DsnParser;
use Relay\Relay;
use _ContaoManager\Symfony\Component\Cache\Adapter\AbstractAdapter;
/**
 * @author Nicolas Grekas <p@tchwork.com>
 */
class SessionHandlerFactory
{
    public static function createHandler(object|string $connection, array $options = []): AbstractSessionHandler
    {
        if ($query = \is_string($connection) ? parse_url($connection) : \false) {
            parse_str($query['query'] ?? '', $query);
            if (($options['ttl'] ?? null) instanceof \Closure) {
                $query['ttl'] = $options['ttl'];
            }
        }
        $options = ($query ?: []) + $options;
        switch (\true) {
            case $connection instanceof \Redis:
            case $connection instanceof Relay:
            case $connection instanceof \RedisArray:
            case $connection instanceof \RedisCluster:
            case $connection instanceof \_ContaoManager\Predis\ClientInterface:
                return new RedisSessionHandler($connection);
            case $connection instanceof \Memcached:
                return new MemcachedSessionHandler($connection);
            case $connection instanceof \PDO:
                return new PdoSessionHandler($connection);
            case !\is_string($connection):
                throw new \InvalidArgumentException(\sprintf('Unsupported Connection: "%s".', get_debug_type($connection)));
            case str_starts_with($connection, 'file://'):
                $savePath = substr($connection, 7);
                return new StrictSessionHandler(new NativeFileSessionHandler('' === $savePath ? null : $savePath));
            case str_starts_with($connection, 'redis:'):
            case str_starts_with($connection, 'rediss:'):
            case str_starts_with($connection, 'memcached:'):
                if (!class_exists(AbstractAdapter::class)) {
                    throw new \InvalidArgumentException('Unsupported Redis or Memcached DSN. Try running "composer require symfony/cache".');
                }
                $handlerClass = str_starts_with($connection, 'memcached:') ? MemcachedSessionHandler::class : RedisSessionHandler::class;
                $connection = preg_replace('/([?&])prefix=[^&]*+&?/', '\1', $connection);
                $connection = AbstractAdapter::createConnection($connection, ['lazy' => \true]);
                return new $handlerClass($connection, array_intersect_key($options, ['prefix' => 1, 'ttl' => 1]));
            case str_starts_with($connection, 'pdo_oci://'):
                if (!class_exists(DriverManager::class)) {
                    throw new \InvalidArgumentException('Unsupported PDO OCI DSN. Try running "composer require doctrine/dbal".');
                }
                $connection[3] = '-';
                $params = class_exists(DsnParser::class) ? (new DsnParser())->parse($connection) : ['url' => $connection];
                $config = new Configuration();
                if (class_exists(DefaultSchemaManagerFactory::class)) {
                    $config->setSchemaManagerFactory(new DefaultSchemaManagerFactory());
                }
                $connection = DriverManager::getConnection($params, $config);
                // The condition should be removed once support for DBAL <3.3 is dropped
                $connection = method_exists($connection, 'getNativeConnection') ? $connection->getNativeConnection() : $connection->getWrappedConnection();
            // no break;
            case str_starts_with($connection, 'mssql://'):
            case str_starts_with($connection, 'mysql://'):
            case str_starts_with($connection, 'mysql2://'):
            case str_starts_with($connection, 'pgsql://'):
            case str_starts_with($connection, 'postgres://'):
            case str_starts_with($connection, 'postgresql://'):
            case str_starts_with($connection, 'sqlsrv://'):
            case str_starts_with($connection, 'sqlite://'):
            case str_starts_with($connection, 'sqlite3://'):
                return new PdoSessionHandler($connection, $options);
        }
        throw new \InvalidArgumentException(\sprintf('Unsupported Connection: "%s".', $connection));
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\HttpFoundation\Session\Storage\Handler;

use _ContaoManager\Doctrine\DBAL\Schema\Schema;
use _ContaoManager\Doctrine\DBAL\Types\Types;
/**
 * Session handler using a PDO connection to read and write data.
 *
 * It works with MySQL, PostgreSQL, Oracle, SQL Server and SQLite and implements
 * different locking strategies to handle concurrent access to the same session.
 * Locking is necessary to prevent loss of data due to race conditions and to keep
 * the session data consistent between read() and write(). With locking, requests
 * for the same session will wait until the other one finished writing. For this
 * reason it's best practice to close a session as early as possible to improve
 * concurrency. PHPs internal files session handler also implements locking.
 *
 * Attention: Since SQLite does not support row level locks but locks the whole database,
 * it means only one session can be accessed at a time. Even different sessions would wait
 * for another to finish. So saving session in SQLite should only be considered for
 * development or prototypes.
 *
 * Session data is a binary string that can contain non-printable characters like the null byte.
 * For this reason it must be saved in a binary column in the database like BLOB in MySQL.
 * Saving it in a character column could corrupt the data. You can use createTable()
 * to initialize a correctly defined table.
 *
 * @see https://php.net/sessionhandlerinterface
 *
 * @author Fabien Potencier <fabien@symfony.com>
 * @author Michael Williams <michael.williams@funsational.com>
 * @author Tobias Schultze <http://tobion.de>
 */
class PdoSessionHandler extends AbstractSessionHandler
{
    /**
     * No locking is done. This means sessions are prone to loss of data due to
     * race conditions of concurrent requests to the same session. The last session
     * write will win in this case. It might be useful when you implement your own
     * logic to deal with this like an optimistic approach.
     */
    public const LOCK_NONE = 0;
    /**
     * Creates an application-level lock on a session. The disadvantage is that the
     * lock is not enforced by the database and thus other, unaware parts of the
     * application could still concurrently modify the session. The advantage is it
     * does not require a transaction.
     * This mode is not available for SQLite and not yet implemented for oci and sqlsrv.
     */
    public const LOCK_ADVISORY = 1;
    /**
     * Issues a real row lock. Since it uses a transaction between opening and
     * closing a session, you have to be careful when you use same database connection
     * that you also use for your application logic. This mode is the default because
     * it's the only reliable solution across DBMSs.
     */
    public const LOCK_TRANSACTIONAL = 2;
    private \PDO $pdo;
    /**
     * DSN string or null for session.save_path or false when lazy connection disabled.
     */
    private string|false|null $dsn = \false;
    private string $driver;
    private string $table = 'sessions';
    private string $idCol = 'sess_id';
    private string $dataCol = 'sess_data';
    private string $lifetimeCol = 'sess_lifetime';
    private string $timeCol = 'sess_time';
    /**
     * Time to live in seconds.
     */
    private int|\Closure|null $ttl;
    /**
     * Username when lazy-connect.
     */
    private ?string $username = null;
    /**
     * Password when lazy-connect.
     */
    private ?string $password = null;
    /**
     * Connection options when lazy-connect.
     */
    private array $connectionOptions = [];
    /**
     * The strategy for locking, see constants.
     */
    private int $lockMode = self::LOCK_TRANSACTIONAL;
    /**
     * It's an array to support multiple reads before closing which is manual, non-standard usage.
     *
     * @var \PDOStatement[] An array of statements to release advisory locks
     */
    private array $unlockStatements = [];
    /**
     * True when the current session exists but expired according to session.gc_maxlifetime.
     */
    private bool $sessionExpired = \false;
    /**
     * Whether a transaction is active.
     */
    private bool $inTransaction = \false;
    /**
     * Whether gc() has been called.
     */
    private bool $gcCalled = \false;
    /**
     * You can either pass an existing database connection as PDO instance or
     * pass a DSN string that will be used to lazy-connect to the database
     * when the session is actually used. Furthermore it's possible to pass null
     * which will then use the session.save_path ini setting as PDO DSN parameter.
     *
     * List of available options:
     *  * db_table: The name of the table [default: sessions]
     *  * db_id_col: The column where to store the session id [default: sess_id]
     *  * db_data_col: The column where to store the session data [default: sess_data]
     *  * db_lifetime_col: The column where to store the lifetime [default: sess_lifetime]
     *  * db_time_col: The column where to store the timestamp [default: sess_time]
     *  * db_username: The username when lazy-connect [default: '']
     *  * db_password: The password when lazy-connect [default: '']
     *  * db_connection_options: An array of driver-specific connection options [default: []]
     *  * lock_mode: The strategy for locking, see constants [default: LOCK_TRANSACTIONAL]
     *  * ttl: The time to live in seconds.
     *
     * @param \PDO|string|null $pdoOrDsn A \PDO instance or DSN string or URL string or null
     *
     * @throws \InvalidArgumentException When PDO error mode is not PDO::ERRMODE_EXCEPTION
     */
    public function __construct(
        #[\SensitiveParameter]
        \PDO|string|null $pdoOrDsn = null,
        #[\SensitiveParameter]
        array $options = []
    )
    {
        if ($pdoOrDsn instanceof \PDO) {
            if (\PDO::ERRMODE_EXCEPTION !== $pdoOrDsn->getAttribute(\PDO::ATTR_ERRMODE)) {
                throw new \InvalidArgumentException(\sprintf('"%s" requires PDO error mode attribute be set to throw Exceptions (i.e. $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION)).', __CLASS__));
            }
            $this->pdo = $pdoOrDsn;
            $this->driver = $this->pdo->getAttribute(\PDO::ATTR_DRIVER_NAME);
        } elseif (\is_string($pdoOrDsn) && str_contains($pdoOrDsn, '://')) {
            $this->dsn = $this->buildDsnFromUrl($pdoOrDsn);
        } else {
            $this->dsn = $pdoOrDsn;
        }
        $this->table = $options['db_table'] ?? $this->table;
        $this->idCol = $options['db_id_col'] ?? $this->idCol;
        $this->dataCol = $options['db_data_col'] ?? $this->dataCol;
        $this->lifetimeCol = $options['db_lifetime_col'] ?? $this->lifetimeCol;
        $this->timeCol = $options['db_time_col'] ?? $this->timeCol;
        $this->username = $options['db_username'] ?? $this->username;
        $this->password = $options['db_password'] ?? $this->password;
        $this->connectionOptions = $options['db_connection_options'] ?? $this->connectionOptions;
        $this->lockMode = $options['lock_mode'] ?? $this->lockMode;
        $this->ttl = $options['ttl'] ?? null;
    }
    /**
     * Adds the Table to the Schema if it doesn't exist.
     */
    public function configureSchema(Schema $schema, ?\Closure $isSameDatabase = null): void
    {
        if ($schema->hasTable($this->table) || $isSameDatabase && !$isSameDatabase($this->getConnection()->exec(...))) {
            return;
        }
        $table = $schema->createTable($this->table);
        switch ($this->driver) {
            case 'mysql':
                $table->addColumn($this->idCol, Types::BINARY)->setLength(128)->setNotnull(\true);
                $table->addColumn($this->dataCol, Types::BLOB)->setNotnull(\true);
                $table->addColumn($this->lifetimeCol, Types::INTEGER)->setUnsigned(\true)->setNotnull(\true);
                $table->addColumn($this->timeCol, Types::INTEGER)->setUnsigned(\true)->setNotnull(\true);
                $table->addOption('engine', 'InnoDB');
                break;
            case 'sqlite':
                $table->addColumn($this->idCol, Types::TEXT)->setNotnull(\true);
                $table->addColumn($this->dataCol, Types::BLOB)->setNotnull(\true);
                $table->addColumn($this->lifetimeCol, Types::INTEGER)->setNotnull(\true);
                $table->addColumn($this->timeCol, Types::INTEGER)->setNotnull(\true);
                break;
            case 'pgsql':
                $table->addColumn($this->idCol, Types::STRING)->setLength(128)->setNotnull(\true);
                $table->addColumn($this->dataCol, Types::BINARY)->setNotnull(\true);
                $table->addColumn($this->lifetimeCol, Types::INTEGER)->setNotnull(\true);
                $table->addColumn($this->timeCol, Types::INTEGER)->setNotnull(\true);
                break;
            case 'oci':
                $table->addColumn($this->idCol, Types::STRING)->setLength(128)->setNotnull(\true);
                $table->addColumn($this->dataCol, Types::BLOB)->setNotnull(\true);
                $table->addColumn($this->lifetimeCol, Types::INTEGER)->setNotnull(\true);
                $table->addColumn($this->timeCol, Types::INTEGER)->setNotnull(\true);
                break;
            case 'sqlsrv':
                $table->addColumn($this->idCol, Types::STRING)->setLength(128)->setNotnull(\true);
                $table->addColumn($this->dataCol, Types::BLOB)->setNotnull(\true);
                $table->addColumn($this->lifetimeCol, Types::INTEGER)->setUnsigned(\true)->setNotnull(\true);
                $table->addColumn($this->timeCol, Types::INTEGER)->setUnsigned(\true)->setNotnull(\true);
                break;
            default:
                throw new \DomainException(\sprintf('Creating the session table is currently not implemented for PDO driver "%s".', $this->driver));
        }
        $table->setPrimaryKey([$this->idCol]);
        $table->addIndex([$this->lifetimeCol], $this->lifetimeCol . '_idx');
    }
    /**
     * Creates the table to store sessions which can be called once for setup.
     *
     * Session ID is saved in a column of maximum length 128 because that is enough even
     * for a 512 bit configured session.hash_function like Whirlpool. Session data is
     * saved in a BLOB. One could also use a shorter inlined varbinary column
     * if one was sure the data fits into it.
     *
     * @return void
     *
     * @throws \PDOException    When the table already exists
     * @throws \DomainException When an unsupported PDO driver is used
     */
    public function createTable()
    {
        // connect if we are not yet
        $this->getConnection();
        $sql = match ($this->driver) {
            // We use varbinary for the ID column because it prevents unwanted conversions:
            // - character set conversions between server and client
            // - trailing space removal
            // - case-insensitivity
            // - language processing like é == e
            'mysql' => "CREATE TABLE {$this->table} ({$this->idCol} VARBINARY(128) NOT NULL PRIMARY KEY, {$this->dataCol} BLOB NOT NULL, {$this->lifetimeCol} INTEGER UNSIGNED NOT NULL, {$this->timeCol} INTEGER UNSIGNED NOT NULL) ENGINE = InnoDB",
            'sqlite' => "CREATE TABLE {$this->table} ({$this->idCol} TEXT NOT NULL PRIMARY KEY, {$this->dataCol} BLOB NOT NULL, {$this->lifetimeCol} INTEGER NOT NULL, {$this->timeCol} INTEGER NOT NULL)",
            'pgsql' => "CREATE TABLE {$this->table} ({$this->idCol} VARCHAR(128) NOT NULL PRIMARY KEY, {$this->dataCol} BYTEA NOT NULL, {$this->lifetimeCol} INTEGER NOT NULL, {$this->timeCol} INTEGER NOT NULL)",
            'oci' => "CREATE TABLE {$this->table} ({$this->idCol} VARCHAR2(128) NOT NULL PRIMARY KEY, {$this->dataCol} BLOB NOT NULL, {$this->lifetimeCol} INTEGER NOT NULL, {$this->timeCol} INTEGER NOT NULL)",
            'sqlsrv' => "CREATE TABLE {$this->table} ({$this->idCol} VARCHAR(128) NOT NULL PRIMARY KEY, {$this->dataCol} VARBINARY(MAX) NOT NULL, {$this->lifetimeCol} INTEGER NOT NULL, {$this->timeCol} INTEGER NOT NULL)",
            default => throw new \DomainException(\sprintf('Creating the session table is currently not implemented for PDO driver "%s".', $this->driver)),
        };
        try {
            $this->pdo->exec($sql);
            $this->pdo->exec("CREATE INDEX {$this->lifetimeCol}_idx ON {$this->table} ({$this->lifetimeCol})");
        } catch (\PDOException $e) {
            $this->rollback();
            throw $e;
        }
    }
    /**
     * Returns true when the current session exists but expired according to session.gc_maxlifetime.
     *
     * Can be used to distinguish between a new session and one that expired due to inactivity.
     */
    public function isSessionExpired(): bool
    {
        return $this->sessionExpired;
    }
    public function open(string $savePath, string $sessionName): bool
    {
        $this->sessionExpired = \false;
        if (!isset($this->pdo)) {
            $this->connect($this->dsn ?: $savePath);
        }
        return parent::open($savePath, $sessionName);
    }
    public function read(
        #[\SensitiveParameter]
        string $sessionId
    ): string
    {
        try {
            return parent::read($sessionId);
        } catch (\PDOException $e) {
            $this->rollback();
            throw $e;
        }
    }
    public function gc(int $maxlifetime): int|false
    {
        // We delay gc() to close() so that it is executed outside the transactional and blocking read-write process.
        // This way, pruning expired sessions does not block them from being started while the current session is used.
        $this->gcCalled = \true;
        return 0;
    }
    protected function doDestroy(
        #[\SensitiveParameter]
        string $sessionId
    ): bool
    {
        // delete the record associated with this id
        $sql = "DELETE FROM {$this->table} WHERE {$this->idCol} = :id";
        try {
            $stmt = $this->pdo->prepare($sql);
            $stmt->bindParam(':id', $sessionId, \PDO::PARAM_STR);
            $stmt->execute();
        } catch (\PDOException $e) {
            $this->rollback();
            throw $e;
        }
        return \true;
    }
    protected function doWrite(
        #[\SensitiveParameter]
        string $sessionId,
        string $data
    ): bool
    {
        $maxlifetime = (int) (($this->ttl instanceof \Closure ? ($this->ttl)() : $this->ttl) ?? \ini_get('session.gc_maxlifetime'));
        try {
            // We use a single MERGE SQL query when supported by the database.
            $mergeStmt = $this->getMergeStatement($sessionId, $data, $maxlifetime);
            if (null !== $mergeStmt) {
                $mergeStmt->execute();
                return \true;
            }
            $updateStmt = $this->getUpdateStatement($sessionId, $data, $maxlifetime);
            $updateStmt->execute();
            // When MERGE is not supported, like in Postgres < 9.5, we have to use this approach that can result in
            // duplicate key errors when the same session is written simultaneously (given the LOCK_NONE behavior).
            // We can just catch such an error and re-execute the update. This is similar to a serializable
            // transaction with retry logic on serialization failures but without the overhead and without possible
            // false positives due to longer gap locking.
            if (!$updateStmt->rowCount()) {
                try {
                    $insertStmt = $this->getInsertStatement($sessionId, $data, $maxlifetime);
                    $insertStmt->execute();
                } catch (\PDOException $e) {
                    // Handle integrity violation SQLSTATE 23000 (or a subclass like 23505 in Postgres) for duplicate keys
                    if (str_starts_with($e->getCode(), '23')) {
                        $updateStmt->execute();
                    } else {
                        throw $e;
                    }
                }
            }
        } catch (\PDOException $e) {
            $this->rollback();
            throw $e;
        }
        return \true;
    }
    public function updateTimestamp(
        #[\SensitiveParameter]
        string $sessionId,
        string $data
    ): bool
    {
        $expiry = time() + (int) (($this->ttl instanceof \Closure ? ($this->ttl)() : $this->ttl) ?? \ini_get('session.gc_maxlifetime'));
        try {
            $updateStmt = $this->pdo->prepare("UPDATE {$this->table} SET {$this->lifetimeCol} = :expiry, {$this->timeCol} = :time WHERE {$this->idCol} = :id");
            $updateStmt->bindValue(':id', $sessionId, \PDO::PARAM_STR);
            $updateStmt->bindValue(':expiry', $expiry, \PDO::PARAM_INT);
            $updateStmt->bindValue(':time', time(), \PDO::PARAM_INT);
            $updateStmt->execute();
        } catch (\PDOException $e) {
            $this->rollback();
            throw $e;
        }
        return \true;
    }
    public function close(): bool
    {
        $this->commit();
        while ($unlockStmt = array_shift($this->unlockStatements)) {
            $unlockStmt->execute();
        }
        if ($this->gcCalled) {
            $this->gcCalled = \false;
            // delete the session records that have expired
            $sql = "DELETE FROM {$this->table} WHERE {$this->lifetimeCol} < :time";
            $stmt = $this->pdo->prepare($sql);
            $stmt->bindValue(':time', time(), \PDO::PARAM_INT);
            $stmt->execute();
        }
        if (\false !== $this->dsn) {
            unset($this->pdo, $this->driver);
            // only close lazy-connection
        }
        return \true;
    }
    /**
     * Lazy-connects to the database.
     */
    private function connect(
        #[\SensitiveParameter]
        string $dsn
    ): void
    {
        $this->pdo = new \PDO($dsn, $this->username, $this->password, $this->connectionOptions);
        $this->pdo->setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION);
        $this->driver = $this->pdo->getAttribute(\PDO::ATTR_DRIVER_NAME);
    }
    /**
     * Builds a PDO DSN from a URL-like connection string.
     *
     * @todo implement missing support for oci DSN (which look totally different from other PDO ones)
     */
    private function buildDsnFromUrl(
        #[\SensitiveParameter]
        string $dsnOrUrl
    ): string
    {
        // (pdo_)?sqlite3?:///... => (pdo_)?sqlite3?://localhost/... or else the URL will be invalid
        $url = preg_replace('#^((?:pdo_)?sqlite3?):///#', '$1://localhost/', $dsnOrUrl);
        $params = parse_url($url);
        if (\false === $params) {
            return $dsnOrUrl;
            // If the URL is not valid, let's assume it might be a DSN already.
        }
        $params = array_map('rawurldecode', $params);
        // Override the default username and password. Values passed through options will still win over these in the constructor.
        if (isset($params['user'])) {
            $this->username = $params['user'];
        }
        if (isset($params['pass'])) {
            $this->password = $params['pass'];
        }
        if (!isset($params['scheme'])) {
            throw new \InvalidArgumentException('URLs without scheme are not supported to configure the PdoSessionHandler.');
        }
        $driverAliasMap = [
            'mssql' => 'sqlsrv',
            'mysql2' => 'mysql',
            // Amazon RDS, for some weird reason
            'postgres' => 'pgsql',
            'postgresql' => 'pgsql',
            'sqlite3' => 'sqlite',
        ];
        $driver = $driverAliasMap[$params['scheme']] ?? $params['scheme'];
        // Doctrine DBAL supports passing its internal pdo_* driver names directly too (allowing both dashes and underscores). This allows supporting the same here.
        if (str_starts_with($driver, 'pdo_') || str_starts_with($driver, 'pdo-')) {
            $driver = substr($driver, 4);
        }
        $dsn = null;
        switch ($driver) {
            case 'mysql':
                $dsn = 'mysql:';
                if ('' !== ($params['query'] ?? '')) {
                    $queryParams = [];
                    parse_str($params['query'], $queryParams);
                    if ('' !== ($queryParams['charset'] ?? '')) {
                        $dsn .= 'charset=' . $queryParams['charset'] . ';';
                    }
                    if ('' !== ($queryParams['unix_socket'] ?? '')) {
                        $dsn .= 'unix_socket=' . $queryParams['unix_socket'] . ';';
                        if (isset($params['path'])) {
                            $dbName = substr($params['path'], 1);
                            // Remove the leading slash
                            $dsn .= 'dbname=' . $dbName . ';';
                        }
                        return $dsn;
                    }
                }
            // If "unix_socket" is not in the query, we continue with the same process as pgsql
            // no break
            case 'pgsql':
                $dsn ??= 'pgsql:';
                if (isset($params['host']) && '' !== $params['host']) {
                    $dsn .= 'host=' . $params['host'] . ';';
                }
                if (isset($params['port']) && '' !== $params['port']) {
                    $dsn .= 'port=' . $params['port'] . ';';
                }
                if (isset($params['path'])) {
                    $dbName = substr($params['path'], 1);
                    // Remove the leading slash
                    $dsn .= 'dbname=' . $dbName . ';';
                }
                return $dsn;
            case 'sqlite':
                return 'sqlite:' . substr($params['path'], 1);
            case 'sqlsrv':
                $dsn = 'sqlsrv:server=';
                if (isset($params['host'])) {
                    $dsn .= $params['host'];
                }
                if (isset($params['port']) && '' !== $params['port']) {
                    $dsn .= ',' . $params['port'];
                }
                if (isset($params['path'])) {
                    $dbName = substr($params['path'], 1);
                    // Remove the leading slash
                    $dsn .= ';Database=' . $dbName;
                }
                return $dsn;
            default:
                throw new \InvalidArgumentException(\sprintf('The scheme "%s" is not supported by the PdoSessionHandler URL configuration. Pass a PDO DSN directly.', $params['scheme']));
        }
    }
    /**
     * Helper method to begin a transaction.
     *
     * Since SQLite does not support row level locks, we have to acquire a reserved lock
     * on the database immediately. Because of https://bugs.php.net/42766 we have to create
     * such a transaction manually which also means we cannot use PDO::commit or
     * PDO::rollback or PDO::inTransaction for SQLite.
     *
     * Also MySQLs default isolation, REPEATABLE READ, causes deadlock for different sessions
     * due to https://percona.com/blog/2013/12/12/one-more-innodb-gap-lock-to-avoid/ .
     * So we change it to READ COMMITTED.
     */
    private function beginTransaction(): void
    {
        if (!$this->inTransaction) {
            if ('sqlite' === $this->driver) {
                $this->pdo->exec('BEGIN IMMEDIATE TRANSACTION');
            } else {
                if ('mysql' === $this->driver) {
                    $this->pdo->exec('SET TRANSACTION ISOLATION LEVEL READ COMMITTED');
                }
                $this->pdo->beginTransaction();
            }
            $this->inTransaction = \true;
        }
    }
    /**
     * Helper method to commit a transaction.
     */
    private function commit(): void
    {
        if ($this->inTransaction) {
            try {
                // commit read-write transaction which also releases the lock
                if ('sqlite' === $this->driver) {
                    $this->pdo->exec('COMMIT');
                } else {
                    $this->pdo->commit();
                }
                $this->inTransaction = \false;
            } catch (\PDOException $e) {
                $this->rollback();
                throw $e;
            }
        }
    }
    /**
     * Helper method to rollback a transaction.
     */
    private function rollback(): void
    {
        // We only need to rollback if we are in a transaction. Otherwise the resulting
        // error would hide the real problem why rollback was called. We might not be
        // in a transaction when not using the transactional locking behavior or when
        // two callbacks (e.g. destroy and write) are invoked that both fail.
        if ($this->inTransaction) {
            if ('sqlite' === $this->driver) {
                $this->pdo->exec('ROLLBACK');
            } else {
                $this->pdo->rollBack();
            }
            $this->inTransaction = \false;
        }
    }
    /**
     * Reads the session data in respect to the different locking strategies.
     *
     * We need to make sure we do not return session data that is already considered garbage according
     * to the session.gc_maxlifetime setting because gc() is called after read() and only sometimes.
     */
    protected function doRead(
        #[\SensitiveParameter]
        string $sessionId
    ): string
    {
        if (self::LOCK_ADVISORY === $this->lockMode) {
            $this->unlockStatements[] = $this->doAdvisoryLock($sessionId);
        }
        $selectSql = $this->getSelectSql();
        $selectStmt = $this->pdo->prepare($selectSql);
        $selectStmt->bindParam(':id', $sessionId, \PDO::PARAM_STR);
        $insertStmt = null;
        while (\true) {
            $selectStmt->execute();
            $sessionRows = $selectStmt->fetchAll(\PDO::FETCH_NUM);
            if ($sessionRows) {
                $expiry = (int) $sessionRows[0][1];
                if ($expiry < time()) {
                    $this->sessionExpired = \true;
                    return '';
                }
                return \is_resource($sessionRows[0][0]) ? stream_get_contents($sessionRows[0][0]) : $sessionRows[0][0];
            }
            if (null !== $insertStmt) {
                $this->rollback();
                throw new \RuntimeException('Failed to read session: INSERT reported a duplicate id but next SELECT did not return any data.');
            }
            if (!filter_var(\ini_get('session.use_strict_mode'), \FILTER_VALIDATE_BOOL) && self::LOCK_TRANSACTIONAL === $this->lockMode && 'sqlite' !== $this->driver) {
                // In strict mode, session fixation is not possible: new sessions always start with a unique
                // random id, so that concurrency is not possible and this code path can be skipped.
                // Exclusive-reading of non-existent rows does not block, so we need to do an insert to block
                // until other connections to the session are committed.
                try {
                    $insertStmt = $this->getInsertStatement($sessionId, '', 0);
                    $insertStmt->execute();
                } catch (\PDOException $e) {
                    // Catch duplicate key error because other connection created the session already.
                    // It would only not be the case when the other connection destroyed the session.
                    if (str_starts_with($e->getCode(), '23')) {
                        // Retrieve finished session data written by concurrent connection by restarting the loop.
                        // We have to start a new transaction as a failed query will mark the current transaction as
                        // aborted in PostgreSQL and disallow further queries within it.
                        $this->rollback();
                        $this->beginTransaction();
                        continue;
                    }
                    throw $e;
                }
            }
            return '';
        }
    }
    /**
     * Executes an application-level lock on the database.
     *
     * @return \PDOStatement The statement that needs to be executed later to release the lock
     *
     * @throws \DomainException When an unsupported PDO driver is used
     *
     * @todo implement missing advisory locks
     *       - for oci using DBMS_LOCK.REQUEST
     *       - for sqlsrv using sp_getapplock with LockOwner = Session
     */
    private function doAdvisoryLock(
        #[\SensitiveParameter]
        string $sessionId
    ): \PDOStatement
    {
        switch ($this->driver) {
            case 'mysql':
                // MySQL 5.7.5 and later enforces a maximum length on lock names of 64 characters. Previously, no limit was enforced.
                $lockId = substr($sessionId, 0, 64);
                // should we handle the return value? 0 on timeout, null on error
                // we use a timeout of 50 seconds which is also the default for innodb_lock_wait_timeout
                $stmt = $this->pdo->prepare('SELECT GET_LOCK(:key, 50)');
                $stmt->bindValue(':key', $lockId, \PDO::PARAM_STR);
                $stmt->execute();
                $releaseStmt = $this->pdo->prepare('DO RELEASE_LOCK(:key)');
                $releaseStmt->bindValue(':key', $lockId, \PDO::PARAM_STR);
                return $releaseStmt;
            case 'pgsql':
                // Obtaining an exclusive session level advisory lock requires an integer key.
                // When session.sid_bits_per_character > 4, the session id can contain non-hex-characters.
                // So we cannot just use hexdec().
                if (4 === \PHP_INT_SIZE) {
                    $sessionInt1 = $this->convertStringToInt($sessionId);
                    $sessionInt2 = $this->convertStringToInt(substr($sessionId, 4, 4));
                    $stmt = $this->pdo->prepare('SELECT pg_advisory_lock(:key1, :key2)');
                    $stmt->bindValue(':key1', $sessionInt1, \PDO::PARAM_INT);
                    $stmt->bindValue(':key2', $sessionInt2, \PDO::PARAM_INT);
                    $stmt->execute();
                    $releaseStmt = $this->pdo->prepare('SELECT pg_advisory_unlock(:key1, :key2)');
                    $releaseStmt->bindValue(':key1', $sessionInt1, \PDO::PARAM_INT);
                    $releaseStmt->bindValue(':key2', $sessionInt2, \PDO::PARAM_INT);
                } else {
                    $sessionBigInt = $this->convertStringToInt($sessionId);
                    $stmt = $this->pdo->prepare('SELECT pg_advisory_lock(:key)');
                    $stmt->bindValue(':key', $sessionBigInt, \PDO::PARAM_INT);
                    $stmt->execute();
                    $releaseStmt = $this->pdo->prepare('SELECT pg_advisory_unlock(:key)');
                    $releaseStmt->bindValue(':key', $sessionBigInt, \PDO::PARAM_INT);
                }
                return $releaseStmt;
            case 'sqlite':
                throw new \DomainException('SQLite does not support advisory locks.');
            default:
                throw new \DomainException(\sprintf('Advisory locks are currently not implemented for PDO driver "%s".', $this->driver));
        }
    }
    /**
     * Encodes the first 4 (when PHP_INT_SIZE == 4) or 8 characters of the string as an integer.
     *
     * Keep in mind, PHP integers are signed.
     */
    private function convertStringToInt(string $string): int
    {
        if (4 === \PHP_INT_SIZE) {
            return (\ord($string[3]) << 24) + (\ord($string[2]) << 16) + (\ord($string[1]) << 8) + \ord($string[0]);
        }
        $int1 = (\ord($string[7]) << 24) + (\ord($string[6]) << 16) + (\ord($string[5]) << 8) + \ord($string[4]);
        $int2 = (\ord($string[3]) << 24) + (\ord($string[2]) << 16) + (\ord($string[1]) << 8) + \ord($string[0]);
        return $int2 + ($int1 << 32);
    }
    /**
     * Return a locking or nonlocking SQL query to read session information.
     *
     * @throws \DomainException When an unsupported PDO driver is used
     */
    private function getSelectSql(): string
    {
        if (self::LOCK_TRANSACTIONAL === $this->lockMode) {
            $this->beginTransaction();
            switch ($this->driver) {
                case 'mysql':
                case 'oci':
                case 'pgsql':
                    return "SELECT {$this->dataCol}, {$this->lifetimeCol} FROM {$this->table} WHERE {$this->idCol} = :id FOR UPDATE";
                case 'sqlsrv':
                    return "SELECT {$this->dataCol}, {$this->lifetimeCol} FROM {$this->table} WITH (UPDLOCK, ROWLOCK) WHERE {$this->idCol} = :id";
                case 'sqlite':
                    // we already locked when starting transaction
                    break;
                default:
                    throw new \DomainException(\sprintf('Transactional locks are currently not implemented for PDO driver "%s".', $this->driver));
            }
        }
        return "SELECT {$this->dataCol}, {$this->lifetimeCol} FROM {$this->table} WHERE {$this->idCol} = :id";
    }
    /**
     * Returns an insert statement supported by the database for writing session data.
     */
    private function getInsertStatement(
        #[\SensitiveParameter]
        string $sessionId,
        string $sessionData,
        int $maxlifetime
    ): \PDOStatement
    {
        switch ($this->driver) {
            case 'oci':
                $data = fopen('php://memory', 'r+');
                fwrite($data, $sessionData);
                rewind($data);
                $sql = "INSERT INTO {$this->table} ({$this->idCol}, {$this->dataCol}, {$this->lifetimeCol}, {$this->timeCol}) VALUES (:id, EMPTY_BLOB(), :expiry, :time) RETURNING {$this->dataCol} into :data";
                break;
            case 'sqlsrv':
                $data = fopen('php://memory', 'r+');
                fwrite($data, $sessionData);
                rewind($data);
                $sql = "INSERT INTO {$this->table} ({$this->idCol}, {$this->dataCol}, {$this->lifetimeCol}, {$this->timeCol}) VALUES (:id, :data, :expiry, :time)";
                break;
            default:
                $data = $sessionData;
                $sql = "INSERT INTO {$this->table} ({$this->idCol}, {$this->dataCol}, {$this->lifetimeCol}, {$this->timeCol}) VALUES (:id, :data, :expiry, :time)";
                break;
        }
        $stmt = $this->pdo->prepare($sql);
        $stmt->bindParam(':id', $sessionId, \PDO::PARAM_STR);
        $stmt->bindParam(':data', $data, \PDO::PARAM_LOB);
        $stmt->bindValue(':expiry', time() + $maxlifetime, \PDO::PARAM_INT);
        $stmt->bindValue(':time', time(), \PDO::PARAM_INT);
        return $stmt;
    }
    /**
     * Returns an update statement supported by the database for writing session data.
     */
    private function getUpdateStatement(
        #[\SensitiveParameter]
        string $sessionId,
        string $sessionData,
        int $maxlifetime
    ): \PDOStatement
    {
        switch ($this->driver) {
            case 'oci':
                $data = fopen('php://memory', 'r+');
                fwrite($data, $sessionData);
                rewind($data);
                $sql = "UPDATE {$this->table} SET {$this->dataCol} = EMPTY_BLOB(), {$this->lifetimeCol} = :expiry, {$this->timeCol} = :time WHERE {$this->idCol} = :id RETURNING {$this->dataCol} into :data";
                break;
            case 'sqlsrv':
                $data = fopen('php://memory', 'r+');
                fwrite($data, $sessionData);
                rewind($data);
                $sql = "UPDATE {$this->table} SET {$this->dataCol} = :data, {$this->lifetimeCol} = :expiry, {$this->timeCol} = :time WHERE {$this->idCol} = :id";
                break;
            default:
                $data = $sessionData;
                $sql = "UPDATE {$this->table} SET {$this->dataCol} = :data, {$this->lifetimeCol} = :expiry, {$this->timeCol} = :time WHERE {$this->idCol} = :id";
                break;
        }
        $stmt = $this->pdo->prepare($sql);
        $stmt->bindParam(':id', $sessionId, \PDO::PARAM_STR);
        $stmt->bindParam(':data', $data, \PDO::PARAM_LOB);
        $stmt->bindValue(':expiry', time() + $maxlifetime, \PDO::PARAM_INT);
        $stmt->bindValue(':time', time(), \PDO::PARAM_INT);
        return $stmt;
    }
    /**
     * Returns a merge/upsert (i.e. insert or update) statement when supported by the database for writing session data.
     */
    private function getMergeStatement(
        #[\SensitiveParameter]
        string $sessionId,
        string $data,
        int $maxlifetime
    ): ?\PDOStatement
    {
        switch (\true) {
            case 'mysql' === $this->driver:
                $mergeSql = "INSERT INTO {$this->table} ({$this->idCol}, {$this->dataCol}, {$this->lifetimeCol}, {$this->timeCol}) VALUES (:id, :data, :expiry, :time) " . "ON DUPLICATE KEY UPDATE {$this->dataCol} = VALUES({$this->dataCol}), {$this->lifetimeCol} = VALUES({$this->lifetimeCol}), {$this->timeCol} = VALUES({$this->timeCol})";
                break;
            case 'sqlsrv' === $this->driver && version_compare($this->pdo->getAttribute(\PDO::ATTR_SERVER_VERSION), '10', '>='):
                // MERGE is only available since SQL Server 2008 and must be terminated by semicolon
                // It also requires HOLDLOCK according to https://weblogs.sqlteam.com/dang/2009/01/31/upsert-race-condition-with-merge/
                $mergeSql = "MERGE INTO {$this->table} WITH (HOLDLOCK) USING (SELECT 1 AS dummy) AS src ON ({$this->idCol} = ?) " . "WHEN NOT MATCHED THEN INSERT ({$this->idCol}, {$this->dataCol}, {$this->lifetimeCol}, {$this->timeCol}) VALUES (?, ?, ?, ?) " . "WHEN MATCHED THEN UPDATE SET {$this->dataCol} = ?, {$this->lifetimeCol} = ?, {$this->timeCol} = ?;";
                break;
            case 'sqlite' === $this->driver:
                $mergeSql = "INSERT OR REPLACE INTO {$this->table} ({$this->idCol}, {$this->dataCol}, {$this->lifetimeCol}, {$this->timeCol}) VALUES (:id, :data, :expiry, :time)";
                break;
            case 'pgsql' === $this->driver && version_compare($this->pdo->getAttribute(\PDO::ATTR_SERVER_VERSION), '9.5', '>='):
                $mergeSql = "INSERT INTO {$this->table} ({$this->idCol}, {$this->dataCol}, {$this->lifetimeCol}, {$this->timeCol}) VALUES (:id, :data, :expiry, :time) " . "ON CONFLICT ({$this->idCol}) DO UPDATE SET ({$this->dataCol}, {$this->lifetimeCol}, {$this->timeCol}) = (EXCLUDED.{$this->dataCol}, EXCLUDED.{$this->lifetimeCol}, EXCLUDED.{$this->timeCol})";
                break;
            default:
                // MERGE is not supported with LOBs: https://oracle.com/technetwork/articles/fuecks-lobs-095315.html
                return null;
        }
        $mergeStmt = $this->pdo->prepare($mergeSql);
        if ('sqlsrv' === $this->driver) {
            $dataStream = fopen('php://memory', 'r+');
            fwrite($dataStream, $data);
            rewind($dataStream);
            $mergeStmt->bindParam(1, $sessionId, \PDO::PARAM_STR);
            $mergeStmt->bindParam(2, $sessionId, \PDO::PARAM_STR);
            $mergeStmt->bindParam(3, $dataStream, \PDO::PARAM_LOB);
            $mergeStmt->bindValue(4, time() + $maxlifetime, \PDO::PARAM_INT);
            $mergeStmt->bindValue(5, time(), \PDO::PARAM_INT);
            $mergeStmt->bindParam(6, $dataStream, \PDO::PARAM_LOB);
            $mergeStmt->bindValue(7, time() + $maxlifetime, \PDO::PARAM_INT);
            $mergeStmt->bindValue(8, time(), \PDO::PARAM_INT);
        } else {
            $mergeStmt->bindParam(':id', $sessionId, \PDO::PARAM_STR);
            $mergeStmt->bindParam(':data', $data, \PDO::PARAM_LOB);
            $mergeStmt->bindValue(':expiry', time() + $maxlifetime, \PDO::PARAM_INT);
            $mergeStmt->bindValue(':time', time(), \PDO::PARAM_INT);
        }
        return $mergeStmt;
    }
    /**
     * Return a PDO instance.
     */
    protected function getConnection(): \PDO
    {
        if (!isset($this->pdo)) {
            $this->connect($this->dsn ?: \ini_get('session.save_path'));
        }
        return $this->pdo;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\HttpFoundation\Session\Storage\Handler;

use _ContaoManager\Symfony\Component\Cache\Marshaller\MarshallerInterface;
/**
 * @author Ahmed TAILOULOUTE <ahmed.tailouloute@gmail.com>
 */
class MarshallingSessionHandler implements \SessionHandlerInterface, \SessionUpdateTimestampHandlerInterface
{
    private AbstractSessionHandler $handler;
    private MarshallerInterface $marshaller;
    public function __construct(AbstractSessionHandler $handler, MarshallerInterface $marshaller)
    {
        $this->handler = $handler;
        $this->marshaller = $marshaller;
    }
    public function open(string $savePath, string $name): bool
    {
        return $this->handler->open($savePath, $name);
    }
    public function close(): bool
    {
        return $this->handler->close();
    }
    public function destroy(
        #[\SensitiveParameter]
        string $sessionId
    ): bool
    {
        return $this->handler->destroy($sessionId);
    }
    public function gc(int $maxlifetime): int|false
    {
        return $this->handler->gc($maxlifetime);
    }
    public function read(
        #[\SensitiveParameter]
        string $sessionId
    ): string
    {
        return $this->marshaller->unmarshall($this->handler->read($sessionId));
    }
    public function write(
        #[\SensitiveParameter]
        string $sessionId,
        string $data
    ): bool
    {
        $failed = [];
        $marshalledData = $this->marshaller->marshall(['data' => $data], $failed);
        if (isset($failed['data'])) {
            return \false;
        }
        return $this->handler->write($sessionId, $marshalledData['data']);
    }
    public function validateId(
        #[\SensitiveParameter]
        string $sessionId
    ): bool
    {
        return $this->handler->validateId($sessionId);
    }
    public function updateTimestamp(
        #[\SensitiveParameter]
        string $sessionId,
        string $data
    ): bool
    {
        return $this->handler->updateTimestamp($sessionId, $data);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\HttpFoundation\Session\Storage\Handler;

/**
 * Native session handler using PHP's built in file storage.
 *
 * @author Drak <drak@zikula.org>
 */
class NativeFileSessionHandler extends \SessionHandler
{
    /**
     * @param string|null $savePath Path of directory to save session files
     *                              Default null will leave setting as defined by PHP.
     *                              '/path', 'N;/path', or 'N;octal-mode;/path
     *
     * @see https://php.net/session.configuration#ini.session.save-path for further details.
     *
     * @throws \InvalidArgumentException On invalid $savePath
     * @throws \RuntimeException         When failing to create the save directory
     */
    public function __construct(?string $savePath = null)
    {
        $baseDir = $savePath ??= \ini_get('session.save_path');
        if ($count = substr_count($savePath, ';')) {
            if ($count > 2) {
                throw new \InvalidArgumentException(\sprintf('Invalid argument $savePath \'%s\'.', $savePath));
            }
            // characters after last ';' are the path
            $baseDir = ltrim(strrchr($savePath, ';'), ';');
        }
        if ($baseDir && !is_dir($baseDir) && !@mkdir($baseDir, 0777, \true) && !is_dir($baseDir)) {
            throw new \RuntimeException(\sprintf('Session Storage was not able to create directory "%s".', $baseDir));
        }
        if ($savePath !== \ini_get('session.save_path')) {
            ini_set('session.save_path', $savePath);
        }
        if ('files' !== \ini_get('session.save_handler')) {
            ini_set('session.save_handler', 'files');
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\HttpFoundation\Session\Storage\Handler;

/**
 * Migrating session handler for migrating from one handler to another. It reads
 * from the current handler and writes both the current and new ones.
 *
 * It ignores errors from the new handler.
 *
 * @author Ross Motley <ross.motley@amara.com>
 * @author Oliver Radwell <oliver.radwell@amara.com>
 */
class MigratingSessionHandler implements \SessionHandlerInterface, \SessionUpdateTimestampHandlerInterface
{
    private \SessionHandlerInterface&\SessionUpdateTimestampHandlerInterface $currentHandler;
    private \SessionHandlerInterface&\SessionUpdateTimestampHandlerInterface $writeOnlyHandler;
    public function __construct(\SessionHandlerInterface $currentHandler, \SessionHandlerInterface $writeOnlyHandler)
    {
        if (!$currentHandler instanceof \SessionUpdateTimestampHandlerInterface) {
            $currentHandler = new StrictSessionHandler($currentHandler);
        }
        if (!$writeOnlyHandler instanceof \SessionUpdateTimestampHandlerInterface) {
            $writeOnlyHandler = new StrictSessionHandler($writeOnlyHandler);
        }
        $this->currentHandler = $currentHandler;
        $this->writeOnlyHandler = $writeOnlyHandler;
    }
    public function close(): bool
    {
        $result = $this->currentHandler->close();
        $this->writeOnlyHandler->close();
        return $result;
    }
    public function destroy(
        #[\SensitiveParameter]
        string $sessionId
    ): bool
    {
        $result = $this->currentHandler->destroy($sessionId);
        $this->writeOnlyHandler->destroy($sessionId);
        return $result;
    }
    public function gc(int $maxlifetime): int|false
    {
        $result = $this->currentHandler->gc($maxlifetime);
        $this->writeOnlyHandler->gc($maxlifetime);
        return $result;
    }
    public function open(string $savePath, string $sessionName): bool
    {
        $result = $this->currentHandler->open($savePath, $sessionName);
        $this->writeOnlyHandler->open($savePath, $sessionName);
        return $result;
    }
    public function read(
        #[\SensitiveParameter]
        string $sessionId
    ): string
    {
        // No reading from new handler until switch-over
        return $this->currentHandler->read($sessionId);
    }
    public function write(
        #[\SensitiveParameter]
        string $sessionId,
        string $sessionData
    ): bool
    {
        $result = $this->currentHandler->write($sessionId, $sessionData);
        $this->writeOnlyHandler->write($sessionId, $sessionData);
        return $result;
    }
    public function validateId(
        #[\SensitiveParameter]
        string $sessionId
    ): bool
    {
        // No reading from new handler until switch-over
        return $this->currentHandler->validateId($sessionId);
    }
    public function updateTimestamp(
        #[\SensitiveParameter]
        string $sessionId,
        string $sessionData
    ): bool
    {
        $result = $this->currentHandler->updateTimestamp($sessionId, $sessionData);
        $this->writeOnlyHandler->updateTimestamp($sessionId, $sessionData);
        return $result;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\HttpFoundation\Session\Storage\Handler;

use _ContaoManager\Symfony\Component\Cache\Marshaller\MarshallerInterface;
/**
 * @author Ahmed TAILOULOUTE <ahmed.tailouloute@gmail.com>
 */
class IdentityMarshaller implements MarshallerInterface
{
    public function marshall(array $values, ?array &$failed): array
    {
        foreach ($values as $key => $value) {
            if (!\is_string($value)) {
                throw new \LogicException(\sprintf('%s accepts only string as data.', __METHOD__));
            }
        }
        return $values;
    }
    public function unmarshall(string $value): string
    {
        return $value;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\HttpFoundation\Session\Storage\Handler;

use MongoDB\BSON\Binary;
use MongoDB\BSON\UTCDateTime;
use _ContaoManager\MongoDB\Client;
use MongoDB\Driver\BulkWrite;
use MongoDB\Driver\Manager;
use MongoDB\Driver\Query;
/**
 * Session handler using the MongoDB driver extension.
 *
 * @author Markus Bachmann <markus.bachmann@bachi.biz>
 * @author Jérôme Tamarelle <jerome@tamarelle.net>
 *
 * @see https://php.net/mongodb
 */
class MongoDbSessionHandler extends AbstractSessionHandler
{
    private Manager $manager;
    private string $namespace;
    private array $options;
    private int|\Closure|null $ttl;
    /**
     * Constructor.
     *
     * List of available options:
     *  * database: The name of the database [required]
     *  * collection: The name of the collection [required]
     *  * id_field: The field name for storing the session id [default: _id]
     *  * data_field: The field name for storing the session data [default: data]
     *  * time_field: The field name for storing the timestamp [default: time]
     *  * expiry_field: The field name for storing the expiry-timestamp [default: expires_at]
     *  * ttl: The time to live in seconds.
     *
     * It is strongly recommended to put an index on the `expiry_field` for
     * garbage-collection. Alternatively it's possible to automatically expire
     * the sessions in the database as described below:
     *
     * A TTL collections can be used on MongoDB 2.2+ to cleanup expired sessions
     * automatically. Such an index can for example look like this:
     *
     *     db.<session-collection>.createIndex(
     *         { "<expiry-field>": 1 },
     *         { "expireAfterSeconds": 0 }
     *     )
     *
     * More details on: https://docs.mongodb.org/manual/tutorial/expire-data/
     *
     * If you use such an index, you can drop `gc_probability` to 0 since
     * no garbage-collection is required.
     *
     * @throws \InvalidArgumentException When "database" or "collection" not provided
     */
    public function __construct(Client|Manager $mongo, array $options)
    {
        if (!isset($options['database']) || !isset($options['collection'])) {
            throw new \InvalidArgumentException('You must provide the "database" and "collection" option for MongoDBSessionHandler.');
        }
        if ($mongo instanceof Client) {
            $mongo = $mongo->getManager();
        }
        $this->manager = $mongo;
        $this->namespace = $options['database'] . '.' . $options['collection'];
        $this->options = array_merge(['id_field' => '_id', 'data_field' => 'data', 'time_field' => 'time', 'expiry_field' => 'expires_at'], $options);
        $this->ttl = $this->options['ttl'] ?? null;
    }
    public function close(): bool
    {
        return \true;
    }
    protected function doDestroy(
        #[\SensitiveParameter]
        string $sessionId
    ): bool
    {
        $write = new BulkWrite();
        $write->delete([$this->options['id_field'] => $sessionId], ['limit' => 1]);
        $this->manager->executeBulkWrite($this->namespace, $write);
        return \true;
    }
    public function gc(int $maxlifetime): int|false
    {
        $write = new BulkWrite();
        $write->delete([$this->options['expiry_field'] => ['$lt' => $this->getUTCDateTime()]]);
        $result = $this->manager->executeBulkWrite($this->namespace, $write);
        return $result->getDeletedCount() ?? \false;
    }
    protected function doWrite(
        #[\SensitiveParameter]
        string $sessionId,
        string $data
    ): bool
    {
        $ttl = ($this->ttl instanceof \Closure ? ($this->ttl)() : $this->ttl) ?? \ini_get('session.gc_maxlifetime');
        $expiry = $this->getUTCDateTime($ttl);
        $fields = [$this->options['time_field'] => $this->getUTCDateTime(), $this->options['expiry_field'] => $expiry, $this->options['data_field'] => new Binary($data, Binary::TYPE_GENERIC)];
        $write = new BulkWrite();
        $write->update([$this->options['id_field'] => $sessionId], ['$set' => $fields], ['upsert' => \true]);
        $this->manager->executeBulkWrite($this->namespace, $write);
        return \true;
    }
    public function updateTimestamp(
        #[\SensitiveParameter]
        string $sessionId,
        string $data
    ): bool
    {
        $ttl = ($this->ttl instanceof \Closure ? ($this->ttl)() : $this->ttl) ?? \ini_get('session.gc_maxlifetime');
        $expiry = $this->getUTCDateTime($ttl);
        $write = new BulkWrite();
        $write->update([$this->options['id_field'] => $sessionId], ['$set' => [$this->options['time_field'] => $this->getUTCDateTime(), $this->options['expiry_field'] => $expiry]], ['multi' => \false]);
        $this->manager->executeBulkWrite($this->namespace, $write);
        return \true;
    }
    protected function doRead(
        #[\SensitiveParameter]
        string $sessionId
    ): string
    {
        $cursor = $this->manager->executeQuery($this->namespace, new Query([$this->options['id_field'] => $sessionId, $this->options['expiry_field'] => ['$gte' => $this->getUTCDateTime()]], ['projection' => ['_id' => \false, $this->options['data_field'] => \true], 'limit' => 1]));
        foreach ($cursor as $document) {
            return (string) $document->{$this->options['data_field']} ?? '';
        }
        // Not found
        return '';
    }
    private function getUTCDateTime(int $additionalSeconds = 0): UTCDateTime
    {
        return new UTCDateTime((time() + $additionalSeconds) * 1000);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\HttpFoundation\Session\Storage\Handler;

use _ContaoManager\Predis\Response\ErrorInterface;
use Relay\Relay;
/**
 * Redis based session storage handler based on the Redis class
 * provided by the PHP redis extension.
 *
 * @author Dalibor Karlović <dalibor@flexolabs.io>
 */
class RedisSessionHandler extends AbstractSessionHandler
{
    /**
     * Key prefix for shared environments.
     */
    private string $prefix;
    /**
     * Time to live in seconds.
     */
    private int|\Closure|null $ttl;
    /**
     * List of available options:
     *  * prefix: The prefix to use for the keys in order to avoid collision on the Redis server
     *  * ttl: The time to live in seconds.
     *
     * @throws \InvalidArgumentException When unsupported client or options are passed
     */
    public function __construct(private \Redis|Relay|\RedisArray|\RedisCluster|\_ContaoManager\Predis\ClientInterface $redis, array $options = [])
    {
        if ($diff = array_diff(array_keys($options), ['prefix', 'ttl'])) {
            throw new \InvalidArgumentException(\sprintf('The following options are not supported "%s".', implode(', ', $diff)));
        }
        $this->prefix = $options['prefix'] ?? 'sf_s';
        $this->ttl = $options['ttl'] ?? null;
    }
    protected function doRead(
        #[\SensitiveParameter]
        string $sessionId
    ): string
    {
        return $this->redis->get($this->prefix . $sessionId) ?: '';
    }
    protected function doWrite(
        #[\SensitiveParameter]
        string $sessionId,
        string $data
    ): bool
    {
        $ttl = ($this->ttl instanceof \Closure ? ($this->ttl)() : $this->ttl) ?? \ini_get('session.gc_maxlifetime');
        $result = $this->redis->setEx($this->prefix . $sessionId, (int) $ttl, $data);
        return $result && !$result instanceof ErrorInterface;
    }
    protected function doDestroy(
        #[\SensitiveParameter]
        string $sessionId
    ): bool
    {
        static $unlink = \true;
        if ($unlink) {
            try {
                $unlink = \false !== $this->redis->unlink($this->prefix . $sessionId);
            } catch (\Throwable) {
                $unlink = \false;
            }
        }
        if (!$unlink) {
            $this->redis->del($this->prefix . $sessionId);
        }
        return \true;
    }
    #[\ReturnTypeWillChange]
    public function close(): bool
    {
        return \true;
    }
    public function gc(int $maxlifetime): int|false
    {
        return 0;
    }
    public function updateTimestamp(
        #[\SensitiveParameter]
        string $sessionId,
        string $data
    ): bool
    {
        $ttl = ($this->ttl instanceof \Closure ? ($this->ttl)() : $this->ttl) ?? \ini_get('session.gc_maxlifetime');
        return $this->redis->expire($this->prefix . $sessionId, (int) $ttl);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\HttpFoundation\Session\Storage\Handler;

/**
 * Adds basic `SessionUpdateTimestampHandlerInterface` behaviors to another `SessionHandlerInterface`.
 *
 * @author Nicolas Grekas <p@tchwork.com>
 */
class StrictSessionHandler extends AbstractSessionHandler
{
    private \SessionHandlerInterface $handler;
    private bool $doDestroy;
    public function __construct(\SessionHandlerInterface $handler)
    {
        if ($handler instanceof \SessionUpdateTimestampHandlerInterface) {
            throw new \LogicException(\sprintf('"%s" is already an instance of "SessionUpdateTimestampHandlerInterface", you cannot wrap it with "%s".', get_debug_type($handler), self::class));
        }
        $this->handler = $handler;
    }
    /**
     * Returns true if this handler wraps an internal PHP session save handler using \SessionHandler.
     *
     * @internal
     */
    public function isWrapper(): bool
    {
        return $this->handler instanceof \SessionHandler;
    }
    public function open(string $savePath, string $sessionName): bool
    {
        parent::open($savePath, $sessionName);
        return $this->handler->open($savePath, $sessionName);
    }
    protected function doRead(
        #[\SensitiveParameter]
        string $sessionId
    ): string
    {
        return $this->handler->read($sessionId);
    }
    public function updateTimestamp(
        #[\SensitiveParameter]
        string $sessionId,
        string $data
    ): bool
    {
        return $this->write($sessionId, $data);
    }
    protected function doWrite(
        #[\SensitiveParameter]
        string $sessionId,
        string $data
    ): bool
    {
        return $this->handler->write($sessionId, $data);
    }
    public function destroy(
        #[\SensitiveParameter]
        string $sessionId
    ): bool
    {
        $this->doDestroy = \true;
        $destroyed = parent::destroy($sessionId);
        return $this->doDestroy ? $this->doDestroy($sessionId) : $destroyed;
    }
    protected function doDestroy(
        #[\SensitiveParameter]
        string $sessionId
    ): bool
    {
        $this->doDestroy = \false;
        return $this->handler->destroy($sessionId);
    }
    public function close(): bool
    {
        return $this->handler->close();
    }
    public function gc(int $maxlifetime): int|false
    {
        return $this->handler->gc($maxlifetime);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\HttpFoundation\Session\Storage\Handler;

/**
 * Memcached based session storage handler based on the Memcached class
 * provided by the PHP memcached extension.
 *
 * @see https://php.net/memcached
 *
 * @author Drak <drak@zikula.org>
 */
class MemcachedSessionHandler extends AbstractSessionHandler
{
    private \Memcached $memcached;
    /**
     * Time to live in seconds.
     */
    private int|\Closure|null $ttl;
    /**
     * Key prefix for shared environments.
     */
    private string $prefix;
    /**
     * Constructor.
     *
     * List of available options:
     *  * prefix: The prefix to use for the memcached keys in order to avoid collision
     *  * ttl: The time to live in seconds.
     *
     * @throws \InvalidArgumentException When unsupported options are passed
     */
    public function __construct(\Memcached $memcached, array $options = [])
    {
        $this->memcached = $memcached;
        if ($diff = array_diff(array_keys($options), ['prefix', 'expiretime', 'ttl'])) {
            throw new \InvalidArgumentException(\sprintf('The following options are not supported "%s".', implode(', ', $diff)));
        }
        $this->ttl = $options['expiretime'] ?? $options['ttl'] ?? null;
        $this->prefix = $options['prefix'] ?? 'sf2s';
    }
    public function close(): bool
    {
        return $this->memcached->quit();
    }
    protected function doRead(
        #[\SensitiveParameter]
        string $sessionId
    ): string
    {
        return $this->memcached->get($this->prefix . $sessionId) ?: '';
    }
    public function updateTimestamp(
        #[\SensitiveParameter]
        string $sessionId,
        string $data
    ): bool
    {
        $this->memcached->touch($this->prefix . $sessionId, $this->getCompatibleTtl());
        return \true;
    }
    protected function doWrite(
        #[\SensitiveParameter]
        string $sessionId,
        string $data
    ): bool
    {
        return $this->memcached->set($this->prefix . $sessionId, $data, $this->getCompatibleTtl());
    }
    private function getCompatibleTtl(): int
    {
        $ttl = ($this->ttl instanceof \Closure ? ($this->ttl)() : $this->ttl) ?? \ini_get('session.gc_maxlifetime');
        // If the relative TTL that is used exceeds 30 days, memcached will treat the value as Unix time.
        // We have to convert it to an absolute Unix time at this point, to make sure the TTL is correct.
        if ($ttl > 60 * 60 * 24 * 30) {
            $ttl += time();
        }
        return $ttl;
    }
    protected function doDestroy(
        #[\SensitiveParameter]
        string $sessionId
    ): bool
    {
        $result = $this->memcached->delete($this->prefix . $sessionId);
        return $result || \Memcached::RES_NOTFOUND == $this->memcached->getResultCode();
    }
    public function gc(int $maxlifetime): int|false
    {
        // not required here because memcached will auto expire the records anyhow.
        return 0;
    }
    /**
     * Return a Memcached instance.
     */
    protected function getMemcached(): \Memcached
    {
        return $this->memcached;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\HttpFoundation\Session\Storage;

use _ContaoManager\Symfony\Component\HttpFoundation\Session\SessionBagInterface;
use _ContaoManager\Symfony\Component\HttpFoundation\Session\Storage\Handler\StrictSessionHandler;
use _ContaoManager\Symfony\Component\HttpFoundation\Session\Storage\Proxy\AbstractProxy;
use _ContaoManager\Symfony\Component\HttpFoundation\Session\Storage\Proxy\SessionHandlerProxy;
// Help opcache.preload discover always-needed symbols
class_exists(MetadataBag::class);
class_exists(StrictSessionHandler::class);
class_exists(SessionHandlerProxy::class);
/**
 * This provides a base class for session attribute storage.
 *
 * @author Drak <drak@zikula.org>
 */
class NativeSessionStorage implements SessionStorageInterface
{
    /**
     * @var SessionBagInterface[]
     */
    protected $bags = [];
    /**
     * @var bool
     */
    protected $started = \false;
    /**
     * @var bool
     */
    protected $closed = \false;
    /**
     * @var AbstractProxy|\SessionHandlerInterface
     */
    protected $saveHandler;
    /**
     * @var MetadataBag
     */
    protected $metadataBag;
    /**
     * Depending on how you want the storage driver to behave you probably
     * want to override this constructor entirely.
     *
     * List of options for $options array with their defaults.
     *
     * @see https://php.net/session.configuration for options
     * but we omit 'session.' from the beginning of the keys for convenience.
     *
     * ("auto_start", is not supported as it tells PHP to start a session before
     * PHP starts to execute user-land code. Setting during runtime has no effect).
     *
     * cache_limiter, "" (use "0" to prevent headers from being sent entirely).
     * cache_expire, "0"
     * cookie_domain, ""
     * cookie_httponly, ""
     * cookie_lifetime, "0"
     * cookie_path, "/"
     * cookie_secure, ""
     * cookie_samesite, null
     * gc_divisor, "100"
     * gc_maxlifetime, "1440"
     * gc_probability, "1"
     * lazy_write, "1"
     * name, "PHPSESSID"
     * referer_check, ""
     * serialize_handler, "php"
     * use_strict_mode, "1"
     * use_cookies, "1"
     * use_only_cookies, "1"
     * use_trans_sid, "0"
     * sid_length, "32"
     * sid_bits_per_character, "5"
     * trans_sid_hosts, $_SERVER['HTTP_HOST']
     * trans_sid_tags, "a=href,area=href,frame=src,form="
     */
    public function __construct(array $options = [], AbstractProxy|\SessionHandlerInterface|null $handler = null, ?MetadataBag $metaBag = null)
    {
        if (!\extension_loaded('session')) {
            throw new \LogicException('PHP extension "session" is required.');
        }
        $options += ['cache_limiter' => '', 'cache_expire' => 0, 'use_cookies' => 1, 'lazy_write' => 1, 'use_strict_mode' => 1];
        session_register_shutdown();
        $this->setMetadataBag($metaBag);
        $this->setOptions($options);
        $this->setSaveHandler($handler);
    }
    /**
     * Gets the save handler instance.
     */
    public function getSaveHandler(): AbstractProxy|\SessionHandlerInterface
    {
        return $this->saveHandler;
    }
    public function start(): bool
    {
        if ($this->started) {
            return \true;
        }
        if (\PHP_SESSION_ACTIVE === session_status()) {
            throw new \RuntimeException('Failed to start the session: already started by PHP.');
        }
        if (filter_var(\ini_get('session.use_cookies'), \FILTER_VALIDATE_BOOL) && headers_sent($file, $line)) {
            throw new \RuntimeException(\sprintf('Failed to start the session because headers have already been sent by "%s" at line %d.', $file, $line));
        }
        $sessionId = $_COOKIE[session_name()] ?? null;
        /*
         * Explanation of the session ID regular expression: `/^[a-zA-Z0-9,-]{22,250}$/`.
         *
         * ---------- Part 1
         *
         * The part `[a-zA-Z0-9,-]` is related to the PHP ini directive `session.sid_bits_per_character` defined as 6.
         * See https://php.net/session.configuration#ini.session.sid-bits-per-character
         * Allowed values are integers such as:
         * - 4 for range `a-f0-9`
         * - 5 for range `a-v0-9`
         * - 6 for range `a-zA-Z0-9,-`
         *
         * ---------- Part 2
         *
         * The part `{22,250}` is related to the PHP ini directive `session.sid_length`.
         * See https://php.net/session.configuration#ini.session.sid-length
         * Allowed values are integers between 22 and 256, but we use 250 for the max.
         *
         * Where does the 250 come from?
         * - The length of Windows and Linux filenames is limited to 255 bytes. Then the max must not exceed 255.
         * - The session filename prefix is `sess_`, a 5 bytes string. Then the max must not exceed 255 - 5 = 250.
         *
         * ---------- Conclusion
         *
         * The parts 1 and 2 prevent the warning below:
         * `PHP Warning: SessionHandler::read(): Session ID is too long or contains illegal characters. Only the A-Z, a-z, 0-9, "-", and "," characters are allowed.`
         *
         * The part 2 prevents the warning below:
         * `PHP Warning: SessionHandler::read(): open(filepath, O_RDWR) failed: No such file or directory (2).`
         */
        if ($sessionId && $this->saveHandler instanceof AbstractProxy && 'files' === $this->saveHandler->getSaveHandlerName() && !preg_match('/^[a-zA-Z0-9,-]{22,250}$/', $sessionId)) {
            // the session ID in the header is invalid, create a new one
            session_id(session_create_id());
        }
        // ok to try and start the session
        if (!session_start()) {
            throw new \RuntimeException('Failed to start the session.');
        }
        $this->loadSession();
        return \true;
    }
    public function getId(): string
    {
        return $this->saveHandler->getId();
    }
    /**
     * @return void
     */
    public function setId(string $id)
    {
        $this->saveHandler->setId($id);
    }
    public function getName(): string
    {
        return $this->saveHandler->getName();
    }
    /**
     * @return void
     */
    public function setName(string $name)
    {
        $this->saveHandler->setName($name);
    }
    public function regenerate(bool $destroy = \false, ?int $lifetime = null): bool
    {
        // Cannot regenerate the session ID for non-active sessions.
        if (\PHP_SESSION_ACTIVE !== session_status()) {
            return \false;
        }
        if (headers_sent()) {
            return \false;
        }
        if (null !== $lifetime && $lifetime != \ini_get('session.cookie_lifetime')) {
            $this->save();
            ini_set('session.cookie_lifetime', $lifetime);
            $this->start();
        }
        if ($destroy) {
            $this->metadataBag->stampNew();
        }
        return session_regenerate_id($destroy);
    }
    /**
     * @return void
     */
    public function save()
    {
        // Store a copy so we can restore the bags in case the session was not left empty
        $session = $_SESSION;
        foreach ($this->bags as $bag) {
            if (empty($_SESSION[$key = $bag->getStorageKey()])) {
                unset($_SESSION[$key]);
            }
        }
        if ($_SESSION && [$key = $this->metadataBag->getStorageKey()] === array_keys($_SESSION)) {
            unset($_SESSION[$key]);
        }
        // Register error handler to add information about the current save handler
        $previousHandler = set_error_handler(function ($type, $msg, $file, $line) use (&$previousHandler) {
            if (\E_WARNING === $type && str_starts_with($msg, 'session_write_close():')) {
                $handler = $this->saveHandler instanceof SessionHandlerProxy ? $this->saveHandler->getHandler() : $this->saveHandler;
                $msg = \sprintf('session_write_close(): Failed to write session data with "%s" handler', $handler::class);
            }
            return $previousHandler ? $previousHandler($type, $msg, $file, $line) : \false;
        });
        try {
            session_write_close();
        } finally {
            restore_error_handler();
            // Restore only if not empty
            if ($_SESSION) {
                $_SESSION = $session;
            }
        }
        $this->closed = \true;
        $this->started = \false;
    }
    /**
     * @return void
     */
    public function clear()
    {
        // clear out the bags
        foreach ($this->bags as $bag) {
            $bag->clear();
        }
        // clear out the session
        $_SESSION = [];
        // reconnect the bags to the session
        $this->loadSession();
    }
    /**
     * @return void
     */
    public function registerBag(SessionBagInterface $bag)
    {
        if ($this->started) {
            throw new \LogicException('Cannot register a bag when the session is already started.');
        }
        $this->bags[$bag->getName()] = $bag;
    }
    public function getBag(string $name): SessionBagInterface
    {
        if (!isset($this->bags[$name])) {
            throw new \InvalidArgumentException(\sprintf('The SessionBagInterface "%s" is not registered.', $name));
        }
        if (!$this->started && $this->saveHandler->isActive()) {
            $this->loadSession();
        } elseif (!$this->started) {
            $this->start();
        }
        return $this->bags[$name];
    }
    /**
     * @return void
     */
    public function setMetadataBag(?MetadataBag $metaBag = null)
    {
        if (1 > \func_num_args()) {
            trigger_deprecation('symfony/http-foundation', '6.2', 'Calling "%s()" without any arguments is deprecated, pass null explicitly instead.', __METHOD__);
        }
        $this->metadataBag = $metaBag ?? new MetadataBag();
    }
    /**
     * Gets the MetadataBag.
     */
    public function getMetadataBag(): MetadataBag
    {
        return $this->metadataBag;
    }
    public function isStarted(): bool
    {
        return $this->started;
    }
    /**
     * Sets session.* ini variables.
     *
     * For convenience we omit 'session.' from the beginning of the keys.
     * Explicitly ignores other ini keys.
     *
     * @param array $options Session ini directives [key => value]
     *
     * @see https://php.net/session.configuration
     *
     * @return void
     */
    public function setOptions(array $options)
    {
        if (headers_sent() || \PHP_SESSION_ACTIVE === session_status()) {
            return;
        }
        $validOptions = array_flip(['cache_expire', 'cache_limiter', 'cookie_domain', 'cookie_httponly', 'cookie_lifetime', 'cookie_path', 'cookie_secure', 'cookie_samesite', 'gc_divisor', 'gc_maxlifetime', 'gc_probability', 'lazy_write', 'name', 'referer_check', 'serialize_handler', 'use_strict_mode', 'use_cookies', 'use_only_cookies', 'use_trans_sid', 'sid_length', 'sid_bits_per_character', 'trans_sid_hosts', 'trans_sid_tags']);
        foreach ($options as $key => $value) {
            if (isset($validOptions[$key])) {
                if ('cookie_secure' === $key && 'auto' === $value) {
                    continue;
                }
                ini_set('session.' . $key, $value);
            }
        }
    }
    /**
     * Registers session save handler as a PHP session handler.
     *
     * To use internal PHP session save handlers, override this method using ini_set with
     * session.save_handler and session.save_path e.g.
     *
     *     ini_set('session.save_handler', 'files');
     *     ini_set('session.save_path', '/tmp');
     *
     * or pass in a \SessionHandler instance which configures session.save_handler in the
     * constructor, for a template see NativeFileSessionHandler.
     *
     * @see https://php.net/session-set-save-handler
     * @see https://php.net/sessionhandlerinterface
     * @see https://php.net/sessionhandler
     *
     * @return void
     *
     * @throws \InvalidArgumentException
     */
    public function setSaveHandler(AbstractProxy|\SessionHandlerInterface|null $saveHandler = null)
    {
        if (1 > \func_num_args()) {
            trigger_deprecation('symfony/http-foundation', '6.2', 'Calling "%s()" without any arguments is deprecated, pass null explicitly instead.', __METHOD__);
        }
        // Wrap $saveHandler in proxy and prevent double wrapping of proxy
        if (!$saveHandler instanceof AbstractProxy && $saveHandler instanceof \SessionHandlerInterface) {
            $saveHandler = new SessionHandlerProxy($saveHandler);
        } elseif (!$saveHandler instanceof AbstractProxy) {
            $saveHandler = new SessionHandlerProxy(new StrictSessionHandler(new \SessionHandler()));
        }
        $this->saveHandler = $saveHandler;
        if (headers_sent() || \PHP_SESSION_ACTIVE === session_status()) {
            return;
        }
        if ($this->saveHandler instanceof SessionHandlerProxy) {
            session_set_save_handler($this->saveHandler, \false);
        }
    }
    /**
     * Load the session with attributes.
     *
     * After starting the session, PHP retrieves the session from whatever handlers
     * are set to (either PHP's internal, or a custom save handler set with session_set_save_handler()).
     * PHP takes the return value from the read() handler, unserializes it
     * and populates $_SESSION with the result automatically.
     *
     * @return void
     */
    protected function loadSession(?array &$session = null)
    {
        if (null === $session) {
            $session =& $_SESSION;
        }
        $bags = array_merge($this->bags, [$this->metadataBag]);
        foreach ($bags as $bag) {
            $key = $bag->getStorageKey();
            $session[$key] = isset($session[$key]) && \is_array($session[$key]) ? $session[$key] : [];
            $bag->initialize($session[$key]);
        }
        $this->started = \true;
        $this->closed = \false;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\HttpFoundation\Session\Storage;

use _ContaoManager\Symfony\Component\HttpFoundation\Session\SessionBagInterface;
/**
 * StorageInterface.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 * @author Drak <drak@zikula.org>
 */
interface SessionStorageInterface
{
    /**
     * Starts the session.
     *
     * @throws \RuntimeException if something goes wrong starting the session
     */
    public function start(): bool;
    /**
     * Checks if the session is started.
     */
    public function isStarted(): bool;
    /**
     * Returns the session ID.
     */
    public function getId(): string;
    /**
     * Sets the session ID.
     *
     * @return void
     */
    public function setId(string $id);
    /**
     * Returns the session name.
     */
    public function getName(): string;
    /**
     * Sets the session name.
     *
     * @return void
     */
    public function setName(string $name);
    /**
     * Regenerates id that represents this storage.
     *
     * This method must invoke session_regenerate_id($destroy) unless
     * this interface is used for a storage object designed for unit
     * or functional testing where a real PHP session would interfere
     * with testing.
     *
     * Note regenerate+destroy should not clear the session data in memory
     * only delete the session data from persistent storage.
     *
     * Care: When regenerating the session ID no locking is involved in PHP's
     * session design. See https://bugs.php.net/61470 for a discussion.
     * So you must make sure the regenerated session is saved BEFORE sending the
     * headers with the new ID. Symfony's HttpKernel offers a listener for this.
     * See Symfony\Component\HttpKernel\EventListener\SaveSessionListener.
     * Otherwise session data could get lost again for concurrent requests with the
     * new ID. One result could be that you get logged out after just logging in.
     *
     * @param bool     $destroy  Destroy session when regenerating?
     * @param int|null $lifetime Sets the cookie lifetime for the session cookie. A null value
     *                           will leave the system settings unchanged, 0 sets the cookie
     *                           to expire with browser session. Time is in seconds, and is
     *                           not a Unix timestamp.
     *
     * @throws \RuntimeException If an error occurs while regenerating this storage
     */
    public function regenerate(bool $destroy = \false, ?int $lifetime = null): bool;
    /**
     * Force the session to be saved and closed.
     *
     * This method must invoke session_write_close() unless this interface is
     * used for a storage object design for unit or functional testing where
     * a real PHP session would interfere with testing, in which case
     * it should actually persist the session data if required.
     *
     * @return void
     *
     * @throws \RuntimeException if the session is saved without being started, or if the session
     *                           is already closed
     */
    public function save();
    /**
     * Clear all session data in memory.
     *
     * @return void
     */
    public function clear();
    /**
     * Gets a SessionBagInterface by name.
     *
     * @throws \InvalidArgumentException If the bag does not exist
     */
    public function getBag(string $name): SessionBagInterface;
    /**
     * Registers a SessionBagInterface for use.
     *
     * @return void
     */
    public function registerBag(SessionBagInterface $bag);
    public function getMetadataBag(): MetadataBag;
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\HttpFoundation\Session\Storage;

use _ContaoManager\Symfony\Component\HttpFoundation\Request;
// Help opcache.preload discover always-needed symbols
class_exists(MockFileSessionStorage::class);
/**
 * @author Jérémy Derussé <jeremy@derusse.com>
 */
class MockFileSessionStorageFactory implements SessionStorageFactoryInterface
{
    private ?string $savePath;
    private string $name;
    private ?MetadataBag $metaBag;
    /**
     * @see MockFileSessionStorage constructor.
     */
    public function __construct(?string $savePath = null, string $name = 'MOCKSESSID', ?MetadataBag $metaBag = null)
    {
        $this->savePath = $savePath;
        $this->name = $name;
        $this->metaBag = $metaBag;
    }
    public function createStorage(?Request $request): SessionStorageInterface
    {
        return new MockFileSessionStorage($this->savePath, $this->name, $this->metaBag);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\HttpFoundation\Session\Storage\Proxy;

use _ContaoManager\Symfony\Component\HttpFoundation\Session\Storage\Handler\StrictSessionHandler;
/**
 * @author Drak <drak@zikula.org>
 */
class SessionHandlerProxy extends AbstractProxy implements \SessionHandlerInterface, \SessionUpdateTimestampHandlerInterface
{
    protected $handler;
    public function __construct(\SessionHandlerInterface $handler)
    {
        $this->handler = $handler;
        $this->wrapper = $handler instanceof \SessionHandler;
        $this->saveHandlerName = $this->wrapper || $handler instanceof StrictSessionHandler && $handler->isWrapper() ? \ini_get('session.save_handler') : 'user';
    }
    public function getHandler(): \SessionHandlerInterface
    {
        return $this->handler;
    }
    // \SessionHandlerInterface
    public function open(string $savePath, string $sessionName): bool
    {
        return $this->handler->open($savePath, $sessionName);
    }
    public function close(): bool
    {
        return $this->handler->close();
    }
    public function read(
        #[\SensitiveParameter]
        string $sessionId
    ): string|false
    {
        return $this->handler->read($sessionId);
    }
    public function write(
        #[\SensitiveParameter]
        string $sessionId,
        string $data
    ): bool
    {
        return $this->handler->write($sessionId, $data);
    }
    public function destroy(
        #[\SensitiveParameter]
        string $sessionId
    ): bool
    {
        return $this->handler->destroy($sessionId);
    }
    public function gc(int $maxlifetime): int|false
    {
        return $this->handler->gc($maxlifetime);
    }
    public function validateId(
        #[\SensitiveParameter]
        string $sessionId
    ): bool
    {
        return !$this->handler instanceof \SessionUpdateTimestampHandlerInterface || $this->handler->validateId($sessionId);
    }
    public function updateTimestamp(
        #[\SensitiveParameter]
        string $sessionId,
        string $data
    ): bool
    {
        return $this->handler instanceof \SessionUpdateTimestampHandlerInterface ? $this->handler->updateTimestamp($sessionId, $data) : $this->write($sessionId, $data);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\HttpFoundation\Session\Storage\Proxy;

/**
 * @author Drak <drak@zikula.org>
 */
abstract class AbstractProxy
{
    /**
     * Flag if handler wraps an internal PHP session handler (using \SessionHandler).
     *
     * @var bool
     */
    protected $wrapper = \false;
    /**
     * @var string
     */
    protected $saveHandlerName;
    /**
     * Gets the session.save_handler name.
     */
    public function getSaveHandlerName(): ?string
    {
        return $this->saveHandlerName;
    }
    /**
     * Is this proxy handler and instance of \SessionHandlerInterface.
     */
    public function isSessionHandlerInterface(): bool
    {
        return $this instanceof \SessionHandlerInterface;
    }
    /**
     * Returns true if this handler wraps an internal PHP session save handler using \SessionHandler.
     */
    public function isWrapper(): bool
    {
        return $this->wrapper;
    }
    /**
     * Has a session started?
     */
    public function isActive(): bool
    {
        return \PHP_SESSION_ACTIVE === session_status();
    }
    /**
     * Gets the session ID.
     */
    public function getId(): string
    {
        return session_id();
    }
    /**
     * Sets the session ID.
     *
     * @return void
     *
     * @throws \LogicException
     */
    public function setId(string $id)
    {
        if ($this->isActive()) {
            throw new \LogicException('Cannot change the ID of an active session.');
        }
        session_id($id);
    }
    /**
     * Gets the session name.
     */
    public function getName(): string
    {
        return session_name();
    }
    /**
     * Sets the session name.
     *
     * @return void
     *
     * @throws \LogicException
     */
    public function setName(string $name)
    {
        if ($this->isActive()) {
            throw new \LogicException('Cannot change the name of an active session.');
        }
        session_name($name);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\HttpFoundation\Session\Storage;

use _ContaoManager\Symfony\Component\HttpFoundation\Request;
use _ContaoManager\Symfony\Component\HttpFoundation\Session\Storage\Proxy\AbstractProxy;
// Help opcache.preload discover always-needed symbols
class_exists(NativeSessionStorage::class);
/**
 * @author Jérémy Derussé <jeremy@derusse.com>
 */
class NativeSessionStorageFactory implements SessionStorageFactoryInterface
{
    private array $options;
    private AbstractProxy|\SessionHandlerInterface|null $handler;
    private ?MetadataBag $metaBag;
    private bool $secure;
    /**
     * @see NativeSessionStorage constructor.
     */
    public function __construct(array $options = [], AbstractProxy|\SessionHandlerInterface|null $handler = null, ?MetadataBag $metaBag = null, bool $secure = \false)
    {
        $this->options = $options;
        $this->handler = $handler;
        $this->metaBag = $metaBag;
        $this->secure = $secure;
    }
    public function createStorage(?Request $request): SessionStorageInterface
    {
        $storage = new NativeSessionStorage($this->options, $this->handler, $this->metaBag);
        if ($this->secure && $request?->isSecure()) {
            $storage->setOptions(['cookie_secure' => \true]);
        }
        return $storage;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\HttpFoundation\Session\Storage;

use _ContaoManager\Symfony\Component\HttpFoundation\Session\Storage\Proxy\AbstractProxy;
/**
 * Allows session to be started by PHP and managed by Symfony.
 *
 * @author Drak <drak@zikula.org>
 */
class PhpBridgeSessionStorage extends NativeSessionStorage
{
    public function __construct(AbstractProxy|\SessionHandlerInterface|null $handler = null, ?MetadataBag $metaBag = null)
    {
        if (!\extension_loaded('session')) {
            throw new \LogicException('PHP extension "session" is required.');
        }
        $this->setMetadataBag($metaBag);
        $this->setSaveHandler($handler);
    }
    public function start(): bool
    {
        if ($this->started) {
            return \true;
        }
        $this->loadSession();
        return \true;
    }
    /**
     * @return void
     */
    public function clear()
    {
        // clear out the bags and nothing else that may be set
        // since the purpose of this driver is to share a handler
        foreach ($this->bags as $bag) {
            $bag->clear();
        }
        // reconnect the bags to the session
        $this->loadSession();
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\HttpFoundation\Session\Storage;

use _ContaoManager\Symfony\Component\HttpFoundation\Request;
/**
 * @author Jérémy Derussé <jeremy@derusse.com>
 */
interface SessionStorageFactoryInterface
{
    /**
     * Creates a new instance of SessionStorageInterface.
     */
    public function createStorage(?Request $request): SessionStorageInterface;
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\HttpFoundation\Session\Storage;

/**
 * MockFileSessionStorage is used to mock sessions for
 * functional testing where you may need to persist session data
 * across separate PHP processes.
 *
 * No PHP session is actually started since a session can be initialized
 * and shutdown only once per PHP execution cycle and this class does
 * not pollute any session related globals, including session_*() functions
 * or session.* PHP ini directives.
 *
 * @author Drak <drak@zikula.org>
 */
class MockFileSessionStorage extends MockArraySessionStorage
{
    private string $savePath;
    /**
     * @param string|null $savePath Path of directory to save session files
     */
    public function __construct(?string $savePath = null, string $name = 'MOCKSESSID', ?MetadataBag $metaBag = null)
    {
        $savePath ??= sys_get_temp_dir();
        if (!is_dir($savePath) && !@mkdir($savePath, 0777, \true) && !is_dir($savePath)) {
            throw new \RuntimeException(\sprintf('Session Storage was not able to create directory "%s".', $savePath));
        }
        $this->savePath = $savePath;
        parent::__construct($name, $metaBag);
    }
    public function start(): bool
    {
        if ($this->started) {
            return \true;
        }
        if (!$this->id) {
            $this->id = $this->generateId();
        }
        $this->read();
        $this->started = \true;
        return \true;
    }
    public function regenerate(bool $destroy = \false, ?int $lifetime = null): bool
    {
        if (!$this->started) {
            $this->start();
        }
        if ($destroy) {
            $this->destroy();
        }
        return parent::regenerate($destroy, $lifetime);
    }
    /**
     * @return void
     */
    public function save()
    {
        if (!$this->started) {
            throw new \RuntimeException('Trying to save a session that was not started yet or was already closed.');
        }
        $data = $this->data;
        foreach ($this->bags as $bag) {
            if (empty($data[$key = $bag->getStorageKey()])) {
                unset($data[$key]);
            }
        }
        if ([$key = $this->metadataBag->getStorageKey()] === array_keys($data)) {
            unset($data[$key]);
        }
        try {
            if ($data) {
                $path = $this->getFilePath();
                $tmp = $path . bin2hex(random_bytes(6));
                file_put_contents($tmp, serialize($data));
                rename($tmp, $path);
            } else {
                $this->destroy();
            }
        } finally {
            $this->data = $data;
        }
        // this is needed when the session object is re-used across multiple requests
        // in functional tests.
        $this->started = \false;
    }
    /**
     * Deletes a session from persistent storage.
     * Deliberately leaves session data in memory intact.
     */
    private function destroy(): void
    {
        set_error_handler(static function () {
        });
        try {
            unlink($this->getFilePath());
        } finally {
            restore_error_handler();
        }
    }
    /**
     * Calculate path to file.
     */
    private function getFilePath(): string
    {
        return $this->savePath . '/' . $this->id . '.mocksess';
    }
    /**
     * Reads session from storage and loads session.
     */
    private function read(): void
    {
        set_error_handler(static function () {
        });
        try {
            $data = file_get_contents($this->getFilePath());
        } finally {
            restore_error_handler();
        }
        $this->data = $data ? unserialize($data) : [];
        $this->loadSession();
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\HttpFoundation\Session\Storage;

use _ContaoManager\Symfony\Component\HttpFoundation\Request;
use _ContaoManager\Symfony\Component\HttpFoundation\Session\Storage\Proxy\AbstractProxy;
// Help opcache.preload discover always-needed symbols
class_exists(PhpBridgeSessionStorage::class);
/**
 * @author Jérémy Derussé <jeremy@derusse.com>
 */
class PhpBridgeSessionStorageFactory implements SessionStorageFactoryInterface
{
    private AbstractProxy|\SessionHandlerInterface|null $handler;
    private ?MetadataBag $metaBag;
    private bool $secure;
    public function __construct(AbstractProxy|\SessionHandlerInterface|null $handler = null, ?MetadataBag $metaBag = null, bool $secure = \false)
    {
        $this->handler = $handler;
        $this->metaBag = $metaBag;
        $this->secure = $secure;
    }
    public function createStorage(?Request $request): SessionStorageInterface
    {
        $storage = new PhpBridgeSessionStorage($this->handler, $this->metaBag);
        if ($this->secure && $request?->isSecure()) {
            $storage->setOptions(['cookie_secure' => \true]);
        }
        return $storage;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\HttpFoundation\Session\Storage;

use _ContaoManager\Symfony\Component\HttpFoundation\Session\SessionBagInterface;
/**
 * Metadata container.
 *
 * Adds metadata to the session.
 *
 * @author Drak <drak@zikula.org>
 */
class MetadataBag implements SessionBagInterface
{
    public const CREATED = 'c';
    public const UPDATED = 'u';
    public const LIFETIME = 'l';
    private string $name = '__metadata';
    private string $storageKey;
    /**
     * @var array
     */
    protected $meta = [self::CREATED => 0, self::UPDATED => 0, self::LIFETIME => 0];
    /**
     * Unix timestamp.
     */
    private int $lastUsed;
    private int $updateThreshold;
    private ?int $cookieLifetime;
    /**
     * @param string   $storageKey      The key used to store bag in the session
     * @param int      $updateThreshold The time to wait between two UPDATED updates
     * @param int|null $cookieLifetime  The configured cookie lifetime; null to read from php.ini
     */
    public function __construct(string $storageKey = '_sf2_meta', int $updateThreshold = 0, ?int $cookieLifetime = null)
    {
        $this->storageKey = $storageKey;
        $this->updateThreshold = $updateThreshold;
        $this->cookieLifetime = $cookieLifetime;
    }
    /**
     * @return void
     */
    public function initialize(array &$array)
    {
        $this->meta =& $array;
        if (isset($array[self::CREATED])) {
            $this->lastUsed = $this->meta[self::UPDATED];
            $timeStamp = time();
            if ($timeStamp - $array[self::UPDATED] >= $this->updateThreshold) {
                $this->meta[self::UPDATED] = $timeStamp;
            }
        } else {
            $this->stampCreated();
        }
    }
    /**
     * Gets the lifetime that the session cookie was set with.
     */
    public function getLifetime(): int
    {
        return $this->meta[self::LIFETIME];
    }
    /**
     * Stamps a new session's metadata.
     *
     * @param int|null $lifetime Sets the cookie lifetime for the session cookie. A null value
     *                           will leave the system settings unchanged, 0 sets the cookie
     *                           to expire with browser session. Time is in seconds, and is
     *                           not a Unix timestamp.
     *
     * @return void
     */
    public function stampNew(?int $lifetime = null)
    {
        $this->stampCreated($lifetime);
    }
    public function getStorageKey(): string
    {
        return $this->storageKey;
    }
    /**
     * Gets the created timestamp metadata.
     *
     * @return int Unix timestamp
     */
    public function getCreated(): int
    {
        return $this->meta[self::CREATED];
    }
    /**
     * Gets the last used metadata.
     *
     * @return int Unix timestamp
     */
    public function getLastUsed(): int
    {
        return $this->lastUsed;
    }
    public function clear(): mixed
    {
        // nothing to do
        return null;
    }
    public function getName(): string
    {
        return $this->name;
    }
    /**
     * Sets name.
     *
     * @return void
     */
    public function setName(string $name)
    {
        $this->name = $name;
    }
    private function stampCreated(?int $lifetime = null): void
    {
        $timeStamp = time();
        $this->meta[self::CREATED] = $this->meta[self::UPDATED] = $this->lastUsed = $timeStamp;
        $this->meta[self::LIFETIME] = $lifetime ?? $this->cookieLifetime ?? (int) \ini_get('session.cookie_lifetime');
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\HttpFoundation\Session\Storage;

use _ContaoManager\Symfony\Component\HttpFoundation\Session\SessionBagInterface;
/**
 * MockArraySessionStorage mocks the session for unit tests.
 *
 * No PHP session is actually started since a session can be initialized
 * and shutdown only once per PHP execution cycle.
 *
 * When doing functional testing, you should use MockFileSessionStorage instead.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 * @author Bulat Shakirzyanov <mallluhuct@gmail.com>
 * @author Drak <drak@zikula.org>
 */
class MockArraySessionStorage implements SessionStorageInterface
{
    /**
     * @var string
     */
    protected $id = '';
    /**
     * @var string
     */
    protected $name;
    /**
     * @var bool
     */
    protected $started = \false;
    /**
     * @var bool
     */
    protected $closed = \false;
    /**
     * @var array
     */
    protected $data = [];
    /**
     * @var MetadataBag
     */
    protected $metadataBag;
    /**
     * @var array|SessionBagInterface[]
     */
    protected $bags = [];
    public function __construct(string $name = 'MOCKSESSID', ?MetadataBag $metaBag = null)
    {
        $this->name = $name;
        $this->setMetadataBag($metaBag);
    }
    /**
     * @return void
     */
    public function setSessionData(array $array)
    {
        $this->data = $array;
    }
    public function start(): bool
    {
        if ($this->started) {
            return \true;
        }
        if (empty($this->id)) {
            $this->id = $this->generateId();
        }
        $this->loadSession();
        return \true;
    }
    public function regenerate(bool $destroy = \false, ?int $lifetime = null): bool
    {
        if (!$this->started) {
            $this->start();
        }
        $this->metadataBag->stampNew($lifetime);
        $this->id = $this->generateId();
        return \true;
    }
    public function getId(): string
    {
        return $this->id;
    }
    /**
     * @return void
     */
    public function setId(string $id)
    {
        if ($this->started) {
            throw new \LogicException('Cannot set session ID after the session has started.');
        }
        $this->id = $id;
    }
    public function getName(): string
    {
        return $this->name;
    }
    /**
     * @return void
     */
    public function setName(string $name)
    {
        $this->name = $name;
    }
    /**
     * @return void
     */
    public function save()
    {
        if (!$this->started || $this->closed) {
            throw new \RuntimeException('Trying to save a session that was not started yet or was already closed.');
        }
        // nothing to do since we don't persist the session data
        $this->closed = \false;
        $this->started = \false;
    }
    /**
     * @return void
     */
    public function clear()
    {
        // clear out the bags
        foreach ($this->bags as $bag) {
            $bag->clear();
        }
        // clear out the session
        $this->data = [];
        // reconnect the bags to the session
        $this->loadSession();
    }
    /**
     * @return void
     */
    public function registerBag(SessionBagInterface $bag)
    {
        $this->bags[$bag->getName()] = $bag;
    }
    public function getBag(string $name): SessionBagInterface
    {
        if (!isset($this->bags[$name])) {
            throw new \InvalidArgumentException(\sprintf('The SessionBagInterface "%s" is not registered.', $name));
        }
        if (!$this->started) {
            $this->start();
        }
        return $this->bags[$name];
    }
    public function isStarted(): bool
    {
        return $this->started;
    }
    /**
     * @return void
     */
    public function setMetadataBag(?MetadataBag $bag = null)
    {
        if (1 > \func_num_args()) {
            trigger_deprecation('symfony/http-foundation', '6.2', 'Calling "%s()" without any arguments is deprecated, pass null explicitly instead.', __METHOD__);
        }
        $this->metadataBag = $bag ?? new MetadataBag();
    }
    /**
     * Gets the MetadataBag.
     */
    public function getMetadataBag(): MetadataBag
    {
        return $this->metadataBag;
    }
    /**
     * Generates a session ID.
     *
     * This doesn't need to be particularly cryptographically secure since this is just
     * a mock.
     */
    protected function generateId(): string
    {
        return bin2hex(random_bytes(16));
    }
    /**
     * @return void
     */
    protected function loadSession()
    {
        $bags = array_merge($this->bags, [$this->metadataBag]);
        foreach ($bags as $bag) {
            $key = $bag->getStorageKey();
            $this->data[$key] ??= [];
            $bag->initialize($this->data[$key]);
        }
        $this->started = \true;
        $this->closed = \false;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\HttpFoundation\Session;

use _ContaoManager\Symfony\Component\HttpFoundation\Session\Storage\MetadataBag;
/**
 * Interface for the session.
 *
 * @author Drak <drak@zikula.org>
 */
interface SessionInterface
{
    /**
     * Starts the session storage.
     *
     * @throws \RuntimeException if session fails to start
     */
    public function start(): bool;
    /**
     * Returns the session ID.
     */
    public function getId(): string;
    /**
     * Sets the session ID.
     *
     * @return void
     */
    public function setId(string $id);
    /**
     * Returns the session name.
     */
    public function getName(): string;
    /**
     * Sets the session name.
     *
     * @return void
     */
    public function setName(string $name);
    /**
     * Invalidates the current session.
     *
     * Clears all session attributes and flashes and regenerates the
     * session and deletes the old session from persistence.
     *
     * @param int|null $lifetime Sets the cookie lifetime for the session cookie. A null value
     *                           will leave the system settings unchanged, 0 sets the cookie
     *                           to expire with browser session. Time is in seconds, and is
     *                           not a Unix timestamp.
     */
    public function invalidate(?int $lifetime = null): bool;
    /**
     * Migrates the current session to a new session id while maintaining all
     * session attributes.
     *
     * @param bool     $destroy  Whether to delete the old session or leave it to garbage collection
     * @param int|null $lifetime Sets the cookie lifetime for the session cookie. A null value
     *                           will leave the system settings unchanged, 0 sets the cookie
     *                           to expire with browser session. Time is in seconds, and is
     *                           not a Unix timestamp.
     */
    public function migrate(bool $destroy = \false, ?int $lifetime = null): bool;
    /**
     * Force the session to be saved and closed.
     *
     * This method is generally not required for real sessions as
     * the session will be automatically saved at the end of
     * code execution.
     *
     * @return void
     */
    public function save();
    /**
     * Checks if an attribute is defined.
     */
    public function has(string $name): bool;
    /**
     * Returns an attribute.
     */
    public function get(string $name, mixed $default = null): mixed;
    /**
     * Sets an attribute.
     *
     * @return void
     */
    public function set(string $name, mixed $value);
    /**
     * Returns attributes.
     */
    public function all(): array;
    /**
     * Sets attributes.
     *
     * @return void
     */
    public function replace(array $attributes);
    /**
     * Removes an attribute.
     *
     * @return mixed The removed value or null when it does not exist
     */
    public function remove(string $name): mixed;
    /**
     * Clears all attributes.
     *
     * @return void
     */
    public function clear();
    /**
     * Checks if the session was started.
     */
    public function isStarted(): bool;
    /**
     * Registers a SessionBagInterface with the session.
     *
     * @return void
     */
    public function registerBag(SessionBagInterface $bag);
    /**
     * Gets a bag instance by name.
     */
    public function getBag(string $name): SessionBagInterface;
    /**
     * Gets session meta.
     */
    public function getMetadataBag(): MetadataBag;
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\HttpFoundation\Session\Flash;

/**
 * AutoExpireFlashBag flash message container.
 *
 * @author Drak <drak@zikula.org>
 */
class AutoExpireFlashBag implements FlashBagInterface
{
    private string $name = 'flashes';
    private array $flashes = ['display' => [], 'new' => []];
    private string $storageKey;
    /**
     * @param string $storageKey The key used to store flashes in the session
     */
    public function __construct(string $storageKey = '_symfony_flashes')
    {
        $this->storageKey = $storageKey;
    }
    public function getName(): string
    {
        return $this->name;
    }
    /**
     * @return void
     */
    public function setName(string $name)
    {
        $this->name = $name;
    }
    /**
     * @return void
     */
    public function initialize(array &$flashes)
    {
        $this->flashes =& $flashes;
        // The logic: messages from the last request will be stored in new, so we move them to previous
        // This request we will show what is in 'display'.  What is placed into 'new' this time round will
        // be moved to display next time round.
        $this->flashes['display'] = \array_key_exists('new', $this->flashes) ? $this->flashes['new'] : [];
        $this->flashes['new'] = [];
    }
    /**
     * @return void
     */
    public function add(string $type, mixed $message)
    {
        $this->flashes['new'][$type][] = $message;
    }
    public function peek(string $type, array $default = []): array
    {
        return $this->has($type) ? $this->flashes['display'][$type] : $default;
    }
    public function peekAll(): array
    {
        return \array_key_exists('display', $this->flashes) ? $this->flashes['display'] : [];
    }
    public function get(string $type, array $default = []): array
    {
        $return = $default;
        if (!$this->has($type)) {
            return $return;
        }
        if (isset($this->flashes['display'][$type])) {
            $return = $this->flashes['display'][$type];
            unset($this->flashes['display'][$type]);
        }
        return $return;
    }
    public function all(): array
    {
        $return = $this->flashes['display'];
        $this->flashes['display'] = [];
        return $return;
    }
    /**
     * @return void
     */
    public function setAll(array $messages)
    {
        $this->flashes['new'] = $messages;
    }
    /**
     * @return void
     */
    public function set(string $type, string|array $messages)
    {
        $this->flashes['new'][$type] = (array) $messages;
    }
    public function has(string $type): bool
    {
        return \array_key_exists($type, $this->flashes['display']) && $this->flashes['display'][$type];
    }
    public function keys(): array
    {
        return array_keys($this->flashes['display']);
    }
    public function getStorageKey(): string
    {
        return $this->storageKey;
    }
    public function clear(): mixed
    {
        return $this->all();
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\HttpFoundation\Session\Flash;

use _ContaoManager\Symfony\Component\HttpFoundation\Session\SessionBagInterface;
/**
 * FlashBagInterface.
 *
 * @author Drak <drak@zikula.org>
 */
interface FlashBagInterface extends SessionBagInterface
{
    /**
     * Adds a flash message for the given type.
     *
     * @return void
     */
    public function add(string $type, mixed $message);
    /**
     * Registers one or more messages for a given type.
     *
     * @return void
     */
    public function set(string $type, string|array $messages);
    /**
     * Gets flash messages for a given type.
     *
     * @param string $type    Message category type
     * @param array  $default Default value if $type does not exist
     */
    public function peek(string $type, array $default = []): array;
    /**
     * Gets all flash messages.
     */
    public function peekAll(): array;
    /**
     * Gets and clears flash from the stack.
     *
     * @param array $default Default value if $type does not exist
     */
    public function get(string $type, array $default = []): array;
    /**
     * Gets and clears flashes from the stack.
     */
    public function all(): array;
    /**
     * Sets all flash messages.
     *
     * @return void
     */
    public function setAll(array $messages);
    /**
     * Has flash messages for a given type?
     */
    public function has(string $type): bool;
    /**
     * Returns a list of all defined types.
     */
    public function keys(): array;
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\HttpFoundation\Session\Flash;

/**
 * FlashBag flash message container.
 *
 * @author Drak <drak@zikula.org>
 */
class FlashBag implements FlashBagInterface
{
    private string $name = 'flashes';
    private array $flashes = [];
    private string $storageKey;
    /**
     * @param string $storageKey The key used to store flashes in the session
     */
    public function __construct(string $storageKey = '_symfony_flashes')
    {
        $this->storageKey = $storageKey;
    }
    public function getName(): string
    {
        return $this->name;
    }
    /**
     * @return void
     */
    public function setName(string $name)
    {
        $this->name = $name;
    }
    /**
     * @return void
     */
    public function initialize(array &$flashes)
    {
        $this->flashes =& $flashes;
    }
    /**
     * @return void
     */
    public function add(string $type, mixed $message)
    {
        $this->flashes[$type][] = $message;
    }
    public function peek(string $type, array $default = []): array
    {
        return $this->has($type) ? $this->flashes[$type] : $default;
    }
    public function peekAll(): array
    {
        return $this->flashes;
    }
    public function get(string $type, array $default = []): array
    {
        if (!$this->has($type)) {
            return $default;
        }
        $return = $this->flashes[$type];
        unset($this->flashes[$type]);
        return $return;
    }
    public function all(): array
    {
        $return = $this->peekAll();
        $this->flashes = [];
        return $return;
    }
    /**
     * @return void
     */
    public function set(string $type, string|array $messages)
    {
        $this->flashes[$type] = (array) $messages;
    }
    /**
     * @return void
     */
    public function setAll(array $messages)
    {
        $this->flashes = $messages;
    }
    public function has(string $type): bool
    {
        return \array_key_exists($type, $this->flashes) && $this->flashes[$type];
    }
    public function keys(): array
    {
        return array_keys($this->flashes);
    }
    public function getStorageKey(): string
    {
        return $this->storageKey;
    }
    public function clear(): mixed
    {
        return $this->all();
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\HttpFoundation\Session;

use _ContaoManager\Symfony\Component\HttpFoundation\RequestStack;
use _ContaoManager\Symfony\Component\HttpFoundation\Session\Storage\SessionStorageFactoryInterface;
// Help opcache.preload discover always-needed symbols
class_exists(Session::class);
/**
 * @author Jérémy Derussé <jeremy@derusse.com>
 */
class SessionFactory implements SessionFactoryInterface
{
    private RequestStack $requestStack;
    private SessionStorageFactoryInterface $storageFactory;
    private ?\Closure $usageReporter;
    public function __construct(RequestStack $requestStack, SessionStorageFactoryInterface $storageFactory, ?callable $usageReporter = null)
    {
        $this->requestStack = $requestStack;
        $this->storageFactory = $storageFactory;
        $this->usageReporter = null === $usageReporter ? null : $usageReporter(...);
    }
    public function createSession(): SessionInterface
    {
        return new Session($this->storageFactory->createStorage($this->requestStack->getMainRequest()), null, null, $this->usageReporter);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\HttpFoundation\Session;

/**
 * @author Nicolas Grekas <p@tchwork.com>
 *
 * @internal
 */
final class SessionBagProxy implements SessionBagInterface
{
    private SessionBagInterface $bag;
    private array $data;
    private ?int $usageIndex;
    private ?\Closure $usageReporter;
    public function __construct(SessionBagInterface $bag, array &$data, ?int &$usageIndex, ?callable $usageReporter)
    {
        $this->bag = $bag;
        $this->data =& $data;
        $this->usageIndex =& $usageIndex;
        $this->usageReporter = null === $usageReporter ? null : $usageReporter(...);
    }
    public function getBag(): SessionBagInterface
    {
        ++$this->usageIndex;
        if ($this->usageReporter && 0 <= $this->usageIndex) {
            ($this->usageReporter)();
        }
        return $this->bag;
    }
    public function isEmpty(): bool
    {
        if (!isset($this->data[$this->bag->getStorageKey()])) {
            return \true;
        }
        ++$this->usageIndex;
        if ($this->usageReporter && 0 <= $this->usageIndex) {
            ($this->usageReporter)();
        }
        return empty($this->data[$this->bag->getStorageKey()]);
    }
    public function getName(): string
    {
        return $this->bag->getName();
    }
    public function initialize(array &$array): void
    {
        ++$this->usageIndex;
        if ($this->usageReporter && 0 <= $this->usageIndex) {
            ($this->usageReporter)();
        }
        $this->data[$this->bag->getStorageKey()] =& $array;
        $this->bag->initialize($array);
    }
    public function getStorageKey(): string
    {
        return $this->bag->getStorageKey();
    }
    public function clear(): mixed
    {
        return $this->bag->clear();
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\HttpFoundation\Session;

/**
 * Session Bag store.
 *
 * @author Drak <drak@zikula.org>
 */
interface SessionBagInterface
{
    /**
     * Gets this bag's name.
     */
    public function getName(): string;
    /**
     * Initializes the Bag.
     *
     * @return void
     */
    public function initialize(array &$array);
    /**
     * Gets the storage key for this bag.
     */
    public function getStorageKey(): string;
    /**
     * Clears out data from bag.
     *
     * @return mixed Whatever data was contained
     */
    public function clear(): mixed;
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\VarExporter;

use _ContaoManager\Symfony\Component\VarExporter\Exception\ExceptionInterface;
use _ContaoManager\Symfony\Component\VarExporter\Exception\NotInstantiableTypeException;
use _ContaoManager\Symfony\Component\VarExporter\Internal\Registry;
/**
 * A utility class to create objects without calling their constructor.
 *
 * @author Nicolas Grekas <p@tchwork.com>
 */
final class Instantiator
{
    /**
     * Creates an object and sets its properties without calling its constructor nor any other methods.
     *
     * @see Hydrator::hydrate() for examples
     *
     * @template T of object
     *
     * @param class-string<T>                           $class            The class of the instance to create
     * @param array<string, mixed>                      $properties       The properties to set on the instance
     * @param array<class-string, array<string, mixed>> $scopedProperties The properties to set on the instance,
     *                                                                    keyed by their declaring class
     *
     * @return T
     *
     * @throws ExceptionInterface When the instance cannot be created
     */
    public static function instantiate(string $class, array $properties = [], array $scopedProperties = []): object
    {
        $reflector = Registry::$reflectors[$class] ??= Registry::getClassReflector($class);
        if (Registry::$cloneable[$class]) {
            $instance = clone Registry::$prototypes[$class];
        } elseif (Registry::$instantiableWithoutConstructor[$class]) {
            $instance = $reflector->newInstanceWithoutConstructor();
        } elseif (null === Registry::$prototypes[$class]) {
            throw new NotInstantiableTypeException($class);
        } elseif ($reflector->implementsInterface('Serializable') && !method_exists($class, '__unserialize')) {
            $instance = unserialize('C:' . \strlen($class) . ':"' . $class . '":0:{}');
        } else {
            $instance = unserialize('O:' . \strlen($class) . ':"' . $class . '":0:{}');
        }
        return $properties || $scopedProperties ? Hydrator::hydrate($instance, $properties, $scopedProperties) : $instance;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\VarExporter;

use _ContaoManager\Symfony\Component\VarExporter\Exception\LogicException;
use _ContaoManager\Symfony\Component\VarExporter\Internal\Hydrator;
use _ContaoManager\Symfony\Component\VarExporter\Internal\LazyObjectRegistry;
/**
 * @author Nicolas Grekas <p@tchwork.com>
 */
final class ProxyHelper
{
    /**
     * Helps generate lazy-loading ghost objects.
     *
     * @throws LogicException When the class is incompatible with ghost objects
     */
    public static function generateLazyGhost(\ReflectionClass $class): string
    {
        if (\PHP_VERSION_ID >= 80200 && \PHP_VERSION_ID < 80300 && $class->isReadOnly()) {
            throw new LogicException(\sprintf('Cannot generate lazy ghost with PHP < 8.3: class "%s" is readonly.', $class->name));
        }
        if ($class->isFinal()) {
            throw new LogicException(\sprintf('Cannot generate lazy ghost: class "%s" is final.', $class->name));
        }
        if ($class->isInterface() || $class->isAbstract() || $class->isTrait()) {
            throw new LogicException(\sprintf('Cannot generate lazy ghost: "%s" is not a concrete class.', $class->name));
        }
        if (\stdClass::class !== $class->name && $class->isInternal()) {
            throw new LogicException(\sprintf('Cannot generate lazy ghost: class "%s" is internal.', $class->name));
        }
        if ($class->hasMethod('__get') && 'mixed' !== (self::exportType($class->getMethod('__get')) ?? 'mixed')) {
            throw new LogicException(\sprintf('Cannot generate lazy ghost: return type of method "%s::__get()" should be "mixed".', $class->name));
        }
        static $traitMethods;
        $traitMethods ??= (new \ReflectionClass(LazyGhostTrait::class))->getMethods();
        foreach ($traitMethods as $method) {
            if ($class->hasMethod($method->name) && $class->getMethod($method->name)->isFinal()) {
                throw new LogicException(\sprintf('Cannot generate lazy ghost: method "%s::%s()" is final.', $class->name, $method->name));
            }
        }
        $parent = $class;
        while ($parent = $parent->getParentClass()) {
            if (\stdClass::class !== $parent->name && $parent->isInternal()) {
                throw new LogicException(\sprintf('Cannot generate lazy ghost: class "%s" extends "%s" which is internal.', $class->name, $parent->name));
            }
        }
        $hooks = '';
        $propertyScopes = Hydrator::$propertyScopes[$class->name] ??= Hydrator::getPropertyScopes($class->name);
        foreach ($propertyScopes as $key => [$scope, $name, , $access]) {
            $propertyScopes[$k = "\x00{$scope}\x00{$name}"] ?? $propertyScopes[$k = "\x00*\x00{$name}"] ?? $k = $name;
            $flags = $access >> 2;
            if ($k !== $key || !($access & Hydrator::PROPERTY_HAS_HOOKS) || $flags & \ReflectionProperty::IS_VIRTUAL) {
                continue;
            }
            if ($flags & (\ReflectionProperty::IS_FINAL | \ReflectionProperty::IS_PRIVATE)) {
                throw new LogicException(\sprintf('Cannot generate lazy ghost: property "%s::$%s" is final or private(set).', $class->name, $name));
            }
            $p = $propertyScopes[$k][4] ?? Hydrator::$propertyScopes[$class->name][$k][4] = new \ReflectionProperty($scope, $name);
            $type = self::exportType($p);
            $hooks .= "\n    " . ($p->isProtected() ? 'protected' : 'public') . ($p->isProtectedSet() ? ' protected(set)' : '') . " {$type} \${$name}" . ($p->hasDefaultValue() ? ' = ' . VarExporter::export($p->getDefaultValue()) : '') . " {\n";
            foreach ($p->getHooks() as $hook => $method) {
                if ('get' === $hook) {
                    $ref = $method->returnsReference() ? '&' : '';
                    $hooks .= "        {$ref}get { \$this->initializeLazyObject(); return parent::\${$name}::get(); }\n";
                } elseif ('set' === $hook) {
                    $parameters = self::exportParameters($method, \true);
                    $arg = '$' . $method->getParameters()[0]->name;
                    $hooks .= "        set({$parameters}) { \$this->initializeLazyObject(); parent::\${$name}::set({$arg}); }\n";
                } else {
                    throw new LogicException(\sprintf('Cannot generate lazy ghost: hook "%s::%s()" is not supported.', $class->name, $method->name));
                }
            }
            $hooks .= "        }\n";
        }
        $propertyScopes = self::exportPropertyScopes($class->name, $propertyScopes);
        return <<<EOPHP
 extends \\{$class->name} implements \\_ContaoManager\\Symfony\\Component\\VarExporter\\LazyObjectInterface
{
    use \\_ContaoManager\\Symfony\\Component\\VarExporter\\LazyGhostTrait;

    private const LAZY_OBJECT_PROPERTY_SCOPES = {$propertyScopes};
{$hooks}}

// Help opcache.preload discover always-needed symbols
class_exists(\\_ContaoManager\\Symfony\\Component\\VarExporter\\Internal\\Hydrator::class);
class_exists(\\_ContaoManager\\Symfony\\Component\\VarExporter\\Internal\\LazyObjectRegistry::class);
class_exists(\\_ContaoManager\\Symfony\\Component\\VarExporter\\Internal\\LazyObjectState::class);

EOPHP;
    }
    /**
     * Helps generate lazy-loading virtual proxies.
     *
     * @param \ReflectionClass[] $interfaces
     *
     * @throws LogicException When the class is incompatible with virtual proxies
     */
    public static function generateLazyProxy(?\ReflectionClass $class, array $interfaces = []): string
    {
        if (!class_exists($class?->name ?? \stdClass::class, \false)) {
            throw new LogicException(\sprintf('Cannot generate lazy proxy: "%s" is not a class.', $class->name));
        }
        if ($class?->isFinal()) {
            throw new LogicException(\sprintf('Cannot generate lazy proxy: class "%s" is final.', $class->name));
        }
        if (\PHP_VERSION_ID >= 80200 && \PHP_VERSION_ID < 80300 && $class?->isReadOnly()) {
            throw new LogicException(\sprintf('Cannot generate lazy proxy with PHP < 8.3: class "%s" is readonly.', $class->name));
        }
        $propertyScopes = $class ? Hydrator::$propertyScopes[$class->name] ??= Hydrator::getPropertyScopes($class->name) : [];
        $abstractProperties = [];
        $hookedProperties = [];
        if (\PHP_VERSION_ID >= 80400 && $class) {
            foreach ($propertyScopes as $key => [$scope, $name, , $access]) {
                $propertyScopes[$k = "\x00{$scope}\x00{$name}"] ?? $propertyScopes[$k = "\x00*\x00{$name}"] ?? $k = $name;
                $flags = $access >> 2;
                if ($k !== $key) {
                    continue;
                }
                if ($flags & \ReflectionProperty::IS_ABSTRACT) {
                    $abstractProperties[$name] = $propertyScopes[$k][4] ?? Hydrator::$propertyScopes[$class->name][$k][4] = new \ReflectionProperty($scope, $name);
                    continue;
                }
                $abstractProperties[$name] = \false;
                if (!($access & Hydrator::PROPERTY_HAS_HOOKS) || $flags & \ReflectionProperty::IS_VIRTUAL) {
                    continue;
                }
                if ($flags & (\ReflectionProperty::IS_FINAL | \ReflectionProperty::IS_PRIVATE)) {
                    throw new LogicException(\sprintf('Cannot generate lazy proxy: property "%s::$%s" is final or private(set).', $class->name, $name));
                }
                $p = $propertyScopes[$k][4] ?? Hydrator::$propertyScopes[$class->name][$k][4] = new \ReflectionProperty($scope, $name);
                $hookedProperties[$name] = [$p, $p->getHooks()];
            }
        }
        $methodReflectors = [$class?->getMethods(\ReflectionMethod::IS_PUBLIC | \ReflectionMethod::IS_PROTECTED) ?? []];
        foreach ($interfaces as $interface) {
            if (!$interface->isInterface()) {
                throw new LogicException(\sprintf('Cannot generate lazy proxy: "%s" is not an interface.', $interface->name));
            }
            $methodReflectors[] = $interface->getMethods();
            if (\PHP_VERSION_ID >= 80400) {
                foreach ($interface->getProperties() as $p) {
                    $abstractProperties[$p->name] ??= $p;
                    $hookedProperties[$p->name] ??= [$p, []];
                    $hookedProperties[$p->name][1] += $p->getHooks();
                }
            }
        }
        $hooks = '';
        foreach (array_filter($abstractProperties) as $name => $p) {
            $type = self::exportType($p);
            $hooks .= "\n    " . ($p->isProtected() ? 'protected' : 'public') . ($p->isProtectedSet() ? ' protected(set)' : '') . " {$type} \${$name};\n";
        }
        foreach ($hookedProperties as $name => [$p, $methods]) {
            $type = self::exportType($p);
            $hooks .= "\n    " . ($p->isProtected() ? 'protected' : 'public') . ($p->isProtectedSet() ? ' protected(set)' : '') . " {$type} \${$name} {\n";
            foreach ($methods as $hook => $method) {
                if ('get' === $hook) {
                    $ref = $method->returnsReference() ? '&' : '';
                    $hooks .= <<<EOPHP
        {$ref}get {
            if (isset(\$this->lazyObjectState)) {
                return (\$this->lazyObjectState->realInstance ??= (\$this->lazyObjectState->initializer)())->{$p->name};
            }

            return parent::\${$p->name}::get();
        }

EOPHP;
                } elseif ('set' === $hook) {
                    $parameters = self::exportParameters($method, \true);
                    $arg = '$' . $method->getParameters()[0]->name;
                    $hooks .= <<<EOPHP
        set({$parameters}) {
            if (isset(\$this->lazyObjectState)) {
                \$this->lazyObjectState->realInstance ??= (\$this->lazyObjectState->initializer)();
                \$this->lazyObjectState->realInstance->{$p->name} = {$arg};
            }

            parent::\${$p->name}::set({$arg});
        }

EOPHP;
                } else {
                    throw new LogicException(\sprintf('Cannot generate lazy proxy: hook "%s::%s()" is not supported.', $class->name, $method->name));
                }
            }
            $hooks .= "    }\n";
        }
        $extendsInternalClass = \false;
        if ($parent = $class) {
            do {
                $extendsInternalClass = \stdClass::class !== $parent->name && $parent->isInternal();
            } while (!$extendsInternalClass && $parent = $parent->getParentClass());
        }
        $methodsHaveToBeProxied = $extendsInternalClass;
        $methods = [];
        $methodReflectors = array_merge(...$methodReflectors);
        foreach ($methodReflectors as $method) {
            if ('__get' !== strtolower($method->name) || 'mixed' === $type = self::exportType($method) ?? 'mixed') {
                continue;
            }
            $methodsHaveToBeProxied = \true;
            $trait = new \ReflectionMethod(LazyProxyTrait::class, '__get');
            $body = \array_slice(file($trait->getFileName()), $trait->getStartLine() - 1, $trait->getEndLine() - $trait->getStartLine());
            $body[0] = str_replace('): mixed', '): ' . $type, $body[0]);
            $methods['__get'] = strtr(implode('', $body) . '    }', ['Hydrator' => '\\' . Hydrator::class, 'Registry' => '\\' . LazyObjectRegistry::class]);
            break;
        }
        foreach ($methodReflectors as $method) {
            if ($method->isStatic() && !$method->isAbstract() || isset($methods[$lcName = strtolower($method->name)])) {
                continue;
            }
            if ($method->isFinal()) {
                if ($extendsInternalClass || $methodsHaveToBeProxied || method_exists(LazyProxyTrait::class, $method->name)) {
                    throw new LogicException(\sprintf('Cannot generate lazy proxy: method "%s::%s()" is final.', $class->name, $method->name));
                }
                continue;
            }
            if (method_exists(LazyProxyTrait::class, $method->name) || $method->isProtected() && !$method->isAbstract()) {
                continue;
            }
            $signature = self::exportSignature($method, \true, $args);
            $parentCall = $method->isAbstract() ? "throw new \\BadMethodCallException('Cannot forward abstract method \"{$method->class}::{$method->name}()\".')" : "parent::{$method->name}({$args})";
            if ($method->isStatic()) {
                $body = "        {$parentCall};";
            } elseif (str_ends_with($signature, '): never') || str_ends_with($signature, '): void')) {
                $body = <<<EOPHP
        if (isset(\$this->lazyObjectState)) {
            (\$this->lazyObjectState->realInstance ??= (\$this->lazyObjectState->initializer)())->{$method->name}({$args});
        } else {
            {$parentCall};
        }
EOPHP;
            } else {
                if (!$methodsHaveToBeProxied && !$method->isAbstract()) {
                    // Skip proxying methods that might return $this
                    foreach (preg_split('/[()|&]++/', self::exportType($method) ?? 'static') as $type) {
                        if (\in_array($type = ltrim($type, '?'), ['static', 'object'], \true)) {
                            continue 2;
                        }
                        foreach ([$class, ...$interfaces] as $r) {
                            if ($r && is_a($r->name, $type, \true)) {
                                continue 3;
                            }
                        }
                    }
                }
                $body = <<<EOPHP
        if (isset(\$this->lazyObjectState)) {
            return (\$this->lazyObjectState->realInstance ??= (\$this->lazyObjectState->initializer)())->{$method->name}({$args});
        }

        return {$parentCall};
EOPHP;
            }
            $methods[$lcName] = "    {$signature}\n    {\n{$body}\n    }";
        }
        $types = $interfaces = array_unique(array_column($interfaces, 'name'));
        $interfaces[] = LazyObjectInterface::class;
        $interfaces = implode(', \\', $interfaces);
        $parent = $class ? ' extends \\' . $class->name : '';
        array_unshift($types, $class ? 'parent' : '');
        $type = ltrim(implode('&\\', $types), '&');
        if (!$class) {
            $trait = new \ReflectionMethod(LazyProxyTrait::class, 'initializeLazyObject');
            $body = \array_slice(file($trait->getFileName()), $trait->getStartLine() - 1, $trait->getEndLine() - $trait->getStartLine());
            $body[0] = str_replace('): parent', '): ' . $type, $body[0]);
            $methods = ['initializeLazyObject' => implode('', $body) . '    }'] + $methods;
        }
        $body = $methods ? "\n" . implode("\n\n", $methods) . "\n" : '';
        $propertyScopes = $class ? self::exportPropertyScopes($class->name, $propertyScopes) : '[]';
        if ($class?->hasMethod('__unserialize') && !$class->getMethod('__unserialize')->getParameters()[0]->getType()) {
            // fix contravariance type problem when $class declares a `__unserialize()` method without typehint.
            $lazyProxyTraitStatement = <<<EOPHP
use \\_ContaoManager\\Symfony\\Component\\VarExporter\\LazyProxyTrait {
        __unserialize as private __doUnserialize;
    }
EOPHP;
            $body .= <<<EOPHP

    public function __unserialize(\$data): void
    {
        \$this->__doUnserialize(\$data);
    }

EOPHP;
        } else {
            $lazyProxyTraitStatement = <<<EOPHP
use \\_ContaoManager\\Symfony\\Component\\VarExporter\\LazyProxyTrait;
EOPHP;
        }
        return <<<EOPHP
{$parent} implements \\{$interfaces}
{
    {$lazyProxyTraitStatement}

    private const LAZY_OBJECT_PROPERTY_SCOPES = {$propertyScopes};
{$hooks}{$body}}

// Help opcache.preload discover always-needed symbols
class_exists(\\_ContaoManager\\Symfony\\Component\\VarExporter\\Internal\\Hydrator::class);
class_exists(\\_ContaoManager\\Symfony\\Component\\VarExporter\\Internal\\LazyObjectRegistry::class);
class_exists(\\_ContaoManager\\Symfony\\Component\\VarExporter\\Internal\\LazyObjectState::class);

EOPHP;
    }
    public static function exportParameters(\ReflectionFunctionAbstract $function, bool $withParameterTypes = \true, ?string &$args = null): string
    {
        $byRefIndex = 0;
        $args = '';
        $param = null;
        $parameters = [];
        $namespace = $function instanceof \ReflectionMethod ? $function->class : $function->getNamespaceName() . '\\';
        $namespace = substr($namespace, 0, strrpos($namespace, '\\') ?: 0);
        foreach ($function->getParameters() as $param) {
            $parameters[] = ($param->getAttributes(\SensitiveParameter::class) ? '#[\SensitiveParameter] ' : '') . ($withParameterTypes && $param->hasType() ? self::exportType($param) . ' ' : '') . ($param->isPassedByReference() ? '&' : '') . ($param->isVariadic() ? '...' : '') . '$' . $param->name . ($param->isOptional() && !$param->isVariadic() ? ' = ' . self::exportDefault($param, $namespace) : '');
            if ($param->isPassedByReference()) {
                $byRefIndex = 1 + $param->getPosition();
            }
            $args .= ($param->isVariadic() ? '...$' : '$') . $param->name . ', ';
        }
        if (!$param || !$byRefIndex) {
            $args = '...\func_get_args()';
        } elseif ($param->isVariadic()) {
            $args = substr($args, 0, -2);
        } else {
            $args = explode(', ', $args, 1 + $byRefIndex);
            $args[$byRefIndex] = \sprintf('...\array_slice(\func_get_args(), %d)', $byRefIndex);
            $args = implode(', ', $args);
        }
        return implode(', ', $parameters);
    }
    public static function exportSignature(\ReflectionFunctionAbstract $function, bool $withParameterTypes = \true, ?string &$args = null): string
    {
        $parameters = self::exportParameters($function, $withParameterTypes, $args);
        $signature = 'function ' . ($function->returnsReference() ? '&' : '') . ($function->isClosure() ? '' : $function->name) . '(' . $parameters . ')';
        if ($function instanceof \ReflectionMethod) {
            $signature = ($function->isPublic() ? 'public ' : ($function->isProtected() ? 'protected ' : 'private ')) . ($function->isStatic() ? 'static ' : '') . $signature;
        }
        if ($function->hasReturnType()) {
            $signature .= ': ' . self::exportType($function);
        }
        static $getPrototype;
        $getPrototype ??= (new \ReflectionMethod(\ReflectionMethod::class, 'getPrototype'))->invoke(...);
        while ($function) {
            if ($function->hasTentativeReturnType()) {
                return '#[\ReturnTypeWillChange] ' . $signature;
            }
            try {
                $function = $function instanceof \ReflectionMethod && $function->isAbstract() ? \false : $getPrototype($function);
            } catch (\ReflectionException) {
                break;
            }
        }
        return $signature;
    }
    public static function exportType(\ReflectionFunctionAbstract|\ReflectionProperty|\ReflectionParameter $owner, bool $noBuiltin = \false, ?\ReflectionType $type = null): ?string
    {
        if (!$type ??= $owner instanceof \ReflectionFunctionAbstract ? $owner->getReturnType() : $owner->getType()) {
            return null;
        }
        $class = null;
        $types = [];
        if ($type instanceof \ReflectionUnionType) {
            $reflectionTypes = $type->getTypes();
            $glue = '|';
        } elseif ($type instanceof \ReflectionIntersectionType) {
            $reflectionTypes = $type->getTypes();
            $glue = '&';
        } else {
            $reflectionTypes = [$type];
            $glue = null;
        }
        foreach ($reflectionTypes as $type) {
            if ($type instanceof \ReflectionIntersectionType) {
                if ('' !== $name = '(' . self::exportType($owner, $noBuiltin, $type) . ')') {
                    $types[] = $name;
                }
                continue;
            }
            $name = $type->getName();
            if ($noBuiltin && $type->isBuiltin()) {
                continue;
            }
            if (\in_array($name, ['parent', 'self'], \true) && $class ??= $owner->getDeclaringClass()) {
                $name = 'parent' === $name ? ($class->getParentClass() ?: null)?->name ?? 'parent' : $class->name;
            }
            $types[] = ($noBuiltin || $type->isBuiltin() || 'static' === $name ? '' : '\\') . $name;
        }
        if (!$types) {
            return '';
        }
        if (null === $glue) {
            $defaultNull = $owner instanceof \ReflectionParameter && 'NULL' === rtrim(substr(explode('$' . $owner->name . ' = ', (string) $owner, 2)[1] ?? '', 0, -2));
            return (!$noBuiltin && ($type->allowsNull() || $defaultNull) && !\in_array($name, ['mixed', 'null'], \true) ? '?' : '') . $types[0];
        }
        sort($types);
        return implode($glue, $types);
    }
    private static function exportPropertyScopes(string $parent, array $propertyScopes): string
    {
        uksort($propertyScopes, 'strnatcmp');
        foreach ($propertyScopes as $k => $v) {
            unset($propertyScopes[$k][4]);
        }
        $propertyScopes = VarExporter::export($propertyScopes);
        $propertyScopes = str_replace(VarExporter::export($parent), 'parent::class', $propertyScopes);
        $propertyScopes = preg_replace("/(?|(,)\n( )       |\n        |,\n    (\\]))/", '$1$2', $propertyScopes);
        $propertyScopes = str_replace("\n", "\n    ", $propertyScopes);
        return $propertyScopes;
    }
    private static function exportDefault(\ReflectionParameter $param, $namespace): string
    {
        $default = rtrim(substr(explode('$' . $param->name . ' = ', (string) $param, 2)[1] ?? '', 0, -2));
        if (\in_array($default, ['<default>', 'NULL'], \true)) {
            return 'null';
        }
        if (str_ends_with($default, "...'") && preg_match("/^'(?:[^'\\\\]*+(?:\\\\.)*+)*+'\$/", $default)) {
            return VarExporter::export($param->getDefaultValue());
        }
        $regexp = "/(\"(?:[^\"\\\\]*+(?:\\\\.)*+)*+\"|'(?:[^'\\\\]*+(?:\\\\.)*+)*+')/";
        $parts = preg_split($regexp, $default, -1, \PREG_SPLIT_DELIM_CAPTURE | \PREG_SPLIT_NO_EMPTY);
        $regexp = '/([\[\( ]|^)([a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*+(?:\\\\[a-zA-Z0-9_\x7f-\xff]++)*+)(\(?)(?!: )/';
        $callback = \false !== strpbrk($default, "\\:('") && ($class = $param->getDeclaringClass()) ? fn($m) => $m[1] . match ($m[2]) {
            'new', 'false', 'true', 'null' => $m[2],
            'NULL' => 'null',
            'self' => '\\' . $class->name,
            'namespace\parent', 'parent' => ($parent = $class->getParentClass()) ? '\\' . $parent->name : 'parent',
            default => self::exportSymbol($m[2], '(' !== $m[3], $namespace),
        } . $m[3] : fn($m) => $m[1] . match ($m[2]) {
            'new', 'false', 'true', 'null', 'self', 'parent' => $m[2],
            'NULL' => 'null',
            default => self::exportSymbol($m[2], '(' !== $m[3], $namespace),
        } . $m[3];
        return implode('', array_map(fn($part) => match ($part[0]) {
            '"' => $part,
            // for internal classes only
            "'" => \false !== strpbrk($part, "\\\x00\r\n") ? '"' . substr(str_replace(['$', "\x00", "\r", "\n"], ['\$', '\0', '\r', '\n'], $part), 1, -1) . '"' : $part,
            default => preg_replace_callback($regexp, $callback, $part),
        }, $parts));
    }
    private static function exportSymbol(string $symbol, bool $mightBeRootConst, string $namespace): string
    {
        if (!$mightBeRootConst || \false === ($ns = strrpos($symbol, '\\')) || substr($symbol, 0, $ns) !== $namespace || \defined($symbol) || !\defined(substr($symbol, $ns + 1))) {
            return '\\' . $symbol;
        }
        return '\\' . substr($symbol, $ns + 1);
    }
}
Copyright (c) 2018-present Fabien Potencier

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is furnished
to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
CHANGELOG
=========

6.4
---

 * Deprecate per-property lazy-initializers

6.2
---

 * Add support for lazy ghost objects and virtual proxies
 * Add `Hydrator::hydrate()`
 * Preserve PHP references also when using `Hydrator::hydrate()` or `Instantiator::instantiate()`
 * Add support for hydrating from native (array) casts

5.1.0
-----

 * added argument `array &$foundClasses` to `VarExporter::export()` to ease with preloading exported values

4.2.0
-----

 * added the component
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\VarExporter;

use _ContaoManager\Symfony\Component\VarExporter\Internal\Hydrator as InternalHydrator;
/**
 * Utility class to hydrate the properties of an object.
 *
 * @author Nicolas Grekas <p@tchwork.com>
 */
final class Hydrator
{
    /**
     * Sets the properties of an object, including private and protected ones.
     *
     * For example:
     *
     *     // Sets the public or protected $object->propertyName property
     *     Hydrator::hydrate($object, ['propertyName' => $propertyValue]);
     *
     *     // Sets a private property defined on its parent Bar class:
     *     Hydrator::hydrate($object, ["\0Bar\0privateBarProperty" => $propertyValue]);
     *
     *     // Alternative way to set the private $object->privateBarProperty property
     *     Hydrator::hydrate($object, [], [
     *         Bar::class => ['privateBarProperty' => $propertyValue],
     *     ]);
     *
     * Instances of ArrayObject, ArrayIterator and SplObjectStorage can be hydrated
     * by using the special "\0" property name to define their internal value:
     *
     *     // Hydrates an SplObjectStorage where $info1 is attached to $obj1, etc.
     *     Hydrator::hydrate($object, ["\0" => [$obj1, $info1, $obj2, $info2...]]);
     *
     *     // Hydrates an ArrayObject populated with $inputArray
     *     Hydrator::hydrate($object, ["\0" => [$inputArray]]);
     *
     * @template T of object
     *
     * @param T                                         $instance         The object to hydrate
     * @param array<string, mixed>                      $properties       The properties to set on the instance
     * @param array<class-string, array<string, mixed>> $scopedProperties The properties to set on the instance,
     *                                                                    keyed by their declaring class
     *
     * @return T
     */
    public static function hydrate(object $instance, array $properties = [], array $scopedProperties = []): object
    {
        if ($properties) {
            $class = $instance::class;
            $propertyScopes = InternalHydrator::$propertyScopes[$class] ??= InternalHydrator::getPropertyScopes($class);
            foreach ($properties as $name => &$value) {
                [$scope, $name, $writeScope] = $propertyScopes[$name] ?? [$class, $name, $class];
                $scopedProperties[$writeScope ?? $scope][$name] =& $value;
            }
            unset($value);
        }
        foreach ($scopedProperties as $scope => $properties) {
            if ($properties) {
                (InternalHydrator::$simpleHydrators[$scope] ??= InternalHydrator::getSimpleHydrator($scope))($properties, $instance);
            }
        }
        return $instance;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\VarExporter\Internal;

use _ContaoManager\Symfony\Component\VarExporter\Hydrator as PublicHydrator;
/**
 * Keeps the state of lazy objects.
 *
 * As a micro-optimization, this class uses no type declarations.
 *
 * @internal
 */
class LazyObjectState
{
    public const STATUS_UNINITIALIZED_FULL = 1;
    public const STATUS_UNINITIALIZED_PARTIAL = 2;
    public const STATUS_INITIALIZED_FULL = 3;
    public const STATUS_INITIALIZED_PARTIAL = 4;
    /**
     * @var array<string, true>
     */
    public readonly array $skippedProperties;
    /**
     * @var self::STATUS_*
     */
    public int $status = 0;
    public object $realInstance;
    public function __construct(public readonly \Closure|array $initializer, $skippedProperties = [])
    {
        $this->skippedProperties = $skippedProperties;
        $this->status = \is_array($initializer) ? self::STATUS_UNINITIALIZED_PARTIAL : self::STATUS_UNINITIALIZED_FULL;
    }
    public function initialize($instance, $propertyName, $writeScope)
    {
        if (self::STATUS_INITIALIZED_FULL === $this->status) {
            return self::STATUS_INITIALIZED_FULL;
        }
        if (\is_array($this->initializer)) {
            $class = $instance::class;
            $writeScope ??= $class;
            $propertyScopes = Hydrator::$propertyScopes[$class];
            $propertyScopes[$k = "\x00{$writeScope}\x00{$propertyName}"] ?? $propertyScopes[$k = "\x00*\x00{$propertyName}"] ?? $k = $propertyName;
            if ($initializer = $this->initializer[$k] ?? null) {
                $value = $initializer(...[$instance, $propertyName, $writeScope, LazyObjectRegistry::$defaultProperties[$class][$k] ?? null]);
                $accessor = LazyObjectRegistry::$classAccessors[$writeScope] ??= LazyObjectRegistry::getClassAccessors($writeScope);
                $accessor['set']($instance, $propertyName, $value);
                return $this->status = self::STATUS_INITIALIZED_PARTIAL;
            }
            if ($initializer = $this->initializer["\x00"] ?? null) {
                if (!\is_array($values = $initializer($instance, LazyObjectRegistry::$defaultProperties[$class]))) {
                    throw new \TypeError(\sprintf('The lazy-initializer defined for instance of "%s" must return an array, got "%s".', $class, get_debug_type($values)));
                }
                $properties = (array) $instance;
                foreach ($values as $key => $value) {
                    if (!\array_key_exists($key, $properties) && [$scope, $name, $writeScope] = $propertyScopes[$key] ?? null) {
                        $scope = $writeScope ?? $scope;
                        $accessor = LazyObjectRegistry::$classAccessors[$scope] ??= LazyObjectRegistry::getClassAccessors($scope);
                        $accessor['set']($instance, $name, $value);
                        if ($k === $key) {
                            $this->status = self::STATUS_INITIALIZED_PARTIAL;
                        }
                    }
                }
            }
            return $this->status;
        }
        if (self::STATUS_INITIALIZED_PARTIAL === $this->status) {
            return self::STATUS_INITIALIZED_PARTIAL;
        }
        $this->status = self::STATUS_INITIALIZED_PARTIAL;
        try {
            if ($defaultProperties = array_diff_key(LazyObjectRegistry::$defaultProperties[$instance::class], $this->skippedProperties)) {
                PublicHydrator::hydrate($instance, $defaultProperties);
            }
            ($this->initializer)($instance);
        } catch (\Throwable $e) {
            $this->status = self::STATUS_UNINITIALIZED_FULL;
            $this->reset($instance);
            throw $e;
        }
        return $this->status = self::STATUS_INITIALIZED_FULL;
    }
    public function reset($instance): void
    {
        $class = $instance::class;
        $propertyScopes = Hydrator::$propertyScopes[$class] ??= Hydrator::getPropertyScopes($class);
        $skippedProperties = $this->skippedProperties;
        $properties = (array) $instance;
        $onlyProperties = \is_array($this->initializer) ? $this->initializer : null;
        foreach ($propertyScopes as $key => [$scope, $name, , $access]) {
            $propertyScopes[$k = "\x00{$scope}\x00{$name}"] ?? $propertyScopes[$k = "\x00*\x00{$name}"] ?? $k = $name;
            if ($k === $key && ($access & Hydrator::PROPERTY_HAS_HOOKS || $access >> 2 & \ReflectionProperty::IS_READONLY || !\array_key_exists($k, $properties))) {
                $skippedProperties[$k] = \true;
            }
        }
        foreach (LazyObjectRegistry::$classResetters[$class] as $reset) {
            $reset($instance, $skippedProperties, $onlyProperties);
        }
        $this->status = self::STATUS_INITIALIZED_FULL === $this->status ? self::STATUS_UNINITIALIZED_FULL : self::STATUS_UNINITIALIZED_PARTIAL;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\VarExporter\Internal;

/**
 * Stores the state of lazy objects and caches related reflection information.
 *
 * As a micro-optimization, this class uses no type declarations.
 *
 * @internal
 */
class LazyObjectRegistry
{
    /**
     * @var array<class-string, \ReflectionClass>
     */
    public static array $classReflectors = [];
    /**
     * @var array<class-string, array<string, mixed>>
     */
    public static array $defaultProperties = [];
    /**
     * @var array<class-string, list<\Closure>>
     */
    public static array $classResetters = [];
    /**
     * @var array<class-string, array{get: \Closure, set: \Closure, isset: \Closure, unset: \Closure}>
     */
    public static array $classAccessors = [];
    /**
     * @var array<class-string, array{set: bool, isset: bool, unset: bool, clone: bool, serialize: bool, unserialize: bool, sleep: bool, wakeup: bool, destruct: bool, get: int}>
     */
    public static array $parentMethods = [];
    public static ?\Closure $noInitializerState = null;
    public static function getClassResetters($class)
    {
        $classProperties = [];
        $hookedProperties = [];
        if ((self::$classReflectors[$class] ??= new \ReflectionClass($class))->isInternal()) {
            $propertyScopes = [];
        } else {
            $propertyScopes = Hydrator::$propertyScopes[$class] ??= Hydrator::getPropertyScopes($class);
        }
        foreach ($propertyScopes as $key => [$scope, $name, $writeScope, $access]) {
            $propertyScopes[$k = "\x00{$scope}\x00{$name}"] ?? $propertyScopes[$k = "\x00*\x00{$name}"] ?? $k = $name;
            if ($k !== $key || "\x00{$class}\x00lazyObjectState" === $k) {
                continue;
            }
            if ($access & Hydrator::PROPERTY_HAS_HOOKS) {
                $hookedProperties[$k] = \true;
            } else {
                $classProperties[$writeScope ?? $scope][$name] = $key;
            }
        }
        $resetters = [];
        foreach ($classProperties as $scope => $properties) {
            $resetters[] = \Closure::bind(static function ($instance, $skippedProperties, $onlyProperties = null) use ($properties) {
                foreach ($properties as $name => $key) {
                    if (!\array_key_exists($key, $skippedProperties) && (null === $onlyProperties || \array_key_exists($key, $onlyProperties))) {
                        unset($instance->{$name});
                    }
                }
            }, null, $scope);
        }
        $resetters[] = static function ($instance, $skippedProperties, $onlyProperties = null) use ($hookedProperties) {
            foreach ((array) $instance as $name => $value) {
                if ("\x00" !== ($name[0] ?? '') && !\array_key_exists($name, $skippedProperties) && (null === $onlyProperties || \array_key_exists($name, $onlyProperties)) && !isset($hookedProperties[$name])) {
                    unset($instance->{$name});
                }
            }
        };
        return $resetters;
    }
    public static function getClassAccessors($class)
    {
        return \Closure::bind(static fn() => ['get' => static function &($instance, $name, $notByRef) {
            if (!$notByRef) {
                return $instance->{$name};
            }
            $value = $instance->{$name};
            return $value;
        }, 'set' => static function ($instance, $name, $value) {
            $instance->{$name} = $value;
        }, 'isset' => static fn($instance, $name) => isset($instance->{$name}), 'unset' => static function ($instance, $name) {
            unset($instance->{$name});
        }], null, \Closure::class === $class ? null : $class)();
    }
    public static function getParentMethods($class)
    {
        $parent = get_parent_class($class);
        $methods = [];
        foreach (['set', 'isset', 'unset', 'clone', 'serialize', 'unserialize', 'sleep', 'wakeup', 'destruct', 'get'] as $method) {
            if (!$parent || !method_exists($parent, '__' . $method)) {
                $methods[$method] = \false;
            } else {
                $m = new \ReflectionMethod($parent, '__' . $method);
                $methods[$method] = !$m->isAbstract() && !$m->isPrivate();
            }
        }
        $methods['get'] = $methods['get'] ? $m->returnsReference() ? 2 : 1 : 0;
        return $methods;
    }
    public static function getScopeForRead($propertyScopes, $class, $property)
    {
        if (!isset($propertyScopes[$k = "\x00{$class}\x00{$property}"]) && !isset($propertyScopes[$k = "\x00*\x00{$property}"])) {
            return null;
        }
        $frame = debug_backtrace(\DEBUG_BACKTRACE_PROVIDE_OBJECT | \DEBUG_BACKTRACE_IGNORE_ARGS, 3)[2];
        if (\ReflectionProperty::class === $scope = $frame['class'] ?? \Closure::class) {
            $scope = $frame['object']->class;
        }
        if ('*' === $k[1] && ($class === $scope || is_subclass_of($class, $scope) && !isset($propertyScopes["\x00{$scope}\x00{$property}"]))) {
            return null;
        }
        return $scope;
    }
    public static function getScopeForWrite($propertyScopes, $class, $property, $flags)
    {
        if (!($flags & (\ReflectionProperty::IS_PRIVATE | \ReflectionProperty::IS_PROTECTED | \ReflectionProperty::IS_READONLY | (\PHP_VERSION_ID >= 80400 ? \ReflectionProperty::IS_PRIVATE_SET | \ReflectionProperty::IS_PROTECTED_SET : 0)))) {
            return null;
        }
        $frame = debug_backtrace(\DEBUG_BACKTRACE_PROVIDE_OBJECT | \DEBUG_BACKTRACE_IGNORE_ARGS, 3)[2];
        if (\ReflectionProperty::class === $scope = $frame['class'] ?? \Closure::class) {
            $scope = $frame['object']->class;
        }
        if ($flags & (\ReflectionProperty::IS_PRIVATE | (\PHP_VERSION_ID >= 80400 ? \ReflectionProperty::IS_PRIVATE_SET : \ReflectionProperty::IS_READONLY))) {
            return $scope;
        }
        if ($flags & (\ReflectionProperty::IS_PROTECTED | (\PHP_VERSION_ID >= 80400 ? \ReflectionProperty::IS_PROTECTED_SET : 0)) && ($class === $scope || is_subclass_of($class, $scope) && !isset($propertyScopes["\x00{$scope}\x00{$property}"]))) {
            return null;
        }
        return $scope;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\VarExporter\Internal;

/**
 * @author Nicolas Grekas <p@tchwork.com>
 *
 * @internal
 */
class Values
{
    public $values;
    public function __construct(array $values)
    {
        $this->values = $values;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\VarExporter\Internal;

use _ContaoManager\Symfony\Component\Serializer\Attribute\Ignore;
if (\PHP_VERSION_ID >= 80300) {
    /**
     * @internal
     */
    trait LazyObjectTrait
    {
        #[Ignore]
        private readonly LazyObjectState $lazyObjectState;
    }
} else {
    /**
     * @internal
     */
    trait LazyObjectTrait
    {
        #[Ignore]
        private LazyObjectState $lazyObjectState;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\VarExporter\Internal;

use _ContaoManager\Symfony\Component\VarExporter\Exception\ClassNotFoundException;
/**
 * @author Nicolas Grekas <p@tchwork.com>
 *
 * @internal
 */
class Hydrator
{
    public const PROPERTY_HAS_HOOKS = 1;
    public const PROPERTY_NOT_BY_REF = 2;
    public static array $hydrators = [];
    public static array $simpleHydrators = [];
    public static array $propertyScopes = [];
    public $registry;
    public $values;
    public $properties;
    public $value;
    public $wakeups;
    public function __construct(?Registry $registry, ?Values $values, array $properties, $value, array $wakeups)
    {
        $this->registry = $registry;
        $this->values = $values;
        $this->properties = $properties;
        $this->value = $value;
        $this->wakeups = $wakeups;
    }
    public static function hydrate($objects, $values, $properties, $value, $wakeups)
    {
        foreach ($properties as $class => $vars) {
            (self::$hydrators[$class] ??= self::getHydrator($class))($vars, $objects);
        }
        foreach ($wakeups as $k => $v) {
            if (\is_array($v)) {
                $objects[-$k]->__unserialize($v);
            } else {
                $objects[$v]->__wakeup();
            }
        }
        return $value;
    }
    public static function getHydrator($class)
    {
        $baseHydrator = self::$hydrators['stdClass'] ??= static function ($properties, $objects) {
            foreach ($properties as $name => $values) {
                foreach ($values as $i => $v) {
                    $objects[$i]->{$name} = $v;
                }
            }
        };
        switch ($class) {
            case 'stdClass':
                return $baseHydrator;
            case 'ErrorException':
                return $baseHydrator->bindTo(null, new class extends \ErrorException
                {
                });
            case 'TypeError':
                return $baseHydrator->bindTo(null, new class extends \Error
                {
                });
            case 'SplObjectStorage':
                return static function ($properties, $objects) {
                    foreach ($properties as $name => $values) {
                        if ("\x00" === $name) {
                            foreach ($values as $i => $v) {
                                for ($j = 0; $j < \count($v); ++$j) {
                                    $objects[$i][$v[$j]] = $v[++$j];
                                }
                            }
                            continue;
                        }
                        foreach ($values as $i => $v) {
                            $objects[$i]->{$name} = $v;
                        }
                    }
                };
        }
        if (!class_exists($class) && !interface_exists($class, \false) && !trait_exists($class, \false)) {
            throw new ClassNotFoundException($class);
        }
        $classReflector = new \ReflectionClass($class);
        switch ($class) {
            case 'ArrayIterator':
            case 'ArrayObject':
                $constructor = $classReflector->getConstructor()->invokeArgs(...);
                return static function ($properties, $objects) use ($constructor) {
                    foreach ($properties as $name => $values) {
                        if ("\x00" !== $name) {
                            foreach ($values as $i => $v) {
                                $objects[$i]->{$name} = $v;
                            }
                        }
                    }
                    foreach ($properties["\x00"] ?? [] as $i => $v) {
                        $constructor($objects[$i], $v);
                    }
                };
        }
        if (!$classReflector->isInternal()) {
            return $baseHydrator->bindTo(null, $class);
        }
        if ($classReflector->name !== $class) {
            return self::$hydrators[$classReflector->name] ??= self::getHydrator($classReflector->name);
        }
        $propertySetters = [];
        foreach ($classReflector->getProperties() as $propertyReflector) {
            if (!$propertyReflector->isStatic()) {
                $propertySetters[$propertyReflector->name] = $propertyReflector->setValue(...);
            }
        }
        if (!$propertySetters) {
            return $baseHydrator;
        }
        return static function ($properties, $objects) use ($propertySetters) {
            foreach ($properties as $name => $values) {
                if ($setValue = $propertySetters[$name] ?? null) {
                    foreach ($values as $i => $v) {
                        $setValue($objects[$i], $v);
                    }
                    continue;
                }
                foreach ($values as $i => $v) {
                    $objects[$i]->{$name} = $v;
                }
            }
        };
    }
    public static function getSimpleHydrator($class)
    {
        $baseHydrator = self::$simpleHydrators['stdClass'] ??= (function ($properties, $object) {
            $notByRef = (array) $this;
            foreach ($properties as $name => &$value) {
                if (!$noRef = $notByRef[$name] ?? \false) {
                    $object->{$name} = $value;
                    $object->{$name} =& $value;
                } elseif (\true !== $noRef) {
                    $noRef($object, $value);
                } else {
                    $object->{$name} = $value;
                }
            }
        })->bindTo(new \stdClass());
        switch ($class) {
            case 'stdClass':
                return $baseHydrator;
            case 'ErrorException':
                return $baseHydrator->bindTo(new \stdClass(), new class extends \ErrorException
                {
                });
            case 'TypeError':
                return $baseHydrator->bindTo(new \stdClass(), new class extends \Error
                {
                });
            case 'SplObjectStorage':
                return static function ($properties, $object) {
                    foreach ($properties as $name => &$value) {
                        if ("\x00" !== $name) {
                            $object->{$name} = $value;
                            $object->{$name} =& $value;
                            continue;
                        }
                        for ($i = 0; $i < \count($value); ++$i) {
                            $object[$value[$i]] = $value[++$i];
                        }
                    }
                };
        }
        if (!class_exists($class) && !interface_exists($class, \false) && !trait_exists($class, \false)) {
            throw new ClassNotFoundException($class);
        }
        $classReflector = new \ReflectionClass($class);
        switch ($class) {
            case 'ArrayIterator':
            case 'ArrayObject':
                $constructor = $classReflector->getConstructor()->invokeArgs(...);
                return static function ($properties, $object) use ($constructor) {
                    foreach ($properties as $name => &$value) {
                        if ("\x00" === $name) {
                            $constructor($object, $value);
                        } else {
                            $object->{$name} = $value;
                            $object->{$name} =& $value;
                        }
                    }
                };
        }
        if (!$classReflector->isInternal()) {
            $notByRef = new \stdClass();
            foreach ($classReflector->getProperties() as $propertyReflector) {
                if ($propertyReflector->isStatic()) {
                    continue;
                }
                if (\PHP_VERSION_ID >= 80400 && !$propertyReflector->isAbstract() && $propertyReflector->getHooks()) {
                    $notByRef->{$propertyReflector->name} = $propertyReflector->setRawValue(...);
                } elseif ($propertyReflector->isReadOnly()) {
                    $notByRef->{$propertyReflector->name} = static function ($object, $value) use ($propertyReflector) {
                        if (!$propertyReflector->isInitialized($object)) {
                            $propertyReflector->setValue($object, $value);
                        }
                    };
                }
            }
            return $baseHydrator->bindTo($notByRef, $class);
        }
        if ($classReflector->name !== $class) {
            return self::$simpleHydrators[$classReflector->name] ??= self::getSimpleHydrator($classReflector->name);
        }
        $propertySetters = [];
        foreach ($classReflector->getProperties() as $propertyReflector) {
            if (!$propertyReflector->isStatic()) {
                $propertySetters[$propertyReflector->name] = $propertyReflector->setValue(...);
            }
        }
        if (!$propertySetters) {
            return $baseHydrator;
        }
        return static function ($properties, $object) use ($propertySetters) {
            foreach ($properties as $name => &$value) {
                if ($setValue = $propertySetters[$name] ?? null) {
                    $setValue($object, $value);
                } else {
                    $object->{$name} = $value;
                    $object->{$name} =& $value;
                }
            }
        };
    }
    /**
     * @return array
     */
    public static function getPropertyScopes($class)
    {
        $propertyScopes = [];
        $r = new \ReflectionClass($class);
        foreach ($r->getProperties() as $property) {
            $flags = $property->getModifiers();
            if (\ReflectionProperty::IS_STATIC & $flags) {
                continue;
            }
            $name = $property->name;
            $access = $flags << 2 | ($flags & \ReflectionProperty::IS_READONLY ? self::PROPERTY_NOT_BY_REF : 0);
            if (\PHP_VERSION_ID >= 80400 && !$property->isAbstract() && $h = $property->getHooks()) {
                $access |= self::PROPERTY_HAS_HOOKS | (isset($h['get']) && !$h['get']->returnsReference() ? self::PROPERTY_NOT_BY_REF : 0);
            }
            if (\ReflectionProperty::IS_PRIVATE & $flags) {
                $propertyScopes["\x00{$class}\x00{$name}"] = $propertyScopes[$name] = [$class, $name, null, $access, $property];
                continue;
            }
            $propertyScopes[$name] = [$class, $name, null, $access, $property];
            if ($flags & (\PHP_VERSION_ID >= 80400 ? \ReflectionProperty::IS_PRIVATE_SET : \ReflectionProperty::IS_READONLY)) {
                $propertyScopes[$name][2] = $property->class;
            }
            if (\ReflectionProperty::IS_PROTECTED & $flags) {
                $propertyScopes["\x00*\x00{$name}"] = $propertyScopes[$name];
            }
        }
        while ($r = $r->getParentClass()) {
            $class = $r->name;
            foreach ($r->getProperties(\ReflectionProperty::IS_PRIVATE) as $property) {
                $flags = $property->getModifiers();
                if (\ReflectionProperty::IS_STATIC & $flags) {
                    continue;
                }
                $name = $property->name;
                $access = $flags << 2 | ($flags & \ReflectionProperty::IS_READONLY ? self::PROPERTY_NOT_BY_REF : 0);
                if (\PHP_VERSION_ID >= 80400 && $h = $property->getHooks()) {
                    $access |= self::PROPERTY_HAS_HOOKS | (isset($h['get']) && !$h['get']->returnsReference() ? self::PROPERTY_NOT_BY_REF : 0);
                }
                $propertyScopes["\x00{$class}\x00{$name}"] = [$class, $name, null, $access, $property];
                $propertyScopes[$name] ??= $propertyScopes["\x00{$class}\x00{$name}"];
            }
        }
        return $propertyScopes;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\VarExporter\Internal;

use _ContaoManager\Symfony\Component\VarExporter\Exception\ClassNotFoundException;
use _ContaoManager\Symfony\Component\VarExporter\Exception\NotInstantiableTypeException;
/**
 * @author Nicolas Grekas <p@tchwork.com>
 *
 * @internal
 */
class Registry
{
    public static array $reflectors = [];
    public static array $prototypes = [];
    public static array $factories = [];
    public static array $cloneable = [];
    public static array $instantiableWithoutConstructor = [];
    public $classes = [];
    public function __construct(array $classes)
    {
        $this->classes = $classes;
    }
    public static function unserialize($objects, $serializables)
    {
        $unserializeCallback = ini_set('unserialize_callback_func', __CLASS__ . '::getClassReflector');
        try {
            foreach ($serializables as $k => $v) {
                $objects[$k] = unserialize($v);
            }
        } finally {
            ini_set('unserialize_callback_func', $unserializeCallback);
        }
        return $objects;
    }
    public static function p($class)
    {
        self::getClassReflector($class, \true, \true);
        return self::$prototypes[$class];
    }
    public static function f($class)
    {
        $reflector = self::$reflectors[$class] ??= self::getClassReflector($class, \true, \false);
        return self::$factories[$class] = [$reflector, 'newInstanceWithoutConstructor'](...);
    }
    public static function getClassReflector($class, $instantiableWithoutConstructor = \false, $cloneable = null)
    {
        if (!($isClass = class_exists($class)) && !interface_exists($class, \false) && !trait_exists($class, \false)) {
            throw new ClassNotFoundException($class);
        }
        $reflector = new \ReflectionClass($class);
        if ($instantiableWithoutConstructor) {
            $proto = $reflector->newInstanceWithoutConstructor();
        } elseif (!$isClass || $reflector->isAbstract()) {
            throw new NotInstantiableTypeException($class);
        } elseif ($reflector->name !== $class) {
            $reflector = self::$reflectors[$name = $reflector->name] ??= self::getClassReflector($name, \false, $cloneable);
            self::$cloneable[$class] = self::$cloneable[$name];
            self::$instantiableWithoutConstructor[$class] = self::$instantiableWithoutConstructor[$name];
            self::$prototypes[$class] = self::$prototypes[$name];
            return $reflector;
        } else {
            try {
                $proto = $reflector->newInstanceWithoutConstructor();
                $instantiableWithoutConstructor = \true;
            } catch (\ReflectionException) {
                $proto = $reflector->implementsInterface('Serializable') && !method_exists($class, '__unserialize') ? 'C:' : 'O:';
                if ('C:' === $proto && !$reflector->getMethod('unserialize')->isInternal()) {
                    $proto = null;
                } else {
                    try {
                        $proto = @unserialize($proto . \strlen($class) . ':"' . $class . '":0:{}');
                    } catch (\Exception $e) {
                        if (__FILE__ !== $e->getFile()) {
                            throw $e;
                        }
                        throw new NotInstantiableTypeException($class, $e);
                    }
                    if (\false === $proto) {
                        throw new NotInstantiableTypeException($class);
                    }
                }
            }
            if (null !== $proto && !$proto instanceof \Throwable && !$proto instanceof \Serializable && !method_exists($class, '__sleep') && !method_exists($class, '__serialize')) {
                try {
                    serialize($proto);
                } catch (\Exception $e) {
                    throw new NotInstantiableTypeException($class, $e);
                }
            }
        }
        if (null === $cloneable) {
            if (($proto instanceof \Reflector || $proto instanceof \ReflectionGenerator || $proto instanceof \ReflectionType || $proto instanceof \IteratorIterator || $proto instanceof \RecursiveIteratorIterator) && (!$proto instanceof \Serializable && !method_exists($proto, '__wakeup') && !method_exists($class, '__unserialize'))) {
                throw new NotInstantiableTypeException($class);
            }
            $cloneable = $reflector->isCloneable() && !$reflector->hasMethod('__clone');
        }
        self::$cloneable[$class] = $cloneable;
        self::$instantiableWithoutConstructor[$class] = $instantiableWithoutConstructor;
        self::$prototypes[$class] = $proto;
        if ($proto instanceof \Throwable) {
            static $setTrace;
            if (null === $setTrace) {
                $setTrace = [new \ReflectionProperty(\Error::class, 'trace'), new \ReflectionProperty(\Exception::class, 'trace')];
                $setTrace[0] = $setTrace[0]->setValue(...);
                $setTrace[1] = $setTrace[1]->setValue(...);
            }
            $setTrace[$proto instanceof \Exception]($proto, []);
        }
        return $reflector;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\VarExporter\Internal;

/**
 * @author Nicolas Grekas <p@tchwork.com>
 *
 * @internal
 */
class Reference
{
    public int $count = 0;
    public function __construct(public readonly int $id, public readonly mixed $value = null)
    {
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\VarExporter\Internal;

use _ContaoManager\Symfony\Component\VarExporter\Exception\NotInstantiableTypeException;
/**
 * @author Nicolas Grekas <p@tchwork.com>
 *
 * @internal
 */
class Exporter
{
    /**
     * Prepares an array of values for VarExporter.
     *
     * For performance this method is public and has no type-hints.
     *
     * @param array             &$values
     * @param \SplObjectStorage $objectsPool
     * @param array             &$refsPool
     * @param int               &$objectsCount
     * @param bool              &$valuesAreStatic
     *
     * @return array
     *
     * @throws NotInstantiableTypeException When a value cannot be serialized
     */
    public static function prepare($values, $objectsPool, &$refsPool, &$objectsCount, &$valuesAreStatic)
    {
        $refs = $values;
        foreach ($values as $k => $value) {
            if (\is_resource($value)) {
                throw new NotInstantiableTypeException(get_resource_type($value) . ' resource');
            }
            $refs[$k] = $objectsPool;
            if ($isRef = !$valueIsStatic = $values[$k] !== $objectsPool) {
                $values[$k] =& $value;
                // Break hard references to make $values completely
                unset($value);
                // independent from the original structure
                $refs[$k] = $value = $values[$k];
                if ($value instanceof Reference && 0 > $value->id) {
                    $valuesAreStatic = \false;
                    ++$value->count;
                    continue;
                }
                $refsPool[] = [&$refs[$k], $value, &$value];
                $refs[$k] = $values[$k] = new Reference(-\count($refsPool), $value);
            }
            if (\is_array($value)) {
                if ($value) {
                    $value = self::prepare($value, $objectsPool, $refsPool, $objectsCount, $valueIsStatic);
                }
                goto handle_value;
            } elseif (!\is_object($value) || $value instanceof \UnitEnum) {
                goto handle_value;
            }
            $valueIsStatic = \false;
            if (isset($objectsPool[$value])) {
                ++$objectsCount;
                $value = new Reference($objectsPool[$value][0]);
                goto handle_value;
            }
            $class = $value::class;
            $reflector = Registry::$reflectors[$class] ??= Registry::getClassReflector($class);
            $properties = [];
            $sleep = null;
            $proto = Registry::$prototypes[$class];
            if ($reflector->hasMethod('__serialize')) {
                if (!$reflector->getMethod('__serialize')->isPublic()) {
                    throw new \Error(\sprintf('Call to %s method "%s::__serialize()".', $reflector->getMethod('__serialize')->isProtected() ? 'protected' : 'private', $class));
                }
                if (!\is_array($arrayValue = $value->__serialize())) {
                    throw new \TypeError($class . '::__serialize() must return an array');
                }
                if ($reflector->hasMethod('__unserialize')) {
                    $properties = $arrayValue;
                    goto prepare_value;
                }
            } elseif (($value instanceof \ArrayIterator || $value instanceof \ArrayObject) && null !== $proto) {
                // ArrayIterator and ArrayObject need special care because their "flags"
                // option changes the behavior of the (array) casting operator.
                [$arrayValue, $properties] = self::getArrayObjectProperties($value, $proto);
                // populates Registry::$prototypes[$class] with a new instance
                Registry::getClassReflector($class, Registry::$instantiableWithoutConstructor[$class], Registry::$cloneable[$class]);
            } elseif ($value instanceof \SplObjectStorage && Registry::$cloneable[$class] && null !== $proto) {
                // By implementing Serializable, SplObjectStorage breaks
                // internal references; let's deal with it on our own.
                foreach (clone $value as $v) {
                    $properties[] = $v;
                    $properties[] = $value[$v];
                }
                $properties = ['SplObjectStorage' => ["\x00" => $properties]];
                $arrayValue = (array) $value;
            } elseif ($value instanceof \Serializable || $value instanceof \__PHP_Incomplete_Class || \PHP_VERSION_ID < 80200 && $value instanceof \DatePeriod) {
                ++$objectsCount;
                $objectsPool[$value] = [$id = \count($objectsPool), serialize($value), [], 0];
                $value = new Reference($id);
                goto handle_value;
            } else {
                if (method_exists($class, '__sleep')) {
                    if (!\is_array($sleep = $value->__sleep())) {
                        trigger_error('serialize(): __sleep should return an array only containing the names of instance-variables to serialize', \E_USER_NOTICE);
                        $value = null;
                        goto handle_value;
                    }
                    $sleep = array_flip($sleep);
                }
                $arrayValue = (array) $value;
            }
            $proto = (array) $proto;
            foreach ($arrayValue as $name => $v) {
                $i = 0;
                $n = (string) $name;
                if ('' === $n || "\x00" !== $n[0]) {
                    $parent = $reflector;
                    do {
                        $p = $parent->hasProperty($n) ? $parent->getProperty($n) : null;
                    } while (!$p && $parent = $parent->getParentClass());
                    $c = $p && (!$p->isPublic() || (\PHP_VERSION_ID >= 80400 ? $p->isProtectedSet() || $p->isPrivateSet() : $p->isReadOnly())) ? $p->class : 'stdClass';
                } elseif ('*' === $n[1]) {
                    $n = substr($n, 3);
                    $c = $reflector->getProperty($n)->class;
                } else {
                    $i = strpos($n, "\x00", 2);
                    $c = substr($n, 1, $i - 1);
                    $n = substr($n, 1 + $i);
                }
                if (null !== $sleep) {
                    if (!isset($sleep[$name]) && (!isset($sleep[$n]) || $i && $c !== $class)) {
                        unset($arrayValue[$name]);
                        continue;
                    }
                    unset($sleep[$name], $sleep[$n]);
                }
                if ("\x00Error\x00trace" === $name || "\x00Exception\x00trace" === $name) {
                    $properties[$c][$n] = $v;
                } elseif (!\array_key_exists($name, $proto) || $proto[$name] !== $v) {
                    $properties[match ($c) {
                        'Error' => 'TypeError',
                        'Exception' => 'ErrorException',
                        default => $c,
                    }][$n] = $v;
                }
            }
            if ($sleep) {
                foreach ($sleep as $n => $v) {
                    trigger_error(\sprintf('serialize(): "%s" returned as member variable from __sleep() but does not exist', $n), \E_USER_NOTICE);
                }
            }
            if (method_exists($class, '__unserialize')) {
                $properties = $arrayValue;
            }
            prepare_value:
            $objectsPool[$value] = [$id = \count($objectsPool)];
            $properties = self::prepare($properties, $objectsPool, $refsPool, $objectsCount, $valueIsStatic);
            ++$objectsCount;
            $objectsPool[$value] = [$id, $class, $properties, method_exists($class, '__unserialize') ? -$objectsCount : (method_exists($class, '__wakeup') ? $objectsCount : 0)];
            $value = new Reference($id);
            handle_value:
            if ($isRef) {
                unset($value);
                // Break the hard reference created above
            } elseif (!$valueIsStatic) {
                $values[$k] = $value;
            }
            $valuesAreStatic = $valueIsStatic && $valuesAreStatic;
        }
        return $values;
    }
    public static function export($value, $indent = '')
    {
        switch (\true) {
            case \is_int($value) || \is_float($value):
                return var_export($value, \true);
            case [] === $value:
                return '[]';
            case \false === $value:
                return 'false';
            case \true === $value:
                return 'true';
            case null === $value:
                return 'null';
            case '' === $value:
                return "''";
            case $value instanceof \UnitEnum:
                return '\\' . ltrim(var_export($value, \true), '\\');
        }
        if ($value instanceof Reference) {
            if (0 <= $value->id) {
                return '$o[' . $value->id . ']';
            }
            if (!$value->count) {
                return self::export($value->value, $indent);
            }
            $value = -$value->id;
            return '&$r[' . $value . ']';
        }
        $subIndent = $indent . '    ';
        if (\is_string($value)) {
            $code = \sprintf("'%s'", addcslashes($value, "'\\"));
            $code = preg_replace_callback("/((?:[\\0\\r\\n]|‪|‫|‭|‮|⁦|⁧|⁨|‬|⁩)++)(.)/", function ($m) use ($subIndent) {
                $m[1] = \sprintf('\'."%s".\'', str_replace(["\x00", "\r", "\n", "‪", "‫", "‭", "‮", "⁦", "⁧", "⁨", "‬", "⁩", '\n\\'], ['\0', '\r', '\n', '\u{202A}', '\u{202B}', '\u{202D}', '\u{202E}', '\u{2066}', '\u{2067}', '\u{2068}', '\u{202C}', '\u{2069}', '\n"' . "\n" . $subIndent . '."\\'], $m[1]));
                if ("'" === $m[2]) {
                    return substr($m[1], 0, -2);
                }
                if (str_ends_with($m[1], 'n".\'')) {
                    return substr_replace($m[1], "\n" . $subIndent . ".'" . $m[2], -2);
                }
                return $m[1] . $m[2];
            }, $code, -1, $count);
            if ($count && str_starts_with($code, "''.")) {
                $code = substr($code, 3);
            }
            return $code;
        }
        if (\is_array($value)) {
            $j = -1;
            $code = '';
            foreach ($value as $k => $v) {
                $code .= $subIndent;
                if (!\is_int($k) || 1 !== $k - $j) {
                    $code .= self::export($k, $subIndent) . ' => ';
                }
                if (\is_int($k) && $k > $j) {
                    $j = $k;
                }
                $code .= self::export($v, $subIndent) . ",\n";
            }
            return "[\n" . $code . $indent . ']';
        }
        if ($value instanceof Values) {
            $code = $subIndent . "\$r = [],\n";
            foreach ($value->values as $k => $v) {
                $code .= $subIndent . '$r[' . $k . '] = ' . self::export($v, $subIndent) . ",\n";
            }
            return "[\n" . $code . $indent . ']';
        }
        if ($value instanceof Registry) {
            return self::exportRegistry($value, $indent, $subIndent);
        }
        if ($value instanceof Hydrator) {
            return self::exportHydrator($value, $indent, $subIndent);
        }
        throw new \UnexpectedValueException(\sprintf('Cannot export value of type "%s".', get_debug_type($value)));
    }
    private static function exportRegistry(Registry $value, string $indent, string $subIndent): string
    {
        $code = '';
        $serializables = [];
        $seen = [];
        $prototypesAccess = 0;
        $factoriesAccess = 0;
        $r = '\\' . Registry::class;
        $j = -1;
        foreach ($value->classes as $k => $class) {
            if (':' === ($class[1] ?? null)) {
                $serializables[$k] = $class;
                continue;
            }
            if (!Registry::$instantiableWithoutConstructor[$class]) {
                if (is_subclass_of($class, 'Serializable') && !method_exists($class, '__unserialize')) {
                    $serializables[$k] = 'C:' . \strlen($class) . ':"' . $class . '":0:{}';
                } else {
                    $serializables[$k] = 'O:' . \strlen($class) . ':"' . $class . '":0:{}';
                }
                if (is_subclass_of($class, 'Throwable')) {
                    $eol = is_subclass_of($class, 'Error') ? "\x00Error\x00" : "\x00Exception\x00";
                    $serializables[$k] = substr_replace($serializables[$k], '1:{s:' . (5 + \strlen($eol)) . ':"' . $eol . 'trace";a:0:{}}', -4);
                }
                continue;
            }
            $code .= $subIndent . (1 !== $k - $j ? $k . ' => ' : '');
            $j = $k;
            $eol = ",\n";
            $c = '[' . self::export($class) . ']';
            if ($seen[$class] ?? \false) {
                if (Registry::$cloneable[$class]) {
                    ++$prototypesAccess;
                    $code .= 'clone $p' . $c;
                } else {
                    ++$factoriesAccess;
                    $code .= '$f' . $c . '()';
                }
            } else {
                $seen[$class] = \true;
                if (Registry::$cloneable[$class]) {
                    $code .= 'clone (' . ($prototypesAccess++ ? '$p' : '($p = &' . $r . '::$prototypes)') . $c . ' ?? ' . $r . '::p';
                } else {
                    $code .= '(' . ($factoriesAccess++ ? '$f' : '($f = &' . $r . '::$factories)') . $c . ' ?? ' . $r . '::f';
                    $eol = '()' . $eol;
                }
                $code .= '(' . substr($c, 1, -1) . '))';
            }
            $code .= $eol;
        }
        if (1 === $prototypesAccess) {
            $code = str_replace('($p = &' . $r . '::$prototypes)', $r . '::$prototypes', $code);
        }
        if (1 === $factoriesAccess) {
            $code = str_replace('($f = &' . $r . '::$factories)', $r . '::$factories', $code);
        }
        if ('' !== $code) {
            $code = "\n" . $code . $indent;
        }
        if ($serializables) {
            $code = $r . '::unserialize([' . $code . '], ' . self::export($serializables, $indent) . ')';
        } else {
            $code = '[' . $code . ']';
        }
        return '$o = ' . $code;
    }
    private static function exportHydrator(Hydrator $value, string $indent, string $subIndent): string
    {
        $code = '';
        foreach ($value->properties as $class => $properties) {
            $code .= $subIndent . '    ' . self::export($class) . ' => ' . self::export($properties, $subIndent . '    ') . ",\n";
        }
        $code = [self::export($value->registry, $subIndent), self::export($value->values, $subIndent), '' !== $code ? "[\n" . $code . $subIndent . ']' : '[]', self::export($value->value, $subIndent), self::export($value->wakeups, $subIndent)];
        return '\\' . $value::class . "::hydrate(\n" . $subIndent . implode(",\n" . $subIndent, $code) . "\n" . $indent . ')';
    }
    /**
     * @param \ArrayIterator|\ArrayObject $value
     * @param \ArrayIterator|\ArrayObject $proto
     */
    private static function getArrayObjectProperties($value, $proto): array
    {
        $reflector = $value instanceof \ArrayIterator ? 'ArrayIterator' : 'ArrayObject';
        $reflector = Registry::$reflectors[$reflector] ??= Registry::getClassReflector($reflector);
        $properties = [$arrayValue = (array) $value, $reflector->getMethod('getFlags')->invoke($value), $value instanceof \ArrayObject ? $reflector->getMethod('getIteratorClass')->invoke($value) : 'ArrayIterator'];
        $reflector = $reflector->getMethod('setFlags');
        $reflector->invoke($proto, \ArrayObject::STD_PROP_LIST);
        if ($properties[1] & \ArrayObject::STD_PROP_LIST) {
            $reflector->invoke($value, 0);
            $properties[0] = (array) $value;
        } else {
            $reflector->invoke($value, \ArrayObject::STD_PROP_LIST);
            $arrayValue = (array) $value;
        }
        $reflector->invoke($value, $properties[1]);
        if ([[], 0, 'ArrayIterator'] === $properties) {
            $properties = [];
        } else {
            if ('ArrayIterator' === $properties[2]) {
                unset($properties[2]);
            }
            $properties = [$reflector->class => ["\x00" => $properties]];
        }
        return [$arrayValue, $properties];
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\VarExporter;

use _ContaoManager\Symfony\Component\Serializer\Attribute\Ignore;
use _ContaoManager\Symfony\Component\VarExporter\Internal\Hydrator;
use _ContaoManager\Symfony\Component\VarExporter\Internal\LazyObjectRegistry as Registry;
use _ContaoManager\Symfony\Component\VarExporter\Internal\LazyObjectState;
use _ContaoManager\Symfony\Component\VarExporter\Internal\LazyObjectTrait;
trait LazyGhostTrait
{
    use LazyObjectTrait;
    /**
     * Creates a lazy-loading ghost instance.
     *
     * Skipped properties should be indexed by their array-cast identifier, see
     * https://php.net/manual/language.types.array#language.types.array.casting
     *
     * @param (\Closure(static):void   $initializer       The closure should initialize the object it receives as argument
     * @param array<string, true>|null $skippedProperties An array indexed by the properties to skip, a.k.a. the ones
     *                                                    that the initializer doesn't initialize, if any
     * @param static|null              $instance
     */
    public static function createLazyGhost(\Closure|array $initializer, ?array $skippedProperties = null, ?object $instance = null): static
    {
        if (\is_array($initializer)) {
            trigger_deprecation('symfony/var-exporter', '6.4', 'Per-property lazy-initializers are deprecated and won\'t be supported anymore in 7.0, use an object initializer instead.');
        }
        $onlyProperties = null === $skippedProperties && \is_array($initializer) ? $initializer : null;
        if (self::class !== $class = $instance ? $instance::class : static::class) {
            $skippedProperties["\x00" . self::class . "\x00lazyObjectState"] = \true;
        } elseif (\defined($class . '::LAZY_OBJECT_PROPERTY_SCOPES')) {
            Hydrator::$propertyScopes[$class] ??= $class::LAZY_OBJECT_PROPERTY_SCOPES;
        }
        $instance ??= (Registry::$classReflectors[$class] ??= new \ReflectionClass($class))->newInstanceWithoutConstructor();
        Registry::$defaultProperties[$class] ??= (array) $instance;
        $instance->lazyObjectState = new LazyObjectState($initializer, $skippedProperties ??= []);
        foreach (Registry::$classResetters[$class] ??= Registry::getClassResetters($class) as $reset) {
            $reset($instance, $skippedProperties, $onlyProperties);
        }
        return $instance;
    }
    /**
     * Returns whether the object is initialized.
     *
     * @param $partial Whether partially initialized objects should be considered as initialized
     */
    #[Ignore]
    public function isLazyObjectInitialized(bool $partial = \false): bool
    {
        if (!$state = $this->lazyObjectState ?? null) {
            return \true;
        }
        if (!\is_array($state->initializer)) {
            return LazyObjectState::STATUS_INITIALIZED_FULL === $state->status;
        }
        $class = $this::class;
        $properties = (array) $this;
        if ($partial) {
            return (bool) array_intersect_key($state->initializer, $properties);
        }
        $propertyScopes = Hydrator::$propertyScopes[$class] ??= Hydrator::getPropertyScopes($class);
        foreach ($state->initializer as $key => $initializer) {
            if (!\array_key_exists($key, $properties) && isset($propertyScopes[$key])) {
                return \false;
            }
        }
        return \true;
    }
    /**
     * Forces initialization of a lazy object and returns it.
     */
    public function initializeLazyObject(): static
    {
        if (!$state = $this->lazyObjectState ?? null) {
            return $this;
        }
        if (!\is_array($state->initializer)) {
            if (LazyObjectState::STATUS_UNINITIALIZED_FULL === $state->status) {
                $state->initialize($this, '', null);
            }
            return $this;
        }
        $values = isset($state->initializer["\x00"]) ? null : [];
        $class = $this::class;
        $properties = (array) $this;
        $propertyScopes = Hydrator::$propertyScopes[$class] ??= Hydrator::getPropertyScopes($class);
        foreach ($state->initializer as $key => $initializer) {
            if (\array_key_exists($key, $properties) || ![$scope, $name, $writeScope] = $propertyScopes[$key] ?? null) {
                continue;
            }
            $scope = $writeScope ?? $scope;
            if (null === $values) {
                if (!\is_array($values = $state->initializer["\x00"]($this, Registry::$defaultProperties[$class]))) {
                    throw new \TypeError(\sprintf('The lazy-initializer defined for instance of "%s" must return an array, got "%s".', $class, get_debug_type($values)));
                }
                if (\array_key_exists($key, $properties = (array) $this)) {
                    continue;
                }
            }
            if (\array_key_exists($key, $values)) {
                $accessor = Registry::$classAccessors[$scope] ??= Registry::getClassAccessors($scope);
                $accessor['set']($this, $name, $properties[$key] = $values[$key]);
            } else {
                $state->initialize($this, $name, $scope);
                $properties = (array) $this;
            }
        }
        return $this;
    }
    /**
     * @return bool Returns false when the object cannot be reset, ie when it's not a lazy object
     */
    public function resetLazyObject(): bool
    {
        if (!$state = $this->lazyObjectState ?? null) {
            return \false;
        }
        if (LazyObjectState::STATUS_UNINITIALIZED_FULL !== $state->status) {
            $state->reset($this);
        }
        return \true;
    }
    public function &__get($name): mixed
    {
        $propertyScopes = Hydrator::$propertyScopes[$this::class] ??= Hydrator::getPropertyScopes($this::class);
        $scope = null;
        $notByRef = 0;
        if ([$class, , $writeScope, $access] = $propertyScopes[$name] ?? null) {
            $scope = Registry::getScopeForRead($propertyScopes, $class, $name);
            $state = $this->lazyObjectState ?? null;
            if ($state && (null === $scope || isset($propertyScopes["\x00{$scope}\x00{$name}"]))) {
                $notByRef = $access & Hydrator::PROPERTY_NOT_BY_REF;
                if (LazyObjectState::STATUS_INITIALIZED_FULL === $state->status) {
                    // Work around php/php-src#12695
                    $property = null === $scope ? $name : "\x00{$scope}\x00{$name}";
                    $property = $propertyScopes[$property][4] ?? Hydrator::$propertyScopes[$this::class][$property][4] = new \ReflectionProperty($scope ?? $class, $name);
                } else {
                    $property = null;
                }
                if (\PHP_VERSION_ID >= 80400 && !$notByRef && $access >> 2 & \ReflectionProperty::IS_PRIVATE_SET) {
                    $scope ??= $writeScope;
                }
                if ($property?->isInitialized($this) ?? LazyObjectState::STATUS_UNINITIALIZED_PARTIAL !== $state->initialize($this, $name, $writeScope ?? $scope)) {
                    goto get_in_scope;
                }
            }
        }
        if ($parent = (Registry::$parentMethods[self::class] ??= Registry::getParentMethods(self::class))['get']) {
            if (2 === $parent) {
                return parent::__get($name);
            }
            $value = parent::__get($name);
            return $value;
        }
        if (null === $class) {
            $frame = debug_backtrace(\DEBUG_BACKTRACE_IGNORE_ARGS, 1)[0];
            trigger_error(\sprintf('Undefined property: %s::$%s in %s on line %s', $this::class, $name, $frame['file'], $frame['line']), \E_USER_NOTICE);
        }
        get_in_scope:
        try {
            if (null === $scope) {
                if (!$notByRef) {
                    return $this->{$name};
                }
                $value = $this->{$name};
                return $value;
            }
            $accessor = Registry::$classAccessors[$scope] ??= Registry::getClassAccessors($scope);
            return $accessor['get']($this, $name, $notByRef);
        } catch (\Error $e) {
            if (\Error::class !== $e::class || !str_starts_with($e->getMessage(), 'Cannot access uninitialized non-nullable property')) {
                throw $e;
            }
            try {
                if (null === $scope) {
                    $this->{$name} = [];
                    return $this->{$name};
                }
                $accessor['set']($this, $name, []);
                return $accessor['get']($this, $name, $notByRef);
            } catch (\Error) {
                if (preg_match('/^Cannot access uninitialized non-nullable property ([^ ]++) by reference$/', $e->getMessage(), $matches)) {
                    throw new \Error('Typed property ' . $matches[1] . ' must not be accessed before initialization', $e->getCode(), $e->getPrevious());
                }
                throw $e;
            }
        }
    }
    public function __set($name, $value): void
    {
        $propertyScopes = Hydrator::$propertyScopes[$this::class] ??= Hydrator::getPropertyScopes($this::class);
        $scope = null;
        if ([$class, , $writeScope, $access] = $propertyScopes[$name] ?? null) {
            $scope = Registry::getScopeForWrite($propertyScopes, $class, $name, $access >> 2);
            $state = $this->lazyObjectState ?? null;
            if ($state && ($writeScope === $scope || isset($propertyScopes["\x00{$scope}\x00{$name}"])) && LazyObjectState::STATUS_INITIALIZED_FULL !== $state->status) {
                if (LazyObjectState::STATUS_UNINITIALIZED_FULL === $state->status) {
                    $state->initialize($this, $name, $writeScope ?? $scope);
                }
                goto set_in_scope;
            }
        }
        if ((Registry::$parentMethods[self::class] ??= Registry::getParentMethods(self::class))['set']) {
            parent::__set($name, $value);
            return;
        }
        set_in_scope:
        if (null === $scope) {
            $this->{$name} = $value;
        } else {
            $accessor = Registry::$classAccessors[$scope] ??= Registry::getClassAccessors($scope);
            $accessor['set']($this, $name, $value);
        }
    }
    public function __isset($name): bool
    {
        $propertyScopes = Hydrator::$propertyScopes[$this::class] ??= Hydrator::getPropertyScopes($this::class);
        $scope = null;
        if ([$class, , $writeScope] = $propertyScopes[$name] ?? null) {
            $scope = Registry::getScopeForRead($propertyScopes, $class, $name);
            $state = $this->lazyObjectState ?? null;
            if ($state && (null === $scope || isset($propertyScopes["\x00{$scope}\x00{$name}"])) && LazyObjectState::STATUS_INITIALIZED_FULL !== $state->status && LazyObjectState::STATUS_UNINITIALIZED_PARTIAL !== $state->initialize($this, $name, $writeScope ?? $scope)) {
                goto isset_in_scope;
            }
        }
        if ((Registry::$parentMethods[self::class] ??= Registry::getParentMethods(self::class))['isset']) {
            return parent::__isset($name);
        }
        isset_in_scope:
        if (null === $scope) {
            return isset($this->{$name});
        }
        $accessor = Registry::$classAccessors[$scope] ??= Registry::getClassAccessors($scope);
        return $accessor['isset']($this, $name);
    }
    public function __unset($name): void
    {
        $propertyScopes = Hydrator::$propertyScopes[$this::class] ??= Hydrator::getPropertyScopes($this::class);
        $scope = null;
        if ([$class, , $writeScope, $access] = $propertyScopes[$name] ?? null) {
            $scope = Registry::getScopeForWrite($propertyScopes, $class, $name, $access >> 2);
            $state = $this->lazyObjectState ?? null;
            if ($state && ($writeScope === $scope || isset($propertyScopes["\x00{$scope}\x00{$name}"])) && LazyObjectState::STATUS_INITIALIZED_FULL !== $state->status) {
                if (LazyObjectState::STATUS_UNINITIALIZED_FULL === $state->status) {
                    $state->initialize($this, $name, $writeScope ?? $scope);
                }
                goto unset_in_scope;
            }
        }
        if ((Registry::$parentMethods[self::class] ??= Registry::getParentMethods(self::class))['unset']) {
            parent::__unset($name);
            return;
        }
        unset_in_scope:
        if (null === $scope) {
            unset($this->{$name});
        } else {
            $accessor = Registry::$classAccessors[$scope] ??= Registry::getClassAccessors($scope);
            $accessor['unset']($this, $name);
        }
    }
    public function __clone(): void
    {
        if ($state = $this->lazyObjectState ?? null) {
            $this->lazyObjectState = clone $state;
        }
        if ((Registry::$parentMethods[self::class] ??= Registry::getParentMethods(self::class))['clone']) {
            parent::__clone();
        }
    }
    public function __serialize(): array
    {
        $class = self::class;
        if ((Registry::$parentMethods[$class] ??= Registry::getParentMethods($class))['serialize']) {
            $properties = parent::__serialize();
        } else {
            $this->initializeLazyObject();
            $properties = (array) $this;
        }
        unset($properties["\x00{$class}\x00lazyObjectState"]);
        if (Registry::$parentMethods[$class]['serialize'] || !Registry::$parentMethods[$class]['sleep']) {
            return $properties;
        }
        $scope = get_parent_class($class);
        $data = [];
        foreach (parent::__sleep() as $name) {
            $value = $properties[$k = $name] ?? $properties[$k = "\x00*\x00{$name}"] ?? $properties[$k = "\x00{$class}\x00{$name}"] ?? $properties[$k = "\x00{$scope}\x00{$name}"] ?? $k = null;
            if (null === $k) {
                trigger_error(\sprintf('serialize(): "%s" returned as member variable from __sleep() but does not exist', $name), \E_USER_NOTICE);
            } else {
                $data[$k] = $value;
            }
        }
        return $data;
    }
    public function __destruct()
    {
        $state = $this->lazyObjectState ?? null;
        if ($state && \in_array($state->status, [LazyObjectState::STATUS_UNINITIALIZED_FULL, LazyObjectState::STATUS_UNINITIALIZED_PARTIAL], \true)) {
            return;
        }
        if ((Registry::$parentMethods[self::class] ??= Registry::getParentMethods(self::class))['destruct']) {
            parent::__destruct();
        }
    }
    #[Ignore]
    private function setLazyObjectAsInitialized(bool $initialized): void
    {
        $state = $this->lazyObjectState ?? null;
        if ($state && !\is_array($state->initializer)) {
            $state->status = $initialized ? LazyObjectState::STATUS_INITIALIZED_FULL : LazyObjectState::STATUS_UNINITIALIZED_FULL;
        }
    }
}
VarExporter Component
=====================

The VarExporter component provides various tools to deal with the internal state
of objects:

- `VarExporter::export()` allows exporting any serializable PHP data structure to
  plain PHP code. While doing so, it preserves all the semantics associated with
  the serialization mechanism of PHP (`__wakeup`, `__sleep`, `Serializable`,
  `__serialize`, `__unserialize`);
- `Instantiator::instantiate()` creates an object and sets its properties without
  calling its constructor nor any other methods;
- `Hydrator::hydrate()` can set the properties of an existing object;
- `Lazy*Trait` can make a class behave as a lazy-loading ghost or virtual proxy.

VarExporter::export()
---------------------

The reason to use `VarExporter::export()` *vs* `serialize()` or
[igbinary](https://github.com/igbinary/igbinary) is performance: thanks to
OPcache, the resulting code is significantly faster and more memory efficient
than using `unserialize()` or `igbinary_unserialize()`.

Unlike `var_export()`, this works on any serializable PHP value.

It also provides a few improvements over `var_export()`/`serialize()`:

 * the output is PSR-2 compatible;
 * the output can be re-indented without messing up with `\r` or `\n` in the data;
 * missing classes throw a `ClassNotFoundException` instead of being unserialized
   to `PHP_Incomplete_Class` objects;
 * references involving `SplObjectStorage`, `ArrayObject` or `ArrayIterator`
   instances are preserved;
 * `Reflection*`, `IteratorIterator` and `RecursiveIteratorIterator` classes
   throw an exception when being serialized (their unserialized version is broken
   anyway, see https://bugs.php.net/76737).

Instantiator and Hydrator
-------------------------

`Instantiator::instantiate($class)` creates an object of the given class without
calling its constructor nor any other methods.

`Hydrator::hydrate()` sets the properties of an existing object, including
private and protected ones. For example:

```php
// Sets the public or protected $object->propertyName property
Hydrator::hydrate($object, ['propertyName' => $propertyValue]);

// Sets a private property defined on its parent Bar class:
Hydrator::hydrate($object, ["\0Bar\0privateBarProperty" => $propertyValue]);

// Alternative way to set the private $object->privateBarProperty property
Hydrator::hydrate($object, [], [
    Bar::class => ['privateBarProperty' => $propertyValue],
]);
```

`Lazy*Trait`
------------

The component provides two lazy-loading patterns: ghost objects and virtual
proxies (see https://martinfowler.com/eaaCatalog/lazyLoad.html for reference).

Ghost objects work only with concrete and non-internal classes. In the generic
case, they are not compatible with using factories in their initializer.

Virtual proxies work with concrete, abstract or internal classes. They provide an
API that looks like the actual objects and forward calls to them. They can cause
identity problems because proxies might not be seen as equivalents to the actual
objects they proxy.

Because of this identity problem, ghost objects should be preferred when
possible. Exceptions thrown by the `ProxyHelper` class can help decide when it
can be used or not.

Ghost objects and virtual proxies both provide implementations for the
`LazyObjectInterface` which allows resetting them to their initial state or to
forcibly initialize them when needed. Note that resetting a ghost object skips
its read-only properties. You should use a virtual proxy to reset read-only
properties.

### `LazyGhostTrait`

By using `LazyGhostTrait` either directly in your classes or by using
`ProxyHelper::generateLazyGhost()`, you can make their instances lazy-loadable.
This works by creating these instances empty and by computing their state only
when accessing a property.

```php
class FooLazyGhost extends Foo
{
    use LazyGhostTrait;
}

$foo = FooLazyGhost::createLazyGhost(initializer: function (Foo $instance): void {
    // [...] Use whatever heavy logic you need here
    // to compute the $dependencies of the $instance
    $instance->__construct(...$dependencies);
    // [...] Call setters, etc. if needed
});

// $foo is now a lazy-loading ghost object. The initializer will
// be called only when and if a *property* is accessed.
```

### `LazyProxyTrait`

Alternatively, `LazyProxyTrait` can be used to create virtual proxies:

```php
$proxyCode = ProxyHelper::generateLazyProxy(new ReflectionClass(Foo::class));
// $proxyCode contains the reference to LazyProxyTrait
// and should be dumped into a file in production envs
eval('class FooLazyProxy'.$proxyCode);

$foo = FooLazyProxy::createLazyProxy(initializer: function (): Foo {
    // [...] Use whatever heavy logic you need here
    // to compute the $dependencies of the $instance
    $instance = new Foo(...$dependencies);
    // [...] Call setters, etc. if needed

    return $instance;
});
// $foo is now a lazy-loading virtual proxy object. The initializer will
// be called only when and if a *method* is called.
```

Resources
---------

 * [Documentation](https://symfony.com/doc/current/components/var_exporter.html)
 * [Contributing](https://symfony.com/doc/current/contributing/index.html)
 * [Report issues](https://github.com/symfony/symfony/issues) and
   [send Pull Requests](https://github.com/symfony/symfony/pulls)
   in the [main Symfony repository](https://github.com/symfony/symfony)
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\VarExporter;

use _ContaoManager\Symfony\Component\Serializer\Attribute\Ignore;
use _ContaoManager\Symfony\Component\VarExporter\Hydrator as PublicHydrator;
use _ContaoManager\Symfony\Component\VarExporter\Internal\Hydrator;
use _ContaoManager\Symfony\Component\VarExporter\Internal\LazyObjectRegistry as Registry;
use _ContaoManager\Symfony\Component\VarExporter\Internal\LazyObjectState;
use _ContaoManager\Symfony\Component\VarExporter\Internal\LazyObjectTrait;
trait LazyProxyTrait
{
    use LazyObjectTrait;
    /**
     * Creates a lazy-loading virtual proxy.
     *
     * @param \Closure():object $initializer Returns the proxied object
     * @param static|null       $instance
     */
    public static function createLazyProxy(\Closure $initializer, ?object $instance = null): static
    {
        if (self::class !== $class = $instance ? $instance::class : static::class) {
            $skippedProperties = ["\x00" . self::class . "\x00lazyObjectState" => \true];
        } elseif (\defined($class . '::LAZY_OBJECT_PROPERTY_SCOPES')) {
            Hydrator::$propertyScopes[$class] ??= $class::LAZY_OBJECT_PROPERTY_SCOPES;
        }
        $instance ??= (Registry::$classReflectors[$class] ??= new \ReflectionClass($class))->newInstanceWithoutConstructor();
        $instance->lazyObjectState = new LazyObjectState($initializer);
        foreach (Registry::$classResetters[$class] ??= Registry::getClassResetters($class) as $reset) {
            $reset($instance, $skippedProperties ??= []);
        }
        return $instance;
    }
    /**
     * Returns whether the object is initialized.
     *
     * @param $partial Whether partially initialized objects should be considered as initialized
     */
    #[Ignore]
    public function isLazyObjectInitialized(bool $partial = \false): bool
    {
        return !isset($this->lazyObjectState) || isset($this->lazyObjectState->realInstance) || Registry::$noInitializerState === $this->lazyObjectState->initializer;
    }
    /**
     * Forces initialization of a lazy object and returns it.
     */
    public function initializeLazyObject(): parent
    {
        if ($state = $this->lazyObjectState ?? null) {
            return $state->realInstance ??= ($state->initializer)();
        }
        return $this;
    }
    /**
     * @return bool Returns false when the object cannot be reset, ie when it's not a lazy object
     */
    public function resetLazyObject(): bool
    {
        if (!isset($this->lazyObjectState) || Registry::$noInitializerState === $this->lazyObjectState->initializer) {
            return \false;
        }
        unset($this->lazyObjectState->realInstance);
        return \true;
    }
    public function &__get($name): mixed
    {
        $propertyScopes = Hydrator::$propertyScopes[$this::class] ??= Hydrator::getPropertyScopes($this::class);
        $scope = null;
        $instance = $this;
        $notByRef = 0;
        if ([$class, , $writeScope, $access] = $propertyScopes[$name] ?? null) {
            $notByRef = $access & Hydrator::PROPERTY_NOT_BY_REF;
            $scope = Registry::getScopeForRead($propertyScopes, $class, $name);
            if (null === $scope || isset($propertyScopes["\x00{$scope}\x00{$name}"])) {
                if ($state = $this->lazyObjectState ?? null) {
                    $instance = $state->realInstance ??= ($state->initializer)();
                }
                if (\PHP_VERSION_ID >= 80400 && !$notByRef && $access >> 2 & \ReflectionProperty::IS_PRIVATE_SET) {
                    $scope ??= $writeScope;
                }
                $parent = 2;
                goto get_in_scope;
            }
        }
        $parent = (Registry::$parentMethods[self::class] ??= Registry::getParentMethods(self::class))['get'];
        if ($state = $this->lazyObjectState ?? null) {
            $instance = $state->realInstance ??= ($state->initializer)();
        } else {
            if (2 === $parent) {
                return parent::__get($name);
            }
            $value = parent::__get($name);
            return $value;
        }
        if (!$parent && null === $class && !\array_key_exists($name, (array) $instance)) {
            $frame = debug_backtrace(\DEBUG_BACKTRACE_IGNORE_ARGS, 1)[0];
            trigger_error(\sprintf('Undefined property: %s::$%s in %s on line %s', $instance::class, $name, $frame['file'], $frame['line']), \E_USER_NOTICE);
        }
        get_in_scope:
        $notByRef = $notByRef || 1 === $parent;
        try {
            if (null === $scope) {
                if (!$notByRef) {
                    return $instance->{$name};
                }
                $value = $instance->{$name};
                return $value;
            }
            $accessor = Registry::$classAccessors[$scope] ??= Registry::getClassAccessors($scope);
            return $accessor['get']($instance, $name, $notByRef);
        } catch (\Error $e) {
            if (\Error::class !== $e::class || !str_starts_with($e->getMessage(), 'Cannot access uninitialized non-nullable property')) {
                throw $e;
            }
            try {
                if (null === $scope) {
                    $instance->{$name} = [];
                    return $instance->{$name};
                }
                $accessor['set']($instance, $name, []);
                return $accessor['get']($instance, $name, $notByRef);
            } catch (\Error) {
                throw $e;
            }
        }
    }
    public function __set($name, $value): void
    {
        $propertyScopes = Hydrator::$propertyScopes[$this::class] ??= Hydrator::getPropertyScopes($this::class);
        $scope = null;
        $instance = $this;
        if ([$class, , $writeScope, $access] = $propertyScopes[$name] ?? null) {
            $scope = Registry::getScopeForWrite($propertyScopes, $class, $name, $access >> 2);
            if ($writeScope === $scope || isset($propertyScopes["\x00{$scope}\x00{$name}"])) {
                if ($state = $this->lazyObjectState ?? null) {
                    $instance = $state->realInstance ??= ($state->initializer)();
                }
                goto set_in_scope;
            }
        }
        if ($state = $this->lazyObjectState ?? null) {
            $instance = $state->realInstance ??= ($state->initializer)();
        } elseif ((Registry::$parentMethods[self::class] ??= Registry::getParentMethods(self::class))['set']) {
            parent::__set($name, $value);
            return;
        }
        set_in_scope:
        if (null === $scope) {
            $instance->{$name} = $value;
        } else {
            $accessor = Registry::$classAccessors[$scope] ??= Registry::getClassAccessors($scope);
            $accessor['set']($instance, $name, $value);
        }
    }
    public function __isset($name): bool
    {
        $propertyScopes = Hydrator::$propertyScopes[$this::class] ??= Hydrator::getPropertyScopes($this::class);
        $scope = null;
        $instance = $this;
        if ([$class] = $propertyScopes[$name] ?? null) {
            $scope = Registry::getScopeForRead($propertyScopes, $class, $name);
            if (null === $scope || isset($propertyScopes["\x00{$scope}\x00{$name}"])) {
                if ($state = $this->lazyObjectState ?? null) {
                    $instance = $state->realInstance ??= ($state->initializer)();
                }
                goto isset_in_scope;
            }
        }
        if ($state = $this->lazyObjectState ?? null) {
            $instance = $state->realInstance ??= ($state->initializer)();
        } elseif ((Registry::$parentMethods[self::class] ??= Registry::getParentMethods(self::class))['isset']) {
            return parent::__isset($name);
        }
        isset_in_scope:
        if (null === $scope) {
            return isset($instance->{$name});
        }
        $accessor = Registry::$classAccessors[$scope] ??= Registry::getClassAccessors($scope);
        return $accessor['isset']($instance, $name);
    }
    public function __unset($name): void
    {
        $propertyScopes = Hydrator::$propertyScopes[$this::class] ??= Hydrator::getPropertyScopes($this::class);
        $scope = null;
        $instance = $this;
        if ([$class, , $writeScope, $access] = $propertyScopes[$name] ?? null) {
            $scope = Registry::getScopeForWrite($propertyScopes, $class, $name, $access >> 2);
            if ($writeScope === $scope || isset($propertyScopes["\x00{$scope}\x00{$name}"])) {
                if ($state = $this->lazyObjectState ?? null) {
                    $instance = $state->realInstance ??= ($state->initializer)();
                }
                goto unset_in_scope;
            }
        }
        if ($state = $this->lazyObjectState ?? null) {
            $instance = $state->realInstance ??= ($state->initializer)();
        } elseif ((Registry::$parentMethods[self::class] ??= Registry::getParentMethods(self::class))['unset']) {
            parent::__unset($name);
            return;
        }
        unset_in_scope:
        if (null === $scope) {
            unset($instance->{$name});
        } else {
            $accessor = Registry::$classAccessors[$scope] ??= Registry::getClassAccessors($scope);
            $accessor['unset']($instance, $name);
        }
    }
    public function __clone(): void
    {
        if (!isset($this->lazyObjectState)) {
            if ((Registry::$parentMethods[self::class] ??= Registry::getParentMethods(self::class))['clone']) {
                parent::__clone();
            }
            return;
        }
        $this->lazyObjectState = clone $this->lazyObjectState;
        if (isset($this->lazyObjectState->realInstance)) {
            $this->lazyObjectState->realInstance = clone $this->lazyObjectState->realInstance;
        }
    }
    public function __serialize(): array
    {
        $class = self::class;
        $state = $this->lazyObjectState ?? null;
        if (!$state && (Registry::$parentMethods[$class] ??= Registry::getParentMethods($class))['serialize']) {
            $properties = parent::__serialize();
        } else {
            $properties = (array) $this;
            if ($state) {
                unset($properties["\x00{$class}\x00lazyObjectState"]);
                $properties["\x00{$class}\x00lazyObjectReal"] = $state->realInstance ??= ($state->initializer)();
            }
        }
        if ($state || Registry::$parentMethods[$class]['serialize'] || !Registry::$parentMethods[$class]['sleep']) {
            return $properties;
        }
        $scope = get_parent_class($class);
        $data = [];
        foreach (parent::__sleep() as $name) {
            $value = $properties[$k = $name] ?? $properties[$k = "\x00*\x00{$name}"] ?? $properties[$k = "\x00{$class}\x00{$name}"] ?? $properties[$k = "\x00{$scope}\x00{$name}"] ?? $k = null;
            if (null === $k) {
                trigger_error(\sprintf('serialize(): "%s" returned as member variable from __sleep() but does not exist', $name), \E_USER_NOTICE);
            } else {
                $data[$k] = $value;
            }
        }
        return $data;
    }
    public function __unserialize(array $data): void
    {
        $class = self::class;
        if ($instance = $data["\x00{$class}\x00lazyObjectReal"] ?? null) {
            unset($data["\x00{$class}\x00lazyObjectReal"]);
            foreach (Registry::$classResetters[$class] ??= Registry::getClassResetters($class) as $reset) {
                $reset($this, $data);
            }
            if ($data) {
                PublicHydrator::hydrate($this, $data);
            }
            $this->lazyObjectState = new LazyObjectState(Registry::$noInitializerState ??= static fn() => throw new \LogicException('Lazy proxy has no initializer.'));
            $this->lazyObjectState->realInstance = $instance;
        } elseif ((Registry::$parentMethods[$class] ??= Registry::getParentMethods($class))['unserialize']) {
            parent::__unserialize($data);
        } else {
            PublicHydrator::hydrate($this, $data);
            if (Registry::$parentMethods[$class]['wakeup']) {
                parent::__wakeup();
            }
        }
    }
    public function __destruct()
    {
        if (isset($this->lazyObjectState)) {
            return;
        }
        if ((Registry::$parentMethods[self::class] ??= Registry::getParentMethods(self::class))['destruct']) {
            parent::__destruct();
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\VarExporter;

use _ContaoManager\Symfony\Component\VarExporter\Exception\ExceptionInterface;
use _ContaoManager\Symfony\Component\VarExporter\Internal\Exporter;
use _ContaoManager\Symfony\Component\VarExporter\Internal\Hydrator;
use _ContaoManager\Symfony\Component\VarExporter\Internal\Registry;
use _ContaoManager\Symfony\Component\VarExporter\Internal\Values;
/**
 * Exports serializable PHP values to PHP code.
 *
 * VarExporter allows serializing PHP data structures to plain PHP code (like var_export())
 * while preserving all the semantics associated with serialize() (unlike var_export()).
 *
 * By leveraging OPcache, the generated PHP code is faster than doing the same with unserialize().
 *
 * @author Nicolas Grekas <p@tchwork.com>
 */
final class VarExporter
{
    /**
     * Exports a serializable PHP value to PHP code.
     *
     * @param bool  &$isStaticValue Set to true after execution if the provided value is static, false otherwise
     * @param array &$foundClasses  Classes found in the value are added to this list as both keys and values
     *
     * @throws ExceptionInterface When the provided value cannot be serialized
     */
    public static function export(mixed $value, ?bool &$isStaticValue = null, array &$foundClasses = []): string
    {
        $isStaticValue = \true;
        if (!\is_object($value) && !(\is_array($value) && $value) && !\is_resource($value) || $value instanceof \UnitEnum) {
            return Exporter::export($value);
        }
        $objectsPool = new \SplObjectStorage();
        $refsPool = [];
        $objectsCount = 0;
        try {
            $value = Exporter::prepare([$value], $objectsPool, $refsPool, $objectsCount, $isStaticValue)[0];
        } finally {
            $references = [];
            foreach ($refsPool as $i => $v) {
                if ($v[0]->count) {
                    $references[1 + $i] = $v[2];
                }
                $v[0] = $v[1];
            }
        }
        if ($isStaticValue) {
            return Exporter::export($value);
        }
        $classes = [];
        $values = [];
        $states = [];
        foreach ($objectsPool as $i => $v) {
            [, $class, $values[], $wakeup] = $objectsPool[$v];
            $foundClasses[$class] = $classes[] = $class;
            if (0 < $wakeup) {
                $states[$wakeup] = $i;
            } elseif (0 > $wakeup) {
                $states[-$wakeup] = [$i, array_pop($values)];
                $values[] = [];
            }
        }
        ksort($states);
        $wakeups = [null];
        foreach ($states as $v) {
            if (\is_array($v)) {
                $wakeups[-$v[0]] = $v[1];
            } else {
                $wakeups[] = $v;
            }
        }
        if (null === $wakeups[0]) {
            unset($wakeups[0]);
        }
        $properties = [];
        foreach ($values as $i => $vars) {
            foreach ($vars as $class => $values) {
                foreach ($values as $name => $v) {
                    $properties[$class][$name][$i] = $v;
                }
            }
        }
        if ($classes || $references) {
            $value = new Hydrator(new Registry($classes), $references ? new Values($references) : null, $properties, $value, $wakeups);
        } else {
            $isStaticValue = \true;
        }
        return Exporter::export($value);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\VarExporter;

interface LazyObjectInterface
{
    /**
     * Returns whether the object is initialized.
     *
     * @param $partial Whether partially initialized objects should be considered as initialized
     */
    public function isLazyObjectInitialized(bool $partial = \false): bool;
    /**
     * Forces initialization of a lazy object and returns it.
     */
    public function initializeLazyObject(): object;
    /**
     * @return bool Returns false when the object cannot be reset, ie when it's not a lazy object
     */
    public function resetLazyObject(): bool;
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\VarExporter\Exception;

class LogicException extends \LogicException implements ExceptionInterface
{
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\VarExporter\Exception;

interface ExceptionInterface extends \Throwable
{
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\VarExporter\Exception;

class ClassNotFoundException extends \Exception implements ExceptionInterface
{
    public function __construct(string $class, ?\Throwable $previous = null)
    {
        parent::__construct(\sprintf('Class "%s" not found.', $class), 0, $previous);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\VarExporter\Exception;

class NotInstantiableTypeException extends \Exception implements ExceptionInterface
{
    public function __construct(string $type, ?\Throwable $previous = null)
    {
        parent::__construct(\sprintf('Type "%s" is not instantiable.', $type), 0, $previous);
    }
}
{
    "name": "symfony\/var-exporter",
    "type": "library",
    "description": "Allows exporting any serializable PHP data structure to plain PHP code",
    "keywords": [
        "export",
        "serialize",
        "instantiate",
        "hydrate",
        "construct",
        "clone",
        "lazy-loading",
        "proxy"
    ],
    "homepage": "https:\/\/symfony.com",
    "license": "MIT",
    "authors": [
        {
            "name": "Nicolas Grekas",
            "email": "p@tchwork.com"
        },
        {
            "name": "Symfony Community",
            "homepage": "https:\/\/symfony.com\/contributors"
        }
    ],
    "require": {
        "php": ">=8.1",
        "symfony\/deprecation-contracts": "^2.5|^3"
    },
    "require-dev": {
        "symfony\/property-access": "^6.4|^7.0",
        "symfony\/serializer": "^6.4|^7.0",
        "symfony\/var-dumper": "^5.4|^6.0|^7.0"
    },
    "autoload": {
        "psr-4": {
            "_ContaoManager\\Symfony\\Component\\VarExporter\\": ""
        },
        "exclude-from-classmap": [
            "\/Tests\/"
        ]
    },
    "minimum-stability": "dev"
}<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\ErrorHandler\ErrorEnhancer;

interface ErrorEnhancerInterface
{
    /**
     * Returns an \Throwable instance if the class is able to improve the error, null otherwise.
     */
    public function enhance(\Throwable $error): ?\Throwable;
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\ErrorHandler\ErrorEnhancer;

use Composer\Autoload\ClassLoader;
use _ContaoManager\Symfony\Component\ErrorHandler\DebugClassLoader;
use _ContaoManager\Symfony\Component\ErrorHandler\Error\ClassNotFoundError;
use _ContaoManager\Symfony\Component\ErrorHandler\Error\FatalError;
/**
 * @author Fabien Potencier <fabien@symfony.com>
 */
class ClassNotFoundErrorEnhancer implements ErrorEnhancerInterface
{
    public function enhance(\Throwable $error): ?\Throwable
    {
        // Some specific versions of PHP produce a fatal error when extending a not found class.
        $message = !$error instanceof FatalError ? $error->getMessage() : $error->getError()['message'];
        if (!preg_match('/^(Class|Interface|Trait) [\'"]([^\'"]+)[\'"] not found$/', $message, $matches)) {
            return null;
        }
        $typeName = strtolower($matches[1]);
        $fullyQualifiedClassName = $matches[2];
        if (\false !== $namespaceSeparatorIndex = strrpos($fullyQualifiedClassName, '\\')) {
            $className = substr($fullyQualifiedClassName, $namespaceSeparatorIndex + 1);
            $namespacePrefix = substr($fullyQualifiedClassName, 0, $namespaceSeparatorIndex);
            $message = \sprintf('Attempted to load %s "%s" from namespace "%s".', $typeName, $className, $namespacePrefix);
            $tail = ' for another namespace?';
        } else {
            $className = $fullyQualifiedClassName;
            $message = \sprintf('Attempted to load %s "%s" from the global namespace.', $typeName, $className);
            $tail = '?';
        }
        if ($candidates = $this->getClassCandidates($className)) {
            $tail = array_pop($candidates) . '"?';
            if ($candidates) {
                $tail = ' for e.g. "' . implode('", "', $candidates) . '" or "' . $tail;
            } else {
                $tail = ' for "' . $tail;
            }
        }
        $message .= "\nDid you forget a \"use\" statement" . $tail;
        return new ClassNotFoundError($message, $error);
    }
    /**
     * Tries to guess the full namespace for a given class name.
     *
     * By default, it looks for PSR-0 and PSR-4 classes registered via a Symfony or a Composer
     * autoloader (that should cover all common cases).
     *
     * @param string $class A class name (without its namespace)
     *
     * Returns an array of possible fully qualified class names
     */
    private function getClassCandidates(string $class): array
    {
        if (!\is_array($functions = spl_autoload_functions())) {
            return [];
        }
        // find Symfony and Composer autoloaders
        $classes = [];
        foreach ($functions as $function) {
            if (!\is_array($function)) {
                continue;
            }
            // get class loaders wrapped by DebugClassLoader
            if ($function[0] instanceof DebugClassLoader) {
                $function = $function[0]->getClassLoader();
                if (!\is_array($function)) {
                    continue;
                }
            }
            if ($function[0] instanceof ClassLoader) {
                foreach ($function[0]->getPrefixes() as $prefix => $paths) {
                    foreach ($paths as $path) {
                        $classes[] = $this->findClassInPath($path, $class, $prefix);
                    }
                }
                foreach ($function[0]->getPrefixesPsr4() as $prefix => $paths) {
                    foreach ($paths as $path) {
                        $classes[] = $this->findClassInPath($path, $class, $prefix);
                    }
                }
            }
        }
        return array_unique(array_merge([], ...$classes));
    }
    private function findClassInPath(string $path, string $class, string $prefix): array
    {
        $path = (realpath($path . '/' . strtr($prefix, '\_', '//')) ?: realpath($path . '/' . \dirname(strtr($prefix, '\_', '//')))) ?: realpath($path);
        if (!$path || !is_dir($path)) {
            return [];
        }
        $classes = [];
        $filename = $class . '.php';
        foreach (new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($path, \RecursiveDirectoryIterator::SKIP_DOTS), \RecursiveIteratorIterator::LEAVES_ONLY) as $file) {
            if ($filename == $file->getFileName() && $class = $this->convertFileToClass($path, $file->getPathName(), $prefix)) {
                $classes[] = $class;
            }
        }
        return $classes;
    }
    private function convertFileToClass(string $path, string $file, string $prefix): ?string
    {
        $candidates = [
            // namespaced class
            $namespacedClass = str_replace([$path . \DIRECTORY_SEPARATOR, '.php', '/'], ['', '', '\\'], $file),
            // namespaced class (with target dir)
            $prefix . $namespacedClass,
            // namespaced class (with target dir and separator)
            $prefix . '\\' . $namespacedClass,
            // PEAR class
            str_replace('\\', '_', $namespacedClass),
            // PEAR class (with target dir)
            str_replace('\\', '_', $prefix . $namespacedClass),
            // PEAR class (with target dir and separator)
            str_replace('\\', '_', $prefix . '\\' . $namespacedClass),
        ];
        if ($prefix) {
            $candidates = array_filter($candidates, fn($candidate) => str_starts_with($candidate, $prefix));
        }
        // We cannot use the autoloader here as most of them use require; but if the class
        // is not found, the new autoloader call will require the file again leading to a
        // "cannot redeclare class" error.
        foreach ($candidates as $candidate) {
            if ($this->classExists($candidate)) {
                return $candidate;
            }
        }
        // Symfony may ship some polyfills, like "Normalizer". But if the Intl
        // extension is already installed, the next require_once will fail with
        // a compile error because the class is already defined. And this one
        // does not throw a Throwable. So it's better to skip it here.
        if (str_contains($file, 'Resources/stubs')) {
            return null;
        }
        try {
            require_once $file;
        } catch (\Throwable) {
            return null;
        }
        foreach ($candidates as $candidate) {
            if ($this->classExists($candidate)) {
                return $candidate;
            }
        }
        return null;
    }
    private function classExists(string $class): bool
    {
        return class_exists($class, \false) || interface_exists($class, \false) || trait_exists($class, \false);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\ErrorHandler\ErrorEnhancer;

use _ContaoManager\Symfony\Component\ErrorHandler\Error\FatalError;
use _ContaoManager\Symfony\Component\ErrorHandler\Error\UndefinedFunctionError;
/**
 * @author Fabien Potencier <fabien@symfony.com>
 */
class UndefinedFunctionErrorEnhancer implements ErrorEnhancerInterface
{
    public function enhance(\Throwable $error): ?\Throwable
    {
        if ($error instanceof FatalError) {
            return null;
        }
        $message = $error->getMessage();
        $messageLen = \strlen($message);
        $notFoundSuffix = '()';
        $notFoundSuffixLen = \strlen($notFoundSuffix);
        if ($notFoundSuffixLen > $messageLen) {
            return null;
        }
        if (0 !== substr_compare($message, $notFoundSuffix, -$notFoundSuffixLen)) {
            return null;
        }
        $prefix = 'Call to undefined function ';
        $prefixLen = \strlen($prefix);
        if (!str_starts_with($message, $prefix)) {
            return null;
        }
        $fullyQualifiedFunctionName = substr($message, $prefixLen, -$notFoundSuffixLen);
        if (\false !== $namespaceSeparatorIndex = strrpos($fullyQualifiedFunctionName, '\\')) {
            $functionName = substr($fullyQualifiedFunctionName, $namespaceSeparatorIndex + 1);
            $namespacePrefix = substr($fullyQualifiedFunctionName, 0, $namespaceSeparatorIndex);
            $message = \sprintf('Attempted to call function "%s" from namespace "%s".', $functionName, $namespacePrefix);
        } else {
            $functionName = $fullyQualifiedFunctionName;
            $message = \sprintf('Attempted to call function "%s" from the global namespace.', $functionName);
        }
        $candidates = [];
        foreach (get_defined_functions() as $type => $definedFunctionNames) {
            foreach ($definedFunctionNames as $definedFunctionName) {
                if (\false !== $namespaceSeparatorIndex = strrpos($definedFunctionName, '\\')) {
                    $definedFunctionNameBasename = substr($definedFunctionName, $namespaceSeparatorIndex + 1);
                } else {
                    $definedFunctionNameBasename = $definedFunctionName;
                }
                if ($definedFunctionNameBasename === $functionName) {
                    $candidates[] = '\\' . $definedFunctionName;
                }
            }
        }
        if ($candidates) {
            sort($candidates);
            $last = array_pop($candidates) . '"?';
            if ($candidates) {
                $candidates = 'e.g. "' . implode('", "', $candidates) . '" or "' . $last;
            } else {
                $candidates = '"' . $last;
            }
            $message .= "\nDid you mean to call " . $candidates;
        }
        return new UndefinedFunctionError($message, $error);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\ErrorHandler\ErrorEnhancer;

use _ContaoManager\Symfony\Component\ErrorHandler\Error\FatalError;
use _ContaoManager\Symfony\Component\ErrorHandler\Error\UndefinedMethodError;
/**
 * @author Grégoire Pineau <lyrixx@lyrixx.info>
 */
class UndefinedMethodErrorEnhancer implements ErrorEnhancerInterface
{
    public function enhance(\Throwable $error): ?\Throwable
    {
        if ($error instanceof FatalError) {
            return null;
        }
        $message = $error->getMessage();
        preg_match('/^Call to undefined method (.*)::(.*)\(\)$/', $message, $matches);
        if (!$matches) {
            return null;
        }
        $className = $matches[1];
        $methodName = $matches[2];
        $message = \sprintf('Attempted to call an undefined method named "%s" of class "%s".', $methodName, $className);
        if ('' === $methodName || !class_exists($className) || null === $methods = get_class_methods($className)) {
            // failed to get the class or its methods on which an unknown method was called (for example on an anonymous class)
            return new UndefinedMethodError($message, $error);
        }
        $candidates = [];
        foreach ($methods as $definedMethodName) {
            $lev = levenshtein($methodName, $definedMethodName);
            if ($lev <= \strlen($methodName) / 3 || str_contains($definedMethodName, $methodName)) {
                $candidates[] = $definedMethodName;
            }
        }
        if ($candidates) {
            sort($candidates);
            $last = array_pop($candidates) . '"?';
            if ($candidates) {
                $candidates = 'e.g. "' . implode('", "', $candidates) . '" or "' . $last;
            } else {
                $candidates = '"' . $last;
            }
            $message .= "\nDid you mean to call " . $candidates;
        }
        return new UndefinedMethodError($message, $error);
    }
}
Copyright (c) 2019-present Fabien Potencier

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is furnished
to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
CHANGELOG
=========

6.4
---

 * `FlattenExceptionNormalizer` no longer implements `ContextAwareNormalizerInterface`

6.3
---

 * Display exception properties in the HTML error page

6.1
---

 * Report overridden `@final` constants and properties
 * Read environment variable `SYMFONY_IDE` to configure file link format

5.4
---

 * Make `DebugClassLoader` trigger deprecation notices on missing return types
 * Add `SYMFONY_PATCH_TYPE_DECLARATIONS='force=2'` mode to `DebugClassLoader` to turn annotations into native return types

5.2.0
-----

 * added the ability to set `HtmlErrorRenderer::$template` to a custom template to render when not in debug mode.

5.1.0
-----

 * The `HtmlErrorRenderer` and `SerializerErrorRenderer` add `X-Debug-Exception` and `X-Debug-Exception-File` headers in debug mode.

4.4.0
-----

 * added the component
 * added `ErrorHandler::call()` method utility to turn any PHP error into `\ErrorException`
#!/usr/bin/env php
<?php 


/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
if ('cli' !== \PHP_SAPI) {
    throw new \Exception('This script must be run from the command line.');
}
if (\in_array('-h', $argv) || \in_array('--help', $argv)) {
    echo \implode(\PHP_EOL, [' Patches type declarations based on "@return" PHPDoc and triggers deprecations for', ' incompatible method declarations.', '', ' This assists you to make your package compatible with Symfony 6, but it can be used', ' for any class/package.', '', ' Available configuration via environment variables:', '  SYMFONY_PATCH_TYPE_DECLARATIONS', '      A url-encoded string to change the behavior of the script. Available parameters:', '      - "force": any value enables deprecation notices - can be any of:', '          - "phpdoc" to patch only docblock annotations', '          - "2" to add all possible return types', '          - "1" to add return types but only to tests/final/internal/private methods', '      - "php": the target version of PHP - e.g. "7.1" doesn\'t generate "object" types', '      - "deprecations": "1" to trigger a deprecation notice when a child class misses a', '                        return type while the parent declares an "@return" annotation', '', '  SYMFONY_PATCH_TYPE_EXCLUDE', '      A regex matched against the full path to the class - any match will be excluded', '', ' Example: "SYMFONY_PATCH_TYPE_DECLARATIONS=php=7.4 ./patch-type-declarations"']);
    exit;
}
if (\false === \getenv('SYMFONY_PATCH_TYPE_DECLARATIONS')) {
    \putenv('SYMFONY_PATCH_TYPE_DECLARATIONS=force=2');
    echo 'No SYMFONY_PATCH_TYPE_DECLARATIONS env var set, patching type declarations in all methods (run the command with "-h" for more information).' . \PHP_EOL;
}
if (\is_file($autoload = __DIR__ . '/../../../../autoload.php')) {
    // noop
} elseif (\is_file($autoload = __DIR__ . '/../../../../../../../autoload.php')) {
    // noop
} else {
    echo \PHP_EOL . '  /!\ Cannot find the Composer autoloader, did you forget to run "composer install"?' . \PHP_EOL;
    exit(1);
}
if (\is_file($phpunitAutoload = \dirname($autoload) . '/bin/.phpunit/phpunit/vendor/autoload.php')) {
    require $phpunitAutoload;
}
$loader = require $autoload;
Symfony\Component\ErrorHandler\DebugClassLoader::enable();
$deprecations = [];
\set_error_handler(function ($type, $msg, $file, $line, $context = []) use (&$deprecations) {
    if (\E_USER_DEPRECATED !== $type) {
        return;
    }
    [, , , , , $class] = \explode('"', $msg);
    $deprecations[$class][] = $msg;
});
$exclude = \getenv('SYMFONY_PATCH_TYPE_EXCLUDE') ?: null;
foreach ($loader->getClassMap() as $class => $file) {
    if (\str_contains($file = \realpath($file), \DIRECTORY_SEPARATOR . 'vendor' . \DIRECTORY_SEPARATOR)) {
        continue;
    }
    if ($exclude && \preg_match($exclude, $file)) {
        continue;
    }
    \class_exists($class);
}
Symfony\Component\ErrorHandler\DebugClassLoader::checkClasses();
foreach ($deprecations as $class => $classDeprecations) {
    echo $class . ' (' . \count($classDeprecations) . ')' . \PHP_EOL;
    echo \implode(\PHP_EOL, $classDeprecations) . \PHP_EOL . \PHP_EOL;
}
if ($deprecations && \str_contains(\getenv('SYMFONY_PATCH_TYPE_DECLARATIONS') ?? '', 'force')) {
    echo 'These deprecations might be fixed by the patch script, run this again to check for type deprecations.' . \PHP_EOL;
}
#!/usr/bin/env php
<?php 


/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
if ('cli' !== \PHP_SAPI) {
    throw new \Exception('This script must be run from the command line.');
}
// Run from the root of the php-src repository, this script generates
// a table with all the methods that have a tentative return type.
//
// Usage: find -name *.stub.php | sort | /path/to/extract-tentative-return-types.php > /path/to/TentativeTypes.php
echo <<<EOPHP
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\\Component\\ErrorHandler\\Internal;

/**
 * This class has been generated by extract-tentative-return-types.php.
 *
 * @internal
 */
class TentativeTypes
{
    public const RETURN_TYPES = [

EOPHP;
while (\false !== $file = \fgets(\STDIN)) {
    $code = \file_get_contents(\substr($file, 0, -1));
    if (!\str_contains($code, '@tentative-return-type')) {
        continue;
    }
    $code = \preg_split('{^\s*(?:(?:abstract )?class|interface|trait) ([^\s]++)}m', $code, -1, \PREG_SPLIT_DELIM_CAPTURE);
    if (1 === \count($code)) {
        continue;
    }
    for ($i = 1; null !== $class = $code[$i] ?? null; $i += 2) {
        $methods = $code[1 + $i];
        if (!\str_contains($methods, '@tentative-return-type')) {
            continue;
        }
        echo "        '{$class}' => [\n";
        \preg_replace_callback('{@tentative-return-type.*?[\s]function ([^(]++)[^)]++\)\s*+:\s*+([^\n;\{]++)}s', function ($m) {
            $m[2] = \str_replace(' ', '', $m[2]);
            echo "            '{$m[1]}' => '{$m[2]}',\n";
            return '';
        }, $methods);
        echo "        ],\n";
    }
}
echo <<<EOPHP
    ];
}

EOPHP
;
<div class="exception-summary <?php 


echo !$exceptionMessage ? 'exception-without-message' : '';
?>">
    <div class="exception-metadata">
        <div class="container">
            <h2 class="exception-hierarchy">
                <?php 
foreach (\array_reverse($exception->getAllPrevious(), \true) as $index => $previousException) {
    ?>
                    <a href="#trace-box-<?php 
    echo $index + 2;
    ?>"><?php 
    echo $this->abbrClass($previousException->getClass());
    ?></a>
                    <span class="icon"><?php 
    echo $this->include('assets/images/chevron-right.svg');
    ?></span>
                <?php 
}
?>
                <a href="#trace-box-1"><?php 
echo $this->abbrClass($exception->getClass());
?></a>
            </h2>
            <h2 class="exception-http">
                HTTP <?php 
echo $statusCode;
?> <small><?php 
echo $statusText;
?></small>
            </h2>
        </div>
    </div>
    <div class="exception-message-wrapper">
        <div class="container">
            <h1 class="break-long-words exception-message<?php 
echo \mb_strlen($exceptionMessage) > 180 ? ' long' : '';
?>"><?php 
echo $this->formatFileFromText(\nl2br($exceptionMessage));
?></h1>

            <div class="exception-illustration hidden-xs-down">
                <?php 
echo $this->include('assets/images/symfony-ghost.svg.php');
?>
            </div>
        </div>
    </div>
</div>

<div class="container">
    <div class="sf-tabs">
        <div class="tab">
            <?php 
$exceptionAsArray = $exception->toArray();
$exceptionWithUserCode = [];
$exceptionAsArrayCount = \count($exceptionAsArray);
$last = $exceptionAsArrayCount - 1;
foreach ($exceptionAsArray as $i => $e) {
    foreach ($e['trace'] as $trace) {
        if ($trace['file'] && !\str_contains($trace['file'], '/vendor/') && !\str_contains($trace['file'], '/var/cache/') && $i < $last) {
            $exceptionWithUserCode[] = $i;
        }
    }
}
?>
            <h3 class="tab-title">
                <?php 
if ($exceptionAsArrayCount > 1) {
    ?>
                    Exceptions <span class="badge"><?php 
    echo $exceptionAsArrayCount;
    ?></span>
                <?php 
} else {
    ?>
                    Exception
                <?php 
}
?>
            </h3>

            <div class="tab-content">
                <?php 
foreach ($exceptionAsArray as $i => $e) {
    echo $this->include('views/traces.html.php', ['exception' => $e, 'index' => $i + 1, 'expand' => \in_array($i, $exceptionWithUserCode, \true) || [] === $exceptionWithUserCode && 0 === $i]);
}
?>
            </div>
        </div>

        <?php 
if ($logger) {
    ?>
        <div class="tab <?php 
    echo !$logger->getLogs() ? 'disabled' : '';
    ?>">
            <h3 class="tab-title">
                Logs
                <?php 
    if ($logger->countErrors()) {
        ?><span class="badge status-error"><?php 
        echo $logger->countErrors();
        ?></span><?php 
    }
    ?>
            </h3>

            <div class="tab-content">
                <?php 
    if ($logger->getLogs()) {
        ?>
                    <?php 
        echo $this->include('views/logs.html.php', ['logs' => $logger->getLogs()]);
        ?>
                <?php 
    } else {
        ?>
                    <div class="empty">
                        <p>No log messages</p>
                    </div>
                <?php 
    }
    ?>
            </div>
        </div>
        <?php 
}
?>

        <div class="tab">
            <h3 class="tab-title">
                <?php 
if ($exceptionAsArrayCount > 1) {
    ?>
                    Stack Traces <span class="badge"><?php 
    echo $exceptionAsArrayCount;
    ?></span>
                <?php 
} else {
    ?>
                    Stack Trace
                <?php 
}
?>
            </h3>

            <div class="tab-content">
                <?php 
foreach ($exceptionAsArray as $i => $e) {
    echo $this->include('views/traces_text.html.php', ['exception' => $e, 'index' => $i + 1, 'numExceptions' => $exceptionAsArrayCount]);
}
?>
            </div>
        </div>

        <?php 
if ($currentContent) {
    ?>
        <div class="tab">
            <h3 class="tab-title">Output content</h3>

            <div class="tab-content">
                <?php 
    echo $currentContent;
    ?>
            </div>
        </div>
        <?php 
}
?>
    </div>
</div>
<?php 
<div class="trace trace-as-html" id="trace-box-<?php 


echo $index;
?>">
    <div class="trace-details">
        <div class="trace-head">
            <div class="sf-toggle" data-toggle-selector="#trace-html-<?php 
echo $index;
?>" data-toggle-initial="<?php 
echo $expand ? 'display' : '';
?>">
                <span class="icon icon-close"><?php 
echo $this->include('assets/images/icon-minus-square-o.svg');
?></span>
                <span class="icon icon-open"><?php 
echo $this->include('assets/images/icon-plus-square-o.svg');
?></span>
                <?php 
$separator = \strrpos($exception['class'], '\\');
$separator = \false === $separator ? 0 : $separator + 1;
$namespace = \substr($exception['class'], 0, $separator);
$class = \substr($exception['class'], $separator);
?>
                <?php 
if ('' === $class) {
    ?>
                    <br>
                <?php 
} else {
    ?>
                    <h3 class="trace-class">
                        <?php 
    if ('' !== $namespace) {
        ?>
                            <span class="trace-namespace"><?php 
        echo $namespace;
        ?></span>
                        <?php 
    }
    ?>
                        <?php 
    echo $class;
    ?>
                    </h3>
                <?php 
}
?>
                <?php 
if ($exception['message'] && $index > 1) {
    ?>
                    <p class="break-long-words trace-message"><?php 
    echo $this->escape($exception['message']);
    ?></p>
                <?php 
}
?>
            </div>
            <?php 
if (\count($exception['data'] ?? [])) {
    ?>
                <details class="exception-properties-wrapper">
                    <summary>Show exception properties</summary>
                    <div class="exception-properties">
                        <?php 
    echo $this->dumpValue($exception['data']);
    ?>
                    </div>
                </details>
            <?php 
}
?>
        </div>

        <div id="trace-html-<?php 
echo $index;
?>" class="sf-toggle-content">
        <?php 
$isFirstUserCode = \true;
foreach ($exception['trace'] as $i => $trace) {
    $isVendorTrace = $trace['file'] && (\str_contains($trace['file'], '/vendor/') || \str_contains($trace['file'], '/var/cache/'));
    $displayCodeSnippet = $isFirstUserCode && !$isVendorTrace;
    if ($displayCodeSnippet) {
        $isFirstUserCode = \false;
    }
    ?>
            <div class="trace-line <?php 
    echo $isVendorTrace ? 'trace-from-vendor' : '';
    ?>">
                <?php 
    echo $this->include('views/trace.html.php', ['prefix' => $index, 'i' => $i, 'trace' => $trace, 'style' => $isVendorTrace ? 'compact' : ($displayCodeSnippet ? 'expanded' : '')]);
    ?>
            </div>
            <?php 
}
?>
        </div>
    </div>
</div>
<?php 
<table class="trace trace-as-text">
    <thead class="trace-head">
        <tr>
            <th class="sf-toggle" data-toggle-selector="#trace-text-<?php 


echo $index;
?>" data-toggle-initial="<?php 
echo 1 === $index ? 'display' : '';
?>">
                <div class="trace-class">
                    <?php 
if ($numExceptions > 1) {
    ?>
                        <span class="text-muted">[<?php 
    echo $numExceptions - $index + 1;
    ?>/<?php 
    echo $numExceptions;
    ?>]</span>
                    <?php 
}
?>
                    <?php 
echo ($parts = \explode('\\', $exception['class'])) ? \end($parts) : '';
?>
                    <span class="icon icon-close"><?php 
echo $this->include('assets/images/icon-minus-square-o.svg');
?></span>
                    <span class="icon icon-open"><?php 
echo $this->include('assets/images/icon-plus-square-o.svg');
?></span>
                </div>
            </th>
        </tr>
    </thead>

    <tbody id="trace-text-<?php 
echo $index;
?>">
        <tr>
            <td>
                <?php 
if ($exception['trace']) {
    ?>
                <pre class="stacktrace">
<?php 
    echo $this->escape($exception['class']) . ":\n";
    if ($exception['message']) {
        echo $this->escape($exception['message']) . "\n";
    }
    foreach ($exception['trace'] as $trace) {
        echo "\n  ";
        if ($trace['function']) {
            echo $this->escape('at ' . $trace['class'] . $trace['type'] . $trace['function']) . '(' . (isset($trace['args']) ? $this->formatArgsAsText($trace['args']) : '') . ')';
        }
        if ($trace['file'] && $trace['line']) {
            echo ($trace['function'] ? "\n     (" : 'at ') . \strtr(\strip_tags($this->formatFile($trace['file'], $trace['line'])), [' at line ' . $trace['line'] => '']) . ':' . $trace['line'] . ($trace['function'] ? ')' : '');
        }
    }
    ?>
                </pre>
                <?php 
}
?>
            </td>
        </tr>
    </tbody>
</table>
<?php 
<table class="logs" data-filter-level="Emergency,Alert,Critical,Error,Warning,Notice,Info,Debug" data-filters>
<?php 


$channelIsDefined = isset($logs[0]['channel']);
?>
    <thead>
        <tr>
            <th data-filter="level">Level</th>
            <?php 
if ($channelIsDefined) {
    ?><th data-filter="channel">Channel</th><?php 
}
?>
            <th class="full-width">Message</th>
        </tr>
    </thead>

    <tbody>
    <?php 
foreach ($logs as $log) {
    if ($log['priority'] >= 400) {
        $status = 'error';
    } elseif ($log['priority'] >= 300) {
        $status = 'warning';
    } else {
        $severity = 0;
        if (($exception = $log['context']['exception'] ?? null) instanceof \ErrorException || $exception instanceof \_ContaoManager\Symfony\Component\ErrorHandler\Exception\SilencedErrorContext) {
            $severity = $exception->getSeverity();
        }
        $status = \E_DEPRECATED === $severity || \E_USER_DEPRECATED === $severity ? 'warning' : 'normal';
    }
    ?>
        <tr class="status-<?php 
    echo $status;
    ?>" data-filter-level="<?php 
    echo \strtolower($this->escape($log['priorityName']));
    ?>"<?php 
    if ($channelIsDefined) {
        ?> data-filter-channel="<?php 
        echo $this->escape($log['channel']);
        ?>"<?php 
    }
    ?>>
            <td class="text-small nowrap">
                <span class="colored text-bold"><?php 
    echo $this->escape($log['priorityName']);
    ?></span>
                <span class="text-muted newline"><?php 
    echo \date('H:i:s', $log['timestamp']);
    ?></span>
            </td>
            <?php 
    if ($channelIsDefined) {
        ?>
            <td class="text-small text-bold nowrap">
                <?php 
        echo $this->escape($log['channel']);
        ?>
            </td>
            <?php 
    }
    ?>
            <td>
                <?php 
    echo $this->formatLogMessage($log['message'], $log['context']);
    ?>
                <?php 
    if ($log['context']) {
        ?>
                <pre class="text-muted prewrap m-t-5"><?php 
        echo $this->escape(\json_encode($log['context'], \JSON_PRETTY_PRINT | \JSON_UNESCAPED_UNICODE | \JSON_UNESCAPED_SLASHES));
        ?></pre>
                <?php 
    }
    ?>
            </td>
        </tr>
    <?php 
}
?>
    </tbody>
</table>
<?php 
<div class="trace-line-header break-long-words <?php 


echo $trace['file'] ? 'sf-toggle' : '';
?>" data-toggle-selector="#trace-html-<?php 
echo $prefix;
?>-<?php 
echo $i;
?>" data-toggle-initial="<?php 
echo 'expanded' === $style ? 'display' : '';
?>">
    <?php 
if ($trace['file']) {
    ?>
        <span class="icon icon-close"><?php 
    echo $this->include('assets/images/icon-minus-square.svg');
    ?></span>
        <span class="icon icon-open"><?php 
    echo $this->include('assets/images/icon-plus-square.svg');
    ?></span>
    <?php 
}
?>

    <?php 
if ('compact' !== $style && $trace['function']) {
    ?>
        <span class="trace-class"><?php 
    echo $this->abbrClass($trace['class']);
    ?></span><?php 
    if ($trace['type']) {
        ?><span class="trace-type"><?php 
        echo $trace['type'];
        ?></span><?php 
    }
    ?><span class="trace-method"><?php 
    echo $trace['function'];
    ?></span><?php 
    if (isset($trace['args'])) {
        ?><span class="trace-arguments">(<?php 
        echo $this->formatArgs($trace['args']);
        ?>)</span><?php 
    }
    ?>
    <?php 
}
?>

    <?php 
if ($trace['file']) {
    ?>
        <?php 
    $lineNumber = $trace['line'] ?: 1;
    $fileLink = $this->fileLinkFormat->format($trace['file'], $lineNumber);
    $filePath = \strtr(\strip_tags($this->formatFile($trace['file'], $lineNumber)), [' at line ' . $lineNumber => '']);
    $filePathParts = \explode(\DIRECTORY_SEPARATOR, $filePath);
    ?>
        <span class="block trace-file-path">
            in
            <a href="<?php 
    echo $fileLink;
    ?>">
                <?php 
    echo \implode(\DIRECTORY_SEPARATOR, \array_slice($filePathParts, 0, -1)) . \DIRECTORY_SEPARATOR;
    ?><strong><?php 
    echo \end($filePathParts);
    ?></strong>
            </a>
            <?php 
    if ('compact' === $style && $trace['function']) {
        ?>
                <span class="trace-type"><?php 
        echo $trace['type'];
        ?></span>
                <span class="trace-method"><?php 
        echo $trace['function'];
        ?></span>
            <?php 
    }
    ?>
            (line <?php 
    echo $lineNumber;
    ?>)
            <span class="icon icon-copy hidden" data-clipboard-text="<?php 
    echo \implode(\DIRECTORY_SEPARATOR, $filePathParts) . ':' . $lineNumber;
    ?>">
                <?php 
    echo $this->include('assets/images/icon-copy.svg');
    ?>
            </span>
        </span>
    <?php 
}
?>
</div>
<?php 
if ($trace['file']) {
    ?>
    <div id="trace-html-<?php 
    echo $prefix . '-' . $i;
    ?>" class="trace-code sf-toggle-content">
        <?php 
    echo \strtr($this->fileExcerpt($trace['file'], $trace['line'], 5), ['#DD0000' => 'var(--highlight-string)', '#007700' => 'var(--highlight-keyword)', '#0000BB' => 'var(--highlight-default)', '#FF8000' => 'var(--highlight-comment)']);
    ?>
    </div>
<?php 
}
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="<?php 


echo $this->charset;
?>" />
    <meta name="robots" content="noindex,nofollow,noarchive" />
    <title>An Error Occurred: <?php 
echo $statusText;
?></title>
    <link rel="icon" href="data:image/svg+xml,<svg xmlns=%22http://www.w3.org/2000/svg%22 viewBox=%220 0 128 128%22><text y=%221.2em%22 font-size=%2296%22>❌</text></svg>" />
    <style><?php 
echo $this->include('assets/css/error.css');
?></style>
</head>
<body>
<div class="container">
    <h1>Oops! An Error Occurred</h1>
    <h2>The server returned a "<?php 
echo $statusCode;
?> <?php 
echo $statusText;
?>".</h2>

    <p>
        Something is broken. Please let us know what you were doing when this error occurred.
        We will fix it as soon as possible. Sorry for any inconvenience caused.
    </p>
</div>
</body>
</html>
<?php 
<!-- <?php 


echo $_message = \sprintf('%s (%d %s)', $exceptionMessage, $statusCode, $statusText);
?> -->
<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="<?php 
echo $this->charset;
?>" />
        <meta name="robots" content="noindex,nofollow" />
        <meta name="viewport" content="width=device-width,initial-scale=1" />
        <title><?php 
echo $_message;
?></title>
        <link rel="icon" type="image/png" href="<?php 
echo $this->include('assets/images/favicon.png.base64');
?>" />
        <style><?php 
echo $this->include('assets/css/exception.css');
?></style>
        <style><?php 
echo $this->include('assets/css/exception_full.css');
?></style>
    </head>
    <body>
        <script>
            document.body.classList.add(
                localStorage.getItem('symfony/profiler/theme') || (matchMedia('(prefers-color-scheme: dark)').matches ? 'theme-dark' : 'theme-light')
            );
        </script>

        <?php 
if (\class_exists(\_ContaoManager\Symfony\Component\HttpKernel\Kernel::class)) {
    ?>
            <header>
                <div class="container">
                    <h1 class="logo"><?php 
    echo $this->include('assets/images/symfony-logo.svg');
    ?> Symfony Exception</h1>

                    <div class="help-link">
                        <a href="https://symfony.com/doc/<?php 
    echo \_ContaoManager\Symfony\Component\HttpKernel\Kernel::VERSION;
    ?>/index.html">
                            <span class="icon"><?php 
    echo $this->include('assets/images/icon-book.svg');
    ?></span>
                            <span class="hidden-xs-down">Symfony</span> Docs
                        </a>
                    </div>
                </div>
            </header>
        <?php 
}
?>

        <?php 
echo $this->include('views/exception.html.php', $context);
?>

        <script>
            <?php 
echo $this->include('assets/js/exception.js');
?>
        </script>
    </body>
</html>
<!-- <?php 
echo $_message;
?> -->
<?php 
/* This file is based on WebProfilerBundle/Resources/views/Profiler/profiler.css.twig.
   If you make any change in this file, verify the same change is needed in the other file. */
:root {
    --font-sans-serif: Helvetica, Arial, sans-serif;
    --page-background: #f9f9f9;
    --color-text: #222;
    /* when updating any of these colors, do the same in toolbar.css.twig */
    --color-success: #4f805d;
    --color-warning: #a46a1f;
    --color-error: #b0413e;
    --color-muted: #999;
    --tab-background: #f0f0f0;
    --tab-border-color: #e5e5e5;
    --tab-active-border-color: #d4d4d4;
    --tab-color: #444;
    --tab-active-background: #fff;
    --tab-active-color: var(--color-text);
    --tab-disabled-background: #f5f5f5;
    --tab-disabled-color: #999;
    --selected-badge-background: #e5e5e5;
    --selected-badge-color: #525252;
    --selected-badge-shadow: inset 0 0 0 1px #d4d4d4;
    --selected-badge-warning-background: #fde496;
    --selected-badge-warning-color: #785b02;
    --selected-badge-warning-shadow: inset 0 0 0 1px #e6af05;
    --selected-badge-danger-background: #FCE9ED;
    --selected-badge-danger-color: #83122A;
    --selected-badge-danger-shadow: inset 0 0 0 1px #F5B8C5;
    --metric-value-background: #fff;
    --metric-value-color: inherit;
    --metric-unit-color: #999;
    --metric-label-background: #e0e0e0;
    --metric-label-color: inherit;
    --table-border: #e0e0e0;
    --table-background: #fff;
    --table-header: #e0e0e0;
    --trace-selected-background: #F7E5A1;
    --tree-active-background: #F7E5A1;
    --exception-title-color: var(--base-2);
    --shadow: 0px 0px 1px rgba(128, 128, 128, .2);
    --border: 1px solid #e0e0e0;
    --background-error: var(--color-error);
    --highlight-comment: #969896;
    --highlight-default: #222222;
    --highlight-keyword: #a71d5d;
    --highlight-string: #183691;
    --base-0: #fff;
    --base-1: #f5f5f5;
    --base-2: #e0e0e0;
    --base-3: #ccc;
    --base-4: #666;
    --base-5: #444;
    --base-6: #222;
}

.theme-dark {
    --page-background: #36393e;
    --color-text: #e0e0e0;
    --color-muted: #777;
    --color-error: #f76864;
    --tab-background: #404040;
    --tab-border-color: #737373;
    --tab-active-border-color: #171717;
    --tab-color: var(--color-text);
    --tab-active-background: #d4d4d4;
    --tab-active-color: #262626;
    --tab-disabled-background: var(--page-background);
    --tab-disabled-color: #a3a3a3;
    --selected-badge-background: #555;
    --selected-badge-color: #ddd;
    --selected-badge-shadow: none;
    --selected-badge-warning-background: #fcd55f;
    --selected-badge-warning-color: #785b02;
    --selected-badge-warning-shadow: inset 0 0 0 1px #af8503;
    --selected-badge-danger-background: #B41939;
    --selected-badge-danger-color: #FCE9ED;
    --selected-badge-danger-shadow: none;
    --metric-value-background: #555;
    --metric-value-color: inherit;
    --metric-unit-color: #999;
    --metric-label-background: #777;
    --metric-label-color: #e0e0e0;
    --trace-selected-background: #5d5227cc;
    --table-border: #444;
    --table-background: #333;
    --table-header: #555;
    --info-background: rgba(79, 148, 195, 0.5);
    --tree-active-background: var(--metric-label-background);
    --exception-title-color: var(--base-2);
    --shadow: 0px 0px 1px rgba(32, 32, 32, .2);
    --border: 1px solid #666;
    --background-error: #b0413e;
    --highlight-comment: #dedede;
    --highlight-default: var(--base-6);
    --highlight-keyword: #de8986;
    --highlight-string: #70a6fd;
    --base-0: #2e3136;
    --base-1: #444;
    --base-2: #666;
    --base-3: #666;
    --base-4: #666;
    --base-5: #e0e0e0;
    --base-6: #f5f5f5;
    --card-label-background: var(--tab-active-background);
    --card-label-color: var(--tab-active-color);
}

html{font-family:sans-serif;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%}body{margin:0}article,aside,details,figcaption,figure,footer,header,hgroup,main,menu,nav,section{display:block}audio,canvas,progress,video{display:inline-block;vertical-align:baseline}audio:not([controls]){display:none;height:0}[hidden],template{display:none}a{background-color:transparent}a:active,a:hover{outline:0}abbr[title]{border-bottom:1px dotted}b,strong{font-weight:700}dfn{font-style:italic}h1{margin:.67em 0;font-size:2em}mark{color:#000;background:#ff0}small{font-size:80%}sub,sup{position:relative;font-size:75%;line-height:0;vertical-align:baseline}sup{top:-.5em}sub{bottom:-.25em}img{border:0}svg:not(:root){overflow:hidden}figure{margin:1em 40px}hr{height:0;-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box}pre{overflow:auto}code,kbd,pre,samp{font-family:monospace,monospace;font-size:1em}button,input,optgroup,select,textarea{margin:0;font:inherit;color:inherit}button{overflow:visible}button,select{text-transform:none}button,html input[type="button"],input[type="reset"],input[type="submit"]{-webkit-appearance:button;cursor:pointer}button[disabled],html input[disabled]{cursor:default}button::-moz-focus-inner,input::-moz-focus-inner{padding:0;border:0}input{line-height:normal}input[type="checkbox"],input[type="radio"]{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;padding:0}input[type="number"]::-webkit-inner-spin-button,input[type="number"]::-webkit-outer-spin-button{height:auto}input[type="search"]{-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;-webkit-appearance:textfield}input[type="search"]::-webkit-search-cancel-button,input[type="search"]::-webkit-search-decoration{-webkit-appearance:none}fieldset{padding:.35em .625em .75em;margin:0 2px;border:1px solid silver}legend{padding:0;border:0}textarea{overflow:auto}optgroup{font-weight:700}table{border-spacing:0;border-collapse:collapse}td,th{padding:0}summary{cursor: pointer}

html {
    /* always display the vertical scrollbar to avoid jumps when toggling contents */
    overflow-y: scroll;
}
body { background-color: var(--page-background); color: var(--base-6); font: 14px/1.4 Helvetica, Arial, sans-serif; padding-bottom: 45px; }

a { cursor: pointer; text-decoration: none; }
a:hover { text-decoration: underline; }
abbr[title] { border-bottom: none; cursor: help; text-decoration: none; }

code, pre { font: 13px/1.5 Consolas, Monaco, Menlo, "Ubuntu Mono", "Liberation Mono", monospace; }

table, tr, th, td { background: var(--base-0); border-collapse: collapse; vertical-align: top; }
table { background: var(--base-0); border: var(--border); box-shadow: 0px 0px 1px rgba(128, 128, 128, .2); margin: 1em 0; width: 100%; }
table th, table td { border: solid var(--base-2); border-width: 1px 0; padding: 8px 10px; }
table th { background-color: var(--base-2); font-weight: bold; text-align: left; }

.m-t-5 { margin-top: 5px; }
.hidden-xs-down { display: none; }
.block { display: block; }
.full-width { width: 100%; }
.hidden { display: none; }
.prewrap { white-space: pre-wrap; }
.nowrap { white-space: nowrap; }
.newline { display: block; }
.break-long-words { word-wrap: break-word; overflow-wrap: break-word; -webkit-hyphens: auto; -moz-hyphens: auto; hyphens: auto; min-width: 0; }
.text-small { font-size: 12px !important; }
.text-muted { color: #999; }
.text-bold { font-weight: bold; }
.empty { border: 4px dashed var(--base-2); color: #999; margin: 1em 0; padding: .5em 2em; }

.status-success { background: rgba(94, 151, 110, 0.3); }
.status-warning { background: rgba(240, 181, 24, 0.3); }
.status-error { background: rgba(176, 65, 62, 0.2); }
.status-success td, .status-warning td, .status-error td { background: transparent; }
tr.status-error td, tr.status-warning td { border-bottom: 1px solid var(--base-2); border-top: 1px solid var(--base-2); }
.status-warning .colored { color: #A46A1F; }
.status-error .colored  { color: var(--color-error); }

.sf-toggle { cursor: pointer; position: relative; }
.sf-toggle-content { -moz-transition: display .25s ease; -webkit-transition: display .25s ease; transition: display .25s ease; }
.sf-toggle-content.sf-toggle-hidden { display: none; }
.sf-toggle-content.sf-toggle-visible { display: block; }
thead.sf-toggle-content.sf-toggle-visible, tbody.sf-toggle-content.sf-toggle-visible { display: table-row-group; }
.sf-toggle-off .icon-close, .sf-toggle-on .icon-open { display: none; }
.sf-toggle-off .icon-open, .sf-toggle-on .icon-close { display: block; }

.tab-navigation {
    background-color: var(--tab-background);
    border-radius: 6px;
    box-shadow: inset 0 0 0 1px var(--tab-border-color), 0 0 0 5px var(--page-background);
    display: inline-flex;
    flex-wrap: wrap;
    margin: 0 0 15px;
    padding: 0;
    user-select: none;
    -webkit-user-select: none;
}
.sf-tabs-sm .tab-navigation {
    box-shadow: inset 0 0 0 1px var(--tab-border-color), 0 0 0 4px var(--page-background);
    margin: 0 0 10px;
}
.tab-navigation .tab-control {
    background: transparent;
    border: 0;
    box-shadow: none;
    transition: box-shadow .05s ease-in, background-color .05s ease-in;
    cursor: pointer;
    font-size: 14px;
    font-weight: 500;
    line-height: 1.4;
    margin: 0;
    padding: 4px 14px;
    position: relative;
    text-align: center;
    z-index: 1;
}
.sf-tabs-sm .tab-navigation .tab-control {
    font-size: 13px;
    padding: 2.5px 10px;
}
.tab-navigation .tab-control:before {
    background: var(--tab-border-color);
    bottom: 15%;
    content: "";
    left: 0;
    position: absolute;
    top: 15%;
    width: 1px;
}
.tab-navigation .tab-control:first-child:before,
.tab-navigation .tab-control.active + .tab-control:before,
.tab-navigation .tab-control.active:before {
    width: 0;
}
.tab-navigation .tab-control .badge {
    background: var(--selected-badge-background);
    box-shadow: var(--selected-badge-shadow);
    color: var(--selected-badge-color);
    display: inline-block;
    font-size: 12px;
    font-weight: bold;
    line-height: 1;
    margin-left: 8px;
    min-width: 10px;
    padding: 2px 6px;
    text-align: center;
    white-space: nowrap;
}
.tab-navigation .tab-control.disabled {
    color: var(--tab-disabled-color);
}
.tab-navigation .tab-control.active {
    background-color: var(--tab-active-background);
    border-radius: 6px;
    box-shadow: inset 0 0 0 1.5px var(--tab-active-border-color);
    color: var(--tab-active-color);
    position: relative;
    z-index: 1;
}
.theme-dark .tab-navigation li.active {
    box-shadow: inset 0 0 0 1px var(--tab-border-color);
}
.tab-content > *:first-child {
    margin-top: 0;
}
.tab-navigation .tab-control .badge.status-warning {
    background: var(--selected-badge-warning-background);
    box-shadow: var(--selected-badge-warning-shadow);
    color: var(--selected-badge-warning-color);
}
.tab-navigation .tab-control .badge.status-error {
    background: var(--selected-badge-danger-background);
    box-shadow: var(--selected-badge-danger-shadow);
    color: var(--selected-badge-danger-color);
}

.sf-tabs .tab:not(:first-child) { display: none; }

[data-filters] { position: relative; }
[data-filtered] { cursor: pointer; }
[data-filtered]:after { content: '\00a0\25BE'; }
[data-filtered]:hover .filter-list li { display: inline-flex; }
[class*="filter-hidden-"] { display: none; }
.filter-list { position: absolute; border: var(--border); box-shadow: var(--shadow); margin: 0; padding: 0; display: flex; flex-direction: column; }
.filter-list :after { content: ''; }
.filter-list li {
    background: var(--tab-disabled-background);
    border-bottom: var(--border);
    color: var(--tab-disabled-color);
    display: none;
    list-style: none;
    margin: 0;
    padding: 5px 10px;
    text-align: left;
    font-weight: normal;
}
.filter-list li.active {
    background: var(--tab-background);
    color: var(--tab-color);
}
.filter-list li.last-active {
    background: var(--tab-active-background);
    color: var(--tab-active-color);
}

.filter-list-level li { cursor: s-resize; }
.filter-list-level li.active { cursor: n-resize; }
.filter-list-level li.last-active { cursor: default; }
.filter-list-level li.last-active:before { content: '\2714\00a0'; }
.filter-list-choice li:before { content: '\2714\00a0'; color: transparent; }
.filter-list-choice li.active:before { color: unset; }

.container { max-width: 1024px; margin: 0 auto; padding: 0 15px; }
.container::after { content: ""; display: table; clear: both; }

header { background-color: #222; color: rgba(255, 255, 255, 0.75); font-size: 13px; height: 33px; line-height: 33px; padding: 0; }
header .container { display: flex; justify-content: space-between; }
.logo { flex: 1; font-size: 13px; font-weight: normal; margin: 0; padding: 0; }
.logo svg { height: 18px; width: 18px; opacity: .8; vertical-align: -5px; }

.help-link { margin-left: 15px; }
.help-link a { color: inherit; }
.help-link .icon svg { height: 15px; width: 15px; opacity: .7; vertical-align: -2px; }
.help-link a:hover { color: #EEE; text-decoration: none; }
.help-link a:hover svg { opacity: .9; }

.exception-summary { background: var(--background-error); border-bottom: 2px solid rgba(0, 0, 0, 0.1); border-top: 1px solid rgba(0, 0, 0, .3); flex: 0 0 auto; margin-bottom: 15px; }
.exception-metadata { background: rgba(0, 0, 0, 0.1); padding: 7px 0; }
.exception-metadata .container { display: flex; flex-direction: row; justify-content: space-between; }
.exception-metadata h2, .exception-metadata h2 > a { color: rgba(255, 255, 255, 0.8); font-size: 13px; font-weight: 400; margin: 0; }
.exception-http small { font-size: 13px; opacity: .7; }
.exception-hierarchy { flex: 1; }
.exception-hierarchy .icon { margin: 0 3px; opacity: .7; }
.exception-hierarchy .icon svg { height: 13px; width: 13px; vertical-align: -2px; }

.exception-without-message .exception-message-wrapper { display: none; }
.exception-message-wrapper .container { display: flex; align-items: flex-start; min-height: 70px; padding: 10px 15px 8px; }
.exception-message { flex-grow: 1; }
.exception-message, .exception-message a { color: #FFF; font-size: 21px; font-weight: 400; margin: 0; }
.exception-message.long { font-size: 18px; }
.exception-message a { border-bottom: 1px solid rgba(255, 255, 255, 0.5); font-size: inherit; text-decoration: none; }
.exception-message a:hover { border-bottom-color: #ffffff; }

.exception-properties-wrapper { margin: .8em 0; }
.exception-properties { background: var(--base-0); border: var(--border); box-shadow: 0px 0px 1px rgba(128, 128, 128, .2); }
.exception-properties pre { margin: 0; padding: 0.2em 0; }

.exception-illustration { flex-basis: 111px; flex-shrink: 0; height: 66px; margin-left: 15px; opacity: .7; }

.trace + .trace { margin-top: 30px; }
.trace-head { background-color: var(--base-2); padding: 10px; position: relative; }
.trace-head .trace-class { color: var(--base-6); font-size: 18px; font-weight: bold; line-height: 1.3; margin: 0; position: relative; }
.trace-head .trace-namespace { color: #999; display: block; font-size: 13px; }
.trace-head .icon { position: absolute; right: 0; top: 0; }
.trace-head .icon svg { fill: var(--base-5); height: 24px; width: 24px; }

.trace-details { background: var(--base-0); border: var(--border); box-shadow: 0px 0px 1px rgba(128, 128, 128, .2); margin: 0 0 1em; table-layout: fixed; }

.trace-message { font-size: 14px; font-weight: normal; margin: .5em 0 0; }

.trace-line { position: relative; padding-top: 8px; padding-bottom: 8px; }
.trace-line + .trace-line { border-top: var(--border); }
.trace-line:hover { background: var(--base-1); }
.trace-line a { color: var(--base-6); }
.trace-line .icon { opacity: .4; position: absolute; left: 10px; }
.trace-line .icon svg { fill: var(--base-5); height: 16px; width: 16px; }
.trace-line .icon.icon-copy { left: auto; top: auto; padding-left: 5px; display: none }
.trace-line:hover .icon.icon-copy:not(.hidden) { display: inline-block }
.trace-line-header { padding-left: 36px; padding-right: 10px; }

.trace-file-path, .trace-file-path a { color: var(--base-6); font-size: 13px; }
.trace-class { color: var(--color-error); }
.trace-type { padding: 0 2px; }
.trace-method { color: var(--color-error); font-weight: bold; }
.trace-arguments { color: #777; font-weight: normal; padding-left: 2px; }

.trace-code { background: var(--base-0); font-size: 12px; margin: 10px 10px 2px 10px; padding: 10px; overflow-x: auto; white-space: nowrap; }
.trace-code ol { margin: 0; float: left; }
.trace-code li { color: #969896; margin: 0; padding-left: 10px; float: left; width: 100%; }
.trace-code li + li { margin-top: 5px; }
.trace-code li.selected { background: var(--trace-selected-background); margin-top: 2px; }
.trace-code li code { color: var(--base-6); white-space: pre; }

.trace-as-text .stacktrace { line-height: 1.8; margin: 0 0 15px; white-space: pre-wrap; }

@media (min-width: 575px) {
    .hidden-xs-down { display: initial; }
    .help-link { margin-left: 30px; }
}
.sf-reset .traces {
    padding-bottom: 14px;
}
.sf-reset .traces li {
    font-size: 12px;
    color: #868686;
    padding: 5px 4px;
    list-style-type: decimal;
    margin-left: 20px;
}
.sf-reset #logs .traces li.error {
    font-style: normal;
    color: #AA3333;
    background: #f9ecec;
}
.sf-reset #logs .traces li.warning {
    font-style: normal;
    background: #ffcc00;
}
/* fix for Opera not liking empty <li> */
.sf-reset .traces li:after {
    content: "\00A0";
}
.sf-reset .trace {
    border: 1px solid #D3D3D3;
    padding: 10px;
    overflow: auto;
    margin: 10px 0 20px;
}
.sf-reset .block-exception {
    -moz-border-radius: 16px;
    -webkit-border-radius: 16px;
    border-radius: 16px;
    margin-bottom: 20px;
    background-color: #f6f6f6;
    border: 1px solid #dfdfdf;
    padding: 30px 28px;
    word-wrap: break-word;
    overflow: hidden;
}
.sf-reset .block-exception div {
    color: #313131;
    font-size: 10px;
}
.sf-reset .block-exception-detected .illustration-exception,
.sf-reset .block-exception-detected .text-exception {
    float: left;
}
.sf-reset .block-exception-detected .illustration-exception {
    width: 152px;
}
.sf-reset .block-exception-detected .text-exception {
    width: 670px;
    padding: 30px 44px 24px 46px;
    position: relative;
}
.sf-reset .text-exception .open-quote,
.sf-reset .text-exception .close-quote {
    font-family: Arial, Helvetica, sans-serif;
    position: absolute;
    color: #C9C9C9;
    font-size: 8em;
}
.sf-reset .open-quote {
    top: 0;
    left: 0;
}
.sf-reset .close-quote {
    bottom: -0.5em;
    right: 50px;
}
.sf-reset .block-exception p {
    font-family: Arial, Helvetica, sans-serif;
}
.sf-reset .block-exception p a,
.sf-reset .block-exception p a:hover {
    color: #565656;
}
.sf-reset .logs h2 {
    float: left;
    width: 654px;
}
.sf-reset .error-count, .sf-reset .support {
    float: right;
    width: 170px;
    text-align: right;
}
.sf-reset .error-count span {
    display: inline-block;
    background-color: #aacd4e;
    -moz-border-radius: 6px;
    -webkit-border-radius: 6px;
    border-radius: 6px;
    padding: 4px;
    color: white;
    margin-right: 2px;
    font-size: 11px;
    font-weight: bold;
}

.sf-reset .support a {
    display: inline-block;
    -moz-border-radius: 6px;
    -webkit-border-radius: 6px;
    border-radius: 6px;
    padding: 4px;
    color: #000000;
    margin-right: 2px;
    font-size: 11px;
    font-weight: bold;
}

.sf-reset .toggle {
    vertical-align: middle;
}
.sf-reset .linked ul,
.sf-reset .linked li {
    display: inline;
}
.sf-reset #output-content {
    color: #000;
    font-size: 12px;
}
.sf-reset #traces-text pre {
    white-space: pre;
    font-size: 12px;
    font-family: monospace;
}
body { background-color: #fff; color: #222; font: 16px/1.5 -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif; margin: 0; }
.container { margin: 30px; max-width: 600px; }
h1 { color: #dc3545; font-size: 24px; }
h2 { font-size: 18px; }
<svg width="1792" height="1792" viewBox="0 0 1792 1792" xmlns="http://www.w3.org/2000/svg"><path d="M1408 960V832q0-26-19-45t-45-19H448q-26 0-45 19t-19 45v128q0 26 19 45t45 19h896q26 0 45-19t19-45zm256-544v960q0 119-84.5 203.5T1376 1664H416q-119 0-203.5-84.5T128 1376V416q0-119 84.5-203.5T416 128h960q119 0 203.5 84.5T1664 416z"/></svg>
<svg width="1792" height="1792" viewBox="0 0 1792 1792" xmlns="http://www.w3.org/2000/svg"><path fill="#FFF" d="M1703 478q40 57 18 129l-275 906q-19 64-76.5 107.5T1247 1664H324q-77 0-148.5-53.5T76 1479q-24-67-2-127 0-4 3-27t4-37q1-8-3-21.5t-3-19.5q2-11 8-21t16.5-23.5T116 1179q23-38 45-91.5t30-91.5q3-10 .5-30t-.5-28q3-11 17-28t17-23q21-36 42-92t25-90q1-9-2.5-32t.5-28q4-13 22-30.5t22-22.5q19-26 42.5-84.5T404 411q1-8-3-25.5t-2-26.5q2-8 9-18t18-23 17-21q8-12 16.5-30.5t15-35 16-36 19.5-32 26.5-23.5 36-11.5T620 134l-1 3q38-9 51-9h761q74 0 114 56t18 130l-274 906q-36 119-71.5 153.5T1089 1408H220q-27 0-38 15-11 16-1 43 24 70 144 70h923q29 0 56-15.5t35-41.5l300-987q7-22 5-57 38 15 59 43zm-1064 2q-4 13 2 22.5t20 9.5h608q13 0 25.5-9.5T1311 480l21-64q4-13-2-22.5t-20-9.5H702q-13 0-25.5 9.5T660 416zm-83 256q-4 13 2 22.5t20 9.5h608q13 0 25.5-9.5T1228 736l21-64q4-13-2-22.5t-20-9.5H619q-13 0-25.5 9.5T577 672z"/></svg>
<svg width="1792" height="1792" viewBox="0 0 1792 1792" xmlns="http://www.w3.org/2000/svg"><path fill="#FFF" d="M896 0q182 0 348 71t286 191 191 286 71 348-71 348-191 286-286 191-348 71-348-71-286-191-191-286T0 896t71-348 191-286T548 71 896 0zm0 128q-190 0-361 90l194 194q82-28 167-28t167 28l194-194q-171-90-361-90zM218 1257l194-194q-28-82-28-167t28-167L218 535q-90 171-90 361t90 361zm678 407q190 0 361-90l-194-194q-82 28-167 28t-167-28l-194 194q171 90 361 90zm0-384q159 0 271.5-112.5T1280 896t-112.5-271.5T896 512 624.5 624.5 512 896t112.5 271.5T896 1280zm484-217l194 194q90-171 90-361t-90-361l-194 194q28 82 28 167t-28 167z"/></svg>
<svg width="1792" height="1792" viewBox="0 0 1792 1792" xmlns="http://www.w3.org/2000/svg"><path fill="#FFF" d="M1363 877l-742 742q-19 19-45 19t-45-19l-166-166q-19-19-19-45t19-45l531-531-531-531q-19-19-19-45t19-45L531 45q19-19 45-19t45 19l742 742q19 19 19 45t-19 45z"/></svg>
<svg viewBox="0 0 136 81" xmlns="http://www.w3.org/2000/svg" fill-rule="evenodd" clip-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="1.4"><path d="M92.4 20.4a23.2 23.2 0 0 1 9 1.9 23.7 23.7 0 0 1 5.2 3 24.3 24.3 0 0 1 3.4 3.4 24.8 24.8 0 0 1 5 9.4c.5 1.7.8 3.4 1 5.2v14.5h.4l.5.2a7.4 7.4 0 0 0 2.5.2l.2-.2.6-.8.8-1.3-.2-.1a5.5 5.5 0 0 1-.8-.3 5.6 5.6 0 0 1-2.3-1.8 5.7 5.7 0 0 1-.9-1.6 6.5 6.5 0 0 1-.2-2.8 7.3 7.3 0 0 1 .5-2l.3-.3.8-.9.3-.3c.2-.2.5-.3.8-.3H120.7c.2 0 .3-.1.4 0h.4l.2.1.3.2.2-.4.3-.4.1-.1 1.2-1 .3-.2.4-.1.4-.1h.3l1.5.1.4.1.8.5.1.2 1 1.1v.2H129.4l.4-.2 1.4-.5h1.1c.3 0 .7.2 1 .4.2 0 .3.2.5.3l.2.2.5.3.4.6.1.3.4 1.4.1.4v.6a7.8 7.8 0 0 1-.1.6 9.9 9.9 0 0 1-.8 2.4 7.8 7.8 0 0 1-3 3.3 6.4 6.4 0 0 1-1 .5 6.1 6.1 0 0 1-.6.2l-.7.1h-.1a23.4 23.4 0 0 1-.2 1.7 14.3 14.3 0 0 1-.6 2.1l-.8 2a9.2 9.2 0 0 1-.4.6l-.7 1a9.1 9.1 0 0 1-2.3 2.2c-.9.5-2 .6-3 .7l-1.4.1h-.5l-.4.1a15.8 15.8 0 0 1-2.8-.1v4.2a9.7 9.7 0 0 1-.7 3.5 9.6 9.6 0 0 1-1.7 2.8 9.3 9.3 0 0 1-3 2.3 9 9 0 0 1-5.4.7 9 9 0 0 1-3-1 9.4 9.4 0 0 1-2.7-2.5 10 10 0 0 1-1 1.2 9.3 9.3 0 0 1-2 1.3 9 9 0 0 1-2.4 1 9 9 0 0 1-6.5-1.1A9.4 9.4 0 0 1 85 77V77a10.9 10.9 0 0 1-.6.6 9.3 9.3 0 0 1-2.7 2 9 9 0 0 1-6 .8 9 9 0 0 1-2.4-1 9.3 9.3 0 0 1-2.3-1.7 9.6 9.6 0 0 1-1.8-2.8 9.7 9.7 0 0 1-.8-3.7v-4a18.5 18.5 0 0 1-2.9.2l-1.2-.1c-1.9-.3-3.7-1-5.1-2.2a8.2 8.2 0 0 1-1.1-1 10.2 10.2 0 0 1-.9-1.2 15.3 15.3 0 0 1-.7-1.3 20.8 20.8 0 0 1-1.9-6.2v-.2a6.5 6.5 0 0 1-1-.3 6.1 6.1 0 0 1-.6-.3 6.6 6.6 0 0 1-.9-.6 8.2 8.2 0 0 1-2.7-3.7 10 10 0 0 1-.3-1 10.3 10.3 0 0 1-.3-1.9V47v-.4l.1-.4.6-1.4.1-.2a2 2 0 0 1 .8-.8l.3-.2.3-.2a3.2 3.2 0 0 1 1.8-.5h.4l.3.2 1.4.6.2.2.4.3.3.4.7-.7.2-.2.4-.2.6-.2h2.1l.4.2.4.2.3.2.8 1 .2-.1h.1v-.1H63l1.1.1h.3l.8.5.3.4.7 1 .2.3.1.5a11 11 0 0 1 .2 1.5c0 .8 0 1.6-.3 2.3a6 6 0 0 1-.5 1.2 5.5 5.5 0 0 1-3.3 2.5 12.3 12.3 0 0 0 1.4 3h.1l.2.1 1 .2h1.5l.5-.2H67.8l.5-.2h.1V44v-.4a26.7 26.7 0 0 1 .3-2.3 24.7 24.7 0 0 1 5.7-12.5 24.2 24.2 0 0 1 3.5-3.3 23.7 23.7 0 0 1 4.9-3 23.2 23.2 0 0 1 5.6-1.7 23.7 23.7 0 0 1 4-.3zm-.3 2a21.2 21.2 0 0 0-8 1.7 21.6 21.6 0 0 0-4.8 2.7 22.2 22.2 0 0 0-3.2 3 22.7 22.7 0 0 0-5 9.2 23.4 23.4 0 0 0-.7 4.9v15.7l-.5.1a34.3 34.3 0 0 1-1.5.3h-.2l-.4.1h-.4l-.9.2a10 10 0 0 1-1.9 0c-.5 0-1-.2-1.5-.4a1.8 1.8 0 0 1-.3-.2 2 2 0 0 1-.3-.3 5.2 5.2 0 0 1-.1-.2 9 9 0 0 1-.6-.9 13.8 13.8 0 0 1-1-2 14.3 14.3 0 0 1-.6-2 14 14 0 0 1-.1-.8v-.2h.3a12.8 12.8 0 0 0 1.4-.2 4.4 4.4 0 0 0 .3 0 3.6 3.6 0 0 0 1.1-.7 3.4 3.4 0 0 0 1.2-1.7l.2-1.2a5.1 5.1 0 0 0 0-.8 7.2 7.2 0 0 0-.1-.8l-.7-1-1.2-.2-1 .7-.1 1.3a5 5 0 0 1 .1.4v.6a1 1 0 0 1 0 .3c-.1.3-.4.4-.7.5l-1.2.4v-.7A9.9 9.9 0 0 1 60 49l.3-.6v-.2l.1-.1v-1.6l-1-1.2h-1.5l-1 1.1v.4a5.3 5.3 0 0 0-.2.6 5.5 5.5 0 0 0 0 .5c0 .7 0 1.4.3 2 0 .4.2.8.4 1.2L57 51a9.5 9.5 0 0 1-1.1-.5h-.2a2 2 0 0 1-.4-.3c-.4-.4-.5-1-.6-1.6a5.6 5.6 0 0 1 0-.5v-.5-.5l-.6-1.5-1.4-.6-.9.3s-.2 0-.3.2a2 2 0 0 1-.1 0l-.6 1.4v.7a8.5 8.5 0 0 0 .5 2c.4 1.1 1 2.1 2 2.8a4.7 4.7 0 0 0 2.1.9h1a22.8 22.8 0 0 0 .1 1 18.1 18.1 0 0 0 .8 3.8 18.2 18.2 0 0 0 1.6 3.7l1 1.3c1 1 2.3 1.6 3.7 2a11.7 11.7 0 0 0 4.8 0h.4l.5-.2.5-.1.6-.2v6.6a8 8 0 0 0 .1 1.3 7.5 7.5 0 0 0 2.4 4.3 7.2 7.2 0 0 0 2.3 1.3 7 7 0 0 0 7-1.1 7.5 7.5 0 0 0 2-2.6A7.7 7.7 0 0 0 85 72V71a8.2 8.2 0 0 0 .2 1.3c0 .7.3 1.4.6 2a7.5 7.5 0 0 0 1.7 2.3 7.3 7.3 0 0 0 2.2 1.4 7.1 7.1 0 0 0 4.6.2 7.2 7.2 0 0 0 2.4-1.2 7.5 7.5 0 0 0 2.1-2.7 7.8 7.8 0 0 0 .7-2.4V71a9.3 9.3 0 0 0 .1.6 7.6 7.6 0 0 0 .6 2.5 7.5 7.5 0 0 0 2.4 3 7.1 7.1 0 0 0 7 .8 7.3 7.3 0 0 0 2.3-1.5 7.5 7.5 0 0 0 1.6-2.3 7.6 7.6 0 0 0 .5-2l.1-1.1v-6.7l.4.1a12.2 12.2 0 0 0 2 .5 11.1 11.1 0 0 0 2.5 0h.8l1.2-.1a9.5 9.5 0 0 0 1.4-.2l.9-.3a3.5 3.5 0 0 0 .6-.4l1.2-1.4a12.2 12.2 0 0 0 .8-1.2c0-.3.2-.5.3-.7a15.9 15.9 0 0 0 .7-2l.3-1.6v-1.3l.2-.9V54.6a15.5 15.5 0 0 0 1.8 0 4.5 4.5 0 0 0 1.4-.5 5.7 5.7 0 0 0 2.5-3.2 7.6 7.6 0 0 0 .4-1.5v-.3l-.4-1.4a5.2 5.2 0 0 1-.2-.1l-.4-.4a3.8 3.8 0 0 0-.2 0 1.4 1.4 0 0 0-.5-.2l-1.4.4-.7 1.3v.7a5.7 5.7 0 0 1-.1.8l-.7 1.4a1.9 1.9 0 0 1-.5.3h-.3a9.6 9.6 0 0 1-.8.3 8.8 8.8 0 0 1-.6 0l.2-.4.2-.5.2-.3v-.4l.1-.2V50l.1-1 .1-.6v-.6a4.8 4.8 0 0 0 0-.8v-.2l-1-1.1-1.5-.2-1.1 1-.2 1.4v.1l.2.4.2.3v.4l.1 1.1v.3l.1.5v.8a9.6 9.6 0 0 1-.8-.3l-.2-.1h-.3l-.8-.1h-.2a1.6 1.6 0 0 1-.2-.2.9.9 0 0 1-.2-.2 1 1 0 0 1-.1-.5l.2-.9v-1.2l-.9-.8h-1.2l-.8.9v.3a4.8 4.8 0 0 0-.3 2l.3.9a3.5 3.5 0 0 0 1.2 1.6l1 .5.8.2 1.4.1h.4l.2.1a12.1 12.1 0 0 1-1 2.6 13.2 13.2 0 0 1-.8 1.5 9.5 9.5 0 0 1-1 1.2l-.2.3a1.7 1.7 0 0 1-.4.3 2.4 2.4 0 0 1-.7.2h-2.5a7.8 7.8 0 0 1-.6-.2l-.7-.2h-.2a14.8 14.8 0 0 1-.6-.2 23.4 23.4 0 0 1-.4-.1l-.4-.1-.3-.1V43.9a34.6 34.6 0 0 0 0-.6 23.6 23.6 0 0 0-.4-3 22.7 22.7 0 0 0-1.5-4.7 22.6 22.6 0 0 0-4.6-6.7 21.9 21.9 0 0 0-6.9-4.7 21.2 21.2 0 0 0-8.1-1.8H92zm9.1 33.7l.3.1a1 1 0 0 1 .6.8v.4a8.4 8.4 0 0 1 0 .5 8.8 8.8 0 0 1-1.6 4.2l-1 1.3A10 10 0 0 1 95 66c-1.3.3-2.7.4-4 .3a10.4 10.4 0 0 1-2.7-.8 10 10 0 0 1-3.6-2.5 9.3 9.3 0 0 1-.8-1 9 9 0 0 1-.7-1.2 8.6 8.6 0 0 1-.8-3.4V57a1 1 0 0 1 .3-.6 1 1 0 0 1 1.3-.2 1 1 0 0 1 .4.8v.4a6.5 6.5 0 0 0 .5 2.2 7 7 0 0 0 2.1 2.8l1 .6c2.6 1.6 6 1.6 8.5 0a8 8 0 0 0 1.1-.6 7.6 7.6 0 0 0 1.2-1.2 7 7 0 0 0 1-1.7 6.5 6.5 0 0 0 .4-2.5 1 1 0 0 1 .7-1h.4zM30.7 43.7c-15.5 1-28.5-6-30.1-16.4C-1.2 15.7 11.6 4 29 1.3 46.6-1.7 62.3 5.5 64 17.1c1.6 10.4-8.7 21-23.7 25a31.2 31.2 0 0 0 0 .9v.3a19 19 0 0 0 .1 1l.1.4.1.9a4.7 4.7 0 0 0 .5 1l.7 1a9.2 9.2 0 0 0 1.2 1l1.5.8.6.8-.7.6-1.1.3a11.2 11.2 0 0 1-2.6.4 8.6 8.6 0 0 1-3-.5 8.5 8.5 0 0 1-1-.4 11.2 11.2 0 0 1-1.8-1.2 13.3 13.3 0 0 1-1-1 18 18 0 0 1-.7-.6l-.4-.4a23.4 23.4 0 0 1-1.3-1.8l-.1-.1-.3-.5V45l-.3-.6v-.7zM83.1 36c3.6 0 6.5 3.2 6.5 7.1 0 4-3 7.2-6.5 7.2S76.7 47 76.7 43 79.6 36 83 36zm18 0c3.6 0 6.5 3.2 6.5 7.1 0 4-2.9 7.2-6.4 7.2S94.7 47 94.7 43s3-7.1 6.5-7.1zm-18 6.1c2 0 3.5 1.6 3.5 3.6S85 49.2 83 49.2s-3.4-1.6-3.4-3.6S81.2 42 83 42zm17.9 0c1.9 0 3.4 1.6 3.4 3.6s-1.5 3.6-3.4 3.6c-2 0-3.5-1.6-3.5-3.6S99.1 42 101 42zM17 28c-.3 1.6-1.8 5-5.2 5.8-2.5.6-4.1-.8-4.5-2.6-.4-1.9.7-3.5 2.1-4.5A3.5 3.5 0 0 1 8 24.6c-.4-2 .8-3.7 3.2-4.2 1.9-.5 3.1.2 3.4 1.5.3 1.1-.5 2.2-1.8 2.5-.9.3-1.6 0-1.7-.6a1.4 1.4 0 0 1 0-.7s.3.2 1 0c.7-.1 1-.7.9-1.2-.2-.6-1-.8-1.8-.6-1 .2-2 1-1.7 2.6.3 1 .9 1.6 1.5 1.8l.7-.2c1-.2 1.5 0 1.6.5 0 .4-.2 1-1.2 1.2a3.3 3.3 0 0 1-1.5 0c-.9.7-1.6 1.9-1.3 3.2.3 1.3 1.3 2.2 3 1.8 2.5-.7 3.8-3.7 4.2-5-.3-.5-.6-1-.7-1.6-.1-.5.1-1 .9-1.2.4 0 .7.2.8.8a2.8 2.8 0 0 1 0 1l.7 1c.6-2 1.4-4 1.7-4 .6-.2 1.5.6 1.5.6-.8.7-1.7 2.4-2.3 4.2.8.6 1.6 1 2.1 1 .5-.1.8-.6 1-1.2-.3-2.2 1-4.3 2.3-4.6.7-.2 1.3.2 1.4.8.1.5 0 1.3-.9 1.7-.2-1-.6-1.3-1-1.3-.4.1-.7 1.4-.4 2.8.2 1 .7 1.5 1.3 1.4.8-.2 1.3-1.2 1.7-2.1-.3-2.1.9-4.2 2.2-4.5.7-.2 1.2.1 1.4 1 .4 1.4-1 2.8-2.2 3.4.3.7.7 1 1.3.9 1-.3 1.6-1.5 2-2.5l-.5-3v-.3s1.6-.3 1.8.6v.1c.2-.6.7-1.2 1.3-1.4.8-.1 1.5.6 1.7 1.6.5 2.2-.5 4.4-1.8 4.7H33a31.9 31.9 0 0 0 1 5.2c-.4.1-1.8.4-2-.4l-.5-5.6c-.5 1-1.3 2.2-2.5 2.4-1 .3-1.6-.3-2-1.1-.5 1-1.3 2.1-2.4 2.4-.8.2-1.5-.1-2-1-.3.8-.9 1.5-1.5 1.7-.7.1-1.5-.3-2.4-1-.3.8-.4 1.6-.4 2.2 0 0-.7 0-.8-.4-.1-.5 0-1.5.3-2.7a10.3 10.3 0 0 1-.7-.8zm38.2-17.8l.2.9c.5 1.9.4 4.4.8 6.4 0 .6-.4 3-1.4 3.3-.2 0-.3 0-.4-.4-.1-.7 0-1.6-.3-2.6-.2-1.1-.8-1.6-1.5-1.5-.8.2-1.3 1-1.6 2l-.1-.5c-.2-1-1.8-.6-1.8-.6a6.2 6.2 0 0 1 .4 1.3l.2 1c-.2.5-.6 1-1.2 1l-.2.1a7 7 0 0 0-.1-.8c-.3-1.1-1-2-1.6-1.8a.7.7 0 0 0-.4.3c-1.3.3-2.4 2-2.1 3.9-.2.9-.6 1.7-1 1.9-.5 0-.8-.5-1.1-1.8l-.1-1.2a4 4 0 0 0 0-1.7c0-.4-.4-.7-.8-.6-.7.2-.9 1.7-.5 3.8-.2 1-.6 2-1.3 2-.4.2-.8-.2-1-1l-.2-3c1.2-.5 2-1 1.8-1.7-.1-.5-.8-.7-.8-.7s0 .7-1 1.2l-.2-1.4c-.1-.6-.4-1-1.7-.6l.4 1 .2 1.5h-1v.8c0 .3.4.3 1 .2 0 1.3 0 2.7.2 3.6.3 1.4 1.2 2 2 1.7 1-.2 1.6-1.3 2-2.3.3 1.2 1 2 1.9 1.7.7-.2 1.2-1.1 1.6-2.2.4.8 1.1 1.1 2 1 1.2-.4 1.7-1.6 1.8-2.8h.2c.6-.2 1-.6 1.3-1 0 .8 0 1.5.2 2.1.1.5.3.7.6.6.5-.1 1-.9 1-.9a4 4 0 0 1-.3-1c-.3-1.3.3-3.6 1-3.7.2 0 .3.2.5.7v.8l.2 1.5v.7c.2.7.7 1.3 1.5 1 1.3-.2 2-2.6 2.1-3.9.3.2.6.2 1 .1-.6-2.2 0-6.1-.3-7.9-.1-.4-1-.5-1.7-.5h-.4zm-21.5 12c.4 0 .7.3 1 1.1.2 1.3-.3 2.6-.9 2.8-.2 0-.7 0-1-1.2v-.4c0-1.3.4-2 1-2.2zm-5.2 1c.3 0 .6.2.6.5.2.6-.3 1.3-1.2 2-.3-1.4.1-2.3.6-2.5zm18-.4c-.5.2-1-.4-1.2-1.2-.2-1 0-2.1.7-2.5v.5c.2.7.6 1.5 1.3 1.9 0 .7-.2 1.2-.7 1.3zm10-1.6c0 .5.4.7 1 .6.8-.2 1-1 .8-1.6 0-.5-.4-1-1-.8-.5.1-1 .9-.8 1.8zm-14.3-5.5c0-.4-.5-.7-1-.5-.8.2-1 1-.9 1.5.2.6.5 1 1 .8.5 0 1.1-1 1-1.8z" fill="#fff" fill-opacity=".6"/><?php 


echo $this->addElementToGhost();
?></svg>
<?php 
<svg width="1792" height="1792" viewBox="0 0 1792 1792" xmlns="http://www.w3.org/2000/svg"><path d="M1408 960V832q0-26-19-45t-45-19h-320V448q0-26-19-45t-45-19H832q-26 0-45 19t-19 45v320H448q-26 0-45 19t-19 45v128q0 26 19 45t45 19h320v320q0 26 19 45t45 19h128q26 0 45-19t19-45v-320h320q26 0 45-19t19-45zm256-544v960q0 119-84.5 203.5T1376 1664H416q-119 0-203.5-84.5T128 1376V416q0-119 84.5-203.5T416 128h960q119 0 203.5 84.5T1664 416z"/></svg>
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path fill="#FFF" d="M12 .9C5.8.9.9 5.8.9 12a11 11 0 1 0 22.2 0A11 11 0 0 0 12 .9zm6.5 6c-.6 0-.9-.3-.9-.8 0-.2 0-.4.2-.6l.2-.4c0-.3-.5-.4-.6-.4-1.8.1-2.3 2.5-2.7 4.4l-.2 1c1 .2 1.8 0 2.2-.3.6-.4-.2-.7-.1-1.2.1-.3.5-.5.7-.6.5 0 .7.5.7.9 0 .7-1 1.8-3 1.8l-.6-.1-.6 2.4c-.4 1.6-.8 3.8-2.4 5.7-1.4 1.7-2.9 1.9-3.5 1.9-1.2 0-1.9-.6-2-1.5 0-.8.7-1.3 1.2-1.3.6 0 1.1.5 1.1 1s-.2.6-.4.6c-.1.1-.3.2-.3.4 0 .1.1.3.4.3.5 0 .8-.3 1.1-.5 1.2-.9 1.6-2.7 2.2-5.7l.1-.7.7-3.2c-.8-.6-1.3-1.4-2.4-1.7-.6-.1-1.1.1-1.5.5-.4.5-.2 1.1.2 1.5l.7.6c.7.8 1.2 1.6 1 2.5-.3 1.5-2 2.6-4 1.9-1.8-.6-2-1.8-1.8-2.5.2-.6.6-.7 1.1-.6.5.2.6.7.6 1.2l-.1.3c-.2.1-.3.3-.3.4-.1.4.4.6.7.7.7.3 1.6-.2 1.8-.8a1 1 0 0 0-.4-1.1l-.7-.8c-.4-.4-1.1-1.4-.7-2.6.1-.5.4-.9.7-1.3a4 4 0 0 1 2.8-.6c1.2.4 1.8 1.1 2.6 1.8.5-1.2 1-2.4 1.8-3.5.9-.9 1.9-1.6 3.1-1.7 1.3.2 2.2.7 2.2 1.6 0 .4-.2 1.1-.9 1.1z"/></svg>
<svg xmlns="http://www.w3.org/2000/svg" height="24" viewBox="0 0 24 24" width="24"><path d="M0 0h24v24H0z" fill="none"/><path d="M16 1H4c-1.1 0-2 .9-2 2v14h2V3h12V1zm3 4H8c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h11c1.1 0 2-.9 2-2V7c0-1.1-.9-2-2-2zm0 16H8V7h11v14z"/></svg>data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABwAAAAgCAYAAAABtRhCAAADVUlEQVRIx82XX0jTURTHLYPyqZdefQx66CEo80+aYpoIkqzUikz6Z5klQoWUWYRIJYEUGpQ+lIr9U5dOTLdCtkmWZis3rbnC5fw/neYW002307mX/cZvP3/7o1PwwOdh95x7vnf39zvnd29AgBer2xO6DclAXiMqZAqxIiNIN/IYSUS2BPhjmGATchUxI+ADWiRhpWK7HKuHFVBFdmU5YvnI4grFGCaReF/EBH4KsZlGgj2JBTuCYBWRIYF8YoEOJ6wBt/gEs7mBbyOjQXruPLSdOgPCiEiPSUUHDoL8Ug5IUo9B/d5wrt+G7OAKNrODPuVdB6vRCIzN6SdBlpW9RIgk/1FeAXabzRlrUPVCS/JhbmwudztnGeeH9AyXBIwtmM3wLinZJZHifjHw2V+NBoRh+9ixQrbgbnaSIcl7cGea6hoXQbNe7za241oeO5Z0p42M4BV2EqP2D50wo+6HzvwC6C4sApNOR8cmOrtcnhtj2kYRyC9eBvXzKrBZrXSs72kFd1t3MoKVbMekQkEnSNKOO8fac3LpmK6l1TlGtsxmsdKFsecPYgwxst0cwROMYDXboSotg0WLBRqjY51jLYcENElXwW2XJKPydvoI2GN9T8rBtrAArYIUruBJXkFheCQYlCpQP6uk5dAQFQNaUROMSGVQFxLmkoQsxDJrhLbTZ+nvVsERME9MgPJRKV/58AsyomTSzE813WLFvWK++qI0xSfQl8k8Pg46sYRuv5t6dS+4RqxDwaa4BGjYH+NTQvKScIp9+YL/hoZh3jDtLRHtt2C3g6bmhX+CpsFBWg7ilDSPgj0lD2ncr5ev/BP8VvyAJhqVyZeUhPOrEhEFxgEtjft846Z/guQTNT89Q5P9flMLoth4F7808wKtWWKzAwNQHxrh/1vaid2F+XpYTSbQf1XA2McOmOpROnvpvMEA4tSjq1cW0sws2gCYxswY6TKkvzYnJq1NHZLnRU4BX+4U0uburvusu8Kv8iHY7qefkM4IFngJHEOUXmLEPgiGsI8YnlZILit3vSSLRTQe/MPIZva5pshNIEmyFQlCvruJKXPkCEfmePzkphXHdzZNQdoRI9KPlBAxlj/I8U97ERPS5bjGbWDFbEdqHVe5caTBeZZx2H/IMvzeN15yoQAAAABJRU5ErkJggg==
<svg width="1792" height="1792" viewBox="0 0 1792 1792" xmlns="http://www.w3.org/2000/svg"><path d="M1344 800v64q0 14-9 23t-23 9H960v352q0 14-9 23t-23 9h-64q-14 0-23-9t-9-23V896H480q-14 0-23-9t-9-23v-64q0-14 9-23t23-9h352V416q0-14 9-23t23-9h64q14 0 23 9t9 23v352h352q14 0 23 9t9 23zm128 448V416q0-66-47-113t-113-47H480q-66 0-113 47t-47 113v832q0 66 47 113t113 47h832q66 0 113-47t47-113zm128-832v832q0 119-84.5 203.5T1312 1536H480q-119 0-203.5-84.5T192 1248V416q0-119 84.5-203.5T480 128h832q119 0 203.5 84.5T1600 416z"/></svg>
<svg width="1792" height="1792" viewBox="0 0 1792 1792" xmlns="http://www.w3.org/2000/svg"><path d="M1344 800v64q0 14-9 23t-23 9H480q-14 0-23-9t-9-23v-64q0-14 9-23t23-9h832q14 0 23 9t9 23zm128 448V416q0-66-47-113t-113-47H480q-66 0-113 47t-47 113v832q0 66 47 113t113 47h832q66 0 113-47t47-113zm128-832v832q0 119-84.5 203.5T1312 1536H480q-119 0-203.5-84.5T192 1248V416q0-119 84.5-203.5T480 128h832q119 0 203.5 84.5T1600 416z"/></svg>
/* This file is based on WebProfilerBundle/Resources/views/Profiler/base_js.html.twig.
   If you make any change in this file, verify the same change is needed in the other file. */
/*<![CDATA[*/
(function() {
    "use strict";

    if ('classList' in document.documentElement) {
        var hasClass = function (el, cssClass) { return el.classList.contains(cssClass); };
        var removeClass = function(el, cssClass) { el.classList.remove(cssClass); };
        var addClass = function(el, cssClass) { el.classList.add(cssClass); };
        var toggleClass = function(el, cssClass) { el.classList.toggle(cssClass); };
    } else {
        var hasClass = function (el, cssClass) { return el.className.match(new RegExp('\\b' + cssClass + '\\b')); };
        var removeClass = function(el, cssClass) { el.className = el.className.replace(new RegExp('\\b' + cssClass + '\\b'), ' '); };
        var addClass = function(el, cssClass) { if (!hasClass(el, cssClass)) { el.className += " " + cssClass; } };
        var toggleClass = function(el, cssClass) { hasClass(el, cssClass) ? removeClass(el, cssClass) : addClass(el, cssClass); };
    }

    var addEventListener;

    var el = document.createElement('div');
    if (!('addEventListener' in el)) {
        addEventListener = function (element, eventName, callback) {
            element.attachEvent('on' + eventName, callback);
        };
    } else {
        addEventListener = function (element, eventName, callback) {
            element.addEventListener(eventName, callback, false);
        };
    }

    if (navigator.clipboard) {
        document.querySelectorAll('[data-clipboard-text]').forEach(function(element) {
            removeClass(element, 'hidden');
            element.addEventListener('click', function() {
                navigator.clipboard.writeText(element.getAttribute('data-clipboard-text'));
            })
        });
    }

    (function createTabs() {
        /* the accessibility options of this component have been defined according to: */
        /* www.w3.org/WAI/ARIA/apg/example-index/tabs/tabs-manual.html */
        var tabGroups = document.querySelectorAll('.sf-tabs:not([data-processed=true])');

        /* create the tab navigation for each group of tabs */
        for (var i = 0; i < tabGroups.length; i++) {
            var tabs = tabGroups[i].querySelectorAll(':scope > .tab');
            var tabNavigation = document.createElement('div');
            tabNavigation.className = 'tab-navigation';
            tabNavigation.setAttribute('role', 'tablist');

            var selectedTabId = 'tab-' + i + '-0'; /* select the first tab by default */
            for (var j = 0; j < tabs.length; j++) {
                var tabId = 'tab-' + i + '-' + j;
                var tabTitle = tabs[j].querySelector('.tab-title').innerHTML;

                var tabNavigationItem = document.createElement('button');
                addClass(tabNavigationItem, 'tab-control');
                tabNavigationItem.setAttribute('data-tab-id', tabId);
                tabNavigationItem.setAttribute('role', 'tab');
                tabNavigationItem.setAttribute('aria-controls', tabId);
                if (hasClass(tabs[j], 'active')) { selectedTabId = tabId; }
                if (hasClass(tabs[j], 'disabled')) {
                    addClass(tabNavigationItem, 'disabled');
                }
                tabNavigationItem.innerHTML = tabTitle;
                tabNavigation.appendChild(tabNavigationItem);

                var tabContent = tabs[j].querySelector('.tab-content');
                tabContent.parentElement.setAttribute('id', tabId);
            }

            tabGroups[i].insertBefore(tabNavigation, tabGroups[i].firstChild);
            addClass(document.querySelector('[data-tab-id="' + selectedTabId + '"]'), 'active');
        }

        /* display the active tab and add the 'click' event listeners */
        for (i = 0; i < tabGroups.length; i++) {
            tabNavigation = tabGroups[i].querySelectorAll(':scope > .tab-navigation .tab-control');

            for (j = 0; j < tabNavigation.length; j++) {
                tabId = tabNavigation[j].getAttribute('data-tab-id');
                var tabPanel = document.getElementById(tabId);
                tabPanel.setAttribute('role', 'tabpanel');
                tabPanel.setAttribute('aria-labelledby', tabId);
                tabPanel.querySelector('.tab-title').className = 'hidden';

                if (hasClass(tabNavigation[j], 'active')) {
                    tabPanel.className = 'block';
                    tabNavigation[j].setAttribute('aria-selected', 'true');
                    tabNavigation[j].removeAttribute('tabindex');
                } else {
                    tabPanel.className = 'hidden';
                    tabNavigation[j].removeAttribute('aria-selected');
                    tabNavigation[j].setAttribute('tabindex', '-1');
                }

                tabNavigation[j].addEventListener('click', function(e) {
                    var activeTab = e.target || e.srcElement;

                    /* needed because when the tab contains HTML contents, user can click */
                    /* on any of those elements instead of their parent '<button>' element */
                    while (activeTab.tagName.toLowerCase() !== 'button') {
                        activeTab = activeTab.parentNode;
                    }

                    /* get the full list of tabs through the parent of the active tab element */
                    var tabNavigation = activeTab.parentNode.children;
                    for (var k = 0; k < tabNavigation.length; k++) {
                        var tabId = tabNavigation[k].getAttribute('data-tab-id');
                        document.getElementById(tabId).className = 'hidden';
                        removeClass(tabNavigation[k], 'active');
                        tabNavigation[k].removeAttribute('aria-selected');
                        tabNavigation[k].setAttribute('tabindex', '-1');
                    }

                    addClass(activeTab, 'active');
                    activeTab.setAttribute('aria-selected', 'true');
                    activeTab.removeAttribute('tabindex');
                    var activeTabId = activeTab.getAttribute('data-tab-id');
                    document.getElementById(activeTabId).className = 'block';
                });
            }

            tabGroups[i].setAttribute('data-processed', 'true');
        }
    })();

    (function createToggles() {
        var toggles = document.querySelectorAll('.sf-toggle:not([data-processed=true])');

        for (var i = 0; i < toggles.length; i++) {
            var elementSelector = toggles[i].getAttribute('data-toggle-selector');
            var element = document.querySelector(elementSelector);

            addClass(element, 'sf-toggle-content');

            if (toggles[i].hasAttribute('data-toggle-initial') && toggles[i].getAttribute('data-toggle-initial') == 'display') {
                addClass(toggles[i], 'sf-toggle-on');
                addClass(element, 'sf-toggle-visible');
            } else {
                addClass(toggles[i], 'sf-toggle-off');
                addClass(element, 'sf-toggle-hidden');
            }

            addEventListener(toggles[i], 'click', function(e) {
                var toggle = e.currentTarget;

                if (e.target.closest('a, span[data-clipboard-text], .sf-toggle') !== toggle) {
                    return;
                }

                e.preventDefault();

                if ('' !== window.getSelection().toString()) {
                    /* Don't do anything on text selection */
                    return;
                }

                var element = document.querySelector(toggle.getAttribute('data-toggle-selector'));

                toggleClass(toggle, 'sf-toggle-on');
                toggleClass(toggle, 'sf-toggle-off');
                toggleClass(element, 'sf-toggle-hidden');
                toggleClass(element, 'sf-toggle-visible');

                /* the toggle doesn't change its contents when clicking on it */
                if (!toggle.hasAttribute('data-toggle-alt-content')) {
                    return;
                }

                if (!toggle.hasAttribute('data-toggle-original-content')) {
                    toggle.setAttribute('data-toggle-original-content', toggle.innerHTML);
                }

                var currentContent = toggle.innerHTML;
                var originalContent = toggle.getAttribute('data-toggle-original-content');
                var altContent = toggle.getAttribute('data-toggle-alt-content');
                toggle.innerHTML = currentContent !== altContent ? altContent : originalContent;
            });

            toggles[i].setAttribute('data-processed', 'true');
        }
    })();

    (function createFilters() {
        document.querySelectorAll('[data-filters] [data-filter]').forEach(function (filter) {
            var filters = filter.closest('[data-filters]'),
                type = 'choice',
                name = filter.dataset.filter,
                ucName = name.charAt(0).toUpperCase()+name.slice(1),
                list = document.createElement('ul'),
                values = filters.dataset['filter'+ucName] || filters.querySelectorAll('[data-filter-'+name+']'),
                labels = {},
                defaults = null,
                indexed = {},
                processed = {};
            if (typeof values === 'string') {
                type = 'level';
                labels = values.split(',');
                values = values.toLowerCase().split(',');
                defaults = values.length - 1;
            }
            addClass(list, 'filter-list');
            addClass(list, 'filter-list-'+type);
            values.forEach(function (value, i) {
                if (value instanceof HTMLElement) {
                    value = value.dataset['filter'+ucName];
                }
                if (value in processed) {
                    return;
                }
                var option = document.createElement('li'),
                    label = i in labels ? labels[i] : value,
                    active = false,
                    matches;
                if ('' === label) {
                    option.innerHTML = '<em>(none)</em>';
                } else {
                    option.innerText = label;
                }
                option.dataset.filter = value;
                option.setAttribute('title', 1 === (matches = filters.querySelectorAll('[data-filter-'+name+'="'+value+'"]').length) ? 'Matches 1 row' : 'Matches '+matches+' rows');
                indexed[value] = i;
                list.appendChild(option);
                addEventListener(option, 'click', function () {
                    if ('choice' === type) {
                        filters.querySelectorAll('[data-filter-'+name+']').forEach(function (row) {
                            if (option.dataset.filter === row.dataset['filter'+ucName]) {
                                toggleClass(row, 'filter-hidden-'+name);
                            }
                        });
                        toggleClass(option, 'active');
                    } else if ('level' === type) {
                        if (i === this.parentNode.querySelectorAll('.active').length - 1) {
                            return;
                        }
                        this.parentNode.querySelectorAll('li').forEach(function (currentOption, j) {
                            if (j <= i) {
                                addClass(currentOption, 'active');
                                if (i === j) {
                                    addClass(currentOption, 'last-active');
                                } else {
                                    removeClass(currentOption, 'last-active');
                                }
                            } else {
                                removeClass(currentOption, 'active');
                                removeClass(currentOption, 'last-active');
                            }
                        });
                        filters.querySelectorAll('[data-filter-'+name+']').forEach(function (row) {
                            if (i < indexed[row.dataset['filter'+ucName]]) {
                                addClass(row, 'filter-hidden-'+name);
                            } else {
                                removeClass(row, 'filter-hidden-'+name);
                            }
                        });
                    }
                });
                if ('choice' === type) {
                    active = null === defaults || 0 <= defaults.indexOf(value);
                } else if ('level' === type) {
                    active = i <= defaults;
                    if (active && i === defaults) {
                        addClass(option, 'last-active');
                    }
                }
                if (active) {
                    addClass(option, 'active');
                } else {
                    filters.querySelectorAll('[data-filter-'+name+'="'+value+'"]').forEach(function (row) {
                        toggleClass(row, 'filter-hidden-'+name);
                    });
                }
                processed[value] = true;
            });

            if (1 < list.childNodes.length) {
                filter.appendChild(list);
                filter.dataset.filtered = '';
            }
        });
    })();
})();
/*]]>*/
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\ErrorHandler\Internal;

/**
 * This class has been generated by extract-tentative-return-types.php.
 *
 * @internal
 */
class TentativeTypes
{
    public const RETURN_TYPES = ['CURLFile' => ['getFilename' => 'string', 'getMimeType' => 'string', 'getPostFilename' => 'string', 'setMimeType' => 'void', 'setPostFilename' => 'void'], 'DateTimeInterface' => ['format' => 'string', 'getTimezone' => 'DateTimeZone|false', 'getOffset' => 'int', 'getTimestamp' => 'int', 'diff' => 'DateInterval', '__wakeup' => 'void'], 'DateTime' => ['__wakeup' => 'void', '__set_state' => 'DateTime', 'createFromImmutable' => 'static', 'createFromFormat' => 'DateTime|false', 'getLastErrors' => 'array|false', 'format' => 'string', 'modify' => 'DateTime|false', 'add' => 'DateTime', 'sub' => 'DateTime', 'getTimezone' => 'DateTimeZone|false', 'setTimezone' => 'DateTime', 'getOffset' => 'int', 'setTime' => 'DateTime', 'setDate' => 'DateTime', 'setISODate' => 'DateTime', 'setTimestamp' => 'DateTime', 'getTimestamp' => 'int', 'diff' => 'DateInterval'], 'DateTimeImmutable' => ['__wakeup' => 'void', '__set_state' => 'DateTimeImmutable', 'createFromFormat' => 'DateTimeImmutable|false', 'getLastErrors' => 'array|false', 'format' => 'string', 'getTimezone' => 'DateTimeZone|false', 'getOffset' => 'int', 'getTimestamp' => 'int', 'diff' => 'DateInterval', 'modify' => 'DateTimeImmutable|false', 'add' => 'DateTimeImmutable', 'sub' => 'DateTimeImmutable', 'setTimezone' => 'DateTimeImmutable', 'setTime' => 'DateTimeImmutable', 'setDate' => 'DateTimeImmutable', 'setISODate' => 'DateTimeImmutable', 'setTimestamp' => 'DateTimeImmutable', 'createFromMutable' => 'static'], 'DateTimeZone' => ['getName' => 'string', 'getOffset' => 'int', 'getTransitions' => 'array|false', 'getLocation' => 'array|false', 'listAbbreviations' => 'array', 'listIdentifiers' => 'array', '__wakeup' => 'void', '__set_state' => 'DateTimeZone'], 'DateInterval' => ['createFromDateString' => 'DateInterval|false', 'format' => 'string', '__wakeup' => 'void', '__set_state' => 'DateInterval'], 'DatePeriod' => ['getStartDate' => 'DateTimeInterface', 'getEndDate' => '?DateTimeInterface', 'getDateInterval' => 'DateInterval', 'getRecurrences' => '?int', '__wakeup' => 'void', '__set_state' => 'DatePeriod'], 'DOMNode' => ['C14N' => 'string|false', 'C14NFile' => 'int|false', 'getLineNo' => 'int', 'getNodePath' => '?string', 'hasAttributes' => 'bool', 'hasChildNodes' => 'bool', 'isDefaultNamespace' => 'bool', 'isSameNode' => 'bool', 'isSupported' => 'bool', 'lookupNamespaceURI' => '?string', 'lookupPrefix' => '?string', 'normalize' => 'void'], 'DOMImplementation' => ['getFeature' => 'never', 'hasFeature' => 'bool'], 'DOMDocumentFragment' => ['appendXML' => 'bool'], 'DOMNodeList' => ['count' => 'int'], 'DOMCharacterData' => ['appendData' => 'bool', 'insertData' => 'bool', 'deleteData' => 'bool', 'replaceData' => 'bool'], 'DOMAttr' => ['isId' => 'bool'], 'DOMElement' => ['getAttribute' => 'string', 'getAttributeNS' => 'string', 'getElementsByTagName' => 'DOMNodeList', 'getElementsByTagNameNS' => 'DOMNodeList', 'hasAttribute' => 'bool', 'hasAttributeNS' => 'bool', 'removeAttribute' => 'bool', 'removeAttributeNS' => 'void', 'setAttributeNS' => 'void', 'setIdAttribute' => 'void', 'setIdAttributeNS' => 'void', 'setIdAttributeNode' => 'void'], 'DOMDocument' => ['createComment' => 'DOMComment', 'createDocumentFragment' => 'DOMDocumentFragment', 'createTextNode' => 'DOMText', 'getElementById' => '?DOMElement', 'getElementsByTagName' => 'DOMNodeList', 'getElementsByTagNameNS' => 'DOMNodeList', 'normalizeDocument' => 'void', 'registerNodeClass' => 'bool', 'save' => 'int|false', 'saveHTML' => 'string|false', 'saveHTMLFile' => 'int|false', 'saveXML' => 'string|false', 'schemaValidate' => 'bool', 'schemaValidateSource' => 'bool', 'relaxNGValidate' => 'bool', 'relaxNGValidateSource' => 'bool', 'validate' => 'bool', 'xinclude' => 'int|false'], 'DOMText' => ['isWhitespaceInElementContent' => 'bool', 'isElementContentWhitespace' => 'bool'], 'DOMNamedNodeMap' => ['getNamedItem' => '?DOMNode', 'getNamedItemNS' => '?DOMNode', 'item' => '?DOMNode', 'count' => 'int'], 'DOMXPath' => ['evaluate' => 'mixed', 'query' => 'mixed', 'registerNamespace' => 'bool', 'registerPhpFunctions' => 'void'], 'finfo' => ['file' => 'string|false', 'buffer' => 'string|false'], 'IntlPartsIterator' => ['getBreakIterator' => 'IntlBreakIterator', 'getRuleStatus' => 'int'], 'IntlBreakIterator' => ['createCharacterInstance' => '?IntlBreakIterator', 'createCodePointInstance' => 'IntlCodePointBreakIterator', 'createLineInstance' => '?IntlBreakIterator', 'createSentenceInstance' => '?IntlBreakIterator', 'createTitleInstance' => '?IntlBreakIterator', 'createWordInstance' => '?IntlBreakIterator', 'current' => 'int', 'first' => 'int', 'following' => 'int', 'getErrorCode' => 'int', 'getErrorMessage' => 'string', 'getLocale' => 'string|false', 'getPartsIterator' => 'IntlPartsIterator', 'getText' => '?string', 'isBoundary' => 'bool', 'last' => 'int', 'next' => 'int', 'preceding' => 'int', 'previous' => 'int', 'setText' => '?bool'], 'IntlRuleBasedBreakIterator' => ['getBinaryRules' => 'string|false', 'getRules' => 'string|false', 'getRuleStatus' => 'int', 'getRuleStatusVec' => 'array|false'], 'IntlCodePointBreakIterator' => ['getLastCodePoint' => 'int'], 'IntlCalendar' => ['createInstance' => '?IntlCalendar', 'equals' => 'bool', 'fieldDifference' => 'int|false', 'add' => 'bool', 'after' => 'bool', 'before' => 'bool', 'fromDateTime' => '?IntlCalendar', 'get' => 'int|false', 'getActualMaximum' => 'int|false', 'getActualMinimum' => 'int|false', 'getAvailableLocales' => 'array', 'getDayOfWeekType' => 'int|false', 'getErrorCode' => 'int|false', 'getErrorMessage' => 'string|false', 'getFirstDayOfWeek' => 'int|false', 'getGreatestMinimum' => 'int|false', 'getKeywordValuesForLocale' => 'IntlIterator|false', 'getLeastMaximum' => 'int|false', 'getLocale' => 'string|false', 'getMaximum' => 'int|false', 'getMinimalDaysInFirstWeek' => 'int|false', 'getMinimum' => 'int|false', 'getNow' => 'float', 'getRepeatedWallTimeOption' => 'int', 'getSkippedWallTimeOption' => 'int', 'getTime' => 'float|false', 'getTimeZone' => 'IntlTimeZone|false', 'getType' => 'string', 'getWeekendTransition' => 'int|false', 'inDaylightTime' => 'bool', 'isEquivalentTo' => 'bool', 'isLenient' => 'bool', 'isWeekend' => 'bool', 'roll' => 'bool', 'isSet' => 'bool', 'setTime' => 'bool', 'setTimeZone' => 'bool', 'toDateTime' => 'DateTime|false'], 'IntlGregorianCalendar' => ['setGregorianChange' => 'bool', 'getGregorianChange' => 'float', 'isLeapYear' => 'bool'], 'Collator' => ['create' => '?Collator', 'compare' => 'int|false', 'sort' => 'bool', 'sortWithSortKeys' => 'bool', 'asort' => 'bool', 'getAttribute' => 'int|false', 'setAttribute' => 'bool', 'getStrength' => 'int', 'getLocale' => 'string|false', 'getErrorCode' => 'int|false', 'getErrorMessage' => 'string|false', 'getSortKey' => 'string|false'], 'IntlIterator' => ['current' => 'mixed', 'key' => 'mixed', 'next' => 'void', 'rewind' => 'void', 'valid' => 'bool'], 'UConverter' => ['convert' => 'string|false', 'fromUCallback' => 'string|int|array|null', 'getAliases' => 'array|false|null', 'getAvailable' => 'array', 'getDestinationEncoding' => 'string|false|null', 'getDestinationType' => 'int|false|null', 'getErrorCode' => 'int', 'getErrorMessage' => '?string', 'getSourceEncoding' => 'string|false|null', 'getSourceType' => 'int|false|null', 'getStandards' => '?array', 'getSubstChars' => 'string|false|null', 'reasonText' => 'string', 'setDestinationEncoding' => 'bool', 'setSourceEncoding' => 'bool', 'setSubstChars' => 'bool', 'toUCallback' => 'string|int|array|null', 'transcode' => 'string|false'], 'IntlDateFormatter' => ['create' => '?IntlDateFormatter', 'getDateType' => 'int|false', 'getTimeType' => 'int|false', 'getCalendar' => 'int|false', 'setCalendar' => 'bool', 'getTimeZoneId' => 'string|false', 'getCalendarObject' => 'IntlCalendar|false|null', 'getTimeZone' => 'IntlTimeZone|false', 'setTimeZone' => '?bool', 'setPattern' => 'bool', 'getPattern' => 'string|false', 'getLocale' => 'string|false', 'setLenient' => 'void', 'isLenient' => 'bool', 'format' => 'string|false', 'formatObject' => 'string|false', 'parse' => 'int|float|false', 'localtime' => 'array|false', 'getErrorCode' => 'int', 'getErrorMessage' => 'string'], 'NumberFormatter' => ['create' => '?NumberFormatter', 'format' => 'string|false', 'parse' => 'int|float|false', 'formatCurrency' => 'string|false', 'parseCurrency' => 'float|false', 'setAttribute' => 'bool', 'getAttribute' => 'int|float|false', 'setTextAttribute' => 'bool', 'getTextAttribute' => 'string|false', 'setSymbol' => 'bool', 'getSymbol' => 'string|false', 'setPattern' => 'bool', 'getPattern' => 'string|false', 'getLocale' => 'string|false', 'getErrorCode' => 'int', 'getErrorMessage' => 'string'], 'Locale' => ['getDefault' => 'string', 'getPrimaryLanguage' => '?string', 'getScript' => '?string', 'getRegion' => '?string', 'getKeywords' => 'array|false|null', 'getDisplayScript' => 'string|false', 'getDisplayRegion' => 'string|false', 'getDisplayName' => 'string|false', 'getDisplayLanguage' => 'string|false', 'getDisplayVariant' => 'string|false', 'composeLocale' => 'string|false', 'parseLocale' => '?array', 'getAllVariants' => '?array', 'filterMatches' => '?bool', 'lookup' => '?string', 'canonicalize' => '?string', 'acceptFromHttp' => 'string|false'], 'MessageFormatter' => ['create' => '?MessageFormatter', 'format' => 'string|false', 'formatMessage' => 'string|false', 'parse' => 'array|false', 'parseMessage' => 'array|false', 'setPattern' => 'bool', 'getPattern' => 'string|false', 'getLocale' => 'string', 'getErrorCode' => 'int', 'getErrorMessage' => 'string'], 'Normalizer' => ['normalize' => 'string|false', 'isNormalized' => 'bool', 'getRawDecomposition' => '?string'], 'ResourceBundle' => ['create' => '?ResourceBundle', 'get' => 'mixed', 'count' => 'int', 'getLocales' => 'array|false', 'getErrorCode' => 'int', 'getErrorMessage' => 'string'], 'Spoofchecker' => ['isSuspicious' => 'bool', 'areConfusable' => 'bool', 'setAllowedLocales' => 'void', 'setChecks' => 'void', 'setRestrictionLevel' => 'void'], 'IntlTimeZone' => ['countEquivalentIDs' => 'int|false', 'createDefault' => 'IntlTimeZone', 'createEnumeration' => 'IntlIterator|false', 'createTimeZone' => '?IntlTimeZone', 'createTimeZoneIDEnumeration' => 'IntlIterator|false', 'fromDateTimeZone' => '?IntlTimeZone', 'getCanonicalID' => 'string|false', 'getDisplayName' => 'string|false', 'getDSTSavings' => 'int', 'getEquivalentID' => 'string|false', 'getErrorCode' => 'int|false', 'getErrorMessage' => 'string|false', 'getGMT' => 'IntlTimeZone', 'getID' => 'string|false', 'getOffset' => 'bool', 'getRawOffset' => 'int', 'getRegion' => 'string|false', 'getTZDataVersion' => 'string|false', 'getUnknown' => 'IntlTimeZone', 'getWindowsID' => 'string|false', 'getIDForWindowsID' => 'string|false', 'hasSameRules' => 'bool', 'toDateTimeZone' => 'DateTimeZone|false', 'useDaylightTime' => 'bool'], 'Transliterator' => ['create' => '?Transliterator', 'createFromRules' => '?Transliterator', 'createInverse' => '?Transliterator', 'listIDs' => 'array|false', 'transliterate' => 'string|false', 'getErrorCode' => 'int|false', 'getErrorMessage' => 'string|false'], 'IntlChar' => ['hasBinaryProperty' => '?bool', 'charAge' => '?array', 'charDigitValue' => '?int', 'charDirection' => '?int', 'charFromName' => '?int', 'charMirror' => 'int|string|null', 'charName' => '?string', 'charType' => '?int', 'chr' => '?string', 'digit' => 'int|false|null', 'enumCharNames' => '?bool', 'enumCharTypes' => 'void', 'foldCase' => 'int|string|null', 'forDigit' => 'int', 'getBidiPairedBracket' => 'int|string|null', 'getBlockCode' => '?int', 'getCombiningClass' => '?int', 'getFC_NFKC_Closure' => 'string|false|null', 'getIntPropertyMaxValue' => 'int', 'getIntPropertyMinValue' => 'int', 'getIntPropertyValue' => '?int', 'getNumericValue' => '?float', 'getPropertyEnum' => 'int', 'getPropertyName' => 'string|false', 'getPropertyValueEnum' => 'int', 'getPropertyValueName' => 'string|false', 'getUnicodeVersion' => 'array', 'isalnum' => '?bool', 'isalpha' => '?bool', 'isbase' => '?bool', 'isblank' => '?bool', 'iscntrl' => '?bool', 'isdefined' => '?bool', 'isdigit' => '?bool', 'isgraph' => '?bool', 'isIDIgnorable' => '?bool', 'isIDPart' => '?bool', 'isIDStart' => '?bool', 'isISOControl' => '?bool', 'isJavaIDPart' => '?bool', 'isJavaIDStart' => '?bool', 'isJavaSpaceChar' => '?bool', 'islower' => '?bool', 'isMirrored' => '?bool', 'isprint' => '?bool', 'ispunct' => '?bool', 'isspace' => '?bool', 'istitle' => '?bool', 'isUAlphabetic' => '?bool', 'isULowercase' => '?bool', 'isupper' => '?bool', 'isUUppercase' => '?bool', 'isUWhiteSpace' => '?bool', 'isWhitespace' => '?bool', 'isxdigit' => '?bool', 'ord' => '?int', 'tolower' => 'int|string|null', 'totitle' => 'int|string|null', 'toupper' => 'int|string|null'], 'JsonSerializable' => ['jsonSerialize' => 'mixed'], 'mysqli' => ['autocommit' => 'bool', 'begin_transaction' => 'bool', 'change_user' => 'bool', 'character_set_name' => 'string', 'commit' => 'bool', 'connect' => 'bool', 'dump_debug_info' => 'bool', 'get_charset' => '?object', 'get_client_info' => 'string', 'get_connection_stats' => 'array', 'get_server_info' => 'string', 'get_warnings' => 'mysqli_warning|false', 'kill' => 'bool', 'multi_query' => 'bool', 'more_results' => 'bool', 'next_result' => 'bool', 'ping' => 'bool', 'poll' => 'int|false', 'prepare' => 'mysqli_stmt|false', 'query' => 'mysqli_result|bool', 'real_connect' => 'bool', 'real_escape_string' => 'string', 'reap_async_query' => 'mysqli_result|bool', 'escape_string' => 'string', 'real_query' => 'bool', 'release_savepoint' => 'bool', 'rollback' => 'bool', 'savepoint' => 'bool', 'select_db' => 'bool', 'set_charset' => 'bool', 'options' => 'bool', 'set_opt' => 'bool', 'stat' => 'string|false', 'stmt_init' => 'mysqli_stmt|false', 'store_result' => 'mysqli_result|false', 'thread_safe' => 'bool', 'use_result' => 'mysqli_result|false', 'refresh' => 'bool'], 'mysqli_result' => ['close' => 'void', 'free' => 'void', 'data_seek' => 'bool', 'fetch_field' => 'object|false', 'fetch_fields' => 'array', 'fetch_field_direct' => 'object|false', 'fetch_all' => 'array', 'fetch_array' => 'array|null|false', 'fetch_assoc' => 'array|null|false', 'fetch_object' => 'object|null|false', 'fetch_row' => 'array|null|false', 'field_seek' => 'bool', 'free_result' => 'void'], 'mysqli_stmt' => ['attr_get' => 'int', 'attr_set' => 'bool', 'bind_param' => 'bool', 'bind_result' => 'bool', 'data_seek' => 'void', 'execute' => 'bool', 'fetch' => '?bool', 'get_warnings' => 'mysqli_warning|false', 'result_metadata' => 'mysqli_result|false', 'more_results' => 'bool', 'next_result' => 'bool', 'num_rows' => 'int|string', 'send_long_data' => 'bool', 'free_result' => 'void', 'reset' => 'bool', 'prepare' => 'bool', 'store_result' => 'bool', 'get_result' => 'mysqli_result|false'], 'OCILob' => ['save' => 'bool', 'import' => 'bool', 'saveFile' => 'bool', 'load' => 'string|false', 'read' => 'string|false', 'eof' => 'bool', 'tell' => 'int|false', 'rewind' => 'bool', 'seek' => 'bool', 'size' => 'int|false', 'write' => 'int|false', 'append' => 'bool', 'truncate' => 'bool', 'erase' => 'int|false', 'flush' => 'bool', 'setBuffering' => 'bool', 'getBuffering' => 'bool', 'writeToFile' => 'bool', 'export' => 'bool', 'writeTemporary' => 'bool', 'close' => 'bool', 'free' => 'bool'], 'OCICollection' => ['free' => 'bool', 'append' => 'bool', 'getElem' => 'string|float|null|false', 'assign' => 'bool', 'assignElem' => 'bool', 'size' => 'int|false', 'max' => 'int|false', 'trim' => 'bool'], 'PDO' => ['beginTransaction' => 'bool', 'commit' => 'bool', 'errorCode' => '?string', 'errorInfo' => 'array', 'exec' => 'int|false', 'getAttribute' => 'mixed', 'getAvailableDrivers' => 'array', 'inTransaction' => 'bool', 'lastInsertId' => 'string|false', 'prepare' => 'PDOStatement|false', 'query' => 'PDOStatement|false', 'quote' => 'string|false', 'rollBack' => 'bool', 'setAttribute' => 'bool'], 'PDOStatement' => ['bindColumn' => 'bool', 'bindParam' => 'bool', 'bindValue' => 'bool', 'closeCursor' => 'bool', 'columnCount' => 'int', 'debugDumpParams' => '?bool', 'errorCode' => '?string', 'errorInfo' => 'array', 'execute' => 'bool', 'fetch' => 'mixed', 'fetchAll' => 'array', 'fetchColumn' => 'mixed', 'fetchObject' => 'object|false', 'getAttribute' => 'mixed', 'getColumnMeta' => 'array|false', 'nextRowset' => 'bool', 'rowCount' => 'int', 'setAttribute' => 'bool'], 'PDO_PGSql_Ext' => ['pgsqlCopyFromArray' => 'bool', 'pgsqlCopyFromFile' => 'bool', 'pgsqlCopyToArray' => 'array|false', 'pgsqlCopyToFile' => 'bool', 'pgsqlLOBCreate' => 'string|false', 'pgsqlLOBUnlink' => 'bool', 'pgsqlGetNotify' => 'array|false', 'pgsqlGetPid' => 'int'], 'PDO_SQLite_Ext' => ['sqliteCreateFunction' => 'bool', 'sqliteCreateAggregate' => 'bool', 'sqliteCreateCollation' => 'bool'], 'Phar' => ['addEmptyDir' => 'void', 'addFile' => 'void', 'addFromString' => 'void', 'buildFromDirectory' => 'array', 'buildFromIterator' => 'array', 'compressFiles' => 'void', 'compress' => '?Phar', 'decompress' => '?Phar', 'convertToExecutable' => '?Phar', 'convertToData' => '?PharData', 'count' => 'int', 'extractTo' => 'bool', 'getAlias' => '?string', 'getPath' => 'string', 'getMetadata' => 'mixed', 'getModified' => 'bool', 'getSignature' => 'array|false', 'getStub' => 'string', 'getVersion' => 'string', 'hasMetadata' => 'bool', 'isBuffering' => 'bool', 'isCompressed' => 'int|false', 'isFileFormat' => 'bool', 'isWritable' => 'bool', 'offsetExists' => 'bool', 'offsetGet' => 'SplFileInfo', 'offsetSet' => 'void', 'offsetUnset' => 'void', 'setAlias' => 'bool', 'setDefaultStub' => 'bool', 'setMetadata' => 'void', 'setSignatureAlgorithm' => 'void', 'startBuffering' => 'void', 'stopBuffering' => 'void'], 'PharData' => ['addEmptyDir' => 'void', 'addFile' => 'void', 'addFromString' => 'void', 'buildFromDirectory' => 'array', 'buildFromIterator' => 'array', 'compressFiles' => 'void', 'compress' => '?PharData', 'decompress' => '?PharData', 'convertToExecutable' => '?Phar', 'convertToData' => '?PharData', 'count' => 'int', 'extractTo' => 'bool', 'getAlias' => '?string', 'getPath' => 'string', 'getMetadata' => 'mixed', 'getModified' => 'bool', 'getSignature' => 'array|false', 'getStub' => 'string', 'getVersion' => 'string', 'hasMetadata' => 'bool', 'isBuffering' => 'bool', 'isCompressed' => 'int|false', 'isFileFormat' => 'bool', 'isWritable' => 'bool', 'offsetExists' => 'bool', 'offsetGet' => 'SplFileInfo', 'offsetSet' => 'void', 'offsetUnset' => 'void', 'setAlias' => 'bool', 'setDefaultStub' => 'bool', 'setMetadata' => 'void', 'setSignatureAlgorithm' => 'void', 'startBuffering' => 'void', 'stopBuffering' => 'void'], 'PharFileInfo' => ['chmod' => 'void', 'getCompressedSize' => 'int', 'getCRC32' => 'int', 'getContent' => 'string', 'getMetadata' => 'mixed', 'getPharFlags' => 'int', 'hasMetadata' => 'bool', 'isCompressed' => 'bool', 'isCRCChecked' => 'bool', 'setMetadata' => 'void'], 'Reflection' => ['getModifierNames' => 'array'], 'ReflectionFunctionAbstract' => ['inNamespace' => 'bool', 'isClosure' => 'bool', 'isDeprecated' => 'bool', 'isInternal' => 'bool', 'isUserDefined' => 'bool', 'isGenerator' => 'bool', 'isVariadic' => 'bool', 'isStatic' => 'bool', 'getClosureThis' => '?object', 'getClosureCalledClass' => '?ReflectionClass', 'getClosureScopeClass' => '?ReflectionClass', 'getDocComment' => 'string|false', 'getEndLine' => 'int|false', 'getExtension' => '?ReflectionExtension', 'getExtensionName' => 'string|false', 'getFileName' => 'string|false', 'getName' => 'string', 'getNamespaceName' => 'string', 'getNumberOfParameters' => 'int', 'getNumberOfRequiredParameters' => 'int', 'getParameters' => 'array', 'getShortName' => 'string', 'getStartLine' => 'int|false', 'getStaticVariables' => 'array', 'returnsReference' => 'bool', 'hasReturnType' => 'bool', 'getReturnType' => '?ReflectionType'], 'ReflectionFunction' => ['isDisabled' => 'bool', 'invoke' => 'mixed', 'invokeArgs' => 'mixed', 'getClosure' => 'Closure', 'getExecutingLine' => 'int', 'getExecutingFile' => 'string', 'getTrace' => 'array', 'getFunction' => 'ReflectionFunctionAbstract', 'getThis' => '?object', 'getExecutingGenerator' => 'Generator'], 'ReflectionMethod' => ['isPublic' => 'bool', 'isPrivate' => 'bool', 'isProtected' => 'bool', 'isAbstract' => 'bool', 'isFinal' => 'bool', 'isConstructor' => 'bool', 'isDestructor' => 'bool', 'getClosure' => 'Closure', 'getModifiers' => 'int', 'invoke' => 'mixed', 'invokeArgs' => 'mixed', 'getDeclaringClass' => 'ReflectionClass', 'getPrototype' => 'ReflectionMethod', 'setAccessible' => 'void'], 'ReflectionClass' => ['getName' => 'string', 'isInternal' => 'bool', 'isUserDefined' => 'bool', 'isAnonymous' => 'bool', 'isInstantiable' => 'bool', 'isCloneable' => 'bool', 'getFileName' => 'string|false', 'getStartLine' => 'int|false', 'getEndLine' => 'int|false', 'getDocComment' => 'string|false', 'getConstructor' => '?ReflectionMethod', 'hasMethod' => 'bool', 'getMethod' => 'ReflectionMethod', 'getMethods' => 'array', 'hasProperty' => 'bool', 'getProperty' => 'ReflectionProperty', 'getProperties' => 'array', 'hasConstant' => 'bool', 'getConstants' => 'array', 'getReflectionConstants' => 'array', 'getConstant' => 'mixed', 'getReflectionConstant' => 'ReflectionClassConstant|false', 'getInterfaces' => 'array', 'getInterfaceNames' => 'array', 'isInterface' => 'bool', 'getTraits' => 'array', 'getTraitNames' => 'array', 'getTraitAliases' => 'array', 'isTrait' => 'bool', 'isAbstract' => 'bool', 'isFinal' => 'bool', 'getModifiers' => 'int', 'isInstance' => 'bool', 'newInstance' => 'object', 'newInstanceWithoutConstructor' => 'object', 'newInstanceArgs' => '?object', 'getParentClass' => 'ReflectionClass|false', 'isSubclassOf' => 'bool', 'getStaticProperties' => '?array', 'getStaticPropertyValue' => 'mixed', 'setStaticPropertyValue' => 'void', 'getDefaultProperties' => 'array', 'isIterable' => 'bool', 'isIterateable' => 'bool', 'implementsInterface' => 'bool', 'getExtension' => '?ReflectionExtension', 'getExtensionName' => 'string|false', 'inNamespace' => 'bool', 'getNamespaceName' => 'string', 'getShortName' => 'string'], 'ReflectionProperty' => ['getName' => 'string', 'getValue' => 'mixed', 'setValue' => 'void', 'isInitialized' => 'bool', 'isPublic' => 'bool', 'isPrivate' => 'bool', 'isProtected' => 'bool', 'isStatic' => 'bool', 'isDefault' => 'bool', 'getModifiers' => 'int', 'getDeclaringClass' => 'ReflectionClass', 'getDocComment' => 'string|false', 'setAccessible' => 'void', 'getType' => '?ReflectionType', 'hasType' => 'bool', 'getDefaultValue' => 'mixed'], 'ReflectionClassConstant' => ['getName' => 'string', 'getValue' => 'mixed', 'isPublic' => 'bool', 'isPrivate' => 'bool', 'isProtected' => 'bool', 'getModifiers' => 'int', 'getDeclaringClass' => 'ReflectionClass', 'getDocComment' => 'string|false'], 'ReflectionParameter' => ['getName' => 'string', 'isPassedByReference' => 'bool', 'canBePassedByValue' => 'bool', 'getDeclaringFunction' => 'ReflectionFunctionAbstract', 'getDeclaringClass' => '?ReflectionClass', 'getClass' => '?ReflectionClass', 'hasType' => 'bool', 'getType' => '?ReflectionType', 'isArray' => 'bool', 'isCallable' => 'bool', 'allowsNull' => 'bool', 'getPosition' => 'int', 'isOptional' => 'bool', 'isDefaultValueAvailable' => 'bool', 'getDefaultValue' => 'mixed', 'isDefaultValueConstant' => 'bool', 'getDefaultValueConstantName' => '?string', 'isVariadic' => 'bool'], 'ReflectionType' => ['allowsNull' => 'bool'], 'ReflectionNamedType' => ['getName' => 'string', 'isBuiltin' => 'bool'], 'ReflectionExtension' => ['getName' => 'string', 'getVersion' => '?string', 'getFunctions' => 'array', 'getConstants' => 'array', 'getINIEntries' => 'array', 'getClasses' => 'array', 'getClassNames' => 'array', 'getDependencies' => 'array', 'info' => 'void', 'isPersistent' => 'bool', 'isTemporary' => 'bool'], 'ReflectionZendExtension' => ['getName' => 'string', 'getVersion' => 'string', 'getAuthor' => 'string', 'getURL' => 'string', 'getCopyright' => 'string'], 'SessionHandlerInterface' => ['open' => 'bool', 'close' => 'bool', 'read' => 'string|false', 'write' => 'bool', 'destroy' => 'bool', 'gc' => 'int|false'], 'SessionIdInterface' => ['create_sid' => 'string'], 'SessionUpdateTimestampHandlerInterface' => ['validateId' => 'bool', 'updateTimestamp' => 'bool'], 'SessionHandler' => ['open' => 'bool', 'close' => 'bool', 'read' => 'string|false', 'write' => 'bool', 'destroy' => 'bool', 'gc' => 'int|false', 'create_sid' => 'string'], 'SimpleXMLElement' => ['xpath' => 'array|null|false', 'registerXPathNamespace' => 'bool', 'asXML' => 'string|bool', 'saveXML' => 'string|bool', 'getNamespaces' => 'array', 'getDocNamespaces' => 'array|false', 'children' => '?SimpleXMLElement', 'attributes' => '?SimpleXMLElement', 'addChild' => '?SimpleXMLElement', 'addAttribute' => 'void', 'getName' => 'string', 'count' => 'int', 'rewind' => 'void', 'valid' => 'bool', 'current' => 'SimpleXMLElement', 'key' => 'string', 'next' => 'void', 'hasChildren' => 'bool', 'getChildren' => '?SimpleXMLElement'], 'SNMP' => ['close' => 'bool', 'setSecurity' => 'bool', 'get' => 'mixed', 'getnext' => 'mixed', 'walk' => 'array|false', 'set' => 'bool', 'getErrno' => 'int', 'getError' => 'string'], 'SoapServer' => ['fault' => 'void', 'addSoapHeader' => 'void', 'setPersistence' => 'void', 'setClass' => 'void', 'setObject' => 'void', 'getFunctions' => 'array', 'addFunction' => 'void', 'handle' => 'void'], 'SoapClient' => ['__call' => 'mixed', '__soapCall' => 'mixed', '__getFunctions' => '?array', '__getTypes' => '?array', '__getLastRequest' => '?string', '__getLastResponse' => '?string', '__getLastRequestHeaders' => '?string', '__getLastResponseHeaders' => '?string', '__doRequest' => '?string', '__setCookie' => 'void', '__getCookies' => 'array', '__setSoapHeaders' => 'bool', '__setLocation' => '?string'], 'ArrayObject' => ['offsetExists' => 'bool', 'offsetGet' => 'mixed', 'offsetSet' => 'void', 'offsetUnset' => 'void', 'append' => 'void', 'getArrayCopy' => 'array', 'count' => 'int', 'getFlags' => 'int', 'setFlags' => 'void', 'asort' => 'bool', 'ksort' => 'bool', 'uasort' => 'bool', 'uksort' => 'bool', 'natsort' => 'bool', 'natcasesort' => 'bool', 'unserialize' => 'void', 'serialize' => 'string', '__serialize' => 'array', '__unserialize' => 'void', 'getIterator' => 'Iterator', 'exchangeArray' => 'array', 'setIteratorClass' => 'void', 'getIteratorClass' => 'string', '__debugInfo' => 'array'], 'ArrayIterator' => ['offsetExists' => 'bool', 'offsetGet' => 'mixed', 'offsetSet' => 'void', 'offsetUnset' => 'void', 'append' => 'void', 'getArrayCopy' => 'array', 'count' => 'int', 'getFlags' => 'int', 'setFlags' => 'void', 'asort' => 'bool', 'ksort' => 'bool', 'uasort' => 'bool', 'uksort' => 'bool', 'natsort' => 'bool', 'natcasesort' => 'bool', 'unserialize' => 'void', 'serialize' => 'string', '__serialize' => 'array', '__unserialize' => 'void', 'rewind' => 'void', 'current' => 'mixed', 'key' => 'string|int|null', 'next' => 'void', 'valid' => 'bool', 'seek' => 'void', '__debugInfo' => 'array'], 'RecursiveArrayIterator' => ['hasChildren' => 'bool', 'getChildren' => '?RecursiveArrayIterator'], 'SplFileInfo' => ['getPath' => 'string', 'getFilename' => 'string', 'getExtension' => 'string', 'getBasename' => 'string', 'getPathname' => 'string', 'getPerms' => 'int|false', 'getInode' => 'int|false', 'getSize' => 'int|false', 'getOwner' => 'int|false', 'getGroup' => 'int|false', 'getATime' => 'int|false', 'getMTime' => 'int|false', 'getCTime' => 'int|false', 'getType' => 'string|false', 'isWritable' => 'bool', 'isReadable' => 'bool', 'isExecutable' => 'bool', 'isFile' => 'bool', 'isDir' => 'bool', 'isLink' => 'bool', 'getLinkTarget' => 'string|false', 'getRealPath' => 'string|false', 'getFileInfo' => 'SplFileInfo', 'getPathInfo' => '?SplFileInfo', 'openFile' => 'SplFileObject', 'setFileClass' => 'void', 'setInfoClass' => 'void', '__debugInfo' => 'array', '_bad_state_ex' => 'void'], 'DirectoryIterator' => ['getFilename' => 'string', 'getExtension' => 'string', 'getBasename' => 'string', 'isDot' => 'bool', 'rewind' => 'void', 'valid' => 'bool', 'key' => 'mixed', 'current' => 'mixed', 'next' => 'void', 'seek' => 'void'], 'FilesystemIterator' => ['rewind' => 'void', 'key' => 'string', 'current' => 'string|SplFileInfo|FilesystemIterator', 'getFlags' => 'int', 'setFlags' => 'void'], 'RecursiveDirectoryIterator' => ['hasChildren' => 'bool', 'getChildren' => 'RecursiveDirectoryIterator', 'getSubPath' => 'string', 'getSubPathname' => 'string'], 'GlobIterator' => ['count' => 'int'], 'SplFileObject' => ['rewind' => 'void', 'eof' => 'bool', 'valid' => 'bool', 'fgets' => 'string', 'fread' => 'string|false', 'fgetcsv' => 'array|false', 'fputcsv' => 'int|false', 'setCsvControl' => 'void', 'getCsvControl' => 'array', 'flock' => 'bool', 'fflush' => 'bool', 'ftell' => 'int|false', 'fseek' => 'int', 'fgetc' => 'string|false', 'fpassthru' => 'int', 'fscanf' => 'array|int|null', 'fwrite' => 'int|false', 'fstat' => 'array', 'ftruncate' => 'bool', 'current' => 'string|array|false', 'key' => 'int', 'next' => 'void', 'setFlags' => 'void', 'getFlags' => 'int', 'setMaxLineLen' => 'void', 'getMaxLineLen' => 'int', 'hasChildren' => 'false', 'getChildren' => 'null', 'seek' => 'void', 'getCurrentLine' => 'string'], 'SplDoublyLinkedList' => ['add' => 'void', 'pop' => 'mixed', 'shift' => 'mixed', 'push' => 'void', 'unshift' => 'void', 'top' => 'mixed', 'bottom' => 'mixed', '__debugInfo' => 'array', 'count' => 'int', 'isEmpty' => 'bool', 'setIteratorMode' => 'int', 'getIteratorMode' => 'int', 'offsetExists' => 'bool', 'offsetGet' => 'mixed', 'offsetSet' => 'void', 'offsetUnset' => 'void', 'rewind' => 'void', 'current' => 'mixed', 'key' => 'int', 'prev' => 'void', 'next' => 'void', 'valid' => 'bool', 'unserialize' => 'void', 'serialize' => 'string', '__serialize' => 'array', '__unserialize' => 'void'], 'SplQueue' => ['enqueue' => 'void', 'dequeue' => 'mixed'], 'SplFixedArray' => ['__wakeup' => 'void', 'count' => 'int', 'toArray' => 'array', 'fromArray' => 'SplFixedArray', 'getSize' => 'int', 'offsetExists' => 'bool', 'offsetGet' => 'mixed', 'offsetSet' => 'void', 'offsetUnset' => 'void'], 'SplPriorityQueue' => ['compare' => 'int', 'setExtractFlags' => 'int', 'top' => 'mixed', 'extract' => 'mixed', 'count' => 'int', 'isEmpty' => 'bool', 'rewind' => 'void', 'current' => 'mixed', 'key' => 'int', 'next' => 'void', 'valid' => 'bool', 'isCorrupted' => 'bool', 'getExtractFlags' => 'int', '__debugInfo' => 'array'], 'SplHeap' => ['extract' => 'mixed', 'insert' => 'bool', 'top' => 'mixed', 'count' => 'int', 'isEmpty' => 'bool', 'rewind' => 'void', 'current' => 'mixed', 'key' => 'int', 'next' => 'void', 'valid' => 'bool', 'recoverFromCorruption' => 'bool', 'compare' => 'int', 'isCorrupted' => 'bool', '__debugInfo' => 'array'], 'SplMinHeap' => ['compare' => 'int'], 'SplMaxHeap' => ['compare' => 'int'], 'EmptyIterator' => ['current' => 'never', 'next' => 'void', 'key' => 'never', 'valid' => 'false', 'rewind' => 'void'], 'CallbackFilterIterator' => ['accept' => 'bool'], 'RecursiveCallbackFilterIterator' => ['hasChildren' => 'bool', 'getChildren' => 'RecursiveCallbackFilterIterator'], 'RecursiveIterator' => ['hasChildren' => 'bool', 'getChildren' => '?RecursiveIterator'], 'RecursiveIteratorIterator' => ['rewind' => 'void', 'valid' => 'bool', 'key' => 'mixed', 'current' => 'mixed', 'next' => 'void', 'getDepth' => 'int', 'getSubIterator' => '?RecursiveIterator', 'getInnerIterator' => 'RecursiveIterator', 'beginIteration' => 'void', 'endIteration' => 'void', 'callHasChildren' => 'bool', 'callGetChildren' => '?RecursiveIterator', 'beginChildren' => 'void', 'endChildren' => 'void', 'nextElement' => 'void', 'setMaxDepth' => 'void', 'getMaxDepth' => 'int|false'], 'OuterIterator' => ['getInnerIterator' => '?Iterator'], 'IteratorIterator' => ['getInnerIterator' => '?Iterator', 'rewind' => 'void', 'valid' => 'bool', 'key' => 'mixed', 'current' => 'mixed', 'next' => 'void'], 'FilterIterator' => ['accept' => 'bool', 'rewind' => 'void', 'next' => 'void'], 'RecursiveFilterIterator' => ['hasChildren' => 'bool', 'getChildren' => '?RecursiveFilterIterator'], 'ParentIterator' => ['accept' => 'bool'], 'SeekableIterator' => ['seek' => 'void'], 'LimitIterator' => ['rewind' => 'void', 'valid' => 'bool', 'next' => 'void', 'seek' => 'int', 'getPosition' => 'int'], 'CachingIterator' => ['rewind' => 'void', 'valid' => 'bool', 'next' => 'void', 'hasNext' => 'bool', 'getFlags' => 'int', 'setFlags' => 'void', 'offsetGet' => 'mixed', 'offsetSet' => 'void', 'offsetUnset' => 'void', 'offsetExists' => 'bool', 'getCache' => 'array', 'count' => 'int'], 'RecursiveCachingIterator' => ['hasChildren' => 'bool', 'getChildren' => '?RecursiveCachingIterator'], 'NoRewindIterator' => ['rewind' => 'void', 'valid' => 'bool', 'key' => 'mixed', 'current' => 'mixed', 'next' => 'void'], 'AppendIterator' => ['append' => 'void', 'rewind' => 'void', 'valid' => 'bool', 'current' => 'mixed', 'next' => 'void', 'getIteratorIndex' => '?int', 'getArrayIterator' => 'ArrayIterator'], 'InfiniteIterator' => ['next' => 'void'], 'RegexIterator' => ['accept' => 'bool', 'getMode' => 'int', 'setMode' => 'void', 'getFlags' => 'int', 'setFlags' => 'void', 'getRegex' => 'string', 'getPregFlags' => 'int', 'setPregFlags' => 'void'], 'RecursiveRegexIterator' => ['accept' => 'bool', 'hasChildren' => 'bool', 'getChildren' => 'RecursiveRegexIterator'], 'RecursiveTreeIterator' => ['key' => 'mixed', 'current' => 'mixed', 'getPrefix' => 'string', 'setPostfix' => 'void', 'setPrefixPart' => 'void', 'getEntry' => 'string', 'getPostfix' => 'string'], 'SplObserver' => ['update' => 'void'], 'SplSubject' => ['attach' => 'void', 'detach' => 'void', 'notify' => 'void'], 'SplObjectStorage' => ['attach' => 'void', 'detach' => 'void', 'contains' => 'bool', 'addAll' => 'int', 'removeAll' => 'int', 'removeAllExcept' => 'int', 'getInfo' => 'mixed', 'setInfo' => 'void', 'count' => 'int', 'rewind' => 'void', 'valid' => 'bool', 'key' => 'int', 'current' => 'object', 'next' => 'void', 'unserialize' => 'void', 'serialize' => 'string', 'offsetExists' => 'bool', 'offsetGet' => 'mixed', 'offsetSet' => 'void', 'offsetUnset' => 'void', 'getHash' => 'string', '__serialize' => 'array', '__unserialize' => 'void', '__debugInfo' => 'array'], 'MultipleIterator' => ['getFlags' => 'int', 'setFlags' => 'void', 'attachIterator' => 'void', 'detachIterator' => 'void', 'containsIterator' => 'bool', 'countIterators' => 'int', 'rewind' => 'void', 'valid' => 'bool', 'key' => 'array', 'current' => 'array', 'next' => 'void', '__debugInfo' => 'array'], 'SQLite3' => ['open' => 'void', 'version' => 'array', 'lastInsertRowID' => 'int', 'lastErrorCode' => 'int', 'lastExtendedErrorCode' => 'int', 'lastErrorMsg' => 'string', 'changes' => 'int', 'busyTimeout' => 'bool', 'loadExtension' => 'bool', 'backup' => 'bool', 'escapeString' => 'string', 'prepare' => 'SQLite3Stmt|false', 'exec' => 'bool', 'query' => 'SQLite3Result|false', 'querySingle' => 'mixed', 'createFunction' => 'bool', 'createAggregate' => 'bool', 'createCollation' => 'bool', 'enableExceptions' => 'bool', 'enableExtendedResultCodes' => 'bool', 'setAuthorizer' => 'bool'], 'SQLite3Stmt' => ['bindParam' => 'bool', 'bindValue' => 'bool', 'clear' => 'bool', 'close' => 'bool', 'execute' => 'SQLite3Result|false', 'getSQL' => 'string|false', 'paramCount' => 'int', 'readOnly' => 'bool', 'reset' => 'bool'], 'SQLite3Result' => ['numColumns' => 'int', 'columnName' => 'string|false', 'columnType' => 'int|false', 'fetchArray' => 'array|false', 'reset' => 'bool'], 'Directory' => ['close' => 'void', 'rewind' => 'void', 'read' => 'string|false'], 'php_user_filter' => ['filter' => 'int', 'onCreate' => 'bool', 'onClose' => 'void'], 'tidy' => ['getOpt' => 'string|int|bool', 'cleanRepair' => 'bool', 'parseFile' => 'bool', 'parseString' => 'bool', 'repairString' => 'string|false', 'repairFile' => 'string|false', 'diagnose' => 'bool', 'getRelease' => 'string', 'getConfig' => 'array', 'getStatus' => 'int', 'getHtmlVer' => 'int', 'getOptDoc' => 'string|false', 'isXhtml' => 'bool', 'isXml' => 'bool', 'root' => '?tidyNode', 'head' => '?tidyNode', 'html' => '?tidyNode', 'body' => '?tidyNode'], 'XMLReader' => ['getAttribute' => '?string', 'getAttributeNo' => '?string', 'getAttributeNs' => '?string', 'getParserProperty' => 'bool', 'isValid' => 'bool', 'lookupNamespace' => '?string', 'moveToAttribute' => 'bool', 'moveToAttributeNo' => 'bool', 'moveToAttributeNs' => 'bool', 'moveToElement' => 'bool', 'moveToFirstAttribute' => 'bool', 'moveToNextAttribute' => 'bool', 'read' => 'bool', 'next' => 'bool', 'readInnerXml' => 'string', 'readOuterXml' => 'string', 'readString' => 'string', 'setSchema' => 'bool', 'setParserProperty' => 'bool', 'setRelaxNGSchema' => 'bool', 'setRelaxNGSchemaSource' => 'bool', 'expand' => 'DOMNode|false'], 'XMLWriter' => ['openUri' => 'bool', 'openMemory' => 'bool', 'setIndent' => 'bool', 'setIndentString' => 'bool', 'startComment' => 'bool', 'endComment' => 'bool', 'startAttribute' => 'bool', 'endAttribute' => 'bool', 'writeAttribute' => 'bool', 'startAttributeNs' => 'bool', 'writeAttributeNs' => 'bool', 'startElement' => 'bool', 'endElement' => 'bool', 'fullEndElement' => 'bool', 'startElementNs' => 'bool', 'writeElement' => 'bool', 'writeElementNs' => 'bool', 'startPi' => 'bool', 'endPi' => 'bool', 'writePi' => 'bool', 'startCdata' => 'bool', 'endCdata' => 'bool', 'writeCdata' => 'bool', 'text' => 'bool', 'writeRaw' => 'bool', 'startDocument' => 'bool', 'endDocument' => 'bool', 'writeComment' => 'bool', 'startDtd' => 'bool', 'endDtd' => 'bool', 'writeDtd' => 'bool', 'startDtdElement' => 'bool', 'endDtdElement' => 'bool', 'writeDtdElement' => 'bool', 'startDtdAttlist' => 'bool', 'endDtdAttlist' => 'bool', 'writeDtdAttlist' => 'bool', 'startDtdEntity' => 'bool', 'endDtdEntity' => 'bool', 'writeDtdEntity' => 'bool', 'outputMemory' => 'string', 'flush' => 'string|int'], 'XSLTProcessor' => ['importStylesheet' => 'bool', 'transformToDoc' => 'DOMDocument|false', 'transformToUri' => 'int', 'transformToXml' => 'string|null|false', 'setParameter' => 'bool', 'getParameter' => 'string|false', 'removeParameter' => 'bool', 'hasExsltSupport' => 'bool', 'registerPHPFunctions' => 'void', 'setSecurityPrefs' => 'int', 'getSecurityPrefs' => 'int'], 'ZipArchive' => ['open' => 'bool|int', 'setPassword' => 'bool', 'close' => 'bool', 'count' => 'int', 'getStatusString' => 'string', 'addEmptyDir' => 'bool', 'addFromString' => 'bool', 'addFile' => 'bool', 'replaceFile' => 'bool', 'addGlob' => 'array|false', 'addPattern' => 'array|false', 'renameIndex' => 'bool', 'renameName' => 'bool', 'setArchiveComment' => 'bool', 'getArchiveComment' => 'string|false', 'setCommentIndex' => 'bool', 'setCommentName' => 'bool', 'setMtimeIndex' => 'bool', 'setMtimeName' => 'bool', 'getCommentIndex' => 'string|false', 'getCommentName' => 'string|false', 'deleteIndex' => 'bool', 'deleteName' => 'bool', 'statName' => 'array|false', 'statIndex' => 'array|false', 'locateName' => 'int|false', 'getNameIndex' => 'string|false', 'unchangeArchive' => 'bool', 'unchangeAll' => 'bool', 'unchangeIndex' => 'bool', 'unchangeName' => 'bool', 'extractTo' => 'bool', 'getFromName' => 'string|false', 'getFromIndex' => 'string|false', 'setExternalAttributesName' => 'bool', 'setExternalAttributesIndex' => 'bool', 'getExternalAttributesName' => 'bool', 'getExternalAttributesIndex' => 'bool', 'setCompressionName' => 'bool', 'setCompressionIndex' => 'bool', 'setEncryptionName' => 'bool', 'setEncryptionIndex' => 'bool', 'registerProgressCallback' => 'bool', 'registerCancelCallback' => 'bool'], 'Exception' => ['__wakeup' => 'void'], 'Error' => ['__wakeup' => 'void'], 'IteratorAggregate' => ['getIterator' => 'Traversable'], 'Iterator' => ['current' => 'mixed', 'next' => 'void', 'key' => 'mixed', 'valid' => 'bool', 'rewind' => 'void'], 'ArrayAccess' => ['offsetExists' => 'bool', 'offsetGet' => 'mixed', 'offsetSet' => 'void', 'offsetUnset' => 'void'], 'Countable' => ['count' => 'int']];
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\ErrorHandler;

/**
 * Registers all the debug tools.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class Debug
{
    public static function enable(): ErrorHandler
    {
        error_reporting(\E_ALL & ~\E_DEPRECATED & ~\E_USER_DEPRECATED);
        if (!\in_array(\PHP_SAPI, ['cli', 'phpdbg', 'embed'], \true)) {
            ini_set('display_errors', 0);
        } elseif (!filter_var(\ini_get('log_errors'), \FILTER_VALIDATE_BOOL) || \ini_get('error_log')) {
            // CLI - display errors only if they're not already logged to STDERR
            ini_set('display_errors', 1);
        }
        @ini_set('zend.assertions', 1);
        ini_set('assert.active', 1);
        ini_set('assert.exception', 1);
        DebugClassLoader::enable();
        return ErrorHandler::register(new ErrorHandler(new BufferingLogger(), \true));
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\ErrorHandler\ErrorRenderer;

use _ContaoManager\Symfony\Component\ErrorHandler\Exception\FlattenException;
use _ContaoManager\Symfony\Component\HttpFoundation\Request;
use _ContaoManager\Symfony\Component\HttpFoundation\RequestStack;
use _ContaoManager\Symfony\Component\Serializer\Exception\NotEncodableValueException;
use _ContaoManager\Symfony\Component\Serializer\SerializerInterface;
/**
 * Formats an exception using Serializer for rendering.
 *
 * @author Nicolas Grekas <p@tchwork.com>
 */
class SerializerErrorRenderer implements ErrorRendererInterface
{
    private SerializerInterface $serializer;
    private string|\Closure $format;
    private ErrorRendererInterface $fallbackErrorRenderer;
    private bool|\Closure $debug;
    /**
     * @param string|callable(FlattenException) $format The format as a string or a callable that should return it
     *                                                  formats not supported by Request::getMimeTypes() should be given as mime types
     * @param bool|callable                     $debug  The debugging mode as a boolean or a callable that should return it
     */
    public function __construct(SerializerInterface $serializer, string|callable $format, ?ErrorRendererInterface $fallbackErrorRenderer = null, bool|callable $debug = \false)
    {
        $this->serializer = $serializer;
        $this->format = \is_string($format) ? $format : $format(...);
        $this->fallbackErrorRenderer = $fallbackErrorRenderer ?? new HtmlErrorRenderer();
        $this->debug = \is_bool($debug) ? $debug : $debug(...);
    }
    public function render(\Throwable $exception): FlattenException
    {
        $headers = ['Vary' => 'Accept'];
        $debug = \is_bool($this->debug) ? $this->debug : ($this->debug)($exception);
        if ($debug) {
            $headers['X-Debug-Exception'] = rawurlencode(substr($exception->getMessage(), 0, 2000));
            $headers['X-Debug-Exception-File'] = rawurlencode($exception->getFile()) . ':' . $exception->getLine();
        }
        $flattenException = FlattenException::createFromThrowable($exception, null, $headers);
        try {
            $format = \is_string($this->format) ? $this->format : ($this->format)($flattenException);
            $headers['Content-Type'] = Request::getMimeTypes($format)[0] ?? $format;
            $flattenException->setAsString($this->serializer->serialize($flattenException, $format, ['exception' => $exception, 'debug' => $debug]));
        } catch (NotEncodableValueException) {
            $flattenException = $this->fallbackErrorRenderer->render($exception);
        }
        return $flattenException->setHeaders($flattenException->getHeaders() + $headers);
    }
    public static function getPreferredFormat(RequestStack $requestStack): \Closure
    {
        return static function () use ($requestStack) {
            if (!$request = $requestStack->getCurrentRequest()) {
                throw new NotEncodableValueException();
            }
            return $request->getPreferredFormat();
        };
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\ErrorHandler\ErrorRenderer;

use _ContaoManager\Symfony\Component\ErrorHandler\Exception\FlattenException;
use _ContaoManager\Symfony\Component\VarDumper\Cloner\VarCloner;
use _ContaoManager\Symfony\Component\VarDumper\Dumper\CliDumper;
// Help opcache.preload discover always-needed symbols
class_exists(CliDumper::class);
/**
 * @author Nicolas Grekas <p@tchwork.com>
 */
class CliErrorRenderer implements ErrorRendererInterface
{
    public function render(\Throwable $exception): FlattenException
    {
        $cloner = new VarCloner();
        $dumper = new class extends CliDumper
        {
            protected function supportsColors(): bool
            {
                $outputStream = $this->outputStream;
                $this->outputStream = fopen('php://stdout', 'w');
                try {
                    return parent::supportsColors();
                } finally {
                    $this->outputStream = $outputStream;
                }
            }
        };
        return FlattenException::createFromThrowable($exception)->setAsString($dumper->dump($cloner->cloneVar($exception), \true));
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\ErrorHandler\ErrorRenderer;

use _ContaoManager\Symfony\Component\ErrorHandler\Exception\FlattenException;
/**
 * Formats an exception to be used as response content.
 *
 * @author Yonel Ceruto <yonelceruto@gmail.com>
 */
interface ErrorRendererInterface
{
    public const IDE_LINK_FORMATS = ['textmate' => 'txmt://open?url=file://%f&line=%l', 'macvim' => 'mvim://open?url=file://%f&line=%l', 'emacs' => 'emacs://open?url=file://%f&line=%l', 'sublime' => 'subl://open?url=file://%f&line=%l', 'phpstorm' => 'phpstorm://open?file=%f&line=%l', 'atom' => 'atom://core/open/file?filename=%f&line=%l', 'vscode' => 'vscode://file/%f:%l'];
    /**
     * Renders a Throwable as a FlattenException.
     */
    public function render(\Throwable $exception): FlattenException;
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\ErrorHandler\ErrorRenderer;

use _ContaoManager\Psr\Log\LoggerInterface;
use _ContaoManager\Symfony\Component\ErrorHandler\Exception\FlattenException;
use _ContaoManager\Symfony\Component\HttpFoundation\RequestStack;
use _ContaoManager\Symfony\Component\HttpFoundation\Response;
use _ContaoManager\Symfony\Component\HttpKernel\Log\DebugLoggerConfigurator;
use _ContaoManager\Symfony\Component\VarDumper\Cloner\Data;
use _ContaoManager\Symfony\Component\VarDumper\Dumper\HtmlDumper;
/**
 * @author Yonel Ceruto <yonelceruto@gmail.com>
 */
class HtmlErrorRenderer implements ErrorRendererInterface
{
    private const GHOST_ADDONS = ['02-14' => self::GHOST_HEART, '02-29' => self::GHOST_PLUS, '10-18' => self::GHOST_GIFT];
    private const GHOST_GIFT = 'M124.00534057617188,5.3606138080358505 C124.40059661865234,4.644828304648399 125.1237564086914,3.712414965033531 123.88127899169922,3.487462028861046 C123.53517150878906,3.3097832053899765 123.18894958496094,2.9953975528478622 122.8432846069336,3.345616325736046 C122.07421112060547,3.649444565176964 121.40750122070312,4.074306473135948 122.2164306640625,4.869479164481163 C122.57514953613281,5.3830065578222275 122.90142822265625,6.503447040915489 123.3077621459961,6.626829609274864 C123.55027770996094,6.210384353995323 123.7774658203125,5.785196766257286 124.00534057617188,5.3606138080358505 zM122.30630493164062,7.336987480521202 C121.60028076171875,6.076864704489708 121.03211975097656,4.72498320043087 120.16796875,3.562500938773155 C119.11695098876953,2.44033907353878 117.04605865478516,2.940566048026085 116.57544708251953,4.387995228171349 C115.95028686523438,5.819030746817589 117.2991714477539,7.527640804648399 118.826171875,7.348545059561729 C119.98493194580078,7.367936596274376 121.15027618408203,7.420116886496544 122.30630493164062,7.336987480521202 zM128.1732177734375,7.379541382193565 C129.67486572265625,7.17823551595211 130.53842163085938,5.287807449698448 129.68344116210938,4.032590612769127 C128.92578125,2.693056806921959 126.74605560302734,2.6463639587163925 125.98509216308594,4.007616028189659 C125.32617950439453,5.108129009604454 124.75428009033203,6.258124336600304 124.14962768554688,7.388818249106407 C125.48638916015625,7.465229496359825 126.8357162475586,7.447416767477989 128.1732177734375,7.379541382193565 zM130.6601104736328,8.991325363516808 C131.17202758789062,8.540884003043175 133.1543731689453,8.009847149252892 131.65304565429688,7.582054600119591 C131.2811279296875,7.476506695151329 130.84751892089844,6.99234913289547 130.5132598876953,7.124847874045372 C129.78744506835938,8.02728746831417 128.67140197753906,8.55669592320919 127.50616455078125,8.501235947012901 C127.27806091308594,8.576229080557823 126.11459350585938,8.38720129430294 126.428955078125,8.601900085806847 C127.25099182128906,9.070617660880089 128.0523223876953,9.579657539725304 128.902587890625,9.995706543326378 C129.49813842773438,9.678531631827354 130.0761260986328,9.329126343131065 130.6601104736328,8.991325363516808 zM118.96446990966797,9.246344551444054 C119.4022445678711,8.991325363516808 119.84001922607422,8.736305221915245 120.27779388427734,8.481284126639366 C118.93965911865234,8.414779648184776 117.40827941894531,8.607666000723839 116.39698791503906,7.531384453177452 C116.11186981201172,7.212117180228233 115.83845520019531,6.846597656607628 115.44329071044922,7.248530372977257 C114.96995544433594,7.574637398123741 113.5140609741211,7.908811077475548 114.63501739501953,8.306883797049522 C115.61112976074219,8.883499130606651 116.58037567138672,9.474181160330772 117.58061218261719,10.008124336600304 C118.05723571777344,9.784612640738487 118.50651550292969,9.5052699893713 118.96446990966797,9.246344551444054 zM125.38018035888672,12.091858848929405 C125.9474868774414,11.636047348380089 127.32159423828125,11.201767906546593 127.36749267578125,10.712632164359093 C126.08487701416016,9.974547371268272 124.83960723876953,9.152772888541222 123.49772644042969,8.528907760977745 C123.03594207763672,8.353693947196007 122.66152954101562,8.623294815421104 122.28982543945312,8.857431396842003 C121.19065856933594,9.51122473180294 120.06505584716797,10.12446115911007 119.00167083740234,10.835315689444542 C120.39238739013672,11.69529627263546 121.79983520507812,12.529837593436241 123.22095489501953,13.338589653372765 C123.94580841064453,12.932025894522667 124.66128540039062,12.508862480521202 125.38018035888672,12.091858848929405 zM131.07164001464844,13.514615997672081 C131.66018676757812,13.143282875418663 132.2487335205078,12.771927818655968 132.8372802734375,12.400571808218956 C132.8324737548828,11.156818374991417 132.8523406982422,9.912529930472374 132.81829833984375,8.669195160269737 C131.63046264648438,9.332009300589561 130.45948791503906,10.027913078665733 129.30828857421875,10.752535805106163 C129.182373046875,12.035354599356651 129.24623107910156,13.33940313756466 129.27359008789062,14.628684982657433 C129.88104248046875,14.27079389989376 130.4737548828125,13.888019546866417 131.07164001464844,13.514640793204308 zM117.26847839355469,12.731024727225304 C117.32825469970703,11.67083452641964 117.45709991455078,10.46224020421505 116.17853546142578,10.148179039359093 C115.37110900878906,9.77159021794796 114.25194549560547,8.806716904044151 113.62991333007812,8.81639002263546 C113.61052703857422,10.0110072940588 113.62078857421875,11.20585821568966 113.61869049072266,12.400571808218956 C114.81139373779297,13.144886955618858 115.98292541503906,13.925040230154991 117.20137023925781,14.626662239432335 C117.31951141357422,14.010867103934288 117.24227905273438,13.35805033147335 117.26847839355469,12.731024727225304 zM125.80937957763672,16.836034759879112 C126.51483917236328,16.390663132071495 127.22030639648438,15.945291504263878 127.92576599121094,15.49991987645626 C127.92250061035156,14.215868934988976 127.97560119628906,12.929980263113976 127.91757202148438,11.647302612662315 C127.14225769042969,11.869626984000206 126.25550079345703,12.556857094168663 125.43866729736328,12.983742699027061 C124.82704162597656,13.342005714774132 124.21542358398438,13.700271591544151 123.60379028320312,14.05853746831417 C123.61585235595703,15.429577812552452 123.57081604003906,16.803131088614464 123.64839172363281,18.172149643301964 C124.37957000732422,17.744937881827354 125.09130859375,17.284801468253136 125.80937957763672,16.836034759879112 zM122.8521499633789,16.115344032645226 C122.8521499633789,15.429741844534874 122.8521499633789,14.744139656424522 122.8521499633789,14.05853746831417 C121.43595123291016,13.230924591422081 120.02428436279297,12.395455345511436 118.60256958007812,11.577354416251183 C118.52394104003906,12.888403877615929 118.56887817382812,14.204405769705772 118.55702209472656,15.517732605338097 C119.97289276123047,16.4041957706213 121.37410736083984,17.314891800284386 122.80789947509766,18.172149643301964 C122.86368560791016,17.488990768790245 122.84332275390625,16.800363525748253 122.8521499633789,16.115344032645226 zM131.10684204101562,18.871450409293175 C131.68399047851562,18.48711584508419 132.2611541748047,18.10278509557247 132.8383026123047,17.718475326895714 C132.81423950195312,16.499977096915245 132.89776611328125,15.264989838004112 132.77627563476562,14.05993078649044 C131.5760040283203,14.744719490408897 130.41763305664062,15.524359688162804 129.23875427246094,16.255397781729698 C129.26707458496094,17.516149505972862 129.18060302734375,18.791316971182823 129.3108367919922,20.041303619742393 C129.91973876953125,19.667551025748253 130.51010131835938,19.264152511954308 131.10684204101562,18.871450409293175 zM117.2557373046875,18.188333496451378 C117.25104522705078,17.549470886588097 117.24633026123047,16.91058538854122 117.24163055419922,16.271720871329308 C116.04924774169922,15.525708183646202 114.87187957763672,14.75476549565792 113.66158294677734,14.038097366690636 C113.5858383178711,15.262084946036339 113.62901306152344,16.49083898961544 113.61761474609375,17.717010483145714 C114.82051086425781,18.513254150748253 116.00987243652344,19.330610260367393 117.22888946533203,20.101993545889854 C117.27559661865234,19.466014847159386 117.25241088867188,18.825733169913292 117.2557373046875,18.188333496451378 zM125.8398666381836,22.38675306737423 C126.54049682617188,21.921453461050987 127.24110412597656,21.456151947379112 127.94172668457031,20.99083136022091 C127.94009399414062,19.693386062979698 127.96646118164062,18.395381912589073 127.93160247802734,17.098379120230675 C126.50540924072266,17.97775076329708 125.08877563476562,18.873308166861534 123.68258666992188,19.78428266942501 C123.52366638183594,21.03710363805294 123.626708984375,22.32878302037716 123.62647247314453,23.595300659537315 C124.06291198730469,23.86113165318966 125.1788101196289,22.68297766149044 125.8398666381836,22.38675306737423 zM122.8521499633789,21.83134649693966 C122.76741790771484,20.936696991324425 123.21651458740234,19.67745779454708 122.0794677734375,19.330633148550987 C120.93280029296875,18.604360565543175 119.7907485961914,17.870157226920128 118.62899780273438,17.16818617284298 C118.45966339111328,18.396427139639854 118.63676452636719,19.675991043448448 118.50668334960938,20.919256195425987 C119.89984130859375,21.92635916173458 121.32942199707031,22.88914106786251 122.78502655029297,23.803510650992393 C122.90177917480469,23.1627406924963 122.82917022705078,22.48402212560177 122.8521499633789,21.83134649693966 zM117.9798355102539,21.59483526647091 C116.28416442871094,20.46288488805294 114.58848571777344,19.330957397818565 112.892822265625,18.199007019400597 C112.89473724365234,14.705654129385948 112.84647369384766,11.211485847830772 112.90847778320312,7.718807205557823 C113.7575912475586,7.194885239005089 114.66117858886719,6.765397056937218 115.5350341796875,6.284702762961388 C114.97061157226562,4.668964847922325 115.78496551513672,2.7054970115423203 117.42159271240234,2.1007001250982285 C118.79354095458984,1.537783369421959 120.44731903076172,2.0457767099142075 121.32200622558594,3.23083733022213 C121.95732116699219,2.9050118774175644 122.59264373779297,2.5791852325201035 123.22796630859375,2.253336176276207 C123.86669921875,2.5821153968572617 124.50543975830078,2.9108948558568954 125.1441650390625,3.23967407643795 C126.05941009521484,2.154020771384239 127.62747192382812,1.5344576686620712 128.986328125,2.1429056972265244 C130.61741638183594,2.716217741370201 131.50650024414062,4.675290569663048 130.9215545654297,6.2884936183691025 C131.8018341064453,6.78548763692379 132.7589111328125,7.1738648265600204 133.5660400390625,7.780336365103722 C133.60182189941406,11.252970680594444 133.56637573242188,14.726140961050987 133.5631103515625,18.199007019400597 C130.18914794921875,20.431867584586143 126.86984252929688,22.74994657933712 123.44108581542969,24.897907242178917 C122.44406127929688,24.897628769278526 121.5834732055664,23.815067276358604 120.65831756591797,23.37616156041622 C119.76387023925781,22.784828171133995 118.87168884277344,22.19007681310177 117.9798355102539,21.59483526647091 z';
    private const GHOST_HEART = 'M125.91386369681868,8.305165958366445 C128.95033202169043,-0.40540639102854037 140.8469835342744,8.305165958366445 125.91386369681868,19.504526138305664 C110.98208663272044,8.305165958366445 122.87795231771452,-0.40540639102854037 125.91386369681868,8.305165958366445 z';
    private const GHOST_PLUS = 'M111.36824226379395,8.969108581542969 L118.69175148010254,8.969108581542969 L118.69175148010254,1.6455793380737305 L126.20429420471191,1.6455793380737305 L126.20429420471191,8.969108581542969 L133.52781105041504,8.969108581542969 L133.52781105041504,16.481630325317383 L126.20429420471191,16.481630325317383 L126.20429420471191,23.805158615112305 L118.69175148010254,23.805158615112305 L118.69175148010254,16.481630325317383 L111.36824226379395,16.481630325317383 z';
    private bool|\Closure $debug;
    private string $charset;
    private FileLinkFormatter $fileLinkFormat;
    private ?string $projectDir;
    private string|\Closure $outputBuffer;
    private ?LoggerInterface $logger;
    private static string $template = 'views/error.html.php';
    /**
     * @param bool|callable   $debug        The debugging mode as a boolean or a callable that should return it
     * @param string|callable $outputBuffer The output buffer as a string or a callable that should return it
     */
    public function __construct(bool|callable $debug = \false, ?string $charset = null, string|FileLinkFormatter|null $fileLinkFormat = null, ?string $projectDir = null, string|callable $outputBuffer = '', ?LoggerInterface $logger = null)
    {
        $this->debug = \is_bool($debug) ? $debug : $debug(...);
        $this->charset = $charset ?: (\ini_get('default_charset') ?: 'UTF-8');
        $this->fileLinkFormat = $fileLinkFormat instanceof FileLinkFormatter ? $fileLinkFormat : new FileLinkFormatter($fileLinkFormat);
        $this->projectDir = $projectDir;
        $this->outputBuffer = \is_string($outputBuffer) ? $outputBuffer : $outputBuffer(...);
        $this->logger = $logger;
    }
    public function render(\Throwable $exception): FlattenException
    {
        $headers = ['Content-Type' => 'text/html; charset=' . $this->charset];
        if (\is_bool($this->debug) ? $this->debug : ($this->debug)($exception)) {
            $headers['X-Debug-Exception'] = rawurlencode(substr($exception->getMessage(), 0, 2000));
            $headers['X-Debug-Exception-File'] = rawurlencode($exception->getFile()) . ':' . $exception->getLine();
        }
        $exception = FlattenException::createWithDataRepresentation($exception, null, $headers);
        return $exception->setAsString($this->renderException($exception));
    }
    /**
     * Gets the HTML content associated with the given exception.
     */
    public function getBody(FlattenException $exception): string
    {
        return $this->renderException($exception, 'views/exception.html.php');
    }
    /**
     * Gets the stylesheet associated with the given exception.
     */
    public function getStylesheet(): string
    {
        if (!$this->debug) {
            return $this->include('assets/css/error.css');
        }
        return $this->include('assets/css/exception.css');
    }
    public static function isDebug(RequestStack $requestStack, bool $debug): \Closure
    {
        return static function () use ($requestStack, $debug): bool {
            if (!$request = $requestStack->getCurrentRequest()) {
                return $debug;
            }
            return $debug && $request->attributes->getBoolean('showException', \true);
        };
    }
    public static function getAndCleanOutputBuffer(RequestStack $requestStack): \Closure
    {
        return static function () use ($requestStack): string {
            if (!$request = $requestStack->getCurrentRequest()) {
                return '';
            }
            $startObLevel = $request->headers->get('X-Php-Ob-Level', -1);
            if (ob_get_level() <= $startObLevel) {
                return '';
            }
            Response::closeOutputBuffers($startObLevel + 1, \true);
            return ob_get_clean();
        };
    }
    private function renderException(FlattenException $exception, string $debugTemplate = 'views/exception_full.html.php'): string
    {
        $debug = \is_bool($this->debug) ? $this->debug : ($this->debug)($exception);
        $statusText = $this->escape($exception->getStatusText());
        $statusCode = $this->escape($exception->getStatusCode());
        if (!$debug) {
            return $this->include(self::$template, ['statusText' => $statusText, 'statusCode' => $statusCode]);
        }
        $exceptionMessage = $this->escape($exception->getMessage());
        return $this->include($debugTemplate, ['exception' => $exception, 'exceptionMessage' => $exceptionMessage, 'statusText' => $statusText, 'statusCode' => $statusCode, 'logger' => null !== $this->logger && class_exists(DebugLoggerConfigurator::class) ? DebugLoggerConfigurator::getDebugLogger($this->logger) : null, 'currentContent' => \is_string($this->outputBuffer) ? $this->outputBuffer : ($this->outputBuffer)()]);
    }
    private function dumpValue(Data $value): string
    {
        $dumper = new HtmlDumper();
        $dumper->setTheme('light');
        return $dumper->dump($value, \true);
    }
    private function formatArgs(array $args): string
    {
        $result = [];
        foreach ($args as $key => $item) {
            if ('object' === $item[0]) {
                $formattedValue = \sprintf('<em>object</em>(%s)', $this->abbrClass($item[1]));
            } elseif ('array' === $item[0]) {
                $formattedValue = \sprintf('<em>array</em>(%s)', \is_array($item[1]) ? $this->formatArgs($item[1]) : $item[1]);
            } elseif ('null' === $item[0]) {
                $formattedValue = '<em>null</em>';
            } elseif ('boolean' === $item[0]) {
                $formattedValue = '<em>' . strtolower(var_export($item[1], \true)) . '</em>';
            } elseif ('resource' === $item[0]) {
                $formattedValue = '<em>resource</em>';
            } elseif (preg_match('/[^\x07-\x0D\x1B\x20-\xFF]/', $item[1])) {
                $formattedValue = '<em>binary string</em>';
            } else {
                $formattedValue = str_replace("\n", '', $this->escape(var_export($item[1], \true)));
            }
            $result[] = \is_int($key) ? $formattedValue : \sprintf("'%s' => %s", $this->escape($key), $formattedValue);
        }
        return implode(', ', $result);
    }
    private function formatArgsAsText(array $args): string
    {
        return strip_tags($this->formatArgs($args));
    }
    private function escape(string $string): string
    {
        return htmlspecialchars($string, \ENT_COMPAT | \ENT_SUBSTITUTE, $this->charset);
    }
    private function abbrClass(string $class): string
    {
        $parts = explode('\\', $class);
        $short = array_pop($parts);
        return \sprintf('<abbr title="%s">%s</abbr>', $class, $short);
    }
    private function getFileRelative(string $file): ?string
    {
        $file = str_replace('\\', '/', $file);
        if (null !== $this->projectDir && str_starts_with($file, $this->projectDir)) {
            return ltrim(substr($file, \strlen($this->projectDir)), '/');
        }
        return null;
    }
    /**
     * Formats a file path.
     *
     * @param string $file An absolute file path
     * @param int    $line The line number
     * @param string $text Use this text for the link rather than the file path
     */
    private function formatFile(string $file, int $line, ?string $text = null): string
    {
        $file = trim($file);
        if (null === $text) {
            $text = $file;
            if (null !== $rel = $this->getFileRelative($text)) {
                $rel = explode('/', $rel, 2);
                $text = \sprintf('<abbr title="%s%2$s">%s</abbr>%s', $this->projectDir, $rel[0], '/' . ($rel[1] ?? ''));
            }
        }
        if (0 < $line) {
            $text .= ' at line ' . $line;
        }
        if (!file_exists($file)) {
            return $text;
        }
        $link = $this->fileLinkFormat->format($file, $line);
        return \sprintf('<a href="%s" title="Click to open this file" class="file_link">%s</a>', $this->escape($link), $text);
    }
    /**
     * Returns an excerpt of a code file around the given line number.
     *
     * @param string $file       A file path
     * @param int    $line       The selected line number
     * @param int    $srcContext The number of displayed lines around or -1 for the whole file
     */
    private function fileExcerpt(string $file, int $line, int $srcContext = 3): string
    {
        if (is_file($file) && is_readable($file)) {
            // highlight_file could throw warnings
            // see https://bugs.php.net/25725
            $code = @highlight_file($file, \true);
            if (\PHP_VERSION_ID >= 80300) {
                // remove main pre/code tags
                $code = preg_replace('#^<pre.*?>\s*<code.*?>(.*)</code>\s*</pre>#s', '\1', $code);
                // split multiline span tags
                $code = preg_replace_callback('#<span ([^>]++)>((?:[^<\n]*+\n)++[^<]*+)</span>#', function ($m) {
                    return "<span {$m[1]}>" . str_replace("\n", "</span>\n<span {$m[1]}>", $m[2]) . '</span>';
                }, $code);
                $content = explode("\n", $code);
            } else {
                // remove main code/span tags
                $code = preg_replace('#^<code.*?>\s*<span.*?>(.*)</span>\s*</code>#s', '\1', $code);
                // split multiline spans
                $code = preg_replace_callback('#<span ([^>]++)>((?:[^<]*+<br \/>)++[^<]*+)</span>#', fn($m) => "<span {$m[1]}>" . str_replace('<br />', "</span><br /><span {$m[1]}>", $m[2]) . '</span>', $code);
                $content = explode('<br />', $code);
            }
            $lines = [];
            if (0 > $srcContext) {
                $srcContext = \count($content);
            }
            for ($i = max($line - $srcContext, 1), $max = min($line + $srcContext, \count($content)); $i <= $max; ++$i) {
                $lines[] = '<li' . ($i == $line ? ' class="selected"' : '') . '><code>' . $this->fixCodeMarkup($content[$i - 1]) . '</code></li>';
            }
            return '<ol start="' . max($line - $srcContext, 1) . '">' . implode("\n", $lines) . '</ol>';
        }
        return '';
    }
    private function fixCodeMarkup(string $line): string
    {
        // </span> ending tag from previous line
        $opening = strpos($line, '<span');
        $closing = strpos($line, '</span>');
        if (\false !== $closing && (\false === $opening || $closing < $opening)) {
            $line = substr_replace($line, '', $closing, 7);
        }
        // missing </span> tag at the end of line
        $opening = strrpos($line, '<span');
        $closing = strrpos($line, '</span>');
        if (\false !== $opening && (\false === $closing || $closing < $opening)) {
            $line .= '</span>';
        }
        return trim($line);
    }
    private function formatFileFromText(string $text): string
    {
        return preg_replace_callback('/in ("|&quot;)?(.+?)\1(?: +(?:on|at))? +line (\d+)/s', fn($match) => 'in ' . $this->formatFile($match[2], $match[3]), $text) ?? $text;
    }
    private function formatLogMessage(string $message, array $context): string
    {
        if ($context && str_contains($message, '{')) {
            $replacements = [];
            foreach ($context as $key => $val) {
                if (\is_scalar($val)) {
                    $replacements['{' . $key . '}'] = $val;
                }
            }
            if ($replacements) {
                $message = strtr($message, $replacements);
            }
        }
        return $this->escape($message);
    }
    private function addElementToGhost(): string
    {
        if (!isset(self::GHOST_ADDONS[date('m-d')])) {
            return '';
        }
        return '<path d="' . self::GHOST_ADDONS[date('m-d')] . '" fill="#fff" fill-opacity="0.6"></path>';
    }
    private function include(string $name, array $context = []): string
    {
        extract($context, \EXTR_SKIP);
        ob_start();
        include is_file(\dirname(__DIR__) . '/Resources/' . $name) ? \dirname(__DIR__) . '/Resources/' . $name : $name;
        return trim(ob_get_clean());
    }
    /**
     * Allows overriding the default non-debug template.
     *
     * @param string $template path to the custom template file to render
     */
    public static function setTemplate(string $template): void
    {
        self::$template = $template;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\ErrorHandler\ErrorRenderer;

use _ContaoManager\Symfony\Component\HttpFoundation\Request;
use _ContaoManager\Symfony\Component\HttpFoundation\RequestStack;
use _ContaoManager\Symfony\Component\Routing\Generator\UrlGeneratorInterface;
/**
 * Formats debug file links.
 *
 * @author Jérémy Romey <jeremy@free-agent.fr>
 *
 * @final
 */
class FileLinkFormatter
{
    private array|false $fileLinkFormat;
    private ?RequestStack $requestStack = null;
    private ?string $baseDir = null;
    private \Closure|string|null $urlFormat;
    /**
     * @param string|\Closure $urlFormat The URL format, or a closure that returns it on-demand
     */
    public function __construct(string|array|null $fileLinkFormat = null, ?RequestStack $requestStack = null, ?string $baseDir = null, string|\Closure|null $urlFormat = null)
    {
        $fileLinkFormat ??= $_ENV['SYMFONY_IDE'] ?? $_SERVER['SYMFONY_IDE'] ?? '';
        if (!\is_array($f = $fileLinkFormat)) {
            $f = ((ErrorRendererInterface::IDE_LINK_FORMATS[$f] ?? $f ?: \ini_get('xdebug.file_link_format')) ?: get_cfg_var('xdebug.file_link_format')) ?: 'file://%f#L%l';
            $i = strpos($f, '&', max(strrpos($f, '%f'), strrpos($f, '%l'))) ?: \strlen($f);
            $fileLinkFormat = [substr($f, 0, $i)] + preg_split('/&([^>]++)>/', substr($f, $i), -1, \PREG_SPLIT_DELIM_CAPTURE);
        }
        $this->fileLinkFormat = $fileLinkFormat;
        $this->requestStack = $requestStack;
        $this->baseDir = $baseDir;
        $this->urlFormat = $urlFormat;
    }
    /**
     * @return string|false
     */
    public function format(string $file, int $line): string|bool
    {
        if ($fmt = $this->getFileLinkFormat()) {
            for ($i = 1; isset($fmt[$i]); ++$i) {
                if (str_starts_with($file, $k = $fmt[$i++])) {
                    $file = substr_replace($file, $fmt[$i], 0, \strlen($k));
                    break;
                }
            }
            return strtr($fmt[0], ['%f' => $file, '%l' => $line]);
        }
        return \false;
    }
    public function __serialize(): array
    {
        $this->fileLinkFormat = $this->getFileLinkFormat();
        return ['fileLinkFormat' => $this->fileLinkFormat];
    }
    /**
     * @internal
     */
    public static function generateUrlFormat(UrlGeneratorInterface $router, string $routeName, string $queryString): ?string
    {
        try {
            return $router->generate($routeName) . $queryString;
        } catch (\Throwable) {
            return null;
        }
    }
    private function getFileLinkFormat(): array|false
    {
        if ($this->fileLinkFormat) {
            return $this->fileLinkFormat;
        }
        if ($this->requestStack && $this->baseDir && $this->urlFormat) {
            $request = $this->requestStack->getMainRequest();
            if ($request instanceof Request && (!$this->urlFormat instanceof \Closure || $this->urlFormat = ($this->urlFormat)())) {
                return [$request->getSchemeAndHttpHost() . $this->urlFormat, $this->baseDir . \DIRECTORY_SEPARATOR, ''];
            }
        }
        return \false;
    }
}
if (!class_exists(\_ContaoManager\Symfony\Component\HttpKernel\Debug\FileLinkFormatter::class, \false)) {
    class_alias(FileLinkFormatter::class, \_ContaoManager\Symfony\Component\HttpKernel\Debug\FileLinkFormatter::class);
}
ErrorHandler Component
======================

The ErrorHandler component provides tools to manage errors and ease debugging PHP code.

Getting Started
---------------

```
$ composer require symfony/error-handler
```

```php
use Symfony\Component\ErrorHandler\Debug;
use Symfony\Component\ErrorHandler\ErrorHandler;
use Symfony\Component\ErrorHandler\DebugClassLoader;

Debug::enable();

// or enable only one feature
//ErrorHandler::register();
//DebugClassLoader::enable();

// If you want a custom generic template when debug is not enabled
// HtmlErrorRenderer::setTemplate('/path/to/custom/error.html.php');

$data = ErrorHandler::call(static function () use ($filename, $datetimeFormat) {
    // if any code executed inside this anonymous function fails, a PHP exception
    // will be thrown, even if the code uses the '@' PHP silence operator
    $data = json_decode(file_get_contents($filename), true);
    $data['read_at'] = date($datetimeFormat);
    file_put_contents($filename, json_encode($data));

    return $data;
});
```

Resources
---------

 * [Contributing](https://symfony.com/doc/current/contributing/index.html)
 * [Report issues](https://github.com/symfony/symfony/issues) and
   [send Pull Requests](https://github.com/symfony/symfony/pulls)
   in the [main Symfony repository](https://github.com/symfony/symfony)
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\ErrorHandler;

use Composer\InstalledVersions;
use _ContaoManager\Doctrine\Common\Persistence\Proxy as LegacyProxy;
use _ContaoManager\Doctrine\Persistence\Proxy;
use _ContaoManager\Mockery\MockInterface;
use _ContaoManager\Phake\IMock;
use _ContaoManager\PHPUnit\Framework\MockObject\Matcher\StatelessInvocation;
use _ContaoManager\PHPUnit\Framework\MockObject\MockObject;
use _ContaoManager\PHPUnit\Framework\MockObject\Stub;
use _ContaoManager\Prophecy\Prophecy\ProphecySubjectInterface;
use _ContaoManager\ProxyManager\Proxy\ProxyInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Argument\LazyClosure;
use _ContaoManager\Symfony\Component\ErrorHandler\Internal\TentativeTypes;
use _ContaoManager\Symfony\Component\VarExporter\LazyObjectInterface;
/**
 * Autoloader checking if the class is really defined in the file found.
 *
 * The ClassLoader will wrap all registered autoloaders
 * and will throw an exception if a file is found but does
 * not declare the class.
 *
 * It can also patch classes to turn docblocks into actual return types.
 * This behavior is controlled by the SYMFONY_PATCH_TYPE_DECLARATIONS env var,
 * which is a url-encoded array with the follow parameters:
 *  - "force": any value enables deprecation notices - can be any of:
 *      - "phpdoc" to patch only docblock annotations
 *      - "2" to add all possible return types
 *      - "1" to add return types but only to tests/final/internal/private methods
 *  - "php": the target version of PHP - e.g. "7.1" doesn't generate "object" types
 *  - "deprecations": "1" to trigger a deprecation notice when a child class misses a
 *                    return type while the parent declares an "@return" annotation
 *
 * Note that patching doesn't care about any coding style so you'd better to run
 * php-cs-fixer after, with rules "phpdoc_trim_consecutive_blank_line_separation"
 * and "no_superfluous_phpdoc_tags" enabled typically.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 * @author Christophe Coevoet <stof@notk.org>
 * @author Nicolas Grekas <p@tchwork.com>
 * @author Guilhem Niot <guilhem.niot@gmail.com>
 */
class DebugClassLoader
{
    private const SPECIAL_RETURN_TYPES = ['void' => 'void', 'null' => 'null', 'resource' => 'resource', 'boolean' => 'bool', 'true' => 'true', 'false' => 'false', 'integer' => 'int', 'array' => 'array', 'bool' => 'bool', 'callable' => 'callable', 'float' => 'float', 'int' => 'int', 'iterable' => 'iterable', 'object' => 'object', 'string' => 'string', 'self' => 'self', 'parent' => 'parent', 'mixed' => 'mixed', 'static' => 'static', '$this' => 'static', 'list' => 'array', 'class-string' => 'string', 'never' => 'never'];
    private const BUILTIN_RETURN_TYPES = ['void' => \true, 'array' => \true, 'false' => \true, 'bool' => \true, 'callable' => \true, 'float' => \true, 'int' => \true, 'iterable' => \true, 'object' => \true, 'string' => \true, 'self' => \true, 'parent' => \true, 'mixed' => \true, 'static' => \true, 'null' => \true, 'true' => \true, 'never' => \true];
    private const MAGIC_METHODS = ['__isset' => 'bool', '__sleep' => 'array', '__toString' => 'string', '__debugInfo' => 'array', '__serialize' => 'array'];
    /**
     * @var callable
     */
    private $classLoader;
    private bool $isFinder;
    private array $loaded = [];
    private array $patchTypes = [];
    private static int $caseCheck;
    private static array $checkedClasses = [];
    private static array $final = [];
    private static array $finalMethods = [];
    private static array $finalProperties = [];
    private static array $finalConstants = [];
    private static array $deprecated = [];
    private static array $internal = [];
    private static array $internalMethods = [];
    private static array $annotatedParameters = [];
    private static array $darwinCache = ['/' => ['/', []]];
    /**
     * @var array<string, list<array{0: string, 1: bool, 2: string, 3: string, 4: string|null}>>
     *
     * Maps an interface FQCN (or an abstract class accumulating entries from its interfaces) to the list of
     * "@method" annotations declared on it. For interfaces, the entry is populated directly by parsing the
     * annotations from the interface's docblock. For abstract classes, the information from all implemented
     * interfaces is merged together, so that the check can later be applied to the first concrete subclass.
     *
     * Each entry is a tuple of:
     *   [0] string      $interface   - FQCN of the interface that carries the "@method" annotation
     *   [1] bool        $static      - whether the method is declared static
     *   [2] string      $returnType  - return type from the annotation, or '' if absent
     *   [3] string      $name        - method name plus its parameter signature, e.g. "foo($arg, int $n)"
     *   [4] string|null $description - description text (period-normalised), or null if absent
     */
    private static array $method = [];
    private static array $returnTypes = [];
    private static array $methodTraits = [];
    private static array $fileOffsets = [];
    public function __construct(callable $classLoader)
    {
        $this->classLoader = $classLoader;
        $this->isFinder = \is_array($classLoader) && method_exists($classLoader[0], 'findFile');
        parse_str($_ENV['SYMFONY_PATCH_TYPE_DECLARATIONS'] ?? $_SERVER['SYMFONY_PATCH_TYPE_DECLARATIONS'] ?? getenv('SYMFONY_PATCH_TYPE_DECLARATIONS') ?: '', $this->patchTypes);
        $this->patchTypes += ['force' => null, 'php' => \PHP_MAJOR_VERSION . '.' . \PHP_MINOR_VERSION, 'deprecations' => \true];
        if ('phpdoc' === $this->patchTypes['force']) {
            $this->patchTypes['force'] = 'docblock';
        }
        if (!isset(self::$caseCheck)) {
            $file = is_file(__FILE__) ? __FILE__ : rtrim(realpath('.'), \DIRECTORY_SEPARATOR);
            $i = strrpos($file, \DIRECTORY_SEPARATOR);
            $dir = substr($file, 0, 1 + $i);
            $file = substr($file, 1 + $i);
            $test = strtoupper($file) === $file ? strtolower($file) : strtoupper($file);
            $test = realpath($dir . $test);
            if (\false === $test || \false === $i) {
                // filesystem is case sensitive
                self::$caseCheck = 0;
            } elseif (str_ends_with($test, $file)) {
                // filesystem is case insensitive and realpath() normalizes the case of characters
                self::$caseCheck = 1;
            } elseif ('Darwin' === \PHP_OS_FAMILY) {
                // on MacOSX, HFS+ is case insensitive but realpath() doesn't normalize the case of characters
                self::$caseCheck = 2;
            } else {
                // filesystem case checks failed, fallback to disabling them
                self::$caseCheck = 0;
            }
        }
    }
    public function getClassLoader(): callable
    {
        return $this->classLoader;
    }
    /**
     * Wraps all autoloaders.
     */
    public static function enable(): void
    {
        // Ensures we don't hit https://bugs.php.net/42098
        class_exists(ErrorHandler::class);
        class_exists(\_ContaoManager\Psr\Log\LogLevel::class);
        if (!\is_array($functions = spl_autoload_functions())) {
            return;
        }
        foreach ($functions as $function) {
            spl_autoload_unregister($function);
        }
        foreach ($functions as $function) {
            if (!\is_array($function) || !$function[0] instanceof self) {
                $function = [new static($function), 'loadClass'];
            }
            spl_autoload_register($function);
        }
    }
    /**
     * Disables the wrapping.
     */
    public static function disable(): void
    {
        if (!\is_array($functions = spl_autoload_functions())) {
            return;
        }
        foreach ($functions as $function) {
            spl_autoload_unregister($function);
        }
        foreach ($functions as $function) {
            if (\is_array($function) && $function[0] instanceof self) {
                $function = $function[0]->getClassLoader();
            }
            spl_autoload_register($function);
        }
    }
    public static function checkClasses(): bool
    {
        if (!\is_array($functions = spl_autoload_functions())) {
            return \false;
        }
        $loader = null;
        foreach ($functions as $function) {
            if (\is_array($function) && $function[0] instanceof self) {
                $loader = $function[0];
                break;
            }
        }
        if (null === $loader) {
            return \false;
        }
        static $offsets = ['get_declared_interfaces' => 0, 'get_declared_traits' => 0, 'get_declared_classes' => 0];
        foreach ($offsets as $getSymbols => $i) {
            $symbols = $getSymbols();
            for (; $i < \count($symbols); ++$i) {
                if (!is_subclass_of($symbols[$i], MockObject::class) && !is_subclass_of($symbols[$i], Stub::class) && !is_subclass_of($symbols[$i], ProphecySubjectInterface::class) && !is_subclass_of($symbols[$i], Proxy::class) && !is_subclass_of($symbols[$i], ProxyInterface::class) && !is_subclass_of($symbols[$i], LazyObjectInterface::class) && !is_subclass_of($symbols[$i], LegacyProxy::class) && !is_subclass_of($symbols[$i], MockInterface::class) && !is_subclass_of($symbols[$i], IMock::class) && !(is_subclass_of($symbols[$i], LazyClosure::class) && str_contains($symbols[$i], "@anonymous\x00"))) {
                    $loader->checkClass($symbols[$i]);
                }
            }
            $offsets[$getSymbols] = $i;
        }
        return \true;
    }
    public function findFile(string $class): ?string
    {
        return $this->isFinder ? $this->classLoader[0]->findFile($class) ?: null : null;
    }
    /**
     * Loads the given class or interface.
     *
     * @throws \RuntimeException
     */
    public function loadClass(string $class): void
    {
        $e = error_reporting(error_reporting() | \E_PARSE | \E_ERROR | \E_CORE_ERROR | \E_COMPILE_ERROR);
        try {
            if ($this->isFinder && !isset($this->loaded[$class])) {
                $this->loaded[$class] = \true;
                if (!$file = $this->classLoader[0]->findFile($class) ?: '') {
                    // no-op
                } elseif (\function_exists('opcache_is_script_cached') && @opcache_is_script_cached($file)) {
                    include $file;
                    return;
                } elseif (\false === include $file) {
                    return;
                }
            } else {
                ($this->classLoader)($class);
                $file = '';
            }
        } finally {
            error_reporting($e);
        }
        $this->checkClass($class, $file);
    }
    private function checkClass(string $class, ?string $file = null): void
    {
        $exists = null === $file || class_exists($class, \false) || interface_exists($class, \false) || trait_exists($class, \false);
        if (null !== $file && $class && '\\' === $class[0]) {
            $class = substr($class, 1);
        }
        if ($exists) {
            if (isset(self::$checkedClasses[$class])) {
                return;
            }
            self::$checkedClasses[$class] = \true;
            $refl = new \ReflectionClass($class);
            if (null === $file && $refl->isInternal()) {
                return;
            }
            $name = $refl->getName();
            if ($name !== $class && 0 === strcasecmp($name, $class)) {
                throw new \RuntimeException(\sprintf('Case mismatch between loaded and declared class names: "%s" vs "%s".', $class, $name));
            }
            $deprecations = $this->checkAnnotations($refl, $name);
            foreach ($deprecations as $message) {
                @trigger_error($message, \E_USER_DEPRECATED);
            }
        }
        if (!$file) {
            return;
        }
        if (!$exists) {
            if (str_contains($class, '/')) {
                throw new \RuntimeException(\sprintf('Trying to autoload a class with an invalid name "%s". Be careful that the namespace separator is "\" in PHP, not "/".', $class));
            }
            throw new \RuntimeException(\sprintf('The autoloader expected class "%s" to be defined in file "%s". The file was found but the class was not in it, the class name or namespace probably has a typo.', $class, $file));
        }
        if (self::$caseCheck && $message = $this->checkCase($refl, $file, $class)) {
            throw new \RuntimeException(\sprintf('Case mismatch between class and real file names: "%s" vs "%s" in "%s".', $message[0], $message[1], $message[2]));
        }
    }
    public function checkAnnotations(\ReflectionClass $refl, string $class): array
    {
        if ('Symfony\Bridge\PhpUnit\Legacy\SymfonyTestsListenerForV7' === $class || 'Symfony\Bridge\PhpUnit\Legacy\SymfonyTestsListenerForV6' === $class) {
            return [];
        }
        $deprecations = [];
        $className = str_contains($class, "@anonymous\x00") ? ((get_parent_class($class) ?: key(class_implements($class))) ?: 'class') . '@anonymous' : $class;
        // Don't trigger deprecations for classes in the same vendor
        if ($class !== $className) {
            $vendor = preg_match('/^namespace ([^;\\\\\\s]++)[;\\\\]/m', @file_get_contents($refl->getFileName()), $vendor) ? $vendor[1] . '\\' : '';
            $vendorLen = \strlen($vendor);
        } elseif (2 > $vendorLen = 1 + (strpos($class, '\\') ?: strpos($class, '_'))) {
            $vendorLen = 0;
            $vendor = '';
        } else {
            $vendor = str_replace('_', '\\', substr($class, 0, $vendorLen));
        }
        $parent = get_parent_class($class) ?: null;
        self::$returnTypes[$class] = [];
        $classIsTemplate = \false;
        // Detect annotations on the class
        if ($doc = $this->parsePhpDoc($refl)) {
            $classIsTemplate = isset($doc['template']) || isset($doc['template-covariant']);
            foreach (['final', 'deprecated', 'internal'] as $annotation) {
                if (null !== $description = $doc[$annotation][0] ?? null) {
                    self::${$annotation}[$class] = '' !== $description ? ' ' . $description . (preg_match('/[.!]$/', $description) ? '' : '.') : '.';
                }
            }
            if ($refl->isInterface() && isset($doc['method'])) {
                foreach ($doc['method'] as $name => [$static, $returnType, $signature, $description]) {
                    if ($refl->hasMethod($static ? '__callStatic' : '__call')) {
                        // When the interface has "virtual" @method declarations but at the same time contains a __call/__callStatic magic method,
                        // do not trigger a deprecation notice. This is to address special use cases like in Predis' ClientInterface where the
                        // "@method" annotations never intend to actually add the method to the interface, but are used to document the "virtual"
                        // API provided by the interface through the technical implementation of magic calls. This might cause false negatives
                        // (missing notices) in the case that such interfaces are later amended with actual (real) methods.
                        continue;
                    }
                    self::$method[$class][] = [$class, $static, $returnType, $name . $signature, $description];
                    if ('' !== $returnType) {
                        $this->setReturnType($returnType, $refl->name, $name, $refl->getFileName(), $parent);
                    }
                }
            }
        }
        $parentAndOwnInterfaces = $this->getOwnInterfaces($class, $parent);
        if ($parent) {
            $parentAndOwnInterfaces[$parent] = $parent;
            if (!isset(self::$checkedClasses[$parent])) {
                $this->checkClass($parent);
            }
            if (isset(self::$final[$parent])) {
                $deprecations[] = \sprintf('The "%s" class is considered final%s It may change without further notice as of its next major version. You should not extend it from "%s".', $parent, self::$final[$parent], $className);
            }
        }
        // When the parent is a concrete class, we will trigger deprecation notices to make it aware that it needs
        // to add the new methods announced with @method. The parent will have to provide all those methods.
        // For child classes this means they will not need to deal with @method coming from any of the interfaces
        // the parent implements.
        // Put those interfaces that we can ignore into $parentInterfaces.
        // The ternary makes use of the fact that abstract parent classes will accumulate the methods in self::$method,
        // so !isset(self::$method[$parent]) indicates a concrete parent class.
        $parentInterfaces = $parent && !isset(self::$method[$parent]) ? class_implements($parent, \false) : [];
        // Detect if the parent is annotated
        foreach ($parentAndOwnInterfaces + class_uses($class, \false) as $use) {
            if (!isset(self::$checkedClasses[$use])) {
                $this->checkClass($use);
            }
            if (isset(self::$deprecated[$use]) && strncmp($vendor, str_replace('_', '\\', $use), $vendorLen) && !isset(self::$deprecated[$class])) {
                $type = class_exists($class, \false) ? 'class' : (interface_exists($class, \false) ? 'interface' : 'trait');
                $verb = class_exists($use, \false) || interface_exists($class, \false) ? 'extends' : (interface_exists($use, \false) ? 'implements' : 'uses');
                $deprecations[] = \sprintf('The "%s" %s %s "%s" that is deprecated%s', $className, $type, $verb, $use, self::$deprecated[$use]);
            }
            if (isset(self::$internal[$use]) && strncmp($vendor, str_replace('_', '\\', $use), $vendorLen)) {
                $deprecations[] = \sprintf('The "%s" %s is considered internal%s It may change without further notice. You should not use it from "%s".', $use, class_exists($use, \false) ? 'class' : (interface_exists($use, \false) ? 'interface' : 'trait'), self::$internal[$use], $className);
            }
            if (isset(self::$method[$use])) {
                if ($refl->isAbstract() || $refl->isInterface()) {
                    // Abstract classes and interfaces inherit @method from interfaces they
                    // implement directly or through inheritance.
                    if (isset(self::$method[$class])) {
                        self::$method[$class] = array_merge(self::$method[$class], self::$method[$use]);
                    } else {
                        self::$method[$class] = self::$method[$use];
                    }
                } else {
                    if (!strncmp($vendor, str_replace('_', '\\', $use), $vendorLen) && str_starts_with($className, 'Symfony\\') && (!class_exists(InstalledVersions::class) || 'symfony/symfony' !== InstalledVersions::getRootPackage()['name'])) {
                        // skip "same vendor" @method deprecations for Symfony\* classes unless symfony/symfony is being tested
                        continue;
                    }
                    foreach (self::$method[$use] as [$interface, $static, $returnType, $name, $description]) {
                        if (isset($parentInterfaces[$interface])) {
                            // The @method annotation comes from an interface that has already been implemented by a concrete parent class,
                            // so we can ignore it here.
                            continue;
                        }
                        $realName = substr($name, 0, strpos($name, '('));
                        if (!$refl->hasMethod($realName) || !($methodRefl = $refl->getMethod($realName))->isPublic() || ($static xor $methodRefl->isStatic())) {
                            $deprecations[] = \sprintf('Class "%s" should implement method "%s::%s%s"%s', $className, ($static ? 'static ' : '') . $interface, $name, $returnType ? ': ' . $returnType : '', null === $description ? '.' : ': ' . $description);
                        }
                    }
                }
            }
        }
        if (trait_exists($class)) {
            $file = $refl->getFileName();
            foreach ($refl->getMethods() as $method) {
                if ($method->getFileName() === $file) {
                    self::$methodTraits[$file][$method->getStartLine()] = $class;
                }
            }
            return $deprecations;
        }
        // Inherit @final, @internal, @param and @return annotations for methods
        self::$finalMethods[$class] = [];
        self::$internalMethods[$class] = [];
        self::$annotatedParameters[$class] = [];
        self::$finalProperties[$class] = [];
        self::$finalConstants[$class] = [];
        foreach ($parentAndOwnInterfaces as $use) {
            foreach (['finalMethods', 'internalMethods', 'annotatedParameters', 'returnTypes', 'finalProperties', 'finalConstants'] as $property) {
                if (isset(self::${$property}[$use])) {
                    self::${$property}[$class] = self::${$property}[$class] ? self::${$property}[$use] + self::${$property}[$class] : self::${$property}[$use];
                }
            }
            if (null !== (TentativeTypes::RETURN_TYPES[$use] ?? null)) {
                foreach (TentativeTypes::RETURN_TYPES[$use] as $method => $returnType) {
                    $returnType = explode('|', $returnType);
                    foreach ($returnType as $i => $t) {
                        if ('?' !== $t && !isset(self::BUILTIN_RETURN_TYPES[$t])) {
                            $returnType[$i] = '\\' . $t;
                        }
                    }
                    $returnType = implode('|', $returnType);
                    self::$returnTypes[$class] += [$method => [$returnType, str_starts_with($returnType, '?') ? substr($returnType, 1) . '|null' : $returnType, $use, '']];
                }
            }
        }
        foreach ($refl->getMethods() as $method) {
            if ($method->class !== $class) {
                continue;
            }
            if (null === $ns = self::$methodTraits[$method->getFileName()][$method->getStartLine()] ?? null) {
                $ns = $vendor;
                $len = $vendorLen;
            } elseif (2 > $len = 1 + (strpos($ns, '\\') ?: strpos($ns, '_'))) {
                $len = 0;
                $ns = '';
            } else {
                $ns = str_replace('_', '\\', substr($ns, 0, $len));
            }
            if ($parent && isset(self::$finalMethods[$parent][$method->name])) {
                [$declaringClass, $message] = self::$finalMethods[$parent][$method->name];
                $deprecations[] = \sprintf('The "%s::%s()" method is considered final%s It may change without further notice as of its next major version. You should not extend it from "%s".', $declaringClass, $method->name, $message, $className);
            }
            if (isset(self::$internalMethods[$class][$method->name])) {
                [$declaringClass, $message] = self::$internalMethods[$class][$method->name];
                if (strncmp($ns, $declaringClass, $len)) {
                    $deprecations[] = \sprintf('The "%s::%s()" method is considered internal%s It may change without further notice. You should not extend it from "%s".', $declaringClass, $method->name, $message, $className);
                }
            }
            // To read method annotations
            $doc = $this->parsePhpDoc($method);
            if (($classIsTemplate || isset($doc['template']) || isset($doc['template-covariant'])) && $method->hasReturnType()) {
                unset($doc['return']);
            }
            if (isset(self::$annotatedParameters[$class][$method->name])) {
                $definedParameters = [];
                foreach ($method->getParameters() as $parameter) {
                    $definedParameters[$parameter->name] = \true;
                }
                foreach (self::$annotatedParameters[$class][$method->name] as $parameterName => $deprecation) {
                    if (!isset($definedParameters[$parameterName]) && !isset($doc['param'][$parameterName])) {
                        $deprecations[] = \sprintf($deprecation, $className);
                    }
                }
            }
            $forcePatchTypes = $this->patchTypes['force'];
            if ($canAddReturnType = null !== $forcePatchTypes && !str_contains($method->getFileName(), \DIRECTORY_SEPARATOR . 'vendor' . \DIRECTORY_SEPARATOR)) {
                if ('void' !== (self::MAGIC_METHODS[$method->name] ?? 'void')) {
                    $this->patchTypes['force'] = $forcePatchTypes ?: 'docblock';
                }
                $canAddReturnType = 2 === (int) $forcePatchTypes || \false !== stripos($method->getFileName(), \DIRECTORY_SEPARATOR . 'Tests' . \DIRECTORY_SEPARATOR) || $refl->isFinal() || $method->isFinal() || $method->isPrivate() || '.' === (self::$internal[$class] ?? null) && !$refl->isAbstract() || '.' === (self::$final[$class] ?? null) || '' === ($doc['final'][0] ?? null) || '' === ($doc['internal'][0] ?? null);
            }
            if (null !== ($returnType = self::$returnTypes[$class][$method->name] ?? null) && 'docblock' === $this->patchTypes['force'] && !$method->hasReturnType() && isset(TentativeTypes::RETURN_TYPES[$returnType[2]][$method->name])) {
                $this->patchReturnTypeWillChange($method);
            }
            if (null !== ($returnType ??= self::MAGIC_METHODS[$method->name] ?? null) && !$method->hasReturnType() && !isset($doc['return'])) {
                [$normalizedType, $returnType, $declaringClass, $declaringFile] = \is_string($returnType) ? [$returnType, $returnType, '', ''] : $returnType;
                if ($canAddReturnType && 'docblock' !== $this->patchTypes['force']) {
                    $this->patchMethod($method, $returnType, $declaringFile, $normalizedType);
                }
                if (!isset($doc['deprecated']) && strncmp($ns, $declaringClass, $len)) {
                    if ('docblock' === $this->patchTypes['force']) {
                        $this->patchMethod($method, $returnType, $declaringFile, $normalizedType);
                    } elseif ('' !== $declaringClass && $this->patchTypes['deprecations']) {
                        $deprecations[] = \sprintf('Method "%s::%s()" might add "%s" as a native return type declaration in the future. Do the same in %s "%s" now to avoid errors or add an explicit @return annotation to suppress this message.', $declaringClass, $method->name, $normalizedType, interface_exists($declaringClass) ? 'implementation' : 'child class', $className);
                    }
                }
            }
            if (!$doc) {
                $this->patchTypes['force'] = $forcePatchTypes;
                continue;
            }
            if (isset($doc['return']) || 'void' !== (self::MAGIC_METHODS[$method->name] ?? 'void')) {
                $this->setReturnType($doc['return'] ?? self::MAGIC_METHODS[$method->name], $method->class, $method->name, $method->getFileName(), $parent, $method->getReturnType());
                if (isset(self::$returnTypes[$class][$method->name][0]) && $canAddReturnType) {
                    $this->fixReturnStatements($method, self::$returnTypes[$class][$method->name][0]);
                }
                if ($method->isPrivate()) {
                    unset(self::$returnTypes[$class][$method->name]);
                }
            }
            $this->patchTypes['force'] = $forcePatchTypes;
            if ($method->isPrivate()) {
                continue;
            }
            $finalOrInternal = \false;
            foreach (['final', 'internal'] as $annotation) {
                if (null !== $description = $doc[$annotation][0] ?? null) {
                    self::${$annotation . 'Methods'}[$class][$method->name] = [$class, '' !== $description ? ' ' . $description . (preg_match('/[[:punct:]]$/', $description) ? '' : '.') : '.'];
                    $finalOrInternal = \true;
                }
            }
            if ($finalOrInternal || $method->isConstructor() || !isset($doc['param']) || StatelessInvocation::class === $class) {
                continue;
            }
            if (!isset(self::$annotatedParameters[$class][$method->name])) {
                $definedParameters = [];
                foreach ($method->getParameters() as $parameter) {
                    $definedParameters[$parameter->name] = \true;
                }
            }
            foreach ($doc['param'] as $parameterName => $parameterType) {
                if (!isset($definedParameters[$parameterName])) {
                    self::$annotatedParameters[$class][$method->name][$parameterName] = \sprintf('The "%%s::%s()" method will require a new "%s$%s" argument in the next major version of its %s "%s", not defining it is deprecated.', $method->name, $parameterType ? $parameterType . ' ' : '', $parameterName, interface_exists($className) ? 'interface' : 'parent class', $className);
                }
            }
        }
        $finals = isset(self::$final[$class]) || $refl->isFinal() ? [] : ['finalConstants' => $refl->getReflectionConstants(\ReflectionClassConstant::IS_PUBLIC | \ReflectionClassConstant::IS_PROTECTED), 'finalProperties' => $refl->getProperties(\ReflectionProperty::IS_PUBLIC | \ReflectionProperty::IS_PROTECTED)];
        foreach ($finals as $type => $reflectors) {
            foreach ($reflectors as $r) {
                if ($r->class !== $class) {
                    continue;
                }
                $doc = $this->parsePhpDoc($r);
                foreach ($parentAndOwnInterfaces as $use) {
                    if (isset(self::${$type}[$use][$r->name]) && !isset($doc['deprecated']) && ('finalConstants' === $type || substr($use, 0, strrpos($use, '\\')) !== substr($use, 0, strrpos($class, '\\')))) {
                        $msg = 'finalConstants' === $type ? '%s" constant' : '$%s" property';
                        $deprecations[] = \sprintf('The "%s::' . $msg . ' is considered final. You should not override it in "%s".', self::${$type}[$use][$r->name], $r->name, $class);
                    }
                }
                if (isset($doc['final']) || 'finalProperties' === $type && str_starts_with($class, 'Symfony\\') && !$r->hasType()) {
                    self::${$type}[$class][$r->name] = $class;
                }
            }
        }
        return $deprecations;
    }
    public function checkCase(\ReflectionClass $refl, string $file, string $class): ?array
    {
        $real = explode('\\', $class . strrchr($file, '.'));
        $tail = explode(\DIRECTORY_SEPARATOR, str_replace('/', \DIRECTORY_SEPARATOR, $file));
        $i = \count($tail) - 1;
        $j = \count($real) - 1;
        while (isset($tail[$i], $real[$j]) && $tail[$i] === $real[$j]) {
            --$i;
            --$j;
        }
        array_splice($tail, 0, $i + 1);
        if (!$tail) {
            return null;
        }
        $tail = \DIRECTORY_SEPARATOR . implode(\DIRECTORY_SEPARATOR, $tail);
        $tailLen = \strlen($tail);
        $real = $refl->getFileName();
        if (2 === self::$caseCheck) {
            $real = $this->darwinRealpath($real);
        }
        if (0 === substr_compare($real, $tail, -$tailLen, $tailLen, \true) && 0 !== substr_compare($real, $tail, -$tailLen, $tailLen, \false)) {
            return [substr($tail, -$tailLen + 1), substr($real, -$tailLen + 1), substr($real, 0, -$tailLen + 1)];
        }
        return null;
    }
    /**
     * `realpath` on MacOSX doesn't normalize the case of characters.
     */
    private function darwinRealpath(string $real): string
    {
        $i = 1 + strrpos($real, '/');
        $file = substr($real, $i);
        $real = substr($real, 0, $i);
        if (isset(self::$darwinCache[$real])) {
            $kDir = $real;
        } else {
            $kDir = strtolower($real);
            if (isset(self::$darwinCache[$kDir])) {
                $real = self::$darwinCache[$kDir][0];
            } else {
                $dir = getcwd();
                if (!@chdir($real)) {
                    return $real . $file;
                }
                $real = getcwd() . '/';
                chdir($dir);
                $dir = $real;
                $k = $kDir;
                $i = \strlen($dir) - 1;
                while (!isset(self::$darwinCache[$k])) {
                    self::$darwinCache[$k] = [$dir, []];
                    self::$darwinCache[$dir] =& self::$darwinCache[$k];
                    while ('/' !== $dir[--$i]) {
                    }
                    $k = substr($k, 0, ++$i);
                    $dir = substr($dir, 0, $i--);
                }
            }
        }
        $dirFiles = self::$darwinCache[$kDir][1];
        if (!isset($dirFiles[$file]) && str_ends_with($file, ') : eval()\'d code')) {
            // Get the file name from "file_name.php(123) : eval()'d code"
            $file = substr($file, 0, strrpos($file, '(', -17));
        }
        if (isset($dirFiles[$file])) {
            return $real . $dirFiles[$file];
        }
        $kFile = strtolower($file);
        if (!isset($dirFiles[$kFile])) {
            foreach (scandir($real, 2) as $f) {
                if ('.' !== $f[0]) {
                    $dirFiles[$f] = $f;
                    if ($f === $file) {
                        $kFile = $file;
                    } elseif ($f !== $k = strtolower($f)) {
                        $dirFiles[$k] = $f;
                    }
                }
            }
            self::$darwinCache[$kDir][1] = $dirFiles;
        }
        return $real . $dirFiles[$kFile];
    }
    /**
     * `class_implements` includes interfaces from the parents so we have to manually exclude them.
     *
     * @return string[]
     */
    private function getOwnInterfaces(string $class, ?string $parent): array
    {
        $ownInterfaces = class_implements($class, \false);
        if ($parent) {
            foreach (class_implements($parent, \false) as $interface) {
                unset($ownInterfaces[$interface]);
            }
        }
        foreach ($ownInterfaces as $interface) {
            foreach (class_implements($interface) as $interface) {
                unset($ownInterfaces[$interface]);
            }
        }
        return $ownInterfaces;
    }
    private function setReturnType(string $types, string $class, string $method, string $filename, ?string $parent, ?\ReflectionType $returnType = null): void
    {
        if ('__construct' === $method) {
            return;
        }
        if ('null' === $types) {
            self::$returnTypes[$class][$method] = ['null', 'null', $class, $filename];
            return;
        }
        if ($nullable = str_starts_with($types, 'null|')) {
            $types = substr($types, 5);
        } elseif ($nullable = str_ends_with($types, '|null')) {
            $types = substr($types, 0, -5);
        }
        $arrayType = ['array' => 'array'];
        $typesMap = [];
        $glue = str_contains($types, '&') ? '&' : '|';
        foreach (explode($glue, $types) as $t) {
            $t = self::SPECIAL_RETURN_TYPES[strtolower($t)] ?? $t;
            $typesMap[$this->normalizeType($t, $class, $parent, $returnType)][$t] = $t;
        }
        if (isset($typesMap['array'])) {
            if (isset($typesMap['Traversable']) || isset($typesMap['\Traversable'])) {
                $typesMap['iterable'] = $arrayType !== $typesMap['array'] ? $typesMap['array'] : ['iterable'];
                unset($typesMap['array'], $typesMap['Traversable'], $typesMap['\Traversable']);
            } elseif ($arrayType !== $typesMap['array'] && isset(self::$returnTypes[$class][$method]) && !$returnType) {
                return;
            }
        }
        if (isset($typesMap['array']) && isset($typesMap['iterable'])) {
            if ($arrayType !== $typesMap['array']) {
                $typesMap['iterable'] = $typesMap['array'];
            }
            unset($typesMap['array']);
        }
        $iterable = $object = \true;
        foreach ($typesMap as $n => $t) {
            if ('null' !== $n) {
                $iterable = $iterable && (\in_array($n, ['array', 'iterable']) || str_contains($n, 'Iterator'));
                $object = $object && (\in_array($n, ['callable', 'object', '$this', 'static']) || !isset(self::SPECIAL_RETURN_TYPES[$n]));
            }
        }
        $phpTypes = [];
        $docTypes = [];
        foreach ($typesMap as $n => $t) {
            if ('null' === $n) {
                $nullable = \true;
                continue;
            }
            $docTypes[] = $t;
            if ('mixed' === $n || 'void' === $n) {
                $nullable = \false;
                $phpTypes = ['' => $n];
                continue;
            }
            if ('resource' === $n) {
                // there is no native type for "resource"
                return;
            }
            if (!preg_match('/^(?:\\\\?[a-zA-Z_\x80-\xff][a-zA-Z0-9_\x80-\xff]*)+$/', $n)) {
                // exclude any invalid PHP class name (e.g. `Cookie::SAMESITE_*`)
                continue;
            }
            if (!isset($phpTypes[''])) {
                $phpTypes[] = $n;
            }
        }
        $docTypes = array_merge([], ...$docTypes);
        if (!$phpTypes) {
            return;
        }
        if (1 < \count($phpTypes)) {
            if ($iterable && '8.0' > $this->patchTypes['php']) {
                $phpTypes = $docTypes = ['iterable'];
            } elseif ($object && 'object' === $this->patchTypes['force']) {
                $phpTypes = $docTypes = ['object'];
            } elseif ('8.0' > $this->patchTypes['php']) {
                // ignore multi-types return declarations
                return;
            }
        }
        $phpType = \sprintf($nullable ? 1 < \count($phpTypes) ? '%s|null' : '?%s' : '%s', implode($glue, $phpTypes));
        $docType = \sprintf($nullable ? '%s|null' : '%s', implode($glue, $docTypes));
        self::$returnTypes[$class][$method] = [$phpType, $docType, $class, $filename];
    }
    private function normalizeType(string $type, string $class, ?string $parent, ?\ReflectionType $returnType): string
    {
        if (isset(self::SPECIAL_RETURN_TYPES[$lcType = strtolower($type)])) {
            if ('parent' === $lcType = self::SPECIAL_RETURN_TYPES[$lcType]) {
                $lcType = null !== $parent ? '\\' . $parent : 'parent';
            } elseif ('self' === $lcType) {
                $lcType = '\\' . $class;
            }
            return $lcType;
        }
        // We could resolve "use" statements to return the FQDN
        // but this would be too expensive for a runtime checker
        if (!str_ends_with($type, '[]')) {
            return $type;
        }
        if ($returnType instanceof \ReflectionNamedType) {
            $type = $returnType->getName();
            if ('mixed' !== $type) {
                return isset(self::SPECIAL_RETURN_TYPES[$type]) ? $type : '\\' . $type;
            }
        }
        return 'array';
    }
    /**
     * Utility method to add #[ReturnTypeWillChange] where php triggers deprecations.
     */
    private function patchReturnTypeWillChange(\ReflectionMethod $method): void
    {
        if (\count($method->getAttributes(\ReturnTypeWillChange::class))) {
            return;
        }
        if (!is_file($file = $method->getFileName())) {
            return;
        }
        $fileOffset = self::$fileOffsets[$file] ?? 0;
        $code = file($file);
        $startLine = $method->getStartLine() + $fileOffset - 2;
        if (\false !== stripos($code[$startLine], 'ReturnTypeWillChange')) {
            return;
        }
        $code[$startLine] .= "    #[\\ReturnTypeWillChange]\n";
        self::$fileOffsets[$file] = 1 + $fileOffset;
        file_put_contents($file, $code);
    }
    /**
     * Utility method to add @return annotations to the Symfony code-base where it triggers self-deprecations.
     */
    private function patchMethod(\ReflectionMethod $method, string $returnType, string $declaringFile, string $normalizedType): void
    {
        static $patchedMethods = [];
        static $useStatements = [];
        if (!is_file($file = $method->getFileName()) || isset($patchedMethods[$file][$startLine = $method->getStartLine()])) {
            return;
        }
        $patchedMethods[$file][$startLine] = \true;
        $fileOffset = self::$fileOffsets[$file] ?? 0;
        $startLine += $fileOffset - 2;
        if ($nullable = str_ends_with($returnType, '|null')) {
            $returnType = substr($returnType, 0, -5);
        }
        $glue = str_contains($returnType, '&') ? '&' : '|';
        $returnType = explode($glue, $returnType);
        $code = file($file);
        foreach ($returnType as $i => $type) {
            if (preg_match('/((?:\[\])+)$/', $type, $m)) {
                $type = substr($type, 0, -\strlen($m[1]));
                $format = '%s' . $m[1];
            } else {
                $format = null;
            }
            if (isset(self::SPECIAL_RETURN_TYPES[$type]) || '\\' === $type[0] && !$p = strrpos($type, '\\', 1)) {
                continue;
            }
            [$namespace, $useOffset, $useMap] = $useStatements[$file] ??= self::getUseStatements($file);
            if ('\\' !== $type[0]) {
                [$declaringNamespace, , $declaringUseMap] = $useStatements[$declaringFile] ??= self::getUseStatements($declaringFile);
                $p = strpos($type, '\\', 1);
                $alias = $p ? substr($type, 0, $p) : $type;
                if (isset($declaringUseMap[$alias])) {
                    $type = '\\' . $declaringUseMap[$alias] . ($p ? substr($type, $p) : '');
                } else {
                    $type = '\\' . $declaringNamespace . $type;
                }
                $p = strrpos($type, '\\', 1);
            }
            $alias = substr($type, 1 + $p);
            $type = substr($type, 1);
            if (!isset($useMap[$alias]) && (class_exists($c = $namespace . $alias) || interface_exists($c) || trait_exists($c))) {
                $useMap[$alias] = $c;
            }
            if (!isset($useMap[$alias])) {
                $useStatements[$file][2][$alias] = $type;
                $code[$useOffset] = "use {$type};\n" . $code[$useOffset];
                ++$fileOffset;
            } elseif ($useMap[$alias] !== $type) {
                $alias .= 'FIXME';
                $useStatements[$file][2][$alias] = $type;
                $code[$useOffset] = "use {$type} as {$alias};\n" . $code[$useOffset];
                ++$fileOffset;
            }
            $returnType[$i] = null !== $format ? \sprintf($format, $alias) : $alias;
        }
        if ('docblock' === $this->patchTypes['force'] || 'object' === $normalizedType && '7.1' === $this->patchTypes['php']) {
            $returnType = implode($glue, $returnType) . ($nullable ? '|null' : '');
            if (str_contains($code[$startLine], '#[')) {
                --$startLine;
            }
            if ($method->getDocComment()) {
                $code[$startLine] = "     * @return {$returnType}\n" . $code[$startLine];
            } else {
                $code[$startLine] .= <<<EOTXT
    /**
     * @return {$returnType}
     */

EOTXT;
            }
            $fileOffset += substr_count($code[$startLine], "\n") - 1;
        }
        self::$fileOffsets[$file] = $fileOffset;
        file_put_contents($file, $code);
        $this->fixReturnStatements($method, $normalizedType);
    }
    private static function getUseStatements(string $file): array
    {
        $namespace = '';
        $useMap = [];
        $useOffset = 0;
        if (!is_file($file)) {
            return [$namespace, $useOffset, $useMap];
        }
        $file = file($file);
        for ($i = 0; $i < \count($file); ++$i) {
            if (preg_match('/^(class|interface|trait|abstract) /', $file[$i])) {
                break;
            }
            if (str_starts_with($file[$i], 'namespace ')) {
                $namespace = substr($file[$i], \strlen('namespace '), -2) . '\\';
                $useOffset = $i + 2;
            }
            if (str_starts_with($file[$i], 'use ')) {
                $useOffset = $i;
                for (; str_starts_with($file[$i], 'use '); ++$i) {
                    $u = explode(' as ', substr($file[$i], 4, -2), 2);
                    if (1 === \count($u)) {
                        $p = strrpos($u[0], '\\');
                        $useMap[substr($u[0], \false !== $p ? 1 + $p : 0)] = $u[0];
                    } else {
                        $useMap[$u[1]] = $u[0];
                    }
                }
                break;
            }
        }
        return [$namespace, $useOffset, $useMap];
    }
    private function fixReturnStatements(\ReflectionMethod $method, string $returnType): void
    {
        if ('docblock' !== $this->patchTypes['force']) {
            if ('7.1' === $this->patchTypes['php'] && 'object' === ltrim($returnType, '?')) {
                return;
            }
            if ('7.4' > $this->patchTypes['php'] && $method->hasReturnType()) {
                return;
            }
            if ('8.0' > $this->patchTypes['php'] && (str_contains($returnType, '|') || \in_array($returnType, ['mixed', 'static'], \true))) {
                return;
            }
            if ('8.1' > $this->patchTypes['php'] && str_contains($returnType, '&')) {
                return;
            }
        }
        if (!is_file($file = $method->getFileName())) {
            return;
        }
        $fixedCode = $code = file($file);
        $i = (self::$fileOffsets[$file] ?? 0) + $method->getStartLine();
        if ('?' !== $returnType && 'docblock' !== $this->patchTypes['force']) {
            $fixedCode[$i - 1] = preg_replace('/\)(?::[^;\n]++)?(;?\n)/', "): {$returnType}\\1", $code[$i - 1]);
        }
        $end = $method->isGenerator() ? $i : $method->getEndLine();
        $inClosure = \false;
        $braces = 0;
        for (; $i < $end; ++$i) {
            if (!$inClosure) {
                $inClosure = str_contains($code[$i], 'function (');
            }
            if ($inClosure) {
                $braces += substr_count($code[$i], '{') - substr_count($code[$i], '}');
                $inClosure = $braces > 0;
                continue;
            }
            if ('void' === $returnType) {
                $fixedCode[$i] = str_replace('    return null;', '    return;', $code[$i]);
            } elseif ('mixed' === $returnType || '?' === $returnType[0]) {
                $fixedCode[$i] = str_replace('    return;', '    return null;', $code[$i]);
            } else {
                $fixedCode[$i] = str_replace('    return;', "    return {$returnType}!?;", $code[$i]);
            }
        }
        if ($fixedCode !== $code) {
            file_put_contents($file, $fixedCode);
        }
    }
    /**
     * @param \ReflectionClass|\ReflectionMethod|\ReflectionProperty $reflector
     */
    private function parsePhpDoc(\Reflector $reflector): array
    {
        if (!$doc = $reflector->getDocComment()) {
            return [];
        }
        $tagName = '';
        $tagContent = '';
        $tags = [];
        foreach (explode("\n", substr($doc, 3, -2)) as $line) {
            $line = ltrim($line);
            $line = ltrim($line, '*');
            if ('' === $line = trim($line)) {
                if ('' !== $tagName) {
                    $tags[$tagName][] = $tagContent;
                }
                $tagName = $tagContent = '';
                continue;
            }
            if ('@' === $line[0]) {
                if ('' !== $tagName) {
                    $tags[$tagName][] = $tagContent;
                    $tagContent = '';
                }
                if (preg_match('{^@([-a-zA-Z0-9_:]++)(\s|$)}', $line, $m)) {
                    $tagName = $m[1];
                    $tagContent = str_replace("\t", ' ', ltrim(substr($line, 2 + \strlen($tagName))));
                } else {
                    $tagName = '';
                }
            } elseif ('' !== $tagName) {
                $tagContent .= ' ' . str_replace("\t", ' ', $line);
            }
        }
        if ('' !== $tagName) {
            $tags[$tagName][] = $tagContent;
        }
        foreach ($tags['method'] ?? [] as $i => $method) {
            unset($tags['method'][$i]);
            $parts = preg_split('{(\s++|\((?:[^()]*+|(?R))*\)(?: *: *[^ ]++)?|<(?:[^<>]*+|(?R))*>|\{(?:[^{}]*+|(?R))*\})}', $method, -1, \PREG_SPLIT_DELIM_CAPTURE);
            $returnType = '';
            $static = 'static' === $parts[0];
            for ($i = $static ? 2 : 0; null !== $p = $parts[$i] ?? null; $i += 2) {
                if (\in_array($p, ['', 'callable'], \true) || \in_array(substr($returnType, -1), ['|', '&'], \true) || \in_array($p[0], ['|', '&'], \true)) {
                    $returnType .= trim($parts[$i - 1] ?? '') . $p;
                    continue;
                }
                $signature = '(' === ($parts[$i + 1][0] ?? '(') ? $parts[$i + 1] ?? '()' : null;
                if (null === $signature && '' === $returnType) {
                    $returnType = $p;
                    continue;
                }
                if ($static && 2 === $i) {
                    $static = \false;
                    $returnType = 'static';
                }
                if (\in_array($description = trim(implode('', \array_slice($parts, 2 + $i))), ['', '.'], \true)) {
                    $description = null;
                } elseif (!preg_match('/[.!]$/', $description)) {
                    $description .= '.';
                }
                $tags['method'][$p] = [$static, $returnType, $signature ?? '()', $description];
                break;
            }
        }
        foreach ($tags['param'] ?? [] as $i => $param) {
            unset($tags['param'][$i]);
            if (\strlen($param) !== strcspn($param, '<{(')) {
                $param = preg_replace('{\(([^()]*+|(?R))*\)(?: *: *[^ ]++)?|<([^<>]*+|(?R))*>|\{([^{}]*+|(?R))*\}}', '', $param);
            }
            if (\false === $i = strpos($param, '$')) {
                continue;
            }
            $type = 0 === $i ? '' : rtrim(substr($param, 0, $i), ' &');
            $param = substr($param, 1 + $i, (strpos($param, ' ', $i) ?: 1 + $i + \strlen($param)) - $i - 1);
            $tags['param'][$param] = $type;
        }
        foreach (['var', 'return'] as $k) {
            if (null === $v = $tags[$k][0] ?? null) {
                continue;
            }
            if (\strlen($v) !== strcspn($v, '<{(')) {
                $v = preg_replace('{\(([^()]*+|(?R))*\)(?: *: *[^ ]++)?|<([^<>]*+|(?R))*>|\{([^{}]*+|(?R))*\}}', '', $v);
            }
            $tags[$k] = substr($v, 0, strpos($v, ' ') ?: \strlen($v)) ?: null;
        }
        return $tags;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\ErrorHandler;

use _ContaoManager\Psr\Log\AbstractLogger;
/**
 * A buffering logger that stacks logs for later.
 *
 * @author Nicolas Grekas <p@tchwork.com>
 */
class BufferingLogger extends AbstractLogger
{
    private array $logs = [];
    public function log($level, $message, array $context = []): void
    {
        $this->logs[] = [$level, $message, $context];
    }
    public function cleanLogs(): array
    {
        $logs = $this->logs;
        $this->logs = [];
        return $logs;
    }
    public function __serialize(): array
    {
        throw new \BadMethodCallException('Cannot serialize ' . __CLASS__);
    }
    public function __unserialize(array $data): void
    {
        throw new \BadMethodCallException('Cannot unserialize ' . __CLASS__);
    }
    public function __destruct()
    {
        foreach ($this->logs as [$level, $message, $context]) {
            if (str_contains($message, '{')) {
                foreach ($context as $key => $val) {
                    if (null === $val || \is_scalar($val) || \is_object($val) && \is_callable([$val, '__toString'])) {
                        $message = str_replace("{{$key}}", $val, $message);
                    } elseif ($val instanceof \DateTimeInterface) {
                        $message = str_replace("{{$key}}", $val->format(\DateTimeInterface::RFC3339), $message);
                    } elseif (\is_object($val)) {
                        $message = str_replace("{{$key}}", '[object ' . get_debug_type($val) . ']', $message);
                    } else {
                        $message = str_replace("{{$key}}", '[' . \gettype($val) . ']', $message);
                    }
                }
            }
            error_log(\sprintf('%s [%s] %s', date(\DateTimeInterface::RFC3339), $level, $message));
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\ErrorHandler;

use _ContaoManager\Psr\Log\LoggerInterface;
use _ContaoManager\Psr\Log\LogLevel;
use _ContaoManager\Symfony\Component\ErrorHandler\Error\FatalError;
use _ContaoManager\Symfony\Component\ErrorHandler\Error\OutOfMemoryError;
use _ContaoManager\Symfony\Component\ErrorHandler\ErrorEnhancer\ClassNotFoundErrorEnhancer;
use _ContaoManager\Symfony\Component\ErrorHandler\ErrorEnhancer\ErrorEnhancerInterface;
use _ContaoManager\Symfony\Component\ErrorHandler\ErrorEnhancer\UndefinedFunctionErrorEnhancer;
use _ContaoManager\Symfony\Component\ErrorHandler\ErrorEnhancer\UndefinedMethodErrorEnhancer;
use _ContaoManager\Symfony\Component\ErrorHandler\ErrorRenderer\CliErrorRenderer;
use _ContaoManager\Symfony\Component\ErrorHandler\ErrorRenderer\HtmlErrorRenderer;
use _ContaoManager\Symfony\Component\ErrorHandler\Exception\SilencedErrorContext;
/**
 * A generic ErrorHandler for the PHP engine.
 *
 * Provides five bit fields that control how errors are handled:
 * - thrownErrors: errors thrown as \ErrorException
 * - loggedErrors: logged errors, when not @-silenced
 * - scopedErrors: errors thrown or logged with their local context
 * - tracedErrors: errors logged with their stack trace
 * - screamedErrors: never @-silenced errors
 *
 * Each error level can be logged by a dedicated PSR-3 logger object.
 * Screaming only applies to logging.
 * Throwing takes precedence over logging.
 * Uncaught exceptions are logged as E_ERROR.
 * E_DEPRECATED and E_USER_DEPRECATED levels never throw.
 * E_RECOVERABLE_ERROR and E_USER_ERROR levels always throw.
 * Non catchable errors that can be detected at shutdown time are logged when the scream bit field allows so.
 * As errors have a performance cost, repeated errors are all logged, so that the developer
 * can see them and weight them as more important to fix than others of the same level.
 *
 * @author Nicolas Grekas <p@tchwork.com>
 * @author Grégoire Pineau <lyrixx@lyrixx.info>
 *
 * @final
 */
class ErrorHandler
{
    private array $levels = [\E_DEPRECATED => 'Deprecated', \E_USER_DEPRECATED => 'User Deprecated', \E_NOTICE => 'Notice', \E_USER_NOTICE => 'User Notice', \E_WARNING => 'Warning', \E_USER_WARNING => 'User Warning', \E_COMPILE_WARNING => 'Compile Warning', \E_CORE_WARNING => 'Core Warning', \E_USER_ERROR => 'User Error', \E_RECOVERABLE_ERROR => 'Catchable Fatal Error', \E_COMPILE_ERROR => 'Compile Error', \E_PARSE => 'Parse Error', \E_ERROR => 'Error', \E_CORE_ERROR => 'Core Error'];
    private array $loggers = [\E_DEPRECATED => [null, LogLevel::INFO], \E_USER_DEPRECATED => [null, LogLevel::INFO], \E_NOTICE => [null, LogLevel::WARNING], \E_USER_NOTICE => [null, LogLevel::WARNING], \E_WARNING => [null, LogLevel::WARNING], \E_USER_WARNING => [null, LogLevel::WARNING], \E_COMPILE_WARNING => [null, LogLevel::WARNING], \E_CORE_WARNING => [null, LogLevel::WARNING], \E_USER_ERROR => [null, LogLevel::CRITICAL], \E_RECOVERABLE_ERROR => [null, LogLevel::CRITICAL], \E_COMPILE_ERROR => [null, LogLevel::CRITICAL], \E_PARSE => [null, LogLevel::CRITICAL], \E_ERROR => [null, LogLevel::CRITICAL], \E_CORE_ERROR => [null, LogLevel::CRITICAL]];
    private int $thrownErrors = 0x1fff;
    // E_ALL - E_DEPRECATED - E_USER_DEPRECATED
    private int $scopedErrors = 0x1fff;
    // E_ALL - E_DEPRECATED - E_USER_DEPRECATED
    private int $tracedErrors = 0x77fb;
    // E_ALL - E_STRICT - E_PARSE
    private int $screamedErrors = 0x55;
    // E_ERROR + E_CORE_ERROR + E_COMPILE_ERROR + E_PARSE
    private int $loggedErrors = 0;
    private \Closure $configureException;
    private bool $debug;
    private bool $isRecursive = \false;
    private bool $isRoot = \false;
    /** @var callable|null */
    private $exceptionHandler;
    private ?BufferingLogger $bootstrappingLogger = null;
    private static ?string $reservedMemory = null;
    private static array $silencedErrorCache = [];
    private static int $silencedErrorCount = 0;
    private static int $exitCode = 0;
    /**
     * Registers the error handler.
     */
    public static function register(?self $handler = null, bool $replace = \true): self
    {
        if (null === self::$reservedMemory) {
            self::$reservedMemory = str_repeat('x', 32768);
            register_shutdown_function(self::handleFatalError(...));
        }
        if ($handlerIsNew = null === $handler) {
            $handler = new static();
        }
        if (null === $prev = set_error_handler([$handler, 'handleError'])) {
            restore_error_handler();
            // Specifying the error types earlier would expose us to https://bugs.php.net/63206
            set_error_handler([$handler, 'handleError'], $handler->thrownErrors | $handler->loggedErrors);
            $handler->isRoot = \true;
        }
        if ($handlerIsNew && \is_array($prev) && $prev[0] instanceof self) {
            $handler = $prev[0];
            $replace = \false;
        }
        if (!$replace && $prev) {
            restore_error_handler();
            $handlerIsRegistered = \is_array($prev) && $handler === $prev[0];
        } else {
            $handlerIsRegistered = \true;
        }
        if (\is_array($prev = set_exception_handler([$handler, 'handleException'])) && $prev[0] instanceof self) {
            restore_exception_handler();
            if (!$handlerIsRegistered) {
                $handler = $prev[0];
            } elseif ($handler !== $prev[0] && $replace) {
                set_exception_handler([$handler, 'handleException']);
                $p = $prev[0]->setExceptionHandler(null);
                $handler->setExceptionHandler($p);
                $prev[0]->setExceptionHandler($p);
            }
        } else {
            $handler->setExceptionHandler($prev ?? [$handler, 'renderException']);
        }
        $handler->throwAt(\E_ALL & $handler->thrownErrors, \true);
        return $handler;
    }
    /**
     * Calls a function and turns any PHP error into \ErrorException.
     *
     * @throws \ErrorException When $function(...$arguments) triggers a PHP error
     */
    public static function call(callable $function, mixed ...$arguments): mixed
    {
        set_error_handler(static function (int $type, string $message, string $file, int $line) {
            if (__FILE__ === $file) {
                $trace = debug_backtrace(\DEBUG_BACKTRACE_IGNORE_ARGS, 3);
                $file = $trace[2]['file'] ?? $file;
                $line = $trace[2]['line'] ?? $line;
            }
            throw new \ErrorException($message, 0, $type, $file, $line);
        });
        try {
            return $function(...$arguments);
        } finally {
            restore_error_handler();
        }
    }
    public function __construct(?BufferingLogger $bootstrappingLogger = null, bool $debug = \false)
    {
        if (\PHP_VERSION_ID < 80400) {
            $this->levels[\E_STRICT] = 'Runtime Notice';
            $this->loggers[\E_STRICT] = [null, LogLevel::WARNING];
        }
        if ($bootstrappingLogger) {
            $this->bootstrappingLogger = $bootstrappingLogger;
            $this->setDefaultLogger($bootstrappingLogger);
        }
        $traceReflector = new \ReflectionProperty(\Exception::class, 'trace');
        $this->configureException = \Closure::bind(static function ($e, $trace, $file = null, $line = null) use ($traceReflector) {
            $traceReflector->setValue($e, $trace);
            $e->file = $file ?? $e->file;
            $e->line = $line ?? $e->line;
        }, null, new class extends \Exception
        {
        });
        $this->debug = $debug;
    }
    /**
     * Sets a logger to non assigned errors levels.
     *
     * @param LoggerInterface $logger  A PSR-3 logger to put as default for the given levels
     * @param array|int|null  $levels  An array map of E_* to LogLevel::* or an integer bit field of E_* constants
     * @param bool            $replace Whether to replace or not any existing logger
     */
    public function setDefaultLogger(LoggerInterface $logger, array|int|null $levels = \E_ALL, bool $replace = \false): void
    {
        $loggers = [];
        if (\is_array($levels)) {
            foreach ($levels as $type => $logLevel) {
                if (empty($this->loggers[$type][0]) || $replace || $this->loggers[$type][0] === $this->bootstrappingLogger) {
                    $loggers[$type] = [$logger, $logLevel];
                }
            }
        } else {
            $levels ??= \E_ALL;
            foreach ($this->loggers as $type => $log) {
                if ($type & $levels && (empty($log[0]) || $replace || $log[0] === $this->bootstrappingLogger)) {
                    $log[0] = $logger;
                    $loggers[$type] = $log;
                }
            }
        }
        $this->setLoggers($loggers);
    }
    /**
     * Sets a logger for each error level.
     *
     * @param array $loggers Error levels to [LoggerInterface|null, LogLevel::*] map
     *
     * @throws \InvalidArgumentException
     */
    public function setLoggers(array $loggers): array
    {
        $prevLogged = $this->loggedErrors;
        $prev = $this->loggers;
        $flush = [];
        foreach ($loggers as $type => $log) {
            if (!isset($prev[$type])) {
                throw new \InvalidArgumentException('Unknown error type: ' . $type);
            }
            if (!\is_array($log)) {
                $log = [$log];
            } elseif (!\array_key_exists(0, $log)) {
                throw new \InvalidArgumentException('No logger provided.');
            }
            if (null === $log[0]) {
                $this->loggedErrors &= ~$type;
            } elseif ($log[0] instanceof LoggerInterface) {
                $this->loggedErrors |= $type;
            } else {
                throw new \InvalidArgumentException('Invalid logger provided.');
            }
            $this->loggers[$type] = $log + $prev[$type];
            if ($this->bootstrappingLogger && $prev[$type][0] === $this->bootstrappingLogger) {
                $flush[$type] = $type;
            }
        }
        $this->reRegister($prevLogged | $this->thrownErrors);
        if ($flush) {
            foreach ($this->bootstrappingLogger->cleanLogs() as $log) {
                $type = ThrowableUtils::getSeverity($log[2]['exception']);
                if (!isset($flush[$type])) {
                    $this->bootstrappingLogger->log($log[0], $log[1], $log[2]);
                } elseif ($this->loggers[$type][0]) {
                    $this->loggers[$type][0]->log($this->loggers[$type][1], $log[1], $log[2]);
                }
            }
        }
        return $prev;
    }
    public function setExceptionHandler(?callable $handler): ?callable
    {
        $prev = $this->exceptionHandler;
        $this->exceptionHandler = $handler;
        return $prev;
    }
    /**
     * Sets the PHP error levels that throw an exception when a PHP error occurs.
     *
     * @param int  $levels  A bit field of E_* constants for thrown errors
     * @param bool $replace Replace or amend the previous value
     */
    public function throwAt(int $levels, bool $replace = \false): int
    {
        $prev = $this->thrownErrors;
        $this->thrownErrors = ($levels | \E_RECOVERABLE_ERROR | \E_USER_ERROR) & ~\E_USER_DEPRECATED & ~\E_DEPRECATED;
        if (!$replace) {
            $this->thrownErrors |= $prev;
        }
        $this->reRegister($prev | $this->loggedErrors);
        return $prev;
    }
    /**
     * Sets the PHP error levels for which local variables are preserved.
     *
     * @param int  $levels  A bit field of E_* constants for scoped errors
     * @param bool $replace Replace or amend the previous value
     */
    public function scopeAt(int $levels, bool $replace = \false): int
    {
        $prev = $this->scopedErrors;
        $this->scopedErrors = $levels;
        if (!$replace) {
            $this->scopedErrors |= $prev;
        }
        return $prev;
    }
    /**
     * Sets the PHP error levels for which the stack trace is preserved.
     *
     * @param int  $levels  A bit field of E_* constants for traced errors
     * @param bool $replace Replace or amend the previous value
     */
    public function traceAt(int $levels, bool $replace = \false): int
    {
        $prev = $this->tracedErrors;
        $this->tracedErrors = $levels;
        if (!$replace) {
            $this->tracedErrors |= $prev;
        }
        return $prev;
    }
    /**
     * Sets the error levels where the @-operator is ignored.
     *
     * @param int  $levels  A bit field of E_* constants for screamed errors
     * @param bool $replace Replace or amend the previous value
     */
    public function screamAt(int $levels, bool $replace = \false): int
    {
        $prev = $this->screamedErrors;
        $this->screamedErrors = $levels;
        if (!$replace) {
            $this->screamedErrors |= $prev;
        }
        return $prev;
    }
    /**
     * Re-registers as a PHP error handler if levels changed.
     */
    private function reRegister(int $prev): void
    {
        if ($prev !== ($this->thrownErrors | $this->loggedErrors)) {
            $handler = set_error_handler(static fn() => null);
            $handler = \is_array($handler) ? $handler[0] : null;
            restore_error_handler();
            if ($handler === $this) {
                restore_error_handler();
                if ($this->isRoot) {
                    set_error_handler([$this, 'handleError'], $this->thrownErrors | $this->loggedErrors);
                } else {
                    set_error_handler([$this, 'handleError']);
                }
            }
        }
    }
    /**
     * Handles errors by filtering then logging them according to the configured bit fields.
     *
     * @return bool Returns false when no handling happens so that the PHP engine can handle the error itself
     *
     * @throws \ErrorException When $this->thrownErrors requests so
     *
     * @internal
     */
    public function handleError(int $type, string $message, string $file, int $line): bool
    {
        if (\E_WARNING === $type && '"' === $message[0] && str_contains($message, '" targeting switch is equivalent to "break')) {
            $type = \E_DEPRECATED;
        }
        // Level is the current error reporting level to manage silent error.
        $level = error_reporting();
        $silenced = 0 === ($level & $type);
        // Strong errors are not authorized to be silenced.
        $level |= \E_RECOVERABLE_ERROR | \E_USER_ERROR | \E_DEPRECATED | \E_USER_DEPRECATED;
        $log = $this->loggedErrors & $type;
        $throw = $this->thrownErrors & $type & $level;
        $type &= $level | $this->screamedErrors;
        // Never throw on warnings triggered by assert()
        if (\E_WARNING === $type && 'a' === $message[0] && 0 === strncmp($message, 'assert(): ', 10)) {
            $throw = 0;
        }
        if (!$type || !$log && !$throw) {
            return \false;
        }
        $logMessage = $this->levels[$type] . ': ' . $message;
        if (!$throw && !($type & $level)) {
            if (!isset(self::$silencedErrorCache[$id = $file . ':' . $line])) {
                $lightTrace = $this->tracedErrors & $type ? $this->cleanTrace(debug_backtrace(\DEBUG_BACKTRACE_IGNORE_ARGS, 5), $type, $file, $line, \false) : [];
                $errorAsException = new SilencedErrorContext($type, $file, $line, isset($lightTrace[1]) ? [$lightTrace[0]] : $lightTrace);
            } elseif (isset(self::$silencedErrorCache[$id][$message])) {
                $lightTrace = null;
                $errorAsException = self::$silencedErrorCache[$id][$message];
                ++$errorAsException->count;
            } else {
                $lightTrace = [];
                $errorAsException = null;
            }
            if (100 < ++self::$silencedErrorCount) {
                self::$silencedErrorCache = $lightTrace = [];
                self::$silencedErrorCount = 1;
            }
            if ($errorAsException) {
                self::$silencedErrorCache[$id][$message] = $errorAsException;
            }
            if (null === $lightTrace) {
                return \true;
            }
        } else {
            if (\PHP_VERSION_ID < 80303 && str_contains($message, '@anonymous')) {
                $backtrace = debug_backtrace(\false, 5);
                for ($i = 1; isset($backtrace[$i]); ++$i) {
                    if (isset($backtrace[$i]['function'], $backtrace[$i]['args'][0]) && ('trigger_error' === $backtrace[$i]['function'] || 'user_error' === $backtrace[$i]['function'])) {
                        if ($backtrace[$i]['args'][0] !== $message) {
                            $message = $backtrace[$i]['args'][0];
                        }
                        break;
                    }
                }
            }
            if (str_contains($message, "@anonymous\x00")) {
                $message = $this->parseAnonymousClass($message);
                $logMessage = $this->levels[$type] . ': ' . $message;
            }
            $errorAsException = new \ErrorException($logMessage, 0, $type, $file, $line);
            if ($throw || $this->tracedErrors & $type) {
                $backtrace = $errorAsException->getTrace();
                $backtrace = $this->cleanTrace($backtrace, $type, $file, $line, $throw);
                ($this->configureException)($errorAsException, $backtrace, $file, $line);
            } else {
                ($this->configureException)($errorAsException, []);
            }
        }
        if ($throw) {
            throw $errorAsException;
        }
        if ($this->isRecursive) {
            $log = 0;
        } else {
            try {
                $this->isRecursive = \true;
                $level = $type & $level ? $this->loggers[$type][1] : LogLevel::DEBUG;
                $this->loggers[$type][0]->log($level, $logMessage, $errorAsException ? ['exception' => $errorAsException] : []);
            } finally {
                $this->isRecursive = \false;
            }
        }
        return !$silenced && $type && $log;
    }
    /**
     * Handles an exception by logging then forwarding it to another handler.
     *
     * @internal
     */
    public function handleException(\Throwable $exception): void
    {
        $handlerException = null;
        if (!$exception instanceof FatalError) {
            self::$exitCode = 255;
            $type = ThrowableUtils::getSeverity($exception);
        } else {
            $type = $exception->getError()['type'];
        }
        if ($this->loggedErrors & $type) {
            if (str_contains($message = $exception->getMessage(), "@anonymous\x00")) {
                $message = $this->parseAnonymousClass($message);
            }
            if ($exception instanceof FatalError) {
                $message = 'Fatal ' . $message;
            } elseif ($exception instanceof \Error) {
                $message = 'Uncaught Error: ' . $message;
            } elseif ($exception instanceof \ErrorException) {
                $message = 'Uncaught ' . $message;
            } else {
                $message = 'Uncaught Exception: ' . $message;
            }
            try {
                $this->loggers[$type][0]->log($this->loggers[$type][1], $message, ['exception' => $exception]);
            } catch (\Throwable $handlerException) {
            }
        }
        $exception = $this->enhanceError($exception);
        $exceptionHandler = $this->exceptionHandler;
        $this->exceptionHandler = [$this, 'renderException'];
        if (null === $exceptionHandler || $exceptionHandler === $this->exceptionHandler) {
            $this->exceptionHandler = null;
        }
        try {
            if (null !== $exceptionHandler) {
                $exceptionHandler($exception);
                return;
            }
            $handlerException ??= $exception;
        } catch (\Throwable $handlerException) {
        }
        if ($exception === $handlerException && null === $this->exceptionHandler) {
            self::$reservedMemory = null;
            // Disable the fatal error handler
            throw $exception;
            // Give back $exception to the native handler
        }
        $loggedErrors = $this->loggedErrors;
        if ($exception === $handlerException) {
            $this->loggedErrors &= ~$type;
        }
        try {
            $this->handleException($handlerException);
        } finally {
            $this->loggedErrors = $loggedErrors;
        }
    }
    /**
     * Shutdown registered function for handling PHP fatal errors.
     *
     * @param array|null $error An array as returned by error_get_last()
     *
     * @internal
     */
    public static function handleFatalError(?array $error = null): void
    {
        if (null === self::$reservedMemory) {
            return;
        }
        $handler = self::$reservedMemory = null;
        $handlers = [];
        $previousHandler = null;
        $sameHandlerLimit = 10;
        while (!\is_array($handler) || !$handler[0] instanceof self) {
            $handler = set_exception_handler('is_int');
            restore_exception_handler();
            if (!$handler) {
                break;
            }
            restore_exception_handler();
            if ($handler !== $previousHandler) {
                array_unshift($handlers, $handler);
                $previousHandler = $handler;
            } elseif (0 === --$sameHandlerLimit) {
                $handler = null;
                break;
            }
        }
        foreach ($handlers as $h) {
            set_exception_handler($h);
        }
        if (!$handler) {
            if (null === $error && $exitCode = self::$exitCode) {
                register_shutdown_function('register_shutdown_function', function () use ($exitCode) {
                    exit($exitCode);
                });
            }
            return;
        }
        if ($handler !== $h) {
            $handler[0]->setExceptionHandler($h);
        }
        $handler = $handler[0];
        $handlers = [];
        if ($exit = null === $error) {
            $error = error_get_last();
        }
        if ($error && $error['type'] &= \E_PARSE | \E_ERROR | \E_CORE_ERROR | \E_COMPILE_ERROR) {
            // Let's not throw anymore but keep logging
            $handler->throwAt(0, \true);
            $trace = $error['backtrace'] ?? null;
            if (str_starts_with($error['message'], 'Allowed memory') || str_starts_with($error['message'], 'Out of memory')) {
                $fatalError = new OutOfMemoryError($handler->levels[$error['type']] . ': ' . $error['message'], 0, $error, 2, \false, $trace);
            } else {
                $fatalError = new FatalError($handler->levels[$error['type']] . ': ' . $error['message'], 0, $error, 2, \true, $trace);
            }
        } else {
            $fatalError = null;
        }
        try {
            if (null !== $fatalError) {
                self::$exitCode = 255;
                $handler->handleException($fatalError);
            }
        } catch (FatalError) {
            // Ignore this re-throw
        }
        if ($exit && $exitCode = self::$exitCode) {
            register_shutdown_function('register_shutdown_function', function () use ($exitCode) {
                exit($exitCode);
            });
        }
    }
    /**
     * Renders the given exception.
     *
     * As this method is mainly called during boot where nothing is yet available,
     * the output is always either HTML or CLI depending where PHP runs.
     */
    private function renderException(\Throwable $exception): void
    {
        $renderer = \in_array(\PHP_SAPI, ['cli', 'phpdbg', 'embed'], \true) ? new CliErrorRenderer() : new HtmlErrorRenderer($this->debug);
        $exception = $renderer->render($exception);
        if (!headers_sent()) {
            http_response_code($exception->getStatusCode());
            foreach ($exception->getHeaders() as $name => $value) {
                header($name . ': ' . $value, \false);
            }
        }
        echo $exception->getAsString();
    }
    public function enhanceError(\Throwable $exception): \Throwable
    {
        if ($exception instanceof OutOfMemoryError) {
            return $exception;
        }
        foreach ($this->getErrorEnhancers() as $errorEnhancer) {
            if ($e = $errorEnhancer->enhance($exception)) {
                return $e;
            }
        }
        return $exception;
    }
    /**
     * Override this method if you want to define more error enhancers.
     *
     * @return ErrorEnhancerInterface[]
     */
    protected function getErrorEnhancers(): iterable
    {
        return [new UndefinedFunctionErrorEnhancer(), new UndefinedMethodErrorEnhancer(), new ClassNotFoundErrorEnhancer()];
    }
    /**
     * Cleans the trace by removing function arguments and the frames added by the error handler and DebugClassLoader.
     */
    private function cleanTrace(array $backtrace, int $type, string &$file, int &$line, bool $throw): array
    {
        $lightTrace = $backtrace;
        for ($i = 0; isset($backtrace[$i]); ++$i) {
            if (isset($backtrace[$i]['file'], $backtrace[$i]['line']) && $backtrace[$i]['line'] === $line && $backtrace[$i]['file'] === $file) {
                $lightTrace = \array_slice($lightTrace, 1 + $i);
                break;
            }
        }
        if (\E_USER_DEPRECATED === $type) {
            for ($i = 0; isset($lightTrace[$i]); ++$i) {
                if (!isset($lightTrace[$i]['file'], $lightTrace[$i]['line'], $lightTrace[$i]['function'])) {
                    continue;
                }
                if (!isset($lightTrace[$i]['class']) && 'trigger_deprecation' === $lightTrace[$i]['function']) {
                    $file = $lightTrace[$i]['file'];
                    $line = $lightTrace[$i]['line'];
                    $lightTrace = \array_slice($lightTrace, 1 + $i);
                    break;
                }
            }
        }
        if (class_exists(DebugClassLoader::class, \false)) {
            for ($i = \count($lightTrace) - 2; 0 < $i; --$i) {
                if (DebugClassLoader::class === ($lightTrace[$i]['class'] ?? null)) {
                    array_splice($lightTrace, --$i, 2);
                }
            }
        }
        if (!($throw || $this->scopedErrors & $type)) {
            for ($i = 0; isset($lightTrace[$i]); ++$i) {
                unset($lightTrace[$i]['args'], $lightTrace[$i]['object']);
            }
        }
        return $lightTrace;
    }
    /**
     * Parse the error message by removing the anonymous class notation
     * and using the parent class instead if possible.
     */
    private function parseAnonymousClass(string $message): string
    {
        return preg_replace_callback('/[a-zA-Z_\x7f-\xff][\\\\a-zA-Z0-9_\x7f-\xff]*+@anonymous\x00.*?\.php(?:0x?|:[0-9]++\$)?[0-9a-fA-F]++/', static fn($m) => class_exists($m[0], \false) ? ((get_parent_class($m[0]) ?: key(class_implements($m[0]))) ?: 'class') . '@anonymous' : $m[0], $message);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\ErrorHandler;

use _ContaoManager\Symfony\Component\ErrorHandler\Exception\SilencedErrorContext;
/**
 * @internal
 */
class ThrowableUtils
{
    public static function getSeverity(SilencedErrorContext|\Throwable $throwable): int
    {
        if ($throwable instanceof \ErrorException || $throwable instanceof SilencedErrorContext) {
            return $throwable->getSeverity();
        }
        if ($throwable instanceof \ParseError) {
            return \E_PARSE;
        }
        if ($throwable instanceof \TypeError) {
            return \E_RECOVERABLE_ERROR;
        }
        return \E_ERROR;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\ErrorHandler\Error;

class OutOfMemoryError extends FatalError
{
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\ErrorHandler\Error;

class UndefinedMethodError extends \Error
{
    public function __construct(string $message, \Throwable $previous)
    {
        parent::__construct($message, $previous->getCode(), $previous->getPrevious());
        foreach (['file' => $previous->getFile(), 'line' => $previous->getLine(), 'trace' => $previous->getTrace()] as $property => $value) {
            $refl = new \ReflectionProperty(\Error::class, $property);
            $refl->setValue($this, $value);
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\ErrorHandler\Error;

class FatalError extends \Error
{
    private array $error;
    /**
     * @param array $error An array as returned by error_get_last()
     */
    public function __construct(string $message, int $code, array $error, ?int $traceOffset = null, bool $traceArgs = \true, ?array $trace = null)
    {
        parent::__construct($message, $code);
        $this->error = $error;
        if (null !== $trace) {
            if (!$traceArgs) {
                foreach ($trace as &$frame) {
                    unset($frame['args'], $frame['this'], $frame);
                }
            }
        } elseif (null !== $traceOffset) {
            if (\function_exists('xdebug_get_function_stack') && \in_array(\ini_get('xdebug.mode'), ['develop', \false], \true) && $trace = @xdebug_get_function_stack()) {
                if (0 < $traceOffset) {
                    array_splice($trace, -$traceOffset);
                }
                foreach ($trace as &$frame) {
                    if (!isset($frame['type'])) {
                        // XDebug pre 2.1.1 doesn't currently set the call type key http://bugs.xdebug.org/view.php?id=695
                        if (isset($frame['class'])) {
                            $frame['type'] = '::';
                        }
                    } elseif ('dynamic' === $frame['type']) {
                        $frame['type'] = '->';
                    } elseif ('static' === $frame['type']) {
                        $frame['type'] = '::';
                    }
                    // XDebug also has a different name for the parameters array
                    if (!$traceArgs) {
                        unset($frame['params'], $frame['args']);
                    } elseif (isset($frame['params']) && !isset($frame['args'])) {
                        $frame['args'] = $frame['params'];
                        unset($frame['params']);
                    }
                }
                unset($frame);
                $trace = array_reverse($trace);
            } else {
                $trace = [];
            }
        }
        foreach (['file' => $error['file'], 'line' => $error['line'], 'trace' => $trace] as $property => $value) {
            if (null !== $value) {
                $refl = new \ReflectionProperty(\Error::class, $property);
                $refl->setValue($this, $value);
            }
        }
    }
    public function getError(): array
    {
        return $this->error;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\ErrorHandler\Error;

class UndefinedFunctionError extends \Error
{
    public function __construct(string $message, \Throwable $previous)
    {
        parent::__construct($message, $previous->getCode(), $previous->getPrevious());
        foreach (['file' => $previous->getFile(), 'line' => $previous->getLine(), 'trace' => $previous->getTrace()] as $property => $value) {
            $refl = new \ReflectionProperty(\Error::class, $property);
            $refl->setValue($this, $value);
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\ErrorHandler\Error;

class ClassNotFoundError extends \Error
{
    public function __construct(string $message, \Throwable $previous)
    {
        parent::__construct($message, $previous->getCode(), $previous->getPrevious());
        foreach (['file' => $previous->getFile(), 'line' => $previous->getLine(), 'trace' => $previous->getTrace()] as $property => $value) {
            $refl = new \ReflectionProperty(\Error::class, $property);
            $refl->setValue($this, $value);
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\ErrorHandler\Exception;

use _ContaoManager\Symfony\Component\HttpFoundation\Exception\RequestExceptionInterface;
use _ContaoManager\Symfony\Component\HttpFoundation\Response;
use _ContaoManager\Symfony\Component\HttpKernel\Exception\HttpExceptionInterface;
use _ContaoManager\Symfony\Component\VarDumper\Caster\Caster;
use _ContaoManager\Symfony\Component\VarDumper\Cloner\Data;
use _ContaoManager\Symfony\Component\VarDumper\Cloner\Stub;
use _ContaoManager\Symfony\Component\VarDumper\Cloner\VarCloner;
/**
 * FlattenException wraps a PHP Error or Exception to be able to serialize it.
 *
 * Basically, this class removes all objects from the trace.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class FlattenException
{
    private string $message;
    private string|int $code;
    private ?self $previous = null;
    private array $trace;
    private string $traceAsString;
    private string $class;
    private int $statusCode;
    private string $statusText;
    private array $headers;
    private string $file;
    private int $line;
    private ?string $asString = null;
    private Data $dataRepresentation;
    public static function create(\Exception $exception, ?int $statusCode = null, array $headers = []): static
    {
        return static::createFromThrowable($exception, $statusCode, $headers);
    }
    public static function createFromThrowable(\Throwable $exception, ?int $statusCode = null, array $headers = []): static
    {
        $e = new static();
        $e->setMessage($exception->getMessage());
        $e->setCode($exception->getCode());
        if ($exception instanceof HttpExceptionInterface) {
            $statusCode = $exception->getStatusCode();
            $headers = array_merge($headers, $exception->getHeaders());
        } elseif ($exception instanceof RequestExceptionInterface) {
            $statusCode = 400;
        }
        $statusCode ??= 500;
        if (class_exists(Response::class) && isset(Response::$statusTexts[$statusCode])) {
            $statusText = Response::$statusTexts[$statusCode];
        } else {
            $statusText = 'Whoops, looks like something went wrong.';
        }
        $e->setStatusText($statusText);
        $e->setStatusCode($statusCode);
        $e->setHeaders($headers);
        $e->setTraceFromThrowable($exception);
        $e->setClass(get_debug_type($exception));
        $e->setFile($exception->getFile());
        $e->setLine($exception->getLine());
        $previous = $exception->getPrevious();
        if ($previous instanceof \Throwable) {
            $e->setPrevious(static::createFromThrowable($previous));
        }
        return $e;
    }
    public static function createWithDataRepresentation(\Throwable $throwable, ?int $statusCode = null, array $headers = [], ?VarCloner $cloner = null): static
    {
        $e = static::createFromThrowable($throwable, $statusCode, $headers);
        static $defaultCloner;
        if (!$cloner ??= $defaultCloner) {
            $cloner = $defaultCloner = new VarCloner();
            $cloner->addCasters([\Throwable::class => function (\Throwable $e, array $a, Stub $s, bool $isNested): array {
                if (!$isNested) {
                    unset($a[Caster::PREFIX_PROTECTED . 'message']);
                    unset($a[Caster::PREFIX_PROTECTED . 'code']);
                    unset($a[Caster::PREFIX_PROTECTED . 'file']);
                    unset($a[Caster::PREFIX_PROTECTED . 'line']);
                    unset($a["\x00Error\x00trace"], $a["\x00Exception\x00trace"]);
                    unset($a["\x00Error\x00previous"], $a["\x00Exception\x00previous"]);
                }
                return $a;
            }]);
        }
        return $e->setDataRepresentation($cloner->cloneVar($throwable));
    }
    public function toArray(): array
    {
        $exceptions = [];
        foreach (array_merge([$this], $this->getAllPrevious()) as $exception) {
            $exceptions[] = ['message' => $exception->getMessage(), 'class' => $exception->getClass(), 'trace' => $exception->getTrace(), 'data' => $exception->getDataRepresentation()];
        }
        return $exceptions;
    }
    public function getStatusCode(): int
    {
        return $this->statusCode;
    }
    /**
     * @return $this
     */
    public function setStatusCode(int $code): static
    {
        $this->statusCode = $code;
        return $this;
    }
    public function getHeaders(): array
    {
        return $this->headers;
    }
    /**
     * @return $this
     */
    public function setHeaders(array $headers): static
    {
        $this->headers = $headers;
        return $this;
    }
    public function getClass(): string
    {
        return $this->class;
    }
    /**
     * @return $this
     */
    public function setClass(string $class): static
    {
        $this->class = str_contains($class, "@anonymous\x00") ? ((get_parent_class($class) ?: key(class_implements($class))) ?: 'class') . '@anonymous' : $class;
        return $this;
    }
    public function getFile(): string
    {
        return $this->file;
    }
    /**
     * @return $this
     */
    public function setFile(string $file): static
    {
        $this->file = $file;
        return $this;
    }
    public function getLine(): int
    {
        return $this->line;
    }
    /**
     * @return $this
     */
    public function setLine(int $line): static
    {
        $this->line = $line;
        return $this;
    }
    public function getStatusText(): string
    {
        return $this->statusText;
    }
    /**
     * @return $this
     */
    public function setStatusText(string $statusText): static
    {
        $this->statusText = $statusText;
        return $this;
    }
    public function getMessage(): string
    {
        return $this->message;
    }
    /**
     * @return $this
     */
    public function setMessage(string $message): static
    {
        if (str_contains($message, "@anonymous\x00")) {
            $message = preg_replace_callback('/[a-zA-Z_\x7f-\xff][\\\\a-zA-Z0-9_\x7f-\xff]*+@anonymous\x00.*?\.php(?:0x?|:[0-9]++\$)?[0-9a-fA-F]++/', fn($m) => class_exists($m[0], \false) ? ((get_parent_class($m[0]) ?: key(class_implements($m[0]))) ?: 'class') . '@anonymous' : $m[0], $message);
        }
        $this->message = $message;
        return $this;
    }
    /**
     * @return int|string int most of the time (might be a string with PDOException)
     */
    public function getCode(): int|string
    {
        return $this->code;
    }
    /**
     * @return $this
     */
    public function setCode(int|string $code): static
    {
        $this->code = $code;
        return $this;
    }
    public function getPrevious(): ?self
    {
        return $this->previous;
    }
    /**
     * @return $this
     */
    public function setPrevious(?self $previous): static
    {
        $this->previous = $previous;
        return $this;
    }
    /**
     * @return self[]
     */
    public function getAllPrevious(): array
    {
        $exceptions = [];
        $e = $this;
        while ($e = $e->getPrevious()) {
            $exceptions[] = $e;
        }
        return $exceptions;
    }
    public function getTrace(): array
    {
        return $this->trace;
    }
    /**
     * @return $this
     */
    public function setTraceFromThrowable(\Throwable $throwable): static
    {
        $this->traceAsString = $throwable->getTraceAsString();
        return $this->setTrace($throwable->getTrace(), $throwable->getFile(), $throwable->getLine());
    }
    /**
     * @return $this
     */
    public function setTrace(array $trace, ?string $file, ?int $line): static
    {
        $this->trace = [];
        $this->trace[] = ['namespace' => '', 'short_class' => '', 'class' => '', 'type' => '', 'function' => '', 'file' => $file, 'line' => $line, 'args' => []];
        foreach ($trace as $entry) {
            $class = '';
            $namespace = '';
            if (isset($entry['class'])) {
                $parts = explode('\\', $entry['class']);
                $class = array_pop($parts);
                $namespace = implode('\\', $parts);
            }
            $this->trace[] = ['namespace' => $namespace, 'short_class' => $class, 'class' => $entry['class'] ?? '', 'type' => $entry['type'] ?? '', 'function' => $entry['function'] ?? null, 'file' => $entry['file'] ?? null, 'line' => $entry['line'] ?? null, 'args' => isset($entry['args']) ? $this->flattenArgs($entry['args']) : []];
        }
        return $this;
    }
    public function getDataRepresentation(): ?Data
    {
        return $this->dataRepresentation ?? null;
    }
    /**
     * @return $this
     */
    public function setDataRepresentation(Data $data): static
    {
        $this->dataRepresentation = $data;
        return $this;
    }
    private function flattenArgs(array $args, int $level = 0, int &$count = 0): array
    {
        $result = [];
        foreach ($args as $key => $value) {
            if (++$count > 10000.0) {
                return ['array', '*SKIPPED over 10000 entries*'];
            }
            if ($value instanceof \__PHP_Incomplete_Class) {
                $result[$key] = ['incomplete-object', $this->getClassNameFromIncomplete($value)];
            } elseif (\is_object($value)) {
                $result[$key] = ['object', get_debug_type($value)];
            } elseif (\is_array($value)) {
                if ($level > 10) {
                    $result[$key] = ['array', '*DEEP NESTED ARRAY*'];
                } else {
                    $result[$key] = ['array', $this->flattenArgs($value, $level + 1, $count)];
                }
            } elseif (null === $value) {
                $result[$key] = ['null', null];
            } elseif (\is_bool($value)) {
                $result[$key] = ['boolean', $value];
            } elseif (\is_int($value)) {
                $result[$key] = ['integer', $value];
            } elseif (\is_float($value)) {
                $result[$key] = ['float', $value];
            } elseif (\is_resource($value)) {
                $result[$key] = ['resource', get_resource_type($value)];
            } else {
                $result[$key] = ['string', (string) $value];
            }
        }
        return $result;
    }
    private function getClassNameFromIncomplete(\__PHP_Incomplete_Class $value): string
    {
        $array = new \ArrayObject($value);
        return $array['__PHP_Incomplete_Class_Name'];
    }
    public function getTraceAsString(): string
    {
        return $this->traceAsString;
    }
    /**
     * @return $this
     */
    public function setAsString(?string $asString): static
    {
        $this->asString = $asString;
        return $this;
    }
    public function getAsString(): string
    {
        if (null !== $this->asString) {
            return $this->asString;
        }
        $message = '';
        $next = \false;
        foreach (array_reverse(array_merge([$this], $this->getAllPrevious())) as $exception) {
            if ($next) {
                $message .= 'Next ';
            } else {
                $next = \true;
            }
            $message .= $exception->getClass();
            if ('' != $exception->getMessage()) {
                $message .= ': ' . $exception->getMessage();
            }
            $message .= ' in ' . $exception->getFile() . ':' . $exception->getLine() . "\nStack trace:\n" . $exception->getTraceAsString() . "\n\n";
        }
        return rtrim($message);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\ErrorHandler\Exception;

/**
 * Data Object that represents a Silenced Error.
 *
 * @author Grégoire Pineau <lyrixx@lyrixx.info>
 */
class SilencedErrorContext implements \JsonSerializable
{
    public $count = 1;
    private int $severity;
    private string $file;
    private int $line;
    private array $trace;
    public function __construct(int $severity, string $file, int $line, array $trace = [], int $count = 1)
    {
        $this->severity = $severity;
        $this->file = $file;
        $this->line = $line;
        $this->trace = $trace;
        $this->count = $count;
    }
    public function getSeverity(): int
    {
        return $this->severity;
    }
    public function getFile(): string
    {
        return $this->file;
    }
    public function getLine(): int
    {
        return $this->line;
    }
    public function getTrace(): array
    {
        return $this->trace;
    }
    public function jsonSerialize(): array
    {
        return ['severity' => $this->severity, 'file' => $this->file, 'line' => $this->line, 'trace' => $this->trace, 'count' => $this->count];
    }
}
{
    "name": "symfony\/error-handler",
    "type": "library",
    "description": "Provides tools to manage errors and ease debugging PHP code",
    "keywords": [],
    "homepage": "https:\/\/symfony.com",
    "license": "MIT",
    "authors": [
        {
            "name": "Fabien Potencier",
            "email": "fabien@symfony.com"
        },
        {
            "name": "Symfony Community",
            "homepage": "https:\/\/symfony.com\/contributors"
        }
    ],
    "require": {
        "php": ">=8.1",
        "psr\/log": "^1|^2|^3",
        "symfony\/var-dumper": "^5.4|^6.0|^7.0"
    },
    "require-dev": {
        "symfony\/http-kernel": "^6.4|^7.0",
        "symfony\/serializer": "^5.4|^6.0|^7.0",
        "symfony\/deprecation-contracts": "^2.5|^3"
    },
    "conflict": {
        "symfony\/deprecation-contracts": "<2.5",
        "symfony\/http-kernel": "<6.4"
    },
    "autoload": {
        "psr-4": {
            "_ContaoManager\\Symfony\\Component\\ErrorHandler\\": ""
        },
        "exclude-from-classmap": [
            "\/Tests\/"
        ]
    },
    "bin": [
        "Resources\/bin\/patch-type-declarations"
    ],
    "minimum-stability": "dev"
}<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Contracts\Cache;

use _ContaoManager\Psr\Cache\CacheItemInterface;
/**
 * Computes and returns the cached value of an item.
 *
 * @author Nicolas Grekas <p@tchwork.com>
 *
 * @template T
 */
interface CallbackInterface
{
    /**
     * @param CacheItemInterface|ItemInterface $item  The item to compute the value for
     * @param bool                             &$save Should be set to false when the value should not be saved in the pool
     *
     * @return T The computed value for the passed item
     */
    public function __invoke(CacheItemInterface $item, bool &$save): mixed;
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Contracts\Cache;

use _ContaoManager\Psr\Cache\CacheException;
use _ContaoManager\Psr\Cache\CacheItemInterface;
use _ContaoManager\Psr\Cache\InvalidArgumentException;
/**
 * Augments PSR-6's CacheItemInterface with support for tags and metadata.
 *
 * @author Nicolas Grekas <p@tchwork.com>
 */
interface ItemInterface extends CacheItemInterface
{
    /**
     * References the Unix timestamp stating when the item will expire.
     */
    public const METADATA_EXPIRY = 'expiry';
    /**
     * References the time the item took to be created, in milliseconds.
     */
    public const METADATA_CTIME = 'ctime';
    /**
     * References the list of tags that were assigned to the item, as string[].
     */
    public const METADATA_TAGS = 'tags';
    /**
     * Reserved characters that cannot be used in a key or tag.
     */
    public const RESERVED_CHARACTERS = '{}()/\@:';
    /**
     * Adds a tag to a cache item.
     *
     * Tags are strings that follow the same validation rules as keys.
     *
     * @param string|string[] $tags A tag or array of tags
     *
     * @return $this
     *
     * @throws InvalidArgumentException When $tag is not valid
     * @throws CacheException           When the item comes from a pool that is not tag-aware
     */
    public function tag(string|iterable $tags): static;
    /**
     * Returns a list of metadata info that were saved alongside with the cached value.
     *
     * See ItemInterface::METADATA_* consts for keys potentially found in the returned array.
     */
    public function getMetadata(): array;
}
Copyright (c) 2018-present Fabien Potencier

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is furnished
to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
CHANGELOG
=========

The changelog is maintained for all Symfony contracts at the following URL:
https://github.com/symfony/contracts/blob/main/CHANGELOG.md
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Contracts\Cache;

use _ContaoManager\Psr\Cache\CacheItemInterface;
use _ContaoManager\Psr\Cache\InvalidArgumentException;
/**
 * Covers most simple to advanced caching needs.
 *
 * @author Nicolas Grekas <p@tchwork.com>
 */
interface CacheInterface
{
    /**
     * Fetches a value from the pool or computes it if not found.
     *
     * On cache misses, a callback is called that should return the missing value.
     * This callback is given a PSR-6 CacheItemInterface instance corresponding to the
     * requested key, that could be used e.g. for expiration control. It could also
     * be an ItemInterface instance when its additional features are needed.
     *
     * @template T
     *
     * @param string $key The key of the item to retrieve from the cache
     * @param (callable(CacheItemInterface,bool):T)|(callable(ItemInterface,bool):T)|CallbackInterface<T> $callback
     * @param float|null $beta      A float that, as it grows, controls the likeliness of triggering
     *                              early expiration. 0 disables it, INF forces immediate expiration.
     *                              The default (or providing null) is implementation dependent but should
     *                              typically be 1.0, which should provide optimal stampede protection.
     *                              See https://en.wikipedia.org/wiki/Cache_stampede#Probabilistic_early_expiration
     * @param array      &$metadata The metadata of the cached item {@see ItemInterface::getMetadata()}
     *
     * @return T
     *
     * @throws InvalidArgumentException When $key is not valid or when $beta is negative
     */
    public function get(string $key, callable $callback, ?float $beta = null, ?array &$metadata = null): mixed;
    /**
     * Removes an item from the pool.
     *
     * @param string $key The key to delete
     *
     * @return bool True if the item was successfully removed, false if there was any error
     *
     * @throws InvalidArgumentException When $key is not valid
     */
    public function delete(string $key): bool;
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Contracts\Cache;

use _ContaoManager\Psr\Cache\InvalidArgumentException;
/**
 * Enables namespace-based invalidation by prefixing keys with backend-native namespace separators.
 *
 * Note that calling `withSubNamespace()` MUST NOT mutate the pool, but return a new instance instead.
 *
 * When tags are used, they MUST ignore sub-namespaces.
 *
 * @author Nicolas Grekas <p@tchwork.com>
 */
interface NamespacedPoolInterface
{
    /**
     * @throws InvalidArgumentException If the namespace contains characters found in ItemInterface's RESERVED_CHARACTERS
     */
    public function withSubNamespace(string $namespace): static;
}
Symfony Cache Contracts
=======================

A set of abstractions extracted out of the Symfony components.

Can be used to build on semantics that the Symfony components proved useful and
that already have battle tested implementations.

See https://github.com/symfony/contracts/blob/main/README.md for more information.
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Contracts\Cache;

use _ContaoManager\Psr\Cache\CacheItemPoolInterface;
use _ContaoManager\Psr\Cache\InvalidArgumentException;
use _ContaoManager\Psr\Log\LoggerInterface;
// Help opcache.preload discover always-needed symbols
class_exists(InvalidArgumentException::class);
/**
 * An implementation of CacheInterface for PSR-6 CacheItemPoolInterface classes.
 *
 * @author Nicolas Grekas <p@tchwork.com>
 */
trait CacheTrait
{
    public function get(string $key, callable $callback, ?float $beta = null, ?array &$metadata = null): mixed
    {
        return $this->doGet($this, $key, $callback, $beta, $metadata);
    }
    public function delete(string $key): bool
    {
        return $this->deleteItem($key);
    }
    private function doGet(CacheItemPoolInterface $pool, string $key, callable $callback, ?float $beta, ?array &$metadata = null, ?LoggerInterface $logger = null): mixed
    {
        if (0 > $beta ??= 1.0) {
            throw new class(\sprintf('Argument "$beta" provided to "%s::get()" must be a positive number, %f given.', static::class, $beta)) extends \InvalidArgumentException implements InvalidArgumentException
            {
            };
        }
        $item = $pool->getItem($key);
        $recompute = !$item->isHit() || \INF === $beta;
        $metadata = $item instanceof ItemInterface ? $item->getMetadata() : [];
        if (!$recompute && $metadata) {
            $expiry = $metadata[ItemInterface::METADATA_EXPIRY] ?? \false;
            $ctime = $metadata[ItemInterface::METADATA_CTIME] ?? \false;
            if ($recompute = $ctime && $expiry && $expiry <= ($now = microtime(\true)) - $ctime / 1000 * $beta * log(random_int(1, \PHP_INT_MAX) / \PHP_INT_MAX)) {
                // force applying defaultLifetime to expiry
                $item->expiresAt(null);
                $logger?->info('Item "{key}" elected for early recomputation {delta}s before its expiration', ['key' => $key, 'delta' => \sprintf('%.1f', $expiry - $now)]);
            }
        }
        if ($recompute) {
            $save = \true;
            $item->set($callback($item, $save));
            if ($save) {
                $pool->save($item);
            }
        }
        return $item->get();
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Contracts\Cache;

use _ContaoManager\Psr\Cache\InvalidArgumentException;
/**
 * Allows invalidating cached items using tags.
 *
 * @author Nicolas Grekas <p@tchwork.com>
 */
interface TagAwareCacheInterface extends CacheInterface
{
    /**
     * Invalidates cached items using tags.
     *
     * When implemented on a PSR-6 pool, invalidation should not apply
     * to deferred items. Instead, they should be committed as usual.
     * This allows replacing old tagged values by new ones without
     * race conditions.
     *
     * @param string[] $tags An array of tags to invalidate
     *
     * @return bool True on success
     *
     * @throws InvalidArgumentException When $tags is not valid
     */
    public function invalidateTags(array $tags): bool;
}
{
    "name": "symfony\/cache-contracts",
    "type": "library",
    "description": "Generic abstractions related to caching",
    "keywords": [
        "abstractions",
        "contracts",
        "decoupling",
        "interfaces",
        "interoperability",
        "standards"
    ],
    "homepage": "https:\/\/symfony.com",
    "license": "MIT",
    "authors": [
        {
            "name": "Nicolas Grekas",
            "email": "p@tchwork.com"
        },
        {
            "name": "Symfony Community",
            "homepage": "https:\/\/symfony.com\/contributors"
        }
    ],
    "require": {
        "php": ">=8.1",
        "psr\/cache": "^3.0"
    },
    "autoload": {
        "psr-4": {
            "_ContaoManager\\Symfony\\Contracts\\Cache\\": ""
        }
    },
    "minimum-stability": "dev",
    "extra": {
        "branch-alias": {
            "dev-main": "3.6-dev"
        },
        "thanks": {
            "name": "symfony\/contracts",
            "url": "https:\/\/github.com\/symfony\/contracts"
        }
    }
}<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\DependencyInjection;

use _ContaoManager\Symfony\Component\DependencyInjection\Exception\EnvNotFoundException;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\ParameterCircularReferenceException;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\RuntimeException;
/**
 * @author Nicolas Grekas <p@tchwork.com>
 */
class EnvVarProcessor implements EnvVarProcessorInterface
{
    private ContainerInterface $container;
    /** @var \Traversable<EnvVarLoaderInterface> */
    private \Traversable $loaders;
    private array $loadedVars = [];
    /**
     * @param \Traversable<EnvVarLoaderInterface>|null $loaders
     */
    public function __construct(ContainerInterface $container, ?\Traversable $loaders = null)
    {
        $this->container = $container;
        $this->loaders = $loaders ?? new \ArrayIterator();
    }
    public static function getProvidedTypes(): array
    {
        return ['base64' => 'string', 'bool' => 'bool', 'not' => 'bool', 'const' => 'bool|int|float|string|array', 'csv' => 'array', 'file' => 'string', 'float' => 'float', 'int' => 'int', 'json' => 'array', 'key' => 'bool|int|float|string|array', 'url' => 'array', 'query_string' => 'array', 'resolve' => 'string', 'default' => 'bool|int|float|string|array', 'string' => 'string', 'trim' => 'string', 'require' => 'bool|int|float|string|array', 'enum' => \BackedEnum::class, 'shuffle' => 'array', 'defined' => 'bool'];
    }
    public function getEnv(string $prefix, string $name, \Closure $getEnv): mixed
    {
        $i = strpos($name, ':');
        if ('key' === $prefix) {
            if (\false === $i) {
                throw new RuntimeException(\sprintf('Invalid env "key:%s": a key specifier should be provided.', $name));
            }
            $next = substr($name, $i + 1);
            $key = substr($name, 0, $i);
            $array = $getEnv($next);
            if (!\is_array($array)) {
                throw new RuntimeException(\sprintf('Resolved value of "%s" did not result in an array value.', $next));
            }
            if (!isset($array[$key]) && !\array_key_exists($key, $array)) {
                throw new EnvNotFoundException(\sprintf('Key "%s" not found in %s (resolved from "%s").', $key, json_encode($array), $next));
            }
            return $array[$key];
        }
        if ('enum' === $prefix) {
            if (\false === $i) {
                throw new RuntimeException(\sprintf('Invalid env "enum:%s": a "%s" class-string should be provided.', $name, \BackedEnum::class));
            }
            $next = substr($name, $i + 1);
            $backedEnumClassName = substr($name, 0, $i);
            $backedEnumValue = $getEnv($next);
            if (!\is_string($backedEnumValue) && !\is_int($backedEnumValue)) {
                throw new RuntimeException(\sprintf('Resolved value of "%s" did not result in a string or int value.', $next));
            }
            if (!is_subclass_of($backedEnumClassName, \BackedEnum::class)) {
                throw new RuntimeException(\sprintf('"%s" is not a "%s".', $backedEnumClassName, \BackedEnum::class));
            }
            return $backedEnumClassName::tryFrom($backedEnumValue) ?? throw new RuntimeException(\sprintf('Enum value "%s" is not backed by "%s".', $backedEnumValue, $backedEnumClassName));
        }
        if ('defined' === $prefix) {
            try {
                return '' !== ($getEnv($name) ?? '');
            } catch (EnvNotFoundException) {
                return \false;
            }
        }
        if ('default' === $prefix) {
            if (\false === $i) {
                throw new RuntimeException(\sprintf('Invalid env "default:%s": a fallback parameter should be provided.', $name));
            }
            $next = substr($name, $i + 1);
            $default = substr($name, 0, $i);
            if ('' !== $default && !$this->container->hasParameter($default)) {
                throw new RuntimeException(\sprintf('Invalid env fallback in "default:%s": parameter "%s" not found.', $name, $default));
            }
            try {
                $env = $getEnv($next);
                if ('' !== $env && null !== $env) {
                    return $env;
                }
            } catch (EnvNotFoundException) {
                // no-op
            }
            return '' === $default ? null : $this->container->getParameter($default);
        }
        if ('file' === $prefix || 'require' === $prefix) {
            if (!\is_scalar($file = $getEnv($name))) {
                throw new RuntimeException(\sprintf('Invalid file name: env var "%s" is non-scalar.', $name));
            }
            if (!is_file($file)) {
                throw new EnvNotFoundException(\sprintf('File "%s" not found (resolved from "%s").', $file, $name));
            }
            if ('file' === $prefix) {
                return file_get_contents($file);
            } else {
                return require $file;
            }
        }
        $returnNull = \false;
        if ('' === $prefix) {
            if ('' === $name) {
                return null;
            }
            $returnNull = \true;
            $prefix = 'string';
        }
        if (\false !== $i || 'string' !== $prefix) {
            $env = $getEnv($name);
        } elseif ('' === ($env = $_ENV[$name] ?? (str_starts_with($name, 'HTTP_') ? null : $_SERVER[$name] ?? null)) || \false !== $env && \false === $env ??= getenv($name) ?? \false) {
            foreach ($this->loadedVars as $i => $vars) {
                if (\false === $env = $vars[$name] ?? $env) {
                    continue;
                }
                if ($env instanceof \Stringable) {
                    $this->loadedVars[$i][$name] = $env = (string) $env;
                }
                if ('' !== ($env ?? '')) {
                    break;
                }
            }
            if (\false === $env || '' === $env) {
                $loaders = $this->loaders;
                $this->loaders = new \ArrayIterator();
                try {
                    $i = 0;
                    $ended = \true;
                    $count = $loaders instanceof \Countable ? $loaders->count() : 0;
                    foreach ($loaders as $loader) {
                        if (\count($this->loadedVars) > $i++) {
                            continue;
                        }
                        $this->loadedVars[] = $vars = $loader->loadEnvVars();
                        if (\false === $env = $vars[$name] ?? $env) {
                            continue;
                        }
                        if ($env instanceof \Stringable) {
                            $this->loadedVars[array_key_last($this->loadedVars)][$name] = $env = (string) $env;
                        }
                        if ('' !== ($env ?? '')) {
                            $ended = \false;
                            break;
                        }
                    }
                    if ($ended || $count === $i) {
                        $loaders = $this->loaders;
                    }
                } catch (ParameterCircularReferenceException) {
                    // skip loaders that need an env var that is not defined
                } finally {
                    $this->loaders = $loaders;
                }
            }
            if (\false === $env) {
                if (!$this->container->hasParameter("env({$name})")) {
                    throw new EnvNotFoundException(\sprintf('Environment variable not found: "%s".', $name));
                }
                $env = $this->container->getParameter("env({$name})");
            }
        }
        if (null === $env) {
            if ($returnNull) {
                return null;
            }
            if (!isset($this->getProvidedTypes()[$prefix])) {
                throw new RuntimeException(\sprintf('Unsupported env var prefix "%s".', $prefix));
            }
            if (!\in_array($prefix, ['string', 'bool', 'not', 'int', 'float'], \true)) {
                return null;
            }
        }
        if ('shuffle' === $prefix) {
            \is_array($env) ? shuffle($env) : throw new RuntimeException(\sprintf('Env var "%s" cannot be shuffled, expected array, got "%s".', $name, get_debug_type($env)));
            return $env;
        }
        if (null !== $env && !\is_scalar($env)) {
            throw new RuntimeException(\sprintf('Non-scalar env var "%s" cannot be cast to "%s".', $name, $prefix));
        }
        if ('string' === $prefix) {
            return (string) $env;
        }
        if (\in_array($prefix, ['bool', 'not'], \true)) {
            $env = (bool) ((filter_var($env, \FILTER_VALIDATE_BOOL) ?: filter_var($env, \FILTER_VALIDATE_INT)) ?: filter_var($env, \FILTER_VALIDATE_FLOAT));
            return 'not' === $prefix xor $env;
        }
        if ('int' === $prefix) {
            if (null !== $env && \false === $env = filter_var($env, \FILTER_VALIDATE_INT) ?: filter_var($env, \FILTER_VALIDATE_FLOAT)) {
                throw new RuntimeException(\sprintf('Non-numeric env var "%s" cannot be cast to int.', $name));
            }
            return (int) $env;
        }
        if ('float' === $prefix) {
            if (null !== $env && \false === $env = filter_var($env, \FILTER_VALIDATE_FLOAT)) {
                throw new RuntimeException(\sprintf('Non-numeric env var "%s" cannot be cast to float.', $name));
            }
            return (float) $env;
        }
        if ('const' === $prefix) {
            if (!\defined($env)) {
                throw new RuntimeException(\sprintf('Env var "%s" maps to undefined constant "%s".', $name, $env));
            }
            return \constant($env);
        }
        if ('base64' === $prefix) {
            return base64_decode(strtr($env, '-_', '+/'));
        }
        if ('json' === $prefix) {
            $env = json_decode($env, \true);
            if (\JSON_ERROR_NONE !== json_last_error()) {
                throw new RuntimeException(\sprintf('Invalid JSON in env var "%s": ', $name) . json_last_error_msg());
            }
            if (null !== $env && !\is_array($env)) {
                throw new RuntimeException(\sprintf('Invalid JSON env var "%s": array or null expected, "%s" given.', $name, get_debug_type($env)));
            }
            return $env;
        }
        if ('url' === $prefix) {
            $params = parse_url($env);
            if (\false === $params) {
                throw new RuntimeException(\sprintf('Invalid URL in env var "%s".', $name));
            }
            if (!isset($params['scheme'], $params['host'])) {
                throw new RuntimeException(\sprintf('Invalid URL in env var "%s": scheme and host expected.', $name));
            }
            $params += ['port' => null, 'user' => null, 'pass' => null, 'path' => null, 'query' => null, 'fragment' => null];
            $params['user'] = null !== $params['user'] ? rawurldecode($params['user']) : null;
            $params['pass'] = null !== $params['pass'] ? rawurldecode($params['pass']) : null;
            // remove the '/' separator
            $params['path'] = '/' === ($params['path'] ?? '/') ? '' : substr($params['path'], 1);
            return $params;
        }
        if ('query_string' === $prefix) {
            $queryString = parse_url($env, \PHP_URL_QUERY) ?: (parse_url($env, \PHP_URL_SCHEME) ? '' : $env);
            parse_str($queryString, $result);
            return $result;
        }
        if ('resolve' === $prefix) {
            return preg_replace_callback('/%%|%([^%\s]+)%/', function ($match) use ($name, $getEnv) {
                if (!isset($match[1])) {
                    return '%';
                }
                if (str_starts_with($match[1], 'env(') && str_ends_with($match[1], ')') && 'env()' !== $match[1]) {
                    $value = $getEnv(substr($match[1], 4, -1));
                } else {
                    $value = $this->container->getParameter($match[1]);
                }
                if (!\is_scalar($value)) {
                    throw new RuntimeException(\sprintf('Parameter "%s" found when resolving env var "%s" must be scalar, "%s" given.', $match[1], $name, get_debug_type($value)));
                }
                return $value;
            }, $env);
        }
        if ('csv' === $prefix) {
            return '' === $env ? [] : str_getcsv($env, ',', '"', '');
        }
        if ('trim' === $prefix) {
            return trim($env);
        }
        throw new RuntimeException(\sprintf('Unsupported env var prefix "%s" for env name "%s".', $prefix, $name));
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\DependencyInjection;

trigger_deprecation('symfony/dependency-injection', '6.4', '"%s" is deprecated, use dependency injection instead.', ContainerAwareTrait::class);
/**
 * ContainerAware trait.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 *
 * @deprecated since Symfony 6.4, use dependency injection instead
 */
trait ContainerAwareTrait
{
    /**
     * @var ContainerInterface|null
     */
    protected $container;
    /**
     * @return void
     */
    public function setContainer(?ContainerInterface $container = null)
    {
        if (1 > \func_num_args()) {
            trigger_deprecation('symfony/dependency-injection', '6.2', 'Calling "%s::%s()" without any arguments is deprecated, pass null explicitly instead.', __CLASS__, __FUNCTION__);
        }
        $this->container = $container;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\DependencyInjection;

use _ContaoManager\Symfony\Component\DependencyInjection\Exception\LogicException;
use _ContaoManager\Symfony\Component\ExpressionLanguage\ExpressionFunction;
use _ContaoManager\Symfony\Component\ExpressionLanguage\ExpressionFunctionProviderInterface;
/**
 * Define some ExpressionLanguage functions.
 *
 * To get a service, use service('request').
 * To get a parameter, use parameter('kernel.debug').
 * To get an env variable, use env('SOME_VARIABLE').
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class ExpressionLanguageProvider implements ExpressionFunctionProviderInterface
{
    private ?\Closure $serviceCompiler;
    private ?\Closure $getEnv;
    public function __construct(?callable $serviceCompiler = null, ?\Closure $getEnv = null)
    {
        $this->serviceCompiler = null === $serviceCompiler ? null : $serviceCompiler(...);
        $this->getEnv = $getEnv;
    }
    public function getFunctions(): array
    {
        return [new ExpressionFunction('service', $this->serviceCompiler ?? fn($arg) => \sprintf('$container->get(%s)', $arg), fn(array $variables, $value) => $variables['container']->get($value)), new ExpressionFunction('parameter', fn($arg) => \sprintf('$container->getParameter(%s)', $arg), fn(array $variables, $value) => $variables['container']->getParameter($value)), new ExpressionFunction('env', fn($arg) => \sprintf('$container->getEnv(%s)', $arg), function (array $variables, $value) {
            if (!$this->getEnv) {
                throw new LogicException('You need to pass a getEnv closure to the expression language provider to use the "env" function.');
            }
            return ($this->getEnv)($value);
        }), new ExpressionFunction('arg', fn($arg) => \sprintf('$args?->get(%s)', $arg), fn(array $variables, $value) => $variables['args']?->get($value))];
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\DependencyInjection;

use _ContaoManager\Symfony\Component\DependencyInjection\Argument\RewindableGenerator;
use _ContaoManager\Symfony\Component\DependencyInjection\Argument\ServiceLocator as ArgumentServiceLocator;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\EnvNotFoundException;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\ParameterCircularReferenceException;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\ParameterNotFoundException;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\RuntimeException;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\ServiceCircularReferenceException;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException;
use _ContaoManager\Symfony\Component\DependencyInjection\ParameterBag\EnvPlaceholderParameterBag;
use _ContaoManager\Symfony\Component\DependencyInjection\ParameterBag\FrozenParameterBag;
use _ContaoManager\Symfony\Component\DependencyInjection\ParameterBag\ParameterBag;
use _ContaoManager\Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface;
use _ContaoManager\Symfony\Contracts\Service\ResetInterface;
// Help opcache.preload discover always-needed symbols
class_exists(RewindableGenerator::class);
class_exists(ArgumentServiceLocator::class);
/**
 * Container is a dependency injection container.
 *
 * It gives access to object instances (services).
 * Services and parameters are simple key/pair stores.
 * The container can have five possible behaviors when a service
 * does not exist (or is not initialized for the last case):
 *
 *  * EXCEPTION_ON_INVALID_REFERENCE: Throws an exception at compilation time (the default)
 *  * NULL_ON_INVALID_REFERENCE:      Returns null
 *  * IGNORE_ON_INVALID_REFERENCE:    Ignores the wrapping command asking for the reference
 *                                    (for instance, ignore a setter if the service does not exist)
 *  * IGNORE_ON_UNINITIALIZED_REFERENCE: Ignores/returns null for uninitialized services or invalid references
 *  * RUNTIME_EXCEPTION_ON_INVALID_REFERENCE: Throws an exception at runtime
 *
 * @author Fabien Potencier <fabien@symfony.com>
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
class Container implements ContainerInterface, ResetInterface
{
    protected $parameterBag;
    protected $services = [];
    protected $privates = [];
    protected $fileMap = [];
    protected $methodMap = [];
    protected $factories = [];
    protected $aliases = [];
    protected $loading = [];
    protected $resolving = [];
    protected $syntheticIds = [];
    private array $envCache = [];
    private bool $compiled = \false;
    private \Closure $getEnv;
    private static \Closure $make;
    public function __construct(?ParameterBagInterface $parameterBag = null)
    {
        $this->parameterBag = $parameterBag ?? new EnvPlaceholderParameterBag();
    }
    /**
     * Compiles the container.
     *
     * This method does two things:
     *
     *  * Parameter values are resolved;
     *  * The parameter bag is frozen.
     *
     * @return void
     */
    public function compile()
    {
        $this->parameterBag->resolve();
        $this->parameterBag = new FrozenParameterBag($this->parameterBag->all(), $this->parameterBag instanceof ParameterBag ? $this->parameterBag->allDeprecated() : []);
        $this->compiled = \true;
    }
    /**
     * Returns true if the container is compiled.
     */
    public function isCompiled(): bool
    {
        return $this->compiled;
    }
    /**
     * Gets the service container parameter bag.
     */
    public function getParameterBag(): ParameterBagInterface
    {
        return $this->parameterBag;
    }
    /**
     * Gets a parameter.
     *
     * @return array|bool|string|int|float|\UnitEnum|null
     *
     * @throws ParameterNotFoundException if the parameter is not defined
     */
    public function getParameter(string $name)
    {
        return $this->parameterBag->get($name);
    }
    public function hasParameter(string $name): bool
    {
        return $this->parameterBag->has($name);
    }
    /**
     * @return void
     */
    public function setParameter(string $name, array|bool|string|int|float|\UnitEnum|null $value)
    {
        $this->parameterBag->set($name, $value);
    }
    /**
     * Sets a service.
     *
     * Setting a synthetic service to null resets it: has() returns false and get()
     * behaves in the same way as if the service was never created.
     *
     * @return void
     */
    public function set(string $id, ?object $service)
    {
        // Runs the internal initializer; used by the dumped container to include always-needed files
        if (isset($this->privates['service_container']) && $this->privates['service_container'] instanceof \Closure) {
            $initialize = $this->privates['service_container'];
            unset($this->privates['service_container']);
            $initialize($this);
        }
        if ('service_container' === $id) {
            throw new InvalidArgumentException('You cannot set service "service_container".');
        }
        if (!(isset($this->fileMap[$id]) || isset($this->methodMap[$id]))) {
            if (isset($this->syntheticIds[$id]) || !isset($this->getRemovedIds()[$id])) {
                // no-op
            } elseif (null === $service) {
                throw new InvalidArgumentException(\sprintf('The "%s" service is private, you cannot unset it.', $id));
            } else {
                throw new InvalidArgumentException(\sprintf('The "%s" service is private, you cannot replace it.', $id));
            }
        } elseif (isset($this->services[$id])) {
            throw new InvalidArgumentException(\sprintf('The "%s" service is already initialized, you cannot replace it.', $id));
        }
        if (isset($this->aliases[$id])) {
            unset($this->aliases[$id]);
        }
        if (null === $service) {
            unset($this->services[$id]);
            return;
        }
        $this->services[$id] = $service;
    }
    public function has(string $id): bool
    {
        if (isset($this->aliases[$id])) {
            $id = $this->aliases[$id];
        }
        if (isset($this->services[$id])) {
            return \true;
        }
        if ('service_container' === $id) {
            return \true;
        }
        return isset($this->fileMap[$id]) || isset($this->methodMap[$id]);
    }
    /**
     * Gets a service.
     *
     * @throws ServiceCircularReferenceException When a circular reference is detected
     * @throws ServiceNotFoundException          When the service is not defined
     *
     * @see Reference
     */
    public function get(string $id, int $invalidBehavior = self::EXCEPTION_ON_INVALID_REFERENCE): ?object
    {
        return $this->services[$id] ?? $this->services[$id = $this->aliases[$id] ?? $id] ?? ('service_container' === $id ? $this : ($this->factories[$id] ?? self::$make ??= self::make(...))($this, $id, $invalidBehavior));
    }
    /**
     * Creates a service.
     *
     * As a separate method to allow "get()" to use the really fast `??` operator.
     */
    private static function make(self $container, string $id, int $invalidBehavior): ?object
    {
        if (isset($container->loading[$id])) {
            throw new ServiceCircularReferenceException($id, array_merge(array_keys($container->loading), [$id]));
        }
        $container->loading[$id] = \true;
        try {
            if (isset($container->fileMap[$id])) {
                return 4 === $invalidBehavior ? null : $container->load($container->fileMap[$id]);
            } elseif (isset($container->methodMap[$id])) {
                return 4 === $invalidBehavior ? null : $container->{$container->methodMap[$id]}($container);
            }
        } catch (\Exception $e) {
            unset($container->services[$id]);
            throw $e;
        } finally {
            unset($container->loading[$id]);
        }
        if (self::EXCEPTION_ON_INVALID_REFERENCE === $invalidBehavior) {
            if (!$id) {
                throw new ServiceNotFoundException($id);
            }
            if (isset($container->syntheticIds[$id])) {
                throw new ServiceNotFoundException($id, null, null, [], \sprintf('The "%s" service is synthetic, it needs to be set at boot time before it can be used.', $id));
            }
            if (isset($container->getRemovedIds()[$id])) {
                throw new ServiceNotFoundException($id, null, null, [], \sprintf('The "%s" service or alias has been removed or inlined when the container was compiled. You should either make it public, or stop using the container directly and use dependency injection instead.', $id));
            }
            $alternatives = [];
            foreach ($container->getServiceIds() as $knownId) {
                if ('' === $knownId || '.' === $knownId[0]) {
                    continue;
                }
                $lev = levenshtein($id, $knownId);
                if ($lev <= \strlen($id) / 3 || str_contains($knownId, $id)) {
                    $alternatives[] = $knownId;
                }
            }
            throw new ServiceNotFoundException($id, null, null, $alternatives);
        }
        return null;
    }
    /**
     * Returns true if the given service has actually been initialized.
     */
    public function initialized(string $id): bool
    {
        if (isset($this->aliases[$id])) {
            $id = $this->aliases[$id];
        }
        if ('service_container' === $id) {
            return \false;
        }
        return isset($this->services[$id]);
    }
    /**
     * @return void
     */
    public function reset()
    {
        $services = $this->services + $this->privates;
        foreach ($services as $service) {
            try {
                if ($service instanceof ResetInterface) {
                    $service->reset();
                }
            } catch (\Throwable) {
                continue;
            }
        }
        $this->services = $this->factories = $this->privates = [];
    }
    /**
     * Gets all service ids.
     *
     * @return string[]
     */
    public function getServiceIds(): array
    {
        return array_map('strval', array_unique(array_merge(['service_container'], array_keys($this->fileMap), array_keys($this->methodMap), array_keys($this->aliases), array_keys($this->services))));
    }
    /**
     * Gets service ids that existed at compile time.
     */
    public function getRemovedIds(): array
    {
        return [];
    }
    /**
     * Camelizes a string.
     */
    public static function camelize(string $id): string
    {
        return strtr(ucwords(strtr($id, ['_' => ' ', '.' => '_ ', '\\' => '_ '])), [' ' => '']);
    }
    /**
     * A string to underscore.
     */
    public static function underscore(string $id): string
    {
        return strtolower(preg_replace(['/([A-Z]+)([A-Z][a-z])/', '/([a-z\d])([A-Z])/'], ['\1_\2', '\1_\2'], str_replace('_', '.', $id)));
    }
    /**
     * Creates a service by requiring its factory file.
     *
     * @return mixed
     */
    protected function load(string $file)
    {
        return require $file;
    }
    /**
     * Fetches a variable from the environment.
     *
     * @throws EnvNotFoundException When the environment variable is not found and has no default value
     */
    protected function getEnv(string $name): mixed
    {
        if (isset($this->resolving[$envName = "env({$name})"])) {
            throw new ParameterCircularReferenceException(array_keys($this->resolving));
        }
        if (isset($this->envCache[$name]) || \array_key_exists($name, $this->envCache)) {
            return $this->envCache[$name];
        }
        if (!$this->has($id = 'container.env_var_processors_locator')) {
            $this->set($id, new ServiceLocator([]));
        }
        $this->getEnv ??= $this->getEnv(...);
        $processors = $this->get($id);
        if (\false !== $i = strpos($name, ':')) {
            $prefix = substr($name, 0, $i);
            $localName = substr($name, 1 + $i);
        } else {
            $prefix = 'string';
            $localName = $name;
        }
        $processor = $processors->has($prefix) ? $processors->get($prefix) : new EnvVarProcessor($this);
        if (\false === $i) {
            $prefix = '';
        }
        $this->resolving[$envName] = \true;
        try {
            return $this->envCache[$name] = $processor->getEnv($prefix, $localName, $this->getEnv);
        } finally {
            unset($this->resolving[$envName]);
        }
    }
    /**
     * @internal
     */
    final protected function getService(string|false $registry, string $id, ?string $method, string|bool $load): mixed
    {
        if ('service_container' === $id) {
            return $this;
        }
        if (\is_string($load)) {
            throw new RuntimeException($load);
        }
        if (null === $method) {
            return \false !== $registry ? $this->{$registry}[$id] ?? null : null;
        }
        if (\false !== $registry) {
            return $this->{$registry}[$id] ??= $load ? $this->load($method) : $this->{$method}($this);
        }
        if (!$load) {
            return $this->{$method}($this);
        }
        return ($factory = $this->factories[$id] ?? $this->factories['service_container'][$id] ?? null) ? $factory($this) : $this->load($method);
    }
    private function __clone()
    {
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\DependencyInjection;

use _ContaoManager\Psr\Container\ContainerInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException;
/**
 * Turns public and "container.reversible" services back to their ids.
 *
 * @author Nicolas Grekas <p@tchwork.com>
 */
final class ReverseContainer
{
    private Container $serviceContainer;
    private ContainerInterface $reversibleLocator;
    private string $tagName;
    private \Closure $getServiceId;
    public function __construct(Container $serviceContainer, ContainerInterface $reversibleLocator, string $tagName = 'container.reversible')
    {
        $this->serviceContainer = $serviceContainer;
        $this->reversibleLocator = $reversibleLocator;
        $this->tagName = $tagName;
        $this->getServiceId = \Closure::bind(fn(object $service): ?string => (array_search($service, $this->services, \true) ?: array_search($service, $this->privates, \true)) ?: null, $serviceContainer, Container::class);
    }
    /**
     * Returns the id of the passed object when it exists as a service.
     *
     * To be reversible, services need to be either public or be tagged with "container.reversible".
     */
    public function getId(object $service): ?string
    {
        if ($this->serviceContainer === $service) {
            return 'service_container';
        }
        if (null === $id = ($this->getServiceId)($service)) {
            return null;
        }
        if ($this->serviceContainer->has($id) || $this->reversibleLocator->has($id)) {
            return $id;
        }
        return null;
    }
    /**
     * @throws ServiceNotFoundException When the service is not reversible
     */
    public function getService(string $id): object
    {
        if ($this->reversibleLocator->has($id)) {
            return $this->reversibleLocator->get($id);
        }
        if (isset($this->serviceContainer->getRemovedIds()[$id])) {
            throw new ServiceNotFoundException($id, null, null, [], \sprintf('The "%s" service is private and cannot be accessed by reference. You should either make it public, or tag it as "%s".', $id, $this->tagName));
        }
        return $this->serviceContainer->get($id);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\DependencyInjection;

/**
 * Represents a variable.
 *
 *     $var = new Variable('a');
 *
 * will be dumped as
 *
 *     $a
 *
 * by the PHP dumper.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
class Variable
{
    private string $name;
    public function __construct(string $name)
    {
        $this->name = $name;
    }
    public function __toString(): string
    {
        return $this->name;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\DependencyInjection\Extension;

use _ContaoManager\Symfony\Component\Config\Definition\ConfigurableInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerBuilder;
use _ContaoManager\Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;
/**
 * @author Yonel Ceruto <yonelceruto@gmail.com>
 */
interface ConfigurableExtensionInterface extends ConfigurableInterface
{
    /**
     * Allows an extension to prepend the extension configurations.
     */
    public function prependExtension(ContainerConfigurator $container, ContainerBuilder $builder): void;
    /**
     * Loads a specific configuration.
     */
    public function loadExtension(array $config, ContainerConfigurator $container, ContainerBuilder $builder): void;
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\DependencyInjection\Extension;

use _ContaoManager\Symfony\Component\DependencyInjection\ContainerBuilder;
/**
 * ExtensionInterface is the interface implemented by container extension classes.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
interface ExtensionInterface
{
    /**
     * Loads a specific configuration.
     *
     * @param array<array<mixed>> $configs
     *
     * @return void
     *
     * @throws \InvalidArgumentException When provided tag is not defined in this extension
     */
    public function load(array $configs, ContainerBuilder $container);
    /**
     * Returns the namespace to be used for this extension (XML namespace).
     *
     * @return string
     */
    public function getNamespace();
    /**
     * Returns the base path for the XSD files.
     *
     * @return string|false
     */
    public function getXsdValidationBasePath();
    /**
     * Returns the recommended alias to use in XML.
     *
     * This alias is also the mandatory prefix to use when using YAML.
     *
     * @return string
     */
    public function getAlias();
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\DependencyInjection\Extension;

use _ContaoManager\Symfony\Component\Config\Definition\Configuration;
use _ContaoManager\Symfony\Component\Config\Definition\ConfigurationInterface;
use _ContaoManager\Symfony\Component\Config\Definition\Configurator\DefinitionConfigurator;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerBuilder;
use _ContaoManager\Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;
/**
 * An Extension that provides configuration hooks.
 *
 * @author Yonel Ceruto <yonelceruto@gmail.com>
 */
abstract class AbstractExtension extends Extension implements ConfigurableExtensionInterface, PrependExtensionInterface
{
    use ExtensionTrait;
    public function configure(DefinitionConfigurator $definition): void
    {
    }
    public function prependExtension(ContainerConfigurator $container, ContainerBuilder $builder): void
    {
    }
    public function loadExtension(array $config, ContainerConfigurator $container, ContainerBuilder $builder): void
    {
    }
    public function getConfiguration(array $config, ContainerBuilder $container): ?ConfigurationInterface
    {
        return new Configuration($this, $container, $this->getAlias());
    }
    final public function prepend(ContainerBuilder $container): void
    {
        $callback = function (ContainerConfigurator $configurator) use ($container) {
            $this->prependExtension($configurator, $container);
        };
        $this->executeConfiguratorCallback($container, $callback, $this);
    }
    final public function load(array $configs, ContainerBuilder $container): void
    {
        $config = $this->processConfiguration($this->getConfiguration([], $container), $configs);
        $callback = function (ContainerConfigurator $configurator) use ($config, $container) {
            $this->loadExtension($config, $configurator, $container);
        };
        $this->executeConfiguratorCallback($container, $callback, $this);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\DependencyInjection\Extension;

use _ContaoManager\Symfony\Component\Config\Builder\ConfigBuilderGenerator;
use _ContaoManager\Symfony\Component\Config\FileLocator;
use _ContaoManager\Symfony\Component\Config\Loader\DelegatingLoader;
use _ContaoManager\Symfony\Component\Config\Loader\LoaderResolver;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerBuilder;
use _ContaoManager\Symfony\Component\DependencyInjection\Loader\ClosureLoader;
use _ContaoManager\Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;
use _ContaoManager\Symfony\Component\DependencyInjection\Loader\DirectoryLoader;
use _ContaoManager\Symfony\Component\DependencyInjection\Loader\GlobFileLoader;
use _ContaoManager\Symfony\Component\DependencyInjection\Loader\IniFileLoader;
use _ContaoManager\Symfony\Component\DependencyInjection\Loader\PhpFileLoader;
use _ContaoManager\Symfony\Component\DependencyInjection\Loader\XmlFileLoader;
use _ContaoManager\Symfony\Component\DependencyInjection\Loader\YamlFileLoader;
/**
 * @author Yonel Ceruto <yonelceruto@gmail.com>
 */
trait ExtensionTrait
{
    private function executeConfiguratorCallback(ContainerBuilder $container, \Closure $callback, ConfigurableExtensionInterface $subject): void
    {
        $env = $container->getParameter('kernel.environment');
        $loader = $this->createContainerLoader($container, $env);
        $file = (new \ReflectionObject($subject))->getFileName();
        $bundleLoader = $loader->getResolver()->resolve($file);
        if (!$bundleLoader instanceof PhpFileLoader) {
            throw new \LogicException('Unable to create the ContainerConfigurator.');
        }
        $bundleLoader->setCurrentDir(\dirname($file));
        $instanceof =& \Closure::bind(fn&() => $this->instanceof, $bundleLoader, $bundleLoader)();
        try {
            $callback(new ContainerConfigurator($container, $bundleLoader, $instanceof, $file, $file, $env));
        } finally {
            $instanceof = [];
            $bundleLoader->registerAliasesForSinglyImplementedInterfaces();
        }
    }
    private function createContainerLoader(ContainerBuilder $container, string $env): DelegatingLoader
    {
        $buildDir = $container->getParameter('kernel.build_dir');
        $locator = new FileLocator();
        $resolver = new LoaderResolver([new XmlFileLoader($container, $locator, $env), new YamlFileLoader($container, $locator, $env), new IniFileLoader($container, $locator, $env), new PhpFileLoader($container, $locator, $env, new ConfigBuilderGenerator($buildDir)), new GlobFileLoader($container, $locator, $env), new DirectoryLoader($container, $locator, $env), new ClosureLoader($container, $env)]);
        return new DelegatingLoader($resolver);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\DependencyInjection\Extension;

use _ContaoManager\Symfony\Component\Config\Definition\ConfigurationInterface;
use _ContaoManager\Symfony\Component\Config\Definition\Processor;
use _ContaoManager\Symfony\Component\DependencyInjection\Container;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerBuilder;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\BadMethodCallException;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\LogicException;
/**
 * Provides useful features shared by many extensions.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
abstract class Extension implements ExtensionInterface, ConfigurationExtensionInterface
{
    private array $processedConfigs = [];
    /**
     * @return string|false
     */
    public function getXsdValidationBasePath()
    {
        return \false;
    }
    /**
     * @return string
     */
    public function getNamespace()
    {
        return 'http://example.org/schema/dic/' . $this->getAlias();
    }
    /**
     * Returns the recommended alias to use in XML.
     *
     * This alias is also the mandatory prefix to use when using YAML.
     *
     * This convention is to remove the "Extension" postfix from the class
     * name and then lowercase and underscore the result. So:
     *
     *     AcmeHelloExtension
     *
     * becomes
     *
     *     acme_hello
     *
     * This can be overridden in a sub-class to specify the alias manually.
     *
     * @throws BadMethodCallException When the extension name does not follow conventions
     */
    public function getAlias(): string
    {
        $className = static::class;
        if (!str_ends_with($className, 'Extension')) {
            throw new BadMethodCallException('This extension does not follow the naming convention; you must overwrite the getAlias() method.');
        }
        $classBaseName = substr(strrchr($className, '\\'), 1, -9);
        return Container::underscore($classBaseName);
    }
    /**
     * @return ConfigurationInterface|null
     */
    public function getConfiguration(array $config, ContainerBuilder $container)
    {
        $class = static::class;
        if (str_contains($class, "\x00")) {
            return null;
            // ignore anonymous classes
        }
        $class = substr_replace($class, '\Configuration', strrpos($class, '\\'));
        $class = $container->getReflectionClass($class);
        if (!$class) {
            return null;
        }
        if (!$class->implementsInterface(ConfigurationInterface::class)) {
            throw new LogicException(\sprintf('The extension configuration class "%s" must implement "%s".', $class->getName(), ConfigurationInterface::class));
        }
        if (!($constructor = $class->getConstructor()) || !$constructor->getNumberOfRequiredParameters()) {
            return $class->newInstance();
        }
        return null;
    }
    final protected function processConfiguration(ConfigurationInterface $configuration, array $configs): array
    {
        $processor = new Processor();
        return $this->processedConfigs[] = $processor->processConfiguration($configuration, $configs);
    }
    /**
     * @internal
     */
    final public function getProcessedConfigs(): array
    {
        try {
            return $this->processedConfigs;
        } finally {
            $this->processedConfigs = [];
        }
    }
    /**
     * @throws InvalidArgumentException When the config is not enableable
     */
    protected function isConfigEnabled(ContainerBuilder $container, array $config): bool
    {
        if (!\array_key_exists('enabled', $config)) {
            throw new InvalidArgumentException("The config array has no 'enabled' key.");
        }
        return (bool) $container->getParameterBag()->resolveValue($config['enabled']);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\DependencyInjection\Extension;

use _ContaoManager\Symfony\Component\DependencyInjection\ContainerBuilder;
interface PrependExtensionInterface
{
    /**
     * Allow an extension to prepend the extension configurations.
     *
     * @return void
     */
    public function prepend(ContainerBuilder $container);
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\DependencyInjection\Extension;

use _ContaoManager\Symfony\Component\Config\Definition\ConfigurationInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerBuilder;
/**
 * ConfigurationExtensionInterface is the interface implemented by container extension classes.
 *
 * @author Kevin Bond <kevinbond@gmail.com>
 */
interface ConfigurationExtensionInterface
{
    /**
     * Returns extension configuration.
     *
     * @return ConfigurationInterface|null
     */
    public function getConfiguration(array $config, ContainerBuilder $container);
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\DependencyInjection\Attribute;

/**
 * An attribute to tell how a base type should be autoconfigured.
 *
 * @author Nicolas Grekas <p@tchwork.com>
 */
#[\Attribute(\Attribute::TARGET_CLASS | \Attribute::IS_REPEATABLE)]
class Autoconfigure
{
    public function __construct(public ?array $tags = null, public ?array $calls = null, public ?array $bind = null, public bool|string|null $lazy = null, public ?bool $public = null, public ?bool $shared = null, public ?bool $autowire = null, public ?array $properties = null, public array|string|null $configurator = null, public ?string $constructor = null)
    {
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\DependencyInjection\Attribute;

use _ContaoManager\Symfony\Component\DependencyInjection\Argument\TaggedIteratorArgument;
/**
 * Autowires an iterator of services based on a tag name.
 */
#[\Attribute(\Attribute::TARGET_PARAMETER)]
class AutowireIterator extends Autowire
{
    /**
     * @param string|string[] $exclude A service or a list of services to exclude
     */
    public function __construct(string $tag, ?string $indexAttribute = null, ?string $defaultIndexMethod = null, ?string $defaultPriorityMethod = null, string|array $exclude = [], bool $excludeSelf = \true)
    {
        parent::__construct(new TaggedIteratorArgument($tag, $indexAttribute, $defaultIndexMethod, \false, $defaultPriorityMethod, (array) $exclude, $excludeSelf));
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\DependencyInjection\Attribute;

use _ContaoManager\Symfony\Component\DependencyInjection\ContainerInterface;
#[\Attribute(\Attribute::TARGET_CLASS)]
class AsDecorator
{
    public function __construct(public string $decorates, public int $priority = 0, public int $onInvalid = ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE)
    {
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\DependencyInjection\Attribute;

use _ContaoManager\Symfony\Component\DependencyInjection\Argument\ServiceClosureArgument;
use _ContaoManager\Symfony\Component\DependencyInjection\Reference;
/**
 * Attribute to wrap a service in a closure that returns it.
 */
#[\Attribute(\Attribute::TARGET_PARAMETER)]
class AutowireServiceClosure extends Autowire
{
    public function __construct(string $service)
    {
        parent::__construct(new ServiceClosureArgument(new Reference($service)));
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\DependencyInjection\Attribute;

/**
 * An attribute to tell under which index and priority a service class should be found in tagged iterators/locators.
 *
 * @author Nicolas Grekas <p@tchwork.com>
 */
#[\Attribute(\Attribute::TARGET_CLASS)]
class AsTaggedItem
{
    public function __construct(public ?string $index = null, public ?int $priority = null)
    {
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\DependencyInjection\Attribute;

use _ContaoManager\Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\LogicException;
/**
 * An attribute to tell how a dependency is used and hint named autowiring aliases.
 *
 * @author Nicolas Grekas <p@tchwork.com>
 */
#[\Attribute(\Attribute::TARGET_PARAMETER | \Attribute::TARGET_PROPERTY)]
final class Target
{
    public function __construct(public ?string $name = null)
    {
    }
    public function getParsedName(): string
    {
        if (null === $this->name) {
            throw new LogicException(\sprintf('Cannot parse the name of a #[Target] attribute that has not been resolved. Did you forget to call "%s::parseName()"?', __CLASS__));
        }
        return lcfirst(str_replace(' ', '', ucwords(preg_replace('/[^a-zA-Z0-9\x7f-\xff]++/', ' ', $this->name))));
    }
    public static function parseName(\ReflectionParameter $parameter, ?self &$attribute = null, ?string &$parsedName = null): string
    {
        $attribute = null;
        if (!$target = $parameter->getAttributes(self::class)[0] ?? null) {
            $parsedName = (new self($parameter->name))->getParsedName();
            return $parameter->name;
        }
        $attribute = $target->newInstance();
        $name = $attribute->name ??= $parameter->name;
        $parsedName = $attribute->getParsedName();
        if (!preg_match('/^[a-zA-Z_\x7f-\xff]/', $parsedName)) {
            if (($function = $parameter->getDeclaringFunction()) instanceof \ReflectionMethod) {
                $function = $function->class . '::' . $function->name;
            } else {
                $function = $function->name;
            }
            throw new InvalidArgumentException(\sprintf('Invalid #[Target] name "%s" on parameter "$%s" of "%s()": the first character must be a letter.', $name, $parameter->name, $function));
        }
        return preg_match('/^[a-zA-Z0-9_\x7f-\xff]++$/', $name) ? $name : $parsedName;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\DependencyInjection\Attribute;

/**
 * An attribute to tell under which environment this class should be registered as a service.
 *
 * @author Nicolas Grekas <p@tchwork.com>
 */
#[\Attribute(\Attribute::TARGET_CLASS | \Attribute::TARGET_METHOD | \Attribute::TARGET_FUNCTION | \Attribute::IS_REPEATABLE)]
class When
{
    public function __construct(public string $env)
    {
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\DependencyInjection\Attribute;

#[\Attribute(\Attribute::TARGET_PARAMETER | \Attribute::TARGET_PROPERTY)]
class AutowireDecorated
{
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\DependencyInjection\Attribute;

#[\Attribute(\Attribute::TARGET_PARAMETER)]
class TaggedIterator extends AutowireIterator
{
    public function __construct(public string $tag, public ?string $indexAttribute = null, public ?string $defaultIndexMethod = null, public ?string $defaultPriorityMethod = null, public string|array $exclude = [], public bool $excludeSelf = \true)
    {
        parent::__construct($tag, $indexAttribute, $defaultIndexMethod, $defaultPriorityMethod, $exclude, $excludeSelf);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\DependencyInjection\Attribute;

use _ContaoManager\Symfony\Component\DependencyInjection\Argument\ServiceLocatorArgument;
use _ContaoManager\Symfony\Component\DependencyInjection\Argument\TaggedIteratorArgument;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
use _ContaoManager\Symfony\Component\DependencyInjection\TypedReference;
use _ContaoManager\Symfony\Contracts\Service\Attribute\SubscribedService;
use _ContaoManager\Symfony\Contracts\Service\ServiceSubscriberInterface;
/**
 * Autowires a service locator based on a tag name or an explicit list of key => service-type pairs.
 */
#[\Attribute(\Attribute::TARGET_PARAMETER)]
class AutowireLocator extends Autowire
{
    /**
     * @see ServiceSubscriberInterface::getSubscribedServices()
     *
     * @param string|array<string|Autowire|SubscribedService> $services An explicit list of services or a tag name
     * @param string|string[]                                 $exclude  A service or a list of services to exclude
     */
    public function __construct(string|array $services, ?string $indexAttribute = null, ?string $defaultIndexMethod = null, ?string $defaultPriorityMethod = null, string|array $exclude = [], bool $excludeSelf = \true)
    {
        if (\is_string($services)) {
            parent::__construct(new ServiceLocatorArgument(new TaggedIteratorArgument($services, $indexAttribute, $defaultIndexMethod, \true, $defaultPriorityMethod, (array) $exclude, $excludeSelf)));
            return;
        }
        $references = [];
        foreach ($services as $key => $type) {
            $attributes = [];
            if ($type instanceof Autowire) {
                $references[$key] = $type;
                continue;
            }
            if ($type instanceof SubscribedService) {
                $key = $type->key ?? $key;
                $attributes = $type->attributes;
                $type = ($type->nullable ? '?' : '') . ($type->type ?? throw new InvalidArgumentException(\sprintf('When "%s" is used, a type must be set.', SubscribedService::class)));
            }
            if (!\is_string($type) || !preg_match('/(?(DEFINE)(?<cn>[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*+))(?(DEFINE)(?<fqcn>(?&cn)(?:\\\\(?&cn))*+))^\??(?&fqcn)(?:(?:\|(?&fqcn))*+|(?:&(?&fqcn))*+)$/', $type)) {
                throw new InvalidArgumentException(\sprintf('"%s" is not a PHP type for key "%s".', \is_string($type) ? $type : get_debug_type($type), $key));
            }
            $optionalBehavior = ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE;
            if ('?' === $type[0]) {
                $type = substr($type, 1);
                $optionalBehavior = ContainerInterface::IGNORE_ON_INVALID_REFERENCE;
            }
            if (\is_int($name = $key)) {
                $key = $type;
                $name = null;
            }
            $references[$key] = new TypedReference($type, $type, $optionalBehavior, $name, $attributes);
        }
        parent::__construct(new ServiceLocatorArgument($references));
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\DependencyInjection\Attribute;

use _ContaoManager\Symfony\Component\DependencyInjection\Definition;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\LogicException;
use _ContaoManager\Symfony\Component\DependencyInjection\Reference;
/**
 * Attribute to tell which callable to give to an argument of type Closure.
 */
#[\Attribute(\Attribute::TARGET_PARAMETER)]
class AutowireCallable extends Autowire
{
    /**
     * @param bool|class-string $lazy Whether to use lazy-loading for this argument
     */
    public function __construct(string|array|null $callable = null, ?string $service = null, ?string $method = null, bool|string $lazy = \false)
    {
        if (!(null !== $callable xor null !== $service)) {
            throw new LogicException('#[AutowireCallable] attribute must declare exactly one of $callable or $service.');
        }
        if (null === $service && null !== $method) {
            throw new LogicException('#[AutowireCallable] attribute cannot have a $method without a $service.');
        }
        parent::__construct($callable ?? [new Reference($service), $method ?? '__invoke'], lazy: $lazy);
    }
    public function buildDefinition(mixed $value, ?string $type, \ReflectionParameter $parameter): Definition
    {
        return (new Definition($type = \is_array($this->lazy) ? current($this->lazy) : ($type ?: 'Closure')))->setFactory(['Closure', 'fromCallable'])->setArguments([\is_array($value) ? $value + [1 => '__invoke'] : $value])->setLazy($this->lazy || 'Closure' !== $type && 'callable' !== (string) $parameter->getType());
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\DependencyInjection\Attribute;

use _ContaoManager\Symfony\Component\DependencyInjection\Argument\ArgumentInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\LogicException;
use _ContaoManager\Symfony\Component\DependencyInjection\Reference;
use _ContaoManager\Symfony\Component\ExpressionLanguage\Expression;
/**
 * Attribute to tell a parameter how to be autowired.
 *
 * @author Kevin Bond <kevinbond@gmail.com>
 */
#[\Attribute(\Attribute::TARGET_PARAMETER | \Attribute::TARGET_PROPERTY)]
class Autowire
{
    public readonly string|array|Expression|Reference|ArgumentInterface|null $value;
    public readonly bool|array $lazy;
    /**
     * Use only ONE of the following.
     *
     * @param string|array|ArgumentInterface|null $value      Value to inject (ie "%kernel.project_dir%/some/path")
     * @param string|null                         $service    Service ID (ie "some.service")
     * @param string|null                         $expression Expression (ie 'service("some.service").someMethod()')
     * @param string|null                         $env        Environment variable name (ie 'SOME_ENV_VARIABLE')
     * @param string|null                         $param      Parameter name (ie 'some.parameter.name')
     * @param bool|class-string|class-string[]    $lazy       Whether to use lazy-loading for this argument
     */
    public function __construct(string|array|ArgumentInterface|null $value = null, ?string $service = null, ?string $expression = null, ?string $env = null, ?string $param = null, bool|string|array $lazy = \false)
    {
        if ($this->lazy = \is_string($lazy) ? [$lazy] : $lazy) {
            if (null !== ($expression ?? $env ?? $param)) {
                throw new LogicException('#[Autowire] attribute cannot be $lazy and use $expression, $env, or $param.');
            }
            if (null !== $value && null !== $service) {
                throw new LogicException('#[Autowire] attribute cannot declare $value and $service at the same time.');
            }
        } elseif (1 !== (null !== $value) + (null !== $service) + (null !== $expression) + (null !== $env) + (null !== $param)) {
            throw new LogicException('#[Autowire] attribute must declare exactly one of $service, $expression, $env, $param or $value.');
        }
        if (\is_string($value) && str_starts_with($value, '@')) {
            match (\true) {
                str_starts_with($value, '@@') => $value = substr($value, 1),
                str_starts_with($value, '@=') => $expression = substr($value, 2),
                default => $service = substr($value, 1),
            };
        }
        $this->value = match (\true) {
            null !== $service => new Reference($service),
            null !== $expression => class_exists(Expression::class) ? new Expression($expression) : throw new LogicException('Unable to use expressions as the Symfony ExpressionLanguage component is not installed. Try running "composer require symfony/expression-language".'),
            null !== $env => "%env({$env})%",
            null !== $param => "%{$param}%",
            default => $value,
        };
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\DependencyInjection\Attribute;

/**
 * An attribute to tell how a base type should be tagged.
 *
 * @author Nicolas Grekas <p@tchwork.com>
 */
#[\Attribute(\Attribute::TARGET_CLASS | \Attribute::IS_REPEATABLE)]
class AutoconfigureTag extends Autoconfigure
{
    public function __construct(?string $name = null, array $attributes = [])
    {
        parent::__construct(tags: [[$name ?? 0 => $attributes]]);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\DependencyInjection\Attribute;

#[\Attribute(\Attribute::TARGET_PARAMETER)]
class TaggedLocator extends AutowireLocator
{
    public function __construct(public string $tag, public ?string $indexAttribute = null, public ?string $defaultIndexMethod = null, public ?string $defaultPriorityMethod = null, public string|array $exclude = [], public bool $excludeSelf = \true)
    {
        parent::__construct($tag, $indexAttribute, $defaultIndexMethod, $defaultPriorityMethod, $exclude, $excludeSelf);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\DependencyInjection\Attribute;

trigger_deprecation('symfony/dependency-injection', '6.3', 'The "%s" class is deprecated, use "%s" instead.', MapDecorated::class, AutowireDecorated::class);
/**
 * @deprecated since Symfony 6.3, use AutowireDecorated instead
 */
#[\Attribute(\Attribute::TARGET_PARAMETER)]
class MapDecorated
{
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\DependencyInjection\Attribute;

/**
 * An attribute to tell the class should not be registered as service.
 *
 * @author Grégoire Pineau <lyrixx@lyrixx.info>
 */
#[\Attribute(\Attribute::TARGET_CLASS)]
class Exclude
{
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\DependencyInjection\Attribute;

/**
 * An attribute to tell under which alias a service should be registered or to use the implemented interface if no parameter is given.
 *
 * @author Alan Poulain <contact@alanpoulain.eu>
 */
#[\Attribute(\Attribute::TARGET_CLASS | \Attribute::IS_REPEATABLE)]
final class AsAlias
{
    public function __construct(public ?string $id = null, public bool $public = \false)
    {
    }
}
Copyright (c) 2004-present Fabien Potencier

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is furnished
to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
CHANGELOG
=========

6.4
---

 * Allow using `#[Target]` with no arguments to state that a parameter must match a named autowiring alias
 * Deprecate `ContainerAwareInterface` and `ContainerAwareTrait`, use dependency injection instead
 * Add `defined` env var processor that returns `true` for defined and neither null nor empty env vars
 * Add `#[AutowireLocator]` and `#[AutowireIterator]` attributes

6.3
---

 * Add options `inline_factories` and `inline_class_loader` to `PhpDumper::dump()`
 * Deprecate `PhpDumper` options `inline_factories_parameter` and `inline_class_loader_parameter`
 * Add `RemoveBuildParametersPass`, which removes parameters starting with a dot during compilation
 * Add support for nesting autowiring-related attributes into `#[Autowire(...)]`
 * Deprecate undefined and numeric keys with `service_locator` config
 * Fail if Target attribute does not exist during compilation
 * Enable deprecating parameters with `ContainerBuilder::deprecateParameter()`
 * Add `#[AsAlias]` attribute to tell under which alias a service should be registered or to use the implemented interface if no parameter is given
 * Allow to trim XML service parameters value by using `trim="true"` attribute
 * Allow extending the `Autowire` attribute
 * Add `#[Exclude]` to skip autoregistering a class
 * Add support for generating lazy closures
 * Add support for autowiring services as closures using `#[AutowireCallable]` or `#[AutowireServiceClosure]`
 * Add support for `#[Autowire(lazy: true|class-string)]`
 * Make it possible to cast callables into single-method interfaces
 * Deprecate `#[MapDecorated]`, use `#[AutowireDecorated]` instead
 * Deprecate the `@required` annotation, use the `Symfony\Contracts\Service\Attribute\Required` attribute instead
 * Add `constructor` option to services declaration and to `#[Autoconfigure]`

6.2
---

 * Use lazy-loading ghost objects and virtual proxies out of the box
 * Add arguments `&$asGhostObject` and `$id` to LazyProxy's `DumperInterface` to allow using ghost objects for lazy loading services
 * Add `enum` env var processor
 * Add `shuffle` env var processor
 * Allow #[When] to be extended
 * Change the signature of `ContainerAwareInterface::setContainer()` to `setContainer(?ContainerInterface)`
 * Deprecate calling `ContainerAwareTrait::setContainer()` without arguments
 * Deprecate using numeric parameter names
 * Add support for tagged iterators/locators `exclude` option to the xml and yaml loaders/dumpers
 * Allow injecting `string $env` into php config closures
 * Add `excludeSelf` parameter to `TaggedIteratorArgument` with default value to `true`
   to control whether the referencing service should be automatically excluded from the iterator

6.1
---

 * Add `#[MapDecorated]` attribute telling to which parameter the decorated service should be mapped in a decorator
 * Add `#[AsDecorator]` attribute to make a service decorates another
 * Add `$exclude` to `TaggedIterator` and `TaggedLocator` attributes
 * Add `$exclude` to `tagged_iterator` and `tagged_locator` configurator
 * Add an `env` function to the expression language provider
 * Add an `Autowire` attribute to tell a parameter how to be autowired
 * Allow using expressions as service factories
 * Add argument type `closure` to help passing closures to services
 * Deprecate `ReferenceSetArgumentTrait`
 * Add `AbstractExtension` class for DI configuration/definition on a single file

6.0
---

 * Remove `Definition::setPrivate()` and `Alias::setPrivate()`, use `setPublic()` instead
 * Remove `inline()` in favor of `inline_service()` and `ref()` in favor of `service()` when using the PHP-DSL
 * Remove `Definition::getDeprecationMessage()`, use `Definition::getDeprecation()` instead
 * Remove `Alias::getDeprecationMessage()`, use `Alias::getDeprecation()` instead
 * Remove the `Psr\Container\ContainerInterface` and `Symfony\Component\DependencyInjection\ContainerInterface` aliases of the `service_container` service

5.4
---
 * Add `$defaultIndexMethod` and `$defaultPriorityMethod` to `TaggedIterator` and `TaggedLocator` attributes
 * Add `service_closure()` to the PHP-DSL
 * Add support for autoconfigurable attributes on methods, properties and parameters
 * Make auto-aliases private by default
 * Add support for autowiring union and intersection types

5.3
---

 * Add `ServicesConfigurator::remove()` in the PHP-DSL
 * Add `%env(not:...)%` processor to negate boolean values
 * Add support for loading autoconfiguration rules via the `#[Autoconfigure]` and `#[AutoconfigureTag]` attributes on PHP 8
 * Add `#[AsTaggedItem]` attribute for defining the index and priority of classes found in tagged iterators/locators
 * Add autoconfigurable attributes
 * Add support for autowiring tagged iterators and locators via attributes on PHP 8
 * Add support for per-env configuration in XML and Yaml loaders
 * Add `ContainerBuilder::willBeAvailable()` to help with conditional configuration
 * Add support an integer return value for default_index_method
 * Add `#[When(env: 'foo')]` to skip autoregistering a class when the env doesn't match
 * Add `env()` and `EnvConfigurator` in the PHP-DSL
 * Add support for `ConfigBuilder` in the `PhpFileLoader`
 * Add `ContainerConfigurator::env()` to get the current environment
 * Add `#[Target]` to tell how a dependency is used and hint named autowiring aliases

5.2.0
-----

 * added `param()` and `abstract_arg()` in the PHP-DSL
 * deprecated `Definition::setPrivate()` and `Alias::setPrivate()`, use `setPublic()` instead
 * added support for the `#[Required]` attribute

5.1.0
-----

 * deprecated `inline()` in favor of `inline_service()` and `ref()` in favor of `service()` when using the PHP-DSL
 * allow decorators to reference their decorated service using the special `.inner` id
 * added support to autowire public typed properties in php 7.4
 * added support for defining method calls, a configurator, and property setters in `InlineServiceConfigurator`
 * added possibility to define abstract service arguments
 * allowed mixing "parent" and instanceof-conditionals/defaults/bindings
 * updated the signature of method `Definition::setDeprecated()` to `Definition::setDeprecation(string $package, string $version, string $message)`
 * updated the signature of method `Alias::setDeprecated()` to `Alias::setDeprecation(string $package, string $version, string $message)`
 * updated the signature of method `DeprecateTrait::deprecate()` to `DeprecateTrait::deprecation(string $package, string $version, string $message)`
 * deprecated the `Psr\Container\ContainerInterface` and `Symfony\Component\DependencyInjection\ContainerInterface` aliases of the `service_container` service,
   configure them explicitly instead
 * added class `Symfony\Component\DependencyInjection\Dumper\Preloader` to help with preloading on PHP 7.4+
 * added tags `container.preload`/`.no_preload` to declare extra classes to preload/services to not preload
 * allowed loading and dumping tags with an attribute named "name"
 * deprecated `Definition::getDeprecationMessage()`, use `Definition::getDeprecation()` instead
 * deprecated `Alias::getDeprecationMessage()`, use `Alias::getDeprecation()` instead
 * added support of PHP8 static return type for withers
 * added `AliasDeprecatedPublicServicesPass` to deprecate public services to private

5.0.0
-----

 * removed support for auto-discovered extension configuration class which does not implement `ConfigurationInterface`
 * removed support for non-string default env() parameters
 * moved `ServiceSubscriberInterface` to the `Symfony\Contracts\Service` namespace
 * removed `RepeatedPass` and `RepeatablePassInterface`
 * removed support for short factory/configurator syntax from `YamlFileLoader`
 * removed `ResettableContainerInterface`, use `ResetInterface` instead
 * added argument `$returnsClone` to `Definition::addMethodCall()`
 * removed `tagged`, use `tagged_iterator` instead

4.4.0
-----

 * added `CheckTypeDeclarationsPass` to check injected parameters type during compilation
 * added support for opcache.preload by generating a preloading script in the cache folder
 * added support for dumping the container in one file instead of many files
 * deprecated support for short factories and short configurators in Yaml
 * added `tagged_iterator` alias for `tagged` which might be deprecated in a future version
 * deprecated passing an instance of `Symfony\Component\DependencyInjection\Parameter` as class name to `Symfony\Component\DependencyInjection\Definition`
 * added support for binding iterable and tagged services
 * made singly-implemented interfaces detection be scoped by file
 * added ability to define a static priority method for tagged service
 * added support for improved syntax to define method calls in Yaml
 * made the `%env(base64:...)%` processor able to decode base64url
 * added ability to choose behavior of decorations on non existent decorated services

4.3.0
-----

 * added `%env(trim:...)%` processor to trim a string value
 * added `%env(default:param_name:...)%` processor to fallback to a parameter or to null when using `%env(default::...)%`
 * added `%env(url:...)%` processor to convert a URL or DNS into an array of components
 * added `%env(query_string:...)%` processor to convert a query string into an array of key values
 * added support for deprecating aliases
 * made `ContainerParametersResource` final and not implement `Serializable` anymore
 * added `ReverseContainer`: a container that turns services back to their ids
 * added ability to define an index for a tagged collection
 * added ability to define an index for services in an injected service locator argument
 * made `ServiceLocator` implement `ServiceProviderInterface`
 * deprecated support for non-string default env() parameters
 * added `%env(require:...)%` processor to `require()` a PHP file and use the value returned from it

4.2.0
-----

 * added `ContainerBuilder::registerAliasForArgument()` to support autowiring by type+name
 * added support for binding by type+name
 * added `ServiceSubscriberTrait` to ease implementing `ServiceSubscriberInterface` using methods' return types
 * added `ServiceLocatorArgument` and `!service_locator` config tag for creating optimized service-locators
 * added support for autoconfiguring bindings
 * added `%env(key:...)%` processor to fetch a specific key from an array
 * deprecated `ServiceSubscriberInterface`, use the same interface from the `Symfony\Contracts\Service` namespace instead
 * deprecated `ResettableContainerInterface`, use `Symfony\Contracts\Service\ResetInterface` instead

4.1.0
-----

 * added support for variadics in named arguments
 * added PSR-11 `ContainerBagInterface` and its `ContainerBag` implementation to access parameters as-a-service
 * added support for service's decorators autowiring
 * deprecated the `TypedReference::canBeAutoregistered()` and  `TypedReference::getRequiringClass()` methods
 * environment variables are validated when used in extension configuration
 * deprecated support for auto-discovered extension configuration class which does not implement `ConfigurationInterface`

4.0.0
-----

 * Relying on service auto-registration while autowiring is not supported anymore.
   Explicitly inject your dependencies or create services whose ids are
   their fully-qualified class name.

   Before:

   ```php
   namespace App\Controller;

   use App\Mailer;

   class DefaultController
   {
       public function __construct(Mailer $mailer) {
           // ...
       }

       // ...
   }
   ```
   ```yml
   services:
       App\Controller\DefaultController:
           autowire: true
   ```

   After:

   ```php
   // same PHP code
   ```
   ```yml
   services:
       App\Controller\DefaultController:
           autowire: true

       # or
       # App\Controller\DefaultController:
       #     arguments: { $mailer: "@App\Mailer" }

       App\Mailer:
           autowire: true
    ```
 * removed autowiring services based on the types they implement
 * added a third `$methodName` argument to the `getProxyFactoryCode()` method
   of the `DumperInterface`
 * removed support for autowiring types
 * removed `Container::isFrozen`
 * removed support for dumping an ucompiled container in `PhpDumper`
 * removed support for generating a dumped `Container` without populating the method map
 * removed support for case insensitive service identifiers
 * removed the `DefinitionDecorator` class, replaced by `ChildDefinition`
 * removed the `AutowireServiceResource` class and related `AutowirePass::createResourceForClass()` method
 * removed `LoggingFormatter`, `Compiler::getLoggingFormatter()` and `addLogMessage()` class and methods, use the `ContainerBuilder::log()` method instead
 * removed `FactoryReturnTypePass`
 * removed `ContainerBuilder::addClassResource()`, use the `addObjectResource()` or the `getReflectionClass()` method instead.
 * removed support for top-level anonymous services
 * removed silent behavior for unused attributes and elements
 * removed support for setting and accessing private services in `Container`
 * removed support for setting pre-defined services in `Container`
 * removed support for case insensitivity of parameter names
 * removed `AutowireExceptionPass` and `AutowirePass::getAutowiringExceptions()`, use `Definition::addError()` and the `DefinitionErrorExceptionPass` instead

3.4.0
-----

 * moved the `ExtensionCompilerPass` to before-optimization passes with priority -1000
 * deprecated "public-by-default" definitions and aliases, the new default will be "private" in 4.0
 * added `EnvVarProcessorInterface` and corresponding "container.env_var_processor" tag for processing env vars
 * added support for ignore-on-uninitialized references
 * deprecated service auto-registration while autowiring
 * deprecated the ability to check for the initialization of a private service with the `Container::initialized()` method
 * deprecated support for top-level anonymous services in XML
 * deprecated case insensitivity of parameter names
 * deprecated the `ResolveDefinitionTemplatesPass` class in favor of `ResolveChildDefinitionsPass`
 * added `TaggedIteratorArgument` with YAML (`!tagged foo`) and XML (`<service type="tagged"/>`) support
 * deprecated `AutowireExceptionPass` and `AutowirePass::getAutowiringExceptions()`, use `Definition::addError()` and the `DefinitionErrorExceptionPass` instead

3.3.0
-----

 * deprecated autowiring services based on the types they implement;
   rename (or alias) your services to their FQCN id to make them autowirable
 * added "ServiceSubscriberInterface" - to allow for per-class explicit service-locator definitions
 * added "container.service_locator" tag for defining service-locator services
 * added anonymous services support in YAML configuration files using the `!service` tag.
 * added "TypedReference" and "ServiceClosureArgument" for creating service-locator services
 * added `ServiceLocator` - a PSR-11 container holding a set of services to be lazily loaded
 * added "instanceof" section for local interface-defined configs
 * added prototype services for PSR4-based discovery and registration
 * added `ContainerBuilder::getReflectionClass()` for retrieving and tracking reflection class info
 * deprecated `ContainerBuilder::getClassResource()`, use `ContainerBuilder::getReflectionClass()` or `ContainerBuilder::addObjectResource()` instead
 * added `ContainerBuilder::fileExists()` for checking and tracking file or directory existence
 * deprecated autowiring-types, use aliases instead
 * added support for omitting the factory class name in a service definition if the definition class is set
 * deprecated case insensitivity of service identifiers
 * added "iterator" argument type for lazy iteration over a set of values and services
 * added file-wide configurable defaults for service attributes "public", "tags",
   "autowire" and "autoconfigure"
 * made the "class" attribute optional, using the "id" as fallback
 * using the `PhpDumper` with an uncompiled `ContainerBuilder` is deprecated and
   will not be supported anymore in 4.0
 * deprecated the `DefinitionDecorator` class in favor of `ChildDefinition`
 * allow config files to be loaded using a glob pattern
 * [BC BREAK] the `NullDumper` class is now final

3.2.0
-----

 * allowed to prioritize compiler passes by introducing a third argument to `PassConfig::addPass()`, to `Compiler::addPass` and to `ContainerBuilder::addCompilerPass()`
 * added support for PHP constants in YAML configuration files
 * deprecated the ability to set or unset a private service with the `Container::set()` method
 * deprecated the ability to check for the existence of a private service with the `Container::has()` method
 * deprecated the ability to request a private service with the `Container::get()` method
 * deprecated support for generating a dumped `Container` without populating the method map

3.0.0
-----

 * removed all deprecated codes from 2.x versions

2.8.0
-----

 * deprecated the abstract ContainerAware class in favor of ContainerAwareTrait
 * deprecated IntrospectableContainerInterface, to be merged with ContainerInterface in 3.0
 * allowed specifying a directory to recursively load all configuration files it contains
 * deprecated the concept of scopes
 * added `Definition::setShared()` and `Definition::isShared()`
 * added ResettableContainerInterface to be able to reset the container to release memory on shutdown
 * added a way to define the priority of service decoration
 * added support for service autowiring

2.7.0
-----

 * deprecated synchronized services

2.6.0
-----

 * added new factory syntax and deprecated the old one

2.5.0
-----

 * added DecoratorServicePass and a way to override a service definition (Definition::setDecoratedService())
 * deprecated SimpleXMLElement class.

2.4.0
-----

 * added support for expressions in service definitions
 * added ContainerAwareTrait to add default container aware behavior to a class

2.2.0
-----

 * added Extension::isConfigEnabled() to ease working with enableable configurations
 * added an Extension base class with sensible defaults to be used in conjunction
   with the Config component.
 * added PrependExtensionInterface (to be able to allow extensions to prepend
   application configuration settings for any Bundle)

2.1.0
-----

 * added IntrospectableContainerInterface (to be able to check if a service
   has been initialized or not)
 * added ConfigurationExtensionInterface
 * added Definition::clearTag()
 * component exceptions that inherit base SPL classes are now used exclusively
   (this includes dumped containers)
 * [BC BREAK] fixed unescaping of class arguments, method
   ParameterBag::unescapeValue() was made public
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\DependencyInjection\Config;

use _ContaoManager\Symfony\Component\Config\Resource\ResourceInterface;
use _ContaoManager\Symfony\Component\Config\ResourceCheckerInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerInterface;
/**
 * @author Maxime Steinhausser <maxime.steinhausser@gmail.com>
 */
class ContainerParametersResourceChecker implements ResourceCheckerInterface
{
    private ContainerInterface $container;
    public function __construct(ContainerInterface $container)
    {
        $this->container = $container;
    }
    public function supports(ResourceInterface $metadata): bool
    {
        return $metadata instanceof ContainerParametersResource;
    }
    public function isFresh(ResourceInterface $resource, int $timestamp): bool
    {
        foreach ($resource->getParameters() as $key => $value) {
            if (!$this->container->hasParameter($key) || $this->container->getParameter($key) !== $value) {
                return \false;
            }
        }
        return \true;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\DependencyInjection\Config;

use _ContaoManager\Symfony\Component\Config\Resource\ResourceInterface;
/**
 * Tracks container parameters.
 *
 * @author Maxime Steinhausser <maxime.steinhausser@gmail.com>
 *
 * @final
 */
class ContainerParametersResource implements ResourceInterface
{
    private array $parameters;
    /**
     * @param array $parameters The container parameters to track
     */
    public function __construct(array $parameters)
    {
        $this->parameters = $parameters;
    }
    public function __toString(): string
    {
        return 'container_parameters_' . hash('xxh128', serialize($this->parameters));
    }
    public function getParameters(): array
    {
        return $this->parameters;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\DependencyInjection\Argument;

trigger_deprecation('symfony/dependency-injection', '6.1', '"%s" is deprecated.', ReferenceSetArgumentTrait::class);
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
use _ContaoManager\Symfony\Component\DependencyInjection\Reference;
/**
 * @author Titouan Galopin <galopintitouan@gmail.com>
 * @author Nicolas Grekas <p@tchwork.com>
 *
 * @deprecated since Symfony 6.1
 */
trait ReferenceSetArgumentTrait
{
    private array $values;
    /**
     * @param Reference[] $values
     */
    public function __construct(array $values)
    {
        $this->setValues($values);
    }
    /**
     * @return Reference[]
     */
    public function getValues(): array
    {
        return $this->values;
    }
    /**
     * @param Reference[] $values The service references to put in the set
     *
     * @return void
     */
    public function setValues(array $values)
    {
        foreach ($values as $k => $v) {
            if (null !== $v && !$v instanceof Reference) {
                throw new InvalidArgumentException(\sprintf('A "%s" must hold only Reference instances, "%s" given.', __CLASS__, get_debug_type($v)));
            }
        }
        $this->values = $values;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\DependencyInjection\Argument;

/**
 * Represents an abstract service argument, which have to be set by a compiler pass or a DI extension.
 */
final class AbstractArgument
{
    private string $text;
    private string $context = '';
    public function __construct(string $text = '')
    {
        $this->text = trim($text, '. ');
    }
    public function setContext(string $context): void
    {
        $this->context = $context . ' is abstract' . ('' === $this->text ? '' : ': ');
    }
    public function getText(): string
    {
        return $this->text;
    }
    public function getTextWithContext(): string
    {
        return $this->context . $this->text . '.';
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\DependencyInjection\Argument;

/**
 * @internal
 */
class RewindableGenerator implements \IteratorAggregate, \Countable
{
    private \Closure $generator;
    private \Closure|int $count;
    public function __construct(callable $generator, int|callable $count)
    {
        $this->generator = $generator(...);
        $this->count = \is_int($count) ? $count : $count(...);
    }
    public function getIterator(): \Traversable
    {
        $g = $this->generator;
        return $g();
    }
    public function count(): int
    {
        if (!\is_int($count = $this->count)) {
            $this->count = $count();
        }
        return $this->count;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\DependencyInjection\Argument;

/**
 * Represents a closure acting as a service locator.
 *
 * @author Nicolas Grekas <p@tchwork.com>
 */
class ServiceLocatorArgument implements ArgumentInterface
{
    private array $values;
    private ?TaggedIteratorArgument $taggedIteratorArgument = null;
    public function __construct(array|TaggedIteratorArgument $values = [])
    {
        if ($values instanceof TaggedIteratorArgument) {
            $this->taggedIteratorArgument = $values;
            $values = [];
        }
        $this->setValues($values);
    }
    public function getTaggedIteratorArgument(): ?TaggedIteratorArgument
    {
        return $this->taggedIteratorArgument;
    }
    public function getValues(): array
    {
        return $this->values;
    }
    /**
     * @return void
     */
    public function setValues(array $values)
    {
        $this->values = $values;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\DependencyInjection\Argument;

/**
 * @author Guilhem Niot <guilhem.niot@gmail.com>
 */
final class BoundArgument implements ArgumentInterface
{
    public const SERVICE_BINDING = 0;
    public const DEFAULTS_BINDING = 1;
    public const INSTANCEOF_BINDING = 2;
    private static int $sequence = 0;
    private mixed $value;
    private ?int $identifier = null;
    private ?bool $used = null;
    private int $type;
    private ?string $file;
    public function __construct(mixed $value, bool $trackUsage = \true, int $type = 0, ?string $file = null)
    {
        $this->value = $value;
        if ($trackUsage) {
            $this->identifier = ++self::$sequence;
        } else {
            $this->used = \true;
        }
        $this->type = $type;
        $this->file = $file;
    }
    public function getValues(): array
    {
        return [$this->value, $this->identifier, $this->used, $this->type, $this->file];
    }
    public function setValues(array $values): void
    {
        if (5 === \count($values)) {
            [$this->value, $this->identifier, $this->used, $this->type, $this->file] = $values;
        } else {
            [$this->value, $this->identifier, $this->used] = $values;
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\DependencyInjection\Argument;

/**
 * Represents a collection of values to lazily iterate over.
 *
 * @author Titouan Galopin <galopintitouan@gmail.com>
 */
class IteratorArgument implements ArgumentInterface
{
    private array $values;
    public function __construct(array $values)
    {
        $this->setValues($values);
    }
    public function getValues(): array
    {
        return $this->values;
    }
    /**
     * @return void
     */
    public function setValues(array $values)
    {
        $this->values = $values;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\DependencyInjection\Argument;

use _ContaoManager\Symfony\Component\DependencyInjection\ContainerBuilder;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\RuntimeException;
use _ContaoManager\Symfony\Component\DependencyInjection\Reference;
use _ContaoManager\Symfony\Component\VarExporter\ProxyHelper;
/**
 * @author Nicolas Grekas <p@tchwork.com>
 *
 * @internal
 */
class LazyClosure
{
    public readonly object $service;
    public function __construct(private \Closure $initializer)
    {
        unset($this->service);
    }
    public function __get(mixed $name): mixed
    {
        if ('service' !== $name) {
            throw new InvalidArgumentException(\sprintf('Cannot read property "%s" from a lazy closure.', $name));
        }
        if (isset($this->initializer)) {
            if (\is_string($service = ($this->initializer)())) {
                $service = (new \ReflectionClass($service))->newInstanceWithoutConstructor();
            }
            $this->service = $service;
            unset($this->initializer);
        }
        return $this->service;
    }
    public static function getCode(string $initializer, array $callable, string $class, ContainerBuilder $container, ?string $id): string
    {
        $method = $callable[1];
        if ($asClosure = 'Closure' === $class) {
            $class = ($callable[0] instanceof Reference ? $container->findDefinition($callable[0]) : $callable[0])->getClass();
        }
        $r = $container->getReflectionClass($class);
        if (null !== $id) {
            $id = \sprintf(' for service "%s"', $id);
        }
        if (!$asClosure) {
            $id = str_replace('%', '%%', (string) $id);
            if (!$r || !$r->isInterface()) {
                throw new RuntimeException(\sprintf("Cannot create adapter{$id} because \"%s\" is not an interface.", $class));
            }
            if (1 !== \count($method = $r->getMethods())) {
                throw new RuntimeException(\sprintf("Cannot create adapter{$id} because interface \"%s\" doesn't have exactly one method.", $class));
            }
            $method = $method[0]->name;
        } elseif (!$r || !$r->hasMethod($method)) {
            throw new RuntimeException("Cannot create lazy closure{$id} because its corresponding callable is invalid.");
        }
        $methodReflector = $r->getMethod($method);
        $code = ProxyHelper::exportSignature($methodReflector, \true, $args);
        if ($asClosure) {
            $code = ' { ' . preg_replace('/: static$/', ': \\' . $r->name, $code);
        } else {
            $code = ' implements \\' . $r->name . ' { ' . $code;
        }
        $code = 'new class(' . $initializer . ') extends \\' . self::class . $code . ' { ' . ($methodReflector->hasReturnType() && 'void' === (string) $methodReflector->getReturnType() ? '' : 'return ') . '$this->service->' . $callable[1] . '(' . $args . '); } ' . '}';
        return $asClosure ? '(' . $code . ')->' . $method . '(...)' : $code;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\DependencyInjection\Argument;

/**
 * Represents a collection of services found by tag name to lazily iterate over.
 *
 * @author Roland Franssen <franssen.roland@gmail.com>
 */
class TaggedIteratorArgument extends IteratorArgument
{
    private string $tag;
    private mixed $indexAttribute;
    private ?string $defaultIndexMethod;
    private ?string $defaultPriorityMethod;
    private bool $needsIndexes;
    private array $exclude;
    private bool $excludeSelf = \true;
    /**
     * @param string      $tag                   The name of the tag identifying the target services
     * @param string|null $indexAttribute        The name of the attribute that defines the key referencing each service in the tagged collection
     * @param string|null $defaultIndexMethod    The static method that should be called to get each service's key when their tag doesn't define the previous attribute
     * @param bool        $needsIndexes          Whether indexes are required and should be generated when computing the map
     * @param string|null $defaultPriorityMethod The static method that should be called to get each service's priority when their tag doesn't define the "priority" attribute
     * @param array       $exclude               Services to exclude from the iterator
     * @param bool        $excludeSelf           Whether to automatically exclude the referencing service from the iterator
     */
    public function __construct(string $tag, ?string $indexAttribute = null, ?string $defaultIndexMethod = null, bool $needsIndexes = \false, ?string $defaultPriorityMethod = null, array $exclude = [], bool $excludeSelf = \true)
    {
        parent::__construct([]);
        if (null === $indexAttribute && $needsIndexes) {
            $indexAttribute = preg_match('/[^.]++$/', $tag, $m) ? $m[0] : $tag;
        }
        $this->tag = $tag;
        $this->indexAttribute = $indexAttribute;
        $this->defaultIndexMethod = $defaultIndexMethod ?: ($indexAttribute ? 'getDefault' . str_replace(' ', '', ucwords(preg_replace('/[^a-zA-Z0-9\x7f-\xff]++/', ' ', $indexAttribute))) . 'Name' : null);
        $this->needsIndexes = $needsIndexes;
        $this->defaultPriorityMethod = $defaultPriorityMethod ?: ($indexAttribute ? 'getDefault' . str_replace(' ', '', ucwords(preg_replace('/[^a-zA-Z0-9\x7f-\xff]++/', ' ', $indexAttribute))) . 'Priority' : null);
        $this->exclude = $exclude;
        $this->excludeSelf = $excludeSelf;
    }
    /**
     * @return string
     */
    public function getTag()
    {
        return $this->tag;
    }
    public function getIndexAttribute(): ?string
    {
        return $this->indexAttribute;
    }
    public function getDefaultIndexMethod(): ?string
    {
        return $this->defaultIndexMethod;
    }
    public function needsIndexes(): bool
    {
        return $this->needsIndexes;
    }
    public function getDefaultPriorityMethod(): ?string
    {
        return $this->defaultPriorityMethod;
    }
    public function getExclude(): array
    {
        return $this->exclude;
    }
    public function excludeSelf(): bool
    {
        return $this->excludeSelf;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\DependencyInjection\Argument;

/**
 * Represents a complex argument containing nested values.
 *
 * @author Titouan Galopin <galopintitouan@gmail.com>
 */
interface ArgumentInterface
{
    public function getValues(): array;
    /**
     * @return void
     */
    public function setValues(array $values);
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\DependencyInjection\Argument;

use _ContaoManager\Symfony\Component\DependencyInjection\ServiceLocator as BaseServiceLocator;
/**
 * @author Nicolas Grekas <p@tchwork.com>
 *
 * @internal
 */
class ServiceLocator extends BaseServiceLocator
{
    private \Closure $factory;
    private array $serviceMap;
    private ?array $serviceTypes;
    public function __construct(\Closure $factory, array $serviceMap, ?array $serviceTypes = null)
    {
        $this->factory = $factory;
        $this->serviceMap = $serviceMap;
        $this->serviceTypes = $serviceTypes;
        parent::__construct($serviceMap);
    }
    public function get(string $id): mixed
    {
        return match (\count($this->serviceMap[$id] ?? [])) {
            0 => parent::get($id),
            1 => $this->serviceMap[$id][0],
            default => ($this->factory)(...$this->serviceMap[$id]),
        };
    }
    public function getProvidedServices(): array
    {
        return $this->serviceTypes ??= array_map(fn() => '?', $this->serviceMap);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\DependencyInjection\Argument;

use _ContaoManager\Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
/**
 * Represents a service wrapped in a memoizing closure.
 *
 * @author Nicolas Grekas <p@tchwork.com>
 */
class ServiceClosureArgument implements ArgumentInterface
{
    private array $values;
    public function __construct(mixed $value)
    {
        $this->values = [$value];
    }
    public function getValues(): array
    {
        return $this->values;
    }
    /**
     * @return void
     */
    public function setValues(array $values)
    {
        if ([0] !== array_keys($values)) {
            throw new InvalidArgumentException('A ServiceClosureArgument must hold one and only one value.');
        }
        $this->values = $values;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\DependencyInjection;

use Composer\InstalledVersions;
use _ContaoManager\Symfony\Component\Config\Resource\ClassExistenceResource;
use _ContaoManager\Symfony\Component\Config\Resource\ComposerResource;
use _ContaoManager\Symfony\Component\Config\Resource\DirectoryResource;
use _ContaoManager\Symfony\Component\Config\Resource\FileExistenceResource;
use _ContaoManager\Symfony\Component\Config\Resource\FileResource;
use _ContaoManager\Symfony\Component\Config\Resource\GlobResource;
use _ContaoManager\Symfony\Component\Config\Resource\ReflectionClassResource;
use _ContaoManager\Symfony\Component\Config\Resource\ResourceInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Argument\AbstractArgument;
use _ContaoManager\Symfony\Component\DependencyInjection\Argument\IteratorArgument;
use _ContaoManager\Symfony\Component\DependencyInjection\Argument\LazyClosure;
use _ContaoManager\Symfony\Component\DependencyInjection\Argument\RewindableGenerator;
use _ContaoManager\Symfony\Component\DependencyInjection\Argument\ServiceClosureArgument;
use _ContaoManager\Symfony\Component\DependencyInjection\Argument\ServiceLocator;
use _ContaoManager\Symfony\Component\DependencyInjection\Argument\ServiceLocatorArgument;
use _ContaoManager\Symfony\Component\DependencyInjection\Attribute\Target;
use _ContaoManager\Symfony\Component\DependencyInjection\Compiler\Compiler;
use _ContaoManager\Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Compiler\PassConfig;
use _ContaoManager\Symfony\Component\DependencyInjection\Compiler\ResolveEnvPlaceholdersPass;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\BadMethodCallException;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\LogicException;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\ParameterNotFoundException;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\RuntimeException;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\ServiceCircularReferenceException;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException;
use _ContaoManager\Symfony\Component\DependencyInjection\Extension\ExtensionInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\LazyProxy\Instantiator\InstantiatorInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\LazyProxy\Instantiator\LazyServiceInstantiator;
use _ContaoManager\Symfony\Component\DependencyInjection\LazyProxy\Instantiator\RealServiceInstantiator;
use _ContaoManager\Symfony\Component\DependencyInjection\ParameterBag\EnvPlaceholderParameterBag;
use _ContaoManager\Symfony\Component\DependencyInjection\ParameterBag\ParameterBag;
use _ContaoManager\Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface;
use _ContaoManager\Symfony\Component\ExpressionLanguage\Expression;
use _ContaoManager\Symfony\Component\ExpressionLanguage\ExpressionFunctionProviderInterface;
/**
 * ContainerBuilder is a DI container that provides an API to easily describe services.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class ContainerBuilder extends Container implements TaggedContainerInterface
{
    /**
     * @var array<string, ExtensionInterface>
     */
    private array $extensions = [];
    /**
     * @var array<string, ExtensionInterface>
     */
    private array $extensionsByNs = [];
    /**
     * @var array<string, Definition>
     */
    private array $definitions = [];
    /**
     * @var array<string, Alias>
     */
    private array $aliasDefinitions = [];
    /**
     * @var array<string, ResourceInterface>
     */
    private array $resources = [];
    /**
     * @var array<string, array<array<string, mixed>>>
     */
    private array $extensionConfigs = [];
    private Compiler $compiler;
    private bool $trackResources;
    private InstantiatorInterface $proxyInstantiator;
    private ExpressionLanguage $expressionLanguage;
    /**
     * @var ExpressionFunctionProviderInterface[]
     */
    private array $expressionLanguageProviders = [];
    /**
     * @var string[] with tag names used by findTaggedServiceIds
     */
    private array $usedTags = [];
    /**
     * @var string[][] a map of env var names to their placeholders
     */
    private array $envPlaceholders = [];
    /**
     * @var int[] a map of env vars to their resolution counter
     */
    private array $envCounters = [];
    /**
     * @var string[] the list of vendor directories
     */
    private array $vendors;
    /**
     * @var array<string, bool> the cache for paths being in vendor directories
     */
    private array $pathsInVendor = [];
    /**
     * @var array<string, ChildDefinition>
     */
    private array $autoconfiguredInstanceof = [];
    /**
     * @var array<string, callable>
     */
    private array $autoconfiguredAttributes = [];
    /**
     * @var array<string, bool>
     */
    private array $removedIds = [];
    /**
     * @var array<int, bool>
     */
    private array $removedBindingIds = [];
    private const INTERNAL_TYPES = ['int' => \true, 'float' => \true, 'string' => \true, 'bool' => \true, 'resource' => \true, 'object' => \true, 'array' => \true, 'null' => \true, 'callable' => \true, 'iterable' => \true, 'mixed' => \true];
    public function __construct(?ParameterBagInterface $parameterBag = null)
    {
        parent::__construct($parameterBag);
        $this->trackResources = interface_exists(ResourceInterface::class);
        $this->setDefinition('service_container', (new Definition(ContainerInterface::class))->setSynthetic(\true)->setPublic(\true));
    }
    /**
     * @var array<string, \ReflectionClass>
     */
    private array $classReflectors;
    /**
     * Sets the track resources flag.
     *
     * If you are not using the loaders and therefore don't want
     * to depend on the Config component, set this flag to false.
     *
     * @return void
     */
    public function setResourceTracking(bool $track)
    {
        $this->trackResources = $track;
    }
    /**
     * Checks if resources are tracked.
     */
    public function isTrackingResources(): bool
    {
        return $this->trackResources;
    }
    /**
     * Sets the instantiator to be used when fetching proxies.
     *
     * @return void
     */
    public function setProxyInstantiator(InstantiatorInterface $proxyInstantiator)
    {
        $this->proxyInstantiator = $proxyInstantiator;
    }
    /**
     * @return void
     */
    public function registerExtension(ExtensionInterface $extension)
    {
        $this->extensions[$extension->getAlias()] = $extension;
        if (\false !== $extension->getNamespace()) {
            $this->extensionsByNs[$extension->getNamespace() ?? ''] = $extension;
        }
    }
    /**
     * Returns an extension by alias or namespace.
     *
     * @throws LogicException if the extension is not registered
     */
    public function getExtension(string $name): ExtensionInterface
    {
        if (isset($this->extensions[$name])) {
            return $this->extensions[$name];
        }
        if (isset($this->extensionsByNs[$name])) {
            return $this->extensionsByNs[$name];
        }
        throw new LogicException(\sprintf('Container extension "%s" is not registered.', $name));
    }
    /**
     * Returns all registered extensions.
     *
     * @return array<string, ExtensionInterface>
     */
    public function getExtensions(): array
    {
        return $this->extensions;
    }
    /**
     * Checks if we have an extension.
     */
    public function hasExtension(string $name): bool
    {
        return isset($this->extensions[$name]) || isset($this->extensionsByNs[$name]);
    }
    /**
     * Returns an array of resources loaded to build this configuration.
     *
     * @return ResourceInterface[]
     */
    public function getResources(): array
    {
        return array_values($this->resources);
    }
    /**
     * @return $this
     */
    public function addResource(ResourceInterface $resource): static
    {
        if (!$this->trackResources) {
            return $this;
        }
        if ($resource instanceof GlobResource && $this->inVendors($resource->getPrefix())) {
            return $this;
        }
        $this->resources[(string) $resource] = $resource;
        return $this;
    }
    /**
     * Sets the resources for this configuration.
     *
     * @param array<string, ResourceInterface> $resources
     *
     * @return $this
     */
    public function setResources(array $resources): static
    {
        if (!$this->trackResources) {
            return $this;
        }
        $this->resources = $resources;
        return $this;
    }
    /**
     * Adds the object class hierarchy as resources.
     *
     * @param object|string $object An object instance or class name
     *
     * @return $this
     */
    public function addObjectResource(object|string $object): static
    {
        if ($this->trackResources) {
            if (\is_object($object)) {
                $object = $object::class;
            }
            if (!isset($this->classReflectors[$object])) {
                $this->classReflectors[$object] = new \ReflectionClass($object);
            }
            $class = $this->classReflectors[$object];
            foreach ($class->getInterfaceNames() as $name) {
                if (null === $interface =& $this->classReflectors[$name]) {
                    $interface = new \ReflectionClass($name);
                }
                $file = $interface->getFileName();
                if (\false !== $file && file_exists($file)) {
                    $this->fileExists($file);
                }
            }
            do {
                $file = $class->getFileName();
                if (\false !== $file && file_exists($file)) {
                    $this->fileExists($file);
                }
                foreach ($class->getTraitNames() as $name) {
                    $this->addObjectResource($name);
                }
            } while ($class = $class->getParentClass());
        }
        return $this;
    }
    /**
     * Retrieves the requested reflection class and registers it for resource tracking.
     *
     * @throws \ReflectionException when a parent class/interface/trait is not found and $throw is true
     *
     * @final
     */
    public function getReflectionClass(?string $class, bool $throw = \true): ?\ReflectionClass
    {
        if (!$class = $this->getParameterBag()->resolveValue($class)) {
            return null;
        }
        if (isset(self::INTERNAL_TYPES[$class])) {
            return null;
        }
        $resource = $classReflector = null;
        try {
            if (isset($this->classReflectors[$class])) {
                $classReflector = $this->classReflectors[$class];
            } elseif (class_exists(ClassExistenceResource::class)) {
                $resource = new ClassExistenceResource($class, \false);
                $classReflector = $resource->isFresh(0) ? \false : new \ReflectionClass($class);
            } else {
                $classReflector = class_exists($class) || interface_exists($class, \false) ? new \ReflectionClass($class) : \false;
            }
        } catch (\ReflectionException $e) {
            if ($throw) {
                throw $e;
            }
        }
        if ($this->trackResources) {
            if (!$classReflector) {
                $this->addResource($resource ?? new ClassExistenceResource($class, \false));
            } elseif (!$classReflector->isInternal()) {
                $path = $classReflector->getFileName();
                if (!$this->inVendors($path)) {
                    $this->addResource(new ReflectionClassResource($classReflector, $this->vendors));
                }
            }
            $this->classReflectors[$class] = $classReflector;
        }
        return $classReflector ?: null;
    }
    /**
     * Checks whether the requested file or directory exists and registers the result for resource tracking.
     *
     * @param string      $path          The file or directory path for which to check the existence
     * @param bool|string $trackContents Whether to track contents of the given resource. If a string is passed,
     *                                   it will be used as pattern for tracking contents of the requested directory
     *
     * @final
     */
    public function fileExists(string $path, bool|string $trackContents = \true): bool
    {
        $exists = file_exists($path);
        if (!$this->trackResources || $this->inVendors($path)) {
            return $exists;
        }
        if (!$exists) {
            $this->addResource(new FileExistenceResource($path));
            return $exists;
        }
        if (is_dir($path)) {
            if ($trackContents) {
                $this->addResource(new DirectoryResource($path, \is_string($trackContents) ? $trackContents : null));
            } else {
                $this->addResource(new GlobResource($path, '/*', \false));
            }
        } elseif ($trackContents) {
            $this->addResource(new FileResource($path));
        }
        return $exists;
    }
    /**
     * Loads the configuration for an extension.
     *
     * @param string                    $extension The extension alias or namespace
     * @param array<string, mixed>|null $values    An array of values that customizes the extension
     *
     * @return $this
     *
     * @throws BadMethodCallException When this ContainerBuilder is compiled
     * @throws \LogicException        if the extension is not registered
     */
    public function loadFromExtension(string $extension, ?array $values = null): static
    {
        if ($this->isCompiled()) {
            throw new BadMethodCallException('Cannot load from an extension on a compiled container.');
        }
        $namespace = $this->getExtension($extension)->getAlias();
        $this->extensionConfigs[$namespace][] = $values ?? [];
        return $this;
    }
    /**
     * Adds a compiler pass.
     *
     * @param string $type     The type of compiler pass
     * @param int    $priority Used to sort the passes
     *
     * @return $this
     */
    public function addCompilerPass(CompilerPassInterface $pass, string $type = PassConfig::TYPE_BEFORE_OPTIMIZATION, int $priority = 0): static
    {
        $this->getCompiler()->addPass($pass, $type, $priority);
        $this->addObjectResource($pass);
        return $this;
    }
    /**
     * Returns the compiler pass config which can then be modified.
     */
    public function getCompilerPassConfig(): PassConfig
    {
        return $this->getCompiler()->getPassConfig();
    }
    /**
     * Returns the compiler.
     */
    public function getCompiler(): Compiler
    {
        return $this->compiler ??= new Compiler();
    }
    /**
     * Sets a service.
     *
     * @return void
     *
     * @throws BadMethodCallException When this ContainerBuilder is compiled
     */
    public function set(string $id, ?object $service)
    {
        if ($this->isCompiled() && (isset($this->definitions[$id]) && !$this->definitions[$id]->isSynthetic())) {
            // setting a synthetic service on a compiled container is alright
            throw new BadMethodCallException(\sprintf('Setting service "%s" for an unknown or non-synthetic service definition on a compiled container is not allowed.', $id));
        }
        unset($this->definitions[$id], $this->aliasDefinitions[$id], $this->removedIds[$id]);
        parent::set($id, $service);
    }
    /**
     * Removes a service definition.
     *
     * @return void
     */
    public function removeDefinition(string $id)
    {
        if (isset($this->definitions[$id])) {
            unset($this->definitions[$id]);
            $this->removedIds[$id] = \true;
        }
    }
    public function has(string $id): bool
    {
        return isset($this->definitions[$id]) || isset($this->aliasDefinitions[$id]) || parent::has($id);
    }
    /**
     * @throws InvalidArgumentException          when no definitions are available
     * @throws ServiceCircularReferenceException When a circular reference is detected
     * @throws ServiceNotFoundException          When the service is not defined
     * @throws \Exception
     *
     * @see Reference
     */
    public function get(string $id, int $invalidBehavior = ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE): ?object
    {
        if ($this->isCompiled() && isset($this->removedIds[$id])) {
            return ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE >= $invalidBehavior ? parent::get($id) : null;
        }
        return $this->doGet($id, $invalidBehavior);
    }
    private function doGet(string $id, int $invalidBehavior = ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE, ?array &$inlineServices = null, bool $isConstructorArgument = \false): mixed
    {
        if (isset($inlineServices[$id])) {
            return $inlineServices[$id];
        }
        if (null === $inlineServices) {
            $isConstructorArgument = \true;
            $inlineServices = [];
        }
        try {
            if (ContainerInterface::IGNORE_ON_UNINITIALIZED_REFERENCE === $invalidBehavior) {
                return $this->privates[$id] ?? parent::get($id, $invalidBehavior);
            }
            if (null !== $service = $this->privates[$id] ?? parent::get($id, ContainerInterface::NULL_ON_INVALID_REFERENCE)) {
                return $service;
            }
        } catch (ServiceCircularReferenceException $e) {
            if ($isConstructorArgument) {
                throw $e;
            }
        }
        if (!isset($this->definitions[$id]) && isset($this->aliasDefinitions[$id])) {
            $alias = $this->aliasDefinitions[$id];
            if ($alias->isDeprecated()) {
                $deprecation = $alias->getDeprecation($id);
                trigger_deprecation($deprecation['package'], $deprecation['version'], $deprecation['message']);
            }
            return $this->doGet((string) $alias, $invalidBehavior, $inlineServices, $isConstructorArgument);
        }
        try {
            $definition = $this->getDefinition($id);
        } catch (ServiceNotFoundException $e) {
            if (ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE < $invalidBehavior) {
                return null;
            }
            throw $e;
        }
        if ($definition->hasErrors() && $e = $definition->getErrors()) {
            throw new RuntimeException(reset($e));
        }
        if ($isConstructorArgument) {
            $this->loading[$id] = \true;
        }
        try {
            return $this->createService($definition, $inlineServices, $isConstructorArgument, $id);
        } finally {
            if ($isConstructorArgument) {
                unset($this->loading[$id]);
            }
        }
    }
    /**
     * Merges a ContainerBuilder with the current ContainerBuilder configuration.
     *
     * Service definitions overrides the current defined ones.
     *
     * But for parameters, they are overridden by the current ones. It allows
     * the parameters passed to the container constructor to have precedence
     * over the loaded ones.
     *
     *     $container = new ContainerBuilder(new ParameterBag(['foo' => 'bar']));
     *     $loader = new LoaderXXX($container);
     *     $loader->load('resource_name');
     *     $container->register('foo', 'stdClass');
     *
     * In the above example, even if the loaded resource defines a foo
     * parameter, the value will still be 'bar' as defined in the ContainerBuilder
     * constructor.
     *
     * @return void
     *
     * @throws BadMethodCallException When this ContainerBuilder is compiled
     */
    public function merge(self $container)
    {
        if ($this->isCompiled()) {
            throw new BadMethodCallException('Cannot merge on a compiled container.');
        }
        foreach ($container->getDefinitions() as $id => $definition) {
            if (!$definition->hasTag('container.excluded') || !$this->has($id)) {
                $this->setDefinition($id, $definition);
            }
        }
        $this->addAliases($container->getAliases());
        $parameterBag = $this->getParameterBag();
        $otherBag = $container->getParameterBag();
        $parameterBag->add($otherBag->all());
        if ($parameterBag instanceof ParameterBag && $otherBag instanceof ParameterBag) {
            foreach ($otherBag->allDeprecated() as $name => $deprecated) {
                $parameterBag->deprecate($name, ...$deprecated);
            }
        }
        if ($this->trackResources) {
            foreach ($container->getResources() as $resource) {
                $this->addResource($resource);
            }
        }
        foreach ($this->extensions as $name => $extension) {
            if (!isset($this->extensionConfigs[$name])) {
                $this->extensionConfigs[$name] = [];
            }
            $this->extensionConfigs[$name] = array_merge($this->extensionConfigs[$name], $container->getExtensionConfig($name));
        }
        if ($parameterBag instanceof EnvPlaceholderParameterBag && $otherBag instanceof EnvPlaceholderParameterBag) {
            $envPlaceholders = $otherBag->getEnvPlaceholders();
            $parameterBag->mergeEnvPlaceholders($otherBag);
        } else {
            $envPlaceholders = [];
        }
        foreach ($container->envCounters as $env => $count) {
            if (!$count && !isset($envPlaceholders[$env])) {
                continue;
            }
            if (!isset($this->envCounters[$env])) {
                $this->envCounters[$env] = $count;
            } else {
                $this->envCounters[$env] += $count;
            }
        }
        foreach ($container->getAutoconfiguredInstanceof() as $interface => $childDefinition) {
            if (isset($this->autoconfiguredInstanceof[$interface])) {
                throw new InvalidArgumentException(\sprintf('"%s" has already been autoconfigured and merge() does not support merging autoconfiguration for the same class/interface.', $interface));
            }
            $this->autoconfiguredInstanceof[$interface] = $childDefinition;
        }
        foreach ($container->getAutoconfiguredAttributes() as $attribute => $configurator) {
            if (isset($this->autoconfiguredAttributes[$attribute])) {
                throw new InvalidArgumentException(\sprintf('"%s" has already been autoconfigured and merge() does not support merging autoconfiguration for the same attribute.', $attribute));
            }
            $this->autoconfiguredAttributes[$attribute] = $configurator;
        }
    }
    /**
     * Returns the configuration array for the given extension.
     *
     * @return array<array<string, mixed>>
     */
    public function getExtensionConfig(string $name): array
    {
        if (!isset($this->extensionConfigs[$name])) {
            $this->extensionConfigs[$name] = [];
        }
        return $this->extensionConfigs[$name];
    }
    /**
     * Prepends a config array to the configs of the given extension.
     *
     * @param array<string, mixed> $config
     *
     * @return void
     */
    public function prependExtensionConfig(string $name, array $config)
    {
        if (!isset($this->extensionConfigs[$name])) {
            $this->extensionConfigs[$name] = [];
        }
        array_unshift($this->extensionConfigs[$name], $config);
    }
    /**
     * Deprecates a service container parameter.
     *
     * @throws ParameterNotFoundException if the parameter is not defined
     */
    public function deprecateParameter(string $name, string $package, string $version, string $message = 'The parameter "%s" is deprecated.'): void
    {
        if (!$this->parameterBag instanceof ParameterBag) {
            throw new BadMethodCallException(\sprintf('The parameter bag must be an instance of "%s" to call "%s".', ParameterBag::class, __METHOD__));
        }
        $this->parameterBag->deprecate($name, $package, $version, $message);
    }
    /**
     * Compiles the container.
     *
     * This method passes the container to compiler
     * passes whose job is to manipulate and optimize
     * the container.
     *
     * The main compiler passes roughly do four things:
     *
     *  * The extension configurations are merged;
     *  * Parameter values are resolved;
     *  * The parameter bag is frozen;
     *  * Extension loading is disabled.
     *
     * @param bool $resolveEnvPlaceholders Whether %env()% parameters should be resolved at build time using
     *                                     the current env var values (true), or be resolved at runtime based
     *                                     on the environment (false). In general, this should be set to "true"
     *                                     when you want to use the current ContainerBuilder directly, and to
     *                                     "false" when the container is dumped instead.
     *
     * @return void
     */
    public function compile(bool $resolveEnvPlaceholders = \false)
    {
        $compiler = $this->getCompiler();
        if ($this->trackResources) {
            foreach ($compiler->getPassConfig()->getPasses() as $pass) {
                $this->addObjectResource($pass);
            }
        }
        $bag = $this->getParameterBag();
        if ($resolveEnvPlaceholders && $bag instanceof EnvPlaceholderParameterBag) {
            $compiler->addPass(new ResolveEnvPlaceholdersPass(), PassConfig::TYPE_AFTER_REMOVING, -1000);
        }
        $compiler->compile($this);
        foreach ($this->definitions as $id => $definition) {
            if ($this->trackResources && $definition->isLazy()) {
                $this->getReflectionClass($definition->getClass());
            }
        }
        $this->extensionConfigs = [];
        if ($bag instanceof EnvPlaceholderParameterBag) {
            if ($resolveEnvPlaceholders) {
                $this->parameterBag = new ParameterBag($this->resolveEnvPlaceholders($this->escapeParameters($bag->all()), \true));
            }
            $this->envPlaceholders = $bag->getEnvPlaceholders();
        }
        parent::compile();
        foreach ($this->definitions + $this->aliasDefinitions as $id => $definition) {
            if (!$definition->isPublic() || $definition->isPrivate()) {
                $this->removedIds[$id] = \true;
            }
        }
    }
    public function getServiceIds(): array
    {
        return array_map('strval', array_unique(array_merge(array_keys($this->getDefinitions()), array_keys($this->aliasDefinitions), parent::getServiceIds())));
    }
    /**
     * Gets removed service or alias ids.
     *
     * @return array<string, bool>
     */
    public function getRemovedIds(): array
    {
        return $this->removedIds;
    }
    /**
     * Adds the service aliases.
     *
     * @param array<string, string|Alias> $aliases
     *
     * @return void
     */
    public function addAliases(array $aliases)
    {
        foreach ($aliases as $alias => $id) {
            $this->setAlias($alias, $id);
        }
    }
    /**
     * Sets the service aliases.
     *
     * @param array<string, string|Alias> $aliases
     *
     * @return void
     */
    public function setAliases(array $aliases)
    {
        $this->aliasDefinitions = [];
        $this->addAliases($aliases);
    }
    /**
     * Sets an alias for an existing service.
     *
     * @throws InvalidArgumentException if the id is not a string or an Alias
     * @throws InvalidArgumentException if the alias is for itself
     */
    public function setAlias(string $alias, string|Alias $id): Alias
    {
        if ('' === $alias || '\\' === $alias[-1] || \strlen($alias) !== strcspn($alias, "\x00\r\n'")) {
            throw new InvalidArgumentException(\sprintf('Invalid alias id: "%s".', $alias));
        }
        if (\is_string($id)) {
            $id = new Alias($id);
        }
        if ($alias === (string) $id) {
            throw new InvalidArgumentException(\sprintf('An alias cannot reference itself, got a circular reference on "%s".', $alias));
        }
        unset($this->definitions[$alias], $this->removedIds[$alias]);
        return $this->aliasDefinitions[$alias] = $id;
    }
    /**
     * @return void
     */
    public function removeAlias(string $alias)
    {
        if (isset($this->aliasDefinitions[$alias])) {
            unset($this->aliasDefinitions[$alias]);
            $this->removedIds[$alias] = \true;
        }
    }
    public function hasAlias(string $id): bool
    {
        return isset($this->aliasDefinitions[$id]);
    }
    /**
     * @return array<string, Alias>
     */
    public function getAliases(): array
    {
        return $this->aliasDefinitions;
    }
    /**
     * @throws InvalidArgumentException if the alias does not exist
     */
    public function getAlias(string $id): Alias
    {
        if (!isset($this->aliasDefinitions[$id])) {
            throw new InvalidArgumentException(\sprintf('The service alias "%s" does not exist.', $id));
        }
        return $this->aliasDefinitions[$id];
    }
    /**
     * Registers a service definition.
     *
     * This methods allows for simple registration of service definition
     * with a fluid interface.
     */
    public function register(string $id, ?string $class = null): Definition
    {
        return $this->setDefinition($id, new Definition($class));
    }
    /**
     * Registers an autowired service definition.
     *
     * This method implements a shortcut for using setDefinition() with
     * an autowired definition.
     */
    public function autowire(string $id, ?string $class = null): Definition
    {
        return $this->setDefinition($id, (new Definition($class))->setAutowired(\true));
    }
    /**
     * Adds the service definitions.
     *
     * @param array<string, Definition> $definitions
     *
     * @return void
     */
    public function addDefinitions(array $definitions)
    {
        foreach ($definitions as $id => $definition) {
            $this->setDefinition($id, $definition);
        }
    }
    /**
     * Sets the service definitions.
     *
     * @param array<string, Definition> $definitions
     *
     * @return void
     */
    public function setDefinitions(array $definitions)
    {
        $this->definitions = [];
        $this->addDefinitions($definitions);
    }
    /**
     * Gets all service definitions.
     *
     * @return array<string, Definition>
     */
    public function getDefinitions(): array
    {
        return $this->definitions;
    }
    /**
     * Sets a service definition.
     *
     * @throws BadMethodCallException When this ContainerBuilder is compiled
     */
    public function setDefinition(string $id, Definition $definition): Definition
    {
        if ($this->isCompiled()) {
            throw new BadMethodCallException('Adding definition to a compiled container is not allowed.');
        }
        if ('' === $id || '\\' === $id[-1] || \strlen($id) !== strcspn($id, "\x00\r\n'")) {
            throw new InvalidArgumentException(\sprintf('Invalid service id: "%s".', $id));
        }
        unset($this->aliasDefinitions[$id], $this->removedIds[$id]);
        return $this->definitions[$id] = $definition;
    }
    /**
     * Returns true if a service definition exists under the given identifier.
     */
    public function hasDefinition(string $id): bool
    {
        return isset($this->definitions[$id]);
    }
    /**
     * Gets a service definition.
     *
     * @throws ServiceNotFoundException if the service definition does not exist
     */
    public function getDefinition(string $id): Definition
    {
        if (!isset($this->definitions[$id])) {
            throw new ServiceNotFoundException($id);
        }
        return $this->definitions[$id];
    }
    /**
     * Gets a service definition by id or alias.
     *
     * The method "unaliases" recursively to return a Definition instance.
     *
     * @throws ServiceNotFoundException if the service definition does not exist
     */
    public function findDefinition(string $id): Definition
    {
        $seen = [];
        while (isset($this->aliasDefinitions[$id])) {
            $id = (string) $this->aliasDefinitions[$id];
            if (isset($seen[$id])) {
                $seen = array_values($seen);
                $seen = \array_slice($seen, array_search($id, $seen));
                $seen[] = $id;
                throw new ServiceCircularReferenceException($id, $seen);
            }
            $seen[$id] = $id;
        }
        return $this->getDefinition($id);
    }
    /**
     * Creates a service for a service definition.
     *
     * @throws RuntimeException         When the factory definition is incomplete
     * @throws RuntimeException         When the service is a synthetic service
     * @throws InvalidArgumentException When configure callable is not callable
     */
    private function createService(Definition $definition, array &$inlineServices, bool $isConstructorArgument = \false, ?string $id = null, bool|object $tryProxy = \true): mixed
    {
        if (null === $id && isset($inlineServices[$h = spl_object_hash($definition)])) {
            return $inlineServices[$h];
        }
        if ($definition instanceof ChildDefinition) {
            throw new RuntimeException(\sprintf('Constructing service "%s" from a parent definition is not supported at build time.', $id));
        }
        if ($definition->isSynthetic()) {
            throw new RuntimeException(\sprintf('You have requested a synthetic service ("%s"). The DIC does not know how to construct this service.', $id));
        }
        if ($definition->isDeprecated()) {
            $deprecation = $definition->getDeprecation($id);
            trigger_deprecation($deprecation['package'], $deprecation['version'], $deprecation['message']);
        }
        $parameterBag = $this->getParameterBag();
        $class = $parameterBag->resolveValue($definition->getClass()) ?: (['Closure', 'fromCallable'] === $definition->getFactory() ? 'Closure' : null);
        if (['Closure', 'fromCallable'] === $definition->getFactory() && ('Closure' !== $class || $definition->isLazy())) {
            $callable = $parameterBag->unescapeValue($parameterBag->resolveValue($definition->getArgument(0)));
            if ($callable instanceof Reference || $callable instanceof Definition) {
                $callable = [$callable, '__invoke'];
            }
            if (\is_array($callable) && ('Closure' !== $class || $callable[0] instanceof Reference || $callable[0] instanceof Definition && !isset($inlineServices[spl_object_hash($callable[0])]))) {
                $initializer = function () use ($callable, &$inlineServices) {
                    return $this->doResolveServices($callable[0], $inlineServices);
                };
                $proxy = eval('return ' . LazyClosure::getCode('$initializer', $callable, $class, $this, $id) . ';');
                $this->shareService($definition, $proxy, $id, $inlineServices);
                return $proxy;
            }
        }
        if (\true === $tryProxy && $definition->isLazy() && ['Closure', 'fromCallable'] !== $definition->getFactory() && !$tryProxy = !($proxy = $this->proxyInstantiator ??= new LazyServiceInstantiator()) || $proxy instanceof RealServiceInstantiator) {
            $proxy = $proxy->instantiateProxy($this, (clone $definition)->setClass($class)->setTags(($definition->hasTag('proxy') ? ['proxy' => $parameterBag->resolveValue($definition->getTag('proxy'))] : []) + $definition->getTags()), $id, function ($proxy = \false) use ($definition, &$inlineServices, $id) {
                return $this->createService($definition, $inlineServices, \true, $id, $proxy);
            });
            $this->shareService($definition, $proxy, $id, $inlineServices);
            return $proxy;
        }
        if (null !== $definition->getFile()) {
            require_once $parameterBag->resolveValue($definition->getFile());
        }
        $arguments = $definition->getArguments();
        if (null !== $factory = $definition->getFactory()) {
            if (\is_array($factory)) {
                $factory = [$this->doResolveServices($parameterBag->resolveValue($factory[0]), $inlineServices, $isConstructorArgument), $factory[1]];
            } elseif (!\is_string($factory)) {
                throw new RuntimeException(\sprintf('Cannot create service "%s" because of invalid factory.', $id));
            } elseif (str_starts_with($factory, '@=')) {
                $factory = fn(ServiceLocator $arguments) => $this->getExpressionLanguage()->evaluate(substr($factory, 2), ['container' => $this, 'args' => $arguments]);
                $arguments = [new ServiceLocatorArgument($arguments)];
            }
        }
        $arguments = $this->doResolveServices($parameterBag->unescapeValue($parameterBag->resolveValue($arguments)), $inlineServices, $isConstructorArgument);
        if (null !== $id && $definition->isShared() && (isset($this->services[$id]) || isset($this->privates[$id])) && (\true === $tryProxy || !$definition->isLazy())) {
            return $this->services[$id] ?? $this->privates[$id];
        }
        if (!array_is_list($arguments)) {
            $arguments = array_combine(array_map(fn($k) => preg_replace('/^.*\$/', '', $k), array_keys($arguments)), $arguments);
        }
        if (null !== $factory) {
            $service = $factory(...$arguments);
            if (!$definition->isDeprecated() && \is_array($factory) && \is_string($factory[0])) {
                $r = new \ReflectionClass($factory[0]);
                if (0 < strpos($r->getDocComment() ?: '', "\n * @deprecated ")) {
                    trigger_deprecation('', '', 'The "%s" service relies on the deprecated "%s" factory class. It should either be deprecated or its factory upgraded.', $id, $r->name);
                }
            }
        } else {
            $r = new \ReflectionClass($class);
            if (\is_object($tryProxy)) {
                if ($r->getConstructor()) {
                    $tryProxy->__construct(...$arguments);
                }
                $service = $tryProxy;
            } else {
                $service = $r->getConstructor() ? $r->newInstanceArgs($arguments) : $r->newInstance();
            }
            if (!$definition->isDeprecated() && 0 < strpos($r->getDocComment() ?: '', "\n * @deprecated ")) {
                trigger_deprecation('', '', 'The "%s" service relies on the deprecated "%s" class. It should either be deprecated or its implementation upgraded.', $id, $r->name);
            }
        }
        $lastWitherIndex = null;
        foreach ($definition->getMethodCalls() as $k => $call) {
            if ($call[2] ?? \false) {
                $lastWitherIndex = $k;
            }
        }
        if (null === $lastWitherIndex && (\true === $tryProxy || !$definition->isLazy())) {
            // share only if proxying failed, or if not a proxy, and if no withers are found
            $this->shareService($definition, $service, $id, $inlineServices);
        }
        $properties = $this->doResolveServices($parameterBag->unescapeValue($parameterBag->resolveValue($definition->getProperties())), $inlineServices);
        foreach ($properties as $name => $value) {
            $service->{$name} = $value;
        }
        foreach ($definition->getMethodCalls() as $k => $call) {
            $service = $this->callMethod($service, $call, $inlineServices);
            if ($lastWitherIndex === $k && (\true === $tryProxy || !$definition->isLazy())) {
                // share only if proxying failed, or if not a proxy, and this is the last wither
                $this->shareService($definition, $service, $id, $inlineServices);
            }
        }
        if ($callable = $definition->getConfigurator()) {
            if (\is_array($callable)) {
                $callable[0] = $parameterBag->resolveValue($callable[0]);
                if ($callable[0] instanceof Reference) {
                    $callable[0] = $this->doGet((string) $callable[0], $callable[0]->getInvalidBehavior(), $inlineServices);
                } elseif ($callable[0] instanceof Definition) {
                    $callable[0] = $this->createService($callable[0], $inlineServices);
                }
            }
            if (!\is_callable($callable)) {
                throw new InvalidArgumentException(\sprintf('The configure callable for class "%s" is not a callable.', get_debug_type($service)));
            }
            $callable($service);
        }
        return $service;
    }
    /**
     * Replaces service references by the real service instance and evaluates expressions.
     *
     * @return mixed The same value with all service references replaced by
     *               the real service instances and all expressions evaluated
     */
    public function resolveServices(mixed $value): mixed
    {
        return $this->doResolveServices($value);
    }
    private function doResolveServices(mixed $value, array &$inlineServices = [], bool $isConstructorArgument = \false): mixed
    {
        if (\is_array($value)) {
            foreach ($value as $k => $v) {
                $value[$k] = $this->doResolveServices($v, $inlineServices, $isConstructorArgument);
            }
        } elseif ($value instanceof ServiceClosureArgument) {
            $reference = $value->getValues()[0];
            $value = fn() => $this->resolveServices($reference);
        } elseif ($value instanceof IteratorArgument) {
            $value = new RewindableGenerator(function () use ($value, &$inlineServices) {
                foreach ($value->getValues() as $k => $v) {
                    foreach (self::getServiceConditionals($v) as $s) {
                        if (!$this->has($s)) {
                            continue 2;
                        }
                    }
                    foreach (self::getInitializedConditionals($v) as $s) {
                        if (!$this->doGet($s, ContainerInterface::IGNORE_ON_UNINITIALIZED_REFERENCE, $inlineServices)) {
                            continue 2;
                        }
                    }
                    yield $k => $this->doResolveServices($v, $inlineServices);
                }
            }, function () use ($value): int {
                $count = 0;
                foreach ($value->getValues() as $v) {
                    foreach (self::getServiceConditionals($v) as $s) {
                        if (!$this->has($s)) {
                            continue 2;
                        }
                    }
                    foreach (self::getInitializedConditionals($v) as $s) {
                        if (!$this->doGet($s, ContainerInterface::IGNORE_ON_UNINITIALIZED_REFERENCE)) {
                            continue 2;
                        }
                    }
                    ++$count;
                }
                return $count;
            });
        } elseif ($value instanceof ServiceLocatorArgument) {
            $refs = $types = [];
            foreach ($value->getValues() as $k => $v) {
                $refs[$k] = [$v, null];
                $types[$k] = $v instanceof TypedReference ? $v->getType() : '?';
            }
            $value = new ServiceLocator($this->resolveServices(...), $refs, $types);
        } elseif ($value instanceof Reference) {
            $value = $this->doGet((string) $value, $value->getInvalidBehavior(), $inlineServices, $isConstructorArgument);
        } elseif ($value instanceof Definition) {
            $value = $this->createService($value, $inlineServices, $isConstructorArgument);
        } elseif ($value instanceof Parameter) {
            $value = $this->getParameter((string) $value);
        } elseif ($value instanceof Expression) {
            $value = $this->getExpressionLanguage()->evaluate($value, ['container' => $this]);
        } elseif ($value instanceof AbstractArgument) {
            throw new RuntimeException($value->getTextWithContext());
        }
        return $value;
    }
    /**
     * Returns service ids for a given tag.
     *
     * Example:
     *
     *     $container->register('foo')->addTag('my.tag', ['hello' => 'world']);
     *
     *     $serviceIds = $container->findTaggedServiceIds('my.tag');
     *     foreach ($serviceIds as $serviceId => $tags) {
     *         foreach ($tags as $tag) {
     *             echo $tag['hello'];
     *         }
     *     }
     *
     * @return array<string, array> An array of tags with the tagged service as key, holding a list of attribute arrays
     */
    public function findTaggedServiceIds(string $name, bool $throwOnAbstract = \false): array
    {
        $this->usedTags[] = $name;
        $tags = [];
        foreach ($this->getDefinitions() as $id => $definition) {
            if ($definition->hasTag($name) && !$definition->hasTag('container.excluded')) {
                if ($throwOnAbstract && $definition->isAbstract()) {
                    throw new InvalidArgumentException(\sprintf('The service "%s" tagged "%s" must not be abstract.', $id, $name));
                }
                $tags[$id] = $definition->getTag($name);
            }
        }
        return $tags;
    }
    /**
     * Returns all tags the defined services use.
     *
     * @return string[]
     */
    public function findTags(): array
    {
        $tags = [];
        foreach ($this->getDefinitions() as $id => $definition) {
            $tags[] = array_keys($definition->getTags());
        }
        return array_unique(array_merge([], ...$tags));
    }
    /**
     * Returns all tags not queried by findTaggedServiceIds.
     *
     * @return string[]
     */
    public function findUnusedTags(): array
    {
        return array_values(array_diff($this->findTags(), $this->usedTags));
    }
    /**
     * @return void
     */
    public function addExpressionLanguageProvider(ExpressionFunctionProviderInterface $provider)
    {
        $this->expressionLanguageProviders[] = $provider;
    }
    /**
     * @return ExpressionFunctionProviderInterface[]
     */
    public function getExpressionLanguageProviders(): array
    {
        return $this->expressionLanguageProviders;
    }
    /**
     * Returns a ChildDefinition that will be used for autoconfiguring the interface/class.
     */
    public function registerForAutoconfiguration(string $interface): ChildDefinition
    {
        if (!isset($this->autoconfiguredInstanceof[$interface])) {
            $this->autoconfiguredInstanceof[$interface] = new ChildDefinition('');
        }
        return $this->autoconfiguredInstanceof[$interface];
    }
    /**
     * Registers an attribute that will be used for autoconfiguring annotated classes.
     *
     * The third argument passed to the callable is the reflector of the
     * class/method/property/parameter that the attribute targets. Using one or many of
     * \ReflectionClass|\ReflectionMethod|\ReflectionProperty|\ReflectionParameter as a type-hint
     * for this argument allows filtering which attributes should be passed to the callable.
     *
     * @template T
     *
     * @param class-string<T>                                $attributeClass
     * @param callable(ChildDefinition, T, \Reflector): void $configurator
     */
    public function registerAttributeForAutoconfiguration(string $attributeClass, callable $configurator): void
    {
        $this->autoconfiguredAttributes[$attributeClass] = $configurator;
    }
    /**
     * Registers an autowiring alias that only binds to a specific argument name.
     *
     * The argument name is derived from $name if provided (from $id otherwise)
     * using camel case: "foo.bar" or "foo_bar" creates an alias bound to
     * "$fooBar"-named arguments with $type as type-hint. Such arguments will
     * receive the service $id when autowiring is used.
     */
    public function registerAliasForArgument(string $id, string $type, ?string $name = null): Alias
    {
        $parsedName = (new Target($name ??= $id))->getParsedName();
        if (!preg_match('/^[a-zA-Z_\x7f-\xff]/', $parsedName)) {
            if ($id !== $name) {
                $id = \sprintf(' for service "%s"', $id);
            }
            throw new InvalidArgumentException(\sprintf('Invalid argument name "%s"' . $id . ': the first character must be a letter.', $name));
        }
        if ($parsedName !== $name) {
            $this->setAlias('.' . $type . ' $' . $name, $type . ' $' . $parsedName);
        }
        return $this->setAlias($type . ' $' . $parsedName, $id);
    }
    /**
     * Returns an array of ChildDefinition[] keyed by interface.
     *
     * @return array<string, ChildDefinition>
     */
    public function getAutoconfiguredInstanceof(): array
    {
        return $this->autoconfiguredInstanceof;
    }
    /**
     * @return array<string, callable>
     */
    public function getAutoconfiguredAttributes(): array
    {
        return $this->autoconfiguredAttributes;
    }
    /**
     * Resolves env parameter placeholders in a string or an array.
     *
     * @param string|true|null $format    A sprintf() format returning the replacement for each env var name or
     *                                    null to resolve back to the original "%env(VAR)%" format or
     *                                    true to resolve to the actual values of the referenced env vars
     * @param array            &$usedEnvs Env vars found while resolving are added to this array
     *
     * @return mixed The value with env parameters resolved if a string or an array is passed
     */
    public function resolveEnvPlaceholders(mixed $value, string|bool|null $format = null, ?array &$usedEnvs = null): mixed
    {
        $bag = $this->getParameterBag();
        if (\true === $format ??= '%%env(%s)%%') {
            $value = $bag->resolveValue($value);
        }
        if ($value instanceof Definition) {
            $value = (array) $value;
        }
        if (\is_array($value)) {
            $result = [];
            foreach ($value as $k => $v) {
                $result[\is_string($k) ? $this->resolveEnvPlaceholders($k, $format, $usedEnvs) : $k] = $this->resolveEnvPlaceholders($v, $format, $usedEnvs);
            }
            return $result;
        }
        if (!\is_string($value) || 38 > \strlen($value) || \false === stripos($value, 'env_')) {
            return $value;
        }
        $envPlaceholders = $bag instanceof EnvPlaceholderParameterBag ? $bag->getEnvPlaceholders() : $this->envPlaceholders;
        $completed = \false;
        preg_match_all('/env_[a-f0-9]{16}_\w+_[a-f0-9]{32}/Ui', $value, $matches);
        $usedPlaceholders = array_flip($matches[0]);
        foreach ($envPlaceholders as $env => $placeholders) {
            foreach ($placeholders as $placeholder) {
                if (isset($usedPlaceholders[$placeholder])) {
                    if (\true === $format) {
                        $resolved = $bag->escapeValue($this->getEnv($env));
                    } else {
                        $resolved = \sprintf($format, $env);
                    }
                    if ($placeholder === $value) {
                        $value = $resolved;
                        $completed = \true;
                    } else {
                        if (!\is_string($resolved) && !is_numeric($resolved)) {
                            throw new RuntimeException(\sprintf('A string value must be composed of strings and/or numbers, but found parameter "env(%s)" of type "%s" inside string value "%s".', $env, get_debug_type($resolved), $this->resolveEnvPlaceholders($value)));
                        }
                        $value = str_ireplace($placeholder, $resolved, $value);
                    }
                    $usedEnvs[$env] = $env;
                    $this->envCounters[$env] = isset($this->envCounters[$env]) ? 1 + $this->envCounters[$env] : 1;
                    if ($completed) {
                        break 2;
                    }
                }
            }
        }
        return $value;
    }
    /**
     * Get statistics about env usage.
     *
     * @return int[] The number of time each env vars has been resolved
     */
    public function getEnvCounters(): array
    {
        $bag = $this->getParameterBag();
        $envPlaceholders = $bag instanceof EnvPlaceholderParameterBag ? $bag->getEnvPlaceholders() : $this->envPlaceholders;
        foreach ($envPlaceholders as $env => $placeholders) {
            if (!isset($this->envCounters[$env])) {
                $this->envCounters[$env] = 0;
            }
        }
        return $this->envCounters;
    }
    /**
     * @final
     */
    public function log(CompilerPassInterface $pass, string $message): void
    {
        $this->getCompiler()->log($pass, $this->resolveEnvPlaceholders($message));
    }
    /**
     * Checks whether a class is available and will remain available in the "no-dev" mode of Composer.
     *
     * When parent packages are provided and if any of them is in dev-only mode,
     * the class will be considered available even if it is also in dev-only mode.
     *
     * @throws \LogicException If dependencies have been installed with Composer 1
     */
    final public static function willBeAvailable(string $package, string $class, array $parentPackages): bool
    {
        if (!class_exists(InstalledVersions::class)) {
            throw new \LogicException(\sprintf('Calling "%s" when dependencies have been installed with Composer 1 is not supported. Consider upgrading to Composer 2.', __METHOD__));
        }
        if (!class_exists($class) && !interface_exists($class, \false) && !trait_exists($class, \false)) {
            return \false;
        }
        if (!InstalledVersions::isInstalled($package) || InstalledVersions::isInstalled($package, \false)) {
            return \true;
        }
        // the package is installed but in dev-mode only, check if this applies to one of the parent packages too
        $rootPackage = InstalledVersions::getRootPackage()['name'] ?? '';
        if ('symfony/symfony' === $rootPackage) {
            return \true;
        }
        foreach ($parentPackages as $parentPackage) {
            if ($rootPackage === $parentPackage || InstalledVersions::isInstalled($parentPackage) && !InstalledVersions::isInstalled($parentPackage, \false)) {
                return \true;
            }
        }
        return \false;
    }
    /**
     * Gets removed binding ids.
     *
     * @return array<int, bool>
     *
     * @internal
     */
    public function getRemovedBindingIds(): array
    {
        return $this->removedBindingIds;
    }
    /**
     * Removes bindings for a service.
     *
     * @internal
     */
    public function removeBindings(string $id): void
    {
        if ($this->hasDefinition($id)) {
            foreach ($this->getDefinition($id)->getBindings() as $key => $binding) {
                [, $bindingId] = $binding->getValues();
                $this->removedBindingIds[(int) $bindingId] = \true;
            }
        }
    }
    /**
     * @return string[]
     *
     * @internal
     */
    public static function getServiceConditionals(mixed $value): array
    {
        $services = [];
        if (\is_array($value)) {
            foreach ($value as $v) {
                $services = array_unique(array_merge($services, self::getServiceConditionals($v)));
            }
        } elseif ($value instanceof Reference && ContainerInterface::IGNORE_ON_INVALID_REFERENCE === $value->getInvalidBehavior()) {
            $services[] = (string) $value;
        }
        return $services;
    }
    /**
     * @return string[]
     *
     * @internal
     */
    public static function getInitializedConditionals(mixed $value): array
    {
        $services = [];
        if (\is_array($value)) {
            foreach ($value as $v) {
                $services = array_unique(array_merge($services, self::getInitializedConditionals($v)));
            }
        } elseif ($value instanceof Reference && ContainerInterface::IGNORE_ON_UNINITIALIZED_REFERENCE === $value->getInvalidBehavior()) {
            $services[] = (string) $value;
        }
        return $services;
    }
    /**
     * Computes a reasonably unique hash of a serializable value.
     */
    public static function hash(mixed $value): string
    {
        $hash = substr(base64_encode(hash('sha256', serialize($value), \true)), 0, 7);
        return str_replace(['/', '+'], ['.', '_'], $hash);
    }
    protected function getEnv(string $name): mixed
    {
        $value = parent::getEnv($name);
        $bag = $this->getParameterBag();
        if (!\is_string($value) || !$bag instanceof EnvPlaceholderParameterBag) {
            return $value;
        }
        $envPlaceholders = $bag->getEnvPlaceholders();
        if (isset($envPlaceholders[$name][$value])) {
            $bag = new ParameterBag($bag->all());
            return $bag->unescapeValue($bag->get("env({$name})"));
        }
        foreach ($envPlaceholders as $env => $placeholders) {
            if (isset($placeholders[$value])) {
                return $this->getEnv($env);
            }
        }
        $this->resolving["env({$name})"] = \true;
        try {
            return $bag->unescapeValue($this->resolveEnvPlaceholders($bag->escapeValue($value), \true));
        } finally {
            unset($this->resolving["env({$name})"]);
        }
    }
    private function callMethod(object $service, array $call, array &$inlineServices): mixed
    {
        foreach (self::getServiceConditionals($call[1]) as $s) {
            if (!$this->has($s)) {
                return $service;
            }
        }
        foreach (self::getInitializedConditionals($call[1]) as $s) {
            if (!$this->doGet($s, ContainerInterface::IGNORE_ON_UNINITIALIZED_REFERENCE, $inlineServices)) {
                return $service;
            }
        }
        $result = $service->{$call[0]}(...$this->doResolveServices($this->getParameterBag()->unescapeValue($this->getParameterBag()->resolveValue($call[1])), $inlineServices));
        return empty($call[2]) ? $service : $result;
    }
    private function shareService(Definition $definition, mixed $service, ?string $id, array &$inlineServices): void
    {
        $inlineServices[$id ?? spl_object_hash($definition)] = $service;
        if (null !== $id && $definition->isShared()) {
            if ($definition->isPrivate() && $this->isCompiled()) {
                $this->privates[$id] = $service;
            } else {
                $this->services[$id] = $service;
            }
            unset($this->loading[$id]);
        }
    }
    private function getExpressionLanguage(): ExpressionLanguage
    {
        if (!isset($this->expressionLanguage)) {
            if (!class_exists(Expression::class)) {
                throw new LogicException('Expressions cannot be used without the ExpressionLanguage component. Try running "composer require symfony/expression-language".');
            }
            $this->expressionLanguage = new ExpressionLanguage(null, $this->expressionLanguageProviders, null, $this->getEnv(...));
        }
        return $this->expressionLanguage;
    }
    private function inVendors(string $path): bool
    {
        $path = is_file($path) ? \dirname($path) : $path;
        if (isset($this->pathsInVendor[$path])) {
            return $this->pathsInVendor[$path];
        }
        $this->vendors ??= (new ComposerResource())->getVendors();
        $path = realpath($path) ?: $path;
        if (isset($this->pathsInVendor[$path])) {
            return $this->pathsInVendor[$path];
        }
        foreach ($this->vendors as $vendor) {
            if (str_starts_with($path, $vendor) && \false !== strpbrk(substr($path, \strlen($vendor), 1), '/' . \DIRECTORY_SEPARATOR)) {
                $this->addResource(new FileResource($vendor . '/composer/installed.json'));
                return $this->pathsInVendor[$path] = \true;
            }
        }
        return $this->pathsInVendor[$path] = \false;
    }
    private function escapeParameters(array $parameters): array
    {
        $params = [];
        foreach ($parameters as $k => $v) {
            $params[$k] = match (\true) {
                \is_array($v) => $this->escapeParameters($v),
                \is_string($v) => str_replace('%', '%%', $v),
                default => $v,
            };
        }
        return $params;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\DependencyInjection;

use _ContaoManager\Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\OutOfBoundsException;
/**
 * This definition extends another definition.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
class ChildDefinition extends Definition
{
    private string $parent;
    /**
     * @param string $parent The id of Definition instance to decorate
     */
    public function __construct(string $parent)
    {
        $this->parent = $parent;
    }
    /**
     * Returns the Definition to inherit from.
     */
    public function getParent(): string
    {
        return $this->parent;
    }
    /**
     * Sets the Definition to inherit from.
     *
     * @return $this
     */
    public function setParent(string $parent): static
    {
        $this->parent = $parent;
        return $this;
    }
    /**
     * Gets an argument to pass to the service constructor/factory method.
     *
     * If replaceArgument() has been used to replace an argument, this method
     * will return the replacement value.
     *
     * @throws OutOfBoundsException When the argument does not exist
     */
    public function getArgument(int|string $index): mixed
    {
        if (\array_key_exists('index_' . $index, $this->arguments)) {
            return $this->arguments['index_' . $index];
        }
        return parent::getArgument($index);
    }
    /**
     * You should always use this method when overwriting existing arguments
     * of the parent definition.
     *
     * If you directly call setArguments() keep in mind that you must follow
     * certain conventions when you want to overwrite the arguments of the
     * parent definition, otherwise your arguments will only be appended.
     *
     * @return $this
     *
     * @throws InvalidArgumentException when $index isn't an integer
     */
    public function replaceArgument(int|string $index, mixed $value): static
    {
        if (\is_int($index)) {
            $this->arguments['index_' . $index] = $value;
        } elseif (str_starts_with($index, '$')) {
            $this->arguments[$index] = $value;
        } else {
            throw new InvalidArgumentException('The argument must be an existing index or the name of a constructor\'s parameter.');
        }
        return $this;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\DependencyInjection;

/**
 * Reference represents a service reference.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class Reference
{
    private string $id;
    private int $invalidBehavior;
    public function __construct(string $id, int $invalidBehavior = ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE)
    {
        $this->id = $id;
        $this->invalidBehavior = $invalidBehavior;
    }
    public function __toString(): string
    {
        return $this->id;
    }
    /**
     * Returns the behavior to be used when the service does not exist.
     */
    public function getInvalidBehavior(): int
    {
        return $this->invalidBehavior;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\DependencyInjection\ParameterBag;

use _ContaoManager\Symfony\Component\DependencyInjection\Exception\LogicException;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\ParameterNotFoundException;
/**
 * ParameterBagInterface is the interface implemented by objects that manage service container parameters.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
interface ParameterBagInterface
{
    /**
     * Clears all parameters.
     *
     * @return void
     *
     * @throws LogicException if the ParameterBagInterface cannot be cleared
     */
    public function clear();
    /**
     * Adds parameters to the service container parameters.
     *
     * @return void
     *
     * @throws LogicException if the parameter cannot be added
     */
    public function add(array $parameters);
    /**
     * Gets the service container parameters.
     */
    public function all(): array;
    /**
     * Gets a service container parameter.
     *
     * @throws ParameterNotFoundException if the parameter is not defined
     */
    public function get(string $name): array|bool|string|int|float|\UnitEnum|null;
    /**
     * Removes a parameter.
     *
     * @return void
     */
    public function remove(string $name);
    /**
     * Sets a service container parameter.
     *
     * @return void
     *
     * @throws LogicException if the parameter cannot be set
     */
    public function set(string $name, array|bool|string|int|float|\UnitEnum|null $value);
    /**
     * Returns true if a parameter name is defined.
     */
    public function has(string $name): bool;
    /**
     * Replaces parameter placeholders (%name%) by their values for all parameters.
     *
     * @return void
     */
    public function resolve();
    /**
     * Replaces parameter placeholders (%name%) by their values.
     *
     * @return mixed
     *
     * @throws ParameterNotFoundException if a placeholder references a parameter that does not exist
     */
    public function resolveValue(mixed $value);
    /**
     * Escape parameter placeholders %.
     */
    public function escapeValue(mixed $value): mixed;
    /**
     * Unescape parameter placeholders %.
     */
    public function unescapeValue(mixed $value): mixed;
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\DependencyInjection\ParameterBag;

use _ContaoManager\Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\RuntimeException;
/**
 * @author Nicolas Grekas <p@tchwork.com>
 */
class EnvPlaceholderParameterBag extends ParameterBag
{
    private string $envPlaceholderUniquePrefix;
    private array $envPlaceholders = [];
    private array $unusedEnvPlaceholders = [];
    private array $providedTypes = [];
    private static int $counter = 0;
    public function get(string $name): array|bool|string|int|float|\UnitEnum|null
    {
        if (str_starts_with($name, 'env(') && str_ends_with($name, ')') && 'env()' !== $name) {
            $env = substr($name, 4, -1);
            if (isset($this->envPlaceholders[$env])) {
                foreach ($this->envPlaceholders[$env] as $placeholder) {
                    return $placeholder;
                    // return first result
                }
            }
            if (isset($this->unusedEnvPlaceholders[$env])) {
                foreach ($this->unusedEnvPlaceholders[$env] as $placeholder) {
                    return $placeholder;
                    // return first result
                }
            }
            if (!preg_match('/^(?:[-.\w\\\\]*+:)*+\w*+$/', $env)) {
                throw new InvalidArgumentException(\sprintf('Invalid %s name: only "word" characters are allowed.', $name));
            }
            if ($this->has($name) && null !== ($defaultValue = parent::get($name)) && !\is_string($defaultValue)) {
                throw new RuntimeException(\sprintf('The default value of an env() parameter must be a string or null, but "%s" given to "%s".', get_debug_type($defaultValue), $name));
            }
            $uniqueName = hash('xxh128', $name . '_' . self::$counter++);
            $placeholder = \sprintf('%s_%s_%s', $this->getEnvPlaceholderUniquePrefix(), strtr($env, ':-.\\', '____'), $uniqueName);
            $this->envPlaceholders[$env][$placeholder] = $placeholder;
            return $placeholder;
        }
        return parent::get($name);
    }
    /**
     * Gets the common env placeholder prefix for env vars created by this bag.
     */
    public function getEnvPlaceholderUniquePrefix(): string
    {
        if (!isset($this->envPlaceholderUniquePrefix)) {
            $reproducibleEntropy = unserialize(serialize($this->parameters));
            array_walk_recursive($reproducibleEntropy, function (&$v) {
                $v = null;
            });
            $this->envPlaceholderUniquePrefix = 'env_' . substr(hash('xxh128', serialize($reproducibleEntropy)), -16);
        }
        return $this->envPlaceholderUniquePrefix;
    }
    /**
     * Returns the map of env vars used in the resolved parameter values to their placeholders.
     *
     * @return string[][] A map of env var names to their placeholders
     */
    public function getEnvPlaceholders(): array
    {
        return $this->envPlaceholders;
    }
    public function getUnusedEnvPlaceholders(): array
    {
        return $this->unusedEnvPlaceholders;
    }
    /**
     * @return void
     */
    public function clearUnusedEnvPlaceholders()
    {
        $this->unusedEnvPlaceholders = [];
    }
    /**
     * Merges the env placeholders of another EnvPlaceholderParameterBag.
     *
     * @return void
     */
    public function mergeEnvPlaceholders(self $bag)
    {
        if ($newPlaceholders = $bag->getEnvPlaceholders()) {
            $this->envPlaceholders += $newPlaceholders;
            foreach ($newPlaceholders as $env => $placeholders) {
                $this->envPlaceholders[$env] += $placeholders;
            }
        }
        if ($newUnusedPlaceholders = $bag->getUnusedEnvPlaceholders()) {
            $this->unusedEnvPlaceholders += $newUnusedPlaceholders;
            foreach ($newUnusedPlaceholders as $env => $placeholders) {
                $this->unusedEnvPlaceholders[$env] += $placeholders;
            }
        }
    }
    /**
     * Maps env prefixes to their corresponding PHP types.
     *
     * @return void
     */
    public function setProvidedTypes(array $providedTypes)
    {
        $this->providedTypes = $providedTypes;
    }
    /**
     * Gets the PHP types corresponding to env() parameter prefixes.
     *
     * @return string[][]
     */
    public function getProvidedTypes(): array
    {
        return $this->providedTypes;
    }
    /**
     * @return void
     */
    public function resolve()
    {
        if ($this->resolved) {
            return;
        }
        parent::resolve();
        foreach ($this->envPlaceholders as $env => $placeholders) {
            if ($this->has($name = "env({$env})") && null !== ($default = $this->parameters[$name]) && !\is_string($default)) {
                throw new RuntimeException(\sprintf('The default value of env parameter "%s" must be a string or null, "%s" given.', $env, get_debug_type($default)));
            }
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\DependencyInjection\ParameterBag;

use _ContaoManager\Symfony\Component\DependencyInjection\Exception\ParameterCircularReferenceException;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\ParameterNotFoundException;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\RuntimeException;
/**
 * Holds parameters.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class ParameterBag implements ParameterBagInterface
{
    protected $parameters = [];
    protected $resolved = \false;
    protected array $deprecatedParameters = [];
    public function __construct(array $parameters = [])
    {
        $this->add($parameters);
    }
    /**
     * @return void
     */
    public function clear()
    {
        $this->parameters = [];
    }
    /**
     * @return void
     */
    public function add(array $parameters)
    {
        foreach ($parameters as $key => $value) {
            $this->set($key, $value);
        }
    }
    public function all(): array
    {
        return $this->parameters;
    }
    public function allDeprecated(): array
    {
        return $this->deprecatedParameters;
    }
    public function get(string $name): array|bool|string|int|float|\UnitEnum|null
    {
        if (!\array_key_exists($name, $this->parameters)) {
            if (!$name) {
                throw new ParameterNotFoundException($name);
            }
            $alternatives = [];
            foreach ($this->parameters as $key => $parameterValue) {
                $lev = levenshtein($name, $key);
                if ($lev <= \strlen($name) / 3 || str_contains($key, $name)) {
                    $alternatives[] = $key;
                }
            }
            $nonNestedAlternative = null;
            if (!\count($alternatives) && str_contains($name, '.')) {
                $namePartsLength = array_map('strlen', explode('.', $name));
                $key = substr($name, 0, -1 * (1 + array_pop($namePartsLength)));
                while (\count($namePartsLength)) {
                    if ($this->has($key)) {
                        if (\is_array($this->get($key))) {
                            $nonNestedAlternative = $key;
                        }
                        break;
                    }
                    $key = substr($key, 0, -1 * (1 + array_pop($namePartsLength)));
                }
            }
            throw new ParameterNotFoundException($name, null, null, null, $alternatives, $nonNestedAlternative);
        }
        if (isset($this->deprecatedParameters[$name])) {
            trigger_deprecation(...$this->deprecatedParameters[$name]);
        }
        return $this->parameters[$name];
    }
    /**
     * @return void
     */
    public function set(string $name, array|bool|string|int|float|\UnitEnum|null $value)
    {
        if (is_numeric($name)) {
            trigger_deprecation('symfony/dependency-injection', '6.2', \sprintf('Using numeric parameter name "%s" is deprecated and will throw as of 7.0.', $name));
            // uncomment the following line in 7.0
            // throw new InvalidArgumentException(sprintf('The parameter name "%s" cannot be numeric.', $name));
        }
        $this->parameters[$name] = $value;
    }
    /**
     * Deprecates a service container parameter.
     *
     * @return void
     *
     * @throws ParameterNotFoundException if the parameter is not defined
     */
    public function deprecate(string $name, string $package, string $version, string $message = 'The parameter "%s" is deprecated.')
    {
        if (!\array_key_exists($name, $this->parameters)) {
            throw new ParameterNotFoundException($name);
        }
        $this->deprecatedParameters[$name] = [$package, $version, $message, $name];
    }
    public function has(string $name): bool
    {
        return \array_key_exists($name, $this->parameters);
    }
    /**
     * @return void
     */
    public function remove(string $name)
    {
        unset($this->parameters[$name], $this->deprecatedParameters[$name]);
    }
    /**
     * @return void
     */
    public function resolve()
    {
        if ($this->resolved) {
            return;
        }
        $parameters = [];
        foreach ($this->parameters as $key => $value) {
            try {
                $value = $this->resolveValue($value);
                $parameters[$key] = $this->unescapeValue($value);
            } catch (ParameterNotFoundException $e) {
                $e->setSourceKey($key);
                throw $e;
            }
        }
        $this->parameters = $parameters;
        $this->resolved = \true;
    }
    /**
     * Replaces parameter placeholders (%name%) by their values.
     *
     * @template TValue of array<array|scalar>|scalar
     *
     * @param TValue $value
     * @param array  $resolving An array of keys that are being resolved (used internally to detect circular references)
     *
     * @psalm-return (TValue is scalar ? array|scalar : array<array|scalar>)
     *
     * @throws ParameterNotFoundException          if a placeholder references a parameter that does not exist
     * @throws ParameterCircularReferenceException if a circular reference if detected
     * @throws RuntimeException                    when a given parameter has a type problem
     */
    public function resolveValue(mixed $value, array $resolving = []): mixed
    {
        if (\is_array($value)) {
            $args = [];
            foreach ($value as $key => $v) {
                $resolvedKey = \is_string($key) ? $this->resolveValue($key, $resolving) : $key;
                if (!\is_scalar($resolvedKey) && !$resolvedKey instanceof \Stringable) {
                    throw new RuntimeException(\sprintf('Array keys must be a scalar-value, but found key "%s" to resolve to type "%s".', $key, get_debug_type($resolvedKey)));
                }
                $args[$resolvedKey] = $this->resolveValue($v, $resolving);
            }
            return $args;
        }
        if (!\is_string($value) || '' === $value || !str_contains($value, '%')) {
            return $value;
        }
        return $this->resolveString($value, $resolving);
    }
    /**
     * Resolves parameters inside a string.
     *
     * @param array $resolving An array of keys that are being resolved (used internally to detect circular references)
     *
     * @throws ParameterNotFoundException          if a placeholder references a parameter that does not exist
     * @throws ParameterCircularReferenceException if a circular reference if detected
     * @throws RuntimeException                    when a given parameter has a type problem
     */
    public function resolveString(string $value, array $resolving = []): mixed
    {
        // we do this to deal with non string values (Boolean, integer, ...)
        // as the preg_replace_callback throw an exception when trying
        // a non-string in a parameter value
        if (preg_match('/^%([^%\s]+)%$/', $value, $match)) {
            $key = $match[1];
            if (isset($resolving[$key])) {
                throw new ParameterCircularReferenceException(array_keys($resolving));
            }
            $resolving[$key] = \true;
            return $this->resolved ? $this->get($key) : $this->resolveValue($this->get($key), $resolving);
        }
        return preg_replace_callback('/%%|%([^%\s]+)%/', function ($match) use ($resolving, $value) {
            // skip %%
            if (!isset($match[1])) {
                return '%%';
            }
            $key = $match[1];
            if (isset($resolving[$key])) {
                throw new ParameterCircularReferenceException(array_keys($resolving));
            }
            $resolved = $this->get($key);
            if (!\is_string($resolved) && !is_numeric($resolved)) {
                throw new RuntimeException(\sprintf('A string value must be composed of strings and/or numbers, but found parameter "%s" of type "%s" inside string value "%s".', $key, get_debug_type($resolved), $value));
            }
            $resolved = (string) $resolved;
            $resolving[$key] = \true;
            return $this->isResolved() ? $resolved : $this->resolveString($resolved, $resolving);
        }, $value);
    }
    /**
     * @return bool
     */
    public function isResolved()
    {
        return $this->resolved;
    }
    public function escapeValue(mixed $value): mixed
    {
        if (\is_string($value)) {
            return str_replace('%', '%%', $value);
        }
        if (\is_array($value)) {
            $result = [];
            foreach ($value as $k => $v) {
                $result[$k] = $this->escapeValue($v);
            }
            return $result;
        }
        return $value;
    }
    public function unescapeValue(mixed $value): mixed
    {
        if (\is_string($value)) {
            return str_replace('%%', '%', $value);
        }
        if (\is_array($value)) {
            $result = [];
            foreach ($value as $k => $v) {
                $result[$k] = $this->unescapeValue($v);
            }
            return $result;
        }
        return $value;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\DependencyInjection\ParameterBag;

use _ContaoManager\Psr\Container\ContainerInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\ParameterNotFoundException;
/**
 * ContainerBagInterface is the interface implemented by objects that manage service container parameters.
 *
 * @author Nicolas Grekas <p@tchwork.com>
 */
interface ContainerBagInterface extends ContainerInterface
{
    /**
     * Gets the service container parameters.
     */
    public function all(): array;
    /**
     * Replaces parameter placeholders (%name%) by their values.
     *
     * @template TValue of array<array|scalar>|scalar
     *
     * @param TValue $value
     *
     * @return mixed
     *
     * @psalm-return (TValue is scalar ? array|scalar : array<array|scalar>)
     *
     * @throws ParameterNotFoundException if a placeholder references a parameter that does not exist
     */
    public function resolveValue(mixed $value);
    /**
     * Escape parameter placeholders %.
     */
    public function escapeValue(mixed $value): mixed;
    /**
     * Unescape parameter placeholders %.
     */
    public function unescapeValue(mixed $value): mixed;
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\DependencyInjection\ParameterBag;

use _ContaoManager\Symfony\Component\DependencyInjection\Container;
/**
 * @author Nicolas Grekas <p@tchwork.com>
 */
class ContainerBag extends FrozenParameterBag implements ContainerBagInterface
{
    private Container $container;
    public function __construct(Container $container)
    {
        $this->container = $container;
    }
    public function all(): array
    {
        return $this->container->getParameterBag()->all();
    }
    public function get(string $name): array|bool|string|int|float|\UnitEnum|null
    {
        return $this->container->getParameter($name);
    }
    public function has(string $name): bool
    {
        return $this->container->hasParameter($name);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\DependencyInjection\ParameterBag;

use _ContaoManager\Symfony\Component\DependencyInjection\Exception\LogicException;
/**
 * Holds read-only parameters.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class FrozenParameterBag extends ParameterBag
{
    /**
     * For performance reasons, the constructor assumes that
     * all keys are already lowercased.
     *
     * This is always the case when used internally.
     */
    public function __construct(array $parameters = [], protected array $deprecatedParameters = [])
    {
        $this->parameters = $parameters;
        $this->resolved = \true;
    }
    /**
     * @return never
     */
    public function clear()
    {
        throw new LogicException('Impossible to call clear() on a frozen ParameterBag.');
    }
    /**
     * @return never
     */
    public function add(array $parameters)
    {
        throw new LogicException('Impossible to call add() on a frozen ParameterBag.');
    }
    /**
     * @return never
     */
    public function set(string $name, array|bool|string|int|float|\UnitEnum|null $value)
    {
        throw new LogicException('Impossible to call set() on a frozen ParameterBag.');
    }
    /**
     * @return never
     */
    public function deprecate(string $name, string $package, string $version, string $message = 'The parameter "%s" is deprecated.')
    {
        throw new LogicException('Impossible to call deprecate() on a frozen ParameterBag.');
    }
    /**
     * @return never
     */
    public function remove(string $name)
    {
        throw new LogicException('Impossible to call remove() on a frozen ParameterBag.');
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\DependencyInjection;

use _ContaoManager\Symfony\Component\DependencyInjection\Argument\BoundArgument;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\OutOfBoundsException;
/**
 * Definition represents a service definition.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class Definition
{
    private const DEFAULT_DEPRECATION_TEMPLATE = 'The "%service_id%" service is deprecated. You should stop using it, as it will be removed in the future.';
    private ?string $class = null;
    private ?string $file = null;
    private string|array|null $factory = null;
    private bool $shared = \true;
    private array $deprecation = [];
    private array $properties = [];
    private array $calls = [];
    private array $instanceof = [];
    private bool $autoconfigured = \false;
    private string|array|null $configurator = null;
    private array $tags = [];
    private bool $public = \false;
    private bool $synthetic = \false;
    private bool $abstract = \false;
    private bool $lazy = \false;
    private ?array $decoratedService = null;
    private bool $autowired = \false;
    private array $changes = [];
    private array $bindings = [];
    private array $errors = [];
    protected $arguments = [];
    /**
     * @internal
     *
     * Used to store the name of the inner id when using service decoration together with autowiring
     */
    public ?string $innerServiceId = null;
    /**
     * @internal
     *
     * Used to store the behavior to follow when using service decoration and the decorated service is invalid
     */
    public ?int $decorationOnInvalid = null;
    public function __construct(?string $class = null, array $arguments = [])
    {
        if (null !== $class) {
            $this->setClass($class);
        }
        $this->arguments = $arguments;
    }
    /**
     * Returns all changes tracked for the Definition object.
     */
    public function getChanges(): array
    {
        return $this->changes;
    }
    /**
     * Sets the tracked changes for the Definition object.
     *
     * @param array $changes An array of changes for this Definition
     *
     * @return $this
     */
    public function setChanges(array $changes): static
    {
        $this->changes = $changes;
        return $this;
    }
    /**
     * Sets a factory.
     *
     * @param string|array|Reference|null $factory A PHP function, reference or an array containing a class/Reference and a method to call
     *
     * @return $this
     */
    public function setFactory(string|array|Reference|null $factory): static
    {
        $this->changes['factory'] = \true;
        if (\is_string($factory) && str_contains($factory, '::')) {
            $factory = explode('::', $factory, 2);
        } elseif ($factory instanceof Reference) {
            $factory = [$factory, '__invoke'];
        }
        $this->factory = $factory;
        return $this;
    }
    /**
     * Gets the factory.
     *
     * @return string|array|null The PHP function or an array containing a class/Reference and a method to call
     */
    public function getFactory(): string|array|null
    {
        return $this->factory;
    }
    /**
     * Sets the service that this service is decorating.
     *
     * @param string|null $id        The decorated service id, use null to remove decoration
     * @param string|null $renamedId The new decorated service id
     *
     * @return $this
     *
     * @throws InvalidArgumentException in case the decorated service id and the new decorated service id are equals
     */
    public function setDecoratedService(?string $id, ?string $renamedId = null, int $priority = 0, int $invalidBehavior = ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE): static
    {
        if ($renamedId && $id === $renamedId) {
            throw new InvalidArgumentException(\sprintf('The decorated service inner name for "%s" must be different than the service name itself.', $id));
        }
        $this->changes['decorated_service'] = \true;
        if (null === $id) {
            $this->decoratedService = null;
        } else {
            $this->decoratedService = [$id, $renamedId, $priority];
            if (ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE !== $invalidBehavior) {
                $this->decoratedService[] = $invalidBehavior;
            }
        }
        return $this;
    }
    /**
     * Gets the service that this service is decorating.
     *
     * @return array|null An array composed of the decorated service id, the new id for it and the priority of decoration, null if no service is decorated
     */
    public function getDecoratedService(): ?array
    {
        return $this->decoratedService;
    }
    /**
     * Sets the service class.
     *
     * @return $this
     */
    public function setClass(?string $class): static
    {
        $this->changes['class'] = \true;
        $this->class = $class;
        return $this;
    }
    /**
     * Gets the service class.
     */
    public function getClass(): ?string
    {
        return $this->class;
    }
    /**
     * Sets the arguments to pass to the service constructor/factory method.
     *
     * @return $this
     */
    public function setArguments(array $arguments): static
    {
        $this->arguments = $arguments;
        return $this;
    }
    /**
     * Sets the properties to define when creating the service.
     *
     * @return $this
     */
    public function setProperties(array $properties): static
    {
        $this->properties = $properties;
        return $this;
    }
    /**
     * Gets the properties to define when creating the service.
     */
    public function getProperties(): array
    {
        return $this->properties;
    }
    /**
     * Sets a specific property.
     *
     * @return $this
     */
    public function setProperty(string $name, mixed $value): static
    {
        $this->properties[$name] = $value;
        return $this;
    }
    /**
     * Adds an argument to pass to the service constructor/factory method.
     *
     * @return $this
     */
    public function addArgument(mixed $argument): static
    {
        $this->arguments[] = $argument;
        return $this;
    }
    /**
     * Replaces a specific argument.
     *
     * @return $this
     *
     * @throws OutOfBoundsException When the replaced argument does not exist
     */
    public function replaceArgument(int|string $index, mixed $argument): static
    {
        if (0 === \count($this->arguments)) {
            throw new OutOfBoundsException(\sprintf('Cannot replace arguments for class "%s" if none have been configured yet.', $this->class));
        }
        if (\is_int($index) && ($index < 0 || $index > \count($this->arguments) - 1)) {
            throw new OutOfBoundsException(\sprintf('The index "%d" is not in the range [0, %d] of the arguments of class "%s".', $index, \count($this->arguments) - 1, $this->class));
        }
        if (!\array_key_exists($index, $this->arguments)) {
            throw new OutOfBoundsException(\sprintf('The argument "%s" doesn\'t exist in class "%s".', $index, $this->class));
        }
        $this->arguments[$index] = $argument;
        return $this;
    }
    /**
     * Sets a specific argument.
     *
     * @return $this
     */
    public function setArgument(int|string $key, mixed $value): static
    {
        $this->arguments[$key] = $value;
        return $this;
    }
    /**
     * Gets the arguments to pass to the service constructor/factory method.
     */
    public function getArguments(): array
    {
        return $this->arguments;
    }
    /**
     * Gets an argument to pass to the service constructor/factory method.
     *
     * @throws OutOfBoundsException When the argument does not exist
     */
    public function getArgument(int|string $index): mixed
    {
        if (!\array_key_exists($index, $this->arguments)) {
            throw new OutOfBoundsException(\sprintf('The argument "%s" doesn\'t exist in class "%s".', $index, $this->class));
        }
        return $this->arguments[$index];
    }
    /**
     * Sets the methods to call after service initialization.
     *
     * @return $this
     */
    public function setMethodCalls(array $calls = []): static
    {
        $this->calls = [];
        foreach ($calls as $call) {
            $this->addMethodCall($call[0], $call[1], $call[2] ?? \false);
        }
        return $this;
    }
    /**
     * Adds a method to call after service initialization.
     *
     * @param string $method       The method name to call
     * @param array  $arguments    An array of arguments to pass to the method call
     * @param bool   $returnsClone Whether the call returns the service instance or not
     *
     * @return $this
     *
     * @throws InvalidArgumentException on empty $method param
     */
    public function addMethodCall(string $method, array $arguments = [], bool $returnsClone = \false): static
    {
        if (empty($method)) {
            throw new InvalidArgumentException('Method name cannot be empty.');
        }
        $this->calls[] = $returnsClone ? [$method, $arguments, \true] : [$method, $arguments];
        return $this;
    }
    /**
     * Removes a method to call after service initialization.
     *
     * @return $this
     */
    public function removeMethodCall(string $method): static
    {
        foreach ($this->calls as $i => $call) {
            if ($call[0] === $method) {
                unset($this->calls[$i]);
            }
        }
        return $this;
    }
    /**
     * Check if the current definition has a given method to call after service initialization.
     */
    public function hasMethodCall(string $method): bool
    {
        foreach ($this->calls as $call) {
            if ($call[0] === $method) {
                return \true;
            }
        }
        return \false;
    }
    /**
     * Gets the methods to call after service initialization.
     */
    public function getMethodCalls(): array
    {
        return $this->calls;
    }
    /**
     * Sets the definition templates to conditionally apply on the current definition, keyed by parent interface/class.
     *
     * @param ChildDefinition[] $instanceof
     *
     * @return $this
     */
    public function setInstanceofConditionals(array $instanceof): static
    {
        $this->instanceof = $instanceof;
        return $this;
    }
    /**
     * Gets the definition templates to conditionally apply on the current definition, keyed by parent interface/class.
     *
     * @return ChildDefinition[]
     */
    public function getInstanceofConditionals(): array
    {
        return $this->instanceof;
    }
    /**
     * Sets whether or not instanceof conditionals should be prepended with a global set.
     *
     * @return $this
     */
    public function setAutoconfigured(bool $autoconfigured): static
    {
        $this->changes['autoconfigured'] = \true;
        $this->autoconfigured = $autoconfigured;
        return $this;
    }
    public function isAutoconfigured(): bool
    {
        return $this->autoconfigured;
    }
    /**
     * Sets tags for this definition.
     *
     * @return $this
     */
    public function setTags(array $tags): static
    {
        $this->tags = $tags;
        return $this;
    }
    /**
     * Returns all tags.
     */
    public function getTags(): array
    {
        return $this->tags;
    }
    /**
     * Gets a tag by name.
     */
    public function getTag(string $name): array
    {
        return $this->tags[$name] ?? [];
    }
    /**
     * Adds a tag for this definition.
     *
     * @return $this
     */
    public function addTag(string $name, array $attributes = []): static
    {
        $this->tags[$name][] = $attributes;
        return $this;
    }
    /**
     * Whether this definition has a tag with the given name.
     */
    public function hasTag(string $name): bool
    {
        return isset($this->tags[$name]);
    }
    /**
     * Clears all tags for a given name.
     *
     * @return $this
     */
    public function clearTag(string $name): static
    {
        unset($this->tags[$name]);
        return $this;
    }
    /**
     * Clears the tags for this definition.
     *
     * @return $this
     */
    public function clearTags(): static
    {
        $this->tags = [];
        return $this;
    }
    /**
     * Sets a file to require before creating the service.
     *
     * @return $this
     */
    public function setFile(?string $file): static
    {
        $this->changes['file'] = \true;
        $this->file = $file;
        return $this;
    }
    /**
     * Gets the file to require before creating the service.
     */
    public function getFile(): ?string
    {
        return $this->file;
    }
    /**
     * Sets if the service must be shared or not.
     *
     * @return $this
     */
    public function setShared(bool $shared): static
    {
        $this->changes['shared'] = \true;
        $this->shared = $shared;
        return $this;
    }
    /**
     * Whether this service is shared.
     */
    public function isShared(): bool
    {
        return $this->shared;
    }
    /**
     * Sets the visibility of this service.
     *
     * @return $this
     */
    public function setPublic(bool $boolean): static
    {
        $this->changes['public'] = \true;
        $this->public = $boolean;
        return $this;
    }
    /**
     * Whether this service is public facing.
     */
    public function isPublic(): bool
    {
        return $this->public;
    }
    /**
     * Whether this service is private.
     */
    public function isPrivate(): bool
    {
        return !$this->public;
    }
    /**
     * Sets the lazy flag of this service.
     *
     * @return $this
     */
    public function setLazy(bool $lazy): static
    {
        $this->changes['lazy'] = \true;
        $this->lazy = $lazy;
        return $this;
    }
    /**
     * Whether this service is lazy.
     */
    public function isLazy(): bool
    {
        return $this->lazy;
    }
    /**
     * Sets whether this definition is synthetic, that is not constructed by the
     * container, but dynamically injected.
     *
     * @return $this
     */
    public function setSynthetic(bool $boolean): static
    {
        $this->synthetic = $boolean;
        if (!isset($this->changes['public'])) {
            $this->setPublic(\true);
        }
        return $this;
    }
    /**
     * Whether this definition is synthetic, that is not constructed by the
     * container, but dynamically injected.
     */
    public function isSynthetic(): bool
    {
        return $this->synthetic;
    }
    /**
     * Whether this definition is abstract, that means it merely serves as a
     * template for other definitions.
     *
     * @return $this
     */
    public function setAbstract(bool $boolean): static
    {
        $this->abstract = $boolean;
        return $this;
    }
    /**
     * Whether this definition is abstract, that means it merely serves as a
     * template for other definitions.
     */
    public function isAbstract(): bool
    {
        return $this->abstract;
    }
    /**
     * Whether this definition is deprecated, that means it should not be called
     * anymore.
     *
     * @param string $package The name of the composer package that is triggering the deprecation
     * @param string $version The version of the package that introduced the deprecation
     * @param string $message The deprecation message to use
     *
     * @return $this
     *
     * @throws InvalidArgumentException when the message template is invalid
     */
    public function setDeprecated(string $package, string $version, string $message): static
    {
        if ('' !== $message) {
            if (preg_match('#[\r\n]|\*/#', $message)) {
                throw new InvalidArgumentException('Invalid characters found in deprecation template.');
            }
            if (!str_contains($message, '%service_id%')) {
                throw new InvalidArgumentException('The deprecation template must contain the "%service_id%" placeholder.');
            }
        }
        $this->changes['deprecated'] = \true;
        $this->deprecation = ['package' => $package, 'version' => $version, 'message' => $message ?: self::DEFAULT_DEPRECATION_TEMPLATE];
        return $this;
    }
    /**
     * Whether this definition is deprecated, that means it should not be called
     * anymore.
     */
    public function isDeprecated(): bool
    {
        return (bool) $this->deprecation;
    }
    /**
     * @param string $id Service id relying on this definition
     */
    public function getDeprecation(string $id): array
    {
        return ['package' => $this->deprecation['package'], 'version' => $this->deprecation['version'], 'message' => str_replace('%service_id%', $id, $this->deprecation['message'])];
    }
    /**
     * Sets a configurator to call after the service is fully initialized.
     *
     * @param string|array|Reference|null $configurator A PHP function, reference or an array containing a class/Reference and a method to call
     *
     * @return $this
     */
    public function setConfigurator(string|array|Reference|null $configurator): static
    {
        $this->changes['configurator'] = \true;
        if (\is_string($configurator) && str_contains($configurator, '::')) {
            $configurator = explode('::', $configurator, 2);
        } elseif ($configurator instanceof Reference) {
            $configurator = [$configurator, '__invoke'];
        }
        $this->configurator = $configurator;
        return $this;
    }
    /**
     * Gets the configurator to call after the service is fully initialized.
     */
    public function getConfigurator(): string|array|null
    {
        return $this->configurator;
    }
    /**
     * Is the definition autowired?
     */
    public function isAutowired(): bool
    {
        return $this->autowired;
    }
    /**
     * Enables/disables autowiring.
     *
     * @return $this
     */
    public function setAutowired(bool $autowired): static
    {
        $this->changes['autowired'] = \true;
        $this->autowired = $autowired;
        return $this;
    }
    /**
     * Gets bindings.
     *
     * @return BoundArgument[]
     */
    public function getBindings(): array
    {
        return $this->bindings;
    }
    /**
     * Sets bindings.
     *
     * Bindings map $named or FQCN arguments to values that should be
     * injected in the matching parameters (of the constructor, of methods
     * called and of controller actions).
     *
     * @return $this
     */
    public function setBindings(array $bindings): static
    {
        foreach ($bindings as $key => $binding) {
            if (0 < strpos($key, '$') && $key !== $k = preg_replace('/[ \t]*\$/', ' $', $key)) {
                unset($bindings[$key]);
                $bindings[$key = $k] = $binding;
            }
            if (!$binding instanceof BoundArgument) {
                $bindings[$key] = new BoundArgument($binding);
            }
        }
        $this->bindings = $bindings;
        return $this;
    }
    /**
     * Add an error that occurred when building this Definition.
     *
     * @return $this
     */
    public function addError(string|\Closure|self $error): static
    {
        if ($error instanceof self) {
            $this->errors = array_merge($this->errors, $error->errors);
        } else {
            $this->errors[] = $error;
        }
        return $this;
    }
    /**
     * Returns any errors that occurred while building this Definition.
     */
    public function getErrors(): array
    {
        foreach ($this->errors as $i => $error) {
            if ($error instanceof \Closure) {
                $this->errors[$i] = (string) $error();
            } elseif (!\is_string($error)) {
                $this->errors[$i] = (string) $error;
            }
        }
        return $this->errors;
    }
    public function hasErrors(): bool
    {
        return (bool) $this->errors;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\DependencyInjection;

use _ContaoManager\Symfony\Component\DependencyInjection\Exception\RuntimeException;
/**
 * The EnvVarProcessorInterface is implemented by objects that manage environment-like variables.
 *
 * @author Nicolas Grekas <p@tchwork.com>
 */
interface EnvVarProcessorInterface
{
    /**
     * Returns the value of the given variable as managed by the current instance.
     *
     * @param string                  $prefix The namespace of the variable; when the empty string is passed, null values should be kept as is
     * @param string                  $name   The name of the variable within the namespace
     * @param \Closure(string): mixed $getEnv A closure that allows fetching more env vars
     *
     * @throws RuntimeException on error
     */
    public function getEnv(string $prefix, string $name, \Closure $getEnv): mixed;
    /**
     * @return array<string, string> The PHP-types managed by getEnv(), keyed by prefixes
     */
    public static function getProvidedTypes(): array;
}
DependencyInjection Component
=============================

The DependencyInjection component allows you to standardize and centralize the
way objects are constructed in your application.

Resources
---------

 * [Documentation](https://symfony.com/doc/current/components/dependency_injection.html)
 * [Contributing](https://symfony.com/doc/current/contributing/index.html)
 * [Report issues](https://github.com/symfony/symfony/issues) and
   [send Pull Requests](https://github.com/symfony/symfony/pulls)
   in the [main Symfony repository](https://github.com/symfony/symfony)
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\DependencyInjection;

use _ContaoManager\Psr\Container\ContainerInterface as PsrContainerInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\ParameterNotFoundException;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\ServiceCircularReferenceException;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException;
/**
 * ContainerInterface is the interface implemented by service container classes.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
interface ContainerInterface extends PsrContainerInterface
{
    public const RUNTIME_EXCEPTION_ON_INVALID_REFERENCE = 0;
    public const EXCEPTION_ON_INVALID_REFERENCE = 1;
    public const NULL_ON_INVALID_REFERENCE = 2;
    public const IGNORE_ON_INVALID_REFERENCE = 3;
    public const IGNORE_ON_UNINITIALIZED_REFERENCE = 4;
    /**
     * @return void
     */
    public function set(string $id, ?object $service);
    /**
     * @template B of self::*_REFERENCE
     *
     * @param B $invalidBehavior
     *
     * @psalm-return (B is self::EXCEPTION_ON_INVALID_REFERENCE|self::RUNTIME_EXCEPTION_ON_INVALID_REFERENCE ? object : object|null)
     *
     * @throws ServiceCircularReferenceException When a circular reference is detected
     * @throws ServiceNotFoundException          When the service is not defined
     *
     * @see Reference
     */
    public function get(string $id, int $invalidBehavior = self::EXCEPTION_ON_INVALID_REFERENCE): ?object;
    public function has(string $id): bool;
    /**
     * Check for whether or not a service has been initialized.
     */
    public function initialized(string $id): bool;
    /**
     * @return array|bool|string|int|float|\UnitEnum|null
     *
     * @throws ParameterNotFoundException if the parameter is not defined
     */
    public function getParameter(string $name);
    public function hasParameter(string $name): bool;
    /**
     * @return void
     */
    public function setParameter(string $name, array|bool|string|int|float|\UnitEnum|null $value);
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\DependencyInjection\Loader;

use _ContaoManager\Symfony\Component\Config\Exception\FileLocatorFileNotFoundException;
use _ContaoManager\Symfony\Component\Config\Exception\LoaderLoadException;
use _ContaoManager\Symfony\Component\Config\FileLocatorInterface;
use _ContaoManager\Symfony\Component\Config\Loader\FileLoader as BaseFileLoader;
use _ContaoManager\Symfony\Component\Config\Loader\Loader;
use _ContaoManager\Symfony\Component\Config\Resource\GlobResource;
use _ContaoManager\Symfony\Component\DependencyInjection\Alias;
use _ContaoManager\Symfony\Component\DependencyInjection\Attribute\AsAlias;
use _ContaoManager\Symfony\Component\DependencyInjection\Attribute\Exclude;
use _ContaoManager\Symfony\Component\DependencyInjection\Attribute\When;
use _ContaoManager\Symfony\Component\DependencyInjection\ChildDefinition;
use _ContaoManager\Symfony\Component\DependencyInjection\Compiler\RegisterAutoconfigureAttributesPass;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerBuilder;
use _ContaoManager\Symfony\Component\DependencyInjection\Definition;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\LogicException;
/**
 * FileLoader is the abstract class used by all built-in loaders that are file based.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
abstract class FileLoader extends BaseFileLoader
{
    public const ANONYMOUS_ID_REGEXP = '/^\.\d+_[^~]*+~[._a-zA-Z\d]{7}$/';
    protected $container;
    protected $isLoadingInstanceof = \false;
    protected $instanceof = [];
    protected $interfaces = [];
    protected $singlyImplemented = [];
    /** @var array<string, Alias> */
    protected $aliases = [];
    protected $autoRegisterAliasesForSinglyImplementedInterfaces = \true;
    public function __construct(ContainerBuilder $container, FileLocatorInterface $locator, ?string $env = null)
    {
        $this->container = $container;
        parent::__construct($locator, $env);
    }
    /**
     * @param bool|string $ignoreErrors Whether errors should be ignored; pass "not_found" to ignore only when the loaded resource is not found
     */
    public function import(mixed $resource, ?string $type = null, bool|string $ignoreErrors = \false, ?string $sourceResource = null, $exclude = null): mixed
    {
        $args = \func_get_args();
        if ($ignoreNotFound = 'not_found' === $ignoreErrors) {
            $args[2] = \false;
        } elseif (!\is_bool($ignoreErrors)) {
            throw new \TypeError(\sprintf('Invalid argument $ignoreErrors provided to "%s::import()": boolean or "not_found" expected, "%s" given.', static::class, get_debug_type($ignoreErrors)));
        }
        try {
            return parent::import(...$args);
        } catch (LoaderLoadException $e) {
            if (!$ignoreNotFound || !($prev = $e->getPrevious()) instanceof FileLocatorFileNotFoundException) {
                throw $e;
            }
            foreach ($prev->getTrace() as $frame) {
                if ('import' === ($frame['function'] ?? null) && is_a($frame['class'] ?? '', Loader::class, \true)) {
                    break;
                }
            }
            if (__FILE__ !== $frame['file']) {
                throw $e;
            }
        }
        return null;
    }
    /**
     * Registers a set of classes as services using PSR-4 for discovery.
     *
     * @param Definition           $prototype A definition to use as template
     * @param string               $namespace The namespace prefix of classes in the scanned directory
     * @param string               $resource  The directory to look for classes, glob-patterns allowed
     * @param string|string[]|null $exclude   A globbed path of files to exclude or an array of globbed paths of files to exclude
     * @param string|null          $source    The path to the file that defines the auto-discovery rule
     *
     * @return void
     */
    public function registerClasses(Definition $prototype, string $namespace, string $resource, string|array|null $exclude = null)
    {
        if (!str_ends_with($namespace, '\\')) {
            throw new InvalidArgumentException(\sprintf('Namespace prefix must end with a "\": "%s".', $namespace));
        }
        if (!preg_match('/^(?:[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*+\\\\)++$/', $namespace)) {
            throw new InvalidArgumentException(\sprintf('Namespace is not a valid PSR-4 prefix: "%s".', $namespace));
        }
        // This can happen with YAML files
        if (\is_array($exclude) && \in_array(null, $exclude, \true)) {
            throw new InvalidArgumentException('The exclude list must not contain a "null" value.');
        }
        // This can happen with XML files
        if (\is_array($exclude) && \in_array('', $exclude, \true)) {
            throw new InvalidArgumentException('The exclude list must not contain an empty value.');
        }
        $source = \func_num_args() > 4 ? func_get_arg(4) : null;
        $autoconfigureAttributes = new RegisterAutoconfigureAttributesPass();
        $autoconfigureAttributes = $autoconfigureAttributes->accept($prototype) ? $autoconfigureAttributes : null;
        $classes = $this->findClasses($namespace, $resource, (array) $exclude, $autoconfigureAttributes, $source);
        $getPrototype = static fn() => clone $prototype;
        $serialized = serialize($prototype);
        // avoid deep cloning if no definitions are nested
        if (strpos($serialized, 'O:48:"Symfony\Component\DependencyInjection\Definition"', 55) || strpos($serialized, 'O:53:"Symfony\Component\DependencyInjection\ChildDefinition"', 55)) {
            // prepare for deep cloning
            foreach (['Arguments', 'Properties', 'MethodCalls', 'Configurator', 'Factory', 'Bindings'] as $key) {
                $serialized = serialize($prototype->{'get' . $key}());
                if (strpos($serialized, 'O:48:"Symfony\Component\DependencyInjection\Definition"') || strpos($serialized, 'O:53:"Symfony\Component\DependencyInjection\ChildDefinition"')) {
                    $getPrototype = static fn() => $getPrototype()->{'set' . $key}(unserialize($serialized));
                }
            }
        }
        unset($serialized);
        foreach ($classes as $class => $errorMessage) {
            if (null === $errorMessage && $autoconfigureAttributes) {
                $r = $this->container->getReflectionClass($class);
                if ($r->getAttributes(Exclude::class)[0] ?? null) {
                    $this->addContainerExcludedTag($class, $source);
                    continue;
                }
                if ($this->env) {
                    $attribute = null;
                    foreach ($r->getAttributes(When::class, \ReflectionAttribute::IS_INSTANCEOF) as $attribute) {
                        if ($this->env === $attribute->newInstance()->env) {
                            $attribute = null;
                            break;
                        }
                    }
                    if (null !== $attribute) {
                        $this->addContainerExcludedTag($class, $source);
                        continue;
                    }
                }
            }
            if (interface_exists($class, \false)) {
                $this->interfaces[] = $class;
            } else {
                $this->setDefinition($class, $definition = $getPrototype());
                $definition->setClass($class);
                if (null !== $errorMessage) {
                    $definition->addError($errorMessage);
                    continue;
                }
                $interfaces = [];
                foreach (class_implements($class, \false) as $interface) {
                    $this->singlyImplemented[$interface] = ($this->singlyImplemented[$interface] ?? $class) !== $class ? \false : $class;
                    $interfaces[] = $interface;
                }
                if (!$autoconfigureAttributes) {
                    continue;
                }
                $r = $this->container->getReflectionClass($class);
                $defaultAlias = 1 === \count($interfaces) ? $interfaces[0] : null;
                foreach ($r->getAttributes(AsAlias::class) as $attr) {
                    /** @var AsAlias $attribute */
                    $attribute = $attr->newInstance();
                    $alias = $attribute->id ?? $defaultAlias;
                    $public = $attribute->public;
                    if (null === $alias) {
                        throw new LogicException(\sprintf('Alias cannot be automatically determined for class "%s". If you have used the #[AsAlias] attribute with a class implementing multiple interfaces, add the interface you want to alias to the first parameter of #[AsAlias].', $class));
                    }
                    if (isset($this->aliases[$alias])) {
                        throw new LogicException(\sprintf('The "%s" alias has already been defined with the #[AsAlias] attribute in "%s".', $alias, $this->aliases[$alias]));
                    }
                    $this->aliases[$alias] = new Alias($class, $public);
                }
            }
        }
        foreach ($this->aliases as $alias => $aliasDefinition) {
            $this->container->setAlias($alias, $aliasDefinition);
        }
        if ($this->autoRegisterAliasesForSinglyImplementedInterfaces) {
            $this->registerAliasesForSinglyImplementedInterfaces();
        }
    }
    /**
     * @return void
     */
    public function registerAliasesForSinglyImplementedInterfaces()
    {
        foreach ($this->interfaces as $interface) {
            if (!empty($this->singlyImplemented[$interface]) && !isset($this->aliases[$interface]) && !$this->container->has($interface)) {
                $this->container->setAlias($interface, $this->singlyImplemented[$interface]);
            }
        }
        $this->interfaces = $this->singlyImplemented = $this->aliases = [];
    }
    /**
     * Registers a definition in the container with its instanceof-conditionals.
     *
     * @return void
     */
    protected function setDefinition(string $id, Definition $definition)
    {
        $this->container->removeBindings($id);
        foreach ($definition->getTag('container.error') as $error) {
            if (isset($error['message'])) {
                $definition->addError($error['message']);
            }
        }
        if ($this->isLoadingInstanceof) {
            if (!$definition instanceof ChildDefinition) {
                throw new InvalidArgumentException(\sprintf('Invalid type definition "%s": ChildDefinition expected, "%s" given.', $id, get_debug_type($definition)));
            }
            $this->instanceof[$id] = $definition;
        } else {
            $this->container->setDefinition($id, $definition->setInstanceofConditionals($this->instanceof));
        }
    }
    private function findClasses(string $namespace, string $pattern, array $excludePatterns, ?RegisterAutoconfigureAttributesPass $autoconfigureAttributes, ?string $source): array
    {
        $parameterBag = $this->container->getParameterBag();
        $excludePaths = [];
        $excludePrefix = null;
        $excludePatterns = $parameterBag->unescapeValue($parameterBag->resolveValue($excludePatterns));
        foreach ($excludePatterns as $excludePattern) {
            foreach ($this->glob($excludePattern, \true, $resource, \true, \true) as $path => $info) {
                $excludePrefix ??= $resource->getPrefix();
                // normalize Windows slashes and remove trailing slashes
                $excludePaths[rtrim(str_replace('\\', '/', $path), '/')] = \true;
            }
        }
        $pattern = $parameterBag->unescapeValue($parameterBag->resolveValue($pattern));
        $classes = [];
        $prefixLen = null;
        foreach ($this->glob($pattern, \true, $resource, \false, \false, $excludePaths) as $path => $info) {
            if (null === $prefixLen) {
                $prefixLen = \strlen($resource->getPrefix());
                if ($excludePrefix && !str_starts_with($excludePrefix, $resource->getPrefix())) {
                    throw new InvalidArgumentException(\sprintf('Invalid "exclude" pattern when importing classes for "%s": make sure your "exclude" pattern (%s) is a subset of the "resource" pattern (%s).', $namespace, $excludePattern, $pattern));
                }
            }
            if (isset($excludePaths[str_replace('\\', '/', $path)])) {
                continue;
            }
            if (!str_ends_with($path, '.php')) {
                continue;
            }
            $class = $namespace . ltrim(str_replace('/', '\\', substr($path, $prefixLen, -4)), '\\');
            if (!preg_match('/^[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*+(?:\\\\[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*+)*+$/', $class)) {
                continue;
            }
            try {
                $r = $this->container->getReflectionClass($class);
            } catch (\ReflectionException $e) {
                $classes[$class] = $e->getMessage();
                continue;
            }
            // check to make sure the expected class exists
            if (!$r) {
                throw new InvalidArgumentException(\sprintf('Expected to find class "%s" in file "%s" while importing services from resource "%s", but it was not found! Check the namespace prefix used with the resource.', $class, $path, $pattern));
            }
            if ($r->isInstantiable() || $r->isInterface()) {
                $classes[$class] = null;
            }
            if ($autoconfigureAttributes && !$r->isInstantiable()) {
                $autoconfigureAttributes->processClass($this->container, $r);
            }
        }
        // track only for new & removed files
        if ($resource instanceof GlobResource) {
            $this->container->addResource($resource);
        } else {
            foreach ($resource as $path) {
                $this->container->fileExists($path, \false);
            }
        }
        if (null !== $prefixLen) {
            foreach ($excludePaths as $path => $_) {
                $class = $namespace . ltrim(str_replace('/', '\\', substr($path, $prefixLen, str_ends_with($path, '.php') ? -4 : null)), '\\');
                $this->addContainerExcludedTag($class, $source);
            }
        }
        return $classes;
    }
    private function addContainerExcludedTag(string $class, ?string $source): void
    {
        if ($this->container->has($class)) {
            return;
        }
        static $attributes = [];
        if (null !== $source && !isset($attributes[$source])) {
            $attributes[$source] = ['source' => \sprintf('in "%s/%s"', basename(\dirname($source)), basename($source))];
        }
        $this->container->register($class, $class)->setAbstract(\true)->addTag('container.excluded', null !== $source ? $attributes[$source] : []);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\DependencyInjection\Loader;

use _ContaoManager\Symfony\Component\DependencyInjection\Alias;
use _ContaoManager\Symfony\Component\DependencyInjection\Argument\AbstractArgument;
use _ContaoManager\Symfony\Component\DependencyInjection\Argument\BoundArgument;
use _ContaoManager\Symfony\Component\DependencyInjection\Argument\IteratorArgument;
use _ContaoManager\Symfony\Component\DependencyInjection\Argument\ServiceClosureArgument;
use _ContaoManager\Symfony\Component\DependencyInjection\Argument\ServiceLocatorArgument;
use _ContaoManager\Symfony\Component\DependencyInjection\Argument\TaggedIteratorArgument;
use _ContaoManager\Symfony\Component\DependencyInjection\ChildDefinition;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerBuilder;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Definition;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\LogicException;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\RuntimeException;
use _ContaoManager\Symfony\Component\DependencyInjection\Extension\ExtensionInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Reference;
use _ContaoManager\Symfony\Component\ExpressionLanguage\Expression;
use _ContaoManager\Symfony\Component\Yaml\Exception\ParseException;
use _ContaoManager\Symfony\Component\Yaml\Parser as YamlParser;
use _ContaoManager\Symfony\Component\Yaml\Tag\TaggedValue;
use _ContaoManager\Symfony\Component\Yaml\Yaml;
/**
 * YamlFileLoader loads YAML files service definitions.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class YamlFileLoader extends FileLoader
{
    private const SERVICE_KEYWORDS = ['alias' => 'alias', 'parent' => 'parent', 'class' => 'class', 'shared' => 'shared', 'synthetic' => 'synthetic', 'lazy' => 'lazy', 'public' => 'public', 'abstract' => 'abstract', 'deprecated' => 'deprecated', 'factory' => 'factory', 'file' => 'file', 'arguments' => 'arguments', 'properties' => 'properties', 'configurator' => 'configurator', 'calls' => 'calls', 'tags' => 'tags', 'decorates' => 'decorates', 'decoration_inner_name' => 'decoration_inner_name', 'decoration_priority' => 'decoration_priority', 'decoration_on_invalid' => 'decoration_on_invalid', 'autowire' => 'autowire', 'autoconfigure' => 'autoconfigure', 'bind' => 'bind', 'constructor' => 'constructor'];
    private const PROTOTYPE_KEYWORDS = ['resource' => 'resource', 'namespace' => 'namespace', 'exclude' => 'exclude', 'parent' => 'parent', 'shared' => 'shared', 'lazy' => 'lazy', 'public' => 'public', 'abstract' => 'abstract', 'deprecated' => 'deprecated', 'factory' => 'factory', 'arguments' => 'arguments', 'properties' => 'properties', 'configurator' => 'configurator', 'calls' => 'calls', 'tags' => 'tags', 'autowire' => 'autowire', 'autoconfigure' => 'autoconfigure', 'bind' => 'bind', 'constructor' => 'constructor'];
    private const INSTANCEOF_KEYWORDS = ['shared' => 'shared', 'lazy' => 'lazy', 'public' => 'public', 'properties' => 'properties', 'configurator' => 'configurator', 'calls' => 'calls', 'tags' => 'tags', 'autowire' => 'autowire', 'bind' => 'bind', 'constructor' => 'constructor'];
    private const DEFAULTS_KEYWORDS = ['public' => 'public', 'tags' => 'tags', 'autowire' => 'autowire', 'autoconfigure' => 'autoconfigure', 'bind' => 'bind'];
    private YamlParser $yamlParser;
    private int $anonymousServicesCount;
    private string $anonymousServicesSuffix;
    protected $autoRegisterAliasesForSinglyImplementedInterfaces = \false;
    public function load(mixed $resource, ?string $type = null): mixed
    {
        $path = $this->locator->locate($resource);
        $content = $this->loadFile($path);
        $this->container->fileExists($path);
        // empty file
        if (null === $content) {
            return null;
        }
        $this->loadContent($content, $path);
        // per-env configuration
        if ($this->env && isset($content['when@' . $this->env])) {
            if (!\is_array($content['when@' . $this->env])) {
                throw new InvalidArgumentException(\sprintf('The "when@%s" key should contain an array in "%s". Check your YAML syntax.', $this->env, $path));
            }
            $env = $this->env;
            $this->env = null;
            try {
                $this->loadContent($content['when@' . $env], $path);
            } finally {
                $this->env = $env;
            }
        }
        return null;
    }
    private function loadContent(array $content, string $path): void
    {
        // imports
        $this->parseImports($content, $path);
        // parameters
        if (isset($content['parameters'])) {
            if (!\is_array($content['parameters'])) {
                throw new InvalidArgumentException(\sprintf('The "parameters" key should contain an array in "%s". Check your YAML syntax.', $path));
            }
            foreach ($content['parameters'] as $key => $value) {
                $this->container->setParameter($key, $this->resolveServices($value, $path, \true));
            }
        }
        // extensions
        $this->loadFromExtensions($content);
        // services
        $this->anonymousServicesCount = 0;
        $this->anonymousServicesSuffix = '~' . ContainerBuilder::hash($path);
        $this->setCurrentDir(\dirname($path));
        try {
            $this->parseDefinitions($content, $path);
        } finally {
            $this->instanceof = [];
            $this->registerAliasesForSinglyImplementedInterfaces();
        }
    }
    public function supports(mixed $resource, ?string $type = null): bool
    {
        if (!\is_string($resource)) {
            return \false;
        }
        if (null === $type && \in_array(pathinfo($resource, \PATHINFO_EXTENSION), ['yaml', 'yml'], \true)) {
            return \true;
        }
        return \in_array($type, ['yaml', 'yml'], \true);
    }
    private function parseImports(array $content, string $file): void
    {
        if (!isset($content['imports'])) {
            return;
        }
        if (!\is_array($content['imports'])) {
            throw new InvalidArgumentException(\sprintf('The "imports" key should contain an array in "%s". Check your YAML syntax.', $file));
        }
        $defaultDirectory = \dirname($file);
        foreach ($content['imports'] as $import) {
            if (!\is_array($import)) {
                $import = ['resource' => $import];
            }
            if (!isset($import['resource'])) {
                throw new InvalidArgumentException(\sprintf('An import should provide a resource in "%s". Check your YAML syntax.', $file));
            }
            $this->setCurrentDir($defaultDirectory);
            $this->import($import['resource'], $import['type'] ?? null, $import['ignore_errors'] ?? \false, $file);
        }
    }
    private function parseDefinitions(array $content, string $file, bool $trackBindings = \true): void
    {
        if (!isset($content['services'])) {
            return;
        }
        if (!\is_array($content['services'])) {
            throw new InvalidArgumentException(\sprintf('The "services" key should contain an array in "%s". Check your YAML syntax.', $file));
        }
        if (\array_key_exists('_instanceof', $content['services'])) {
            $instanceof = $content['services']['_instanceof'];
            unset($content['services']['_instanceof']);
            if (!\is_array($instanceof)) {
                throw new InvalidArgumentException(\sprintf('Service "_instanceof" key must be an array, "%s" given in "%s".', get_debug_type($instanceof), $file));
            }
            $this->instanceof = [];
            $this->isLoadingInstanceof = \true;
            foreach ($instanceof as $id => $service) {
                if (!$service || !\is_array($service)) {
                    throw new InvalidArgumentException(\sprintf('Type definition "%s" must be a non-empty array within "_instanceof" in "%s". Check your YAML syntax.', $id, $file));
                }
                if (\is_string($service) && str_starts_with($service, '@')) {
                    throw new InvalidArgumentException(\sprintf('Type definition "%s" cannot be an alias within "_instanceof" in "%s". Check your YAML syntax.', $id, $file));
                }
                $this->parseDefinition($id, $service, $file, [], \false, $trackBindings);
            }
        }
        $this->isLoadingInstanceof = \false;
        $defaults = $this->parseDefaults($content, $file);
        foreach ($content['services'] as $id => $service) {
            $this->parseDefinition($id, $service, $file, $defaults, \false, $trackBindings);
        }
    }
    /**
     * @throws InvalidArgumentException
     */
    private function parseDefaults(array &$content, string $file): array
    {
        if (!\array_key_exists('_defaults', $content['services'])) {
            return [];
        }
        $defaults = $content['services']['_defaults'];
        unset($content['services']['_defaults']);
        if (!\is_array($defaults)) {
            throw new InvalidArgumentException(\sprintf('Service "_defaults" key must be an array, "%s" given in "%s".', get_debug_type($defaults), $file));
        }
        foreach ($defaults as $key => $default) {
            if (!isset(self::DEFAULTS_KEYWORDS[$key])) {
                throw new InvalidArgumentException(\sprintf('The configuration key "%s" cannot be used to define a default value in "%s". Allowed keys are "%s".', $key, $file, implode('", "', self::DEFAULTS_KEYWORDS)));
            }
        }
        if (isset($defaults['tags'])) {
            if (!\is_array($tags = $defaults['tags'])) {
                throw new InvalidArgumentException(\sprintf('Parameter "tags" in "_defaults" must be an array in "%s". Check your YAML syntax.', $file));
            }
            foreach ($tags as $tag) {
                if (!\is_array($tag)) {
                    $tag = ['name' => $tag];
                }
                if (1 === \count($tag) && \is_array(current($tag))) {
                    $name = key($tag);
                    $tag = current($tag);
                } else {
                    if (!isset($tag['name'])) {
                        throw new InvalidArgumentException(\sprintf('A "tags" entry in "_defaults" is missing a "name" key in "%s".', $file));
                    }
                    $name = $tag['name'];
                    unset($tag['name']);
                }
                if (!\is_string($name) || '' === $name) {
                    throw new InvalidArgumentException(\sprintf('The tag name in "_defaults" must be a non-empty string in "%s".', $file));
                }
                $this->validateAttributes(\sprintf('Tag "%s", attribute "%s" in "_defaults" must be of a scalar-type in "%s". Check your YAML syntax.', $name, '%s', $file), $tag);
            }
        }
        if (isset($defaults['bind'])) {
            if (!\is_array($defaults['bind'])) {
                throw new InvalidArgumentException(\sprintf('Parameter "bind" in "_defaults" must be an array in "%s". Check your YAML syntax.', $file));
            }
            foreach ($this->resolveServices($defaults['bind'], $file) as $argument => $value) {
                $defaults['bind'][$argument] = new BoundArgument($value, \true, BoundArgument::DEFAULTS_BINDING, $file);
            }
        }
        return $defaults;
    }
    private function isUsingShortSyntax(array $service): bool
    {
        foreach ($service as $key => $value) {
            if (\is_string($key) && ('' === $key || '$' !== $key[0] && !str_contains($key, '\\'))) {
                return \false;
            }
        }
        return \true;
    }
    /**
     * @throws InvalidArgumentException When tags are invalid
     */
    private function parseDefinition(string $id, array|string|null $service, string $file, array $defaults, bool $return = \false, bool $trackBindings = \true): Definition|Alias|null
    {
        if (preg_match('/^_[a-zA-Z0-9_]*$/', $id)) {
            throw new InvalidArgumentException(\sprintf('Service names that start with an underscore are reserved. Rename the "%s" service or define it in XML instead.', $id));
        }
        if (\is_string($service) && str_starts_with($service, '@')) {
            $alias = new Alias(substr($service, 1));
            if (isset($defaults['public'])) {
                $alias->setPublic($defaults['public']);
            }
            return $return ? $alias : $this->container->setAlias($id, $alias);
        }
        if (\is_array($service) && $this->isUsingShortSyntax($service)) {
            $service = ['arguments' => $service];
        }
        if (!\is_array($service ??= [])) {
            throw new InvalidArgumentException(\sprintf('A service definition must be an array or a string starting with "@" but "%s" found for service "%s" in "%s". Check your YAML syntax.', get_debug_type($service), $id, $file));
        }
        if (isset($service['stack'])) {
            if (!\is_array($service['stack'])) {
                throw new InvalidArgumentException(\sprintf('A stack must be an array of definitions, "%s" given for service "%s" in "%s". Check your YAML syntax.', get_debug_type($service), $id, $file));
            }
            $stack = [];
            foreach ($service['stack'] as $k => $frame) {
                if (\is_array($frame) && 1 === \count($frame) && !isset(self::SERVICE_KEYWORDS[key($frame)])) {
                    $frame = ['class' => key($frame), 'arguments' => current($frame)];
                }
                if (\is_array($frame) && isset($frame['stack'])) {
                    throw new InvalidArgumentException(\sprintf('Service stack "%s" cannot contain another stack in "%s".', $id, $file));
                }
                $definition = $this->parseDefinition($id . '" at index "' . $k, $frame, $file, $defaults, \true);
                if ($definition instanceof Definition) {
                    $definition->setInstanceofConditionals($this->instanceof);
                }
                $stack[$k] = $definition;
            }
            if ($diff = array_diff(array_keys($service), ['stack', 'public', 'deprecated'])) {
                throw new InvalidArgumentException(\sprintf('Invalid attribute "%s"; supported ones are "public" and "deprecated" for service "%s" in "%s". Check your YAML syntax.', implode('", "', $diff), $id, $file));
            }
            $service = ['parent' => '', 'arguments' => $stack, 'tags' => ['container.stack'], 'public' => $service['public'] ?? null, 'deprecated' => $service['deprecated'] ?? null];
        }
        $definition = isset($service[0]) && $service[0] instanceof Definition ? array_shift($service) : null;
        $return = null === $definition ? $return : \true;
        if (isset($service['from_callable'])) {
            foreach (['alias', 'parent', 'synthetic', 'factory', 'file', 'arguments', 'properties', 'configurator', 'calls'] as $key) {
                if (isset($service['factory'])) {
                    throw new InvalidArgumentException(\sprintf('The configuration key "%s" is unsupported for the service "%s" when using "from_callable" in "%s".', $key, $id, $file));
                }
            }
            if ('Closure' !== $service['class'] ??= 'Closure') {
                $service['lazy'] = \true;
            }
            $service['factory'] = ['Closure', 'fromCallable'];
            $service['arguments'] = [$service['from_callable']];
            unset($service['from_callable']);
        }
        $this->checkDefinition($id, $service, $file);
        if (isset($service['alias'])) {
            $alias = new Alias($service['alias']);
            if (isset($service['public'])) {
                $alias->setPublic($service['public']);
            } elseif (isset($defaults['public'])) {
                $alias->setPublic($defaults['public']);
            }
            foreach ($service as $key => $value) {
                if (!\in_array($key, ['alias', 'public', 'deprecated'])) {
                    throw new InvalidArgumentException(\sprintf('The configuration key "%s" is unsupported for the service "%s" which is defined as an alias in "%s". Allowed configuration keys for service aliases are "alias", "public" and "deprecated".', $key, $id, $file));
                }
                if ('deprecated' === $key) {
                    $deprecation = \is_array($value) ? $value : ['message' => $value];
                    if (!isset($deprecation['package'])) {
                        throw new InvalidArgumentException(\sprintf('Missing attribute "package" of the "deprecated" option in "%s".', $file));
                    }
                    if (!isset($deprecation['version'])) {
                        throw new InvalidArgumentException(\sprintf('Missing attribute "version" of the "deprecated" option in "%s".', $file));
                    }
                    $alias->setDeprecated($deprecation['package'] ?? '', $deprecation['version'] ?? '', $deprecation['message'] ?? '');
                }
            }
            return $return ? $alias : $this->container->setAlias($id, $alias);
        }
        $changes = [];
        if (null !== $definition) {
            $changes = $definition->getChanges();
        } elseif ($this->isLoadingInstanceof) {
            $definition = new ChildDefinition('');
        } elseif (isset($service['parent'])) {
            if ('' !== $service['parent'] && '@' === $service['parent'][0]) {
                throw new InvalidArgumentException(\sprintf('The value of the "parent" option for the "%s" service must be the id of the service without the "@" prefix (replace "%s" with "%s").', $id, $service['parent'], substr($service['parent'], 1)));
            }
            $definition = new ChildDefinition($service['parent']);
        } else {
            $definition = new Definition();
        }
        if (isset($defaults['public'])) {
            $definition->setPublic($defaults['public']);
        }
        if (isset($defaults['autowire'])) {
            $definition->setAutowired($defaults['autowire']);
        }
        if (isset($defaults['autoconfigure'])) {
            $definition->setAutoconfigured($defaults['autoconfigure']);
        }
        $definition->setChanges($changes);
        if (isset($service['class'])) {
            $definition->setClass($service['class']);
        }
        if (isset($service['shared'])) {
            $definition->setShared($service['shared']);
        }
        if (isset($service['synthetic'])) {
            $definition->setSynthetic($service['synthetic']);
        }
        if (isset($service['lazy'])) {
            $definition->setLazy((bool) $service['lazy']);
            if (\is_string($service['lazy'])) {
                $definition->addTag('proxy', ['interface' => $service['lazy']]);
            }
        }
        if (isset($service['public'])) {
            $definition->setPublic($service['public']);
        }
        if (isset($service['abstract'])) {
            $definition->setAbstract($service['abstract']);
        }
        if (isset($service['deprecated'])) {
            $deprecation = \is_array($service['deprecated']) ? $service['deprecated'] : ['message' => $service['deprecated']];
            if (!isset($deprecation['package'])) {
                throw new InvalidArgumentException(\sprintf('Missing attribute "package" of the "deprecated" option in "%s".', $file));
            }
            if (!isset($deprecation['version'])) {
                throw new InvalidArgumentException(\sprintf('Missing attribute "version" of the "deprecated" option in "%s".', $file));
            }
            $definition->setDeprecated($deprecation['package'] ?? '', $deprecation['version'] ?? '', $deprecation['message'] ?? '');
        }
        if (isset($service['factory'])) {
            $definition->setFactory($this->parseCallable($service['factory'], 'factory', $id, $file));
        }
        if (isset($service['constructor'])) {
            if (null !== $definition->getFactory()) {
                throw new LogicException(\sprintf('The "%s" service cannot declare a factory as well as a constructor.', $id));
            }
            $definition->setFactory([null, $service['constructor']]);
        }
        if (isset($service['file'])) {
            $definition->setFile($service['file']);
        }
        if (isset($service['arguments'])) {
            $definition->setArguments($this->resolveServices($service['arguments'], $file));
        }
        if (isset($service['properties'])) {
            $definition->setProperties($this->resolveServices($service['properties'], $file));
        }
        if (isset($service['configurator'])) {
            $definition->setConfigurator($this->parseCallable($service['configurator'], 'configurator', $id, $file));
        }
        if (isset($service['calls'])) {
            if (!\is_array($service['calls'])) {
                throw new InvalidArgumentException(\sprintf('Parameter "calls" must be an array for service "%s" in "%s". Check your YAML syntax.', $id, $file));
            }
            foreach ($service['calls'] as $k => $call) {
                if (!\is_array($call) && (!\is_string($k) || !$call instanceof TaggedValue)) {
                    throw new InvalidArgumentException(\sprintf('Invalid method call for service "%s": expected map or array, "%s" given in "%s".', $id, $call instanceof TaggedValue ? '!' . $call->getTag() : get_debug_type($call), $file));
                }
                if (\is_string($k)) {
                    throw new InvalidArgumentException(\sprintf('Invalid method call for service "%s", did you forget a leading dash before "%s: ..." in "%s"?', $id, $k, $file));
                }
                if (isset($call['method']) && \is_string($call['method'])) {
                    $method = $call['method'];
                    $args = $call['arguments'] ?? [];
                    $returnsClone = $call['returns_clone'] ?? \false;
                } else if (1 === \count($call) && \is_string(key($call))) {
                    $method = key($call);
                    $args = $call[$method];
                    if ($args instanceof TaggedValue) {
                        if ('returns_clone' !== $args->getTag()) {
                            throw new InvalidArgumentException(\sprintf('Unsupported tag "!%s", did you mean "!returns_clone" for service "%s" in "%s"?', $args->getTag(), $id, $file));
                        }
                        $returnsClone = \true;
                        $args = $args->getValue();
                    } else {
                        $returnsClone = \false;
                    }
                } elseif (empty($call[0])) {
                    throw new InvalidArgumentException(\sprintf('Invalid call for service "%s": the method must be defined as the first index of an array or as the only key of a map in "%s".', $id, $file));
                } else {
                    $method = $call[0];
                    $args = $call[1] ?? [];
                    $returnsClone = $call[2] ?? \false;
                }
                if (!\is_array($args)) {
                    throw new InvalidArgumentException(\sprintf('The second parameter for function call "%s" must be an array of its arguments for service "%s" in "%s". Check your YAML syntax.', $method, $id, $file));
                }
                $args = $this->resolveServices($args, $file);
                $definition->addMethodCall($method, $args, $returnsClone);
            }
        }
        $tags = $service['tags'] ?? [];
        if (!\is_array($tags)) {
            throw new InvalidArgumentException(\sprintf('Parameter "tags" must be an array for service "%s" in "%s". Check your YAML syntax.', $id, $file));
        }
        if (isset($defaults['tags'])) {
            $tags = array_merge($tags, $defaults['tags']);
        }
        foreach ($tags as $tag) {
            if (!\is_array($tag)) {
                $tag = ['name' => $tag];
            }
            if (1 === \count($tag) && \is_array(current($tag))) {
                $name = key($tag);
                $tag = current($tag);
            } else {
                if (!isset($tag['name'])) {
                    throw new InvalidArgumentException(\sprintf('A "tags" entry is missing a "name" key for service "%s" in "%s".', $id, $file));
                }
                $name = $tag['name'];
                unset($tag['name']);
            }
            if (!\is_string($name) || '' === $name) {
                throw new InvalidArgumentException(\sprintf('The tag name for service "%s" in "%s" must be a non-empty string.', $id, $file));
            }
            $this->validateAttributes(\sprintf('A "tags" attribute must be of a scalar-type for service "%s", tag "%s", attribute "%s" in "%s". Check your YAML syntax.', $id, $name, '%s', $file), $tag);
            $definition->addTag($name, $tag);
        }
        if (null !== $decorates = $service['decorates'] ?? null) {
            if ('' !== $decorates && '@' === $decorates[0]) {
                throw new InvalidArgumentException(\sprintf('The value of the "decorates" option for the "%s" service must be the id of the service without the "@" prefix (replace "%s" with "%s").', $id, $service['decorates'], substr($decorates, 1)));
            }
            $decorationOnInvalid = \array_key_exists('decoration_on_invalid', $service) ? $service['decoration_on_invalid'] : 'exception';
            if ('exception' === $decorationOnInvalid) {
                $invalidBehavior = ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE;
            } elseif ('ignore' === $decorationOnInvalid) {
                $invalidBehavior = ContainerInterface::IGNORE_ON_INVALID_REFERENCE;
            } elseif (null === $decorationOnInvalid) {
                $invalidBehavior = ContainerInterface::NULL_ON_INVALID_REFERENCE;
            } elseif ('null' === $decorationOnInvalid) {
                throw new InvalidArgumentException(\sprintf('Invalid value "%s" for attribute "decoration_on_invalid" on service "%s". Did you mean null (without quotes) in "%s"?', $decorationOnInvalid, $id, $file));
            } else {
                throw new InvalidArgumentException(\sprintf('Invalid value "%s" for attribute "decoration_on_invalid" on service "%s". Did you mean "exception", "ignore" or null in "%s"?', $decorationOnInvalid, $id, $file));
            }
            $renameId = $service['decoration_inner_name'] ?? null;
            $priority = $service['decoration_priority'] ?? 0;
            $definition->setDecoratedService($decorates, $renameId, $priority, $invalidBehavior);
        }
        if (isset($service['autowire'])) {
            $definition->setAutowired($service['autowire']);
        }
        if (isset($defaults['bind']) || isset($service['bind'])) {
            // deep clone, to avoid multiple process of the same instance in the passes
            $bindings = $definition->getBindings();
            $bindings += isset($defaults['bind']) ? unserialize(serialize($defaults['bind'])) : [];
            if (isset($service['bind'])) {
                if (!\is_array($service['bind'])) {
                    throw new InvalidArgumentException(\sprintf('Parameter "bind" must be an array for service "%s" in "%s". Check your YAML syntax.', $id, $file));
                }
                $bindings = array_merge($bindings, $this->resolveServices($service['bind'], $file));
                $bindingType = $this->isLoadingInstanceof ? BoundArgument::INSTANCEOF_BINDING : BoundArgument::SERVICE_BINDING;
                foreach ($bindings as $argument => $value) {
                    if (!$value instanceof BoundArgument) {
                        $bindings[$argument] = new BoundArgument($value, $trackBindings, $bindingType, $file);
                    }
                }
            }
            $definition->setBindings($bindings);
        }
        if (isset($service['autoconfigure'])) {
            $definition->setAutoconfigured($service['autoconfigure']);
        }
        if (\array_key_exists('namespace', $service) && !\array_key_exists('resource', $service)) {
            throw new InvalidArgumentException(\sprintf('A "resource" attribute must be set when the "namespace" attribute is set for service "%s" in "%s". Check your YAML syntax.', $id, $file));
        }
        if ($return) {
            if (\array_key_exists('resource', $service)) {
                throw new InvalidArgumentException(\sprintf('Invalid "resource" attribute found for service "%s" in "%s". Check your YAML syntax.', $id, $file));
            }
            return $definition;
        }
        if (\array_key_exists('resource', $service)) {
            if (!\is_string($service['resource'])) {
                throw new InvalidArgumentException(\sprintf('A "resource" attribute must be of type string for service "%s" in "%s". Check your YAML syntax.', $id, $file));
            }
            $exclude = $service['exclude'] ?? null;
            $namespace = $service['namespace'] ?? $id;
            $this->registerClasses($definition, $namespace, $service['resource'], $exclude, $file);
        } else {
            $this->setDefinition($id, $definition);
        }
        return null;
    }
    /**
     * @throws InvalidArgumentException When errors occur
     */
    private function parseCallable(mixed $callable, string $parameter, string $id, string $file): string|array|Reference
    {
        if (\is_string($callable)) {
            if (str_starts_with($callable, '@=')) {
                if ('factory' !== $parameter) {
                    throw new InvalidArgumentException(\sprintf('Using expressions in "%s" for the "%s" service is not supported in "%s".', $parameter, $id, $file));
                }
                if (!class_exists(Expression::class)) {
                    throw new \LogicException('The "@=" expression syntax cannot be used without the ExpressionLanguage component. Try running "composer require symfony/expression-language".');
                }
                return $callable;
            }
            if ('' !== $callable && '@' === $callable[0]) {
                if (!str_contains($callable, ':')) {
                    return [$this->resolveServices($callable, $file), '__invoke'];
                }
                throw new InvalidArgumentException(\sprintf('The value of the "%s" option for the "%s" service must be the id of the service without the "@" prefix (replace "%s" with "%s" in "%s").', $parameter, $id, $callable, substr($callable, 1), $file));
            }
            return $callable;
        }
        if (\is_array($callable)) {
            if (isset($callable[0]) && isset($callable[1])) {
                return [$this->resolveServices($callable[0], $file), $callable[1]];
            }
            if ('factory' === $parameter && isset($callable[1]) && null === $callable[0]) {
                return $callable;
            }
            throw new InvalidArgumentException(\sprintf('Parameter "%s" must contain an array with two elements for service "%s" in "%s". Check your YAML syntax.', $parameter, $id, $file));
        }
        throw new InvalidArgumentException(\sprintf('Parameter "%s" must be a string or an array for service "%s" in "%s". Check your YAML syntax.', $parameter, $id, $file));
    }
    /**
     * Loads a YAML file.
     *
     * @throws InvalidArgumentException when the given file is not a local file or when it does not exist
     */
    protected function loadFile(string $file): ?array
    {
        if (!class_exists(YamlParser::class)) {
            throw new RuntimeException('Unable to load YAML config files as the Symfony Yaml Component is not installed. Try running "composer require symfony/yaml".');
        }
        if (!stream_is_local($file)) {
            throw new InvalidArgumentException(\sprintf('This is not a local file "%s".', $file));
        }
        if (!is_file($file)) {
            throw new InvalidArgumentException(\sprintf('The file "%s" does not exist.', $file));
        }
        $this->yamlParser ??= new YamlParser();
        try {
            $configuration = $this->yamlParser->parseFile($file, Yaml::PARSE_CONSTANT | Yaml::PARSE_CUSTOM_TAGS);
        } catch (ParseException $e) {
            throw new InvalidArgumentException(\sprintf('The file "%s" does not contain valid YAML: ', $file) . $e->getMessage(), 0, $e);
        }
        return $this->validate($configuration, $file);
    }
    /**
     * Validates a YAML file.
     *
     * @throws InvalidArgumentException When service file is not valid
     */
    private function validate(mixed $content, string $file): ?array
    {
        if (null === $content) {
            return $content;
        }
        if (!\is_array($content)) {
            throw new InvalidArgumentException(\sprintf('The service file "%s" is not valid. It should contain an array. Check your YAML syntax.', $file));
        }
        foreach ($content as $namespace => $data) {
            if (\in_array($namespace, ['imports', 'parameters', 'services']) || str_starts_with($namespace, 'when@')) {
                continue;
            }
            if (!$this->container->hasExtension($namespace)) {
                $extensionNamespaces = array_filter(array_map(fn(ExtensionInterface $ext) => $ext->getAlias(), $this->container->getExtensions()));
                throw new InvalidArgumentException(\sprintf('There is no extension able to load the configuration for "%s" (in "%s"). Looked for namespace "%s", found "%s".', $namespace, $file, $namespace, $extensionNamespaces ? \sprintf('"%s"', implode('", "', $extensionNamespaces)) : 'none'));
            }
        }
        return $content;
    }
    private function resolveServices(mixed $value, string $file, bool $isParameter = \false): mixed
    {
        if ($value instanceof TaggedValue) {
            $argument = $value->getValue();
            if ('closure' === $value->getTag()) {
                $argument = $this->resolveServices($argument, $file, $isParameter);
                return (new Definition('Closure'))->setFactory(['Closure', 'fromCallable'])->addArgument($argument);
            }
            if ('iterator' === $value->getTag()) {
                if (!\is_array($argument)) {
                    throw new InvalidArgumentException(\sprintf('"!iterator" tag only accepts sequences in "%s".', $file));
                }
                $argument = $this->resolveServices($argument, $file, $isParameter);
                return new IteratorArgument($argument);
            }
            if ('service_closure' === $value->getTag()) {
                $argument = $this->resolveServices($argument, $file, $isParameter);
                return new ServiceClosureArgument($argument);
            }
            if ('service_locator' === $value->getTag()) {
                if (!\is_array($argument)) {
                    throw new InvalidArgumentException(\sprintf('"!service_locator" tag only accepts maps in "%s".', $file));
                }
                $argument = $this->resolveServices($argument, $file, $isParameter);
                if (isset($argument[0])) {
                    trigger_deprecation('symfony/dependency-injection', '6.3', 'Using integers as keys in a "!service_locator" tag is deprecated. The keys will default to the IDs of the original services in 7.0.');
                }
                return new ServiceLocatorArgument($argument);
            }
            if (\in_array($value->getTag(), ['tagged', 'tagged_iterator', 'tagged_locator'], \true)) {
                $forLocator = 'tagged_locator' === $value->getTag();
                if (\is_array($argument) && isset($argument['tag']) && $argument['tag']) {
                    if ($diff = array_diff(array_keys($argument), $supportedKeys = ['tag', 'index_by', 'default_index_method', 'default_priority_method', 'exclude', 'exclude_self'])) {
                        throw new InvalidArgumentException(\sprintf('"!%s" tag contains unsupported key "%s"; supported ones are "%s".', $value->getTag(), implode('", "', $diff), implode('", "', $supportedKeys)));
                    }
                    $argument = new TaggedIteratorArgument($argument['tag'], $argument['index_by'] ?? null, $argument['default_index_method'] ?? null, $forLocator, $argument['default_priority_method'] ?? null, (array) ($argument['exclude'] ?? null), $argument['exclude_self'] ?? \true);
                } elseif (\is_string($argument) && $argument) {
                    $argument = new TaggedIteratorArgument($argument, null, null, $forLocator);
                } else {
                    throw new InvalidArgumentException(\sprintf('"!%s" tags only accept a non empty string or an array with a key "tag" in "%s".', $value->getTag(), $file));
                }
                if ($forLocator) {
                    $argument = new ServiceLocatorArgument($argument);
                }
                return $argument;
            }
            if ('service' === $value->getTag()) {
                if ($isParameter) {
                    throw new InvalidArgumentException(\sprintf('Using an anonymous service in a parameter is not allowed in "%s".', $file));
                }
                $isLoadingInstanceof = $this->isLoadingInstanceof;
                $this->isLoadingInstanceof = \false;
                $instanceof = $this->instanceof;
                $this->instanceof = [];
                $id = \sprintf('.%d_%s', ++$this->anonymousServicesCount, preg_replace('/^.*\\\\/', '', $argument['class'] ?? '') . $this->anonymousServicesSuffix);
                $this->parseDefinition($id, $argument, $file, []);
                if (!$this->container->hasDefinition($id)) {
                    throw new InvalidArgumentException(\sprintf('Creating an alias using the tag "!service" is not allowed in "%s".', $file));
                }
                $this->container->getDefinition($id);
                $this->isLoadingInstanceof = $isLoadingInstanceof;
                $this->instanceof = $instanceof;
                return new Reference($id);
            }
            if ('abstract' === $value->getTag()) {
                return new AbstractArgument($value->getValue());
            }
            throw new InvalidArgumentException(\sprintf('Unsupported tag "!%s".', $value->getTag()));
        }
        if (\is_array($value)) {
            foreach ($value as $k => $v) {
                $value[$k] = $this->resolveServices($v, $file, $isParameter);
            }
        } elseif (\is_string($value) && str_starts_with($value, '@=')) {
            if ($isParameter) {
                throw new InvalidArgumentException(\sprintf('Using expressions in parameters is not allowed in "%s".', $file));
            }
            if (!class_exists(Expression::class)) {
                throw new \LogicException('The "@=" expression syntax cannot be used without the ExpressionLanguage component. Try running "composer require symfony/expression-language".');
            }
            return new Expression(substr($value, 2));
        } elseif (\is_string($value) && str_starts_with($value, '@')) {
            if (str_starts_with($value, '@@')) {
                $value = substr($value, 1);
                $invalidBehavior = null;
            } elseif (str_starts_with($value, '@!')) {
                $value = substr($value, 2);
                $invalidBehavior = ContainerInterface::IGNORE_ON_UNINITIALIZED_REFERENCE;
            } elseif (str_starts_with($value, '@?')) {
                $value = substr($value, 2);
                $invalidBehavior = ContainerInterface::IGNORE_ON_INVALID_REFERENCE;
            } else {
                $value = substr($value, 1);
                $invalidBehavior = ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE;
            }
            if (null !== $invalidBehavior) {
                $value = new Reference($value, $invalidBehavior);
            }
        }
        return $value;
    }
    private function loadFromExtensions(array $content): void
    {
        foreach ($content as $namespace => $values) {
            if (\in_array($namespace, ['imports', 'parameters', 'services']) || str_starts_with($namespace, 'when@')) {
                continue;
            }
            if (!\is_array($values) && null !== $values) {
                $values = [];
            }
            $this->container->loadFromExtension($namespace, $values);
        }
    }
    private function checkDefinition(string $id, array $definition, string $file): void
    {
        if ($this->isLoadingInstanceof) {
            $keywords = self::INSTANCEOF_KEYWORDS;
        } elseif (isset($definition['resource']) || isset($definition['namespace'])) {
            $keywords = self::PROTOTYPE_KEYWORDS;
        } else {
            $keywords = self::SERVICE_KEYWORDS;
        }
        foreach ($definition as $key => $value) {
            if (!isset($keywords[$key])) {
                throw new InvalidArgumentException(\sprintf('The configuration key "%s" is unsupported for definition "%s" in "%s". Allowed configuration keys are "%s".', $key, $id, $file, implode('", "', $keywords)));
            }
        }
    }
    private function validateAttributes(string $message, array $attributes, array $path = []): void
    {
        foreach ($attributes as $name => $value) {
            if (\is_array($value)) {
                $this->validateAttributes($message, $value, [...$path, $name]);
            } elseif (!\is_scalar($value ?? '')) {
                $name = implode('.', [...$path, $name]);
                throw new InvalidArgumentException(\sprintf($message, $name));
            }
        }
    }
}
<?xml version="1.0" encoding="UTF-8" ?>

<xsd:schema xmlns="http://symfony.com/schema/dic/services"
     xmlns:xsd="http://www.w3.org/2001/XMLSchema"
     targetNamespace="http://symfony.com/schema/dic/services"
     elementFormDefault="qualified">

  <xsd:annotation>
    <xsd:documentation><![CDATA[
      Symfony XML Services Schema, version 1.0
      Authors: Fabien Potencier

      This defines a way to describe PHP objects (services) and their
      dependencies.
    ]]></xsd:documentation>
  </xsd:annotation>

  <xsd:element name="container" type="container" />

  <xsd:complexType name="container">
    <xsd:annotation>
      <xsd:documentation><![CDATA[
        The root element of a service file.
      ]]></xsd:documentation>
    </xsd:annotation>
    <xsd:sequence>
      <xsd:group ref="foreign" />
      <xsd:sequence minOccurs="0">
        <xsd:element name="imports" type="imports" />
        <xsd:group ref="foreign" />
      </xsd:sequence>
      <xsd:sequence minOccurs="0">
        <xsd:element name="parameters" type="parameters" />
        <xsd:group ref="foreign" />
      </xsd:sequence>
      <xsd:sequence minOccurs="0">
        <xsd:element name="services" type="services" />
        <xsd:group ref="foreign" />
      </xsd:sequence>
      <xsd:sequence minOccurs="0" maxOccurs="unbounded">
        <xsd:element name="when" type="when" />
      </xsd:sequence>
    </xsd:sequence>
  </xsd:complexType>

  <xsd:complexType name="when">
    <xsd:sequence>
      <xsd:group ref="foreign" />
      <xsd:sequence minOccurs="0">
        <xsd:element name="imports" type="imports" />
        <xsd:group ref="foreign" />
      </xsd:sequence>
      <xsd:sequence minOccurs="0">
        <xsd:element name="parameters" type="parameters" />
        <xsd:group ref="foreign" />
      </xsd:sequence>
      <xsd:sequence minOccurs="0">
        <xsd:element name="services" type="services" />
        <xsd:group ref="foreign" />
      </xsd:sequence>
    </xsd:sequence>
    <xsd:attribute name="env" type="xsd:string" use="required" />
  </xsd:complexType>

  <xsd:group name="foreign">
    <xsd:sequence>
      <xsd:any namespace="##other" processContents="lax" minOccurs="0" maxOccurs="unbounded" />
    </xsd:sequence>
  </xsd:group>

  <xsd:complexType name="services">
    <xsd:annotation>
      <xsd:documentation><![CDATA[
        Enclosing element for the definition of all services
      ]]></xsd:documentation>
    </xsd:annotation>
    <xsd:choice maxOccurs="unbounded">
      <xsd:element name="service" type="service" minOccurs="1" />
      <xsd:element name="prototype" type="prototype" minOccurs="0" />
      <xsd:element name="defaults" type="defaults" minOccurs="0" maxOccurs="1" />
      <xsd:element name="instanceof" type="instanceof" minOccurs="0" />
      <xsd:element name="stack" type="stack" minOccurs="0" />
    </xsd:choice>
  </xsd:complexType>

  <xsd:complexType name="imports">
    <xsd:annotation>
      <xsd:documentation><![CDATA[
        Enclosing element for the import elements
      ]]></xsd:documentation>
    </xsd:annotation>
    <xsd:choice minOccurs="1" maxOccurs="unbounded">
      <xsd:element name="import" type="import" />
    </xsd:choice>
  </xsd:complexType>

  <xsd:complexType name="import">
    <xsd:annotation>
      <xsd:documentation><![CDATA[
        Import an external resource defining other services or parameters
      ]]></xsd:documentation>
    </xsd:annotation>
    <xsd:attribute name="resource" type="xsd:string" use="required" />
    <xsd:attribute name="ignore-errors" type="ignore_errors" />
    <xsd:attribute name="type" type="xsd:string" />
  </xsd:complexType>

  <xsd:complexType name="callable">
    <xsd:choice minOccurs="0" maxOccurs="1">
      <xsd:element name="service" type="service" minOccurs="0" maxOccurs="1" />
    </xsd:choice>
    <xsd:attribute name="service" type="xsd:string" />
    <xsd:attribute name="class" type="xsd:string" />
    <xsd:attribute name="method" type="xsd:string" />
    <xsd:attribute name="function" type="xsd:string" />
  </xsd:complexType>

  <xsd:complexType name="factory">
    <xsd:choice minOccurs="0" maxOccurs="1">
      <xsd:element name="service" type="service" minOccurs="0" maxOccurs="1" />
    </xsd:choice>
    <xsd:attribute name="service" type="xsd:string" />
    <xsd:attribute name="class" type="xsd:string" />
    <xsd:attribute name="method" type="xsd:string" />
    <xsd:attribute name="function" type="xsd:string" />
    <xsd:attribute name="expression" type="xsd:string" />
  </xsd:complexType>

  <xsd:complexType name="defaults">
    <xsd:annotation>
      <xsd:documentation><![CDATA[
        Enclosing element for the service definitions' defaults for the current file
      ]]></xsd:documentation>
    </xsd:annotation>
    <xsd:choice maxOccurs="unbounded">
      <xsd:element name="tag" type="tag" minOccurs="0" maxOccurs="unbounded" />
      <xsd:element name="bind" type="bind" minOccurs="0" maxOccurs="unbounded" />
    </xsd:choice>
    <xsd:attribute name="public" type="boolean" />
    <xsd:attribute name="autowire" type="boolean" />
    <xsd:attribute name="autoconfigure" type="boolean" />
  </xsd:complexType>

  <xsd:complexType name="service">
    <xsd:choice maxOccurs="unbounded">
      <xsd:element name="file" type="xsd:string" minOccurs="0" maxOccurs="1" />
      <xsd:element name="argument" type="argument" minOccurs="0" maxOccurs="unbounded" />
      <xsd:element name="configurator" type="callable" minOccurs="0" maxOccurs="1" />
      <xsd:element name="factory" type="factory" minOccurs="0" maxOccurs="1" />
      <xsd:element name="from-callable" type="factory" minOccurs="0" maxOccurs="1" />
      <xsd:element name="deprecated" type="deprecated" minOccurs="0" maxOccurs="1" />
      <xsd:element name="call" type="call" minOccurs="0" maxOccurs="unbounded" />
      <xsd:element name="tag" type="tag" minOccurs="0" maxOccurs="unbounded" />
      <xsd:element name="property" type="property" minOccurs="0" maxOccurs="unbounded" />
      <xsd:element name="bind" type="bind" minOccurs="0" maxOccurs="unbounded" />
    </xsd:choice>
    <xsd:attribute name="id" type="xsd:string" />
    <xsd:attribute name="class" type="xsd:string" />
    <xsd:attribute name="shared" type="boolean" />
    <xsd:attribute name="public" type="boolean" />
    <xsd:attribute name="synthetic" type="boolean" />
    <xsd:attribute name="lazy" type="xsd:string" />
    <xsd:attribute name="abstract" type="boolean" />
    <xsd:attribute name="alias" type="xsd:string" />
    <xsd:attribute name="parent" type="xsd:string" />
    <xsd:attribute name="decorates" type="xsd:string" />
    <xsd:attribute name="decoration-on-invalid" type="invalid_decorated_service_sequence" />
    <xsd:attribute name="decoration-inner-name" type="xsd:string" />
    <xsd:attribute name="decoration-priority" type="xsd:integer" />
    <xsd:attribute name="autowire" type="boolean" />
    <xsd:attribute name="autoconfigure" type="boolean" />
    <xsd:attribute name="constructor" type="xsd:string" />
  </xsd:complexType>

  <xsd:complexType name="instanceof">
    <xsd:choice maxOccurs="unbounded">
      <xsd:element name="configurator" type="callable" minOccurs="0" maxOccurs="1" />
      <xsd:element name="call" type="call" minOccurs="0" maxOccurs="unbounded" />
      <xsd:element name="tag" type="tag" minOccurs="0" maxOccurs="unbounded" />
      <xsd:element name="property" type="property" minOccurs="0" maxOccurs="unbounded" />
      <xsd:element name="bind" type="bind" minOccurs="0" maxOccurs="unbounded" />
    </xsd:choice>
    <xsd:attribute name="id" type="xsd:string" use="required" />
    <xsd:attribute name="shared" type="boolean" />
    <xsd:attribute name="public" type="boolean" />
    <xsd:attribute name="lazy" type="xsd:string" />
    <xsd:attribute name="autowire" type="boolean" />
    <xsd:attribute name="autoconfigure" type="boolean" />
    <xsd:attribute name="constructor" type="xsd:string" />
  </xsd:complexType>

  <xsd:complexType name="prototype">
    <xsd:choice maxOccurs="unbounded">
      <xsd:element name="argument" type="argument" minOccurs="0" maxOccurs="unbounded" />
      <xsd:element name="configurator" type="callable" minOccurs="0" maxOccurs="1" />
      <xsd:element name="factory" type="factory" minOccurs="0" maxOccurs="1" />
      <xsd:element name="deprecated" type="deprecated" minOccurs="0" maxOccurs="1" />
      <xsd:element name="call" type="call" minOccurs="0" maxOccurs="unbounded" />
      <xsd:element name="tag" type="tag" minOccurs="0" maxOccurs="unbounded" />
      <xsd:element name="property" type="property" minOccurs="0" maxOccurs="unbounded" />
      <xsd:element name="bind" type="bind" minOccurs="0" maxOccurs="unbounded" />
      <xsd:element name="exclude" type="xsd:string" minOccurs="0" maxOccurs="unbounded" />
    </xsd:choice>
    <xsd:attribute name="namespace" type="xsd:string" use="required" />
    <xsd:attribute name="resource" type="xsd:string" use="required" />
    <xsd:attribute name="exclude" type="xsd:string" />
    <xsd:attribute name="shared" type="boolean" />
    <xsd:attribute name="public" type="boolean" />
    <xsd:attribute name="lazy" type="xsd:string" />
    <xsd:attribute name="abstract" type="boolean" />
    <xsd:attribute name="parent" type="xsd:string" />
    <xsd:attribute name="autowire" type="boolean" />
    <xsd:attribute name="autoconfigure" type="boolean" />
    <xsd:attribute name="constructor" type="xsd:string" />
  </xsd:complexType>

  <xsd:complexType name="stack">
    <xsd:choice maxOccurs="unbounded">
      <xsd:element name="service" type="service" minOccurs="1" />
      <xsd:element name="deprecated" type="deprecated" minOccurs="0" maxOccurs="1" />
    </xsd:choice>
    <xsd:attribute name="id" type="xsd:string" use="required" />
    <xsd:attribute name="public" type="boolean" />
  </xsd:complexType>

  <xsd:complexType name="tag" mixed="true">
    <xsd:choice minOccurs="0">
      <xsd:element name="attribute" type="tag_attribute" maxOccurs="unbounded"/>
    </xsd:choice>
    <xsd:anyAttribute namespace="##any" processContents="lax" />
  </xsd:complexType>

  <xsd:complexType name="deprecated">
    <xsd:simpleContent>
      <xsd:extension base="xsd:string">
        <xsd:attribute name="package" type="xsd:string" use="required" />
        <xsd:attribute name="version" type="xsd:string" use="required" />
      </xsd:extension>
    </xsd:simpleContent>
  </xsd:complexType>

  <xsd:complexType name="tag_attribute" mixed="true">
    <xsd:choice minOccurs="0">
      <xsd:element name="attribute" type="tag_attribute" maxOccurs="unbounded" />
    </xsd:choice>
    <xsd:attribute name="name" type="xsd:string" use="required" />
  </xsd:complexType>

  <xsd:complexType name="parameters">
    <xsd:choice minOccurs="1" maxOccurs="unbounded">
      <xsd:element name="parameter" type="parameter" />
    </xsd:choice>
    <xsd:attribute name="type" type="parameter_type" />
    <xsd:attribute name="key" type="xsd:string" />
  </xsd:complexType>

  <xsd:complexType name="parameter" mixed="true">
    <xsd:choice minOccurs="0" maxOccurs="unbounded">
      <xsd:element name="parameter" type="parameter" />
    </xsd:choice>
    <xsd:attribute name="type" type="parameter_type" />
    <xsd:attribute name="id" type="xsd:string" />
    <xsd:attribute name="key" type="xsd:string" />
    <xsd:attribute name="on-invalid" type="invalid_sequence" />
    <xsd:attribute name="trim" type="xsd:boolean" />
  </xsd:complexType>

  <xsd:complexType name="property" mixed="true">
    <xsd:choice minOccurs="0">
      <xsd:element name="property" type="property" maxOccurs="unbounded" />
      <xsd:element name="service" type="service" />
    </xsd:choice>
    <xsd:attribute name="type" type="argument_type" />
    <xsd:attribute name="id" type="xsd:string" />
    <xsd:attribute name="key" type="xsd:string" />
    <xsd:attribute name="name" type="xsd:string" />
    <xsd:attribute name="on-invalid" type="invalid_sequence" />
    <xsd:attribute name="tag" type="xsd:string" />
  </xsd:complexType>

  <xsd:complexType name="bind" mixed="true">
    <xsd:choice maxOccurs="unbounded">
      <xsd:element name="bind" type="bind_argument" minOccurs="0" maxOccurs="unbounded" />
      <xsd:element name="service" type="service" />
    </xsd:choice>
    <xsd:attribute name="type" type="argument_type" />
    <xsd:attribute name="id" type="xsd:string" />
    <xsd:attribute name="key" type="xsd:string" use="required" />
    <xsd:attribute name="on-invalid" type="invalid_sequence" />
    <xsd:attribute name="method" type="xsd:string" />
    <xsd:attribute name="tag" type="xsd:string" />
  </xsd:complexType>

  <xsd:complexType name="bind_argument" mixed="true">
    <xsd:choice minOccurs="0">
      <xsd:element name="bind" type="bind_argument" maxOccurs="unbounded" />
      <xsd:element name="service" type="service" />
      <xsd:element name="exclude" type="xsd:string" maxOccurs="unbounded" />
    </xsd:choice>
    <xsd:attribute name="type" type="argument_type" />
    <xsd:attribute name="id" type="xsd:string" />
    <xsd:attribute name="key" type="xsd:string" />
    <xsd:attribute name="index" type="xsd:integer" />
    <xsd:attribute name="on-invalid" type="invalid_sequence" />
    <xsd:attribute name="tag" type="xsd:string" />
    <xsd:attribute name="index-by" type="xsd:string" />
    <xsd:attribute name="default-index-method" type="xsd:string" />
    <xsd:attribute name="default-priority-method" type="xsd:string" />
    <xsd:attribute name="exclude" type="xsd:string" />
  </xsd:complexType>

  <xsd:complexType name="argument" mixed="true">
    <xsd:choice minOccurs="0">
      <xsd:element name="argument" type="argument" maxOccurs="unbounded" />
      <xsd:element name="service" type="service" />
      <xsd:element name="exclude" type="xsd:string" maxOccurs="unbounded" />
    </xsd:choice>
    <xsd:attribute name="type" type="argument_type" />
    <xsd:attribute name="id" type="xsd:string" />
    <xsd:attribute name="key" type="xsd:string" />
    <xsd:attribute name="index" type="xsd:integer" />
    <xsd:attribute name="on-invalid" type="invalid_sequence" />
    <xsd:attribute name="tag" type="xsd:string" />
    <xsd:attribute name="index-by" type="xsd:string" />
    <xsd:attribute name="default-index-method" type="xsd:string" />
    <xsd:attribute name="default-priority-method" type="xsd:string" />
    <xsd:attribute name="exclude" type="xsd:string" />
    <xsd:attribute name="exclude-self" type="xsd:boolean" />
  </xsd:complexType>

  <xsd:complexType name="call">
    <xsd:choice minOccurs="0">
      <xsd:element name="argument" type="argument" maxOccurs="unbounded" />
    </xsd:choice>
    <xsd:attribute name="method" type="xsd:string" />
    <xsd:attribute name="returns-clone" type="boolean" />
  </xsd:complexType>

  <xsd:simpleType name="parameter_type">
    <xsd:restriction base="xsd:string">
      <xsd:enumeration value="collection" />
      <xsd:enumeration value="string" />
      <xsd:enumeration value="constant" />
      <xsd:enumeration value="binary" />
    </xsd:restriction>
  </xsd:simpleType>

  <xsd:simpleType name="argument_type">
    <xsd:restriction base="xsd:string">
      <xsd:enumeration value="abstract" />
      <xsd:enumeration value="collection" />
      <xsd:enumeration value="service" />
      <xsd:enumeration value="expression" />
      <xsd:enumeration value="string" />
      <xsd:enumeration value="constant" />
      <xsd:enumeration value="binary" />
      <xsd:enumeration value="iterator" />
      <xsd:enumeration value="closure" />
      <xsd:enumeration value="service_closure" />
      <xsd:enumeration value="service_locator" />
      <!-- "tagged" is an alias of "tagged_iterator", using "tagged_iterator" is preferred. -->
      <xsd:enumeration value="tagged" />
      <xsd:enumeration value="tagged_iterator" />
      <xsd:enumeration value="tagged_locator" />
    </xsd:restriction>
  </xsd:simpleType>

  <xsd:simpleType name="ignore_errors">
    <xsd:restriction base="xsd:string">
      <xsd:pattern value="(true|false|not_found)" />
    </xsd:restriction>
  </xsd:simpleType>

  <xsd:simpleType name="invalid_sequence">
    <xsd:restriction base="xsd:string">
      <xsd:enumeration value="null" />
      <xsd:enumeration value="ignore" />
      <xsd:enumeration value="exception" />
      <xsd:enumeration value="ignore_uninitialized" />
    </xsd:restriction>
  </xsd:simpleType>

  <xsd:simpleType name="invalid_decorated_service_sequence">
    <xsd:restriction base="xsd:string">
      <xsd:enumeration value="null" />
      <xsd:enumeration value="ignore" />
      <xsd:enumeration value="exception" />
    </xsd:restriction>
  </xsd:simpleType>

  <xsd:simpleType name="boolean">
    <xsd:restriction base="xsd:string">
      <xsd:pattern value="(%.+%|true|false)" />
    </xsd:restriction>
  </xsd:simpleType>
</xsd:schema>
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\DependencyInjection\Loader;

use _ContaoManager\Symfony\Component\Config\Builder\ConfigBuilderGenerator;
use _ContaoManager\Symfony\Component\Config\Builder\ConfigBuilderGeneratorInterface;
use _ContaoManager\Symfony\Component\Config\Builder\ConfigBuilderInterface;
use _ContaoManager\Symfony\Component\Config\FileLocatorInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Attribute\When;
use _ContaoManager\Symfony\Component\DependencyInjection\Container;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerBuilder;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
use _ContaoManager\Symfony\Component\DependencyInjection\Extension\ConfigurationExtensionInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Extension\ExtensionInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;
/**
 * PhpFileLoader loads service definitions from a PHP file.
 *
 * The PHP file is required and the $container variable can be
 * used within the file to change the container.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class PhpFileLoader extends FileLoader
{
    protected $autoRegisterAliasesForSinglyImplementedInterfaces = \false;
    private ?ConfigBuilderGeneratorInterface $generator;
    public function __construct(ContainerBuilder $container, FileLocatorInterface $locator, ?string $env = null, ?ConfigBuilderGeneratorInterface $generator = null)
    {
        parent::__construct($container, $locator, $env);
        $this->generator = $generator;
    }
    public function load(mixed $resource, ?string $type = null): mixed
    {
        // the container and loader variables are exposed to the included file below
        $container = $this->container;
        $loader = $this;
        $path = $this->locator->locate($resource);
        $this->setCurrentDir(\dirname($path));
        $this->container->fileExists($path);
        // the closure forbids access to the private scope in the included file
        $load = \Closure::bind(function ($path, $env) use ($container, $loader, $resource, $type) {
            return include $path;
        }, $this, ProtectedPhpFileLoader::class);
        $instanceof = $this->instanceof;
        $this->instanceof = [];
        try {
            $callback = $load($path, $this->env);
            if (\is_object($callback) && \is_callable($callback)) {
                $this->executeCallback($callback, new ContainerConfigurator($this->container, $this, $this->instanceof, $path, $resource, $this->env), $path);
            }
        } finally {
            $this->instanceof = $instanceof;
            $this->registerAliasesForSinglyImplementedInterfaces();
        }
        return null;
    }
    public function supports(mixed $resource, ?string $type = null): bool
    {
        if (!\is_string($resource)) {
            return \false;
        }
        if (null === $type && 'php' === pathinfo($resource, \PATHINFO_EXTENSION)) {
            return \true;
        }
        return 'php' === $type;
    }
    /**
     * Resolve the parameters to the $callback and execute it.
     */
    private function executeCallback(callable $callback, ContainerConfigurator $containerConfigurator, string $path): void
    {
        $callback = $callback(...);
        $arguments = [];
        $configBuilders = [];
        $r = new \ReflectionFunction($callback);
        $attribute = null;
        foreach ($r->getAttributes(When::class, \ReflectionAttribute::IS_INSTANCEOF) as $attribute) {
            if ($this->env === $attribute->newInstance()->env) {
                $attribute = null;
                break;
            }
        }
        if (null !== $attribute) {
            return;
        }
        foreach ($r->getParameters() as $parameter) {
            $reflectionType = $parameter->getType();
            if (!$reflectionType instanceof \ReflectionNamedType) {
                throw new \InvalidArgumentException(\sprintf('Could not resolve argument "$%s" for "%s". You must typehint it (for example with "%s" or "%s").', $parameter->getName(), $path, ContainerConfigurator::class, ContainerBuilder::class));
            }
            $type = $reflectionType->getName();
            switch ($type) {
                case ContainerConfigurator::class:
                    $arguments[] = $containerConfigurator;
                    break;
                case ContainerBuilder::class:
                    $arguments[] = $this->container;
                    break;
                case FileLoader::class:
                case self::class:
                    $arguments[] = $this;
                    break;
                case 'string':
                    if (null !== $this->env && 'env' === $parameter->getName()) {
                        $arguments[] = $this->env;
                        break;
                    }
                // no break
                default:
                    try {
                        $configBuilder = $this->configBuilder($type);
                    } catch (InvalidArgumentException|\LogicException $e) {
                        throw new \InvalidArgumentException(\sprintf('Could not resolve argument "%s" for "%s".', $type . ' $' . $parameter->getName(), $path), 0, $e);
                    }
                    $configBuilders[] = $configBuilder;
                    $arguments[] = $configBuilder;
            }
        }
        // Force load ContainerConfigurator to make env(), param() etc available.
        class_exists(ContainerConfigurator::class);
        $callback(...$arguments);
        /** @var ConfigBuilderInterface $configBuilder */
        foreach ($configBuilders as $configBuilder) {
            $containerConfigurator->extension($configBuilder->getExtensionAlias(), $configBuilder->toArray());
        }
    }
    /**
     * @param string $namespace FQCN string for a class implementing ConfigBuilderInterface
     */
    private function configBuilder(string $namespace): ConfigBuilderInterface
    {
        if (!class_exists(ConfigBuilderGenerator::class)) {
            throw new \LogicException('You cannot use the config builder as the Config component is not installed. Try running "composer require symfony/config".');
        }
        if (null === $this->generator) {
            throw new \LogicException('You cannot use the ConfigBuilders without providing a class implementing ConfigBuilderGeneratorInterface.');
        }
        // If class exists and implements ConfigBuilderInterface
        if (class_exists($namespace) && is_subclass_of($namespace, ConfigBuilderInterface::class)) {
            return new $namespace();
        }
        // If it does not start with Symfony\Config\ we don't know how to handle this
        if (!str_starts_with($namespace, 'Symfony\Config\\')) {
            throw new InvalidArgumentException(\sprintf('Could not find or generate class "%s".', $namespace));
        }
        // Try to get the extension alias
        $alias = Container::underscore(substr($namespace, 15, -6));
        if (str_contains($alias, '\\')) {
            throw new InvalidArgumentException('You can only use "root" ConfigBuilders from "Symfony\Config\" namespace. Nested classes like "Symfony\Config\Framework\CacheConfig" cannot be used.');
        }
        if (!$this->container->hasExtension($alias)) {
            $extensions = array_filter(array_map(fn(ExtensionInterface $ext) => $ext->getAlias(), $this->container->getExtensions()));
            throw new InvalidArgumentException(\sprintf('There is no extension able to load the configuration for "%s". Looked for namespace "%s", found "%s".', $namespace, $alias, $extensions ? implode('", "', $extensions) : 'none'));
        }
        $extension = $this->container->getExtension($alias);
        if (!$extension instanceof ConfigurationExtensionInterface) {
            throw new \LogicException(\sprintf('You cannot use the config builder for "%s" because the extension does not implement "%s".', $namespace, ConfigurationExtensionInterface::class));
        }
        $configuration = $extension->getConfiguration([], $this->container);
        $loader = $this->generator->build($configuration);
        return $loader();
    }
}
/**
 * @internal
 */
final class ProtectedPhpFileLoader extends PhpFileLoader
{
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\DependencyInjection\Loader;

use _ContaoManager\Symfony\Component\Config\Util\XmlUtils;
use _ContaoManager\Symfony\Component\DependencyInjection\Alias;
use _ContaoManager\Symfony\Component\DependencyInjection\Argument\AbstractArgument;
use _ContaoManager\Symfony\Component\DependencyInjection\Argument\BoundArgument;
use _ContaoManager\Symfony\Component\DependencyInjection\Argument\IteratorArgument;
use _ContaoManager\Symfony\Component\DependencyInjection\Argument\ServiceClosureArgument;
use _ContaoManager\Symfony\Component\DependencyInjection\Argument\ServiceLocatorArgument;
use _ContaoManager\Symfony\Component\DependencyInjection\Argument\TaggedIteratorArgument;
use _ContaoManager\Symfony\Component\DependencyInjection\ChildDefinition;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerBuilder;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Definition;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\LogicException;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\RuntimeException;
use _ContaoManager\Symfony\Component\DependencyInjection\Extension\ExtensionInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Reference;
use _ContaoManager\Symfony\Component\ExpressionLanguage\Expression;
/**
 * XmlFileLoader loads XML files service definitions.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class XmlFileLoader extends FileLoader
{
    public const NS = 'http://symfony.com/schema/dic/services';
    protected $autoRegisterAliasesForSinglyImplementedInterfaces = \false;
    public function load(mixed $resource, ?string $type = null): mixed
    {
        $path = $this->locator->locate($resource);
        $xml = $this->parseFileToDOM($path);
        $this->container->fileExists($path);
        $this->loadXml($xml, $path);
        if ($this->env) {
            $xpath = new \DOMXPath($xml);
            $xpath->registerNamespace('container', self::NS);
            foreach ($xpath->query(\sprintf('//container:when[@env="%s"]', $this->env)) ?: [] as $root) {
                $env = $this->env;
                $this->env = null;
                try {
                    $this->loadXml($xml, $path, $root);
                } finally {
                    $this->env = $env;
                }
            }
        }
        return null;
    }
    private function loadXml(\DOMDocument $xml, string $path, ?\DOMNode $root = null): void
    {
        $defaults = $this->getServiceDefaults($xml, $path, $root);
        // anonymous services
        $this->processAnonymousServices($xml, $path, $root);
        // imports
        $this->parseImports($xml, $path, $root);
        // parameters
        $this->parseParameters($xml, $path, $root);
        // extensions
        $this->loadFromExtensions($xml, $root);
        // services
        try {
            $this->parseDefinitions($xml, $path, $defaults, $root);
        } finally {
            $this->instanceof = [];
            $this->registerAliasesForSinglyImplementedInterfaces();
        }
    }
    public function supports(mixed $resource, ?string $type = null): bool
    {
        if (!\is_string($resource)) {
            return \false;
        }
        if (null === $type && 'xml' === pathinfo($resource, \PATHINFO_EXTENSION)) {
            return \true;
        }
        return 'xml' === $type;
    }
    private function parseParameters(\DOMDocument $xml, string $file, ?\DOMNode $root = null): void
    {
        if ($parameters = $this->getChildren($root ?? $xml->documentElement, 'parameters')) {
            $this->container->getParameterBag()->add($this->getArgumentsAsPhp($parameters[0], 'parameter', $file));
        }
    }
    private function parseImports(\DOMDocument $xml, string $file, ?\DOMNode $root = null): void
    {
        $xpath = new \DOMXPath($xml);
        $xpath->registerNamespace('container', self::NS);
        if (\false === $imports = $xpath->query('./container:imports/container:import', $root)) {
            return;
        }
        $defaultDirectory = \dirname($file);
        foreach ($imports as $import) {
            $this->setCurrentDir($defaultDirectory);
            $this->import($import->getAttribute('resource'), XmlUtils::phpize($import->getAttribute('type')) ?: null, XmlUtils::phpize($import->getAttribute('ignore-errors')) ?: \false, $file);
        }
    }
    private function parseDefinitions(\DOMDocument $xml, string $file, Definition $defaults, ?\DOMNode $root = null): void
    {
        $xpath = new \DOMXPath($xml);
        $xpath->registerNamespace('container', self::NS);
        if (\false === $services = $xpath->query('./container:services/container:service|./container:services/container:prototype|./container:services/container:stack', $root)) {
            return;
        }
        $this->setCurrentDir(\dirname($file));
        $this->instanceof = [];
        $this->isLoadingInstanceof = \true;
        $instanceof = $xpath->query('./container:services/container:instanceof', $root);
        foreach ($instanceof as $service) {
            $this->setDefinition((string) $service->getAttribute('id'), $this->parseDefinition($service, $file, new Definition()));
        }
        $this->isLoadingInstanceof = \false;
        foreach ($services as $service) {
            if ('stack' === $service->tagName) {
                $service->setAttribute('parent', '-');
                $definition = $this->parseDefinition($service, $file, $defaults)->setTags(array_merge_recursive(['container.stack' => [[]]], $defaults->getTags()));
                $this->setDefinition($id = (string) $service->getAttribute('id'), $definition);
                $stack = [];
                foreach ($this->getChildren($service, 'service') as $k => $frame) {
                    $k = $frame->getAttribute('id') ?: $k;
                    $frame->setAttribute('id', $id . '" at index "' . $k);
                    if ($alias = $frame->getAttribute('alias')) {
                        $this->validateAlias($frame, $file);
                        $stack[$k] = new Reference($alias);
                    } else {
                        $stack[$k] = $this->parseDefinition($frame, $file, $defaults)->setInstanceofConditionals($this->instanceof);
                    }
                }
                $definition->setArguments($stack);
            } elseif (null !== $definition = $this->parseDefinition($service, $file, $defaults)) {
                if ('prototype' === $service->tagName) {
                    $excludes = array_column($this->getChildren($service, 'exclude'), 'nodeValue');
                    if ($service->hasAttribute('exclude')) {
                        if (\count($excludes) > 0) {
                            throw new InvalidArgumentException('You cannot use both the attribute "exclude" and <exclude> tags at the same time.');
                        }
                        $excludes = [$service->getAttribute('exclude')];
                    }
                    $this->registerClasses($definition, (string) $service->getAttribute('namespace'), (string) $service->getAttribute('resource'), $excludes, $file);
                } else {
                    $this->setDefinition((string) $service->getAttribute('id'), $definition);
                }
            }
        }
    }
    private function getServiceDefaults(\DOMDocument $xml, string $file, ?\DOMNode $root = null): Definition
    {
        $xpath = new \DOMXPath($xml);
        $xpath->registerNamespace('container', self::NS);
        if (null === $defaultsNode = $xpath->query('./container:services/container:defaults', $root)->item(0)) {
            return new Definition();
        }
        $defaultsNode->setAttribute('id', '<defaults>');
        return $this->parseDefinition($defaultsNode, $file, new Definition());
    }
    /**
     * Parses an individual Definition.
     */
    private function parseDefinition(\DOMElement $service, string $file, Definition $defaults): ?Definition
    {
        if ($alias = $service->getAttribute('alias')) {
            $this->validateAlias($service, $file);
            $this->container->setAlias($service->getAttribute('id'), $alias = new Alias($alias));
            if ($publicAttr = $service->getAttribute('public')) {
                $alias->setPublic(XmlUtils::phpize($publicAttr));
            } elseif ($defaults->getChanges()['public'] ?? \false) {
                $alias->setPublic($defaults->isPublic());
            }
            if ($deprecated = $this->getChildren($service, 'deprecated')) {
                $message = $deprecated[0]->nodeValue ?: '';
                $package = $deprecated[0]->getAttribute('package') ?: '';
                $version = $deprecated[0]->getAttribute('version') ?: '';
                if (!$deprecated[0]->hasAttribute('package')) {
                    throw new InvalidArgumentException(\sprintf('Missing attribute "package" at node "deprecated" in "%s".', $file));
                }
                if (!$deprecated[0]->hasAttribute('version')) {
                    throw new InvalidArgumentException(\sprintf('Missing attribute "version" at node "deprecated" in "%s".', $file));
                }
                $alias->setDeprecated($package, $version, $message);
            }
            return null;
        }
        if ($this->isLoadingInstanceof) {
            $definition = new ChildDefinition('');
        } elseif ($parent = $service->getAttribute('parent')) {
            $definition = new ChildDefinition($parent);
        } else {
            $definition = new Definition();
        }
        if ($defaults->getChanges()['public'] ?? \false) {
            $definition->setPublic($defaults->isPublic());
        }
        $definition->setAutowired($defaults->isAutowired());
        $definition->setAutoconfigured($defaults->isAutoconfigured());
        $definition->setChanges([]);
        foreach (['class', 'public', 'shared', 'synthetic', 'abstract'] as $key) {
            if ($value = $service->getAttribute($key)) {
                $method = 'set' . $key;
                $definition->{$method}(XmlUtils::phpize($value));
            }
        }
        if ($value = $service->getAttribute('lazy')) {
            $definition->setLazy((bool) $value = XmlUtils::phpize($value));
            if (\is_string($value)) {
                $definition->addTag('proxy', ['interface' => $value]);
            }
        }
        if ($value = $service->getAttribute('autowire')) {
            $definition->setAutowired(XmlUtils::phpize($value));
        }
        if ($value = $service->getAttribute('autoconfigure')) {
            $definition->setAutoconfigured(XmlUtils::phpize($value));
        }
        if ($files = $this->getChildren($service, 'file')) {
            $definition->setFile($files[0]->nodeValue);
        }
        if ($deprecated = $this->getChildren($service, 'deprecated')) {
            $message = $deprecated[0]->nodeValue ?: '';
            $package = $deprecated[0]->getAttribute('package') ?: '';
            $version = $deprecated[0]->getAttribute('version') ?: '';
            if (!$deprecated[0]->hasAttribute('package')) {
                throw new InvalidArgumentException(\sprintf('Missing attribute "package" at node "deprecated" in "%s".', $file));
            }
            if (!$deprecated[0]->hasAttribute('version')) {
                throw new InvalidArgumentException(\sprintf('Missing attribute "version" at node "deprecated" in "%s".', $file));
            }
            $definition->setDeprecated($package, $version, $message);
        }
        $definition->setArguments($this->getArgumentsAsPhp($service, 'argument', $file, $definition instanceof ChildDefinition));
        $definition->setProperties($this->getArgumentsAsPhp($service, 'property', $file));
        if ($factories = $this->getChildren($service, 'factory')) {
            $factory = $factories[0];
            if ($function = $factory->getAttribute('function')) {
                $definition->setFactory($function);
            } elseif ($expression = $factory->getAttribute('expression')) {
                if (!class_exists(Expression::class)) {
                    throw new \LogicException('The "expression" attribute cannot be used on factories without the ExpressionLanguage component. Try running "composer require symfony/expression-language".');
                }
                $definition->setFactory('@=' . $expression);
            } else {
                if ($childService = $factory->getAttribute('service')) {
                    $class = new Reference($childService, ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE);
                } else {
                    $class = $factory->hasAttribute('class') ? $factory->getAttribute('class') : null;
                }
                $definition->setFactory([$class, $factory->getAttribute('method') ?: '__invoke']);
            }
        }
        if ($constructor = $service->getAttribute('constructor')) {
            if (null !== $definition->getFactory()) {
                throw new LogicException(\sprintf('The "%s" service cannot declare a factory as well as a constructor.', $service->getAttribute('id')));
            }
            $definition->setFactory([null, $constructor]);
        }
        if ($configurators = $this->getChildren($service, 'configurator')) {
            $configurator = $configurators[0];
            if ($function = $configurator->getAttribute('function')) {
                $definition->setConfigurator($function);
            } else {
                if ($childService = $configurator->getAttribute('service')) {
                    $class = new Reference($childService, ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE);
                } else {
                    $class = $configurator->getAttribute('class');
                }
                $definition->setConfigurator([$class, $configurator->getAttribute('method') ?: '__invoke']);
            }
        }
        foreach ($this->getChildren($service, 'call') as $call) {
            $definition->addMethodCall($call->getAttribute('method'), $this->getArgumentsAsPhp($call, 'argument', $file), XmlUtils::phpize($call->getAttribute('returns-clone')) ?: \false);
        }
        $tags = $this->getChildren($service, 'tag');
        foreach ($tags as $tag) {
            $tagNameComesFromAttribute = $tag->childElementCount || '' === $tag->nodeValue;
            if ('' === $tagName = $tagNameComesFromAttribute ? $tag->getAttribute('name') : $tag->nodeValue) {
                throw new InvalidArgumentException(\sprintf('The tag name for service "%s" in "%s" must be a non-empty string.', (string) $service->getAttribute('id'), $file));
            }
            $parameters = $this->getTagAttributes($tag, \sprintf('The attribute name of tag "%s" for service "%s" in %s must be a non-empty string.', $tagName, (string) $service->getAttribute('id'), $file));
            foreach ($tag->attributes as $name => $node) {
                if ($tagNameComesFromAttribute && 'name' === $name) {
                    continue;
                }
                if (str_contains($name, '-') && !str_contains($name, '_') && !\array_key_exists($normalizedName = str_replace('-', '_', $name), $parameters)) {
                    $parameters[$normalizedName] = XmlUtils::phpize($node->nodeValue);
                }
                // keep not normalized key
                $parameters[$name] = XmlUtils::phpize($node->nodeValue);
            }
            $definition->addTag($tagName, $parameters);
        }
        $definition->setTags(array_merge_recursive($definition->getTags(), $defaults->getTags()));
        $bindings = $this->getArgumentsAsPhp($service, 'bind', $file);
        $bindingType = $this->isLoadingInstanceof ? BoundArgument::INSTANCEOF_BINDING : BoundArgument::SERVICE_BINDING;
        foreach ($bindings as $argument => $value) {
            $bindings[$argument] = new BoundArgument($value, \true, $bindingType, $file);
        }
        // deep clone, to avoid multiple process of the same instance in the passes
        $bindings = array_merge(unserialize(serialize($defaults->getBindings())), $bindings);
        if ($bindings) {
            $definition->setBindings($bindings);
        }
        if ($decorates = $service->getAttribute('decorates')) {
            $decorationOnInvalid = $service->getAttribute('decoration-on-invalid') ?: 'exception';
            if ('exception' === $decorationOnInvalid) {
                $invalidBehavior = ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE;
            } elseif ('ignore' === $decorationOnInvalid) {
                $invalidBehavior = ContainerInterface::IGNORE_ON_INVALID_REFERENCE;
            } elseif ('null' === $decorationOnInvalid) {
                $invalidBehavior = ContainerInterface::NULL_ON_INVALID_REFERENCE;
            } else {
                throw new InvalidArgumentException(\sprintf('Invalid value "%s" for attribute "decoration-on-invalid" on service "%s". Did you mean "exception", "ignore" or "null" in "%s"?', $decorationOnInvalid, $service->getAttribute('id'), $file));
            }
            $renameId = $service->hasAttribute('decoration-inner-name') ? $service->getAttribute('decoration-inner-name') : null;
            $priority = $service->hasAttribute('decoration-priority') ? $service->getAttribute('decoration-priority') : 0;
            $definition->setDecoratedService($decorates, $renameId, $priority, $invalidBehavior);
        }
        if ($callable = $this->getChildren($service, 'from-callable')) {
            if ($definition instanceof ChildDefinition) {
                throw new InvalidArgumentException(\sprintf('Attribute "parent" is unsupported when using "<from-callable>" on service "%s".', (string) $service->getAttribute('id')));
            }
            foreach (['Attribute "synthetic"' => 'isSynthetic', 'Attribute "file"' => 'getFile', 'Tag "<factory>"' => 'getFactory', 'Tag "<argument>"' => 'getArguments', 'Tag "<property>"' => 'getProperties', 'Tag "<configurator>"' => 'getConfigurator', 'Tag "<call>"' => 'getMethodCalls'] as $key => $method) {
                if ($definition->{$method}()) {
                    throw new InvalidArgumentException($key . \sprintf(' is unsupported when using "<from-callable>" on service "%s".', (string) $service->getAttribute('id')));
                }
            }
            $definition->setFactory(['Closure', 'fromCallable']);
            if ('Closure' !== ($definition->getClass() ?? 'Closure')) {
                $definition->setLazy(\true);
            } else {
                $definition->setClass('Closure');
            }
            $callable = $callable[0];
            if ($function = $callable->getAttribute('function')) {
                $definition->setArguments([$function]);
            } elseif ($expression = $callable->getAttribute('expression')) {
                if (!class_exists(Expression::class)) {
                    throw new \LogicException('The "expression" attribute cannot be used without the ExpressionLanguage component. Try running "composer require symfony/expression-language".');
                }
                $definition->setArguments(['@=' . $expression]);
            } else {
                if ($childService = $callable->getAttribute('service')) {
                    $class = new Reference($childService, ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE);
                } else {
                    $class = $callable->hasAttribute('class') ? $callable->getAttribute('class') : null;
                }
                $definition->setArguments([[$class, $callable->getAttribute('method') ?: '__invoke']]);
            }
        }
        return $definition;
    }
    /**
     * Parses an XML file to a \DOMDocument.
     *
     * @throws InvalidArgumentException When loading of XML file returns error
     */
    private function parseFileToDOM(string $file): \DOMDocument
    {
        try {
            $dom = XmlUtils::loadFile($file, $this->validateSchema(...));
        } catch (\InvalidArgumentException $e) {
            $invalidSecurityElements = [];
            $errors = explode("\n", $e->getMessage());
            foreach ($errors as $i => $error) {
                if (preg_match("#^\\[ERROR 1871] Element '\\{http://symfony\\.com/schema/dic/security}([^']+)'#", $error, $matches)) {
                    $invalidSecurityElements[$i] = $matches[1];
                }
            }
            if ($invalidSecurityElements) {
                $dom = XmlUtils::loadFile($file);
                foreach ($invalidSecurityElements as $errorIndex => $tagName) {
                    foreach ($dom->getElementsByTagNameNS('http://symfony.com/schema/dic/security', $tagName) as $element) {
                        if (!$parent = $element->parentNode) {
                            continue;
                        }
                        if ('http://symfony.com/schema/dic/security' !== $parent->namespaceURI) {
                            continue;
                        }
                        if ('provider' === $parent->localName || 'firewall' === $parent->localName) {
                            unset($errors[$errorIndex]);
                        }
                    }
                }
            }
            if ($errors) {
                throw new InvalidArgumentException(\sprintf('Unable to parse file "%s": ', $file) . implode("\n", $errors), $e->getCode(), $e);
            }
        }
        $this->validateExtensions($dom, $file);
        return $dom;
    }
    /**
     * Processes anonymous services.
     */
    private function processAnonymousServices(\DOMDocument $xml, string $file, ?\DOMNode $root = null): void
    {
        $definitions = [];
        $count = 0;
        $suffix = '~' . ContainerBuilder::hash($file);
        $xpath = new \DOMXPath($xml);
        $xpath->registerNamespace('container', self::NS);
        // anonymous services as arguments/properties
        if (\false !== $nodes = $xpath->query('.//container:argument[@type="service"][not(@id)]|.//container:property[@type="service"][not(@id)]|.//container:bind[not(@id)]|.//container:factory[not(@service)]|.//container:configurator[not(@service)]', $root)) {
            foreach ($nodes as $node) {
                if ($services = $this->getChildren($node, 'service')) {
                    // give it a unique name
                    $id = \sprintf('.%d_%s', ++$count, preg_replace('/^.*\\\\/', '', $services[0]->getAttribute('class')) . $suffix);
                    $node->setAttribute('id', $id);
                    $node->setAttribute('service', $id);
                    $definitions[$id] = [$services[0], $file];
                    $services[0]->setAttribute('id', $id);
                    // anonymous services are always private
                    // we could not use the constant false here, because of XML parsing
                    $services[0]->setAttribute('public', 'false');
                }
            }
        }
        // anonymous services "in the wild"
        if (\false !== $nodes = $xpath->query('.//container:services/container:service[not(@id)]', $root)) {
            foreach ($nodes as $node) {
                throw new InvalidArgumentException(\sprintf('Top-level services must have "id" attribute, none found in "%s" at line %d.', $file, $node->getLineNo()));
            }
        }
        // resolve definitions
        uksort($definitions, 'strnatcmp');
        foreach (array_reverse($definitions) as $id => [$domElement, $file]) {
            if (null !== $definition = $this->parseDefinition($domElement, $file, new Definition())) {
                $this->setDefinition($id, $definition);
            }
        }
    }
    private function getArgumentsAsPhp(\DOMElement $node, string $name, string $file, bool $isChildDefinition = \false): array
    {
        $arguments = [];
        foreach ($this->getChildren($node, $name) as $arg) {
            if ($arg->hasAttribute('name')) {
                $arg->setAttribute('key', $arg->getAttribute('name'));
            }
            // this is used by ChildDefinition to overwrite a specific
            // argument of the parent definition
            if ($arg->hasAttribute('index')) {
                $key = ($isChildDefinition ? 'index_' : '') . $arg->getAttribute('index');
            } elseif (!$arg->hasAttribute('key')) {
                // Append an empty argument, then fetch its key to overwrite it later
                $arguments[] = null;
                $keys = array_keys($arguments);
                $key = array_pop($keys);
            } else {
                $key = $arg->getAttribute('key');
            }
            $trim = $arg->hasAttribute('trim') && XmlUtils::phpize($arg->getAttribute('trim'));
            $onInvalid = $arg->getAttribute('on-invalid');
            $invalidBehavior = ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE;
            if ('ignore' == $onInvalid) {
                $invalidBehavior = ContainerInterface::IGNORE_ON_INVALID_REFERENCE;
            } elseif ('ignore_uninitialized' == $onInvalid) {
                $invalidBehavior = ContainerInterface::IGNORE_ON_UNINITIALIZED_REFERENCE;
            } elseif ('null' == $onInvalid) {
                $invalidBehavior = ContainerInterface::NULL_ON_INVALID_REFERENCE;
            }
            switch ($type = $arg->getAttribute('type')) {
                case 'service':
                    if ('' === $arg->getAttribute('id')) {
                        throw new InvalidArgumentException(\sprintf('Tag "<%s>" with type="service" has no or empty "id" attribute in "%s".', $name, $file));
                    }
                    $arguments[$key] = new Reference($arg->getAttribute('id'), $invalidBehavior);
                    break;
                case 'expression':
                    if (!class_exists(Expression::class)) {
                        throw new \LogicException('The type="expression" attribute cannot be used without the ExpressionLanguage component. Try running "composer require symfony/expression-language".');
                    }
                    $arguments[$key] = new Expression($arg->nodeValue);
                    break;
                case 'collection':
                    $arguments[$key] = $this->getArgumentsAsPhp($arg, $name, $file);
                    break;
                case 'iterator':
                    $arg = $this->getArgumentsAsPhp($arg, $name, $file);
                    $arguments[$key] = new IteratorArgument($arg);
                    break;
                case 'closure':
                case 'service_closure':
                    if ('' !== $arg->getAttribute('id')) {
                        $arg = new Reference($arg->getAttribute('id'), $invalidBehavior);
                    } else {
                        $arg = $this->getArgumentsAsPhp($arg, $name, $file);
                    }
                    $arguments[$key] = match ($type) {
                        'service_closure' => new ServiceClosureArgument($arg),
                        'closure' => (new Definition('Closure'))->setFactory(['Closure', 'fromCallable'])->addArgument($arg),
                    };
                    break;
                case 'service_locator':
                    $arg = $this->getArgumentsAsPhp($arg, $name, $file);
                    if (isset($arg[0])) {
                        trigger_deprecation('symfony/dependency-injection', '6.3', 'Skipping "key" argument or using integers as values in a "service_locator" tag is deprecated. The keys will default to the IDs of the original services in 7.0.');
                    }
                    $arguments[$key] = new ServiceLocatorArgument($arg);
                    break;
                case 'tagged':
                case 'tagged_iterator':
                case 'tagged_locator':
                    $forLocator = 'tagged_locator' === $type;
                    if (!$arg->getAttribute('tag')) {
                        throw new InvalidArgumentException(\sprintf('Tag "<%s>" with type="%s" has no or empty "tag" attribute in "%s".', $name, $type, $file));
                    }
                    $excludes = array_column($this->getChildren($arg, 'exclude'), 'nodeValue');
                    if ($arg->hasAttribute('exclude')) {
                        if (\count($excludes) > 0) {
                            throw new InvalidArgumentException('You cannot use both the attribute "exclude" and <exclude> tags at the same time.');
                        }
                        $excludes = [$arg->getAttribute('exclude')];
                    }
                    $arguments[$key] = new TaggedIteratorArgument($arg->getAttribute('tag'), $arg->getAttribute('index-by') ?: null, $arg->getAttribute('default-index-method') ?: null, $forLocator, $arg->getAttribute('default-priority-method') ?: null, $excludes, !$arg->hasAttribute('exclude-self') || XmlUtils::phpize($arg->getAttribute('exclude-self')));
                    if ($forLocator) {
                        $arguments[$key] = new ServiceLocatorArgument($arguments[$key]);
                    }
                    break;
                case 'binary':
                    if (\false === $value = base64_decode($arg->nodeValue)) {
                        throw new InvalidArgumentException(\sprintf('Tag "<%s>" with type="binary" is not a valid base64 encoded string.', $name));
                    }
                    $arguments[$key] = $value;
                    break;
                case 'abstract':
                    $arguments[$key] = new AbstractArgument($arg->nodeValue);
                    break;
                case 'string':
                    $arguments[$key] = $trim ? trim($arg->nodeValue) : $arg->nodeValue;
                    break;
                case 'constant':
                    $arguments[$key] = \constant(trim($arg->nodeValue));
                    break;
                default:
                    $arguments[$key] = XmlUtils::phpize($trim ? trim($arg->nodeValue) : $arg->nodeValue);
            }
        }
        return $arguments;
    }
    /**
     * Get child elements by name.
     *
     * @return \DOMElement[]
     */
    private function getChildren(\DOMNode $node, string $name): array
    {
        $children = [];
        foreach ($node->childNodes as $child) {
            if ($child instanceof \DOMElement && $child->localName === $name && self::NS === $child->namespaceURI) {
                $children[] = $child;
            }
        }
        return $children;
    }
    private function getTagAttributes(\DOMNode $node, string $missingName): array
    {
        $parameters = [];
        $children = $this->getChildren($node, 'attribute');
        foreach ($children as $childNode) {
            if ('' === $name = $childNode->getAttribute('name')) {
                throw new InvalidArgumentException($missingName);
            }
            if ($this->getChildren($childNode, 'attribute')) {
                $parameters[$name] = $this->getTagAttributes($childNode, $missingName);
            } else {
                if (str_contains($name, '-') && !str_contains($name, '_') && !\array_key_exists($normalizedName = str_replace('-', '_', $name), $parameters)) {
                    $parameters[$normalizedName] = XmlUtils::phpize($childNode->nodeValue);
                }
                // keep not normalized key
                $parameters[$name] = XmlUtils::phpize($childNode->nodeValue);
            }
        }
        return $parameters;
    }
    /**
     * Validates a documents XML schema.
     *
     * @throws RuntimeException When extension references a non-existent XSD file
     */
    public function validateSchema(\DOMDocument $dom): bool
    {
        $schemaLocations = ['http://symfony.com/schema/dic/services' => str_replace('\\', '/', __DIR__ . '/schema/dic/services/services-1.0.xsd')];
        if ($element = $dom->documentElement->getAttributeNS('http://www.w3.org/2001/XMLSchema-instance', 'schemaLocation')) {
            $items = preg_split('/\s+/', $element);
            for ($i = 0, $nb = \count($items); $i < $nb; $i += 2) {
                if (!$this->container->hasExtension($items[$i])) {
                    continue;
                }
                if (($extension = $this->container->getExtension($items[$i])) && \false !== $extension->getXsdValidationBasePath()) {
                    $ns = $extension->getNamespace();
                    $path = str_replace([$ns, str_replace('http://', 'https://', $ns)], str_replace('\\', '/', $extension->getXsdValidationBasePath()) . '/', $items[$i + 1]);
                    if (!is_file($path)) {
                        throw new RuntimeException(\sprintf('Extension "%s" references a non-existent XSD file "%s".', get_debug_type($extension), $path));
                    }
                    $schemaLocations[$items[$i]] = $path;
                }
            }
        }
        $tmpfiles = [];
        $imports = '';
        foreach ($schemaLocations as $namespace => $location) {
            $parts = explode('/', $location);
            $locationstart = 'file:///';
            if (0 === stripos($location, 'phar://')) {
                $tmpfile = tempnam(sys_get_temp_dir(), 'symfony');
                if ($tmpfile) {
                    copy($location, $tmpfile);
                    $tmpfiles[] = $tmpfile;
                    $parts = explode('/', str_replace('\\', '/', $tmpfile));
                } else {
                    array_shift($parts);
                    $locationstart = 'phar:///';
                }
            } elseif ('\\' === \DIRECTORY_SEPARATOR && str_starts_with($location, '\\\\')) {
                $locationstart = '';
            }
            $drive = '\\' === \DIRECTORY_SEPARATOR ? array_shift($parts) . '/' : '';
            $location = $locationstart . $drive . implode('/', array_map('rawurlencode', $parts));
            $imports .= \sprintf('  <xsd:import namespace="%s" schemaLocation="%s" />' . "\n", $namespace, $location);
        }
        $source = <<<EOF
<?xml version="1.0" encoding="utf-8" ?>
<xsd:schema xmlns="http://symfony.com/schema"
    xmlns:xsd="http://www.w3.org/2001/XMLSchema"
    targetNamespace="http://symfony.com/schema"
    elementFormDefault="qualified">

    <xsd:import namespace="http://www.w3.org/XML/1998/namespace"/>
{$imports}
</xsd:schema>
EOF;
        if ($this->shouldEnableEntityLoader()) {
            $disableEntities = libxml_disable_entity_loader(\false);
            $valid = @$dom->schemaValidateSource($source);
            libxml_disable_entity_loader($disableEntities);
        } else {
            $valid = @$dom->schemaValidateSource($source);
        }
        foreach ($tmpfiles as $tmpfile) {
            @unlink($tmpfile);
        }
        return $valid;
    }
    private function shouldEnableEntityLoader(): bool
    {
        static $dom, $schema;
        if (null === $dom) {
            $dom = new \DOMDocument();
            $dom->loadXML('<?xml version="1.0"?><test/>');
            $tmpfile = tempnam(sys_get_temp_dir(), 'symfony');
            register_shutdown_function(static function () use ($tmpfile) {
                @unlink($tmpfile);
            });
            $schema = '<?xml version="1.0" encoding="utf-8"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <xsd:include schemaLocation="file:///' . rawurlencode(str_replace('\\', '/', $tmpfile)) . '" />
</xsd:schema>';
            file_put_contents($tmpfile, '<?xml version="1.0" encoding="utf-8"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <xsd:element name="test" type="testType" />
  <xsd:complexType name="testType"/>
</xsd:schema>');
        }
        return !@$dom->schemaValidateSource($schema);
    }
    private function validateAlias(\DOMElement $alias, string $file): void
    {
        foreach ($alias->attributes as $name => $node) {
            if (!\in_array($name, ['alias', 'id', 'public'])) {
                throw new InvalidArgumentException(\sprintf('Invalid attribute "%s" defined for alias "%s" in "%s".', $name, $alias->getAttribute('id'), $file));
            }
        }
        foreach ($alias->childNodes as $child) {
            if (!$child instanceof \DOMElement || self::NS !== $child->namespaceURI) {
                continue;
            }
            if ('deprecated' !== $child->localName) {
                throw new InvalidArgumentException(\sprintf('Invalid child element "%s" defined for alias "%s" in "%s".', $child->localName, $alias->getAttribute('id'), $file));
            }
        }
    }
    /**
     * Validates an extension.
     *
     * @throws InvalidArgumentException When no extension is found corresponding to a tag
     */
    private function validateExtensions(\DOMDocument $dom, string $file): void
    {
        foreach ($dom->documentElement->childNodes as $node) {
            if (!$node instanceof \DOMElement || 'http://symfony.com/schema/dic/services' === $node->namespaceURI) {
                continue;
            }
            // can it be handled by an extension?
            if (!$this->container->hasExtension($node->namespaceURI)) {
                $extensionNamespaces = array_filter(array_map(fn(ExtensionInterface $ext) => $ext->getNamespace(), $this->container->getExtensions()));
                throw new InvalidArgumentException(\sprintf('There is no extension able to load the configuration for "%s" (in "%s"). Looked for namespace "%s", found "%s".', $node->tagName, $file, $node->namespaceURI, $extensionNamespaces ? implode('", "', $extensionNamespaces) : 'none'));
            }
        }
    }
    /**
     * Loads from an extension.
     */
    private function loadFromExtensions(\DOMDocument $xml): void
    {
        foreach ($xml->documentElement->childNodes as $node) {
            if (!$node instanceof \DOMElement || self::NS === $node->namespaceURI) {
                continue;
            }
            $values = static::convertDomElementToArray($node);
            if (!\is_array($values)) {
                $values = [];
            }
            $this->container->loadFromExtension($node->namespaceURI, $values);
        }
    }
    /**
     * Converts a \DOMElement object to a PHP array.
     *
     * The following rules applies during the conversion:
     *
     *  * Each tag is converted to a key value or an array
     *    if there is more than one "value"
     *
     *  * The content of a tag is set under a "value" key (<foo>bar</foo>)
     *    if the tag also has some nested tags
     *
     *  * The attributes are converted to keys (<foo foo="bar"/>)
     *
     *  * The nested-tags are converted to keys (<foo><foo>bar</foo></foo>)
     *
     * @param \DOMElement $element A \DOMElement instance
     */
    public static function convertDomElementToArray(\DOMElement $element): mixed
    {
        return XmlUtils::convertDomElementToArray($element, \false);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\DependencyInjection\Loader;

use _ContaoManager\Symfony\Component\Config\Util\XmlUtils;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
/**
 * IniFileLoader loads parameters from INI files.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class IniFileLoader extends FileLoader
{
    public function load(mixed $resource, ?string $type = null): mixed
    {
        $path = $this->locator->locate($resource);
        $this->container->fileExists($path);
        // first pass to catch parsing errors
        $result = parse_ini_file($path, \true);
        if (\false === $result || [] === $result) {
            throw new InvalidArgumentException(\sprintf('The "%s" file is not valid.', $resource));
        }
        // real raw parsing
        $result = parse_ini_file($path, \true, \INI_SCANNER_RAW);
        if (isset($result['parameters']) && \is_array($result['parameters'])) {
            foreach ($result['parameters'] as $key => $value) {
                if (\is_array($value)) {
                    $this->container->setParameter($key, array_map($this->phpize(...), $value));
                } else {
                    $this->container->setParameter($key, $this->phpize($value));
                }
            }
        }
        if ($this->env && \is_array($result['parameters@' . $this->env] ?? null)) {
            foreach ($result['parameters@' . $this->env] as $key => $value) {
                $this->container->setParameter($key, $this->phpize($value));
            }
        }
        return null;
    }
    public function supports(mixed $resource, ?string $type = null): bool
    {
        if (!\is_string($resource)) {
            return \false;
        }
        if (null === $type && 'ini' === pathinfo($resource, \PATHINFO_EXTENSION)) {
            return \true;
        }
        return 'ini' === $type;
    }
    /**
     * Note that the following features are not supported:
     *  * strings with escaped quotes are not supported "foo\"bar";
     *  * string concatenation ("foo" "bar").
     */
    private function phpize(string $value): mixed
    {
        // trim on the right as comments removal keep whitespaces
        if ($value !== $v = rtrim($value)) {
            $value = '""' === substr_replace($v, '', 1, -1) ? substr($v, 1, -1) : $v;
        }
        $lowercaseValue = strtolower($value);
        return match (\true) {
            \defined($value) => \constant($value),
            'yes' === $lowercaseValue, 'on' === $lowercaseValue => \true,
            'no' === $lowercaseValue, 'off' === $lowercaseValue, 'none' === $lowercaseValue => \false,
            isset($value[1]) && ("'" === $value[0] && "'" === $value[\strlen($value) - 1] || '"' === $value[0] && '"' === $value[\strlen($value) - 1]) => substr($value, 1, -1),
            // quoted string
            default => XmlUtils::phpize($value),
        };
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\DependencyInjection\Loader\Configurator;

use _ContaoManager\Symfony\Component\DependencyInjection\Alias;
use _ContaoManager\Symfony\Component\DependencyInjection\ChildDefinition;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerBuilder;
use _ContaoManager\Symfony\Component\DependencyInjection\Definition;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException;
use _ContaoManager\Symfony\Component\DependencyInjection\Loader\PhpFileLoader;
/**
 * @author Nicolas Grekas <p@tchwork.com>
 */
class ServicesConfigurator extends AbstractConfigurator
{
    public const FACTORY = 'services';
    private Definition $defaults;
    private ContainerBuilder $container;
    private PhpFileLoader $loader;
    private array $instanceof;
    private ?string $path;
    private string $anonymousHash;
    private int $anonymousCount;
    public function __construct(ContainerBuilder $container, PhpFileLoader $loader, array &$instanceof, ?string $path = null, int &$anonymousCount = 0)
    {
        $this->defaults = new Definition();
        $this->container = $container;
        $this->loader = $loader;
        $this->instanceof =& $instanceof;
        $this->path = $path;
        $this->anonymousHash = ContainerBuilder::hash($path ?: mt_rand());
        $this->anonymousCount =& $anonymousCount;
        $instanceof = [];
    }
    /**
     * Defines a set of defaults for following service definitions.
     */
    final public function defaults(): DefaultsConfigurator
    {
        return new DefaultsConfigurator($this, $this->defaults = new Definition(), $this->path);
    }
    /**
     * Defines an instanceof-conditional to be applied to following service definitions.
     */
    final public function instanceof(string $fqcn): InstanceofConfigurator
    {
        $this->instanceof[$fqcn] = $definition = new ChildDefinition('');
        return new InstanceofConfigurator($this, $definition, $fqcn, $this->path);
    }
    /**
     * Registers a service.
     *
     * @param string|null $id    The service id, or null to create an anonymous service
     * @param string|null $class The class of the service, or null when $id is also the class name
     */
    final public function set(?string $id, ?string $class = null): ServiceConfigurator
    {
        $defaults = $this->defaults;
        $definition = new Definition();
        if (null === $id) {
            if (!$class) {
                throw new \LogicException('Anonymous services must have a class name.');
            }
            $id = \sprintf('.%d_%s', ++$this->anonymousCount, preg_replace('/^.*\\\\/', '', $class) . '~' . $this->anonymousHash);
        } elseif (!$defaults->isPublic() || !$defaults->isPrivate()) {
            $definition->setPublic($defaults->isPublic() && !$defaults->isPrivate());
        }
        $definition->setAutowired($defaults->isAutowired());
        $definition->setAutoconfigured($defaults->isAutoconfigured());
        // deep clone, to avoid multiple process of the same instance in the passes
        $definition->setBindings(unserialize(serialize($defaults->getBindings())));
        $definition->setChanges([]);
        $configurator = new ServiceConfigurator($this->container, $this->instanceof, \true, $this, $definition, $id, $defaults->getTags(), $this->path);
        return null !== $class ? $configurator->class($class) : $configurator;
    }
    /**
     * Removes an already defined service definition or alias.
     *
     * @return $this
     */
    final public function remove(string $id): static
    {
        $this->container->removeDefinition($id);
        $this->container->removeAlias($id);
        return $this;
    }
    /**
     * Creates an alias.
     */
    final public function alias(string $id, string $referencedId): AliasConfigurator
    {
        $ref = static::processValue($referencedId, \true);
        $alias = new Alias((string) $ref);
        if (!$this->defaults->isPublic() || !$this->defaults->isPrivate()) {
            $alias->setPublic($this->defaults->isPublic());
        }
        $this->container->setAlias($id, $alias);
        return new AliasConfigurator($this, $alias);
    }
    /**
     * Registers a PSR-4 namespace using a glob pattern.
     */
    final public function load(string $namespace, string $resource): PrototypeConfigurator
    {
        return new PrototypeConfigurator($this, $this->loader, $this->defaults, $namespace, $resource, \true, $this->path);
    }
    /**
     * Gets an already defined service definition.
     *
     * @throws ServiceNotFoundException if the service definition does not exist
     */
    final public function get(string $id): ServiceConfigurator
    {
        $definition = $this->container->getDefinition($id);
        return new ServiceConfigurator($this->container, $definition->getInstanceofConditionals(), \true, $this, $definition, $id, []);
    }
    /**
     * Registers a stack of decorator services.
     *
     * @param InlineServiceConfigurator[]|ReferenceConfigurator[] $services
     */
    final public function stack(string $id, array $services): AliasConfigurator
    {
        foreach ($services as $i => $service) {
            if ($service instanceof InlineServiceConfigurator) {
                $definition = $service->definition->setInstanceofConditionals($this->instanceof);
                $changes = $definition->getChanges();
                $definition->setAutowired((isset($changes['autowired']) ? $definition : $this->defaults)->isAutowired());
                $definition->setAutoconfigured((isset($changes['autoconfigured']) ? $definition : $this->defaults)->isAutoconfigured());
                $definition->setBindings(array_merge($this->defaults->getBindings(), $definition->getBindings()));
                $definition->setChanges($changes);
                $services[$i] = $definition;
            } elseif (!$service instanceof ReferenceConfigurator) {
                throw new InvalidArgumentException(\sprintf('"%s()" expects a list of definitions as returned by "%s()" or "%s()", "%s" given at index "%s" for service "%s".', __METHOD__, InlineServiceConfigurator::FACTORY, ReferenceConfigurator::FACTORY, $service instanceof AbstractConfigurator ? $service::FACTORY . '()' : get_debug_type($service), $i, $id));
            }
        }
        $alias = $this->alias($id, '');
        $alias->definition = $this->set($id)->parent('')->args($services)->tag('container.stack')->definition;
        return $alias;
    }
    /**
     * Registers a service.
     */
    final public function __invoke(string $id, ?string $class = null): ServiceConfigurator
    {
        return $this->set($id, $class);
    }
    public function __destruct()
    {
        $this->loader->registerAliasesForSinglyImplementedInterfaces();
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\DependencyInjection\Loader\Configurator;

use _ContaoManager\Symfony\Component\DependencyInjection\Definition;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
/**
 * @author Nicolas Grekas <p@tchwork.com>
 */
class DefaultsConfigurator extends AbstractServiceConfigurator
{
    use Traits\AutoconfigureTrait;
    use Traits\AutowireTrait;
    use Traits\BindTrait;
    use Traits\PublicTrait;
    public const FACTORY = 'defaults';
    private ?string $path;
    public function __construct(ServicesConfigurator $parent, Definition $definition, ?string $path = null)
    {
        parent::__construct($parent, $definition, null, []);
        $this->path = $path;
    }
    /**
     * Adds a tag for this definition.
     *
     * @return $this
     *
     * @throws InvalidArgumentException when an invalid tag name or attribute is provided
     */
    final public function tag(string $name, array $attributes = []): static
    {
        if ('' === $name) {
            throw new InvalidArgumentException('The tag name in "_defaults" must be a non-empty string.');
        }
        $this->validateAttributes($name, $attributes);
        $this->definition->addTag($name, $attributes);
        return $this;
    }
    /**
     * Defines an instanceof-conditional to be applied to following service definitions.
     */
    final public function instanceof(string $fqcn): InstanceofConfigurator
    {
        return $this->parent->instanceof($fqcn);
    }
    private function validateAttributes(string $tag, array $attributes, array $path = []): void
    {
        foreach ($attributes as $name => $value) {
            if (\is_array($value)) {
                $this->validateAttributes($tag, $value, [...$path, $name]);
            } elseif (!\is_scalar($value ?? '')) {
                $name = implode('.', [...$path, $name]);
                throw new InvalidArgumentException(\sprintf('Tag "%s", attribute "%s" in "_defaults" must be of a scalar-type or an array of scalar-type.', $tag, $name));
            }
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\DependencyInjection\Loader\Configurator;

use _ContaoManager\Symfony\Component\DependencyInjection\ContainerInterface;
/**
 * @author Nicolas Grekas <p@tchwork.com>
 */
class ReferenceConfigurator extends AbstractConfigurator
{
    /** @internal */
    protected string $id;
    /** @internal */
    protected int $invalidBehavior = ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE;
    public function __construct(string $id)
    {
        $this->id = $id;
    }
    /**
     * @return $this
     */
    final public function ignoreOnInvalid(): static
    {
        $this->invalidBehavior = ContainerInterface::IGNORE_ON_INVALID_REFERENCE;
        return $this;
    }
    /**
     * @return $this
     */
    final public function nullOnInvalid(): static
    {
        $this->invalidBehavior = ContainerInterface::NULL_ON_INVALID_REFERENCE;
        return $this;
    }
    /**
     * @return $this
     */
    final public function ignoreOnUninitialized(): static
    {
        $this->invalidBehavior = ContainerInterface::IGNORE_ON_UNINITIALIZED_REFERENCE;
        return $this;
    }
    public function __toString(): string
    {
        return $this->id;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\DependencyInjection\Loader\Configurator;

use _ContaoManager\Symfony\Component\DependencyInjection\Definition;
/**
 * @author Nicolas Grekas <p@tchwork.com>
 */
class FromCallableConfigurator extends AbstractServiceConfigurator
{
    use Traits\AbstractTrait;
    use Traits\AutoconfigureTrait;
    use Traits\AutowireTrait;
    use Traits\BindTrait;
    use Traits\DecorateTrait;
    use Traits\DeprecateTrait;
    use Traits\LazyTrait;
    use Traits\PublicTrait;
    use Traits\ShareTrait;
    use Traits\TagTrait;
    public const FACTORY = 'services';
    private ServiceConfigurator $serviceConfigurator;
    public function __construct(ServiceConfigurator $serviceConfigurator, Definition $definition)
    {
        $this->serviceConfigurator = $serviceConfigurator;
        parent::__construct($serviceConfigurator->parent, $definition, $serviceConfigurator->id);
    }
    public function __destruct()
    {
        $this->serviceConfigurator->__destruct();
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\DependencyInjection\Loader\Configurator\Traits;

trait ClassTrait
{
    /**
     * Sets the service class.
     *
     * @return $this
     */
    final public function class(?string $class): static
    {
        $this->definition->setClass($class);
        return $this;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\DependencyInjection\Loader\Configurator\Traits;

use _ContaoManager\Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
trait CallTrait
{
    /**
     * Adds a method to call after service initialization.
     *
     * @param string $method       The method name to call
     * @param array  $arguments    An array of arguments to pass to the method call
     * @param bool   $returnsClone Whether the call returns the service instance or not
     *
     * @return $this
     *
     * @throws InvalidArgumentException on empty $method param
     */
    final public function call(string $method, array $arguments = [], bool $returnsClone = \false): static
    {
        $this->definition->addMethodCall($method, static::processValue($arguments, \true), $returnsClone);
        return $this;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\DependencyInjection\Loader\Configurator\Traits;

trait SyntheticTrait
{
    /**
     * Sets whether this definition is synthetic, that is not constructed by the
     * container, but dynamically injected.
     *
     * @return $this
     */
    final public function synthetic(bool $synthetic = \true): static
    {
        $this->definition->setSynthetic($synthetic);
        return $this;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\DependencyInjection\Loader\Configurator\Traits;

trait PropertyTrait
{
    /**
     * Sets a specific property.
     *
     * @return $this
     */
    final public function property(string $name, mixed $value): static
    {
        $this->definition->setProperty($name, static::processValue($value, \true));
        return $this;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\DependencyInjection\Loader\Configurator\Traits;

trait ArgumentTrait
{
    /**
     * Sets the arguments to pass to the service constructor/factory method.
     *
     * @return $this
     */
    final public function args(array $arguments): static
    {
        $this->definition->setArguments(static::processValue($arguments, \true));
        return $this;
    }
    /**
     * Sets one argument to pass to the service constructor/factory method.
     *
     * @return $this
     */
    final public function arg(string|int $key, mixed $value): static
    {
        $this->definition->setArgument($key, static::processValue($value, \true));
        return $this;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\DependencyInjection\Loader\Configurator\Traits;

use _ContaoManager\Symfony\Component\DependencyInjection\Loader\Configurator\ReferenceConfigurator;
trait ConfiguratorTrait
{
    /**
     * Sets a configurator to call after the service is fully initialized.
     *
     * @return $this
     */
    final public function configurator(string|array|ReferenceConfigurator $configurator): static
    {
        $this->definition->setConfigurator(static::processValue($configurator, \true));
        return $this;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\DependencyInjection\Loader\Configurator\Traits;

use _ContaoManager\Symfony\Component\DependencyInjection\ChildDefinition;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
trait ParentTrait
{
    /**
     * Sets the Definition to inherit from.
     *
     * @return $this
     *
     * @throws InvalidArgumentException when parent cannot be set
     */
    final public function parent(string $parent): static
    {
        if (!$this->allowParent) {
            throw new InvalidArgumentException(\sprintf('A parent cannot be defined when either "_instanceof" or "_defaults" are also defined for service prototype "%s".', $this->id));
        }
        if ($this->definition instanceof ChildDefinition) {
            $this->definition->setParent($parent);
        } else {
            // cast Definition to ChildDefinition
            $definition = serialize($this->definition);
            $definition = substr_replace($definition, '68', 2, 2);
            $definition = substr_replace($definition, 'Child', 59, 0);
            $definition = unserialize($definition);
            $this->definition = $definition->setParent($parent);
        }
        return $this;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\DependencyInjection\Loader\Configurator\Traits;

use _ContaoManager\Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
use _ContaoManager\Symfony\Component\DependencyInjection\Loader\Configurator\ReferenceConfigurator;
use _ContaoManager\Symfony\Component\ExpressionLanguage\Expression;
trait FactoryTrait
{
    /**
     * Sets a factory.
     *
     * @return $this
     */
    final public function factory(string|array|ReferenceConfigurator|Expression $factory): static
    {
        if (\is_string($factory) && 1 === substr_count($factory, ':')) {
            $factoryParts = explode(':', $factory);
            throw new InvalidArgumentException(\sprintf('Invalid factory "%s": the "service:method" notation is not available when using PHP-based DI configuration. Use "[service(\'%s\'), \'%s\']" instead.', $factory, $factoryParts[0], $factoryParts[1]));
        }
        if ($factory instanceof Expression) {
            $factory = '@=' . $factory;
        }
        $this->definition->setFactory(static::processValue($factory, \true));
        return $this;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\DependencyInjection\Loader\Configurator\Traits;

use _ContaoManager\Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
trait TagTrait
{
    /**
     * Adds a tag for this definition.
     *
     * @return $this
     */
    final public function tag(string $name, array $attributes = []): static
    {
        if ('' === $name) {
            throw new InvalidArgumentException(\sprintf('The tag name for service "%s" must be a non-empty string.', $this->id));
        }
        $this->validateAttributes($name, $attributes);
        $this->definition->addTag($name, $attributes);
        return $this;
    }
    private function validateAttributes(string $tag, array $attributes, array $path = []): void
    {
        foreach ($attributes as $name => $value) {
            if (\is_array($value)) {
                $this->validateAttributes($tag, $value, [...$path, $name]);
            } elseif (!\is_scalar($value ?? '')) {
                $name = implode('.', [...$path, $name]);
                throw new InvalidArgumentException(\sprintf('A tag attribute must be of a scalar-type or an array of scalar-types for service "%s", tag "%s", attribute "%s".', $this->id, $tag, $name));
            }
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\DependencyInjection\Loader\Configurator\Traits;

trait PublicTrait
{
    /**
     * @return $this
     */
    final public function public(): static
    {
        $this->definition->setPublic(\true);
        return $this;
    }
    /**
     * @return $this
     */
    final public function private(): static
    {
        $this->definition->setPublic(\false);
        return $this;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\DependencyInjection\Loader\Configurator\Traits;

use _ContaoManager\Symfony\Component\DependencyInjection\ContainerInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
trait DecorateTrait
{
    /**
     * Sets the service that this service is decorating.
     *
     * @param string|null $id The decorated service id, use null to remove decoration
     *
     * @return $this
     *
     * @throws InvalidArgumentException in case the decorated service id and the new decorated service id are equals
     */
    final public function decorate(?string $id, ?string $renamedId = null, int $priority = 0, int $invalidBehavior = ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE): static
    {
        $this->definition->setDecoratedService($id, $renamedId, $priority, $invalidBehavior);
        return $this;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\DependencyInjection\Loader\Configurator\Traits;

use _ContaoManager\Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
trait AutoconfigureTrait
{
    /**
     * Sets whether or not instanceof conditionals should be prepended with a global set.
     *
     * @return $this
     *
     * @throws InvalidArgumentException when a parent is already set
     */
    final public function autoconfigure(bool $autoconfigured = \true): static
    {
        $this->definition->setAutoconfigured($autoconfigured);
        return $this;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\DependencyInjection\Loader\Configurator\Traits;

use _ContaoManager\Symfony\Component\DependencyInjection\ChildDefinition;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
use _ContaoManager\Symfony\Component\DependencyInjection\Loader\Configurator\FromCallableConfigurator;
use _ContaoManager\Symfony\Component\DependencyInjection\Loader\Configurator\ReferenceConfigurator;
use _ContaoManager\Symfony\Component\ExpressionLanguage\Expression;
trait FromCallableTrait
{
    final public function fromCallable(string|array|ReferenceConfigurator|Expression $callable): FromCallableConfigurator
    {
        if ($this->definition instanceof ChildDefinition) {
            throw new InvalidArgumentException('The configuration key "parent" is unsupported when using "fromCallable()".');
        }
        foreach (['synthetic' => 'isSynthetic', 'factory' => 'getFactory', 'file' => 'getFile', 'arguments' => 'getArguments', 'properties' => 'getProperties', 'configurator' => 'getConfigurator', 'calls' => 'getMethodCalls'] as $key => $method) {
            if ($this->definition->{$method}()) {
                throw new InvalidArgumentException(\sprintf('The configuration key "%s" is unsupported when using "fromCallable()".', $key));
            }
        }
        $this->definition->setFactory(['Closure', 'fromCallable']);
        if (\is_string($callable) && 1 === substr_count($callable, ':')) {
            $parts = explode(':', $callable);
            throw new InvalidArgumentException(\sprintf('Invalid callable "%s": the "service:method" notation is not available when using PHP-based DI configuration. Use "[service(\'%s\'), \'%s\']" instead.', $callable, $parts[0], $parts[1]));
        }
        if ($callable instanceof Expression) {
            $callable = '@=' . $callable;
        }
        $this->definition->setArguments([static::processValue($callable, \true)]);
        if ('Closure' !== ($this->definition->getClass() ?? 'Closure')) {
            $this->definition->setLazy(\true);
        } else {
            $this->definition->setClass('Closure');
        }
        return new FromCallableConfigurator($this, $this->definition);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\DependencyInjection\Loader\Configurator\Traits;

use _ContaoManager\Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
trait DeprecateTrait
{
    /**
     * Whether this definition is deprecated, that means it should not be called anymore.
     *
     * @param string $package The name of the composer package that is triggering the deprecation
     * @param string $version The version of the package that introduced the deprecation
     * @param string $message The deprecation message to use
     *
     * @return $this
     *
     * @throws InvalidArgumentException when the message template is invalid
     */
    final public function deprecate(string $package, string $version, string $message): static
    {
        $this->definition->setDeprecated($package, $version, $message);
        return $this;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\DependencyInjection\Loader\Configurator\Traits;

use _ContaoManager\Symfony\Component\DependencyInjection\Argument\BoundArgument;
use _ContaoManager\Symfony\Component\DependencyInjection\Loader\Configurator\DefaultsConfigurator;
use _ContaoManager\Symfony\Component\DependencyInjection\Loader\Configurator\InstanceofConfigurator;
trait BindTrait
{
    /**
     * Sets bindings.
     *
     * Bindings map $named or FQCN arguments to values that should be
     * injected in the matching parameters (of the constructor, of methods
     * called and of controller actions).
     *
     * @param string $nameOrFqcn A parameter name with its "$" prefix, or an FQCN
     * @param mixed  $valueOrRef The value or reference to bind
     *
     * @return $this
     */
    final public function bind(string $nameOrFqcn, mixed $valueOrRef): static
    {
        $valueOrRef = static::processValue($valueOrRef, \true);
        $bindings = $this->definition->getBindings();
        $type = $this instanceof DefaultsConfigurator ? BoundArgument::DEFAULTS_BINDING : ($this instanceof InstanceofConfigurator ? BoundArgument::INSTANCEOF_BINDING : BoundArgument::SERVICE_BINDING);
        $bindings[$nameOrFqcn] = new BoundArgument($valueOrRef, \true, $type, $this->path ?? null);
        $this->definition->setBindings($bindings);
        return $this;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\DependencyInjection\Loader\Configurator\Traits;

trait LazyTrait
{
    /**
     * Sets the lazy flag of this service.
     *
     * @param bool|string $lazy A FQCN to derivate the lazy proxy from or `true` to make it extend from the definition's class
     *
     * @return $this
     */
    final public function lazy(bool|string $lazy = \true): static
    {
        $this->definition->setLazy((bool) $lazy);
        if (\is_string($lazy)) {
            $this->definition->addTag('proxy', ['interface' => $lazy]);
        }
        return $this;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\DependencyInjection\Loader\Configurator\Traits;

trait FileTrait
{
    /**
     * Sets a file to require before creating the service.
     *
     * @return $this
     */
    final public function file(string $file): static
    {
        $this->definition->setFile($file);
        return $this;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\DependencyInjection\Loader\Configurator\Traits;

trait AbstractTrait
{
    /**
     * Whether this definition is abstract, that means it merely serves as a
     * template for other definitions.
     *
     * @return $this
     */
    final public function abstract(bool $abstract = \true): static
    {
        $this->definition->setAbstract($abstract);
        return $this;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\DependencyInjection\Loader\Configurator\Traits;

trait ShareTrait
{
    /**
     * Sets if the service must be shared or not.
     *
     * @return $this
     */
    final public function share(bool $shared = \true): static
    {
        $this->definition->setShared($shared);
        return $this;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\DependencyInjection\Loader\Configurator\Traits;

trait AutowireTrait
{
    /**
     * Enables/disables autowiring.
     *
     * @return $this
     */
    final public function autowire(bool $autowired = \true): static
    {
        $this->definition->setAutowired($autowired);
        return $this;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\DependencyInjection\Loader\Configurator\Traits;

trait ConstructorTrait
{
    /**
     * Sets a static constructor.
     *
     * @return $this
     */
    final public function constructor(string $constructor): static
    {
        $this->definition->setFactory([null, $constructor]);
        return $this;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\DependencyInjection\Loader\Configurator;

use _ContaoManager\Symfony\Component\Config\Loader\ParamConfigurator;
use _ContaoManager\Symfony\Component\DependencyInjection\Alias;
use _ContaoManager\Symfony\Component\DependencyInjection\Argument\AbstractArgument;
use _ContaoManager\Symfony\Component\DependencyInjection\Argument\ArgumentInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Argument\ServiceClosureArgument;
use _ContaoManager\Symfony\Component\DependencyInjection\Definition;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
use _ContaoManager\Symfony\Component\DependencyInjection\Parameter;
use _ContaoManager\Symfony\Component\DependencyInjection\Reference;
use _ContaoManager\Symfony\Component\ExpressionLanguage\Expression;
abstract class AbstractConfigurator
{
    public const FACTORY = 'unknown';
    /**
     * @var \Closure(mixed, bool):mixed|null
     */
    public static $valuePreProcessor;
    /** @internal */
    protected Definition|Alias|null $definition = null;
    /**
     * @return mixed
     */
    public function __call(string $method, array $args)
    {
        if (method_exists($this, 'set' . $method)) {
            return $this->{'set' . $method}(...$args);
        }
        throw new \BadMethodCallException(\sprintf('Call to undefined method "%s::%s()".', static::class, $method));
    }
    public function __serialize(): array
    {
        throw new \BadMethodCallException('Cannot serialize ' . __CLASS__);
    }
    public function __unserialize(array $data): void
    {
        throw new \BadMethodCallException('Cannot unserialize ' . __CLASS__);
    }
    /**
     * Checks that a value is valid, optionally replacing Definition and Reference configurators by their configure value.
     *
     * @param bool $allowServices whether Definition and Reference are allowed; by default, only scalars, arrays and enum are
     *
     * @return mixed the value, optionally cast to a Definition/Reference
     */
    public static function processValue(mixed $value, bool $allowServices = \false): mixed
    {
        if (\is_array($value)) {
            foreach ($value as $k => $v) {
                $value[$k] = static::processValue($v, $allowServices);
            }
            return self::$valuePreProcessor ? (self::$valuePreProcessor)($value, $allowServices) : $value;
        }
        if (self::$valuePreProcessor) {
            $value = (self::$valuePreProcessor)($value, $allowServices);
        }
        if ($value instanceof ParamConfigurator) {
            return (string) $value;
        }
        if (\is_scalar($value ?? '') || $value instanceof \UnitEnum) {
            return $value;
        }
        if (!$allowServices) {
            throw new InvalidArgumentException(\sprintf('Cannot use values of type "%s" in service configuration files.', get_debug_type($value)));
        }
        if ($value instanceof ReferenceConfigurator) {
            $reference = new Reference($value->id, $value->invalidBehavior);
            return $value instanceof ClosureReferenceConfigurator ? new ServiceClosureArgument($reference) : $reference;
        }
        if ($value instanceof InlineServiceConfigurator) {
            $def = $value->definition;
            $value->definition = null;
            return $def;
        }
        if ($value instanceof self) {
            throw new InvalidArgumentException(\sprintf('"%s()" can be used only at the root of service configuration files.', $value::FACTORY));
        }
        switch (\true) {
            case $value instanceof ArgumentInterface:
            case $value instanceof Definition:
            case $value instanceof Expression:
            case $value instanceof Parameter:
            case $value instanceof AbstractArgument:
            case $value instanceof Reference:
                return $value;
        }
        throw new InvalidArgumentException(\sprintf('Cannot use values of type "%s" in service configuration files.', get_debug_type($value)));
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\DependencyInjection\Loader\Configurator;

class ClosureReferenceConfigurator extends ReferenceConfigurator
{
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\DependencyInjection\Loader\Configurator;

use _ContaoManager\Symfony\Component\Config\Loader\ParamConfigurator;
class EnvConfigurator extends ParamConfigurator
{
    /**
     * @var string[]
     */
    private array $stack;
    public function __construct(string $name)
    {
        $this->stack = explode(':', $name);
    }
    public function __toString(): string
    {
        return '%env(' . implode(':', $this->stack) . ')%';
    }
    /**
     * @return $this
     */
    public function __call(string $name, array $arguments): static
    {
        $processor = strtolower(preg_replace(['/([A-Z]+)([A-Z][a-z])/', '/([a-z\d])([A-Z])/'], '\1_\2', $name));
        $this->custom($processor, ...$arguments);
        return $this;
    }
    /**
     * @return $this
     */
    public function custom(string $processor, ...$args): static
    {
        array_unshift($this->stack, $processor, ...$args);
        return $this;
    }
    /**
     * @return $this
     */
    public function base64(): static
    {
        array_unshift($this->stack, 'base64');
        return $this;
    }
    /**
     * @return $this
     */
    public function bool(): static
    {
        array_unshift($this->stack, 'bool');
        return $this;
    }
    /**
     * @return $this
     */
    public function not(): static
    {
        array_unshift($this->stack, 'not');
        return $this;
    }
    /**
     * @return $this
     */
    public function const(): static
    {
        array_unshift($this->stack, 'const');
        return $this;
    }
    /**
     * @return $this
     */
    public function csv(): static
    {
        array_unshift($this->stack, 'csv');
        return $this;
    }
    /**
     * @return $this
     */
    public function file(): static
    {
        array_unshift($this->stack, 'file');
        return $this;
    }
    /**
     * @return $this
     */
    public function float(): static
    {
        array_unshift($this->stack, 'float');
        return $this;
    }
    /**
     * @return $this
     */
    public function int(): static
    {
        array_unshift($this->stack, 'int');
        return $this;
    }
    /**
     * @return $this
     */
    public function json(): static
    {
        array_unshift($this->stack, 'json');
        return $this;
    }
    /**
     * @return $this
     */
    public function key(string $key): static
    {
        array_unshift($this->stack, 'key', $key);
        return $this;
    }
    /**
     * @return $this
     */
    public function url(): static
    {
        array_unshift($this->stack, 'url');
        return $this;
    }
    /**
     * @return $this
     */
    public function queryString(): static
    {
        array_unshift($this->stack, 'query_string');
        return $this;
    }
    /**
     * @return $this
     */
    public function resolve(): static
    {
        array_unshift($this->stack, 'resolve');
        return $this;
    }
    /**
     * @return $this
     */
    public function default(string $fallbackParam): static
    {
        array_unshift($this->stack, 'default', $fallbackParam);
        return $this;
    }
    /**
     * @return $this
     */
    public function string(): static
    {
        array_unshift($this->stack, 'string');
        return $this;
    }
    /**
     * @return $this
     */
    public function trim(): static
    {
        array_unshift($this->stack, 'trim');
        return $this;
    }
    /**
     * @return $this
     */
    public function require(): static
    {
        array_unshift($this->stack, 'require');
        return $this;
    }
    /**
     * @param class-string<\BackedEnum> $backedEnumClassName
     *
     * @return $this
     */
    public function enum(string $backedEnumClassName): static
    {
        array_unshift($this->stack, 'enum', $backedEnumClassName);
        return $this;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\DependencyInjection\Loader\Configurator;

use _ContaoManager\Symfony\Component\DependencyInjection\Definition;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException;
abstract class AbstractServiceConfigurator extends AbstractConfigurator
{
    protected $parent;
    protected $id;
    private array $defaultTags = [];
    public function __construct(ServicesConfigurator $parent, Definition $definition, ?string $id = null, array $defaultTags = [])
    {
        $this->parent = $parent;
        $this->definition = $definition;
        $this->id = $id;
        $this->defaultTags = $defaultTags;
    }
    public function __destruct()
    {
        // default tags should be added last
        foreach ($this->defaultTags as $name => $attributes) {
            foreach ($attributes as $attribute) {
                $this->definition->addTag($name, $attribute);
            }
        }
        $this->defaultTags = [];
    }
    /**
     * Registers a service.
     */
    final public function set(?string $id, ?string $class = null): ServiceConfigurator
    {
        $this->__destruct();
        return $this->parent->set($id, $class);
    }
    /**
     * Creates an alias.
     */
    final public function alias(string $id, string $referencedId): AliasConfigurator
    {
        $this->__destruct();
        return $this->parent->alias($id, $referencedId);
    }
    /**
     * Registers a PSR-4 namespace using a glob pattern.
     */
    final public function load(string $namespace, string $resource): PrototypeConfigurator
    {
        $this->__destruct();
        return $this->parent->load($namespace, $resource);
    }
    /**
     * Gets an already defined service definition.
     *
     * @throws ServiceNotFoundException if the service definition does not exist
     */
    final public function get(string $id): ServiceConfigurator
    {
        $this->__destruct();
        return $this->parent->get($id);
    }
    /**
     * Removes an already defined service definition or alias.
     */
    final public function remove(string $id): ServicesConfigurator
    {
        $this->__destruct();
        return $this->parent->remove($id);
    }
    /**
     * Registers a stack of decorator services.
     *
     * @param InlineServiceConfigurator[]|ReferenceConfigurator[] $services
     */
    final public function stack(string $id, array $services): AliasConfigurator
    {
        $this->__destruct();
        return $this->parent->stack($id, $services);
    }
    /**
     * Registers a service.
     */
    final public function __invoke(string $id, ?string $class = null): ServiceConfigurator
    {
        $this->__destruct();
        return $this->parent->set($id, $class);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\DependencyInjection\Loader\Configurator;

use _ContaoManager\Symfony\Component\DependencyInjection\Definition;
/**
 * @author Nicolas Grekas <p@tchwork.com>
 */
class InstanceofConfigurator extends AbstractServiceConfigurator
{
    use Traits\AutowireTrait;
    use Traits\BindTrait;
    use Traits\CallTrait;
    use Traits\ConfiguratorTrait;
    use Traits\ConstructorTrait;
    use Traits\LazyTrait;
    use Traits\PropertyTrait;
    use Traits\PublicTrait;
    use Traits\ShareTrait;
    use Traits\TagTrait;
    public const FACTORY = 'instanceof';
    private ?string $path;
    public function __construct(ServicesConfigurator $parent, Definition $definition, string $id, ?string $path = null)
    {
        parent::__construct($parent, $definition, $id, []);
        $this->path = $path;
    }
    /**
     * Defines an instanceof-conditional to be applied to following service definitions.
     */
    final public function instanceof(string $fqcn): self
    {
        return $this->parent->instanceof($fqcn);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\DependencyInjection\Loader\Configurator;

use _ContaoManager\Symfony\Component\Config\Loader\ParamConfigurator;
use _ContaoManager\Symfony\Component\DependencyInjection\Argument\AbstractArgument;
use _ContaoManager\Symfony\Component\DependencyInjection\Argument\IteratorArgument;
use _ContaoManager\Symfony\Component\DependencyInjection\Argument\ServiceLocatorArgument;
use _ContaoManager\Symfony\Component\DependencyInjection\Argument\TaggedIteratorArgument;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerBuilder;
use _ContaoManager\Symfony\Component\DependencyInjection\Definition;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
use _ContaoManager\Symfony\Component\DependencyInjection\Extension\ExtensionInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Loader\PhpFileLoader;
use _ContaoManager\Symfony\Component\ExpressionLanguage\Expression;
/**
 * @author Nicolas Grekas <p@tchwork.com>
 */
class ContainerConfigurator extends AbstractConfigurator
{
    public const FACTORY = 'container';
    private ContainerBuilder $container;
    private PhpFileLoader $loader;
    private array $instanceof;
    private string $path;
    private string $file;
    private int $anonymousCount = 0;
    private ?string $env;
    public function __construct(ContainerBuilder $container, PhpFileLoader $loader, array &$instanceof, string $path, string $file, ?string $env = null)
    {
        $this->container = $container;
        $this->loader = $loader;
        $this->instanceof =& $instanceof;
        $this->path = $path;
        $this->file = $file;
        $this->env = $env;
    }
    final public function extension(string $namespace, array $config): void
    {
        if (!$this->container->hasExtension($namespace)) {
            $extensions = array_filter(array_map(fn(ExtensionInterface $ext) => $ext->getAlias(), $this->container->getExtensions()));
            throw new InvalidArgumentException(\sprintf('There is no extension able to load the configuration for "%s" (in "%s"). Looked for namespace "%s", found "%s".', $namespace, $this->file, $namespace, $extensions ? implode('", "', $extensions) : 'none'));
        }
        $this->container->loadFromExtension($namespace, static::processValue($config));
    }
    final public function import(string $resource, ?string $type = null, bool|string $ignoreErrors = \false): void
    {
        $this->loader->setCurrentDir(\dirname($this->path));
        $this->loader->import($resource, $type, $ignoreErrors, $this->file);
    }
    final public function parameters(): ParametersConfigurator
    {
        return new ParametersConfigurator($this->container);
    }
    final public function services(): ServicesConfigurator
    {
        return new ServicesConfigurator($this->container, $this->loader, $this->instanceof, $this->path, $this->anonymousCount);
    }
    /**
     * Get the current environment to be able to write conditional configuration.
     */
    final public function env(): ?string
    {
        return $this->env;
    }
    final public function withPath(string $path): static
    {
        $clone = clone $this;
        $clone->path = $clone->file = $path;
        $clone->loader->setCurrentDir(\dirname($path));
        return $clone;
    }
}
/**
 * Creates a parameter.
 */
function param(string $name): ParamConfigurator
{
    return new ParamConfigurator($name);
}
/**
 * Creates a reference to a service.
 */
function service(string $serviceId): ReferenceConfigurator
{
    return new ReferenceConfigurator($serviceId);
}
/**
 * Creates an inline service.
 */
function inline_service(?string $class = null): InlineServiceConfigurator
{
    return new InlineServiceConfigurator(new Definition($class));
}
/**
 * Creates a service locator.
 *
 * @param array<ReferenceConfigurator|InlineServiceConfigurator> $values
 */
function service_locator(array $values): ServiceLocatorArgument
{
    $values = AbstractConfigurator::processValue($values, \true);
    if (isset($values[0])) {
        trigger_deprecation('symfony/dependency-injection', '6.3', 'Using integers as keys in a "service_locator()" argument is deprecated. The keys will default to the IDs of the original services in 7.0.');
    }
    return new ServiceLocatorArgument($values);
}
/**
 * Creates a lazy iterator.
 *
 * @param ReferenceConfigurator[] $values
 */
function iterator(array $values): IteratorArgument
{
    return new IteratorArgument(AbstractConfigurator::processValue($values, \true));
}
/**
 * Creates a lazy iterator by tag name.
 */
function tagged_iterator(string $tag, ?string $indexAttribute = null, ?string $defaultIndexMethod = null, ?string $defaultPriorityMethod = null, string|array $exclude = [], bool $excludeSelf = \true): TaggedIteratorArgument
{
    return new TaggedIteratorArgument($tag, $indexAttribute, $defaultIndexMethod, \false, $defaultPriorityMethod, (array) $exclude, $excludeSelf);
}
/**
 * Creates a service locator by tag name.
 */
function tagged_locator(string $tag, ?string $indexAttribute = null, ?string $defaultIndexMethod = null, ?string $defaultPriorityMethod = null, string|array $exclude = [], bool $excludeSelf = \true): ServiceLocatorArgument
{
    return new ServiceLocatorArgument(new TaggedIteratorArgument($tag, $indexAttribute, $defaultIndexMethod, \true, $defaultPriorityMethod, (array) $exclude, $excludeSelf));
}
/**
 * Creates an expression.
 */
function expr(string $expression): Expression
{
    return new Expression($expression);
}
/**
 * Creates an abstract argument.
 */
function abstract_arg(string $description): AbstractArgument
{
    return new AbstractArgument($description);
}
/**
 * Creates an environment variable reference.
 */
function env(string $name): EnvConfigurator
{
    return new EnvConfigurator($name);
}
/**
 * Creates a closure service reference.
 */
function service_closure(string $serviceId): ClosureReferenceConfigurator
{
    return new ClosureReferenceConfigurator($serviceId);
}
/**
 * Creates a closure.
 */
function closure(string|array|ReferenceConfigurator|Expression $callable): InlineServiceConfigurator
{
    return (new InlineServiceConfigurator(new Definition('Closure')))->factory(['Closure', 'fromCallable'])->args([$callable]);
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\DependencyInjection\Loader\Configurator;

use _ContaoManager\Symfony\Component\DependencyInjection\Alias;
/**
 * @author Nicolas Grekas <p@tchwork.com>
 */
class AliasConfigurator extends AbstractServiceConfigurator
{
    use Traits\DeprecateTrait;
    use Traits\PublicTrait;
    public const FACTORY = 'alias';
    public function __construct(ServicesConfigurator $parent, Alias $alias)
    {
        $this->parent = $parent;
        $this->definition = $alias;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\DependencyInjection\Loader\Configurator;

use _ContaoManager\Symfony\Component\DependencyInjection\Definition;
/**
 * @author Nicolas Grekas <p@tchwork.com>
 */
class InlineServiceConfigurator extends AbstractConfigurator
{
    use Traits\ArgumentTrait;
    use Traits\AutowireTrait;
    use Traits\BindTrait;
    use Traits\CallTrait;
    use Traits\ConfiguratorTrait;
    use Traits\ConstructorTrait;
    use Traits\FactoryTrait;
    use Traits\FileTrait;
    use Traits\LazyTrait;
    use Traits\ParentTrait;
    use Traits\PropertyTrait;
    use Traits\TagTrait;
    public const FACTORY = 'service';
    private string $id = '[inline]';
    private bool $allowParent = \true;
    private ?string $path = null;
    public function __construct(Definition $definition)
    {
        $this->definition = $definition;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\DependencyInjection\Loader\Configurator;

use _ContaoManager\Symfony\Component\DependencyInjection\Definition;
use _ContaoManager\Symfony\Component\DependencyInjection\Loader\PhpFileLoader;
/**
 * @author Nicolas Grekas <p@tchwork.com>
 */
class PrototypeConfigurator extends AbstractServiceConfigurator
{
    use Traits\AbstractTrait;
    use Traits\ArgumentTrait;
    use Traits\AutoconfigureTrait;
    use Traits\AutowireTrait;
    use Traits\BindTrait;
    use Traits\CallTrait;
    use Traits\ConfiguratorTrait;
    use Traits\ConstructorTrait;
    use Traits\DeprecateTrait;
    use Traits\FactoryTrait;
    use Traits\LazyTrait;
    use Traits\ParentTrait;
    use Traits\PropertyTrait;
    use Traits\PublicTrait;
    use Traits\ShareTrait;
    use Traits\TagTrait;
    public const FACTORY = 'load';
    private PhpFileLoader $loader;
    private string $resource;
    private ?array $excludes = null;
    private bool $allowParent;
    private ?string $path;
    public function __construct(ServicesConfigurator $parent, PhpFileLoader $loader, Definition $defaults, string $namespace, string $resource, bool $allowParent, ?string $path = null)
    {
        $definition = new Definition();
        if (!$defaults->isPublic() || !$defaults->isPrivate()) {
            $definition->setPublic($defaults->isPublic());
        }
        $definition->setAutowired($defaults->isAutowired());
        $definition->setAutoconfigured($defaults->isAutoconfigured());
        // deep clone, to avoid multiple process of the same instance in the passes
        $definition->setBindings(unserialize(serialize($defaults->getBindings())));
        $definition->setChanges([]);
        $this->loader = $loader;
        $this->resource = $resource;
        $this->allowParent = $allowParent;
        $this->path = $path;
        parent::__construct($parent, $definition, $namespace, $defaults->getTags());
    }
    public function __destruct()
    {
        parent::__destruct();
        if (isset($this->loader)) {
            $this->loader->registerClasses($this->definition, $this->id, $this->resource, $this->excludes, $this->path);
        }
        unset($this->loader);
    }
    /**
     * Excludes files from registration using glob patterns.
     *
     * @param string[]|string $excludes
     *
     * @return $this
     */
    final public function exclude(array|string $excludes): static
    {
        $this->excludes = (array) $excludes;
        return $this;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\DependencyInjection\Loader\Configurator;

use _ContaoManager\Symfony\Component\DependencyInjection\ContainerBuilder;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
use _ContaoManager\Symfony\Component\ExpressionLanguage\Expression;
/**
 * @author Nicolas Grekas <p@tchwork.com>
 */
class ParametersConfigurator extends AbstractConfigurator
{
    public const FACTORY = 'parameters';
    private ContainerBuilder $container;
    public function __construct(ContainerBuilder $container)
    {
        $this->container = $container;
    }
    /**
     * @return $this
     */
    final public function set(string $name, mixed $value): static
    {
        if ($value instanceof Expression) {
            throw new InvalidArgumentException(\sprintf('Using an expression in parameter "%s" is not allowed.', $name));
        }
        $this->container->setParameter($name, static::processValue($value, \true));
        return $this;
    }
    /**
     * @return $this
     */
    final public function __invoke(string $name, mixed $value): static
    {
        return $this->set($name, $value);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\DependencyInjection\Loader\Configurator;

use _ContaoManager\Symfony\Component\DependencyInjection\ContainerBuilder;
use _ContaoManager\Symfony\Component\DependencyInjection\Definition;
/**
 * @author Nicolas Grekas <p@tchwork.com>
 */
class ServiceConfigurator extends AbstractServiceConfigurator
{
    use Traits\AbstractTrait;
    use Traits\ArgumentTrait;
    use Traits\AutoconfigureTrait;
    use Traits\AutowireTrait;
    use Traits\BindTrait;
    use Traits\CallTrait;
    use Traits\ClassTrait;
    use Traits\ConfiguratorTrait;
    use Traits\ConstructorTrait;
    use Traits\DecorateTrait;
    use Traits\DeprecateTrait;
    use Traits\FactoryTrait;
    use Traits\FileTrait;
    use Traits\FromCallableTrait;
    use Traits\LazyTrait;
    use Traits\ParentTrait;
    use Traits\PropertyTrait;
    use Traits\PublicTrait;
    use Traits\ShareTrait;
    use Traits\SyntheticTrait;
    use Traits\TagTrait;
    public const FACTORY = 'services';
    private ContainerBuilder $container;
    private array $instanceof;
    private bool $allowParent;
    private ?string $path;
    private bool $destructed = \false;
    public function __construct(ContainerBuilder $container, array $instanceof, bool $allowParent, ServicesConfigurator $parent, Definition $definition, ?string $id, array $defaultTags, ?string $path = null)
    {
        $this->container = $container;
        $this->instanceof = $instanceof;
        $this->allowParent = $allowParent;
        $this->path = $path;
        parent::__construct($parent, $definition, $id, $defaultTags);
    }
    public function __destruct()
    {
        if ($this->destructed) {
            return;
        }
        $this->destructed = \true;
        parent::__destruct();
        $this->container->removeBindings($this->id);
        $this->container->setDefinition($this->id, $this->definition->setInstanceofConditionals($this->instanceof));
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\DependencyInjection\Loader;

/**
 * DirectoryLoader is a recursive loader to go through directories.
 *
 * @author Sebastien Lavoie <seb@wemakecustom.com>
 */
class DirectoryLoader extends FileLoader
{
    public function load(mixed $file, ?string $type = null): mixed
    {
        $file = rtrim($file, '/');
        $path = $this->locator->locate($file);
        $this->container->fileExists($path, \false);
        foreach (scandir($path) as $dir) {
            if ('.' !== $dir[0]) {
                if (is_dir($path . '/' . $dir)) {
                    $dir .= '/';
                    // append / to allow recursion
                }
                $this->setCurrentDir($path);
                $this->import($dir, null, \false, $path);
            }
        }
        return null;
    }
    public function supports(mixed $resource, ?string $type = null): bool
    {
        if ('directory' === $type) {
            return \true;
        }
        return null === $type && \is_string($resource) && str_ends_with($resource, '/');
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\DependencyInjection\Loader;

/**
 * GlobFileLoader loads files from a glob pattern.
 *
 * @author Nicolas Grekas <p@tchwork.com>
 */
class GlobFileLoader extends FileLoader
{
    public function load(mixed $resource, ?string $type = null): mixed
    {
        foreach ($this->glob($resource, \false, $globResource) as $path => $info) {
            $this->import($path);
        }
        $this->container->addResource($globResource);
        return null;
    }
    public function supports(mixed $resource, ?string $type = null): bool
    {
        return 'glob' === $type;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\DependencyInjection\Loader;

use _ContaoManager\Symfony\Component\Config\Loader\Loader;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerBuilder;
/**
 * ClosureLoader loads service definitions from a PHP closure.
 *
 * The Closure has access to the container as its first argument.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class ClosureLoader extends Loader
{
    private ContainerBuilder $container;
    public function __construct(ContainerBuilder $container, ?string $env = null)
    {
        $this->container = $container;
        parent::__construct($env);
    }
    public function load(mixed $resource, ?string $type = null): mixed
    {
        return $resource($this->container, $this->env);
    }
    public function supports(mixed $resource, ?string $type = null): bool
    {
        return $resource instanceof \Closure;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\DependencyInjection\LazyProxy;

trigger_deprecation('symfony/dependency-injection', '6.2', 'The "%s" class is deprecated, use "%s" instead.', ProxyHelper::class, \_ContaoManager\Symfony\Component\VarExporter\ProxyHelper::class);
/**
 * @author Nicolas Grekas <p@tchwork.com>
 *
 * @deprecated since Symfony 6.2, use VarExporter's ProxyHelper instead
 */
class ProxyHelper
{
    /**
     * @return string|null The FQCN or builtin name of the type hint, or null when the type hint references an invalid self|parent context
     */
    public static function getTypeHint(\ReflectionFunctionAbstract $r, ?\ReflectionParameter $p = null, bool $noBuiltin = \false): ?string
    {
        if ($p instanceof \ReflectionParameter) {
            $type = $p->getType();
        } else {
            $type = $r->getReturnType();
        }
        if (!$type) {
            return null;
        }
        return self::getTypeHintForType($type, $r, $noBuiltin);
    }
    private static function getTypeHintForType(\ReflectionType $type, \ReflectionFunctionAbstract $r, bool $noBuiltin): ?string
    {
        $types = [];
        $glue = '|';
        if ($type instanceof \ReflectionUnionType) {
            $reflectionTypes = $type->getTypes();
        } elseif ($type instanceof \ReflectionIntersectionType) {
            $reflectionTypes = $type->getTypes();
            $glue = '&';
        } elseif ($type instanceof \ReflectionNamedType) {
            $reflectionTypes = [$type];
        } else {
            return null;
        }
        foreach ($reflectionTypes as $type) {
            if ($type instanceof \ReflectionIntersectionType) {
                $typeHint = self::getTypeHintForType($type, $r, $noBuiltin);
                if (null === $typeHint) {
                    return null;
                }
                $types[] = \sprintf('(%s)', $typeHint);
                continue;
            }
            if ($type->isBuiltin()) {
                if (!$noBuiltin) {
                    $types[] = $type->getName();
                }
                continue;
            }
            $lcName = strtolower($type->getName());
            $prefix = $noBuiltin ? '' : '\\';
            if ('self' !== $lcName && 'parent' !== $lcName) {
                $types[] = $prefix . $type->getName();
                continue;
            }
            if (!$r instanceof \ReflectionMethod) {
                continue;
            }
            if ('self' === $lcName) {
                $types[] = $prefix . $r->getDeclaringClass()->name;
            } else {
                $types[] = ($parent = $r->getDeclaringClass()->getParentClass()) ? $prefix . $parent->name : null;
            }
        }
        sort($types);
        return $types ? implode($glue, $types) : null;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\DependencyInjection\LazyProxy\PhpDumper;

use _ContaoManager\Symfony\Component\DependencyInjection\Definition;
/**
 * Lazy proxy dumper capable of generating the instantiation logic PHP code for proxied services.
 *
 * @author Marco Pivetta <ocramius@gmail.com>
 */
interface DumperInterface
{
    /**
     * Inspects whether the given definitions should produce proxy instantiation logic in the dumped container.
     *
     * @param bool|null   &$asGhostObject Set to true after the call if the proxy is a ghost object
     * @param string|null $id
     */
    public function isProxyCandidate(Definition $definition): bool;
    /**
     * Generates the code to be used to instantiate a proxy in the dumped factory code.
     */
    public function getProxyFactoryCode(Definition $definition, string $id, string $factoryCode): string;
    /**
     * Generates the code for the lazy proxy.
     *
     * @param string|null $id
     */
    public function getProxyCode(Definition $definition): string;
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\DependencyInjection\LazyProxy\PhpDumper;

use _ContaoManager\Symfony\Component\DependencyInjection\Definition;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
use _ContaoManager\Symfony\Component\VarExporter\Exception\LogicException;
use _ContaoManager\Symfony\Component\VarExporter\ProxyHelper;
/**
 * @author Nicolas Grekas <p@tchwork.com>
 */
final class LazyServiceDumper implements DumperInterface
{
    public function __construct(private string $salt = '')
    {
    }
    public function isProxyCandidate(Definition $definition, ?bool &$asGhostObject = null, ?string $id = null): bool
    {
        $asGhostObject = \false;
        if ($definition->hasTag('proxy')) {
            if (!$definition->isLazy()) {
                throw new InvalidArgumentException(\sprintf('Invalid definition for service "%s": setting the "proxy" tag on a service requires it to be "lazy".', $id ?? $definition->getClass()));
            }
            return \true;
        }
        if (!$definition->isLazy()) {
            return \false;
        }
        if (!($class = $definition->getClass()) || !(class_exists($class) || interface_exists($class, \false))) {
            return \false;
        }
        if ($definition->getFactory()) {
            return \true;
        }
        foreach ($definition->getMethodCalls() as $call) {
            if ($call[2] ?? \false) {
                return \true;
            }
        }
        try {
            $asGhostObject = (bool) ProxyHelper::generateLazyGhost(new \ReflectionClass($class));
        } catch (LogicException) {
        }
        return \true;
    }
    public function getProxyFactoryCode(Definition $definition, string $id, string $factoryCode): string
    {
        $instantiation = 'return';
        if ($definition->isShared()) {
            $instantiation .= \sprintf(' $container->%s[%s] =', $definition->isPublic() && !$definition->isPrivate() ? 'services' : 'privates', var_export($id, \true));
        }
        $asGhostObject = str_contains($factoryCode, '$proxy');
        $proxyClass = $this->getProxyClass($definition, $asGhostObject);
        if (!$asGhostObject) {
            return <<<EOF
        if (true === \$lazyLoad) {
            {$instantiation} \$container->createProxy('{$proxyClass}', static fn () => \\{$proxyClass}::createLazyProxy(static fn () => {$factoryCode}));
        }


EOF;
        }
        $factoryCode = \sprintf('static fn ($proxy) => %s', $factoryCode);
        return <<<EOF
        if (true === \$lazyLoad) {
            {$instantiation} \$container->createProxy('{$proxyClass}', static fn () => \\{$proxyClass}::createLazyGhost({$factoryCode}));
        }


EOF;
    }
    public function getProxyCode(Definition $definition, ?string $id = null): string
    {
        if (!$this->isProxyCandidate($definition, $asGhostObject, $id)) {
            throw new InvalidArgumentException(\sprintf('Cannot instantiate lazy proxy for service "%s".', $id ?? $definition->getClass()));
        }
        $proxyClass = $this->getProxyClass($definition, $asGhostObject, $class);
        if ($asGhostObject) {
            try {
                return (\PHP_VERSION_ID >= 80200 && $class?->isReadOnly() ? 'readonly ' : '') . 'class ' . $proxyClass . ProxyHelper::generateLazyGhost($class);
            } catch (LogicException $e) {
                throw new InvalidArgumentException(\sprintf('Cannot generate lazy ghost for service "%s".', $id ?? $definition->getClass()), 0, $e);
            }
        }
        $interfaces = [];
        if ($definition->hasTag('proxy')) {
            foreach ($definition->getTag('proxy') as $tag) {
                if (!isset($tag['interface'])) {
                    throw new InvalidArgumentException(\sprintf('Invalid definition for service "%s": the "interface" attribute is missing on a "proxy" tag.', $id ?? $definition->getClass()));
                }
                if (!interface_exists($tag['interface']) && !class_exists($tag['interface'], \false)) {
                    throw new InvalidArgumentException(\sprintf('Invalid definition for service "%s": several "proxy" tags found but "%s" is not an interface.', $id ?? $definition->getClass(), $tag['interface']));
                }
                if ('object' !== $definition->getClass() && !is_a($class->name, $tag['interface'], \true)) {
                    throw new InvalidArgumentException(\sprintf('Invalid "proxy" tag for service "%s": class "%s" doesn\'t implement "%s".', $id ?? $definition->getClass(), $definition->getClass(), $tag['interface']));
                }
                $interfaces[] = new \ReflectionClass($tag['interface']);
            }
            $class = 1 === \count($interfaces) && !$interfaces[0]->isInterface() ? array_pop($interfaces) : null;
        } elseif ($class->isInterface()) {
            $interfaces = [$class];
            $class = null;
        }
        try {
            return (\PHP_VERSION_ID >= 80200 && $class?->isReadOnly() ? 'readonly ' : '') . 'class ' . $proxyClass . ProxyHelper::generateLazyProxy($class, $interfaces);
        } catch (LogicException $e) {
            throw new InvalidArgumentException(\sprintf('Cannot generate lazy proxy for service "%s".', $id ?? $definition->getClass()), 0, $e);
        }
    }
    public function getProxyClass(Definition $definition, bool $asGhostObject, ?\ReflectionClass &$class = null): string
    {
        $class = 'object' !== $definition->getClass() ? $definition->getClass() : 'stdClass';
        $class = new \ReflectionClass($class);
        return preg_replace('/^.*\\\\/', '', $definition->getClass()) . ($asGhostObject ? 'Ghost' : 'Proxy') . ucfirst(substr(hash('sha256', $this->salt . '+' . $class->name . '+' . serialize($definition->getTag('proxy'))), -7));
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\DependencyInjection\LazyProxy\PhpDumper;

use _ContaoManager\Symfony\Component\DependencyInjection\Definition;
/**
 * Null dumper, negates any proxy code generation for any given service definition.
 *
 * @author Marco Pivetta <ocramius@gmail.com>
 *
 * @final
 */
class NullDumper implements DumperInterface
{
    public function isProxyCandidate(Definition $definition, ?bool &$asGhostObject = null, ?string $id = null): bool
    {
        return $asGhostObject = \false;
    }
    public function getProxyFactoryCode(Definition $definition, string $id, string $factoryCode): string
    {
        return '';
    }
    public function getProxyCode(Definition $definition, ?string $id = null): string
    {
        return '';
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\DependencyInjection\LazyProxy\Instantiator;

use _ContaoManager\Symfony\Component\DependencyInjection\ContainerInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Definition;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
use _ContaoManager\Symfony\Component\DependencyInjection\LazyProxy\PhpDumper\LazyServiceDumper;
/**
 * @author Nicolas Grekas <p@tchwork.com>
 */
final class LazyServiceInstantiator implements InstantiatorInterface
{
    public function instantiateProxy(ContainerInterface $container, Definition $definition, string $id, callable $realInstantiator): object
    {
        $dumper = new LazyServiceDumper();
        if (!$dumper->isProxyCandidate($definition, $asGhostObject, $id)) {
            throw new InvalidArgumentException(\sprintf('Cannot instantiate lazy proxy for service "%s".', $id));
        }
        if (!class_exists($proxyClass = $dumper->getProxyClass($definition, $asGhostObject), \false)) {
            eval($dumper->getProxyCode($definition, $id));
        }
        return $asGhostObject ? $proxyClass::createLazyGhost($realInstantiator) : $proxyClass::createLazyProxy($realInstantiator);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\DependencyInjection\LazyProxy\Instantiator;

use _ContaoManager\Symfony\Component\DependencyInjection\ContainerInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Definition;
/**
 * Noop proxy instantiator - produces the real service instead of a proxy instance.
 *
 * @author Marco Pivetta <ocramius@gmail.com>
 */
class RealServiceInstantiator implements InstantiatorInterface
{
    public function instantiateProxy(ContainerInterface $container, Definition $definition, string $id, callable $realInstantiator): object
    {
        return $realInstantiator();
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\DependencyInjection\LazyProxy\Instantiator;

use _ContaoManager\Symfony\Component\DependencyInjection\ContainerInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Definition;
/**
 * Lazy proxy instantiator, capable of instantiating a proxy given a container, the
 * service definitions and a callback that produces the real service instance.
 *
 * @author Marco Pivetta <ocramius@gmail.com>
 */
interface InstantiatorInterface
{
    /**
     * Instantiates a proxy object.
     *
     * @param string            $id               Identifier of the requested service
     * @param callable(object=) $realInstantiator A callback that is capable of producing the real service instance
     *
     * @return object
     */
    public function instantiateProxy(ContainerInterface $container, Definition $definition, string $id, callable $realInstantiator);
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\DependencyInjection;

use _ContaoManager\Psr\Cache\CacheItemPoolInterface;
use _ContaoManager\Symfony\Component\ExpressionLanguage\ExpressionLanguage as BaseExpressionLanguage;
if (!class_exists(BaseExpressionLanguage::class)) {
    return;
}
/**
 * Adds some function to the default ExpressionLanguage.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 *
 * @see ExpressionLanguageProvider
 */
class ExpressionLanguage extends BaseExpressionLanguage
{
    public function __construct(?CacheItemPoolInterface $cache = null, array $providers = [], ?callable $serviceCompiler = null, ?\Closure $getEnv = null)
    {
        // prepend the default provider to let users override it easily
        array_unshift($providers, new ExpressionLanguageProvider($serviceCompiler, $getEnv));
        parent::__construct($cache, $providers);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\DependencyInjection;

use _ContaoManager\Psr\Container\ContainerExceptionInterface;
use _ContaoManager\Psr\Container\NotFoundExceptionInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\RuntimeException;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\ServiceCircularReferenceException;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException;
use _ContaoManager\Symfony\Contracts\Service\ServiceLocatorTrait;
use _ContaoManager\Symfony\Contracts\Service\ServiceProviderInterface;
use _ContaoManager\Symfony\Contracts\Service\ServiceSubscriberInterface;
/**
 * @author Robin Chalas <robin.chalas@gmail.com>
 * @author Nicolas Grekas <p@tchwork.com>
 *
 * @template-covariant T of mixed
 *
 * @implements ServiceProviderInterface<T>
 */
class ServiceLocator implements ServiceProviderInterface, \Countable
{
    use ServiceLocatorTrait {
        get as private doGet;
    }
    private ?string $externalId = null;
    private ?Container $container = null;
    public function get(string $id): mixed
    {
        if (!$this->externalId) {
            return $this->doGet($id);
        }
        try {
            return $this->doGet($id);
        } catch (RuntimeException $e) {
            $what = \sprintf('service "%s" required by "%s"', $id, $this->externalId);
            $message = preg_replace('/service "\.service_locator\.[^"]++"/', $what, $e->getMessage());
            if ($e->getMessage() === $message) {
                $message = \sprintf('Cannot resolve %s: %s', $what, $message);
            }
            $r = new \ReflectionProperty($e, 'message');
            $r->setValue($e, $message);
            throw $e;
        }
    }
    /**
     * @return mixed
     */
    public function __invoke(string $id)
    {
        return isset($this->factories[$id]) ? $this->get($id) : null;
    }
    /**
     * @internal
     */
    public function withContext(string $externalId, Container $container): static
    {
        $locator = clone $this;
        $locator->externalId = $externalId;
        $locator->container = $container;
        return $locator;
    }
    public function count(): int
    {
        return \count($this->getProvidedServices());
    }
    private function createNotFoundException(string $id): NotFoundExceptionInterface
    {
        if ($this->loading) {
            $msg = \sprintf('The service "%s" has a dependency on a non-existent service "%s". This locator %s', end($this->loading), $id, $this->formatAlternatives());
            return new ServiceNotFoundException($id, end($this->loading) ?: null, null, [], $msg);
        }
        $class = debug_backtrace(\DEBUG_BACKTRACE_PROVIDE_OBJECT | \DEBUG_BACKTRACE_IGNORE_ARGS, 4);
        $class = isset($class[3]['object']) ? $class[3]['object']::class : null;
        $externalId = $this->externalId ?: $class;
        $msg = [];
        $msg[] = \sprintf('Service "%s" not found:', $id);
        if (!$this->container) {
            $class = null;
        } elseif ($this->container->has($id) || isset($this->container->getRemovedIds()[$id])) {
            $msg[] = 'even though it exists in the app\'s container,';
        } else {
            try {
                $this->container->get($id);
                $class = null;
            } catch (ServiceNotFoundException $e) {
                if ($e->getAlternatives()) {
                    $msg[] = \sprintf('did you mean %s? Anyway,', $this->formatAlternatives($e->getAlternatives(), 'or'));
                } else {
                    $class = null;
                }
            }
        }
        if ($externalId) {
            $msg[] = \sprintf('the container inside "%s" is a smaller service locator that %s', $externalId, $this->formatAlternatives());
        } else {
            $msg[] = \sprintf('the current service locator %s', $this->formatAlternatives());
        }
        if (!$class) {
            // no-op
        } elseif (is_subclass_of($class, ServiceSubscriberInterface::class)) {
            $msg[] = \sprintf('Unless you need extra laziness, try using dependency injection instead. Otherwise, you need to declare it using "%s::getSubscribedServices()".', preg_replace('/([^\\\\]++\\\\)++/', '', $class));
        } else {
            $msg[] = 'Try using dependency injection instead.';
        }
        return new ServiceNotFoundException($id, end($this->loading) ?: null, null, [], implode(' ', $msg));
    }
    private function createCircularReferenceException(string $id, array $path): ContainerExceptionInterface
    {
        return new ServiceCircularReferenceException($id, $path);
    }
    private function formatAlternatives(?array $alternatives = null, string $separator = 'and'): string
    {
        $format = '"%s"%s';
        if (null === $alternatives) {
            if (!$alternatives = array_keys($this->factories)) {
                return 'is empty...';
            }
            $format = \sprintf('only knows about the %s service%s.', $format, 1 < \count($alternatives) ? 's' : '');
        }
        $last = array_pop($alternatives);
        return \sprintf($format, $alternatives ? implode('", "', $alternatives) : $last, $alternatives ? \sprintf(' %s "%s"', $separator, $last) : '');
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\DependencyInjection;

/**
 * Represents a PHP type-hinted service reference.
 *
 * @author Nicolas Grekas <p@tchwork.com>
 */
class TypedReference extends Reference
{
    private string $type;
    private ?string $name;
    private array $attributes;
    /**
     * @param string      $id              The service identifier
     * @param string      $type            The PHP type of the identified service
     * @param int         $invalidBehavior The behavior when the service does not exist
     * @param string|null $name            The name of the argument targeting the service
     * @param array       $attributes      The attributes to be used
     */
    public function __construct(string $id, string $type, int $invalidBehavior = ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE, ?string $name = null, array $attributes = [])
    {
        $this->name = $type === $id ? $name : null;
        parent::__construct($id, $invalidBehavior);
        $this->type = $type;
        $this->attributes = $attributes;
    }
    /**
     * @return string
     */
    public function getType()
    {
        return $this->type;
    }
    public function getName(): ?string
    {
        return $this->name;
    }
    public function getAttributes(): array
    {
        return $this->attributes;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\DependencyInjection;

use _ContaoManager\Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
class Alias
{
    private const DEFAULT_DEPRECATION_TEMPLATE = 'The "%alias_id%" service alias is deprecated. You should stop using it, as it will be removed in the future.';
    private string $id;
    private bool $public;
    private array $deprecation = [];
    public function __construct(string $id, bool $public = \false)
    {
        $this->id = $id;
        $this->public = $public;
    }
    /**
     * Checks if this DI Alias should be public or not.
     */
    public function isPublic(): bool
    {
        return $this->public;
    }
    /**
     * Sets if this Alias is public.
     *
     * @return $this
     */
    public function setPublic(bool $boolean): static
    {
        $this->public = $boolean;
        return $this;
    }
    /**
     * Whether this alias is private.
     */
    public function isPrivate(): bool
    {
        return !$this->public;
    }
    /**
     * Whether this alias is deprecated, that means it should not be referenced
     * anymore.
     *
     * @param string $package The name of the composer package that is triggering the deprecation
     * @param string $version The version of the package that introduced the deprecation
     * @param string $message The deprecation message to use
     *
     * @return $this
     *
     * @throws InvalidArgumentException when the message template is invalid
     */
    public function setDeprecated(string $package, string $version, string $message): static
    {
        if ('' !== $message) {
            if (preg_match('#[\r\n]|\*/#', $message)) {
                throw new InvalidArgumentException('Invalid characters found in deprecation template.');
            }
            if (!str_contains($message, '%alias_id%')) {
                throw new InvalidArgumentException('The deprecation template must contain the "%alias_id%" placeholder.');
            }
        }
        $this->deprecation = ['package' => $package, 'version' => $version, 'message' => $message ?: self::DEFAULT_DEPRECATION_TEMPLATE];
        return $this;
    }
    public function isDeprecated(): bool
    {
        return (bool) $this->deprecation;
    }
    /**
     * @param string $id Service id relying on this definition
     */
    public function getDeprecation(string $id): array
    {
        return ['package' => $this->deprecation['package'], 'version' => $this->deprecation['version'], 'message' => str_replace('%alias_id%', $id, $this->deprecation['message'])];
    }
    public function __toString(): string
    {
        return $this->id;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\DependencyInjection\Exception;

/**
 * This exception is thrown when a circular reference in a parameter is detected.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class ParameterCircularReferenceException extends RuntimeException
{
    private array $parameters;
    public function __construct(array $parameters, ?\Throwable $previous = null)
    {
        parent::__construct(\sprintf('Circular reference detected for parameter "%s" ("%s" > "%s").', $parameters[0], implode('" > "', $parameters), $parameters[0]), 0, $previous);
        $this->parameters = $parameters;
    }
    /**
     * @return array
     */
    public function getParameters()
    {
        return $this->parameters;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\DependencyInjection\Exception;

/**
 * Base LogicException for Dependency Injection component.
 */
class LogicException extends \LogicException implements ExceptionInterface
{
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\DependencyInjection\Exception;

/**
 * This exception is thrown when an environment variable is not found.
 *
 * @author Nicolas Grekas <p@tchwork.com>
 */
class EnvNotFoundException extends InvalidArgumentException
{
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\DependencyInjection\Exception;

use _ContaoManager\Psr\Container\NotFoundExceptionInterface;
/**
 * This exception is thrown when a non-existent parameter is used.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class ParameterNotFoundException extends InvalidArgumentException implements NotFoundExceptionInterface
{
    private string $key;
    private ?string $sourceId;
    private ?string $sourceKey;
    private array $alternatives;
    private ?string $nonNestedAlternative;
    /**
     * @param string          $key                  The requested parameter key
     * @param string|null     $sourceId             The service id that references the non-existent parameter
     * @param string|null     $sourceKey            The parameter key that references the non-existent parameter
     * @param \Throwable|null $previous             The previous exception
     * @param string[]        $alternatives         Some parameter name alternatives
     * @param string|null     $nonNestedAlternative The alternative parameter name when the user expected dot notation for nested parameters
     */
    public function __construct(string $key, ?string $sourceId = null, ?string $sourceKey = null, ?\Throwable $previous = null, array $alternatives = [], ?string $nonNestedAlternative = null)
    {
        $this->key = $key;
        $this->sourceId = $sourceId;
        $this->sourceKey = $sourceKey;
        $this->alternatives = $alternatives;
        $this->nonNestedAlternative = $nonNestedAlternative;
        parent::__construct('', 0, $previous);
        $this->updateRepr();
    }
    /**
     * @return void
     */
    public function updateRepr()
    {
        if (null !== $this->sourceId) {
            $this->message = \sprintf('The service "%s" has a dependency on a non-existent parameter "%s".', $this->sourceId, $this->key);
        } elseif (null !== $this->sourceKey) {
            $this->message = \sprintf('The parameter "%s" has a dependency on a non-existent parameter "%s".', $this->sourceKey, $this->key);
        } elseif ('.' === ($this->key[0] ?? '')) {
            $this->message = \sprintf('Parameter "%s" not found. It was probably deleted during the compilation of the container.', $this->key);
        } else {
            $this->message = \sprintf('You have requested a non-existent parameter "%s".', $this->key);
        }
        if ($this->alternatives) {
            if (1 == \count($this->alternatives)) {
                $this->message .= ' Did you mean this: "';
            } else {
                $this->message .= ' Did you mean one of these: "';
            }
            $this->message .= implode('", "', $this->alternatives) . '"?';
        } elseif (null !== $this->nonNestedAlternative) {
            $this->message .= ' You cannot access nested array items, do you want to inject "' . $this->nonNestedAlternative . '" instead?';
        }
    }
    /**
     * @return string
     */
    public function getKey()
    {
        return $this->key;
    }
    /**
     * @return string|null
     */
    public function getSourceId()
    {
        return $this->sourceId;
    }
    /**
     * @return string|null
     */
    public function getSourceKey()
    {
        return $this->sourceKey;
    }
    /**
     * @return void
     */
    public function setSourceId(?string $sourceId)
    {
        $this->sourceId = $sourceId;
        $this->updateRepr();
    }
    /**
     * @return void
     */
    public function setSourceKey(?string $sourceKey)
    {
        $this->sourceKey = $sourceKey;
        $this->updateRepr();
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\DependencyInjection\Exception;

use _ContaoManager\Psr\Container\ContainerExceptionInterface;
/**
 * Base ExceptionInterface for Dependency Injection component.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 * @author Bulat Shakirzyanov <bulat@theopenskyproject.com>
 */
interface ExceptionInterface extends ContainerExceptionInterface, \Throwable
{
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\DependencyInjection\Exception;

/**
 * Base OutOfBoundsException for Dependency Injection component.
 */
class OutOfBoundsException extends \OutOfBoundsException implements ExceptionInterface
{
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\DependencyInjection\Exception;

/**
 * This exception is thrown when a circular reference is detected.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
class ServiceCircularReferenceException extends RuntimeException
{
    private string $serviceId;
    private array $path;
    public function __construct(string $serviceId, array $path, ?\Throwable $previous = null)
    {
        parent::__construct(\sprintf('Circular reference detected for service "%s", path: "%s".', $serviceId, implode(' -> ', $path)), 0, $previous);
        $this->serviceId = $serviceId;
        $this->path = $path;
    }
    /**
     * @return string
     */
    public function getServiceId()
    {
        return $this->serviceId;
    }
    /**
     * @return array
     */
    public function getPath()
    {
        return $this->path;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\DependencyInjection\Exception;

use _ContaoManager\Psr\Container\NotFoundExceptionInterface;
/**
 * This exception is thrown when a non-existent service is requested.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
class ServiceNotFoundException extends InvalidArgumentException implements NotFoundExceptionInterface
{
    private string $id;
    private ?string $sourceId;
    private array $alternatives;
    public function __construct(string $id, ?string $sourceId = null, ?\Throwable $previous = null, array $alternatives = [], ?string $msg = null)
    {
        if (null !== $msg) {
            // no-op
        } elseif (null === $sourceId) {
            $msg = \sprintf('You have requested a non-existent service "%s".', $id);
        } else {
            $msg = \sprintf('The service "%s" has a dependency on a non-existent service "%s".', $sourceId, $id);
        }
        if ($alternatives) {
            if (1 == \count($alternatives)) {
                $msg .= ' Did you mean this: "';
            } else {
                $msg .= ' Did you mean one of these: "';
            }
            $msg .= implode('", "', $alternatives) . '"?';
        }
        parent::__construct($msg, 0, $previous);
        $this->id = $id;
        $this->sourceId = $sourceId;
        $this->alternatives = $alternatives;
    }
    /**
     * @return string
     */
    public function getId()
    {
        return $this->id;
    }
    /**
     * @return string|null
     */
    public function getSourceId()
    {
        return $this->sourceId;
    }
    /**
     * @return array
     */
    public function getAlternatives()
    {
        return $this->alternatives;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\DependencyInjection\Exception;

/**
 * Base RuntimeException for Dependency Injection component.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
class RuntimeException extends \RuntimeException implements ExceptionInterface
{
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\DependencyInjection\Exception;

/**
 * Base InvalidArgumentException for Dependency Injection component.
 *
 * @author Bulat Shakirzyanov <bulat@theopenskyproject.com>
 */
class InvalidArgumentException extends \InvalidArgumentException implements ExceptionInterface
{
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\DependencyInjection\Exception;

/**
 * Base BadMethodCallException for Dependency Injection component.
 */
class BadMethodCallException extends \BadMethodCallException implements ExceptionInterface
{
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\DependencyInjection\Exception;

/**
 * Thrown when a definition cannot be autowired.
 */
class AutowiringFailedException extends RuntimeException
{
    private string $serviceId;
    private ?\Closure $messageCallback = null;
    public function __construct(string $serviceId, string|\Closure $message = '', int $code = 0, ?\Throwable $previous = null)
    {
        $this->serviceId = $serviceId;
        if ($message instanceof \Closure && \function_exists('xdebug_is_enabled') && xdebug_is_enabled()) {
            $message = $message();
        }
        if (!$message instanceof \Closure) {
            parent::__construct($message, $code, $previous);
            return;
        }
        $this->messageCallback = $message;
        parent::__construct('', $code, $previous);
        $this->message = new class($this->message, $this->messageCallback)
        {
            private string|self $message;
            private ?\Closure $messageCallback;
            public function __construct(&$message, &$messageCallback)
            {
                $this->message =& $message;
                $this->messageCallback =& $messageCallback;
            }
            public function __toString(): string
            {
                $messageCallback = $this->messageCallback;
                $this->messageCallback = null;
                try {
                    return $this->message = $messageCallback();
                } catch (\Throwable $e) {
                    return $this->message = $e->getMessage();
                }
            }
        };
    }
    public function getMessageCallback(): ?\Closure
    {
        return $this->messageCallback;
    }
    /**
     * @return string
     */
    public function getServiceId()
    {
        return $this->serviceId;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\DependencyInjection\Exception;

/**
 * Thrown when trying to inject a parameter into a constructor/method with an incompatible type.
 *
 * @author Nicolas Grekas <p@tchwork.com>
 * @author Julien Maulny <jmaulny@darkmira.fr>
 */
class InvalidParameterTypeException extends InvalidArgumentException
{
    public function __construct(string $serviceId, string $type, \ReflectionParameter $parameter)
    {
        $acceptedType = $parameter->getType();
        $acceptedType = $acceptedType instanceof \ReflectionNamedType ? $acceptedType->getName() : (string) $acceptedType;
        $this->code = $type;
        $function = $parameter->getDeclaringFunction();
        $functionName = $function instanceof \ReflectionMethod ? \sprintf('%s::%s', $function->getDeclaringClass()->getName(), $function->getName()) : $function->getName();
        parent::__construct(\sprintf('Invalid definition for service "%s": argument %d of "%s()" accepts "%s", "%s" passed.', $serviceId, 1 + $parameter->getPosition(), $functionName, $acceptedType, $type));
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\DependencyInjection\Exception;

/**
 * This exception wraps exceptions whose messages contain a reference to an env parameter.
 *
 * @author Nicolas Grekas <p@tchwork.com>
 */
class EnvParameterException extends InvalidArgumentException
{
    public function __construct(array $envs, ?\Throwable $previous = null, string $message = 'Incompatible use of dynamic environment variables "%s" found in parameters.')
    {
        parent::__construct(\sprintf($message, implode('", "', $envs)), 0, $previous);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\DependencyInjection;

/**
 * TaggedContainerInterface is the interface implemented when a container knows how to deals with tags.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
interface TaggedContainerInterface extends ContainerInterface
{
    /**
     * Returns service ids for a given tag.
     *
     * @param string $name The tag name
     */
    public function findTaggedServiceIds(string $name): array;
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\DependencyInjection;

/**
 * Parameter represents a parameter reference.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class Parameter
{
    private string $id;
    public function __construct(string $id)
    {
        $this->id = $id;
    }
    public function __toString(): string
    {
        return $this->id;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\DependencyInjection\Compiler;

use _ContaoManager\Symfony\Component\DependencyInjection\Alias;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerBuilder;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException;
use _ContaoManager\Symfony\Component\DependencyInjection\Reference;
/**
 * Overwrites a service but keeps the overridden one.
 *
 * @author Christophe Coevoet <stof@notk.org>
 * @author Fabien Potencier <fabien@symfony.com>
 * @author Diego Saint Esteben <diego@saintesteben.me>
 */
class DecoratorServicePass extends AbstractRecursivePass
{
    protected bool $skipScalars = \true;
    /**
     * @return void
     */
    public function process(ContainerBuilder $container)
    {
        $definitions = new \SplPriorityQueue();
        $order = \PHP_INT_MAX;
        foreach ($container->getDefinitions() as $id => $definition) {
            if (!$decorated = $definition->getDecoratedService()) {
                continue;
            }
            $definitions->insert([$id, $definition], [$decorated[2], --$order]);
        }
        $decoratingDefinitions = [];
        $decoratedIds = [];
        $tagsToKeep = $container->hasParameter('container.behavior_describing_tags') ? $container->getParameter('container.behavior_describing_tags') : ['proxy', 'container.do_not_inline', 'container.service_locator', 'container.service_subscriber', 'container.service_subscriber.locator'];
        foreach ($definitions as [$id, $definition]) {
            $decoratedService = $definition->getDecoratedService();
            [$inner, $renamedId] = $decoratedService;
            $invalidBehavior = $decoratedService[3] ?? ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE;
            $definition->setDecoratedService(null);
            if (!$renamedId) {
                $renamedId = $id . '.inner';
            }
            $decoratedIds[$inner] ??= $renamedId;
            $this->currentId = $renamedId;
            $this->processValue($definition);
            $definition->innerServiceId = $renamedId;
            $definition->decorationOnInvalid = $invalidBehavior;
            // we create a new alias/service for the service we are replacing
            // to be able to reference it in the new one
            if ($container->hasAlias($inner)) {
                $alias = $container->getAlias($inner);
                $public = $alias->isPublic();
                $container->setAlias($renamedId, new Alias((string) $alias, \false));
                $decoratedDefinition = $container->findDefinition($alias);
            } elseif ($container->hasDefinition($inner)) {
                $decoratedDefinition = $container->getDefinition($inner);
                $public = $decoratedDefinition->isPublic();
                $decoratedDefinition->setPublic(\false);
                $container->setDefinition($renamedId, $decoratedDefinition);
                $decoratingDefinitions[$inner] = $decoratedDefinition;
            } elseif (ContainerInterface::IGNORE_ON_INVALID_REFERENCE === $invalidBehavior) {
                $container->removeDefinition($id);
                continue;
            } elseif (ContainerInterface::NULL_ON_INVALID_REFERENCE === $invalidBehavior) {
                $public = $definition->isPublic();
                $decoratedDefinition = null;
            } else {
                throw new ServiceNotFoundException($inner, $id);
            }
            if ($decoratedDefinition?->isSynthetic()) {
                throw new InvalidArgumentException(\sprintf('A synthetic service cannot be decorated: service "%s" cannot decorate "%s".', $id, $inner));
            }
            if (isset($decoratingDefinitions[$inner])) {
                $decoratingDefinition = $decoratingDefinitions[$inner];
                $decoratingTags = $decoratingDefinition->getTags();
                $resetTags = [];
                // Behavior-describing tags must not be transferred out to decorators
                foreach ($tagsToKeep as $containerTag) {
                    if (isset($decoratingTags[$containerTag])) {
                        $resetTags[$containerTag] = $decoratingTags[$containerTag];
                        unset($decoratingTags[$containerTag]);
                    }
                }
                $definition->setTags(array_merge($decoratingTags, $definition->getTags()));
                $decoratingDefinition->setTags($resetTags);
                $decoratingDefinitions[$inner] = $definition;
            }
            $container->setAlias($inner, $id)->setPublic($public);
        }
        foreach ($decoratingDefinitions as $inner => $definition) {
            $definition->addTag('container.decorator', ['id' => $inner, 'inner' => $decoratedIds[$inner]]);
        }
    }
    protected function processValue(mixed $value, bool $isRoot = \false): mixed
    {
        if ($value instanceof Reference && '.inner' === (string) $value) {
            return new Reference($this->currentId, $value->getInvalidBehavior());
        }
        return parent::processValue($value, $isRoot);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\DependencyInjection\Compiler;

use _ContaoManager\Symfony\Component\DependencyInjection\Argument\ArgumentInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Argument\ServiceClosureArgument;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerBuilder;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Definition;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\RuntimeException;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException;
use _ContaoManager\Symfony\Component\DependencyInjection\Reference;
use _ContaoManager\Symfony\Component\DependencyInjection\TypedReference;
/**
 * Emulates the invalid behavior if the reference is not found within the
 * container.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
class ResolveInvalidReferencesPass implements CompilerPassInterface
{
    private ContainerBuilder $container;
    private RuntimeException $signalingException;
    private string $currentId;
    /**
     * Process the ContainerBuilder to resolve invalid references.
     *
     * @return void
     */
    public function process(ContainerBuilder $container)
    {
        $this->container = $container;
        $this->signalingException = new RuntimeException('Invalid reference.');
        try {
            foreach ($container->getDefinitions() as $this->currentId => $definition) {
                $this->processValue($definition);
            }
        } finally {
            unset($this->container, $this->signalingException);
        }
    }
    /**
     * Processes arguments to determine invalid references.
     *
     * @throws RuntimeException When an invalid reference is found
     */
    private function processValue(mixed $value, int $rootLevel = 0, int $level = 0): mixed
    {
        if ($value instanceof ServiceClosureArgument) {
            $value->setValues($this->processValue($value->getValues(), 1, 1));
        } elseif ($value instanceof ArgumentInterface) {
            $value->setValues($this->processValue($value->getValues(), $rootLevel, 1 + $level));
        } elseif ($value instanceof Definition) {
            if ($value->isSynthetic() || $value->isAbstract()) {
                return $value;
            }
            $value->setArguments($this->processValue($value->getArguments(), 0));
            $value->setProperties($this->processValue($value->getProperties(), 1));
            $value->setMethodCalls($this->processValue($value->getMethodCalls(), 2));
        } elseif (\is_array($value)) {
            $i = 0;
            foreach ($value as $k => $v) {
                try {
                    if (\false !== $i && $k !== $i++) {
                        $i = \false;
                    }
                    if ($v !== $processedValue = $this->processValue($v, $rootLevel, 1 + $level)) {
                        $value[$k] = $processedValue;
                    }
                } catch (RuntimeException $e) {
                    if ($rootLevel < $level || $rootLevel && !$level) {
                        unset($value[$k]);
                    } elseif ($rootLevel) {
                        throw $e;
                    } else {
                        $value[$k] = null;
                    }
                }
            }
            // Ensure numerically indexed arguments have sequential numeric keys.
            if (\false !== $i) {
                $value = array_values($value);
            }
        } elseif ($value instanceof Reference) {
            if ($this->container->hasDefinition($id = (string) $value) ? !$this->container->getDefinition($id)->hasTag('container.excluded') : $this->container->hasAlias($id)) {
                return $value;
            }
            $currentDefinition = $this->container->getDefinition($this->currentId);
            // resolve decorated service behavior depending on decorator service
            if ($currentDefinition->innerServiceId === $id && ContainerInterface::NULL_ON_INVALID_REFERENCE === $currentDefinition->decorationOnInvalid) {
                return null;
            }
            $invalidBehavior = $value->getInvalidBehavior();
            if (ContainerInterface::RUNTIME_EXCEPTION_ON_INVALID_REFERENCE === $invalidBehavior && $value instanceof TypedReference && !$this->container->has($id)) {
                $e = new ServiceNotFoundException($id, $this->currentId);
                // since the error message varies by $id and $this->currentId, so should the id of the dummy errored definition
                $this->container->register($id = \sprintf('.errored.%s.%s', $this->currentId, $id), $value->getType())->addError($e->getMessage());
                return new TypedReference($id, $value->getType(), $value->getInvalidBehavior());
            }
            // resolve invalid behavior
            if (ContainerInterface::NULL_ON_INVALID_REFERENCE === $invalidBehavior) {
                $value = null;
            } elseif (ContainerInterface::IGNORE_ON_INVALID_REFERENCE === $invalidBehavior) {
                if (0 < $level || $rootLevel) {
                    throw $this->signalingException;
                }
                $value = null;
            }
        }
        return $value;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\DependencyInjection\Compiler;

use _ContaoManager\Symfony\Component\Config\Definition\BaseNode;
use _ContaoManager\Symfony\Component\Config\Definition\ConfigurationInterface;
use _ContaoManager\Symfony\Component\Config\Definition\Processor;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerBuilder;
use _ContaoManager\Symfony\Component\DependencyInjection\Extension\ConfigurationExtensionInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\ParameterBag\EnvPlaceholderParameterBag;
use _ContaoManager\Symfony\Component\DependencyInjection\ParameterBag\ParameterBag;
/**
 * Validates environment variable placeholders used in extension configuration with dummy values.
 *
 * @author Roland Franssen <franssen.roland@gmail.com>
 */
class ValidateEnvPlaceholdersPass implements CompilerPassInterface
{
    private const TYPE_FIXTURES = ['array' => [], 'bool' => \false, 'float' => 0.0, 'int' => 0, 'string' => ''];
    private array $extensionConfig = [];
    /**
     * @return void
     */
    public function process(ContainerBuilder $container)
    {
        $this->extensionConfig = [];
        if (!class_exists(BaseNode::class) || !$extensions = $container->getExtensions()) {
            return;
        }
        $resolvingBag = $container->getParameterBag();
        if (!$resolvingBag instanceof EnvPlaceholderParameterBag) {
            return;
        }
        $defaultBag = new ParameterBag($resolvingBag->all());
        $envTypes = $resolvingBag->getProvidedTypes();
        foreach ($resolvingBag->getEnvPlaceholders() + $resolvingBag->getUnusedEnvPlaceholders() as $env => $placeholders) {
            $values = $this->getPlaceholderValues($env, $defaultBag, $envTypes);
            foreach ($placeholders as $placeholder) {
                BaseNode::setPlaceholder($placeholder, $values);
            }
        }
        $processor = new Processor();
        foreach ($extensions as $name => $extension) {
            if (!($extension instanceof ConfigurationExtensionInterface || $extension instanceof ConfigurationInterface) || !$config = array_filter($container->getExtensionConfig($name))) {
                // this extension has no semantic configuration or was not called
                continue;
            }
            $config = $resolvingBag->resolveValue($config);
            if ($extension instanceof ConfigurationInterface) {
                $configuration = $extension;
            } elseif (null === $configuration = $extension->getConfiguration($config, $container)) {
                continue;
            }
            $this->extensionConfig[$name] = $processor->processConfiguration($configuration, $config);
        }
        $resolvingBag->clearUnusedEnvPlaceholders();
    }
    /**
     * @internal
     */
    public function getExtensionConfig(): array
    {
        try {
            return $this->extensionConfig;
        } finally {
            $this->extensionConfig = [];
        }
    }
    /**
     * @param array<string, list<string>> $envTypes
     *
     * @return array<string, mixed>
     */
    private function getPlaceholderValues(string $env, ParameterBag $defaultBag, array $envTypes): array
    {
        if (\false === $i = strpos($env, ':')) {
            [$default, $defaultType] = $this->getParameterDefaultAndDefaultType("env({$env})", $defaultBag);
            return [$defaultType => $default];
        }
        $prefix = substr($env, 0, $i);
        if ('default' === $prefix) {
            $parts = explode(':', $env);
            array_shift($parts);
            // Remove 'default' prefix
            $parameter = array_shift($parts);
            // Retrieve and remove parameter
            [$defaultParameter, $defaultParameterType] = $this->getParameterDefaultAndDefaultType($parameter, $defaultBag);
            return [$defaultParameterType => $defaultParameter, ...$this->getPlaceholderValues(implode(':', $parts), $defaultBag, $envTypes)];
        }
        $values = [];
        foreach ($envTypes[$prefix] ?? ['string'] as $type) {
            $values[$type] = self::TYPE_FIXTURES[$type] ?? null;
        }
        return $values;
    }
    /**
     * @return array{0: string, 1: string}
     */
    private function getParameterDefaultAndDefaultType(string $name, ParameterBag $defaultBag): array
    {
        $default = $defaultBag->has($name) ? $defaultBag->get($name) : self::TYPE_FIXTURES['string'];
        $defaultType = null !== $default ? get_debug_type($default) : 'string';
        return [$default, $defaultType];
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\DependencyInjection\Compiler;

use _ContaoManager\Symfony\Component\DependencyInjection\ContainerBuilder;
use _ContaoManager\Symfony\Component\DependencyInjection\EnvVarProcessor;
use _ContaoManager\Symfony\Component\DependencyInjection\EnvVarProcessorInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
use _ContaoManager\Symfony\Component\DependencyInjection\ParameterBag\EnvPlaceholderParameterBag;
use _ContaoManager\Symfony\Component\DependencyInjection\Reference;
/**
 * Creates the container.env_var_processors_locator service.
 *
 * @author Nicolas Grekas <p@tchwork.com>
 */
class RegisterEnvVarProcessorsPass implements CompilerPassInterface
{
    private const ALLOWED_TYPES = ['array', 'bool', 'float', 'int', 'string', \BackedEnum::class];
    /**
     * @return void
     */
    public function process(ContainerBuilder $container)
    {
        $bag = $container->getParameterBag();
        $types = [];
        $processors = [];
        foreach ($container->findTaggedServiceIds('container.env_var_processor') as $id => $tags) {
            if (!$r = $container->getReflectionClass($class = $container->getDefinition($id)->getClass())) {
                throw new InvalidArgumentException(\sprintf('Class "%s" used for service "%s" cannot be found.', $class, $id));
            } elseif (!$r->isSubclassOf(EnvVarProcessorInterface::class)) {
                throw new InvalidArgumentException(\sprintf('Service "%s" must implement interface "%s".', $id, EnvVarProcessorInterface::class));
            }
            foreach ($class::getProvidedTypes() as $prefix => $type) {
                $processors[$prefix] = new Reference($id);
                $types[$prefix] = self::validateProvidedTypes($type, $class);
            }
        }
        if ($bag instanceof EnvPlaceholderParameterBag) {
            foreach (EnvVarProcessor::getProvidedTypes() as $prefix => $type) {
                if (!isset($types[$prefix])) {
                    $types[$prefix] = self::validateProvidedTypes($type, EnvVarProcessor::class);
                }
            }
            $bag->setProvidedTypes($types);
        }
        if ($processors) {
            $container->setAlias('container.env_var_processors_locator', (string) ServiceLocatorTagPass::register($container, $processors))->setPublic(\true);
        }
    }
    private static function validateProvidedTypes(string $types, string $class): array
    {
        $types = explode('|', $types);
        foreach ($types as $type) {
            if (!\in_array($type, self::ALLOWED_TYPES)) {
                throw new InvalidArgumentException(\sprintf('Invalid type "%s" returned by "%s::getProvidedTypes()", expected one of "%s".', $type, $class, implode('", "', self::ALLOWED_TYPES)));
            }
        }
        return $types;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\DependencyInjection\Compiler;

use _ContaoManager\Symfony\Component\DependencyInjection\Attribute\Autoconfigure;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerBuilder;
use _ContaoManager\Symfony\Component\DependencyInjection\Definition;
use _ContaoManager\Symfony\Component\DependencyInjection\Loader\YamlFileLoader;
/**
 * Reads #[Autoconfigure] attributes on definitions that are autoconfigured
 * and don't have the "container.ignore_attributes" tag.
 *
 * @author Nicolas Grekas <p@tchwork.com>
 */
final class RegisterAutoconfigureAttributesPass implements CompilerPassInterface
{
    private static \Closure $registerForAutoconfiguration;
    public function process(ContainerBuilder $container): void
    {
        foreach ($container->getDefinitions() as $id => $definition) {
            if ($this->accept($definition) && $class = $container->getReflectionClass($definition->getClass(), \false)) {
                $this->processClass($container, $class);
            }
        }
    }
    public function accept(Definition $definition): bool
    {
        return $definition->isAutoconfigured() && !$definition->hasTag('container.ignore_attributes');
    }
    public function processClass(ContainerBuilder $container, \ReflectionClass $class): void
    {
        foreach ($class->getAttributes(Autoconfigure::class, \ReflectionAttribute::IS_INSTANCEOF) as $attribute) {
            self::registerForAutoconfiguration($container, $class, $attribute);
        }
    }
    private static function registerForAutoconfiguration(ContainerBuilder $container, \ReflectionClass $class, \ReflectionAttribute $attribute): void
    {
        if (isset(self::$registerForAutoconfiguration)) {
            (self::$registerForAutoconfiguration)($container, $class, $attribute);
            return;
        }
        $parseDefinitions = new \ReflectionMethod(YamlFileLoader::class, 'parseDefinitions');
        $yamlLoader = $parseDefinitions->getDeclaringClass()->newInstanceWithoutConstructor();
        self::$registerForAutoconfiguration = static function (ContainerBuilder $container, \ReflectionClass $class, \ReflectionAttribute $attribute) use ($parseDefinitions, $yamlLoader) {
            $attribute = (array) $attribute->newInstance();
            foreach ($attribute['tags'] ?? [] as $i => $tag) {
                if (\is_array($tag) && [0] === array_keys($tag)) {
                    $attribute['tags'][$i] = [$class->name => $tag[0]];
                }
            }
            $parseDefinitions->invoke($yamlLoader, ['services' => ['_instanceof' => [$class->name => [$container->registerForAutoconfiguration($class->name)] + $attribute]]], $class->getFileName(), \false);
        };
        (self::$registerForAutoconfiguration)($container, $class, $attribute);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\DependencyInjection\Compiler;

use _ContaoManager\Symfony\Component\DependencyInjection\ContainerBuilder;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\EnvParameterException;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\RuntimeException;
use _ContaoManager\Symfony\Component\DependencyInjection\Loader\FileLoader;
/**
 * This pass validates each definition individually only taking the information
 * into account which is contained in the definition itself.
 *
 * Later passes can rely on the following, and specifically do not need to
 * perform these checks themselves:
 *
 * - non synthetic, non abstract services always have a class set
 * - synthetic services are always public
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
class CheckDefinitionValidityPass implements CompilerPassInterface
{
    /**
     * Processes the ContainerBuilder to validate the Definition.
     *
     * @return void
     *
     * @throws RuntimeException When the Definition is invalid
     */
    public function process(ContainerBuilder $container)
    {
        foreach ($container->getDefinitions() as $id => $definition) {
            if ($definition->hasErrors()) {
                continue;
            }
            // synthetic service is public
            if ($definition->isSynthetic() && !$definition->isPublic()) {
                throw new RuntimeException(\sprintf('A synthetic service ("%s") must be public.', $id));
            }
            // non-synthetic, non-abstract service has class
            if (!$definition->isAbstract() && !$definition->isSynthetic() && !$definition->getClass() && !$definition->hasTag('container.service_locator') && (!$definition->getFactory() || !preg_match(FileLoader::ANONYMOUS_ID_REGEXP, $id))) {
                if ($definition->getFactory()) {
                    throw new RuntimeException(\sprintf('Please add the class to service "%s" even if it is constructed by a factory since we might need to add method calls based on compile-time checks.', $id));
                }
                if (class_exists($id) || interface_exists($id, \false)) {
                    if (str_starts_with($id, '\\') && 1 < substr_count($id, '\\')) {
                        throw new RuntimeException(\sprintf('The definition for "%s" has no class attribute, and appears to reference a class or interface. Please specify the class attribute explicitly or remove the leading backslash by renaming the service to "%s" to get rid of this error.', $id, substr($id, 1)));
                    }
                    throw new RuntimeException(\sprintf('The definition for "%s" has no class attribute, and appears to reference a class or interface in the global namespace. Leaving out the "class" attribute is only allowed for namespaced classes. Please specify the class attribute explicitly to get rid of this error.', $id));
                }
                throw new RuntimeException(\sprintf('The definition for "%s" has no class. If you intend to inject this service dynamically at runtime, please mark it as synthetic=true. If this is an abstract definition solely used by child definitions, please add abstract=true, otherwise specify a class to get rid of this error.', $id));
            }
            // tag attribute values must be scalars
            foreach ($definition->getTags() as $name => $tags) {
                foreach ($tags as $attributes) {
                    $this->validateAttributes($id, $name, $attributes);
                }
            }
            if ($definition->isPublic() && !$definition->isPrivate()) {
                $resolvedId = $container->resolveEnvPlaceholders($id, null, $usedEnvs);
                if (null !== $usedEnvs) {
                    throw new EnvParameterException([$resolvedId], null, 'A service name ("%s") cannot contain dynamic values.');
                }
            }
        }
        foreach ($container->getAliases() as $id => $alias) {
            if ($alias->isPublic() && !$alias->isPrivate()) {
                $resolvedId = $container->resolveEnvPlaceholders($id, null, $usedEnvs);
                if (null !== $usedEnvs) {
                    throw new EnvParameterException([$resolvedId], null, 'An alias name ("%s") cannot contain dynamic values.');
                }
            }
        }
    }
    private function validateAttributes(string $id, string $tag, array $attributes, array $path = []): void
    {
        foreach ($attributes as $name => $value) {
            if (\is_array($value)) {
                $this->validateAttributes($id, $tag, $value, [...$path, $name]);
            } elseif (!\is_scalar($value) && null !== $value) {
                $name = implode('.', [...$path, $name]);
                throw new RuntimeException(\sprintf('A "tags" attribute must be of a scalar-type for service "%s", tag "%s", attribute "%s".', $id, $tag, $name));
            }
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\DependencyInjection\Compiler;

use _ContaoManager\Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
/**
 * Compiler Pass Configuration.
 *
 * This class has a default configuration embedded.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
class PassConfig
{
    public const TYPE_AFTER_REMOVING = 'afterRemoving';
    public const TYPE_BEFORE_OPTIMIZATION = 'beforeOptimization';
    public const TYPE_BEFORE_REMOVING = 'beforeRemoving';
    public const TYPE_OPTIMIZE = 'optimization';
    public const TYPE_REMOVE = 'removing';
    private MergeExtensionConfigurationPass $mergePass;
    private array $afterRemovingPasses;
    private array $beforeOptimizationPasses;
    private array $beforeRemovingPasses = [];
    private array $optimizationPasses;
    private array $removingPasses;
    public function __construct()
    {
        $this->mergePass = new MergeExtensionConfigurationPass();
        $this->beforeOptimizationPasses = [100 => [new ResolveClassPass(), new RegisterAutoconfigureAttributesPass(), new AutowireAsDecoratorPass(), new AttributeAutoconfigurationPass(), new ResolveInstanceofConditionalsPass(), new RegisterEnvVarProcessorsPass()], -1000 => [new ExtensionCompilerPass()]];
        $this->optimizationPasses = [[new AutoAliasServicePass(), new ValidateEnvPlaceholdersPass(), new ResolveDecoratorStackPass(), new ResolveChildDefinitionsPass(), new RegisterServiceSubscribersPass(), new ResolveParameterPlaceHoldersPass(\false, \false), new ResolveFactoryClassPass(), new ResolveNamedArgumentsPass(), new AutowireRequiredMethodsPass(), new AutowireRequiredPropertiesPass(), new ResolveBindingsPass(), new ServiceLocatorTagPass(), new DecoratorServicePass(), new CheckDefinitionValidityPass(), new AutowirePass(\false), new ServiceLocatorTagPass(), new ResolveTaggedIteratorArgumentPass(), new ResolveServiceSubscribersPass(), new ResolveReferencesToAliasesPass(), new ResolveInvalidReferencesPass(), new AnalyzeServiceReferencesPass(\true), new CheckCircularReferencesPass(), new CheckReferenceValidityPass(), new CheckArgumentsValidityPass(\false)]];
        $this->removingPasses = [[new RemovePrivateAliasesPass(), new ReplaceAliasByActualDefinitionPass(), new RemoveAbstractDefinitionsPass(), new RemoveUnusedDefinitionsPass(), new AnalyzeServiceReferencesPass(), new CheckExceptionOnInvalidReferenceBehaviorPass(), new InlineServiceDefinitionsPass(new AnalyzeServiceReferencesPass()), new AnalyzeServiceReferencesPass(), new DefinitionErrorExceptionPass()]];
        $this->afterRemovingPasses = [
            0 => [new ResolveHotPathPass(), new ResolveNoPreloadPass(), new AliasDeprecatedPublicServicesPass()],
            // Let build parameters be available as late as possible
            // Don't remove array parameters since ResolveParameterPlaceHoldersPass doesn't resolve them
            -2048 => [new RemoveBuildParametersPass(\true)],
        ];
    }
    /**
     * Returns all passes in order to be processed.
     *
     * @return CompilerPassInterface[]
     */
    public function getPasses(): array
    {
        return array_merge([$this->mergePass], $this->getBeforeOptimizationPasses(), $this->getOptimizationPasses(), $this->getBeforeRemovingPasses(), $this->getRemovingPasses(), $this->getAfterRemovingPasses());
    }
    /**
     * Adds a pass.
     *
     * @return void
     *
     * @throws InvalidArgumentException when a pass type doesn't exist
     */
    public function addPass(CompilerPassInterface $pass, string $type = self::TYPE_BEFORE_OPTIMIZATION, int $priority = 0)
    {
        $property = $type . 'Passes';
        if (!isset($this->{$property})) {
            throw new InvalidArgumentException(\sprintf('Invalid type "%s".', $type));
        }
        $passes =& $this->{$property};
        if (!isset($passes[$priority])) {
            $passes[$priority] = [];
        }
        $passes[$priority][] = $pass;
    }
    /**
     * Gets all passes for the AfterRemoving pass.
     *
     * @return CompilerPassInterface[]
     */
    public function getAfterRemovingPasses(): array
    {
        return $this->sortPasses($this->afterRemovingPasses);
    }
    /**
     * Gets all passes for the BeforeOptimization pass.
     *
     * @return CompilerPassInterface[]
     */
    public function getBeforeOptimizationPasses(): array
    {
        return $this->sortPasses($this->beforeOptimizationPasses);
    }
    /**
     * Gets all passes for the BeforeRemoving pass.
     *
     * @return CompilerPassInterface[]
     */
    public function getBeforeRemovingPasses(): array
    {
        return $this->sortPasses($this->beforeRemovingPasses);
    }
    /**
     * Gets all passes for the Optimization pass.
     *
     * @return CompilerPassInterface[]
     */
    public function getOptimizationPasses(): array
    {
        return $this->sortPasses($this->optimizationPasses);
    }
    /**
     * Gets all passes for the Removing pass.
     *
     * @return CompilerPassInterface[]
     */
    public function getRemovingPasses(): array
    {
        return $this->sortPasses($this->removingPasses);
    }
    /**
     * Gets the Merge pass.
     */
    public function getMergePass(): CompilerPassInterface
    {
        return $this->mergePass;
    }
    /**
     * @return void
     */
    public function setMergePass(CompilerPassInterface $pass)
    {
        $this->mergePass = $pass;
    }
    /**
     * Sets the AfterRemoving passes.
     *
     * @param CompilerPassInterface[] $passes
     *
     * @return void
     */
    public function setAfterRemovingPasses(array $passes)
    {
        $this->afterRemovingPasses = [$passes];
    }
    /**
     * Sets the BeforeOptimization passes.
     *
     * @param CompilerPassInterface[] $passes
     *
     * @return void
     */
    public function setBeforeOptimizationPasses(array $passes)
    {
        $this->beforeOptimizationPasses = [$passes];
    }
    /**
     * Sets the BeforeRemoving passes.
     *
     * @param CompilerPassInterface[] $passes
     *
     * @return void
     */
    public function setBeforeRemovingPasses(array $passes)
    {
        $this->beforeRemovingPasses = [$passes];
    }
    /**
     * Sets the Optimization passes.
     *
     * @param CompilerPassInterface[] $passes
     *
     * @return void
     */
    public function setOptimizationPasses(array $passes)
    {
        $this->optimizationPasses = [$passes];
    }
    /**
     * Sets the Removing passes.
     *
     * @param CompilerPassInterface[] $passes
     *
     * @return void
     */
    public function setRemovingPasses(array $passes)
    {
        $this->removingPasses = [$passes];
    }
    /**
     * Sort passes by priority.
     *
     * @param array $passes CompilerPassInterface instances with their priority as key
     *
     * @return CompilerPassInterface[]
     */
    private function sortPasses(array $passes): array
    {
        if (0 === \count($passes)) {
            return [];
        }
        krsort($passes);
        // Flatten the array
        return array_merge(...$passes);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\DependencyInjection\Compiler;

use _ContaoManager\Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
use _ContaoManager\Symfony\Component\DependencyInjection\Reference;
/**
 * This is a directed graph of your services.
 *
 * This information can be used by your compiler passes instead of collecting
 * it themselves which improves performance quite a lot.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 *
 * @final
 */
class ServiceReferenceGraph
{
    /**
     * @var ServiceReferenceGraphNode[]
     */
    private array $nodes = [];
    public function hasNode(string $id): bool
    {
        return isset($this->nodes[$id]);
    }
    /**
     * Gets a node by identifier.
     *
     * @throws InvalidArgumentException if no node matches the supplied identifier
     */
    public function getNode(string $id): ServiceReferenceGraphNode
    {
        if (!isset($this->nodes[$id])) {
            throw new InvalidArgumentException(\sprintf('There is no node with id "%s".', $id));
        }
        return $this->nodes[$id];
    }
    /**
     * Returns all nodes.
     *
     * @return ServiceReferenceGraphNode[]
     */
    public function getNodes(): array
    {
        return $this->nodes;
    }
    /**
     * Clears all nodes.
     */
    public function clear(): void
    {
        foreach ($this->nodes as $node) {
            $node->clear();
        }
        $this->nodes = [];
    }
    /**
     * Connects 2 nodes together in the Graph.
     */
    public function connect(?string $sourceId, mixed $sourceValue, ?string $destId, mixed $destValue = null, ?Reference $reference = null, bool $lazy = \false, bool $weak = \false, bool $byConstructor = \false, bool $byMultiUseArgument = \false): void
    {
        if (null === $sourceId || null === $destId) {
            return;
        }
        $sourceNode = $this->createNode($sourceId, $sourceValue);
        $destNode = $this->createNode($destId, $destValue);
        $edge = new ServiceReferenceGraphEdge($sourceNode, $destNode, $reference, $lazy, $weak, $byConstructor, $byMultiUseArgument);
        $sourceNode->addOutEdge($edge);
        $destNode->addInEdge($edge);
    }
    private function createNode(string $id, mixed $value): ServiceReferenceGraphNode
    {
        if (isset($this->nodes[$id]) && $this->nodes[$id]->getValue() === $value) {
            return $this->nodes[$id];
        }
        return $this->nodes[$id] = new ServiceReferenceGraphNode($id, $value);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\DependencyInjection\Compiler;

use _ContaoManager\Symfony\Component\DependencyInjection\ContainerBuilder;
use _ContaoManager\Symfony\Component\DependencyInjection\Definition;
use _ContaoManager\Symfony\Component\DependencyInjection\Reference;
/**
 * Propagate the "container.no_preload" tag.
 *
 * @author Nicolas Grekas <p@tchwork.com>
 */
class ResolveNoPreloadPass extends AbstractRecursivePass
{
    private const DO_PRELOAD_TAG = '.container.do_preload';
    protected bool $skipScalars = \true;
    private array $resolvedIds = [];
    /**
     * @return void
     */
    public function process(ContainerBuilder $container)
    {
        $this->container = $container;
        try {
            foreach ($container->getDefinitions() as $id => $definition) {
                if ($definition->isPublic() && !$definition->isPrivate() && !isset($this->resolvedIds[$id])) {
                    $this->resolvedIds[$id] = \true;
                    $this->processValue($definition, \true);
                }
            }
            foreach ($container->getAliases() as $alias) {
                if ($alias->isPublic() && !$alias->isPrivate() && !isset($this->resolvedIds[$id = (string) $alias]) && $container->hasDefinition($id)) {
                    $this->resolvedIds[$id] = \true;
                    $this->processValue($container->getDefinition($id), \true);
                }
            }
        } finally {
            $this->resolvedIds = [];
            $this->container = null;
        }
        foreach ($container->getDefinitions() as $definition) {
            if ($definition->hasTag(self::DO_PRELOAD_TAG)) {
                $definition->clearTag(self::DO_PRELOAD_TAG);
            } elseif (!$definition->isDeprecated() && !$definition->hasErrors()) {
                $definition->addTag('container.no_preload');
            }
        }
    }
    protected function processValue(mixed $value, bool $isRoot = \false): mixed
    {
        if ($value instanceof Reference && ContainerBuilder::IGNORE_ON_UNINITIALIZED_REFERENCE !== $value->getInvalidBehavior() && $this->container->hasDefinition($id = (string) $value)) {
            $definition = $this->container->getDefinition($id);
            if (!isset($this->resolvedIds[$id]) && (!$definition->isPublic() || $definition->isPrivate())) {
                $this->resolvedIds[$id] = \true;
                $this->processValue($definition, \true);
            }
            return $value;
        }
        if (!$value instanceof Definition) {
            return parent::processValue($value, $isRoot);
        }
        if ($value->hasTag('container.no_preload') || $value->isDeprecated() || $value->hasErrors()) {
            return $value;
        }
        if ($isRoot) {
            $value->addTag(self::DO_PRELOAD_TAG);
        }
        return parent::processValue($value, $isRoot);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\DependencyInjection\Compiler;

use _ContaoManager\Symfony\Component\DependencyInjection\Alias;
use _ContaoManager\Symfony\Component\DependencyInjection\Definition;
/**
 * Represents a node in your service graph.
 *
 * Value is typically a definition, or an alias.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
class ServiceReferenceGraphNode
{
    private string $id;
    private array $inEdges = [];
    private array $outEdges = [];
    private mixed $value;
    public function __construct(string $id, mixed $value)
    {
        $this->id = $id;
        $this->value = $value;
    }
    /**
     * @return void
     */
    public function addInEdge(ServiceReferenceGraphEdge $edge)
    {
        $this->inEdges[] = $edge;
    }
    /**
     * @return void
     */
    public function addOutEdge(ServiceReferenceGraphEdge $edge)
    {
        $this->outEdges[] = $edge;
    }
    /**
     * Checks if the value of this node is an Alias.
     */
    public function isAlias(): bool
    {
        return $this->value instanceof Alias;
    }
    /**
     * Checks if the value of this node is a Definition.
     */
    public function isDefinition(): bool
    {
        return $this->value instanceof Definition;
    }
    /**
     * Returns the identifier.
     */
    public function getId(): string
    {
        return $this->id;
    }
    /**
     * Returns the in edges.
     *
     * @return ServiceReferenceGraphEdge[]
     */
    public function getInEdges(): array
    {
        return $this->inEdges;
    }
    /**
     * Returns the out edges.
     *
     * @return ServiceReferenceGraphEdge[]
     */
    public function getOutEdges(): array
    {
        return $this->outEdges;
    }
    /**
     * Returns the value of this Node.
     */
    public function getValue(): mixed
    {
        return $this->value;
    }
    /**
     * Clears all edges.
     *
     * @return void
     */
    public function clear()
    {
        $this->inEdges = $this->outEdges = [];
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\DependencyInjection\Compiler;

use _ContaoManager\Symfony\Component\DependencyInjection\Argument\IteratorArgument;
use _ContaoManager\Symfony\Component\DependencyInjection\Argument\RewindableGenerator;
use _ContaoManager\Symfony\Component\DependencyInjection\Argument\ServiceClosureArgument;
use _ContaoManager\Symfony\Component\DependencyInjection\Argument\ServiceLocatorArgument;
use _ContaoManager\Symfony\Component\DependencyInjection\Container;
use _ContaoManager\Symfony\Component\DependencyInjection\Definition;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\InvalidParameterTypeException;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\RuntimeException;
use _ContaoManager\Symfony\Component\DependencyInjection\ExpressionLanguage;
use _ContaoManager\Symfony\Component\DependencyInjection\Parameter;
use _ContaoManager\Symfony\Component\DependencyInjection\ParameterBag\EnvPlaceholderParameterBag;
use _ContaoManager\Symfony\Component\DependencyInjection\Reference;
use _ContaoManager\Symfony\Component\DependencyInjection\ServiceLocator;
use _ContaoManager\Symfony\Component\ExpressionLanguage\Expression;
/**
 * Checks whether injected parameters are compatible with type declarations.
 *
 * This pass should be run after all optimization passes.
 *
 * It can be added either:
 *  * before removing passes to check all services even if they are not currently used,
 *  * after removing passes to check only services are used in the app.
 *
 * @author Nicolas Grekas <p@tchwork.com>
 * @author Julien Maulny <jmaulny@darkmira.fr>
 */
final class CheckTypeDeclarationsPass extends AbstractRecursivePass
{
    protected bool $skipScalars = \true;
    private const SCALAR_TYPES = ['int' => \true, 'float' => \true, 'bool' => \true, 'string' => \true];
    private const BUILTIN_TYPES = ['array' => \true, 'bool' => \true, 'callable' => \true, 'float' => \true, 'int' => \true, 'iterable' => \true, 'object' => \true, 'string' => \true];
    private bool $autoload;
    private array $skippedIds;
    private ExpressionLanguage $expressionLanguage;
    /**
     * @param bool  $autoload   Whether services who's class in not loaded should be checked or not.
     *                          Defaults to false to save loading code during compilation.
     * @param array $skippedIds An array indexed by the service ids to skip
     */
    public function __construct(bool $autoload = \false, array $skippedIds = [])
    {
        $this->autoload = $autoload;
        $this->skippedIds = $skippedIds;
    }
    protected function processValue(mixed $value, bool $isRoot = \false): mixed
    {
        if (isset($this->skippedIds[$this->currentId ?? ''])) {
            return $value;
        }
        if (!$value instanceof Definition || $value->hasErrors() || $value->isDeprecated()) {
            return parent::processValue($value, $isRoot);
        }
        if (!$this->autoload) {
            if (!$class = $value->getClass()) {
                return parent::processValue($value, $isRoot);
            }
            if (!class_exists($class, \false) && !interface_exists($class, \false)) {
                return parent::processValue($value, $isRoot);
            }
        }
        if (ServiceLocator::class === $value->getClass()) {
            return parent::processValue($value, $isRoot);
        }
        if ($constructor = $this->getConstructor($value, \false)) {
            $this->checkTypeDeclarations($value, $constructor, $value->getArguments());
        }
        foreach ($value->getMethodCalls() as $methodCall) {
            try {
                $reflectionMethod = $this->getReflectionMethod($value, $methodCall[0]);
            } catch (RuntimeException $e) {
                if ($value->getFactory()) {
                    continue;
                }
                throw $e;
            }
            $this->checkTypeDeclarations($value, $reflectionMethod, $methodCall[1]);
        }
        return parent::processValue($value, $isRoot);
    }
    /**
     * @throws InvalidArgumentException When not enough parameters are defined for the method
     */
    private function checkTypeDeclarations(Definition $checkedDefinition, \ReflectionFunctionAbstract $reflectionFunction, array $values): void
    {
        $numberOfRequiredParameters = $reflectionFunction->getNumberOfRequiredParameters();
        if (\count($values) < $numberOfRequiredParameters) {
            throw new InvalidArgumentException(\sprintf('Invalid definition for service "%s": "%s::%s()" requires %d arguments, %d passed.', $this->currentId, $reflectionFunction->class, $reflectionFunction->name, $numberOfRequiredParameters, \count($values)));
        }
        $reflectionParameters = $reflectionFunction->getParameters();
        $checksCount = min($reflectionFunction->getNumberOfParameters(), \count($values));
        $envPlaceholderUniquePrefix = $this->container->getParameterBag() instanceof EnvPlaceholderParameterBag ? $this->container->getParameterBag()->getEnvPlaceholderUniquePrefix() : null;
        for ($i = 0; $i < $checksCount; ++$i) {
            $p = $reflectionParameters[$i];
            if (!$p->hasType() || $p->isVariadic()) {
                continue;
            }
            $key = $i;
            if (\array_key_exists($p->name, $values)) {
                $key = $p->name;
            } elseif (!\array_key_exists($i, $values)) {
                continue;
            }
            $this->checkType($checkedDefinition, $values[$key], $p, $envPlaceholderUniquePrefix);
        }
        if ($reflectionFunction->isVariadic() && ($lastParameter = end($reflectionParameters))->hasType()) {
            $variadicParameters = \array_slice($values, $lastParameter->getPosition());
            foreach ($variadicParameters as $variadicParameter) {
                $this->checkType($checkedDefinition, $variadicParameter, $lastParameter, $envPlaceholderUniquePrefix);
            }
        }
    }
    /**
     * @throws InvalidParameterTypeException When a parameter is not compatible with the declared type
     */
    private function checkType(Definition $checkedDefinition, mixed $value, \ReflectionParameter $parameter, ?string $envPlaceholderUniquePrefix, ?\ReflectionType $reflectionType = null): void
    {
        $reflectionType ??= $parameter->getType();
        if ($reflectionType instanceof \ReflectionUnionType) {
            foreach ($reflectionType->getTypes() as $t) {
                try {
                    $this->checkType($checkedDefinition, $value, $parameter, $envPlaceholderUniquePrefix, $t);
                    return;
                } catch (InvalidParameterTypeException $e) {
                }
            }
            throw new InvalidParameterTypeException($this->currentId, $e->getCode(), $parameter);
        }
        if ($reflectionType instanceof \ReflectionIntersectionType) {
            foreach ($reflectionType->getTypes() as $t) {
                $this->checkType($checkedDefinition, $value, $parameter, $envPlaceholderUniquePrefix, $t);
            }
            return;
        }
        if (!$reflectionType instanceof \ReflectionNamedType) {
            return;
        }
        $type = $reflectionType->getName();
        if ($value instanceof Reference) {
            if (!$this->container->has($value = (string) $value)) {
                return;
            }
            if ('service_container' === $value && is_a($type, Container::class, \true)) {
                return;
            }
            $value = $this->container->findDefinition($value);
        }
        if ('self' === $type) {
            $type = $parameter->getDeclaringClass()->getName();
        }
        if ('static' === $type) {
            $type = $checkedDefinition->getClass();
        }
        $class = null;
        if ($value instanceof Definition) {
            if ($value->hasErrors() || $value->getFactory()) {
                return;
            }
            $class = $value->getClass();
            if ($class && isset(self::BUILTIN_TYPES[strtolower($class)])) {
                $class = strtolower($class);
            } elseif (!$class || !$this->autoload && !class_exists($class, \false) && !interface_exists($class, \false)) {
                return;
            }
        } elseif ($value instanceof Parameter) {
            $value = $this->container->getParameter($value);
        } elseif ($value instanceof Expression) {
            try {
                $value = $this->getExpressionLanguage()->evaluate($value, ['container' => $this->container]);
            } catch (\Exception) {
                // If a service from the expression cannot be fetched from the container, we skip the validation.
                return;
            }
        } elseif (\is_string($value)) {
            if ('%' === ($value[0] ?? '') && preg_match('/^%([^%]+)%$/', $value, $match)) {
                $value = $this->container->getParameter(substr($value, 1, -1));
            }
            if ($envPlaceholderUniquePrefix && \is_string($value) && str_contains($value, 'env_')) {
                // If the value is an env placeholder that is either mixed with a string or with another env placeholder, then its resolved value will always be a string, so we don't need to resolve it.
                // We don't need to change the value because it is already a string.
                if ('' === preg_replace('/' . $envPlaceholderUniquePrefix . '_\w+_[a-f0-9]{32}/U', '', $value, -1, $c) && 1 === $c) {
                    try {
                        $value = $this->container->resolveEnvPlaceholders($value, \true);
                    } catch (\Exception) {
                        // If an env placeholder cannot be resolved, we skip the validation.
                        return;
                    }
                }
            }
        }
        if (null === $value && $parameter->allowsNull()) {
            return;
        }
        if (null === $class) {
            if ($value instanceof IteratorArgument) {
                $class = RewindableGenerator::class;
            } elseif ($value instanceof ServiceClosureArgument) {
                $class = \Closure::class;
            } elseif ($value instanceof ServiceLocatorArgument) {
                $class = ServiceLocator::class;
            } elseif (\is_object($value)) {
                $class = $value::class;
            } else {
                $class = \gettype($value);
                $class = ['integer' => 'int', 'double' => 'float', 'boolean' => 'bool'][$class] ?? $class;
            }
        }
        if (isset(self::SCALAR_TYPES[$type]) && isset(self::SCALAR_TYPES[$class])) {
            return;
        }
        if ('string' === $type && method_exists($class, '__toString')) {
            return;
        }
        if ('callable' === $type && (\Closure::class === $class || method_exists($class, '__invoke'))) {
            return;
        }
        if ('callable' === $type && \is_array($value) && isset($value[0]) && ($value[0] instanceof Reference || $value[0] instanceof Definition || \is_string($value[0]))) {
            return;
        }
        if ('iterable' === $type && (\is_array($value) || 'array' === $class || is_subclass_of($class, \Traversable::class))) {
            return;
        }
        if ($type === $class) {
            return;
        }
        if ('object' === $type && !isset(self::BUILTIN_TYPES[$class])) {
            return;
        }
        if ('mixed' === $type) {
            return;
        }
        if (is_a($class, $type, \true)) {
            return;
        }
        if ('false' === $type) {
            if (\false === $value) {
                return;
            }
        } elseif ('true' === $type) {
            if (\true === $value) {
                return;
            }
        } elseif ($reflectionType->isBuiltin()) {
            $checkFunction = \sprintf('is_%s', $type);
            if ($checkFunction($value)) {
                return;
            }
        }
        throw new InvalidParameterTypeException($this->currentId, \is_object($value) ? $class : get_debug_type($value), $parameter);
    }
    private function getExpressionLanguage(): ExpressionLanguage
    {
        return $this->expressionLanguage ??= new ExpressionLanguage(null, $this->container->getExpressionLanguageProviders());
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\DependencyInjection\Compiler;

use _ContaoManager\Symfony\Component\DependencyInjection\Argument\ArgumentInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerBuilder;
use _ContaoManager\Symfony\Component\DependencyInjection\Definition;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\ServiceCircularReferenceException;
use _ContaoManager\Symfony\Component\DependencyInjection\Reference;
/**
 * Inline service definitions where this is possible.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
class InlineServiceDefinitionsPass extends AbstractRecursivePass
{
    protected bool $skipScalars = \true;
    private ?AnalyzeServiceReferencesPass $analyzingPass;
    private array $cloningIds = [];
    private array $connectedIds = [];
    private array $notInlinedIds = [];
    private array $inlinedIds = [];
    private array $notInlinableIds = [];
    private ?ServiceReferenceGraph $graph = null;
    public function __construct(?AnalyzeServiceReferencesPass $analyzingPass = null)
    {
        $this->analyzingPass = $analyzingPass;
    }
    /**
     * @return void
     */
    public function process(ContainerBuilder $container)
    {
        $this->container = $container;
        if ($this->analyzingPass) {
            $analyzedContainer = new ContainerBuilder();
            $analyzedContainer->setAliases($container->getAliases());
            $analyzedContainer->setDefinitions($container->getDefinitions());
            foreach ($container->getExpressionLanguageProviders() as $provider) {
                $analyzedContainer->addExpressionLanguageProvider($provider);
            }
        } else {
            $analyzedContainer = $container;
        }
        try {
            $notInlinableIds = [];
            $remainingInlinedIds = [];
            $this->connectedIds = $this->notInlinedIds = $container->getDefinitions();
            do {
                if ($this->analyzingPass) {
                    $analyzedContainer->setDefinitions(array_intersect_key($analyzedContainer->getDefinitions(), $this->connectedIds));
                    $this->analyzingPass->process($analyzedContainer);
                }
                $this->graph = $analyzedContainer->getCompiler()->getServiceReferenceGraph();
                $notInlinedIds = $this->notInlinedIds;
                $notInlinableIds += $this->notInlinableIds;
                $this->connectedIds = $this->notInlinedIds = $this->inlinedIds = $this->notInlinableIds = [];
                foreach ($analyzedContainer->getDefinitions() as $id => $definition) {
                    if (!$this->graph->hasNode($id)) {
                        continue;
                    }
                    if ($definition->isPublic()) {
                        $this->connectedIds[$id] = \true;
                    }
                    foreach ($this->graph->getNode($id)->getOutEdges() as $edge) {
                        if (isset($notInlinedIds[$edge->getSourceNode()->getId()])) {
                            $this->currentId = $id;
                            $this->processValue($definition, \true);
                            break;
                        }
                    }
                }
                foreach ($this->inlinedIds as $id => $isPublicOrNotShared) {
                    if ($isPublicOrNotShared) {
                        $remainingInlinedIds[$id] = $id;
                    } else {
                        $container->removeDefinition($id);
                        $analyzedContainer->removeDefinition($id);
                    }
                }
            } while ($this->inlinedIds && $this->analyzingPass);
            foreach ($remainingInlinedIds as $id) {
                if (isset($notInlinableIds[$id])) {
                    continue;
                }
                $definition = $container->getDefinition($id);
                if (!$definition->isShared() && !$definition->isPublic()) {
                    $container->removeDefinition($id);
                }
            }
        } finally {
            $this->container = null;
            $this->connectedIds = $this->notInlinedIds = $this->inlinedIds = [];
            $this->notInlinableIds = [];
            $this->graph = null;
        }
    }
    protected function processValue(mixed $value, bool $isRoot = \false): mixed
    {
        if ($value instanceof ArgumentInterface) {
            // References found in ArgumentInterface::getValues() are not inlineable
            return $value;
        }
        if ($value instanceof Definition && $this->cloningIds) {
            if ($value->isShared()) {
                return $value;
            }
            $value = clone $value;
        }
        if (!$value instanceof Reference) {
            return parent::processValue($value, $isRoot);
        } elseif (!$this->container->hasDefinition($id = (string) $value)) {
            return $value;
        }
        $definition = $this->container->getDefinition($id);
        if (isset($this->notInlinableIds[$id]) || !$this->isInlineableDefinition($id, $definition)) {
            if ($this->currentId !== $id) {
                $this->notInlinableIds[$id] = \true;
            }
            return $value;
        }
        $this->container->log($this, \sprintf('Inlined service "%s" to "%s".', $id, $this->currentId));
        $this->inlinedIds[$id] = $definition->isPublic() || !$definition->isShared();
        $this->notInlinedIds[$this->currentId ?? ''] = \true;
        if ($definition->isShared()) {
            return $definition;
        }
        if (isset($this->cloningIds[$id])) {
            $ids = array_keys($this->cloningIds);
            $ids[] = $id;
            throw new ServiceCircularReferenceException($id, \array_slice($ids, array_search($id, $ids)));
        }
        $this->cloningIds[$id] = \true;
        try {
            return $this->processValue($definition);
        } finally {
            unset($this->cloningIds[$id]);
        }
    }
    /**
     * Checks if the definition is inlineable.
     */
    private function isInlineableDefinition(string $id, Definition $definition): bool
    {
        if ($definition->hasErrors() || $definition->isDeprecated() || $definition->isLazy() || $definition->isSynthetic() || $definition->hasTag('container.do_not_inline')) {
            return \false;
        }
        if (!$definition->isShared()) {
            if (!$this->graph->hasNode($id)) {
                return \true;
            }
            foreach ($this->graph->getNode($id)->getInEdges() as $edge) {
                $srcId = $edge->getSourceNode()->getId();
                $this->connectedIds[$srcId] = \true;
                if ($edge->isWeak() || $edge->isLazy()) {
                    return !$this->connectedIds[$id] = \true;
                }
            }
            return \true;
        }
        if ($definition->isPublic() || $this->currentId === $id || !$this->graph->hasNode($id)) {
            return \false;
        }
        $this->connectedIds[$id] = \true;
        $srcIds = [];
        $srcCount = 0;
        foreach ($this->graph->getNode($id)->getInEdges() as $edge) {
            $srcId = $edge->getSourceNode()->getId();
            $this->connectedIds[$srcId] = \true;
            if ($edge->isWeak() || $edge->isLazy()) {
                return \false;
            }
            $srcIds[$srcId] = \true;
            ++$srcCount;
        }
        if (1 !== \count($srcIds)) {
            $this->notInlinedIds[$id] = \true;
            return \false;
        }
        if ($srcCount > 1 && \is_array($factory = $definition->getFactory()) && ($factory[0] instanceof Reference || $factory[0] instanceof Definition)) {
            return \false;
        }
        $srcDefinition = $this->container->getDefinition($srcId);
        return $srcDefinition->isShared() && !$srcDefinition->isLazy();
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\DependencyInjection\Compiler;

use _ContaoManager\Symfony\Component\DependencyInjection\Definition;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\RuntimeException;
/**
 * @author Maxime Steinhausser <maxime.steinhausser@gmail.com>
 */
class ResolveFactoryClassPass extends AbstractRecursivePass
{
    protected bool $skipScalars = \true;
    protected function processValue(mixed $value, bool $isRoot = \false): mixed
    {
        if ($value instanceof Definition && \is_array($factory = $value->getFactory()) && null === $factory[0]) {
            if (null === $class = $value->getClass()) {
                throw new RuntimeException(\sprintf('The "%s" service is defined to be created by a factory, but is missing the factory class. Did you forget to define the factory or service class?', $this->currentId));
            }
            $factory[0] = $class;
            $value->setFactory($factory);
        }
        return parent::processValue($value, $isRoot);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\DependencyInjection\Compiler;

use _ContaoManager\Symfony\Component\DependencyInjection\Argument\AbstractArgument;
use _ContaoManager\Symfony\Component\DependencyInjection\Argument\BoundArgument;
use _ContaoManager\Symfony\Component\DependencyInjection\Argument\ServiceLocatorArgument;
use _ContaoManager\Symfony\Component\DependencyInjection\Argument\TaggedIteratorArgument;
use _ContaoManager\Symfony\Component\DependencyInjection\Attribute\Autowire;
use _ContaoManager\Symfony\Component\DependencyInjection\Attribute\Target;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerBuilder;
use _ContaoManager\Symfony\Component\DependencyInjection\Definition;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\RuntimeException;
use _ContaoManager\Symfony\Component\DependencyInjection\Reference;
use _ContaoManager\Symfony\Component\DependencyInjection\TypedReference;
use _ContaoManager\Symfony\Component\VarExporter\ProxyHelper;
/**
 * @author Guilhem Niot <guilhem.niot@gmail.com>
 */
class ResolveBindingsPass extends AbstractRecursivePass
{
    protected bool $skipScalars = \true;
    private array $usedBindings = [];
    private array $unusedBindings = [];
    private array $errorMessages = [];
    /**
     * @return void
     */
    public function process(ContainerBuilder $container)
    {
        $this->usedBindings = $container->getRemovedBindingIds();
        try {
            parent::process($container);
            foreach ($this->unusedBindings as [$key, $serviceId, $bindingType, $file]) {
                $argumentType = $argumentName = $message = null;
                if (str_contains($key, ' ')) {
                    [$argumentType, $argumentName] = explode(' ', $key, 2);
                } elseif ('$' === $key[0]) {
                    $argumentName = $key;
                } else {
                    $argumentType = $key;
                }
                if ($argumentType) {
                    $message .= \sprintf('of type "%s" ', $argumentType);
                }
                if ($argumentName) {
                    $message .= \sprintf('named "%s" ', $argumentName);
                }
                if (BoundArgument::DEFAULTS_BINDING === $bindingType) {
                    $message .= 'under "_defaults"';
                } elseif (BoundArgument::INSTANCEOF_BINDING === $bindingType) {
                    $message .= 'under "_instanceof"';
                } else {
                    $message .= \sprintf('for service "%s"', $serviceId);
                }
                if ($file) {
                    $message .= \sprintf(' in file "%s"', $file);
                }
                $message = \sprintf('A binding is configured for an argument %s, but no corresponding argument has been found. It may be unused and should be removed, or it may have a typo.', $message);
                if ($this->errorMessages) {
                    $message .= \sprintf("\nCould be related to%s:", 1 < \count($this->errorMessages) ? ' one of' : '');
                }
                foreach ($this->errorMessages as $m) {
                    $message .= "\n - " . $m;
                }
                throw new InvalidArgumentException($message);
            }
        } finally {
            $this->usedBindings = [];
            $this->unusedBindings = [];
            $this->errorMessages = [];
        }
    }
    protected function processValue(mixed $value, bool $isRoot = \false): mixed
    {
        if ($value instanceof TypedReference && $value->getType() === (string) $value) {
            // Already checked
            $bindings = $this->container->getDefinition($this->currentId)->getBindings();
            $name = $value->getName();
            if (isset($name, $bindings[$name = $value . ' $' . $name])) {
                return $this->getBindingValue($bindings[$name]);
            }
            if (isset($bindings[$value->getType()])) {
                return $this->getBindingValue($bindings[$value->getType()]);
            }
            return parent::processValue($value, $isRoot);
        }
        if (!$value instanceof Definition || !$bindings = $value->getBindings()) {
            return parent::processValue($value, $isRoot);
        }
        $bindingNames = [];
        foreach ($bindings as $key => $binding) {
            [$bindingValue, $bindingId, $used, $bindingType, $file] = $binding->getValues();
            if ($used) {
                $this->usedBindings[$bindingId ?? ''] = \true;
                unset($this->unusedBindings[$bindingId ?? '']);
            } elseif (!isset($this->usedBindings[$bindingId ?? ''])) {
                $this->unusedBindings[$bindingId ?? ''] = [$key, $this->currentId, $bindingType, $file];
            }
            if (preg_match('/^(?:(?:array|bool|float|int|string|iterable|([^ $]++)) )\$/', $key, $m)) {
                $bindingNames[substr($key, \strlen($m[0]))] = $binding;
            }
            if (!isset($m[1])) {
                continue;
            }
            if (is_subclass_of($m[1], \UnitEnum::class)) {
                $bindingNames[substr($key, \strlen($m[0]))] = $binding;
                continue;
            }
            if (null !== $bindingValue && !$bindingValue instanceof Reference && !$bindingValue instanceof Definition && !$bindingValue instanceof TaggedIteratorArgument && !$bindingValue instanceof ServiceLocatorArgument) {
                throw new InvalidArgumentException(\sprintf('Invalid value for binding key "%s" for service "%s": expected "%s", "%s", "%s", "%s" or null, "%s" given.', $key, $this->currentId, Reference::class, Definition::class, TaggedIteratorArgument::class, ServiceLocatorArgument::class, get_debug_type($bindingValue)));
            }
        }
        if ($value->isAbstract()) {
            return parent::processValue($value, $isRoot);
        }
        $calls = $value->getMethodCalls();
        try {
            if ($constructor = $this->getConstructor($value, \false)) {
                $calls[] = [$constructor, $value->getArguments()];
            }
        } catch (RuntimeException $e) {
            $this->errorMessages[] = $e->getMessage();
            $this->container->getDefinition($this->currentId)->addError($e->getMessage());
            return parent::processValue($value, $isRoot);
        }
        foreach ($calls as $i => $call) {
            [$method, $arguments] = $call;
            if ($method instanceof \ReflectionFunctionAbstract) {
                $reflectionMethod = $method;
            } else {
                try {
                    $reflectionMethod = $this->getReflectionMethod($value, $method);
                } catch (RuntimeException $e) {
                    if ($value->getFactory()) {
                        continue;
                    }
                    throw $e;
                }
            }
            $names = [];
            foreach ($reflectionMethod->getParameters() as $key => $parameter) {
                $names[$key] = $parameter->name;
                if (\array_key_exists($key, $arguments) && '' !== $arguments[$key] && !$arguments[$key] instanceof AbstractArgument) {
                    continue;
                }
                if (\array_key_exists($parameter->name, $arguments) && '' !== $arguments[$parameter->name] && !$arguments[$parameter->name] instanceof AbstractArgument) {
                    continue;
                }
                if ($value->isAutowired() && !$value->hasTag('container.ignore_attributes') && $parameter->getAttributes(Autowire::class, \ReflectionAttribute::IS_INSTANCEOF)) {
                    continue;
                }
                $typeHint = ltrim(ProxyHelper::exportType($parameter) ?? '', '?');
                $name = Target::parseName($parameter, parsedName: $parsedName);
                if ($typeHint && (\array_key_exists($k = preg_replace('/(^|[(|&])\\\\/', '\1', $typeHint) . ' $' . $name, $bindings) || \array_key_exists($k = preg_replace('/(^|[(|&])\\\\/', '\1', $typeHint) . ' $' . $parsedName, $bindings))) {
                    $arguments[$key] = $this->getBindingValue($bindings[$k]);
                    continue;
                }
                if (\array_key_exists($k = '$' . $name, $bindings) || \array_key_exists($k = '$' . $parsedName, $bindings)) {
                    $arguments[$key] = $this->getBindingValue($bindings[$k]);
                    continue;
                }
                if ($typeHint && '\\' === $typeHint[0] && isset($bindings[$typeHint = substr($typeHint, 1)])) {
                    $arguments[$key] = $this->getBindingValue($bindings[$typeHint]);
                    continue;
                }
                if (null !== $binding = $bindingNames[$name] ?? $bindingNames[$parsedName] ?? $bindingNames[$parameter->name] ?? null) {
                    $bindingKey = array_search($binding, $bindings, \true);
                    $argumentType = substr($bindingKey, 0, strpos($bindingKey, ' '));
                    $this->errorMessages[] = \sprintf('Did you forget to add the type "%s" to argument "$%s" of method "%s::%s()"?', $argumentType, $parameter->name, $reflectionMethod->class, $reflectionMethod->name);
                }
            }
            foreach ($names as $key => $name) {
                if (\array_key_exists($name, $arguments) && (0 === $key || \array_key_exists($key - 1, $arguments))) {
                    if (!\array_key_exists($key, $arguments)) {
                        $arguments[$key] = $arguments[$name];
                    }
                    unset($arguments[$name]);
                }
            }
            if ($arguments !== $call[1]) {
                ksort($arguments, \SORT_NATURAL);
                $calls[$i][1] = $arguments;
            }
        }
        if ($constructor) {
            [, $arguments] = array_pop($calls);
            if ($arguments !== $value->getArguments()) {
                $value->setArguments($arguments);
            }
        }
        if ($calls !== $value->getMethodCalls()) {
            $value->setMethodCalls($calls);
        }
        return parent::processValue($value, $isRoot);
    }
    private function getBindingValue(BoundArgument $binding): mixed
    {
        [$bindingValue, $bindingId] = $binding->getValues();
        $this->usedBindings[$bindingId ?? ''] = \true;
        unset($this->unusedBindings[$bindingId ?? '']);
        return $bindingValue;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\DependencyInjection\Compiler;

use _ContaoManager\Symfony\Component\DependencyInjection\Attribute\AsDecorator;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerBuilder;
use _ContaoManager\Symfony\Component\DependencyInjection\Definition;
/**
 * Reads #[AsDecorator] attributes on definitions that are autowired
 * and don't have the "container.ignore_attributes" tag.
 */
final class AutowireAsDecoratorPass implements CompilerPassInterface
{
    public function process(ContainerBuilder $container): void
    {
        foreach ($container->getDefinitions() as $definition) {
            if ($this->accept($definition) && $reflectionClass = $container->getReflectionClass($definition->getClass(), \false)) {
                $this->processClass($definition, $reflectionClass);
            }
        }
    }
    private function accept(Definition $definition): bool
    {
        return !$definition->hasTag('container.ignore_attributes') && $definition->isAutowired();
    }
    private function processClass(Definition $definition, \ReflectionClass $reflectionClass): void
    {
        foreach ($reflectionClass->getAttributes(AsDecorator::class, \ReflectionAttribute::IS_INSTANCEOF) as $attribute) {
            $attribute = $attribute->newInstance();
            $definition->setDecoratedService($attribute->decorates, null, $attribute->priority, $attribute->onInvalid);
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\DependencyInjection\Compiler;

use _ContaoManager\Symfony\Component\DependencyInjection\Argument\TaggedIteratorArgument;
use _ContaoManager\Symfony\Component\DependencyInjection\Attribute\AsTaggedItem;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerBuilder;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
use _ContaoManager\Symfony\Component\DependencyInjection\Reference;
use _ContaoManager\Symfony\Component\DependencyInjection\TypedReference;
/**
 * Trait that allows a generic method to find and sort service by priority option in the tag.
 *
 * @author Iltar van der Berg <kjarli@gmail.com>
 */
trait PriorityTaggedServiceTrait
{
    /**
     * Finds all services with the given tag name and order them by their priority.
     *
     * The order of additions must be respected for services having the same priority,
     * and knowing that the \SplPriorityQueue class does not respect the FIFO method,
     * we should not use that class.
     *
     * @see https://bugs.php.net/53710
     * @see https://bugs.php.net/60926
     *
     * @return Reference[]
     */
    private function findAndSortTaggedServices(string|TaggedIteratorArgument $tagName, ContainerBuilder $container, array $exclude = []): array
    {
        $indexAttribute = $defaultIndexMethod = $needsIndexes = $defaultPriorityMethod = null;
        if ($tagName instanceof TaggedIteratorArgument) {
            $indexAttribute = $tagName->getIndexAttribute();
            $defaultIndexMethod = $tagName->getDefaultIndexMethod();
            $needsIndexes = $tagName->needsIndexes();
            $defaultPriorityMethod = $tagName->getDefaultPriorityMethod() ?? 'getDefaultPriority';
            $exclude = array_merge($exclude, $tagName->getExclude());
            $tagName = $tagName->getTag();
        }
        $i = 0;
        $services = [];
        foreach ($container->findTaggedServiceIds($tagName, \true) as $serviceId => $attributes) {
            if (\in_array($serviceId, $exclude, \true)) {
                continue;
            }
            $defaultPriority = null;
            $defaultIndex = null;
            $definition = $container->getDefinition($serviceId);
            $class = $definition->getClass();
            $class = $container->getParameterBag()->resolveValue($class) ?: null;
            $checkTaggedItem = !$definition->hasTag($definition->isAutoconfigured() ? 'container.ignore_attributes' : $tagName);
            // For decorated services, walk the decoration chain to find #[AsTaggedItem] on the original service
            $innerClass = null;
            $innerDef = $definition;
            while ($innerId = $innerDef->getTag('container.decorator')[0]['inner'] ?? null) {
                if (!$container->has($innerId)) {
                    break;
                }
                $innerDef = $container->findDefinition($innerId);
                $innerClass = $container->getParameterBag()->resolveValue($innerDef->getClass()) ?: null;
            }
            foreach ($attributes as $attribute) {
                $index = $priority = null;
                if (isset($attribute['priority'])) {
                    $priority = $attribute['priority'];
                } elseif (null === $defaultPriority && $defaultPriorityMethod && $class) {
                    $defaultPriority = PriorityTaggedServiceUtil::getDefault($container, $serviceId, $class, $defaultPriorityMethod, $tagName, 'priority', $checkTaggedItem);
                    if (null === $defaultPriority && $innerClass) {
                        $defaultPriority = PriorityTaggedServiceUtil::getDefault($container, $serviceId, $innerClass, $defaultPriorityMethod, $tagName, 'priority', \true);
                    }
                }
                $priority ??= $defaultPriority ??= 0;
                if (null === $indexAttribute && !$defaultIndexMethod && !$needsIndexes) {
                    $services[] = [$priority, ++$i, null, $serviceId, null];
                    continue 2;
                }
                if (null !== $indexAttribute && isset($attribute[$indexAttribute])) {
                    $index = $attribute[$indexAttribute];
                } elseif (null === $defaultIndex && $defaultPriorityMethod && $class) {
                    $defaultIndex = PriorityTaggedServiceUtil::getDefault($container, $serviceId, $class, $defaultIndexMethod ?? 'getDefaultName', $tagName, $indexAttribute, $checkTaggedItem);
                    if (null === $defaultIndex && $innerClass) {
                        $defaultIndex = PriorityTaggedServiceUtil::getDefault($container, $serviceId, $innerClass, $defaultIndexMethod ?? 'getDefaultName', $tagName, $indexAttribute, \true);
                    }
                }
                $decorated = $definition->getTag('container.decorator')[0]['id'] ?? null;
                $index = $index ?? $defaultIndex ?? $defaultIndex = $decorated ?? $serviceId;
                $services[] = [$priority, ++$i, $index, $serviceId, $class];
            }
        }
        uasort($services, static fn($a, $b) => $b[0] <=> $a[0] ?: $a[1] <=> $b[1]);
        $refs = [];
        foreach ($services as [, , $index, $serviceId, $class]) {
            if (!$class) {
                $reference = new Reference($serviceId);
            } elseif ($index === $serviceId) {
                $reference = new TypedReference($serviceId, $class);
            } else {
                $reference = new TypedReference($serviceId, $class, ContainerBuilder::EXCEPTION_ON_INVALID_REFERENCE, $index);
            }
            if (null === $index) {
                $refs[] = $reference;
            } else {
                $refs[$index] = $reference;
            }
        }
        return $refs;
    }
}
/**
 * @internal
 */
class PriorityTaggedServiceUtil
{
    public static function getDefault(ContainerBuilder $container, string $serviceId, string $class, string $defaultMethod, string $tagName, ?string $indexAttribute, bool $checkTaggedItem): string|int|null
    {
        if (!($r = $container->getReflectionClass($class)) || !$checkTaggedItem && !$r->hasMethod($defaultMethod)) {
            return null;
        }
        if ($checkTaggedItem && !$r->hasMethod($defaultMethod)) {
            foreach ($r->getAttributes(AsTaggedItem::class) as $attribute) {
                return 'priority' === $indexAttribute ? $attribute->newInstance()->priority : $attribute->newInstance()->index;
            }
            return null;
        }
        if ($r->isInterface()) {
            return null;
        }
        if (null !== $indexAttribute) {
            $service = $class !== $serviceId ? \sprintf('service "%s"', $serviceId) : 'on the corresponding service';
            $message = [\sprintf('Either method "%s::%s()" should ', $class, $defaultMethod), \sprintf(' or tag "%s" on %s is missing attribute "%s".', $tagName, $service, $indexAttribute)];
        } else {
            $message = [\sprintf('Method "%s::%s()" should ', $class, $defaultMethod), '.'];
        }
        if (!($rm = $r->getMethod($defaultMethod))->isStatic()) {
            throw new InvalidArgumentException(implode('be static', $message));
        }
        if (!$rm->isPublic()) {
            throw new InvalidArgumentException(implode('be public', $message));
        }
        $default = $rm->invoke(null);
        if ('priority' === $indexAttribute) {
            if (!\is_int($default)) {
                throw new InvalidArgumentException(implode(\sprintf('return int (got "%s")', get_debug_type($default)), $message));
            }
            return $default;
        }
        if (\is_int($default)) {
            $default = (string) $default;
        }
        if (!\is_string($default)) {
            throw new InvalidArgumentException(implode(\sprintf('return string|int (got "%s")', get_debug_type($default)), $message));
        }
        return $default;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\DependencyInjection\Compiler;

use _ContaoManager\Symfony\Component\DependencyInjection\Argument\ServiceClosureArgument;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerBuilder;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Definition;
use _ContaoManager\Symfony\Component\DependencyInjection\Reference;
/**
 * @author Nicolas Grekas <p@tchwork.com>
 */
class RegisterReverseContainerPass implements CompilerPassInterface
{
    private bool $beforeRemoving;
    public function __construct(bool $beforeRemoving)
    {
        $this->beforeRemoving = $beforeRemoving;
    }
    /**
     * @return void
     */
    public function process(ContainerBuilder $container)
    {
        if (!$container->hasDefinition('reverse_container')) {
            return;
        }
        $refType = $this->beforeRemoving ? ContainerInterface::IGNORE_ON_UNINITIALIZED_REFERENCE : ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE;
        $services = [];
        foreach ($container->findTaggedServiceIds('container.reversible') as $id => $tags) {
            $services[$id] = new Reference($id, $refType);
        }
        if ($this->beforeRemoving) {
            // prevent inlining of the reverse container
            $services['reverse_container'] = new Reference('reverse_container', $refType);
        }
        $locator = $container->getDefinition('reverse_container')->getArgument(1);
        if ($locator instanceof Reference) {
            $locator = $container->getDefinition((string) $locator);
        }
        if ($locator instanceof Definition) {
            foreach ($services as $id => $ref) {
                $services[$id] = new ServiceClosureArgument($ref);
            }
            $locator->replaceArgument(0, $services);
        } else {
            $locator->setValues($services);
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\DependencyInjection\Compiler;

use _ContaoManager\Symfony\Component\DependencyInjection\Argument\ArgumentInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\ChildDefinition;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerBuilder;
use _ContaoManager\Symfony\Component\DependencyInjection\Definition;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\LogicException;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\RuntimeException;
use _ContaoManager\Symfony\Component\DependencyInjection\ExpressionLanguage;
use _ContaoManager\Symfony\Component\DependencyInjection\Reference;
use _ContaoManager\Symfony\Component\ExpressionLanguage\Expression;
/**
 * @author Nicolas Grekas <p@tchwork.com>
 */
abstract class AbstractRecursivePass implements CompilerPassInterface
{
    /**
     * @var ContainerBuilder
     */
    protected $container;
    protected $currentId;
    protected bool $skipScalars = \false;
    private bool $processExpressions = \false;
    private ExpressionLanguage $expressionLanguage;
    private bool $inExpression = \false;
    /**
     * @return void
     */
    public function process(ContainerBuilder $container)
    {
        $this->container = $container;
        try {
            $this->processValue($container->getDefinitions(), \true);
        } finally {
            $this->container = null;
        }
    }
    /**
     * @return void
     */
    protected function enableExpressionProcessing()
    {
        $this->processExpressions = \true;
    }
    protected function inExpression(bool $reset = \true): bool
    {
        $inExpression = $this->inExpression;
        if ($reset) {
            $this->inExpression = \false;
        }
        return $inExpression;
    }
    /**
     * Processes a value found in a definition tree.
     *
     * @return mixed
     */
    protected function processValue(mixed $value, bool $isRoot = \false)
    {
        if (\is_array($value)) {
            foreach ($value as $k => $v) {
                if ((!$v || \is_scalar($v)) && $this->skipScalars) {
                    continue;
                }
                if ($isRoot) {
                    if ($v instanceof Definition && $v->hasTag('container.excluded')) {
                        continue;
                    }
                    $this->currentId = $k;
                }
                if ($v !== $processedValue = $this->processValue($v, $isRoot)) {
                    $value[$k] = $processedValue;
                }
            }
        } elseif ($value instanceof ArgumentInterface) {
            $value->setValues($this->processValue($value->getValues()));
        } elseif ($value instanceof Expression && $this->processExpressions) {
            $this->getExpressionLanguage()->compile((string) $value, ['this' => 'container', 'args' => 'args']);
        } elseif ($value instanceof Definition) {
            $value->setArguments($this->processValue($value->getArguments()));
            $value->setProperties($this->processValue($value->getProperties()));
            $value->setMethodCalls($this->processValue($value->getMethodCalls()));
            $changes = $value->getChanges();
            if (isset($changes['factory'])) {
                if (\is_string($factory = $value->getFactory()) && str_starts_with($factory, '@=')) {
                    if (!class_exists(Expression::class)) {
                        throw new LogicException('Expressions cannot be used in service factories without the ExpressionLanguage component. Try running "composer require symfony/expression-language".');
                    }
                    $factory = new Expression(substr($factory, 2));
                }
                if (($factory = $this->processValue($factory)) instanceof Expression) {
                    $factory = '@=' . $factory;
                }
                $value->setFactory($factory);
            }
            if (isset($changes['configurator'])) {
                $value->setConfigurator($this->processValue($value->getConfigurator()));
            }
        }
        return $value;
    }
    /**
     * @throws RuntimeException
     */
    protected function getConstructor(Definition $definition, bool $required): ?\ReflectionFunctionAbstract
    {
        if ($definition->isSynthetic()) {
            return null;
        }
        if (\is_string($factory = $definition->getFactory())) {
            if (str_starts_with($factory, '@=')) {
                return new \ReflectionFunction(static function (...$args) {
                });
            }
            if (!\function_exists($factory)) {
                throw new RuntimeException(\sprintf('Invalid service "%s": function "%s" does not exist.', $this->currentId, $factory));
            }
            $r = new \ReflectionFunction($factory);
            if (\false !== $r->getFileName() && file_exists($r->getFileName())) {
                $this->container->fileExists($r->getFileName());
            }
            return $r;
        }
        if ($factory) {
            [$class, $method] = $factory;
            if ('__construct' === $method) {
                throw new RuntimeException(\sprintf('Invalid service "%s": "__construct()" cannot be used as a factory method.', $this->currentId));
            }
            if ($class instanceof Reference) {
                $factoryDefinition = $this->container->findDefinition((string) $class);
                while (null === ($class = $factoryDefinition->getClass()) && $factoryDefinition instanceof ChildDefinition) {
                    $factoryDefinition = $this->container->findDefinition($factoryDefinition->getParent());
                }
            } elseif ($class instanceof Definition) {
                $class = $class->getClass();
            } else {
                $class ??= $definition->getClass();
            }
            return $this->getReflectionMethod(new Definition($class), $method);
        }
        while (null === ($class = $definition->getClass()) && $definition instanceof ChildDefinition) {
            $definition = $this->container->findDefinition($definition->getParent());
        }
        try {
            if (!$r = $this->container->getReflectionClass($class)) {
                if (null === $class) {
                    throw new RuntimeException(\sprintf('Invalid service "%s": the class is not set.', $this->currentId));
                }
                throw new RuntimeException(\sprintf('Invalid service "%s": class "%s" does not exist.', $this->currentId, $class));
            }
        } catch (\ReflectionException $e) {
            throw new RuntimeException(\sprintf('Invalid service "%s": ', $this->currentId) . lcfirst($e->getMessage()));
        }
        if (!$r = $r->getConstructor()) {
            if ($required) {
                throw new RuntimeException(\sprintf('Invalid service "%s": class%s has no constructor.', $this->currentId, \sprintf($class !== $this->currentId ? ' "%s"' : '', $class)));
            }
        } elseif (!$r->isPublic()) {
            throw new RuntimeException(\sprintf('Invalid service "%s": ', $this->currentId) . \sprintf($class !== $this->currentId ? 'constructor of class "%s"' : 'its constructor', $class) . ' must be public.');
        }
        return $r;
    }
    /**
     * @throws RuntimeException
     */
    protected function getReflectionMethod(Definition $definition, string $method): \ReflectionFunctionAbstract
    {
        if ('__construct' === $method) {
            return $this->getConstructor($definition, \true);
        }
        while (null === ($class = $definition->getClass()) && $definition instanceof ChildDefinition) {
            $definition = $this->container->findDefinition($definition->getParent());
        }
        if (null === $class) {
            throw new RuntimeException(\sprintf('Invalid service "%s": the class is not set.', $this->currentId));
        }
        if (!$r = $this->container->getReflectionClass($class)) {
            throw new RuntimeException(\sprintf('Invalid service "%s": class "%s" does not exist.', $this->currentId, $class));
        }
        if (!$r->hasMethod($method)) {
            if ($r->hasMethod('__call') && ($r = $r->getMethod('__call')) && $r->isPublic()) {
                return new \ReflectionMethod(static function (...$arguments) {
                }, '__invoke');
            }
            if ($r->hasMethod('__callStatic') && ($r = $r->getMethod('__callStatic')) && $r->isPublic()) {
                return new \ReflectionMethod(static function (...$arguments) {
                }, '__invoke');
            }
            throw new RuntimeException(\sprintf('Invalid service "%s": method "%s()" does not exist.', $this->currentId, $class !== $this->currentId ? $class . '::' . $method : $method));
        }
        $r = $r->getMethod($method);
        if (!$r->isPublic()) {
            throw new RuntimeException(\sprintf('Invalid service "%s": method "%s()" must be public.', $this->currentId, $class !== $this->currentId ? $class . '::' . $method : $method));
        }
        return $r;
    }
    private function getExpressionLanguage(): ExpressionLanguage
    {
        if (!isset($this->expressionLanguage)) {
            if (!class_exists(ExpressionLanguage::class)) {
                throw new LogicException('Unable to use expressions as the Symfony ExpressionLanguage component is not installed. Try running "composer require symfony/expression-language".');
            }
            $providers = $this->container->getExpressionLanguageProviders();
            $this->expressionLanguage = new ExpressionLanguage(null, $providers, function (string $arg): string {
                if ('""' === substr_replace($arg, '', 1, -1)) {
                    $id = stripcslashes(substr($arg, 1, -1));
                    $this->inExpression = \true;
                    $arg = $this->processValue(new Reference($id));
                    $this->inExpression = \false;
                    if (!$arg instanceof Reference) {
                        throw new RuntimeException(\sprintf('"%s::processValue()" must return a Reference when processing an expression, "%s" returned for service("%s").', static::class, get_debug_type($arg), $id));
                    }
                    $arg = \sprintf('"%s"', $arg);
                }
                return \sprintf('$this->get(%s)', $arg);
            });
        }
        return $this->expressionLanguage;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\DependencyInjection\Compiler;

use _ContaoManager\Symfony\Component\DependencyInjection\ContainerBuilder;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
use _ContaoManager\Symfony\Component\DependencyInjection\Reference;
final class AliasDeprecatedPublicServicesPass extends AbstractRecursivePass
{
    protected bool $skipScalars = \true;
    private array $aliases = [];
    public function process(ContainerBuilder $container): void
    {
        foreach ($container->findTaggedServiceIds('container.private') as $id => $tags) {
            if (null === $package = $tags[0]['package'] ?? null) {
                throw new InvalidArgumentException(\sprintf('The "package" attribute is mandatory for the "container.private" tag on the "%s" service.', $id));
            }
            if (null === $version = $tags[0]['version'] ?? null) {
                throw new InvalidArgumentException(\sprintf('The "version" attribute is mandatory for the "container.private" tag on the "%s" service.', $id));
            }
            $definition = $container->getDefinition($id);
            if (!$definition->isPublic() || $definition->isPrivate()) {
                continue;
            }
            $container->setAlias($id, $aliasId = '.container.private.' . $id)->setPublic(\true)->setDeprecated($package, $version, 'Accessing the "%alias_id%" service directly from the container is deprecated, use dependency injection instead.');
            $container->setDefinition($aliasId, $definition);
            $this->aliases[$id] = $aliasId;
        }
        parent::process($container);
    }
    protected function processValue(mixed $value, bool $isRoot = \false): mixed
    {
        if ($value instanceof Reference && isset($this->aliases[$id = (string) $value])) {
            return new Reference($this->aliases[$id], $value->getInvalidBehavior());
        }
        return parent::processValue($value, $isRoot);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\DependencyInjection\Compiler;

use _ContaoManager\Symfony\Component\DependencyInjection\ChildDefinition;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerBuilder;
use _ContaoManager\Symfony\Component\DependencyInjection\Definition;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\RuntimeException;
/**
 * Applies instanceof conditionals to definitions.
 *
 * @author Nicolas Grekas <p@tchwork.com>
 */
class ResolveInstanceofConditionalsPass implements CompilerPassInterface
{
    /**
     * @return void
     */
    public function process(ContainerBuilder $container)
    {
        foreach ($container->getAutoconfiguredInstanceof() as $interface => $definition) {
            if ($definition->getArguments()) {
                throw new InvalidArgumentException(\sprintf('Autoconfigured instanceof for type "%s" defines arguments but these are not supported and should be removed.', $interface));
            }
        }
        $tagsToKeep = [];
        if ($container->hasParameter('container.behavior_describing_tags')) {
            $tagsToKeep = $container->getParameter('container.behavior_describing_tags');
        }
        foreach ($container->getDefinitions() as $id => $definition) {
            $container->setDefinition($id, $this->processDefinition($container, $id, $definition, $tagsToKeep));
        }
        if ($container->hasParameter('container.behavior_describing_tags')) {
            $container->getParameterBag()->remove('container.behavior_describing_tags');
        }
    }
    private function processDefinition(ContainerBuilder $container, string $id, Definition $definition, array $tagsToKeep): Definition
    {
        $instanceofConditionals = $definition->getInstanceofConditionals();
        $autoconfiguredInstanceof = $definition->isAutoconfigured() ? $container->getAutoconfiguredInstanceof() : [];
        if (!$instanceofConditionals && !$autoconfiguredInstanceof) {
            return $definition;
        }
        if (!$class = $container->getParameterBag()->resolveValue($definition->getClass())) {
            return $definition;
        }
        $conditionals = $this->mergeConditionals($autoconfiguredInstanceof, $instanceofConditionals, $container);
        $definition->setInstanceofConditionals([]);
        $shared = null;
        $instanceofTags = [];
        $instanceofCalls = [];
        $instanceofBindings = [];
        $reflectionClass = null;
        $parent = $definition instanceof ChildDefinition ? $definition->getParent() : null;
        foreach ($conditionals as $interface => $instanceofDefs) {
            if ($interface !== $class && !$reflectionClass ??= $container->getReflectionClass($class, \false) ?: \false) {
                continue;
            }
            if ($interface !== $class && !is_subclass_of($class, $interface)) {
                continue;
            }
            foreach ($instanceofDefs as $key => $instanceofDef) {
                /** @var ChildDefinition $instanceofDef */
                $instanceofDef = clone $instanceofDef;
                $instanceofDef->setAbstract(\true)->setParent($parent ?: '.abstract.instanceof.' . $id);
                $parent = '.instanceof.' . $interface . '.' . $key . '.' . $id;
                $container->setDefinition($parent, $instanceofDef);
                $instanceofTags[] = [$interface, $instanceofDef->getTags()];
                $instanceofBindings = $instanceofDef->getBindings() + $instanceofBindings;
                foreach ($instanceofDef->getMethodCalls() as $methodCall) {
                    $instanceofCalls[] = $methodCall;
                }
                $instanceofDef->setTags([]);
                $instanceofDef->setMethodCalls([]);
                $instanceofDef->setBindings([]);
                if (isset($instanceofDef->getChanges()['shared'])) {
                    $shared = $instanceofDef->isShared();
                }
            }
        }
        if ($parent) {
            $bindings = $definition->getBindings();
            $abstract = $container->setDefinition('.abstract.instanceof.' . $id, $definition);
            $definition->setBindings([]);
            $definition = serialize($definition);
            if (Definition::class === $abstract::class) {
                // cast Definition to ChildDefinition
                $definition = substr_replace($definition, '68', 2, 2);
                $definition = substr_replace($definition, 'Child', 59, 0);
            }
            /** @var ChildDefinition $definition */
            $definition = unserialize($definition);
            $definition->setParent($parent);
            if (null !== $shared && !isset($definition->getChanges()['shared'])) {
                $definition->setShared($shared);
            }
            // Don't add tags to service decorators
            $i = \count($instanceofTags);
            while (0 <= --$i) {
                [$interface, $tags] = $instanceofTags[$i];
                foreach ($tags as $k => $v) {
                    if (null === $definition->getDecoratedService() || $interface === $definition->getClass() || \in_array($k, $tagsToKeep, \true)) {
                        foreach ($v as $v) {
                            if ($definition->hasTag($k) && \in_array($v, $definition->getTag($k))) {
                                continue;
                            }
                            $definition->addTag($k, $v);
                        }
                    }
                }
            }
            $definition->setMethodCalls(array_merge($instanceofCalls, $definition->getMethodCalls()));
            $definition->setBindings($bindings + $instanceofBindings);
            // reset fields with "merge" behavior
            $abstract->setBindings([])->setArguments([])->setMethodCalls([])->setDecoratedService(null)->setTags([])->setAbstract(\true);
        }
        return $definition;
    }
    private function mergeConditionals(array $autoconfiguredInstanceof, array $instanceofConditionals, ContainerBuilder $container): array
    {
        // make each value an array of ChildDefinition
        $conditionals = array_map(fn($childDef) => [$childDef], $autoconfiguredInstanceof);
        foreach ($instanceofConditionals as $interface => $instanceofDef) {
            // make sure the interface/class exists (but don't validate automaticInstanceofConditionals)
            if (!$container->getReflectionClass($interface)) {
                throw new RuntimeException(\sprintf('"%s" is set as an "instanceof" conditional, but it does not exist.', $interface));
            }
            if (!isset($autoconfiguredInstanceof[$interface])) {
                $conditionals[$interface] = [];
            }
            $conditionals[$interface][] = $instanceofDef;
        }
        return $conditionals;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\DependencyInjection\Compiler;

use _ContaoManager\Symfony\Component\DependencyInjection\ContainerBuilder;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\ServiceCircularReferenceException;
use _ContaoManager\Symfony\Component\DependencyInjection\Reference;
/**
 * Replaces all references to aliases with references to the actual service.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
class ResolveReferencesToAliasesPass extends AbstractRecursivePass
{
    protected bool $skipScalars = \true;
    /**
     * @return void
     */
    public function process(ContainerBuilder $container)
    {
        parent::process($container);
        foreach ($container->getAliases() as $id => $alias) {
            $aliasId = (string) $alias;
            $this->currentId = $id;
            if ($aliasId !== $defId = $this->getDefinitionId($aliasId, $container)) {
                $newAlias = $container->setAlias($id, $defId)->setPublic($alias->isPublic());
                if ($alias->isDeprecated()) {
                    $newAlias->setDeprecated(...array_values($alias->getDeprecation('%alias_id%')));
                }
            }
        }
    }
    protected function processValue(mixed $value, bool $isRoot = \false): mixed
    {
        if (!$value instanceof Reference) {
            return parent::processValue($value, $isRoot);
        }
        $defId = $this->getDefinitionId($id = (string) $value, $this->container);
        return $defId !== $id ? new Reference($defId, $value->getInvalidBehavior()) : $value;
    }
    private function getDefinitionId(string $id, ContainerBuilder $container): string
    {
        if (!$container->hasAlias($id)) {
            return $id;
        }
        $alias = $container->getAlias($id);
        if ($alias->isDeprecated()) {
            $referencingDefinition = $container->hasDefinition($this->currentId) ? $container->getDefinition($this->currentId) : $container->getAlias($this->currentId);
            if (!$referencingDefinition->isDeprecated()) {
                $deprecation = $alias->getDeprecation($id);
                trigger_deprecation($deprecation['package'], $deprecation['version'], rtrim($deprecation['message'], '. ') . '. It is being referenced by the "%s" ' . ($container->hasDefinition($this->currentId) ? 'service.' : 'alias.'), $this->currentId);
            }
        }
        $seen = [];
        do {
            if (isset($seen[$id])) {
                throw new ServiceCircularReferenceException($id, array_merge(array_keys($seen), [$id]));
            }
            $seen[$id] = \true;
            $id = (string) $container->getAlias($id);
        } while ($container->hasAlias($id));
        return $id;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\DependencyInjection\Compiler;

use _ContaoManager\Symfony\Component\DependencyInjection\Definition;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\RuntimeException;
/**
 * Checks if arguments of methods are properly configured.
 *
 * @author Kévin Dunglas <dunglas@gmail.com>
 * @author Nicolas Grekas <p@tchwork.com>
 */
class CheckArgumentsValidityPass extends AbstractRecursivePass
{
    protected bool $skipScalars = \true;
    private bool $throwExceptions;
    public function __construct(bool $throwExceptions = \true)
    {
        $this->throwExceptions = $throwExceptions;
    }
    protected function processValue(mixed $value, bool $isRoot = \false): mixed
    {
        if (!$value instanceof Definition) {
            return parent::processValue($value, $isRoot);
        }
        $i = 0;
        $hasNamedArgs = \false;
        foreach ($value->getArguments() as $k => $v) {
            if (preg_match('/^[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*$/', $k)) {
                $hasNamedArgs = \true;
                continue;
            }
            if ($k !== $i++) {
                if (!\is_int($k)) {
                    $msg = \sprintf('Invalid constructor argument for service "%s": integer expected but found string "%s". Check your service definition.', $this->currentId, $k);
                    $value->addError($msg);
                    if ($this->throwExceptions) {
                        throw new RuntimeException($msg);
                    }
                    break;
                }
                $msg = \sprintf('Invalid constructor argument %d for service "%s": argument %d must be defined before. Check your service definition.', 1 + $k, $this->currentId, $i);
                $value->addError($msg);
                if ($this->throwExceptions) {
                    throw new RuntimeException($msg);
                }
            }
            if ($hasNamedArgs) {
                $msg = \sprintf('Invalid constructor argument for service "%s": cannot use positional argument after named argument. Check your service definition.', $this->currentId);
                $value->addError($msg);
                if ($this->throwExceptions) {
                    throw new RuntimeException($msg);
                }
                break;
            }
        }
        foreach ($value->getMethodCalls() as $methodCall) {
            $i = 0;
            $hasNamedArgs = \false;
            foreach ($methodCall[1] as $k => $v) {
                if (preg_match('/^[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*$/', $k)) {
                    $hasNamedArgs = \true;
                    continue;
                }
                if ($k !== $i++) {
                    if (!\is_int($k)) {
                        $msg = \sprintf('Invalid argument for method call "%s" of service "%s": integer expected but found string "%s". Check your service definition.', $methodCall[0], $this->currentId, $k);
                        $value->addError($msg);
                        if ($this->throwExceptions) {
                            throw new RuntimeException($msg);
                        }
                        break;
                    }
                    $msg = \sprintf('Invalid argument %d for method call "%s" of service "%s": argument %d must be defined before. Check your service definition.', 1 + $k, $methodCall[0], $this->currentId, $i);
                    $value->addError($msg);
                    if ($this->throwExceptions) {
                        throw new RuntimeException($msg);
                    }
                }
                if ($hasNamedArgs) {
                    $msg = \sprintf('Invalid argument for method call "%s" of service "%s": cannot use positional argument after named argument. Check your service definition.', $methodCall[0], $this->currentId);
                    $value->addError($msg);
                    if ($this->throwExceptions) {
                        throw new RuntimeException($msg);
                    }
                    break;
                }
            }
        }
        return null;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\DependencyInjection\Compiler;

use _ContaoManager\Symfony\Component\DependencyInjection\ChildDefinition;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerBuilder;
use _ContaoManager\Symfony\Component\DependencyInjection\Definition;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\LogicException;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\RuntimeException;
/**
 * @author Alexander M. Turek <me@derrabus.de>
 */
final class AttributeAutoconfigurationPass extends AbstractRecursivePass
{
    protected bool $skipScalars = \true;
    private array $classAttributeConfigurators = [];
    private array $methodAttributeConfigurators = [];
    private array $propertyAttributeConfigurators = [];
    private array $parameterAttributeConfigurators = [];
    public function process(ContainerBuilder $container): void
    {
        if (!$container->getAutoconfiguredAttributes()) {
            return;
        }
        foreach ($container->getAutoconfiguredAttributes() as $attributeName => $callable) {
            $callableReflector = new \ReflectionFunction($callable(...));
            if ($callableReflector->getNumberOfParameters() <= 2) {
                $this->classAttributeConfigurators[$attributeName] = $callable;
                continue;
            }
            $reflectorParameter = $callableReflector->getParameters()[2];
            $parameterType = $reflectorParameter->getType();
            $types = [];
            if ($parameterType instanceof \ReflectionUnionType) {
                foreach ($parameterType->getTypes() as $type) {
                    $types[] = $type->getName();
                }
            } elseif ($parameterType instanceof \ReflectionNamedType) {
                $types[] = $parameterType->getName();
            } else {
                throw new LogicException(\sprintf('Argument "$%s" of attribute autoconfigurator should have a type, use one or more of "\ReflectionClass|\ReflectionMethod|\ReflectionProperty|\ReflectionParameter|\Reflector" in "%s" on line "%d".', $reflectorParameter->getName(), $callableReflector->getFileName(), $callableReflector->getStartLine()));
            }
            try {
                $attributeReflector = new \ReflectionClass($attributeName);
            } catch (\ReflectionException) {
                continue;
            }
            $targets = $attributeReflector->getAttributes(\Attribute::class)[0] ?? 0;
            $targets = $targets ? $targets->getArguments()[0] ?? -1 : 0;
            foreach (['class', 'method', 'property', 'parameter'] as $symbol) {
                if (['Reflector'] !== $types) {
                    if (!\in_array('Reflection' . ucfirst($symbol), $types, \true)) {
                        continue;
                    }
                    if (!($targets & \constant('Attribute::TARGET_' . strtoupper($symbol)))) {
                        throw new LogicException(\sprintf('Invalid type "Reflection%s" on argument "$%s": attribute "%s" cannot target a ' . $symbol . ' in "%s" on line "%d".', ucfirst($symbol), $reflectorParameter->getName(), $attributeName, $callableReflector->getFileName(), $callableReflector->getStartLine()));
                    }
                }
                $this->{$symbol . 'AttributeConfigurators'}[$attributeName] = $callable;
            }
        }
        parent::process($container);
    }
    protected function processValue(mixed $value, bool $isRoot = \false): mixed
    {
        if (!$value instanceof Definition || !$value->isAutoconfigured() || $value->isAbstract() || $value->hasTag('container.ignore_attributes') || !$classReflector = $this->container->getReflectionClass($value->getClass(), \false)) {
            return parent::processValue($value, $isRoot);
        }
        $instanceof = $value->getInstanceofConditionals();
        $conditionals = $instanceof[$classReflector->getName()] ?? new ChildDefinition('');
        if ($this->classAttributeConfigurators) {
            foreach ($classReflector->getAttributes() as $attribute) {
                if ($configurator = $this->classAttributeConfigurators[$attribute->getName()] ?? null) {
                    $configurator($conditionals, $attribute->newInstance(), $classReflector);
                }
            }
        }
        if ($this->parameterAttributeConfigurators) {
            try {
                $constructorReflector = $this->getConstructor($value, \false);
            } catch (RuntimeException) {
                $constructorReflector = null;
            }
            if ($constructorReflector) {
                foreach ($constructorReflector->getParameters() as $parameterReflector) {
                    foreach ($parameterReflector->getAttributes() as $attribute) {
                        if ($configurator = $this->parameterAttributeConfigurators[$attribute->getName()] ?? null) {
                            $configurator($conditionals, $attribute->newInstance(), $parameterReflector);
                        }
                    }
                }
            }
        }
        if ($this->methodAttributeConfigurators || $this->parameterAttributeConfigurators) {
            foreach ($classReflector->getMethods(\ReflectionMethod::IS_PUBLIC) as $methodReflector) {
                if ($methodReflector->isConstructor() || $methodReflector->isDestructor()) {
                    continue;
                }
                if ($this->methodAttributeConfigurators) {
                    foreach ($methodReflector->getAttributes() as $attribute) {
                        if ($configurator = $this->methodAttributeConfigurators[$attribute->getName()] ?? null) {
                            $configurator($conditionals, $attribute->newInstance(), $methodReflector);
                        }
                    }
                }
                if ($this->parameterAttributeConfigurators) {
                    foreach ($methodReflector->getParameters() as $parameterReflector) {
                        foreach ($parameterReflector->getAttributes() as $attribute) {
                            if ($configurator = $this->parameterAttributeConfigurators[$attribute->getName()] ?? null) {
                                $configurator($conditionals, $attribute->newInstance(), $parameterReflector);
                            }
                        }
                    }
                }
            }
        }
        if ($this->propertyAttributeConfigurators) {
            foreach ($classReflector->getProperties(\ReflectionProperty::IS_PUBLIC) as $propertyReflector) {
                if ($propertyReflector->isStatic()) {
                    continue;
                }
                foreach ($propertyReflector->getAttributes() as $attribute) {
                    if ($configurator = $this->propertyAttributeConfigurators[$attribute->getName()] ?? null) {
                        $configurator($conditionals, $attribute->newInstance(), $propertyReflector);
                    }
                }
            }
        }
        if (!isset($instanceof[$classReflector->getName()]) && new ChildDefinition('') != $conditionals) {
            $instanceof[$classReflector->getName()] = $conditionals;
            $value->setInstanceofConditionals($instanceof);
        }
        return parent::processValue($value, $isRoot);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\DependencyInjection\Compiler;

use _ContaoManager\Symfony\Component\DependencyInjection\Attribute\Autowire;
use _ContaoManager\Symfony\Component\DependencyInjection\Attribute\AutowireDecorated;
use _ContaoManager\Symfony\Component\DependencyInjection\Attribute\Target;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Definition;
use _ContaoManager\Symfony\Component\DependencyInjection\TypedReference;
use _ContaoManager\Symfony\Contracts\Service\Attribute\Required;
/**
 * Looks for definitions with autowiring enabled and registers their corresponding "#[Required]" properties.
 *
 * @author Sebastien Morel (Plopix) <morel.seb@gmail.com>
 * @author Nicolas Grekas <p@tchwork.com>
 */
class AutowireRequiredPropertiesPass extends AbstractRecursivePass
{
    protected bool $skipScalars = \true;
    protected function processValue(mixed $value, bool $isRoot = \false): mixed
    {
        $value = parent::processValue($value, $isRoot);
        if (!$value instanceof Definition || !$value->isAutowired() || $value->isAbstract() || !$value->getClass()) {
            return $value;
        }
        if (!$reflectionClass = $this->container->getReflectionClass($value->getClass(), \false)) {
            return $value;
        }
        $properties = $value->getProperties();
        foreach ($reflectionClass->getProperties() as $reflectionProperty) {
            if (!($type = $reflectionProperty->getType()) instanceof \ReflectionNamedType) {
                continue;
            }
            $doc = \false;
            if (!$reflectionProperty->getAttributes(Required::class) && (\false === ($doc = $reflectionProperty->getDocComment()) || \false === stripos($doc, '@required') || !preg_match('#(?:^/\*\*|\n\s*+\*)\s*+@required(?:\s|\*/$)#i', $doc))) {
                continue;
            }
            if ($doc) {
                trigger_deprecation('symfony/dependency-injection', '6.3', 'Using the "@required" annotation on property "%s::$%s" is deprecated, use the "Symfony\Contracts\Service\Attribute\Required" attribute instead.', $reflectionProperty->class, $reflectionProperty->name);
            }
            if (\array_key_exists($name = $reflectionProperty->getName(), $properties)) {
                continue;
            }
            $type = $type->getName();
            $value->setProperty($name, new TypedReference($type, $type, ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE, $name, array_map(static fn($a) => $a->newInstance(), array_merge($reflectionProperty->getAttributes(Autowire::class, \ReflectionAttribute::IS_INSTANCEOF), $reflectionProperty->getAttributes(AutowireDecorated::class), $reflectionProperty->getAttributes(Target::class)))));
        }
        return $value;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\DependencyInjection\Compiler;

use _ContaoManager\Symfony\Component\DependencyInjection\Argument\AbstractArgument;
use _ContaoManager\Symfony\Component\DependencyInjection\Definition;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
use _ContaoManager\Symfony\Component\DependencyInjection\Reference;
use _ContaoManager\Symfony\Component\VarExporter\ProxyHelper;
/**
 * Resolves named arguments to their corresponding numeric index.
 *
 * @author Kévin Dunglas <dunglas@gmail.com>
 */
class ResolveNamedArgumentsPass extends AbstractRecursivePass
{
    protected bool $skipScalars = \true;
    protected function processValue(mixed $value, bool $isRoot = \false): mixed
    {
        if ($value instanceof AbstractArgument && $value->getText() . '.' === $value->getTextWithContext()) {
            $value->setContext(\sprintf('A value found in service "%s"', $this->currentId));
        }
        if (!$value instanceof Definition) {
            return parent::processValue($value, $isRoot);
        }
        $calls = $value->getMethodCalls();
        $calls[] = ['__construct', $value->getArguments()];
        foreach ($calls as $i => $call) {
            [$method, $arguments] = $call;
            $parameters = null;
            $resolvedKeys = [];
            $resolvedArguments = [];
            foreach ($arguments as $key => $argument) {
                if ($argument instanceof AbstractArgument && $argument->getText() . '.' === $argument->getTextWithContext()) {
                    $argument->setContext(\sprintf('Argument ' . (\is_int($key) ? 1 + $key : '"%3$s"') . ' of ' . ('__construct' === $method ? 'service "%s"' : 'method call "%s::%s()"'), $this->currentId, $method, $key));
                }
                if (\is_int($key)) {
                    $resolvedKeys[$key] = $key;
                    $resolvedArguments[$key] = $argument;
                    continue;
                }
                if (null === $parameters) {
                    $r = $this->getReflectionMethod($value, $method);
                    $class = $r instanceof \ReflectionMethod ? $r->class : $this->currentId;
                    $method = $r->getName();
                    $parameters = $r->getParameters();
                }
                if (isset($key[0]) && '$' !== $key[0] && !class_exists($key) && !interface_exists($key, \false)) {
                    throw new InvalidArgumentException(\sprintf('Invalid service "%s": did you forget to add the "$" prefix to argument "%s"?', $this->currentId, $key));
                }
                if (isset($key[0]) && '$' === $key[0]) {
                    foreach ($parameters as $j => $p) {
                        if ($key === '$' . $p->name) {
                            if ($p->isVariadic() && \is_array($argument)) {
                                foreach ($argument as $variadicArgument) {
                                    $resolvedKeys[$j] = $j;
                                    $resolvedArguments[$j++] = $variadicArgument;
                                }
                            } else {
                                $resolvedKeys[$j] = $p->name;
                                $resolvedArguments[$j] = $argument;
                            }
                            continue 2;
                        }
                    }
                    throw new InvalidArgumentException(\sprintf('Invalid service "%s": method "%s()" has no argument named "%s". Check your service definition.', $this->currentId, $class !== $this->currentId ? $class . '::' . $method : $method, $key));
                }
                if (null !== $argument && !$argument instanceof Reference && !$argument instanceof Definition) {
                    throw new InvalidArgumentException(\sprintf('Invalid service "%s": the value of argument "%s" of method "%s()" must be null, an instance of "%s" or an instance of "%s", "%s" given.', $this->currentId, $key, $class !== $this->currentId ? $class . '::' . $method : $method, Reference::class, Definition::class, get_debug_type($argument)));
                }
                $typeFound = \false;
                foreach ($parameters as $j => $p) {
                    if (!\array_key_exists($j, $resolvedArguments) && ProxyHelper::exportType($p, \true) === $key) {
                        $resolvedKeys[$j] = $p->name;
                        $resolvedArguments[$j] = $argument;
                        $typeFound = \true;
                    }
                }
                if (!$typeFound) {
                    throw new InvalidArgumentException(\sprintf('Invalid service "%s": method "%s()" has no argument type-hinted as "%s". Check your service definition.', $this->currentId, $class !== $this->currentId ? $class . '::' . $method : $method, $key));
                }
            }
            if ($resolvedArguments !== $call[1]) {
                ksort($resolvedArguments);
                if (!$value->isAutowired() && !array_is_list($resolvedArguments)) {
                    ksort($resolvedKeys);
                    $resolvedArguments = array_combine($resolvedKeys, $resolvedArguments);
                }
                $calls[$i][1] = $resolvedArguments;
            }
        }
        [, $arguments] = array_pop($calls);
        if ($arguments !== $value->getArguments()) {
            $value->setArguments($arguments);
        }
        if ($calls !== $value->getMethodCalls()) {
            $value->setMethodCalls($calls);
        }
        foreach ($value->getProperties() as $key => $argument) {
            if ($argument instanceof AbstractArgument && $argument->getText() . '.' === $argument->getTextWithContext()) {
                $argument->setContext(\sprintf('Property "%s" of service "%s"', $key, $this->currentId));
            }
        }
        return parent::processValue($value, $isRoot);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\DependencyInjection\Compiler;

use _ContaoManager\Symfony\Component\DependencyInjection\ContainerBuilder;
/**
 * Remove private aliases from the container. They were only used to establish
 * dependencies between services, and these dependencies have been resolved in
 * one of the previous passes.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
class RemovePrivateAliasesPass implements CompilerPassInterface
{
    /**
     * Removes private aliases from the ContainerBuilder.
     *
     * @return void
     */
    public function process(ContainerBuilder $container)
    {
        foreach ($container->getAliases() as $id => $alias) {
            if ($alias->isPublic()) {
                continue;
            }
            $container->removeAlias($id);
            $container->log($this, \sprintf('Removed service "%s"; reason: private alias.', $id));
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\DependencyInjection\Compiler;

use _ContaoManager\Symfony\Component\Config\Definition\BaseNode;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerBuilder;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\LogicException;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\RuntimeException;
use _ContaoManager\Symfony\Component\DependencyInjection\Extension\ConfigurationExtensionInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Extension\Extension;
use _ContaoManager\Symfony\Component\DependencyInjection\Extension\ExtensionInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Extension\PrependExtensionInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\ParameterBag\EnvPlaceholderParameterBag;
use _ContaoManager\Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface;
/**
 * Merges extension configs into the container builder.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class MergeExtensionConfigurationPass implements CompilerPassInterface
{
    /**
     * @return void
     */
    public function process(ContainerBuilder $container)
    {
        $parameters = $container->getParameterBag()->all();
        $definitions = $container->getDefinitions();
        $aliases = $container->getAliases();
        $exprLangProviders = $container->getExpressionLanguageProviders();
        $configAvailable = class_exists(BaseNode::class);
        foreach ($container->getExtensions() as $extension) {
            if ($extension instanceof PrependExtensionInterface) {
                $extension->prepend($container);
            }
        }
        foreach ($container->getExtensions() as $name => $extension) {
            if (!$config = $container->getExtensionConfig($name)) {
                // this extension was not called
                continue;
            }
            $resolvingBag = $container->getParameterBag();
            if ($resolvingBag instanceof EnvPlaceholderParameterBag && $extension instanceof Extension) {
                // create a dedicated bag so that we can track env vars per-extension
                $resolvingBag = new MergeExtensionConfigurationParameterBag($resolvingBag);
                if ($configAvailable) {
                    BaseNode::setPlaceholderUniquePrefix($resolvingBag->getEnvPlaceholderUniquePrefix());
                }
            }
            $config = $resolvingBag->resolveValue($config);
            try {
                $tmpContainer = new MergeExtensionConfigurationContainerBuilder($extension, $resolvingBag);
                $tmpContainer->setResourceTracking($container->isTrackingResources());
                $tmpContainer->addObjectResource($extension);
                if ($extension instanceof ConfigurationExtensionInterface && null !== $configuration = $extension->getConfiguration($config, $tmpContainer)) {
                    $tmpContainer->addObjectResource($configuration);
                }
                foreach ($exprLangProviders as $provider) {
                    $tmpContainer->addExpressionLanguageProvider($provider);
                }
                $extension->load($config, $tmpContainer);
            } catch (\Exception $e) {
                if ($resolvingBag instanceof MergeExtensionConfigurationParameterBag) {
                    $container->getParameterBag()->mergeEnvPlaceholders($resolvingBag);
                }
                throw $e;
            }
            if ($resolvingBag instanceof MergeExtensionConfigurationParameterBag) {
                // don't keep track of env vars that are *overridden* when configs are merged
                $resolvingBag->freezeAfterProcessing($extension, $tmpContainer);
            }
            $container->merge($tmpContainer);
            $container->getParameterBag()->add($parameters);
        }
        $container->addDefinitions($definitions);
        $container->addAliases($aliases);
    }
}
/**
 * @internal
 */
class MergeExtensionConfigurationParameterBag extends EnvPlaceholderParameterBag
{
    private array $processedEnvPlaceholders;
    public function __construct(parent $parameterBag)
    {
        parent::__construct($parameterBag->all());
        $this->mergeEnvPlaceholders($parameterBag);
    }
    public function freezeAfterProcessing(Extension $extension, ContainerBuilder $container): void
    {
        if (!$config = $extension->getProcessedConfigs()) {
            // Extension::processConfiguration() wasn't called, we cannot know how configs were merged
            return;
        }
        $this->processedEnvPlaceholders = [];
        // serialize config and container to catch env vars nested in object graphs
        $config = serialize($config) . serialize($container->getDefinitions()) . serialize($container->getAliases()) . serialize($container->getParameterBag()->all());
        if (\false === stripos($config, 'env_')) {
            return;
        }
        preg_match_all('/env_[a-f0-9]{16}_\w+_[a-f0-9]{32}/Ui', $config, $matches);
        $usedPlaceholders = array_flip($matches[0]);
        foreach (parent::getEnvPlaceholders() as $env => $placeholders) {
            foreach ($placeholders as $placeholder) {
                if (isset($usedPlaceholders[$placeholder])) {
                    $this->processedEnvPlaceholders[$env] = $placeholders;
                    break;
                }
            }
        }
    }
    public function getEnvPlaceholders(): array
    {
        return $this->processedEnvPlaceholders ?? parent::getEnvPlaceholders();
    }
    public function getUnusedEnvPlaceholders(): array
    {
        return !isset($this->processedEnvPlaceholders) ? [] : array_diff_key(parent::getEnvPlaceholders(), $this->processedEnvPlaceholders);
    }
}
/**
 * A container builder preventing using methods that wouldn't have any effect from extensions.
 *
 * @internal
 */
class MergeExtensionConfigurationContainerBuilder extends ContainerBuilder
{
    private string $extensionClass;
    public function __construct(ExtensionInterface $extension, ?ParameterBagInterface $parameterBag = null)
    {
        parent::__construct($parameterBag);
        $this->extensionClass = $extension::class;
    }
    public function addCompilerPass(CompilerPassInterface $pass, string $type = PassConfig::TYPE_BEFORE_OPTIMIZATION, int $priority = 0): static
    {
        throw new LogicException(\sprintf('You cannot add compiler pass "%s" from extension "%s". Compiler passes must be registered before the container is compiled.', get_debug_type($pass), $this->extensionClass));
    }
    public function registerExtension(ExtensionInterface $extension)
    {
        throw new LogicException(\sprintf('You cannot register extension "%s" from "%s". Extensions must be registered before the container is compiled.', get_debug_type($extension), $this->extensionClass));
    }
    public function compile(bool $resolveEnvPlaceholders = \false)
    {
        throw new LogicException(\sprintf('Cannot compile the container in extension "%s".', $this->extensionClass));
    }
    public function resolveEnvPlaceholders(mixed $value, string|bool|null $format = null, ?array &$usedEnvs = null): mixed
    {
        if (\true !== $format || !\is_string($value)) {
            return parent::resolveEnvPlaceholders($value, $format, $usedEnvs);
        }
        $bag = $this->getParameterBag();
        $value = $bag->resolveValue($value);
        if (!$bag instanceof EnvPlaceholderParameterBag) {
            return parent::resolveEnvPlaceholders($value, $format, $usedEnvs);
        }
        foreach ($bag->getEnvPlaceholders() as $env => $placeholders) {
            if (!str_contains($env, ':')) {
                continue;
            }
            foreach ($placeholders as $placeholder) {
                if (\false !== stripos($value, $placeholder)) {
                    throw new RuntimeException(\sprintf('Using a cast in "env(%s)" is incompatible with resolution at compile time in "%s". The logic in the extension should be moved to a compiler pass, or an env parameter with no cast should be used instead.', $env, $this->extensionClass));
                }
            }
        }
        return parent::resolveEnvPlaceholders($value, $format, $usedEnvs);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\DependencyInjection\Compiler;

/**
 * Represents an edge in your service graph.
 *
 * Value is typically a reference.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
class ServiceReferenceGraphEdge
{
    private ServiceReferenceGraphNode $sourceNode;
    private ServiceReferenceGraphNode $destNode;
    private mixed $value;
    private bool $lazy;
    private bool $weak;
    private bool $byConstructor;
    private bool $byMultiUseArgument;
    public function __construct(ServiceReferenceGraphNode $sourceNode, ServiceReferenceGraphNode $destNode, mixed $value = null, bool $lazy = \false, bool $weak = \false, bool $byConstructor = \false, bool $byMultiUseArgument = \false)
    {
        $this->sourceNode = $sourceNode;
        $this->destNode = $destNode;
        $this->value = $value;
        $this->lazy = $lazy;
        $this->weak = $weak;
        $this->byConstructor = $byConstructor;
        $this->byMultiUseArgument = $byMultiUseArgument;
    }
    /**
     * Returns the value of the edge.
     */
    public function getValue(): mixed
    {
        return $this->value;
    }
    /**
     * Returns the source node.
     */
    public function getSourceNode(): ServiceReferenceGraphNode
    {
        return $this->sourceNode;
    }
    /**
     * Returns the destination node.
     */
    public function getDestNode(): ServiceReferenceGraphNode
    {
        return $this->destNode;
    }
    /**
     * Returns true if the edge is lazy, meaning it's a dependency not requiring direct instantiation.
     */
    public function isLazy(): bool
    {
        return $this->lazy;
    }
    /**
     * Returns true if the edge is weak, meaning it shouldn't prevent removing the target service.
     */
    public function isWeak(): bool
    {
        return $this->weak;
    }
    /**
     * Returns true if the edge links with a constructor argument.
     */
    public function isReferencedByConstructor(): bool
    {
        return $this->byConstructor;
    }
    public function isFromMultiUseArgument(): bool
    {
        return $this->byMultiUseArgument;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\DependencyInjection\Compiler;

use _ContaoManager\Symfony\Component\DependencyInjection\Argument\ArgumentInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerBuilder;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Definition;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\RuntimeException;
use _ContaoManager\Symfony\Component\DependencyInjection\Reference;
/**
 * Throws an exception for any Definitions that have errors and still exist.
 *
 * @author Ryan Weaver <ryan@knpuniversity.com>
 */
class DefinitionErrorExceptionPass extends AbstractRecursivePass
{
    protected bool $skipScalars = \true;
    private array $erroredDefinitions = [];
    private array $sourceReferences = [];
    /**
     * @return void
     */
    public function process(ContainerBuilder $container)
    {
        try {
            parent::process($container);
            $visitedIds = [];
            foreach ($this->erroredDefinitions as $id => $definition) {
                if ($this->isErrorForRuntime($id, $visitedIds)) {
                    continue;
                }
                // only show the first error so the user can focus on it
                $errors = $definition->getErrors();
                throw new RuntimeException(reset($errors));
            }
        } finally {
            $this->erroredDefinitions = [];
            $this->sourceReferences = [];
        }
    }
    protected function processValue(mixed $value, bool $isRoot = \false): mixed
    {
        if ($value instanceof ArgumentInterface) {
            parent::processValue($value->getValues());
            return $value;
        }
        if ($value instanceof Reference && $this->currentId !== $targetId = (string) $value) {
            if (ContainerInterface::RUNTIME_EXCEPTION_ON_INVALID_REFERENCE === $value->getInvalidBehavior() || ContainerInterface::IGNORE_ON_UNINITIALIZED_REFERENCE === $value->getInvalidBehavior()) {
                $this->sourceReferences[$targetId][$this->currentId ?? ''] ??= \true;
            } else {
                $this->sourceReferences[$targetId][$this->currentId ?? ''] = \false;
            }
            return $value;
        }
        if (!$value instanceof Definition || !$value->hasErrors() || $value->hasTag('container.error')) {
            return parent::processValue($value, $isRoot);
        }
        $this->erroredDefinitions[$this->currentId ?? ''] = $value;
        return parent::processValue($value);
    }
    private function isErrorForRuntime(string $id, array &$visitedIds): bool
    {
        if (!isset($this->sourceReferences[$id])) {
            return \false;
        }
        if (isset($visitedIds[$id])) {
            return $visitedIds[$id];
        }
        $visitedIds[$id] = \true;
        foreach ($this->sourceReferences[$id] as $sourceId => $isRuntime) {
            if ($visitedIds[$sourceId] ?? $visitedIds[$sourceId] = $this->isErrorForRuntime($sourceId, $visitedIds)) {
                continue;
            }
            if (!$isRuntime) {
                return \false;
            }
        }
        return \true;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\DependencyInjection\Compiler;

use _ContaoManager\Symfony\Component\DependencyInjection\ContainerBuilder;
use _ContaoManager\Symfony\Component\DependencyInjection\Reference;
/**
 * Removes unused service definitions from the container.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 * @author Nicolas Grekas <p@tchwork.com>
 */
class RemoveUnusedDefinitionsPass extends AbstractRecursivePass
{
    protected bool $skipScalars = \true;
    private array $connectedIds = [];
    /**
     * Processes the ContainerBuilder to remove unused definitions.
     *
     * @return void
     */
    public function process(ContainerBuilder $container)
    {
        try {
            $this->enableExpressionProcessing();
            $this->container = $container;
            $connectedIds = [];
            $aliases = $container->getAliases();
            foreach ($aliases as $id => $alias) {
                if ($alias->isPublic()) {
                    $this->connectedIds[] = (string) $aliases[$id];
                }
            }
            foreach ($container->getDefinitions() as $id => $definition) {
                if ($definition->isPublic()) {
                    $connectedIds[$id] = \true;
                    $this->processValue($definition);
                }
            }
            while ($this->connectedIds) {
                $ids = $this->connectedIds;
                $this->connectedIds = [];
                foreach ($ids as $id) {
                    if (!isset($connectedIds[$id]) && $container->hasDefinition($id)) {
                        $connectedIds[$id] = \true;
                        $this->processValue($container->getDefinition($id));
                    }
                }
            }
            foreach ($container->getDefinitions() as $id => $definition) {
                if (!isset($connectedIds[$id])) {
                    $container->removeDefinition($id);
                    $container->resolveEnvPlaceholders(!$definition->hasErrors() ? serialize($definition) : $definition);
                    $container->log($this, \sprintf('Removed service "%s"; reason: unused.', $id));
                }
            }
        } finally {
            $this->container = null;
            $this->connectedIds = [];
        }
    }
    protected function processValue(mixed $value, bool $isRoot = \false): mixed
    {
        if (!$value instanceof Reference) {
            return parent::processValue($value, $isRoot);
        }
        if (ContainerBuilder::IGNORE_ON_UNINITIALIZED_REFERENCE !== $value->getInvalidBehavior()) {
            $this->connectedIds[] = (string) $value;
        }
        return $value;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\DependencyInjection\Compiler;

use _ContaoManager\Symfony\Component\Config\Resource\ClassExistenceResource;
use _ContaoManager\Symfony\Component\DependencyInjection\Attribute\Autowire;
use _ContaoManager\Symfony\Component\DependencyInjection\Attribute\AutowireCallable;
use _ContaoManager\Symfony\Component\DependencyInjection\Attribute\AutowireDecorated;
use _ContaoManager\Symfony\Component\DependencyInjection\Attribute\MapDecorated;
use _ContaoManager\Symfony\Component\DependencyInjection\Attribute\Target;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerBuilder;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Definition;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\AutowiringFailedException;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\ParameterNotFoundException;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\RuntimeException;
use _ContaoManager\Symfony\Component\DependencyInjection\Reference;
use _ContaoManager\Symfony\Component\DependencyInjection\TypedReference;
use _ContaoManager\Symfony\Component\VarExporter\ProxyHelper;
/**
 * Inspects existing service definitions and wires the autowired ones using the type hints of their classes.
 *
 * @author Kévin Dunglas <dunglas@gmail.com>
 * @author Nicolas Grekas <p@tchwork.com>
 */
class AutowirePass extends AbstractRecursivePass
{
    protected bool $skipScalars = \true;
    private array $types;
    private array $ambiguousServiceTypes;
    private array $autowiringAliases;
    private ?string $lastFailure = null;
    private bool $throwOnAutowiringException;
    private ?string $decoratedClass = null;
    private ?string $decoratedId = null;
    private ?array $methodCalls = null;
    private object $defaultArgument;
    private ?\Closure $getPreviousValue = null;
    private ?int $decoratedMethodIndex = null;
    private ?int $decoratedMethodArgumentIndex = null;
    private ?self $typesClone = null;
    public function __construct(bool $throwOnAutowireException = \true)
    {
        $this->throwOnAutowiringException = $throwOnAutowireException;
        $this->defaultArgument = new class
        {
            public $value;
            public $names;
            public $bag;
            public function withValue(\ReflectionParameter $parameter): self
            {
                $clone = clone $this;
                $clone->value = $this->bag->escapeValue($parameter->getDefaultValue());
                return $clone;
            }
        };
    }
    /**
     * @return void
     */
    public function process(ContainerBuilder $container)
    {
        $this->defaultArgument->bag = $container->getParameterBag();
        try {
            $this->typesClone = clone $this;
            parent::process($container);
        } finally {
            $this->decoratedClass = null;
            $this->decoratedId = null;
            $this->methodCalls = null;
            $this->defaultArgument->bag = null;
            $this->defaultArgument->names = null;
            $this->getPreviousValue = null;
            $this->decoratedMethodIndex = null;
            $this->decoratedMethodArgumentIndex = null;
            $this->typesClone = null;
        }
    }
    protected function processValue(mixed $value, bool $isRoot = \false): mixed
    {
        if ($value instanceof Autowire) {
            return $this->processValue($this->container->getParameterBag()->resolveValue($value->value));
        }
        if ($value instanceof AutowireDecorated || $value instanceof MapDecorated) {
            $definition = $this->container->getDefinition($this->currentId);
            return new Reference($definition->innerServiceId ?? $this->currentId . '.inner', $definition->decorationOnInvalid ?? ContainerInterface::NULL_ON_INVALID_REFERENCE);
        }
        try {
            return $this->doProcessValue($value, $isRoot);
        } catch (AutowiringFailedException $e) {
            if ($this->throwOnAutowiringException) {
                throw $e;
            }
            $this->container->getDefinition($this->currentId)->addError($e->getMessageCallback() ?? $e->getMessage());
            return parent::processValue($value, $isRoot);
        }
    }
    private function doProcessValue(mixed $value, bool $isRoot = \false): mixed
    {
        if ($value instanceof TypedReference) {
            foreach ($value->getAttributes() as $attribute) {
                if ($attribute === $v = $this->processValue($attribute)) {
                    continue;
                }
                if (!$attribute instanceof Autowire || !$v instanceof Reference) {
                    return $v;
                }
                $invalidBehavior = ContainerBuilder::EXCEPTION_ON_INVALID_REFERENCE !== $v->getInvalidBehavior() ? $v->getInvalidBehavior() : $value->getInvalidBehavior();
                $value = $v instanceof TypedReference ? new TypedReference($v, $v->getType(), $invalidBehavior, $v->getName() ?? $value->getName(), array_merge($v->getAttributes(), $value->getAttributes())) : new TypedReference($v, $value->getType(), $invalidBehavior, $value->getName(), $value->getAttributes());
                break;
            }
            if ($ref = $this->getAutowiredReference($value, \true)) {
                return $ref;
            }
            if (ContainerBuilder::RUNTIME_EXCEPTION_ON_INVALID_REFERENCE === $value->getInvalidBehavior()) {
                $message = $this->createTypeNotFoundMessageCallback($value, 'it');
                // since the error message varies by referenced id and $this->currentId, so should the id of the dummy errored definition
                $this->container->register($id = \sprintf('.errored.%s.%s', $this->currentId, (string) $value), $value->getType())->addError($message);
                return new TypedReference($id, $value->getType(), $value->getInvalidBehavior(), $value->getName());
            }
        }
        $value = parent::processValue($value, $isRoot);
        if (!$value instanceof Definition || !$value->isAutowired() || $value->isAbstract() || !$value->getClass()) {
            return $value;
        }
        if (!$reflectionClass = $this->container->getReflectionClass($value->getClass(), \false)) {
            $this->container->log($this, \sprintf('Skipping service "%s": Class or interface "%s" cannot be loaded.', $this->currentId, $value->getClass()));
            return $value;
        }
        $this->methodCalls = $value->getMethodCalls();
        try {
            $constructor = $this->getConstructor($value, \false);
        } catch (RuntimeException $e) {
            throw new AutowiringFailedException($this->currentId, $e->getMessage(), 0, $e);
        }
        if ($constructor) {
            array_unshift($this->methodCalls, [$constructor, $value->getArguments()]);
        }
        $checkAttributes = !$value->hasTag('container.ignore_attributes');
        $this->methodCalls = $this->autowireCalls($reflectionClass, $isRoot, $checkAttributes);
        if ($constructor) {
            [, $arguments] = array_shift($this->methodCalls);
            if ($arguments !== $value->getArguments()) {
                $value->setArguments($arguments);
            }
        }
        if ($this->methodCalls !== $value->getMethodCalls()) {
            $value->setMethodCalls($this->methodCalls);
        }
        return $value;
    }
    private function autowireCalls(\ReflectionClass $reflectionClass, bool $isRoot, bool $checkAttributes): array
    {
        $this->decoratedId = null;
        $this->decoratedClass = null;
        $this->getPreviousValue = null;
        if ($isRoot && ($definition = $this->container->getDefinition($this->currentId)) && null !== ($this->decoratedId = $definition->innerServiceId) && $this->container->has($this->decoratedId)) {
            $this->decoratedClass = $this->container->findDefinition($this->decoratedId)->getClass();
        }
        $patchedIndexes = [];
        foreach ($this->methodCalls as $i => $call) {
            [$method, $arguments] = $call;
            if ($method instanceof \ReflectionFunctionAbstract) {
                $reflectionMethod = $method;
            } else {
                $definition = new Definition($reflectionClass->name);
                try {
                    $reflectionMethod = $this->getReflectionMethod($definition, $method);
                } catch (RuntimeException $e) {
                    if ($definition->getFactory()) {
                        continue;
                    }
                    throw $e;
                }
            }
            $arguments = $this->autowireMethod($reflectionMethod, $arguments, $checkAttributes, $i);
            if ($arguments !== $call[1]) {
                $this->methodCalls[$i][1] = $arguments;
                $patchedIndexes[] = $i;
            }
        }
        // use named arguments to skip complex default values
        foreach ($patchedIndexes as $i) {
            $namedArguments = null;
            $arguments = $this->methodCalls[$i][1];
            foreach ($arguments as $j => $value) {
                if ($namedArguments && !$value instanceof $this->defaultArgument) {
                    unset($arguments[$j]);
                    $arguments[$namedArguments[$j]] = $value;
                }
                if (!$value instanceof $this->defaultArgument) {
                    continue;
                }
                if (\is_array($value->value) ? $value->value : \is_object($value->value)) {
                    unset($arguments[$j]);
                    $namedArguments = $value->names;
                }
                if ($namedArguments) {
                    unset($arguments[$j]);
                } else {
                    $arguments[$j] = $value->value;
                }
            }
            $this->methodCalls[$i][1] = $arguments;
        }
        return $this->methodCalls;
    }
    /**
     * Autowires the constructor or a method.
     *
     * @throws AutowiringFailedException
     */
    private function autowireMethod(\ReflectionFunctionAbstract $reflectionMethod, array $arguments, bool $checkAttributes, int $methodIndex): array
    {
        $class = $reflectionMethod instanceof \ReflectionMethod ? $reflectionMethod->class : $this->currentId;
        $method = $reflectionMethod->name;
        $parameters = $reflectionMethod->getParameters();
        if ($reflectionMethod->isVariadic()) {
            array_pop($parameters);
        }
        $this->defaultArgument->names = new \ArrayObject();
        foreach ($parameters as $index => $parameter) {
            $this->defaultArgument->names[$index] = $parameter->name;
            if (\array_key_exists($parameter->name, $arguments)) {
                $arguments[$index] = $arguments[$parameter->name];
                unset($arguments[$parameter->name]);
            }
            if (\array_key_exists($index, $arguments) && '' !== $arguments[$index]) {
                continue;
            }
            $type = ProxyHelper::exportType($parameter, \true);
            $target = null;
            $name = Target::parseName($parameter, $target);
            $target = $target ? [$target] : [];
            $getValue = function () use ($type, $parameter, $class, $method, $name, $target) {
                if (!$value = $this->getAutowiredReference($ref = new TypedReference($type, $type, ContainerBuilder::EXCEPTION_ON_INVALID_REFERENCE, $name, $target), \false)) {
                    $failureMessage = $this->createTypeNotFoundMessageCallback($ref, \sprintf('argument "$%s" of method "%s()"', $parameter->name, $class !== $this->currentId ? $class . '::' . $method : $method));
                    if ($parameter->isDefaultValueAvailable()) {
                        $value = $this->defaultArgument->withValue($parameter);
                    } elseif (!$parameter->allowsNull()) {
                        throw new AutowiringFailedException($this->currentId, $failureMessage);
                    }
                }
                return $value;
            };
            if ($checkAttributes) {
                foreach ($parameter->getAttributes(Autowire::class, \ReflectionAttribute::IS_INSTANCEOF) as $attribute) {
                    $attribute = $attribute->newInstance();
                    $invalidBehavior = $parameter->allowsNull() ? ContainerInterface::NULL_ON_INVALID_REFERENCE : ContainerBuilder::EXCEPTION_ON_INVALID_REFERENCE;
                    try {
                        $value = $this->processValue(new TypedReference($type ?: '?', $type ?: 'mixed', $invalidBehavior, $name, [$attribute, ...$target]));
                    } catch (ParameterNotFoundException $e) {
                        if (!$parameter->isDefaultValueAvailable()) {
                            throw new AutowiringFailedException($this->currentId, $e->getMessage(), 0, $e);
                        }
                        $arguments[$index] = clone $this->defaultArgument;
                        $arguments[$index]->value = $parameter->getDefaultValue();
                        continue 2;
                    }
                    if ($attribute instanceof AutowireCallable) {
                        $value = $attribute->buildDefinition($value, $type, $parameter);
                    } elseif ($lazy = $attribute->lazy) {
                        $definition = (new Definition($type))->setFactory('current')->setArguments([[$value ??= $getValue()]])->setLazy(\true);
                        if (!\is_array($lazy)) {
                            if (str_contains($type, '|')) {
                                throw new AutowiringFailedException($this->currentId, \sprintf('Cannot use #[Autowire] with option "lazy: true" on union types for service "%s"; set the option to the interface(s) that should be proxied instead.', $this->currentId));
                            }
                            $lazy = str_contains($type, '&') ? explode('&', $type) : [];
                        }
                        if ($lazy) {
                            if (!class_exists($type) && !interface_exists($type, \false)) {
                                $definition->setClass('object');
                            }
                            foreach ($lazy as $v) {
                                $definition->addTag('proxy', ['interface' => $v]);
                            }
                        }
                        if ($definition->getClass() !== (string) $value || $definition->getTag('proxy')) {
                            $value .= '.' . $this->container->hash([$definition->getClass(), $definition->getTag('proxy')]);
                        }
                        $this->container->setDefinition($value = '.lazy.' . $value, $definition);
                        $value = new Reference($value);
                    }
                    $arguments[$index] = $value;
                    continue 2;
                }
                foreach ($parameter->getAttributes(AutowireDecorated::class) as $attribute) {
                    $arguments[$index] = $this->processValue($attribute->newInstance());
                    continue 2;
                }
                foreach ($parameter->getAttributes(MapDecorated::class) as $attribute) {
                    $arguments[$index] = $this->processValue($attribute->newInstance());
                    continue 2;
                }
            }
            if (!$type) {
                if (isset($arguments[$index])) {
                    continue;
                }
                // no default value? Then fail
                if (!$parameter->isDefaultValueAvailable()) {
                    // For core classes, isDefaultValueAvailable() can
                    // be false when isOptional() returns true. If the
                    // argument *is* optional, allow it to be missing
                    if ($parameter->isOptional()) {
                        --$index;
                        break;
                    }
                    $type = ProxyHelper::exportType($parameter);
                    $type = $type ? \sprintf('is type-hinted "%s"', preg_replace('/(^|[(|&])\\\\|^\?\\\\?/', '\1', $type)) : 'has no type-hint';
                    throw new AutowiringFailedException($this->currentId, \sprintf('Cannot autowire service "%s": argument "$%s" of method "%s()" %s, you should configure its value explicitly.', $this->currentId, $parameter->name, $class !== $this->currentId ? $class . '::' . $method : $method, $type));
                }
                // specifically pass the default value
                $arguments[$index] = $this->defaultArgument->withValue($parameter);
                continue;
            }
            if ($this->decoratedClass && is_a($this->decoratedClass, $type, \true)) {
                if ($this->getPreviousValue) {
                    // The inner service is injected only if there is only 1 argument matching the type of the decorated class
                    // across all arguments of all autowired methods.
                    // If a second matching argument is found, the default behavior is restored.
                    $getPreviousValue = $this->getPreviousValue;
                    $this->methodCalls[$this->decoratedMethodIndex][1][$this->decoratedMethodArgumentIndex] = $getPreviousValue();
                    $this->decoratedClass = null;
                    // Prevent further checks
                } else {
                    $arguments[$index] = new TypedReference($this->decoratedId, $this->decoratedClass);
                    $this->getPreviousValue = $getValue;
                    $this->decoratedMethodIndex = $methodIndex;
                    $this->decoratedMethodArgumentIndex = $index;
                    continue;
                }
            }
            $arguments[$index] = $getValue();
        }
        if ($parameters && !isset($arguments[++$index])) {
            while (0 <= --$index) {
                if (!$arguments[$index] instanceof $this->defaultArgument) {
                    break;
                }
                unset($arguments[$index]);
            }
        }
        // it's possible index 1 was set, then index 0, then 2, etc
        // make sure that we re-order so they're injected as expected
        ksort($arguments, \SORT_NATURAL);
        return $arguments;
    }
    /**
     * Returns a reference to the service matching the given type, if any.
     */
    private function getAutowiredReference(TypedReference $reference, bool $filterType): ?TypedReference
    {
        $this->lastFailure = null;
        $type = $reference->getType();
        if ($type !== (string) $reference) {
            return $reference;
        }
        if ($filterType && \false !== $m = strpbrk($type, '&|')) {
            $types = array_diff(explode($m[0], $type), ['int', 'string', 'array', 'bool', 'float', 'iterable', 'object', 'callable', 'null']);
            sort($types);
            $type = implode($m[0], $types);
        }
        $name = $target = (array_filter($reference->getAttributes(), static fn($a) => $a instanceof Target)[0] ?? null)?->name;
        if (null !== $name ??= $reference->getName()) {
            if ($this->container->has($alias = $type . ' $' . $name) && !$this->container->findDefinition($alias)->isAbstract()) {
                return new TypedReference($alias, $type, $reference->getInvalidBehavior());
            }
            if (null !== ($alias = $this->getCombinedAlias($type, $name)) && !$this->container->findDefinition($alias)->isAbstract()) {
                return new TypedReference($alias, $type, $reference->getInvalidBehavior());
            }
            $parsedName = (new Target($name))->getParsedName();
            if ($this->container->has($alias = $type . ' $' . $parsedName) && !$this->container->findDefinition($alias)->isAbstract()) {
                return new TypedReference($alias, $type, $reference->getInvalidBehavior());
            }
            if (null !== ($alias = $this->getCombinedAlias($type, $parsedName)) && !$this->container->findDefinition($alias)->isAbstract()) {
                return new TypedReference($alias, $type, $reference->getInvalidBehavior());
            }
            if ($this->container->has($n = $name) && !$this->container->findDefinition($n)->isAbstract() || $this->container->has($n = $parsedName) && !$this->container->findDefinition($n)->isAbstract()) {
                foreach ($this->container->getAliases() as $id => $alias) {
                    if ($n === (string) $alias && str_starts_with($id, $type . ' $')) {
                        return new TypedReference($n, $type, $reference->getInvalidBehavior());
                    }
                }
            }
            if (null !== $target) {
                return null;
            }
        }
        if ($this->container->has($type) && !$this->container->findDefinition($type)->isAbstract()) {
            return new TypedReference($type, $type, $reference->getInvalidBehavior());
        }
        if (null !== ($alias = $this->getCombinedAlias($type)) && !$this->container->findDefinition($alias)->isAbstract()) {
            return new TypedReference($alias, $type, $reference->getInvalidBehavior());
        }
        return null;
    }
    /**
     * Populates the list of available types.
     */
    private function populateAvailableTypes(ContainerBuilder $container): void
    {
        $this->types = [];
        $this->ambiguousServiceTypes = [];
        $this->autowiringAliases = [];
        foreach ($container->getDefinitions() as $id => $definition) {
            $this->populateAvailableType($container, $id, $definition);
        }
        $prev = null;
        foreach ($container->getAliases() as $id => $alias) {
            $this->populateAutowiringAlias($id, $prev);
            $prev = $id;
        }
    }
    /**
     * Populates the list of available types for a given definition.
     */
    private function populateAvailableType(ContainerBuilder $container, string $id, Definition $definition): void
    {
        // Never use abstract services
        if ($definition->isAbstract()) {
            return;
        }
        if ('' === $id || '.' === $id[0] || $definition->isDeprecated() || !$reflectionClass = $container->getReflectionClass($definition->getClass(), \false)) {
            return;
        }
        foreach ($reflectionClass->getInterfaces() as $reflectionInterface) {
            $this->set($reflectionInterface->name, $id);
        }
        do {
            $this->set($reflectionClass->name, $id);
        } while ($reflectionClass = $reflectionClass->getParentClass());
        $this->populateAutowiringAlias($id);
    }
    /**
     * Associates a type and a service id if applicable.
     */
    private function set(string $type, string $id): void
    {
        // is this already a type/class that is known to match multiple services?
        if (isset($this->ambiguousServiceTypes[$type])) {
            $this->ambiguousServiceTypes[$type][] = $id;
            return;
        }
        // check to make sure the type doesn't match multiple services
        if (!isset($this->types[$type]) || $this->types[$type] === $id) {
            $this->types[$type] = $id;
            return;
        }
        // keep an array of all services matching this type
        if (!isset($this->ambiguousServiceTypes[$type])) {
            $this->ambiguousServiceTypes[$type] = [$this->types[$type]];
            unset($this->types[$type]);
        }
        $this->ambiguousServiceTypes[$type][] = $id;
    }
    private function createTypeNotFoundMessageCallback(TypedReference $reference, string $label): \Closure
    {
        if (!isset($this->typesClone->container)) {
            $this->typesClone->container = new ContainerBuilder($this->container->getParameterBag());
            $this->typesClone->container->setAliases($this->container->getAliases());
            $this->typesClone->container->setDefinitions($this->container->getDefinitions());
            $this->typesClone->container->setResourceTracking(\false);
        }
        $currentId = $this->currentId;
        return (fn() => $this->createTypeNotFoundMessage($reference, $label, $currentId))->bindTo($this->typesClone);
    }
    private function createTypeNotFoundMessage(TypedReference $reference, string $label, string $currentId): string
    {
        $type = $reference->getType();
        $i = null;
        $namespace = $type;
        do {
            $namespace = substr($namespace, 0, $i);
            if ($this->container->hasDefinition($namespace) && $tag = $this->container->getDefinition($namespace)->getTag('container.excluded')) {
                return \sprintf('Cannot autowire service "%s": %s needs an instance of "%s" but this type has been excluded %s.', $currentId, $label, $type, $tag[0]['source'] ?? 'from autowiring');
            }
        } while (\false !== $i = strrpos($namespace, '\\'));
        if (!$r = $this->container->getReflectionClass($type, \false)) {
            // either $type does not exist or a parent class does not exist
            try {
                if (class_exists(ClassExistenceResource::class)) {
                    $resource = new ClassExistenceResource($type, \false);
                    // isFresh() will explode ONLY if a parent class/trait does not exist
                    $resource->isFresh(0);
                    $parentMsg = \false;
                } else {
                    $parentMsg = "couldn't be loaded. Either it was not found or it is missing a parent class or a trait";
                }
            } catch (\ReflectionException $e) {
                $parentMsg = \sprintf('is missing a parent class (%s)', $e->getMessage());
            }
            $message = \sprintf('has type "%s" but this class %s.', $type, $parentMsg ?: 'was not found');
        } else {
            $alternatives = $this->createTypeAlternatives($this->container, $reference);
            if (null !== $target = array_filter($reference->getAttributes(), static fn($a) => $a instanceof Target)[0] ?? null) {
                $target = null !== $target->name ? "('{$target->name}')" : '';
                $message = \sprintf('has "#[Target%s]" but no such target exists.%s', $target, $alternatives);
            } else {
                $message = $this->container->has($type) ? 'this service is abstract' : 'no such service exists';
                $message = \sprintf('references %s "%s" but %s.%s', $r->isInterface() ? 'interface' : 'class', $type, $message, $alternatives);
            }
            if ($r->isInterface() && !$alternatives) {
                $message .= ' Did you create a class that implements this interface?';
            }
        }
        $message = \sprintf('Cannot autowire service "%s": %s %s', $currentId, $label, $message);
        if (null !== $this->lastFailure) {
            $message = $this->lastFailure . "\n" . $message;
            $this->lastFailure = null;
        }
        return $message;
    }
    private function createTypeAlternatives(ContainerBuilder $container, TypedReference $reference): string
    {
        // try suggesting available aliases first
        if ($message = $this->getAliasesSuggestionForType($container, $type = $reference->getType())) {
            return ' ' . $message;
        }
        if (!isset($this->ambiguousServiceTypes)) {
            $this->populateAvailableTypes($container);
        }
        $servicesAndAliases = $container->getServiceIds();
        $autowiringAliases = $this->autowiringAliases[$type] ?? [];
        unset($autowiringAliases['']);
        if ($autowiringAliases) {
            return \sprintf(' Did you mean to target%s "%s" instead?', 1 < \count($autowiringAliases) ? ' one of' : '', implode('", "', $autowiringAliases));
        }
        if (!$container->has($type) && \false !== $key = array_search(strtolower($type), array_map('strtolower', $servicesAndAliases))) {
            return \sprintf(' Did you mean "%s"?', $servicesAndAliases[$key]);
        } elseif (isset($this->ambiguousServiceTypes[$type])) {
            $message = \sprintf('one of these existing services: "%s"', implode('", "', $this->ambiguousServiceTypes[$type]));
        } elseif (isset($this->types[$type])) {
            $message = \sprintf('the existing "%s" service', $this->types[$type]);
        } else {
            return '';
        }
        return \sprintf(' You should maybe alias this %s to %s.', class_exists($type, \false) ? 'class' : 'interface', $message);
    }
    private function getAliasesSuggestionForType(ContainerBuilder $container, string $type): ?string
    {
        $aliases = [];
        foreach (class_parents($type) + class_implements($type) as $parent) {
            if ($container->has($parent) && !$container->findDefinition($parent)->isAbstract()) {
                $aliases[] = $parent;
            }
        }
        if (1 < $len = \count($aliases)) {
            $message = 'Try changing the type-hint to one of its parents: ';
            for ($i = 0, --$len; $i < $len; ++$i) {
                $message .= \sprintf('%s "%s", ', class_exists($aliases[$i], \false) ? 'class' : 'interface', $aliases[$i]);
            }
            $message .= \sprintf('or %s "%s".', class_exists($aliases[$i], \false) ? 'class' : 'interface', $aliases[$i]);
            return $message;
        }
        if ($aliases) {
            return \sprintf('Try changing the type-hint to "%s" instead.', $aliases[0]);
        }
        return null;
    }
    private function populateAutowiringAlias(string $id, ?string $target = null): void
    {
        if (!preg_match('/(?(DEFINE)(?<V>[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*+))^((?&V)(?:\\\\(?&V))*+)(?: \$((?&V)))?$/', $id, $m)) {
            return;
        }
        $type = $m[2];
        $name = $m[3] ?? '';
        if (class_exists($type, \false) || interface_exists($type, \false)) {
            if (null !== $target && str_starts_with($target, '.' . $type . ' $') && (new Target($target = substr($target, \strlen($type) + 3)))->getParsedName() === $name) {
                $name = $target;
            }
            $this->autowiringAliases[$type][$name] = $name;
        }
    }
    private function getCombinedAlias(string $type, ?string $name = null): ?string
    {
        if (str_contains($type, '&')) {
            $types = explode('&', $type);
        } elseif (str_contains($type, '|')) {
            $types = explode('|', $type);
        } else {
            return null;
        }
        $alias = null;
        $suffix = $name ? ' $' . $name : '';
        foreach ($types as $type) {
            if (!$this->container->hasAlias($type . $suffix)) {
                return null;
            }
            if (null === $alias) {
                $alias = (string) $this->container->getAlias($type . $suffix);
            } elseif ((string) $this->container->getAlias($type . $suffix) !== $alias) {
                return null;
            }
        }
        return $alias;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\DependencyInjection\Compiler;

use _ContaoManager\Symfony\Component\DependencyInjection\Alias;
use _ContaoManager\Symfony\Component\DependencyInjection\Argument\ServiceClosureArgument;
use _ContaoManager\Symfony\Component\DependencyInjection\Argument\ServiceLocatorArgument;
use _ContaoManager\Symfony\Component\DependencyInjection\Argument\TaggedIteratorArgument;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerBuilder;
use _ContaoManager\Symfony\Component\DependencyInjection\Definition;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
use _ContaoManager\Symfony\Component\DependencyInjection\Reference;
use _ContaoManager\Symfony\Component\DependencyInjection\ServiceLocator;
/**
 * Applies the "container.service_locator" tag by wrapping references into ServiceClosureArgument instances.
 *
 * @author Nicolas Grekas <p@tchwork.com>
 */
final class ServiceLocatorTagPass extends AbstractRecursivePass
{
    use PriorityTaggedServiceTrait;
    protected bool $skipScalars = \true;
    protected function processValue(mixed $value, bool $isRoot = \false): mixed
    {
        if ($value instanceof ServiceLocatorArgument) {
            if ($value->getTaggedIteratorArgument()) {
                $value->setValues($this->findAndSortTaggedServices($value->getTaggedIteratorArgument(), $this->container));
            }
            return self::register($this->container, $value->getValues());
        }
        if ($value instanceof Definition) {
            $value->setBindings(parent::processValue($value->getBindings()));
        }
        if (!$value instanceof Definition || !$value->hasTag('container.service_locator')) {
            return parent::processValue($value, $isRoot);
        }
        if (!$value->getClass()) {
            $value->setClass(ServiceLocator::class);
        }
        $services = $value->getArguments()[0] ?? null;
        if ($services instanceof TaggedIteratorArgument) {
            $services = $this->findAndSortTaggedServices($services, $this->container);
        }
        if (!\is_array($services)) {
            throw new InvalidArgumentException(\sprintf('Invalid definition for service "%s": an array of references is expected as first argument when the "container.service_locator" tag is set.', $this->currentId));
        }
        $i = 0;
        foreach ($services as $k => $v) {
            if ($v instanceof ServiceClosureArgument) {
                continue;
            }
            if ($i === $k) {
                if ($v instanceof Reference) {
                    unset($services[$k]);
                    $k = (string) $v;
                }
                ++$i;
            } elseif (\is_int($k)) {
                $i = null;
            }
            $services[$k] = new ServiceClosureArgument($v);
        }
        ksort($services);
        $value->setArgument(0, $services);
        $id = '.service_locator.' . ContainerBuilder::hash($value);
        if ($isRoot) {
            if ($id !== $this->currentId) {
                $this->container->setAlias($id, new Alias($this->currentId, \false));
            }
            return $value;
        }
        $this->container->setDefinition($id, $value->setPublic(\false));
        return new Reference($id);
    }
    public static function register(ContainerBuilder $container, array $map, ?string $callerId = null): Reference
    {
        foreach ($map as $k => $v) {
            $map[$k] = new ServiceClosureArgument($v);
        }
        $locator = (new Definition(ServiceLocator::class))->addArgument($map)->addTag('container.service_locator');
        if (null !== $callerId && $container->hasDefinition($callerId)) {
            $locator->setBindings($container->getDefinition($callerId)->getBindings());
        }
        if (!$container->hasDefinition($id = '.service_locator.' . ContainerBuilder::hash($locator))) {
            $container->setDefinition($id, $locator);
        }
        if (null !== $callerId) {
            $locatorId = $id;
            // Locators are shared when they hold the exact same list of factories;
            // to have them specialized per consumer service, we use a cloning factory
            // to derivate customized instances from the prototype one.
            $container->register($id .= '.' . $callerId, ServiceLocator::class)->setFactory([new Reference($locatorId), 'withContext'])->addTag('container.service_locator_context', ['id' => $callerId])->addArgument($callerId)->addArgument(new Reference('service_container'));
        }
        return new Reference($id);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\DependencyInjection\Compiler;

use _ContaoManager\Symfony\Component\DependencyInjection\Argument\TaggedIteratorArgument;
/**
 * Resolves all TaggedIteratorArgument arguments.
 *
 * @author Roland Franssen <franssen.roland@gmail.com>
 */
class ResolveTaggedIteratorArgumentPass extends AbstractRecursivePass
{
    use PriorityTaggedServiceTrait;
    protected bool $skipScalars = \true;
    protected function processValue(mixed $value, bool $isRoot = \false): mixed
    {
        if (!$value instanceof TaggedIteratorArgument) {
            return parent::processValue($value, $isRoot);
        }
        $exclude = $value->getExclude();
        if ($value->excludeSelf()) {
            $exclude[] = $this->currentId;
        }
        $value->setValues($this->findAndSortTaggedServices($value, $this->container, $exclude));
        return $value;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\DependencyInjection\Compiler;

use _ContaoManager\Symfony\Component\DependencyInjection\Definition;
/**
 * Replaces env var placeholders by their current values.
 */
class ResolveEnvPlaceholdersPass extends AbstractRecursivePass
{
    protected bool $skipScalars = \false;
    protected function processValue(mixed $value, bool $isRoot = \false): mixed
    {
        if (\is_string($value)) {
            return $this->container->resolveEnvPlaceholders($value, \true);
        }
        if ($value instanceof Definition) {
            $changes = $value->getChanges();
            if (isset($changes['class'])) {
                $value->setClass($this->container->resolveEnvPlaceholders($value->getClass(), \true));
            }
            if (isset($changes['file'])) {
                $value->setFile($this->container->resolveEnvPlaceholders($value->getFile(), \true));
            }
        }
        $value = parent::processValue($value, $isRoot);
        if ($value && \is_array($value) && !$isRoot) {
            $value = array_combine($this->container->resolveEnvPlaceholders(array_keys($value), \true), $value);
        }
        return $value;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\DependencyInjection\Compiler;

use _ContaoManager\Symfony\Component\DependencyInjection\ContainerBuilder;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\ServiceCircularReferenceException;
/**
 * Checks your services for circular references.
 *
 * References from method calls are ignored since we might be able to resolve
 * these references depending on the order in which services are called.
 *
 * Circular reference from method calls will only be detected at run-time.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
class CheckCircularReferencesPass implements CompilerPassInterface
{
    private array $currentPath;
    private array $checkedNodes;
    private array $checkedLazyNodes;
    /**
     * Checks the ContainerBuilder object for circular references.
     *
     * @return void
     */
    public function process(ContainerBuilder $container)
    {
        $graph = $container->getCompiler()->getServiceReferenceGraph();
        $this->checkedNodes = [];
        foreach ($graph->getNodes() as $id => $node) {
            $this->currentPath = [$id];
            $this->checkOutEdges($node->getOutEdges());
        }
    }
    /**
     * Checks for circular references.
     *
     * @param ServiceReferenceGraphEdge[] $edges An array of Edges
     *
     * @throws ServiceCircularReferenceException when a circular reference is found
     */
    private function checkOutEdges(array $edges): void
    {
        foreach ($edges as $edge) {
            $node = $edge->getDestNode();
            $id = $node->getId();
            if (!empty($this->checkedNodes[$id])) {
                continue;
            }
            $isLeaf = (bool) $node->getValue();
            $isConcrete = !$edge->isLazy() && !$edge->isWeak();
            // Skip already checked lazy services if they are still lazy. Will not gain any new information.
            if (!empty($this->checkedLazyNodes[$id]) && (!$isLeaf || !$isConcrete)) {
                continue;
            }
            // Process concrete references, otherwise defer check circular references for lazy edges.
            if (!$isLeaf || $isConcrete) {
                $searchKey = array_search($id, $this->currentPath);
                $this->currentPath[] = $id;
                if (\false !== $searchKey) {
                    throw new ServiceCircularReferenceException($id, \array_slice($this->currentPath, $searchKey));
                }
                $this->checkOutEdges($node->getOutEdges());
                $this->checkedNodes[$id] = \true;
                unset($this->checkedLazyNodes[$id]);
            } else {
                $this->checkedLazyNodes[$id] = \true;
            }
            array_pop($this->currentPath);
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\DependencyInjection\Compiler;

use _ContaoManager\Symfony\Component\DependencyInjection\ContainerBuilder;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException;
use _ContaoManager\Symfony\Component\DependencyInjection\Reference;
/**
 * Checks that all references are pointing to a valid service.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
class CheckExceptionOnInvalidReferenceBehaviorPass extends AbstractRecursivePass
{
    protected bool $skipScalars = \true;
    private array $serviceLocatorContextIds = [];
    /**
     * @return void
     */
    public function process(ContainerBuilder $container)
    {
        $this->serviceLocatorContextIds = [];
        foreach ($container->findTaggedServiceIds('container.service_locator_context') as $id => $tags) {
            $this->serviceLocatorContextIds[$id] = $tags[0]['id'];
            $container->getDefinition($id)->clearTag('container.service_locator_context');
        }
        try {
            parent::process($container);
        } finally {
            $this->serviceLocatorContextIds = [];
        }
    }
    protected function processValue(mixed $value, bool $isRoot = \false): mixed
    {
        if (!$value instanceof Reference) {
            return parent::processValue($value, $isRoot);
        }
        if (ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE < $value->getInvalidBehavior() || $this->container->has($id = (string) $value)) {
            return $value;
        }
        $currentId = $this->currentId;
        $graph = $this->container->getCompiler()->getServiceReferenceGraph();
        if (isset($this->serviceLocatorContextIds[$currentId])) {
            $currentId = $this->serviceLocatorContextIds[$currentId];
            $locator = $this->container->getDefinition($this->currentId)->getFactory()[0];
            $this->throwServiceNotFoundException($value, $currentId, $locator->getArgument(0));
        }
        if ('.' === $currentId[0] && $graph->hasNode($currentId)) {
            foreach ($graph->getNode($currentId)->getInEdges() as $edge) {
                if (!$edge->getValue() instanceof Reference || ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE < $edge->getValue()->getInvalidBehavior()) {
                    continue;
                }
                $sourceId = $edge->getSourceNode()->getId();
                if ('.' !== $sourceId[0]) {
                    $currentId = $sourceId;
                    break;
                }
                if (isset($this->serviceLocatorContextIds[$sourceId])) {
                    $currentId = $this->serviceLocatorContextIds[$sourceId];
                    $locator = $this->container->getDefinition($this->currentId);
                    $this->throwServiceNotFoundException($value, $currentId, $locator->getArgument(0));
                }
            }
        }
        $this->throwServiceNotFoundException($value, $currentId, $value);
    }
    private function throwServiceNotFoundException(Reference $ref, string $sourceId, $value): void
    {
        $id = (string) $ref;
        $alternatives = [];
        foreach ($this->container->getServiceIds() as $knownId) {
            if ('' === $knownId || '.' === $knownId[0] || $knownId === $this->currentId) {
                continue;
            }
            $lev = levenshtein($id, $knownId);
            if ($lev <= \strlen($id) / 3 || str_contains($knownId, $id)) {
                $alternatives[] = $knownId;
            }
        }
        $pass = new class extends AbstractRecursivePass
        {
            public Reference $ref;
            public string $sourceId;
            public array $alternatives;
            public function processValue(mixed $value, bool $isRoot = \false): mixed
            {
                if ($this->ref !== $value) {
                    return parent::processValue($value, $isRoot);
                }
                $sourceId = $this->sourceId;
                if (null !== $this->currentId && $this->currentId !== (string) $value) {
                    $sourceId = $this->currentId . '" in the container provided to "' . $sourceId;
                }
                throw new ServiceNotFoundException((string) $value, $sourceId, null, $this->alternatives);
            }
        };
        $pass->ref = $ref;
        $pass->sourceId = $sourceId;
        $pass->alternatives = $alternatives;
        $pass->processValue($value, \true);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\DependencyInjection\Compiler;

use _ContaoManager\Symfony\Component\DependencyInjection\ContainerBuilder;
class RemoveBuildParametersPass implements CompilerPassInterface
{
    /**
     * @var array<string, mixed>
     */
    private array $removedParameters = [];
    public function __construct(private bool $preserveArrays = \false)
    {
    }
    /**
     * @return void
     */
    public function process(ContainerBuilder $container)
    {
        $parameterBag = $container->getParameterBag();
        $this->removedParameters = [];
        foreach ($parameterBag->all() as $name => $value) {
            if ('.' === ($name[0] ?? '') && (!$this->preserveArrays || !\is_array($value))) {
                $this->removedParameters[$name] = $value;
                $parameterBag->remove($name);
                $container->log($this, \sprintf('Removing build parameter "%s".', $name));
            }
        }
    }
    /**
     * @return array<string, mixed>
     */
    public function getRemovedParameters(): array
    {
        return $this->removedParameters;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\DependencyInjection\Compiler;

use _ContaoManager\Symfony\Component\DependencyInjection\Alias;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerBuilder;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
/**
 * Sets a service to be an alias of another one, given a format pattern.
 */
class AutoAliasServicePass implements CompilerPassInterface
{
    /**
     * @return void
     */
    public function process(ContainerBuilder $container)
    {
        foreach ($container->findTaggedServiceIds('auto_alias') as $serviceId => $tags) {
            foreach ($tags as $tag) {
                if (!isset($tag['format'])) {
                    throw new InvalidArgumentException(\sprintf('Missing tag information "format" on auto_alias service "%s".', $serviceId));
                }
                $aliasId = $container->getParameterBag()->resolveValue($tag['format']);
                if ($container->hasDefinition($aliasId) || $container->hasAlias($aliasId)) {
                    $alias = new Alias($aliasId, $container->getDefinition($serviceId)->isPublic());
                    $container->setAlias($serviceId, $alias);
                }
            }
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\DependencyInjection\Compiler;

use _ContaoManager\Symfony\Component\DependencyInjection\ContainerBuilder;
use _ContaoManager\Symfony\Component\DependencyInjection\Definition;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\ParameterNotFoundException;
use _ContaoManager\Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface;
/**
 * Resolves all parameter placeholders "%somevalue%" to their real values.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
class ResolveParameterPlaceHoldersPass extends AbstractRecursivePass
{
    protected bool $skipScalars = \false;
    private ParameterBagInterface $bag;
    public function __construct(private bool $resolveArrays = \true, private bool $throwOnResolveException = \true)
    {
    }
    /**
     * @return void
     *
     * @throws ParameterNotFoundException
     */
    public function process(ContainerBuilder $container)
    {
        $this->bag = $container->getParameterBag();
        try {
            parent::process($container);
            $aliases = [];
            foreach ($container->getAliases() as $name => $target) {
                $this->currentId = $name;
                $aliases[$this->bag->resolveValue($name)] = $target;
            }
            $container->setAliases($aliases);
        } catch (ParameterNotFoundException $e) {
            $e->setSourceId($this->currentId);
            throw $e;
        }
        $this->bag->resolve();
        unset($this->bag);
    }
    protected function processValue(mixed $value, bool $isRoot = \false): mixed
    {
        if (\is_string($value)) {
            try {
                $v = $this->bag->resolveValue($value);
            } catch (ParameterNotFoundException $e) {
                if ($this->throwOnResolveException) {
                    throw $e;
                }
                $v = null;
                $this->container->getDefinition($this->currentId)->addError($e->getMessage());
            }
            return $this->resolveArrays || !$v || !\is_array($v) ? $v : $value;
        }
        if ($value instanceof Definition) {
            $value->setBindings($this->processValue($value->getBindings()));
            $changes = $value->getChanges();
            if (isset($changes['class'])) {
                $value->setClass($this->bag->resolveValue($value->getClass()));
            }
            if (isset($changes['file'])) {
                $value->setFile($this->bag->resolveValue($value->getFile()));
            }
            $tags = $value->getTags();
            if (isset($tags['proxy'])) {
                $tags['proxy'] = $this->bag->resolveValue($tags['proxy']);
                $value->setTags($tags);
            }
        }
        $value = parent::processValue($value, $isRoot);
        if ($value && \is_array($value)) {
            $value = array_combine($this->bag->resolveValue(array_keys($value)), $value);
        }
        return $value;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\DependencyInjection\Compiler;

use _ContaoManager\Symfony\Component\DependencyInjection\ChildDefinition;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerBuilder;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
/**
 * @author Nicolas Grekas <p@tchwork.com>
 */
class ResolveClassPass implements CompilerPassInterface
{
    /**
     * @return void
     */
    public function process(ContainerBuilder $container)
    {
        foreach ($container->getDefinitions() as $id => $definition) {
            if ($definition->isSynthetic() || $definition->hasErrors() || null !== $definition->getClass() || !preg_match('/^[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*+(?:\\\\[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*+)++$/', $id)) {
                continue;
            }
            if ($definition instanceof ChildDefinition && !class_exists($id)) {
                throw new InvalidArgumentException(\sprintf('Service definition "%s" has a parent but no class, and its name looks like an FQCN. Either the class is missing or you want to inherit it from the parent service. To resolve this ambiguity, please rename this service to a non-FQCN (e.g. using dots), or create the missing class.', $id));
            }
            $definition->setClass($id);
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\DependencyInjection\Compiler;

use _ContaoManager\Symfony\Component\DependencyInjection\ContainerBuilder;
/**
 * Removes abstract Definitions.
 */
class RemoveAbstractDefinitionsPass implements CompilerPassInterface
{
    /**
     * Removes abstract definitions from the ContainerBuilder.
     *
     * @return void
     */
    public function process(ContainerBuilder $container)
    {
        foreach ($container->getDefinitions() as $id => $definition) {
            if ($definition->isAbstract()) {
                $container->resolveEnvPlaceholders($definition);
                $container->removeDefinition($id);
                $container->log($this, \sprintf('Removed service "%s"; reason: abstract.', $id));
            }
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\DependencyInjection\Compiler;

use _ContaoManager\Symfony\Component\DependencyInjection\Definition;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\RuntimeException;
use _ContaoManager\Symfony\Component\DependencyInjection\Reference;
/**
 * Checks the validity of references.
 *
 * The following checks are performed by this pass:
 * - target definitions are not abstract
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
class CheckReferenceValidityPass extends AbstractRecursivePass
{
    protected bool $skipScalars = \true;
    protected function processValue(mixed $value, bool $isRoot = \false): mixed
    {
        if ($isRoot && $value instanceof Definition && ($value->isSynthetic() || $value->isAbstract())) {
            return $value;
        }
        if ($value instanceof Reference && $this->container->hasDefinition((string) $value)) {
            $targetDefinition = $this->container->getDefinition((string) $value);
            if ($targetDefinition->isAbstract()) {
                throw new RuntimeException(\sprintf('The definition "%s" has a reference to an abstract definition "%s". Abstract definitions cannot be the target of references.', $this->currentId, $value));
            }
        }
        return parent::processValue($value, $isRoot);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\DependencyInjection\Compiler;

use _ContaoManager\Psr\Container\ContainerInterface as PsrContainerInterface;
use _ContaoManager\Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use _ContaoManager\Symfony\Component\DependencyInjection\Argument\BoundArgument;
use _ContaoManager\Symfony\Component\DependencyInjection\Attribute\Autowire;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Definition;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
use _ContaoManager\Symfony\Component\DependencyInjection\Reference;
use _ContaoManager\Symfony\Component\DependencyInjection\TypedReference;
use _ContaoManager\Symfony\Component\HttpFoundation\Session\SessionInterface;
use _ContaoManager\Symfony\Contracts\Service\Attribute\SubscribedService;
use _ContaoManager\Symfony\Contracts\Service\ServiceProviderInterface;
use _ContaoManager\Symfony\Contracts\Service\ServiceSubscriberInterface;
/**
 * Compiler pass to register tagged services that require a service locator.
 *
 * @author Nicolas Grekas <p@tchwork.com>
 */
class RegisterServiceSubscribersPass extends AbstractRecursivePass
{
    protected bool $skipScalars = \true;
    protected function processValue(mixed $value, bool $isRoot = \false): mixed
    {
        if (!$value instanceof Definition || $value->isAbstract() || $value->isSynthetic() || !$value->hasTag('container.service_subscriber')) {
            return parent::processValue($value, $isRoot);
        }
        $serviceMap = [];
        $autowire = $value->isAutowired();
        foreach ($value->getTag('container.service_subscriber') as $attributes) {
            if (!$attributes) {
                $autowire = \true;
                continue;
            }
            ksort($attributes);
            if ([] !== array_diff(array_keys($attributes), ['id', 'key'])) {
                throw new InvalidArgumentException(\sprintf('The "container.service_subscriber" tag accepts only the "key" and "id" attributes, "%s" given for service "%s".', implode('", "', array_keys($attributes)), $this->currentId));
            }
            if (!\array_key_exists('id', $attributes)) {
                throw new InvalidArgumentException(\sprintf('Missing "id" attribute on "container.service_subscriber" tag with key="%s" for service "%s".', $attributes['key'], $this->currentId));
            }
            if (!\array_key_exists('key', $attributes)) {
                $attributes['key'] = $attributes['id'];
            }
            if (isset($serviceMap[$attributes['key']])) {
                continue;
            }
            $serviceMap[$attributes['key']] = new Reference($attributes['id']);
        }
        $class = $value->getClass();
        if (!$r = $this->container->getReflectionClass($class)) {
            throw new InvalidArgumentException(\sprintf('Class "%s" used for service "%s" cannot be found.', $class, $this->currentId));
        }
        if (!$r->isSubclassOf(ServiceSubscriberInterface::class)) {
            throw new InvalidArgumentException(\sprintf('Service "%s" must implement interface "%s".', $this->currentId, ServiceSubscriberInterface::class));
        }
        $class = $r->name;
        // to remove when symfony/dependency-injection will stop being compatible with symfony/framework-bundle<6.0
        $replaceDeprecatedSession = $this->container->has('.session.deprecated') && $r->isSubclassOf(AbstractController::class);
        $subscriberMap = [];
        foreach ($class::getSubscribedServices() as $key => $type) {
            $attributes = [];
            if (!isset($serviceMap[$key]) && $type instanceof Autowire) {
                $subscriberMap[$key] = $type;
                continue;
            }
            if ($type instanceof SubscribedService) {
                $key = $type->key ?? $key;
                $attributes = $type->attributes;
                $type = ($type->nullable ? '?' : '') . ($type->type ?? throw new InvalidArgumentException(\sprintf('When "%s::getSubscribedServices()" returns "%s", a type must be set.', $class, SubscribedService::class)));
            }
            if (!\is_string($type) || !preg_match('/(?(DEFINE)(?<cn>[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*+))(?(DEFINE)(?<fqcn>(?&cn)(?:\\\\(?&cn))*+))^\??(?&fqcn)(?:(?:\|(?&fqcn))*+|(?:&(?&fqcn))*+)$/', $type)) {
                throw new InvalidArgumentException(\sprintf('"%s::getSubscribedServices()" must return valid PHP types for service "%s" key "%s", "%s" returned.', $class, $this->currentId, $key, \is_string($type) ? $type : get_debug_type($type)));
            }
            $optionalBehavior = ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE;
            if ('?' === $type[0]) {
                $type = substr($type, 1);
                $optionalBehavior = ContainerInterface::IGNORE_ON_INVALID_REFERENCE;
            }
            if (\is_int($name = $key)) {
                $key = $type;
                $name = null;
            }
            if (!isset($serviceMap[$key])) {
                if (!$autowire) {
                    throw new InvalidArgumentException(\sprintf('Service "%s" misses a "container.service_subscriber" tag with "key"/"id" attributes corresponding to entry "%s" as returned by "%s::getSubscribedServices()".', $this->currentId, $key, $class));
                }
                if ($replaceDeprecatedSession && SessionInterface::class === $type) {
                    // This prevents triggering the deprecation when building the container
                    // to remove when symfony/dependency-injection will stop being compatible with symfony/framework-bundle<6.0
                    $type = '.session.deprecated';
                }
                $serviceMap[$key] = new Reference($type);
            }
            if ($name) {
                if (\false !== $i = strpos($name, '::get')) {
                    $name = lcfirst(substr($name, 5 + $i));
                } elseif (str_contains($name, '::')) {
                    $name = null;
                }
            }
            if (null !== $name && !$this->container->has($name) && !$this->container->has($type . ' $' . $name)) {
                $camelCaseName = lcfirst(str_replace(' ', '', ucwords(preg_replace('/[^a-zA-Z0-9\x7f-\xff]++/', ' ', $name))));
                $name = $this->container->has($type . ' $' . $camelCaseName) ? $camelCaseName : $name;
            }
            $subscriberMap[$key] = new TypedReference((string) $serviceMap[$key], $type, $optionalBehavior, $name, $attributes);
            unset($serviceMap[$key]);
        }
        if ($serviceMap = array_keys($serviceMap)) {
            $message = \sprintf(1 < \count($serviceMap) ? 'keys "%s" do' : 'key "%s" does', str_replace('%', '%%', implode('", "', $serviceMap)));
            throw new InvalidArgumentException(\sprintf('Service %s not exist in the map returned by "%s::getSubscribedServices()" for service "%s".', $message, $class, $this->currentId));
        }
        $locatorRef = ServiceLocatorTagPass::register($this->container, $subscriberMap, $this->currentId);
        $value->addTag('container.service_subscriber.locator', ['id' => (string) $locatorRef]);
        $value->setBindings([PsrContainerInterface::class => new BoundArgument($locatorRef, \false), ServiceProviderInterface::class => new BoundArgument($locatorRef, \false)] + $value->getBindings());
        return parent::processValue($value);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\DependencyInjection\Compiler;

use _ContaoManager\Symfony\Component\DependencyInjection\Argument\ArgumentInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerBuilder;
use _ContaoManager\Symfony\Component\DependencyInjection\Definition;
use _ContaoManager\Symfony\Component\DependencyInjection\Reference;
/**
 * Propagate "container.hot_path" tags to referenced services.
 *
 * @author Nicolas Grekas <p@tchwork.com>
 */
class ResolveHotPathPass extends AbstractRecursivePass
{
    protected bool $skipScalars = \true;
    private array $resolvedIds = [];
    /**
     * @return void
     */
    public function process(ContainerBuilder $container)
    {
        try {
            parent::process($container);
            $container->getDefinition('service_container')->clearTag('container.hot_path');
        } finally {
            $this->resolvedIds = [];
        }
    }
    protected function processValue(mixed $value, bool $isRoot = \false): mixed
    {
        if ($value instanceof ArgumentInterface) {
            return $value;
        }
        if ($value instanceof Definition && $isRoot) {
            if ($value->isDeprecated()) {
                return $value->clearTag('container.hot_path');
            }
            $this->resolvedIds[$this->currentId ?? ''] = \true;
            if (!$value->hasTag('container.hot_path')) {
                return $value;
            }
        }
        if ($value instanceof Reference && ContainerBuilder::IGNORE_ON_UNINITIALIZED_REFERENCE !== $value->getInvalidBehavior() && $this->container->hasDefinition($id = (string) $value)) {
            $definition = $this->container->getDefinition($id);
            if ($definition->isDeprecated() || $definition->hasTag('container.hot_path')) {
                return $value;
            }
            $definition->addTag('container.hot_path');
            if (isset($this->resolvedIds[$id])) {
                parent::processValue($definition, \false);
            }
            return $value;
        }
        return parent::processValue($value, $isRoot);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\DependencyInjection\Compiler;

use _ContaoManager\Symfony\Component\DependencyInjection\Alias;
use _ContaoManager\Symfony\Component\DependencyInjection\ChildDefinition;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerBuilder;
use _ContaoManager\Symfony\Component\DependencyInjection\Definition;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\ServiceCircularReferenceException;
use _ContaoManager\Symfony\Component\DependencyInjection\Reference;
/**
 * @author Nicolas Grekas <p@tchwork.com>
 */
class ResolveDecoratorStackPass implements CompilerPassInterface
{
    /**
     * @return void
     */
    public function process(ContainerBuilder $container)
    {
        $stacks = [];
        foreach ($container->findTaggedServiceIds('container.stack') as $id => $tags) {
            $definition = $container->getDefinition($id);
            if (!$definition instanceof ChildDefinition) {
                throw new InvalidArgumentException(\sprintf('Invalid service "%s": only definitions with a "parent" can have the "container.stack" tag.', $id));
            }
            if (!$stack = $definition->getArguments()) {
                throw new InvalidArgumentException(\sprintf('Invalid service "%s": the stack of decorators is empty.', $id));
            }
            $stacks[$id] = $stack;
        }
        if (!$stacks) {
            return;
        }
        $resolvedDefinitions = [];
        foreach ($container->getDefinitions() as $id => $definition) {
            if (!isset($stacks[$id])) {
                $resolvedDefinitions[$id] = $definition;
                continue;
            }
            foreach (array_reverse($this->resolveStack($stacks, [$id]), \true) as $k => $v) {
                $resolvedDefinitions[$k] = $v;
            }
            $alias = $container->setAlias($id, $k);
            if ($definition->getChanges()['public'] ?? \false) {
                $alias->setPublic($definition->isPublic());
            }
            if ($definition->isDeprecated()) {
                $alias->setDeprecated(...array_values($definition->getDeprecation('%alias_id%')));
            }
        }
        $container->setDefinitions($resolvedDefinitions);
    }
    private function resolveStack(array $stacks, array $path): array
    {
        $definitions = [];
        $id = end($path);
        $prefix = '.' . $id . '.';
        if (!isset($stacks[$id])) {
            return [$id => new ChildDefinition($id)];
        }
        if (key($path) !== $searchKey = array_search($id, $path)) {
            throw new ServiceCircularReferenceException($id, \array_slice($path, $searchKey));
        }
        foreach ($stacks[$id] as $k => $definition) {
            if ($definition instanceof ChildDefinition && isset($stacks[$definition->getParent()])) {
                $path[] = $definition->getParent();
                $definition = unserialize(serialize($definition));
                // deep clone
            } elseif ($definition instanceof Definition) {
                $definitions[$decoratedId = $prefix . $k] = $definition;
                continue;
            } elseif ($definition instanceof Reference || $definition instanceof Alias) {
                $path[] = (string) $definition;
            } else {
                throw new InvalidArgumentException(\sprintf('Invalid service "%s": unexpected value of type "%s" found in the stack of decorators.', $id, get_debug_type($definition)));
            }
            $p = $prefix . $k;
            foreach ($this->resolveStack($stacks, $path) as $k => $v) {
                $definitions[$decoratedId = $p . $k] = $definition instanceof ChildDefinition ? $definition->setParent($k) : new ChildDefinition($k);
                $definition = null;
            }
            array_pop($path);
        }
        if (1 === \count($path)) {
            foreach ($definitions as $k => $definition) {
                $definition->setPublic(\false)->setTags([])->setDecoratedService($decoratedId);
            }
            $definition->setDecoratedService(null);
        }
        return $definitions;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\DependencyInjection\Compiler;

use _ContaoManager\Psr\Container\ContainerInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Definition;
use _ContaoManager\Symfony\Component\DependencyInjection\Reference;
use _ContaoManager\Symfony\Contracts\Service\ServiceProviderInterface;
/**
 * Compiler pass to inject their service locator to service subscribers.
 *
 * @author Nicolas Grekas <p@tchwork.com>
 */
class ResolveServiceSubscribersPass extends AbstractRecursivePass
{
    protected bool $skipScalars = \true;
    private ?string $serviceLocator = null;
    protected function processValue(mixed $value, bool $isRoot = \false): mixed
    {
        if ($value instanceof Reference && $this->serviceLocator && \in_array((string) $value, [ContainerInterface::class, ServiceProviderInterface::class], \true)) {
            return new Reference($this->serviceLocator);
        }
        if (!$value instanceof Definition) {
            return parent::processValue($value, $isRoot);
        }
        $serviceLocator = $this->serviceLocator;
        $this->serviceLocator = null;
        if ($value->hasTag('container.service_subscriber.locator')) {
            $this->serviceLocator = $value->getTag('container.service_subscriber.locator')[0]['id'];
            $value->clearTag('container.service_subscriber.locator');
        }
        try {
            return parent::processValue($value);
        } finally {
            $this->serviceLocator = $serviceLocator;
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\DependencyInjection\Compiler;

use _ContaoManager\Symfony\Component\DependencyInjection\ContainerBuilder;
/**
 * Interface that must be implemented by compilation passes.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
interface CompilerPassInterface
{
    /**
     * You can modify the container here before it is dumped to PHP code.
     *
     * @return void
     */
    public function process(ContainerBuilder $container);
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\DependencyInjection\Compiler;

use _ContaoManager\Symfony\Component\DependencyInjection\ContainerBuilder;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException;
use _ContaoManager\Symfony\Component\DependencyInjection\Reference;
/**
 * Replaces aliases with actual service definitions, effectively removing these
 * aliases.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
class ReplaceAliasByActualDefinitionPass extends AbstractRecursivePass
{
    protected bool $skipScalars = \true;
    private array $replacements;
    /**
     * Process the Container to replace aliases with service definitions.
     *
     * @return void
     *
     * @throws InvalidArgumentException if the service definition does not exist
     */
    public function process(ContainerBuilder $container)
    {
        // First collect all alias targets that need to be replaced
        $seenAliasTargets = [];
        $replacements = [];
        // Sort aliases so non-deprecated ones come first. This ensures that when
        // multiple aliases point to the same private definition, non-deprecated
        // aliases get priority for renaming. Otherwise, the definition might be
        // renamed to a deprecated alias ID, causing the original service ID to
        // become an alias to the deprecated one (inverting the alias chain).
        $aliases = $container->getAliases();
        uasort($aliases, static fn($a, $b) => $a->isDeprecated() <=> $b->isDeprecated());
        foreach ($aliases as $definitionId => $target) {
            $targetId = (string) $target;
            // Special case: leave this target alone
            if ('service_container' === $targetId) {
                continue;
            }
            // Check if target needs to be replaced
            if (isset($replacements[$targetId])) {
                $container->setAlias($definitionId, $replacements[$targetId])->setPublic($target->isPublic());
                if ($target->isDeprecated()) {
                    $container->getAlias($definitionId)->setDeprecated(...array_values($target->getDeprecation('%alias_id%')));
                }
            }
            // No need to process the same target twice
            if (isset($seenAliasTargets[$targetId])) {
                continue;
            }
            // Process new target
            $seenAliasTargets[$targetId] = \true;
            try {
                $definition = $container->getDefinition($targetId);
            } catch (ServiceNotFoundException $e) {
                if ('' !== $e->getId() && '@' === $e->getId()[0]) {
                    throw new ServiceNotFoundException($e->getId(), $e->getSourceId(), null, [substr($e->getId(), 1)]);
                }
                throw $e;
            }
            if ($definition->isPublic()) {
                continue;
            }
            // Remove private definition and schedule for replacement
            $definition->setPublic($target->isPublic());
            $container->setDefinition($definitionId, $definition);
            $container->removeDefinition($targetId);
            $replacements[$targetId] = $definitionId;
            if ($target->isPublic() && $target->isDeprecated()) {
                $definition->addTag('container.private', $target->getDeprecation('%service_id%'));
            }
        }
        $this->replacements = $replacements;
        parent::process($container);
        $this->replacements = [];
    }
    protected function processValue(mixed $value, bool $isRoot = \false): mixed
    {
        if ($value instanceof Reference && isset($this->replacements[$referenceId = (string) $value])) {
            // Perform the replacement
            $newId = $this->replacements[$referenceId];
            $value = new Reference($newId, $value->getInvalidBehavior());
            $this->container->log($this, \sprintf('Changed reference of service "%s" previously pointing to "%s" to "%s".', $this->currentId, $referenceId, $newId));
        }
        return parent::processValue($value, $isRoot);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\DependencyInjection\Compiler;

use _ContaoManager\Symfony\Component\DependencyInjection\ChildDefinition;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Definition;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\ExceptionInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\RuntimeException;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\ServiceCircularReferenceException;
/**
 * This replaces all ChildDefinition instances with their equivalent fully
 * merged Definition instance.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 * @author Nicolas Grekas <p@tchwork.com>
 */
class ResolveChildDefinitionsPass extends AbstractRecursivePass
{
    protected bool $skipScalars = \true;
    private array $currentPath;
    protected function processValue(mixed $value, bool $isRoot = \false): mixed
    {
        if (!$value instanceof Definition) {
            return parent::processValue($value, $isRoot);
        }
        if ($isRoot) {
            // yes, we are specifically fetching the definition from the
            // container to ensure we are not operating on stale data
            $value = $this->container->getDefinition($this->currentId);
        }
        if ($value instanceof ChildDefinition) {
            $this->currentPath = [];
            $value = $this->resolveDefinition($value);
            if ($isRoot) {
                $this->container->setDefinition($this->currentId, $value);
            }
        }
        return parent::processValue($value, $isRoot);
    }
    /**
     * Resolves the definition.
     *
     * @throws RuntimeException When the definition is invalid
     */
    private function resolveDefinition(ChildDefinition $definition): Definition
    {
        try {
            return $this->doResolveDefinition($definition);
        } catch (ServiceCircularReferenceException $e) {
            throw $e;
        } catch (ExceptionInterface $e) {
            $r = new \ReflectionProperty($e, 'message');
            $r->setValue($e, \sprintf('Service "%s": %s', $this->currentId, $e->getMessage()));
            throw $e;
        }
    }
    private function doResolveDefinition(ChildDefinition $definition): Definition
    {
        if (!$this->container->has($parent = $definition->getParent())) {
            throw new RuntimeException(\sprintf('Parent definition "%s" does not exist.', $parent));
        }
        $searchKey = array_search($parent, $this->currentPath);
        $this->currentPath[] = $parent;
        if (\false !== $searchKey) {
            throw new ServiceCircularReferenceException($parent, \array_slice($this->currentPath, $searchKey));
        }
        $parentDef = $this->container->findDefinition($parent);
        if ($parentDef instanceof ChildDefinition) {
            $id = $this->currentId;
            $this->currentId = $parent;
            $parentDef = $this->resolveDefinition($parentDef);
            $this->container->setDefinition($parent, $parentDef);
            $this->currentId = $id;
        }
        $this->container->log($this, \sprintf('Resolving inheritance for "%s" (parent: %s).', $this->currentId, $parent));
        $def = new Definition();
        // merge in parent definition
        // purposely ignored attributes: abstract, shared, tags, autoconfigured
        $def->setClass($parentDef->getClass());
        $def->setArguments($parentDef->getArguments());
        $def->setMethodCalls($parentDef->getMethodCalls());
        $def->setProperties($parentDef->getProperties());
        if ($parentDef->isDeprecated()) {
            $deprecation = $parentDef->getDeprecation('%service_id%');
            $def->setDeprecated($deprecation['package'], $deprecation['version'], $deprecation['message']);
        }
        $def->setFactory($parentDef->getFactory());
        $def->setConfigurator($parentDef->getConfigurator());
        $def->setFile($parentDef->getFile());
        $def->setPublic($parentDef->isPublic());
        $def->setLazy($parentDef->isLazy());
        $def->setAutowired($parentDef->isAutowired());
        $def->setChanges($parentDef->getChanges());
        $def->setBindings($definition->getBindings() + $parentDef->getBindings());
        $def->setSynthetic($definition->isSynthetic());
        // overwrite with values specified in the decorator
        $changes = $definition->getChanges();
        if (isset($changes['class'])) {
            $def->setClass($definition->getClass());
        }
        if (isset($changes['factory'])) {
            $def->setFactory($definition->getFactory());
        }
        if (isset($changes['configurator'])) {
            $def->setConfigurator($definition->getConfigurator());
        }
        if (isset($changes['file'])) {
            $def->setFile($definition->getFile());
        }
        if (isset($changes['public'])) {
            $def->setPublic($definition->isPublic());
        } else {
            $def->setPublic($parentDef->isPublic());
        }
        if (isset($changes['lazy'])) {
            $def->setLazy($definition->isLazy());
        }
        if (isset($changes['deprecated']) && $definition->isDeprecated()) {
            $deprecation = $definition->getDeprecation('%service_id%');
            $def->setDeprecated($deprecation['package'], $deprecation['version'], $deprecation['message']);
        }
        if (isset($changes['autowired'])) {
            $def->setAutowired($definition->isAutowired());
        }
        if (isset($changes['shared'])) {
            $def->setShared($definition->isShared());
        }
        if (isset($changes['decorated_service'])) {
            $decoratedService = $definition->getDecoratedService();
            if (null === $decoratedService) {
                $def->setDecoratedService($decoratedService);
            } else {
                $def->setDecoratedService($decoratedService[0], $decoratedService[1], $decoratedService[2], $decoratedService[3] ?? ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE);
            }
        }
        // merge arguments
        foreach ($definition->getArguments() as $k => $v) {
            if (is_numeric($k)) {
                $def->addArgument($v);
            } elseif (str_starts_with($k, 'index_')) {
                $def->replaceArgument((int) substr($k, \strlen('index_')), $v);
            } else {
                $def->setArgument($k, $v);
            }
        }
        // merge properties
        foreach ($definition->getProperties() as $k => $v) {
            $def->setProperty($k, $v);
        }
        // append method calls
        if ($calls = $definition->getMethodCalls()) {
            $def->setMethodCalls(array_merge($def->getMethodCalls(), $calls));
        }
        $def->addError($parentDef);
        $def->addError($definition);
        // these attributes are always taken from the child
        $def->setAbstract($definition->isAbstract());
        $def->setTags($definition->getTags());
        // autoconfigure is never taken from parent (on purpose)
        // and it's not legal on an instanceof
        $def->setAutoconfigured($definition->isAutoconfigured());
        if (!$def->hasTag('proxy')) {
            foreach ($parentDef->getTag('proxy') as $v) {
                $def->addTag('proxy', $v);
            }
        }
        return $def;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\DependencyInjection\Compiler;

use _ContaoManager\Symfony\Component\DependencyInjection\ContainerBuilder;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\EnvParameterException;
/**
 * This class is used to remove circular dependencies between individual passes.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
class Compiler
{
    private PassConfig $passConfig;
    private array $log = [];
    private ServiceReferenceGraph $serviceReferenceGraph;
    public function __construct()
    {
        $this->passConfig = new PassConfig();
        $this->serviceReferenceGraph = new ServiceReferenceGraph();
    }
    public function getPassConfig(): PassConfig
    {
        return $this->passConfig;
    }
    public function getServiceReferenceGraph(): ServiceReferenceGraph
    {
        return $this->serviceReferenceGraph;
    }
    /**
     * @return void
     */
    public function addPass(CompilerPassInterface $pass, string $type = PassConfig::TYPE_BEFORE_OPTIMIZATION, int $priority = 0)
    {
        $this->passConfig->addPass($pass, $type, $priority);
    }
    /**
     * @final
     *
     * @return void
     */
    public function log(CompilerPassInterface $pass, string $message)
    {
        if (str_contains($message, "\n")) {
            $message = str_replace("\n", "\n" . $pass::class . ': ', trim($message));
        }
        $this->log[] = $pass::class . ': ' . $message;
    }
    public function getLog(): array
    {
        return $this->log;
    }
    /**
     * Run the Compiler and process all Passes.
     *
     * @return void
     */
    public function compile(ContainerBuilder $container)
    {
        try {
            foreach ($this->passConfig->getPasses() as $pass) {
                $pass->process($container);
            }
        } catch (\Exception $e) {
            $usedEnvs = [];
            $prev = $e;
            do {
                $msg = $prev->getMessage();
                if ($msg !== $resolvedMsg = $container->resolveEnvPlaceholders($msg, null, $usedEnvs)) {
                    $r = new \ReflectionProperty($prev, 'message');
                    $r->setValue($prev, $resolvedMsg);
                }
            } while ($prev = $prev->getPrevious());
            if ($usedEnvs) {
                $e = new EnvParameterException($usedEnvs, $e);
            }
            throw $e;
        } finally {
            $this->getServiceReferenceGraph()->clear();
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\DependencyInjection\Compiler;

use _ContaoManager\Symfony\Component\DependencyInjection\ContainerBuilder;
/**
 * A pass to automatically process extensions if they implement
 * CompilerPassInterface.
 *
 * @author Wouter J <wouter@wouterj.nl>
 */
class ExtensionCompilerPass implements CompilerPassInterface
{
    /**
     * @return void
     */
    public function process(ContainerBuilder $container)
    {
        foreach ($container->getExtensions() as $extension) {
            if (!$extension instanceof CompilerPassInterface) {
                continue;
            }
            $extension->process($container);
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\DependencyInjection\Compiler;

use _ContaoManager\Symfony\Component\DependencyInjection\Argument\ArgumentInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Argument\IteratorArgument;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerBuilder;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Definition;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\LogicException;
use _ContaoManager\Symfony\Component\DependencyInjection\Reference;
use _ContaoManager\Symfony\Component\ExpressionLanguage\Expression;
/**
 * Run this pass before passes that need to know more about the relation of
 * your services.
 *
 * This class will populate the ServiceReferenceGraph with information. You can
 * retrieve the graph in other passes from the compiler.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 * @author Nicolas Grekas <p@tchwork.com>
 */
class AnalyzeServiceReferencesPass extends AbstractRecursivePass
{
    protected bool $skipScalars = \true;
    private ServiceReferenceGraph $graph;
    private ?Definition $currentDefinition = null;
    private bool $onlyConstructorArguments;
    private bool $hasProxyDumper;
    private bool $lazy;
    private bool $byConstructor;
    private bool $byFactory;
    private bool $byMultiUseArgument;
    private array $definitions;
    private array $aliases;
    /**
     * @param bool $onlyConstructorArguments Sets this Service Reference pass to ignore method calls
     */
    public function __construct(bool $onlyConstructorArguments = \false, bool $hasProxyDumper = \true)
    {
        $this->onlyConstructorArguments = $onlyConstructorArguments;
        $this->hasProxyDumper = $hasProxyDumper;
        $this->enableExpressionProcessing();
    }
    /**
     * Processes a ContainerBuilder object to populate the service reference graph.
     *
     * @return void
     */
    public function process(ContainerBuilder $container)
    {
        $this->container = $container;
        $this->graph = $container->getCompiler()->getServiceReferenceGraph();
        $this->graph->clear();
        $this->lazy = \false;
        $this->byConstructor = \false;
        $this->byFactory = \false;
        $this->byMultiUseArgument = \false;
        $this->definitions = $container->getDefinitions();
        $this->aliases = $container->getAliases();
        foreach ($this->aliases as $id => $alias) {
            $targetId = $this->getDefinitionId((string) $alias);
            $this->graph->connect($id, $alias, $targetId, null !== $targetId ? $this->container->getDefinition($targetId) : null, null);
        }
        try {
            parent::process($container);
        } finally {
            $this->aliases = $this->definitions = [];
        }
    }
    protected function processValue(mixed $value, bool $isRoot = \false): mixed
    {
        $lazy = $this->lazy;
        $inExpression = $this->inExpression();
        if ($value instanceof ArgumentInterface) {
            $this->lazy = !$this->byFactory || !$value instanceof IteratorArgument;
            $byMultiUseArgument = $this->byMultiUseArgument;
            if ($value instanceof IteratorArgument) {
                $this->byMultiUseArgument = \true;
            }
            parent::processValue($value->getValues());
            $this->byMultiUseArgument = $byMultiUseArgument;
            $this->lazy = $lazy;
            return $value;
        }
        if ($value instanceof Reference) {
            $targetId = $this->getDefinitionId((string) $value);
            $targetDefinition = null !== $targetId ? $this->container->getDefinition($targetId) : null;
            $this->graph->connect($this->currentId, $this->currentDefinition, $targetId, $targetDefinition, $value, $this->lazy || $this->hasProxyDumper && $targetDefinition?->isLazy(), ContainerInterface::IGNORE_ON_UNINITIALIZED_REFERENCE === $value->getInvalidBehavior(), $this->byConstructor, $this->byMultiUseArgument);
            if ($inExpression) {
                $this->graph->connect('.internal.reference_in_expression', null, $targetId, $targetDefinition, $value, $this->lazy || $targetDefinition?->isLazy(), \true, $this->byConstructor, $this->byMultiUseArgument);
            }
            return $value;
        }
        if (!$value instanceof Definition) {
            return parent::processValue($value, $isRoot);
        }
        if ($isRoot) {
            if ($value->isSynthetic() || $value->isAbstract()) {
                return $value;
            }
            $this->currentDefinition = $value;
        } elseif ($this->currentDefinition === $value) {
            return $value;
        }
        $this->lazy = \false;
        $byConstructor = $this->byConstructor;
        $this->byConstructor = $isRoot || $byConstructor;
        $byFactory = $this->byFactory;
        $this->byFactory = \true;
        if (\is_string($factory = $value->getFactory()) && str_starts_with($factory, '@=')) {
            if (!class_exists(Expression::class)) {
                throw new LogicException('Expressions cannot be used in service factories without the ExpressionLanguage component. Try running "composer require symfony/expression-language".');
            }
            $factory = new Expression(substr($factory, 2));
        }
        $this->processValue($factory);
        $this->byFactory = $byFactory;
        $this->processValue($value->getArguments());
        $properties = $value->getProperties();
        $setters = $value->getMethodCalls();
        // Any references before a "wither" are part of the constructor-instantiation graph
        $lastWitherIndex = null;
        foreach ($setters as $k => $call) {
            if ($call[2] ?? \false) {
                $lastWitherIndex = $k;
            }
        }
        if (null !== $lastWitherIndex) {
            $this->processValue($properties);
            $setters = $properties = [];
            foreach ($value->getMethodCalls() as $k => $call) {
                if (null === $lastWitherIndex) {
                    $setters[] = $call;
                    continue;
                }
                if ($lastWitherIndex === $k) {
                    $lastWitherIndex = null;
                }
                $this->processValue($call);
            }
        }
        $this->byConstructor = $byConstructor;
        if (!$this->onlyConstructorArguments) {
            $this->processValue($properties);
            $this->processValue($setters);
            $this->processValue($value->getConfigurator());
        }
        $this->lazy = $lazy;
        return $value;
    }
    private function getDefinitionId(string $id): ?string
    {
        while (isset($this->aliases[$id])) {
            $id = (string) $this->aliases[$id];
        }
        return isset($this->definitions[$id]) ? $id : null;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\DependencyInjection\Compiler;

use _ContaoManager\Symfony\Component\DependencyInjection\Definition;
use _ContaoManager\Symfony\Contracts\Service\Attribute\Required;
/**
 * Looks for definitions with autowiring enabled and registers their corresponding "#[Required]" methods as setters.
 *
 * @author Nicolas Grekas <p@tchwork.com>
 */
class AutowireRequiredMethodsPass extends AbstractRecursivePass
{
    protected bool $skipScalars = \true;
    protected function processValue(mixed $value, bool $isRoot = \false): mixed
    {
        $value = parent::processValue($value, $isRoot);
        if (!$value instanceof Definition || !$value->isAutowired() || $value->isAbstract() || !$value->getClass()) {
            return $value;
        }
        if (!$reflectionClass = $this->container->getReflectionClass($value->getClass(), \false)) {
            return $value;
        }
        $alreadyCalledMethods = [];
        $withers = [];
        foreach ($value->getMethodCalls() as [$method]) {
            $alreadyCalledMethods[strtolower($method)] = \true;
        }
        foreach ($reflectionClass->getMethods() as $reflectionMethod) {
            $r = $reflectionMethod;
            if ($r->isConstructor() || isset($alreadyCalledMethods[strtolower($r->name)])) {
                continue;
            }
            while (\true) {
                if ($r->getAttributes(Required::class)) {
                    if ($this->isWither($r, $r->getDocComment() ?: '')) {
                        $withers[] = [$r->name, [], \true];
                    } else {
                        $value->addMethodCall($r->name, []);
                    }
                    break;
                }
                if (\false !== $doc = $r->getDocComment()) {
                    if (\false !== stripos($doc, '@required') && preg_match('#(?:^/\*\*|\n\s*+\*)\s*+@required(?:\s|\*/$)#i', $doc)) {
                        trigger_deprecation('symfony/dependency-injection', '6.3', 'Relying on the "@required" annotation on method "%s::%s()" is deprecated, use the "Symfony\Contracts\Service\Attribute\Required" attribute instead.', $reflectionMethod->class, $reflectionMethod->name);
                        if ($this->isWither($reflectionMethod, $doc)) {
                            $withers[] = [$reflectionMethod->name, [], \true];
                        } else {
                            $value->addMethodCall($reflectionMethod->name, []);
                        }
                        break;
                    }
                    if (\false === stripos($doc, '@inheritdoc') || !preg_match('#(?:^/\*\*|\n\s*+\*)\s*+(?:\{@inheritdoc\}|@inheritdoc)(?:\s|\*/$)#i', $doc)) {
                        break;
                    }
                }
                try {
                    $r = $r->getPrototype();
                } catch (\ReflectionException) {
                    break;
                    // method has no prototype
                }
            }
        }
        if ($withers) {
            // Prepend withers to prevent creating circular loops
            $setters = $value->getMethodCalls();
            $value->setMethodCalls($withers);
            foreach ($setters as $call) {
                $value->addMethodCall($call[0], $call[1], $call[2] ?? \false);
            }
        }
        return $value;
    }
    private function isWither(\ReflectionMethod $reflectionMethod, string $doc): bool
    {
        $match = preg_match('#(?:^/\*\*|\n\s*+\*)\s*+@return\s++(static|\$this)[\s\*]#i', $doc, $matches);
        if ($match && 'static' === $matches[1]) {
            return \true;
        }
        if ($match && '$this' === $matches[1]) {
            return \false;
        }
        $reflectionType = $reflectionMethod->hasReturnType() ? $reflectionMethod->getReturnType() : null;
        return $reflectionType instanceof \ReflectionNamedType && 'static' === $reflectionType->getName();
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\DependencyInjection\Dumper;

use _ContaoManager\Symfony\Component\DependencyInjection\Argument\ArgumentInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerBuilder;
use _ContaoManager\Symfony\Component\DependencyInjection\Definition;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\ParameterNotFoundException;
use _ContaoManager\Symfony\Component\DependencyInjection\Parameter;
use _ContaoManager\Symfony\Component\DependencyInjection\ParameterBag\ParameterBag;
use _ContaoManager\Symfony\Component\DependencyInjection\Reference;
/**
 * GraphvizDumper dumps a service container as a graphviz file.
 *
 * You can convert the generated dot file with the dot utility (http://www.graphviz.org/):
 *
 *   dot -Tpng container.dot > foo.png
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class GraphvizDumper extends Dumper
{
    private array $nodes;
    private array $edges;
    // All values should be strings
    private array $options = ['graph' => ['ratio' => 'compress'], 'node' => ['fontsize' => '11', 'fontname' => 'Arial', 'shape' => 'record'], 'edge' => ['fontsize' => '9', 'fontname' => 'Arial', 'color' => 'grey', 'arrowhead' => 'open', 'arrowsize' => '0.5'], 'node.instance' => ['fillcolor' => '#9999ff', 'style' => 'filled'], 'node.definition' => ['fillcolor' => '#eeeeee'], 'node.missing' => ['fillcolor' => '#ff9999', 'style' => 'filled']];
    /**
     * Dumps the service container as a graphviz graph.
     *
     * Available options:
     *
     *  * graph: The default options for the whole graph
     *  * node: The default options for nodes
     *  * edge: The default options for edges
     *  * node.instance: The default options for services that are defined directly by object instances
     *  * node.definition: The default options for services that are defined via service definition instances
     *  * node.missing: The default options for missing services
     */
    public function dump(array $options = []): string
    {
        foreach (['graph', 'node', 'edge', 'node.instance', 'node.definition', 'node.missing'] as $key) {
            if (isset($options[$key])) {
                $this->options[$key] = array_merge($this->options[$key], $options[$key]);
            }
        }
        $this->nodes = $this->findNodes();
        $this->edges = [];
        foreach ($this->container->getDefinitions() as $id => $definition) {
            $this->edges[$id] = array_merge($this->findEdges($id, $definition->getArguments(), \true, ''), $this->findEdges($id, $definition->getProperties(), \false, ''));
            foreach ($definition->getMethodCalls() as $call) {
                $this->edges[$id] = array_merge($this->edges[$id], $this->findEdges($id, $call[1], \false, $call[0] . '()'));
            }
        }
        return $this->container->resolveEnvPlaceholders($this->startDot() . $this->addNodes() . $this->addEdges() . $this->endDot(), '__ENV_%s__');
    }
    private function addNodes(): string
    {
        $code = '';
        foreach ($this->nodes as $id => $node) {
            $aliases = $this->getAliases($id);
            $code .= \sprintf("  node_%s [label=\"%s\\n%s\\n\", shape=%s%s];\n", $this->dotize($id), $id . ($aliases ? ' (' . implode(', ', $aliases) . ')' : ''), $node['class'], $this->options['node']['shape'], $this->addAttributes($node['attributes']));
        }
        return $code;
    }
    private function addEdges(): string
    {
        $code = '';
        foreach ($this->edges as $id => $edges) {
            foreach ($edges as $edge) {
                $code .= \sprintf("  node_%s -> node_%s [label=\"%s\" style=\"%s\"%s];\n", $this->dotize($id), $this->dotize($edge['to']), $edge['name'], $edge['required'] ? 'filled' : 'dashed', $edge['lazy'] ? ' color="#9999ff"' : '');
            }
        }
        return $code;
    }
    /**
     * Finds all edges belonging to a specific service id.
     */
    private function findEdges(string $id, array $arguments, bool $required, string $name, bool $lazy = \false): array
    {
        $edges = [];
        foreach ($arguments as $argument) {
            if ($argument instanceof Parameter) {
                $argument = $this->container->hasParameter($argument) ? $this->container->getParameter($argument) : null;
            } elseif (\is_string($argument) && preg_match('/^%([^%]+)%$/', $argument, $match)) {
                $argument = $this->container->hasParameter($match[1]) ? $this->container->getParameter($match[1]) : null;
            }
            if ($argument instanceof Reference) {
                $lazyEdge = $lazy;
                if (!$this->container->has((string) $argument)) {
                    $this->nodes[(string) $argument] = ['name' => $name, 'required' => $required, 'class' => '', 'attributes' => $this->options['node.missing']];
                } elseif ('service_container' !== (string) $argument) {
                    $lazyEdge = $lazy || $this->container->getDefinition((string) $argument)->isLazy();
                }
                $edges[] = [['name' => $name, 'required' => $required, 'to' => $argument, 'lazy' => $lazyEdge]];
            } elseif ($argument instanceof ArgumentInterface) {
                $edges[] = $this->findEdges($id, $argument->getValues(), $required, $name, \true);
            } elseif ($argument instanceof Definition) {
                $edges[] = $this->findEdges($id, $argument->getArguments(), $required, '');
                $edges[] = $this->findEdges($id, $argument->getProperties(), \false, '');
                foreach ($argument->getMethodCalls() as $call) {
                    $edges[] = $this->findEdges($id, $call[1], \false, $call[0] . '()');
                }
            } elseif (\is_array($argument)) {
                $edges[] = $this->findEdges($id, $argument, $required, $name, $lazy);
            }
        }
        return array_merge([], ...$edges);
    }
    private function findNodes(): array
    {
        $nodes = [];
        $container = $this->cloneContainer();
        foreach ($container->getDefinitions() as $id => $definition) {
            $class = $definition->getClass();
            if (str_starts_with($class, '\\')) {
                $class = substr($class, 1);
            }
            try {
                $class = $this->container->getParameterBag()->resolveValue($class);
            } catch (ParameterNotFoundException) {
            }
            $nodes[$id] = ['class' => str_replace('\\', '\\\\', $class), 'attributes' => array_merge($this->options['node.definition'], ['style' => $definition->isShared() ? 'filled' : 'dotted'])];
            $container->setDefinition($id, new Definition('stdClass'));
        }
        foreach ($container->getServiceIds() as $id) {
            if (\array_key_exists($id, $container->getAliases())) {
                continue;
            }
            if (!$container->hasDefinition($id)) {
                $nodes[$id] = ['class' => str_replace('\\', '\\\\', $container->get($id)::class), 'attributes' => $this->options['node.instance']];
            }
        }
        return $nodes;
    }
    private function cloneContainer(): ContainerBuilder
    {
        $parameterBag = new ParameterBag($this->container->getParameterBag()->all());
        $container = new ContainerBuilder($parameterBag);
        $container->setDefinitions($this->container->getDefinitions());
        $container->setAliases($this->container->getAliases());
        $container->setResources($this->container->getResources());
        foreach ($this->container->getExtensions() as $extension) {
            $container->registerExtension($extension);
        }
        return $container;
    }
    private function startDot(): string
    {
        return \sprintf("digraph sc {\n  %s\n  node [%s];\n  edge [%s];\n\n", $this->addOptions($this->options['graph']), $this->addOptions($this->options['node']), $this->addOptions($this->options['edge']));
    }
    private function endDot(): string
    {
        return "}\n";
    }
    private function addAttributes(array $attributes): string
    {
        $code = [];
        foreach ($attributes as $k => $v) {
            $code[] = \sprintf('%s="%s"', $k, $v);
        }
        return $code ? ', ' . implode(', ', $code) : '';
    }
    private function addOptions(array $options): string
    {
        $code = [];
        foreach ($options as $k => $v) {
            $code[] = \sprintf('%s="%s"', $k, $v);
        }
        return implode(' ', $code);
    }
    private function dotize(string $id): string
    {
        return preg_replace('/\W/i', '_', $id);
    }
    private function getAliases(string $id): array
    {
        $aliases = [];
        foreach ($this->container->getAliases() as $alias => $origin) {
            if ($id == $origin) {
                $aliases[] = $alias;
            }
        }
        return $aliases;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\DependencyInjection\Dumper;

use _ContaoManager\Symfony\Component\DependencyInjection\Alias;
use _ContaoManager\Symfony\Component\DependencyInjection\Argument\AbstractArgument;
use _ContaoManager\Symfony\Component\DependencyInjection\Argument\ArgumentInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Argument\IteratorArgument;
use _ContaoManager\Symfony\Component\DependencyInjection\Argument\ServiceClosureArgument;
use _ContaoManager\Symfony\Component\DependencyInjection\Argument\ServiceLocatorArgument;
use _ContaoManager\Symfony\Component\DependencyInjection\Argument\TaggedIteratorArgument;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Definition;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\LogicException;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\RuntimeException;
use _ContaoManager\Symfony\Component\DependencyInjection\Parameter;
use _ContaoManager\Symfony\Component\DependencyInjection\Reference;
use _ContaoManager\Symfony\Component\ExpressionLanguage\Expression;
use _ContaoManager\Symfony\Component\Yaml\Dumper as YmlDumper;
use _ContaoManager\Symfony\Component\Yaml\Parser;
use _ContaoManager\Symfony\Component\Yaml\Tag\TaggedValue;
use _ContaoManager\Symfony\Component\Yaml\Yaml;
/**
 * YamlDumper dumps a service container as a YAML string.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class YamlDumper extends Dumper
{
    private YmlDumper $dumper;
    /**
     * Dumps the service container as an YAML string.
     */
    public function dump(array $options = []): string
    {
        if (!class_exists(YmlDumper::class)) {
            throw new LogicException('Unable to dump the container as the Symfony Yaml Component is not installed. Try running "composer require symfony/yaml".');
        }
        $this->dumper ??= new YmlDumper();
        return $this->addParameters() . "\n" . $this->addServices();
    }
    private function addService(string $id, Definition $definition): string
    {
        $code = "    {$this->dumper->dump($id)}:\n";
        if ($class = $definition->getClass()) {
            if (str_starts_with($class, '\\')) {
                $class = substr($class, 1);
            }
            $code .= \sprintf("        class: %s\n", $this->dumper->dump($this->container->resolveEnvPlaceholders($class)));
        }
        if (!$definition->isPrivate()) {
            $code .= \sprintf("        public: %s\n", $definition->isPublic() ? 'true' : 'false');
        }
        $tagsCode = '';
        $tags = $definition->getTags();
        $tags['container.error'] = array_map(fn($e) => ['message' => $e], $definition->getErrors());
        foreach ($tags as $name => $tags) {
            foreach ($tags as $attributes) {
                $att = [];
                foreach ($attributes as $key => $value) {
                    $att[] = \sprintf('%s: %s', $this->dumper->dump($key), $this->dumper->dump($value));
                }
                $att = $att ? ': { ' . implode(', ', $att) . ' }' : '';
                $tagsCode .= \sprintf("            - %s%s\n", $this->dumper->dump($name), $att);
            }
        }
        if ($tagsCode) {
            $code .= "        tags:\n" . $tagsCode;
        }
        if ($definition->getFile()) {
            $code .= \sprintf("        file: %s\n", $this->dumper->dump($this->container->resolveEnvPlaceholders($definition->getFile())));
        }
        if ($definition->isSynthetic()) {
            $code .= "        synthetic: true\n";
        }
        if ($definition->isDeprecated()) {
            $code .= "        deprecated:\n";
            foreach ($definition->getDeprecation('%service_id%') as $key => $value) {
                if ('' !== $value) {
                    $code .= \sprintf("            %s: %s\n", $key, $this->dumper->dump($value));
                }
            }
        }
        if ($definition->isAutowired()) {
            $code .= "        autowire: true\n";
        }
        if ($definition->isAutoconfigured()) {
            $code .= "        autoconfigure: true\n";
        }
        if ($definition->isAbstract()) {
            $code .= "        abstract: true\n";
        }
        if ($definition->isLazy()) {
            $code .= "        lazy: true\n";
        }
        if ($definition->getArguments()) {
            $code .= \sprintf("        arguments: %s\n", $this->dumper->dump($this->dumpValue($definition->getArguments()), 0));
        }
        if ($definition->getProperties()) {
            $code .= \sprintf("        properties: %s\n", $this->dumper->dump($this->dumpValue($definition->getProperties()), 0));
        }
        if ($definition->getMethodCalls()) {
            $code .= \sprintf("        calls:\n%s\n", $this->dumper->dump($this->dumpValue($definition->getMethodCalls()), 1, 12));
        }
        if (!$definition->isShared()) {
            $code .= "        shared: false\n";
        }
        if (null !== $decoratedService = $definition->getDecoratedService()) {
            [$decorated, $renamedId, $priority] = $decoratedService;
            $code .= \sprintf("        decorates: %s\n", $decorated);
            if (null !== $renamedId) {
                $code .= \sprintf("        decoration_inner_name: %s\n", $renamedId);
            }
            if (0 !== $priority) {
                $code .= \sprintf("        decoration_priority: %s\n", $priority);
            }
            $decorationOnInvalid = $decoratedService[3] ?? ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE;
            if (\in_array($decorationOnInvalid, [ContainerInterface::IGNORE_ON_INVALID_REFERENCE, ContainerInterface::NULL_ON_INVALID_REFERENCE])) {
                $invalidBehavior = ContainerInterface::NULL_ON_INVALID_REFERENCE === $decorationOnInvalid ? 'null' : 'ignore';
                $code .= \sprintf("        decoration_on_invalid: %s\n", $invalidBehavior);
            }
        }
        if ($callable = $definition->getFactory()) {
            if (\is_array($callable) && ['Closure', 'fromCallable'] !== $callable && $definition->getClass() === $callable[0]) {
                $code .= \sprintf("        constructor: %s\n", $callable[1]);
            } else {
                $code .= \sprintf("        factory: %s\n", $this->dumper->dump($this->dumpCallable($callable), 0));
            }
        }
        if ($callable = $definition->getConfigurator()) {
            $code .= \sprintf("        configurator: %s\n", $this->dumper->dump($this->dumpCallable($callable), 0));
        }
        return $code;
    }
    private function addServiceAlias(string $alias, Alias $id): string
    {
        $deprecated = '';
        if ($id->isDeprecated()) {
            $deprecated = "        deprecated:\n";
            foreach ($id->getDeprecation('%alias_id%') as $key => $value) {
                if ('' !== $value) {
                    $deprecated .= \sprintf("            %s: %s\n", $key, $value);
                }
            }
        }
        if (!$id->isDeprecated() && $id->isPrivate()) {
            return \sprintf("    %s: '@%s'\n", $alias, $id);
        }
        if ($id->isPublic()) {
            $deprecated = "        public: true\n" . $deprecated;
        }
        return \sprintf("    %s:\n        alias: %s\n%s", $alias, $id, $deprecated);
    }
    private function addServices(): string
    {
        if (!$this->container->getDefinitions()) {
            return '';
        }
        $code = "services:\n";
        foreach ($this->container->getDefinitions() as $id => $definition) {
            $code .= $this->addService($id, $definition);
        }
        $aliases = $this->container->getAliases();
        foreach ($aliases as $alias => $id) {
            while (isset($aliases[(string) $id])) {
                $id = $aliases[(string) $id];
            }
            $code .= $this->addServiceAlias($alias, $id);
        }
        return $code;
    }
    private function addParameters(): string
    {
        if (!$this->container->getParameterBag()->all()) {
            return '';
        }
        $parameters = $this->prepareParameters($this->container->getParameterBag()->all(), $this->container->isCompiled());
        return $this->dumper->dump(['parameters' => $parameters], 2);
    }
    /**
     * Dumps callable to YAML format.
     */
    private function dumpCallable(mixed $callable): mixed
    {
        if (\is_array($callable)) {
            if ($callable[0] instanceof Reference) {
                $callable = [$this->getServiceCall((string) $callable[0], $callable[0]), $callable[1]];
            } else {
                $callable = [$callable[0], $callable[1]];
            }
        }
        return $this->container->resolveEnvPlaceholders($callable);
    }
    /**
     * Dumps the value to YAML format.
     *
     * @throws RuntimeException When trying to dump object or resource
     */
    private function dumpValue(mixed $value): mixed
    {
        if ($value instanceof ServiceClosureArgument) {
            $value = $value->getValues()[0];
            return new TaggedValue('service_closure', $this->dumpValue($value));
        }
        if ($value instanceof ArgumentInterface) {
            $tag = $value;
            if ($value instanceof TaggedIteratorArgument || $value instanceof ServiceLocatorArgument && $tag = $value->getTaggedIteratorArgument()) {
                if (null === $tag->getIndexAttribute()) {
                    $content = $tag->getTag();
                } else {
                    $content = ['tag' => $tag->getTag(), 'index_by' => $tag->getIndexAttribute()];
                    if (null !== $tag->getDefaultIndexMethod()) {
                        $content['default_index_method'] = $tag->getDefaultIndexMethod();
                    }
                    if (null !== $tag->getDefaultPriorityMethod()) {
                        $content['default_priority_method'] = $tag->getDefaultPriorityMethod();
                    }
                }
                if ($excludes = $tag->getExclude()) {
                    if (!\is_array($content)) {
                        $content = ['tag' => $content];
                    }
                    $content['exclude'] = 1 === \count($excludes) ? $excludes[0] : $excludes;
                }
                if (!$tag->excludeSelf()) {
                    $content['exclude_self'] = \false;
                }
                return new TaggedValue($value instanceof TaggedIteratorArgument ? 'tagged_iterator' : 'tagged_locator', $content);
            }
            if ($value instanceof IteratorArgument) {
                $tag = 'iterator';
            } elseif ($value instanceof ServiceLocatorArgument) {
                $tag = 'service_locator';
            } else {
                throw new RuntimeException(\sprintf('Unspecified Yaml tag for type "%s".', get_debug_type($value)));
            }
            return new TaggedValue($tag, $this->dumpValue($value->getValues()));
        }
        if (\is_array($value)) {
            $code = [];
            foreach ($value as $k => $v) {
                $code[$this->container->resolveEnvPlaceholders($k)] = $this->dumpValue($v);
            }
            return $code;
        } elseif ($value instanceof Reference) {
            return $this->getServiceCall((string) $value, $value);
        } elseif ($value instanceof Parameter) {
            return $this->getParameterCall((string) $value);
        } elseif ($value instanceof Expression) {
            return $this->getExpressionCall((string) $value);
        } elseif ($value instanceof Definition) {
            return new TaggedValue('service', (new Parser())->parse("_:\n" . $this->addService('_', $value), Yaml::PARSE_CUSTOM_TAGS)['_']['_']);
        } elseif ($value instanceof \UnitEnum) {
            return new TaggedValue('php/const', \sprintf('%s::%s', $value::class, $value->name));
        } elseif ($value instanceof AbstractArgument) {
            return new TaggedValue('abstract', $value->getText());
        } elseif (\is_object($value) || \is_resource($value)) {
            throw new RuntimeException(\sprintf('Unable to dump a service container if a parameter is an object or a resource, got "%s".', get_debug_type($value)));
        }
        return $this->container->resolveEnvPlaceholders($value);
    }
    private function getServiceCall(string $id, ?Reference $reference = null): string
    {
        if (null !== $reference) {
            switch ($reference->getInvalidBehavior()) {
                case ContainerInterface::RUNTIME_EXCEPTION_ON_INVALID_REFERENCE:
                    break;
                case ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE:
                    break;
                case ContainerInterface::IGNORE_ON_UNINITIALIZED_REFERENCE:
                    return \sprintf('@!%s', $id);
                default:
                    return \sprintf('@?%s', $id);
            }
        }
        return \sprintf('@%s', $id);
    }
    private function getParameterCall(string $id): string
    {
        return \sprintf('%%%s%%', $id);
    }
    private function getExpressionCall(string $expression): string
    {
        return \sprintf('@=%s', $expression);
    }
    private function prepareParameters(array $parameters, bool $escape = \true): array
    {
        $filtered = [];
        foreach ($parameters as $key => $value) {
            if (\is_array($value)) {
                $value = $this->prepareParameters($value, $escape);
            } elseif ($value instanceof Reference || \is_string($value) && str_starts_with($value, '@')) {
                $value = '@' . $value;
            }
            $filtered[$key] = $value;
        }
        return $escape ? $this->container->resolveEnvPlaceholders($this->escape($filtered)) : $filtered;
    }
    private function escape(array $arguments): array
    {
        $args = [];
        foreach ($arguments as $k => $v) {
            if (\is_array($v)) {
                $args[$k] = $this->escape($v);
            } elseif (\is_string($v)) {
                $args[$k] = str_replace('%', '%%', $v);
            } else {
                $args[$k] = $v;
            }
        }
        return $args;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\DependencyInjection\Dumper;

/**
 * @author Nicolas Grekas <p@tchwork.com>
 */
final class Preloader
{
    public static function append(string $file, array $list): void
    {
        if (!file_exists($file)) {
            throw new \LogicException(\sprintf('File "%s" does not exist.', $file));
        }
        $cacheDir = \dirname($file);
        $classes = [];
        foreach ($list as $item) {
            if (str_starts_with($item, $cacheDir)) {
                file_put_contents($file, \sprintf("require_once __DIR__.%s;\n", var_export(strtr(substr($item, \strlen($cacheDir)), \DIRECTORY_SEPARATOR, '/'), \true)), \FILE_APPEND);
                continue;
            }
            $classes[] = \sprintf("\$classes[] = %s;\n", var_export($item, \true));
        }
        file_put_contents($file, \sprintf("\n\$classes = [];\n%s\$preloaded = Preloader::preload(\$classes, \$preloaded);\n", implode('', $classes)), \FILE_APPEND);
    }
    public static function preload(array $classes, array $preloaded = []): array
    {
        set_error_handler(function ($t, $m, $f, $l) {
            if (error_reporting() & $t) {
                if (__FILE__ !== $f) {
                    throw new \ErrorException($m, 0, $t, $f, $l);
                }
                throw new \ReflectionException($m);
            }
        });
        $prev = [];
        try {
            while ($prev !== $classes) {
                $prev = $classes;
                foreach ($classes as $c) {
                    if (!isset($preloaded[$c])) {
                        self::doPreload($c, $preloaded);
                    }
                }
                $classes = array_merge(get_declared_classes(), get_declared_interfaces(), get_declared_traits());
            }
        } finally {
            restore_error_handler();
        }
        return $preloaded;
    }
    private static function doPreload(string $class, array &$preloaded): void
    {
        if (isset($preloaded[$class]) || \in_array($class, ['self', 'static', 'parent'], \true)) {
            return;
        }
        $preloaded[$class] = \true;
        try {
            if (!class_exists($class) && !interface_exists($class, \false) && !trait_exists($class, \false)) {
                return;
            }
            $r = new \ReflectionClass($class);
            if ($r->isInternal()) {
                return;
            }
            $r->getConstants();
            $r->getDefaultProperties();
            foreach ($r->getProperties(\ReflectionProperty::IS_PUBLIC) as $p) {
                self::preloadType($p->getType(), $preloaded);
            }
            foreach ($r->getMethods(\ReflectionMethod::IS_PUBLIC) as $m) {
                foreach ($m->getParameters() as $p) {
                    if ($p->isDefaultValueAvailable() && $p->isDefaultValueConstant()) {
                        $c = $p->getDefaultValueConstantName();
                        if ($i = strpos($c, '::')) {
                            self::doPreload(substr($c, 0, $i), $preloaded);
                        }
                    }
                    self::preloadType($p->getType(), $preloaded);
                }
                self::preloadType($m->getReturnType(), $preloaded);
            }
        } catch (\Throwable) {
            // ignore missing classes
        }
    }
    private static function preloadType(?\ReflectionType $t, array &$preloaded): void
    {
        if (!$t) {
            return;
        }
        foreach ($t instanceof \ReflectionUnionType || $t instanceof \ReflectionIntersectionType ? $t->getTypes() : [$t] as $t) {
            if (!$t->isBuiltin()) {
                self::doPreload($t instanceof \ReflectionNamedType ? $t->getName() : $t, $preloaded);
            }
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\DependencyInjection\Dumper;

use _ContaoManager\Symfony\Component\DependencyInjection\Alias;
use _ContaoManager\Symfony\Component\DependencyInjection\Argument\AbstractArgument;
use _ContaoManager\Symfony\Component\DependencyInjection\Argument\IteratorArgument;
use _ContaoManager\Symfony\Component\DependencyInjection\Argument\ServiceClosureArgument;
use _ContaoManager\Symfony\Component\DependencyInjection\Argument\ServiceLocatorArgument;
use _ContaoManager\Symfony\Component\DependencyInjection\Argument\TaggedIteratorArgument;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Definition;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\RuntimeException;
use _ContaoManager\Symfony\Component\DependencyInjection\Parameter;
use _ContaoManager\Symfony\Component\DependencyInjection\Reference;
use _ContaoManager\Symfony\Component\ExpressionLanguage\Expression;
/**
 * XmlDumper dumps a service container as an XML string.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 * @author Martin Hasoň <martin.hason@gmail.com>
 */
class XmlDumper extends Dumper
{
    private \DOMDocument $document;
    /**
     * Dumps the service container as an XML string.
     */
    public function dump(array $options = []): string
    {
        $this->document = new \DOMDocument('1.0', 'utf-8');
        $this->document->formatOutput = \true;
        $container = $this->document->createElementNS('http://symfony.com/schema/dic/services', 'container');
        $container->setAttribute('xmlns:xsi', 'http://www.w3.org/2001/XMLSchema-instance');
        $container->setAttribute('xsi:schemaLocation', 'http://symfony.com/schema/dic/services https://symfony.com/schema/dic/services/services-1.0.xsd');
        $this->addParameters($container);
        $this->addServices($container);
        $this->document->appendChild($container);
        $xml = $this->document->saveXML();
        unset($this->document);
        return $this->container->resolveEnvPlaceholders($xml);
    }
    private function addParameters(\DOMElement $parent): void
    {
        $data = $this->container->getParameterBag()->all();
        if (!$data) {
            return;
        }
        if ($this->container->isCompiled()) {
            $data = $this->escape($data);
        }
        $parameters = $this->document->createElement('parameters');
        $parent->appendChild($parameters);
        $this->convertParameters($data, 'parameter', $parameters);
    }
    private function addMethodCalls(array $methodcalls, \DOMElement $parent): void
    {
        foreach ($methodcalls as $methodcall) {
            $call = $this->document->createElement('call');
            $call->setAttribute('method', $methodcall[0]);
            if (\count($methodcall[1])) {
                $this->convertParameters($methodcall[1], 'argument', $call);
            }
            if ($methodcall[2] ?? \false) {
                $call->setAttribute('returns-clone', 'true');
            }
            $parent->appendChild($call);
        }
    }
    private function addService(Definition $definition, ?string $id, \DOMElement $parent): void
    {
        $service = $this->document->createElement('service');
        if (null !== $id) {
            $service->setAttribute('id', $id);
        }
        if ($class = $definition->getClass()) {
            if (str_starts_with($class, '\\')) {
                $class = substr($class, 1);
            }
            $service->setAttribute('class', $class);
        }
        if (!$definition->isShared()) {
            $service->setAttribute('shared', 'false');
        }
        if ($definition->isPublic()) {
            $service->setAttribute('public', 'true');
        }
        if ($definition->isSynthetic()) {
            $service->setAttribute('synthetic', 'true');
        }
        if ($definition->isLazy()) {
            $service->setAttribute('lazy', 'true');
        }
        if (null !== $decoratedService = $definition->getDecoratedService()) {
            [$decorated, $renamedId, $priority] = $decoratedService;
            $service->setAttribute('decorates', $decorated);
            $decorationOnInvalid = $decoratedService[3] ?? ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE;
            if (\in_array($decorationOnInvalid, [ContainerInterface::IGNORE_ON_INVALID_REFERENCE, ContainerInterface::NULL_ON_INVALID_REFERENCE], \true)) {
                $invalidBehavior = ContainerInterface::NULL_ON_INVALID_REFERENCE === $decorationOnInvalid ? 'null' : 'ignore';
                $service->setAttribute('decoration-on-invalid', $invalidBehavior);
            }
            if (null !== $renamedId) {
                $service->setAttribute('decoration-inner-name', $renamedId);
            }
            if (0 !== $priority) {
                $service->setAttribute('decoration-priority', $priority);
            }
        }
        $tags = $definition->getTags();
        $tags['container.error'] = array_map(fn($e) => ['message' => $e], $definition->getErrors());
        foreach ($tags as $name => $tags) {
            foreach ($tags as $attributes) {
                $tag = $this->document->createElement('tag');
                // Check if we have recursive attributes
                if (array_filter($attributes, \is_array(...))) {
                    $tag->setAttribute('name', $name);
                    $this->addTagRecursiveAttributes($tag, $attributes);
                } else {
                    if (!\array_key_exists('name', $attributes)) {
                        $tag->setAttribute('name', $name);
                    } else {
                        $tag->appendChild($this->document->createTextNode($name));
                    }
                    foreach ($attributes as $key => $value) {
                        $tag->setAttribute($key, $value ?? '');
                    }
                }
                $service->appendChild($tag);
            }
        }
        if ($definition->getFile()) {
            $file = $this->document->createElement('file');
            $file->appendChild($this->document->createTextNode($definition->getFile()));
            $service->appendChild($file);
        }
        if ($parameters = $definition->getArguments()) {
            $this->convertParameters($parameters, 'argument', $service);
        }
        if ($parameters = $definition->getProperties()) {
            $this->convertParameters($parameters, 'property', $service, 'name');
        }
        $this->addMethodCalls($definition->getMethodCalls(), $service);
        if ($callable = $definition->getFactory()) {
            if (\is_array($callable) && ['Closure', 'fromCallable'] !== $callable && $definition->getClass() === $callable[0]) {
                $service->setAttribute('constructor', $callable[1]);
            } else {
                $factory = $this->document->createElement('factory');
                if (\is_array($callable) && $callable[0] instanceof Definition) {
                    $this->addService($callable[0], null, $factory);
                    $factory->setAttribute('method', $callable[1]);
                } elseif (\is_array($callable)) {
                    if (null !== $callable[0]) {
                        $factory->setAttribute($callable[0] instanceof Reference ? 'service' : 'class', $callable[0]);
                    }
                    $factory->setAttribute('method', $callable[1]);
                } else {
                    $factory->setAttribute('function', $callable);
                }
                $service->appendChild($factory);
            }
        }
        if ($definition->isDeprecated()) {
            $deprecation = $definition->getDeprecation('%service_id%');
            $deprecated = $this->document->createElement('deprecated');
            $deprecated->appendChild($this->document->createTextNode($definition->getDeprecation('%service_id%')['message']));
            $deprecated->setAttribute('package', $deprecation['package']);
            $deprecated->setAttribute('version', $deprecation['version']);
            $service->appendChild($deprecated);
        }
        if ($definition->isAutowired()) {
            $service->setAttribute('autowire', 'true');
        }
        if ($definition->isAutoconfigured()) {
            $service->setAttribute('autoconfigure', 'true');
        }
        if ($definition->isAbstract()) {
            $service->setAttribute('abstract', 'true');
        }
        if ($callable = $definition->getConfigurator()) {
            $configurator = $this->document->createElement('configurator');
            if (\is_array($callable) && $callable[0] instanceof Definition) {
                $this->addService($callable[0], null, $configurator);
                $configurator->setAttribute('method', $callable[1]);
            } elseif (\is_array($callable)) {
                $configurator->setAttribute($callable[0] instanceof Reference ? 'service' : 'class', $callable[0]);
                $configurator->setAttribute('method', $callable[1]);
            } else {
                $configurator->setAttribute('function', $callable);
            }
            $service->appendChild($configurator);
        }
        $parent->appendChild($service);
    }
    private function addServiceAlias(string $alias, Alias $id, \DOMElement $parent): void
    {
        $service = $this->document->createElement('service');
        $service->setAttribute('id', $alias);
        $service->setAttribute('alias', $id);
        if ($id->isPublic()) {
            $service->setAttribute('public', 'true');
        }
        if ($id->isDeprecated()) {
            $deprecation = $id->getDeprecation('%alias_id%');
            $deprecated = $this->document->createElement('deprecated');
            $deprecated->appendChild($this->document->createTextNode($deprecation['message']));
            $deprecated->setAttribute('package', $deprecation['package']);
            $deprecated->setAttribute('version', $deprecation['version']);
            $service->appendChild($deprecated);
        }
        $parent->appendChild($service);
    }
    private function addServices(\DOMElement $parent): void
    {
        $definitions = $this->container->getDefinitions();
        if (!$definitions) {
            return;
        }
        $services = $this->document->createElement('services');
        foreach ($definitions as $id => $definition) {
            $this->addService($definition, $id, $services);
        }
        $aliases = $this->container->getAliases();
        foreach ($aliases as $alias => $id) {
            while (isset($aliases[(string) $id])) {
                $id = $aliases[(string) $id];
            }
            $this->addServiceAlias($alias, $id, $services);
        }
        $parent->appendChild($services);
    }
    private function addTagRecursiveAttributes(\DOMElement $parent, array $attributes): void
    {
        foreach ($attributes as $name => $value) {
            $attribute = $this->document->createElement('attribute');
            $attribute->setAttribute('name', $name);
            if (\is_array($value)) {
                $this->addTagRecursiveAttributes($attribute, $value);
            } else {
                $attribute->appendChild($this->document->createTextNode($value));
            }
            $parent->appendChild($attribute);
        }
    }
    private function convertParameters(array $parameters, string $type, \DOMElement $parent, string $keyAttribute = 'key'): void
    {
        $withKeys = !array_is_list($parameters);
        foreach ($parameters as $key => $value) {
            $element = $this->document->createElement($type);
            if ($withKeys) {
                $element->setAttribute($keyAttribute, $key);
            }
            if (\is_array($tag = $value)) {
                $element->setAttribute('type', 'collection');
                $this->convertParameters($value, $type, $element, 'key');
            } elseif ($value instanceof TaggedIteratorArgument || $value instanceof ServiceLocatorArgument && $tag = $value->getTaggedIteratorArgument()) {
                $element->setAttribute('type', $value instanceof TaggedIteratorArgument ? 'tagged_iterator' : 'tagged_locator');
                $element->setAttribute('tag', $tag->getTag());
                if (null !== $tag->getIndexAttribute()) {
                    $element->setAttribute('index-by', $tag->getIndexAttribute());
                    if (null !== $tag->getDefaultIndexMethod()) {
                        $element->setAttribute('default-index-method', $tag->getDefaultIndexMethod());
                    }
                    if (null !== $tag->getDefaultPriorityMethod()) {
                        $element->setAttribute('default-priority-method', $tag->getDefaultPriorityMethod());
                    }
                }
                if ($excludes = $tag->getExclude()) {
                    if (1 === \count($excludes)) {
                        $element->setAttribute('exclude', $excludes[0]);
                    } else {
                        foreach ($excludes as $exclude) {
                            $element->appendChild($this->document->createElement('exclude', $exclude));
                        }
                    }
                }
                if (!$tag->excludeSelf()) {
                    $element->setAttribute('exclude-self', 'false');
                }
            } elseif ($value instanceof IteratorArgument) {
                $element->setAttribute('type', 'iterator');
                $this->convertParameters($value->getValues(), $type, $element, 'key');
            } elseif ($value instanceof ServiceLocatorArgument) {
                $element->setAttribute('type', 'service_locator');
                $this->convertParameters($value->getValues(), $type, $element, 'key');
            } elseif ($value instanceof ServiceClosureArgument && !$value->getValues()[0] instanceof Reference) {
                $element->setAttribute('type', 'service_closure');
                $this->convertParameters($value->getValues(), $type, $element, 'key');
            } elseif ($value instanceof Reference || $value instanceof ServiceClosureArgument) {
                $element->setAttribute('type', 'service');
                if ($value instanceof ServiceClosureArgument) {
                    $element->setAttribute('type', 'service_closure');
                    $value = $value->getValues()[0];
                }
                $element->setAttribute('id', (string) $value);
                $behavior = $value->getInvalidBehavior();
                if (ContainerInterface::NULL_ON_INVALID_REFERENCE == $behavior) {
                    $element->setAttribute('on-invalid', 'null');
                } elseif (ContainerInterface::IGNORE_ON_INVALID_REFERENCE == $behavior) {
                    $element->setAttribute('on-invalid', 'ignore');
                } elseif (ContainerInterface::IGNORE_ON_UNINITIALIZED_REFERENCE == $behavior) {
                    $element->setAttribute('on-invalid', 'ignore_uninitialized');
                }
            } elseif ($value instanceof Definition) {
                $element->setAttribute('type', 'service');
                $this->addService($value, null, $element);
            } elseif ($value instanceof Expression) {
                $element->setAttribute('type', 'expression');
                $text = $this->document->createTextNode(self::phpToXml((string) $value));
                $element->appendChild($text);
            } elseif (\is_string($value) && !preg_match('/^[^\x00-\x08\x0B\x0C\x0E-\x1F\x7F]*+$/u', $value)) {
                $element->setAttribute('type', 'binary');
                $text = $this->document->createTextNode(self::phpToXml(base64_encode($value)));
                $element->appendChild($text);
            } elseif ($value instanceof \UnitEnum) {
                $element->setAttribute('type', 'constant');
                $element->appendChild($this->document->createTextNode(self::phpToXml($value)));
            } elseif ($value instanceof AbstractArgument) {
                $element->setAttribute('type', 'abstract');
                $text = $this->document->createTextNode(self::phpToXml($value->getText()));
                $element->appendChild($text);
            } else {
                if (\in_array($value, ['null', 'true', 'false'], \true)) {
                    $element->setAttribute('type', 'string');
                }
                if (\is_string($value) && (is_numeric($value) || preg_match('/^0b[01]*$/', $value) || preg_match('/^0x[0-9a-f]++$/i', $value))) {
                    $element->setAttribute('type', 'string');
                }
                $text = $this->document->createTextNode(self::phpToXml($value));
                $element->appendChild($text);
            }
            $parent->appendChild($element);
        }
    }
    /**
     * Escapes arguments.
     */
    private function escape(array $arguments): array
    {
        $args = [];
        foreach ($arguments as $k => $v) {
            if (\is_array($v)) {
                $args[$k] = $this->escape($v);
            } elseif (\is_string($v)) {
                $args[$k] = str_replace('%', '%%', $v);
            } else {
                $args[$k] = $v;
            }
        }
        return $args;
    }
    /**
     * Converts php types to xml types.
     *
     * @throws RuntimeException When trying to dump object or resource
     */
    public static function phpToXml(mixed $value): string
    {
        switch (\true) {
            case null === $value:
                return 'null';
            case \true === $value:
                return 'true';
            case \false === $value:
                return 'false';
            case $value instanceof Parameter:
                return '%' . $value . '%';
            case $value instanceof \UnitEnum:
                return \sprintf('%s::%s', $value::class, $value->name);
            case \is_object($value) || \is_resource($value):
                throw new RuntimeException(\sprintf('Unable to dump a service container if a parameter is an object or a resource, got "%s".', get_debug_type($value)));
            default:
                return (string) $value;
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\DependencyInjection\Dumper;

/**
 * DumperInterface is the interface implemented by service container dumper classes.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
interface DumperInterface
{
    /**
     * Dumps the service container.
     */
    public function dump(array $options = []): string|array;
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\DependencyInjection\Dumper;

use _ContaoManager\Symfony\Component\DependencyInjection\ContainerBuilder;
/**
 * Dumper is the abstract class for all built-in dumpers.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
abstract class Dumper implements DumperInterface
{
    protected $container;
    public function __construct(ContainerBuilder $container)
    {
        $this->container = $container;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\DependencyInjection\Dumper;

use Composer\Autoload\ClassLoader;
use _ContaoManager\Symfony\Component\Config\Resource\FileResource;
use _ContaoManager\Symfony\Component\DependencyInjection\Argument\AbstractArgument;
use _ContaoManager\Symfony\Component\DependencyInjection\Argument\ArgumentInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Argument\IteratorArgument;
use _ContaoManager\Symfony\Component\DependencyInjection\Argument\LazyClosure;
use _ContaoManager\Symfony\Component\DependencyInjection\Argument\ServiceClosureArgument;
use _ContaoManager\Symfony\Component\DependencyInjection\Argument\ServiceLocator;
use _ContaoManager\Symfony\Component\DependencyInjection\Argument\ServiceLocatorArgument;
use _ContaoManager\Symfony\Component\DependencyInjection\Compiler\AnalyzeServiceReferencesPass;
use _ContaoManager\Symfony\Component\DependencyInjection\Compiler\CheckCircularReferencesPass;
use _ContaoManager\Symfony\Component\DependencyInjection\Compiler\ServiceReferenceGraphNode;
use _ContaoManager\Symfony\Component\DependencyInjection\Container;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerBuilder;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Definition;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\EnvParameterException;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\LogicException;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\RuntimeException;
use _ContaoManager\Symfony\Component\DependencyInjection\ExpressionLanguage;
use _ContaoManager\Symfony\Component\DependencyInjection\LazyProxy\PhpDumper\DumperInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\LazyProxy\PhpDumper\LazyServiceDumper;
use _ContaoManager\Symfony\Component\DependencyInjection\LazyProxy\PhpDumper\NullDumper;
use _ContaoManager\Symfony\Component\DependencyInjection\Loader\FileLoader;
use _ContaoManager\Symfony\Component\DependencyInjection\Parameter;
use _ContaoManager\Symfony\Component\DependencyInjection\ParameterBag\ParameterBag;
use _ContaoManager\Symfony\Component\DependencyInjection\Reference;
use _ContaoManager\Symfony\Component\DependencyInjection\ServiceLocator as BaseServiceLocator;
use _ContaoManager\Symfony\Component\DependencyInjection\TypedReference;
use _ContaoManager\Symfony\Component\DependencyInjection\Variable;
use _ContaoManager\Symfony\Component\ErrorHandler\DebugClassLoader;
use _ContaoManager\Symfony\Component\ExpressionLanguage\Expression;
/**
 * PhpDumper dumps a service container as a PHP class.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
class PhpDumper extends Dumper
{
    /**
     * Characters that might appear in the generated variable name as first character.
     */
    public const FIRST_CHARS = 'abcdefghijklmnopqrstuvwxyz';
    /**
     * Characters that might appear in the generated variable name as any but the first character.
     */
    public const NON_FIRST_CHARS = 'abcdefghijklmnopqrstuvwxyz0123456789_';
    /** @var \SplObjectStorage<Definition, Variable>|null */
    private ?\SplObjectStorage $definitionVariables = null;
    private ?array $referenceVariables = null;
    private int $variableCount;
    private ?\SplObjectStorage $inlinedDefinitions = null;
    private ?array $serviceCalls = null;
    private array $reservedVariables = ['instance', 'class', 'this', 'container'];
    private ExpressionLanguage $expressionLanguage;
    private ?string $targetDirRegex = null;
    private int $targetDirMaxMatches;
    private string $docStar;
    private array $serviceIdToMethodNameMap;
    private array $usedMethodNames;
    private string $namespace;
    private bool $asFiles;
    private string $hotPathTag;
    private array $preloadTags;
    private bool $inlineFactories;
    private bool $inlineRequires;
    private array $inlinedRequires = [];
    private array $circularReferences = [];
    private array $singleUsePrivateIds = [];
    private array $preload = [];
    private bool $addGetService = \false;
    private array $locatedIds = [];
    private string $serviceLocatorTag;
    private array $exportedVariables = [];
    private array $dynamicParameters = [];
    private string $baseClass;
    private string $class;
    private DumperInterface $proxyDumper;
    private bool $hasProxyDumper = \true;
    public function __construct(ContainerBuilder $container)
    {
        if (!$container->isCompiled()) {
            throw new LogicException('Cannot dump an uncompiled container.');
        }
        parent::__construct($container);
    }
    /**
     * Sets the dumper to be used when dumping proxies in the generated container.
     *
     * @return void
     */
    public function setProxyDumper(DumperInterface $proxyDumper)
    {
        $this->proxyDumper = $proxyDumper;
        $this->hasProxyDumper = !$proxyDumper instanceof NullDumper;
    }
    /**
     * Dumps the service container as a PHP class.
     *
     * Available options:
     *
     *  * class:      The class name
     *  * base_class: The base class name
     *  * namespace:  The class namespace
     *  * as_files:   To split the container in several files
     *
     * @return string|array A PHP class representing the service container or an array of PHP files if the "as_files" option is set
     *
     * @throws EnvParameterException When an env var exists but has not been dumped
     */
    public function dump(array $options = []): string|array
    {
        $this->locatedIds = [];
        $this->targetDirRegex = null;
        $this->inlinedRequires = [];
        $this->exportedVariables = [];
        $this->dynamicParameters = [];
        $options = array_merge([
            'class' => 'ProjectServiceContainer',
            'base_class' => 'Container',
            'namespace' => '',
            'as_files' => \false,
            'debug' => \true,
            'hot_path_tag' => 'container.hot_path',
            'preload_tags' => ['container.preload', 'container.no_preload'],
            'inline_factories_parameter' => 'container.dumper.inline_factories',
            // @deprecated since Symfony 6.3
            'inline_class_loader_parameter' => 'container.dumper.inline_class_loader',
            // @deprecated since Symfony 6.3
            'inline_factories' => null,
            'inline_class_loader' => null,
            'preload_classes' => [],
            'service_locator_tag' => 'container.service_locator',
            'build_time' => time(),
        ], $options);
        $this->addGetService = \false;
        $this->namespace = $options['namespace'];
        $this->asFiles = $options['as_files'];
        $this->hotPathTag = $options['hot_path_tag'];
        $this->preloadTags = $options['preload_tags'];
        $this->inlineFactories = \false;
        if (isset($options['inline_factories'])) {
            $this->inlineFactories = $this->asFiles && $options['inline_factories'];
        } elseif (!$options['inline_factories_parameter']) {
            trigger_deprecation('symfony/dependency-injection', '6.3', 'Option "inline_factories_parameter" passed to "%s()" is deprecated, use option "inline_factories" instead.', __METHOD__);
        } elseif ($this->container->hasParameter($options['inline_factories_parameter'])) {
            trigger_deprecation('symfony/dependency-injection', '6.3', 'Option "inline_factories_parameter" passed to "%s()" is deprecated, use option "inline_factories" instead.', __METHOD__);
            $this->inlineFactories = $this->asFiles && $this->container->getParameter($options['inline_factories_parameter']);
        }
        $this->inlineRequires = $options['debug'];
        if (isset($options['inline_class_loader'])) {
            $this->inlineRequires = $options['inline_class_loader'];
        } elseif (!$options['inline_class_loader_parameter']) {
            trigger_deprecation('symfony/dependency-injection', '6.3', 'Option "inline_class_loader_parameter" passed to "%s()" is deprecated, use option "inline_class_loader" instead.', __METHOD__);
            $this->inlineRequires = \false;
        } elseif ($this->container->hasParameter($options['inline_class_loader_parameter'])) {
            trigger_deprecation('symfony/dependency-injection', '6.3', 'Option "inline_class_loader_parameter" passed to "%s()" is deprecated, use option "inline_class_loader" instead.', __METHOD__);
            $this->inlineRequires = $this->container->getParameter($options['inline_class_loader_parameter']);
        }
        $this->serviceLocatorTag = $options['service_locator_tag'];
        $this->class = $options['class'];
        if (!str_starts_with($baseClass = $options['base_class'], '\\') && 'Container' !== $baseClass) {
            $baseClass = \sprintf('%s\%s', $options['namespace'] ? '\\' . $options['namespace'] : '', $baseClass);
            $this->baseClass = $baseClass;
        } elseif ('Container' === $baseClass) {
            $this->baseClass = Container::class;
        } else {
            $this->baseClass = $baseClass;
        }
        $this->initializeMethodNamesMap('Container' === $baseClass ? Container::class : $baseClass);
        if (!$this->hasProxyDumper) {
            (new AnalyzeServiceReferencesPass(\true, \false))->process($this->container);
            (new CheckCircularReferencesPass())->process($this->container);
        }
        $this->analyzeReferences();
        $this->docStar = $options['debug'] ? '*' : '';
        if (!empty($options['file']) && is_dir($dir = \dirname($options['file']))) {
            // Build a regexp where the first root dirs are mandatory,
            // but every other sub-dir is optional up to the full path in $dir
            // Mandate at least 1 root dir and not more than 5 optional dirs.
            $dir = explode(\DIRECTORY_SEPARATOR, realpath($dir));
            $i = \count($dir);
            if (2 + (int) ('\\' === \DIRECTORY_SEPARATOR) <= $i) {
                $regex = '';
                $lastOptionalDir = $i > 8 ? $i - 5 : 2 + (int) ('\\' === \DIRECTORY_SEPARATOR);
                $this->targetDirMaxMatches = $i - $lastOptionalDir;
                while (--$i >= $lastOptionalDir) {
                    $regex = \sprintf('(%s%s)?', preg_quote(\DIRECTORY_SEPARATOR . $dir[$i], '#'), $regex);
                }
                do {
                    $regex = preg_quote(\DIRECTORY_SEPARATOR . $dir[$i], '#') . $regex;
                } while (0 < --$i);
                $this->targetDirRegex = '#(^|file://|[:;, \|\r\n])' . preg_quote($dir[0], '#') . $regex . '#';
            }
        }
        $proxyClasses = $this->inlineFactories ? $this->generateProxyClasses() : null;
        if ($options['preload_classes']) {
            $this->preload = array_combine($options['preload_classes'], $options['preload_classes']);
        }
        $code = $this->addDefaultParametersMethod();
        $code = $this->startClass($options['class'], $baseClass, $this->inlineFactories && $proxyClasses) . $this->addServices($services) . $this->addDeprecatedAliases() . $code;
        $proxyClasses ??= $this->generateProxyClasses();
        if ($this->addGetService) {
            $code = preg_replace("/\r?\n\r?\n    public function __construct.+?\\{\r?\n/s", "\n    protected \\Closure \$getService;\$0", $code, 1);
        }
        if ($this->asFiles) {
            $fileTemplate = <<<EOF
<?php

use _ContaoManager\\Symfony\\Component\\DependencyInjection\\Argument\\RewindableGenerator;
use _ContaoManager\\Symfony\\Component\\DependencyInjection\\ContainerInterface;
use _ContaoManager\\Symfony\\Component\\DependencyInjection\\Exception\\RuntimeException;

/*{$this->docStar}
 * @internal This class has been auto-generated by the Symfony Dependency Injection Component.
 */
class %s extends {$options['class']}
{%s}

EOF;
            $files = [];
            $preloadedFiles = [];
            $ids = $this->container->getRemovedIds();
            foreach ($this->container->getDefinitions() as $id => $definition) {
                if (!$definition->isPublic()) {
                    $ids[$id] = \true;
                }
            }
            if ($ids = array_keys($ids)) {
                sort($ids);
                $c = "<?php\n\nreturn [\n";
                foreach ($ids as $id) {
                    $c .= '    ' . $this->doExport($id) . " => true,\n";
                }
                $files['removed-ids.php'] = $c . "];\n";
            }
            if (!$this->inlineFactories) {
                foreach ($this->generateServiceFiles($services) as $file => [$c, $preload]) {
                    $files[$file] = \sprintf($fileTemplate, substr($file, 0, -4), $c);
                    if ($preload) {
                        $preloadedFiles[$file] = $file;
                    }
                }
                foreach ($proxyClasses as $file => $c) {
                    $files[$file] = "<?php\n" . $c;
                    $preloadedFiles[$file] = $file;
                }
            }
            $code .= $this->endClass();
            if ($this->inlineFactories && $proxyClasses) {
                $files['proxy-classes.php'] = "<?php\n\n";
                foreach ($proxyClasses as $c) {
                    $files['proxy-classes.php'] .= $c;
                }
            }
            $files[$options['class'] . '.php'] = $code;
            $hash = ucfirst(strtr(ContainerBuilder::hash($files), '._', 'xx'));
            $code = [];
            foreach ($files as $file => $c) {
                $code["Container{$hash}/{$file}"] = substr_replace($c, "<?php\n\nnamespace Container{$hash};\n", 0, 6);
                if (isset($preloadedFiles[$file])) {
                    $preloadedFiles[$file] = "Container{$hash}/{$file}";
                }
            }
            $namespaceLine = $this->namespace ? "\nnamespace {$this->namespace};\n" : '';
            $time = $options['build_time'];
            $id = hash('crc32', $hash . $time);
            $this->asFiles = \false;
            if ($this->preload && null !== $autoloadFile = $this->getAutoloadFile()) {
                $autoloadFile = trim($this->export($autoloadFile), '()\\');
                $preloadedFiles = array_reverse($preloadedFiles);
                if ('' !== $preloadedFiles = implode("';\nrequire __DIR__.'/", $preloadedFiles)) {
                    $preloadedFiles = "require __DIR__.'/{$preloadedFiles}';\n";
                }
                $code[$options['class'] . '.preload.php'] = <<<EOF
<?php

// This file has been auto-generated by the Symfony Dependency Injection Component
// You can reference it in the "opcache.preload" php.ini setting on PHP >= 7.4 when preloading is desired

use _ContaoManager\\Symfony\\Component\\DependencyInjection\\Dumper\\Preloader;

if (in_array(PHP_SAPI, ['cli', 'phpdbg', 'embed'], true)) {
    return;
}

require {$autoloadFile};
(require __DIR__.'/{$options['class']}.php')->set(\\Container{$hash}\\{$options['class']}::class, null);
{$preloadedFiles}
\$classes = [];

EOF;
                foreach ($this->preload as $class) {
                    if (!$class || str_contains($class, '$') || \in_array($class, ['int', 'float', 'string', 'bool', 'resource', 'object', 'array', 'null', 'callable', 'iterable', 'mixed', 'void', 'never'], \true)) {
                        continue;
                    }
                    if (!(class_exists($class, \false) || interface_exists($class, \false) || trait_exists($class, \false)) || (new \ReflectionClass($class))->isUserDefined()) {
                        $code[$options['class'] . '.preload.php'] .= \sprintf("\$classes[] = '%s';\n", $class);
                    }
                }
                $code[$options['class'] . '.preload.php'] .= <<<'EOF'

$preloaded = Preloader::preload($classes);

EOF;
            }
            $code[$options['class'] . '.php'] = <<<EOF
<?php
{$namespaceLine}
// This file has been auto-generated by the Symfony Dependency Injection Component for internal use.

if (\\class_exists(\\Container{$hash}\\{$options['class']}::class, false)) {
    // no-op
} elseif (!include __DIR__.'/Container{$hash}/{$options['class']}.php') {
    touch(__DIR__.'/Container{$hash}.legacy');

    return;
}

if (!\\class_exists({$options['class']}::class, false)) {
    \\class_alias(\\Container{$hash}\\{$options['class']}::class, {$options['class']}::class, false);
}

return new \\Container{$hash}\\{$options['class']}([
    'container.build_hash' => '{$hash}',
    'container.build_id' => '{$id}',
    'container.build_time' => {$time},
    'container.runtime_mode' => \\in_array(\\PHP_SAPI, ['cli', 'phpdbg', 'embed'], true) ? 'web=0' : 'web=1',
], __DIR__.\\DIRECTORY_SEPARATOR.'Container{$hash}');

EOF;
        } else {
            $code .= $this->endClass();
            foreach ($proxyClasses as $c) {
                $code .= $c;
            }
        }
        $this->targetDirRegex = null;
        $this->inlinedRequires = [];
        $this->circularReferences = [];
        $this->locatedIds = [];
        $this->exportedVariables = [];
        $this->dynamicParameters = [];
        $this->preload = [];
        $unusedEnvs = [];
        foreach ($this->container->getEnvCounters() as $env => $use) {
            if (!$use) {
                $unusedEnvs[] = $env;
            }
        }
        if ($unusedEnvs) {
            throw new EnvParameterException($unusedEnvs, null, 'Environment variables "%s" are never used. Please, check your container\'s configuration.');
        }
        return $code;
    }
    /**
     * Retrieves the currently set proxy dumper or instantiates one.
     */
    private function getProxyDumper(): DumperInterface
    {
        return $this->proxyDumper ??= new LazyServiceDumper($this->class);
    }
    private function analyzeReferences(): void
    {
        (new AnalyzeServiceReferencesPass(\false, $this->hasProxyDumper))->process($this->container);
        $checkedNodes = [];
        $this->circularReferences = [];
        $this->singleUsePrivateIds = [];
        foreach ($this->container->getCompiler()->getServiceReferenceGraph()->getNodes() as $id => $node) {
            if (!$node->getValue() instanceof Definition) {
                continue;
            }
            if ($this->isSingleUsePrivateNode($node)) {
                $this->singleUsePrivateIds[$id] = $id;
            }
            $this->collectCircularReferences($id, $node->getOutEdges(), $checkedNodes);
        }
        $this->container->getCompiler()->getServiceReferenceGraph()->clear();
        $this->singleUsePrivateIds = array_diff_key($this->singleUsePrivateIds, $this->circularReferences);
    }
    private function collectCircularReferences(string $sourceId, array $edges, array &$checkedNodes, array &$loops = [], array $path = [], bool $byConstructor = \true): void
    {
        $path[$sourceId] = $byConstructor;
        $checkedNodes[$sourceId] = \true;
        foreach ($edges as $edge) {
            $node = $edge->getDestNode();
            $id = $node->getId();
            if ($sourceId === $id && !$edge->isLazy() || !$node->getValue() instanceof Definition || $edge->isWeak()) {
                continue;
            }
            if (isset($path[$id])) {
                $loop = null;
                $loopByConstructor = $edge->isReferencedByConstructor() && !$edge->isLazy();
                $pathInLoop = [$id, []];
                foreach ($path as $k => $pathByConstructor) {
                    if (null !== $loop) {
                        $loop[] = $k;
                        $pathInLoop[1][$k] = $pathByConstructor;
                        $loops[$k][] =& $pathInLoop;
                        $loopByConstructor = $loopByConstructor && $pathByConstructor;
                    } elseif ($k === $id) {
                        $loop = [];
                    }
                }
                $this->addCircularReferences($id, $loop, $loopByConstructor);
            } elseif (!isset($checkedNodes[$id])) {
                $this->collectCircularReferences($id, $node->getOutEdges(), $checkedNodes, $loops, $path, $edge->isReferencedByConstructor() && !$edge->isLazy());
            } elseif (isset($loops[$id])) {
                // we already had detected loops for this edge
                // let's check if we have a common ancestor in one of the detected loops
                foreach ($loops[$id] as [$first, $loopPath]) {
                    if (!isset($path[$first])) {
                        continue;
                    }
                    // We have a common ancestor, let's fill the current path
                    $fillPath = null;
                    foreach ($loopPath as $k => $pathByConstructor) {
                        if (null !== $fillPath) {
                            $fillPath[$k] = $pathByConstructor;
                        } elseif ($k === $id) {
                            $fillPath = $path;
                            $fillPath[$k] = $pathByConstructor;
                        }
                    }
                    // we can now build the loop
                    $loop = null;
                    $loopByConstructor = $edge->isReferencedByConstructor() && !$edge->isLazy();
                    foreach ($fillPath as $k => $pathByConstructor) {
                        if (null !== $loop) {
                            $loop[] = $k;
                            $loopByConstructor = $loopByConstructor && $pathByConstructor;
                        } elseif ($k === $first) {
                            $loop = [];
                        }
                    }
                    $this->addCircularReferences($first, $loop, $loopByConstructor);
                    break;
                }
            }
        }
        unset($path[$sourceId]);
    }
    private function addCircularReferences(string $sourceId, array $currentPath, bool $byConstructor): void
    {
        $currentId = $sourceId;
        $currentPath = array_reverse($currentPath);
        $currentPath[] = $currentId;
        foreach ($currentPath as $parentId) {
            if (empty($this->circularReferences[$parentId][$currentId])) {
                $this->circularReferences[$parentId][$currentId] = $byConstructor;
            }
            $currentId = $parentId;
        }
    }
    private function collectLineage(string $class, array &$lineage): void
    {
        if (isset($lineage[$class])) {
            return;
        }
        if (!$r = $this->container->getReflectionClass($class, \false)) {
            return;
        }
        if (is_a($class, $this->baseClass, \true)) {
            return;
        }
        $file = $r->getFileName();
        if ($file && str_ends_with($file, ') : eval()\'d code')) {
            $file = substr($file, 0, strrpos($file, '(', -17));
        }
        if (!$file || $this->doExport($file) === $exportedFile = $this->export($file)) {
            return;
        }
        $lineage[$class] = substr($exportedFile, 1, -1);
        if ($parent = $r->getParentClass()) {
            $this->collectLineage($parent->name, $lineage);
        }
        foreach ($r->getInterfaces() as $parent) {
            $this->collectLineage($parent->name, $lineage);
        }
        foreach ($r->getTraits() as $parent) {
            $this->collectLineage($parent->name, $lineage);
        }
        unset($lineage[$class]);
        $lineage[$class] = substr($exportedFile, 1, -1);
    }
    private function generateProxyClasses(): array
    {
        $proxyClasses = [];
        $alreadyGenerated = [];
        $definitions = $this->container->getDefinitions();
        $strip = '' === $this->docStar;
        $proxyDumper = $this->getProxyDumper();
        ksort($definitions);
        foreach ($definitions as $id => $definition) {
            if (!$definition = $this->isProxyCandidate($definition, $asGhostObject, $id)) {
                continue;
            }
            if (isset($alreadyGenerated[$asGhostObject][$class = $definition->getClass()])) {
                continue;
            }
            $alreadyGenerated[$asGhostObject][$class] = \true;
            foreach (array_column($definition->getTag('proxy'), 'interface') ?: [$class] as $r) {
                if (!$r = $this->container->getReflectionClass($r)) {
                    continue;
                }
                do {
                    if ($file = $r->getFileName()) {
                        if (str_ends_with($file, ') : eval()\'d code')) {
                            $file = substr($file, 0, strrpos($file, '(', -17));
                        }
                        if (is_file($file)) {
                            $this->container->addResource(new FileResource($file));
                        }
                    }
                    $r = $r->getParentClass() ?: null;
                } while ($r?->isUserDefined());
            }
            if ("\n" === $proxyCode = "\n" . $proxyDumper->getProxyCode($definition, $id)) {
                continue;
            }
            if ($this->inlineRequires) {
                $lineage = [];
                $this->collectLineage($class, $lineage);
                $code = '';
                foreach (array_diff_key(array_flip($lineage), $this->inlinedRequires) as $file => $class) {
                    if ($this->inlineFactories) {
                        $this->inlinedRequires[$file] = \true;
                    }
                    $code .= \sprintf("include_once %s;\n", $file);
                }
                $proxyCode = $code . $proxyCode;
            }
            if ($strip) {
                $proxyCode = "<?php\n" . $proxyCode;
                $proxyCode = substr(self::stripComments($proxyCode), 5);
            }
            $proxyClass = $this->inlineRequires ? substr($proxyCode, \strlen($code)) : $proxyCode;
            $i = strpos($proxyClass, 'class');
            $proxyClass = substr($proxyClass, 6 + $i, strpos($proxyClass, ' ', 7 + $i) - $i - 6);
            if ($this->asFiles || $this->namespace) {
                $proxyCode .= "\nif (!\\class_exists('{$proxyClass}', false)) {\n    \\class_alias(__NAMESPACE__.'\\\\{$proxyClass}', '{$proxyClass}', false);\n}\n";
            }
            $proxyClasses[$proxyClass . '.php'] = $proxyCode;
        }
        return $proxyClasses;
    }
    private function addServiceInclude(string $cId, Definition $definition, bool $isProxyCandidate): string
    {
        $code = '';
        if ($this->inlineRequires && (!$this->isHotPath($definition) || $isProxyCandidate)) {
            $lineage = [];
            foreach ($this->inlinedDefinitions as $def) {
                if (!$def->isDeprecated()) {
                    foreach ($this->getClasses($def, $cId) as $class) {
                        $this->collectLineage($class, $lineage);
                    }
                }
            }
            foreach ($this->serviceCalls as $id => [$callCount, $behavior]) {
                if ('service_container' !== $id && $id !== $cId && ContainerInterface::IGNORE_ON_UNINITIALIZED_REFERENCE !== $behavior && $this->container->has($id) && $this->isTrivialInstance($def = $this->container->findDefinition($id))) {
                    foreach ($this->getClasses($def, $cId) as $class) {
                        $this->collectLineage($class, $lineage);
                    }
                }
            }
            foreach (array_diff_key(array_flip($lineage), $this->inlinedRequires) as $file => $class) {
                $code .= \sprintf("        include_once %s;\n", $file);
            }
        }
        foreach ($this->inlinedDefinitions as $def) {
            if ($file = $def->getFile()) {
                $file = $this->dumpValue($file);
                $file = '(' === $file[0] ? substr($file, 1, -1) : $file;
                $code .= \sprintf("        include_once %s;\n", $file);
            }
        }
        if ('' !== $code) {
            $code .= "\n";
        }
        return $code;
    }
    /**
     * @throws InvalidArgumentException
     * @throws RuntimeException
     */
    private function addServiceInstance(string $id, Definition $definition, bool $isSimpleInstance): string
    {
        $class = $this->dumpValue($definition->getClass());
        if (str_starts_with($class, "'") && !str_contains($class, '$') && !preg_match('/^\'(?:\\\\{2})?[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*(?:\\\\{2}[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*)*\'$/', $class)) {
            throw new InvalidArgumentException(\sprintf('"%s" is not a valid class name for the "%s" service.', $class, $id));
        }
        $asGhostObject = \false;
        $isProxyCandidate = $this->isProxyCandidate($definition, $asGhostObject, $id);
        $lastWitherIndex = null;
        foreach ($definition->getMethodCalls() as $k => $call) {
            if ($call[2] ?? \false) {
                $lastWitherIndex = $k;
            }
        }
        $shouldShareInline = !$isProxyCandidate && $definition->isShared() && !isset($this->singleUsePrivateIds[$id]) && null === $lastWitherIndex;
        $serviceAccessor = \sprintf('$container->%s[%s]', $this->container->getDefinition($id)->isPublic() ? 'services' : 'privates', $this->doExport($id));
        $return = match (\true) {
            $shouldShareInline && !isset($this->circularReferences[$id]) && $isSimpleInstance => 'return ' . $serviceAccessor . ' = ',
            $shouldShareInline && !isset($this->circularReferences[$id]) => $serviceAccessor . ' = $instance = ',
            $shouldShareInline || !$isSimpleInstance => '$instance = ',
            default => 'return ',
        };
        $code = $this->addNewInstance($definition, '        ' . $return, $id, $asGhostObject);
        if ($shouldShareInline && isset($this->circularReferences[$id])) {
            $code .= \sprintf("\n        if (isset(%s)) {\n            return %1\$s;\n        }\n\n        %s%1\$s = \$instance;\n", $serviceAccessor, $isSimpleInstance ? 'return ' : '');
        }
        return $code;
    }
    private function isTrivialInstance(Definition $definition): bool
    {
        if ($definition->hasErrors()) {
            return \true;
        }
        if ($definition->isSynthetic() || $definition->getFile() || $definition->getMethodCalls() || $definition->getProperties() || $definition->getConfigurator()) {
            return \false;
        }
        if ($definition->isDeprecated() || $definition->isLazy() || $definition->getFactory() || 3 < \count($definition->getArguments())) {
            return \false;
        }
        foreach ($definition->getArguments() as $arg) {
            if (!$arg || $arg instanceof Parameter) {
                continue;
            }
            if (\is_array($arg) && 3 >= \count($arg)) {
                foreach ($arg as $k => $v) {
                    if ($this->dumpValue($k) !== $this->dumpValue($k, \false)) {
                        return \false;
                    }
                    if (!$v || $v instanceof Parameter) {
                        continue;
                    }
                    if ($v instanceof Reference && $this->container->has($id = (string) $v) && $this->container->findDefinition($id)->isSynthetic()) {
                        continue;
                    }
                    if (!\is_scalar($v) || $this->dumpValue($v) !== $this->dumpValue($v, \false)) {
                        return \false;
                    }
                }
            } elseif ($arg instanceof Reference && $this->container->has($id = (string) $arg) && $this->container->findDefinition($id)->isSynthetic()) {
                continue;
            } elseif (!\is_scalar($arg) || $this->dumpValue($arg) !== $this->dumpValue($arg, \false)) {
                return \false;
            }
        }
        return \true;
    }
    private function addServiceMethodCalls(Definition $definition, string $variableName, ?string $sharedNonLazyId): string
    {
        $lastWitherIndex = null;
        foreach ($definition->getMethodCalls() as $k => $call) {
            if ($call[2] ?? \false) {
                $lastWitherIndex = $k;
            }
        }
        $calls = '';
        foreach ($definition->getMethodCalls() as $k => $call) {
            $arguments = [];
            foreach ($call[1] as $i => $value) {
                $arguments[] = (\is_string($i) ? $i . ': ' : '') . $this->dumpValue($value);
            }
            $witherAssignation = '';
            if ($call[2] ?? \false) {
                if (null !== $sharedNonLazyId && $lastWitherIndex === $k && 'instance' === $variableName) {
                    $witherAssignation = \sprintf('$container->%s[\'%s\'] = ', $definition->isPublic() ? 'services' : 'privates', $sharedNonLazyId);
                }
                $witherAssignation .= \sprintf('$%s = ', $variableName);
            }
            $calls .= $this->wrapServiceConditionals($call[1], \sprintf("        %s\$%s->%s(%s);\n", $witherAssignation, $variableName, $call[0], implode(', ', $arguments)));
        }
        return $calls;
    }
    private function addServiceProperties(Definition $definition, string $variableName = 'instance'): string
    {
        $code = '';
        foreach ($definition->getProperties() as $name => $value) {
            $code .= \sprintf("        \$%s->%s = %s;\n", $variableName, $name, $this->dumpValue($value));
        }
        return $code;
    }
    private function addServiceConfigurator(Definition $definition, string $variableName = 'instance'): string
    {
        if (!$callable = $definition->getConfigurator()) {
            return '';
        }
        if (\is_array($callable)) {
            if ($callable[0] instanceof Reference || $callable[0] instanceof Definition && $this->definitionVariables->offsetExists($callable[0])) {
                return \sprintf("        %s->%s(\$%s);\n", $this->dumpValue($callable[0]), $callable[1], $variableName);
            }
            $class = $this->dumpValue($callable[0]);
            // If the class is a string we can optimize away
            if (str_starts_with($class, "'") && !str_contains($class, '$')) {
                return \sprintf("        %s::%s(\$%s);\n", $this->dumpLiteralClass($class), $callable[1], $variableName);
            }
            if (str_starts_with($class, 'new ')) {
                return \sprintf("        (%s)->%s(\$%s);\n", $this->dumpValue($callable[0]), $callable[1], $variableName);
            }
            return \sprintf("        [%s, '%s'](\$%s);\n", $this->dumpValue($callable[0]), $callable[1], $variableName);
        }
        return \sprintf("        %s(\$%s);\n", $callable, $variableName);
    }
    private function addService(string $id, Definition $definition): array
    {
        $this->definitionVariables = new \SplObjectStorage();
        $this->referenceVariables = [];
        $this->variableCount = 0;
        $this->referenceVariables[$id] = new Variable('instance');
        $return = [];
        if ($class = $definition->getClass()) {
            $class = $class instanceof Parameter ? '%' . $class . '%' : $this->container->resolveEnvPlaceholders($class);
            $return[] = \sprintf(str_starts_with($class, '%') ? '@return object A %1$s instance' : '@return \%s', ltrim($class, '\\'));
        } elseif ($factory = $definition->getFactory()) {
            if (\is_string($factory) && !str_starts_with($factory, '@=')) {
                $return[] = \sprintf('@return object An instance returned by %s()', $factory);
            } elseif (\is_array($factory) && (\is_string($factory[0]) || $factory[0] instanceof Definition || $factory[0] instanceof Reference)) {
                $class = $factory[0] instanceof Definition ? $factory[0]->getClass() : (string) $factory[0];
                $class = $class instanceof Parameter ? '%' . $class . '%' : $this->container->resolveEnvPlaceholders($class);
                $return[] = \sprintf('@return object An instance returned by %s::%s()', $class, $factory[1]);
            }
        }
        if ($definition->isDeprecated()) {
            if ($return && str_starts_with($return[\count($return) - 1], '@return')) {
                $return[] = '';
            }
            $deprecation = $definition->getDeprecation($id);
            $return[] = \sprintf('@deprecated %s', ($deprecation['package'] || $deprecation['version'] ? "Since {$deprecation['package']} {$deprecation['version']}: " : '') . $deprecation['message']);
        }
        $return = str_replace("\n     * \n", "\n     *\n", implode("\n     * ", $return));
        $return = $this->container->resolveEnvPlaceholders($return);
        $shared = $definition->isShared() ? ' shared' : '';
        $public = $definition->isPublic() ? 'public' : 'private';
        $autowired = $definition->isAutowired() ? ' autowired' : '';
        $asFile = $this->asFiles && !$this->inlineFactories && !$this->isHotPath($definition);
        $methodName = $this->generateMethodName($id);
        if ($asFile || $definition->isLazy()) {
            $lazyInitialization = ', $lazyLoad = true';
        } else {
            $lazyInitialization = '';
        }
        $code = <<<EOF

    /*{$this->docStar}
     * Gets the {$public} '{$id}'{$shared}{$autowired} service.
     *
     * {$return}
EOF;
        $code = str_replace('*/', ' ', $code) . <<<EOF

     */
    protected static function {$methodName}(\$container{$lazyInitialization})
    {

EOF;
        if ($asFile) {
            $file = $methodName . '.php';
            $code = str_replace("protected static function {$methodName}(", 'public static function do(', $code);
        } else {
            $file = null;
        }
        if ($definition->hasErrors() && $e = $definition->getErrors()) {
            $code .= \sprintf("        throw new RuntimeException(%s);\n", $this->export(reset($e)));
        } else {
            $this->serviceCalls = [];
            $this->inlinedDefinitions = $this->getDefinitionsFromArguments([$definition], null, $this->serviceCalls);
            if ($definition->isDeprecated()) {
                $deprecation = $definition->getDeprecation($id);
                $code .= \sprintf("        trigger_deprecation(%s, %s, %s);\n\n", $this->export($deprecation['package']), $this->export($deprecation['version']), $this->export($deprecation['message']));
            } elseif ($definition->hasTag($this->hotPathTag) || !$definition->hasTag($this->preloadTags[1])) {
                foreach ($this->inlinedDefinitions as $def) {
                    foreach ($this->getClasses($def, $id) as $class) {
                        $this->preload[$class] = $class;
                    }
                }
            }
            if (!$definition->isShared()) {
                $factory = \sprintf('$container->factories%s[%s]', $definition->isPublic() ? '' : "['service_container']", $this->doExport($id));
            }
            $asGhostObject = \false;
            if ($isProxyCandidate = $this->isProxyCandidate($definition, $asGhostObject, $id)) {
                $definition = $isProxyCandidate;
                if (!$definition->isShared()) {
                    $code .= \sprintf('        %s ??= ', $factory);
                    if ($definition->isPublic()) {
                        $code .= \sprintf("fn () => self::%s(\$container);\n\n", $asFile ? 'do' : $methodName);
                    } else {
                        $code .= \sprintf("self::%s(...);\n\n", $asFile ? 'do' : $methodName);
                    }
                }
                $lazyLoad = $asGhostObject ? '$proxy' : 'false';
                $factoryCode = $asFile ? \sprintf('self::do($container, %s)', $lazyLoad) : \sprintf('self::%s($container, %s)', $methodName, $lazyLoad);
                $code .= $this->getProxyDumper()->getProxyFactoryCode($definition, $id, $factoryCode);
            }
            $c = $this->addServiceInclude($id, $definition, null !== $isProxyCandidate);
            if ('' !== $c && $isProxyCandidate && !$definition->isShared()) {
                $c = implode("\n", array_map(fn($line) => $line ? '    ' . $line : $line, explode("\n", $c)));
                $code .= "        static \$include = true;\n\n";
                $code .= "        if (\$include) {\n";
                $code .= $c;
                $code .= "            \$include = false;\n";
                $code .= "        }\n\n";
            } else {
                $code .= $c;
            }
            $c = $this->addInlineService($id, $definition);
            if (!$isProxyCandidate && !$definition->isShared()) {
                $c = implode("\n", array_map(fn($line) => $line ? '    ' . $line : $line, explode("\n", $c)));
                $lazyloadInitialization = $definition->isLazy() ? ', $lazyLoad = true' : '';
                $c = \sprintf("        %s = function (\$container%s) {\n%s        };\n\n        return %1\$s(\$container);\n", $factory, $lazyloadInitialization, $c);
            }
            $code .= $c;
        }
        $code .= "    }\n";
        $this->definitionVariables = $this->inlinedDefinitions = null;
        $this->referenceVariables = $this->serviceCalls = null;
        return [$file, $code];
    }
    private function addInlineVariables(string $id, Definition $definition, array $arguments, bool $forConstructor): string
    {
        $code = '';
        foreach ($arguments as $argument) {
            if (\is_array($argument)) {
                $code .= $this->addInlineVariables($id, $definition, $argument, $forConstructor);
            } elseif ($argument instanceof Reference) {
                $code .= $this->addInlineReference($id, $definition, $argument, $forConstructor);
            } elseif ($argument instanceof Definition) {
                $code .= $this->addInlineService($id, $definition, $argument, $forConstructor);
            }
        }
        return $code;
    }
    private function addInlineReference(string $id, Definition $definition, string $targetId, bool $forConstructor): string
    {
        while ($this->container->hasAlias($targetId)) {
            $targetId = (string) $this->container->getAlias($targetId);
        }
        [$callCount, $behavior] = $this->serviceCalls[$targetId];
        if ($id === $targetId) {
            return $this->addInlineService($id, $definition, $definition);
        }
        if ('service_container' === $targetId || isset($this->referenceVariables[$targetId])) {
            return '';
        }
        if ($this->container->hasDefinition($targetId) && ($def = $this->container->getDefinition($targetId)) && !$def->isShared()) {
            return '';
        }
        $hasSelfRef = isset($this->circularReferences[$id][$targetId]) && !isset($this->definitionVariables[$definition]) && !($this->hasProxyDumper && $definition->isLazy());
        if ($hasSelfRef && !$forConstructor && !$forConstructor = !$this->circularReferences[$id][$targetId]) {
            $code = $this->addInlineService($id, $definition, $definition);
        } else {
            $code = '';
        }
        if (isset($this->referenceVariables[$targetId]) || 2 > $callCount && (!$hasSelfRef || !$forConstructor)) {
            return $code;
        }
        $name = $this->getNextVariableName();
        $this->referenceVariables[$targetId] = new Variable($name);
        $reference = ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE !== $behavior ? new Reference($targetId, $behavior) : null;
        $code .= \sprintf("        \$%s = %s;\n", $name, $this->getServiceCall($targetId, $reference));
        if (!$hasSelfRef || !$forConstructor) {
            return $code;
        }
        $code .= \sprintf(<<<'EOTXT'

        if (isset($container->%s[%s])) {
            return $container->%1$s[%2$s];
        }

EOTXT
, $this->container->getDefinition($id)->isPublic() ? 'services' : 'privates', $this->doExport($id));
        return $code;
    }
    private function addInlineService(string $id, Definition $definition, ?Definition $inlineDef = null, bool $forConstructor = \true): string
    {
        $code = '';
        if ($isSimpleInstance = $isRootInstance = null === $inlineDef) {
            foreach ($this->serviceCalls as $targetId => [, , $byConstructor]) {
                if ($byConstructor && isset($this->circularReferences[$id][$targetId]) && !$this->circularReferences[$id][$targetId] && !($this->hasProxyDumper && $definition->isLazy())) {
                    $code .= $this->addInlineReference($id, $definition, $targetId, $forConstructor);
                }
            }
        }
        if (isset($this->definitionVariables[$inlineDef ??= $definition])) {
            return $code;
        }
        $arguments = [$inlineDef->getArguments(), $inlineDef->getFactory()];
        $code .= $this->addInlineVariables($id, $definition, $arguments, $forConstructor);
        if ($arguments = array_filter([$inlineDef->getProperties(), $inlineDef->getMethodCalls(), $inlineDef->getConfigurator()])) {
            $isSimpleInstance = \false;
        } elseif ($definition !== $inlineDef && 2 > $this->inlinedDefinitions[$inlineDef]) {
            return $code;
        }
        $asGhostObject = \false;
        $isProxyCandidate = $this->isProxyCandidate($inlineDef, $asGhostObject, $id);
        if (isset($this->definitionVariables[$inlineDef])) {
            $isSimpleInstance = \false;
        } else {
            $name = $definition === $inlineDef ? 'instance' : $this->getNextVariableName();
            $this->definitionVariables[$inlineDef] = new Variable($name);
            $code .= '' !== $code ? "\n" : '';
            if ('instance' === $name) {
                $code .= $this->addServiceInstance($id, $definition, $isSimpleInstance);
            } else {
                $code .= $this->addNewInstance($inlineDef, '        $' . $name . ' = ', $id);
            }
            if ('' !== $inline = $this->addInlineVariables($id, $definition, $arguments, \false)) {
                $code .= "\n" . $inline . "\n";
            } elseif ($arguments && 'instance' === $name) {
                $code .= "\n";
            }
            $code .= $this->addServiceProperties($inlineDef, $name);
            $code .= $this->addServiceMethodCalls($inlineDef, $name, !$isProxyCandidate && $inlineDef->isShared() && !isset($this->singleUsePrivateIds[$id]) ? $id : null);
            $code .= $this->addServiceConfigurator($inlineDef, $name);
        }
        if (!$isRootInstance || $isSimpleInstance) {
            return $code;
        }
        return $code . "\n        return \$instance;\n";
    }
    private function addServices(?array &$services = null): string
    {
        $publicServices = $privateServices = '';
        $definitions = $this->container->getDefinitions();
        ksort($definitions);
        foreach ($definitions as $id => $definition) {
            if (!$definition->isSynthetic()) {
                $services[$id] = $this->addService($id, $definition);
            } elseif ($definition->hasTag($this->hotPathTag) || !$definition->hasTag($this->preloadTags[1])) {
                $services[$id] = null;
                foreach ($this->getClasses($definition, $id) as $class) {
                    $this->preload[$class] = $class;
                }
            }
        }
        foreach ($definitions as $id => $definition) {
            if (!([$file, $code] = $services[$id]) || null !== $file) {
                continue;
            }
            if ($definition->isPublic()) {
                $publicServices .= $code;
            } elseif (!$this->isTrivialInstance($definition) || isset($this->locatedIds[$id])) {
                $privateServices .= $code;
            }
        }
        return $publicServices . $privateServices;
    }
    private function generateServiceFiles(array $services): iterable
    {
        $definitions = $this->container->getDefinitions();
        ksort($definitions);
        foreach ($definitions as $id => $definition) {
            if (([$file, $code] = $services[$id]) && null !== $file && ($definition->isPublic() || !$this->isTrivialInstance($definition) || isset($this->locatedIds[$id]))) {
                yield $file => [$code, $definition->hasTag($this->hotPathTag) || !$definition->hasTag($this->preloadTags[1]) && !$definition->isDeprecated() && !$definition->hasErrors()];
            }
        }
    }
    private function addNewInstance(Definition $definition, string $return = '', ?string $id = null, bool $asGhostObject = \false): string
    {
        $tail = $return ? str_repeat(')', substr_count($return, '(') - substr_count($return, ')')) . ";\n" : '';
        if (BaseServiceLocator::class === $definition->getClass() && $definition->hasTag($this->serviceLocatorTag)) {
            $arguments = [];
            foreach ($definition->getArgument(0) as $k => $argument) {
                $arguments[$k] = $argument->getValues()[0];
            }
            return $return . $this->dumpValue(new ServiceLocatorArgument($arguments)) . $tail;
        }
        $arguments = [];
        foreach ($definition->getArguments() as $i => $value) {
            $arguments[] = (\is_string($i) ? $i . ': ' : '') . $this->dumpValue($value);
        }
        if ($callable = $definition->getFactory()) {
            if ('current' === $callable && [0] === array_keys($definition->getArguments()) && \is_array($value) && [0] === array_keys($value)) {
                return $return . $this->dumpValue($value[0]) . $tail;
            }
            if (['Closure', 'fromCallable'] === $callable) {
                $callable = $definition->getArgument(0);
                if ($callable instanceof ServiceClosureArgument) {
                    return $return . $this->dumpValue($callable) . $tail;
                }
                $arguments = ['...'];
                if ($callable instanceof Reference || $callable instanceof Definition) {
                    $callable = [$callable, '__invoke'];
                }
            }
            if (\is_string($callable) && str_starts_with($callable, '@=')) {
                return $return . \sprintf('(($args = %s) ? (%s) : null)', $this->dumpValue(new ServiceLocatorArgument($definition->getArguments())), $this->getExpressionLanguage()->compile(substr($callable, 2), ['container' => 'container', 'args' => 'args'])) . $tail;
            }
            if (!\is_array($callable)) {
                return $return . \sprintf('%s(%s)', $this->dumpLiteralClass($this->dumpValue($callable)), $arguments ? implode(', ', $arguments) : '') . $tail;
            }
            if (!preg_match('/^[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*$/', $callable[1])) {
                throw new RuntimeException(\sprintf('Cannot dump definition because of invalid factory method (%s).', $callable[1] ?: 'n/a'));
            }
            if (['...'] === $arguments && ('Closure' !== ($class = $definition->getClass() ?: 'Closure') || $definition->isLazy() && ($callable[0] instanceof Reference || $callable[0] instanceof Definition && !$this->definitionVariables->offsetExists($callable[0])))) {
                $initializer = 'fn () => ' . $this->dumpValue($callable[0]);
                $this->preload[LazyClosure::class] = LazyClosure::class;
                return $return . LazyClosure::getCode($initializer, $callable, $class, $this->container, $id) . $tail;
            }
            if ($callable[0] instanceof Reference || $callable[0] instanceof Definition && $this->definitionVariables->offsetExists($callable[0])) {
                return $return . \sprintf('%s->%s(%s)', $this->dumpValue($callable[0]), $callable[1], $arguments ? implode(', ', $arguments) : '') . $tail;
            }
            $class = $this->dumpValue($callable[0]);
            // If the class is a string we can optimize away
            if (str_starts_with($class, "'") && !str_contains($class, '$')) {
                if ("''" === $class) {
                    throw new RuntimeException(\sprintf('Cannot dump definition: "%s" service is defined to be created by a factory but is missing the service reference, did you forget to define the factory service id or class?', $id ? 'The "' . $id . '"' : 'inline'));
                }
                return $return . \sprintf('%s::%s(%s)', $this->dumpLiteralClass($class), $callable[1], $arguments ? implode(', ', $arguments) : '') . $tail;
            }
            if (str_starts_with($class, 'new ')) {
                return $return . \sprintf('(%s)->%s(%s)', $class, $callable[1], $arguments ? implode(', ', $arguments) : '') . $tail;
            }
            return $return . \sprintf("[%s, '%s'](%s)", $class, $callable[1], $arguments ? implode(', ', $arguments) : '') . $tail;
        }
        if (null === $class = $definition->getClass()) {
            throw new RuntimeException('Cannot dump definitions which have no class nor factory.');
        }
        if (!$asGhostObject) {
            return $return . \sprintf('new %s(%s)', $this->dumpLiteralClass($this->dumpValue($class)), implode(', ', $arguments)) . $tail;
        }
        if (!method_exists($this->container->getParameterBag()->resolveValue($class), '__construct')) {
            return $return . '$lazyLoad' . $tail;
        }
        return $return . \sprintf('($lazyLoad->__construct(%s) && false ?: $lazyLoad)', implode(', ', $arguments)) . $tail;
    }
    private function startClass(string $class, string $baseClass, bool $hasProxyClasses): string
    {
        $namespaceLine = !$this->asFiles && $this->namespace ? "\nnamespace {$this->namespace};\n" : '';
        $code = <<<EOF
<?php
{$namespaceLine}
use _ContaoManager\\Symfony\\Component\\DependencyInjection\\Argument\\RewindableGenerator;
use _ContaoManager\\Symfony\\Component\\DependencyInjection\\ContainerInterface;
use _ContaoManager\\Symfony\\Component\\DependencyInjection\\Container;
use _ContaoManager\\Symfony\\Component\\DependencyInjection\\Exception\\LogicException;
use _ContaoManager\\Symfony\\Component\\DependencyInjection\\Exception\\ParameterNotFoundException;
use _ContaoManager\\Symfony\\Component\\DependencyInjection\\Exception\\RuntimeException;
use _ContaoManager\\Symfony\\Component\\DependencyInjection\\ParameterBag\\FrozenParameterBag;
use _ContaoManager\\Symfony\\Component\\DependencyInjection\\ParameterBag\\ParameterBagInterface;

/*{$this->docStar}
 * @internal This class has been auto-generated by the Symfony Dependency Injection Component.
 */
class {$class} extends {$baseClass}
{
    private const DEPRECATED_PARAMETERS = [];

    protected \$parameters = [];

    public function __construct()
    {

EOF;
        $code = str_replace("    private const DEPRECATED_PARAMETERS = [];\n\n", $this->addDeprecatedParameters(), $code);
        if ($this->asFiles) {
            $code = str_replace('__construct()', '__construct(private array $buildParameters = [], protected string $containerDir = __DIR__)', $code);
            if (null !== $this->targetDirRegex) {
                $code = str_replace('$parameters = []', "\$targetDir;\n    protected \$parameters = []", $code);
                $code .= '        $this->targetDir = \dirname($containerDir);' . "\n";
            }
        }
        if ($this->needsUnsetParameterBag()) {
            $code .= "        parent::__construct();\n";
            $code .= "        unset(\$this->parameterBag);\n\n";
        }
        if ($this->container->getParameterBag()->all()) {
            $code .= "        \$this->parameters = \$this->getDefaultParameters();\n\n";
        }
        $code .= "        \$this->services = \$this->privates = [];\n";
        $code .= $this->addSyntheticIds();
        $code .= $this->addMethodMap();
        $code .= $this->asFiles && !$this->inlineFactories ? $this->addFileMap() : '';
        $code .= $this->addAliases();
        $code .= $this->addInlineRequires($hasProxyClasses);
        $code .= <<<EOF
    }

    public function compile(): void
    {
        throw new LogicException('You cannot compile a dumped container that was already compiled.');
    }

    public function isCompiled(): bool
    {
        return true;
    }

EOF;
        $code .= $this->addRemovedIds();
        if ($this->asFiles && !$this->inlineFactories) {
            $code .= <<<'EOF'

    protected function load($file, $lazyLoad = true): mixed
    {
        if (class_exists($class = __NAMESPACE__.'\\'.$file, false)) {
            return $class::do($this, $lazyLoad);
        }

        if ('.' === $file[-4]) {
            $class = substr($class, 0, -4);
        } else {
            $file .= '.php';
        }

        $service = require $this->containerDir.\DIRECTORY_SEPARATOR.$file;

        return class_exists($class, false) ? $class::do($this, $lazyLoad) : $service;
    }

EOF;
        }
        foreach ($this->container->getDefinitions() as $definition) {
            if (!$definition->isLazy() || !$this->hasProxyDumper) {
                continue;
            }
            if ($this->asFiles && !$this->inlineFactories) {
                $proxyLoader = "class_exists(\$class, false) || require __DIR__.'/'.\$class.'.php';\n\n        ";
            } else {
                $proxyLoader = '';
            }
            $code .= <<<EOF

    protected function createProxy(\$class, \\Closure \$factory)
    {
        {$proxyLoader}return \$factory();
    }

EOF;
            break;
        }
        return $code;
    }
    private function addSyntheticIds(): string
    {
        $code = '';
        $definitions = $this->container->getDefinitions();
        ksort($definitions);
        foreach ($definitions as $id => $definition) {
            if ($definition->isSynthetic() && 'service_container' !== $id) {
                $code .= '            ' . $this->doExport($id) . " => true,\n";
            }
        }
        return $code ? "        \$this->syntheticIds = [\n{$code}        ];\n" : '';
    }
    private function addRemovedIds(): string
    {
        $ids = $this->container->getRemovedIds();
        foreach ($this->container->getDefinitions() as $id => $definition) {
            if (!$definition->isPublic()) {
                $ids[$id] = \true;
            }
        }
        if (!$ids) {
            return '';
        }
        if ($this->asFiles) {
            $code = "require \$this->containerDir.\\DIRECTORY_SEPARATOR.'removed-ids.php'";
        } else {
            $code = '';
            $ids = array_keys($ids);
            sort($ids);
            foreach ($ids as $id) {
                if (preg_match(FileLoader::ANONYMOUS_ID_REGEXP, $id)) {
                    continue;
                }
                $code .= '            ' . $this->doExport($id) . " => true,\n";
            }
            $code = "[\n{$code}        ]";
        }
        return <<<EOF

    public function getRemovedIds(): array
    {
        return {$code};
    }

EOF;
    }
    private function addDeprecatedParameters(): string
    {
        if (!($bag = $this->container->getParameterBag()) instanceof ParameterBag) {
            return '';
        }
        if (!$deprecated = $bag->allDeprecated()) {
            return '';
        }
        $code = '';
        ksort($deprecated);
        foreach ($deprecated as $param => $deprecation) {
            $code .= '        ' . $this->doExport($param) . ' => [' . implode(', ', array_map($this->doExport(...), $deprecation)) . "],\n";
        }
        return "    private const DEPRECATED_PARAMETERS = [\n{$code}    ];\n\n";
    }
    private function addMethodMap(): string
    {
        $code = '';
        $definitions = $this->container->getDefinitions();
        ksort($definitions);
        foreach ($definitions as $id => $definition) {
            if (!$definition->isSynthetic() && $definition->isPublic() && (!$this->asFiles || $this->inlineFactories || $this->isHotPath($definition))) {
                $code .= '            ' . $this->doExport($id) . ' => ' . $this->doExport($this->generateMethodName($id)) . ",\n";
            }
        }
        $aliases = $this->container->getAliases();
        foreach ($aliases as $alias => $id) {
            if (!$id->isDeprecated()) {
                continue;
            }
            $code .= '            ' . $this->doExport($alias) . ' => ' . $this->doExport($this->generateMethodName($alias)) . ",\n";
        }
        return $code ? "        \$this->methodMap = [\n{$code}        ];\n" : '';
    }
    private function addFileMap(): string
    {
        $code = '';
        $definitions = $this->container->getDefinitions();
        ksort($definitions);
        foreach ($definitions as $id => $definition) {
            if (!$definition->isSynthetic() && $definition->isPublic() && !$this->isHotPath($definition)) {
                $code .= \sprintf("            %s => '%s',\n", $this->doExport($id), $this->generateMethodName($id));
            }
        }
        return $code ? "        \$this->fileMap = [\n{$code}        ];\n" : '';
    }
    private function addAliases(): string
    {
        if (!$aliases = $this->container->getAliases()) {
            return "\n        \$this->aliases = [];\n";
        }
        $code = "        \$this->aliases = [\n";
        ksort($aliases);
        foreach ($aliases as $alias => $id) {
            if ($id->isDeprecated()) {
                continue;
            }
            $id = (string) $id;
            while (isset($aliases[$id])) {
                $id = (string) $aliases[$id];
            }
            $code .= '            ' . $this->doExport($alias) . ' => ' . $this->doExport($id) . ",\n";
        }
        return $code . "        ];\n";
    }
    private function addDeprecatedAliases(): string
    {
        $code = '';
        $aliases = $this->container->getAliases();
        foreach ($aliases as $alias => $definition) {
            if (!$definition->isDeprecated()) {
                continue;
            }
            $public = $definition->isPublic() ? 'public' : 'private';
            $id = (string) $definition;
            $methodNameAlias = $this->generateMethodName($alias);
            $idExported = $this->export($id);
            $deprecation = $definition->getDeprecation($alias);
            $packageExported = $this->export($deprecation['package']);
            $versionExported = $this->export($deprecation['version']);
            $messageExported = $this->export($deprecation['message']);
            $code .= <<<EOF

    /*{$this->docStar}
     * Gets the {$public} '{$alias}' alias.
     *
     * @return object The "{$id}" service.
     */
    protected static function {$methodNameAlias}(\$container)
    {
        trigger_deprecation({$packageExported}, {$versionExported}, {$messageExported});

        return \$container->get({$idExported});
    }

EOF;
        }
        return $code;
    }
    private function addInlineRequires(bool $hasProxyClasses): string
    {
        $lineage = [];
        $hotPathServices = $this->hotPathTag && $this->inlineRequires ? $this->container->findTaggedServiceIds($this->hotPathTag) : [];
        foreach ($hotPathServices as $id => $tags) {
            $definition = $this->container->getDefinition($id);
            if ($definition->isLazy() && $this->hasProxyDumper) {
                continue;
            }
            $inlinedDefinitions = $this->getDefinitionsFromArguments([$definition]);
            foreach ($inlinedDefinitions as $def) {
                foreach ($this->getClasses($def, $id) as $class) {
                    $this->collectLineage($class, $lineage);
                }
            }
        }
        $code = '';
        foreach ($lineage as $file) {
            if (!isset($this->inlinedRequires[$file])) {
                $this->inlinedRequires[$file] = \true;
                $code .= \sprintf("\n            include_once %s;", $file);
            }
        }
        if ($hasProxyClasses) {
            $code .= "\n            include_once __DIR__.'/proxy-classes.php';";
        }
        return $code ? \sprintf("\n        \$this->privates['service_container'] = static function (\$container) {%s\n        };\n", $code) : '';
    }
    private function needsUnsetParameterBag(): bool
    {
        if (Container::class === $this->baseClass) {
            return \false;
        }
        $r = $this->container->getReflectionClass($this->baseClass, \false);
        return null !== $r && null !== ($constructor = $r->getConstructor()) && 0 === $constructor->getNumberOfRequiredParameters() && Container::class !== $constructor->getDeclaringClass()->name;
    }
    private function addDefaultParametersMethod(): string
    {
        if (!$this->container->getParameterBag()->all() && !$this->needsUnsetParameterBag()) {
            return '';
        }
        $php = [];
        $dynamicPhp = [];
        foreach ($this->container->getParameterBag()->all() as $key => $value) {
            if ($key !== $resolvedKey = $this->container->resolveEnvPlaceholders($key)) {
                throw new InvalidArgumentException(\sprintf('Parameter name cannot use env parameters: "%s".', $resolvedKey));
            }
            $hasEnum = \false;
            $export = $this->exportParameters([$value], '', 12, $hasEnum);
            $export = explode('0 => ', substr(rtrim($export, " ]\n"), 2, -1), 2);
            if ($hasEnum || preg_match("/\\\$container->(?:getEnv\\('(?:[-.\\w\\\\]*+:)*+\\w*+'\\)|targetDir\\.'')/", $export[1])) {
                $dynamicPhp[$key] = \sprintf('%s%s => %s,', $export[0], $this->export($key), $export[1]);
                $this->dynamicParameters[$key] = \true;
            } else {
                $php[] = \sprintf('%s%s => %s,', $export[0], $this->export($key), $export[1]);
            }
        }
        $parameters = \sprintf("[\n%s\n%s]", implode("\n", $php), str_repeat(' ', 8));
        $code = <<<'EOF'

    public function getParameter(string $name): array|bool|string|int|float|\UnitEnum|null
    {
        if (isset(self::DEPRECATED_PARAMETERS[$name])) {
            trigger_deprecation(...self::DEPRECATED_PARAMETERS[$name]);
        }

        if (\array_key_exists($name, $this->buildParameters)) {
            return $this->buildParameters[$name];
        }

        if (isset($this->loadedDynamicParameters[$name])) {
            return $this->loadedDynamicParameters[$name] ? $this->dynamicParameters[$name] : $this->getDynamicParameter($name);
        }

        if (!\array_key_exists($name, $this->parameters) || '.' === ($name[0] ?? '')) {
            throw new ParameterNotFoundException($name);
        }

        return $this->parameters[$name];
    }

    public function hasParameter(string $name): bool
    {
        if (\array_key_exists($name, $this->buildParameters)) {
            return true;
        }

        return \array_key_exists($name, $this->parameters) || isset($this->loadedDynamicParameters[$name]);
    }

    public function setParameter(string $name, $value): void
    {
        throw new LogicException('Impossible to call set() on a frozen ParameterBag.');
    }

    public function getParameterBag(): ParameterBagInterface
    {
        if (!isset($this->parameterBag)) {
            $parameters = $this->parameters;
            foreach ($this->loadedDynamicParameters as $name => $loaded) {
                $parameters[$name] = $loaded ? $this->dynamicParameters[$name] : $this->getDynamicParameter($name);
            }
            foreach ($this->buildParameters as $name => $value) {
                $parameters[$name] = $value;
            }
            $this->parameterBag = new FrozenParameterBag($parameters, self::DEPRECATED_PARAMETERS);
        }

        return $this->parameterBag;
    }

EOF;
        if (!$this->asFiles) {
            $code = preg_replace('/^.*buildParameters.*\n.*\n.*\n\n?/m', '', $code);
        }
        if (!($bag = $this->container->getParameterBag()) instanceof ParameterBag || !$bag->allDeprecated()) {
            $code = preg_replace("/\n.*DEPRECATED_PARAMETERS.*\n.*\n.*\n/m", '', $code, 1);
            $code = str_replace(', self::DEPRECATED_PARAMETERS', '', $code);
        }
        if ($dynamicPhp) {
            $loadedDynamicParameters = $this->exportParameters(array_combine(array_keys($dynamicPhp), array_fill(0, \count($dynamicPhp), \false)), '', 8);
            $getDynamicParameter = <<<'EOF'
        $container = $this;
        $value = match ($name) {
%s
            default => throw new ParameterNotFoundException($name),
        };
        $this->loadedDynamicParameters[$name] = true;

        return $this->dynamicParameters[$name] = $value;
EOF;
            $getDynamicParameter = \sprintf($getDynamicParameter, implode("\n", $dynamicPhp));
        } else {
            $loadedDynamicParameters = '[]';
            $getDynamicParameter = str_repeat(' ', 8) . 'throw new ParameterNotFoundException($name);';
        }
        $code .= <<<EOF

    private \$loadedDynamicParameters = {$loadedDynamicParameters};
    private \$dynamicParameters = [];

    private function getDynamicParameter(string \$name)
    {
{$getDynamicParameter}
    }

    protected function getDefaultParameters(): array
    {
        return {$parameters};
    }

EOF;
        return $code;
    }
    /**
     * @throws InvalidArgumentException
     */
    private function exportParameters(array $parameters, string $path = '', int $indent = 12, bool &$hasEnum = \false): string
    {
        $php = [];
        foreach ($parameters as $key => $value) {
            if (\is_array($value)) {
                $value = $this->exportParameters($value, $path . '/' . $key, $indent + 4, $hasEnum);
            } elseif ($value instanceof ArgumentInterface) {
                throw new InvalidArgumentException(\sprintf('You cannot dump a container with parameters that contain special arguments. "%s" found in "%s".', get_debug_type($value), $path . '/' . $key));
            } elseif ($value instanceof Variable) {
                throw new InvalidArgumentException(\sprintf('You cannot dump a container with parameters that contain variable references. Variable "%s" found in "%s".', $value, $path . '/' . $key));
            } elseif ($value instanceof Definition) {
                throw new InvalidArgumentException(\sprintf('You cannot dump a container with parameters that contain service definitions. Definition for "%s" found in "%s".', $value->getClass(), $path . '/' . $key));
            } elseif ($value instanceof Reference) {
                throw new InvalidArgumentException(\sprintf('You cannot dump a container with parameters that contain references to other services (reference to service "%s" found in "%s").', $value, $path . '/' . $key));
            } elseif ($value instanceof Expression) {
                throw new InvalidArgumentException(\sprintf('You cannot dump a container with parameters that contain expressions. Expression "%s" found in "%s".', $value, $path . '/' . $key));
            } elseif ($value instanceof \UnitEnum) {
                $hasEnum = \true;
                $value = \sprintf('\%s::%s', $value::class, $value->name);
            } else {
                $value = $this->export($value);
            }
            $php[] = \sprintf('%s%s => %s,', str_repeat(' ', $indent), $this->export($key), $value);
        }
        return \sprintf("[\n%s\n%s]", implode("\n", $php), str_repeat(' ', $indent - 4));
    }
    private function endClass(): string
    {
        return <<<'EOF'
}

EOF;
    }
    private function wrapServiceConditionals(mixed $value, string $code): string
    {
        if (!$condition = $this->getServiceConditionals($value)) {
            return $code;
        }
        // re-indent the wrapped code
        $code = implode("\n", array_map(fn($line) => $line ? '    ' . $line : $line, explode("\n", $code)));
        return \sprintf("        if (%s) {\n%s        }\n", $condition, $code);
    }
    private function getServiceConditionals(mixed $value): string
    {
        $conditions = [];
        foreach (ContainerBuilder::getInitializedConditionals($value) as $service) {
            if (!$this->container->hasDefinition($service)) {
                return 'false';
            }
            $conditions[] = \sprintf('isset($container->%s[%s])', $this->container->getDefinition($service)->isPublic() ? 'services' : 'privates', $this->doExport($service));
        }
        foreach (ContainerBuilder::getServiceConditionals($value) as $service) {
            if ($this->container->hasDefinition($service) && !$this->container->getDefinition($service)->isPublic()) {
                continue;
            }
            $conditions[] = \sprintf('$container->has(%s)', $this->doExport($service));
        }
        if (!$conditions) {
            return '';
        }
        return implode(' && ', $conditions);
    }
    private function getDefinitionsFromArguments(array $arguments, ?\SplObjectStorage $definitions = null, array &$calls = [], ?bool $byConstructor = null): \SplObjectStorage
    {
        $definitions ??= new \SplObjectStorage();
        foreach ($arguments as $argument) {
            if (\is_array($argument)) {
                $this->getDefinitionsFromArguments($argument, $definitions, $calls, $byConstructor);
            } elseif ($argument instanceof Reference) {
                $id = (string) $argument;
                while ($this->container->hasAlias($id)) {
                    $id = (string) $this->container->getAlias($id);
                }
                if (!isset($calls[$id])) {
                    $calls[$id] = [0, $argument->getInvalidBehavior(), $byConstructor];
                } else {
                    $calls[$id][1] = min($calls[$id][1], $argument->getInvalidBehavior());
                }
                ++$calls[$id][0];
            } elseif (!$argument instanceof Definition) {
                // no-op
            } elseif (isset($definitions[$argument])) {
                $definitions[$argument] = 1 + $definitions[$argument];
            } else {
                $definitions[$argument] = 1;
                $arguments = [$argument->getArguments(), $argument->getFactory()];
                $this->getDefinitionsFromArguments($arguments, $definitions, $calls, null === $byConstructor || $byConstructor);
                $arguments = [$argument->getProperties(), $argument->getMethodCalls(), $argument->getConfigurator()];
                $this->getDefinitionsFromArguments($arguments, $definitions, $calls, null !== $byConstructor && $byConstructor);
            }
        }
        return $definitions;
    }
    /**
     * @throws RuntimeException
     */
    private function dumpValue(mixed $value, bool $interpolate = \true): string
    {
        if (\is_array($value)) {
            if ($value && $interpolate && \false !== $param = array_search($value, $this->container->getParameterBag()->all(), \true)) {
                return $this->dumpValue("%{$param}%");
            }
            $isList = array_is_list($value);
            $code = [];
            foreach ($value as $k => $v) {
                $code[] = $isList ? $this->dumpValue($v, $interpolate) : \sprintf('%s => %s', $this->dumpValue($k, $interpolate), $this->dumpValue($v, $interpolate));
            }
            return \sprintf('[%s]', implode(', ', $code));
        } elseif ($value instanceof ArgumentInterface) {
            $scope = [$this->definitionVariables, $this->referenceVariables];
            $this->definitionVariables = $this->referenceVariables = null;
            try {
                if ($value instanceof ServiceClosureArgument) {
                    $value = $value->getValues()[0];
                    $code = $this->dumpValue($value, $interpolate);
                    $returnedType = '';
                    if ($value instanceof TypedReference) {
                        $type = $value->getType();
                        $nullable = ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE >= $value->getInvalidBehavior() ? '' : '?';
                        if ('?' === ($type[0] ?? '')) {
                            $type = substr($type, 1);
                            $nullable = '?';
                        }
                        $returnedType = \sprintf(': %s\%s', $nullable, str_replace(['|', '&'], ['|\\', '&\\'], $type));
                    }
                    $attribute = '';
                    if ($value instanceof Reference) {
                        $attribute = 'name: ' . $this->dumpValue((string) $value, $interpolate);
                        if ($this->container->hasDefinition($value) && ($class = $this->container->findDefinition($value)->getClass()) && $class !== (string) $value) {
                            $attribute .= ', class: ' . $this->dumpValue($class, $interpolate);
                        }
                        $attribute = \sprintf('#[\Closure(%s)] ', $attribute);
                    }
                    return \sprintf('%sfn ()%s => %s', $attribute, $returnedType, $code);
                }
                if ($value instanceof IteratorArgument) {
                    if (!$values = $value->getValues()) {
                        return 'new RewindableGenerator(fn () => new \EmptyIterator(), 0)';
                    }
                    $code = [];
                    $code[] = 'new RewindableGenerator(function () use ($container) {';
                    $operands = [0];
                    foreach ($values as $k => $v) {
                        ($c = $this->getServiceConditionals($v)) ? $operands[] = "(int) ({$c})" : ++$operands[0];
                        $v = $this->wrapServiceConditionals($v, \sprintf("        yield %s => %s;\n", $this->dumpValue($k, $interpolate), $this->dumpValue($v, $interpolate)));
                        foreach (explode("\n", $v) as $v) {
                            if ($v) {
                                $code[] = '    ' . $v;
                            }
                        }
                    }
                    $code[] = \sprintf('        }, %s)', \count($operands) > 1 ? 'fn () => ' . implode(' + ', $operands) : $operands[0]);
                    return implode("\n", $code);
                }
                if ($value instanceof ServiceLocatorArgument) {
                    $serviceMap = '';
                    $serviceTypes = '';
                    foreach ($value->getValues() as $k => $v) {
                        if (!$v instanceof Reference) {
                            $serviceMap .= \sprintf("\n            %s => [%s],", $this->export($k), $this->dumpValue($v));
                            $serviceTypes .= \sprintf("\n            %s => '?',", $this->export($k));
                            continue;
                        }
                        $id = (string) $v;
                        while ($this->container->hasAlias($id)) {
                            $id = (string) $this->container->getAlias($id);
                        }
                        $definition = $this->container->getDefinition($id);
                        $load = !($definition->hasErrors() && $e = $definition->getErrors()) ? $this->asFiles && !$this->inlineFactories && !$this->isHotPath($definition) : reset($e);
                        $serviceMap .= \sprintf("\n            %s => [%s, %s, %s, %s],", $this->export($k), $this->export($definition->isShared() ? $definition->isPublic() ? 'services' : 'privates' : \false), $this->doExport($id), $this->export(ContainerInterface::IGNORE_ON_UNINITIALIZED_REFERENCE !== $v->getInvalidBehavior() && !\is_string($load) ? $this->generateMethodName($id) : null), $this->export($load));
                        $serviceTypes .= \sprintf("\n            %s => %s,", $this->export($k), $this->export($v instanceof TypedReference ? $v->getType() : '?'));
                        $this->locatedIds[$id] = \true;
                    }
                    $this->addGetService = \true;
                    return \sprintf('new \%s($container->getService ??= $container->getService(...), [%s%s], [%s%s])', ServiceLocator::class, $serviceMap, $serviceMap ? "\n        " : '', $serviceTypes, $serviceTypes ? "\n        " : '');
                }
            } finally {
                [$this->definitionVariables, $this->referenceVariables] = $scope;
            }
        } elseif ($value instanceof Definition) {
            if ($value->hasErrors() && $e = $value->getErrors()) {
                return \sprintf('throw new RuntimeException(%s)', $this->export(reset($e)));
            }
            if ($this->definitionVariables?->offsetExists($value)) {
                return $this->dumpValue($this->definitionVariables[$value], $interpolate);
            }
            if ($value->getMethodCalls()) {
                throw new RuntimeException('Cannot dump definitions which have method calls.');
            }
            if ($value->getProperties()) {
                throw new RuntimeException('Cannot dump definitions which have properties.');
            }
            if (null !== $value->getConfigurator()) {
                throw new RuntimeException('Cannot dump definitions which have a configurator.');
            }
            return $this->addNewInstance($value);
        } elseif ($value instanceof Variable) {
            return '$' . $value;
        } elseif ($value instanceof Reference) {
            $id = (string) $value;
            while ($this->container->hasAlias($id)) {
                $id = (string) $this->container->getAlias($id);
            }
            if (null !== $this->referenceVariables && isset($this->referenceVariables[$id])) {
                return $this->dumpValue($this->referenceVariables[$id], $interpolate);
            }
            return $this->getServiceCall($id, $value);
        } elseif ($value instanceof Expression) {
            return $this->getExpressionLanguage()->compile((string) $value, ['container' => 'container']);
        } elseif ($value instanceof Parameter) {
            return $this->dumpParameter($value);
        } elseif (\true === $interpolate && \is_string($value)) {
            if (preg_match('/^%([^%]+)%$/', $value, $match)) {
                // we do this to deal with non string values (Boolean, integer, ...)
                // the preg_replace_callback converts them to strings
                return $this->dumpParameter($match[1]);
            } else {
                $replaceParameters = fn($match) => "'." . $this->dumpParameter($match[2]) . ".'";
                $code = str_replace('%%', '%', preg_replace_callback('/(?<!%)(%)([^%]+)\1/', $replaceParameters, $this->export($value)));
                return $code;
            }
        } elseif ($value instanceof \UnitEnum) {
            return \sprintf('\%s::%s', $value::class, $value->name);
        } elseif ($value instanceof AbstractArgument) {
            throw new RuntimeException($value->getTextWithContext());
        } elseif (\is_object($value) || \is_resource($value)) {
            throw new RuntimeException(\sprintf('Unable to dump a service container if a parameter is an object or a resource, got "%s".', get_debug_type($value)));
        }
        return $this->export($value);
    }
    /**
     * Dumps a string to a literal (aka PHP Code) class value.
     *
     * @throws RuntimeException
     */
    private function dumpLiteralClass(string $class): string
    {
        if (str_contains($class, '$')) {
            return \sprintf('${($_ = %s) && false ?: "_"}', $class);
        }
        if (!str_starts_with($class, "'") || !preg_match('/^\'(?:\\\\{2})?[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*(?:\\\\{2}[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*)*\'$/', $class)) {
            throw new RuntimeException(\sprintf('Cannot dump definition because of invalid class name (%s).', $class ?: 'n/a'));
        }
        $class = substr(str_replace('\\\\', '\\', $class), 1, -1);
        return str_starts_with($class, '\\') ? $class : '\\' . $class;
    }
    private function dumpParameter(string $name): string
    {
        if (!$this->container->hasParameter($name) || ($this->dynamicParameters[$name] ?? \false)) {
            return \sprintf('$container->getParameter(%s)', $this->doExport($name));
        }
        $value = $this->container->getParameter($name);
        $dumpedValue = $this->dumpValue($value, \false);
        if (!$value || !\is_array($value)) {
            return $dumpedValue;
        }
        return \sprintf('$container->parameters[%s]', $this->doExport($name));
    }
    private function getServiceCall(string $id, ?Reference $reference = null): string
    {
        while ($this->container->hasAlias($id)) {
            $id = (string) $this->container->getAlias($id);
        }
        if ('service_container' === $id) {
            return '$container';
        }
        if ($this->container->hasDefinition($id) && $definition = $this->container->getDefinition($id)) {
            if ($definition->isSynthetic()) {
                $code = \sprintf('$container->get(%s%s)', $this->doExport($id), null !== $reference ? ', ' . $reference->getInvalidBehavior() : '');
            } elseif (null !== $reference && ContainerInterface::IGNORE_ON_UNINITIALIZED_REFERENCE === $reference->getInvalidBehavior()) {
                $code = 'null';
                if (!$definition->isShared()) {
                    return $code;
                }
            } elseif ($this->isTrivialInstance($definition)) {
                if ($definition->hasErrors() && $e = $definition->getErrors()) {
                    return \sprintf('throw new RuntimeException(%s)', $this->export(reset($e)));
                }
                $code = $this->addNewInstance($definition, '', $id);
                if ($definition->isShared() && !isset($this->singleUsePrivateIds[$id])) {
                    return \sprintf('($container->%s[%s] ??= %s)', $definition->isPublic() ? 'services' : 'privates', $this->doExport($id), $code);
                }
                $code = "({$code})";
            } else {
                $code = $this->asFiles && !$this->inlineFactories && !$this->isHotPath($definition) ? "\$container->load('%s')" : 'self::%s($container)';
                $code = \sprintf($code, $this->generateMethodName($id));
                if (!$definition->isShared()) {
                    $factory = \sprintf('$container->factories%s[%s]', $definition->isPublic() ? '' : "['service_container']", $this->doExport($id));
                    $code = \sprintf('(isset(%s) ? %1$s($container) : %s)', $factory, $code);
                }
            }
            if ($definition->isShared() && !isset($this->singleUsePrivateIds[$id])) {
                $code = \sprintf('($container->%s[%s] ?? %s)', $definition->isPublic() ? 'services' : 'privates', $this->doExport($id), $code);
            }
            return $code;
        }
        if (null !== $reference && ContainerInterface::IGNORE_ON_UNINITIALIZED_REFERENCE === $reference->getInvalidBehavior()) {
            return 'null';
        }
        if (null !== $reference && ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE < $reference->getInvalidBehavior()) {
            $code = \sprintf('$container->get(%s, ContainerInterface::NULL_ON_INVALID_REFERENCE)', $this->doExport($id));
        } else {
            $code = \sprintf('$container->get(%s)', $this->doExport($id));
        }
        return \sprintf('($container->services[%s] ?? %s)', $this->doExport($id), $code);
    }
    /**
     * Initializes the method names map to avoid conflicts with the Container methods.
     */
    private function initializeMethodNamesMap(string $class): void
    {
        $this->serviceIdToMethodNameMap = [];
        $this->usedMethodNames = [];
        if ($reflectionClass = $this->container->getReflectionClass($class)) {
            foreach ($reflectionClass->getMethods() as $method) {
                $this->usedMethodNames[strtolower($method->getName())] = \true;
            }
        }
    }
    /**
     * @throws InvalidArgumentException
     */
    private function generateMethodName(string $id): string
    {
        if (isset($this->serviceIdToMethodNameMap[$id])) {
            return $this->serviceIdToMethodNameMap[$id];
        }
        $i = strrpos($id, '\\');
        $name = Container::camelize(\false !== $i && isset($id[1 + $i]) ? substr($id, 1 + $i) : $id);
        $name = preg_replace('/[^a-zA-Z0-9_\x7f-\xff]/', '', $name);
        $methodName = 'get' . $name . 'Service';
        $suffix = 1;
        while (isset($this->usedMethodNames[strtolower($methodName)])) {
            ++$suffix;
            $methodName = 'get' . $name . $suffix . 'Service';
        }
        $this->serviceIdToMethodNameMap[$id] = $methodName;
        $this->usedMethodNames[strtolower($methodName)] = \true;
        return $methodName;
    }
    private function getNextVariableName(): string
    {
        $firstChars = self::FIRST_CHARS;
        $firstCharsLength = \strlen($firstChars);
        $nonFirstChars = self::NON_FIRST_CHARS;
        $nonFirstCharsLength = \strlen($nonFirstChars);
        while (\true) {
            $name = '';
            $i = $this->variableCount;
            if ('' === $name) {
                $name .= $firstChars[$i % $firstCharsLength];
                $i = (int) ($i / $firstCharsLength);
            }
            while ($i > 0) {
                --$i;
                $name .= $nonFirstChars[$i % $nonFirstCharsLength];
                $i = (int) ($i / $nonFirstCharsLength);
            }
            ++$this->variableCount;
            // check that the name is not reserved
            if (\in_array($name, $this->reservedVariables, \true)) {
                continue;
            }
            return $name;
        }
    }
    private function getExpressionLanguage(): ExpressionLanguage
    {
        if (!isset($this->expressionLanguage)) {
            if (!class_exists(\_ContaoManager\Symfony\Component\ExpressionLanguage\ExpressionLanguage::class)) {
                throw new LogicException('Unable to use expressions as the Symfony ExpressionLanguage component is not installed. Try running "composer require symfony/expression-language".');
            }
            $providers = $this->container->getExpressionLanguageProviders();
            $this->expressionLanguage = new ExpressionLanguage(null, $providers, function ($arg) {
                $id = '""' === substr_replace($arg, '', 1, -1) ? stripcslashes(substr($arg, 1, -1)) : null;
                if (null !== $id && ($this->container->hasAlias($id) || $this->container->hasDefinition($id))) {
                    return $this->getServiceCall($id);
                }
                return \sprintf('$container->get(%s)', $arg);
            });
            if ($this->container->isTrackingResources()) {
                foreach ($providers as $provider) {
                    $this->container->addObjectResource($provider);
                }
            }
        }
        return $this->expressionLanguage;
    }
    private function isHotPath(Definition $definition): bool
    {
        return $this->hotPathTag && $definition->hasTag($this->hotPathTag) && !$definition->isDeprecated();
    }
    private function isSingleUsePrivateNode(ServiceReferenceGraphNode $node): bool
    {
        if ($node->getValue()->isPublic()) {
            return \false;
        }
        $ids = [];
        foreach ($node->getInEdges() as $edge) {
            if (!$value = $edge->getSourceNode()->getValue()) {
                continue;
            }
            if ($edge->isLazy() || !$value instanceof Definition || !$value->isShared() || $edge->isFromMultiUseArgument()) {
                return \false;
            }
            // When the source node is a proxy or ghost, it will construct its references only when the node itself is initialized.
            // Since the node can be cloned before being fully initialized, we do not know how often its references are used.
            if ($this->getProxyDumper()->isProxyCandidate($value)) {
                return \false;
            }
            $ids[$edge->getSourceNode()->getId()] = \true;
        }
        return 1 === \count($ids);
    }
    private function export(mixed $value): mixed
    {
        if (null !== $this->targetDirRegex && \is_string($value) && preg_match($this->targetDirRegex, $value, $matches, \PREG_OFFSET_CAPTURE)) {
            $suffix = $matches[0][1] + \strlen($matches[0][0]);
            $matches[0][1] += \strlen($matches[1][0]);
            $prefix = $matches[0][1] ? $this->doExport(substr($value, 0, $matches[0][1]), \true) . '.' : '';
            if ('\\' === \DIRECTORY_SEPARATOR && isset($value[$suffix])) {
                $cookie = '\\' . random_int(100000, \PHP_INT_MAX);
                $suffix = '.' . $this->doExport(str_replace('\\', $cookie, substr($value, $suffix)), \true);
                $suffix = str_replace('\\' . $cookie, "'.\\DIRECTORY_SEPARATOR.'", $suffix);
            } else {
                $suffix = isset($value[$suffix]) ? '.' . $this->doExport(substr($value, $suffix), \true) : '';
            }
            $dirname = $this->asFiles ? '$container->containerDir' : '__DIR__';
            $offset = 2 + $this->targetDirMaxMatches - \count($matches);
            if (0 < $offset) {
                $dirname = \sprintf('\dirname(__DIR__, %d)', $offset + (int) $this->asFiles);
            } elseif ($this->asFiles) {
                $dirname = "\$container->targetDir.''";
                // empty string concatenation on purpose
            }
            if ($prefix || $suffix) {
                return \sprintf('(%s%s%s)', $prefix, $dirname, $suffix);
            }
            return $dirname;
        }
        return $this->doExport($value, \true);
    }
    private function doExport(mixed $value, bool $resolveEnv = \false): mixed
    {
        $shouldCacheValue = $resolveEnv && \is_string($value);
        if ($shouldCacheValue && isset($this->exportedVariables[$value])) {
            return $this->exportedVariables[$value];
        }
        if (\is_string($value) && str_contains($value, "\n")) {
            $cleanParts = explode("\n", $value);
            $cleanParts = array_map(fn($part) => var_export($part, \true), $cleanParts);
            $export = implode('."\n".', $cleanParts);
        } else {
            $export = var_export($value, \true);
        }
        if ($resolveEnv && "'" === $export[0] && $export !== $resolvedExport = $this->container->resolveEnvPlaceholders($export, "'.\$container->getEnv('string:%s').'")) {
            $export = $resolvedExport;
            if (str_ends_with($export, ".''")) {
                $export = substr($export, 0, -3);
                if ("'" === $export[1]) {
                    $export = substr_replace($export, '', 23, 7);
                }
            }
            if ("'" === $export[1]) {
                $export = substr($export, 3);
            }
        }
        if ($shouldCacheValue) {
            $this->exportedVariables[$value] = $export;
        }
        return $export;
    }
    private function getAutoloadFile(): ?string
    {
        $file = null;
        foreach (spl_autoload_functions() as $autoloader) {
            if (!\is_array($autoloader)) {
                continue;
            }
            if ($autoloader[0] instanceof DebugClassLoader) {
                $autoloader = $autoloader[0]->getClassLoader();
            }
            if (!\is_array($autoloader) || !$autoloader[0] instanceof ClassLoader || !$autoloader[0]->findFile(__CLASS__)) {
                continue;
            }
            foreach (get_declared_classes() as $class) {
                if (str_starts_with($class, 'ComposerAutoloaderInit') && $class::getLoader() === $autoloader[0]) {
                    $file = \dirname((new \ReflectionClass($class))->getFileName(), 2) . '/autoload.php';
                    if (null !== $this->targetDirRegex && preg_match($this->targetDirRegex . 'A', $file)) {
                        return $file;
                    }
                }
            }
        }
        return $file;
    }
    private function getClasses(Definition $definition, string $id): array
    {
        $classes = [];
        while ($definition instanceof Definition) {
            foreach ($definition->getTag($this->preloadTags[0]) as $tag) {
                if (!isset($tag['class'])) {
                    throw new InvalidArgumentException(\sprintf('Missing attribute "class" on tag "%s" for service "%s".', $this->preloadTags[0], $id));
                }
                $classes[] = trim($tag['class'], '\\');
            }
            if ($class = $definition->getClass()) {
                $classes[] = trim($class, '\\');
            }
            $factory = $definition->getFactory();
            if (\is_string($factory) && !str_starts_with($factory, '@=') && str_contains($factory, '::')) {
                $factory = explode('::', $factory);
            }
            if (!\is_array($factory)) {
                $definition = $factory;
                continue;
            }
            $definition = $factory[0] ?? null;
            if (\is_string($definition)) {
                $classes[] = trim($factory[0], '\\');
            }
        }
        return $classes;
    }
    private function isProxyCandidate(Definition $definition, ?bool &$asGhostObject, string $id): ?Definition
    {
        $asGhostObject = \false;
        if (['Closure', 'fromCallable'] === $definition->getFactory()) {
            return null;
        }
        if (!$definition->isLazy() || !$this->hasProxyDumper) {
            return null;
        }
        return $this->getProxyDumper()->isProxyCandidate($definition, $asGhostObject, $id) ? $definition : null;
    }
    /**
     * Removes comments from a PHP source string.
     *
     * We don't use the PHP php_strip_whitespace() function
     * as we want the content to be readable and well-formatted.
     */
    private static function stripComments(string $source): string
    {
        if (!\function_exists('token_get_all') && !\function_exists('_ContaoManager\token_get_all')) {
            return $source;
        }
        $rawChunk = '';
        $output = '';
        $tokens = token_get_all($source);
        $ignoreSpace = \false;
        for ($i = 0; isset($tokens[$i]); ++$i) {
            $token = $tokens[$i];
            if (!isset($token[1]) || 'b"' === $token) {
                $rawChunk .= $token;
            } elseif (\T_START_HEREDOC === $token[0]) {
                $output .= $rawChunk . $token[1];
                do {
                    $token = $tokens[++$i];
                    $output .= isset($token[1]) && 'b"' !== $token ? $token[1] : $token;
                } while (\T_END_HEREDOC !== $token[0]);
                $rawChunk = '';
            } elseif (\T_WHITESPACE === $token[0]) {
                if ($ignoreSpace) {
                    $ignoreSpace = \false;
                    continue;
                }
                // replace multiple new lines with a single newline
                $rawChunk .= preg_replace(['/\n{2,}/S'], "\n", $token[1]);
            } elseif (\in_array($token[0], [\T_COMMENT, \T_DOC_COMMENT])) {
                if (!\in_array($rawChunk[\strlen($rawChunk) - 1], [' ', "\n", "\r", "\t"], \true)) {
                    $rawChunk .= ' ';
                }
                $ignoreSpace = \true;
            } else {
                $rawChunk .= $token[1];
                // The PHP-open tag already has a new-line
                if (\T_OPEN_TAG === $token[0]) {
                    $ignoreSpace = \true;
                } else {
                    $ignoreSpace = \false;
                }
            }
        }
        $output .= $rawChunk;
        unset($tokens, $rawChunk);
        gc_mem_caches();
        return $output;
    }
}
{
    "name": "symfony\/dependency-injection",
    "type": "library",
    "description": "Allows you to standardize and centralize the way objects are constructed in your application",
    "keywords": [],
    "homepage": "https:\/\/symfony.com",
    "license": "MIT",
    "authors": [
        {
            "name": "Fabien Potencier",
            "email": "fabien@symfony.com"
        },
        {
            "name": "Symfony Community",
            "homepage": "https:\/\/symfony.com\/contributors"
        }
    ],
    "require": {
        "php": ">=8.1",
        "psr\/container": "^1.1|^2.0",
        "symfony\/deprecation-contracts": "^2.5|^3",
        "symfony\/service-contracts": "^2.5|^3.0",
        "symfony\/var-exporter": "^6.4.20|^7.2.5"
    },
    "require-dev": {
        "symfony\/yaml": "^5.4|^6.0|^7.0",
        "symfony\/config": "^6.1|^7.0",
        "symfony\/expression-language": "^5.4|^6.0|^7.0"
    },
    "conflict": {
        "ext-psr": "<1.1|>=2",
        "symfony\/config": "<6.1",
        "symfony\/finder": "<5.4",
        "symfony\/proxy-manager-bridge": "<6.3",
        "symfony\/yaml": "<5.4"
    },
    "provide": {
        "psr\/container-implementation": "1.1|2.0",
        "symfony\/service-implementation": "1.1|2.0|3.0"
    },
    "autoload": {
        "psr-4": {
            "_ContaoManager\\Symfony\\Component\\DependencyInjection\\": ""
        },
        "exclude-from-classmap": [
            "\/Tests\/"
        ]
    },
    "minimum-stability": "dev"
}<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\DependencyInjection;

/**
 * EnvVarLoaderInterface objects return key/value pairs that are added to the list of available env vars.
 *
 * @author Nicolas Grekas <p@tchwork.com>
 */
interface EnvVarLoaderInterface
{
    /**
     * @return array<string|\Stringable> Key/value pairs that can be accessed using the regular "%env()%" syntax
     */
    public function loadEnvVars(): array;
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\DependencyInjection;

/**
 * ContainerAwareInterface should be implemented by classes that depends on a Container.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 *
 * @deprecated since Symfony 6.4, use dependency injection instead
 */
interface ContainerAwareInterface
{
    /**
     * Sets the container.
     *
     * @return void
     */
    public function setContainer(?ContainerInterface $container);
}
Copyright (c) 2022-present Fabien Potencier

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is furnished
to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Clock\Test;

use _ContaoManager\PHPUnit\Framework\Attributes\After;
use _ContaoManager\PHPUnit\Framework\Attributes\Before;
use _ContaoManager\PHPUnit\Framework\Attributes\BeforeClass;
use _ContaoManager\Psr\Clock\ClockInterface;
use _ContaoManager\Symfony\Component\Clock\Clock;
use _ContaoManager\Symfony\Component\Clock\MockClock;
use function _ContaoManager\Symfony\Component\Clock\now;
/**
 * Helps with mocking the time in your test cases.
 *
 * This trait provides one self::mockTime() method that freezes the time.
 * It restores the global clock after each test case.
 * self::mockTime() accepts either a string (eg '+1 days' or '2022-12-22'),
 * a DateTimeImmutable, or a boolean (to freeze/restore the global clock).
 *
 * @author Nicolas Grekas <p@tchwork.com>
 */
trait ClockSensitiveTrait
{
    public static function mockTime(string|\DateTimeImmutable|bool $when = \true): ClockInterface
    {
        Clock::set(match (\true) {
            \false === $when => self::saveClockBeforeTest(\false),
            \true === $when => new MockClock(),
            $when instanceof \DateTimeImmutable => new MockClock($when),
            default => new MockClock(now($when)),
        });
        return Clock::get();
    }
    /**
     * @beforeClass
     *
     * @before
     *
     * @internal
     */
    #[Before]
    #[BeforeClass]
    public static function saveClockBeforeTest(bool $save = \true): ClockInterface
    {
        static $originalClock;
        if ($save && $originalClock) {
            self::restoreClockAfterTest();
        }
        return $save ? $originalClock = Clock::get() : $originalClock;
    }
    /**
     * @after
     *
     * @internal
     */
    #[After]
    protected static function restoreClockAfterTest(): void
    {
        Clock::set(self::saveClockBeforeTest(\false));
    }
}
CHANGELOG
=========

6.4
---

 * Add `DatePoint`: an immutable DateTime implementation with stricter error handling and return types
 * Throw `DateMalformedStringException`/`DateInvalidTimeZoneException` when appropriate
 * Add `$modifier` argument to the `now()` helper

6.3
---

 * Add `ClockAwareTrait` to help write time-sensitive classes
 * Add `Clock` class and `now()` function

6.2
---

 * Add the component
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Clock;

if (!\function_exists(now::class)) {
    /**
     * @throws \DateMalformedStringException When the modifier is invalid
     */
    function now(string $modifier = 'now'): DatePoint
    {
        if ('now' !== $modifier) {
            return new DatePoint($modifier);
        }
        $now = Clock::get()->now();
        return $now instanceof DatePoint ? $now : DatePoint::createFromInterface($now);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Clock;

use _ContaoManager\Psr\Clock\ClockInterface;
use _ContaoManager\Symfony\Contracts\Service\Attribute\Required;
/**
 * A trait to help write time-sensitive classes.
 *
 * @author Nicolas Grekas <p@tchwork.com>
 */
trait ClockAwareTrait
{
    private readonly ClockInterface $clock;
    #[Required]
    public function setClock(ClockInterface $clock): void
    {
        $this->clock = $clock;
    }
    /**
     * @return DatePoint
     */
    protected function now(): \DateTimeImmutable
    {
        $now = ($this->clock ??= new Clock())->now();
        return $now instanceof DatePoint ? $now : DatePoint::createFromInterface($now);
    }
}
Clock Component
===============

Symfony Clock decouples applications from the system clock.

Getting Started
---------------

```
$ composer require symfony/clock
```

```php
use Symfony\Component\Clock\NativeClock;
use Symfony\Component\Clock\ClockInterface;

class MyClockSensitiveClass
{
    public function __construct(
        private ClockInterface $clock,
    ) {
        // Only if you need to force a timezone:
        //$this->clock = $clock->withTimeZone('UTC');
    }

    public function doSomething()
    {
        $now = $this->clock->now();
        // [...] do something with $now, which is a \DateTimeImmutable object

        $this->clock->sleep(2.5); // Pause execution for 2.5 seconds
    }
}

$clock = new NativeClock();
$service = new MyClockSensitiveClass($clock);
$service->doSomething();
```

Resources
---------

 * [Documentation](https://symfony.com/doc/current/components/clock.html)
 * [Contributing](https://symfony.com/doc/current/contributing/index.html)
 * [Report issues](https://github.com/symfony/symfony/issues) and
   [send Pull Requests](https://github.com/symfony/symfony/pulls)
   in the [main Symfony repository](https://github.com/symfony/symfony)
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Clock;

/**
 * A clock that always returns the same date, suitable for testing time-sensitive logic.
 *
 * Consider using ClockSensitiveTrait in your test cases instead of using this class directly.
 *
 * @author Nicolas Grekas <p@tchwork.com>
 */
final class MockClock implements ClockInterface
{
    private DatePoint $now;
    /**
     * @throws \DateMalformedStringException When $now is invalid
     * @throws \DateInvalidTimeZoneException When $timezone is invalid
     */
    public function __construct(\DateTimeImmutable|string $now = 'now', \DateTimeZone|string|null $timezone = null)
    {
        if (\PHP_VERSION_ID >= 80300 && \is_string($timezone)) {
            $timezone = new \DateTimeZone($timezone);
        } elseif (\is_string($timezone)) {
            try {
                $timezone = new \DateTimeZone($timezone);
            } catch (\Exception $e) {
                throw new \DateInvalidTimeZoneException($e->getMessage(), $e->getCode(), $e);
            }
        }
        if (\is_string($now)) {
            $now = new DatePoint($now, $timezone ?? new \DateTimeZone('UTC'));
        } elseif (!$now instanceof DatePoint) {
            $now = DatePoint::createFromInterface($now);
        }
        $this->now = null !== $timezone ? $now->setTimezone($timezone) : $now;
    }
    public function now(): DatePoint
    {
        return clone $this->now;
    }
    public function sleep(float|int $seconds): void
    {
        if (0 >= $seconds) {
            return;
        }
        $now = (float) $this->now->format('Uu') + $seconds * 1000000.0;
        $now = substr_replace(\sprintf('@%07.0F', $now), '.', -6, 0);
        $timezone = $this->now->getTimezone();
        $this->now = DatePoint::createFromInterface(new \DateTimeImmutable($now, $timezone))->setTimezone($timezone);
    }
    /**
     * @throws \DateMalformedStringException When $modifier is invalid
     */
    public function modify(string $modifier): void
    {
        if (\PHP_VERSION_ID < 80300) {
            $this->now = @$this->now->modify($modifier) ?: throw new \DateMalformedStringException(error_get_last()['message'] ?? \sprintf('Invalid modifier: "%s". Could not modify MockClock.', $modifier));
            return;
        }
        $this->now = $this->now->modify($modifier);
    }
    /**
     * @throws \DateInvalidTimeZoneException When the timezone name is invalid
     */
    public function withTimeZone(\DateTimeZone|string $timezone): static
    {
        if (\PHP_VERSION_ID >= 80300 && \is_string($timezone)) {
            $timezone = new \DateTimeZone($timezone);
        } elseif (\is_string($timezone)) {
            try {
                $timezone = new \DateTimeZone($timezone);
            } catch (\Exception $e) {
                throw new \DateInvalidTimeZoneException($e->getMessage(), $e->getCode(), $e);
            }
        }
        $clone = clone $this;
        $clone->now = $clone->now->setTimezone($timezone);
        return $clone;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Clock;

use _ContaoManager\Psr\Clock\ClockInterface as PsrClockInterface;
/**
 * A global clock.
 *
 * @author Nicolas Grekas <p@tchwork.com>
 */
final class Clock implements ClockInterface
{
    private static ClockInterface $globalClock;
    public function __construct(private readonly ?PsrClockInterface $clock = null, private ?\DateTimeZone $timezone = null)
    {
    }
    /**
     * Returns the current global clock.
     *
     * Note that you should prefer injecting a ClockInterface or using
     * ClockAwareTrait when possible instead of using this method.
     */
    public static function get(): ClockInterface
    {
        return self::$globalClock ??= new NativeClock();
    }
    public static function set(PsrClockInterface $clock): void
    {
        self::$globalClock = $clock instanceof ClockInterface ? $clock : new self($clock);
    }
    public function now(): DatePoint
    {
        $now = ($this->clock ?? self::get())->now();
        if (!$now instanceof DatePoint) {
            $now = DatePoint::createFromInterface($now);
        }
        return isset($this->timezone) ? $now->setTimezone($this->timezone) : $now;
    }
    public function sleep(float|int $seconds): void
    {
        $clock = $this->clock ?? self::get();
        if ($clock instanceof ClockInterface) {
            $clock->sleep($seconds);
        } else {
            (new NativeClock())->sleep($seconds);
        }
    }
    /**
     * @throws \DateInvalidTimeZoneException When $timezone is invalid
     */
    public function withTimeZone(\DateTimeZone|string $timezone): static
    {
        if (\PHP_VERSION_ID >= 80300 && \is_string($timezone)) {
            $timezone = new \DateTimeZone($timezone);
        } elseif (\is_string($timezone)) {
            try {
                $timezone = new \DateTimeZone($timezone);
            } catch (\Exception $e) {
                throw new \DateInvalidTimeZoneException($e->getMessage(), $e->getCode(), $e);
            }
        }
        $clone = clone $this;
        $clone->timezone = $timezone;
        return $clone;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Clock;

/**
 * A monotonic clock suitable for performance profiling.
 *
 * @author Nicolas Grekas <p@tchwork.com>
 */
final class MonotonicClock implements ClockInterface
{
    private int $sOffset;
    private int $usOffset;
    private \DateTimeZone $timezone;
    /**
     * @throws \DateInvalidTimeZoneException When $timezone is invalid
     */
    public function __construct(\DateTimeZone|string|null $timezone = null)
    {
        if (\false === $offset = hrtime()) {
            throw new \RuntimeException('hrtime() returned false: the runtime environment does not provide access to a monotonic timer.');
        }
        $time = explode(' ', microtime(), 2);
        $this->sOffset = $time[1] - $offset[0];
        $this->usOffset = (int) ($time[0] * 1000000) - (int) ($offset[1] / 1000);
        $this->timezone = \is_string($timezone ??= date_default_timezone_get()) ? $this->withTimeZone($timezone)->timezone : $timezone;
    }
    public function now(): DatePoint
    {
        [$s, $us] = hrtime();
        if (1000000 <= $us = (int) ($us / 1000) + $this->usOffset) {
            ++$s;
            $us -= 1000000;
        } elseif (0 > $us) {
            --$s;
            $us += 1000000;
        }
        if (6 !== \strlen($now = (string) $us)) {
            $now = str_pad($now, 6, '0', \STR_PAD_LEFT);
        }
        $now = '@' . ($s + $this->sOffset) . '.' . $now;
        return DatePoint::createFromInterface(new \DateTimeImmutable($now, $this->timezone))->setTimezone($this->timezone);
    }
    public function sleep(float|int $seconds): void
    {
        if (0 < $s = (int) $seconds) {
            sleep($s);
        }
        if (0 < $us = $seconds - $s) {
            usleep((int) ($us * 1000000.0));
        }
    }
    /**
     * @throws \DateInvalidTimeZoneException When $timezone is invalid
     */
    public function withTimeZone(\DateTimeZone|string $timezone): static
    {
        if (\PHP_VERSION_ID >= 80300 && \is_string($timezone)) {
            $timezone = new \DateTimeZone($timezone);
        } elseif (\is_string($timezone)) {
            try {
                $timezone = new \DateTimeZone($timezone);
            } catch (\Exception $e) {
                throw new \DateInvalidTimeZoneException($e->getMessage(), $e->getCode(), $e);
            }
        }
        $clone = clone $this;
        $clone->timezone = $timezone;
        return $clone;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Clock;

use _ContaoManager\Psr\Clock\ClockInterface as PsrClockInterface;
/**
 * @author Nicolas Grekas <p@tchwork.com>
 */
interface ClockInterface extends PsrClockInterface
{
    public function sleep(float|int $seconds): void;
    public function withTimeZone(\DateTimeZone|string $timezone): static;
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Clock;

/**
 * An immmutable DateTime with stricter error handling and return types than the native one.
 *
 * @author Nicolas Grekas <p@tchwork.com>
 */
final class DatePoint extends \DateTimeImmutable
{
    /**
     * @throws \DateMalformedStringException When $datetime is invalid
     */
    public function __construct(string $datetime = 'now', ?\DateTimeZone $timezone = null, ?parent $reference = null)
    {
        $now = $reference ?? Clock::get()->now();
        if ('now' !== $datetime) {
            if (!$now instanceof static) {
                $now = static::createFromInterface($now);
            }
            if (\PHP_VERSION_ID < 80300) {
                try {
                    $builtInDate = new parent($datetime, $timezone ?? $now->getTimezone());
                    $timezone = $builtInDate->getTimezone();
                } catch (\Exception $e) {
                    throw new \DateMalformedStringException($e->getMessage(), $e->getCode(), $e);
                }
            } else {
                $builtInDate = new parent($datetime, $timezone ?? $now->getTimezone());
                $timezone = $builtInDate->getTimezone();
            }
            $now = $now->setTimezone($timezone)->modify($datetime);
            if ('00:00:00.000000' === $builtInDate->format('H:i:s.u')) {
                $now = $now->setTime(0, 0);
            }
        } elseif (null !== $timezone) {
            $now = $now->setTimezone($timezone);
        }
        if (\PHP_VERSION_ID < 80200) {
            $now = (array) $now;
            $this->date = $now['date'];
            $this->timezone_type = $now['timezone_type'];
            $this->timezone = $now['timezone'];
            $this->__wakeup();
            return;
        }
        $this->__unserialize((array) $now);
    }
    /**
     * @throws \DateMalformedStringException When $format or $datetime are invalid
     */
    public static function createFromFormat(string $format, string $datetime, ?\DateTimeZone $timezone = null): static
    {
        return parent::createFromFormat($format, $datetime, $timezone) ?: throw new \DateMalformedStringException(static::getLastErrors()['errors'][0] ?? 'Invalid date string or format.');
    }
    public static function createFromInterface(\DateTimeInterface $object): static
    {
        return parent::createFromInterface($object);
    }
    public static function createFromMutable(\DateTime $object): static
    {
        return parent::createFromMutable($object);
    }
    public function add(\DateInterval $interval): static
    {
        return parent::add($interval);
    }
    public function sub(\DateInterval $interval): static
    {
        return parent::sub($interval);
    }
    /**
     * @throws \DateMalformedStringException When $modifier is invalid
     */
    public function modify(string $modifier): static
    {
        if (\PHP_VERSION_ID < 80300) {
            return @parent::modify($modifier) ?: throw new \DateMalformedStringException(error_get_last()['message'] ?? \sprintf('Invalid modifier: "%s".', $modifier));
        }
        return parent::modify($modifier);
    }
    public function setTimestamp(int $value): static
    {
        return parent::setTimestamp($value);
    }
    public function setDate(int $year, int $month, int $day): static
    {
        return parent::setDate($year, $month, $day);
    }
    public function setISODate(int $year, int $week, int $day = 1): static
    {
        return parent::setISODate($year, $week, $day);
    }
    public function setTime(int $hour, int $minute, int $second = 0, int $microsecond = 0): static
    {
        return parent::setTime($hour, $minute, $second, $microsecond);
    }
    public function setTimezone(\DateTimeZone $timezone): static
    {
        return parent::setTimezone($timezone);
    }
    public function getTimezone(): \DateTimeZone
    {
        return parent::getTimezone() ?: throw new \DateInvalidTimeZoneException('The DatePoint object has no timezone.');
    }
}
{
    "name": "symfony\/clock",
    "type": "library",
    "description": "Decouples applications from the system clock",
    "keywords": [
        "clock",
        "time",
        "psr20"
    ],
    "homepage": "https:\/\/symfony.com",
    "license": "MIT",
    "authors": [
        {
            "name": "Nicolas Grekas",
            "email": "p@tchwork.com"
        },
        {
            "name": "Symfony Community",
            "homepage": "https:\/\/symfony.com\/contributors"
        }
    ],
    "provide": {
        "psr\/clock-implementation": "1.0"
    },
    "require": {
        "php": ">=8.1",
        "psr\/clock": "^1.0",
        "symfony\/polyfill-php83": "^1.28"
    },
    "autoload": {
        "files": [
            "Resources\/now.php"
        ],
        "psr-4": {
            "_ContaoManager\\Symfony\\Component\\Clock\\": ""
        },
        "exclude-from-classmap": [
            "\/Tests\/"
        ]
    },
    "minimum-stability": "dev"
}<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Clock;

/**
 * A clock that relies the system time.
 *
 * @author Nicolas Grekas <p@tchwork.com>
 */
final class NativeClock implements ClockInterface
{
    private \DateTimeZone $timezone;
    /**
     * @throws \DateInvalidTimeZoneException When $timezone is invalid
     */
    public function __construct(\DateTimeZone|string|null $timezone = null)
    {
        $this->timezone = \is_string($timezone ??= date_default_timezone_get()) ? $this->withTimeZone($timezone)->timezone : $timezone;
    }
    public function now(): DatePoint
    {
        return DatePoint::createFromInterface(new \DateTimeImmutable('now', $this->timezone));
    }
    public function sleep(float|int $seconds): void
    {
        if (0 < $s = (int) $seconds) {
            sleep($s);
        }
        if (0 < $us = $seconds - $s) {
            usleep((int) ($us * 1000000.0));
        }
    }
    /**
     * @throws \DateInvalidTimeZoneException When $timezone is invalid
     */
    public function withTimeZone(\DateTimeZone|string $timezone): static
    {
        if (\PHP_VERSION_ID >= 80300 && \is_string($timezone)) {
            $timezone = new \DateTimeZone($timezone);
        } elseif (\is_string($timezone)) {
            try {
                $timezone = new \DateTimeZone($timezone);
            } catch (\Exception $e) {
                throw new \DateInvalidTimeZoneException($e->getMessage(), $e->getCode(), $e);
            }
        }
        $clone = clone $this;
        $clone->timezone = $timezone;
        return $clone;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\PasswordHasher;

use _ContaoManager\Symfony\Component\PasswordHasher\Exception\InvalidPasswordException;
/**
 * Provides password hashing capabilities.
 *
 * @author Robin Chalas <robin.chalas@gmail.com>
 * @author Fabien Potencier <fabien@symfony.com>
 * @author Nicolas Grekas <p@tchwork.com>
 */
interface PasswordHasherInterface
{
    public const MAX_PASSWORD_LENGTH = 4096;
    /**
     * Hashes a plain password.
     *
     * @throws InvalidPasswordException When the plain password is invalid, e.g. excessively long
     */
    public function hash(
        #[\SensitiveParameter]
        string $plainPassword
    ): string;
    /**
     * Verifies a plain password against a hash.
     */
    public function verify(
        string $hashedPassword,
        #[\SensitiveParameter]
        string $plainPassword
    ): bool;
    /**
     * Checks if a password hash would benefit from rehashing.
     */
    public function needsRehash(string $hashedPassword): bool;
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\PasswordHasher\Hasher;

use _ContaoManager\Symfony\Component\PasswordHasher\Exception\InvalidPasswordException;
use _ContaoManager\Symfony\Component\PasswordHasher\Exception\LogicException;
use _ContaoManager\Symfony\Component\PasswordHasher\PasswordHasherInterface;
/**
 * Hashes passwords using libsodium.
 *
 * @author Robin Chalas <robin.chalas@gmail.com>
 * @author Zan Baldwin <hello@zanbaldwin.com>
 * @author Dominik Müller <dominik.mueller@jkweb.ch>
 */
final class SodiumPasswordHasher implements PasswordHasherInterface
{
    use CheckPasswordLengthTrait;
    private int $opsLimit;
    private int $memLimit;
    public function __construct(?int $opsLimit = null, ?int $memLimit = null)
    {
        if (!self::isSupported()) {
            throw new LogicException('Libsodium is not available. You should either install the sodium extension or use a different password hasher.');
        }
        $this->opsLimit = $opsLimit ?? max(4, \defined('SODIUM_CRYPTO_PWHASH_OPSLIMIT_INTERACTIVE') ? \SODIUM_CRYPTO_PWHASH_OPSLIMIT_INTERACTIVE : 4);
        $this->memLimit = $memLimit ?? max(64 * 1024 * 1024, \defined('SODIUM_CRYPTO_PWHASH_MEMLIMIT_INTERACTIVE') ? \SODIUM_CRYPTO_PWHASH_MEMLIMIT_INTERACTIVE : 64 * 1024 * 1024);
        if (3 > $this->opsLimit) {
            throw new \InvalidArgumentException('$opsLimit must be 3 or greater.');
        }
        if (10 * 1024 > $this->memLimit) {
            throw new \InvalidArgumentException('$memLimit must be 10k or greater.');
        }
    }
    public static function isSupported(): bool
    {
        return version_compare(\extension_loaded('sodium') ? \SODIUM_LIBRARY_VERSION : phpversion('libsodium'), '1.0.14', '>=');
    }
    public function hash(
        #[\SensitiveParameter]
        string $plainPassword
    ): string
    {
        if ($this->isPasswordTooLong($plainPassword)) {
            throw new InvalidPasswordException();
        }
        if (\function_exists('sodium_crypto_pwhash_str')) {
            return sodium_crypto_pwhash_str($plainPassword, $this->opsLimit, $this->memLimit);
        }
        if (\extension_loaded('libsodium')) {
            return \Sodium\crypto_pwhash_str($plainPassword, $this->opsLimit, $this->memLimit);
        }
        throw new LogicException('Libsodium is not available. You should either install the sodium extension or use a different password hasher.');
    }
    public function verify(
        string $hashedPassword,
        #[\SensitiveParameter]
        string $plainPassword
    ): bool
    {
        if ('' === $plainPassword) {
            return \false;
        }
        if ($this->isPasswordTooLong($plainPassword)) {
            return \false;
        }
        if (!str_starts_with($hashedPassword, '$argon')) {
            if (str_starts_with($hashedPassword, '$2') && (72 < \strlen($plainPassword) || str_contains($plainPassword, "\x00"))) {
                $plainPassword = base64_encode(hash('sha512', $plainPassword, \true));
            }
            // Accept validating non-argon passwords for seamless migrations
            return password_verify($plainPassword, $hashedPassword);
        }
        if (\function_exists('sodium_crypto_pwhash_str_verify')) {
            return sodium_crypto_pwhash_str_verify($hashedPassword, $plainPassword);
        }
        if (\extension_loaded('libsodium')) {
            return \Sodium\crypto_pwhash_str_verify($hashedPassword, $plainPassword);
        }
        return \false;
    }
    public function needsRehash(string $hashedPassword): bool
    {
        if (\function_exists('sodium_crypto_pwhash_str_needs_rehash')) {
            return sodium_crypto_pwhash_str_needs_rehash($hashedPassword, $this->opsLimit, $this->memLimit);
        }
        if (\extension_loaded('libsodium')) {
            return \_ContaoManager\Sodium\crypto_pwhash_str_needs_rehash($hashedPassword, $this->opsLimit, $this->memLimit);
        }
        throw new LogicException('Libsodium is not available. You should either install the sodium extension or use a different password hasher.');
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\PasswordHasher\Hasher;

use _ContaoManager\Symfony\Component\PasswordHasher\PasswordHasherInterface;
/**
 * @author Robin Chalas <robin.chalas@gmail.com>
 */
trait CheckPasswordLengthTrait
{
    private function isPasswordTooLong(
        #[\SensitiveParameter]
        string $password
    ): bool
    {
        return PasswordHasherInterface::MAX_PASSWORD_LENGTH < \strlen($password);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\PasswordHasher\Hasher;

use _ContaoManager\Symfony\Component\Security\Core\User\LegacyPasswordAuthenticatedUserInterface;
use _ContaoManager\Symfony\Component\Security\Core\User\PasswordAuthenticatedUserInterface;
/**
 * Hashes passwords based on the user and the PasswordHasherFactory.
 *
 * @author Ariel Ferrandini <arielferrandini@gmail.com>
 *
 * @final
 */
class UserPasswordHasher implements UserPasswordHasherInterface
{
    private PasswordHasherFactoryInterface $hasherFactory;
    public function __construct(PasswordHasherFactoryInterface $hasherFactory)
    {
        $this->hasherFactory = $hasherFactory;
    }
    public function hashPassword(
        PasswordAuthenticatedUserInterface $user,
        #[\SensitiveParameter]
        string $plainPassword
    ): string
    {
        $salt = null;
        if ($user instanceof LegacyPasswordAuthenticatedUserInterface) {
            $salt = $user->getSalt();
        }
        $hasher = $this->hasherFactory->getPasswordHasher($user);
        return $hasher->hash($plainPassword, $salt);
    }
    public function isPasswordValid(
        PasswordAuthenticatedUserInterface $user,
        #[\SensitiveParameter]
        string $plainPassword
    ): bool
    {
        $salt = null;
        if ($user instanceof LegacyPasswordAuthenticatedUserInterface) {
            $salt = $user->getSalt();
        }
        if (null === $user->getPassword()) {
            return \false;
        }
        $hasher = $this->hasherFactory->getPasswordHasher($user);
        return $hasher->verify($user->getPassword(), $plainPassword, $salt);
    }
    public function needsRehash(PasswordAuthenticatedUserInterface $user): bool
    {
        if (null === $user->getPassword()) {
            return \false;
        }
        $hasher = $this->hasherFactory->getPasswordHasher($user);
        return $hasher->needsRehash($user->getPassword());
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\PasswordHasher\Hasher;

use _ContaoManager\Symfony\Component\PasswordHasher\Exception\InvalidPasswordException;
use _ContaoManager\Symfony\Component\PasswordHasher\Exception\LogicException;
use _ContaoManager\Symfony\Component\PasswordHasher\LegacyPasswordHasherInterface;
/**
 * Pbkdf2PasswordHasher uses the PBKDF2 (Password-Based Key Derivation Function 2).
 *
 * Providing a high level of Cryptographic security,
 *  PBKDF2 is recommended by the National Institute of Standards and Technology (NIST).
 *
 * But also warrants a warning, using PBKDF2 (with a high number of iterations) slows down the process.
 * PBKDF2 should be used with caution and care.
 *
 * @author Sebastiaan Stok <s.stok@rollerscapes.net>
 * @author Andrew Johnson
 * @author Fabien Potencier <fabien@symfony.com>
 */
final class Pbkdf2PasswordHasher implements LegacyPasswordHasherInterface
{
    use CheckPasswordLengthTrait;
    private string $algorithm;
    private bool $encodeHashAsBase64;
    private int $iterations = 1;
    private int $length;
    private int $encodedLength = -1;
    /**
     * @param string $algorithm          The digest algorithm to use
     * @param bool   $encodeHashAsBase64 Whether to base64 encode the password hash
     * @param int    $iterations         The number of iterations to use to stretch the password hash
     * @param int    $length             Length of derived key to create
     */
    public function __construct(string $algorithm = 'sha512', bool $encodeHashAsBase64 = \true, int $iterations = 1000, int $length = 40)
    {
        $this->algorithm = $algorithm;
        $this->encodeHashAsBase64 = $encodeHashAsBase64;
        $this->length = $length;
        try {
            $this->encodedLength = \strlen($this->hash('', 'salt'));
        } catch (\LogicException) {
            // ignore unsupported algorithm
        }
        $this->iterations = $iterations;
    }
    public function hash(
        #[\SensitiveParameter]
        string $plainPassword,
        ?string $salt = null
    ): string
    {
        if ($this->isPasswordTooLong($plainPassword)) {
            throw new InvalidPasswordException();
        }
        if (!\in_array($this->algorithm, hash_algos(), \true)) {
            throw new LogicException(\sprintf('The algorithm "%s" is not supported.', $this->algorithm));
        }
        $digest = hash_pbkdf2($this->algorithm, $plainPassword, $salt ?? '', $this->iterations, $this->length, \true);
        return $this->encodeHashAsBase64 ? base64_encode($digest) : bin2hex($digest);
    }
    public function verify(
        string $hashedPassword,
        #[\SensitiveParameter]
        string $plainPassword,
        ?string $salt = null
    ): bool
    {
        if (\strlen($hashedPassword) !== $this->encodedLength || str_contains($hashedPassword, '$')) {
            return \false;
        }
        return !$this->isPasswordTooLong($plainPassword) && hash_equals($hashedPassword, $this->hash($plainPassword, $salt));
    }
    public function needsRehash(string $hashedPassword): bool
    {
        return \false;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\PasswordHasher\Hasher;

/**
 * @author Christophe Coevoet <stof@notk.org>
 */
interface PasswordHasherAwareInterface
{
    /**
     * Gets the name of the password hasher used to hash the password.
     *
     * If the method returns null, the standard way to retrieve the password hasher
     * will be used instead.
     */
    public function getPasswordHasherName(): ?string;
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\PasswordHasher\Hasher;

use _ContaoManager\Symfony\Component\PasswordHasher\Exception\InvalidPasswordException;
use _ContaoManager\Symfony\Component\PasswordHasher\PasswordHasherInterface;
/**
 * Hashes passwords using password_hash().
 *
 * @author Elnur Abdurrakhimov <elnur@elnur.pro>
 * @author Terje Bråten <terje@braten.be>
 * @author Nicolas Grekas <p@tchwork.com>
 */
final class NativePasswordHasher implements PasswordHasherInterface
{
    use CheckPasswordLengthTrait;
    private string $algorithm = \PASSWORD_BCRYPT;
    private array $options;
    /**
     * @param string|null $algorithm An algorithm supported by password_hash() or null to use the best available algorithm
     */
    public function __construct(?int $opsLimit = null, ?int $memLimit = null, ?int $cost = null, ?string $algorithm = null)
    {
        $cost ??= 13;
        $opsLimit ??= max(4, \defined('SODIUM_CRYPTO_PWHASH_OPSLIMIT_INTERACTIVE') ? \SODIUM_CRYPTO_PWHASH_OPSLIMIT_INTERACTIVE : 4);
        $memLimit ??= max(64 * 1024 * 1024, \defined('SODIUM_CRYPTO_PWHASH_MEMLIMIT_INTERACTIVE') ? \SODIUM_CRYPTO_PWHASH_MEMLIMIT_INTERACTIVE : 64 * 1024 * 1024);
        if (3 > $opsLimit) {
            throw new \InvalidArgumentException('$opsLimit must be 3 or greater.');
        }
        if (10 * 1024 > $memLimit) {
            throw new \InvalidArgumentException('$memLimit must be 10k or greater.');
        }
        if ($cost < 4 || 31 < $cost) {
            throw new \InvalidArgumentException('$cost must be in the range of 4-31.');
        }
        if (null !== $algorithm) {
            $algorithms = [1 => \PASSWORD_BCRYPT, '2y' => \PASSWORD_BCRYPT];
            if (\defined('PASSWORD_ARGON2I')) {
                $algorithms[2] = $algorithms['argon2i'] = \PASSWORD_ARGON2I;
            }
            if (\defined('PASSWORD_ARGON2ID')) {
                $algorithms[3] = $algorithms['argon2id'] = \PASSWORD_ARGON2ID;
            }
            $this->algorithm = $algorithms[$algorithm] ?? $algorithm;
        }
        $this->options = ['cost' => $cost, 'time_cost' => $opsLimit, 'memory_cost' => $memLimit >> 10, 'threads' => 1];
    }
    public function hash(
        #[\SensitiveParameter]
        string $plainPassword
    ): string
    {
        if ($this->isPasswordTooLong($plainPassword)) {
            throw new InvalidPasswordException();
        }
        if (\PASSWORD_BCRYPT === $this->algorithm && (72 < \strlen($plainPassword) || str_contains($plainPassword, "\x00"))) {
            $plainPassword = base64_encode(hash('sha512', $plainPassword, \true));
        }
        return password_hash($plainPassword, $this->algorithm, $this->options);
    }
    public function verify(
        string $hashedPassword,
        #[\SensitiveParameter]
        string $plainPassword
    ): bool
    {
        if ('' === $plainPassword || $this->isPasswordTooLong($plainPassword)) {
            return \false;
        }
        if (!str_starts_with($hashedPassword, '$argon')) {
            // Bcrypt cuts on NUL chars and after 72 bytes
            if (str_starts_with($hashedPassword, '$2') && (72 < \strlen($plainPassword) || str_contains($plainPassword, "\x00"))) {
                $plainPassword = base64_encode(hash('sha512', $plainPassword, \true));
            }
            return password_verify($plainPassword, $hashedPassword);
        }
        if (\extension_loaded('sodium') && version_compare(\SODIUM_LIBRARY_VERSION, '1.0.14', '>=')) {
            return sodium_crypto_pwhash_str_verify($hashedPassword, $plainPassword);
        }
        if (\extension_loaded('libsodium') && version_compare(phpversion('libsodium'), '1.0.14', '>=')) {
            return \Sodium\crypto_pwhash_str_verify($hashedPassword, $plainPassword);
        }
        return password_verify($plainPassword, $hashedPassword);
    }
    public function needsRehash(string $hashedPassword): bool
    {
        return password_needs_rehash($hashedPassword, $this->algorithm, $this->options);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\PasswordHasher\Hasher;

use _ContaoManager\Symfony\Component\PasswordHasher\Exception\InvalidPasswordException;
use _ContaoManager\Symfony\Component\PasswordHasher\Exception\LogicException;
use _ContaoManager\Symfony\Component\PasswordHasher\LegacyPasswordHasherInterface;
/**
 * MessageDigestPasswordHasher uses a message digest algorithm.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class MessageDigestPasswordHasher implements LegacyPasswordHasherInterface
{
    use CheckPasswordLengthTrait;
    private string $algorithm;
    private bool $encodeHashAsBase64;
    private int $iterations = 1;
    private int $hashLength = -1;
    /**
     * @param string $algorithm          The digest algorithm to use
     * @param bool   $encodeHashAsBase64 Whether to base64 encode the password hash
     * @param int    $iterations         The number of iterations to use to stretch the password hash
     */
    public function __construct(string $algorithm = 'sha512', bool $encodeHashAsBase64 = \true, int $iterations = 5000)
    {
        $this->algorithm = $algorithm;
        $this->encodeHashAsBase64 = $encodeHashAsBase64;
        try {
            $this->hashLength = \strlen($this->hash('', 'salt'));
        } catch (\LogicException) {
            // ignore algorithm not supported
        }
        $this->iterations = $iterations;
    }
    public function hash(
        #[\SensitiveParameter]
        string $plainPassword,
        ?string $salt = null
    ): string
    {
        if ($this->isPasswordTooLong($plainPassword)) {
            throw new InvalidPasswordException();
        }
        if (!\in_array($this->algorithm, hash_algos(), \true)) {
            throw new LogicException(\sprintf('The algorithm "%s" is not supported.', $this->algorithm));
        }
        $salted = $this->mergePasswordAndSalt($plainPassword, $salt);
        $digest = hash($this->algorithm, $salted, \true);
        // "stretch" hash
        for ($i = 1; $i < $this->iterations; ++$i) {
            $digest = hash($this->algorithm, $digest . $salted, \true);
        }
        return $this->encodeHashAsBase64 ? base64_encode($digest) : bin2hex($digest);
    }
    public function verify(
        string $hashedPassword,
        #[\SensitiveParameter]
        string $plainPassword,
        ?string $salt = null
    ): bool
    {
        if (\strlen($hashedPassword) !== $this->hashLength || str_contains($hashedPassword, '$')) {
            return \false;
        }
        return !$this->isPasswordTooLong($plainPassword) && hash_equals($hashedPassword, $this->hash($plainPassword, $salt));
    }
    public function needsRehash(string $hashedPassword): bool
    {
        return \false;
    }
    private function mergePasswordAndSalt(
        #[\SensitiveParameter]
        string $password,
        ?string $salt
    ): string
    {
        if (!$salt) {
            return $password;
        }
        if (\false !== strrpos($salt, '{') || \false !== strrpos($salt, '}')) {
            throw new \InvalidArgumentException('Cannot use { or } in salt.');
        }
        return $password . '{' . $salt . '}';
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\PasswordHasher\Hasher;

use _ContaoManager\Symfony\Component\Security\Core\User\PasswordAuthenticatedUserInterface;
/**
 * Interface for the user password hasher service.
 *
 * @author Ariel Ferrandini <arielferrandini@gmail.com>
 */
interface UserPasswordHasherInterface
{
    /**
     * Hashes the plain password for the given user.
     */
    public function hashPassword(
        PasswordAuthenticatedUserInterface $user,
        #[\SensitiveParameter]
        string $plainPassword
    ): string;
    /**
     * Checks if the plaintext password matches the user's password.
     */
    public function isPasswordValid(
        PasswordAuthenticatedUserInterface $user,
        #[\SensitiveParameter]
        string $plainPassword
    ): bool;
    /**
     * Checks if an encoded password would benefit from rehashing.
     */
    public function needsRehash(PasswordAuthenticatedUserInterface $user): bool;
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\PasswordHasher\Hasher;

use _ContaoManager\Symfony\Component\PasswordHasher\Exception\InvalidPasswordException;
use _ContaoManager\Symfony\Component\PasswordHasher\LegacyPasswordHasherInterface;
/**
 * PlaintextPasswordHasher does not do any hashing but is useful in testing environments.
 *
 * As this hasher is not cryptographically secure, usage of it in production environments is discouraged.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class PlaintextPasswordHasher implements LegacyPasswordHasherInterface
{
    use CheckPasswordLengthTrait;
    private bool $ignorePasswordCase;
    /**
     * @param bool $ignorePasswordCase Compare password case-insensitive
     */
    public function __construct(bool $ignorePasswordCase = \false)
    {
        $this->ignorePasswordCase = $ignorePasswordCase;
    }
    public function hash(
        #[\SensitiveParameter]
        string $plainPassword,
        ?string $salt = null
    ): string
    {
        if ($this->isPasswordTooLong($plainPassword)) {
            throw new InvalidPasswordException();
        }
        return $this->mergePasswordAndSalt($plainPassword, $salt);
    }
    public function verify(
        string $hashedPassword,
        #[\SensitiveParameter]
        string $plainPassword,
        ?string $salt = null
    ): bool
    {
        if ($this->isPasswordTooLong($plainPassword)) {
            return \false;
        }
        $pass2 = $this->mergePasswordAndSalt($plainPassword, $salt);
        if (!$this->ignorePasswordCase) {
            return hash_equals($hashedPassword, $pass2);
        }
        return hash_equals(strtolower($hashedPassword), strtolower($pass2));
    }
    public function needsRehash(string $hashedPassword): bool
    {
        return \false;
    }
    private function mergePasswordAndSalt(
        #[\SensitiveParameter]
        string $password,
        ?string $salt
    ): string
    {
        if (empty($salt)) {
            return $password;
        }
        if (\false !== strrpos($salt, '{') || \false !== strrpos($salt, '}')) {
            throw new \InvalidArgumentException('Cannot use { or } in salt.');
        }
        return $password . '{' . $salt . '}';
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\PasswordHasher\Hasher;

use _ContaoManager\Symfony\Component\PasswordHasher\PasswordHasherInterface;
use _ContaoManager\Symfony\Component\Security\Core\User\PasswordAuthenticatedUserInterface;
/**
 * PasswordHasherFactoryInterface to support different password hashers for different user accounts.
 *
 * @author Robin Chalas <robin.chalas@gmail.com>
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
interface PasswordHasherFactoryInterface
{
    /**
     * Returns the password hasher to use for the given user.
     *
     * @throws \RuntimeException When no password hasher could be found for the user
     */
    public function getPasswordHasher(string|PasswordAuthenticatedUserInterface|PasswordHasherAwareInterface $user): PasswordHasherInterface;
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\PasswordHasher\Hasher;

use _ContaoManager\Symfony\Component\PasswordHasher\PasswordHasherInterface;
/**
 * Hashes passwords using the best available hasher.
 * Verifies them using a chain of hashers.
 *
 * /!\ Don't put a PlaintextPasswordHasher in the list as that'd mean a leaked hash
 * could be used to authenticate successfully without knowing the cleartext password.
 *
 * @author Nicolas Grekas <p@tchwork.com>
 */
final class MigratingPasswordHasher implements PasswordHasherInterface
{
    private PasswordHasherInterface $bestHasher;
    private array $extraHashers;
    public function __construct(PasswordHasherInterface $bestHasher, PasswordHasherInterface ...$extraHashers)
    {
        $this->bestHasher = $bestHasher;
        $this->extraHashers = $extraHashers;
    }
    public function hash(
        #[\SensitiveParameter]
        string $plainPassword,
        ?string $salt = null
    ): string
    {
        return $this->bestHasher->hash($plainPassword, $salt);
    }
    public function verify(
        string $hashedPassword,
        #[\SensitiveParameter]
        string $plainPassword,
        ?string $salt = null
    ): bool
    {
        if ($this->bestHasher->verify($hashedPassword, $plainPassword, $salt)) {
            return \true;
        }
        if (!$this->bestHasher->needsRehash($hashedPassword)) {
            return \false;
        }
        foreach ($this->extraHashers as $hasher) {
            if ($hasher->verify($hashedPassword, $plainPassword, $salt)) {
                return \true;
            }
        }
        return \false;
    }
    public function needsRehash(string $hashedPassword): bool
    {
        return $this->bestHasher->needsRehash($hashedPassword);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\PasswordHasher\Hasher;

use _ContaoManager\Symfony\Component\PasswordHasher\Exception\LogicException;
use _ContaoManager\Symfony\Component\PasswordHasher\PasswordHasherInterface;
use _ContaoManager\Symfony\Component\Security\Core\User\PasswordAuthenticatedUserInterface;
/**
 * A generic hasher factory implementation.
 *
 * @author Nicolas Grekas <p@tchwork.com>
 * @author Robin Chalas <robin.chalas@gmail.com>
 */
class PasswordHasherFactory implements PasswordHasherFactoryInterface
{
    private array $passwordHashers;
    /**
     * @param array<string, PasswordHasherInterface|array> $passwordHashers
     */
    public function __construct(array $passwordHashers)
    {
        $this->passwordHashers = $passwordHashers;
    }
    public function getPasswordHasher(string|PasswordAuthenticatedUserInterface|PasswordHasherAwareInterface $user): PasswordHasherInterface
    {
        $hasherKey = null;
        if ($user instanceof PasswordHasherAwareInterface && null !== $hasherName = $user->getPasswordHasherName()) {
            if (!\array_key_exists($hasherName, $this->passwordHashers)) {
                throw new \RuntimeException(\sprintf('The password hasher "%s" was not configured.', $hasherName));
            }
            $hasherKey = $hasherName;
        } else {
            foreach ($this->passwordHashers as $class => $hasher) {
                if (\is_object($user) && $user instanceof $class || !\is_object($user) && (is_subclass_of($user, $class) || $user == $class)) {
                    $hasherKey = $class;
                    break;
                }
            }
        }
        if (null === $hasherKey) {
            throw new \RuntimeException(\sprintf('No password hasher has been configured for account "%s".', \is_object($user) ? get_debug_type($user) : $user));
        }
        if (!$this->passwordHashers[$hasherKey] instanceof PasswordHasherInterface) {
            $this->passwordHashers[$hasherKey] = $this->createHasher($this->passwordHashers[$hasherKey]);
        }
        return $this->passwordHashers[$hasherKey];
    }
    /**
     * Creates the actual hasher instance.
     *
     * @throws \InvalidArgumentException
     */
    private function createHasher(array $config, bool $isExtra = \false): PasswordHasherInterface
    {
        if (isset($config['instance'])) {
            if (!isset($config['migrate_from'])) {
                return $config['instance'];
            }
            $config = $this->getMigratingPasswordConfig($config);
        }
        if (isset($config['algorithm'])) {
            $rawConfig = $config;
            $config = $this->getHasherConfigFromAlgorithm($config);
        }
        if (!isset($config['class'])) {
            throw new \InvalidArgumentException('"class" must be set in ' . json_encode($config));
        }
        if (!isset($config['arguments'])) {
            throw new \InvalidArgumentException('"arguments" must be set in ' . json_encode($config));
        }
        $hasher = new $config['class'](...$config['arguments']);
        if ($isExtra || !\in_array($config['class'], [NativePasswordHasher::class, SodiumPasswordHasher::class], \true)) {
            return $hasher;
        }
        if ($rawConfig ?? null) {
            $extrapasswordHashers = array_map(function (string $algo) use ($rawConfig): PasswordHasherInterface {
                $rawConfig['algorithm'] = $algo;
                return $this->createHasher($rawConfig);
            }, ['pbkdf2', $rawConfig['hash_algorithm'] ?? 'sha512']);
        } else {
            $extrapasswordHashers = [new Pbkdf2PasswordHasher(), new MessageDigestPasswordHasher()];
        }
        return new MigratingPasswordHasher($hasher, ...$extrapasswordHashers);
    }
    private function getHasherConfigFromAlgorithm(array $config): array
    {
        if ('auto' === $config['algorithm']) {
            // "plaintext" is not listed as any leaked hashes could then be used to authenticate directly
            if (SodiumPasswordHasher::isSupported()) {
                $algorithms = ['native', 'sodium', 'pbkdf2'];
            } else {
                $algorithms = ['native', 'pbkdf2'];
            }
            if ($config['hash_algorithm'] ?? '') {
                $algorithms[] = $config['hash_algorithm'];
            }
            $hasherChain = [];
            foreach ($algorithms as $algorithm) {
                $config['algorithm'] = $algorithm;
                $hasherChain[] = $this->createHasher($config, \true);
            }
            return ['class' => MigratingPasswordHasher::class, 'arguments' => $hasherChain];
        }
        if ($config['migrate_from'] ?? \false) {
            return $this->getMigratingPasswordConfig($config);
        }
        switch ($config['algorithm']) {
            case 'plaintext':
                return ['class' => PlaintextPasswordHasher::class, 'arguments' => [$config['ignore_case'] ?? \false]];
            case 'pbkdf2':
                return ['class' => Pbkdf2PasswordHasher::class, 'arguments' => [$config['hash_algorithm'] ?? 'sha512', $config['encode_as_base64'] ?? \true, $config['iterations'] ?? 1000, $config['key_length'] ?? 40]];
            case 'bcrypt':
                $config['algorithm'] = 'native';
                $config['native_algorithm'] = \PASSWORD_BCRYPT;
                return $this->getHasherConfigFromAlgorithm($config);
            case 'native':
                return ['class' => NativePasswordHasher::class, 'arguments' => [$config['time_cost'] ?? null, ($config['memory_cost'] ?? 0) << 10 ?: null, $config['cost'] ?? null] + (isset($config['native_algorithm']) ? [3 => $config['native_algorithm']] : [])];
            case 'sodium':
                return ['class' => SodiumPasswordHasher::class, 'arguments' => [$config['time_cost'] ?? null, ($config['memory_cost'] ?? 0) << 10 ?: null]];
            case 'argon2i':
                if (SodiumPasswordHasher::isSupported() && !\defined('SODIUM_CRYPTO_PWHASH_ALG_ARGON2ID13')) {
                    $config['algorithm'] = 'sodium';
                } elseif (\defined('PASSWORD_ARGON2I')) {
                    $config['algorithm'] = 'native';
                    $config['native_algorithm'] = \PASSWORD_ARGON2I;
                } else {
                    throw new LogicException(\sprintf('Algorithm "argon2i" is not available. Use "%s" instead.', \defined('SODIUM_CRYPTO_PWHASH_ALG_ARGON2ID13') ? 'argon2id" or "auto' : 'auto'));
                }
                return $this->getHasherConfigFromAlgorithm($config);
            case 'argon2id':
                if (($hasSodium = SodiumPasswordHasher::isSupported()) && \defined('SODIUM_CRYPTO_PWHASH_ALG_ARGON2ID13')) {
                    $config['algorithm'] = 'sodium';
                } elseif (\defined('PASSWORD_ARGON2ID')) {
                    $config['algorithm'] = 'native';
                    $config['native_algorithm'] = \PASSWORD_ARGON2ID;
                } else {
                    throw new LogicException(\sprintf('Algorithm "argon2id" is not available. Either use "%s", upgrade to PHP 7.3+ or use libsodium 1.0.15+ instead.', \defined('PASSWORD_ARGON2I') || $hasSodium ? 'argon2i", "auto' : 'auto'));
                }
                return $this->getHasherConfigFromAlgorithm($config);
        }
        return ['class' => MessageDigestPasswordHasher::class, 'arguments' => [$config['algorithm'], $config['encode_as_base64'] ?? \true, $config['iterations'] ?? 5000]];
    }
    private function getMigratingPasswordConfig(array $config): array
    {
        $frompasswordHashers = $config['migrate_from'];
        unset($config['migrate_from']);
        $hasherChain = [$this->createHasher($config, \true)];
        foreach ($frompasswordHashers as $name) {
            if ($hasher = $this->passwordHashers[$name] ?? \false) {
                $hasher = $hasher instanceof PasswordHasherInterface ? $hasher : $this->createHasher($hasher, \true);
            } else {
                $hasher = $this->createHasher(['algorithm' => $name], \true);
            }
            $hasherChain[] = $hasher;
        }
        return ['class' => MigratingPasswordHasher::class, 'arguments' => $hasherChain];
    }
}
Copyright (c) 2004-present Fabien Potencier

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is furnished
to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
CHANGELOG
=========

6.2
---

 * Use `SensitiveParameter` attribute to redact sensitive values in back traces

5.3
---

 * Add the component
 * Use `bcrypt` as default algorithm in `NativePasswordHasher`
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\PasswordHasher;

use _ContaoManager\Symfony\Component\PasswordHasher\Exception\InvalidPasswordException;
/**
 * Provides password hashing and verification capabilities for "legacy" hashers that require external salts.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 * @author Nicolas Grekas <p@tchwork.com>
 * @author Robin Chalas <robin.chalas@gmail.com>
 */
interface LegacyPasswordHasherInterface extends PasswordHasherInterface
{
    /**
     * Hashes a plain password.
     *
     * @throws InvalidPasswordException If the plain password is invalid, e.g. excessively long
     */
    public function hash(
        #[\SensitiveParameter]
        string $plainPassword,
        ?string $salt = null
    ): string;
    /**
     * Checks that a plain password and a salt match a password hash.
     */
    public function verify(
        string $hashedPassword,
        #[\SensitiveParameter]
        string $plainPassword,
        ?string $salt = null
    ): bool;
}
PasswordHasher Component
========================

The PasswordHasher component provides secure password hashing utilities.

Getting Started
---------------

```
$ composer require symfony/password-hasher
```

```php
use Symfony\Component\PasswordHasher\Hasher\PasswordHasherFactory;

// Configure different password hashers via the factory
$factory = new PasswordHasherFactory([
    'common' => ['algorithm' => 'bcrypt'],
    'memory-hard' => ['algorithm' => 'sodium'],
]);

// Retrieve the right password hasher by its name
$passwordHasher = $factory->getPasswordHasher('common');

// Hash a plain password
$hash = $passwordHasher->hash('plain'); // returns a bcrypt hash

// Verify that a given plain password matches the hash
$passwordHasher->verify($hash, 'wrong'); // returns false
$passwordHasher->verify($hash, 'plain'); // returns true (valid)
```

Resources
---------

 * [Documentation](https://symfony.com/doc/current/security.html#c-hashing-passwords)
 * [Contributing](https://symfony.com/doc/current/contributing/index.html)
 * [Report issues](https://github.com/symfony/symfony/issues) and
   [send Pull Requests](https://github.com/symfony/symfony/pulls)
   in the [main Symfony repository](https://github.com/symfony/symfony)
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\PasswordHasher\Command;

use _ContaoManager\Symfony\Component\Console\Attribute\AsCommand;
use _ContaoManager\Symfony\Component\Console\Command\Command;
use _ContaoManager\Symfony\Component\Console\Completion\CompletionInput;
use _ContaoManager\Symfony\Component\Console\Completion\CompletionSuggestions;
use _ContaoManager\Symfony\Component\Console\Exception\InvalidArgumentException;
use _ContaoManager\Symfony\Component\Console\Exception\RuntimeException;
use _ContaoManager\Symfony\Component\Console\Input\InputArgument;
use _ContaoManager\Symfony\Component\Console\Input\InputInterface;
use _ContaoManager\Symfony\Component\Console\Input\InputOption;
use _ContaoManager\Symfony\Component\Console\Output\ConsoleOutputInterface;
use _ContaoManager\Symfony\Component\Console\Output\OutputInterface;
use _ContaoManager\Symfony\Component\Console\Question\Question;
use _ContaoManager\Symfony\Component\Console\Style\SymfonyStyle;
use _ContaoManager\Symfony\Component\PasswordHasher\Hasher\PasswordHasherFactoryInterface;
use _ContaoManager\Symfony\Component\PasswordHasher\LegacyPasswordHasherInterface;
/**
 * Hashes a user's password.
 *
 * @author Sarah Khalil <mkhalil.sarah@gmail.com>
 * @author Robin Chalas <robin.chalas@gmail.com>
 *
 * @final
 */
#[AsCommand(name: 'security:hash-password', description: 'Hash a user password')]
class UserPasswordHashCommand extends Command
{
    private PasswordHasherFactoryInterface $hasherFactory;
    private array $userClasses;
    public function __construct(PasswordHasherFactoryInterface $hasherFactory, array $userClasses = [])
    {
        $this->hasherFactory = $hasherFactory;
        $this->userClasses = $userClasses;
        parent::__construct();
    }
    protected function configure(): void
    {
        $this->addArgument('password', InputArgument::OPTIONAL, 'The plain password to hash.')->addArgument('user-class', InputArgument::OPTIONAL, 'The User entity class path associated with the hasher used to hash the password.')->addOption('empty-salt', null, InputOption::VALUE_NONE, 'Do not generate a salt or let the hasher generate one.')->setHelp(<<<EOF

The <info>%command.name%</info> command hashes passwords according to your
security configuration. This command is mainly used to generate passwords for
the <comment>in_memory</comment> user provider type and for changing passwords
in the database while developing the application.

Suppose that you have the following security configuration in your application:

<comment>
# config/packages/security.yml
security:
    password_hashers:
        Symfony\\Component\\Security\\Core\\User\\InMemoryUser: plaintext
        App\\Entity\\User: auto
</comment>

If you execute the command non-interactively, the first available configured
user class under the <comment>security.password_hashers</comment> key is used and a random salt is
generated to hash the password:

  <info>php %command.full_name% --no-interaction [password]</info>

Pass the full user class path as the second argument to hash passwords for
your own entities:

  <info>php %command.full_name% --no-interaction [password] 'App\\Entity\\User'</info>

Executing the command interactively allows you to generate a random salt for
hashing the password:

  <info>php %command.full_name% [password] 'App\\Entity\\User'</info>

In case your hasher doesn't require a salt, add the <comment>empty-salt</comment> option:

  <info>php %command.full_name% --empty-salt [password] 'App\\Entity\\User'</info>

EOF
);
    }
    protected function execute(InputInterface $input, OutputInterface $output): int
    {
        $io = new SymfonyStyle($input, $output);
        $errorIo = $output instanceof ConsoleOutputInterface ? new SymfonyStyle($input, $output->getErrorOutput()) : $io;
        $input->isInteractive() ? $errorIo->title('Symfony Password Hash Utility') : $errorIo->newLine();
        $password = $input->getArgument('password');
        $userClass = $this->getUserClass($input, $io);
        $emptySalt = $input->getOption('empty-salt');
        $hasher = $this->hasherFactory->getPasswordHasher($userClass);
        $saltlessWithoutEmptySalt = !$emptySalt && !$hasher instanceof LegacyPasswordHasherInterface;
        if ($saltlessWithoutEmptySalt) {
            $emptySalt = \true;
        }
        if (!$password) {
            if (!$input->isInteractive()) {
                $errorIo->error('The password must not be empty.');
                return 1;
            }
            $passwordQuestion = $this->createPasswordQuestion();
            $password = $errorIo->askQuestion($passwordQuestion);
        }
        $salt = null;
        if ($input->isInteractive() && !$emptySalt) {
            $emptySalt = \true;
            $errorIo->note('The command will take care of generating a salt for you. Be aware that some hashers advise to let them generate their own salt. If you\'re using one of those hashers, please answer \'no\' to the question below. ' . \PHP_EOL . 'Provide the \'empty-salt\' option in order to let the hasher handle the generation itself.');
            if ($errorIo->confirm('Confirm salt generation ?')) {
                $salt = $this->generateSalt();
                $emptySalt = \false;
            }
        } elseif (!$emptySalt) {
            $salt = $this->generateSalt();
        }
        $hashedPassword = $hasher->hash($password, $salt);
        $rows = [['Hasher used', $hasher::class], ['Password hash', $hashedPassword]];
        if (!$emptySalt) {
            $rows[] = ['Generated salt', $salt];
        }
        $io->table(['Key', 'Value'], $rows);
        if (!$emptySalt) {
            $errorIo->note(\sprintf('Make sure that your salt storage field fits the salt length: %s chars', \strlen($salt)));
        } elseif ($saltlessWithoutEmptySalt) {
            $errorIo->note('Self-salting hasher used: the hasher generated its own built-in salt.');
        }
        $errorIo->success('Password hashing succeeded');
        return 0;
    }
    public function complete(CompletionInput $input, CompletionSuggestions $suggestions): void
    {
        if ($input->mustSuggestArgumentValuesFor('user-class')) {
            $suggestions->suggestValues($this->userClasses);
            return;
        }
    }
    /**
     * Create the password question to ask the user for the password to be hashed.
     */
    private function createPasswordQuestion(): Question
    {
        $passwordQuestion = new Question('Type in your password to be hashed');
        return $passwordQuestion->setValidator(function ($value) {
            if ('' === trim($value)) {
                throw new InvalidArgumentException('The password must not be empty.');
            }
            return $value;
        })->setHidden(\true)->setMaxAttempts(20);
    }
    private function generateSalt(): string
    {
        return base64_encode(random_bytes(30));
    }
    private function getUserClass(InputInterface $input, SymfonyStyle $io): string
    {
        if (null !== $userClass = $input->getArgument('user-class')) {
            return $userClass;
        }
        if (!$this->userClasses) {
            throw new RuntimeException('There are no configured password hashers for the "security" extension.');
        }
        if (!$input->isInteractive() || 1 === \count($this->userClasses)) {
            return reset($this->userClasses);
        }
        $userClasses = $this->userClasses;
        natcasesort($userClasses);
        $userClasses = array_values($userClasses);
        return $io->choice('For which user class would you like to hash a password?', $userClasses, reset($userClasses));
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\PasswordHasher\Exception;

/**
 * @author Robin Chalas <robin.chalas@gmail.com>
 */
class LogicException extends \LogicException implements ExceptionInterface
{
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\PasswordHasher\Exception;

/**
 * Interface for exceptions thrown by the password-hasher component.
 *
 * @author Robin Chalas <robin.chalas@gmail.com>
 */
interface ExceptionInterface extends \Throwable
{
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\PasswordHasher\Exception;

/**
 * @author Robin Chalas <robin.chalas@gmail.com>
 */
class InvalidPasswordException extends \RuntimeException implements ExceptionInterface
{
    public function __construct(string $message = 'Invalid password.', int $code = 0, ?\Throwable $previous = null)
    {
        parent::__construct($message, $code, $previous);
    }
}
{
    "name": "symfony\/password-hasher",
    "type": "library",
    "description": "Provides password hashing utilities",
    "keywords": [
        "password",
        "hashing"
    ],
    "homepage": "https:\/\/symfony.com",
    "license": "MIT",
    "authors": [
        {
            "name": "Robin Chalas",
            "email": "robin.chalas@gmail.com"
        },
        {
            "name": "Symfony Community",
            "homepage": "https:\/\/symfony.com\/contributors"
        }
    ],
    "require": {
        "php": ">=8.1"
    },
    "require-dev": {
        "symfony\/security-core": "^5.4|^6.0|^7.0",
        "symfony\/console": "^5.4|^6.0|^7.0"
    },
    "conflict": {
        "symfony\/security-core": "<5.4"
    },
    "autoload": {
        "psr-4": {
            "_ContaoManager\\Symfony\\Component\\PasswordHasher\\": ""
        },
        "exclude-from-classmap": [
            "\/Tests\/"
        ]
    },
    "minimum-stability": "dev"
}Copyright (c) 2004-present Fabien Potencier

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is furnished
to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Process;

/**
 * Generic executable finder.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
class ExecutableFinder
{
    private const CMD_BUILTINS = ['assoc', 'break', 'call', 'cd', 'chdir', 'cls', 'color', 'copy', 'date', 'del', 'dir', 'echo', 'endlocal', 'erase', 'exit', 'for', 'ftype', 'goto', 'help', 'if', 'label', 'md', 'mkdir', 'mklink', 'move', 'path', 'pause', 'popd', 'prompt', 'pushd', 'rd', 'rem', 'ren', 'rename', 'rmdir', 'set', 'setlocal', 'shift', 'start', 'time', 'title', 'type', 'ver', 'vol'];
    private array $suffixes = [];
    /**
     * Replaces default suffixes of executable.
     *
     * @return void
     */
    public function setSuffixes(array $suffixes)
    {
        $this->suffixes = $suffixes;
    }
    /**
     * Adds new possible suffix to check for executable.
     *
     * @return void
     */
    public function addSuffix(string $suffix)
    {
        $this->suffixes[] = $suffix;
    }
    /**
     * Finds an executable by name.
     *
     * @param string      $name      The executable name (without the extension)
     * @param string|null $default   The default to return if no executable is found
     * @param array       $extraDirs Additional dirs to check into
     */
    public function find(string $name, ?string $default = null, array $extraDirs = []): ?string
    {
        // windows built-in commands that are present in cmd.exe should not be resolved using PATH as they do not exist as exes
        if ('\\' === \DIRECTORY_SEPARATOR && \in_array(strtolower($name), self::CMD_BUILTINS, \true)) {
            return $name;
        }
        $dirs = array_merge(explode(\PATH_SEPARATOR, getenv('PATH') ?: getenv('Path')), $extraDirs);
        $suffixes = [];
        if ('\\' === \DIRECTORY_SEPARATOR) {
            $pathExt = getenv('PATHEXT');
            $suffixes = $this->suffixes;
            $suffixes = array_merge($suffixes, $pathExt ? explode(\PATH_SEPARATOR, $pathExt) : ['.exe', '.bat', '.cmd', '.com']);
        }
        $suffixes = '' !== pathinfo($name, \PATHINFO_EXTENSION) ? array_merge([''], $suffixes) : array_merge($suffixes, ['']);
        foreach ($suffixes as $suffix) {
            foreach ($dirs as $dir) {
                if ('' === $dir) {
                    $dir = '.';
                }
                if (@is_file($file = $dir . \DIRECTORY_SEPARATOR . $name . $suffix) && ('\\' === \DIRECTORY_SEPARATOR || @is_executable($file))) {
                    return $file;
                }
                if (!@is_dir($dir) && basename($dir) === $name . $suffix && @is_executable($dir)) {
                    return $dir;
                }
            }
        }
        if ('\\' === \DIRECTORY_SEPARATOR || !\function_exists('exec') || \strlen($name) !== strcspn($name, '/' . \DIRECTORY_SEPARATOR)) {
            return $default;
        }
        $execResult = exec('command -v -- ' . escapeshellarg($name));
        if (($executablePath = substr($execResult, 0, strpos($execResult, \PHP_EOL) ?: null)) && @is_executable($executablePath)) {
            return $executablePath;
        }
        return $default;
    }
}
CHANGELOG
=========

6.4
---

 * Add `PhpSubprocess` to handle PHP subprocesses that take over the
   configuration from their parent
 * Add `RunProcessMessage` and `RunProcessMessageHandler`

5.2.0
-----

 * added `Process::setOptions()` to set `Process` specific options
 * added option `create_new_console` to allow a subprocess to continue
   to run after the main script exited, both on Linux and on Windows

5.1.0
-----

 * added `Process::getStartTime()` to retrieve the start time of the process as float

5.0.0
-----

 * removed `Process::inheritEnvironmentVariables()`
 * removed `PhpProcess::setPhpBinary()`
 * `Process` must be instantiated with a command array, use `Process::fromShellCommandline()` when the command should be parsed by the shell
 * removed `Process::setCommandLine()`

4.4.0
-----

 * deprecated `Process::inheritEnvironmentVariables()`: env variables are always inherited.
 * added `Process::getLastOutputTime()` method

4.2.0
-----

 * added the `Process::fromShellCommandline()` to run commands in a shell wrapper
 * deprecated passing a command as string when creating a `Process` instance
 * deprecated the `Process::setCommandline()` and the `PhpProcess::setPhpBinary()` methods
 * added the `Process::waitUntil()` method to wait for the process only for a
   specific output, then continue the normal execution of your application

4.1.0
-----

 * added the `Process::isTtySupported()` method that allows to check for TTY support
 * made `PhpExecutableFinder` look for the `PHP_BINARY` env var when searching the php binary
 * added the `ProcessSignaledException` class to properly catch signaled process errors

4.0.0
-----

 * environment variables will always be inherited
 * added a second `array $env = []` argument to the `start()`, `run()`,
   `mustRun()`, and `restart()` methods of the `Process` class
 * added a second `array $env = []` argument to the `start()` method of the
   `PhpProcess` class
 * the `ProcessUtils::escapeArgument()` method has been removed
 * the `areEnvironmentVariablesInherited()`, `getOptions()`, and `setOptions()`
   methods of the `Process` class have been removed
 * support for passing `proc_open()` options has been removed
 * removed the `ProcessBuilder` class, use the `Process` class instead
 * removed the `getEnhanceWindowsCompatibility()` and `setEnhanceWindowsCompatibility()` methods of the `Process` class
 * passing a not existing working directory to the constructor of the `Symfony\Component\Process\Process` class is not
   supported anymore

3.4.0
-----

 * deprecated the ProcessBuilder class
 * deprecated calling `Process::start()` without setting a valid working directory beforehand (via `setWorkingDirectory()` or constructor)

3.3.0
-----

 * added command line arrays in the `Process` class
 * added `$env` argument to `Process::start()`, `run()`, `mustRun()` and `restart()` methods
 * deprecated the `ProcessUtils::escapeArgument()` method
 * deprecated not inheriting environment variables
 * deprecated configuring `proc_open()` options
 * deprecated configuring enhanced Windows compatibility
 * deprecated configuring enhanced sigchild compatibility

2.5.0
-----

 * added support for PTY mode
 * added the convenience method "mustRun"
 * deprecation: Process::setStdin() is deprecated in favor of Process::setInput()
 * deprecation: Process::getStdin() is deprecated in favor of Process::getInput()
 * deprecation: Process::setInput() and ProcessBuilder::setInput() do not accept non-scalar types

2.4.0
-----

 * added the ability to define an idle timeout

2.3.0
-----

 * added ProcessUtils::escapeArgument() to fix the bug in escapeshellarg() function on Windows
 * added Process::signal()
 * added Process::getPid()
 * added support for a TTY mode

2.2.0
-----

 * added ProcessBuilder::setArguments() to reset the arguments on a builder
 * added a way to retrieve the standard and error output incrementally
 * added Process:restart()

2.1.0
-----

 * added support for non-blocking processes (start(), wait(), isRunning(), stop())
 * enhanced Windows compatibility
 * added Process::getExitCodeText() that returns a string representation for
   the exit code returned by the process
 * added ProcessBuilder
Process Component
=================

The Process component executes commands in sub-processes.

Resources
---------

 * [Documentation](https://symfony.com/doc/current/components/process.html)
 * [Contributing](https://symfony.com/doc/current/contributing/index.html)
 * [Report issues](https://github.com/symfony/symfony/issues) and
   [send Pull Requests](https://github.com/symfony/symfony/pulls)
   in the [main Symfony repository](https://github.com/symfony/symfony)
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Process\Pipes;

use _ContaoManager\Symfony\Component\Process\Process;
/**
 * UnixPipes implementation uses unix pipes as handles.
 *
 * @author Romain Neutron <imprec@gmail.com>
 *
 * @internal
 */
class UnixPipes extends AbstractPipes
{
    private ?bool $ttyMode;
    private bool $ptyMode;
    private bool $haveReadSupport;
    public function __construct(?bool $ttyMode, bool $ptyMode, mixed $input, bool $haveReadSupport)
    {
        $this->ttyMode = $ttyMode;
        $this->ptyMode = $ptyMode;
        $this->haveReadSupport = $haveReadSupport;
        parent::__construct($input);
    }
    public function __serialize(): array
    {
        throw new \BadMethodCallException('Cannot serialize ' . __CLASS__);
    }
    public function __unserialize(array $data): void
    {
        throw new \BadMethodCallException('Cannot unserialize ' . __CLASS__);
    }
    public function __destruct()
    {
        $this->close();
    }
    public function getDescriptors(): array
    {
        if (!$this->haveReadSupport) {
            $nullstream = fopen('/dev/null', 'c');
            return [['pipe', 'r'], $nullstream, $nullstream];
        }
        if ($this->ttyMode) {
            return [['file', '/dev/tty', 'r'], ['file', '/dev/tty', 'w'], ['file', '/dev/tty', 'w']];
        }
        if ($this->ptyMode && Process::isPtySupported()) {
            return [['pty'], ['pty'], ['pipe', 'w']];
        }
        return [
            ['pipe', 'r'],
            ['pipe', 'w'],
            // stdout
            ['pipe', 'w'],
        ];
    }
    public function getFiles(): array
    {
        return [];
    }
    public function readAndWrite(bool $blocking, bool $close = \false): array
    {
        $this->unblock();
        $w = $this->write();
        $read = $e = [];
        $r = $this->pipes;
        unset($r[0]);
        // let's have a look if something changed in streams
        set_error_handler($this->handleError(...));
        if (($r || $w) && \false === stream_select($r, $w, $e, 0, $blocking ? Process::TIMEOUT_PRECISION * 1000000.0 : 0)) {
            restore_error_handler();
            // if a system call has been interrupted, forget about it, let's try again
            // otherwise, an error occurred, let's reset pipes
            if (!$this->hasSystemCallBeenInterrupted()) {
                $this->pipes = [];
            }
            return $read;
        }
        restore_error_handler();
        foreach ($r as $pipe) {
            // prior PHP 5.4 the array passed to stream_select is modified and
            // lose key association, we have to find back the key
            $read[$type = array_search($pipe, $this->pipes, \true)] = '';
            do {
                $data = @fread($pipe, self::CHUNK_SIZE);
                $read[$type] .= $data;
            } while (isset($data[0]) && ($close || isset($data[self::CHUNK_SIZE - 1])));
            if (!isset($read[$type][0])) {
                unset($read[$type]);
            }
            if ($close && feof($pipe)) {
                fclose($pipe);
                unset($this->pipes[$type]);
            }
        }
        return $read;
    }
    public function haveReadSupport(): bool
    {
        return $this->haveReadSupport;
    }
    public function areOpen(): bool
    {
        return (bool) $this->pipes;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Process\Pipes;

use _ContaoManager\Symfony\Component\Process\Exception\RuntimeException;
use _ContaoManager\Symfony\Component\Process\Process;
/**
 * WindowsPipes implementation uses temporary files as handles.
 *
 * @see https://bugs.php.net/51800
 * @see https://bugs.php.net/65650
 *
 * @author Romain Neutron <imprec@gmail.com>
 *
 * @internal
 */
class WindowsPipes extends AbstractPipes
{
    private array $files = [];
    private array $fileHandles = [];
    private array $lockHandles = [];
    private array $readBytes = [Process::STDOUT => 0, Process::STDERR => 0];
    private bool $haveReadSupport;
    public function __construct(mixed $input, bool $haveReadSupport)
    {
        $this->haveReadSupport = $haveReadSupport;
        if ($this->haveReadSupport) {
            // Fix for PHP bug #51800: reading from STDOUT pipe hangs forever on Windows if the output is too big.
            // Workaround for this problem is to use temporary files instead of pipes on Windows platform.
            //
            // @see https://bugs.php.net/51800
            $pipes = [Process::STDOUT => Process::OUT, Process::STDERR => Process::ERR];
            $tmpDir = sys_get_temp_dir();
            $lastError = 'unknown reason';
            set_error_handler(function ($type, $msg) use (&$lastError) {
                $lastError = $msg;
            });
            for ($i = 0;; ++$i) {
                foreach ($pipes as $pipe => $name) {
                    $file = \sprintf('%s\sf_proc_%02X.%s', $tmpDir, $i, $name);
                    if (!$h = fopen($file . '.lock', 'w')) {
                        if (file_exists($file . '.lock')) {
                            continue 2;
                        }
                        restore_error_handler();
                        throw new RuntimeException('A temporary file could not be opened to write the process output: ' . $lastError);
                    }
                    if (!flock($h, \LOCK_EX | \LOCK_NB)) {
                        continue 2;
                    }
                    if (isset($this->lockHandles[$pipe])) {
                        flock($this->lockHandles[$pipe], \LOCK_UN);
                        fclose($this->lockHandles[$pipe]);
                    }
                    $this->lockHandles[$pipe] = $h;
                    if (!($h = fopen($file, 'w')) || !fclose($h) || !$h = fopen($file, 'r')) {
                        flock($this->lockHandles[$pipe], \LOCK_UN);
                        fclose($this->lockHandles[$pipe]);
                        unset($this->lockHandles[$pipe]);
                        continue 2;
                    }
                    $this->fileHandles[$pipe] = $h;
                    $this->files[$pipe] = $file;
                }
                break;
            }
            restore_error_handler();
        }
        parent::__construct($input);
    }
    public function __serialize(): array
    {
        throw new \BadMethodCallException('Cannot serialize ' . __CLASS__);
    }
    public function __unserialize(array $data): void
    {
        throw new \BadMethodCallException('Cannot unserialize ' . __CLASS__);
    }
    public function __destruct()
    {
        $this->close();
    }
    public function getDescriptors(): array
    {
        if (!$this->haveReadSupport) {
            $nullstream = fopen('NUL', 'c');
            return [['pipe', 'r'], $nullstream, $nullstream];
        }
        // We're not using pipe on Windows platform as it hangs (https://bugs.php.net/51800)
        // We're not using file handles as it can produce corrupted output https://bugs.php.net/65650
        // So we redirect output within the commandline and pass the nul device to the process
        return [['pipe', 'r'], ['file', 'NUL', 'w'], ['file', 'NUL', 'w']];
    }
    public function getFiles(): array
    {
        return $this->files;
    }
    public function readAndWrite(bool $blocking, bool $close = \false): array
    {
        $this->unblock();
        $w = $this->write();
        $read = $r = $e = [];
        if ($blocking) {
            if ($w) {
                @stream_select($r, $w, $e, 0, Process::TIMEOUT_PRECISION * 1000000.0);
            } elseif ($this->fileHandles) {
                usleep((int) (Process::TIMEOUT_PRECISION * 1000000.0));
            }
        }
        foreach ($this->fileHandles as $type => $fileHandle) {
            $data = stream_get_contents($fileHandle, -1, $this->readBytes[$type]);
            if (isset($data[0])) {
                $this->readBytes[$type] += \strlen($data);
                $read[$type] = $data;
            }
            if ($close) {
                ftruncate($fileHandle, 0);
                fclose($fileHandle);
                flock($this->lockHandles[$type], \LOCK_UN);
                fclose($this->lockHandles[$type]);
                unset($this->fileHandles[$type], $this->lockHandles[$type]);
            }
        }
        return $read;
    }
    public function haveReadSupport(): bool
    {
        return $this->haveReadSupport;
    }
    public function areOpen(): bool
    {
        return $this->pipes && $this->fileHandles;
    }
    public function close(): void
    {
        parent::close();
        foreach ($this->fileHandles as $type => $handle) {
            ftruncate($handle, 0);
            fclose($handle);
            flock($this->lockHandles[$type], \LOCK_UN);
            fclose($this->lockHandles[$type]);
        }
        $this->fileHandles = $this->lockHandles = [];
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Process\Pipes;

use _ContaoManager\Symfony\Component\Process\Exception\InvalidArgumentException;
/**
 * @author Romain Neutron <imprec@gmail.com>
 *
 * @internal
 */
abstract class AbstractPipes implements PipesInterface
{
    public array $pipes = [];
    private string $inputBuffer = '';
    /** @var resource|string|\Iterator */
    private $input;
    private bool $blocked = \true;
    private ?string $lastError = null;
    /**
     * @param resource|string|\Iterator $input
     */
    public function __construct($input)
    {
        if (\is_resource($input) || $input instanceof \Iterator) {
            $this->input = $input;
        } else {
            $this->inputBuffer = (string) $input;
        }
    }
    public function close(): void
    {
        foreach ($this->pipes as $pipe) {
            if (\is_resource($pipe)) {
                fclose($pipe);
            }
        }
        $this->pipes = [];
    }
    /**
     * Returns true if a system call has been interrupted.
     *
     * stream_select() returns false when the `select` system call is interrupted by an incoming signal.
     */
    protected function hasSystemCallBeenInterrupted(): bool
    {
        $lastError = $this->lastError;
        $this->lastError = null;
        if (null === $lastError) {
            return \false;
        }
        if (\false !== stripos($lastError, 'interrupted system call')) {
            return \true;
        }
        // on applications with a different locale than english, the message above is not found because
        // it's translated. So we also check for the SOCKET_EINTR constant which is defined under
        // Windows and UNIX-like platforms (if available on the platform).
        return \defined('SOCKET_EINTR') && str_starts_with($lastError, 'stream_select(): Unable to select [' . \SOCKET_EINTR . ']');
    }
    /**
     * Unblocks streams.
     */
    protected function unblock(): void
    {
        if (!$this->blocked) {
            return;
        }
        foreach ($this->pipes as $pipe) {
            stream_set_blocking($pipe, \false);
        }
        if (\is_resource($this->input)) {
            stream_set_blocking($this->input, \false);
        }
        $this->blocked = \false;
    }
    /**
     * Writes input to stdin.
     *
     * @throws InvalidArgumentException When an input iterator yields a non supported value
     */
    protected function write(): ?array
    {
        if (!isset($this->pipes[0])) {
            return null;
        }
        $input = $this->input;
        if ($input instanceof \Iterator) {
            if (!$input->valid()) {
                $input = null;
            } elseif (\is_resource($input = $input->current())) {
                stream_set_blocking($input, \false);
            } elseif (!isset($this->inputBuffer[0])) {
                if (!\is_string($input)) {
                    if (!\is_scalar($input)) {
                        throw new InvalidArgumentException(\sprintf('"%s" yielded a value of type "%s", but only scalars and stream resources are supported.', get_debug_type($this->input), get_debug_type($input)));
                    }
                    $input = (string) $input;
                }
                $this->inputBuffer = $input;
                $this->input->next();
                $input = null;
            } else {
                $input = null;
            }
        }
        $r = $e = [];
        $w = [$this->pipes[0]];
        // let's have a look if something changed in streams
        if (\false === @stream_select($r, $w, $e, 0, 0)) {
            return null;
        }
        foreach ($w as $stdin) {
            if (isset($this->inputBuffer[0])) {
                if (\false === $written = @fwrite($stdin, $this->inputBuffer)) {
                    return $this->closeBrokenInputPipe();
                }
                $this->inputBuffer = substr($this->inputBuffer, $written);
                if (isset($this->inputBuffer[0]) && isset($this->pipes[0])) {
                    return [$this->pipes[0]];
                }
            }
            if ($input) {
                while (\true) {
                    $data = fread($input, self::CHUNK_SIZE);
                    if (!isset($data[0])) {
                        break;
                    }
                    if (\false === $written = @fwrite($stdin, $data)) {
                        return $this->closeBrokenInputPipe();
                    }
                    $data = substr($data, $written);
                    if (isset($data[0])) {
                        $this->inputBuffer = $data;
                        return isset($this->pipes[0]) ? [$this->pipes[0]] : null;
                    }
                }
                if (feof($input)) {
                    if ($this->input instanceof \Iterator) {
                        $this->input->next();
                    } else {
                        $this->input = null;
                    }
                }
            }
        }
        // no input to read on resource, buffer is empty
        if (!isset($this->inputBuffer[0]) && !($this->input instanceof \Iterator ? $this->input->valid() : $this->input)) {
            $this->input = null;
            fclose($this->pipes[0]);
            unset($this->pipes[0]);
        } elseif (!$w) {
            return [$this->pipes[0]];
        }
        return null;
    }
    private function closeBrokenInputPipe(): void
    {
        $this->lastError = error_get_last()['message'] ?? null;
        if (\is_resource($this->pipes[0] ?? null)) {
            fclose($this->pipes[0]);
        }
        unset($this->pipes[0]);
        $this->input = null;
        $this->inputBuffer = '';
    }
    /**
     * @internal
     */
    public function handleError(int $type, string $msg): void
    {
        $this->lastError = $msg;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Process\Pipes;

/**
 * PipesInterface manages descriptors and pipes for the use of proc_open.
 *
 * @author Romain Neutron <imprec@gmail.com>
 *
 * @internal
 */
interface PipesInterface
{
    public const CHUNK_SIZE = 16384;
    /**
     * Returns an array of descriptors for the use of proc_open.
     */
    public function getDescriptors(): array;
    /**
     * Returns an array of filenames indexed by their related stream in case these pipes use temporary files.
     *
     * @return string[]
     */
    public function getFiles(): array;
    /**
     * Reads data in file handles and pipes.
     *
     * @param bool $blocking Whether to use blocking calls or not
     * @param bool $close    Whether to close pipes if they've reached EOF
     *
     * @return string[] An array of read data indexed by their fd
     */
    public function readAndWrite(bool $blocking, bool $close = \false): array;
    /**
     * Returns if the current state has open file handles or pipes.
     */
    public function areOpen(): bool;
    /**
     * Returns if pipes are able to read output.
     */
    public function haveReadSupport(): bool;
    /**
     * Closes file handles and pipes.
     */
    public function close(): void;
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Process;

use _ContaoManager\Symfony\Component\Process\Exception\RuntimeException;
/**
 * Provides a way to continuously write to the input of a Process until the InputStream is closed.
 *
 * @author Nicolas Grekas <p@tchwork.com>
 *
 * @implements \IteratorAggregate<int, string>
 */
class InputStream implements \IteratorAggregate
{
    private ?\Closure $onEmpty = null;
    private array $input = [];
    private bool $open = \true;
    /**
     * Sets a callback that is called when the write buffer becomes empty.
     *
     * @return void
     */
    public function onEmpty(?callable $onEmpty = null)
    {
        $this->onEmpty = null !== $onEmpty ? $onEmpty(...) : null;
    }
    /**
     * Appends an input to the write buffer.
     *
     * @param resource|string|int|float|bool|\Traversable|null $input The input to append as scalar,
     *                                                                stream resource or \Traversable
     *
     * @return void
     */
    public function write(mixed $input)
    {
        if (null === $input) {
            return;
        }
        if ($this->isClosed()) {
            throw new RuntimeException(\sprintf('"%s" is closed.', static::class));
        }
        $this->input[] = ProcessUtils::validateInput(__METHOD__, $input);
    }
    /**
     * Closes the write buffer.
     *
     * @return void
     */
    public function close()
    {
        $this->open = \false;
    }
    /**
     * Tells whether the write buffer is closed or not.
     *
     * @return bool
     */
    public function isClosed()
    {
        return !$this->open;
    }
    public function getIterator(): \Traversable
    {
        $this->open = \true;
        while ($this->open || $this->input) {
            if (!$this->input) {
                yield '';
                continue;
            }
            $current = array_shift($this->input);
            if ($current instanceof \Iterator) {
                yield from $current;
            } else {
                yield $current;
            }
            if (!$this->input && $this->open && null !== $onEmpty = $this->onEmpty) {
                $this->write($onEmpty($this));
            }
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Process\Messenger;

use _ContaoManager\Symfony\Component\Process\Process;
/**
 * @author Kevin Bond <kevinbond@gmail.com>
 */
final class RunProcessContext
{
    public readonly ?int $exitCode;
    public readonly ?string $output;
    public readonly ?string $errorOutput;
    public function __construct(public readonly RunProcessMessage $message, Process $process)
    {
        $this->exitCode = $process->getExitCode();
        $this->output = $process->isOutputDisabled() ? null : $process->getOutput();
        $this->errorOutput = $process->isOutputDisabled() ? null : $process->getErrorOutput();
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Process\Messenger;

/**
 * @author Kevin Bond <kevinbond@gmail.com>
 */
class RunProcessMessage implements \Stringable
{
    public function __construct(public readonly array $command, public readonly ?string $cwd = null, public readonly ?array $env = null, public readonly mixed $input = null, public readonly ?float $timeout = 60.0)
    {
    }
    public function __toString(): string
    {
        return implode(' ', $this->command);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Process\Messenger;

use _ContaoManager\Symfony\Component\Process\Exception\ProcessFailedException;
use _ContaoManager\Symfony\Component\Process\Exception\RunProcessFailedException;
use _ContaoManager\Symfony\Component\Process\Process;
/**
 * @author Kevin Bond <kevinbond@gmail.com>
 */
final class RunProcessMessageHandler
{
    public function __invoke(RunProcessMessage $message): RunProcessContext
    {
        $process = new Process($message->command, $message->cwd, $message->env, $message->input, $message->timeout);
        try {
            return new RunProcessContext($message, $process->mustRun());
        } catch (ProcessFailedException $e) {
            throw new RunProcessFailedException($e, new RunProcessContext($message, $e->getProcess()));
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Process;

use _ContaoManager\Symfony\Component\Process\Exception\LogicException;
use _ContaoManager\Symfony\Component\Process\Exception\RuntimeException;
/**
 * PhpProcess runs a PHP script in an independent process.
 *
 *     $p = new PhpProcess('<?php echo "foo"; ?>');
 *     $p->run();
 *     print $p->getOutput()."\n";
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class PhpProcess extends Process
{
    /**
     * @param string      $script  The PHP script to run (as a string)
     * @param string|null $cwd     The working directory or null to use the working dir of the current PHP process
     * @param array|null  $env     The environment variables or null to use the same environment as the current PHP process
     * @param int         $timeout The timeout in seconds
     * @param array|null  $php     Path to the PHP binary to use with any additional arguments
     */
    public function __construct(string $script, ?string $cwd = null, ?array $env = null, int $timeout = 60, ?array $php = null)
    {
        if (null === $php) {
            $executableFinder = new PhpExecutableFinder();
            $php = $executableFinder->find(\false);
            $php = \false === $php ? null : array_merge([$php], $executableFinder->findArguments());
        }
        if ('phpdbg' === \PHP_SAPI) {
            $file = tempnam(sys_get_temp_dir(), 'dbg');
            file_put_contents($file, $script);
            register_shutdown_function('unlink', $file);
            $php[] = $file;
            $script = null;
        }
        parent::__construct($php, $cwd, $env, $script, $timeout);
    }
    public static function fromShellCommandline(string $command, ?string $cwd = null, ?array $env = null, mixed $input = null, ?float $timeout = 60): static
    {
        throw new LogicException(\sprintf('The "%s()" method cannot be called when using "%s".', __METHOD__, self::class));
    }
    /**
     * @return void
     */
    public function start(?callable $callback = null, array $env = [])
    {
        if (null === $this->getCommandLine()) {
            throw new RuntimeException('Unable to find the PHP executable.');
        }
        parent::start($callback, $env);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Process;

use _ContaoManager\Symfony\Component\Process\Exception\LogicException;
use _ContaoManager\Symfony\Component\Process\Exception\RuntimeException;
/**
 * PhpSubprocess runs a PHP command as a subprocess while keeping the original php.ini settings.
 *
 * For this, it generates a temporary php.ini file taking over all the current settings and disables
 * loading additional .ini files. Basically, your command gets prefixed using "php -n -c /tmp/temp.ini".
 *
 * Given your php.ini contains "memory_limit=-1" and you have a "MemoryTest.php" with the following content:
 *
 *     <?php var_dump(ini_get('memory_limit'));
 *
 * These are the differences between the regular Process and PhpSubprocess classes:
 *
 *     $p = new Process(['php', '-d', 'memory_limit=256M', 'MemoryTest.php']);
 *     $p->run();
 *     print $p->getOutput()."\n";
 *
 * This will output "string(2) "-1", because the process is started with the default php.ini settings.
 *
 *     $p = new PhpSubprocess(['MemoryTest.php'], null, null, 60, ['php', '-d', 'memory_limit=256M']);
 *     $p->run();
 *     print $p->getOutput()."\n";
 *
 * This will output "string(4) "256M"", because the process is started with the temporarily created php.ini settings.
 *
 * @author Yanick Witschi <yanick.witschi@terminal42.ch>
 * @author Partially copied and heavily inspired from composer/xdebug-handler by John Stevenson <john-stevenson@blueyonder.co.uk>
 */
class PhpSubprocess extends Process
{
    /**
     * @param array       $command The command to run and its arguments listed as separate entries. They will automatically
     *                             get prefixed with the PHP binary
     * @param string|null $cwd     The working directory or null to use the working dir of the current PHP process
     * @param array|null  $env     The environment variables or null to use the same environment as the current PHP process
     * @param int         $timeout The timeout in seconds
     * @param array|null  $php     Path to the PHP binary to use with any additional arguments
     */
    public function __construct(array $command, ?string $cwd = null, ?array $env = null, int $timeout = 60, ?array $php = null)
    {
        if (null === $php) {
            $executableFinder = new PhpExecutableFinder();
            $php = $executableFinder->find(\false);
            $php = \false === $php ? null : array_merge([$php], $executableFinder->findArguments());
        }
        if (null === $php) {
            throw new RuntimeException('Unable to find PHP binary.');
        }
        $tmpIni = $this->writeTmpIni($this->getAllIniFiles(), sys_get_temp_dir());
        $php = array_merge($php, ['-n', '-c', $tmpIni]);
        register_shutdown_function('unlink', $tmpIni);
        $command = array_merge($php, $command);
        parent::__construct($command, $cwd, $env, null, $timeout);
    }
    public static function fromShellCommandline(string $command, ?string $cwd = null, ?array $env = null, mixed $input = null, ?float $timeout = 60): static
    {
        throw new LogicException(\sprintf('The "%s()" method cannot be called when using "%s".', __METHOD__, self::class));
    }
    public function start(?callable $callback = null, array $env = []): void
    {
        if (null === $this->getCommandLine()) {
            throw new RuntimeException('Unable to find the PHP executable.');
        }
        parent::start($callback, $env);
    }
    private function writeTmpIni(array $iniFiles, string $tmpDir): string
    {
        if (\false === $tmpfile = @tempnam($tmpDir, '')) {
            throw new RuntimeException('Unable to create temporary ini file.');
        }
        // $iniFiles has at least one item and it may be empty
        if ('' === $iniFiles[0]) {
            array_shift($iniFiles);
        }
        $content = '';
        foreach ($iniFiles as $file) {
            // Check for inaccessible ini files
            if (($data = @file_get_contents($file)) === \false) {
                throw new RuntimeException('Unable to read ini: ' . $file);
            }
            // Check and remove directives after HOST and PATH sections
            if (preg_match('/^\s*\[(?:PATH|HOST)\s*=/mi', $data, $matches, \PREG_OFFSET_CAPTURE)) {
                $data = substr($data, 0, $matches[0][1]);
            }
            $content .= $data . "\n";
        }
        // Merge loaded settings into our ini content, if it is valid
        $config = parse_ini_string($content);
        $loaded = ini_get_all(null, \false);
        if (\false === $config || \false === $loaded) {
            throw new RuntimeException('Unable to parse ini data.');
        }
        $content .= $this->mergeLoadedConfig($loaded, $config);
        // Work-around for https://bugs.php.net/bug.php?id=75932
        $content .= "opcache.enable_cli=0\n";
        if (\false === @file_put_contents($tmpfile, $content)) {
            throw new RuntimeException('Unable to write temporary ini file.');
        }
        return $tmpfile;
    }
    private function mergeLoadedConfig(array $loadedConfig, array $iniConfig): string
    {
        $content = '';
        foreach ($loadedConfig as $name => $value) {
            if (!\is_string($value)) {
                continue;
            }
            if (!isset($iniConfig[$name]) || $iniConfig[$name] !== $value) {
                // Double-quote escape each value
                $content .= $name . '="' . addcslashes($value, '\"') . "\"\n";
            }
        }
        return $content;
    }
    private function getAllIniFiles(): array
    {
        $paths = [(string) php_ini_loaded_file()];
        if (\false !== $scanned = php_ini_scanned_files()) {
            $paths = array_merge($paths, array_map('trim', explode(',', $scanned)));
        }
        return $paths;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Process;

/**
 * An executable finder specifically designed for the PHP executable.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
class PhpExecutableFinder
{
    private ExecutableFinder $executableFinder;
    public function __construct()
    {
        $this->executableFinder = new ExecutableFinder();
    }
    /**
     * Finds The PHP executable.
     */
    public function find(bool $includeArgs = \true): string|false
    {
        if ($php = getenv('PHP_BINARY')) {
            if (!is_executable($php) && !$php = $this->executableFinder->find($php)) {
                return \false;
            }
            if (@is_dir($php)) {
                return \false;
            }
            return $php;
        }
        $args = $this->findArguments();
        $args = $includeArgs && $args ? ' ' . implode(' ', $args) : '';
        // PHP_BINARY return the current sapi executable
        if (\PHP_BINARY && \in_array(\PHP_SAPI, ['cli', 'cli-server', 'phpdbg'], \true)) {
            return \PHP_BINARY . $args;
        }
        if ($php = getenv('PHP_PATH')) {
            if (!@is_executable($php) || @is_dir($php)) {
                return \false;
            }
            return $php;
        }
        if ($php = getenv('PHP_PEAR_PHP_BIN')) {
            if (@is_executable($php) && !@is_dir($php)) {
                return $php;
            }
        }
        if (@is_executable($php = \PHP_BINDIR . ('\\' === \DIRECTORY_SEPARATOR ? '\php.exe' : '/php')) && !@is_dir($php)) {
            return $php;
        }
        $dirs = [\PHP_BINDIR];
        if ('\\' === \DIRECTORY_SEPARATOR) {
            $dirs[] = 'C:\xampp\php\\';
        }
        return $this->executableFinder->find('php', \false, $dirs);
    }
    /**
     * Finds the PHP executable arguments.
     */
    public function findArguments(): array
    {
        $arguments = [];
        if ('phpdbg' === \PHP_SAPI) {
            $arguments[] = '-qrr';
        }
        return $arguments;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Process\Exception;

use _ContaoManager\Symfony\Component\Process\Process;
/**
 * Exception that is thrown when a process has been signaled.
 *
 * @author Sullivan Senechal <soullivaneuh@gmail.com>
 */
final class ProcessSignaledException extends RuntimeException
{
    private Process $process;
    public function __construct(Process $process)
    {
        $this->process = $process;
        parent::__construct(\sprintf('The process has been signaled with signal "%s".', $process->getTermSignal()));
    }
    public function getProcess(): Process
    {
        return $this->process;
    }
    public function getSignal(): int
    {
        return $this->getProcess()->getTermSignal();
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Process\Exception;

/**
 * LogicException for the Process Component.
 *
 * @author Romain Neutron <imprec@gmail.com>
 */
class LogicException extends \LogicException implements ExceptionInterface
{
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Process\Exception;

/**
 * Marker Interface for the Process Component.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
interface ExceptionInterface extends \Throwable
{
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Process\Exception;

use _ContaoManager\Symfony\Component\Process\Process;
/**
 * Exception for failed processes.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
class ProcessFailedException extends RuntimeException
{
    private Process $process;
    public function __construct(Process $process)
    {
        if ($process->isSuccessful()) {
            throw new InvalidArgumentException('Expected a failed process, but the given process was successful.');
        }
        $error = \sprintf('The command "%s" failed.' . "\n\nExit Code: %s(%s)\n\nWorking directory: %s", $process->getCommandLine(), $process->getExitCode(), $process->getExitCodeText(), $process->getWorkingDirectory());
        if (!$process->isOutputDisabled()) {
            $error .= \sprintf("\n\nOutput:\n================\n%s\n\nError Output:\n================\n%s", $process->getOutput(), $process->getErrorOutput());
        }
        parent::__construct($error);
        $this->process = $process;
    }
    /**
     * @return Process
     */
    public function getProcess()
    {
        return $this->process;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Process\Exception;

/**
 * RuntimeException for the Process Component.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
class RuntimeException extends \RuntimeException implements ExceptionInterface
{
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Process\Exception;

use _ContaoManager\Symfony\Component\Process\Process;
/**
 * Exception that is thrown when a process times out.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
class ProcessTimedOutException extends RuntimeException
{
    public const TYPE_GENERAL = 1;
    public const TYPE_IDLE = 2;
    private Process $process;
    private int $timeoutType;
    public function __construct(Process $process, int $timeoutType)
    {
        $this->process = $process;
        $this->timeoutType = $timeoutType;
        parent::__construct(\sprintf('The process "%s" exceeded the timeout of %s seconds.', $process->getCommandLine(), $this->getExceededTimeout()));
    }
    /**
     * @return Process
     */
    public function getProcess()
    {
        return $this->process;
    }
    /**
     * @return bool
     */
    public function isGeneralTimeout()
    {
        return self::TYPE_GENERAL === $this->timeoutType;
    }
    /**
     * @return bool
     */
    public function isIdleTimeout()
    {
        return self::TYPE_IDLE === $this->timeoutType;
    }
    public function getExceededTimeout(): ?float
    {
        return match ($this->timeoutType) {
            self::TYPE_GENERAL => $this->process->getTimeout(),
            self::TYPE_IDLE => $this->process->getIdleTimeout(),
            default => throw new \LogicException(\sprintf('Unknown timeout type "%d".', $this->timeoutType)),
        };
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Process\Exception;

/**
 * InvalidArgumentException for the Process Component.
 *
 * @author Romain Neutron <imprec@gmail.com>
 */
class InvalidArgumentException extends \InvalidArgumentException implements ExceptionInterface
{
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Process\Exception;

use _ContaoManager\Symfony\Component\Process\Messenger\RunProcessContext;
/**
 * @author Kevin Bond <kevinbond@gmail.com>
 */
final class RunProcessFailedException extends RuntimeException
{
    public function __construct(ProcessFailedException $exception, public readonly RunProcessContext $context)
    {
        parent::__construct($exception->getMessage(), $exception->getCode());
    }
}
{
    "name": "symfony\/process",
    "type": "library",
    "description": "Executes commands in sub-processes",
    "keywords": [],
    "homepage": "https:\/\/symfony.com",
    "license": "MIT",
    "authors": [
        {
            "name": "Fabien Potencier",
            "email": "fabien@symfony.com"
        },
        {
            "name": "Symfony Community",
            "homepage": "https:\/\/symfony.com\/contributors"
        }
    ],
    "require": {
        "php": ">=8.1"
    },
    "autoload": {
        "psr-4": {
            "_ContaoManager\\Symfony\\Component\\Process\\": ""
        },
        "exclude-from-classmap": [
            "\/Tests\/"
        ]
    },
    "minimum-stability": "dev"
}<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Process;

use _ContaoManager\Symfony\Component\Process\Exception\InvalidArgumentException;
/**
 * ProcessUtils is a bunch of utility methods.
 *
 * This class contains static methods only and is not meant to be instantiated.
 *
 * @author Martin Hasoň <martin.hason@gmail.com>
 */
class ProcessUtils
{
    /**
     * This class should not be instantiated.
     */
    private function __construct()
    {
    }
    /**
     * Validates and normalizes a Process input.
     *
     * @param string $caller The name of method call that validates the input
     * @param mixed  $input  The input to validate
     *
     * @throws InvalidArgumentException In case the input is not valid
     */
    public static function validateInput(string $caller, mixed $input): mixed
    {
        if (null !== $input) {
            if (\is_resource($input)) {
                return $input;
            }
            if (\is_scalar($input)) {
                return (string) $input;
            }
            if ($input instanceof Process) {
                return $input->getIterator($input::ITER_SKIP_ERR);
            }
            if ($input instanceof \Iterator) {
                return $input;
            }
            if ($input instanceof \Traversable) {
                return new \IteratorIterator($input);
            }
            throw new InvalidArgumentException(\sprintf('"%s" only accepts strings, Traversable objects or stream resources.', $caller));
        }
        return $input;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Process;

use _ContaoManager\Symfony\Component\Process\Exception\InvalidArgumentException;
use _ContaoManager\Symfony\Component\Process\Exception\LogicException;
use _ContaoManager\Symfony\Component\Process\Exception\ProcessFailedException;
use _ContaoManager\Symfony\Component\Process\Exception\ProcessSignaledException;
use _ContaoManager\Symfony\Component\Process\Exception\ProcessTimedOutException;
use _ContaoManager\Symfony\Component\Process\Exception\RuntimeException;
use _ContaoManager\Symfony\Component\Process\Pipes\UnixPipes;
use _ContaoManager\Symfony\Component\Process\Pipes\WindowsPipes;
/**
 * Process is a thin wrapper around proc_* functions to easily
 * start independent PHP processes.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 * @author Romain Neutron <imprec@gmail.com>
 *
 * @implements \IteratorAggregate<string, string>
 */
class Process implements \IteratorAggregate
{
    public const ERR = 'err';
    public const OUT = 'out';
    public const STATUS_READY = 'ready';
    public const STATUS_STARTED = 'started';
    public const STATUS_TERMINATED = 'terminated';
    public const STDIN = 0;
    public const STDOUT = 1;
    public const STDERR = 2;
    // Timeout Precision in seconds.
    public const TIMEOUT_PRECISION = 0.2;
    public const ITER_NON_BLOCKING = 1;
    // By default, iterating over outputs is a blocking call, use this flag to make it non-blocking
    public const ITER_KEEP_OUTPUT = 2;
    // By default, outputs are cleared while iterating, use this flag to keep them in memory
    public const ITER_SKIP_OUT = 4;
    // Use this flag to skip STDOUT while iterating
    public const ITER_SKIP_ERR = 8;
    // Use this flag to skip STDERR while iterating
    private ?\Closure $callback = null;
    private array|string $commandline;
    private ?string $cwd;
    private array $env = [];
    /** @var resource|string|\Iterator|null */
    private $input;
    private ?float $starttime = null;
    private ?float $lastOutputTime = null;
    private ?float $timeout = null;
    private ?float $idleTimeout = null;
    private ?int $exitcode = null;
    private array $fallbackStatus = [];
    private array $processInformation;
    private bool $outputDisabled = \false;
    /** @var resource */
    private $stdout;
    /** @var resource */
    private $stderr;
    /** @var resource|null */
    private $process;
    private string $status = self::STATUS_READY;
    private int $incrementalOutputOffset = 0;
    private int $incrementalErrorOutputOffset = 0;
    private bool $tty = \false;
    private bool $pty;
    private array $options = ['suppress_errors' => \true, 'bypass_shell' => \true];
    private WindowsPipes|UnixPipes $processPipes;
    private ?int $latestSignal = null;
    private static ?bool $sigchild = null;
    /**
     * Exit codes translation table.
     *
     * User-defined errors must use exit codes in the 64-113 range.
     */
    public static $exitCodes = [
        0 => 'OK',
        1 => 'General error',
        2 => 'Misuse of shell builtins',
        126 => 'Invoked command cannot execute',
        127 => 'Command not found',
        128 => 'Invalid exit argument',
        // signals
        129 => 'Hangup',
        130 => 'Interrupt',
        131 => 'Quit and dump core',
        132 => 'Illegal instruction',
        133 => 'Trace/breakpoint trap',
        134 => 'Process aborted',
        135 => 'Bus error: "access to undefined portion of memory object"',
        136 => 'Floating point exception: "erroneous arithmetic operation"',
        137 => 'Kill (terminate immediately)',
        138 => 'User-defined 1',
        139 => 'Segmentation violation',
        140 => 'User-defined 2',
        141 => 'Write to pipe with no one reading',
        142 => 'Signal raised by alarm',
        143 => 'Termination (request to terminate)',
        // 144 - not defined
        145 => 'Child process terminated, stopped (or continued*)',
        146 => 'Continue if stopped',
        147 => 'Stop executing temporarily',
        148 => 'Terminal stop signal',
        149 => 'Background process attempting to read from tty ("in")',
        150 => 'Background process attempting to write to tty ("out")',
        151 => 'Urgent data available on socket',
        152 => 'CPU time limit exceeded',
        153 => 'File size limit exceeded',
        154 => 'Signal raised by timer counting virtual time: "virtual timer expired"',
        155 => 'Profiling timer expired',
        // 156 - not defined
        157 => 'Pollable event',
        // 158 - not defined
        159 => 'Bad syscall',
    ];
    /**
     * @param array          $command The command to run and its arguments listed as separate entries
     * @param string|null    $cwd     The working directory or null to use the working dir of the current PHP process
     * @param array|null     $env     The environment variables or null to use the same environment as the current PHP process
     * @param mixed          $input   The input as stream resource, scalar or \Traversable, or null for no input
     * @param int|float|null $timeout The timeout in seconds or null to disable
     *
     * @throws LogicException When proc_open is not installed
     */
    public function __construct(array $command, ?string $cwd = null, ?array $env = null, mixed $input = null, ?float $timeout = 60)
    {
        if (!\function_exists('proc_open') && !\function_exists('_ContaoManager\proc_open')) {
            throw new LogicException('The Process class relies on proc_open, which is not available on your PHP installation.');
        }
        $this->commandline = $command;
        $this->cwd = $cwd;
        // on Windows, if the cwd changed via chdir(), proc_open defaults to the dir where PHP was started
        // on Gnu/Linux, PHP builds with --enable-maintainer-zts are also affected
        // @see : https://bugs.php.net/51800
        // @see : https://bugs.php.net/50524
        if (null === $this->cwd && (\defined('ZEND_THREAD_SAFE') || '\\' === \DIRECTORY_SEPARATOR)) {
            $this->cwd = getcwd();
        }
        if (null !== $env) {
            $this->setEnv($env);
        }
        $this->setInput($input);
        $this->setTimeout($timeout);
        $this->pty = \false;
    }
    /**
     * Creates a Process instance as a command-line to be run in a shell wrapper.
     *
     * Command-lines are parsed by the shell of your OS (/bin/sh on Unix-like, cmd.exe on Windows.)
     * This allows using e.g. pipes or conditional execution. In this mode, signals are sent to the
     * shell wrapper and not to your commands.
     *
     * In order to inject dynamic values into command-lines, we strongly recommend using placeholders.
     * This will save escaping values, which is not portable nor secure anyway:
     *
     *   $process = Process::fromShellCommandline('my_command "${:MY_VAR}"');
     *   $process->run(null, ['MY_VAR' => $theValue]);
     *
     * @param string         $command The command line to pass to the shell of the OS
     * @param string|null    $cwd     The working directory or null to use the working dir of the current PHP process
     * @param array|null     $env     The environment variables or null to use the same environment as the current PHP process
     * @param mixed          $input   The input as stream resource, scalar or \Traversable, or null for no input
     * @param int|float|null $timeout The timeout in seconds or null to disable
     *
     * @throws LogicException When proc_open is not installed
     */
    public static function fromShellCommandline(string $command, ?string $cwd = null, ?array $env = null, mixed $input = null, ?float $timeout = 60): static
    {
        $process = new static([], $cwd, $env, $input, $timeout);
        $process->commandline = $command;
        return $process;
    }
    public function __serialize(): array
    {
        throw new \BadMethodCallException('Cannot serialize ' . __CLASS__);
    }
    public function __unserialize(array $data): void
    {
        throw new \BadMethodCallException('Cannot unserialize ' . __CLASS__);
    }
    public function __destruct()
    {
        if ($this->options['create_new_console'] ?? \false) {
            $this->processPipes->close();
        } else {
            $this->stop(0);
        }
    }
    public function __clone()
    {
        $this->resetProcessData();
    }
    /**
     * Runs the process.
     *
     * The callback receives the type of output (out or err) and
     * some bytes from the output in real-time. It allows to have feedback
     * from the independent process during execution.
     *
     * The STDOUT and STDERR are also available after the process is finished
     * via the getOutput() and getErrorOutput() methods.
     *
     * @param callable|null $callback A PHP callback to run whenever there is some
     *                                output available on STDOUT or STDERR
     *
     * @return int The exit status code
     *
     * @throws RuntimeException         When process can't be launched
     * @throws RuntimeException         When process is already running
     * @throws ProcessTimedOutException When process timed out
     * @throws ProcessSignaledException When process stopped after receiving signal
     * @throws LogicException           In case a callback is provided and output has been disabled
     *
     * @final
     */
    public function run(?callable $callback = null, array $env = []): int
    {
        $this->start($callback, $env);
        return $this->wait();
    }
    /**
     * Runs the process.
     *
     * This is identical to run() except that an exception is thrown if the process
     * exits with a non-zero exit code.
     *
     * @return $this
     *
     * @throws ProcessFailedException   When process didn't terminate successfully
     * @throws RuntimeException         When process can't be launched
     * @throws RuntimeException         When process is already running
     * @throws ProcessTimedOutException When process timed out
     * @throws ProcessSignaledException When process stopped after receiving signal
     * @throws LogicException           In case a callback is provided and output has been disabled
     *
     * @final
     */
    public function mustRun(?callable $callback = null, array $env = []): static
    {
        if (0 !== $this->run($callback, $env)) {
            throw new ProcessFailedException($this);
        }
        return $this;
    }
    /**
     * Starts the process and returns after writing the input to STDIN.
     *
     * This method blocks until all STDIN data is sent to the process then it
     * returns while the process runs in the background.
     *
     * The termination of the process can be awaited with wait().
     *
     * The callback receives the type of output (out or err) and some bytes from
     * the output in real-time while writing the standard input to the process.
     * It allows to have feedback from the independent process during execution.
     *
     * @param callable|null $callback A PHP callback to run whenever there is some
     *                                output available on STDOUT or STDERR
     *
     * @return void
     *
     * @throws RuntimeException When process can't be launched
     * @throws RuntimeException When process is already running
     * @throws LogicException   In case a callback is provided and output has been disabled
     */
    public function start(?callable $callback = null, array $env = [])
    {
        if ($this->isRunning()) {
            throw new RuntimeException('Process is already running.');
        }
        $this->resetProcessData();
        $this->starttime = $this->lastOutputTime = microtime(\true);
        $this->callback = $this->buildCallback($callback);
        $descriptors = $this->getDescriptors(null !== $callback);
        if ($this->env) {
            $env += '\\' === \DIRECTORY_SEPARATOR ? array_diff_ukey($this->env, $env, 'strcasecmp') : $this->env;
        }
        $env += '\\' === \DIRECTORY_SEPARATOR ? array_diff_ukey($this->getDefaultEnv(), $env, 'strcasecmp') : $this->getDefaultEnv();
        if (\is_array($commandline = $this->commandline)) {
            $commandline = implode(' ', array_map($this->escapeArgument(...), $commandline));
            if ('\\' !== \DIRECTORY_SEPARATOR) {
                // exec is mandatory to deal with sending a signal to the process
                $commandline = 'exec ' . $commandline;
            }
        } else {
            $commandline = $this->replacePlaceholders($commandline, $env);
        }
        if ('\\' === \DIRECTORY_SEPARATOR) {
            $commandline = $this->prepareWindowsCommandLine($commandline, $env);
        } elseif ($this->isSigchildEnabled()) {
            // last exit code is output on the fourth pipe and caught to work around --enable-sigchild
            $descriptors[3] = ['pipe', 'w'];
            // See https://unix.stackexchange.com/questions/71205/background-process-pipe-input
            $commandline = '{ (' . $commandline . ') <&3 3<&- 3>/dev/null & } 3<&0;';
            $commandline .= 'pid=$!; echo $pid >&3; wait $pid 2>/dev/null; code=$?; echo $code >&3; exit $code';
        }
        $envPairs = [];
        foreach ($env as $k => $v) {
            if (\false !== $v && !\in_array($k = (string) $k, ['', 'argc', 'argv', 'ARGC', 'ARGV'], \true) && !str_contains($k, '=') && !str_contains($k, "\x00")) {
                $envPairs[] = $k . '=' . $v;
            }
        }
        if (!is_dir($this->cwd)) {
            throw new RuntimeException(\sprintf('The provided cwd "%s" does not exist.', $this->cwd));
        }
        $process = @proc_open($commandline, $descriptors, $this->processPipes->pipes, $this->cwd, $envPairs, $this->options);
        if (!$process) {
            throw new RuntimeException('Unable to launch a new process.');
        }
        $this->process = $process;
        $this->status = self::STATUS_STARTED;
        if (isset($descriptors[3])) {
            $this->fallbackStatus['pid'] = (int) fgets($this->processPipes->pipes[3]);
        }
        if ($this->tty) {
            return;
        }
        $this->updateStatus(\false);
        $this->checkTimeout();
    }
    /**
     * Restarts the process.
     *
     * Be warned that the process is cloned before being started.
     *
     * @param callable|null $callback A PHP callback to run whenever there is some
     *                                output available on STDOUT or STDERR
     *
     * @throws RuntimeException When process can't be launched
     * @throws RuntimeException When process is already running
     *
     * @see start()
     *
     * @final
     */
    public function restart(?callable $callback = null, array $env = []): static
    {
        if ($this->isRunning()) {
            throw new RuntimeException('Process is already running.');
        }
        $process = clone $this;
        $process->start($callback, $env);
        return $process;
    }
    /**
     * Waits for the process to terminate.
     *
     * The callback receives the type of output (out or err) and some bytes
     * from the output in real-time while writing the standard input to the process.
     * It allows to have feedback from the independent process during execution.
     *
     * @param callable|null $callback A valid PHP callback
     *
     * @return int The exitcode of the process
     *
     * @throws ProcessTimedOutException When process timed out
     * @throws ProcessSignaledException When process stopped after receiving signal
     * @throws LogicException           When process is not yet started
     */
    public function wait(?callable $callback = null): int
    {
        $this->requireProcessIsStarted(__FUNCTION__);
        $this->updateStatus(\false);
        if (null !== $callback) {
            if (!$this->processPipes->haveReadSupport()) {
                $this->stop(0);
                throw new LogicException('Pass the callback to the "Process::start" method or call enableOutput to use a callback with "Process::wait".');
            }
            $this->callback = $this->buildCallback($callback);
        }
        do {
            $this->checkTimeout();
            $running = $this->isRunning() && ('\\' === \DIRECTORY_SEPARATOR || $this->processPipes->areOpen());
            $this->readPipes($running, '\\' !== \DIRECTORY_SEPARATOR || !$running);
        } while ($running);
        while ($this->isRunning()) {
            $this->checkTimeout();
            usleep(1000);
        }
        if ($this->processInformation['signaled'] && $this->processInformation['termsig'] !== $this->latestSignal) {
            throw new ProcessSignaledException($this);
        }
        return $this->exitcode;
    }
    /**
     * Waits until the callback returns true.
     *
     * The callback receives the type of output (out or err) and some bytes
     * from the output in real-time while writing the standard input to the process.
     * It allows to have feedback from the independent process during execution.
     *
     * @throws RuntimeException         When process timed out
     * @throws LogicException           When process is not yet started
     * @throws ProcessTimedOutException In case the timeout was reached
     */
    public function waitUntil(callable $callback): bool
    {
        $this->requireProcessIsStarted(__FUNCTION__);
        $this->updateStatus(\false);
        if (!$this->processPipes->haveReadSupport()) {
            $this->stop(0);
            throw new LogicException('Pass the callback to the "Process::start" method or call enableOutput to use a callback with "Process::waitUntil".');
        }
        $callback = $this->buildCallback($callback);
        $ready = \false;
        while (\true) {
            $this->checkTimeout();
            $running = '\\' === \DIRECTORY_SEPARATOR ? $this->isRunning() : $this->processPipes->areOpen();
            $output = $this->processPipes->readAndWrite($running, '\\' !== \DIRECTORY_SEPARATOR || !$running);
            foreach ($output as $type => $data) {
                if (3 !== $type) {
                    $ready = $callback(self::STDOUT === $type ? self::OUT : self::ERR, $data) || $ready;
                } elseif (!isset($this->fallbackStatus['signaled'])) {
                    $this->fallbackStatus['exitcode'] = (int) $data;
                }
            }
            if ($ready) {
                return \true;
            }
            if (!$running) {
                return \false;
            }
            usleep(1000);
        }
    }
    /**
     * Returns the Pid (process identifier), if applicable.
     *
     * @return int|null The process id if running, null otherwise
     */
    public function getPid(): ?int
    {
        return $this->isRunning() ? $this->processInformation['pid'] : null;
    }
    /**
     * Sends a POSIX signal to the process.
     *
     * @param int $signal A valid POSIX signal (see https://php.net/pcntl.constants)
     *
     * @return $this
     *
     * @throws LogicException   In case the process is not running
     * @throws RuntimeException In case --enable-sigchild is activated and the process can't be killed
     * @throws RuntimeException In case of failure
     */
    public function signal(int $signal): static
    {
        $this->doSignal($signal, \true);
        return $this;
    }
    /**
     * Disables fetching output and error output from the underlying process.
     *
     * @return $this
     *
     * @throws RuntimeException In case the process is already running
     * @throws LogicException   if an idle timeout is set
     */
    public function disableOutput(): static
    {
        if ($this->isRunning()) {
            throw new RuntimeException('Disabling output while the process is running is not possible.');
        }
        if (null !== $this->idleTimeout) {
            throw new LogicException('Output cannot be disabled while an idle timeout is set.');
        }
        $this->outputDisabled = \true;
        return $this;
    }
    /**
     * Enables fetching output and error output from the underlying process.
     *
     * @return $this
     *
     * @throws RuntimeException In case the process is already running
     */
    public function enableOutput(): static
    {
        if ($this->isRunning()) {
            throw new RuntimeException('Enabling output while the process is running is not possible.');
        }
        $this->outputDisabled = \false;
        return $this;
    }
    /**
     * Returns true in case the output is disabled, false otherwise.
     */
    public function isOutputDisabled(): bool
    {
        return $this->outputDisabled;
    }
    /**
     * Returns the current output of the process (STDOUT).
     *
     * @throws LogicException in case the output has been disabled
     * @throws LogicException In case the process is not started
     */
    public function getOutput(): string
    {
        $this->readPipesForOutput(__FUNCTION__);
        if (\false === $ret = stream_get_contents($this->stdout, -1, 0)) {
            return '';
        }
        return $ret;
    }
    /**
     * Returns the output incrementally.
     *
     * In comparison with the getOutput method which always return the whole
     * output, this one returns the new output since the last call.
     *
     * @throws LogicException in case the output has been disabled
     * @throws LogicException In case the process is not started
     */
    public function getIncrementalOutput(): string
    {
        $this->readPipesForOutput(__FUNCTION__);
        $latest = stream_get_contents($this->stdout, -1, $this->incrementalOutputOffset);
        $this->incrementalOutputOffset = ftell($this->stdout);
        if (\false === $latest) {
            return '';
        }
        return $latest;
    }
    /**
     * Returns an iterator to the output of the process, with the output type as keys (Process::OUT/ERR).
     *
     * @param int $flags A bit field of Process::ITER_* flags
     *
     * @return \Generator<string, string>
     *
     * @throws LogicException in case the output has been disabled
     * @throws LogicException In case the process is not started
     */
    public function getIterator(int $flags = 0): \Generator
    {
        $this->readPipesForOutput(__FUNCTION__, \false);
        $clearOutput = !(self::ITER_KEEP_OUTPUT & $flags);
        $blocking = !(self::ITER_NON_BLOCKING & $flags);
        $yieldOut = !(self::ITER_SKIP_OUT & $flags);
        $yieldErr = !(self::ITER_SKIP_ERR & $flags);
        while (null !== $this->callback || $yieldOut && !feof($this->stdout) || $yieldErr && !feof($this->stderr)) {
            if ($yieldOut) {
                $out = stream_get_contents($this->stdout, -1, $this->incrementalOutputOffset);
                if (isset($out[0])) {
                    if ($clearOutput) {
                        $this->clearOutput();
                    } else {
                        $this->incrementalOutputOffset = ftell($this->stdout);
                    }
                    yield self::OUT => $out;
                }
            }
            if ($yieldErr) {
                $err = stream_get_contents($this->stderr, -1, $this->incrementalErrorOutputOffset);
                if (isset($err[0])) {
                    if ($clearOutput) {
                        $this->clearErrorOutput();
                    } else {
                        $this->incrementalErrorOutputOffset = ftell($this->stderr);
                    }
                    yield self::ERR => $err;
                }
            }
            if (!$blocking && !isset($out[0]) && !isset($err[0])) {
                yield self::OUT => '';
            }
            $this->checkTimeout();
            $this->readPipesForOutput(__FUNCTION__, $blocking);
        }
    }
    /**
     * Clears the process output.
     *
     * @return $this
     */
    public function clearOutput(): static
    {
        ftruncate($this->stdout, 0);
        fseek($this->stdout, 0);
        $this->incrementalOutputOffset = 0;
        return $this;
    }
    /**
     * Returns the current error output of the process (STDERR).
     *
     * @throws LogicException in case the output has been disabled
     * @throws LogicException In case the process is not started
     */
    public function getErrorOutput(): string
    {
        $this->readPipesForOutput(__FUNCTION__);
        if (\false === $ret = stream_get_contents($this->stderr, -1, 0)) {
            return '';
        }
        return $ret;
    }
    /**
     * Returns the errorOutput incrementally.
     *
     * In comparison with the getErrorOutput method which always return the
     * whole error output, this one returns the new error output since the last
     * call.
     *
     * @throws LogicException in case the output has been disabled
     * @throws LogicException In case the process is not started
     */
    public function getIncrementalErrorOutput(): string
    {
        $this->readPipesForOutput(__FUNCTION__);
        $latest = stream_get_contents($this->stderr, -1, $this->incrementalErrorOutputOffset);
        $this->incrementalErrorOutputOffset = ftell($this->stderr);
        if (\false === $latest) {
            return '';
        }
        return $latest;
    }
    /**
     * Clears the process output.
     *
     * @return $this
     */
    public function clearErrorOutput(): static
    {
        ftruncate($this->stderr, 0);
        fseek($this->stderr, 0);
        $this->incrementalErrorOutputOffset = 0;
        return $this;
    }
    /**
     * Returns the exit code returned by the process.
     *
     * @return int|null The exit status code, null if the Process is not terminated
     */
    public function getExitCode(): ?int
    {
        $this->updateStatus(\false);
        return $this->exitcode;
    }
    /**
     * Returns a string representation for the exit code returned by the process.
     *
     * This method relies on the Unix exit code status standardization
     * and might not be relevant for other operating systems.
     *
     * @return string|null A string representation for the exit status code, null if the Process is not terminated
     *
     * @see http://tldp.org/LDP/abs/html/exitcodes.html
     * @see http://en.wikipedia.org/wiki/Unix_signal
     */
    public function getExitCodeText(): ?string
    {
        if (null === $exitcode = $this->getExitCode()) {
            return null;
        }
        return self::$exitCodes[$exitcode] ?? 'Unknown error';
    }
    /**
     * Checks if the process ended successfully.
     */
    public function isSuccessful(): bool
    {
        return 0 === $this->getExitCode();
    }
    /**
     * Returns true if the child process has been terminated by an uncaught signal.
     *
     * It always returns false on Windows.
     *
     * @throws LogicException In case the process is not terminated
     */
    public function hasBeenSignaled(): bool
    {
        $this->requireProcessIsTerminated(__FUNCTION__);
        return $this->processInformation['signaled'];
    }
    /**
     * Returns the number of the signal that caused the child process to terminate its execution.
     *
     * It is only meaningful if hasBeenSignaled() returns true.
     *
     * @throws RuntimeException In case --enable-sigchild is activated
     * @throws LogicException   In case the process is not terminated
     */
    public function getTermSignal(): int
    {
        $this->requireProcessIsTerminated(__FUNCTION__);
        if ($this->isSigchildEnabled() && -1 === $this->processInformation['termsig']) {
            throw new RuntimeException('This PHP has been compiled with --enable-sigchild. Term signal cannot be retrieved.');
        }
        return $this->processInformation['termsig'];
    }
    /**
     * Returns true if the child process has been stopped by a signal.
     *
     * It always returns false on Windows.
     *
     * @throws LogicException In case the process is not terminated
     */
    public function hasBeenStopped(): bool
    {
        $this->requireProcessIsTerminated(__FUNCTION__);
        return $this->processInformation['stopped'];
    }
    /**
     * Returns the number of the signal that caused the child process to stop its execution.
     *
     * It is only meaningful if hasBeenStopped() returns true.
     *
     * @throws LogicException In case the process is not terminated
     */
    public function getStopSignal(): int
    {
        $this->requireProcessIsTerminated(__FUNCTION__);
        return $this->processInformation['stopsig'];
    }
    /**
     * Checks if the process is currently running.
     */
    public function isRunning(): bool
    {
        if (self::STATUS_STARTED !== $this->status) {
            return \false;
        }
        $this->updateStatus(\false);
        return $this->processInformation['running'];
    }
    /**
     * Checks if the process has been started with no regard to the current state.
     */
    public function isStarted(): bool
    {
        return self::STATUS_READY != $this->status;
    }
    /**
     * Checks if the process is terminated.
     */
    public function isTerminated(): bool
    {
        $this->updateStatus(\false);
        return self::STATUS_TERMINATED == $this->status;
    }
    /**
     * Gets the process status.
     *
     * The status is one of: ready, started, terminated.
     */
    public function getStatus(): string
    {
        $this->updateStatus(\false);
        return $this->status;
    }
    /**
     * Stops the process.
     *
     * @param int|float $timeout The timeout in seconds
     * @param int|null  $signal  A POSIX signal to send in case the process has not stop at timeout, default is SIGKILL (9)
     *
     * @return int|null The exit-code of the process or null if it's not running
     */
    public function stop(float $timeout = 10, ?int $signal = null): ?int
    {
        $timeoutMicro = microtime(\true) + $timeout;
        if ($this->isRunning()) {
            // given SIGTERM may not be defined and that "proc_terminate" uses the constant value and not the constant itself, we use the same here
            $this->doSignal(15, \false);
            do {
                usleep(1000);
            } while ($this->isRunning() && microtime(\true) < $timeoutMicro);
            if ($this->isRunning()) {
                // Avoid exception here: process is supposed to be running, but it might have stopped just
                // after this line. In any case, let's silently discard the error, we cannot do anything.
                $this->doSignal($signal ?: 9, \false);
            }
        }
        if ($this->isRunning()) {
            if (isset($this->fallbackStatus['pid'])) {
                unset($this->fallbackStatus['pid']);
                return $this->stop(0, $signal);
            }
            $this->close();
        }
        return $this->exitcode;
    }
    /**
     * Adds a line to the STDOUT stream.
     *
     * @internal
     */
    public function addOutput(string $line): void
    {
        $this->lastOutputTime = microtime(\true);
        fseek($this->stdout, 0, \SEEK_END);
        fwrite($this->stdout, $line);
        fseek($this->stdout, $this->incrementalOutputOffset);
    }
    /**
     * Adds a line to the STDERR stream.
     *
     * @internal
     */
    public function addErrorOutput(string $line): void
    {
        $this->lastOutputTime = microtime(\true);
        fseek($this->stderr, 0, \SEEK_END);
        fwrite($this->stderr, $line);
        fseek($this->stderr, $this->incrementalErrorOutputOffset);
    }
    /**
     * Gets the last output time in seconds.
     */
    public function getLastOutputTime(): ?float
    {
        return $this->lastOutputTime;
    }
    /**
     * Gets the command line to be executed.
     */
    public function getCommandLine(): string
    {
        return \is_array($this->commandline) ? implode(' ', array_map($this->escapeArgument(...), $this->commandline)) : $this->commandline;
    }
    /**
     * Gets the process timeout in seconds (max. runtime).
     */
    public function getTimeout(): ?float
    {
        return $this->timeout;
    }
    /**
     * Gets the process idle timeout in seconds (max. time since last output).
     */
    public function getIdleTimeout(): ?float
    {
        return $this->idleTimeout;
    }
    /**
     * Sets the process timeout (max. runtime) in seconds.
     *
     * To disable the timeout, set this value to null.
     *
     * @return $this
     *
     * @throws InvalidArgumentException if the timeout is negative
     */
    public function setTimeout(?float $timeout): static
    {
        $this->timeout = $this->validateTimeout($timeout);
        return $this;
    }
    /**
     * Sets the process idle timeout (max. time since last output) in seconds.
     *
     * To disable the timeout, set this value to null.
     *
     * @return $this
     *
     * @throws LogicException           if the output is disabled
     * @throws InvalidArgumentException if the timeout is negative
     */
    public function setIdleTimeout(?float $timeout): static
    {
        if (null !== $timeout && $this->outputDisabled) {
            throw new LogicException('Idle timeout cannot be set while the output is disabled.');
        }
        $this->idleTimeout = $this->validateTimeout($timeout);
        return $this;
    }
    /**
     * Enables or disables the TTY mode.
     *
     * @return $this
     *
     * @throws RuntimeException In case the TTY mode is not supported
     */
    public function setTty(bool $tty): static
    {
        if ('\\' === \DIRECTORY_SEPARATOR && $tty) {
            throw new RuntimeException('TTY mode is not supported on Windows platform.');
        }
        if ($tty && !self::isTtySupported()) {
            throw new RuntimeException('TTY mode requires /dev/tty to be read/writable.');
        }
        $this->tty = $tty;
        return $this;
    }
    /**
     * Checks if the TTY mode is enabled.
     */
    public function isTty(): bool
    {
        return $this->tty;
    }
    /**
     * Sets PTY mode.
     *
     * @return $this
     */
    public function setPty(bool $bool): static
    {
        $this->pty = $bool;
        return $this;
    }
    /**
     * Returns PTY state.
     */
    public function isPty(): bool
    {
        return $this->pty;
    }
    /**
     * Gets the working directory.
     */
    public function getWorkingDirectory(): ?string
    {
        if (null === $this->cwd) {
            // getcwd() will return false if any one of the parent directories does not have
            // the readable or search mode set, even if the current directory does
            return getcwd() ?: null;
        }
        return $this->cwd;
    }
    /**
     * Sets the current working directory.
     *
     * @return $this
     */
    public function setWorkingDirectory(string $cwd): static
    {
        $this->cwd = $cwd;
        return $this;
    }
    /**
     * Gets the environment variables.
     */
    public function getEnv(): array
    {
        return $this->env;
    }
    /**
     * Sets the environment variables.
     *
     * @param array<string|\Stringable> $env The new environment variables
     *
     * @return $this
     */
    public function setEnv(array $env): static
    {
        $this->env = $env;
        return $this;
    }
    /**
     * Gets the Process input.
     *
     * @return resource|string|\Iterator|null
     */
    public function getInput()
    {
        return $this->input;
    }
    /**
     * Sets the input.
     *
     * This content will be passed to the underlying process standard input.
     *
     * @param string|resource|\Traversable|self|null $input The content
     *
     * @return $this
     *
     * @throws LogicException In case the process is running
     */
    public function setInput(mixed $input): static
    {
        if ($this->isRunning()) {
            throw new LogicException('Input cannot be set while the process is running.');
        }
        $this->input = ProcessUtils::validateInput(__METHOD__, $input);
        return $this;
    }
    /**
     * Performs a check between the timeout definition and the time the process started.
     *
     * In case you run a background process (with the start method), you should
     * trigger this method regularly to ensure the process timeout
     *
     * @return void
     *
     * @throws ProcessTimedOutException In case the timeout was reached
     */
    public function checkTimeout()
    {
        if (self::STATUS_STARTED !== $this->status) {
            return;
        }
        if (null !== $this->timeout && $this->timeout < microtime(\true) - $this->starttime) {
            $this->stop(0);
            throw new ProcessTimedOutException($this, ProcessTimedOutException::TYPE_GENERAL);
        }
        if (null !== $this->idleTimeout && $this->idleTimeout < microtime(\true) - $this->lastOutputTime) {
            $this->stop(0);
            throw new ProcessTimedOutException($this, ProcessTimedOutException::TYPE_IDLE);
        }
    }
    /**
     * @throws LogicException in case process is not started
     */
    public function getStartTime(): float
    {
        if (!$this->isStarted()) {
            throw new LogicException('Start time is only available after process start.');
        }
        return $this->starttime;
    }
    /**
     * Defines options to pass to the underlying proc_open().
     *
     * @see https://php.net/proc_open for the options supported by PHP.
     *
     * Enabling the "create_new_console" option allows a subprocess to continue
     * to run after the main process exited, on both Windows and *nix
     *
     * @return void
     */
    public function setOptions(array $options)
    {
        if ($this->isRunning()) {
            throw new RuntimeException('Setting options while the process is running is not possible.');
        }
        $defaultOptions = $this->options;
        $existingOptions = ['blocking_pipes', 'create_process_group', 'create_new_console'];
        foreach ($options as $key => $value) {
            if (!\in_array($key, $existingOptions)) {
                $this->options = $defaultOptions;
                throw new LogicException(\sprintf('Invalid option "%s" passed to "%s()". Supported options are "%s".', $key, __METHOD__, implode('", "', $existingOptions)));
            }
            $this->options[$key] = $value;
        }
    }
    /**
     * Returns whether TTY is supported on the current operating system.
     */
    public static function isTtySupported(): bool
    {
        static $isTtySupported;
        return $isTtySupported ??= '/' === \DIRECTORY_SEPARATOR && stream_isatty(\STDOUT) && @is_writable('/dev/tty');
    }
    /**
     * Returns whether PTY is supported on the current operating system.
     */
    public static function isPtySupported(): bool
    {
        static $result;
        if (null !== $result) {
            return $result;
        }
        if ('\\' === \DIRECTORY_SEPARATOR) {
            return $result = \false;
        }
        return $result = (bool) @proc_open('echo 1 >/dev/null', [['pty'], ['pty'], ['pty']], $pipes);
    }
    /**
     * Creates the descriptors needed by the proc_open.
     */
    private function getDescriptors(bool $hasCallback): array
    {
        if ($this->input instanceof \Iterator) {
            $this->input->rewind();
        }
        if ('\\' === \DIRECTORY_SEPARATOR) {
            $this->processPipes = new WindowsPipes($this->input, !$this->outputDisabled || $hasCallback);
        } else {
            $this->processPipes = new UnixPipes($this->isTty(), $this->isPty(), $this->input, !$this->outputDisabled || $hasCallback);
        }
        return $this->processPipes->getDescriptors();
    }
    /**
     * Builds up the callback used by wait().
     *
     * The callbacks adds all occurred output to the specific buffer and calls
     * the user callback (if present) with the received output.
     *
     * @param callable|null $callback The user defined PHP callback
     */
    protected function buildCallback(?callable $callback = null): \Closure
    {
        if ($this->outputDisabled) {
            return fn($type, $data): bool => null !== $callback && $callback($type, $data);
        }
        $out = self::OUT;
        return function ($type, $data) use ($callback, $out): bool {
            if ($out == $type) {
                $this->addOutput($data);
            } else {
                $this->addErrorOutput($data);
            }
            return null !== $callback && $callback($type, $data);
        };
    }
    /**
     * Updates the status of the process, reads pipes.
     *
     * @param bool $blocking Whether to use a blocking read call
     *
     * @return void
     */
    protected function updateStatus(bool $blocking)
    {
        if (self::STATUS_STARTED !== $this->status) {
            return;
        }
        if ($this->processInformation['running'] ?? \true) {
            $this->processInformation = proc_get_status($this->process);
        }
        $running = $this->processInformation['running'];
        $this->readPipes($running && $blocking, '\\' !== \DIRECTORY_SEPARATOR || !$running);
        if ($this->fallbackStatus && $this->isSigchildEnabled()) {
            $this->processInformation = $this->fallbackStatus + $this->processInformation;
        }
        if (!$running) {
            $this->close();
        }
    }
    /**
     * Returns whether PHP has been compiled with the '--enable-sigchild' option or not.
     */
    protected function isSigchildEnabled(): bool
    {
        if (null !== self::$sigchild) {
            return self::$sigchild;
        }
        if (!\function_exists('phpinfo') && !\function_exists('_ContaoManager\phpinfo')) {
            return self::$sigchild = \false;
        }
        ob_start();
        phpinfo(\INFO_GENERAL);
        return self::$sigchild = str_contains(ob_get_clean(), '--enable-sigchild');
    }
    /**
     * Reads pipes for the freshest output.
     *
     * @param string $caller   The name of the method that needs fresh outputs
     * @param bool   $blocking Whether to use blocking calls or not
     *
     * @throws LogicException in case output has been disabled or process is not started
     */
    private function readPipesForOutput(string $caller, bool $blocking = \false): void
    {
        if ($this->outputDisabled) {
            throw new LogicException('Output has been disabled.');
        }
        $this->requireProcessIsStarted($caller);
        $this->updateStatus($blocking);
    }
    /**
     * Validates and returns the filtered timeout.
     *
     * @throws InvalidArgumentException if the given timeout is a negative number
     */
    private function validateTimeout(?float $timeout): ?float
    {
        $timeout = (float) $timeout;
        if (0.0 === $timeout) {
            $timeout = null;
        } elseif ($timeout < 0) {
            throw new InvalidArgumentException('The timeout value must be a valid positive integer or float number.');
        }
        return $timeout;
    }
    /**
     * Reads pipes, executes callback.
     *
     * @param bool $blocking Whether to use blocking calls or not
     * @param bool $close    Whether to close file handles or not
     */
    private function readPipes(bool $blocking, bool $close): void
    {
        $result = $this->processPipes->readAndWrite($blocking, $close);
        $callback = $this->callback;
        foreach ($result as $type => $data) {
            if (3 !== $type) {
                $callback(self::STDOUT === $type ? self::OUT : self::ERR, $data);
            } elseif (!isset($this->fallbackStatus['signaled'])) {
                $this->fallbackStatus['exitcode'] = (int) $data;
            }
        }
    }
    /**
     * Closes process resource, closes file handles, sets the exitcode.
     *
     * @return int The exitcode
     */
    private function close(): int
    {
        $this->processPipes->close();
        if ($this->process) {
            proc_close($this->process);
            $this->process = null;
        }
        $this->exitcode = $this->processInformation['exitcode'];
        $this->status = self::STATUS_TERMINATED;
        if (-1 === $this->exitcode) {
            if ($this->processInformation['signaled'] && 0 < $this->processInformation['termsig']) {
                // if process has been signaled, no exitcode but a valid termsig, apply Unix convention
                $this->exitcode = 128 + $this->processInformation['termsig'];
            } elseif ($this->isSigchildEnabled()) {
                $this->processInformation['signaled'] = \true;
                $this->processInformation['termsig'] = -1;
            }
        }
        // Free memory from self-reference callback created by buildCallback
        // Doing so in other contexts like __destruct or by garbage collector is ineffective
        // Now pipes are closed, so the callback is no longer necessary
        $this->callback = null;
        return $this->exitcode;
    }
    /**
     * Resets data related to the latest run of the process.
     */
    private function resetProcessData(): void
    {
        $this->starttime = null;
        $this->callback = null;
        $this->exitcode = null;
        $this->fallbackStatus = [];
        $this->processInformation = [];
        $this->stdout = fopen('php://temp/maxmemory:' . 1024 * 1024, 'w+');
        $this->stderr = fopen('php://temp/maxmemory:' . 1024 * 1024, 'w+');
        $this->process = null;
        $this->latestSignal = null;
        $this->status = self::STATUS_READY;
        $this->incrementalOutputOffset = 0;
        $this->incrementalErrorOutputOffset = 0;
    }
    /**
     * Sends a POSIX signal to the process.
     *
     * @param int  $signal         A valid POSIX signal (see https://php.net/pcntl.constants)
     * @param bool $throwException Whether to throw exception in case signal failed
     *
     * @throws LogicException   In case the process is not running
     * @throws RuntimeException In case --enable-sigchild is activated and the process can't be killed
     * @throws RuntimeException In case of failure
     */
    private function doSignal(int $signal, bool $throwException): bool
    {
        if (null === $pid = $this->getPid()) {
            if ($throwException) {
                throw new LogicException('Cannot send signal on a non running process.');
            }
            return \false;
        }
        if ('\\' === \DIRECTORY_SEPARATOR) {
            exec(\sprintf('taskkill /F /T /PID %d 2>&1', $pid), $output, $exitCode);
            if ($exitCode && $this->isRunning()) {
                if ($throwException) {
                    throw new RuntimeException(\sprintf('Unable to kill the process (%s).', implode(' ', $output)));
                }
                return \false;
            }
        } else {
            if (!$this->isSigchildEnabled()) {
                $ok = @proc_terminate($this->process, $signal);
            } elseif (\function_exists('posix_kill')) {
                $ok = @posix_kill($pid, $signal);
            } elseif ($ok = proc_open(\sprintf('kill -%d %d', $signal, $pid), [2 => ['pipe', 'w']], $pipes)) {
                $ok = \false === fgets($pipes[2]);
            }
            if (!$ok) {
                if ($throwException) {
                    throw new RuntimeException(\sprintf('Error while sending signal "%s".', $signal));
                }
                return \false;
            }
        }
        $this->latestSignal = $signal;
        $this->fallbackStatus['signaled'] = \true;
        $this->fallbackStatus['exitcode'] = -1;
        $this->fallbackStatus['termsig'] = $this->latestSignal;
        return \true;
    }
    private function prepareWindowsCommandLine(string $cmd, array &$env): string
    {
        $uid = uniqid('', \true);
        $cmd = preg_replace_callback('/"(?:(
                [^"%!^]*+
                (?:
                    (?: !LF! | "(?:\^[%!^])?+" )
                    [^"%!^]*+
                )++
            ) | [^"]*+ )"/x', function ($m) use (&$env, $uid) {
            static $varCount = 0;
            static $varCache = [];
            if (!isset($m[1])) {
                return $m[0];
            }
            if (isset($varCache[$m[0]])) {
                return $varCache[$m[0]];
            }
            if (str_contains($value = $m[1], "\x00")) {
                $value = str_replace("\x00", '?', $value);
            }
            if (\false === strpbrk($value, "\"%!\n")) {
                return '"' . $value . '"';
            }
            $value = str_replace(['!LF!', '"^!"', '"^%"', '"^^"', '""'], ["\n", '!', '%', '^', '"'], $value);
            $value = '"' . preg_replace('/(\\\\*)"/', '$1$1\"', $value) . '"';
            $var = $uid . ++$varCount;
            $env[$var] = $value;
            return $varCache[$m[0]] = '!' . $var . '!';
        }, $cmd);
        static $comSpec;
        if (!$comSpec && $comSpec = (new ExecutableFinder())->find('cmd.exe')) {
            // Escape according to CommandLineToArgvW rules
            $comSpec = '"' . preg_replace('{(\\\\*+)"}', '$1$1\"', $comSpec) . '"';
        }
        $cmd = ($comSpec ?? 'cmd') . ' /V:ON /E:ON /D /C (' . str_replace("\n", ' ', $cmd) . ')';
        foreach ($this->processPipes->getFiles() as $offset => $filename) {
            $cmd .= ' ' . $offset . '>"' . $filename . '"';
        }
        return $cmd;
    }
    /**
     * Ensures the process is running or terminated, throws a LogicException if the process has a not started.
     *
     * @throws LogicException if the process has not run
     */
    private function requireProcessIsStarted(string $functionName): void
    {
        if (!$this->isStarted()) {
            throw new LogicException(\sprintf('Process must be started before calling "%s()".', $functionName));
        }
    }
    /**
     * Ensures the process is terminated, throws a LogicException if the process has a status different than "terminated".
     *
     * @throws LogicException if the process is not yet terminated
     */
    private function requireProcessIsTerminated(string $functionName): void
    {
        if (!$this->isTerminated()) {
            throw new LogicException(\sprintf('Process must be terminated before calling "%s()".', $functionName));
        }
    }
    /**
     * Escapes a string to be used as a shell argument.
     */
    private function escapeArgument(?string $argument): string
    {
        if ('' === $argument || null === $argument) {
            return '""';
        }
        if ('\\' !== \DIRECTORY_SEPARATOR) {
            return "'" . str_replace("'", "'\\''", $argument) . "'";
        }
        if (str_contains($argument, "\x00")) {
            $argument = str_replace("\x00", '?', $argument);
        }
        if (!preg_match('/[()%!^"<>&|\s[\]=;*?\'$]/', $argument)) {
            return $argument;
        }
        $argument = preg_replace('/(\\\\+)$/', '$1$1', $argument);
        return '"' . str_replace(['"', '^', '%', '!', "\n"], ['""', '"^^"', '"^%"', '"^!"', '!LF!'], $argument) . '"';
    }
    private function replacePlaceholders(string $commandline, array $env): string
    {
        return preg_replace_callback('/"\$\{:([_a-zA-Z]++[_a-zA-Z0-9]*+)\}"/', function ($matches) use ($commandline, $env) {
            if (!isset($env[$matches[1]]) || \false === $env[$matches[1]]) {
                throw new InvalidArgumentException(\sprintf('Command line is missing a value for parameter "%s": ', $matches[1]) . $commandline);
            }
            return $this->escapeArgument($env[$matches[1]]);
        }, $commandline);
    }
    private function getDefaultEnv(): array
    {
        $env = getenv();
        $env = ('\\' === \DIRECTORY_SEPARATOR ? array_intersect_ukey($env, $_SERVER, 'strcasecmp') : array_intersect_key($env, $_SERVER)) ?: $env;
        return $_ENV + ('\\' === \DIRECTORY_SEPARATOR ? array_diff_ukey($env, $_ENV, 'strcasecmp') : $env);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Console\DataCollector;

use _ContaoManager\Symfony\Component\Console\Command\Command;
use _ContaoManager\Symfony\Component\Console\Debug\CliRequest;
use _ContaoManager\Symfony\Component\Console\Output\OutputInterface;
use _ContaoManager\Symfony\Component\Console\SignalRegistry\SignalMap;
use _ContaoManager\Symfony\Component\HttpFoundation\Request;
use _ContaoManager\Symfony\Component\HttpFoundation\Response;
use _ContaoManager\Symfony\Component\HttpKernel\DataCollector\DataCollector;
use _ContaoManager\Symfony\Component\VarDumper\Cloner\Data;
/**
 * @internal
 *
 * @author Jules Pietri <jules@heahprod.com>
 */
final class CommandDataCollector extends DataCollector
{
    public function collect(Request $request, Response $response, ?\Throwable $exception = null): void
    {
        if (!$request instanceof CliRequest) {
            return;
        }
        $command = $request->command;
        $application = $command->getApplication();
        $this->data = ['command' => $this->cloneVar($command->command), 'exit_code' => $command->exitCode, 'interrupted_by_signal' => $command->interruptedBySignal, 'duration' => $command->duration, 'max_memory_usage' => $command->maxMemoryUsage, 'verbosity_level' => match ($command->output->getVerbosity()) {
            OutputInterface::VERBOSITY_QUIET => 'quiet',
            OutputInterface::VERBOSITY_NORMAL => 'normal',
            OutputInterface::VERBOSITY_VERBOSE => 'verbose',
            OutputInterface::VERBOSITY_VERY_VERBOSE => 'very verbose',
            OutputInterface::VERBOSITY_DEBUG => 'debug',
        }, 'interactive' => $command->isInteractive, 'validate_input' => !$command->ignoreValidation, 'enabled' => $command->isEnabled(), 'visible' => !$command->isHidden(), 'input' => $this->cloneVar($command->input), 'output' => $this->cloneVar($command->output), 'interactive_inputs' => array_map($this->cloneVar(...), $command->interactiveInputs), 'signalable' => $command->getSubscribedSignals(), 'handled_signals' => $command->handledSignals, 'helper_set' => array_map($this->cloneVar(...), iterator_to_array($command->getHelperSet()))];
        $baseDefinition = $application->getDefinition();
        foreach ($command->arguments as $argName => $argValue) {
            if ($baseDefinition->hasArgument($argName)) {
                $this->data['application_inputs'][$argName] = $this->cloneVar($argValue);
            } else {
                $this->data['arguments'][$argName] = $this->cloneVar($argValue);
            }
        }
        foreach ($command->options as $optName => $optValue) {
            if ($baseDefinition->hasOption($optName)) {
                $this->data['application_inputs']['--' . $optName] = $this->cloneVar($optValue);
            } else {
                $this->data['options'][$optName] = $this->cloneVar($optValue);
            }
        }
    }
    public function getName(): string
    {
        return 'command';
    }
    /**
     * @return array{
     *     class?: class-string,
     *     executor?: string,
     *     file: string,
     *     line: int,
     * }
     */
    public function getCommand(): array
    {
        $class = $this->data['command']->getType();
        $r = new \ReflectionMethod($class, 'execute');
        if (Command::class !== $r->getDeclaringClass()) {
            return ['executor' => $class . '::' . $r->name, 'file' => $r->getFileName(), 'line' => $r->getStartLine()];
        }
        $r = new \ReflectionClass($class);
        return ['class' => $class, 'file' => $r->getFileName(), 'line' => $r->getStartLine()];
    }
    public function getInterruptedBySignal(): ?string
    {
        if (isset($this->data['interrupted_by_signal'])) {
            return \sprintf('%s (%d)', SignalMap::getSignalName($this->data['interrupted_by_signal']), $this->data['interrupted_by_signal']);
        }
        return null;
    }
    public function getDuration(): string
    {
        return $this->data['duration'];
    }
    public function getMaxMemoryUsage(): string
    {
        return $this->data['max_memory_usage'];
    }
    public function getVerbosityLevel(): string
    {
        return $this->data['verbosity_level'];
    }
    public function getInteractive(): bool
    {
        return $this->data['interactive'];
    }
    public function getValidateInput(): bool
    {
        return $this->data['validate_input'];
    }
    public function getEnabled(): bool
    {
        return $this->data['enabled'];
    }
    public function getVisible(): bool
    {
        return $this->data['visible'];
    }
    public function getInput(): Data
    {
        return $this->data['input'];
    }
    public function getOutput(): Data
    {
        return $this->data['output'];
    }
    /**
     * @return Data[]
     */
    public function getArguments(): array
    {
        return $this->data['arguments'] ?? [];
    }
    /**
     * @return Data[]
     */
    public function getOptions(): array
    {
        return $this->data['options'] ?? [];
    }
    /**
     * @return Data[]
     */
    public function getApplicationInputs(): array
    {
        return $this->data['application_inputs'] ?? [];
    }
    /**
     * @return Data[]
     */
    public function getInteractiveInputs(): array
    {
        return $this->data['interactive_inputs'] ?? [];
    }
    public function getSignalable(): array
    {
        return array_map(static fn(int $signal): string => \sprintf('%s (%d)', SignalMap::getSignalName($signal), $signal), $this->data['signalable']);
    }
    public function getHandledSignals(): array
    {
        $keys = array_map(static fn(int $signal): string => \sprintf('%s (%d)', SignalMap::getSignalName($signal), $signal), array_keys($this->data['handled_signals']));
        return array_combine($keys, array_values($this->data['handled_signals']));
    }
    /**
     * @return Data[]
     */
    public function getHelperSet(): array
    {
        return $this->data['helper_set'] ?? [];
    }
    public function reset(): void
    {
        $this->data = [];
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Console;

use _ContaoManager\Symfony\Component\Console\Event\ConsoleCommandEvent;
use _ContaoManager\Symfony\Component\Console\Event\ConsoleErrorEvent;
use _ContaoManager\Symfony\Component\Console\Event\ConsoleSignalEvent;
use _ContaoManager\Symfony\Component\Console\Event\ConsoleTerminateEvent;
/**
 * Contains all events dispatched by an Application.
 *
 * @author Francesco Levorato <git@flevour.net>
 */
final class ConsoleEvents
{
    /**
     * The COMMAND event allows you to attach listeners before any command is
     * executed by the console. It also allows you to modify the command, input and output
     * before they are handed to the command.
     *
     * @Event("Symfony\Component\Console\Event\ConsoleCommandEvent")
     */
    public const COMMAND = 'console.command';
    /**
     * The SIGNAL event allows you to perform some actions
     * after the command execution was interrupted.
     *
     * @Event("Symfony\Component\Console\Event\ConsoleSignalEvent")
     */
    public const SIGNAL = 'console.signal';
    /**
     * The TERMINATE event allows you to attach listeners after a command is
     * executed by the console.
     *
     * @Event("Symfony\Component\Console\Event\ConsoleTerminateEvent")
     */
    public const TERMINATE = 'console.terminate';
    /**
     * The ERROR event occurs when an uncaught exception or error appears.
     *
     * This event allows you to deal with the exception/error or
     * to modify the thrown exception.
     *
     * @Event("Symfony\Component\Console\Event\ConsoleErrorEvent")
     */
    public const ERROR = 'console.error';
    /**
     * Event aliases.
     *
     * These aliases can be consumed by RegisterListenersPass.
     */
    public const ALIASES = [ConsoleCommandEvent::class => self::COMMAND, ConsoleErrorEvent::class => self::ERROR, ConsoleSignalEvent::class => self::SIGNAL, ConsoleTerminateEvent::class => self::TERMINATE];
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Console;

use _ContaoManager\Symfony\Component\Console\Output\OutputInterface;
/**
 * @author Pierre du Plessis <pdples@gmail.com>
 */
final class Cursor
{
    private OutputInterface $output;
    /** @var resource */
    private $input;
    /**
     * @param resource|null $input
     */
    public function __construct(OutputInterface $output, $input = null)
    {
        $this->output = $output;
        $this->input = $input ?? (\defined('STDIN') ? \STDIN : fopen('php://input', 'r+'));
    }
    /**
     * @return $this
     */
    public function moveUp(int $lines = 1): static
    {
        $this->output->write(\sprintf("\x1b[%dA", $lines));
        return $this;
    }
    /**
     * @return $this
     */
    public function moveDown(int $lines = 1): static
    {
        $this->output->write(\sprintf("\x1b[%dB", $lines));
        return $this;
    }
    /**
     * @return $this
     */
    public function moveRight(int $columns = 1): static
    {
        $this->output->write(\sprintf("\x1b[%dC", $columns));
        return $this;
    }
    /**
     * @return $this
     */
    public function moveLeft(int $columns = 1): static
    {
        $this->output->write(\sprintf("\x1b[%dD", $columns));
        return $this;
    }
    /**
     * @return $this
     */
    public function moveToColumn(int $column): static
    {
        $this->output->write(\sprintf("\x1b[%dG", $column));
        return $this;
    }
    /**
     * @return $this
     */
    public function moveToPosition(int $column, int $row): static
    {
        $this->output->write(\sprintf("\x1b[%d;%dH", $row + 1, $column));
        return $this;
    }
    /**
     * @return $this
     */
    public function savePosition(): static
    {
        $this->output->write("\x1b7");
        return $this;
    }
    /**
     * @return $this
     */
    public function restorePosition(): static
    {
        $this->output->write("\x1b8");
        return $this;
    }
    /**
     * @return $this
     */
    public function hide(): static
    {
        $this->output->write("\x1b[?25l");
        return $this;
    }
    /**
     * @return $this
     */
    public function show(): static
    {
        $this->output->write("\x1b[?25h\x1b[?0c");
        return $this;
    }
    /**
     * Clears all the output from the current line.
     *
     * @return $this
     */
    public function clearLine(): static
    {
        $this->output->write("\x1b[2K");
        return $this;
    }
    /**
     * Clears all the output from the current line after the current position.
     */
    public function clearLineAfter(): self
    {
        $this->output->write("\x1b[K");
        return $this;
    }
    /**
     * Clears all the output from the cursors' current position to the end of the screen.
     *
     * @return $this
     */
    public function clearOutput(): static
    {
        $this->output->write("\x1b[0J");
        return $this;
    }
    /**
     * Clears the entire screen.
     *
     * @return $this
     */
    public function clearScreen(): static
    {
        $this->output->write("\x1b[2J");
        return $this;
    }
    /**
     * Returns the current cursor position as x,y coordinates.
     */
    public function getCurrentPosition(): array
    {
        static $isTtySupported;
        if (!$isTtySupported ??= '/' === \DIRECTORY_SEPARATOR && stream_isatty(\STDOUT)) {
            return [1, 1];
        }
        $sttyMode = shell_exec('stty -g');
        shell_exec('stty -icanon -echo');
        @fwrite($this->input, "\x1b[6n");
        $code = trim(fread($this->input, 1024));
        shell_exec(\sprintf('stty %s', $sttyMode));
        sscanf($code, "\x1b[%d;%dR", $row, $col);
        return [$col, $row];
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Console;

use _ContaoManager\Symfony\Component\Console\Command\Command;
use _ContaoManager\Symfony\Component\Console\Command\CompleteCommand;
use _ContaoManager\Symfony\Component\Console\Command\DumpCompletionCommand;
use _ContaoManager\Symfony\Component\Console\Command\HelpCommand;
use _ContaoManager\Symfony\Component\Console\Command\LazyCommand;
use _ContaoManager\Symfony\Component\Console\Command\ListCommand;
use _ContaoManager\Symfony\Component\Console\Command\SignalableCommandInterface;
use _ContaoManager\Symfony\Component\Console\CommandLoader\CommandLoaderInterface;
use _ContaoManager\Symfony\Component\Console\Completion\CompletionInput;
use _ContaoManager\Symfony\Component\Console\Completion\CompletionSuggestions;
use _ContaoManager\Symfony\Component\Console\Completion\Suggestion;
use _ContaoManager\Symfony\Component\Console\Event\ConsoleCommandEvent;
use _ContaoManager\Symfony\Component\Console\Event\ConsoleErrorEvent;
use _ContaoManager\Symfony\Component\Console\Event\ConsoleSignalEvent;
use _ContaoManager\Symfony\Component\Console\Event\ConsoleTerminateEvent;
use _ContaoManager\Symfony\Component\Console\Exception\CommandNotFoundException;
use _ContaoManager\Symfony\Component\Console\Exception\ExceptionInterface;
use _ContaoManager\Symfony\Component\Console\Exception\LogicException;
use _ContaoManager\Symfony\Component\Console\Exception\NamespaceNotFoundException;
use _ContaoManager\Symfony\Component\Console\Exception\RuntimeException;
use _ContaoManager\Symfony\Component\Console\Formatter\OutputFormatter;
use _ContaoManager\Symfony\Component\Console\Helper\DebugFormatterHelper;
use _ContaoManager\Symfony\Component\Console\Helper\DescriptorHelper;
use _ContaoManager\Symfony\Component\Console\Helper\FormatterHelper;
use _ContaoManager\Symfony\Component\Console\Helper\Helper;
use _ContaoManager\Symfony\Component\Console\Helper\HelperSet;
use _ContaoManager\Symfony\Component\Console\Helper\ProcessHelper;
use _ContaoManager\Symfony\Component\Console\Helper\QuestionHelper;
use _ContaoManager\Symfony\Component\Console\Input\ArgvInput;
use _ContaoManager\Symfony\Component\Console\Input\ArrayInput;
use _ContaoManager\Symfony\Component\Console\Input\InputArgument;
use _ContaoManager\Symfony\Component\Console\Input\InputAwareInterface;
use _ContaoManager\Symfony\Component\Console\Input\InputDefinition;
use _ContaoManager\Symfony\Component\Console\Input\InputInterface;
use _ContaoManager\Symfony\Component\Console\Input\InputOption;
use _ContaoManager\Symfony\Component\Console\Output\ConsoleOutput;
use _ContaoManager\Symfony\Component\Console\Output\ConsoleOutputInterface;
use _ContaoManager\Symfony\Component\Console\Output\OutputInterface;
use _ContaoManager\Symfony\Component\Console\SignalRegistry\SignalRegistry;
use _ContaoManager\Symfony\Component\Console\Style\SymfonyStyle;
use _ContaoManager\Symfony\Component\ErrorHandler\ErrorHandler;
use _ContaoManager\Symfony\Contracts\EventDispatcher\EventDispatcherInterface;
use _ContaoManager\Symfony\Contracts\Service\ResetInterface;
/**
 * An Application is the container for a collection of commands.
 *
 * It is the main entry point of a Console application.
 *
 * This class is optimized for a standard CLI environment.
 *
 * Usage:
 *
 *     $app = new Application('myapp', '1.0 (stable)');
 *     $app->add(new SimpleCommand());
 *     $app->run();
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class Application implements ResetInterface
{
    private array $commands = [];
    private bool $wantHelps = \false;
    private ?Command $runningCommand = null;
    private string $name;
    private string $version;
    private ?CommandLoaderInterface $commandLoader = null;
    private bool $catchExceptions = \true;
    private bool $catchErrors = \false;
    private bool $autoExit = \true;
    private InputDefinition $definition;
    private HelperSet $helperSet;
    private ?EventDispatcherInterface $dispatcher = null;
    private Terminal $terminal;
    private string $defaultCommand;
    private bool $singleCommand = \false;
    private bool $initialized = \false;
    private ?SignalRegistry $signalRegistry = null;
    private array $signalsToDispatchEvent = [];
    public function __construct(string $name = 'UNKNOWN', string $version = 'UNKNOWN')
    {
        $this->name = $name;
        $this->version = $version;
        $this->terminal = new Terminal();
        $this->defaultCommand = 'list';
        if (\defined('SIGINT') && SignalRegistry::isSupported()) {
            $this->signalRegistry = new SignalRegistry();
            $this->signalsToDispatchEvent = [\SIGINT, \SIGTERM, \SIGUSR1, \SIGUSR2];
        }
    }
    /**
     * @final
     */
    public function setDispatcher(EventDispatcherInterface $dispatcher): void
    {
        $this->dispatcher = $dispatcher;
    }
    /**
     * @return void
     */
    public function setCommandLoader(CommandLoaderInterface $commandLoader)
    {
        $this->commandLoader = $commandLoader;
    }
    public function getSignalRegistry(): SignalRegistry
    {
        if (!$this->signalRegistry) {
            throw new RuntimeException('Signals are not supported. Make sure that the "pcntl" extension is installed and that "pcntl_*" functions are not disabled by your php.ini\'s "disable_functions" directive.');
        }
        return $this->signalRegistry;
    }
    /**
     * @return void
     */
    public function setSignalsToDispatchEvent(int ...$signalsToDispatchEvent)
    {
        $this->signalsToDispatchEvent = $signalsToDispatchEvent;
    }
    /**
     * Runs the current application.
     *
     * @return int 0 if everything went fine, or an error code
     *
     * @throws \Exception When running fails. Bypass this when {@link setCatchExceptions()}.
     */
    public function run(?InputInterface $input = null, ?OutputInterface $output = null): int
    {
        if (\function_exists('putenv')) {
            @putenv('LINES=' . $this->terminal->getHeight());
            @putenv('COLUMNS=' . $this->terminal->getWidth());
        }
        $input ??= new ArgvInput();
        $output ??= new ConsoleOutput();
        $renderException = function (\Throwable $e) use ($output) {
            if ($output instanceof ConsoleOutputInterface) {
                $this->renderThrowable($e, $output->getErrorOutput());
            } else {
                $this->renderThrowable($e, $output);
            }
        };
        if ($phpHandler = set_exception_handler($renderException)) {
            restore_exception_handler();
            if (!\is_array($phpHandler) || !$phpHandler[0] instanceof ErrorHandler) {
                $errorHandler = \true;
            } elseif ($errorHandler = $phpHandler[0]->setExceptionHandler($renderException)) {
                $phpHandler[0]->setExceptionHandler($errorHandler);
            }
        }
        try {
            $this->configureIO($input, $output);
            $exitCode = $this->doRun($input, $output);
        } catch (\Throwable $e) {
            if ($e instanceof \Exception && !$this->catchExceptions) {
                throw $e;
            }
            if (!$e instanceof \Exception && !$this->catchErrors) {
                throw $e;
            }
            $renderException($e);
            $exitCode = $e->getCode();
            if (is_numeric($exitCode)) {
                $exitCode = (int) $exitCode;
                if ($exitCode <= 0) {
                    $exitCode = 1;
                }
            } else {
                $exitCode = 1;
            }
        } finally {
            // if the exception handler changed, keep it
            // otherwise, unregister $renderException
            if (!$phpHandler) {
                if (set_exception_handler($renderException) === $renderException) {
                    restore_exception_handler();
                }
                restore_exception_handler();
            } elseif (!$errorHandler) {
                $finalHandler = $phpHandler[0]->setExceptionHandler(null);
                if ($finalHandler !== $renderException) {
                    $phpHandler[0]->setExceptionHandler($finalHandler);
                }
            }
        }
        if ($this->autoExit) {
            if ($exitCode > 255) {
                $exitCode = 255;
            }
            exit($exitCode);
        }
        return $exitCode;
    }
    /**
     * Runs the current application.
     *
     * @return int 0 if everything went fine, or an error code
     */
    public function doRun(InputInterface $input, OutputInterface $output)
    {
        if (\true === $input->hasParameterOption(['--version', '-V'], \true)) {
            $output->writeln($this->getLongVersion());
            return 0;
        }
        try {
            // Makes ArgvInput::getFirstArgument() able to distinguish an option from an argument.
            $input->bind($this->getDefinition());
        } catch (ExceptionInterface) {
            // Errors must be ignored, full binding/validation happens later when the command is known.
        }
        $name = $this->getCommandName($input);
        if (\true === $input->hasParameterOption(['--help', '-h'], \true)) {
            if (!$name) {
                $name = 'help';
                $input = new ArrayInput(['command_name' => $this->defaultCommand]);
            } else {
                $this->wantHelps = \true;
            }
        }
        if (!$name) {
            $name = $this->defaultCommand;
            $definition = $this->getDefinition();
            $definition->setArguments(array_merge($definition->getArguments(), ['command' => new InputArgument('command', InputArgument::OPTIONAL, $definition->getArgument('command')->getDescription(), $name)]));
        }
        try {
            $this->runningCommand = null;
            // the command name MUST be the first element of the input
            $command = $this->find($name);
        } catch (\Throwable $e) {
            if ($e instanceof CommandNotFoundException && !$e instanceof NamespaceNotFoundException && 1 === \count($alternatives = $e->getAlternatives()) && $input->isInteractive()) {
                $alternative = $alternatives[0];
                $style = new SymfonyStyle($input, $output);
                $output->writeln('');
                $formattedBlock = (new FormatterHelper())->formatBlock(\sprintf('Command "%s" is not defined.', $name), 'error', \true);
                $output->writeln($formattedBlock);
                if (!$style->confirm(\sprintf('Do you want to run "%s" instead? ', $alternative), \false)) {
                    if (null !== $this->dispatcher) {
                        $event = new ConsoleErrorEvent($input, $output, $e);
                        $this->dispatcher->dispatch($event, ConsoleEvents::ERROR);
                        return $event->getExitCode();
                    }
                    return 1;
                }
                $command = $this->find($alternative);
            } else {
                if (null !== $this->dispatcher) {
                    $event = new ConsoleErrorEvent($input, $output, $e);
                    $this->dispatcher->dispatch($event, ConsoleEvents::ERROR);
                    if (0 === $event->getExitCode()) {
                        return 0;
                    }
                    $e = $event->getError();
                }
                try {
                    if ($e instanceof CommandNotFoundException && $namespace = $this->findNamespace($name)) {
                        $helper = new DescriptorHelper();
                        $helper->describe($output instanceof ConsoleOutputInterface ? $output->getErrorOutput() : $output, $this, ['format' => 'txt', 'raw_text' => \false, 'namespace' => $namespace, 'short' => \false]);
                        return isset($event) ? $event->getExitCode() : 1;
                    }
                    throw $e;
                } catch (NamespaceNotFoundException) {
                    throw $e;
                }
            }
        }
        if ($command instanceof LazyCommand) {
            $command = $command->getCommand();
        }
        $this->runningCommand = $command;
        $exitCode = $this->doRunCommand($command, $input, $output);
        $this->runningCommand = null;
        return $exitCode;
    }
    /**
     * @return void
     */
    public function reset()
    {
    }
    /**
     * @return void
     */
    public function setHelperSet(HelperSet $helperSet)
    {
        $this->helperSet = $helperSet;
    }
    /**
     * Get the helper set associated with the command.
     */
    public function getHelperSet(): HelperSet
    {
        return $this->helperSet ??= $this->getDefaultHelperSet();
    }
    /**
     * @return void
     */
    public function setDefinition(InputDefinition $definition)
    {
        $this->definition = $definition;
    }
    /**
     * Gets the InputDefinition related to this Application.
     */
    public function getDefinition(): InputDefinition
    {
        $this->definition ??= $this->getDefaultInputDefinition();
        if ($this->singleCommand) {
            $inputDefinition = $this->definition;
            $inputDefinition->setArguments();
            return $inputDefinition;
        }
        return $this->definition;
    }
    /**
     * Adds suggestions to $suggestions for the current completion input (e.g. option or argument).
     */
    public function complete(CompletionInput $input, CompletionSuggestions $suggestions): void
    {
        if (CompletionInput::TYPE_ARGUMENT_VALUE === $input->getCompletionType() && 'command' === $input->getCompletionName()) {
            foreach ($this->all() as $name => $command) {
                // skip hidden commands and aliased commands as they already get added below
                if ($command->isHidden() || $command->getName() !== $name) {
                    continue;
                }
                $suggestions->suggestValue(new Suggestion($command->getName(), $command->getDescription()));
                foreach ($command->getAliases() as $name) {
                    $suggestions->suggestValue(new Suggestion($name, $command->getDescription()));
                }
            }
            return;
        }
        if (CompletionInput::TYPE_OPTION_NAME === $input->getCompletionType()) {
            $suggestions->suggestOptions($this->getDefinition()->getOptions());
            return;
        }
        if (CompletionInput::TYPE_OPTION_VALUE === $input->getCompletionType() && ($definition = $this->getDefinition())->hasOption($input->getCompletionName())) {
            $definition->getOption($input->getCompletionName())->complete($input, $suggestions);
            return;
        }
    }
    /**
     * Gets the help message.
     */
    public function getHelp(): string
    {
        return $this->getLongVersion();
    }
    /**
     * Gets whether to catch exceptions or not during commands execution.
     */
    public function areExceptionsCaught(): bool
    {
        return $this->catchExceptions;
    }
    /**
     * Sets whether to catch exceptions or not during commands execution.
     *
     * @return void
     */
    public function setCatchExceptions(bool $boolean)
    {
        $this->catchExceptions = $boolean;
    }
    /**
     * Sets whether to catch errors or not during commands execution.
     */
    public function setCatchErrors(bool $catchErrors = \true): void
    {
        $this->catchErrors = $catchErrors;
    }
    /**
     * Gets whether to automatically exit after a command execution or not.
     */
    public function isAutoExitEnabled(): bool
    {
        return $this->autoExit;
    }
    /**
     * Sets whether to automatically exit after a command execution or not.
     *
     * @return void
     */
    public function setAutoExit(bool $boolean)
    {
        $this->autoExit = $boolean;
    }
    /**
     * Gets the name of the application.
     */
    public function getName(): string
    {
        return $this->name;
    }
    /**
     * Sets the application name.
     *
     * @return void
     */
    public function setName(string $name)
    {
        $this->name = $name;
    }
    /**
     * Gets the application version.
     */
    public function getVersion(): string
    {
        return $this->version;
    }
    /**
     * Sets the application version.
     *
     * @return void
     */
    public function setVersion(string $version)
    {
        $this->version = $version;
    }
    /**
     * Returns the long version of the application.
     *
     * @return string
     */
    public function getLongVersion()
    {
        if ('UNKNOWN' !== $this->getName()) {
            if ('UNKNOWN' !== $this->getVersion()) {
                return \sprintf('%s <info>%s</info>', $this->getName(), $this->getVersion());
            }
            return $this->getName();
        }
        return 'Console Tool';
    }
    /**
     * Registers a new command.
     */
    public function register(string $name): Command
    {
        return $this->add(new Command($name));
    }
    /**
     * Adds an array of command objects.
     *
     * If a Command is not enabled it will not be added.
     *
     * @param Command[] $commands An array of commands
     *
     * @return void
     */
    public function addCommands(array $commands)
    {
        foreach ($commands as $command) {
            $this->add($command);
        }
    }
    /**
     * Adds a command object.
     *
     * If a command with the same name already exists, it will be overridden.
     * If the command is not enabled it will not be added.
     *
     * @return Command|null
     */
    public function add(Command $command)
    {
        $this->init();
        $command->setApplication($this);
        if (!$command->isEnabled()) {
            $command->setApplication(null);
            return null;
        }
        if (!$command instanceof LazyCommand) {
            // Will throw if the command is not correctly initialized.
            $command->getDefinition();
        }
        if (!$command->getName()) {
            throw new LogicException(\sprintf('The command defined in "%s" cannot have an empty name.', get_debug_type($command)));
        }
        $this->commands[$command->getName()] = $command;
        foreach ($command->getAliases() as $alias) {
            $this->commands[$alias] = $command;
        }
        return $command;
    }
    /**
     * Returns a registered command by name or alias.
     *
     * @return Command
     *
     * @throws CommandNotFoundException When given command name does not exist
     */
    public function get(string $name)
    {
        $this->init();
        if (!$this->has($name)) {
            throw new CommandNotFoundException(\sprintf('The command "%s" does not exist.', $name));
        }
        // When the command has a different name than the one used at the command loader level
        if (!isset($this->commands[$name])) {
            throw new CommandNotFoundException(\sprintf('The "%s" command cannot be found because it is registered under multiple names. Make sure you don\'t set a different name via constructor or "setName()".', $name));
        }
        $command = $this->commands[$name];
        if ($this->wantHelps) {
            $this->wantHelps = \false;
            $helpCommand = $this->get('help');
            $helpCommand->setCommand($command);
            return $helpCommand;
        }
        return $command;
    }
    /**
     * Returns true if the command exists, false otherwise.
     */
    public function has(string $name): bool
    {
        $this->init();
        return isset($this->commands[$name]) || $this->commandLoader?->has($name) && $this->add($this->commandLoader->get($name));
    }
    /**
     * Returns an array of all unique namespaces used by currently registered commands.
     *
     * It does not return the global namespace which always exists.
     *
     * @return string[]
     */
    public function getNamespaces(): array
    {
        $namespaces = [];
        foreach ($this->all() as $command) {
            if ($command->isHidden()) {
                continue;
            }
            $namespaces[] = $this->extractAllNamespaces($command->getName());
            foreach ($command->getAliases() as $alias) {
                $namespaces[] = $this->extractAllNamespaces($alias);
            }
        }
        return array_values(array_unique(array_filter(array_merge([], ...$namespaces))));
    }
    /**
     * Finds a registered namespace by a name or an abbreviation.
     *
     * @throws NamespaceNotFoundException When namespace is incorrect or ambiguous
     */
    public function findNamespace(string $namespace): string
    {
        $allNamespaces = $this->getNamespaces();
        $expr = implode('[^:]*:', array_map('preg_quote', explode(':', $namespace))) . '[^:]*';
        $namespaces = preg_grep('{^' . $expr . '}', $allNamespaces);
        if (empty($namespaces)) {
            $message = \sprintf('There are no commands defined in the "%s" namespace.', $namespace);
            if ($alternatives = $this->findAlternatives($namespace, $allNamespaces)) {
                if (1 == \count($alternatives)) {
                    $message .= "\n\nDid you mean this?\n    ";
                } else {
                    $message .= "\n\nDid you mean one of these?\n    ";
                }
                $message .= implode("\n    ", $alternatives);
            }
            throw new NamespaceNotFoundException($message, $alternatives);
        }
        $exact = \in_array($namespace, $namespaces, \true);
        if (\count($namespaces) > 1 && !$exact) {
            throw new NamespaceNotFoundException(\sprintf("The namespace \"%s\" is ambiguous.\nDid you mean one of these?\n%s.", $namespace, $this->getAbbreviationSuggestions(array_values($namespaces))), array_values($namespaces));
        }
        return $exact ? $namespace : reset($namespaces);
    }
    /**
     * Finds a command by name or alias.
     *
     * Contrary to get, this command tries to find the best
     * match if you give it an abbreviation of a name or alias.
     *
     * @return Command
     *
     * @throws CommandNotFoundException When command name is incorrect or ambiguous
     */
    public function find(string $name)
    {
        $this->init();
        $aliases = [];
        foreach ($this->commands as $command) {
            foreach ($command->getAliases() as $alias) {
                if (!$this->has($alias)) {
                    $this->commands[$alias] = $command;
                }
            }
        }
        if ($this->has($name)) {
            return $this->get($name);
        }
        $allCommands = $this->commandLoader ? array_merge($this->commandLoader->getNames(), array_keys($this->commands)) : array_keys($this->commands);
        $expr = implode('[^:]*:', array_map('preg_quote', explode(':', $name))) . '[^:]*';
        $commands = preg_grep('{^' . $expr . '}', $allCommands);
        if (empty($commands)) {
            $commands = preg_grep('{^' . $expr . '}i', $allCommands);
        }
        // if no commands matched or we just matched namespaces
        if (empty($commands) || \count(preg_grep('{^' . $expr . '$}i', $commands)) < 1) {
            if (\false !== $pos = strrpos($name, ':')) {
                // check if a namespace exists and contains commands
                $this->findNamespace(substr($name, 0, $pos));
            }
            $message = \sprintf('Command "%s" is not defined.', $name);
            if ($alternatives = $this->findAlternatives($name, $allCommands)) {
                $wantHelps = $this->wantHelps;
                $this->wantHelps = \false;
                // remove hidden commands
                if ($alternatives = array_filter($alternatives, fn($name) => !$this->get($name)->isHidden())) {
                    $message .= \sprintf("\n\nDid you mean %s?\n    %s", 1 === \count($alternatives) ? 'this' : 'one of these', implode("\n    ", $alternatives));
                }
                $this->wantHelps = $wantHelps;
            }
            throw new CommandNotFoundException($message, array_values($alternatives));
        }
        // filter out aliases for commands which are already on the list
        if (\count($commands) > 1) {
            $commandList = $this->commandLoader ? array_merge(array_flip($this->commandLoader->getNames()), $this->commands) : $this->commands;
            $commands = array_unique(array_filter($commands, function ($nameOrAlias) use (&$commandList, $commands, &$aliases) {
                if (!$commandList[$nameOrAlias] instanceof Command) {
                    $commandList[$nameOrAlias] = $this->commandLoader->get($nameOrAlias);
                }
                $commandName = $commandList[$nameOrAlias]->getName();
                $aliases[$nameOrAlias] = $commandName;
                return $commandName === $nameOrAlias || !\in_array($commandName, $commands);
            }));
        }
        // check whether all commands left are aliases to the same one
        if (\count($commands) > 1) {
            $uniqueCommands = array_unique(array_map(function ($nameOrAlias) use (&$commandList) {
                if (!$commandList[$nameOrAlias] instanceof Command) {
                    $commandList[$nameOrAlias] = $this->commandLoader->get($nameOrAlias);
                }
                return $commandList[$nameOrAlias]->getName();
            }, $commands));
            if (1 === \count($uniqueCommands)) {
                $commands = [reset($uniqueCommands)];
            }
        }
        if (\count($commands) > 1) {
            $usableWidth = $this->terminal->getWidth() - 10;
            $abbrevs = array_values($commands);
            $maxLen = 0;
            foreach ($abbrevs as $abbrev) {
                $maxLen = max(Helper::width($abbrev), $maxLen);
            }
            $abbrevs = array_map(function ($cmd) use ($commandList, $usableWidth, $maxLen, &$commands) {
                if ($commandList[$cmd]->isHidden()) {
                    unset($commands[array_search($cmd, $commands)]);
                    return \false;
                }
                $abbrev = str_pad($cmd, $maxLen, ' ') . ' ' . $commandList[$cmd]->getDescription();
                return Helper::width($abbrev) > $usableWidth ? Helper::substr($abbrev, 0, $usableWidth - 3) . '...' : $abbrev;
            }, array_values($commands));
            if (\count($commands) > 1) {
                $suggestions = $this->getAbbreviationSuggestions(array_filter($abbrevs));
                throw new CommandNotFoundException(\sprintf("Command \"%s\" is ambiguous.\nDid you mean one of these?\n%s.", $name, $suggestions), array_values($commands));
            }
        }
        $command = $commands ? $this->get(reset($commands)) : null;
        if (!$command || $command->isHidden()) {
            throw new CommandNotFoundException(\sprintf('The command "%s" does not exist.', $name));
        }
        return $command;
    }
    /**
     * Gets the commands (registered in the given namespace if provided).
     *
     * The array keys are the full names and the values the command instances.
     *
     * @return Command[]
     */
    public function all(?string $namespace = null)
    {
        $this->init();
        if (null === $namespace) {
            if (!$this->commandLoader) {
                return $this->commands;
            }
            $commands = $this->commands;
            foreach ($this->commandLoader->getNames() as $name) {
                if (!isset($commands[$name]) && $this->has($name)) {
                    $commands[$name] = $this->get($name);
                }
            }
            return $commands;
        }
        $commands = [];
        foreach ($this->commands as $name => $command) {
            if ($namespace === $this->extractNamespace($name, substr_count($namespace, ':') + 1)) {
                $commands[$name] = $command;
            }
        }
        if ($this->commandLoader) {
            foreach ($this->commandLoader->getNames() as $name) {
                if (!isset($commands[$name]) && $namespace === $this->extractNamespace($name, substr_count($namespace, ':') + 1) && $this->has($name)) {
                    $commands[$name] = $this->get($name);
                }
            }
        }
        return $commands;
    }
    /**
     * Returns an array of possible abbreviations given a set of names.
     *
     * @return string[][]
     */
    public static function getAbbreviations(array $names): array
    {
        $abbrevs = [];
        foreach ($names as $name) {
            for ($len = \strlen($name); $len > 0; --$len) {
                $abbrev = substr($name, 0, $len);
                $abbrevs[$abbrev][] = $name;
            }
        }
        return $abbrevs;
    }
    public function renderThrowable(\Throwable $e, OutputInterface $output): void
    {
        $output->writeln('', OutputInterface::VERBOSITY_QUIET);
        $this->doRenderThrowable($e, $output);
        if (null !== $this->runningCommand) {
            $output->writeln(\sprintf('<info>%s</info>', OutputFormatter::escape(\sprintf($this->runningCommand->getSynopsis(), $this->getName()))), OutputInterface::VERBOSITY_QUIET);
            $output->writeln('', OutputInterface::VERBOSITY_QUIET);
        }
    }
    protected function doRenderThrowable(\Throwable $e, OutputInterface $output): void
    {
        do {
            $message = trim($e->getMessage());
            if ('' === $message || OutputInterface::VERBOSITY_VERBOSE <= $output->getVerbosity()) {
                $class = get_debug_type($e);
                $title = \sprintf('  [%s%s]  ', $class, 0 !== ($code = $e->getCode()) ? ' (' . $code . ')' : '');
                $len = Helper::width($title);
            } else {
                $len = 0;
            }
            if (str_contains($message, "@anonymous\x00")) {
                $message = preg_replace_callback('/[a-zA-Z_\x7f-\xff][\\\\a-zA-Z0-9_\x7f-\xff]*+@anonymous\x00.*?\.php(?:0x?|:[0-9]++\$)?[0-9a-fA-F]++/', fn($m) => class_exists($m[0], \false) ? ((get_parent_class($m[0]) ?: key(class_implements($m[0]))) ?: 'class') . '@anonymous' : $m[0], $message);
            }
            $width = $this->terminal->getWidth() ? $this->terminal->getWidth() - 1 : \PHP_INT_MAX;
            $lines = [];
            foreach ('' !== $message ? preg_split('/\r?\n/', $message) : [] as $line) {
                foreach ($this->splitStringByWidth($line, $width - 4) as $line) {
                    // pre-format lines to get the right string length
                    $lineLength = Helper::width($line) + 4;
                    $lines[] = [$line, $lineLength];
                    $len = max($lineLength, $len);
                }
            }
            $messages = [];
            if (!$e instanceof ExceptionInterface || OutputInterface::VERBOSITY_VERBOSE <= $output->getVerbosity()) {
                $messages[] = \sprintf('<comment>%s</comment>', OutputFormatter::escape(\sprintf('In %s line %s:', basename($e->getFile()) ?: 'n/a', $e->getLine() ?: 'n/a')));
            }
            $messages[] = $emptyLine = \sprintf('<error>%s</error>', str_repeat(' ', $len));
            if ('' === $message || OutputInterface::VERBOSITY_VERBOSE <= $output->getVerbosity()) {
                $messages[] = \sprintf('<error>%s%s</error>', $title, str_repeat(' ', max(0, $len - Helper::width($title))));
            }
            foreach ($lines as $line) {
                $messages[] = \sprintf('<error>  %s  %s</error>', OutputFormatter::escape($line[0]), str_repeat(' ', $len - $line[1]));
            }
            $messages[] = $emptyLine;
            $messages[] = '';
            $output->writeln($messages, OutputInterface::VERBOSITY_QUIET);
            if (OutputInterface::VERBOSITY_VERBOSE <= $output->getVerbosity()) {
                $output->writeln('<comment>Exception trace:</comment>', OutputInterface::VERBOSITY_QUIET);
                // exception related properties
                $trace = $e->getTrace();
                array_unshift($trace, ['function' => '', 'file' => $e->getFile() ?: 'n/a', 'line' => $e->getLine() ?: 'n/a', 'args' => []]);
                for ($i = 0, $count = \count($trace); $i < $count; ++$i) {
                    $class = $trace[$i]['class'] ?? '';
                    $type = $trace[$i]['type'] ?? '';
                    $function = $trace[$i]['function'] ?? '';
                    $file = $trace[$i]['file'] ?? 'n/a';
                    $line = $trace[$i]['line'] ?? 'n/a';
                    $output->writeln(\sprintf(' %s%s at <info>%s:%s</info>', $class, $function ? $type . $function . '()' : '', $file, $line), OutputInterface::VERBOSITY_QUIET);
                }
                $output->writeln('', OutputInterface::VERBOSITY_QUIET);
            }
        } while ($e = $e->getPrevious());
    }
    /**
     * Configures the input and output instances based on the user arguments and options.
     *
     * @return void
     */
    protected function configureIO(InputInterface $input, OutputInterface $output)
    {
        if (\true === $input->hasParameterOption(['--ansi'], \true)) {
            $output->setDecorated(\true);
        } elseif (\true === $input->hasParameterOption(['--no-ansi'], \true)) {
            $output->setDecorated(\false);
        }
        if (\true === $input->hasParameterOption(['--no-interaction', '-n'], \true)) {
            $input->setInteractive(\false);
        }
        switch ($shellVerbosity = (int) getenv('SHELL_VERBOSITY')) {
            case -1:
                $output->setVerbosity(OutputInterface::VERBOSITY_QUIET);
                break;
            case 1:
                $output->setVerbosity(OutputInterface::VERBOSITY_VERBOSE);
                break;
            case 2:
                $output->setVerbosity(OutputInterface::VERBOSITY_VERY_VERBOSE);
                break;
            case 3:
                $output->setVerbosity(OutputInterface::VERBOSITY_DEBUG);
                break;
            default:
                $shellVerbosity = 0;
                break;
        }
        if (\true === $input->hasParameterOption(['--quiet', '-q'], \true)) {
            $output->setVerbosity(OutputInterface::VERBOSITY_QUIET);
            $shellVerbosity = -1;
        } else if ($input->hasParameterOption('-vvv', \true) || $input->hasParameterOption('--verbose=3', \true) || 3 === $input->getParameterOption('--verbose', \false, \true)) {
            $output->setVerbosity(OutputInterface::VERBOSITY_DEBUG);
            $shellVerbosity = 3;
        } elseif ($input->hasParameterOption('-vv', \true) || $input->hasParameterOption('--verbose=2', \true) || 2 === $input->getParameterOption('--verbose', \false, \true)) {
            $output->setVerbosity(OutputInterface::VERBOSITY_VERY_VERBOSE);
            $shellVerbosity = 2;
        } elseif ($input->hasParameterOption('-v', \true) || $input->hasParameterOption('--verbose=1', \true) || $input->hasParameterOption('--verbose', \true) || $input->getParameterOption('--verbose', \false, \true)) {
            $output->setVerbosity(OutputInterface::VERBOSITY_VERBOSE);
            $shellVerbosity = 1;
        }
        if (-1 === $shellVerbosity) {
            $input->setInteractive(\false);
        }
        if (\function_exists('putenv')) {
            @putenv('SHELL_VERBOSITY=' . $shellVerbosity);
        }
        $_ENV['SHELL_VERBOSITY'] = $shellVerbosity;
        $_SERVER['SHELL_VERBOSITY'] = $shellVerbosity;
    }
    /**
     * Runs the current command.
     *
     * If an event dispatcher has been attached to the application,
     * events are also dispatched during the life-cycle of the command.
     *
     * @return int 0 if everything went fine, or an error code
     */
    protected function doRunCommand(Command $command, InputInterface $input, OutputInterface $output)
    {
        foreach ($command->getHelperSet() as $helper) {
            if ($helper instanceof InputAwareInterface) {
                $helper->setInput($input);
            }
        }
        $registeredSignals = \false;
        $commandSignals = $command instanceof SignalableCommandInterface ? $command->getSubscribedSignals() : [];
        if ($commandSignals || $this->dispatcher && $this->signalsToDispatchEvent) {
            if (!$this->signalRegistry) {
                throw new RuntimeException('Unable to subscribe to signal events. Make sure that the "pcntl" extension is installed and that "pcntl_*" functions are not disabled by your php.ini\'s "disable_functions" directive.');
            }
            $registeredSignals = \true;
            $this->getSignalRegistry()->pushCurrentHandlers();
            if ($this->dispatcher) {
                // We register application signals, so that we can dispatch the event
                foreach ($this->signalsToDispatchEvent as $signal) {
                    $event = new ConsoleSignalEvent($command, $input, $output, $signal);
                    $this->signalRegistry->register($signal, function ($signal) use ($event, $command, $commandSignals) {
                        $this->dispatcher->dispatch($event, ConsoleEvents::SIGNAL);
                        $exitCode = $event->getExitCode();
                        // If the command is signalable, we call the handleSignal() method
                        if (\in_array($signal, $commandSignals, \true)) {
                            $exitCode = $command->handleSignal($signal, $exitCode);
                            // BC layer for Symfony <= 5
                            if (null === $exitCode) {
                                trigger_deprecation('symfony/console', '6.3', 'Not returning an exit code from "%s::handleSignal()" is deprecated, return "false" to keep the command running or "0" to exit successfully.', get_debug_type($command));
                                $exitCode = 0;
                            }
                        }
                        if (\false !== $exitCode) {
                            $event = new ConsoleTerminateEvent($command, $event->getInput(), $event->getOutput(), $exitCode, $signal);
                            $this->dispatcher->dispatch($event, ConsoleEvents::TERMINATE);
                            exit($event->getExitCode());
                        }
                    });
                }
                // then we register command signals, but not if already handled after the dispatcher
                $commandSignals = array_diff($commandSignals, $this->signalsToDispatchEvent);
            }
            foreach ($commandSignals as $signal) {
                $this->signalRegistry->register($signal, function (int $signal) use ($command): void {
                    $exitCode = $command->handleSignal($signal);
                    // BC layer for Symfony <= 5
                    if (null === $exitCode) {
                        trigger_deprecation('symfony/console', '6.3', 'Not returning an exit code from "%s::handleSignal()" is deprecated, return "false" to keep the command running or "0" to exit successfully.', get_debug_type($command));
                        $exitCode = 0;
                    }
                    if (\false !== $exitCode) {
                        exit($exitCode);
                    }
                });
            }
        }
        if (null === $this->dispatcher) {
            try {
                return $command->run($input, $output);
            } finally {
                if ($registeredSignals) {
                    $this->getSignalRegistry()->popPreviousHandlers();
                }
            }
        }
        // bind before the console.command event, so the listeners have access to input options/arguments
        try {
            $command->mergeApplicationDefinition();
            $input->bind($command->getDefinition());
        } catch (ExceptionInterface) {
            // ignore invalid options/arguments for now, to allow the event listeners to customize the InputDefinition
        }
        $event = new ConsoleCommandEvent($command, $input, $output);
        $e = null;
        try {
            $this->dispatcher->dispatch($event, ConsoleEvents::COMMAND);
            if ($event->commandShouldRun()) {
                $exitCode = $command->run($input, $output);
            } else {
                $exitCode = ConsoleCommandEvent::RETURN_CODE_DISABLED;
            }
        } catch (\Throwable $e) {
            $event = new ConsoleErrorEvent($input, $output, $e, $command);
            $this->dispatcher->dispatch($event, ConsoleEvents::ERROR);
            $e = $event->getError();
            if (0 === $exitCode = $event->getExitCode()) {
                $e = null;
            }
        } finally {
            if ($registeredSignals) {
                $this->getSignalRegistry()->popPreviousHandlers();
            }
        }
        $event = new ConsoleTerminateEvent($command, $input, $output, $exitCode);
        $this->dispatcher->dispatch($event, ConsoleEvents::TERMINATE);
        if (null !== $e) {
            throw $e;
        }
        return $event->getExitCode();
    }
    /**
     * Gets the name of the command based on input.
     */
    protected function getCommandName(InputInterface $input): ?string
    {
        return $this->singleCommand ? $this->defaultCommand : $input->getFirstArgument();
    }
    /**
     * Gets the default input definition.
     */
    protected function getDefaultInputDefinition(): InputDefinition
    {
        return new InputDefinition([new InputArgument('command', InputArgument::REQUIRED, 'The command to execute'), new InputOption('--help', '-h', InputOption::VALUE_NONE, 'Display help for the given command. When no command is given display help for the <info>' . $this->defaultCommand . '</info> command'), new InputOption('--quiet', '-q', InputOption::VALUE_NONE, 'Do not output any message'), new InputOption('--verbose', '-v|vv|vvv', InputOption::VALUE_NONE, 'Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug'), new InputOption('--version', '-V', InputOption::VALUE_NONE, 'Display this application version'), new InputOption('--ansi', '', InputOption::VALUE_NEGATABLE, 'Force (or disable --no-ansi) ANSI output', null), new InputOption('--no-interaction', '-n', InputOption::VALUE_NONE, 'Do not ask any interactive question')]);
    }
    /**
     * Gets the default commands that should always be available.
     *
     * @return Command[]
     */
    protected function getDefaultCommands(): array
    {
        return [new HelpCommand(), new ListCommand(), new CompleteCommand(), new DumpCompletionCommand()];
    }
    /**
     * Gets the default helper set with the helpers that should always be available.
     */
    protected function getDefaultHelperSet(): HelperSet
    {
        return new HelperSet([new FormatterHelper(), new DebugFormatterHelper(), new ProcessHelper(), new QuestionHelper()]);
    }
    /**
     * Returns abbreviated suggestions in string format.
     */
    private function getAbbreviationSuggestions(array $abbrevs): string
    {
        return '    ' . implode("\n    ", $abbrevs);
    }
    /**
     * Returns the namespace part of the command name.
     *
     * This method is not part of public API and should not be used directly.
     */
    public function extractNamespace(string $name, ?int $limit = null): string
    {
        $parts = explode(':', $name, -1);
        return implode(':', null === $limit ? $parts : \array_slice($parts, 0, $limit));
    }
    /**
     * Finds alternative of $name among $collection,
     * if nothing is found in $collection, try in $abbrevs.
     *
     * @return string[]
     */
    private function findAlternatives(string $name, iterable $collection): array
    {
        $threshold = 1000.0;
        $alternatives = [];
        $collectionParts = [];
        foreach ($collection as $item) {
            $collectionParts[$item] = explode(':', $item);
        }
        foreach (explode(':', $name) as $i => $subname) {
            foreach ($collectionParts as $collectionName => $parts) {
                $exists = isset($alternatives[$collectionName]);
                if (!isset($parts[$i]) && $exists) {
                    $alternatives[$collectionName] += $threshold;
                    continue;
                } elseif (!isset($parts[$i])) {
                    continue;
                }
                $lev = levenshtein($subname, $parts[$i]);
                if ($lev <= \strlen($subname) / 3 || '' !== $subname && str_contains($parts[$i], $subname)) {
                    $alternatives[$collectionName] = $exists ? $alternatives[$collectionName] + $lev : $lev;
                } elseif ($exists) {
                    $alternatives[$collectionName] += $threshold;
                }
            }
        }
        foreach ($collection as $item) {
            $lev = levenshtein($name, $item);
            if ($lev <= \strlen($name) / 3 || str_contains($item, $name)) {
                $alternatives[$item] = isset($alternatives[$item]) ? $alternatives[$item] - $lev : $lev;
            }
        }
        $alternatives = array_filter($alternatives, fn($lev) => $lev < 2 * $threshold);
        ksort($alternatives, \SORT_NATURAL | \SORT_FLAG_CASE);
        return array_keys($alternatives);
    }
    /**
     * Sets the default Command name.
     *
     * @return $this
     */
    public function setDefaultCommand(string $commandName, bool $isSingleCommand = \false): static
    {
        $this->defaultCommand = explode('|', ltrim($commandName, '|'))[0];
        if ($isSingleCommand) {
            // Ensure the command exist
            $this->find($commandName);
            $this->singleCommand = \true;
        }
        return $this;
    }
    /**
     * @internal
     */
    public function isSingleCommand(): bool
    {
        return $this->singleCommand;
    }
    private function splitStringByWidth(string $string, int $width): array
    {
        // str_split is not suitable for multi-byte characters, we should use preg_split to get char array properly.
        // additionally, array_slice() is not enough as some character has doubled width.
        // we need a function to split string not by character count but by string width
        if (\false === $encoding = mb_detect_encoding($string, null, \true)) {
            return str_split($string, $width);
        }
        $utf8String = mb_convert_encoding($string, 'utf8', $encoding);
        $lines = [];
        $line = '';
        $offset = 0;
        while (preg_match('/.{1,10000}/u', $utf8String, $m, 0, $offset)) {
            $offset += \strlen($m[0]);
            foreach (preg_split('//u', $m[0]) as $char) {
                // test if $char could be appended to current line
                if (Helper::width($line . $char) <= $width) {
                    $line .= $char;
                    continue;
                }
                // if not, push current line to array and make new line
                $lines[] = str_pad($line, $width);
                $line = $char;
            }
        }
        $lines[] = \count($lines) ? str_pad($line, $width) : $line;
        mb_convert_variables($encoding, 'utf8', $lines);
        return $lines;
    }
    /**
     * Returns all namespaces of the command name.
     *
     * @return string[]
     */
    private function extractAllNamespaces(string $name): array
    {
        // -1 as third argument is needed to skip the command short name when exploding
        $parts = explode(':', $name, -1);
        $namespaces = [];
        foreach ($parts as $part) {
            if (\count($namespaces)) {
                $namespaces[] = end($namespaces) . ':' . $part;
            } else {
                $namespaces[] = $part;
            }
        }
        return $namespaces;
    }
    private function init(): void
    {
        if ($this->initialized) {
            return;
        }
        $this->initialized = \true;
        foreach ($this->getDefaultCommands() as $command) {
            $this->add($command);
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Console\Logger;

use _ContaoManager\Psr\Log\AbstractLogger;
use _ContaoManager\Psr\Log\InvalidArgumentException;
use _ContaoManager\Psr\Log\LogLevel;
use _ContaoManager\Symfony\Component\Console\Output\ConsoleOutputInterface;
use _ContaoManager\Symfony\Component\Console\Output\OutputInterface;
/**
 * PSR-3 compliant console logger.
 *
 * @author Kévin Dunglas <dunglas@gmail.com>
 *
 * @see https://www.php-fig.org/psr/psr-3/
 */
class ConsoleLogger extends AbstractLogger
{
    public const INFO = 'info';
    public const ERROR = 'error';
    private OutputInterface $output;
    private array $verbosityLevelMap = [LogLevel::EMERGENCY => OutputInterface::VERBOSITY_NORMAL, LogLevel::ALERT => OutputInterface::VERBOSITY_NORMAL, LogLevel::CRITICAL => OutputInterface::VERBOSITY_NORMAL, LogLevel::ERROR => OutputInterface::VERBOSITY_NORMAL, LogLevel::WARNING => OutputInterface::VERBOSITY_NORMAL, LogLevel::NOTICE => OutputInterface::VERBOSITY_VERBOSE, LogLevel::INFO => OutputInterface::VERBOSITY_VERY_VERBOSE, LogLevel::DEBUG => OutputInterface::VERBOSITY_DEBUG];
    private array $formatLevelMap = [LogLevel::EMERGENCY => self::ERROR, LogLevel::ALERT => self::ERROR, LogLevel::CRITICAL => self::ERROR, LogLevel::ERROR => self::ERROR, LogLevel::WARNING => self::INFO, LogLevel::NOTICE => self::INFO, LogLevel::INFO => self::INFO, LogLevel::DEBUG => self::INFO];
    private bool $errored = \false;
    public function __construct(OutputInterface $output, array $verbosityLevelMap = [], array $formatLevelMap = [])
    {
        $this->output = $output;
        $this->verbosityLevelMap = $verbosityLevelMap + $this->verbosityLevelMap;
        $this->formatLevelMap = $formatLevelMap + $this->formatLevelMap;
    }
    public function log($level, $message, array $context = []): void
    {
        if (!isset($this->verbosityLevelMap[$level])) {
            throw new InvalidArgumentException(\sprintf('The log level "%s" does not exist.', $level));
        }
        $output = $this->output;
        // Write to the error output if necessary and available
        if (self::ERROR === $this->formatLevelMap[$level]) {
            if ($this->output instanceof ConsoleOutputInterface) {
                $output = $output->getErrorOutput();
            }
            $this->errored = \true;
        }
        // the if condition check isn't necessary -- it's the same one that $output will do internally anyway.
        // We only do it for efficiency here as the message formatting is relatively expensive.
        if ($output->getVerbosity() >= $this->verbosityLevelMap[$level]) {
            $output->writeln(\sprintf('<%1$s>[%2$s] %3$s</%1$s>', $this->formatLevelMap[$level], $level, $this->interpolate($message, $context)), $this->verbosityLevelMap[$level]);
        }
    }
    /**
     * Returns true when any messages have been logged at error levels.
     */
    public function hasErrored(): bool
    {
        return $this->errored;
    }
    /**
     * Interpolates context values into the message placeholders.
     *
     * @author PHP Framework Interoperability Group
     */
    private function interpolate(string $message, array $context): string
    {
        if (!str_contains($message, '{')) {
            return $message;
        }
        $replacements = [];
        foreach ($context as $key => $val) {
            if (null === $val || \is_scalar($val) || $val instanceof \Stringable) {
                $replacements["{{$key}}"] = $val;
            } elseif ($val instanceof \DateTimeInterface) {
                $replacements["{{$key}}"] = $val->format(\DateTimeInterface::RFC3339);
            } elseif (\is_object($val)) {
                $replacements["{{$key}}"] = '[object ' . $val::class . ']';
            } else {
                $replacements["{{$key}}"] = '[' . \gettype($val) . ']';
            }
        }
        return strtr($message, $replacements);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Console\Attribute;

/**
 * Service tag to autoconfigure commands.
 */
#[\Attribute(\Attribute::TARGET_CLASS)]
class AsCommand
{
    public function __construct(public string $name, public ?string $description = null, array $aliases = [], bool $hidden = \false)
    {
        if (!$hidden && !$aliases) {
            return;
        }
        $name = explode('|', $name);
        $name = array_merge($name, $aliases);
        if ($hidden && '' !== $name[0]) {
            array_unshift($name, '');
        }
        $this->name = implode('|', $name);
    }
}
Copyright (c) 2004-present Fabien Potencier

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is furnished
to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
CHANGELOG
=========

6.4
---

 * Add `SignalMap` to map signal value to its name
 * Multi-line text in vertical tables is aligned properly
 * The application can also catch errors with `Application::setCatchErrors(true)`
 * Add `RunCommandMessage` and `RunCommandMessageHandler`
 * Dispatch `ConsoleTerminateEvent` after an exit on signal handling and add `ConsoleTerminateEvent::getInterruptingSignal()`

6.3
---

 * Add support for choosing exit code while handling signal, or to not exit at all
 * Add `ProgressBar::setPlaceholderFormatter` to set a placeholder attached to a instance, instead of being global.
 * Add `ReStructuredTextDescriptor`

6.2
---

 * Improve truecolor terminal detection in some cases
 * Add support for 256 color terminals (conversion from Ansi24 to Ansi8 if terminal is capable of it)
 * Deprecate calling `*Command::setApplication()`, `*FormatterStyle::setForeground/setBackground()`, `Helper::setHelpSet()`, `Input*::setDefault()`, `Question::setAutocompleterCallback/setValidator()`without any arguments
 * Change the signature of `OutputFormatterStyleInterface::setForeground/setBackground()` to `setForeground/setBackground(?string)`
 * Change the signature of `HelperInterface::setHelperSet()` to `setHelperSet(?HelperSet)`

6.1
---

 * Add support to display table vertically when calling setVertical()
 * Add method `__toString()` to `InputInterface`
 * Added `OutputWrapper` to prevent truncated URL in `SymfonyStyle::createBlock`.
 * Deprecate `Command::$defaultName` and `Command::$defaultDescription`, use the `AsCommand` attribute instead
 * Add suggested values for arguments and options in input definition, for input completion
 * Add `$resumeAt` parameter to `ProgressBar#start()`, so that one can easily 'resume' progress on longer tasks, and still get accurate `getEstimate()` and `getRemaining()` results.

6.0
---

 * `Command::setHidden()` has a default value (`true`) for `$hidden` parameter and is final
 * Remove `Helper::strlen()`, use `Helper::width()` instead
 * Remove `Helper::strlenWithoutDecoration()`, use `Helper::removeDecoration()` instead
 * `AddConsoleCommandPass` can not be configured anymore
 * Remove `HelperSet::setCommand()` and `getCommand()` without replacement

5.4
---

 * Add `TesterTrait::assertCommandIsSuccessful()` to test command
 * Deprecate `HelperSet::setCommand()` and `getCommand()` without replacement

5.3
---

 * Add `GithubActionReporter` to render annotations in a Github Action
 * Add `InputOption::VALUE_NEGATABLE` flag to handle `--foo`/`--no-foo` options
 * Add the `Command::$defaultDescription` static property and the `description` attribute
   on the `console.command` tag to allow the `list` command to instantiate commands lazily
 * Add option `--short` to the `list` command
 * Add support for bright colors
 * Add `#[AsCommand]` attribute for declaring commands on PHP 8
 * Add `Helper::width()` and `Helper::length()`
 * The `--ansi` and `--no-ansi` options now default to `null`.

5.2.0
-----

 * Added `SingleCommandApplication::setAutoExit()` to allow testing via `CommandTester`
 * added support for multiline responses to questions through `Question::setMultiline()`
   and `Question::isMultiline()`
 * Added `SignalRegistry` class to stack signals handlers
 * Added support for signals:
    * Added `Application::getSignalRegistry()` and `Application::setSignalsToDispatchEvent()` methods
    * Added `SignalableCommandInterface` interface
 * Added `TableCellStyle` class to customize table cell
 * Removed `php ` prefix invocation from help messages.

5.1.0
-----

 * `Command::setHidden()` is final since Symfony 5.1
 * Add `SingleCommandApplication`
 * Add `Cursor` class

5.0.0
-----

 * removed support for finding hidden commands using an abbreviation, use the full name instead
 * removed `TableStyle::setCrossingChar()` method in favor of `TableStyle::setDefaultCrossingChar()`
 * removed `TableStyle::setHorizontalBorderChar()` method in favor of `TableStyle::setDefaultCrossingChars()`
 * removed `TableStyle::getHorizontalBorderChar()` method in favor of `TableStyle::getBorderChars()`
 * removed `TableStyle::setVerticalBorderChar()` method in favor of `TableStyle::setVerticalBorderChars()`
 * removed `TableStyle::getVerticalBorderChar()` method in favor of `TableStyle::getBorderChars()`
 * removed support for returning `null` from `Command::execute()`, return `0` instead
 * `ProcessHelper::run()` accepts only `array|Symfony\Component\Process\Process` for its `command` argument
 * `Application::setDispatcher` accepts only `Symfony\Contracts\EventDispatcher\EventDispatcherInterface`
   for its `dispatcher` argument
 * renamed `Application::renderException()` and `Application::doRenderException()`
   to `renderThrowable()` and `doRenderThrowable()` respectively.

4.4.0
-----

 * deprecated finding hidden commands using an abbreviation, use the full name instead
 * added `Question::setTrimmable` default to true to allow the answer to be trimmed
 * added method `minSecondsBetweenRedraws()` and `maxSecondsBetweenRedraws()` on `ProgressBar`
 * `Application` implements `ResetInterface`
 * marked all dispatched event classes as `@final`
 * added support for displaying table horizontally
 * deprecated returning `null` from `Command::execute()`, return `0` instead
 * Deprecated the `Application::renderException()` and `Application::doRenderException()` methods,
   use `renderThrowable()` and `doRenderThrowable()` instead.
 * added support for the `NO_COLOR` env var (https://no-color.org/)

4.3.0
-----

 * added support for hyperlinks
 * added `ProgressBar::iterate()` method that simplify updating the progress bar when iterating
 * added `Question::setAutocompleterCallback()` to provide a callback function
   that dynamically generates suggestions as the user types

4.2.0
-----

 * allowed passing commands as `[$process, 'ENV_VAR' => 'value']` to
   `ProcessHelper::run()` to pass environment variables
 * deprecated passing a command as a string to `ProcessHelper::run()`,
   pass it the command as an array of its arguments instead
 * made the `ProcessHelper` class final
 * added `WrappableOutputFormatterInterface::formatAndWrap()` (implemented in `OutputFormatter`)
 * added `capture_stderr_separately` option to `CommandTester::execute()`

4.1.0
-----

 * added option to run suggested command if command is not found and only 1 alternative is available
 * added option to modify console output and print multiple modifiable sections
 * added support for iterable messages in output `write` and `writeln` methods

4.0.0
-----

 * `OutputFormatter` throws an exception when unknown options are used
 * removed `QuestionHelper::setInputStream()/getInputStream()`
 * removed `Application::getTerminalWidth()/getTerminalHeight()` and
   `Application::setTerminalDimensions()/getTerminalDimensions()`
 * removed `ConsoleExceptionEvent`
 * removed `ConsoleEvents::EXCEPTION`

3.4.0
-----

 * added `SHELL_VERBOSITY` env var to control verbosity
 * added `CommandLoaderInterface`, `FactoryCommandLoader` and PSR-11
   `ContainerCommandLoader` for commands lazy-loading
 * added a case-insensitive command name matching fallback
 * added static `Command::$defaultName/getDefaultName()`, allowing for
   commands to be registered at compile time in the application command loader.
   Setting the `$defaultName` property avoids the need for filling the `command`
   attribute on the `console.command` tag when using `AddConsoleCommandPass`.

3.3.0
-----

 * added `ExceptionListener`
 * added `AddConsoleCommandPass` (originally in FrameworkBundle)
 * [BC BREAK] `Input::getOption()` no longer returns the default value for options
   with value optional explicitly passed empty
 * added console.error event to catch exceptions thrown by other listeners
 * deprecated console.exception event in favor of console.error
 * added ability to handle `CommandNotFoundException` through the
   `console.error` event
 * deprecated default validation in `SymfonyQuestionHelper::ask`

3.2.0
------

 * added `setInputs()` method to CommandTester for ease testing of commands expecting inputs
 * added `setStream()` and `getStream()` methods to Input (implement StreamableInputInterface)
 * added StreamableInputInterface
 * added LockableTrait

3.1.0
-----

 * added truncate method to FormatterHelper
 * added setColumnWidth(s) method to Table

2.8.3
-----

 * remove readline support from the question helper as it caused issues

2.8.0
-----

 * use readline for user input in the question helper when available to allow
   the use of arrow keys

2.6.0
-----

 * added a Process helper
 * added a DebugFormatter helper

2.5.0
-----

 * deprecated the dialog helper (use the question helper instead)
 * deprecated TableHelper in favor of Table
 * deprecated ProgressHelper in favor of ProgressBar
 * added ConsoleLogger
 * added a question helper
 * added a way to set the process name of a command
 * added a way to set a default command instead of `ListCommand`

2.4.0
-----

 * added a way to force terminal dimensions
 * added a convenient method to detect verbosity level
 * [BC BREAK] made descriptors use output instead of returning a string

2.3.0
-----

 * added multiselect support to the select dialog helper
 * added Table Helper for tabular data rendering
 * added support for events in `Application`
 * added a way to normalize EOLs in `ApplicationTester::getDisplay()` and `CommandTester::getDisplay()`
 * added a way to set the progress bar progress via the `setCurrent` method
 * added support for multiple InputOption shortcuts, written as `'-a|-b|-c'`
 * added two additional verbosity levels, VERBOSITY_VERY_VERBOSE and VERBOSITY_DEBUG

2.2.0
-----

 * added support for colorization on Windows via ConEmu
 * add a method to Dialog Helper to ask for a question and hide the response
 * added support for interactive selections in console (DialogHelper::select())
 * added support for autocompletion as you type in Dialog Helper

2.1.0
-----

 * added ConsoleOutputInterface
 * added the possibility to disable a command (Command::isEnabled())
 * added suggestions when a command does not exist
 * added a --raw option to the list command
 * added support for STDERR in the console output class (errors are now sent
   to STDERR)
 * made the defaults (helper set, commands, input definition) in Application
   more easily customizable
 * added support for the shell even if readline is not available
 * added support for process isolation in Symfony shell via
   `--process-isolation` switch
 * added support for `--`, which disables options parsing after that point
   (tokens will be parsed as arguments)
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Console\Input;

/**
 * StreamableInputInterface is the interface implemented by all input classes
 * that have an input stream.
 *
 * @author Robin Chalas <robin.chalas@gmail.com>
 */
interface StreamableInputInterface extends InputInterface
{
    /**
     * Sets the input stream to read from when interacting with the user.
     *
     * This is mainly useful for testing purpose.
     *
     * @param resource $stream The input stream
     *
     * @return void
     */
    public function setStream($stream);
    /**
     * Returns the input stream.
     *
     * @return resource|null
     */
    public function getStream();
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Console\Input;

use _ContaoManager\Symfony\Component\Console\Exception\InvalidArgumentException;
use _ContaoManager\Symfony\Component\Console\Exception\InvalidOptionException;
/**
 * ArrayInput represents an input provided as an array.
 *
 * Usage:
 *
 *     $input = new ArrayInput(['command' => 'foo:bar', 'foo' => 'bar', '--bar' => 'foobar']);
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class ArrayInput extends Input
{
    private array $parameters;
    public function __construct(array $parameters, ?InputDefinition $definition = null)
    {
        $this->parameters = $parameters;
        parent::__construct($definition);
    }
    public function getFirstArgument(): ?string
    {
        foreach ($this->parameters as $param => $value) {
            if ($param && \is_string($param) && '-' === $param[0]) {
                continue;
            }
            return $value;
        }
        return null;
    }
    public function hasParameterOption(string|array $values, bool $onlyParams = \false): bool
    {
        $values = (array) $values;
        foreach ($this->parameters as $k => $v) {
            if (!\is_int($k)) {
                $v = $k;
            }
            if ($onlyParams && '--' === $v) {
                return \false;
            }
            if (\in_array($v, $values)) {
                return \true;
            }
        }
        return \false;
    }
    public function getParameterOption(string|array $values, string|bool|int|float|array|null $default = \false, bool $onlyParams = \false): mixed
    {
        $values = (array) $values;
        foreach ($this->parameters as $k => $v) {
            if ($onlyParams && ('--' === $k || \is_int($k) && '--' === $v)) {
                return $default;
            }
            if (\is_int($k)) {
                if (\in_array($v, $values)) {
                    return \true;
                }
            } elseif (\in_array($k, $values)) {
                return $v;
            }
        }
        return $default;
    }
    /**
     * Returns a stringified representation of the args passed to the command.
     */
    public function __toString(): string
    {
        $params = [];
        foreach ($this->parameters as $param => $val) {
            if ($param && \is_string($param) && '-' === $param[0]) {
                $glue = '-' === $param[1] ? '=' : ' ';
                if (\is_array($val)) {
                    foreach ($val as $v) {
                        $params[] = $param . ('' != $v ? $glue . $this->escapeToken($v) : '');
                    }
                } else {
                    $params[] = $param . ('' != $val ? $glue . $this->escapeToken($val) : '');
                }
            } else {
                $params[] = \is_array($val) ? implode(' ', array_map($this->escapeToken(...), $val)) : $this->escapeToken($val);
            }
        }
        return implode(' ', $params);
    }
    /**
     * @return void
     */
    protected function parse()
    {
        foreach ($this->parameters as $key => $value) {
            if ('--' === $key) {
                return;
            }
            if (str_starts_with($key, '--')) {
                $this->addLongOption(substr($key, 2), $value);
            } elseif (str_starts_with($key, '-')) {
                $this->addShortOption(substr($key, 1), $value);
            } else {
                $this->addArgument($key, $value);
            }
        }
    }
    /**
     * Adds a short option value.
     *
     * @throws InvalidOptionException When option given doesn't exist
     */
    private function addShortOption(string $shortcut, mixed $value): void
    {
        if (!$this->definition->hasShortcut($shortcut)) {
            throw new InvalidOptionException(\sprintf('The "-%s" option does not exist.', $shortcut));
        }
        $this->addLongOption($this->definition->getOptionForShortcut($shortcut)->getName(), $value);
    }
    /**
     * Adds a long option value.
     *
     * @throws InvalidOptionException When option given doesn't exist
     * @throws InvalidOptionException When a required value is missing
     */
    private function addLongOption(string $name, mixed $value): void
    {
        if (!$this->definition->hasOption($name)) {
            if (!$this->definition->hasNegation($name)) {
                throw new InvalidOptionException(\sprintf('The "--%s" option does not exist.', $name));
            }
            $optionName = $this->definition->negationToName($name);
            $this->options[$optionName] = \false;
            return;
        }
        $option = $this->definition->getOption($name);
        if (null === $value) {
            if ($option->isValueRequired()) {
                throw new InvalidOptionException(\sprintf('The "--%s" option requires a value.', $name));
            }
            if (!$option->isValueOptional()) {
                $value = \true;
            }
        }
        $this->options[$name] = $value;
    }
    /**
     * Adds an argument value.
     *
     * @throws InvalidArgumentException When argument given doesn't exist
     */
    private function addArgument(string|int $name, mixed $value): void
    {
        if (!$this->definition->hasArgument($name)) {
            throw new InvalidArgumentException(\sprintf('The "%s" argument does not exist.', $name));
        }
        $this->arguments[$name] = $value;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Console\Input;

use _ContaoManager\Symfony\Component\Console\Exception\RuntimeException;
/**
 * ArgvInput represents an input coming from the CLI arguments.
 *
 * Usage:
 *
 *     $input = new ArgvInput();
 *
 * By default, the `$_SERVER['argv']` array is used for the input values.
 *
 * This can be overridden by explicitly passing the input values in the constructor:
 *
 *     $input = new ArgvInput($_SERVER['argv']);
 *
 * If you pass it yourself, don't forget that the first element of the array
 * is the name of the running application.
 *
 * When passing an argument to the constructor, be sure that it respects
 * the same rules as the argv one. It's almost always better to use the
 * `StringInput` when you want to provide your own input.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 *
 * @see http://www.gnu.org/software/libc/manual/html_node/Argument-Syntax.html
 * @see http://www.opengroup.org/onlinepubs/009695399/basedefs/xbd_chap12.html#tag_12_02
 */
class ArgvInput extends Input
{
    private array $tokens;
    private array $parsed;
    public function __construct(?array $argv = null, ?InputDefinition $definition = null)
    {
        $argv ??= $_SERVER['argv'] ?? [];
        // strip the application name
        array_shift($argv);
        $this->tokens = $argv;
        parent::__construct($definition);
    }
    /**
     * @return void
     */
    protected function setTokens(array $tokens)
    {
        $this->tokens = $tokens;
    }
    /**
     * @return void
     */
    protected function parse()
    {
        $parseOptions = \true;
        $this->parsed = $this->tokens;
        while (null !== $token = array_shift($this->parsed)) {
            $parseOptions = $this->parseToken($token, $parseOptions);
        }
    }
    protected function parseToken(string $token, bool $parseOptions): bool
    {
        if ($parseOptions && '' == $token) {
            $this->parseArgument($token);
        } elseif ($parseOptions && '--' == $token) {
            return \false;
        } elseif ($parseOptions && str_starts_with($token, '--')) {
            $this->parseLongOption($token);
        } elseif ($parseOptions && '-' === $token[0] && '-' !== $token) {
            $this->parseShortOption($token);
        } else {
            $this->parseArgument($token);
        }
        return $parseOptions;
    }
    /**
     * Parses a short option.
     */
    private function parseShortOption(string $token): void
    {
        $name = substr($token, 1);
        if (\strlen($name) > 1) {
            if ($this->definition->hasShortcut($name[0]) && $this->definition->getOptionForShortcut($name[0])->acceptValue()) {
                // an option with a value (with no space)
                $this->addShortOption($name[0], substr($name, 1));
            } else {
                $this->parseShortOptionSet($name);
            }
        } else {
            $this->addShortOption($name, null);
        }
    }
    /**
     * Parses a short option set.
     *
     * @throws RuntimeException When option given doesn't exist
     */
    private function parseShortOptionSet(string $name): void
    {
        $len = \strlen($name);
        for ($i = 0; $i < $len; ++$i) {
            if (!$this->definition->hasShortcut($name[$i])) {
                $encoding = mb_detect_encoding($name, null, \true);
                throw new RuntimeException(\sprintf('The "-%s" option does not exist.', \false === $encoding ? $name[$i] : mb_substr($name, $i, 1, $encoding)));
            }
            $option = $this->definition->getOptionForShortcut($name[$i]);
            if ($option->acceptValue()) {
                $this->addLongOption($option->getName(), $i === $len - 1 ? null : substr($name, $i + 1));
                break;
            } else {
                $this->addLongOption($option->getName(), null);
            }
        }
    }
    /**
     * Parses a long option.
     */
    private function parseLongOption(string $token): void
    {
        $name = substr($token, 2);
        if (\false !== $pos = strpos($name, '=')) {
            if ('' === $value = substr($name, $pos + 1)) {
                array_unshift($this->parsed, $value);
            }
            $this->addLongOption(substr($name, 0, $pos), $value);
        } else {
            $this->addLongOption($name, null);
        }
    }
    /**
     * Parses an argument.
     *
     * @throws RuntimeException When too many arguments are given
     */
    private function parseArgument(string $token): void
    {
        $c = \count($this->arguments);
        // if input is expecting another argument, add it
        if ($this->definition->hasArgument($c)) {
            $arg = $this->definition->getArgument($c);
            $this->arguments[$arg->getName()] = $arg->isArray() ? [$token] : $token;
            // if last argument isArray(), append token to last argument
        } elseif ($this->definition->hasArgument($c - 1) && $this->definition->getArgument($c - 1)->isArray()) {
            $arg = $this->definition->getArgument($c - 1);
            $this->arguments[$arg->getName()][] = $token;
            // unexpected argument
        } else {
            $all = $this->definition->getArguments();
            $symfonyCommandName = null;
            if (($inputArgument = $all[$key = array_key_first($all) ?? ''] ?? null) && 'command' === $inputArgument->getName()) {
                $symfonyCommandName = $this->arguments['command'] ?? null;
                unset($all[$key]);
            }
            if (\count($all)) {
                if ($symfonyCommandName) {
                    $message = \sprintf('Too many arguments to "%s" command, expected arguments "%s".', $symfonyCommandName, implode('" "', array_keys($all)));
                } else {
                    $message = \sprintf('Too many arguments, expected arguments "%s".', implode('" "', array_keys($all)));
                }
            } elseif ($symfonyCommandName) {
                $message = \sprintf('No arguments expected for "%s" command, got "%s".', $symfonyCommandName, $token);
            } else {
                $message = \sprintf('No arguments expected, got "%s".', $token);
            }
            throw new RuntimeException($message);
        }
    }
    /**
     * Adds a short option value.
     *
     * @throws RuntimeException When option given doesn't exist
     */
    private function addShortOption(string $shortcut, mixed $value): void
    {
        if (!$this->definition->hasShortcut($shortcut)) {
            throw new RuntimeException(\sprintf('The "-%s" option does not exist.', $shortcut));
        }
        $this->addLongOption($this->definition->getOptionForShortcut($shortcut)->getName(), $value);
    }
    /**
     * Adds a long option value.
     *
     * @throws RuntimeException When option given doesn't exist
     */
    private function addLongOption(string $name, mixed $value): void
    {
        if (!$this->definition->hasOption($name)) {
            if (!$this->definition->hasNegation($name)) {
                throw new RuntimeException(\sprintf('The "--%s" option does not exist.', $name));
            }
            $optionName = $this->definition->negationToName($name);
            if (null !== $value) {
                throw new RuntimeException(\sprintf('The "--%s" option does not accept a value.', $name));
            }
            $this->options[$optionName] = \false;
            return;
        }
        $option = $this->definition->getOption($name);
        if (null !== $value && !$option->acceptValue()) {
            throw new RuntimeException(\sprintf('The "--%s" option does not accept a value.', $name));
        }
        if (\in_array($value, ['', null], \true) && $option->acceptValue() && \count($this->parsed)) {
            // if option accepts an optional or mandatory argument
            // let's see if there is one provided
            $next = array_shift($this->parsed);
            if (isset($next[0]) && '-' !== $next[0] || \in_array($next, ['', null], \true)) {
                $value = $next;
            } else {
                array_unshift($this->parsed, $next);
            }
        }
        if (null === $value) {
            if ($option->isValueRequired()) {
                throw new RuntimeException(\sprintf('The "--%s" option requires a value.', $name));
            }
            if (!$option->isArray() && !$option->isValueOptional()) {
                $value = \true;
            }
        }
        if ($option->isArray()) {
            $this->options[$name][] = $value;
        } else {
            $this->options[$name] = $value;
        }
    }
    public function getFirstArgument(): ?string
    {
        $isOption = \false;
        foreach ($this->tokens as $i => $token) {
            if ($token && '-' === $token[0]) {
                if (str_contains($token, '=') || !isset($this->tokens[$i + 1])) {
                    continue;
                }
                // If it's a long option, consider that everything after "--" is the option name.
                // Otherwise, use the last char (if it's a short option set, only the last one can take a value with space separator)
                $name = '-' === $token[1] ? substr($token, 2) : substr($token, -1);
                if (!isset($this->options[$name]) && !$this->definition->hasShortcut($name)) {
                    // noop
                } elseif ((isset($this->options[$name]) || isset($this->options[$name = $this->definition->shortcutToName($name)])) && $this->tokens[$i + 1] === $this->options[$name]) {
                    $isOption = \true;
                }
                continue;
            }
            if ($isOption) {
                $isOption = \false;
                continue;
            }
            return $token;
        }
        return null;
    }
    public function hasParameterOption(string|array $values, bool $onlyParams = \false): bool
    {
        $values = (array) $values;
        foreach ($this->tokens as $token) {
            if ($onlyParams && '--' === $token) {
                return \false;
            }
            foreach ($values as $value) {
                // Options with values:
                //   For long options, test for '--option=' at beginning
                //   For short options, test for '-o' at beginning
                $leading = str_starts_with($value, '--') ? $value . '=' : $value;
                if ($token === $value || '' !== $leading && str_starts_with($token, $leading)) {
                    return \true;
                }
            }
        }
        return \false;
    }
    public function getParameterOption(string|array $values, string|bool|int|float|array|null $default = \false, bool $onlyParams = \false): mixed
    {
        $values = (array) $values;
        $tokens = $this->tokens;
        while (0 < \count($tokens)) {
            $token = array_shift($tokens);
            if ($onlyParams && '--' === $token) {
                return $default;
            }
            foreach ($values as $value) {
                if ($token === $value) {
                    return array_shift($tokens);
                }
                // Options with values:
                //   For long options, test for '--option=' at beginning
                //   For short options, test for '-o' at beginning
                $leading = str_starts_with($value, '--') ? $value . '=' : $value;
                if ('' !== $leading && str_starts_with($token, $leading)) {
                    return substr($token, \strlen($leading));
                }
            }
        }
        return $default;
    }
    /**
     * Returns a stringified representation of the args passed to the command.
     */
    public function __toString(): string
    {
        $tokens = array_map(function ($token) {
            if (preg_match('{^(-[^=]+=)(.+)}', $token, $match)) {
                return $match[1] . $this->escapeToken($match[2]);
            }
            if ($token && '-' !== $token[0]) {
                return $this->escapeToken($token);
            }
            return $token;
        }, $this->tokens);
        return implode(' ', $tokens);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Console\Input;

use _ContaoManager\Symfony\Component\Console\Command\Command;
use _ContaoManager\Symfony\Component\Console\Completion\CompletionInput;
use _ContaoManager\Symfony\Component\Console\Completion\CompletionSuggestions;
use _ContaoManager\Symfony\Component\Console\Completion\Suggestion;
use _ContaoManager\Symfony\Component\Console\Exception\InvalidArgumentException;
use _ContaoManager\Symfony\Component\Console\Exception\LogicException;
/**
 * Represents a command line argument.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class InputArgument
{
    public const REQUIRED = 1;
    public const OPTIONAL = 2;
    public const IS_ARRAY = 4;
    private string $name;
    private int $mode;
    private string|int|bool|array|float|null $default;
    private array|\Closure $suggestedValues;
    private string $description;
    /**
     * @param string                                                                        $name            The argument name
     * @param int|null                                                                      $mode            The argument mode: a bit mask of self::REQUIRED, self::OPTIONAL and self::IS_ARRAY
     * @param string                                                                        $description     A description text
     * @param string|bool|int|float|array|null                                              $default         The default value (for self::OPTIONAL mode only)
     * @param array|\Closure(CompletionInput,CompletionSuggestions):list<string|Suggestion> $suggestedValues The values used for input completion
     *
     * @throws InvalidArgumentException When argument mode is not valid
     */
    public function __construct(string $name, ?int $mode = null, string $description = '', string|bool|int|float|array|null $default = null, \Closure|array $suggestedValues = [])
    {
        if (null === $mode) {
            $mode = self::OPTIONAL;
        } elseif ($mode > 7 || $mode < 1) {
            throw new InvalidArgumentException(\sprintf('Argument mode "%s" is not valid.', $mode));
        }
        $this->name = $name;
        $this->mode = $mode;
        $this->description = $description;
        $this->suggestedValues = $suggestedValues;
        $this->setDefault($default);
    }
    /**
     * Returns the argument name.
     */
    public function getName(): string
    {
        return $this->name;
    }
    /**
     * Returns true if the argument is required.
     *
     * @return bool true if parameter mode is self::REQUIRED, false otherwise
     */
    public function isRequired(): bool
    {
        return self::REQUIRED === (self::REQUIRED & $this->mode);
    }
    /**
     * Returns true if the argument can take multiple values.
     *
     * @return bool true if mode is self::IS_ARRAY, false otherwise
     */
    public function isArray(): bool
    {
        return self::IS_ARRAY === (self::IS_ARRAY & $this->mode);
    }
    /**
     * Sets the default value.
     *
     * @return void
     *
     * @throws LogicException When incorrect default value is given
     */
    public function setDefault(string|bool|int|float|array|null $default = null)
    {
        if (1 > \func_num_args()) {
            trigger_deprecation('symfony/console', '6.2', 'Calling "%s()" without any arguments is deprecated, pass null explicitly instead.', __METHOD__);
        }
        if ($this->isRequired() && null !== $default) {
            throw new LogicException('Cannot set a default value except for InputArgument::OPTIONAL mode.');
        }
        if ($this->isArray()) {
            if (null === $default) {
                $default = [];
            } elseif (!\is_array($default)) {
                throw new LogicException('A default value for an array argument must be an array.');
            }
        }
        $this->default = $default;
    }
    /**
     * Returns the default value.
     */
    public function getDefault(): string|bool|int|float|array|null
    {
        return $this->default;
    }
    public function hasCompletion(): bool
    {
        return [] !== $this->suggestedValues;
    }
    /**
     * Adds suggestions to $suggestions for the current completion input.
     *
     * @see Command::complete()
     */
    public function complete(CompletionInput $input, CompletionSuggestions $suggestions): void
    {
        $values = $this->suggestedValues;
        if ($values instanceof \Closure && !\is_array($values = $values($input))) {
            throw new LogicException(\sprintf('Closure for argument "%s" must return an array. Got "%s".', $this->name, get_debug_type($values)));
        }
        if ($values) {
            $suggestions->suggestValues($values);
        }
    }
    /**
     * Returns the description text.
     */
    public function getDescription(): string
    {
        return $this->description;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Console\Input;

/**
 * InputAwareInterface should be implemented by classes that depends on the
 * Console Input.
 *
 * @author Wouter J <waldio.webdesign@gmail.com>
 */
interface InputAwareInterface
{
    /**
     * Sets the Console Input.
     *
     * @return void
     */
    public function setInput(InputInterface $input);
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Console\Input;

use _ContaoManager\Symfony\Component\Console\Command\Command;
use _ContaoManager\Symfony\Component\Console\Completion\CompletionInput;
use _ContaoManager\Symfony\Component\Console\Completion\CompletionSuggestions;
use _ContaoManager\Symfony\Component\Console\Completion\Suggestion;
use _ContaoManager\Symfony\Component\Console\Exception\InvalidArgumentException;
use _ContaoManager\Symfony\Component\Console\Exception\LogicException;
/**
 * Represents a command line option.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class InputOption
{
    /**
     * Do not accept input for the option (e.g. --yell). This is the default behavior of options.
     */
    public const VALUE_NONE = 1;
    /**
     * A value must be passed when the option is used (e.g. --iterations=5 or -i5).
     */
    public const VALUE_REQUIRED = 2;
    /**
     * The option may or may not have a value (e.g. --yell or --yell=loud).
     */
    public const VALUE_OPTIONAL = 4;
    /**
     * The option accepts multiple values (e.g. --dir=/foo --dir=/bar).
     */
    public const VALUE_IS_ARRAY = 8;
    /**
     * The option may have either positive or negative value (e.g. --ansi or --no-ansi).
     */
    public const VALUE_NEGATABLE = 16;
    private string $name;
    private string|array|null $shortcut;
    private int $mode;
    private string|int|bool|array|float|null $default;
    private array|\Closure $suggestedValues;
    private string $description;
    /**
     * @param string|array|null                                                             $shortcut        The shortcuts, can be null, a string of shortcuts delimited by | or an array of shortcuts
     * @param int|null                                                                      $mode            The option mode: One of the VALUE_* constants
     * @param string|bool|int|float|array|null                                              $default         The default value (must be null for self::VALUE_NONE)
     * @param array|\Closure(CompletionInput,CompletionSuggestions):list<string|Suggestion> $suggestedValues The values used for input completion
     *
     * @throws InvalidArgumentException If option mode is invalid or incompatible
     */
    public function __construct(string $name, string|array|null $shortcut = null, ?int $mode = null, string $description = '', string|bool|int|float|array|null $default = null, array|\Closure $suggestedValues = [])
    {
        if (str_starts_with($name, '--')) {
            $name = substr($name, 2);
        }
        if (empty($name)) {
            throw new InvalidArgumentException('An option name cannot be empty.');
        }
        if ('' === $shortcut || [] === $shortcut || \false === $shortcut) {
            $shortcut = null;
        }
        if (null !== $shortcut) {
            if (\is_array($shortcut)) {
                $shortcut = implode('|', $shortcut);
            }
            $shortcuts = preg_split('{(\|)-?}', ltrim($shortcut, '-'));
            $shortcuts = array_filter($shortcuts, 'strlen');
            $shortcut = implode('|', $shortcuts);
            if ('' === $shortcut) {
                throw new InvalidArgumentException('An option shortcut cannot be empty.');
            }
        }
        if (null === $mode) {
            $mode = self::VALUE_NONE;
        } elseif ($mode >= self::VALUE_NEGATABLE << 1 || $mode < 1) {
            throw new InvalidArgumentException(\sprintf('Option mode "%s" is not valid.', $mode));
        }
        $this->name = $name;
        $this->shortcut = $shortcut;
        $this->mode = $mode;
        $this->description = $description;
        $this->suggestedValues = $suggestedValues;
        if ($suggestedValues && !$this->acceptValue()) {
            throw new LogicException('Cannot set suggested values if the option does not accept a value.');
        }
        if ($this->isArray() && !$this->acceptValue()) {
            throw new InvalidArgumentException('Impossible to have an option mode VALUE_IS_ARRAY if the option does not accept a value.');
        }
        if ($this->isNegatable() && $this->acceptValue()) {
            throw new InvalidArgumentException('Impossible to have an option mode VALUE_NEGATABLE if the option also accepts a value.');
        }
        $this->setDefault($default);
    }
    /**
     * Returns the option shortcut.
     */
    public function getShortcut(): ?string
    {
        return $this->shortcut;
    }
    /**
     * Returns the option name.
     */
    public function getName(): string
    {
        return $this->name;
    }
    /**
     * Returns true if the option accepts a value.
     *
     * @return bool true if value mode is not self::VALUE_NONE, false otherwise
     */
    public function acceptValue(): bool
    {
        return $this->isValueRequired() || $this->isValueOptional();
    }
    /**
     * Returns true if the option requires a value.
     *
     * @return bool true if value mode is self::VALUE_REQUIRED, false otherwise
     */
    public function isValueRequired(): bool
    {
        return self::VALUE_REQUIRED === (self::VALUE_REQUIRED & $this->mode);
    }
    /**
     * Returns true if the option takes an optional value.
     *
     * @return bool true if value mode is self::VALUE_OPTIONAL, false otherwise
     */
    public function isValueOptional(): bool
    {
        return self::VALUE_OPTIONAL === (self::VALUE_OPTIONAL & $this->mode);
    }
    /**
     * Returns true if the option can take multiple values.
     *
     * @return bool true if mode is self::VALUE_IS_ARRAY, false otherwise
     */
    public function isArray(): bool
    {
        return self::VALUE_IS_ARRAY === (self::VALUE_IS_ARRAY & $this->mode);
    }
    public function isNegatable(): bool
    {
        return self::VALUE_NEGATABLE === (self::VALUE_NEGATABLE & $this->mode);
    }
    /**
     * @return void
     */
    public function setDefault(string|bool|int|float|array|null $default = null)
    {
        if (1 > \func_num_args()) {
            trigger_deprecation('symfony/console', '6.2', 'Calling "%s()" without any arguments is deprecated, pass null explicitly instead.', __METHOD__);
        }
        if (self::VALUE_NONE === (self::VALUE_NONE & $this->mode) && null !== $default) {
            throw new LogicException('Cannot set a default value when using InputOption::VALUE_NONE mode.');
        }
        if ($this->isArray()) {
            if (null === $default) {
                $default = [];
            } elseif (!\is_array($default)) {
                throw new LogicException('A default value for an array option must be an array.');
            }
        }
        $this->default = $this->acceptValue() || $this->isNegatable() ? $default : \false;
    }
    /**
     * Returns the default value.
     */
    public function getDefault(): string|bool|int|float|array|null
    {
        return $this->default;
    }
    /**
     * Returns the description text.
     */
    public function getDescription(): string
    {
        return $this->description;
    }
    public function hasCompletion(): bool
    {
        return [] !== $this->suggestedValues;
    }
    /**
     * Adds suggestions to $suggestions for the current completion input.
     *
     * @see Command::complete()
     */
    public function complete(CompletionInput $input, CompletionSuggestions $suggestions): void
    {
        $values = $this->suggestedValues;
        if ($values instanceof \Closure && !\is_array($values = $values($input))) {
            throw new LogicException(\sprintf('Closure for option "%s" must return an array. Got "%s".', $this->name, get_debug_type($values)));
        }
        if ($values) {
            $suggestions->suggestValues($values);
        }
    }
    /**
     * Checks whether the given option equals this one.
     */
    public function equals(self $option): bool
    {
        return $option->getName() === $this->getName() && $option->getShortcut() === $this->getShortcut() && $option->getDefault() === $this->getDefault() && $option->isNegatable() === $this->isNegatable() && $option->isArray() === $this->isArray() && $option->isValueRequired() === $this->isValueRequired() && $option->isValueOptional() === $this->isValueOptional();
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Console\Input;

use _ContaoManager\Symfony\Component\Console\Exception\InvalidArgumentException;
use _ContaoManager\Symfony\Component\Console\Exception\LogicException;
/**
 * A InputDefinition represents a set of valid command line arguments and options.
 *
 * Usage:
 *
 *     $definition = new InputDefinition([
 *         new InputArgument('name', InputArgument::REQUIRED),
 *         new InputOption('foo', 'f', InputOption::VALUE_REQUIRED),
 *     ]);
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class InputDefinition
{
    private array $arguments = [];
    private int $requiredCount = 0;
    private ?InputArgument $lastArrayArgument = null;
    private ?InputArgument $lastOptionalArgument = null;
    private array $options = [];
    private array $negations = [];
    private array $shortcuts = [];
    /**
     * @param array $definition An array of InputArgument and InputOption instance
     */
    public function __construct(array $definition = [])
    {
        $this->setDefinition($definition);
    }
    /**
     * Sets the definition of the input.
     *
     * @return void
     */
    public function setDefinition(array $definition)
    {
        $arguments = [];
        $options = [];
        foreach ($definition as $item) {
            if ($item instanceof InputOption) {
                $options[] = $item;
            } else {
                $arguments[] = $item;
            }
        }
        $this->setArguments($arguments);
        $this->setOptions($options);
    }
    /**
     * Sets the InputArgument objects.
     *
     * @param InputArgument[] $arguments An array of InputArgument objects
     *
     * @return void
     */
    public function setArguments(array $arguments = [])
    {
        $this->arguments = [];
        $this->requiredCount = 0;
        $this->lastOptionalArgument = null;
        $this->lastArrayArgument = null;
        $this->addArguments($arguments);
    }
    /**
     * Adds an array of InputArgument objects.
     *
     * @param InputArgument[] $arguments An array of InputArgument objects
     *
     * @return void
     */
    public function addArguments(?array $arguments = [])
    {
        if (null !== $arguments) {
            foreach ($arguments as $argument) {
                $this->addArgument($argument);
            }
        }
    }
    /**
     * @return void
     *
     * @throws LogicException When incorrect argument is given
     */
    public function addArgument(InputArgument $argument)
    {
        if (isset($this->arguments[$argument->getName()])) {
            throw new LogicException(\sprintf('An argument with name "%s" already exists.', $argument->getName()));
        }
        if (null !== $this->lastArrayArgument) {
            throw new LogicException(\sprintf('Cannot add a required argument "%s" after an array argument "%s".', $argument->getName(), $this->lastArrayArgument->getName()));
        }
        if ($argument->isRequired() && null !== $this->lastOptionalArgument) {
            throw new LogicException(\sprintf('Cannot add a required argument "%s" after an optional one "%s".', $argument->getName(), $this->lastOptionalArgument->getName()));
        }
        if ($argument->isArray()) {
            $this->lastArrayArgument = $argument;
        }
        if ($argument->isRequired()) {
            ++$this->requiredCount;
        } else {
            $this->lastOptionalArgument = $argument;
        }
        $this->arguments[$argument->getName()] = $argument;
    }
    /**
     * Returns an InputArgument by name or by position.
     *
     * @throws InvalidArgumentException When argument given doesn't exist
     */
    public function getArgument(string|int $name): InputArgument
    {
        if (!$this->hasArgument($name)) {
            throw new InvalidArgumentException(\sprintf('The "%s" argument does not exist.', $name));
        }
        $arguments = \is_int($name) ? array_values($this->arguments) : $this->arguments;
        return $arguments[$name];
    }
    /**
     * Returns true if an InputArgument object exists by name or position.
     */
    public function hasArgument(string|int $name): bool
    {
        $arguments = \is_int($name) ? array_values($this->arguments) : $this->arguments;
        return isset($arguments[$name]);
    }
    /**
     * Gets the array of InputArgument objects.
     *
     * @return InputArgument[]
     */
    public function getArguments(): array
    {
        return $this->arguments;
    }
    /**
     * Returns the number of InputArguments.
     */
    public function getArgumentCount(): int
    {
        return null !== $this->lastArrayArgument ? \PHP_INT_MAX : \count($this->arguments);
    }
    /**
     * Returns the number of required InputArguments.
     */
    public function getArgumentRequiredCount(): int
    {
        return $this->requiredCount;
    }
    /**
     * @return array<string|bool|int|float|array|null>
     */
    public function getArgumentDefaults(): array
    {
        $values = [];
        foreach ($this->arguments as $argument) {
            $values[$argument->getName()] = $argument->getDefault();
        }
        return $values;
    }
    /**
     * Sets the InputOption objects.
     *
     * @param InputOption[] $options An array of InputOption objects
     *
     * @return void
     */
    public function setOptions(array $options = [])
    {
        $this->options = [];
        $this->shortcuts = [];
        $this->negations = [];
        $this->addOptions($options);
    }
    /**
     * Adds an array of InputOption objects.
     *
     * @param InputOption[] $options An array of InputOption objects
     *
     * @return void
     */
    public function addOptions(array $options = [])
    {
        foreach ($options as $option) {
            $this->addOption($option);
        }
    }
    /**
     * @return void
     *
     * @throws LogicException When option given already exist
     */
    public function addOption(InputOption $option)
    {
        if (isset($this->options[$option->getName()]) && !$option->equals($this->options[$option->getName()])) {
            throw new LogicException(\sprintf('An option named "%s" already exists.', $option->getName()));
        }
        if (isset($this->negations[$option->getName()])) {
            throw new LogicException(\sprintf('An option named "%s" already exists.', $option->getName()));
        }
        if ($option->getShortcut()) {
            foreach (explode('|', $option->getShortcut()) as $shortcut) {
                if (isset($this->shortcuts[$shortcut]) && !$option->equals($this->options[$this->shortcuts[$shortcut]])) {
                    throw new LogicException(\sprintf('An option with shortcut "%s" already exists.', $shortcut));
                }
            }
        }
        $this->options[$option->getName()] = $option;
        if ($option->getShortcut()) {
            foreach (explode('|', $option->getShortcut()) as $shortcut) {
                $this->shortcuts[$shortcut] = $option->getName();
            }
        }
        if ($option->isNegatable()) {
            $negatedName = 'no-' . $option->getName();
            if (isset($this->options[$negatedName])) {
                throw new LogicException(\sprintf('An option named "%s" already exists.', $negatedName));
            }
            $this->negations[$negatedName] = $option->getName();
        }
    }
    /**
     * Returns an InputOption by name.
     *
     * @throws InvalidArgumentException When option given doesn't exist
     */
    public function getOption(string $name): InputOption
    {
        if (!$this->hasOption($name)) {
            throw new InvalidArgumentException(\sprintf('The "--%s" option does not exist.', $name));
        }
        return $this->options[$name];
    }
    /**
     * Returns true if an InputOption object exists by name.
     *
     * This method can't be used to check if the user included the option when
     * executing the command (use getOption() instead).
     */
    public function hasOption(string $name): bool
    {
        return isset($this->options[$name]);
    }
    /**
     * Gets the array of InputOption objects.
     *
     * @return InputOption[]
     */
    public function getOptions(): array
    {
        return $this->options;
    }
    /**
     * Returns true if an InputOption object exists by shortcut.
     */
    public function hasShortcut(string $name): bool
    {
        return isset($this->shortcuts[$name]);
    }
    /**
     * Returns true if an InputOption object exists by negated name.
     */
    public function hasNegation(string $name): bool
    {
        return isset($this->negations[$name]);
    }
    /**
     * Gets an InputOption by shortcut.
     */
    public function getOptionForShortcut(string $shortcut): InputOption
    {
        return $this->getOption($this->shortcutToName($shortcut));
    }
    /**
     * @return array<string|bool|int|float|array|null>
     */
    public function getOptionDefaults(): array
    {
        $values = [];
        foreach ($this->options as $option) {
            $values[$option->getName()] = $option->getDefault();
        }
        return $values;
    }
    /**
     * Returns the InputOption name given a shortcut.
     *
     * @throws InvalidArgumentException When option given does not exist
     *
     * @internal
     */
    public function shortcutToName(string $shortcut): string
    {
        if (!isset($this->shortcuts[$shortcut])) {
            throw new InvalidArgumentException(\sprintf('The "-%s" option does not exist.', $shortcut));
        }
        return $this->shortcuts[$shortcut];
    }
    /**
     * Returns the InputOption name given a negation.
     *
     * @throws InvalidArgumentException When option given does not exist
     *
     * @internal
     */
    public function negationToName(string $negation): string
    {
        if (!isset($this->negations[$negation])) {
            throw new InvalidArgumentException(\sprintf('The "--%s" option does not exist.', $negation));
        }
        return $this->negations[$negation];
    }
    /**
     * Gets the synopsis.
     */
    public function getSynopsis(bool $short = \false): string
    {
        $elements = [];
        if ($short && $this->getOptions()) {
            $elements[] = '[options]';
        } elseif (!$short) {
            foreach ($this->getOptions() as $option) {
                $value = '';
                if ($option->acceptValue()) {
                    $value = \sprintf(' %s%s%s', $option->isValueOptional() ? '[' : '', strtoupper($option->getName()), $option->isValueOptional() ? ']' : '');
                }
                $shortcut = $option->getShortcut() ? \sprintf('-%s|', $option->getShortcut()) : '';
                $negation = $option->isNegatable() ? \sprintf('|--no-%s', $option->getName()) : '';
                $elements[] = \sprintf('[%s--%s%s%s]', $shortcut, $option->getName(), $value, $negation);
            }
        }
        if (\count($elements) && $this->getArguments()) {
            $elements[] = '[--]';
        }
        $tail = '';
        foreach ($this->getArguments() as $argument) {
            $element = '<' . $argument->getName() . '>';
            if ($argument->isArray()) {
                $element .= '...';
            }
            if (!$argument->isRequired()) {
                $element = '[' . $element;
                $tail .= ']';
            }
            $elements[] = $element;
        }
        return implode(' ', $elements) . $tail;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Console\Input;

use _ContaoManager\Symfony\Component\Console\Exception\InvalidArgumentException;
/**
 * StringInput represents an input provided as a string.
 *
 * Usage:
 *
 *     $input = new StringInput('foo --bar="foobar"');
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class StringInput extends ArgvInput
{
    /**
     * @deprecated since Symfony 6.1
     */
    public const REGEX_STRING = '([^\s]+?)(?:\s|(?<!\\\\)"|(?<!\\\\)\'|$)';
    public const REGEX_UNQUOTED_STRING = '([^\s\\\\]+?)';
    public const REGEX_QUOTED_STRING = '(?:"([^"\\\\]*(?:\\\\.[^"\\\\]*)*)"|\'([^\'\\\\]*(?:\\\\.[^\'\\\\]*)*)\')';
    /**
     * @param string $input A string representing the parameters from the CLI
     */
    public function __construct(string $input)
    {
        parent::__construct([]);
        $this->setTokens($this->tokenize($input));
    }
    /**
     * Tokenizes a string.
     *
     * @throws InvalidArgumentException When unable to parse input (should never happen)
     */
    private function tokenize(string $input): array
    {
        $tokens = [];
        $length = \strlen($input);
        $cursor = 0;
        $token = null;
        while ($cursor < $length) {
            if ('\\' === $input[$cursor]) {
                $token .= $input[++$cursor] ?? '';
                ++$cursor;
                continue;
            }
            if (preg_match('/\s+/A', $input, $match, 0, $cursor)) {
                if (null !== $token) {
                    $tokens[] = $token;
                    $token = null;
                }
            } elseif (preg_match('/([^="\'\s]+?)(=?)(' . self::REGEX_QUOTED_STRING . '+)/A', $input, $match, 0, $cursor)) {
                $token .= $match[1] . $match[2] . stripcslashes(str_replace(['"\'', '\'"', '\'\'', '""'], '', substr($match[3], 1, -1)));
            } elseif (preg_match('/' . self::REGEX_QUOTED_STRING . '/A', $input, $match, 0, $cursor)) {
                $token .= stripcslashes(substr($match[0], 1, -1));
            } elseif (preg_match('/' . self::REGEX_UNQUOTED_STRING . '/A', $input, $match, 0, $cursor)) {
                $token .= $match[1];
            } else {
                // should never happen
                throw new InvalidArgumentException(\sprintf('Unable to parse input near "... %s ...".', substr($input, $cursor, 10)));
            }
            $cursor += \strlen($match[0]);
        }
        if (null !== $token) {
            $tokens[] = $token;
        }
        return $tokens;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Console\Input;

use _ContaoManager\Symfony\Component\Console\Exception\InvalidArgumentException;
use _ContaoManager\Symfony\Component\Console\Exception\RuntimeException;
/**
 * Input is the base class for all concrete Input classes.
 *
 * Three concrete classes are provided by default:
 *
 *  * `ArgvInput`: The input comes from the CLI arguments (argv)
 *  * `StringInput`: The input is provided as a string
 *  * `ArrayInput`: The input is provided as an array
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
abstract class Input implements InputInterface, StreamableInputInterface
{
    protected $definition;
    /** @var resource */
    protected $stream;
    protected $options = [];
    protected $arguments = [];
    protected $interactive = \true;
    public function __construct(?InputDefinition $definition = null)
    {
        if (null === $definition) {
            $this->definition = new InputDefinition();
        } else {
            $this->bind($definition);
            $this->validate();
        }
    }
    /**
     * @return void
     */
    public function bind(InputDefinition $definition)
    {
        $this->arguments = [];
        $this->options = [];
        $this->definition = $definition;
        $this->parse();
    }
    /**
     * Processes command line arguments.
     *
     * @return void
     */
    abstract protected function parse();
    /**
     * @return void
     */
    public function validate()
    {
        $definition = $this->definition;
        $givenArguments = $this->arguments;
        $missingArguments = array_filter(array_keys($definition->getArguments()), fn($argument) => !\array_key_exists($argument, $givenArguments) && $definition->getArgument($argument)->isRequired());
        if (\count($missingArguments) > 0) {
            throw new RuntimeException(\sprintf('Not enough arguments (missing: "%s").', implode(', ', $missingArguments)));
        }
    }
    public function isInteractive(): bool
    {
        return $this->interactive;
    }
    /**
     * @return void
     */
    public function setInteractive(bool $interactive)
    {
        $this->interactive = $interactive;
    }
    public function getArguments(): array
    {
        return array_merge($this->definition->getArgumentDefaults(), $this->arguments);
    }
    public function getArgument(string $name): mixed
    {
        if (!$this->definition->hasArgument($name)) {
            throw new InvalidArgumentException(\sprintf('The "%s" argument does not exist.', $name));
        }
        return $this->arguments[$name] ?? $this->definition->getArgument($name)->getDefault();
    }
    /**
     * @return void
     */
    public function setArgument(string $name, mixed $value)
    {
        if (!$this->definition->hasArgument($name)) {
            throw new InvalidArgumentException(\sprintf('The "%s" argument does not exist.', $name));
        }
        $this->arguments[$name] = $value;
    }
    public function hasArgument(string $name): bool
    {
        return $this->definition->hasArgument($name);
    }
    public function getOptions(): array
    {
        return array_merge($this->definition->getOptionDefaults(), $this->options);
    }
    public function getOption(string $name): mixed
    {
        if ($this->definition->hasNegation($name)) {
            if (null === $value = $this->getOption($this->definition->negationToName($name))) {
                return $value;
            }
            return !$value;
        }
        if (!$this->definition->hasOption($name)) {
            throw new InvalidArgumentException(\sprintf('The "%s" option does not exist.', $name));
        }
        return \array_key_exists($name, $this->options) ? $this->options[$name] : $this->definition->getOption($name)->getDefault();
    }
    /**
     * @return void
     */
    public function setOption(string $name, mixed $value)
    {
        if ($this->definition->hasNegation($name)) {
            $this->options[$this->definition->negationToName($name)] = !$value;
            return;
        } elseif (!$this->definition->hasOption($name)) {
            throw new InvalidArgumentException(\sprintf('The "%s" option does not exist.', $name));
        }
        $this->options[$name] = $value;
    }
    public function hasOption(string $name): bool
    {
        return $this->definition->hasOption($name) || $this->definition->hasNegation($name);
    }
    /**
     * Escapes a token through escapeshellarg if it contains unsafe chars.
     */
    public function escapeToken(string $token): string
    {
        return preg_match('{^[\w-]+$}', $token) ? $token : escapeshellarg($token);
    }
    /**
     * @param resource $stream
     *
     * @return void
     */
    public function setStream($stream)
    {
        $this->stream = $stream;
    }
    /**
     * @return resource
     */
    public function getStream()
    {
        return $this->stream;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Console\Input;

use _ContaoManager\Symfony\Component\Console\Exception\InvalidArgumentException;
use _ContaoManager\Symfony\Component\Console\Exception\RuntimeException;
/**
 * InputInterface is the interface implemented by all input classes.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 *
 * @method string __toString() Returns a stringified representation of the args passed to the command.
 *                             InputArguments MUST be escaped as well as the InputOption values passed to the command.
 */
interface InputInterface
{
    /**
     * Returns the first argument from the raw parameters (not parsed).
     */
    public function getFirstArgument(): ?string;
    /**
     * Returns true if the raw parameters (not parsed) contain a value.
     *
     * This method is to be used to introspect the input parameters
     * before they have been validated. It must be used carefully.
     * Does not necessarily return the correct result for short options
     * when multiple flags are combined in the same option.
     *
     * @param string|array $values     The values to look for in the raw parameters (can be an array)
     * @param bool         $onlyParams Only check real parameters, skip those following an end of options (--) signal
     */
    public function hasParameterOption(string|array $values, bool $onlyParams = \false): bool;
    /**
     * Returns the value of a raw option (not parsed).
     *
     * This method is to be used to introspect the input parameters
     * before they have been validated. It must be used carefully.
     * Does not necessarily return the correct result for short options
     * when multiple flags are combined in the same option.
     *
     * @param string|array                     $values     The value(s) to look for in the raw parameters (can be an array)
     * @param string|bool|int|float|array|null $default    The default value to return if no result is found
     * @param bool                             $onlyParams Only check real parameters, skip those following an end of options (--) signal
     *
     * @return mixed
     */
    public function getParameterOption(string|array $values, string|bool|int|float|array|null $default = \false, bool $onlyParams = \false);
    /**
     * Binds the current Input instance with the given arguments and options.
     *
     * @return void
     *
     * @throws RuntimeException
     */
    public function bind(InputDefinition $definition);
    /**
     * Validates the input.
     *
     * @return void
     *
     * @throws RuntimeException When not enough arguments are given
     */
    public function validate();
    /**
     * Returns all the given arguments merged with the default values.
     *
     * @return array<string|bool|int|float|array|null>
     */
    public function getArguments(): array;
    /**
     * Returns the argument value for a given argument name.
     *
     * @return mixed
     *
     * @throws InvalidArgumentException When argument given doesn't exist
     */
    public function getArgument(string $name);
    /**
     * Sets an argument value by name.
     *
     * @return void
     *
     * @throws InvalidArgumentException When argument given doesn't exist
     */
    public function setArgument(string $name, mixed $value);
    /**
     * Returns true if an InputArgument object exists by name or position.
     */
    public function hasArgument(string $name): bool;
    /**
     * Returns all the given options merged with the default values.
     *
     * @return array<string|bool|int|float|array|null>
     */
    public function getOptions(): array;
    /**
     * Returns the option value for a given option name.
     *
     * @return mixed
     *
     * @throws InvalidArgumentException When option given doesn't exist
     */
    public function getOption(string $name);
    /**
     * Sets an option value by name.
     *
     * @return void
     *
     * @throws InvalidArgumentException When option given doesn't exist
     */
    public function setOption(string $name, mixed $value);
    /**
     * Returns true if an InputOption object exists by name.
     */
    public function hasOption(string $name): bool;
    /**
     * Is this input means interactive?
     */
    public function isInteractive(): bool;
    /**
     * Sets the input interactivity.
     *
     * @return void
     */
    public function setInteractive(bool $interactive);
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Console;

use _ContaoManager\Symfony\Component\Console\Output\AnsiColorMode;
class Terminal
{
    public const DEFAULT_COLOR_MODE = AnsiColorMode::Ansi4;
    private static ?AnsiColorMode $colorMode = null;
    private static ?int $width = null;
    private static ?int $height = null;
    private static ?bool $stty = null;
    /**
     * About Ansi color types: https://en.wikipedia.org/wiki/ANSI_escape_code#Colors
     * For more information about true color support with terminals https://github.com/termstandard/colors/.
     */
    public static function getColorMode(): AnsiColorMode
    {
        // Use Cache from previous run (or user forced mode)
        if (null !== self::$colorMode) {
            return self::$colorMode;
        }
        // Try with $COLORTERM first
        if (\is_string($colorterm = getenv('COLORTERM'))) {
            $colorterm = strtolower($colorterm);
            if (str_contains($colorterm, 'truecolor')) {
                self::setColorMode(AnsiColorMode::Ansi24);
                return self::$colorMode;
            }
            if (str_contains($colorterm, '256color')) {
                self::setColorMode(AnsiColorMode::Ansi8);
                return self::$colorMode;
            }
        }
        // Try with $TERM
        if (\is_string($term = getenv('TERM'))) {
            $term = strtolower($term);
            if (str_contains($term, 'truecolor')) {
                self::setColorMode(AnsiColorMode::Ansi24);
                return self::$colorMode;
            }
            if (str_contains($term, '256color')) {
                self::setColorMode(AnsiColorMode::Ansi8);
                return self::$colorMode;
            }
        }
        self::setColorMode(self::DEFAULT_COLOR_MODE);
        return self::$colorMode;
    }
    /**
     * Force a terminal color mode rendering.
     */
    public static function setColorMode(?AnsiColorMode $colorMode): void
    {
        self::$colorMode = $colorMode;
    }
    /**
     * Gets the terminal width.
     */
    public function getWidth(): int
    {
        $width = getenv('COLUMNS');
        if (\false !== $width) {
            return (int) trim($width);
        }
        if (null === self::$width) {
            self::initDimensions();
        }
        return self::$width ?: 80;
    }
    /**
     * Gets the terminal height.
     */
    public function getHeight(): int
    {
        $height = getenv('LINES');
        if (\false !== $height) {
            return (int) trim($height);
        }
        if (null === self::$height) {
            self::initDimensions();
        }
        return self::$height ?: 50;
    }
    /**
     * @internal
     */
    public static function hasSttyAvailable(): bool
    {
        if (null !== self::$stty) {
            return self::$stty;
        }
        // skip check if shell_exec function is disabled
        if (!\function_exists('shell_exec') && !\function_exists('_ContaoManager\shell_exec')) {
            return \false;
        }
        return self::$stty = (bool) @shell_exec('stty 2> ' . ('\\' === \DIRECTORY_SEPARATOR ? 'NUL' : '/dev/null'));
    }
    private static function initDimensions(): void
    {
        if ('\\' === \DIRECTORY_SEPARATOR) {
            $ansicon = getenv('ANSICON');
            if (\false !== $ansicon && preg_match('/^(\d+)x(\d+)(?: \((\d+)x(\d+)\))?$/', trim($ansicon), $matches)) {
                // extract [w, H] from "wxh (WxH)"
                // or [w, h] from "wxh"
                self::$width = (int) $matches[1];
                self::$height = isset($matches[4]) ? (int) $matches[4] : (int) $matches[2];
            } elseif (!self::hasVt100Support() && self::hasSttyAvailable()) {
                // only use stty on Windows if the terminal does not support vt100 (e.g. Windows 7 + git-bash)
                // testing for stty in a Windows 10 vt100-enabled console will implicitly disable vt100 support on STDOUT
                self::initDimensionsUsingStty();
            } elseif (null !== $dimensions = self::getConsoleMode()) {
                // extract [w, h] from "wxh"
                self::$width = (int) $dimensions[0];
                self::$height = (int) $dimensions[1];
            }
        } else {
            self::initDimensionsUsingStty();
        }
    }
    /**
     * Returns whether STDOUT has vt100 support (some Windows 10+ configurations).
     */
    private static function hasVt100Support(): bool
    {
        return \function_exists('sapi_windows_vt100_support') && sapi_windows_vt100_support(fopen('php://stdout', 'w'));
    }
    /**
     * Initializes dimensions using the output of an stty columns line.
     */
    private static function initDimensionsUsingStty(): void
    {
        if ($sttyString = self::getSttyColumns()) {
            if (preg_match('/rows.(\d+);.columns.(\d+);/is', $sttyString, $matches)) {
                // extract [w, h] from "rows h; columns w;"
                self::$width = (int) $matches[2];
                self::$height = (int) $matches[1];
            } elseif (preg_match('/;.(\d+).rows;.(\d+).columns/is', $sttyString, $matches)) {
                // extract [w, h] from "; h rows; w columns"
                self::$width = (int) $matches[2];
                self::$height = (int) $matches[1];
            }
        }
    }
    /**
     * Runs and parses mode CON if it's available, suppressing any error output.
     *
     * @return int[]|null An array composed of the width and the height or null if it could not be parsed
     */
    private static function getConsoleMode(): ?array
    {
        $info = self::readFromProcess('mode CON');
        if (null === $info || !preg_match('/--------+\r?\n.+?(\d+)\r?\n.+?(\d+)\r?\n/', $info, $matches)) {
            return null;
        }
        return [(int) $matches[2], (int) $matches[1]];
    }
    /**
     * Runs and parses stty -a if it's available, suppressing any error output.
     */
    private static function getSttyColumns(): ?string
    {
        return self::readFromProcess(['stty', '-a']);
    }
    private static function readFromProcess(string|array $command): ?string
    {
        if (!\function_exists('proc_open') && !\function_exists('_ContaoManager\proc_open')) {
            return null;
        }
        $descriptorspec = [1 => ['pipe', 'w'], 2 => ['pipe', 'w']];
        $cp = \function_exists('sapi_windows_cp_set') ? sapi_windows_cp_get() : 0;
        if (!$process = @proc_open($command, $descriptorspec, $pipes, null, null, ['suppress_errors' => \true])) {
            return null;
        }
        $info = stream_get_contents($pipes[1]);
        fclose($pipes[1]);
        fclose($pipes[2]);
        proc_close($process);
        if ($cp) {
            sapi_windows_cp_set($cp);
        }
        return $info;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Console\CI;

use _ContaoManager\Symfony\Component\Console\Output\OutputInterface;
/**
 * Utility class for Github actions.
 *
 * @author Maxime Steinhausser <maxime.steinhausser@gmail.com>
 */
class GithubActionReporter
{
    private OutputInterface $output;
    /**
     * @see https://github.com/actions/toolkit/blob/5e5e1b7aacba68a53836a34db4a288c3c1c1585b/packages/core/src/command.ts#L80-L85
     */
    private const ESCAPED_DATA = ['%' => '%25', "\r" => '%0D', "\n" => '%0A'];
    /**
     * @see https://github.com/actions/toolkit/blob/5e5e1b7aacba68a53836a34db4a288c3c1c1585b/packages/core/src/command.ts#L87-L94
     */
    private const ESCAPED_PROPERTIES = ['%' => '%25', "\r" => '%0D', "\n" => '%0A', ':' => '%3A', ',' => '%2C'];
    public function __construct(OutputInterface $output)
    {
        $this->output = $output;
    }
    public static function isGithubActionEnvironment(): bool
    {
        return \false !== getenv('GITHUB_ACTIONS');
    }
    /**
     * Output an error using the Github annotations format.
     *
     * @see https://docs.github.com/en/free-pro-team@latest/actions/reference/workflow-commands-for-github-actions#setting-an-error-message
     */
    public function error(string $message, ?string $file = null, ?int $line = null, ?int $col = null): void
    {
        $this->log('error', $message, $file, $line, $col);
    }
    /**
     * Output a warning using the Github annotations format.
     *
     * @see https://docs.github.com/en/free-pro-team@latest/actions/reference/workflow-commands-for-github-actions#setting-a-warning-message
     */
    public function warning(string $message, ?string $file = null, ?int $line = null, ?int $col = null): void
    {
        $this->log('warning', $message, $file, $line, $col);
    }
    /**
     * Output a debug log using the Github annotations format.
     *
     * @see https://docs.github.com/en/free-pro-team@latest/actions/reference/workflow-commands-for-github-actions#setting-a-debug-message
     */
    public function debug(string $message, ?string $file = null, ?int $line = null, ?int $col = null): void
    {
        $this->log('debug', $message, $file, $line, $col);
    }
    private function log(string $type, string $message, ?string $file = null, ?int $line = null, ?int $col = null): void
    {
        // Some values must be encoded.
        $message = strtr($message, self::ESCAPED_DATA);
        if (!$file) {
            // No file provided, output the message solely:
            $this->output->writeln(\sprintf('::%s::%s', $type, $message));
            return;
        }
        $this->output->writeln(\sprintf('::%s file=%s,line=%s,col=%s::%s', $type, strtr($file, self::ESCAPED_PROPERTIES), strtr($line ?? 1, self::ESCAPED_PROPERTIES), strtr($col ?? 0, self::ESCAPED_PROPERTIES), $message));
    }
}
# This file is part of the Symfony package.
#
# (c) Fabien Potencier <fabien@symfony.com>
#
# For the full copyright and license information, please view
# https://symfony.com/doc/current/contributing/code/license.html

_sf_{{ COMMAND_NAME }}() {

    # Use the default completion for shell redirect operators.
    for w in '>' '>>' '&>' '<'; do
        if [[ $w = "${COMP_WORDS[COMP_CWORD-1]}" ]]; then
            compopt -o filenames
            COMPREPLY=($(compgen -f -- "${COMP_WORDS[COMP_CWORD]}"))
            return 0
        fi
    done

    # Use newline as only separator to allow space in completion values
    local IFS=$'\n'
    local sf_cmd="${COMP_WORDS[0]}"

    # for an alias, get the real script behind it
    sf_cmd_type=$(type -t $sf_cmd)
    if [[ $sf_cmd_type == "alias" ]]; then
        sf_cmd=$(alias $sf_cmd | sed -E "s/alias $sf_cmd='(.*)'/\1/")
    elif [[ $sf_cmd_type == "file" ]]; then
        sf_cmd=$(type -p $sf_cmd)
    fi

    if [[ $sf_cmd_type != "function" && ! -x $sf_cmd ]]; then
        return 1
    fi

    local cur prev words cword
    _get_comp_words_by_ref -n := cur prev words cword

    local completecmd=("$sf_cmd" "_complete" "--no-interaction" "-sbash" "-c$cword" "-a{{ VERSION }}")
    for w in ${words[@]}; do
        w="${w//\\\\/\\}"
        # remove quotes from typed values
        quote="${w:0:1}"
        if [ "$quote" == \' ]; then
            w="${w%\'}"
            w="${w#\'}"
        elif [ "$quote" == \" ]; then
            w="${w%\"}"
            w="${w#\"}"
        fi
        # empty values are ignored
        if [ ! -z "$w" ]; then
            completecmd+=("-i$w")
        fi
    done

    local sfcomplete
    if sfcomplete=$(${completecmd[@]} 2>&1); then
        local quote suggestions
        quote=${cur:0:1}

        # Use single quotes by default if suggestions contains backslash (FQCN)
        if [ "$quote" == '' ] && [[ "$sfcomplete" =~ \\ ]]; then
            quote=\'
        fi

        if [ "$quote" == \' ]; then
            # single quotes: no additional escaping (does not accept ' in values)
            suggestions=$(for s in $sfcomplete; do printf $'%q%q%q\n' "$quote" "$s" "$quote"; done)
        elif [ "$quote" == \" ]; then
            # double quotes: double escaping for \ $ ` "
            suggestions=$(for s in $sfcomplete; do
                s=${s//\\/\\\\}
                s=${s//\$/\\\$}
                s=${s//\`/\\\`}
                s=${s//\"/\\\"}
                printf $'%q%q%q\n' "$quote" "$s" "$quote";
            done)
        else
            # no quotes: double escaping
            suggestions=$(for s in $sfcomplete; do printf $'%q\n' $(printf '%q' "$s"); done)
        fi
        COMPREPLY=($(IFS=$'\n' compgen -W "$suggestions" -- $(printf -- "%q" "$cur")))
        __ltrim_colon_completions "$cur"
    else
        if [[ "$sfcomplete" != *"Command \"_complete\" is not defined."* ]]; then
            >&2 echo
            >&2 echo $sfcomplete
        fi

        return 1
    fi
}

complete -F _sf_{{ COMMAND_NAME }} {{ COMMAND_NAME }}
MZ                @                                       	!L!This program cannot be run in DOS mode.
$       ,;B;B;B2מ:B2-B2ƞ9B2ў?Ba98B;CB2Ȟ:B2֞:B2Ӟ:BRich;B        PE  L MoO         	  
         8           @                      `     ?   @                           "  P    @                      P  p   !                             8!  @                                          .text   	      
                    `.rdata  	       
                 @  @.data      0                    @  .rsrc       @                    @  @.reloc     P      "              @  B                                                                                                                                                                                                                                                                                                                                                        j$@ x  j @ e EPV  @ EЃPV @ MX @ e EP5H @ L @ YY5\ @ EP5` @ D @ YYP @ MMT @ 3H  ; 0@ u  h@   l3@ $40@ 5h3@ 40@ h$0@ h(0@ h 0@  @ 00@ }j  Yjh"@   3ۉ]d   p]俀3@ SVW0 @ ;t;u3Fuh  4 @ 3F|3@ ;u
j\  Y;|3@ u,5|3@ h @ h @   YYtE      5<0@ |3@ ;uh @ h @ l  YY|3@    9]uSW8 @ 93@ th3@   Yt
SjS3@ $0@  @ 5$0@ 5(0@ 5 0@ 80@ 9,0@ u7P @ E	MPQ  YYËeE80@ 39,0@ uPh @ 9<0@ u @ E80@   øMZ  f9  @ t3M< @   @ 8PE  uH  t  uՃ   v39   xtv39   j,0@ p @ jl @ YY3@ 3@  @ t3@  @ p3@  @  x3@ V    =0@  uh@  @ Yg  =0@ u	j @ Y3{  U(  H1@ D1@ @1@ <1@ 581@ =41@ f`1@ fT1@ f01@ f,1@ f%(1@ f-$1@ X1@ E L1@ EP1@ E\1@ 0@   P1@ L0@ @0@ 	 D0@     0@ 0@  @ 0@ j?  Yj   @ h!@ $ @ =0@  uj  Yh	 ( @ P, @ ËUE 8csmu*xu$@= t=!t="t= @u  3] hH@   @ 3% @ jh("@ b  53@ 5 @ YEuu @ Ygj  Ye 53@ ։E53@ YYEEPEPu5l @ YPU  Eu֣3@ uփ3@ E	   E  j  YËUuNYH]ËV!@ !@ W;stЃ;r_^ËV"@ "@ W;stЃ;r_^% @ ̋UMMZ  f9t3]ËA<8PE  u3ҹ  f9H]̋UEH<ASVq3WDv}H;r	X;r
B(;r3_^[]̋UjhH"@ he@ d    PSVW 0@ 1E3PEd    eE    h  @ *tUE-  @ Ph  @ Pt;@$ЃEMd    Y_^[]ËE3=  ËeE3Md    Y_^[]% @ % @ he@ d5    D$l$l$+SVW 0@ 1E3PeuEEEEd    ËMd    Y__^[]QËUuuuuh@ h 0@    ]ËVh   h   3V   tVVVVV   ^3ËU 0@ e e SWN@  ;tt	У0@ `VEP< @ u3u @ 3 @ 3 @ 3EP @ E3E3;uO@u5 0@ ։50@ ^_[%t @ %x @ %| @ % @ % @ % @ % @ % @ % @ Pd5    D$+d$SVW( 0@ 3PEuEEd    ËMd    Y__^[]QËM3M%T @ T$BJ3J3l"@ s                                                                                                                                                                                                                                                     #  #  #  )  r)  b)  H)  4)  )  (  (  (  (  (  (  )      #  $  %  %  &  d&  &  $      ('  '  '  '  '  (  ((  6(  '  H(  Z(  t(  (  '  '   '  '  '  l'  ^'  R'  F'  >'  >(  0'  '  )          @         W@ @                     MoO       l   !    @0@ 0@ bad allocation      H                                                            0@ !@    RSDSьJ!LZ    c:\users\seld\documents\visual studio 2010\Projects\hiddeninp\Release\hiddeninp.pdb     e                            @ @                 :@             @ @ @ "   d"@                        "          #      $#          &  D   H#          (  h                       #  #  #  )  r)  b)  H)  4)  )  (  (  (  (  (  (  )      #  $  %  %  &  d&  &  $      ('  '  '  '  '  (  ((  6(  '  H(  Z(  t(  (  '  '   '  '  '  l'  ^'  R'  F'  >'  >(  0'  '  )      GetConsoleMode  SetConsoleMode  ;GetStdHandle  KERNEL32.dll   ??$?6DU?$char_traits@D@std@@V?$allocator@D@1@@std@@YAAAV?$basic_ostream@DU?$char_traits@D@std@@@0@AAV10@ABV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@0@@Z ?cout@std@@3V?$basic_ostream@DU?$char_traits@D@std@@@1@A  J?cin@std@@3V?$basic_istream@DU?$char_traits@D@std@@@1@A  ??$getline@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@YAAAV?$basic_istream@DU?$char_traits@D@std@@@0@AAV10@AAV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@0@@Z ??6?$basic_ostream@DU?$char_traits@D@std@@@std@@QAEAAV01@P6AAAV01@AAV01@@Z@Z  _??1?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@QAE@XZ  {??0?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@QAE@XZ  ?endl@std@@YAAAV?$basic_ostream@DU?$char_traits@D@std@@@1@AAV21@@Z  MSVCP90.dll _amsg_exit   __getmainargs ,_cexit  |_exit f _XcptFilter exit   __initenv _initterm _initterm_e <_configthreadlocale  __setusermatherr  _adjust_fdiv   __p__commode   __p__fmode  j_encode_pointer  __set_app_type  K_crt_debugger_hook  C ?terminate@@YAXXZ MSVCR90.dll _unlock  __dllonexit v_lock _onexit `_decode_pointer s_except_handler4_common _invoke_watson  ?_controlfp_s  InterlockedExchange !Sleep InterlockedCompareExchange  -TerminateProcess  GetCurrentProcess >UnhandledExceptionFilter  SetUnhandledExceptionFilter IsDebuggerPresent TQueryPerformanceCounter fGetTickCount  GetCurrentThreadId  GetCurrentProcessId OGetSystemTimeAsFileTime s __CxxFrameHandler3                                                    N@D   $!@                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            8                   P                   h                	                   	     @  (        C  V        (4   V S _ V E R S I O N _ I N F O                                                  S t r i n g F i l e I n f o   b   0 4 0 9 0 4 b 0    Q  F i l e D e s c r i p t i o n     R e a d s   f r o m   s t d i n   w i t h o u t   l e a k i n g   i n f o   t o   t h e   t e r m i n a l   a n d   o u t p u t s   b a c k   t o   s t d o u t     6   F i l e V e r s i o n     1 ,   0 ,   0 ,   0     8   I n t e r n a l N a m e   h i d d e n i n p u t   P   L e g a l C o p y r i g h t   J o r d i   B o g g i a n o   -   2 0 1 2   H   O r i g i n a l F i l e n a m e   h i d d e n i n p u t . e x e   :   P r o d u c t N a m e     H i d d e n   I n p u t     :   P r o d u c t V e r s i o n   1 ,   0 ,   0 ,   0     D    V a r F i l e I n f o     $    T r a n s l a t i o n     	<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
  <trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">
    <security>
      <requestedPrivileges>
        <requestedExecutionLevel level="asInvoker" uiAccess="false"></requestedExecutionLevel>
      </requestedPrivileges>
    </security>
  </trustInfo>
  <dependency>
    <dependentAssembly>
      <assemblyIdentity type="win32" name="Microsoft.VC90.CRT" version="9.0.21022.8" processorArchitecture="x86" publicKeyToken="1fc8b3b9a1e18e3b"></assemblyIdentity>
    </dependentAssembly>
  </dependency>
</assembly>PAPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDING   @  00!0/080F0L0T0^0d0n0{000000000000001#1-1@1J1O1T1v1{1111111111111112"2*23292A2M2_2j2p222222222222333%303N3T3Z3`3f3l3s3z333333333333333334444%4;4B444444444445!5^5c5555H6M6_6}666 777*7w7|77777888=8E8P8V8\8b8h8n8t8z88889      $   0001 1t1x12 2@2\2`2h2t2 0     0                                                                                                                                                  #compdef {{ COMMAND_NAME }}

# This file is part of the Symfony package.
#
# (c) Fabien Potencier <fabien@symfony.com>
#
# For the full copyright and license information, please view
# https://symfony.com/doc/current/contributing/code/license.html

#
# zsh completions for {{ COMMAND_NAME }}
#
# References:
#   - https://github.com/spf13/cobra/blob/master/zsh_completions.go
#   - https://github.com/symfony/symfony/blob/5.4/src/Symfony/Component/Console/Resources/completion.bash
#
_sf_{{ COMMAND_NAME }}() {
    local lastParam flagPrefix requestComp out comp
    local -a completions

    # The user could have moved the cursor backwards on the command-line.
    # We need to trigger completion from the $CURRENT location, so we need
    # to truncate the command-line ($words) up to the $CURRENT location.
    # (We cannot use $CURSOR as its value does not work when a command is an alias.)
    words=("${=words[1,CURRENT]}") lastParam=${words[-1]}

    # For zsh, when completing a flag with an = (e.g., {{ COMMAND_NAME }} -n=<TAB>)
    # completions must be prefixed with the flag
    setopt local_options BASH_REMATCH
    if [[ "${lastParam}" =~ '-.*=' ]]; then
        # We are dealing with a flag with an =
        flagPrefix="-P ${BASH_REMATCH}"
    fi

    # Prepare the command to obtain completions
    requestComp="${words[0]} ${words[1]} _complete --no-interaction -szsh -a{{ VERSION }} -c$((CURRENT-1))" i=""
    for w in ${words[@]}; do
        w=$(printf -- '%b' "$w")
        # remove quotes from typed values
        quote="${w:0:1}"
        if [ "$quote" = \' ]; then
            w="${w%\'}"
            w="${w#\'}"
        elif [ "$quote" = \" ]; then
            w="${w%\"}"
            w="${w#\"}"
        fi
        # empty values are ignored
        if [ ! -z "$w" ]; then
            i="${i}-i${w} "
        fi
    done

    # Ensure at least 1 input
    if [ "${i}" = "" ]; then
        requestComp="${requestComp} -i\" \""
    else
        requestComp="${requestComp} ${i}"
    fi

    # Use eval to handle any environment variables and such
    out=$(eval ${requestComp} 2>/dev/null)

    while IFS='\n' read -r comp; do
        if [ -n "$comp" ]; then
            # If requested, completions are returned with a description.
            # The description is preceded by a TAB character.
            # For zsh's _describe, we need to use a : instead of a TAB.
            # We first need to escape any : as part of the completion itself.
            comp=${comp//:/\\:}
            local tab=$(printf '\t')
            comp=${comp//$tab/:}
            completions+=${comp}
        fi
    done < <(printf "%s\n" "${out[@]}")

    # Let inbuilt _describe handle completions
    eval _describe "completions" completions $flagPrefix
    return $?
}

compdef _sf_{{ COMMAND_NAME }} {{ COMMAND_NAME }}
# This file is part of the Symfony package.
#
# (c) Fabien Potencier <fabien@symfony.com>
#
# For the full copyright and license information, please view
# https://symfony.com/doc/current/contributing/code/license.html

function _sf_{{ COMMAND_NAME }}
    set sf_cmd (commandline -o)
    set c (count (commandline -oc))

    set completecmd "$sf_cmd[1]" "_complete" "--no-interaction" "-sfish" "-a{{ VERSION }}"

    for i in $sf_cmd
        if [ $i != "" ]
            set completecmd $completecmd "-i$i"
        end
    end

    set completecmd $completecmd "-c$c"

    set sfcomplete ($completecmd)

    for i in $sfcomplete
        echo $i
    end
end

complete -c '{{ COMMAND_NAME }}' -a '(_sf_{{ COMMAND_NAME }})' -f
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Console\Output;

use _ContaoManager\Symfony\Component\Console\Exception\InvalidArgumentException;
use _ContaoManager\Symfony\Component\Console\Formatter\OutputFormatterInterface;
/**
 * A BufferedOutput that keeps only the last N chars.
 *
 * @author Jérémy Derussé <jeremy@derusse.com>
 */
class TrimmedBufferOutput extends Output
{
    private int $maxLength;
    private string $buffer = '';
    public function __construct(int $maxLength, ?int $verbosity = self::VERBOSITY_NORMAL, bool $decorated = \false, ?OutputFormatterInterface $formatter = null)
    {
        if ($maxLength <= 0) {
            throw new InvalidArgumentException(\sprintf('"%s()" expects a strictly positive maxLength. Got %d.', __METHOD__, $maxLength));
        }
        parent::__construct($verbosity, $decorated, $formatter);
        $this->maxLength = $maxLength;
    }
    /**
     * Empties buffer and returns its content.
     */
    public function fetch(): string
    {
        $content = $this->buffer;
        $this->buffer = '';
        return $content;
    }
    /**
     * @return void
     */
    protected function doWrite(string $message, bool $newline)
    {
        $this->buffer .= $message;
        if ($newline) {
            $this->buffer .= \PHP_EOL;
        }
        $this->buffer = substr($this->buffer, 0 - $this->maxLength);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Console\Output;

/**
 * ConsoleOutputInterface is the interface implemented by ConsoleOutput class.
 * This adds information about stderr and section output stream.
 *
 * @author Dariusz Górecki <darek.krk@gmail.com>
 */
interface ConsoleOutputInterface extends OutputInterface
{
    /**
     * Gets the OutputInterface for errors.
     */
    public function getErrorOutput(): OutputInterface;
    /**
     * @return void
     */
    public function setErrorOutput(OutputInterface $error);
    public function section(): ConsoleSectionOutput;
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Console\Output;

/**
 * @author Jean-François Simon <contact@jfsimon.fr>
 */
class BufferedOutput extends Output
{
    private string $buffer = '';
    /**
     * Empties buffer and returns its content.
     */
    public function fetch(): string
    {
        $content = $this->buffer;
        $this->buffer = '';
        return $content;
    }
    /**
     * @return void
     */
    protected function doWrite(string $message, bool $newline)
    {
        $this->buffer .= $message;
        if ($newline) {
            $this->buffer .= \PHP_EOL;
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Console\Output;

use _ContaoManager\Symfony\Component\Console\Formatter\OutputFormatterInterface;
/**
 * OutputInterface is the interface implemented by all Output classes.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
interface OutputInterface
{
    public const VERBOSITY_QUIET = 16;
    public const VERBOSITY_NORMAL = 32;
    public const VERBOSITY_VERBOSE = 64;
    public const VERBOSITY_VERY_VERBOSE = 128;
    public const VERBOSITY_DEBUG = 256;
    public const OUTPUT_NORMAL = 1;
    public const OUTPUT_RAW = 2;
    public const OUTPUT_PLAIN = 4;
    /**
     * Writes a message to the output.
     *
     * @param bool $newline Whether to add a newline
     * @param int  $options A bitmask of options (one of the OUTPUT or VERBOSITY constants),
     *                      0 is considered the same as self::OUTPUT_NORMAL | self::VERBOSITY_NORMAL
     *
     * @return void
     */
    public function write(string|iterable $messages, bool $newline = \false, int $options = 0);
    /**
     * Writes a message to the output and adds a newline at the end.
     *
     * @param int $options A bitmask of options (one of the OUTPUT or VERBOSITY constants),
     *                     0 is considered the same as self::OUTPUT_NORMAL | self::VERBOSITY_NORMAL
     *
     * @return void
     */
    public function writeln(string|iterable $messages, int $options = 0);
    /**
     * Sets the verbosity of the output.
     *
     * @param self::VERBOSITY_* $level
     *
     * @return void
     */
    public function setVerbosity(int $level);
    /**
     * Gets the current verbosity of the output.
     *
     * @return self::VERBOSITY_*
     */
    public function getVerbosity(): int;
    /**
     * Returns whether verbosity is quiet (-q).
     */
    public function isQuiet(): bool;
    /**
     * Returns whether verbosity is verbose (-v).
     */
    public function isVerbose(): bool;
    /**
     * Returns whether verbosity is very verbose (-vv).
     */
    public function isVeryVerbose(): bool;
    /**
     * Returns whether verbosity is debug (-vvv).
     */
    public function isDebug(): bool;
    /**
     * Sets the decorated flag.
     *
     * @return void
     */
    public function setDecorated(bool $decorated);
    /**
     * Gets the decorated flag.
     */
    public function isDecorated(): bool;
    /**
     * @return void
     */
    public function setFormatter(OutputFormatterInterface $formatter);
    /**
     * Returns current output formatter instance.
     */
    public function getFormatter(): OutputFormatterInterface;
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Console\Output;

use _ContaoManager\Symfony\Component\Console\Exception\InvalidArgumentException;
/**
 * @author Fabien Potencier <fabien@symfony.com>
 * @author Julien Boudry <julien@condorcet.vote>
 */
enum AnsiColorMode
{
    /*
     * Classical 4-bit Ansi colors, including 8 classical colors and 8 bright color. Output syntax is "ESC[${foreGroundColorcode};${backGroundColorcode}m"
     * Must be compatible with all terminals and it's the minimal version supported.
     */
    case Ansi4;
    /*
     * 8-bit Ansi colors (240 different colors + 16 duplicate color codes, ensuring backward compatibility).
     * Output syntax is: "ESC[38;5;${foreGroundColorcode};48;5;${backGroundColorcode}m"
     * Should be compatible with most terminals.
     */
    case Ansi8;
    /*
     * 24-bit Ansi colors (RGB).
     * Output syntax is: "ESC[38;2;${foreGroundColorcodeRed};${foreGroundColorcodeGreen};${foreGroundColorcodeBlue};48;2;${backGroundColorcodeRed};${backGroundColorcodeGreen};${backGroundColorcodeBlue}m"
     * May be compatible with many modern terminals.
     */
    case Ansi24;
    /**
     * Converts an RGB hexadecimal color to the corresponding Ansi code.
     */
    public function convertFromHexToAnsiColorCode(string $hexColor): string
    {
        $hexColor = str_replace('#', '', $hexColor);
        if (3 === \strlen($hexColor)) {
            $hexColor = $hexColor[0] . $hexColor[0] . $hexColor[1] . $hexColor[1] . $hexColor[2] . $hexColor[2];
        }
        if (6 !== \strlen($hexColor)) {
            throw new InvalidArgumentException(\sprintf('Invalid "#%s" color.', $hexColor));
        }
        $color = hexdec($hexColor);
        $r = $color >> 16 & 255;
        $g = $color >> 8 & 255;
        $b = $color & 255;
        return match ($this) {
            self::Ansi4 => (string) $this->convertFromRGB($r, $g, $b),
            self::Ansi8 => '8;5;' . (string) $this->convertFromRGB($r, $g, $b),
            self::Ansi24 => \sprintf('8;2;%d;%d;%d', $r, $g, $b),
        };
    }
    private function convertFromRGB(int $r, int $g, int $b): int
    {
        return match ($this) {
            self::Ansi4 => $this->degradeHexColorToAnsi4($r, $g, $b),
            self::Ansi8 => $this->degradeHexColorToAnsi8($r, $g, $b),
            default => throw new InvalidArgumentException("RGB cannot be converted to {$this->name}."),
        };
    }
    private function degradeHexColorToAnsi4(int $r, int $g, int $b): int
    {
        return round($b / 255) << 2 | round($g / 255) << 1 | round($r / 255);
    }
    /**
     * Inspired from https://github.com/ajalt/colormath/blob/e464e0da1b014976736cf97250063248fc77b8e7/colormath/src/commonMain/kotlin/com/github/ajalt/colormath/model/Ansi256.kt code (MIT license).
     */
    private function degradeHexColorToAnsi8(int $r, int $g, int $b): int
    {
        if ($r === $g && $g === $b) {
            if ($r < 8) {
                return 16;
            }
            if ($r > 248) {
                return 231;
            }
            return (int) round(($r - 8) / 247 * 24) + 232;
        } else {
            return 16 + 36 * (int) round($r / 255 * 5) + 6 * (int) round($g / 255 * 5) + (int) round($b / 255 * 5);
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Console\Output;

use _ContaoManager\Symfony\Component\Console\Formatter\OutputFormatter;
use _ContaoManager\Symfony\Component\Console\Formatter\OutputFormatterInterface;
/**
 * Base class for output classes.
 *
 * There are five levels of verbosity:
 *
 *  * normal: no option passed (normal output)
 *  * verbose: -v (more output)
 *  * very verbose: -vv (highly extended output)
 *  * debug: -vvv (all debug output)
 *  * quiet: -q (no output)
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
abstract class Output implements OutputInterface
{
    private int $verbosity;
    private OutputFormatterInterface $formatter;
    /**
     * @param int|null                      $verbosity The verbosity level (one of the VERBOSITY constants in OutputInterface)
     * @param bool                          $decorated Whether to decorate messages
     * @param OutputFormatterInterface|null $formatter Output formatter instance (null to use default OutputFormatter)
     */
    public function __construct(?int $verbosity = self::VERBOSITY_NORMAL, bool $decorated = \false, ?OutputFormatterInterface $formatter = null)
    {
        $this->verbosity = $verbosity ?? self::VERBOSITY_NORMAL;
        $this->formatter = $formatter ?? new OutputFormatter();
        $this->formatter->setDecorated($decorated);
    }
    /**
     * @return void
     */
    public function setFormatter(OutputFormatterInterface $formatter)
    {
        $this->formatter = $formatter;
    }
    public function getFormatter(): OutputFormatterInterface
    {
        return $this->formatter;
    }
    /**
     * @return void
     */
    public function setDecorated(bool $decorated)
    {
        $this->formatter->setDecorated($decorated);
    }
    public function isDecorated(): bool
    {
        return $this->formatter->isDecorated();
    }
    /**
     * @return void
     */
    public function setVerbosity(int $level)
    {
        $this->verbosity = $level;
    }
    public function getVerbosity(): int
    {
        return $this->verbosity;
    }
    public function isQuiet(): bool
    {
        return self::VERBOSITY_QUIET === $this->verbosity;
    }
    public function isVerbose(): bool
    {
        return self::VERBOSITY_VERBOSE <= $this->verbosity;
    }
    public function isVeryVerbose(): bool
    {
        return self::VERBOSITY_VERY_VERBOSE <= $this->verbosity;
    }
    public function isDebug(): bool
    {
        return self::VERBOSITY_DEBUG <= $this->verbosity;
    }
    /**
     * @return void
     */
    public function writeln(string|iterable $messages, int $options = self::OUTPUT_NORMAL)
    {
        $this->write($messages, \true, $options);
    }
    /**
     * @return void
     */
    public function write(string|iterable $messages, bool $newline = \false, int $options = self::OUTPUT_NORMAL)
    {
        if (!is_iterable($messages)) {
            $messages = [$messages];
        }
        $types = self::OUTPUT_NORMAL | self::OUTPUT_RAW | self::OUTPUT_PLAIN;
        $type = $types & $options ?: self::OUTPUT_NORMAL;
        $verbosities = self::VERBOSITY_QUIET | self::VERBOSITY_NORMAL | self::VERBOSITY_VERBOSE | self::VERBOSITY_VERY_VERBOSE | self::VERBOSITY_DEBUG;
        $verbosity = $verbosities & $options ?: self::VERBOSITY_NORMAL;
        if ($verbosity > $this->getVerbosity()) {
            return;
        }
        foreach ($messages as $message) {
            switch ($type) {
                case OutputInterface::OUTPUT_NORMAL:
                    $message = $this->formatter->format($message);
                    break;
                case OutputInterface::OUTPUT_RAW:
                    break;
                case OutputInterface::OUTPUT_PLAIN:
                    $message = strip_tags($this->formatter->format($message));
                    break;
            }
            $this->doWrite($message ?? '', $newline);
        }
    }
    /**
     * Writes a message to the output.
     *
     * @return void
     */
    abstract protected function doWrite(string $message, bool $newline);
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Console\Output;

use _ContaoManager\Symfony\Component\Console\Formatter\OutputFormatterInterface;
use _ContaoManager\Symfony\Component\Console\Helper\Helper;
use _ContaoManager\Symfony\Component\Console\Terminal;
/**
 * @author Pierre du Plessis <pdples@gmail.com>
 * @author Gabriel Ostrolucký <gabriel.ostrolucky@gmail.com>
 */
class ConsoleSectionOutput extends StreamOutput
{
    private array $content = [];
    private int $lines = 0;
    private array $sections;
    private Terminal $terminal;
    private int $maxHeight = 0;
    /**
     * @param resource               $stream
     * @param ConsoleSectionOutput[] $sections
     */
    public function __construct($stream, array &$sections, int $verbosity, bool $decorated, OutputFormatterInterface $formatter)
    {
        parent::__construct($stream, $verbosity, $decorated, $formatter);
        array_unshift($sections, $this);
        $this->sections =& $sections;
        $this->terminal = new Terminal();
    }
    /**
     * Defines a maximum number of lines for this section.
     *
     * When more lines are added, the section will automatically scroll to the
     * end (i.e. remove the first lines to comply with the max height).
     */
    public function setMaxHeight(int $maxHeight): void
    {
        // when changing max height, clear output of current section and redraw again with the new height
        $previousMaxHeight = $this->maxHeight;
        $this->maxHeight = $maxHeight;
        $existingContent = $this->popStreamContentUntilCurrentSection($previousMaxHeight ? min($previousMaxHeight, $this->lines) : $this->lines);
        parent::doWrite($this->getVisibleContent(), \false);
        parent::doWrite($existingContent, \false);
    }
    /**
     * Clears previous output for this section.
     *
     * @param int $lines Number of lines to clear. If null, then the entire output of this section is cleared
     *
     * @return void
     */
    public function clear(?int $lines = null)
    {
        if (empty($this->content) || !$this->isDecorated()) {
            return;
        }
        if ($lines) {
            array_splice($this->content, -$lines);
        } else {
            $lines = $this->lines;
            $this->content = [];
        }
        $this->lines -= $lines;
        parent::doWrite($this->popStreamContentUntilCurrentSection($this->maxHeight ? min($this->maxHeight, $lines) : $lines), \false);
    }
    /**
     * Overwrites the previous output with a new message.
     *
     * @return void
     */
    public function overwrite(string|iterable $message)
    {
        $this->clear();
        $this->writeln($message);
    }
    public function getContent(): string
    {
        return implode('', $this->content);
    }
    public function getVisibleContent(): string
    {
        if (0 === $this->maxHeight) {
            return $this->getContent();
        }
        return implode('', \array_slice($this->content, -$this->maxHeight));
    }
    /**
     * @internal
     */
    public function addContent(string $input, bool $newline = \true): int
    {
        $width = $this->terminal->getWidth();
        $lines = explode(\PHP_EOL, $input);
        $linesAdded = 0;
        $count = \count($lines) - 1;
        foreach ($lines as $i => $lineContent) {
            // re-add the line break (that has been removed in the above `explode()` for
            // - every line that is not the last line
            // - if $newline is required, also add it to the last line
            if ($i < $count || $newline) {
                $lineContent .= \PHP_EOL;
            }
            // skip line if there is no text (or newline for that matter)
            if ('' === $lineContent) {
                continue;
            }
            // For the first line, check if the previous line (last entry of `$this->content`)
            // needs to be continued (i.e. does not end with a line break).
            if (0 === $i && \false !== ($lastLine = end($this->content)) && !str_ends_with($lastLine, \PHP_EOL)) {
                // deduct the line count of the previous line
                $this->lines -= (int) ceil($this->getDisplayLength($lastLine) / $width) ?: 1;
                // concatenate previous and new line
                $lineContent = $lastLine . $lineContent;
                // replace last entry of `$this->content` with the new expanded line
                array_splice($this->content, -1, 1, $lineContent);
            } else {
                // otherwise just add the new content
                $this->content[] = $lineContent;
            }
            $linesAdded += (int) ceil($this->getDisplayLength($lineContent) / $width) ?: 1;
        }
        $this->lines += $linesAdded;
        return $linesAdded;
    }
    /**
     * @internal
     */
    public function addNewLineOfInputSubmit(): void
    {
        $this->content[] = \PHP_EOL;
        ++$this->lines;
    }
    /**
     * @return void
     */
    protected function doWrite(string $message, bool $newline)
    {
        // Simulate newline behavior for consistent output formatting, avoiding extra logic
        if (!$newline && str_ends_with($message, \PHP_EOL)) {
            $message = substr($message, 0, -\strlen(\PHP_EOL));
            $newline = \true;
        }
        if (!$this->isDecorated()) {
            parent::doWrite($message, $newline);
            return;
        }
        // Check if the previous line (last entry of `$this->content`) needs to be continued
        // (i.e. does not end with a line break). In which case, it needs to be erased first.
        $linesToClear = $deleteLastLine = ($lastLine = end($this->content) ?: '') && !str_ends_with($lastLine, \PHP_EOL) ? 1 : 0;
        $linesAdded = $this->addContent($message, $newline);
        if ($lineOverflow = $this->maxHeight > 0 && $this->lines > $this->maxHeight) {
            // on overflow, clear the whole section and redraw again (to remove the first lines)
            $linesToClear = $this->maxHeight;
        }
        $erasedContent = $this->popStreamContentUntilCurrentSection($linesToClear);
        if ($lineOverflow) {
            // redraw existing lines of the section
            $previousLinesOfSection = \array_slice($this->content, $this->lines - $this->maxHeight, $this->maxHeight - $linesAdded);
            parent::doWrite(implode('', $previousLinesOfSection), \false);
        }
        // if the last line was removed, re-print its content together with the new content.
        // otherwise, just print the new content.
        parent::doWrite($deleteLastLine ? $lastLine . $message : $message, \true);
        parent::doWrite($erasedContent, \false);
    }
    /**
     * At initial stage, cursor is at the end of stream output. This method makes cursor crawl upwards until it hits
     * current section. Then it erases content it crawled through. Optionally, it erases part of current section too.
     */
    private function popStreamContentUntilCurrentSection(int $numberOfLinesToClearFromCurrentSection = 0): string
    {
        $numberOfLinesToClear = $numberOfLinesToClearFromCurrentSection;
        $erasedContent = [];
        foreach ($this->sections as $section) {
            if ($section === $this) {
                break;
            }
            $numberOfLinesToClear += $section->maxHeight ? min($section->lines, $section->maxHeight) : $section->lines;
            if ('' !== $sectionContent = $section->getVisibleContent()) {
                if (!str_ends_with($sectionContent, \PHP_EOL)) {
                    $sectionContent .= \PHP_EOL;
                }
                $erasedContent[] = $sectionContent;
            }
        }
        if ($numberOfLinesToClear > 0) {
            // move cursor up n lines
            parent::doWrite(\sprintf("\x1b[%dA", $numberOfLinesToClear), \false);
            // erase to end of screen
            parent::doWrite("\x1b[0J", \false);
        }
        return implode('', array_reverse($erasedContent));
    }
    private function getDisplayLength(string $text): int
    {
        return Helper::width(Helper::removeDecoration($this->getFormatter(), str_replace("\t", '        ', $text)));
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Console\Output;

use _ContaoManager\Symfony\Component\Console\Formatter\OutputFormatterInterface;
/**
 * ConsoleOutput is the default class for all CLI output. It uses STDOUT and STDERR.
 *
 * This class is a convenient wrapper around `StreamOutput` for both STDOUT and STDERR.
 *
 *     $output = new ConsoleOutput();
 *
 * This is equivalent to:
 *
 *     $output = new StreamOutput(fopen('php://stdout', 'w'));
 *     $stdErr = new StreamOutput(fopen('php://stderr', 'w'));
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class ConsoleOutput extends StreamOutput implements ConsoleOutputInterface
{
    private OutputInterface $stderr;
    private array $consoleSectionOutputs = [];
    /**
     * @param int                           $verbosity The verbosity level (one of the VERBOSITY constants in OutputInterface)
     * @param bool|null                     $decorated Whether to decorate messages (null for auto-guessing)
     * @param OutputFormatterInterface|null $formatter Output formatter instance (null to use default OutputFormatter)
     */
    public function __construct(int $verbosity = self::VERBOSITY_NORMAL, ?bool $decorated = null, ?OutputFormatterInterface $formatter = null)
    {
        parent::__construct($this->openOutputStream(), $verbosity, $decorated, $formatter);
        if (null === $formatter) {
            // for BC reasons, stdErr has it own Formatter only when user don't inject a specific formatter.
            $this->stderr = new StreamOutput($this->openErrorStream(), $verbosity, $decorated);
            return;
        }
        $actualDecorated = $this->isDecorated();
        $this->stderr = new StreamOutput($this->openErrorStream(), $verbosity, $decorated, $this->getFormatter());
        if (null === $decorated) {
            $this->setDecorated($actualDecorated && $this->stderr->isDecorated());
        }
    }
    /**
     * Creates a new output section.
     */
    public function section(): ConsoleSectionOutput
    {
        return new ConsoleSectionOutput($this->getStream(), $this->consoleSectionOutputs, $this->getVerbosity(), $this->isDecorated(), $this->getFormatter());
    }
    /**
     * @return void
     */
    public function setDecorated(bool $decorated)
    {
        parent::setDecorated($decorated);
        $this->stderr->setDecorated($decorated);
    }
    /**
     * @return void
     */
    public function setFormatter(OutputFormatterInterface $formatter)
    {
        parent::setFormatter($formatter);
        $this->stderr->setFormatter($formatter);
    }
    /**
     * @return void
     */
    public function setVerbosity(int $level)
    {
        parent::setVerbosity($level);
        $this->stderr->setVerbosity($level);
    }
    public function getErrorOutput(): OutputInterface
    {
        return $this->stderr;
    }
    /**
     * @return void
     */
    public function setErrorOutput(OutputInterface $error)
    {
        $this->stderr = $error;
    }
    /**
     * Returns true if current environment supports writing console output to
     * STDOUT.
     */
    protected function hasStdoutSupport(): bool
    {
        return \false === $this->isRunningOS400();
    }
    /**
     * Returns true if current environment supports writing console output to
     * STDERR.
     */
    protected function hasStderrSupport(): bool
    {
        return \false === $this->isRunningOS400();
    }
    /**
     * Checks if current executing environment is IBM iSeries (OS400), which
     * doesn't properly convert character-encodings between ASCII to EBCDIC.
     */
    private function isRunningOS400(): bool
    {
        $checks = [\function_exists('php_uname') ? php_uname('s') : '', getenv('OSTYPE'), \PHP_OS];
        return \false !== stripos(implode(';', $checks), 'OS400');
    }
    /**
     * @return resource
     */
    private function openOutputStream()
    {
        static $stdout;
        if ($stdout) {
            return $stdout;
        }
        if (!$this->hasStdoutSupport()) {
            return $stdout = fopen('php://output', 'w');
        }
        // Use STDOUT when possible to prevent from opening too many file descriptors
        if (!\defined('STDOUT')) {
            return $stdout = @fopen('php://stdout', 'w') ?: fopen('php://output', 'w');
        }
        // On Windows, STDOUT is opened in text mode; reopen in binary mode to prevent \n to \r\n conversion
        if ('\\' === \DIRECTORY_SEPARATOR) {
            return $stdout = @fopen('php://stdout', 'w') ?: \STDOUT;
        }
        return $stdout = \STDOUT;
    }
    /**
     * @return resource
     */
    private function openErrorStream()
    {
        static $stderr;
        if ($stderr) {
            return $stderr;
        }
        if (!$this->hasStderrSupport()) {
            return $stderr = fopen('php://output', 'w');
        }
        // Use STDERR when possible to prevent from opening too many file descriptors
        if (!\defined('STDERR')) {
            return $stderr = @fopen('php://stderr', 'w') ?: fopen('php://output', 'w');
        }
        // On Windows, STDERR is opened in text mode; reopen in binary mode to prevent \n → \r\n conversion
        if ('\\' === \DIRECTORY_SEPARATOR) {
            return $stderr = @fopen('php://stderr', 'w') ?: \STDERR;
        }
        return $stderr ??= \STDERR;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Console\Output;

use _ContaoManager\Symfony\Component\Console\Formatter\NullOutputFormatter;
use _ContaoManager\Symfony\Component\Console\Formatter\OutputFormatterInterface;
/**
 * NullOutput suppresses all output.
 *
 *     $output = new NullOutput();
 *
 * @author Fabien Potencier <fabien@symfony.com>
 * @author Tobias Schultze <http://tobion.de>
 */
class NullOutput implements OutputInterface
{
    private NullOutputFormatter $formatter;
    /**
     * @return void
     */
    public function setFormatter(OutputFormatterInterface $formatter)
    {
        // do nothing
    }
    public function getFormatter(): OutputFormatterInterface
    {
        // to comply with the interface we must return a OutputFormatterInterface
        return $this->formatter ??= new NullOutputFormatter();
    }
    /**
     * @return void
     */
    public function setDecorated(bool $decorated)
    {
        // do nothing
    }
    public function isDecorated(): bool
    {
        return \false;
    }
    /**
     * @return void
     */
    public function setVerbosity(int $level)
    {
        // do nothing
    }
    public function getVerbosity(): int
    {
        return self::VERBOSITY_QUIET;
    }
    public function isQuiet(): bool
    {
        return \true;
    }
    public function isVerbose(): bool
    {
        return \false;
    }
    public function isVeryVerbose(): bool
    {
        return \false;
    }
    public function isDebug(): bool
    {
        return \false;
    }
    /**
     * @return void
     */
    public function writeln(string|iterable $messages, int $options = self::OUTPUT_NORMAL)
    {
        // do nothing
    }
    /**
     * @return void
     */
    public function write(string|iterable $messages, bool $newline = \false, int $options = self::OUTPUT_NORMAL)
    {
        // do nothing
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Console\Output;

use _ContaoManager\Symfony\Component\Console\Exception\InvalidArgumentException;
use _ContaoManager\Symfony\Component\Console\Formatter\OutputFormatterInterface;
/**
 * StreamOutput writes the output to a given stream.
 *
 * Usage:
 *
 *     $output = new StreamOutput(fopen('php://stdout', 'w'));
 *
 * As `StreamOutput` can use any stream, you can also use a file:
 *
 *     $output = new StreamOutput(fopen('/path/to/output.log', 'a', false));
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class StreamOutput extends Output
{
    /** @var resource */
    private $stream;
    /**
     * @param resource                      $stream    A stream resource
     * @param int                           $verbosity The verbosity level (one of the VERBOSITY constants in OutputInterface)
     * @param bool|null                     $decorated Whether to decorate messages (null for auto-guessing)
     * @param OutputFormatterInterface|null $formatter Output formatter instance (null to use default OutputFormatter)
     *
     * @throws InvalidArgumentException When first argument is not a real stream
     */
    public function __construct($stream, int $verbosity = self::VERBOSITY_NORMAL, ?bool $decorated = null, ?OutputFormatterInterface $formatter = null)
    {
        if (!\is_resource($stream) || 'stream' !== get_resource_type($stream)) {
            throw new InvalidArgumentException('The StreamOutput class needs a stream as its first argument.');
        }
        $this->stream = $stream;
        $decorated ??= $this->hasColorSupport();
        parent::__construct($verbosity, $decorated, $formatter);
    }
    /**
     * Gets the stream attached to this StreamOutput instance.
     *
     * @return resource
     */
    public function getStream()
    {
        return $this->stream;
    }
    /**
     * @return void
     */
    protected function doWrite(string $message, bool $newline)
    {
        if ($newline) {
            $message .= \PHP_EOL;
        }
        @fwrite($this->stream, $message);
        fflush($this->stream);
    }
    /**
     * Returns true if the stream supports colorization.
     *
     * Colorization is disabled if not supported by the stream:
     *
     * This is tricky on Windows, because Cygwin, Msys2 etc emulate pseudo
     * terminals via named pipes, so we can only check the environment.
     *
     * Reference: Composer\XdebugHandler\Process::supportsColor
     * https://github.com/composer/xdebug-handler
     *
     * @return bool true if the stream supports colorization, false otherwise
     */
    protected function hasColorSupport(): bool
    {
        // Follow https://no-color.org/
        if ('' !== (($_SERVER['NO_COLOR'] ?? getenv('NO_COLOR'))[0] ?? '')) {
            return \false;
        }
        // Detect msysgit/mingw and assume this is a tty because detection
        // does not work correctly, see https://github.com/composer/composer/issues/9690
        if (!@stream_isatty($this->stream) && !\in_array(strtoupper((string) getenv('MSYSTEM')), ['MINGW32', 'MINGW64'], \true)) {
            return \false;
        }
        if ('\\' === \DIRECTORY_SEPARATOR && @sapi_windows_vt100_support($this->stream)) {
            return \true;
        }
        if ('Hyper' === getenv('TERM_PROGRAM') || \false !== getenv('COLORTERM') || \false !== getenv('ANSICON') || 'ON' === getenv('ConEmuANSI')) {
            return \true;
        }
        if ('dumb' === $term = (string) getenv('TERM')) {
            return \false;
        }
        // See https://github.com/chalk/supports-color/blob/d4f413efaf8da045c5ab440ed418ef02dbb28bf1/index.js#L157
        return preg_match('/^((screen|xterm|vt100|vt220|putty|rxvt|ansi|cygwin|linux).*)|(.*-256(color)?(-bce)?)$/', $term);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Console\Completion\Output;

use _ContaoManager\Symfony\Component\Console\Completion\CompletionSuggestions;
use _ContaoManager\Symfony\Component\Console\Output\OutputInterface;
/**
 * @author Guillaume Aveline <guillaume.aveline@pm.me>
 */
class FishCompletionOutput implements CompletionOutputInterface
{
    public function write(CompletionSuggestions $suggestions, OutputInterface $output): void
    {
        $values = $suggestions->getValueSuggestions();
        foreach ($suggestions->getOptionSuggestions() as $option) {
            $values[] = '--' . $option->getName();
            if ($option->isNegatable()) {
                $values[] = '--no-' . $option->getName();
            }
        }
        $output->write(implode("\n", $values));
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Console\Completion\Output;

use _ContaoManager\Symfony\Component\Console\Completion\CompletionSuggestions;
use _ContaoManager\Symfony\Component\Console\Output\OutputInterface;
/**
 * @author Wouter de Jong <wouter@wouterj.nl>
 */
class BashCompletionOutput implements CompletionOutputInterface
{
    public function write(CompletionSuggestions $suggestions, OutputInterface $output): void
    {
        $values = $suggestions->getValueSuggestions();
        foreach ($suggestions->getOptionSuggestions() as $option) {
            $values[] = '--' . $option->getName();
            if ($option->isNegatable()) {
                $values[] = '--no-' . $option->getName();
            }
        }
        $output->writeln(implode("\n", $values));
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Console\Completion\Output;

use _ContaoManager\Symfony\Component\Console\Completion\CompletionSuggestions;
use _ContaoManager\Symfony\Component\Console\Output\OutputInterface;
/**
 * Transforms the {@see CompletionSuggestions} object into output readable by the shell completion.
 *
 * @author Wouter de Jong <wouter@wouterj.nl>
 */
interface CompletionOutputInterface
{
    public function write(CompletionSuggestions $suggestions, OutputInterface $output): void;
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Console\Completion\Output;

use _ContaoManager\Symfony\Component\Console\Completion\CompletionSuggestions;
use _ContaoManager\Symfony\Component\Console\Output\OutputInterface;
/**
 * @author Jitendra A <adhocore@gmail.com>
 */
class ZshCompletionOutput implements CompletionOutputInterface
{
    public function write(CompletionSuggestions $suggestions, OutputInterface $output): void
    {
        $values = [];
        foreach ($suggestions->getValueSuggestions() as $value) {
            $values[] = $value->getValue() . ($value->getDescription() ? "\t" . $value->getDescription() : '');
        }
        foreach ($suggestions->getOptionSuggestions() as $option) {
            $values[] = '--' . $option->getName() . ($option->getDescription() ? "\t" . $option->getDescription() : '');
            if ($option->isNegatable()) {
                $values[] = '--no-' . $option->getName() . ($option->getDescription() ? "\t" . $option->getDescription() : '');
            }
        }
        $output->write(implode("\n", $values) . "\n");
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Console\Completion;

/**
 * Represents a single suggested value.
 *
 * @author Wouter de Jong <wouter@wouterj.nl>
 */
class Suggestion implements \Stringable
{
    public function __construct(private readonly string $value, private readonly string $description = '')
    {
    }
    public function getValue(): string
    {
        return $this->value;
    }
    public function getDescription(): string
    {
        return $this->description;
    }
    public function __toString(): string
    {
        return $this->getValue();
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Console\Completion;

use _ContaoManager\Symfony\Component\Console\Input\InputOption;
/**
 * Stores all completion suggestions for the current input.
 *
 * @author Wouter de Jong <wouter@wouterj.nl>
 */
final class CompletionSuggestions
{
    private array $valueSuggestions = [];
    private array $optionSuggestions = [];
    /**
     * Add a suggested value for an input option or argument.
     *
     * @return $this
     */
    public function suggestValue(string|Suggestion $value): static
    {
        $this->valueSuggestions[] = !$value instanceof Suggestion ? new Suggestion($value) : $value;
        return $this;
    }
    /**
     * Add multiple suggested values at once for an input option or argument.
     *
     * @param list<string|Suggestion> $values
     *
     * @return $this
     */
    public function suggestValues(array $values): static
    {
        foreach ($values as $value) {
            $this->suggestValue($value);
        }
        return $this;
    }
    /**
     * Add a suggestion for an input option name.
     *
     * @return $this
     */
    public function suggestOption(InputOption $option): static
    {
        $this->optionSuggestions[] = $option;
        return $this;
    }
    /**
     * Add multiple suggestions for input option names at once.
     *
     * @param InputOption[] $options
     *
     * @return $this
     */
    public function suggestOptions(array $options): static
    {
        foreach ($options as $option) {
            $this->suggestOption($option);
        }
        return $this;
    }
    /**
     * @return InputOption[]
     */
    public function getOptionSuggestions(): array
    {
        return $this->optionSuggestions;
    }
    /**
     * @return Suggestion[]
     */
    public function getValueSuggestions(): array
    {
        return $this->valueSuggestions;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Console\Completion;

use _ContaoManager\Symfony\Component\Console\Exception\RuntimeException;
use _ContaoManager\Symfony\Component\Console\Input\ArgvInput;
use _ContaoManager\Symfony\Component\Console\Input\InputDefinition;
use _ContaoManager\Symfony\Component\Console\Input\InputOption;
/**
 * An input specialized for shell completion.
 *
 * This input allows unfinished option names or values and exposes what kind of
 * completion is expected.
 *
 * @author Wouter de Jong <wouter@wouterj.nl>
 */
final class CompletionInput extends ArgvInput
{
    public const TYPE_ARGUMENT_VALUE = 'argument_value';
    public const TYPE_OPTION_VALUE = 'option_value';
    public const TYPE_OPTION_NAME = 'option_name';
    public const TYPE_NONE = 'none';
    private array $tokens;
    private int $currentIndex;
    private string $completionType;
    private ?string $completionName = null;
    private string $completionValue = '';
    /**
     * Converts a terminal string into tokens.
     *
     * This is required for shell completions without COMP_WORDS support.
     */
    public static function fromString(string $inputStr, int $currentIndex): self
    {
        preg_match_all('/(?<=^|\s)([\'"]?)(.+?)(?<!\\\\)\1(?=$|\s)/', $inputStr, $tokens);
        return self::fromTokens($tokens[0], $currentIndex);
    }
    /**
     * Create an input based on an COMP_WORDS token list.
     *
     * @param string[] $tokens       the set of split tokens (e.g. COMP_WORDS or argv)
     * @param int      $currentIndex the index of the cursor (e.g. COMP_CWORD)
     */
    public static function fromTokens(array $tokens, int $currentIndex): self
    {
        $input = new self($tokens);
        $input->tokens = $tokens;
        $input->currentIndex = $currentIndex;
        return $input;
    }
    public function bind(InputDefinition $definition): void
    {
        parent::bind($definition);
        $relevantToken = $this->getRelevantToken();
        if ('-' === $relevantToken[0]) {
            // the current token is an input option: complete either option name or option value
            [$optionToken, $optionValue] = explode('=', $relevantToken, 2) + ['', ''];
            $option = $this->getOptionFromToken($optionToken);
            if (null === $option && !$this->isCursorFree()) {
                $this->completionType = self::TYPE_OPTION_NAME;
                $this->completionValue = $relevantToken;
                return;
            }
            if ($option?->acceptValue()) {
                $this->completionType = self::TYPE_OPTION_VALUE;
                $this->completionName = $option->getName();
                $this->completionValue = $optionValue ?: (!str_starts_with($optionToken, '--') ? substr($optionToken, 2) : '');
                return;
            }
        }
        $previousToken = $this->tokens[$this->currentIndex - 1];
        if ('-' === $previousToken[0] && '' !== trim($previousToken, '-')) {
            // check if previous option accepted a value
            $previousOption = $this->getOptionFromToken($previousToken);
            if ($previousOption?->acceptValue()) {
                $this->completionType = self::TYPE_OPTION_VALUE;
                $this->completionName = $previousOption->getName();
                $this->completionValue = $relevantToken;
                return;
            }
        }
        // complete argument value
        $this->completionType = self::TYPE_ARGUMENT_VALUE;
        foreach ($this->definition->getArguments() as $argumentName => $argument) {
            if (!isset($this->arguments[$argumentName])) {
                break;
            }
            $argumentValue = $this->arguments[$argumentName];
            $this->completionName = $argumentName;
            if (\is_array($argumentValue)) {
                $this->completionValue = $argumentValue ? $argumentValue[array_key_last($argumentValue)] : null;
            } else {
                $this->completionValue = $argumentValue;
            }
        }
        if ($this->currentIndex >= \count($this->tokens)) {
            if (!isset($this->arguments[$argumentName]) || $this->definition->getArgument($argumentName)->isArray()) {
                $this->completionName = $argumentName;
                $this->completionValue = '';
            } else {
                // we've reached the end
                $this->completionType = self::TYPE_NONE;
                $this->completionName = null;
                $this->completionValue = '';
            }
        }
    }
    /**
     * Returns the type of completion required.
     *
     * TYPE_ARGUMENT_VALUE when completing the value of an input argument
     * TYPE_OPTION_VALUE   when completing the value of an input option
     * TYPE_OPTION_NAME    when completing the name of an input option
     * TYPE_NONE           when nothing should be completed
     *
     * TYPE_OPTION_NAME and TYPE_NONE are already implemented by the Console component.
     *
     * @return self::TYPE_*
     */
    public function getCompletionType(): string
    {
        return $this->completionType;
    }
    /**
     * The name of the input option or argument when completing a value.
     *
     * @return string|null returns null when completing an option name
     */
    public function getCompletionName(): ?string
    {
        return $this->completionName;
    }
    /**
     * The value already typed by the user (or empty string).
     */
    public function getCompletionValue(): string
    {
        return $this->completionValue;
    }
    public function mustSuggestOptionValuesFor(string $optionName): bool
    {
        return self::TYPE_OPTION_VALUE === $this->getCompletionType() && $optionName === $this->getCompletionName();
    }
    public function mustSuggestArgumentValuesFor(string $argumentName): bool
    {
        return self::TYPE_ARGUMENT_VALUE === $this->getCompletionType() && $argumentName === $this->getCompletionName();
    }
    protected function parseToken(string $token, bool $parseOptions): bool
    {
        try {
            return parent::parseToken($token, $parseOptions);
        } catch (RuntimeException) {
            // suppress errors, completed input is almost never valid
        }
        return $parseOptions;
    }
    private function getOptionFromToken(string $optionToken): ?InputOption
    {
        $optionName = ltrim($optionToken, '-');
        if (!$optionName) {
            return null;
        }
        if ('-' === ($optionToken[1] ?? ' ')) {
            // long option name
            return $this->definition->hasOption($optionName) ? $this->definition->getOption($optionName) : null;
        }
        // short option name
        return $this->definition->hasShortcut($optionName[0]) ? $this->definition->getOptionForShortcut($optionName[0]) : null;
    }
    /**
     * The token of the cursor, or the last token if the cursor is at the end of the input.
     */
    private function getRelevantToken(): string
    {
        return $this->tokens[$this->isCursorFree() ? $this->currentIndex - 1 : $this->currentIndex];
    }
    /**
     * Whether the cursor is "free" (i.e. at the end of the input preceded by a space).
     */
    private function isCursorFree(): bool
    {
        $nrOfTokens = \count($this->tokens);
        if ($this->currentIndex > $nrOfTokens) {
            throw new \LogicException('Current index is invalid, it must be the number of input tokens or one more.');
        }
        return $this->currentIndex >= $nrOfTokens;
    }
    public function __toString()
    {
        $str = '';
        foreach ($this->tokens as $i => $token) {
            $str .= $token;
            if ($this->currentIndex === $i) {
                $str .= '|';
            }
            $str .= ' ';
        }
        if ($this->currentIndex > $i) {
            $str .= '|';
        }
        return rtrim($str);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Console\Style;

use _ContaoManager\Symfony\Component\Console\Formatter\OutputFormatterInterface;
use _ContaoManager\Symfony\Component\Console\Helper\ProgressBar;
use _ContaoManager\Symfony\Component\Console\Output\ConsoleOutputInterface;
use _ContaoManager\Symfony\Component\Console\Output\OutputInterface;
/**
 * Decorates output to add console style guide helpers.
 *
 * @author Kevin Bond <kevinbond@gmail.com>
 */
abstract class OutputStyle implements OutputInterface, StyleInterface
{
    private OutputInterface $output;
    public function __construct(OutputInterface $output)
    {
        $this->output = $output;
    }
    /**
     * @return void
     */
    public function newLine(int $count = 1)
    {
        $this->output->write(str_repeat(\PHP_EOL, $count));
    }
    public function createProgressBar(int $max = 0): ProgressBar
    {
        return new ProgressBar($this->output, $max);
    }
    /**
     * @return void
     */
    public function write(string|iterable $messages, bool $newline = \false, int $type = self::OUTPUT_NORMAL)
    {
        $this->output->write($messages, $newline, $type);
    }
    /**
     * @return void
     */
    public function writeln(string|iterable $messages, int $type = self::OUTPUT_NORMAL)
    {
        $this->output->writeln($messages, $type);
    }
    /**
     * @return void
     */
    public function setVerbosity(int $level)
    {
        $this->output->setVerbosity($level);
    }
    public function getVerbosity(): int
    {
        return $this->output->getVerbosity();
    }
    /**
     * @return void
     */
    public function setDecorated(bool $decorated)
    {
        $this->output->setDecorated($decorated);
    }
    public function isDecorated(): bool
    {
        return $this->output->isDecorated();
    }
    /**
     * @return void
     */
    public function setFormatter(OutputFormatterInterface $formatter)
    {
        $this->output->setFormatter($formatter);
    }
    public function getFormatter(): OutputFormatterInterface
    {
        return $this->output->getFormatter();
    }
    public function isQuiet(): bool
    {
        return $this->output->isQuiet();
    }
    public function isVerbose(): bool
    {
        return $this->output->isVerbose();
    }
    public function isVeryVerbose(): bool
    {
        return $this->output->isVeryVerbose();
    }
    public function isDebug(): bool
    {
        return $this->output->isDebug();
    }
    /**
     * @return OutputInterface
     */
    protected function getErrorOutput()
    {
        if (!$this->output instanceof ConsoleOutputInterface) {
            return $this->output;
        }
        return $this->output->getErrorOutput();
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Console\Style;

use _ContaoManager\Symfony\Component\Console\Exception\InvalidArgumentException;
use _ContaoManager\Symfony\Component\Console\Exception\RuntimeException;
use _ContaoManager\Symfony\Component\Console\Formatter\OutputFormatter;
use _ContaoManager\Symfony\Component\Console\Helper\Helper;
use _ContaoManager\Symfony\Component\Console\Helper\OutputWrapper;
use _ContaoManager\Symfony\Component\Console\Helper\ProgressBar;
use _ContaoManager\Symfony\Component\Console\Helper\SymfonyQuestionHelper;
use _ContaoManager\Symfony\Component\Console\Helper\Table;
use _ContaoManager\Symfony\Component\Console\Helper\TableCell;
use _ContaoManager\Symfony\Component\Console\Helper\TableSeparator;
use _ContaoManager\Symfony\Component\Console\Input\InputInterface;
use _ContaoManager\Symfony\Component\Console\Output\ConsoleOutputInterface;
use _ContaoManager\Symfony\Component\Console\Output\ConsoleSectionOutput;
use _ContaoManager\Symfony\Component\Console\Output\OutputInterface;
use _ContaoManager\Symfony\Component\Console\Output\TrimmedBufferOutput;
use _ContaoManager\Symfony\Component\Console\Question\ChoiceQuestion;
use _ContaoManager\Symfony\Component\Console\Question\ConfirmationQuestion;
use _ContaoManager\Symfony\Component\Console\Question\Question;
use _ContaoManager\Symfony\Component\Console\Terminal;
/**
 * Output decorator helpers for the Symfony Style Guide.
 *
 * @author Kevin Bond <kevinbond@gmail.com>
 */
class SymfonyStyle extends OutputStyle
{
    public const MAX_LINE_LENGTH = 120;
    private InputInterface $input;
    private OutputInterface $output;
    private SymfonyQuestionHelper $questionHelper;
    private ProgressBar $progressBar;
    private int $lineLength;
    private TrimmedBufferOutput $bufferedOutput;
    public function __construct(InputInterface $input, OutputInterface $output)
    {
        $this->input = $input;
        $this->bufferedOutput = new TrimmedBufferOutput(\DIRECTORY_SEPARATOR === '\\' ? 4 : 2, $output->getVerbosity(), \false, clone $output->getFormatter());
        // Windows cmd wraps lines as soon as the terminal width is reached, whether there are following chars or not.
        $width = (new Terminal())->getWidth() ?: self::MAX_LINE_LENGTH;
        $this->lineLength = min($width - (int) (\DIRECTORY_SEPARATOR === '\\'), self::MAX_LINE_LENGTH);
        parent::__construct($this->output = $output);
    }
    /**
     * Formats a message as a block of text.
     *
     * @return void
     */
    public function block(string|array $messages, ?string $type = null, ?string $style = null, string $prefix = ' ', bool $padding = \false, bool $escape = \true)
    {
        $messages = \is_array($messages) ? array_values($messages) : [$messages];
        $this->autoPrependBlock();
        $this->writeln($this->createBlock($messages, $type, $style, $prefix, $padding, $escape));
        $this->newLine();
    }
    /**
     * @return void
     */
    public function title(string $message)
    {
        $this->autoPrependBlock();
        $this->writeln([\sprintf('<comment>%s</>', OutputFormatter::escapeTrailingBackslash($message)), \sprintf('<comment>%s</>', str_repeat('=', Helper::width(Helper::removeDecoration($this->getFormatter(), $message))))]);
        $this->newLine();
    }
    /**
     * @return void
     */
    public function section(string $message)
    {
        $this->autoPrependBlock();
        $this->writeln([\sprintf('<comment>%s</>', OutputFormatter::escapeTrailingBackslash($message)), \sprintf('<comment>%s</>', str_repeat('-', Helper::width(Helper::removeDecoration($this->getFormatter(), $message))))]);
        $this->newLine();
    }
    /**
     * @return void
     */
    public function listing(array $elements)
    {
        $this->autoPrependText();
        $elements = array_map(static fn($element) => \sprintf(' * %s', $element), $elements);
        $this->writeln($elements);
        $this->newLine();
    }
    /**
     * @return void
     */
    public function text(string|array $message)
    {
        $this->autoPrependText();
        $messages = \is_array($message) ? array_values($message) : [$message];
        foreach ($messages as $message) {
            $this->writeln(\sprintf(' %s', $message));
        }
    }
    /**
     * Formats a command comment.
     *
     * @return void
     */
    public function comment(string|array $message)
    {
        $this->block($message, null, null, '<fg=default;bg=default> // </>', \false, \false);
    }
    /**
     * @return void
     */
    public function success(string|array $message)
    {
        $this->block($message, 'OK', 'fg=black;bg=green', ' ', \true);
    }
    /**
     * @return void
     */
    public function error(string|array $message)
    {
        $this->block($message, 'ERROR', 'fg=white;bg=red', ' ', \true);
    }
    /**
     * @return void
     */
    public function warning(string|array $message)
    {
        $this->block($message, 'WARNING', 'fg=black;bg=yellow', ' ', \true);
    }
    /**
     * @return void
     */
    public function note(string|array $message)
    {
        $this->block($message, 'NOTE', 'fg=yellow', ' ! ');
    }
    /**
     * Formats an info message.
     *
     * @return void
     */
    public function info(string|array $message)
    {
        $this->block($message, 'INFO', 'fg=green', ' ', \true);
    }
    /**
     * @return void
     */
    public function caution(string|array $message)
    {
        $this->block($message, 'CAUTION', 'fg=white;bg=red', ' ! ', \true);
    }
    /**
     * @return void
     */
    public function table(array $headers, array $rows)
    {
        $this->createTable()->setHeaders($headers)->setRows($rows)->render();
        $this->newLine();
    }
    /**
     * Formats a horizontal table.
     *
     * @return void
     */
    public function horizontalTable(array $headers, array $rows)
    {
        $this->createTable()->setHorizontal(\true)->setHeaders($headers)->setRows($rows)->render();
        $this->newLine();
    }
    /**
     * Formats a list of key/value horizontally.
     *
     * Each row can be one of:
     * * 'A title'
     * * ['key' => 'value']
     * * new TableSeparator()
     *
     * @return void
     */
    public function definitionList(string|array|TableSeparator ...$list)
    {
        $headers = [];
        $row = [];
        foreach ($list as $value) {
            if ($value instanceof TableSeparator) {
                $headers[] = $value;
                $row[] = $value;
                continue;
            }
            if (\is_string($value)) {
                $headers[] = new TableCell($value, ['colspan' => 2]);
                $row[] = null;
                continue;
            }
            if (!\is_array($value)) {
                throw new InvalidArgumentException('Value should be an array, string, or an instance of TableSeparator.');
            }
            $headers[] = key($value);
            $row[] = current($value);
        }
        $this->horizontalTable($headers, [$row]);
    }
    public function ask(string $question, ?string $default = null, ?callable $validator = null): mixed
    {
        $question = new Question($question, $default);
        $question->setValidator($validator);
        return $this->askQuestion($question);
    }
    public function askHidden(string $question, ?callable $validator = null): mixed
    {
        $question = new Question($question);
        $question->setHidden(\true);
        $question->setValidator($validator);
        return $this->askQuestion($question);
    }
    public function confirm(string $question, bool $default = \true): bool
    {
        return $this->askQuestion(new ConfirmationQuestion($question, $default));
    }
    public function choice(string $question, array $choices, mixed $default = null, bool $multiSelect = \false): mixed
    {
        if (null !== $default) {
            $values = array_flip($choices);
            $default = $values[$default] ?? $default;
        }
        $questionChoice = new ChoiceQuestion($question, $choices, $default);
        $questionChoice->setMultiselect($multiSelect);
        return $this->askQuestion($questionChoice);
    }
    /**
     * @return void
     */
    public function progressStart(int $max = 0)
    {
        $this->progressBar = $this->createProgressBar($max);
        $this->progressBar->start();
    }
    /**
     * @return void
     */
    public function progressAdvance(int $step = 1)
    {
        $this->getProgressBar()->advance($step);
    }
    /**
     * @return void
     */
    public function progressFinish()
    {
        $this->getProgressBar()->finish();
        $this->newLine(2);
        unset($this->progressBar);
    }
    public function createProgressBar(int $max = 0): ProgressBar
    {
        $progressBar = parent::createProgressBar($max);
        if ('\\' !== \DIRECTORY_SEPARATOR || 'Hyper' === getenv('TERM_PROGRAM')) {
            $progressBar->setEmptyBarCharacter('░');
            // light shade character \u2591
            $progressBar->setProgressCharacter('');
            $progressBar->setBarCharacter('▓');
            // dark shade character \u2593
        }
        return $progressBar;
    }
    /**
     * @see ProgressBar::iterate()
     *
     * @template TKey
     * @template TValue
     *
     * @param iterable<TKey, TValue> $iterable
     * @param int|null               $max      Number of steps to complete the bar (0 if indeterminate), if null it will be inferred from $iterable
     *
     * @return iterable<TKey, TValue>
     */
    public function progressIterate(iterable $iterable, ?int $max = null): iterable
    {
        yield from $this->createProgressBar()->iterate($iterable, $max);
        $this->newLine(2);
    }
    public function askQuestion(Question $question): mixed
    {
        if ($this->input->isInteractive()) {
            $this->autoPrependBlock();
        }
        $this->questionHelper ??= new SymfonyQuestionHelper();
        $answer = $this->questionHelper->ask($this->input, $this, $question);
        if ($this->input->isInteractive()) {
            if ($this->output instanceof ConsoleSectionOutput) {
                // add the new line of the `return` to submit the input to ConsoleSectionOutput, because ConsoleSectionOutput is holding all it's lines.
                // this is relevant when a `ConsoleSectionOutput::clear` is called.
                $this->output->addNewLineOfInputSubmit();
            }
            $this->newLine();
            $this->bufferedOutput->write("\n");
        }
        return $answer;
    }
    /**
     * @return void
     */
    public function writeln(string|iterable $messages, int $type = self::OUTPUT_NORMAL)
    {
        if (!is_iterable($messages)) {
            $messages = [$messages];
        }
        foreach ($messages as $message) {
            parent::writeln($message, $type);
            $this->writeBuffer($message, \true, $type);
        }
    }
    /**
     * @return void
     */
    public function write(string|iterable $messages, bool $newline = \false, int $type = self::OUTPUT_NORMAL)
    {
        if (!is_iterable($messages)) {
            $messages = [$messages];
        }
        foreach ($messages as $message) {
            parent::write($message, $newline, $type);
            $this->writeBuffer($message, $newline, $type);
        }
    }
    /**
     * @return void
     */
    public function newLine(int $count = 1)
    {
        parent::newLine($count);
        $this->bufferedOutput->write(str_repeat("\n", $count));
    }
    /**
     * Returns a new instance which makes use of stderr if available.
     */
    public function getErrorStyle(): self
    {
        return new self($this->input, $this->getErrorOutput());
    }
    public function createTable(): Table
    {
        $output = $this->output instanceof ConsoleOutputInterface ? $this->output->section() : $this->output;
        $style = clone Table::getStyleDefinition('symfony-style-guide');
        $style->setCellHeaderFormat('<info>%s</info>');
        return (new Table($output))->setStyle($style);
    }
    private function getProgressBar(): ProgressBar
    {
        return $this->progressBar ?? throw new RuntimeException('The ProgressBar is not started.');
    }
    private function autoPrependBlock(): void
    {
        $chars = substr(str_replace(\PHP_EOL, "\n", $this->bufferedOutput->fetch()), -2);
        if (!isset($chars[0])) {
            $this->newLine();
            // empty history, so we should start with a new line.
            return;
        }
        // Prepend new line for each non LF chars (This means no blank line was output before)
        $this->newLine(2 - substr_count($chars, "\n"));
    }
    private function autoPrependText(): void
    {
        $fetched = $this->bufferedOutput->fetch();
        // Prepend new line if last char isn't EOL:
        if ($fetched && !str_ends_with($fetched, "\n")) {
            $this->newLine();
        }
    }
    private function writeBuffer(string $message, bool $newLine, int $type): void
    {
        // We need to know if the last chars are PHP_EOL
        $this->bufferedOutput->write($message, $newLine, $type);
    }
    private function createBlock(iterable $messages, ?string $type = null, ?string $style = null, string $prefix = ' ', bool $padding = \false, bool $escape = \false): array
    {
        $indentLength = 0;
        $prefixLength = Helper::width(Helper::removeDecoration($this->getFormatter(), $prefix));
        $lines = [];
        if (null !== $type) {
            $type = \sprintf('[%s] ', $type);
            $indentLength = Helper::width($type);
            $lineIndentation = str_repeat(' ', $indentLength);
        }
        // wrap and add newlines for each element
        $outputWrapper = new OutputWrapper();
        foreach ($messages as $key => $message) {
            if ($escape) {
                $message = OutputFormatter::escape($message);
            }
            $message = str_replace("\r\n", "\n", $message);
            $lines = array_merge($lines, explode("\n", $outputWrapper->wrap($message, $this->lineLength - $prefixLength - $indentLength, "\n")));
            if (\count($messages) > 1 && $key < \count($messages) - 1) {
                $lines[] = '';
            }
        }
        $firstLineIndex = 0;
        if ($padding && $this->isDecorated()) {
            $firstLineIndex = 1;
            array_unshift($lines, '');
            $lines[] = '';
        }
        foreach ($lines as $i => &$line) {
            if (null !== $type) {
                $line = $firstLineIndex === $i ? $type . $line : $lineIndentation . $line;
            }
            $line = $prefix . $line;
            $line .= str_repeat(' ', max($this->lineLength - Helper::width(Helper::removeDecoration($this->getFormatter(), $line)), 0));
            if ($style) {
                $line = \sprintf('<%s>%s</>', $style, $line);
            }
        }
        return $lines;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Console\Style;

/**
 * Output style helpers.
 *
 * @author Kevin Bond <kevinbond@gmail.com>
 */
interface StyleInterface
{
    /**
     * Formats a command title.
     *
     * @return void
     */
    public function title(string $message);
    /**
     * Formats a section title.
     *
     * @return void
     */
    public function section(string $message);
    /**
     * Formats a list.
     *
     * @return void
     */
    public function listing(array $elements);
    /**
     * Formats informational text.
     *
     * @return void
     */
    public function text(string|array $message);
    /**
     * Formats a success result bar.
     *
     * @return void
     */
    public function success(string|array $message);
    /**
     * Formats an error result bar.
     *
     * @return void
     */
    public function error(string|array $message);
    /**
     * Formats an warning result bar.
     *
     * @return void
     */
    public function warning(string|array $message);
    /**
     * Formats a note admonition.
     *
     * @return void
     */
    public function note(string|array $message);
    /**
     * Formats a caution admonition.
     *
     * @return void
     */
    public function caution(string|array $message);
    /**
     * Formats a table.
     *
     * @return void
     */
    public function table(array $headers, array $rows);
    /**
     * Asks a question.
     */
    public function ask(string $question, ?string $default = null, ?callable $validator = null): mixed;
    /**
     * Asks a question with the user input hidden.
     */
    public function askHidden(string $question, ?callable $validator = null): mixed;
    /**
     * Asks for confirmation.
     */
    public function confirm(string $question, bool $default = \true): bool;
    /**
     * Asks a choice question.
     */
    public function choice(string $question, array $choices, mixed $default = null): mixed;
    /**
     * Add newline(s).
     *
     * @return void
     */
    public function newLine(int $count = 1);
    /**
     * Starts the progress output.
     *
     * @return void
     */
    public function progressStart(int $max = 0);
    /**
     * Advances the progress output X steps.
     *
     * @return void
     */
    public function progressAdvance(int $step = 1);
    /**
     * Finishes the progress output.
     *
     * @return void
     */
    public function progressFinish();
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Console\Question;

use _ContaoManager\Symfony\Component\Console\Exception\InvalidArgumentException;
/**
 * Represents a choice question.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class ChoiceQuestion extends Question
{
    private array $choices;
    private bool $multiselect = \false;
    private string $prompt = ' > ';
    private string $errorMessage = 'Value "%s" is invalid';
    /**
     * @param string                                   $question The question to ask to the user
     * @param array<string|bool|int|float|\Stringable> $choices  The list of available choices
     * @param string|bool|int|float|null               $default  The default answer to return
     */
    public function __construct(string $question, array $choices, string|bool|int|float|null $default = null)
    {
        if (!$choices) {
            throw new \LogicException('Choice question must have at least 1 choice available.');
        }
        parent::__construct($question, $default);
        $this->choices = $choices;
        $this->setValidator($this->getDefaultValidator());
        $this->setAutocompleterValues($choices);
    }
    /**
     * @return array<string|bool|int|float|\Stringable>
     */
    public function getChoices(): array
    {
        return $this->choices;
    }
    /**
     * Sets multiselect option.
     *
     * When multiselect is set to true, multiple choices can be answered.
     *
     * @return $this
     */
    public function setMultiselect(bool $multiselect): static
    {
        $this->multiselect = $multiselect;
        $this->setValidator($this->getDefaultValidator());
        return $this;
    }
    /**
     * Returns whether the choices are multiselect.
     */
    public function isMultiselect(): bool
    {
        return $this->multiselect;
    }
    /**
     * Gets the prompt for choices.
     */
    public function getPrompt(): string
    {
        return $this->prompt;
    }
    /**
     * Sets the prompt for choices.
     *
     * @return $this
     */
    public function setPrompt(string $prompt): static
    {
        $this->prompt = $prompt;
        return $this;
    }
    /**
     * Sets the error message for invalid values.
     *
     * The error message has a string placeholder (%s) for the invalid value.
     *
     * @return $this
     */
    public function setErrorMessage(string $errorMessage): static
    {
        $this->errorMessage = $errorMessage;
        $this->setValidator($this->getDefaultValidator());
        return $this;
    }
    private function getDefaultValidator(): callable
    {
        $choices = $this->choices;
        $errorMessage = $this->errorMessage;
        $multiselect = $this->multiselect;
        $isAssoc = $this->isAssoc($choices);
        return function ($selected) use ($choices, $errorMessage, $multiselect, $isAssoc) {
            if ($multiselect) {
                // Check for a separated comma values
                if (!preg_match('/^[^,]+(?:,[^,]+)*$/', (string) $selected, $matches)) {
                    throw new InvalidArgumentException(\sprintf($errorMessage, $selected));
                }
                $selectedChoices = explode(',', (string) $selected);
            } else {
                $selectedChoices = [$selected];
            }
            if ($this->isTrimmable()) {
                foreach ($selectedChoices as $k => $v) {
                    $selectedChoices[$k] = trim((string) $v);
                }
            }
            $multiselectChoices = [];
            foreach ($selectedChoices as $value) {
                $results = [];
                foreach ($choices as $key => $choice) {
                    if ($choice === $value) {
                        $results[] = $key;
                    }
                }
                if (\count($results) > 1) {
                    throw new InvalidArgumentException(\sprintf('The provided answer is ambiguous. Value should be one of "%s".', implode('" or "', $results)));
                }
                $result = array_search($value, $choices);
                if (!$isAssoc) {
                    if (\false !== $result) {
                        $result = $choices[$result];
                    } elseif (isset($choices[$value])) {
                        $result = $choices[$value];
                    }
                } elseif (\false === $result && isset($choices[$value])) {
                    $result = $value;
                }
                if (\false === $result) {
                    throw new InvalidArgumentException(\sprintf($errorMessage, $value));
                }
                // For associative choices, consistently return the key as string:
                $multiselectChoices[] = $isAssoc ? (string) $result : $result;
            }
            if ($multiselect) {
                return $multiselectChoices;
            }
            return current($multiselectChoices);
        };
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Console\Question;

use _ContaoManager\Symfony\Component\Console\Exception\InvalidArgumentException;
use _ContaoManager\Symfony\Component\Console\Exception\LogicException;
/**
 * Represents a Question.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class Question
{
    private string $question;
    private ?int $attempts = null;
    private bool $hidden = \false;
    private bool $hiddenFallback = \true;
    private ?\Closure $autocompleterCallback = null;
    private ?\Closure $validator = null;
    private string|int|bool|float|null $default;
    private ?\Closure $normalizer = null;
    private bool $trimmable = \true;
    private bool $multiline = \false;
    /**
     * @param string                     $question The question to ask to the user
     * @param string|bool|int|float|null $default  The default answer to return if the user enters nothing
     */
    public function __construct(string $question, string|bool|int|float|null $default = null)
    {
        $this->question = $question;
        $this->default = $default;
    }
    /**
     * Returns the question.
     */
    public function getQuestion(): string
    {
        return $this->question;
    }
    /**
     * Returns the default answer.
     */
    public function getDefault(): string|bool|int|float|null
    {
        return $this->default;
    }
    /**
     * Returns whether the user response accepts newline characters.
     */
    public function isMultiline(): bool
    {
        return $this->multiline;
    }
    /**
     * Sets whether the user response should accept newline characters.
     *
     * @return $this
     */
    public function setMultiline(bool $multiline): static
    {
        $this->multiline = $multiline;
        return $this;
    }
    /**
     * Returns whether the user response must be hidden.
     */
    public function isHidden(): bool
    {
        return $this->hidden;
    }
    /**
     * Sets whether the user response must be hidden or not.
     *
     * @return $this
     *
     * @throws LogicException In case the autocompleter is also used
     */
    public function setHidden(bool $hidden): static
    {
        if ($this->autocompleterCallback) {
            throw new LogicException('A hidden question cannot use the autocompleter.');
        }
        $this->hidden = $hidden;
        return $this;
    }
    /**
     * In case the response cannot be hidden, whether to fallback on non-hidden question or not.
     */
    public function isHiddenFallback(): bool
    {
        return $this->hiddenFallback;
    }
    /**
     * Sets whether to fallback on non-hidden question if the response cannot be hidden.
     *
     * @return $this
     */
    public function setHiddenFallback(bool $fallback): static
    {
        $this->hiddenFallback = $fallback;
        return $this;
    }
    /**
     * Gets values for the autocompleter.
     */
    public function getAutocompleterValues(): ?iterable
    {
        $callback = $this->getAutocompleterCallback();
        return $callback ? $callback('') : null;
    }
    /**
     * Sets values for the autocompleter.
     *
     * @return $this
     *
     * @throws LogicException
     */
    public function setAutocompleterValues(?iterable $values): static
    {
        if (\is_array($values)) {
            $values = $this->isAssoc($values) ? array_merge(array_keys($values), array_values($values)) : array_values($values);
            $callback = static fn() => $values;
        } elseif ($values instanceof \Traversable) {
            $callback = static function () use ($values) {
                static $valueCache;
                return $valueCache ??= iterator_to_array($values, \false);
            };
        } else {
            $callback = null;
        }
        return $this->setAutocompleterCallback($callback);
    }
    /**
     * Gets the callback function used for the autocompleter.
     */
    public function getAutocompleterCallback(): ?callable
    {
        return $this->autocompleterCallback;
    }
    /**
     * Sets the callback function used for the autocompleter.
     *
     * The callback is passed the user input as argument and should return an iterable of corresponding suggestions.
     *
     * @return $this
     */
    public function setAutocompleterCallback(?callable $callback = null): static
    {
        if (1 > \func_num_args()) {
            trigger_deprecation('symfony/console', '6.2', 'Calling "%s()" without any arguments is deprecated, pass null explicitly instead.', __METHOD__);
        }
        if ($this->hidden && null !== $callback) {
            throw new LogicException('A hidden question cannot use the autocompleter.');
        }
        $this->autocompleterCallback = null === $callback ? null : $callback(...);
        return $this;
    }
    /**
     * Sets a validator for the question.
     *
     * @return $this
     */
    public function setValidator(?callable $validator = null): static
    {
        if (1 > \func_num_args()) {
            trigger_deprecation('symfony/console', '6.2', 'Calling "%s()" without any arguments is deprecated, pass null explicitly instead.', __METHOD__);
        }
        $this->validator = null === $validator ? null : $validator(...);
        return $this;
    }
    /**
     * Gets the validator for the question.
     */
    public function getValidator(): ?callable
    {
        return $this->validator;
    }
    /**
     * Sets the maximum number of attempts.
     *
     * Null means an unlimited number of attempts.
     *
     * @return $this
     *
     * @throws InvalidArgumentException in case the number of attempts is invalid
     */
    public function setMaxAttempts(?int $attempts): static
    {
        if (null !== $attempts && $attempts < 1) {
            throw new InvalidArgumentException('Maximum number of attempts must be a positive value.');
        }
        $this->attempts = $attempts;
        return $this;
    }
    /**
     * Gets the maximum number of attempts.
     *
     * Null means an unlimited number of attempts.
     */
    public function getMaxAttempts(): ?int
    {
        return $this->attempts;
    }
    /**
     * Sets a normalizer for the response.
     *
     * The normalizer can be a callable (a string), a closure or a class implementing __invoke.
     *
     * @return $this
     */
    public function setNormalizer(callable $normalizer): static
    {
        $this->normalizer = $normalizer(...);
        return $this;
    }
    /**
     * Gets the normalizer for the response.
     *
     * The normalizer can ba a callable (a string), a closure or a class implementing __invoke.
     */
    public function getNormalizer(): ?callable
    {
        return $this->normalizer;
    }
    /**
     * @return bool
     */
    protected function isAssoc(array $array)
    {
        return (bool) \count(array_filter(array_keys($array), 'is_string'));
    }
    public function isTrimmable(): bool
    {
        return $this->trimmable;
    }
    /**
     * @return $this
     */
    public function setTrimmable(bool $trimmable): static
    {
        $this->trimmable = $trimmable;
        return $this;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Console\Question;

/**
 * Represents a yes/no question.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class ConfirmationQuestion extends Question
{
    private string $trueAnswerRegex;
    /**
     * @param string $question        The question to ask to the user
     * @param bool   $default         The default answer to return, true or false
     * @param string $trueAnswerRegex A regex to match the "yes" answer
     */
    public function __construct(string $question, bool $default = \true, string $trueAnswerRegex = '/^y/i')
    {
        parent::__construct($question, $default);
        $this->trueAnswerRegex = $trueAnswerRegex;
        $this->setNormalizer($this->getDefaultNormalizer());
    }
    /**
     * Returns the default answer normalizer.
     */
    private function getDefaultNormalizer(): callable
    {
        $default = $this->getDefault();
        $regex = $this->trueAnswerRegex;
        return function ($answer) use ($default, $regex) {
            if (\is_bool($answer)) {
                return $answer;
            }
            $answerIsTrue = (bool) preg_match($regex, $answer);
            if (\false === $default) {
                return $answer && $answerIsTrue;
            }
            return '' === $answer || $answerIsTrue;
        };
    }
}
Console Component
=================

The Console component eases the creation of beautiful and testable command line
interfaces.

Sponsor
-------

The Console component for Symfony 6.4 is [backed][1] by [Les-Tilleuls.coop][2].

Les-Tilleuls.coop is a team of 70+ Symfony experts who can help you design, develop and
fix your projects. They provide a wide range of professional services including development,
consulting, coaching, training and audits. They also are highly skilled in JS, Go and DevOps.
They are a worker cooperative!

Help Symfony by [sponsoring][3] its development!

Resources
---------

 * [Documentation](https://symfony.com/doc/current/components/console.html)
 * [Contributing](https://symfony.com/doc/current/contributing/index.html)
 * [Report issues](https://github.com/symfony/symfony/issues) and
   [send Pull Requests](https://github.com/symfony/symfony/pulls)
   in the [main Symfony repository](https://github.com/symfony/symfony)

Credits
-------

`Resources/bin/hiddeninput.exe` is a third party binary provided within this
component. Find sources and license at https://github.com/Seldaek/hidden-input.

[1]: https://symfony.com/backers
[2]: https://les-tilleuls.coop
[3]: https://symfony.com/sponsor
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Console\Formatter;

use _ContaoManager\Symfony\Component\Console\Color;
/**
 * Formatter style class for defining styles.
 *
 * @author Konstantin Kudryashov <ever.zet@gmail.com>
 */
class OutputFormatterStyle implements OutputFormatterStyleInterface
{
    private Color $color;
    private string $foreground;
    private string $background;
    private array $options;
    private ?string $href = null;
    private bool $handlesHrefGracefully;
    /**
     * Initializes output formatter style.
     *
     * @param string|null $foreground The style foreground color name
     * @param string|null $background The style background color name
     */
    public function __construct(?string $foreground = null, ?string $background = null, array $options = [])
    {
        $this->color = new Color($this->foreground = $foreground ?: '', $this->background = $background ?: '', $this->options = $options);
    }
    /**
     * @return void
     */
    public function setForeground(?string $color = null)
    {
        if (1 > \func_num_args()) {
            trigger_deprecation('symfony/console', '6.2', 'Calling "%s()" without any arguments is deprecated, pass null explicitly instead.', __METHOD__);
        }
        $this->color = new Color($this->foreground = $color ?: '', $this->background, $this->options);
    }
    /**
     * @return void
     */
    public function setBackground(?string $color = null)
    {
        if (1 > \func_num_args()) {
            trigger_deprecation('symfony/console', '6.2', 'Calling "%s()" without any arguments is deprecated, pass null explicitly instead.', __METHOD__);
        }
        $this->color = new Color($this->foreground, $this->background = $color ?: '', $this->options);
    }
    public function setHref(string $url): void
    {
        $this->href = $url;
    }
    /**
     * @return void
     */
    public function setOption(string $option)
    {
        $this->options[] = $option;
        $this->color = new Color($this->foreground, $this->background, $this->options);
    }
    /**
     * @return void
     */
    public function unsetOption(string $option)
    {
        $pos = array_search($option, $this->options);
        if (\false !== $pos) {
            unset($this->options[$pos]);
        }
        $this->color = new Color($this->foreground, $this->background, $this->options);
    }
    /**
     * @return void
     */
    public function setOptions(array $options)
    {
        $this->color = new Color($this->foreground, $this->background, $this->options = $options);
    }
    public function apply(string $text): string
    {
        $this->handlesHrefGracefully ??= 'JetBrains-JediTerm' !== getenv('TERMINAL_EMULATOR') && (!getenv('KONSOLE_VERSION') || (int) getenv('KONSOLE_VERSION') > 201100) && !isset($_SERVER['IDEA_INITIAL_DIRECTORY']);
        if (null !== $this->href && $this->handlesHrefGracefully) {
            $text = "\x1b]8;;{$this->href}\x1b\\{$text}\x1b]8;;\x1b\\";
        }
        return $this->color->apply($text);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Console\Formatter;

/**
 * Formatter style interface for defining styles.
 *
 * @author Konstantin Kudryashov <ever.zet@gmail.com>
 */
interface OutputFormatterStyleInterface
{
    /**
     * Sets style foreground color.
     *
     * @return void
     */
    public function setForeground(?string $color);
    /**
     * Sets style background color.
     *
     * @return void
     */
    public function setBackground(?string $color);
    /**
     * Sets some specific style option.
     *
     * @return void
     */
    public function setOption(string $option);
    /**
     * Unsets some specific style option.
     *
     * @return void
     */
    public function unsetOption(string $option);
    /**
     * Sets multiple style options at once.
     *
     * @return void
     */
    public function setOptions(array $options);
    /**
     * Applies the style to a given text.
     */
    public function apply(string $text): string;
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Console\Formatter;

/**
 * @author Tien Xuan Vo <tien.xuan.vo@gmail.com>
 */
final class NullOutputFormatterStyle implements OutputFormatterStyleInterface
{
    public function apply(string $text): string
    {
        return $text;
    }
    public function setBackground(?string $color = null): void
    {
        if (1 > \func_num_args()) {
            trigger_deprecation('symfony/console', '6.2', 'Calling "%s()" without any arguments is deprecated, pass null explicitly instead.', __METHOD__);
        }
        // do nothing
    }
    public function setForeground(?string $color = null): void
    {
        if (1 > \func_num_args()) {
            trigger_deprecation('symfony/console', '6.2', 'Calling "%s()" without any arguments is deprecated, pass null explicitly instead.', __METHOD__);
        }
        // do nothing
    }
    public function setOption(string $option): void
    {
        // do nothing
    }
    public function setOptions(array $options): void
    {
        // do nothing
    }
    public function unsetOption(string $option): void
    {
        // do nothing
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Console\Formatter;

/**
 * Formatter interface for console output.
 *
 * @author Konstantin Kudryashov <ever.zet@gmail.com>
 */
interface OutputFormatterInterface
{
    /**
     * Sets the decorated flag.
     *
     * @return void
     */
    public function setDecorated(bool $decorated);
    /**
     * Whether the output will decorate messages.
     */
    public function isDecorated(): bool;
    /**
     * Sets a new style.
     *
     * @return void
     */
    public function setStyle(string $name, OutputFormatterStyleInterface $style);
    /**
     * Checks if output formatter has style with specified name.
     */
    public function hasStyle(string $name): bool;
    /**
     * Gets style options from style with specified name.
     *
     * @throws \InvalidArgumentException When style isn't defined
     */
    public function getStyle(string $name): OutputFormatterStyleInterface;
    /**
     * Formats a message according to the given styles.
     */
    public function format(?string $message): ?string;
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Console\Formatter;

use _ContaoManager\Symfony\Component\Console\Exception\InvalidArgumentException;
use _ContaoManager\Symfony\Component\Console\Helper\Helper;
use function _ContaoManager\Symfony\Component\String\b;
/**
 * Formatter class for console output.
 *
 * @author Konstantin Kudryashov <ever.zet@gmail.com>
 * @author Roland Franssen <franssen.roland@gmail.com>
 */
class OutputFormatter implements WrappableOutputFormatterInterface
{
    private bool $decorated;
    private array $styles = [];
    private OutputFormatterStyleStack $styleStack;
    public function __clone()
    {
        $this->styleStack = clone $this->styleStack;
        foreach ($this->styles as $key => $value) {
            $this->styles[$key] = clone $value;
        }
    }
    /**
     * Escapes "<" and ">" special chars in given text.
     */
    public static function escape(string $text): string
    {
        $text = preg_replace('/([^\\\\]|^)([<>])/', '$1\\\\$2', $text);
        return self::escapeTrailingBackslash($text);
    }
    /**
     * Escapes trailing "\" in given text.
     *
     * @internal
     */
    public static function escapeTrailingBackslash(string $text): string
    {
        if (str_ends_with($text, '\\')) {
            $len = \strlen($text);
            $text = rtrim($text, '\\');
            $text = str_replace("\x00", '', $text);
            $text .= str_repeat("\x00", $len - \strlen($text));
        }
        return $text;
    }
    /**
     * Initializes console output formatter.
     *
     * @param OutputFormatterStyleInterface[] $styles Array of "name => FormatterStyle" instances
     */
    public function __construct(bool $decorated = \false, array $styles = [])
    {
        $this->decorated = $decorated;
        $this->setStyle('error', new OutputFormatterStyle('white', 'red'));
        $this->setStyle('info', new OutputFormatterStyle('green'));
        $this->setStyle('comment', new OutputFormatterStyle('yellow'));
        $this->setStyle('question', new OutputFormatterStyle('black', 'cyan'));
        foreach ($styles as $name => $style) {
            $this->setStyle($name, $style);
        }
        $this->styleStack = new OutputFormatterStyleStack();
    }
    /**
     * @return void
     */
    public function setDecorated(bool $decorated)
    {
        $this->decorated = $decorated;
    }
    public function isDecorated(): bool
    {
        return $this->decorated;
    }
    /**
     * @return void
     */
    public function setStyle(string $name, OutputFormatterStyleInterface $style)
    {
        $this->styles[strtolower($name)] = $style;
    }
    public function hasStyle(string $name): bool
    {
        return isset($this->styles[strtolower($name)]);
    }
    public function getStyle(string $name): OutputFormatterStyleInterface
    {
        if (!$this->hasStyle($name)) {
            throw new InvalidArgumentException(\sprintf('Undefined style: "%s".', $name));
        }
        return $this->styles[strtolower($name)];
    }
    public function format(?string $message): ?string
    {
        return $this->formatAndWrap($message, 0);
    }
    /**
     * @return string
     */
    public function formatAndWrap(?string $message, int $width)
    {
        if (null === $message) {
            return '';
        }
        // For ASCII-only strings, byte positions equal character positions,
        // so we can use native strlen/substr which is much faster than Helper::length/substr.
        $isAscii = !preg_match('/[\x80-\xFF]/', $message);
        $offset = 0;
        $output = '';
        $openTagRegex = '[a-z](?:[^\\\\<>]*+ | \\\\.)*';
        $closeTagRegex = '[a-z][^<>]*+';
        $currentLineLength = 0;
        preg_match_all("#<(({$openTagRegex}) | /({$closeTagRegex})?)>#ix", $message, $matches, \PREG_OFFSET_CAPTURE);
        foreach ($matches[0] as $i => $match) {
            $pos = $match[1];
            $text = $match[0];
            if (0 != $pos && '\\' == $message[$pos - 1]) {
                continue;
            }
            if ($isAscii) {
                // For ASCII, byte position = character position, no conversion needed
                $output .= $this->applyCurrentStyle(substr($message, $offset, $pos - $offset), $output, $width, $currentLineLength);
                $offset = $pos + \strlen($text);
            } else {
                // convert byte position to character position.
                $pos = Helper::length(substr($message, 0, $pos));
                // add the text up to the next tag
                $output .= $this->applyCurrentStyle(Helper::substr($message, $offset, $pos - $offset), $output, $width, $currentLineLength);
                $offset = $pos + Helper::length($text);
            }
            // opening tag?
            if ($open = '/' !== $text[1]) {
                $tag = $matches[1][$i][0];
            } else {
                $tag = $matches[3][$i][0] ?? '';
            }
            if (!$open && !$tag) {
                // </>
                $this->styleStack->pop();
            } elseif (null === $style = $this->createStyleFromString($tag)) {
                $output .= $this->applyCurrentStyle($text, $output, $width, $currentLineLength);
            } elseif ($open) {
                $this->styleStack->push($style);
            } else {
                $this->styleStack->pop($style);
            }
        }
        $output .= $this->applyCurrentStyle($isAscii ? substr($message, $offset) : Helper::substr($message, $offset), $output, $width, $currentLineLength);
        return strtr($output, ["\x00" => '\\', '\<' => '<', '\>' => '>']);
    }
    public function getStyleStack(): OutputFormatterStyleStack
    {
        return $this->styleStack;
    }
    /**
     * Tries to create new style instance from string.
     */
    private function createStyleFromString(string $string): ?OutputFormatterStyleInterface
    {
        if (isset($this->styles[$string])) {
            return $this->styles[$string];
        }
        if (!preg_match_all('/([^=]+)=([^;]+)(;|$)/', $string, $matches, \PREG_SET_ORDER)) {
            return null;
        }
        $style = new OutputFormatterStyle();
        foreach ($matches as $match) {
            array_shift($match);
            $match[0] = strtolower($match[0]);
            if ('fg' == $match[0]) {
                $style->setForeground(strtolower($match[1]));
            } elseif ('bg' == $match[0]) {
                $style->setBackground(strtolower($match[1]));
            } elseif ('href' === $match[0]) {
                $url = preg_replace('{\\\\([<>])}', '$1', $match[1]);
                $style->setHref($url);
            } elseif ('options' === $match[0]) {
                preg_match_all('([^,;]+)', strtolower($match[1]), $options);
                $options = array_shift($options);
                foreach ($options as $option) {
                    $style->setOption($option);
                }
            } else {
                return null;
            }
        }
        return $style;
    }
    /**
     * Applies current style from stack to text, if must be applied.
     */
    private function applyCurrentStyle(string $text, string $current, int $width, int &$currentLineLength): string
    {
        if ('' === $text) {
            return '';
        }
        if (!$width) {
            return $this->isDecorated() ? $this->styleStack->getCurrent()->apply($text) : $text;
        }
        if (!$currentLineLength && '' !== $current) {
            $text = ltrim($text);
        }
        if ($currentLineLength) {
            $lines = explode("\n", $text, 2);
            $prefix = Helper::substr($lines[0], 0, $i = $width - $currentLineLength) . "\n";
            $text = Helper::substr($lines[0], $i);
            if (isset($lines[1])) {
                // $prefix may contain the full first line in which the \n is already a part of $prefix.
                if ('' !== $text) {
                    $text .= "\n";
                }
                $text .= $lines[1];
            }
        } else {
            $prefix = '';
        }
        preg_match('~(\n)$~', $text, $matches);
        $text = $prefix . $this->addLineBreaks($text, $width);
        $text = rtrim($text, "\n") . ($matches[1] ?? '');
        if (!$currentLineLength && '' !== $current && !str_ends_with($current, "\n")) {
            $text = "\n" . $text;
        }
        $lines = explode("\n", $text);
        foreach ($lines as $i => $line) {
            $currentLineLength = 0 === $i ? $currentLineLength + Helper::length($line) : Helper::length($line);
            if ($width <= $currentLineLength) {
                $currentLineLength = 0;
            }
        }
        if ($this->isDecorated()) {
            foreach ($lines as $i => $line) {
                $lines[$i] = $this->styleStack->getCurrent()->apply($line);
            }
        }
        return implode("\n", $lines);
    }
    private function addLineBreaks(string $text, int $width): string
    {
        $encoding = mb_detect_encoding($text, null, \true) ?: 'UTF-8';
        return b($text)->toUnicodeString($encoding)->wordwrap($width, "\n", \true)->toByteString($encoding);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Console\Formatter;

/**
 * @author Tien Xuan Vo <tien.xuan.vo@gmail.com>
 */
final class NullOutputFormatter implements OutputFormatterInterface
{
    private NullOutputFormatterStyle $style;
    public function format(?string $message): ?string
    {
        return null;
    }
    public function getStyle(string $name): OutputFormatterStyleInterface
    {
        // to comply with the interface we must return a OutputFormatterStyleInterface
        return $this->style ??= new NullOutputFormatterStyle();
    }
    public function hasStyle(string $name): bool
    {
        return \false;
    }
    public function isDecorated(): bool
    {
        return \false;
    }
    public function setDecorated(bool $decorated): void
    {
        // do nothing
    }
    public function setStyle(string $name, OutputFormatterStyleInterface $style): void
    {
        // do nothing
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Console\Formatter;

/**
 * Formatter interface for console output that supports word wrapping.
 *
 * @author Roland Franssen <franssen.roland@gmail.com>
 */
interface WrappableOutputFormatterInterface extends OutputFormatterInterface
{
    /**
     * Formats a message according to the given styles, wrapping at `$width` (0 means no wrapping).
     *
     * @return string
     */
    public function formatAndWrap(?string $message, int $width);
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Console\Formatter;

use _ContaoManager\Symfony\Component\Console\Exception\InvalidArgumentException;
use _ContaoManager\Symfony\Contracts\Service\ResetInterface;
/**
 * @author Jean-François Simon <contact@jfsimon.fr>
 */
class OutputFormatterStyleStack implements ResetInterface
{
    /**
     * @var OutputFormatterStyleInterface[]
     */
    private array $styles = [];
    private OutputFormatterStyleInterface $emptyStyle;
    public function __construct(?OutputFormatterStyleInterface $emptyStyle = null)
    {
        $this->emptyStyle = $emptyStyle ?? new OutputFormatterStyle();
        $this->reset();
    }
    /**
     * Resets stack (ie. empty internal arrays).
     *
     * @return void
     */
    public function reset()
    {
        $this->styles = [];
    }
    /**
     * Pushes a style in the stack.
     *
     * @return void
     */
    public function push(OutputFormatterStyleInterface $style)
    {
        $this->styles[] = $style;
    }
    /**
     * Pops a style from the stack.
     *
     * @throws InvalidArgumentException When style tags incorrectly nested
     */
    public function pop(?OutputFormatterStyleInterface $style = null): OutputFormatterStyleInterface
    {
        if (!$this->styles) {
            return $this->emptyStyle;
        }
        if (null === $style) {
            return array_pop($this->styles);
        }
        foreach (array_reverse($this->styles, \true) as $index => $stackedStyle) {
            if ($style->apply('') === $stackedStyle->apply('')) {
                $this->styles = \array_slice($this->styles, 0, $index);
                return $stackedStyle;
            }
        }
        throw new InvalidArgumentException('Incorrectly nested style tag found.');
    }
    /**
     * Computes current style with stacks top codes.
     */
    public function getCurrent(): OutputFormatterStyleInterface
    {
        if (!$this->styles) {
            return $this->emptyStyle;
        }
        return $this->styles[\count($this->styles) - 1];
    }
    /**
     * @return $this
     */
    public function setEmptyStyle(OutputFormatterStyleInterface $emptyStyle): static
    {
        $this->emptyStyle = $emptyStyle;
        return $this;
    }
    public function getEmptyStyle(): OutputFormatterStyleInterface
    {
        return $this->emptyStyle;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Console\Messenger;

use _ContaoManager\Symfony\Component\Console\Exception\RunCommandFailedException;
/**
 * @author Kevin Bond <kevinbond@gmail.com>
 */
class RunCommandMessage implements \Stringable
{
    /**
     * @param bool $throwOnFailure  If the command has a non-zero exit code, throw {@see RunCommandFailedException}
     * @param bool $catchExceptions @see Application::setCatchExceptions()
     */
    public function __construct(public readonly string $input, public readonly bool $throwOnFailure = \true, public readonly bool $catchExceptions = \false)
    {
    }
    public function __toString(): string
    {
        return $this->input;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Console\Messenger;

/**
 * @author Kevin Bond <kevinbond@gmail.com>
 */
final class RunCommandContext
{
    public function __construct(public readonly RunCommandMessage $message, public readonly int $exitCode, public readonly string $output)
    {
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Console\Messenger;

use _ContaoManager\Symfony\Component\Console\Application;
use _ContaoManager\Symfony\Component\Console\Command\Command;
use _ContaoManager\Symfony\Component\Console\Exception\RunCommandFailedException;
use _ContaoManager\Symfony\Component\Console\Input\StringInput;
use _ContaoManager\Symfony\Component\Console\Output\BufferedOutput;
use _ContaoManager\Symfony\Component\Messenger\Exception\RecoverableExceptionInterface;
use _ContaoManager\Symfony\Component\Messenger\Exception\UnrecoverableExceptionInterface;
/**
 * @author Kevin Bond <kevinbond@gmail.com>
 */
final class RunCommandMessageHandler
{
    public function __construct(private readonly Application $application)
    {
    }
    public function __invoke(RunCommandMessage $message): RunCommandContext
    {
        $input = new StringInput($message->input);
        $output = new BufferedOutput();
        $this->application->setCatchExceptions($message->catchExceptions);
        try {
            $exitCode = $this->application->run($input, $output);
        } catch (UnrecoverableExceptionInterface|RecoverableExceptionInterface $e) {
            throw $e;
        } catch (\Throwable $e) {
            throw new RunCommandFailedException($e, new RunCommandContext($message, Command::FAILURE, $output->fetch()));
        }
        if ($message->throwOnFailure && Command::SUCCESS !== $exitCode) {
            throw new RunCommandFailedException(\sprintf('Command "%s" exited with code "%s".', $message->input, $exitCode), new RunCommandContext($message, $exitCode, $output->fetch()));
        }
        return new RunCommandContext($message, $exitCode, $output->fetch());
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Console;

use _ContaoManager\Symfony\Component\Console\Exception\InvalidArgumentException;
/**
 * @author Fabien Potencier <fabien@symfony.com>
 */
final class Color
{
    private const COLORS = ['black' => 0, 'red' => 1, 'green' => 2, 'yellow' => 3, 'blue' => 4, 'magenta' => 5, 'cyan' => 6, 'white' => 7, 'default' => 9];
    private const BRIGHT_COLORS = ['gray' => 0, 'bright-red' => 1, 'bright-green' => 2, 'bright-yellow' => 3, 'bright-blue' => 4, 'bright-magenta' => 5, 'bright-cyan' => 6, 'bright-white' => 7];
    private const AVAILABLE_OPTIONS = ['bold' => ['set' => 1, 'unset' => 22], 'underscore' => ['set' => 4, 'unset' => 24], 'blink' => ['set' => 5, 'unset' => 25], 'reverse' => ['set' => 7, 'unset' => 27], 'conceal' => ['set' => 8, 'unset' => 28]];
    private string $foreground;
    private string $background;
    private array $options = [];
    public function __construct(string $foreground = '', string $background = '', array $options = [])
    {
        $this->foreground = $this->parseColor($foreground);
        $this->background = $this->parseColor($background, \true);
        foreach ($options as $option) {
            if (!isset(self::AVAILABLE_OPTIONS[$option])) {
                throw new InvalidArgumentException(\sprintf('Invalid option specified: "%s". Expected one of (%s).', $option, implode(', ', array_keys(self::AVAILABLE_OPTIONS))));
            }
            $this->options[$option] = self::AVAILABLE_OPTIONS[$option];
        }
    }
    public function apply(string $text): string
    {
        return $this->set() . $text . $this->unset();
    }
    public function set(): string
    {
        $setCodes = [];
        if ('' !== $this->foreground) {
            $setCodes[] = $this->foreground;
        }
        if ('' !== $this->background) {
            $setCodes[] = $this->background;
        }
        foreach ($this->options as $option) {
            $setCodes[] = $option['set'];
        }
        if (0 === \count($setCodes)) {
            return '';
        }
        return \sprintf("\x1b[%sm", implode(';', $setCodes));
    }
    public function unset(): string
    {
        $unsetCodes = [];
        if ('' !== $this->foreground) {
            $unsetCodes[] = 39;
        }
        if ('' !== $this->background) {
            $unsetCodes[] = 49;
        }
        foreach ($this->options as $option) {
            $unsetCodes[] = $option['unset'];
        }
        if (0 === \count($unsetCodes)) {
            return '';
        }
        return \sprintf("\x1b[%sm", implode(';', $unsetCodes));
    }
    private function parseColor(string $color, bool $background = \false): string
    {
        if ('' === $color) {
            return '';
        }
        if ('#' === $color[0]) {
            return ($background ? '4' : '3') . Terminal::getColorMode()->convertFromHexToAnsiColorCode($color);
        }
        if (isset(self::COLORS[$color])) {
            return ($background ? '4' : '3') . self::COLORS[$color];
        }
        if (isset(self::BRIGHT_COLORS[$color])) {
            return ($background ? '10' : '9') . self::BRIGHT_COLORS[$color];
        }
        throw new InvalidArgumentException(\sprintf('Invalid "%s" color; expected one of (%s).', $color, implode(', ', array_merge(array_keys(self::COLORS), array_keys(self::BRIGHT_COLORS)))));
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Console\SignalRegistry;

final class SignalRegistry
{
    /**
     * @var array<int, array<callable>>
     */
    private array $signalHandlers = [];
    /**
     * @var array<array<int, array<callable>>>
     */
    private array $stack = [];
    /**
     * @var array<int, callable|int|string>
     */
    private array $originalHandlers = [];
    public function __construct()
    {
        if (\function_exists('pcntl_async_signals')) {
            pcntl_async_signals(\true);
        }
    }
    public function register(int $signal, callable $signalHandler): void
    {
        $previous = pcntl_signal_get_handler($signal);
        if (!isset($this->originalHandlers[$signal])) {
            $this->originalHandlers[$signal] = $previous;
        }
        if (!isset($this->signalHandlers[$signal])) {
            if (\is_callable($previous) && [$this, 'handle'] !== $previous) {
                $this->signalHandlers[$signal][] = $previous;
            }
        }
        $this->signalHandlers[$signal][] = $signalHandler;
        pcntl_signal($signal, [$this, 'handle']);
    }
    public static function isSupported(): bool
    {
        return \function_exists('pcntl_signal');
    }
    /**
     * @internal
     */
    public function handle(int $signal): void
    {
        $count = \count($this->signalHandlers[$signal]);
        foreach ($this->signalHandlers[$signal] as $i => $signalHandler) {
            $hasNext = $i !== $count - 1;
            $signalHandler($signal, $hasNext);
        }
    }
    /**
     * Pushes the current active handlers onto the stack and clears the active list.
     *
     * This prepares the registry for a new set of handlers within a specific scope.
     *
     * @internal
     */
    public function pushCurrentHandlers(): void
    {
        $this->stack[] = $this->signalHandlers;
        $this->signalHandlers = [];
    }
    /**
     * Restores the previous handlers from the stack, making them active.
     *
     * This also restores the original OS-level signal handler if no
     * more handlers are registered for a signal that was just popped.
     *
     * @internal
     */
    public function popPreviousHandlers(): void
    {
        $popped = $this->signalHandlers;
        $this->signalHandlers = array_pop($this->stack) ?? [];
        // Restore OS handler if no more Symfony handlers for this signal
        foreach ($popped as $signal => $handlers) {
            if (!($this->signalHandlers[$signal] ?? \false) && isset($this->originalHandlers[$signal])) {
                pcntl_signal($signal, $this->originalHandlers[$signal]);
            }
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Console\SignalRegistry;

/**
 * @author Grégoire Pineau <lyrixx@lyrixx.info>
 */
class SignalMap
{
    private static array $map;
    public static function getSignalName(int $signal): ?string
    {
        if (!\extension_loaded('pcntl')) {
            return null;
        }
        if (!isset(self::$map)) {
            $r = new \ReflectionExtension('pcntl');
            $c = $r->getConstants();
            $map = array_filter($c, fn($k) => str_starts_with($k, 'SIG') && !str_starts_with($k, 'SIG_') && 'SIGBABY' !== $k, \ARRAY_FILTER_USE_KEY);
            self::$map = array_flip($map);
        }
        return self::$map[$signal] ?? null;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Console;

use _ContaoManager\Symfony\Component\Console\Command\Command;
use _ContaoManager\Symfony\Component\Console\Input\InputInterface;
use _ContaoManager\Symfony\Component\Console\Output\OutputInterface;
/**
 * @author Grégoire Pineau <lyrixx@lyrixx.info>
 */
class SingleCommandApplication extends Command
{
    private string $version = 'UNKNOWN';
    private bool $autoExit = \true;
    private bool $running = \false;
    /**
     * @return $this
     */
    public function setVersion(string $version): static
    {
        $this->version = $version;
        return $this;
    }
    /**
     * @final
     *
     * @return $this
     */
    public function setAutoExit(bool $autoExit): static
    {
        $this->autoExit = $autoExit;
        return $this;
    }
    public function run(?InputInterface $input = null, ?OutputInterface $output = null): int
    {
        if ($this->running) {
            return parent::run($input, $output);
        }
        // We use the command name as the application name
        $application = new Application($this->getName() ?: 'UNKNOWN', $this->version);
        $application->setAutoExit($this->autoExit);
        // Fix the usage of the command displayed with "--help"
        $this->setName($_SERVER['argv'][0]);
        $application->add($this);
        $application->setDefaultCommand($this->getName(), \true);
        $this->running = \true;
        try {
            $ret = $application->run($input, $output);
        } finally {
            $this->running = \false;
        }
        return $ret ?? 1;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Console\CommandLoader;

use _ContaoManager\Symfony\Component\Console\Command\Command;
use _ContaoManager\Symfony\Component\Console\Exception\CommandNotFoundException;
/**
 * @author Robin Chalas <robin.chalas@gmail.com>
 */
interface CommandLoaderInterface
{
    /**
     * Loads a command.
     *
     * @throws CommandNotFoundException
     */
    public function get(string $name): Command;
    /**
     * Checks if a command exists.
     */
    public function has(string $name): bool;
    /**
     * @return string[]
     */
    public function getNames(): array;
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Console\CommandLoader;

use _ContaoManager\Psr\Container\ContainerInterface;
use _ContaoManager\Symfony\Component\Console\Command\Command;
use _ContaoManager\Symfony\Component\Console\Exception\CommandNotFoundException;
/**
 * Loads commands from a PSR-11 container.
 *
 * @author Robin Chalas <robin.chalas@gmail.com>
 */
class ContainerCommandLoader implements CommandLoaderInterface
{
    private ContainerInterface $container;
    private array $commandMap;
    /**
     * @param array $commandMap An array with command names as keys and service ids as values
     */
    public function __construct(ContainerInterface $container, array $commandMap)
    {
        $this->container = $container;
        $this->commandMap = $commandMap;
    }
    public function get(string $name): Command
    {
        if (!$this->has($name)) {
            throw new CommandNotFoundException(\sprintf('Command "%s" does not exist.', $name));
        }
        return $this->container->get($this->commandMap[$name]);
    }
    public function has(string $name): bool
    {
        return isset($this->commandMap[$name]) && $this->container->has($this->commandMap[$name]);
    }
    public function getNames(): array
    {
        return array_keys($this->commandMap);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Console\CommandLoader;

use _ContaoManager\Symfony\Component\Console\Command\Command;
use _ContaoManager\Symfony\Component\Console\Exception\CommandNotFoundException;
/**
 * A simple command loader using factories to instantiate commands lazily.
 *
 * @author Maxime Steinhausser <maxime.steinhausser@gmail.com>
 */
class FactoryCommandLoader implements CommandLoaderInterface
{
    private array $factories;
    /**
     * @param callable[] $factories Indexed by command names
     */
    public function __construct(array $factories)
    {
        $this->factories = $factories;
    }
    public function has(string $name): bool
    {
        return isset($this->factories[$name]);
    }
    public function get(string $name): Command
    {
        if (!isset($this->factories[$name])) {
            throw new CommandNotFoundException(\sprintf('Command "%s" does not exist.', $name));
        }
        $factory = $this->factories[$name];
        return $factory();
    }
    public function getNames(): array
    {
        return array_keys($this->factories);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Console\Descriptor;

use _ContaoManager\Symfony\Component\Console\Application;
use _ContaoManager\Symfony\Component\Console\Command\Command;
use _ContaoManager\Symfony\Component\Console\Formatter\OutputFormatter;
use _ContaoManager\Symfony\Component\Console\Helper\Helper;
use _ContaoManager\Symfony\Component\Console\Input\InputArgument;
use _ContaoManager\Symfony\Component\Console\Input\InputDefinition;
use _ContaoManager\Symfony\Component\Console\Input\InputOption;
/**
 * Text descriptor.
 *
 * @author Jean-François Simon <contact@jfsimon.fr>
 *
 * @internal
 */
class TextDescriptor extends Descriptor
{
    protected function describeInputArgument(InputArgument $argument, array $options = []): void
    {
        if (null !== $argument->getDefault() && (!\is_array($argument->getDefault()) || \count($argument->getDefault()))) {
            $default = \sprintf('<comment> [default: %s]</comment>', $this->formatDefaultValue($argument->getDefault()));
        } else {
            $default = '';
        }
        $totalWidth = $options['total_width'] ?? Helper::width($argument->getName());
        $spacingWidth = $totalWidth - \strlen($argument->getName());
        $this->writeText(\sprintf(
            '  <info>%s</info>  %s%s%s',
            $argument->getName(),
            str_repeat(' ', $spacingWidth),
            // + 4 = 2 spaces before <info>, 2 spaces after </info>
            preg_replace('/\s*[\r\n]\s*/', "\n" . str_repeat(' ', $totalWidth + 4), $argument->getDescription()),
            $default
        ), $options);
    }
    protected function describeInputOption(InputOption $option, array $options = []): void
    {
        if ($option->acceptValue() && null !== $option->getDefault() && (!\is_array($option->getDefault()) || \count($option->getDefault()))) {
            $default = \sprintf('<comment> [default: %s]</comment>', $this->formatDefaultValue($option->getDefault()));
        } else {
            $default = '';
        }
        $value = '';
        if ($option->acceptValue()) {
            $value = '=' . strtoupper($option->getName());
            if ($option->isValueOptional()) {
                $value = '[' . $value . ']';
            }
        }
        $totalWidth = $options['total_width'] ?? $this->calculateTotalWidthForOptions([$option]);
        $synopsis = \sprintf('%s%s', $option->getShortcut() ? \sprintf('-%s, ', $option->getShortcut()) : '    ', \sprintf($option->isNegatable() ? '--%1$s|--no-%1$s' : '--%1$s%2$s', $option->getName(), $value));
        $spacingWidth = $totalWidth - Helper::width($synopsis);
        $this->writeText(\sprintf(
            '  <info>%s</info>  %s%s%s%s',
            $synopsis,
            str_repeat(' ', $spacingWidth),
            // + 4 = 2 spaces before <info>, 2 spaces after </info>
            preg_replace('/\s*[\r\n]\s*/', "\n" . str_repeat(' ', $totalWidth + 4), $option->getDescription()),
            $default,
            $option->isArray() ? '<comment> (multiple values allowed)</comment>' : ''
        ), $options);
    }
    protected function describeInputDefinition(InputDefinition $definition, array $options = []): void
    {
        $totalWidth = $this->calculateTotalWidthForOptions($definition->getOptions());
        foreach ($definition->getArguments() as $argument) {
            $totalWidth = max($totalWidth, Helper::width($argument->getName()));
        }
        if ($definition->getArguments()) {
            $this->writeText('<comment>Arguments:</comment>', $options);
            $this->writeText("\n");
            foreach ($definition->getArguments() as $argument) {
                $this->describeInputArgument($argument, array_merge($options, ['total_width' => $totalWidth]));
                $this->writeText("\n");
            }
        }
        if ($definition->getArguments() && $definition->getOptions()) {
            $this->writeText("\n");
        }
        if ($definition->getOptions()) {
            $laterOptions = [];
            $this->writeText('<comment>Options:</comment>', $options);
            foreach ($definition->getOptions() as $option) {
                if (\strlen($option->getShortcut() ?? '') > 1) {
                    $laterOptions[] = $option;
                    continue;
                }
                $this->writeText("\n");
                $this->describeInputOption($option, array_merge($options, ['total_width' => $totalWidth]));
            }
            foreach ($laterOptions as $option) {
                $this->writeText("\n");
                $this->describeInputOption($option, array_merge($options, ['total_width' => $totalWidth]));
            }
        }
    }
    protected function describeCommand(Command $command, array $options = []): void
    {
        $command->mergeApplicationDefinition(\false);
        if ($description = $command->getDescription()) {
            $this->writeText('<comment>Description:</comment>', $options);
            $this->writeText("\n");
            $this->writeText('  ' . $description);
            $this->writeText("\n\n");
        }
        $this->writeText('<comment>Usage:</comment>', $options);
        foreach (array_merge([$command->getSynopsis(\true)], $command->getAliases(), $command->getUsages()) as $usage) {
            $this->writeText("\n");
            $this->writeText('  ' . OutputFormatter::escape($usage), $options);
        }
        $this->writeText("\n");
        $definition = $command->getDefinition();
        if ($definition->getOptions() || $definition->getArguments()) {
            $this->writeText("\n");
            $this->describeInputDefinition($definition, $options);
            $this->writeText("\n");
        }
        $help = $command->getProcessedHelp();
        if ($help && $help !== $description) {
            $this->writeText("\n");
            $this->writeText('<comment>Help:</comment>', $options);
            $this->writeText("\n");
            $this->writeText('  ' . str_replace("\n", "\n  ", $help), $options);
            $this->writeText("\n");
        }
    }
    protected function describeApplication(Application $application, array $options = []): void
    {
        $describedNamespace = $options['namespace'] ?? null;
        $description = new ApplicationDescription($application, $describedNamespace);
        if (isset($options['raw_text']) && $options['raw_text']) {
            $width = $this->getColumnWidth($description->getCommands());
            foreach ($description->getCommands() as $command) {
                $this->writeText(\sprintf("%-{$width}s %s", $command->getName(), $command->getDescription()), $options);
                $this->writeText("\n");
            }
        } else {
            if ('' != $help = $application->getHelp()) {
                $this->writeText("{$help}\n\n", $options);
            }
            $this->writeText("<comment>Usage:</comment>\n", $options);
            $this->writeText("  command [options] [arguments]\n\n", $options);
            $this->describeInputDefinition(new InputDefinition($application->getDefinition()->getOptions()), $options);
            $this->writeText("\n");
            $this->writeText("\n");
            $commands = $description->getCommands();
            $namespaces = $description->getNamespaces();
            if ($describedNamespace && $namespaces) {
                // make sure all alias commands are included when describing a specific namespace
                $describedNamespaceInfo = reset($namespaces);
                foreach ($describedNamespaceInfo['commands'] as $name) {
                    $commands[$name] = $description->getCommand($name);
                }
            }
            // calculate max. width based on available commands per namespace
            $width = $this->getColumnWidth(array_merge(...array_values(array_map(fn($namespace) => array_intersect($namespace['commands'], array_keys($commands)), array_values($namespaces)))));
            if ($describedNamespace) {
                $this->writeText(\sprintf('<comment>Available commands for the "%s" namespace:</comment>', $describedNamespace), $options);
            } else {
                $this->writeText('<comment>Available commands:</comment>', $options);
            }
            foreach ($namespaces as $namespace) {
                $namespace['commands'] = array_filter($namespace['commands'], fn($name) => isset($commands[$name]));
                if (!$namespace['commands']) {
                    continue;
                }
                if (!$describedNamespace && ApplicationDescription::GLOBAL_NAMESPACE !== $namespace['id']) {
                    $this->writeText("\n");
                    $this->writeText(' <comment>' . $namespace['id'] . '</comment>', $options);
                }
                foreach ($namespace['commands'] as $name) {
                    $this->writeText("\n");
                    $spacingWidth = $width - Helper::width($name);
                    $command = $commands[$name];
                    $commandAliases = $name === $command->getName() ? $this->getCommandAliasesText($command) : '';
                    $this->writeText(\sprintf('  <info>%s</info>%s%s', $name, str_repeat(' ', $spacingWidth), $commandAliases . $command->getDescription()), $options);
                }
            }
            $this->writeText("\n");
        }
    }
    private function writeText(string $content, array $options = []): void
    {
        $this->write(isset($options['raw_text']) && $options['raw_text'] ? strip_tags($content) : $content, isset($options['raw_output']) ? !$options['raw_output'] : \true);
    }
    /**
     * Formats command aliases to show them in the command description.
     */
    private function getCommandAliasesText(Command $command): string
    {
        $text = '';
        $aliases = $command->getAliases();
        if ($aliases) {
            $text = '[' . implode('|', $aliases) . '] ';
        }
        return $text;
    }
    /**
     * Formats input option/argument default value.
     */
    private function formatDefaultValue(mixed $default): string
    {
        if (\INF === $default) {
            return 'INF';
        }
        if (\is_string($default)) {
            $default = OutputFormatter::escape($default);
        } elseif (\is_array($default)) {
            foreach ($default as $key => $value) {
                if (\is_string($value)) {
                    $default[$key] = OutputFormatter::escape($value);
                }
            }
        }
        return str_replace('\\\\', '\\', json_encode($default, \JSON_UNESCAPED_SLASHES | \JSON_UNESCAPED_UNICODE));
    }
    /**
     * @param array<Command|string> $commands
     */
    private function getColumnWidth(array $commands): int
    {
        $widths = [];
        foreach ($commands as $command) {
            if ($command instanceof Command) {
                $widths[] = Helper::width($command->getName());
                foreach ($command->getAliases() as $alias) {
                    $widths[] = Helper::width($alias);
                }
            } else {
                $widths[] = Helper::width($command);
            }
        }
        return $widths ? max($widths) + 2 : 0;
    }
    /**
     * @param InputOption[] $options
     */
    private function calculateTotalWidthForOptions(array $options): int
    {
        $totalWidth = 0;
        foreach ($options as $option) {
            // "-" + shortcut + ", --" + name
            $nameLength = 1 + max(Helper::width($option->getShortcut()), 1) + 4 + Helper::width($option->getName());
            if ($option->isNegatable()) {
                $nameLength += 6 + Helper::width($option->getName());
                // |--no- + name
            } elseif ($option->acceptValue()) {
                $valueLength = 1 + Helper::width($option->getName());
                // = + value
                $valueLength += $option->isValueOptional() ? 2 : 0;
                // [ + ]
                $nameLength += $valueLength;
            }
            $totalWidth = max($totalWidth, $nameLength);
        }
        return $totalWidth;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Console\Descriptor;

use _ContaoManager\Symfony\Component\Console\Application;
use _ContaoManager\Symfony\Component\Console\Command\Command;
use _ContaoManager\Symfony\Component\Console\Exception\CommandNotFoundException;
/**
 * @author Jean-François Simon <jeanfrancois.simon@sensiolabs.com>
 *
 * @internal
 */
class ApplicationDescription
{
    public const GLOBAL_NAMESPACE = '_global';
    private Application $application;
    private ?string $namespace;
    private bool $showHidden;
    private array $namespaces;
    /**
     * @var array<string, Command>
     */
    private array $commands;
    /**
     * @var array<string, Command>
     */
    private array $aliases = [];
    public function __construct(Application $application, ?string $namespace = null, bool $showHidden = \false)
    {
        $this->application = $application;
        $this->namespace = $namespace;
        $this->showHidden = $showHidden;
    }
    public function getNamespaces(): array
    {
        if (!isset($this->namespaces)) {
            $this->inspectApplication();
        }
        return $this->namespaces;
    }
    /**
     * @return Command[]
     */
    public function getCommands(): array
    {
        if (!isset($this->commands)) {
            $this->inspectApplication();
        }
        return $this->commands;
    }
    /**
     * @throws CommandNotFoundException
     */
    public function getCommand(string $name): Command
    {
        if (!isset($this->commands[$name]) && !isset($this->aliases[$name])) {
            throw new CommandNotFoundException(\sprintf('Command "%s" does not exist.', $name));
        }
        return $this->commands[$name] ?? $this->aliases[$name];
    }
    private function inspectApplication(): void
    {
        $this->commands = [];
        $this->namespaces = [];
        $all = $this->application->all($this->namespace ? $this->application->findNamespace($this->namespace) : null);
        foreach ($this->sortCommands($all) as $namespace => $commands) {
            $names = [];
            /** @var Command $command */
            foreach ($commands as $name => $command) {
                if (!$command->getName() || !$this->showHidden && $command->isHidden()) {
                    continue;
                }
                if ($command->getName() === $name) {
                    $this->commands[$name] = $command;
                } else {
                    $this->aliases[$name] = $command;
                }
                $names[] = $name;
            }
            $this->namespaces[$namespace] = ['id' => $namespace, 'commands' => $names];
        }
    }
    private function sortCommands(array $commands): array
    {
        $namespacedCommands = [];
        $globalCommands = [];
        $sortedCommands = [];
        foreach ($commands as $name => $command) {
            $key = $this->application->extractNamespace($name, 1);
            if (\in_array($key, ['', self::GLOBAL_NAMESPACE], \true)) {
                $globalCommands[$name] = $command;
            } else {
                $namespacedCommands[$key][$name] = $command;
            }
        }
        if ($globalCommands) {
            ksort($globalCommands);
            $sortedCommands[self::GLOBAL_NAMESPACE] = $globalCommands;
        }
        if ($namespacedCommands) {
            ksort($namespacedCommands, \SORT_STRING);
            foreach ($namespacedCommands as $key => $commandsSet) {
                ksort($commandsSet);
                $sortedCommands[$key] = $commandsSet;
            }
        }
        return $sortedCommands;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Console\Descriptor;

use _ContaoManager\Symfony\Component\Console\Application;
use _ContaoManager\Symfony\Component\Console\Command\Command;
use _ContaoManager\Symfony\Component\Console\Input\InputArgument;
use _ContaoManager\Symfony\Component\Console\Input\InputDefinition;
use _ContaoManager\Symfony\Component\Console\Input\InputOption;
/**
 * XML descriptor.
 *
 * @author Jean-François Simon <contact@jfsimon.fr>
 *
 * @internal
 */
class XmlDescriptor extends Descriptor
{
    public function getInputDefinitionDocument(InputDefinition $definition): \DOMDocument
    {
        $dom = new \DOMDocument('1.0', 'UTF-8');
        $dom->appendChild($definitionXML = $dom->createElement('definition'));
        $definitionXML->appendChild($argumentsXML = $dom->createElement('arguments'));
        foreach ($definition->getArguments() as $argument) {
            $this->appendDocument($argumentsXML, $this->getInputArgumentDocument($argument));
        }
        $definitionXML->appendChild($optionsXML = $dom->createElement('options'));
        foreach ($definition->getOptions() as $option) {
            $this->appendDocument($optionsXML, $this->getInputOptionDocument($option));
        }
        return $dom;
    }
    public function getCommandDocument(Command $command, bool $short = \false): \DOMDocument
    {
        $dom = new \DOMDocument('1.0', 'UTF-8');
        $dom->appendChild($commandXML = $dom->createElement('command'));
        $commandXML->setAttribute('id', $command->getName());
        $commandXML->setAttribute('name', $command->getName());
        $commandXML->setAttribute('hidden', $command->isHidden() ? 1 : 0);
        $commandXML->appendChild($usagesXML = $dom->createElement('usages'));
        $commandXML->appendChild($descriptionXML = $dom->createElement('description'));
        $descriptionXML->appendChild($dom->createTextNode(str_replace("\n", "\n ", $command->getDescription())));
        if ($short) {
            foreach ($command->getAliases() as $usage) {
                $usagesXML->appendChild($dom->createElement('usage', $usage));
            }
        } else {
            $command->mergeApplicationDefinition(\false);
            foreach (array_merge([$command->getSynopsis()], $command->getAliases(), $command->getUsages()) as $usage) {
                $usagesXML->appendChild($dom->createElement('usage', $usage));
            }
            $commandXML->appendChild($helpXML = $dom->createElement('help'));
            $helpXML->appendChild($dom->createTextNode(str_replace("\n", "\n ", $command->getProcessedHelp())));
            $definitionXML = $this->getInputDefinitionDocument($command->getDefinition());
            $this->appendDocument($commandXML, $definitionXML->getElementsByTagName('definition')->item(0));
        }
        return $dom;
    }
    public function getApplicationDocument(Application $application, ?string $namespace = null, bool $short = \false): \DOMDocument
    {
        $dom = new \DOMDocument('1.0', 'UTF-8');
        $dom->appendChild($rootXml = $dom->createElement('symfony'));
        if ('UNKNOWN' !== $application->getName()) {
            $rootXml->setAttribute('name', $application->getName());
            if ('UNKNOWN' !== $application->getVersion()) {
                $rootXml->setAttribute('version', $application->getVersion());
            }
        }
        $rootXml->appendChild($commandsXML = $dom->createElement('commands'));
        $description = new ApplicationDescription($application, $namespace, \true);
        if ($namespace) {
            $commandsXML->setAttribute('namespace', $namespace);
        }
        foreach ($description->getCommands() as $command) {
            $this->appendDocument($commandsXML, $this->getCommandDocument($command, $short));
        }
        if (!$namespace) {
            $rootXml->appendChild($namespacesXML = $dom->createElement('namespaces'));
            foreach ($description->getNamespaces() as $namespaceDescription) {
                $namespacesXML->appendChild($namespaceArrayXML = $dom->createElement('namespace'));
                $namespaceArrayXML->setAttribute('id', $namespaceDescription['id']);
                foreach ($namespaceDescription['commands'] as $name) {
                    $namespaceArrayXML->appendChild($commandXML = $dom->createElement('command'));
                    $commandXML->appendChild($dom->createTextNode($name));
                }
            }
        }
        return $dom;
    }
    protected function describeInputArgument(InputArgument $argument, array $options = []): void
    {
        $this->writeDocument($this->getInputArgumentDocument($argument));
    }
    protected function describeInputOption(InputOption $option, array $options = []): void
    {
        $this->writeDocument($this->getInputOptionDocument($option));
    }
    protected function describeInputDefinition(InputDefinition $definition, array $options = []): void
    {
        $this->writeDocument($this->getInputDefinitionDocument($definition));
    }
    protected function describeCommand(Command $command, array $options = []): void
    {
        $this->writeDocument($this->getCommandDocument($command, $options['short'] ?? \false));
    }
    protected function describeApplication(Application $application, array $options = []): void
    {
        $this->writeDocument($this->getApplicationDocument($application, $options['namespace'] ?? null, $options['short'] ?? \false));
    }
    /**
     * Appends document children to parent node.
     */
    private function appendDocument(\DOMNode $parentNode, \DOMNode $importedParent): void
    {
        foreach ($importedParent->childNodes as $childNode) {
            $parentNode->appendChild($parentNode->ownerDocument->importNode($childNode, \true));
        }
    }
    /**
     * Writes DOM document.
     */
    private function writeDocument(\DOMDocument $dom): void
    {
        $dom->formatOutput = \true;
        $this->write($dom->saveXML());
    }
    private function getInputArgumentDocument(InputArgument $argument): \DOMDocument
    {
        $dom = new \DOMDocument('1.0', 'UTF-8');
        $dom->appendChild($objectXML = $dom->createElement('argument'));
        $objectXML->setAttribute('name', $argument->getName());
        $objectXML->setAttribute('is_required', $argument->isRequired() ? 1 : 0);
        $objectXML->setAttribute('is_array', $argument->isArray() ? 1 : 0);
        $objectXML->appendChild($descriptionXML = $dom->createElement('description'));
        $descriptionXML->appendChild($dom->createTextNode($argument->getDescription()));
        $objectXML->appendChild($defaultsXML = $dom->createElement('defaults'));
        $defaults = \is_array($argument->getDefault()) ? $argument->getDefault() : (\is_bool($argument->getDefault()) ? [var_export($argument->getDefault(), \true)] : ($argument->getDefault() ? [$argument->getDefault()] : []));
        foreach ($defaults as $default) {
            $defaultsXML->appendChild($defaultXML = $dom->createElement('default'));
            $defaultXML->appendChild($dom->createTextNode($default));
        }
        return $dom;
    }
    private function getInputOptionDocument(InputOption $option): \DOMDocument
    {
        $dom = new \DOMDocument('1.0', 'UTF-8');
        $dom->appendChild($objectXML = $dom->createElement('option'));
        $objectXML->setAttribute('name', '--' . $option->getName());
        $pos = strpos($option->getShortcut() ?? '', '|');
        if (\false !== $pos) {
            $objectXML->setAttribute('shortcut', '-' . substr($option->getShortcut(), 0, $pos));
            $objectXML->setAttribute('shortcuts', '-' . str_replace('|', '|-', $option->getShortcut()));
        } else {
            $objectXML->setAttribute('shortcut', $option->getShortcut() ? '-' . $option->getShortcut() : '');
        }
        $objectXML->setAttribute('accept_value', $option->acceptValue() ? 1 : 0);
        $objectXML->setAttribute('is_value_required', $option->isValueRequired() ? 1 : 0);
        $objectXML->setAttribute('is_multiple', $option->isArray() ? 1 : 0);
        $objectXML->appendChild($descriptionXML = $dom->createElement('description'));
        $descriptionXML->appendChild($dom->createTextNode($option->getDescription()));
        if ($option->acceptValue()) {
            $defaults = \is_array($option->getDefault()) ? $option->getDefault() : (\is_bool($option->getDefault()) ? [var_export($option->getDefault(), \true)] : ($option->getDefault() ? [$option->getDefault()] : []));
            $objectXML->appendChild($defaultsXML = $dom->createElement('defaults'));
            if (!empty($defaults)) {
                foreach ($defaults as $default) {
                    $defaultsXML->appendChild($defaultXML = $dom->createElement('default'));
                    $defaultXML->appendChild($dom->createTextNode($default));
                }
            }
        }
        if ($option->isNegatable()) {
            $dom->appendChild($objectXML = $dom->createElement('option'));
            $objectXML->setAttribute('name', '--no-' . $option->getName());
            $objectXML->setAttribute('shortcut', '');
            $objectXML->setAttribute('accept_value', 0);
            $objectXML->setAttribute('is_value_required', 0);
            $objectXML->setAttribute('is_multiple', 0);
            $objectXML->appendChild($descriptionXML = $dom->createElement('description'));
            $descriptionXML->appendChild($dom->createTextNode('Negate the "--' . $option->getName() . '" option'));
        }
        return $dom;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Console\Descriptor;

use _ContaoManager\Symfony\Component\Console\Output\OutputInterface;
/**
 * Descriptor interface.
 *
 * @author Jean-François Simon <contact@jfsimon.fr>
 */
interface DescriptorInterface
{
    /**
     * @return void
     */
    public function describe(OutputInterface $output, object $object, array $options = []);
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Console\Descriptor;

use _ContaoManager\Symfony\Component\Console\Application;
use _ContaoManager\Symfony\Component\Console\Command\Command;
use _ContaoManager\Symfony\Component\Console\Exception\InvalidArgumentException;
use _ContaoManager\Symfony\Component\Console\Input\InputArgument;
use _ContaoManager\Symfony\Component\Console\Input\InputDefinition;
use _ContaoManager\Symfony\Component\Console\Input\InputOption;
use _ContaoManager\Symfony\Component\Console\Output\OutputInterface;
/**
 * @author Jean-François Simon <jeanfrancois.simon@sensiolabs.com>
 *
 * @internal
 */
abstract class Descriptor implements DescriptorInterface
{
    protected OutputInterface $output;
    public function describe(OutputInterface $output, object $object, array $options = []): void
    {
        $this->output = $output;
        match (\true) {
            $object instanceof InputArgument => $this->describeInputArgument($object, $options),
            $object instanceof InputOption => $this->describeInputOption($object, $options),
            $object instanceof InputDefinition => $this->describeInputDefinition($object, $options),
            $object instanceof Command => $this->describeCommand($object, $options),
            $object instanceof Application => $this->describeApplication($object, $options),
            default => throw new InvalidArgumentException(\sprintf('Object of type "%s" is not describable.', get_debug_type($object))),
        };
    }
    protected function write(string $content, bool $decorated = \false): void
    {
        $this->output->write($content, \false, $decorated ? OutputInterface::OUTPUT_NORMAL : OutputInterface::OUTPUT_RAW);
    }
    /**
     * Describes an InputArgument instance.
     */
    abstract protected function describeInputArgument(InputArgument $argument, array $options = []): void;
    /**
     * Describes an InputOption instance.
     */
    abstract protected function describeInputOption(InputOption $option, array $options = []): void;
    /**
     * Describes an InputDefinition instance.
     */
    abstract protected function describeInputDefinition(InputDefinition $definition, array $options = []): void;
    /**
     * Describes a Command instance.
     */
    abstract protected function describeCommand(Command $command, array $options = []): void;
    /**
     * Describes an Application instance.
     */
    abstract protected function describeApplication(Application $application, array $options = []): void;
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Console\Descriptor;

use _ContaoManager\Symfony\Component\Console\Application;
use _ContaoManager\Symfony\Component\Console\Command\Command;
use _ContaoManager\Symfony\Component\Console\Helper\Helper;
use _ContaoManager\Symfony\Component\Console\Input\InputArgument;
use _ContaoManager\Symfony\Component\Console\Input\InputDefinition;
use _ContaoManager\Symfony\Component\Console\Input\InputOption;
use _ContaoManager\Symfony\Component\Console\Output\OutputInterface;
use _ContaoManager\Symfony\Component\String\UnicodeString;
class ReStructuredTextDescriptor extends Descriptor
{
    // <h1>
    private string $partChar = '=';
    // <h2>
    private string $chapterChar = '-';
    // <h3>
    private string $sectionChar = '~';
    // <h4>
    private string $subsectionChar = '.';
    // <h5>
    private string $subsubsectionChar = '^';
    // <h6>
    private string $paragraphsChar = '"';
    private array $visibleNamespaces = [];
    public function describe(OutputInterface $output, object $object, array $options = []): void
    {
        $decorated = $output->isDecorated();
        $output->setDecorated(\false);
        parent::describe($output, $object, $options);
        $output->setDecorated($decorated);
    }
    /**
     * Override parent method to set $decorated = true.
     */
    protected function write(string $content, bool $decorated = \true): void
    {
        parent::write($content, $decorated);
    }
    protected function describeInputArgument(InputArgument $argument, array $options = []): void
    {
        $this->write($argument->getName() ?: '<none>' . "\n" . str_repeat($this->paragraphsChar, Helper::width($argument->getName())) . "\n\n" . ($argument->getDescription() ? preg_replace('/\s*[\r\n]\s*/', "\n", $argument->getDescription()) . "\n\n" : '') . '- **Is required**: ' . ($argument->isRequired() ? 'yes' : 'no') . "\n" . '- **Is array**: ' . ($argument->isArray() ? 'yes' : 'no') . "\n" . '- **Default**: ``' . str_replace("\n", '', var_export($argument->getDefault(), \true)) . '``');
    }
    protected function describeInputOption(InputOption $option, array $options = []): void
    {
        $name = '\-\-' . $option->getName();
        if ($option->isNegatable()) {
            $name .= '|\-\-no-' . $option->getName();
        }
        if ($option->getShortcut()) {
            $name .= '|-' . str_replace('|', '|-', $option->getShortcut());
        }
        $optionDescription = $option->getDescription() ? preg_replace('/\s*[\r\n]\s*/', "\n\n", $option->getDescription()) . "\n\n" : '';
        $optionDescription = (new UnicodeString($optionDescription))->ascii();
        $this->write($name . "\n" . str_repeat($this->paragraphsChar, Helper::width($name)) . "\n\n" . $optionDescription . '- **Accept value**: ' . ($option->acceptValue() ? 'yes' : 'no') . "\n" . '- **Is value required**: ' . ($option->isValueRequired() ? 'yes' : 'no') . "\n" . '- **Is multiple**: ' . ($option->isArray() ? 'yes' : 'no') . "\n" . '- **Is negatable**: ' . ($option->isNegatable() ? 'yes' : 'no') . "\n" . '- **Default**: ``' . str_replace("\n", '', var_export($option->getDefault(), \true)) . '``' . "\n");
    }
    protected function describeInputDefinition(InputDefinition $definition, array $options = []): void
    {
        if ($showArguments = (bool) $definition->getArguments()) {
            $this->write("Arguments\n" . str_repeat($this->subsubsectionChar, 9)) . "\n\n";
            foreach ($definition->getArguments() as $argument) {
                $this->write("\n\n");
                $this->describeInputArgument($argument);
            }
        }
        if ($nonDefaultOptions = $this->getNonDefaultOptions($definition)) {
            if ($showArguments) {
                $this->write("\n\n");
            }
            $this->write("Options\n" . str_repeat($this->subsubsectionChar, 7) . "\n\n");
            foreach ($nonDefaultOptions as $option) {
                $this->describeInputOption($option);
                $this->write("\n");
            }
        }
    }
    protected function describeCommand(Command $command, array $options = []): void
    {
        if ($options['short'] ?? \false) {
            $this->write('``' . $command->getName() . "``\n" . str_repeat($this->subsectionChar, Helper::width($command->getName())) . "\n\n" . ($command->getDescription() ? $command->getDescription() . "\n\n" : '') . "Usage\n" . str_repeat($this->paragraphsChar, 5) . "\n\n" . array_reduce($command->getAliases(), static fn($carry, $usage) => $carry . '- ``' . $usage . '``' . "\n"));
            return;
        }
        $command->mergeApplicationDefinition(\false);
        foreach ($command->getAliases() as $alias) {
            $this->write('.. _' . $alias . ":\n\n");
        }
        $this->write($command->getName() . "\n" . str_repeat($this->subsectionChar, Helper::width($command->getName())) . "\n\n" . ($command->getDescription() ? $command->getDescription() . "\n\n" : '') . "Usage\n" . str_repeat($this->subsubsectionChar, 5) . "\n\n" . array_reduce(array_merge([$command->getSynopsis()], $command->getAliases(), $command->getUsages()), static fn($carry, $usage) => $carry . '- ``' . $usage . '``' . "\n"));
        if ($help = $command->getProcessedHelp()) {
            $this->write("\n");
            $this->write($help);
        }
        $definition = $command->getDefinition();
        if ($definition->getOptions() || $definition->getArguments()) {
            $this->write("\n\n");
            $this->describeInputDefinition($definition);
        }
    }
    protected function describeApplication(Application $application, array $options = []): void
    {
        $description = new ApplicationDescription($application, $options['namespace'] ?? null);
        $title = $this->getApplicationTitle($application);
        $this->write($title . "\n" . str_repeat($this->partChar, Helper::width($title)));
        $this->createTableOfContents($description, $application);
        $this->describeCommands($application, $options);
    }
    private function getApplicationTitle(Application $application): string
    {
        if ('UNKNOWN' === $application->getName()) {
            return 'Console Tool';
        }
        if ('UNKNOWN' !== $application->getVersion()) {
            return \sprintf('%s %s', $application->getName(), $application->getVersion());
        }
        return $application->getName();
    }
    private function describeCommands($application, array $options): void
    {
        $title = 'Commands';
        $this->write("\n\n{$title}\n" . str_repeat($this->chapterChar, Helper::width($title)) . "\n\n");
        foreach ($this->visibleNamespaces as $namespace) {
            if ('_global' === $namespace) {
                $commands = $application->all('');
                $this->write('Global' . "\n" . str_repeat($this->sectionChar, Helper::width('Global')) . "\n\n");
            } else {
                $commands = $application->all($namespace);
                $this->write($namespace . "\n" . str_repeat($this->sectionChar, Helper::width($namespace)) . "\n\n");
            }
            foreach ($this->removeAliasesAndHiddenCommands($commands) as $command) {
                $this->describeCommand($command, $options);
                $this->write("\n\n");
            }
        }
    }
    private function createTableOfContents(ApplicationDescription $description, Application $application): void
    {
        $this->setVisibleNamespaces($description);
        $chapterTitle = 'Table of Contents';
        $this->write("\n\n{$chapterTitle}\n" . str_repeat($this->chapterChar, Helper::width($chapterTitle)) . "\n\n");
        foreach ($this->visibleNamespaces as $namespace) {
            if ('_global' === $namespace) {
                $commands = $application->all('');
            } else {
                $commands = $application->all($namespace);
                $this->write("\n\n");
                $this->write($namespace . "\n" . str_repeat($this->sectionChar, Helper::width($namespace)) . "\n\n");
            }
            $commands = $this->removeAliasesAndHiddenCommands($commands);
            $this->write("\n\n");
            $this->write(implode("\n", array_map(static fn($commandName) => \sprintf('- `%s`_', $commandName), array_keys($commands))));
        }
    }
    private function getNonDefaultOptions(InputDefinition $definition): array
    {
        $globalOptions = ['help', 'quiet', 'verbose', 'version', 'ansi', 'no-interaction'];
        $nonDefaultOptions = [];
        foreach ($definition->getOptions() as $option) {
            // Skip global options.
            if (!\in_array($option->getName(), $globalOptions)) {
                $nonDefaultOptions[] = $option;
            }
        }
        return $nonDefaultOptions;
    }
    private function setVisibleNamespaces(ApplicationDescription $description): void
    {
        $commands = $description->getCommands();
        foreach ($description->getNamespaces() as $namespace) {
            try {
                $namespaceCommands = $namespace['commands'];
                foreach ($namespaceCommands as $key => $commandName) {
                    if (!\array_key_exists($commandName, $commands)) {
                        // If the array key does not exist, then this is an alias.
                        unset($namespaceCommands[$key]);
                    } elseif ($commands[$commandName]->isHidden()) {
                        unset($namespaceCommands[$key]);
                    }
                }
                if (!$namespaceCommands) {
                    // If the namespace contained only aliases or hidden commands, skip the namespace.
                    continue;
                }
            } catch (\Exception) {
            }
            $this->visibleNamespaces[] = $namespace['id'];
        }
    }
    private function removeAliasesAndHiddenCommands(array $commands): array
    {
        foreach ($commands as $key => $command) {
            if ($command->isHidden() || \in_array($key, $command->getAliases(), \true)) {
                unset($commands[$key]);
            }
        }
        unset($commands['completion']);
        return $commands;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Console\Descriptor;

use _ContaoManager\Symfony\Component\Console\Application;
use _ContaoManager\Symfony\Component\Console\Command\Command;
use _ContaoManager\Symfony\Component\Console\Input\InputArgument;
use _ContaoManager\Symfony\Component\Console\Input\InputDefinition;
use _ContaoManager\Symfony\Component\Console\Input\InputOption;
/**
 * JSON descriptor.
 *
 * @author Jean-François Simon <contact@jfsimon.fr>
 *
 * @internal
 */
class JsonDescriptor extends Descriptor
{
    protected function describeInputArgument(InputArgument $argument, array $options = []): void
    {
        $this->writeData($this->getInputArgumentData($argument), $options);
    }
    protected function describeInputOption(InputOption $option, array $options = []): void
    {
        $this->writeData($this->getInputOptionData($option), $options);
        if ($option->isNegatable()) {
            $this->writeData($this->getInputOptionData($option, \true), $options);
        }
    }
    protected function describeInputDefinition(InputDefinition $definition, array $options = []): void
    {
        $this->writeData($this->getInputDefinitionData($definition), $options);
    }
    protected function describeCommand(Command $command, array $options = []): void
    {
        $this->writeData($this->getCommandData($command, $options['short'] ?? \false), $options);
    }
    protected function describeApplication(Application $application, array $options = []): void
    {
        $describedNamespace = $options['namespace'] ?? null;
        $description = new ApplicationDescription($application, $describedNamespace, \true);
        $commands = [];
        foreach ($description->getCommands() as $command) {
            $commands[] = $this->getCommandData($command, $options['short'] ?? \false);
        }
        $data = [];
        if ('UNKNOWN' !== $application->getName()) {
            $data['application']['name'] = $application->getName();
            if ('UNKNOWN' !== $application->getVersion()) {
                $data['application']['version'] = $application->getVersion();
            }
        }
        $data['commands'] = $commands;
        if ($describedNamespace) {
            $data['namespace'] = $describedNamespace;
        } else {
            $data['namespaces'] = array_values($description->getNamespaces());
        }
        $this->writeData($data, $options);
    }
    /**
     * Writes data as json.
     */
    private function writeData(array $data, array $options): void
    {
        $flags = $options['json_encoding'] ?? 0;
        $this->write(json_encode($data, $flags));
    }
    private function getInputArgumentData(InputArgument $argument): array
    {
        return ['name' => $argument->getName(), 'is_required' => $argument->isRequired(), 'is_array' => $argument->isArray(), 'description' => preg_replace('/\s*[\r\n]\s*/', ' ', $argument->getDescription()), 'default' => \INF === $argument->getDefault() ? 'INF' : $argument->getDefault()];
    }
    private function getInputOptionData(InputOption $option, bool $negated = \false): array
    {
        return $negated ? ['name' => '--no-' . $option->getName(), 'shortcut' => '', 'accept_value' => \false, 'is_value_required' => \false, 'is_multiple' => \false, 'description' => 'Negate the "--' . $option->getName() . '" option', 'default' => null === $option->getDefault() ? null : !$option->getDefault()] : ['name' => '--' . $option->getName(), 'shortcut' => $option->getShortcut() ? '-' . str_replace('|', '|-', $option->getShortcut()) : '', 'accept_value' => $option->acceptValue(), 'is_value_required' => $option->isValueRequired(), 'is_multiple' => $option->isArray(), 'description' => preg_replace('/\s*[\r\n]\s*/', ' ', $option->getDescription()), 'default' => \INF === $option->getDefault() ? 'INF' : $option->getDefault()];
    }
    private function getInputDefinitionData(InputDefinition $definition): array
    {
        $inputArguments = [];
        foreach ($definition->getArguments() as $name => $argument) {
            $inputArguments[$name] = $this->getInputArgumentData($argument);
        }
        $inputOptions = [];
        foreach ($definition->getOptions() as $name => $option) {
            $inputOptions[$name] = $this->getInputOptionData($option);
            if ($option->isNegatable()) {
                $inputOptions['no-' . $name] = $this->getInputOptionData($option, \true);
            }
        }
        return ['arguments' => $inputArguments, 'options' => $inputOptions];
    }
    private function getCommandData(Command $command, bool $short = \false): array
    {
        $data = ['name' => $command->getName(), 'description' => $command->getDescription()];
        if ($short) {
            $data += ['usage' => $command->getAliases()];
        } else {
            $command->mergeApplicationDefinition(\false);
            $data += ['usage' => array_merge([$command->getSynopsis()], $command->getUsages(), $command->getAliases()), 'help' => $command->getProcessedHelp(), 'definition' => $this->getInputDefinitionData($command->getDefinition())];
        }
        $data['hidden'] = $command->isHidden();
        return $data;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Console\Descriptor;

use _ContaoManager\Symfony\Component\Console\Application;
use _ContaoManager\Symfony\Component\Console\Command\Command;
use _ContaoManager\Symfony\Component\Console\Helper\Helper;
use _ContaoManager\Symfony\Component\Console\Input\InputArgument;
use _ContaoManager\Symfony\Component\Console\Input\InputDefinition;
use _ContaoManager\Symfony\Component\Console\Input\InputOption;
use _ContaoManager\Symfony\Component\Console\Output\OutputInterface;
/**
 * Markdown descriptor.
 *
 * @author Jean-François Simon <contact@jfsimon.fr>
 *
 * @internal
 */
class MarkdownDescriptor extends Descriptor
{
    public function describe(OutputInterface $output, object $object, array $options = []): void
    {
        $decorated = $output->isDecorated();
        $output->setDecorated(\false);
        parent::describe($output, $object, $options);
        $output->setDecorated($decorated);
    }
    protected function write(string $content, bool $decorated = \true): void
    {
        parent::write($content, $decorated);
    }
    protected function describeInputArgument(InputArgument $argument, array $options = []): void
    {
        $this->write('#### `' . ($argument->getName() ?: '<none>') . "`\n\n" . ($argument->getDescription() ? preg_replace('/\s*[\r\n]\s*/', "\n", $argument->getDescription()) . "\n\n" : '') . '* Is required: ' . ($argument->isRequired() ? 'yes' : 'no') . "\n" . '* Is array: ' . ($argument->isArray() ? 'yes' : 'no') . "\n" . '* Default: `' . str_replace("\n", '', var_export($argument->getDefault(), \true)) . '`');
    }
    protected function describeInputOption(InputOption $option, array $options = []): void
    {
        $name = '--' . $option->getName();
        if ($option->isNegatable()) {
            $name .= '|--no-' . $option->getName();
        }
        if ($option->getShortcut()) {
            $name .= '|-' . str_replace('|', '|-', $option->getShortcut()) . '';
        }
        $this->write('#### `' . $name . '`' . "\n\n" . ($option->getDescription() ? preg_replace('/\s*[\r\n]\s*/', "\n", $option->getDescription()) . "\n\n" : '') . '* Accept value: ' . ($option->acceptValue() ? 'yes' : 'no') . "\n" . '* Is value required: ' . ($option->isValueRequired() ? 'yes' : 'no') . "\n" . '* Is multiple: ' . ($option->isArray() ? 'yes' : 'no') . "\n" . '* Is negatable: ' . ($option->isNegatable() ? 'yes' : 'no') . "\n" . '* Default: `' . str_replace("\n", '', var_export($option->getDefault(), \true)) . '`');
    }
    protected function describeInputDefinition(InputDefinition $definition, array $options = []): void
    {
        if ($showArguments = \count($definition->getArguments()) > 0) {
            $this->write('### Arguments');
            foreach ($definition->getArguments() as $argument) {
                $this->write("\n\n");
                $this->describeInputArgument($argument);
            }
        }
        if (\count($definition->getOptions()) > 0) {
            if ($showArguments) {
                $this->write("\n\n");
            }
            $this->write('### Options');
            foreach ($definition->getOptions() as $option) {
                $this->write("\n\n");
                $this->describeInputOption($option);
            }
        }
    }
    protected function describeCommand(Command $command, array $options = []): void
    {
        if ($options['short'] ?? \false) {
            $this->write('`' . $command->getName() . "`\n" . str_repeat('-', Helper::width($command->getName()) + 2) . "\n\n" . ($command->getDescription() ? $command->getDescription() . "\n\n" : '') . '### Usage' . "\n\n" . array_reduce($command->getAliases(), fn($carry, $usage) => $carry . '* `' . $usage . '`' . "\n"));
            return;
        }
        $command->mergeApplicationDefinition(\false);
        $this->write('`' . $command->getName() . "`\n" . str_repeat('-', Helper::width($command->getName()) + 2) . "\n\n" . ($command->getDescription() ? $command->getDescription() . "\n\n" : '') . '### Usage' . "\n\n" . array_reduce(array_merge([$command->getSynopsis()], $command->getAliases(), $command->getUsages()), fn($carry, $usage) => $carry . '* `' . $usage . '`' . "\n"));
        if ($help = $command->getProcessedHelp()) {
            $this->write("\n");
            $this->write($help);
        }
        $definition = $command->getDefinition();
        if ($definition->getOptions() || $definition->getArguments()) {
            $this->write("\n\n");
            $this->describeInputDefinition($definition);
        }
    }
    protected function describeApplication(Application $application, array $options = []): void
    {
        $describedNamespace = $options['namespace'] ?? null;
        $description = new ApplicationDescription($application, $describedNamespace);
        $title = $this->getApplicationTitle($application);
        $this->write($title . "\n" . str_repeat('=', Helper::width($title)));
        foreach ($description->getNamespaces() as $namespace) {
            if (ApplicationDescription::GLOBAL_NAMESPACE !== $namespace['id']) {
                $this->write("\n\n");
                $this->write('**' . $namespace['id'] . ':**');
            }
            $this->write("\n\n");
            $this->write(implode("\n", array_map(fn($commandName) => \sprintf('* [`%s`](#%s)', $commandName, str_replace(':', '', $description->getCommand($commandName)->getName())), $namespace['commands'])));
        }
        foreach ($description->getCommands() as $command) {
            $this->write("\n\n");
            $this->describeCommand($command, $options);
        }
    }
    private function getApplicationTitle(Application $application): string
    {
        if ('UNKNOWN' !== $application->getName()) {
            if ('UNKNOWN' !== $application->getVersion()) {
                return \sprintf('%s %s', $application->getName(), $application->getVersion());
            }
            return $application->getName();
        }
        return 'Console Tool';
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Console\Tester;

use _ContaoManager\Symfony\Component\Console\Command\Command;
use _ContaoManager\Symfony\Component\Console\Input\ArrayInput;
/**
 * Eases the testing of console commands.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 * @author Robin Chalas <robin.chalas@gmail.com>
 */
class CommandTester
{
    use TesterTrait;
    private Command $command;
    public function __construct(Command $command)
    {
        $this->command = $command;
    }
    /**
     * Executes the command.
     *
     * Available execution options:
     *
     *  * interactive:               Sets the input interactive flag
     *  * decorated:                 Sets the output decorated flag
     *  * verbosity:                 Sets the output verbosity flag
     *  * capture_stderr_separately: Make output of stdOut and stdErr separately available
     *
     * @param array $input   An array of command arguments and options
     * @param array $options An array of execution options
     *
     * @return int The command exit code
     */
    public function execute(array $input, array $options = []): int
    {
        // set the command name automatically if the application requires
        // this argument and no command name was passed
        if (!isset($input['command']) && null !== ($application = $this->command->getApplication()) && $application->getDefinition()->hasArgument('command')) {
            $input = array_merge(['command' => $this->command->getName()], $input);
        }
        $this->input = new ArrayInput($input);
        // Use an in-memory input stream even if no inputs are set so that QuestionHelper::ask() does not rely on the blocking STDIN.
        $this->input->setStream(self::createStream($this->inputs));
        if (isset($options['interactive'])) {
            $this->input->setInteractive($options['interactive']);
        }
        if (!isset($options['decorated'])) {
            $options['decorated'] = \false;
        }
        $this->initOutput($options);
        return $this->statusCode = $this->command->run($this->input, $this->output);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Console\Tester;

use _ContaoManager\PHPUnit\Framework\Assert;
use _ContaoManager\Symfony\Component\Console\Input\InputInterface;
use _ContaoManager\Symfony\Component\Console\Output\ConsoleOutput;
use _ContaoManager\Symfony\Component\Console\Output\OutputInterface;
use _ContaoManager\Symfony\Component\Console\Output\StreamOutput;
use _ContaoManager\Symfony\Component\Console\Tester\Constraint\CommandIsSuccessful;
/**
 * @author Amrouche Hamza <hamza.simperfit@gmail.com>
 */
trait TesterTrait
{
    private StreamOutput $output;
    private array $inputs = [];
    private bool $captureStreamsIndependently = \false;
    private InputInterface $input;
    private int $statusCode;
    /**
     * Gets the display returned by the last execution of the command or application.
     *
     * @throws \RuntimeException If it's called before the execute method
     */
    public function getDisplay(bool $normalize = \false): string
    {
        if (!isset($this->output)) {
            throw new \RuntimeException('Output not initialized, did you execute the command before requesting the display?');
        }
        rewind($this->output->getStream());
        $display = stream_get_contents($this->output->getStream());
        if ($normalize) {
            $display = str_replace(\PHP_EOL, "\n", $display);
        }
        return $display;
    }
    /**
     * Gets the output written to STDERR by the application.
     *
     * @param bool $normalize Whether to normalize end of lines to \n or not
     */
    public function getErrorOutput(bool $normalize = \false): string
    {
        if (!$this->captureStreamsIndependently) {
            throw new \LogicException('The error output is not available when the tester is run without "capture_stderr_separately" option set.');
        }
        rewind($this->output->getErrorOutput()->getStream());
        $display = stream_get_contents($this->output->getErrorOutput()->getStream());
        if ($normalize) {
            $display = str_replace(\PHP_EOL, "\n", $display);
        }
        return $display;
    }
    /**
     * Gets the input instance used by the last execution of the command or application.
     */
    public function getInput(): InputInterface
    {
        return $this->input;
    }
    /**
     * Gets the output instance used by the last execution of the command or application.
     */
    public function getOutput(): OutputInterface
    {
        return $this->output;
    }
    /**
     * Gets the status code returned by the last execution of the command or application.
     *
     * @throws \RuntimeException If it's called before the execute method
     */
    public function getStatusCode(): int
    {
        return $this->statusCode ?? throw new \RuntimeException('Status code not initialized, did you execute the command before requesting the status code?');
    }
    public function assertCommandIsSuccessful(string $message = ''): void
    {
        Assert::assertThat($this->statusCode, new CommandIsSuccessful(), $message);
    }
    /**
     * Sets the user inputs.
     *
     * @param array $inputs An array of strings representing each input
     *                      passed to the command input stream
     *
     * @return $this
     */
    public function setInputs(array $inputs): static
    {
        $this->inputs = $inputs;
        return $this;
    }
    /**
     * Initializes the output property.
     *
     * Available options:
     *
     *  * decorated:                 Sets the output decorated flag
     *  * verbosity:                 Sets the output verbosity flag
     *  * capture_stderr_separately: Make output of stdOut and stdErr separately available
     */
    private function initOutput(array $options): void
    {
        $this->captureStreamsIndependently = $options['capture_stderr_separately'] ?? \false;
        if (!$this->captureStreamsIndependently) {
            $this->output = new StreamOutput(fopen('php://memory', 'w', \false));
            if (isset($options['decorated'])) {
                $this->output->setDecorated($options['decorated']);
            }
            if (isset($options['verbosity'])) {
                $this->output->setVerbosity($options['verbosity']);
            }
        } else {
            $this->output = new ConsoleOutput($options['verbosity'] ?? ConsoleOutput::VERBOSITY_NORMAL, $options['decorated'] ?? null);
            $errorOutput = new StreamOutput(fopen('php://memory', 'w', \false));
            $errorOutput->setFormatter($this->output->getFormatter());
            $errorOutput->setVerbosity($this->output->getVerbosity());
            $errorOutput->setDecorated($this->output->isDecorated());
            $reflectedOutput = new \ReflectionObject($this->output);
            $strErrProperty = $reflectedOutput->getProperty('stderr');
            $strErrProperty->setValue($this->output, $errorOutput);
            $reflectedParent = $reflectedOutput->getParentClass();
            $streamProperty = $reflectedParent->getProperty('stream');
            $streamProperty->setValue($this->output, fopen('php://memory', 'w', \false));
        }
    }
    /**
     * @return resource
     */
    private static function createStream(array $inputs)
    {
        $stream = fopen('php://memory', 'r+', \false);
        foreach ($inputs as $input) {
            fwrite($stream, $input);
            if (!str_ends_with($input, "\x04")) {
                fwrite($stream, \PHP_EOL);
            }
        }
        rewind($stream);
        return $stream;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Console\Tester;

use _ContaoManager\Symfony\Component\Console\Application;
use _ContaoManager\Symfony\Component\Console\Input\ArrayInput;
/**
 * Eases the testing of console applications.
 *
 * When testing an application, don't forget to disable the auto exit flag:
 *
 *     $application = new Application();
 *     $application->setAutoExit(false);
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class ApplicationTester
{
    use TesterTrait;
    private Application $application;
    public function __construct(Application $application)
    {
        $this->application = $application;
    }
    /**
     * Executes the application.
     *
     * Available options:
     *
     *  * interactive:               Sets the input interactive flag
     *  * decorated:                 Sets the output decorated flag
     *  * verbosity:                 Sets the output verbosity flag
     *  * capture_stderr_separately: Make output of stdOut and stdErr separately available
     *
     * @return int The command exit code
     */
    public function run(array $input, array $options = []): int
    {
        $prevShellVerbosity = [getenv('SHELL_VERBOSITY'), $_ENV['SHELL_VERBOSITY'] ?? \false, $_SERVER['SHELL_VERBOSITY'] ?? \false];
        try {
            $this->input = new ArrayInput($input);
            if (isset($options['interactive'])) {
                $this->input->setInteractive($options['interactive']);
            }
            if ($this->inputs) {
                $this->input->setStream(self::createStream($this->inputs));
            }
            $this->initOutput($options);
            // Temporarily clear SHELL_VERBOSITY to prevent Application::configureIO
            // from overriding the interactive and verbosity settings set above
            if (\function_exists('putenv')) {
                @putenv('SHELL_VERBOSITY');
            }
            unset($_ENV['SHELL_VERBOSITY'], $_SERVER['SHELL_VERBOSITY']);
            return $this->statusCode = $this->application->run($this->input, $this->output);
        } finally {
            // SHELL_VERBOSITY is set by Application::configureIO so we need to unset/reset it
            // to its previous value to avoid one test's verbosity to spread to the following tests
            if (\false === $prevShellVerbosity[0]) {
                if (\function_exists('putenv')) {
                    @putenv('SHELL_VERBOSITY');
                }
            } else if (\function_exists('putenv')) {
                @putenv('SHELL_VERBOSITY=' . $prevShellVerbosity[0]);
            }
            if (\false === $prevShellVerbosity[1]) {
                unset($_ENV['SHELL_VERBOSITY']);
            } else {
                $_ENV['SHELL_VERBOSITY'] = $prevShellVerbosity[1];
            }
            if (\false === $prevShellVerbosity[2]) {
                unset($_SERVER['SHELL_VERBOSITY']);
            } else {
                $_SERVER['SHELL_VERBOSITY'] = $prevShellVerbosity[2];
            }
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Console\Tester;

use _ContaoManager\Symfony\Component\Console\Command\Command;
use _ContaoManager\Symfony\Component\Console\Completion\CompletionInput;
use _ContaoManager\Symfony\Component\Console\Completion\CompletionSuggestions;
/**
 * Eases the testing of command completion.
 *
 * @author Jérôme Tamarelle <jerome@tamarelle.net>
 */
class CommandCompletionTester
{
    private Command $command;
    public function __construct(Command $command)
    {
        $this->command = $command;
    }
    /**
     * Create completion suggestions from input tokens.
     */
    public function complete(array $input): array
    {
        $currentIndex = \count($input);
        if ('' === end($input)) {
            array_pop($input);
        }
        array_unshift($input, $this->command->getName());
        $completionInput = CompletionInput::fromTokens($input, $currentIndex);
        $completionInput->bind($this->command->getDefinition());
        $suggestions = new CompletionSuggestions();
        $this->command->complete($completionInput, $suggestions);
        $options = [];
        foreach ($suggestions->getOptionSuggestions() as $option) {
            $options[] = '--' . $option->getName();
        }
        return array_map('strval', array_merge($options, $suggestions->getValueSuggestions()));
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Console\Tester\Constraint;

use _ContaoManager\PHPUnit\Framework\Constraint\Constraint;
use _ContaoManager\Symfony\Component\Console\Command\Command;
final class CommandIsSuccessful extends Constraint
{
    public function toString(): string
    {
        return 'is successful';
    }
    protected function matches($other): bool
    {
        return Command::SUCCESS === $other;
    }
    protected function failureDescription($other): string
    {
        return 'the command ' . $this->toString();
    }
    protected function additionalFailureDescription($other): string
    {
        $mapping = [Command::FAILURE => 'Command failed.', Command::INVALID => 'Command was invalid.'];
        return $mapping[$other] ?? \sprintf('Command returned exit status %d.', $other);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Console\Command;

use _ContaoManager\Symfony\Component\Console\Application;
use _ContaoManager\Symfony\Component\Console\Completion\CompletionInput;
use _ContaoManager\Symfony\Component\Console\Completion\CompletionSuggestions;
use _ContaoManager\Symfony\Component\Console\Helper\HelperInterface;
use _ContaoManager\Symfony\Component\Console\Helper\HelperSet;
use _ContaoManager\Symfony\Component\Console\Input\InputDefinition;
use _ContaoManager\Symfony\Component\Console\Input\InputInterface;
use _ContaoManager\Symfony\Component\Console\Output\ConsoleOutputInterface;
use _ContaoManager\Symfony\Component\Console\Output\OutputInterface;
use _ContaoManager\Symfony\Component\Stopwatch\Stopwatch;
/**
 * @internal
 *
 * @author Jules Pietri <jules@heahprod.com>
 */
final class TraceableCommand extends Command implements SignalableCommandInterface
{
    public readonly Command $command;
    public int $exitCode;
    public ?int $interruptedBySignal = null;
    public bool $ignoreValidation;
    public bool $isInteractive = \false;
    public string $duration = 'n/a';
    public string $maxMemoryUsage = 'n/a';
    public InputInterface $input;
    public OutputInterface $output;
    /** @var array<string, mixed> */
    public array $arguments;
    /** @var array<string, mixed> */
    public array $options;
    /** @var array<string, mixed> */
    public array $interactiveInputs = [];
    public array $handledSignals = [];
    public function __construct(Command $command, private readonly Stopwatch $stopwatch)
    {
        if ($command instanceof LazyCommand) {
            $command = $command->getCommand();
        }
        $this->command = $command;
        // prevent call to self::getDefaultDescription()
        $this->setDescription($command->getDescription());
        parent::__construct($command->getName());
        // init below enables calling {@see parent::run()}
        [$code, $processTitle, $ignoreValidationErrors] = \Closure::bind(function () {
            return [$this->code, $this->processTitle, $this->ignoreValidationErrors];
        }, $command, Command::class)();
        if (\is_callable($code)) {
            $this->setCode($code);
        }
        if ($processTitle) {
            parent::setProcessTitle($processTitle);
        }
        if ($ignoreValidationErrors) {
            parent::ignoreValidationErrors();
        }
        $this->ignoreValidation = $ignoreValidationErrors;
    }
    public function __call(string $name, array $arguments): mixed
    {
        return $this->command->{$name}(...$arguments);
    }
    public function getSubscribedSignals(): array
    {
        return $this->command instanceof SignalableCommandInterface ? $this->command->getSubscribedSignals() : [];
    }
    public function handleSignal(int $signal, int|false $previousExitCode = 0): int|false
    {
        if (!$this->command instanceof SignalableCommandInterface) {
            return \false;
        }
        $event = $this->stopwatch->start($this->getName() . '.handle_signal');
        $exit = $this->command->handleSignal($signal, $previousExitCode);
        $event->stop();
        if (!isset($this->handledSignals[$signal])) {
            $this->handledSignals[$signal] = ['handled' => 0, 'duration' => 0, 'memory' => 0];
        }
        ++$this->handledSignals[$signal]['handled'];
        $this->handledSignals[$signal]['duration'] += $event->getDuration();
        $this->handledSignals[$signal]['memory'] = max($this->handledSignals[$signal]['memory'], $event->getMemory() >> 20);
        return $exit;
    }
    /**
     * {@inheritdoc}
     *
     * Calling parent method is required to be used in {@see parent::run()}.
     */
    public function ignoreValidationErrors(): void
    {
        $this->ignoreValidation = \true;
        $this->command->ignoreValidationErrors();
        parent::ignoreValidationErrors();
    }
    public function setApplication(?Application $application = null): void
    {
        $this->command->setApplication($application);
    }
    public function getApplication(): ?Application
    {
        return $this->command->getApplication();
    }
    public function setHelperSet(HelperSet $helperSet): void
    {
        $this->command->setHelperSet($helperSet);
    }
    public function getHelperSet(): ?HelperSet
    {
        return $this->command->getHelperSet();
    }
    public function isEnabled(): bool
    {
        return $this->command->isEnabled();
    }
    public function complete(CompletionInput $input, CompletionSuggestions $suggestions): void
    {
        $this->command->complete($input, $suggestions);
    }
    /**
     * {@inheritdoc}
     *
     * Calling parent method is required to be used in {@see parent::run()}.
     */
    public function setCode(callable $code): static
    {
        $this->command->setCode($code);
        return parent::setCode(function (InputInterface $input, OutputInterface $output) use ($code): int {
            $event = $this->stopwatch->start($this->getName() . '.code');
            $this->exitCode = $code($input, $output);
            $event->stop();
            return $this->exitCode;
        });
    }
    /**
     * @internal
     */
    public function mergeApplicationDefinition(bool $mergeArgs = \true): void
    {
        $this->command->mergeApplicationDefinition($mergeArgs);
    }
    public function setDefinition(array|InputDefinition $definition): static
    {
        $this->command->setDefinition($definition);
        return $this;
    }
    public function getDefinition(): InputDefinition
    {
        return $this->command->getDefinition();
    }
    public function getNativeDefinition(): InputDefinition
    {
        return $this->command->getNativeDefinition();
    }
    public function addArgument(string $name, ?int $mode = null, string $description = '', mixed $default = null, array|\Closure $suggestedValues = []): static
    {
        $this->command->addArgument($name, $mode, $description, $default, $suggestedValues);
        return $this;
    }
    public function addOption(string $name, string|array|null $shortcut = null, ?int $mode = null, string $description = '', mixed $default = null, array|\Closure $suggestedValues = []): static
    {
        $this->command->addOption($name, $shortcut, $mode, $description, $default, $suggestedValues);
        return $this;
    }
    /**
     * {@inheritdoc}
     *
     * Calling parent method is required to be used in {@see parent::run()}.
     */
    public function setProcessTitle(string $title): static
    {
        $this->command->setProcessTitle($title);
        return parent::setProcessTitle($title);
    }
    public function setHelp(string $help): static
    {
        $this->command->setHelp($help);
        return $this;
    }
    public function getHelp(): string
    {
        return $this->command->getHelp();
    }
    public function getProcessedHelp(): string
    {
        return $this->command->getProcessedHelp();
    }
    public function getSynopsis(bool $short = \false): string
    {
        return $this->command->getSynopsis($short);
    }
    public function addUsage(string $usage): static
    {
        $this->command->addUsage($usage);
        return $this;
    }
    public function getUsages(): array
    {
        return $this->command->getUsages();
    }
    public function getHelper(string $name): HelperInterface
    {
        return $this->command->getHelper($name);
    }
    public function run(InputInterface $input, OutputInterface $output): int
    {
        $this->input = $input;
        $this->output = $output;
        $this->arguments = $input->getArguments();
        $this->options = $input->getOptions();
        $event = $this->stopwatch->start($this->getName(), 'command');
        try {
            $this->exitCode = $this->command->run($input, $output);
        } finally {
            $event->stop();
            if ($output instanceof ConsoleOutputInterface && $output->isDebug()) {
                $output->getErrorOutput()->writeln((string) $event);
            }
            $this->duration = $event->getDuration() . ' ms';
            $this->maxMemoryUsage = ($event->getMemory() >> 20) . ' MiB';
            if ($this->isInteractive) {
                $this->extractInteractiveInputs($input->getArguments(), $input->getOptions());
            }
        }
        return $this->exitCode;
    }
    protected function initialize(InputInterface $input, OutputInterface $output): void
    {
        $event = $this->stopwatch->start($this->getName() . '.init', 'command');
        $this->command->initialize($input, $output);
        $event->stop();
    }
    protected function interact(InputInterface $input, OutputInterface $output): void
    {
        if (!$this->isInteractive = Command::class !== (new \ReflectionMethod($this->command, 'interact'))->getDeclaringClass()->getName()) {
            return;
        }
        $event = $this->stopwatch->start($this->getName() . '.interact', 'command');
        $this->command->interact($input, $output);
        $event->stop();
    }
    protected function execute(InputInterface $input, OutputInterface $output): int
    {
        $event = $this->stopwatch->start($this->getName() . '.execute', 'command');
        $exitCode = $this->command->execute($input, $output);
        $event->stop();
        return $exitCode;
    }
    private function extractInteractiveInputs(array $arguments, array $options): void
    {
        foreach ($arguments as $argName => $argValue) {
            if (\array_key_exists($argName, $this->arguments) && $this->arguments[$argName] === $argValue) {
                continue;
            }
            $this->interactiveInputs[$argName] = $argValue;
        }
        foreach ($options as $optName => $optValue) {
            if (\array_key_exists($optName, $this->options) && $this->options[$optName] === $optValue) {
                continue;
            }
            $this->interactiveInputs['--' . $optName] = $optValue;
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Console\Command;

use _ContaoManager\Symfony\Component\Console\Application;
use _ContaoManager\Symfony\Component\Console\Completion\CompletionInput;
use _ContaoManager\Symfony\Component\Console\Completion\CompletionSuggestions;
use _ContaoManager\Symfony\Component\Console\Completion\Suggestion;
use _ContaoManager\Symfony\Component\Console\Helper\HelperInterface;
use _ContaoManager\Symfony\Component\Console\Helper\HelperSet;
use _ContaoManager\Symfony\Component\Console\Input\InputDefinition;
use _ContaoManager\Symfony\Component\Console\Input\InputInterface;
use _ContaoManager\Symfony\Component\Console\Output\OutputInterface;
/**
 * @author Nicolas Grekas <p@tchwork.com>
 */
final class LazyCommand extends Command
{
    private \Closure|Command $command;
    private ?bool $isEnabled;
    public function __construct(string $name, array $aliases, string $description, bool $isHidden, \Closure $commandFactory, ?bool $isEnabled = \true)
    {
        $this->setName($name)->setAliases($aliases)->setHidden($isHidden)->setDescription($description);
        $this->command = $commandFactory;
        $this->isEnabled = $isEnabled;
    }
    public function ignoreValidationErrors(): void
    {
        $this->getCommand()->ignoreValidationErrors();
    }
    public function setApplication(?Application $application = null): void
    {
        if (1 > \func_num_args()) {
            trigger_deprecation('symfony/console', '6.2', 'Calling "%s()" without any arguments is deprecated, pass null explicitly instead.', __METHOD__);
        }
        if ($this->command instanceof parent) {
            $this->command->setApplication($application);
        }
        parent::setApplication($application);
    }
    public function setHelperSet(HelperSet $helperSet): void
    {
        if ($this->command instanceof parent) {
            $this->command->setHelperSet($helperSet);
        }
        parent::setHelperSet($helperSet);
    }
    public function isEnabled(): bool
    {
        return $this->isEnabled ?? $this->getCommand()->isEnabled();
    }
    public function run(InputInterface $input, OutputInterface $output): int
    {
        return $this->getCommand()->run($input, $output);
    }
    public function complete(CompletionInput $input, CompletionSuggestions $suggestions): void
    {
        $this->getCommand()->complete($input, $suggestions);
    }
    public function setCode(callable $code): static
    {
        $this->getCommand()->setCode($code);
        return $this;
    }
    /**
     * @internal
     */
    public function mergeApplicationDefinition(bool $mergeArgs = \true): void
    {
        $this->getCommand()->mergeApplicationDefinition($mergeArgs);
    }
    public function setDefinition(array|InputDefinition $definition): static
    {
        $this->getCommand()->setDefinition($definition);
        return $this;
    }
    public function getDefinition(): InputDefinition
    {
        return $this->getCommand()->getDefinition();
    }
    public function getNativeDefinition(): InputDefinition
    {
        return $this->getCommand()->getNativeDefinition();
    }
    /**
     * @param array|\Closure(CompletionInput,CompletionSuggestions):list<string|Suggestion> $suggestedValues The values used for input completion
     */
    public function addArgument(string $name, ?int $mode = null, string $description = '', mixed $default = null): static
    {
        $suggestedValues = 5 <= \func_num_args() ? func_get_arg(4) : [];
        $this->getCommand()->addArgument($name, $mode, $description, $default, $suggestedValues);
        return $this;
    }
    /**
     * @param array|\Closure(CompletionInput,CompletionSuggestions):list<string|Suggestion> $suggestedValues The values used for input completion
     */
    public function addOption(string $name, string|array|null $shortcut = null, ?int $mode = null, string $description = '', mixed $default = null): static
    {
        $suggestedValues = 6 <= \func_num_args() ? func_get_arg(5) : [];
        $this->getCommand()->addOption($name, $shortcut, $mode, $description, $default, $suggestedValues);
        return $this;
    }
    public function setProcessTitle(string $title): static
    {
        $this->getCommand()->setProcessTitle($title);
        return $this;
    }
    public function setHelp(string $help): static
    {
        $this->getCommand()->setHelp($help);
        return $this;
    }
    public function getHelp(): string
    {
        return $this->getCommand()->getHelp();
    }
    public function getProcessedHelp(): string
    {
        return $this->getCommand()->getProcessedHelp();
    }
    public function getSynopsis(bool $short = \false): string
    {
        return $this->getCommand()->getSynopsis($short);
    }
    public function addUsage(string $usage): static
    {
        $this->getCommand()->addUsage($usage);
        return $this;
    }
    public function getUsages(): array
    {
        return $this->getCommand()->getUsages();
    }
    public function getHelper(string $name): HelperInterface
    {
        return $this->getCommand()->getHelper($name);
    }
    public function getCommand(): parent
    {
        if (!$this->command instanceof \Closure) {
            return $this->command;
        }
        $command = $this->command = ($this->command)();
        $command->setApplication($this->getApplication());
        if (null !== $this->getHelperSet()) {
            $command->setHelperSet($this->getHelperSet());
        }
        $command->setName($this->getName())->setAliases($this->getAliases())->setHidden($this->isHidden())->setDescription($this->getDescription());
        // Will throw if the command is not correctly initialized.
        $command->getDefinition();
        return $command;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Console\Command;

use _ContaoManager\Symfony\Component\Console\Exception\LogicException;
use _ContaoManager\Symfony\Component\Lock\LockFactory;
use _ContaoManager\Symfony\Component\Lock\LockInterface;
use _ContaoManager\Symfony\Component\Lock\Store\FlockStore;
use _ContaoManager\Symfony\Component\Lock\Store\SemaphoreStore;
/**
 * Basic lock feature for commands.
 *
 * @author Geoffrey Brier <geoffrey.brier@gmail.com>
 */
trait LockableTrait
{
    private ?LockInterface $lock = null;
    /**
     * Locks a command.
     */
    private function lock(?string $name = null, bool $blocking = \false): bool
    {
        if (!class_exists(SemaphoreStore::class)) {
            throw new LogicException('To enable the locking feature you must install the symfony/lock component. Try running "composer require symfony/lock".');
        }
        if (null !== $this->lock) {
            throw new LogicException('A lock is already in place.');
        }
        if (SemaphoreStore::isSupported()) {
            $store = new SemaphoreStore();
        } else {
            $store = new FlockStore();
        }
        $this->lock = (new LockFactory($store))->createLock($name ?: $this->getName());
        if (!$this->lock->acquire($blocking)) {
            $this->lock = null;
            return \false;
        }
        return \true;
    }
    /**
     * Releases the command lock if there is one.
     */
    private function release(): void
    {
        if ($this->lock) {
            $this->lock->release();
            $this->lock = null;
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Console\Command;

use _ContaoManager\Symfony\Component\Console\Descriptor\ApplicationDescription;
use _ContaoManager\Symfony\Component\Console\Helper\DescriptorHelper;
use _ContaoManager\Symfony\Component\Console\Input\InputArgument;
use _ContaoManager\Symfony\Component\Console\Input\InputInterface;
use _ContaoManager\Symfony\Component\Console\Input\InputOption;
use _ContaoManager\Symfony\Component\Console\Output\OutputInterface;
/**
 * HelpCommand displays the help for a given command.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class HelpCommand extends Command
{
    private Command $command;
    /**
     * @return void
     */
    protected function configure()
    {
        $this->ignoreValidationErrors();
        $this->setName('help')->setDefinition([new InputArgument('command_name', InputArgument::OPTIONAL, 'The command name', 'help', fn() => array_keys((new ApplicationDescription($this->getApplication()))->getCommands())), new InputOption('format', null, InputOption::VALUE_REQUIRED, 'The output format (txt, xml, json, or md)', 'txt', fn() => (new DescriptorHelper())->getFormats()), new InputOption('raw', null, InputOption::VALUE_NONE, 'To output raw command help')])->setDescription('Display help for a command')->setHelp(<<<'EOF'
The <info>%command.name%</info> command displays help for a given command:

  <info>%command.full_name% list</info>

You can also output the help in other formats by using the <comment>--format</comment> option:

  <info>%command.full_name% --format=xml list</info>

To display the list of available commands, please use the <info>list</info> command.
EOF
);
    }
    /**
     * @return void
     */
    public function setCommand(Command $command)
    {
        $this->command = $command;
    }
    protected function execute(InputInterface $input, OutputInterface $output): int
    {
        $this->command ??= $this->getApplication()->find($input->getArgument('command_name'));
        $helper = new DescriptorHelper();
        $helper->describe($output, $this->command, ['format' => $input->getOption('format'), 'raw_text' => $input->getOption('raw')]);
        unset($this->command);
        return 0;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Console\Command;

use _ContaoManager\Symfony\Component\Console\Attribute\AsCommand;
use _ContaoManager\Symfony\Component\Console\Completion\CompletionInput;
use _ContaoManager\Symfony\Component\Console\Completion\CompletionSuggestions;
use _ContaoManager\Symfony\Component\Console\Completion\Output\BashCompletionOutput;
use _ContaoManager\Symfony\Component\Console\Completion\Output\CompletionOutputInterface;
use _ContaoManager\Symfony\Component\Console\Completion\Output\FishCompletionOutput;
use _ContaoManager\Symfony\Component\Console\Completion\Output\ZshCompletionOutput;
use _ContaoManager\Symfony\Component\Console\Exception\CommandNotFoundException;
use _ContaoManager\Symfony\Component\Console\Exception\ExceptionInterface;
use _ContaoManager\Symfony\Component\Console\Input\InputInterface;
use _ContaoManager\Symfony\Component\Console\Input\InputOption;
use _ContaoManager\Symfony\Component\Console\Output\OutputInterface;
/**
 * Responsible for providing the values to the shell completion.
 *
 * @author Wouter de Jong <wouter@wouterj.nl>
 */
#[AsCommand(name: '|_complete', description: 'Internal command to provide shell completion suggestions')]
final class CompleteCommand extends Command
{
    public const COMPLETION_API_VERSION = '1';
    /**
     * @deprecated since Symfony 6.1
     */
    protected static $defaultName = '|_complete';
    /**
     * @deprecated since Symfony 6.1
     */
    protected static $defaultDescription = 'Internal command to provide shell completion suggestions';
    private array $completionOutputs;
    private bool $isDebug = \false;
    /**
     * @param array<string, class-string<CompletionOutputInterface>> $completionOutputs A list of additional completion outputs, with shell name as key and FQCN as value
     */
    public function __construct(array $completionOutputs = [])
    {
        // must be set before the parent constructor, as the property value is used in configure()
        $this->completionOutputs = $completionOutputs + ['bash' => BashCompletionOutput::class, 'fish' => FishCompletionOutput::class, 'zsh' => ZshCompletionOutput::class];
        parent::__construct();
    }
    protected function configure(): void
    {
        $this->addOption('shell', 's', InputOption::VALUE_REQUIRED, 'The shell type ("' . implode('", "', array_keys($this->completionOutputs)) . '")')->addOption('input', 'i', InputOption::VALUE_REQUIRED | InputOption::VALUE_IS_ARRAY, 'An array of input tokens (e.g. COMP_WORDS or argv)')->addOption('current', 'c', InputOption::VALUE_REQUIRED, 'The index of the "input" array that the cursor is in (e.g. COMP_CWORD)')->addOption('api-version', 'a', InputOption::VALUE_REQUIRED, 'The API version of the completion script')->addOption('symfony', 'S', InputOption::VALUE_REQUIRED, 'deprecated');
    }
    protected function initialize(InputInterface $input, OutputInterface $output): void
    {
        $this->isDebug = filter_var(getenv('SYMFONY_COMPLETION_DEBUG'), \FILTER_VALIDATE_BOOL);
    }
    protected function execute(InputInterface $input, OutputInterface $output): int
    {
        try {
            // "symfony" must be kept for compat with the shell scripts generated by Symfony Console 5.4 - 6.1
            $version = $input->getOption('symfony') ? '1' : $input->getOption('api-version');
            if ($version && version_compare($version, self::COMPLETION_API_VERSION, '<')) {
                $message = \sprintf('Completion script version is not supported ("%s" given, ">=%s" required).', $version, self::COMPLETION_API_VERSION);
                $this->log($message);
                $output->writeln($message . ' Install the Symfony completion script again by using the "completion" command.');
                return 126;
            }
            $shell = $input->getOption('shell');
            if (!$shell) {
                throw new \RuntimeException('The "--shell" option must be set.');
            }
            if (!$completionOutput = $this->completionOutputs[$shell] ?? \false) {
                throw new \RuntimeException(\sprintf('Shell completion is not supported for your shell: "%s" (supported: "%s").', $shell, implode('", "', array_keys($this->completionOutputs))));
            }
            $completionInput = $this->createCompletionInput($input);
            $suggestions = new CompletionSuggestions();
            $this->log(['', '<comment>' . date('Y-m-d H:i:s') . '</>', '<info>Input:</> <comment>("|" indicates the cursor position)</>', '  ' . (string) $completionInput, '<info>Command:</>', '  ' . (string) implode(' ', $_SERVER['argv']), '<info>Messages:</>']);
            if ($command = $this->findCommand($completionInput, $output)) {
                $command->mergeApplicationDefinition();
                $completionInput->bind($command->getDefinition());
            }
            if (null === $command) {
                $this->log('  No command found, completing using the Application class.');
                $this->getApplication()->complete($completionInput, $suggestions);
            } elseif ($completionInput->mustSuggestArgumentValuesFor('command')) {
                $this->log('  Command found, completing command name.');
                // expand shortcut names ("cache:cl<TAB>") into their full name ("cache:clear")
                $commandNames = array_filter(array_merge([$command->getName()], $command->getAliases()));
                foreach ($commandNames as $name) {
                    if (str_starts_with($name, $completionInput->getCompletionValue())) {
                        $commandNames = [$name];
                        break;
                    }
                }
                $suggestions->suggestValues($commandNames);
            } else if (CompletionInput::TYPE_OPTION_NAME === $completionInput->getCompletionType()) {
                $this->log('  Completing option names for the <comment>' . ($command instanceof LazyCommand ? $command->getCommand() : $command)::class . '</> command.');
                $suggestions->suggestOptions($command->getDefinition()->getOptions());
            } else {
                $this->log(['  Completing using the <comment>' . ($command instanceof LazyCommand ? $command->getCommand() : $command)::class . '</> class.', '  Completing <comment>' . $completionInput->getCompletionType() . '</> for <comment>' . $completionInput->getCompletionName() . '</>']);
                if (null !== $compval = $completionInput->getCompletionValue()) {
                    $this->log('  Current value: <comment>' . $compval . '</>');
                }
                $command->complete($completionInput, $suggestions);
            }
            /** @var CompletionOutputInterface $completionOutput */
            $completionOutput = new $completionOutput();
            $this->log('<info>Suggestions:</>');
            if ($options = $suggestions->getOptionSuggestions()) {
                $this->log('  --' . implode(' --', array_map(fn($o) => $o->getName(), $options)));
            } elseif ($values = $suggestions->getValueSuggestions()) {
                $this->log('  ' . implode(' ', $values));
            } else {
                $this->log('  <comment>No suggestions were provided</>');
            }
            $completionOutput->write($suggestions, $output);
        } catch (\Throwable $e) {
            $this->log(['<error>Error!</error>', (string) $e]);
            if ($output->isDebug()) {
                throw $e;
            }
            return 2;
        }
        return 0;
    }
    private function createCompletionInput(InputInterface $input): CompletionInput
    {
        $currentIndex = $input->getOption('current');
        if (!$currentIndex || !ctype_digit($currentIndex)) {
            throw new \RuntimeException('The "--current" option must be set and it must be an integer.');
        }
        $completionInput = CompletionInput::fromTokens($input->getOption('input'), (int) $currentIndex);
        try {
            $completionInput->bind($this->getApplication()->getDefinition());
        } catch (ExceptionInterface) {
        }
        return $completionInput;
    }
    private function findCommand(CompletionInput $completionInput, OutputInterface $output): ?Command
    {
        try {
            $inputName = $completionInput->getFirstArgument();
            if (null === $inputName) {
                return null;
            }
            return $this->getApplication()->find($inputName);
        } catch (CommandNotFoundException) {
        }
        return null;
    }
    private function log($messages): void
    {
        if (!$this->isDebug) {
            return;
        }
        $commandName = basename($_SERVER['argv'][0]);
        file_put_contents(sys_get_temp_dir() . '/sf_' . $commandName . '.log', implode(\PHP_EOL, (array) $messages) . \PHP_EOL, \FILE_APPEND);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Console\Command;

use _ContaoManager\Symfony\Component\Console\Descriptor\ApplicationDescription;
use _ContaoManager\Symfony\Component\Console\Helper\DescriptorHelper;
use _ContaoManager\Symfony\Component\Console\Input\InputArgument;
use _ContaoManager\Symfony\Component\Console\Input\InputInterface;
use _ContaoManager\Symfony\Component\Console\Input\InputOption;
use _ContaoManager\Symfony\Component\Console\Output\OutputInterface;
/**
 * ListCommand displays the list of all available commands for the application.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class ListCommand extends Command
{
    /**
     * @return void
     */
    protected function configure()
    {
        $this->setName('list')->setDefinition([new InputArgument('namespace', InputArgument::OPTIONAL, 'The namespace name', null, fn() => array_keys((new ApplicationDescription($this->getApplication()))->getNamespaces())), new InputOption('raw', null, InputOption::VALUE_NONE, 'To output raw command list'), new InputOption('format', null, InputOption::VALUE_REQUIRED, 'The output format (txt, xml, json, or md)', 'txt', fn() => (new DescriptorHelper())->getFormats()), new InputOption('short', null, InputOption::VALUE_NONE, 'To skip describing commands\' arguments')])->setDescription('List commands')->setHelp(<<<'EOF'
The <info>%command.name%</info> command lists all commands:

  <info>%command.full_name%</info>

You can also display the commands for a specific namespace:

  <info>%command.full_name% test</info>

You can also output the information in other formats by using the <comment>--format</comment> option:

  <info>%command.full_name% --format=xml</info>

It's also possible to get raw list of commands (useful for embedding command runner):

  <info>%command.full_name% --raw</info>
EOF
);
    }
    protected function execute(InputInterface $input, OutputInterface $output): int
    {
        $helper = new DescriptorHelper();
        $helper->describe($output, $this->getApplication(), ['format' => $input->getOption('format'), 'raw_text' => $input->getOption('raw'), 'namespace' => $input->getArgument('namespace'), 'short' => $input->getOption('short')]);
        return 0;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Console\Command;

use _ContaoManager\Symfony\Component\Console\Attribute\AsCommand;
use _ContaoManager\Symfony\Component\Console\Input\InputArgument;
use _ContaoManager\Symfony\Component\Console\Input\InputInterface;
use _ContaoManager\Symfony\Component\Console\Input\InputOption;
use _ContaoManager\Symfony\Component\Console\Output\ConsoleOutputInterface;
use _ContaoManager\Symfony\Component\Console\Output\OutputInterface;
use _ContaoManager\Symfony\Component\Process\Process;
/**
 * Dumps the completion script for the current shell.
 *
 * @author Wouter de Jong <wouter@wouterj.nl>
 */
#[AsCommand(name: 'completion', description: 'Dump the shell completion script')]
final class DumpCompletionCommand extends Command
{
    /**
     * @deprecated since Symfony 6.1
     */
    protected static $defaultName = 'completion';
    /**
     * @deprecated since Symfony 6.1
     */
    protected static $defaultDescription = 'Dump the shell completion script';
    private array $supportedShells;
    protected function configure(): void
    {
        $fullCommand = $_SERVER['PHP_SELF'];
        $commandName = basename($fullCommand);
        $fullCommand = @realpath($fullCommand) ?: $fullCommand;
        $shell = $this->guessShell();
        [$rcFile, $completionFile] = match ($shell) {
            'fish' => ['~/.config/fish/config.fish', "/etc/fish/completions/{$commandName}.fish"],
            'zsh' => ['~/.zshrc', '$fpath[1]/_' . $commandName],
            default => ['~/.bashrc', "/etc/bash_completion.d/{$commandName}"],
        };
        $supportedShells = implode(', ', $this->getSupportedShells());
        $this->setHelp(<<<EOH
The <info>%command.name%</> command dumps the shell completion script required
to use shell autocompletion (currently, {$supportedShells} completion are supported).

<comment>Static installation
-------------------</>

Dump the script to a global completion file and restart your shell:

    <info>%command.full_name% {$shell} | sudo tee {$completionFile}</>

Or dump the script to a local file and source it:

    <info>%command.full_name% {$shell} > completion.sh</>

    <comment># source the file whenever you use the project</>
    <info>source completion.sh</>

    <comment># or add this line at the end of your "{$rcFile}" file:</>
    <info>source /path/to/completion.sh</>

<comment>Dynamic installation
--------------------</>

Add this to the end of your shell configuration file (e.g. <info>"{$rcFile}"</>):

    <info>eval "\$({$fullCommand} completion {$shell})"</>
EOH
)->addArgument('shell', InputArgument::OPTIONAL, 'The shell type (e.g. "bash"), the value of the "$SHELL" env var will be used if this is not given', null, $this->getSupportedShells(...))->addOption('debug', null, InputOption::VALUE_NONE, 'Tail the completion debug log');
    }
    protected function execute(InputInterface $input, OutputInterface $output): int
    {
        $commandName = basename($_SERVER['argv'][0]);
        if ($input->getOption('debug')) {
            $this->tailDebugLog($commandName, $output);
            return 0;
        }
        $shell = $input->getArgument('shell') ?? self::guessShell();
        $completionFile = __DIR__ . '/../Resources/completion.' . $shell;
        if (!file_exists($completionFile)) {
            $supportedShells = $this->getSupportedShells();
            if ($output instanceof ConsoleOutputInterface) {
                $output = $output->getErrorOutput();
            }
            if ($shell) {
                $output->writeln(\sprintf('<error>Detected shell "%s", which is not supported by Symfony shell completion (supported shells: "%s").</>', $shell, implode('", "', $supportedShells)));
            } else {
                $output->writeln(\sprintf('<error>Shell not detected, Symfony shell completion only supports "%s").</>', implode('", "', $supportedShells)));
            }
            return 2;
        }
        $output->write(str_replace(['{{ COMMAND_NAME }}', '{{ VERSION }}'], [$commandName, CompleteCommand::COMPLETION_API_VERSION], file_get_contents($completionFile)));
        return 0;
    }
    private static function guessShell(): string
    {
        return basename($_SERVER['SHELL'] ?? '');
    }
    private function tailDebugLog(string $commandName, OutputInterface $output): void
    {
        $debugFile = sys_get_temp_dir() . '/sf_' . $commandName . '.log';
        if (!file_exists($debugFile)) {
            touch($debugFile);
        }
        $process = new Process(['tail', '-f', $debugFile], null, null, null, 0);
        $process->run(function (string $type, string $line) use ($output): void {
            $output->write($line);
        });
    }
    /**
     * @return string[]
     */
    private function getSupportedShells(): array
    {
        if (isset($this->supportedShells)) {
            return $this->supportedShells;
        }
        $shells = [];
        foreach (new \DirectoryIterator(__DIR__ . '/../Resources/') as $file) {
            if (str_starts_with($file->getBasename(), 'completion.') && $file->isFile()) {
                $shells[] = $file->getExtension();
            }
        }
        sort($shells);
        return $this->supportedShells = $shells;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Console\Command;

/**
 * Interface for command reacting to signal.
 *
 * @author Grégoire Pineau <lyrixx@lyrix.info>
 */
interface SignalableCommandInterface
{
    /**
     * Returns the list of signals to subscribe.
     */
    public function getSubscribedSignals(): array;
    /**
     * The method will be called when the application is signaled.
     *
     * @param int|false $previousExitCode
     *
     * @return int|false The exit code to return or false to continue the normal execution
     */
    public function handleSignal(int $signal);
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Console\Command;

use _ContaoManager\Symfony\Component\Console\Application;
use _ContaoManager\Symfony\Component\Console\Attribute\AsCommand;
use _ContaoManager\Symfony\Component\Console\Completion\CompletionInput;
use _ContaoManager\Symfony\Component\Console\Completion\CompletionSuggestions;
use _ContaoManager\Symfony\Component\Console\Completion\Suggestion;
use _ContaoManager\Symfony\Component\Console\Exception\ExceptionInterface;
use _ContaoManager\Symfony\Component\Console\Exception\InvalidArgumentException;
use _ContaoManager\Symfony\Component\Console\Exception\LogicException;
use _ContaoManager\Symfony\Component\Console\Helper\HelperInterface;
use _ContaoManager\Symfony\Component\Console\Helper\HelperSet;
use _ContaoManager\Symfony\Component\Console\Input\InputArgument;
use _ContaoManager\Symfony\Component\Console\Input\InputDefinition;
use _ContaoManager\Symfony\Component\Console\Input\InputInterface;
use _ContaoManager\Symfony\Component\Console\Input\InputOption;
use _ContaoManager\Symfony\Component\Console\Output\OutputInterface;
/**
 * Base class for all commands.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class Command
{
    // see https://tldp.org/LDP/abs/html/exitcodes.html
    public const SUCCESS = 0;
    public const FAILURE = 1;
    public const INVALID = 2;
    /**
     * @var string|null The default command name
     *
     * @deprecated since Symfony 6.1, use the AsCommand attribute instead
     */
    protected static $defaultName;
    /**
     * @var string|null The default command description
     *
     * @deprecated since Symfony 6.1, use the AsCommand attribute instead
     */
    protected static $defaultDescription;
    private ?Application $application = null;
    private ?string $name = null;
    private ?string $processTitle = null;
    private array $aliases = [];
    private InputDefinition $definition;
    private bool $hidden = \false;
    private string $help = '';
    private string $description = '';
    private ?InputDefinition $fullDefinition = null;
    private bool $ignoreValidationErrors = \false;
    private ?\Closure $code = null;
    private array $synopsis = [];
    private array $usages = [];
    private ?HelperSet $helperSet = null;
    public static function getDefaultName(): ?string
    {
        $class = static::class;
        if ($attribute = (new \ReflectionClass($class))->getAttributes(AsCommand::class)) {
            return $attribute[0]->newInstance()->name;
        }
        $r = new \ReflectionProperty($class, 'defaultName');
        if ($class !== $r->class || null === static::$defaultName) {
            return null;
        }
        trigger_deprecation('symfony/console', '6.1', 'Relying on the static property "$defaultName" for setting a command name is deprecated. Add the "%s" attribute to the "%s" class instead.', AsCommand::class, static::class);
        return static::$defaultName;
    }
    public static function getDefaultDescription(): ?string
    {
        $class = static::class;
        if ($attribute = (new \ReflectionClass($class))->getAttributes(AsCommand::class)) {
            return $attribute[0]->newInstance()->description;
        }
        $r = new \ReflectionProperty($class, 'defaultDescription');
        if ($class !== $r->class || null === static::$defaultDescription) {
            return null;
        }
        trigger_deprecation('symfony/console', '6.1', 'Relying on the static property "$defaultDescription" for setting a command description is deprecated. Add the "%s" attribute to the "%s" class instead.', AsCommand::class, static::class);
        return static::$defaultDescription;
    }
    /**
     * @param string|null $name The name of the command; passing null means it must be set in configure()
     *
     * @throws LogicException When the command name is empty
     */
    public function __construct(?string $name = null)
    {
        $this->definition = new InputDefinition();
        if (null === $name && null !== $name = static::getDefaultName()) {
            $aliases = explode('|', $name);
            if ('' === $name = array_shift($aliases)) {
                $this->setHidden(\true);
                $name = array_shift($aliases);
            }
            $this->setAliases($aliases);
        }
        if (null !== $name) {
            $this->setName($name);
        }
        if ('' === $this->description) {
            $this->setDescription(static::getDefaultDescription() ?? '');
        }
        $this->configure();
    }
    /**
     * Ignores validation errors.
     *
     * This is mainly useful for the help command.
     *
     * @return void
     */
    public function ignoreValidationErrors()
    {
        $this->ignoreValidationErrors = \true;
    }
    /**
     * @return void
     */
    public function setApplication(?Application $application = null)
    {
        if (1 > \func_num_args()) {
            trigger_deprecation('symfony/console', '6.2', 'Calling "%s()" without any arguments is deprecated, pass null explicitly instead.', __METHOD__);
        }
        $this->application = $application;
        if ($application) {
            $this->setHelperSet($application->getHelperSet());
        } else {
            $this->helperSet = null;
        }
        $this->fullDefinition = null;
    }
    /**
     * @return void
     */
    public function setHelperSet(HelperSet $helperSet)
    {
        $this->helperSet = $helperSet;
    }
    /**
     * Gets the helper set.
     */
    public function getHelperSet(): ?HelperSet
    {
        return $this->helperSet;
    }
    /**
     * Gets the application instance for this command.
     */
    public function getApplication(): ?Application
    {
        return $this->application;
    }
    /**
     * Checks whether the command is enabled or not in the current environment.
     *
     * Override this to check for x or y and return false if the command cannot
     * run properly under the current conditions.
     *
     * @return bool
     */
    public function isEnabled()
    {
        return \true;
    }
    /**
     * Configures the current command.
     *
     * @return void
     */
    protected function configure()
    {
    }
    /**
     * Executes the current command.
     *
     * This method is not abstract because you can use this class
     * as a concrete class. In this case, instead of defining the
     * execute() method, you set the code to execute by passing
     * a Closure to the setCode() method.
     *
     * @return int 0 if everything went fine, or an exit code
     *
     * @throws LogicException When this abstract method is not implemented
     *
     * @see setCode()
     */
    protected function execute(InputInterface $input, OutputInterface $output)
    {
        throw new LogicException('You must override the execute() method in the concrete command class.');
    }
    /**
     * Interacts with the user.
     *
     * This method is executed before the InputDefinition is validated.
     * This means that this is the only place where the command can
     * interactively ask for values of missing required arguments.
     *
     * @return void
     */
    protected function interact(InputInterface $input, OutputInterface $output)
    {
    }
    /**
     * Initializes the command after the input has been bound and before the input
     * is validated.
     *
     * This is mainly useful when a lot of commands extends one main command
     * where some things need to be initialized based on the input arguments and options.
     *
     * @see InputInterface::bind()
     * @see InputInterface::validate()
     *
     * @return void
     */
    protected function initialize(InputInterface $input, OutputInterface $output)
    {
    }
    /**
     * Runs the command.
     *
     * The code to execute is either defined directly with the
     * setCode() method or by overriding the execute() method
     * in a sub-class.
     *
     * @return int The command exit code
     *
     * @throws ExceptionInterface When input binding fails. Bypass this by calling {@link ignoreValidationErrors()}.
     *
     * @see setCode()
     * @see execute()
     */
    public function run(InputInterface $input, OutputInterface $output): int
    {
        // add the application arguments and options
        $this->mergeApplicationDefinition();
        // bind the input against the command specific arguments/options
        try {
            $input->bind($this->getDefinition());
        } catch (ExceptionInterface $e) {
            if (!$this->ignoreValidationErrors) {
                throw $e;
            }
        }
        $this->initialize($input, $output);
        if (null !== $this->processTitle) {
            if (\function_exists('cli_set_process_title')) {
                if (!@cli_set_process_title($this->processTitle)) {
                    if ('Darwin' === \PHP_OS) {
                        $output->writeln('<comment>Running "cli_set_process_title" as an unprivileged user is not supported on MacOS.</comment>', OutputInterface::VERBOSITY_VERY_VERBOSE);
                    } else {
                        cli_set_process_title($this->processTitle);
                    }
                }
            } elseif (\function_exists('setproctitle')) {
                setproctitle($this->processTitle);
            } elseif (OutputInterface::VERBOSITY_VERY_VERBOSE === $output->getVerbosity()) {
                $output->writeln('<comment>Install the proctitle PECL to be able to change the process title.</comment>');
            }
        }
        if ($input->isInteractive()) {
            $this->interact($input, $output);
        }
        // The command name argument is often omitted when a command is executed directly with its run() method.
        // It would fail the validation if we didn't make sure the command argument is present,
        // since it's required by the application.
        if ($input->hasArgument('command') && null === $input->getArgument('command')) {
            $input->setArgument('command', $this->getName());
        }
        $input->validate();
        if ($this->code) {
            $statusCode = ($this->code)($input, $output);
        } else {
            $statusCode = $this->execute($input, $output);
            if (!\is_int($statusCode)) {
                throw new \TypeError(\sprintf('Return value of "%s::execute()" must be of the type int, "%s" returned.', static::class, get_debug_type($statusCode)));
            }
        }
        return is_numeric($statusCode) ? (int) $statusCode : 0;
    }
    /**
     * Adds suggestions to $suggestions for the current completion input (e.g. option or argument).
     */
    public function complete(CompletionInput $input, CompletionSuggestions $suggestions): void
    {
        $definition = $this->getDefinition();
        if (CompletionInput::TYPE_OPTION_VALUE === $input->getCompletionType() && $definition->hasOption($input->getCompletionName())) {
            $definition->getOption($input->getCompletionName())->complete($input, $suggestions);
        } elseif (CompletionInput::TYPE_ARGUMENT_VALUE === $input->getCompletionType() && $definition->hasArgument($input->getCompletionName())) {
            $definition->getArgument($input->getCompletionName())->complete($input, $suggestions);
        }
    }
    /**
     * Sets the code to execute when running this command.
     *
     * If this method is used, it overrides the code defined
     * in the execute() method.
     *
     * @param callable $code A callable(InputInterface $input, OutputInterface $output)
     *
     * @return $this
     *
     * @throws InvalidArgumentException
     *
     * @see execute()
     */
    public function setCode(callable $code): static
    {
        if ($code instanceof \Closure) {
            $r = new \ReflectionFunction($code);
            if (null === $r->getClosureThis()) {
                set_error_handler(static function () {
                });
                try {
                    if ($c = \Closure::bind($code, $this)) {
                        $code = $c;
                    }
                } finally {
                    restore_error_handler();
                }
            }
        } else {
            $code = $code(...);
        }
        $this->code = $code;
        return $this;
    }
    /**
     * Merges the application definition with the command definition.
     *
     * This method is not part of public API and should not be used directly.
     *
     * @param bool $mergeArgs Whether to merge or not the Application definition arguments to Command definition arguments
     *
     * @internal
     */
    public function mergeApplicationDefinition(bool $mergeArgs = \true): void
    {
        if (null === $this->application) {
            return;
        }
        $this->fullDefinition = new InputDefinition();
        $this->fullDefinition->setOptions($this->definition->getOptions());
        $this->fullDefinition->addOptions($this->application->getDefinition()->getOptions());
        if ($mergeArgs) {
            $this->fullDefinition->setArguments($this->application->getDefinition()->getArguments());
            $this->fullDefinition->addArguments($this->definition->getArguments());
        } else {
            $this->fullDefinition->setArguments($this->definition->getArguments());
        }
    }
    /**
     * Sets an array of argument and option instances.
     *
     * @return $this
     */
    public function setDefinition(array|InputDefinition $definition): static
    {
        if ($definition instanceof InputDefinition) {
            $this->definition = $definition;
        } else {
            $this->definition->setDefinition($definition);
        }
        $this->fullDefinition = null;
        return $this;
    }
    /**
     * Gets the InputDefinition attached to this Command.
     */
    public function getDefinition(): InputDefinition
    {
        return $this->fullDefinition ?? $this->getNativeDefinition();
    }
    /**
     * Gets the InputDefinition to be used to create representations of this Command.
     *
     * Can be overridden to provide the original command representation when it would otherwise
     * be changed by merging with the application InputDefinition.
     *
     * This method is not part of public API and should not be used directly.
     */
    public function getNativeDefinition(): InputDefinition
    {
        return $this->definition ?? throw new LogicException(\sprintf('Command class "%s" is not correctly initialized. You probably forgot to call the parent constructor.', static::class));
    }
    /**
     * Adds an argument.
     *
     * @param $mode    The argument mode: InputArgument::REQUIRED or InputArgument::OPTIONAL
     * @param $default The default value (for InputArgument::OPTIONAL mode only)
     * @param array|\Closure(CompletionInput,CompletionSuggestions):list<string|Suggestion> $suggestedValues The values used for input completion
     *
     * @return $this
     *
     * @throws InvalidArgumentException When argument mode is not valid
     */
    public function addArgument(string $name, ?int $mode = null, string $description = '', mixed $default = null): static
    {
        $suggestedValues = 5 <= \func_num_args() ? func_get_arg(4) : [];
        if (!\is_array($suggestedValues) && !$suggestedValues instanceof \Closure) {
            throw new \TypeError(\sprintf('Argument 5 passed to "%s()" must be array or \Closure, "%s" given.', __METHOD__, get_debug_type($suggestedValues)));
        }
        $this->definition->addArgument(new InputArgument($name, $mode, $description, $default, $suggestedValues));
        $this->fullDefinition?->addArgument(new InputArgument($name, $mode, $description, $default, $suggestedValues));
        return $this;
    }
    /**
     * Adds an option.
     *
     * @param $shortcut The shortcuts, can be null, a string of shortcuts delimited by | or an array of shortcuts
     * @param $mode     The option mode: One of the InputOption::VALUE_* constants
     * @param $default  The default value (must be null for InputOption::VALUE_NONE)
     * @param array|\Closure(CompletionInput,CompletionSuggestions):list<string|Suggestion> $suggestedValues The values used for input completion
     *
     * @return $this
     *
     * @throws InvalidArgumentException If option mode is invalid or incompatible
     */
    public function addOption(string $name, string|array|null $shortcut = null, ?int $mode = null, string $description = '', mixed $default = null): static
    {
        $suggestedValues = 6 <= \func_num_args() ? func_get_arg(5) : [];
        if (!\is_array($suggestedValues) && !$suggestedValues instanceof \Closure) {
            throw new \TypeError(\sprintf('Argument 5 passed to "%s()" must be array or \Closure, "%s" given.', __METHOD__, get_debug_type($suggestedValues)));
        }
        $this->definition->addOption(new InputOption($name, $shortcut, $mode, $description, $default, $suggestedValues));
        $this->fullDefinition?->addOption(new InputOption($name, $shortcut, $mode, $description, $default, $suggestedValues));
        return $this;
    }
    /**
     * Sets the name of the command.
     *
     * This method can set both the namespace and the name if
     * you separate them by a colon (:)
     *
     *     $command->setName('foo:bar');
     *
     * @return $this
     *
     * @throws InvalidArgumentException When the name is invalid
     */
    public function setName(string $name): static
    {
        $this->validateName($name);
        $this->name = $name;
        return $this;
    }
    /**
     * Sets the process title of the command.
     *
     * This feature should be used only when creating a long process command,
     * like a daemon.
     *
     * @return $this
     */
    public function setProcessTitle(string $title): static
    {
        $this->processTitle = $title;
        return $this;
    }
    /**
     * Returns the command name.
     */
    public function getName(): ?string
    {
        return $this->name;
    }
    /**
     * @param bool $hidden Whether or not the command should be hidden from the list of commands
     *
     * @return $this
     */
    public function setHidden(bool $hidden = \true): static
    {
        $this->hidden = $hidden;
        return $this;
    }
    /**
     * @return bool whether the command should be publicly shown or not
     */
    public function isHidden(): bool
    {
        return $this->hidden;
    }
    /**
     * Sets the description for the command.
     *
     * @return $this
     */
    public function setDescription(string $description): static
    {
        $this->description = $description;
        return $this;
    }
    /**
     * Returns the description for the command.
     */
    public function getDescription(): string
    {
        return $this->description;
    }
    /**
     * Sets the help for the command.
     *
     * @return $this
     */
    public function setHelp(string $help): static
    {
        $this->help = $help;
        return $this;
    }
    /**
     * Returns the help for the command.
     */
    public function getHelp(): string
    {
        return $this->help;
    }
    /**
     * Returns the processed help for the command replacing the %command.name% and
     * %command.full_name% patterns with the real values dynamically.
     */
    public function getProcessedHelp(): string
    {
        $name = $this->name;
        $isSingleCommand = $this->application?->isSingleCommand();
        $placeholders = ['%command.name%', '%command.full_name%'];
        $replacements = [$name, $isSingleCommand ? $_SERVER['PHP_SELF'] : $_SERVER['PHP_SELF'] . ' ' . $name];
        return str_replace($placeholders, $replacements, $this->getHelp() ?: $this->getDescription());
    }
    /**
     * Sets the aliases for the command.
     *
     * @param string[] $aliases An array of aliases for the command
     *
     * @return $this
     *
     * @throws InvalidArgumentException When an alias is invalid
     */
    public function setAliases(iterable $aliases): static
    {
        $list = [];
        foreach ($aliases as $alias) {
            $this->validateName($alias);
            $list[] = $alias;
        }
        $this->aliases = \is_array($aliases) ? $aliases : $list;
        return $this;
    }
    /**
     * Returns the aliases for the command.
     */
    public function getAliases(): array
    {
        return $this->aliases;
    }
    /**
     * Returns the synopsis for the command.
     *
     * @param bool $short Whether to show the short version of the synopsis (with options folded) or not
     */
    public function getSynopsis(bool $short = \false): string
    {
        $key = $short ? 'short' : 'long';
        if (!isset($this->synopsis[$key])) {
            $this->synopsis[$key] = trim(\sprintf('%s %s', $this->name, $this->definition->getSynopsis($short)));
        }
        return $this->synopsis[$key];
    }
    /**
     * Add a command usage example, it'll be prefixed with the command name.
     *
     * @return $this
     */
    public function addUsage(string $usage): static
    {
        if (!str_starts_with($usage, $this->name)) {
            $usage = \sprintf('%s %s', $this->name, $usage);
        }
        $this->usages[] = $usage;
        return $this;
    }
    /**
     * Returns alternative usages of the command.
     */
    public function getUsages(): array
    {
        return $this->usages;
    }
    /**
     * Gets a helper instance by name.
     *
     * @return HelperInterface
     *
     * @throws LogicException           if no HelperSet is defined
     * @throws InvalidArgumentException if the helper is not defined
     */
    public function getHelper(string $name): mixed
    {
        if (null === $this->helperSet) {
            throw new LogicException(\sprintf('Cannot retrieve helper "%s" because there is no HelperSet defined. Did you forget to add your command to the application or to set the application on the command using the setApplication() method? You can also set the HelperSet directly using the setHelperSet() method.', $name));
        }
        return $this->helperSet->get($name);
    }
    /**
     * Validates a command name.
     *
     * It must be non-empty and parts can optionally be separated by ":".
     *
     * @throws InvalidArgumentException When the name is invalid
     */
    private function validateName(string $name): void
    {
        if (!preg_match('/^[^\:]++(\:[^\:]++)*$/', $name)) {
            throw new InvalidArgumentException(\sprintf('Command name "%s" is invalid.', $name));
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Console\Helper;

use _ContaoManager\Symfony\Component\Console\Exception\InvalidArgumentException;
use _ContaoManager\Symfony\Component\Console\Exception\LogicException;
/**
 * Defines the styles for a Table.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 * @author Саша Стаменковић <umpirsky@gmail.com>
 * @author Dany Maillard <danymaillard93b@gmail.com>
 */
class TableStyle
{
    private string $paddingChar = ' ';
    private string $horizontalOutsideBorderChar = '-';
    private string $horizontalInsideBorderChar = '-';
    private string $verticalOutsideBorderChar = '|';
    private string $verticalInsideBorderChar = '|';
    private string $crossingChar = '+';
    private string $crossingTopRightChar = '+';
    private string $crossingTopMidChar = '+';
    private string $crossingTopLeftChar = '+';
    private string $crossingMidRightChar = '+';
    private string $crossingBottomRightChar = '+';
    private string $crossingBottomMidChar = '+';
    private string $crossingBottomLeftChar = '+';
    private string $crossingMidLeftChar = '+';
    private string $crossingTopLeftBottomChar = '+';
    private string $crossingTopMidBottomChar = '+';
    private string $crossingTopRightBottomChar = '+';
    private string $headerTitleFormat = '<fg=black;bg=white;options=bold> %s </>';
    private string $footerTitleFormat = '<fg=black;bg=white;options=bold> %s </>';
    private string $cellHeaderFormat = '<info>%s</info>';
    private string $cellRowFormat = '%s';
    private string $cellRowContentFormat = ' %s ';
    private string $borderFormat = '%s';
    private int $padType = \STR_PAD_RIGHT;
    /**
     * Sets padding character, used for cell padding.
     *
     * @return $this
     */
    public function setPaddingChar(string $paddingChar): static
    {
        if (!$paddingChar) {
            throw new LogicException('The padding char must not be empty.');
        }
        $this->paddingChar = $paddingChar;
        return $this;
    }
    /**
     * Gets padding character, used for cell padding.
     */
    public function getPaddingChar(): string
    {
        return $this->paddingChar;
    }
    /**
     * Sets horizontal border characters.
     *
     * <code>
     * ╔═══════════════╤══════════════════════════╤══════════════════╗
     * ║ ISBN          │ Title                    │ Author           ║
     * ╠═══════1═══════╪══════════════════════════╪══════════════════╣
     * ║ 99921-58-10-7 │ Divine Comedy            │ Dante Alighieri  ║
     * ║ 9971-5-0210-0 │ A Tale of Two Cities     │ Charles Dickens  ║
     * ╟───────2───────┼──────────────────────────┼──────────────────╢
     * ║ 960-425-059-0 │ The Lord of the Rings    │ J. R. R. Tolkien ║
     * ║ 80-902734-1-6 │ And Then There Were None │ Agatha Christie  ║
     * ╚═══════════════╧══════════════════════════╧══════════════════╝
     * </code>
     *
     * @return $this
     */
    public function setHorizontalBorderChars(string $outside, ?string $inside = null): static
    {
        $this->horizontalOutsideBorderChar = $outside;
        $this->horizontalInsideBorderChar = $inside ?? $outside;
        return $this;
    }
    /**
     * Sets vertical border characters.
     *
     * <code>
     * ╔═══════════════╤══════════════════════════╤══════════════════╗
     * 1 ISBN          2 Title                    │ Author           ║
     * ╠═══════════════╪══════════════════════════╪══════════════════╣
     * ║ 99921-58-10-7 │ Divine Comedy            │ Dante Alighieri  ║
     * ║ 9971-5-0210-0 │ A Tale of Two Cities     │ Charles Dickens  ║
     * ║ 960-425-059-0 │ The Lord of the Rings    │ J. R. R. Tolkien ║
     * ║ 80-902734-1-6 │ And Then There Were None │ Agatha Christie  ║
     * ╚═══════════════╧══════════════════════════╧══════════════════╝
     * </code>
     *
     * @return $this
     */
    public function setVerticalBorderChars(string $outside, ?string $inside = null): static
    {
        $this->verticalOutsideBorderChar = $outside;
        $this->verticalInsideBorderChar = $inside ?? $outside;
        return $this;
    }
    /**
     * Gets border characters.
     *
     * @internal
     */
    public function getBorderChars(): array
    {
        return [$this->horizontalOutsideBorderChar, $this->verticalOutsideBorderChar, $this->horizontalInsideBorderChar, $this->verticalInsideBorderChar];
    }
    /**
     * Sets crossing characters.
     *
     * Example:
     * <code>
     * 1═══════════════2══════════════════════════2══════════════════3
     * ║ ISBN          │ Title                    │ Author           ║
     * 8'══════════════0'═════════════════════════0'═════════════════4'
     * ║ 99921-58-10-7 │ Divine Comedy            │ Dante Alighieri  ║
     * ║ 9971-5-0210-0 │ A Tale of Two Cities     │ Charles Dickens  ║
     * 8───────────────0──────────────────────────0──────────────────4
     * ║ 960-425-059-0 │ The Lord of the Rings    │ J. R. R. Tolkien ║
     * ║ 80-902734-1-6 │ And Then There Were None │ Agatha Christie  ║
     * 7═══════════════6══════════════════════════6══════════════════5
     * </code>
     *
     * @param string      $cross          Crossing char (see #0 of example)
     * @param string      $topLeft        Top left char (see #1 of example)
     * @param string      $topMid         Top mid char (see #2 of example)
     * @param string      $topRight       Top right char (see #3 of example)
     * @param string      $midRight       Mid right char (see #4 of example)
     * @param string      $bottomRight    Bottom right char (see #5 of example)
     * @param string      $bottomMid      Bottom mid char (see #6 of example)
     * @param string      $bottomLeft     Bottom left char (see #7 of example)
     * @param string      $midLeft        Mid left char (see #8 of example)
     * @param string|null $topLeftBottom  Top left bottom char (see #8' of example), equals to $midLeft if null
     * @param string|null $topMidBottom   Top mid bottom char (see #0' of example), equals to $cross if null
     * @param string|null $topRightBottom Top right bottom char (see #4' of example), equals to $midRight if null
     *
     * @return $this
     */
    public function setCrossingChars(string $cross, string $topLeft, string $topMid, string $topRight, string $midRight, string $bottomRight, string $bottomMid, string $bottomLeft, string $midLeft, ?string $topLeftBottom = null, ?string $topMidBottom = null, ?string $topRightBottom = null): static
    {
        $this->crossingChar = $cross;
        $this->crossingTopLeftChar = $topLeft;
        $this->crossingTopMidChar = $topMid;
        $this->crossingTopRightChar = $topRight;
        $this->crossingMidRightChar = $midRight;
        $this->crossingBottomRightChar = $bottomRight;
        $this->crossingBottomMidChar = $bottomMid;
        $this->crossingBottomLeftChar = $bottomLeft;
        $this->crossingMidLeftChar = $midLeft;
        $this->crossingTopLeftBottomChar = $topLeftBottom ?? $midLeft;
        $this->crossingTopMidBottomChar = $topMidBottom ?? $cross;
        $this->crossingTopRightBottomChar = $topRightBottom ?? $midRight;
        return $this;
    }
    /**
     * Sets default crossing character used for each cross.
     *
     * @see {@link setCrossingChars()} for setting each crossing individually.
     */
    public function setDefaultCrossingChar(string $char): self
    {
        return $this->setCrossingChars($char, $char, $char, $char, $char, $char, $char, $char, $char);
    }
    /**
     * Gets crossing character.
     */
    public function getCrossingChar(): string
    {
        return $this->crossingChar;
    }
    /**
     * Gets crossing characters.
     *
     * @internal
     */
    public function getCrossingChars(): array
    {
        return [$this->crossingChar, $this->crossingTopLeftChar, $this->crossingTopMidChar, $this->crossingTopRightChar, $this->crossingMidRightChar, $this->crossingBottomRightChar, $this->crossingBottomMidChar, $this->crossingBottomLeftChar, $this->crossingMidLeftChar, $this->crossingTopLeftBottomChar, $this->crossingTopMidBottomChar, $this->crossingTopRightBottomChar];
    }
    /**
     * Sets header cell format.
     *
     * @return $this
     */
    public function setCellHeaderFormat(string $cellHeaderFormat): static
    {
        $this->cellHeaderFormat = $cellHeaderFormat;
        return $this;
    }
    /**
     * Gets header cell format.
     */
    public function getCellHeaderFormat(): string
    {
        return $this->cellHeaderFormat;
    }
    /**
     * Sets row cell format.
     *
     * @return $this
     */
    public function setCellRowFormat(string $cellRowFormat): static
    {
        $this->cellRowFormat = $cellRowFormat;
        return $this;
    }
    /**
     * Gets row cell format.
     */
    public function getCellRowFormat(): string
    {
        return $this->cellRowFormat;
    }
    /**
     * Sets row cell content format.
     *
     * @return $this
     */
    public function setCellRowContentFormat(string $cellRowContentFormat): static
    {
        $this->cellRowContentFormat = $cellRowContentFormat;
        return $this;
    }
    /**
     * Gets row cell content format.
     */
    public function getCellRowContentFormat(): string
    {
        return $this->cellRowContentFormat;
    }
    /**
     * Sets table border format.
     *
     * @return $this
     */
    public function setBorderFormat(string $borderFormat): static
    {
        $this->borderFormat = $borderFormat;
        return $this;
    }
    /**
     * Gets table border format.
     */
    public function getBorderFormat(): string
    {
        return $this->borderFormat;
    }
    /**
     * Sets cell padding type.
     *
     * @return $this
     */
    public function setPadType(int $padType): static
    {
        if (!\in_array($padType, [\STR_PAD_LEFT, \STR_PAD_RIGHT, \STR_PAD_BOTH], \true)) {
            throw new InvalidArgumentException('Invalid padding type. Expected one of (STR_PAD_LEFT, STR_PAD_RIGHT, STR_PAD_BOTH).');
        }
        $this->padType = $padType;
        return $this;
    }
    /**
     * Gets cell padding type.
     */
    public function getPadType(): int
    {
        return $this->padType;
    }
    public function getHeaderTitleFormat(): string
    {
        return $this->headerTitleFormat;
    }
    /**
     * @return $this
     */
    public function setHeaderTitleFormat(string $format): static
    {
        $this->headerTitleFormat = $format;
        return $this;
    }
    public function getFooterTitleFormat(): string
    {
        return $this->footerTitleFormat;
    }
    /**
     * @return $this
     */
    public function setFooterTitleFormat(string $format): static
    {
        $this->footerTitleFormat = $format;
        return $this;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Console\Helper;

/**
 * @internal
 */
class TableRows implements \IteratorAggregate
{
    private \Closure $generator;
    public function __construct(\Closure $generator)
    {
        $this->generator = $generator;
    }
    public function getIterator(): \Traversable
    {
        return ($this->generator)();
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Console\Helper;

use _ContaoManager\Symfony\Component\Console\Formatter\OutputFormatter;
use _ContaoManager\Symfony\Component\Console\Output\OutputInterface;
use _ContaoManager\Symfony\Component\Console\Question\ChoiceQuestion;
use _ContaoManager\Symfony\Component\Console\Question\ConfirmationQuestion;
use _ContaoManager\Symfony\Component\Console\Question\Question;
use _ContaoManager\Symfony\Component\Console\Style\SymfonyStyle;
/**
 * Symfony Style Guide compliant question helper.
 *
 * @author Kevin Bond <kevinbond@gmail.com>
 */
class SymfonyQuestionHelper extends QuestionHelper
{
    /**
     * @return void
     */
    protected function writePrompt(OutputInterface $output, Question $question)
    {
        $text = OutputFormatter::escapeTrailingBackslash($question->getQuestion());
        $default = $question->getDefault();
        if ($question->isMultiline()) {
            $text .= \sprintf(' (press %s to continue)', $this->getEofShortcut($output));
        }
        switch (\true) {
            case null === $default:
                $text = \sprintf(' <info>%s</info>:', $text);
                break;
            case $question instanceof ConfirmationQuestion:
                $text = \sprintf(' <info>%s (yes/no)</info> [<comment>%s</comment>]:', $text, $default ? 'yes' : 'no');
                break;
            case $question instanceof ChoiceQuestion && $question->isMultiselect():
                $choices = $question->getChoices();
                $default = explode(',', $default);
                foreach ($default as $key => $value) {
                    $default[$key] = $choices[trim($value)];
                }
                $text = \sprintf(' <info>%s</info> [<comment>%s</comment>]:', $text, OutputFormatter::escape(implode(', ', $default)));
                break;
            case $question instanceof ChoiceQuestion:
                $choices = $question->getChoices();
                $text = \sprintf(' <info>%s</info> [<comment>%s</comment>]:', $text, OutputFormatter::escape($choices[$default] ?? $default));
                break;
            default:
                $text = \sprintf(' <info>%s</info> [<comment>%s</comment>]:', $text, OutputFormatter::escape($default));
        }
        $output->writeln($text);
        $prompt = ' > ';
        if ($question instanceof ChoiceQuestion) {
            $output->writeln($this->formatChoiceQuestionChoices($question, 'comment'));
            $prompt = $question->getPrompt();
        }
        $output->write($prompt);
    }
    /**
     * @return void
     */
    protected function writeError(OutputInterface $output, \Exception $error)
    {
        if ($output instanceof SymfonyStyle) {
            $output->newLine();
            $output->error($error->getMessage());
            return;
        }
        parent::writeError($output, $error);
    }
    private function getEofShortcut(OutputInterface $output): string
    {
        if ('\\' === \DIRECTORY_SEPARATOR && !$output->isDecorated()) {
            return '<comment>Ctrl+Z</comment> then <comment>Enter</comment>';
        }
        return '<comment>Ctrl+D</comment>';
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Console\Helper;

/**
 * HelperInterface is the interface all helpers must implement.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
interface HelperInterface
{
    /**
     * Sets the helper set associated with this helper.
     *
     * @return void
     */
    public function setHelperSet(?HelperSet $helperSet);
    /**
     * Gets the helper set associated with this helper.
     */
    public function getHelperSet(): ?HelperSet;
    /**
     * Returns the canonical name of this helper.
     *
     * @return string
     */
    public function getName();
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Console\Helper;

use _ContaoManager\Symfony\Component\Console\Exception\InvalidArgumentException;
/**
 * @author Abdellatif Ait boudad <a.aitboudad@gmail.com>
 */
class TableCell
{
    private string $value;
    private array $options = ['rowspan' => 1, 'colspan' => 1, 'style' => null];
    public function __construct(string $value = '', array $options = [])
    {
        $this->value = $value;
        // check option names
        if ($diff = array_diff(array_keys($options), array_keys($this->options))) {
            throw new InvalidArgumentException(\sprintf('The TableCell does not support the following options: \'%s\'.', implode('\', \'', $diff)));
        }
        if (isset($options['style']) && !$options['style'] instanceof TableCellStyle) {
            throw new InvalidArgumentException('The style option must be an instance of "TableCellStyle".');
        }
        $this->options = array_merge($this->options, $options);
    }
    /**
     * Returns the cell value.
     */
    public function __toString(): string
    {
        return $this->value;
    }
    /**
     * Gets number of colspan.
     */
    public function getColspan(): int
    {
        return (int) $this->options['colspan'];
    }
    /**
     * Gets number of rowspan.
     */
    public function getRowspan(): int
    {
        return (int) $this->options['rowspan'];
    }
    public function getStyle(): ?TableCellStyle
    {
        return $this->options['style'];
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Console\Helper;

use _ContaoManager\Symfony\Component\Console\Output\ConsoleOutputInterface;
use _ContaoManager\Symfony\Component\Console\Output\OutputInterface;
use _ContaoManager\Symfony\Component\Process\Exception\ProcessFailedException;
use _ContaoManager\Symfony\Component\Process\Process;
/**
 * The ProcessHelper class provides helpers to run external processes.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 *
 * @final
 */
class ProcessHelper extends Helper
{
    /**
     * Runs an external process.
     *
     * @param array|Process $cmd      An instance of Process or an array of the command and arguments
     * @param callable|null $callback A PHP callback to run whenever there is some
     *                                output available on STDOUT or STDERR
     */
    public function run(OutputInterface $output, array|Process $cmd, ?string $error = null, ?callable $callback = null, int $verbosity = OutputInterface::VERBOSITY_VERY_VERBOSE): Process
    {
        if (!class_exists(Process::class)) {
            throw new \LogicException('The ProcessHelper cannot be run as the Process component is not installed. Try running "compose require symfony/process".');
        }
        if ($output instanceof ConsoleOutputInterface) {
            $output = $output->getErrorOutput();
        }
        $formatter = $this->getHelperSet()->get('debug_formatter');
        if ($cmd instanceof Process) {
            $cmd = [$cmd];
        }
        if (\is_string($cmd[0] ?? null)) {
            $process = new Process($cmd);
            $cmd = [];
        } elseif (($cmd[0] ?? null) instanceof Process) {
            $process = $cmd[0];
            unset($cmd[0]);
        } else {
            throw new \InvalidArgumentException(\sprintf('Invalid command provided to "%s()": the command should be an array whose first element is either the path to the binary to run or a "Process" object.', __METHOD__));
        }
        if ($verbosity <= $output->getVerbosity()) {
            $output->write($formatter->start(spl_object_hash($process), $this->escapeString($process->getCommandLine())));
        }
        if ($output->isDebug()) {
            $callback = $this->wrapCallback($output, $process, $callback);
        }
        $process->run($callback, $cmd);
        if ($verbosity <= $output->getVerbosity()) {
            $message = $process->isSuccessful() ? 'Command ran successfully' : \sprintf('%s Command did not run successfully', $process->getExitCode());
            $output->write($formatter->stop(spl_object_hash($process), $message, $process->isSuccessful()));
        }
        if (!$process->isSuccessful() && null !== $error) {
            $output->writeln(\sprintf('<error>%s</error>', $this->escapeString($error)));
        }
        return $process;
    }
    /**
     * Runs the process.
     *
     * This is identical to run() except that an exception is thrown if the process
     * exits with a non-zero exit code.
     *
     * @param array|Process $cmd      An instance of Process or a command to run
     * @param callable|null $callback A PHP callback to run whenever there is some
     *                                output available on STDOUT or STDERR
     *
     * @throws ProcessFailedException
     *
     * @see run()
     */
    public function mustRun(OutputInterface $output, array|Process $cmd, ?string $error = null, ?callable $callback = null): Process
    {
        $process = $this->run($output, $cmd, $error, $callback);
        if (!$process->isSuccessful()) {
            throw new ProcessFailedException($process);
        }
        return $process;
    }
    /**
     * Wraps a Process callback to add debugging output.
     */
    public function wrapCallback(OutputInterface $output, Process $process, ?callable $callback = null): callable
    {
        if ($output instanceof ConsoleOutputInterface) {
            $output = $output->getErrorOutput();
        }
        $formatter = $this->getHelperSet()->get('debug_formatter');
        return function ($type, $buffer) use ($output, $process, $callback, $formatter) {
            $output->write($formatter->progress(spl_object_hash($process), $this->escapeString($buffer), Process::ERR === $type));
            if (null !== $callback) {
                $callback($type, $buffer);
            }
        };
    }
    private function escapeString(string $str): string
    {
        return str_replace('<', '\<', $str);
    }
    public function getName(): string
    {
        return 'process';
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Console\Helper;

/**
 * Marks a row as being a separator.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class TableSeparator extends TableCell
{
    public function __construct(array $options = [])
    {
        parent::__construct('', $options);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Console\Helper;

/**
 * Simple output wrapper for "tagged outputs" instead of wordwrap(). This solution is based on a StackOverflow
 * answer: https://stackoverflow.com/a/20434776/1476819 from user557597 (alias SLN).
 *
 *  (?:
 *       # -- Words/Characters
 *       (                       # (1 start)
 *            (?>                     # Atomic Group - Match words with valid breaks
 *                 .{1,16}                 #  1-N characters
 *                                         #  Followed by one of 4 prioritized, non-linebreak whitespace
 *                 (?:                     #  break types:
 *                      (?<= [^\S\r\n] )        # 1. - Behind a non-linebreak whitespace
 *                      [^\S\r\n]?              #      ( optionally accept an extra non-linebreak whitespace )
 *                   |  (?= \r? \n )            # 2. - Ahead a linebreak
 *                   |  $                       # 3. - EOS
 *                   |  [^\S\r\n]               # 4. - Accept an extra non-linebreak whitespace
 *                 )
 *            )                       # End atomic group
 *         |
 *            .{1,16}                 # No valid word breaks, just break on the N'th character
 *       )                       # (1 end)
 *       (?: \r? \n )?           # Optional linebreak after Words/Characters
 *    |
 *       # -- Or, Linebreak
 *       (?: \r? \n | $ )        # Stand alone linebreak or at EOS
 *  )
 *
 * @author Krisztián Ferenczi <ferenczi.krisztian@gmail.com>
 *
 * @see https://stackoverflow.com/a/20434776/1476819
 */
final class OutputWrapper
{
    private const TAG_OPEN_REGEX_SEGMENT = '[a-z](?:[^\\\\<>]*+ | \\\\.)*';
    private const TAG_CLOSE_REGEX_SEGMENT = '[a-z][^<>]*+';
    private const URL_PATTERN = 'https?://\S+';
    public function __construct(private bool $allowCutUrls = \false)
    {
    }
    public function wrap(string $text, int $width, string $break = "\n"): string
    {
        if (!$width) {
            return $text;
        }
        $tagPattern = \sprintf('<(?:(?:%s)|/(?:%s)?)>', self::TAG_OPEN_REGEX_SEGMENT, self::TAG_CLOSE_REGEX_SEGMENT);
        $limitPattern = "{1,{$width}}";
        $patternBlocks = [$tagPattern];
        if (!$this->allowCutUrls) {
            $patternBlocks[] = self::URL_PATTERN;
        }
        $patternBlocks[] = '.';
        $blocks = implode('|', $patternBlocks);
        $rowPattern = "(?:{$blocks}){$limitPattern}";
        $pattern = \sprintf('#(?:((?>(%1$s)((?<=[^\S\r\n])[^\S\r\n]?|(?=\r?\n)|$|[^\S\r\n]))|(%1$s))(?:\r?\n)?|(?:\r?\n|$))#imux', $rowPattern);
        $output = rtrim(preg_replace($pattern, '\1' . $break, $text), $break);
        return str_replace(' ' . $break, $break, $output);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Console\Helper;

use _ContaoManager\Symfony\Component\Console\Formatter\OutputFormatter;
/**
 * The Formatter class provides helpers to format messages.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class FormatterHelper extends Helper
{
    /**
     * Formats a message within a section.
     */
    public function formatSection(string $section, string $message, string $style = 'info'): string
    {
        return \sprintf('<%s>[%s]</%s> %s', $style, $section, $style, $message);
    }
    /**
     * Formats a message as a block of text.
     */
    public function formatBlock(string|array $messages, string $style, bool $large = \false): string
    {
        if (!\is_array($messages)) {
            $messages = [$messages];
        }
        $len = 0;
        $lines = [];
        foreach ($messages as $message) {
            $message = OutputFormatter::escape($message);
            $lines[] = \sprintf($large ? '  %s  ' : ' %s ', $message);
            $len = max(self::width($message) + ($large ? 4 : 2), $len);
        }
        $messages = $large ? [str_repeat(' ', $len)] : [];
        for ($i = 0; isset($lines[$i]); ++$i) {
            $messages[] = $lines[$i] . str_repeat(' ', $len - self::width($lines[$i]));
        }
        if ($large) {
            $messages[] = str_repeat(' ', $len);
        }
        for ($i = 0; isset($messages[$i]); ++$i) {
            $messages[$i] = \sprintf('<%s>%s</%s>', $style, $messages[$i], $style);
        }
        return implode("\n", $messages);
    }
    /**
     * Truncates a message to the given length.
     */
    public function truncate(string $message, int $length, string $suffix = '...'): string
    {
        $computedLength = $length - self::width($suffix);
        if ($computedLength > self::width($message)) {
            return $message;
        }
        return self::substr($message, 0, $length) . $suffix;
    }
    public function getName(): string
    {
        return 'formatter';
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Console\Helper;

use _ContaoManager\Symfony\Component\Console\Exception\InvalidArgumentException;
/**
 * @author Yewhen Khoptynskyi <khoptynskyi@gmail.com>
 */
class TableCellStyle
{
    public const DEFAULT_ALIGN = 'left';
    private const TAG_OPTIONS = ['fg', 'bg', 'options'];
    private const ALIGN_MAP = ['left' => \STR_PAD_RIGHT, 'center' => \STR_PAD_BOTH, 'right' => \STR_PAD_LEFT];
    private array $options = ['fg' => 'default', 'bg' => 'default', 'options' => null, 'align' => self::DEFAULT_ALIGN, 'cellFormat' => null];
    public function __construct(array $options = [])
    {
        if ($diff = array_diff(array_keys($options), array_keys($this->options))) {
            throw new InvalidArgumentException(\sprintf('The TableCellStyle does not support the following options: \'%s\'.', implode('\', \'', $diff)));
        }
        if (isset($options['align']) && !\array_key_exists($options['align'], self::ALIGN_MAP)) {
            throw new InvalidArgumentException(\sprintf('Wrong align value. Value must be following: \'%s\'.', implode('\', \'', array_keys(self::ALIGN_MAP))));
        }
        $this->options = array_merge($this->options, $options);
    }
    public function getOptions(): array
    {
        return $this->options;
    }
    /**
     * Gets options we need for tag for example fg, bg.
     *
     * @return string[]
     */
    public function getTagOptions(): array
    {
        return array_filter($this->getOptions(), fn($key) => \in_array($key, self::TAG_OPTIONS) && isset($this->options[$key]), \ARRAY_FILTER_USE_KEY);
    }
    public function getPadByAlign(): int
    {
        return self::ALIGN_MAP[$this->getOptions()['align']];
    }
    public function getCellFormat(): ?string
    {
        return $this->getOptions()['cellFormat'];
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Console\Helper;

use _ContaoManager\Symfony\Component\Console\Cursor;
use _ContaoManager\Symfony\Component\Console\Exception\LogicException;
use _ContaoManager\Symfony\Component\Console\Output\ConsoleOutputInterface;
use _ContaoManager\Symfony\Component\Console\Output\ConsoleSectionOutput;
use _ContaoManager\Symfony\Component\Console\Output\OutputInterface;
use _ContaoManager\Symfony\Component\Console\Terminal;
/**
 * The ProgressBar provides helpers to display progress output.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 * @author Chris Jones <leeked@gmail.com>
 */
final class ProgressBar
{
    public const FORMAT_VERBOSE = 'verbose';
    public const FORMAT_VERY_VERBOSE = 'very_verbose';
    public const FORMAT_DEBUG = 'debug';
    public const FORMAT_NORMAL = 'normal';
    private const FORMAT_VERBOSE_NOMAX = 'verbose_nomax';
    private const FORMAT_VERY_VERBOSE_NOMAX = 'very_verbose_nomax';
    private const FORMAT_DEBUG_NOMAX = 'debug_nomax';
    private const FORMAT_NORMAL_NOMAX = 'normal_nomax';
    private int $barWidth = 28;
    private string $barChar;
    private string $emptyBarChar = '-';
    private string $progressChar = '>';
    private ?string $format = null;
    private ?string $internalFormat = null;
    private ?int $redrawFreq = 1;
    private int $writeCount = 0;
    private float $lastWriteTime = 0;
    private float $minSecondsBetweenRedraws = 0;
    private float $maxSecondsBetweenRedraws = 1;
    private OutputInterface $output;
    private int $step = 0;
    private int $startingStep = 0;
    private ?int $max = null;
    private int $startTime;
    private int $stepWidth;
    private float $percent = 0.0;
    private array $messages = [];
    private bool $overwrite = \true;
    private Terminal $terminal;
    private ?string $previousMessage = null;
    private Cursor $cursor;
    private array $placeholders = [];
    private static array $formatters;
    private static array $formats;
    /**
     * @param int $max Maximum steps (0 if unknown)
     */
    public function __construct(OutputInterface $output, int $max = 0, float $minSecondsBetweenRedraws = 1 / 25)
    {
        if ($output instanceof ConsoleOutputInterface) {
            $output = $output->getErrorOutput();
        }
        $this->output = $output;
        $this->setMaxSteps($max);
        $this->terminal = new Terminal();
        if (0 < $minSecondsBetweenRedraws) {
            $this->redrawFreq = null;
            $this->minSecondsBetweenRedraws = $minSecondsBetweenRedraws;
        }
        if (!$this->output->isDecorated()) {
            // disable overwrite when output does not support ANSI codes.
            $this->overwrite = \false;
            // set a reasonable redraw frequency so output isn't flooded
            $this->redrawFreq = null;
        }
        $this->startTime = time();
        $this->cursor = new Cursor($output);
    }
    /**
     * Sets a placeholder formatter for a given name, globally for all instances of ProgressBar.
     *
     * This method also allow you to override an existing placeholder.
     *
     * @param string                       $name     The placeholder name (including the delimiter char like %)
     * @param callable(ProgressBar):string $callable A PHP callable
     */
    public static function setPlaceholderFormatterDefinition(string $name, callable $callable): void
    {
        self::$formatters ??= self::initPlaceholderFormatters();
        self::$formatters[$name] = $callable;
    }
    /**
     * Gets the placeholder formatter for a given name.
     *
     * @param string $name The placeholder name (including the delimiter char like %)
     */
    public static function getPlaceholderFormatterDefinition(string $name): ?callable
    {
        self::$formatters ??= self::initPlaceholderFormatters();
        return self::$formatters[$name] ?? null;
    }
    /**
     * Sets a placeholder formatter for a given name, for this instance only.
     *
     * @param callable(ProgressBar):string $callable A PHP callable
     */
    public function setPlaceholderFormatter(string $name, callable $callable): void
    {
        $this->placeholders[$name] = $callable;
    }
    /**
     * Gets the placeholder formatter for a given name.
     *
     * @param string $name The placeholder name (including the delimiter char like %)
     */
    public function getPlaceholderFormatter(string $name): ?callable
    {
        return $this->placeholders[$name] ?? $this::getPlaceholderFormatterDefinition($name);
    }
    /**
     * Sets a format for a given name.
     *
     * This method also allow you to override an existing format.
     *
     * @param string $name   The format name
     * @param string $format A format string
     */
    public static function setFormatDefinition(string $name, string $format): void
    {
        self::$formats ??= self::initFormats();
        self::$formats[$name] = $format;
    }
    /**
     * Gets the format for a given name.
     *
     * @param string $name The format name
     */
    public static function getFormatDefinition(string $name): ?string
    {
        self::$formats ??= self::initFormats();
        return self::$formats[$name] ?? null;
    }
    /**
     * Associates a text with a named placeholder.
     *
     * The text is displayed when the progress bar is rendered but only
     * when the corresponding placeholder is part of the custom format line
     * (by wrapping the name with %).
     *
     * @param string $message The text to associate with the placeholder
     * @param string $name    The name of the placeholder
     */
    public function setMessage(string $message, string $name = 'message'): void
    {
        $this->messages[$name] = $message;
    }
    public function getMessage(string $name = 'message'): ?string
    {
        return $this->messages[$name] ?? null;
    }
    public function getStartTime(): int
    {
        return $this->startTime;
    }
    public function getMaxSteps(): int
    {
        return $this->max;
    }
    public function getProgress(): int
    {
        return $this->step;
    }
    private function getStepWidth(): int
    {
        return $this->stepWidth;
    }
    public function getProgressPercent(): float
    {
        return $this->percent;
    }
    public function getBarOffset(): float
    {
        return floor($this->max ? $this->percent * $this->barWidth : (null === $this->redrawFreq ? (int) (min(5, $this->barWidth / 15) * $this->writeCount) : $this->step) % $this->barWidth);
    }
    public function getEstimated(): float
    {
        if (0 === $this->step || $this->step === $this->startingStep) {
            return 0;
        }
        return round((time() - $this->startTime) / ($this->step - $this->startingStep) * $this->max);
    }
    public function getRemaining(): float
    {
        if (0 === $this->step || $this->step === $this->startingStep) {
            return 0;
        }
        return round((time() - $this->startTime) / ($this->step - $this->startingStep) * ($this->max - $this->step));
    }
    public function setBarWidth(int $size): void
    {
        $this->barWidth = max(1, $size);
    }
    public function getBarWidth(): int
    {
        return $this->barWidth;
    }
    public function setBarCharacter(string $char): void
    {
        $this->barChar = $char;
    }
    public function getBarCharacter(): string
    {
        return $this->barChar ?? ($this->max ? '=' : $this->emptyBarChar);
    }
    public function setEmptyBarCharacter(string $char): void
    {
        $this->emptyBarChar = $char;
    }
    public function getEmptyBarCharacter(): string
    {
        return $this->emptyBarChar;
    }
    public function setProgressCharacter(string $char): void
    {
        $this->progressChar = $char;
    }
    public function getProgressCharacter(): string
    {
        return $this->progressChar;
    }
    public function setFormat(string $format): void
    {
        $this->format = null;
        $this->internalFormat = $format;
    }
    /**
     * Sets the redraw frequency.
     *
     * @param int|null $freq The frequency in steps
     */
    public function setRedrawFrequency(?int $freq): void
    {
        $this->redrawFreq = null !== $freq ? max(1, $freq) : null;
    }
    public function minSecondsBetweenRedraws(float $seconds): void
    {
        $this->minSecondsBetweenRedraws = $seconds;
    }
    public function maxSecondsBetweenRedraws(float $seconds): void
    {
        $this->maxSecondsBetweenRedraws = $seconds;
    }
    /**
     * Returns an iterator that will automatically update the progress bar when iterated.
     *
     * @template TKey
     * @template TValue
     *
     * @param iterable<TKey, TValue> $iterable
     * @param int|null               $max      Number of steps to complete the bar (0 if indeterminate), if null it will be inferred from $iterable
     *
     * @return iterable<TKey, TValue>
     */
    public function iterate(iterable $iterable, ?int $max = null): iterable
    {
        $this->start($max ?? (is_countable($iterable) ? \count($iterable) : 0));
        foreach ($iterable as $key => $value) {
            yield $key => $value;
            $this->advance();
        }
        $this->finish();
    }
    /**
     * Starts the progress output.
     *
     * @param int|null $max     Number of steps to complete the bar (0 if indeterminate), null to leave unchanged
     * @param int      $startAt The starting point of the bar (useful e.g. when resuming a previously started bar)
     */
    public function start(?int $max = null, int $startAt = 0): void
    {
        $this->startTime = time();
        $this->step = $startAt;
        $this->startingStep = $startAt;
        $startAt > 0 ? $this->setProgress($startAt) : $this->percent = 0.0;
        if (null !== $max) {
            $this->setMaxSteps($max);
        }
        $this->display();
    }
    /**
     * Advances the progress output X steps.
     *
     * @param int $step Number of steps to advance
     */
    public function advance(int $step = 1): void
    {
        $this->setProgress($this->step + $step);
    }
    /**
     * Sets whether to overwrite the progressbar, false for new line.
     */
    public function setOverwrite(bool $overwrite): void
    {
        $this->overwrite = $overwrite;
    }
    public function setProgress(int $step): void
    {
        if ($this->max && $step > $this->max) {
            $this->max = $step;
        } elseif ($step < 0) {
            $step = 0;
        }
        $redrawFreq = $this->redrawFreq ?? ($this->max ?: 10) / 10;
        $prevPeriod = (int) ($this->step / $redrawFreq);
        $currPeriod = (int) ($step / $redrawFreq);
        $this->step = $step;
        $this->percent = $this->max ? (float) $this->step / $this->max : 0;
        $timeInterval = microtime(\true) - $this->lastWriteTime;
        // Draw regardless of other limits
        if ($this->max === $step) {
            $this->display();
            return;
        }
        // Throttling
        if ($timeInterval < $this->minSecondsBetweenRedraws) {
            return;
        }
        // Draw each step period, but not too late
        if ($prevPeriod !== $currPeriod || $timeInterval >= $this->maxSecondsBetweenRedraws) {
            $this->display();
        }
    }
    public function setMaxSteps(int $max): void
    {
        $this->format = null;
        $this->max = max(0, $max);
        $this->stepWidth = $this->max ? Helper::width((string) $this->max) : 4;
    }
    /**
     * Finishes the progress output.
     */
    public function finish(): void
    {
        if (!$this->max) {
            $this->max = $this->step;
        }
        if ($this->step === $this->max && !$this->overwrite) {
            // prevent double 100% output
            return;
        }
        $this->setProgress($this->max);
    }
    /**
     * Outputs the current progress string.
     */
    public function display(): void
    {
        if (OutputInterface::VERBOSITY_QUIET === $this->output->getVerbosity()) {
            return;
        }
        if (null === $this->format) {
            $this->setRealFormat($this->internalFormat ?: $this->determineBestFormat());
        }
        $this->overwrite($this->buildLine());
    }
    /**
     * Removes the progress bar from the current line.
     *
     * This is useful if you wish to write some output
     * while a progress bar is running.
     * Call display() to show the progress bar again.
     */
    public function clear(): void
    {
        if (!$this->overwrite) {
            return;
        }
        if (null === $this->format) {
            $this->setRealFormat($this->internalFormat ?: $this->determineBestFormat());
        }
        $this->overwrite('');
    }
    private function setRealFormat(string $format): void
    {
        // try to use the _nomax variant if available
        if (!$this->max && null !== self::getFormatDefinition($format . '_nomax')) {
            $this->format = self::getFormatDefinition($format . '_nomax');
        } elseif (null !== self::getFormatDefinition($format)) {
            $this->format = self::getFormatDefinition($format);
        } else {
            $this->format = $format;
        }
    }
    /**
     * Overwrites a previous message to the output.
     */
    private function overwrite(string $message): void
    {
        if ($this->previousMessage === $message) {
            return;
        }
        $originalMessage = $message;
        if ($this->overwrite) {
            if (null !== $this->previousMessage) {
                if ($this->output instanceof ConsoleSectionOutput) {
                    $messageLines = explode("\n", $this->previousMessage);
                    $lineCount = \count($messageLines);
                    $lastLineWithoutDecoration = Helper::removeDecoration($this->output->getFormatter(), end($messageLines) ?? '');
                    // When the last previous line is empty (without formatting) it is already cleared by the section output, so we don't need to clear it again
                    if ('' === $lastLineWithoutDecoration) {
                        --$lineCount;
                    }
                    foreach ($messageLines as $messageLine) {
                        $messageLineLength = Helper::width(Helper::removeDecoration($this->output->getFormatter(), $messageLine));
                        if ($messageLineLength > $this->terminal->getWidth()) {
                            $lineCount += floor($messageLineLength / $this->terminal->getWidth());
                        }
                    }
                    $this->output->clear($lineCount);
                } else {
                    $lineCount = substr_count($this->previousMessage, "\n");
                    for ($i = 0; $i < $lineCount; ++$i) {
                        $this->cursor->moveToColumn(1);
                        $this->cursor->clearLine();
                        $this->cursor->moveUp();
                    }
                    $this->cursor->moveToColumn(1);
                    $this->cursor->clearLine();
                }
            }
        } elseif ($this->step > 0) {
            $message = \PHP_EOL . $message;
        }
        $this->previousMessage = $originalMessage;
        $this->lastWriteTime = microtime(\true);
        $this->output->write($message);
        ++$this->writeCount;
    }
    private function determineBestFormat(): string
    {
        return match ($this->output->getVerbosity()) {
            // OutputInterface::VERBOSITY_QUIET: display is disabled anyway
            OutputInterface::VERBOSITY_VERBOSE => $this->max ? self::FORMAT_VERBOSE : self::FORMAT_VERBOSE_NOMAX,
            OutputInterface::VERBOSITY_VERY_VERBOSE => $this->max ? self::FORMAT_VERY_VERBOSE : self::FORMAT_VERY_VERBOSE_NOMAX,
            OutputInterface::VERBOSITY_DEBUG => $this->max ? self::FORMAT_DEBUG : self::FORMAT_DEBUG_NOMAX,
            default => $this->max ? self::FORMAT_NORMAL : self::FORMAT_NORMAL_NOMAX,
        };
    }
    private static function initPlaceholderFormatters(): array
    {
        return ['bar' => function (self $bar, OutputInterface $output) {
            $completeBars = $bar->getBarOffset();
            $display = str_repeat($bar->getBarCharacter(), $completeBars);
            if ($completeBars < $bar->getBarWidth()) {
                $emptyBars = $bar->getBarWidth() - $completeBars - Helper::length(Helper::removeDecoration($output->getFormatter(), $bar->getProgressCharacter()));
                $display .= $bar->getProgressCharacter() . str_repeat($bar->getEmptyBarCharacter(), $emptyBars);
            }
            return $display;
        }, 'elapsed' => fn(self $bar) => Helper::formatTime(time() - $bar->getStartTime(), 2), 'remaining' => function (self $bar) {
            if (!$bar->getMaxSteps()) {
                throw new LogicException('Unable to display the remaining time if the maximum number of steps is not set.');
            }
            return Helper::formatTime($bar->getRemaining(), 2);
        }, 'estimated' => function (self $bar) {
            if (!$bar->getMaxSteps()) {
                throw new LogicException('Unable to display the estimated time if the maximum number of steps is not set.');
            }
            return Helper::formatTime($bar->getEstimated(), 2);
        }, 'memory' => fn(self $bar) => Helper::formatMemory(memory_get_usage(\true)), 'current' => fn(self $bar) => str_pad($bar->getProgress(), $bar->getStepWidth(), ' ', \STR_PAD_LEFT), 'max' => fn(self $bar) => $bar->getMaxSteps(), 'percent' => fn(self $bar) => floor($bar->getProgressPercent() * 100)];
    }
    private static function initFormats(): array
    {
        return [self::FORMAT_NORMAL => ' %current%/%max% [%bar%] %percent:3s%%', self::FORMAT_NORMAL_NOMAX => ' %current% [%bar%]', self::FORMAT_VERBOSE => ' %current%/%max% [%bar%] %percent:3s%% %elapsed:6s%', self::FORMAT_VERBOSE_NOMAX => ' %current% [%bar%] %elapsed:6s%', self::FORMAT_VERY_VERBOSE => ' %current%/%max% [%bar%] %percent:3s%% %elapsed:6s%/%estimated:-6s%', self::FORMAT_VERY_VERBOSE_NOMAX => ' %current% [%bar%] %elapsed:6s%', self::FORMAT_DEBUG => ' %current%/%max% [%bar%] %percent:3s%% %elapsed:6s%/%estimated:-6s% %memory:6s%', self::FORMAT_DEBUG_NOMAX => ' %current% [%bar%] %elapsed:6s% %memory:6s%'];
    }
    private function buildLine(): string
    {
        \assert(null !== $this->format);
        $regex = "{%([a-z\\-_]+)(?:\\:([^%]+))?%}i";
        $callback = function ($matches) {
            if ($formatter = $this->getPlaceholderFormatter($matches[1])) {
                $text = $formatter($this, $this->output);
            } elseif (isset($this->messages[$matches[1]])) {
                $text = $this->messages[$matches[1]];
            } else {
                return $matches[0];
            }
            if (isset($matches[2])) {
                $text = \sprintf('%' . $matches[2], $text);
            }
            return $text;
        };
        $line = preg_replace_callback($regex, $callback, $this->format);
        // gets string length for each sub line with multiline format
        $linesLength = array_map(fn($subLine) => Helper::width(Helper::removeDecoration($this->output->getFormatter(), rtrim($subLine, "\r"))), explode("\n", $line));
        $linesWidth = max($linesLength);
        $terminalWidth = $this->terminal->getWidth();
        if ($linesWidth <= $terminalWidth) {
            return $line;
        }
        $this->setBarWidth($this->barWidth - $linesWidth + $terminalWidth);
        return preg_replace_callback($regex, $callback, $this->format);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Console\Helper;

/**
 * TerminalInputHelper stops Ctrl-C and similar signals from leaving the terminal in
 * an unusable state if its settings have been modified when reading user input.
 * This can be an issue on non-Windows platforms.
 *
 * Usage:
 *
 *     $inputHelper = new TerminalInputHelper($inputStream);
 *
 *     ...change terminal settings
 *
 *     // Wait for input before all input reads
 *     $inputHelper->waitForInput();
 *
 *     ...read input
 *
 *     // Call finish to restore terminal settings and signal handlers
 *     $inputHelper->finish()
 *
 * @internal
 */
final class TerminalInputHelper
{
    /** @var resource */
    private $inputStream;
    private bool $isStdin;
    private string $initialState = '';
    private int $signalToKill = 0;
    private array $signalHandlers = [];
    private array $targetSignals = [];
    private bool $withStty;
    /**
     * @param resource $inputStream
     *
     * @throws \RuntimeException If unable to read terminal settings
     */
    public function __construct($inputStream, bool $withStty = \true)
    {
        $this->inputStream = $inputStream;
        $this->isStdin = 'php://stdin' === stream_get_meta_data($inputStream)['uri'];
        $this->withStty = $withStty;
        if ($withStty) {
            if (!\is_string($state = shell_exec('stty -g'))) {
                throw new \RuntimeException('Unable to read the terminal settings.');
            }
            $this->initialState = $state;
            $this->createSignalHandlers();
        }
    }
    /**
     * Waits for input.
     */
    public function waitForInput(): void
    {
        if ($this->isStdin) {
            $r = [$this->inputStream];
            $w = [];
            // Allow signal handlers to run
            while (0 === @stream_select($r, $w, $w, 0, 100)) {
                $r = [$this->inputStream];
            }
        }
        if ($this->withStty) {
            $this->checkForKillSignal();
        }
    }
    /**
     * Restores terminal state and signal handlers.
     */
    public function finish(): void
    {
        if (!$this->withStty) {
            return;
        }
        // Safeguard in case an unhandled kill signal exists
        $this->checkForKillSignal();
        shell_exec('stty ' . $this->initialState);
        $this->signalToKill = 0;
        foreach ($this->signalHandlers as $signal => $originalHandler) {
            pcntl_signal($signal, $originalHandler);
        }
        $this->signalHandlers = [];
        $this->targetSignals = [];
    }
    private function createSignalHandlers(): void
    {
        if (!\function_exists('pcntl_async_signals') || !\function_exists('pcntl_signal') && !\function_exists('_ContaoManager\pcntl_signal')) {
            return;
        }
        pcntl_async_signals(\true);
        $this->targetSignals = [\SIGINT, \SIGQUIT, \SIGTERM];
        foreach ($this->targetSignals as $signal) {
            $this->signalHandlers[$signal] = pcntl_signal_get_handler($signal);
            pcntl_signal($signal, function ($signal) {
                // Save current state, then restore to initial state
                $currentState = shell_exec('stty -g');
                shell_exec('stty ' . $this->initialState);
                $originalHandler = $this->signalHandlers[$signal];
                if (\is_callable($originalHandler)) {
                    $originalHandler($signal);
                    // Handler did not exit, so restore to current state
                    shell_exec('stty ' . $currentState);
                    return;
                }
                // Not a callable, so SIG_DFL or SIG_IGN
                if (\SIG_DFL === $originalHandler) {
                    $this->signalToKill = $signal;
                }
            });
        }
    }
    private function checkForKillSignal(): void
    {
        if (\in_array($this->signalToKill, $this->targetSignals, \true)) {
            // Try posix_kill
            if (\function_exists('posix_kill')) {
                pcntl_signal($this->signalToKill, \SIG_DFL);
                posix_kill(getmypid(), $this->signalToKill);
            }
            // Best attempt fallback
            exit(128 + $this->signalToKill);
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Console\Helper;

/**
 * Helps outputting debug information when running an external program from a command.
 *
 * An external program can be a Process, an HTTP request, or anything else.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class DebugFormatterHelper extends Helper
{
    private const COLORS = ['black', 'red', 'green', 'yellow', 'blue', 'magenta', 'cyan', 'white', 'default'];
    private array $started = [];
    private int $count = -1;
    /**
     * Starts a debug formatting session.
     */
    public function start(string $id, string $message, string $prefix = 'RUN'): string
    {
        $this->started[$id] = ['border' => ++$this->count % \count(self::COLORS)];
        return \sprintf("%s<bg=blue;fg=white> %s </> <fg=blue>%s</>\n", $this->getBorder($id), $prefix, $message);
    }
    /**
     * Adds progress to a formatting session.
     */
    public function progress(string $id, string $buffer, bool $error = \false, string $prefix = 'OUT', string $errorPrefix = 'ERR'): string
    {
        $message = '';
        if ($error) {
            if (isset($this->started[$id]['out'])) {
                $message .= "\n";
                unset($this->started[$id]['out']);
            }
            if (!isset($this->started[$id]['err'])) {
                $message .= \sprintf('%s<bg=red;fg=white> %s </> ', $this->getBorder($id), $errorPrefix);
                $this->started[$id]['err'] = \true;
            }
            $message .= str_replace("\n", \sprintf("\n%s<bg=red;fg=white> %s </> ", $this->getBorder($id), $errorPrefix), $buffer);
        } else {
            if (isset($this->started[$id]['err'])) {
                $message .= "\n";
                unset($this->started[$id]['err']);
            }
            if (!isset($this->started[$id]['out'])) {
                $message .= \sprintf('%s<bg=green;fg=white> %s </> ', $this->getBorder($id), $prefix);
                $this->started[$id]['out'] = \true;
            }
            $message .= str_replace("\n", \sprintf("\n%s<bg=green;fg=white> %s </> ", $this->getBorder($id), $prefix), $buffer);
        }
        return $message;
    }
    /**
     * Stops a formatting session.
     */
    public function stop(string $id, string $message, bool $successful, string $prefix = 'RES'): string
    {
        $trailingEOL = isset($this->started[$id]['out']) || isset($this->started[$id]['err']) ? "\n" : '';
        if ($successful) {
            return \sprintf("%s%s<bg=green;fg=white> %s </> <fg=green>%s</>\n", $trailingEOL, $this->getBorder($id), $prefix, $message);
        }
        $message = \sprintf("%s%s<bg=red;fg=white> %s </> <fg=red>%s</>\n", $trailingEOL, $this->getBorder($id), $prefix, $message);
        unset($this->started[$id]['out'], $this->started[$id]['err']);
        return $message;
    }
    private function getBorder(string $id): string
    {
        return \sprintf('<bg=%s> </>', self::COLORS[$this->started[$id]['border']]);
    }
    public function getName(): string
    {
        return 'debug_formatter';
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Console\Helper;

use _ContaoManager\Symfony\Component\Console\Exception\InvalidArgumentException;
/**
 * HelperSet represents a set of helpers to be used with a command.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 *
 * @implements \IteratorAggregate<string, HelperInterface>
 */
class HelperSet implements \IteratorAggregate
{
    /** @var array<string, HelperInterface> */
    private array $helpers = [];
    /**
     * @param HelperInterface[] $helpers
     */
    public function __construct(array $helpers = [])
    {
        foreach ($helpers as $alias => $helper) {
            $this->set($helper, \is_int($alias) ? null : $alias);
        }
    }
    /**
     * @return void
     */
    public function set(HelperInterface $helper, ?string $alias = null)
    {
        $this->helpers[$helper->getName()] = $helper;
        if (null !== $alias) {
            $this->helpers[$alias] = $helper;
        }
        $helper->setHelperSet($this);
    }
    /**
     * Returns true if the helper if defined.
     */
    public function has(string $name): bool
    {
        return isset($this->helpers[$name]);
    }
    /**
     * Gets a helper value.
     *
     * @throws InvalidArgumentException if the helper is not defined
     */
    public function get(string $name): HelperInterface
    {
        if (!$this->has($name)) {
            throw new InvalidArgumentException(\sprintf('The helper "%s" is not defined.', $name));
        }
        return $this->helpers[$name];
    }
    public function getIterator(): \Traversable
    {
        return new \ArrayIterator($this->helpers);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Console\Helper;

use _ContaoManager\Symfony\Component\Console\Output\OutputInterface;
use _ContaoManager\Symfony\Component\VarDumper\Cloner\ClonerInterface;
use _ContaoManager\Symfony\Component\VarDumper\Cloner\VarCloner;
use _ContaoManager\Symfony\Component\VarDumper\Dumper\CliDumper;
/**
 * @author Roland Franssen <franssen.roland@gmail.com>
 */
final class Dumper
{
    private OutputInterface $output;
    private ?CliDumper $dumper;
    private ?ClonerInterface $cloner;
    private \Closure $handler;
    public function __construct(OutputInterface $output, ?CliDumper $dumper = null, ?ClonerInterface $cloner = null)
    {
        $this->output = $output;
        $this->dumper = $dumper;
        $this->cloner = $cloner;
        if (class_exists(CliDumper::class)) {
            $this->handler = function ($var): string {
                $dumper = $this->dumper ??= new CliDumper(null, null, CliDumper::DUMP_LIGHT_ARRAY | CliDumper::DUMP_COMMA_SEPARATOR);
                $dumper->setColors($this->output->isDecorated());
                return rtrim($dumper->dump(($this->cloner ??= new VarCloner())->cloneVar($var)->withRefHandles(\false), \true));
            };
        } else {
            $this->handler = fn($var): string => match (\true) {
                null === $var => 'null',
                \true === $var => 'true',
                \false === $var => 'false',
                \is_string($var) => '"' . $var . '"',
                default => rtrim(print_r($var, \true)),
            };
        }
    }
    public function __invoke(mixed $var): string
    {
        return ($this->handler)($var);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Console\Helper;

use _ContaoManager\Symfony\Component\Console\Input\InputAwareInterface;
use _ContaoManager\Symfony\Component\Console\Input\InputInterface;
/**
 * An implementation of InputAwareInterface for Helpers.
 *
 * @author Wouter J <waldio.webdesign@gmail.com>
 */
abstract class InputAwareHelper extends Helper implements InputAwareInterface
{
    protected $input;
    /**
     * @return void
     */
    public function setInput(InputInterface $input)
    {
        $this->input = $input;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Console\Helper;

use _ContaoManager\Symfony\Component\Console\Cursor;
use _ContaoManager\Symfony\Component\Console\Exception\MissingInputException;
use _ContaoManager\Symfony\Component\Console\Exception\RuntimeException;
use _ContaoManager\Symfony\Component\Console\Formatter\OutputFormatter;
use _ContaoManager\Symfony\Component\Console\Formatter\OutputFormatterStyle;
use _ContaoManager\Symfony\Component\Console\Input\InputInterface;
use _ContaoManager\Symfony\Component\Console\Input\StreamableInputInterface;
use _ContaoManager\Symfony\Component\Console\Output\ConsoleOutputInterface;
use _ContaoManager\Symfony\Component\Console\Output\ConsoleSectionOutput;
use _ContaoManager\Symfony\Component\Console\Output\OutputInterface;
use _ContaoManager\Symfony\Component\Console\Question\ChoiceQuestion;
use _ContaoManager\Symfony\Component\Console\Question\Question;
use _ContaoManager\Symfony\Component\Console\Terminal;
use function _ContaoManager\Symfony\Component\String\s;
/**
 * The QuestionHelper class provides helpers to interact with the user.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class QuestionHelper extends Helper
{
    /**
     * @var resource|null
     */
    private $inputStream;
    private static bool $stty = \true;
    private static bool $stdinIsInteractive;
    /**
     * Asks a question to the user.
     *
     * @return mixed The user answer
     *
     * @throws RuntimeException If there is no data to read in the input stream
     */
    public function ask(InputInterface $input, OutputInterface $output, Question $question): mixed
    {
        if ($output instanceof ConsoleOutputInterface) {
            $output = $output->getErrorOutput();
        }
        if (!$input->isInteractive()) {
            return $this->getDefaultAnswer($question);
        }
        if ($input instanceof StreamableInputInterface && $stream = $input->getStream()) {
            $this->inputStream = $stream;
        }
        try {
            if (!$question->getValidator()) {
                return $this->doAsk($output, $question);
            }
            $interviewer = fn() => $this->doAsk($output, $question);
            return $this->validateAttempts($interviewer, $output, $question);
        } catch (MissingInputException $exception) {
            $input->setInteractive(\false);
            if (null === $fallbackOutput = $this->getDefaultAnswer($question)) {
                throw $exception;
            }
            return $fallbackOutput;
        }
    }
    public function getName(): string
    {
        return 'question';
    }
    /**
     * Prevents usage of stty.
     *
     * @return void
     */
    public static function disableStty()
    {
        self::$stty = \false;
    }
    /**
     * Asks the question to the user.
     *
     * @throws RuntimeException In case the fallback is deactivated and the response cannot be hidden
     */
    private function doAsk(OutputInterface $output, Question $question): mixed
    {
        $this->writePrompt($output, $question);
        $inputStream = $this->inputStream ?: \STDIN;
        $autocomplete = $question->getAutocompleterCallback();
        if (null === $autocomplete || !self::$stty || !Terminal::hasSttyAvailable()) {
            $ret = \false;
            if ($question->isHidden()) {
                try {
                    $hiddenResponse = $this->getHiddenResponse($output, $inputStream, $question->isTrimmable());
                    $ret = $question->isTrimmable() ? trim($hiddenResponse) : $hiddenResponse;
                } catch (RuntimeException $e) {
                    if (!$question->isHiddenFallback()) {
                        throw $e;
                    }
                }
            }
            if (\false === $ret) {
                $isBlocked = stream_get_meta_data($inputStream)['blocked'] ?? \true;
                if (!$isBlocked) {
                    stream_set_blocking($inputStream, \true);
                }
                $ret = $this->readInput($inputStream, $question);
                if (!$isBlocked) {
                    stream_set_blocking($inputStream, \false);
                }
                if (\false === $ret) {
                    throw new MissingInputException('Aborted.');
                }
                if ($question->isTrimmable()) {
                    $ret = trim($ret);
                }
            }
        } else {
            $autocomplete = $this->autocomplete($output, $question, $inputStream, $autocomplete);
            $ret = $question->isTrimmable() ? trim($autocomplete) : $autocomplete;
        }
        if ($output instanceof ConsoleSectionOutput) {
            $output->addContent('');
            // add EOL to the question
            $output->addContent($ret);
        }
        $ret = \strlen($ret) > 0 ? $ret : $question->getDefault();
        if ($normalizer = $question->getNormalizer()) {
            return $normalizer($ret);
        }
        return $ret;
    }
    private function getDefaultAnswer(Question $question): mixed
    {
        $default = $question->getDefault();
        if (null === $default) {
            return $default;
        }
        if ($validator = $question->getValidator()) {
            return \call_user_func($validator, $default);
        } elseif ($question instanceof ChoiceQuestion) {
            $choices = $question->getChoices();
            if (!$question->isMultiselect()) {
                return $choices[$default] ?? $default;
            }
            $default = explode(',', $default);
            foreach ($default as $k => $v) {
                $v = $question->isTrimmable() ? trim($v) : $v;
                $default[$k] = $choices[$v] ?? $v;
            }
        }
        return $default;
    }
    /**
     * Outputs the question prompt.
     *
     * @return void
     */
    protected function writePrompt(OutputInterface $output, Question $question)
    {
        $message = $question->getQuestion();
        if ($question instanceof ChoiceQuestion) {
            $output->writeln(array_merge([$question->getQuestion()], $this->formatChoiceQuestionChoices($question, 'info')));
            $message = $question->getPrompt();
        }
        $output->write($message);
    }
    /**
     * @return string[]
     */
    protected function formatChoiceQuestionChoices(ChoiceQuestion $question, string $tag): array
    {
        $messages = [];
        $maxWidth = max(array_map([__CLASS__, 'width'], array_keys($choices = $question->getChoices())));
        foreach ($choices as $key => $value) {
            $padding = str_repeat(' ', $maxWidth - self::width($key));
            $messages[] = \sprintf("  [<{$tag}>%s{$padding}</{$tag}>] %s", $key, $value);
        }
        return $messages;
    }
    /**
     * Outputs an error message.
     *
     * @return void
     */
    protected function writeError(OutputInterface $output, \Exception $error)
    {
        if (null !== $this->getHelperSet() && $this->getHelperSet()->has('formatter')) {
            $message = $this->getHelperSet()->get('formatter')->formatBlock($error->getMessage(), 'error');
        } else {
            $message = '<error>' . $error->getMessage() . '</error>';
        }
        $output->writeln($message);
    }
    /**
     * Autocompletes a question.
     *
     * @param resource $inputStream
     */
    private function autocomplete(OutputInterface $output, Question $question, $inputStream, callable $autocomplete): string
    {
        $cursor = new Cursor($output, $inputStream);
        $fullChoice = '';
        $ret = '';
        $i = 0;
        $ofs = -1;
        $matches = $autocomplete($ret);
        $numMatches = \count($matches);
        $inputHelper = new TerminalInputHelper($inputStream);
        // Disable icanon (so we can fread each keypress) and echo (we'll do echoing here instead)
        shell_exec('stty -icanon -echo');
        // Add highlighted text style
        $output->getFormatter()->setStyle('hl', new OutputFormatterStyle('black', 'white'));
        // Read a keypress
        while (!feof($inputStream)) {
            $inputHelper->waitForInput();
            $c = fread($inputStream, 1);
            // as opposed to fgets(), fread() returns an empty string when the stream content is empty, not false.
            if (\false === $c || '' === $ret && '' === $c && null === $question->getDefault()) {
                // Restore the terminal so it behaves normally again
                $inputHelper->finish();
                throw new MissingInputException('Aborted.');
            } elseif ("" === $c) {
                // Backspace Character
                if (0 === $numMatches && 0 !== $i) {
                    --$i;
                    $cursor->moveLeft(s($fullChoice)->slice(-1)->width(\false));
                    $fullChoice = self::substr($fullChoice, 0, $i);
                }
                if (0 === $i) {
                    $ofs = -1;
                    $matches = $autocomplete($ret);
                    $numMatches = \count($matches);
                } else {
                    $numMatches = 0;
                }
                // Pop the last character off the end of our string
                $ret = self::substr($ret, 0, $i);
            } elseif ("\x1b" === $c) {
                // Did we read an escape sequence?
                $c .= fread($inputStream, 2);
                // A = Up Arrow. B = Down Arrow
                if (isset($c[2]) && ('A' === $c[2] || 'B' === $c[2])) {
                    if ('A' === $c[2] && -1 === $ofs) {
                        $ofs = 0;
                    }
                    if (0 === $numMatches) {
                        continue;
                    }
                    $ofs += 'A' === $c[2] ? -1 : 1;
                    $ofs = ($numMatches + $ofs) % $numMatches;
                }
            } elseif ('' === $c || \ord($c) < 32) {
                if ("\t" === $c || "\n" === $c) {
                    if ($numMatches > 0 && -1 !== $ofs) {
                        $ret = (string) $matches[$ofs];
                        // Echo out remaining chars for current match
                        $remainingCharacters = substr($ret, \strlen($this->mostRecentlyEnteredValue($fullChoice)));
                        $output->write($remainingCharacters);
                        $fullChoice .= $remainingCharacters;
                        $i = \false === ($encoding = mb_detect_encoding($fullChoice, null, \true)) ? \strlen($fullChoice) : mb_strlen($fullChoice, $encoding);
                        $matches = array_filter($autocomplete($ret), fn($match) => '' === $ret || str_starts_with($match, $ret));
                        $numMatches = \count($matches);
                        $ofs = -1;
                    }
                    if ("\n" === $c) {
                        $output->write($c);
                        break;
                    }
                    $numMatches = 0;
                }
                continue;
            } else {
                if ("\x80" <= $c) {
                    $c .= fread($inputStream, ["\xc0" => 1, "\xd0" => 1, "\xe0" => 2, "\xf0" => 3][$c & "\xf0"]);
                }
                $output->write($c);
                $ret .= $c;
                $fullChoice .= $c;
                ++$i;
                $tempRet = $ret;
                if ($question instanceof ChoiceQuestion && $question->isMultiselect()) {
                    $tempRet = $this->mostRecentlyEnteredValue($fullChoice);
                }
                $numMatches = 0;
                $ofs = 0;
                foreach ($autocomplete($ret) as $value) {
                    // If typed characters match the beginning chunk of value (e.g. [AcmeDe]moBundle)
                    if (str_starts_with($value, $tempRet)) {
                        $matches[$numMatches++] = $value;
                    }
                }
            }
            $cursor->clearLineAfter();
            if ($numMatches > 0 && -1 !== $ofs) {
                $cursor->savePosition();
                // Write highlighted text, complete the partially entered response
                $charactersEntered = \strlen($this->mostRecentlyEnteredValue($fullChoice));
                $output->write('<hl>' . OutputFormatter::escapeTrailingBackslash(substr($matches[$ofs], $charactersEntered)) . '</hl>');
                $cursor->restorePosition();
            }
        }
        // Restore the terminal so it behaves normally again
        $inputHelper->finish();
        return $fullChoice;
    }
    private function mostRecentlyEnteredValue(string $entered): string
    {
        // Determine the most recent value that the user entered
        if (!str_contains($entered, ',')) {
            return $entered;
        }
        $choices = explode(',', $entered);
        if ('' !== $lastChoice = trim($choices[\count($choices) - 1])) {
            return $lastChoice;
        }
        return $entered;
    }
    /**
     * Gets a hidden response from user.
     *
     * @param resource $inputStream The handler resource
     * @param bool     $trimmable   Is the answer trimmable
     *
     * @throws RuntimeException In case the fallback is deactivated and the response cannot be hidden
     */
    private function getHiddenResponse(OutputInterface $output, $inputStream, bool $trimmable = \true): string
    {
        if ('\\' === \DIRECTORY_SEPARATOR) {
            $exe = __DIR__ . '/../Resources/bin/hiddeninput.exe';
            // handle code running from a phar
            if (str_starts_with(__FILE__, 'phar:')) {
                $tmpExe = sys_get_temp_dir() . '/hiddeninput.exe';
                copy($exe, $tmpExe);
                $exe = $tmpExe;
            }
            $sExec = shell_exec('"' . $exe . '"');
            $value = $trimmable ? rtrim($sExec) : $sExec;
            $output->writeln('');
            if (isset($tmpExe)) {
                unlink($tmpExe);
            }
            return $value;
        }
        $inputHelper = null;
        if (self::$stty && Terminal::hasSttyAvailable()) {
            $inputHelper = new TerminalInputHelper($inputStream);
            shell_exec('stty -echo');
        } elseif ($this->isInteractiveInput($inputStream)) {
            throw new RuntimeException('Unable to hide the response.');
        }
        $value = $this->doReadInput($inputStream, helper: $inputHelper);
        if (4095 === \strlen($value)) {
            $errOutput = $output instanceof ConsoleOutputInterface ? $output->getErrorOutput() : $output;
            $errOutput->warning('The value was possibly truncated by your shell or terminal emulator');
        }
        // Restore the terminal so it behaves normally again
        $inputHelper?->finish();
        if ($trimmable) {
            $value = trim($value);
        }
        $output->writeln('');
        return $value;
    }
    /**
     * Validates an attempt.
     *
     * @param callable $interviewer A callable that will ask for a question and return the result
     *
     * @throws \Exception In case the max number of attempts has been reached and no valid response has been given
     */
    private function validateAttempts(callable $interviewer, OutputInterface $output, Question $question): mixed
    {
        $error = null;
        $attempts = $question->getMaxAttempts();
        while (null === $attempts || $attempts--) {
            if (null !== $error) {
                $this->writeError($output, $error);
            }
            try {
                return $question->getValidator()($interviewer());
            } catch (MissingInputException $e) {
                throw $error ?? $e;
            } catch (RuntimeException $e) {
                throw $e;
            } catch (\Exception $error) {
            }
        }
        throw $error;
    }
    private function isInteractiveInput($inputStream): bool
    {
        if ('php://stdin' !== (stream_get_meta_data($inputStream)['uri'] ?? null)) {
            return \false;
        }
        if (isset(self::$stdinIsInteractive)) {
            return self::$stdinIsInteractive;
        }
        return self::$stdinIsInteractive = @stream_isatty(fopen('php://stdin', 'r'));
    }
    /**
     * Reads one or more lines of input and returns what is read.
     *
     * @param resource $inputStream The handler resource
     * @param Question $question    The question being asked
     */
    private function readInput($inputStream, Question $question): string|false
    {
        if (!$question->isMultiline()) {
            $cp = $this->setIOCodepage();
            $ret = $this->doReadInput($inputStream);
            return $this->resetIOCodepage($cp, $ret);
        }
        $multiLineStreamReader = $this->cloneInputStream($inputStream);
        if (null === $multiLineStreamReader) {
            return \false;
        }
        $cp = $this->setIOCodepage();
        $ret = $this->doReadInput($multiLineStreamReader, "\x04");
        if (stream_get_meta_data($inputStream)['seekable']) {
            fseek($inputStream, ftell($multiLineStreamReader));
        }
        return $this->resetIOCodepage($cp, $ret);
    }
    private function setIOCodepage(): int
    {
        if (\function_exists('sapi_windows_cp_set')) {
            $cp = sapi_windows_cp_get();
            sapi_windows_cp_set(sapi_windows_cp_get('oem'));
            return $cp;
        }
        return 0;
    }
    /**
     * Sets console I/O to the specified code page and converts the user input.
     */
    private function resetIOCodepage(int $cp, string|false $input): string|false
    {
        if (0 !== $cp) {
            sapi_windows_cp_set($cp);
            if (\false !== $input && '' !== $input) {
                $input = sapi_windows_cp_conv(sapi_windows_cp_get('oem'), $cp, $input);
            }
        }
        return $input;
    }
    /**
     * Clones an input stream in order to act on one instance of the same
     * stream without affecting the other instance.
     *
     * @param resource $inputStream The handler resource
     *
     * @return resource|null The cloned resource, null in case it could not be cloned
     */
    private function cloneInputStream($inputStream)
    {
        $streamMetaData = stream_get_meta_data($inputStream);
        $seekable = $streamMetaData['seekable'] ?? \false;
        $mode = $streamMetaData['mode'] ?? 'rb';
        $uri = $streamMetaData['uri'] ?? null;
        if (null === $uri) {
            return null;
        }
        $cloneStream = fopen($uri, $mode);
        // For seekable and writable streams, add all the same data to the
        // cloned stream and then seek to the same offset.
        if (\true === $seekable && !\in_array($mode, ['r', 'rb', 'rt'])) {
            $offset = ftell($inputStream);
            rewind($inputStream);
            stream_copy_to_stream($inputStream, $cloneStream);
            fseek($inputStream, $offset);
            fseek($cloneStream, $offset);
        }
        return $cloneStream;
    }
    /**
     * @param resource $inputStream
     */
    private function doReadInput($inputStream, ?string $exitChar = null, ?TerminalInputHelper $helper = null): string
    {
        $ret = '';
        $helper ??= new TerminalInputHelper($inputStream, \false);
        while (!feof($inputStream)) {
            $helper->waitForInput();
            $char = fread($inputStream, 1);
            // as opposed to fgets(), fread() returns an empty string when the stream content is empty, not false.
            if (\false === $char || '' === $ret && '' === $char) {
                throw new MissingInputException('Aborted.');
            }
            if (\PHP_EOL === "{$ret}{$char}" || $exitChar === $char) {
                break;
            }
            $ret .= $char;
            if (null === $exitChar && "\n" === $char) {
                break;
            }
        }
        return $ret;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Console\Helper;

use _ContaoManager\Symfony\Component\Console\Formatter\OutputFormatterInterface;
use _ContaoManager\Symfony\Component\String\UnicodeString;
/**
 * Helper is the base class for all helper classes.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
abstract class Helper implements HelperInterface
{
    protected $helperSet;
    /**
     * @return void
     */
    public function setHelperSet(?HelperSet $helperSet = null)
    {
        if (1 > \func_num_args()) {
            trigger_deprecation('symfony/console', '6.2', 'Calling "%s()" without any arguments is deprecated, pass null explicitly instead.', __METHOD__);
        }
        $this->helperSet = $helperSet;
    }
    public function getHelperSet(): ?HelperSet
    {
        return $this->helperSet;
    }
    /**
     * Returns the width of a string, using mb_strwidth if it is available.
     * The width is how many characters positions the string will use.
     */
    public static function width(?string $string): int
    {
        $string ??= '';
        if (preg_match('//u', $string)) {
            $string = preg_replace('/[\p{Cc}\x7F]++/u', '', $string, -1, $count);
            return (new UnicodeString($string))->width(\false) + $count;
        }
        if (\false === $encoding = mb_detect_encoding($string, null, \true)) {
            return \strlen($string);
        }
        return mb_strwidth($string, $encoding);
    }
    /**
     * Returns the length of a string, using mb_strlen if it is available.
     * The length is related to how many bytes the string will use.
     */
    public static function length(?string $string): int
    {
        $string ??= '';
        if (preg_match('//u', $string)) {
            return (new UnicodeString($string))->length();
        }
        if (\false === $encoding = mb_detect_encoding($string, null, \true)) {
            return \strlen($string);
        }
        return mb_strlen($string, $encoding);
    }
    /**
     * Returns the subset of a string, using mb_substr if it is available.
     */
    public static function substr(?string $string, int $from, ?int $length = null): string
    {
        $string ??= '';
        if (preg_match('//u', $string)) {
            return (new UnicodeString($string))->slice($from, $length);
        }
        if (\false === $encoding = mb_detect_encoding($string, null, \true)) {
            return substr($string, $from, $length);
        }
        return mb_substr($string, $from, $length, $encoding);
    }
    /**
     * @return string
     */
    public static function formatTime(int|float $secs, int $precision = 1)
    {
        $secs = (int) floor($secs);
        if (0 === $secs) {
            return '< 1 sec';
        }
        static $timeFormats = [[1, '1 sec', 'secs'], [60, '1 min', 'mins'], [3600, '1 hr', 'hrs'], [86400, '1 day', 'days']];
        $times = [];
        foreach ($timeFormats as $index => $format) {
            $seconds = isset($timeFormats[$index + 1]) ? $secs % $timeFormats[$index + 1][0] : $secs;
            if (isset($times[$index - $precision])) {
                unset($times[$index - $precision]);
            }
            if (0 === $seconds) {
                continue;
            }
            $unitCount = $seconds / $format[0];
            $times[$index] = 1 === $unitCount ? $format[1] : $unitCount . ' ' . $format[2];
            if ($secs === $seconds) {
                break;
            }
            $secs -= $seconds;
        }
        return implode(', ', array_reverse($times));
    }
    /**
     * @return string
     */
    public static function formatMemory(int $memory)
    {
        if ($memory >= 1024 * 1024 * 1024) {
            return \sprintf('%.1f GiB', $memory / 1024 / 1024 / 1024);
        }
        if ($memory >= 1024 * 1024) {
            return \sprintf('%.1f MiB', $memory / 1024 / 1024);
        }
        if ($memory >= 1024) {
            return \sprintf('%d KiB', $memory / 1024);
        }
        return \sprintf('%d B', $memory);
    }
    /**
     * @return string
     */
    public static function removeDecoration(OutputFormatterInterface $formatter, ?string $string)
    {
        $isDecorated = $formatter->isDecorated();
        $formatter->setDecorated(\false);
        // remove <...> formatting
        $string = $formatter->format($string ?? '');
        // remove already formatted characters
        $string = preg_replace("/\x1b\\[[^m]*m/", '', $string ?? '');
        // remove terminal hyperlinks
        $string = preg_replace('/\033]8;[^;]*;[^\033]*\033\\\\/', '', $string ?? '');
        $formatter->setDecorated($isDecorated);
        return $string;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Console\Helper;

use _ContaoManager\Symfony\Component\Console\Exception\InvalidArgumentException;
use _ContaoManager\Symfony\Component\Console\Exception\RuntimeException;
use _ContaoManager\Symfony\Component\Console\Formatter\OutputFormatter;
use _ContaoManager\Symfony\Component\Console\Formatter\WrappableOutputFormatterInterface;
use _ContaoManager\Symfony\Component\Console\Output\ConsoleSectionOutput;
use _ContaoManager\Symfony\Component\Console\Output\OutputInterface;
/**
 * Provides helpers to display a table.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 * @author Саша Стаменковић <umpirsky@gmail.com>
 * @author Abdellatif Ait boudad <a.aitboudad@gmail.com>
 * @author Max Grigorian <maxakawizard@gmail.com>
 * @author Dany Maillard <danymaillard93b@gmail.com>
 */
class Table
{
    private const SEPARATOR_TOP = 0;
    private const SEPARATOR_TOP_BOTTOM = 1;
    private const SEPARATOR_MID = 2;
    private const SEPARATOR_BOTTOM = 3;
    private const BORDER_OUTSIDE = 0;
    private const BORDER_INSIDE = 1;
    private const DISPLAY_ORIENTATION_DEFAULT = 'default';
    private const DISPLAY_ORIENTATION_HORIZONTAL = 'horizontal';
    private const DISPLAY_ORIENTATION_VERTICAL = 'vertical';
    private ?string $headerTitle = null;
    private ?string $footerTitle = null;
    private array $headers = [];
    private array $rows = [];
    private array $effectiveColumnWidths = [];
    private int $numberOfColumns;
    private OutputInterface $output;
    private TableStyle $style;
    private array $columnStyles = [];
    private array $columnWidths = [];
    private array $columnMaxWidths = [];
    private bool $rendered = \false;
    private string $displayOrientation = self::DISPLAY_ORIENTATION_DEFAULT;
    private static array $styles;
    public function __construct(OutputInterface $output)
    {
        $this->output = $output;
        self::$styles ??= self::initStyles();
        $this->setStyle('default');
    }
    /**
     * Sets a style definition.
     *
     * @return void
     */
    public static function setStyleDefinition(string $name, TableStyle $style)
    {
        self::$styles ??= self::initStyles();
        self::$styles[$name] = $style;
    }
    /**
     * Gets a style definition by name.
     */
    public static function getStyleDefinition(string $name): TableStyle
    {
        self::$styles ??= self::initStyles();
        return self::$styles[$name] ?? throw new InvalidArgumentException(\sprintf('Style "%s" is not defined.', $name));
    }
    /**
     * Sets table style.
     *
     * @return $this
     */
    public function setStyle(TableStyle|string $name): static
    {
        $this->style = $this->resolveStyle($name);
        return $this;
    }
    /**
     * Gets the current table style.
     */
    public function getStyle(): TableStyle
    {
        return $this->style;
    }
    /**
     * Sets table column style.
     *
     * @param TableStyle|string $name The style name or a TableStyle instance
     *
     * @return $this
     */
    public function setColumnStyle(int $columnIndex, TableStyle|string $name): static
    {
        $this->columnStyles[$columnIndex] = $this->resolveStyle($name);
        return $this;
    }
    /**
     * Gets the current style for a column.
     *
     * If style was not set, it returns the global table style.
     */
    public function getColumnStyle(int $columnIndex): TableStyle
    {
        return $this->columnStyles[$columnIndex] ?? $this->getStyle();
    }
    /**
     * Sets the minimum width of a column.
     *
     * @return $this
     */
    public function setColumnWidth(int $columnIndex, int $width): static
    {
        $this->columnWidths[$columnIndex] = $width;
        return $this;
    }
    /**
     * Sets the minimum width of all columns.
     *
     * @return $this
     */
    public function setColumnWidths(array $widths): static
    {
        $this->columnWidths = [];
        foreach ($widths as $index => $width) {
            $this->setColumnWidth($index, $width);
        }
        return $this;
    }
    /**
     * Sets the maximum width of a column.
     *
     * Any cell within this column which contents exceeds the specified width will be wrapped into multiple lines, while
     * formatted strings are preserved.
     *
     * @return $this
     */
    public function setColumnMaxWidth(int $columnIndex, int $width): static
    {
        if (!$this->output->getFormatter() instanceof WrappableOutputFormatterInterface) {
            throw new \LogicException(\sprintf('Setting a maximum column width is only supported when using a "%s" formatter, got "%s".', WrappableOutputFormatterInterface::class, get_debug_type($this->output->getFormatter())));
        }
        $this->columnMaxWidths[$columnIndex] = $width;
        return $this;
    }
    /**
     * @return $this
     */
    public function setHeaders(array $headers): static
    {
        $headers = array_values($headers);
        if ($headers && !\is_array($headers[0])) {
            $headers = [$headers];
        }
        $this->headers = $headers;
        return $this;
    }
    /**
     * @return $this
     */
    public function setRows(array $rows)
    {
        $this->rows = [];
        return $this->addRows($rows);
    }
    /**
     * @return $this
     */
    public function addRows(array $rows): static
    {
        foreach ($rows as $row) {
            $this->addRow($row);
        }
        return $this;
    }
    /**
     * @return $this
     */
    public function addRow(TableSeparator|array $row): static
    {
        if ($row instanceof TableSeparator) {
            $this->rows[] = $row;
            return $this;
        }
        $this->rows[] = array_values($row);
        return $this;
    }
    /**
     * Adds a row to the table, and re-renders the table.
     *
     * @return $this
     */
    public function appendRow(TableSeparator|array $row): static
    {
        if (!$this->output instanceof ConsoleSectionOutput) {
            throw new RuntimeException(\sprintf('Output should be an instance of "%s" when calling "%s".', ConsoleSectionOutput::class, __METHOD__));
        }
        if ($this->rendered) {
            $this->output->clear($this->calculateRowCount());
        }
        $this->addRow($row);
        $this->render();
        return $this;
    }
    /**
     * @return $this
     */
    public function setRow(int|string $column, array $row): static
    {
        $this->rows[$column] = $row;
        return $this;
    }
    /**
     * @return $this
     */
    public function setHeaderTitle(?string $title): static
    {
        $this->headerTitle = $title;
        return $this;
    }
    /**
     * @return $this
     */
    public function setFooterTitle(?string $title): static
    {
        $this->footerTitle = $title;
        return $this;
    }
    /**
     * @return $this
     */
    public function setHorizontal(bool $horizontal = \true): static
    {
        $this->displayOrientation = $horizontal ? self::DISPLAY_ORIENTATION_HORIZONTAL : self::DISPLAY_ORIENTATION_DEFAULT;
        return $this;
    }
    /**
     * @return $this
     */
    public function setVertical(bool $vertical = \true): static
    {
        $this->displayOrientation = $vertical ? self::DISPLAY_ORIENTATION_VERTICAL : self::DISPLAY_ORIENTATION_DEFAULT;
        return $this;
    }
    /**
     * Renders table to output.
     *
     * Example:
     *
     *     +---------------+-----------------------+------------------+
     *     | ISBN          | Title                 | Author           |
     *     +---------------+-----------------------+------------------+
     *     | 99921-58-10-7 | Divine Comedy         | Dante Alighieri  |
     *     | 9971-5-0210-0 | A Tale of Two Cities  | Charles Dickens  |
     *     | 960-425-059-0 | The Lord of the Rings | J. R. R. Tolkien |
     *     +---------------+-----------------------+------------------+
     *
     * @return void
     */
    public function render()
    {
        $divider = new TableSeparator();
        $isCellWithColspan = static fn($cell) => $cell instanceof TableCell && $cell->getColspan() >= 2;
        $horizontal = self::DISPLAY_ORIENTATION_HORIZONTAL === $this->displayOrientation;
        $vertical = self::DISPLAY_ORIENTATION_VERTICAL === $this->displayOrientation;
        $rows = [];
        if ($horizontal) {
            foreach ($this->headers[0] ?? [] as $i => $header) {
                $rows[$i] = [$header];
                foreach ($this->rows as $row) {
                    if ($row instanceof TableSeparator) {
                        continue;
                    }
                    if (isset($row[$i])) {
                        $rows[$i][] = $row[$i];
                    } elseif ($isCellWithColspan($rows[$i][0])) {
                        // Noop, there is a "title"
                    } else {
                        $rows[$i][] = null;
                    }
                }
            }
        } elseif ($vertical) {
            $formatter = $this->output->getFormatter();
            $maxHeaderLength = array_reduce($this->headers[0] ?? [], static fn($max, $header) => max($max, Helper::width(Helper::removeDecoration($formatter, $header))), 0);
            foreach ($this->rows as $row) {
                if ($row instanceof TableSeparator) {
                    continue;
                }
                if ($rows) {
                    $rows[] = [$divider];
                }
                $containsColspan = \false;
                foreach ($row as $cell) {
                    if ($containsColspan = $isCellWithColspan($cell)) {
                        break;
                    }
                }
                $headers = $this->headers[0] ?? [];
                $maxRows = max(\count($headers), \count($row));
                for ($i = 0; $i < $maxRows; ++$i) {
                    $cell = (string) ($row[$i] ?? '');
                    $eol = str_contains($cell, "\r\n") ? "\r\n" : "\n";
                    $parts = explode($eol, $cell);
                    foreach ($parts as $idx => $part) {
                        if ($headers && !$containsColspan) {
                            if (0 === $idx) {
                                $rows[] = [\sprintf('<comment>%s%s</>: %s', str_repeat(' ', $maxHeaderLength - Helper::width(Helper::removeDecoration($formatter, $headers[$i] ?? ''))), $headers[$i] ?? '', $part)];
                            } else {
                                $rows[] = [\sprintf('%s  %s', str_pad('', $maxHeaderLength, ' ', \STR_PAD_LEFT), $part)];
                            }
                        } elseif ('' !== $cell) {
                            $rows[] = [$part];
                        }
                    }
                }
            }
        } else {
            $rows = array_merge($this->headers, [$divider], $this->rows);
        }
        $this->calculateNumberOfColumns($rows);
        $rowGroups = $this->buildTableRows($rows);
        $this->calculateColumnsWidth($rowGroups);
        $isHeader = !$horizontal;
        $isFirstRow = $horizontal;
        $hasTitle = (bool) $this->headerTitle;
        foreach ($rowGroups as $rowGroup) {
            $isHeaderSeparatorRendered = \false;
            foreach ($rowGroup as $row) {
                if ($divider === $row) {
                    $isHeader = \false;
                    $isFirstRow = \true;
                    continue;
                }
                if ($row instanceof TableSeparator) {
                    $this->renderRowSeparator();
                    continue;
                }
                if (!$row) {
                    continue;
                }
                if ($isHeader && !$isHeaderSeparatorRendered) {
                    $this->renderRowSeparator(self::SEPARATOR_TOP, $hasTitle ? $this->headerTitle : null, $hasTitle ? $this->style->getHeaderTitleFormat() : null);
                    $hasTitle = \false;
                    $isHeaderSeparatorRendered = \true;
                }
                if ($isFirstRow) {
                    $this->renderRowSeparator($horizontal ? self::SEPARATOR_TOP : self::SEPARATOR_TOP_BOTTOM, $hasTitle ? $this->headerTitle : null, $hasTitle ? $this->style->getHeaderTitleFormat() : null);
                    $isFirstRow = \false;
                    $hasTitle = \false;
                }
                if ($vertical) {
                    $isHeader = \false;
                    $isFirstRow = \false;
                }
                if ($horizontal) {
                    $this->renderRow($row, $this->style->getCellRowFormat(), $this->style->getCellHeaderFormat());
                } else {
                    $this->renderRow($row, $isHeader ? $this->style->getCellHeaderFormat() : $this->style->getCellRowFormat());
                }
            }
        }
        $this->renderRowSeparator(self::SEPARATOR_BOTTOM, $this->footerTitle, $this->style->getFooterTitleFormat());
        $this->cleanup();
        $this->rendered = \true;
    }
    /**
     * Renders horizontal header separator.
     *
     * Example:
     *
     *     +-----+-----------+-------+
     */
    private function renderRowSeparator(int $type = self::SEPARATOR_MID, ?string $title = null, ?string $titleFormat = null): void
    {
        if (!$count = $this->numberOfColumns) {
            return;
        }
        $borders = $this->style->getBorderChars();
        if (!$borders[0] && !$borders[2] && !$this->style->getCrossingChar()) {
            return;
        }
        $crossings = $this->style->getCrossingChars();
        if (self::SEPARATOR_MID === $type) {
            [$horizontal, $leftChar, $midChar, $rightChar] = [$borders[2], $crossings[8], $crossings[0], $crossings[4]];
        } elseif (self::SEPARATOR_TOP === $type) {
            [$horizontal, $leftChar, $midChar, $rightChar] = [$borders[0], $crossings[1], $crossings[2], $crossings[3]];
        } elseif (self::SEPARATOR_TOP_BOTTOM === $type) {
            [$horizontal, $leftChar, $midChar, $rightChar] = [$borders[0], $crossings[9], $crossings[10], $crossings[11]];
        } else {
            [$horizontal, $leftChar, $midChar, $rightChar] = [$borders[0], $crossings[7], $crossings[6], $crossings[5]];
        }
        $markup = $leftChar;
        for ($column = 0; $column < $count; ++$column) {
            $markup .= str_repeat($horizontal, $this->effectiveColumnWidths[$column]);
            $markup .= $column === $count - 1 ? $rightChar : $midChar;
        }
        if (null !== $title) {
            $titleLength = Helper::width(Helper::removeDecoration($formatter = $this->output->getFormatter(), $formattedTitle = \sprintf($titleFormat, $title)));
            $markupLength = Helper::width($markup);
            if ($titleLength > $limit = $markupLength - 4) {
                $titleLength = $limit;
                $formatLength = Helper::width(Helper::removeDecoration($formatter, \sprintf($titleFormat, '')));
                $formattedTitle = \sprintf($titleFormat, Helper::substr($title, 0, $limit - $formatLength - 3) . '...');
            }
            $titleStart = intdiv($markupLength - $titleLength, 2);
            if (\false === mb_detect_encoding($markup, null, \true)) {
                $markup = substr_replace($markup, $formattedTitle, $titleStart, $titleLength);
            } else {
                $markup = mb_substr($markup, 0, $titleStart) . $formattedTitle . mb_substr($markup, $titleStart + $titleLength);
            }
        }
        $this->output->writeln(\sprintf($this->style->getBorderFormat(), $markup));
    }
    /**
     * Renders vertical column separator.
     */
    private function renderColumnSeparator(int $type = self::BORDER_OUTSIDE): string
    {
        $borders = $this->style->getBorderChars();
        return \sprintf($this->style->getBorderFormat(), self::BORDER_OUTSIDE === $type ? $borders[1] : $borders[3]);
    }
    /**
     * Renders table row.
     *
     * Example:
     *
     *     | 9971-5-0210-0 | A Tale of Two Cities  | Charles Dickens  |
     */
    private function renderRow(array $row, string $cellFormat, ?string $firstCellFormat = null): void
    {
        $rowContent = $this->renderColumnSeparator(self::BORDER_OUTSIDE);
        $columns = $this->getRowColumns($row);
        $last = \count($columns) - 1;
        foreach ($columns as $i => $column) {
            if ($firstCellFormat && 0 === $i) {
                $rowContent .= $this->renderCell($row, $column, $firstCellFormat);
            } else {
                $rowContent .= $this->renderCell($row, $column, $cellFormat);
            }
            $rowContent .= $this->renderColumnSeparator($last === $i ? self::BORDER_OUTSIDE : self::BORDER_INSIDE);
        }
        $this->output->writeln($rowContent);
    }
    /**
     * Renders table cell with padding.
     */
    private function renderCell(array $row, int $column, string $cellFormat): string
    {
        $cell = $row[$column] ?? '';
        $width = $this->effectiveColumnWidths[$column];
        if ($cell instanceof TableCell && $cell->getColspan() > 1) {
            // add the width of the following columns(numbers of colspan).
            foreach (range($column + 1, $column + $cell->getColspan() - 1) as $nextColumn) {
                $width += $this->getColumnSeparatorWidth() + $this->effectiveColumnWidths[$nextColumn];
            }
        }
        // str_pad won't work properly with multi-byte strings, we need to fix the padding
        $width += \strlen($cell) - Helper::width($cell) - substr_count($cell, "\x00");
        $style = $this->getColumnStyle($column);
        if ($cell instanceof TableSeparator) {
            return \sprintf($style->getBorderFormat(), str_repeat($style->getBorderChars()[2], $width));
        }
        $width += Helper::length($cell) - Helper::length(Helper::removeDecoration($this->output->getFormatter(), $cell));
        $content = \sprintf($style->getCellRowContentFormat(), $cell);
        $padType = $style->getPadType();
        if ($cell instanceof TableCell && $cell->getStyle() instanceof TableCellStyle) {
            $isNotStyledByTag = !preg_match('/^<(\w+|(\w+=[\w,]+;?)*)>.+<\/(\w+|(\w+=\w+;?)*)?>$/', $cell);
            if ($isNotStyledByTag) {
                $cellFormat = $cell->getStyle()->getCellFormat();
                if (!\is_string($cellFormat)) {
                    $tag = http_build_query($cell->getStyle()->getTagOptions(), '', ';');
                    $cellFormat = '<' . $tag . '>%s</>';
                }
                if (str_contains($content, '</>')) {
                    $content = str_replace('</>', '', $content);
                    $width -= 3;
                }
                if (str_contains($content, '<fg=default;bg=default>')) {
                    $content = str_replace('<fg=default;bg=default>', '', $content);
                    $width -= \strlen('<fg=default;bg=default>');
                }
            }
            $padType = $cell->getStyle()->getPadByAlign();
        }
        return \sprintf($cellFormat, str_pad($content, $width, $style->getPaddingChar(), $padType));
    }
    /**
     * Calculate number of columns for this table.
     */
    private function calculateNumberOfColumns(array $rows): void
    {
        $columns = [0];
        foreach ($rows as $row) {
            if ($row instanceof TableSeparator) {
                continue;
            }
            $columns[] = $this->getNumberOfColumns($row);
        }
        $this->numberOfColumns = max($columns);
    }
    private function buildTableRows(array $rows): TableRows
    {
        /** @var WrappableOutputFormatterInterface $formatter */
        $formatter = $this->output->getFormatter();
        $unmergedRows = [];
        for ($rowKey = 0; $rowKey < \count($rows); ++$rowKey) {
            $rows = $this->fillNextRows($rows, $rowKey);
            // Remove any new line breaks and replace it with a new line
            foreach ($rows[$rowKey] as $column => $cell) {
                $colspan = $cell instanceof TableCell ? $cell->getColspan() : 1;
                $minWrappedWidth = 0;
                $widthApplied = [];
                $lengthColumnBorder = $this->getColumnSeparatorWidth() + Helper::width($this->style->getCellRowContentFormat()) - 2;
                for ($i = $column; $i < $column + $colspan; ++$i) {
                    if (isset($this->columnMaxWidths[$i])) {
                        $minWrappedWidth += $this->columnMaxWidths[$i];
                        $widthApplied[] = ['type' => 'max', 'column' => $i];
                    } elseif (($this->columnWidths[$i] ?? 0) > 0 && $colspan > 1) {
                        $minWrappedWidth += $this->columnWidths[$i];
                        $widthApplied[] = ['type' => 'min', 'column' => $i];
                    }
                }
                if (1 === \count($widthApplied)) {
                    if ($colspan > 1) {
                        $minWrappedWidth *= $colspan;
                        // previous logic
                    }
                } elseif (\count($widthApplied) > 1) {
                    $minWrappedWidth += (\count($widthApplied) - 1) * $lengthColumnBorder;
                }
                $cellWidth = Helper::width(Helper::removeDecoration($formatter, $cell));
                if ($minWrappedWidth && $cellWidth > $minWrappedWidth) {
                    $cell = $formatter->formatAndWrap($cell, $minWrappedWidth);
                }
                // update minimal columnWidths for spanned columns
                if ($colspan > 1 && $minWrappedWidth > 0) {
                    $columnsMinWidthProcessed = [];
                    $cellWidth = min($cellWidth, $minWrappedWidth);
                    foreach ($widthApplied as $item) {
                        if ('max' === $item['type'] && $cellWidth >= $this->columnMaxWidths[$item['column']]) {
                            $minWidthColumn = $this->columnMaxWidths[$item['column']];
                            $this->columnWidths[$item['column']] = $minWidthColumn;
                            $columnsMinWidthProcessed[$item['column']] = \true;
                            $cellWidth -= $minWidthColumn + $lengthColumnBorder;
                        }
                    }
                    for ($i = $column; $i < $column + $colspan; ++$i) {
                        if (isset($columnsMinWidthProcessed[$i])) {
                            continue;
                        }
                        $this->columnWidths[$i] = $cellWidth + $lengthColumnBorder;
                    }
                }
                if (!str_contains($cell ?? '', "\n")) {
                    continue;
                }
                $eol = str_contains($cell ?? '', "\r\n") ? "\r\n" : "\n";
                $escaped = implode($eol, array_map(OutputFormatter::escapeTrailingBackslash(...), explode($eol, $cell)));
                $cell = $cell instanceof TableCell ? new TableCell($escaped, ['colspan' => $cell->getColspan()]) : $escaped;
                $lines = explode($eol, str_replace($eol, '<fg=default;bg=default></>' . $eol, $cell));
                foreach ($lines as $lineKey => $line) {
                    if ($colspan > 1) {
                        $line = new TableCell($line, ['colspan' => $colspan]);
                    }
                    if (0 === $lineKey) {
                        $rows[$rowKey][$column] = $line;
                    } else {
                        if (!\array_key_exists($rowKey, $unmergedRows) || !\array_key_exists($lineKey, $unmergedRows[$rowKey])) {
                            $unmergedRows[$rowKey][$lineKey] = $this->copyRow($rows, $rowKey);
                        }
                        $unmergedRows[$rowKey][$lineKey][$column] = $line;
                    }
                }
            }
        }
        return new TableRows(function () use ($rows, $unmergedRows): \Traversable {
            foreach ($rows as $rowKey => $row) {
                $rowGroup = [$row instanceof TableSeparator ? $row : $this->fillCells($row)];
                if (isset($unmergedRows[$rowKey])) {
                    foreach ($unmergedRows[$rowKey] as $row) {
                        $rowGroup[] = $row instanceof TableSeparator ? $row : $this->fillCells($row);
                    }
                }
                yield $rowGroup;
            }
        });
    }
    private function calculateRowCount(): int
    {
        $numberOfRows = \count(iterator_to_array($this->buildTableRows(array_merge($this->headers, [new TableSeparator()], $this->rows))));
        if ($this->headers) {
            ++$numberOfRows;
            // Add row for header separator
        }
        if ($this->rows) {
            ++$numberOfRows;
            // Add row for footer separator
        }
        return $numberOfRows;
    }
    /**
     * fill rows that contains rowspan > 1.
     *
     * @throws InvalidArgumentException
     */
    private function fillNextRows(array $rows, int $line): array
    {
        $unmergedRows = [];
        foreach ($rows[$line] as $column => $cell) {
            if (null !== $cell && !$cell instanceof TableCell && !\is_scalar($cell) && !$cell instanceof \Stringable) {
                throw new InvalidArgumentException(\sprintf('A cell must be a TableCell, a scalar or an object implementing "__toString()", "%s" given.', get_debug_type($cell)));
            }
            if ($cell instanceof TableCell && $cell->getRowspan() > 1) {
                $nbLines = $cell->getRowspan() - 1;
                $lines = [$cell];
                if (str_contains($cell, "\n")) {
                    $eol = str_contains($cell, "\r\n") ? "\r\n" : "\n";
                    $lines = explode($eol, str_replace($eol, '<fg=default;bg=default>' . $eol . '</>', $cell));
                    $nbLines = \count($lines) > $nbLines ? substr_count($cell, $eol) : $nbLines;
                    $rows[$line][$column] = new TableCell($lines[0], ['colspan' => $cell->getColspan(), 'style' => $cell->getStyle()]);
                    unset($lines[0]);
                }
                // create a two dimensional array (rowspan x colspan)
                $unmergedRows = array_replace_recursive(array_fill($line + 1, $nbLines, []), $unmergedRows);
                foreach ($unmergedRows as $unmergedRowKey => $unmergedRow) {
                    $value = $lines[$unmergedRowKey - $line] ?? '';
                    $unmergedRows[$unmergedRowKey][$column] = new TableCell($value, ['colspan' => $cell->getColspan(), 'style' => $cell->getStyle()]);
                    if ($nbLines === $unmergedRowKey - $line) {
                        break;
                    }
                }
            }
        }
        foreach ($unmergedRows as $unmergedRowKey => $unmergedRow) {
            // we need to know if $unmergedRow will be merged or inserted into $rows
            if (isset($rows[$unmergedRowKey]) && \is_array($rows[$unmergedRowKey]) && $this->getNumberOfColumns($rows[$unmergedRowKey]) + $this->getNumberOfColumns($unmergedRows[$unmergedRowKey]) <= $this->numberOfColumns) {
                foreach ($unmergedRow as $cellKey => $cell) {
                    // insert cell into row at cellKey position
                    array_splice($rows[$unmergedRowKey], $cellKey, 0, [$cell]);
                }
            } else {
                $row = $this->copyRow($rows, $unmergedRowKey - 1);
                foreach ($unmergedRow as $column => $cell) {
                    if (!empty($cell)) {
                        $row[$column] = $unmergedRow[$column];
                    }
                }
                array_splice($rows, $unmergedRowKey, 0, [$row]);
            }
        }
        return $rows;
    }
    /**
     * fill cells for a row that contains colspan > 1.
     */
    private function fillCells(iterable $row): iterable
    {
        $newRow = [];
        foreach ($row as $column => $cell) {
            $newRow[] = $cell;
            if ($cell instanceof TableCell && $cell->getColspan() > 1) {
                foreach (range($column + 1, $column + $cell->getColspan() - 1) as $position) {
                    // insert empty value at column position
                    $newRow[] = '';
                }
            }
        }
        return $newRow ?: $row;
    }
    private function copyRow(array $rows, int $line): array
    {
        $row = $rows[$line];
        foreach ($row as $cellKey => $cellValue) {
            $row[$cellKey] = '';
            if ($cellValue instanceof TableCell) {
                $row[$cellKey] = new TableCell('', ['colspan' => $cellValue->getColspan()]);
            }
        }
        return $row;
    }
    /**
     * Gets number of columns by row.
     */
    private function getNumberOfColumns(array $row): int
    {
        $columns = \count($row);
        foreach ($row as $column) {
            $columns += $column instanceof TableCell ? $column->getColspan() - 1 : 0;
        }
        return $columns;
    }
    /**
     * Gets list of columns for the given row.
     */
    private function getRowColumns(array $row): array
    {
        $columns = range(0, $this->numberOfColumns - 1);
        foreach ($row as $cellKey => $cell) {
            if ($cell instanceof TableCell && $cell->getColspan() > 1) {
                // exclude grouped columns.
                $columns = array_diff($columns, range($cellKey + 1, $cellKey + $cell->getColspan() - 1));
            }
        }
        return $columns;
    }
    /**
     * Calculates columns widths.
     */
    private function calculateColumnsWidth(iterable $groups): void
    {
        for ($column = 0; $column < $this->numberOfColumns; ++$column) {
            $lengths = [];
            foreach ($groups as $group) {
                foreach ($group as $row) {
                    if ($row instanceof TableSeparator) {
                        continue;
                    }
                    foreach ($row as $i => $cell) {
                        if ($cell instanceof TableCell) {
                            $textContent = Helper::removeDecoration($this->output->getFormatter(), $cell);
                            $textLength = Helper::width($textContent);
                            if ($textLength > 0) {
                                $contentColumns = mb_str_split($textContent, ceil($textLength / $cell->getColspan()));
                                foreach ($contentColumns as $position => $content) {
                                    $row[$i + $position] = $content;
                                }
                            }
                        }
                    }
                    $lengths[] = $this->getCellWidth($row, $column);
                }
            }
            $this->effectiveColumnWidths[$column] = max($lengths) + Helper::width($this->style->getCellRowContentFormat()) - 2;
        }
    }
    private function getColumnSeparatorWidth(): int
    {
        return Helper::width(\sprintf($this->style->getBorderFormat(), $this->style->getBorderChars()[3]));
    }
    private function getCellWidth(array $row, int $column): int
    {
        $cellWidth = 0;
        if (isset($row[$column])) {
            $cell = $row[$column];
            $cellWidth = Helper::width(Helper::removeDecoration($this->output->getFormatter(), $cell));
        }
        $columnWidth = $this->columnWidths[$column] ?? 0;
        $cellWidth = max($cellWidth, $columnWidth);
        return isset($this->columnMaxWidths[$column]) ? min($this->columnMaxWidths[$column], $cellWidth) : $cellWidth;
    }
    /**
     * Called after rendering to cleanup cache data.
     */
    private function cleanup(): void
    {
        $this->effectiveColumnWidths = [];
        unset($this->numberOfColumns);
    }
    /**
     * @return array<string, TableStyle>
     */
    private static function initStyles(): array
    {
        $borderless = new TableStyle();
        $borderless->setHorizontalBorderChars('=')->setVerticalBorderChars(' ')->setDefaultCrossingChar(' ');
        $compact = new TableStyle();
        $compact->setHorizontalBorderChars('')->setVerticalBorderChars('')->setDefaultCrossingChar('')->setCellRowContentFormat('%s ');
        $styleGuide = new TableStyle();
        $styleGuide->setHorizontalBorderChars('-')->setVerticalBorderChars(' ')->setDefaultCrossingChar(' ')->setCellHeaderFormat('%s');
        $box = (new TableStyle())->setHorizontalBorderChars('─')->setVerticalBorderChars('│')->setCrossingChars('┼', '┌', '┬', '┐', '┤', '┘', '┴', '└', '├');
        $boxDouble = (new TableStyle())->setHorizontalBorderChars('═', '─')->setVerticalBorderChars('║', '│')->setCrossingChars('┼', '╔', '╤', '╗', '╢', '╝', '╧', '╚', '╟', '╠', '╪', '╣');
        return ['default' => new TableStyle(), 'borderless' => $borderless, 'compact' => $compact, 'symfony-style-guide' => $styleGuide, 'box' => $box, 'box-double' => $boxDouble];
    }
    private function resolveStyle(TableStyle|string $name): TableStyle
    {
        if ($name instanceof TableStyle) {
            return $name;
        }
        return self::$styles[$name] ?? throw new InvalidArgumentException(\sprintf('Style "%s" is not defined.', $name));
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Console\Helper;

use _ContaoManager\Symfony\Component\Console\Exception\InvalidArgumentException;
use _ContaoManager\Symfony\Component\Console\Exception\LogicException;
use _ContaoManager\Symfony\Component\Console\Output\ConsoleSectionOutput;
use _ContaoManager\Symfony\Component\Console\Output\OutputInterface;
/**
 * @author Kevin Bond <kevinbond@gmail.com>
 */
class ProgressIndicator
{
    private const FORMATS = ['normal' => ' %indicator% %message%', 'normal_no_ansi' => ' %message%', 'verbose' => ' %indicator% %message% (%elapsed:6s%)', 'verbose_no_ansi' => ' %message% (%elapsed:6s%)', 'very_verbose' => ' %indicator% %message% (%elapsed:6s%, %memory:6s%)', 'very_verbose_no_ansi' => ' %message% (%elapsed:6s%, %memory:6s%)'];
    private OutputInterface $output;
    private int $startTime;
    private ?string $format = null;
    private ?string $message = null;
    private array $indicatorValues;
    private int $indicatorCurrent;
    private int $indicatorChangeInterval;
    private float $indicatorUpdateTime;
    private bool $started = \false;
    /**
     * @var array<string, callable>
     */
    private static array $formatters;
    /**
     * @param int        $indicatorChangeInterval Change interval in milliseconds
     * @param array|null $indicatorValues         Animated indicator characters
     */
    public function __construct(OutputInterface $output, ?string $format = null, int $indicatorChangeInterval = 100, ?array $indicatorValues = null)
    {
        $this->output = $output;
        $format ??= $this->determineBestFormat();
        $indicatorValues ??= ['-', '\\', '|', '/'];
        $indicatorValues = array_values($indicatorValues);
        if (2 > \count($indicatorValues)) {
            throw new InvalidArgumentException('Must have at least 2 indicator value characters.');
        }
        $this->format = self::getFormatDefinition($format);
        $this->indicatorChangeInterval = $indicatorChangeInterval;
        $this->indicatorValues = $indicatorValues;
        $this->startTime = time();
    }
    /**
     * Sets the current indicator message.
     *
     * @return void
     */
    public function setMessage(?string $message)
    {
        $this->message = $message;
        $this->display();
    }
    /**
     * Starts the indicator output.
     *
     * @return void
     */
    public function start(string $message)
    {
        if ($this->started) {
            throw new LogicException('Progress indicator already started.');
        }
        $this->message = $message;
        $this->started = \true;
        $this->startTime = time();
        $this->indicatorUpdateTime = $this->getCurrentTimeInMilliseconds() + $this->indicatorChangeInterval;
        $this->indicatorCurrent = 0;
        $this->display();
    }
    /**
     * Advances the indicator.
     *
     * @return void
     */
    public function advance()
    {
        if (!$this->started) {
            throw new LogicException('Progress indicator has not yet been started.');
        }
        if (!$this->output->isDecorated()) {
            return;
        }
        $currentTime = $this->getCurrentTimeInMilliseconds();
        if ($currentTime < $this->indicatorUpdateTime) {
            return;
        }
        $this->indicatorUpdateTime = $currentTime + $this->indicatorChangeInterval;
        ++$this->indicatorCurrent;
        $this->display();
    }
    /**
     * Finish the indicator with message.
     *
     * @return void
     */
    public function finish(string $message)
    {
        if (!$this->started) {
            throw new LogicException('Progress indicator has not yet been started.');
        }
        $this->message = $message;
        $this->display();
        if (!$this->output instanceof ConsoleSectionOutput) {
            $this->output->writeln('');
        }
        $this->started = \false;
    }
    /**
     * Gets the format for a given name.
     */
    public static function getFormatDefinition(string $name): ?string
    {
        return self::FORMATS[$name] ?? null;
    }
    /**
     * Sets a placeholder formatter for a given name.
     *
     * This method also allow you to override an existing placeholder.
     *
     * @return void
     */
    public static function setPlaceholderFormatterDefinition(string $name, callable $callable)
    {
        self::$formatters ??= self::initPlaceholderFormatters();
        self::$formatters[$name] = $callable;
    }
    /**
     * Gets the placeholder formatter for a given name (including the delimiter char like %).
     */
    public static function getPlaceholderFormatterDefinition(string $name): ?callable
    {
        self::$formatters ??= self::initPlaceholderFormatters();
        return self::$formatters[$name] ?? null;
    }
    private function display(): void
    {
        if (OutputInterface::VERBOSITY_QUIET === $this->output->getVerbosity()) {
            return;
        }
        $this->overwrite(preg_replace_callback("{%([a-z\\-_]+)(?:\\:([^%]+))?%}i", function ($matches) {
            if ($formatter = self::getPlaceholderFormatterDefinition($matches[1])) {
                return $formatter($this);
            }
            return $matches[0];
        }, $this->format ?? ''));
    }
    private function determineBestFormat(): string
    {
        return match ($this->output->getVerbosity()) {
            // OutputInterface::VERBOSITY_QUIET: display is disabled anyway
            OutputInterface::VERBOSITY_VERBOSE => $this->output->isDecorated() ? 'verbose' : 'verbose_no_ansi',
            OutputInterface::VERBOSITY_VERY_VERBOSE, OutputInterface::VERBOSITY_DEBUG => $this->output->isDecorated() ? 'very_verbose' : 'very_verbose_no_ansi',
            default => $this->output->isDecorated() ? 'normal' : 'normal_no_ansi',
        };
    }
    /**
     * Overwrites a previous message to the output.
     */
    private function overwrite(string $message): void
    {
        if ($this->output instanceof ConsoleSectionOutput) {
            $this->output->overwrite($message);
        } elseif ($this->output->isDecorated()) {
            $this->output->write("\r\x1b[2K");
            $this->output->write($message);
        } else {
            $this->output->writeln($message);
        }
    }
    private function getCurrentTimeInMilliseconds(): float
    {
        return round(microtime(\true) * 1000);
    }
    /**
     * @return array<string, \Closure>
     */
    private static function initPlaceholderFormatters(): array
    {
        return ['indicator' => fn(self $indicator) => $indicator->indicatorValues[$indicator->indicatorCurrent % \count($indicator->indicatorValues)], 'message' => fn(self $indicator) => $indicator->message, 'elapsed' => fn(self $indicator) => Helper::formatTime(time() - $indicator->startTime, 2), 'memory' => fn() => Helper::formatMemory(memory_get_usage(\true))];
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Console\Helper;

use _ContaoManager\Symfony\Component\Console\Descriptor\DescriptorInterface;
use _ContaoManager\Symfony\Component\Console\Descriptor\JsonDescriptor;
use _ContaoManager\Symfony\Component\Console\Descriptor\MarkdownDescriptor;
use _ContaoManager\Symfony\Component\Console\Descriptor\ReStructuredTextDescriptor;
use _ContaoManager\Symfony\Component\Console\Descriptor\TextDescriptor;
use _ContaoManager\Symfony\Component\Console\Descriptor\XmlDescriptor;
use _ContaoManager\Symfony\Component\Console\Exception\InvalidArgumentException;
use _ContaoManager\Symfony\Component\Console\Output\OutputInterface;
/**
 * This class adds helper method to describe objects in various formats.
 *
 * @author Jean-François Simon <contact@jfsimon.fr>
 */
class DescriptorHelper extends Helper
{
    /**
     * @var DescriptorInterface[]
     */
    private array $descriptors = [];
    public function __construct()
    {
        $this->register('txt', new TextDescriptor())->register('xml', new XmlDescriptor())->register('json', new JsonDescriptor())->register('md', new MarkdownDescriptor())->register('rst', new ReStructuredTextDescriptor());
    }
    /**
     * Describes an object if supported.
     *
     * Available options are:
     * * format: string, the output format name
     * * raw_text: boolean, sets output type as raw
     *
     * @return void
     *
     * @throws InvalidArgumentException when the given format is not supported
     */
    public function describe(OutputInterface $output, ?object $object, array $options = [])
    {
        $options = array_merge(['raw_text' => \false, 'format' => 'txt'], $options);
        if (!isset($this->descriptors[$options['format']])) {
            throw new InvalidArgumentException(\sprintf('Unsupported format "%s".', $options['format']));
        }
        $descriptor = $this->descriptors[$options['format']];
        $descriptor->describe($output, $object, $options);
    }
    /**
     * Registers a descriptor.
     *
     * @return $this
     */
    public function register(string $format, DescriptorInterface $descriptor): static
    {
        $this->descriptors[$format] = $descriptor;
        return $this;
    }
    public function getName(): string
    {
        return 'descriptor';
    }
    public function getFormats(): array
    {
        return array_keys($this->descriptors);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Console\DependencyInjection;

use _ContaoManager\Symfony\Component\Console\Command\Command;
use _ContaoManager\Symfony\Component\Console\Command\LazyCommand;
use _ContaoManager\Symfony\Component\Console\CommandLoader\ContainerCommandLoader;
use _ContaoManager\Symfony\Component\DependencyInjection\Argument\ServiceClosureArgument;
use _ContaoManager\Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use _ContaoManager\Symfony\Component\DependencyInjection\Compiler\ServiceLocatorTagPass;
use _ContaoManager\Symfony\Component\DependencyInjection\ContainerBuilder;
use _ContaoManager\Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
use _ContaoManager\Symfony\Component\DependencyInjection\Reference;
use _ContaoManager\Symfony\Component\DependencyInjection\TypedReference;
/**
 * Registers console commands.
 *
 * @author Grégoire Pineau <lyrixx@lyrixx.info>
 */
class AddConsoleCommandPass implements CompilerPassInterface
{
    /**
     * @return void
     */
    public function process(ContainerBuilder $container)
    {
        $commandServices = $container->findTaggedServiceIds('console.command', \true);
        $lazyCommandMap = [];
        $lazyCommandRefs = [];
        $serviceIds = [];
        foreach ($commandServices as $id => $tags) {
            $definition = $container->getDefinition($id);
            $definition->addTag('container.no_preload');
            $class = $container->getParameterBag()->resolveValue($definition->getClass());
            if (isset($tags[0]['command'])) {
                $aliases = $tags[0]['command'];
            } else {
                if (!$r = $container->getReflectionClass($class)) {
                    throw new InvalidArgumentException(\sprintf('Class "%s" used for service "%s" cannot be found.', $class, $id));
                }
                if (!$r->isSubclassOf(Command::class)) {
                    throw new InvalidArgumentException(\sprintf('The service "%s" tagged "%s" must be a subclass of "%s".', $id, 'console.command', Command::class));
                }
                $aliases = str_replace('%', '%%', $class::getDefaultName() ?? '');
            }
            $aliases = explode('|', $aliases ?? '');
            $commandName = array_shift($aliases);
            if ($isHidden = '' === $commandName) {
                $commandName = array_shift($aliases);
            }
            if (null === $commandName) {
                if (!$definition->isPublic() || $definition->isPrivate() || $definition->hasTag('container.private')) {
                    $commandId = 'console.command.public_alias.' . $id;
                    $container->setAlias($commandId, $id)->setPublic(\true);
                    $id = $commandId;
                }
                $serviceIds[] = $id;
                continue;
            }
            $description = $tags[0]['description'] ?? null;
            unset($tags[0]);
            $lazyCommandMap[$commandName] = $id;
            $lazyCommandRefs[$id] = new TypedReference($id, $class);
            foreach ($aliases as $alias) {
                $lazyCommandMap[$alias] = $id;
            }
            foreach ($tags as $tag) {
                if (isset($tag['command'])) {
                    $aliases[] = $tag['command'];
                    $lazyCommandMap[$tag['command']] = $id;
                }
                $description ??= $tag['description'] ?? null;
            }
            $definition->addMethodCall('setName', [$commandName]);
            if ($aliases) {
                $definition->addMethodCall('setAliases', [$aliases]);
            }
            if ($isHidden) {
                $definition->addMethodCall('setHidden', [\true]);
            }
            if (!$description) {
                if (!$r = $container->getReflectionClass($class)) {
                    throw new InvalidArgumentException(\sprintf('Class "%s" used for service "%s" cannot be found.', $class, $id));
                }
                if (!$r->isSubclassOf(Command::class)) {
                    throw new InvalidArgumentException(\sprintf('The service "%s" tagged "%s" must be a subclass of "%s".', $id, 'console.command', Command::class));
                }
                $description = str_replace('%', '%%', $class::getDefaultDescription() ?? '');
            }
            if ($description) {
                $definition->addMethodCall('setDescription', [$description]);
                $container->register('.' . $id . '.lazy', LazyCommand::class)->setArguments([$commandName, $aliases, $description, $isHidden, new ServiceClosureArgument($lazyCommandRefs[$id])]);
                $lazyCommandRefs[$id] = new Reference('.' . $id . '.lazy');
            }
        }
        $container->register('console.command_loader', ContainerCommandLoader::class)->setPublic(\true)->addTag('container.no_preload')->setArguments([ServiceLocatorTagPass::register($container, $lazyCommandRefs), $lazyCommandMap]);
        $container->setParameter('console.command.ids', $serviceIds);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Console\Exception;

/**
 * @author Jérôme Tamarelle <jerome@tamarelle.net>
 */
class LogicException extends \LogicException implements ExceptionInterface
{
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Console\Exception;

/**
 * Represents an incorrect option name or value typed in the console.
 *
 * @author Jérôme Tamarelle <jerome@tamarelle.net>
 */
class InvalidOptionException extends \InvalidArgumentException implements ExceptionInterface
{
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Console\Exception;

use _ContaoManager\Symfony\Component\Console\Messenger\RunCommandContext;
/**
 * @author Kevin Bond <kevinbond@gmail.com>
 */
final class RunCommandFailedException extends RuntimeException
{
    public function __construct(\Throwable|string $exception, public readonly RunCommandContext $context)
    {
        parent::__construct($exception instanceof \Throwable ? $exception->getMessage() : $exception, $exception instanceof \Throwable && \is_int($exception->getCode()) ? $exception->getCode() : 0, $exception instanceof \Throwable ? $exception : null);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Console\Exception;

/**
 * ExceptionInterface.
 *
 * @author Jérôme Tamarelle <jerome@tamarelle.net>
 */
interface ExceptionInterface extends \Throwable
{
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Console\Exception;

/**
 * @author Jérôme Tamarelle <jerome@tamarelle.net>
 */
class RuntimeException extends \RuntimeException implements ExceptionInterface
{
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Console\Exception;

/**
 * Represents an incorrect namespace typed in the console.
 *
 * @author Pierre du Plessis <pdples@gmail.com>
 */
class NamespaceNotFoundException extends CommandNotFoundException
{
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Console\Exception;

/**
 * @author Jérôme Tamarelle <jerome@tamarelle.net>
 */
class InvalidArgumentException extends \InvalidArgumentException implements ExceptionInterface
{
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Console\Exception;

/**
 * Represents failure to read input from stdin.
 *
 * @author Gabriel Ostrolucký <gabriel.ostrolucky@gmail.com>
 */
class MissingInputException extends RuntimeException implements ExceptionInterface
{
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Console\Exception;

/**
 * Represents an incorrect command name typed in the console.
 *
 * @author Jérôme Tamarelle <jerome@tamarelle.net>
 */
class CommandNotFoundException extends \InvalidArgumentException implements ExceptionInterface
{
    private array $alternatives;
    /**
     * @param string          $message      Exception message to throw
     * @param string[]        $alternatives List of similar defined names
     * @param int             $code         Exception code
     * @param \Throwable|null $previous     Previous exception used for the exception chaining
     */
    public function __construct(string $message, array $alternatives = [], int $code = 0, ?\Throwable $previous = null)
    {
        parent::__construct($message, $code, $previous);
        $this->alternatives = $alternatives;
    }
    /**
     * @return string[]
     */
    public function getAlternatives(): array
    {
        return $this->alternatives;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Console\Event;

use _ContaoManager\Symfony\Component\Console\Command\Command;
use _ContaoManager\Symfony\Component\Console\Input\InputInterface;
use _ContaoManager\Symfony\Component\Console\Output\OutputInterface;
/**
 * Allows to manipulate the exit code of a command after its execution.
 *
 * @author Francesco Levorato <git@flevour.net>
 * @author Jules Pietri <jules@heahprod.com>
 */
final class ConsoleTerminateEvent extends ConsoleEvent
{
    public function __construct(Command $command, InputInterface $input, OutputInterface $output, private int $exitCode, private readonly ?int $interruptingSignal = null)
    {
        parent::__construct($command, $input, $output);
    }
    public function setExitCode(int $exitCode): void
    {
        $this->exitCode = $exitCode;
    }
    public function getExitCode(): int
    {
        return $this->exitCode;
    }
    public function getInterruptingSignal(): ?int
    {
        return $this->interruptingSignal;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Console\Event;

use _ContaoManager\Symfony\Component\Console\Command\Command;
use _ContaoManager\Symfony\Component\Console\Input\InputInterface;
use _ContaoManager\Symfony\Component\Console\Output\OutputInterface;
/**
 * Allows to handle throwables thrown while running a command.
 *
 * @author Wouter de Jong <wouter@wouterj.nl>
 */
final class ConsoleErrorEvent extends ConsoleEvent
{
    private \Throwable $error;
    private int $exitCode;
    public function __construct(InputInterface $input, OutputInterface $output, \Throwable $error, ?Command $command = null)
    {
        parent::__construct($command, $input, $output);
        $this->error = $error;
    }
    public function getError(): \Throwable
    {
        return $this->error;
    }
    public function setError(\Throwable $error): void
    {
        $this->error = $error;
    }
    public function setExitCode(int $exitCode): void
    {
        $this->exitCode = $exitCode;
        $r = new \ReflectionProperty($this->error, 'code');
        $r->setValue($this->error, $this->exitCode);
    }
    public function getExitCode(): int
    {
        return $this->exitCode ?? (\is_int($this->error->getCode()) && 0 !== $this->error->getCode() ? $this->error->getCode() : 1);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Console\Event;

/**
 * Allows to do things before the command is executed, like skipping the command or executing code before the command is
 * going to be executed.
 *
 * Changing the input arguments will have no effect.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
final class ConsoleCommandEvent extends ConsoleEvent
{
    /**
     * The return code for skipped commands, this will also be passed into the terminate event.
     */
    public const RETURN_CODE_DISABLED = 113;
    /**
     * Indicates if the command should be run or skipped.
     */
    private bool $commandShouldRun = \true;
    /**
     * Disables the command, so it won't be run.
     */
    public function disableCommand(): bool
    {
        return $this->commandShouldRun = \false;
    }
    public function enableCommand(): bool
    {
        return $this->commandShouldRun = \true;
    }
    /**
     * Returns true if the command is runnable, false otherwise.
     */
    public function commandShouldRun(): bool
    {
        return $this->commandShouldRun;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Console\Event;

use _ContaoManager\Symfony\Component\Console\Command\Command;
use _ContaoManager\Symfony\Component\Console\Input\InputInterface;
use _ContaoManager\Symfony\Component\Console\Output\OutputInterface;
use _ContaoManager\Symfony\Contracts\EventDispatcher\Event;
/**
 * Allows to inspect input and output of a command.
 *
 * @author Francesco Levorato <git@flevour.net>
 */
class ConsoleEvent extends Event
{
    protected $command;
    private InputInterface $input;
    private OutputInterface $output;
    public function __construct(?Command $command, InputInterface $input, OutputInterface $output)
    {
        $this->command = $command;
        $this->input = $input;
        $this->output = $output;
    }
    /**
     * Gets the command that is executed.
     */
    public function getCommand(): ?Command
    {
        return $this->command;
    }
    /**
     * Gets the input instance.
     */
    public function getInput(): InputInterface
    {
        return $this->input;
    }
    /**
     * Gets the output instance.
     */
    public function getOutput(): OutputInterface
    {
        return $this->output;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Console\Event;

use _ContaoManager\Symfony\Component\Console\Command\Command;
use _ContaoManager\Symfony\Component\Console\Input\InputInterface;
use _ContaoManager\Symfony\Component\Console\Output\OutputInterface;
/**
 * @author marie <marie@users.noreply.github.com>
 */
final class ConsoleSignalEvent extends ConsoleEvent
{
    private int $handlingSignal;
    private int|false $exitCode;
    public function __construct(Command $command, InputInterface $input, OutputInterface $output, int $handlingSignal, int|false $exitCode = 0)
    {
        parent::__construct($command, $input, $output);
        $this->handlingSignal = $handlingSignal;
        $this->exitCode = $exitCode;
    }
    public function getHandlingSignal(): int
    {
        return $this->handlingSignal;
    }
    public function setExitCode(int $exitCode): void
    {
        if ($exitCode < 0 || $exitCode > 255) {
            throw new \InvalidArgumentException('Exit code must be between 0 and 255.');
        }
        $this->exitCode = $exitCode;
    }
    public function abortExit(): void
    {
        $this->exitCode = \false;
    }
    public function getExitCode(): int|false
    {
        return $this->exitCode;
    }
}
{
    "name": "symfony\/console",
    "type": "library",
    "description": "Eases the creation of beautiful and testable command line interfaces",
    "keywords": [
        "console",
        "cli",
        "command-line",
        "terminal"
    ],
    "homepage": "https:\/\/symfony.com",
    "license": "MIT",
    "authors": [
        {
            "name": "Fabien Potencier",
            "email": "fabien@symfony.com"
        },
        {
            "name": "Symfony Community",
            "homepage": "https:\/\/symfony.com\/contributors"
        }
    ],
    "require": {
        "php": ">=8.1",
        "symfony\/deprecation-contracts": "^2.5|^3",
        "symfony\/polyfill-mbstring": "~1.0",
        "symfony\/service-contracts": "^2.5|^3",
        "symfony\/string": "^5.4|^6.0|^7.0"
    },
    "require-dev": {
        "symfony\/config": "^5.4|^6.0|^7.0",
        "symfony\/event-dispatcher": "^5.4|^6.0|^7.0",
        "symfony\/dependency-injection": "^5.4|^6.0|^7.0",
        "symfony\/http-foundation": "^6.4|^7.0",
        "symfony\/http-kernel": "^6.4|^7.0",
        "symfony\/lock": "^5.4|^6.0|^7.0",
        "symfony\/messenger": "^5.4|^6.0|^7.0",
        "symfony\/process": "^5.4|^6.0|^7.0",
        "symfony\/stopwatch": "^5.4|^6.0|^7.0",
        "symfony\/var-dumper": "^5.4|^6.0|^7.0",
        "psr\/log": "^1|^2|^3"
    },
    "provide": {
        "psr\/log-implementation": "1.0|2.0|3.0"
    },
    "conflict": {
        "symfony\/dependency-injection": "<5.4",
        "symfony\/dotenv": "<5.4",
        "symfony\/event-dispatcher": "<5.4",
        "symfony\/lock": "<5.4",
        "symfony\/process": "<5.4"
    },
    "autoload": {
        "psr-4": {
            "_ContaoManager\\Symfony\\Component\\Console\\": ""
        },
        "exclude-from-classmap": [
            "\/Tests\/"
        ]
    },
    "minimum-stability": "dev"
}<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Console\Debug;

use _ContaoManager\Symfony\Component\Console\Command\TraceableCommand;
use _ContaoManager\Symfony\Component\HttpFoundation\Request;
use _ContaoManager\Symfony\Component\HttpFoundation\Response;
/**
 * @internal
 */
final class CliRequest extends Request
{
    public function __construct(public readonly TraceableCommand $command)
    {
        parent::__construct(attributes: ['_controller' => \get_class($command->command), '_virtual_type' => 'command'], server: $_SERVER);
    }
    // Methods below allow to populate a profile, thus enable search and filtering
    public function getUri(): string
    {
        if ($this->server->has('SYMFONY_CLI_BINARY_NAME')) {
            $binary = $this->server->get('SYMFONY_CLI_BINARY_NAME') . ' console';
        } else {
            $binary = $this->server->get('argv')[0];
        }
        return $binary . ' ' . $this->command->input;
    }
    public function getMethod(): string
    {
        return $this->command->isInteractive ? 'INTERACTIVE' : 'BATCH';
    }
    public function getResponse(): Response
    {
        return new class($this->command->exitCode) extends Response
        {
            public function __construct(private readonly int $exitCode)
            {
                parent::__construct();
            }
            public function getStatusCode(): int
            {
                return $this->exitCode;
            }
        };
    }
    public function getClientIp(): string
    {
        $application = $this->command->getApplication();
        return $application->getName() . ' ' . $application->getVersion();
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Symfony\Component\Console\EventListener;

use _ContaoManager\Psr\Log\LoggerInterface;
use _ContaoManager\Symfony\Component\Console\ConsoleEvents;
use _ContaoManager\Symfony\Component\Console\Event\ConsoleErrorEvent;
use _ContaoManager\Symfony\Component\Console\Event\ConsoleEvent;
use _ContaoManager\Symfony\Component\Console\Event\ConsoleTerminateEvent;
use _ContaoManager\Symfony\Component\EventDispatcher\EventSubscriberInterface;
/**
 * @author James Halsall <james.t.halsall@googlemail.com>
 * @author Robin Chalas <robin.chalas@gmail.com>
 */
class ErrorListener implements EventSubscriberInterface
{
    private ?LoggerInterface $logger;
    public function __construct(?LoggerInterface $logger = null)
    {
        $this->logger = $logger;
    }
    /**
     * @return void
     */
    public function onConsoleError(ConsoleErrorEvent $event)
    {
        if (null === $this->logger) {
            return;
        }
        $error = $event->getError();
        if (!$inputString = $this->getInputString($event)) {
            $this->logger->critical('An error occurred while using the console. Message: "{message}"', ['exception' => $error, 'message' => $error->getMessage()]);
            return;
        }
        $this->logger->critical('Error thrown while running command "{command}". Message: "{message}"', ['exception' => $error, 'command' => $inputString, 'message' => $error->getMessage()]);
    }
    /**
     * @return void
     */
    public function onConsoleTerminate(ConsoleTerminateEvent $event)
    {
        if (null === $this->logger) {
            return;
        }
        $exitCode = $event->getExitCode();
        if (0 === $exitCode) {
            return;
        }
        if (!$inputString = $this->getInputString($event)) {
            $this->logger->debug('The console exited with code "{code}"', ['code' => $exitCode]);
            return;
        }
        $this->logger->debug('Command "{command}" exited with code "{code}"', ['command' => $inputString, 'code' => $exitCode]);
    }
    public static function getSubscribedEvents(): array
    {
        return [ConsoleEvents::ERROR => ['onConsoleError', -128], ConsoleEvents::TERMINATE => ['onConsoleTerminate', -128]];
    }
    private static function getInputString(ConsoleEvent $event): ?string
    {
        $commandName = $event->getCommand()?->getName();
        $input = $event->getInput();
        if ($input instanceof \Stringable) {
            if ($commandName) {
                return str_replace(["'{$commandName}'", "\"{$commandName}\""], $commandName, (string) $input);
            }
            return (string) $input;
        }
        return $commandName;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

use Symfony\Polyfill\Mbstring as p;

if (!function_exists('mb_convert_encoding')) {
    function mb_convert_encoding(array|string|null $string, ?string $to_encoding, array|string|null $from_encoding = null): array|string|false { return p\Mbstring::mb_convert_encoding($string ?? '', (string) $to_encoding, $from_encoding); }
}
if (!function_exists('mb_decode_mimeheader')) {
    function mb_decode_mimeheader(?string $string): string { return p\Mbstring::mb_decode_mimeheader((string) $string); }
}
if (!function_exists('mb_encode_mimeheader')) {
    function mb_encode_mimeheader(?string $string, ?string $charset = null, ?string $transfer_encoding = null, ?string $newline = "\r\n", ?int $indent = 0): string { return p\Mbstring::mb_encode_mimeheader((string) $string, $charset, $transfer_encoding, (string) $newline, (int) $indent); }
}
if (!function_exists('mb_decode_numericentity')) {
    function mb_decode_numericentity(?string $string, array $map, ?string $encoding = null): string { return p\Mbstring::mb_decode_numericentity((string) $string, $map, $encoding); }
}
if (!function_exists('mb_encode_numericentity')) {
    function mb_encode_numericentity(?string $string, array $map, ?string $encoding = null, ?bool $hex = false): string { return p\Mbstring::mb_encode_numericentity((string) $string, $map, $encoding, (bool) $hex); }
}
if (!function_exists('mb_convert_case')) {
    function mb_convert_case(?string $string, ?int $mode, ?string $encoding = null): string { return p\Mbstring::mb_convert_case((string) $string, (int) $mode, $encoding); }
}
if (!function_exists('mb_internal_encoding')) {
    function mb_internal_encoding(?string $encoding = null): string|bool { return p\Mbstring::mb_internal_encoding($encoding); }
}
if (!function_exists('mb_language')) {
    function mb_language(?string $language = null): string|bool { return p\Mbstring::mb_language($language); }
}
if (!function_exists('mb_list_encodings')) {
    function mb_list_encodings(): array { return p\Mbstring::mb_list_encodings(); }
}
if (!function_exists('mb_encoding_aliases')) {
    function mb_encoding_aliases(?string $encoding): array { return p\Mbstring::mb_encoding_aliases((string) $encoding); }
}
if (!function_exists('mb_check_encoding')) {
    function mb_check_encoding(array|string|null $value = null, ?string $encoding = null): bool { return p\Mbstring::mb_check_encoding($value, $encoding); }
}
if (!function_exists('mb_detect_encoding')) {
    function mb_detect_encoding(?string $string, array|string|null $encodings = null, ?bool $strict = false): string|false { return p\Mbstring::mb_detect_encoding((string) $string, $encodings, (bool) $strict); }
}
if (!function_exists('mb_detect_order')) {
    function mb_detect_order(array|string|null $encoding = null): array|bool { return p\Mbstring::mb_detect_order($encoding); }
}
if (!function_exists('mb_parse_str')) {
    function mb_parse_str(?string $string, &$result = []): bool { parse_str((string) $string, $result); return (bool) $result; }
}
if (!function_exists('mb_strlen')) {
    function mb_strlen(?string $string, ?string $encoding = null): int { return p\Mbstring::mb_strlen((string) $string, $encoding); }
}
if (!function_exists('mb_strpos')) {
    function mb_strpos(?string $haystack, ?string $needle, ?int $offset = 0, ?string $encoding = null): int|false { return p\Mbstring::mb_strpos((string) $haystack, (string) $needle, (int) $offset, $encoding); }
}
if (!function_exists('mb_strtolower')) {
    function mb_strtolower(?string $string, ?string $encoding = null): string { return p\Mbstring::mb_strtolower((string) $string, $encoding); }
}
if (!function_exists('mb_strtoupper')) {
    function mb_strtoupper(?string $string, ?string $encoding = null): string { return p\Mbstring::mb_strtoupper((string) $string, $encoding); }
}
if (!function_exists('mb_substitute_character')) {
    function mb_substitute_character(string|int|null $substitute_character = null): string|int|bool { return p\Mbstring::mb_substitute_character($substitute_character); }
}
if (!function_exists('mb_substr')) {
    function mb_substr(?string $string, ?int $start, ?int $length = null, ?string $encoding = null): string { return p\Mbstring::mb_substr((string) $string, (int) $start, $length, $encoding); }
}
if (!function_exists('mb_stripos')) {
    function mb_stripos(?string $haystack, ?string $needle, ?int $offset = 0, ?string $encoding = null): int|false { return p\Mbstring::mb_stripos((string) $haystack, (string) $needle, (int) $offset, $encoding); }
}
if (!function_exists('mb_stristr')) {
    function mb_stristr(?string $haystack, ?string $needle, ?bool $before_needle = false, ?string $encoding = null): string|false { return p\Mbstring::mb_stristr((string) $haystack, (string) $needle, (bool) $before_needle, $encoding); }
}
if (!function_exists('mb_strrchr')) {
    function mb_strrchr(?string $haystack, ?string $needle, ?bool $before_needle = false, ?string $encoding = null): string|false { return p\Mbstring::mb_strrchr((string) $haystack, (string) $needle, (bool) $before_needle, $encoding); }
}
if (!function_exists('mb_strrichr')) {
    function mb_strrichr(?string $haystack, ?string $needle, ?bool $before_needle = false, ?string $encoding = null): string|false { return p\Mbstring::mb_strrichr((string) $haystack, (string) $needle, (bool) $before_needle, $encoding); }
}
if (!function_exists('mb_strripos')) {
    function mb_strripos(?string $haystack, ?string $needle, ?int $offset = 0, ?string $encoding = null): int|false { return p\Mbstring::mb_strripos((string) $haystack, (string) $needle, (int) $offset, $encoding); }
}
if (!function_exists('mb_strrpos')) {
    function mb_strrpos(?string $haystack, ?string $needle, ?int $offset = 0, ?string $encoding = null): int|false { return p\Mbstring::mb_strrpos((string) $haystack, (string) $needle, (int) $offset, $encoding); }
}
if (!function_exists('mb_strstr')) {
    function mb_strstr(?string $haystack, ?string $needle, ?bool $before_needle = false, ?string $encoding = null): string|false { return p\Mbstring::mb_strstr((string) $haystack, (string) $needle, (bool) $before_needle, $encoding); }
}
if (!function_exists('mb_get_info')) {
    function mb_get_info(?string $type = 'all'): array|string|int|false|null { return p\Mbstring::mb_get_info((string) $type); }
}
if (!function_exists('mb_http_output')) {
    function mb_http_output(?string $encoding = null): string|bool { return p\Mbstring::mb_http_output($encoding); }
}
if (!function_exists('mb_strwidth')) {
    function mb_strwidth(?string $string, ?string $encoding = null): int { return p\Mbstring::mb_strwidth((string) $string, $encoding); }
}
if (!function_exists('mb_substr_count')) {
    function mb_substr_count(?string $haystack, ?string $needle, ?string $encoding = null): int { return p\Mbstring::mb_substr_count((string) $haystack, (string) $needle, $encoding); }
}
if (!function_exists('mb_output_handler')) {
    function mb_output_handler(?string $string, ?int $status): string { return p\Mbstring::mb_output_handler((string) $string, (int) $status); }
}
if (!function_exists('mb_http_input')) {
    function mb_http_input(?string $type = null): array|string|false { return p\Mbstring::mb_http_input($type); }
}

if (!function_exists('mb_convert_variables')) {
    function mb_convert_variables(?string $to_encoding, array|string|null $from_encoding, mixed &$var, mixed &...$vars): string|false { return p\Mbstring::mb_convert_variables((string) $to_encoding, $from_encoding ?? '', $var, ...$vars); }
}

if (!function_exists('mb_ord')) {
    function mb_ord(?string $string, ?string $encoding = null): int|false { return p\Mbstring::mb_ord((string) $string, $encoding); }
}
if (!function_exists('mb_chr')) {
    function mb_chr(?int $codepoint, ?string $encoding = null): string|false { return p\Mbstring::mb_chr((int) $codepoint, $encoding); }
}
if (!function_exists('mb_scrub')) {
    function mb_scrub(?string $string, ?string $encoding = null): string { $encoding ??= mb_internal_encoding(); return mb_convert_encoding((string) $string, $encoding, $encoding); }
}
if (!function_exists('mb_str_split')) {
    function mb_str_split(?string $string, ?int $length = 1, ?string $encoding = null): array { return p\Mbstring::mb_str_split((string) $string, (int) $length, $encoding); }
}

if (!function_exists('mb_str_pad')) {
    function mb_str_pad(string $string, int $length, string $pad_string = ' ', int $pad_type = STR_PAD_RIGHT, ?string $encoding = null): string { return p\Mbstring::mb_str_pad($string, $length, $pad_string, $pad_type, $encoding); }
}

if (!function_exists('mb_ucfirst')) {
    function mb_ucfirst(string $string, ?string $encoding = null): string { return p\Mbstring::mb_ucfirst($string, $encoding); }
}

if (!function_exists('mb_lcfirst')) {
    function mb_lcfirst(string $string, ?string $encoding = null): string { return p\Mbstring::mb_lcfirst($string, $encoding); }
}

if (!function_exists('mb_trim')) {
    function mb_trim(string $string, ?string $characters = null, ?string $encoding = null): string { return p\Mbstring::mb_trim($string, $characters, $encoding); }
}

if (!function_exists('mb_ltrim')) {
    function mb_ltrim(string $string, ?string $characters = null, ?string $encoding = null): string { return p\Mbstring::mb_ltrim($string, $characters, $encoding); }
}

if (!function_exists('mb_rtrim')) {
    function mb_rtrim(string $string, ?string $characters = null, ?string $encoding = null): string { return p\Mbstring::mb_rtrim($string, $characters, $encoding); }
}

if (extension_loaded('mbstring')) {
    return;
}

if (!defined('MB_CASE_UPPER')) {
    define('MB_CASE_UPPER', 0);
}
if (!defined('MB_CASE_LOWER')) {
    define('MB_CASE_LOWER', 1);
}
if (!defined('MB_CASE_TITLE')) {
    define('MB_CASE_TITLE', 2);
}
Copyright (c) 2015-present Fabien Potencier

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is furnished
to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
<?php

namespace _ContaoManager;

return ['İ' => 'i̇', 'µ' => 'μ', 'ſ' => 's', 'ͅ' => 'ι', 'ς' => 'σ', 'ϐ' => 'β', 'ϑ' => 'θ', 'ϕ' => 'φ', 'ϖ' => 'π', 'ϰ' => 'κ', 'ϱ' => 'ρ', 'ϵ' => 'ε', 'ẛ' => 'ṡ', 'ι' => 'ι', 'ß' => 'ss', 'ŉ' => 'ʼn', 'ǰ' => 'ǰ', 'ΐ' => 'ΐ', 'ΰ' => 'ΰ', 'և' => 'եւ', 'ẖ' => 'ẖ', 'ẗ' => 'ẗ', 'ẘ' => 'ẘ', 'ẙ' => 'ẙ', 'ẚ' => 'aʾ', 'ẞ' => 'ss', 'ὐ' => 'ὐ', 'ὒ' => 'ὒ', 'ὔ' => 'ὔ', 'ὖ' => 'ὖ', 'ᾀ' => 'ἀι', 'ᾁ' => 'ἁι', 'ᾂ' => 'ἂι', 'ᾃ' => 'ἃι', 'ᾄ' => 'ἄι', 'ᾅ' => 'ἅι', 'ᾆ' => 'ἆι', 'ᾇ' => 'ἇι', 'ᾈ' => 'ἀι', 'ᾉ' => 'ἁι', 'ᾊ' => 'ἂι', 'ᾋ' => 'ἃι', 'ᾌ' => 'ἄι', 'ᾍ' => 'ἅι', 'ᾎ' => 'ἆι', 'ᾏ' => 'ἇι', 'ᾐ' => 'ἠι', 'ᾑ' => 'ἡι', 'ᾒ' => 'ἢι', 'ᾓ' => 'ἣι', 'ᾔ' => 'ἤι', 'ᾕ' => 'ἥι', 'ᾖ' => 'ἦι', 'ᾗ' => 'ἧι', 'ᾘ' => 'ἠι', 'ᾙ' => 'ἡι', 'ᾚ' => 'ἢι', 'ᾛ' => 'ἣι', 'ᾜ' => 'ἤι', 'ᾝ' => 'ἥι', 'ᾞ' => 'ἦι', 'ᾟ' => 'ἧι', 'ᾠ' => 'ὠι', 'ᾡ' => 'ὡι', 'ᾢ' => 'ὢι', 'ᾣ' => 'ὣι', 'ᾤ' => 'ὤι', 'ᾥ' => 'ὥι', 'ᾦ' => 'ὦι', 'ᾧ' => 'ὧι', 'ᾨ' => 'ὠι', 'ᾩ' => 'ὡι', 'ᾪ' => 'ὢι', 'ᾫ' => 'ὣι', 'ᾬ' => 'ὤι', 'ᾭ' => 'ὥι', 'ᾮ' => 'ὦι', 'ᾯ' => 'ὧι', 'ᾲ' => 'ὰι', 'ᾳ' => 'αι', 'ᾴ' => 'άι', 'ᾶ' => 'ᾶ', 'ᾷ' => 'ᾶι', 'ᾼ' => 'αι', 'ῂ' => 'ὴι', 'ῃ' => 'ηι', 'ῄ' => 'ήι', 'ῆ' => 'ῆ', 'ῇ' => 'ῆι', 'ῌ' => 'ηι', 'ῒ' => 'ῒ', 'ῖ' => 'ῖ', 'ῗ' => 'ῗ', 'ῢ' => 'ῢ', 'ῤ' => 'ῤ', 'ῦ' => 'ῦ', 'ῧ' => 'ῧ', 'ῲ' => 'ὼι', 'ῳ' => 'ωι', 'ῴ' => 'ώι', 'ῶ' => 'ῶ', 'ῷ' => 'ῶι', 'ῼ' => 'ωι', 'ﬀ' => 'ff', 'ﬁ' => 'fi', 'ﬂ' => 'fl', 'ﬃ' => 'ffi', 'ﬄ' => 'ffl', 'ﬅ' => 'st', 'ﬆ' => 'st', 'ﬓ' => 'մն', 'ﬔ' => 'մե', 'ﬕ' => 'մի', 'ﬖ' => 'վն', 'ﬗ' => 'մխ'];
<?php

namespace _ContaoManager;

return array('A' => 'a', 'B' => 'b', 'C' => 'c', 'D' => 'd', 'E' => 'e', 'F' => 'f', 'G' => 'g', 'H' => 'h', 'I' => 'i', 'J' => 'j', 'K' => 'k', 'L' => 'l', 'M' => 'm', 'N' => 'n', 'O' => 'o', 'P' => 'p', 'Q' => 'q', 'R' => 'r', 'S' => 's', 'T' => 't', 'U' => 'u', 'V' => 'v', 'W' => 'w', 'X' => 'x', 'Y' => 'y', 'Z' => 'z', 'À' => 'à', 'Á' => 'á', 'Â' => 'â', 'Ã' => 'ã', 'Ä' => 'ä', 'Å' => 'å', 'Æ' => 'æ', 'Ç' => 'ç', 'È' => 'è', 'É' => 'é', 'Ê' => 'ê', 'Ë' => 'ë', 'Ì' => 'ì', 'Í' => 'í', 'Î' => 'î', 'Ï' => 'ï', 'Ð' => 'ð', 'Ñ' => 'ñ', 'Ò' => 'ò', 'Ó' => 'ó', 'Ô' => 'ô', 'Õ' => 'õ', 'Ö' => 'ö', 'Ø' => 'ø', 'Ù' => 'ù', 'Ú' => 'ú', 'Û' => 'û', 'Ü' => 'ü', 'Ý' => 'ý', 'Þ' => 'þ', 'Ā' => 'ā', 'Ă' => 'ă', 'Ą' => 'ą', 'Ć' => 'ć', 'Ĉ' => 'ĉ', 'Ċ' => 'ċ', 'Č' => 'č', 'Ď' => 'ď', 'Đ' => 'đ', 'Ē' => 'ē', 'Ĕ' => 'ĕ', 'Ė' => 'ė', 'Ę' => 'ę', 'Ě' => 'ě', 'Ĝ' => 'ĝ', 'Ğ' => 'ğ', 'Ġ' => 'ġ', 'Ģ' => 'ģ', 'Ĥ' => 'ĥ', 'Ħ' => 'ħ', 'Ĩ' => 'ĩ', 'Ī' => 'ī', 'Ĭ' => 'ĭ', 'Į' => 'į', 'İ' => 'i̇', 'Ĳ' => 'ĳ', 'Ĵ' => 'ĵ', 'Ķ' => 'ķ', 'Ĺ' => 'ĺ', 'Ļ' => 'ļ', 'Ľ' => 'ľ', 'Ŀ' => 'ŀ', 'Ł' => 'ł', 'Ń' => 'ń', 'Ņ' => 'ņ', 'Ň' => 'ň', 'Ŋ' => 'ŋ', 'Ō' => 'ō', 'Ŏ' => 'ŏ', 'Ő' => 'ő', 'Œ' => 'œ', 'Ŕ' => 'ŕ', 'Ŗ' => 'ŗ', 'Ř' => 'ř', 'Ś' => 'ś', 'Ŝ' => 'ŝ', 'Ş' => 'ş', 'Š' => 'š', 'Ţ' => 'ţ', 'Ť' => 'ť', 'Ŧ' => 'ŧ', 'Ũ' => 'ũ', 'Ū' => 'ū', 'Ŭ' => 'ŭ', 'Ů' => 'ů', 'Ű' => 'ű', 'Ų' => 'ų', 'Ŵ' => 'ŵ', 'Ŷ' => 'ŷ', 'Ÿ' => 'ÿ', 'Ź' => 'ź', 'Ż' => 'ż', 'Ž' => 'ž', 'Ɓ' => 'ɓ', 'Ƃ' => 'ƃ', 'Ƅ' => 'ƅ', 'Ɔ' => 'ɔ', 'Ƈ' => 'ƈ', 'Ɖ' => 'ɖ', 'Ɗ' => 'ɗ', 'Ƌ' => 'ƌ', 'Ǝ' => 'ǝ', 'Ə' => 'ə', 'Ɛ' => 'ɛ', 'Ƒ' => 'ƒ', 'Ɠ' => 'ɠ', 'Ɣ' => 'ɣ', 'Ɩ' => 'ɩ', 'Ɨ' => 'ɨ', 'Ƙ' => 'ƙ', 'Ɯ' => 'ɯ', 'Ɲ' => 'ɲ', 'Ɵ' => 'ɵ', 'Ơ' => 'ơ', 'Ƣ' => 'ƣ', 'Ƥ' => 'ƥ', 'Ʀ' => 'ʀ', 'Ƨ' => 'ƨ', 'Ʃ' => 'ʃ', 'Ƭ' => 'ƭ', 'Ʈ' => 'ʈ', 'Ư' => 'ư', 'Ʊ' => 'ʊ', 'Ʋ' => 'ʋ', 'Ƴ' => 'ƴ', 'Ƶ' => 'ƶ', 'Ʒ' => 'ʒ', 'Ƹ' => 'ƹ', 'Ƽ' => 'ƽ', 'Ǆ' => 'ǆ', 'ǅ' => 'ǆ', 'Ǉ' => 'ǉ', 'ǈ' => 'ǉ', 'Ǌ' => 'ǌ', 'ǋ' => 'ǌ', 'Ǎ' => 'ǎ', 'Ǐ' => 'ǐ', 'Ǒ' => 'ǒ', 'Ǔ' => 'ǔ', 'Ǖ' => 'ǖ', 'Ǘ' => 'ǘ', 'Ǚ' => 'ǚ', 'Ǜ' => 'ǜ', 'Ǟ' => 'ǟ', 'Ǡ' => 'ǡ', 'Ǣ' => 'ǣ', 'Ǥ' => 'ǥ', 'Ǧ' => 'ǧ', 'Ǩ' => 'ǩ', 'Ǫ' => 'ǫ', 'Ǭ' => 'ǭ', 'Ǯ' => 'ǯ', 'Ǳ' => 'ǳ', 'ǲ' => 'ǳ', 'Ǵ' => 'ǵ', 'Ƕ' => 'ƕ', 'Ƿ' => 'ƿ', 'Ǹ' => 'ǹ', 'Ǻ' => 'ǻ', 'Ǽ' => 'ǽ', 'Ǿ' => 'ǿ', 'Ȁ' => 'ȁ', 'Ȃ' => 'ȃ', 'Ȅ' => 'ȅ', 'Ȇ' => 'ȇ', 'Ȉ' => 'ȉ', 'Ȋ' => 'ȋ', 'Ȍ' => 'ȍ', 'Ȏ' => 'ȏ', 'Ȑ' => 'ȑ', 'Ȓ' => 'ȓ', 'Ȕ' => 'ȕ', 'Ȗ' => 'ȗ', 'Ș' => 'ș', 'Ț' => 'ț', 'Ȝ' => 'ȝ', 'Ȟ' => 'ȟ', 'Ƞ' => 'ƞ', 'Ȣ' => 'ȣ', 'Ȥ' => 'ȥ', 'Ȧ' => 'ȧ', 'Ȩ' => 'ȩ', 'Ȫ' => 'ȫ', 'Ȭ' => 'ȭ', 'Ȯ' => 'ȯ', 'Ȱ' => 'ȱ', 'Ȳ' => 'ȳ', 'Ⱥ' => 'ⱥ', 'Ȼ' => 'ȼ', 'Ƚ' => 'ƚ', 'Ⱦ' => 'ⱦ', 'Ɂ' => 'ɂ', 'Ƀ' => 'ƀ', 'Ʉ' => 'ʉ', 'Ʌ' => 'ʌ', 'Ɇ' => 'ɇ', 'Ɉ' => 'ɉ', 'Ɋ' => 'ɋ', 'Ɍ' => 'ɍ', 'Ɏ' => 'ɏ', 'Ͱ' => 'ͱ', 'Ͳ' => 'ͳ', 'Ͷ' => 'ͷ', 'Ϳ' => 'ϳ', 'Ά' => 'ά', 'Έ' => 'έ', 'Ή' => 'ή', 'Ί' => 'ί', 'Ό' => 'ό', 'Ύ' => 'ύ', 'Ώ' => 'ώ', 'Α' => 'α', 'Β' => 'β', 'Γ' => 'γ', 'Δ' => 'δ', 'Ε' => 'ε', 'Ζ' => 'ζ', 'Η' => 'η', 'Θ' => 'θ', 'Ι' => 'ι', 'Κ' => 'κ', 'Λ' => 'λ', 'Μ' => 'μ', 'Ν' => 'ν', 'Ξ' => 'ξ', 'Ο' => 'ο', 'Π' => 'π', 'Ρ' => 'ρ', 'Σ' => 'σ', 'Τ' => 'τ', 'Υ' => 'υ', 'Φ' => 'φ', 'Χ' => 'χ', 'Ψ' => 'ψ', 'Ω' => 'ω', 'Ϊ' => 'ϊ', 'Ϋ' => 'ϋ', 'Ϗ' => 'ϗ', 'Ϙ' => 'ϙ', 'Ϛ' => 'ϛ', 'Ϝ' => 'ϝ', 'Ϟ' => 'ϟ', 'Ϡ' => 'ϡ', 'Ϣ' => 'ϣ', 'Ϥ' => 'ϥ', 'Ϧ' => 'ϧ', 'Ϩ' => 'ϩ', 'Ϫ' => 'ϫ', 'Ϭ' => 'ϭ', 'Ϯ' => 'ϯ', 'ϴ' => 'θ', 'Ϸ' => 'ϸ', 'Ϲ' => 'ϲ', 'Ϻ' => 'ϻ', 'Ͻ' => 'ͻ', 'Ͼ' => 'ͼ', 'Ͽ' => 'ͽ', 'Ѐ' => 'ѐ', 'Ё' => 'ё', 'Ђ' => 'ђ', 'Ѓ' => 'ѓ', 'Є' => 'є', 'Ѕ' => 'ѕ', 'І' => 'і', 'Ї' => 'ї', 'Ј' => 'ј', 'Љ' => 'љ', 'Њ' => 'њ', 'Ћ' => 'ћ', 'Ќ' => 'ќ', 'Ѝ' => 'ѝ', 'Ў' => 'ў', 'Џ' => 'џ', 'А' => 'а', 'Б' => 'б', 'В' => 'в', 'Г' => 'г', 'Д' => 'д', 'Е' => 'е', 'Ж' => 'ж', 'З' => 'з', 'И' => 'и', 'Й' => 'й', 'К' => 'к', 'Л' => 'л', 'М' => 'м', 'Н' => 'н', 'О' => 'о', 'П' => 'п', 'Р' => 'р', 'С' => 'с', 'Т' => 'т', 'У' => 'у', 'Ф' => 'ф', 'Х' => 'х', 'Ц' => 'ц', 'Ч' => 'ч', 'Ш' => 'ш', 'Щ' => 'щ', 'Ъ' => 'ъ', 'Ы' => 'ы', 'Ь' => 'ь', 'Э' => 'э', 'Ю' => 'ю', 'Я' => 'я', 'Ѡ' => 'ѡ', 'Ѣ' => 'ѣ', 'Ѥ' => 'ѥ', 'Ѧ' => 'ѧ', 'Ѩ' => 'ѩ', 'Ѫ' => 'ѫ', 'Ѭ' => 'ѭ', 'Ѯ' => 'ѯ', 'Ѱ' => 'ѱ', 'Ѳ' => 'ѳ', 'Ѵ' => 'ѵ', 'Ѷ' => 'ѷ', 'Ѹ' => 'ѹ', 'Ѻ' => 'ѻ', 'Ѽ' => 'ѽ', 'Ѿ' => 'ѿ', 'Ҁ' => 'ҁ', 'Ҋ' => 'ҋ', 'Ҍ' => 'ҍ', 'Ҏ' => 'ҏ', 'Ґ' => 'ґ', 'Ғ' => 'ғ', 'Ҕ' => 'ҕ', 'Җ' => 'җ', 'Ҙ' => 'ҙ', 'Қ' => 'қ', 'Ҝ' => 'ҝ', 'Ҟ' => 'ҟ', 'Ҡ' => 'ҡ', 'Ң' => 'ң', 'Ҥ' => 'ҥ', 'Ҧ' => 'ҧ', 'Ҩ' => 'ҩ', 'Ҫ' => 'ҫ', 'Ҭ' => 'ҭ', 'Ү' => 'ү', 'Ұ' => 'ұ', 'Ҳ' => 'ҳ', 'Ҵ' => 'ҵ', 'Ҷ' => 'ҷ', 'Ҹ' => 'ҹ', 'Һ' => 'һ', 'Ҽ' => 'ҽ', 'Ҿ' => 'ҿ', 'Ӏ' => 'ӏ', 'Ӂ' => 'ӂ', 'Ӄ' => 'ӄ', 'Ӆ' => 'ӆ', 'Ӈ' => 'ӈ', 'Ӊ' => 'ӊ', 'Ӌ' => 'ӌ', 'Ӎ' => 'ӎ', 'Ӑ' => 'ӑ', 'Ӓ' => 'ӓ', 'Ӕ' => 'ӕ', 'Ӗ' => 'ӗ', 'Ә' => 'ә', 'Ӛ' => 'ӛ', 'Ӝ' => 'ӝ', 'Ӟ' => 'ӟ', 'Ӡ' => 'ӡ', 'Ӣ' => 'ӣ', 'Ӥ' => 'ӥ', 'Ӧ' => 'ӧ', 'Ө' => 'ө', 'Ӫ' => 'ӫ', 'Ӭ' => 'ӭ', 'Ӯ' => 'ӯ', 'Ӱ' => 'ӱ', 'Ӳ' => 'ӳ', 'Ӵ' => 'ӵ', 'Ӷ' => 'ӷ', 'Ӹ' => 'ӹ', 'Ӻ' => 'ӻ', 'Ӽ' => 'ӽ', 'Ӿ' => 'ӿ', 'Ԁ' => 'ԁ', 'Ԃ' => 'ԃ', 'Ԅ' => 'ԅ', 'Ԇ' => 'ԇ', 'Ԉ' => 'ԉ', 'Ԋ' => 'ԋ', 'Ԍ' => 'ԍ', 'Ԏ' => 'ԏ', 'Ԑ' => 'ԑ', 'Ԓ' => 'ԓ', 'Ԕ' => 'ԕ', 'Ԗ' => 'ԗ', 'Ԙ' => 'ԙ', 'Ԛ' => 'ԛ', 'Ԝ' => 'ԝ', 'Ԟ' => 'ԟ', 'Ԡ' => 'ԡ', 'Ԣ' => 'ԣ', 'Ԥ' => 'ԥ', 'Ԧ' => 'ԧ', 'Ԩ' => 'ԩ', 'Ԫ' => 'ԫ', 'Ԭ' => 'ԭ', 'Ԯ' => 'ԯ', 'Ա' => 'ա', 'Բ' => 'բ', 'Գ' => 'գ', 'Դ' => 'դ', 'Ե' => 'ե', 'Զ' => 'զ', 'Է' => 'է', 'Ը' => 'ը', 'Թ' => 'թ', 'Ժ' => 'ժ', 'Ի' => 'ի', 'Լ' => 'լ', 'Խ' => 'խ', 'Ծ' => 'ծ', 'Կ' => 'կ', 'Հ' => 'հ', 'Ձ' => 'ձ', 'Ղ' => 'ղ', 'Ճ' => 'ճ', 'Մ' => 'մ', 'Յ' => 'յ', 'Ն' => 'ն', 'Շ' => 'շ', 'Ո' => 'ո', 'Չ' => 'չ', 'Պ' => 'պ', 'Ջ' => 'ջ', 'Ռ' => 'ռ', 'Ս' => 'ս', 'Վ' => 'վ', 'Տ' => 'տ', 'Ր' => 'ր', 'Ց' => 'ց', 'Ւ' => 'ւ', 'Փ' => 'փ', 'Ք' => 'ք', 'Օ' => 'օ', 'Ֆ' => 'ֆ', 'Ⴀ' => 'ⴀ', 'Ⴁ' => 'ⴁ', 'Ⴂ' => 'ⴂ', 'Ⴃ' => 'ⴃ', 'Ⴄ' => 'ⴄ', 'Ⴅ' => 'ⴅ', 'Ⴆ' => 'ⴆ', 'Ⴇ' => 'ⴇ', 'Ⴈ' => 'ⴈ', 'Ⴉ' => 'ⴉ', 'Ⴊ' => 'ⴊ', 'Ⴋ' => 'ⴋ', 'Ⴌ' => 'ⴌ', 'Ⴍ' => 'ⴍ', 'Ⴎ' => 'ⴎ', 'Ⴏ' => 'ⴏ', 'Ⴐ' => 'ⴐ', 'Ⴑ' => 'ⴑ', 'Ⴒ' => 'ⴒ', 'Ⴓ' => 'ⴓ', 'Ⴔ' => 'ⴔ', 'Ⴕ' => 'ⴕ', 'Ⴖ' => 'ⴖ', 'Ⴗ' => 'ⴗ', 'Ⴘ' => 'ⴘ', 'Ⴙ' => 'ⴙ', 'Ⴚ' => 'ⴚ', 'Ⴛ' => 'ⴛ', 'Ⴜ' => 'ⴜ', 'Ⴝ' => 'ⴝ', 'Ⴞ' => 'ⴞ', 'Ⴟ' => 'ⴟ', 'Ⴠ' => 'ⴠ', 'Ⴡ' => 'ⴡ', 'Ⴢ' => 'ⴢ', 'Ⴣ' => 'ⴣ', 'Ⴤ' => 'ⴤ', 'Ⴥ' => 'ⴥ', 'Ⴧ' => 'ⴧ', 'Ⴭ' => 'ⴭ', 'Ꭰ' => 'ꭰ', 'Ꭱ' => 'ꭱ', 'Ꭲ' => 'ꭲ', 'Ꭳ' => 'ꭳ', 'Ꭴ' => 'ꭴ', 'Ꭵ' => 'ꭵ', 'Ꭶ' => 'ꭶ', 'Ꭷ' => 'ꭷ', 'Ꭸ' => 'ꭸ', 'Ꭹ' => 'ꭹ', 'Ꭺ' => 'ꭺ', 'Ꭻ' => 'ꭻ', 'Ꭼ' => 'ꭼ', 'Ꭽ' => 'ꭽ', 'Ꭾ' => 'ꭾ', 'Ꭿ' => 'ꭿ', 'Ꮀ' => 'ꮀ', 'Ꮁ' => 'ꮁ', 'Ꮂ' => 'ꮂ', 'Ꮃ' => 'ꮃ', 'Ꮄ' => 'ꮄ', 'Ꮅ' => 'ꮅ', 'Ꮆ' => 'ꮆ', 'Ꮇ' => 'ꮇ', 'Ꮈ' => 'ꮈ', 'Ꮉ' => 'ꮉ', 'Ꮊ' => 'ꮊ', 'Ꮋ' => 'ꮋ', 'Ꮌ' => 'ꮌ', 'Ꮍ' => 'ꮍ', 'Ꮎ' => 'ꮎ', 'Ꮏ' => 'ꮏ', 'Ꮐ' => 'ꮐ', 'Ꮑ' => 'ꮑ', 'Ꮒ' => 'ꮒ', 'Ꮓ' => 'ꮓ', 'Ꮔ' => 'ꮔ', 'Ꮕ' => 'ꮕ', 'Ꮖ' => 'ꮖ', 'Ꮗ' => 'ꮗ', 'Ꮘ' => 'ꮘ', 'Ꮙ' => 'ꮙ', 'Ꮚ' => 'ꮚ', 'Ꮛ' => 'ꮛ', 'Ꮜ' => 'ꮜ', 'Ꮝ' => 'ꮝ', 'Ꮞ' => 'ꮞ', 'Ꮟ' => 'ꮟ', 'Ꮠ' => 'ꮠ', 'Ꮡ' => 'ꮡ', 'Ꮢ' => 'ꮢ', 'Ꮣ' => 'ꮣ', 'Ꮤ' => 'ꮤ', 'Ꮥ' => 'ꮥ', 'Ꮦ' => 'ꮦ', 'Ꮧ' => 'ꮧ', 'Ꮨ' => 'ꮨ', 'Ꮩ' => 'ꮩ', 'Ꮪ' => 'ꮪ', 'Ꮫ' => 'ꮫ', 'Ꮬ' => 'ꮬ', 'Ꮭ' => 'ꮭ', 'Ꮮ' => 'ꮮ', 'Ꮯ' => 'ꮯ', 'Ꮰ' => 'ꮰ', 'Ꮱ' => 'ꮱ', 'Ꮲ' => 'ꮲ', 'Ꮳ' => 'ꮳ', 'Ꮴ' => 'ꮴ', 'Ꮵ' => 'ꮵ', 'Ꮶ' => 'ꮶ', 'Ꮷ' => 'ꮷ', 'Ꮸ' => 'ꮸ', 'Ꮹ' => 'ꮹ', 'Ꮺ' => 'ꮺ', 'Ꮻ' => 'ꮻ', 'Ꮼ' => 'ꮼ', 'Ꮽ' => 'ꮽ', 'Ꮾ' => 'ꮾ', 'Ꮿ' => 'ꮿ', 'Ᏸ' => 'ᏸ', 'Ᏹ' => 'ᏹ', 'Ᏺ' => 'ᏺ', 'Ᏻ' => 'ᏻ', 'Ᏼ' => 'ᏼ', 'Ᏽ' => 'ᏽ', 'Ა' => 'ა', 'Ბ' => 'ბ', 'Გ' => 'გ', 'Დ' => 'დ', 'Ე' => 'ე', 'Ვ' => 'ვ', 'Ზ' => 'ზ', 'Თ' => 'თ', 'Ი' => 'ი', 'Კ' => 'კ', 'Ლ' => 'ლ', 'Მ' => 'მ', 'Ნ' => 'ნ', 'Ო' => 'ო', 'Პ' => 'პ', 'Ჟ' => 'ჟ', 'Რ' => 'რ', 'Ს' => 'ს', 'Ტ' => 'ტ', 'Უ' => 'უ', 'Ფ' => 'ფ', 'Ქ' => 'ქ', 'Ღ' => 'ღ', 'Ყ' => 'ყ', 'Შ' => 'შ', 'Ჩ' => 'ჩ', 'Ც' => 'ც', 'Ძ' => 'ძ', 'Წ' => 'წ', 'Ჭ' => 'ჭ', 'Ხ' => 'ხ', 'Ჯ' => 'ჯ', 'Ჰ' => 'ჰ', 'Ჱ' => 'ჱ', 'Ჲ' => 'ჲ', 'Ჳ' => 'ჳ', 'Ჴ' => 'ჴ', 'Ჵ' => 'ჵ', 'Ჶ' => 'ჶ', 'Ჷ' => 'ჷ', 'Ჸ' => 'ჸ', 'Ჹ' => 'ჹ', 'Ჺ' => 'ჺ', 'Ჽ' => 'ჽ', 'Ჾ' => 'ჾ', 'Ჿ' => 'ჿ', 'Ḁ' => 'ḁ', 'Ḃ' => 'ḃ', 'Ḅ' => 'ḅ', 'Ḇ' => 'ḇ', 'Ḉ' => 'ḉ', 'Ḋ' => 'ḋ', 'Ḍ' => 'ḍ', 'Ḏ' => 'ḏ', 'Ḑ' => 'ḑ', 'Ḓ' => 'ḓ', 'Ḕ' => 'ḕ', 'Ḗ' => 'ḗ', 'Ḙ' => 'ḙ', 'Ḛ' => 'ḛ', 'Ḝ' => 'ḝ', 'Ḟ' => 'ḟ', 'Ḡ' => 'ḡ', 'Ḣ' => 'ḣ', 'Ḥ' => 'ḥ', 'Ḧ' => 'ḧ', 'Ḩ' => 'ḩ', 'Ḫ' => 'ḫ', 'Ḭ' => 'ḭ', 'Ḯ' => 'ḯ', 'Ḱ' => 'ḱ', 'Ḳ' => 'ḳ', 'Ḵ' => 'ḵ', 'Ḷ' => 'ḷ', 'Ḹ' => 'ḹ', 'Ḻ' => 'ḻ', 'Ḽ' => 'ḽ', 'Ḿ' => 'ḿ', 'Ṁ' => 'ṁ', 'Ṃ' => 'ṃ', 'Ṅ' => 'ṅ', 'Ṇ' => 'ṇ', 'Ṉ' => 'ṉ', 'Ṋ' => 'ṋ', 'Ṍ' => 'ṍ', 'Ṏ' => 'ṏ', 'Ṑ' => 'ṑ', 'Ṓ' => 'ṓ', 'Ṕ' => 'ṕ', 'Ṗ' => 'ṗ', 'Ṙ' => 'ṙ', 'Ṛ' => 'ṛ', 'Ṝ' => 'ṝ', 'Ṟ' => 'ṟ', 'Ṡ' => 'ṡ', 'Ṣ' => 'ṣ', 'Ṥ' => 'ṥ', 'Ṧ' => 'ṧ', 'Ṩ' => 'ṩ', 'Ṫ' => 'ṫ', 'Ṭ' => 'ṭ', 'Ṯ' => 'ṯ', 'Ṱ' => 'ṱ', 'Ṳ' => 'ṳ', 'Ṵ' => 'ṵ', 'Ṷ' => 'ṷ', 'Ṹ' => 'ṹ', 'Ṻ' => 'ṻ', 'Ṽ' => 'ṽ', 'Ṿ' => 'ṿ', 'Ẁ' => 'ẁ', 'Ẃ' => 'ẃ', 'Ẅ' => 'ẅ', 'Ẇ' => 'ẇ', 'Ẉ' => 'ẉ', 'Ẋ' => 'ẋ', 'Ẍ' => 'ẍ', 'Ẏ' => 'ẏ', 'Ẑ' => 'ẑ', 'Ẓ' => 'ẓ', 'Ẕ' => 'ẕ', 'ẞ' => 'ß', 'Ạ' => 'ạ', 'Ả' => 'ả', 'Ấ' => 'ấ', 'Ầ' => 'ầ', 'Ẩ' => 'ẩ', 'Ẫ' => 'ẫ', 'Ậ' => 'ậ', 'Ắ' => 'ắ', 'Ằ' => 'ằ', 'Ẳ' => 'ẳ', 'Ẵ' => 'ẵ', 'Ặ' => 'ặ', 'Ẹ' => 'ẹ', 'Ẻ' => 'ẻ', 'Ẽ' => 'ẽ', 'Ế' => 'ế', 'Ề' => 'ề', 'Ể' => 'ể', 'Ễ' => 'ễ', 'Ệ' => 'ệ', 'Ỉ' => 'ỉ', 'Ị' => 'ị', 'Ọ' => 'ọ', 'Ỏ' => 'ỏ', 'Ố' => 'ố', 'Ồ' => 'ồ', 'Ổ' => 'ổ', 'Ỗ' => 'ỗ', 'Ộ' => 'ộ', 'Ớ' => 'ớ', 'Ờ' => 'ờ', 'Ở' => 'ở', 'Ỡ' => 'ỡ', 'Ợ' => 'ợ', 'Ụ' => 'ụ', 'Ủ' => 'ủ', 'Ứ' => 'ứ', 'Ừ' => 'ừ', 'Ử' => 'ử', 'Ữ' => 'ữ', 'Ự' => 'ự', 'Ỳ' => 'ỳ', 'Ỵ' => 'ỵ', 'Ỷ' => 'ỷ', 'Ỹ' => 'ỹ', 'Ỻ' => 'ỻ', 'Ỽ' => 'ỽ', 'Ỿ' => 'ỿ', 'Ἀ' => 'ἀ', 'Ἁ' => 'ἁ', 'Ἂ' => 'ἂ', 'Ἃ' => 'ἃ', 'Ἄ' => 'ἄ', 'Ἅ' => 'ἅ', 'Ἆ' => 'ἆ', 'Ἇ' => 'ἇ', 'Ἐ' => 'ἐ', 'Ἑ' => 'ἑ', 'Ἒ' => 'ἒ', 'Ἓ' => 'ἓ', 'Ἔ' => 'ἔ', 'Ἕ' => 'ἕ', 'Ἠ' => 'ἠ', 'Ἡ' => 'ἡ', 'Ἢ' => 'ἢ', 'Ἣ' => 'ἣ', 'Ἤ' => 'ἤ', 'Ἥ' => 'ἥ', 'Ἦ' => 'ἦ', 'Ἧ' => 'ἧ', 'Ἰ' => 'ἰ', 'Ἱ' => 'ἱ', 'Ἲ' => 'ἲ', 'Ἳ' => 'ἳ', 'Ἴ' => 'ἴ', 'Ἵ' => 'ἵ', 'Ἶ' => 'ἶ', 'Ἷ' => 'ἷ', 'Ὀ' => 'ὀ', 'Ὁ' => 'ὁ', 'Ὂ' => 'ὂ', 'Ὃ' => 'ὃ', 'Ὄ' => 'ὄ', 'Ὅ' => 'ὅ', 'Ὑ' => 'ὑ', 'Ὓ' => 'ὓ', 'Ὕ' => 'ὕ', 'Ὗ' => 'ὗ', 'Ὠ' => 'ὠ', 'Ὡ' => 'ὡ', 'Ὢ' => 'ὢ', 'Ὣ' => 'ὣ', 'Ὤ' => 'ὤ', 'Ὥ' => 'ὥ', 'Ὦ' => 'ὦ', 'Ὧ' => 'ὧ', 'ᾈ' => 'ᾀ', 'ᾉ' => 'ᾁ', 'ᾊ' => 'ᾂ', 'ᾋ' => 'ᾃ', 'ᾌ' => 'ᾄ', 'ᾍ' => 'ᾅ', 'ᾎ' => 'ᾆ', 'ᾏ' => 'ᾇ', 'ᾘ' => 'ᾐ', 'ᾙ' => 'ᾑ', 'ᾚ' => 'ᾒ', 'ᾛ' => 'ᾓ', 'ᾜ' => 'ᾔ', 'ᾝ' => 'ᾕ', 'ᾞ' => 'ᾖ', 'ᾟ' => 'ᾗ', 'ᾨ' => 'ᾠ', 'ᾩ' => 'ᾡ', 'ᾪ' => 'ᾢ', 'ᾫ' => 'ᾣ', 'ᾬ' => 'ᾤ', 'ᾭ' => 'ᾥ', 'ᾮ' => 'ᾦ', 'ᾯ' => 'ᾧ', 'Ᾰ' => 'ᾰ', 'Ᾱ' => 'ᾱ', 'Ὰ' => 'ὰ', 'Ά' => 'ά', 'ᾼ' => 'ᾳ', 'Ὲ' => 'ὲ', 'Έ' => 'έ', 'Ὴ' => 'ὴ', 'Ή' => 'ή', 'ῌ' => 'ῃ', 'Ῐ' => 'ῐ', 'Ῑ' => 'ῑ', 'Ὶ' => 'ὶ', 'Ί' => 'ί', 'Ῠ' => 'ῠ', 'Ῡ' => 'ῡ', 'Ὺ' => 'ὺ', 'Ύ' => 'ύ', 'Ῥ' => 'ῥ', 'Ὸ' => 'ὸ', 'Ό' => 'ό', 'Ὼ' => 'ὼ', 'Ώ' => 'ώ', 'ῼ' => 'ῳ', 'Ω' => 'ω', 'K' => 'k', 'Å' => 'å', 'Ⅎ' => 'ⅎ', 'Ⅰ' => 'ⅰ', 'Ⅱ' => 'ⅱ', 'Ⅲ' => 'ⅲ', 'Ⅳ' => 'ⅳ', 'Ⅴ' => 'ⅴ', 'Ⅵ' => 'ⅵ', 'Ⅶ' => 'ⅶ', 'Ⅷ' => 'ⅷ', 'Ⅸ' => 'ⅸ', 'Ⅹ' => 'ⅹ', 'Ⅺ' => 'ⅺ', 'Ⅻ' => 'ⅻ', 'Ⅼ' => 'ⅼ', 'Ⅽ' => 'ⅽ', 'Ⅾ' => 'ⅾ', 'Ⅿ' => 'ⅿ', 'Ↄ' => 'ↄ', 'Ⓐ' => 'ⓐ', 'Ⓑ' => 'ⓑ', 'Ⓒ' => 'ⓒ', 'Ⓓ' => 'ⓓ', 'Ⓔ' => 'ⓔ', 'Ⓕ' => 'ⓕ', 'Ⓖ' => 'ⓖ', 'Ⓗ' => 'ⓗ', 'Ⓘ' => 'ⓘ', 'Ⓙ' => 'ⓙ', 'Ⓚ' => 'ⓚ', 'Ⓛ' => 'ⓛ', 'Ⓜ' => 'ⓜ', 'Ⓝ' => 'ⓝ', 'Ⓞ' => 'ⓞ', 'Ⓟ' => 'ⓟ', 'Ⓠ' => 'ⓠ', 'Ⓡ' => 'ⓡ', 'Ⓢ' => 'ⓢ', 'Ⓣ' => 'ⓣ', 'Ⓤ' => 'ⓤ', 'Ⓥ' => 'ⓥ', 'Ⓦ' => 'ⓦ', 'Ⓧ' => 'ⓧ', 'Ⓨ' => 'ⓨ', 'Ⓩ' => 'ⓩ', 'Ⰰ' => 'ⰰ', 'Ⰱ' => 'ⰱ', 'Ⰲ' => 'ⰲ', 'Ⰳ' => 'ⰳ', 'Ⰴ' => 'ⰴ', 'Ⰵ' => 'ⰵ', 'Ⰶ' => 'ⰶ', 'Ⰷ' => 'ⰷ', 'Ⰸ' => 'ⰸ', 'Ⰹ' => 'ⰹ', 'Ⰺ' => 'ⰺ', 'Ⰻ' => 'ⰻ', 'Ⰼ' => 'ⰼ', 'Ⰽ' => 'ⰽ', 'Ⰾ' => 'ⰾ', 'Ⰿ' => 'ⰿ', 'Ⱀ' => 'ⱀ', 'Ⱁ' => 'ⱁ', 'Ⱂ' => 'ⱂ', 'Ⱃ' => 'ⱃ', 'Ⱄ' => 'ⱄ', 'Ⱅ' => 'ⱅ', 'Ⱆ' => 'ⱆ', 'Ⱇ' => 'ⱇ', 'Ⱈ' => 'ⱈ', 'Ⱉ' => 'ⱉ', 'Ⱊ' => 'ⱊ', 'Ⱋ' => 'ⱋ', 'Ⱌ' => 'ⱌ', 'Ⱍ' => 'ⱍ', 'Ⱎ' => 'ⱎ', 'Ⱏ' => 'ⱏ', 'Ⱐ' => 'ⱐ', 'Ⱑ' => 'ⱑ', 'Ⱒ' => 'ⱒ', 'Ⱓ' => 'ⱓ', 'Ⱔ' => 'ⱔ', 'Ⱕ' => 'ⱕ', 'Ⱖ' => 'ⱖ', 'Ⱗ' => 'ⱗ', 'Ⱘ' => 'ⱘ', 'Ⱙ' => 'ⱙ', 'Ⱚ' => 'ⱚ', 'Ⱛ' => 'ⱛ', 'Ⱜ' => 'ⱜ', 'Ⱝ' => 'ⱝ', 'Ⱞ' => 'ⱞ', 'Ⱡ' => 'ⱡ', 'Ɫ' => 'ɫ', 'Ᵽ' => 'ᵽ', 'Ɽ' => 'ɽ', 'Ⱨ' => 'ⱨ', 'Ⱪ' => 'ⱪ', 'Ⱬ' => 'ⱬ', 'Ɑ' => 'ɑ', 'Ɱ' => 'ɱ', 'Ɐ' => 'ɐ', 'Ɒ' => 'ɒ', 'Ⱳ' => 'ⱳ', 'Ⱶ' => 'ⱶ', 'Ȿ' => 'ȿ', 'Ɀ' => 'ɀ', 'Ⲁ' => 'ⲁ', 'Ⲃ' => 'ⲃ', 'Ⲅ' => 'ⲅ', 'Ⲇ' => 'ⲇ', 'Ⲉ' => 'ⲉ', 'Ⲋ' => 'ⲋ', 'Ⲍ' => 'ⲍ', 'Ⲏ' => 'ⲏ', 'Ⲑ' => 'ⲑ', 'Ⲓ' => 'ⲓ', 'Ⲕ' => 'ⲕ', 'Ⲗ' => 'ⲗ', 'Ⲙ' => 'ⲙ', 'Ⲛ' => 'ⲛ', 'Ⲝ' => 'ⲝ', 'Ⲟ' => 'ⲟ', 'Ⲡ' => 'ⲡ', 'Ⲣ' => 'ⲣ', 'Ⲥ' => 'ⲥ', 'Ⲧ' => 'ⲧ', 'Ⲩ' => 'ⲩ', 'Ⲫ' => 'ⲫ', 'Ⲭ' => 'ⲭ', 'Ⲯ' => 'ⲯ', 'Ⲱ' => 'ⲱ', 'Ⲳ' => 'ⲳ', 'Ⲵ' => 'ⲵ', 'Ⲷ' => 'ⲷ', 'Ⲹ' => 'ⲹ', 'Ⲻ' => 'ⲻ', 'Ⲽ' => 'ⲽ', 'Ⲿ' => 'ⲿ', 'Ⳁ' => 'ⳁ', 'Ⳃ' => 'ⳃ', 'Ⳅ' => 'ⳅ', 'Ⳇ' => 'ⳇ', 'Ⳉ' => 'ⳉ', 'Ⳋ' => 'ⳋ', 'Ⳍ' => 'ⳍ', 'Ⳏ' => 'ⳏ', 'Ⳑ' => 'ⳑ', 'Ⳓ' => 'ⳓ', 'Ⳕ' => 'ⳕ', 'Ⳗ' => 'ⳗ', 'Ⳙ' => 'ⳙ', 'Ⳛ' => 'ⳛ', 'Ⳝ' => 'ⳝ', 'Ⳟ' => 'ⳟ', 'Ⳡ' => 'ⳡ', 'Ⳣ' => 'ⳣ', 'Ⳬ' => 'ⳬ', 'Ⳮ' => 'ⳮ', 'Ⳳ' => 'ⳳ', 'Ꙁ' => 'ꙁ', 'Ꙃ' => 'ꙃ', 'Ꙅ' => 'ꙅ', 'Ꙇ' => 'ꙇ', 'Ꙉ' => 'ꙉ', 'Ꙋ' => 'ꙋ', 'Ꙍ' => 'ꙍ', 'Ꙏ' => 'ꙏ', 'Ꙑ' => 'ꙑ', 'Ꙓ' => 'ꙓ', 'Ꙕ' => 'ꙕ', 'Ꙗ' => 'ꙗ', 'Ꙙ' => 'ꙙ', 'Ꙛ' => 'ꙛ', 'Ꙝ' => 'ꙝ', 'Ꙟ' => 'ꙟ', 'Ꙡ' => 'ꙡ', 'Ꙣ' => 'ꙣ', 'Ꙥ' => 'ꙥ', 'Ꙧ' => 'ꙧ', 'Ꙩ' => 'ꙩ', 'Ꙫ' => 'ꙫ', 'Ꙭ' => 'ꙭ', 'Ꚁ' => 'ꚁ', 'Ꚃ' => 'ꚃ', 'Ꚅ' => 'ꚅ', 'Ꚇ' => 'ꚇ', 'Ꚉ' => 'ꚉ', 'Ꚋ' => 'ꚋ', 'Ꚍ' => 'ꚍ', 'Ꚏ' => 'ꚏ', 'Ꚑ' => 'ꚑ', 'Ꚓ' => 'ꚓ', 'Ꚕ' => 'ꚕ', 'Ꚗ' => 'ꚗ', 'Ꚙ' => 'ꚙ', 'Ꚛ' => 'ꚛ', 'Ꜣ' => 'ꜣ', 'Ꜥ' => 'ꜥ', 'Ꜧ' => 'ꜧ', 'Ꜩ' => 'ꜩ', 'Ꜫ' => 'ꜫ', 'Ꜭ' => 'ꜭ', 'Ꜯ' => 'ꜯ', 'Ꜳ' => 'ꜳ', 'Ꜵ' => 'ꜵ', 'Ꜷ' => 'ꜷ', 'Ꜹ' => 'ꜹ', 'Ꜻ' => 'ꜻ', 'Ꜽ' => 'ꜽ', 'Ꜿ' => 'ꜿ', 'Ꝁ' => 'ꝁ', 'Ꝃ' => 'ꝃ', 'Ꝅ' => 'ꝅ', 'Ꝇ' => 'ꝇ', 'Ꝉ' => 'ꝉ', 'Ꝋ' => 'ꝋ', 'Ꝍ' => 'ꝍ', 'Ꝏ' => 'ꝏ', 'Ꝑ' => 'ꝑ', 'Ꝓ' => 'ꝓ', 'Ꝕ' => 'ꝕ', 'Ꝗ' => 'ꝗ', 'Ꝙ' => 'ꝙ', 'Ꝛ' => 'ꝛ', 'Ꝝ' => 'ꝝ', 'Ꝟ' => 'ꝟ', 'Ꝡ' => 'ꝡ', 'Ꝣ' => 'ꝣ', 'Ꝥ' => 'ꝥ', 'Ꝧ' => 'ꝧ', 'Ꝩ' => 'ꝩ', 'Ꝫ' => 'ꝫ', 'Ꝭ' => 'ꝭ', 'Ꝯ' => 'ꝯ', 'Ꝺ' => 'ꝺ', 'Ꝼ' => 'ꝼ', 'Ᵹ' => 'ᵹ', 'Ꝿ' => 'ꝿ', 'Ꞁ' => 'ꞁ', 'Ꞃ' => 'ꞃ', 'Ꞅ' => 'ꞅ', 'Ꞇ' => 'ꞇ', 'Ꞌ' => 'ꞌ', 'Ɥ' => 'ɥ', 'Ꞑ' => 'ꞑ', 'Ꞓ' => 'ꞓ', 'Ꞗ' => 'ꞗ', 'Ꞙ' => 'ꞙ', 'Ꞛ' => 'ꞛ', 'Ꞝ' => 'ꞝ', 'Ꞟ' => 'ꞟ', 'Ꞡ' => 'ꞡ', 'Ꞣ' => 'ꞣ', 'Ꞥ' => 'ꞥ', 'Ꞧ' => 'ꞧ', 'Ꞩ' => 'ꞩ', 'Ɦ' => 'ɦ', 'Ɜ' => 'ɜ', 'Ɡ' => 'ɡ', 'Ɬ' => 'ɬ', 'Ɪ' => 'ɪ', 'Ʞ' => 'ʞ', 'Ʇ' => 'ʇ', 'Ʝ' => 'ʝ', 'Ꭓ' => 'ꭓ', 'Ꞵ' => 'ꞵ', 'Ꞷ' => 'ꞷ', 'Ꞹ' => 'ꞹ', 'Ꞻ' => 'ꞻ', 'Ꞽ' => 'ꞽ', 'Ꞿ' => 'ꞿ', 'Ꟃ' => 'ꟃ', 'Ꞔ' => 'ꞔ', 'Ʂ' => 'ʂ', 'Ᶎ' => 'ᶎ', 'Ꟈ' => 'ꟈ', 'Ꟊ' => 'ꟊ', 'Ꟶ' => 'ꟶ', 'Ａ' => 'ａ', 'Ｂ' => 'ｂ', 'Ｃ' => 'ｃ', 'Ｄ' => 'ｄ', 'Ｅ' => 'ｅ', 'Ｆ' => 'ｆ', 'Ｇ' => 'ｇ', 'Ｈ' => 'ｈ', 'Ｉ' => 'ｉ', 'Ｊ' => 'ｊ', 'Ｋ' => 'ｋ', 'Ｌ' => 'ｌ', 'Ｍ' => 'ｍ', 'Ｎ' => 'ｎ', 'Ｏ' => 'ｏ', 'Ｐ' => 'ｐ', 'Ｑ' => 'ｑ', 'Ｒ' => 'ｒ', 'Ｓ' => 'ｓ', 'Ｔ' => 'ｔ', 'Ｕ' => 'ｕ', 'Ｖ' => 'ｖ', 'Ｗ' => 'ｗ', 'Ｘ' => 'ｘ', 'Ｙ' => 'ｙ', 'Ｚ' => 'ｚ', '𐐀' => '𐐨', '𐐁' => '𐐩', '𐐂' => '𐐪', '𐐃' => '𐐫', '𐐄' => '𐐬', '𐐅' => '𐐭', '𐐆' => '𐐮', '𐐇' => '𐐯', '𐐈' => '𐐰', '𐐉' => '𐐱', '𐐊' => '𐐲', '𐐋' => '𐐳', '𐐌' => '𐐴', '𐐍' => '𐐵', '𐐎' => '𐐶', '𐐏' => '𐐷', '𐐐' => '𐐸', '𐐑' => '𐐹', '𐐒' => '𐐺', '𐐓' => '𐐻', '𐐔' => '𐐼', '𐐕' => '𐐽', '𐐖' => '𐐾', '𐐗' => '𐐿', '𐐘' => '𐑀', '𐐙' => '𐑁', '𐐚' => '𐑂', '𐐛' => '𐑃', '𐐜' => '𐑄', '𐐝' => '𐑅', '𐐞' => '𐑆', '𐐟' => '𐑇', '𐐠' => '𐑈', '𐐡' => '𐑉', '𐐢' => '𐑊', '𐐣' => '𐑋', '𐐤' => '𐑌', '𐐥' => '𐑍', '𐐦' => '𐑎', '𐐧' => '𐑏', '𐒰' => '𐓘', '𐒱' => '𐓙', '𐒲' => '𐓚', '𐒳' => '𐓛', '𐒴' => '𐓜', '𐒵' => '𐓝', '𐒶' => '𐓞', '𐒷' => '𐓟', '𐒸' => '𐓠', '𐒹' => '𐓡', '𐒺' => '𐓢', '𐒻' => '𐓣', '𐒼' => '𐓤', '𐒽' => '𐓥', '𐒾' => '𐓦', '𐒿' => '𐓧', '𐓀' => '𐓨', '𐓁' => '𐓩', '𐓂' => '𐓪', '𐓃' => '𐓫', '𐓄' => '𐓬', '𐓅' => '𐓭', '𐓆' => '𐓮', '𐓇' => '𐓯', '𐓈' => '𐓰', '𐓉' => '𐓱', '𐓊' => '𐓲', '𐓋' => '𐓳', '𐓌' => '𐓴', '𐓍' => '𐓵', '𐓎' => '𐓶', '𐓏' => '𐓷', '𐓐' => '𐓸', '𐓑' => '𐓹', '𐓒' => '𐓺', '𐓓' => '𐓻', '𐲀' => '𐳀', '𐲁' => '𐳁', '𐲂' => '𐳂', '𐲃' => '𐳃', '𐲄' => '𐳄', '𐲅' => '𐳅', '𐲆' => '𐳆', '𐲇' => '𐳇', '𐲈' => '𐳈', '𐲉' => '𐳉', '𐲊' => '𐳊', '𐲋' => '𐳋', '𐲌' => '𐳌', '𐲍' => '𐳍', '𐲎' => '𐳎', '𐲏' => '𐳏', '𐲐' => '𐳐', '𐲑' => '𐳑', '𐲒' => '𐳒', '𐲓' => '𐳓', '𐲔' => '𐳔', '𐲕' => '𐳕', '𐲖' => '𐳖', '𐲗' => '𐳗', '𐲘' => '𐳘', '𐲙' => '𐳙', '𐲚' => '𐳚', '𐲛' => '𐳛', '𐲜' => '𐳜', '𐲝' => '𐳝', '𐲞' => '𐳞', '𐲟' => '𐳟', '𐲠' => '𐳠', '𐲡' => '𐳡', '𐲢' => '𐳢', '𐲣' => '𐳣', '𐲤' => '𐳤', '𐲥' => '𐳥', '𐲦' => '𐳦', '𐲧' => '𐳧', '𐲨' => '𐳨', '𐲩' => '𐳩', '𐲪' => '𐳪', '𐲫' => '𐳫', '𐲬' => '𐳬', '𐲭' => '𐳭', '𐲮' => '𐳮', '𐲯' => '𐳯', '𐲰' => '𐳰', '𐲱' => '𐳱', '𐲲' => '𐳲', '𑢠' => '𑣀', '𑢡' => '𑣁', '𑢢' => '𑣂', '𑢣' => '𑣃', '𑢤' => '𑣄', '𑢥' => '𑣅', '𑢦' => '𑣆', '𑢧' => '𑣇', '𑢨' => '𑣈', '𑢩' => '𑣉', '𑢪' => '𑣊', '𑢫' => '𑣋', '𑢬' => '𑣌', '𑢭' => '𑣍', '𑢮' => '𑣎', '𑢯' => '𑣏', '𑢰' => '𑣐', '𑢱' => '𑣑', '𑢲' => '𑣒', '𑢳' => '𑣓', '𑢴' => '𑣔', '𑢵' => '𑣕', '𑢶' => '𑣖', '𑢷' => '𑣗', '𑢸' => '𑣘', '𑢹' => '𑣙', '𑢺' => '𑣚', '𑢻' => '𑣛', '𑢼' => '𑣜', '𑢽' => '𑣝', '𑢾' => '𑣞', '𑢿' => '𑣟', '𖹀' => '𖹠', '𖹁' => '𖹡', '𖹂' => '𖹢', '𖹃' => '𖹣', '𖹄' => '𖹤', '𖹅' => '𖹥', '𖹆' => '𖹦', '𖹇' => '𖹧', '𖹈' => '𖹨', '𖹉' => '𖹩', '𖹊' => '𖹪', '𖹋' => '𖹫', '𖹌' => '𖹬', '𖹍' => '𖹭', '𖹎' => '𖹮', '𖹏' => '𖹯', '𖹐' => '𖹰', '𖹑' => '𖹱', '𖹒' => '𖹲', '𖹓' => '𖹳', '𖹔' => '𖹴', '𖹕' => '𖹵', '𖹖' => '𖹶', '𖹗' => '𖹷', '𖹘' => '𖹸', '𖹙' => '𖹹', '𖹚' => '𖹺', '𖹛' => '𖹻', '𖹜' => '𖹼', '𖹝' => '𖹽', '𖹞' => '𖹾', '𖹟' => '𖹿', '𞤀' => '𞤢', '𞤁' => '𞤣', '𞤂' => '𞤤', '𞤃' => '𞤥', '𞤄' => '𞤦', '𞤅' => '𞤧', '𞤆' => '𞤨', '𞤇' => '𞤩', '𞤈' => '𞤪', '𞤉' => '𞤫', '𞤊' => '𞤬', '𞤋' => '𞤭', '𞤌' => '𞤮', '𞤍' => '𞤯', '𞤎' => '𞤰', '𞤏' => '𞤱', '𞤐' => '𞤲', '𞤑' => '𞤳', '𞤒' => '𞤴', '𞤓' => '𞤵', '𞤔' => '𞤶', '𞤕' => '𞤷', '𞤖' => '𞤸', '𞤗' => '𞤹', '𞤘' => '𞤺', '𞤙' => '𞤻', '𞤚' => '𞤼', '𞤛' => '𞤽', '𞤜' => '𞤾', '𞤝' => '𞤿', '𞤞' => '𞥀', '𞤟' => '𞥁', '𞤠' => '𞥂', '𞤡' => '𞥃');
<?php

namespace _ContaoManager;

// from Case_Ignorable in https://unicode.org/Public/UNIDATA/DerivedCoreProperties.txt
return '/(?<![\x{0027}\x{002E}\x{003A}\x{005E}\x{0060}\x{00A8}\x{00AD}\x{00AF}\x{00B4}\x{00B7}\x{00B8}\x{02B0}-\x{02C1}\x{02C2}-\x{02C5}\x{02C6}-\x{02D1}\x{02D2}-\x{02DF}\x{02E0}-\x{02E4}\x{02E5}-\x{02EB}\x{02EC}\x{02ED}\x{02EE}\x{02EF}-\x{02FF}\x{0300}-\x{036F}\x{0374}\x{0375}\x{037A}\x{0384}-\x{0385}\x{0387}\x{0483}-\x{0487}\x{0488}-\x{0489}\x{0559}\x{0591}-\x{05BD}\x{05BF}\x{05C1}-\x{05C2}\x{05C4}-\x{05C5}\x{05C7}\x{05F4}\x{0600}-\x{0605}\x{0610}-\x{061A}\x{061C}\x{0640}\x{064B}-\x{065F}\x{0670}\x{06D6}-\x{06DC}\x{06DD}\x{06DF}-\x{06E4}\x{06E5}-\x{06E6}\x{06E7}-\x{06E8}\x{06EA}-\x{06ED}\x{070F}\x{0711}\x{0730}-\x{074A}\x{07A6}-\x{07B0}\x{07EB}-\x{07F3}\x{07F4}-\x{07F5}\x{07FA}\x{07FD}\x{0816}-\x{0819}\x{081A}\x{081B}-\x{0823}\x{0824}\x{0825}-\x{0827}\x{0828}\x{0829}-\x{082D}\x{0859}-\x{085B}\x{08D3}-\x{08E1}\x{08E2}\x{08E3}-\x{0902}\x{093A}\x{093C}\x{0941}-\x{0948}\x{094D}\x{0951}-\x{0957}\x{0962}-\x{0963}\x{0971}\x{0981}\x{09BC}\x{09C1}-\x{09C4}\x{09CD}\x{09E2}-\x{09E3}\x{09FE}\x{0A01}-\x{0A02}\x{0A3C}\x{0A41}-\x{0A42}\x{0A47}-\x{0A48}\x{0A4B}-\x{0A4D}\x{0A51}\x{0A70}-\x{0A71}\x{0A75}\x{0A81}-\x{0A82}\x{0ABC}\x{0AC1}-\x{0AC5}\x{0AC7}-\x{0AC8}\x{0ACD}\x{0AE2}-\x{0AE3}\x{0AFA}-\x{0AFF}\x{0B01}\x{0B3C}\x{0B3F}\x{0B41}-\x{0B44}\x{0B4D}\x{0B56}\x{0B62}-\x{0B63}\x{0B82}\x{0BC0}\x{0BCD}\x{0C00}\x{0C04}\x{0C3E}-\x{0C40}\x{0C46}-\x{0C48}\x{0C4A}-\x{0C4D}\x{0C55}-\x{0C56}\x{0C62}-\x{0C63}\x{0C81}\x{0CBC}\x{0CBF}\x{0CC6}\x{0CCC}-\x{0CCD}\x{0CE2}-\x{0CE3}\x{0D00}-\x{0D01}\x{0D3B}-\x{0D3C}\x{0D41}-\x{0D44}\x{0D4D}\x{0D62}-\x{0D63}\x{0DCA}\x{0DD2}-\x{0DD4}\x{0DD6}\x{0E31}\x{0E34}-\x{0E3A}\x{0E46}\x{0E47}-\x{0E4E}\x{0EB1}\x{0EB4}-\x{0EB9}\x{0EBB}-\x{0EBC}\x{0EC6}\x{0EC8}-\x{0ECD}\x{0F18}-\x{0F19}\x{0F35}\x{0F37}\x{0F39}\x{0F71}-\x{0F7E}\x{0F80}-\x{0F84}\x{0F86}-\x{0F87}\x{0F8D}-\x{0F97}\x{0F99}-\x{0FBC}\x{0FC6}\x{102D}-\x{1030}\x{1032}-\x{1037}\x{1039}-\x{103A}\x{103D}-\x{103E}\x{1058}-\x{1059}\x{105E}-\x{1060}\x{1071}-\x{1074}\x{1082}\x{1085}-\x{1086}\x{108D}\x{109D}\x{10FC}\x{135D}-\x{135F}\x{1712}-\x{1714}\x{1732}-\x{1734}\x{1752}-\x{1753}\x{1772}-\x{1773}\x{17B4}-\x{17B5}\x{17B7}-\x{17BD}\x{17C6}\x{17C9}-\x{17D3}\x{17D7}\x{17DD}\x{180B}-\x{180D}\x{180E}\x{1843}\x{1885}-\x{1886}\x{18A9}\x{1920}-\x{1922}\x{1927}-\x{1928}\x{1932}\x{1939}-\x{193B}\x{1A17}-\x{1A18}\x{1A1B}\x{1A56}\x{1A58}-\x{1A5E}\x{1A60}\x{1A62}\x{1A65}-\x{1A6C}\x{1A73}-\x{1A7C}\x{1A7F}\x{1AA7}\x{1AB0}-\x{1ABD}\x{1ABE}\x{1B00}-\x{1B03}\x{1B34}\x{1B36}-\x{1B3A}\x{1B3C}\x{1B42}\x{1B6B}-\x{1B73}\x{1B80}-\x{1B81}\x{1BA2}-\x{1BA5}\x{1BA8}-\x{1BA9}\x{1BAB}-\x{1BAD}\x{1BE6}\x{1BE8}-\x{1BE9}\x{1BED}\x{1BEF}-\x{1BF1}\x{1C2C}-\x{1C33}\x{1C36}-\x{1C37}\x{1C78}-\x{1C7D}\x{1CD0}-\x{1CD2}\x{1CD4}-\x{1CE0}\x{1CE2}-\x{1CE8}\x{1CED}\x{1CF4}\x{1CF8}-\x{1CF9}\x{1D2C}-\x{1D6A}\x{1D78}\x{1D9B}-\x{1DBF}\x{1DC0}-\x{1DF9}\x{1DFB}-\x{1DFF}\x{1FBD}\x{1FBF}-\x{1FC1}\x{1FCD}-\x{1FCF}\x{1FDD}-\x{1FDF}\x{1FED}-\x{1FEF}\x{1FFD}-\x{1FFE}\x{200B}-\x{200F}\x{2018}\x{2019}\x{2024}\x{2027}\x{202A}-\x{202E}\x{2060}-\x{2064}\x{2066}-\x{206F}\x{2071}\x{207F}\x{2090}-\x{209C}\x{20D0}-\x{20DC}\x{20DD}-\x{20E0}\x{20E1}\x{20E2}-\x{20E4}\x{20E5}-\x{20F0}\x{2C7C}-\x{2C7D}\x{2CEF}-\x{2CF1}\x{2D6F}\x{2D7F}\x{2DE0}-\x{2DFF}\x{2E2F}\x{3005}\x{302A}-\x{302D}\x{3031}-\x{3035}\x{303B}\x{3099}-\x{309A}\x{309B}-\x{309C}\x{309D}-\x{309E}\x{30FC}-\x{30FE}\x{A015}\x{A4F8}-\x{A4FD}\x{A60C}\x{A66F}\x{A670}-\x{A672}\x{A674}-\x{A67D}\x{A67F}\x{A69C}-\x{A69D}\x{A69E}-\x{A69F}\x{A6F0}-\x{A6F1}\x{A700}-\x{A716}\x{A717}-\x{A71F}\x{A720}-\x{A721}\x{A770}\x{A788}\x{A789}-\x{A78A}\x{A7F8}-\x{A7F9}\x{A802}\x{A806}\x{A80B}\x{A825}-\x{A826}\x{A8C4}-\x{A8C5}\x{A8E0}-\x{A8F1}\x{A8FF}\x{A926}-\x{A92D}\x{A947}-\x{A951}\x{A980}-\x{A982}\x{A9B3}\x{A9B6}-\x{A9B9}\x{A9BC}\x{A9CF}\x{A9E5}\x{A9E6}\x{AA29}-\x{AA2E}\x{AA31}-\x{AA32}\x{AA35}-\x{AA36}\x{AA43}\x{AA4C}\x{AA70}\x{AA7C}\x{AAB0}\x{AAB2}-\x{AAB4}\x{AAB7}-\x{AAB8}\x{AABE}-\x{AABF}\x{AAC1}\x{AADD}\x{AAEC}-\x{AAED}\x{AAF3}-\x{AAF4}\x{AAF6}\x{AB5B}\x{AB5C}-\x{AB5F}\x{ABE5}\x{ABE8}\x{ABED}\x{FB1E}\x{FBB2}-\x{FBC1}\x{FE00}-\x{FE0F}\x{FE13}\x{FE20}-\x{FE2F}\x{FE52}\x{FE55}\x{FEFF}\x{FF07}\x{FF0E}\x{FF1A}\x{FF3E}\x{FF40}\x{FF70}\x{FF9E}-\x{FF9F}\x{FFE3}\x{FFF9}-\x{FFFB}\x{101FD}\x{102E0}\x{10376}-\x{1037A}\x{10A01}-\x{10A03}\x{10A05}-\x{10A06}\x{10A0C}-\x{10A0F}\x{10A38}-\x{10A3A}\x{10A3F}\x{10AE5}-\x{10AE6}\x{10D24}-\x{10D27}\x{10F46}-\x{10F50}\x{11001}\x{11038}-\x{11046}\x{1107F}-\x{11081}\x{110B3}-\x{110B6}\x{110B9}-\x{110BA}\x{110BD}\x{110CD}\x{11100}-\x{11102}\x{11127}-\x{1112B}\x{1112D}-\x{11134}\x{11173}\x{11180}-\x{11181}\x{111B6}-\x{111BE}\x{111C9}-\x{111CC}\x{1122F}-\x{11231}\x{11234}\x{11236}-\x{11237}\x{1123E}\x{112DF}\x{112E3}-\x{112EA}\x{11300}-\x{11301}\x{1133B}-\x{1133C}\x{11340}\x{11366}-\x{1136C}\x{11370}-\x{11374}\x{11438}-\x{1143F}\x{11442}-\x{11444}\x{11446}\x{1145E}\x{114B3}-\x{114B8}\x{114BA}\x{114BF}-\x{114C0}\x{114C2}-\x{114C3}\x{115B2}-\x{115B5}\x{115BC}-\x{115BD}\x{115BF}-\x{115C0}\x{115DC}-\x{115DD}\x{11633}-\x{1163A}\x{1163D}\x{1163F}-\x{11640}\x{116AB}\x{116AD}\x{116B0}-\x{116B5}\x{116B7}\x{1171D}-\x{1171F}\x{11722}-\x{11725}\x{11727}-\x{1172B}\x{1182F}-\x{11837}\x{11839}-\x{1183A}\x{11A01}-\x{11A0A}\x{11A33}-\x{11A38}\x{11A3B}-\x{11A3E}\x{11A47}\x{11A51}-\x{11A56}\x{11A59}-\x{11A5B}\x{11A8A}-\x{11A96}\x{11A98}-\x{11A99}\x{11C30}-\x{11C36}\x{11C38}-\x{11C3D}\x{11C3F}\x{11C92}-\x{11CA7}\x{11CAA}-\x{11CB0}\x{11CB2}-\x{11CB3}\x{11CB5}-\x{11CB6}\x{11D31}-\x{11D36}\x{11D3A}\x{11D3C}-\x{11D3D}\x{11D3F}-\x{11D45}\x{11D47}\x{11D90}-\x{11D91}\x{11D95}\x{11D97}\x{11EF3}-\x{11EF4}\x{16AF0}-\x{16AF4}\x{16B30}-\x{16B36}\x{16B40}-\x{16B43}\x{16F8F}-\x{16F92}\x{16F93}-\x{16F9F}\x{16FE0}-\x{16FE1}\x{1BC9D}-\x{1BC9E}\x{1BCA0}-\x{1BCA3}\x{1D167}-\x{1D169}\x{1D173}-\x{1D17A}\x{1D17B}-\x{1D182}\x{1D185}-\x{1D18B}\x{1D1AA}-\x{1D1AD}\x{1D242}-\x{1D244}\x{1DA00}-\x{1DA36}\x{1DA3B}-\x{1DA6C}\x{1DA75}\x{1DA84}\x{1DA9B}-\x{1DA9F}\x{1DAA1}-\x{1DAAF}\x{1E000}-\x{1E006}\x{1E008}-\x{1E018}\x{1E01B}-\x{1E021}\x{1E023}-\x{1E024}\x{1E026}-\x{1E02A}\x{1E8D0}-\x{1E8D6}\x{1E944}-\x{1E94A}\x{1F3FB}-\x{1F3FF}\x{E0001}\x{E0020}-\x{E007F}\x{E0100}-\x{E01EF}])(\pL)(\pL*+)/u';
<?php

namespace _ContaoManager;

return array('a' => 'A', 'b' => 'B', 'c' => 'C', 'd' => 'D', 'e' => 'E', 'f' => 'F', 'g' => 'G', 'h' => 'H', 'i' => 'I', 'j' => 'J', 'k' => 'K', 'l' => 'L', 'm' => 'M', 'n' => 'N', 'o' => 'O', 'p' => 'P', 'q' => 'Q', 'r' => 'R', 's' => 'S', 't' => 'T', 'u' => 'U', 'v' => 'V', 'w' => 'W', 'x' => 'X', 'y' => 'Y', 'z' => 'Z', 'µ' => 'Μ', 'à' => 'À', 'á' => 'Á', 'â' => 'Â', 'ã' => 'Ã', 'ä' => 'Ä', 'å' => 'Å', 'æ' => 'Æ', 'ç' => 'Ç', 'è' => 'È', 'é' => 'É', 'ê' => 'Ê', 'ë' => 'Ë', 'ì' => 'Ì', 'í' => 'Í', 'î' => 'Î', 'ï' => 'Ï', 'ð' => 'Ð', 'ñ' => 'Ñ', 'ò' => 'Ò', 'ó' => 'Ó', 'ô' => 'Ô', 'õ' => 'Õ', 'ö' => 'Ö', 'ø' => 'Ø', 'ù' => 'Ù', 'ú' => 'Ú', 'û' => 'Û', 'ü' => 'Ü', 'ý' => 'Ý', 'þ' => 'Þ', 'ÿ' => 'Ÿ', 'ā' => 'Ā', 'ă' => 'Ă', 'ą' => 'Ą', 'ć' => 'Ć', 'ĉ' => 'Ĉ', 'ċ' => 'Ċ', 'č' => 'Č', 'ď' => 'Ď', 'đ' => 'Đ', 'ē' => 'Ē', 'ĕ' => 'Ĕ', 'ė' => 'Ė', 'ę' => 'Ę', 'ě' => 'Ě', 'ĝ' => 'Ĝ', 'ğ' => 'Ğ', 'ġ' => 'Ġ', 'ģ' => 'Ģ', 'ĥ' => 'Ĥ', 'ħ' => 'Ħ', 'ĩ' => 'Ĩ', 'ī' => 'Ī', 'ĭ' => 'Ĭ', 'į' => 'Į', 'ı' => 'I', 'ĳ' => 'Ĳ', 'ĵ' => 'Ĵ', 'ķ' => 'Ķ', 'ĺ' => 'Ĺ', 'ļ' => 'Ļ', 'ľ' => 'Ľ', 'ŀ' => 'Ŀ', 'ł' => 'Ł', 'ń' => 'Ń', 'ņ' => 'Ņ', 'ň' => 'Ň', 'ŋ' => 'Ŋ', 'ō' => 'Ō', 'ŏ' => 'Ŏ', 'ő' => 'Ő', 'œ' => 'Œ', 'ŕ' => 'Ŕ', 'ŗ' => 'Ŗ', 'ř' => 'Ř', 'ś' => 'Ś', 'ŝ' => 'Ŝ', 'ş' => 'Ş', 'š' => 'Š', 'ţ' => 'Ţ', 'ť' => 'Ť', 'ŧ' => 'Ŧ', 'ũ' => 'Ũ', 'ū' => 'Ū', 'ŭ' => 'Ŭ', 'ů' => 'Ů', 'ű' => 'Ű', 'ų' => 'Ų', 'ŵ' => 'Ŵ', 'ŷ' => 'Ŷ', 'ź' => 'Ź', 'ż' => 'Ż', 'ž' => 'Ž', 'ſ' => 'S', 'ƀ' => 'Ƀ', 'ƃ' => 'Ƃ', 'ƅ' => 'Ƅ', 'ƈ' => 'Ƈ', 'ƌ' => 'Ƌ', 'ƒ' => 'Ƒ', 'ƕ' => 'Ƕ', 'ƙ' => 'Ƙ', 'ƚ' => 'Ƚ', 'ƞ' => 'Ƞ', 'ơ' => 'Ơ', 'ƣ' => 'Ƣ', 'ƥ' => 'Ƥ', 'ƨ' => 'Ƨ', 'ƭ' => 'Ƭ', 'ư' => 'Ư', 'ƴ' => 'Ƴ', 'ƶ' => 'Ƶ', 'ƹ' => 'Ƹ', 'ƽ' => 'Ƽ', 'ƿ' => 'Ƿ', 'ǅ' => 'Ǆ', 'ǆ' => 'Ǆ', 'ǈ' => 'Ǉ', 'ǉ' => 'Ǉ', 'ǋ' => 'Ǌ', 'ǌ' => 'Ǌ', 'ǎ' => 'Ǎ', 'ǐ' => 'Ǐ', 'ǒ' => 'Ǒ', 'ǔ' => 'Ǔ', 'ǖ' => 'Ǖ', 'ǘ' => 'Ǘ', 'ǚ' => 'Ǚ', 'ǜ' => 'Ǜ', 'ǝ' => 'Ǝ', 'ǟ' => 'Ǟ', 'ǡ' => 'Ǡ', 'ǣ' => 'Ǣ', 'ǥ' => 'Ǥ', 'ǧ' => 'Ǧ', 'ǩ' => 'Ǩ', 'ǫ' => 'Ǫ', 'ǭ' => 'Ǭ', 'ǯ' => 'Ǯ', 'ǲ' => 'Ǳ', 'ǳ' => 'Ǳ', 'ǵ' => 'Ǵ', 'ǹ' => 'Ǹ', 'ǻ' => 'Ǻ', 'ǽ' => 'Ǽ', 'ǿ' => 'Ǿ', 'ȁ' => 'Ȁ', 'ȃ' => 'Ȃ', 'ȅ' => 'Ȅ', 'ȇ' => 'Ȇ', 'ȉ' => 'Ȉ', 'ȋ' => 'Ȋ', 'ȍ' => 'Ȍ', 'ȏ' => 'Ȏ', 'ȑ' => 'Ȑ', 'ȓ' => 'Ȓ', 'ȕ' => 'Ȕ', 'ȗ' => 'Ȗ', 'ș' => 'Ș', 'ț' => 'Ț', 'ȝ' => 'Ȝ', 'ȟ' => 'Ȟ', 'ȣ' => 'Ȣ', 'ȥ' => 'Ȥ', 'ȧ' => 'Ȧ', 'ȩ' => 'Ȩ', 'ȫ' => 'Ȫ', 'ȭ' => 'Ȭ', 'ȯ' => 'Ȯ', 'ȱ' => 'Ȱ', 'ȳ' => 'Ȳ', 'ȼ' => 'Ȼ', 'ȿ' => 'Ȿ', 'ɀ' => 'Ɀ', 'ɂ' => 'Ɂ', 'ɇ' => 'Ɇ', 'ɉ' => 'Ɉ', 'ɋ' => 'Ɋ', 'ɍ' => 'Ɍ', 'ɏ' => 'Ɏ', 'ɐ' => 'Ɐ', 'ɑ' => 'Ɑ', 'ɒ' => 'Ɒ', 'ɓ' => 'Ɓ', 'ɔ' => 'Ɔ', 'ɖ' => 'Ɖ', 'ɗ' => 'Ɗ', 'ə' => 'Ə', 'ɛ' => 'Ɛ', 'ɜ' => 'Ɜ', 'ɠ' => 'Ɠ', 'ɡ' => 'Ɡ', 'ɣ' => 'Ɣ', 'ɥ' => 'Ɥ', 'ɦ' => 'Ɦ', 'ɨ' => 'Ɨ', 'ɩ' => 'Ɩ', 'ɪ' => 'Ɪ', 'ɫ' => 'Ɫ', 'ɬ' => 'Ɬ', 'ɯ' => 'Ɯ', 'ɱ' => 'Ɱ', 'ɲ' => 'Ɲ', 'ɵ' => 'Ɵ', 'ɽ' => 'Ɽ', 'ʀ' => 'Ʀ', 'ʂ' => 'Ʂ', 'ʃ' => 'Ʃ', 'ʇ' => 'Ʇ', 'ʈ' => 'Ʈ', 'ʉ' => 'Ʉ', 'ʊ' => 'Ʊ', 'ʋ' => 'Ʋ', 'ʌ' => 'Ʌ', 'ʒ' => 'Ʒ', 'ʝ' => 'Ʝ', 'ʞ' => 'Ʞ', 'ͅ' => 'Ι', 'ͱ' => 'Ͱ', 'ͳ' => 'Ͳ', 'ͷ' => 'Ͷ', 'ͻ' => 'Ͻ', 'ͼ' => 'Ͼ', 'ͽ' => 'Ͽ', 'ά' => 'Ά', 'έ' => 'Έ', 'ή' => 'Ή', 'ί' => 'Ί', 'α' => 'Α', 'β' => 'Β', 'γ' => 'Γ', 'δ' => 'Δ', 'ε' => 'Ε', 'ζ' => 'Ζ', 'η' => 'Η', 'θ' => 'Θ', 'ι' => 'Ι', 'κ' => 'Κ', 'λ' => 'Λ', 'μ' => 'Μ', 'ν' => 'Ν', 'ξ' => 'Ξ', 'ο' => 'Ο', 'π' => 'Π', 'ρ' => 'Ρ', 'ς' => 'Σ', 'σ' => 'Σ', 'τ' => 'Τ', 'υ' => 'Υ', 'φ' => 'Φ', 'χ' => 'Χ', 'ψ' => 'Ψ', 'ω' => 'Ω', 'ϊ' => 'Ϊ', 'ϋ' => 'Ϋ', 'ό' => 'Ό', 'ύ' => 'Ύ', 'ώ' => 'Ώ', 'ϐ' => 'Β', 'ϑ' => 'Θ', 'ϕ' => 'Φ', 'ϖ' => 'Π', 'ϗ' => 'Ϗ', 'ϙ' => 'Ϙ', 'ϛ' => 'Ϛ', 'ϝ' => 'Ϝ', 'ϟ' => 'Ϟ', 'ϡ' => 'Ϡ', 'ϣ' => 'Ϣ', 'ϥ' => 'Ϥ', 'ϧ' => 'Ϧ', 'ϩ' => 'Ϩ', 'ϫ' => 'Ϫ', 'ϭ' => 'Ϭ', 'ϯ' => 'Ϯ', 'ϰ' => 'Κ', 'ϱ' => 'Ρ', 'ϲ' => 'Ϲ', 'ϳ' => 'Ϳ', 'ϵ' => 'Ε', 'ϸ' => 'Ϸ', 'ϻ' => 'Ϻ', 'а' => 'А', 'б' => 'Б', 'в' => 'В', 'г' => 'Г', 'д' => 'Д', 'е' => 'Е', 'ж' => 'Ж', 'з' => 'З', 'и' => 'И', 'й' => 'Й', 'к' => 'К', 'л' => 'Л', 'м' => 'М', 'н' => 'Н', 'о' => 'О', 'п' => 'П', 'р' => 'Р', 'с' => 'С', 'т' => 'Т', 'у' => 'У', 'ф' => 'Ф', 'х' => 'Х', 'ц' => 'Ц', 'ч' => 'Ч', 'ш' => 'Ш', 'щ' => 'Щ', 'ъ' => 'Ъ', 'ы' => 'Ы', 'ь' => 'Ь', 'э' => 'Э', 'ю' => 'Ю', 'я' => 'Я', 'ѐ' => 'Ѐ', 'ё' => 'Ё', 'ђ' => 'Ђ', 'ѓ' => 'Ѓ', 'є' => 'Є', 'ѕ' => 'Ѕ', 'і' => 'І', 'ї' => 'Ї', 'ј' => 'Ј', 'љ' => 'Љ', 'њ' => 'Њ', 'ћ' => 'Ћ', 'ќ' => 'Ќ', 'ѝ' => 'Ѝ', 'ў' => 'Ў', 'џ' => 'Џ', 'ѡ' => 'Ѡ', 'ѣ' => 'Ѣ', 'ѥ' => 'Ѥ', 'ѧ' => 'Ѧ', 'ѩ' => 'Ѩ', 'ѫ' => 'Ѫ', 'ѭ' => 'Ѭ', 'ѯ' => 'Ѯ', 'ѱ' => 'Ѱ', 'ѳ' => 'Ѳ', 'ѵ' => 'Ѵ', 'ѷ' => 'Ѷ', 'ѹ' => 'Ѹ', 'ѻ' => 'Ѻ', 'ѽ' => 'Ѽ', 'ѿ' => 'Ѿ', 'ҁ' => 'Ҁ', 'ҋ' => 'Ҋ', 'ҍ' => 'Ҍ', 'ҏ' => 'Ҏ', 'ґ' => 'Ґ', 'ғ' => 'Ғ', 'ҕ' => 'Ҕ', 'җ' => 'Җ', 'ҙ' => 'Ҙ', 'қ' => 'Қ', 'ҝ' => 'Ҝ', 'ҟ' => 'Ҟ', 'ҡ' => 'Ҡ', 'ң' => 'Ң', 'ҥ' => 'Ҥ', 'ҧ' => 'Ҧ', 'ҩ' => 'Ҩ', 'ҫ' => 'Ҫ', 'ҭ' => 'Ҭ', 'ү' => 'Ү', 'ұ' => 'Ұ', 'ҳ' => 'Ҳ', 'ҵ' => 'Ҵ', 'ҷ' => 'Ҷ', 'ҹ' => 'Ҹ', 'һ' => 'Һ', 'ҽ' => 'Ҽ', 'ҿ' => 'Ҿ', 'ӂ' => 'Ӂ', 'ӄ' => 'Ӄ', 'ӆ' => 'Ӆ', 'ӈ' => 'Ӈ', 'ӊ' => 'Ӊ', 'ӌ' => 'Ӌ', 'ӎ' => 'Ӎ', 'ӏ' => 'Ӏ', 'ӑ' => 'Ӑ', 'ӓ' => 'Ӓ', 'ӕ' => 'Ӕ', 'ӗ' => 'Ӗ', 'ә' => 'Ә', 'ӛ' => 'Ӛ', 'ӝ' => 'Ӝ', 'ӟ' => 'Ӟ', 'ӡ' => 'Ӡ', 'ӣ' => 'Ӣ', 'ӥ' => 'Ӥ', 'ӧ' => 'Ӧ', 'ө' => 'Ө', 'ӫ' => 'Ӫ', 'ӭ' => 'Ӭ', 'ӯ' => 'Ӯ', 'ӱ' => 'Ӱ', 'ӳ' => 'Ӳ', 'ӵ' => 'Ӵ', 'ӷ' => 'Ӷ', 'ӹ' => 'Ӹ', 'ӻ' => 'Ӻ', 'ӽ' => 'Ӽ', 'ӿ' => 'Ӿ', 'ԁ' => 'Ԁ', 'ԃ' => 'Ԃ', 'ԅ' => 'Ԅ', 'ԇ' => 'Ԇ', 'ԉ' => 'Ԉ', 'ԋ' => 'Ԋ', 'ԍ' => 'Ԍ', 'ԏ' => 'Ԏ', 'ԑ' => 'Ԑ', 'ԓ' => 'Ԓ', 'ԕ' => 'Ԕ', 'ԗ' => 'Ԗ', 'ԙ' => 'Ԙ', 'ԛ' => 'Ԛ', 'ԝ' => 'Ԝ', 'ԟ' => 'Ԟ', 'ԡ' => 'Ԡ', 'ԣ' => 'Ԣ', 'ԥ' => 'Ԥ', 'ԧ' => 'Ԧ', 'ԩ' => 'Ԩ', 'ԫ' => 'Ԫ', 'ԭ' => 'Ԭ', 'ԯ' => 'Ԯ', 'ա' => 'Ա', 'բ' => 'Բ', 'գ' => 'Գ', 'դ' => 'Դ', 'ե' => 'Ե', 'զ' => 'Զ', 'է' => 'Է', 'ը' => 'Ը', 'թ' => 'Թ', 'ժ' => 'Ժ', 'ի' => 'Ի', 'լ' => 'Լ', 'խ' => 'Խ', 'ծ' => 'Ծ', 'կ' => 'Կ', 'հ' => 'Հ', 'ձ' => 'Ձ', 'ղ' => 'Ղ', 'ճ' => 'Ճ', 'մ' => 'Մ', 'յ' => 'Յ', 'ն' => 'Ն', 'շ' => 'Շ', 'ո' => 'Ո', 'չ' => 'Չ', 'պ' => 'Պ', 'ջ' => 'Ջ', 'ռ' => 'Ռ', 'ս' => 'Ս', 'վ' => 'Վ', 'տ' => 'Տ', 'ր' => 'Ր', 'ց' => 'Ց', 'ւ' => 'Ւ', 'փ' => 'Փ', 'ք' => 'Ք', 'օ' => 'Օ', 'ֆ' => 'Ֆ', 'ა' => 'Ა', 'ბ' => 'Ბ', 'გ' => 'Გ', 'დ' => 'Დ', 'ე' => 'Ე', 'ვ' => 'Ვ', 'ზ' => 'Ზ', 'თ' => 'Თ', 'ი' => 'Ი', 'კ' => 'Კ', 'ლ' => 'Ლ', 'მ' => 'Მ', 'ნ' => 'Ნ', 'ო' => 'Ო', 'პ' => 'Პ', 'ჟ' => 'Ჟ', 'რ' => 'Რ', 'ს' => 'Ს', 'ტ' => 'Ტ', 'უ' => 'Უ', 'ფ' => 'Ფ', 'ქ' => 'Ქ', 'ღ' => 'Ღ', 'ყ' => 'Ყ', 'შ' => 'Შ', 'ჩ' => 'Ჩ', 'ც' => 'Ც', 'ძ' => 'Ძ', 'წ' => 'Წ', 'ჭ' => 'Ჭ', 'ხ' => 'Ხ', 'ჯ' => 'Ჯ', 'ჰ' => 'Ჰ', 'ჱ' => 'Ჱ', 'ჲ' => 'Ჲ', 'ჳ' => 'Ჳ', 'ჴ' => 'Ჴ', 'ჵ' => 'Ჵ', 'ჶ' => 'Ჶ', 'ჷ' => 'Ჷ', 'ჸ' => 'Ჸ', 'ჹ' => 'Ჹ', 'ჺ' => 'Ჺ', 'ჽ' => 'Ჽ', 'ჾ' => 'Ჾ', 'ჿ' => 'Ჿ', 'ᏸ' => 'Ᏸ', 'ᏹ' => 'Ᏹ', 'ᏺ' => 'Ᏺ', 'ᏻ' => 'Ᏻ', 'ᏼ' => 'Ᏼ', 'ᏽ' => 'Ᏽ', 'ᲀ' => 'В', 'ᲁ' => 'Д', 'ᲂ' => 'О', 'ᲃ' => 'С', 'ᲄ' => 'Т', 'ᲅ' => 'Т', 'ᲆ' => 'Ъ', 'ᲇ' => 'Ѣ', 'ᲈ' => 'Ꙋ', 'ᵹ' => 'Ᵹ', 'ᵽ' => 'Ᵽ', 'ᶎ' => 'Ᶎ', 'ḁ' => 'Ḁ', 'ḃ' => 'Ḃ', 'ḅ' => 'Ḅ', 'ḇ' => 'Ḇ', 'ḉ' => 'Ḉ', 'ḋ' => 'Ḋ', 'ḍ' => 'Ḍ', 'ḏ' => 'Ḏ', 'ḑ' => 'Ḑ', 'ḓ' => 'Ḓ', 'ḕ' => 'Ḕ', 'ḗ' => 'Ḗ', 'ḙ' => 'Ḙ', 'ḛ' => 'Ḛ', 'ḝ' => 'Ḝ', 'ḟ' => 'Ḟ', 'ḡ' => 'Ḡ', 'ḣ' => 'Ḣ', 'ḥ' => 'Ḥ', 'ḧ' => 'Ḧ', 'ḩ' => 'Ḩ', 'ḫ' => 'Ḫ', 'ḭ' => 'Ḭ', 'ḯ' => 'Ḯ', 'ḱ' => 'Ḱ', 'ḳ' => 'Ḳ', 'ḵ' => 'Ḵ', 'ḷ' => 'Ḷ', 'ḹ' => 'Ḹ', 'ḻ' => 'Ḻ', 'ḽ' => 'Ḽ', 'ḿ' => 'Ḿ', 'ṁ' => 'Ṁ', 'ṃ' => 'Ṃ', 'ṅ' => 'Ṅ', 'ṇ' => 'Ṇ', 'ṉ' => 'Ṉ', 'ṋ' => 'Ṋ', 'ṍ' => 'Ṍ', 'ṏ' => 'Ṏ', 'ṑ' => 'Ṑ', 'ṓ' => 'Ṓ', 'ṕ' => 'Ṕ', 'ṗ' => 'Ṗ', 'ṙ' => 'Ṙ', 'ṛ' => 'Ṛ', 'ṝ' => 'Ṝ', 'ṟ' => 'Ṟ', 'ṡ' => 'Ṡ', 'ṣ' => 'Ṣ', 'ṥ' => 'Ṥ', 'ṧ' => 'Ṧ', 'ṩ' => 'Ṩ', 'ṫ' => 'Ṫ', 'ṭ' => 'Ṭ', 'ṯ' => 'Ṯ', 'ṱ' => 'Ṱ', 'ṳ' => 'Ṳ', 'ṵ' => 'Ṵ', 'ṷ' => 'Ṷ', 'ṹ' => 'Ṹ', 'ṻ' => 'Ṻ', 'ṽ' => 'Ṽ', 'ṿ' => 'Ṿ', 'ẁ' => 'Ẁ', 'ẃ' => 'Ẃ', 'ẅ' => 'Ẅ', 'ẇ' => 'Ẇ', 'ẉ' => 'Ẉ', 'ẋ' => 'Ẋ', 'ẍ' => 'Ẍ', 'ẏ' => 'Ẏ', 'ẑ' => 'Ẑ', 'ẓ' => 'Ẓ', 'ẕ' => 'Ẕ', 'ẛ' => 'Ṡ', 'ạ' => 'Ạ', 'ả' => 'Ả', 'ấ' => 'Ấ', 'ầ' => 'Ầ', 'ẩ' => 'Ẩ', 'ẫ' => 'Ẫ', 'ậ' => 'Ậ', 'ắ' => 'Ắ', 'ằ' => 'Ằ', 'ẳ' => 'Ẳ', 'ẵ' => 'Ẵ', 'ặ' => 'Ặ', 'ẹ' => 'Ẹ', 'ẻ' => 'Ẻ', 'ẽ' => 'Ẽ', 'ế' => 'Ế', 'ề' => 'Ề', 'ể' => 'Ể', 'ễ' => 'Ễ', 'ệ' => 'Ệ', 'ỉ' => 'Ỉ', 'ị' => 'Ị', 'ọ' => 'Ọ', 'ỏ' => 'Ỏ', 'ố' => 'Ố', 'ồ' => 'Ồ', 'ổ' => 'Ổ', 'ỗ' => 'Ỗ', 'ộ' => 'Ộ', 'ớ' => 'Ớ', 'ờ' => 'Ờ', 'ở' => 'Ở', 'ỡ' => 'Ỡ', 'ợ' => 'Ợ', 'ụ' => 'Ụ', 'ủ' => 'Ủ', 'ứ' => 'Ứ', 'ừ' => 'Ừ', 'ử' => 'Ử', 'ữ' => 'Ữ', 'ự' => 'Ự', 'ỳ' => 'Ỳ', 'ỵ' => 'Ỵ', 'ỷ' => 'Ỷ', 'ỹ' => 'Ỹ', 'ỻ' => 'Ỻ', 'ỽ' => 'Ỽ', 'ỿ' => 'Ỿ', 'ἀ' => 'Ἀ', 'ἁ' => 'Ἁ', 'ἂ' => 'Ἂ', 'ἃ' => 'Ἃ', 'ἄ' => 'Ἄ', 'ἅ' => 'Ἅ', 'ἆ' => 'Ἆ', 'ἇ' => 'Ἇ', 'ἐ' => 'Ἐ', 'ἑ' => 'Ἑ', 'ἒ' => 'Ἒ', 'ἓ' => 'Ἓ', 'ἔ' => 'Ἔ', 'ἕ' => 'Ἕ', 'ἠ' => 'Ἠ', 'ἡ' => 'Ἡ', 'ἢ' => 'Ἢ', 'ἣ' => 'Ἣ', 'ἤ' => 'Ἤ', 'ἥ' => 'Ἥ', 'ἦ' => 'Ἦ', 'ἧ' => 'Ἧ', 'ἰ' => 'Ἰ', 'ἱ' => 'Ἱ', 'ἲ' => 'Ἲ', 'ἳ' => 'Ἳ', 'ἴ' => 'Ἴ', 'ἵ' => 'Ἵ', 'ἶ' => 'Ἶ', 'ἷ' => 'Ἷ', 'ὀ' => 'Ὀ', 'ὁ' => 'Ὁ', 'ὂ' => 'Ὂ', 'ὃ' => 'Ὃ', 'ὄ' => 'Ὄ', 'ὅ' => 'Ὅ', 'ὑ' => 'Ὑ', 'ὓ' => 'Ὓ', 'ὕ' => 'Ὕ', 'ὗ' => 'Ὗ', 'ὠ' => 'Ὠ', 'ὡ' => 'Ὡ', 'ὢ' => 'Ὢ', 'ὣ' => 'Ὣ', 'ὤ' => 'Ὤ', 'ὥ' => 'Ὥ', 'ὦ' => 'Ὦ', 'ὧ' => 'Ὧ', 'ὰ' => 'Ὰ', 'ά' => 'Ά', 'ὲ' => 'Ὲ', 'έ' => 'Έ', 'ὴ' => 'Ὴ', 'ή' => 'Ή', 'ὶ' => 'Ὶ', 'ί' => 'Ί', 'ὸ' => 'Ὸ', 'ό' => 'Ό', 'ὺ' => 'Ὺ', 'ύ' => 'Ύ', 'ὼ' => 'Ὼ', 'ώ' => 'Ώ', 'ᾀ' => 'ἈΙ', 'ᾁ' => 'ἉΙ', 'ᾂ' => 'ἊΙ', 'ᾃ' => 'ἋΙ', 'ᾄ' => 'ἌΙ', 'ᾅ' => 'ἍΙ', 'ᾆ' => 'ἎΙ', 'ᾇ' => 'ἏΙ', 'ᾐ' => 'ἨΙ', 'ᾑ' => 'ἩΙ', 'ᾒ' => 'ἪΙ', 'ᾓ' => 'ἫΙ', 'ᾔ' => 'ἬΙ', 'ᾕ' => 'ἭΙ', 'ᾖ' => 'ἮΙ', 'ᾗ' => 'ἯΙ', 'ᾠ' => 'ὨΙ', 'ᾡ' => 'ὩΙ', 'ᾢ' => 'ὪΙ', 'ᾣ' => 'ὫΙ', 'ᾤ' => 'ὬΙ', 'ᾥ' => 'ὭΙ', 'ᾦ' => 'ὮΙ', 'ᾧ' => 'ὯΙ', 'ᾰ' => 'Ᾰ', 'ᾱ' => 'Ᾱ', 'ᾳ' => 'ΑΙ', 'ι' => 'Ι', 'ῃ' => 'ΗΙ', 'ῐ' => 'Ῐ', 'ῑ' => 'Ῑ', 'ῠ' => 'Ῠ', 'ῡ' => 'Ῡ', 'ῥ' => 'Ῥ', 'ῳ' => 'ΩΙ', 'ⅎ' => 'Ⅎ', 'ⅰ' => 'Ⅰ', 'ⅱ' => 'Ⅱ', 'ⅲ' => 'Ⅲ', 'ⅳ' => 'Ⅳ', 'ⅴ' => 'Ⅴ', 'ⅵ' => 'Ⅵ', 'ⅶ' => 'Ⅶ', 'ⅷ' => 'Ⅷ', 'ⅸ' => 'Ⅸ', 'ⅹ' => 'Ⅹ', 'ⅺ' => 'Ⅺ', 'ⅻ' => 'Ⅻ', 'ⅼ' => 'Ⅼ', 'ⅽ' => 'Ⅽ', 'ⅾ' => 'Ⅾ', 'ⅿ' => 'Ⅿ', 'ↄ' => 'Ↄ', 'ⓐ' => 'Ⓐ', 'ⓑ' => 'Ⓑ', 'ⓒ' => 'Ⓒ', 'ⓓ' => 'Ⓓ', 'ⓔ' => 'Ⓔ', 'ⓕ' => 'Ⓕ', 'ⓖ' => 'Ⓖ', 'ⓗ' => 'Ⓗ', 'ⓘ' => 'Ⓘ', 'ⓙ' => 'Ⓙ', 'ⓚ' => 'Ⓚ', 'ⓛ' => 'Ⓛ', 'ⓜ' => 'Ⓜ', 'ⓝ' => 'Ⓝ', 'ⓞ' => 'Ⓞ', 'ⓟ' => 'Ⓟ', 'ⓠ' => 'Ⓠ', 'ⓡ' => 'Ⓡ', 'ⓢ' => 'Ⓢ', 'ⓣ' => 'Ⓣ', 'ⓤ' => 'Ⓤ', 'ⓥ' => 'Ⓥ', 'ⓦ' => 'Ⓦ', 'ⓧ' => 'Ⓧ', 'ⓨ' => 'Ⓨ', 'ⓩ' => 'Ⓩ', 'ⰰ' => 'Ⰰ', 'ⰱ' => 'Ⰱ', 'ⰲ' => 'Ⰲ', 'ⰳ' => 'Ⰳ', 'ⰴ' => 'Ⰴ', 'ⰵ' => 'Ⰵ', 'ⰶ' => 'Ⰶ', 'ⰷ' => 'Ⰷ', 'ⰸ' => 'Ⰸ', 'ⰹ' => 'Ⰹ', 'ⰺ' => 'Ⰺ', 'ⰻ' => 'Ⰻ', 'ⰼ' => 'Ⰼ', 'ⰽ' => 'Ⰽ', 'ⰾ' => 'Ⰾ', 'ⰿ' => 'Ⰿ', 'ⱀ' => 'Ⱀ', 'ⱁ' => 'Ⱁ', 'ⱂ' => 'Ⱂ', 'ⱃ' => 'Ⱃ', 'ⱄ' => 'Ⱄ', 'ⱅ' => 'Ⱅ', 'ⱆ' => 'Ⱆ', 'ⱇ' => 'Ⱇ', 'ⱈ' => 'Ⱈ', 'ⱉ' => 'Ⱉ', 'ⱊ' => 'Ⱊ', 'ⱋ' => 'Ⱋ', 'ⱌ' => 'Ⱌ', 'ⱍ' => 'Ⱍ', 'ⱎ' => 'Ⱎ', 'ⱏ' => 'Ⱏ', 'ⱐ' => 'Ⱐ', 'ⱑ' => 'Ⱑ', 'ⱒ' => 'Ⱒ', 'ⱓ' => 'Ⱓ', 'ⱔ' => 'Ⱔ', 'ⱕ' => 'Ⱕ', 'ⱖ' => 'Ⱖ', 'ⱗ' => 'Ⱗ', 'ⱘ' => 'Ⱘ', 'ⱙ' => 'Ⱙ', 'ⱚ' => 'Ⱚ', 'ⱛ' => 'Ⱛ', 'ⱜ' => 'Ⱜ', 'ⱝ' => 'Ⱝ', 'ⱞ' => 'Ⱞ', 'ⱡ' => 'Ⱡ', 'ⱥ' => 'Ⱥ', 'ⱦ' => 'Ⱦ', 'ⱨ' => 'Ⱨ', 'ⱪ' => 'Ⱪ', 'ⱬ' => 'Ⱬ', 'ⱳ' => 'Ⱳ', 'ⱶ' => 'Ⱶ', 'ⲁ' => 'Ⲁ', 'ⲃ' => 'Ⲃ', 'ⲅ' => 'Ⲅ', 'ⲇ' => 'Ⲇ', 'ⲉ' => 'Ⲉ', 'ⲋ' => 'Ⲋ', 'ⲍ' => 'Ⲍ', 'ⲏ' => 'Ⲏ', 'ⲑ' => 'Ⲑ', 'ⲓ' => 'Ⲓ', 'ⲕ' => 'Ⲕ', 'ⲗ' => 'Ⲗ', 'ⲙ' => 'Ⲙ', 'ⲛ' => 'Ⲛ', 'ⲝ' => 'Ⲝ', 'ⲟ' => 'Ⲟ', 'ⲡ' => 'Ⲡ', 'ⲣ' => 'Ⲣ', 'ⲥ' => 'Ⲥ', 'ⲧ' => 'Ⲧ', 'ⲩ' => 'Ⲩ', 'ⲫ' => 'Ⲫ', 'ⲭ' => 'Ⲭ', 'ⲯ' => 'Ⲯ', 'ⲱ' => 'Ⲱ', 'ⲳ' => 'Ⲳ', 'ⲵ' => 'Ⲵ', 'ⲷ' => 'Ⲷ', 'ⲹ' => 'Ⲹ', 'ⲻ' => 'Ⲻ', 'ⲽ' => 'Ⲽ', 'ⲿ' => 'Ⲿ', 'ⳁ' => 'Ⳁ', 'ⳃ' => 'Ⳃ', 'ⳅ' => 'Ⳅ', 'ⳇ' => 'Ⳇ', 'ⳉ' => 'Ⳉ', 'ⳋ' => 'Ⳋ', 'ⳍ' => 'Ⳍ', 'ⳏ' => 'Ⳏ', 'ⳑ' => 'Ⳑ', 'ⳓ' => 'Ⳓ', 'ⳕ' => 'Ⳕ', 'ⳗ' => 'Ⳗ', 'ⳙ' => 'Ⳙ', 'ⳛ' => 'Ⳛ', 'ⳝ' => 'Ⳝ', 'ⳟ' => 'Ⳟ', 'ⳡ' => 'Ⳡ', 'ⳣ' => 'Ⳣ', 'ⳬ' => 'Ⳬ', 'ⳮ' => 'Ⳮ', 'ⳳ' => 'Ⳳ', 'ⴀ' => 'Ⴀ', 'ⴁ' => 'Ⴁ', 'ⴂ' => 'Ⴂ', 'ⴃ' => 'Ⴃ', 'ⴄ' => 'Ⴄ', 'ⴅ' => 'Ⴅ', 'ⴆ' => 'Ⴆ', 'ⴇ' => 'Ⴇ', 'ⴈ' => 'Ⴈ', 'ⴉ' => 'Ⴉ', 'ⴊ' => 'Ⴊ', 'ⴋ' => 'Ⴋ', 'ⴌ' => 'Ⴌ', 'ⴍ' => 'Ⴍ', 'ⴎ' => 'Ⴎ', 'ⴏ' => 'Ⴏ', 'ⴐ' => 'Ⴐ', 'ⴑ' => 'Ⴑ', 'ⴒ' => 'Ⴒ', 'ⴓ' => 'Ⴓ', 'ⴔ' => 'Ⴔ', 'ⴕ' => 'Ⴕ', 'ⴖ' => 'Ⴖ', 'ⴗ' => 'Ⴗ', 'ⴘ' => 'Ⴘ', 'ⴙ' => 'Ⴙ', 'ⴚ' => 'Ⴚ', 'ⴛ' => 'Ⴛ', 'ⴜ' => 'Ⴜ', 'ⴝ' => 'Ⴝ', 'ⴞ' => 'Ⴞ', 'ⴟ' => 'Ⴟ', 'ⴠ' => 'Ⴠ', 'ⴡ' => 'Ⴡ', 'ⴢ' => 'Ⴢ', 'ⴣ' => 'Ⴣ', 'ⴤ' => 'Ⴤ', 'ⴥ' => 'Ⴥ', 'ⴧ' => 'Ⴧ', 'ⴭ' => 'Ⴭ', 'ꙁ' => 'Ꙁ', 'ꙃ' => 'Ꙃ', 'ꙅ' => 'Ꙅ', 'ꙇ' => 'Ꙇ', 'ꙉ' => 'Ꙉ', 'ꙋ' => 'Ꙋ', 'ꙍ' => 'Ꙍ', 'ꙏ' => 'Ꙏ', 'ꙑ' => 'Ꙑ', 'ꙓ' => 'Ꙓ', 'ꙕ' => 'Ꙕ', 'ꙗ' => 'Ꙗ', 'ꙙ' => 'Ꙙ', 'ꙛ' => 'Ꙛ', 'ꙝ' => 'Ꙝ', 'ꙟ' => 'Ꙟ', 'ꙡ' => 'Ꙡ', 'ꙣ' => 'Ꙣ', 'ꙥ' => 'Ꙥ', 'ꙧ' => 'Ꙧ', 'ꙩ' => 'Ꙩ', 'ꙫ' => 'Ꙫ', 'ꙭ' => 'Ꙭ', 'ꚁ' => 'Ꚁ', 'ꚃ' => 'Ꚃ', 'ꚅ' => 'Ꚅ', 'ꚇ' => 'Ꚇ', 'ꚉ' => 'Ꚉ', 'ꚋ' => 'Ꚋ', 'ꚍ' => 'Ꚍ', 'ꚏ' => 'Ꚏ', 'ꚑ' => 'Ꚑ', 'ꚓ' => 'Ꚓ', 'ꚕ' => 'Ꚕ', 'ꚗ' => 'Ꚗ', 'ꚙ' => 'Ꚙ', 'ꚛ' => 'Ꚛ', 'ꜣ' => 'Ꜣ', 'ꜥ' => 'Ꜥ', 'ꜧ' => 'Ꜧ', 'ꜩ' => 'Ꜩ', 'ꜫ' => 'Ꜫ', 'ꜭ' => 'Ꜭ', 'ꜯ' => 'Ꜯ', 'ꜳ' => 'Ꜳ', 'ꜵ' => 'Ꜵ', 'ꜷ' => 'Ꜷ', 'ꜹ' => 'Ꜹ', 'ꜻ' => 'Ꜻ', 'ꜽ' => 'Ꜽ', 'ꜿ' => 'Ꜿ', 'ꝁ' => 'Ꝁ', 'ꝃ' => 'Ꝃ', 'ꝅ' => 'Ꝅ', 'ꝇ' => 'Ꝇ', 'ꝉ' => 'Ꝉ', 'ꝋ' => 'Ꝋ', 'ꝍ' => 'Ꝍ', 'ꝏ' => 'Ꝏ', 'ꝑ' => 'Ꝑ', 'ꝓ' => 'Ꝓ', 'ꝕ' => 'Ꝕ', 'ꝗ' => 'Ꝗ', 'ꝙ' => 'Ꝙ', 'ꝛ' => 'Ꝛ', 'ꝝ' => 'Ꝝ', 'ꝟ' => 'Ꝟ', 'ꝡ' => 'Ꝡ', 'ꝣ' => 'Ꝣ', 'ꝥ' => 'Ꝥ', 'ꝧ' => 'Ꝧ', 'ꝩ' => 'Ꝩ', 'ꝫ' => 'Ꝫ', 'ꝭ' => 'Ꝭ', 'ꝯ' => 'Ꝯ', 'ꝺ' => 'Ꝺ', 'ꝼ' => 'Ꝼ', 'ꝿ' => 'Ꝿ', 'ꞁ' => 'Ꞁ', 'ꞃ' => 'Ꞃ', 'ꞅ' => 'Ꞅ', 'ꞇ' => 'Ꞇ', 'ꞌ' => 'Ꞌ', 'ꞑ' => 'Ꞑ', 'ꞓ' => 'Ꞓ', 'ꞔ' => 'Ꞔ', 'ꞗ' => 'Ꞗ', 'ꞙ' => 'Ꞙ', 'ꞛ' => 'Ꞛ', 'ꞝ' => 'Ꞝ', 'ꞟ' => 'Ꞟ', 'ꞡ' => 'Ꞡ', 'ꞣ' => 'Ꞣ', 'ꞥ' => 'Ꞥ', 'ꞧ' => 'Ꞧ', 'ꞩ' => 'Ꞩ', 'ꞵ' => 'Ꞵ', 'ꞷ' => 'Ꞷ', 'ꞹ' => 'Ꞹ', 'ꞻ' => 'Ꞻ', 'ꞽ' => 'Ꞽ', 'ꞿ' => 'Ꞿ', 'ꟃ' => 'Ꟃ', 'ꟈ' => 'Ꟈ', 'ꟊ' => 'Ꟊ', 'ꟶ' => 'Ꟶ', 'ꭓ' => 'Ꭓ', 'ꭰ' => 'Ꭰ', 'ꭱ' => 'Ꭱ', 'ꭲ' => 'Ꭲ', 'ꭳ' => 'Ꭳ', 'ꭴ' => 'Ꭴ', 'ꭵ' => 'Ꭵ', 'ꭶ' => 'Ꭶ', 'ꭷ' => 'Ꭷ', 'ꭸ' => 'Ꭸ', 'ꭹ' => 'Ꭹ', 'ꭺ' => 'Ꭺ', 'ꭻ' => 'Ꭻ', 'ꭼ' => 'Ꭼ', 'ꭽ' => 'Ꭽ', 'ꭾ' => 'Ꭾ', 'ꭿ' => 'Ꭿ', 'ꮀ' => 'Ꮀ', 'ꮁ' => 'Ꮁ', 'ꮂ' => 'Ꮂ', 'ꮃ' => 'Ꮃ', 'ꮄ' => 'Ꮄ', 'ꮅ' => 'Ꮅ', 'ꮆ' => 'Ꮆ', 'ꮇ' => 'Ꮇ', 'ꮈ' => 'Ꮈ', 'ꮉ' => 'Ꮉ', 'ꮊ' => 'Ꮊ', 'ꮋ' => 'Ꮋ', 'ꮌ' => 'Ꮌ', 'ꮍ' => 'Ꮍ', 'ꮎ' => 'Ꮎ', 'ꮏ' => 'Ꮏ', 'ꮐ' => 'Ꮐ', 'ꮑ' => 'Ꮑ', 'ꮒ' => 'Ꮒ', 'ꮓ' => 'Ꮓ', 'ꮔ' => 'Ꮔ', 'ꮕ' => 'Ꮕ', 'ꮖ' => 'Ꮖ', 'ꮗ' => 'Ꮗ', 'ꮘ' => 'Ꮘ', 'ꮙ' => 'Ꮙ', 'ꮚ' => 'Ꮚ', 'ꮛ' => 'Ꮛ', 'ꮜ' => 'Ꮜ', 'ꮝ' => 'Ꮝ', 'ꮞ' => 'Ꮞ', 'ꮟ' => 'Ꮟ', 'ꮠ' => 'Ꮠ', 'ꮡ' => 'Ꮡ', 'ꮢ' => 'Ꮢ', 'ꮣ' => 'Ꮣ', 'ꮤ' => 'Ꮤ', 'ꮥ' => 'Ꮥ', 'ꮦ' => 'Ꮦ', 'ꮧ' => 'Ꮧ', 'ꮨ' => 'Ꮨ', 'ꮩ' => 'Ꮩ', 'ꮪ' => 'Ꮪ', 'ꮫ' => 'Ꮫ', 'ꮬ' => 'Ꮬ', 'ꮭ' => 'Ꮭ', 'ꮮ' => 'Ꮮ', 'ꮯ' => 'Ꮯ', 'ꮰ' => 'Ꮰ', 'ꮱ' => 'Ꮱ', 'ꮲ' => 'Ꮲ', 'ꮳ' => 'Ꮳ', 'ꮴ' => 'Ꮴ', 'ꮵ' => 'Ꮵ', 'ꮶ' => 'Ꮶ', 'ꮷ' => 'Ꮷ', 'ꮸ' => 'Ꮸ', 'ꮹ' => 'Ꮹ', 'ꮺ' => 'Ꮺ', 'ꮻ' => 'Ꮻ', 'ꮼ' => 'Ꮼ', 'ꮽ' => 'Ꮽ', 'ꮾ' => 'Ꮾ', 'ꮿ' => 'Ꮿ', 'ａ' => 'Ａ', 'ｂ' => 'Ｂ', 'ｃ' => 'Ｃ', 'ｄ' => 'Ｄ', 'ｅ' => 'Ｅ', 'ｆ' => 'Ｆ', 'ｇ' => 'Ｇ', 'ｈ' => 'Ｈ', 'ｉ' => 'Ｉ', 'ｊ' => 'Ｊ', 'ｋ' => 'Ｋ', 'ｌ' => 'Ｌ', 'ｍ' => 'Ｍ', 'ｎ' => 'Ｎ', 'ｏ' => 'Ｏ', 'ｐ' => 'Ｐ', 'ｑ' => 'Ｑ', 'ｒ' => 'Ｒ', 'ｓ' => 'Ｓ', 'ｔ' => 'Ｔ', 'ｕ' => 'Ｕ', 'ｖ' => 'Ｖ', 'ｗ' => 'Ｗ', 'ｘ' => 'Ｘ', 'ｙ' => 'Ｙ', 'ｚ' => 'Ｚ', '𐐨' => '𐐀', '𐐩' => '𐐁', '𐐪' => '𐐂', '𐐫' => '𐐃', '𐐬' => '𐐄', '𐐭' => '𐐅', '𐐮' => '𐐆', '𐐯' => '𐐇', '𐐰' => '𐐈', '𐐱' => '𐐉', '𐐲' => '𐐊', '𐐳' => '𐐋', '𐐴' => '𐐌', '𐐵' => '𐐍', '𐐶' => '𐐎', '𐐷' => '𐐏', '𐐸' => '𐐐', '𐐹' => '𐐑', '𐐺' => '𐐒', '𐐻' => '𐐓', '𐐼' => '𐐔', '𐐽' => '𐐕', '𐐾' => '𐐖', '𐐿' => '𐐗', '𐑀' => '𐐘', '𐑁' => '𐐙', '𐑂' => '𐐚', '𐑃' => '𐐛', '𐑄' => '𐐜', '𐑅' => '𐐝', '𐑆' => '𐐞', '𐑇' => '𐐟', '𐑈' => '𐐠', '𐑉' => '𐐡', '𐑊' => '𐐢', '𐑋' => '𐐣', '𐑌' => '𐐤', '𐑍' => '𐐥', '𐑎' => '𐐦', '𐑏' => '𐐧', '𐓘' => '𐒰', '𐓙' => '𐒱', '𐓚' => '𐒲', '𐓛' => '𐒳', '𐓜' => '𐒴', '𐓝' => '𐒵', '𐓞' => '𐒶', '𐓟' => '𐒷', '𐓠' => '𐒸', '𐓡' => '𐒹', '𐓢' => '𐒺', '𐓣' => '𐒻', '𐓤' => '𐒼', '𐓥' => '𐒽', '𐓦' => '𐒾', '𐓧' => '𐒿', '𐓨' => '𐓀', '𐓩' => '𐓁', '𐓪' => '𐓂', '𐓫' => '𐓃', '𐓬' => '𐓄', '𐓭' => '𐓅', '𐓮' => '𐓆', '𐓯' => '𐓇', '𐓰' => '𐓈', '𐓱' => '𐓉', '𐓲' => '𐓊', '𐓳' => '𐓋', '𐓴' => '𐓌', '𐓵' => '𐓍', '𐓶' => '𐓎', '𐓷' => '𐓏', '𐓸' => '𐓐', '𐓹' => '𐓑', '𐓺' => '𐓒', '𐓻' => '𐓓', '𐳀' => '𐲀', '𐳁' => '𐲁', '𐳂' => '𐲂', '𐳃' => '𐲃', '𐳄' => '𐲄', '𐳅' => '𐲅', '𐳆' => '𐲆', '𐳇' => '𐲇', '𐳈' => '𐲈', '𐳉' => '𐲉', '𐳊' => '𐲊', '𐳋' => '𐲋', '𐳌' => '𐲌', '𐳍' => '𐲍', '𐳎' => '𐲎', '𐳏' => '𐲏', '𐳐' => '𐲐', '𐳑' => '𐲑', '𐳒' => '𐲒', '𐳓' => '𐲓', '𐳔' => '𐲔', '𐳕' => '𐲕', '𐳖' => '𐲖', '𐳗' => '𐲗', '𐳘' => '𐲘', '𐳙' => '𐲙', '𐳚' => '𐲚', '𐳛' => '𐲛', '𐳜' => '𐲜', '𐳝' => '𐲝', '𐳞' => '𐲞', '𐳟' => '𐲟', '𐳠' => '𐲠', '𐳡' => '𐲡', '𐳢' => '𐲢', '𐳣' => '𐲣', '𐳤' => '𐲤', '𐳥' => '𐲥', '𐳦' => '𐲦', '𐳧' => '𐲧', '𐳨' => '𐲨', '𐳩' => '𐲩', '𐳪' => '𐲪', '𐳫' => '𐲫', '𐳬' => '𐲬', '𐳭' => '𐲭', '𐳮' => '𐲮', '𐳯' => '𐲯', '𐳰' => '𐲰', '𐳱' => '𐲱', '𐳲' => '𐲲', '𑣀' => '𑢠', '𑣁' => '𑢡', '𑣂' => '𑢢', '𑣃' => '𑢣', '𑣄' => '𑢤', '𑣅' => '𑢥', '𑣆' => '𑢦', '𑣇' => '𑢧', '𑣈' => '𑢨', '𑣉' => '𑢩', '𑣊' => '𑢪', '𑣋' => '𑢫', '𑣌' => '𑢬', '𑣍' => '𑢭', '𑣎' => '𑢮', '𑣏' => '𑢯', '𑣐' => '𑢰', '𑣑' => '𑢱', '𑣒' => '𑢲', '𑣓' => '𑢳', '𑣔' => '𑢴', '𑣕' => '𑢵', '𑣖' => '𑢶', '𑣗' => '𑢷', '𑣘' => '𑢸', '𑣙' => '𑢹', '𑣚' => '𑢺', '𑣛' => '𑢻', '𑣜' => '𑢼', '𑣝' => '𑢽', '𑣞' => '𑢾', '𑣟' => '𑢿', '𖹠' => '𖹀', '𖹡' => '𖹁', '𖹢' => '𖹂', '𖹣' => '𖹃', '𖹤' => '𖹄', '𖹥' => '𖹅', '𖹦' => '𖹆', '𖹧' => '𖹇', '𖹨' => '𖹈', '𖹩' => '𖹉', '𖹪' => '𖹊', '𖹫' => '𖹋', '𖹬' => '𖹌', '𖹭' => '𖹍', '𖹮' => '𖹎', '𖹯' => '𖹏', '𖹰' => '𖹐', '𖹱' => '𖹑', '𖹲' => '𖹒', '𖹳' => '𖹓', '𖹴' => '𖹔', '𖹵' => '𖹕', '𖹶' => '𖹖', '𖹷' => '𖹗', '𖹸' => '𖹘', '𖹹' => '𖹙', '𖹺' => '𖹚', '𖹻' => '𖹛', '𖹼' => '𖹜', '𖹽' => '𖹝', '𖹾' => '𖹞', '𖹿' => '𖹟', '𞤢' => '𞤀', '𞤣' => '𞤁', '𞤤' => '𞤂', '𞤥' => '𞤃', '𞤦' => '𞤄', '𞤧' => '𞤅', '𞤨' => '𞤆', '𞤩' => '𞤇', '𞤪' => '𞤈', '𞤫' => '𞤉', '𞤬' => '𞤊', '𞤭' => '𞤋', '𞤮' => '𞤌', '𞤯' => '𞤍', '𞤰' => '𞤎', '𞤱' => '𞤏', '𞤲' => '𞤐', '𞤳' => '𞤑', '𞤴' => '𞤒', '𞤵' => '𞤓', '𞤶' => '𞤔', '𞤷' => '𞤕', '𞤸' => '𞤖', '𞤹' => '𞤗', '𞤺' => '𞤘', '𞤻' => '𞤙', '𞤼' => '𞤚', '𞤽' => '𞤛', '𞤾' => '𞤜', '𞤿' => '𞤝', '𞥀' => '𞤞', '𞥁' => '𞤟', '𞥂' => '𞤠', '𞥃' => '𞤡', 'ß' => 'SS', 'ﬀ' => 'FF', 'ﬁ' => 'FI', 'ﬂ' => 'FL', 'ﬃ' => 'FFI', 'ﬄ' => 'FFL', 'ﬅ' => 'ST', 'ﬆ' => 'ST', 'և' => 'ԵՒ', 'ﬓ' => 'ՄՆ', 'ﬔ' => 'ՄԵ', 'ﬕ' => 'ՄԻ', 'ﬖ' => 'ՎՆ', 'ﬗ' => 'ՄԽ', 'ŉ' => 'ʼN', 'ΐ' => 'Ϊ́', 'ΰ' => 'Ϋ́', 'ǰ' => 'J̌', 'ẖ' => 'H̱', 'ẗ' => 'T̈', 'ẘ' => 'W̊', 'ẙ' => 'Y̊', 'ẚ' => 'Aʾ', 'ὐ' => 'Υ̓', 'ὒ' => 'Υ̓̀', 'ὔ' => 'Υ̓́', 'ὖ' => 'Υ̓͂', 'ᾶ' => 'Α͂', 'ῆ' => 'Η͂', 'ῒ' => 'Ϊ̀', 'ΐ' => 'Ϊ́', 'ῖ' => 'Ι͂', 'ῗ' => 'Ϊ͂', 'ῢ' => 'Ϋ̀', 'ΰ' => 'Ϋ́', 'ῤ' => 'Ρ̓', 'ῦ' => 'Υ͂', 'ῧ' => 'Ϋ͂', 'ῶ' => 'Ω͂', 'ᾈ' => 'ἈΙ', 'ᾉ' => 'ἉΙ', 'ᾊ' => 'ἊΙ', 'ᾋ' => 'ἋΙ', 'ᾌ' => 'ἌΙ', 'ᾍ' => 'ἍΙ', 'ᾎ' => 'ἎΙ', 'ᾏ' => 'ἏΙ', 'ᾘ' => 'ἨΙ', 'ᾙ' => 'ἩΙ', 'ᾚ' => 'ἪΙ', 'ᾛ' => 'ἫΙ', 'ᾜ' => 'ἬΙ', 'ᾝ' => 'ἭΙ', 'ᾞ' => 'ἮΙ', 'ᾟ' => 'ἯΙ', 'ᾨ' => 'ὨΙ', 'ᾩ' => 'ὩΙ', 'ᾪ' => 'ὪΙ', 'ᾫ' => 'ὫΙ', 'ᾬ' => 'ὬΙ', 'ᾭ' => 'ὭΙ', 'ᾮ' => 'ὮΙ', 'ᾯ' => 'ὯΙ', 'ᾼ' => 'ΑΙ', 'ῌ' => 'ΗΙ', 'ῼ' => 'ΩΙ', 'ᾲ' => 'ᾺΙ', 'ᾴ' => 'ΆΙ', 'ῂ' => 'ῊΙ', 'ῄ' => 'ΉΙ', 'ῲ' => 'ῺΙ', 'ῴ' => 'ΏΙ', 'ᾷ' => 'Α͂Ι', 'ῇ' => 'Η͂Ι', 'ῷ' => 'Ω͂Ι');
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Symfony\Polyfill\Mbstring;

/**
 * Partial mbstring implementation in PHP, iconv based, UTF-8 centric.
 *
 * Implemented:
 * - mb_chr                  - Returns a specific character from its Unicode code point
 * - mb_convert_encoding     - Convert character encoding
 * - mb_convert_variables    - Convert character code in variable(s)
 * - mb_decode_mimeheader    - Decode string in MIME header field
 * - mb_encode_mimeheader    - Encode string for MIME header XXX NATIVE IMPLEMENTATION IS REALLY BUGGED
 * - mb_decode_numericentity - Decode HTML numeric string reference to character
 * - mb_encode_numericentity - Encode character to HTML numeric string reference
 * - mb_convert_case         - Perform case folding on a string
 * - mb_detect_encoding      - Detect character encoding
 * - mb_get_info             - Get internal settings of mbstring
 * - mb_http_input           - Detect HTTP input character encoding
 * - mb_http_output          - Set/Get HTTP output character encoding
 * - mb_internal_encoding    - Set/Get internal character encoding
 * - mb_list_encodings       - Returns an array of all supported encodings
 * - mb_ord                  - Returns the Unicode code point of a character
 * - mb_output_handler       - Callback function converts character encoding in output buffer
 * - mb_scrub                - Replaces ill-formed byte sequences with substitute characters
 * - mb_strlen               - Get string length
 * - mb_strpos               - Find position of first occurrence of string in a string
 * - mb_strrpos              - Find position of last occurrence of a string in a string
 * - mb_str_split            - Convert a string to an array
 * - mb_strtolower           - Make a string lowercase
 * - mb_strtoupper           - Make a string uppercase
 * - mb_substitute_character - Set/Get substitution character
 * - mb_substr               - Get part of string
 * - mb_stripos              - Finds position of first occurrence of a string within another, case insensitive
 * - mb_stristr              - Finds first occurrence of a string within another, case insensitive
 * - mb_strrchr              - Finds the last occurrence of a character in a string within another
 * - mb_strrichr             - Finds the last occurrence of a character in a string within another, case insensitive
 * - mb_strripos             - Finds position of last occurrence of a string within another, case insensitive
 * - mb_strstr               - Finds first occurrence of a string within another
 * - mb_strwidth             - Return width of string
 * - mb_substr_count         - Count the number of substring occurrences
 * - mb_ucfirst              - Make a string's first character uppercase
 * - mb_lcfirst              - Make a string's first character lowercase
 * - mb_trim                 - Strip whitespace (or other characters) from the beginning and end of a string
 * - mb_ltrim                - Strip whitespace (or other characters) from the beginning of a string
 * - mb_rtrim                - Strip whitespace (or other characters) from the end of a string
 *
 * Not implemented:
 * - mb_convert_kana         - Convert "kana" one from another ("zen-kaku", "han-kaku" and more)
 * - mb_ereg_*               - Regular expression with multibyte support
 * - mb_parse_str            - Parse GET/POST/COOKIE data and set global variable
 * - mb_preferred_mime_name  - Get MIME charset string
 * - mb_regex_encoding       - Returns current encoding for multibyte regex as string
 * - mb_regex_set_options    - Set/Get the default options for mbregex functions
 * - mb_send_mail            - Send encoded mail
 * - mb_split                - Split multibyte string using regular expression
 * - mb_strcut               - Get part of string
 * - mb_strimwidth           - Get truncated string with specified width
 *
 * @author Nicolas Grekas <p@tchwork.com>
 *
 * @internal
 */
final class Mbstring
{
    public const MB_CASE_FOLD = \PHP_INT_MAX;
    private const SIMPLE_CASE_FOLD = [['µ', 'ſ', "ͅ", 'ς', "ϐ", "ϑ", "ϕ", "ϖ", "ϰ", "ϱ", "ϵ", "ẛ", "ι"], ['μ', 's', 'ι', 'σ', 'β', 'θ', 'φ', 'π', 'κ', 'ρ', 'ε', "ṡ", 'ι']];
    private static $encodingList = ['ASCII', 'UTF-8'];
    private static $language = 'neutral';
    private static $internalEncoding = 'UTF-8';
    public static function mb_convert_encoding($s, $toEncoding, $fromEncoding = null)
    {
        if (\is_array($s)) {
            $r = [];
            foreach ($s as $str) {
                $r[] = self::mb_convert_encoding($str, $toEncoding, $fromEncoding);
            }
            return $r;
        }
        if (\is_array($fromEncoding) || null !== $fromEncoding && \false !== strpos($fromEncoding, ',')) {
            $fromEncoding = self::mb_detect_encoding($s, $fromEncoding);
        } else {
            $fromEncoding = self::getEncoding($fromEncoding);
        }
        $toEncoding = self::getEncoding($toEncoding);
        if ('BASE64' === $fromEncoding) {
            $s = base64_decode($s);
            $fromEncoding = $toEncoding;
        }
        if ('BASE64' === $toEncoding) {
            return base64_encode($s);
        }
        if ('HTML-ENTITIES' === $toEncoding || 'HTML' === $toEncoding) {
            if ('HTML-ENTITIES' === $fromEncoding || 'HTML' === $fromEncoding) {
                $fromEncoding = 'Windows-1252';
            }
            if ('UTF-8' !== $fromEncoding) {
                $s = iconv($fromEncoding, 'UTF-8//IGNORE', $s);
            }
            return preg_replace_callback('/[\x80-\xFF]+/', [__CLASS__, 'html_encoding_callback'], $s);
        }
        if ('HTML-ENTITIES' === $fromEncoding) {
            $s = html_entity_decode($s, \ENT_COMPAT, 'UTF-8');
            $fromEncoding = 'UTF-8';
        }
        return iconv($fromEncoding, $toEncoding . '//IGNORE', $s);
    }
    public static function mb_convert_variables($toEncoding, $fromEncoding, &...$vars)
    {
        $ok = \true;
        array_walk_recursive($vars, static function (&$v) use (&$ok, $toEncoding, $fromEncoding) {
            if (\false === $v = self::mb_convert_encoding($v, $toEncoding, $fromEncoding)) {
                $ok = \false;
            }
        });
        return $ok ? $fromEncoding : \false;
    }
    public static function mb_decode_mimeheader($s)
    {
        return iconv_mime_decode($s, 2, self::$internalEncoding);
    }
    public static function mb_encode_mimeheader($s, $charset = null, $transferEncoding = null, $linefeed = null, $indent = null)
    {
        trigger_error('mb_encode_mimeheader() is bugged. Please use iconv_mime_encode() instead', \E_USER_WARNING);
    }
    public static function mb_decode_numericentity($s, $convmap, $encoding = null)
    {
        if (null !== $s && !\is_scalar($s) && !(\is_object($s) && method_exists($s, '__toString'))) {
            trigger_error('mb_decode_numericentity() expects parameter 1 to be string, ' . \gettype($s) . ' given', \E_USER_WARNING);
            return null;
        }
        if (!\is_array($convmap) || 80000 > \PHP_VERSION_ID && !$convmap) {
            return \false;
        }
        if (null !== $encoding && !\is_scalar($encoding)) {
            trigger_error('mb_decode_numericentity() expects parameter 3 to be string, ' . \gettype($s) . ' given', \E_USER_WARNING);
            return '';
            // Instead of null (cf. mb_encode_numericentity).
        }
        $s = (string) $s;
        if ('' === $s) {
            return '';
        }
        $encoding = self::getEncoding($encoding);
        if ('UTF-8' === $encoding) {
            $encoding = null;
            if (!preg_match('//u', $s)) {
                $s = @iconv('UTF-8', 'UTF-8//IGNORE', $s);
            }
        } else {
            $s = iconv($encoding, 'UTF-8//IGNORE', $s);
        }
        $cnt = floor(\count($convmap) / 4) * 4;
        for ($i = 0; $i < $cnt; $i += 4) {
            // collector_decode_htmlnumericentity ignores $convmap[$i + 3]
            $convmap[$i] += $convmap[$i + 2];
            $convmap[$i + 1] += $convmap[$i + 2];
        }
        $s = preg_replace_callback('/&#(?:0*([0-9]+)|x0*([0-9a-fA-F]+))' . (\PHP_VERSION_ID >= 80200 ? '' : '(?!&)') . ';?/', static function (array $m) use ($cnt, $convmap) {
            $c = isset($m[2]) ? (int) hexdec($m[2]) : $m[1];
            for ($i = 0; $i < $cnt; $i += 4) {
                if ($c >= $convmap[$i] && $c <= $convmap[$i + 1]) {
                    return self::mb_chr($c - $convmap[$i + 2]);
                }
            }
            return $m[0];
        }, $s);
        if (null === $encoding) {
            return $s;
        }
        return iconv('UTF-8', $encoding . '//IGNORE', $s);
    }
    public static function mb_encode_numericentity($s, $convmap, $encoding = null, $is_hex = \false)
    {
        if (null !== $s && !\is_scalar($s) && !(\is_object($s) && method_exists($s, '__toString'))) {
            trigger_error('mb_encode_numericentity() expects parameter 1 to be string, ' . \gettype($s) . ' given', \E_USER_WARNING);
            return null;
        }
        if (!\is_array($convmap) || 80000 > \PHP_VERSION_ID && !$convmap) {
            return \false;
        }
        if (null !== $encoding && !\is_scalar($encoding)) {
            trigger_error('mb_encode_numericentity() expects parameter 3 to be string, ' . \gettype($s) . ' given', \E_USER_WARNING);
            return null;
            // Instead of '' (cf. mb_decode_numericentity).
        }
        if (null !== $is_hex && !\is_scalar($is_hex)) {
            trigger_error('mb_encode_numericentity() expects parameter 4 to be boolean, ' . \gettype($s) . ' given', \E_USER_WARNING);
            return null;
        }
        $s = (string) $s;
        if ('' === $s) {
            return '';
        }
        $encoding = self::getEncoding($encoding);
        if ('UTF-8' === $encoding) {
            $encoding = null;
            if (!preg_match('//u', $s)) {
                $s = @iconv('UTF-8', 'UTF-8//IGNORE', $s);
            }
        } else {
            $s = iconv($encoding, 'UTF-8//IGNORE', $s);
        }
        static $ulenMask = ["\xc0" => 2, "\xd0" => 2, "\xe0" => 3, "\xf0" => 4];
        $cnt = floor(\count($convmap) / 4) * 4;
        $i = 0;
        $len = \strlen($s);
        $result = '';
        while ($i < $len) {
            $ulen = $s[$i] < "\x80" ? 1 : $ulenMask[$s[$i] & "\xf0"];
            $uchr = substr($s, $i, $ulen);
            $i += $ulen;
            $c = self::mb_ord($uchr);
            for ($j = 0; $j < $cnt; $j += 4) {
                if ($c >= $convmap[$j] && $c <= $convmap[$j + 1]) {
                    $cOffset = $c + $convmap[$j + 2] & $convmap[$j + 3];
                    $result .= $is_hex ? \sprintf('&#x%X;', $cOffset) : '&#' . $cOffset . ';';
                    continue 2;
                }
            }
            $result .= $uchr;
        }
        if (null === $encoding) {
            return $result;
        }
        return iconv('UTF-8', $encoding . '//IGNORE', $result);
    }
    public static function mb_convert_case($s, $mode, $encoding = null)
    {
        $s = (string) $s;
        if ('' === $s) {
            return '';
        }
        $encoding = self::getEncoding($encoding);
        if ('UTF-8' === $encoding) {
            $encoding = null;
            if (!preg_match('//u', $s)) {
                $s = @iconv('UTF-8', 'UTF-8//IGNORE', $s);
            }
        } else {
            $s = iconv($encoding, 'UTF-8//IGNORE', $s);
        }
        if (\MB_CASE_TITLE == $mode) {
            static $titleRegexp = null;
            if (null === $titleRegexp) {
                $titleRegexp = self::getData('titleCaseRegexp');
            }
            $s = preg_replace_callback($titleRegexp, [__CLASS__, 'title_case'], $s);
        } else {
            if (\MB_CASE_UPPER == $mode) {
                static $upper = null;
                if (null === $upper) {
                    $upper = self::getData('upperCase');
                }
                $map = $upper;
            } else {
                if (self::MB_CASE_FOLD === $mode) {
                    static $caseFolding = null;
                    if (null === $caseFolding) {
                        $caseFolding = self::getData('caseFolding');
                    }
                    $s = strtr($s, $caseFolding);
                }
                static $lower = null;
                if (null === $lower) {
                    $lower = self::getData('lowerCase');
                }
                $map = $lower;
            }
            static $ulenMask = ["\xc0" => 2, "\xd0" => 2, "\xe0" => 3, "\xf0" => 4];
            $i = 0;
            $len = \strlen($s);
            while ($i < $len) {
                $ulen = $s[$i] < "\x80" ? 1 : $ulenMask[$s[$i] & "\xf0"];
                $uchr = substr($s, $i, $ulen);
                $i += $ulen;
                if (isset($map[$uchr])) {
                    $uchr = $map[$uchr];
                    $nlen = \strlen($uchr);
                    if ($nlen == $ulen) {
                        $nlen = $i;
                        do {
                            $s[--$nlen] = $uchr[--$ulen];
                        } while ($ulen);
                    } else {
                        $s = substr_replace($s, $uchr, $i - $ulen, $ulen);
                        $len += $nlen - $ulen;
                        $i += $nlen - $ulen;
                    }
                }
            }
        }
        if (null === $encoding) {
            return $s;
        }
        return iconv('UTF-8', $encoding . '//IGNORE', $s);
    }
    public static function mb_internal_encoding($encoding = null)
    {
        if (null === $encoding) {
            return self::$internalEncoding;
        }
        $normalizedEncoding = self::getEncoding($encoding);
        if ('UTF-8' === $normalizedEncoding || \false !== @iconv($normalizedEncoding, $normalizedEncoding, ' ')) {
            self::$internalEncoding = $normalizedEncoding;
            return \true;
        }
        if (80000 > \PHP_VERSION_ID) {
            return \false;
        }
        throw new \ValueError(\sprintf('Argument #1 ($encoding) must be a valid encoding, "%s" given', $encoding));
    }
    public static function mb_language($lang = null)
    {
        if (null === $lang) {
            return self::$language;
        }
        switch ($normalizedLang = strtolower($lang)) {
            case 'uni':
            case 'neutral':
                self::$language = $normalizedLang;
                return \true;
        }
        if (80000 > \PHP_VERSION_ID) {
            return \false;
        }
        throw new \ValueError(\sprintf('Argument #1 ($language) must be a valid language, "%s" given', $lang));
    }
    public static function mb_list_encodings()
    {
        return ['UTF-8'];
    }
    public static function mb_encoding_aliases($encoding)
    {
        switch (strtoupper($encoding)) {
            case 'UTF8':
            case 'UTF-8':
                return ['utf8'];
        }
        return \false;
    }
    public static function mb_check_encoding($var = null, $encoding = null)
    {
        if (null === $encoding) {
            if (null === $var) {
                return \false;
            }
            $encoding = self::$internalEncoding;
        }
        if (!\is_array($var)) {
            return self::mb_detect_encoding($var, [$encoding]) || \false !== @iconv($encoding, $encoding, $var);
        }
        foreach ($var as $key => $value) {
            if (!self::mb_check_encoding($key, $encoding)) {
                return \false;
            }
            if (!self::mb_check_encoding($value, $encoding)) {
                return \false;
            }
        }
        return \true;
    }
    public static function mb_detect_encoding($str, $encodingList = null, $strict = \false)
    {
        if (null === $encodingList) {
            $encodingList = self::$encodingList;
        } else {
            if (!\is_array($encodingList)) {
                $encodingList = array_map('trim', explode(',', $encodingList));
            }
            $encodingList = array_map('strtoupper', $encodingList);
        }
        foreach ($encodingList as $enc) {
            switch ($enc) {
                case 'ASCII':
                    if (!preg_match('/[\x80-\xFF]/', $str)) {
                        return $enc;
                    }
                    break;
                case 'UTF8':
                case 'UTF-8':
                    if (preg_match('//u', $str)) {
                        return 'UTF-8';
                    }
                    break;
                default:
                    if (0 === strncmp($enc, 'ISO-8859-', 9)) {
                        return $enc;
                    }
            }
        }
        return \false;
    }
    public static function mb_detect_order($encodingList = null)
    {
        if (null === $encodingList) {
            return self::$encodingList;
        }
        if (!\is_array($encodingList)) {
            $encodingList = array_map('trim', explode(',', $encodingList));
        }
        $encodingList = array_map('strtoupper', $encodingList);
        foreach ($encodingList as $enc) {
            switch ($enc) {
                default:
                    if (strncmp($enc, 'ISO-8859-', 9)) {
                        return \false;
                    }
                // no break
                case 'ASCII':
                case 'UTF8':
                case 'UTF-8':
            }
        }
        self::$encodingList = $encodingList;
        return \true;
    }
    public static function mb_strlen($s, $encoding = null)
    {
        $encoding = self::getEncoding($encoding);
        if ('CP850' === $encoding || 'ASCII' === $encoding) {
            return \strlen($s);
        }
        return @iconv_strlen($s, $encoding);
    }
    public static function mb_strpos($haystack, $needle, $offset = 0, $encoding = null)
    {
        $encoding = self::getEncoding($encoding);
        if ('CP850' === $encoding || 'ASCII' === $encoding) {
            return strpos($haystack, $needle, $offset);
        }
        $needle = (string) $needle;
        if ('' === $needle) {
            if (80000 > \PHP_VERSION_ID) {
                trigger_error(__METHOD__ . ': Empty delimiter', \E_USER_WARNING);
                return \false;
            }
            return 0;
        }
        return iconv_strpos($haystack, $needle, $offset, $encoding);
    }
    public static function mb_strrpos($haystack, $needle, $offset = 0, $encoding = null)
    {
        $encoding = self::getEncoding($encoding);
        if ('CP850' === $encoding || 'ASCII' === $encoding) {
            return strrpos($haystack, $needle, $offset);
        }
        if ($offset != (int) $offset) {
            $offset = 0;
        } elseif ($offset = (int) $offset) {
            if ($offset < 0) {
                if (0 > $offset += self::mb_strlen($needle)) {
                    $haystack = self::mb_substr($haystack, 0, $offset, $encoding);
                }
                $offset = 0;
            } else {
                $haystack = self::mb_substr($haystack, $offset, 2147483647, $encoding);
            }
        }
        $pos = '' !== $needle || 80000 > \PHP_VERSION_ID ? iconv_strrpos($haystack, $needle, $encoding) : self::mb_strlen($haystack, $encoding);
        return \false !== $pos ? $offset + $pos : \false;
    }
    public static function mb_str_split($string, $split_length = 1, $encoding = null)
    {
        if (null !== $string && !\is_scalar($string) && !(\is_object($string) && method_exists($string, '__toString'))) {
            trigger_error('mb_str_split() expects parameter 1 to be string, ' . \gettype($string) . ' given', \E_USER_WARNING);
            return null;
        }
        if (1 > $split_length = (int) $split_length) {
            if (80000 > \PHP_VERSION_ID) {
                trigger_error('The length of each segment must be greater than zero', \E_USER_WARNING);
                return \false;
            }
            throw new \ValueError('Argument #2 ($length) must be greater than 0');
        }
        if (null === $encoding) {
            $encoding = mb_internal_encoding();
        }
        if ('UTF-8' === $encoding = self::getEncoding($encoding)) {
            $rx = '/(';
            while (65535 < $split_length) {
                $rx .= '.{65535}';
                $split_length -= 65535;
            }
            $rx .= '.{' . $split_length . '})/us';
            return preg_split($rx, $string, -1, \PREG_SPLIT_DELIM_CAPTURE | \PREG_SPLIT_NO_EMPTY);
        }
        $result = [];
        $length = mb_strlen($string, $encoding);
        for ($i = 0; $i < $length; $i += $split_length) {
            $result[] = mb_substr($string, $i, $split_length, $encoding);
        }
        return $result;
    }
    public static function mb_strtolower($s, $encoding = null)
    {
        return self::mb_convert_case($s, \MB_CASE_LOWER, $encoding);
    }
    public static function mb_strtoupper($s, $encoding = null)
    {
        return self::mb_convert_case($s, \MB_CASE_UPPER, $encoding);
    }
    public static function mb_substitute_character($c = null)
    {
        if (null === $c) {
            return 'none';
        }
        if (0 === strcasecmp($c, 'none')) {
            return \true;
        }
        if (80000 > \PHP_VERSION_ID) {
            return \false;
        }
        if (\is_int($c) || 'long' === $c || 'entity' === $c) {
            return \false;
        }
        throw new \ValueError('Argument #1 ($substitute_character) must be "none", "long", "entity" or a valid codepoint');
    }
    public static function mb_substr($s, $start, $length = null, $encoding = null)
    {
        $encoding = self::getEncoding($encoding);
        if ('CP850' === $encoding || 'ASCII' === $encoding) {
            return (string) substr($s, $start, null === $length ? 2147483647 : $length);
        }
        if ($start < 0) {
            $start = iconv_strlen($s, $encoding) + $start;
            if ($start < 0) {
                $start = 0;
            }
        }
        if (null === $length) {
            $length = 2147483647;
        } elseif ($length < 0) {
            $length = iconv_strlen($s, $encoding) + $length - $start;
            if ($length < 0) {
                return '';
            }
        }
        return (string) iconv_substr($s, $start, $length, $encoding);
    }
    public static function mb_stripos($haystack, $needle, $offset = 0, $encoding = null)
    {
        [$haystack, $needle] = str_replace(self::SIMPLE_CASE_FOLD[0], self::SIMPLE_CASE_FOLD[1], [self::mb_convert_case($haystack, \MB_CASE_LOWER, $encoding), self::mb_convert_case($needle, \MB_CASE_LOWER, $encoding)]);
        return self::mb_strpos($haystack, $needle, $offset, $encoding);
    }
    public static function mb_stristr($haystack, $needle, $part = \false, $encoding = null)
    {
        $pos = self::mb_stripos($haystack, $needle, 0, $encoding);
        return self::getSubpart($pos, $part, $haystack, $encoding);
    }
    public static function mb_strrchr($haystack, $needle, $part = \false, $encoding = null)
    {
        $encoding = self::getEncoding($encoding);
        if ('CP850' === $encoding || 'ASCII' === $encoding) {
            $pos = strrpos($haystack, $needle);
        } else {
            $needle = self::mb_substr($needle, 0, 1, $encoding);
            $pos = iconv_strrpos($haystack, $needle, $encoding);
        }
        return self::getSubpart($pos, $part, $haystack, $encoding);
    }
    public static function mb_strrichr($haystack, $needle, $part = \false, $encoding = null)
    {
        $needle = self::mb_substr($needle, 0, 1, $encoding);
        $pos = self::mb_strripos($haystack, $needle, $encoding);
        return self::getSubpart($pos, $part, $haystack, $encoding);
    }
    public static function mb_strripos($haystack, $needle, $offset = 0, $encoding = null)
    {
        $haystack = self::mb_convert_case($haystack, \MB_CASE_LOWER, $encoding);
        $needle = self::mb_convert_case($needle, \MB_CASE_LOWER, $encoding);
        $haystack = str_replace(self::SIMPLE_CASE_FOLD[0], self::SIMPLE_CASE_FOLD[1], $haystack);
        $needle = str_replace(self::SIMPLE_CASE_FOLD[0], self::SIMPLE_CASE_FOLD[1], $needle);
        return self::mb_strrpos($haystack, $needle, $offset, $encoding);
    }
    public static function mb_strstr($haystack, $needle, $part = \false, $encoding = null)
    {
        $pos = strpos($haystack, $needle);
        if (\false === $pos) {
            return \false;
        }
        if ($part) {
            return substr($haystack, 0, $pos);
        }
        return substr($haystack, $pos);
    }
    public static function mb_get_info($type = 'all')
    {
        $info = ['internal_encoding' => self::$internalEncoding, 'http_output' => 'pass', 'http_output_conv_mimetypes' => '^(text/|application/xhtml\+xml)', 'func_overload' => 0, 'func_overload_list' => 'no overload', 'mail_charset' => 'UTF-8', 'mail_header_encoding' => 'BASE64', 'mail_body_encoding' => 'BASE64', 'illegal_chars' => 0, 'encoding_translation' => 'Off', 'language' => self::$language, 'detect_order' => self::$encodingList, 'substitute_character' => 'none', 'strict_detection' => 'Off'];
        if ('all' === $type) {
            return $info;
        }
        if (isset($info[$type])) {
            return $info[$type];
        }
        return \false;
    }
    public static function mb_http_input($type = '')
    {
        return \false;
    }
    public static function mb_http_output($encoding = null)
    {
        return null !== $encoding ? 'pass' === $encoding : 'pass';
    }
    public static function mb_strwidth($s, $encoding = null)
    {
        $encoding = self::getEncoding($encoding);
        if ('UTF-8' !== $encoding) {
            $s = iconv($encoding, 'UTF-8//IGNORE', $s);
        }
        $s = preg_replace('/[\x{1100}-\x{115F}\x{2329}\x{232A}\x{2E80}-\x{303E}\x{3040}-\x{A4CF}\x{AC00}-\x{D7A3}\x{F900}-\x{FAFF}\x{FE10}-\x{FE19}\x{FE30}-\x{FE6F}\x{FF00}-\x{FF60}\x{FFE0}-\x{FFE6}\x{20000}-\x{2FFFD}\x{30000}-\x{3FFFD}]/u', '', $s, -1, $wide);
        return ($wide << 1) + iconv_strlen($s, 'UTF-8');
    }
    public static function mb_substr_count($haystack, $needle, $encoding = null)
    {
        return substr_count($haystack, $needle);
    }
    public static function mb_output_handler($contents, $status)
    {
        return $contents;
    }
    public static function mb_chr($code, $encoding = null)
    {
        if (0x80 > $code %= 0x200000) {
            $s = \chr($code);
        } elseif (0x800 > $code) {
            $s = \chr(0xc0 | $code >> 6) . \chr(0x80 | $code & 0x3f);
        } elseif (0x10000 > $code) {
            $s = \chr(0xe0 | $code >> 12) . \chr(0x80 | $code >> 6 & 0x3f) . \chr(0x80 | $code & 0x3f);
        } else {
            $s = \chr(0xf0 | $code >> 18) . \chr(0x80 | $code >> 12 & 0x3f) . \chr(0x80 | $code >> 6 & 0x3f) . \chr(0x80 | $code & 0x3f);
        }
        if ('UTF-8' !== $encoding = self::getEncoding($encoding)) {
            $s = mb_convert_encoding($s, $encoding, 'UTF-8');
        }
        return $s;
    }
    public static function mb_ord($s, $encoding = null)
    {
        if ('UTF-8' !== $encoding = self::getEncoding($encoding)) {
            $s = mb_convert_encoding($s, 'UTF-8', $encoding);
        }
        if (1 === \strlen($s)) {
            return \ord($s);
        }
        $code = ($s = unpack('C*', substr($s, 0, 4))) ? $s[1] : 0;
        if (0xf0 <= $code) {
            return ($code - 0xf0 << 18) + ($s[2] - 0x80 << 12) + ($s[3] - 0x80 << 6) + $s[4] - 0x80;
        }
        if (0xe0 <= $code) {
            return ($code - 0xe0 << 12) + ($s[2] - 0x80 << 6) + $s[3] - 0x80;
        }
        if (0xc0 <= $code) {
            return ($code - 0xc0 << 6) + $s[2] - 0x80;
        }
        return $code;
    }
    /** @return string|false */
    public static function mb_str_pad(string $string, int $length, string $pad_string = ' ', int $pad_type = \STR_PAD_RIGHT, ?string $encoding = null)
    {
        if (!\in_array($pad_type, [\STR_PAD_RIGHT, \STR_PAD_LEFT, \STR_PAD_BOTH], \true)) {
            if (\PHP_VERSION_ID < 80000) {
                trigger_error('mb_str_pad(): Argument #4 ($pad_type) must be STR_PAD_LEFT, STR_PAD_RIGHT, or STR_PAD_BOTH', \E_USER_WARNING);
                return \false;
            }
            throw new \ValueError('mb_str_pad(): Argument #4 ($pad_type) must be STR_PAD_LEFT, STR_PAD_RIGHT, or STR_PAD_BOTH');
        }
        if (null === $encoding) {
            $encoding = self::mb_internal_encoding();
        } elseif (!self::assertEncoding($encoding, 'mb_str_pad(): Argument #5 ($encoding) must be a valid encoding, "%s" given')) {
            return \false;
        }
        if (self::mb_strlen($pad_string, $encoding) <= 0) {
            if (\PHP_VERSION_ID < 80000) {
                trigger_error('mb_str_pad(): Argument #3 ($pad_string) must be a non-empty string', \E_USER_WARNING);
                return \false;
            }
            throw new \ValueError('mb_str_pad(): Argument #3 ($pad_string) must be a non-empty string');
        }
        $paddingRequired = $length - self::mb_strlen($string, $encoding);
        if ($paddingRequired < 1) {
            return $string;
        }
        switch ($pad_type) {
            case \STR_PAD_LEFT:
                return self::mb_substr(str_repeat($pad_string, $paddingRequired), 0, $paddingRequired, $encoding) . $string;
            case \STR_PAD_RIGHT:
                return $string . self::mb_substr(str_repeat($pad_string, $paddingRequired), 0, $paddingRequired, $encoding);
            default:
                $leftPaddingLength = floor($paddingRequired / 2);
                $rightPaddingLength = $paddingRequired - $leftPaddingLength;
                return self::mb_substr(str_repeat($pad_string, $leftPaddingLength), 0, $leftPaddingLength, $encoding) . $string . self::mb_substr(str_repeat($pad_string, $rightPaddingLength), 0, $rightPaddingLength, $encoding);
        }
    }
    /** @return string|false */
    public static function mb_ucfirst(string $string, ?string $encoding = null)
    {
        if (null === $encoding) {
            $encoding = self::mb_internal_encoding();
        } elseif (!self::assertEncoding($encoding, 'mb_ucfirst(): Argument #2 ($encoding) must be a valid encoding, "%s" given')) {
            return \false;
        }
        $firstChar = mb_substr($string, 0, 1, $encoding);
        $firstChar = mb_convert_case($firstChar, \MB_CASE_TITLE, $encoding);
        return $firstChar . mb_substr($string, 1, null, $encoding);
    }
    /** @return string|false */
    public static function mb_lcfirst(string $string, ?string $encoding = null)
    {
        if (null === $encoding) {
            $encoding = self::mb_internal_encoding();
        } elseif (!self::assertEncoding($encoding, 'mb_lcfirst(): Argument #2 ($encoding) must be a valid encoding, "%s" given')) {
            return \false;
        }
        $firstChar = mb_substr($string, 0, 1, $encoding);
        $firstChar = mb_convert_case($firstChar, \MB_CASE_LOWER, $encoding);
        return $firstChar . mb_substr($string, 1, null, $encoding);
    }
    private static function getSubpart($pos, $part, $haystack, $encoding)
    {
        if (\false === $pos) {
            return \false;
        }
        if ($part) {
            return self::mb_substr($haystack, 0, $pos, $encoding);
        }
        return self::mb_substr($haystack, $pos, null, $encoding);
    }
    private static function html_encoding_callback(array $m)
    {
        $i = 1;
        $entities = '';
        $m = unpack('C*', htmlentities($m[0], \ENT_COMPAT, 'UTF-8'));
        while (isset($m[$i])) {
            if (0x80 > $m[$i]) {
                $entities .= \chr($m[$i++]);
                continue;
            }
            if (0xf0 <= $m[$i]) {
                $c = ($m[$i++] - 0xf0 << 18) + ($m[$i++] - 0x80 << 12) + ($m[$i++] - 0x80 << 6) + $m[$i++] - 0x80;
            } elseif (0xe0 <= $m[$i]) {
                $c = ($m[$i++] - 0xe0 << 12) + ($m[$i++] - 0x80 << 6) + $m[$i++] - 0x80;
            } else {
                $c = ($m[$i++] - 0xc0 << 6) + $m[$i++] - 0x80;
            }
            $entities .= '&#' . $c . ';';
        }
        return $entities;
    }
    private static function title_case(array $s)
    {
        return self::mb_convert_case($s[1], \MB_CASE_UPPER, 'UTF-8') . self::mb_convert_case($s[2], \MB_CASE_LOWER, 'UTF-8');
    }
    private static function getData($file)
    {
        if (file_exists($file = __DIR__ . '/Resources/unidata/' . $file . '.php')) {
            return require $file;
        }
        return \false;
    }
    private static function getEncoding($encoding)
    {
        if (null === $encoding) {
            return self::$internalEncoding;
        }
        if ('UTF-8' === $encoding) {
            return 'UTF-8';
        }
        $encoding = strtoupper($encoding);
        if ('8BIT' === $encoding || 'BINARY' === $encoding) {
            return 'CP850';
        }
        if ('UTF8' === $encoding) {
            return 'UTF-8';
        }
        if ('UTF-32' === $encoding) {
            return 'UTF-32BE';
        }
        if ('UTF-16' === $encoding) {
            return 'UTF-16BE';
        }
        return $encoding;
    }
    /** @return string|false */
    public static function mb_trim(string $string, ?string $characters = null, ?string $encoding = null)
    {
        return self::mb_internal_trim('{^[%s]+|[%1$s]+$}Du', $string, $characters, $encoding, __FUNCTION__);
    }
    /** @return string|false */
    public static function mb_ltrim(string $string, ?string $characters = null, ?string $encoding = null)
    {
        return self::mb_internal_trim('{^[%s]+}Du', $string, $characters, $encoding, __FUNCTION__);
    }
    /** @return string|false */
    public static function mb_rtrim(string $string, ?string $characters = null, ?string $encoding = null)
    {
        return self::mb_internal_trim('{[%s]+$}Du', $string, $characters, $encoding, __FUNCTION__);
    }
    /** @return string|false */
    private static function mb_internal_trim(string $regex, string $string, ?string $characters, ?string $encoding, string $function)
    {
        if (null === $encoding) {
            $encoding = self::mb_internal_encoding();
        } elseif (!self::assertEncoding($encoding, $function . '(): Argument #3 ($encoding) must be a valid encoding, "%s" given')) {
            return \false;
        }
        if ('' === $characters) {
            return null === $encoding ? $string : self::mb_convert_encoding($string, $encoding);
        }
        if ('UTF-8' === $encoding) {
            $encoding = null;
            if (!preg_match('//u', $string)) {
                $string = @iconv('UTF-8', 'UTF-8//IGNORE', $string);
            }
            if (null !== $characters && !preg_match('//u', $characters)) {
                $characters = @iconv('UTF-8', 'UTF-8//IGNORE', $characters);
            }
        } else {
            $string = iconv($encoding, 'UTF-8//IGNORE', $string);
            if (null !== $characters) {
                $characters = iconv($encoding, 'UTF-8//IGNORE', $characters);
            }
        }
        if (null === $characters) {
            $characters = "\\0 \f\n\r\t\v                 　᠎";
        } else {
            $characters = preg_quote($characters);
        }
        $string = preg_replace(\sprintf($regex, $characters), '', $string);
        if (null === $encoding) {
            return $string;
        }
        return iconv('UTF-8', $encoding . '//IGNORE', $string);
    }
    private static function assertEncoding(string $encoding, string $errorFormat): bool
    {
        try {
            $validEncoding = @self::mb_check_encoding('', $encoding);
        } catch (\ValueError $e) {
            throw new \ValueError(\sprintf($errorFormat, $encoding));
        }
        if (!$validEncoding) {
            if (80000 > \PHP_VERSION_ID) {
                trigger_error(\sprintf($errorFormat, $encoding), \E_USER_WARNING);
            } else {
                throw new \ValueError(\sprintf($errorFormat, $encoding));
            }
        }
        return $validEncoding;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

use Symfony\Polyfill\Mbstring as p;

if (\PHP_VERSION_ID >= 80000) {
    return require __DIR__.'/bootstrap80.php';
}

if (!function_exists('mb_convert_encoding')) {
    function mb_convert_encoding($string, $to_encoding, $from_encoding = null) { return p\Mbstring::mb_convert_encoding($string, $to_encoding, $from_encoding); }
}
if (!function_exists('mb_decode_mimeheader')) {
    function mb_decode_mimeheader($string) { return p\Mbstring::mb_decode_mimeheader($string); }
}
if (!function_exists('mb_encode_mimeheader')) {
    function mb_encode_mimeheader($string, $charset = null, $transfer_encoding = null, $newline = "\r\n", $indent = 0) { return p\Mbstring::mb_encode_mimeheader($string, $charset, $transfer_encoding, $newline, $indent); }
}
if (!function_exists('mb_decode_numericentity')) {
    function mb_decode_numericentity($string, $map, $encoding = null) { return p\Mbstring::mb_decode_numericentity($string, $map, $encoding); }
}
if (!function_exists('mb_encode_numericentity')) {
    function mb_encode_numericentity($string, $map, $encoding = null, $hex = false) { return p\Mbstring::mb_encode_numericentity($string, $map, $encoding, $hex); }
}
if (!function_exists('mb_convert_case')) {
    function mb_convert_case($string, $mode, $encoding = null) { return p\Mbstring::mb_convert_case($string, $mode, $encoding); }
}
if (!function_exists('mb_internal_encoding')) {
    function mb_internal_encoding($encoding = null) { return p\Mbstring::mb_internal_encoding($encoding); }
}
if (!function_exists('mb_language')) {
    function mb_language($language = null) { return p\Mbstring::mb_language($language); }
}
if (!function_exists('mb_list_encodings')) {
    function mb_list_encodings() { return p\Mbstring::mb_list_encodings(); }
}
if (!function_exists('mb_encoding_aliases')) {
    function mb_encoding_aliases($encoding) { return p\Mbstring::mb_encoding_aliases($encoding); }
}
if (!function_exists('mb_check_encoding')) {
    function mb_check_encoding($value = null, $encoding = null) { return p\Mbstring::mb_check_encoding($value, $encoding); }
}
if (!function_exists('mb_detect_encoding')) {
    function mb_detect_encoding($string, $encodings = null, $strict = false) { return p\Mbstring::mb_detect_encoding($string, $encodings, $strict); }
}
if (!function_exists('mb_detect_order')) {
    function mb_detect_order($encoding = null) { return p\Mbstring::mb_detect_order($encoding); }
}
if (!function_exists('mb_parse_str')) {
    function mb_parse_str($string, &$result = []) { parse_str($string, $result); return (bool) $result; }
}
if (!function_exists('mb_strlen')) {
    function mb_strlen($string, $encoding = null) { return p\Mbstring::mb_strlen($string, $encoding); }
}
if (!function_exists('mb_strpos')) {
    function mb_strpos($haystack, $needle, $offset = 0, $encoding = null) { return p\Mbstring::mb_strpos($haystack, $needle, $offset, $encoding); }
}
if (!function_exists('mb_strtolower')) {
    function mb_strtolower($string, $encoding = null) { return p\Mbstring::mb_strtolower($string, $encoding); }
}
if (!function_exists('mb_strtoupper')) {
    function mb_strtoupper($string, $encoding = null) { return p\Mbstring::mb_strtoupper($string, $encoding); }
}
if (!function_exists('mb_substitute_character')) {
    function mb_substitute_character($substitute_character = null) { return p\Mbstring::mb_substitute_character($substitute_character); }
}
if (!function_exists('mb_substr')) {
    function mb_substr($string, $start, $length = 2147483647, $encoding = null) { return p\Mbstring::mb_substr($string, $start, $length, $encoding); }
}
if (!function_exists('mb_stripos')) {
    function mb_stripos($haystack, $needle, $offset = 0, $encoding = null) { return p\Mbstring::mb_stripos($haystack, $needle, $offset, $encoding); }
}
if (!function_exists('mb_stristr')) {
    function mb_stristr($haystack, $needle, $before_needle = false, $encoding = null) { return p\Mbstring::mb_stristr($haystack, $needle, $before_needle, $encoding); }
}
if (!function_exists('mb_strrchr')) {
    function mb_strrchr($haystack, $needle, $before_needle = false, $encoding = null) { return p\Mbstring::mb_strrchr($haystack, $needle, $before_needle, $encoding); }
}
if (!function_exists('mb_strrichr')) {
    function mb_strrichr($haystack, $needle, $before_needle = false, $encoding = null) { return p\Mbstring::mb_strrichr($haystack, $needle, $before_needle, $encoding); }
}
if (!function_exists('mb_strripos')) {
    function mb_strripos($haystack, $needle, $offset = 0, $encoding = null) { return p\Mbstring::mb_strripos($haystack, $needle, $offset, $encoding); }
}
if (!function_exists('mb_strrpos')) {
    function mb_strrpos($haystack, $needle, $offset = 0, $encoding = null) { return p\Mbstring::mb_strrpos($haystack, $needle, $offset, $encoding); }
}
if (!function_exists('mb_strstr')) {
    function mb_strstr($haystack, $needle, $before_needle = false, $encoding = null) { return p\Mbstring::mb_strstr($haystack, $needle, $before_needle, $encoding); }
}
if (!function_exists('mb_get_info')) {
    function mb_get_info($type = 'all') { return p\Mbstring::mb_get_info($type); }
}
if (!function_exists('mb_http_output')) {
    function mb_http_output($encoding = null) { return p\Mbstring::mb_http_output($encoding); }
}
if (!function_exists('mb_strwidth')) {
    function mb_strwidth($string, $encoding = null) { return p\Mbstring::mb_strwidth($string, $encoding); }
}
if (!function_exists('mb_substr_count')) {
    function mb_substr_count($haystack, $needle, $encoding = null) { return p\Mbstring::mb_substr_count($haystack, $needle, $encoding); }
}
if (!function_exists('mb_output_handler')) {
    function mb_output_handler($string, $status) { return p\Mbstring::mb_output_handler($string, $status); }
}
if (!function_exists('mb_http_input')) {
    function mb_http_input($type = null) { return p\Mbstring::mb_http_input($type); }
}

if (!function_exists('mb_convert_variables')) {
    function mb_convert_variables($to_encoding, $from_encoding, &...$vars) { return p\Mbstring::mb_convert_variables($to_encoding, $from_encoding, ...$vars); }
}

if (!function_exists('mb_ord')) {
    function mb_ord($string, $encoding = null) { return p\Mbstring::mb_ord($string, $encoding); }
}
if (!function_exists('mb_chr')) {
    function mb_chr($codepoint, $encoding = null) { return p\Mbstring::mb_chr($codepoint, $encoding); }
}
if (!function_exists('mb_scrub')) {
    function mb_scrub($string, $encoding = null) { $encoding = null === $encoding ? mb_internal_encoding() : $encoding; return mb_convert_encoding($string, $encoding, $encoding); }
}
if (!function_exists('mb_str_split')) {
    function mb_str_split($string, $length = 1, $encoding = null) { return p\Mbstring::mb_str_split($string, $length, $encoding); }
}

if (!function_exists('mb_str_pad')) {
    function mb_str_pad(string $string, int $length, string $pad_string = ' ', int $pad_type = STR_PAD_RIGHT, ?string $encoding = null) { return p\Mbstring::mb_str_pad($string, $length, $pad_string, $pad_type, $encoding); }
}

if (!function_exists('mb_ucfirst')) {
    function mb_ucfirst(string $string, ?string $encoding = null) { return p\Mbstring::mb_ucfirst($string, $encoding); }
}

if (!function_exists('mb_lcfirst')) {
    function mb_lcfirst(string $string, ?string $encoding = null) { return p\Mbstring::mb_lcfirst($string, $encoding); }
}

if (!function_exists('mb_trim')) {
    function mb_trim(string $string, ?string $characters = null, ?string $encoding = null) { return p\Mbstring::mb_trim($string, $characters, $encoding); }
}

if (!function_exists('mb_ltrim')) {
    function mb_ltrim(string $string, ?string $characters = null, ?string $encoding = null) { return p\Mbstring::mb_ltrim($string, $characters, $encoding); }
}

if (!function_exists('mb_rtrim')) {
    function mb_rtrim(string $string, ?string $characters = null, ?string $encoding = null) { return p\Mbstring::mb_rtrim($string, $characters, $encoding); }
}

if (extension_loaded('mbstring')) {
    return;
}

if (!defined('MB_CASE_UPPER')) {
    define('MB_CASE_UPPER', 0);
}
if (!defined('MB_CASE_LOWER')) {
    define('MB_CASE_LOWER', 1);
}
if (!defined('MB_CASE_TITLE')) {
    define('MB_CASE_TITLE', 2);
}
Symfony Polyfill / Mbstring
===========================

This component provides a partial, native PHP implementation for the
[Mbstring](https://php.net/mbstring) extension.

More information can be found in the
[main Polyfill README](https://github.com/symfony/polyfill/blob/main/README.md).

License
=======

This library is released under the [MIT license](LICENSE).
{
    "name": "symfony\/polyfill-mbstring",
    "type": "library",
    "description": "Symfony polyfill for the Mbstring extension",
    "keywords": [
        "polyfill",
        "shim",
        "compatibility",
        "portable",
        "mbstring"
    ],
    "homepage": "https:\/\/symfony.com",
    "license": "MIT",
    "authors": [
        {
            "name": "Nicolas Grekas",
            "email": "p@tchwork.com"
        },
        {
            "name": "Symfony Community",
            "homepage": "https:\/\/symfony.com\/contributors"
        }
    ],
    "require": {
        "php": ">=7.2",
        "ext-iconv": "*"
    },
    "provide": {
        "ext-mbstring": "*"
    },
    "autoload": {
        "psr-4": {
            "Symfony\\Polyfill\\Mbstring\\": ""
        },
        "files": [
            "bootstrap.php"
        ]
    },
    "suggest": {
        "ext-mbstring": "For best performance"
    },
    "minimum-stability": "dev",
    "extra": {
        "thanks": {
            "name": "symfony\/polyfill",
            "url": "https:\/\/github.com\/symfony\/polyfill"
        }
    }
}<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

use Symfony\Polyfill\Intl\Grapheme as p;

if (!function_exists('grapheme_str_split')) {
    function grapheme_str_split(string $string, int $length = 1): array|false { return p\Grapheme::grapheme_str_split($string, $length); }
}
if (!function_exists('grapheme_levenshtein')) {
    function grapheme_levenshtein(string $string1, string $string2, int $insertion_cost = 1, int $replacement_cost = 1, int $deletion_cost = 1, string $locale = ''): int|false { return p\Grapheme::grapheme_levenshtein($string1, $string2, $insertion_cost, $replacement_cost, $deletion_cost); }
}

if (extension_loaded('intl')) {
    return;
}

if (!defined('GRAPHEME_EXTR_COUNT')) {
    define('GRAPHEME_EXTR_COUNT', 0);
}
if (!defined('GRAPHEME_EXTR_MAXBYTES')) {
    define('GRAPHEME_EXTR_MAXBYTES', 1);
}
if (!defined('GRAPHEME_EXTR_MAXCHARS')) {
    define('GRAPHEME_EXTR_MAXCHARS', 2);
}

if (!function_exists('grapheme_extract')) {
    function grapheme_extract(?string $haystack, ?int $size, ?int $type = GRAPHEME_EXTR_COUNT, ?int $offset = 0, &$next = null): string|false { return p\Grapheme::grapheme_extract((string) $haystack, (int) $size, (int) $type, (int) $offset, $next); }
}
if (!function_exists('grapheme_stripos')) {
    function grapheme_stripos(?string $haystack, ?string $needle, ?int $offset = 0): int|false { return p\Grapheme::grapheme_stripos((string) $haystack, (string) $needle, (int) $offset); }
}
if (!function_exists('grapheme_stristr')) {
    function grapheme_stristr(?string $haystack, ?string $needle, ?bool $beforeNeedle = false): string|false { return p\Grapheme::grapheme_stristr((string) $haystack, (string) $needle, (bool) $beforeNeedle); }
}
if (!function_exists('grapheme_strlen')) {
    function grapheme_strlen(?string $string): int|false|null { return p\Grapheme::grapheme_strlen((string) $string); }
}
if (!function_exists('grapheme_strpos')) {
    function grapheme_strpos(?string $haystack, ?string $needle, ?int $offset = 0): int|false { return p\Grapheme::grapheme_strpos((string) $haystack, (string) $needle, (int) $offset); }
}
if (!function_exists('grapheme_strripos')) {
    function grapheme_strripos(?string $haystack, ?string $needle, ?int $offset = 0): int|false { return p\Grapheme::grapheme_strripos((string) $haystack, (string) $needle, (int) $offset); }
}
if (!function_exists('grapheme_strrpos')) {
    function grapheme_strrpos(?string $haystack, ?string $needle, ?int $offset = 0): int|false { return p\Grapheme::grapheme_strrpos((string) $haystack, (string) $needle, (int) $offset); }
}
if (!function_exists('grapheme_strstr')) {
    function grapheme_strstr(?string $haystack, ?string $needle, ?bool $beforeNeedle = false): string|false { return p\Grapheme::grapheme_strstr((string) $haystack, (string) $needle, (bool) $beforeNeedle); }
}
if (!function_exists('grapheme_substr')) {
    function grapheme_substr(?string $string, ?int $offset, ?int $length = null): string|false { return p\Grapheme::grapheme_substr((string) $string, (int) $offset, $length); }
}
Copyright (c) 2015-present Fabien Potencier

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is furnished
to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Symfony\Polyfill\Intl\Grapheme;

\define('SYMFONY_GRAPHEME_CLUSTER_RX', ((float) \PCRE_VERSION < 10 ? (float) \PCRE_VERSION >= 8.32 : (float) \PCRE_VERSION >= 10.39) ? '\X' : \Symfony\Polyfill\Intl\Grapheme\Grapheme::GRAPHEME_CLUSTER_RX);
/**
 * Partial intl implementation in pure PHP.
 *
 * Implemented:
 * - grapheme_extract  - Extract a sequence of grapheme clusters from a text buffer, which must be encoded in UTF-8
 * - grapheme_stripos  - Find position (in grapheme units) of first occurrence of a case-insensitive string
 * - grapheme_stristr  - Returns part of haystack string from the first occurrence of case-insensitive needle to the end of haystack
 * - grapheme_strlen   - Get string length in grapheme units
 * - grapheme_strpos   - Find position (in grapheme units) of first occurrence of a string
 * - grapheme_strripos - Find position (in grapheme units) of last occurrence of a case-insensitive string
 * - grapheme_strrpos  - Find position (in grapheme units) of last occurrence of a string
 * - grapheme_strstr   - Returns part of haystack string from the first occurrence of needle to the end of haystack
 * - grapheme_substr   - Return part of a string
 * - grapheme_str_split - Splits a string into an array of individual or chunks of graphemes
 * - grapheme_levenshtein - Calculate the grapheme-unit Levenshtein distance between two strings
 *
 * @author Nicolas Grekas <p@tchwork.com>
 *
 * @internal
 */
final class Grapheme
{
    // (CRLF|([ZWNJ-ZWJ]|T+|L*(LV?V+|LV|LVT)T*|L+|[^Control])[Extend]*|[Control])
    // This regular expression is a work around for http://bugs.exim.org/1279
    public const GRAPHEME_CLUSTER_RX = '(?:\r\n|(?:[ -~\x{200C}\x{200D}]|[ᆨ-ᇹ]+|[ᄀ-ᅟ]*(?:[가개갸걔거게겨계고과괘괴교구궈궤귀규그긔기까깨꺄꺠꺼께껴꼐꼬꽈꽤꾀꾜꾸꿔꿰뀌뀨끄끠끼나내냐냬너네녀녜노놔놰뇌뇨누눠눼뉘뉴느늬니다대댜댸더데뎌뎨도돠돼되됴두둬뒈뒤듀드듸디따때땨떄떠떼뗘뗴또똬뙈뙤뚀뚜뚸뛔뛰뜌뜨띄띠라래랴럐러레려례로롸뢔뢰료루뤄뤠뤼류르릐리마매먀먜머메며몌모뫄뫠뫼묘무뭐뭬뮈뮤므믜미바배뱌뱨버베벼볘보봐봬뵈뵤부붜붸뷔뷰브븨비빠빼뺘뺴뻐뻬뼈뼤뽀뽜뽸뾔뾰뿌뿨쀄쀠쀼쁘쁴삐사새샤섀서세셔셰소솨쇄쇠쇼수숴쉐쉬슈스싀시싸쌔쌰썌써쎄쎠쎼쏘쏴쐐쐬쑈쑤쒀쒜쒸쓔쓰씌씨아애야얘어에여예오와왜외요우워웨위유으의이자재쟈쟤저제져졔조좌좨죄죠주줘줴쥐쥬즈즤지짜째쨔쨰쩌쩨쪄쪠쪼쫘쫴쬐쬬쭈쭤쮀쮜쮸쯔쯰찌차채챠챼처체쳐쳬초촤쵀최쵸추춰췌취츄츠츼치카캐캬컈커케켜켸코콰쾌쾨쿄쿠쿼퀘퀴큐크킈키타태탸턔터테텨톄토톼퇘퇴툐투퉈퉤튀튜트틔티파패퍄퍠퍼페펴폐포퐈퐤푀표푸풔풰퓌퓨프픠피하해햐햬허헤혀혜호화홰회효후훠훼휘휴흐희히]?[ᅠ-ᆢ]+|[가-힣])[ᆨ-ᇹ]*|[ᄀ-ᅟ]+|[^\p{Cc}\p{Cf}\p{Zl}\p{Zp}])[\p{Mn}\p{Me}\x{09BE}\x{09D7}\x{0B3E}\x{0B57}\x{0BBE}\x{0BD7}\x{0CC2}\x{0CD5}\x{0CD6}\x{0D3E}\x{0D57}\x{0DCF}\x{0DDF}\x{200C}\x{200D}\x{1D165}\x{1D16E}-\x{1D172}]*|[\p{Cc}\p{Cf}\p{Zl}\p{Zp}])';
    private const CASE_FOLD = [['µ', 'ſ', "ͅ", 'ς', "ϐ", "ϑ", "ϕ", "ϖ", "ϰ", "ϱ", "ϵ", "ẛ", "ι"], ['μ', 's', 'ι', 'σ', 'β', 'θ', 'φ', 'π', 'κ', 'ρ', 'ε', "ṡ", 'ι']];
    public static function grapheme_extract($s, $size, $type = \GRAPHEME_EXTR_COUNT, $start = 0, &$next = 0)
    {
        if (0 > $start) {
            $start = \strlen($s) + $start;
        }
        if (!\is_scalar($s)) {
            $hasError = \false;
            set_error_handler(static function () use (&$hasError) {
                $hasError = \true;
            });
            $next = substr($s, $start);
            restore_error_handler();
            if ($hasError) {
                substr($s, $start);
                $s = '';
            } else {
                $s = $next;
            }
        } else {
            $s = substr($s, $start);
        }
        $size = (int) $size;
        $type = (int) $type;
        $start = (int) $start;
        if (\GRAPHEME_EXTR_COUNT !== $type && \GRAPHEME_EXTR_MAXBYTES !== $type && \GRAPHEME_EXTR_MAXCHARS !== $type) {
            if (80000 > \PHP_VERSION_ID) {
                return \false;
            }
            throw new \ValueError('grapheme_extract(): Argument #3 ($type) must be one of GRAPHEME_EXTR_COUNT, GRAPHEME_EXTR_MAXBYTES, or GRAPHEME_EXTR_MAXCHARS');
        }
        if (!isset($s[0]) || 0 > $size || 0 > $start) {
            return \false;
        }
        if (0 === $size) {
            return '';
        }
        $next = $start;
        $s = preg_split('/(' . \SYMFONY_GRAPHEME_CLUSTER_RX . ')/u', "\r\n" . $s, $size + 1, \PREG_SPLIT_NO_EMPTY | \PREG_SPLIT_DELIM_CAPTURE);
        if (!isset($s[1])) {
            return \false;
        }
        $i = 1;
        $ret = '';
        do {
            if (\GRAPHEME_EXTR_COUNT === $type) {
                --$size;
            } elseif (\GRAPHEME_EXTR_MAXBYTES === $type) {
                $size -= \strlen($s[$i]);
            } else {
                $size -= iconv_strlen($s[$i], 'UTF-8//IGNORE');
            }
            if ($size >= 0) {
                $ret .= $s[$i];
            }
        } while (isset($s[++$i]) && $size > 0);
        $next += \strlen($ret);
        return $ret;
    }
    public static function grapheme_strlen($s)
    {
        preg_replace('/' . \SYMFONY_GRAPHEME_CLUSTER_RX . '/u', '', $s, -1, $len);
        return 0 === $len && '' !== $s ? null : $len;
    }
    public static function grapheme_substr($s, $start, $len = null)
    {
        if (null === $len) {
            $len = 2147483647;
        }
        preg_match_all('/' . \SYMFONY_GRAPHEME_CLUSTER_RX . '/u', $s, $s);
        $slen = \count($s[0]);
        $start = (int) $start;
        if (0 > $start) {
            $start += $slen;
        }
        if (0 > $start) {
            if (\PHP_VERSION_ID < 80000) {
                return \false;
            }
            $start = 0;
        }
        if ($start >= $slen) {
            return \PHP_VERSION_ID >= 80000 ? '' : \false;
        }
        $rem = $slen - $start;
        if (0 > $len) {
            $len += $rem;
        }
        if (0 === $len) {
            return '';
        }
        if (0 > $len) {
            return \PHP_VERSION_ID >= 80000 ? '' : \false;
        }
        if ($len > $rem) {
            $len = $rem;
        }
        return implode('', \array_slice($s[0], $start, $len));
    }
    public static function grapheme_strpos($s, $needle, $offset = 0)
    {
        return self::grapheme_position($s, $needle, $offset, 0);
    }
    public static function grapheme_stripos($s, $needle, $offset = 0)
    {
        return self::grapheme_position($s, $needle, $offset, 1);
    }
    public static function grapheme_strrpos($s, $needle, $offset = 0)
    {
        return self::grapheme_position($s, $needle, $offset, 2);
    }
    public static function grapheme_strripos($s, $needle, $offset = 0)
    {
        return self::grapheme_position($s, $needle, $offset, 3);
    }
    public static function grapheme_stristr($s, $needle, $beforeNeedle = \false)
    {
        return mb_stristr($s, $needle, $beforeNeedle, 'UTF-8');
    }
    public static function grapheme_strstr($s, $needle, $beforeNeedle = \false)
    {
        return mb_strstr($s, $needle, $beforeNeedle, 'UTF-8');
    }
    public static function grapheme_str_split($s, $len = 1)
    {
        if (0 > $len || 1073741823 < $len) {
            if (80000 > \PHP_VERSION_ID) {
                return \false;
            }
            throw new \ValueError('grapheme_str_split(): Argument #2 ($length) must be greater than 0 and less than or equal to 1073741823.');
        }
        if ('' === $s) {
            return [];
        }
        if (!preg_match_all('/(' . \SYMFONY_GRAPHEME_CLUSTER_RX . ')/u', $s, $matches)) {
            return \false;
        }
        if (1 === $len) {
            return $matches[0];
        }
        $chunks = array_chunk($matches[0], $len);
        foreach ($chunks as &$chunk) {
            $chunk = implode('', $chunk);
        }
        return $chunks;
    }
    public static function grapheme_levenshtein($s1, $s2, $insertion_cost = 1, $replacement_cost = 1, $deletion_cost = 1)
    {
        if (!preg_match('//u', $s1) || !preg_match('//u', $s2)) {
            return \false;
        }
        if (0 > $insertion_cost || 0 > $replacement_cost || 0 > $deletion_cost) {
            if (80000 > \PHP_VERSION_ID) {
                return \false;
            }
            throw new \ValueError('grapheme_levenshtein(): Argument #3 ($insertion_cost), #4 ($replacement_cost), and #5 ($deletion_cost) must be greater than or equal to 0');
        }
        preg_match_all('/' . \SYMFONY_GRAPHEME_CLUSTER_RX . '/u', $s1, $s1);
        preg_match_all('/' . \SYMFONY_GRAPHEME_CLUSTER_RX . '/u', $s2, $s2);
        $s1 = $s1[0];
        $s2 = $s2[0];
        $l1 = \count($s1);
        $l2 = \count($s2);
        if (0 === $l1) {
            return $l2 * $insertion_cost;
        }
        if (0 === $l2) {
            return $l1 * $deletion_cost;
        }
        $dp = array_fill(0, $l1 + 1, array_fill(0, $l2 + 1, 0));
        for ($i = 1; $i <= $l1; ++$i) {
            $dp[$i][0] = $dp[$i - 1][0] + $deletion_cost;
        }
        for ($j = 1; $j <= $l2; ++$j) {
            $dp[0][$j] = $dp[0][$j - 1] + $insertion_cost;
        }
        for ($i = 1; $i <= $l1; ++$i) {
            for ($j = 1; $j <= $l2; ++$j) {
                $cost = $s1[$i - 1] === $s2[$j - 1] ? 0 : $replacement_cost;
                $dp[$i][$j] = min($dp[$i - 1][$j] + $deletion_cost, $dp[$i][$j - 1] + $insertion_cost, $dp[$i - 1][$j - 1] + $cost);
            }
        }
        return $dp[$l1][$l2];
    }
    private static function grapheme_position($s, $needle, $offset, $mode)
    {
        $needle = (string) $needle;
        if (80000 > \PHP_VERSION_ID && !preg_match('/./us', $needle)) {
            return \false;
        }
        $s = (string) $s;
        if (!preg_match('/./us', $s)) {
            return \false;
        }
        if ($offset > 0) {
            $s = self::grapheme_substr($s, $offset);
        } elseif ($offset < 0) {
            if (2 > $mode) {
                $offset += self::grapheme_strlen($s);
                $s = self::grapheme_substr($s, $offset);
                if (0 > $offset) {
                    $offset = 0;
                }
            } elseif (0 > $offset += self::grapheme_strlen($needle)) {
                $s = self::grapheme_substr($s, 0, $offset);
                $offset = 0;
            } else {
                $offset = 0;
            }
        }
        // As UTF-8 is self-synchronizing, and we have ensured the strings are valid UTF-8,
        // we can use normal binary string functions here. For case-insensitive searches,
        // case fold the strings first.
        $caseInsensitive = $mode & 1;
        $reverse = $mode & 2;
        if ($caseInsensitive) {
            // Use the same case folding mode as mbstring does for mb_stripos().
            // Stick to SIMPLE case folding to avoid changing the length of the string, which
            // might result in offsets being shifted.
            $mode = \defined('MB_CASE_FOLD_SIMPLE') ? \MB_CASE_FOLD_SIMPLE : \MB_CASE_LOWER;
            $s = mb_convert_case($s, $mode, 'UTF-8');
            $needle = mb_convert_case($needle, $mode, 'UTF-8');
            if (!\defined('MB_CASE_FOLD_SIMPLE')) {
                $s = str_replace(self::CASE_FOLD[0], self::CASE_FOLD[1], $s);
                $needle = str_replace(self::CASE_FOLD[0], self::CASE_FOLD[1], $needle);
            }
        }
        if ($reverse) {
            $needlePos = strrpos($s, $needle);
        } else {
            $needlePos = strpos($s, $needle);
        }
        return \false !== $needlePos ? self::grapheme_strlen(substr($s, 0, $needlePos)) + $offset : \false;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

use Symfony\Polyfill\Intl\Grapheme as p;

if (\PHP_VERSION_ID >= 80000) {
    return require __DIR__.'/bootstrap80.php';
}

if (!defined('GRAPHEME_EXTR_COUNT')) {
    define('GRAPHEME_EXTR_COUNT', 0);
}
if (!defined('GRAPHEME_EXTR_MAXBYTES')) {
    define('GRAPHEME_EXTR_MAXBYTES', 1);
}
if (!defined('GRAPHEME_EXTR_MAXCHARS')) {
    define('GRAPHEME_EXTR_MAXCHARS', 2);
}

if (!function_exists('grapheme_extract')) {
    function grapheme_extract($haystack, $size, $type = 0, $start = 0, &$next = 0) { return p\Grapheme::grapheme_extract($haystack, $size, $type, $start, $next); }
}
if (!function_exists('grapheme_stripos')) {
    function grapheme_stripos($haystack, $needle, $offset = 0) { return p\Grapheme::grapheme_stripos($haystack, $needle, $offset); }
}
if (!function_exists('grapheme_stristr')) {
    function grapheme_stristr($haystack, $needle, $beforeNeedle = false) { return p\Grapheme::grapheme_stristr($haystack, $needle, $beforeNeedle); }
}
if (!function_exists('grapheme_strlen')) {
    function grapheme_strlen($input) { return p\Grapheme::grapheme_strlen($input); }
}
if (!function_exists('grapheme_strpos')) {
    function grapheme_strpos($haystack, $needle, $offset = 0) { return p\Grapheme::grapheme_strpos($haystack, $needle, $offset); }
}
if (!function_exists('grapheme_strripos')) {
    function grapheme_strripos($haystack, $needle, $offset = 0) { return p\Grapheme::grapheme_strripos($haystack, $needle, $offset); }
}
if (!function_exists('grapheme_strrpos')) {
    function grapheme_strrpos($haystack, $needle, $offset = 0) { return p\Grapheme::grapheme_strrpos($haystack, $needle, $offset); }
}
if (!function_exists('grapheme_strstr')) {
    function grapheme_strstr($haystack, $needle, $beforeNeedle = false) { return p\Grapheme::grapheme_strstr($haystack, $needle, $beforeNeedle); }
}
if (!function_exists('grapheme_substr')) {
    function grapheme_substr($string, $offset, $length = null) { return p\Grapheme::grapheme_substr($string, $offset, $length); }
}
if (!function_exists('grapheme_str_split')) {
    function grapheme_str_split(string $string, int $length = 1) { return p\Grapheme::grapheme_str_split($string, $length); }
}
if (!function_exists('grapheme_levenshtein')) {
    function grapheme_levenshtein(string $string1, string $string2, int $insertion_cost = 1, int $replacement_cost = 1, int $deletion_cost = 1, string $locale = '') { return p\Php85::grapheme_levenshtein($string1, $string2, $insertion_cost, $replacement_cost, $deletion_cost); }
}
Symfony Polyfill / Intl: Grapheme
=================================

This component provides a partial, native PHP implementation of the
[Grapheme functions](https://php.net/intl.grapheme) from the
[Intl](https://php.net/intl) extension.

- [`grapheme_extract`](https://php.net/grapheme_extract): Extract a sequence of grapheme
  clusters from a text buffer, which must be encoded in UTF-8
- [`grapheme_stripos`](https://php.net/grapheme_stripos): Find position (in grapheme units)
  of first occurrence of a case-insensitive string
- [`grapheme_stristr`](https://php.net/grapheme_stristr): Returns part of haystack string
  from the first occurrence of case-insensitive needle to the end of haystack
- [`grapheme_strlen`](https://php.net/grapheme_strlen): Get string length in grapheme units
- [`grapheme_strpos`](https://php.net/grapheme_strpos): Find position (in grapheme units)
  of first occurrence of a string
- [`grapheme_strripos`](https://php.net/grapheme_strripos): Find position (in grapheme units)
  of last occurrence of a case-insensitive string
- [`grapheme_strrpos`](https://php.net/grapheme_strrpos): Find position (in grapheme units)
  of last occurrence of a string
- [`grapheme_strstr`](https://php.net/grapheme_strstr): Returns part of haystack string from
  the first occurrence of needle to the end of haystack
- [`grapheme_substr`](https://php.net/grapheme_substr): Return part of a string
- [`grapheme_str_split`](https://php.net/grapheme_str_split): Splits a string into an array of individual or chunks of graphemes

More information can be found in the
[main Polyfill README](https://github.com/symfony/polyfill/blob/main/README.md).

License
=======

This library is released under the [MIT license](LICENSE).
{
    "name": "symfony\/polyfill-intl-grapheme",
    "type": "library",
    "description": "Symfony polyfill for intl's grapheme_* functions",
    "keywords": [
        "polyfill",
        "shim",
        "compatibility",
        "portable",
        "intl",
        "grapheme"
    ],
    "homepage": "https:\/\/symfony.com",
    "license": "MIT",
    "authors": [
        {
            "name": "Nicolas Grekas",
            "email": "p@tchwork.com"
        },
        {
            "name": "Symfony Community",
            "homepage": "https:\/\/symfony.com\/contributors"
        }
    ],
    "require": {
        "php": ">=7.2"
    },
    "autoload": {
        "psr-4": {
            "Symfony\\Polyfill\\Intl\\Grapheme\\": ""
        },
        "files": [
            "bootstrap.php"
        ]
    },
    "suggest": {
        "ext-intl": "For best performance"
    },
    "minimum-stability": "dev",
    "extra": {
        "thanks": {
            "name": "symfony\/polyfill",
            "url": "https:\/\/github.com\/symfony\/polyfill"
        }
    }
}Copyright (c) 2015-2022 Ben Ramsey <ben@benramsey.com>

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
<h1 align="center">ramsey/collection</h1>

<p align="center">
    <strong>A PHP library for representing and manipulating collections.</strong>
</p>

<p align="center">
    <a href="https://github.com/ramsey/collection"><img src="http://img.shields.io/badge/source-ramsey/collection-blue.svg?style=flat-square" alt="Source Code"></a>
    <a href="https://packagist.org/packages/ramsey/collection"><img src="https://img.shields.io/packagist/v/ramsey/collection.svg?style=flat-square&label=release" alt="Download Package"></a>
    <a href="https://php.net"><img src="https://img.shields.io/packagist/php-v/ramsey/collection.svg?style=flat-square&colorB=%238892BF" alt="PHP Programming Language"></a>
    <a href="https://github.com/ramsey/collection/blob/master/LICENSE"><img src="https://img.shields.io/packagist/l/ramsey/collection.svg?style=flat-square&colorB=darkcyan" alt="Read License"></a>
    <a href="https://github.com/ramsey/collection/actions/workflows/continuous-integration.yml"><img src="https://img.shields.io/github/actions/workflow/status/ramsey/collection/continuous-integration.yml?branch=main&logo=github&style=flat-square" alt="Build Status"></a>
    <a href="https://codecov.io/gh/ramsey/collection"><img src="https://img.shields.io/codecov/c/gh/ramsey/collection?label=codecov&logo=codecov&style=flat-square" alt="Codecov Code Coverage"></a>
</p>

## About

ramsey/collection is a PHP library for representing and manipulating collections.

Much inspiration for this library came from the [Java Collections Framework][java].

This project adheres to a [code of conduct](CODE_OF_CONDUCT.md).
By participating in this project and its community, you are expected to
uphold this code.

## Installation

Install this package as a dependency using [Composer](https://getcomposer.org).

``` bash
composer require ramsey/collection
```

## Usage

Examples of how to use this library may be found in the
[Wiki pages](https://github.com/ramsey/collection/wiki/Examples).

## Contributing

Contributions are welcome! To contribute, please familiarize yourself with
[CONTRIBUTING.md](CONTRIBUTING.md).

## Coordinated Disclosure

Keeping user information safe and secure is a top priority, and we welcome the
contribution of external security researchers. If you believe you've found a
security issue in software that is maintained in this repository, please read
[SECURITY.md][] for instructions on submitting a vulnerability report.

## Copyright and License

The ramsey/collection library is copyright © [Ben Ramsey](https://benramsey.com)
and licensed for use under the terms of the
MIT License (MIT). Please see [LICENSE](LICENSE) for more information.


[java]: http://docs.oracle.com/javase/8/docs/technotes/guides/collections/index.html
[security.md]: https://github.com/ramsey/collection/blob/main/SECURITY.md
{
    "name": "ramsey\/collection",
    "description": "A PHP library for representing and manipulating collections.",
    "license": "MIT",
    "type": "library",
    "keywords": [
        "array",
        "collection",
        "hash",
        "map",
        "queue",
        "set"
    ],
    "authors": [
        {
            "name": "Ben Ramsey",
            "email": "ben@benramsey.com",
            "homepage": "https:\/\/benramsey.com"
        }
    ],
    "require": {
        "php": "^8.1"
    },
    "require-dev": {
        "captainhook\/plugin-composer": "^5.3",
        "ergebnis\/composer-normalize": "^2.45",
        "fakerphp\/faker": "^1.24",
        "hamcrest\/hamcrest-php": "^2.0",
        "jangregor\/phpstan-prophecy": "^2.1",
        "mockery\/mockery": "^1.6",
        "php-parallel-lint\/php-console-highlighter": "^1.0",
        "php-parallel-lint\/php-parallel-lint": "^1.4",
        "phpspec\/prophecy-phpunit": "^2.3",
        "phpstan\/extension-installer": "^1.4",
        "phpstan\/phpstan": "^2.1",
        "phpstan\/phpstan-mockery": "^2.0",
        "phpstan\/phpstan-phpunit": "^2.0",
        "phpunit\/phpunit": "^10.5",
        "ramsey\/coding-standard": "^2.3",
        "ramsey\/conventional-commits": "^1.6",
        "roave\/security-advisories": "dev-latest"
    },
    "prefer-stable": true,
    "autoload": {
        "psr-4": {
            "_ContaoManager\\Ramsey\\Collection\\": "src\/"
        }
    },
    "autoload-dev": {
        "psr-4": {
            "_ContaoManager\\Ramsey\\Collection\\Test\\": "tests\/"
        }
    },
    "config": {
        "allow-plugins": {
            "captainhook\/plugin-composer": true,
            "dealerdirect\/phpcodesniffer-composer-installer": true,
            "ergebnis\/composer-normalize": true,
            "phpstan\/extension-installer": true
        },
        "sort-packages": true
    },
    "extra": {
        "captainhook": {
            "force-install": true
        },
        "ramsey\/conventional-commits": {
            "configFile": "conventional-commits.json"
        }
    },
    "scripts": {
        "dev:analyze": [
            "@dev:analyze:phpstan"
        ],
        "dev:analyze:phpstan": "phpstan analyse --ansi --memory-limit=1G",
        "dev:build:clean": "git clean -fX build\/",
        "dev:lint": [
            "@dev:lint:syntax",
            "@dev:lint:style"
        ],
        "dev:lint:fix": "phpcbf",
        "dev:lint:style": "phpcs --colors",
        "dev:lint:syntax": "parallel-lint --colors src\/ tests\/",
        "dev:test": [
            "@dev:lint",
            "@dev:analyze",
            "@dev:test:unit"
        ],
        "dev:test:coverage:ci": "phpunit --colors=always --coverage-text --coverage-clover build\/coverage\/clover.xml --coverage-cobertura build\/coverage\/cobertura.xml --coverage-crap4j build\/coverage\/crap4j.xml --coverage-xml build\/coverage\/coverage-xml --log-junit build\/junit.xml",
        "dev:test:coverage:html": "phpunit --colors=always --coverage-html build\/coverage\/coverage-html\/",
        "dev:test:unit": "phpunit --colors=always",
        "test": "@dev:test"
    },
    "scripts-descriptions": {
        "dev:analyze": "Runs all static analysis checks.",
        "dev:analyze:phpstan": "Runs the PHPStan static analyzer.",
        "dev:build:clean": "Cleans the build\/ directory.",
        "dev:lint": "Runs all linting checks.",
        "dev:lint:fix": "Auto-fixes coding standards issues, if possible.",
        "dev:lint:style": "Checks for coding standards issues.",
        "dev:lint:syntax": "Checks for syntax errors.",
        "dev:test": "Runs linting, static analysis, and unit tests.",
        "dev:test:coverage:ci": "Runs unit tests and generates CI coverage reports.",
        "dev:test:coverage:html": "Runs unit tests and generates HTML coverage report.",
        "dev:test:unit": "Runs unit tests.",
        "test": "Runs linting, static analysis, and unit tests."
    }
}<!--
    This policy template was created using the HackerOne Policy Builder [1],
    with guidance from the National Telecommunications and Information
    Administration Coordinated Vulnerability Disclosure Template [2].
 -->

# Vulnerability Disclosure Policy (VDP)

## Brand Promise

<!--
    This is your brand promise. Its objective is to "demonstrate a clear, good
    faith commitment to customers and other stakeholders potentially impacted by
    security vulnerabilities" [2].
-->

Keeping user information safe and secure is a top priority, and we welcome the
contribution of external security researchers.

## Scope

<!--
    This is your initial scope. It tells vulnerability finders and reporters
    "which systems and capabilities are 'fair game' versus 'off limits'" [2].
    For software packages, this is often a list of currently maintained versions
    of the package.
-->

If you believe you've found a security issue in software that is maintained in
this repository, we encourage you to notify us.

| Version | In scope | Source code |
| ------- | :------: | ----------- |
| latest  | ✅        | https://github.com/ramsey/collection |

## How to Submit a Report

<!--
    This is your communication process. It tells security researchers how to
    contact you to report a vulnerability. It may be a link to a web form that
    uses HTTPS for secure communication, or it may be an email address.
    Optionally, you may choose to include a PGP public key, so that researchers
    may send you encrypted messages.
-->

To submit a vulnerability report, please contact us at security@ramsey.dev.
Your submission will be reviewed and validated by a member of our team.

## Safe Harbor

<!--
    This section assures vulnerability finders and reporters that they will
    receive good faith responses to their good faith acts. In other words,
    "we will not take legal action if..." [2].
-->

We support safe harbor for security researchers who:

* Make a good faith effort to avoid privacy violations, destruction of data, and
  interruption or degradation of our services.
* Only interact with accounts you own or with explicit permission of the account
  holder. If you do encounter Personally Identifiable Information (PII) contact
  us immediately, do not proceed with access, and immediately purge any local
  information.
* Provide us with a reasonable amount of time to resolve vulnerabilities prior
  to any disclosure to the public or a third party.

We will consider activities conducted consistent with this policy to constitute
"authorized" conduct and will not pursue civil action or initiate a complaint to
law enforcement. We will help to the extent we can if legal action is initiated
by a third party against you.

Please submit a report to us before engaging in conduct that may be inconsistent
with or unaddressed by this policy.

## Preferences

<!--
    The preferences section sets expectations based on priority and submission
    volume, rather than legal objection or restriction [2].

    According to the NTIA [2]:

        This section is a living document that sets expectations for preferences
        and priorities, typically maintained by the support and engineering
        team. This can outline classes of vulnerabilities, reporting style
        (crash dumps, CVSS scoring, proof-of-concept, etc.), tools, etc. Too
        many preferences can set the wrong tone or make reporting findings
        difficult to navigate. This section also sets expectations to the
        researcher community for what types of issues are considered important
        or not.
-->

* Please provide detailed reports with reproducible steps and a clearly defined
  impact.
* Include the version number of the vulnerable package in your report
* Social engineering (e.g. phishing, vishing, smishing) is prohibited.

<!--
    References

    [1] HackerOne. Policy builder. Retrieved from https://hackerone.com/policy-builder/

    [2] NTIA Safety Working Group. 2016. "Early stage" coordinated vulnerability
    disclosure template: Version 1.1. (15 December 2016). Retrieved from
    https://www.ntia.doc.gov/files/ntia/publications/ntia_vuln_disclosure_early_stage_template.pdf
-->

## Encryption Key for security@ramsey.dev

For increased privacy when reporting sensitive issues, you may encrypt your
message using the following public key:

```
-----BEGIN PGP PUBLIC KEY BLOCK-----

mQINBF+Z9gEBEACbT/pIx8RR0K18t8Z2rDnmEV44YdT7HNsMdq+D6SAlx8UUb6AU
jGIbV9dgBgGNtOLU1pxloaJwL9bWIRbj+X/Qb2WNIP//Vz1Y40ox1dSpfCUrizXx
kb4p58Xml0PsB8dg3b4RDUgKwGC37ne5xmDnigyJPbiB2XJ6Xc46oPCjh86XROTK
wEBB2lY67ClBlSlvC2V9KmbTboRQkLdQDhOaUosMb99zRb0EWqDLaFkZVjY5HI7i
0pTveE6dI12NfHhTwKjZ5pUiAZQGlKA6J1dMjY2unxHZkQj5MlMfrLSyJHZxccdJ
xD94T6OTcTHt/XmMpI2AObpewZDdChDQmcYDZXGfAhFoJmbvXsmLMGXKgzKoZ/ls
RmLsQhh7+/r8E+Pn5r+A6Hh4uAc14ApyEP0ckKeIXw1C6pepHM4E8TEXVr/IA6K/
z6jlHORixIFX7iNOnfHh+qwOgZw40D6JnBfEzjFi+T2Cy+JzN2uy7I8UnecTMGo3
5t6astPy6xcH6kZYzFTV7XERR6LIIVyLAiMFd8kF5MbJ8N5ElRFsFHPW+82N2HDX
c60iSaTB85k6R6xd8JIKDiaKE4sSuw2wHFCKq33d/GamYezp1wO+bVUQg88efljC
2JNFyD+vl30josqhw1HcmbE1TP3DlYeIL5jQOlxCMsgai6JtTfHFM/5MYwARAQAB
tBNzZWN1cml0eUByYW1zZXkuZGV2iQJUBBMBCAA+FiEE4drPD+/ofZ570fAYq0bv
vXQCywIFAl+Z9gECGwMFCQeGH4AFCwkIBwIGFQoJCAsCBBYCAwECHgECF4AACgkQ
q0bvvXQCywIkEA//Qcwv8MtTCy01LHZd9c7VslwhNdXQDYymcTyjcYw8x7O22m4B
3hXE6vqAplFhVxxkqXB2ef0tQuzxhPHNJgkCE4Wq4i+V6qGpaSVHQT2W6DN/NIhL
vS8OdScc6zddmIbIkSrzVVAtjwehFNEIrX3DnbbbK+Iku7vsKT5EclOluIsjlYoX
goW8IeReyDBqOe2H3hoCGw6EA0D/NYV2bJnfy53rXVIyarsXXeOLp7eNEH6Td7aW
PVSrMZJe1t+knrEGnEdrXWzlg4lCJJCtemGv+pKBUomnyISXSdqyoRCCzvQjqyig
2kRebUX8BXPW33p4OXPj9sIboUOjZwormWwqqbFMO+J4TiVCUoEoheI7emPFRcNN
QtPJrjbY1++OznBc0GRpfeUkGoU1cbRl1bnepnFIZMTDLkrVW6I1Y4q8ZVwX3BkE
N81ctFrRpHBlU36EdHvjPQmGtuiL77Qq3fWmMv7yTvK1wHJAXfEb0ZJWHZCbck3w
l0CVq0Z+UUAOM8Rp1N0N8m92xtapav0qCFU9qzf2J5qX6GRmWv+d29wPgFHzDWBm
nnrYYIA4wJLx00U6SMcVBSnNe91B+RfGY5XQhbWPjQQecOGCSDsxaFAq2MeOVJyZ
bIjLYfG9GxoLKr5R7oLRJvZI4nKKBc1Kci/crZbdiSdQhSQGlDz88F1OHeCIdQQQ
EQgAHRYhBOhdAxHd+lus86YQ57Atl5icjAcbBQJfmfdIAAoJELAtl5icjAcbFVcA
/1LqB3ZjsnXDAvvAXZVjSPqofSlpMLeRQP6IM/A9Odq0AQCZrtZc1knOMGEcjppK
Rk+sy/R0Mshy8TDuaZIRgh2Ux7kCDQRfmfYBARAAmchKzzVz7IaEq7PnZDb3szQs
T/+E9F3m39yOpV4fEB1YzObonFakXNT7Gw2tZEx0eitUMqQ/13jjfu3UdzlKl2bR
qA8LrSQRhB+PTC9A1XvwxCUYhhjGiLzJ9CZL6hBQB43qHOmE9XJPme90geLsF+gK
u39Waj1SNWzwGg+Gy1Gl5f2AJoDTxznreCuFGj+Vfaczt/hlfgqpOdb9jsmdoE7t
3DSWppA9dRHWwQSgE6J28rR4QySBcqyXS6IMykqaJn7Z26yNIaITLnHCZOSY8zhP
ha7GFsN549EOCgECbrnPt9dmI2+hQE0RO0e7SOBNsIf5sz/i7urhwuj0CbOqhjc2
X1AEVNFCVcb6HPi/AWefdFCRu0gaWQxn5g+9nkq5slEgvzCCiKYzaBIcr8qR6Hb4
FaOPVPxO8vndRouq57Ws8XpAwbPttioFuCqF4u9K+tK/8e2/R8QgRYJsE3Cz/Fu8
+pZFpMnqbDEbK3DL3ss+1ed1sky+mDV8qXXeI33XW5hMFnk1JWshUjHNlQmE6ftC
U0xSTMVUtwJhzH2zDp8lEdu7qi3EsNULOl68ozDr6soWAvCbHPeTdTOnFySGCleG
/3TonsoZJs/sSPPJnxFQ1DtgQL6EbhIwa0ZwU4eKYVHZ9tjxuMX3teFzRvOrJjgs
+ywGlsIURtEckT5Y6nMAEQEAAYkCPAQYAQgAJhYhBOHazw/v6H2ee9HwGKtG7710
AssCBQJfmfYBAhsMBQkHhh+AAAoJEKtG7710AssC8NcP/iDAcy1aZFvkA0EbZ85p
i7/+ywtE/1wF4U4/9OuLcoskqGGnl1pJNPooMOSBCfreoTB8HimT0Fln0CoaOm4Q
pScNq39JXmf4VxauqUJVARByP6zUfgYarqoaZNeuFF0S4AZJ2HhGzaQPjDz1uKVM
PE6tQSgQkFzdZ9AtRA4vElTH6yRAgmepUsOihk0b0gUtVnwtRYZ8e0Qt3ie97a73
DxLgAgedFRUbLRYiT0vNaYbainBsLWKpN/T8odwIg/smP0Khjp/ckV60cZTdBiPR
szBTPJESMUTu0VPntc4gWwGsmhZJg/Tt/qP08XYo3VxNYBegyuWwNR66zDWvwvGH
muMv5UchuDxp6Rt3JkIO4voMT1JSjWy9p8krkPEE4V6PxAagLjdZSkt92wVLiK5x
y5gNrtPhU45YdRAKHr36OvJBJQ42CDaZ6nzrzghcIp9CZ7ANHrI+QLRM/csz+AGA
szSp6S4mc1lnxxfbOhPPpebZPn0nIAXoZnnoVKdrxBVedPQHT59ZFvKTQ9Fs7gd3
sYNuc7tJGFGC2CxBH4ANDpOQkc5q9JJ1HSGrXU3juxIiRgfA26Q22S9c71dXjElw
Ri584QH+bL6kkYmm8xpKF6TVwhwu5xx/jBPrbWqFrtbvLNrnfPoapTihBfdIhkT6
nmgawbBHA02D5xEqB5SU3WJu
=eJNx
-----END PGP PUBLIC KEY BLOCK-----
```
<?php

/**
 * This file is part of the ramsey/collection library
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @copyright Copyright (c) Ben Ramsey <ben@benramsey.com>
 * @license http://opensource.org/licenses/MIT MIT
 */
declare (strict_types=1);
namespace _ContaoManager\Ramsey\Collection;

use _ContaoManager\Ramsey\Collection\Exception\InvalidArgumentException;
use _ContaoManager\Ramsey\Collection\Exception\NoSuchElementException;
use function array_key_last;
use function array_pop;
use function array_unshift;
/**
 * This class provides a basic implementation of `DoubleEndedQueueInterface`, to
 * minimize the effort required to implement this interface.
 *
 * @template T
 * @extends Queue<T>
 * @implements DoubleEndedQueueInterface<T>
 */
class DoubleEndedQueue extends Queue implements DoubleEndedQueueInterface
{
    /**
     * Constructs a double-ended queue (dequeue) object of the specified type,
     * optionally with the specified data.
     *
     * @param string $queueType The type or class name associated with this dequeue.
     * @param array<array-key, T> $data The initial items to store in the dequeue.
     */
    public function __construct(private readonly string $queueType, array $data = [])
    {
        parent::__construct($this->queueType, $data);
    }
    /**
     * @throws InvalidArgumentException if $element is of the wrong type
     */
    public function addFirst(mixed $element): bool
    {
        if ($this->checkType($this->getType(), $element) === \false) {
            throw new InvalidArgumentException('Value must be of type ' . $this->getType() . '; value is ' . $this->toolValueToString($element));
        }
        array_unshift($this->data, $element);
        return \true;
    }
    /**
     * @throws InvalidArgumentException if $element is of the wrong type
     */
    public function addLast(mixed $element): bool
    {
        return $this->add($element);
    }
    public function offerFirst(mixed $element): bool
    {
        try {
            return $this->addFirst($element);
        } catch (InvalidArgumentException) {
            return \false;
        }
    }
    public function offerLast(mixed $element): bool
    {
        return $this->offer($element);
    }
    /**
     * @return T the first element in this queue.
     *
     * @throws NoSuchElementException if the queue is empty
     */
    public function removeFirst(): mixed
    {
        return $this->remove();
    }
    /**
     * @return T the last element in this queue.
     *
     * @throws NoSuchElementException if this queue is empty.
     */
    public function removeLast(): mixed
    {
        return $this->pollLast() ?? throw new NoSuchElementException('Can\'t return element from Queue. Queue is empty.');
    }
    /**
     * @return T | null the head of this queue, or `null` if this queue is empty.
     */
    public function pollFirst(): mixed
    {
        return $this->poll();
    }
    /**
     * @return T | null the tail of this queue, or `null` if this queue is empty.
     */
    public function pollLast(): mixed
    {
        return array_pop($this->data);
    }
    /**
     * @return T the head of this queue.
     *
     * @throws NoSuchElementException if this queue is empty.
     */
    public function firstElement(): mixed
    {
        return $this->element();
    }
    /**
     * @return T the tail of this queue.
     *
     * @throws NoSuchElementException if this queue is empty.
     */
    public function lastElement(): mixed
    {
        return $this->peekLast() ?? throw new NoSuchElementException('Can\'t return element from Queue. Queue is empty.');
    }
    /**
     * @return T | null the head of this queue, or `null` if this queue is empty.
     */
    public function peekFirst(): mixed
    {
        return $this->peek();
    }
    /**
     * @return T | null the tail of this queue, or `null` if this queue is empty.
     */
    public function peekLast(): mixed
    {
        $lastIndex = array_key_last($this->data);
        if ($lastIndex === null) {
            return null;
        }
        return $this->data[$lastIndex];
    }
}
<?php

/**
 * This file is part of the ramsey/collection library
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @copyright Copyright (c) Ben Ramsey <ben@benramsey.com>
 * @license http://opensource.org/licenses/MIT MIT
 */
declare (strict_types=1);
namespace _ContaoManager\Ramsey\Collection;

/**
 * This class contains the basic implementation of a collection that does not
 * allow duplicated values (a set), to minimize the effort required to implement
 * this specific type of collection.
 *
 * @template T
 * @extends AbstractCollection<T>
 */
abstract class AbstractSet extends AbstractCollection
{
    public function add(mixed $element): bool
    {
        if ($this->contains($element)) {
            return \false;
        }
        // Call offsetSet() on the parent instead of add(), since calling
        // parent::add() will invoke $this->offsetSet(), which will call
        // $this->contains() a second time. This can cause performance issues
        // with extremely large collections. For more information, see
        // https://github.com/ramsey/collection/issues/68.
        parent::offsetSet(null, $element);
        return \true;
    }
    public function offsetSet(mixed $offset, mixed $value): void
    {
        if ($this->contains($value)) {
            return;
        }
        parent::offsetSet($offset, $value);
    }
}
<?php

/**
 * This file is part of the ramsey/collection library
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @copyright Copyright (c) Ben Ramsey <ben@benramsey.com>
 * @license http://opensource.org/licenses/MIT MIT
 */
declare (strict_types=1);
namespace _ContaoManager\Ramsey\Collection;

use _ContaoManager\Ramsey\Collection\Exception\NoSuchElementException;
use RuntimeException;
/**
 * A queue is a collection in which the entities in the collection are kept in
 * order.
 *
 * The principal operations on the queue are the addition of entities to the end
 * (tail), also known as *enqueue*, and removal of entities from the front
 * (head), also known as *dequeue*. This makes the queue a first-in-first-out
 * (FIFO) data structure.
 *
 * Besides basic array operations, queues provide additional insertion,
 * extraction, and inspection operations. Each of these methods exists in two
 * forms: one throws an exception if the operation fails, the other returns a
 * special value (either `null` or `false`, depending on the operation). The
 * latter form of the insert operation is designed specifically for use with
 * capacity-restricted `QueueInterface` implementations; in most
 * implementations, insert operations cannot fail.
 *
 * <table>
 * <caption>Summary of QueueInterface methods</caption>
 * <thead>
 * <tr>
 * <td></td>
 * <td><em>Throws exception</em></td>
 * <td><em>Returns special value</em></td>
 * </tr>
 * </thead>
 * <tbody>
 * <tr>
 * <th>Insert</th>
 * <td><code>add()</code></td>
 * <td><code>offer()</code></td>
 * </tr>
 * <tr>
 * <th>Remove</th>
 * <td><code>remove()</code></td>
 * <td><code>poll()</code></td>
 * </tr>
 * <tr>
 * <th>Examine</th>
 * <td><code>element()</code></td>
 * <td><code>peek()</code></td>
 * </tr>
 * </tbody>
 * </table>
 *
 * Queues typically, but do not necessarily, order elements in a FIFO
 * (first-in-first-out) manner. Among the exceptions are priority queues, which
 * order elements according to a supplied comparator, or the elements' natural
 * ordering, and LIFO queues (or stacks) which order the elements LIFO
 * (last-in-first-out). Whatever the ordering used, the head of the queue is
 * that element which would be removed by a call to remove() or poll(). In a
 * FIFO queue, all new elements are inserted at the tail of the queue. Other
 * kinds of queues may use different placement rules. Every `QueueInterface`
 * implementation must specify its ordering properties.
 *
 * The `offer()` method inserts an element if possible, otherwise returning
 * `false`. This differs from the `add()` method, which can fail to add an
 * element only by throwing an unchecked exception. The `offer()` method is
 * designed for use when failure is a normal, rather than exceptional
 * occurrence, for example, in fixed-capacity (or "bounded") queues.
 *
 * The `remove()` and `poll()` methods remove and return the head of the queue.
 * Exactly which element is removed from the queue is a function of the queue's
 * ordering policy, which differs from implementation to implementation. The
 * `remove()` and `poll()` methods differ only in their behavior when the queue
 * is empty: the `remove()` method throws an exception, while the `poll()`
 * method returns `null`.
 *
 * The `element()` and `peek()` methods return, but do not remove, the head of
 * the queue.
 *
 * `QueueInterface` implementations generally do not allow insertion of `null`
 * elements, although some implementations do not prohibit insertion of `null`.
 * Even in the implementations that permit it, `null` should not be inserted
 * into a queue, as `null` is also used as a special return value by the
 * `poll()` method to indicate that the queue contains no elements.
 *
 * @template T
 * @extends ArrayInterface<T>
 */
interface QueueInterface extends ArrayInterface
{
    /**
     * Ensures that this queue contains the specified element (optional
     * operation).
     *
     * Returns `true` if this queue changed as a result of the call. (Returns
     * `false` if this queue does not permit duplicates and already contains the
     * specified element.)
     *
     * Queues that support this operation may place limitations on what elements
     * may be added to this queue. In particular, some queues will refuse to add
     * `null` elements, and others will impose restrictions on the type of
     * elements that may be added. Queue classes should clearly specify in their
     * documentation any restrictions on what elements may be added.
     *
     * If a queue refuses to add a particular element for any reason other than
     * that it already contains the element, it must throw an exception (rather
     * than returning `false`). This preserves the invariant that a queue always
     * contains the specified element after this call returns.
     *
     * @see self::offer()
     *
     * @param T $element The element to add to this queue.
     *
     * @return bool `true` if this queue changed as a result of the call.
     *
     * @throws RuntimeException if a queue refuses to add a particular element
     *     for any reason other than that it already contains the element.
     *     Implementations should use a more-specific exception that extends
     *     `\RuntimeException`.
     */
    public function add(mixed $element): bool;
    /**
     * Retrieves, but does not remove, the head of this queue.
     *
     * This method differs from `peek()` only in that it throws an exception if
     * this queue is empty.
     *
     * @see self::peek()
     *
     * @return T the head of this queue.
     *
     * @throws NoSuchElementException if this queue is empty.
     */
    public function element(): mixed;
    /**
     * Inserts the specified element into this queue if it is possible to do so
     * immediately without violating capacity restrictions.
     *
     * When using a capacity-restricted queue, this method is generally
     * preferable to `add()`, which can fail to insert an element only by
     * throwing an exception.
     *
     * @see self::add()
     *
     * @param T $element The element to add to this queue.
     *
     * @return bool `true` if the element was added to this queue, else `false`.
     */
    public function offer(mixed $element): bool;
    /**
     * Retrieves, but does not remove, the head of this queue, or returns `null`
     * if this queue is empty.
     *
     * @see self::element()
     *
     * @return T | null the head of this queue, or `null` if this queue is empty.
     */
    public function peek(): mixed;
    /**
     * Retrieves and removes the head of this queue, or returns `null`
     * if this queue is empty.
     *
     * @see self::remove()
     *
     * @return T | null the head of this queue, or `null` if this queue is empty.
     */
    public function poll(): mixed;
    /**
     * Retrieves and removes the head of this queue.
     *
     * This method differs from `poll()` only in that it throws an exception if
     * this queue is empty.
     *
     * @see self::poll()
     *
     * @return T the head of this queue.
     *
     * @throws NoSuchElementException if this queue is empty.
     */
    public function remove(): mixed;
    /**
     * Returns the type associated with this queue.
     */
    public function getType(): string;
}
<?php

/**
 * This file is part of the ramsey/collection library
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @copyright Copyright (c) Ben Ramsey <ben@benramsey.com>
 * @license http://opensource.org/licenses/MIT MIT
 */
declare (strict_types=1);
namespace _ContaoManager\Ramsey\Collection;

use Closure;
use _ContaoManager\Ramsey\Collection\Exception\CollectionMismatchException;
use _ContaoManager\Ramsey\Collection\Exception\InvalidArgumentException;
use _ContaoManager\Ramsey\Collection\Exception\InvalidPropertyOrMethod;
use _ContaoManager\Ramsey\Collection\Exception\NoSuchElementException;
use _ContaoManager\Ramsey\Collection\Exception\UnsupportedOperationException;
use _ContaoManager\Ramsey\Collection\Tool\TypeTrait;
use _ContaoManager\Ramsey\Collection\Tool\ValueExtractorTrait;
use _ContaoManager\Ramsey\Collection\Tool\ValueToStringTrait;
use function array_filter;
use function array_key_first;
use function array_key_last;
use function array_map;
use function array_merge;
use function array_reduce;
use function array_search;
use function array_udiff;
use function array_uintersect;
use function in_array;
use function is_int;
use function is_object;
use function spl_object_id;
use function sprintf;
use function usort;
/**
 * This class provides a basic implementation of `CollectionInterface`, to
 * minimize the effort required to implement this interface
 *
 * @template T
 * @extends AbstractArray<T>
 * @implements CollectionInterface<T>
 */
abstract class AbstractCollection extends AbstractArray implements CollectionInterface
{
    use TypeTrait;
    use ValueToStringTrait;
    use ValueExtractorTrait;
    /**
     * @throws InvalidArgumentException if $element is of the wrong type.
     */
    public function add(mixed $element): bool
    {
        $this[] = $element;
        return \true;
    }
    public function contains(mixed $element, bool $strict = \true): bool
    {
        return in_array($element, $this->data, $strict);
    }
    /**
     * @throws InvalidArgumentException if $element is of the wrong type.
     */
    public function offsetSet(mixed $offset, mixed $value): void
    {
        if ($this->checkType($this->getType(), $value) === \false) {
            throw new InvalidArgumentException('Value must be of type ' . $this->getType() . '; value is ' . $this->toolValueToString($value));
        }
        if ($offset === null) {
            $this->data[] = $value;
        } else {
            $this->data[$offset] = $value;
        }
    }
    public function remove(mixed $element): bool
    {
        if (($position = array_search($element, $this->data, \true)) !== \false) {
            unset($this[$position]);
            return \true;
        }
        return \false;
    }
    /**
     * @throws InvalidPropertyOrMethod if the $propertyOrMethod does not exist
     *     on the elements in this collection.
     * @throws UnsupportedOperationException if unable to call column() on this
     *     collection.
     *
     * @inheritDoc
     */
    public function column(string $propertyOrMethod): array
    {
        $temp = [];
        foreach ($this->data as $item) {
            $temp[] = $this->extractValue($item, $propertyOrMethod);
        }
        return $temp;
    }
    /**
     * @return T
     *
     * @throws NoSuchElementException if this collection is empty.
     */
    public function first(): mixed
    {
        $firstIndex = array_key_first($this->data);
        if ($firstIndex === null) {
            throw new NoSuchElementException('Can\'t determine first item. Collection is empty');
        }
        return $this->data[$firstIndex];
    }
    /**
     * @return T
     *
     * @throws NoSuchElementException if this collection is empty.
     */
    public function last(): mixed
    {
        $lastIndex = array_key_last($this->data);
        if ($lastIndex === null) {
            throw new NoSuchElementException('Can\'t determine last item. Collection is empty');
        }
        return $this->data[$lastIndex];
    }
    /**
     * @return CollectionInterface<T>
     *
     * @throws InvalidPropertyOrMethod if the $propertyOrMethod does not exist
     *     on the elements in this collection.
     * @throws UnsupportedOperationException if unable to call sort() on this
     *     collection.
     */
    public function sort(?string $propertyOrMethod = null, Sort $order = Sort::Ascending): CollectionInterface
    {
        $collection = clone $this;
        usort($collection->data, function (mixed $a, mixed $b) use ($propertyOrMethod, $order): int {
            $aValue = $this->extractValue($a, $propertyOrMethod);
            $bValue = $this->extractValue($b, $propertyOrMethod);
            return ($aValue <=> $bValue) * ($order === Sort::Descending ? -1 : 1);
        });
        return $collection;
    }
    /**
     * @param callable(T): bool $callback A callable to use for filtering elements.
     *
     * @return CollectionInterface<T>
     */
    public function filter(callable $callback): CollectionInterface
    {
        $collection = clone $this;
        $collection->data = array_merge([], array_filter($collection->data, $callback));
        return $collection;
    }
    /**
     * @return CollectionInterface<T>
     *
     * @throws InvalidPropertyOrMethod if the $propertyOrMethod does not exist
     *     on the elements in this collection.
     * @throws UnsupportedOperationException if unable to call where() on this
     *     collection.
     */
    public function where(?string $propertyOrMethod, mixed $value): CollectionInterface
    {
        return $this->filter(fn(mixed $item): bool => $this->extractValue($item, $propertyOrMethod) === $value);
    }
    /**
     * @param callable(T): TCallbackReturn $callback A callable to apply to each
     *     item of the collection.
     *
     * @return CollectionInterface<TCallbackReturn>
     *
     * @template TCallbackReturn
     */
    public function map(callable $callback): CollectionInterface
    {
        return new Collection('mixed', array_map($callback, $this->data));
    }
    /**
     * @param callable(TCarry, T): TCarry $callback A callable to apply to each
     *     item of the collection to reduce it to a single value.
     * @param TCarry $initial This is the initial value provided to the callback.
     *
     * @return TCarry
     *
     * @template TCarry
     */
    public function reduce(callable $callback, mixed $initial): mixed
    {
        return array_reduce($this->data, $callback, $initial);
    }
    /**
     * @param CollectionInterface<T> $other The collection to check for divergent
     *     items.
     *
     * @return CollectionInterface<T>
     *
     * @throws CollectionMismatchException if the compared collections are of
     *     differing types.
     */
    public function diff(CollectionInterface $other): CollectionInterface
    {
        $this->compareCollectionTypes($other);
        $diffAtoB = array_udiff($this->data, $other->toArray(), $this->getComparator());
        $diffBtoA = array_udiff($other->toArray(), $this->data, $this->getComparator());
        $collection = clone $this;
        $collection->data = array_merge($diffAtoB, $diffBtoA);
        return $collection;
    }
    /**
     * @param CollectionInterface<T> $other The collection to check for
     *     intersecting items.
     *
     * @return CollectionInterface<T>
     *
     * @throws CollectionMismatchException if the compared collections are of
     *     differing types.
     */
    public function intersect(CollectionInterface $other): CollectionInterface
    {
        $this->compareCollectionTypes($other);
        $collection = clone $this;
        $collection->data = array_uintersect($this->data, $other->toArray(), $this->getComparator());
        return $collection;
    }
    /**
     * @param CollectionInterface<T> ...$collections The collections to merge.
     *
     * @return CollectionInterface<T>
     *
     * @throws CollectionMismatchException if unable to merge any of the given
     *     collections or items within the given collections due to type
     *     mismatch errors.
     */
    public function merge(CollectionInterface ...$collections): CollectionInterface
    {
        $mergedCollection = clone $this;
        foreach ($collections as $index => $collection) {
            if (!$collection instanceof static) {
                throw new CollectionMismatchException(sprintf('Collection with index %d must be of type %s', $index, static::class));
            }
            // When using generics (Collection.php, Set.php, etc),
            // we also need to make sure that the internal types match each other
            if ($this->getUniformType($collection) !== $this->getUniformType($this)) {
                throw new CollectionMismatchException(sprintf('Collection items in collection with index %d must be of type %s', $index, $this->getType()));
            }
            foreach ($collection as $key => $value) {
                if (is_int($key)) {
                    $mergedCollection[] = $value;
                } else {
                    $mergedCollection[$key] = $value;
                }
            }
        }
        return $mergedCollection;
    }
    /**
     * @param CollectionInterface<T> $other
     *
     * @throws CollectionMismatchException
     */
    private function compareCollectionTypes(CollectionInterface $other): void
    {
        if (!$other instanceof static) {
            throw new CollectionMismatchException('Collection must be of type ' . static::class);
        }
        // When using generics (Collection.php, Set.php, etc),
        // we also need to make sure that the internal types match each other
        if ($this->getUniformType($other) !== $this->getUniformType($this)) {
            throw new CollectionMismatchException('Collection items must be of type ' . $this->getType());
        }
    }
    private function getComparator(): Closure
    {
        return function (mixed $a, mixed $b): int {
            // If the two values are object, we convert them to unique scalars.
            // If the collection contains mixed values (unlikely) where some are objects
            // and some are not, we leave them as they are.
            // The comparator should still work and the result of $a < $b should
            // be consistent but unpredictable since not documented.
            if (is_object($a) && is_object($b)) {
                $a = spl_object_id($a);
                $b = spl_object_id($b);
            }
            return $a === $b ? 0 : ($a < $b ? 1 : -1);
        };
    }
    /**
     * @param CollectionInterface<mixed> $collection
     */
    private function getUniformType(CollectionInterface $collection): string
    {
        return match ($collection->getType()) {
            'integer' => 'int',
            'boolean' => 'bool',
            'double' => 'float',
            default => $collection->getType(),
        };
    }
}
<?php

/**
 * This file is part of the ramsey/collection library
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @copyright Copyright (c) Ben Ramsey <ben@benramsey.com>
 * @license http://opensource.org/licenses/MIT MIT
 */
declare (strict_types=1);
namespace _ContaoManager\Ramsey\Collection;

use ArrayIterator;
use Traversable;
use function count;
/**
 * This class provides a basic implementation of `ArrayInterface`, to minimize
 * the effort required to implement this interface.
 *
 * @template T
 * @implements ArrayInterface<T>
 */
abstract class AbstractArray implements ArrayInterface
{
    /**
     * The items of this array.
     *
     * @var array<array-key, T>
     */
    protected array $data = [];
    /**
     * Constructs a new array object.
     *
     * @param array<array-key, T> $data The initial items to add to this array.
     */
    public function __construct(array $data = [])
    {
        // Invoke offsetSet() for each value added; in this way, subclasses
        // may provide additional logic about values added to the array object.
        foreach ($data as $key => $value) {
            $this[$key] = $value;
        }
    }
    /**
     * Returns an iterator for this array.
     *
     * @link http://php.net/manual/en/iteratoraggregate.getiterator.php IteratorAggregate::getIterator()
     *
     * @return Traversable<array-key, T>
     */
    public function getIterator(): Traversable
    {
        return new ArrayIterator($this->data);
    }
    /**
     * Returns `true` if the given offset exists in this array.
     *
     * @link http://php.net/manual/en/arrayaccess.offsetexists.php ArrayAccess::offsetExists()
     *
     * @param array-key $offset The offset to check.
     */
    public function offsetExists(mixed $offset): bool
    {
        return isset($this->data[$offset]);
    }
    /**
     * Returns the value at the specified offset.
     *
     * @link http://php.net/manual/en/arrayaccess.offsetget.php ArrayAccess::offsetGet()
     *
     * @param array-key $offset The offset for which a value should be returned.
     *
     * @return T the value stored at the offset, or null if the offset
     *     does not exist.
     */
    public function offsetGet(mixed $offset): mixed
    {
        return $this->data[$offset];
    }
    /**
     * Sets the given value to the given offset in the array.
     *
     * @link http://php.net/manual/en/arrayaccess.offsetset.php ArrayAccess::offsetSet()
     *
     * @param array-key | null $offset The offset to set. If `null`, the value
     *     may be set at a numerically-indexed offset.
     * @param T $value The value to set at the given offset.
     */
    public function offsetSet(mixed $offset, mixed $value): void
    {
        if ($offset === null) {
            $this->data[] = $value;
        } else {
            $this->data[$offset] = $value;
        }
    }
    /**
     * Removes the given offset and its value from the array.
     *
     * @link http://php.net/manual/en/arrayaccess.offsetunset.php ArrayAccess::offsetUnset()
     *
     * @param array-key $offset The offset to remove from the array.
     */
    public function offsetUnset(mixed $offset): void
    {
        unset($this->data[$offset]);
    }
    /**
     * Returns data suitable for PHP serialization.
     *
     * @link https://www.php.net/manual/en/language.oop5.magic.php#language.oop5.magic.serialize
     * @link https://www.php.net/serialize
     *
     * @return array<array-key, T>
     */
    public function __serialize(): array
    {
        return $this->data;
    }
    /**
     * Adds unserialized data to the object.
     *
     * @param array<array-key, T> $data
     */
    public function __unserialize(array $data): void
    {
        $this->data = $data;
    }
    /**
     * Returns the number of items in this array.
     *
     * @link http://php.net/manual/en/countable.count.php Countable::count()
     */
    public function count(): int
    {
        return count($this->data);
    }
    public function clear(): void
    {
        $this->data = [];
    }
    /**
     * @inheritDoc
     */
    public function toArray(): array
    {
        return $this->data;
    }
    public function isEmpty(): bool
    {
        return $this->data === [];
    }
}
<?php

/**
 * This file is part of the ramsey/collection library
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @copyright Copyright (c) Ben Ramsey <ben@benramsey.com>
 * @license http://opensource.org/licenses/MIT MIT
 */
declare (strict_types=1);
namespace _ContaoManager\Ramsey\Collection;

use _ContaoManager\Ramsey\Collection\Exception\InvalidArgumentException;
use _ContaoManager\Ramsey\Collection\Exception\NoSuchElementException;
use _ContaoManager\Ramsey\Collection\Tool\TypeTrait;
use _ContaoManager\Ramsey\Collection\Tool\ValueToStringTrait;
use function array_key_first;
/**
 * This class provides a basic implementation of `QueueInterface`, to minimize
 * the effort required to implement this interface.
 *
 * @template T
 * @extends AbstractArray<T>
 * @implements QueueInterface<T>
 */
class Queue extends AbstractArray implements QueueInterface
{
    use TypeTrait;
    use ValueToStringTrait;
    /**
     * Constructs a queue object of the specified type, optionally with the
     * specified data.
     *
     * @param string $queueType The type or class name associated with this queue.
     * @param array<array-key, T> $data The initial items to store in the queue.
     */
    public function __construct(private readonly string $queueType, array $data = [])
    {
        parent::__construct($data);
    }
    /**
     * {@inheritDoc}
     *
     * Since arbitrary offsets may not be manipulated in a queue, this method
     * serves only to fulfill the `ArrayAccess` interface requirements. It is
     * invoked by other operations when adding values to the queue.
     *
     * @throws InvalidArgumentException if $value is of the wrong type.
     */
    public function offsetSet(mixed $offset, mixed $value): void
    {
        if ($this->checkType($this->getType(), $value) === \false) {
            throw new InvalidArgumentException('Value must be of type ' . $this->getType() . '; value is ' . $this->toolValueToString($value));
        }
        $this->data[] = $value;
    }
    /**
     * @throws InvalidArgumentException if $value is of the wrong type.
     */
    public function add(mixed $element): bool
    {
        $this[] = $element;
        return \true;
    }
    /**
     * @return T
     *
     * @throws NoSuchElementException if this queue is empty.
     */
    public function element(): mixed
    {
        return $this->peek() ?? throw new NoSuchElementException('Can\'t return element from Queue. Queue is empty.');
    }
    public function offer(mixed $element): bool
    {
        try {
            return $this->add($element);
        } catch (InvalidArgumentException) {
            return \false;
        }
    }
    /**
     * @return T | null
     */
    public function peek(): mixed
    {
        $index = array_key_first($this->data);
        if ($index === null) {
            return null;
        }
        return $this[$index];
    }
    /**
     * @return T | null
     */
    public function poll(): mixed
    {
        $index = array_key_first($this->data);
        if ($index === null) {
            return null;
        }
        $head = $this[$index];
        unset($this[$index]);
        return $head;
    }
    /**
     * @return T
     *
     * @throws NoSuchElementException if this queue is empty.
     */
    public function remove(): mixed
    {
        return $this->poll() ?? throw new NoSuchElementException('Can\'t return element from Queue. Queue is empty.');
    }
    public function getType(): string
    {
        return $this->queueType;
    }
}
<?php

/**
 * This file is part of the ramsey/collection library
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @copyright Copyright (c) Ben Ramsey <ben@benramsey.com>
 * @license http://opensource.org/licenses/MIT MIT
 */
declare (strict_types=1);
namespace _ContaoManager\Ramsey\Collection;

/**
 * A set is a collection that contains no duplicate elements.
 *
 * Great care must be exercised if mutable objects are used as set elements.
 * The behavior of a set is not specified if the value of an object is changed
 * in a manner that affects equals comparisons while the object is an element in
 * the set.
 *
 * Example usage:
 *
 * ```
 * $foo = new \My\Foo();
 * $set = new Set(\My\Foo::class);
 *
 * $set->add($foo); // returns TRUE, the element doesn't exist
 * $set->add($foo); // returns FALSE, the element already exists
 *
 * $bar = new \My\Foo();
 * $set->add($bar); // returns TRUE, $bar !== $foo
 * ```
 *
 * @template T
 * @extends AbstractSet<T>
 */
class Set extends AbstractSet
{
    /**
     * Constructs a set object of the specified type, optionally with the
     * specified data.
     *
     * @param string $setType The type or class name associated with this set.
     * @param array<array-key, T> $data The initial items to store in the set.
     */
    public function __construct(private readonly string $setType, array $data = [])
    {
        parent::__construct($data);
    }
    public function getType(): string
    {
        return $this->setType;
    }
}
<?php

/**
 * This file is part of the ramsey/collection library
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @copyright Copyright (c) Ben Ramsey <ben@benramsey.com>
 * @license http://opensource.org/licenses/MIT MIT
 */
declare (strict_types=1);
namespace _ContaoManager\Ramsey\Collection;

use _ContaoManager\Ramsey\Collection\Exception\NoSuchElementException;
use RuntimeException;
/**
 * A linear collection that supports element insertion and removal at both ends.
 *
 * Most `DoubleEndedQueueInterface` implementations place no fixed limits on the
 * number of elements they may contain, but this interface supports
 * capacity-restricted double-ended queues as well as those with no fixed size
 * limit.
 *
 * This interface defines methods to access the elements at both ends of the
 * double-ended queue. Methods are provided to insert, remove, and examine the
 * element. Each of these methods exists in two forms: one throws an exception
 * if the operation fails, the other returns a special value (either `null` or
 * `false`, depending on the operation). The latter form of the insert operation
 * is designed specifically for use with capacity-restricted implementations; in
 * most implementations, insert operations cannot fail.
 *
 * The twelve methods described above are summarized in the following table:
 *
 * <table>
 * <caption>Summary of DoubleEndedQueueInterface methods</caption>
 * <thead>
 * <tr>
 * <th></th>
 * <th colspan=2>First Element (Head)</th>
 * <th colspan=2>Last Element (Tail)</th>
 * </tr>
 * <tr>
 * <td></td>
 * <td><em>Throws exception</em></td>
 * <td><em>Special value</em></td>
 * <td><em>Throws exception</em></td>
 * <td><em>Special value</em></td>
 * </tr>
 * </thead>
 * <tbody>
 * <tr>
 * <th>Insert</th>
 * <td><code>addFirst()</code></td>
 * <td><code>offerFirst()</code></td>
 * <td><code>addLast()</code></td>
 * <td><code>offerLast()</code></td>
 * </tr>
 * <tr>
 * <th>Remove</th>
 * <td><code>removeFirst()</code></td>
 * <td><code>pollFirst()</code></td>
 * <td><code>removeLast()</code></td>
 * <td><code>pollLast()</code></td>
 * </tr>
 * <tr>
 * <th>Examine</th>
 * <td><code>firstElement()</code></td>
 * <td><code>peekFirst()</code></td>
 * <td><code>lastElement()</code></td>
 * <td><code>peekLast()</code></td>
 * </tr>
 * </tbody>
 * </table>
 *
 * This interface extends the `QueueInterface`. When a double-ended queue is
 * used as a queue, FIFO (first-in-first-out) behavior results. Elements are
 * added at the end of the double-ended queue and removed from the beginning.
 * The methods inherited from the `QueueInterface` are precisely equivalent to
 * `DoubleEndedQueueInterface` methods as indicated in the following table:
 *
 * <table>
 * <caption>Comparison of QueueInterface and DoubleEndedQueueInterface methods</caption>
 * <thead>
 * <tr>
 * <th>QueueInterface Method</th>
 * <th>DoubleEndedQueueInterface Method</th>
 * </tr>
 * </thead>
 * <tbody>
 * <tr>
 * <td><code>add()</code></td>
 * <td><code>addLast()</code></td>
 * </tr>
 * <tr>
 * <td><code>offer()</code></td>
 * <td><code>offerLast()</code></td>
 * </tr>
 * <tr>
 * <td><code>remove()</code></td>
 * <td><code>removeFirst()</code></td>
 * </tr>
 * <tr>
 * <td><code>poll()</code></td>
 * <td><code>pollFirst()</code></td>
 * </tr>
 * <tr>
 * <td><code>element()</code></td>
 * <td><code>firstElement()</code></td>
 * </tr>
 * <tr>
 * <td><code>peek()</code></td>
 * <td><code>peekFirst()</code></td>
 * </tr>
 * </tbody>
 * </table>
 *
 * Double-ended queues can also be used as LIFO (last-in-first-out) stacks. When
 * a double-ended queue is used as a stack, elements are pushed and popped from
 * the beginning of the double-ended queue. Stack concepts are precisely
 * equivalent to `DoubleEndedQueueInterface` methods as indicated in the table
 * below:
 *
 * <table>
 * <caption>Comparison of stack concepts and DoubleEndedQueueInterface methods</caption>
 * <thead>
 * <tr>
 * <th>Stack concept</th>
 * <th>DoubleEndedQueueInterface Method</th>
 * </tr>
 * </thead>
 * <tbody>
 * <tr>
 * <td><em>push</em></td>
 * <td><code>addFirst()</code></td>
 * </tr>
 * <tr>
 * <td><em>pop</em></td>
 * <td><code>removeFirst()</code></td>
 * </tr>
 * <tr>
 * <td><em>peek</em></td>
 * <td><code>peekFirst()</code></td>
 * </tr>
 * </tbody>
 * </table>
 *
 * Note that the `peek()` method works equally well when a double-ended queue is
 * used as a queue or a stack; in either case, elements are drawn from the
 * beginning of the double-ended queue.
 *
 * While `DoubleEndedQueueInterface` implementations are not strictly required
 * to prohibit the insertion of `null` elements, they are strongly encouraged to
 * do so. Users of any `DoubleEndedQueueInterface` implementations that do allow
 * `null` elements are strongly encouraged *not* to take advantage of the
 * ability to insert nulls. This is so because `null` is used as a special
 * return value by various methods to indicated that the double-ended queue is
 * empty.
 *
 * @template T
 * @extends QueueInterface<T>
 */
interface DoubleEndedQueueInterface extends QueueInterface
{
    /**
     * Inserts the specified element at the front of this queue if it is
     * possible to do so immediately without violating capacity restrictions.
     *
     * When using a capacity-restricted double-ended queue, it is generally
     * preferable to use the `offerFirst()` method.
     *
     * @param T $element The element to add to the front of this queue.
     *
     * @return bool `true` if this queue changed as a result of the call.
     *
     * @throws RuntimeException if a queue refuses to add a particular element
     *     for any reason other than that it already contains the element.
     *     Implementations should use a more-specific exception that extends
     *     `\RuntimeException`.
     */
    public function addFirst(mixed $element): bool;
    /**
     * Inserts the specified element at the end of this queue if it is possible
     * to do so immediately without violating capacity restrictions.
     *
     * When using a capacity-restricted double-ended queue, it is generally
     * preferable to use the `offerLast()` method.
     *
     * This method is equivalent to `add()`.
     *
     * @param T $element The element to add to the end of this queue.
     *
     * @return bool `true` if this queue changed as a result of the call.
     *
     * @throws RuntimeException if a queue refuses to add a particular element
     *     for any reason other than that it already contains the element.
     *     Implementations should use a more-specific exception that extends
     *     `\RuntimeException`.
     */
    public function addLast(mixed $element): bool;
    /**
     * Inserts the specified element at the front of this queue if it is
     * possible to do so immediately without violating capacity restrictions.
     *
     * When using a capacity-restricted queue, this method is generally
     * preferable to `addFirst()`, which can fail to insert an element only by
     * throwing an exception.
     *
     * @param T $element The element to add to the front of this queue.
     *
     * @return bool `true` if the element was added to this queue, else `false`.
     */
    public function offerFirst(mixed $element): bool;
    /**
     * Inserts the specified element at the end of this queue if it is possible
     * to do so immediately without violating capacity restrictions.
     *
     * When using a capacity-restricted queue, this method is generally
     * preferable to `addLast()` which can fail to insert an element only by
     * throwing an exception.
     *
     * @param T $element The element to add to the end of this queue.
     *
     * @return bool `true` if the element was added to this queue, else `false`.
     */
    public function offerLast(mixed $element): bool;
    /**
     * Retrieves and removes the head of this queue.
     *
     * This method differs from `pollFirst()` only in that it throws an
     * exception if this queue is empty.
     *
     * @return T the first element in this queue.
     *
     * @throws NoSuchElementException if this queue is empty.
     */
    public function removeFirst(): mixed;
    /**
     * Retrieves and removes the tail of this queue.
     *
     * This method differs from `pollLast()` only in that it throws an exception
     * if this queue is empty.
     *
     * @return T the last element in this queue.
     *
     * @throws NoSuchElementException if this queue is empty.
     */
    public function removeLast(): mixed;
    /**
     * Retrieves and removes the head of this queue, or returns `null` if this
     * queue is empty.
     *
     * @return T | null the head of this queue, or `null` if this queue is empty.
     */
    public function pollFirst(): mixed;
    /**
     * Retrieves and removes the tail of this queue, or returns `null` if this
     * queue is empty.
     *
     * @return T | null the tail of this queue, or `null` if this queue is empty.
     */
    public function pollLast(): mixed;
    /**
     * Retrieves, but does not remove, the head of this queue.
     *
     * This method differs from `peekFirst()` only in that it throws an
     * exception if this queue is empty.
     *
     * @return T the head of this queue.
     *
     * @throws NoSuchElementException if this queue is empty.
     */
    public function firstElement(): mixed;
    /**
     * Retrieves, but does not remove, the tail of this queue.
     *
     * This method differs from `peekLast()` only in that it throws an exception
     * if this queue is empty.
     *
     * @return T the tail of this queue.
     *
     * @throws NoSuchElementException if this queue is empty.
     */
    public function lastElement(): mixed;
    /**
     * Retrieves, but does not remove, the head of this queue, or returns `null`
     * if this queue is empty.
     *
     * @return T | null the head of this queue, or `null` if this queue is empty.
     */
    public function peekFirst(): mixed;
    /**
     * Retrieves, but does not remove, the tail of this queue, or returns `null`
     * if this queue is empty.
     *
     * @return T | null the tail of this queue, or `null` if this queue is empty.
     */
    public function peekLast(): mixed;
}
<?php

/**
 * This file is part of the ramsey/collection library
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @copyright Copyright (c) Ben Ramsey <ben@benramsey.com>
 * @license http://opensource.org/licenses/MIT MIT
 */
declare (strict_types=1);
namespace _ContaoManager\Ramsey\Collection\Map;

/**
 * A `TypedMapInterface` represents a map of elements where key and value are
 * typed.
 *
 * @template K of array-key
 * @template T
 * @extends MapInterface<K, T>
 */
interface TypedMapInterface extends MapInterface
{
    /**
     * Return the type used on the key.
     */
    public function getKeyType(): string;
    /**
     * Return the type forced on the values.
     */
    public function getValueType(): string;
}
<?php

/**
 * This file is part of the ramsey/collection library
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @copyright Copyright (c) Ben Ramsey <ben@benramsey.com>
 * @license http://opensource.org/licenses/MIT MIT
 */
declare (strict_types=1);
namespace _ContaoManager\Ramsey\Collection\Map;

use _ContaoManager\Ramsey\Collection\Exception\InvalidArgumentException;
use _ContaoManager\Ramsey\Collection\Tool\TypeTrait;
use _ContaoManager\Ramsey\Collection\Tool\ValueToStringTrait;
/**
 * This class provides a basic implementation of `TypedMapInterface`, to
 * minimize the effort required to implement this interface.
 *
 * @template K of array-key
 * @template T
 * @extends AbstractMap<K, T>
 * @implements TypedMapInterface<K, T>
 */
abstract class AbstractTypedMap extends AbstractMap implements TypedMapInterface
{
    use TypeTrait;
    use ValueToStringTrait;
    /**
     * @param K $offset
     * @param T $value
     *
     * @inheritDoc
     */
    public function offsetSet(mixed $offset, mixed $value): void
    {
        if ($this->checkType($this->getKeyType(), $offset) === \false) {
            throw new InvalidArgumentException('Key must be of type ' . $this->getKeyType() . '; key is ' . $this->toolValueToString($offset));
        }
        if ($this->checkType($this->getValueType(), $value) === \false) {
            throw new InvalidArgumentException('Value must be of type ' . $this->getValueType() . '; value is ' . $this->toolValueToString($value));
        }
        parent::offsetSet($offset, $value);
    }
}
<?php

/**
 * This file is part of the ramsey/collection library
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @copyright Copyright (c) Ben Ramsey <ben@benramsey.com>
 * @license http://opensource.org/licenses/MIT MIT
 */
declare (strict_types=1);
namespace _ContaoManager\Ramsey\Collection\Map;

use _ContaoManager\Ramsey\Collection\ArrayInterface;
/**
 * An object that maps keys to values.
 *
 * A map cannot contain duplicate keys; each key can map to at most one value.
 *
 * @template K of array-key
 * @template T
 * @extends ArrayInterface<T>
 */
interface MapInterface extends ArrayInterface
{
    /**
     * Returns `true` if this map contains a mapping for the specified key.
     *
     * @param K $key The key to check in the map.
     */
    public function containsKey(int|string $key): bool;
    /**
     * Returns `true` if this map maps one or more keys to the specified value.
     *
     * This performs a strict type check on the value.
     *
     * @param T $value The value to check in the map.
     */
    public function containsValue(mixed $value): bool;
    /**
     * Return an array of the keys contained in this map.
     *
     * @return list<K>
     */
    public function keys(): array;
    /**
     * Returns the value to which the specified key is mapped, `null` if this
     * map contains no mapping for the key, or (optionally) `$defaultValue` if
     * this map contains no mapping for the key.
     *
     * @param K $key The key to return from the map.
     * @param T | null $defaultValue The default value to use if `$key` is not found.
     *
     * @return T | null the value or `null` if the key could not be found.
     */
    public function get(int|string $key, mixed $defaultValue = null): mixed;
    /**
     * Associates the specified value with the specified key in this map.
     *
     * If the map previously contained a mapping for the key, the old value is
     * replaced by the specified value.
     *
     * @param K $key The key to put or replace in the map.
     * @param T $value The value to store at `$key`.
     *
     * @return T | null the previous value associated with key, or `null` if
     *     there was no mapping for `$key`.
     */
    public function put(int|string $key, mixed $value): mixed;
    /**
     * Associates the specified value with the specified key in this map only if
     * it is not already set.
     *
     * If there is already a value associated with `$key`, this returns that
     * value without replacing it.
     *
     * @param K $key The key to put in the map.
     * @param T $value The value to store at `$key`.
     *
     * @return T | null the previous value associated with key, or `null` if
     *     there was no mapping for `$key`.
     */
    public function putIfAbsent(int|string $key, mixed $value): mixed;
    /**
     * Removes the mapping for a key from this map if it is present.
     *
     * @param K $key The key to remove from the map.
     *
     * @return T | null the previous value associated with key, or `null` if
     *     there was no mapping for `$key`.
     */
    public function remove(int|string $key): mixed;
    /**
     * Removes the entry for the specified key only if it is currently mapped to
     * the specified value.
     *
     * This performs a strict type check on the value.
     *
     * @param K $key The key to remove from the map.
     * @param T $value The value to match.
     *
     * @return bool true if the value was removed.
     */
    public function removeIf(int|string $key, mixed $value): bool;
    /**
     * Replaces the entry for the specified key only if it is currently mapped
     * to some value.
     *
     * @param K $key The key to replace.
     * @param T $value The value to set at `$key`.
     *
     * @return T | null the previous value associated with key, or `null` if
     *     there was no mapping for `$key`.
     */
    public function replace(int|string $key, mixed $value): mixed;
    /**
     * Replaces the entry for the specified key only if currently mapped to the
     * specified value.
     *
     * This performs a strict type check on the value.
     *
     * @param K $key The key to remove from the map.
     * @param T $oldValue The value to match.
     * @param T $newValue The value to use as a replacement.
     *
     * @return bool true if the value was replaced.
     */
    public function replaceIf(int|string $key, mixed $oldValue, mixed $newValue): bool;
}
<?php

/**
 * This file is part of the ramsey/collection library
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @copyright Copyright (c) Ben Ramsey <ben@benramsey.com>
 * @license http://opensource.org/licenses/MIT MIT
 */
declare (strict_types=1);
namespace _ContaoManager\Ramsey\Collection\Map;

/**
 * A `TypedMap` represents a map of elements where key and value are typed.
 *
 * Each element is identified by a key with defined type and a value of defined
 * type. The keys of the map must be unique. The values on the map can be
 * repeated but each with its own different key.
 *
 * The most common case is to use a string type key, but it's not limited to
 * this type of keys.
 *
 * This is a direct implementation of `TypedMapInterface`, provided for the sake
 * of convenience.
 *
 * Example usage:
 *
 * ```
 * $map = new TypedMap('string', Foo::class);
 * $map['x'] = new Foo();
 * foreach ($map as $key => $value) {
 *     // do something with $key, it will be a Foo::class
 * }
 *
 * // this will throw an exception since key must be string
 * $map[10] = new Foo();
 *
 * // this will throw an exception since value must be a Foo
 * $map['bar'] = 'bar';
 *
 * // initialize map with contents
 * $map = new TypedMap('string', Foo::class, [
 *     new Foo(), new Foo(), new Foo()
 * ]);
 * ```
 *
 * It is preferable to subclass `AbstractTypedMap` to create your own typed map
 * implementation:
 *
 * ```
 * class FooTypedMap extends AbstractTypedMap
 * {
 *     public function getKeyType()
 *     {
 *         return 'int';
 *     }
 *
 *     public function getValueType()
 *     {
 *          return Foo::class;
 *     }
 * }
 * ```
 *
 * … but you also may use the `TypedMap` class:
 *
 * ```
 * class FooTypedMap extends TypedMap
 * {
 *     public function __constructor(array $data = [])
 *     {
 *         parent::__construct('int', Foo::class, $data);
 *     }
 * }
 * ```
 *
 * @template K of array-key
 * @template T
 * @extends AbstractTypedMap<K, T>
 */
class TypedMap extends AbstractTypedMap
{
    /**
     * Constructs a map object of the specified key and value types,
     * optionally with the specified data.
     *
     * @param string $keyType The data type of the map's keys.
     * @param string $valueType The data type of the map's values.
     * @param array<K, T> $data The initial data to set for this map.
     */
    public function __construct(private readonly string $keyType, private readonly string $valueType, array $data = [])
    {
        parent::__construct($data);
    }
    public function getKeyType(): string
    {
        return $this->keyType;
    }
    public function getValueType(): string
    {
        return $this->valueType;
    }
}
<?php

/**
 * This file is part of the ramsey/collection library
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @copyright Copyright (c) Ben Ramsey <ben@benramsey.com>
 * @license http://opensource.org/licenses/MIT MIT
 */
declare (strict_types=1);
namespace _ContaoManager\Ramsey\Collection\Map;

/**
 * `AssociativeArrayMap` represents a standard associative array object.
 *
 * @extends AbstractMap<string, mixed>
 */
class AssociativeArrayMap extends AbstractMap
{
}
<?php

/**
 * This file is part of the ramsey/collection library
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @copyright Copyright (c) Ben Ramsey <ben@benramsey.com>
 * @license http://opensource.org/licenses/MIT MIT
 */
declare (strict_types=1);
namespace _ContaoManager\Ramsey\Collection\Map;

use _ContaoManager\Ramsey\Collection\Exception\InvalidArgumentException;
use _ContaoManager\Ramsey\Collection\Tool\TypeTrait;
use _ContaoManager\Ramsey\Collection\Tool\ValueToStringTrait;
use function array_combine;
use function array_key_exists;
use function is_int;
/**
 * `NamedParameterMap` represents a mapping of values to a set of named keys
 * that may optionally be typed
 *
 * @extends AbstractMap<string, mixed>
 */
class NamedParameterMap extends AbstractMap
{
    use TypeTrait;
    use ValueToStringTrait;
    /**
     * Named parameters defined for this map.
     *
     * @var array<string, string>
     */
    private readonly array $namedParameters;
    /**
     * Constructs a new `NamedParameterMap`.
     *
     * @param array<array-key, string> $namedParameters The named parameters defined for this map.
     * @param array<string, mixed> $data An initial set of data to set on this map.
     */
    public function __construct(array $namedParameters, array $data = [])
    {
        $this->namedParameters = $this->filterNamedParameters($namedParameters);
        parent::__construct($data);
    }
    /**
     * Returns named parameters set for this `NamedParameterMap`.
     *
     * @return array<string, string>
     */
    public function getNamedParameters(): array
    {
        return $this->namedParameters;
    }
    public function offsetSet(mixed $offset, mixed $value): void
    {
        if (!array_key_exists($offset, $this->namedParameters)) {
            throw new InvalidArgumentException('Attempting to set value for unconfigured parameter \'' . $this->toolValueToString($offset) . '\'');
        }
        if ($this->checkType($this->namedParameters[$offset], $value) === \false) {
            throw new InvalidArgumentException('Value for \'' . $offset . '\' must be of type ' . $this->namedParameters[$offset] . '; value is ' . $this->toolValueToString($value));
        }
        $this->data[$offset] = $value;
    }
    /**
     * Given an array of named parameters, constructs a proper mapping of
     * named parameters to types.
     *
     * @param array<array-key, string> $namedParameters The named parameters to filter.
     *
     * @return array<string, string>
     */
    protected function filterNamedParameters(array $namedParameters): array
    {
        $names = [];
        $types = [];
        foreach ($namedParameters as $key => $value) {
            if (is_int($key)) {
                $names[] = $value;
                $types[] = 'mixed';
            } else {
                $names[] = $key;
                $types[] = $value;
            }
        }
        return array_combine($names, $types) ?: [];
    }
}
<?php

/**
 * This file is part of the ramsey/collection library
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @copyright Copyright (c) Ben Ramsey <ben@benramsey.com>
 * @license http://opensource.org/licenses/MIT MIT
 */
declare (strict_types=1);
namespace _ContaoManager\Ramsey\Collection\Map;

use _ContaoManager\Ramsey\Collection\AbstractArray;
use _ContaoManager\Ramsey\Collection\Exception\InvalidArgumentException;
use Traversable;
use function array_key_exists;
use function array_keys;
use function in_array;
use function var_export;
/**
 * This class provides a basic implementation of `MapInterface`, to minimize the
 * effort required to implement this interface.
 *
 * @template K of array-key
 * @template T
 * @extends AbstractArray<T>
 * @implements MapInterface<K, T>
 */
abstract class AbstractMap extends AbstractArray implements MapInterface
{
    /**
     * @param array<K, T> $data The initial items to add to this map.
     */
    public function __construct(array $data = [])
    {
        parent::__construct($data);
    }
    /**
     * @return Traversable<K, T>
     */
    public function getIterator(): Traversable
    {
        return parent::getIterator();
    }
    /**
     * @param K $offset The offset to set
     * @param T $value The value to set at the given offset.
     *
     * @inheritDoc
     */
    public function offsetSet(mixed $offset, mixed $value): void
    {
        if ($offset === null) {
            throw new InvalidArgumentException('Map elements are key/value pairs; a key must be provided for ' . 'value ' . var_export($value, \true));
        }
        $this->data[$offset] = $value;
    }
    public function containsKey(int|string $key): bool
    {
        return array_key_exists($key, $this->data);
    }
    public function containsValue(mixed $value): bool
    {
        return in_array($value, $this->data, \true);
    }
    /**
     * @inheritDoc
     */
    public function keys(): array
    {
        /** @var list<K> */
        return array_keys($this->data);
    }
    /**
     * @param K $key The key to return from the map.
     * @param T | null $defaultValue The default value to use if `$key` is not found.
     *
     * @return T | null the value or `null` if the key could not be found.
     */
    public function get(int|string $key, mixed $defaultValue = null): mixed
    {
        return $this[$key] ?? $defaultValue;
    }
    /**
     * @param K $key The key to put or replace in the map.
     * @param T $value The value to store at `$key`.
     *
     * @return T | null the previous value associated with key, or `null` if
     *     there was no mapping for `$key`.
     */
    public function put(int|string $key, mixed $value): mixed
    {
        $previousValue = $this->get($key);
        $this[$key] = $value;
        return $previousValue;
    }
    /**
     * @param K $key The key to put in the map.
     * @param T $value The value to store at `$key`.
     *
     * @return T | null the previous value associated with key, or `null` if
     *     there was no mapping for `$key`.
     */
    public function putIfAbsent(int|string $key, mixed $value): mixed
    {
        $currentValue = $this->get($key);
        if ($currentValue === null) {
            $this[$key] = $value;
        }
        return $currentValue;
    }
    /**
     * @param K $key The key to remove from the map.
     *
     * @return T | null the previous value associated with key, or `null` if
     *     there was no mapping for `$key`.
     */
    public function remove(int|string $key): mixed
    {
        $previousValue = $this->get($key);
        unset($this[$key]);
        return $previousValue;
    }
    public function removeIf(int|string $key, mixed $value): bool
    {
        if ($this->get($key) === $value) {
            unset($this[$key]);
            return \true;
        }
        return \false;
    }
    /**
     * @param K $key The key to replace.
     * @param T $value The value to set at `$key`.
     *
     * @return T | null the previous value associated with key, or `null` if
     *     there was no mapping for `$key`.
     */
    public function replace(int|string $key, mixed $value): mixed
    {
        $currentValue = $this->get($key);
        if ($this->containsKey($key)) {
            $this[$key] = $value;
        }
        return $currentValue;
    }
    public function replaceIf(int|string $key, mixed $oldValue, mixed $newValue): bool
    {
        if ($this->get($key) === $oldValue) {
            $this[$key] = $newValue;
            return \true;
        }
        return \false;
    }
    /**
     * @return array<K, T>
     */
    public function __serialize(): array
    {
        /** @var array<K, T> */
        return parent::__serialize();
    }
    /**
     * @return array<K, T>
     */
    public function toArray(): array
    {
        /** @var array<K, T> */
        return parent::toArray();
    }
}
<?php

/**
 * This file is part of the ramsey/collection library
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @copyright Copyright (c) Ben Ramsey <ben@benramsey.com>
 * @license http://opensource.org/licenses/MIT MIT
 */
declare (strict_types=1);
namespace _ContaoManager\Ramsey\Collection;

/**
 * `GenericArray` represents a standard array object.
 *
 * @extends AbstractArray<mixed>
 */
class GenericArray extends AbstractArray
{
}
<?php

/**
 * This file is part of the ramsey/collection library
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @copyright Copyright (c) Ben Ramsey <ben@benramsey.com>
 * @license http://opensource.org/licenses/MIT MIT
 */
declare (strict_types=1);
namespace _ContaoManager\Ramsey\Collection;

use ArrayAccess;
use Countable;
use IteratorAggregate;
/**
 * `ArrayInterface` provides traversable array functionality to data types.
 *
 * @template T
 * @extends ArrayAccess<array-key, T>
 * @extends IteratorAggregate<array-key, T>
 */
interface ArrayInterface extends ArrayAccess, Countable, IteratorAggregate
{
    /**
     * Removes all items from this array.
     */
    public function clear(): void;
    /**
     * Returns a native PHP array representation of this array object.
     *
     * @return array<array-key, T>
     */
    public function toArray(): array;
    /**
     * Returns `true` if this array is empty.
     */
    public function isEmpty(): bool;
}
<?php

/**
 * This file is part of the ramsey/collection library
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @copyright Copyright (c) Ben Ramsey <ben@benramsey.com>
 * @license http://opensource.org/licenses/MIT MIT
 */
declare (strict_types=1);
namespace _ContaoManager\Ramsey\Collection;

/**
 * Collection sorting
 */
enum Sort : string
{
    /**
     * Sort items in a collection in ascending order.
     */
    case Ascending = 'asc';
    /**
     * Sort items in a collection in descending order.
     */
    case Descending = 'desc';
}
<?php

/**
 * This file is part of the ramsey/collection library
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @copyright Copyright (c) Ben Ramsey <ben@benramsey.com>
 * @license http://opensource.org/licenses/MIT MIT
 */
declare (strict_types=1);
namespace _ContaoManager\Ramsey\Collection;

/**
 * A collection represents a group of objects.
 *
 * Each object in the collection is of a specific, defined type.
 *
 * This is a direct implementation of `CollectionInterface`, provided for
 * the sake of convenience.
 *
 * Example usage:
 *
 * ```
 * $collection = new \Ramsey\Collection\Collection('My\\Foo');
 * $collection->add(new \My\Foo());
 * $collection->add(new \My\Foo());
 *
 * foreach ($collection as $foo) {
 *     // Do something with $foo
 * }
 * ```
 *
 * It is preferable to subclass `AbstractCollection` to create your own typed
 * collections. For example:
 *
 * ```
 * namespace My\Foo;
 *
 * class FooCollection extends \Ramsey\Collection\AbstractCollection
 * {
 *     public function getType()
 *     {
 *         return 'My\\Foo';
 *     }
 * }
 * ```
 *
 * And then use it similarly to the earlier example:
 *
 * ```
 * $fooCollection = new \My\Foo\FooCollection();
 * $fooCollection->add(new \My\Foo());
 * $fooCollection->add(new \My\Foo());
 *
 * foreach ($fooCollection as $foo) {
 *     // Do something with $foo
 * }
 * ```
 *
 * The benefit with this approach is that you may do type-checking on the
 * collection object:
 *
 * ```
 * if ($collection instanceof \My\Foo\FooCollection) {
 *     // the collection is a collection of My\Foo objects
 * }
 * ```
 *
 * @template T
 * @extends AbstractCollection<T>
 */
class Collection extends AbstractCollection
{
    /**
     * Constructs a collection object of the specified type, optionally with the
     * specified data.
     *
     * @param string $collectionType The type or class name associated with this
     *     collection.
     * @param array<array-key, T> $data The initial items to store in the collection.
     */
    public function __construct(private readonly string $collectionType, array $data = [])
    {
        parent::__construct($data);
    }
    public function getType(): string
    {
        return $this->collectionType;
    }
}
<?php

/**
 * This file is part of the ramsey/collection library
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @copyright Copyright (c) Ben Ramsey <ben@benramsey.com>
 * @license http://opensource.org/licenses/MIT MIT
 */
declare (strict_types=1);
namespace _ContaoManager\Ramsey\Collection;

use _ContaoManager\Ramsey\Collection\Exception\CollectionMismatchException;
use _ContaoManager\Ramsey\Collection\Exception\InvalidArgumentException;
use _ContaoManager\Ramsey\Collection\Exception\InvalidPropertyOrMethod;
use _ContaoManager\Ramsey\Collection\Exception\NoSuchElementException;
use _ContaoManager\Ramsey\Collection\Exception\UnsupportedOperationException;
/**
 * A collection represents a group of values, known as its elements.
 *
 * Some collections allow duplicate elements and others do not. Some are ordered
 * and others unordered.
 *
 * @template T
 * @extends ArrayInterface<T>
 */
interface CollectionInterface extends ArrayInterface
{
    /**
     * Ensures that this collection contains the specified element (optional
     * operation).
     *
     * Returns `true` if this collection changed as a result of the call.
     * (Returns `false` if this collection does not permit duplicates and
     * already contains the specified element.)
     *
     * Collections that support this operation may place limitations on what
     * elements may be added to this collection. In particular, some
     * collections will refuse to add `null` elements, and others will impose
     * restrictions on the type of elements that may be added. Collection
     * classes should clearly specify in their documentation any restrictions
     * on what elements may be added.
     *
     * If a collection refuses to add a particular element for any reason other
     * than that it already contains the element, it must throw an exception
     * (rather than returning `false`). This preserves the invariant that a
     * collection always contains the specified element after this call returns.
     *
     * @param T $element The element to add to the collection.
     *
     * @return bool `true` if this collection changed as a result of the call.
     *
     * @throws InvalidArgumentException if the collection refuses to add the
     *     $element for any reason other than that it already contains the element.
     */
    public function add(mixed $element): bool;
    /**
     * Returns `true` if this collection contains the specified element.
     *
     * @param T $element The element to check whether the collection contains.
     * @param bool $strict Whether to perform a strict type check on the value.
     */
    public function contains(mixed $element, bool $strict = \true): bool;
    /**
     * Returns the type associated with this collection.
     */
    public function getType(): string;
    /**
     * Removes a single instance of the specified element from this collection,
     * if it is present.
     *
     * @param T $element The element to remove from the collection.
     *
     * @return bool `true` if an element was removed as a result of this call.
     */
    public function remove(mixed $element): bool;
    /**
     * Returns the values from the given property, method, or array key.
     *
     * @param string $propertyOrMethod The name of the property, method, or
     *     array key to evaluate and return.
     *
     * @return list<mixed>
     *
     * @throws InvalidPropertyOrMethod if the $propertyOrMethod does not exist
     *     on the elements in this collection.
     * @throws UnsupportedOperationException if unable to call column() on this
     *     collection.
     */
    public function column(string $propertyOrMethod): array;
    /**
     * Returns the first item of the collection.
     *
     * @return T
     *
     * @throws NoSuchElementException if this collection is empty.
     */
    public function first(): mixed;
    /**
     * Returns the last item of the collection.
     *
     * @return T
     *
     * @throws NoSuchElementException if this collection is empty.
     */
    public function last(): mixed;
    /**
     * Sort the collection by a property, method, or array key with the given
     * sort order.
     *
     * If $propertyOrMethod is `null`, this will sort by comparing each element.
     *
     * This will always leave the original collection untouched and will return
     * a new one.
     *
     * @param string | null $propertyOrMethod The property, method, or array key
     *     to sort by.
     * @param Sort $order The sort order for the resulting collection.
     *
     * @return CollectionInterface<T>
     *
     * @throws InvalidPropertyOrMethod if the $propertyOrMethod does not exist
     *     on the elements in this collection.
     * @throws UnsupportedOperationException if unable to call sort() on this
     *     collection.
     */
    public function sort(?string $propertyOrMethod = null, Sort $order = Sort::Ascending): self;
    /**
     * Filter out items of the collection which don't match the criteria of
     * given callback.
     *
     * This will always leave the original collection untouched and will return
     * a new one.
     *
     * See the {@link http://php.net/manual/en/function.array-filter.php PHP array_filter() documentation}
     * for examples of how the `$callback` parameter works.
     *
     * @param callable(T): bool $callback A callable to use for filtering elements.
     *
     * @return CollectionInterface<T>
     */
    public function filter(callable $callback): self;
    /**
     * Create a new collection where the result of the given property, method,
     * or array key of each item in the collection equals the given value.
     *
     * This will always leave the original collection untouched and will return
     * a new one.
     *
     * @param string | null $propertyOrMethod The property, method, or array key
     *     to evaluate. If `null`, the element itself is compared to $value.
     * @param mixed $value The value to match.
     *
     * @return CollectionInterface<T>
     *
     * @throws InvalidPropertyOrMethod if the $propertyOrMethod does not exist
     *     on the elements in this collection.
     * @throws UnsupportedOperationException if unable to call where() on this
     *     collection.
     */
    public function where(?string $propertyOrMethod, mixed $value): self;
    /**
     * Apply a given callback method on each item of the collection.
     *
     * This will always leave the original collection untouched. The new
     * collection is created by mapping the callback to each item of the
     * original collection.
     *
     * See the {@link http://php.net/manual/en/function.array-map.php PHP array_map() documentation}
     * for examples of how the `$callback` parameter works.
     *
     * @param callable(T): TCallbackReturn $callback A callable to apply to each
     *     item of the collection.
     *
     * @return CollectionInterface<TCallbackReturn>
     *
     * @template TCallbackReturn
     */
    public function map(callable $callback): self;
    /**
     * Apply a given callback method on each item of the collection
     * to reduce it to a single value.
     *
     * See the {@link http://php.net/manual/en/function.array-reduce.php PHP array_reduce() documentation}
     * for examples of how the `$callback` and `$initial` parameters work.
     *
     * @param callable(TCarry, T): TCarry $callback A callable to apply to each
     *     item of the collection to reduce it to a single value.
     * @param TCarry $initial This is the initial value provided to the callback.
     *
     * @return TCarry
     *
     * @template TCarry
     */
    public function reduce(callable $callback, mixed $initial): mixed;
    /**
     * Create a new collection with divergent items between current and given
     * collection.
     *
     * @param CollectionInterface<T> $other The collection to check for divergent
     *     items.
     *
     * @return CollectionInterface<T>
     *
     * @throws CollectionMismatchException if the compared collections are of
     *     differing types.
     */
    public function diff(CollectionInterface $other): self;
    /**
     * Create a new collection with intersecting item between current and given
     * collection.
     *
     * @param CollectionInterface<T> $other The collection to check for
     *     intersecting items.
     *
     * @return CollectionInterface<T>
     *
     * @throws CollectionMismatchException if the compared collections are of
     *     differing types.
     */
    public function intersect(CollectionInterface $other): self;
    /**
     * Merge current items and items of given collections into a new one.
     *
     * @param CollectionInterface<T> ...$collections The collections to merge.
     *
     * @return CollectionInterface<T>
     *
     * @throws CollectionMismatchException if unable to merge any of the given
     *     collections or items within the given collections due to type
     *     mismatch errors.
     */
    public function merge(CollectionInterface ...$collections): self;
}
<?php

/**
 * This file is part of the ramsey/collection library
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @copyright Copyright (c) Ben Ramsey <ben@benramsey.com>
 * @license http://opensource.org/licenses/MIT MIT
 */
declare (strict_types=1);
namespace _ContaoManager\Ramsey\Collection\Exception;

use RuntimeException;
/**
 * Thrown to indicate that the requested operation is not supported.
 */
class UnsupportedOperationException extends RuntimeException implements CollectionException
{
}
<?php

/**
 * This file is part of the ramsey/collection library
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @copyright Copyright (c) Ben Ramsey <ben@benramsey.com>
 * @license http://opensource.org/licenses/MIT MIT
 */
declare (strict_types=1);
namespace _ContaoManager\Ramsey\Collection\Exception;

use OutOfBoundsException as PhpOutOfBoundsException;
/**
 * Thrown when attempting to access an element out of the range of the collection.
 */
class OutOfBoundsException extends PhpOutOfBoundsException implements CollectionException
{
}
<?php

/**
 * This file is part of the ramsey/collection library
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @copyright Copyright (c) Ben Ramsey <ben@benramsey.com>
 * @license http://opensource.org/licenses/MIT MIT
 */
declare (strict_types=1);
namespace _ContaoManager\Ramsey\Collection\Exception;

use Throwable;
interface CollectionException extends Throwable
{
}
<?php

/**
 * This file is part of the ramsey/collection library
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @copyright Copyright (c) Ben Ramsey <ben@benramsey.com>
 * @license http://opensource.org/licenses/MIT MIT
 */
declare (strict_types=1);
namespace _ContaoManager\Ramsey\Collection\Exception;

use InvalidArgumentException as PhpInvalidArgumentException;
/**
 * Thrown to indicate an argument is not of the expected type.
 */
class InvalidArgumentException extends PhpInvalidArgumentException implements CollectionException
{
}
<?php

/**
 * This file is part of the ramsey/collection library
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @copyright Copyright (c) Ben Ramsey <ben@benramsey.com>
 * @license http://opensource.org/licenses/MIT MIT
 */
declare (strict_types=1);
namespace _ContaoManager\Ramsey\Collection\Exception;

use RuntimeException;
/**
 * Thrown when attempting to access an element that does not exist.
 */
class NoSuchElementException extends RuntimeException implements CollectionException
{
}
<?php

/**
 * This file is part of the ramsey/collection library
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @copyright Copyright (c) Ben Ramsey <ben@benramsey.com>
 * @license http://opensource.org/licenses/MIT MIT
 */
declare (strict_types=1);
namespace _ContaoManager\Ramsey\Collection\Exception;

use RuntimeException;
/**
 * Thrown when attempting to evaluate a property, method, or array key
 * that doesn't exist on an element or cannot otherwise be evaluated in the
 * current context.
 */
class InvalidPropertyOrMethod extends RuntimeException implements CollectionException
{
}
<?php

/**
 * This file is part of the ramsey/collection library
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @copyright Copyright (c) Ben Ramsey <ben@benramsey.com>
 * @license http://opensource.org/licenses/MIT MIT
 */
declare (strict_types=1);
namespace _ContaoManager\Ramsey\Collection\Exception;

use RuntimeException;
/**
 * Thrown when attempting to operate on collections of differing types.
 */
class CollectionMismatchException extends RuntimeException implements CollectionException
{
}
<?php

/**
 * This file is part of the ramsey/collection library
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @copyright Copyright (c) Ben Ramsey <ben@benramsey.com>
 * @license http://opensource.org/licenses/MIT MIT
 */
declare (strict_types=1);
namespace _ContaoManager\Ramsey\Collection\Tool;

use DateTimeInterface;
use function assert;
use function get_resource_type;
use function is_array;
use function is_bool;
use function is_callable;
use function is_object;
use function is_resource;
use function is_scalar;
/**
 * Provides functionality to express a value as string
 */
trait ValueToStringTrait
{
    /**
     * Returns a string representation of the value.
     *
     * - null value: `'NULL'`
     * - boolean: `'TRUE'`, `'FALSE'`
     * - array: `'Array'`
     * - scalar: converted-value
     * - resource: `'(type resource #number)'`
     * - object with `__toString()`: result of `__toString()`
     * - object DateTime: ISO 8601 date
     * - object: `'(className Object)'`
     * - anonymous function: same as object
     *
     * @param mixed $value the value to return as a string.
     */
    protected function toolValueToString(mixed $value): string
    {
        // null
        if ($value === null) {
            return 'NULL';
        }
        // boolean constants
        if (is_bool($value)) {
            return $value ? 'TRUE' : 'FALSE';
        }
        // array
        if (is_array($value)) {
            return 'Array';
        }
        // scalar types (integer, float, string)
        if (is_scalar($value)) {
            return (string) $value;
        }
        // resource
        if (is_resource($value)) {
            return '(' . get_resource_type($value) . ' resource #' . (int) $value . ')';
        }
        // From here, $value should be an object.
        assert(is_object($value));
        // __toString() is implemented
        if (is_callable([$value, '__toString'])) {
            /** @var string */
            return $value->__toString();
        }
        // object of type \DateTime
        if ($value instanceof DateTimeInterface) {
            return $value->format('c');
        }
        // unknown type
        return '(' . $value::class . ' Object)';
    }
}
<?php

/**
 * This file is part of the ramsey/collection library
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @copyright Copyright (c) Ben Ramsey <ben@benramsey.com>
 * @license http://opensource.org/licenses/MIT MIT
 */
declare (strict_types=1);
namespace _ContaoManager\Ramsey\Collection\Tool;

use function is_array;
use function is_bool;
use function is_callable;
use function is_float;
use function is_int;
use function is_numeric;
use function is_object;
use function is_resource;
use function is_scalar;
use function is_string;
/**
 * Provides functionality to check values for specific types.
 */
trait TypeTrait
{
    /**
     * Returns `true` if value is of the specified type.
     *
     * @param string $type The type to check the value against.
     * @param mixed $value The value to check.
     */
    protected function checkType(string $type, mixed $value): bool
    {
        return match ($type) {
            'array' => is_array($value),
            'bool', 'boolean' => is_bool($value),
            'callable' => is_callable($value),
            'float', 'double' => is_float($value),
            'int', 'integer' => is_int($value),
            'null' => $value === null,
            'numeric' => is_numeric($value),
            'object' => is_object($value),
            'resource' => is_resource($value),
            'scalar' => is_scalar($value),
            'string' => is_string($value),
            'mixed' => \true,
            default => $value instanceof $type,
        };
    }
}
<?php

/**
 * This file is part of the ramsey/collection library
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @copyright Copyright (c) Ben Ramsey <ben@benramsey.com>
 * @license http://opensource.org/licenses/MIT MIT
 */
declare (strict_types=1);
namespace _ContaoManager\Ramsey\Collection\Tool;

use _ContaoManager\Ramsey\Collection\Exception\InvalidPropertyOrMethod;
use _ContaoManager\Ramsey\Collection\Exception\UnsupportedOperationException;
use ReflectionProperty;
use function is_array;
use function is_object;
use function method_exists;
use function property_exists;
use function sprintf;
/**
 * Provides functionality to extract the value of a property or method from an object.
 */
trait ValueExtractorTrait
{
    /**
     * Returns the type associated with this collection.
     */
    abstract public function getType(): string;
    /**
     * Extracts the value of the given property, method, or array key from the
     * element.
     *
     * If `$propertyOrMethod` is `null`, we return the element as-is.
     *
     * @param mixed $element The element to extract the value from.
     * @param string | null $propertyOrMethod The property or method for which the
     *     value should be extracted.
     *
     * @return mixed the value extracted from the specified property, method,
     *     or array key, or the element itself.
     *
     * @throws InvalidPropertyOrMethod
     * @throws UnsupportedOperationException
     */
    protected function extractValue(mixed $element, ?string $propertyOrMethod): mixed
    {
        if ($propertyOrMethod === null) {
            return $element;
        }
        if (!is_object($element) && !is_array($element)) {
            throw new UnsupportedOperationException(sprintf('The collection type "%s" does not support the $propertyOrMethod parameter', $this->getType()));
        }
        if (is_array($element)) {
            return $element[$propertyOrMethod] ?? throw new InvalidPropertyOrMethod(sprintf('Key or index "%s" not found in collection elements', $propertyOrMethod));
        }
        if (property_exists($element, $propertyOrMethod) && method_exists($element, $propertyOrMethod)) {
            $reflectionProperty = new ReflectionProperty($element, $propertyOrMethod);
            if ($reflectionProperty->isPublic()) {
                return $element->{$propertyOrMethod};
            }
            return $element->{$propertyOrMethod}();
        }
        if (property_exists($element, $propertyOrMethod)) {
            return $element->{$propertyOrMethod};
        }
        if (method_exists($element, $propertyOrMethod)) {
            return $element->{$propertyOrMethod}();
        }
        if (isset($element->{$propertyOrMethod})) {
            return $element->{$propertyOrMethod};
        }
        throw new InvalidPropertyOrMethod(sprintf('Method or property "%s" not defined in %s', $propertyOrMethod, $element::class));
    }
}
Copyright (c) 2012-2025 Ben Ramsey <ben@benramsey.com>

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
<h1 align="center">ramsey/uuid</h1>

<p align="center">
    <strong>A PHP library for generating and working with UUIDs.</strong>
</p>

<p align="center">
    <a href="https://github.com/ramsey/uuid"><img src="http://img.shields.io/badge/source-ramsey/uuid-blue.svg?style=flat-square" alt="Source Code"></a>
    <a href="https://packagist.org/packages/ramsey/uuid"><img src="https://img.shields.io/packagist/v/ramsey/uuid.svg?style=flat-square&label=release" alt="Download Package"></a>
    <a href="https://php.net"><img src="https://img.shields.io/packagist/php-v/ramsey/uuid.svg?style=flat-square&colorB=%238892BF" alt="PHP Programming Language"></a>
    <a href="https://github.com/ramsey/uuid/blob/4.x/LICENSE"><img src="https://img.shields.io/packagist/l/ramsey/uuid.svg?style=flat-square&colorB=darkcyan" alt="Read License"></a>
    <a href="https://github.com/ramsey/uuid/actions/workflows/continuous-integration.yml"><img src="https://img.shields.io/github/actions/workflow/status/ramsey/uuid/continuous-integration.yml?branch=4.x&logo=github&style=flat-square" alt="Build Status"></a>
    <a href="https://app.codecov.io/gh/ramsey/uuid/branch/4.x"><img src="https://img.shields.io/codecov/c/github/ramsey/uuid/4.x?label=codecov&logo=codecov&style=flat-square" alt="Codecov Code Coverage"></a>
</p>

ramsey/uuid is a PHP library for generating and working with universally unique
identifiers (UUIDs).

This project adheres to a [code of conduct](CODE_OF_CONDUCT.md).
By participating in this project and its community, you are expected to
uphold this code.

Much inspiration for this library came from the [Java][javauuid] and
[Python][pyuuid] UUID libraries.

## Installation

The preferred method of installation is via [Composer][]. Run the following
command to install the package and add it as a requirement to your project's
`composer.json`:

```bash
composer require ramsey/uuid
```

## Upgrading to Version 4

See the documentation for a thorough upgrade guide:

* [Upgrading ramsey/uuid Version 3 to 4](https://uuid.ramsey.dev/en/stable/upgrading/3-to-4.html)

## Documentation

Please see <https://uuid.ramsey.dev> for documentation, tips, examples, and
frequently asked questions.

## Contributing

Contributions are welcome! To contribute, please familiarize yourself with
[CONTRIBUTING.md](CONTRIBUTING.md).

## Coordinated Disclosure

Keeping user information safe and secure is a top priority, and we welcome the
contribution of external security researchers. If you believe you've found a
security issue in software that is maintained in this repository, please read
[SECURITY.md][] for instructions on submitting a vulnerability report.

## ramsey/uuid for Enterprise

Available as part of the Tidelift Subscription.

The maintainers of ramsey/uuid and thousands of other packages are working with
Tidelift to deliver commercial support and maintenance for the open source
packages you use to build your applications. Save time, reduce risk, and improve
code health, while paying the maintainers of the exact packages you use.
[Learn more.](https://tidelift.com/subscription/pkg/packagist-ramsey-uuid?utm_source=undefined&utm_medium=referral&utm_campaign=enterprise&utm_term=repo)

## Copyright and License

The ramsey/uuid library is copyright © [Ben Ramsey](https://benramsey.com/) and
licensed for use under the MIT License (MIT). Please see [LICENSE][] for more
information.

[rfc4122]: http://tools.ietf.org/html/rfc4122
[conduct]: https://github.com/ramsey/uuid/blob/4.x/CODE_OF_CONDUCT.md
[javauuid]: http://docs.oracle.com/javase/6/docs/api/java/util/UUID.html
[pyuuid]: http://docs.python.org/3/library/uuid.html
[composer]: http://getcomposer.org/
[contributing.md]: https://github.com/ramsey/uuid/blob/4.x/CONTRIBUTING.md
[security.md]: https://github.com/ramsey/uuid/blob/4.x/SECURITY.md
[license]: https://github.com/ramsey/uuid/blob/4.x/LICENSE
{
    "name": "ramsey\/uuid",
    "description": "A PHP library for generating and working with universally unique identifiers (UUIDs).",
    "license": "MIT",
    "type": "library",
    "keywords": [
        "uuid",
        "identifier",
        "guid"
    ],
    "require": {
        "php": "^8.0",
        "brick\/math": "^0.8.16 || ^0.9 || ^0.10 || ^0.11 || ^0.12 || ^0.13 || ^0.14",
        "ramsey\/collection": "^1.2 || ^2.0"
    },
    "require-dev": {
        "captainhook\/captainhook": "^5.25",
        "captainhook\/plugin-composer": "^5.3",
        "dealerdirect\/phpcodesniffer-composer-installer": "^1.0",
        "ergebnis\/composer-normalize": "^2.47",
        "mockery\/mockery": "^1.6",
        "paragonie\/random-lib": "^2",
        "php-mock\/php-mock": "^2.6",
        "php-mock\/php-mock-mockery": "^1.5",
        "php-parallel-lint\/php-parallel-lint": "^1.4.0",
        "phpbench\/phpbench": "^1.2.14",
        "phpstan\/extension-installer": "^1.4",
        "phpstan\/phpstan": "^2.1",
        "phpstan\/phpstan-mockery": "^2.0",
        "phpstan\/phpstan-phpunit": "^2.0",
        "phpunit\/phpunit": "^9.6",
        "slevomat\/coding-standard": "^8.18",
        "squizlabs\/php_codesniffer": "^3.13"
    },
    "replace": {
        "rhumsaa\/uuid": "self.version"
    },
    "suggest": {
        "ext-bcmath": "Enables faster math with arbitrary-precision integers using BCMath.",
        "ext-gmp": "Enables faster math with arbitrary-precision integers using GMP.",
        "ext-uuid": "Enables the use of PeclUuidTimeGenerator and PeclUuidRandomGenerator.",
        "paragonie\/random-lib": "Provides RandomLib for use with the RandomLibAdapter",
        "ramsey\/uuid-doctrine": "Allows the use of Ramsey\\Uuid\\Uuid as Doctrine field type."
    },
    "minimum-stability": "dev",
    "prefer-stable": true,
    "autoload": {
        "psr-4": {
            "_ContaoManager\\Ramsey\\Uuid\\": "src\/"
        },
        "files": [
            "src\/functions.php"
        ]
    },
    "autoload-dev": {
        "psr-4": {
            "_ContaoManager\\Ramsey\\Uuid\\Benchmark\\": "tests\/benchmark\/",
            "_ContaoManager\\Ramsey\\Uuid\\StaticAnalysis\\": "tests\/static-analysis\/",
            "_ContaoManager\\Ramsey\\Uuid\\Test\\": "tests\/"
        }
    },
    "config": {
        "allow-plugins": {
            "captainhook\/plugin-composer": true,
            "dealerdirect\/phpcodesniffer-composer-installer": true,
            "ergebnis\/composer-normalize": true,
            "phpstan\/extension-installer": true
        },
        "sort-packages": true
    },
    "extra": {
        "captainhook": {
            "force-install": true
        }
    },
    "scripts": {
        "dev:analyze": "@dev:analyze:phpstan",
        "dev:analyze:phpstan": "phpstan analyse --ansi --memory-limit 1G",
        "dev:bench": "@php -d 'error_reporting=24575' vendor\/bin\/phpbench run",
        "dev:build:clean": "git clean -fX build\/",
        "dev:lint": [
            "@dev:lint:syntax",
            "@dev:lint:style"
        ],
        "dev:lint:fix": "phpcbf --cache=build\/cache\/phpcs.cache",
        "dev:lint:style": "phpcs --cache=build\/cache\/phpcs.cache --colors",
        "dev:lint:syntax": "parallel-lint --colors src\/ tests\/",
        "dev:test": [
            "@dev:lint",
            "@dev:bench",
            "@dev:analyze",
            "@dev:test:unit"
        ],
        "dev:test:coverage:ci": "@php -d 'xdebug.mode=coverage' vendor\/bin\/phpunit --colors=always --coverage-text --coverage-clover build\/coverage\/clover.xml --coverage-cobertura build\/coverage\/cobertura.xml --coverage-crap4j build\/coverage\/crap4j.xml --coverage-xml build\/coverage\/coverage-xml --log-junit build\/junit.xml",
        "dev:test:coverage:html": "@php -d 'xdebug.mode=coverage' vendor\/bin\/phpunit --colors=always --coverage-html build\/coverage\/coverage-html\/",
        "dev:test:unit": "phpunit --colors=always",
        "test": "@dev:test"
    },
    "scripts-descriptions": {
        "dev:analyze": "Runs all static analysis checks.",
        "dev:analyze:phpstan": "Runs the PHPStan static analyzer.",
        "dev:bench": "Runs PHPBench benchmark tests.",
        "dev:build:clean": "Cleans the build\/ directory.",
        "dev:lint": "Runs all linting checks.",
        "dev:lint:fix": "Auto-fixes coding standards issues, if possible.",
        "dev:lint:style": "Checks for coding standards issues.",
        "dev:lint:syntax": "Checks for syntax errors.",
        "dev:test": "Runs linting, static analysis, and unit tests.",
        "dev:test:coverage:ci": "Runs unit tests and generates CI coverage reports.",
        "dev:test:coverage:html": "Runs unit tests and generates HTML coverage report.",
        "dev:test:unit": "Runs unit tests.",
        "test": "Runs linting, static analysis, and unit tests."
    }
}<?php

/**
 * This file is part of the ramsey/uuid library
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @copyright Copyright (c) Ben Ramsey <ben@benramsey.com>
 * @license http://opensource.org/licenses/MIT MIT
 * phpcs:disable Squiz.Functions.GlobalFunction
 */
declare (strict_types=1);
namespace _ContaoManager\Ramsey\Uuid;

use DateTimeInterface;
use _ContaoManager\Ramsey\Uuid\Type\Hexadecimal;
use _ContaoManager\Ramsey\Uuid\Type\Integer as IntegerObject;
/**
 * Returns a version 1 (Gregorian time) UUID from a host ID, sequence number, and the current time
 *
 * @param Hexadecimal | int | string | null $node A 48-bit number representing the hardware address; this number may be
 *     represented as an integer or a hexadecimal string
 * @param int | null $clockSeq A 14-bit number used to help avoid duplicates that could arise when the clock is set
 *     backwards in time or if the node ID changes
 *
 * @return non-empty-string Version 1 UUID as a string
 */
function v1($node = null, ?int $clockSeq = null): string
{
    return Uuid::uuid1($node, $clockSeq)->toString();
}
/**
 * Returns a version 2 (DCE Security) UUID from a local domain, local identifier, host ID, clock sequence, and the current time
 *
 * @param int $localDomain The local domain to use when generating bytes, according to DCE Security
 * @param IntegerObject | null $localIdentifier The local identifier for the given domain; this may be a UID or GID on
 *     POSIX systems, if the local domain is a person or group, or it may be a site-defined identifier if the local
 *     domain is org
 * @param Hexadecimal | null $node A 48-bit number representing the hardware address
 * @param int | null $clockSeq A 14-bit number used to help avoid duplicates that could arise when the clock is set
 *     backwards in time or if the node ID changes
 *
 * @return non-empty-string Version 2 UUID as a string
 */
function v2(int $localDomain, ?IntegerObject $localIdentifier = null, ?Hexadecimal $node = null, ?int $clockSeq = null): string
{
    return Uuid::uuid2($localDomain, $localIdentifier, $node, $clockSeq)->toString();
}
/**
 * Returns a version 3 (name-based) UUID based on the MD5 hash of a namespace ID and a name
 *
 * @param UuidInterface | string $ns The namespace (must be a valid UUID)
 *
 * @return non-empty-string Version 3 UUID as a string
 *
 * @pure
 */
function v3($ns, string $name): string
{
    return Uuid::uuid3($ns, $name)->toString();
}
/**
 * Returns a version 4 (random) UUID
 *
 * @return non-empty-string Version 4 UUID as a string
 */
function v4(): string
{
    return Uuid::uuid4()->toString();
}
/**
 * Returns a version 5 (name-based) UUID based on the SHA-1 hash of a namespace ID and a name
 *
 * @param UuidInterface | string $ns The namespace (must be a valid UUID)
 *
 * @return non-empty-string Version 5 UUID as a string
 *
 * @pure
 */
function v5($ns, string $name): string
{
    return Uuid::uuid5($ns, $name)->toString();
}
/**
 * Returns a version 6 (reordered Gregorian time) UUID from a host ID, sequence number, and the current time
 *
 * @param Hexadecimal | null $node A 48-bit number representing the hardware address
 * @param int | null $clockSeq A 14-bit number used to help avoid duplicates that could arise when the clock is set
 *     backwards in time or if the node ID changes
 *
 * @return non-empty-string Version 6 UUID as a string
 */
function v6(?Hexadecimal $node = null, ?int $clockSeq = null): string
{
    return Uuid::uuid6($node, $clockSeq)->toString();
}
/**
 * Returns a version 7 (Unix Epoch time) UUID
 *
 * @param DateTimeInterface|null $dateTime An optional date/time from which to create the version 7 UUID. If not
 *     provided, the UUID is generated using the current date/time.
 *
 * @return non-empty-string Version 7 UUID as a string
 */
function v7(?DateTimeInterface $dateTime = null): string
{
    return Uuid::uuid7($dateTime)->toString();
}
/**
 * Returns a version 8 (custom format) UUID
 *
 * The bytes provided may contain any value according to your application's needs. Be aware, however, that other
 * applications may not understand the semantics of the value.
 *
 * @param string $bytes A 16-byte octet string. This is an open blob of data that you may fill with 128 bits of
 *     information. Be aware, however, bits 48 through 51 will be replaced with the UUID version field, and bits 64 and
 *     65 will be replaced with the UUID variant. You MUST NOT rely on these bits for your application needs.
 *
 * @return non-empty-string Version 8 UUID as a string
 *
 * @pure
 */
function v8(string $bytes): string
{
    return Uuid::uuid8($bytes)->toString();
}
<?php

/**
 * This file is part of the ramsey/uuid library
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @copyright Copyright (c) Ben Ramsey <ben@benramsey.com>
 * @license http://opensource.org/licenses/MIT MIT
 */
declare (strict_types=1);
namespace _ContaoManager\Ramsey\Uuid\Validator;

use _ContaoManager\Ramsey\Uuid\Uuid;
use function preg_match;
use function str_replace;
/**
 * GenericValidator validates strings as UUIDs of any variant
 *
 * @immutable
 */
final class GenericValidator implements ValidatorInterface
{
    /**
     * Regular expression pattern for matching a UUID of any variant.
     */
    private const VALID_PATTERN = '\A[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{12}\z';
    /**
     * @return non-empty-string
     */
    public function getPattern(): string
    {
        return self::VALID_PATTERN;
    }
    public function validate(string $uuid): bool
    {
        /** @phpstan-ignore possiblyImpure.functionCall */
        $uuid = str_replace(['urn:', 'uuid:', 'URN:', 'UUID:', '{', '}'], '', $uuid);
        /** @phpstan-ignore possiblyImpure.functionCall */
        return $uuid === Uuid::NIL || preg_match('/' . self::VALID_PATTERN . '/Dms', $uuid);
    }
}
<?php

/**
 * This file is part of the ramsey/uuid library
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @copyright Copyright (c) Ben Ramsey <ben@benramsey.com>
 * @license http://opensource.org/licenses/MIT MIT
 */
declare (strict_types=1);
namespace _ContaoManager\Ramsey\Uuid\Validator;

/**
 * A validator validates a string as a proper UUID
 *
 * @immutable
 */
interface ValidatorInterface
{
    /**
     * Returns the regular expression pattern used by this validator
     *
     * @return non-empty-string The regular expression pattern this validator uses
     */
    public function getPattern(): string;
    /**
     * Returns true if the provided string represents a UUID
     *
     * @param string $uuid The string to validate as a UUID
     *
     * @return bool True if the string is a valid UUID, false otherwise
     *
     * @pure
     */
    public function validate(string $uuid): bool;
}
<?php

/**
 * This file is part of the ramsey/uuid library
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @copyright Copyright (c) Ben Ramsey <ben@benramsey.com>
 * @license http://opensource.org/licenses/MIT MIT
 */
declare (strict_types=1);
namespace _ContaoManager\Ramsey\Uuid\Converter\Time;

use _ContaoManager\Ramsey\Uuid\Converter\TimeConverterInterface;
use _ContaoManager\Ramsey\Uuid\Math\CalculatorInterface;
use _ContaoManager\Ramsey\Uuid\Math\RoundingMode;
use _ContaoManager\Ramsey\Uuid\Type\Hexadecimal;
use _ContaoManager\Ramsey\Uuid\Type\Integer as IntegerObject;
use _ContaoManager\Ramsey\Uuid\Type\Time;
use function explode;
use function str_pad;
use const STR_PAD_LEFT;
/**
 * GenericTimeConverter uses the provided calculator to calculate and convert time values
 *
 * @immutable
 */
class GenericTimeConverter implements TimeConverterInterface
{
    /**
     * The number of 100-nanosecond intervals from the Gregorian calendar epoch to the Unix epoch.
     */
    private const GREGORIAN_TO_UNIX_INTERVALS = '122192928000000000';
    /**
     * The number of 100-nanosecond intervals in one second.
     */
    private const SECOND_INTERVALS = '10000000';
    /**
     * The number of 100-nanosecond intervals in one microsecond.
     */
    private const MICROSECOND_INTERVALS = '10';
    public function __construct(private CalculatorInterface $calculator)
    {
    }
    public function calculateTime(string $seconds, string $microseconds): Hexadecimal
    {
        /** @phpstan-ignore possiblyImpure.new */
        $timestamp = new Time($seconds, $microseconds);
        // Convert the seconds into a count of 100-nanosecond intervals.
        $sec = $this->calculator->multiply($timestamp->getSeconds(), new IntegerObject(self::SECOND_INTERVALS));
        // Convert the microseconds into a count of 100-nanosecond intervals.
        $usec = $this->calculator->multiply($timestamp->getMicroseconds(), new IntegerObject(self::MICROSECOND_INTERVALS));
        /**
         * Combine the intervals of seconds and microseconds and add the count of 100-nanosecond intervals from the
         * Gregorian calendar epoch to the Unix epoch. This gives us the correct count of 100-nanosecond intervals since
         * the Gregorian calendar epoch for the given seconds and microseconds.
         *
         * @var IntegerObject $uuidTime
         * @phpstan-ignore possiblyImpure.new
         */
        $uuidTime = $this->calculator->add($sec, $usec, new IntegerObject(self::GREGORIAN_TO_UNIX_INTERVALS));
        /**
         * PHPStan considers CalculatorInterface::toHexadecimal, Hexadecimal:toString impure.
         *
         * @phpstan-ignore possiblyImpure.new
         */
        return new Hexadecimal(str_pad($this->calculator->toHexadecimal($uuidTime)->toString(), 16, '0', STR_PAD_LEFT));
    }
    public function convertTime(Hexadecimal $uuidTimestamp): Time
    {
        // From the total, subtract the number of 100-nanosecond intervals from the Gregorian calendar epoch to the Unix
        // epoch. This gives us the number of 100-nanosecond intervals from the Unix epoch, which also includes the microtime.
        $epochNanoseconds = $this->calculator->subtract($this->calculator->toInteger($uuidTimestamp), new IntegerObject(self::GREGORIAN_TO_UNIX_INTERVALS));
        // Convert the 100-nanosecond intervals into seconds and microseconds.
        $unixTimestamp = $this->calculator->divide(RoundingMode::HALF_UP, 6, $epochNanoseconds, new IntegerObject(self::SECOND_INTERVALS));
        $split = explode('.', (string) $unixTimestamp, 2);
        /** @phpstan-ignore possiblyImpure.new */
        return new Time($split[0], $split[1] ?? 0);
    }
}
<?php

/**
 * This file is part of the ramsey/uuid library
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @copyright Copyright (c) Ben Ramsey <ben@benramsey.com>
 * @license http://opensource.org/licenses/MIT MIT
 */
declare (strict_types=1);
namespace _ContaoManager\Ramsey\Uuid\Converter\Time;

use _ContaoManager\Ramsey\Uuid\Converter\TimeConverterInterface;
use _ContaoManager\Ramsey\Uuid\Math\CalculatorInterface;
use _ContaoManager\Ramsey\Uuid\Math\RoundingMode;
use _ContaoManager\Ramsey\Uuid\Type\Hexadecimal;
use _ContaoManager\Ramsey\Uuid\Type\Integer as IntegerObject;
use _ContaoManager\Ramsey\Uuid\Type\Time;
use function explode;
use function str_pad;
use const STR_PAD_LEFT;
/**
 * UnixTimeConverter converts Unix Epoch timestamps to/from hexadecimal values consisting of milliseconds elapsed since
 * the Unix Epoch
 *
 * @immutable
 */
class UnixTimeConverter implements TimeConverterInterface
{
    private const MILLISECONDS = 1000;
    public function __construct(private CalculatorInterface $calculator)
    {
    }
    public function calculateTime(string $seconds, string $microseconds): Hexadecimal
    {
        /** @phpstan-ignore possiblyImpure.new */
        $timestamp = new Time($seconds, $microseconds);
        // Convert the seconds into milliseconds.
        $sec = $this->calculator->multiply($timestamp->getSeconds(), new IntegerObject(self::MILLISECONDS));
        // Convert the microseconds into milliseconds; the scale is zero because we need to discard the fractional part.
        $usec = $this->calculator->divide(
            RoundingMode::DOWN,
            // Always round down to stay in the previous millisecond.
            0,
            $timestamp->getMicroseconds(),
            new IntegerObject(self::MILLISECONDS)
        );
        /** @var IntegerObject $unixTime */
        $unixTime = $this->calculator->add($sec, $usec);
        /** @phpstan-ignore possiblyImpure.new */
        return new Hexadecimal(str_pad($this->calculator->toHexadecimal($unixTime)->toString(), 12, '0', STR_PAD_LEFT));
    }
    public function convertTime(Hexadecimal $uuidTimestamp): Time
    {
        $milliseconds = $this->calculator->toInteger($uuidTimestamp);
        $unixTimestamp = $this->calculator->divide(RoundingMode::HALF_UP, 6, $milliseconds, new IntegerObject(self::MILLISECONDS));
        $split = explode('.', (string) $unixTimestamp, 2);
        /** @phpstan-ignore possiblyImpure.new */
        return new Time($split[0], $split[1] ?? '0');
    }
}
<?php

/**
 * This file is part of the ramsey/uuid library
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @copyright Copyright (c) Ben Ramsey <ben@benramsey.com>
 * @license http://opensource.org/licenses/MIT MIT
 */
declare (strict_types=1);
namespace _ContaoManager\Ramsey\Uuid\Converter\Time;

use _ContaoManager\Ramsey\Uuid\Converter\TimeConverterInterface;
use _ContaoManager\Ramsey\Uuid\Math\BrickMathCalculator;
use _ContaoManager\Ramsey\Uuid\Math\CalculatorInterface;
use _ContaoManager\Ramsey\Uuid\Type\Hexadecimal;
use _ContaoManager\Ramsey\Uuid\Type\Integer as IntegerObject;
use _ContaoManager\Ramsey\Uuid\Type\Time;
use function count;
use function dechex;
use function explode;
use function is_float;
use function is_int;
use function str_pad;
use function strlen;
use function substr;
use const STR_PAD_LEFT;
use const STR_PAD_RIGHT;
/**
 * PhpTimeConverter uses built-in PHP functions and standard math operations available to the PHP programming language
 * to provide facilities for converting parts of time into representations that may be used in UUIDs
 *
 * @immutable
 */
class PhpTimeConverter implements TimeConverterInterface
{
    /**
     * The number of 100-nanosecond intervals from the Gregorian calendar epoch to the Unix epoch.
     */
    private const GREGORIAN_TO_UNIX_INTERVALS = 0x1b21dd213814000;
    /**
     * The number of 100-nanosecond intervals in one second.
     */
    private const SECOND_INTERVALS = 10000000;
    /**
     * The number of 100-nanosecond intervals in one microsecond.
     */
    private const MICROSECOND_INTERVALS = 10;
    private int $phpPrecision;
    private CalculatorInterface $calculator;
    private TimeConverterInterface $fallbackConverter;
    public function __construct(?CalculatorInterface $calculator = null, ?TimeConverterInterface $fallbackConverter = null)
    {
        if ($calculator === null) {
            $calculator = new BrickMathCalculator();
        }
        if ($fallbackConverter === null) {
            $fallbackConverter = new GenericTimeConverter($calculator);
        }
        $this->calculator = $calculator;
        $this->fallbackConverter = $fallbackConverter;
        $this->phpPrecision = (int) ini_get('precision');
    }
    public function calculateTime(string $seconds, string $microseconds): Hexadecimal
    {
        $seconds = new IntegerObject($seconds);
        /** @phpstan-ignore possiblyImpure.new */
        $microseconds = new IntegerObject($microseconds);
        /** @phpstan-ignore possiblyImpure.new */
        // Calculate the count of 100-nanosecond intervals since the Gregorian calendar epoch
        // for the given seconds and microseconds.
        $uuidTime = (int) $seconds->toString() * self::SECOND_INTERVALS + (int) $microseconds->toString() * self::MICROSECOND_INTERVALS + self::GREGORIAN_TO_UNIX_INTERVALS;
        // Check to see whether we've overflowed the max/min integer size.
        // If so, we will default to a different time converter.
        // @phpstan-ignore function.alreadyNarrowedType (the integer value might have overflowed)
        if (!is_int($uuidTime)) {
            return $this->fallbackConverter->calculateTime($seconds->toString(), $microseconds->toString());
        }
        /** @phpstan-ignore possiblyImpure.new */
        return new Hexadecimal(str_pad(dechex($uuidTime), 16, '0', STR_PAD_LEFT));
    }
    public function convertTime(Hexadecimal $uuidTimestamp): Time
    {
        $timestamp = $this->calculator->toInteger($uuidTimestamp);
        // Convert the 100-nanosecond intervals into seconds and microseconds.
        $splitTime = $this->splitTime(($timestamp->toString() - self::GREGORIAN_TO_UNIX_INTERVALS) / self::SECOND_INTERVALS);
        if (count($splitTime) === 0) {
            return $this->fallbackConverter->convertTime($uuidTimestamp);
        }
        /** @phpstan-ignore possiblyImpure.new */
        return new Time($splitTime['sec'], $splitTime['usec']);
    }
    /**
     * @param float | int $time The time to split into seconds and microseconds
     *
     * @return string[]
     *
     * @pure
     */
    private function splitTime(float|int $time): array
    {
        $split = explode('.', (string) $time, 2);
        // If the $time value is a float but $split only has 1 element, then the float math was rounded up to the next
        // second, so we want to return an empty array to allow use of the fallback converter.
        if (is_float($time) && count($split) === 1) {
            return [];
        }
        if (count($split) === 1) {
            return ['sec' => $split[0], 'usec' => '0'];
        }
        // If the microseconds are less than six characters AND the length of the number is greater than or equal to the
        // PHP precision, then it's possible that we lost some precision for the microseconds. Return an empty array so
        // that we can choose to use the fallback converter.
        if (strlen($split[1]) < 6 && strlen((string) $time) >= $this->phpPrecision) {
            return [];
        }
        $microseconds = $split[1];
        // Ensure the microseconds are no longer than 6 digits. If they are,
        // truncate the number to the first 6 digits and round up, if needed.
        if (strlen($microseconds) > 6) {
            $roundingDigit = (int) substr($microseconds, 6, 1);
            $microseconds = (int) substr($microseconds, 0, 6);
            if ($roundingDigit >= 5) {
                $microseconds++;
            }
        }
        return ['sec' => $split[0], 'usec' => str_pad((string) $microseconds, 6, '0', STR_PAD_RIGHT)];
    }
}
<?php

/**
 * This file is part of the ramsey/uuid library
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @copyright Copyright (c) Ben Ramsey <ben@benramsey.com>
 * @license http://opensource.org/licenses/MIT MIT
 */
declare (strict_types=1);
namespace _ContaoManager\Ramsey\Uuid\Converter\Time;

/**
 * @deprecated DegradedTimeConverter is no longer necessary for converting time on 32-bit systems. Please transition to
 *     {@see GenericTimeConverter}.
 *
 * @immutable
 */
class DegradedTimeConverter extends BigNumberTimeConverter
{
}
<?php

/**
 * This file is part of the ramsey/uuid library
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @copyright Copyright (c) Ben Ramsey <ben@benramsey.com>
 * @license http://opensource.org/licenses/MIT MIT
 */
declare (strict_types=1);
namespace _ContaoManager\Ramsey\Uuid\Converter\Time;

use _ContaoManager\Ramsey\Uuid\Converter\TimeConverterInterface;
use _ContaoManager\Ramsey\Uuid\Math\BrickMathCalculator;
use _ContaoManager\Ramsey\Uuid\Type\Hexadecimal;
use _ContaoManager\Ramsey\Uuid\Type\Time;
/**
 * Previously used to integrate moontoast/math as a bignum arithmetic library, BigNumberTimeConverter is deprecated in
 * favor of GenericTimeConverter
 *
 * @deprecated Please transition to {@see GenericTimeConverter}.
 *
 * @immutable
 */
class BigNumberTimeConverter implements TimeConverterInterface
{
    private TimeConverterInterface $converter;
    public function __construct()
    {
        $this->converter = new GenericTimeConverter(new BrickMathCalculator());
    }
    public function calculateTime(string $seconds, string $microseconds): Hexadecimal
    {
        return $this->converter->calculateTime($seconds, $microseconds);
    }
    public function convertTime(Hexadecimal $uuidTimestamp): Time
    {
        return $this->converter->convertTime($uuidTimestamp);
    }
}
<?php

/**
 * This file is part of the ramsey/uuid library
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @copyright Copyright (c) Ben Ramsey <ben@benramsey.com>
 * @license http://opensource.org/licenses/MIT MIT
 */
declare (strict_types=1);
namespace _ContaoManager\Ramsey\Uuid\Converter\Number;

/**
 * @deprecated DegradedNumberConverter is no longer necessary for converting numbers on 32-bit systems. Please
 *     transition to {@see GenericNumberConverter}.
 *
 * @immutable
 */
class DegradedNumberConverter extends BigNumberConverter
{
}
<?php

/**
 * This file is part of the ramsey/uuid library
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @copyright Copyright (c) Ben Ramsey <ben@benramsey.com>
 * @license http://opensource.org/licenses/MIT MIT
 */
declare (strict_types=1);
namespace _ContaoManager\Ramsey\Uuid\Converter\Number;

use _ContaoManager\Ramsey\Uuid\Converter\NumberConverterInterface;
use _ContaoManager\Ramsey\Uuid\Math\BrickMathCalculator;
/**
 * Previously used to integrate moontoast/math as a bignum arithmetic library, BigNumberConverter is deprecated in favor
 * of GenericNumberConverter
 *
 * @deprecated Please transition to {@see GenericNumberConverter}.
 *
 * @immutable
 */
class BigNumberConverter implements NumberConverterInterface
{
    private NumberConverterInterface $converter;
    public function __construct()
    {
        $this->converter = new GenericNumberConverter(new BrickMathCalculator());
    }
    /**
     * @pure
     */
    public function fromHex(string $hex): string
    {
        return $this->converter->fromHex($hex);
    }
    /**
     * @pure
     */
    public function toHex(string $number): string
    {
        return $this->converter->toHex($number);
    }
}
<?php

/**
 * This file is part of the ramsey/uuid library
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @copyright Copyright (c) Ben Ramsey <ben@benramsey.com>
 * @license http://opensource.org/licenses/MIT MIT
 */
declare (strict_types=1);
namespace _ContaoManager\Ramsey\Uuid\Converter\Number;

use _ContaoManager\Ramsey\Uuid\Converter\NumberConverterInterface;
use _ContaoManager\Ramsey\Uuid\Math\CalculatorInterface;
use _ContaoManager\Ramsey\Uuid\Type\Integer as IntegerObject;
/**
 * GenericNumberConverter uses the provided calculator to convert decimal numbers to and from hexadecimal values
 *
 * @immutable
 */
class GenericNumberConverter implements NumberConverterInterface
{
    public function __construct(private CalculatorInterface $calculator)
    {
    }
    /**
     * @pure
     */
    public function fromHex(string $hex): string
    {
        return $this->calculator->fromBase($hex, 16)->toString();
    }
    /**
     * @pure
     */
    public function toHex(string $number): string
    {
        /** @phpstan-ignore return.type, possiblyImpure.new */
        return $this->calculator->toBase(new IntegerObject($number), 16);
    }
}
<?php

/**
 * This file is part of the ramsey/uuid library
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @copyright Copyright (c) Ben Ramsey <ben@benramsey.com>
 * @license http://opensource.org/licenses/MIT MIT
 */
declare (strict_types=1);
namespace _ContaoManager\Ramsey\Uuid\Converter;

use _ContaoManager\Ramsey\Uuid\Type\Hexadecimal;
use _ContaoManager\Ramsey\Uuid\Type\Time;
/**
 * A time converter converts timestamps into representations that may be used in UUIDs
 *
 * @immutable
 */
interface TimeConverterInterface
{
    /**
     * Uses the provided seconds and micro-seconds to calculate the count of 100-nanosecond intervals since
     * UTC 00:00:00.00, 15 October 1582, for RFC 9562 (formerly RFC 4122) variant UUIDs
     *
     * @link https://www.rfc-editor.org/rfc/rfc9562#appendix-A RFC 9562, Appendix A. Test Vectors
     *
     * @param string $seconds A string representation of seconds since the Unix epoch for the time to calculate
     * @param string $microseconds A string representation of the micro-seconds associated with the time to calculate
     *
     * @return Hexadecimal The full UUID timestamp as a Hexadecimal value
     *
     * @pure
     */
    public function calculateTime(string $seconds, string $microseconds): Hexadecimal;
    /**
     * Converts a timestamp extracted from a UUID to a Unix timestamp
     *
     * @param Hexadecimal $uuidTimestamp A hexadecimal representation of a UUID timestamp; a UUID timestamp is a count
     *     of 100-nanosecond intervals since UTC 00:00:00.00, 15 October 1582.
     *
     * @return Time An instance of {@see Time}
     *
     * @pure
     */
    public function convertTime(Hexadecimal $uuidTimestamp): Time;
}
<?php

/**
 * This file is part of the ramsey/uuid library
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @copyright Copyright (c) Ben Ramsey <ben@benramsey.com>
 * @license http://opensource.org/licenses/MIT MIT
 */
declare (strict_types=1);
namespace _ContaoManager\Ramsey\Uuid\Converter;

/**
 * A number converter converts UUIDs from hexadecimal characters into representations of integers and vice versa
 *
 * @immutable
 */
interface NumberConverterInterface
{
    /**
     * Converts a hexadecimal number into a string integer representation of the number
     *
     * The integer representation returned is a string representation of the integer to accommodate unsigned integers
     * that are greater than `PHP_INT_MAX`.
     *
     * @param string $hex The hexadecimal string representation to convert
     *
     * @return numeric-string String representation of an integer
     *
     * @pure
     */
    public function fromHex(string $hex): string;
    /**
     * Converts a string integer representation into a hexadecimal string representation of the number
     *
     * @param string $number A string integer representation to convert; this must be a numeric string to accommodate
     *     unsigned integers that are greater than `PHP_INT_MAX`.
     *
     * @return non-empty-string Hexadecimal string
     *
     * @pure
     */
    public function toHex(string $number): string;
}
<?php

/**
 * This file is part of the ramsey/uuid library
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @copyright Copyright (c) Ben Ramsey <ben@benramsey.com>
 * @license http://opensource.org/licenses/MIT MIT
 */
declare (strict_types=1);
namespace _ContaoManager\Ramsey\Uuid;

use DateTimeImmutable;
use DateTimeInterface;
use _ContaoManager\Ramsey\Uuid\Converter\NumberConverterInterface;
use _ContaoManager\Ramsey\Uuid\Exception\DateTimeException;
use _ContaoManager\Ramsey\Uuid\Exception\UnsupportedOperationException;
use Throwable;
use function str_pad;
use function substr;
use const STR_PAD_LEFT;
/**
 * This trait encapsulates deprecated methods for ramsey/uuid; this trait and its methods will be removed in ramsey/uuid 5.0.0.
 *
 * @deprecated This trait and its methods will be removed in ramsey/uuid 5.0.0.
 *
 * @immutable
 */
trait DeprecatedUuidMethodsTrait
{
    /**
     * @deprecated Use {@see UuidInterface::getFields()} to get a {@see \Ramsey\Uuid\Fields\FieldsInterface} instance.
     *     If it is a {@see \Ramsey\Uuid\Rfc4122\FieldsInterface} instance, you may call
     *     {@see \Ramsey\Uuid\Rfc4122\FieldsInterface::getClockSeqHiAndReserved()} and use the arbitrary-precision math
     *     library of your choice to convert it to a string integer.
     */
    public function getClockSeqHiAndReserved(): string
    {
        return $this->numberConverter->fromHex($this->fields->getClockSeqHiAndReserved()->toString());
    }
    /**
     * @deprecated Use {@see UuidInterface::getFields()} to get a {@see \Ramsey\Uuid\Fields\FieldsInterface} instance.
     *     If it is a {@see \Ramsey\Uuid\Rfc4122\FieldsInterface} instance, you may call
     *     {@see \Ramsey\Uuid\Rfc4122\FieldsInterface::getClockSeqHiAndReserved()}.
     */
    public function getClockSeqHiAndReservedHex(): string
    {
        return $this->fields->getClockSeqHiAndReserved()->toString();
    }
    /**
     * @deprecated Use {@see UuidInterface::getFields()} to get a {@see \Ramsey\Uuid\Fields\FieldsInterface} instance.
     *     If it is a {@see \Ramsey\Uuid\Rfc4122\FieldsInterface} instance, you may call
     *     {@see \Ramsey\Uuid\Rfc4122\FieldsInterface::getClockSeqLow()} and use the arbitrary-precision math library of
     *     your choice to convert it to a string integer.
     */
    public function getClockSeqLow(): string
    {
        return $this->numberConverter->fromHex($this->fields->getClockSeqLow()->toString());
    }
    /**
     * @deprecated Use {@see UuidInterface::getFields()} to get a {@see \Ramsey\Uuid\Fields\FieldsInterface} instance.
     *     If it is a {@see \Ramsey\Uuid\Rfc4122\FieldsInterface} instance, you may call
     *     {@see \Ramsey\Uuid\Rfc4122\FieldsInterface::getClockSeqLow()}.
     */
    public function getClockSeqLowHex(): string
    {
        return $this->fields->getClockSeqLow()->toString();
    }
    /**
     * @deprecated Use {@see UuidInterface::getFields()} to get a {@see \Ramsey\Uuid\Fields\FieldsInterface} instance.
     *     If it is a {@see \Ramsey\Uuid\Rfc4122\FieldsInterface} instance, you may call
     *     {@see \Ramsey\Uuid\Rfc4122\FieldsInterface::getClockSeq()} and use the arbitrary-precision math library of
     *     your choice to convert it to a string integer.
     */
    public function getClockSequence(): string
    {
        return $this->numberConverter->fromHex($this->fields->getClockSeq()->toString());
    }
    /**
     * @deprecated Use {@see UuidInterface::getFields()} to get a {@see \Ramsey\Uuid\Fields\FieldsInterface} instance.
     *     If it is a {@see \Ramsey\Uuid\Rfc4122\FieldsInterface} instance, you may call
     *     {@see \Ramsey\Uuid\Rfc4122\FieldsInterface::getClockSeq()}.
     */
    public function getClockSequenceHex(): string
    {
        return $this->fields->getClockSeq()->toString();
    }
    /**
     * @deprecated This method will be removed in 5.0.0. There is no alternative recommendation, so plan accordingly.
     */
    public function getNumberConverter(): NumberConverterInterface
    {
        return $this->numberConverter;
    }
    /**
     * @deprecated In ramsey/uuid version 5.0.0, this will be removed. It is available at {@see UuidV1::getDateTime()}.
     *
     * @return DateTimeImmutable An immutable instance of DateTimeInterface
     *
     * @throws UnsupportedOperationException if UUID is not time-based
     * @throws DateTimeException if DateTime throws an exception/error
     */
    public function getDateTime(): DateTimeInterface
    {
        if ($this->fields->getVersion() !== 1) {
            throw new UnsupportedOperationException('Not a time-based UUID');
        }
        $time = $this->timeConverter->convertTime($this->fields->getTimestamp());
        try {
            return new DateTimeImmutable('@' . $time->getSeconds()->toString() . '.' . str_pad($time->getMicroseconds()->toString(), 6, '0', STR_PAD_LEFT));
        } catch (Throwable $e) {
            throw new DateTimeException($e->getMessage(), (int) $e->getCode(), $e);
        }
    }
    /**
     * @deprecated Use {@see UuidInterface::getFields()} to get a {@see \Ramsey\Uuid\Fields\FieldsInterface} instance.
     *
     * @return string[]
     */
    public function getFieldsHex(): array
    {
        return ['time_low' => $this->fields->getTimeLow()->toString(), 'time_mid' => $this->fields->getTimeMid()->toString(), 'time_hi_and_version' => $this->fields->getTimeHiAndVersion()->toString(), 'clock_seq_hi_and_reserved' => $this->fields->getClockSeqHiAndReserved()->toString(), 'clock_seq_low' => $this->fields->getClockSeqLow()->toString(), 'node' => $this->fields->getNode()->toString()];
    }
    /**
     * @deprecated This method will be removed in 5.0.0. There is no direct alternative, but the same information may be
     *     obtained by splitting in half the value returned by {@see UuidInterface::getHex()}.
     */
    public function getLeastSignificantBits(): string
    {
        $leastSignificantHex = substr($this->getHex()->toString(), 16);
        return $this->numberConverter->fromHex($leastSignificantHex);
    }
    /**
     * @deprecated This method will be removed in 5.0.0. There is no direct alternative, but the same information may be
     *     obtained by splitting in half the value returned by {@see UuidInterface::getHex()}.
     */
    public function getLeastSignificantBitsHex(): string
    {
        return substr($this->getHex()->toString(), 16);
    }
    /**
     * @deprecated This method will be removed in 5.0.0. There is no direct alternative, but the same information may be
     *     obtained by splitting in half the value returned by {@see UuidInterface::getHex()}.
     */
    public function getMostSignificantBits(): string
    {
        $mostSignificantHex = substr($this->getHex()->toString(), 0, 16);
        return $this->numberConverter->fromHex($mostSignificantHex);
    }
    /**
     * @deprecated This method will be removed in 5.0.0. There is no direct alternative, but the same information may be
     *     obtained by splitting in half the value returned by {@see UuidInterface::getHex()}.
     */
    public function getMostSignificantBitsHex(): string
    {
        return substr($this->getHex()->toString(), 0, 16);
    }
    /**
     * @deprecated Use {@see UuidInterface::getFields()} to get a {@see \Ramsey\Uuid\Fields\FieldsInterface} instance.
     *     If it is a {@see \Ramsey\Uuid\Rfc4122\FieldsInterface} instance, you may call
     *     {@see \Ramsey\Uuid\Rfc4122\FieldsInterface::getNode()} and use the arbitrary-precision math library of your
     *     choice to convert it to a string integer.
     */
    public function getNode(): string
    {
        return $this->numberConverter->fromHex($this->fields->getNode()->toString());
    }
    /**
     * @deprecated Use {@see UuidInterface::getFields()} to get a {@see \Ramsey\Uuid\Fields\FieldsInterface} instance.
     *     If it is a {@see \Ramsey\Uuid\Rfc4122\FieldsInterface} instance, you may call
     *     {@see \Ramsey\Uuid\Rfc4122\FieldsInterface::getNode()}.
     */
    public function getNodeHex(): string
    {
        return $this->fields->getNode()->toString();
    }
    /**
     * @deprecated Use {@see UuidInterface::getFields()} to get a {@see \Ramsey\Uuid\Fields\FieldsInterface} instance.
     *     If it is a {@see \Ramsey\Uuid\Rfc4122\FieldsInterface} instance, you may call
     *     {@see \Ramsey\Uuid\Rfc4122\FieldsInterface::getTimeHiAndVersion()} and use the arbitrary-precision math
     *     library of your choice to convert it to a string integer.
     */
    public function getTimeHiAndVersion(): string
    {
        return $this->numberConverter->fromHex($this->fields->getTimeHiAndVersion()->toString());
    }
    /**
     * @deprecated Use {@see UuidInterface::getFields()} to get a {@see \Ramsey\Uuid\Fields\FieldsInterface} instance.
     *     If it is a {@see \Ramsey\Uuid\Rfc4122\FieldsInterface} instance, you may call
     *     {@see \Ramsey\Uuid\Rfc4122\FieldsInterface::getTimeHiAndVersion()}.
     */
    public function getTimeHiAndVersionHex(): string
    {
        return $this->fields->getTimeHiAndVersion()->toString();
    }
    /**
     * @deprecated Use {@see UuidInterface::getFields()} to get a {@see \Ramsey\Uuid\Fields\FieldsInterface} instance.
     *     If it is a {@see \Ramsey\Uuid\Rfc4122\FieldsInterface} instance, you may call
     *     {@see \Ramsey\Uuid\Rfc4122\FieldsInterface::getTimeLow()} and use the arbitrary-precision math library of
     *     your choice to convert it to a string integer.
     */
    public function getTimeLow(): string
    {
        return $this->numberConverter->fromHex($this->fields->getTimeLow()->toString());
    }
    /**
     * @deprecated Use {@see UuidInterface::getFields()} to get a {@see \Ramsey\Uuid\Fields\FieldsInterface} instance.
     *     If it is a {@see \Ramsey\Uuid\Rfc4122\FieldsInterface} instance, you may call
     *     {@see \Ramsey\Uuid\Rfc4122\FieldsInterface::getTimeLow()}.
     */
    public function getTimeLowHex(): string
    {
        return $this->fields->getTimeLow()->toString();
    }
    /**
     * @deprecated Use {@see UuidInterface::getFields()} to get a {@see \Ramsey\Uuid\Fields\FieldsInterface} instance.
     *     If it is a {@see \Ramsey\Uuid\Rfc4122\FieldsInterface} instance, you may call
     *     {@see \Ramsey\Uuid\Rfc4122\FieldsInterface::getTimeMid()} and use the arbitrary-precision math library of
     *     your choice to convert it to a string integer.
     */
    public function getTimeMid(): string
    {
        return $this->numberConverter->fromHex($this->fields->getTimeMid()->toString());
    }
    /**
     * @deprecated Use {@see UuidInterface::getFields()} to get a {@see \Ramsey\Uuid\Fields\FieldsInterface} instance.
     *     If it is a {@see \Ramsey\Uuid\Rfc4122\FieldsInterface} instance, you may call
     *     {@see \Ramsey\Uuid\Rfc4122\FieldsInterface::getTimeMid()}.
     */
    public function getTimeMidHex(): string
    {
        return $this->fields->getTimeMid()->toString();
    }
    /**
     * @deprecated Use {@see UuidInterface::getFields()} to get a {@see \Ramsey\Uuid\Fields\FieldsInterface} instance.
     *     If it is a {@see \Ramsey\Uuid\Rfc4122\FieldsInterface} instance, you may call
     *     {@see \Ramsey\Uuid\Rfc4122\FieldsInterface::getTimestamp()} and use the arbitrary-precision math library of
     *     your choice to convert it to a string integer.
     */
    public function getTimestamp(): string
    {
        if ($this->fields->getVersion() !== 1) {
            throw new UnsupportedOperationException('Not a time-based UUID');
        }
        return $this->numberConverter->fromHex($this->fields->getTimestamp()->toString());
    }
    /**
     * @deprecated Use {@see UuidInterface::getFields()} to get a {@see \Ramsey\Uuid\Fields\FieldsInterface} instance.
     *     If it is a {@see \Ramsey\Uuid\Rfc4122\FieldsInterface} instance, you may call
     *     {@see \Ramsey\Uuid\Rfc4122\FieldsInterface::getTimestamp()}.
     */
    public function getTimestampHex(): string
    {
        if ($this->fields->getVersion() !== 1) {
            throw new UnsupportedOperationException('Not a time-based UUID');
        }
        return $this->fields->getTimestamp()->toString();
    }
    /**
     * @deprecated Use {@see UuidInterface::getFields()} to get a {@see \Ramsey\Uuid\Fields\FieldsInterface} instance.
     *     If it is a {@see \Ramsey\Uuid\Rfc4122\FieldsInterface} instance, you may call
     *     {@see \Ramsey\Uuid\Rfc4122\FieldsInterface::getVariant()}.
     */
    public function getVariant(): ?int
    {
        return $this->fields->getVariant();
    }
    /**
     * @deprecated Use {@see UuidInterface::getFields()} to get a {@see \Ramsey\Uuid\Fields\FieldsInterface} instance.
     *     If it is a {@see \Ramsey\Uuid\Rfc4122\FieldsInterface} instance, you may call
     *     {@see \Ramsey\Uuid\Rfc4122\FieldsInterface::getVersion()}.
     */
    public function getVersion(): ?int
    {
        return $this->fields->getVersion();
    }
}
<?php

/**
 * This file is part of the ramsey/uuid library
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @copyright Copyright (c) Ben Ramsey <ben@benramsey.com>
 * @license http://opensource.org/licenses/MIT MIT
 */
declare (strict_types=1);
namespace _ContaoManager\Ramsey\Uuid\Codec;

use _ContaoManager\Ramsey\Uuid\Exception\InvalidUuidStringException;
use _ContaoManager\Ramsey\Uuid\UuidInterface;
use function bin2hex;
use function sprintf;
use function substr;
use function substr_replace;
/**
 * TimestampFirstCombCodec encodes and decodes COMBs, with the timestamp as the first 48 bits
 *
 * In contrast with the TimestampLastCombCodec, the TimestampFirstCombCodec adds the timestamp to the first 48 bits of
 * the COMB. To generate a timestamp-first COMB, set the TimestampFirstCombCodec as the codec, along with the
 * CombGenerator as the random generator.
 *
 * ```
 * $factory = new UuidFactory();
 *
 * $factory->setCodec(new TimestampFirstCombCodec($factory->getUuidBuilder()));
 *
 * $factory->setRandomGenerator(new CombGenerator(
 *     $factory->getRandomGenerator(),
 *     $factory->getNumberConverter(),
 * ));
 *
 * $timestampFirstComb = $factory->uuid4();
 * ```
 *
 * @deprecated Please migrate to {@link https://uuid.ramsey.dev/en/stable/rfc4122/version7.html Version 7, Unix Epoch Time UUIDs}.
 *
 * @link https://web.archive.org/web/20240118030355/https://www.informit.com/articles/printerfriendly/25862 The Cost of GUIDs as Primary Keys
 *
 * @immutable
 */
class TimestampFirstCombCodec extends StringCodec
{
    /**
     * @return non-empty-string
     */
    public function encode(UuidInterface $uuid): string
    {
        /** @phpstan-ignore possiblyImpure.methodCall */
        $bytes = $this->swapBytes($uuid->getFields()->getBytes());
        return sprintf('%08s-%04s-%04s-%04s-%012s', bin2hex(substr($bytes, 0, 4)), bin2hex(substr($bytes, 4, 2)), bin2hex(substr($bytes, 6, 2)), bin2hex(substr($bytes, 8, 2)), bin2hex(substr($bytes, 10)));
    }
    /**
     * @return non-empty-string
     */
    public function encodeBinary(UuidInterface $uuid): string
    {
        /** @phpstan-ignore-next-line PHPStan complains that this is not a non-empty-string. */
        return $this->swapBytes($uuid->getFields()->getBytes());
    }
    /**
     * @throws InvalidUuidStringException
     *
     * @inheritDoc
     */
    public function decode(string $encodedUuid): UuidInterface
    {
        /** @phpstan-ignore possiblyImpure.methodCall */
        $bytes = $this->getBytes($encodedUuid);
        /** @phpstan-ignore possiblyImpure.methodCall */
        return $this->getBuilder()->build($this, $this->swapBytes($bytes));
    }
    public function decodeBytes(string $bytes): UuidInterface
    {
        /** @phpstan-ignore possiblyImpure.methodCall */
        return $this->getBuilder()->build($this, $this->swapBytes($bytes));
    }
    /**
     * Swaps bytes according to the timestamp-first COMB rules
     *
     * @pure
     */
    private function swapBytes(string $bytes): string
    {
        $first48Bits = substr($bytes, 0, 6);
        $last48Bits = substr($bytes, -6);
        return substr_replace(substr_replace($bytes, $last48Bits, 0, 6), $first48Bits, -6);
    }
}
<?php

/**
 * This file is part of the ramsey/uuid library
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @copyright Copyright (c) Ben Ramsey <ben@benramsey.com>
 * @license http://opensource.org/licenses/MIT MIT
 */
declare (strict_types=1);
namespace _ContaoManager\Ramsey\Uuid\Codec;

use _ContaoManager\Ramsey\Uuid\Exception\InvalidArgumentException;
use _ContaoManager\Ramsey\Uuid\Exception\UnsupportedOperationException;
use _ContaoManager\Ramsey\Uuid\Rfc4122\FieldsInterface as Rfc4122FieldsInterface;
use _ContaoManager\Ramsey\Uuid\Uuid;
use _ContaoManager\Ramsey\Uuid\UuidInterface;
use function strlen;
use function substr;
/**
 * OrderedTimeCodec encodes and decodes a UUID, optimizing the byte order for more efficient storage
 *
 * For binary representations of version 1 UUID, this codec may be used to reorganize the time fields, making the UUID
 * closer to sequential when storing the bytes. According to Percona, this optimization can improve database INSERT and
 * SELECT statements using the UUID column as a key.
 *
 * The string representation of the UUID will remain unchanged. Only the binary representation is reordered.
 *
 * PLEASE NOTE: Binary representations of UUIDs encoded with this codec must be decoded with this codec. Decoding using
 * another codec can result in malformed UUIDs.
 *
 * @deprecated Please migrate to {@link https://uuid.ramsey.dev/en/stable/rfc4122/version6.html Version 6, reordered time-based UUIDs}.
 *
 * @link https://www.percona.com/blog/2014/12/19/store-uuid-optimized-way/ Storing UUID Values in MySQL
 *
 * @immutable
 */
class OrderedTimeCodec extends StringCodec
{
    /**
     * Returns a binary string representation of a UUID, with the timestamp fields rearranged for optimized storage
     *
     * @return non-empty-string
     */
    public function encodeBinary(UuidInterface $uuid): string
    {
        if (!$uuid->getFields() instanceof Rfc4122FieldsInterface || $uuid->getFields()->getVersion() !== Uuid::UUID_TYPE_TIME) {
            throw new InvalidArgumentException('Expected version 1 (time-based) UUID');
        }
        /** @phpstan-ignore possiblyImpure.methodCall */
        $bytes = $uuid->getFields()->getBytes();
        return $bytes[6] . $bytes[7] . $bytes[4] . $bytes[5] . $bytes[0] . $bytes[1] . $bytes[2] . $bytes[3] . substr($bytes, 8);
    }
    /**
     * Returns a UuidInterface derived from an ordered-time binary string representation
     *
     * @throws InvalidArgumentException if $bytes is an invalid length
     *
     * @inheritDoc
     */
    public function decodeBytes(string $bytes): UuidInterface
    {
        if (strlen($bytes) !== 16) {
            throw new InvalidArgumentException('$bytes string should contain 16 characters.');
        }
        // Rearrange the bytes to their original order.
        $rearrangedBytes = $bytes[4] . $bytes[5] . $bytes[6] . $bytes[7] . $bytes[2] . $bytes[3] . $bytes[0] . $bytes[1] . substr($bytes, 8);
        $uuid = parent::decodeBytes($rearrangedBytes);
        /** @phpstan-ignore possiblyImpure.methodCall */
        $fields = $uuid->getFields();
        if (!$fields instanceof Rfc4122FieldsInterface || $fields->getVersion() !== Uuid::UUID_TYPE_TIME) {
            throw new UnsupportedOperationException('Attempting to decode a non-time-based UUID using OrderedTimeCodec');
        }
        return $uuid;
    }
}
<?php

/**
 * This file is part of the ramsey/uuid library
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @copyright Copyright (c) Ben Ramsey <ben@benramsey.com>
 * @license http://opensource.org/licenses/MIT MIT
 */
declare (strict_types=1);
namespace _ContaoManager\Ramsey\Uuid\Codec;

use _ContaoManager\Ramsey\Uuid\UuidInterface;
/**
 * A codec encodes and decodes a UUID according to defined rules
 *
 * @immutable
 */
interface CodecInterface
{
    /**
     * Returns a hexadecimal string representation of a UuidInterface
     *
     * @param UuidInterface $uuid The UUID for which to create a hexadecimal string representation
     *
     * @return non-empty-string Hexadecimal string representation of a UUID
     *
     * @pure
     */
    public function encode(UuidInterface $uuid): string;
    /**
     * Returns a binary string representation of a UuidInterface
     *
     * @param UuidInterface $uuid The UUID for which to create a binary string representation
     *
     * @return non-empty-string Binary string representation of a UUID
     *
     * @pure
     */
    public function encodeBinary(UuidInterface $uuid): string;
    /**
     * Returns a UuidInterface derived from a hexadecimal string representation
     *
     * @param string $encodedUuid The hexadecimal string representation to convert into a UuidInterface instance
     *
     * @return UuidInterface An instance of a UUID decoded from a hexadecimal string representation
     *
     * @pure
     */
    public function decode(string $encodedUuid): UuidInterface;
    /**
     * Returns a UuidInterface derived from a binary string representation
     *
     * @param string $bytes The binary string representation to convert into a UuidInterface instance
     *
     * @return UuidInterface An instance of a UUID decoded from a binary string representation
     *
     * @pure
     */
    public function decodeBytes(string $bytes): UuidInterface;
}
<?php

/**
 * This file is part of the ramsey/uuid library
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @copyright Copyright (c) Ben Ramsey <ben@benramsey.com>
 * @license http://opensource.org/licenses/MIT MIT
 */
declare (strict_types=1);
namespace _ContaoManager\Ramsey\Uuid\Codec;

use _ContaoManager\Ramsey\Uuid\Guid\Guid;
use _ContaoManager\Ramsey\Uuid\UuidInterface;
use function bin2hex;
use function sprintf;
use function substr;
/**
 * GuidStringCodec encodes and decodes globally unique identifiers (GUID)
 *
 * @see Guid
 *
 * @immutable
 */
class GuidStringCodec extends StringCodec
{
    public function encode(UuidInterface $uuid): string
    {
        /** @phpstan-ignore possiblyImpure.methodCall */
        $hex = bin2hex($uuid->getFields()->getBytes());
        /** @var non-empty-string */
        return sprintf('%02s%02s%02s%02s-%02s%02s-%02s%02s-%04s-%012s', substr($hex, 6, 2), substr($hex, 4, 2), substr($hex, 2, 2), substr($hex, 0, 2), substr($hex, 10, 2), substr($hex, 8, 2), substr($hex, 14, 2), substr($hex, 12, 2), substr($hex, 16, 4), substr($hex, 20));
    }
    public function decode(string $encodedUuid): UuidInterface
    {
        /** @phpstan-ignore possiblyImpure.methodCall */
        $bytes = $this->getBytes($encodedUuid);
        /** @phpstan-ignore possiblyImpure.methodCall, possiblyImpure.methodCall */
        return $this->getBuilder()->build($this, $this->swapBytes($bytes));
    }
    public function decodeBytes(string $bytes): UuidInterface
    {
        // Call parent::decode() to preserve the correct byte order.
        return parent::decode(bin2hex($bytes));
    }
    /**
     * Swaps bytes according to the GUID rules
     */
    private function swapBytes(string $bytes): string
    {
        return $bytes[3] . $bytes[2] . $bytes[1] . $bytes[0] . $bytes[5] . $bytes[4] . $bytes[7] . $bytes[6] . substr($bytes, 8);
    }
}
<?php

/**
 * This file is part of the ramsey/uuid library
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @copyright Copyright (c) Ben Ramsey <ben@benramsey.com>
 * @license http://opensource.org/licenses/MIT MIT
 */
declare (strict_types=1);
namespace _ContaoManager\Ramsey\Uuid\Codec;

use _ContaoManager\Ramsey\Uuid\Builder\UuidBuilderInterface;
use _ContaoManager\Ramsey\Uuid\Exception\InvalidArgumentException;
use _ContaoManager\Ramsey\Uuid\Exception\InvalidUuidStringException;
use _ContaoManager\Ramsey\Uuid\Uuid;
use _ContaoManager\Ramsey\Uuid\UuidInterface;
use function bin2hex;
use function hex2bin;
use function implode;
use function sprintf;
use function str_replace;
use function strlen;
use function substr;
/**
 * StringCodec encodes and decodes RFC 9562 (formerly RFC 4122) UUIDs
 *
 * @immutable
 */
class StringCodec implements CodecInterface
{
    /**
     * Constructs a StringCodec
     *
     * @param UuidBuilderInterface $builder The builder to use when encoding UUIDs
     */
    public function __construct(private UuidBuilderInterface $builder)
    {
    }
    public function encode(UuidInterface $uuid): string
    {
        /** @phpstan-ignore possiblyImpure.methodCall */
        $hex = bin2hex($uuid->getFields()->getBytes());
        /** @var non-empty-string */
        return sprintf('%08s-%04s-%04s-%04s-%012s', substr($hex, 0, 8), substr($hex, 8, 4), substr($hex, 12, 4), substr($hex, 16, 4), substr($hex, 20));
    }
    /**
     * @return non-empty-string
     */
    public function encodeBinary(UuidInterface $uuid): string
    {
        /** @phpstan-ignore-next-line PHPStan complains that this is not a non-empty-string. */
        return $uuid->getFields()->getBytes();
    }
    /**
     * @throws InvalidUuidStringException
     *
     * @inheritDoc
     */
    public function decode(string $encodedUuid): UuidInterface
    {
        /** @phpstan-ignore possiblyImpure.methodCall */
        return $this->builder->build($this, $this->getBytes($encodedUuid));
    }
    public function decodeBytes(string $bytes): UuidInterface
    {
        if (strlen($bytes) !== 16) {
            throw new InvalidArgumentException('$bytes string should contain 16 characters.');
        }
        return $this->builder->build($this, $bytes);
    }
    /**
     * Returns the UUID builder
     */
    protected function getBuilder(): UuidBuilderInterface
    {
        return $this->builder;
    }
    /**
     * Returns a byte string of the UUID
     */
    protected function getBytes(string $encodedUuid): string
    {
        $parsedUuid = str_replace(['urn:', 'uuid:', 'URN:', 'UUID:', '{', '}', '-'], '', $encodedUuid);
        $components = [substr($parsedUuid, 0, 8), substr($parsedUuid, 8, 4), substr($parsedUuid, 12, 4), substr($parsedUuid, 16, 4), substr($parsedUuid, 20)];
        if (!Uuid::isValid(implode('-', $components))) {
            throw new InvalidUuidStringException('Invalid UUID string: ' . $encodedUuid);
        }
        return (string) hex2bin($parsedUuid);
    }
}
<?php

/**
 * This file is part of the ramsey/uuid library
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @copyright Copyright (c) Ben Ramsey <ben@benramsey.com>
 * @license http://opensource.org/licenses/MIT MIT
 */
declare (strict_types=1);
namespace _ContaoManager\Ramsey\Uuid\Codec;

/**
 * TimestampLastCombCodec encodes and decodes COMBs, with the timestamp as the last 48 bits
 *
 * The CombGenerator when used with the StringCodec (and, by proxy, the TimestampLastCombCodec) adds the timestamp to
 * the last 48 bits of the COMB. The TimestampLastCombCodec is provided for the sake of consistency. In practice, it is
 * identical to the standard StringCodec, but it may be used with the CombGenerator for additional context when reading
 * code.
 *
 * Consider the following code. By default, the codec used by UuidFactory is the StringCodec, but here, we explicitly
 * set the TimestampLastCombCodec. It is redundant, but it is clear that we intend this COMB to be generated with the
 * timestamp appearing at the end.
 *
 * ```
 * $factory = new UuidFactory();
 *
 * $factory->setCodec(new TimestampLastCombCodec($factory->getUuidBuilder()));
 *
 * $factory->setRandomGenerator(new CombGenerator(
 *     $factory->getRandomGenerator(),
 *     $factory->getNumberConverter(),
 * ));
 *
 * $timestampLastComb = $factory->uuid4();
 * ```
 *
 * @deprecated Please use {@see StringCodec} instead.
 *
 * @immutable
 */
class TimestampLastCombCodec extends StringCodec
{
}
<?php

/**
 * This file is part of the ramsey/uuid library
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @copyright Copyright (c) Ben Ramsey <ben@benramsey.com>
 * @license http://opensource.org/licenses/MIT MIT
 */
declare (strict_types=1);
namespace _ContaoManager\Ramsey\Uuid;

use BadMethodCallException;
use DateTimeInterface;
use _ContaoManager\Ramsey\Uuid\Codec\CodecInterface;
use _ContaoManager\Ramsey\Uuid\Converter\NumberConverterInterface;
use _ContaoManager\Ramsey\Uuid\Converter\TimeConverterInterface;
use _ContaoManager\Ramsey\Uuid\Exception\InvalidArgumentException;
use _ContaoManager\Ramsey\Uuid\Exception\UnsupportedOperationException;
use _ContaoManager\Ramsey\Uuid\Fields\FieldsInterface;
use _ContaoManager\Ramsey\Uuid\Lazy\LazyUuidFromString;
use _ContaoManager\Ramsey\Uuid\Rfc4122\FieldsInterface as Rfc4122FieldsInterface;
use _ContaoManager\Ramsey\Uuid\Type\Hexadecimal;
use _ContaoManager\Ramsey\Uuid\Type\Integer as IntegerObject;
use ValueError;
use function assert;
use function bin2hex;
use function method_exists;
use function preg_match;
use function sprintf;
use function str_replace;
use function strcmp;
use function strlen;
use function strtolower;
use function substr;
/**
 * Uuid provides constants and static methods for working with and generating UUIDs
 *
 * @immutable
 */
class Uuid implements UuidInterface
{
    use DeprecatedUuidMethodsTrait;
    /**
     * When this namespace is specified, the name string is a fully qualified domain name
     *
     * @link https://www.rfc-editor.org/rfc/rfc9562#section-6.6 RFC 9562, 6.6. Namespace ID Usage and Allocation
     */
    public const NAMESPACE_DNS = '6ba7b810-9dad-11d1-80b4-00c04fd430c8';
    /**
     * When this namespace is specified, the name string is a URL
     *
     * @link https://www.rfc-editor.org/rfc/rfc9562#section-6.6 RFC 9562, 6.6. Namespace ID Usage and Allocation
     */
    public const NAMESPACE_URL = '6ba7b811-9dad-11d1-80b4-00c04fd430c8';
    /**
     * When this namespace is specified, the name string is an ISO OID
     *
     * @link https://www.rfc-editor.org/rfc/rfc9562#section-6.6 RFC 9562, 6.6. Namespace ID Usage and Allocation
     */
    public const NAMESPACE_OID = '6ba7b812-9dad-11d1-80b4-00c04fd430c8';
    /**
     * When this namespace is specified, the name string is an X.500 DN (in DER or a text output format)
     *
     * @link https://www.rfc-editor.org/rfc/rfc9562#section-6.6 RFC 9562, 6.6. Namespace ID Usage and Allocation
     */
    public const NAMESPACE_X500 = '6ba7b814-9dad-11d1-80b4-00c04fd430c8';
    /**
     * The Nil UUID is a special form of UUID that is specified to have all 128 bits set to zero
     *
     * @link https://www.rfc-editor.org/rfc/rfc9562#section-5.9 RFC 9562, 5.9. Nil UUID
     */
    public const NIL = '00000000-0000-0000-0000-000000000000';
    /**
     * The Max UUID is a special form of UUID that is specified to have all 128 bits set to one
     *
     * @link https://www.rfc-editor.org/rfc/rfc9562#section-5.10 RFC 9562, 5.10. Max UUID
     */
    public const MAX = 'ffffffff-ffff-ffff-ffff-ffffffffffff';
    /**
     * Variant: reserved, NCS backward compatibility
     *
     * @link https://www.rfc-editor.org/rfc/rfc9562#section-4.1 RFC 9562, 4.1. Variant Field
     */
    public const RESERVED_NCS = 0;
    /**
     * Variant: the UUID layout specified in RFC 9562 (formerly RFC 4122)
     *
     * @link https://www.rfc-editor.org/rfc/rfc9562#section-4.1 RFC 9562, 4.1. Variant Field
     * @see Uuid::RFC_9562
     */
    public const RFC_4122 = 2;
    /**
     * Variant: the UUID layout specified in RFC 9562 (formerly RFC 4122)
     *
     * @link https://www.rfc-editor.org/rfc/rfc9562#section-4.1 RFC 9562, 4.1. Variant Field
     */
    public const RFC_9562 = 2;
    /**
     * Variant: reserved, Microsoft Corporation backward compatibility
     *
     * @link https://www.rfc-editor.org/rfc/rfc9562#section-4.1 RFC 9562, 4.1. Variant Field
     */
    public const RESERVED_MICROSOFT = 6;
    /**
     * Variant: reserved for future definition
     *
     * @link https://www.rfc-editor.org/rfc/rfc9562#section-4.1 RFC 9562, 4.1. Variant Field
     */
    public const RESERVED_FUTURE = 7;
    /**
     * @deprecated Use {@see ValidatorInterface::getPattern()} instead.
     */
    public const VALID_PATTERN = '^[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{12}$';
    /**
     * Version 1 (Gregorian time) UUID
     *
     * @link https://www.rfc-editor.org/rfc/rfc9562#section-4.2 RFC 9562, 4.2. Version Field
     */
    public const UUID_TYPE_TIME = 1;
    /**
     * Version 2 (DCE Security) UUID
     *
     * @link https://www.rfc-editor.org/rfc/rfc9562#section-4.2 RFC 9562, 4.2. Version Field
     */
    public const UUID_TYPE_DCE_SECURITY = 2;
    /**
     * @deprecated Use {@see Uuid::UUID_TYPE_DCE_SECURITY} instead.
     */
    public const UUID_TYPE_IDENTIFIER = 2;
    /**
     * Version 3 (name-based and hashed with MD5) UUID
     *
     * @link https://www.rfc-editor.org/rfc/rfc9562#section-4.2 RFC 9562, 4.2. Version Field
     */
    public const UUID_TYPE_HASH_MD5 = 3;
    /**
     * Version 4 (random) UUID
     *
     * @link https://www.rfc-editor.org/rfc/rfc9562#section-4.2 RFC 9562, 4.2. Version Field
     */
    public const UUID_TYPE_RANDOM = 4;
    /**
     * Version 5 (name-based and hashed with SHA1) UUID
     *
     * @link https://www.rfc-editor.org/rfc/rfc9562#section-4.2 RFC 9562, 4.2. Version Field
     */
    public const UUID_TYPE_HASH_SHA1 = 5;
    /**
     * @deprecated Use {@see Uuid::UUID_TYPE_REORDERED_TIME} instead.
     */
    public const UUID_TYPE_PEABODY = 6;
    /**
     * Version 6 (reordered Gregorian time) UUID
     *
     * @link https://www.rfc-editor.org/rfc/rfc9562#section-4.2 RFC 9562, 4.2. Version Field
     */
    public const UUID_TYPE_REORDERED_TIME = 6;
    /**
     * Version 7 (Unix Epoch time) UUID
     *
     * @link https://www.rfc-editor.org/rfc/rfc9562#section-4.2 RFC 9562, 4.2. Version Field
     */
    public const UUID_TYPE_UNIX_TIME = 7;
    /**
     * Version 8 (custom format) UUID
     *
     * @link https://www.rfc-editor.org/rfc/rfc9562#section-4.2 RFC 9562, 4.2. Version Field
     */
    public const UUID_TYPE_CUSTOM = 8;
    /**
     * DCE Security principal domain
     *
     * @link https://pubs.opengroup.org/onlinepubs/9696989899/chap11.htm#tagcjh_14_05_01_01 DCE 1.1, §11.5.1.1
     */
    public const DCE_DOMAIN_PERSON = 0;
    /**
     * DCE Security group domain
     *
     * @link https://pubs.opengroup.org/onlinepubs/9696989899/chap11.htm#tagcjh_14_05_01_01 DCE 1.1, §11.5.1.1
     */
    public const DCE_DOMAIN_GROUP = 1;
    /**
     * DCE Security organization domain
     *
     * @link https://pubs.opengroup.org/onlinepubs/9696989899/chap11.htm#tagcjh_14_05_01_01 DCE 1.1, §11.5.1.1
     */
    public const DCE_DOMAIN_ORG = 2;
    /**
     * DCE Security domain string names
     *
     * @link https://pubs.opengroup.org/onlinepubs/9696989899/chap11.htm#tagcjh_14_05_01_01 DCE 1.1, §11.5.1.1
     */
    public const DCE_DOMAIN_NAMES = [self::DCE_DOMAIN_PERSON => 'person', self::DCE_DOMAIN_GROUP => 'group', self::DCE_DOMAIN_ORG => 'org'];
    /**
     * @phpstan-ignore property.readOnlyByPhpDocDefaultValue
     */
    private static ?UuidFactoryInterface $factory = null;
    /**
     * @var bool flag to detect if the UUID factory was replaced internally, which disables all optimizations for the
     *     default/happy path internal scenarios
     * @phpstan-ignore property.readOnlyByPhpDocDefaultValue
     */
    private static bool $factoryReplaced = \false;
    protected CodecInterface $codec;
    protected NumberConverterInterface $numberConverter;
    protected Rfc4122FieldsInterface $fields;
    protected TimeConverterInterface $timeConverter;
    /**
     * Creates a universally unique identifier (UUID) from an array of fields
     *
     * Unless you're making advanced use of this library to generate identifiers that deviate from RFC 9562 (formerly
     * RFC 4122), you probably do not want to instantiate a UUID directly. Use the static methods, instead:
     *
     * ```
     * use Ramsey\Uuid\Uuid;
     *
     * $timeBasedUuid = Uuid::uuid1();
     * $namespaceMd5Uuid = Uuid::uuid3(Uuid::NAMESPACE_URL, 'http://php.net/');
     * $randomUuid = Uuid::uuid4();
     * $namespaceSha1Uuid = Uuid::uuid5(Uuid::NAMESPACE_URL, 'http://php.net/');
     * ```
     *
     * @param Rfc4122FieldsInterface $fields The fields from which to construct a UUID
     * @param NumberConverterInterface $numberConverter The number converter to use for converting hex values to/from integers
     * @param CodecInterface $codec The codec to use when encoding or decoding UUID strings
     * @param TimeConverterInterface $timeConverter The time converter to use for converting timestamps extracted from a
     *     UUID to unix timestamps
     */
    public function __construct(Rfc4122FieldsInterface $fields, NumberConverterInterface $numberConverter, CodecInterface $codec, TimeConverterInterface $timeConverter)
    {
        $this->fields = $fields;
        $this->codec = $codec;
        $this->numberConverter = $numberConverter;
        $this->timeConverter = $timeConverter;
    }
    /**
     * @return non-empty-string
     */
    public function __toString(): string
    {
        return $this->toString();
    }
    /**
     * Converts the UUID to a string for JSON serialization
     */
    public function jsonSerialize(): string
    {
        return $this->toString();
    }
    /**
     * Converts the UUID to a string for PHP serialization
     */
    public function serialize(): string
    {
        return $this->codec->encode($this);
    }
    /**
     * @return array{bytes: string}
     */
    public function __serialize(): array
    {
        return ['bytes' => $this->serialize()];
    }
    /**
     * Re-constructs the object from its serialized form
     *
     * @param string $data The serialized PHP string to unserialize into a UuidInterface instance
     */
    public function unserialize(string $data): void
    {
        if (strlen($data) === 16) {
            /** @var Uuid $uuid */
            $uuid = self::getFactory()->fromBytes($data);
        } else {
            /** @var Uuid $uuid */
            $uuid = self::getFactory()->fromString($data);
        }
        /** @phpstan-ignore property.readOnlyByPhpDocAssignNotInConstructor */
        $this->codec = $uuid->codec;
        /** @phpstan-ignore property.readOnlyByPhpDocAssignNotInConstructor */
        $this->numberConverter = $uuid->numberConverter;
        /** @phpstan-ignore property.readOnlyByPhpDocAssignNotInConstructor */
        $this->fields = $uuid->fields;
        /** @phpstan-ignore property.readOnlyByPhpDocAssignNotInConstructor */
        $this->timeConverter = $uuid->timeConverter;
    }
    /**
     * @param array{bytes?: string} $data
     */
    public function __unserialize(array $data): void
    {
        // @codeCoverageIgnoreStart
        if (!isset($data['bytes'])) {
            throw new ValueError(sprintf('%s(): Argument #1 ($data) is invalid', __METHOD__));
        }
        // @codeCoverageIgnoreEnd
        $this->unserialize($data['bytes']);
    }
    public function compareTo(UuidInterface $other): int
    {
        $compare = strcmp($this->toString(), $other->toString());
        if ($compare < 0) {
            return -1;
        }
        if ($compare > 0) {
            return 1;
        }
        return 0;
    }
    public function equals(?object $other): bool
    {
        if (!$other instanceof UuidInterface) {
            return \false;
        }
        return $this->compareTo($other) === 0;
    }
    /**
     * @return non-empty-string
     */
    public function getBytes(): string
    {
        return $this->codec->encodeBinary($this);
    }
    public function getFields(): FieldsInterface
    {
        return $this->fields;
    }
    public function getHex(): Hexadecimal
    {
        return new Hexadecimal(str_replace('-', '', $this->toString()));
    }
    public function getInteger(): IntegerObject
    {
        return new IntegerObject($this->numberConverter->fromHex($this->getHex()->toString()));
    }
    public function getUrn(): string
    {
        return 'urn:uuid:' . $this->toString();
    }
    /**
     * @return non-empty-string
     */
    public function toString(): string
    {
        return $this->codec->encode($this);
    }
    /**
     * Returns the factory used to create UUIDs
     */
    public static function getFactory(): UuidFactoryInterface
    {
        if (self::$factory === null) {
            self::$factory = new UuidFactory();
        }
        return self::$factory;
    }
    /**
     * Sets the factory used to create UUIDs
     *
     * @param UuidFactoryInterface $factory A factory that will be used by this class to create UUIDs
     */
    public static function setFactory(UuidFactoryInterface $factory): void
    {
        // Note: non-strict equality is intentional here. If the factory is configured differently, every assumption
        //       around purity is broken, and we have to internally decide everything differently.
        // phpcs:ignore SlevomatCodingStandard.Operators.DisallowEqualOperators.DisallowedNotEqualOperator
        self::$factoryReplaced = $factory != new UuidFactory();
        self::$factory = $factory;
    }
    /**
     * Creates a UUID from a byte string
     *
     * @param string $bytes A binary string
     *
     * @return UuidInterface A UuidInterface instance created from a binary string representation
     *
     * @throws InvalidArgumentException
     *
     * @pure
     */
    public static function fromBytes(string $bytes): UuidInterface
    {
        /** @phpstan-ignore impure.staticPropertyAccess */
        if (!self::$factoryReplaced && strlen($bytes) === 16) {
            $base16Uuid = bin2hex($bytes);
            // Note: we are calling `fromString` internally because we don't know if the given `$bytes` is a valid UUID
            return self::fromString(substr($base16Uuid, 0, 8) . '-' . substr($base16Uuid, 8, 4) . '-' . substr($base16Uuid, 12, 4) . '-' . substr($base16Uuid, 16, 4) . '-' . substr($base16Uuid, 20, 12));
        }
        /** @phpstan-ignore possiblyImpure.methodCall */
        return self::getFactory()->fromBytes($bytes);
    }
    /**
     * Creates a UUID from the string standard representation
     *
     * @param string $uuid A hexadecimal string
     *
     * @return UuidInterface A UuidInterface instance created from a hexadecimal string representation
     *
     * @throws InvalidArgumentException
     *
     * @pure
     */
    public static function fromString(string $uuid): UuidInterface
    {
        $uuid = strtolower($uuid);
        /** @phpstan-ignore impure.staticPropertyAccess, possiblyImpure.functionCall */
        if (!self::$factoryReplaced && preg_match(LazyUuidFromString::VALID_REGEX, $uuid) === 1) {
            /** @phpstan-ignore possiblyImpure.functionCall */
            assert($uuid !== '');
            /** @phpstan-ignore possiblyImpure.new */
            return new LazyUuidFromString($uuid);
        }
        /** @phpstan-ignore possiblyImpure.methodCall */
        return self::getFactory()->fromString($uuid);
    }
    /**
     * Creates a UUID from a DateTimeInterface instance
     *
     * @param DateTimeInterface $dateTime The date and time
     * @param Hexadecimal | null $node A 48-bit number representing the hardware address
     * @param int | null $clockSeq A 14-bit number used to help avoid duplicates that could arise when the clock is set
     *     backwards in time or if the node ID changes
     *
     * @return UuidInterface A UuidInterface instance that represents a version 1 UUID created from a DateTimeInterface instance
     */
    public static function fromDateTime(DateTimeInterface $dateTime, ?Hexadecimal $node = null, ?int $clockSeq = null): UuidInterface
    {
        return self::getFactory()->fromDateTime($dateTime, $node, $clockSeq);
    }
    /**
     * Creates a UUID from the Hexadecimal object
     *
     * @param Hexadecimal $hex Hexadecimal object representing a hexadecimal number
     *
     * @return UuidInterface A UuidInterface instance created from the Hexadecimal object representing a hexadecimal number
     *
     * @throws InvalidArgumentException
     *
     * @pure
     */
    public static function fromHexadecimal(Hexadecimal $hex): UuidInterface
    {
        /** @phpstan-ignore possiblyImpure.methodCall */
        $factory = self::getFactory();
        if (method_exists($factory, 'fromHexadecimal')) {
            /** @phpstan-ignore possiblyImpure.methodCall */
            $uuid = $factory->fromHexadecimal($hex);
            /** @phpstan-ignore possiblyImpure.functionCall */
            assert($uuid instanceof UuidInterface);
            return $uuid;
        }
        throw new BadMethodCallException('The method fromHexadecimal() does not exist on the provided factory');
    }
    /**
     * Creates a UUID from a 128-bit integer string
     *
     * @param string $integer String representation of 128-bit integer
     *
     * @return UuidInterface A UuidInterface instance created from the string representation of a 128-bit integer
     *
     * @throws InvalidArgumentException
     *
     * @pure
     */
    public static function fromInteger(string $integer): UuidInterface
    {
        /** @phpstan-ignore possiblyImpure.methodCall */
        return self::getFactory()->fromInteger($integer);
    }
    /**
     * Returns true if the provided string is a valid UUID
     *
     * @param string $uuid A string to validate as a UUID
     *
     * @return bool True if the string is a valid UUID, false otherwise
     *
     * @phpstan-assert-if-true =non-empty-string $uuid
     *
     * @pure
     */
    public static function isValid(string $uuid): bool
    {
        /** @phpstan-ignore possiblyImpure.methodCall, possiblyImpure.methodCall */
        return self::getFactory()->getValidator()->validate($uuid);
    }
    /**
     * Returns a version 1 (Gregorian time) UUID from a host ID, sequence number, and the current time
     *
     * @param Hexadecimal | int | string | null $node A 48-bit number representing the hardware address; this number may
     *     be represented as an integer or a hexadecimal string
     * @param int | null $clockSeq A 14-bit number used to help avoid duplicates that could arise when the clock is set
     *     backwards in time or if the node ID changes
     *
     * @return UuidInterface A UuidInterface instance that represents a version 1 UUID
     */
    public static function uuid1($node = null, ?int $clockSeq = null): UuidInterface
    {
        return self::getFactory()->uuid1($node, $clockSeq);
    }
    /**
     * Returns a version 2 (DCE Security) UUID from a local domain, local identifier, host ID, clock sequence, and the current time
     *
     * @param int $localDomain The local domain to use when generating bytes, according to DCE Security
     * @param IntegerObject | null $localIdentifier The local identifier for the given domain; this may be a UID or GID
     *     on POSIX systems, if the local domain is "person" or "group," or it may be a site-defined identifier if the
     *     local domain is "org"
     * @param Hexadecimal | null $node A 48-bit number representing the hardware address
     * @param int | null $clockSeq A 14-bit number used to help avoid duplicates that could arise when the clock is set
     *     backwards in time or if the node ID changes (in a version 2 UUID, the lower 8 bits of this number are
     *     replaced with the domain).
     *
     * @return UuidInterface A UuidInterface instance that represents a version 2 UUID
     */
    public static function uuid2(int $localDomain, ?IntegerObject $localIdentifier = null, ?Hexadecimal $node = null, ?int $clockSeq = null): UuidInterface
    {
        return self::getFactory()->uuid2($localDomain, $localIdentifier, $node, $clockSeq);
    }
    /**
     * Returns a version 3 (name-based) UUID based on the MD5 hash of a namespace ID and a name
     *
     * @param UuidInterface | string $ns The namespace (must be a valid UUID)
     * @param string $name The name to use for creating a UUID
     *
     * @return UuidInterface A UuidInterface instance that represents a version 3 UUID
     *
     * @pure
     */
    public static function uuid3($ns, string $name): UuidInterface
    {
        /** @phpstan-ignore possiblyImpure.methodCall */
        return self::getFactory()->uuid3($ns, $name);
    }
    /**
     * Returns a version 4 (random) UUID
     *
     * @return UuidInterface A UuidInterface instance that represents a version 4 UUID
     */
    public static function uuid4(): UuidInterface
    {
        return self::getFactory()->uuid4();
    }
    /**
     * Returns a version 5 (name-based) UUID based on the SHA-1 hash of a namespace ID and a name
     *
     * @param UuidInterface | string $ns The namespace (must be a valid UUID)
     * @param string $name The name to use for creating a UUID
     *
     * @return UuidInterface A UuidInterface instance that represents a version 5 UUID
     *
     * @pure
     */
    public static function uuid5($ns, string $name): UuidInterface
    {
        /** @phpstan-ignore possiblyImpure.methodCall */
        return self::getFactory()->uuid5($ns, $name);
    }
    /**
     * Returns a version 6 (reordered Gregorian time) UUID from a host ID, sequence number, and the current time
     *
     * @param Hexadecimal | null $node A 48-bit number representing the hardware address
     * @param int | null $clockSeq A 14-bit number used to help avoid duplicates that could arise when the clock is set
     *     backwards in time or if the node ID changes
     *
     * @return UuidInterface A UuidInterface instance that represents a version 6 UUID
     */
    public static function uuid6(?Hexadecimal $node = null, ?int $clockSeq = null): UuidInterface
    {
        return self::getFactory()->uuid6($node, $clockSeq);
    }
    /**
     * Returns a version 7 (Unix Epoch time) UUID
     *
     * @param DateTimeInterface | null $dateTime An optional date/time from which to create the version 7 UUID. If not
     *     provided, the UUID is generated using the current date/time.
     *
     * @return UuidInterface A UuidInterface instance that represents a version 7 UUID
     */
    public static function uuid7(?DateTimeInterface $dateTime = null): UuidInterface
    {
        $factory = self::getFactory();
        if (method_exists($factory, 'uuid7')) {
            /** @var UuidInterface */
            return $factory->uuid7($dateTime);
        }
        throw new UnsupportedOperationException('The provided factory does not support the uuid7() method');
    }
    /**
     * Returns a version 8 (custom format) UUID
     *
     * The bytes provided may contain any value according to your application's needs. Be aware, however, that other
     * applications may not understand the semantics of the value.
     *
     * @param string $bytes A 16-byte octet string. This is an open blob of data that you may fill with 128 bits of
     *     information. Be aware, however, bits 48 through 51 will be replaced with the UUID version field, and bits 64
     *     and 65 will be replaced with the UUID variant. You MUST NOT rely on these bits for your application needs.
     *
     * @return UuidInterface A UuidInterface instance that represents a version 8 UUID
     *
     * @pure
     */
    public static function uuid8(string $bytes): UuidInterface
    {
        /** @phpstan-ignore possiblyImpure.methodCall */
        $factory = self::getFactory();
        if (method_exists($factory, 'uuid8')) {
            /**
             * @var UuidInterface
             * @phpstan-ignore possiblyImpure.methodCall
             */
            return $factory->uuid8($bytes);
        }
        throw new UnsupportedOperationException('The provided factory does not support the uuid8() method');
    }
}
<?php

/**
 * This file is part of the ramsey/uuid library
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @copyright Copyright (c) Ben Ramsey <ben@benramsey.com>
 * @license http://opensource.org/licenses/MIT MIT
 */
declare (strict_types=1);
namespace _ContaoManager\Ramsey\Uuid\Provider;

use _ContaoManager\Ramsey\Uuid\Rfc4122\UuidV2;
use _ContaoManager\Ramsey\Uuid\Type\Integer as IntegerObject;
/**
 * A DCE provider provides access to local domain identifiers for version 2, DCE Security, UUIDs
 *
 * @see UuidV2
 */
interface DceSecurityProviderInterface
{
    /**
     * Returns a user identifier for the system
     *
     * @link https://en.wikipedia.org/wiki/User_identifier User identifier
     */
    public function getUid(): IntegerObject;
    /**
     * Returns a group identifier for the system
     *
     * @link https://en.wikipedia.org/wiki/Group_identifier Group identifier
     */
    public function getGid(): IntegerObject;
}
<?php

/**
 * This file is part of the ramsey/uuid library
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @copyright Copyright (c) Ben Ramsey <ben@benramsey.com>
 * @license http://opensource.org/licenses/MIT MIT
 */
declare (strict_types=1);
namespace _ContaoManager\Ramsey\Uuid\Provider\Dce;

use _ContaoManager\Ramsey\Uuid\Exception\DceSecurityException;
use _ContaoManager\Ramsey\Uuid\Provider\DceSecurityProviderInterface;
use _ContaoManager\Ramsey\Uuid\Type\Integer as IntegerObject;
use function escapeshellarg;
use function preg_split;
use function str_getcsv;
use function strrpos;
use function strtolower;
use function strtoupper;
use function substr;
use function trim;
use const PREG_SPLIT_NO_EMPTY;
/**
 * SystemDceSecurityProvider retrieves the user or group identifiers from the system
 */
class SystemDceSecurityProvider implements DceSecurityProviderInterface
{
    /**
     * @throws DceSecurityException if unable to get a user identifier
     *
     * @inheritDoc
     */
    public function getUid(): IntegerObject
    {
        /** @var IntegerObject | int | float | string | null $uid */
        static $uid = null;
        if ($uid instanceof IntegerObject) {
            return $uid;
        }
        if ($uid === null) {
            $uid = $this->getSystemUid();
        }
        if ($uid === '') {
            throw new DceSecurityException('Unable to get a user identifier using the system DCE Security provider; please provide a custom ' . 'identifier or use a different provider');
        }
        $uid = new IntegerObject($uid);
        return $uid;
    }
    /**
     * @throws DceSecurityException if unable to get a group identifier
     *
     * @inheritDoc
     */
    public function getGid(): IntegerObject
    {
        /** @var IntegerObject | int | float | string | null $gid */
        static $gid = null;
        if ($gid instanceof IntegerObject) {
            return $gid;
        }
        if ($gid === null) {
            $gid = $this->getSystemGid();
        }
        if ($gid === '') {
            throw new DceSecurityException('Unable to get a group identifier using the system DCE Security provider; please provide a custom ' . 'identifier or use a different provider');
        }
        $gid = new IntegerObject($gid);
        return $gid;
    }
    /**
     * Returns the UID from the system
     */
    private function getSystemUid(): string
    {
        if (!$this->hasShellExec()) {
            return '';
        }
        return match ($this->getOs()) {
            'WIN' => $this->getWindowsUid(),
            default => trim((string) shell_exec('id -u')),
        };
    }
    /**
     * Returns the GID from the system
     */
    private function getSystemGid(): string
    {
        if (!$this->hasShellExec()) {
            return '';
        }
        return match ($this->getOs()) {
            'WIN' => $this->getWindowsGid(),
            default => trim((string) shell_exec('id -g')),
        };
    }
    /**
     * Returns true if shell_exec() is available for use
     */
    private function hasShellExec(): bool
    {
        return !str_contains(strtolower((string) ini_get('disable_functions')), 'shell_exec');
    }
    /**
     * Returns the PHP_OS string
     */
    private function getOs(): string
    {
        /** @var string $phpOs */
        $phpOs = constant('PHP_OS');
        return strtoupper(substr($phpOs, 0, 3));
    }
    /**
     * Returns the user identifier for a user on a Windows system
     *
     * Windows does not have the same concept as an effective POSIX UID for the running script. Instead, each user is
     * uniquely identified by an SID (security identifier). The SID includes three 32-bit unsigned integers that make up
     * a unique domain identifier, followed by an RID (relative identifier) that we will use as the UID. The primary
     * caveat is that this UID may not be unique to the system, since it is, instead, unique to the domain.
     *
     * @link https://www.lifewire.com/what-is-an-sid-number-2626005 What Is an SID Number?
     * @link https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-dtyp/81d92bba-d22b-4a8c-908a-554ab29148ab Well-known SID Structures
     * @link https://learn.microsoft.com/en-us/windows-server/identity/ad-ds/manage/understand-security-identifiers#well-known-sids Well-known SIDs
     * @link https://www.windows-commandline.com/get-sid-of-user/ Get SID of user
     */
    private function getWindowsUid(): string
    {
        $response = shell_exec('whoami /user /fo csv /nh');
        if ($response === null) {
            return '';
        }
        $sid = str_getcsv(trim((string) $response), escape: '\\')[1] ?? '';
        if (($lastHyphen = strrpos($sid, '-')) === \false) {
            return '';
        }
        return trim(substr($sid, $lastHyphen + 1));
    }
    /**
     * Returns a group identifier for a user on a Windows system
     *
     * Since Windows does not have the same concept as an effective POSIX GID for the running script, we will get the
     * local group memberships for the user running the script. Then, we will get the SID (security identifier) for the
     * first group that appears in that list. Finally, we will return the RID (relative identifier) for the group and
     * use that as the GID.
     *
     * @link https://www.windows-commandline.com/list-of-user-groups-command-line/ List of user groups command line
     */
    private function getWindowsGid(): string
    {
        $response = shell_exec('net user %username% | findstr /b /i "Local Group Memberships"');
        if ($response === null) {
            return '';
        }
        $userGroups = preg_split('/\s{2,}/', (string) $response, -1, PREG_SPLIT_NO_EMPTY);
        $firstGroup = trim($userGroups[1] ?? '', "* \t\n\r\x00\v");
        if ($firstGroup === '') {
            return '';
        }
        $response = shell_exec('wmic group get name,sid | findstr /b /i ' . escapeshellarg($firstGroup));
        if ($response === null) {
            return '';
        }
        $userGroup = preg_split('/\s{2,}/', (string) $response, -1, PREG_SPLIT_NO_EMPTY);
        $sid = $userGroup[1] ?? '';
        if (($lastHyphen = strrpos($sid, '-')) === \false) {
            return '';
        }
        return trim(substr($sid, $lastHyphen + 1));
    }
}
<?php

/**
 * This file is part of the ramsey/uuid library
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @copyright Copyright (c) Ben Ramsey <ben@benramsey.com>
 * @license http://opensource.org/licenses/MIT MIT
 */
declare (strict_types=1);
namespace _ContaoManager\Ramsey\Uuid\Provider;

use _ContaoManager\Ramsey\Uuid\Type\Hexadecimal;
/**
 * A node provider retrieves or generates a node ID
 */
interface NodeProviderInterface
{
    /**
     * Returns a node ID
     *
     * @return Hexadecimal The node ID as a hexadecimal string
     */
    public function getNode(): Hexadecimal;
}
<?php

/**
 * This file is part of the ramsey/uuid library
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @copyright Copyright (c) Ben Ramsey <ben@benramsey.com>
 * @license http://opensource.org/licenses/MIT MIT
 */
declare (strict_types=1);
namespace _ContaoManager\Ramsey\Uuid\Provider\Time;

use _ContaoManager\Ramsey\Uuid\Provider\TimeProviderInterface;
use _ContaoManager\Ramsey\Uuid\Type\Time;
use function gettimeofday;
/**
 * SystemTimeProvider retrieves the current time using built-in PHP functions
 */
class SystemTimeProvider implements TimeProviderInterface
{
    public function getTime(): Time
    {
        $time = gettimeofday();
        return new Time($time['sec'], $time['usec']);
    }
}
<?php

/**
 * This file is part of the ramsey/uuid library
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @copyright Copyright (c) Ben Ramsey <ben@benramsey.com>
 * @license http://opensource.org/licenses/MIT MIT
 */
declare (strict_types=1);
namespace _ContaoManager\Ramsey\Uuid\Provider\Time;

use _ContaoManager\Ramsey\Uuid\Provider\TimeProviderInterface;
use _ContaoManager\Ramsey\Uuid\Type\Integer as IntegerObject;
use _ContaoManager\Ramsey\Uuid\Type\Time;
/**
 * FixedTimeProvider uses a known time to provide the time
 *
 * This provider allows the use of a previously generated, or known, time when generating time-based UUIDs.
 */
class FixedTimeProvider implements TimeProviderInterface
{
    public function __construct(private Time $time)
    {
    }
    /**
     * Sets the `usec` component of the time
     *
     * @param IntegerObject | int | string $value The `usec` value to set
     */
    public function setUsec($value): void
    {
        $this->time = new Time($this->time->getSeconds(), $value);
    }
    /**
     * Sets the `sec` component of the time
     *
     * @param IntegerObject | int | string $value The `sec` value to set
     */
    public function setSec($value): void
    {
        $this->time = new Time($value, $this->time->getMicroseconds());
    }
    public function getTime(): Time
    {
        return $this->time;
    }
}
<?php

/**
 * This file is part of the ramsey/uuid library
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @copyright Copyright (c) Ben Ramsey <ben@benramsey.com>
 * @license http://opensource.org/licenses/MIT MIT
 */
declare (strict_types=1);
namespace _ContaoManager\Ramsey\Uuid\Provider;

use _ContaoManager\Ramsey\Uuid\Type\Time;
/**
 * A time provider retrieves the current time
 */
interface TimeProviderInterface
{
    /**
     * Returns a time object
     */
    public function getTime(): Time;
}
<?php

/**
 * This file is part of the ramsey/uuid library
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @copyright Copyright (c) Ben Ramsey <ben@benramsey.com>
 * @license http://opensource.org/licenses/MIT MIT
 */
declare (strict_types=1);
namespace _ContaoManager\Ramsey\Uuid\Provider\Node;

use _ContaoManager\Ramsey\Uuid\Exception\RandomSourceException;
use _ContaoManager\Ramsey\Uuid\Provider\NodeProviderInterface;
use _ContaoManager\Ramsey\Uuid\Type\Hexadecimal;
use Throwable;
use function bin2hex;
use function dechex;
use function hex2bin;
use function hexdec;
use function str_pad;
use function substr;
use const STR_PAD_LEFT;
/**
 * RandomNodeProvider generates a random node ID
 *
 * @link https://www.rfc-editor.org/rfc/rfc9562#section-6.10 RFC 9562, 6.10. UUIDs That Do Not Identify the Host
 */
class RandomNodeProvider implements NodeProviderInterface
{
    public function getNode(): Hexadecimal
    {
        try {
            $nodeBytes = random_bytes(6);
        } catch (Throwable $exception) {
            throw new RandomSourceException($exception->getMessage(), (int) $exception->getCode(), $exception);
        }
        // Split the node bytes for math on 32-bit systems.
        $nodeMsb = substr($nodeBytes, 0, 3);
        $nodeLsb = substr($nodeBytes, 3);
        // Set the multicast bit; see RFC 9562, section 6.10.
        $nodeMsb = hex2bin(str_pad(dechex(hexdec(bin2hex($nodeMsb)) | 0x10000), 6, '0', STR_PAD_LEFT));
        return new Hexadecimal(str_pad(bin2hex($nodeMsb . $nodeLsb), 12, '0', STR_PAD_LEFT));
    }
}
<?php

/**
 * This file is part of the ramsey/uuid library
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @copyright Copyright (c) Ben Ramsey <ben@benramsey.com>
 * @license http://opensource.org/licenses/MIT MIT
 */
declare (strict_types=1);
namespace _ContaoManager\Ramsey\Uuid\Provider\Node;

use _ContaoManager\Ramsey\Uuid\Exception\NodeException;
use _ContaoManager\Ramsey\Uuid\Provider\NodeProviderInterface;
use _ContaoManager\Ramsey\Uuid\Type\Hexadecimal;
/**
 * FallbackNodeProvider retrieves the system node ID by stepping through a list of providers until a node ID can be obtained
 */
class FallbackNodeProvider implements NodeProviderInterface
{
    /**
     * @param iterable<NodeProviderInterface> $providers Array of node providers
     */
    public function __construct(private iterable $providers)
    {
    }
    public function getNode(): Hexadecimal
    {
        $lastProviderException = null;
        foreach ($this->providers as $provider) {
            try {
                return $provider->getNode();
            } catch (NodeException $exception) {
                $lastProviderException = $exception;
                continue;
            }
        }
        throw new NodeException(message: 'Unable to find a suitable node provider', previous: $lastProviderException);
    }
}
<?php

/**
 * This file is part of the ramsey/uuid library
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @copyright Copyright (c) Ben Ramsey <ben@benramsey.com>
 * @license http://opensource.org/licenses/MIT MIT
 */
declare (strict_types=1);
namespace _ContaoManager\Ramsey\Uuid\Provider\Node;

use _ContaoManager\Ramsey\Uuid\Exception\NodeException;
use _ContaoManager\Ramsey\Uuid\Provider\NodeProviderInterface;
use _ContaoManager\Ramsey\Uuid\Type\Hexadecimal;
use function array_filter;
use function array_map;
use function array_walk;
use function count;
use function ob_get_clean;
use function ob_start;
use function preg_match;
use function preg_match_all;
use function reset;
use function str_contains;
use function str_replace;
use function strtolower;
use function strtoupper;
use function substr;
use const GLOB_NOSORT;
use const PREG_PATTERN_ORDER;
/**
 * SystemNodeProvider retrieves the system node ID, if possible
 *
 * The system node ID, or host ID, is often the same as the MAC address for a network interface on the host.
 */
class SystemNodeProvider implements NodeProviderInterface
{
    /**
     * Pattern to match nodes in `ifconfig` and `ipconfig` output.
     */
    private const IFCONFIG_PATTERN = '/[^:]([0-9a-f]{2}([:-])[0-9a-f]{2}(\2[0-9a-f]{2}){4})[^:]/i';
    /**
     * Pattern to match nodes in sysfs stream output.
     */
    private const SYSFS_PATTERN = '/^([0-9a-f]{2}:){5}[0-9a-f]{2}$/i';
    public function getNode(): Hexadecimal
    {
        $node = $this->getNodeFromSystem();
        if ($node === '') {
            throw new NodeException('Unable to fetch a node for this system');
        }
        return new Hexadecimal($node);
    }
    /**
     * Returns the system node if found
     */
    protected function getNodeFromSystem(): string
    {
        /** @var string | null $node */
        static $node = null;
        if ($node !== null) {
            return $node;
        }
        // First, try a Linux-specific approach.
        $node = $this->getSysfs();
        if ($node === '') {
            // Search ifconfig output for MAC addresses & return the first one.
            $node = $this->getIfconfig();
        }
        $node = str_replace([':', '-'], '', $node);
        return $node;
    }
    /**
     * Returns the network interface configuration for the system
     *
     * @codeCoverageIgnore
     */
    protected function getIfconfig(): string
    {
        if (str_contains(strtolower((string) ini_get('disable_functions')), 'passthru')) {
            return '';
        }
        /** @var string $phpOs */
        $phpOs = constant('PHP_OS');
        ob_start();
        switch (strtoupper(substr($phpOs, 0, 3))) {
            case 'WIN':
                passthru('ipconfig /all 2>&1');
                break;
            case 'DAR':
                passthru('ifconfig 2>&1');
                break;
            case 'FRE':
                passthru('netstat -i -f link 2>&1');
                break;
            case 'LIN':
            default:
                passthru('netstat -ie 2>&1');
                break;
        }
        $ifconfig = (string) ob_get_clean();
        if (preg_match_all(self::IFCONFIG_PATTERN, $ifconfig, $matches, PREG_PATTERN_ORDER)) {
            foreach ($matches[1] as $iface) {
                if ($iface !== '00:00:00:00:00:00' && $iface !== '00-00-00-00-00-00') {
                    return $iface;
                }
            }
        }
        return '';
    }
    /**
     * Returns MAC address from the first system interface via the sysfs interface
     */
    protected function getSysfs(): string
    {
        /** @var string $phpOs */
        $phpOs = constant('PHP_OS');
        if (strtoupper($phpOs) !== 'LINUX') {
            return '';
        }
        $addressPaths = glob('/sys/class/net/*/address', GLOB_NOSORT);
        if ($addressPaths === \false || count($addressPaths) === 0) {
            return '';
        }
        /** @var array<array-key, string> $macs */
        $macs = [];
        array_walk($addressPaths, function (string $addressPath) use (&$macs): void {
            if (is_readable($addressPath)) {
                $macs[] = file_get_contents($addressPath);
            }
        });
        /** @var callable $trim */
        $trim = 'trim';
        $macs = array_map($trim, $macs);
        // Remove invalid entries.
        $macs = array_filter($macs, function (mixed $address): bool {
            assert(is_string($address));
            return $address !== '00:00:00:00:00:00' && preg_match(self::SYSFS_PATTERN, $address);
        });
        /** @var bool | string $mac */
        $mac = reset($macs);
        return (string) $mac;
    }
}
<?php

/**
 * This file is part of the ramsey/uuid library
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @copyright Copyright (c) Ben Ramsey <ben@benramsey.com>
 * @license http://opensource.org/licenses/MIT MIT
 */
declare (strict_types=1);
namespace _ContaoManager\Ramsey\Uuid\Provider\Node;

use _ContaoManager\Ramsey\Collection\AbstractCollection;
use _ContaoManager\Ramsey\Uuid\Provider\NodeProviderInterface;
use _ContaoManager\Ramsey\Uuid\Type\Hexadecimal;
/**
 * A collection of NodeProviderInterface objects
 *
 * @deprecated this class has been deprecated and will be removed in 5.0.0. The use-case for this class comes from a
 *     pre-`phpstan/phpstan` and pre-`vimeo/psalm` ecosystem, in which type safety had to be mostly enforced at runtime:
 *     that is no longer necessary, now that you can safely verify your code to be correct and use more generic types
 *     like `iterable<T>` instead.
 *
 * @extends AbstractCollection<NodeProviderInterface>
 */
class NodeProviderCollection extends AbstractCollection
{
    public function getType(): string
    {
        return NodeProviderInterface::class;
    }
    /**
     * Re-constructs the object from its serialized form
     *
     * @param string $serialized The serialized PHP string to unserialize into a UuidInterface instance
     */
    public function unserialize($serialized): void
    {
        /** @var array<array-key, NodeProviderInterface> $data */
        $data = unserialize($serialized, ['allowed_classes' => [Hexadecimal::class, RandomNodeProvider::class, StaticNodeProvider::class, SystemNodeProvider::class]]);
        /** @phpstan-ignore-next-line */
        $this->data = array_filter($data, fn($unserialized): bool => $unserialized instanceof NodeProviderInterface);
    }
}
<?php

/**
 * This file is part of the ramsey/uuid library
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @copyright Copyright (c) Ben Ramsey <ben@benramsey.com>
 * @license http://opensource.org/licenses/MIT MIT
 */
declare (strict_types=1);
namespace _ContaoManager\Ramsey\Uuid\Provider\Node;

use _ContaoManager\Ramsey\Uuid\Exception\InvalidArgumentException;
use _ContaoManager\Ramsey\Uuid\Provider\NodeProviderInterface;
use _ContaoManager\Ramsey\Uuid\Type\Hexadecimal;
use function dechex;
use function hexdec;
use function str_pad;
use function substr;
use const STR_PAD_LEFT;
/**
 * StaticNodeProvider provides a static node value with the multicast bit set
 *
 * @link https://www.rfc-editor.org/rfc/rfc9562#section-6.10 RFC 9562, 6.10. UUIDs That Do Not Identify the Host
 */
class StaticNodeProvider implements NodeProviderInterface
{
    private Hexadecimal $node;
    /**
     * @param Hexadecimal $node The static node value to use
     */
    public function __construct(Hexadecimal $node)
    {
        if (strlen($node->toString()) > 12) {
            throw new InvalidArgumentException('Static node value cannot be greater than 12 hexadecimal characters');
        }
        $this->node = $this->setMulticastBit($node);
    }
    public function getNode(): Hexadecimal
    {
        return $this->node;
    }
    /**
     * Set the multicast bit for the static node value
     */
    private function setMulticastBit(Hexadecimal $node): Hexadecimal
    {
        $nodeHex = str_pad($node->toString(), 12, '0', STR_PAD_LEFT);
        $firstOctet = substr($nodeHex, 0, 2);
        $firstOctet = str_pad(dechex(hexdec($firstOctet) | 0x1), 2, '0', STR_PAD_LEFT);
        return new Hexadecimal($firstOctet . substr($nodeHex, 2));
    }
}
<?php

/**
 * This file is part of the ramsey/uuid library
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @copyright Copyright (c) Ben Ramsey <ben@benramsey.com>
 * @license http://opensource.org/licenses/MIT MIT
 */
declare (strict_types=1);
namespace _ContaoManager\Ramsey\Uuid;

use _ContaoManager\Ramsey\Uuid\Builder\FallbackBuilder;
use _ContaoManager\Ramsey\Uuid\Builder\UuidBuilderInterface;
use _ContaoManager\Ramsey\Uuid\Codec\CodecInterface;
use _ContaoManager\Ramsey\Uuid\Codec\GuidStringCodec;
use _ContaoManager\Ramsey\Uuid\Codec\StringCodec;
use _ContaoManager\Ramsey\Uuid\Converter\Number\GenericNumberConverter;
use _ContaoManager\Ramsey\Uuid\Converter\NumberConverterInterface;
use _ContaoManager\Ramsey\Uuid\Converter\Time\GenericTimeConverter;
use _ContaoManager\Ramsey\Uuid\Converter\Time\PhpTimeConverter;
use _ContaoManager\Ramsey\Uuid\Converter\TimeConverterInterface;
use _ContaoManager\Ramsey\Uuid\Generator\DceSecurityGenerator;
use _ContaoManager\Ramsey\Uuid\Generator\DceSecurityGeneratorInterface;
use _ContaoManager\Ramsey\Uuid\Generator\NameGeneratorFactory;
use _ContaoManager\Ramsey\Uuid\Generator\NameGeneratorInterface;
use _ContaoManager\Ramsey\Uuid\Generator\PeclUuidNameGenerator;
use _ContaoManager\Ramsey\Uuid\Generator\PeclUuidRandomGenerator;
use _ContaoManager\Ramsey\Uuid\Generator\PeclUuidTimeGenerator;
use _ContaoManager\Ramsey\Uuid\Generator\RandomGeneratorFactory;
use _ContaoManager\Ramsey\Uuid\Generator\RandomGeneratorInterface;
use _ContaoManager\Ramsey\Uuid\Generator\TimeGeneratorFactory;
use _ContaoManager\Ramsey\Uuid\Generator\TimeGeneratorInterface;
use _ContaoManager\Ramsey\Uuid\Generator\UnixTimeGenerator;
use _ContaoManager\Ramsey\Uuid\Guid\GuidBuilder;
use _ContaoManager\Ramsey\Uuid\Math\BrickMathCalculator;
use _ContaoManager\Ramsey\Uuid\Math\CalculatorInterface;
use _ContaoManager\Ramsey\Uuid\Nonstandard\UuidBuilder as NonstandardUuidBuilder;
use _ContaoManager\Ramsey\Uuid\Provider\Dce\SystemDceSecurityProvider;
use _ContaoManager\Ramsey\Uuid\Provider\DceSecurityProviderInterface;
use _ContaoManager\Ramsey\Uuid\Provider\Node\FallbackNodeProvider;
use _ContaoManager\Ramsey\Uuid\Provider\Node\RandomNodeProvider;
use _ContaoManager\Ramsey\Uuid\Provider\Node\SystemNodeProvider;
use _ContaoManager\Ramsey\Uuid\Provider\NodeProviderInterface;
use _ContaoManager\Ramsey\Uuid\Provider\Time\SystemTimeProvider;
use _ContaoManager\Ramsey\Uuid\Provider\TimeProviderInterface;
use _ContaoManager\Ramsey\Uuid\Rfc4122\UuidBuilder as Rfc4122UuidBuilder;
use _ContaoManager\Ramsey\Uuid\Validator\GenericValidator;
use _ContaoManager\Ramsey\Uuid\Validator\ValidatorInterface;
use const PHP_INT_SIZE;
/**
 * FeatureSet detects and exposes available features in the current environment
 *
 * A feature set is used by UuidFactory to determine the available features and capabilities of the environment.
 */
class FeatureSet
{
    private ?TimeProviderInterface $timeProvider = null;
    private CalculatorInterface $calculator;
    private CodecInterface $codec;
    private DceSecurityGeneratorInterface $dceSecurityGenerator;
    private NameGeneratorInterface $nameGenerator;
    private NodeProviderInterface $nodeProvider;
    private NumberConverterInterface $numberConverter;
    private RandomGeneratorInterface $randomGenerator;
    private TimeConverterInterface $timeConverter;
    private TimeGeneratorInterface $timeGenerator;
    private TimeGeneratorInterface $unixTimeGenerator;
    private UuidBuilderInterface $builder;
    private ValidatorInterface $validator;
    /**
     * @param bool $useGuids True build UUIDs using the GuidStringCodec
     * @param bool $force32Bit True to force the use of 32-bit functionality (primarily for testing purposes)
     * @param bool $forceNoBigNumber (obsolete)
     * @param bool $ignoreSystemNode True to disable attempts to check for the system node ID (primarily for testing purposes)
     * @param bool $enablePecl True to enable the use of the PeclUuidTimeGenerator to generate version 1 UUIDs
     *
     * @phpstan-ignore constructor.unusedParameter ($forceNoBigNumber is deprecated)
     */
    public function __construct(bool $useGuids = \false, private bool $force32Bit = \false, bool $forceNoBigNumber = \false, private bool $ignoreSystemNode = \false, private bool $enablePecl = \false)
    {
        $this->randomGenerator = $this->buildRandomGenerator();
        $this->setCalculator(new BrickMathCalculator());
        $this->builder = $this->buildUuidBuilder($useGuids);
        $this->codec = $this->buildCodec($useGuids);
        $this->nodeProvider = $this->buildNodeProvider();
        $this->nameGenerator = $this->buildNameGenerator();
        $this->setTimeProvider(new SystemTimeProvider());
        $this->setDceSecurityProvider(new SystemDceSecurityProvider());
        $this->validator = new GenericValidator();
        assert($this->timeProvider !== null);
        $this->unixTimeGenerator = $this->buildUnixTimeGenerator();
    }
    /**
     * Returns the builder configured for this environment
     */
    public function getBuilder(): UuidBuilderInterface
    {
        return $this->builder;
    }
    /**
     * Returns the calculator configured for this environment
     */
    public function getCalculator(): CalculatorInterface
    {
        return $this->calculator;
    }
    /**
     * Returns the codec configured for this environment
     */
    public function getCodec(): CodecInterface
    {
        return $this->codec;
    }
    /**
     * Returns the DCE Security generator configured for this environment
     */
    public function getDceSecurityGenerator(): DceSecurityGeneratorInterface
    {
        return $this->dceSecurityGenerator;
    }
    /**
     * Returns the name generator configured for this environment
     */
    public function getNameGenerator(): NameGeneratorInterface
    {
        return $this->nameGenerator;
    }
    /**
     * Returns the node provider configured for this environment
     */
    public function getNodeProvider(): NodeProviderInterface
    {
        return $this->nodeProvider;
    }
    /**
     * Returns the number converter configured for this environment
     */
    public function getNumberConverter(): NumberConverterInterface
    {
        return $this->numberConverter;
    }
    /**
     * Returns the random generator configured for this environment
     */
    public function getRandomGenerator(): RandomGeneratorInterface
    {
        return $this->randomGenerator;
    }
    /**
     * Returns the time converter configured for this environment
     */
    public function getTimeConverter(): TimeConverterInterface
    {
        return $this->timeConverter;
    }
    /**
     * Returns the time generator configured for this environment
     */
    public function getTimeGenerator(): TimeGeneratorInterface
    {
        return $this->timeGenerator;
    }
    /**
     * Returns the Unix Epoch time generator configured for this environment
     */
    public function getUnixTimeGenerator(): TimeGeneratorInterface
    {
        return $this->unixTimeGenerator;
    }
    /**
     * Returns the validator configured for this environment
     */
    public function getValidator(): ValidatorInterface
    {
        return $this->validator;
    }
    /**
     * Sets the calculator to use in this environment
     */
    public function setCalculator(CalculatorInterface $calculator): void
    {
        $this->calculator = $calculator;
        $this->numberConverter = $this->buildNumberConverter($calculator);
        $this->timeConverter = $this->buildTimeConverter($calculator);
        if (isset($this->timeProvider)) {
            $this->timeGenerator = $this->buildTimeGenerator($this->timeProvider);
        }
    }
    /**
     * Sets the DCE Security provider to use in this environment
     */
    public function setDceSecurityProvider(DceSecurityProviderInterface $dceSecurityProvider): void
    {
        $this->dceSecurityGenerator = $this->buildDceSecurityGenerator($dceSecurityProvider);
    }
    /**
     * Sets the node provider to use in this environment
     */
    public function setNodeProvider(NodeProviderInterface $nodeProvider): void
    {
        $this->nodeProvider = $nodeProvider;
        if (isset($this->timeProvider)) {
            $this->timeGenerator = $this->buildTimeGenerator($this->timeProvider);
        }
    }
    /**
     * Sets the time provider to use in this environment
     */
    public function setTimeProvider(TimeProviderInterface $timeProvider): void
    {
        $this->timeProvider = $timeProvider;
        $this->timeGenerator = $this->buildTimeGenerator($timeProvider);
    }
    /**
     * Set the validator to use in this environment
     */
    public function setValidator(ValidatorInterface $validator): void
    {
        $this->validator = $validator;
    }
    /**
     * Returns a codec configured for this environment
     *
     * @param bool $useGuids Whether to build UUIDs using the GuidStringCodec
     */
    private function buildCodec(bool $useGuids = \false): CodecInterface
    {
        if ($useGuids) {
            return new GuidStringCodec($this->builder);
        }
        return new StringCodec($this->builder);
    }
    /**
     * Returns a DCE Security generator configured for this environment
     */
    private function buildDceSecurityGenerator(DceSecurityProviderInterface $dceSecurityProvider): DceSecurityGeneratorInterface
    {
        return new DceSecurityGenerator($this->numberConverter, $this->timeGenerator, $dceSecurityProvider);
    }
    /**
     * Returns a node provider configured for this environment
     */
    private function buildNodeProvider(): NodeProviderInterface
    {
        if ($this->ignoreSystemNode) {
            return new RandomNodeProvider();
        }
        return new FallbackNodeProvider([new SystemNodeProvider(), new RandomNodeProvider()]);
    }
    /**
     * Returns a number converter configured for this environment
     */
    private function buildNumberConverter(CalculatorInterface $calculator): NumberConverterInterface
    {
        return new GenericNumberConverter($calculator);
    }
    /**
     * Returns a random generator configured for this environment
     */
    private function buildRandomGenerator(): RandomGeneratorInterface
    {
        if ($this->enablePecl) {
            return new PeclUuidRandomGenerator();
        }
        return (new RandomGeneratorFactory())->getGenerator();
    }
    /**
     * Returns a time generator configured for this environment
     *
     * @param TimeProviderInterface $timeProvider The time provider to use with
     *     the time generator
     */
    private function buildTimeGenerator(TimeProviderInterface $timeProvider): TimeGeneratorInterface
    {
        if ($this->enablePecl) {
            return new PeclUuidTimeGenerator();
        }
        return (new TimeGeneratorFactory($this->nodeProvider, $this->timeConverter, $timeProvider))->getGenerator();
    }
    /**
     * Returns a Unix Epoch time generator configured for this environment
     */
    private function buildUnixTimeGenerator(): TimeGeneratorInterface
    {
        return new UnixTimeGenerator($this->randomGenerator);
    }
    /**
     * Returns a name generator configured for this environment
     */
    private function buildNameGenerator(): NameGeneratorInterface
    {
        if ($this->enablePecl) {
            return new PeclUuidNameGenerator();
        }
        return (new NameGeneratorFactory())->getGenerator();
    }
    /**
     * Returns a time converter configured for this environment
     */
    private function buildTimeConverter(CalculatorInterface $calculator): TimeConverterInterface
    {
        $genericConverter = new GenericTimeConverter($calculator);
        if ($this->is64BitSystem()) {
            return new PhpTimeConverter($calculator, $genericConverter);
        }
        return $genericConverter;
    }
    /**
     * Returns a UUID builder configured for this environment
     *
     * @param bool $useGuids Whether to build UUIDs using the GuidStringCodec
     */
    private function buildUuidBuilder(bool $useGuids = \false): UuidBuilderInterface
    {
        if ($useGuids) {
            return new GuidBuilder($this->numberConverter, $this->timeConverter);
        }
        return new FallbackBuilder([new Rfc4122UuidBuilder($this->numberConverter, $this->timeConverter), new NonstandardUuidBuilder($this->numberConverter, $this->timeConverter)]);
    }
    /**
     * Returns true if the PHP build is 64-bit
     */
    private function is64BitSystem(): bool
    {
        return PHP_INT_SIZE === 8 && !$this->force32Bit;
    }
}
<?php

/**
 * This file is part of the ramsey/uuid library
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @copyright Copyright (c) Ben Ramsey <ben@benramsey.com>
 * @license http://opensource.org/licenses/MIT MIT
 */
declare (strict_types=1);
namespace _ContaoManager\Ramsey\Uuid\Rfc4122;

use _ContaoManager\Ramsey\Uuid\Fields\FieldsInterface as BaseFieldsInterface;
use _ContaoManager\Ramsey\Uuid\Type\Hexadecimal;
/**
 * UUID fields, as defined by RFC 4122
 *
 * This interface defines the fields of an RFC 4122 variant UUID. Since RFC 9562 removed the concept of fields and
 * instead defined layouts that are specific to a given version, this interface is a legacy artifact of the earlier, and
 * now obsolete, RFC 4122.
 *
 * The fields of an RFC 4122 variant UUID are:
 *
 * * **time_low**: The low field of the timestamp, an unsigned 32-bit integer
 * * **time_mid**: The middle field of the timestamp, an unsigned 16-bit integer
 * * **time_hi_and_version**: The high field of the timestamp multiplexed with the version number, an unsigned 16-bit integer
 * * **clock_seq_hi_and_reserved**: The high field of the clock sequence multiplexed with the variant, an unsigned 8-bit integer
 * * **clock_seq_low**: The low field of the clock sequence, an unsigned 8-bit integer
 * * **node**: The spatially unique node identifier, an unsigned 48-bit integer
 *
 * @link https://www.rfc-editor.org/rfc/rfc4122#section-4.1 RFC 4122, 4.1. Format
 * @link https://www.rfc-editor.org/rfc/rfc9562#section-4 RFC 9562, 4. UUID Format
 *
 * @immutable
 */
interface FieldsInterface extends BaseFieldsInterface
{
    /**
     * Returns the full 16-bit clock sequence, with the variant bits (two most significant bits) masked out
     */
    public function getClockSeq(): Hexadecimal;
    /**
     * Returns the high field of the clock sequence multiplexed with the variant
     */
    public function getClockSeqHiAndReserved(): Hexadecimal;
    /**
     * Returns the low field of the clock sequence
     */
    public function getClockSeqLow(): Hexadecimal;
    /**
     * Returns the node field
     */
    public function getNode(): Hexadecimal;
    /**
     * Returns the high field of the timestamp multiplexed with the version
     */
    public function getTimeHiAndVersion(): Hexadecimal;
    /**
     * Returns the low field of the timestamp
     */
    public function getTimeLow(): Hexadecimal;
    /**
     * Returns the middle field of the timestamp
     */
    public function getTimeMid(): Hexadecimal;
    /**
     * Returns the full 60-bit timestamp, without the version
     */
    public function getTimestamp(): Hexadecimal;
    /**
     * Returns the variant
     *
     * The variant number describes the layout of the UUID. The variant number has the following meaning:
     *
     * - 0 - Reserved for NCS backward compatibility
     * - 2 - The RFC 9562 (formerly RFC 4122) variant
     * - 6 - Reserved, Microsoft Corporation backward compatibility
     * - 7 - Reserved for future definition
     *
     * For RFC 9562 (formerly RFC 4122) variant UUIDs, this value should always be the integer `2`.
     *
     * @link https://www.rfc-editor.org/rfc/rfc9562#section-4.1 RFC 9562, 4.1. Variant Field
     */
    public function getVariant(): int;
    /**
     * Returns the UUID version
     *
     * The version number describes how the UUID was generated and has the following meaning:
     *
     * 1. Gregorian time UUID
     * 2. DCE security UUID
     * 3. Name-based UUID hashed with MD5
     * 4. Randomly generated UUID
     * 5. Name-based UUID hashed with SHA-1
     * 6. Reordered Gregorian time UUID
     * 7. Unix Epoch time UUID
     * 8. Custom format UUID
     *
     * This returns `null` if the UUID is not an RFC 9562 (formerly RFC 4122) variant, since the version is only
     * meaningful for this variant.
     *
     * @link https://www.rfc-editor.org/rfc/rfc9562#section-4.2 RFC 9562, 4.2. Version Field
     *
     * @pure
     */
    public function getVersion(): ?int;
    /**
     * Returns true if these fields represent a nil UUID
     *
     * The nil UUID is a special form of UUID that is specified to have all 128 bits set to zero.
     *
     * @pure
     */
    public function isNil(): bool;
}
<?php

/**
 * This file is part of the ramsey/uuid library
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @copyright Copyright (c) Ben Ramsey <ben@benramsey.com>
 * @license http://opensource.org/licenses/MIT MIT
 */
declare (strict_types=1);
namespace _ContaoManager\Ramsey\Uuid\Rfc4122;

use _ContaoManager\Ramsey\Uuid\Codec\CodecInterface;
use _ContaoManager\Ramsey\Uuid\Converter\NumberConverterInterface;
use _ContaoManager\Ramsey\Uuid\Converter\TimeConverterInterface;
use _ContaoManager\Ramsey\Uuid\Exception\InvalidArgumentException;
use _ContaoManager\Ramsey\Uuid\Rfc4122\FieldsInterface as Rfc4122FieldsInterface;
use _ContaoManager\Ramsey\Uuid\Uuid;
/**
 * Custom format, or version 8, UUIDs provide an RFC-compatible format for experimental or vendor-specific uses
 *
 * The only requirement for version 8 UUIDs is that the version and variant bits must be set. Otherwise, implementations
 * are free to set the other bits according to their needs. As a result, the uniqueness of version 8 UUIDs is
 * implementation-specific and should not be assumed.
 *
 * @link https://www.rfc-editor.org/rfc/rfc9562#section-5.8 RFC 9562, 5.8. UUID Version 8
 *
 * @immutable
 */
final class UuidV8 extends Uuid implements UuidInterface
{
    /**
     * Creates a version 8 (custom format) UUID
     *
     * @param Rfc4122FieldsInterface $fields The fields from which to construct a UUID
     * @param NumberConverterInterface $numberConverter The number converter to use for converting hex values to/from integers
     * @param CodecInterface $codec The codec to use when encoding or decoding UUID strings
     * @param TimeConverterInterface $timeConverter The time converter to use for converting timestamps extracted from a
     *     UUID to unix timestamps
     */
    public function __construct(Rfc4122FieldsInterface $fields, NumberConverterInterface $numberConverter, CodecInterface $codec, TimeConverterInterface $timeConverter)
    {
        if ($fields->getVersion() !== Uuid::UUID_TYPE_CUSTOM) {
            throw new InvalidArgumentException('Fields used to create a UuidV8 must represent a version 8 (custom format) UUID');
        }
        parent::__construct($fields, $numberConverter, $codec, $timeConverter);
    }
}
<?php

/**
 * This file is part of the ramsey/uuid library
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @copyright Copyright (c) Ben Ramsey <ben@benramsey.com>
 * @license http://opensource.org/licenses/MIT MIT
 */
declare (strict_types=1);
namespace _ContaoManager\Ramsey\Uuid\Rfc4122;

use _ContaoManager\Ramsey\Uuid\Uuid;
use _ContaoManager\Ramsey\Uuid\Validator\ValidatorInterface;
use function preg_match;
use function str_replace;
/**
 * Rfc4122\Validator validates strings as UUIDs of the RFC 9562 (formerly RFC 4122) variant
 *
 * @immutable
 */
final class Validator implements ValidatorInterface
{
    private const VALID_PATTERN = '\A[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-' . '[1-8][0-9A-Fa-f]{3}-[ABab89][0-9A-Fa-f]{3}-[0-9A-Fa-f]{12}\z';
    /**
     * @return non-empty-string
     */
    public function getPattern(): string
    {
        return self::VALID_PATTERN;
    }
    public function validate(string $uuid): bool
    {
        /** @phpstan-ignore possiblyImpure.functionCall */
        $uuid = strtolower(str_replace(['urn:', 'uuid:', 'URN:', 'UUID:', '{', '}'], '', $uuid));
        /** @phpstan-ignore possiblyImpure.functionCall */
        return $uuid === Uuid::NIL || $uuid === Uuid::MAX || preg_match('/' . self::VALID_PATTERN . '/Dms', $uuid);
    }
}
<?php

/**
 * This file is part of the ramsey/uuid library
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @copyright Copyright (c) Ben Ramsey <ben@benramsey.com>
 * @license http://opensource.org/licenses/MIT MIT
 */
declare (strict_types=1);
namespace _ContaoManager\Ramsey\Uuid\Rfc4122;

/**
 * Provides common functionality for max UUIDs
 *
 * @immutable
 */
trait MaxTrait
{
    /**
     * Returns the bytes that comprise the fields
     *
     * @pure
     */
    abstract public function getBytes(): string;
    /**
     * Returns true if the byte string represents a max UUID
     *
     * @pure
     */
    public function isMax(): bool
    {
        return $this->getBytes() === "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff";
    }
}
<?php

/**
 * This file is part of the ramsey/uuid library
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @copyright Copyright (c) Ben Ramsey <ben@benramsey.com>
 * @license http://opensource.org/licenses/MIT MIT
 */
declare (strict_types=1);
namespace _ContaoManager\Ramsey\Uuid\Rfc4122;

use _ContaoManager\Ramsey\Uuid\Uuid;
/**
 * Provides common functionality for handling the version, as defined by RFC 9562 (formerly RFC 4122)
 *
 * @immutable
 */
trait VersionTrait
{
    /**
     * Returns the UUID version
     *
     * The version number describes how the UUID was generated and has the following meaning:
     *
     * 1. Gregorian time UUID
     * 2. DCE security UUID
     * 3. Name-based UUID hashed with MD5
     * 4. Randomly generated UUID
     * 5. Name-based UUID hashed with SHA-1
     * 6. Reordered Gregorian time UUID
     * 7. Unix Epoch time UUID
     * 8. Custom format UUID
     *
     * This returns `null` if the UUID is not an RFC 9562 (formerly RFC 4122) variant, since the version is only
     * meaningful for this variant.
     *
     * @link https://www.rfc-editor.org/rfc/rfc9562#section-4.2 RFC 9562, 4.2. Version Field
     *
     * @pure
     */
    abstract public function getVersion(): ?int;
    /**
     * Returns true if these fields represent a max UUID
     */
    abstract public function isMax(): bool;
    /**
     * Returns true if these fields represent a nil UUID
     */
    abstract public function isNil(): bool;
    /**
     * Returns true if the version matches one of those defined by RFC 9562 (formerly RFC 4122)
     *
     * @return bool True if the UUID version is valid, false otherwise
     */
    private function isCorrectVersion(): bool
    {
        if ($this->isNil() || $this->isMax()) {
            return \true;
        }
        return match ($this->getVersion()) {
            Uuid::UUID_TYPE_TIME, Uuid::UUID_TYPE_DCE_SECURITY, Uuid::UUID_TYPE_HASH_MD5, Uuid::UUID_TYPE_RANDOM, Uuid::UUID_TYPE_HASH_SHA1, Uuid::UUID_TYPE_REORDERED_TIME, Uuid::UUID_TYPE_UNIX_TIME, Uuid::UUID_TYPE_CUSTOM => \true,
            default => \false,
        };
    }
}
<?php

/**
 * This file is part of the ramsey/uuid library
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @copyright Copyright (c) Ben Ramsey <ben@benramsey.com>
 * @license http://opensource.org/licenses/MIT MIT
 */
declare (strict_types=1);
namespace _ContaoManager\Ramsey\Uuid\Rfc4122;

/**
 * Provides common functionality for nil UUIDs
 *
 * @immutable
 */
trait NilTrait
{
    /**
     * Returns the bytes that comprise the fields
     *
     * @pure
     */
    abstract public function getBytes(): string;
    /**
     * Returns true if the byte string represents a nil UUID
     */
    public function isNil(): bool
    {
        return $this->getBytes() === "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00";
    }
}
<?php

/**
 * This file is part of the ramsey/uuid library
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @copyright Copyright (c) Ben Ramsey <ben@benramsey.com>
 * @license http://opensource.org/licenses/MIT MIT
 */
declare (strict_types=1);
namespace _ContaoManager\Ramsey\Uuid\Rfc4122;

use _ContaoManager\Ramsey\Uuid\Exception\InvalidArgumentException;
use _ContaoManager\Ramsey\Uuid\Fields\SerializableFieldsTrait;
use _ContaoManager\Ramsey\Uuid\Type\Hexadecimal;
use _ContaoManager\Ramsey\Uuid\Uuid;
use function bin2hex;
use function dechex;
use function hexdec;
use function sprintf;
use function str_pad;
use function strlen;
use function substr;
use function unpack;
use const STR_PAD_LEFT;
/**
 * RFC 9562 (formerly RFC 4122) variant UUIDs consist of a set of named fields
 *
 * Internally, this class represents the fields together as a 16-byte binary string.
 *
 * @immutable
 */
final class Fields implements FieldsInterface
{
    use MaxTrait;
    use NilTrait;
    use SerializableFieldsTrait;
    use VariantTrait;
    use VersionTrait;
    /**
     * @param string $bytes A 16-byte binary string representation of a UUID
     *
     * @throws InvalidArgumentException if the byte string is not exactly 16 bytes
     * @throws InvalidArgumentException if the byte string does not represent an RFC 9562 (formerly RFC 4122) UUID
     * @throws InvalidArgumentException if the byte string does not contain a valid version
     */
    public function __construct(private string $bytes)
    {
        if (strlen($this->bytes) !== 16) {
            throw new InvalidArgumentException('The byte string must be 16 bytes long; ' . 'received ' . strlen($this->bytes) . ' bytes');
        }
        if (!$this->isCorrectVariant()) {
            throw new InvalidArgumentException('The byte string received does not conform to the RFC 9562 (formerly RFC 4122) variant');
        }
        if (!$this->isCorrectVersion()) {
            throw new InvalidArgumentException('The byte string received does not contain a valid RFC 9562 (formerly RFC 4122) version');
        }
    }
    /**
     * @pure
     */
    public function getBytes(): string
    {
        return $this->bytes;
    }
    public function getClockSeq(): Hexadecimal
    {
        if ($this->isMax()) {
            $clockSeq = 0xffff;
        } elseif ($this->isNil()) {
            $clockSeq = 0x0;
        } else {
            $clockSeq = hexdec(bin2hex(substr($this->bytes, 8, 2))) & 0x3fff;
        }
        return new Hexadecimal(str_pad(dechex($clockSeq), 4, '0', STR_PAD_LEFT));
    }
    public function getClockSeqHiAndReserved(): Hexadecimal
    {
        return new Hexadecimal(bin2hex(substr($this->bytes, 8, 1)));
    }
    public function getClockSeqLow(): Hexadecimal
    {
        return new Hexadecimal(bin2hex(substr($this->bytes, 9, 1)));
    }
    public function getNode(): Hexadecimal
    {
        return new Hexadecimal(bin2hex(substr($this->bytes, 10)));
    }
    public function getTimeHiAndVersion(): Hexadecimal
    {
        return new Hexadecimal(bin2hex(substr($this->bytes, 6, 2)));
    }
    public function getTimeLow(): Hexadecimal
    {
        return new Hexadecimal(bin2hex(substr($this->bytes, 0, 4)));
    }
    public function getTimeMid(): Hexadecimal
    {
        return new Hexadecimal(bin2hex(substr($this->bytes, 4, 2)));
    }
    /**
     * Returns the full 60-bit timestamp, without the version
     *
     * For version 2 UUIDs, the time_low field is the local identifier and should not be returned as part of the time.
     * For this reason, we set the bottom 32 bits of the timestamp to 0's. As a result, there is some loss of timestamp
     * fidelity, for version 2 UUIDs. The timestamp can be off by a range of 0 to 429.4967295 seconds (or 7 minutes, 9
     * seconds, and 496,730 microseconds).
     *
     * For version 6 UUIDs, the timestamp order is reversed from the typical RFC 9562 (formerly RFC 4122) order (the
     * time bits are in the correct bit order, so that it is monotonically increasing). In returning the timestamp
     * value, we put the bits in the order: time_low + time_mid + time_hi.
     */
    public function getTimestamp(): Hexadecimal
    {
        return new Hexadecimal(match ($this->getVersion()) {
            Uuid::UUID_TYPE_DCE_SECURITY => sprintf('%03x%04s%08s', hexdec($this->getTimeHiAndVersion()->toString()) & 0xfff, $this->getTimeMid()->toString(), ''),
            Uuid::UUID_TYPE_REORDERED_TIME => sprintf('%08s%04s%03x', $this->getTimeLow()->toString(), $this->getTimeMid()->toString(), hexdec($this->getTimeHiAndVersion()->toString()) & 0xfff),
            // The Unix timestamp in version 7 UUIDs is a 48-bit number, but for consistency, we will return a 60-bit
            // number, padded to the left with zeros.
            Uuid::UUID_TYPE_UNIX_TIME => sprintf('%011s%04s', $this->getTimeLow()->toString(), $this->getTimeMid()->toString()),
            default => sprintf('%03x%04s%08s', hexdec($this->getTimeHiAndVersion()->toString()) & 0xfff, $this->getTimeMid()->toString(), $this->getTimeLow()->toString()),
        });
    }
    public function getVersion(): ?int
    {
        if ($this->isNil() || $this->isMax()) {
            return null;
        }
        /** @var int[] $parts */
        $parts = unpack('n*', $this->bytes);
        return $parts[4] >> 12;
    }
    private function isCorrectVariant(): bool
    {
        if ($this->isNil() || $this->isMax()) {
            return \true;
        }
        return $this->getVariant() === Uuid::RFC_4122;
    }
}
<?php

/**
 * This file is part of the ramsey/uuid library
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @copyright Copyright (c) Ben Ramsey <ben@benramsey.com>
 * @license http://opensource.org/licenses/MIT MIT
 */
declare (strict_types=1);
namespace _ContaoManager\Ramsey\Uuid\Rfc4122;

use _ContaoManager\Ramsey\Uuid\Uuid;
/**
 * The nil UUID is a special form of UUID that has all 128 bits set to zero (`0`)
 *
 * @link https://www.rfc-editor.org/rfc/rfc9562#section-5.9 RFC 9562, 5.9. Nil UUID
 *
 * @immutable
 */
final class NilUuid extends Uuid implements UuidInterface
{
}
<?php

/**
 * This file is part of the ramsey/uuid library
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @copyright Copyright (c) Ben Ramsey <ben@benramsey.com>
 * @license http://opensource.org/licenses/MIT MIT
 */
declare (strict_types=1);
namespace _ContaoManager\Ramsey\Uuid\Rfc4122;

use _ContaoManager\Ramsey\Uuid\Uuid;
/**
 * The max UUID is a special form of UUID that has all 128 bits set to one (`1`)
 *
 * @link https://www.rfc-editor.org/rfc/rfc9562#section-5.10 RFC 9562, 5.10. Max UUID
 *
 * @immutable
 */
final class MaxUuid extends Uuid implements UuidInterface
{
}
<?php

/**
 * This file is part of the ramsey/uuid library
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @copyright Copyright (c) Ben Ramsey <ben@benramsey.com>
 * @license http://opensource.org/licenses/MIT MIT
 */
declare (strict_types=1);
namespace _ContaoManager\Ramsey\Uuid\Rfc4122;

use _ContaoManager\Ramsey\Uuid\UuidInterface as BaseUuidInterface;
/**
 * A universally unique identifier (UUID), as defined in RFC 9562 (formerly RFC 4122)
 *
 * @link https://www.rfc-editor.org/rfc/rfc9562 RFC 9562
 *
 * @immutable
 */
interface UuidInterface extends BaseUuidInterface
{
}
<?php

/**
 * This file is part of the ramsey/uuid library
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @copyright Copyright (c) Ben Ramsey <ben@benramsey.com>
 * @license http://opensource.org/licenses/MIT MIT
 */
declare (strict_types=1);
namespace _ContaoManager\Ramsey\Uuid\Rfc4122;

use DateTimeImmutable;
use DateTimeInterface;
use _ContaoManager\Ramsey\Uuid\Exception\DateTimeException;
use Throwable;
use function str_pad;
use const STR_PAD_LEFT;
/**
 * Provides common functionality for getting the time from a time-based UUID
 *
 * @immutable
 */
trait TimeTrait
{
    /**
     * Returns a DateTimeInterface object representing the timestamp associated with the UUID
     *
     * @return DateTimeImmutable A PHP DateTimeImmutable instance representing the timestamp of a time-based UUID
     */
    public function getDateTime(): DateTimeInterface
    {
        $time = $this->timeConverter->convertTime($this->fields->getTimestamp());
        try {
            return new DateTimeImmutable('@' . $time->getSeconds()->toString() . '.' . str_pad($time->getMicroseconds()->toString(), 6, '0', STR_PAD_LEFT));
        } catch (Throwable $e) {
            throw new DateTimeException($e->getMessage(), (int) $e->getCode(), $e);
        }
    }
}
<?php

/**
 * This file is part of the ramsey/uuid library
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @copyright Copyright (c) Ben Ramsey <ben@benramsey.com>
 * @license http://opensource.org/licenses/MIT MIT
 */
declare (strict_types=1);
namespace _ContaoManager\Ramsey\Uuid\Rfc4122;

use _ContaoManager\Ramsey\Uuid\Exception\InvalidBytesException;
use _ContaoManager\Ramsey\Uuid\Uuid;
use function decbin;
use function str_pad;
use function str_starts_with;
use function strlen;
use function substr;
use function unpack;
use const STR_PAD_LEFT;
/**
 * Provides common functionality for handling the variant, as defined by RFC 9562 (formerly RFC 4122)
 *
 * @immutable
 */
trait VariantTrait
{
    /**
     * Returns the bytes that comprise the fields
     */
    abstract public function getBytes(): string;
    /**
     * Returns the variant
     *
     * The variant number describes the layout of the UUID. The variant number has the following meaning:
     *
     * - 0 - Reserved for NCS backward compatibility
     * - 2 - The RFC 9562 (formerly RFC 4122) variant
     * - 6 - Reserved, Microsoft Corporation backward compatibility
     * - 7 - Reserved for future definition
     *
     * For RFC 9562 (formerly RFC 4122) variant UUIDs, this value should always be the integer `2`.
     *
     * @link https://www.rfc-editor.org/rfc/rfc9562#section-4.1 RFC 9562, 4.1. Variant Field
     */
    public function getVariant(): int
    {
        if (strlen($this->getBytes()) !== 16) {
            throw new InvalidBytesException('Invalid number of bytes');
        }
        // According to RFC 9562, sections {@link https://www.rfc-editor.org/rfc/rfc9562#section-4.1 4.1} and
        // {@link https://www.rfc-editor.org/rfc/rfc9562#section-5.10 5.10}, the Max UUID falls within the range
        // of the future variant.
        if ($this->isMax()) {
            return Uuid::RESERVED_FUTURE;
        }
        // According to RFC 9562, sections {@link https://www.rfc-editor.org/rfc/rfc9562#section-4.1 4.1} and
        // {@link https://www.rfc-editor.org/rfc/rfc9562#section-5.9 5.9}, the Nil UUID falls within the range
        // of the Apollo NCS variant.
        if ($this->isNil()) {
            return Uuid::RESERVED_NCS;
        }
        /** @var int[] $parts */
        $parts = unpack('n*', $this->getBytes());
        // $parts[5] is a 16-bit, unsigned integer containing the variant bits of the UUID. We convert this integer into
        // a string containing a binary representation, padded to 16 characters. We analyze the first three characters
        // (three most-significant bits) to determine the variant.
        $msb = substr(str_pad(decbin($parts[5]), 16, '0', STR_PAD_LEFT), 0, 3);
        if ($msb === '111') {
            return Uuid::RESERVED_FUTURE;
        } elseif ($msb === '110') {
            return Uuid::RESERVED_MICROSOFT;
        } elseif (str_starts_with($msb, '10')) {
            return Uuid::RFC_4122;
        }
        return Uuid::RESERVED_NCS;
    }
}
<?php

/**
 * This file is part of the ramsey/uuid library
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @copyright Copyright (c) Ben Ramsey <ben@benramsey.com>
 * @license http://opensource.org/licenses/MIT MIT
 */
declare (strict_types=1);
namespace _ContaoManager\Ramsey\Uuid\Rfc4122;

use _ContaoManager\Ramsey\Uuid\Builder\UuidBuilderInterface;
use _ContaoManager\Ramsey\Uuid\Codec\CodecInterface;
use _ContaoManager\Ramsey\Uuid\Converter\NumberConverterInterface;
use _ContaoManager\Ramsey\Uuid\Converter\Time\UnixTimeConverter;
use _ContaoManager\Ramsey\Uuid\Converter\TimeConverterInterface;
use _ContaoManager\Ramsey\Uuid\Exception\UnableToBuildUuidException;
use _ContaoManager\Ramsey\Uuid\Exception\UnsupportedOperationException;
use _ContaoManager\Ramsey\Uuid\Math\BrickMathCalculator;
use _ContaoManager\Ramsey\Uuid\Rfc4122\UuidInterface as Rfc4122UuidInterface;
use _ContaoManager\Ramsey\Uuid\Uuid;
use _ContaoManager\Ramsey\Uuid\UuidInterface;
use Throwable;
/**
 * UuidBuilder builds instances of RFC 9562 (formerly 4122) UUIDs
 *
 * @immutable
 */
class UuidBuilder implements UuidBuilderInterface
{
    private TimeConverterInterface $unixTimeConverter;
    /**
     * Constructs the DefaultUuidBuilder
     *
     * @param NumberConverterInterface $numberConverter The number converter to use when constructing the Uuid
     * @param TimeConverterInterface $timeConverter The time converter to use for converting Gregorian time extracted
     *     from version 1, 2, and 6 UUIDs to Unix timestamps
     * @param TimeConverterInterface | null $unixTimeConverter The time converter to use for converter Unix Epoch time
     *     extracted from version 7 UUIDs to Unix timestamps
     */
    public function __construct(private NumberConverterInterface $numberConverter, private TimeConverterInterface $timeConverter, ?TimeConverterInterface $unixTimeConverter = null)
    {
        $this->unixTimeConverter = $unixTimeConverter ?? new UnixTimeConverter(new BrickMathCalculator());
    }
    /**
     * Builds and returns a Uuid
     *
     * @param CodecInterface $codec The codec to use for building this Uuid instance
     * @param string $bytes The byte string from which to construct a UUID
     *
     * @return Rfc4122UuidInterface UuidBuilder returns instances of Rfc4122UuidInterface
     *
     * @pure
     */
    public function build(CodecInterface $codec, string $bytes): UuidInterface
    {
        try {
            /** @var Fields $fields */
            $fields = $this->buildFields($bytes);
            if ($fields->isNil()) {
                /** @phpstan-ignore possiblyImpure.new */
                return new NilUuid($fields, $this->numberConverter, $codec, $this->timeConverter);
            }
            if ($fields->isMax()) {
                /** @phpstan-ignore possiblyImpure.new */
                return new MaxUuid($fields, $this->numberConverter, $codec, $this->timeConverter);
            }
            return match ($fields->getVersion()) {
                /** @phpstan-ignore possiblyImpure.new */
                Uuid::UUID_TYPE_TIME => new UuidV1($fields, $this->numberConverter, $codec, $this->timeConverter),
                Uuid::UUID_TYPE_DCE_SECURITY => new UuidV2($fields, $this->numberConverter, $codec, $this->timeConverter),
                /** @phpstan-ignore possiblyImpure.new */
                Uuid::UUID_TYPE_HASH_MD5 => new UuidV3($fields, $this->numberConverter, $codec, $this->timeConverter),
                /** @phpstan-ignore possiblyImpure.new */
                Uuid::UUID_TYPE_RANDOM => new UuidV4($fields, $this->numberConverter, $codec, $this->timeConverter),
                /** @phpstan-ignore possiblyImpure.new */
                Uuid::UUID_TYPE_HASH_SHA1 => new UuidV5($fields, $this->numberConverter, $codec, $this->timeConverter),
                Uuid::UUID_TYPE_REORDERED_TIME => new UuidV6($fields, $this->numberConverter, $codec, $this->timeConverter),
                Uuid::UUID_TYPE_UNIX_TIME => new UuidV7($fields, $this->numberConverter, $codec, $this->unixTimeConverter),
                /** @phpstan-ignore possiblyImpure.new */
                Uuid::UUID_TYPE_CUSTOM => new UuidV8($fields, $this->numberConverter, $codec, $this->timeConverter),
                default => throw new UnsupportedOperationException('The UUID version in the given fields is not supported by this UUID builder'),
            };
        } catch (Throwable $e) {
            /** @phpstan-ignore possiblyImpure.methodCall, possiblyImpure.methodCall */
            throw new UnableToBuildUuidException($e->getMessage(), (int) $e->getCode(), $e);
        }
    }
    /**
     * Proxy method to allow injecting a mock for testing
     *
     * @pure
     */
    protected function buildFields(string $bytes): FieldsInterface
    {
        /** @phpstan-ignore possiblyImpure.new */
        return new Fields($bytes);
    }
}
<?php

/**
 * This file is part of the ramsey/uuid library
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @copyright Copyright (c) Ben Ramsey <ben@benramsey.com>
 * @license http://opensource.org/licenses/MIT MIT
 */
declare (strict_types=1);
namespace _ContaoManager\Ramsey\Uuid\Rfc4122;

use _ContaoManager\Ramsey\Uuid\Codec\CodecInterface;
use _ContaoManager\Ramsey\Uuid\Converter\NumberConverterInterface;
use _ContaoManager\Ramsey\Uuid\Converter\TimeConverterInterface;
use _ContaoManager\Ramsey\Uuid\Exception\InvalidArgumentException;
use _ContaoManager\Ramsey\Uuid\Rfc4122\FieldsInterface as Rfc4122FieldsInterface;
use _ContaoManager\Ramsey\Uuid\Uuid;
/**
 * Gregorian time, or version 1, UUIDs include timestamp, clock sequence, and node values, combined into a 128-bit unsigned integer
 *
 * @link https://www.rfc-editor.org/rfc/rfc9562#section-5.1 RFC 9562, 5.1. UUID Version 1
 *
 * @immutable
 */
final class UuidV1 extends Uuid implements UuidInterface
{
    use TimeTrait;
    /**
     * Creates a version 1 (Gregorian time) UUID
     *
     * @param Rfc4122FieldsInterface $fields The fields from which to construct a UUID
     * @param NumberConverterInterface $numberConverter The number converter to use for converting hex values to/from integers
     * @param CodecInterface $codec The codec to use when encoding or decoding UUID strings
     * @param TimeConverterInterface $timeConverter The time converter to use for converting timestamps extracted from a
     *     UUID to unix timestamps
     */
    public function __construct(Rfc4122FieldsInterface $fields, NumberConverterInterface $numberConverter, CodecInterface $codec, TimeConverterInterface $timeConverter)
    {
        if ($fields->getVersion() !== Uuid::UUID_TYPE_TIME) {
            throw new InvalidArgumentException('Fields used to create a UuidV1 must represent a version 1 (time-based) UUID');
        }
        parent::__construct($fields, $numberConverter, $codec, $timeConverter);
    }
}
<?php

/**
 * This file is part of the ramsey/uuid library
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @copyright Copyright (c) Ben Ramsey <ben@benramsey.com>
 * @license http://opensource.org/licenses/MIT MIT
 */
declare (strict_types=1);
namespace _ContaoManager\Ramsey\Uuid\Rfc4122;

use _ContaoManager\Ramsey\Uuid\Codec\CodecInterface;
use _ContaoManager\Ramsey\Uuid\Converter\NumberConverterInterface;
use _ContaoManager\Ramsey\Uuid\Converter\TimeConverterInterface;
use _ContaoManager\Ramsey\Uuid\Exception\InvalidArgumentException;
use _ContaoManager\Ramsey\Uuid\Rfc4122\FieldsInterface as Rfc4122FieldsInterface;
use _ContaoManager\Ramsey\Uuid\Uuid;
/**
 * Version 3 UUIDs are named-based, using a combination of a namespace and name that are hashed into a 128-bit unsigned
 * integer using the MD5 hashing algorithm
 *
 * @link https://www.rfc-editor.org/rfc/rfc9562#section-5.3 RFC 9562, 5.3. UUID Version 3
 *
 * @immutable
 */
final class UuidV3 extends Uuid implements UuidInterface
{
    /**
     * Creates a version 3 (name-based, MD5-hashed) UUID
     *
     * @param Rfc4122FieldsInterface $fields The fields from which to construct a UUID
     * @param NumberConverterInterface $numberConverter The number converter to use for converting hex values to/from integers
     * @param CodecInterface $codec The codec to use when encoding or decoding UUID strings
     * @param TimeConverterInterface $timeConverter The time converter to use for converting timestamps extracted from a
     *     UUID to unix timestamps
     */
    public function __construct(Rfc4122FieldsInterface $fields, NumberConverterInterface $numberConverter, CodecInterface $codec, TimeConverterInterface $timeConverter)
    {
        if ($fields->getVersion() !== Uuid::UUID_TYPE_HASH_MD5) {
            throw new InvalidArgumentException('Fields used to create a UuidV3 must represent a version 3 (name-based, MD5-hashed) UUID');
        }
        parent::__construct($fields, $numberConverter, $codec, $timeConverter);
    }
}
<?php

/**
 * This file is part of the ramsey/uuid library
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @copyright Copyright (c) Ben Ramsey <ben@benramsey.com>
 * @license http://opensource.org/licenses/MIT MIT
 */
declare (strict_types=1);
namespace _ContaoManager\Ramsey\Uuid\Rfc4122;

use _ContaoManager\Ramsey\Uuid\Codec\CodecInterface;
use _ContaoManager\Ramsey\Uuid\Converter\NumberConverterInterface;
use _ContaoManager\Ramsey\Uuid\Converter\TimeConverterInterface;
use _ContaoManager\Ramsey\Uuid\Exception\InvalidArgumentException;
use _ContaoManager\Ramsey\Uuid\Rfc4122\FieldsInterface as Rfc4122FieldsInterface;
use _ContaoManager\Ramsey\Uuid\Type\Integer as IntegerObject;
use _ContaoManager\Ramsey\Uuid\Uuid;
use function hexdec;
/**
 * DCE Security version, or version 2, UUIDs include local domain identifier, local ID for the specified domain, and
 * node values that are combined into a 128-bit unsigned integer
 *
 * It is important to note that a version 2 UUID suffers from some loss of timestamp fidelity, due to replacing the
 * time_low field with the local identifier. When constructing the timestamp value for date purposes, we replace the
 * local identifier bits with zeros. As a result, the timestamp can be off by a range of 0 to 429.4967295 seconds (or 7
 * minutes, 9 seconds, and 496,730 microseconds).
 *
 * Astute observers might note this value directly corresponds to `2^32-1`, or `0xffffffff`. The local identifier is
 * 32-bits, and we have set each of these bits to `0`, so the maximum range of timestamp drift is `0x00000000` to
 * `0xffffffff` (counted in 100-nanosecond intervals).
 *
 * @link https://www.rfc-editor.org/rfc/rfc9562#section-5.2 RFC 9562, 5.2. UUID Version 2
 * @link https://publications.opengroup.org/c311 DCE 1.1: Authentication and Security Services
 * @link https://publications.opengroup.org/c706 DCE 1.1: Remote Procedure Call
 * @link https://pubs.opengroup.org/onlinepubs/9696989899/chap5.htm#tagcjh_08_02_01_01 DCE 1.1: Auth & Sec, §5.2.1.1
 * @link https://pubs.opengroup.org/onlinepubs/9696989899/chap11.htm#tagcjh_14_05_01_01 DCE 1.1: Auth & Sec, §11.5.1.1
 * @link https://pubs.opengroup.org/onlinepubs/9629399/apdxa.htm DCE 1.1: RPC, Appendix A
 * @link https://github.com/google/uuid Go package for UUIDs (includes DCE implementation)
 *
 * @immutable
 */
final class UuidV2 extends Uuid implements UuidInterface
{
    use TimeTrait;
    /**
     * Creates a version 2 (DCE Security) UUID
     *
     * @param Rfc4122FieldsInterface $fields The fields from which to construct a UUID
     * @param NumberConverterInterface $numberConverter The number converter to use for converting hex values to/from integers
     * @param CodecInterface $codec The codec to use when encoding or decoding UUID strings
     * @param TimeConverterInterface $timeConverter The time converter to use for converting timestamps extracted from a
     *     UUID to unix timestamps
     */
    public function __construct(Rfc4122FieldsInterface $fields, NumberConverterInterface $numberConverter, CodecInterface $codec, TimeConverterInterface $timeConverter)
    {
        if ($fields->getVersion() !== Uuid::UUID_TYPE_DCE_SECURITY) {
            throw new InvalidArgumentException('Fields used to create a UuidV2 must represent a version 2 (DCE Security) UUID');
        }
        parent::__construct($fields, $numberConverter, $codec, $timeConverter);
    }
    /**
     * Returns the local domain used to create this version 2 UUID
     */
    public function getLocalDomain(): int
    {
        /** @var Rfc4122FieldsInterface $fields */
        $fields = $this->getFields();
        return (int) hexdec($fields->getClockSeqLow()->toString());
    }
    /**
     * Returns the string name of the local domain
     */
    public function getLocalDomainName(): string
    {
        return Uuid::DCE_DOMAIN_NAMES[$this->getLocalDomain()];
    }
    /**
     * Returns the local identifier for the domain used to create this version 2 UUID
     */
    public function getLocalIdentifier(): IntegerObject
    {
        /** @var Rfc4122FieldsInterface $fields */
        $fields = $this->getFields();
        return new IntegerObject($this->numberConverter->fromHex($fields->getTimeLow()->toString()));
    }
}
<?php

/**
 * This file is part of the ramsey/uuid library
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @copyright Copyright (c) Ben Ramsey <ben@benramsey.com>
 * @license http://opensource.org/licenses/MIT MIT
 */
declare (strict_types=1);
namespace _ContaoManager\Ramsey\Uuid\Rfc4122;

use _ContaoManager\Ramsey\Uuid\Nonstandard\UuidV6 as NonstandardUuidV6;
/**
 * Reordered Gregorian time, or version 6, UUIDs include timestamp, clock sequence, and node values that are combined
 * into a 128-bit unsigned integer
 *
 * @link https://www.rfc-editor.org/rfc/rfc9562#section-5.6 RFC 9562, 5.6. UUID Version 6
 *
 * @immutable
 */
final class UuidV6 extends NonstandardUuidV6 implements UuidInterface
{
}
<?php

/**
 * This file is part of the ramsey/uuid library
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @copyright Copyright (c) Ben Ramsey <ben@benramsey.com>
 * @license http://opensource.org/licenses/MIT MIT
 */
declare (strict_types=1);
namespace _ContaoManager\Ramsey\Uuid\Rfc4122;

use _ContaoManager\Ramsey\Uuid\Codec\CodecInterface;
use _ContaoManager\Ramsey\Uuid\Converter\NumberConverterInterface;
use _ContaoManager\Ramsey\Uuid\Converter\TimeConverterInterface;
use _ContaoManager\Ramsey\Uuid\Exception\InvalidArgumentException;
use _ContaoManager\Ramsey\Uuid\Rfc4122\FieldsInterface as Rfc4122FieldsInterface;
use _ContaoManager\Ramsey\Uuid\Uuid;
/**
 * Unix Epoch time, or version 7, UUIDs include a timestamp in milliseconds since the Unix Epoch, along with random bytes
 *
 * @link https://www.rfc-editor.org/rfc/rfc9562#section-5.7 RFC 9562, 5.7. UUID Version 7
 *
 * @immutable
 */
final class UuidV7 extends Uuid implements UuidInterface
{
    use TimeTrait;
    /**
     * Creates a version 7 (Unix Epoch time) UUID
     *
     * @param Rfc4122FieldsInterface $fields The fields from which to construct a UUID
     * @param NumberConverterInterface $numberConverter The number converter to use for converting hex values to/from integers
     * @param CodecInterface $codec The codec to use when encoding or decoding UUID strings
     * @param TimeConverterInterface $timeConverter The time converter to use for converting timestamps extracted from a
     *     UUID to unix timestamps
     */
    public function __construct(Rfc4122FieldsInterface $fields, NumberConverterInterface $numberConverter, CodecInterface $codec, TimeConverterInterface $timeConverter)
    {
        if ($fields->getVersion() !== Uuid::UUID_TYPE_UNIX_TIME) {
            throw new InvalidArgumentException('Fields used to create a UuidV7 must represent a version 7 (Unix Epoch time) UUID');
        }
        parent::__construct($fields, $numberConverter, $codec, $timeConverter);
    }
}
<?php

/**
 * This file is part of the ramsey/uuid library
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @copyright Copyright (c) Ben Ramsey <ben@benramsey.com>
 * @license http://opensource.org/licenses/MIT MIT
 */
declare (strict_types=1);
namespace _ContaoManager\Ramsey\Uuid\Rfc4122;

use _ContaoManager\Ramsey\Uuid\Codec\CodecInterface;
use _ContaoManager\Ramsey\Uuid\Converter\NumberConverterInterface;
use _ContaoManager\Ramsey\Uuid\Converter\TimeConverterInterface;
use _ContaoManager\Ramsey\Uuid\Exception\InvalidArgumentException;
use _ContaoManager\Ramsey\Uuid\Rfc4122\FieldsInterface as Rfc4122FieldsInterface;
use _ContaoManager\Ramsey\Uuid\Uuid;
/**
 * Version 5 UUIDs are named-based, using a combination of a namespace and name that are hashed into a 128-bit unsigned
 * integer using the SHA1 hashing algorithm
 *
 * @link https://www.rfc-editor.org/rfc/rfc9562#section-5.5 RFC 9562, 5.5. UUID Version 5
 *
 * @immutable
 */
final class UuidV5 extends Uuid implements UuidInterface
{
    /**
     * Creates a version 5 (name-based, SHA1-hashed) UUID
     *
     * @param Rfc4122FieldsInterface $fields The fields from which to construct a UUID
     * @param NumberConverterInterface $numberConverter The number converter to use for converting hex values to/from integers
     * @param CodecInterface $codec The codec to use when encoding or decoding UUID strings
     * @param TimeConverterInterface $timeConverter The time converter to use for converting timestamps extracted from a
     *     UUID to unix timestamps
     */
    public function __construct(Rfc4122FieldsInterface $fields, NumberConverterInterface $numberConverter, CodecInterface $codec, TimeConverterInterface $timeConverter)
    {
        if ($fields->getVersion() !== Uuid::UUID_TYPE_HASH_SHA1) {
            throw new InvalidArgumentException('Fields used to create a UuidV5 must represent a version 5 (named-based, SHA1-hashed) UUID');
        }
        parent::__construct($fields, $numberConverter, $codec, $timeConverter);
    }
}
<?php

/**
 * This file is part of the ramsey/uuid library
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @copyright Copyright (c) Ben Ramsey <ben@benramsey.com>
 * @license http://opensource.org/licenses/MIT MIT
 */
declare (strict_types=1);
namespace _ContaoManager\Ramsey\Uuid\Rfc4122;

use _ContaoManager\Ramsey\Uuid\Codec\CodecInterface;
use _ContaoManager\Ramsey\Uuid\Converter\NumberConverterInterface;
use _ContaoManager\Ramsey\Uuid\Converter\TimeConverterInterface;
use _ContaoManager\Ramsey\Uuid\Exception\InvalidArgumentException;
use _ContaoManager\Ramsey\Uuid\Rfc4122\FieldsInterface as Rfc4122FieldsInterface;
use _ContaoManager\Ramsey\Uuid\Uuid;
/**
 * Random, or version 4, UUIDs are randomly or pseudo-randomly generated 128-bit integers
 *
 * @link https://www.rfc-editor.org/rfc/rfc9562#section-5.4 RFC 9562, 5.4. UUID Version 4
 *
 * @immutable
 */
final class UuidV4 extends Uuid implements UuidInterface
{
    /**
     * Creates a version 4 (random) UUID
     *
     * @param Rfc4122FieldsInterface $fields The fields from which to construct a UUID
     * @param NumberConverterInterface $numberConverter The number converter to use for converting hex values to/from integers
     * @param CodecInterface $codec The codec to use when encoding or decoding UUID strings
     * @param TimeConverterInterface $timeConverter The time converter to use for converting timestamps extracted from a
     *     UUID to unix timestamps
     */
    public function __construct(Rfc4122FieldsInterface $fields, NumberConverterInterface $numberConverter, CodecInterface $codec, TimeConverterInterface $timeConverter)
    {
        if ($fields->getVersion() !== Uuid::UUID_TYPE_RANDOM) {
            throw new InvalidArgumentException('Fields used to create a UuidV4 must represent a version 4 (random) UUID');
        }
        parent::__construct($fields, $numberConverter, $codec, $timeConverter);
    }
}
<?php

/**
 * This file is part of the ramsey/uuid library
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @copyright Copyright (c) Ben Ramsey <ben@benramsey.com>
 * @license http://opensource.org/licenses/MIT MIT
 */
declare (strict_types=1);
namespace _ContaoManager\Ramsey\Uuid;

use JsonSerializable;
use _ContaoManager\Ramsey\Uuid\Fields\FieldsInterface;
use _ContaoManager\Ramsey\Uuid\Type\Hexadecimal;
use _ContaoManager\Ramsey\Uuid\Type\Integer as IntegerObject;
use Serializable;
use Stringable;
/**
 * A UUID is a universally unique identifier adhering to an agreed-upon representation format and standard for generation
 *
 * @immutable
 */
interface UuidInterface extends DeprecatedUuidInterface, JsonSerializable, Serializable, Stringable
{
    /**
     * Returns -1, 0, or 1 if the UUID is less than, equal to, or greater than the other UUID
     *
     * The first of two UUIDs is greater than the second if the most significant field in which the UUIDs differ is
     * greater for the first UUID.
     *
     * @param UuidInterface $other The UUID to compare
     *
     * @return int<-1,1> -1, 0, or 1 if the UUID is less than, equal to, or greater than $other
     */
    public function compareTo(UuidInterface $other): int;
    /**
     * Returns true if the UUID is equal to the provided object
     *
     * The result is true if and only if the argument is not null, is a UUID object, has the same variant, and contains
     * the same value, bit-for-bit, as the UUID.
     *
     * @param object | null $other An object to test for equality with this UUID
     *
     * @return bool True if the other object is equal to this UUID
     */
    public function equals(?object $other): bool;
    /**
     * Returns the binary string representation of the UUID
     *
     * @return non-empty-string
     *
     * @pure
     */
    public function getBytes(): string;
    /**
     * Returns the fields that comprise this UUID
     */
    public function getFields(): FieldsInterface;
    /**
     * Returns the hexadecimal representation of the UUID
     */
    public function getHex(): Hexadecimal;
    /**
     * Returns the integer representation of the UUID
     */
    public function getInteger(): IntegerObject;
    /**
     * Returns the string standard representation of the UUID as a URN
     *
     * @link http://en.wikipedia.org/wiki/Uniform_Resource_Name Uniform Resource Name
     * @link https://www.rfc-editor.org/rfc/rfc9562.html#section-4 RFC 9562, 4. UUID Format
     * @link https://www.rfc-editor.org/rfc/rfc9562.html#section-7 RFC 9562, 7. IANA Considerations
     * @link https://www.rfc-editor.org/rfc/rfc4122.html#section-3 RFC 4122, 3. Namespace Registration Template
     */
    public function getUrn(): string;
    /**
     * Returns the string standard representation of the UUID
     *
     * @return non-empty-string
     *
     * @pure
     */
    public function toString(): string;
    /**
     * Casts the UUID to the string standard representation
     *
     * @return non-empty-string
     *
     * @pure
     */
    public function __toString(): string;
}
<?php

/**
 * This file was originally part of brick/math
 *
 * Copyright (c) 2013-present Benjamin Morel
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 *
 * @link https://github.com/brick/math brick/math at GitHub
 */
declare (strict_types=1);
namespace _ContaoManager\Ramsey\Uuid\Math;

/**
 * Specifies a rounding behavior for numerical operations capable of discarding precision.
 *
 * Each rounding mode indicates how the least significant returned digit of a rounded result is to be calculated. If
 * fewer digits are returned than the digits needed to represent the exact numerical result, the discarded digits will
 * be referred to as the discarded fraction regardless of the digits' contribution to the value of the number. In other
 * words, considered as a numerical value, the discarded fraction could have an absolute value greater than one.
 */
final class RoundingMode
{
    /**
     * Asserts that the requested operation has an exact result; hence no rounding is necessary.
     */
    public const UNNECESSARY = 0;
    /**
     * Rounds away from zero.
     *
     * Always increments the digit prior to a nonzero discarded fraction. Note that this rounding mode never decreases
     * the magnitude of the calculated value.
     */
    public const UP = 1;
    /**
     * Rounds towards zero.
     *
     * Never increments the digit prior to a discarded fraction (i.e., truncates). Note that this rounding mode never
     * increases the magnitude of the calculated value.
     */
    public const DOWN = 2;
    /**
     * Rounds towards positive infinity.
     *
     * If the result is positive, behaves as for UP; if negative, behaves as for DOWN. Note that this rounding mode
     * never decreases the calculated value.
     */
    public const CEILING = 3;
    /**
     * Rounds towards negative infinity.
     *
     * If the result is positive, behave as for DOWN; if negative, behave as for UP. Note that this rounding mode never
     * increases the calculated value.
     */
    public const FLOOR = 4;
    /**
     * Rounds towards "nearest neighbor" unless both neighbors are equidistant, in which case round up.
     *
     * Behaves as for UP if the discarded fraction is >= 0.5; otherwise, behaves as for DOWN. Note that this is the
     * rounding mode commonly taught at school.
     */
    public const HALF_UP = 5;
    /**
     * Rounds towards "nearest neighbor" unless both neighbors are equidistant, in which case round down.
     *
     * Behaves as for UP if the discarded fraction is > 0.5; otherwise, behaves as for DOWN.
     */
    public const HALF_DOWN = 6;
    /**
     * Rounds towards "nearest neighbor" unless both neighbors are equidistant, in which case round towards positive infinity.
     *
     * If the result is positive, behaves as for HALF_UP; if negative, behaves as for HALF_DOWN.
     */
    public const HALF_CEILING = 7;
    /**
     * Rounds towards "nearest neighbor" unless both neighbors are equidistant, in which case round towards negative infinity.
     *
     * If the result is positive, behaves as for HALF_DOWN; if negative, behaves as for HALF_UP.
     */
    public const HALF_FLOOR = 8;
    /**
     * Rounds towards the "nearest neighbor" unless both neighbors are equidistant, in which case rounds towards the even neighbor.
     *
     * Behaves as for HALF_UP if the digit to the left of the discarded fraction is odd; behaves as for HALF_DOWN if it's even.
     *
     * Note that this is the rounding mode that statistically minimizes cumulative error when applied repeatedly over a
     * sequence of calculations. It is sometimes known as "Banker's rounding", and is chiefly used in the USA.
     */
    public const HALF_EVEN = 9;
    /**
     * Private constructor. This class is not instantiable.
     *
     * @codeCoverageIgnore
     */
    private function __construct()
    {
    }
}
<?php

/**
 * This file is part of the ramsey/uuid library
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @copyright Copyright (c) Ben Ramsey <ben@benramsey.com>
 * @license http://opensource.org/licenses/MIT MIT
 */
declare (strict_types=1);
namespace _ContaoManager\Ramsey\Uuid\Math;

use _ContaoManager\Ramsey\Uuid\Type\Hexadecimal;
use _ContaoManager\Ramsey\Uuid\Type\Integer as IntegerObject;
use _ContaoManager\Ramsey\Uuid\Type\NumberInterface;
/**
 * A calculator performs arithmetic operations on numbers
 *
 * @immutable
 */
interface CalculatorInterface
{
    /**
     * Returns the sum of all the provided parameters
     *
     * @param NumberInterface $augend The first addend (the integer being added to)
     * @param NumberInterface ...$addends The additional integers to a add to the augend
     *
     * @return NumberInterface The sum of all the parameters
     *
     * @pure
     */
    public function add(NumberInterface $augend, NumberInterface ...$addends): NumberInterface;
    /**
     * Returns the difference of all the provided parameters
     *
     * @param NumberInterface $minuend The integer being subtracted from
     * @param NumberInterface ...$subtrahends The integers to subtract from the minuend
     *
     * @return NumberInterface The difference after subtracting all parameters
     *
     * @pure
     */
    public function subtract(NumberInterface $minuend, NumberInterface ...$subtrahends): NumberInterface;
    /**
     * Returns the product of all the provided parameters
     *
     * @param NumberInterface $multiplicand The integer to be multiplied
     * @param NumberInterface ...$multipliers The factors by which to multiply the multiplicand
     *
     * @return NumberInterface The product of multiplying all the provided parameters
     *
     * @pure
     */
    public function multiply(NumberInterface $multiplicand, NumberInterface ...$multipliers): NumberInterface;
    /**
     * Returns the quotient of the provided parameters divided left-to-right
     *
     * @param int $roundingMode The RoundingMode constant to use for this operation
     * @param int $scale The scale to use for this operation
     * @param NumberInterface $dividend The integer to be divided
     * @param NumberInterface ...$divisors The integers to divide $dividend by, in the order in which the division
     *     operations should take place (left-to-right)
     *
     * @return NumberInterface The quotient of dividing the provided parameters left-to-right
     *
     * @pure
     */
    public function divide(int $roundingMode, int $scale, NumberInterface $dividend, NumberInterface ...$divisors): NumberInterface;
    /**
     * Converts a value from an arbitrary base to a base-10 integer value
     *
     * @param string $value The value to convert
     * @param int $base The base to convert from (i.e., 2, 16, 32, etc.)
     *
     * @return IntegerObject The base-10 integer value of the converted value
     *
     * @pure
     */
    public function fromBase(string $value, int $base): IntegerObject;
    /**
     * Converts a base-10 integer value to an arbitrary base
     *
     * @param IntegerObject $value The integer value to convert
     * @param int $base The base to convert to (i.e., 2, 16, 32, etc.)
     *
     * @return string The value represented in the specified base
     *
     * @pure
     */
    public function toBase(IntegerObject $value, int $base): string;
    /**
     * Converts an Integer instance to a Hexadecimal instance
     *
     * @pure
     */
    public function toHexadecimal(IntegerObject $value): Hexadecimal;
    /**
     * Converts a Hexadecimal instance to an Integer instance
     *
     * @pure
     */
    public function toInteger(Hexadecimal $value): IntegerObject;
}
<?php

/**
 * This file is part of the ramsey/uuid library
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @copyright Copyright (c) Ben Ramsey <ben@benramsey.com>
 * @license http://opensource.org/licenses/MIT MIT
 */
declare (strict_types=1);
namespace _ContaoManager\Ramsey\Uuid\Math;

use _ContaoManager\Brick\Math\BigDecimal;
use _ContaoManager\Brick\Math\BigInteger;
use _ContaoManager\Brick\Math\Exception\MathException;
use _ContaoManager\Brick\Math\RoundingMode as BrickMathRounding;
use _ContaoManager\Ramsey\Uuid\Exception\InvalidArgumentException;
use _ContaoManager\Ramsey\Uuid\Type\Decimal;
use _ContaoManager\Ramsey\Uuid\Type\Hexadecimal;
use _ContaoManager\Ramsey\Uuid\Type\Integer as IntegerObject;
use _ContaoManager\Ramsey\Uuid\Type\NumberInterface;
/**
 * A calculator using the brick/math library for arbitrary-precision arithmetic
 *
 * @immutable
 */
final class BrickMathCalculator implements CalculatorInterface
{
    private const ROUNDING_MODE_MAP = [RoundingMode::UNNECESSARY => BrickMathRounding::UNNECESSARY, RoundingMode::UP => BrickMathRounding::UP, RoundingMode::DOWN => BrickMathRounding::DOWN, RoundingMode::CEILING => BrickMathRounding::CEILING, RoundingMode::FLOOR => BrickMathRounding::FLOOR, RoundingMode::HALF_UP => BrickMathRounding::HALF_UP, RoundingMode::HALF_DOWN => BrickMathRounding::HALF_DOWN, RoundingMode::HALF_CEILING => BrickMathRounding::HALF_CEILING, RoundingMode::HALF_FLOOR => BrickMathRounding::HALF_FLOOR, RoundingMode::HALF_EVEN => BrickMathRounding::HALF_EVEN];
    public function add(NumberInterface $augend, NumberInterface ...$addends): NumberInterface
    {
        $sum = BigInteger::of($augend->toString());
        foreach ($addends as $addend) {
            $sum = $sum->plus($addend->toString());
        }
        /** @phpstan-ignore possiblyImpure.new */
        return new IntegerObject((string) $sum);
    }
    public function subtract(NumberInterface $minuend, NumberInterface ...$subtrahends): NumberInterface
    {
        $difference = BigInteger::of($minuend->toString());
        foreach ($subtrahends as $subtrahend) {
            $difference = $difference->minus($subtrahend->toString());
        }
        /** @phpstan-ignore possiblyImpure.new */
        return new IntegerObject((string) $difference);
    }
    public function multiply(NumberInterface $multiplicand, NumberInterface ...$multipliers): NumberInterface
    {
        $product = BigInteger::of($multiplicand->toString());
        foreach ($multipliers as $multiplier) {
            $product = $product->multipliedBy($multiplier->toString());
        }
        /** @phpstan-ignore possiblyImpure.new */
        return new IntegerObject((string) $product);
    }
    public function divide(int $roundingMode, int $scale, NumberInterface $dividend, NumberInterface ...$divisors): NumberInterface
    {
        /** @phpstan-ignore possiblyImpure.methodCall */
        $brickRounding = $this->getBrickRoundingMode($roundingMode);
        $quotient = BigDecimal::of($dividend->toString());
        foreach ($divisors as $divisor) {
            $quotient = $quotient->dividedBy($divisor->toString(), $scale, $brickRounding);
        }
        if ($scale === 0) {
            /** @phpstan-ignore possiblyImpure.new */
            return new IntegerObject((string) $quotient->toBigInteger());
        }
        /** @phpstan-ignore possiblyImpure.new */
        return new Decimal((string) $quotient);
    }
    public function fromBase(string $value, int $base): IntegerObject
    {
        try {
            /** @phpstan-ignore possiblyImpure.new */
            return new IntegerObject((string) BigInteger::fromBase($value, $base));
        } catch (MathException|\InvalidArgumentException $exception) {
            throw new InvalidArgumentException($exception->getMessage(), (int) $exception->getCode(), $exception);
        }
    }
    public function toBase(IntegerObject $value, int $base): string
    {
        try {
            return BigInteger::of($value->toString())->toBase($base);
        } catch (MathException|\InvalidArgumentException $exception) {
            throw new InvalidArgumentException($exception->getMessage(), (int) $exception->getCode(), $exception);
        }
    }
    public function toHexadecimal(IntegerObject $value): Hexadecimal
    {
        /** @phpstan-ignore possiblyImpure.new */
        return new Hexadecimal($this->toBase($value, 16));
    }
    public function toInteger(Hexadecimal $value): IntegerObject
    {
        return $this->fromBase($value->toString(), 16);
    }
    /**
     * Maps ramsey/uuid rounding modes to those used by brick/math
     *
     * @return BrickMathRounding::*
     */
    private function getBrickRoundingMode(int $roundingMode)
    {
        return self::ROUNDING_MODE_MAP[$roundingMode] ?? BrickMathRounding::UNNECESSARY;
    }
}
<?php

/**
 * This file is part of the ramsey/uuid library
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @copyright Copyright (c) Ben Ramsey <ben@benramsey.com>
 * @license http://opensource.org/licenses/MIT MIT
 */
declare (strict_types=1);
namespace _ContaoManager\Ramsey\Uuid;

use DateTimeInterface;
use _ContaoManager\Ramsey\Uuid\Type\Hexadecimal;
use _ContaoManager\Ramsey\Uuid\Type\Integer as IntegerObject;
use _ContaoManager\Ramsey\Uuid\Validator\ValidatorInterface;
/**
 * UuidFactoryInterface defines the common functionality all `UuidFactory` instances must implement
 */
interface UuidFactoryInterface
{
    /**
     * Creates a UUID from a byte string
     *
     * @param string $bytes A binary string
     *
     * @return UuidInterface A UuidInterface instance created from a binary string representation
     *
     * @pure
     */
    public function fromBytes(string $bytes): UuidInterface;
    /**
     * Creates a UUID from a DateTimeInterface instance
     *
     * @param DateTimeInterface $dateTime The date and time
     * @param Hexadecimal | null $node A 48-bit number representing the hardware address
     * @param int | null $clockSeq A 14-bit number used to help avoid duplicates that could arise when the clock is set
     *     backwards in time or if the node ID changes
     *
     * @return UuidInterface A UuidInterface instance that represents a version 1 UUID created from a DateTimeInterface instance
     */
    public function fromDateTime(DateTimeInterface $dateTime, ?Hexadecimal $node = null, ?int $clockSeq = null): UuidInterface;
    /**
     * Creates a UUID from a 128-bit integer string
     *
     * @param string $integer String representation of 128-bit integer
     *
     * @return UuidInterface A UuidInterface instance created from the string representation of a 128-bit integer
     *
     * @pure
     */
    public function fromInteger(string $integer): UuidInterface;
    /**
     * Creates a UUID from the string standard representation
     *
     * @param string $uuid A hexadecimal string
     *
     * @return UuidInterface A UuidInterface instance created from a hexadecimal string representation
     *
     * @pure
     */
    public function fromString(string $uuid): UuidInterface;
    /**
     * Returns the validator used by the factory
     */
    public function getValidator(): ValidatorInterface;
    /**
     * Returns a version 1 (Gregorian time) UUID from a host ID, sequence number, and the current time
     *
     * @param Hexadecimal | int | string | null $node A 48-bit number representing the hardware address; this number may
     *     be represented as an integer or a hexadecimal string
     * @param int | null $clockSeq A 14-bit number used to help avoid duplicates that could arise when the clock is set
     *     backwards in time or if the node ID changes
     *
     * @return UuidInterface A UuidInterface instance that represents a version 1 UUID
     */
    public function uuid1($node = null, ?int $clockSeq = null): UuidInterface;
    /**
     * Returns a version 2 (DCE Security) UUID from a local domain, local identifier, host ID, clock sequence, and the
     * current time
     *
     * @param int $localDomain The local domain to use when generating bytes, according to DCE Security
     * @param IntegerObject | null $localIdentifier The local identifier for the given domain; this may be a UID or GID
     *     on POSIX systems, if the local domain is a person or group, or it may be a site-defined identifier if the
     *     local domain is org
     * @param Hexadecimal | null $node A 48-bit number representing the hardware address
     * @param int | null $clockSeq A 14-bit number used to help avoid duplicates that could arise when the clock is set
     *     backwards in time or if the node ID changes
     *
     * @return UuidInterface A UuidInterface instance that represents a version 2 UUID
     */
    public function uuid2(int $localDomain, ?IntegerObject $localIdentifier = null, ?Hexadecimal $node = null, ?int $clockSeq = null): UuidInterface;
    /**
     * Returns a version 3 (name-based) UUID based on the MD5 hash of a namespace ID and a name
     *
     * @param UuidInterface | string $ns The namespace (must be a valid UUID)
     * @param string $name The name to use for creating a UUID
     *
     * @return UuidInterface A UuidInterface instance that represents a version 3 UUID
     *
     * @pure
     */
    public function uuid3($ns, string $name): UuidInterface;
    /**
     * Returns a version 4 (random) UUID
     *
     * @return UuidInterface A UuidInterface instance that represents a version 4 UUID
     */
    public function uuid4(): UuidInterface;
    /**
     * Returns a version 5 (name-based) UUID based on the SHA-1 hash of a namespace ID and a name
     *
     * @param UuidInterface | string $ns The namespace (must be a valid UUID)
     * @param string $name The name to use for creating a UUID
     *
     * @return UuidInterface A UuidInterface instance that represents a version 5 UUID
     *
     * @pure
     */
    public function uuid5($ns, string $name): UuidInterface;
    /**
     * Returns a version 6 (reordered Gregorian time) UUID from a host ID, sequence number, and the current time
     *
     * @param Hexadecimal | null $node A 48-bit number representing the hardware address
     * @param int | null $clockSeq A 14-bit number used to help avoid duplicates that could arise when the clock is set
     *     backwards in time or if the node ID changes
     *
     * @return UuidInterface A UuidInterface instance that represents a version 6 UUID
     */
    public function uuid6(?Hexadecimal $node = null, ?int $clockSeq = null): UuidInterface;
}
<?php

/**
 * This file is part of the ramsey/uuid library
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @copyright Copyright (c) Ben Ramsey <ben@benramsey.com>
 * @license http://opensource.org/licenses/MIT MIT
 */
declare (strict_types=1);
namespace _ContaoManager\Ramsey\Uuid\Generator;

use _ContaoManager\Ramsey\Uuid\Exception\RandomSourceException;
use Throwable;
/**
 * RandomBytesGenerator generates strings of random binary data using the built-in `random_bytes()` PHP function
 *
 * @link http://php.net/random_bytes random_bytes()
 */
class RandomBytesGenerator implements RandomGeneratorInterface
{
    /**
     * @throws RandomSourceException if random_bytes() throws an exception/error
     *
     * @inheritDoc
     */
    public function generate(int $length): string
    {
        try {
            return random_bytes($length);
        } catch (Throwable $exception) {
            throw new RandomSourceException($exception->getMessage(), (int) $exception->getCode(), $exception);
        }
    }
}
<?php

/**
 * This file is part of the ramsey/uuid library
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @copyright Copyright (c) Ben Ramsey <ben@benramsey.com>
 * @license http://opensource.org/licenses/MIT MIT
 */
declare (strict_types=1);
namespace _ContaoManager\Ramsey\Uuid\Generator;

/**
 * NameGeneratorFactory retrieves a default name generator, based on the environment
 */
class NameGeneratorFactory
{
    /**
     * Returns a default name generator, based on the current environment
     */
    public function getGenerator(): NameGeneratorInterface
    {
        return new DefaultNameGenerator();
    }
}
<?php

/**
 * This file is part of the ramsey/uuid library
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @copyright Copyright (c) Ben Ramsey <ben@benramsey.com>
 * @license http://opensource.org/licenses/MIT MIT
 */
declare (strict_types=1);
namespace _ContaoManager\Ramsey\Uuid\Generator;

use _ContaoManager\Brick\Math\BigInteger;
use DateTimeInterface;
use _ContaoManager\Ramsey\Uuid\Type\Hexadecimal;
use function assert;
use function hash;
use function pack;
use function str_pad;
use function strlen;
use function substr;
use function substr_replace;
use function unpack;
use const PHP_INT_SIZE;
use const STR_PAD_LEFT;
/**
 * UnixTimeGenerator generates bytes, combining a 48-bit timestamp in milliseconds since the Unix Epoch with 80 random bits
 *
 * Code and concepts within this class are borrowed from the symfony/uid package and are used under the terms of the MIT
 * license distributed with symfony/uid.
 *
 * symfony/uid is copyright (c) Fabien Potencier.
 *
 * @link https://symfony.com/components/Uid Symfony Uid component
 * @link https://github.com/symfony/uid/blob/4f9f537e57261519808a7ce1d941490736522bbc/UuidV7.php Symfony UuidV7 class
 * @link https://github.com/symfony/uid/blob/6.2/LICENSE MIT License
 */
class UnixTimeGenerator implements TimeGeneratorInterface
{
    private static string $time = '';
    private static ?string $seed = null;
    private static int $seedIndex = 0;
    /** @var int[] */
    private static array $rand = [];
    /** @var int[] */
    private static array $seedParts;
    public function __construct(private RandomGeneratorInterface $randomGenerator, private int $intSize = PHP_INT_SIZE)
    {
    }
    /**
     * @param Hexadecimal | int | string | null $node Unused in this generator
     * @param int | null $clockSeq Unused in this generator
     * @param DateTimeInterface | null $dateTime A date-time instance to use when generating bytes
     */
    public function generate($node = null, ?int $clockSeq = null, ?DateTimeInterface $dateTime = null): string
    {
        if ($dateTime === null) {
            $time = microtime(\false);
            $time = substr($time, 11) . substr($time, 2, 3);
        } else {
            $time = $dateTime->format('Uv');
        }
        if ($time > self::$time || $dateTime !== null && $time !== self::$time) {
            $this->randomize($time);
        } else {
            $time = $this->increment();
        }
        if ($this->intSize >= 8) {
            $time = substr(pack('J', (int) $time), -6);
        } else {
            $time = str_pad(BigInteger::of($time)->toBytes(\false), 6, "\x00", STR_PAD_LEFT);
        }
        assert(strlen($time) === 6);
        return $time . pack('n*', self::$rand[1], self::$rand[2], self::$rand[3], self::$rand[4], self::$rand[5]);
    }
    private function randomize(string $time): void
    {
        if (self::$seed === null) {
            $seed = $this->randomGenerator->generate(16);
            self::$seed = $seed;
        } else {
            $seed = $this->randomGenerator->generate(10);
        }
        /** @var int[] $rand */
        $rand = unpack('n*', $seed);
        $rand[1] &= 0x3ff;
        self::$rand = $rand;
        self::$time = $time;
    }
    /**
     * Special thanks to Nicolas Grekas (<https://github.com/nicolas-grekas>) for sharing the following information:
     *
     * Within the same ms, we increment the rand part by a random 24-bit number.
     *
     * Instead of getting this number from random_bytes(), which is slow, we get it by sha512-hashing self::$seed. This
     * produces 64 bytes of entropy, which we need to split in a list of 24-bit numbers. `unpack()` first splits them
     * into 16 x 32-bit numbers; we take the first byte of each number to get 5 extra 24-bit numbers. Then, we consume
     * each number one-by-one and run this logic every 21 iterations.
     *
     * `self::$rand` holds the random part of the UUID, split into 5 x 16-bit numbers for x86 portability. We increment
     * this random part by the next 24-bit number in the `self::$seedParts` list and decrement `self::$seedIndex`.
     */
    private function increment(): string
    {
        if (self::$seedIndex === 0 && self::$seed !== null) {
            self::$seed = hash('sha512', self::$seed, \true);
            /** @var int[] $s */
            $s = unpack('l*', self::$seed);
            $s[] = $s[1] >> 8 & 0xff0000 | $s[2] >> 16 & 0xff00 | $s[3] >> 24 & 0xff;
            $s[] = $s[4] >> 8 & 0xff0000 | $s[5] >> 16 & 0xff00 | $s[6] >> 24 & 0xff;
            $s[] = $s[7] >> 8 & 0xff0000 | $s[8] >> 16 & 0xff00 | $s[9] >> 24 & 0xff;
            $s[] = $s[10] >> 8 & 0xff0000 | $s[11] >> 16 & 0xff00 | $s[12] >> 24 & 0xff;
            $s[] = $s[13] >> 8 & 0xff0000 | $s[14] >> 16 & 0xff00 | $s[15] >> 24 & 0xff;
            self::$seedParts = $s;
            self::$seedIndex = 21;
        }
        self::$rand[5] = 0xffff & $carry = self::$rand[5] + 1 + (self::$seedParts[self::$seedIndex--] & 0xffffff);
        self::$rand[4] = 0xffff & $carry = self::$rand[4] + ($carry >> 16);
        self::$rand[3] = 0xffff & $carry = self::$rand[3] + ($carry >> 16);
        self::$rand[2] = 0xffff & $carry = self::$rand[2] + ($carry >> 16);
        self::$rand[1] += $carry >> 16;
        if (0xfc00 & self::$rand[1]) {
            $time = self::$time;
            $mtime = (int) substr($time, -9);
            if ($this->intSize >= 8 || strlen($time) < 10) {
                $time = (string) ((int) $time + 1);
            } elseif ($mtime === 999999999) {
                $time = 1 + (int) substr($time, 0, -9) . '000000000';
            } else {
                $mtime++;
                $time = substr_replace($time, str_pad((string) $mtime, 9, '0', STR_PAD_LEFT), -9);
            }
            $this->randomize($time);
        }
        return self::$time;
    }
}
<?php

/**
 * This file is part of the ramsey/uuid library
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @copyright Copyright (c) Ben Ramsey <ben@benramsey.com>
 * @license http://opensource.org/licenses/MIT MIT
 */
declare (strict_types=1);
namespace _ContaoManager\Ramsey\Uuid\Generator;

use _ContaoManager\Ramsey\Uuid\UuidInterface;
/**
 * A name generator generates strings of binary data created by hashing together a namespace with a name, according to a
 * hashing algorithm
 */
interface NameGeneratorInterface
{
    /**
     * Generate a binary string from a namespace and name hashed together with the specified hashing algorithm
     *
     * @param UuidInterface $ns The namespace
     * @param string $name The name to use for creating a UUID
     * @param string $hashAlgorithm The hashing algorithm to use
     *
     * @return string A binary string
     *
     * @pure
     */
    public function generate(UuidInterface $ns, string $name, string $hashAlgorithm): string;
}
<?php

/**
 * This file is part of the ramsey/uuid library
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @copyright Copyright (c) Ben Ramsey <ben@benramsey.com>
 * @license http://opensource.org/licenses/MIT MIT
 */
declare (strict_types=1);
namespace _ContaoManager\Ramsey\Uuid\Generator;

/**
 * RandomGeneratorFactory retrieves a default random generator, based on the environment
 */
class RandomGeneratorFactory
{
    /**
     * Returns a default random generator, based on the current environment
     */
    public function getGenerator(): RandomGeneratorInterface
    {
        return new RandomBytesGenerator();
    }
}
<?php

/**
 * This file is part of the ramsey/uuid library
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @copyright Copyright (c) Ben Ramsey <ben@benramsey.com>
 * @license http://opensource.org/licenses/MIT MIT
 */
declare (strict_types=1);
namespace _ContaoManager\Ramsey\Uuid\Generator;

use _ContaoManager\Ramsey\Uuid\Converter\NumberConverterInterface;
use _ContaoManager\Ramsey\Uuid\Exception\DceSecurityException;
use _ContaoManager\Ramsey\Uuid\Provider\DceSecurityProviderInterface;
use _ContaoManager\Ramsey\Uuid\Type\Hexadecimal;
use _ContaoManager\Ramsey\Uuid\Type\Integer as IntegerObject;
use _ContaoManager\Ramsey\Uuid\Uuid;
use function hex2bin;
use function in_array;
use function pack;
use function str_pad;
use function strlen;
use function substr_replace;
use const STR_PAD_LEFT;
/**
 * DceSecurityGenerator generates strings of binary data based on a local domain, local identifier, node ID, clock
 * sequence, and the current time
 */
class DceSecurityGenerator implements DceSecurityGeneratorInterface
{
    private const DOMAINS = [Uuid::DCE_DOMAIN_PERSON, Uuid::DCE_DOMAIN_GROUP, Uuid::DCE_DOMAIN_ORG];
    /**
     * Upper bounds for the clock sequence in DCE Security UUIDs.
     */
    private const CLOCK_SEQ_HIGH = 63;
    /**
     * Lower bounds for the clock sequence in DCE Security UUIDs.
     */
    private const CLOCK_SEQ_LOW = 0;
    public function __construct(private NumberConverterInterface $numberConverter, private TimeGeneratorInterface $timeGenerator, private DceSecurityProviderInterface $dceSecurityProvider)
    {
    }
    public function generate(int $localDomain, ?IntegerObject $localIdentifier = null, ?Hexadecimal $node = null, ?int $clockSeq = null): string
    {
        if (!in_array($localDomain, self::DOMAINS)) {
            throw new DceSecurityException('Local domain must be a valid DCE Security domain');
        }
        if ($localIdentifier && $localIdentifier->isNegative()) {
            throw new DceSecurityException('Local identifier out of bounds; it must be a value between 0 and 4294967295');
        }
        if ($clockSeq > self::CLOCK_SEQ_HIGH || $clockSeq < self::CLOCK_SEQ_LOW) {
            throw new DceSecurityException('Clock sequence out of bounds; it must be a value between 0 and 63');
        }
        switch ($localDomain) {
            case Uuid::DCE_DOMAIN_ORG:
                if ($localIdentifier === null) {
                    throw new DceSecurityException('A local identifier must be provided for the org domain');
                }
                break;
            case Uuid::DCE_DOMAIN_PERSON:
                if ($localIdentifier === null) {
                    $localIdentifier = $this->dceSecurityProvider->getUid();
                }
                break;
            case Uuid::DCE_DOMAIN_GROUP:
            default:
                if ($localIdentifier === null) {
                    $localIdentifier = $this->dceSecurityProvider->getGid();
                }
                break;
        }
        $identifierHex = $this->numberConverter->toHex($localIdentifier->toString());
        // The maximum value for the local identifier is 0xffffffff, or 4,294,967,295. This is 8 hexadecimal digits, so
        // if the length of hexadecimal digits is greater than 8, we know the value is greater than 0xffffffff.
        if (strlen($identifierHex) > 8) {
            throw new DceSecurityException('Local identifier out of bounds; it must be a value between 0 and 4294967295');
        }
        $domainByte = pack('n', $localDomain)[1];
        $identifierBytes = (string) hex2bin(str_pad($identifierHex, 8, '0', STR_PAD_LEFT));
        if ($node instanceof Hexadecimal) {
            $node = $node->toString();
        }
        // Shift the clock sequence 8 bits to the left, so it matches 0x3f00.
        if ($clockSeq !== null) {
            $clockSeq = $clockSeq << 8;
        }
        $bytes = $this->timeGenerator->generate($node, $clockSeq);
        // Replace bytes in the time-based UUID with DCE Security values.
        $bytes = substr_replace($bytes, $identifierBytes, 0, 4);
        return substr_replace($bytes, $domainByte, 9, 1);
    }
}
<?php

/**
 * This file is part of the ramsey/uuid library
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @copyright Copyright (c) Ben Ramsey <ben@benramsey.com>
 * @license http://opensource.org/licenses/MIT MIT
 */
declare (strict_types=1);
namespace _ContaoManager\Ramsey\Uuid\Generator;

use _ContaoManager\Ramsey\Uuid\Rfc4122\UuidV2;
use _ContaoManager\Ramsey\Uuid\Type\Hexadecimal;
use _ContaoManager\Ramsey\Uuid\Type\Integer as IntegerObject;
/**
 * A DCE Security generator generates strings of binary data based on a local domain, local identifier, node ID, clock
 * sequence, and the current time
 *
 * @see UuidV2
 */
interface DceSecurityGeneratorInterface
{
    /**
     * Generate a binary string from a local domain, local identifier, node ID, clock sequence, and current time
     *
     * @param int $localDomain The local domain to use when generating bytes, according to DCE Security
     * @param IntegerObject | null $localIdentifier The local identifier for the given domain; this may be a UID or GID
     *     on POSIX systems if the local domain is "person" or "group," or it may be a site-defined identifier if the
     *     local domain is "org"
     * @param Hexadecimal | null $node A 48-bit number representing the hardware address
     * @param int | null $clockSeq A 14-bit number used to help avoid duplicates that could arise when the clock is set
     *     backwards in time or if the node ID changes
     *
     * @return string A binary string
     */
    public function generate(int $localDomain, ?IntegerObject $localIdentifier = null, ?Hexadecimal $node = null, ?int $clockSeq = null): string;
}
<?php

/**
 * This file is part of the ramsey/uuid library
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @copyright Copyright (c) Ben Ramsey <ben@benramsey.com>
 * @license http://opensource.org/licenses/MIT MIT
 */
declare (strict_types=1);
namespace _ContaoManager\Ramsey\Uuid\Generator;

use _ContaoManager\Ramsey\Uuid\Converter\TimeConverterInterface;
use _ContaoManager\Ramsey\Uuid\Provider\NodeProviderInterface;
use _ContaoManager\Ramsey\Uuid\Provider\TimeProviderInterface;
/**
 * TimeGeneratorFactory retrieves a default time generator, based on the environment
 */
class TimeGeneratorFactory
{
    public function __construct(private NodeProviderInterface $nodeProvider, private TimeConverterInterface $timeConverter, private TimeProviderInterface $timeProvider)
    {
    }
    /**
     * Returns a default time generator, based on the current environment
     */
    public function getGenerator(): TimeGeneratorInterface
    {
        return new DefaultTimeGenerator($this->nodeProvider, $this->timeConverter, $this->timeProvider);
    }
}
<?php

/**
 * This file is part of the ramsey/uuid library
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @copyright Copyright (c) Ben Ramsey <ben@benramsey.com>
 * @license http://opensource.org/licenses/MIT MIT
 */
declare (strict_types=1);
namespace _ContaoManager\Ramsey\Uuid\Generator;

use _ContaoManager\Ramsey\Uuid\Exception\NameException;
use _ContaoManager\Ramsey\Uuid\UuidInterface;
use ValueError;
use function hash;
/**
 * DefaultNameGenerator generates strings of binary data based on a namespace, name, and hashing algorithm
 */
class DefaultNameGenerator implements NameGeneratorInterface
{
    /**
     * @pure
     */
    public function generate(UuidInterface $ns, string $name, string $hashAlgorithm): string
    {
        try {
            return hash($hashAlgorithm, $ns->getBytes() . $name, \true);
        } catch (ValueError $e) {
            throw new NameException(message: sprintf('Unable to hash namespace and name with algorithm \'%s\'', $hashAlgorithm), previous: $e);
        }
    }
}
<?php

/**
 * This file is part of the ramsey/uuid library
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @copyright Copyright (c) Ben Ramsey <ben@benramsey.com>
 * @license http://opensource.org/licenses/MIT MIT
 */
declare (strict_types=1);
namespace _ContaoManager\Ramsey\Uuid\Generator;

use _ContaoManager\Ramsey\Uuid\Converter\TimeConverterInterface;
use _ContaoManager\Ramsey\Uuid\Exception\InvalidArgumentException;
use _ContaoManager\Ramsey\Uuid\Exception\RandomSourceException;
use _ContaoManager\Ramsey\Uuid\Exception\TimeSourceException;
use _ContaoManager\Ramsey\Uuid\Provider\NodeProviderInterface;
use _ContaoManager\Ramsey\Uuid\Provider\TimeProviderInterface;
use _ContaoManager\Ramsey\Uuid\Type\Hexadecimal;
use Throwable;
use function dechex;
use function hex2bin;
use function is_int;
use function pack;
use function preg_match;
use function sprintf;
use function str_pad;
use function strlen;
use const STR_PAD_LEFT;
/**
 * DefaultTimeGenerator generates strings of binary data based on a node ID, clock sequence, and the current time
 */
class DefaultTimeGenerator implements TimeGeneratorInterface
{
    public function __construct(private NodeProviderInterface $nodeProvider, private TimeConverterInterface $timeConverter, private TimeProviderInterface $timeProvider)
    {
    }
    /**
     * @throws InvalidArgumentException if the parameters contain invalid values
     * @throws RandomSourceException if random_int() throws an exception/error
     *
     * @inheritDoc
     */
    public function generate($node = null, ?int $clockSeq = null): string
    {
        if ($node instanceof Hexadecimal) {
            $node = $node->toString();
        }
        $node = $this->getValidNode($node);
        if ($clockSeq === null) {
            try {
                // This does not use "stable storage"; see RFC 9562, section 6.3.
                $clockSeq = random_int(0, 0x3fff);
            } catch (Throwable $exception) {
                throw new RandomSourceException($exception->getMessage(), (int) $exception->getCode(), $exception);
            }
        }
        $time = $this->timeProvider->getTime();
        $uuidTime = $this->timeConverter->calculateTime($time->getSeconds()->toString(), $time->getMicroseconds()->toString());
        $timeHex = str_pad($uuidTime->toString(), 16, '0', STR_PAD_LEFT);
        if (strlen($timeHex) !== 16) {
            throw new TimeSourceException(sprintf('The generated time of \'%s\' is larger than expected', $timeHex));
        }
        $timeBytes = (string) hex2bin($timeHex);
        return $timeBytes[4] . $timeBytes[5] . $timeBytes[6] . $timeBytes[7] . $timeBytes[2] . $timeBytes[3] . $timeBytes[0] . $timeBytes[1] . pack('n*', $clockSeq) . $node;
    }
    /**
     * Uses the node provider given when constructing this instance to get the node ID (usually a MAC address)
     *
     * @param int | string | null $node A node value that may be used to override the node provider
     *
     * @return string 6-byte binary string representation of the node
     *
     * @throws InvalidArgumentException
     */
    private function getValidNode(int|string|null $node): string
    {
        if ($node === null) {
            $node = $this->nodeProvider->getNode();
        }
        // Convert the node to hex if it is still an integer.
        if (is_int($node)) {
            $node = dechex($node);
        }
        if (!preg_match('/^[A-Fa-f0-9]+$/', (string) $node) || strlen((string) $node) > 12) {
            throw new InvalidArgumentException('Invalid node value');
        }
        return (string) hex2bin(str_pad((string) $node, 12, '0', STR_PAD_LEFT));
    }
}
<?php

/**
 * This file is part of the ramsey/uuid library
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @copyright Copyright (c) Ben Ramsey <ben@benramsey.com>
 * @license http://opensource.org/licenses/MIT MIT
 */
declare (strict_types=1);
namespace _ContaoManager\Ramsey\Uuid\Generator;

use _ContaoManager\RandomLib\Factory;
use _ContaoManager\RandomLib\Generator;
/**
 * RandomLibAdapter generates strings of random binary data using the paragonie/random-lib library
 *
 * @deprecated This class will be removed in 5.0.0. Use the default RandomBytesGenerator or implement your own generator
 *     that implements RandomGeneratorInterface.
 *
 * @link https://packagist.org/packages/paragonie/random-lib paragonie/random-lib
 */
class RandomLibAdapter implements RandomGeneratorInterface
{
    private Generator $generator;
    /**
     * Constructs a RandomLibAdapter
     *
     * By default, if no Generator is passed in, this creates a high-strength generator to use when generating random
     * binary data.
     *
     * @param Generator | null $generator The generator to use when generating binary data
     */
    public function __construct(?Generator $generator = null)
    {
        if ($generator === null) {
            $factory = new Factory();
            $generator = $factory->getHighStrengthGenerator();
        }
        $this->generator = $generator;
    }
    public function generate(int $length): string
    {
        return $this->generator->generate($length);
    }
}
<?php

/**
 * This file is part of the ramsey/uuid library
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @copyright Copyright (c) Ben Ramsey <ben@benramsey.com>
 * @license http://opensource.org/licenses/MIT MIT
 */
declare (strict_types=1);
namespace _ContaoManager\Ramsey\Uuid\Generator;

use _ContaoManager\Ramsey\Uuid\Type\Hexadecimal;
/**
 * A time generator generates strings of binary data based on a node ID, clock sequence, and the current time
 */
interface TimeGeneratorInterface
{
    /**
     * Generate a binary string from a node ID, clock sequence, and current time
     *
     * @param Hexadecimal | int | string | null $node A 48-bit number representing the hardware address; this number may
     *     be represented as an integer or a hexadecimal string
     * @param int | null $clockSeq A 14-bit number used to help avoid duplicates that could arise when the clock is set
     *     backwards in time or if the node ID changes
     *
     * @return string A binary string
     */
    public function generate($node = null, ?int $clockSeq = null): string;
}
<?php

/**
 * This file is part of the ramsey/uuid library
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @copyright Copyright (c) Ben Ramsey <ben@benramsey.com>
 * @license http://opensource.org/licenses/MIT MIT
 */
declare (strict_types=1);
namespace _ContaoManager\Ramsey\Uuid\Generator;

use _ContaoManager\Ramsey\Uuid\Converter\NumberConverterInterface;
use _ContaoManager\Ramsey\Uuid\Exception\InvalidArgumentException;
use function bin2hex;
use function explode;
use function hex2bin;
use function microtime;
use function str_pad;
use function substr;
use const STR_PAD_LEFT;
/**
 * CombGenerator generates COMBs (combined UUID/timestamp)
 *
 * The CombGenerator, when used with the StringCodec (and, by proxy, the TimestampLastCombCodec) or the
 * TimestampFirstCombCodec, combines the current timestamp with a UUID (hence the name "COMB"). The timestamp either
 * appears as the first or last 48 bits of the COMB, depending on the codec used.
 *
 * By default, COMBs will have the timestamp set as the last 48 bits of the identifier.
 *
 * ```
 * $factory = new UuidFactory();
 *
 * $factory->setRandomGenerator(new CombGenerator(
 *     $factory->getRandomGenerator(),
 *     $factory->getNumberConverter(),
 * ));
 *
 * $comb = $factory->uuid4();
 * ```
 *
 * To generate a COMB with the timestamp as the first 48 bits, set the TimestampFirstCombCodec as the codec.
 *
 * ```
 * $factory->setCodec(new TimestampFirstCombCodec($factory->getUuidBuilder()));
 * ```
 *
 * @deprecated Please migrate to {@link https://uuid.ramsey.dev/en/stable/rfc4122/version7.html Version 7, Unix Epoch Time UUIDs}.
 *
 * @link https://web.archive.org/web/20240118030355/https://www.informit.com/articles/printerfriendly/25862 The Cost of GUIDs as Primary Keys
 */
class CombGenerator implements RandomGeneratorInterface
{
    public const TIMESTAMP_BYTES = 6;
    public function __construct(private RandomGeneratorInterface $generator, private NumberConverterInterface $numberConverter)
    {
    }
    /**
     * @throws InvalidArgumentException if $length is not a positive integer greater than or equal to CombGenerator::TIMESTAMP_BYTES
     *
     * @inheritDoc
     */
    public function generate(int $length): string
    {
        if ($length < self::TIMESTAMP_BYTES) {
            throw new InvalidArgumentException('Length must be a positive integer greater than or equal to ' . self::TIMESTAMP_BYTES);
        }
        if ($length % 2 !== 0) {
            throw new InvalidArgumentException('Length must be an even number');
        }
        $hash = '';
        /** @phpstan-ignore greater.alwaysTrue (TIMESTAMP_BYTES constant could change in child classes) */
        if (self::TIMESTAMP_BYTES > 0 && $length > self::TIMESTAMP_BYTES) {
            $hash = $this->generator->generate($length - self::TIMESTAMP_BYTES);
        }
        $lsbTime = str_pad($this->numberConverter->toHex($this->timestamp()), self::TIMESTAMP_BYTES * 2, '0', STR_PAD_LEFT);
        return (string) hex2bin(str_pad(bin2hex($hash), $length - self::TIMESTAMP_BYTES, '0') . $lsbTime);
    }
    /**
     * Returns the current timestamp as a string integer, precise to 0.00001 seconds
     */
    private function timestamp(): string
    {
        $time = explode(' ', microtime(\false));
        return $time[1] . substr($time[0], 2, 5);
    }
}
<?php

/**
 * This file is part of the ramsey/uuid library
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @copyright Copyright (c) Ben Ramsey <ben@benramsey.com>
 * @license http://opensource.org/licenses/MIT MIT
 */
declare (strict_types=1);
namespace _ContaoManager\Ramsey\Uuid\Generator;

/**
 * A random generator generates strings of random binary data
 */
interface RandomGeneratorInterface
{
    /**
     * Generates a string of randomized binary data
     *
     * @param int<1, max> $length The number of bytes to generate of random binary data
     *
     * @return string A binary string
     */
    public function generate(int $length): string;
}
<?php

/**
 * This file is part of the ramsey/uuid library
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @copyright Copyright (c) Ben Ramsey <ben@benramsey.com>
 * @license http://opensource.org/licenses/MIT MIT
 */
declare (strict_types=1);
namespace _ContaoManager\Ramsey\Uuid\Generator;

use function uuid_create;
use function uuid_parse;
use const UUID_TYPE_RANDOM;
/**
 * PeclUuidRandomGenerator generates strings of random binary data using ext-uuid
 *
 * @link https://pecl.php.net/package/uuid ext-uuid
 */
class PeclUuidRandomGenerator implements RandomGeneratorInterface
{
    public function generate(int $length): string
    {
        $uuid = uuid_create(UUID_TYPE_RANDOM);
        return (string) uuid_parse($uuid);
    }
}
<?php

/**
 * This file is part of the ramsey/uuid library
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @copyright Copyright (c) Ben Ramsey <ben@benramsey.com>
 * @license http://opensource.org/licenses/MIT MIT
 */
declare (strict_types=1);
namespace _ContaoManager\Ramsey\Uuid\Generator;

use _ContaoManager\Ramsey\Uuid\Exception\NameException;
use _ContaoManager\Ramsey\Uuid\UuidInterface;
use function sprintf;
use function uuid_generate_md5;
use function uuid_generate_sha1;
use function uuid_parse;
/**
 * PeclUuidNameGenerator generates strings of binary data from a namespace and a name, using ext-uuid
 *
 * @link https://pecl.php.net/package/uuid ext-uuid
 */
class PeclUuidNameGenerator implements NameGeneratorInterface
{
    /**
     * @pure
     */
    public function generate(UuidInterface $ns, string $name, string $hashAlgorithm): string
    {
        $uuid = match ($hashAlgorithm) {
            'md5' => uuid_generate_md5($ns->toString(), $name),
            /** @phpstan-ignore possiblyImpure.functionCall */
            'sha1' => uuid_generate_sha1($ns->toString(), $name),
            /** @phpstan-ignore possiblyImpure.functionCall */
            default => throw new NameException(sprintf('Unable to hash namespace and name with algorithm \'%s\'', $hashAlgorithm)),
        };
        /** @phpstan-ignore possiblyImpure.functionCall */
        return (string) uuid_parse($uuid);
    }
}
<?php

/**
 * This file is part of the ramsey/uuid library
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @copyright Copyright (c) Ben Ramsey <ben@benramsey.com>
 * @license http://opensource.org/licenses/MIT MIT
 */
declare (strict_types=1);
namespace _ContaoManager\Ramsey\Uuid\Generator;

use function uuid_create;
use function uuid_parse;
use const UUID_TYPE_TIME;
/**
 * PeclUuidTimeGenerator generates strings of binary data for time-base UUIDs, using ext-uuid
 *
 * @link https://pecl.php.net/package/uuid ext-uuid
 */
class PeclUuidTimeGenerator implements TimeGeneratorInterface
{
    /**
     * @inheritDoc
     */
    public function generate($node = null, ?int $clockSeq = null): string
    {
        $uuid = uuid_create(UUID_TYPE_TIME);
        return (string) uuid_parse($uuid);
    }
}
<?php

/**
 * This file is part of the ramsey/uuid library
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @copyright Copyright (c) Ben Ramsey <ben@benramsey.com>
 * @license http://opensource.org/licenses/MIT MIT
 */
declare (strict_types=1);
namespace _ContaoManager\Ramsey\Uuid;

/**
 * Provides binary math utilities
 */
class BinaryUtils
{
    /**
     * Applies the variant field to the 16-bit clock sequence
     *
     * @link https://www.rfc-editor.org/rfc/rfc9562#section-4.1 RFC 9562, 4.1. Variant Field
     *
     * @param int $clockSeq The 16-bit clock sequence value before the variant is applied
     *
     * @return int The 16-bit clock sequence multiplexed with the UUID variant
     *
     * @pure
     */
    public static function applyVariant(int $clockSeq): int
    {
        return $clockSeq & 0x3fff | 0x8000;
    }
    /**
     * Applies the version field to the 16-bit `time_hi_and_version` field
     *
     * @link https://www.rfc-editor.org/rfc/rfc9562#section-4.2 RFC 9562, 4.2. Version Field
     *
     * @param int $timeHi The value of the 16-bit `time_hi_and_version` field before the version is applied
     * @param int $version The version to apply to the `time_hi` field
     *
     * @return int The 16-bit time_hi field of the timestamp multiplexed with the UUID version number
     *
     * @pure
     */
    public static function applyVersion(int $timeHi, int $version): int
    {
        return $timeHi & 0xfff | $version << 12;
    }
}
<?php

/**
 * This file is part of the ramsey/uuid library
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @copyright Copyright (c) Ben Ramsey <ben@benramsey.com>
 * @license http://opensource.org/licenses/MIT MIT
 */
declare (strict_types=1);
namespace _ContaoManager\Ramsey\Uuid;

use DateTimeInterface;
use _ContaoManager\Ramsey\Uuid\Builder\UuidBuilderInterface;
use _ContaoManager\Ramsey\Uuid\Codec\CodecInterface;
use _ContaoManager\Ramsey\Uuid\Converter\NumberConverterInterface;
use _ContaoManager\Ramsey\Uuid\Converter\TimeConverterInterface;
use _ContaoManager\Ramsey\Uuid\Generator\DceSecurityGeneratorInterface;
use _ContaoManager\Ramsey\Uuid\Generator\DefaultTimeGenerator;
use _ContaoManager\Ramsey\Uuid\Generator\NameGeneratorInterface;
use _ContaoManager\Ramsey\Uuid\Generator\RandomGeneratorInterface;
use _ContaoManager\Ramsey\Uuid\Generator\TimeGeneratorInterface;
use _ContaoManager\Ramsey\Uuid\Generator\UnixTimeGenerator;
use _ContaoManager\Ramsey\Uuid\Lazy\LazyUuidFromString;
use _ContaoManager\Ramsey\Uuid\Provider\NodeProviderInterface;
use _ContaoManager\Ramsey\Uuid\Provider\Time\FixedTimeProvider;
use _ContaoManager\Ramsey\Uuid\Type\Hexadecimal;
use _ContaoManager\Ramsey\Uuid\Type\Integer as IntegerObject;
use _ContaoManager\Ramsey\Uuid\Type\Time;
use _ContaoManager\Ramsey\Uuid\Validator\ValidatorInterface;
use function bin2hex;
use function hex2bin;
use function pack;
use function str_pad;
use function strtolower;
use function substr;
use function substr_replace;
use function unpack;
use const STR_PAD_LEFT;
class UuidFactory implements UuidFactoryInterface
{
    private CodecInterface $codec;
    private DceSecurityGeneratorInterface $dceSecurityGenerator;
    private NameGeneratorInterface $nameGenerator;
    private NodeProviderInterface $nodeProvider;
    private NumberConverterInterface $numberConverter;
    private RandomGeneratorInterface $randomGenerator;
    private TimeConverterInterface $timeConverter;
    private TimeGeneratorInterface $timeGenerator;
    private TimeGeneratorInterface $unixTimeGenerator;
    private UuidBuilderInterface $uuidBuilder;
    private ValidatorInterface $validator;
    /**
     * @var bool whether the feature set was provided from outside, or we can operate under "default" assumptions
     */
    private bool $isDefaultFeatureSet;
    /**
     * @param FeatureSet | null $features A set of available features in the current environment
     */
    public function __construct(?FeatureSet $features = null)
    {
        $this->isDefaultFeatureSet = $features === null;
        $features = $features ?: new FeatureSet();
        $this->codec = $features->getCodec();
        $this->dceSecurityGenerator = $features->getDceSecurityGenerator();
        $this->nameGenerator = $features->getNameGenerator();
        $this->nodeProvider = $features->getNodeProvider();
        $this->numberConverter = $features->getNumberConverter();
        $this->randomGenerator = $features->getRandomGenerator();
        $this->timeConverter = $features->getTimeConverter();
        $this->timeGenerator = $features->getTimeGenerator();
        $this->uuidBuilder = $features->getBuilder();
        $this->validator = $features->getValidator();
        $this->unixTimeGenerator = $features->getUnixTimeGenerator();
    }
    /**
     * Returns the codec used by this factory
     */
    public function getCodec(): CodecInterface
    {
        return $this->codec;
    }
    /**
     * Sets the codec to use for this factory
     *
     * @param CodecInterface $codec A UUID encoder-decoder
     */
    public function setCodec(CodecInterface $codec): void
    {
        $this->isDefaultFeatureSet = \false;
        $this->codec = $codec;
    }
    /**
     * Returns the name generator used by this factory
     */
    public function getNameGenerator(): NameGeneratorInterface
    {
        return $this->nameGenerator;
    }
    /**
     * Sets the name generator to use for this factory
     *
     * @param NameGeneratorInterface $nameGenerator A generator to generate binary data, based on a namespace and name
     */
    public function setNameGenerator(NameGeneratorInterface $nameGenerator): void
    {
        $this->isDefaultFeatureSet = \false;
        $this->nameGenerator = $nameGenerator;
    }
    /**
     * Returns the node provider used by this factory
     */
    public function getNodeProvider(): NodeProviderInterface
    {
        return $this->nodeProvider;
    }
    /**
     * Returns the random generator used by this factory
     */
    public function getRandomGenerator(): RandomGeneratorInterface
    {
        return $this->randomGenerator;
    }
    /**
     * Returns the time generator used by this factory
     */
    public function getTimeGenerator(): TimeGeneratorInterface
    {
        return $this->timeGenerator;
    }
    /**
     * Sets the time generator to use for this factory
     *
     * @param TimeGeneratorInterface $generator A generator to generate binary data, based on the time
     */
    public function setTimeGenerator(TimeGeneratorInterface $generator): void
    {
        $this->isDefaultFeatureSet = \false;
        $this->timeGenerator = $generator;
    }
    /**
     * Returns the DCE Security generator used by this factory
     */
    public function getDceSecurityGenerator(): DceSecurityGeneratorInterface
    {
        return $this->dceSecurityGenerator;
    }
    /**
     * Sets the DCE Security generator to use for this factory
     *
     * @param DceSecurityGeneratorInterface $generator A generator to generate binary data, based on a local domain and
     *     local identifier
     */
    public function setDceSecurityGenerator(DceSecurityGeneratorInterface $generator): void
    {
        $this->isDefaultFeatureSet = \false;
        $this->dceSecurityGenerator = $generator;
    }
    /**
     * Returns the number converter used by this factory
     */
    public function getNumberConverter(): NumberConverterInterface
    {
        return $this->numberConverter;
    }
    /**
     * Sets the random generator to use for this factory
     *
     * @param RandomGeneratorInterface $generator A generator to generate binary data, based on some random input
     */
    public function setRandomGenerator(RandomGeneratorInterface $generator): void
    {
        $this->isDefaultFeatureSet = \false;
        $this->randomGenerator = $generator;
    }
    /**
     * Sets the number converter to use for this factory
     *
     * @param NumberConverterInterface $converter A converter to use for working with large integers (i.e., integers
     *     greater than PHP_INT_MAX)
     */
    public function setNumberConverter(NumberConverterInterface $converter): void
    {
        $this->isDefaultFeatureSet = \false;
        $this->numberConverter = $converter;
    }
    /**
     * Returns the UUID builder used by this factory
     */
    public function getUuidBuilder(): UuidBuilderInterface
    {
        return $this->uuidBuilder;
    }
    /**
     * Sets the UUID builder to use for this factory
     *
     * @param UuidBuilderInterface $builder A builder for constructing instances of UuidInterface
     */
    public function setUuidBuilder(UuidBuilderInterface $builder): void
    {
        $this->isDefaultFeatureSet = \false;
        $this->uuidBuilder = $builder;
    }
    public function getValidator(): ValidatorInterface
    {
        return $this->validator;
    }
    /**
     * Sets the validator to use for this factory
     *
     * @param ValidatorInterface $validator A validator to use for validating whether a string is a valid UUID
     */
    public function setValidator(ValidatorInterface $validator): void
    {
        $this->isDefaultFeatureSet = \false;
        $this->validator = $validator;
    }
    /**
     * @pure
     */
    public function fromBytes(string $bytes): UuidInterface
    {
        return $this->codec->decodeBytes($bytes);
    }
    /**
     * @pure
     */
    public function fromString(string $uuid): UuidInterface
    {
        $uuid = strtolower($uuid);
        return $this->codec->decode($uuid);
    }
    /**
     * @pure
     */
    public function fromInteger(string $integer): UuidInterface
    {
        $hex = $this->numberConverter->toHex($integer);
        $hex = str_pad($hex, 32, '0', STR_PAD_LEFT);
        return $this->fromString($hex);
    }
    public function fromDateTime(DateTimeInterface $dateTime, ?Hexadecimal $node = null, ?int $clockSeq = null): UuidInterface
    {
        $timeProvider = new FixedTimeProvider(new Time($dateTime->format('U'), $dateTime->format('u')));
        $timeGenerator = new DefaultTimeGenerator($this->nodeProvider, $this->timeConverter, $timeProvider);
        $bytes = $timeGenerator->generate($node?->toString(), $clockSeq);
        return $this->uuidFromBytesAndVersion($bytes, Uuid::UUID_TYPE_TIME);
    }
    /**
     * @pure
     */
    public function fromHexadecimal(Hexadecimal $hex): UuidInterface
    {
        return $this->codec->decode($hex->__toString());
    }
    /**
     * @inheritDoc
     */
    public function uuid1($node = null, ?int $clockSeq = null): UuidInterface
    {
        $bytes = $this->timeGenerator->generate($node, $clockSeq);
        return $this->uuidFromBytesAndVersion($bytes, Uuid::UUID_TYPE_TIME);
    }
    public function uuid2(int $localDomain, ?IntegerObject $localIdentifier = null, ?Hexadecimal $node = null, ?int $clockSeq = null): UuidInterface
    {
        $bytes = $this->dceSecurityGenerator->generate($localDomain, $localIdentifier, $node, $clockSeq);
        return $this->uuidFromBytesAndVersion($bytes, Uuid::UUID_TYPE_DCE_SECURITY);
    }
    /**
     * @inheritDoc
     * @pure
     */
    public function uuid3($ns, string $name): UuidInterface
    {
        return $this->uuidFromNsAndName($ns, $name, Uuid::UUID_TYPE_HASH_MD5, 'md5');
    }
    public function uuid4(): UuidInterface
    {
        $bytes = $this->randomGenerator->generate(16);
        return $this->uuidFromBytesAndVersion($bytes, Uuid::UUID_TYPE_RANDOM);
    }
    /**
     * @inheritDoc
     * @pure
     */
    public function uuid5($ns, string $name): UuidInterface
    {
        return $this->uuidFromNsAndName($ns, $name, Uuid::UUID_TYPE_HASH_SHA1, 'sha1');
    }
    public function uuid6(?Hexadecimal $node = null, ?int $clockSeq = null): UuidInterface
    {
        $bytes = $this->timeGenerator->generate($node?->toString(), $clockSeq);
        // Rearrange the bytes, according to the UUID version 6 specification.
        $v6 = $bytes[6] . $bytes[7] . $bytes[4] . $bytes[5] . $bytes[0] . $bytes[1] . $bytes[2] . $bytes[3];
        $v6 = bin2hex($v6);
        // Drop the first four bits, while adding an empty four bits for the version field. This allows us to
        // reconstruct the correct time from the bytes of this UUID.
        $v6Bytes = hex2bin(substr($v6, 1, 12) . '0' . substr($v6, -3));
        $v6Bytes .= substr($bytes, 8);
        return $this->uuidFromBytesAndVersion($v6Bytes, Uuid::UUID_TYPE_REORDERED_TIME);
    }
    /**
     * Returns a version 7 (Unix Epoch time) UUID
     *
     * @param DateTimeInterface | null $dateTime An optional date/time from which to create the version 7 UUID. If not
     *     provided, the UUID is generated using the current date/time.
     *
     * @return UuidInterface A UuidInterface instance that represents a version 7 UUID
     */
    public function uuid7(?DateTimeInterface $dateTime = null): UuidInterface
    {
        assert($this->unixTimeGenerator instanceof UnixTimeGenerator);
        $bytes = $this->unixTimeGenerator->generate(null, null, $dateTime);
        return $this->uuidFromBytesAndVersion($bytes, Uuid::UUID_TYPE_UNIX_TIME);
    }
    /**
     * Returns a version 8 (custom format) UUID
     *
     * The bytes provided may contain any value according to your application's needs. Be aware, however, that other
     * applications may not understand the semantics of the value.
     *
     * @param string $bytes A 16-byte octet string. This is an open blob of data that you may fill with 128 bits of
     *     information. Be aware, however, bits 48 through 51 will be replaced with the UUID version field, and bits 64
     *     and 65 will be replaced with the UUID variant. You MUST NOT rely on these bits for your application needs.
     *
     * @return UuidInterface A UuidInterface instance that represents a version 8 UUID
     *
     * @pure
     */
    public function uuid8(string $bytes): UuidInterface
    {
        /** @phpstan-ignore possiblyImpure.methodCall */
        return $this->uuidFromBytesAndVersion($bytes, Uuid::UUID_TYPE_CUSTOM);
    }
    /**
     * Returns a Uuid created from the provided byte string
     *
     * Uses the configured builder and codec and the provided byte string to construct a Uuid object.
     *
     * @param string $bytes The byte string from which to construct a UUID
     *
     * @return UuidInterface An instance of UuidInterface, created from the provided bytes
     *
     * @pure
     */
    public function uuid(string $bytes): UuidInterface
    {
        return $this->uuidBuilder->build($this->codec, $bytes);
    }
    /**
     * Returns a version 3 or 5 namespaced Uuid
     *
     * @param UuidInterface | string $ns The namespace (must be a valid UUID)
     * @param string $name The name to hash together with the namespace
     * @param int $version The version of UUID to create (3 or 5)
     * @param string $hashAlgorithm The hashing algorithm to use when hashing together the namespace and name
     *
     * @return UuidInterface An instance of UuidInterface, created by hashing together the provided namespace and name
     *
     * @pure
     */
    private function uuidFromNsAndName(UuidInterface|string $ns, string $name, int $version, string $hashAlgorithm): UuidInterface
    {
        if (!$ns instanceof UuidInterface) {
            $ns = $this->fromString($ns);
        }
        $bytes = $this->nameGenerator->generate($ns, $name, $hashAlgorithm);
        /** @phpstan-ignore possiblyImpure.methodCall */
        return $this->uuidFromBytesAndVersion(substr($bytes, 0, 16), $version);
    }
    /**
     * Returns a Uuid created from the provided bytes and version
     *
     * @param string $bytes The byte string to convert to a UUID
     * @param int $version The version to apply to the UUID
     *
     * @return UuidInterface An instance of UuidInterface, created from the byte string and version
     */
    private function uuidFromBytesAndVersion(string $bytes, int $version): UuidInterface
    {
        /** @var int[] $unpackedTime */
        $unpackedTime = unpack('n*', substr($bytes, 6, 2));
        $timeHi = $unpackedTime[1];
        $timeHiAndVersion = pack('n*', BinaryUtils::applyVersion($timeHi, $version));
        /** @var int[] $unpackedClockSeq */
        $unpackedClockSeq = unpack('n*', substr($bytes, 8, 2));
        $clockSeqHi = $unpackedClockSeq[1];
        $clockSeqHiAndReserved = pack('n*', BinaryUtils::applyVariant($clockSeqHi));
        $bytes = substr_replace($bytes, $timeHiAndVersion, 6, 2);
        $bytes = substr_replace($bytes, $clockSeqHiAndReserved, 8, 2);
        if ($this->isDefaultFeatureSet) {
            return LazyUuidFromString::fromBytes($bytes);
        }
        return $this->uuid($bytes);
    }
}
<?php

/**
 * This file is part of the ramsey/uuid library
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @copyright Copyright (c) Ben Ramsey <ben@benramsey.com>
 * @license http://opensource.org/licenses/MIT MIT
 */
declare (strict_types=1);
namespace _ContaoManager\Ramsey\Uuid\Type;

use _ContaoManager\Ramsey\Uuid\Exception\InvalidArgumentException;
use ValueError;
use function assert;
use function is_numeric;
use function preg_match;
use function sprintf;
use function substr;
/**
 * A value object representing an integer
 *
 * This class exists for type-safety purposes, to ensure that integers returned from ramsey/uuid methods as strings are
 * truly integers and not some other kind of string.
 *
 * To support large integers beyond PHP_INT_MAX and PHP_INT_MIN on both 64-bit and 32-bit systems, we store the integers
 * as strings.
 *
 * @immutable
 */
final class Integer implements NumberInterface
{
    /**
     * @var numeric-string
     */
    private string $value;
    /**
     * @phpstan-ignore property.readOnlyByPhpDocDefaultValue
     */
    private bool $isNegative = \false;
    public function __construct(self|float|int|string $value)
    {
        $this->value = $value instanceof self ? (string) $value : $this->prepareValue($value);
    }
    public function isNegative(): bool
    {
        return $this->isNegative;
    }
    /**
     * @return numeric-string
     *
     * @pure
     */
    public function toString(): string
    {
        return $this->value;
    }
    /**
     * @return numeric-string
     */
    public function __toString(): string
    {
        return $this->toString();
    }
    public function jsonSerialize(): string
    {
        return $this->toString();
    }
    public function serialize(): string
    {
        return $this->toString();
    }
    /**
     * @return array{string: string}
     */
    public function __serialize(): array
    {
        return ['string' => $this->toString()];
    }
    /**
     * Constructs the object from a serialized string representation
     *
     * @param string $data The serialized string representation of the object
     */
    public function unserialize(string $data): void
    {
        $this->__construct($data);
    }
    /**
     * @param array{string?: string} $data
     */
    public function __unserialize(array $data): void
    {
        // @codeCoverageIgnoreStart
        if (!isset($data['string'])) {
            throw new ValueError(sprintf('%s(): Argument #1 ($data) is invalid', __METHOD__));
        }
        // @codeCoverageIgnoreEnd
        $this->unserialize($data['string']);
    }
    /**
     * @return numeric-string
     */
    private function prepareValue(float|int|string $value): string
    {
        $value = (string) $value;
        $sign = '+';
        // If the value contains a sign, remove it for the digit pattern check.
        if (str_starts_with($value, '-') || str_starts_with($value, '+')) {
            $sign = substr($value, 0, 1);
            $value = substr($value, 1);
        }
        if (!preg_match('/^\d+$/', $value)) {
            throw new InvalidArgumentException('Value must be a signed integer or a string containing only ' . 'digits 0-9 and, optionally, a sign (+ or -)');
        }
        // Trim any leading zeros.
        $value = ltrim($value, '0');
        // Set to zero if the string is empty after trimming zeros.
        if ($value === '') {
            $value = '0';
        }
        // Add the negative sign back to the value.
        if ($sign === '-' && $value !== '0') {
            $value = $sign . $value;
            /** @phpstan-ignore property.readOnlyByPhpDocAssignNotInConstructor */
            $this->isNegative = \true;
        }
        assert(is_numeric($value));
        return $value;
    }
}
<?php

/**
 * This file is part of the ramsey/uuid library
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @copyright Copyright (c) Ben Ramsey <ben@benramsey.com>
 * @license http://opensource.org/licenses/MIT MIT
 */
declare (strict_types=1);
namespace _ContaoManager\Ramsey\Uuid\Type;

use _ContaoManager\Ramsey\Uuid\Exception\UnsupportedOperationException;
use _ContaoManager\Ramsey\Uuid\Type\Integer as IntegerObject;
use ValueError;
use function json_decode;
use function json_encode;
use function sprintf;
/**
 * A value object representing a timestamp
 *
 * This class exists for type-safety purposes, to ensure that timestamps used by ramsey/uuid are truly timestamp
 * integers and not some other kind of string or integer.
 *
 * @immutable
 */
final class Time implements TypeInterface
{
    private IntegerObject $seconds;
    private IntegerObject $microseconds;
    public function __construct(IntegerObject|float|int|string $seconds, IntegerObject|float|int|string $microseconds = 0)
    {
        $this->seconds = new IntegerObject($seconds);
        $this->microseconds = new IntegerObject($microseconds);
    }
    /**
     * @pure
     */
    public function getSeconds(): IntegerObject
    {
        return $this->seconds;
    }
    /**
     * @pure
     */
    public function getMicroseconds(): IntegerObject
    {
        return $this->microseconds;
    }
    public function toString(): string
    {
        return $this->seconds->toString() . '.' . sprintf('%06s', $this->microseconds->toString());
    }
    public function __toString(): string
    {
        return $this->toString();
    }
    /**
     * @return string[]
     */
    public function jsonSerialize(): array
    {
        return ['seconds' => $this->getSeconds()->toString(), 'microseconds' => $this->getMicroseconds()->toString()];
    }
    public function serialize(): string
    {
        return (string) json_encode($this);
    }
    /**
     * @return array{seconds: string, microseconds: string}
     */
    public function __serialize(): array
    {
        return ['seconds' => $this->getSeconds()->toString(), 'microseconds' => $this->getMicroseconds()->toString()];
    }
    /**
     * Constructs the object from a serialized string representation
     *
     * @param string $data The serialized string representation of the object
     */
    public function unserialize(string $data): void
    {
        /** @var array{seconds?: float | int | string, microseconds?: float | int | string} $time */
        $time = json_decode($data, \true);
        if (!isset($time['seconds']) || !isset($time['microseconds'])) {
            throw new UnsupportedOperationException('Attempted to unserialize an invalid value');
        }
        $this->__construct($time['seconds'], $time['microseconds']);
    }
    /**
     * @param array{seconds?: string, microseconds?: string} $data
     */
    public function __unserialize(array $data): void
    {
        // @codeCoverageIgnoreStart
        if (!isset($data['seconds']) || !isset($data['microseconds'])) {
            throw new ValueError(sprintf('%s(): Argument #1 ($data) is invalid', __METHOD__));
        }
        // @codeCoverageIgnoreEnd
        $this->__construct($data['seconds'], $data['microseconds']);
    }
}
<?php

/**
 * This file is part of the ramsey/uuid library
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @copyright Copyright (c) Ben Ramsey <ben@benramsey.com>
 * @license http://opensource.org/licenses/MIT MIT
 */
declare (strict_types=1);
namespace _ContaoManager\Ramsey\Uuid\Type;

use _ContaoManager\Ramsey\Uuid\Exception\InvalidArgumentException;
use ValueError;
use function preg_match;
use function sprintf;
use function substr;
/**
 * A value object representing a hexadecimal number
 *
 * This class exists for type-safety purposes, to ensure that hexadecimal numbers returned from ramsey/uuid methods as
 * strings are truly hexadecimal and not some other kind of string.
 *
 * @immutable
 */
final class Hexadecimal implements TypeInterface
{
    /**
     * @var non-empty-string
     */
    private string $value;
    /**
     * @param self | string $value The hexadecimal value to store
     */
    public function __construct(self|string $value)
    {
        $this->value = $value instanceof self ? (string) $value : $this->prepareValue($value);
    }
    /**
     * @return non-empty-string
     *
     * @pure
     */
    public function toString(): string
    {
        return $this->value;
    }
    /**
     * @return non-empty-string
     */
    public function __toString(): string
    {
        return $this->toString();
    }
    /**
     * @return non-empty-string
     */
    public function jsonSerialize(): string
    {
        return $this->toString();
    }
    /**
     * @return non-empty-string
     */
    public function serialize(): string
    {
        return $this->toString();
    }
    /**
     * @return array{string: string}
     */
    public function __serialize(): array
    {
        return ['string' => $this->toString()];
    }
    /**
     * Constructs the object from a serialized string representation
     *
     * @param string $data The serialized string representation of the object
     */
    public function unserialize(string $data): void
    {
        $this->__construct($data);
    }
    /**
     * @param array{string?: string} $data
     */
    public function __unserialize(array $data): void
    {
        // @codeCoverageIgnoreStart
        if (!isset($data['string'])) {
            throw new ValueError(sprintf('%s(): Argument #1 ($data) is invalid', __METHOD__));
        }
        // @codeCoverageIgnoreEnd
        $this->unserialize($data['string']);
    }
    /**
     * @return non-empty-string
     */
    private function prepareValue(string $value): string
    {
        $value = strtolower($value);
        if (str_starts_with($value, '0x')) {
            $value = substr($value, 2);
        }
        if (!preg_match('/^[A-Fa-f0-9]+$/', $value)) {
            throw new InvalidArgumentException('Value must be a hexadecimal number');
        }
        /** @var non-empty-string */
        return $value;
    }
}
<?php

/**
 * This file is part of the ramsey/uuid library
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @copyright Copyright (c) Ben Ramsey <ben@benramsey.com>
 * @license http://opensource.org/licenses/MIT MIT
 */
declare (strict_types=1);
namespace _ContaoManager\Ramsey\Uuid\Type;

/**
 * NumberInterface ensures consistency in numeric values returned by ramsey/uuid
 *
 * @immutable
 */
interface NumberInterface extends TypeInterface
{
    /**
     * Returns true if this number is less than zero
     */
    public function isNegative(): bool;
}
<?php

/**
 * This file is part of the ramsey/uuid library
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @copyright Copyright (c) Ben Ramsey <ben@benramsey.com>
 * @license http://opensource.org/licenses/MIT MIT
 */
declare (strict_types=1);
namespace _ContaoManager\Ramsey\Uuid\Type;

use JsonSerializable;
use Serializable;
/**
 * TypeInterface ensures consistency in typed values returned by ramsey/uuid
 *
 * @immutable
 */
interface TypeInterface extends JsonSerializable, Serializable
{
    /**
     * @pure
     */
    public function toString(): string;
    /**
     * @pure
     */
    public function __toString(): string;
}
<?php

/**
 * This file is part of the ramsey/uuid library
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @copyright Copyright (c) Ben Ramsey <ben@benramsey.com>
 * @license http://opensource.org/licenses/MIT MIT
 */
declare (strict_types=1);
namespace _ContaoManager\Ramsey\Uuid\Type;

use _ContaoManager\Ramsey\Uuid\Exception\InvalidArgumentException;
use ValueError;
use function is_numeric;
use function sprintf;
use function str_starts_with;
/**
 * A value object representing a decimal
 *
 * This class exists for type-safety purposes, to ensure that decimals returned from ramsey/uuid methods as strings are
 * truly decimals and not some other kind of string.
 *
 * To support values as true decimals and not as floats or doubles, we store the decimals as strings.
 *
 * @immutable
 */
final class Decimal implements NumberInterface
{
    private string $value;
    private bool $isNegative;
    public function __construct(float|int|string|self $value)
    {
        $value = (string) $value;
        if (!is_numeric($value)) {
            throw new InvalidArgumentException('Value must be a signed decimal or a string containing only ' . 'digits 0-9 and, optionally, a decimal point or sign (+ or -)');
        }
        // Remove the leading +-symbol.
        if (str_starts_with($value, '+')) {
            $value = substr($value, 1);
        }
        // For cases like `-0` or `-0.0000`, convert the value to `0`.
        if (abs((float) $value) === 0.0) {
            $value = '0';
        }
        if (str_starts_with($value, '-')) {
            $this->isNegative = \true;
        } else {
            $this->isNegative = \false;
        }
        $this->value = $value;
    }
    public function isNegative(): bool
    {
        return $this->isNegative;
    }
    public function toString(): string
    {
        return $this->value;
    }
    public function __toString(): string
    {
        return $this->toString();
    }
    public function jsonSerialize(): string
    {
        return $this->toString();
    }
    public function serialize(): string
    {
        return $this->toString();
    }
    /**
     * @return array{string: string}
     */
    public function __serialize(): array
    {
        return ['string' => $this->toString()];
    }
    /**
     * Constructs the object from a serialized string representation
     *
     * @param string $data The serialized string representation of the object
     */
    public function unserialize(string $data): void
    {
        $this->__construct($data);
    }
    /**
     * @param array{string?: string} $data
     */
    public function __unserialize(array $data): void
    {
        // @codeCoverageIgnoreStart
        if (!isset($data['string'])) {
            throw new ValueError(sprintf('%s(): Argument #1 ($data) is invalid', __METHOD__));
        }
        // @codeCoverageIgnoreEnd
        $this->unserialize($data['string']);
    }
}
<?php

/**
 * This file is part of the ramsey/uuid library
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @copyright Copyright (c) Ben Ramsey <ben@benramsey.com>
 * @license http://opensource.org/licenses/MIT MIT
 */
declare (strict_types=1);
namespace _ContaoManager\Ramsey\Uuid\Guid;

use _ContaoManager\Ramsey\Uuid\Codec\CodecInterface;
use _ContaoManager\Ramsey\Uuid\Converter\NumberConverterInterface;
use _ContaoManager\Ramsey\Uuid\Converter\TimeConverterInterface;
use _ContaoManager\Ramsey\Uuid\Uuid;
/**
 * Guid represents a UUID with "native" (little-endian) byte order
 *
 * From Wikipedia:
 *
 * > The first three fields are unsigned 32- and 16-bit integers and are subject to swapping, while the last two fields
 * > consist of uninterpreted bytes, not subject to swapping. This byte swapping applies even for versions 3, 4, and 5,
 * > where the canonical fields do not correspond to the content of the UUID.
 *
 * The first three fields of a GUID are encoded in little-endian byte order, while the last three fields are in network
 * (big-endian) byte order. This is according to the history of the Microsoft GUID definition.
 *
 * According to the .NET Guid.ToByteArray method documentation:
 *
 * > Note that the order of bytes in the returned byte array is different from the string representation of a Guid value.
 * > The order of the beginning four-byte group and the next two two-byte groups is reversed, whereas the order of the
 * > last two-byte group and the closing six-byte group is the same.
 *
 * @link https://en.wikipedia.org/wiki/Universally_unique_identifier#Variants UUID Variants on Wikipedia
 * @link https://docs.microsoft.com/en-us/windows/win32/api/guiddef/ns-guiddef-guid Windows GUID structure
 * @link https://docs.microsoft.com/en-us/dotnet/api/system.guid .NET Guid Struct
 * @link https://docs.microsoft.com/en-us/dotnet/api/system.guid.tobytearray .NET Guid.ToByteArray Method
 *
 * @immutable
 */
final class Guid extends Uuid
{
    public function __construct(Fields $fields, NumberConverterInterface $numberConverter, CodecInterface $codec, TimeConverterInterface $timeConverter)
    {
        parent::__construct($fields, $numberConverter, $codec, $timeConverter);
    }
}
<?php

/**
 * This file is part of the ramsey/uuid library
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @copyright Copyright (c) Ben Ramsey <ben@benramsey.com>
 * @license http://opensource.org/licenses/MIT MIT
 */
declare (strict_types=1);
namespace _ContaoManager\Ramsey\Uuid\Guid;

use _ContaoManager\Ramsey\Uuid\Exception\InvalidArgumentException;
use _ContaoManager\Ramsey\Uuid\Fields\SerializableFieldsTrait;
use _ContaoManager\Ramsey\Uuid\Rfc4122\FieldsInterface;
use _ContaoManager\Ramsey\Uuid\Rfc4122\MaxTrait;
use _ContaoManager\Ramsey\Uuid\Rfc4122\NilTrait;
use _ContaoManager\Ramsey\Uuid\Rfc4122\VariantTrait;
use _ContaoManager\Ramsey\Uuid\Rfc4122\VersionTrait;
use _ContaoManager\Ramsey\Uuid\Type\Hexadecimal;
use _ContaoManager\Ramsey\Uuid\Uuid;
use function bin2hex;
use function dechex;
use function hexdec;
use function pack;
use function sprintf;
use function str_pad;
use function strlen;
use function substr;
use function unpack;
use const STR_PAD_LEFT;
/**
 * GUIDs consist of a set of named fields, according to RFC 9562 (formerly RFC 4122)
 *
 * @see Guid
 *
 * @immutable
 */
final class Fields implements FieldsInterface
{
    use MaxTrait;
    use NilTrait;
    use SerializableFieldsTrait;
    use VariantTrait;
    use VersionTrait;
    /**
     * @param string $bytes A 16-byte binary string representation of a UUID
     *
     * @throws InvalidArgumentException if the byte string is not exactly 16 bytes
     * @throws InvalidArgumentException if the byte string does not represent a GUID
     * @throws InvalidArgumentException if the byte string does not contain a valid version
     */
    public function __construct(private string $bytes)
    {
        if (strlen($this->bytes) !== 16) {
            throw new InvalidArgumentException('The byte string must be 16 bytes long; received ' . strlen($this->bytes) . ' bytes');
        }
        if (!$this->isCorrectVariant()) {
            throw new InvalidArgumentException('The byte string received does not conform to the RFC 9562 (formerly RFC 4122) ' . 'or Microsoft Corporation variants');
        }
        if (!$this->isCorrectVersion()) {
            throw new InvalidArgumentException('The byte string received does not contain a valid version');
        }
    }
    public function getBytes(): string
    {
        return $this->bytes;
    }
    public function getTimeLow(): Hexadecimal
    {
        // Swap the bytes from little endian to network byte order.
        /** @var string[] $hex */
        $hex = unpack('H*', pack('v*', hexdec(bin2hex(substr($this->bytes, 2, 2))), hexdec(bin2hex(substr($this->bytes, 0, 2)))));
        return new Hexadecimal($hex[1] ?? '');
    }
    public function getTimeMid(): Hexadecimal
    {
        // Swap the bytes from little endian to network byte order.
        /** @var string[] $hex */
        $hex = unpack('H*', pack('v', hexdec(bin2hex(substr($this->bytes, 4, 2)))));
        return new Hexadecimal($hex[1] ?? '');
    }
    public function getTimeHiAndVersion(): Hexadecimal
    {
        // Swap the bytes from little endian to network byte order.
        /** @var string[] $hex */
        $hex = unpack('H*', pack('v', hexdec(bin2hex(substr($this->bytes, 6, 2)))));
        return new Hexadecimal($hex[1] ?? '');
    }
    public function getTimestamp(): Hexadecimal
    {
        return new Hexadecimal(sprintf('%03x%04s%08s', hexdec($this->getTimeHiAndVersion()->toString()) & 0xfff, $this->getTimeMid()->toString(), $this->getTimeLow()->toString()));
    }
    public function getClockSeq(): Hexadecimal
    {
        if ($this->isMax()) {
            $clockSeq = 0xffff;
        } elseif ($this->isNil()) {
            $clockSeq = 0x0;
        } else {
            $clockSeq = hexdec(bin2hex(substr($this->bytes, 8, 2))) & 0x3fff;
        }
        return new Hexadecimal(str_pad(dechex($clockSeq), 4, '0', STR_PAD_LEFT));
    }
    public function getClockSeqHiAndReserved(): Hexadecimal
    {
        return new Hexadecimal(bin2hex(substr($this->bytes, 8, 1)));
    }
    public function getClockSeqLow(): Hexadecimal
    {
        return new Hexadecimal(bin2hex(substr($this->bytes, 9, 1)));
    }
    public function getNode(): Hexadecimal
    {
        return new Hexadecimal(bin2hex(substr($this->bytes, 10)));
    }
    public function getVersion(): ?int
    {
        if ($this->isNil() || $this->isMax()) {
            return null;
        }
        /** @var int[] $parts */
        $parts = unpack('n*', $this->bytes);
        return $parts[4] >> 4 & 0xf;
    }
    private function isCorrectVariant(): bool
    {
        if ($this->isNil() || $this->isMax()) {
            return \true;
        }
        $variant = $this->getVariant();
        return $variant === Uuid::RFC_4122 || $variant === Uuid::RESERVED_MICROSOFT;
    }
}
<?php

/**
 * This file is part of the ramsey/uuid library
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @copyright Copyright (c) Ben Ramsey <ben@benramsey.com>
 * @license http://opensource.org/licenses/MIT MIT
 */
declare (strict_types=1);
namespace _ContaoManager\Ramsey\Uuid\Guid;

use _ContaoManager\Ramsey\Uuid\Builder\UuidBuilderInterface;
use _ContaoManager\Ramsey\Uuid\Codec\CodecInterface;
use _ContaoManager\Ramsey\Uuid\Converter\NumberConverterInterface;
use _ContaoManager\Ramsey\Uuid\Converter\TimeConverterInterface;
use _ContaoManager\Ramsey\Uuid\Exception\UnableToBuildUuidException;
use _ContaoManager\Ramsey\Uuid\UuidInterface;
use Throwable;
/**
 * GuidBuilder builds instances of Guid
 *
 * @see Guid
 *
 * @immutable
 */
class GuidBuilder implements UuidBuilderInterface
{
    /**
     * @param NumberConverterInterface $numberConverter The number converter to use when constructing the Guid
     * @param TimeConverterInterface $timeConverter The time converter to use for converting timestamps extracted from a
     *     UUID to Unix timestamps
     */
    public function __construct(private NumberConverterInterface $numberConverter, private TimeConverterInterface $timeConverter)
    {
    }
    /**
     * Builds and returns a Guid
     *
     * @param CodecInterface $codec The codec to use for building this Guid instance
     * @param string $bytes The byte string from which to construct a UUID
     *
     * @return Guid The GuidBuilder returns an instance of Ramsey\Uuid\Guid\Guid
     *
     * @pure
     */
    public function build(CodecInterface $codec, string $bytes): UuidInterface
    {
        try {
            /** @phpstan-ignore possiblyImpure.new */
            return new Guid($this->buildFields($bytes), $this->numberConverter, $codec, $this->timeConverter);
        } catch (Throwable $e) {
            /** @phpstan-ignore possiblyImpure.methodCall, possiblyImpure.methodCall */
            throw new UnableToBuildUuidException($e->getMessage(), (int) $e->getCode(), $e);
        }
    }
    /**
     * Proxy method to allow injecting a mock for testing
     *
     * @pure
     */
    protected function buildFields(string $bytes): Fields
    {
        /** @phpstan-ignore possiblyImpure.new */
        return new Fields($bytes);
    }
}
<?php

/**
 * This file is part of the ramsey/uuid library
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @copyright Copyright (c) Ben Ramsey <ben@benramsey.com>
 * @license http://opensource.org/licenses/MIT MIT
 */
declare (strict_types=1);
namespace _ContaoManager\Ramsey\Uuid\Lazy;

use DateTimeInterface;
use _ContaoManager\Ramsey\Uuid\Converter\NumberConverterInterface;
use _ContaoManager\Ramsey\Uuid\Exception\UnsupportedOperationException;
use _ContaoManager\Ramsey\Uuid\Fields\FieldsInterface;
use _ContaoManager\Ramsey\Uuid\Rfc4122\UuidV1;
use _ContaoManager\Ramsey\Uuid\Rfc4122\UuidV6;
use _ContaoManager\Ramsey\Uuid\Type\Hexadecimal;
use _ContaoManager\Ramsey\Uuid\Type\Integer as IntegerObject;
use _ContaoManager\Ramsey\Uuid\UuidFactory;
use _ContaoManager\Ramsey\Uuid\UuidInterface;
use ValueError;
use function assert;
use function bin2hex;
use function hex2bin;
use function sprintf;
use function str_replace;
use function substr;
/**
 * Lazy version of a UUID: its format has not been determined yet, so it is mostly only usable for string/bytes
 * conversion. This object optimizes instantiation, serialization and string conversion time, at the cost of increased
 * overhead for more advanced UUID operations.
 *
 * > [!NOTE]
 * > The {@see FieldsInterface} does not declare methods that deprecated API relies upon: the API has been ported from
 * > the {@see \Ramsey\Uuid\Uuid} definition, and is deprecated anyway.
 *
 * > [!NOTE]
 * > The deprecated API from {@see \Ramsey\Uuid\Uuid} is in use here (on purpose): it will be removed once the
 * > deprecated API is gone from this class too.
 *
 * @internal this type is used internally for performance reasons and is not supposed to be directly referenced in consumer libraries.
 */
final class LazyUuidFromString implements UuidInterface
{
    public const VALID_REGEX = '/\A[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}\z/ms';
    private ?UuidInterface $unwrapped = null;
    /**
     * @param non-empty-string $uuid
     */
    public function __construct(private string $uuid)
    {
    }
    public static function fromBytes(string $bytes): self
    {
        $base16Uuid = bin2hex($bytes);
        return new self(substr($base16Uuid, 0, 8) . '-' . substr($base16Uuid, 8, 4) . '-' . substr($base16Uuid, 12, 4) . '-' . substr($base16Uuid, 16, 4) . '-' . substr($base16Uuid, 20, 12));
    }
    public function serialize(): string
    {
        return $this->uuid;
    }
    /**
     * @return array{string: non-empty-string}
     */
    public function __serialize(): array
    {
        return ['string' => $this->uuid];
    }
    /**
     * {@inheritDoc}
     *
     * @param non-empty-string $data
     */
    public function unserialize(string $data): void
    {
        $this->uuid = $data;
    }
    /**
     * @param array{string?: non-empty-string} $data
     */
    public function __unserialize(array $data): void
    {
        // @codeCoverageIgnoreStart
        if (!isset($data['string'])) {
            throw new ValueError(sprintf('%s(): Argument #1 ($data) is invalid', __METHOD__));
        }
        // @codeCoverageIgnoreEnd
        $this->unserialize($data['string']);
    }
    public function getNumberConverter(): NumberConverterInterface
    {
        return ($this->unwrapped ?? $this->unwrap())->getNumberConverter();
    }
    /**
     * @inheritDoc
     */
    public function getFieldsHex(): array
    {
        return ($this->unwrapped ?? $this->unwrap())->getFieldsHex();
    }
    public function getClockSeqHiAndReservedHex(): string
    {
        return ($this->unwrapped ?? $this->unwrap())->getClockSeqHiAndReservedHex();
    }
    public function getClockSeqLowHex(): string
    {
        return ($this->unwrapped ?? $this->unwrap())->getClockSeqLowHex();
    }
    public function getClockSequenceHex(): string
    {
        return ($this->unwrapped ?? $this->unwrap())->getClockSequenceHex();
    }
    public function getDateTime(): DateTimeInterface
    {
        return ($this->unwrapped ?? $this->unwrap())->getDateTime();
    }
    public function getLeastSignificantBitsHex(): string
    {
        return ($this->unwrapped ?? $this->unwrap())->getLeastSignificantBitsHex();
    }
    public function getMostSignificantBitsHex(): string
    {
        return ($this->unwrapped ?? $this->unwrap())->getMostSignificantBitsHex();
    }
    public function getNodeHex(): string
    {
        return ($this->unwrapped ?? $this->unwrap())->getNodeHex();
    }
    public function getTimeHiAndVersionHex(): string
    {
        return ($this->unwrapped ?? $this->unwrap())->getTimeHiAndVersionHex();
    }
    public function getTimeLowHex(): string
    {
        return ($this->unwrapped ?? $this->unwrap())->getTimeLowHex();
    }
    public function getTimeMidHex(): string
    {
        return ($this->unwrapped ?? $this->unwrap())->getTimeMidHex();
    }
    public function getTimestampHex(): string
    {
        return ($this->unwrapped ?? $this->unwrap())->getTimestampHex();
    }
    public function getUrn(): string
    {
        return ($this->unwrapped ?? $this->unwrap())->getUrn();
    }
    public function getVariant(): ?int
    {
        return ($this->unwrapped ?? $this->unwrap())->getVariant();
    }
    public function getVersion(): ?int
    {
        return ($this->unwrapped ?? $this->unwrap())->getVersion();
    }
    public function compareTo(UuidInterface $other): int
    {
        return ($this->unwrapped ?? $this->unwrap())->compareTo($other);
    }
    public function equals(?object $other): bool
    {
        if (!$other instanceof UuidInterface) {
            return \false;
        }
        return $this->uuid === $other->toString();
    }
    public function getBytes(): string
    {
        /**
         * @var non-empty-string
         * @phpstan-ignore possiblyImpure.functionCall, possiblyImpure.functionCall
         */
        return (string) hex2bin(str_replace('-', '', $this->uuid));
    }
    public function getFields(): FieldsInterface
    {
        return ($this->unwrapped ?? $this->unwrap())->getFields();
    }
    public function getHex(): Hexadecimal
    {
        return ($this->unwrapped ?? $this->unwrap())->getHex();
    }
    public function getInteger(): IntegerObject
    {
        return ($this->unwrapped ?? $this->unwrap())->getInteger();
    }
    public function toString(): string
    {
        return $this->uuid;
    }
    public function __toString(): string
    {
        return $this->uuid;
    }
    public function jsonSerialize(): string
    {
        return $this->uuid;
    }
    /**
     * @deprecated Use {@see UuidInterface::getFields()} to get a {@see FieldsInterface} instance. If it is a
     *     {@see Rfc4122FieldsInterface} instance, you may call {@see Rfc4122FieldsInterface::getClockSeqHiAndReserved()}
     *     and use the arbitrary-precision math library of your choice to convert it to a string integer.
     */
    public function getClockSeqHiAndReserved(): string
    {
        $instance = $this->unwrapped ?? $this->unwrap();
        $fields = $instance->getFields();
        assert($fields instanceof \_ContaoManager\Ramsey\Uuid\Rfc4122\FieldsInterface);
        return $instance->getNumberConverter()->fromHex($fields->getClockSeqHiAndReserved()->toString());
    }
    /**
     * @deprecated Use {@see UuidInterface::getFields()} to get a {@see FieldsInterface} instance. If it is a
     *     {@see Rfc4122FieldsInterface} instance, you may call {@see Rfc4122FieldsInterface::getClockSeqLow()} and use
     *     the arbitrary-precision math library of your choice to convert it to a string integer.
     */
    public function getClockSeqLow(): string
    {
        $instance = $this->unwrapped ?? $this->unwrap();
        $fields = $instance->getFields();
        assert($fields instanceof \_ContaoManager\Ramsey\Uuid\Rfc4122\FieldsInterface);
        return $instance->getNumberConverter()->fromHex($fields->getClockSeqLow()->toString());
    }
    /**
     * @deprecated Use {@see UuidInterface::getFields()} to get a {@see FieldsInterface} instance. If it is a
     *     {@see Rfc4122FieldsInterface} instance, you may call {@see Rfc4122FieldsInterface::getClockSeq()} and use the
     *     arbitrary-precision math library of your choice to convert it to a string integer.
     */
    public function getClockSequence(): string
    {
        $instance = $this->unwrapped ?? $this->unwrap();
        $fields = $instance->getFields();
        assert($fields instanceof \_ContaoManager\Ramsey\Uuid\Rfc4122\FieldsInterface);
        return $instance->getNumberConverter()->fromHex($fields->getClockSeq()->toString());
    }
    /**
     * @deprecated This method will be removed in 5.0.0. There is no direct alternative, but the same information may be
     *     obtained by splitting in half the value returned by {@see UuidInterface::getHex()}.
     */
    public function getLeastSignificantBits(): string
    {
        $instance = $this->unwrapped ?? $this->unwrap();
        return $instance->getNumberConverter()->fromHex(substr($instance->getHex()->toString(), 16));
    }
    /**
     * @deprecated This method will be removed in 5.0.0. There is no direct alternative, but the same information may be
     *     obtained by splitting in half the value returned by {@see UuidInterface::getHex()}.
     */
    public function getMostSignificantBits(): string
    {
        $instance = $this->unwrapped ?? $this->unwrap();
        return $instance->getNumberConverter()->fromHex(substr($instance->getHex()->toString(), 0, 16));
    }
    /**
     * @deprecated Use {@see UuidInterface::getFields()} to get a {@see FieldsInterface} instance. If it is a
     *     {@see Rfc4122FieldsInterface} instance, you may call {@see Rfc4122FieldsInterface::getNode()} and use the
     *     arbitrary-precision math library of your choice to convert it to a string integer.
     */
    public function getNode(): string
    {
        $instance = $this->unwrapped ?? $this->unwrap();
        $fields = $instance->getFields();
        assert($fields instanceof \_ContaoManager\Ramsey\Uuid\Rfc4122\FieldsInterface);
        return $instance->getNumberConverter()->fromHex($fields->getNode()->toString());
    }
    /**
     * @deprecated Use {@see UuidInterface::getFields()} to get a {@see FieldsInterface} instance. If it is a
     *     {@see Rfc4122FieldsInterface} instance, you may call {@see Rfc4122FieldsInterface::getTimeHiAndVersion()} and
     *     use the arbitrary-precision math library of your choice to convert it to a string integer.
     */
    public function getTimeHiAndVersion(): string
    {
        $instance = $this->unwrapped ?? $this->unwrap();
        $fields = $instance->getFields();
        assert($fields instanceof \_ContaoManager\Ramsey\Uuid\Rfc4122\FieldsInterface);
        return $instance->getNumberConverter()->fromHex($fields->getTimeHiAndVersion()->toString());
    }
    /**
     * @deprecated Use {@see UuidInterface::getFields()} to get a {@see FieldsInterface} instance. If it is a
     *     {@see Rfc4122FieldsInterface} instance, you may call {@see Rfc4122FieldsInterface::getTimeLow()} and use the
     *     arbitrary-precision math library of your choice to convert it to a string integer.
     */
    public function getTimeLow(): string
    {
        $instance = $this->unwrapped ?? $this->unwrap();
        $fields = $instance->getFields();
        assert($fields instanceof \_ContaoManager\Ramsey\Uuid\Rfc4122\FieldsInterface);
        return $instance->getNumberConverter()->fromHex($fields->getTimeLow()->toString());
    }
    /**
     * @deprecated Use {@see UuidInterface::getFields()} to get a {@see FieldsInterface} instance. If it is a
     *     {@see Rfc4122FieldsInterface} instance, you may call {@see Rfc4122FieldsInterface::getTimeMid()} and use the
     *     arbitrary-precision math library of your choice to convert it to a string integer.
     */
    public function getTimeMid(): string
    {
        $instance = $this->unwrapped ?? $this->unwrap();
        $fields = $instance->getFields();
        assert($fields instanceof \_ContaoManager\Ramsey\Uuid\Rfc4122\FieldsInterface);
        return $instance->getNumberConverter()->fromHex($fields->getTimeMid()->toString());
    }
    /**
     * @deprecated Use {@see UuidInterface::getFields()} to get a {@see FieldsInterface} instance. If it is a
     *     {@see Rfc4122FieldsInterface} instance, you may call {@see Rfc4122FieldsInterface::getTimestamp()} and use
     *     the arbitrary-precision math library of your choice to convert it to a string integer.
     */
    public function getTimestamp(): string
    {
        $instance = $this->unwrapped ?? $this->unwrap();
        $fields = $instance->getFields();
        assert($fields instanceof \_ContaoManager\Ramsey\Uuid\Rfc4122\FieldsInterface);
        if ($fields->getVersion() !== 1) {
            throw new UnsupportedOperationException('Not a time-based UUID');
        }
        return $instance->getNumberConverter()->fromHex($fields->getTimestamp()->toString());
    }
    public function toUuidV1(): UuidV1
    {
        $instance = $this->unwrapped ?? $this->unwrap();
        if ($instance instanceof UuidV1) {
            return $instance;
        }
        assert($instance instanceof UuidV6);
        return $instance->toUuidV1();
    }
    public function toUuidV6(): UuidV6
    {
        $instance = $this->unwrapped ?? $this->unwrap();
        assert($instance instanceof UuidV6);
        return $instance;
    }
    private function unwrap(): UuidInterface
    {
        return $this->unwrapped = (new UuidFactory())->fromString($this->uuid);
    }
}
<?php

/**
 * This file is part of the ramsey/uuid library
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @copyright Copyright (c) Ben Ramsey <ben@benramsey.com>
 * @license http://opensource.org/licenses/MIT MIT
 */
declare (strict_types=1);
namespace _ContaoManager\Ramsey\Uuid;

/**
 * @deprecated DegradedUuid is no longer necessary to represent UUIDs on 32-bit systems.
 *     Transition any type declarations using this class to {@see UuidInterface}.
 *
 * @immutable
 */
class DegradedUuid extends Uuid
{
}
<?php

/**
 * This file is part of the ramsey/uuid library
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @copyright Copyright (c) Ben Ramsey <ben@benramsey.com>
 * @license http://opensource.org/licenses/MIT MIT
 */
declare (strict_types=1);
namespace _ContaoManager\Ramsey\Uuid\Fields;

use Serializable;
/**
 * UUIDs consist of unsigned integers, the bytes of which are separated into fields and arranged in a particular layout
 * defined by the specification for the variant
 *
 * @immutable
 */
interface FieldsInterface extends Serializable
{
    /**
     * Returns the bytes that comprise the fields
     *
     * @pure
     */
    public function getBytes(): string;
}
<?php

/**
 * This file is part of the ramsey/uuid library
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @copyright Copyright (c) Ben Ramsey <ben@benramsey.com>
 * @license http://opensource.org/licenses/MIT MIT
 */
declare (strict_types=1);
namespace _ContaoManager\Ramsey\Uuid\Fields;

use ValueError;
use function base64_decode;
use function sprintf;
use function strlen;
/**
 * Provides common serialization functionality to fields
 *
 * @immutable
 */
trait SerializableFieldsTrait
{
    /**
     * @param string $bytes The bytes that comprise the fields
     */
    abstract public function __construct(string $bytes);
    /**
     * Returns the bytes that comprise the fields
     */
    abstract public function getBytes(): string;
    /**
     * Returns a string representation of the object
     */
    public function serialize(): string
    {
        return $this->getBytes();
    }
    /**
     * @return array{bytes: string}
     */
    public function __serialize(): array
    {
        return ['bytes' => $this->getBytes()];
    }
    /**
     * Constructs the object from a serialized string representation
     *
     * @param string $data The serialized string representation of the object
     */
    public function unserialize(string $data): void
    {
        if (strlen($data) === 16) {
            $this->__construct($data);
        } else {
            $this->__construct(base64_decode($data));
        }
    }
    /**
     * @param array{bytes?: string} $data
     */
    public function __unserialize(array $data): void
    {
        // @codeCoverageIgnoreStart
        if (!isset($data['bytes'])) {
            throw new ValueError(sprintf('%s(): Argument #1 ($data) is invalid', __METHOD__));
        }
        // @codeCoverageIgnoreEnd
        $this->unserialize($data['bytes']);
    }
}
<?php

/**
 * This file is part of the ramsey/uuid library
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @copyright Copyright (c) Ben Ramsey <ben@benramsey.com>
 * @license http://opensource.org/licenses/MIT MIT
 */
declare (strict_types=1);
namespace _ContaoManager\Ramsey\Uuid;

use DateTimeInterface;
use _ContaoManager\Ramsey\Uuid\Converter\NumberConverterInterface;
/**
 * This interface encapsulates deprecated methods for ramsey/uuid
 *
 * @immutable
 */
interface DeprecatedUuidInterface
{
    /**
     * @deprecated This method will be removed in 5.0.0. There is no alternative recommendation, so plan accordingly.
     */
    public function getNumberConverter(): NumberConverterInterface;
    /**
     * @deprecated Use {@see UuidInterface::getFields()} to get a {@see FieldsInterface} instance.
     *
     * @return string[]
     */
    public function getFieldsHex(): array;
    /**
     * @deprecated Use {@see UuidInterface::getFields()} to get a {@see FieldsInterface} instance. If it is a
     *     {@see \Ramsey\Uuid\Rfc4122\FieldsInterface} instance, you may call
     *     {@see \Ramsey\Uuid\Rfc4122\FieldsInterface::getClockSeqHiAndReserved()}.
     */
    public function getClockSeqHiAndReservedHex(): string;
    /**
     * @deprecated Use {@see UuidInterface::getFields()} to get a {@see FieldsInterface} instance. If it is a
     *     {@see \Ramsey\Uuid\Rfc4122\FieldsInterface} instance, you may call
     *     {@see \Ramsey\Uuid\Rfc4122\FieldsInterface::getClockSeqLow()}.
     */
    public function getClockSeqLowHex(): string;
    /**
     * @deprecated Use {@see UuidInterface::getFields()} to get a {@see FieldsInterface} instance. If it is a
     *     {@see \Ramsey\Uuid\Rfc4122\FieldsInterface} instance, you may call
     *     {@see \Ramsey\Uuid\Rfc4122\FieldsInterface::getClockSeq()}.
     */
    public function getClockSequenceHex(): string;
    /**
     * @deprecated In ramsey/uuid version 5.0.0, this will be removed from the interface. It is available at
     *     {@see UuidV1::getDateTime()}.
     */
    public function getDateTime(): DateTimeInterface;
    /**
     * @deprecated This method will be removed in 5.0.0. There is no direct alternative, but the same information may be
     *     obtained by splitting in half the value returned by {@see UuidInterface::getHex()}.
     */
    public function getLeastSignificantBitsHex(): string;
    /**
     * @deprecated This method will be removed in 5.0.0. There is no direct alternative, but the same information may be
     *     obtained by splitting in half the value returned by {@see UuidInterface::getHex()}.
     */
    public function getMostSignificantBitsHex(): string;
    /**
     * @deprecated Use {@see UuidInterface::getFields()} to get a {@see FieldsInterface} instance. If it is a
     *     {@see \Ramsey\Uuid\Rfc4122\FieldsInterface} instance, you may call
     *     {@see \Ramsey\Uuid\Rfc4122\FieldsInterface::getNode()}.
     */
    public function getNodeHex(): string;
    /**
     * @deprecated Use {@see UuidInterface::getFields()} to get a {@see FieldsInterface} instance. If it is a
     *     {@see \Ramsey\Uuid\Rfc4122\FieldsInterface} instance, you may call
     *     {@see \Ramsey\Uuid\Rfc4122\FieldsInterface::getTimeHiAndVersion()}.
     */
    public function getTimeHiAndVersionHex(): string;
    /**
     * @deprecated Use {@see UuidInterface::getFields()} to get a {@see FieldsInterface} instance. If it is a
     *     {@see \Ramsey\Uuid\Rfc4122\FieldsInterface} instance, you may call
     *     {@see \Ramsey\Uuid\Rfc4122\FieldsInterface::getTimeLow()}.
     */
    public function getTimeLowHex(): string;
    /**
     * @deprecated Use {@see UuidInterface::getFields()} to get a {@see FieldsInterface} instance. If it is a
     *     {@see \Ramsey\Uuid\Rfc4122\FieldsInterface} instance, you may call
     *     {@see \Ramsey\Uuid\Rfc4122\FieldsInterface::getTimeMid()}.
     */
    public function getTimeMidHex(): string;
    /**
     * @deprecated Use {@see UuidInterface::getFields()} to get a {@see FieldsInterface} instance. If it is a
     *     {@see \Ramsey\Uuid\Rfc4122\FieldsInterface} instance, you may call
     *     {@see \Ramsey\Uuid\Rfc4122\FieldsInterface::getTimestamp()}.
     */
    public function getTimestampHex(): string;
    /**
     * @deprecated Use {@see UuidInterface::getFields()} to get a {@see FieldsInterface} instance. If it is a
     *     {@see \Ramsey\Uuid\Rfc4122\FieldsInterface} instance, you may call
     *     {@see \Ramsey\Uuid\Rfc4122\FieldsInterface::getVariant()}.
     */
    public function getVariant(): ?int;
    /**
     * @deprecated Use {@see UuidInterface::getFields()} to get a {@see FieldsInterface} instance. If it is a
     *     {@see \Ramsey\Uuid\Rfc4122\FieldsInterface} instance, you may call
     *     {@see \Ramsey\Uuid\Rfc4122\FieldsInterface::getVersion()}.
     */
    public function getVersion(): ?int;
}
<?php

/**
 * This file is part of the ramsey/uuid library
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @copyright Copyright (c) Ben Ramsey <ben@benramsey.com>
 * @license http://opensource.org/licenses/MIT MIT
 */
declare (strict_types=1);
namespace _ContaoManager\Ramsey\Uuid\Builder;

use _ContaoManager\Ramsey\Uuid\Codec\CodecInterface;
use _ContaoManager\Ramsey\Uuid\Converter\NumberConverterInterface;
use _ContaoManager\Ramsey\Uuid\Converter\Time\DegradedTimeConverter;
use _ContaoManager\Ramsey\Uuid\Converter\TimeConverterInterface;
use _ContaoManager\Ramsey\Uuid\DegradedUuid;
use _ContaoManager\Ramsey\Uuid\Rfc4122\Fields as Rfc4122Fields;
use _ContaoManager\Ramsey\Uuid\UuidInterface;
/**
 * @deprecated DegradedUuid instances are no longer necessary to support 32-bit systems. Please transition to {@see DefaultUuidBuilder}.
 *
 * @immutable
 */
class DegradedUuidBuilder implements UuidBuilderInterface
{
    private TimeConverterInterface $timeConverter;
    /**
     * @param NumberConverterInterface $numberConverter The number converter to use when constructing the DegradedUuid
     * @param TimeConverterInterface|null $timeConverter The time converter to use for converting timestamps extracted
     *     from a UUID to Unix timestamps
     */
    public function __construct(private NumberConverterInterface $numberConverter, ?TimeConverterInterface $timeConverter = null)
    {
        $this->timeConverter = $timeConverter ?: new DegradedTimeConverter();
    }
    /**
     * Builds and returns a DegradedUuid
     *
     * @param CodecInterface $codec The codec to use for building this DegradedUuid instance
     * @param string $bytes The byte string from which to construct a UUID
     *
     * @return DegradedUuid The DegradedUuidBuild returns an instance of Ramsey\Uuid\DegradedUuid
     *
     * @phpstan-impure
     */
    public function build(CodecInterface $codec, string $bytes): UuidInterface
    {
        return new DegradedUuid(new Rfc4122Fields($bytes), $this->numberConverter, $codec, $this->timeConverter);
    }
}
<?php

/**
 * This file is part of the ramsey/uuid library
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @copyright Copyright (c) Ben Ramsey <ben@benramsey.com>
 * @license http://opensource.org/licenses/MIT MIT
 */
declare (strict_types=1);
namespace _ContaoManager\Ramsey\Uuid\Builder;

use _ContaoManager\Ramsey\Uuid\Codec\CodecInterface;
use _ContaoManager\Ramsey\Uuid\UuidInterface;
/**
 * A UUID builder builds instances of UuidInterface
 *
 * @immutable
 */
interface UuidBuilderInterface
{
    /**
     * Builds and returns a UuidInterface
     *
     * @param CodecInterface $codec The codec to use for building this UuidInterface instance
     * @param string $bytes The byte string from which to construct a UUID
     *
     * @return UuidInterface Implementations may choose to return more specific instances of UUIDs that implement UuidInterface
     *
     * @pure
     */
    public function build(CodecInterface $codec, string $bytes): UuidInterface;
}
<?php

/**
 * This file is part of the ramsey/uuid library
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @copyright Copyright (c) Ben Ramsey <ben@benramsey.com>
 * @license http://opensource.org/licenses/MIT MIT
 */
declare (strict_types=1);
namespace _ContaoManager\Ramsey\Uuid\Builder;

use _ContaoManager\Ramsey\Collection\AbstractCollection;
use _ContaoManager\Ramsey\Uuid\Converter\Number\GenericNumberConverter;
use _ContaoManager\Ramsey\Uuid\Converter\Time\GenericTimeConverter;
use _ContaoManager\Ramsey\Uuid\Converter\Time\PhpTimeConverter;
use _ContaoManager\Ramsey\Uuid\Guid\GuidBuilder;
use _ContaoManager\Ramsey\Uuid\Math\BrickMathCalculator;
use _ContaoManager\Ramsey\Uuid\Nonstandard\UuidBuilder as NonstandardUuidBuilder;
use _ContaoManager\Ramsey\Uuid\Rfc4122\UuidBuilder as Rfc4122UuidBuilder;
use Traversable;
/**
 * A collection of UuidBuilderInterface objects
 *
 * @deprecated this class has been deprecated and will be removed in 5.0.0. The use-case for this class comes from a
 *     pre-`phpstan/phpstan` and pre-`vimeo/psalm` ecosystem, in which type safety had to be mostly enforced at runtime:
 *     that is no longer necessary, now that you can safely verify your code to be correct, and use more generic types
 *     like `iterable<T>` instead.
 *
 * @extends AbstractCollection<UuidBuilderInterface>
 */
class BuilderCollection extends AbstractCollection
{
    public function getType(): string
    {
        return UuidBuilderInterface::class;
    }
    public function getIterator(): Traversable
    {
        return parent::getIterator();
    }
    /**
     * Re-constructs the object from its serialized form
     *
     * @param string $serialized The serialized PHP string to unserialize into a UuidInterface instance
     */
    public function unserialize($serialized): void
    {
        /** @var array<array-key, UuidBuilderInterface> $data */
        $data = unserialize($serialized, ['allowed_classes' => [BrickMathCalculator::class, GenericNumberConverter::class, GenericTimeConverter::class, GuidBuilder::class, NonstandardUuidBuilder::class, PhpTimeConverter::class, Rfc4122UuidBuilder::class]]);
        $this->data = array_filter($data, function ($unserialized): bool {
            /** @phpstan-ignore instanceof.alwaysTrue */
            return $unserialized instanceof UuidBuilderInterface;
        });
    }
}
<?php

/**
 * This file is part of the ramsey/uuid library
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @copyright Copyright (c) Ben Ramsey <ben@benramsey.com>
 * @license http://opensource.org/licenses/MIT MIT
 */
declare (strict_types=1);
namespace _ContaoManager\Ramsey\Uuid\Builder;

use _ContaoManager\Ramsey\Uuid\Codec\CodecInterface;
use _ContaoManager\Ramsey\Uuid\Exception\BuilderNotFoundException;
use _ContaoManager\Ramsey\Uuid\Exception\UnableToBuildUuidException;
use _ContaoManager\Ramsey\Uuid\UuidInterface;
/**
 * FallbackBuilder builds a UUID by stepping through a list of UUID builders until a UUID can be constructed without exceptions
 *
 * @immutable
 */
class FallbackBuilder implements UuidBuilderInterface
{
    /**
     * @param iterable<UuidBuilderInterface> $builders An array of UUID builders
     */
    public function __construct(private iterable $builders)
    {
    }
    /**
     * Builds and returns a UuidInterface instance using the first builder that succeeds
     *
     * @param CodecInterface $codec The codec to use for building this instance
     * @param string $bytes The byte string from which to construct a UUID
     *
     * @return UuidInterface an instance of a UUID object
     *
     * @pure
     */
    public function build(CodecInterface $codec, string $bytes): UuidInterface
    {
        $lastBuilderException = null;
        foreach ($this->builders as $builder) {
            try {
                return $builder->build($codec, $bytes);
            } catch (UnableToBuildUuidException $exception) {
                $lastBuilderException = $exception;
                continue;
            }
        }
        throw new BuilderNotFoundException('Could not find a suitable builder for the provided codec and fields', 0, $lastBuilderException);
    }
}
<?php

/**
 * This file is part of the ramsey/uuid library
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @copyright Copyright (c) Ben Ramsey <ben@benramsey.com>
 * @license http://opensource.org/licenses/MIT MIT
 */
declare (strict_types=1);
namespace _ContaoManager\Ramsey\Uuid\Builder;

use _ContaoManager\Ramsey\Uuid\Rfc4122\UuidBuilder as Rfc4122UuidBuilder;
/**
 * @deprecated Please transition to {@see Rfc4122UuidBuilder}.
 *
 * @immutable
 */
class DefaultUuidBuilder extends Rfc4122UuidBuilder
{
}
<?php

/**
 * This file is part of the ramsey/uuid library
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @copyright Copyright (c) Ben Ramsey <ben@benramsey.com>
 * @license http://opensource.org/licenses/MIT MIT
 */
declare (strict_types=1);
namespace _ContaoManager\Ramsey\Uuid\Exception;

use RuntimeException as PhpRuntimeException;
/**
 * Thrown to indicate that the source of random data encountered an error
 *
 * This exception is used mostly to indicate that random_bytes() or random_int() threw an exception. However, it may be
 * used for other sources of random data.
 */
class RandomSourceException extends PhpRuntimeException implements UuidExceptionInterface
{
}
<?php

/**
 * This file is part of the ramsey/uuid library
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @copyright Copyright (c) Ben Ramsey <ben@benramsey.com>
 * @license http://opensource.org/licenses/MIT MIT
 */
declare (strict_types=1);
namespace _ContaoManager\Ramsey\Uuid\Exception;

use RuntimeException as PhpRuntimeException;
/**
 * Thrown to indicate that attempting to fetch or create a node ID encountered an error
 */
class NodeException extends PhpRuntimeException implements UuidExceptionInterface
{
}
<?php

/**
 * This file is part of the ramsey/uuid library
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @copyright Copyright (c) Ben Ramsey <ben@benramsey.com>
 * @license http://opensource.org/licenses/MIT MIT
 */
declare (strict_types=1);
namespace _ContaoManager\Ramsey\Uuid\Exception;

use RuntimeException as PhpRuntimeException;
/**
 * Thrown to indicate that the PHP DateTime extension encountered an exception/error
 */
class DateTimeException extends PhpRuntimeException implements UuidExceptionInterface
{
}
<?php

/**
 * This file is part of the ramsey/uuid library
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @copyright Copyright (c) Ben Ramsey <ben@benramsey.com>
 * @license http://opensource.org/licenses/MIT MIT
 */
declare (strict_types=1);
namespace _ContaoManager\Ramsey\Uuid\Exception;

use RuntimeException as PhpRuntimeException;
/**
 * Thrown to indicate that the source of time encountered an error
 */
class TimeSourceException extends PhpRuntimeException implements UuidExceptionInterface
{
}
<?php

/**
 * This file is part of the ramsey/uuid library
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @copyright Copyright (c) Ben Ramsey <ben@benramsey.com>
 * @license http://opensource.org/licenses/MIT MIT
 */
declare (strict_types=1);
namespace _ContaoManager\Ramsey\Uuid\Exception;

use LogicException as PhpLogicException;
/**
 * Thrown to indicate that the requested operation is not supported
 */
class UnsupportedOperationException extends PhpLogicException implements UuidExceptionInterface
{
}
<?php

/**
 * This file is part of the ramsey/uuid library
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @copyright Copyright (c) Ben Ramsey <ben@benramsey.com>
 * @license http://opensource.org/licenses/MIT MIT
 */
declare (strict_types=1);
namespace _ContaoManager\Ramsey\Uuid\Exception;

use RuntimeException as PhpRuntimeException;
/**
 * Thrown to indicate that the bytes being operated on are invalid in some way
 */
class InvalidBytesException extends PhpRuntimeException implements UuidExceptionInterface
{
}
<?php

/**
 * This file is part of the ramsey/uuid library
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @copyright Copyright (c) Ben Ramsey <ben@benramsey.com>
 * @license http://opensource.org/licenses/MIT MIT
 */
declare (strict_types=1);
namespace _ContaoManager\Ramsey\Uuid\Exception;

use RuntimeException as PhpRuntimeException;
/**
 * Thrown to indicate an exception occurred while dealing with DCE Security (version 2) UUIDs
 */
class DceSecurityException extends PhpRuntimeException implements UuidExceptionInterface
{
}
<?php

/**
 * This file is part of the ramsey/uuid library
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @copyright Copyright (c) Ben Ramsey <ben@benramsey.com>
 * @license http://opensource.org/licenses/MIT MIT
 */
declare (strict_types=1);
namespace _ContaoManager\Ramsey\Uuid\Exception;

use RuntimeException as PhpRuntimeException;
/**
 * Thrown to indicate that an error occurred while attempting to hash a namespace and name
 */
class NameException extends PhpRuntimeException implements UuidExceptionInterface
{
}
<?php

/**
 * This file is part of the ramsey/uuid library
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @copyright Copyright (c) Ben Ramsey <ben@benramsey.com>
 * @license http://opensource.org/licenses/MIT MIT
 */
declare (strict_types=1);
namespace _ContaoManager\Ramsey\Uuid\Exception;

use InvalidArgumentException as PhpInvalidArgumentException;
/**
 * Thrown to indicate that the argument received is not valid
 */
class InvalidArgumentException extends PhpInvalidArgumentException implements UuidExceptionInterface
{
}
<?php

/**
 * This file is part of the ramsey/uuid library
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @copyright Copyright (c) Ben Ramsey <ben@benramsey.com>
 * @license http://opensource.org/licenses/MIT MIT
 */
declare (strict_types=1);
namespace _ContaoManager\Ramsey\Uuid\Exception;

use RuntimeException as PhpRuntimeException;
/**
 * Thrown to indicate that no suitable builder could be found
 */
class BuilderNotFoundException extends PhpRuntimeException implements UuidExceptionInterface
{
}
<?php

/**
 * This file is part of the ramsey/uuid library
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @copyright Copyright (c) Ben Ramsey <ben@benramsey.com>
 * @license http://opensource.org/licenses/MIT MIT
 */
declare (strict_types=1);
namespace _ContaoManager\Ramsey\Uuid\Exception;

use RuntimeException as PhpRuntimeException;
/**
 * Thrown to indicate a builder is unable to build a UUID
 */
class UnableToBuildUuidException extends PhpRuntimeException implements UuidExceptionInterface
{
}
<?php

/**
 * This file is part of the ramsey/uuid library
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @copyright Copyright (c) Ben Ramsey <ben@benramsey.com>
 * @license http://opensource.org/licenses/MIT MIT
 */
declare (strict_types=1);
namespace _ContaoManager\Ramsey\Uuid\Exception;

use Throwable;
interface UuidExceptionInterface extends Throwable
{
}
<?php

/**
 * This file is part of the ramsey/uuid library
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @copyright Copyright (c) Ben Ramsey <ben@benramsey.com>
 * @license http://opensource.org/licenses/MIT MIT
 */
declare (strict_types=1);
namespace _ContaoManager\Ramsey\Uuid\Exception;

/**
 * Thrown to indicate that the string received is not a valid UUID
 *
 * The InvalidArgumentException that this extends is the ramsey/uuid version of this exception. It exists in the same
 * namespace as this class.
 */
class InvalidUuidStringException extends InvalidArgumentException implements UuidExceptionInterface
{
}
<?php

/**
 * This file is part of the ramsey/uuid library
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @copyright Copyright (c) Ben Ramsey <ben@benramsey.com>
 * @license http://opensource.org/licenses/MIT MIT
 */
declare (strict_types=1);
namespace _ContaoManager\Ramsey\Uuid\Nonstandard;

use _ContaoManager\Ramsey\Uuid\Exception\InvalidArgumentException;
use _ContaoManager\Ramsey\Uuid\Fields\SerializableFieldsTrait;
use _ContaoManager\Ramsey\Uuid\Rfc4122\FieldsInterface;
use _ContaoManager\Ramsey\Uuid\Rfc4122\VariantTrait;
use _ContaoManager\Ramsey\Uuid\Type\Hexadecimal;
use function bin2hex;
use function dechex;
use function hexdec;
use function sprintf;
use function str_pad;
use function strlen;
use function substr;
use const STR_PAD_LEFT;
/**
 * Nonstandard UUID fields do not conform to the RFC 9562 (formerly RFC 4122) standard
 *
 * Since some systems may create nonstandard UUIDs, this implements the {@see FieldsInterface}, so that functionality of
 * a nonstandard UUID is not degraded, in the event these UUIDs are expected to contain RFC 9562 (formerly RFC 4122) fields.
 *
 * Internally, this class represents the fields together as a 16-byte binary string.
 *
 * @immutable
 */
final class Fields implements FieldsInterface
{
    use SerializableFieldsTrait;
    use VariantTrait;
    /**
     * @param string $bytes A 16-byte binary string representation of a UUID
     *
     * @throws InvalidArgumentException if the byte string is not exactly 16 bytes
     */
    public function __construct(private string $bytes)
    {
        if (strlen($this->bytes) !== 16) {
            throw new InvalidArgumentException('The byte string must be 16 bytes long; received ' . strlen($this->bytes) . ' bytes');
        }
    }
    public function getBytes(): string
    {
        return $this->bytes;
    }
    public function getClockSeq(): Hexadecimal
    {
        $clockSeq = hexdec(bin2hex(substr($this->bytes, 8, 2))) & 0x3fff;
        return new Hexadecimal(str_pad(dechex($clockSeq), 4, '0', STR_PAD_LEFT));
    }
    public function getClockSeqHiAndReserved(): Hexadecimal
    {
        return new Hexadecimal(bin2hex(substr($this->bytes, 8, 1)));
    }
    public function getClockSeqLow(): Hexadecimal
    {
        return new Hexadecimal(bin2hex(substr($this->bytes, 9, 1)));
    }
    public function getNode(): Hexadecimal
    {
        return new Hexadecimal(bin2hex(substr($this->bytes, 10)));
    }
    public function getTimeHiAndVersion(): Hexadecimal
    {
        return new Hexadecimal(bin2hex(substr($this->bytes, 6, 2)));
    }
    public function getTimeLow(): Hexadecimal
    {
        return new Hexadecimal(bin2hex(substr($this->bytes, 0, 4)));
    }
    public function getTimeMid(): Hexadecimal
    {
        return new Hexadecimal(bin2hex(substr($this->bytes, 4, 2)));
    }
    public function getTimestamp(): Hexadecimal
    {
        return new Hexadecimal(sprintf('%03x%04s%08s', hexdec($this->getTimeHiAndVersion()->toString()) & 0xfff, $this->getTimeMid()->toString(), $this->getTimeLow()->toString()));
    }
    public function getVersion(): ?int
    {
        return null;
    }
    public function isNil(): bool
    {
        return \false;
    }
    public function isMax(): bool
    {
        return \false;
    }
}
<?php

/**
 * This file is part of the ramsey/uuid library
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @copyright Copyright (c) Ben Ramsey <ben@benramsey.com>
 * @license http://opensource.org/licenses/MIT MIT
 */
declare (strict_types=1);
namespace _ContaoManager\Ramsey\Uuid\Nonstandard;

use _ContaoManager\Ramsey\Uuid\Codec\CodecInterface;
use _ContaoManager\Ramsey\Uuid\Converter\NumberConverterInterface;
use _ContaoManager\Ramsey\Uuid\Converter\TimeConverterInterface;
use _ContaoManager\Ramsey\Uuid\Uuid as BaseUuid;
/**
 * Nonstandard\Uuid is a UUID that doesn't conform to RFC 9562 (formerly RFC 4122)
 *
 * @immutable
 * @pure
 */
final class Uuid extends BaseUuid
{
    public function __construct(Fields $fields, NumberConverterInterface $numberConverter, CodecInterface $codec, TimeConverterInterface $timeConverter)
    {
        parent::__construct($fields, $numberConverter, $codec, $timeConverter);
    }
}
<?php

/**
 * This file is part of the ramsey/uuid library
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @copyright Copyright (c) Ben Ramsey <ben@benramsey.com>
 * @license http://opensource.org/licenses/MIT MIT
 */
declare (strict_types=1);
namespace _ContaoManager\Ramsey\Uuid\Nonstandard;

use _ContaoManager\Ramsey\Uuid\Builder\UuidBuilderInterface;
use _ContaoManager\Ramsey\Uuid\Codec\CodecInterface;
use _ContaoManager\Ramsey\Uuid\Converter\NumberConverterInterface;
use _ContaoManager\Ramsey\Uuid\Converter\TimeConverterInterface;
use _ContaoManager\Ramsey\Uuid\Exception\UnableToBuildUuidException;
use _ContaoManager\Ramsey\Uuid\UuidInterface;
use Throwable;
/**
 * Nonstandard\UuidBuilder builds instances of Nonstandard\Uuid
 *
 * @immutable
 */
class UuidBuilder implements UuidBuilderInterface
{
    /**
     * @param NumberConverterInterface $numberConverter The number converter to use when constructing the Nonstandard\Uuid
     * @param TimeConverterInterface $timeConverter The time converter to use for converting timestamps extracted from a
     *     UUID to Unix timestamps
     */
    public function __construct(private NumberConverterInterface $numberConverter, private TimeConverterInterface $timeConverter)
    {
    }
    /**
     * Builds and returns a Nonstandard\Uuid
     *
     * @param CodecInterface $codec The codec to use for building this instance
     * @param string $bytes The byte string from which to construct a UUID
     *
     * @return Uuid The Nonstandard\UuidBuilder returns an instance of Nonstandard\Uuid
     *
     * @pure
     */
    public function build(CodecInterface $codec, string $bytes): UuidInterface
    {
        try {
            /** @phpstan-ignore possiblyImpure.new */
            return new Uuid($this->buildFields($bytes), $this->numberConverter, $codec, $this->timeConverter);
        } catch (Throwable $e) {
            /** @phpstan-ignore possiblyImpure.methodCall, possiblyImpure.methodCall */
            throw new UnableToBuildUuidException($e->getMessage(), (int) $e->getCode(), $e);
        }
    }
    /**
     * Proxy method to allow injecting a mock for testing
     *
     * @pure
     */
    protected function buildFields(string $bytes): Fields
    {
        /** @phpstan-ignore possiblyImpure.new */
        return new Fields($bytes);
    }
}
<?php

/**
 * This file is part of the ramsey/uuid library
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @copyright Copyright (c) Ben Ramsey <ben@benramsey.com>
 * @license http://opensource.org/licenses/MIT MIT
 */
declare (strict_types=1);
namespace _ContaoManager\Ramsey\Uuid\Nonstandard;

use _ContaoManager\Ramsey\Uuid\Codec\CodecInterface;
use _ContaoManager\Ramsey\Uuid\Converter\NumberConverterInterface;
use _ContaoManager\Ramsey\Uuid\Converter\TimeConverterInterface;
use _ContaoManager\Ramsey\Uuid\Exception\InvalidArgumentException;
use _ContaoManager\Ramsey\Uuid\Lazy\LazyUuidFromString;
use _ContaoManager\Ramsey\Uuid\Rfc4122\FieldsInterface as Rfc4122FieldsInterface;
use _ContaoManager\Ramsey\Uuid\Rfc4122\TimeTrait;
use _ContaoManager\Ramsey\Uuid\Rfc4122\UuidInterface;
use _ContaoManager\Ramsey\Uuid\Rfc4122\UuidV1;
use _ContaoManager\Ramsey\Uuid\Uuid as BaseUuid;
/**
 * Reordered time, or version 6, UUIDs include timestamp, clock sequence, and node values that are combined into a
 * 128-bit unsigned integer
 *
 * @deprecated Use {@see \Ramsey\Uuid\Rfc4122\UuidV6} instead.
 *
 * @link https://github.com/uuid6/uuid6-ietf-draft UUID version 6 IETF draft
 * @link http://gh.peabody.io/uuidv6/ "Version 6" UUIDs
 * @link https://www.rfc-editor.org/rfc/rfc9562#section-5.6 RFC 9562, 5.6. UUID Version 6
 *
 * @immutable
 */
class UuidV6 extends BaseUuid implements UuidInterface
{
    use TimeTrait;
    /**
     * Creates a version 6 (reordered Gregorian time) UUID
     *
     * @param Rfc4122FieldsInterface $fields The fields from which to construct a UUID
     * @param NumberConverterInterface $numberConverter The number converter to use for converting hex values to/from integers
     * @param CodecInterface $codec The codec to use when encoding or decoding UUID strings
     * @param TimeConverterInterface $timeConverter The time converter to use for converting timestamps extracted from a
     *     UUID to unix timestamps
     */
    public function __construct(Rfc4122FieldsInterface $fields, NumberConverterInterface $numberConverter, CodecInterface $codec, TimeConverterInterface $timeConverter)
    {
        if ($fields->getVersion() !== BaseUuid::UUID_TYPE_REORDERED_TIME) {
            throw new InvalidArgumentException('Fields used to create a UuidV6 must represent a version 6 (reordered time) UUID');
        }
        parent::__construct($fields, $numberConverter, $codec, $timeConverter);
    }
    /**
     * Converts this UUID into an instance of a version 1 UUID
     */
    public function toUuidV1(): UuidV1
    {
        $hex = $this->getHex()->toString();
        $hex = substr($hex, 7, 5) . substr($hex, 13, 3) . substr($hex, 3, 4) . '1' . substr($hex, 0, 3) . substr($hex, 16);
        /** @var LazyUuidFromString $uuid */
        $uuid = BaseUuid::fromBytes((string) hex2bin($hex));
        return $uuid->toUuidV1();
    }
    /**
     * Converts a version 1 UUID into an instance of a version 6 UUID
     */
    public static function fromUuidV1(UuidV1 $uuidV1): \_ContaoManager\Ramsey\Uuid\Rfc4122\UuidV6
    {
        $hex = $uuidV1->getHex()->toString();
        $hex = substr($hex, 13, 3) . substr($hex, 8, 4) . substr($hex, 0, 5) . '6' . substr($hex, 5, 3) . substr($hex, 16);
        /** @var LazyUuidFromString $uuid */
        $uuid = BaseUuid::fromBytes((string) hex2bin($hex));
        return $uuid->toUuidV6();
    }
}
The MIT License (MIT)

Copyright (c) 2014 Bernhard Schussek

Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Changelog
=========

## UNRELEASED

## 1.12.1

### Fixed

- Exclude tools from export.

## 1.12.0

### Fixed

- Corrected messages and typos in various assertions.
- Document `void` return type.
- Prevent UUIDs with trailing newlines from validating.
- Assert values are strings before ctype checks.

## 1.11.0

### Added

* Added explicit (non-magic) `allNullOr*` methods, with `@psalm-assert` annotations, for better Psalm support.

### Changed

* Trait methods will now check the assertion themselves, instead of using `__callStatic`
* `isList` will now deal correctly with (modified) lists that contain `NaN`
* `reportInvalidArgument` now has a return type of `never`.

### Removed

* Removed `symfony/polyfill-ctype` as a dependency, and require `ext-ctype` instead.
  * You can still require the `symfony/polyfill-ctype` in your project if you need it, as it provides `ext-ctype`

## 1.10.0

### Added

* On invalid assertion, we throw a `Webmozart\Assert\InvalidArgumentException`
* Added `Assert::positiveInteger()`

### Changed

* Using a trait with real implementations of `all*()` and `nullOr*()` methods to improve psalm compatibility.

### Removed

* Support for PHP <7.2

## 1.9.1

## Fixed

* provisional support for PHP 8.0

## 1.9.0

* added better Psalm support for `all*` & `nullOr*` methods
* These methods are now understood by Psalm through a mixin. You may need a newer version of Psalm in order to use this
* added `@psalm-pure` annotation to `Assert::notFalse()`
* added more `@psalm-assert` annotations where appropriate

## Changed

* the `all*` & `nullOr*` methods are now declared on an interface, instead of `@method` annotations.
This interface is linked to the `Assert` class with a `@mixin` annotation. Most IDEs have supported this
for a long time, and you should not lose any autocompletion capabilities. PHPStan has supported this since
version `0.12.20`. This package is marked incompatible (with a composer conflict) with phpstan version prior to that.
If you do not use PHPStan than this does not matter.

## 1.8.0

### Added

* added `Assert::notStartsWith()`
* added `Assert::notEndsWith()`
* added `Assert::inArray()`
* added `@psalm-pure` annotations to pure assertions

### Fixed

* Exception messages of comparisons between `DateTime(Immutable)` objects now display their date & time.
* Custom Exception messages for `Assert::count()` now use the values to render the exception message.

## 1.7.0 (2020-02-14)

### Added

* added `Assert::notFalse()`
* added `Assert::isAOf()`
* added `Assert::isAnyOf()`
* added `Assert::isNotA()`

## 1.6.0 (2019-11-24)

### Added

* added `Assert::validArrayKey()`
* added `Assert::isNonEmptyList()`
* added `Assert::isNonEmptyMap()`
* added `@throws InvalidArgumentException` annotations to all methods that throw.
* added `@psalm-assert` for the list type to the `isList` assertion.

### Fixed

* `ResourceBundle` & `SimpleXMLElement` now pass the `isCountable` assertions.
They are countable, without implementing the `Countable` interface.
* The doc block of `range` now has the proper variables.
* An empty array will now pass `isList` and `isMap`. As it is a valid form of both.
If a non-empty variant is needed, use `isNonEmptyList` or `isNonEmptyMap`.

### Changed

* Removed some `@psalm-assert` annotations, that were 'side effect' assertions See:
  * [#144](https://github.com/webmozart/assert/pull/144)
  * [#145](https://github.com/webmozart/assert/issues/145)
  * [#146](https://github.com/webmozart/assert/pull/146)
  * [#150](https://github.com/webmozart/assert/pull/150)
* If you use Psalm, the minimum version needed is `3.6.0`. Which is enforced through a composer conflict.
If you don't use Psalm, then this has no impact.

## 1.5.0 (2019-08-24)

### Added

* added `Assert::uniqueValues()`
* added `Assert::unicodeLetters()`
* added: `Assert::email()`
* added support for [Psalm](https://github.com/vimeo/psalm), by adding `@psalm-assert` annotations where appropriate.

### Fixed

* `Assert::endsWith()` would not give the correct result when dealing with a multibyte suffix.
* `Assert::length(), minLength, maxLength, lengthBetween` would not give the correct result when dealing with multibyte characters.

**NOTE**: These 2 changes may break your assertions if you relied on the fact that multibyte characters didn't behave correctly.

### Changed

* The names of some variables have been updated to better reflect what they are.
* All function calls are now in their FQN form, slightly increasing performance.
* Tests are now properly ran against HHVM-3.30 and PHP nightly.

### Deprecation

* deprecated `Assert::isTraversable()` in favor of `Assert::isIterable()`
  * This was already done in 1.3.0, but it was only done through a silenced `trigger_error`. It is now annotated as well.

## 1.4.0 (2018-12-25)

### Added

* added `Assert::ip()`
* added `Assert::ipv4()`
* added `Assert::ipv6()`
* added `Assert::notRegex()`
* added `Assert::interfaceExists()`
* added `Assert::isList()`
* added `Assert::isMap()`
* added polyfill for ctype

### Fixed

* Special case when comparing objects implementing `__toString()`

## 1.3.0 (2018-01-29)

### Added

* added `Assert::minCount()`
* added `Assert::maxCount()`
* added `Assert::countBetween()`
* added `Assert::isCountable()`
* added `Assert::notWhitespaceOnly()`
* added `Assert::natural()`
* added `Assert::notContains()`
* added `Assert::isArrayAccessible()`
* added `Assert::isInstanceOfAny()`
* added `Assert::isIterable()`

### Fixed

* `stringNotEmpty` will no longer report "0" is an empty string

### Deprecation

* deprecated `Assert::isTraversable()` in favor of `Assert::isIterable()`

## 1.2.0 (2016-11-23)

 * added `Assert::throws()`
 * added `Assert::count()`
 * added extension point `Assert::reportInvalidArgument()` for custom subclasses

## 1.1.0 (2016-08-09)

 * added `Assert::object()`
 * added `Assert::propertyExists()`
 * added `Assert::propertyNotExists()`
 * added `Assert::methodExists()`
 * added `Assert::methodNotExists()`
 * added `Assert::uuid()`

## 1.0.2 (2015-08-24)

 * integrated Style CI
 * add tests for minimum package dependencies on Travis CI

## 1.0.1 (2015-05-12)

 * added support for PHP 5.3.3

## 1.0.0 (2015-05-12)

 * first stable release

## 1.0.0-beta (2015-03-19)

 * first beta release
Webmozart Assert
================

[![Latest Stable Version](https://poser.pugx.org/webmozart/assert/v/stable.svg)](https://packagist.org/packages/webmozart/assert)
[![Total Downloads](https://poser.pugx.org/webmozart/assert/downloads.svg)](https://packagist.org/packages/webmozart/assert)

This library contains efficient assertions to test the input and output of
your methods. With these assertions, you can greatly reduce the amount of coding
needed to write a safe implementation.

All assertions in the [`Assert`] class throw an `Webmozart\Assert\InvalidArgumentException` if
they fail.

FAQ
---

**What's the difference to [beberlei/assert]?**

This library is heavily inspired by Benjamin Eberlei's wonderful [assert package],
but fixes a usability issue with error messages that can't be fixed there without
breaking backwards compatibility.

This package features usable error messages by default. However, you can also
easily write custom error messages:

```
Assert::string($path, 'The path is expected to be a string. Got: %s');
```

In [beberlei/assert], the ordering of the `%s` placeholders is different for
every assertion. This package, on the contrary, provides consistent placeholder
ordering for all assertions:

* `%s`: The tested value as string, e.g. `"/foo/bar"`.
* `%2$s`, `%3$s`, ...: Additional assertion-specific values, e.g. the
  minimum/maximum length, allowed values, etc.

Check the source code of the assertions to find out details about the additional
available placeholders.

Installation
------------

Use [Composer] to install the package:

```bash
composer require webmozart/assert
```

Example
-------

```php
use Webmozart\Assert\Assert;

class Employee
{
    public function __construct($id)
    {
        Assert::integer($id, 'The employee ID must be an integer. Got: %s');
        Assert::greaterThan($id, 0, 'The employee ID must be a positive integer. Got: %s');
    }
}
```

If you create an employee with an invalid ID, an exception is thrown:

```php
new Employee('foobar');
// => Webmozart\Assert\InvalidArgumentException:
//    The employee ID must be an integer. Got: string

new Employee(-10);
// => Webmozart\Assert\InvalidArgumentException:
//    The employee ID must be a positive integer. Got: -10
```

Assertions
----------

The [`Assert`] class provides the following assertions:

### Type Assertions

Method                                                   | Description
-------------------------------------------------------- | --------------------------------------------------
`string($value, $message = '')`                          | Check that a value is a string
`stringNotEmpty($value, $message = '')`                  | Check that a value is a non-empty string
`integer($value, $message = '')`                         | Check that a value is an integer
`integerish($value, $message = '')`                      | Check that a value casts to an integer
`positiveInteger($value, $message = '')`                 | Check that a value is a positive (non-zero) integer
`float($value, $message = '')`                           | Check that a value is a float
`numeric($value, $message = '')`                         | Check that a value is numeric
`natural($value, $message = '')`                         | Check that a value is a non-negative integer
`boolean($value, $message = '')`                         | Check that a value is a boolean
`scalar($value, $message = '')`                          | Check that a value is a scalar
`object($value, $message = '')`                          | Check that a value is an object
`resource($value, $type = null, $message = '')`          | Check that a value is a resource
`isCallable($value, $message = '')`                      | Check that a value is a callable
`isArray($value, $message = '')`                         | Check that a value is an array
`isTraversable($value, $message = '')`  (deprecated)     | Check that a value is an array or a `\Traversable`
`isIterable($value, $message = '')`                      | Check that a value is an array or a `\Traversable`
`isCountable($value, $message = '')`                     | Check that a value is an array or a `\Countable`
`isInstanceOf($value, $class, $message = '')`            | Check that a value is an `instanceof` a class
`isInstanceOfAny($value, array $classes, $message = '')` | Check that a value is an `instanceof` at least one class on the array of classes
`notInstanceOf($value, $class, $message = '')`           | Check that a value is not an `instanceof` a class
`isAOf($value, $class, $message = '')`                   | Check that a value is of the class or has one of its parents
`isAnyOf($value, array $classes, $message = '')`         | Check that a value is of at least one of the classes or has one of its parents
`isNotA($value, $class, $message = '')`                  | Check that a value is not of the class or has not one of its parents
`isArrayAccessible($value, $message = '')`               | Check that a value can be accessed as an array
`uniqueValues($values, $message = '')`                   | Check that the given array contains unique values

### Comparison Assertions

Method                                          | Description
----------------------------------------------- | ------------------------------------------------------------------
`true($value, $message = '')`                   | Check that a value is `true`
`false($value, $message = '')`                  | Check that a value is `false`
`notFalse($value, $message = '')`               | Check that a value is not `false`
`null($value, $message = '')`                   | Check that a value is `null`
`notNull($value, $message = '')`                | Check that a value is not `null`
`isEmpty($value, $message = '')`                | Check that a value is `empty()`
`notEmpty($value, $message = '')`               | Check that a value is not `empty()`
`eq($value, $value2, $message = '')`            | Check that a value equals another (`==`)
`notEq($value, $value2, $message = '')`         | Check that a value does not equal another (`!=`)
`same($value, $value2, $message = '')`          | Check that a value is identical to another (`===`)
`notSame($value, $value2, $message = '')`       | Check that a value is not identical to another (`!==`)
`greaterThan($value, $value2, $message = '')`   | Check that a value is greater than another
`greaterThanEq($value, $value2, $message = '')` | Check that a value is greater than or equal to another
`lessThan($value, $value2, $message = '')`      | Check that a value is less than another
`lessThanEq($value, $value2, $message = '')`    | Check that a value is less than or equal to another
`range($value, $min, $max, $message = '')`      | Check that a value is within a range
`inArray($value, array $values, $message = '')` | Check that a value is one of a list of values
`oneOf($value, array $values, $message = '')`   | Check that a value is one of a list of values (alias of `inArray`)

### String Assertions

You should check that a value is a string with `Assert::string()` before making
any of the following assertions.

Method                                              | Description
--------------------------------------------------- | -----------------------------------------------------------------
`contains($value, $subString, $message = '')`       | Check that a string contains a substring
`notContains($value, $subString, $message = '')`    | Check that a string does not contain a substring
`startsWith($value, $prefix, $message = '')`        | Check that a string has a prefix
`notStartsWith($value, $prefix, $message = '')`     | Check that a string does not have a prefix
`startsWithLetter($value, $message = '')`           | Check that a string starts with a letter
`endsWith($value, $suffix, $message = '')`          | Check that a string has a suffix
`notEndsWith($value, $suffix, $message = '')`       | Check that a string does not have a suffix
`regex($value, $pattern, $message = '')`            | Check that a string matches a regular expression
`notRegex($value, $pattern, $message = '')`         | Check that a string does not match a regular expression
`unicodeLetters($value, $message = '')`             | Check that a string contains Unicode letters only
`alpha($value, $message = '')`                      | Check that a string contains letters only
`digits($value, $message = '')`                     | Check that a string contains digits only
`alnum($value, $message = '')`                      | Check that a string contains letters and digits only
`lower($value, $message = '')`                      | Check that a string contains lowercase characters only
`upper($value, $message = '')`                      | Check that a string contains uppercase characters only
`length($value, $length, $message = '')`            | Check that a string has a certain number of characters
`minLength($value, $min, $message = '')`            | Check that a string has at least a certain number of characters
`maxLength($value, $max, $message = '')`            | Check that a string has at most a certain number of characters
`lengthBetween($value, $min, $max, $message = '')`  | Check that a string has a length in the given range
`uuid($value, $message = '')`                       | Check that a string is a valid UUID
`ip($value, $message = '')`                         | Check that a string is a valid IP (either IPv4 or IPv6)
`ipv4($value, $message = '')`                       | Check that a string is a valid IPv4
`ipv6($value, $message = '')`                       | Check that a string is a valid IPv6
`email($value, $message = '')`                      | Check that a string is a valid e-mail address
`notWhitespaceOnly($value, $message = '')`          | Check that a string contains at least one non-whitespace character

### File Assertions

Method                              | Description
----------------------------------- | --------------------------------------------------
`fileExists($value, $message = '')` | Check that a value is an existing path
`file($value, $message = '')`       | Check that a value is an existing file
`directory($value, $message = '')`  | Check that a value is an existing directory
`readable($value, $message = '')`   | Check that a value is a readable path
`writable($value, $message = '')`   | Check that a value is a writable path

### Object Assertions

Method                                                | Description
----------------------------------------------------- | --------------------------------------------------
`classExists($value, $message = '')`                  | Check that a value is an existing class name
`subclassOf($value, $class, $message = '')`           | Check that a class is a subclass of another
`interfaceExists($value, $message = '')`              | Check that a value is an existing interface name
`implementsInterface($value, $class, $message = '')`  | Check that a class implements an interface
`propertyExists($value, $property, $message = '')`    | Check that a property exists in a class/object
`propertyNotExists($value, $property, $message = '')` | Check that a property does not exist in a class/object
`methodExists($value, $method, $message = '')`        | Check that a method exists in a class/object
`methodNotExists($value, $method, $message = '')`     | Check that a method does not exist in a class/object

### Array Assertions

Method                                             | Description
-------------------------------------------------- | ------------------------------------------------------------------
`keyExists($array, $key, $message = '')`           | Check that a key exists in an array
`keyNotExists($array, $key, $message = '')`        | Check that a key does not exist in an array
`validArrayKey($key, $message = '')`               | Check that a value is a valid array key (int or string)
`count($array, $number, $message = '')`            | Check that an array contains a specific number of elements
`minCount($array, $min, $message = '')`            | Check that an array contains at least a certain number of elements
`maxCount($array, $max, $message = '')`            | Check that an array contains at most a certain number of elements
`countBetween($array, $min, $max, $message = '')`  | Check that an array has a count in the given range
`isList($array, $message = '')`                    | Check that an array is a non-associative list
`isNonEmptyList($array, $message = '')`            | Check that an array is a non-associative list, and not empty
`isMap($array, $message = '')`                     | Check that an array is associative and has strings as keys
`isNonEmptyMap($array, $message = '')`             | Check that an array is associative and has strings as keys, and is not empty

### Function Assertions

Method                                      | Description
------------------------------------------- | -----------------------------------------------------------------------------------------------------
`throws($closure, $class, $message = '')`   | Check that a function throws a certain exception. Subclasses of the exception class will be accepted.

### Collection Assertions

All of the above assertions can be prefixed with `all*()` to test the contents
of an array or a `\Traversable`:

```php
Assert::allIsInstanceOf($employees, 'Acme\Employee');
```

### Nullable Assertions

All of the above assertions can be prefixed with `nullOr*()` to run the
assertion only if the value is not `null`:

```php
Assert::nullOrString($middleName, 'The middle name must be a string or null. Got: %s');
```

### Extending Assert

The `Assert` class comes with a few methods, which can be overridden to change the class behaviour. You can also extend it to
add your own assertions.

#### Overriding methods

Overriding the following methods in your assertion class allows you to change the behaviour of the assertions:

* `public static function __callStatic($name, $arguments)`
  * This method is used to 'create' the `nullOr` and `all` versions of the assertions.
* `protected static function valueToString($value)`
  * This method is used for error messages, to convert the value to a string value for displaying. You could use this for representing a value object with a `__toString` method for example.
* `protected static function typeToString($value)`
  * This method is used for error messages, to convert a value to a string representing its type.
* `protected static function strlen($value)`
  * This method is used to calculate string length for relevant methods, using the `mb_strlen` if available and useful.
* `protected static function reportInvalidArgument($message)`
  * This method is called when an assertion fails, with the specified error message. Here you can throw your own exception, or log something.

## Static analysis support

Where applicable, assertion functions are annotated to support Psalm's
[Assertion syntax](https://psalm.dev/docs/annotating_code/assertion_syntax/).
A dedicated [PHPStan Plugin](https://github.com/phpstan/phpstan-webmozart-assert) is
required for proper type support.

Authors
-------

* [Bernhard Schussek] a.k.a. [@webmozart]
* [The Community Contributors]

Contribute
----------

Contributions to the package are always welcome!

* Report any bugs or issues you find on the [issue tracker].
* You can grab the source code at the package's [Git repository].

License
-------

All contents of this package are licensed under the [MIT license].

[beberlei/assert]: https://github.com/beberlei/assert
[assert package]: https://github.com/beberlei/assert
[Composer]: https://getcomposer.org
[Bernhard Schussek]: https://webmozarts.com
[The Community Contributors]: https://github.com/webmozart/assert/graphs/contributors
[issue tracker]: https://github.com/webmozart/assert/issues
[Git repository]: https://github.com/webmozart/assert
[@webmozart]: https://twitter.com/webmozart
[MIT license]: LICENSE
[`Assert`]: src/Assert.php
{
    "name": "webmozart\/assert",
    "description": "Assertions to validate method input\/output with nice error messages.",
    "license": "MIT",
    "keywords": [
        "assert",
        "check",
        "validate"
    ],
    "authors": [
        {
            "name": "Bernhard Schussek",
            "email": "bschussek@gmail.com"
        }
    ],
    "require": {
        "php": "^7.2 || ^8.0",
        "ext-ctype": "*",
        "ext-date": "*",
        "ext-filter": "*"
    },
    "suggest": {
        "ext-intl": "",
        "ext-simplexml": "",
        "ext-spl": ""
    },
    "autoload": {
        "psr-4": {
            "_ContaoManager\\Webmozart\\Assert\\": "src\/"
        }
    },
    "autoload-dev": {
        "psr-4": {
            "_ContaoManager\\Webmozart\\Assert\\Bin\\": "bin\/src",
            "_ContaoManager\\Webmozart\\Assert\\Tests\\": "tests\/"
        }
    },
    "extra": {
        "branch-alias": {
            "dev-master": "1.10-dev"
        }
    },
    "scripts": {
        "install-tools": [
            "composer --working-dir=tools\/php-cs-fixer install",
            "composer --working-dir=tools\/phpunit install",
            "composer --working-dir=tools\/psalm install",
            "composer --working-dir=tools\/roave-bc-check install"
        ],
        "bc-check": ".\/tools\/roave-bc-check\/vendor\/bin\/roave-backward-compatibility-check",
        "cs-check": ".\/tools\/php-cs-fixer\/vendor\/bin\/php-cs-fixer check",
        "cs-fix": ".\/tools\/php-cs-fixer\/vendor\/bin\/php-cs-fixer fix",
        "static-analysis": ".\/tools\/psalm\/vendor\/bin\/psalm --threads=4 --root=$(pwd)",
        "test": ".\/tools\/phpunit\/vendor\/bin\/phpunit"
    }
}<?php

namespace _ContaoManager\Webmozart\Assert;

use ArrayAccess;
use Closure;
use Countable;
use Throwable;
/**
 * This trait provides nullOr*, all* and allNullOr* variants of assertion base methods.
 * Do not use this trait directly: it will change, and is not designed for reuse.
 */
trait Mixin
{
    /**
     * @psalm-pure
     *
     * @psalm-assert string|null $value
     *
     * @param mixed  $value
     * @param string $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function nullOrString($value, $message = '')
    {
        null === $value || static::string($value, $message);
    }
    /**
     * @psalm-pure
     *
     * @psalm-assert iterable<string> $value
     *
     * @param mixed  $value
     * @param string $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function allString($value, $message = '')
    {
        static::isIterable($value);
        foreach ($value as $entry) {
            static::string($entry, $message);
        }
    }
    /**
     * @psalm-pure
     *
     * @psalm-assert iterable<string|null> $value
     *
     * @param mixed  $value
     * @param string $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function allNullOrString($value, $message = '')
    {
        static::isIterable($value);
        foreach ($value as $entry) {
            null === $entry || static::string($entry, $message);
        }
    }
    /**
     * @psalm-pure
     *
     * @psalm-assert non-empty-string|null $value
     *
     * @param mixed  $value
     * @param string $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function nullOrStringNotEmpty($value, $message = '')
    {
        null === $value || static::stringNotEmpty($value, $message);
    }
    /**
     * @psalm-pure
     *
     * @psalm-assert iterable<non-empty-string> $value
     *
     * @param mixed  $value
     * @param string $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function allStringNotEmpty($value, $message = '')
    {
        static::isIterable($value);
        foreach ($value as $entry) {
            static::stringNotEmpty($entry, $message);
        }
    }
    /**
     * @psalm-pure
     *
     * @psalm-assert iterable<non-empty-string|null> $value
     *
     * @param mixed  $value
     * @param string $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function allNullOrStringNotEmpty($value, $message = '')
    {
        static::isIterable($value);
        foreach ($value as $entry) {
            null === $entry || static::stringNotEmpty($entry, $message);
        }
    }
    /**
     * @psalm-pure
     *
     * @psalm-assert int|null $value
     *
     * @param mixed  $value
     * @param string $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function nullOrInteger($value, $message = '')
    {
        null === $value || static::integer($value, $message);
    }
    /**
     * @psalm-pure
     *
     * @psalm-assert iterable<int> $value
     *
     * @param mixed  $value
     * @param string $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function allInteger($value, $message = '')
    {
        static::isIterable($value);
        foreach ($value as $entry) {
            static::integer($entry, $message);
        }
    }
    /**
     * @psalm-pure
     *
     * @psalm-assert iterable<int|null> $value
     *
     * @param mixed  $value
     * @param string $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function allNullOrInteger($value, $message = '')
    {
        static::isIterable($value);
        foreach ($value as $entry) {
            null === $entry || static::integer($entry, $message);
        }
    }
    /**
     * @psalm-pure
     *
     * @psalm-assert numeric|null $value
     *
     * @param mixed  $value
     * @param string $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function nullOrIntegerish($value, $message = '')
    {
        null === $value || static::integerish($value, $message);
    }
    /**
     * @psalm-pure
     *
     * @psalm-assert iterable<numeric> $value
     *
     * @param mixed  $value
     * @param string $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function allIntegerish($value, $message = '')
    {
        static::isIterable($value);
        foreach ($value as $entry) {
            static::integerish($entry, $message);
        }
    }
    /**
     * @psalm-pure
     *
     * @psalm-assert iterable<numeric|null> $value
     *
     * @param mixed  $value
     * @param string $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function allNullOrIntegerish($value, $message = '')
    {
        static::isIterable($value);
        foreach ($value as $entry) {
            null === $entry || static::integerish($entry, $message);
        }
    }
    /**
     * @psalm-pure
     *
     * @psalm-assert positive-int|null $value
     *
     * @param mixed  $value
     * @param string $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function nullOrPositiveInteger($value, $message = '')
    {
        null === $value || static::positiveInteger($value, $message);
    }
    /**
     * @psalm-pure
     *
     * @psalm-assert iterable<positive-int> $value
     *
     * @param mixed  $value
     * @param string $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function allPositiveInteger($value, $message = '')
    {
        static::isIterable($value);
        foreach ($value as $entry) {
            static::positiveInteger($entry, $message);
        }
    }
    /**
     * @psalm-pure
     *
     * @psalm-assert iterable<positive-int|null> $value
     *
     * @param mixed  $value
     * @param string $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function allNullOrPositiveInteger($value, $message = '')
    {
        static::isIterable($value);
        foreach ($value as $entry) {
            null === $entry || static::positiveInteger($entry, $message);
        }
    }
    /**
     * @psalm-pure
     *
     * @psalm-assert float|null $value
     *
     * @param mixed  $value
     * @param string $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function nullOrFloat($value, $message = '')
    {
        null === $value || static::float($value, $message);
    }
    /**
     * @psalm-pure
     *
     * @psalm-assert iterable<float> $value
     *
     * @param mixed  $value
     * @param string $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function allFloat($value, $message = '')
    {
        static::isIterable($value);
        foreach ($value as $entry) {
            static::float($entry, $message);
        }
    }
    /**
     * @psalm-pure
     *
     * @psalm-assert iterable<float|null> $value
     *
     * @param mixed  $value
     * @param string $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function allNullOrFloat($value, $message = '')
    {
        static::isIterable($value);
        foreach ($value as $entry) {
            null === $entry || static::float($entry, $message);
        }
    }
    /**
     * @psalm-pure
     *
     * @psalm-assert numeric|null $value
     *
     * @param mixed  $value
     * @param string $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function nullOrNumeric($value, $message = '')
    {
        null === $value || static::numeric($value, $message);
    }
    /**
     * @psalm-pure
     *
     * @psalm-assert iterable<numeric> $value
     *
     * @param mixed  $value
     * @param string $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function allNumeric($value, $message = '')
    {
        static::isIterable($value);
        foreach ($value as $entry) {
            static::numeric($entry, $message);
        }
    }
    /**
     * @psalm-pure
     *
     * @psalm-assert iterable<numeric|null> $value
     *
     * @param mixed  $value
     * @param string $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function allNullOrNumeric($value, $message = '')
    {
        static::isIterable($value);
        foreach ($value as $entry) {
            null === $entry || static::numeric($entry, $message);
        }
    }
    /**
     * @psalm-pure
     *
     * @psalm-assert positive-int|0|null $value
     *
     * @param mixed  $value
     * @param string $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function nullOrNatural($value, $message = '')
    {
        null === $value || static::natural($value, $message);
    }
    /**
     * @psalm-pure
     *
     * @psalm-assert iterable<positive-int|0> $value
     *
     * @param mixed  $value
     * @param string $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function allNatural($value, $message = '')
    {
        static::isIterable($value);
        foreach ($value as $entry) {
            static::natural($entry, $message);
        }
    }
    /**
     * @psalm-pure
     *
     * @psalm-assert iterable<positive-int|0|null> $value
     *
     * @param mixed  $value
     * @param string $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function allNullOrNatural($value, $message = '')
    {
        static::isIterable($value);
        foreach ($value as $entry) {
            null === $entry || static::natural($entry, $message);
        }
    }
    /**
     * @psalm-pure
     *
     * @psalm-assert bool|null $value
     *
     * @param mixed  $value
     * @param string $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function nullOrBoolean($value, $message = '')
    {
        null === $value || static::boolean($value, $message);
    }
    /**
     * @psalm-pure
     *
     * @psalm-assert iterable<bool> $value
     *
     * @param mixed  $value
     * @param string $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function allBoolean($value, $message = '')
    {
        static::isIterable($value);
        foreach ($value as $entry) {
            static::boolean($entry, $message);
        }
    }
    /**
     * @psalm-pure
     *
     * @psalm-assert iterable<bool|null> $value
     *
     * @param mixed  $value
     * @param string $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function allNullOrBoolean($value, $message = '')
    {
        static::isIterable($value);
        foreach ($value as $entry) {
            null === $entry || static::boolean($entry, $message);
        }
    }
    /**
     * @psalm-pure
     *
     * @psalm-assert scalar|null $value
     *
     * @param mixed  $value
     * @param string $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function nullOrScalar($value, $message = '')
    {
        null === $value || static::scalar($value, $message);
    }
    /**
     * @psalm-pure
     *
     * @psalm-assert iterable<scalar> $value
     *
     * @param mixed  $value
     * @param string $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function allScalar($value, $message = '')
    {
        static::isIterable($value);
        foreach ($value as $entry) {
            static::scalar($entry, $message);
        }
    }
    /**
     * @psalm-pure
     *
     * @psalm-assert iterable<scalar|null> $value
     *
     * @param mixed  $value
     * @param string $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function allNullOrScalar($value, $message = '')
    {
        static::isIterable($value);
        foreach ($value as $entry) {
            null === $entry || static::scalar($entry, $message);
        }
    }
    /**
     * @psalm-pure
     *
     * @psalm-assert object|null $value
     *
     * @param mixed  $value
     * @param string $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function nullOrObject($value, $message = '')
    {
        null === $value || static::object($value, $message);
    }
    /**
     * @psalm-pure
     *
     * @psalm-assert iterable<object> $value
     *
     * @param mixed  $value
     * @param string $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function allObject($value, $message = '')
    {
        static::isIterable($value);
        foreach ($value as $entry) {
            static::object($entry, $message);
        }
    }
    /**
     * @psalm-pure
     *
     * @psalm-assert iterable<object|null> $value
     *
     * @param mixed  $value
     * @param string $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function allNullOrObject($value, $message = '')
    {
        static::isIterable($value);
        foreach ($value as $entry) {
            null === $entry || static::object($entry, $message);
        }
    }
    /**
     * @psalm-pure
     *
     * @psalm-assert resource|null $value
     *
     * @param mixed       $value
     * @param string|null $type    type of resource this should be. @see https://www.php.net/manual/en/function.get-resource-type.php
     * @param string      $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function nullOrResource($value, $type = null, $message = '')
    {
        null === $value || static::resource($value, $type, $message);
    }
    /**
     * @psalm-pure
     *
     * @psalm-assert iterable<resource> $value
     *
     * @param mixed       $value
     * @param string|null $type    type of resource this should be. @see https://www.php.net/manual/en/function.get-resource-type.php
     * @param string      $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function allResource($value, $type = null, $message = '')
    {
        static::isIterable($value);
        foreach ($value as $entry) {
            static::resource($entry, $type, $message);
        }
    }
    /**
     * @psalm-pure
     *
     * @psalm-assert iterable<resource|null> $value
     *
     * @param mixed       $value
     * @param string|null $type    type of resource this should be. @see https://www.php.net/manual/en/function.get-resource-type.php
     * @param string      $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function allNullOrResource($value, $type = null, $message = '')
    {
        static::isIterable($value);
        foreach ($value as $entry) {
            null === $entry || static::resource($entry, $type, $message);
        }
    }
    /**
     * @psalm-pure
     *
     * @psalm-assert callable|null $value
     *
     * @param mixed  $value
     * @param string $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function nullOrIsCallable($value, $message = '')
    {
        null === $value || static::isCallable($value, $message);
    }
    /**
     * @psalm-pure
     *
     * @psalm-assert iterable<callable> $value
     *
     * @param mixed  $value
     * @param string $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function allIsCallable($value, $message = '')
    {
        static::isIterable($value);
        foreach ($value as $entry) {
            static::isCallable($entry, $message);
        }
    }
    /**
     * @psalm-pure
     *
     * @psalm-assert iterable<callable|null> $value
     *
     * @param mixed  $value
     * @param string $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function allNullOrIsCallable($value, $message = '')
    {
        static::isIterable($value);
        foreach ($value as $entry) {
            null === $entry || static::isCallable($entry, $message);
        }
    }
    /**
     * @psalm-pure
     *
     * @psalm-assert array|null $value
     *
     * @param mixed  $value
     * @param string $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function nullOrIsArray($value, $message = '')
    {
        null === $value || static::isArray($value, $message);
    }
    /**
     * @psalm-pure
     *
     * @psalm-assert iterable<array> $value
     *
     * @param mixed  $value
     * @param string $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function allIsArray($value, $message = '')
    {
        static::isIterable($value);
        foreach ($value as $entry) {
            static::isArray($entry, $message);
        }
    }
    /**
     * @psalm-pure
     *
     * @psalm-assert iterable<array|null> $value
     *
     * @param mixed  $value
     * @param string $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function allNullOrIsArray($value, $message = '')
    {
        static::isIterable($value);
        foreach ($value as $entry) {
            null === $entry || static::isArray($entry, $message);
        }
    }
    /**
     * @psalm-pure
     *
     * @psalm-assert iterable|null $value
     *
     * @deprecated use "isIterable" or "isInstanceOf" instead
     *
     * @param mixed  $value
     * @param string $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function nullOrIsTraversable($value, $message = '')
    {
        null === $value || static::isTraversable($value, $message);
    }
    /**
     * @psalm-pure
     *
     * @psalm-assert iterable<iterable> $value
     *
     * @deprecated use "isIterable" or "isInstanceOf" instead
     *
     * @param mixed  $value
     * @param string $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function allIsTraversable($value, $message = '')
    {
        static::isIterable($value);
        foreach ($value as $entry) {
            static::isTraversable($entry, $message);
        }
    }
    /**
     * @psalm-pure
     *
     * @psalm-assert iterable<iterable|null> $value
     *
     * @deprecated use "isIterable" or "isInstanceOf" instead
     *
     * @param mixed  $value
     * @param string $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function allNullOrIsTraversable($value, $message = '')
    {
        static::isIterable($value);
        foreach ($value as $entry) {
            null === $entry || static::isTraversable($entry, $message);
        }
    }
    /**
     * @psalm-pure
     *
     * @psalm-assert array|ArrayAccess|null $value
     *
     * @param mixed  $value
     * @param string $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function nullOrIsArrayAccessible($value, $message = '')
    {
        null === $value || static::isArrayAccessible($value, $message);
    }
    /**
     * @psalm-pure
     *
     * @psalm-assert iterable<array|ArrayAccess> $value
     *
     * @param mixed  $value
     * @param string $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function allIsArrayAccessible($value, $message = '')
    {
        static::isIterable($value);
        foreach ($value as $entry) {
            static::isArrayAccessible($entry, $message);
        }
    }
    /**
     * @psalm-pure
     *
     * @psalm-assert iterable<array|ArrayAccess|null> $value
     *
     * @param mixed  $value
     * @param string $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function allNullOrIsArrayAccessible($value, $message = '')
    {
        static::isIterable($value);
        foreach ($value as $entry) {
            null === $entry || static::isArrayAccessible($entry, $message);
        }
    }
    /**
     * @psalm-pure
     *
     * @psalm-assert countable|null $value
     *
     * @param mixed  $value
     * @param string $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function nullOrIsCountable($value, $message = '')
    {
        null === $value || static::isCountable($value, $message);
    }
    /**
     * @psalm-pure
     *
     * @psalm-assert iterable<countable> $value
     *
     * @param mixed  $value
     * @param string $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function allIsCountable($value, $message = '')
    {
        static::isIterable($value);
        foreach ($value as $entry) {
            static::isCountable($entry, $message);
        }
    }
    /**
     * @psalm-pure
     *
     * @psalm-assert iterable<countable|null> $value
     *
     * @param mixed  $value
     * @param string $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function allNullOrIsCountable($value, $message = '')
    {
        static::isIterable($value);
        foreach ($value as $entry) {
            null === $entry || static::isCountable($entry, $message);
        }
    }
    /**
     * @psalm-pure
     *
     * @psalm-assert iterable|null $value
     *
     * @param mixed  $value
     * @param string $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function nullOrIsIterable($value, $message = '')
    {
        null === $value || static::isIterable($value, $message);
    }
    /**
     * @psalm-pure
     *
     * @psalm-assert iterable<iterable> $value
     *
     * @param mixed  $value
     * @param string $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function allIsIterable($value, $message = '')
    {
        static::isIterable($value);
        foreach ($value as $entry) {
            static::isIterable($entry, $message);
        }
    }
    /**
     * @psalm-pure
     *
     * @psalm-assert iterable<iterable|null> $value
     *
     * @param mixed  $value
     * @param string $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function allNullOrIsIterable($value, $message = '')
    {
        static::isIterable($value);
        foreach ($value as $entry) {
            null === $entry || static::isIterable($entry, $message);
        }
    }
    /**
     * @psalm-pure
     *
     * @psalm-template ExpectedType of object
     * @psalm-param class-string<ExpectedType> $class
     * @psalm-assert ExpectedType|null $value
     *
     * @param mixed         $value
     * @param string|object $class
     * @param string        $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function nullOrIsInstanceOf($value, $class, $message = '')
    {
        null === $value || static::isInstanceOf($value, $class, $message);
    }
    /**
     * @psalm-pure
     *
     * @psalm-template ExpectedType of object
     * @psalm-param class-string<ExpectedType> $class
     * @psalm-assert iterable<ExpectedType> $value
     *
     * @param mixed         $value
     * @param string|object $class
     * @param string        $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function allIsInstanceOf($value, $class, $message = '')
    {
        static::isIterable($value);
        foreach ($value as $entry) {
            static::isInstanceOf($entry, $class, $message);
        }
    }
    /**
     * @psalm-pure
     *
     * @psalm-template ExpectedType of object
     * @psalm-param class-string<ExpectedType> $class
     * @psalm-assert iterable<ExpectedType|null> $value
     *
     * @param mixed         $value
     * @param string|object $class
     * @param string        $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function allNullOrIsInstanceOf($value, $class, $message = '')
    {
        static::isIterable($value);
        foreach ($value as $entry) {
            null === $entry || static::isInstanceOf($entry, $class, $message);
        }
    }
    /**
     * @psalm-pure
     *
     * @psalm-template ExpectedType of object
     * @psalm-param class-string<ExpectedType> $class
     *
     * @param mixed         $value
     * @param string|object $class
     * @param string        $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function nullOrNotInstanceOf($value, $class, $message = '')
    {
        null === $value || static::notInstanceOf($value, $class, $message);
    }
    /**
     * @psalm-pure
     *
     * @psalm-template ExpectedType of object
     * @psalm-param class-string<ExpectedType> $class
     *
     * @param mixed         $value
     * @param string|object $class
     * @param string        $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function allNotInstanceOf($value, $class, $message = '')
    {
        static::isIterable($value);
        foreach ($value as $entry) {
            static::notInstanceOf($entry, $class, $message);
        }
    }
    /**
     * @psalm-pure
     *
     * @psalm-template ExpectedType of object
     * @psalm-param class-string<ExpectedType> $class
     * @psalm-assert iterable<!ExpectedType|null> $value
     *
     * @param mixed         $value
     * @param string|object $class
     * @param string        $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function allNullOrNotInstanceOf($value, $class, $message = '')
    {
        static::isIterable($value);
        foreach ($value as $entry) {
            null === $entry || static::notInstanceOf($entry, $class, $message);
        }
    }
    /**
     * @psalm-pure
     *
     * @psalm-param array<class-string> $classes
     *
     * @param mixed                $value
     * @param array<object|string> $classes
     * @param string               $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function nullOrIsInstanceOfAny($value, $classes, $message = '')
    {
        null === $value || static::isInstanceOfAny($value, $classes, $message);
    }
    /**
     * @psalm-pure
     *
     * @psalm-param array<class-string> $classes
     *
     * @param mixed                $value
     * @param array<object|string> $classes
     * @param string               $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function allIsInstanceOfAny($value, $classes, $message = '')
    {
        static::isIterable($value);
        foreach ($value as $entry) {
            static::isInstanceOfAny($entry, $classes, $message);
        }
    }
    /**
     * @psalm-pure
     *
     * @psalm-param array<class-string> $classes
     *
     * @param mixed                $value
     * @param array<object|string> $classes
     * @param string               $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function allNullOrIsInstanceOfAny($value, $classes, $message = '')
    {
        static::isIterable($value);
        foreach ($value as $entry) {
            null === $entry || static::isInstanceOfAny($entry, $classes, $message);
        }
    }
    /**
     * @psalm-pure
     *
     * @psalm-template ExpectedType of object
     * @psalm-param class-string<ExpectedType> $class
     * @psalm-assert ExpectedType|class-string<ExpectedType>|null $value
     *
     * @param object|string|null $value
     * @param string             $class
     * @param string             $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function nullOrIsAOf($value, $class, $message = '')
    {
        null === $value || static::isAOf($value, $class, $message);
    }
    /**
     * @psalm-pure
     *
     * @psalm-template ExpectedType of object
     * @psalm-param class-string<ExpectedType> $class
     * @psalm-assert iterable<ExpectedType|class-string<ExpectedType>> $value
     *
     * @param iterable<object|string> $value
     * @param string                  $class
     * @param string                  $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function allIsAOf($value, $class, $message = '')
    {
        static::isIterable($value);
        foreach ($value as $entry) {
            static::isAOf($entry, $class, $message);
        }
    }
    /**
     * @psalm-pure
     *
     * @psalm-template ExpectedType of object
     * @psalm-param class-string<ExpectedType> $class
     * @psalm-assert iterable<ExpectedType|class-string<ExpectedType>|null> $value
     *
     * @param iterable<object|string|null> $value
     * @param string                       $class
     * @param string                       $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function allNullOrIsAOf($value, $class, $message = '')
    {
        static::isIterable($value);
        foreach ($value as $entry) {
            null === $entry || static::isAOf($entry, $class, $message);
        }
    }
    /**
     * @psalm-pure
     *
     * @psalm-template UnexpectedType of object
     * @psalm-param class-string<UnexpectedType> $class
     *
     * @param object|string|null $value
     * @param string             $class
     * @param string             $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function nullOrIsNotA($value, $class, $message = '')
    {
        null === $value || static::isNotA($value, $class, $message);
    }
    /**
     * @psalm-pure
     *
     * @psalm-template UnexpectedType of object
     * @psalm-param class-string<UnexpectedType> $class
     *
     * @param iterable<object|string> $value
     * @param string                  $class
     * @param string                  $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function allIsNotA($value, $class, $message = '')
    {
        static::isIterable($value);
        foreach ($value as $entry) {
            static::isNotA($entry, $class, $message);
        }
    }
    /**
     * @psalm-pure
     *
     * @psalm-template UnexpectedType of object
     * @psalm-param class-string<UnexpectedType> $class
     * @psalm-assert iterable<!UnexpectedType|null> $value
     * @psalm-assert iterable<!class-string<UnexpectedType>|null> $value
     *
     * @param iterable<object|string|null> $value
     * @param string                       $class
     * @param string                       $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function allNullOrIsNotA($value, $class, $message = '')
    {
        static::isIterable($value);
        foreach ($value as $entry) {
            null === $entry || static::isNotA($entry, $class, $message);
        }
    }
    /**
     * @psalm-pure
     *
     * @psalm-param array<class-string> $classes
     *
     * @param object|string|null $value
     * @param string[]           $classes
     * @param string             $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function nullOrIsAnyOf($value, $classes, $message = '')
    {
        null === $value || static::isAnyOf($value, $classes, $message);
    }
    /**
     * @psalm-pure
     *
     * @psalm-param array<class-string> $classes
     *
     * @param iterable<object|string> $value
     * @param string[]                $classes
     * @param string                  $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function allIsAnyOf($value, $classes, $message = '')
    {
        static::isIterable($value);
        foreach ($value as $entry) {
            static::isAnyOf($entry, $classes, $message);
        }
    }
    /**
     * @psalm-pure
     *
     * @psalm-param array<class-string> $classes
     *
     * @param iterable<object|string|null> $value
     * @param string[]                     $classes
     * @param string                       $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function allNullOrIsAnyOf($value, $classes, $message = '')
    {
        static::isIterable($value);
        foreach ($value as $entry) {
            null === $entry || static::isAnyOf($entry, $classes, $message);
        }
    }
    /**
     * @psalm-pure
     *
     * @psalm-assert empty $value
     *
     * @param mixed  $value
     * @param string $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function nullOrIsEmpty($value, $message = '')
    {
        null === $value || static::isEmpty($value, $message);
    }
    /**
     * @psalm-pure
     *
     * @psalm-assert iterable<empty> $value
     *
     * @param mixed  $value
     * @param string $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function allIsEmpty($value, $message = '')
    {
        static::isIterable($value);
        foreach ($value as $entry) {
            static::isEmpty($entry, $message);
        }
    }
    /**
     * @psalm-pure
     *
     * @psalm-assert iterable<empty|null> $value
     *
     * @param mixed  $value
     * @param string $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function allNullOrIsEmpty($value, $message = '')
    {
        static::isIterable($value);
        foreach ($value as $entry) {
            null === $entry || static::isEmpty($entry, $message);
        }
    }
    /**
     * @psalm-pure
     *
     * @param mixed  $value
     * @param string $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function nullOrNotEmpty($value, $message = '')
    {
        null === $value || static::notEmpty($value, $message);
    }
    /**
     * @psalm-pure
     *
     * @param mixed  $value
     * @param string $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function allNotEmpty($value, $message = '')
    {
        static::isIterable($value);
        foreach ($value as $entry) {
            static::notEmpty($entry, $message);
        }
    }
    /**
     * @psalm-pure
     *
     * @psalm-assert iterable<!empty|null> $value
     *
     * @param mixed  $value
     * @param string $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function allNullOrNotEmpty($value, $message = '')
    {
        static::isIterable($value);
        foreach ($value as $entry) {
            null === $entry || static::notEmpty($entry, $message);
        }
    }
    /**
     * @psalm-pure
     *
     * @psalm-assert iterable<null> $value
     *
     * @param mixed  $value
     * @param string $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function allNull($value, $message = '')
    {
        static::isIterable($value);
        foreach ($value as $entry) {
            static::null($entry, $message);
        }
    }
    /**
     * @psalm-pure
     *
     * @param mixed  $value
     * @param string $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function allNotNull($value, $message = '')
    {
        static::isIterable($value);
        foreach ($value as $entry) {
            static::notNull($entry, $message);
        }
    }
    /**
     * @psalm-pure
     *
     * @psalm-assert true|null $value
     *
     * @param mixed  $value
     * @param string $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function nullOrTrue($value, $message = '')
    {
        null === $value || static::true($value, $message);
    }
    /**
     * @psalm-pure
     *
     * @psalm-assert iterable<true> $value
     *
     * @param mixed  $value
     * @param string $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function allTrue($value, $message = '')
    {
        static::isIterable($value);
        foreach ($value as $entry) {
            static::true($entry, $message);
        }
    }
    /**
     * @psalm-pure
     *
     * @psalm-assert iterable<true|null> $value
     *
     * @param mixed  $value
     * @param string $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function allNullOrTrue($value, $message = '')
    {
        static::isIterable($value);
        foreach ($value as $entry) {
            null === $entry || static::true($entry, $message);
        }
    }
    /**
     * @psalm-pure
     *
     * @psalm-assert false|null $value
     *
     * @param mixed  $value
     * @param string $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function nullOrFalse($value, $message = '')
    {
        null === $value || static::false($value, $message);
    }
    /**
     * @psalm-pure
     *
     * @psalm-assert iterable<false> $value
     *
     * @param mixed  $value
     * @param string $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function allFalse($value, $message = '')
    {
        static::isIterable($value);
        foreach ($value as $entry) {
            static::false($entry, $message);
        }
    }
    /**
     * @psalm-pure
     *
     * @psalm-assert iterable<false|null> $value
     *
     * @param mixed  $value
     * @param string $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function allNullOrFalse($value, $message = '')
    {
        static::isIterable($value);
        foreach ($value as $entry) {
            null === $entry || static::false($entry, $message);
        }
    }
    /**
     * @psalm-pure
     *
     * @param mixed  $value
     * @param string $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function nullOrNotFalse($value, $message = '')
    {
        null === $value || static::notFalse($value, $message);
    }
    /**
     * @psalm-pure
     *
     * @param mixed  $value
     * @param string $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function allNotFalse($value, $message = '')
    {
        static::isIterable($value);
        foreach ($value as $entry) {
            static::notFalse($entry, $message);
        }
    }
    /**
     * @psalm-pure
     *
     * @psalm-assert iterable<!false|null> $value
     *
     * @param mixed  $value
     * @param string $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function allNullOrNotFalse($value, $message = '')
    {
        static::isIterable($value);
        foreach ($value as $entry) {
            null === $entry || static::notFalse($entry, $message);
        }
    }
    /**
     * @param mixed  $value
     * @param string $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function nullOrIp($value, $message = '')
    {
        null === $value || static::ip($value, $message);
    }
    /**
     * @param mixed  $value
     * @param string $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function allIp($value, $message = '')
    {
        static::isIterable($value);
        foreach ($value as $entry) {
            static::ip($entry, $message);
        }
    }
    /**
     * @param mixed  $value
     * @param string $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function allNullOrIp($value, $message = '')
    {
        static::isIterable($value);
        foreach ($value as $entry) {
            null === $entry || static::ip($entry, $message);
        }
    }
    /**
     * @param mixed  $value
     * @param string $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function nullOrIpv4($value, $message = '')
    {
        null === $value || static::ipv4($value, $message);
    }
    /**
     * @param mixed  $value
     * @param string $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function allIpv4($value, $message = '')
    {
        static::isIterable($value);
        foreach ($value as $entry) {
            static::ipv4($entry, $message);
        }
    }
    /**
     * @param mixed  $value
     * @param string $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function allNullOrIpv4($value, $message = '')
    {
        static::isIterable($value);
        foreach ($value as $entry) {
            null === $entry || static::ipv4($entry, $message);
        }
    }
    /**
     * @param mixed  $value
     * @param string $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function nullOrIpv6($value, $message = '')
    {
        null === $value || static::ipv6($value, $message);
    }
    /**
     * @param mixed  $value
     * @param string $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function allIpv6($value, $message = '')
    {
        static::isIterable($value);
        foreach ($value as $entry) {
            static::ipv6($entry, $message);
        }
    }
    /**
     * @param mixed  $value
     * @param string $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function allNullOrIpv6($value, $message = '')
    {
        static::isIterable($value);
        foreach ($value as $entry) {
            null === $entry || static::ipv6($entry, $message);
        }
    }
    /**
     * @param mixed  $value
     * @param string $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function nullOrEmail($value, $message = '')
    {
        null === $value || static::email($value, $message);
    }
    /**
     * @param mixed  $value
     * @param string $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function allEmail($value, $message = '')
    {
        static::isIterable($value);
        foreach ($value as $entry) {
            static::email($entry, $message);
        }
    }
    /**
     * @param mixed  $value
     * @param string $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function allNullOrEmail($value, $message = '')
    {
        static::isIterable($value);
        foreach ($value as $entry) {
            null === $entry || static::email($entry, $message);
        }
    }
    /**
     * @param array|null $values
     * @param string     $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function nullOrUniqueValues($values, $message = '')
    {
        null === $values || static::uniqueValues($values, $message);
    }
    /**
     * @param iterable<array> $values
     * @param string          $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function allUniqueValues($values, $message = '')
    {
        static::isIterable($values);
        foreach ($values as $entry) {
            static::uniqueValues($entry, $message);
        }
    }
    /**
     * @param iterable<array|null> $values
     * @param string               $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function allNullOrUniqueValues($values, $message = '')
    {
        static::isIterable($values);
        foreach ($values as $entry) {
            null === $entry || static::uniqueValues($entry, $message);
        }
    }
    /**
     * @param mixed  $value
     * @param mixed  $expect
     * @param string $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function nullOrEq($value, $expect, $message = '')
    {
        null === $value || static::eq($value, $expect, $message);
    }
    /**
     * @param mixed  $value
     * @param mixed  $expect
     * @param string $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function allEq($value, $expect, $message = '')
    {
        static::isIterable($value);
        foreach ($value as $entry) {
            static::eq($entry, $expect, $message);
        }
    }
    /**
     * @param mixed  $value
     * @param mixed  $expect
     * @param string $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function allNullOrEq($value, $expect, $message = '')
    {
        static::isIterable($value);
        foreach ($value as $entry) {
            null === $entry || static::eq($entry, $expect, $message);
        }
    }
    /**
     * @param mixed  $value
     * @param mixed  $expect
     * @param string $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function nullOrNotEq($value, $expect, $message = '')
    {
        null === $value || static::notEq($value, $expect, $message);
    }
    /**
     * @param mixed  $value
     * @param mixed  $expect
     * @param string $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function allNotEq($value, $expect, $message = '')
    {
        static::isIterable($value);
        foreach ($value as $entry) {
            static::notEq($entry, $expect, $message);
        }
    }
    /**
     * @param mixed  $value
     * @param mixed  $expect
     * @param string $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function allNullOrNotEq($value, $expect, $message = '')
    {
        static::isIterable($value);
        foreach ($value as $entry) {
            null === $entry || static::notEq($entry, $expect, $message);
        }
    }
    /**
     * @psalm-pure
     *
     * @param mixed  $value
     * @param mixed  $expect
     * @param string $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function nullOrSame($value, $expect, $message = '')
    {
        null === $value || static::same($value, $expect, $message);
    }
    /**
     * @psalm-pure
     *
     * @param mixed  $value
     * @param mixed  $expect
     * @param string $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function allSame($value, $expect, $message = '')
    {
        static::isIterable($value);
        foreach ($value as $entry) {
            static::same($entry, $expect, $message);
        }
    }
    /**
     * @psalm-pure
     *
     * @param mixed  $value
     * @param mixed  $expect
     * @param string $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function allNullOrSame($value, $expect, $message = '')
    {
        static::isIterable($value);
        foreach ($value as $entry) {
            null === $entry || static::same($entry, $expect, $message);
        }
    }
    /**
     * @psalm-pure
     *
     * @param mixed  $value
     * @param mixed  $expect
     * @param string $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function nullOrNotSame($value, $expect, $message = '')
    {
        null === $value || static::notSame($value, $expect, $message);
    }
    /**
     * @psalm-pure
     *
     * @param mixed  $value
     * @param mixed  $expect
     * @param string $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function allNotSame($value, $expect, $message = '')
    {
        static::isIterable($value);
        foreach ($value as $entry) {
            static::notSame($entry, $expect, $message);
        }
    }
    /**
     * @psalm-pure
     *
     * @param mixed  $value
     * @param mixed  $expect
     * @param string $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function allNullOrNotSame($value, $expect, $message = '')
    {
        static::isIterable($value);
        foreach ($value as $entry) {
            null === $entry || static::notSame($entry, $expect, $message);
        }
    }
    /**
     * @psalm-pure
     *
     * @param mixed  $value
     * @param mixed  $limit
     * @param string $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function nullOrGreaterThan($value, $limit, $message = '')
    {
        null === $value || static::greaterThan($value, $limit, $message);
    }
    /**
     * @psalm-pure
     *
     * @param mixed  $value
     * @param mixed  $limit
     * @param string $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function allGreaterThan($value, $limit, $message = '')
    {
        static::isIterable($value);
        foreach ($value as $entry) {
            static::greaterThan($entry, $limit, $message);
        }
    }
    /**
     * @psalm-pure
     *
     * @param mixed  $value
     * @param mixed  $limit
     * @param string $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function allNullOrGreaterThan($value, $limit, $message = '')
    {
        static::isIterable($value);
        foreach ($value as $entry) {
            null === $entry || static::greaterThan($entry, $limit, $message);
        }
    }
    /**
     * @psalm-pure
     *
     * @param mixed  $value
     * @param mixed  $limit
     * @param string $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function nullOrGreaterThanEq($value, $limit, $message = '')
    {
        null === $value || static::greaterThanEq($value, $limit, $message);
    }
    /**
     * @psalm-pure
     *
     * @param mixed  $value
     * @param mixed  $limit
     * @param string $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function allGreaterThanEq($value, $limit, $message = '')
    {
        static::isIterable($value);
        foreach ($value as $entry) {
            static::greaterThanEq($entry, $limit, $message);
        }
    }
    /**
     * @psalm-pure
     *
     * @param mixed  $value
     * @param mixed  $limit
     * @param string $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function allNullOrGreaterThanEq($value, $limit, $message = '')
    {
        static::isIterable($value);
        foreach ($value as $entry) {
            null === $entry || static::greaterThanEq($entry, $limit, $message);
        }
    }
    /**
     * @psalm-pure
     *
     * @param mixed  $value
     * @param mixed  $limit
     * @param string $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function nullOrLessThan($value, $limit, $message = '')
    {
        null === $value || static::lessThan($value, $limit, $message);
    }
    /**
     * @psalm-pure
     *
     * @param mixed  $value
     * @param mixed  $limit
     * @param string $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function allLessThan($value, $limit, $message = '')
    {
        static::isIterable($value);
        foreach ($value as $entry) {
            static::lessThan($entry, $limit, $message);
        }
    }
    /**
     * @psalm-pure
     *
     * @param mixed  $value
     * @param mixed  $limit
     * @param string $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function allNullOrLessThan($value, $limit, $message = '')
    {
        static::isIterable($value);
        foreach ($value as $entry) {
            null === $entry || static::lessThan($entry, $limit, $message);
        }
    }
    /**
     * @psalm-pure
     *
     * @param mixed  $value
     * @param mixed  $limit
     * @param string $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function nullOrLessThanEq($value, $limit, $message = '')
    {
        null === $value || static::lessThanEq($value, $limit, $message);
    }
    /**
     * @psalm-pure
     *
     * @param mixed  $value
     * @param mixed  $limit
     * @param string $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function allLessThanEq($value, $limit, $message = '')
    {
        static::isIterable($value);
        foreach ($value as $entry) {
            static::lessThanEq($entry, $limit, $message);
        }
    }
    /**
     * @psalm-pure
     *
     * @param mixed  $value
     * @param mixed  $limit
     * @param string $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function allNullOrLessThanEq($value, $limit, $message = '')
    {
        static::isIterable($value);
        foreach ($value as $entry) {
            null === $entry || static::lessThanEq($entry, $limit, $message);
        }
    }
    /**
     * @psalm-pure
     *
     * @param mixed  $value
     * @param mixed  $min
     * @param mixed  $max
     * @param string $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function nullOrRange($value, $min, $max, $message = '')
    {
        null === $value || static::range($value, $min, $max, $message);
    }
    /**
     * @psalm-pure
     *
     * @param mixed  $value
     * @param mixed  $min
     * @param mixed  $max
     * @param string $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function allRange($value, $min, $max, $message = '')
    {
        static::isIterable($value);
        foreach ($value as $entry) {
            static::range($entry, $min, $max, $message);
        }
    }
    /**
     * @psalm-pure
     *
     * @param mixed  $value
     * @param mixed  $min
     * @param mixed  $max
     * @param string $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function allNullOrRange($value, $min, $max, $message = '')
    {
        static::isIterable($value);
        foreach ($value as $entry) {
            null === $entry || static::range($entry, $min, $max, $message);
        }
    }
    /**
     * @psalm-pure
     *
     * @param mixed  $value
     * @param array  $values
     * @param string $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function nullOrOneOf($value, $values, $message = '')
    {
        null === $value || static::oneOf($value, $values, $message);
    }
    /**
     * @psalm-pure
     *
     * @param mixed  $value
     * @param array  $values
     * @param string $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function allOneOf($value, $values, $message = '')
    {
        static::isIterable($value);
        foreach ($value as $entry) {
            static::oneOf($entry, $values, $message);
        }
    }
    /**
     * @psalm-pure
     *
     * @param mixed  $value
     * @param array  $values
     * @param string $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function allNullOrOneOf($value, $values, $message = '')
    {
        static::isIterable($value);
        foreach ($value as $entry) {
            null === $entry || static::oneOf($entry, $values, $message);
        }
    }
    /**
     * @psalm-pure
     *
     * @param mixed  $value
     * @param array  $values
     * @param string $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function nullOrInArray($value, $values, $message = '')
    {
        null === $value || static::inArray($value, $values, $message);
    }
    /**
     * @psalm-pure
     *
     * @param mixed  $value
     * @param array  $values
     * @param string $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function allInArray($value, $values, $message = '')
    {
        static::isIterable($value);
        foreach ($value as $entry) {
            static::inArray($entry, $values, $message);
        }
    }
    /**
     * @psalm-pure
     *
     * @param mixed  $value
     * @param array  $values
     * @param string $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function allNullOrInArray($value, $values, $message = '')
    {
        static::isIterable($value);
        foreach ($value as $entry) {
            null === $entry || static::inArray($entry, $values, $message);
        }
    }
    /**
     * @psalm-pure
     *
     * @param string|null $value
     * @param string      $subString
     * @param string      $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function nullOrContains($value, $subString, $message = '')
    {
        null === $value || static::contains($value, $subString, $message);
    }
    /**
     * @psalm-pure
     *
     * @param iterable<string> $value
     * @param string           $subString
     * @param string           $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function allContains($value, $subString, $message = '')
    {
        static::isIterable($value);
        foreach ($value as $entry) {
            static::contains($entry, $subString, $message);
        }
    }
    /**
     * @psalm-pure
     *
     * @param iterable<string|null> $value
     * @param string                $subString
     * @param string                $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function allNullOrContains($value, $subString, $message = '')
    {
        static::isIterable($value);
        foreach ($value as $entry) {
            null === $entry || static::contains($entry, $subString, $message);
        }
    }
    /**
     * @psalm-pure
     *
     * @param string|null $value
     * @param string      $subString
     * @param string      $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function nullOrNotContains($value, $subString, $message = '')
    {
        null === $value || static::notContains($value, $subString, $message);
    }
    /**
     * @psalm-pure
     *
     * @param iterable<string> $value
     * @param string           $subString
     * @param string           $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function allNotContains($value, $subString, $message = '')
    {
        static::isIterable($value);
        foreach ($value as $entry) {
            static::notContains($entry, $subString, $message);
        }
    }
    /**
     * @psalm-pure
     *
     * @param iterable<string|null> $value
     * @param string                $subString
     * @param string                $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function allNullOrNotContains($value, $subString, $message = '')
    {
        static::isIterable($value);
        foreach ($value as $entry) {
            null === $entry || static::notContains($entry, $subString, $message);
        }
    }
    /**
     * @psalm-pure
     *
     * @param string|null $value
     * @param string      $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function nullOrNotWhitespaceOnly($value, $message = '')
    {
        null === $value || static::notWhitespaceOnly($value, $message);
    }
    /**
     * @psalm-pure
     *
     * @param iterable<string> $value
     * @param string           $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function allNotWhitespaceOnly($value, $message = '')
    {
        static::isIterable($value);
        foreach ($value as $entry) {
            static::notWhitespaceOnly($entry, $message);
        }
    }
    /**
     * @psalm-pure
     *
     * @param iterable<string|null> $value
     * @param string                $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function allNullOrNotWhitespaceOnly($value, $message = '')
    {
        static::isIterable($value);
        foreach ($value as $entry) {
            null === $entry || static::notWhitespaceOnly($entry, $message);
        }
    }
    /**
     * @psalm-pure
     *
     * @param string|null $value
     * @param string      $prefix
     * @param string      $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function nullOrStartsWith($value, $prefix, $message = '')
    {
        null === $value || static::startsWith($value, $prefix, $message);
    }
    /**
     * @psalm-pure
     *
     * @param iterable<string> $value
     * @param string           $prefix
     * @param string           $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function allStartsWith($value, $prefix, $message = '')
    {
        static::isIterable($value);
        foreach ($value as $entry) {
            static::startsWith($entry, $prefix, $message);
        }
    }
    /**
     * @psalm-pure
     *
     * @param iterable<string|null> $value
     * @param string                $prefix
     * @param string                $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function allNullOrStartsWith($value, $prefix, $message = '')
    {
        static::isIterable($value);
        foreach ($value as $entry) {
            null === $entry || static::startsWith($entry, $prefix, $message);
        }
    }
    /**
     * @psalm-pure
     *
     * @param string|null $value
     * @param string      $prefix
     * @param string      $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function nullOrNotStartsWith($value, $prefix, $message = '')
    {
        null === $value || static::notStartsWith($value, $prefix, $message);
    }
    /**
     * @psalm-pure
     *
     * @param iterable<string> $value
     * @param string           $prefix
     * @param string           $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function allNotStartsWith($value, $prefix, $message = '')
    {
        static::isIterable($value);
        foreach ($value as $entry) {
            static::notStartsWith($entry, $prefix, $message);
        }
    }
    /**
     * @psalm-pure
     *
     * @param iterable<string|null> $value
     * @param string                $prefix
     * @param string                $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function allNullOrNotStartsWith($value, $prefix, $message = '')
    {
        static::isIterable($value);
        foreach ($value as $entry) {
            null === $entry || static::notStartsWith($entry, $prefix, $message);
        }
    }
    /**
     * @psalm-pure
     *
     * @param mixed  $value
     * @param string $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function nullOrStartsWithLetter($value, $message = '')
    {
        null === $value || static::startsWithLetter($value, $message);
    }
    /**
     * @psalm-pure
     *
     * @param mixed  $value
     * @param string $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function allStartsWithLetter($value, $message = '')
    {
        static::isIterable($value);
        foreach ($value as $entry) {
            static::startsWithLetter($entry, $message);
        }
    }
    /**
     * @psalm-pure
     *
     * @param mixed  $value
     * @param string $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function allNullOrStartsWithLetter($value, $message = '')
    {
        static::isIterable($value);
        foreach ($value as $entry) {
            null === $entry || static::startsWithLetter($entry, $message);
        }
    }
    /**
     * @psalm-pure
     *
     * @param string|null $value
     * @param string      $suffix
     * @param string      $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function nullOrEndsWith($value, $suffix, $message = '')
    {
        null === $value || static::endsWith($value, $suffix, $message);
    }
    /**
     * @psalm-pure
     *
     * @param iterable<string> $value
     * @param string           $suffix
     * @param string           $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function allEndsWith($value, $suffix, $message = '')
    {
        static::isIterable($value);
        foreach ($value as $entry) {
            static::endsWith($entry, $suffix, $message);
        }
    }
    /**
     * @psalm-pure
     *
     * @param iterable<string|null> $value
     * @param string                $suffix
     * @param string                $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function allNullOrEndsWith($value, $suffix, $message = '')
    {
        static::isIterable($value);
        foreach ($value as $entry) {
            null === $entry || static::endsWith($entry, $suffix, $message);
        }
    }
    /**
     * @psalm-pure
     *
     * @param string|null $value
     * @param string      $suffix
     * @param string      $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function nullOrNotEndsWith($value, $suffix, $message = '')
    {
        null === $value || static::notEndsWith($value, $suffix, $message);
    }
    /**
     * @psalm-pure
     *
     * @param iterable<string> $value
     * @param string           $suffix
     * @param string           $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function allNotEndsWith($value, $suffix, $message = '')
    {
        static::isIterable($value);
        foreach ($value as $entry) {
            static::notEndsWith($entry, $suffix, $message);
        }
    }
    /**
     * @psalm-pure
     *
     * @param iterable<string|null> $value
     * @param string                $suffix
     * @param string                $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function allNullOrNotEndsWith($value, $suffix, $message = '')
    {
        static::isIterable($value);
        foreach ($value as $entry) {
            null === $entry || static::notEndsWith($entry, $suffix, $message);
        }
    }
    /**
     * @psalm-pure
     *
     * @param string|null $value
     * @param string      $pattern
     * @param string      $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function nullOrRegex($value, $pattern, $message = '')
    {
        null === $value || static::regex($value, $pattern, $message);
    }
    /**
     * @psalm-pure
     *
     * @param iterable<string> $value
     * @param string           $pattern
     * @param string           $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function allRegex($value, $pattern, $message = '')
    {
        static::isIterable($value);
        foreach ($value as $entry) {
            static::regex($entry, $pattern, $message);
        }
    }
    /**
     * @psalm-pure
     *
     * @param iterable<string|null> $value
     * @param string                $pattern
     * @param string                $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function allNullOrRegex($value, $pattern, $message = '')
    {
        static::isIterable($value);
        foreach ($value as $entry) {
            null === $entry || static::regex($entry, $pattern, $message);
        }
    }
    /**
     * @psalm-pure
     *
     * @param string|null $value
     * @param string      $pattern
     * @param string      $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function nullOrNotRegex($value, $pattern, $message = '')
    {
        null === $value || static::notRegex($value, $pattern, $message);
    }
    /**
     * @psalm-pure
     *
     * @param iterable<string> $value
     * @param string           $pattern
     * @param string           $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function allNotRegex($value, $pattern, $message = '')
    {
        static::isIterable($value);
        foreach ($value as $entry) {
            static::notRegex($entry, $pattern, $message);
        }
    }
    /**
     * @psalm-pure
     *
     * @param iterable<string|null> $value
     * @param string                $pattern
     * @param string                $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function allNullOrNotRegex($value, $pattern, $message = '')
    {
        static::isIterable($value);
        foreach ($value as $entry) {
            null === $entry || static::notRegex($entry, $pattern, $message);
        }
    }
    /**
     * @psalm-pure
     *
     * @param mixed  $value
     * @param string $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function nullOrUnicodeLetters($value, $message = '')
    {
        null === $value || static::unicodeLetters($value, $message);
    }
    /**
     * @psalm-pure
     *
     * @param mixed  $value
     * @param string $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function allUnicodeLetters($value, $message = '')
    {
        static::isIterable($value);
        foreach ($value as $entry) {
            static::unicodeLetters($entry, $message);
        }
    }
    /**
     * @psalm-pure
     *
     * @param mixed  $value
     * @param string $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function allNullOrUnicodeLetters($value, $message = '')
    {
        static::isIterable($value);
        foreach ($value as $entry) {
            null === $entry || static::unicodeLetters($entry, $message);
        }
    }
    /**
     * @psalm-pure
     *
     * @param mixed  $value
     * @param string $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function nullOrAlpha($value, $message = '')
    {
        null === $value || static::alpha($value, $message);
    }
    /**
     * @psalm-pure
     *
     * @param mixed  $value
     * @param string $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function allAlpha($value, $message = '')
    {
        static::isIterable($value);
        foreach ($value as $entry) {
            static::alpha($entry, $message);
        }
    }
    /**
     * @psalm-pure
     *
     * @param mixed  $value
     * @param string $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function allNullOrAlpha($value, $message = '')
    {
        static::isIterable($value);
        foreach ($value as $entry) {
            null === $entry || static::alpha($entry, $message);
        }
    }
    /**
     * @psalm-pure
     *
     * @param string|null $value
     * @param string      $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function nullOrDigits($value, $message = '')
    {
        null === $value || static::digits($value, $message);
    }
    /**
     * @psalm-pure
     *
     * @param iterable<string> $value
     * @param string           $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function allDigits($value, $message = '')
    {
        static::isIterable($value);
        foreach ($value as $entry) {
            static::digits($entry, $message);
        }
    }
    /**
     * @psalm-pure
     *
     * @param iterable<string|null> $value
     * @param string                $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function allNullOrDigits($value, $message = '')
    {
        static::isIterable($value);
        foreach ($value as $entry) {
            null === $entry || static::digits($entry, $message);
        }
    }
    /**
     * @psalm-pure
     *
     * @param string|null $value
     * @param string      $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function nullOrAlnum($value, $message = '')
    {
        null === $value || static::alnum($value, $message);
    }
    /**
     * @psalm-pure
     *
     * @param iterable<string> $value
     * @param string           $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function allAlnum($value, $message = '')
    {
        static::isIterable($value);
        foreach ($value as $entry) {
            static::alnum($entry, $message);
        }
    }
    /**
     * @psalm-pure
     *
     * @param iterable<string|null> $value
     * @param string                $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function allNullOrAlnum($value, $message = '')
    {
        static::isIterable($value);
        foreach ($value as $entry) {
            null === $entry || static::alnum($entry, $message);
        }
    }
    /**
     * @psalm-pure
     *
     * @psalm-assert lowercase-string|null $value
     *
     * @param string|null $value
     * @param string      $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function nullOrLower($value, $message = '')
    {
        null === $value || static::lower($value, $message);
    }
    /**
     * @psalm-pure
     *
     * @psalm-assert iterable<lowercase-string> $value
     *
     * @param iterable<string> $value
     * @param string           $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function allLower($value, $message = '')
    {
        static::isIterable($value);
        foreach ($value as $entry) {
            static::lower($entry, $message);
        }
    }
    /**
     * @psalm-pure
     *
     * @psalm-assert iterable<lowercase-string|null> $value
     *
     * @param iterable<string|null> $value
     * @param string                $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function allNullOrLower($value, $message = '')
    {
        static::isIterable($value);
        foreach ($value as $entry) {
            null === $entry || static::lower($entry, $message);
        }
    }
    /**
     * @psalm-pure
     *
     * @param string|null $value
     * @param string      $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function nullOrUpper($value, $message = '')
    {
        null === $value || static::upper($value, $message);
    }
    /**
     * @psalm-pure
     *
     * @param iterable<string> $value
     * @param string           $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function allUpper($value, $message = '')
    {
        static::isIterable($value);
        foreach ($value as $entry) {
            static::upper($entry, $message);
        }
    }
    /**
     * @psalm-pure
     *
     * @psalm-assert iterable<!lowercase-string|null> $value
     *
     * @param iterable<string|null> $value
     * @param string                $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function allNullOrUpper($value, $message = '')
    {
        static::isIterable($value);
        foreach ($value as $entry) {
            null === $entry || static::upper($entry, $message);
        }
    }
    /**
     * @psalm-pure
     *
     * @param string|null $value
     * @param int         $length
     * @param string      $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function nullOrLength($value, $length, $message = '')
    {
        null === $value || static::length($value, $length, $message);
    }
    /**
     * @psalm-pure
     *
     * @param iterable<string> $value
     * @param int              $length
     * @param string           $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function allLength($value, $length, $message = '')
    {
        static::isIterable($value);
        foreach ($value as $entry) {
            static::length($entry, $length, $message);
        }
    }
    /**
     * @psalm-pure
     *
     * @param iterable<string|null> $value
     * @param int                   $length
     * @param string                $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function allNullOrLength($value, $length, $message = '')
    {
        static::isIterable($value);
        foreach ($value as $entry) {
            null === $entry || static::length($entry, $length, $message);
        }
    }
    /**
     * @psalm-pure
     *
     * @param string|null $value
     * @param int|float   $min
     * @param string      $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function nullOrMinLength($value, $min, $message = '')
    {
        null === $value || static::minLength($value, $min, $message);
    }
    /**
     * @psalm-pure
     *
     * @param iterable<string> $value
     * @param int|float        $min
     * @param string           $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function allMinLength($value, $min, $message = '')
    {
        static::isIterable($value);
        foreach ($value as $entry) {
            static::minLength($entry, $min, $message);
        }
    }
    /**
     * @psalm-pure
     *
     * @param iterable<string|null> $value
     * @param int|float             $min
     * @param string                $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function allNullOrMinLength($value, $min, $message = '')
    {
        static::isIterable($value);
        foreach ($value as $entry) {
            null === $entry || static::minLength($entry, $min, $message);
        }
    }
    /**
     * @psalm-pure
     *
     * @param string|null $value
     * @param int|float   $max
     * @param string      $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function nullOrMaxLength($value, $max, $message = '')
    {
        null === $value || static::maxLength($value, $max, $message);
    }
    /**
     * @psalm-pure
     *
     * @param iterable<string> $value
     * @param int|float        $max
     * @param string           $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function allMaxLength($value, $max, $message = '')
    {
        static::isIterable($value);
        foreach ($value as $entry) {
            static::maxLength($entry, $max, $message);
        }
    }
    /**
     * @psalm-pure
     *
     * @param iterable<string|null> $value
     * @param int|float             $max
     * @param string                $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function allNullOrMaxLength($value, $max, $message = '')
    {
        static::isIterable($value);
        foreach ($value as $entry) {
            null === $entry || static::maxLength($entry, $max, $message);
        }
    }
    /**
     * @psalm-pure
     *
     * @param string|null $value
     * @param int|float   $min
     * @param int|float   $max
     * @param string      $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function nullOrLengthBetween($value, $min, $max, $message = '')
    {
        null === $value || static::lengthBetween($value, $min, $max, $message);
    }
    /**
     * @psalm-pure
     *
     * @param iterable<string> $value
     * @param int|float        $min
     * @param int|float        $max
     * @param string           $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function allLengthBetween($value, $min, $max, $message = '')
    {
        static::isIterable($value);
        foreach ($value as $entry) {
            static::lengthBetween($entry, $min, $max, $message);
        }
    }
    /**
     * @psalm-pure
     *
     * @param iterable<string|null> $value
     * @param int|float             $min
     * @param int|float             $max
     * @param string                $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function allNullOrLengthBetween($value, $min, $max, $message = '')
    {
        static::isIterable($value);
        foreach ($value as $entry) {
            null === $entry || static::lengthBetween($entry, $min, $max, $message);
        }
    }
    /**
     * @param mixed  $value
     * @param string $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function nullOrFileExists($value, $message = '')
    {
        null === $value || static::fileExists($value, $message);
    }
    /**
     * @param mixed  $value
     * @param string $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function allFileExists($value, $message = '')
    {
        static::isIterable($value);
        foreach ($value as $entry) {
            static::fileExists($entry, $message);
        }
    }
    /**
     * @param mixed  $value
     * @param string $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function allNullOrFileExists($value, $message = '')
    {
        static::isIterable($value);
        foreach ($value as $entry) {
            null === $entry || static::fileExists($entry, $message);
        }
    }
    /**
     * @param mixed  $value
     * @param string $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function nullOrFile($value, $message = '')
    {
        null === $value || static::file($value, $message);
    }
    /**
     * @param mixed  $value
     * @param string $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function allFile($value, $message = '')
    {
        static::isIterable($value);
        foreach ($value as $entry) {
            static::file($entry, $message);
        }
    }
    /**
     * @param mixed  $value
     * @param string $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function allNullOrFile($value, $message = '')
    {
        static::isIterable($value);
        foreach ($value as $entry) {
            null === $entry || static::file($entry, $message);
        }
    }
    /**
     * @param mixed  $value
     * @param string $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function nullOrDirectory($value, $message = '')
    {
        null === $value || static::directory($value, $message);
    }
    /**
     * @param mixed  $value
     * @param string $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function allDirectory($value, $message = '')
    {
        static::isIterable($value);
        foreach ($value as $entry) {
            static::directory($entry, $message);
        }
    }
    /**
     * @param mixed  $value
     * @param string $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function allNullOrDirectory($value, $message = '')
    {
        static::isIterable($value);
        foreach ($value as $entry) {
            null === $entry || static::directory($entry, $message);
        }
    }
    /**
     * @param string|null $value
     * @param string      $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function nullOrReadable($value, $message = '')
    {
        null === $value || static::readable($value, $message);
    }
    /**
     * @param iterable<string> $value
     * @param string           $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function allReadable($value, $message = '')
    {
        static::isIterable($value);
        foreach ($value as $entry) {
            static::readable($entry, $message);
        }
    }
    /**
     * @param iterable<string|null> $value
     * @param string                $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function allNullOrReadable($value, $message = '')
    {
        static::isIterable($value);
        foreach ($value as $entry) {
            null === $entry || static::readable($entry, $message);
        }
    }
    /**
     * @param string|null $value
     * @param string      $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function nullOrWritable($value, $message = '')
    {
        null === $value || static::writable($value, $message);
    }
    /**
     * @param iterable<string> $value
     * @param string           $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function allWritable($value, $message = '')
    {
        static::isIterable($value);
        foreach ($value as $entry) {
            static::writable($entry, $message);
        }
    }
    /**
     * @param iterable<string|null> $value
     * @param string                $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function allNullOrWritable($value, $message = '')
    {
        static::isIterable($value);
        foreach ($value as $entry) {
            null === $entry || static::writable($entry, $message);
        }
    }
    /**
     * @psalm-assert class-string|null $value
     *
     * @param mixed  $value
     * @param string $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function nullOrClassExists($value, $message = '')
    {
        null === $value || static::classExists($value, $message);
    }
    /**
     * @psalm-assert iterable<class-string> $value
     *
     * @param mixed  $value
     * @param string $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function allClassExists($value, $message = '')
    {
        static::isIterable($value);
        foreach ($value as $entry) {
            static::classExists($entry, $message);
        }
    }
    /**
     * @psalm-assert iterable<class-string|null> $value
     *
     * @param mixed  $value
     * @param string $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function allNullOrClassExists($value, $message = '')
    {
        static::isIterable($value);
        foreach ($value as $entry) {
            null === $entry || static::classExists($entry, $message);
        }
    }
    /**
     * @psalm-pure
     *
     * @psalm-template ExpectedType of object
     * @psalm-param class-string<ExpectedType> $class
     * @psalm-assert class-string<ExpectedType>|ExpectedType|null $value
     *
     * @param mixed         $value
     * @param string|object $class
     * @param string        $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function nullOrSubclassOf($value, $class, $message = '')
    {
        null === $value || static::subclassOf($value, $class, $message);
    }
    /**
     * @psalm-pure
     *
     * @psalm-template ExpectedType of object
     * @psalm-param class-string<ExpectedType> $class
     * @psalm-assert iterable<class-string<ExpectedType>|ExpectedType> $value
     *
     * @param mixed         $value
     * @param string|object $class
     * @param string        $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function allSubclassOf($value, $class, $message = '')
    {
        static::isIterable($value);
        foreach ($value as $entry) {
            static::subclassOf($entry, $class, $message);
        }
    }
    /**
     * @psalm-pure
     *
     * @psalm-template ExpectedType of object
     * @psalm-param class-string<ExpectedType> $class
     * @psalm-assert iterable<class-string<ExpectedType>|ExpectedType|null> $value
     *
     * @param mixed         $value
     * @param string|object $class
     * @param string        $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function allNullOrSubclassOf($value, $class, $message = '')
    {
        static::isIterable($value);
        foreach ($value as $entry) {
            null === $entry || static::subclassOf($entry, $class, $message);
        }
    }
    /**
     * @psalm-assert class-string|null $value
     *
     * @param mixed  $value
     * @param string $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function nullOrInterfaceExists($value, $message = '')
    {
        null === $value || static::interfaceExists($value, $message);
    }
    /**
     * @psalm-assert iterable<class-string> $value
     *
     * @param mixed  $value
     * @param string $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function allInterfaceExists($value, $message = '')
    {
        static::isIterable($value);
        foreach ($value as $entry) {
            static::interfaceExists($entry, $message);
        }
    }
    /**
     * @psalm-assert iterable<class-string|null> $value
     *
     * @param mixed  $value
     * @param string $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function allNullOrInterfaceExists($value, $message = '')
    {
        static::isIterable($value);
        foreach ($value as $entry) {
            null === $entry || static::interfaceExists($entry, $message);
        }
    }
    /**
     * @psalm-pure
     *
     * @psalm-template ExpectedType of object
     * @psalm-param class-string<ExpectedType> $interface
     * @psalm-assert class-string<ExpectedType>|ExpectedType|null $value
     *
     * @param mixed  $value
     * @param mixed  $interface
     * @param string $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function nullOrImplementsInterface($value, $interface, $message = '')
    {
        null === $value || static::implementsInterface($value, $interface, $message);
    }
    /**
     * @psalm-pure
     *
     * @psalm-template ExpectedType of object
     * @psalm-param class-string<ExpectedType> $interface
     * @psalm-assert iterable<class-string<ExpectedType>|ExpectedType> $value
     *
     * @param mixed  $value
     * @param mixed  $interface
     * @param string $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function allImplementsInterface($value, $interface, $message = '')
    {
        static::isIterable($value);
        foreach ($value as $entry) {
            static::implementsInterface($entry, $interface, $message);
        }
    }
    /**
     * @psalm-pure
     *
     * @psalm-template ExpectedType of object
     * @psalm-param class-string<ExpectedType> $interface
     * @psalm-assert iterable<class-string<ExpectedType>|ExpectedType|null> $value
     *
     * @param mixed  $value
     * @param mixed  $interface
     * @param string $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function allNullOrImplementsInterface($value, $interface, $message = '')
    {
        static::isIterable($value);
        foreach ($value as $entry) {
            null === $entry || static::implementsInterface($entry, $interface, $message);
        }
    }
    /**
     * @psalm-pure
     *
     * @psalm-param class-string|object|null $classOrObject
     *
     * @param string|object|null $classOrObject
     * @param mixed              $property
     * @param string             $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function nullOrPropertyExists($classOrObject, $property, $message = '')
    {
        null === $classOrObject || static::propertyExists($classOrObject, $property, $message);
    }
    /**
     * @psalm-pure
     *
     * @psalm-param iterable<class-string|object> $classOrObject
     *
     * @param iterable<string|object> $classOrObject
     * @param mixed                   $property
     * @param string                  $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function allPropertyExists($classOrObject, $property, $message = '')
    {
        static::isIterable($classOrObject);
        foreach ($classOrObject as $entry) {
            static::propertyExists($entry, $property, $message);
        }
    }
    /**
     * @psalm-pure
     *
     * @psalm-param iterable<class-string|object|null> $classOrObject
     *
     * @param iterable<string|object|null> $classOrObject
     * @param mixed                        $property
     * @param string                       $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function allNullOrPropertyExists($classOrObject, $property, $message = '')
    {
        static::isIterable($classOrObject);
        foreach ($classOrObject as $entry) {
            null === $entry || static::propertyExists($entry, $property, $message);
        }
    }
    /**
     * @psalm-pure
     *
     * @psalm-param class-string|object|null $classOrObject
     *
     * @param string|object|null $classOrObject
     * @param mixed              $property
     * @param string             $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function nullOrPropertyNotExists($classOrObject, $property, $message = '')
    {
        null === $classOrObject || static::propertyNotExists($classOrObject, $property, $message);
    }
    /**
     * @psalm-pure
     *
     * @psalm-param iterable<class-string|object> $classOrObject
     *
     * @param iterable<string|object> $classOrObject
     * @param mixed                   $property
     * @param string                  $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function allPropertyNotExists($classOrObject, $property, $message = '')
    {
        static::isIterable($classOrObject);
        foreach ($classOrObject as $entry) {
            static::propertyNotExists($entry, $property, $message);
        }
    }
    /**
     * @psalm-pure
     *
     * @psalm-param iterable<class-string|object|null> $classOrObject
     *
     * @param iterable<string|object|null> $classOrObject
     * @param mixed                        $property
     * @param string                       $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function allNullOrPropertyNotExists($classOrObject, $property, $message = '')
    {
        static::isIterable($classOrObject);
        foreach ($classOrObject as $entry) {
            null === $entry || static::propertyNotExists($entry, $property, $message);
        }
    }
    /**
     * @psalm-pure
     *
     * @psalm-param class-string|object|null $classOrObject
     *
     * @param string|object|null $classOrObject
     * @param mixed              $method
     * @param string             $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function nullOrMethodExists($classOrObject, $method, $message = '')
    {
        null === $classOrObject || static::methodExists($classOrObject, $method, $message);
    }
    /**
     * @psalm-pure
     *
     * @psalm-param iterable<class-string|object> $classOrObject
     *
     * @param iterable<string|object> $classOrObject
     * @param mixed                   $method
     * @param string                  $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function allMethodExists($classOrObject, $method, $message = '')
    {
        static::isIterable($classOrObject);
        foreach ($classOrObject as $entry) {
            static::methodExists($entry, $method, $message);
        }
    }
    /**
     * @psalm-pure
     *
     * @psalm-param iterable<class-string|object|null> $classOrObject
     *
     * @param iterable<string|object|null> $classOrObject
     * @param mixed                        $method
     * @param string                       $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function allNullOrMethodExists($classOrObject, $method, $message = '')
    {
        static::isIterable($classOrObject);
        foreach ($classOrObject as $entry) {
            null === $entry || static::methodExists($entry, $method, $message);
        }
    }
    /**
     * @psalm-pure
     *
     * @psalm-param class-string|object|null $classOrObject
     *
     * @param string|object|null $classOrObject
     * @param mixed              $method
     * @param string             $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function nullOrMethodNotExists($classOrObject, $method, $message = '')
    {
        null === $classOrObject || static::methodNotExists($classOrObject, $method, $message);
    }
    /**
     * @psalm-pure
     *
     * @psalm-param iterable<class-string|object> $classOrObject
     *
     * @param iterable<string|object> $classOrObject
     * @param mixed                   $method
     * @param string                  $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function allMethodNotExists($classOrObject, $method, $message = '')
    {
        static::isIterable($classOrObject);
        foreach ($classOrObject as $entry) {
            static::methodNotExists($entry, $method, $message);
        }
    }
    /**
     * @psalm-pure
     *
     * @psalm-param iterable<class-string|object|null> $classOrObject
     *
     * @param iterable<string|object|null> $classOrObject
     * @param mixed                        $method
     * @param string                       $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function allNullOrMethodNotExists($classOrObject, $method, $message = '')
    {
        static::isIterable($classOrObject);
        foreach ($classOrObject as $entry) {
            null === $entry || static::methodNotExists($entry, $method, $message);
        }
    }
    /**
     * @psalm-pure
     *
     * @param array|null $array
     * @param string|int $key
     * @param string     $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function nullOrKeyExists($array, $key, $message = '')
    {
        null === $array || static::keyExists($array, $key, $message);
    }
    /**
     * @psalm-pure
     *
     * @param iterable<array> $array
     * @param string|int      $key
     * @param string          $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function allKeyExists($array, $key, $message = '')
    {
        static::isIterable($array);
        foreach ($array as $entry) {
            static::keyExists($entry, $key, $message);
        }
    }
    /**
     * @psalm-pure
     *
     * @param iterable<array|null> $array
     * @param string|int           $key
     * @param string               $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function allNullOrKeyExists($array, $key, $message = '')
    {
        static::isIterable($array);
        foreach ($array as $entry) {
            null === $entry || static::keyExists($entry, $key, $message);
        }
    }
    /**
     * @psalm-pure
     *
     * @param array|null $array
     * @param string|int $key
     * @param string     $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function nullOrKeyNotExists($array, $key, $message = '')
    {
        null === $array || static::keyNotExists($array, $key, $message);
    }
    /**
     * @psalm-pure
     *
     * @param iterable<array> $array
     * @param string|int      $key
     * @param string          $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function allKeyNotExists($array, $key, $message = '')
    {
        static::isIterable($array);
        foreach ($array as $entry) {
            static::keyNotExists($entry, $key, $message);
        }
    }
    /**
     * @psalm-pure
     *
     * @param iterable<array|null> $array
     * @param string|int           $key
     * @param string               $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function allNullOrKeyNotExists($array, $key, $message = '')
    {
        static::isIterable($array);
        foreach ($array as $entry) {
            null === $entry || static::keyNotExists($entry, $key, $message);
        }
    }
    /**
     * @psalm-pure
     *
     * @psalm-assert array-key|null $value
     *
     * @param mixed  $value
     * @param string $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function nullOrValidArrayKey($value, $message = '')
    {
        null === $value || static::validArrayKey($value, $message);
    }
    /**
     * @psalm-pure
     *
     * @psalm-assert iterable<array-key> $value
     *
     * @param mixed  $value
     * @param string $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function allValidArrayKey($value, $message = '')
    {
        static::isIterable($value);
        foreach ($value as $entry) {
            static::validArrayKey($entry, $message);
        }
    }
    /**
     * @psalm-pure
     *
     * @psalm-assert iterable<array-key|null> $value
     *
     * @param mixed  $value
     * @param string $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function allNullOrValidArrayKey($value, $message = '')
    {
        static::isIterable($value);
        foreach ($value as $entry) {
            null === $entry || static::validArrayKey($entry, $message);
        }
    }
    /**
     * @param Countable|array|null $array
     * @param int                  $number
     * @param string               $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function nullOrCount($array, $number, $message = '')
    {
        null === $array || static::count($array, $number, $message);
    }
    /**
     * @param iterable<Countable|array> $array
     * @param int                       $number
     * @param string                    $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function allCount($array, $number, $message = '')
    {
        static::isIterable($array);
        foreach ($array as $entry) {
            static::count($entry, $number, $message);
        }
    }
    /**
     * @param iterable<Countable|array|null> $array
     * @param int                            $number
     * @param string                         $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function allNullOrCount($array, $number, $message = '')
    {
        static::isIterable($array);
        foreach ($array as $entry) {
            null === $entry || static::count($entry, $number, $message);
        }
    }
    /**
     * @param Countable|array|null $array
     * @param int|float            $min
     * @param string               $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function nullOrMinCount($array, $min, $message = '')
    {
        null === $array || static::minCount($array, $min, $message);
    }
    /**
     * @param iterable<Countable|array> $array
     * @param int|float                 $min
     * @param string                    $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function allMinCount($array, $min, $message = '')
    {
        static::isIterable($array);
        foreach ($array as $entry) {
            static::minCount($entry, $min, $message);
        }
    }
    /**
     * @param iterable<Countable|array|null> $array
     * @param int|float                      $min
     * @param string                         $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function allNullOrMinCount($array, $min, $message = '')
    {
        static::isIterable($array);
        foreach ($array as $entry) {
            null === $entry || static::minCount($entry, $min, $message);
        }
    }
    /**
     * @param Countable|array|null $array
     * @param int|float            $max
     * @param string               $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function nullOrMaxCount($array, $max, $message = '')
    {
        null === $array || static::maxCount($array, $max, $message);
    }
    /**
     * @param iterable<Countable|array> $array
     * @param int|float                 $max
     * @param string                    $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function allMaxCount($array, $max, $message = '')
    {
        static::isIterable($array);
        foreach ($array as $entry) {
            static::maxCount($entry, $max, $message);
        }
    }
    /**
     * @param iterable<Countable|array|null> $array
     * @param int|float                      $max
     * @param string                         $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function allNullOrMaxCount($array, $max, $message = '')
    {
        static::isIterable($array);
        foreach ($array as $entry) {
            null === $entry || static::maxCount($entry, $max, $message);
        }
    }
    /**
     * @param Countable|array|null $array
     * @param int|float            $min
     * @param int|float            $max
     * @param string               $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function nullOrCountBetween($array, $min, $max, $message = '')
    {
        null === $array || static::countBetween($array, $min, $max, $message);
    }
    /**
     * @param iterable<Countable|array> $array
     * @param int|float                 $min
     * @param int|float                 $max
     * @param string                    $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function allCountBetween($array, $min, $max, $message = '')
    {
        static::isIterable($array);
        foreach ($array as $entry) {
            static::countBetween($entry, $min, $max, $message);
        }
    }
    /**
     * @param iterable<Countable|array|null> $array
     * @param int|float                      $min
     * @param int|float                      $max
     * @param string                         $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function allNullOrCountBetween($array, $min, $max, $message = '')
    {
        static::isIterable($array);
        foreach ($array as $entry) {
            null === $entry || static::countBetween($entry, $min, $max, $message);
        }
    }
    /**
     * @psalm-pure
     *
     * @psalm-assert list|null $array
     *
     * @param mixed  $array
     * @param string $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function nullOrIsList($array, $message = '')
    {
        null === $array || static::isList($array, $message);
    }
    /**
     * @psalm-pure
     *
     * @psalm-assert iterable<list> $array
     *
     * @param mixed  $array
     * @param string $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function allIsList($array, $message = '')
    {
        static::isIterable($array);
        foreach ($array as $entry) {
            static::isList($entry, $message);
        }
    }
    /**
     * @psalm-pure
     *
     * @psalm-assert iterable<list|null> $array
     *
     * @param mixed  $array
     * @param string $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function allNullOrIsList($array, $message = '')
    {
        static::isIterable($array);
        foreach ($array as $entry) {
            null === $entry || static::isList($entry, $message);
        }
    }
    /**
     * @psalm-pure
     *
     * @psalm-assert non-empty-list|null $array
     *
     * @param mixed  $array
     * @param string $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function nullOrIsNonEmptyList($array, $message = '')
    {
        null === $array || static::isNonEmptyList($array, $message);
    }
    /**
     * @psalm-pure
     *
     * @psalm-assert iterable<non-empty-list> $array
     *
     * @param mixed  $array
     * @param string $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function allIsNonEmptyList($array, $message = '')
    {
        static::isIterable($array);
        foreach ($array as $entry) {
            static::isNonEmptyList($entry, $message);
        }
    }
    /**
     * @psalm-pure
     *
     * @psalm-assert iterable<non-empty-list|null> $array
     *
     * @param mixed  $array
     * @param string $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function allNullOrIsNonEmptyList($array, $message = '')
    {
        static::isIterable($array);
        foreach ($array as $entry) {
            null === $entry || static::isNonEmptyList($entry, $message);
        }
    }
    /**
     * @psalm-pure
     *
     * @psalm-template T
     * @psalm-param mixed|array<T>|null $array
     * @psalm-assert array<string, T>|null $array
     *
     * @param mixed  $array
     * @param string $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function nullOrIsMap($array, $message = '')
    {
        null === $array || static::isMap($array, $message);
    }
    /**
     * @psalm-pure
     *
     * @psalm-template T
     * @psalm-param iterable<mixed|array<T>> $array
     * @psalm-assert iterable<array<string, T>> $array
     *
     * @param mixed  $array
     * @param string $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function allIsMap($array, $message = '')
    {
        static::isIterable($array);
        foreach ($array as $entry) {
            static::isMap($entry, $message);
        }
    }
    /**
     * @psalm-pure
     *
     * @psalm-template T
     * @psalm-param iterable<mixed|array<T>|null> $array
     * @psalm-assert iterable<array<string, T>|null> $array
     *
     * @param mixed  $array
     * @param string $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function allNullOrIsMap($array, $message = '')
    {
        static::isIterable($array);
        foreach ($array as $entry) {
            null === $entry || static::isMap($entry, $message);
        }
    }
    /**
     * @psalm-pure
     *
     * @psalm-template T
     * @psalm-param mixed|array<T>|null $array
     *
     * @param mixed  $array
     * @param string $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function nullOrIsNonEmptyMap($array, $message = '')
    {
        null === $array || static::isNonEmptyMap($array, $message);
    }
    /**
     * @psalm-pure
     *
     * @psalm-template T
     * @psalm-param iterable<mixed|array<T>> $array
     *
     * @param mixed  $array
     * @param string $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function allIsNonEmptyMap($array, $message = '')
    {
        static::isIterable($array);
        foreach ($array as $entry) {
            static::isNonEmptyMap($entry, $message);
        }
    }
    /**
     * @psalm-pure
     *
     * @psalm-template T
     * @psalm-param iterable<mixed|array<T>|null> $array
     * @psalm-assert iterable<array<string, T>|null> $array
     * @psalm-assert iterable<!empty|null> $array
     *
     * @param mixed  $array
     * @param string $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function allNullOrIsNonEmptyMap($array, $message = '')
    {
        static::isIterable($array);
        foreach ($array as $entry) {
            null === $entry || static::isNonEmptyMap($entry, $message);
        }
    }
    /**
     * @psalm-pure
     *
     * @param string|null $value
     * @param string      $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function nullOrUuid($value, $message = '')
    {
        null === $value || static::uuid($value, $message);
    }
    /**
     * @psalm-pure
     *
     * @param iterable<string> $value
     * @param string           $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function allUuid($value, $message = '')
    {
        static::isIterable($value);
        foreach ($value as $entry) {
            static::uuid($entry, $message);
        }
    }
    /**
     * @psalm-pure
     *
     * @param iterable<string|null> $value
     * @param string                $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function allNullOrUuid($value, $message = '')
    {
        static::isIterable($value);
        foreach ($value as $entry) {
            null === $entry || static::uuid($entry, $message);
        }
    }
    /**
     * @psalm-param class-string<Throwable> $class
     *
     * @param Closure|null $expression
     * @param string       $class
     * @param string       $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function nullOrThrows($expression, $class = 'Exception', $message = '')
    {
        null === $expression || static::throws($expression, $class, $message);
    }
    /**
     * @psalm-param class-string<Throwable> $class
     *
     * @param iterable<Closure> $expression
     * @param string            $class
     * @param string            $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function allThrows($expression, $class = 'Exception', $message = '')
    {
        static::isIterable($expression);
        foreach ($expression as $entry) {
            static::throws($entry, $class, $message);
        }
    }
    /**
     * @psalm-param class-string<Throwable> $class
     *
     * @param iterable<Closure|null> $expression
     * @param string                 $class
     * @param string                 $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function allNullOrThrows($expression, $class = 'Exception', $message = '')
    {
        static::isIterable($expression);
        foreach ($expression as $entry) {
            null === $entry || static::throws($entry, $class, $message);
        }
    }
}
<?php

/*
 * This file is part of the webmozart/assert package.
 *
 * (c) Bernhard Schussek <bschussek@gmail.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Webmozart\Assert;

class InvalidArgumentException extends \InvalidArgumentException
{
}
<?php

/*
 * This file is part of the webmozart/assert package.
 *
 * (c) Bernhard Schussek <bschussek@gmail.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\Webmozart\Assert;

use ArrayAccess;
use BadMethodCallException;
use Closure;
use Countable;
use DateTime;
use DateTimeImmutable;
use Exception;
use ResourceBundle;
use SimpleXMLElement;
use Throwable;
use Traversable;
/**
 * Efficient assertions to validate the input/output of your methods.
 *
 * @since  1.0
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
class Assert
{
    use Mixin;
    /**
     * @psalm-pure
     *
     * @psalm-assert string $value
     *
     * @param mixed  $value
     * @param string $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function string($value, $message = '')
    {
        if (!\is_string($value)) {
            static::reportInvalidArgument(\sprintf($message ?: 'Expected a string. Got: %s', static::typeToString($value)));
        }
    }
    /**
     * @psalm-pure
     *
     * @psalm-assert non-empty-string $value
     *
     * @param mixed  $value
     * @param string $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function stringNotEmpty($value, $message = '')
    {
        static::string($value, $message);
        static::notEq($value, '', $message);
    }
    /**
     * @psalm-pure
     *
     * @psalm-assert int $value
     *
     * @param mixed  $value
     * @param string $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function integer($value, $message = '')
    {
        if (!\is_int($value)) {
            static::reportInvalidArgument(\sprintf($message ?: 'Expected an integer. Got: %s', static::typeToString($value)));
        }
    }
    /**
     * @psalm-pure
     *
     * @psalm-assert numeric $value
     *
     * @param mixed  $value
     * @param string $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function integerish($value, $message = '')
    {
        if (!\is_numeric($value) || $value != (int) $value) {
            static::reportInvalidArgument(\sprintf($message ?: 'Expected an integerish value. Got: %s', static::typeToString($value)));
        }
    }
    /**
     * @psalm-pure
     *
     * @psalm-assert positive-int $value
     *
     * @param mixed  $value
     * @param string $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function positiveInteger($value, $message = '')
    {
        if (!(\is_int($value) && $value > 0)) {
            static::reportInvalidArgument(\sprintf($message ?: 'Expected a positive integer. Got: %s', static::valueToString($value)));
        }
    }
    /**
     * @psalm-pure
     *
     * @psalm-assert float $value
     *
     * @param mixed  $value
     * @param string $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function float($value, $message = '')
    {
        if (!\is_float($value)) {
            static::reportInvalidArgument(\sprintf($message ?: 'Expected a float. Got: %s', static::typeToString($value)));
        }
    }
    /**
     * @psalm-pure
     *
     * @psalm-assert numeric $value
     *
     * @param mixed  $value
     * @param string $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function numeric($value, $message = '')
    {
        if (!\is_numeric($value)) {
            static::reportInvalidArgument(\sprintf($message ?: 'Expected a numeric. Got: %s', static::typeToString($value)));
        }
    }
    /**
     * @psalm-pure
     *
     * @psalm-assert positive-int|0 $value
     *
     * @param mixed  $value
     * @param string $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function natural($value, $message = '')
    {
        if (!\is_int($value) || $value < 0) {
            static::reportInvalidArgument(\sprintf($message ?: 'Expected a non-negative integer. Got: %s', static::valueToString($value)));
        }
    }
    /**
     * @psalm-pure
     *
     * @psalm-assert bool $value
     *
     * @param mixed  $value
     * @param string $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function boolean($value, $message = '')
    {
        if (!\is_bool($value)) {
            static::reportInvalidArgument(\sprintf($message ?: 'Expected a boolean. Got: %s', static::typeToString($value)));
        }
    }
    /**
     * @psalm-pure
     *
     * @psalm-assert scalar $value
     *
     * @param mixed  $value
     * @param string $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function scalar($value, $message = '')
    {
        if (!\is_scalar($value)) {
            static::reportInvalidArgument(\sprintf($message ?: 'Expected a scalar. Got: %s', static::typeToString($value)));
        }
    }
    /**
     * @psalm-pure
     *
     * @psalm-assert object $value
     *
     * @param mixed  $value
     * @param string $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function object($value, $message = '')
    {
        if (!\is_object($value)) {
            static::reportInvalidArgument(\sprintf($message ?: 'Expected an object. Got: %s', static::typeToString($value)));
        }
    }
    /**
     * @psalm-pure
     *
     * @psalm-assert resource $value
     *
     * @param mixed       $value
     * @param string|null $type    type of resource this should be. @see https://www.php.net/manual/en/function.get-resource-type.php
     * @param string      $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function resource($value, $type = null, $message = '')
    {
        if (!\is_resource($value)) {
            static::reportInvalidArgument(\sprintf($message ?: 'Expected a resource. Got: %s', static::typeToString($value), $type));
        }
        if ($type && $type !== \get_resource_type($value)) {
            static::reportInvalidArgument(\sprintf($message ?: 'Expected a resource of type %2$s. Got: %s', static::typeToString($value), $type));
        }
    }
    /**
     * @psalm-pure
     *
     * @psalm-assert callable $value
     *
     * @param mixed  $value
     * @param string $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function isCallable($value, $message = '')
    {
        if (!\is_callable($value)) {
            static::reportInvalidArgument(\sprintf($message ?: 'Expected a callable. Got: %s', static::typeToString($value)));
        }
    }
    /**
     * @psalm-pure
     *
     * @psalm-assert array $value
     *
     * @param mixed  $value
     * @param string $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function isArray($value, $message = '')
    {
        if (!\is_array($value)) {
            static::reportInvalidArgument(\sprintf($message ?: 'Expected an array. Got: %s', static::typeToString($value)));
        }
    }
    /**
     * @psalm-pure
     *
     * @psalm-assert iterable $value
     *
     * @deprecated use "isIterable" or "isInstanceOf" instead
     *
     * @param mixed  $value
     * @param string $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function isTraversable($value, $message = '')
    {
        @\trigger_error(\sprintf('The "%s" assertion is deprecated. You should stop using it, as it will soon be removed in 2.0 version. Use "isIterable" or "isInstanceOf" instead.', __METHOD__), \E_USER_DEPRECATED);
        if (!\is_array($value) && !$value instanceof Traversable) {
            static::reportInvalidArgument(\sprintf($message ?: 'Expected a traversable. Got: %s', static::typeToString($value)));
        }
    }
    /**
     * @psalm-pure
     *
     * @psalm-assert array|ArrayAccess $value
     *
     * @param mixed  $value
     * @param string $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function isArrayAccessible($value, $message = '')
    {
        if (!\is_array($value) && !$value instanceof ArrayAccess) {
            static::reportInvalidArgument(\sprintf($message ?: 'Expected an array accessible. Got: %s', static::typeToString($value)));
        }
    }
    /**
     * @psalm-pure
     *
     * @psalm-assert countable $value
     *
     * @param mixed  $value
     * @param string $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function isCountable($value, $message = '')
    {
        if (!\is_array($value) && !$value instanceof Countable && !$value instanceof ResourceBundle && !$value instanceof SimpleXMLElement) {
            static::reportInvalidArgument(\sprintf($message ?: 'Expected a countable. Got: %s', static::typeToString($value)));
        }
    }
    /**
     * @psalm-pure
     *
     * @psalm-assert iterable $value
     *
     * @param mixed  $value
     * @param string $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function isIterable($value, $message = '')
    {
        if (!\is_array($value) && !$value instanceof Traversable) {
            static::reportInvalidArgument(\sprintf($message ?: 'Expected an iterable. Got: %s', static::typeToString($value)));
        }
    }
    /**
     * @psalm-pure
     *
     * @psalm-template ExpectedType of object
     *
     * @psalm-param class-string<ExpectedType> $class
     *
     * @psalm-assert ExpectedType $value
     *
     * @param mixed         $value
     * @param string|object $class
     * @param string        $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function isInstanceOf($value, $class, $message = '')
    {
        if (!$value instanceof $class) {
            static::reportInvalidArgument(\sprintf($message ?: 'Expected an instance of %2$s. Got: %s', static::typeToString($value), $class));
        }
    }
    /**
     * @psalm-pure
     *
     * @psalm-template ExpectedType of object
     *
     * @psalm-param class-string<ExpectedType> $class
     *
     * @psalm-assert !ExpectedType $value
     *
     * @param mixed         $value
     * @param string|object $class
     * @param string        $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function notInstanceOf($value, $class, $message = '')
    {
        if ($value instanceof $class) {
            static::reportInvalidArgument(\sprintf($message ?: 'Expected an instance other than %2$s. Got: %s', static::typeToString($value), $class));
        }
    }
    /**
     * @psalm-pure
     *
     * @psalm-param array<class-string> $classes
     *
     * @param mixed                $value
     * @param array<object|string> $classes
     * @param string               $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function isInstanceOfAny($value, array $classes, $message = '')
    {
        foreach ($classes as $class) {
            if ($value instanceof $class) {
                return;
            }
        }
        static::reportInvalidArgument(\sprintf($message ?: 'Expected an instance of any of %2$s. Got: %s', static::typeToString($value), \implode(', ', \array_map(array(static::class, 'valueToString'), $classes))));
    }
    /**
     * @psalm-pure
     *
     * @psalm-template ExpectedType of object
     *
     * @psalm-param class-string<ExpectedType> $class
     *
     * @psalm-assert ExpectedType|class-string<ExpectedType> $value
     *
     * @param object|string $value
     * @param string        $class
     * @param string        $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function isAOf($value, $class, $message = '')
    {
        static::string($class, 'Expected class as a string. Got: %s');
        if (!\is_a($value, $class, \is_string($value))) {
            static::reportInvalidArgument(sprintf($message ?: 'Expected an instance of this class or to this class among its parents "%2$s". Got: %s', static::valueToString($value), $class));
        }
    }
    /**
     * @psalm-pure
     *
     * @psalm-template UnexpectedType of object
     *
     * @psalm-param class-string<UnexpectedType> $class
     *
     * @psalm-assert !UnexpectedType $value
     * @psalm-assert !class-string<UnexpectedType> $value
     *
     * @param object|string $value
     * @param string        $class
     * @param string        $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function isNotA($value, $class, $message = '')
    {
        static::string($class, 'Expected class as a string. Got: %s');
        if (\is_a($value, $class, \is_string($value))) {
            static::reportInvalidArgument(sprintf($message ?: 'Expected an instance of this class or to this class among its parents other than "%2$s". Got: %s', static::valueToString($value), $class));
        }
    }
    /**
     * @psalm-pure
     *
     * @psalm-param array<class-string> $classes
     *
     * @param object|string $value
     * @param string[]      $classes
     * @param string        $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function isAnyOf($value, array $classes, $message = '')
    {
        foreach ($classes as $class) {
            static::string($class, 'Expected class as a string. Got: %s');
            if (\is_a($value, $class, \is_string($value))) {
                return;
            }
        }
        static::reportInvalidArgument(sprintf($message ?: 'Expected an instance of any of this classes or any of those classes among their parents "%2$s". Got: %s', static::valueToString($value), \implode(', ', $classes)));
    }
    /**
     * @psalm-pure
     *
     * @psalm-assert empty $value
     *
     * @param mixed  $value
     * @param string $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function isEmpty($value, $message = '')
    {
        if (!empty($value)) {
            static::reportInvalidArgument(\sprintf($message ?: 'Expected an empty value. Got: %s', static::valueToString($value)));
        }
    }
    /**
     * @psalm-pure
     *
     * @psalm-assert !empty $value
     *
     * @param mixed  $value
     * @param string $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function notEmpty($value, $message = '')
    {
        if (empty($value)) {
            static::reportInvalidArgument(\sprintf($message ?: 'Expected a non-empty value. Got: %s', static::valueToString($value)));
        }
    }
    /**
     * @psalm-pure
     *
     * @psalm-assert null $value
     *
     * @param mixed  $value
     * @param string $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function null($value, $message = '')
    {
        if (null !== $value) {
            static::reportInvalidArgument(\sprintf($message ?: 'Expected null. Got: %s', static::valueToString($value)));
        }
    }
    /**
     * @psalm-pure
     *
     * @psalm-assert !null $value
     *
     * @param mixed  $value
     * @param string $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function notNull($value, $message = '')
    {
        if (null === $value) {
            static::reportInvalidArgument($message ?: 'Expected a value other than null.');
        }
    }
    /**
     * @psalm-pure
     *
     * @psalm-assert true $value
     *
     * @param mixed  $value
     * @param string $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function true($value, $message = '')
    {
        if (\true !== $value) {
            static::reportInvalidArgument(\sprintf($message ?: 'Expected a value to be true. Got: %s', static::valueToString($value)));
        }
    }
    /**
     * @psalm-pure
     *
     * @psalm-assert false $value
     *
     * @param mixed  $value
     * @param string $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function false($value, $message = '')
    {
        if (\false !== $value) {
            static::reportInvalidArgument(\sprintf($message ?: 'Expected a value to be false. Got: %s', static::valueToString($value)));
        }
    }
    /**
     * @psalm-pure
     *
     * @psalm-assert !false $value
     *
     * @param mixed  $value
     * @param string $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function notFalse($value, $message = '')
    {
        if (\false === $value) {
            static::reportInvalidArgument($message ?: 'Expected a value other than false.');
        }
    }
    /**
     * @param mixed  $value
     * @param string $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function ip($value, $message = '')
    {
        if (\false === \filter_var($value, \FILTER_VALIDATE_IP)) {
            static::reportInvalidArgument(\sprintf($message ?: 'Expected a value to be an IP. Got: %s', static::valueToString($value)));
        }
    }
    /**
     * @param mixed  $value
     * @param string $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function ipv4($value, $message = '')
    {
        if (\false === \filter_var($value, \FILTER_VALIDATE_IP, \FILTER_FLAG_IPV4)) {
            static::reportInvalidArgument(\sprintf($message ?: 'Expected a value to be an IPv4. Got: %s', static::valueToString($value)));
        }
    }
    /**
     * @param mixed  $value
     * @param string $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function ipv6($value, $message = '')
    {
        if (\false === \filter_var($value, \FILTER_VALIDATE_IP, \FILTER_FLAG_IPV6)) {
            static::reportInvalidArgument(\sprintf($message ?: 'Expected a value to be an IPv6. Got: %s', static::valueToString($value)));
        }
    }
    /**
     * @param mixed  $value
     * @param string $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function email($value, $message = '')
    {
        if (\false === \filter_var($value, \FILTER_VALIDATE_EMAIL)) {
            static::reportInvalidArgument(\sprintf($message ?: 'Expected a value to be a valid e-mail address. Got: %s', static::valueToString($value)));
        }
    }
    /**
     * Does non strict comparisons on the items, so ['3', 3] will not pass the assertion.
     *
     * @param array  $values
     * @param string $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function uniqueValues(array $values, $message = '')
    {
        $allValues = \count($values);
        $uniqueValues = \count(\array_unique($values));
        if ($allValues !== $uniqueValues) {
            $difference = $allValues - $uniqueValues;
            static::reportInvalidArgument(\sprintf($message ?: 'Expected an array of unique values, but %s of them %s duplicated', $difference, 1 === $difference ? 'is' : 'are'));
        }
    }
    /**
     * @param mixed  $value
     * @param mixed  $expect
     * @param string $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function eq($value, $expect, $message = '')
    {
        if ($expect != $value) {
            static::reportInvalidArgument(\sprintf($message ?: 'Expected a value equal to %2$s. Got: %s', static::valueToString($value), static::valueToString($expect)));
        }
    }
    /**
     * @param mixed  $value
     * @param mixed  $expect
     * @param string $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function notEq($value, $expect, $message = '')
    {
        if ($expect == $value) {
            static::reportInvalidArgument(\sprintf($message ?: 'Expected a different value than %s.', static::valueToString($expect)));
        }
    }
    /**
     * @psalm-pure
     *
     * @param mixed  $value
     * @param mixed  $expect
     * @param string $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function same($value, $expect, $message = '')
    {
        if ($expect !== $value) {
            static::reportInvalidArgument(\sprintf($message ?: 'Expected a value identical to %2$s. Got: %s', static::valueToString($value), static::valueToString($expect)));
        }
    }
    /**
     * @psalm-pure
     *
     * @param mixed  $value
     * @param mixed  $expect
     * @param string $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function notSame($value, $expect, $message = '')
    {
        if ($expect === $value) {
            static::reportInvalidArgument(\sprintf($message ?: 'Expected a value not identical to %s.', static::valueToString($expect)));
        }
    }
    /**
     * @psalm-pure
     *
     * @param mixed  $value
     * @param mixed  $limit
     * @param string $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function greaterThan($value, $limit, $message = '')
    {
        if ($value <= $limit) {
            static::reportInvalidArgument(\sprintf($message ?: 'Expected a value greater than %2$s. Got: %s', static::valueToString($value), static::valueToString($limit)));
        }
    }
    /**
     * @psalm-pure
     *
     * @param mixed  $value
     * @param mixed  $limit
     * @param string $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function greaterThanEq($value, $limit, $message = '')
    {
        if ($value < $limit) {
            static::reportInvalidArgument(\sprintf($message ?: 'Expected a value greater than or equal to %2$s. Got: %s', static::valueToString($value), static::valueToString($limit)));
        }
    }
    /**
     * @psalm-pure
     *
     * @param mixed  $value
     * @param mixed  $limit
     * @param string $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function lessThan($value, $limit, $message = '')
    {
        if ($value >= $limit) {
            static::reportInvalidArgument(\sprintf($message ?: 'Expected a value less than %2$s. Got: %s', static::valueToString($value), static::valueToString($limit)));
        }
    }
    /**
     * @psalm-pure
     *
     * @param mixed  $value
     * @param mixed  $limit
     * @param string $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function lessThanEq($value, $limit, $message = '')
    {
        if ($value > $limit) {
            static::reportInvalidArgument(\sprintf($message ?: 'Expected a value less than or equal to %2$s. Got: %s', static::valueToString($value), static::valueToString($limit)));
        }
    }
    /**
     * Inclusive range, so Assert::(3, 3, 5) passes.
     *
     * @psalm-pure
     *
     * @param mixed  $value
     * @param mixed  $min
     * @param mixed  $max
     * @param string $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function range($value, $min, $max, $message = '')
    {
        if ($value < $min || $value > $max) {
            static::reportInvalidArgument(\sprintf($message ?: 'Expected a value between %2$s and %3$s. Got: %s', static::valueToString($value), static::valueToString($min), static::valueToString($max)));
        }
    }
    /**
     * A more human-readable alias of Assert::inArray().
     *
     * @psalm-pure
     *
     * @param mixed  $value
     * @param array  $values
     * @param string $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function oneOf($value, array $values, $message = '')
    {
        static::inArray($value, $values, $message);
    }
    /**
     * Does strict comparison, so Assert::inArray(3, ['3']) does not pass the assertion.
     *
     * @psalm-pure
     *
     * @param mixed  $value
     * @param array  $values
     * @param string $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function inArray($value, array $values, $message = '')
    {
        if (!\in_array($value, $values, \true)) {
            static::reportInvalidArgument(\sprintf($message ?: 'Expected one of: %2$s. Got: %s', static::valueToString($value), \implode(', ', \array_map(array(static::class, 'valueToString'), $values))));
        }
    }
    /**
     * @psalm-pure
     *
     * @param string $value
     * @param string $subString
     * @param string $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function contains($value, $subString, $message = '')
    {
        if (\false === \strpos($value, $subString)) {
            static::reportInvalidArgument(\sprintf($message ?: 'Expected a value to contain %2$s. Got: %s', static::valueToString($value), static::valueToString($subString)));
        }
    }
    /**
     * @psalm-pure
     *
     * @param string $value
     * @param string $subString
     * @param string $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function notContains($value, $subString, $message = '')
    {
        if (\false !== \strpos($value, $subString)) {
            static::reportInvalidArgument(\sprintf($message ?: '%2$s was not expected to be contained in a value. Got: %s', static::valueToString($value), static::valueToString($subString)));
        }
    }
    /**
     * @psalm-pure
     *
     * @param string $value
     * @param string $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function notWhitespaceOnly($value, $message = '')
    {
        if (\preg_match('/^\s*$/', $value)) {
            static::reportInvalidArgument(\sprintf($message ?: 'Expected a non-whitespace string. Got: %s', static::valueToString($value)));
        }
    }
    /**
     * @psalm-pure
     *
     * @param string $value
     * @param string $prefix
     * @param string $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function startsWith($value, $prefix, $message = '')
    {
        if (0 !== \strpos($value, $prefix)) {
            static::reportInvalidArgument(\sprintf($message ?: 'Expected a value to start with %2$s. Got: %s', static::valueToString($value), static::valueToString($prefix)));
        }
    }
    /**
     * @psalm-pure
     *
     * @param string $value
     * @param string $prefix
     * @param string $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function notStartsWith($value, $prefix, $message = '')
    {
        if (0 === \strpos($value, $prefix)) {
            static::reportInvalidArgument(\sprintf($message ?: 'Expected a value not to start with %2$s. Got: %s', static::valueToString($value), static::valueToString($prefix)));
        }
    }
    /**
     * @psalm-pure
     *
     * @param mixed  $value
     * @param string $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function startsWithLetter($value, $message = '')
    {
        static::string($value);
        $valid = isset($value[0]);
        if ($valid) {
            $locale = \setlocale(\LC_CTYPE, 0);
            \setlocale(\LC_CTYPE, 'C');
            $valid = \ctype_alpha($value[0]);
            \setlocale(\LC_CTYPE, $locale);
        }
        if (!$valid) {
            static::reportInvalidArgument(\sprintf($message ?: 'Expected a value to start with a letter. Got: %s', static::valueToString($value)));
        }
    }
    /**
     * @psalm-pure
     *
     * @param string $value
     * @param string $suffix
     * @param string $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function endsWith($value, $suffix, $message = '')
    {
        if ($suffix !== \substr($value, -\strlen($suffix))) {
            static::reportInvalidArgument(\sprintf($message ?: 'Expected a value to end with %2$s. Got: %s', static::valueToString($value), static::valueToString($suffix)));
        }
    }
    /**
     * @psalm-pure
     *
     * @param string $value
     * @param string $suffix
     * @param string $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function notEndsWith($value, $suffix, $message = '')
    {
        if ($suffix === \substr($value, -\strlen($suffix))) {
            static::reportInvalidArgument(\sprintf($message ?: 'Expected a value not to end with %2$s. Got: %s', static::valueToString($value), static::valueToString($suffix)));
        }
    }
    /**
     * @psalm-pure
     *
     * @param string $value
     * @param string $pattern
     * @param string $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function regex($value, $pattern, $message = '')
    {
        if (!\preg_match($pattern, $value)) {
            static::reportInvalidArgument(\sprintf($message ?: 'The value %s does not match the expected pattern.', static::valueToString($value)));
        }
    }
    /**
     * @psalm-pure
     *
     * @param string $value
     * @param string $pattern
     * @param string $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function notRegex($value, $pattern, $message = '')
    {
        if (\preg_match($pattern, $value, $matches, \PREG_OFFSET_CAPTURE)) {
            static::reportInvalidArgument(\sprintf($message ?: 'The value %s matches the pattern %s (at offset %d).', static::valueToString($value), static::valueToString($pattern), $matches[0][1]));
        }
    }
    /**
     * @psalm-pure
     *
     * @param mixed  $value
     * @param string $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function unicodeLetters($value, $message = '')
    {
        static::string($value);
        if (!\preg_match('/^\p{L}+$/u', $value)) {
            static::reportInvalidArgument(\sprintf($message ?: 'Expected a value to contain only Unicode letters. Got: %s', static::valueToString($value)));
        }
    }
    /**
     * @psalm-pure
     *
     * @param mixed  $value
     * @param string $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function alpha($value, $message = '')
    {
        static::string($value);
        $locale = \setlocale(\LC_CTYPE, 0);
        \setlocale(\LC_CTYPE, 'C');
        $valid = !\ctype_alpha($value);
        \setlocale(\LC_CTYPE, $locale);
        if ($valid) {
            static::reportInvalidArgument(\sprintf($message ?: 'Expected a value to contain only letters. Got: %s', static::valueToString($value)));
        }
    }
    /**
     * @psalm-pure
     *
     * @param string $value
     * @param string $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function digits($value, $message = '')
    {
        static::string($value);
        $locale = \setlocale(\LC_CTYPE, 0);
        \setlocale(\LC_CTYPE, 'C');
        $valid = !\ctype_digit($value);
        \setlocale(\LC_CTYPE, $locale);
        if ($valid) {
            static::reportInvalidArgument(\sprintf($message ?: 'Expected a value to contain digits only. Got: %s', static::valueToString($value)));
        }
    }
    /**
     * @psalm-pure
     *
     * @param string $value
     * @param string $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function alnum($value, $message = '')
    {
        static::string($value);
        $locale = \setlocale(\LC_CTYPE, 0);
        \setlocale(\LC_CTYPE, 'C');
        $valid = !\ctype_alnum($value);
        \setlocale(\LC_CTYPE, $locale);
        if ($valid) {
            static::reportInvalidArgument(\sprintf($message ?: 'Expected a value to contain letters and digits only. Got: %s', static::valueToString($value)));
        }
    }
    /**
     * @psalm-pure
     *
     * @psalm-assert lowercase-string $value
     *
     * @param string $value
     * @param string $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function lower($value, $message = '')
    {
        static::string($value);
        $locale = \setlocale(\LC_CTYPE, 0);
        \setlocale(\LC_CTYPE, 'C');
        $valid = !\ctype_lower($value);
        \setlocale(\LC_CTYPE, $locale);
        if ($valid) {
            static::reportInvalidArgument(\sprintf($message ?: 'Expected a value to contain lowercase characters only. Got: %s', static::valueToString($value)));
        }
    }
    /**
     * @psalm-pure
     *
     * @psalm-assert !lowercase-string $value
     *
     * @param string $value
     * @param string $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function upper($value, $message = '')
    {
        static::string($value);
        $locale = \setlocale(\LC_CTYPE, 0);
        \setlocale(\LC_CTYPE, 'C');
        $valid = !\ctype_upper($value);
        \setlocale(\LC_CTYPE, $locale);
        if ($valid) {
            static::reportInvalidArgument(\sprintf($message ?: 'Expected a value to contain uppercase characters only. Got: %s', static::valueToString($value)));
        }
    }
    /**
     * @psalm-pure
     *
     * @param string $value
     * @param int    $length
     * @param string $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function length($value, $length, $message = '')
    {
        if ($length !== static::strlen($value)) {
            static::reportInvalidArgument(\sprintf($message ?: 'Expected a value to contain %2$s characters. Got: %s', static::valueToString($value), $length));
        }
    }
    /**
     * Inclusive min.
     *
     * @psalm-pure
     *
     * @param string    $value
     * @param int|float $min
     * @param string    $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function minLength($value, $min, $message = '')
    {
        if (static::strlen($value) < $min) {
            static::reportInvalidArgument(\sprintf($message ?: 'Expected a value to contain at least %2$s characters. Got: %s', static::valueToString($value), $min));
        }
    }
    /**
     * Inclusive max.
     *
     * @psalm-pure
     *
     * @param string    $value
     * @param int|float $max
     * @param string    $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function maxLength($value, $max, $message = '')
    {
        if (static::strlen($value) > $max) {
            static::reportInvalidArgument(\sprintf($message ?: 'Expected a value to contain at most %2$s characters. Got: %s', static::valueToString($value), $max));
        }
    }
    /**
     * Inclusive , so Assert::lengthBetween('asd', 3, 5); passes the assertion.
     *
     * @psalm-pure
     *
     * @param string    $value
     * @param int|float $min
     * @param int|float $max
     * @param string    $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function lengthBetween($value, $min, $max, $message = '')
    {
        $length = static::strlen($value);
        if ($length < $min || $length > $max) {
            static::reportInvalidArgument(\sprintf($message ?: 'Expected a value to contain between %2$s and %3$s characters. Got: %s', static::valueToString($value), $min, $max));
        }
    }
    /**
     * Will also pass if $value is a directory, use Assert::file() instead if you need to be sure it is a file.
     *
     * @param mixed  $value
     * @param string $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function fileExists($value, $message = '')
    {
        if (!\file_exists($value)) {
            static::reportInvalidArgument(\sprintf($message ?: 'The path %s does not exist.', static::valueToString($value)));
        }
    }
    /**
     * @param mixed  $value
     * @param string $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function file($value, $message = '')
    {
        if (!\is_file($value)) {
            static::reportInvalidArgument(\sprintf($message ?: 'The path %s is not a file.', static::valueToString($value)));
        }
    }
    /**
     * @param mixed  $value
     * @param string $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function directory($value, $message = '')
    {
        if (!\is_dir($value)) {
            static::reportInvalidArgument(\sprintf($message ?: 'The path %s is not a directory.', static::valueToString($value)));
        }
    }
    /**
     * @param string $value
     * @param string $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function readable($value, $message = '')
    {
        if (!\is_readable($value)) {
            static::reportInvalidArgument(\sprintf($message ?: 'The path %s is not readable.', static::valueToString($value)));
        }
    }
    /**
     * @param string $value
     * @param string $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function writable($value, $message = '')
    {
        if (!\is_writable($value)) {
            static::reportInvalidArgument(\sprintf($message ?: 'The path %s is not writable.', static::valueToString($value)));
        }
    }
    /**
     * @psalm-assert class-string $value
     *
     * @param mixed  $value
     * @param string $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function classExists($value, $message = '')
    {
        if (!\class_exists($value)) {
            static::reportInvalidArgument(\sprintf($message ?: 'Expected an existing class name. Got: %s', static::valueToString($value)));
        }
    }
    /**
     * @psalm-pure
     *
     * @psalm-template ExpectedType of object
     *
     * @psalm-param class-string<ExpectedType> $class
     *
     * @psalm-assert class-string<ExpectedType>|ExpectedType $value
     *
     * @param mixed         $value
     * @param string|object $class
     * @param string        $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function subclassOf($value, $class, $message = '')
    {
        if (!\is_subclass_of($value, $class)) {
            static::reportInvalidArgument(\sprintf($message ?: 'Expected a sub-class of %2$s. Got: %s', static::valueToString($value), static::valueToString($class)));
        }
    }
    /**
     * @psalm-assert class-string $value
     *
     * @param mixed  $value
     * @param string $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function interfaceExists($value, $message = '')
    {
        if (!\interface_exists($value)) {
            static::reportInvalidArgument(\sprintf($message ?: 'Expected an existing interface name. got %s', static::valueToString($value)));
        }
    }
    /**
     * @psalm-pure
     *
     * @psalm-template ExpectedType of object
     *
     * @psalm-param class-string<ExpectedType> $interface
     *
     * @psalm-assert class-string<ExpectedType>|ExpectedType $value
     *
     * @param mixed  $value
     * @param mixed  $interface
     * @param string $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function implementsInterface($value, $interface, $message = '')
    {
        if (!\in_array($interface, \class_implements($value))) {
            static::reportInvalidArgument(\sprintf($message ?: 'Expected an implementation of %2$s. Got: %s', static::valueToString($value), static::valueToString($interface)));
        }
    }
    /**
     * @psalm-pure
     *
     * @psalm-param class-string|object $classOrObject
     *
     * @param string|object $classOrObject
     * @param mixed         $property
     * @param string        $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function propertyExists($classOrObject, $property, $message = '')
    {
        if (!\property_exists($classOrObject, $property)) {
            static::reportInvalidArgument(\sprintf($message ?: 'Expected the property %s to exist.', static::valueToString($property)));
        }
    }
    /**
     * @psalm-pure
     *
     * @psalm-param class-string|object $classOrObject
     *
     * @param string|object $classOrObject
     * @param mixed         $property
     * @param string        $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function propertyNotExists($classOrObject, $property, $message = '')
    {
        if (\property_exists($classOrObject, $property)) {
            static::reportInvalidArgument(\sprintf($message ?: 'Expected the property %s to not exist.', static::valueToString($property)));
        }
    }
    /**
     * @psalm-pure
     *
     * @psalm-param class-string|object $classOrObject
     *
     * @param string|object $classOrObject
     * @param mixed         $method
     * @param string        $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function methodExists($classOrObject, $method, $message = '')
    {
        if (!(\is_string($classOrObject) || \is_object($classOrObject)) || !\method_exists($classOrObject, $method)) {
            static::reportInvalidArgument(\sprintf($message ?: 'Expected the method %s to exist.', static::valueToString($method)));
        }
    }
    /**
     * @psalm-pure
     *
     * @psalm-param class-string|object $classOrObject
     *
     * @param string|object $classOrObject
     * @param mixed         $method
     * @param string        $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function methodNotExists($classOrObject, $method, $message = '')
    {
        if ((\is_string($classOrObject) || \is_object($classOrObject)) && \method_exists($classOrObject, $method)) {
            static::reportInvalidArgument(\sprintf($message ?: 'Expected the method %s to not exist.', static::valueToString($method)));
        }
    }
    /**
     * @psalm-pure
     *
     * @param array      $array
     * @param string|int $key
     * @param string     $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function keyExists($array, $key, $message = '')
    {
        if (!(isset($array[$key]) || \array_key_exists($key, $array))) {
            static::reportInvalidArgument(\sprintf($message ?: 'Expected the key %s to exist.', static::valueToString($key)));
        }
    }
    /**
     * @psalm-pure
     *
     * @param array      $array
     * @param string|int $key
     * @param string     $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function keyNotExists($array, $key, $message = '')
    {
        if (isset($array[$key]) || \array_key_exists($key, $array)) {
            static::reportInvalidArgument(\sprintf($message ?: 'Expected the key %s to not exist.', static::valueToString($key)));
        }
    }
    /**
     * Checks if a value is a valid array key (int or string).
     *
     * @psalm-pure
     *
     * @psalm-assert array-key $value
     *
     * @param mixed  $value
     * @param string $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function validArrayKey($value, $message = '')
    {
        if (!(\is_int($value) || \is_string($value))) {
            static::reportInvalidArgument(\sprintf($message ?: 'Expected string or integer. Got: %s', static::typeToString($value)));
        }
    }
    /**
     * Does not check if $array is countable, this can generate a warning on php versions after 7.2.
     *
     * @param Countable|array $array
     * @param int             $number
     * @param string          $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function count($array, $number, $message = '')
    {
        static::eq(\count($array), $number, \sprintf($message ?: 'Expected an array to contain %d elements. Got: %d.', $number, \count($array)));
    }
    /**
     * Does not check if $array is countable, this can generate a warning on php versions after 7.2.
     *
     * @param Countable|array $array
     * @param int|float       $min
     * @param string          $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function minCount($array, $min, $message = '')
    {
        if (\count($array) < $min) {
            static::reportInvalidArgument(\sprintf($message ?: 'Expected an array to contain at least %2$d elements. Got: %d', \count($array), $min));
        }
    }
    /**
     * Does not check if $array is countable, this can generate a warning on php versions after 7.2.
     *
     * @param Countable|array $array
     * @param int|float       $max
     * @param string          $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function maxCount($array, $max, $message = '')
    {
        if (\count($array) > $max) {
            static::reportInvalidArgument(\sprintf($message ?: 'Expected an array to contain at most %2$d elements. Got: %d', \count($array), $max));
        }
    }
    /**
     * Does not check if $array is countable, this can generate a warning on php versions after 7.2.
     *
     * @param Countable|array $array
     * @param int|float       $min
     * @param int|float       $max
     * @param string          $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function countBetween($array, $min, $max, $message = '')
    {
        $count = \count($array);
        if ($count < $min || $count > $max) {
            static::reportInvalidArgument(\sprintf($message ?: 'Expected an array to contain between %2$d and %3$d elements. Got: %d', $count, $min, $max));
        }
    }
    /**
     * @psalm-pure
     *
     * @psalm-assert list $array
     *
     * @param mixed  $array
     * @param string $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function isList($array, $message = '')
    {
        if (!\is_array($array)) {
            static::reportInvalidArgument($message ?: 'Expected list - non-associative array.');
        }
        if (\function_exists('array_is_list')) {
            if (!\array_is_list($array)) {
                static::reportInvalidArgument($message ?: 'Expected list - non-associative array.');
            }
            return;
        }
        if (array() === $array) {
            return;
        }
        $keys = array_keys($array);
        if (array_keys($keys) !== $keys) {
            static::reportInvalidArgument($message ?: 'Expected list - non-associative array.');
        }
    }
    /**
     * @psalm-pure
     *
     * @psalm-assert non-empty-list $array
     *
     * @param mixed  $array
     * @param string $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function isNonEmptyList($array, $message = '')
    {
        static::isList($array, $message);
        static::notEmpty($array, $message);
    }
    /**
     * @psalm-pure
     *
     * @psalm-template T
     *
     * @psalm-param mixed|array<T> $array
     *
     * @psalm-assert array<string, T> $array
     *
     * @param mixed  $array
     * @param string $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function isMap($array, $message = '')
    {
        if (!\is_array($array) || \array_keys($array) !== \array_filter(\array_keys($array), '\is_string')) {
            static::reportInvalidArgument($message ?: 'Expected map - associative array with string keys.');
        }
    }
    /**
     * @psalm-pure
     *
     * @psalm-template T
     *
     * @psalm-param mixed|array<T> $array
     *
     * @psalm-assert array<string, T> $array
     * @psalm-assert !empty $array
     *
     * @param mixed  $array
     * @param string $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function isNonEmptyMap($array, $message = '')
    {
        static::isMap($array, $message);
        static::notEmpty($array, $message);
    }
    /**
     * @psalm-pure
     *
     * @param string $value
     * @param string $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function uuid($value, $message = '')
    {
        $value = \str_replace(array('urn:', 'uuid:', '{', '}'), '', $value);
        // The nil UUID is special form of UUID that is specified to have all
        // 128 bits set to zero.
        if ('00000000-0000-0000-0000-000000000000' === $value) {
            return;
        }
        if (!\preg_match('/^[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{12}$/D', $value)) {
            static::reportInvalidArgument(\sprintf($message ?: 'Value %s is not a valid UUID.', static::valueToString($value)));
        }
    }
    /**
     * @psalm-param class-string<Throwable> $class
     *
     * @param Closure $expression
     * @param string  $class
     * @param string  $message
     *
     * @return void
     *
     * @throws InvalidArgumentException
     */
    public static function throws(Closure $expression, $class = 'Exception', $message = '')
    {
        static::string($class);
        $actual = 'none';
        try {
            $expression();
        } catch (Exception $e) {
            $actual = \get_class($e);
            if ($e instanceof $class) {
                return;
            }
        } catch (Throwable $e) {
            $actual = \get_class($e);
            if ($e instanceof $class) {
                return;
            }
        }
        static::reportInvalidArgument($message ?: \sprintf('Expected to throw "%s", got "%s"', $class, $actual));
    }
    /**
     * @throws BadMethodCallException
     */
    public static function __callStatic($name, $arguments)
    {
        if ('nullOr' === \substr($name, 0, 6)) {
            if (null !== $arguments[0]) {
                $method = \lcfirst(\substr($name, 6));
                \call_user_func_array(array(static::class, $method), $arguments);
            }
            return;
        }
        if ('all' === \substr($name, 0, 3)) {
            static::isIterable($arguments[0]);
            $method = \lcfirst(\substr($name, 3));
            $args = $arguments;
            foreach ($arguments[0] as $entry) {
                $args[0] = $entry;
                \call_user_func_array(array(static::class, $method), $args);
            }
            return;
        }
        throw new BadMethodCallException('No such method: ' . $name);
    }
    /**
     * @param mixed $value
     *
     * @return string
     */
    protected static function valueToString($value)
    {
        if (null === $value) {
            return 'null';
        }
        if (\true === $value) {
            return 'true';
        }
        if (\false === $value) {
            return 'false';
        }
        if (\is_array($value)) {
            return 'array';
        }
        if (\is_object($value)) {
            if (\method_exists($value, '__toString')) {
                return \get_class($value) . ': ' . self::valueToString($value->__toString());
            }
            if ($value instanceof DateTime || $value instanceof DateTimeImmutable) {
                return \get_class($value) . ': ' . self::valueToString($value->format('c'));
            }
            if (\function_exists('enum_exists') && \enum_exists(\get_class($value))) {
                return \get_class($value) . '::' . $value->name;
            }
            return \get_class($value);
        }
        if (\is_resource($value)) {
            return 'resource';
        }
        if (\is_string($value)) {
            return '"' . $value . '"';
        }
        return (string) $value;
    }
    /**
     * @psalm-pure
     *
     * @param mixed $value
     *
     * @return string
     */
    protected static function typeToString($value)
    {
        return \is_object($value) ? \get_class($value) : \gettype($value);
    }
    protected static function strlen($value)
    {
        if (!\function_exists('mb_detect_encoding') && !\function_exists('_ContaoManager\mb_detect_encoding')) {
            return \strlen($value);
        }
        if (\false === $encoding = \mb_detect_encoding($value)) {
            return \strlen($value);
        }
        return \mb_strlen($value, $encoding);
    }
    /**
     * @param string $message
     *
     * @throws InvalidArgumentException
     *
     * @psalm-pure this method is not supposed to perform side-effects
     *
     * @psalm-return never
     */
    protected static function reportInvalidArgument($message)
    {
        throw new InvalidArgumentException($message);
    }
    private function __construct()
    {
    }
}
The MIT License (MIT)

Copyright (c) 2012 Jan Sorgalla, Christian Lück, Cees-Jan Kiewiet, Chris Boden

Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
files (the "Software"), to deal in the Software without
restriction, including without limitation the rights to use,
copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following
conditions:

The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.
# Changelog

## 3.2.0 (2024-05-24)

*   Feature: Improve PHP 8.4+ support by avoiding implicitly nullable type declarations.
    (#260 by @Ayesh)

*   Feature: Include previous exceptions when reporting unhandled promise rejections.
    (#262 by @clue)

*   Update test suite to improve PHP 8.4+ support.
    (#261 by @SimonFrings)

## 3.1.0 (2023-11-16)

*   Feature: Full PHP 8.3 compatibility.
    (#255 by @clue)

*   Feature: Describe all callable arguments with types for `Promise` and `Deferred`.
    (#253 by @clue)

*   Update test suite and minor documentation improvements.
    (#251 by @ondrejmirtes and #250 by @SQKo)

## 3.0.0 (2023-07-11)

A major new feature release, see [**release announcement**](https://clue.engineering/2023/announcing-reactphp-promise-v3).

*   We'd like to emphasize that this component is production ready and battle-tested.
    We plan to support all long-term support (LTS) releases for at least 24 months,
    so you have a rock-solid foundation to build on top of.

*   The v3 release will be the way forward for this package. However, we will still
    actively support v2 and v1 to provide a smooth upgrade path for those not yet
    on the latest versions.

This update involves some major new features and a minor BC break over the
`v2.0.0` release. We've tried hard to avoid BC breaks where possible and
minimize impact otherwise. We expect that most consumers of this package will be
affected by BC breaks, but updating should take no longer than a few minutes.
See below for more details:

*   BC break: PHP 8.1+ recommended, PHP 7.1+ required.
    (#138 and #149 by @WyriHaximus)

*   Feature / BC break: The `PromiseInterface` now includes the functionality of the old ~~`ExtendedPromiseInterface`~~ and ~~`CancellablePromiseInterface`~~.
    Each promise now always includes the `then()`, `catch()`, `finally()` and `cancel()` methods.
    The new `catch()` and `finally()` methods replace the deprecated ~~`otherwise()`~~ and ~~`always()`~~ methods which continue to exist for BC reasons.
    The old ~~`ExtendedPromiseInterface`~~ and ~~`CancellablePromiseInterface`~~ are no longer needed and have been removed as a consequence.
    (#75 by @jsor and #208 by @clue and @WyriHaximus)

    ```php
    // old (multiple interfaces may or may not be implemented)
    assert($promise instanceof PromiseInterface);
    assert(method_exists($promise, 'then'));
    if ($promise instanceof ExtendedPromiseInterface) { assert(method_exists($promise, 'otherwise')); }
    if ($promise instanceof ExtendedPromiseInterface) { assert(method_exists($promise, 'always')); }
    if ($promise instanceof CancellablePromiseInterface) { assert(method_exists($promise, 'cancel')); }
    
    // new (single PromiseInterface with all methods)
    assert($promise instanceof PromiseInterface);
    assert(method_exists($promise, 'then'));
    assert(method_exists($promise, 'catch'));
    assert(method_exists($promise, 'finally'));
    assert(method_exists($promise, 'cancel'));
    ```

*   Feature / BC break: Improve type safety of promises. Require `mixed` fulfillment value argument and `Throwable` (or `Exception`) as rejection reason.
    Add PHPStan template types to ensure strict types for `resolve(T $value): PromiseInterface<T>` and `reject(Throwable $reason): PromiseInterface<never>`.
    It is no longer possible to resolve a promise without a value (use `null` instead) or reject a promise without a reason (use `Throwable` instead).
    (#93, #141 and #142 by @jsor, #138, #149 and #247 by @WyriHaximus and #213 and #246 by @clue)

    ```php
    // old (arguments used to be optional)
    $promise = resolve();
    $promise = reject();
    
    // new (already supported before)
    $promise = resolve(null);
    $promise = reject(new RuntimeException());
    ```

*   Feature / BC break: Report all unhandled rejections by default and remove ~~`done()`~~ method.
    Add new `set_rejection_handler()` function to set the global rejection handler for unhandled promise rejections.
    (#248, #249 and #224 by @clue)

    ```php
    // Unhandled promise rejection with RuntimeException: Unhandled in example.php:2
    reject(new RuntimeException('Unhandled'));
    ```

*   BC break: Remove all deprecated APIs and reduce API surface.
    Remove ~~`some()`~~, ~~`map()`~~, ~~`reduce()`~~ functions, use `any()` and `all()` functions instead.
    Remove internal ~~`FulfilledPromise`~~ and ~~`RejectedPromise`~~ classes, use `resolve()` and `reject()` functions instead.
    Remove legacy promise progress API (deprecated third argument to `then()` method) and deprecated ~~`LazyPromise`~~ class. 
    (#32 and #98 by @jsor and #164, #219 and #220 by @clue)

*   BC break: Make all classes final to encourage composition over inheritance.
    (#80 by @jsor)

*   Feature / BC break: Require `array` (or `iterable`) type for `all()` + `race()` + `any()` functions and bring in line with ES6 specification.
    These functions now require a single argument with a variable number of promises or values as input.
    (#225 by @clue and #35 by @jsor)

*   Fix / BC break: Fix `race()` to return a forever pending promise when called with an empty `array` (or `iterable`) and bring in line with ES6 specification.
    (#83 by @jsor and #225 by @clue)

*   Minor performance improvements by initializing `Deferred` in the constructor and avoiding `call_user_func()` calls.
    (#151 by @WyriHaximus and #171 by @Kubo2)

*   Minor documentation improvements.
    (#110 by @seregazhuk, #132 by @CharlotteDunois, #145 by @danielecr, #178 by @WyriHaximus, #189 by @srdante, #212 by @clue, #214, #239 and #243 by @SimonFrings and #231 by @nhedger)

The following changes had to be ported to this release due to our branching
strategy, but also appeared in the [`2.x` branch](https://github.com/reactphp/promise/tree/2.x):

*   Feature: Support union types and address deprecation of `ReflectionType::getClass()` (PHP 8+).
    (#197 by @cdosoftei and @SimonFrings)

*   Feature: Support intersection types (PHP 8.1+).
    (#209 by @bzikarsky)

*   Feature: Support DNS types (PHP 8.2+).
    (#236 by @nhedger)

*   Feature: Port all memory improvements from `2.x` to `3.x`.
    (#150 by @clue and @WyriHaximus)

*   Fix: Fix checking whether cancellable promise is an object and avoid possible warning.
    (#161 by @smscr)

*   Improve performance by prefixing all global functions calls with \ to skip the look up and resolve process and go straight to the global function.
    (#134 by @WyriHaximus)

*   Improve test suite, update PHPUnit and PHP versions and add `.gitattributes` to exclude dev files from exports.
    (#107 by @carusogabriel, #148 and #234 by @WyriHaximus, #153 by @reedy, #162, #230 and #240 by @clue, #173, #177, #185 and #199 by @SimonFrings, #193 by @woodongwong and #210 by @bzikarsky)

The following changes were originally planned for this release but later reverted
and are not part of the final release:

*   Add iterative callback queue handler to avoid recursion (later removed to improve Fiber support). 
    (#28, #82 and #86 by @jsor, #158 by @WyriHaximus and #229 and #238 by @clue)

*   Trigger an `E_USER_ERROR` instead of throwing an exception from `done()` (later removed entire `done()` method to globally report unhandled rejections).
    (#97 by @jsor and #224 and #248 by @clue)

*   Add type declarations for `some()` (later removed entire `some()` function).
    (#172 by @WyriHaximus and #219 by @clue)

## 2.0.0 (2013-12-10)

See [`2.x` CHANGELOG](https://github.com/reactphp/promise/blob/2.x/CHANGELOG.md) for more details.

## 1.0.0 (2012-11-07)

See [`1.x` CHANGELOG](https://github.com/reactphp/promise/blob/1.x/CHANGELOG.md) for more details.
Promise
=======

A lightweight implementation of
[CommonJS Promises/A](http://wiki.commonjs.org/wiki/Promises/A) for PHP.

[![CI status](https://github.com/reactphp/promise/workflows/CI/badge.svg)](https://github.com/reactphp/promise/actions)
[![installs on Packagist](https://img.shields.io/packagist/dt/react/promise?color=blue&label=installs%20on%20Packagist)](https://packagist.org/packages/react/promise)

Table of Contents
-----------------

1. [Introduction](#introduction)
2. [Concepts](#concepts)
   * [Deferred](#deferred)
   * [Promise](#promise-1)
3. [API](#api)
   * [Deferred](#deferred-1)
     * [Deferred::promise()](#deferredpromise)
     * [Deferred::resolve()](#deferredresolve)
     * [Deferred::reject()](#deferredreject)
   * [PromiseInterface](#promiseinterface)
     * [PromiseInterface::then()](#promiseinterfacethen)
     * [PromiseInterface::catch()](#promiseinterfacecatch)
     * [PromiseInterface::finally()](#promiseinterfacefinally)
     * [PromiseInterface::cancel()](#promiseinterfacecancel)
     * [~~PromiseInterface::otherwise()~~](#promiseinterfaceotherwise)
     * [~~PromiseInterface::always()~~](#promiseinterfacealways)
   * [Promise](#promise-2)
   * [Functions](#functions)
     * [resolve()](#resolve)
     * [reject()](#reject)
     * [all()](#all)
     * [race()](#race)
     * [any()](#any)
     * [set_rejection_handler()](#set_rejection_handler)
4. [Examples](#examples)
   * [How to use Deferred](#how-to-use-deferred)
   * [How promise forwarding works](#how-promise-forwarding-works)
     * [Resolution forwarding](#resolution-forwarding)
     * [Rejection forwarding](#rejection-forwarding)
     * [Mixed resolution and rejection forwarding](#mixed-resolution-and-rejection-forwarding)
5. [Install](#install)
6. [Tests](#tests)
7. [Credits](#credits)
8. [License](#license)

Introduction
------------

Promise is a library implementing
[CommonJS Promises/A](http://wiki.commonjs.org/wiki/Promises/A) for PHP.

It also provides several other useful promise-related concepts, such as joining
multiple promises and mapping and reducing collections of promises.

If you've never heard about promises before,
[read this first](https://gist.github.com/domenic/3889970).

Concepts
--------

### Deferred

A **Deferred** represents a computation or unit of work that may not have
completed yet. Typically (but not always), that computation will be something
that executes asynchronously and completes at some point in the future.

### Promise

While a deferred represents the computation itself, a **Promise** represents
the result of that computation. Thus, each deferred has a promise that acts as
a placeholder for its actual result.

API
---

### Deferred

A deferred represents an operation whose resolution is pending. It has separate
promise and resolver parts.

```php
$deferred = new React\Promise\Deferred();

$promise = $deferred->promise();

$deferred->resolve(mixed $value);
$deferred->reject(\Throwable $reason);
```

The `promise` method returns the promise of the deferred.

The `resolve` and `reject` methods control the state of the deferred.

The constructor of the `Deferred` accepts an optional `$canceller` argument.
See [Promise](#promise-2) for more information.

#### Deferred::promise()

```php
$promise = $deferred->promise();
```

Returns the promise of the deferred, which you can hand out to others while
keeping the authority to modify its state to yourself.

#### Deferred::resolve()

```php
$deferred->resolve(mixed $value);
```

Resolves the promise returned by `promise()`. All consumers are notified by
having `$onFulfilled` (which they registered via `$promise->then()`) called with
`$value`.

If `$value` itself is a promise, the promise will transition to the state of
this promise once it is resolved.

See also the [`resolve()` function](#resolve).

#### Deferred::reject()

```php
$deferred->reject(\Throwable $reason);
```

Rejects the promise returned by `promise()`, signalling that the deferred's
computation failed.
All consumers are notified by having `$onRejected` (which they registered via
`$promise->then()`) called with `$reason`.

See also the [`reject()` function](#reject).

### PromiseInterface

The promise interface provides the common interface for all promise
implementations.
See [Promise](#promise-2) for the only public implementation exposed by this
package.

A promise represents an eventual outcome, which is either fulfillment (success)
and an associated value, or rejection (failure) and an associated reason.

Once in the fulfilled or rejected state, a promise becomes immutable.
Neither its state nor its result (or error) can be modified.

#### PromiseInterface::then()

```php
$transformedPromise = $promise->then(callable $onFulfilled = null, callable $onRejected = null);
```

Transforms a promise's value by applying a function to the promise's fulfillment
or rejection value. Returns a new promise for the transformed result.

The `then()` method registers new fulfilled and rejection handlers with a promise
(all parameters are optional):

  * `$onFulfilled` will be invoked once the promise is fulfilled and passed
    the result as the first argument.
  * `$onRejected` will be invoked once the promise is rejected and passed the
    reason as the first argument.

It returns a new promise that will fulfill with the return value of either
`$onFulfilled` or `$onRejected`, whichever is called, or will reject with
the thrown exception if either throws.

A promise makes the following guarantees about handlers registered in
the same call to `then()`:

  1. Only one of `$onFulfilled` or `$onRejected` will be called,
     never both.
  2. `$onFulfilled` and `$onRejected` will never be called more
     than once.

#### See also

* [resolve()](#resolve) - Creating a resolved promise
* [reject()](#reject) - Creating a rejected promise

#### PromiseInterface::catch()

```php
$promise->catch(callable $onRejected);
```

Registers a rejection handler for promise. It is a shortcut for:

```php
$promise->then(null, $onRejected);
```

Additionally, you can type hint the `$reason` argument of `$onRejected` to catch
only specific errors.

```php
$promise
    ->catch(function (\RuntimeException $reason) {
        // Only catch \RuntimeException instances
        // All other types of errors will propagate automatically
    })
    ->catch(function (\Throwable $reason) {
        // Catch other errors
    });
```

#### PromiseInterface::finally()

```php
$newPromise = $promise->finally(callable $onFulfilledOrRejected);
```

Allows you to execute "cleanup" type tasks in a promise chain.

It arranges for `$onFulfilledOrRejected` to be called, with no arguments,
when the promise is either fulfilled or rejected.

* If `$promise` fulfills, and `$onFulfilledOrRejected` returns successfully,
  `$newPromise` will fulfill with the same value as `$promise`.
* If `$promise` fulfills, and `$onFulfilledOrRejected` throws or returns a
  rejected promise, `$newPromise` will reject with the thrown exception or
  rejected promise's reason.
* If `$promise` rejects, and `$onFulfilledOrRejected` returns successfully,
  `$newPromise` will reject with the same reason as `$promise`.
* If `$promise` rejects, and `$onFulfilledOrRejected` throws or returns a
  rejected promise, `$newPromise` will reject with the thrown exception or
  rejected promise's reason.

`finally()` behaves similarly to the synchronous finally statement. When combined
with `catch()`, `finally()` allows you to write code that is similar to the familiar
synchronous catch/finally pair.

Consider the following synchronous code:

```php
try {
    return doSomething();
} catch (\Throwable $e) {
    return handleError($e);
} finally {
    cleanup();
}
```

Similar asynchronous code (with `doSomething()` that returns a promise) can be
written:

```php
return doSomething()
    ->catch('handleError')
    ->finally('cleanup');
```

#### PromiseInterface::cancel()

``` php
$promise->cancel();
```

The `cancel()` method notifies the creator of the promise that there is no
further interest in the results of the operation.

Once a promise is settled (either fulfilled or rejected), calling `cancel()` on
a promise has no effect.

#### ~~PromiseInterface::otherwise()~~

> Deprecated since v3.0.0, see [`catch()`](#promiseinterfacecatch) instead.

The `otherwise()` method registers a rejection handler for a promise.

This method continues to exist only for BC reasons and to ease upgrading
between versions. It is an alias for:

```php
$promise->catch($onRejected);
```

#### ~~PromiseInterface::always()~~

> Deprecated since v3.0.0, see [`finally()`](#promiseinterfacefinally) instead.

The `always()` method allows you to execute "cleanup" type tasks in a promise chain.

This method continues to exist only for BC reasons and to ease upgrading
between versions. It is an alias for:

```php
$promise->finally($onFulfilledOrRejected);
```

### Promise

Creates a promise whose state is controlled by the functions passed to
`$resolver`.

```php
$resolver = function (callable $resolve, callable $reject) {
    // Do some work, possibly asynchronously, and then
    // resolve or reject.

    $resolve($awesomeResult);
    // or throw new Exception('Promise rejected');
    // or $resolve($anotherPromise);
    // or $reject($nastyError);
};

$canceller = function () {
    // Cancel/abort any running operations like network connections, streams etc.

    // Reject promise by throwing an exception
    throw new Exception('Promise cancelled');
};

$promise = new React\Promise\Promise($resolver, $canceller);
```

The promise constructor receives a resolver function and an optional canceller
function which both will be called with two arguments:

  * `$resolve($value)` - Primary function that seals the fate of the
    returned promise. Accepts either a non-promise value, or another promise.
    When called with a non-promise value, fulfills promise with that value.
    When called with another promise, e.g. `$resolve($otherPromise)`, promise's
    fate will be equivalent to that of `$otherPromise`.
  * `$reject($reason)` - Function that rejects the promise. It is recommended to
    just throw an exception instead of using `$reject()`.

If the resolver or canceller throw an exception, the promise will be rejected
with that thrown exception as the rejection reason.

The resolver function will be called immediately, the canceller function only
once all consumers called the `cancel()` method of the promise.

### Functions

Useful functions for creating and joining collections of promises.

All functions working on promise collections (like `all()`, `race()`,
etc.) support cancellation. This means, if you call `cancel()` on the returned
promise, all promises in the collection are cancelled.

#### resolve()

```php
$promise = React\Promise\resolve(mixed $promiseOrValue);
```

Creates a promise for the supplied `$promiseOrValue`.

If `$promiseOrValue` is a value, it will be the resolution value of the
returned promise.

If `$promiseOrValue` is a thenable (any object that provides a `then()` method),
a trusted promise that follows the state of the thenable is returned.

If `$promiseOrValue` is a promise, it will be returned as is.

The resulting `$promise` implements the [`PromiseInterface`](#promiseinterface)
and can be consumed like any other promise:

```php
$promise = React\Promise\resolve(42);

$promise->then(function (int $result): void {
    var_dump($result);
}, function (\Throwable $e): void {
    echo 'Error: ' . $e->getMessage() . PHP_EOL;
});
```

#### reject()

```php
$promise = React\Promise\reject(\Throwable $reason);
```

Creates a rejected promise for the supplied `$reason`.

Note that the [`\Throwable`](https://www.php.net/manual/en/class.throwable.php) interface introduced in PHP 7 covers 
both user land [`\Exception`](https://www.php.net/manual/en/class.exception.php)'s and 
[`\Error`](https://www.php.net/manual/en/class.error.php) internal PHP errors. By enforcing `\Throwable` as reason to 
reject a promise, any language error or user land exception can be used to reject a promise.

The resulting `$promise` implements the [`PromiseInterface`](#promiseinterface)
and can be consumed like any other promise:

```php
$promise = React\Promise\reject(new RuntimeException('Request failed'));

$promise->then(function (int $result): void {
    var_dump($result);
}, function (\Throwable $e): void {
    echo 'Error: ' . $e->getMessage() . PHP_EOL;
});
```

Note that rejected promises should always be handled similar to how any
exceptions should always be caught in a `try` + `catch` block. If you remove the
last reference to a rejected promise that has not been handled, it will
report an unhandled promise rejection:

```php
function incorrect(): int
{
     $promise = React\Promise\reject(new RuntimeException('Request failed'));

     // Commented out: No rejection handler registered here.
     // $promise->then(null, function (\Throwable $e): void { /* ignore */ });

     // Returning from a function will remove all local variable references, hence why
     // this will report an unhandled promise rejection here.
     return 42;
}

// Calling this function will log an error message plus its stack trace:
// Unhandled promise rejection with RuntimeException: Request failed in example.php:10
incorrect();
```

A rejected promise will be considered "handled" if you catch the rejection
reason with either the [`then()` method](#promiseinterfacethen), the
[`catch()` method](#promiseinterfacecatch), or the
[`finally()` method](#promiseinterfacefinally). Note that each of these methods
return a new promise that may again be rejected if you re-throw an exception.

A rejected promise will also be considered "handled" if you abort the operation
with the [`cancel()` method](#promiseinterfacecancel) (which in turn would
usually reject the promise if it is still pending).

See also the [`set_rejection_handler()` function](#set_rejection_handler).

#### all()

```php
$promise = React\Promise\all(iterable $promisesOrValues);
```

Returns a promise that will resolve only once all the items in
`$promisesOrValues` have resolved. The resolution value of the returned promise
will be an array containing the resolution values of each of the items in
`$promisesOrValues`.

#### race()

```php
$promise = React\Promise\race(iterable $promisesOrValues);
```

Initiates a competitive race that allows one winner. Returns a promise which is
resolved in the same way the first settled promise resolves.

The returned promise will become **infinitely pending** if  `$promisesOrValues`
contains 0 items.

#### any()

```php
$promise = React\Promise\any(iterable $promisesOrValues);
```

Returns a promise that will resolve when any one of the items in
`$promisesOrValues` resolves. The resolution value of the returned promise
will be the resolution value of the triggering item.

The returned promise will only reject if *all* items in `$promisesOrValues` are
rejected. The rejection value will be a `React\Promise\Exception\CompositeException`
which holds all rejection reasons. The rejection reasons can be obtained with
`CompositeException::getThrowables()`.

The returned promise will also reject with a `React\Promise\Exception\LengthException`
if `$promisesOrValues` contains 0 items.

#### set_rejection_handler()

```php
React\Promise\set_rejection_handler(?callable $callback): ?callable;
```

Sets the global rejection handler for unhandled promise rejections.

Note that rejected promises should always be handled similar to how any
exceptions should always be caught in a `try` + `catch` block. If you remove
the last reference to a rejected promise that has not been handled, it will
report an unhandled promise rejection. See also the [`reject()` function](#reject)
for more details.

The `?callable $callback` argument MUST be a valid callback function that
accepts a single `Throwable` argument or a `null` value to restore the
default promise rejection handler. The return value of the callback function
will be ignored and has no effect, so you SHOULD return a `void` value. The
callback function MUST NOT throw or the program will be terminated with a
fatal error.

The function returns the previous rejection handler or `null` if using the
default promise rejection handler.

The default promise rejection handler will log an error message plus its stack
trace:

```php
// Unhandled promise rejection with RuntimeException: Unhandled in example.php:2
React\Promise\reject(new RuntimeException('Unhandled'));
```

The promise rejection handler may be used to use customize the log message or
write to custom log targets. As a rule of thumb, this function should only be
used as a last resort and promise rejections are best handled with either the
[`then()` method](#promiseinterfacethen), the
[`catch()` method](#promiseinterfacecatch), or the
[`finally()` method](#promiseinterfacefinally).
See also the [`reject()` function](#reject) for more details.

Examples
--------

### How to use Deferred

```php
function getAwesomeResultPromise()
{
    $deferred = new React\Promise\Deferred();

    // Execute a Node.js-style function using the callback pattern
    computeAwesomeResultAsynchronously(function (\Throwable $error, $result) use ($deferred) {
        if ($error) {
            $deferred->reject($error);
        } else {
            $deferred->resolve($result);
        }
    });

    // Return the promise
    return $deferred->promise();
}

getAwesomeResultPromise()
    ->then(
        function ($value) {
            // Deferred resolved, do something with $value
        },
        function (\Throwable $reason) {
            // Deferred rejected, do something with $reason
        }
    );
```

### How promise forwarding works

A few simple examples to show how the mechanics of Promises/A forwarding works.
These examples are contrived, of course, and in real usage, promise chains will
typically be spread across several function calls, or even several levels of
your application architecture.

#### Resolution forwarding

Resolved promises forward resolution values to the next promise.
The first promise, `$deferred->promise()`, will resolve with the value passed
to `$deferred->resolve()` below.

Each call to `then()` returns a new promise that will resolve with the return
value of the previous handler. This creates a promise "pipeline".

```php
$deferred = new React\Promise\Deferred();

$deferred->promise()
    ->then(function ($x) {
        // $x will be the value passed to $deferred->resolve() below
        // and returns a *new promise* for $x + 1
        return $x + 1;
    })
    ->then(function ($x) {
        // $x === 2
        // This handler receives the return value of the
        // previous handler.
        return $x + 1;
    })
    ->then(function ($x) {
        // $x === 3
        // This handler receives the return value of the
        // previous handler.
        return $x + 1;
    })
    ->then(function ($x) {
        // $x === 4
        // This handler receives the return value of the
        // previous handler.
        echo 'Resolve ' . $x;
    });

$deferred->resolve(1); // Prints "Resolve 4"
```

#### Rejection forwarding

Rejected promises behave similarly, and also work similarly to try/catch:
When you catch an exception, you must rethrow for it to propagate.

Similarly, when you handle a rejected promise, to propagate the rejection,
"rethrow" it by either returning a rejected promise, or actually throwing
(since promise translates thrown exceptions into rejections)

```php
$deferred = new React\Promise\Deferred();

$deferred->promise()
    ->then(function ($x) {
        throw new \Exception($x + 1);
    })
    ->catch(function (\Exception $x) {
        // Propagate the rejection
        throw $x;
    })
    ->catch(function (\Exception $x) {
        // Can also propagate by returning another rejection
        return React\Promise\reject(
            new \Exception($x->getMessage() + 1)
        );
    })
    ->catch(function ($x) {
        echo 'Reject ' . $x->getMessage(); // 3
    });

$deferred->resolve(1);  // Prints "Reject 3"
```

#### Mixed resolution and rejection forwarding

Just like try/catch, you can choose to propagate or not. Mixing resolutions and
rejections will still forward handler results in a predictable way.

```php
$deferred = new React\Promise\Deferred();

$deferred->promise()
    ->then(function ($x) {
        return $x + 1;
    })
    ->then(function ($x) {
        throw new \Exception($x + 1);
    })
    ->catch(function (\Exception $x) {
        // Handle the rejection, and don't propagate.
        // This is like catch without a rethrow
        return $x->getMessage() + 1;
    })
    ->then(function ($x) {
        echo 'Mixed ' . $x; // 4
    });

$deferred->resolve(1);  // Prints "Mixed 4"
```

Install
-------

The recommended way to install this library is [through Composer](https://getcomposer.org/).
[New to Composer?](https://getcomposer.org/doc/00-intro.md)

This project follows [SemVer](https://semver.org/).
This will install the latest supported version from this branch:

```bash
composer require react/promise:^3.2
```

See also the [CHANGELOG](CHANGELOG.md) for details about version upgrades.

This project aims to run on any platform and thus does not require any PHP
extensions and supports running on PHP 7.1 through current PHP 8+.
It's *highly recommended to use the latest supported PHP version* for this project.

We're committed to providing long-term support (LTS) options and to provide a
smooth upgrade path. If you're using an older PHP version, you may use the
[`2.x` branch](https://github.com/reactphp/promise/tree/2.x) (PHP 5.4+) or
[`1.x` branch](https://github.com/reactphp/promise/tree/1.x) (PHP 5.3+) which both
provide a compatible API but do not take advantage of newer language features.
You may target multiple versions at the same time to support a wider range of
PHP versions like this:

```bash
composer require "react/promise:^3 || ^2 || ^1"
```

## Tests

To run the test suite, you first need to clone this repo and then install all
dependencies [through Composer](https://getcomposer.org/):

```bash
composer install
```

To run the test suite, go to the project root and run:

```bash
vendor/bin/phpunit
```

On top of this, we use PHPStan on max level to ensure type safety across the project:

```bash
vendor/bin/phpstan
```

Credits
-------

Promise is a port of [when.js](https://github.com/cujojs/when)
by [Brian Cavalier](https://github.com/briancavalier).

Also, large parts of the documentation have been ported from the when.js
[Wiki](https://github.com/cujojs/when/wiki) and the
[API docs](https://github.com/cujojs/when/blob/master/docs/api.md).

License
-------

Released under the [MIT](LICENSE) license.
{
    "name": "react\/promise",
    "description": "A lightweight implementation of CommonJS Promises\/A for PHP",
    "license": "MIT",
    "authors": [
        {
            "name": "Jan Sorgalla",
            "homepage": "https:\/\/sorgalla.com\/",
            "email": "jsorgalla@gmail.com"
        },
        {
            "name": "Christian L\u00fcck",
            "homepage": "https:\/\/clue.engineering\/",
            "email": "christian@clue.engineering"
        },
        {
            "name": "Cees-Jan Kiewiet",
            "homepage": "https:\/\/wyrihaximus.net\/",
            "email": "reactphp@ceesjankiewiet.nl"
        },
        {
            "name": "Chris Boden",
            "homepage": "https:\/\/cboden.dev\/",
            "email": "cboden@gmail.com"
        }
    ],
    "require": {
        "php": ">=7.1.0"
    },
    "require-dev": {
        "phpstan\/phpstan": "1.12.28 || 1.4.10",
        "phpunit\/phpunit": "^9.6 || ^7.5"
    },
    "autoload": {
        "psr-4": {
            "React\\Promise\\": "src\/"
        },
        "files": [
            "src\/functions_include.php"
        ]
    },
    "autoload-dev": {
        "psr-4": {
            "React\\Promise\\": [
                "tests\/fixtures\/",
                "tests\/"
            ]
        },
        "files": [
            "tests\/Fiber.php"
        ]
    },
    "keywords": [
        "promise",
        "promises"
    ]
}<?php

namespace React\Promise;

/**
 * @template-covariant T
 */
interface PromiseInterface
{
    /**
     * Transforms a promise's value by applying a function to the promise's fulfillment
     * or rejection value. Returns a new promise for the transformed result.
     *
     * The `then()` method registers new fulfilled and rejection handlers with a promise
     * (all parameters are optional):
     *
     *  * `$onFulfilled` will be invoked once the promise is fulfilled and passed
     *     the result as the first argument.
     *  * `$onRejected` will be invoked once the promise is rejected and passed the
     *     reason as the first argument.
     *
     * It returns a new promise that will fulfill with the return value of either
     * `$onFulfilled` or `$onRejected`, whichever is called, or will reject with
     * the thrown exception if either throws.
     *
     * A promise makes the following guarantees about handlers registered in
     * the same call to `then()`:
     *
     *  1. Only one of `$onFulfilled` or `$onRejected` will be called,
     *      never both.
     *  2. `$onFulfilled` and `$onRejected` will never be called more
     *      than once.
     *
     * @template TFulfilled
     * @template TRejected
     * @param ?(callable((T is void ? null : T)): (PromiseInterface<TFulfilled>|TFulfilled)) $onFulfilled
     * @param ?(callable(\Throwable): (PromiseInterface<TRejected>|TRejected)) $onRejected
     * @return PromiseInterface<($onRejected is null ? ($onFulfilled is null ? T : TFulfilled) : ($onFulfilled is null ? T|TRejected : TFulfilled|TRejected))>
     */
    public function then(?callable $onFulfilled = null, ?callable $onRejected = null): \React\Promise\PromiseInterface;
    /**
     * Registers a rejection handler for promise. It is a shortcut for:
     *
     * ```php
     * $promise->then(null, $onRejected);
     * ```
     *
     * Additionally, you can type hint the `$reason` argument of `$onRejected` to catch
     * only specific errors.
     *
     * @template TThrowable of \Throwable
     * @template TRejected
     * @param callable(TThrowable): (PromiseInterface<TRejected>|TRejected) $onRejected
     * @return PromiseInterface<T|TRejected>
     */
    public function catch(callable $onRejected): \React\Promise\PromiseInterface;
    /**
     * Allows you to execute "cleanup" type tasks in a promise chain.
     *
     * It arranges for `$onFulfilledOrRejected` to be called, with no arguments,
     * when the promise is either fulfilled or rejected.
     *
     * * If `$promise` fulfills, and `$onFulfilledOrRejected` returns successfully,
     *    `$newPromise` will fulfill with the same value as `$promise`.
     * * If `$promise` fulfills, and `$onFulfilledOrRejected` throws or returns a
     *    rejected promise, `$newPromise` will reject with the thrown exception or
     *    rejected promise's reason.
     * * If `$promise` rejects, and `$onFulfilledOrRejected` returns successfully,
     *    `$newPromise` will reject with the same reason as `$promise`.
     * * If `$promise` rejects, and `$onFulfilledOrRejected` throws or returns a
     *    rejected promise, `$newPromise` will reject with the thrown exception or
     *    rejected promise's reason.
     *
     * `finally()` behaves similarly to the synchronous finally statement. When combined
     * with `catch()`, `finally()` allows you to write code that is similar to the familiar
     * synchronous catch/finally pair.
     *
     * Consider the following synchronous code:
     *
     * ```php
     * try {
     *     return doSomething();
     * } catch(\Exception $e) {
     *     return handleError($e);
     * } finally {
     *     cleanup();
     * }
     * ```
     *
     * Similar asynchronous code (with `doSomething()` that returns a promise) can be
     * written:
     *
     * ```php
     * return doSomething()
     *     ->catch('handleError')
     *     ->finally('cleanup');
     * ```
     *
     * @param callable(): (void|PromiseInterface<void>) $onFulfilledOrRejected
     * @return PromiseInterface<T>
     */
    public function finally(callable $onFulfilledOrRejected): \React\Promise\PromiseInterface;
    /**
     * The `cancel()` method notifies the creator of the promise that there is no
     * further interest in the results of the operation.
     *
     * Once a promise is settled (either fulfilled or rejected), calling `cancel()` on
     * a promise has no effect.
     *
     * @return void
     */
    public function cancel(): void;
    /**
     * [Deprecated] Registers a rejection handler for a promise.
     *
     * This method continues to exist only for BC reasons and to ease upgrading
     * between versions. It is an alias for:
     *
     * ```php
     * $promise->catch($onRejected);
     * ```
     *
     * @template TThrowable of \Throwable
     * @template TRejected
     * @param callable(TThrowable): (PromiseInterface<TRejected>|TRejected) $onRejected
     * @return PromiseInterface<T|TRejected>
     * @deprecated 3.0.0 Use catch() instead
     * @see self::catch()
     */
    public function otherwise(callable $onRejected): \React\Promise\PromiseInterface;
    /**
     * [Deprecated] Allows you to execute "cleanup" type tasks in a promise chain.
     *
     * This method continues to exist only for BC reasons and to ease upgrading
     * between versions. It is an alias for:
     *
     * ```php
     * $promise->finally($onFulfilledOrRejected);
     * ```
     *
     * @param callable(): (void|PromiseInterface<void>) $onFulfilledOrRejected
     * @return PromiseInterface<T>
     * @deprecated 3.0.0 Use finally() instead
     * @see self::finally()
     */
    public function always(callable $onFulfilledOrRejected): \React\Promise\PromiseInterface;
}
<?php

namespace React\Promise;

use React\Promise\Exception\CompositeException;
use React\Promise\Internal\FulfilledPromise;
use React\Promise\Internal\RejectedPromise;
/**
 * Creates a promise for the supplied `$promiseOrValue`.
 *
 * If `$promiseOrValue` is a value, it will be the resolution value of the
 * returned promise.
 *
 * If `$promiseOrValue` is a thenable (any object that provides a `then()` method),
 * a trusted promise that follows the state of the thenable is returned.
 *
 * If `$promiseOrValue` is a promise, it will be returned as is.
 *
 * @template T
 * @param PromiseInterface<T>|T $promiseOrValue
 * @return PromiseInterface<T>
 */
function resolve($promiseOrValue): \React\Promise\PromiseInterface
{
    if ($promiseOrValue instanceof \React\Promise\PromiseInterface) {
        return $promiseOrValue;
    }
    if (\is_object($promiseOrValue) && \method_exists($promiseOrValue, 'then')) {
        $canceller = null;
        if (\method_exists($promiseOrValue, 'cancel')) {
            $canceller = [$promiseOrValue, 'cancel'];
            assert(\is_callable($canceller));
        }
        /** @var Promise<T> */
        return new \React\Promise\Promise(function (callable $resolve, callable $reject) use ($promiseOrValue): void {
            $promiseOrValue->then($resolve, $reject);
        }, $canceller);
    }
    return new FulfilledPromise($promiseOrValue);
}
/**
 * Creates a rejected promise for the supplied `$reason`.
 *
 * If `$reason` is a value, it will be the rejection value of the
 * returned promise.
 *
 * If `$reason` is a promise, its completion value will be the rejected
 * value of the returned promise.
 *
 * This can be useful in situations where you need to reject a promise without
 * throwing an exception. For example, it allows you to propagate a rejection with
 * the value of another promise.
 *
 * @return PromiseInterface<never>
 */
function reject(\Throwable $reason): \React\Promise\PromiseInterface
{
    return new RejectedPromise($reason);
}
/**
 * Returns a promise that will resolve only once all the items in
 * `$promisesOrValues` have resolved. The resolution value of the returned promise
 * will be an array containing the resolution values of each of the items in
 * `$promisesOrValues`.
 *
 * @template T
 * @param iterable<PromiseInterface<T>|T> $promisesOrValues
 * @return PromiseInterface<array<T>>
 */
function all(iterable $promisesOrValues): \React\Promise\PromiseInterface
{
    $cancellationQueue = new \React\Promise\Internal\CancellationQueue();
    /** @var Promise<array<T>> */
    return new \React\Promise\Promise(function (callable $resolve, callable $reject) use ($promisesOrValues, $cancellationQueue): void {
        $toResolve = 0;
        /** @var bool */
        $continue = \true;
        $values = [];
        foreach ($promisesOrValues as $i => $promiseOrValue) {
            $cancellationQueue->enqueue($promiseOrValue);
            $values[$i] = null;
            ++$toResolve;
            resolve($promiseOrValue)->then(function ($value) use ($i, &$values, &$toResolve, &$continue, $resolve): void {
                $values[$i] = $value;
                if (0 === --$toResolve && !$continue) {
                    $resolve($values);
                }
            }, function (\Throwable $reason) use (&$continue, $reject): void {
                $continue = \false;
                $reject($reason);
            });
            if (!$continue && !\is_array($promisesOrValues)) {
                break;
            }
        }
        $continue = \false;
        if ($toResolve === 0) {
            $resolve($values);
        }
    }, $cancellationQueue);
}
/**
 * Initiates a competitive race that allows one winner. Returns a promise which is
 * resolved in the same way the first settled promise resolves.
 *
 * The returned promise will become **infinitely pending** if  `$promisesOrValues`
 * contains 0 items.
 *
 * @template T
 * @param iterable<PromiseInterface<T>|T> $promisesOrValues
 * @return PromiseInterface<T>
 */
function race(iterable $promisesOrValues): \React\Promise\PromiseInterface
{
    $cancellationQueue = new \React\Promise\Internal\CancellationQueue();
    /** @var Promise<T> */
    return new \React\Promise\Promise(function (callable $resolve, callable $reject) use ($promisesOrValues, $cancellationQueue): void {
        $continue = \true;
        foreach ($promisesOrValues as $promiseOrValue) {
            $cancellationQueue->enqueue($promiseOrValue);
            resolve($promiseOrValue)->then($resolve, $reject)->finally(function () use (&$continue): void {
                $continue = \false;
            });
            if (!$continue && !\is_array($promisesOrValues)) {
                break;
            }
        }
    }, $cancellationQueue);
}
/**
 * Returns a promise that will resolve when any one of the items in
 * `$promisesOrValues` resolves. The resolution value of the returned promise
 * will be the resolution value of the triggering item.
 *
 * The returned promise will only reject if *all* items in `$promisesOrValues` are
 * rejected. The rejection value will be an array of all rejection reasons.
 *
 * The returned promise will also reject with a `React\Promise\Exception\LengthException`
 * if `$promisesOrValues` contains 0 items.
 *
 * @template T
 * @param iterable<PromiseInterface<T>|T> $promisesOrValues
 * @return PromiseInterface<T>
 */
function any(iterable $promisesOrValues): \React\Promise\PromiseInterface
{
    $cancellationQueue = new \React\Promise\Internal\CancellationQueue();
    /** @var Promise<T> */
    return new \React\Promise\Promise(function (callable $resolve, callable $reject) use ($promisesOrValues, $cancellationQueue): void {
        $toReject = 0;
        $continue = \true;
        $reasons = [];
        foreach ($promisesOrValues as $i => $promiseOrValue) {
            $cancellationQueue->enqueue($promiseOrValue);
            ++$toReject;
            resolve($promiseOrValue)->then(function ($value) use ($resolve, &$continue): void {
                $continue = \false;
                $resolve($value);
            }, function (\Throwable $reason) use ($i, &$reasons, &$toReject, $reject, &$continue): void {
                $reasons[$i] = $reason;
                if (0 === --$toReject && !$continue) {
                    $reject(new CompositeException($reasons, 'All promises rejected.'));
                }
            });
            if (!$continue && !\is_array($promisesOrValues)) {
                break;
            }
        }
        $continue = \false;
        if ($toReject === 0 && !$reasons) {
            $reject(new \React\Promise\Exception\LengthException('Must contain at least 1 item but contains only 0 items.'));
        } elseif ($toReject === 0) {
            $reject(new CompositeException($reasons, 'All promises rejected.'));
        }
    }, $cancellationQueue);
}
/**
 * Sets the global rejection handler for unhandled promise rejections.
 *
 * Note that rejected promises should always be handled similar to how any
 * exceptions should always be caught in a `try` + `catch` block. If you remove
 * the last reference to a rejected promise that has not been handled, it will
 * report an unhandled promise rejection. See also the [`reject()` function](#reject)
 * for more details.
 *
 * The `?callable $callback` argument MUST be a valid callback function that
 * accepts a single `Throwable` argument or a `null` value to restore the
 * default promise rejection handler. The return value of the callback function
 * will be ignored and has no effect, so you SHOULD return a `void` value. The
 * callback function MUST NOT throw or the program will be terminated with a
 * fatal error.
 *
 * The function returns the previous rejection handler or `null` if using the
 * default promise rejection handler.
 *
 * The default promise rejection handler will log an error message plus its
 * stack trace:
 *
 * ```php
 * // Unhandled promise rejection with RuntimeException: Unhandled in example.php:2
 * React\Promise\reject(new RuntimeException('Unhandled'));
 * ```
 *
 * The promise rejection handler may be used to use customize the log message or
 * write to custom log targets. As a rule of thumb, this function should only be
 * used as a last resort and promise rejections are best handled with either the
 * [`then()` method](#promiseinterfacethen), the
 * [`catch()` method](#promiseinterfacecatch), or the
 * [`finally()` method](#promiseinterfacefinally).
 * See also the [`reject()` function](#reject) for more details.
 *
 * @param callable(\Throwable):void|null $callback
 * @return callable(\Throwable):void|null
 */
function set_rejection_handler(?callable $callback): ?callable
{
    static $current = null;
    $previous = $current;
    $current = $callback;
    return $previous;
}
/**
 * @internal
 */
function _checkTypehint(callable $callback, \Throwable $reason): bool
{
    if (\is_array($callback)) {
        $callbackReflection = new \ReflectionMethod($callback[0], $callback[1]);
    } elseif (\is_object($callback) && !$callback instanceof \Closure) {
        $callbackReflection = new \ReflectionMethod($callback, '__invoke');
    } else {
        assert($callback instanceof \Closure || \is_string($callback));
        $callbackReflection = new \ReflectionFunction($callback);
    }
    $parameters = $callbackReflection->getParameters();
    if (!isset($parameters[0])) {
        return \true;
    }
    $expectedException = $parameters[0];
    // Extract the type of the argument and handle different possibilities
    $type = $expectedException->getType();
    $isTypeUnion = \true;
    $types = [];
    switch (\true) {
        case $type === null:
            break;
        case $type instanceof \ReflectionNamedType:
            $types = [$type];
            break;
        case $type instanceof \ReflectionIntersectionType:
            $isTypeUnion = \false;
        case $type instanceof \ReflectionUnionType:
            $types = $type->getTypes();
            break;
        default:
            throw new \LogicException('Unexpected return value of ReflectionParameter::getType');
    }
    // If there is no type restriction, it matches
    if (empty($types)) {
        return \true;
    }
    foreach ($types as $type) {
        if ($type instanceof \ReflectionIntersectionType) {
            foreach ($type->getTypes() as $typeToMatch) {
                assert($typeToMatch instanceof \ReflectionNamedType);
                $name = $typeToMatch->getName();
                if (!$matches = !$typeToMatch->isBuiltin() && $reason instanceof $name) {
                    break;
                }
            }
            assert(isset($matches));
        } else {
            assert($type instanceof \ReflectionNamedType);
            $name = $type->getName();
            $matches = !$type->isBuiltin() && $reason instanceof $name;
        }
        // If we look for a single match (union), we can return early on match
        // If we look for a full match (intersection), we can return early on mismatch
        if ($matches) {
            if ($isTypeUnion) {
                return \true;
            }
        } else if (!$isTypeUnion) {
            return \false;
        }
    }
    // If we look for a single match (union) and did not return early, we matched no type and are false
    // If we look for a full match (intersection) and did not return early, we matched all types and are true
    return $isTypeUnion ? \false : \true;
}
<?php

namespace _ContaoManager;

if (!\function_exists('React\Promise\resolve')) {
    require __DIR__ . '/functions.php';
}
<?php

namespace React\Promise;

use React\Promise\Internal\RejectedPromise;
/**
 * @template T
 * @template-implements PromiseInterface<T>
 */
final class Promise implements \React\Promise\PromiseInterface
{
    /** @var (callable(callable(T):void,callable(\Throwable):void):void)|null */
    private $canceller;
    /** @var ?PromiseInterface<T> */
    private $result;
    /** @var list<callable(PromiseInterface<T>):void> */
    private $handlers = [];
    /** @var int */
    private $requiredCancelRequests = 0;
    /** @var bool */
    private $cancelled = \false;
    /**
     * @param callable(callable(T):void,callable(\Throwable):void):void $resolver
     * @param (callable(callable(T):void,callable(\Throwable):void):void)|null $canceller
     */
    public function __construct(callable $resolver, ?callable $canceller = null)
    {
        $this->canceller = $canceller;
        // Explicitly overwrite arguments with null values before invoking
        // resolver function. This ensure that these arguments do not show up
        // in the stack trace in PHP 7+ only.
        $cb = $resolver;
        $resolver = $canceller = null;
        $this->call($cb);
    }
    public function then(?callable $onFulfilled = null, ?callable $onRejected = null): \React\Promise\PromiseInterface
    {
        if (null !== $this->result) {
            return $this->result->then($onFulfilled, $onRejected);
        }
        if (null === $this->canceller) {
            return new static($this->resolver($onFulfilled, $onRejected));
        }
        // This promise has a canceller, so we create a new child promise which
        // has a canceller that invokes the parent canceller if all other
        // followers are also cancelled. We keep a reference to this promise
        // instance for the static canceller function and clear this to avoid
        // keeping a cyclic reference between parent and follower.
        $parent = $this;
        ++$parent->requiredCancelRequests;
        return new static($this->resolver($onFulfilled, $onRejected), static function () use (&$parent): void {
            assert($parent instanceof self);
            --$parent->requiredCancelRequests;
            if ($parent->requiredCancelRequests <= 0) {
                $parent->cancel();
            }
            $parent = null;
        });
    }
    /**
     * @template TThrowable of \Throwable
     * @template TRejected
     * @param callable(TThrowable): (PromiseInterface<TRejected>|TRejected) $onRejected
     * @return PromiseInterface<T|TRejected>
     */
    public function catch(callable $onRejected): \React\Promise\PromiseInterface
    {
        return $this->then(null, static function (\Throwable $reason) use ($onRejected) {
            if (!_checkTypehint($onRejected, $reason)) {
                return new RejectedPromise($reason);
            }
            /**
             * @var callable(\Throwable):(PromiseInterface<TRejected>|TRejected) $onRejected
             */
            return $onRejected($reason);
        });
    }
    public function finally(callable $onFulfilledOrRejected): \React\Promise\PromiseInterface
    {
        return $this->then(static function ($value) use ($onFulfilledOrRejected): \React\Promise\PromiseInterface {
            /** @var T $value */
            return resolve($onFulfilledOrRejected())->then(function () use ($value) {
                return $value;
            });
        }, static function (\Throwable $reason) use ($onFulfilledOrRejected): \React\Promise\PromiseInterface {
            return resolve($onFulfilledOrRejected())->then(function () use ($reason): RejectedPromise {
                return new RejectedPromise($reason);
            });
        });
    }
    public function cancel(): void
    {
        $this->cancelled = \true;
        $canceller = $this->canceller;
        $this->canceller = null;
        $parentCanceller = null;
        if (null !== $this->result) {
            // Forward cancellation to rejected promise to avoid reporting unhandled rejection
            if ($this->result instanceof RejectedPromise) {
                $this->result->cancel();
            }
            // Go up the promise chain and reach the top most promise which is
            // itself not following another promise
            $root = $this->unwrap($this->result);
            // Return if the root promise is already resolved or a
            // FulfilledPromise or RejectedPromise
            if (!$root instanceof self || null !== $root->result) {
                return;
            }
            $root->requiredCancelRequests--;
            if ($root->requiredCancelRequests <= 0) {
                $parentCanceller = [$root, 'cancel'];
            }
        }
        if (null !== $canceller) {
            $this->call($canceller);
        }
        // For BC, we call the parent canceller after our own canceller
        if ($parentCanceller) {
            $parentCanceller();
        }
    }
    /**
     * @deprecated 3.0.0 Use `catch()` instead
     * @see self::catch()
     */
    public function otherwise(callable $onRejected): \React\Promise\PromiseInterface
    {
        return $this->catch($onRejected);
    }
    /**
     * @deprecated 3.0.0 Use `finally()` instead
     * @see self::finally()
     */
    public function always(callable $onFulfilledOrRejected): \React\Promise\PromiseInterface
    {
        return $this->finally($onFulfilledOrRejected);
    }
    private function resolver(?callable $onFulfilled = null, ?callable $onRejected = null): callable
    {
        return function (callable $resolve, callable $reject) use ($onFulfilled, $onRejected): void {
            $this->handlers[] = static function (\React\Promise\PromiseInterface $promise) use ($onFulfilled, $onRejected, $resolve, $reject): void {
                $promise = $promise->then($onFulfilled, $onRejected);
                if ($promise instanceof self && $promise->result === null) {
                    $promise->handlers[] = static function (\React\Promise\PromiseInterface $promise) use ($resolve, $reject): void {
                        $promise->then($resolve, $reject);
                    };
                } else {
                    $promise->then($resolve, $reject);
                }
            };
        };
    }
    private function reject(\Throwable $reason): void
    {
        if (null !== $this->result) {
            return;
        }
        $this->settle(reject($reason));
    }
    /**
     * @param PromiseInterface<T> $result
     */
    private function settle(\React\Promise\PromiseInterface $result): void
    {
        $result = $this->unwrap($result);
        if ($result === $this) {
            $result = new RejectedPromise(new \LogicException('Cannot resolve a promise with itself.'));
        }
        if ($result instanceof self) {
            $result->requiredCancelRequests++;
        } else {
            // Unset canceller only when not following a pending promise
            $this->canceller = null;
        }
        $handlers = $this->handlers;
        $this->handlers = [];
        $this->result = $result;
        foreach ($handlers as $handler) {
            $handler($result);
        }
        // Forward cancellation to rejected promise to avoid reporting unhandled rejection
        if ($this->cancelled && $result instanceof RejectedPromise) {
            $result->cancel();
        }
    }
    /**
     * @param PromiseInterface<T> $promise
     * @return PromiseInterface<T>
     */
    private function unwrap(\React\Promise\PromiseInterface $promise): \React\Promise\PromiseInterface
    {
        while ($promise instanceof self && null !== $promise->result) {
            /** @var PromiseInterface<T> $promise */
            $promise = $promise->result;
        }
        return $promise;
    }
    /**
     * @param callable(callable(mixed):void,callable(\Throwable):void):void $cb
     */
    private function call(callable $cb): void
    {
        // Explicitly overwrite argument with null value. This ensure that this
        // argument does not show up in the stack trace in PHP 7+ only.
        $callback = $cb;
        $cb = null;
        // Use reflection to inspect number of arguments expected by this callback.
        // We did some careful benchmarking here: Using reflection to avoid unneeded
        // function arguments is actually faster than blindly passing them.
        // Also, this helps avoiding unnecessary function arguments in the call stack
        // if the callback creates an Exception (creating garbage cycles).
        if (\is_array($callback)) {
            $ref = new \ReflectionMethod($callback[0], $callback[1]);
        } elseif (\is_object($callback) && !$callback instanceof \Closure) {
            $ref = new \ReflectionMethod($callback, '__invoke');
        } else {
            assert($callback instanceof \Closure || \is_string($callback));
            $ref = new \ReflectionFunction($callback);
        }
        $args = $ref->getNumberOfParameters();
        try {
            if ($args === 0) {
                $callback();
            } else {
                // Keep references to this promise instance for the static resolve/reject functions.
                // By using static callbacks that are not bound to this instance
                // and passing the target promise instance by reference, we can
                // still execute its resolving logic and still clear this
                // reference when settling the promise. This helps avoiding
                // garbage cycles if any callback creates an Exception.
                // These assumptions are covered by the test suite, so if you ever feel like
                // refactoring this, go ahead, any alternative suggestions are welcome!
                $target =& $this;
                $callback(static function ($value) use (&$target): void {
                    if ($target !== null) {
                        $target->settle(resolve($value));
                        $target = null;
                    }
                }, static function (\Throwable $reason) use (&$target): void {
                    if ($target !== null) {
                        $target->reject($reason);
                        $target = null;
                    }
                });
            }
        } catch (\Throwable $e) {
            $target = null;
            $this->reject($e);
        }
    }
}
<?php

namespace React\Promise;

/**
 * @template T
 */
final class Deferred
{
    /**
     * @var PromiseInterface<T>
     */
    private $promise;
    /** @var callable(T):void */
    private $resolveCallback;
    /** @var callable(\Throwable):void */
    private $rejectCallback;
    /**
     * @param (callable(callable(T):void,callable(\Throwable):void):void)|null $canceller
     */
    public function __construct(?callable $canceller = null)
    {
        $this->promise = new \React\Promise\Promise(function ($resolve, $reject): void {
            $this->resolveCallback = $resolve;
            $this->rejectCallback = $reject;
        }, $canceller);
    }
    /**
     * @return PromiseInterface<T>
     */
    public function promise(): \React\Promise\PromiseInterface
    {
        return $this->promise;
    }
    /**
     * @param T $value
     */
    public function resolve($value): void
    {
        ($this->resolveCallback)($value);
    }
    public function reject(\Throwable $reason): void
    {
        ($this->rejectCallback)($reason);
    }
}
<?php

namespace React\Promise\Internal;

use React\Promise\PromiseInterface;
use function React\Promise\_checkTypehint;
use function React\Promise\resolve;
use function React\Promise\set_rejection_handler;
/**
 * @internal
 *
 * @template-implements PromiseInterface<never>
 */
final class RejectedPromise implements PromiseInterface
{
    /** @var \Throwable */
    private $reason;
    /** @var bool */
    private $handled = \false;
    /**
     * @param \Throwable $reason
     */
    public function __construct(\Throwable $reason)
    {
        $this->reason = $reason;
    }
    /** @throws void */
    public function __destruct()
    {
        if ($this->handled) {
            return;
        }
        $handler = set_rejection_handler(null);
        if ($handler === null) {
            $message = 'Unhandled promise rejection with ' . $this->reason;
            \error_log($message);
            return;
        }
        try {
            $handler($this->reason);
        } catch (\Throwable $e) {
            \preg_match('/^([^:\s]++)(.*+)$/sm', (string) $e, $match);
            \assert(isset($match[1], $match[2]));
            $message = 'Fatal error: Uncaught ' . $match[1] . ' from unhandled promise rejection handler' . $match[2];
            \error_log($message);
            exit(255);
        }
    }
    /**
     * @template TRejected
     * @param ?callable $onFulfilled
     * @param ?(callable(\Throwable): (PromiseInterface<TRejected>|TRejected)) $onRejected
     * @return PromiseInterface<($onRejected is null ? never : TRejected)>
     */
    public function then(?callable $onFulfilled = null, ?callable $onRejected = null): PromiseInterface
    {
        if (null === $onRejected) {
            return $this;
        }
        $this->handled = \true;
        try {
            return resolve($onRejected($this->reason));
        } catch (\Throwable $exception) {
            return new \React\Promise\Internal\RejectedPromise($exception);
        }
    }
    /**
     * @template TThrowable of \Throwable
     * @template TRejected
     * @param callable(TThrowable): (PromiseInterface<TRejected>|TRejected) $onRejected
     * @return PromiseInterface<TRejected>
     */
    public function catch(callable $onRejected): PromiseInterface
    {
        if (!_checkTypehint($onRejected, $this->reason)) {
            return $this;
        }
        /**
         * @var callable(\Throwable):(PromiseInterface<TRejected>|TRejected) $onRejected
         */
        return $this->then(null, $onRejected);
    }
    public function finally(callable $onFulfilledOrRejected): PromiseInterface
    {
        return $this->then(null, function (\Throwable $reason) use ($onFulfilledOrRejected): PromiseInterface {
            return resolve($onFulfilledOrRejected())->then(function () use ($reason): PromiseInterface {
                return new \React\Promise\Internal\RejectedPromise($reason);
            });
        });
    }
    public function cancel(): void
    {
        $this->handled = \true;
    }
    /**
     * @deprecated 3.0.0 Use `catch()` instead
     * @see self::catch()
     */
    public function otherwise(callable $onRejected): PromiseInterface
    {
        return $this->catch($onRejected);
    }
    /**
     * @deprecated 3.0.0 Use `always()` instead
     * @see self::always()
     */
    public function always(callable $onFulfilledOrRejected): PromiseInterface
    {
        return $this->finally($onFulfilledOrRejected);
    }
}
<?php

namespace React\Promise\Internal;

use React\Promise\PromiseInterface;
use function React\Promise\resolve;
/**
 * @internal
 *
 * @template T
 * @template-implements PromiseInterface<T>
 */
final class FulfilledPromise implements PromiseInterface
{
    /** @var T */
    private $value;
    /**
     * @param T $value
     * @throws \InvalidArgumentException
     */
    public function __construct($value = null)
    {
        if ($value instanceof PromiseInterface) {
            throw new \InvalidArgumentException('You cannot create React\Promise\FulfilledPromise with a promise. Use React\Promise\resolve($promiseOrValue) instead.');
        }
        $this->value = $value;
    }
    /**
     * @template TFulfilled
     * @param ?(callable((T is void ? null : T)): (PromiseInterface<TFulfilled>|TFulfilled)) $onFulfilled
     * @return PromiseInterface<($onFulfilled is null ? T : TFulfilled)>
     */
    public function then(?callable $onFulfilled = null, ?callable $onRejected = null): PromiseInterface
    {
        if (null === $onFulfilled) {
            return $this;
        }
        try {
            /**
             * @var PromiseInterface<T>|T $result
             */
            $result = $onFulfilled($this->value);
            return resolve($result);
        } catch (\Throwable $exception) {
            return new \React\Promise\Internal\RejectedPromise($exception);
        }
    }
    public function catch(callable $onRejected): PromiseInterface
    {
        return $this;
    }
    public function finally(callable $onFulfilledOrRejected): PromiseInterface
    {
        return $this->then(function ($value) use ($onFulfilledOrRejected): PromiseInterface {
            /** @var T $value */
            return resolve($onFulfilledOrRejected())->then(function () use ($value) {
                return $value;
            });
        });
    }
    public function cancel(): void
    {
    }
    /**
     * @deprecated 3.0.0 Use `catch()` instead
     * @see self::catch()
     */
    public function otherwise(callable $onRejected): PromiseInterface
    {
        return $this->catch($onRejected);
    }
    /**
     * @deprecated 3.0.0 Use `finally()` instead
     * @see self::finally()
     */
    public function always(callable $onFulfilledOrRejected): PromiseInterface
    {
        return $this->finally($onFulfilledOrRejected);
    }
}
<?php

namespace React\Promise\Internal;

/**
 * @internal
 */
final class CancellationQueue
{
    /** @var bool */
    private $started = \false;
    /** @var object[] */
    private $queue = [];
    public function __invoke(): void
    {
        if ($this->started) {
            return;
        }
        $this->started = \true;
        $this->drain();
    }
    /**
     * @param mixed $cancellable
     */
    public function enqueue($cancellable): void
    {
        if (!\is_object($cancellable) || !\method_exists($cancellable, 'then') || !\method_exists($cancellable, 'cancel')) {
            return;
        }
        $length = \array_push($this->queue, $cancellable);
        if ($this->started && 1 === $length) {
            $this->drain();
        }
    }
    private function drain(): void
    {
        for ($i = \key($this->queue); isset($this->queue[$i]); $i++) {
            $cancellable = $this->queue[$i];
            assert(\method_exists($cancellable, 'cancel'));
            $exception = null;
            try {
                $cancellable->cancel();
            } catch (\Throwable $exception) {
            }
            unset($this->queue[$i]);
            if ($exception) {
                throw $exception;
            }
        }
        $this->queue = [];
    }
}
<?php

namespace React\Promise\Exception;

class LengthException extends \LengthException
{
}
<?php

namespace React\Promise\Exception;

/**
 * Represents an exception that is a composite of one or more other exceptions.
 *
 * This exception is useful in situations where a promise must be rejected
 * with multiple exceptions. It is used for example to reject the returned
 * promise from `some()` and `any()` when too many input promises reject.
 */
class CompositeException extends \Exception
{
    /** @var \Throwable[] */
    private $throwables;
    /** @param \Throwable[] $throwables */
    public function __construct(array $throwables, string $message = '', int $code = 0, ?\Throwable $previous = null)
    {
        parent::__construct($message, $code, $previous);
        $this->throwables = $throwables;
    }
    /**
     * @return \Throwable[]
     */
    public function getThrowables(): array
    {
        return $this->throwables;
    }
}
BSD 3-Clause License

Copyright (c) 2002-2024, Sebastian Bergmann
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

1. Redistributions of source code must retain the above copyright notice, this
   list of conditions and the following disclaimer.

2. Redistributions in binary form must reproduce the above copyright notice,
   this list of conditions and the following disclaimer in the documentation
   and/or other materials provided with the distribution.

3. Neither the name of the copyright holder nor the names of its
   contributors may be used to endorse or promote products derived from
   this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
# ChangeLog

All notable changes are documented in this file using the [Keep a CHANGELOG](http://keepachangelog.com/) principles.

## [5.1.1] - 2024-03-02

### Changed

* Do not use implicitly nullable parameters

## [5.1.0] - 2023-12-22

### Added

* `SebastianBergmann\Diff\Chunk::start()`, `SebastianBergmann\Diff\Chunk::startRange()`, `SebastianBergmann\Diff\Chunk::end()`, `SebastianBergmann\Diff\Chunk::endRange()`, and `SebastianBergmann\Diff\Chunk::lines()`
* `SebastianBergmann\Diff\Diff::from()`, `SebastianBergmann\Diff\Diff::to()`, and `SebastianBergmann\Diff\Diff::chunks()`
* `SebastianBergmann\Diff\Line::content()` and `SebastianBergmann\Diff\Diff::type()`
* `SebastianBergmann\Diff\Line::isAdded()`,`SebastianBergmann\Diff\Line::isRemoved()`, and `SebastianBergmann\Diff\Line::isUnchanged()`

### Changed

* `SebastianBergmann\Diff\Diff` now implements `IteratorAggregate`, iterating over it yields the aggregated `SebastianBergmann\Diff\Chunk` objects
* `SebastianBergmann\Diff\Chunk` now implements `IteratorAggregate`, iterating over it yields the aggregated `SebastianBergmann\Diff\Line` objects

### Deprecated

* `SebastianBergmann\Diff\Chunk::getStart()`, `SebastianBergmann\Diff\Chunk::getStartRange()`, `SebastianBergmann\Diff\Chunk::getEnd()`, `SebastianBergmann\Diff\Chunk::getEndRange()`, and `SebastianBergmann\Diff\Chunk::getLines()`
* `SebastianBergmann\Diff\Diff::getFrom()`, `SebastianBergmann\Diff\Diff::getTo()`, and `SebastianBergmann\Diff\Diff::getChunks()`
* `SebastianBergmann\Diff\Line::getContent()` and `SebastianBergmann\Diff\Diff::getType()`

## [5.0.3] - 2023-05-01

### Changed

* [#119](https://github.com/sebastianbergmann/diff/pull/119): Improve performance of `TimeEfficientLongestCommonSubsequenceCalculator`

## [5.0.2] - 2023-05-01

### Changed

* [#118](https://github.com/sebastianbergmann/diff/pull/118): Improve performance of `MemoryEfficientLongestCommonSubsequenceCalculator`

## [5.0.1] - 2023-03-23

### Fixed

* [#115](https://github.com/sebastianbergmann/diff/pull/115): `Parser::parseFileDiff()` does not handle diffs correctly that only add lines or only remove lines

## [5.0.0] - 2023-02-03

### Changed

* Passing a `DiffOutputBuilderInterface` instance to `Differ::__construct()` is no longer optional

### Removed

* Removed support for PHP 7.3, PHP 7.4, and PHP 8.0

## [4.0.4] - 2020-10-26

### Fixed

* `SebastianBergmann\Diff\Exception` now correctly extends `\Throwable`

## [4.0.3] - 2020-09-28

### Changed

* Changed PHP version constraint in `composer.json` from `^7.3 || ^8.0` to `>=7.3`

## [4.0.2] - 2020-06-30

### Added

* This component is now supported on PHP 8

## [4.0.1] - 2020-05-08

### Fixed

* [#99](https://github.com/sebastianbergmann/diff/pull/99): Regression in unified diff output of identical strings

## [4.0.0] - 2020-02-07

### Removed

* Removed support for PHP 7.1 and PHP 7.2

## [3.0.2] - 2019-02-04

### Changed

* `Chunk::setLines()` now ensures that the `$lines` array only contains `Line` objects

## [3.0.1] - 2018-06-10

### Fixed

* Removed `"minimum-stability": "dev",` from `composer.json`

## [3.0.0] - 2018-02-01

* The `StrictUnifiedDiffOutputBuilder` implementation of the `DiffOutputBuilderInterface` was added

### Changed

* The default `DiffOutputBuilderInterface` implementation now generates context lines (unchanged lines)

### Removed

* Removed support for PHP 7.0

### Fixed

* [#70](https://github.com/sebastianbergmann/diff/issues/70): Diffing of arrays no longer works

## [2.0.1] - 2017-08-03

### Fixed

* [#66](https://github.com/sebastianbergmann/diff/pull/66): Restored backwards compatibility for PHPUnit 6.1.4, 6.2.0, 6.2.1, 6.2.2, and 6.2.3

## [2.0.0] - 2017-07-11 [YANKED]

### Added

* [#64](https://github.com/sebastianbergmann/diff/pull/64): Show line numbers for chunks of a diff

### Removed

* This component is no longer supported on PHP 5.6

[5.1.1]: https://github.com/sebastianbergmann/diff/compare/5.1.0...5.1.1
[5.1.0]: https://github.com/sebastianbergmann/diff/compare/5.0.3...5.1.0
[5.0.3]: https://github.com/sebastianbergmann/diff/compare/5.0.2...5.0.3
[5.0.2]: https://github.com/sebastianbergmann/diff/compare/5.0.1...5.0.2
[5.0.1]: https://github.com/sebastianbergmann/diff/compare/5.0.0...5.0.1
[5.0.0]: https://github.com/sebastianbergmann/diff/compare/4.0.4...5.0.0
[4.0.4]: https://github.com/sebastianbergmann/diff/compare/4.0.3...4.0.4
[4.0.3]: https://github.com/sebastianbergmann/diff/compare/4.0.2...4.0.3
[4.0.2]: https://github.com/sebastianbergmann/diff/compare/4.0.1...4.0.2
[4.0.1]: https://github.com/sebastianbergmann/diff/compare/4.0.0...4.0.1
[4.0.0]: https://github.com/sebastianbergmann/diff/compare/3.0.2...4.0.0
[3.0.2]: https://github.com/sebastianbergmann/diff/compare/3.0.1...3.0.2
[3.0.1]: https://github.com/sebastianbergmann/diff/compare/3.0.0...3.0.1
[3.0.0]: https://github.com/sebastianbergmann/diff/compare/2.0...3.0.0
[2.0.1]: https://github.com/sebastianbergmann/diff/compare/c341c98ce083db77f896a0aa64f5ee7652915970...2.0.1
[2.0.0]: https://github.com/sebastianbergmann/diff/compare/1.4...c341c98ce083db77f896a0aa64f5ee7652915970
[![Latest Stable Version](https://poser.pugx.org/sebastian/diff/v/stable.png)](https://packagist.org/packages/sebastian/diff)
[![CI Status](https://github.com/sebastianbergmann/diff/workflows/CI/badge.svg)](https://github.com/sebastianbergmann/diff/actions)
[![Type Coverage](https://shepherd.dev/github/sebastianbergmann/diff/coverage.svg)](https://shepherd.dev/github/sebastianbergmann/diff)
[![codecov](https://codecov.io/gh/sebastianbergmann/diff/branch/main/graph/badge.svg)](https://codecov.io/gh/sebastianbergmann/diff)

# sebastian/diff

Diff implementation for PHP, factored out of PHPUnit into a stand-alone component.

## Installation

You can add this library as a local, per-project dependency to your project using [Composer](https://getcomposer.org/):

```
composer require sebastian/diff
```

If you only need this library during development, for instance to run your project's test suite, then you should add it as a development-time dependency:

```
composer require --dev sebastian/diff
```

### Usage

#### Generating diff

The `Differ` class can be used to generate a textual representation of the difference between two strings:

```php
<?php
use SebastianBergmann\Diff\Differ;

$differ = new Differ;
print $differ->diff('foo', 'bar');
```

The code above yields the output below:
```diff
--- Original
+++ New
@@ @@
-foo
+bar
```

There are three output builders available in this package:

#### UnifiedDiffOutputBuilder

This is default builder, which generates the output close to udiff and is used by PHPUnit.

```php
<?php

use SebastianBergmann\Diff\Differ;
use SebastianBergmann\Diff\Output\UnifiedDiffOutputBuilder;

$builder = new UnifiedDiffOutputBuilder(
    "--- Original\n+++ New\n", // custom header
    false                      // do not add line numbers to the diff 
);

$differ = new Differ($builder);
print $differ->diff('foo', 'bar');
```

#### StrictUnifiedDiffOutputBuilder

Generates (strict) Unified diff's (unidiffs) with hunks,
similar to `diff -u` and compatible with `patch` and `git apply`.

```php
<?php

use SebastianBergmann\Diff\Differ;
use SebastianBergmann\Diff\Output\StrictUnifiedDiffOutputBuilder;

$builder = new StrictUnifiedDiffOutputBuilder([
    'collapseRanges'      => true, // ranges of length one are rendered with the trailing `,1`
    'commonLineThreshold' => 6,    // number of same lines before ending a new hunk and creating a new one (if needed)
    'contextLines'        => 3,    // like `diff:  -u, -U NUM, --unified[=NUM]`, for patch/git apply compatibility best to keep at least @ 3
    'fromFile'            => '',
    'fromFileDate'        => null,
    'toFile'              => '',
    'toFileDate'          => null,
]);

$differ = new Differ($builder);
print $differ->diff('foo', 'bar');
```

#### DiffOnlyOutputBuilder

Output only the lines that differ.

```php
<?php

use SebastianBergmann\Diff\Differ;
use SebastianBergmann\Diff\Output\DiffOnlyOutputBuilder;

$builder = new DiffOnlyOutputBuilder(
    "--- Original\n+++ New\n"
);

$differ = new Differ($builder);
print $differ->diff('foo', 'bar');
```

#### DiffOutputBuilderInterface

You can pass any output builder to the `Differ` class as longs as it implements the `DiffOutputBuilderInterface`.

#### Parsing diff

The `Parser` class can be used to parse a unified diff into an object graph:

```php
use SebastianBergmann\Diff\Parser;
use SebastianBergmann\Git;

$git = new Git('/usr/local/src/money');

$diff = $git->getDiff(
  '948a1a07768d8edd10dcefa8315c1cbeffb31833',
  'c07a373d2399f3e686234c4f7f088d635eb9641b'
);

$parser = new Parser;

print_r($parser->parse($diff));
```

The code above yields the output below:

    Array
    (
        [0] => SebastianBergmann\Diff\Diff Object
            (
                [from:SebastianBergmann\Diff\Diff:private] => a/tests/MoneyTest.php
                [to:SebastianBergmann\Diff\Diff:private] => b/tests/MoneyTest.php
                [chunks:SebastianBergmann\Diff\Diff:private] => Array
                    (
                        [0] => SebastianBergmann\Diff\Chunk Object
                            (
                                [start:SebastianBergmann\Diff\Chunk:private] => 87
                                [startRange:SebastianBergmann\Diff\Chunk:private] => 7
                                [end:SebastianBergmann\Diff\Chunk:private] => 87
                                [endRange:SebastianBergmann\Diff\Chunk:private] => 7
                                [lines:SebastianBergmann\Diff\Chunk:private] => Array
                                    (
                                        [0] => SebastianBergmann\Diff\Line Object
                                            (
                                                [type:SebastianBergmann\Diff\Line:private] => 3
                                                [content:SebastianBergmann\Diff\Line:private] =>      * @covers SebastianBergmann\Money\Money::add
                                            )

                                        [1] => SebastianBergmann\Diff\Line Object
                                            (
                                                [type:SebastianBergmann\Diff\Line:private] => 3
                                                [content:SebastianBergmann\Diff\Line:private] =>      * @covers SebastianBergmann\Money\Money::newMoney
                                            )

                                        [2] => SebastianBergmann\Diff\Line Object
                                            (
                                                [type:SebastianBergmann\Diff\Line:private] => 3
                                                [content:SebastianBergmann\Diff\Line:private] =>      */
                                            )

                                        [3] => SebastianBergmann\Diff\Line Object
                                            (
                                                [type:SebastianBergmann\Diff\Line:private] => 2
                                                [content:SebastianBergmann\Diff\Line:private] =>     public function testAnotherMoneyWithSameCurrencyObjectCanBeAdded()
                                            )

                                        [4] => SebastianBergmann\Diff\Line Object
                                            (
                                                [type:SebastianBergmann\Diff\Line:private] => 1
                                                [content:SebastianBergmann\Diff\Line:private] =>     public function testAnotherMoneyObjectWithSameCurrencyCanBeAdded()
                                            )

                                        [5] => SebastianBergmann\Diff\Line Object
                                            (
                                                [type:SebastianBergmann\Diff\Line:private] => 3
                                                [content:SebastianBergmann\Diff\Line:private] =>     {
                                            )

                                        [6] => SebastianBergmann\Diff\Line Object
                                            (
                                                [type:SebastianBergmann\Diff\Line:private] => 3
                                                [content:SebastianBergmann\Diff\Line:private] =>         $a = new Money(1, new Currency('EUR'));
                                            )

                                        [7] => SebastianBergmann\Diff\Line Object
                                            (
                                                [type:SebastianBergmann\Diff\Line:private] => 3
                                                [content:SebastianBergmann\Diff\Line:private] =>         $b = new Money(2, new Currency('EUR'));
                                            )
                                    )
                            )
                    )
            )
    )

Note: If the chunk size is 0 lines, i.e., `getStartRange()` or `getEndRange()` return 0, the number of line returned by `getStart()` or `getEnd()` is one lower than one would expect. It is the line number after which the chunk should be inserted or deleted; in all other cases, it gives the first line number of the replaced range of lines.
{
    "name": "sebastian\/diff",
    "description": "Diff implementation",
    "keywords": [
        "diff",
        "udiff",
        "unidiff",
        "unified diff"
    ],
    "homepage": "https:\/\/github.com\/sebastianbergmann\/diff",
    "license": "BSD-3-Clause",
    "authors": [
        {
            "name": "Sebastian Bergmann",
            "email": "sebastian@phpunit.de"
        },
        {
            "name": "Kore Nordmann",
            "email": "mail@kore-nordmann.de"
        }
    ],
    "support": {
        "issues": "https:\/\/github.com\/sebastianbergmann\/diff\/issues",
        "security": "https:\/\/github.com\/sebastianbergmann\/diff\/security\/policy"
    },
    "prefer-stable": true,
    "config": {
        "platform": {
            "php": "8.1.0"
        },
        "optimize-autoloader": true,
        "sort-packages": true
    },
    "require": {
        "php": ">=8.1"
    },
    "require-dev": {
        "phpunit\/phpunit": "^10.0",
        "symfony\/process": "^6.4"
    },
    "autoload": {
        "classmap": [
            "src\/"
        ]
    },
    "autoload-dev": {
        "classmap": [
            "tests\/"
        ]
    },
    "extra": {
        "branch-alias": {
            "dev-main": "5.1-dev"
        }
    }
}# Security Policy

If you believe you have found a security vulnerability in the library that is developed in this repository, please report it to us through coordinated disclosure.

**Please do not report security vulnerabilities through public GitHub issues, discussions, or pull requests.**

Instead, please email `sebastian@phpunit.de`.

Please include as much of the information listed below as you can to help us better understand and resolve the issue:

* The type of issue
* Full paths of source file(s) related to the manifestation of the issue
* The location of the affected source code (tag/branch/commit or direct URL)
* Any special configuration required to reproduce the issue
* Step-by-step instructions to reproduce the issue
* Proof-of-concept or exploit code (if possible)
* Impact of the issue, including how an attacker might exploit the issue

This information will help us triage your report more quickly.

## Web Context

The library that is developed in this repository was either extracted from [PHPUnit](https://github.com/sebastianbergmann/phpunit) or developed specifically as a dependency for PHPUnit.

The library is developed with a focus on development environments and the command-line. No specific testing or hardening with regard to using the library in an HTTP or web context or with untrusted input data is performed. The library might also contain functionality that intentionally exposes internal application data for debugging purposes.

If the library is used in a web application, the application developer is responsible for filtering inputs or escaping outputs as necessary and for verifying that the used functionality is safe for use within the intended context.

Vulnerabilities specific to the use outside a development context will be fixed as applicable, provided that the fix does not have an averse effect on the primary use case for development purposes.

<?php

declare (strict_types=1);
/*
 * This file is part of sebastian/diff.
 *
 * (c) Sebastian Bergmann <sebastian@phpunit.de>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\SebastianBergmann\Diff;

use ArrayIterator;
use IteratorAggregate;
use Traversable;
/**
 * @template-implements IteratorAggregate<int, Chunk>
 */
final class Diff implements IteratorAggregate
{
    /**
     * @psalm-var non-empty-string
     */
    private string $from;
    /**
     * @psalm-var non-empty-string
     */
    private string $to;
    /**
     * @psalm-var list<Chunk>
     */
    private array $chunks;
    /**
     * @psalm-param non-empty-string $from
     * @psalm-param non-empty-string $to
     * @psalm-param list<Chunk> $chunks
     */
    public function __construct(string $from, string $to, array $chunks = [])
    {
        $this->from = $from;
        $this->to = $to;
        $this->chunks = $chunks;
    }
    /**
     * @psalm-return non-empty-string
     */
    public function from(): string
    {
        return $this->from;
    }
    /**
     * @psalm-return non-empty-string
     */
    public function to(): string
    {
        return $this->to;
    }
    /**
     * @psalm-return list<Chunk>
     */
    public function chunks(): array
    {
        return $this->chunks;
    }
    /**
     * @psalm-param list<Chunk> $chunks
     */
    public function setChunks(array $chunks): void
    {
        $this->chunks = $chunks;
    }
    /**
     * @psalm-return non-empty-string
     *
     * @deprecated
     */
    public function getFrom(): string
    {
        return $this->from;
    }
    /**
     * @psalm-return non-empty-string
     *
     * @deprecated
     */
    public function getTo(): string
    {
        return $this->to;
    }
    /**
     * @psalm-return list<Chunk>
     *
     * @deprecated
     */
    public function getChunks(): array
    {
        return $this->chunks;
    }
    public function getIterator(): Traversable
    {
        return new ArrayIterator($this->chunks);
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of sebastian/diff.
 *
 * (c) Sebastian Bergmann <sebastian@phpunit.de>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\SebastianBergmann\Diff;

use function array_pop;
use function assert;
use function count;
use function max;
use function preg_match;
use function preg_split;
/**
 * Unified diff parser.
 */
final class Parser
{
    /**
     * @return Diff[]
     */
    public function parse(string $string): array
    {
        $lines = preg_split('(\r\n|\r|\n)', $string);
        if (!empty($lines) && $lines[count($lines) - 1] === '') {
            array_pop($lines);
        }
        $lineCount = count($lines);
        $diffs = [];
        $diff = null;
        $collected = [];
        for ($i = 0; $i < $lineCount; $i++) {
            if (preg_match('#^---\h+"?(?P<file>[^\v\t"]+)#', $lines[$i], $fromMatch) && preg_match('#^\+\+\+\h+"?(?P<file>[^\v\t"]+)#', $lines[$i + 1], $toMatch)) {
                if ($diff !== null) {
                    $this->parseFileDiff($diff, $collected);
                    $diffs[] = $diff;
                    $collected = [];
                }
                assert(!empty($fromMatch['file']));
                assert(!empty($toMatch['file']));
                $diff = new Diff($fromMatch['file'], $toMatch['file']);
                $i++;
            } else {
                if (preg_match('/^(?:diff --git |index [\da-f.]+|[+-]{3} [ab])/', $lines[$i])) {
                    continue;
                }
                $collected[] = $lines[$i];
            }
        }
        if ($diff !== null && count($collected)) {
            $this->parseFileDiff($diff, $collected);
            $diffs[] = $diff;
        }
        return $diffs;
    }
    private function parseFileDiff(Diff $diff, array $lines): void
    {
        $chunks = [];
        $chunk = null;
        $diffLines = [];
        foreach ($lines as $line) {
            if (preg_match('/^@@\s+-(?P<start>\d+)(?:,\s*(?P<startrange>\d+))?\s+\+(?P<end>\d+)(?:,\s*(?P<endrange>\d+))?\s+@@/', $line, $match, \PREG_UNMATCHED_AS_NULL)) {
                $chunk = new Chunk((int) $match['start'], isset($match['startrange']) ? max(0, (int) $match['startrange']) : 1, (int) $match['end'], isset($match['endrange']) ? max(0, (int) $match['endrange']) : 1);
                $chunks[] = $chunk;
                $diffLines = [];
                continue;
            }
            if (preg_match('/^(?P<type>[+ -])?(?P<line>.*)/', $line, $match)) {
                $type = Line::UNCHANGED;
                if ($match['type'] === '+') {
                    $type = Line::ADDED;
                } elseif ($match['type'] === '-') {
                    $type = Line::REMOVED;
                }
                $diffLines[] = new Line($type, $match['line']);
                $chunk?->setLines($diffLines);
            }
        }
        $diff->setChunks($chunks);
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of sebastian/diff.
 *
 * (c) Sebastian Bergmann <sebastian@phpunit.de>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\SebastianBergmann\Diff;

use function array_reverse;
use function count;
use function max;
use SplFixedArray;
final class TimeEfficientLongestCommonSubsequenceCalculator implements LongestCommonSubsequenceCalculator
{
    /**
     * @inheritDoc
     */
    public function calculate(array $from, array $to): array
    {
        $common = [];
        $fromLength = count($from);
        $toLength = count($to);
        $width = $fromLength + 1;
        $matrix = new SplFixedArray($width * ($toLength + 1));
        for ($i = 0; $i <= $fromLength; $i++) {
            $matrix[$i] = 0;
        }
        for ($j = 0; $j <= $toLength; $j++) {
            $matrix[$j * $width] = 0;
        }
        for ($i = 1; $i <= $fromLength; $i++) {
            for ($j = 1; $j <= $toLength; $j++) {
                $o = $j * $width + $i;
                // don't use max() to avoid function call overhead
                $firstOrLast = $from[$i - 1] === $to[$j - 1] ? $matrix[$o - $width - 1] + 1 : 0;
                if ($matrix[$o - 1] > $matrix[$o - $width]) {
                    if ($firstOrLast > $matrix[$o - 1]) {
                        $matrix[$o] = $firstOrLast;
                    } else {
                        $matrix[$o] = $matrix[$o - 1];
                    }
                } else if ($firstOrLast > $matrix[$o - $width]) {
                    $matrix[$o] = $firstOrLast;
                } else {
                    $matrix[$o] = $matrix[$o - $width];
                }
            }
        }
        $i = $fromLength;
        $j = $toLength;
        while ($i > 0 && $j > 0) {
            if ($from[$i - 1] === $to[$j - 1]) {
                $common[] = $from[$i - 1];
                $i--;
                $j--;
            } else {
                $o = $j * $width + $i;
                if ($matrix[$o - $width] > $matrix[$o - 1]) {
                    $j--;
                } else {
                    $i--;
                }
            }
        }
        return array_reverse($common);
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of sebastian/diff.
 *
 * (c) Sebastian Bergmann <sebastian@phpunit.de>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\SebastianBergmann\Diff\Output;

use function fclose;
use function fopen;
use function fwrite;
use function str_ends_with;
use function stream_get_contents;
use function substr;
use _ContaoManager\SebastianBergmann\Diff\Differ;
/**
 * Builds a diff string representation in a loose unified diff format
 * listing only changes lines. Does not include line numbers.
 */
final class DiffOnlyOutputBuilder implements DiffOutputBuilderInterface
{
    private string $header;
    public function __construct(string $header = "--- Original\n+++ New\n")
    {
        $this->header = $header;
    }
    public function getDiff(array $diff): string
    {
        $buffer = fopen('php://memory', 'r+b');
        if ('' !== $this->header) {
            fwrite($buffer, $this->header);
            if (!str_ends_with($this->header, "\n")) {
                fwrite($buffer, "\n");
            }
        }
        foreach ($diff as $diffEntry) {
            if ($diffEntry[1] === Differ::ADDED) {
                fwrite($buffer, '+' . $diffEntry[0]);
            } elseif ($diffEntry[1] === Differ::REMOVED) {
                fwrite($buffer, '-' . $diffEntry[0]);
            } elseif ($diffEntry[1] === Differ::DIFF_LINE_END_WARNING) {
                fwrite($buffer, ' ' . $diffEntry[0]);
                continue;
                // Warnings should not be tested for line break, it will always be there
            } else {
                /* Not changed (old) 0 */
                continue;
                // we didn't write the not-changed line, so do not add a line break either
            }
            $lc = substr($diffEntry[0], -1);
            if ($lc !== "\n" && $lc !== "\r") {
                fwrite($buffer, "\n");
                // \No newline at end of file
            }
        }
        $diff = stream_get_contents($buffer, -1, 0);
        fclose($buffer);
        return $diff;
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of sebastian/diff.
 *
 * (c) Sebastian Bergmann <sebastian@phpunit.de>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\SebastianBergmann\Diff\Output;

/**
 * Defines how an output builder should take a generated
 * diff array and return a string representation of that diff.
 */
interface DiffOutputBuilderInterface
{
    public function getDiff(array $diff): string;
}
<?php

declare (strict_types=1);
/*
 * This file is part of sebastian/diff.
 *
 * (c) Sebastian Bergmann <sebastian@phpunit.de>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\SebastianBergmann\Diff\Output;

use function array_splice;
use function count;
use function fclose;
use function fopen;
use function fwrite;
use function max;
use function min;
use function str_ends_with;
use function stream_get_contents;
use function substr;
use _ContaoManager\SebastianBergmann\Diff\Differ;
/**
 * Builds a diff string representation in unified diff format in chunks.
 */
final class UnifiedDiffOutputBuilder extends AbstractChunkOutputBuilder
{
    private bool $collapseRanges = \true;
    private int $commonLineThreshold = 6;
    /**
     * @psalm-var positive-int
     */
    private int $contextLines = 3;
    private string $header;
    private bool $addLineNumbers;
    public function __construct(string $header = "--- Original\n+++ New\n", bool $addLineNumbers = \false)
    {
        $this->header = $header;
        $this->addLineNumbers = $addLineNumbers;
    }
    public function getDiff(array $diff): string
    {
        $buffer = fopen('php://memory', 'r+b');
        if ('' !== $this->header) {
            fwrite($buffer, $this->header);
            if (!str_ends_with($this->header, "\n")) {
                fwrite($buffer, "\n");
            }
        }
        if (0 !== count($diff)) {
            $this->writeDiffHunks($buffer, $diff);
        }
        $diff = stream_get_contents($buffer, -1, 0);
        fclose($buffer);
        // If the diff is non-empty and last char is not a linebreak: add it.
        // This might happen when both the `from` and `to` do not have a trailing linebreak
        $last = substr($diff, -1);
        return '' !== $diff && "\n" !== $last && "\r" !== $last ? $diff . "\n" : $diff;
    }
    private function writeDiffHunks($output, array $diff): void
    {
        // detect "No newline at end of file" and insert into `$diff` if needed
        $upperLimit = count($diff);
        if (0 === $diff[$upperLimit - 1][1]) {
            $lc = substr($diff[$upperLimit - 1][0], -1);
            if ("\n" !== $lc) {
                array_splice($diff, $upperLimit, 0, [["\n\\ No newline at end of file\n", Differ::NO_LINE_END_EOF_WARNING]]);
            }
        } else {
            // search back for the last `+` and `-` line,
            // check if it has trailing linebreak, else add a warning under it
            $toFind = [1 => \true, 2 => \true];
            for ($i = $upperLimit - 1; $i >= 0; $i--) {
                if (isset($toFind[$diff[$i][1]])) {
                    unset($toFind[$diff[$i][1]]);
                    $lc = substr($diff[$i][0], -1);
                    if ("\n" !== $lc) {
                        array_splice($diff, $i + 1, 0, [["\n\\ No newline at end of file\n", Differ::NO_LINE_END_EOF_WARNING]]);
                    }
                    if (!count($toFind)) {
                        break;
                    }
                }
            }
        }
        // write hunks to output buffer
        $cutOff = max($this->commonLineThreshold, $this->contextLines);
        $hunkCapture = \false;
        $sameCount = $toRange = $fromRange = 0;
        $toStart = $fromStart = 1;
        $i = 0;
        /** @var int $i */
        foreach ($diff as $i => $entry) {
            if (0 === $entry[1]) {
                // same
                if (\false === $hunkCapture) {
                    $fromStart++;
                    $toStart++;
                    continue;
                }
                $sameCount++;
                $toRange++;
                $fromRange++;
                if ($sameCount === $cutOff) {
                    $contextStartOffset = $hunkCapture - $this->contextLines < 0 ? $hunkCapture : $this->contextLines;
                    // note: $contextEndOffset = $this->contextLines;
                    //
                    // because we never go beyond the end of the diff.
                    // with the cutoff/contextlines here the follow is never true;
                    //
                    // if ($i - $cutOff + $this->contextLines + 1 > \count($diff)) {
                    //    $contextEndOffset = count($diff) - 1;
                    // }
                    //
                    // ; that would be true for a trailing incomplete hunk case which is dealt with after this loop
                    $this->writeHunk($diff, $hunkCapture - $contextStartOffset, $i - $cutOff + $this->contextLines + 1, $fromStart - $contextStartOffset, $fromRange - $cutOff + $contextStartOffset + $this->contextLines, $toStart - $contextStartOffset, $toRange - $cutOff + $contextStartOffset + $this->contextLines, $output);
                    $fromStart += $fromRange;
                    $toStart += $toRange;
                    $hunkCapture = \false;
                    $sameCount = $toRange = $fromRange = 0;
                }
                continue;
            }
            $sameCount = 0;
            if ($entry[1] === Differ::NO_LINE_END_EOF_WARNING) {
                continue;
            }
            if (\false === $hunkCapture) {
                $hunkCapture = $i;
            }
            if (Differ::ADDED === $entry[1]) {
                $toRange++;
            }
            if (Differ::REMOVED === $entry[1]) {
                $fromRange++;
            }
        }
        if (\false === $hunkCapture) {
            return;
        }
        // we end here when cutoff (commonLineThreshold) was not reached, but we were capturing a hunk,
        // do not render hunk till end automatically because the number of context lines might be less than the commonLineThreshold
        $contextStartOffset = $hunkCapture - $this->contextLines < 0 ? $hunkCapture : $this->contextLines;
        // prevent trying to write out more common lines than there are in the diff _and_
        // do not write more than configured through the context lines
        $contextEndOffset = min($sameCount, $this->contextLines);
        $fromRange -= $sameCount;
        $toRange -= $sameCount;
        $this->writeHunk($diff, $hunkCapture - $contextStartOffset, $i - $sameCount + $contextEndOffset + 1, $fromStart - $contextStartOffset, $fromRange + $contextStartOffset + $contextEndOffset, $toStart - $contextStartOffset, $toRange + $contextStartOffset + $contextEndOffset, $output);
    }
    private function writeHunk(array $diff, int $diffStartIndex, int $diffEndIndex, int $fromStart, int $fromRange, int $toStart, int $toRange, $output): void
    {
        if ($this->addLineNumbers) {
            fwrite($output, '@@ -' . $fromStart);
            if (!$this->collapseRanges || 1 !== $fromRange) {
                fwrite($output, ',' . $fromRange);
            }
            fwrite($output, ' +' . $toStart);
            if (!$this->collapseRanges || 1 !== $toRange) {
                fwrite($output, ',' . $toRange);
            }
            fwrite($output, " @@\n");
        } else {
            fwrite($output, "@@ @@\n");
        }
        for ($i = $diffStartIndex; $i < $diffEndIndex; $i++) {
            if ($diff[$i][1] === Differ::ADDED) {
                fwrite($output, '+' . $diff[$i][0]);
            } elseif ($diff[$i][1] === Differ::REMOVED) {
                fwrite($output, '-' . $diff[$i][0]);
            } elseif ($diff[$i][1] === Differ::OLD) {
                fwrite($output, ' ' . $diff[$i][0]);
            } elseif ($diff[$i][1] === Differ::NO_LINE_END_EOF_WARNING) {
                fwrite($output, "\n");
                // $diff[$i][0]
            } else {
                /* Not changed (old) Differ::OLD or Warning Differ::DIFF_LINE_END_WARNING */
                fwrite($output, ' ' . $diff[$i][0]);
            }
        }
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of sebastian/diff.
 *
 * (c) Sebastian Bergmann <sebastian@phpunit.de>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\SebastianBergmann\Diff\Output;

use function array_merge;
use function array_splice;
use function count;
use function fclose;
use function fopen;
use function fwrite;
use function is_bool;
use function is_int;
use function is_string;
use function max;
use function min;
use function sprintf;
use function stream_get_contents;
use function substr;
use _ContaoManager\SebastianBergmann\Diff\ConfigurationException;
use _ContaoManager\SebastianBergmann\Diff\Differ;
/**
 * Strict Unified diff output builder.
 *
 * Generates (strict) Unified diff's (unidiffs) with hunks.
 */
final class StrictUnifiedDiffOutputBuilder implements DiffOutputBuilderInterface
{
    private static array $default = [
        'collapseRanges' => \true,
        // ranges of length one are rendered with the trailing `,1`
        'commonLineThreshold' => 6,
        // number of same lines before ending a new hunk and creating a new one (if needed)
        'contextLines' => 3,
        // like `diff:  -u, -U NUM, --unified[=NUM]`, for patch/git apply compatibility best to keep at least @ 3
        'fromFile' => null,
        'fromFileDate' => null,
        'toFile' => null,
        'toFileDate' => null,
    ];
    private bool $changed;
    private bool $collapseRanges;
    /**
     * @psalm-var positive-int
     */
    private int $commonLineThreshold;
    private string $header;
    /**
     * @psalm-var positive-int
     */
    private int $contextLines;
    public function __construct(array $options = [])
    {
        $options = array_merge(self::$default, $options);
        if (!is_bool($options['collapseRanges'])) {
            throw new ConfigurationException('collapseRanges', 'a bool', $options['collapseRanges']);
        }
        if (!is_int($options['contextLines']) || $options['contextLines'] < 0) {
            throw new ConfigurationException('contextLines', 'an int >= 0', $options['contextLines']);
        }
        if (!is_int($options['commonLineThreshold']) || $options['commonLineThreshold'] <= 0) {
            throw new ConfigurationException('commonLineThreshold', 'an int > 0', $options['commonLineThreshold']);
        }
        $this->assertString($options, 'fromFile');
        $this->assertString($options, 'toFile');
        $this->assertStringOrNull($options, 'fromFileDate');
        $this->assertStringOrNull($options, 'toFileDate');
        $this->header = sprintf("--- %s%s\n+++ %s%s\n", $options['fromFile'], null === $options['fromFileDate'] ? '' : "\t" . $options['fromFileDate'], $options['toFile'], null === $options['toFileDate'] ? '' : "\t" . $options['toFileDate']);
        $this->collapseRanges = $options['collapseRanges'];
        $this->commonLineThreshold = $options['commonLineThreshold'];
        $this->contextLines = $options['contextLines'];
    }
    public function getDiff(array $diff): string
    {
        if (0 === count($diff)) {
            return '';
        }
        $this->changed = \false;
        $buffer = fopen('php://memory', 'r+b');
        fwrite($buffer, $this->header);
        $this->writeDiffHunks($buffer, $diff);
        if (!$this->changed) {
            fclose($buffer);
            return '';
        }
        $diff = stream_get_contents($buffer, -1, 0);
        fclose($buffer);
        // If the last char is not a linebreak: add it.
        // This might happen when both the `from` and `to` do not have a trailing linebreak
        $last = substr($diff, -1);
        return "\n" !== $last && "\r" !== $last ? $diff . "\n" : $diff;
    }
    private function writeDiffHunks($output, array $diff): void
    {
        // detect "No newline at end of file" and insert into `$diff` if needed
        $upperLimit = count($diff);
        if (0 === $diff[$upperLimit - 1][1]) {
            $lc = substr($diff[$upperLimit - 1][0], -1);
            if ("\n" !== $lc) {
                array_splice($diff, $upperLimit, 0, [["\n\\ No newline at end of file\n", Differ::NO_LINE_END_EOF_WARNING]]);
            }
        } else {
            // search back for the last `+` and `-` line,
            // check if it has a trailing linebreak, else add a warning under it
            $toFind = [1 => \true, 2 => \true];
            for ($i = $upperLimit - 1; $i >= 0; $i--) {
                if (isset($toFind[$diff[$i][1]])) {
                    unset($toFind[$diff[$i][1]]);
                    $lc = substr($diff[$i][0], -1);
                    if ("\n" !== $lc) {
                        array_splice($diff, $i + 1, 0, [["\n\\ No newline at end of file\n", Differ::NO_LINE_END_EOF_WARNING]]);
                    }
                    if (!count($toFind)) {
                        break;
                    }
                }
            }
        }
        // write hunks to output buffer
        $cutOff = max($this->commonLineThreshold, $this->contextLines);
        $hunkCapture = \false;
        $sameCount = $toRange = $fromRange = 0;
        $toStart = $fromStart = 1;
        $i = 0;
        /** @var int $i */
        foreach ($diff as $i => $entry) {
            if (0 === $entry[1]) {
                // same
                if (\false === $hunkCapture) {
                    $fromStart++;
                    $toStart++;
                    continue;
                }
                $sameCount++;
                $toRange++;
                $fromRange++;
                if ($sameCount === $cutOff) {
                    $contextStartOffset = $hunkCapture - $this->contextLines < 0 ? $hunkCapture : $this->contextLines;
                    // note: $contextEndOffset = $this->contextLines;
                    //
                    // because we never go beyond the end of the diff.
                    // with the cutoff/contextlines here the follow is never true;
                    //
                    // if ($i - $cutOff + $this->contextLines + 1 > \count($diff)) {
                    //    $contextEndOffset = count($diff) - 1;
                    // }
                    //
                    // ; that would be true for a trailing incomplete hunk case which is dealt with after this loop
                    $this->writeHunk($diff, $hunkCapture - $contextStartOffset, $i - $cutOff + $this->contextLines + 1, $fromStart - $contextStartOffset, $fromRange - $cutOff + $contextStartOffset + $this->contextLines, $toStart - $contextStartOffset, $toRange - $cutOff + $contextStartOffset + $this->contextLines, $output);
                    $fromStart += $fromRange;
                    $toStart += $toRange;
                    $hunkCapture = \false;
                    $sameCount = $toRange = $fromRange = 0;
                }
                continue;
            }
            $sameCount = 0;
            if ($entry[1] === Differ::NO_LINE_END_EOF_WARNING) {
                continue;
            }
            $this->changed = \true;
            if (\false === $hunkCapture) {
                $hunkCapture = $i;
            }
            if (Differ::ADDED === $entry[1]) {
                // added
                $toRange++;
            }
            if (Differ::REMOVED === $entry[1]) {
                // removed
                $fromRange++;
            }
        }
        if (\false === $hunkCapture) {
            return;
        }
        // we end here when cutoff (commonLineThreshold) was not reached, but we were capturing a hunk,
        // do not render hunk till end automatically because the number of context lines might be less than the commonLineThreshold
        $contextStartOffset = $hunkCapture - $this->contextLines < 0 ? $hunkCapture : $this->contextLines;
        // prevent trying to write out more common lines than there are in the diff _and_
        // do not write more than configured through the context lines
        $contextEndOffset = min($sameCount, $this->contextLines);
        $fromRange -= $sameCount;
        $toRange -= $sameCount;
        $this->writeHunk($diff, $hunkCapture - $contextStartOffset, $i - $sameCount + $contextEndOffset + 1, $fromStart - $contextStartOffset, $fromRange + $contextStartOffset + $contextEndOffset, $toStart - $contextStartOffset, $toRange + $contextStartOffset + $contextEndOffset, $output);
    }
    private function writeHunk(array $diff, int $diffStartIndex, int $diffEndIndex, int $fromStart, int $fromRange, int $toStart, int $toRange, $output): void
    {
        fwrite($output, '@@ -' . $fromStart);
        if (!$this->collapseRanges || 1 !== $fromRange) {
            fwrite($output, ',' . $fromRange);
        }
        fwrite($output, ' +' . $toStart);
        if (!$this->collapseRanges || 1 !== $toRange) {
            fwrite($output, ',' . $toRange);
        }
        fwrite($output, " @@\n");
        for ($i = $diffStartIndex; $i < $diffEndIndex; $i++) {
            if ($diff[$i][1] === Differ::ADDED) {
                $this->changed = \true;
                fwrite($output, '+' . $diff[$i][0]);
            } elseif ($diff[$i][1] === Differ::REMOVED) {
                $this->changed = \true;
                fwrite($output, '-' . $diff[$i][0]);
            } elseif ($diff[$i][1] === Differ::OLD) {
                fwrite($output, ' ' . $diff[$i][0]);
            } elseif ($diff[$i][1] === Differ::NO_LINE_END_EOF_WARNING) {
                $this->changed = \true;
                fwrite($output, $diff[$i][0]);
            }
            // } elseif ($diff[$i][1] === Differ::DIFF_LINE_END_WARNING) { // custom comment inserted by PHPUnit/diff package
            //  skip
            // } else {
            //  unknown/invalid
            // }
        }
    }
    private function assertString(array $options, string $option): void
    {
        if (!is_string($options[$option])) {
            throw new ConfigurationException($option, 'a string', $options[$option]);
        }
    }
    private function assertStringOrNull(array $options, string $option): void
    {
        if (null !== $options[$option] && !is_string($options[$option])) {
            throw new ConfigurationException($option, 'a string or <null>', $options[$option]);
        }
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of sebastian/diff.
 *
 * (c) Sebastian Bergmann <sebastian@phpunit.de>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\SebastianBergmann\Diff\Output;

use function count;
abstract class AbstractChunkOutputBuilder implements DiffOutputBuilderInterface
{
    /**
     * Takes input of the diff array and returns the common parts.
     * Iterates through diff line by line.
     */
    protected function getCommonChunks(array $diff, int $lineThreshold = 5): array
    {
        $diffSize = count($diff);
        $capturing = \false;
        $chunkStart = 0;
        $chunkSize = 0;
        $commonChunks = [];
        for ($i = 0; $i < $diffSize; $i++) {
            if ($diff[$i][1] === 0) {
                if ($capturing === \false) {
                    $capturing = \true;
                    $chunkStart = $i;
                    $chunkSize = 0;
                } else {
                    $chunkSize++;
                }
            } elseif ($capturing !== \false) {
                if ($chunkSize >= $lineThreshold) {
                    $commonChunks[$chunkStart] = $chunkStart + $chunkSize;
                }
                $capturing = \false;
            }
        }
        if ($capturing !== \false && $chunkSize >= $lineThreshold) {
            $commonChunks[$chunkStart] = $chunkStart + $chunkSize;
        }
        return $commonChunks;
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of sebastian/diff.
 *
 * (c) Sebastian Bergmann <sebastian@phpunit.de>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\SebastianBergmann\Diff;

interface LongestCommonSubsequenceCalculator
{
    /**
     * Calculates the longest common subsequence of two arrays.
     */
    public function calculate(array $from, array $to): array;
}
<?php

declare (strict_types=1);
/*
 * This file is part of sebastian/diff.
 *
 * (c) Sebastian Bergmann <sebastian@phpunit.de>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\SebastianBergmann\Diff;

use ArrayIterator;
use IteratorAggregate;
use Traversable;
/**
 * @template-implements IteratorAggregate<int, Line>
 */
final class Chunk implements IteratorAggregate
{
    private int $start;
    private int $startRange;
    private int $end;
    private int $endRange;
    private array $lines;
    public function __construct(int $start = 0, int $startRange = 1, int $end = 0, int $endRange = 1, array $lines = [])
    {
        $this->start = $start;
        $this->startRange = $startRange;
        $this->end = $end;
        $this->endRange = $endRange;
        $this->lines = $lines;
    }
    public function start(): int
    {
        return $this->start;
    }
    public function startRange(): int
    {
        return $this->startRange;
    }
    public function end(): int
    {
        return $this->end;
    }
    public function endRange(): int
    {
        return $this->endRange;
    }
    /**
     * @psalm-return list<Line>
     */
    public function lines(): array
    {
        return $this->lines;
    }
    /**
     * @psalm-param list<Line> $lines
     */
    public function setLines(array $lines): void
    {
        foreach ($lines as $line) {
            if (!$line instanceof Line) {
                throw new InvalidArgumentException();
            }
        }
        $this->lines = $lines;
    }
    /**
     * @deprecated Use start() instead
     */
    public function getStart(): int
    {
        return $this->start;
    }
    /**
     * @deprecated Use startRange() instead
     */
    public function getStartRange(): int
    {
        return $this->startRange;
    }
    /**
     * @deprecated Use end() instead
     */
    public function getEnd(): int
    {
        return $this->end;
    }
    /**
     * @deprecated Use endRange() instead
     */
    public function getEndRange(): int
    {
        return $this->endRange;
    }
    /**
     * @psalm-return list<Line>
     *
     * @deprecated Use lines() instead
     */
    public function getLines(): array
    {
        return $this->lines;
    }
    public function getIterator(): Traversable
    {
        return new ArrayIterator($this->lines);
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of sebastian/diff.
 *
 * (c) Sebastian Bergmann <sebastian@phpunit.de>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\SebastianBergmann\Diff;

use const PHP_INT_SIZE;
use const PREG_SPLIT_DELIM_CAPTURE;
use const PREG_SPLIT_NO_EMPTY;
use function array_shift;
use function array_unshift;
use function array_values;
use function count;
use function current;
use function end;
use function is_string;
use function key;
use function min;
use function preg_split;
use function prev;
use function reset;
use function str_ends_with;
use function substr;
use _ContaoManager\SebastianBergmann\Diff\Output\DiffOutputBuilderInterface;
final class Differ
{
    public const OLD = 0;
    public const ADDED = 1;
    public const REMOVED = 2;
    public const DIFF_LINE_END_WARNING = 3;
    public const NO_LINE_END_EOF_WARNING = 4;
    private DiffOutputBuilderInterface $outputBuilder;
    public function __construct(DiffOutputBuilderInterface $outputBuilder)
    {
        $this->outputBuilder = $outputBuilder;
    }
    public function diff(array|string $from, array|string $to, ?LongestCommonSubsequenceCalculator $lcs = null): string
    {
        $diff = $this->diffToArray($from, $to, $lcs);
        return $this->outputBuilder->getDiff($diff);
    }
    public function diffToArray(array|string $from, array|string $to, ?LongestCommonSubsequenceCalculator $lcs = null): array
    {
        if (is_string($from)) {
            $from = $this->splitStringByLines($from);
        }
        if (is_string($to)) {
            $to = $this->splitStringByLines($to);
        }
        [$from, $to, $start, $end] = self::getArrayDiffParted($from, $to);
        if ($lcs === null) {
            $lcs = $this->selectLcsImplementation($from, $to);
        }
        $common = $lcs->calculate(array_values($from), array_values($to));
        $diff = [];
        foreach ($start as $token) {
            $diff[] = [$token, self::OLD];
        }
        reset($from);
        reset($to);
        foreach ($common as $token) {
            while (($fromToken = reset($from)) !== $token) {
                $diff[] = [array_shift($from), self::REMOVED];
            }
            while (($toToken = reset($to)) !== $token) {
                $diff[] = [array_shift($to), self::ADDED];
            }
            $diff[] = [$token, self::OLD];
            array_shift($from);
            array_shift($to);
        }
        while (($token = array_shift($from)) !== null) {
            $diff[] = [$token, self::REMOVED];
        }
        while (($token = array_shift($to)) !== null) {
            $diff[] = [$token, self::ADDED];
        }
        foreach ($end as $token) {
            $diff[] = [$token, self::OLD];
        }
        if ($this->detectUnmatchedLineEndings($diff)) {
            array_unshift($diff, ["#Warning: Strings contain different line endings!\n", self::DIFF_LINE_END_WARNING]);
        }
        return $diff;
    }
    private function splitStringByLines(string $input): array
    {
        return preg_split('/(.*\R)/', $input, -1, PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY);
    }
    private function selectLcsImplementation(array $from, array $to): LongestCommonSubsequenceCalculator
    {
        // We do not want to use the time-efficient implementation if its memory
        // footprint will probably exceed this value. Note that the footprint
        // calculation is only an estimation for the matrix and the LCS method
        // will typically allocate a bit more memory than this.
        $memoryLimit = 100 * 1024 * 1024;
        if ($this->calculateEstimatedFootprint($from, $to) > $memoryLimit) {
            return new MemoryEfficientLongestCommonSubsequenceCalculator();
        }
        return new TimeEfficientLongestCommonSubsequenceCalculator();
    }
    private function calculateEstimatedFootprint(array $from, array $to): float|int
    {
        $itemSize = PHP_INT_SIZE === 4 ? 76 : 144;
        return $itemSize * min(count($from), count($to)) ** 2;
    }
    private function detectUnmatchedLineEndings(array $diff): bool
    {
        $newLineBreaks = ['' => \true];
        $oldLineBreaks = ['' => \true];
        foreach ($diff as $entry) {
            if (self::OLD === $entry[1]) {
                $ln = $this->getLinebreak($entry[0]);
                $oldLineBreaks[$ln] = \true;
                $newLineBreaks[$ln] = \true;
            } elseif (self::ADDED === $entry[1]) {
                $newLineBreaks[$this->getLinebreak($entry[0])] = \true;
            } elseif (self::REMOVED === $entry[1]) {
                $oldLineBreaks[$this->getLinebreak($entry[0])] = \true;
            }
        }
        // if either input or output is a single line without breaks than no warning should be raised
        if (['' => \true] === $newLineBreaks || ['' => \true] === $oldLineBreaks) {
            return \false;
        }
        // two-way compare
        foreach ($newLineBreaks as $break => $set) {
            if (!isset($oldLineBreaks[$break])) {
                return \true;
            }
        }
        foreach ($oldLineBreaks as $break => $set) {
            if (!isset($newLineBreaks[$break])) {
                return \true;
            }
        }
        return \false;
    }
    private function getLinebreak($line): string
    {
        if (!is_string($line)) {
            return '';
        }
        $lc = substr($line, -1);
        if ("\r" === $lc) {
            return "\r";
        }
        if ("\n" !== $lc) {
            return '';
        }
        if (str_ends_with($line, "\r\n")) {
            return "\r\n";
        }
        return "\n";
    }
    private static function getArrayDiffParted(array &$from, array &$to): array
    {
        $start = [];
        $end = [];
        reset($to);
        foreach ($from as $k => $v) {
            $toK = key($to);
            if ($toK === $k && $v === $to[$k]) {
                $start[$k] = $v;
                unset($from[$k], $to[$k]);
            } else {
                break;
            }
        }
        end($from);
        end($to);
        do {
            $fromK = key($from);
            $toK = key($to);
            if (null === $fromK || null === $toK || current($from) !== current($to)) {
                break;
            }
            prev($from);
            prev($to);
            $end = [$fromK => $from[$fromK]] + $end;
            unset($from[$fromK], $to[$toK]);
        } while (\true);
        return [$from, $to, $start, $end];
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of sebastian/diff.
 *
 * (c) Sebastian Bergmann <sebastian@phpunit.de>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\SebastianBergmann\Diff;

final class Line
{
    public const ADDED = 1;
    public const REMOVED = 2;
    public const UNCHANGED = 3;
    private int $type;
    private string $content;
    public function __construct(int $type = self::UNCHANGED, string $content = '')
    {
        $this->type = $type;
        $this->content = $content;
    }
    public function content(): string
    {
        return $this->content;
    }
    public function type(): int
    {
        return $this->type;
    }
    public function isAdded(): bool
    {
        return $this->type === self::ADDED;
    }
    public function isRemoved(): bool
    {
        return $this->type === self::REMOVED;
    }
    public function isUnchanged(): bool
    {
        return $this->type === self::UNCHANGED;
    }
    /**
     * @deprecated
     */
    public function getContent(): string
    {
        return $this->content;
    }
    /**
     * @deprecated
     */
    public function getType(): int
    {
        return $this->type;
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of sebastian/diff.
 *
 * (c) Sebastian Bergmann <sebastian@phpunit.de>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\SebastianBergmann\Diff;

use function gettype;
use function is_object;
use function sprintf;
use Exception;
final class ConfigurationException extends InvalidArgumentException
{
    public function __construct(string $option, string $expected, $value, int $code = 0, ?Exception $previous = null)
    {
        parent::__construct(sprintf('Option "%s" must be %s, got "%s".', $option, $expected, is_object($value) ? $value::class : (null === $value ? '<null>' : gettype($value) . '#' . $value)), $code, $previous);
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of sebastian/diff.
 *
 * (c) Sebastian Bergmann <sebastian@phpunit.de>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\SebastianBergmann\Diff;

class InvalidArgumentException extends \InvalidArgumentException implements Exception
{
}
<?php

declare (strict_types=1);
/*
 * This file is part of sebastian/diff.
 *
 * (c) Sebastian Bergmann <sebastian@phpunit.de>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\SebastianBergmann\Diff;

use Throwable;
interface Exception extends Throwable
{
}
<?php

declare (strict_types=1);
/*
 * This file is part of sebastian/diff.
 *
 * (c) Sebastian Bergmann <sebastian@phpunit.de>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace _ContaoManager\SebastianBergmann\Diff;

use function array_fill;
use function array_merge;
use function array_reverse;
use function array_slice;
use function count;
use function in_array;
use function max;
final class MemoryEfficientLongestCommonSubsequenceCalculator implements LongestCommonSubsequenceCalculator
{
    /**
     * @inheritDoc
     */
    public function calculate(array $from, array $to): array
    {
        $cFrom = count($from);
        $cTo = count($to);
        if ($cFrom === 0) {
            return [];
        }
        if ($cFrom === 1) {
            if (in_array($from[0], $to, \true)) {
                return [$from[0]];
            }
            return [];
        }
        $i = (int) ($cFrom / 2);
        $fromStart = array_slice($from, 0, $i);
        $fromEnd = array_slice($from, $i);
        $llB = $this->length($fromStart, $to);
        $llE = $this->length(array_reverse($fromEnd), array_reverse($to));
        $jMax = 0;
        $max = 0;
        for ($j = 0; $j <= $cTo; $j++) {
            $m = $llB[$j] + $llE[$cTo - $j];
            if ($m >= $max) {
                $max = $m;
                $jMax = $j;
            }
        }
        $toStart = array_slice($to, 0, $jMax);
        $toEnd = array_slice($to, $jMax);
        return array_merge($this->calculate($fromStart, $toStart), $this->calculate($fromEnd, $toEnd));
    }
    private function length(array $from, array $to): array
    {
        $current = array_fill(0, count($to) + 1, 0);
        $cFrom = count($from);
        $cTo = count($to);
        for ($i = 0; $i < $cFrom; $i++) {
            $prev = $current;
            for ($j = 0; $j < $cTo; $j++) {
                if ($from[$i] === $to[$j]) {
                    $current[$j + 1] = $prev[$j] + 1;
                } else if ($current[$j] > $prev[$j + 1]) {
                    $current[$j + 1] = $current[$j];
                } else {
                    $current[$j + 1] = $prev[$j + 1];
                }
            }
        }
        return $current;
    }
}
## Composer lock file validator

This library allows to compare a given `composer.lock` file against your local Composer instance.
 
You can use it to e.g. ensure a provided `composer.lock` does not contain any foreign packages (not required by your Composer 
instance - aka `composer.json`) or package URLs that have been tampered with. It also detects removed packages that 
should be present.

Usage:

```php
use \Terminal42\ComposerLockValidator\Validator;
use \Terminal42\ComposerLockValidator\ValidationException;

$composerLock = [
    'content-hash' => '...',
    'packages' => [...]
    'packages-dev' => [...]
];

// You can either pass an already existing Composer instance
$validator = Validator::createFromComposer($composer);
// Or provide a path to your composer.json
$validator = Validator::createFromComposerJson($pathToComposerJson);

try {
    $validator->validate($composerLock);
} catch (ValidationException $exception) {
    echo 'Invalid: ' . $exception->getMessage();
}

echo 'Valid!';
```


### Partial validation / validation against existing `composer.lock`

When you run `composer update` as a partial update (e.g. `composer update <vendor/package> --with-dependencies`), Composer
will not update the `composer.lock` information of all the other packages. Hence, validating will probably fail because one
of the other packages have experienced metadata updates in the meantime (new URL, probably `abandoned`, different `branch-aliases` etc.).
In such a case, you might want to add your already existing `composer.lock` file as additional source of truth. Every
package in the `composer.lock` you want to validate then has to either match the metadata of the repositories or the entry
of an already existing `composer.lock`. Simply pass the data of the existing `composer.lock` as second argument:

```php
use \Terminal42\ComposerLockValidator\Validator;
use \Terminal42\ComposerLockValidator\ValidationException;

$composerLock = [
    'content-hash' => '...',
    'packages' => [...]
    'packages-dev' => [...]
];

$alreadyExistingComposerLockITrust = [
    'content-hash' => '...',
    'packages' => [...]
    'packages-dev' => [...]
];

// You can either pass an already existing Composer instance
$validator = Validator::createFromComposer($composer);
// Or provide a path to your composer.json
$validator = Validator::createFromComposerJson($pathToComposerJson);

try {
    $validator->validate($composerLock, $alreadyExistingComposerLockITrust);
} catch (ValidationException $exception) {
    echo 'Invalid: ' . $exception->getMessage();
}

echo 'Valid!';
```
{
    "name": "terminal42\/composer-lock-validator",
    "description": "A library to validate a composer.lock file against your local Composer instance",
    "type": "library",
    "license": "MIT",
    "autoload": {
        "psr-4": {
            "_ContaoManager\\Terminal42\\ComposerLockValidator\\": "src\/"
        }
    },
    "autoload-dev": {
        "psr-4": {
            "_ContaoManager\\Terminal42\\ComposerLockValidator\\Tests\\": "tests\/"
        }
    },
    "authors": [
        {
            "name": "Yanick Witschi",
            "email": "yanick.witschi@terminal42.ch"
        }
    ],
    "require": {
        "php": "^8.1",
        "composer\/composer": "^2.8",
        "composer\/semver": "^3.4",
        "sebastian\/diff": "^5.1"
    },
    "require-dev": {
        "phpunit\/phpunit": "^10.5",
        "terminal42\/contao-build-tools": "@dev"
    },
    "config": {
        "allow-plugins": {
            "terminal42\/contao-build-tools": true
        }
    },
    "scripts": {
        "unit-tests": "@php vendor\/bin\/phpunit"
    }
}<?php

declare (strict_types=1);
namespace _ContaoManager\Terminal42\ComposerLockValidator;

use Composer\Composer;
use Composer\DependencyResolver\Pool;
use Composer\DependencyResolver\Request;
use Composer\Factory;
use Composer\IO\IOInterface;
use Composer\IO\NullIO;
use Composer\Package\BasePackage;
use Composer\Package\Dumper\ArrayDumper;
use Composer\Package\Loader\ArrayLoader;
use Composer\Package\PackageInterface;
use Composer\Package\RootAliasPackage;
use Composer\Package\RootPackageInterface;
use Composer\Repository\FilterRepository;
use Composer\Repository\InstalledRepository;
use Composer\Repository\LockArrayRepository;
use Composer\Repository\PlatformRepository;
use Composer\Repository\RepositorySet;
use Composer\Repository\RootPackageRepository;
use Composer\Semver\Constraint\Constraint;
use Composer\Semver\Constraint\MultiConstraint;
use Composer\Semver\Intervals;
final class Validator
{
    private function __construct(private readonly Composer $composer)
    {
    }
    public static function createFromComposerJson(string $pathToComposerJson, IOInterface|null $io = null): self
    {
        return new self(Factory::create($io ?? new NullIO(), $pathToComposerJson));
    }
    public static function createFromComposer(Composer $composer): self
    {
        return new self($composer);
    }
    /**
     * @param array<mixed>      $composerLock
     * @param array<mixed>|null $existingComposerLock
     *
     * @throws ValidationException
     */
    public function validate(array $composerLock, array|null $existingComposerLock = null): void
    {
        try {
            // 1st step, validate basic composer.lock requirements
            $composerLockRepository = $this->buildComposerLockRepository($composerLock);
            // Use the pool because this handles all the replaces and provides as well
            $pool = $this->createPool($composerLockRepository, $existingComposerLock ? $this->buildComposerLockRepository($existingComposerLock) : null);
            // 2nd step: validate if there is a package present, that is not required by the root composer.json
            // 3rd step: validate if no package has been removed from the composer.lock
            $this->validateNoAddedAndRemovedPackages($composerLockRepository, $pool);
            // 4th step: validate the metadata of all provided packages in the composer.lock.
            // In case of the full update, all the packages have to be compared against the repository data
            foreach ($composerLockRepository->getPackages() as $package) {
                $this->validatePackageMetadataAgainstRepositories($package, $pool, null !== $existingComposerLock);
            }
        } catch (ValidationException $exception) {
            throw $exception;
        } catch (\Throwable $exception) {
            throw ValidationException::becauseOfOtherException($exception);
        }
    }
    /**
     * @param array<mixed> $composerLock
     */
    private function buildComposerLockRepository(array $composerLock): LockArrayRepository
    {
        if (!isset($composerLock['packages'], $composerLock['packages-dev']) || !\is_array($composerLock['packages']) || !\is_array($composerLock['packages-dev'])) {
            throw ValidationException::becausePackagesKeyMissingOrIncorrectInComposerLock();
        }
        $composerLockRepo = new LockArrayRepository();
        $loader = new ArrayLoader();
        foreach (array_merge($composerLock['packages'], $composerLock['packages-dev']) as $packageData) {
            $package = $loader->load($packageData);
            $composerLockRepo->addPackage($package);
        }
        return $composerLockRepo;
    }
    private function validateNoAddedAndRemovedPackages(LockArrayRepository $composerLockRepo, Pool $pool): void
    {
        // Create an installed repo with our local root package repo and the provided composer.lock repo to check
        // for valid dependents.
        $installedRepo = new InstalledRepository([new RootPackageRepository($this->getRootPackage()), $composerLockRepo]);
        $allRequirements = [];
        // 2nd step: validate if there is a package present, that is not required by the root composer.json
        foreach ($composerLockRepo->getPackages() as $package) {
            if ([] === $installedRepo->getDependents($package->getName(), null, \false, \false)) {
                throw ValidationException::becauseNoPackageRequiresPackage($package->getName(), $package->getVersion());
            }
            // Collect requirements for the 3rd step
            foreach ($package->getRequires() as $require) {
                if (PlatformRepository::isPlatformPackage($require->getTarget())) {
                    continue;
                }
                $target = $require->getTarget();
                $constraint = $require->getConstraint();
                // Widen the requirement if one package required this package already
                $allRequirements[$target] = isset($allRequirements[$target]) ? new MultiConstraint([$allRequirements[$target], $constraint], \false) : $constraint;
            }
        }
        // 3rd step: validate that no package has been removed from the composer.lock
        foreach ($allRequirements as $packageName => $constraint) {
            $constraint = Intervals::compactConstraint($constraint);
            if ([] === $pool->whatProvides($packageName, $constraint)) {
                throw ValidationException::becauseOfRemovedPackage($packageName, $constraint->getPrettyString());
            }
        }
    }
    /**
     * @throws ValidationException
     * @throws \Throwable
     */
    private function validatePackageMetadataAgainstRepositories(PackageInterface $package, Pool $pool, bool $addHintAboutLocalComposerLockOnFailure): void
    {
        $providedPackageArray = $this->dumpPackage($package);
        foreach ($pool->whatProvides($package->getName(), new Constraint('=', $package->getVersion())) as $validPackage) {
            $validPackageArray = $this->dumpPackage($validPackage);
            if ($providedPackageArray === $validPackageArray) {
                return;
                // Valid!
            }
        }
        throw ValidationException::becauseOfInvalidMetadataForPackage($package->getName(), $package->getVersion(), $providedPackageArray, $validPackageArray ?? [], $addHintAboutLocalComposerLockOnFailure);
    }
    /**
     * @return array<mixed>
     */
    private function dumpPackage(PackageInterface $package): array
    {
        $dumper = new ArrayDumper();
        $dump = $dumper->dump($package);
        // Remove useless keys that might cause issues when validating because Composer tampers with those in the Locker.
        // They are not relevant for integrity checks anyway (still cannot fake download URLs or wrong requires etc.)
        unset($dump['version_normalized'], $dump['time'], $dump['installation-source']);
        // Remove reference and transport-options for path repositories
        if (isset($dump['dist']['type']) && 'path' === $dump['dist']['type']) {
            unset($dump['dist']['reference'], $dump['transport-options']);
        }
        // Sort branch aliases
        if (isset($dump['extra']['branch-alias'])) {
            ksort($dump['extra']['branch-alias']);
        }
        return $dump;
    }
    private function createPool(LockArrayRepository $composerLockRepo, LockArrayRepository|null $existingComposerLockRepo = null): Pool
    {
        $rootPackage = $this->getRootPackage();
        $repoSet = new RepositorySet($rootPackage->getMinimumStability(), $rootPackage->getStabilityFlags(), $rootPackage->getAliases(), $rootPackage->getReferences());
        $repoSet->addRepository(new RootPackageRepository($rootPackage));
        // Add the existing composer lock repo as repository for valid packages too, in case that was passed
        // It must be the first one so it's checked first (= shortcut if it exists) but it must be set to canonical -> false
        // so that other repositories are still checked
        if ($existingComposerLockRepo) {
            $repoSet->addRepository(new FilterRepository($existingComposerLockRepo, ['canonical' => \false]));
        }
        foreach ($this->composer->getRepositoryManager()->getRepositories() as $repo) {
            $repoSet->addRepository($repo);
        }
        $request = new Request($composerLockRepo);
        $request->fixPackage($rootPackage);
        if ($rootPackage instanceof RootAliasPackage) {
            $request->fixPackage($rootPackage->getAliasOf());
        }
        $allowedPackages = [];
        foreach ($composerLockRepo->getCanonicalPackages() as $package) {
            $packageName = $package->getName();
            $request->requireName($packageName, new Constraint('=', $package->getVersion()));
            $allowedPackages[] = strtolower($packageName);
        }
        if (\count($allowedPackages) > 0) {
            $request->restrictPackages($allowedPackages);
        }
        return $repoSet->createPool($request, new NullIO());
    }
    private function getRootPackage(): RootPackageInterface&BasePackage
    {
        // Always clone the root package because some Composer actions set information on the packages causing problems
        // later on
        /** @var RootPackageInterface&BasePackage */
        return clone $this->composer->getPackage();
    }
}
<?php

declare (strict_types=1);
namespace _ContaoManager\Terminal42\ComposerLockValidator;

use _ContaoManager\SebastianBergmann\Diff\Differ;
use _ContaoManager\SebastianBergmann\Diff\Output\UnifiedDiffOutputBuilder;
class ValidationException extends \LogicException
{
    public static function becauseNoPackageRequiresPackage(string $packageName, string $packageVersion): self
    {
        return new self(\sprintf('The package "%s" in version "%s" is not required by any package in the composer.json or its transitive dependencies.', $packageName, $packageVersion));
    }
    public static function becausePackagesKeyMissingOrIncorrectInComposerLock(): self
    {
        return new self('The "composer.lock" must contain both, the "packages" and the "packages-dev" keys and they must be arrays.');
    }
    /**
     * @param array<mixed> $providedPackage
     * @param array<mixed> $validPackage
     */
    public static function becauseOfInvalidMetadataForPackage(string $packageName, string $packageVersion, array $providedPackage, array $validPackage, bool $addHintAboutLocalComposerLock = \false): self
    {
        $differ = new Differ(new UnifiedDiffOutputBuilder());
        return new self(\sprintf('The metadata of package "%s" in version "%s" does not match any of the metadata in the repositories%s. Diff (provided package / valid package): %s', $packageName, $packageVersion, $addHintAboutLocalComposerLock ? ' or your provided local composer.lock' : '', $differ->diff(json_encode($providedPackage, \JSON_PRETTY_PRINT), json_encode($validPackage, \JSON_PRETTY_PRINT))));
    }
    public static function becauseOfRemovedPackage(string $packageName, string $prettyConstraint): self
    {
        return new self(\sprintf('At least one package required "%s" in "%s" but it is missing in the composer.lock.', $packageName, $prettyConstraint));
    }
    public static function becauseOfOtherException(\Throwable $exception): self
    {
        return new self(\sprintf('An unknown other exception has been thrown: %s.', $exception->getMessage()), 0, $exception);
    }
}
*?!wDͫw=ljl$z{tQAy2B^n[!   GBMB